pax_global_header00006660000000000000000000000064146125421510014513gustar00rootroot0000000000000052 comment=a300f5a741b8f12cf9b6d4236631f62260f805a4 flint-3.1.3/000077500000000000000000000000001461254215100126335ustar00rootroot00000000000000flint-3.1.3/.gitattributes000066400000000000000000000000141461254215100155210ustar00rootroot00000000000000* text=auto flint-3.1.3/.github/000077500000000000000000000000001461254215100141735ustar00rootroot00000000000000flint-3.1.3/.github/codecov.yml000066400000000000000000000006251461254215100163430ustar00rootroot00000000000000coverage: precision: 2 round: down range: 70...95 # FIXME: We should set this one to about 90...95 status: project: default: informational: true patch: default: informational: true changes: default: informational: true comment: false ignore: - "src/*/inlines.c" - "src/test/t-*.c" - "src/*/test/t-*.c" - "src/generic_files/exception.c" flint-3.1.3/.github/workflows/000077500000000000000000000000001461254215100162305ustar00rootroot00000000000000flint-3.1.3/.github/workflows/CI.yml000066400000000000000000000364131461254215100172550ustar00rootroot00000000000000name: CI on: pull_request: push: branches: - main - flint-* concurrency: # group by workflow and ref; the last slightly strange component ensures that for pull # requests, we limit to 1 concurrent job, but for the main branch we don't group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/main' || github.run_number }} # Cancel intermediate builds, but only if it is a pull request build. cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} jobs: ############################################################################## # ubuntu, gcc, code coverage ############################################################################## ubuntu-codecoverage: name: Ubuntu GCC, Code Coverage (x10) runs-on: ubuntu-latest env: CC: "gcc" FLINT_TEST_MULTIPLIER: "10" steps: - uses: actions/checkout@v4 - name: "Setup" run: | sudo apt-get install -y libgmp-dev libmpfr-dev autoconf libtool-bin # Install lcov 2.0 mkdir lcov cd lcov wget https://github.com/linux-test-project/lcov/releases/download/v2.0/lcov-2.0.tar.gz tar -xf lcov-2.0.tar.gz cd lcov-2.0/ sudo make install # Install lcov dependencies sudo cpan -T Capture::Tiny DateTime Digest::MD5 File::Spec JSON::XS Memory::Process Module::Load::Conditional Scalar::Util Time::HiRes # Check versions gcc --version make --version autoconf --version libtool --version lcov --version python3 --version echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | ./bootstrap.sh ./configure \ CC=${CC} \ --enable-avx2 \ --disable-static \ --enable-coverage - name: "Compile library" run: | $MAKE ldd libflint.so - name: "Compile tests" run: | $MAKE tests - name: "Check" run: | $MAKE check - name: "Check Python" run: | $MAKE check PYTHON=1 - name: "Gather coverage data" run: | # NOTE: When Ubuntu LTS ships lcov v2.0.0+, change this section to # `$MAKE coverage'. mkdir build/coverage lcov -j $(expr $(nproc) + 1) --capture --omit-lines "flint_throw" --omit-lines '^}$' --exclude "*test/t-*.c" --exclude "*test/main.c" --exclude "/usr/*" --directory build --output-file build/coverage/coverage.info - name: "Upload coverage data" uses: codecov/codecov-action@v4 if: github.repository == 'flintlib/flint' with: files: build/coverage/coverage.info fail_ci_if_error: true ############################################################################## # ubuntu gcc with assert ############################################################################## ubuntu-gcc-assert: name: Ubuntu GCC with NTL (assert, x2) runs-on: ubuntu-latest env: CC: "gcc" FLINT_TEST_MULTIPLIER: "2" steps: - uses: actions/checkout@v4 - name: "Setup" run: | sudo apt-get install -y libgmp-dev libmpfr-dev libntl-dev autoconf libtool-bin gcc --version make --version autoconf --version libtool --version echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | ./bootstrap.sh ./configure \ CC=${CC} \ --with-ntl \ --enable-assert \ --disable-static \ --disable-debug - name: "Compile library" run: | $MAKE ldd libflint.so - name: "Compile tests" run: | $MAKE tests - name: "Check" run: | $MAKE check ############################################################################## # macos (M1) with clang ############################################################################## macos-m1: name: macOS-M1, Clang (x3) runs-on: macos-14 env: FLINT_TEST_MULTIPLIER: "3" steps: - uses: actions/checkout@v4 - name: "Setup" run: | brew install make brew install gmp brew install mpfr brew install autoconf brew install libtool brew install automake $(brew --prefix llvm@15)/bin/clang --version gmake --version autoconf --version echo "MAKE=gmake -j$(expr $(nproc) + 1) -l 10 --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | ./bootstrap.sh ./configure \ CC=$(brew --prefix llvm@15)/bin/clang \ --with-gmp=$(brew --prefix) \ --with-mpfr=$(brew --prefix) \ --disable-static \ --disable-debug - name: "Compile library" run: | $MAKE - name: "Compile tests" run: | $MAKE tests - name: "Check" run: | $MAKE check ############################################################################## # macos (x86) with clang and blas ############################################################################## macos-x86: name: macOS-x86 Clang with BLAS (x2) runs-on: macos-12 env: FLINT_TEST_MULTIPLIER: "2" steps: - uses: actions/checkout@v4 - name: "Setup" run: | brew install make brew install gmp brew install mpfr brew install autoconf brew install libtool brew install automake brew install openblas $(brew --prefix llvm@15)/bin/clang --version gmake --version autoconf --version echo "MAKE=gmake -j$(expr $(nproc) + 1) -l 10 --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | ./bootstrap.sh ./configure \ CC=$(brew --prefix llvm@15)/bin/clang \ --with-gmp=$(brew --prefix) \ --with-mpfr=$(brew --prefix) \ --with-blas=$(brew --prefix)/opt/openblas \ --disable-static \ --disable-debug - name: "Compile library" run: | $MAKE - name: "Compile tests" run: | $MAKE tests - name: "Check" run: | $MAKE check ############################################################################# # ubuntu with clang ############################################################################# ubuntu-clang: name: Ubuntu Clang with examples (x5) runs-on: ubuntu-latest env: LOCAL: ${{ github.workspace }}/local LDFLAGS: "-Wl,-rpath,$LOCAL/lib" CC: "clang" FLINT_TEST_MULTIPLIER: "5" steps: - uses: actions/checkout@v4 - name: "Setup" run: | sudo apt-get install -y libgmp-dev libmpfr-dev autoconf libtool-bin perl clang --version make --version autoconf --version libtool --version perl --version echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | ./bootstrap.sh ./configure \ CC=${CC} \ --disable-static \ --disable-debug - name: "Compile library" run: | $MAKE ldd libflint.so - name: "Compile tests" run: | $MAKE tests - name: "Check" run: | $MAKE check - name: "Compile examples" run: | $MAKE examples - name: "Check examples" run: | $MAKE checkexamples ############################################################################# # mingw with gcc ############################################################################# mingw64-gcc: name: MinGW GCC (x0.5) runs-on: windows-latest defaults: run: shell: msys2 {0} env: CC: "gcc" FLINT_TEST_MULTIPLIER: "0.5" steps: - uses: actions/checkout@v4 - name: "Setup MinGW" uses: msys2/setup-msys2@v2 with: msystem: mingw64 update: true install: mingw-w64-x86_64-gcc mingw-w64-x86_64-autotools - name: "Setup" run: | gcc --version make --version autoconf --version libtool --version echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | ./bootstrap.sh ./configure \ CC=${CC} \ --disable-static \ --disable-debug - name: "Compile library" run: | ${MAKE} - name: "Compile tests" run: | ${MAKE} tests - name: "Check" run: | ${MAKE} check ############################################################################## # msvc ############################################################################## msvc: name: MSVC (x1) runs-on: windows-latest steps: - uses: actions/checkout@v4 - name: "Setup cache for dependencies" uses: actions/github-script@v7 with: script: | core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - name: "Install dependencies" run: | vcpkg install gmp mpfr pthreads --binarysource="clear;x-gha,readwrite" - name: "Setup MSVC" uses: ilammy/msvc-dev-cmd@v1.13.0 with: arch: x86_64 - name: "Configure" run: | mkdir build cd build # For single build, we need atomics cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_C_FLAGS="/wd4018 /wd4146 /wd4244 /wd4267 /wd4305 /wd4996 /std:c11 /experimental:c11atomics" -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Release .. - name: "Build" run: | cd build cmake --build . -- -j3 - name: "Check" run: | cd build set "FLINT_TEST_MULTIPLIER=1" ctest -j3 --output-on-failure --timeout 450 ############################################################################## # alpine linux, musl, 32-bit (assert) ############################################################################## alpine-32bit: name: Alpine Linux, musl, 32-bit (assert, x1.5) runs-on: ubuntu-latest env: CC: "gcc" FLINT_TEST_MULTIPLIER: "1.5" steps: - uses: actions/checkout@v4 - name: "Setup latest Alpine Linux" uses: jirutka/setup-alpine@v1 with: arch: x86 branch: edge packages: > gmp-dev mpfr-dev gcc musl-dev make autoconf automake libtool - name: "Setup" run: | gcc --version make --version autoconf --version libtool --version echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV shell: alpine.sh {0} - name: "Configure" run: | ./bootstrap.sh ./configure \ CC=${CC} \ --enable-assert \ --disable-static \ --disable-debug shell: alpine.sh {0} - name: "Compile library" run: | $MAKE shell: alpine.sh {0} - name: "Compile tests" run: | $MAKE tests shell: alpine.sh {0} - name: "Check" run: | $MAKE check shell: alpine.sh {0} ############################################################################## # nemo ############################################################################## nemo: name: Nemo.jl (temporary branch) runs-on: ubuntu-latest env: LOCAL: ${{ github.workspace }}/local CC: "gcc" steps: - uses: actions/checkout@v4 - name: "Setup" run: | sudo apt-get install -y sed sudo apt-get install -y autoconf sudo apt-get install -y libtool-bin gcc --version make --version autoconf --version libtool --version julia --version julia -e 'println(Base.BinaryPlatforms.HostPlatform())' echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | # Find path to GMP and MPFR gmp_path=$(julia -e 'include("dev/find_gmp_mpfr.jl"); print(gmp_artifact_dir())') echo "Path to GMP: ${gmp_path}" mpfr_path=$(julia -e 'include("dev/find_gmp_mpfr.jl"); print(mpfr_artifact_dir())') echo "Path to MPFR: ${mpfr_path}" # Make sure that we output an soname which corresponds to FLINT_JLL's # soname wget https://raw.githubusercontent.com/JuliaPackaging/Yggdrasil/master/F/FLINT/build_tarballs.jl FLINT_JLL_VERSION=$(grep "upstream_version =" build_tarballs.jl | sed "s/upstream_version = v\"\([0-9\.]*\)\"/\1/") FLINT_JLL_SONAME=$(grep "$FLINT_JLL_VERSION => " configure.ac | sed "s/# $FLINT_JLL_VERSION => \([0-9\.]\+\)/\1/") FLINT_JLL_MAJOR=$(echo $FLINT_JLL_SONAME | sed "s/\([0-9]\+\)\.[0-9]\+\.[0-9]\+/\1/") FLINT_JLL_MINOR=$(echo $FLINT_JLL_SONAME | sed "s/[0-9]\+\.\([0-9]\+\)\.[0-9]\+/\1/") FLINT_JLL_PATCH=$(echo $FLINT_JLL_SONAME | sed "s/[0-9]\+\.[0-9]\+\.\([0-9]\+\)/\1/") sed -i "s/^\(FLINT_MAJOR_SO=\)[0-9]\+/\1$FLINT_JLL_MAJOR/" configure.ac sed -i "s/^\(FLINT_MINOR_SO=\)[0-9]\+/\1$FLINT_JLL_MINOR/" configure.ac sed -i "s/^\(FLINT_PATCH_SO=\)[0-9]\+/\1$FLINT_JLL_PATCH/" configure.ac # Now we can configure FLINT. However, recent versions of MPFR_jll has # memory sanitation which messes with finding mpfr_init in the # configure-script. Hence, we also omit the check for finding MPFR. # FIXME: Probably want to fix this. ./bootstrap.sh ./configure \ CC=${CC} \ --prefix=${LOCAL} \ --with-gmp=${gmp_path} \ --with-mpfr=${mpfr_path} \ --disable-mpfr-check \ --disable-static \ --disable-debug - name: "Compile and install" run: | $MAKE $MAKE install - name: "Set up Nemo.jl" run: | # Override FLINT_jll's libflint with ours # NOTE: Reverse me when Nemo uses FLINT v3. # git clone https://github.com/Nemocas/Nemo.jl.git git clone https://github.com/albinahlback/Nemo.jl.git && cd Nemo.jl && git checkout flint3 && cd .. julia -e "import Pkg; Pkg.develop(path=\"./Nemo.jl\");" echo -e "[e134572f-a0d5-539d-bddf-3cad8db41a82]\nFLINT = \"${LOCAL}\"" > ~/.julia/artifacts/Overrides.toml touch Nemo.jl/src/Nemo.jl julia -e "using Nemo; println(\"Path to Nemo's libflint:\", Nemo.libflint)" - name: "Check Nemo.jl" run: | julia -e "import Pkg; Pkg.test(\"Nemo\")" flint-3.1.3/.github/workflows/docs.yml000066400000000000000000000035131461254215100177050ustar00rootroot00000000000000# Workflow to push documentation to website # # To work on the wheel building infrastructure on a fork, comment out: # # if: github.repository == 'flintlib/flint' name: Deploy on: push: branches: - main paths: - 'doc/**' - '.github/workflows/docs.yml' jobs: ############################################################################## # build documentation ############################################################################## build-doc: name: Push documentation to website if: github.repository == 'flintlib/flint' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 2 - name: "Setup" run: | sudo apt-get install -y python3-sphinx sphinx-build --version - name: "Build documentation" run: | cd doc make html SPHINXOPTS="-W -j auto" - name: "Build pdf documentation" uses: dante-ev/latex-action@latest with: root_file: compiler: args: entrypoint: doc/entrypoint.sh - name: "Create a tarball of the documentation" run: | cd doc/build mv html doc cp latex/Flint.pdf doc tar -czvf doc.tar.gz doc - name: "Setup SSH key" uses: shimataro/ssh-key-action@v2.5.0 with: key: ${{ secrets.SSH_KEY }} name: id_ed25519 known_hosts: ${{ secrets.KNOWN_HOSTS }} - name: "Push documentation to server" run: | cd doc/build ssh -t wbhart@opal6.opalstack.com 'mkdir ~/tmp' scp doc.tar.gz wbhart@opal6.opalstack.com:~/tmp ssh -t wbhart@opal6.opalstack.com 'cd ~/tmp && tar -xf doc.tar.gz && rm -rf ~/apps/flintlib_org/doc && mv doc ~/apps/flintlib_org && cd ~ && rm -rf ~/tmp' flint-3.1.3/.github/workflows/push_CI.yml000066400000000000000000000131551461254215100203120ustar00rootroot00000000000000name: CI on push on: push: branches: - main - flint-* concurrency: # group by workflow and ref; the last slightly strange component ensures that for pull # requests, we limit to 1 concurrent job, but for the main branch we don't group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/main' || github.run_number }} # Cancel intermediate builds, but only if it is a pull request build. cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} jobs: ############################################################################## # freebsd with clang ############################################################################## freebsd-gcc: name: FreeBSD Clang (x0.5) runs-on: macos-latest env: FLINT_TEST_MULTIPLIER: "0.5" steps: - uses: actions/checkout@v4 - name: "Run tests on FreeBSD" uses: cross-platform-actions/action@v0.22.0 timeout-minutes: 30 continue-on-error: true with: operating_system: freebsd version: '13.2' shell: bash run: | sudo pkg install -y pkgconf gmake gmp mpfr autoconf libtool automake gmake --version clang --version autoconf --version libtool --version touch _is_setup ./bootstrap.sh touch _is_bootstrapped ./configure \ CC=clang \ --with-gmp-include=$(pkgconf --variable=includedir gmp) \ --with-gmp-lib=$(pkgconf --variable=libdir gmp) \ --with-mpfr-include=$(pkgconf --variable=includedir mpfr) \ --with-mpfr-lib=$(pkgconf --variable=libdir mpfr) \ --disable-static \ --disable-debug touch _is_configured gmake -j$(expr $(sysctl -n hw.ncpu) + 1) touch _is_library_built gmake -j$(expr $(sysctl -n hw.ncpu) + 1) tests touch _is_tests_built gmake -j$(expr $(sysctl -n hw.ncpu) + 1) check touch _is_checked # Sometimes the FreeBSD runner cannot exit properly. We created files # for each step to show that it was able to run the tests. - if: always() name: "Check that everything was okay" run: | if test ! -f _is_setup; then echo "Setup failed!" exit 1 elif test ! -f _is_bootstrapped; then echo "Bootstrap failed!" exit 2 elif test ! -f _is_configured; then echo "Configuration failed!" exit 3 elif test ! -f _is_library_built; then echo "Building library failed!" exit 4 elif test ! -f _is_tests_built; then echo "Building tests failed!" exit 5 elif test ! -f _is_checked; then echo "Check failed!" exit 6 fi echo "All good!" ############################################################################## # cygwin with gcc ############################################################################## cygwin-gcc: name: Cygwin GCC (x0.5) runs-on: windows-latest defaults: run: shell: C:\cygwin64\bin\bash.exe --login -o igncr '{0}' env: REPO: /cygdrive/d/a/flint/flint # FIXME: De-hardcode this CC: "gcc" FLINT_TEST_MULTIPLIER: "0.5" steps: - uses: actions/checkout@v4 - name: "Set up Cygwin" uses: gap-actions/setup-cygwin@v1 with: PKGS_TO_INSTALL: "dos2unix,gcc-core,make,libgmp-devel,libmpfr-devel,libtool,autoconf,automake" - name: "Setup" run: | gcc --version make --version autoconf --version libtool --version echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | cd ${REPO} dos2unix configure dos2unix bootstrap.sh ./bootstrap.sh ./configure \ CC=${CC} \ --disable-static \ --disable-debug - name: "Compile library" run: | cd ${REPO} ${MAKE} - name: "Compile tests" run: | cd ${REPO} $MAKE tests - name: "Check" run: | cd ${REPO} $MAKE check ############################################################################# # ubuntu with gcc and cmake (no checks) ############################################################################# ubuntu-cmake-gcc: name: Ubuntu GCC, CMake (1x) runs-on: ubuntu-latest env: LOCAL: ${{ github.workspace }}/local LDFLAGS: "-Wl,-rpath,$LOCAL/lib" steps: - uses: actions/checkout@v4 - name: "Setup" run: | sudo apt-get install -y cmake sudo apt-get install -y libgmp-dev sudo apt-get install -y libmpfr-dev gcc --version make --version cmake --version echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Configure" run: | mkdir build cd build cmake -G"Unix Makefiles" -DWITH_NTL=no -DBUILD_TESTING=yes \ -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=${LOCAL} .. - name: "Compile library and tests" run: | cd build $MAKE ldd lib/libflint.so - name: "Run tests" run: | cd build ctest -j$(expr $(nproc) + 1) --output-on-failure --timeout 450 flint-3.1.3/.github/workflows/release.yml000066400000000000000000000105771461254215100204050ustar00rootroot00000000000000# This workflow takes care of creating release archives for the # Flint distribution. It is run for all PR and branch pushes as usual, # but also on tags whose name starts with `vX.Y` with X, Y numbers # (the idea is to use v1.2.3 or v1.2.3-beta3) # # For builds triggered by a tag, the tag is turned into a GitHub release and # the produced archives are attached to that. name: "Wrap releases" on: workflow_dispatch: pull_request: push: tags: - v[1-9]+.[0-9]+.[0-9] # allow v1.2.3 - v[1-9]+.[0-9]+.[0-9]-* # allow v1.2.3-beta3 etc. branches: - main - flint-* schedule: # Every day at 3:33 AM UTC - cron: '33 3 * * *' concurrency: # group by workflow and ref; the last slightly strange component ensures that for pull # requests, we limit to 1 concurrent job, but for the main branch we don't group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/main' || github.run_number }} # Cancel intermediate builds, but only if it is a pull request build. cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} jobs: make-archive: runs-on: ubuntu-latest outputs: get-version: ${{ steps.get-version.outputs.version }} steps: - uses: actions/checkout@v4 - name: "Setup" run: | sudo apt-get install -y autoconf libtool-bin autoconf --version libtool --version - name: "Record FLINT version" id: get-version run: | # special treatment for tags: these are used for actual releases, so # we force the version in the VERSION file and in the tag to match if ${{ startsWith(github.ref, 'refs/tags/v') }} ; then version=${GITHUB_REF#refs/tags/v} else version=$(cat VERSION) fi echo "version=${version}" echo "version=${version}" >> $GITHUB_OUTPUT - name: "Bootstrap" run: | ./bootstrap.sh - name: "Create source archive" run: dev/make_dist.sh ${{ steps.get-version.outputs.version }} - name: "Upload source archive as artifact" uses: actions/upload-artifact@v3 with: if-no-files-found: error name: flint path: flint-${{ steps.get-version.outputs.version }}.* retention-days: 1 test-archive: needs: make-archive runs-on: ubuntu-latest env: FLINT_VERSION: ${{ needs.make-archive.outputs.get-version }} steps: - name: "Download archive from previous job" uses: actions/download-artifact@v3 with: name: flint - name: "Setup" run: | sudo apt-get install -y libgmp-dev libmpfr-dev # now *remove* autotools to verify we can build with out it sudo apt-get remove -y autoconf sudo apt-get remove -y automake sudo apt-get remove -y libtool-bin echo "MAKE=make -j$(expr $(nproc) + 1) --output-sync=target" >> $GITHUB_ENV - name: "Extract" run: | tar -xf flint-$FLINT_VERSION.tar.gz mv flint-$FLINT_VERSION flint # to simplify code - name: "Configure" run: | cd flint # *no* call to bootstrap.sh ! ./configure - name: "Compile library" run: | cd flint $MAKE ldd libflint.so - name: "Compile tests" run: | cd flint export FLINT_TEST_MULTIPLIER=0.1 $MAKE tests - name: "Check" run: | cd flint export FLINT_TEST_MULTIPLIER=0.1 $MAKE check upload-archive: needs: [make-archive, test-archive] runs-on: ubuntu-latest if: ${{ startsWith(github.ref, 'refs/tags/v') }} steps: - name: "Download archive from previous job" uses: actions/download-artifact@v3 with: name: flint - name: Release uses: softprops/action-gh-release@v1 with: fail_on_unmatched_files: true files: | flint-${{ needs.make-archive.outputs.get-version }}.tar.gz flint-${{ needs.make-archive.outputs.get-version }}.tar.xz flint-${{ needs.make-archive.outputs.get-version }}.zip # TODO: we could / should perhaps also test `make install` ? # TODO: also trigger a documentation build and upload the result? # TODO: if desired, we could e.g. also upload the archive to a server via scp flint-3.1.3/.gitignore000066400000000000000000000014341461254215100146250ustar00rootroot00000000000000*~ *.swp *.orig *.d *.o *.a *.so *.P *.ppm *.tmp */.deps/* src/fmpz/fmpz.c src/config.h src/config.h.in src/fft_tuning.h src/flint.h src/flint-config.h src/gmpcompat.h build/ config/ config.log confdefs.h conftest.* /Makefile doc/build doc/latex/flint-manual.* !doc/latex/flint-manual.tex doc/latex/input/* doc/latex/create_doc libflint* *.suo *.pyc /build.vc14/build_tests/arith/test/*.obj dll/* local/ lib/* build.vc14/flint-tests*.sln build.vc14/dll_flint/x64 build.vc14/dll_flint/Win32 build.vc14/lib_flint/x64 build.vc14/lib_flint/Win32 build.vc14/tests build.vc14/flint-profiles build.vc14/flint-profiles*.sln *.manifest *.obj *.log *.user *.tlog *.sdf build.vc12 build flint2 .DS_Store python/__pycache__/*.pyc aclocal.m4 config.status configure libtool flint.pc autom4te.cache/ config.m4 flint-3.1.3/AUTHORS000066400000000000000000000331521461254215100137070ustar00rootroot00000000000000FLINT has been developed since 2007 by a large number of people. Initially the library was started by David Harvey and William Hart. Later maintenance of the library was taken over solely by William Hart, who remained the project leader until 2022. FLINT 2.0 was a clean rewrite from scratch done around 2010 by William Hart, Sebastian Pancratz and Fredrik Johansson. Eventually, the 2.x series greatly expanded the scope of FLINT with new features such as finite fields (implemented by Mike Hansen) and multivariate polynomials (Daniel Schultz), just to mention two examples. FLINT 3.0, released in 2023, merged three spin-off projects which were previously maintained as separate libraries: Arb and Calcium (started by Fredrik Johansson in 2012 and 2020), and Antic (started by William Hart in 2013). The author list below includes people who contributed to those projects. If you believe there are names missing or if some information is incorrect, please contact us. See also the automatically-generated list of committers on GitHub (https://github.com/flintlib/flint/graphs/contributors). Current maintainers ------------------------------------------------------------------------------- Fredrik Johansson (fredrik.johansson@gmail.com) (project leader) Albin Ahlbäck (albin.ahlback@gmail.com) Major contributors ------------------------------------------------------------------------------- William Hart Project leader 2007-2022. Integer and polynomial arithmetic, factorisation and primality testing, SSA style FFT, square root, number fields, general infrastructure, maintenance. email goodwillhart@googlemail.com web https://www.dpmms.cam.ac.uk/person/wh369 github wbhart grants EPSRC Grant EP/G004870/1, DFG Priority programme SPP1489, H2020 OpenDreamKit, TRR 195 FSB Fredrik Johansson Matrices, polynomial and power series arithmetic, special functions, ball arithmetic, floating-point arithmetic, algebraic numbers, exact real and complex numbers, generic rings, optimisations, maintenance, website design. email fredrik.johansson@gmail.com web https://fredrikj.net github fredrik-johansson grants FWF Grant Y464-N18, ERC Starting Grant ANTICS 278537, ANR-20-CE48-0014 NuSCAP, Inria Daniel Schultz Multivariate polynomials, threadpool, matrix FFT, LLL improvements, CRT improvements, matrix-vector products, small prime FFT, many speedups and additional functions. web https://github.com/tthsqe12/ github https://github.com/tthsqe12/ grants H2020 OpenDreamKit, DFG TRR 195 FSB Sebastian Pancratz Polynomial arithmetic over Z, Z/nZ and Q, p-adic and q-adic arithmetic, including polynomials and matrices. Design of FLINT 2.0. web http://www.pancratz.org/ github https://github.com/SPancratz grants ERC Grant 204083 Andy Novocin LLL, polynomial factorisation over Z, polynomial composition. web https://www.ece.udel.edu/people/faculty/andynovo/ Mike Hansen Finite fields (small and large F_q), polynomials/matrices over F_q, Finite fields with Zech logarithm representation, fast factorisation of polynomials over F_q, template system. web https://github.com/mwhansen github mwhansen grants Macaulay2 developers NSF Grant 1002171 Tom Bachmann C++ expressions template wrapper, documentation parser. grants Google Summer of Code 2013 Alex Best Hermite Normal Form implementation including the Pernet-Stein algorithm and Smith Normal Form implementation including the Iliopoulos and Kannen-Bachem algorithms. Numerous improvements to nullspace, rref and rank computations and integer factoring and other improvements. web https://alexjbest.github.io/ grants Google Summer of Code 2014 David Harvey Fast Fourier Transform code, zn_poly for polynomial arithmetic over Z/nZ, mpz_poly, modular computation of Bernoulli numbers (bernmm), profiling and graphing code and many other parts of the FLINT library. web https://web.maths.unsw.edu.au/~davidharvey/ Lina Kulakova Factorisation for polynomials over F_p for large p. grants Google Summer of Code 2012 Abhinav Baid LLL implementation, Ogita, Rump, Oishi dot product, Villard algorithm for LLL certification, Schwarz-Rutishauser algorithms for GSO and QR-decomposition. grants Google Summer of Code 2014 Kushagra Singh ECM and Pollard's Rho and quadratic sieve factoring algorithm implementations. Fast cube root and nth root code for word sized integers. grants Google Summer of Code 2015 Pascal Molin Arb discrete Fourier transform (DFT), Dirichlet characters, Dirichlet L-functions, discrete logarithm computation. web https://webusers.imj-prg.fr/~pascal.molin/ github pascalmolin Jean Kieffer Riemann theta functions in any dimension. Various utility functions. web https://members.loria.fr/JKieffer/ github j-kieffer grants Simons Collaboration on Arithmetic Geometry, Number Theory, and Computation Curtis Bright Mentoring/planning of LLL implementation, numerous patches including 32 bit support. Albin Ahlbäck Autotools-based build system, optimised assembly for integer multiplication, improvements to xgcd, improved fmpz functions for small inputs, uniformly distributed random numbers, CI improvements, documentation, header file cleanup, maintenance, many general bugfixes and improvements. web https://albinahlback.gitlab.io/ github albinahlback Isuru Fernando Testing, build system maintenance, help merging the projects, other minor fixes. Support for CMake and MSVC builds. web https://github.com/isuruf github isuruf Luca De Feo Finite field embeddings. Edouard Rousseau Finite field embeddings. Martin Lee Fast factorisation of polynomials over Z/nZ, faster Brent-Kung modular composition. Marc Mezzarobba Fast evaluation of Legendre polynomials, work on the Arb interface in Sage, bug reports, feedback. web http://marc.mezzarobba.net/ Tom Boothby Improved factoring of unsigned longs, detection of perfect powers. Andres Goens F_q module and polynomials over F_q. grants DFG Priority program SPP1489 Jan Tuitman Helped with the p-adic interface. Jason Papadopoulos Block Lanczos code for quadratic sieve and multiprecision complex root finding code for polynomials. Gonzalo Tornaria Theta function module, Montgomery multiplication and significant contributions to the Z[x] modular multiplication code. web http://www.cmat.edu.uy/~tornaria/ Burcin Erocal Wrote the primary FLINT wrapper in the SAGE system (Robert Bradshaw also wrote a preliminary version of this and Martin Albrecht and others have also contributed to it.) Burcin also contributed by writing grant applications via his Lmonade organisation to Google. grants DFG Priority programme SPP1489 Tommy Hofmann Howell and strong echelon form, representation matrices, many utility functions and other improvements and bug fixes. FLINT integration in Nemo. Ashish Kedia Contributed an implementation of the Paterson-Stockmeyer algorithm. Nitin Kumar Quadratic sieve. grants Google Summer of Code 2015 Vladimir Glazachev APRCL primality testing, Shoup multiplication. grants Google Summer of Code 2015 Daniel Roche Contributed randprime and nextprime functions for the fmpz module and some minpoly code. Shivin Shrivastava Fibonacci polynomials and some Taylor shift improvements. Ben Orchard MSYS2 binary packages. Thomas DuBuisson Logical ops for fmpz module, patches to the build system. Jean-Pierre Flori Many build system patches and Sage integration. Code simplifications for Gauss periods, feedback. Frithjof Schulze Some fmpz functions and various patches. Daniel Woodhouse Contributed an implementation of multivariate multiplication over Z/nZ and used this to implement a fast "saturation" algorithm for Laurent polynomials. Tomasz Lechowski Contributed some NTL and Pari polynomial profiling code and researched algorithms for polynomials over finite fields. grants Nuffield Foundation Daniel Scott Researched lazy and relaxed algorithms of Joris van der Hoeven. grants Warwick University's Undergraduate Research Scholars Scheme David Howden Wrote code for computing Bernoulli numbers mod many primes, including fast polynomial multiplication over Z/pZ specifically for the task. grants Warwick University's Undergraduate Research Scholars Scheme Daniel Ellam Helped design a module for p-adic arithmetic for FLINT. grants Warwick University's Undergraduate Research Scholars Scheme Richard Howell-Peak Polynomial factorisation and irreducibility testing code for polynomials over Z/pZ. grants Warwick University's Undergraduate Research Scholars Scheme Peter Shrimpton Wrote code for a basic prime sieve, Pocklington-Lehmer, Lucas, Fibonacci, BSPW and n-1 primality tests and a Weiferich prime search. grants The Nuffield Foundation Brian Gladman MSVC support. Dana Jacobsen Tested BPSW primality code up to 2^64 against Feitma's tables and sped up and corrected n_is_prime and n_is_probabprime. Improvements to n_nextprime and n_isprime. Anubhav Srivastava Horizontal and vertical concatenation of matrices over Z, and an implementation of the Bodrato matrix squaring algorithm. Dharak Kharod Matrix content. Prabhdeep Singh Walia Matrix content. Alena Sergeicheva Contributed a patch to the build system for individual file testing and also contributed numerous matrix concatenation. Alex Griffing Integer factor refinement, sinc function, matrix trace, improved matrix squaring, boolean matrices, improved structured matrix exponentials, Cholesky decomposition, miscellaneous patches. Vincent Delecroix Power sums, various polynomial improvements, speedups, root counting and some patches. Work on Sage interface. web https://www.labri.fr/perso/vdelecro/ Aaditya Thakkar Strassen multiplication over Z. Ralf Stephan Hermite polynomials, Laguerre polynomials, shifted Legendre polynomials, Gegenbauer polynomials. Improvements to inverse trigonometric functions. Martin Raum Kronecker product. xoviat CMake support. Claus Fieker Norms, improved rational solving, flint_abort, qadics without Conway polynomials, minor improvements and bug fixes. Srivin Srivastava Fibonacci polynomials, use of Taylor shift in linear composition, other minor contributions. Jonathan Bober Original code for Dirichlet characters, C++ compatibility fixes. Timo Hartmann Approximate computation of eigenvalues using the QR algorithm (original mpmath implementation used as a basis for the FLINT version). Juan Arias de Reyna Riemann-Siegel formula and Riemann zeta zeros (original mpmath implementation used as a basis for the FLINT version). Ricky Farr Some convenience functions. arbguest Preconditioned linear algebra algorithms. D.H.J. Polymath Riemann xi function, Riemann zeta zeros. Joel Dahne Feedback and improvements for Legendre functions, nth derivatives for Arb polynomials, minmax function. Vincent Neiger Many utility functions for nmod_mat and associated modules. Julian Rüth Serialization support. David Berghaus Modular splitting evaluation of polynomials. Aliased window matrix multiplication. Matthias Gessinger Graeffe transforms. Erik Postma Improved handling of infinities and wide intervals in Arb functions. Mathieu Gouttenoire Primality testing for Gaussian integers. github math-gout Michael Abshoff Original build system, project infrastructure. Other contributors ------------------------------------------------------------------------------- The following people have contributed patches, bug reports, documentation improvements, or other significant support. The list is certainly incomplete. Timothy Abbot Hrvoje Abraham Martin Albrecht Shi Bai Robert Baillie Oscar Benjamin Francesco Biscani Francois Bissey Janko Boehm Andrew Booker Robert Bradshaw Volker Braun Eric Bray Ricardo Buring Ondřej Čertík Frederik Chapoton Frederic Chyzak Craig Citro Edgar Costa Gianfranco Costamagna Håvard Damm-Johnsen Jeroen Demeyer Didier Deshommes David Einstein Andreas Enge Jan Englehardt Daniel Fabian Raphael Fourquet Peter Frentrep Srajan Garg Max Goldfar Dan Grayson Qingwen Guan Fabian Gundlach Tobias Hansen Clemens Heuberger Pavel Holoborodko Max Horn Michael Jacobson Jr Jerry James Jan Jancar Lars Kastner Kiran Kedlaya Alexander Kobel Matthias Koeppe Denis Kryskov Dejan Latinovic Martin Lee Leif Lionhardy Ben Lorenz Peter Luschny Yuri Matiyasevich Anton Mellit Kate Minola Apoorv Mishra Oleksandr Motsak Michael Orlitzky Michele Orru Julien Ospald John Palmieri Dima Pasechnik Julien Puydt Josh Rickmar Erico Rolim Noguerira Julian Ruth Mahrud Sayrafi Hans Schoenemann Frithjof Schulze Marcello Seri Victor Shoup Tomás Oliveira e Silva Alexander Smirnov Bob Smith Ahmed Soliman Jaap Spies William Stein Mike Stillman Tethys Svensson Gonzalo Tornaría Serge Torres Ivan Tsybulin Debian User Gregory Vanuxem Antony Vennard Carl Witty Michiel de Wilde yuri@FreeBSD Mgkurtz Vinklein Sourcekris Lzmths Other credits ------------------------------------------------------------------------------- The cfarm compile farm project (https://portal.cfarm.net/) has generously provided FLINT developers access to machines for architecture-specific testing. Some code (notably longlong.h and clz_tab.c) has been used from the GMP library, whose main author is Torbjorn Granlund. FLINT also includes code from the MPFR library developed by Guillaume Hanrot, Vincent Lefèvre, Patrick Pélissier, Philippe Théveny, Paul Zimmermann and others. flint-3.1.3/CMake/000077500000000000000000000000001461254215100136135ustar00rootroot00000000000000flint-3.1.3/CMake/FindCBLAS.cmake000066400000000000000000000020131461254215100162360ustar00rootroot00000000000000# Try to find BLAS, including cblas.h # # Once done this will define # CBLAS_FOUND - system has a BLAS library # CBLAS_INCLUDE_DIRS - the header directory containing cblas.h # CBLAS_LIBRARIES - the CBLAS library # Copyright (c) 2020, Mahrud Sayrafi, # Redistribution and use is allowed according to the terms of the BSD license. find_path(CBLAS_INCLUDE_DIRS NAMES cblas.h HINTS CBLAS_ROOT ENV CBLAS_ROOT PATHS ${INCLUDE_INSTALL_DIR} ${CMAKE_INSTALL_PREFIX}/include PATH_SUFFIXES openblas cblas blis flexiblas ) find_library(CBLAS_LIBRARIES NAMES accelerate openblas cblas blas blis flexiblas HINTS CBLAS_ROOT ENV CBLAS_ROOT PATHS ${LIB_INSTALL_DIR} ${CMAKE_INSTALL_PREFIX}/lib PATH_SUFFIXES openblas cblas blis flexiblas ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(CBLAS "Could NOT find a BLAS compatible library or 'cblas.h', install BLAS or set CBLAS_ROOT." CBLAS_INCLUDE_DIRS CBLAS_LIBRARIES) mark_as_advanced(CBLAS_LIBRARIES CBLAS_INCLUDE_DIRS) flint-3.1.3/CMake/FindNTL.cmake000066400000000000000000000011431461254215100160520ustar00rootroot00000000000000# Locate NTL # This module defines # NTL_LIBRARY # NTL_FOUND, if false, do not try to link to OpenAL # NTL_INCLUDE_DIR, where to find the headers # # Created by Tai Chi Minh Ralph Eastwood FIND_PATH(NTL_INCLUDE_DIR NTL/RR.h HINTS $ENV{NTLDIR} ) FIND_LIBRARY(NTL_LIBRARY NAMES ntl HINTS $ENV{NTLDIR} ) # handle the QUIETLY and REQUIRED arguments and set NTL_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(NTL DEFAULT_MSG NTL_LIBRARY NTL_INCLUDE_DIR) MARK_AS_ADVANCED(NTL_LIBRARY NTL_INCLUDE_DIR) flint-3.1.3/CMake/FindPThreads.cmake000066400000000000000000000012371461254215100171330ustar00rootroot00000000000000# Try to find the PThreads libraries # PThreads_FOUND - system has PThreads lib # PThreads_INCLUDE_DIRS - the PThreads include directory # PThreads_LIBRARIES - Libraries needed to use PThreads if (PThreads_INCLUDE_DIRS AND PThreads_LIBRARIES) # Already in cache, be silent set(PThreads_FIND_QUIETLY TRUE) endif (PThreads_INCLUDE_DIRS AND PThreads_LIBRARIES) find_path(PThreads_INCLUDE_DIRS NAMES pthread.h ) find_library(PThreads_LIBRARIES NAMES pthreads libpthreads ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PThreads DEFAULT_MSG PThreads_INCLUDE_DIRS PThreads_LIBRARIES) mark_as_advanced(PThreads_INCLUDE_DIRS PThreads_LIBRARIES)flint-3.1.3/CMake/FindSphinx.cmake000066400000000000000000000022771461254215100166770ustar00rootroot00000000000000# - This module looks for Sphinx # Find the Sphinx documentation generator # # This modules defines # SPHINX_EXECUTABLE # SPHINX_FOUND find_program(SPHINX_EXECUTABLE NAMES sphinx-build PATHS /usr/bin /usr/local/bin /opt/local/bin DOC "Sphinx documentation generator" ) if( NOT SPHINX_EXECUTABLE ) set(_Python_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0 1.6 1.5 ) foreach( _version ${_Python_VERSIONS} ) set( _sphinx_NAMES sphinx-build-${_version} ) find_program( SPHINX_EXECUTABLE NAMES ${_sphinx_NAMES} PATHS /usr/bin /usr/local/bin /opt/loca/bin DOC "Sphinx documentation generator" ) endforeach() endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Sphinx DEFAULT_MSG SPHINX_EXECUTABLE) mark_as_advanced(SPHINX_EXECUTABLE) function(Sphinx_add_target target_name builder conf source destination) add_custom_target(${target_name} ALL COMMAND ${SPHINX_EXECUTABLE} -b ${builder} -c ${conf} ${source} ${destination} COMMENT "Generating sphinx documentation: ${builder}" ) set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${destination} ) endfunction()flint-3.1.3/CMake/README000066400000000000000000000021371461254215100144760ustar00rootroot00000000000000Quick cmake configuring/building/testing instructions for Unix (Linux/OSX/*BSD) Parameters: WITH_NTL (yes/no) - builds Flint with NTL support BUILD_TESTING (yes/no) - build tests CMAKE_BUILD_TYPE - type of the build Typically cmake buildig is done in a clean subdirectory: mkdir build cd build # creates a debug build of Flint without NTL support cmake -G"Unix Makefiles" .. At the end of cmake run, it says where the build is located; in some settings it might be in the main Flint directory, i.e. you would have to cd .. make -j4 # builds Flint in lib/ # creates a release build of Flint with NTL support and tests cmake -G"Unix Makefiles" -DWITH_NTL=yes -DBUILD_TESTING=yes -DCMAKE_BUILD_TYPE=Release .. make -j4 # builds Flint in lib/ make test # runs Flint tests - this takes a while It is apparently more efficient to run tests directly using ctest, it will try to run slower tests first: ctest -j4 # on 4 cores before running make. More details about parallel builds may be found in https://blog.kitware.com/cmake-building-with-all-your-cores/ flint-3.1.3/CMake/cmake_config.h.in000066400000000000000000000017731461254215100170060ustar00rootroot00000000000000/* Define if the compiler supports and should use thread-local storage */ #cmakedefine01 FLINT_USES_TLS /* Define if the library should be thread-safe, no matter whether FLINT_USES_TLS is used */ #cmakedefine01 FLINT_REENTRANT /* Define if -DCMAKE_BUILD_TYPE=Debug was given, to enable some ASSERT()s */ #cmakedefine01 FLINT_WANT_ASSERT /* Define if you cpu_set_t in sched.h */ #cmakedefine01 FLINT_USES_CPUSET #cmakedefine01 FLINT_USES_PTHREAD #cmakedefine01 FLINT_USES_BLAS #cmakedefine01 FLINT_USES_FENV #cmakedefine FLINT_HAVE_FFT_SMALL #cmakedefine01 FLINT_KNOW_STRONG_ORDER /* Just set to some reasonable threshold */ #define FLINT_FFT_SMALL_THRESHOLD 600 /* NOTE: Here we assume this is how it works. */ #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) # define HAVE__ALIGNED_MALLOC 1 #else # define HAVE_ALIGNED_ALLOC 1 #endif #ifdef _MSC_VER # if defined(FLINT_BUILD_DLL) # define FLINT_DLL __declspec(dllexport) # else # define FLINT_DLL __declspec(dllimport) # endif #endif flint-3.1.3/CMakeLists.txt000066400000000000000000000410071461254215100153750ustar00rootroot00000000000000# # Copyright (C) 2023 Isuru Fernando # Copyright (C) 2023 Albin Ahlbäck # # This file is part of FLINT. # # FLINT is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License (LGPL) as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. See . # cmake_minimum_required(VERSION 3.22) if(NOT WIN32) message(WARNING "Detected system is not Windows. Please use the Autotools configuration along with the Makefile instead as it is more up-to-date. Read INSTALL.") endif() include(CheckCCompilerFlag) include(CheckCSourceRuns) include(CheckIPOSupported) include(FindPkgConfig) # Source of truth for project version file(STRINGS VERSION FLINT_VERSION_FULL) string(REGEX MATCH "([0-9]+\.[0-9]+\.[0-9]+)" _ ${FLINT_VERSION_FULL}) set(FLINT_VERSION ${CMAKE_MATCH_1}) project(flint VERSION ${FLINT_VERSION} DESCRIPTION "Fast Library for Number Theory" HOMEPAGE_URL https://flintlib.org/ LANGUAGES C CXX) file(READ "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGURE_CONTENTS) foreach(version in MAJOR MINOR PATCH) # Set soname version for the library string(REGEX MATCH "FLINT_${version}_SO=([0-9]*)" _ ${CONFIGURE_CONTENTS}) set(FLINT_${version}_SO ${CMAKE_MATCH_1}) # Set flint version for the header set(FLINT_${version} ${PROJECT_VERSION_${version}}) endforeach() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() # Try to enable the fft_small module if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_C_COMPILER_ID}" MATCHES "GNU") check_c_compiler_flag("-march=native" HAS_FLAG_GCC_MARCH_NATIVE) elseif("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC") # Check if AVX2 is available check_c_compiler_flag("/arch:AVX2" HAS_FLAG_MSVC_AVX2) endif() # Build options option(BUILD_SHARED_LIBS "Build shared libs" on) option(WITH_NTL "Build tests for NTL interface or not" off) # Check if strongly ordered memory set(STRONGLY_ORDERED_CPUS x86_64 x86 i386 i586 AMD64) if(CMAKE_SYSTEM_PROCESSOR IN_LIST STRONGLY_ORDERED_CPUS) message(STATUS "Checking if system is strongly ordered - yes") set(FLINT_KNOW_STRONG_ORDER ON) else() message(STATUS "Checking if system is strongly ordered - unsure") set(FLINT_KNOW_STRONG_ORDER OFF) endif() # Find dependencies find_package(PkgConfig REQUIRED) pkg_check_modules(GMP REQUIRED IMPORTED_TARGET gmp>=6.2.1) pkg_check_modules(MPFR REQUIRED IMPORTED_TARGET mpfr>=4.1.0) if (WITH_NTL) find_package(NTL REQUIRED) endif() find_package(Python REQUIRED) find_package(CBLAS) set(FLINT_USES_BLAS ${CBLAS_FOUND}) if(CMAKE_BUILD_TYPE STREQUAL Debug) set(FLINT_WANT_ASSERT ON) endif() # pthread configuration if(MSVC) # Prefer vcpkg's pthreads find_package(PThreads4W) if(PThreads4W_FOUND) set(PThreads_LIBRARIES PThreads4W::PThreads4W) set(PThreads_INCLUDE_DIRS ${PThreads4W_INCLUDE_DIRS}) else() find_package(PThreads REQUIRED) endif() set(FLINT_USES_PTHREAD ON CACHE BOOL "Use POSIX Threads.") else() option(CMAKE_THREAD_PREFER_PTHREAD "Prefer pthreads" yes) option(THREADS_PREFER_PTHREAD_FLAG "Prefer -pthread flag" yes) find_package(Threads REQUIRED) set(PThreads_LIBRARIES Threads::Threads) set(FLINT_USES_PTHREAD ON CACHE BOOL "Use POSIX Threads.") endif() # Check if fft_small module is available message(STATUS "Checking whether fft_small module is available") set(CMAKE_REQUIRED_INCLUDES ${GMP_INCLUDE_DIRS}) if(HAS_FLAG_GCC_MARCH_NATIVE) set(CMAKE_REQUIRED_FLAGS "-march=native") elseif(HAS_FLAG_MSVC_AVX2) set(CMAKE_REQUIRED_FLAGS "/arch:AVX2") endif() check_c_source_compiles([[ #include #if GMP_LIMB_BITS != 64 # error error #endif #include #if !(defined(__GNUC__) && defined(__ARM_NEON)) # if !(defined(_MSC_VER) && defined(_M_ARM64)) # error error # endif #endif void main(){};]] FLINT_FFT_SMALL_ARM) check_c_source_compiles([[ #include #if GMP_LIMB_BITS != 64 # error error #endif #if defined(__GNUC__) # include #elif defined(_MSC_VER) # include #else # error error #endif #if !defined(__AVX2__) # error error #endif void main(){};]] FLINT_FFT_SMALL_X86) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_FLAGS) if(FLINT_FFT_SMALL_ARM OR FLINT_FFT_SMALL_X86) message(STATUS "Checking whether fft_small module is available - yes") set(FFT_SMALL fft_small) set(FLINT_HAVE_FFT_SMALL ON) else() message(STATUS "Checking whether fft_small module is available - no") set(FFT_SMALL) endif() # Find sources set(_BUILD_DIRS generic_files thread_pool thread_support ulong_extras long_extras perm double_extras d_vec d_mat mpn_extras mpfr_vec mpfr_mat nmod nmod_vec nmod_mat nmod_poly fmpz fmpz_vec fmpz_mat fmpz_poly fmpz_mod fmpz_mod_vec fmpz_mod_mat fmpz_mod_poly fmpq fmpq_vec fmpq_mat fmpq_poly fq fq_vec fq_mat fq_poly fq_nmod fq_nmod_vec fq_nmod_mat fq_nmod_poly fq_zech fq_zech_vec fq_zech_mat fq_zech_poly fq_default fq_default_mat fq_default_poly fq_embed fq_nmod_embed fq_zech_embed padic padic_mat padic_poly qadic nmod_poly_factor fmpz_factor fmpz_poly_factor fmpz_mod_poly_factor fq_poly_factor fq_nmod_poly_factor fq_zech_poly_factor fq_default_poly_factor nmod_poly_mat fmpz_poly_mat mpoly nmod_mpoly fmpz_mpoly fmpz_mod_mpoly fmpq_mpoly fq_nmod_mpoly fq_zech_mpoly nmod_mpoly_factor fmpz_mpoly_factor fmpz_mod_mpoly_factor fmpq_mpoly_factor fq_nmod_mpoly_factor fq_zech_mpoly_factor fft ${FFT_SMALL} fmpz_poly_q fmpz_lll n_poly arith qsieve aprcl nf nf_elem qfb double_interval dlog fmpz_extras fmpzi bool_mat partitions mag arf acf arb acb arb_mat arb_poly arb_calc arb_hypgeom acb_mat acb_poly acb_calc acb_hypgeom arb_fmpz_poly arb_fpwrap acb_dft acb_elliptic acb_modular acb_dirichlet acb_theta dirichlet bernoulli hypgeom gr gr_generic gr_vec gr_mat gr_poly gr_mpoly gr_special calcium fmpz_mpoly_q fexpr fexpr_builtin qqbar ca ca_ext ca_field ca_vec ca_poly ca_mat ) string(REGEX REPLACE "([A-Za-z0-9_-]+;|[A-Za-z0-9_-]+$)" "src/\\1" BUILD_DIRS "${_BUILD_DIRS}") # NOTE: Template directories are not supposed to be used. set(_HEADERS NTL-interface.h flint.h longlong.h flint-config.h gmpcompat.h fft_tuning.h profiler.h templates.h mpf-impl.h ) string(REGEX REPLACE "([A-Za-z0-9_-]+\.h;|[A-Za-z0-9_-]+\.h$)" "src/\\1" HEADERS "${_HEADERS}") # Setup for flint-config.h check_c_compiler_flag("-mpopcnt" HAS_FLAG_MPOPCNT) check_c_compiler_flag("-funroll-loops" HAS_FLAG_UNROLL_LOOPS) # fenv configuration check_c_source_compiles([[#include #ifndef FE_DOWNWARD # error FE_DOWNWARD not available #endif void main(){};]] FLINT_USES_FENV) # cpu_set_t configuration set(CMAKE_REQUIRED_FLAGS "${PThreads_LIBRARIES}") check_c_source_compiles([[#define _GNU_SOURCE #include #include int main() { cpu_set_t s; CPU_ZERO(&s); pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), 0); return 0; }]] FLINT_USES_CPUSET) unset(CMAKE_REQUIRED_FLAGS) # Thread-local storage configuration set(FLINT_USES_TLS ON CACHE BOOL "Use thread local storage.") # Memory manager configuration set(MEMORY_MANAGER "single" CACHE STRING "The FLINT memory manager.") set_property(CACHE MEMORY_MANAGER PROPERTY STRINGS single reentrant gc) message(STATUS "Using FLINT memory manager: ${MEMORY_MANAGER}") if(MEMORY_MANAGER STREQUAL "reentrant") set(FLINT_REENTRANT ON) else() set(FLINT_REENTRANT OFF) endif() # gmpcompat.h configuration set(CMAKE_REQUIRED_INCLUDES ${GMP_INCLUDE_DIRS}) check_c_source_compiles([[#include #ifndef _LONG_LONG_LIMB # error mp_limb_t != unsigned long long limb #endif void main(){};]] LONG_LONG_LIMB) # Populate headers configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/flint-config.h ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/flint.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/flint.h ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/fmpz/link/fmpz_${MEMORY_MANAGER}.c ${CMAKE_CURRENT_SOURCE_DIR}/src/fmpz/fmpz.c COPYONLY ) if(LONG_LONG_LIMB) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/gmpcompat-longlong.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/gmpcompat.h COPYONLY ) else() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/gmpcompat.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/gmpcompat.h COPYONLY ) endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/fft_tuning64.in ${CMAKE_CURRENT_SOURCE_DIR}/src/fft_tuning.h COPYONLY ) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/fft_tuning32.in ${CMAKE_CURRENT_SOURCE_DIR}/src/fft_tuning.h COPYONLY ) endif() foreach (build_dir IN LISTS BUILD_DIRS) file(GLOB TEMP RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${build_dir}/*.c") list(APPEND SOURCES ${TEMP}) file(GLOB TEMP RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${build_dir}/*.h") list(APPEND HEADERS ${TEMP}) endforeach () set(TEMP ${HEADERS}) set(HEADERS ) foreach(header IN LISTS TEMP) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${header}) list(APPEND HEADERS ${header}) else() list(APPEND HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${header}) endif() endforeach() file(GLOB TEMP "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h") list(APPEND HEADERS ${TEMP}) add_library(flint ${SOURCES}) target_link_libraries(flint PUBLIC PkgConfig::GMP PkgConfig::MPFR ${PThreads_LIBRARIES}) if(FLINT_USES_BLAS) target_link_libraries(flint PUBLIC ${CBLAS_LIBRARIES}) endif() # Include directories target_include_directories(flint PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ${GMP_INCLUDE_DIRS} ${MPFR_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${PThreads_INCLUDE_DIRS}) if(FLINT_USES_BLAS) target_include_directories(flint PUBLIC ${CBLAS_INCLUDE_DIRS}) endif() if(BUILD_SHARED_LIBS AND MSVC) # Export all functions automatically (except global data) set_target_properties(flint PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) # Export flint's global data that are marked manually target_compile_definitions(flint PRIVATE "FLINT_BUILD_DLL") endif() if (HAS_FLAG_MPOPCNT) target_compile_options(flint PUBLIC "-mpopcnt") endif() if (HAS_FLAG_UNROLL_LOOPS) target_compile_options(flint PUBLIC "-funroll-loops") endif() if(HAS_FLAG_GCC_MARCH_NATIVE) target_compile_options(flint PUBLIC "-march=native") elseif(HAS_FLAG_MSVC_AVX2) target_compile_options(flint PUBLIC "/arch:AVX2") endif() # Versioning set_target_properties(flint PROPERTIES VERSION ${FLINT_MAJOR_SO}.${FLINT_MINOR_SO}.${FLINT_PATCH_SO} SOVERSION ${FLINT_MAJOR_SO} ) # Following versioning parts are optional # Match versioning scheme in configure based build system. if (APPLE) if(${CMAKE_VERSION} VERSION_LESS "3.17.0") message(WARNING "To match the versioning scheme of configure based build system, switch to cmake 3.17.0") else () set_target_properties(flint PROPERTIES MACHO_COMPATIBILITY_VERSION ${FLINT_MAJOR_SO}.${FLINT_MINOR_SO} MACHO_CURRENT_VERSION ${FLINT_MAJOR_SO}.${FLINT_MINOR_SO}.${FLINT_PATCH_SO} ) endif() elseif (WIN32) set_target_properties(flint PROPERTIES RUNTIME_OUTPUT_NAME "flint-${FLINT_MAJOR_SO}") endif() set_property(TARGET flint PROPERTY C_STANDARD 11) if(NOT DEFINED IPO_SUPPORTED) message(STATUS "Checking for IPO") check_ipo_supported(RESULT ipo_supported LANGUAGES C) if(ipo_supported) if (MSVC) message(STATUS "Checking for IPO - found, but disabled for MSVC") set(ipo_supported FALSE) else() message(STATUS "Checking for IPO - found") endif() else() message(STATUS "Checking for IPO - not found") endif() set(IPO_SUPPORTED ${ipo_supported} CACHE INTERNAL "Introprocedural Optimization" FORCE) endif() # allow overriding IPO by setting -DCMAKE_INTERPROCEDURAL_OPTIMIZATION if (IPO_SUPPORTED AND "${CMAKE_INTERPROCEDURAL_OPTIMIZATION}" STREQUAL "") set_target_properties(flint PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) endif() if(NOT MSVC) target_link_libraries(flint PUBLIC m) endif() include(GNUInstallDirs) install(TARGETS flint RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" ) install(FILES ${HEADERS} DESTINATION include/flint) set_target_properties(flint PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" ) # Install PkgConfig file set(prefix ${CMAKE_INSTALL_PREFIX}) set(exec_prefix "\$\{prefix\}") set(includedir "\$\{prefix\}/include") set(libdir "\$\{prefix\}/${CMAKE_INSTALL_LIBDIR}") set(PACKAGE_NAME ${PROJECT_NAME}) set(PACKAGE_VERSION ${PROJECT_VERSION}) configure_file(flint.pc.in flint.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/flint.pc DESTINATION lib/pkgconfig) if(BUILD_TESTING) set(FLINT_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src) # To get src/test/main enable_testing() foreach(dir IN LISTS BUILD_DIRS FLINT_SRC) file(GLOB test_file "${dir}/test/main.c") if(test_file) file(RELATIVE_PATH test_name ${CMAKE_CURRENT_SOURCE_DIR} ${test_file}) string(REPLACE "/" "-" test_name ${test_name}) get_filename_component(test_name ${test_name} NAME_WE) add_executable(${test_name} ${test_file}) target_link_libraries(${test_name} flint) add_test(NAME ${test_name} COMMAND $) set_target_properties(${test_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") endif() endforeach () if(WITH_NTL) file(GLOB test_file "src/interfaces/test/t-NTL-interface.cpp") file(RELATIVE_PATH test_name ${CMAKE_CURRENT_SOURCE_DIR} ${test_file}) string(REPLACE "/" "-" test_name ${test_name}) get_filename_component(test_name ${test_name} NAME_WE) add_executable(${test_name} ${test_file}) target_link_libraries(${test_name} flint ${NTL_LIBRARY}) target_include_directories(${test_name} PUBLIC ${NTL_INCLUDE_DIR}) add_test(NAME ${test_name} COMMAND $) set_target_properties(${test_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") endif() endif() if(BUILD_DOCS) find_package(Sphinx REQUIRED) file(GLOB DOC_SOURCES doc/source/*.rst) add_custom_target(html COMMAND ${SPHINX_EXECUTABLE} -b html "${CMAKE_CURRENT_SOURCE_DIR}/doc/source" "${CMAKE_CURRENT_BINARY_DIR}/html" SOURCES ${DOC_SOURCES}) add_custom_target(latex COMMAND ${SPHINX_EXECUTABLE} -b latex "${CMAKE_CURRENT_SOURCE_DIR}/doc/source" "${CMAKE_CURRENT_BINARY_DIR}/latex" SOURCES ${DOC_SOURCES}) add_custom_target(pdf DEPENDS latex COMMAND make WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/latex") endif() flint-3.1.3/COPYING000066400000000000000000001045151461254215100136740ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . flint-3.1.3/COPYING.LESSER000066400000000000000000000167441461254215100146760ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. flint-3.1.3/INSTALL000066400000000000000000000023671461254215100136740ustar00rootroot00000000000000Instructions on installing FLINT ---------------------------------- Building FLINT requires: * GMP (https://gmplib.org/) * MPFR (https://mpfr.org/) * Either of the following build systems: * GNU Make together with GNU Autotools * CMake On a typical Linux or Unix-like system where Autotools is available, FLINT can be built and installed as follows: .. code-block:: bash ./bootstrap.sh ./configure --disable-static make -j make install We also recommend that you run ``make check`` before installing. For a complete list of build settings, write ./configure --help An example of a custom configuration command would be ./configure \ --enable-assert \ --enable-avx2 \ --disable-static \ --with-gmp-include=/home/user1/builds/includes/ \ --with-gmp-lib=/home/user1/builds/lib/ \ --with-mpfr=/usr \ --prefix=/home/user1/installations/ \ CC=clang \ CFLAGS="-Wall -O3 -march=alderlake" For more information, see the FLINT documentation. flint-3.1.3/Makefile.in000066400000000000000000001127261461254215100147110ustar00rootroot00000000000000# # Copyright (C) 2023 Albin Ahlbäck # # This file is part of FLINT. # # FLINT is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License (LGPL) as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. See . # FLINT_DIR:=. SRC_DIR:=src BUILD_DIR:=build ABS_FLINT_DIR:='$(patsubst %/,%, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))' ABS_SRC_DIR:=$(ABS_FLINT_DIR)/$(SRC_DIR) ABS_BUILD_DIR:=$(ABS_FLINT_DIR)/$(SRC_DIR) FLINT_VERSION:=@FLINT_VERSION_FULL@ FLINT_MAJOR_SO:=@FLINT_MAJOR_SO@ FLINT_MINOR_SO:=@FLINT_MINOR_SO@ FLINT_PATCH_SO:=@FLINT_PATCH_SO@ FLINT_LIB:=@FLINT_LIB@ FLINT_LIB_MAJOR:=@FLINT_LIB_MAJOR@ FLINT_LIB_FULL:=@FLINT_LIB_FULL@ FLINT_IMPLIB:=@FLINT_IMPLIB@ FLINT_LIB_STATIC:=@FLINT_LIB_STATIC@ FLINT_DLLLIB:=@FLINT_DLLLIB@ FLINT_DYLIB:=@FLINT_DYLIB@ FLINT_SOLIB:=@FLINT_SOLIB@ prefix:=@prefix@ exec_prefix:=@exec_prefix@ INCLUDEDIR:=@includedir@ LIBDIR:=@libdir@ BINDIR:=@bindir@ PKGCONFIGDIR:=$(LIBDIR)/pkgconfig HOST_OS:=@host_os@ EXEEXT:=@EXEEXT@ AR:=@AR@ CC:=@CC@ CXX:=@CC@ DLLTOOL:=@DLLTOOL@ LD:=@LD@ LN_S:=@LN_S@ M4:=@M4@ MKDIR_P:=@MKDIR_P@ STRIP:=@STRIP@ RM_F:=rm -f RM_RF:=rm -rf CP:=cp CP_A:=cp -a STATIC:=@STATIC@ SHARED:=@SHARED@ COVERAGE:=@COVERAGE@ WANT_NTL:=@WANT_NTL@ WANT_DEPS:=@WANT_DEPS@ WANT_CXX:=@WANT_CXX@ WANT_ADX_ASSEMBLY:=@WANT_ADX_ASSEMBLY@ GMP_LIB_PATH:=@GMP_LIB_PATH@ MPFR_LIB_PATH:=@MPFR_LIB_PATH@ BLAS_LIB_PATH:=@BLAS_LIB_PATH@ GC_LIB_PATH:=@GC_LIB_PATH@ NTL_LIB_PATH:=@NTL_LIB_PATH@ CFLAGS:=@CFLAGS@ TESTCFLAGS:=@TESTCFLAGS@ CPPFLAGS:=@CPPFLAGS@ -DBUILDING_FLINT CPPFLAGS2:=-L$(FLINT_DIR) $(CPPFLAGS) LIB_CPPFLAGS:=@LIB_CPPFLAGS@ CXXFLAGS:=@CXXFLAGS@ LIBS:=@LIBS@ ifneq ($(WANT_NTL), 0) LIBS += -lstdc++ -lntl endif LIBS2:=-lflint $(LIBS) PIC_FLAG:=@PIC_FLAG@ ifeq ($(WANT_ADX_ASSEMBLY),1) ASM_OBJ_FLAGS:=$(filter-out -D%,$(CPPFLAGS) $(LIB_CPPFLAGS)) $(filter-out -funroll-loops -pedantic, $(CFLAGS)) ASM_LOBJ_FLAGS:=$(filter-out -D%,$(PIC_FLAG)) $(ASM_OBJ_FLAGS) endif UNROLL_LOOPS:=@UNROLL_LOOPS@ ifeq ($(UNROLL_LOOPS), 1) ulong_extras_CFLAGS:=-funroll-loops nmod_CFLAGS:=-funroll-loops nmod_vec_CFLAGS:=-funroll-loops nmod_mat_CFLAGS:=-funroll-loops nmod_poly_CFLAGS:=-funroll-loops arith_CFLAGS:=-funroll-loops endif LDFLAGS:=@LDFLAGS@ EXTRA_SHARED_FLAGS:=@EXTRA_SHARED_FLAGS@ $(foreach path, $(sort $(GMP_LIB_PATH) $(MPFR_LIB_PATH) $(BLAS_LIB_PATH) $(GC_LIB_PATH) $(NTL_LIB_PATH)), @WL@-rpath,$(path)) EXE_LDFLAGS:=$(LDFLAGS) $(foreach path, $(sort $(ABS_FLINT_DIR) $(GMP_LIB_PATH) $(MPFR_LIB_PATH) $(BLAS_LIB_PATH) $(GC_LIB_PATH) $(NTL_LIB_PATH)), @WL@-rpath,$(path)) # Obtain level of parallel JOBS:=$(filter -j%,$(MAKEFLAGS)) NJOBS:=$(patsubst -j%,%,$(JOBS)) # User may specify -j without specifying the number of jobs ifneq ($(JOBS),) ifeq ($(NJOBS),) # TODO: Create a thing in autoconf in order to obtain the number of available # cores when -j is specified without any number attached, such as `nproc`. NJOBS:=8 endif endif ################################################################################ ################################################################################ # files and directories ################################################################################ ################################################################################ ################################################################################ # configuration files ################################################################################ CFG_FILES := \ $(FLINT_DIR)/config.h $(SRC_DIR)/flint-config.h \ $(FLINT_DIR)/config.log $(SRC_DIR)/flint.h \ $(SRC_DIR)/fft_tuning.h $(FLINT_DIR)/flint.pc \ $(FLINT_DIR)/Makefile $(SRC_DIR)/fmpz/fmpz.c \ $(SRC_DIR)/gmpcompat.h $(SRC_DIR)/config.m4 ################################################################################ # directories ################################################################################ HEADLESS_DIRS := generic_files HEADER_DIRS := \ thread_pool thread_support \ \ ulong_extras \ long_extras \ perm \ double_extras d_vec d_mat \ mpn_extras \ mpfr_vec mpfr_mat \ nmod nmod_vec nmod_mat nmod_poly \ fmpz fmpz_vec fmpz_mat fmpz_poly \ fmpz_mod fmpz_mod_vec fmpz_mod_mat fmpz_mod_poly \ fmpq fmpq_vec fmpq_mat fmpq_poly \ \ fq fq_vec fq_mat fq_poly \ fq_nmod fq_nmod_vec fq_nmod_mat fq_nmod_poly \ fq_zech fq_zech_mat fq_zech_poly \ fq_default fq_default_mat fq_default_poly \ fq_embed \ fq_nmod_embed \ fq_zech_embed \ padic padic_mat padic_poly \ qadic \ \ nmod_poly_factor fmpz_factor \ fmpz_poly_factor fmpz_mod_poly_factor \ fq_poly_factor fq_nmod_poly_factor \ fq_zech_poly_factor fq_default_poly_factor \ \ nmod_poly_mat fmpz_poly_mat \ \ mpoly nmod_mpoly fmpz_mpoly fmpz_mod_mpoly \ fmpq_mpoly fq_nmod_mpoly fq_zech_mpoly \ \ nmod_mpoly_factor fmpz_mpoly_factor \ fmpz_mod_mpoly_factor fmpq_mpoly_factor \ fq_nmod_mpoly_factor fq_zech_mpoly_factor \ \ fft @FFT_SMALL@ fmpz_poly_q fmpz_lll \ n_poly arith qsieve aprcl \ \ nf nf_elem qfb \ \ double_interval dlog \ fmpz_extras fmpzi \ bool_mat partitions \ mag \ arf acf arb acb \ arb_mat arb_poly arb_calc arb_hypgeom \ acb_mat acb_poly acb_calc acb_hypgeom \ arb_fmpz_poly arb_fpwrap \ acb_dft acb_elliptic acb_modular acb_dirichlet \ acb_theta dirichlet bernoulli hypgeom \ \ gr gr_generic gr_vec gr_mat \ gr_poly gr_mpoly gr_special \ \ calcium \ fmpz_mpoly_q \ fexpr fexpr_builtin \ qqbar \ ca ca_ext ca_field ca_vec \ ca_poly ca_mat DIRS := $(HEADLESS_DIRS) $(HEADER_DIRS) TEMPLATE_DIRS := \ fq_vec_templates fq_mat_templates \ fq_poly_templates fq_poly_factor_templates \ fq_embed_templates fq_templates BUILD_DIRS := \ $(BUILD_DIR) \ $(patsubst %, $(BUILD_DIR)/%, $(DIRS)) \ $(patsubst %, $(BUILD_DIR)/%/profile, $(DIRS)) \ $(patsubst %, $(BUILD_DIR)/%/test, $(DIRS)) \ $(patsubst %, $(BUILD_DIR)/%/tune, $(DIRS)) \ $(BUILD_DIR)/examples $(BUILD_DIR)/profile \ $(BUILD_DIR)/test $(BUILD_DIR)/tune ifneq ($(WANT_NTL), 0) BUILD_DIRS += \ $(BUILD_DIR)/interfaces $(BUILD_DIR)/interfaces/test endif ifneq ($(COVERAGE), 0) BUILD_DIRS += \ $(BUILD_DIR)/coverage endif ifeq ($(WANT_ADX_ASSEMBLY),1) BUILD_DIRS += \ $(BUILD_DIR)/mpn_extras/broadwell endif INSTALL_DIRS := \ $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR)/flint \ $(DESTDIR)$(PKGCONFIGDIR) ifneq ($(FLINT_DLLLIB),0) INSTALL_DIRS += $(DESTDIR)$(BINDIR) endif ################################################################################ # headers ################################################################################ SINGLE_HEADERS := \ flint.h flint-config.h gmpcompat.h \ profiler.h templates.h fft_tuning.h \ \ longlong.h longlong_asm_clang.h \ longlong_asm_gcc.h longlong_div_gnu.h \ longlong_msc_arm64.h longlong_msc_x86.h \ \ crt_helpers.h machine_vectors.h \ \ mpf-impl.h fq_zech_vec.h \ \ limb_types.h nmod_types.h \ fmpz_types.h fmpq_types.h \ fmpz_mod_types.h fq_nmod_types.h \ fq_zech_types.h fq_types.h \ padic_types.h \ n_poly_types.h mpoly_types.h \ arf_types.h acf_types.h \ arb_types.h acb_types.h \ NTL-interface.h HEADERS := $(patsubst %,$(SRC_DIR)/%, \ $(patsubst %,%,$(SINGLE_HEADERS)) \ $(patsubst %,%.h,$(HEADER_DIRS)) \ $(patsubst %,%.h,$(TEMPLATE_DIRS)) \ ) ################################################################################ # sources ################################################################################ define xxx_SOURCES $(1)_SOURCES := $(wildcard $(SRC_DIR)/$(1)/*.c) endef $(foreach dir, $(DIRS), $(eval $(call xxx_SOURCES,$(dir)))) # We clear some template files fmpz_lll_SOURCES := $(filter-out $(SRC_DIR)/fmpz_lll/babai.c $(SRC_DIR)/fmpz_lll/mpf2_lll.c $(SRC_DIR)/fmpz_lll/d_lll.c,$(fmpz_lll_SOURCES)) SOURCES := $(foreach dir,$(DIRS),$($(dir)_SOURCES)) ifeq ($(WANT_ADX_ASSEMBLY),1) mpn_extras_ASM_SOURCES := $(wildcard $(SRC_DIR)/mpn_extras/broadwell/*.asm) mpn_extras_PIC_S_SOURCES := $(patsubst $(SRC_DIR)/%.asm,$(BUILD_DIR)/%_pic.s,$(mpn_extras_ASM_SOURCES)) mpn_extras_S_SOURCES := $(patsubst $(SRC_DIR)/%.asm,$(BUILD_DIR)/%.s,$(mpn_extras_ASM_SOURCES)) ifneq ($(SHARED), 0) mpn_extras_SOURCES += $(mpn_extras_PIC_S_SOURCES) endif ifneq ($(STATIC), 0) mpn_extras_SOURCES += $(mpn_extras_S_SOURCES) endif endif define xxx_PROF_SOURCES $(1)_PROF_SOURCES := $(wildcard $(SRC_DIR)/$(1)/profile/*.c) endef _PROF_SOURCES := $(wildcard $(SRC_DIR)/profile/*.c) $(foreach dir, $(DIRS), $(eval $(call xxx_PROF_SOURCES,$(dir)))) PROF_SOURCES := $(foreach dir,$(DIRS),$($(dir)_PROF_SOURCES)) $(_PROF_SOURCES) # FIXME: De-hardcode fq_zech_vec from this. fq_zech_vec_TEST_SOURCES := $(wildcard $(SRC_DIR)/fq_zech_vec/test/main.c) define xxx_TEST_SOURCES $(1)_TEST_SOURCES := $(wildcard $(SRC_DIR)/$(1)/test/main.c) endef _TEST_SOURCES := $(wildcard $(SRC_DIR)/test/main.c) $(foreach dir, $(DIRS), $(eval $(call xxx_TEST_SOURCES,$(dir)))) TEST_SOURCES := $(_TEST_SOURCES) $(foreach dir,$(DIRS),$($(dir)_TEST_SOURCES)) $(fq_zech_vec_TEST_SOURCES) # NOTE: We do not add CPP files to C files in SOURCES in order to not screw up # the `patsubst' in the object files. ifneq ($(WANT_NTL), 0) interfaces_TEST_SOURCES := $(SRC_DIR)/interfaces/test/t-NTL-interface.cpp endif define xxx_TUNE_SOURCES $(1)_TUNE_SOURCES := $(wildcard $(SRC_DIR)/$(1)/tune/*.c) endef _TUNE_SOURCES := $(wildcard $(SRC_DIR)/tune/*.c) $(foreach dir, $(DIRS), $(eval $(call xxx_TUNE_SOURCES,$(dir)))) TUNE_SOURCES := $(foreach dir,$(DIRS),$($(dir)_TUNE_SOURCES)) $(_TUNE_SOURCES) EXMP_SOURCES := $(wildcard $(FLINT_DIR)/examples/*.c) ################################################################################ # objects ################################################################################ ifneq ($(STATIC), 0) define xxx_OBJS $(1)_OBJS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(filter-out %.s,$($(1)_SOURCES))) endef $(foreach dir, $(DIRS), $(eval $(call xxx_OBJS,$(dir)))) ifeq ($(WANT_ADX_ASSEMBLY),1) mpn_extras_OBJS += $(patsubst %.s,%.o,$(mpn_extras_S_SOURCES)) endif OBJS := $(foreach dir, $(DIRS), $($(dir)_OBJS)) endif ################################################################################ # library objects ################################################################################ ifneq ($(SHARED), 0) define xxx_LOBJS $(1)_LOBJS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.lo,$(filter-out %.s, $($(1)_SOURCES))) endef $(foreach dir, $(DIRS), $(eval $(call xxx_LOBJS,$(dir)))) ifeq ($(WANT_ADX_ASSEMBLY),1) mpn_extras_LOBJS += $(patsubst %_pic.s,%.lo,$(mpn_extras_PIC_S_SOURCES)) endif LOBJS := $(foreach dir, $(DIRS), $($(dir)_LOBJS)) endif ################################################################################ # executables ################################################################################ define xxx_PROFS $(1)_PROFS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%$(EXEEXT),$($(1)_PROF_SOURCES)) endef _PROFS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%$(EXEEXT),$(_PROF_SOURCES)) $(foreach dir, $(DIRS), $(eval $(call xxx_PROFS,$(dir)))) PROFS := $(foreach dir,$(DIRS),$($(dir)_PROFS)) $(_PROFS) define xxx_TESTS $(1)_TESTS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%$(EXEEXT),$($(1)_TEST_SOURCES)) endef _TESTS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%$(EXEEXT),$(_TEST_SOURCES)) $(foreach dir, $(DIRS), $(eval $(call xxx_TESTS,$(dir)))) ifneq ($(WANT_NTL), 0) interfaces_TESTS := $(BUILD_DIR)/interfaces/test/t-NTL-interface$(EXEEXT) endif TESTS := $(_TESTS) $(foreach dir,$(DIRS),$($(dir)_TESTS)) $(interfaces_TESTS) define xxx_TUNES $(1)_TUNES := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%$(EXEEXT),$($(1)_TUNE_SOURCES)) endef _TUNES := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%$(EXEEXT),$(_TUNE_SOURCES)) $(foreach dir, $(DIRS), $(eval $(call xxx_TUNES,$(dir)))) TUNES := $(foreach dir,$(DIRS),$($(dir)_TUNES)) $(_TUNES) EXMPS := $(patsubst $(FLINT_DIR)/%.c,$(BUILD_DIR)/%$(EXEEXT),$(EXMP_SOURCES)) ################################################################################ ################################################################################ # recipes ################################################################################ ################################################################################ ################################################################################ # main recipe ################################################################################ all: library ################################################################################ # library ################################################################################ ifneq ($(SHARED), 0) library: shared endif ifneq ($(STATIC), 0) library: static endif ifneq ($(SHARED), 0) shared: $(FLINT_DIR)/$(FLINT_LIB_FULL) # The following is to avoid reaching the maximum length of command line # arguments, mainly present on MinGW. define xxx_merged_lobj_rule $(BUILD_DIR)/$(1)_merged.lo: $($(1)_LOBJS) | $(BUILD_DIR) @$(LD) -r $($(1)_LOBJS) -o $(BUILD_DIR)/$(1)_merged.lo endef $(foreach dir, $(DIRS), $(eval $(call xxx_merged_lobj_rule,$(dir)))) MERGED_LOBJS:=$(foreach dir, $(DIRS),$(BUILD_DIR)/$(dir)_merged.lo) $(FLINT_DIR)/$(FLINT_LIB_FULL): $(MERGED_LOBJS) @echo "Building $(FLINT_LIB_FULL)" @$(CC) $(CFLAGS) -shared $(EXTRA_SHARED_FLAGS) $(MERGED_LOBJS) -o $(FLINT_LIB_FULL) $(LDFLAGS) $(LIBS) @$(RM_F) $(FLINT_LIB) @$(RM_F) $(FLINT_LIB_MAJOR) @$(LN_S) $(FLINT_LIB_FULL) $(FLINT_LIB) @$(LN_S) $(FLINT_LIB_FULL) $(FLINT_LIB_MAJOR) endif ifneq ($(STATIC), 0) static: $(FLINT_DIR)/$(FLINT_LIB_STATIC) # The following is to avoid reaching the maximum length of command line # arguments, mainly present on MinGW. define xxx_merged_obj_rule $(BUILD_DIR)/$(1)_merged.o: $($(1)_OBJS) | $(BUILD_DIR) @$(LD) -r $($(1)_OBJS) -o $(BUILD_DIR)/$(1)_merged.o endef $(foreach dir, $(DIRS), $(eval $(call xxx_merged_obj_rule,$(dir)))) MERGED_OBJS:=$(foreach dir, $(DIRS),$(BUILD_DIR)/$(dir)_merged.o) $(FLINT_DIR)/$(FLINT_LIB_STATIC): $(MERGED_OBJS) @echo "Building $(FLINT_LIB_STATIC)" @$(AR) rcs $(FLINT_DIR)/$(FLINT_LIB_STATIC) $(MERGED_OBJS) endif ################################################################################ # directories ################################################################################ $(BUILD_DIRS) $(INSTALL_DIRS): $(MKDIR_P) $@ ################################################################################ # inclusions ################################################################################ ifneq ($(WANT_DEPS), 0) ifeq ($(words $(MAKECMDGOALS)), 0) -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d else ifeq ($(words $(MAKECMDGOALS)), 1) ifeq ($(MAKECMDGOALS), clean) # Include nothing else ifeq ($(MAKECMDGOALS), dist) # Include nothing else ifeq ($(MAKECMDGOALS), distclean) # Include nothing else ifeq ($(MAKECMDGOALS), uninstall) # Include nothing else ifeq ($(findstring print-,$(MAKECMDGOALS)), print-) # Include nothing else ifeq ($(MAKECMDGOALS), static) -include $(BUILD_DIR)/*/*.o.d else ifeq ($(MAKECMDGOALS), shared) -include $(BUILD_DIR)/*/*.lo.d else ifeq ($(MAKECMDGOALS), library) -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d else ifeq ($(MAKECMDGOALS), install) -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d else ifeq ($(MAKECMDGOALS), examples) -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/examples/*.d else ifeq ($(MAKECMDGOALS), profile) ifdef MOD $(warning Dependency tracking only set to cover the profile executables of $(MOD).) -include $(foreach dir, $(MOD), $(BUILD_DIR)/$(dir)/profile/*.d) else -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/profile/*.d -include $(BUILD_DIR)/*/profile/*.d endif else ifeq ($(MAKECMDGOALS), tests) -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/test/*.d -include $(BUILD_DIR)/*/test/*.d else ifeq ($(MAKECMDGOALS), check) ifdef MOD $(warning Dependency tracking only set to cover the test executables of $(MOD).) -include $(foreach dir, $(MOD), $(BUILD_DIR)/$(dir)/test/*.d) else -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/test/*.d -include $(BUILD_DIR)/*/test/*.d endif else ifeq ($(MAKECMDGOALS), tune) -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/tune/*.d -include $(BUILD_DIR)/*/tune/*.d else ifeq ($(MAKECMDGOALS), valgrind) ifdef MOD $(warning Dependency tracking only set to cover the test executables of $(MOD).) -include $(foreach dir, $(MOD), $(BUILD_DIR)/$(dir)/test/*.d) else -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/test/*.d -include $(BUILD_DIR)/*/test/*.d endif else # Cannot recognize the command, so we simply include everything -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/test/*.d -include $(BUILD_DIR)/*/test/*.d -include $(BUILD_DIR)/profile/*.d -include $(BUILD_DIR)/*/profile/*.d -include $(BUILD_DIR)/examples/*.d endif else # Multiple goals. Not currently implemented, so simply include everything. -include $(BUILD_DIR)/*/*.o.d -include $(BUILD_DIR)/*/*.lo.d -include $(BUILD_DIR)/test/*.d -include $(BUILD_DIR)/*/test/*.d -include $(BUILD_DIR)/profile/*.d -include $(BUILD_DIR)/*/profile/*.d -include $(BUILD_DIR)/examples/*.d endif endif DEPFLAGS = -MMD -MP -MF $(@:%=%.d) ################################################################################ # generated sources ################################################################################ ifeq ($(WANT_ADX_ASSEMBLY),1) $(BUILD_DIR)/%.s: $(SRC_DIR)/%.asm $(FLINT_DIR)/config.m4 $(SRC_DIR)/mpn_extras/asm-defs.m4 $(SRC_DIR)/mpn_extras/broadwell/x86_64-defs.m4 | $(BUILD_DIR)/mpn_extras/broadwell @$(M4) $< > $@ $(BUILD_DIR)/%_pic.s: $(SRC_DIR)/%.asm $(FLINT_DIR)/config.m4 $(SRC_DIR)/mpn_extras/asm-defs.m4 $(SRC_DIR)/mpn_extras/broadwell/x86_64-defs.m4 | $(BUILD_DIR)/mpn_extras/broadwell @$(M4) -DPIC $< > $@ endif ################################################################################ # objects ################################################################################ ifneq ($(STATIC), 0) define xxx_OBJS_rule $(BUILD_DIR)/$(1)/%.o: $(SRC_DIR)/$(1)/%.c | $(BUILD_DIR)/$(1) @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(CFLAGS) $($(1)_CFLAGS) $(CPPFLAGS) $(LIB_CPPFLAGS) -c $$< -o $$@ $$(DEPFLAGS) endef ifeq ($(WANT_ADX_ASSEMBLY),1) %.o: %.s @echo " CC $(<:$(BUILD_DIR)/%.s=%.asm)" @$(CC) $(ASM_OBJ_FLAGS) -c $< -o $@ endif $(foreach dir, $(DIRS), $(eval $(call xxx_OBJS_rule,$(dir)))) endif ################################################################################ # library objects ################################################################################ ifneq ($(SHARED), 0) define xxx_LOBJS_rule $(BUILD_DIR)/$(1)/%.lo: $(SRC_DIR)/$(1)/%.c | $(BUILD_DIR)/$(1) @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(PIC_FLAG) $(CFLAGS) $($(1)_CFLAGS) $(CPPFLAGS) $(LIB_CPPFLAGS) -c $$< -o $$@ $$(DEPFLAGS) endef ifeq ($(WANT_ADX_ASSEMBLY),1) %.lo: %_pic.s @echo " CC $(<:$(BUILD_DIR)/%.s=%.asm)" @$(CC) $(ASM_LOBJ_FLAGS) -c $< -o $@ endif $(foreach dir, $(DIRS), $(eval $(call xxx_LOBJS_rule,$(dir)))) endif ################################################################################ # executables ################################################################################ ifeq ($(SHARED), 0) $(BUILD_DIR)/profile/%$(EXEEXT): $(SRC_DIR)/profile/%.c $(FLINT_DIR)/$(FLINT_LIB_STATIC) | $(BUILD_DIR)/profile @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) else $(BUILD_DIR)/profile/%$(EXEEXT): $(SRC_DIR)/profile/%.c | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/profile @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) endif ifeq ($(SHARED), 0) define xxx_PROFS_rule $(BUILD_DIR)/$(1)/profile/%$(EXEEXT): $(SRC_DIR)/$(1)/profile/%.c $(FLINT_DIR)/$(FLINT_LIB_STATIC) | $(BUILD_DIR)/$(1)/profile @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $$< -o $$@ $(EXE_LDFLAGS) $(LIBS2) $$(DEPFLAGS) endef else define xxx_PROFS_rule $(BUILD_DIR)/$(1)/profile/%$(EXEEXT): $(SRC_DIR)/$(1)/profile/%.c | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/$(1)/profile @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $$< -o $$@ $(EXE_LDFLAGS) $(LIBS2) $$(DEPFLAGS) endef endif $(foreach dir, $(DIRS), $(eval $(call xxx_PROFS_rule,$(dir)))) ifeq ($(SHARED), 0) $(BUILD_DIR)/test/%$(EXEEXT): $(SRC_DIR)/test/%.c $(FLINT_DIR)/$(FLINT_LIB_STATIC) | $(BUILD_DIR)/test @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) else $(BUILD_DIR)/test/%$(EXEEXT): $(SRC_DIR)/test/%.c | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/test @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) endif ifeq ($(SHARED), 0) define xxx_TESTS_rule $(BUILD_DIR)/$(1)/test/%$(EXEEXT): $(SRC_DIR)/$(1)/test/%.c $(FLINT_DIR)/libflint.a | $(BUILD_DIR)/$(1)/test @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $$< -o $$@ $(EXE_LDFLAGS) $(LIBS2) $$(DEPFLAGS) endef else define xxx_TESTS_rule $(BUILD_DIR)/$(1)/test/%$(EXEEXT): $(SRC_DIR)/$(1)/test/%.c | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/$(1)/test @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $$< -o $$@ $(EXE_LDFLAGS) $(LIBS2) $$(DEPFLAGS) endef endif $(foreach dir, $(DIRS), $(eval $(call xxx_TESTS_rule,$(dir)))) ifneq ($(WANT_NTL), 0) ifeq ($(SHARED), 0) $(BUILD_DIR)/interfaces/test/t-NTL-interface$(EXEEXT): $(SRC_DIR)/interfaces/test/t-NTL-interface.cpp $(FLINT_DIR)/$(FLINT_LIB_STATIC) | $(BUILD_DIR)/interfaces/test @echo " CXX $(<:$(SRC_DIR)/%=%)" @$(CXX) $(CXXFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) else $(BUILD_DIR)/interfaces/test/t-NTL-interface$(EXEEXT): $(SRC_DIR)/interfaces/test/t-NTL-interface.cpp | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/interfaces/test @echo " CXX $(<:$(SRC_DIR)/%=%)" @$(CXX) $(CXXFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) endif endif ifeq ($(SHARED), 0) $(BUILD_DIR)/tune/%$(EXEEXT): $(SRC_DIR)/tune/%.c $(FLINT_DIR)/$(FLINT_LIB_STATIC) | $(BUILD_DIR)/tune @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) else $(BUILD_DIR)/tune/%$(EXEEXT): $(SRC_DIR)/tune/%.c | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/tune @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) endif ifeq ($(SHARED), 0) define xxx_TUNES_rule $(BUILD_DIR)/$(1)/tune/%$(EXEEXT): $(SRC_DIR)/$(1)/tune/%.c $(FLINT_DIR)/$(FLINT_LIB_STATIC) | $(BUILD_DIR)/$(1)/tune @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $$< -o $$@ $(EXE_LDFLAGS) $(LIBS2) $$(DEPFLAGS) endef else define xxx_TUNES_rule $(BUILD_DIR)/$(1)/tune/%$(EXEEXT): $(SRC_DIR)/$(1)/tune/%.c | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/$(1)/tune @echo " CC $$(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $$< -o $$@ $(EXE_LDFLAGS) $(LIBS2) $$(DEPFLAGS) endef endif $(foreach dir, $(DIRS), $(eval $(call xxx_TUNES_rule,$(dir)))) ifeq ($(SHARED), 0) $(BUILD_DIR)/examples/%$(EXEEXT): $(FLINT_DIR)/examples/%.c $(FLINT_DIR)/$(FLINT_LIB_STATIC) | $(BUILD_DIR)/examples @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) else $(BUILD_DIR)/examples/%$(EXEEXT): $(FLINT_DIR)/examples/%.c | $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BUILD_DIR)/examples @echo " CC $(<:$(SRC_DIR)/%=%)" @$(CC) $(TESTCFLAGS) $(CPPFLAGS2) $< -o $@ $(EXE_LDFLAGS) $(LIBS2) $(DEPFLAGS) endif ################################################################################ # examples ################################################################################ examples: library $(EXMPS) %_EXMP_RUN: % @$(FLINT_DIR)/dev/check_examples.sh $(patsubst $(BUILD_DIR)/examples/%,%,$<) $(BUILD_DIR)/examples checkexamples: examples $(EXMPS:%=%_EXMP_RUN) ################################################################################ # profiling ################################################################################ ifdef MOD profile: library $(foreach dir, $(MOD), $($(dir)_PROFS)) else profile: library $(PROFS) endif ################################################################################ # tests ################################################################################ tests: library $(TESTS) # NOTE: File has to be located in another directory in order for this to work. %_TEST_RUN: % @$< # Parallel running of same test file ifneq ($(NJOBS),) number_generator=$(words $2) $(if $(word $1,$2),,$(call number_generator,$1,w $2)) THREAD_LIST:=$(call number_generator,$(NJOBS),w) define xxx_test_run_parallel %_TEST_RUN_$(1): % @$$< --numthreads=$(NJOBS) --thread=$(1) endef $(foreach num, $(THREAD_LIST), $(eval $(call xxx_test_run_parallel,$(num)))) endif # NOTE: One has to run `make check PYTHON=1' and `make check' separately. ifdef PYTHON ifeq ($(findstring linux,$(HOST_OS)),linux) check: library @LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$(ABS_FLINT_DIR) python3 $(SRC_DIR)/python/flint_ctypes.py @echo '' @echo 'All Python tests passed.' else check: library @python3 $(SRC_DIR)/python/flint_ctypes.py @echo '' @echo 'All Python tests passed.' endif else ifdef MOD ifeq ($(NJOBS),) check: library $(patsubst %,%_TEST_RUN,$(foreach dir, $(MOD), $($(dir)_TESTS))) @echo '' ifeq ($(words $(sort $(MOD))),0) @echo 'No tests where performed.' else ifeq ($(words $(sort $(MOD))),1) @echo 'All tests passed for $(sort $(MOD)).' else ifeq ($(words $(sort $(MOD))),2) @echo 'All tests passed for $(firstword $(sort $(MOD))) and $(lastword $(sort $(MOD))).' else @echo 'All tests passed for $(foreach dir,$(filter-out $(lastword $(filter-out $(lastword $(sort $(MOD))),$(sort $(MOD)))) $(lastword $(sort $(MOD))),$(sort $(MOD))),$(dir),) $(lastword $(filter-out $(lastword $(sort $(MOD))),$(sort $(MOD)))) and $(lastword $(sort $(MOD))).' endif else check: library $(foreach x_test,$(patsubst %,%_TEST_RUN,$(foreach dir,$(MOD),$($(dir)_TESTS))),$(foreach num,$(THREAD_LIST),$(x_test)_$(num))) @echo '' ifeq ($(words $(sort $(MOD))),0) @echo 'No tests where performed.' else ifeq ($(words $(sort $(MOD))),1) @echo 'All tests passed for $(sort $(MOD)).' else ifeq ($(words $(sort $(MOD))),2) @echo 'All tests passed for $(firstword $(sort $(MOD))) and $(lastword $(sort $(MOD))).' else @echo 'All tests passed for $(foreach dir,$(filter-out $(lastword $(filter-out $(lastword $(sort $(MOD))),$(sort $(MOD)))) $(lastword $(sort $(MOD))),$(sort $(MOD))),$(dir),) $(lastword $(filter-out $(lastword $(sort $(MOD))),$(sort $(MOD)))) and $(lastword $(sort $(MOD))).' endif endif else check: library $(TESTS:%=%_TEST_RUN) @echo '' @echo 'All tests passed.' endif ################################################################################ # tuning ################################################################################ tune: library $(TUNES) ################################################################################ # valgrind ################################################################################ %_VALGRIND_RUN: % valgrind --track-origins=yes --leak-check=full --show-reachable=yes --log-file="$*.valgrind" $< ifdef MOD valgrind: library $(patsubst %,%_VALGRIND_RUN,$(foreach dir, $(MOD), $($(dir)_TESTS))) else valgrind: library $(TESTS:%=%_VALGRIND_RUN) endif ################################################################################ # coverage ################################################################################ ifneq ($(COVERAGE), 0) coverage: | $(BUILD_DIR)/coverage lcov --capture --exclude "*test/t-*.c" --exclude "*test/main.c" --exclude "/usr/*" --directory $(BUILD_DIR) --output-file $(BUILD_DIR)/coverage/coverage.info # TODO: Add -j $(NJOBS) and --omit-lines "flint_throw" --omit-lines '^}$$' to # lcov flags when next Ubuntu LTS ships lcov v2.0.0+. coverage_html: coverage genhtml $(NJOBS) $(BUILD_DIR)/coverage/coverage.info --output-directory $(BUILD_DIR)/coverage endif ################################################################################ # clean ################################################################################ clean: $(RM_F) $(FLINT_DIR)/$(FLINT_LIB) $(RM_F) $(FLINT_DIR)/$(FLINT_LIB_MAJOR) $(RM_F) $(FLINT_DIR)/$(FLINT_LIB_FULL) ifneq ($(FLINT_DLLLIB), 0) $(RM_F) $(FLINT_DIR)/$(FLINT_IMPLIB) endif $(RM_F) $(FLINT_DIR)/$(FLINT_LIB_STATIC) $(RM_RF) $(BUILD_DIR) distclean: clean $(RM_F) $(CFG_FILES) ################################################################################ # install and uninstall ################################################################################ install: library | $(INSTALL_DIRS) $(CP) flint.pc $(DESTDIR)$(PKGCONFIGDIR)/flint.pc ifneq ($(SHARED), 0) ifneq ($(FLINT_DLLLIB),0) $(CP_A) $(FLINT_DIR)/$(FLINT_LIB) $(DESTDIR)$(BINDIR) $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_MAJOR) $(DESTDIR)$(BINDIR) $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_FULL) $(DESTDIR)$(BINDIR) $(CP) $(FLINT_DIR)/$(FLINT_IMPLIB) $(DESTDIR)$(LIBDIR) else $(CP_A) $(FLINT_DIR)/$(FLINT_LIB) $(DESTDIR)$(LIBDIR) $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_MAJOR) $(DESTDIR)$(LIBDIR) $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_FULL) $(DESTDIR)$(LIBDIR) endif ifneq ($(FLINT_DYLIB),0) install_name_tool -id $(LIBDIR)/$(FLINT_LIB_FULL) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB) endif endif ifneq ($(STATIC), 0) $(CP) $(FLINT_DIR)/$(FLINT_LIB_STATIC) $(DESTDIR)$(LIBDIR) endif $(CP) $(HEADERS) $(DESTDIR)$(INCLUDEDIR)/flint @echo "" @echo '############################################################' @echo '# NOTE: #' @echo '# #' @echo '# Before installing FLINT, ensure its reliability and #' @echo '# functionality by running the command `make check'"'"'. #' @echo '# #' @echo '# This will initiate a series of tests that validates the #' @echo '# execution of FLINT. This verification is a crucial step #' @echo '# in guaranteeing a stable and error-free execution of #' @echo '# your software. #' @echo '# #' @echo '############################################################' uninstall: $(RM_F) $(DESTDIR)$(PKGCONFIGDIR)/flint.pc ifneq ($(FLINT_DLLLIB),0) $(RM_F) $(DESTDIR)$(BINDIR)/$(FLINT_LIB) $(RM_F) $(DESTDIR)$(BINDIR)/$(FLINT_LIB_MAJOR) $(RM_F) $(DESTDIR)$(BINDIR)/$(FLINT_LIB_FULL) $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_IMPLIB) else $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB) $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB_MAJOR) $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB_FULL) endif $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB_STATIC) $(RM_RF) $(DESTDIR)$(INCLUDEDIR)/flint ################################################################################ # regenerate part of the build system of needed ################################################################################ ifneq ($(MAINTAINER_MODE),no) # disable this for releases? ifneq ($(shell command -v autoconf 2> /dev/null),) configure: configure.ac @echo "Running autoconf" @autoconf else configure: configure.ac $(warning autoconf not available, proceeding with stale configure) endif endif config.status: configure ./config.status --recheck Makefile: Makefile.in config.status ./config.status $@ flint.pc: flint.pc.in config.status ./config.status $@ src/flint.h: src/flint.h.in config.status ./config.status $@ libtool: config.status ./config.status $@ src/fft_tuning.h: @FFT_TUNING_IN@ config.status ./config.status $@ src/fmpz/fmpz.c: @FMPZ_C_IN@ config.status ./config.status $@ src/gmpcompat.h: src/@GMPCOMPAT_H_IN@ config.status ./config.status $@ ################################################################################ # maintainer stuff ################################################################################ dist: dev/make_dist.sh $(FLINT_VERSION) ################################################################################ # debugging ################################################################################ print-%: @echo "$*=$($*)" .PHONY: all library shared static examples checkexamples profile tests check tune valgrind clean distclean install uninstall dist %_TEST_RUN %_VALGRIND_RUN print-% coverage coverage_html .SILENT: $(mpn_extras_S_SOURCES) flint-3.1.3/README.md000066400000000000000000000053561461254215100141230ustar00rootroot00000000000000[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://flintlib.org/doc/#) [![CI](https://github.com/flintlib/flint/actions/workflows/CI.yml/badge.svg)](https://github.com/flintlib/flint/actions/workflows/CI.yml) [![codecov](https://codecov.io/gh/flintlib/flint/graph/badge.svg?token=qKHycWTpUP)](https://codecov.io/gh/flintlib/flint) # FLINT (Fast Library for Number Theory) Website: https://flintlib.org Mailing list: https://groups.google.com/g/flint-devel ## Overview FLINT is a C library in support of computations in number theory. It's also a research project into algorithms in number theory. FLINT consists mainly of fast scalar and polynomial arithmetic, factorization and linear algebra over many basic rings (integers, rationals, reals, finite fields, number fields, p-adics). It includes some higher-level functionality for algebraic and analytic number theory. FLINT 2, released in 2011 was a complete rewrite of FLINT 1.x from scratch. FLINT 3, released in 2023, incorporates the [Arb](https://arblib.org/), [Antic](https://github.com/flintlib/antic), [Calcium](https://fredrikj.net/calcium/) and [Generic-Rings](https://github.com/fredrik-johansson/generic-rings) libraries, formerly developed separately. ## Documentation For FLINT's online documentation, see https://flintlib.org/doc/. ## Building from source This example assumes that [GMP](https://gmplib.org/), [MPFR](https://www.mpfr.org/) and the [GNU build system](https://www.gnu.org/software/automake/manual/html_node/GNU-Build-System.html) are already installed. See FLINT's documentation for further instructions on how to build FLINT. git clone https://github.com/flintlib/flint.git && cd flint ./bootstrap.sh ./configure --disable-static # ./configure --help for more options make make check # optional make install # optional make examples # optional cd doc && make html && cd .. # optional: documentation ## Authors FLINT was started in 2007 by [David Harvey](https://web.maths.unsw.edu.au/~davidharvey/) and [William Hart](https://www.dpmms.cam.ac.uk/person/wh369). Maintenance was later taken over solely by William Hart who remained in charge of the project until 2022. A large number of authors have contributed to FLINT over the years; for a complete list, see https://flintlib.org/authors.html or the `AUTHORS` file. The current maintainers are: * [Fredrik Johansson](https://fredrikj.net/) (fredrik.johansson@gmail.com) (project leader since 2022) * [Albin Ahlbäck](https://albinahlback.gitlab.io/) (albin.ahlback@gmail.com) ## License FLINT is distributed under LGPL (GNU Lesser General Public License) version 3 or later. See the `COPYING.LESSER` and `COPYING` files. flint-3.1.3/VERSION000066400000000000000000000000051461254215100136760ustar00rootroot000000000000003.1.0flint-3.1.3/acinclude.m4000066400000000000000000001233611461254215100150320ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # Copyright (c) 2023 Albin Ahlbäck # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 6 # This code is modified to print CC instead of *language* compiler AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether $CC accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS # Test for CXX compiler AC_DEFUN([AX_CXX_CHECK_COMPILE_FLAG], [AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether $CXX accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CXX_CHECK_COMPILE_FLAGS dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl NOTE: The first two patterns are taken from GMP. The license is down below. define(X86_PATTERN, [[i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | athlon-*-* | viac3*-*-* | geode*-*-* | atom-*-*]]) define(X86_64_PATTERN, [[athlon64-*-* | k8-*-* | k10-*-* | bobcat-*-* | jaguar*-*-* | bulldozer*-*-* | piledriver*-*-* | steamroller*-*-* | excavator*-*-* | zen*-*-* | pentium4-*-* | atom-*-* | silvermont-*-* | goldmont-*-* | tremont-*-* | core2-*-* | corei*-*-* | x86_64-*-* | nano-*-* | nehalem*-*-* | westmere*-*-* | sandybridge*-*-* | ivybridge*-*-* | haswell*-*-* | broadwell*-*-* | skylake*-*-* | kabylake*-*-* | icelake*-*-* | tigerlake*-*-* | rocketlake*-*-* | alderlake*-*-* | raptorlake*-*-*]]) define(ARM64_PATTERN, [[aarch64-*-*]]) define(SLOW_VROUNDPD_PATTERN, [[haswell* | broadwell* | skylake* | kabylake* | icelake* | tigerlake* | rocketlake* | alderlake* | raptorlake*]]) define(FAST_VROUNDPD_PATTERN, [[znver[2-4]* | sandybridge* | ivybridge*]]) dnl FLINT_PREPROC_IFELSE(input,[action-if-true],[action-if-false]) dnl ----------------------- dnl Runs preprocessor with CFLAGS. dnl dnl FIXME: Autoconf states that some compilers do not accept CFLAGS in the dnl preprocessor. Which ones is it? GCC and Clang certainly does. If it does dnl not allow CFLAGS into preprocessor, we should just compile normally. AC_DEFUN([FLINT_PREPROC_IFELSE], [AC_REQUIRE([AC_PROG_CPP]) save_ac_cpp="$ac_cpp" ac_cpp="$CPP $CFLAGS $CPPFLAGS" AC_PREPROC_IFELSE($@) ac_cpp="$ac_cpp" ]) dnl FLINT_ARCH dnl ----------------------- dnl Checks compiler for architectures. dnl dnl NOTE: This has to be called after all CFLAGS has been gathered. dnl dnl FIXME: Currently only Clang and GCC. Support more compilers? AC_DEFUN([FLINT_ARCH], [AC_CACHE_CHECK([for host architecture], flint_cv_arch, [flint_cv_arch="unknown" is_gnu="no" AC_PREPROC_IFELSE([AC_LANG_SOURCE([ #ifndef __GNUC__ # error error #endif ])], [is_gnu="yes"]) dnl We only know how to proceed with GCC or Clang AS_VAR_IF([is_gnu],"yes",[ is_clang="no" AC_PREPROC_IFELSE([AC_LANG_SOURCE([ #ifndef __clang__ # error error #endif ])], [is_clang="yes"]) AS_VAR_IF([is_clang],"yes",[ flint_cv_arch=[`echo | $CC -v $CFLAGS -E - 2>&1 | grep "cc1" | sed -n 's/.*-target-cpu \([^ ]*\).*/\1/p'`] ],[ flint_cv_arch=[`echo | $CC -v $CFLAGS -E - 2>&1 | grep "cc1" | sed -n 's/.*-march=\([^ ]*\).*/\1/p'`] ]) ]) ]) ]) dnl FLINT_CHECK_GMP_H(MAJOR, MINOR, PATCHLEVEL) dnl ----------------------- dnl Checks that gmp.h can be found and that its version fullfills the version dnl requirement. AC_DEFUN([FLINT_CHECK_GMP_H], [AC_CHECK_HEADER([gmp.h],,AC_MSG_ERROR([Could not find gmp.h])) AC_MSG_CHECKING([if version of GMP is greater than $1.$2.$3]) AC_PREPROC_IFELSE([AC_LANG_PROGRAM( [#include ],[#if (__GNU_MP_VERSION < $1) \ || (__GNU_MP_VERSION == $1 && __GNU_MP_VERSION_MINOR < $2) \ || (__GNU_MP_VERSION == $1 && __GNU_MP_VERSION_MINOR == $2 && __GNU_MP_VERSION_PATCHLEVEL < $3) # error GMP version $1.$2.$3 or later is required #endif ] )], AC_MSG_RESULT([yes]), AC_MSG_RESULT([no]) AC_MSG_ERROR([GMP version $1.$2.$3 or later is required.]) ) ]) dnl FLINT_CHECK_MPFR_H(MAJOR, MINOR, PATCHLEVEL) dnl ----------------------- dnl Checks that mpfr.h can be found and that its version fullfills the version dnl requirement. AC_DEFUN([FLINT_CHECK_MPFR_H], [AC_REQUIRE([FLINT_CHECK_GMP_H]) AC_CHECK_HEADER([mpfr.h],,AC_MSG_ERROR([Could not find mpfr.h])) AC_MSG_CHECKING([if version of MPFR is greater than $1.$2.$3]) AC_PREPROC_IFELSE([AC_LANG_PROGRAM( [#include ],[#if (MPFR_VERSION_MAJOR < $1) \ || (MPFR_VERSION_MAJOR == $1 && MPFR_VERSION_MINOR < $2) \ || (MPFR_VERSION_MAJOR == $1 && MPFR_VERSION_MINOR == $2 && MPFR_VERSION_PATCHLEVEL < $3) # error MPFR version $1.$2.$3 or later is required #endif ] )], AC_MSG_RESULT([yes]), AC_MSG_RESULT([no]) AC_MSG_ERROR([MPFR version $1.$2.$3 or later is required.]) ) ]) dnl FLINT_GMP_LONG_LONG_LIMB([action-success][,action-fail]) dnl ----------------------- dnl Check if GMP uses long long limb. AC_DEFUN([FLINT_GMP_LONG_LONG_LIMB], [AC_REQUIRE([FLINT_CHECK_GMP_H]) AC_CACHE_CHECK([if GMP defines mp_limb_t as unsigned long long int], flint_cv_gmp_long_long_limb, [AC_PREPROC_IFELSE([AC_LANG_PROGRAM( [ #include ],[ #if !defined(_LONG_LONG_LIMB) # error mp_limb_t != unsigned long long int #endif ] )], flint_cv_gmp_long_long_limb="yes", flint_cv_gmp_long_long_limb="no" )]) AS_VAR_IF([flint_cv_gmp_long_long_limb],"yes", [m4_default([$1], :)], [m4_default([$2], :)]) ]) dnl FLINT_ABI dnl ----------------------- dnl Checks what ABI to use. First checks if ABI is given. If none where given, dnl check GMP's configuration. AC_DEFUN([FLINT_ABI], [AC_REQUIRE([FLINT_CHECK_GMP_H]) AC_ARG_VAR(ABI, [Desired ABI]) AC_CACHE_CHECK([for desired ABI], flint_cv_abi, [if test -n "$ABI"; then flint_cv_abi="$ABI" else AC_PREPROC_IFELSE([AC_LANG_PROGRAM( [ #include ],[ #if GMP_LIMB_BITS == 32 #error Dead man error #endif ] )], flint_cv_abi="64", flint_cv_abi="32" ) fi ]) ]) dnl FLINT_SYSTEM_V_ABI([action-success][,action-fail]) dnl ----------------------- dnl Checks if System V ABI. dnl Do "action-success" if this succeeds, "action-fail" if not. AC_DEFUN([FLINT_SYSTEM_V_ABI], [AC_CACHE_CHECK([if system uses System V ABI], flint_cv_system_v_abi, AC_PREPROC_IFELSE([AC_LANG_PROGRAM([],[ #if !(defined(__APPLE__) || defined(__unix__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)) || defined(__CYGWIN__) #error Dead man error #endif ])], [flint_cv_system_v_abi="yes"], [flint_cv_system_v_abi="no"] )) AS_VAR_IF([flint_cv_system_v_abi],"yes", [m4_default([$1], :)], [m4_default([$2], :)]) ]) dnl FLINT_CHECK_ADX([action-success][,action-fail]) dnl ----------------------- dnl Checks if CPU supports the ADX instruction set. Will only run if CPU is dnl x86_64. Do "action-success" if this succeeds, "action-fail" if not. AC_DEFUN([FLINT_CHECK_ADX], [AS_VAR_IF([host_cpu],"x86_64", [AC_CACHE_CHECK([if ADX instruction set is supported by CPU], flint_cv_check_adx, FLINT_PREPROC_IFELSE([AC_LANG_SOURCE([ #if !defined(__ADX__) #error Dead man error #endif ])], flint_cv_check_adx="yes", flint_cv_check_adx="no") )]) AS_VAR_IF(flint_cv_check_adx,yes, [m4_default([$1], :)], [m4_default([$2], :)]) ]) dnl FLINT_HAVE_ASM([action-success][,action-fail]) dnl ----------------------- dnl Checks if system use FLINT's assembly. dnl Do "action-success" if this succeeds, "action-fail" if not. AC_DEFUN([FLINT_HAVE_ASM], [AC_REQUIRE([FLINT_ABI]) AC_REQUIRE([FLINT_SYSTEM_V_ABI]) AC_REQUIRE([FLINT_CHECK_ADX]) AC_CACHE_CHECK([if system can use FLINT's assembly], flint_cv_have_asm, [flint_cv_have_asm="no" if test "$flint_cv_abi" = "64" && test "$flint_cv_system_v_abi" = "yes"; then if test "$flint_cv_check_adx" = "yes"; then flint_cv_have_asm="yes" fi fi]) AS_VAR_IF([flint_cv_have_asm],"yes", [m4_default([$1], :)], [m4_default([$2], :)]) ]) dnl FLINT_HAVE_FFT_SMALL_ARM_H dnl ----------------------- dnl Checks if system have headers for fft_small on Arm. Will only run if on dnl arm64. AC_DEFUN([FLINT_HAVE_FFT_SMALL_ARM_H], [AS_VAR_IF([host_cpu],"aarch64", [AC_CHECK_HEADER([arm_neon.h],flint_cv_have_fft_small_arm_h="yes")] )]) dnl FLINT_HAVE_FFT_SMALL_ARM_I dnl ----------------------- dnl Checks if system supports Arm NEON instructions. AC_DEFUN([FLINT_HAVE_FFT_SMALL_ARM_I], [AS_VAR_IF([host_cpu],"aarch64", [AC_CACHE_CHECK([if system have required Arm instruction set for fft_small], flint_cv_have_fft_small_arm_i, FLINT_PREPROC_IFELSE([AC_LANG_SOURCE([ #ifndef __ARM_NEON #error Dead man error #endif ])], flint_cv_have_fft_small_arm_i="yes", flint_cv_have_fft_small_arm_i="no") )] )]) dnl FLINT_HAVE_FFT_SMALL_X86_H dnl ----------------------- dnl Checks if system have headers for fft_small on x86. AC_DEFUN([FLINT_HAVE_FFT_SMALL_X86_H], [AS_VAR_IF([host_cpu],"x86_64", [AC_CHECK_HEADERS([immintrin.h], flint_cv_have_fft_small_x86_h="yes", flint_cv_have_fft_small_x86_h="no")] )]) dnl FLINT_HAVE_FFT_SMALL_X86_I dnl ----------------------- dnl Checks if system supports AVX2 instructions. AC_DEFUN([FLINT_HAVE_FFT_SMALL_X86_I], [AS_VAR_IF([host_cpu],"x86_64", [AC_CACHE_CHECK([if system have required x86_64 instruction set for fft_small], flint_cv_have_fft_small_x86_i, FLINT_PREPROC_IFELSE([AC_LANG_SOURCE([ #if !defined(__AVX2__) #error Dead man error #endif ])], flint_cv_have_fft_small_x86_i="yes", flint_cv_have_fft_small_x86_i="no") )] )]) dnl FLINT_CHECK_FFT_SMALL([action-success][,action-fail]) dnl ----------------------- dnl Checks if fft_small module is available. dnl Do "action-success" if this succeeds, "action-fail" if not. AC_DEFUN([FLINT_CHECK_FFT_SMALL], [AC_REQUIRE([FLINT_ABI]) AC_REQUIRE([FLINT_HAVE_FFT_SMALL_ARM_H]) AC_REQUIRE([FLINT_HAVE_FFT_SMALL_ARM_I]) AC_REQUIRE([FLINT_HAVE_FFT_SMALL_X86_H]) AC_REQUIRE([FLINT_HAVE_FFT_SMALL_X86_I]) AC_CACHE_CHECK([if system can use FLINT's fft_small module], flint_cv_check_fft_small, [flint_cv_check_fft_small="no" if test "$flint_cv_abi" = "64"; then if test "$flint_cv_have_fft_small_arm_h" = "yes" && test "$flint_cv_have_fft_small_arm_i" = "yes"; then flint_cv_check_fft_small="yes" fi if test "$flint_cv_have_fft_small_x86_h" = "yes" && test "$flint_cv_have_fft_small_x86_i" = "yes"; then flint_cv_check_fft_small="yes" fi fi ]) AS_VAR_IF([flint_cv_check_fft_small],"yes", [m4_default([$1], :)], [m4_default([$2], :)]) ]) dnl GMP specific autoconf macros dnl (Taken from GMP 6.3.0) dnl dnl Copyright 2000-2006, 2009, 2011, 2013-2018 Free Software Foundation, Inc. dnl dnl This file is part of the GNU MP Library. dnl dnl The GNU MP Library is free software; you can redistribute it and/or modify dnl it under the terms of either: dnl dnl * the GNU Lesser General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your dnl option) any later version. dnl dnl or dnl dnl * the GNU General Public License as published by the Free Software dnl Foundation; either version 2 of the License, or (at your option) any dnl later version. dnl dnl or both in parallel, as here. dnl dnl The GNU MP Library is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dnl for more details. dnl dnl You should have received copies of the GNU General Public License and the dnl GNU Lesser General Public License along with the GNU MP Library. If not, dnl see https://www.gnu.org/licenses/. dnl GMP_INIT([M4-DEF-FILE]) dnl ----------------------- dnl Initializations for GMP config.m4 generation. dnl dnl FIXME: The generated config.m4 doesn't get recreated by config.status. dnl Maybe the relevant "echo"s should go through AC_CONFIG_COMMANDS. dnl NOTE: This is different from GMP. AC_DEFUN([GMP_INIT], [ifelse([$1], , gmp_configm4=config.m4, gmp_configm4="[$1]") gmp_tmpconfigm4=cnfm4.tmp gmp_tmpconfigm4i=cnfm4i.tmp gmp_tmpconfigm4p=cnfm4p.tmp rm -f $gmp_tmpconfigm4 $gmp_tmpconfigm4i $gmp_tmpconfigm4p # All CPUs use asm-defs.m4 echo ["include][(\`src/mpn_extras/asm-defs.m4')"] >>$gmp_tmpconfigm4i ]) dnl GMP_FINISH dnl ---------- dnl Create config.m4 from its accumulated parts. dnl dnl __CONFIG_M4_INCLUDED__ is used so that a second or subsequent include dnl of config.m4 is harmless. dnl dnl A separate ifdef on the angle bracket quoted part ensures the quoting dnl style there is respected. The basic defines from gmp_tmpconfigm4 are dnl fully quoted but are still put under an ifdef in case any have been dnl redefined by one of the m4 include files. dnl dnl Doing a big ifdef within asm-defs.m4 and/or other macro files wouldn't dnl work, since it'd interpret parentheses and quotes in dnl comments, and dnl having a whole file as a macro argument would overflow the string space dnl on BSD m4. AC_DEFUN([GMP_FINISH], [AC_REQUIRE([GMP_INIT]) echo "creating $gmp_configm4" echo ["d""nl $gmp_configm4. Generated automatically by configure."] > $gmp_configm4 if test -f $gmp_tmpconfigm4; then echo ["changequote(<,>)"] >> $gmp_configm4 echo ["ifdef(<__CONFIG_M4_INCLUDED__>,,<"] >> $gmp_configm4 cat $gmp_tmpconfigm4 >> $gmp_configm4 echo [">)"] >> $gmp_configm4 echo ["changequote(\`,')"] >> $gmp_configm4 rm $gmp_tmpconfigm4 fi echo ["ifdef(\`__CONFIG_M4_INCLUDED__',,\`"] >> $gmp_configm4 if test -f $gmp_tmpconfigm4i; then cat $gmp_tmpconfigm4i >> $gmp_configm4 rm $gmp_tmpconfigm4i fi if test -f $gmp_tmpconfigm4p; then cat $gmp_tmpconfigm4p >> $gmp_configm4 rm $gmp_tmpconfigm4p fi echo ["')"] >> $gmp_configm4 echo ["define(\`__CONFIG_M4_INCLUDED__')"] >> $gmp_configm4 ]) dnl GMP_INCLUDE_MPN(FILE) dnl --------------------- dnl Add an include_mpn(`FILE') to config.m4. FILE should be a path dnl relative to the mpn source directory, for example dnl dnl GMP_INCLUDE_MPN(`x86/x86-defs.m4') dnl AC_DEFUN([GMP_INCLUDE_MPN], [AC_REQUIRE([GMP_INIT]) echo ["include(\`$1')"] >> $gmp_tmpconfigm4i ]) dnl GMP_PROG_M4 dnl ----------- dnl Find a working m4, either in $PATH or likely locations, and setup $M4 dnl and an AC_SUBST accordingly. If $M4 is already set then it's a user dnl choice and is accepted with no checks. GMP_PROG_M4 is like dnl AC_PATH_PROG or AC_CHECK_PROG, but tests each m4 found to see if it's dnl good enough. dnl dnl See mpn/asm-defs.m4 for details on the known bad m4s. AC_DEFUN([GMP_PROG_M4], [AC_ARG_VAR(M4,[m4 macro processor]) AC_CACHE_CHECK([for suitable m4], gmp_cv_prog_m4, [if test -n "$M4"; then gmp_cv_prog_m4="$M4" else cat >conftest.m4 <<\EOF dnl Must protect this against being expanded during autoconf m4! dnl Dont put "dnl"s in this as autoconf will flag an error for unexpanded dnl macros. [define(dollarhash,``$][#'')ifelse(dollarhash(x),1,`define(t1,Y)', ``bad: $][# not supported (SunOS /usr/bin/m4) '')ifelse(eval(89),89,`define(t2,Y)', `bad: eval() doesnt support 8 or 9 in a constant (OpenBSD 2.6 m4) ')ifelse(eval(9,9),10,`define(t3,Y)', `bad: eval() doesnt support radix in eval (FreeBSD 8.x,9.0,9.1,9.2 m4) ')ifelse(t1`'t2`'t3,YYY,`good ')] EOF dnl ' <- balance the quotes for emacs sh-mode echo "trying m4" >&AS_MESSAGE_LOG_FD gmp_tmp_val=`(m4 conftest.m4) 2>&AS_MESSAGE_LOG_FD` echo "$gmp_tmp_val" >&AS_MESSAGE_LOG_FD if test "$gmp_tmp_val" = good; then gmp_cv_prog_m4="m4" else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="$PATH:/usr/5bin" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. echo "trying $ac_dir/m4" >&AS_MESSAGE_LOG_FD gmp_tmp_val=`($ac_dir/m4 conftest.m4) 2>&AS_MESSAGE_LOG_FD` echo "$gmp_tmp_val" >&AS_MESSAGE_LOG_FD if test "$gmp_tmp_val" = good; then gmp_cv_prog_m4="$ac_dir/m4" break fi done IFS="$ac_save_ifs" if test -z "$gmp_cv_prog_m4"; then AC_MSG_ERROR([No usable m4 in \$PATH or /usr/5bin (see config.log for reasons).]) fi fi rm -f conftest.m4 fi]) M4="$gmp_cv_prog_m4" AC_SUBST(M4) ]) dnl GMP_PATH_NM dnl ----------- dnl GMP additions to libtool LT_PATH_NM. dnl dnl Note that if LT_PATH_NM can't find a working nm it still leaves dnl $NM set to "nm", so $NM can't be assumed to actually work. dnl dnl A user-selected $NM is always left unchanged. LT_PATH_NM is still run dnl to get the "checking" message printed though. dnl dnl Perhaps it'd be worthwhile checking that nm works, by running it on an dnl actual object file. For instance on sparcv9 solaris old versions of dnl GNU nm don't recognise 64-bit objects. Checking would give a better dnl error message than just a failure in later tests like GMP_ASM_W32 etc. dnl dnl On the other hand it's not really normal autoconf practice to take too dnl much trouble over detecting a broken set of tools. And libtool doesn't dnl do anything at all for say ranlib or strip. So for now we're inclined dnl to just demand that the user provides a coherent environment. AC_DEFUN([GMP_PATH_NM], [ gmp_user_NM=$NM dnl Is already called in LT_INIT dnl LT_PATH_NM # FIXME: When cross compiling (ie. $ac_tool_prefix not empty), libtool # defaults to plain "nm" if a "${ac_tool_prefix}nm" is not found. In this # case run it again to try the native "nm", firstly so that likely locations # are searched, secondly so that -B or -p are added if necessary for BSD # format. This is necessary for instance on OSF with "./configure # --build=alphaev5-dec-osf --host=alphaev6-dec-osf". # if test -z "$gmp_user_NM" && test -n "$ac_tool_prefix" && test "$NM" = nm; then $as_unset lt_cv_path_NM gmp_save_ac_tool_prefix=$ac_tool_prefix ac_tool_prefix= NM= LT_PATH_NM ac_tool_prefix=$gmp_save_ac_tool_prefix fi if test -z "$gmp_user_NM"; then eval nmflags=\"\$nm${abi1}_flags\" test -n "$nmflags" || eval nmflags=\"\$nm${abi2}_flags\" if test -n "$nmflags"; then AC_MSG_CHECKING([for extra nm flags]) NM="$NM $nmflags" AC_MSG_RESULT([$nmflags]) fi fi ]) dnl GMP_DEFINE(MACRO, DEFINITION [, LOCATION]) dnl ------------------------------------------ dnl Define M4 macro MACRO as DEFINITION in temporary file. dnl dnl If LOCATION is `POST', the definition will appear after any include() dnl directives inserted by GMP_INCLUDE. Mind the quoting! No shell dnl variables will get expanded. Don't forget to invoke GMP_FINISH to dnl create file config.m4. config.m4 uses `<' and '>' as quote characters dnl for all defines. AC_DEFUN([GMP_DEFINE], [AC_REQUIRE([GMP_INIT]) echo ['define(<$1>, <$2>)'] >>ifelse([$3], [POST], $gmp_tmpconfigm4p, $gmp_tmpconfigm4) ]) dnl GMP_DEFINE_RAW(STRING [, LOCATION]) dnl ------------------------------------ dnl Put STRING into config.m4 file. dnl dnl If LOCATION is `POST', the definition will appear after any include() dnl directives inserted by GMP_INCLUDE. Don't forget to invoke GMP_FINISH dnl to create file config.m4. AC_DEFUN([GMP_DEFINE_RAW], [AC_REQUIRE([GMP_INIT]) echo [$1] >> ifelse([$2], [POST], $gmp_tmpconfigm4p, $gmp_tmpconfigm4) ]) dnl GMP_TRY_ASSEMBLE(asm-code,[action-success][,action-fail]) dnl ---------------------------------------------------------- dnl Attempt to assemble the given code. dnl Do "action-success" if this succeeds, "action-fail" if not. dnl dnl conftest.o and conftest.out are available for inspection in dnl "action-success". If either action does a "break" out of a loop then dnl an explicit "rm -f conftest*" will be necessary. dnl dnl This is not unlike AC_TRY_COMPILE, but there's no default includes or dnl anything in "asm-code", everything wanted must be given explicitly. AC_DEFUN([GMP_TRY_ASSEMBLE], [cat >conftest.s <&AS_MESSAGE_LOG_FD ifelse([$2],,:,[$2]) else cat conftest.out >&AS_MESSAGE_LOG_FD echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.s >&AS_MESSAGE_LOG_FD ifelse([$3],,:,[$3]) fi rm -f conftest* ]) dnl GMP_ASM_LABEL_SUFFIX dnl -------------------- dnl : - is usual. dnl empty - hppa on HP-UX doesn't use a :, just the label name dnl dnl Note that it's necessary to test the empty case first, since HP "as" dnl will accept "somelabel:", and take it to mean a label with a name that dnl happens to end in a colon. AC_DEFUN([GMP_ASM_LABEL_SUFFIX], [AC_REQUIRE([GMP_ASM_TEXT]) AC_CACHE_CHECK([for assembler label suffix], gmp_cv_asm_label_suffix, [gmp_cv_asm_label_suffix=unknown for i in "" ":"; do echo "trying $i" >&AS_MESSAGE_LOG_FD GMP_TRY_ASSEMBLE( [ $gmp_cv_asm_text somelabel$i], [gmp_cv_asm_label_suffix=$i rm -f conftest* break], [cat conftest.out >&AS_MESSAGE_LOG_FD]) done if test "$gmp_cv_asm_label_suffix" = "unknown"; then AC_MSG_ERROR([Cannot determine label suffix]) fi ]) echo ["define(, <$gmp_cv_asm_label_suffix>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_UNDERSCORE dnl ------------------ dnl Determine whether global symbols need to be prefixed with an underscore. dnl The output from "nm" is grepped to see what a typical symbol looks like. dnl dnl This test used to grep the .o file directly, but that failed with greps dnl that don't like binary files (eg. SunOS 4). dnl dnl This test also used to construct an assembler file with and without an dnl underscore and try to link that to a C file, to see which worked. dnl Although that's what will happen in the real build we don't really want dnl to depend on creating asm files within configure for every possible CPU dnl (or at least we don't want to do that more than we have to). dnl dnl The fallback on no underscore is based on the assumption that the world dnl is moving towards non-underscore systems. There should actually be no dnl good reason for nm to fail though. AC_DEFUN([GMP_ASM_UNDERSCORE], [AC_REQUIRE([GMP_PATH_NM]) AC_CACHE_CHECK([if globals are prefixed by underscore], gmp_cv_asm_underscore, [gmp_cv_asm_underscore="unknown" cat >conftest.c <conftest.out if grep "[[ ]]_gurkmacka" conftest.out >/dev/null; then gmp_cv_asm_underscore=yes elif grep "[[ ]]gurkmacka" conftest.out >/dev/null; then gmp_cv_asm_underscore=no else echo "configure: $NM doesn't have gurkmacka:" >&AS_MESSAGE_LOG_FD cat conftest.out >&AS_MESSAGE_LOG_FD fi else echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.c >&AS_MESSAGE_LOG_FD fi rm -f conftest* ]) case $gmp_cv_asm_underscore in yes) GMP_DEFINE(GSYM_PREFIX, [_]) ;; no) GMP_DEFINE(GSYM_PREFIX, []) ;; *) AC_MSG_WARN([+----------------------------------------------------------]) AC_MSG_WARN([| Cannot determine global symbol prefix.]) AC_MSG_WARN([| $NM output doesn't contain a global data symbol.]) AC_MSG_WARN([| Will proceed with no underscore.]) AC_MSG_WARN([| If this is wrong then you'll get link errors referring]) AC_MSG_WARN([| to ___gmpn_add_n (note three underscores).]) AC_MSG_WARN([| In this case do a fresh build with an override,]) AC_MSG_WARN([| ./configure gmp_cv_asm_underscore=yes]) AC_MSG_WARN([+----------------------------------------------------------]) GMP_DEFINE(GSYM_PREFIX, []) ;; esac ]) dnl GMP_ASM_ALIGN_LOG dnl ----------------- dnl Is parameter to `.align' logarithmic? AC_DEFUN([GMP_ASM_ALIGN_LOG], [AC_REQUIRE([GMP_ASM_GLOBL]) AC_REQUIRE([GMP_ASM_BYTE]) AC_REQUIRE([GMP_ASM_DATA]) AC_REQUIRE([GMP_ASM_LABEL_SUFFIX]) AC_REQUIRE([GMP_PATH_NM]) AC_CACHE_CHECK([if .align assembly directive is logarithmic], gmp_cv_asm_align_log, [GMP_TRY_ASSEMBLE( [ $gmp_cv_asm_data .align 4 $gmp_cv_asm_globl foo $gmp_cv_asm_byte 1 .align 4 foo$gmp_cv_asm_label_suffix $gmp_cv_asm_byte 2], [gmp_tmp_val=[`$NM conftest.$OBJEXT | grep foo | \ sed -e 's;[[][0-9][]]\(.*\);\1;' -e 's;[^1-9]*\([0-9]*\).*;\1;'`] if test "$gmp_tmp_val" = "10" || test "$gmp_tmp_val" = "16"; then gmp_cv_asm_align_log=yes else gmp_cv_asm_align_log=no fi], [AC_MSG_ERROR([cannot assemble alignment test])])]) GMP_DEFINE_RAW(["define(,<$gmp_cv_asm_align_log>)"]) ]) dnl GMP_ASM_ALIGN_FILL_0x90 dnl ----------------------- dnl Determine whether a ",0x90" suffix works on a .align directive. dnl This is only meant for use on x86, 0x90 being a "nop". dnl dnl Old gas, eg. 1.92.3 dnl Needs ",0x90" or else the fill is 0x00, which can't be executed dnl across. dnl dnl New gas, eg. 2.91 dnl Generates multi-byte nop fills even when ",0x90" is given. dnl dnl Solaris 2.6 as dnl ",0x90" is not allowed, causes a fatal error. dnl dnl Solaris 2.8 as dnl ",0x90" does nothing, generates a warning that it's being ignored. dnl dnl SCO OpenServer 5 as dnl Second parameter is max bytes to fill, not a fill pattern. dnl ",0x90" is an error due to being bigger than the first parameter. dnl Multi-byte nop fills are generated in text segments. dnl dnl Note that both solaris "as"s only care about ",0x90" if they actually dnl have to use it to fill something, hence the .byte in the test. It's dnl the second .align which provokes the error or warning. dnl dnl The warning from solaris 2.8 is suppressed to stop anyone worrying that dnl something might be wrong. AC_DEFUN([GMP_ASM_ALIGN_FILL_0x90], [AC_REQUIRE([GMP_ASM_TEXT]) AC_CACHE_CHECK([if the .align directive accepts an 0x90 fill in .text], gmp_cv_asm_align_fill_0x90, [GMP_TRY_ASSEMBLE( [ $gmp_cv_asm_text .align 4, 0x90 .byte 0 .align 4, 0x90], [if grep "Warning: Fill parameter ignored for executable section" conftest.out >/dev/null; then echo "Suppressing this warning by omitting 0x90" 1>&AS_MESSAGE_LOG_FD gmp_cv_asm_align_fill_0x90=no else gmp_cv_asm_align_fill_0x90=yes fi], [gmp_cv_asm_align_fill_0x90=no])]) GMP_DEFINE_RAW(["define(,<$gmp_cv_asm_align_fill_0x90>)"]) ]) dnl GMP_ASM_BYTE dnl ------------ dnl .byte - is usual. dnl data1 - required by ia64 (on hpux at least). dnl dnl This macro is just to support other configure tests, not any actual asm dnl code. AC_DEFUN([GMP_ASM_BYTE], [AC_REQUIRE([GMP_ASM_TEXT]) AC_REQUIRE([GMP_ASM_LABEL_SUFFIX]) AC_CACHE_CHECK([for assembler byte directive], gmp_cv_asm_byte, [for i in .byte data1; do echo "trying $i" >&AS_MESSAGE_LOG_FD GMP_TRY_ASSEMBLE( [ $gmp_cv_asm_data $i 0 ], [gmp_cv_asm_byte=$i rm -f conftest* break], [cat conftest.out >&AS_MESSAGE_LOG_FD]) done if test -z "$gmp_cv_asm_byte"; then AC_MSG_ERROR([Cannot determine how to emit a data byte]) fi ]) ]) dnl GMP_ASM_TEXT dnl ------------ dnl .text - is usual. dnl .code - is needed by the hppa on HP-UX (but ia64 HP-UX uses .text) dnl .csect .text[PR] - is for AIX. AC_DEFUN([GMP_ASM_TEXT], [AC_CACHE_CHECK([how to switch to text section], gmp_cv_asm_text, [for i in ".text" ".code" [".csect .text[PR]"]; do echo "trying $i" >&AS_MESSAGE_LOG_FD GMP_TRY_ASSEMBLE([ $i], [gmp_cv_asm_text=$i rm -f conftest* break]) done if test -z "$gmp_cv_asm_text"; then AC_MSG_ERROR([Cannot determine text section directive]) fi ]) echo ["define(, <$gmp_cv_asm_text>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_DATA dnl ------------ dnl Can we say `.data'? AC_DEFUN([GMP_ASM_DATA], [AC_CACHE_CHECK([how to switch to data section], gmp_cv_asm_data, [case $host in *-*-aix*) gmp_cv_asm_data=[".csect .data[RW]"] ;; *) gmp_cv_asm_data=".data" ;; esac ]) echo ["define(, <$gmp_cv_asm_data>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_RODATA dnl -------------- dnl Find out how to switch to the read-only data section. dnl dnl The compiler output is grepped for the right directive. It's not dnl considered wise to just probe for ".section .rodata" or whatever works, dnl since arbitrary section names might be accepted, but not necessarily do dnl the right thing when they get to the linker. dnl dnl Only a few asm files use RODATA, so this code is perhaps a bit dnl excessive right now, but should find more uses in the future. dnl dnl FIXME: gcc on aix generates something like ".csect _foo.ro_c[RO],3" dnl where foo is the object file. Might need to check for that if we use dnl RODATA there. AC_DEFUN([GMP_ASM_RODATA], [AC_REQUIRE([GMP_ASM_TEXT]) AC_REQUIRE([GMP_ASM_DATA]) AC_REQUIRE([GMP_ASM_LABEL_SUFFIX]) AC_REQUIRE([GMP_ASM_UNDERSCORE]) AC_CACHE_CHECK([how to switch to read-only data section], gmp_cv_asm_rodata, [ dnl Default to DATA on CPUs with split code/data caching, and TEXT dnl elsewhere. i386 means generic x86, so use DATA on it. case $host in X86_64_PATTERN) gmp_cv_asm_rodata="$gmp_cv_asm_data" ;; *) gmp_cv_asm_rodata="$gmp_cv_asm_text" ;; esac cat >conftest.c <&AS_MESSAGE_LOG_FD cat conftest.c >&AS_MESSAGE_LOG_FD gmp_compile="$CC $CFLAGS $CPPFLAGS -S conftest.c >&AS_MESSAGE_LOG_FD" if AC_TRY_EVAL(gmp_compile); then echo "Compiler output:" >&AS_MESSAGE_LOG_FD cat conftest.s >&AS_MESSAGE_LOG_FD if test $gmp_cv_asm_underscore = yes; then tmp_gsym_prefix=_ else tmp_gsym_prefix= fi # must see our label if grep "^${tmp_gsym_prefix}foo$gmp_cv_asm_label_suffix" conftest.s >/dev/null 2>&AS_MESSAGE_LOG_FD; then # take the last directive before our label (hence skipping segments # getting debugging info etc) tmp_match=`sed -n ["/^${tmp_gsym_prefix}foo$gmp_cv_asm_label_suffix/q /^[. ]*data/p /^[. ]*rdata/p /^[. ]*text/p /^[. ]*section/p /^[. ]*csect/p /^[. ]*CSECT/p"] conftest.s | sed -n '$p'` echo "Match: $tmp_match" >&AS_MESSAGE_LOG_FD if test -n "$tmp_match"; then gmp_cv_asm_rodata=$tmp_match fi else echo "Couldn't find label: ^${tmp_gsym_prefix}foo$gmp_cv_asm_label_suffix" >&AS_MESSAGE_LOG_FD fi fi rm -f conftest* ]) echo ["define(, <$gmp_cv_asm_rodata>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_GLOBL dnl ------------- dnl The assembler directive to mark a label as a global symbol. dnl dnl ia64 - .global is standard, according to the Intel documentation. dnl dnl hppa - ".export foo,entry" is demanded by HP hppa "as". ".global" is a dnl kind of import. dnl dnl other - .globl is usual. dnl dnl "gas" tends to accept .globl everywhere, in addition to .export or dnl .global or whatever the system assembler demands. AC_DEFUN([GMP_ASM_GLOBL], [AC_REQUIRE([GMP_ASM_TEXT]) AC_CACHE_CHECK([for assembler global directive], gmp_cv_asm_globl, [case $host in dnl We do not support HPPA or IA64 assembly dnl hppa*-*-*) gmp_cv_asm_globl=.export ;; dnl IA64_PATTERN) gmp_cv_asm_globl=.global ;; *) gmp_cv_asm_globl=.globl ;; esac ]) echo ["define(, <$gmp_cv_asm_globl>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_GLOBL_ATTR dnl ------------------ dnl Do we need something after `GLOBL symbol'? AC_DEFUN([GMP_ASM_GLOBL_ATTR], [AC_REQUIRE([GMP_ASM_GLOBL]) AC_CACHE_CHECK([for assembler global directive attribute], gmp_cv_asm_globl_attr, [case $gmp_cv_asm_globl in .export) gmp_cv_asm_globl_attr=",entry" ;; *) gmp_cv_asm_globl_attr="" ;; esac ]) echo ["define(, <$gmp_cv_asm_globl_attr>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_TYPE dnl ------------ dnl Can we say ".type", and how? dnl dnl For i386 GNU/Linux ELF systems, and very likely other ELF systems, dnl .type and .size are important on functions in shared libraries. If dnl .type is omitted and the mainline program references that function then dnl the code will be copied down to the mainline at load time like a piece dnl of data. If .size is wrong or missing (it defaults to 4 bytes or some dnl such) then incorrect bytes will be copied and a segv is the most likely dnl result. In any case such copying is not what's wanted, a .type dnl directive will ensure a PLT entry is used. dnl dnl In GMP the assembler functions are normally only used from within the dnl library (since most programs are not interested in the low level dnl routines), and in those circumstances a missing .type isn't fatal, dnl letting the problem go unnoticed. tests/mpn/t-asmtype.c aims to check dnl for it. AC_DEFUN([GMP_ASM_TYPE], [AC_CACHE_CHECK([for assembler .type directive], gmp_cv_asm_type, [gmp_cv_asm_type= for gmp_tmp_prefix in @ \# %; do GMP_TRY_ASSEMBLE([ .type sym,${gmp_tmp_prefix}function], [if grep "\.type pseudo-op used outside of \.def/\.endef ignored" conftest.out >/dev/null; then : ; else gmp_cv_asm_type=".type \$][1,${gmp_tmp_prefix}\$][2" break fi]) done rm -f conftest* ]) echo ["define(, <$gmp_cv_asm_type>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_SIZE dnl ------------ dnl Can we say `.size'? AC_DEFUN([GMP_ASM_SIZE], [AC_CACHE_CHECK([for assembler .size directive], gmp_cv_asm_size, [gmp_cv_asm_size= GMP_TRY_ASSEMBLE([ .size sym,1], [if grep "\.size pseudo-op used outside of \.def/\.endef ignored" conftest.out >/dev/null; then : ; else gmp_cv_asm_size=".size \$][1,\$][2" fi]) ]) echo ["define(, <$gmp_cv_asm_size>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_COFF_TYPE dnl ----------------- dnl Determine whether the assembler supports COFF type information. dnl dnl Currently this is only needed for mingw (and cygwin perhaps) and so is dnl run only on the x86s, but it ought to work anywhere. dnl dnl On MINGW, recent versions of the linker have an automatic import scheme dnl for data in a DLL which is referenced by a mainline but without dnl __declspec (__dllimport__) on the prototype. It seems functions dnl without type information are treated as data, or something, and calls dnl to them from the mainline will crash. gcc puts type information on the dnl C functions it generates, we need to do the same for assembler dnl functions. dnl dnl This applies only to functions without __declspec(__dllimport__), dnl ie. without __GMP_DECLSPEC in the case of libgmp, so it also works just dnl to ensure all assembler functions used from outside libgmp have dnl __GMP_DECLSPEC on their prototypes. But this isn't an ideal situation, dnl since we don't want perfectly valid calls going wrong just because dnl there wasn't a prototype in scope. dnl dnl When an auto-import takes place, the following warning is given by the dnl linker. This shouldn't be seen for any functions. dnl dnl Info: resolving _foo by linking to __imp__foo (auto-import) dnl dnl dnl COFF type directives look like the following dnl dnl .def _foo dnl .scl 2 dnl .type 32 dnl .endef dnl dnl _foo is the symbol with GSYM_PREFIX (_). .scl is the storage class, 2 dnl for external, 3 for static. .type is the object type, 32 for a dnl function. dnl dnl On an ELF system, this is (correctly) rejected due to .def, .endef and dnl .scl being invalid, and .type not having enough arguments. AC_DEFUN([GMP_ASM_COFF_TYPE], [AC_REQUIRE([GMP_ASM_TEXT]) AC_REQUIRE([GMP_ASM_GLOBL]) AC_REQUIRE([GMP_ASM_GLOBL_ATTR]) AC_REQUIRE([GMP_ASM_LABEL_SUFFIX]) AC_REQUIRE([GMP_ASM_UNDERSCORE]) AC_CACHE_CHECK([for assembler COFF type directives], gmp_cv_asm_x86_coff_type, [GMP_TRY_ASSEMBLE( [ $gmp_cv_asm_text $gmp_cv_asm_globl ${tmp_gsym_prefix}foo$gmp_cv_asm_globl_attr .def ${tmp_gsym_prefix}foo .scl 2 .type 32 .endef ${tmp_gsym_prefix}foo$gmp_cv_asm_label_suffix ], [gmp_cv_asm_x86_coff_type=yes], [gmp_cv_asm_x86_coff_type=no]) ]) echo ["define(, <$gmp_cv_asm_x86_coff_type>)"] >> $gmp_tmpconfigm4 ]) dnl GMP_ASM_LSYM_PREFIX dnl ------------------- dnl What is the prefix for a local label? dnl dnl The prefixes tested are, dnl dnl L - usual for underscore systems dnl .L - usual for non-underscore systems dnl $ - alpha (gas and OSF system assembler) dnl L$ - hppa (gas and HP-UX system assembler) dnl dnl The default is "L" if the tests fail for any reason. There's a good dnl chance this will be adequate, since on most systems labels are local dnl anyway unless given a ".globl", and an "L" will avoid clashes with dnl other identifers. dnl dnl For gas, ".L" is normally purely local to the assembler, it doesn't get dnl put into the object file at all. This style is preferred, to keep the dnl object files nice and clean. dnl dnl BSD format nm produces a line like dnl dnl 00000000 t Lgurkmacka dnl dnl The symbol code is normally "t" for text, but any lower case letter dnl indicates a local definition. dnl dnl Code "n" is for a debugging symbol, OSF "nm -B" gives that as an upper dnl case "N" for a local. dnl dnl HP-UX nm prints an error message (though seems to give a 0 exit) if dnl there's no symbols at all in an object file, hence the use of "dummy". AC_DEFUN([GMP_ASM_LSYM_PREFIX], [AC_REQUIRE([GMP_ASM_LABEL_SUFFIX]) AC_REQUIRE([GMP_ASM_TEXT]) AC_REQUIRE([GMP_PATH_NM]) AC_CACHE_CHECK([for assembler local label prefix], gmp_cv_asm_lsym_prefix, [gmp_tmp_pre_appears=yes for gmp_tmp_pre in L .L $L $ L$; do echo "Trying $gmp_tmp_pre" >&AS_MESSAGE_LOG_FD GMP_TRY_ASSEMBLE( [ $gmp_cv_asm_text dummy${gmp_cv_asm_label_suffix} ${gmp_tmp_pre}gurkmacka${gmp_cv_asm_label_suffix}], [if $NM conftest.$OBJEXT >conftest.nm 2>&AS_MESSAGE_LOG_FD; then : ; else cat conftest.nm >&AS_MESSAGE_LOG_FD AC_MSG_WARN(["$NM" failure]) break fi cat conftest.nm >&AS_MESSAGE_LOG_FD if grep gurkmacka conftest.nm >/dev/null; then : ; else # no mention of the symbol, this is good echo "$gmp_tmp_pre label doesn't appear in object file at all (good)" >&AS_MESSAGE_LOG_FD gmp_cv_asm_lsym_prefix="$gmp_tmp_pre" gmp_tmp_pre_appears=no break fi if grep [' [a-zN] .*gurkmacka'] conftest.nm >/dev/null; then # symbol mentioned as a local, use this if nothing better echo "$gmp_tmp_pre label is local but still in object file" >&AS_MESSAGE_LOG_FD if test -z "$gmp_cv_asm_lsym_prefix"; then gmp_cv_asm_lsym_prefix="$gmp_tmp_pre" fi else echo "$gmp_tmp_pre label is something unknown" >&AS_MESSAGE_LOG_FD fi ]) done rm -f conftest* if test -z "$gmp_cv_asm_lsym_prefix"; then gmp_cv_asm_lsym_prefix=L AC_MSG_WARN([cannot determine local label, using default $gmp_cv_asm_lsym_prefix]) fi # for development purposes, note whether we got a purely temporary local label echo "Local label appears in object files: $gmp_tmp_pre_appears" >&AS_MESSAGE_LOG_FD ]) echo ["define(, <${gmp_cv_asm_lsym_prefix}>)"] >> $gmp_tmpconfigm4 AC_DEFINE_UNQUOTED(LSYM_PREFIX, "$gmp_cv_asm_lsym_prefix", [Assembler local label prefix]) ]) flint-3.1.3/bootstrap.sh000077500000000000000000000012661461254215100152140ustar00rootroot00000000000000#!/bin/sh set -e rm -rf autom4te.cache autoreconf -f -i -v -Wall # The following lines are from Semigroups/Semigroups, written by Max Horn. if ! test -x config.guess -a -x config.sub ; then automake -acf 2> /dev/null || : fi # There is a second bug in autoconf 2.69 where the generated configure # script complains about install-sh not being there (even though it does # not actually need it). As a workaround, we just provide an empty file # instead. Since newer autoconf versions such as 2.71 are not affected # by the bug, we add a test to limit when this workaround is applied if fgrep -q ac_aux_dir/install-sh configure ; then touch config/install-sh fi rm -rf autom4te.cache flint-3.1.3/code_conventions.md000066400000000000000000000167421461254215100165260ustar00rootroot00000000000000# Code conventions ## Language dialect We use the C11 standard. Where applicable, we utilize the GNU C extension for inline assembly. ## Build system As FLINT have two different building systems. The first one is GNU Make along with GNU Autotools for the configuration, which is the recommended way of compiling FLINT. The second one is CMake, which mainly exists to provide a way for Windows users to compile natively (that is, without the use of MinGW or similar tools). FLINT is built up of several modules, such as `ulong_extras` and `fmpz`. Each module should go in `Makefile.in` and in `CMakeLists.txt` under `BUILD_DIRS`. Each module should have a non-empty test directory. The file names in a module should friendly to case-insensitivity, i.e. it is not a good idea to have both `fmpz/FOO.c` and `fmpz/foo.c`. ## Primitive types Depending on the main interpretation of the value of a variable, where possible the following primitive datatype should be used: | | | |:--------------------------------------:|:------------------------------:| | bit counts up to a single limb | `ulong` | | bit counts, multiprecision | `mp_bitcnt_t` | | byte counts (strings) | `size_t` | | limb counts in multiprecision integers | `mp_size_t` | | limbs (unsigned/signed) | `mp_limb_t`/`mp_limb_signed_t` | | `mp_limb_t` arrays | `mp_ptr`/`mp_srcptr` | | ui/si function constants | `ulong`/`slong` | | exponents (unsigned/signed) | `ulong`/`slong` | | polynomial lengths | `slong` | | number of indeterminates | `slong` | | row/column indices | `slong` | | precision for MPFR types | `mpfr_prec_t` | The typical definitions of these in terms of primitive types are: | | | |:-------------:|:---------------------------------------:| | `mp_bitcnt_t` | `unsigned long` or `unsigned long long` | | `mp_size_t` | `long` or `long long` | | `mp_limb_t` | `unsigned long` or `unsigned long long` | | `mp_ptr` | `mp_limb_t *` | | `mp_srcptr` | `const mp_limb_t *` | | `slong` | `long` or `long long` | | `ulong` | `unsigned long` or `unsigned long long` | ## Constant integers Because the `ulong`/`slong` types can be (unsigned) long on Linux and (unsigned) long long on Windows, we cannot use the usual 123456789UL to declare them. Instead, we provide two macros: ```c WORD(123456789) /* slong constant */ UWORD(123456789) /* ulong constant */ ``` ## Format specifiers Again, because a `ulong`/`slong` use different types on Windows and Linux, we cannot use the format specifiers `%lu`/`%ld` in `printf`. For this purpose we provide the `flint_printf` functions, which is the same as `printf`, except that it supports: ```c flint_printf("%wu", d); /* print ulong */ flint_printf("%wd", d); /* print slong */ ``` ## Use of `const` Input parameters to functions should be marked `const` in the following cases: * complex types that are passed by reference, e.g. `fmpz_poly_t` They should not be used on output parameters or for simple types or simple structs which are passed by value and not reference, e.g. `nmod_t`. ## Random functions When writing functions which produce random values the order of operands should follow one of the following: * If the function returns its random value, the state comes first, e.g: ```c a = n_randint(state, n) ``` * If the function sets its first argument to a random value, the state comes second, e.g. ```c nmod_poly_randtest(poly, state, len, bits) ``` ## Conversion functions When naming functions which convert between objects of different modules, use the convention `module1_get_module2` and `module1_set_module2`, where `module1` is notionally the more complex of the two modules. E.g. `fmpz_poly_get_nmod_poly`. The set function should set an object of `module1` to the value of an object of `module2`, and the get function should do the opposite. ## Underscores in function names Generally, underscores should not be used in function names to "hide" them. Instead, append `_internal` or `_helper` or just make the function static in the file in which it is used and give it a very descriptive name. Underscores at the beginning of function names have a special meaning in Flint. Functions without underscores generally are user facing in the sense that they handle aliasing (if appropriate), memory management and deal with objects that have structs associated to them. Functions with underscores are lower level and may have restrictions, such as not handling aliasing, assuming all objects have already been resized to have enough space for the output to be written and typically take many more arguments, corresponding to the various entries of higher level structs, e.g. an array of coefficients and a length instead of a polynomial struct. ## Code formatting ### Indentation We use soft indentation with a tab size of four spaces. The exception is for preprocessor conditionals, which are formatted with one space after the `#`, such as ```c #if defined(__GNUC__) # define IS_GNU #else # define IS_NOT_GNU #endif ``` ### Comments Comment are made via `/* COMMENT */`, not `// COMMENT`. ### Parentheses for conditionals and functions Parentheses of conditionals are formatted as `if (COND)`, `while (COND)`, `for (INIT; COND; INC)` and `switch (CASE)`. Parentheses of function calls, declarations and initializations are formatted as `func(INPUTS)`. ### Curly braces Opening curly brace are placed on a new line at the same indentation as the line above, and the closing curly brace is placed alone on a new line with one less indentation level as the line above. For example, an if-else statement is formatted as ```c if (COND) { /* Do something */ } else { /* Do something else */ } ``` ### `indent` The C code should follow the style produced by the following call to `indent`, ``` indent -bap -blf -bli0 -cbi0 -cdw -cli4 -cs -i4 -l79 -nbad -nbc -nce -npcs -nprs -nut -pmt -psl -saf -sai -saw -sbi0 -ss -ts4 ``` which is explained as follows: ``` -bap Force blank lines after procedure bodies -blf Put braces on line following function definition line -bli0 Indent braces 0 spaces -cbi0 Indent braces after a case label 0 spaces -cdw Cuddle while of do {} while -cli4 Case label indent of 4 spaces -cs Put a space after a cast operator -i4 Set indentation level to 4 spaces -l79 Set maximum line length for non-comment lines to 79 -nbad Do not force blank lines after declarations -nbc Do not force newlines after commas in declarations -nce Do not cuddle else -npcs Do not put a space after the function in function calls -nprs Do not put a space after every ( and before every ) -nut Use spaces instead of tabs -pmt Preserve access and modificaion times on output files -psl Put the type of a procedure on the line before its name -saf Put a space before each for -sai Space after each for -saw Space after every while -sbi0 Indent braces of a struct, union or enum 0 spaces -ss On one-line for and while statements, for a blank before ; -ts4 Set tab size to 4 spaces ``` flint-3.1.3/configure.ac000066400000000000000000001074251461254215100151320ustar00rootroot00000000000000################################################################################ # preamble ################################################################################ define(FLINT_COPYRIGHT,[[ Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . ]]) define(FLINT_COPYRIGHT_C,[[/* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */]]) dnl TODO dnl * Move more stuff to acinclude.m4 to debloat this file. AC_COPYRIGHT(FLINT_COPYRIGHT) AH_TOP(FLINT_COPYRIGHT_C) AC_PREREQ(2.62) m4_define(FLINT_VERSION,m4_include([VERSION])) AC_INIT(FLINT, FLINT_VERSION, [https://github.com/flintlib/flint/issues/], flint, [https://flintlib.org/]) AC_CONFIG_AUX_DIR([config]) AC_LANG(C) # Every major version of Flint (1.0, 1.1, 1.2, etc.) gets # a new major soname number. # Every time a release happens where interfaces are added # to Flint, the minor soname number gets incremented. # Every patch that is made that doesn't change the Flint # interface updates the patch number. # However, if backwards incompatible changes are made, both # the minor and patch numbers are set to 0. (Hopefully this # doesn't happen in practice.) # flint => soname # 2.5.0 => 13.5.0 # 2.5.1 => 13.5.1 # 2.5.2 => 13.5.2 # 2.6.0 => 14.0.0 # 2.6.1 => 14.0.1 # 2.6.2 => 14.0.2 # 2.6.3 => 14.0.3 # 2.7.0 => 15.0.0 # 2.7.1 => 15.0.1 # 2.8.0 => 16.1.0 # 2.8.1 => 16.1.1 # 2.8.2 => 16.1.2 # 2.8.3 => 16.1.3 # 2.8.4 => 16.1.4 # 2.8.5 => 16.1.5 # 2.9.0 => 17.0.0 # 3.0.0 => 18.0.0 # 3.1.0 => 19.0.0 # NOTE: This must be after AC_INIT FLINT_MAJOR_SO=19 FLINT_MINOR_SO=0 FLINT_PATCH_SO=0 # Make sure that we are in the right directory AC_CONFIG_SRCDIR(src/fmpz/link/fmpz_reentrant.c) ################################################################################ # initialize libtool ################################################################################ # Later we want to overwrite the default CFLAGS. Check now whether they are set # or not as Libtool overwrites CFLAGS. if test -n "${CFLAGS+x}"; then cflags_set="yes" else cflags_set="no" fi if test -n "${TESTCFLAGS+x}"; then testcflags_set="yes" else testcflags_set="no" fi if test -n "${CXXFLAGS+x}"; then cxxflags_set="yes" else cxxflags_set="no" fi LT_INIT if test "$cflags_set" = "no"; then CFLAGS= fi if test "$cxxflags_set" = "no"; then CXXFLAGS= fi ################################################################################ # build system ################################################################################ if test -n "$target_alias"; then AC_MSG_ERROR([FLINT does not support the use of specifying --target.]) fi dnl Get system triplet dnl NOTE: This is already invoked from LT_INIT dnl AC_CANONICAL_HOST ################################################################################ # configure headers ################################################################################ AC_CONFIG_HEADERS(src/config.h src/flint-config.h) ################################################################################ # features ################################################################################ AC_ARG_ENABLE(pthread, [AS_HELP_STRING([--enable-pthread],[Enable pthread [default=yes]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-pthread. Need yes or no.]) ;; esac], enable_pthread="yes") AC_ARG_ENABLE(reentrant, [AS_HELP_STRING([--enable-reentrant],[Build reentrant version of library [default=no]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-reentrant. Need yes or no.]) ;; esac], enable_reentrant="no") # Synonym for thread-safe. Only here for say to users that it is deprecated. AC_ARG_ENABLE(tls) AC_ARG_ENABLE(thread-safe, [AS_HELP_STRING([--enable-thread-safe],[Enable thread-local storage [default=yes]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-tls. Need yes or no.]) ;; esac], enable_thread_safe="yes") if test -n "$enable_tls"; then AC_MSG_ERROR([--enable-tls is an old feature. Please use --enable-thread-safe instead.]) fi AC_ARG_ENABLE(assert, [AS_HELP_STRING([--enable-assert],[Enable use of asserts [default=no]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-assert. Need yes or no.]) ;; esac], enable_assert="no") AC_ARG_ENABLE(coverage, [AS_HELP_STRING([--enable-coverage],[Enable test coverage [default=no]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-coverage. Need yes or no.]) ;; esac], enable_coverage="no") AC_ARG_ENABLE(debug, [AS_HELP_STRING([--enable-debug],[Compile FLINT with debug information [default=yes]])], [case $enableval in yes|no) if test "$enableval" = "no" && test "$enable_coverage" = "yes"; then AC_MSG_ERROR([Debug information is required by coverage.]) fi ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-debug. Need yes or no.]) ;; esac], enable_debug="yes") AC_ARG_ENABLE(dependency-tracking, [AS_HELP_STRING([--enable-dependency-tracking],[Enable GCC automated dependency tracking [default=yes]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-dependency-tracking. Need yes or no.]) ;; esac], enable_dependency_tracking="yes") AC_ARG_ENABLE(pretty-tests, [AS_HELP_STRING([--enable-pretty-tests],[Enable pretty printing for tests [default=yes]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-pretty-tests. Need yes or no.]) ;; esac], enable_pretty_tests="yes") AC_ARG_ENABLE(gmp-internals, [AS_HELP_STRING([--enable-gmp-internals],[Enable calling GMP internals directly [default=yes]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-gmp-internals. Need yes or no.]) ;; esac], enable_gmp_internals="yes") AC_ARG_ENABLE(assembly, [AS_HELP_STRING([--enable-assembly],[Enable assembly routines (if available) [default=yes]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-assembly. Need yes or no.]) ;; esac], enable_assembly="yes") AC_ARG_ENABLE(avx2, [AS_HELP_STRING([--enable-avx2],[Enable AVX2 instructions [default=no]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-avx2. Need yes or no.]) ;; esac], enable_avx2="no") AC_ARG_ENABLE(avx512, [AS_HELP_STRING([--enable-avx512],[Enable AVX512 instructions [default=no]])], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-avx512. Need yes or no.]) ;; esac], enable_avx512="no") AC_ARG_ENABLE(arch, [AS_HELP_STRING([--enable-arch[[=ARCH]]],[Enable and push -march=ARCH option to C compiler [default=native]])], [], enable_arch="native") # Note: This is maintainer level only. Currently only used for Nemo CI. AC_ARG_ENABLE(mpfr-check,[], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([Bad value $enableval for --enable-mpfr-check. Need yes or no.]) ;; esac], enable_mpfr_check="yes") ################################################################################ # packages ################################################################################ AC_ARG_WITH(gmp_include, [AS_HELP_STRING([--with-gmp-include=DIR],[GMP include directory])], CPPFLAGS="$CPPFLAGS -I$withval" gmp_include_path="$withval" ) AC_ARG_WITH(gmp_lib, [AS_HELP_STRING([--with-gmp-lib=DIR],[GMP library directory])], LDFLAGS="$LDFLAGS -L$withval" gmp_lib_path="$withval" ) AC_ARG_WITH(gmp, [AS_HELP_STRING([--with-gmp[[=DIR]]],[GMP install directory])], if test "$with_gmp" = "no"; then AC_MSG_FAILURE([The use of GMP is mandatory.]) elif test "$with_gmp" = "yes"; then : elif test -z "$gmp_include_path" && test -z "$gmp_lib_path"; then CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" gmp_include_path="$withval/include" gmp_lib_path="$withval/lib" with_gmp="yes" else AC_MSG_FAILURE([Cannot use --with-gmp along with --with-gmp-include or --with-gmp-lib.]) fi, with_gmp="yes" ) AC_ARG_WITH(mpfr_include, [AS_HELP_STRING([--with-mpfr-include=DIR],[MPFR include directory])], CPPFLAGS="$CPPFLAGS -I$withval" mpfr_include_path="$withval" ) AC_ARG_WITH(mpfr_lib, [AS_HELP_STRING([--with-mpfr-lib=DIR],[MPFR library directory])], LDFLAGS="$LDFLAGS -L$withval" mpfr_lib_path="$withval" ) AC_ARG_WITH(mpfr, [AS_HELP_STRING([--with-mpfr[[=DIR]]],[MPFR install directory])], if test "$with_mpfr" = "no"; then AC_MSG_FAILURE([The use of MPFR is mandatory.]) elif test "$with_mpfr" = "yes"; then : elif test -z "$mpfr_include_path" && test -z "$mpfr_lib_path"; then CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" mpfr_include_path="$withval/include" mpfr_lib_path="$withval/lib" with_mpfr="yes" else AC_MSG_FAILURE([Cannot use --with-mpfr along with --with-mpfr-include or --with-mpfr-lib.]) fi, with_mpfr="yes" ) AC_ARG_WITH(blas_include, [AS_HELP_STRING([--with-blas-include=DIR],[Use BLAS and specify its include directory])], CPPFLAGS="$CPPFLAGS -I$withval" blas_include_path="$withval" ) AC_ARG_WITH(blas_lib, [AS_HELP_STRING([--with-blas-lib=DIR],[Use BLAS and specify its library directory])], LDFLAGS="$LDFLAGS -L$withval" blas_lib_path="$withval" ) AC_ARG_WITH(blas, [AS_HELP_STRING([--with-blas[[=DIR]]],[Use BLAS and specify its install directory])], if test "$with_blas" = "yes"; then : elif test "$with_blas" = "no"; then if test -n "$blas_include_path" || test -n "$blas_lib_path"; then AC_MSG_FAILURE([--with-blas-include or --with-blas-lib was specified but --with-blas=no.]) fi elif test -z "$blas_include_path" && test -z "$blas_lib_path"; then CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" blas_include_path="$withval/include" blas_lib_path="$withval/lib" with_blas="yes" else AC_MSG_FAILURE([Cannot use --with-blas along with --with-blas-include or --with-blas-lib.]) fi, with_blas="no" ) if test "$with_blas" != "no" || test -n "$blas_include_path" || test -n "$blas_lib_path"; then with_blas="yes" fi AC_ARG_WITH(gc_include, [AS_HELP_STRING([--with-gc-include=DIR],[Use GC and specify its include directory])], CPPFLAGS="$CPPFLAGS -I$withval" gc_include_path="$withval", with_gc_include="no" ) AC_ARG_WITH(gc_lib, [AS_HELP_STRING([--with-gc-lib=DIR],[Use GC and specify its library directory])], LDFLAGS="$LDFLAGS -L$withval" gc_lib_path="$withval", with_gc_lib="no" ) AC_ARG_WITH(gc, [AS_HELP_STRING([--with-gc[[=DIR]]],[Use GC and optionally specify its install directory])], if test "$with_gc" = "yes"; then : elif test "$with_gc" = "no"; then if test -n "$gc_include_path" || test -n "$gc_lib_path"; then AC_MSG_FAILURE([--with-gc-include or --with-gc-lib was specified but --with-gc=no.]) fi elif test -z "$gc_include_path" && test -z "$gc_lib_path"; then CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" gc_include_path="$withval/include" gc_lib_path="$withval/lib" with_gc="yes" else AC_MSG_FAILURE([Cannot use --with-gc along with --with-gc-include or --with-gc-lib.]) fi, with_gc="no" ) if test "$with_gc" != "no" || test -n "$gc_include_path" || test -n "$gc_lib_path"; then with_gc="yes" fi AC_ARG_WITH(ntl_include, [AS_HELP_STRING([--with-ntl-include=DIR],[Use NTL (in tests) and specify its include directory])], CPPFLAGS="$CPPFLAGS -I$withval" ntl_include_path="$withval" ) AC_ARG_WITH(ntl_lib, [AS_HELP_STRING([--with-ntl-lib=DIR],[Use NTL (in tests) and specify its library directory])], LDFLAGS="$LDFLAGS -L$withval" ntl_lib_path="$withval" ) AC_ARG_WITH(ntl, [AS_HELP_STRING([--with-ntl[[=DIR]]],[Use NTL (in tests) and optionally specify its install directory])], if test "$with_ntl" = "yes"; then : elif test "$with_ntl" = "no"; then if test -n "$ntl_include_path" || test -n "$ntl_lib_path"; then AC_MSG_FAILURE([--with-ntl-include or --with-ntl-lib was specified but --with-ntl=no.]) fi elif test -z "$ntl_include_path" && test -z "$ntl_lib_path"; then CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" ntl_include_path="$withval/include" ntl_lib_path="$withval/lib" with_ntl="yes" else AC_MSG_FAILURE([Cannot use --with-ntl along with --with-ntl-include or --with-ntl-lib.]) fi, with_ntl="no" ) if test "$with_ntl" != "no" || test -n "$ntl_include_path" || test -n "$ntl_lib_path"; then with_ntl="yes" fi ################################################################################ # programs ################################################################################ dnl NOTE: The following line is invoked from LT_INIT dnl AC_PROG_CC if test "$with_ntl" = "yes"; then AC_PROG_CXX AC_LANG_PUSH(C++) if test "$cxxflags_set" = "no"; then AX_CXX_CHECK_COMPILE_FLAG([-Wall],[CXXFLAGS="-Wall $CXXFLAGS"]) AX_CXX_CHECK_COMPILE_FLAG([-Werror=implicit-function-declaration],[CXXFLAGS="-Werror=implicit-function-declaration $CXXFLAGS"]) AX_CXX_CHECK_COMPILE_FLAG([-O2],[CXXFLAGS="-O2 $CXXFLAGS"]) if test "$enable_arch" != "no"; then AX_CXX_CHECK_COMPILE_FLAG([-march=$enable_arch],[CXXFLAGS="-march=$enable_arch $CXXFLAGS"]) fi AX_CXX_CHECK_COMPILE_FLAG([-std=c++11],[CXXFLAGS="-std=c++11 $CXXFLAGS"], AC_MSG_ERROR([Couldn't compile with the C++11 standard needed by the NTL interface.]) ) if test "$enable_debug" = "yes"; then if "$ac_cv_prog_cxx_g" = "yes"; then CXXFLAGS="-g $CXXFLAGS" else AC_MSG_ERROR([$CXX does not support the flag -g needed to generate debug information]) fi fi fi AC_LANG_POP fi AC_PROG_MKDIR_P ################################################################################ # environment variables ################################################################################ AC_ARG_VAR([TESTCFLAGS], [Choose different C compiler flags for tests [default=CFLAGS]. Can be useful to compile library at a specific optimization level while compiling tests fast.]) ################################################################################ # check programs and system ################################################################################ AC_C_INLINE if test "$compiler_c_o" = "no"; then AC_MSG_ERROR([Compiler must support both -c and -o simultaneously!]) fi AC_C_BIGENDIAN(flint_big_endian=yes) case "$host_os" in darwin*) flint_lib="libflint.dylib" flint_lib_major="libflint.$FLINT_MAJOR_SO.dylib" flint_lib_full="libflint.$FLINT_MAJOR_SO.$FLINT_MINOR_SO.dylib" extra_shared_flags="-install_name '`pwd`/$flint_lib_full' -compatibility_version $FLINT_MAJOR_SO.$FLINT_MINOR_SO -current_version $FLINT_MAJOR_SO.$FLINT_MINOR_SO.$FLINT_PATCH_SO" flint_dylib="yes" ;; cygwin|mingw*|msys) flint_lib="libflint.dll" flint_lib_major="libflint.$FLINT_MAJOR_SO.dll" flint_lib_full="libflint.$FLINT_MAJOR_SO.$FLINT_MINOR_SO.$FLINT_PATCH_SO.dll" flint_implib="$flint_lib.$libext" extra_shared_flags="-static-libgcc $wl--export-all-symbols,--out-implib,$flint_implib" flint_dlllib="yes" ;; *) flint_lib="libflint.so" flint_lib_major="libflint.so.$FLINT_MAJOR_SO" flint_lib_full="libflint.so.$FLINT_MAJOR_SO.$FLINT_MINOR_SO.$FLINT_PATCH_SO" extra_shared_flags="$wl-soname,$flint_lib_major" flint_solib="yes" ;; esac flint_lib_static="libflint.$libext" if test "`uname -s`" = "android"; then extra_shared_flags="$wl-soname,$flint_lib" fi AC_SUBST(WL,$wl) AC_SUBST(FLINT_LIB,$flint_lib) AC_SUBST(FLINT_LIB_MAJOR,$flint_lib_major) AC_SUBST(FLINT_LIB_FULL,$flint_lib_full) AC_SUBST(FLINT_IMPLIB,$flint_implib) AC_SUBST(FLINT_LIB_STATIC,$flint_lib_static) AC_SUBST(EXTRA_SHARED_FLAGS,$extra_shared_flags) if test "$flint_dlllib" = "yes"; then AC_SUBST(FLINT_DLLLIB,1) else AC_SUBST(FLINT_DLLLIB,0) fi if test "$flint_dylib" = "yes"; then AC_SUBST(FLINT_DYLIB,1) else AC_SUBST(FLINT_DYLIB,0) fi if test "$flint_solib" = "yes"; then AC_SUBST(FLINT_SOLIB,1) else AC_SUBST(FLINT_SOLIB,0) fi case "$host_os" in cygwin|mingw*|msys) if test "$DLLTOOL" = "false"; then AC_MSG_ERROR(["Couldn't find any dlltool that is required to create import libraries for Windows-type systems."]) fi ;; esac dnl FIXME: Improve this check to include more processors. AC_MSG_CHECKING([if memory is strongly-ordered]) case "$host" in X86_PATTERN | X86_64_PATTERN) flint_know_strong_order="yes" AC_MSG_RESULT([yes]) ;; *) flint_know_strong_order="no" AC_MSG_RESULT([unsure]) ;; esac if test "$flint_know_strong_order" = "yes"; then AC_DEFINE(FLINT_KNOW_STRONG_ORDER,1,[Define if system is strongly ordered]) fi ################################################################################ # check GMP ################################################################################ FLINT_CHECK_GMP_H(6,2,1) FLINT_GMP_LONG_LONG_LIMB([gmpcompat_h_in="gmpcompat-longlong.h.in"], [gmpcompat_h_in="gmpcompat.h.in"]) AC_CONFIG_FILES([src/gmpcompat.h:src/$gmpcompat_h_in],[],[gmpcompat_h_in="$gmpcompat_h_in"]) AC_SUBST(GMPCOMPAT_H_IN, $gmpcompat_h_in) ################################################################################ # check MPFR ################################################################################ FLINT_CHECK_MPFR_H(4,1,0) ################################################################################ # check ABI ################################################################################ FLINT_ABI case "$flint_cv_abi" in 32) fft_tuning_in="src/fft_tuning32.in" ;; 64) fft_tuning_in="src/fft_tuning64.in" ;; esac AC_CONFIG_FILES([src/fft_tuning.h:$fft_tuning_in],[],[fft_tuning_in="$fft_tuning_in"]) AC_SUBST(FFT_TUNING_IN, $fft_tuning_in) ################################################################################ # check headers ################################################################################ # Mandatory headers # The following headers are checked previously: # stdio.h stdlib.h stdint.h string.h AC_CHECK_HEADERS([stdarg.h math.h float.h errno.h],, AC_MSG_ERROR([Could not find a mandatory header!])) # Optional headers # The following headers are checked previously: # unistd.h AC_CHECK_HEADERS([fenv.h alloca.h malloc.h sys/param.h windows.h pthread_np.h]) if test "$enable_pthread" = "yes"; then AC_CHECK_HEADER([pthread.h],, AC_MSG_ERROR([Could not find pthread.h!])) fi if test "$enable_assert" = "yes"; then AC_CHECK_HEADER([assert.h],, AC_MSG_ERROR([Could not find assert.h!])) fi if test "$with_blas" = "yes"; then AC_CHECK_HEADER([cblas.h],, AC_MSG_ERROR([Could not find cblas.h!])) fi if test "$with_gc" = "yes"; then AC_CHECK_HEADER([gc.h],, AC_MSG_ERROR([Could not find gc.h!])) fi if test "$with_ntl" = "yes"; then AC_LANG_PUSH([C++]) AC_CHECK_HEADER([NTL/ZZ.h],, AC_MSG_ERROR([Could not find NTL/ZZ.h!])) AC_LANG_POP([C++]) fi ################################################################################ # check libraries ################################################################################ AC_SEARCH_LIBS([atan2],[m], [], [AC_MSG_ERROR(["The C math library was not found!"])]) AC_SEARCH_LIBS([__gmpz_init],[gmp], [], [AC_MSG_ERROR(["GMP library was not found. If you indeed have GMP installed, please submit a bug report to so that we can either fix the issue or give a more proper error message."])]) if test "$enable_gmp_internals" = "yes"; then AC_SEARCH_LIBS([__gmpn_gcd_11],[gmp], [], [AC_MSG_ERROR(["`mpn_gcd_11' was not found in the GMP library. It is needed to enable GMP internals."])]) AC_SEARCH_LIBS([__gmpn_div_q],[gmp], [], [AC_MSG_ERROR([`mpn_div_q' was not found in the GMP library. It is needed to enable GMP internals.])]) AC_SEARCH_LIBS([__gmpn_mul_basecase],[gmp], [], [AC_MSG_ERROR([`mpn_mul_basecase' was not found in the GMP library. It is needed to enable GMP internals.])]) AC_SEARCH_LIBS([__gmpn_modexact_1_odd],[gmp], [AC_DEFINE(FLINT_HAVE_MPN_MODEXACT_1_ODD,1,Define if system has mpn_modexact_1_odd)]) AC_SEARCH_LIBS([__gmpn_addmul_2],[gmp], [AC_DEFINE(FLINT_HAVE_MPN_ADDMUL_2,1,Define if GMP has mpn_addmul_2)]) fi if test "$enable_mpfr_check" = "yes"; then AC_SEARCH_LIBS([mpfr_init],[mpfr], [], [AC_MSG_ERROR([MPFR library was not found. If you indeed have MPFR installed, please submit a bug report to so that we can either fix the issue or give a more proper error message.])]) AC_SEARCH_LIBS([mpfr_round_p],[mpfr], [], [AC_MSG_ERROR(["`mpfr_round_p' was not found in the MPFR library. It is required for FLINT."])]) AC_SEARCH_LIBS([mpfr_mulhigh_n],[mpfr], [], [AC_MSG_ERROR(["`mpfr_mulhigh_n' was not found in the MPFR library. It is required for FLINT."])]) AC_SEARCH_LIBS([mpfr_sqrhigh_n],[mpfr], [], [AC_MSG_ERROR(["`mpfr_sqrhigh_n' was not found in the MPFR library. It is required for FLINT."])]) else LIBS="$LIBS -lmpfr" fi if test "$enable_pthread" = "yes"; then # check if compiler accepts the preferred -pthread AX_CHECK_COMPILE_FLAG([-pthread], [LIBS="-pthread $LIBS"], # check if the compiler can do -lpthread AC_SEARCH_LIBS([pthread_create],[pthread], [], AC_MSG_ERROR([Couldn't link against POSIX threads via -pthread or -lpthread while --enable-pthread was specified.]) ) ) fi if test "$with_blas" = "yes"; then AC_SEARCH_LIBS([cblas_dgemm],[cblas openblas blas],[], [AC_MSG_ERROR([BLAS library was not found. If you indeed have BLAS installed, please submit a bug report to so that we can either fix the issue or give a more proper error message.])] ) fi if test "$with_ntl" = "yes"; then AC_MSG_CHECKING([if linking simple code snippet of NTL works]) SAVE_libs="$LIBS" LIBS="-lntl $LIBS" AC_LANG_PUSH([C++]) dnl The following code snippet was taken from NTL's documentation AC_LINK_IFELSE( [AC_LANG_PROGRAM([[#include ]], [NTL::ZZ a, b, c; std::cin >> a; std::cin >> b; c = (a+1)*(b+1); std::cout << c << "\n";])], AC_MSG_RESULT([yes]), AC_MSG_RESULT([no]) [AC_MSG_ERROR([NTL library was not found. If you indeed have NTL installed, please submit a bug report to so that we can either fix the issue or give a more proper error message.])] ) AC_LANG_POP LIBS="$SAVE_libs" fi ################################################################################ # check settings and environment ################################################################################ AC_SUBST(PIC_FLAG,$pic_flag) AC_MSG_CHECKING([if cpu_set_t is supported]) AC_LINK_IFELSE([AC_LANG_PROGRAM([#define _GNU_SOURCE #include #include ], [cpu_set_t s;CPU_ZERO(&s); pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), 0);])], [AC_DEFINE(FLINT_USES_CPUSET,1,Define if system has cpu_set_t) AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) # ensure alloca works AC_MSG_CHECKING([if alloca works]) AC_LINK_IFELSE([AC_LANG_PROGRAM( [#ifndef alloca # ifdef __GNUC__ # define alloca __builtin_alloca # else # ifdef _MSC_VER # include # define alloca _alloca # else # include /* We assume then that you have alloca.h */ # endif # endif #endif], [char * p = alloca(128);])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Couldn't find alloca, which is required for FLINT. Please submit a bug report to and specify your operating system.])]) AC_CHECK_FUNCS([aligned_alloc _aligned_malloc]) ################################################################################ # CFLAGS ################################################################################ save_CFLAGS="$CFLAGS" CFLAGS="" # The following is needed for Clang to check for unknown options. AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option], [CFLAGS="-Werror=unknown-warning-option"]) if test "$enable_coverage" = "yes"; then AX_CHECK_COMPILE_FLAG([--coverage], [save_CFLAGS="--coverage $save_CFLAGS"], [AC_MSG_ERROR([$CC does not to support test coverage flags])]) LDFLAGS="--coverage $LDFLAGS" if test "$enable_pthread" = "yes"; then AX_CHECK_COMPILE_FLAG([-fprofile-update=atomic], [save_CFLAGS="-fprofile-update=atomic $save_CFLAGS"], [AC_MSG_ERROR([$CC does not to support multi-threaded test coverage flags])]) fi fi if test "$enable_debug" = "yes"; then if test "$ac_cv_prog_cc_g" = "yes"; then save_CFLAGS="-g $save_CFLAGS" else AC_MSG_ERROR([$CC does not support the flag -g needed to generate debug information]) fi fi if test -n "$ABI"; then AX_CHECK_COMPILE_FLAG([-m$ABI], [save_CFLAGS="-m$ABI $save_CFLAGS"], [AC_MSG_ERROR([$CC does not support the ABI flag -m$ABI])] ) fi if test "$enable_avx2" = "yes"; then AX_CHECK_COMPILE_FLAG([-mavx2], [save_CFLAGS="-mavx2 $save_CFLAGS" AC_DEFINE(FLINT_HAVE_AVX2,1,[Define if system has AVX2])], [AC_MSG_ERROR([$CC does not support the flag -mavx2 needed for AVX2 instructions])]) AX_CHECK_COMPILE_FLAG([-mfma], [save_CFLAGS="-mfma $save_CFLAGS"]) fi if test "$enable_avx512" = "yes"; then AX_CHECK_COMPILE_FLAG([-mavx512f], [save_CFLAGS="-mavx512f $save_CFLAGS" AC_DEFINE(FLINT_HAVE_AVX512,1,[Define if system has AVX512])], [AC_MSG_ERROR([$CC does not support the flag -mavx512f needed for AVX512 instructions])]) fi case $host_cpu in sparc*) AX_CHECK_COMPILE_FLAG(-mno-relax,[DEFAULT_CFLAGS="-mno-relax $DEFAULT_CFLAGS"]) ;; *) ;; esac AX_CHECK_COMPILE_FLAG([-Wall],[DEFAULT_CFLAGS="-Wall $DEFAULT_CFLAGS"]) AX_CHECK_COMPILE_FLAG([-Wno-stringop-overread],[DEFAULT_CFLAGS="-Wno-stringop-overread $DEFAULT_CFLAGS"]) AX_CHECK_COMPILE_FLAG([-Wno-stringop-overflow],[DEFAULT_CFLAGS="-Wno-stringop-overflow $DEFAULT_CFLAGS"]) AX_CHECK_COMPILE_FLAG([-Werror=implicit-function-declaration],[DEFAULT_CFLAGS="-Werror=implicit-function-declaration $DEFAULT_CFLAGS"]) AX_CHECK_COMPILE_FLAG([-O3],[DEFAULT_CFLAGS="-O3 $DEFAULT_CFLAGS"]) if test "$enable_arch" != "no"; then AX_CHECK_COMPILE_FLAG([-march=$enable_arch],[DEFAULT_CFLAGS="-march=$enable_arch $DEFAULT_CFLAGS"]) fi AX_CHECK_COMPILE_FLAG([-std=c11],[DEFAULT_CFLAGS="-std=c11 $DEFAULT_CFLAGS"]) AX_CHECK_COMPILE_FLAG([-pedantic],[DEFAULT_CFLAGS="-pedantic $DEFAULT_CFLAGS"]) if test "$cflags_set" = "no"; then CFLAGS="$save_CFLAGS $DEFAULT_CFLAGS" AC_SUBST(UNROLL_LOOPS,1) AC_DEFINE(FLINT_UNROLL_LOOPS, 1, [Define to locally unroll some loops]) else CFLAGS="$save_CFLAGS" AX_CHECK_COMPILE_FLAG([$CFLAGS],[],AC_MSG_ERROR(["Couldn't compile with given CFLAGS!"])) AC_SUBST(UNROLL_LOOPS,0) fi if test "$testcflags_set" = "no"; then TESTCFLAGS="$CFLAGS" else TESTCFLAGS="$TESTCFLAGS $save_CFLAGS" fi CPPFLAGS="-I./src $CPPFLAGS" ################################################################################ # Architecture ################################################################################ FLINT_ARCH ################################################################################ # fft_small module ################################################################################ FLINT_CHECK_FFT_SMALL( [AC_SUBST(FFT_SMALL, [fft_small\ \ \ ]) AC_DEFINE(FLINT_HAVE_FFT_SMALL, 1, [Define to use the fft_small module]) case $flint_cv_arch in FAST_VROUNDPD_PATTERN) fft_small_threshold="400" ;; SLOW_VROUNDPD_PATTERN) fft_small_threshold="1540" ;; *) fft_small_threshold="500" ;; esac AC_DEFINE_UNQUOTED(FLINT_FFT_SMALL_THRESHOLD,[$fft_small_threshold],[Define to set threshold for when to use fft_small module])], [AC_SUBST(FFT_SMALL, [\ \ \ \ \ \ \ \ \ \ \ \ ])]) ################################################################################ # Assembly ################################################################################ if test "$enable_assembly" = "yes"; then FLINT_HAVE_ASM([enable_assembly="yes"], [enable_assembly="no" AC_MSG_WARN([FLINT currently only have assembly routines for System V-type systems for x86_64 processors with ADX instruction set. Disabling assembly...])]) fi if test "$enable_assembly" = "yes"; then GMP_INIT(config.m4) GMP_PROG_M4 GMP_PATH_NM GMP_ASM_TEXT GMP_ASM_DATA GMP_ASM_LABEL_SUFFIX GMP_ASM_GLOBL GMP_ASM_GLOBL_ATTR GMP_ASM_UNDERSCORE GMP_ASM_RODATA GMP_ASM_TYPE GMP_ASM_SIZE GMP_ASM_LSYM_PREFIX GMP_ASM_ALIGN_LOG case $host in ARM64_PATTERN)dnl Currently not active case $host in *-*-darwin*) GMP_INCLUDE_MPN(src/mpn_extras/arm64/darwin.m4) ;; *) GMP_INCLUDE_MPN(src/mpn_extras/arm64/arm64-defs.m4) ;; esac ;; X86_64_PATTERN) AC_DEFINE([FLINT_HAVE_ADX],1,[Define if CPU supports ADX instruction set]) GMP_ASM_ALIGN_FILL_0x90 GMP_ASM_COFF_TYPE GMP_INCLUDE_MPN(src/mpn_extras/broadwell/x86_64-defs.m4) case $host in *-*-darwin*) GMP_INCLUDE_MPN(src/mpn_extras/broadwell/darwin.m4) ;; esac ;; esac GMP_FINISH fi ################################################################################ # substitutions and definitions ################################################################################ AC_SUBST(FLINT_VERSION_FULL, FLINT_VERSION) # split version into major/minor/patch using POSIX variable substitutions tail=FLINT_VERSION FLINT_MAJOR=${tail%%.*} tail=${tail#*.} FLINT_MINOR=${tail%%.*} tail=${tail#*.} FLINT_PATCH=${tail%-*} AC_SUBST(FLINT_MAJOR) AC_SUBST(FLINT_MINOR) AC_SUBST(FLINT_PATCH) AC_SUBST(FLINT_MAJOR_SO) AC_SUBST(FLINT_MINOR_SO) AC_SUBST(FLINT_PATCH_SO) AC_SUBST(GMP_LIB_PATH,$gmp_lib_path) AC_SUBST(MPFR_LIB_PATH,$mpfr_lib_path) AC_SUBST(BLAS_LIB_PATH,$blas_lib_path) AC_SUBST(GC_LIB_PATH,$gc_lib_path) AC_SUBST(NTL_LIB_PATH,$ntl_lib_path) AC_SUBST(LIB_CPPFLAGS,["-DFLINT_NOSTDIO -DFLINT_NOSTDARG"]) # Configure fmpz's memory manager if test "$with_gc" = "yes"; then if test "$enable_thread_safe" = "yes"; then AC_MSG_ERROR(["The Boehm-Demers-Weise garbage collector does not support thread-local storage!"]) fi fmpz_c="src/fmpz/link/fmpz_gc.c" else if test "$enable_reentrant" = "yes"; then fmpz_c="src/fmpz/link/fmpz_reentrant.c" else fmpz_c="src/fmpz/link/fmpz_single.c" fi fi AC_CONFIG_FILES([src/fmpz/fmpz.c:$fmpz_c],[],[fmpz_c="$fmpz_c"]) AC_SUBST(FMPZ_C_IN, $fmpz_c) if test "$enable_shared" = "yes"; then AC_SUBST(SHARED,1) else AC_SUBST(SHARED,0) fi if test "$enable_static" = "yes"; then AC_SUBST(STATIC,1) else AC_SUBST(STATIC,0) fi if test "$enable_coverage" = "yes"; then AC_SUBST(COVERAGE,1) AC_DEFINE(FLINT_COVERAGE,1,[Define to enable coverage.]) else AC_SUBST(COVERAGE,0) fi if test "$enable_dependency_tracking" = "yes"; then AC_SUBST(WANT_DEPS,1) else AC_SUBST(WANT_DEPS,0) fi if test "$enable_pretty_tests" = "yes"; then AC_DEFINE(FLINT_WANT_PRETTY_TESTS,1,[Define to enable pretty printing for tests.]) fi if test "$with_ntl" = "yes"; then AC_SUBST(WANT_NTL,1) else AC_SUBST(WANT_NTL,0) fi if test "$with_blas" = "yes"; then AC_DEFINE(FLINT_USES_BLAS,1,[Define to enable BLAS.]) fi if test "$with_gc" = "yes"; then AC_DEFINE(FLINT_USES_GC,1,[Define to enable the Boehm-Demers-Weise garbage collector.]) fi if test "$flint_big_endian" = "yes"; then AC_DEFINE(FLINT_BIG_ENDIAN,1,[Define if system is big endian.]) fi if test "$enable_pthread" = "yes"; then AC_DEFINE(FLINT_USES_PTHREAD,1,[Define to enable the use of pthread.]) fi if test "$enable_thread_safe" = "yes"; then AC_DEFINE(FLINT_USES_TLS,1,[Define to enable thread-local storage.]) fi if test "$enable_reentrant" = "yes"; then AC_DEFINE(FLINT_REENTRANT,1,[Define to enable reentrant.]) fi if test "$enable_assert" = "yes"; then AC_DEFINE(FLINT_WANT_ASSERT,1,[Define to enable use of asserts.]) fi if test "$enable_gmp_internals" = "yes"; then AC_DEFINE(FLINT_WANT_GMP_INTERNALS,1,[Define to enable use of GMP internals.]) fi if test "$enable_assembly" = "yes"; then case $host in X86_64_PATTERN) AC_SUBST(WANT_ADX_ASSEMBLY,1) ;; *) AC_SUBST(WANT_ADX_ASSEMBLY,0) ;; esac else AC_SUBST(WANT_ADX_ASSEMBLY,0) fi ################################################################################ # epilog ################################################################################ AC_CONFIG_FILES([Makefile flint.pc src/flint.h]) AC_OUTPUT dnl Shorten the original help message m4_cleardivert([HELP_BEGIN])dnl m4_divert_push([HELP_BEGIN])dnl if test "$ac_init_help" = "long"; then cat <<_ACEOF \`configure' configures m4_ifset([AC_PACKAGE_STRING], [AC_PACKAGE_STRING], [this package]) to adapt to many kinds of systems. Usage: $[0] [[OPTION]]... [[VAR=VALUE]]... [To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: ]AS_HELP_STRING([--prefix=PREFIX], [install architecture-independent files in PREFIX [$ac_default_prefix]]) AS_HELP_STRING([--exec-prefix=EPREFIX], [install architecture-dependent files in EPREFIX [PREFIX]])[ By default, \`make install' will install all the files in \`$ac_default_prefix/include' and \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] _ACEOF cat <<\_ACEOF] m4_divert_pop([HELP_BEGIN])dnl dnl NOTE: There is supposed to be a missing `fi' here. flint-3.1.3/deprecations.txt000066400000000000000000000012741461254215100160600ustar00rootroot00000000000000# Deprecated in Flint 2.6.0 (removed) n_gcd_full -> n_gcd fmpz_poly_is_x -> fmpz_poly_is_gen fmpz_mod_poly_is_x -> fmpz_mod_poly_is_gen fmpq_poly_is_x -> fmpq_poly_is_gen # Deprecated in Flint 2.7.0 (removed) nmod_mat_scalar_mul_add -> nmod_mat_scalar_adduml_ui # Deprecated in Flint 2.8.0 fmpz_multi_crt_t -> fmpz_multi_CRT_t fmpz_multi_crt_init -> fmpz_multi_CRT_init fmpz_multi_crt_precompute -> fmpz_multi_CRT_precompute fmpz_multi_crt_precompute_p (removed) fmpz_multi_crt_precomp -> fmpz_multi_CRT_precomp now with sign option fmpz_multi_crt_precomp_p (removed) fmpz_multi_crt -> fmpz_multi_CRT now with sign option fmpz_multi_crt_clear -> fmpz_multi_CRT_clear flint-3.1.3/dev/000077500000000000000000000000001461254215100134115ustar00rootroot00000000000000flint-3.1.3/dev/bench.py000066400000000000000000000133631461254215100150500ustar00rootroot00000000000000import subprocess def run(s): print("running", s) s = subprocess.check_output(s.split()).decode() for line in s.splitlines(): print("--- ", line) return s results = [] def add_result(prefix, time): global results results.append((prefix, time)) def print_results(): global results print() print("==================== DETAILS ====================") total = 0.0 groups = {} group_count = {} for prefix, time in results: total += time descr = " ".join(prefix) print(descr.ljust(40), f'{time:6.3f}') group = prefix[0] if group in groups: groups[group] += time else: groups[group] = time group_count[group] = group_count.get(group, 0) + 1 print("==================== BY GROUP ===================") for group in groups: descr = "%s (%i benchmarks)" % (group, group_count[group]) time = groups[group] print(descr.ljust(40), f'{time:6.3f}') print("====================== TOTAL ====================") descr = "all (%s benchmarks)" % len(results) print(descr.ljust(40), f'{total:6.3f}') print() def arb_bench(): s = run("build/examples/pi 10000000") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "pi 10000000"], time) s = run("build/examples/pi 10000000 -threads 8") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "pi 10000000 -threads 8"], time) s = run("build/examples/bernoulli 1000000 -threads 8") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "bernoulli 1000000 -threads 8"], time) s = run("build/examples/partitions 1000000000000 -threads 8 -quiet") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "partitions 1e12 -threads 8"], time) s = run("build/examples/zeta_zeros -count 1000 -prec 333 -threads 8") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "zeta_zeros 1000 -prec 333 -threads 8"], time) s = run("build/examples/keiper_li 3000 -threads 8") for line in s.splitlines(): if "total: " in line: time = float(line.split()[-1]) add_result(["arb", "keiper_li 3000 -threads 8"], time) s = run("build/examples/integrals -i 4 -prec 1000") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "integrals -i 4 -prec 1000"], time) s = run("build/examples/hilbert_matrix 120") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "hilbert_mat 120"], time) s = run("build/examples/hilbert_matrix -eig 50") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "hilbert_matrix -eig 50"], time) s = run("build/examples/poly_roots a 256") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "poly_roots a 256"], time) s = run("build/examples/class_poly -1000000") for line in s.splitlines(): if "cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["arb", "class_poly -1000000"], time) def fmpz_bench(): s = run("build/fmpz/profile/p-is_prime_bench") for line in s.splitlines(): if "cpu/wall(s):" in line: size = " ".join(line.split()[:3]) time = float(line.split()[-1]) add_result(["fmpz", "is_prime", size], time) s = run("build/fmpz/profile/p-is_probabprime_bench") for line in s.splitlines(): if "cpu/wall(s):" in line: size = " ".join(line.split()[:3]) time = float(line.split()[-1]) add_result(["fmpz", "is_probabprime", size], time) s = run("build/fmpz_factor/profile/p-factor_bench") for line in s.splitlines(): if "cpu/wall(s):" in line: size = " ".join(line.split()[:3]) time = float(line.split()[-1]) add_result(["fmpz", "factor", size], time) def fmpz_poly_bench(): s = run("build/fmpz_poly_factor/profile/p-factor_hard") for line in s.splitlines(): if " ms" in line: poly = line.split()[0] time = float(line.split()[-2]) * 0.001 add_result(["fmpz_poly", "factor", poly], time) def fmpz_mpoly_bench(): s = run("build/fmpz_mpoly_factor/profile/p-factor") for line in s.splitlines(): if "variables" in line: vars = line.split()[1] if "total_time:" in line: time = float(line.split()[-1]) * 0.001 add_result(["fmpz_mpoly", "factor %s variables" % vars], time) def nmod_mpoly_bench(): s = run("build/nmod_mpoly_factor/profile/p-factor") for line in s.splitlines(): if "---" in line: info = " ".join(line.split()[1:-1]) info = info.replace("variables", "vars").replace("characteristic", "p =") if "total_time:" in line: time = float(line.split()[-1]) * 0.001 add_result(["nmod_mpoly", "factor %s" % info], time) def calcium_bench(): s = run("build/examples/huge_expr -ca") for line in s.splitlines(): if "Total: cpu/wall(s):" in line: time = float(line.split()[-1]) add_result(["calcium", "huge_expr"], time) fmpz_bench() fmpz_poly_bench() nmod_mpoly_bench() fmpz_mpoly_bench() arb_bench() calcium_bench() print_results() flint-3.1.3/dev/check_examples.sh000077500000000000000000000157001461254215100167260ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright (C) 2023 Albin Ahlbäck # # This file is part of FLINT. # # FLINT is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License (LGPL) as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. See . if test "$1" = "bernoulli"; then echo -n "bernoulli...." res=$($2/bernoulli 20 -threads 2) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo $res | perl -0ne 'if (/-174611\/330/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "binet"; then echo -n "binet...." res=$($2/binet -limit 2 8) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo $res | perl -0ne 'if (/21 cpu/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "class_poly"; then echo "class_poly....SKIPPED" exit 0 elif test "$1" = "complex_plot"; then echo "complex_plot....SKIPPED" exit 0 elif test "$1" = "crt"; then echo "crt....SKIPPED" exit 0 elif test "$1" = "delta_qexp"; then echo "delta_qexp....SKIPPED" exit 0 elif test "$1" = "dft"; then echo "dft....SKIPPED" exit 0 elif test "$1" = "elementary"; then echo -n "elementary...." res=$($2/elementary) if test "$?" != "0"; then echo "FAIL" exit 1 fi # Check that the first and last expression prints as intended echo "$res" | perl -0ne 'if (/>>> Exp\(Pi\*I\) \+ 1\n0\n/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "$res" | perl -0ne 'if (/>>> Erf\(2\*Log\(Sqrt\(1\/2-Sqrt\(2\)\/4\)\)\+Log\(4\)\) - Erf\(Log\(2-Sqrt\(2\)\)\)\n0\n/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "factor_integer"; then echo -n "factor_integer...." res=$($2/factor_integer -threads 3 144) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo "$res" | perl -0ne 'if (/144 =\n2\^4 \* 3\^2/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "factor_polynomial"; then echo -n "factor_polynomial...." res=$($2/factor_polynomial -threads 2 "4*x*(1+x^2+y^2*x^3+z^4)^2") if test "$?" != "0"; then echo "FAIL" exit 1 fi echo "$res" | perl -0ne 'if (/4\*x\^7\*y\^4\+8\*x\^6\*y\^2\+4\*x\^5\+8\*x\^4\*y\^2\*z\^4\+8\*x\^4\*y\^2\+8\*x\^3\*z\^4\+8\*x\^3\+4\*x\*z\^8\+8\*x\*z\^4\+4\*x =\n4\*\(x\)\^1\*\(x\^3\*y\^2\+x\^2\+z\^4\+1\)\^2/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "fmpq_poly"; then echo "fmpq_poly....SKIPPED" elif test "$1" = "fmpz_mod_poly"; then echo "fmpz_mod_poly....SKIPPED" elif test "$1" = "fmpz_poly_factor_zassenhaus"; then echo "fmpz_poly_factor_zassenhaus....SKIPPED" elif test "$1" = "fmpz_poly_q"; then echo "fmpz_poly_q....SKIPPED" elif test "$1" = "fpwrap"; then echo "fpwrap....SKIPPED" elif test "$1" = "fq_poly"; then echo "fq_poly....SKIPPED" elif test "$1" = "functions_benchmark"; then echo "functions_benchmark....SKIPPED" elif test "$1" = "hilbert_matrix"; then echo -n "hilbert_matrix...." res=$($2/hilbert_matrix -eig 20) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo "$res" | perl -0ne 'if (/prec=20: nan\nprec=40: nan\nprec=80: nan\nprec=160: nan\nprec=320: \[7\.777377397e-29 \+\/- 1.44e-39\]\nsuccess!\n/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "hilbert_matrix_ca"; then echo "hilbert_matrix_ca....SKIPPED" elif test "$1" = "huge_expr"; then echo "huge_expr....SKIPPED" elif test "$1" = "integrals"; then echo -n "integrals...." res=$($2/integrals -i 21 -threads 3) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo "$res" | perl -0ne 'if (/I21 = \[43\.3273391411077 \+\/- 4\.52e-14] \+ \[\+\/- 1\.95e-14\]\*I/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "keiper_li"; then echo "keiper_li....SKIPPED" elif test "$1" = "lcentral"; then echo "lcentral....SKIPPED" elif test "$1" = "logistic"; then echo "logistic....SKIPPED" elif test "$1" = "lvalue"; then echo "lvalue....SKIPPED" elif test "$1" = "machin"; then echo "machin....SKIPPED" elif test "$1" = "multi_crt"; then echo "multi_crt....SKIPPED" elif test "$1" = "padic"; then echo "padic....SKIPPED" elif test "$1" = "partitions"; then echo "partitions....SKIPPED" elif test "$1" = "pi"; then echo -n "pi...." res=$($2/pi 1000 -threads 2) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo "$res" | perl -0ne 'if (/\[3\.14159265358979323846\{\.\.\.959 digits\.\.\.\}76611195909216420199 \+\/- 8\.09e-1001\]/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "poly_roots"; then echo -n "poly_roots...." res=$($2/poly_roots t 10) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo "$res" | perl -0ne 'if (/\n10 roots with multiplicity 1\nsearching for 10 roots, 5 deflated\nprec=32: 5 isolated roots/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 elif test "$1" = "primegen"; then echo "primegen....SKIPPED" elif test "$1" = "qadic"; then echo "qadic....SKIPPED" elif test "$1" = "radix"; then echo "radix....SKIPPED" elif test "$1" = "real_roots"; then echo "real_roots....SKIPPED" elif test "$1" = "stirling_matrix"; then echo "stirling_matrix....SKIPPED" elif test "$1" = "swinnerton_dyer_poly"; then echo "swinnerton_dyer_poly....SKIPPED" elif test "$1" = "taylor_integrals"; then echo "taylor_integrals....SKIPPED" elif test "$1" = "zeta_zeros"; then echo -n "zeta_zeros...." res=$($2/zeta_zeros -count 100 -threads 3) if test "$?" != "0"; then echo "FAIL" exit 1 fi echo "$res" | perl -0ne 'if (/97\t231\.2501887004991648\n98\t231\.9872352531802486\n99\t233\.6934041789083006\n100\t236\.5242296658162058/) { $found=1; last } END { exit !$found }' if test "$?" != "0"; then echo "FAIL" exit 2 fi echo "PASS" exit 0 else exit 3 fi flint-3.1.3/dev/conway/000077500000000000000000000000001461254215100147115ustar00rootroot00000000000000flint-3.1.3/dev/conway/convert_cp_to_new_form.jl000066400000000000000000000523121461254215100220030ustar00rootroot00000000000000# # Copyright (C) 2024 Albin Ahlbäck # # This file is part of FLINT. # # FLINT is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License (LGPL) as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. See . # ############################################################################### ############################################################################### # helper functions ############################################################################### ############################################################################### # Example: # # str = "19,31,21" # new_str, ix = get_comma_separated_item("19,31,21") # # new_str = "19" # # ix = 4 # # str[ix:end] = "31,21" function get_comma_separated_item(str::String) ix = 2 while str[ix] != ',' ix += 1 end return (str[1:ix - 1], ix + 1) end function push_coefficients(op::String, ip::Vector{UInt}, num::UInt, finalseparator::String = ",") for ix in 1:num op *= "$(ip[ix])," end return op[1:end - 1] * finalseparator end ############################################################################### # prime < 260 ############################################################################### # Idea: Search for prime in __flint_cp_primes0, then search for corresponding # degree in __flint_cp_degrees0, then search for non-trivial coefficients in # __flint_ntcoeffs0 by using __flint_numntcoeffs0. function primes_lt_260(lines::Vector{String}) # Lines are on the form "p, deg, c_{0}, c_{1}, ..., c_{deg}" coeffs = Vector{UInt}(undef, 410) # Current line lx = 1 primes = "uint8_t __flint_cp_primes0[] = {" degrees = "uint16_t __flint_cp_degrees0[] = {" numntcoeffs = "uint8_t __flint_numntcoeffs0[] = {" ntcoeffs = "uint8_t __flint_ntcoeffs0[] = {" # Get first prime ps, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] prime = parse(UInt, ps) primes *= "$(prime - 2)," # Check that we start with the correct one ds, _ = get_comma_separated_item(lines[lx]) degree = parse(UInt, ds) if prime != 2 || degree != 1 error() end while prime < 260 # Get degree ds, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] degree = parse(UInt, ds) degrees *= "$ds," # Get coefficients for jx in 0:degree cs, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] coeffs[jx + 1] = parse(UInt, cs) end # Check that leading coefficient indeed is one if coeffs[degree + 1] != 1 error() end # Non-trivial coefficients for jx in degree:-1:1 if coeffs[jx] != 0 numntcoeffs *= "$jx," ntcoeffs = push_coefficients(ntcoeffs, coeffs, jx) break end end # Increment one line in file lx += 1 # Get new prime ps, ix = get_comma_separated_item(lines[lx]) newprime = parse(UInt, ps) if newprime != prime prime = newprime if newprime < 260 primes *= "$(newprime - 2)," end end lines[lx] = lines[lx][ix:end] end primes = primes[1:end] * "0};" degrees = degrees[1:end] * "0};" numntcoeffs = numntcoeffs[1:end - 1] * "};" ntcoeffs = ntcoeffs[1:end - 1] * "};" return lx - 1, primes, degrees, numntcoeffs, ntcoeffs end ############################################################################### # 260 < prime < 300 ############################################################################### function check_deg_1_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != b0 || coeffs[2] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_2_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^16 || coeffs[3] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_3_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != b0 || coeffs[2] >= 2^8 || coeffs[3] != 0 || coeffs[4] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_4_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^16 || coeffs[3] >= 2^8 || coeffs[4] != 0 || coeffs[5] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_5_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != b0 || coeffs[2] >= 2^8 || coeffs[3] != 0 || coeffs[4] != 0 || coeffs[5] != 0 || coeffs[6] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_6_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^16 || coeffs[3] >= 2^8 || coeffs[4] >= 2^8 || coeffs[5] >= 2^8 || coeffs[6] != 0 || coeffs[7] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_7_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != b0 || coeffs[2] >= 2^8 || coeffs[3] != 0 || coeffs[4] != 0 || coeffs[5] != 0 || coeffs[6] != 0 || coeffs[7] != 0 || coeffs[8] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_8_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^8 || coeffs[3] >= 2^16 || coeffs[4] >= 2^8 || coeffs[5] >= 2^8 || coeffs[6] != 0 || coeffs[7] != 0 || coeffs[8] != 0 || coeffs[9] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_9_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != b0 || coeffs[2] >= 2^16 || coeffs[3] >= 2^16 || coeffs[4] >= 2^8 || coeffs[5] != 0 || coeffs[6] != 0 || coeffs[7] != 0 || coeffs[8] != 0 || coeffs[9] != 0 || coeffs[10] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_10_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^16 || coeffs[3] >= 2^8 || coeffs[4] >= 2^16 || coeffs[5] >= 2^8 || coeffs[6] >= 2^16 || coeffs[7] >= 2^8 || coeffs[8] != 0 || coeffs[9] != 0 || coeffs[10] != 0 || coeffs[11] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_11_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != b0 || coeffs[2] >= 2^8 || coeffs[3] != 0 || coeffs[4] != 0 || coeffs[5] != 0 || coeffs[6] != 0 || coeffs[7] != 0 || coeffs[8] != 0 || coeffs[9] != 0 || coeffs[10] != 0 || coeffs[11] != 0 || coeffs[12] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end function check_deg_12_300(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^8 || coeffs[3] >= 2^16 || coeffs[4] >= 2^8 || coeffs[5] >= 2^8 || coeffs[6] >= 2^8 || coeffs[7] >= 2^8 || coeffs[8] >= 2^8 || coeffs[9] >= 2^8 || coeffs[10] != 0 || coeffs[11] != 0 || coeffs[12] != 0 || coeffs[13] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end # [b0, 1], # [a0, b1, 1], # [b0, a1, 0, 1], # [a0, b2, a2, 0, 1], # [b0, a3, 0, 0, 0, 1], # [a0, b3, a4, a5, a6, 0, 1], # [b0, a7, 0, 0, 0, 0, 0, 1], # [a0, a8, b4, a9, a10, 0, 0, 0, 1], # [b0, b5, b6, a11, 0, 0, 0, 0, 0, 1], # [a0, b7, a12, b8, a13, b9, a14, 0, 0, 0, 1], # [b0, a15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], # [a0, a16, b10, a17, a18, a19, a20, a21, a22, 0, 0, 0, 1], function check_coefficients_300(coeffs::Vector{Vector{UInt}}) a0 = coeffs[2][1] b0 = coeffs[1][1] check_deg_1_300(coeffs[1], a0, b0) check_deg_2_300(coeffs[2], a0, b0) check_deg_3_300(coeffs[3], a0, b0) check_deg_4_300(coeffs[4], a0, b0) check_deg_5_300(coeffs[5], a0, b0) check_deg_6_300(coeffs[6], a0, b0) check_deg_7_300(coeffs[7], a0, b0) check_deg_8_300(coeffs[8], a0, b0) check_deg_9_300(coeffs[9], a0, b0) check_deg_10_300(coeffs[10], a0, b0) check_deg_11_300(coeffs[11], a0, b0) check_deg_12_300(coeffs[12], a0, b0) end function primes_lt_300(lines::Vector{String}) coeffs = [Vector{UInt}(undef, ix + 1) for ix in 1:12] # Current line lx = 1 primes = "uint16_t __flint_cp_primes1[] = {" sm_coeffs = "uint8_t __flint_cp_sm_coeffs1[] = {" md_coeffs = "uint16_t __flint_cp_md_coeffs1[] = {" # Get first prime ps, ix = get_comma_separated_item(lines[lx]) prime = parse(UInt, ps) # Check that we start with the correct one ds, _ = get_comma_separated_item(lines[lx][ix:end]) degree = parse(UInt, ds) if prime != 263 || degree != 1 error() end while prime < 300 primes *= "$(prime)," for degree in 1:12 ps, ix = get_comma_separated_item(lines[lx]) thisprime = parse(UInt, ps) lines[lx] = lines[lx][ix:end] if thisprime != prime error("lx = $lx, degree = $degree") end ds, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] thisdegree = parse(UInt, ds) if thisdegree != degree error() end for jx in 0:degree cs, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] coeffs[degree][jx + 1] = parse(UInt, cs) end lx += 1 end check_coefficients_300(coeffs) sm_coeffs *= "$(coeffs[2][1])," sm_coeffs *= "$(coeffs[3][2])," sm_coeffs *= "$(coeffs[4][3])," sm_coeffs *= "$(coeffs[5][2])," sm_coeffs *= "$(coeffs[6][3]),$(coeffs[6][4]),$(coeffs[6][5])," sm_coeffs *= "$(coeffs[7][2])," sm_coeffs *= "$(coeffs[8][2]),$(coeffs[8][4]),$(coeffs[8][5])," sm_coeffs *= "$(coeffs[9][4])," sm_coeffs *= "$(coeffs[10][3]),$(coeffs[10][5]),$(coeffs[10][7])," sm_coeffs *= "$(coeffs[11][2])," sm_coeffs *= "$(coeffs[12][2]),$(coeffs[12][4]),$(coeffs[12][5]),$(coeffs[12][6]),$(coeffs[12][7]),$(coeffs[12][8]),$(coeffs[12][9])," md_coeffs *= "$(coeffs[1][1])," md_coeffs *= "$(coeffs[2][2])," md_coeffs *= "$(coeffs[4][2])," md_coeffs *= "$(coeffs[6][2])," md_coeffs *= "$(coeffs[8][3])," md_coeffs *= "$(coeffs[9][2]),$(coeffs[9][3])," md_coeffs *= "$(coeffs[10][2]),$(coeffs[10][4]),$(coeffs[10][6])," md_coeffs *= "$(coeffs[12][3])," # Get new prime ps, _ = get_comma_separated_item(lines[lx]) newprime = parse(UInt, ps) if newprime == prime error() end prime = newprime end primes = primes[1:end] * "0};" sm_coeffs = sm_coeffs[1:end - 1] * "};" md_coeffs = md_coeffs[1:end - 1] * "};" return lx - 1, primes, sm_coeffs, md_coeffs end ############################################################################### # 300 < prime < 2^16 ############################################################################### check_deg_1(coeffs::Vector{UInt}, a0::UInt, b0::UInt) = check_deg_1_300(coeffs, a0, b0) check_deg_2(coeffs::Vector{UInt}, a0::UInt, b0::UInt) = check_deg_2_300(coeffs, a0, b0) check_deg_3(coeffs::Vector{UInt}, a0::UInt, b0::UInt) = check_deg_3_300(coeffs, a0, b0) check_deg_4(coeffs::Vector{UInt}, a0::UInt, b0::UInt) = check_deg_4_300(coeffs, a0, b0) check_deg_5(coeffs::Vector{UInt}, a0::UInt, b0::UInt) = check_deg_5_300(coeffs, a0, b0) function check_deg_6(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^16 || coeffs[3] >= 2^16 || coeffs[4] >= 2^16 || coeffs[5] >= 2^8 || coeffs[6] != 0 || coeffs[7] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end check_deg_7(coeffs::Vector{UInt}, a0::UInt, b0::UInt) = check_deg_7_300(coeffs, a0, b0) function check_deg_8(coeffs::Vector{UInt}, a0::UInt, b0::UInt) if (coeffs[1] != a0 || coeffs[2] >= 2^16 || coeffs[3] >= 2^16 || coeffs[4] >= 2^16 || coeffs[5] >= 2^8 || coeffs[6] != 0 || coeffs[7] != 0 || coeffs[8] != 0 || coeffs[9] != 1) error("a0 = $a0, b0 = $b0\ncoeffs = $coeffs") end end check_deg_9(coeffs::Vector{UInt}, a0::UInt, b0::UInt) = check_deg_9_300(coeffs, a0, b0) # [b0, 1], # [a0, b1, 1], # [b0, a1, 0, 1], # [a0, b2, a2, 0, 1], # [b0, a3, 0, 0, 0, 1], # [a0, b3, b4, b5, a4, 0, 1], # [b0, a5, 0, 0, 0, 0, 0, 1], # [a0, b6, b7, b8, a6, 0, 0, 0, 1], # [b0, b9, b10, a7, 0, 0, 0, 0, 0, 1], # Case 2: 300 < prime < 1000 # Case 3: 1000 < prime < 3370 # Case 4: 3370 < prime < 11000 # Case 5: 11000 < prime < 2^16 function check_coefficients(coeffs::Vector{Vector{UInt}}, case::Int, special::Bool = false) if case < 2 || case > 5 error() end a0 = coeffs[2][1] b0 = coeffs[1][1] check_deg_1(coeffs[1], a0, b0) check_deg_2(coeffs[2], a0, b0) check_deg_3(coeffs[3], a0, b0) check_deg_4(coeffs[4], a0, b0) if case < 5 check_deg_5(coeffs[5], a0, b0) check_deg_6(coeffs[6], a0, b0) if case < 4 && !special check_deg_7(coeffs[7], a0, b0) if case < 3 check_deg_8(coeffs[8], a0, b0) end check_deg_9(coeffs[9], a0, b0) end end end function primes_lt_2p16(lines::Vector{String}, case::Int) if case < 2 || case > 5 error() end specialprimes = [2689, 2797, 2833, 3019, 3163, 3209, 3331] if case == 2 upperdegree = 9 startingprime = 307 upperprime = 1009 elseif case == 3 upperdegree = 9 startingprime = 1009 upperprime = 3371 elseif case == 4 upperdegree = 6 startingprime = 3371 upperprime = 11003 elseif case == 5 upperdegree = 4 startingprime = 11003 upperprime = 2^16 end coeffs = [Vector{UInt}(undef, ix + 1) for ix in 1:upperdegree] # Current line lx = 1 primes = "uint16_t __flint_cp_primes$case[] = {" sm_coeffs = "uint8_t __flint_cp_sm_coeffs$case[] = {" md_coeffs = "uint16_t __flint_cp_md_coeffs$case[] = {" # Get first prime ps, ix = get_comma_separated_item(lines[lx]) prime = parse(UInt, ps) # Check that we start with the correct one ds, _ = get_comma_separated_item(lines[lx][ix:end]) degree = parse(UInt, ds) if degree != 1 || prime != startingprime error() end while prime < upperprime primes *= "$(prime)," for degree in 1:upperdegree # Treat special cases if case == 3 if degree == 8 continue elseif degree in 7:9 && prime in specialprimes coeffs[degree] = zeros(UInt, degree + 1) continue end end ps, ix = get_comma_separated_item(lines[lx]) thisprime = parse(UInt, ps) lines[lx] = lines[lx][ix:end] if thisprime != prime error("lx = $lx, degree = $degree") end ds, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] thisdegree = parse(UInt, ds) if thisdegree != degree error() end for jx in 0:degree cs, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] coeffs[degree][jx + 1] = parse(UInt, cs) end lx += 1 end check_coefficients(coeffs, case, prime in specialprimes) sm_coeffs *= "$(coeffs[2][1])," sm_coeffs *= "$(coeffs[3][2])," sm_coeffs *= "$(coeffs[4][3])," if case < 5 sm_coeffs *= "$(coeffs[5][2])," sm_coeffs *= "$(coeffs[6][5])," if case < 4 sm_coeffs *= "$(coeffs[7][2])," if case < 3 sm_coeffs *= "$(coeffs[8][5])," end sm_coeffs *= "$(coeffs[9][4])," end end md_coeffs *= "$(coeffs[1][1])," md_coeffs *= "$(coeffs[2][2])," md_coeffs *= "$(coeffs[4][2])," if case < 5 md_coeffs *= "$(coeffs[6][2]),$(coeffs[6][3]),$(coeffs[6][4])," if case < 4 if case < 3 md_coeffs *= "$(coeffs[8][2]),$(coeffs[8][3]),$(coeffs[8][4])," end md_coeffs *= "$(coeffs[9][2]),$(coeffs[9][3])," end end # Get new prime ps, _ = get_comma_separated_item(lines[lx]) newprime = parse(UInt, ps) if newprime == prime error() end prime = newprime end primes = primes[1:end] * "0};" sm_coeffs = sm_coeffs[1:end - 1] * "};" md_coeffs = md_coeffs[1:end - 1] * "};" return lx - 1, primes, sm_coeffs, md_coeffs end ############################################################################### # 2^16 < prime < 110000 ############################################################################### function check_deg_4_gt_2p16(coeffs::Vector{UInt}) if (coeffs[1] >= 2^8 || coeffs[2] >= 2^32 || coeffs[3] >= 2^8 || coeffs[4] != 0 || coeffs[5] != 1) error("coeffs = $coeffs") end end function primes_gt_2p16(lines::Vector{String}) coeffs = Vector{UInt}(undef, 5) # Current line lx = 1 primes = "uint16_t __flint_cp_primes6[] = {" sm_coeffs = "uint8_t __flint_cp_sm_coeffs6[] = {" lg_coeffs = "uint32_t __flint_cp_lg_coeffs6[] = {" # Get first prime ps, ix = get_comma_separated_item(lines[lx]) prime = parse(UInt, ps) # Check that we start with the correct one ds, _ = get_comma_separated_item(lines[lx][ix:end]) degree = parse(UInt, ds) if degree != 4 || prime != 65537 error() end while true primes *= "$(prime - 2^16)," ps, ix = get_comma_separated_item(lines[lx]) thisprime = parse(UInt, ps) lines[lx] = lines[lx][ix:end] ds, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] thisdegree = parse(UInt, ds) if thisdegree != 4 error() end for jx in 0:degree cs, ix = get_comma_separated_item(lines[lx]) lines[lx] = lines[lx][ix:end] coeffs[jx + 1] = parse(UInt, cs) end check_deg_4_gt_2p16(coeffs) sm_coeffs *= "$(coeffs[1])," sm_coeffs *= "$(coeffs[3])," lg_coeffs *= "$(coeffs[2])," # If no more lines are to be found, break if length(lines[lx:end]) < 2 break end lx += 1 # Get new prime ps, _ = get_comma_separated_item(lines[lx]) newprime = parse(UInt, ps) if newprime <= prime error() end prime = newprime end primes = primes[1:end] * "0};" sm_coeffs = sm_coeffs[1:end - 1] * "};" lg_coeffs = lg_coeffs[1:end - 1] * "};" return lx - 1, primes, sm_coeffs, lg_coeffs end ############################################################################### ############################################################################### # main ############################################################################### ############################################################################### function main(filename::String) lines = read_lines() ix = 1 lx, p0, d0, numntcoeffs0, ntcoeffs0 = primes_lt_260(lines[ix:end]) ix += lx lx, p1, sm_coeffs1, md_coeffs1 = primes_lt_300(lines[ix:end]) ix += lx lx, p2, sm_coeffs2, md_coeffs2 = primes_lt_2p16(lines[ix:end], 2) ix += lx lx, p3, sm_coeffs3, md_coeffs3 = primes_lt_2p16(lines[ix:end], 3) ix += lx lx, p4, sm_coeffs4, md_coeffs4 = primes_lt_2p16(lines[ix:end], 4) ix += lx lx, p5, sm_coeffs5, md_coeffs5 = primes_lt_2p16(lines[ix:end], 5) ix += lx lx, p6, sm_coeffs6, lg_coeffs6 = primes_gt_2p16(lines[ix:end]) file = open(filename, "w") write(file, p0) write(file, "\n") write(file, d0) write(file, "\n") write(file, numntcoeffs0) write(file, "\n") write(file, ntcoeffs0) write(file, "\n\n") write(file, p1) write(file, "\n") write(file, sm_coeffs1) write(file, "\n") write(file, md_coeffs1) write(file, "\n\n") write(file, p2) write(file, "\n") write(file, sm_coeffs2) write(file, "\n") write(file, md_coeffs2) write(file, "\n\n") write(file, p3) write(file, "\n") write(file, sm_coeffs3) write(file, "\n") write(file, md_coeffs3) write(file, "\n\n") write(file, p4) write(file, "\n") write(file, sm_coeffs4) write(file, "\n") write(file, md_coeffs4) write(file, "\n\n") write(file, p5) write(file, "\n") write(file, sm_coeffs5) write(file, "\n") write(file, md_coeffs5) write(file, "\n\n") write(file, p6) write(file, "\n") write(file, sm_coeffs6) write(file, "\n") write(file, lg_coeffs6) write(file, "\n") close(file) end flint-3.1.3/dev/conway/notes.c000066400000000000000000000060371461254215100162130ustar00rootroot00000000000000/* prime < 260, degrees are decaying but always less than 410. Coefficients can always be stored in uint8_t. Coefficient sequences are always on the form [a0, a1, a2, ..., an, 0, 0, ..., 0, 1]. Hence, store prime, degree, number of "non-trivial" coefficients, as well as the "non-trivial" coefficients. */ /* 260 < prime < 300, degrees = 1, ..., 12. Polynomials are on the form [b0, 1], [a0, b1, 1], [b0, a1, 0, 1], [a0, b2, a2, 0, 1], [b0, a3, 0, 0, 0, 1], [a0, b3, b4, a4, a5, 0, 1], [b0, a6, 0, 0, 0, 0, 0, 1], [a0, b6, b7, b8, a7, 0, 0, 0, 1], [b0, b9, b10, a8, 0, 0, 0, 0, 0, 1], [a0, b11, b12, b13, b14, b15, 0, 0, 0, 0, 1], [b0, a9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [a0, a10, b16, a11, b17, a12, a13, a14, 0, 0, 0, 0, 1], where a0, ..., a14 < 2^8 and b0, ..., b10 < 2^16. Store prime as uint8_t with offset of 2^8, and store coefficients as 15 uint8_t with 11 uint16_t. */ /* 300 < prime < 1000, degrees = 1, ..., 9. Polynomials are on the form [b0, 1], [a0, b1, 1], [b0, a1, 0, 1], [a0, b2, a2, 0, 1], [b0, a3, 0, 0, 0, 1], [a0, b3, b4, b5, a4, 0, 1], [b0, a5, 0, 0, 0, 0, 0, 1], [a0, b6, b7, b8, a6, 0, 0, 0, 1], [b0, b9, b10, a7, 0, 0, 0, 0, 0, 1], where a0, ..., a7 < 2^8 and b0, ..., b10 < 2^16. Store prime as uint16_t, and store coefficients as 8 uint8_t with 11 uint16_t. */ /* 1000 < prime < 3371, degrees = 1, ..., 7, 9. Some exceptions exists where degree 7 and 9 does not exist. These are p = 2689, 2797, 2833, 3019, 3163, 3209 and 3331. Polynomials are on the form [b0, 1], [a0, b1, 1], [b0, a1, 0, 1], [a0, b2, a2, 0, 1], [b0, a3, 0, 0, 0, 1], [a0, b3, b4, b5, a4, 0, 1], [b0, a5, 0, 0, 0, 0, 0, 1], [b0, b6, b7, a6, 0, 0, 0, 0, 0, 1], where a0, ..., a6 < 2^8 and b0, ..., b7 < 2^16. Store prime as uint16_t, and store coefficients as 7 uint8_t with 8 uint16_t. */ /* 3371 <= prime < 11000, degrees = 1, ..., 6. Polynomials are on the form [b0, 1], [a0, b1, 1], [b0, a1, 0, 1], [a0, b2, a2, 0, 1], [b0, a3, 0, 0, 0, 1], [a0, b3, b4, b5, a4, 0, 1], where a0, ..., a4 < 2^8 and b0, ..., b5 < 2^16. Store prime as uint16_t, and store coefficients as 5 uint8_t with 6 uint16_t. */ /* 11000 < prime < 2^16, degrees = 1, ..., 4. Polynomials are on the form [b0, 1], [a0, b1, 1], [b0, a1, 0, 1], [a0, b2, a2, 0, 1], where a0, ..., a2 < 2^8 and b0, ..., b2 < 2^16. Store prime as uint16_t, and store each prime as 3 uint8_t with 3 uint16_t. */ /* 2^16 < prime, then degrees are all four. Polynomials are on the form [a0, b0, a1, 0, 1], where a0, a1 < 2^8 and b0 < 2^32. Store prime as uint16_t where everything primes are offset by 2^16, and store coefficients as 2 uint8_t with 1 uint32_t. */ flint-3.1.3/dev/find_gmp_mpfr.jl000066400000000000000000000026171461254215100165550ustar00rootroot00000000000000using GMP_jll, MPFR_jll, Artifacts import Pkg function gmp_artifact_dir() artifacts_toml = joinpath(dirname(dirname(Base.pathof(GMP_jll))), "StdlibArtifacts.toml") # If this file exists, it's a stdlib JLL and we must download the artifact ourselves if isfile(artifacts_toml) meta = artifact_meta("GMP", artifacts_toml) hash = Base.SHA1(meta["git-tree-sha1"]) if !artifact_exists(hash) dl_info = first(meta["download"]) Pkg.Artifacts.download_artifact(hash, dl_info["url"], dl_info["sha256"]) end return artifact_path(hash) end # Otherwise, we can just use the artifact directory given to us by GMP_jll return GMP_jll.find_artifact_dir() end function mpfr_artifact_dir() artifacts_toml = joinpath(dirname(dirname(Base.pathof(MPFR_jll))), "StdlibArtifacts.toml") # If this file exists, it's a stdlib JLL and we must download the artifact ourselves if isfile(artifacts_toml) meta = artifact_meta("MPFR", artifacts_toml) hash = Base.SHA1(meta["git-tree-sha1"]) if !artifact_exists(hash) dl_info = first(meta["download"]) Pkg.Artifacts.download_artifact(hash, dl_info["url"], dl_info["sha256"]) end return artifact_path(hash) end # Otherwise, we can just use the artifact directory given to us by MPFR_jll return MPFR_jll.find_artifact_dir() end flint-3.1.3/dev/gen_mul_basecase.jl000066400000000000000000001212201461254215100172120ustar00rootroot00000000000000# # Copyright (C) 2023 Albin Ahlbäck # # This file is part of FLINT. # # FLINT is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License (LGPL) as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. See . # _regs = ["%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9", "%r10", "%r11", "%rax"] # We have omitted rsp as we cannot use it unless we push it to xmm register __regs = ["%rbx", "%rbp", "%r12", "%r13", "%r14", "%r15"] function reg_8_bit(reg::String) if reg == "%rax" return "%al" elseif reg == "%rbx" return "%bl" elseif reg == "%rcx" return "%cl" elseif reg == "%rdx" return "%dl" elseif reg == "%rsp" return "%spl" elseif reg == "%rbp" return "%bpl" elseif reg == "%rsi" return "%sil" elseif reg == "%rdi" return "%dil" elseif reg == "%r8" return "%r8b" elseif reg == "%r9" return "%r9b" elseif reg == "%r10" return "%r10b" elseif reg == "%r11" return "%r11b" elseif reg == "%r12" return "%r12b" elseif reg == "%r13" return "%r13b" elseif reg == "%r14" return "%r14b" elseif reg == "%r15" return "%r15b" else return "hejhoppgummi" end end function reg_32_bit(reg::String) if reg == "%rax" return "%eax" elseif reg == "%rbx" return "%ebx" elseif reg == "%rcx" return "%ecx" elseif reg == "%rdx" return "%edx" elseif reg == "%rsp" return "%esp" elseif reg == "%rbp" return "%ebp" elseif reg == "%rsi" return "%esi" elseif reg == "%rdi" return "%edi" elseif reg == "%r8" return "%r8d" elseif reg == "%r9" return "%r9d" elseif reg == "%r10" return "%r10d" elseif reg == "%r11" return "%r11d" elseif reg == "%r12" return "%r12d" elseif reg == "%r13" return "%r13d" elseif reg == "%r14" return "%r14d" elseif reg == "%r15" return "%r15d" else return "hejhoppgummi" end end ############################################################################### # Preamble ############################################################################### copyright = "dnl dnl Copyright (C) 2023 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl\n" preamble = "include(`config.m4')\n\n\tTEXT\n" function function_pre_post(funname::String) pre = "\tALIGN(16)\n" pre *= "PROLOGUE($funname)\n" post = "EPILOGUE()\n" return (pre, post) end ############################################################################### # m = 1, n = 1 ############################################################################### function function_body_1(m::Int, n::Int = m) if m != 1 || n != 1 error() end regs = ["%rcx", "%rax", "%r8", "%r9", "%r10", "%r11"] numregs = 2 # Number of registers used r0 = regs[1] r1 = regs[2] # Important that r1 is rax res_reg = "%rdi" ap_reg = "%rsi" bp_reg = "%rdx" body = "" body *= "\tmov\t($bp_reg), %rdx\n" body *= "\tmulx\t0*8($ap_reg), $r0, $r1\n" body *= "\tmov\t$r0, 0*8($res_reg)\n" body *= "\tmov\t$r1, 1*8($res_reg)\n" return body * "\n\tret\n" end ############################################################################### # m = 2, n = 1 ############################################################################### function function_body_2_1(m::Int, n::Int = 1) if m != 2 || n != 1 error() end regs = ["%rcx", "%r8", "%rax", "%r9", "%r10", "%r11"] numregs = 5 # Number of registers used r0 = regs[1] r1 = regs[2] r2 = regs[3] # Important that r2 is rax r3 = regs[4] zero_reg = regs[numregs] zero_reg_32 = reg_32_bit(zero_reg) res_reg = "%rdi" ap_reg = "%rsi" bp_reg = "%rdx" body = "" body *= "\tmov\t0*8($bp_reg), %rdx\n" body *= "\txor\t$zero_reg_32, $zero_reg_32\n" body *= "\tmulx\t0*8($ap_reg), $r0, $r1\n" body *= "\tmulx\t1*8($ap_reg), $r3, $r2\n" body *= "\tadcx\t$r3, $r1\n" body *= "\tadcx\t$zero_reg, $r2\n" body *= "\tmov\t$r0, 0*8($res_reg)\n" body *= "\tmov\t$r1, 1*8($res_reg)\n" body *= "\tmov\t$r2, 2*8($res_reg)\n" return body * "\n\tret\n" end ############################################################################### # m = 2, n = 2 ############################################################################### function function_body_2(m::Int, n::Int = m) if m != 2 || n != 2 error() end regs = ["%rcx", "%r8", "%r9", "%rax", "%r10", "%r11"] numregs = 6 # Number of registers used r0 = regs[1] r1 = regs[2] r2 = regs[3] r3 = regs[4] # Important that r3 is rax bp1_reg = regs[numregs - 1] zero_reg = regs[numregs] zero_reg_32 = reg_32_bit(zero_reg) res_reg = "%rdi" ap_reg = "%rsi" bp_reg = "%rdx" body = "" body *= "\tmov\t1*8($bp_reg), $bp1_reg\n" body *= "\tmov\t0*8($bp_reg), %rdx\n" body *= "\txor\t$zero_reg_32, $zero_reg_32\n" body *= "\tmulx\t0*8($ap_reg), $r0, $r1\n" body *= "\tmulx\t1*8($ap_reg), $r3, $r2\n" body *= "\tadcx\t$r3, $r1\n" body *= "\tmov\t$r0, 0*8($res_reg)\n" body *= "\tmov\t$bp1_reg, %rdx\n" body *= "\tmulx\t0*8($ap_reg), $r0, $r3\n" body *= "\tadox\t$r0, $r1\n" body *= "\tadcx\t$r3, $r2\n" body *= "\tmov\t$r1, 1*8($res_reg)\n" body *= "\tmulx\t1*8($ap_reg), $r0, $r3\n" body *= "\tadox\t$r0, $r2\n" body *= "\tadcx\t$zero_reg, $r3\n" body *= "\tadox\t$zero_reg, $r3\n" body *= "\tmov\t$r2, 2*8($res_reg)\n" body *= "\tmov\t$r3, 3*8($res_reg)\n" return body * "\n\tret\n" end ############################################################################### # mul_1 and addmul_1 macros ############################################################################### # Assumes bp[0] is already in %rdx. # This pushes directly into res, apart from the last limb which is left in r5. function mul_1_macro(m::Int) if m < 3 error() end pre = ".macro\tm$(m)_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, " pre *= "r0, r1, r2, r3, r4, r5\n" post = ".endm\n" r0 = "\\r0" r1 = "\\r1" r2 = "\\r2" r3 = "\\r3" r4 = "\\r4" r5 = "\\r5" # Make sure that last limb is pushed into r5 if m % 2 == 0 r4, r5 = r5, r4 elseif m % 4 == 1 r1, r5 = r5, r1 end body = "" body *= "\tmulx\t(0+\\ap_offset)*8(\\ap), $r0, $r3\n" body *= "\tmulx\t(1+\\ap_offset)*8(\\ap), $r1, $r4\n" body *= "\tmulx\t(2+\\ap_offset)*8(\\ap), $r2, $r5\n" body *= "\tadd\t$r3, $r1\n" body *= "\tadc\t$r4, $r2\n" body *= "\tmov\t$r0, (0+\\res_offset)*8(\\res)\n" body *= "\tmov\t$r1, (1+\\res_offset)*8(\\res)\n" body *= "\tmov\t$r2, (2+\\res_offset)*8(\\res)\n" for ix in 1:(m - 1) ÷ 2 - 1 i1 = 2 * ix + 1 i2 = 2 * ix + 2 body *= "\tmulx\t($i1+\\ap_offset)*8(\\ap), $r3, $r4\n" body *= "\tmulx\t($i2+\\ap_offset)*8(\\ap), $r0, $r1\n" body *= "\tadc\t$r3, $r5\n" body *= "\tadc\t$r4, $r0\n" body *= "\tmov\t$r5, ($i1+\\res_offset)*8(\\res)\n" body *= "\tmov\t$r0, ($i2+\\res_offset)*8(\\res)\n" (r0, r2), (r3, r4), (r1, r5) = (r2, r0), (r3, r4), (r5, r1) end if m % 2 == 1 body *= "\tadc\t\$0, $r5\n" else body *= "\tmulx\t($(m - 1)+\\ap_offset)*8(\\ap), $r3, $r4\n" body *= "\tadc\t$r3, $r5\n" body *= "\tadc\t\$0, $r4\n" body *= "\tmov\t$r5, ($(m - 1)+\\res_offset)*8(\\res)\n" end return pre * body * post end # Assumes b is already in %rdx. # Pushes least significant limb into res[res_offset]. # ip1 can be aliased with rN for N > 0 and scr2 # ip2 can be aliased with rN for N > 1 function mulM_macro(n::Int; chain::Bool = false) if n < 2 || n > 8 error() end pre = ".macro\tm$(n)$(chain ? "_chain" : "") res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, " if chain pre *= "ip1, ip2, " end for jx in 0:n-1 pre *= "r$jx, " end pre *= "scr1, scr2, zero\n" post = ".endm\n" body = "" body *= "\tmulx\t(0+\\ap_offset)*8(\\ap), \\scr1, \\r0\n" if chain body *= "\tadcx\t\\ip1, \\scr1\n" body *= "\tmov\t\\scr1, \\res_offset*8(\\res)\n" end body *= "\tmulx\t(1+\\ap_offset)*8(\\ap), \\scr2, \\r1\n" if !chain body *= "\tmov\t\\scr1, \\res_offset*8(\\res)\n" end body *= "\tadcx\t\\scr2, \\r0\n" if chain body *= "\tadox\t\\ip2, \\r0\n" end for jx in 2:n ÷ 2 jxm = 2 * (jx - 1) body *= "\tmulx\t($(jxm)+\\ap_offset)*8(\\ap), \\scr1, \\r$jxm\n" body *= "\tmulx\t($(jxm + 1)+\\ap_offset)*8(\\ap), \\scr2, \\r$(jxm + 1)\n" body *= "\tadcx\t\\scr1, \\r$(jxm - 1)\n" body *= "\tadcx\t\\scr2, \\r$jxm\n" end if n % 2 == 1 body *= "\tmulx\t($(n - 1)+\\ap_offset)*8(\\ap), \\scr1, \\r$(n - 1)\n" body *= "\tadcx\t\\scr1, \\r$(n - 2)\n" end body *= "\tadcx\t\\zero, \\r$(n - 1)\n" return pre * body * post end # Assumes b is already in %rdx. # Pushes least significant limb into res[res_offset]. function addmulM_macro(n::Int) if n < 2 || n > 8 error() end pre = ".macro\tam$(n) res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, " for jx in 0:n pre *= "r$jx, " end pre *= "scr, zero\n" post = ".endm\n" scr1 = "\\r$n" scr2 = "\\scr" if n % 2 == 1 # If n is odd, we need to reorder scr1 and scr2 to make \scr occur at # the right place so that we do not need two scrap registers in the last # multiplication. tmp = scr1 scr1 = scr2 scr2 = tmp end body = "" body *= "\tmulx\t(0+\\ap_offset)*8(\\ap), $scr1, $scr2\n" body *= "\tadcx\t$scr1, \\r0\n" body *= "\tmov\t\\r0, \\res_offset*8(\\res)\n" for jx in 1:n - 1 body *= "\tmulx\t($(jx)+\\ap_offset)*8(\\ap), \\r0, $(jx % 2 == 1 ? scr1 : scr2)\n" body *= "\tadcx\t$(jx % 2 == 0 ? scr1 : scr2), \\r$jx\n" body *= "\tadox\t\\r0, \\r$jx\n" end body *= "\tadcx\t\\zero, \\r$n\n" body *= "\tadox\t\\zero, \\r$n\n" return pre * body * post end ############################################################################### # m ≥ 3, n = 1 ############################################################################### function function_body_M_1(m::Int) if m < 3 error() end body = "\tmov\t0*8(%rdx), %rdx\n" # Important that the last entry is rax to set return value body *= "\tm$(m)_str\t%rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax\n" body *= "\tmov\t%rax, $m*8(%rdi)\n" return body * "\n\tret\n" end ############################################################################### # m > 8, n = 2 ############################################################################### function M_2_getN(m::Int) if m <= 8 error() elseif m <= 9 return 3 elseif m <= 12 return 4 elseif m <= 15 return 5 elseif m <= 16 return 6 else error() end end # Needed macros: mN, amN_chain, mN_chain (if m ÷ N == 2), # m(m % N)_chain (if m % N > 1) and am(m % N) (if m % N > 1). function function_body_M_2(m::Int) if m <= 8 error() end N = M_2_getN(m) # number of available registers is 10 regs = ["%rax", "%r9", "%r10", "%r11", "%rbx", "%rbp", "%r12", "%r13", "%r14", "%r15"] preserve_index = 5 # Starting with %rbx, we have to push it to the stack used_registers = N + 3 res = "%rdi" ap = "%rsi" bp = "%rdx" b0 = "%rcx" b1 = "%r8" if used_registers > length(regs) error() end pre = "\tmov\t0*8($bp), $b0\n" pre *= "\tmov\t1*8($bp), $b1\n" post = "" for jx in preserve_index:used_registers pre = pre * "\tpush\t$(regs[jx])\n" post = "\tpop\t$(regs[jx])\n" * post end rg = deepcopy(regs[1:used_registers]) if m % N == 0 && (m ÷ N) % 2 == 1 rg[1], rg[N + 1] = rg[N + 1], rg[1] elseif m % N == 1 rg[1], rg[4] = rg[4], rg[1] elseif m % N > 1 && (m ÷ N) % 2 == 0 rg[1], rg[N + 1] = rg[N + 1], rg[1] end scr = rg[N + 2] zero = rg[N + 3] body = "" body *= "\n" body *= "\tmov\t$b0, %rdx\n" body *= "\txor\t$(reg_32_bit(zero)), $(reg_32_bit(zero))\n" body *= "\tm$N\t$res, 0, $ap, 0, " for jx in 2:N body *= "$(rg[jx]), " end body *= "$(rg[1]), $(rg[N + 1]), $scr, $zero\n" body *= "\tmov\t$b1, %rdx\n" body *= "\tam$(N)\t$res, 1, $ap, 0, " for jx in 2:N body *= "$(rg[jx]), " end body *= "$(rg[1]), $(rg[N + 1]), $scr, $zero\n" for jx in 3:N body *= "\tmov\t$(rg[jx]), $(jx - 1)*8($res)\n" end for ix in 1:m ÷ N - 1 body *= "\n" body *= "\tmov\t$b0, %rdx\n" body *= "\tm$(N)_chain\t$res, $(ix * N), $ap, $(ix * N), $(rg[1]), $(rg[N + 1]), " for jx in 2:N body *= "$(rg[jx]), " end body *= "$(rg[N + 1]), $scr, $(rg[1]), $zero\n" body *= "\tmov\t$b1, %rdx\n" body *= "\tam$(N)\t$res, $(ix * N + 1), $ap, $(ix * N), " for jx in 2:N body *= "$(rg[jx]), " end body *= "$(rg[N + 1]), $(rg[1]), $scr, $zero\n" for jx in 3:N body *= "\tmov\t$(rg[jx]), $(jx + ix * N - 1)*8($res)\n" end rg[1], rg[N + 1] = rg[N + 1], rg[1] end body *= "\n" if m % N == 0 body *= "\tmov\t$(rg[1]), $(m)*8($res)\n" body *= "\tmov\t$(rg[N + 1]), $(m + 1)*8($res)\n" elseif m % N == 1 body *= "\tmov\t$b0, %rdx\n" body *= "\tmulx\t$((m ÷ N) * N)*8($ap), $(rg[2]), $scr\n" body *= "\tmov\t$b1, %rdx\n" body *= "\tmulx\t$((m ÷ N) * N)*8($ap), $(rg[3]), $(rg[4])\n" body *= "\tadcx\t$(rg[1]), $(rg[2])\n" body *= "\tadcx\t$(rg[N + 1]), $(rg[3])\n" body *= "\tadcx\t$zero, $(rg[4])\n" body *= "\tadox\t$scr, $(rg[3])\n" body *= "\tadox\t$zero, $(rg[4])\n" body *= "\tmov\t$(rg[2]), $((m ÷ N) * N + 0)*8($res)\n" body *= "\tmov\t$(rg[3]), $((m ÷ N) * N + 1)*8($res)\n" body *= "\tmov\t$(rg[4]), $((m ÷ N) * N + 2)*8($res)\n" else body *= "\tmov\t$b0, %rdx\n" body *= "\tm$(m % N)_chain\t$res, $((m ÷ N) * N + 0), $ap, $((m ÷ N) * N), $(rg[1]), $(rg[N + 1]), " for jx in 2:m % N + 1 body *= "$(rg[jx]), " end body *= "$scr, $(rg[1]), $zero\n" body *= "\tmov\t$b1, %rdx\n" body *= "\tam$(m % N)\t$res, $((m ÷ N) * N + 1), $ap, $((m ÷ N) * N), " for jx in 2:m % N + 1 body *= "$(rg[jx]), " end body *= "$(rg[1]), $scr, $zero\n" for jx in 3:m % N + 1 body *= "\tmov\t$(rg[jx]), $((m ÷ N) * N + jx - 1)*8($res)\n" end body *= "\tmov\t$(rg[1]), $(m + 1)*8($res)\n" end return pre * body * post * "\n\tret\n" end ############################################################################### # 3 ≤ m ≤ 8, 2 ≤ n ≤ m, or m > 8, 2 ≤ n ≤ 8 ############################################################################### function function_body_M(m::Int, n::Int = m) if !((3 ≤ m ≤ 8 && 2 ≤ n ≤ m) || (m > 8 && 2 ≤ n ≤ 8)) error() end if m ≤ 8 res_reg = "%rdi" ap_reg = "%rsi" bp_reg_old = "%rdx" bp_reg = "%rcx" mov = "\tmov\t$bp_reg_old, $bp_reg\n" else res_reg = "%rdi" ap_reg_old = "%rdx" # is actually bp ap_reg = "%rcx" bp_reg = "%rsi" mov = "\tmov\t$ap_reg_old, $ap_reg\n" m, n = n, m end regs = ["%rax", "%r8", "%r9", "%r10", "%r11", "%rbx", "%rbp", "%r12", "%r13", "%r14", "%r15"] preserve_index = 6 # Starting with %rbx, we have to push it to the stack numregs = m + 3 # Number of registers used regs_perm = deepcopy(regs[1:m + 1]) # We want the most significant limb to fall on rax if n == 2 regs_perm[1], regs_perm[m + 1] = regs_perm[m + 1], regs_perm[1] else regs_perm[1], regs_perm[((n - 3) % (m + 1)) + 1] = regs_perm[((n - 3) % (m + 1)) + 1], regs_perm[1] end scr_reg = regs[numregs - 1] zero_reg = regs[numregs] zero_reg_32 = reg_32_bit(zero_reg) pre = mov pre *= "\tmov\t0*8($bp_reg), %rdx\n" body = "" post = "" for jx in preserve_index:numregs pre = pre * "\tpush\t$(regs[jx])\n" post = "\tpop\t$(regs[jx])\n" * post end body *= "\n" body *= "\txor\t$zero_reg_32, $zero_reg_32\n" body *= "\n" body *= "\tm$m\t$res_reg, 0, $ap_reg, 0, " for jx in 1:m body *= "$(regs_perm[jx]), " end body *= "$(regs_perm[m + 1]), $scr_reg, $zero_reg\n\n" for jx in 1:n - 1 body *= "\tmov\t$jx*8($bp_reg), %rdx\n" body *= "\tam$m\t$res_reg, $jx, $ap_reg, 0, " for kx in 1:m + 1 body *= "$(regs_perm[kx]), " end body *= "$scr_reg, $zero_reg\n" # Reorder registers regs_perm[1:m], regs_perm[m + 1] = regs_perm[2:m + 1], regs_perm[1] end body *= "\n" for jx in 1:m body *= "\tmov\t$(regs_perm[jx]), $(n + jx - 1)*8($res_reg)\n" end body *= "\n" return pre * body * post * "\n\tret\n" end ############################################################################### # sqr ############################################################################### # NOTE: Aliasing must work for squaring. # NOTE: Although this could be generally programmed, just like the mul case, # we can skip some instructions and additional storage when hardcoding each # case. function function_body_sqr_1() regs = ["%rcx", "%rax"] r0 = regs[1] r1 = regs[2] # Important that r1 is rax res_reg = "%rdi" ap_reg = "%rsi" body = "" body *= "\tmov\t0*8($ap_reg), %rdx\n" body *= "\tmulx\t%rdx, $r0, $r1\n" body *= "\tmov\t$r0, 0*8($res_reg)\n" body *= "\tmov\t$r1, 1*8($res_reg)\n" return body * "\n\tret\n" end function function_body_sqr_2() n = 2 res = _regs[1] ap = _regs[2] this_regs = [_regs[4:end - 1]; __regs] w = this_regs[1:3] s1 = this_regs[4] s2 = _regs[end] pre = "\tmov\t0*8($ap), %rdx\n" post = "" body = "" # Calculate upper triangle body *= "\txor\t$(reg_32_bit(w[3])), $(reg_32_bit(w[3]))\n" body *= "\tmulx\t1*8($ap), $(w[1]), $(w[2])\n" body *= "\tadd\t$(w[1]), $(w[1])\n" body *= "\tadc\t$(w[2]), $(w[2])\n" body *= "\tadc\t$(w[3]), $(w[3])\n" # Calculate diagonal and put into res body *= "\tmulx\t%rdx, $s1, $s2\n" body *= "\tmov\t$s1, 0*8($res)\n" body *= "\tadd\t$s2, $(w[1])\n" body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tmov\t$(w[1]), 1*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" body *= "\tadc\t$s1, $(w[2])\n" body *= "\tadc\t$(w[3]), $s2\n" body *= "\tmov\t$(w[2]), 2*8($res)\n" body *= "\tmov\t$s2, 3*8($res)\n" return pre * body * post * "\n\tret\n" end function function_body_sqr_3() n = 3 res = _regs[1] ap = _regs[2] this_regs = [_regs[4:end - 1]; __regs] w = this_regs[1:5] scr = _regs[end] pre = "\tmov\t0*8($ap), %rdx\n" post = "" body = "" # Calculate upper triangle body *= "\txor\t$(reg_32_bit(w[5])), $(reg_32_bit(w[5]))\n" body *= "\tmulx\t1*8($ap), $(w[1]), $scr\n" # a0 a1 body *= "\tmulx\t2*8($ap), $(w[2]), $(w[3])\n" # a0 a2 body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tadd\t$scr, $(w[2])\n" body *= "\tmulx\t2*8($ap), $scr, $(w[4])\n" # a1 a2 body *= "\tadc\t$scr, $(w[3])\n" body *= "\tadc\t$(w[5]), $(w[4])\n" # Double upper triangle body *= "\tmov\t0*8($ap), %rdx\n" body *= "\tadd\t$(w[1]), $(w[1])\n" body *= "\tadc\t$(w[2]), $(w[2])\n" body *= "\tadc\t$(w[3]), $(w[3])\n" body *= "\tadc\t$(w[4]), $(w[4])\n" body *= "\tadc\t$(w[5]), $(w[5])\n" # Calculate diagonal and put into res body *= "\tmulx\t%rdx, %rdx, $scr\n" # a0^2 body *= "\tmov\t%rdx, 0*8($res)\n" body *= "\tadd\t$scr, $(w[1])\n" body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tmov\t$(w[1]), 1*8($res)\n" body *= "\tmulx\t%rdx, %rdx, $scr\n" # a1^2 body *= "\tadc\t%rdx, $(w[2])\n" body *= "\tadc\t$scr, $(w[3])\n" body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tmov\t$(w[2]), 2*8($res)\n" body *= "\tmov\t$(w[3]), 3*8($res)\n" body *= "\tmulx\t%rdx, %rdx, $scr\n" # a2^2 body *= "\tadc\t%rdx, $(w[4])\n" body *= "\tadc\t$(w[5]), $scr\n" body *= "\tmov\t$(w[4]), 4*8($res)\n" body *= "\tmov\t$scr, 5*8($res)\n" return pre * body * post * "\n\tret\n" end function function_body_sqr_4() n = 4 res = _regs[1] ap = _regs[2] this_regs = [_regs[4:end - 1]; __regs] w = this_regs[1:2 * n - 1] s1 = "error s1" s2 = _regs[end] # Important that this is rax pre = "\tmov\t0*8($ap), %rdx\n" post = "" for jx in 1:2 * n - 1 - length(_regs[4:end - 1]) pre = pre * "\tpush\t$(__regs[jx])\n" post = "\tpop\t$(__regs[jx])\n" * post end body = "" # Calculate upper triangle body *= "\txor\t$(reg_32_bit(w[7])), $(reg_32_bit(w[7]))\n" body *= "\tmulx\t1*8($ap), $(w[1]), $(w[5])\n" # a0 a1 body *= "\tmulx\t2*8($ap), $(w[2]), $(w[6])\n" # a0 a2 body *= "\tmulx\t3*8($ap), $(w[3]), $(w[4])\n" # a0 a3 body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tadox\t$(w[5]), $(w[2])\n" # ADOX body *= "\tadox\t$(w[6]), $(w[3])\n" body *= "\tmulx\t2*8($ap), $(w[5]), $(w[6])\n" # a1 a2 body *= "\tadcx\t$(w[5]), $(w[3])\n" # ADCX body *= "\tadcx\t$(w[6]), $(w[4])\n" body *= "\tmulx\t3*8($ap), $(w[6]), $(w[5])\n" # a1 a3 body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tadox\t$(w[6]), $(w[4])\n" # ADOX body *= "\tadox\t$(w[7]), $(w[5])\n" # Add zero body *= "\tmulx\t3*8($ap), %rdx, $(w[6])\n" # a2 a3 body *= "\tadcx\t%rdx, $(w[5])\n" # ADCX body *= "\tadc\t$(w[7]), $(w[6])\n" # Add zero # Double upper triangle body *= "\tmov\t0*8($ap), %rdx\n" body *= "\tadd\t$(w[1]), $(w[1])\n" body *= "\tadc\t$(w[2]), $(w[2])\n" body *= "\tadc\t$(w[3]), $(w[3])\n" body *= "\tadc\t$(w[4]), $(w[4])\n" body *= "\tadc\t$(w[5]), $(w[5])\n" body *= "\tadc\t$(w[6]), $(w[6])\n" body *= "\tsetc\t$(reg_8_bit(w[7]))\n" # Calculate diagonal and put into res body *= "\tmulx\t%rdx, %rdx, $s2\n" # a0^2 body *= "\tmov\t%rdx, 0*8($res)\n" body *= "\tadd\t$s2, $(w[1])\n" body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tmov\t$(w[1]), 1*8($res)\n" s1 = w[1] w[1] = "error w[1]" body *= "\tmulx\t%rdx, %rdx, $s2\n" # a1^2 body *= "\tadc\t%rdx, $(w[2])\n" body *= "\tadc\t$s2, $(w[3])\n" body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tmov\t$(w[2]), 2*8($res)\n" body *= "\tmov\t$(w[3]), 3*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a2^2 body *= "\tadc\t$s1, $(w[4])\n" body *= "\tadc\t$s2, $(w[5])\n" body *= "\tmov\t3*8($ap), %rdx\n" body *= "\tmov\t$(w[4]), 4*8($res)\n" body *= "\tmov\t$(w[5]), 5*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a3^2 body *= "\tadc\t$s1, $(w[6])\n" body *= "\tadc\t$(w[7]), $s2\n" body *= "\tmov\t$(w[6]), 6*8($res)\n" body *= "\tmov\t$s2, 7*8($res)\n" return pre * body * post * "\n\tret\n" end function function_body_sqr_5() n = 5 res = _regs[1] ap = _regs[2] this_regs = [_regs[4:end - 1]; __regs] w = this_regs[1:2 * n - 1] s1 = "" s2 = _regs[end] # Important that this is rax pre = "\tmov\t0*8($ap), %rdx\n" post = "" for jx in 1:2 * n - 1 - length(_regs[4:end - 1]) pre = pre * "\tpush\t$(__regs[jx])\n" post = "\tpop\t$(__regs[jx])\n" * post end body = "" # Calculate upper triangle body *= "\txor\t$(reg_32_bit(w[9])), $(reg_32_bit(w[9]))\n" body *= "\tmulx\t1*8($ap), $(w[1]), $(w[6])\n" # a0 a1 body *= "\tmulx\t2*8($ap), $(w[2]), $(w[7])\n" # a0 a2 body *= "\tmulx\t3*8($ap), $(w[3]), $(w[8])\n" # a0 a3 body *= "\tmulx\t4*8($ap), $(w[4]), $(w[5])\n" # a0 a4 body *= "\tadcx\t$(w[6]), $(w[2])\n" body *= "\tadcx\t$(w[7]), $(w[3])\n" body *= "\tadcx\t$(w[8]), $(w[4])\n" body *= "\tadcx\t$(w[9]), $(w[5])\n" # Add zero body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tmulx\t2*8($ap), $(w[8]), $(w[6])\n" # a1 a2 body *= "\tadcx\t$(w[8]), $(w[3])\n" # ADCX body *= "\tadcx\t$(w[6]), $(w[4])\n" body *= "\tmulx\t3*8($ap), $(w[8]), $(w[6])\n" # a1 a3 body *= "\tadox\t$(w[8]), $(w[4])\n" # ADOX body *= "\tadox\t$(w[6]), $(w[5])\n" body *= "\tmulx\t4*8($ap), $(w[8]), $(w[6])\n" # a1 a4 body *= "\tadcx\t$(w[8]), $(w[5])\n" # ADCX body *= "\tadcx\t$(w[9]), $(w[6])\n" # Add zero body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tmulx\t3*8($ap), $(w[8]), $(w[7])\n" # a2 a3 body *= "\tadcx\t$(w[8]), $(w[5])\n" # ADCX body *= "\tadcx\t$(w[7]), $(w[6])\n" body *= "\tmulx\t4*8($ap), $(w[8]), $(w[7])\n" # a2 a4 body *= "\tadox\t$(w[8]), $(w[6])\n" # ADOX body *= "\tadox\t$(w[9]), $(w[7])\n" # Add zero body *= "\tmov\t3*8($ap), %rdx\n" body *= "\tmulx\t4*8($ap), %rdx, $(w[8])\n" # a3 a4 body *= "\tadcx\t%rdx, $(w[7])\n" # ADCX body *= "\tadc\t$(w[9]), $(w[8])\n" # Add zero # Double upper triangle body *= "\tmov\t0*8($ap), %rdx\n" body *= "\tadd\t$(w[1]), $(w[1])\n" body *= "\tadc\t$(w[2]), $(w[2])\n" body *= "\tadc\t$(w[3]), $(w[3])\n" body *= "\tadc\t$(w[4]), $(w[4])\n" body *= "\tadc\t$(w[5]), $(w[5])\n" body *= "\tadc\t$(w[6]), $(w[6])\n" body *= "\tadc\t$(w[7]), $(w[7])\n" body *= "\tadc\t$(w[8]), $(w[8])\n" body *= "\tadc\t$(w[9]), $(w[9])\n" # Calculate diagonal and put into res body *= "\tmulx\t%rdx, %rdx, $s2\n" # a0^2 body *= "\tmov\t%rdx, 0*8($res)\n" body *= "\tadd\t$s2, $(w[1])\n" body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tmov\t$(w[1]), 1*8($res)\n" s1 = w[1] w[1] = "error w[1]" body *= "\tmulx\t%rdx, %rdx, $s2\n" # a1^2 body *= "\tadc\t%rdx, $(w[2])\n" body *= "\tadc\t$s2, $(w[3])\n" body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tmov\t$(w[2]), 2*8($res)\n" body *= "\tmov\t$(w[3]), 3*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a2^2 body *= "\tadc\t$s1, $(w[4])\n" body *= "\tadc\t$s2, $(w[5])\n" body *= "\tmov\t3*8($ap), %rdx\n" body *= "\tmov\t$(w[4]), 4*8($res)\n" body *= "\tmov\t$(w[5]), 5*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a3^2 body *= "\tadc\t$s1, $(w[6])\n" body *= "\tadc\t$s2, $(w[7])\n" body *= "\tmov\t4*8($ap), %rdx\n" body *= "\tmov\t$(w[6]), 6*8($res)\n" body *= "\tmov\t$(w[7]), 7*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a4^2 body *= "\tadc\t$s1, $(w[8])\n" body *= "\tadc\t$(w[9]), $s2\n" body *= "\tmov\t$(w[8]), 8*8($res)\n" body *= "\tmov\t$s2, 9*8($res)\n" return pre * body * post * "\n\tret\n" end function function_body_sqr_6() n = 6 res = _regs[1] ap = _regs[2] this_regs = [_regs[4:end - 1]; __regs] w = this_regs[1:2 * n - 1] s1 = "error s1" s2 = _regs[end] # Important that this is rax pre = "\tmov\t0*8($ap), %rdx\n" post = "" for jx in 1:6 pre = pre * "\tpush\t$(__regs[jx])\n" post = "\tpop\t$(__regs[jx])\n" * post end body = "" # Calculate upper triangle body *= "\txor\t$(reg_32_bit(w[11])), $(reg_32_bit(w[11]))\n" body *= "\tmulx\t1*8($ap), $(w[1]), $(w[7])\n" # a0 a1 body *= "\tmulx\t2*8($ap), $(w[2]), $(w[8])\n" # a0 a2 body *= "\tmulx\t3*8($ap), $(w[3]), $(w[9])\n" # a0 a3 body *= "\tmulx\t4*8($ap), $(w[4]), $(w[10])\n" # a0 a4 body *= "\tmulx\t5*8($ap), $(w[5]), $(w[6])\n" # a0 a5 body *= "\tadcx\t$(w[7]), $(w[2])\n" body *= "\tadcx\t$(w[8]), $(w[3])\n" body *= "\tadcx\t$(w[9]), $(w[4])\n" body *= "\tadcx\t$(w[10]), $(w[5])\n" body *= "\tadcx\t$(w[11]), $(w[6])\n" # Add zero body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tmulx\t2*8($ap), $(w[10]), $(w[7])\n" # a1 a2 body *= "\tadcx\t$(w[10]), $(w[3])\n" # ADCX body *= "\tadcx\t$(w[7]), $(w[4])\n" body *= "\tmulx\t3*8($ap), $(w[10]), $(w[7])\n" # a1 a3 body *= "\tadox\t$(w[10]), $(w[4])\n" # ADOX body *= "\tadox\t$(w[7]), $(w[5])\n" body *= "\tmulx\t4*8($ap), $(w[10]), $(w[7])\n" # a1 a4 body *= "\tadcx\t$(w[10]), $(w[5])\n" # ADCX body *= "\tadcx\t$(w[7]), $(w[6])\n" body *= "\tmulx\t5*8($ap), $(w[10]), $(w[7])\n" # a1 a5 body *= "\tadox\t$(w[10]), $(w[6])\n" # ADOX body *= "\tadox\t$(w[11]), $(w[7])\n" # Add zero body *= "\tadcx\t$(w[11]), $(w[7])\n" # Add zero body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tmulx\t3*8($ap), $(w[10]), $(w[8])\n" # a2 a3 body *= "\tadcx\t$(w[10]), $(w[5])\n" # ADCX body *= "\tadcx\t$(w[8]), $(w[6])\n" body *= "\tmulx\t4*8($ap), $(w[10]), $(w[8])\n" # a2 a4 body *= "\tadox\t$(w[10]), $(w[6])\n" # ADOX body *= "\tadox\t$(w[8]), $(w[7])\n" body *= "\tmulx\t5*8($ap), $(w[10]), $(w[8])\n" # a2 a5 body *= "\tadcx\t$(w[10]), $(w[7])\n" # ADCX body *= "\tadcx\t$(w[11]), $(w[8])\n" # Add zero body *= "\tmov\t3*8($ap), %rdx\n" body *= "\tmulx\t4*8($ap), $(w[10]), $(w[9])\n" # a3 a4 body *= "\tadcx\t$(w[10]), $(w[7])\n" # ADCX body *= "\tadcx\t$(w[9]), $(w[8])\n" body *= "\tmulx\t5*8($ap), $(w[10]), $(w[9])\n" # a3 a5 body *= "\tadox\t$(w[10]), $(w[8])\n" # ADOX body *= "\tadox\t$(w[11]), $(w[9])\n" # Add zero body *= "\tmov\t4*8($ap), %rdx\n" body *= "\tmulx\t5*8($ap), %rdx, $(w[10])\n" # a4 a5 body *= "\tadcx\t%rdx, $(w[9])\n" # ADCX body *= "\tadc\t$(w[11]), $(w[10])\n" # Add zero # Double upper triangle body *= "\tmov\t0*8($ap), %rdx\n" body *= "\tadd\t$(w[1]), $(w[1])\n" body *= "\tadc\t$(w[2]), $(w[2])\n" body *= "\tadc\t$(w[3]), $(w[3])\n" body *= "\tadc\t$(w[4]), $(w[4])\n" body *= "\tadc\t$(w[5]), $(w[5])\n" body *= "\tadc\t$(w[6]), $(w[6])\n" body *= "\tadc\t$(w[7]), $(w[7])\n" body *= "\tadc\t$(w[8]), $(w[8])\n" body *= "\tadc\t$(w[9]), $(w[9])\n" body *= "\tadc\t$(w[10]), $(w[10])\n" body *= "\tsetc\t$(reg_8_bit(w[11]))\n" # Calculate diagonal and put into res body *= "\tmulx\t%rdx, %rdx, $s2\n" # a0^2 body *= "\tmov\t%rdx, 0*8($res)\n" body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tadd\t$s2, $(w[1])\n" body *= "\tmov\t$(w[1]), 1*8($res)\n" s1 = w[1] w[1] = "error w[1]" body *= "\tmulx\t%rdx, %rdx, $s2\n" # a1^2 body *= "\tadc\t%rdx, $(w[2])\n" body *= "\tadc\t$s2, $(w[3])\n" body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tmov\t$(w[2]), 2*8($res)\n" body *= "\tmov\t$(w[3]), 3*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a2^2 body *= "\tadc\t$s1, $(w[4])\n" body *= "\tadc\t$s2, $(w[5])\n" body *= "\tmov\t3*8($ap), %rdx\n" body *= "\tmov\t$(w[4]), 4*8($res)\n" body *= "\tmov\t$(w[5]), 5*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a3^2 body *= "\tadc\t$s1, $(w[6])\n" body *= "\tadc\t$s2, $(w[7])\n" body *= "\tmov\t4*8($ap), %rdx\n" body *= "\tmov\t$(w[6]), 6*8($res)\n" body *= "\tmov\t$(w[7]), 7*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a4^2 body *= "\tadc\t$s1, $(w[8])\n" body *= "\tadc\t$s2, $(w[9])\n" body *= "\tmov\t5*8($ap), %rdx\n" body *= "\tmov\t$(w[8]), 8*8($res)\n" body *= "\tmov\t$(w[9]), 9*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a5^2 body *= "\tadc\t$s1, $(w[10])\n" body *= "\tadc\t$(w[11]), $s2\n" body *= "\tmov\t$(w[10]), 10*8($res)\n" body *= "\tmov\t$s2, 11*8($res)\n" return pre * body * post * "\n\tret\n" end function function_body_sqr_7() n = 7 res = _regs[1] ap = _regs[2] this_regs = [_regs[4:end - 1]; __regs] w = [this_regs[1:3]; _regs[end]; this_regs[5:11]; ["error w[$ix]" for ix in 12:2 * n - 2]] s1 = "error s1" s2 = "error s2" zero = this_regs[4] pre = "\tmov\t0*8($ap), %rdx\n" post = "" for jx in 1:6 pre = pre * "\tpush\t$(__regs[jx])\n" post = "\tpop\t$(__regs[jx])\n" * post end body = "" # Calculate upper triangle body *= "\txor\t$(reg_32_bit(zero)), $(reg_32_bit(zero))\n" body *= "\tmulx\t1*8($ap), $(w[1]), $(w[5])\n" # a0 a1 body *= "\tmulx\t2*8($ap), $(w[2]), $(w[6])\n" # a0 a2 body *= "\tmulx\t3*8($ap), $(w[3]), $(w[10])\n" # a0 a3 body *= "\tadcx\t$(w[5]), $(w[2])\n" body *= "\tadcx\t$(w[6]), $(w[3])\n" body *= "\tmulx\t4*8($ap), $(w[4]), $(w[8])\n" # a0 a4 body *= "\tmulx\t5*8($ap), $(w[5]), $(w[9])\n" # a0 a5 body *= "\tmulx\t6*8($ap), $(w[6]), $(w[7])\n" # a0 a6 body *= "\tadcx\t$(w[10]), $(w[4])\n" body *= "\tadcx\t$(w[8]), $(w[5])\n" body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tadcx\t$(w[9]), $(w[6])\n" body *= "\tadcx\t$zero, $(w[7])\n" body *= "\tmulx\t2*8($ap), $(w[10]), $(w[8])\n" # a1 a2 body *= "\tmulx\t3*8($ap), $(w[11]), $(w[9])\n" # a1 a3 body *= "\tadcx\t$(w[10]), $(w[3])\n" # ADCX body *= "\tadcx\t$(w[8]), $(w[4])\n" body *= "\tadox\t$(w[11]), $(w[4])\n" # ADOX body *= "\tadox\t$(w[9]), $(w[5])\n" body *= "\tmulx\t4*8($ap), $(w[10]), $(w[8])\n" # a1 a4 body *= "\tmulx\t5*8($ap), $(w[11]), $(w[9])\n" # a1 a5 body *= "\tadcx\t$(w[10]), $(w[5])\n" # ADCX body *= "\tadcx\t$(w[8]), $(w[6])\n" body *= "\tmulx\t6*8($ap), $(w[10]), $(w[8])\n" # a1 a6 body *= "\tadox\t$(w[11]), $(w[6])\n" # ADOX body *= "\tadox\t$(w[9]), $(w[7])\n" body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tadcx\t$(w[10]), $(w[7])\n" # ADCX body *= "\tadox\t$zero, $(w[8])\n" body *= "\tadcx\t$zero, $(w[8])\n" body *= "\tmulx\t3*8($ap), $(w[11]), $(w[9])\n" # a2 a3 body *= "\tadox\t$(w[11]), $(w[5])\n" # ADOX body *= "\tadox\t$(w[9]), $(w[6])\n" body *= "\tmulx\t4*8($ap), $(w[11]), $(w[9])\n" # a2 a4 body *= "\tadcx\t$(w[11]), $(w[6])\n" # ADCX body *= "\tadcx\t$(w[9]), $(w[7])\n" body *= "\tmulx\t5*8($ap), $(w[11]), $(w[9])\n" # a2 a5 body *= "\tadox\t$(w[11]), $(w[7])\n" # ADOX body *= "\tadox\t$(w[9]), $(w[8])\n" body *= "\tmulx\t6*8($ap), $(w[11]), $(w[9])\n" # a2 a6 body *= "\tadcx\t$(w[11]), $(w[8])\n" # ADCX body *= "\tadox\t$zero, $(w[9])\n" body *= "\tmov\t3*8($ap), %rdx\n" body *= "\tadcx\t$zero, $(w[9])\n" body *= "\tmulx\t4*8($ap), $(w[11]), $(w[10])\n" # a3 a4 body *= "\tadcx\t$(w[11]), $(w[7])\n" # ADCX body *= "\tadcx\t$(w[10]), $(w[8])\n" body *= "\tmulx\t5*8($ap), $(w[11]), $(w[10])\n" # a3 a5 body *= "\tadox\t$(w[11]), $(w[8])\n" # ADOX body *= "\tadox\t$(w[10]), $(w[9])\n" body *= "\tmulx\t6*8($ap), $(w[11]), $(w[10])\n" # a3 a6 body *= "\tmov\t4*8($ap), %rdx\n" body *= "\tadcx\t$(w[11]), $(w[9])\n" # ADCX body *= "\tadcx\t$zero, $(w[10])\n" w[12] = zero zero = "error zero" body *= "\tmulx\t5*8($ap), $(w[12]), $(w[11])\n" # a4 a5 body *= "\tadcx\t$(w[12]), $(w[9])\n" # ADCX body *= "\tadcx\t$(w[11]), $(w[10])\n" body *= "\tmulx\t6*8($ap), $(w[12]), $(w[11])\n" # a4 a6 body *= "\tmov\t\$0, %edx\n" body *= "\tadox\t$(w[12]), $(w[10])\n" # ADOX body *= "\tadox\t%rdx, $(w[11])\n" body *= "\tmov\t5*8($ap), %rdx\n" body *= "\tmulx\t6*8($ap), %rdx, $(w[12])\n" # a5 a6 body *= "\tadcx\t%rdx, $(w[11])\n" # ADCX body *= "\tadc\t\$0, $(w[12])\n" body *= "\ttest\t%al, %al\n" # Double upper triangle body *= "\tmov\t0*8($ap), %rdx\n" body *= "\tadcx\t$(w[1]), $(w[1])\n" body *= "\tadcx\t$(w[2]), $(w[2])\n" body *= "\tadcx\t$(w[3]), $(w[3])\n" body *= "\tadcx\t$(w[4]), $(w[4])\n" body *= "\tadcx\t$(w[5]), $(w[5])\n" body *= "\tadcx\t$(w[6]), $(w[6])\n" body *= "\tpush\t$(w[4])\n" body *= "\tadcx\t$(w[7]), $(w[7])\n" body *= "\tadcx\t$(w[8]), $(w[8])\n" body *= "\tadcx\t$(w[9]), $(w[9])\n" body *= "\tadcx\t$(w[10]), $(w[10])\n" body *= "\tadcx\t$(w[11]), $(w[11])\n" body *= "\tadcx\t$(w[12]), $(w[12])\n" # Calculate diagonal and put into res s2 = w[4] w[4] = "error w[4]" body *= "\tmulx\t%rdx, %rdx, $s2\n" # a0^2 body *= "\tmov\t%rdx, 0*8($res)\n" body *= "\tadox\t$s2, $(w[1])\n" body *= "\tmov\t1*8($ap), %rdx\n" body *= "\tmov\t$(w[1]), 1*8($res)\n" w[4] = w[1] w[1] = "error w[1]" body *= "\tmulx\t%rdx, %rdx, $s2\n" # a1^2 body *= "\tadox\t%rdx, $(w[2])\n" body *= "\tadox\t$s2, $(w[3])\n" body *= "\tpop\t$(w[4])\n" body *= "\tmov\t2*8($ap), %rdx\n" body *= "\tmov\t$(w[2]), 2*8($res)\n" body *= "\tmov\t$(w[3]), 3*8($res)\n" s1 = w[2] w[2] = "error w[2]" body *= "\tmulx\t%rdx, %rdx, $s2\n" # a2^2 body *= "\tadox\t%rdx, $(w[4])\n" body *= "\tadox\t$s2, $(w[5])\n" body *= "\tmov\t3*8($ap), %rdx\n" body *= "\tmov\t$(w[4]), 4*8($res)\n" body *= "\tmov\t$(w[5]), 5*8($res)\n" zero = w[4] w[4] = "error w[4]" body *= "\tmulx\t%rdx, $s1, $s2\n" # a3^2 body *= "\tadox\t$s1, $(w[6])\n" body *= "\tadox\t$s2, $(w[7])\n" body *= "\tmov\t4*8($ap), %rdx\n" body *= "\tmov\t$(w[6]), 6*8($res)\n" body *= "\tmov\t$(w[7]), 7*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a4^2 body *= "\tadox\t$s1, $(w[8])\n" body *= "\tadox\t$s2, $(w[9])\n" body *= "\tmov\t5*8($ap), %rdx\n" body *= "\tmov\t$(w[8]), 8*8($res)\n" body *= "\tmov\t$(w[9]), 9*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a5^2 body *= "\tadox\t$s1, $(w[10])\n" body *= "\tadox\t$s2, $(w[11])\n" body *= "\tmov\t\$0, $(reg_32_bit(zero))\n" body *= "\tmov\t6*8($ap), %rdx\n" body *= "\tmov\t$(w[10]), 10*8($res)\n" body *= "\tmov\t$(w[11]), 11*8($res)\n" body *= "\tmulx\t%rdx, $s1, $s2\n" # a6^2 body *= "\tadox\t$s1, $(w[12])\n" body *= "\tadox\t$zero, $s2\n" body *= "\tadcx\t$zero, $s2\n" body *= "\tmov\t$(w[12]), 12*8($res)\n" body *= "\tmov\t$s2, 13*8($res)\n" return pre * body * post * "\n\tret\n" end ############################################################################### # Generate file ############################################################################### function gen_mul(m::Int, n::Int, file) (pre, post) = function_pre_post("flint_mpn_mul_$(m)_$n") functionbody = "" if m == 1 && n == 1 functionbody = function_body_1(m, n) elseif m == 2 && n == 1 functionbody = function_body_2_1(m, n) elseif m == 2 && n == 2 functionbody = function_body_2(m, n) elseif n == 1 macros = mul_1_macro(m) functionbody = function_body_M_1(m) elseif m ≤ 8 functionbody = function_body_M(m, n) elseif m > 8 && n != 2 functionbody = function_body_M(m, n) elseif n == 2 functionbody = function_body_M_2(m) else error("This won't work for m = $m and n = $n") end str = "$pre$functionbody$post\n" write(file, str) end function gen_sqr(m::Int, file) (pre, post) = function_pre_post("flint_mpn_sqr_$m") functionbody = "" if m == 1 functionbody = function_body_sqr_1() elseif m == 2 functionbody = function_body_sqr_2() elseif m == 3 functionbody = function_body_sqr_3() elseif m == 4 functionbody = function_body_sqr_4() elseif m == 5 functionbody = function_body_sqr_5() elseif m == 6 functionbody = function_body_sqr_6() elseif m == 7 functionbody = function_body_sqr_7() else error("This won't work for m = $m") end str = "$pre$functionbody$post\n" write(file, str) end function gen_all() path = String(@__DIR__) * "/../src/mpn_extras/broadwell/mul_hard.asm" file = open(path, "w") write(file, "$copyright\n$preamble\n") macros = "" for mx in 3:16 macros *= mul_1_macro(mx) * "\n" end for mx in 3:8 macros *= mulM_macro(mx) * "\n" end as = Int[] for mx in 9:16 N = M_2_getN(mx) if mx ÷ N >= 2 append!(as, N) end if mx % N > 1 append!(as, mx % N) end end unique!(as) for mx in as macros *= mulM_macro(mx, chain = true) * "\n" end for mx in 2:8 macros *= addmulM_macro(mx) * "\n" end write(file, macros) for mx in 1:16 for nx in 1:min(mx, 8) gen_mul(mx, nx, file) end end close(file) path = String(@__DIR__) * "/../src/mpn_extras/broadwell/sqr_hard.asm" file = open(path, "w") write(file, "$copyright\n$preamble\n") for mx in 1:7 gen_sqr(mx, file) end close(file) end flint-3.1.3/dev/gen_mul_basecase.py000066400000000000000000000106641461254215100172460ustar00rootroot00000000000000# # Copyright (C) 2023 Fredrik Johansson # # This file is part of FLINT. # # FLINT is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License (LGPL) as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. See . # """ Generic version of mul_n: void flint_mpn_mul_n_basecase(mp_ptr res, mp_srcptr u, mp_srcptr v, mp_size_t n) { mp_limb_t b, a; slong i; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); for (i = 2; i < n; i++) NN_DOTREV_S3_A3_1X1(b, a, res[i], 0, b, a, u, v, i + 1); for (i = n; i < 2 * n - 2; i++) NN_DOTREV_S3_A3_1X1(b, a, res[i], 0, b, a, u + i - n + 1, v + i - n + 1, 2 * n - i - 1); NN_ADDMUL_S2_A2_1X1(res[2 * n - 1], res[2 * n - 2], b, a, u[n - 1], v[n - 1]); } The compiler may refuse to unroll the nested loops, so we generate the code. Schema for a general n x m multiply (here n = 7, m = 4): v0 u0 u1 u2 u3 u4 u5 u6 . v1 u0 u1 u2 u3 u4 u5 u6 . v2 u0 u1 u2 u3 u4 u5 u6 . v3 u0 u1 u2 u3 u4 u5 u6 . """ def mul1v(n): print("mp_limb_t flint_mpn_mul_%i_1v(mp_ptr res, mp_srcptr u, mp_limb_t v0)" % n) print("{") print(" mp_limb_t a;") print(" NN_MUL_1X1(a, res[0], u[0], v0);") for i in range(1, n-1): print(" NN_ADDMUL_S2_A2_1X1(a, res[%i], 0, a, u[%i], v0);" % (i, i)) print(" NN_ADDMUL_S2_A2_1X1(a, res[%i], 0, a, u[%i], v0);" % (n - 1, n - 1)) print(" return a;") print("}") def mulnm(n, m): if m == 1: print("mp_limb_t flint_mpn_mul_%i_1(mp_ptr res, mp_srcptr u, mp_srcptr v)" % n) print("{") print(" mp_limb_t a, v0 = v[0];") print(" NN_MUL_1X1(a, res[0], u[0], v0);") for i in range(1, n-1): print(" NN_ADDMUL_S2_A2_1X1(a, res[%i], 0, a, u[%i], v0);" % (i, i)) print(" NN_ADDMUL_S2_A2_1X1(res[%i], res[%i], 0, a, u[%i], v0);" % (n, n - 1, n - 1)) print(" return res[%i];" % n) print("}") elif m == 2: print("mp_limb_t flint_mpn_mul_%i_%i(mp_ptr res, mp_srcptr u, mp_srcptr v)" % (n, m)) print("{") print(" mp_limb_t b, a;") print(" mp_limb_t w[2];") print(" w[0] = v[0];") print(" w[1] = v[1];") print(" NN_MUL_1X1(a, res[0], u[0], w[0]);") print(" NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, w, 2);") for i in range(2, m): print(" NN_DOTREV_S3_A3_1X1(b, a, res[%i], 0, b, a, u, w, %i);" % (i, i + 1)) for i in range(m, n): print(" NN_DOTREV_S3_A3_1X1(b, a, res[%i], 0, b, a, u + %i, w, %i);" % (i, i - m + 1, m)) for i in range(n, n+m-2): print(" NN_DOTREV_S3_A3_1X1(b, a, res[%i], 0, b, a, u + %i, w + %i, %i);" % (i, i - m + 1, i - n + 1, n + m - i - 1)) print(" NN_ADDMUL_S2_A2_1X1(res[%i], res[%i], b, a, u[%i], w[%i]);" % (n + m - 1, n + m - 2, n - 1, m - 1)) print(" return res[%i];" % (n + m - 1)) print("}") else: print("mp_limb_t flint_mpn_mul_%i_%i(mp_ptr res, mp_srcptr u, mp_srcptr v)" % (n, m)) print("{") print(" mp_limb_t b, a;") print(" NN_MUL_1X1(a, res[0], u[0], v[0]);") print(" NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2);") for i in range(2, m): print(" NN_DOTREV_S3_A3_1X1(b, a, res[%i], 0, b, a, u, v, %i);" % (i, i + 1)) for i in range(m, n): print(" NN_DOTREV_S3_A3_1X1(b, a, res[%i], 0, b, a, u + %i, v, %i);" % (i, i - m + 1, m)) for i in range(n, n+m-2): print(" NN_DOTREV_S3_A3_1X1(b, a, res[%i], 0, b, a, u + %i, v + %i, %i);" % (i, i - m + 1, i - n + 1, n + m - i - 1)) print(" NN_ADDMUL_S2_A2_1X1(res[%i], res[%i], b, a, u[%i], v[%i]);" % (n + m - 1, n + m - 2, n - 1, m - 1)) print(" return res[%i];" % (n + m - 1)) print("}") for n in range(2, 8): for m in range(1, n+1): if n >= 8 and m >= 5: print("void flint_mpn_mul_%i_%i(mp_ptr res, mp_srcptr u, mp_srcptr v)" % (n, m)) print("{") print(" __gmpn_mul_basecase(res, u, %i, v, %i);" % (n, m)) print("}") else: mulnm(n, m) print() print() for n in range(8, 17): mulnm(n, 1) print() #mulnm(n, 2) #print() flint-3.1.3/dev/gen_mulhigh_basecase.jl000066400000000000000000000440401461254215100200560ustar00rootroot00000000000000# # Copyright (C) 2024 Albin Ahlbäck # # This file is part of FLINT. # # FLINT is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License (LGPL) as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. See . # _regs = ["%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9", "%r10", "%r11", "%rax"] __regs = ["%rbx", "%rbp", "%r12", "%r13", "%r14", "%r15"] function R8(reg::String) if reg == "%rax" return "%al" elseif reg == "%rbx" return "%bl" elseif reg == "%rcx" return "%cl" elseif reg == "%rdx" return "%dl" elseif reg == "%rsp" return "%spl" elseif reg == "%rbp" return "%bpl" elseif reg == "%rsi" return "%sil" elseif reg == "%rdi" return "%dil" elseif reg == "%r8" return "%r8b" elseif reg == "%r9" return "%r9b" elseif reg == "%r10" return "%r10b" elseif reg == "%r11" return "%r11b" elseif reg == "%r12" return "%r12b" elseif reg == "%r13" return "%r13b" elseif reg == "%r14" return "%r14b" elseif reg == "%r15" return "%r15b" else return "hejhoppgummi" end end function R32(reg::String) if reg == "%rax" return "%eax" elseif reg == "%rbx" return "%ebx" elseif reg == "%rcx" return "%ecx" elseif reg == "%rdx" return "%edx" elseif reg == "%rsp" return "%esp" elseif reg == "%rbp" return "%ebp" elseif reg == "%rsi" return "%esi" elseif reg == "%rdi" return "%edi" elseif reg == "%r8" return "%r8d" elseif reg == "%r9" return "%r9d" elseif reg == "%r10" return "%r10d" elseif reg == "%r11" return "%r11d" elseif reg == "%r12" return "%r12d" elseif reg == "%r13" return "%r13d" elseif reg == "%r14" return "%r14d" elseif reg == "%r15" return "%r15d" else return "hejhoppgummi" end end ############################################################################### # Preamble ############################################################################### copyright = "dnl dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl\n" preamble = "include(`config.m4')\n\n\tTEXT\n" function function_pre_post(funname::String) pre = "\tALIGN(16)\n" pre *= "PROLOGUE($funname)\n" post = "EPILOGUE()\n" return (pre, post) end ############################################################################### # mulhigh, hardcoded ############################################################################### function mulhigh_1() r0 = _regs[9] # Important that r0 is rax r1 = _regs[4] res = _regs[1] ap = _regs[2] bp = _regs[3] body = "" body *= "\tmov\t0*8($bp), %rdx\n" body *= "\tmulx\t0*8($ap), $r0, $r1\n" body *= "\tmov\t$r1, 0*8($res)\n" return body * "\n\tret\n" end function mulhigh_2() r0 = _regs[9] r1 = _regs[4] r2 = _regs[5] sc = _regs[6] zr = _regs[7] res = _regs[1] ap = _regs[2] bp_old = _regs[3] b1 = _regs[8] body = "" body *= "\tmov\t1*8($bp_old), $b1\n" body *= "\tmov\t0*8($bp_old), %rdx\n" body *= "\txor\t$(R32(zr)), $(R32(zr))\n" body *= "\tmulx\t0*8($ap), $sc, $r0\n" body *= "\tmulx\t1*8($ap), $sc, $r1\n" body *= "\tadcx\t$sc, $r0\n" body *= "\tadcx\t$zr, $r1\n" body *= "\tmov\t$b1, %rdx\n" body *= "\tmulx\t0*8($ap), $sc, $r2\n" body *= "\tadcx\t$sc, $r0\n" body *= "\tadcx\t$r2, $r1\n" body *= "\tmulx\t1*8($ap), $sc, $r2\n" body *= "\tadox\t$sc, $r1\n" body *= "\tadox\t$zr, $r2\n" body *= "\tadcx\t$zr, $r2\n" body *= "\tmov\t$r1, 0*8($res)\n" body *= "\tmov\t$r2, 1*8($res)\n" return body * "\n\tret\n" end # When n = 9, push res to stack. # When n = 10, push res and rsp to xmm register. # When n = 11, do it like n = 10, and also use bp as r(11) as r(11) is only # really needed in the last step. # When n = 12, do it like n = 11 but do not use a zero register. function mulhigh(n::Int; debug::Bool = false) if n < 1 error() elseif n == 1 return mulhigh_1() elseif n == 2 return mulhigh_2() elseif n <= 12 # Continue else error() end if debug res = "res" ap = "ap" bp_old = "bp_old" bp = "bp" sc = "sc" zr = "zr" else res = _regs[1] ap = _regs[2] bp_old = _regs[3] # rdx bp = _regs[4] # rdx is used by mulx, so we need to switch register for bp if n != 12 sc = _regs[5] # scrap register zr = (n < 10) ? _regs[6] : "%rsp" # zero else sc = "%rsp" zr = sc end if n < 9 _r = [_regs[9]; _regs[7:8]; __regs[1:n - 2]] elseif n == 9 _r = [_regs[9]; _regs[7:8]; __regs[1:6]; res] elseif n == 10 _r = [_regs[9]; _regs[6:8]; __regs[1:6]; res] elseif n == 11 _r = [_regs[9]; _regs[6:8]; __regs[1:6]; res; bp] elseif n == 12 _r = [_regs[9]; _regs[5:8]; __regs[1:6]; res; bp] end end r(ix::Int) = debug ? "r$ix" : _r[ix + 1] # Push body = "" for ix in 1:min(n - 2, 6) body *= "\tpush\t$(__regs[ix])\n" end if n == 9 body *= "\tpush\t$res\n" elseif n >= 10 body *= "\tvmovq\t%rsp, %xmm0\n" body *= "\tvmovq\t$res, %xmm1\n" end body *= "\n" # Prepare body *= "\tmov\t$bp_old, $bp\n" body *= "\tmov\t0*8($bp_old), %rdx\n" if n != 12 body *= "\txor\t$(R32(zr)), $(R32(zr))\n" end body *= "\n" # First multiplication chain body *= "\tmulx\t$(n - 2)*8($ap), $sc, $(r(0))\n" body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(1))\n" if n != 12 body *= "\tadcx\t$sc, $(r(0))\n" body *= "\tadcx\t$zr, $(r(1))\n" else body *= "\tadd\t$sc, $(r(0))\n" body *= "\tadc\t\$0, $(r(1))\n" body *= "\ttest\t%al, %al\n" end body *= "\n" # Intermediate multiplication chains for ix in 1:min(n - 2, (n != 12) ? 8 : 9) body *= "\tmov\t$ix*8($bp), %rdx\n" body *= "\tmulx\t$(n - 2 - ix)*8($ap), $sc, $(r(ix + 2))\n" body *= "\tmulx\t$(n - 1 - ix)*8($ap), $sc, $(r(ix + 1))\n" body *= "\tadcx\t$(r(ix + 2)), $(r(0))\n" body *= "\tadox\t$sc, $(r(0))\n" body *= "\tadcx\t$(r(ix + 1)), $(r(1))\n" for jx in 1:ix - 1 body *= "\tmulx\t$(n - 1 - ix + jx)*8($ap), $sc, $(r(ix + 1))\n" body *= "\tadox\t$sc, $(r(jx + 0))\n" body *= "\tadcx\t$(r(ix + 1)), $(r(jx + 1))\n" end body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(ix + 1))\n" body *= "\tadox\t$sc, $(r(ix + 0))\n" if n == 12 body *= "\tmov\t\$0, $(R32(zr))\n" end body *= "\tadcx\t$zr, $(r(ix + 1))\n" body *= "\tadox\t$zr, $(r(ix + 1))\n" body *= "\n" end if n >= 11 N = n - 1 body *= "\tmov\t$(n - 2)*8($bp), %rdx\n" for ix in 0:n - 2 body *= "\tmulx\t$ix*8($ap), $sc, $(r(N))\n" if ix == 0 body *= "\tadcx\t$(r(N)), $(r(ix + 0))\n" else body *= "\tadox\t$sc, $(r(ix - 1))\n" body *= "\tadcx\t$(r(N)), $(r(ix + 0))\n" end end body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(N))\n" body *= "\tadox\t$sc, $(r(N - 1))\n" if n == 12 body *= "\tmov\t\$0, $(R32(zr))\n" end body *= "\tadcx\t$zr, $(r(N))\n" body *= "\tadox\t$zr, $(r(N))\n" body *= "\n" end # Last multiplication chain body *= "\tmov\t$(n - 1)*8($bp), %rdx\n" for ix in 0:n - 2 body *= "\tmulx\t$ix*8($ap), $sc, $(r(n))\n" if ix % 2 == 0 body *= "\tadcx\t$sc, $(r(ix + 0))\n" body *= "\tadcx\t$(r(n)), $(r(ix + 1))\n" else body *= "\tadox\t$sc, $(r(ix + 0))\n" body *= "\tadox\t$(r(n)), $(r(ix + 1))\n" end end body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(n))\n" if (n - 1) % 2 == 0 body *= "\tadcx\t$sc, $(r(n - 1))\n" else body *= "\tadox\t$sc, $(r(n - 1))\n" end if n == 12 body *= "\tmov\t\$0, $(R32(zr))\n" end body *= "\tadcx\t$zr, $(r(n))\n" if n == 9 # Use scrap register for storing pointer to res res = sc body *= "\tpop\t$res\n" end body *= "\tadox\t$zr, $(r(n))\n" body *= "\n" if n == 10 || n == 11 res, zr = sc, "error zr" body *= "\tvmovq\t%xmm1, $res\n" body *= "\tvmovq\t%xmm0, %rsp\n" elseif n == 12 res = sc body *= "\tvmovq\t%xmm1, $res\n" end # Store result for ix in 1:n body *= "\tmov\t$(r(ix)), $(ix - 1)*8($res)\n" end body *= "\n" # Pop if n == 12 body *= "\tvmovq\t%xmm0, %rsp\n" end for ix in min(n - 2, 6):-1:1 body *= "\tpop\t$(__regs[ix])\n" end body *= "\n" if debug print(body * "\tret\n") else return body * "\tret\n" end end ############################################################################### # mulhigh, normalised ############################################################################### function mulhigh_normalised_1() r0 = _regs[9] # Important that r0 is rax r1 = _regs[4] res = _regs[1] ap = _regs[2] bp = _regs[3] body = "" body *= "\tmov\t0*8($bp), %rdx\n" body *= "\tmulx\t0*8($ap), $r0, $r1\n" # Check if normalised body *= "\tmov\t\$0, %rdx\n" body *= "\ttest\t$r1, $r1\n" body *= "\tsetns\t$(R8("%rdx"))\n" body *= "\tjs\tL(1)\n" # If not normalised, shift by one body *= "\tadd\t$r0, $r0\n" body *= "\tadc\t$r1, $r1\n" body *= "L(1):\n" body *= "\tmov\t$r1, 0*8($res)\n" return body * "\n\tret\n" end function mulhigh_normalised_2() r0 = _regs[9] r1 = _regs[4] r2 = _regs[5] sc = _regs[6] zr = _regs[7] res = _regs[1] ap = _regs[2] bp_old = _regs[3] b1 = _regs[8] body = "" body *= "\tmov\t1*8($bp_old), $b1\n" body *= "\tmov\t0*8($bp_old), %rdx\n" body *= "\txor\t$(R32(zr)), $(R32(zr))\n" body *= "\tmulx\t0*8($ap), $sc, $r0\n" body *= "\tmulx\t1*8($ap), $sc, $r1\n" body *= "\tadcx\t$sc, $r0\n" body *= "\tadcx\t$zr, $r1\n" body *= "\tmov\t$b1, %rdx\n" body *= "\tmulx\t0*8($ap), $sc, $r2\n" body *= "\tadcx\t$sc, $r0\n" body *= "\tadcx\t$r2, $r1\n" body *= "\tmulx\t1*8($ap), $sc, $r2\n" body *= "\tadox\t$sc, $r1\n" body *= "\tadox\t$zr, $r2\n" body *= "\tadcx\t$zr, $r2\n" # Check if normalised body *= "\tmov\t\$0, %rdx\n" body *= "\ttest\t$r2, $r2\n" body *= "\tsetns\t$(R8("%rdx"))\n" body *= "\tjs\tL(2)\n" # If not normalised, shift by one body *= "\tadd\t$r0, $r0\n" body *= "\tadc\t$r1, $r1\n" body *= "\tadc\t$r2, $r2\n" body *= "L(2):\n" body *= "\tmov\t$r1, 0*8($res)\n" body *= "\tmov\t$r2, 1*8($res)\n" return body * "\n\tret\n" end function mulhigh_normalised(n::Int; debug::Bool = false) if n < 1 error() elseif n == 1 return mulhigh_normalised_1() elseif n == 2 return mulhigh_normalised_2() elseif n <= 12 # Continue else error() end if debug res = "res" ap = "ap" bp_old = "bp_old" bp = "bp" sc = "sc" zr = "zr" else res = _regs[1] ap = _regs[2] bp_old = _regs[3] # rdx bp = _regs[4] # rdx is used by mulx, so we need to switch register for bp if n != 12 sc = _regs[5] # scrap register zr = (n < 10) ? _regs[6] : "%rsp" # zero else sc = "%rsp" zr = sc end if n < 9 _r = [_regs[9]; _regs[7:8]; __regs[1:n - 2]] elseif n == 9 _r = [_regs[9]; _regs[7:8]; __regs[1:6]; res] elseif n == 10 _r = [_regs[9]; _regs[6:8]; __regs[1:6]; res] elseif n == 11 _r = [_regs[9]; _regs[6:8]; __regs[1:6]; res; bp] elseif n == 12 _r = [_regs[9]; _regs[5:8]; __regs[1:6]; res; bp] end end r(ix::Int) = debug ? "r$ix" : _r[ix + 1] # Push body = "" for ix in 1:min(n - 2, 6) body *= "\tpush\t$(__regs[ix])\n" end if n == 9 body *= "\tpush\t$res\n" elseif n >= 10 body *= "\tvmovq\t%rsp, %xmm0\n" body *= "\tvmovq\t$res, %xmm1\n" end body *= "\n" # Prepare body *= "\tmov\t$bp_old, $bp\n" body *= "\tmov\t0*8($bp_old), %rdx\n" if n != 12 body *= "\txor\t$(R32(zr)), $(R32(zr))\n" end body *= "\n" # First multiplication chain body *= "\tmulx\t$(n - 2)*8($ap), $sc, $(r(0))\n" body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(1))\n" if n != 12 body *= "\tadcx\t$sc, $(r(0))\n" body *= "\tadcx\t$zr, $(r(1))\n" else body *= "\tadd\t$sc, $(r(0))\n" body *= "\tadc\t\$0, $(r(1))\n" body *= "\ttest\t%al, %al\n" end body *= "\n" # Intermediate multiplication chains for ix in 1:min(n - 2, (n != 12) ? 8 : 9) body *= "\tmov\t$ix*8($bp), %rdx\n" body *= "\tmulx\t$(n - 2 - ix)*8($ap), $sc, $(r(ix + 2))\n" body *= "\tmulx\t$(n - 1 - ix)*8($ap), $sc, $(r(ix + 1))\n" body *= "\tadcx\t$(r(ix + 2)), $(r(0))\n" body *= "\tadox\t$sc, $(r(0))\n" body *= "\tadcx\t$(r(ix + 1)), $(r(1))\n" for jx in 1:ix - 1 body *= "\tmulx\t$(n - 1 - ix + jx)*8($ap), $sc, $(r(ix + 1))\n" body *= "\tadox\t$sc, $(r(jx + 0))\n" body *= "\tadcx\t$(r(ix + 1)), $(r(jx + 1))\n" end body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(ix + 1))\n" body *= "\tadox\t$sc, $(r(ix + 0))\n" if n == 12 body *= "\tmov\t\$0, $(R32(zr))\n" end body *= "\tadcx\t$zr, $(r(ix + 1))\n" body *= "\tadox\t$zr, $(r(ix + 1))\n" body *= "\n" end if n >= 11 N = n - 1 body *= "\tmov\t$(n - 2)*8($bp), %rdx\n" for ix in 0:n - 2 body *= "\tmulx\t$ix*8($ap), $sc, $(r(N))\n" if ix == 0 body *= "\tadcx\t$(r(N)), $(r(ix + 0))\n" else body *= "\tadox\t$sc, $(r(ix - 1))\n" body *= "\tadcx\t$(r(N)), $(r(ix + 0))\n" end end body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(N))\n" body *= "\tadox\t$sc, $(r(N - 1))\n" if n == 12 body *= "\tmov\t\$0, $(R32(zr))\n" end body *= "\tadcx\t$zr, $(r(N))\n" body *= "\tadox\t$zr, $(r(N))\n" body *= "\n" end # Last multiplication chain body *= "\tmov\t$(n - 1)*8($bp), %rdx\n" for ix in 0:n - 2 body *= "\tmulx\t$ix*8($ap), $sc, $(r(n))\n" if ix % 2 == 0 body *= "\tadcx\t$sc, $(r(ix + 0))\n" body *= "\tadcx\t$(r(n)), $(r(ix + 1))\n" else body *= "\tadox\t$sc, $(r(ix + 0))\n" body *= "\tadox\t$(r(n)), $(r(ix + 1))\n" end end body *= "\tmulx\t$(n - 1)*8($ap), $sc, $(r(n))\n" if (n - 1) % 2 == 0 body *= "\tadcx\t$sc, $(r(n - 1))\n" else body *= "\tadox\t$sc, $(r(n - 1))\n" end if n == 12 body *= "\tmov\t\$0, $(R32(zr))\n" end body *= "\tadcx\t$zr, $(r(n))\n" if n == 9 # Use scrap register for storing pointer to res res = sc body *= "\tpop\t$res\n" end body *= "\tadox\t$zr, $(r(n))\n" body *= "\n" # Check if normalised body *= "\tmov\t\$0, %rdx\n" body *= "\ttest\t$(r(n)), $(r(n))\n" body *= "\tsetns\t$(R8("%rdx"))\n" body *= "\tjs\tL($n)\n" # If not normalised, shift by one body *= "\tadd\t$(r(0)), $(r(0))\n" for ix in 1:n body *= "\tadc\t$(r(ix)), $(r(ix))\n" end body *= "L($n):\n" if n == 10 || n == 11 res, zr = sc, "error zr" body *= "\tvmovq\t%xmm1, $res\n" body *= "\tvmovq\t%xmm0, %rsp\n" elseif n == 12 res = sc body *= "\tvmovq\t%xmm1, $res\n" end # Store result for ix in 1:n body *= "\tmov\t$(r(ix)), $(ix - 1)*8($res)\n" end body *= "\n" # Pop if n == 12 body *= "\tvmovq\t%xmm0, %rsp\n" end for ix in min(n - 2, 6):-1:1 body *= "\tpop\t$(__regs[ix])\n" end body *= "\n" if debug print(body * "\tret\n") else return body * "\tret\n" end end ############################################################################### # Generate file ############################################################################### function gen_mulhigh(m::Int, file) (pre, post) = function_pre_post("flint_mpn_mulhigh_$m") functionbody = mulhigh(m) str = "$pre$functionbody$post\n" write(file, str) end function gen_mulhigh_normalised(m::Int, file) (pre, post) = function_pre_post("flint_mpn_mulhigh_normalised_$m") functionbody = mulhigh_normalised(m) str = "$pre$functionbody$post\n" write(file, str) end function gen_all() # mulhigh path = String(@__DIR__) * "/../src/mpn_extras/broadwell/mulhigh_hard.asm" file = open(path, "w") write(file, "$copyright\n$preamble\n") for m in 1:12 gen_mulhigh(m, file) end close(file) # mulhigh_normalised path = String(@__DIR__) * "/../src/mpn_extras/broadwell/mulhigh_normalised_hard.asm" file = open(path, "w") write(file, "$copyright\n$preamble\n") for m in 1:12 gen_mulhigh_normalised(m, file) end close(file) end flint-3.1.3/dev/make_dist.sh000077500000000000000000000027461461254215100157210ustar00rootroot00000000000000#!/usr/bin/env bash # # This script is called by `make dist` and `.github/workflows/release.yml` # in order to create a flint release tarball. It must be called from within # the root directory of the flint source tree. # set -ex # first argument: the FLINT version in the form 1.2.3 or 1.2.3-something # if not given, uses the version in the VERSION file flint_version=$1 # second, optional argument: the git revision from which to make the # release; default is to use the HEAD commit. git_ref=${2:-HEAD} # prefix used for the content of the tarball, and also the basename of # the final archive. archive_prefix="flint-$flint_version" echo "Exporting from git" git archive --format tar.gz --prefix "${archive_prefix}/" ${git_ref} > ${archive_prefix}.tar.gz echo "Extracting" tar -xf ${archive_prefix}.tar.gz rm ${archive_prefix}.tar.gz echo "Adding / patching / removing files" # copy some files that should be included in the distribution archive cp -r config ${archive_prefix}/ cp configure ${archive_prefix}/ cp src/config.h.in ${archive_prefix}/src/ # remove some things we don't want to install cd ${archive_prefix} rm -rf .[a-z]* # no dot files rm -rf dev # update VERSION file printf $flint_version > VERSION # return to top directory cd .. # create the source archives echo "Create .tar.gz" tar -cvzf ${archive_prefix}.tar.gz ${archive_prefix} echo "Create .tar.xz" tar -cJf ${archive_prefix}.tar.xz ${archive_prefix} echo "Create .zip" zip -9 -r ${archive_prefix}.zip ${archive_prefix} flint-3.1.3/doc/000077500000000000000000000000001461254215100134005ustar00rootroot00000000000000flint-3.1.3/doc/Makefile000066400000000000000000000011471461254215100150430ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = -j=auto SPHINXBUILD = sphinx-build SPHINXPROJ = Flint SOURCEDIR = source BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) flint-3.1.3/doc/entrypoint.sh000077500000000000000000000001601461254215100161470ustar00rootroot00000000000000#!/bin/bash cd doc apt-get update apt-get -y install python3-sphinx make make latexpdf SPHINXOPTS="-W -j auto" flint-3.1.3/doc/latex/000077500000000000000000000000001461254215100145155ustar00rootroot00000000000000flint-3.1.3/doc/latex/flint-manual.bib000066400000000000000000000362341461254215100175720ustar00rootroot00000000000000@INPROCEEDINGS{AbbottBronsteinMulders1999, author = {Abbott, John and Bronstein, Manuel and Mulders, Thom}, title = {Fast deterministic computation of determinants of dense matrices}, booktitle = {In proceedings of ACM International Symposium on Symbolic and Algebraic Computation}, year = {1999}, pages = {1997-2004}, publisher = {ACM Press} } @BOOK{Apostol1997, author = {Apostol, Tom}, title = {Modular functions and Dirichlet series in number theory}, year = {1997}, publisher = {Springer}, edition = {Second}, } @ARTICLE{ArnoldMonagan2011, author = {Arnold, Andrew and Monagan, Michael}, title = {Calculating cyclotomic polynomials}, journal = {Mathematics of Computation}, volume = {80}, number = {276}, month = {October}, year = {2011}, pages = {2359--2379} } @ARTICLE{BaiWag1980, author = {Baillie, Robert and Wagstaff, Samuel S., Jr.}, title = {{L}ucas Pseudoprimes}, journal = {Mathematics of Computation}, year = {1980}, volume = {35}, pages = {pp. 1391--1417}, number = {152}, abstract = {We define several types of pseudoprimes with respect to Lucas sequences and prove the analogs of various theorems about ordinary pseudoprimes. For example, we show that Lucas pseudoprimes are rare and we count the Lucas sequences modulo $n$ with respect to which $n$ is a Lucas pseudoprime. We suggest some powerful new primality tests which combine Lucas pseudoprimes with ordinary pseudoprimes. Since these tests require the evaluation of the least number $f(n)$ for which the Jacobi symbol $(f(n)/n)$ is less than 1, we evaluate the average order of the function $f$.}, copyright = {Copyright (C) 1980 American Mathematical Society}, issn = {00255718}, publisher = {American Mathematical Society}, url = {https://www.jstor.org/stable/2006406} } @ARTICLE{BerTas2010, author = {D. Berend and T. Tassa}, title = {{I}mproved bounds on {B}ell numbers and on moments of sums of random variables}, journal = {Probability and Mathematical Statistics}, volume = {30}, year = {2010}, pages = {pp. 185--205}, url = {https://www.openu.ac.il/home/tamirtassa/Publications/lp_moments.pdf} } @ARTICLE{BrentKung1978, author = {Brent, R. P. and Kung, H. T.}, title = {Fast Algorithms for Manipulating Formal Power Series}, year = {1978}, journal = {J. ACM}, volume = {25}, number = {4}, pages = {581--595}, } @ARTICLE{BuhlerCrandallSompolski1992, title = {Irregular primes to one million}, author = {Buhler, J.P. and Crandall, R.E. and Sompolski, R.W.}, journal = {Math. Comp.}, volume = {59}, number = {2000}, year = {1992}, month = {October}, pages = {717--722}, } @ARTICLE{Borwein2000, author = {Borwein, P.}, title = {An Efficient Algorithm for the Riemann Zeta Function}, journal = {Canadian Mathematical Society Conference Proceedings}, volume = {27}, year = {2000}, pages = {29--34}, } @ARTICLE{Chen2003, author = "Zhuo Chen and John Greene", title = "Some Comments on {Baillie--PSW} Pseudoprimes", journal = j-FIB-QUART, volume = "41", number = "4", pages = "334--344", month = aug, year = "2003", CODEN = "FIBQAU", ISSN = "0015-0517", ISSN-L = "0015-0517", bibdate = "Thu Oct 20 18:03:49 MDT 2011", bibsource = "https://www.fq.math.ca/41-4.html; http://www.math.utah.edu/pub/tex/bib/fibquart.bib", URL = "https://www.fq.math.ca/Scanned/41-4/chen.pdf", acknowledgement = ack-nhfb, ajournal = "Fib. Quart", fjournal = "The Fibonacci Quarterly. Official Organ of the Fibonacci Association", journal-URL = "https://www.fq.math.ca/", } @BOOK{Coh1996, title = {A course in computational algebraic number theory}, author = {Cohen, Henri}, edition = {Second}, publisher = {Springer}, year = {1996}, } @inproceedings{Col1971, author = {Collins, George E.}, title = {The Calculation of Multivariate Polynomial Resultants}, booktitle = {Proceedings of the Second ACM Symposium on Symbolic and Algebraic Manipulation}, series = {SYMSAC '71}, year = {1971}, location = {Los Angeles, California, USA}, pages = {212--222}, numpages = {11}, url = {https://doi.org/10.1145/800204.806289}, doi = {10.1145/800204.806289}, acmid = {806289}, publisher = {ACM}, address = {New York, NY, USA}, } @BOOK{CraPom2005, title = {Prime Numbers: A Computational Perspective}, publisher = {Springer}, year = {2005}, author = {Richard Crandall and Carl Pomerance}, pages = {597}, edition = {Second}, month = {August}, } @ARTICLE{DelegliseNicolasZimmermann2009, author = {Del\'eglise, Marc and Nicolas, Jean-Louis and Zimmermann, Paul}, title = {Landau's function for one million billions}, journal = {J. Th\'eor. Nombres Bordeaux}, year = {2009}, volume = {20}, pages = {625-671}, number = {3}, journal = {Journal de Th\'eorie des Nombres de Bordeaux}, url = {https://doi.org/10.5802/jtnb.644} } @ARTICLE{DomKanTro1987, author = {Domich, P. D. and Kannan, R. and Trotter, L. E. Jr.}, title = {Hermite Normal Form Computation Using Modulo Determinant Arithmetic}, journal = {Math. Operations Res.}, year = {1987}, volume = {12}, pages = {50--59}, } @ARTICLE{Dus1999, author = {Dusart, Pierre}, title = {The {$k$}th prime is greater than {$k(\ln k+\ln\ln k-1)$} for {$k\geq2$}}, journal = {Math. Comp.}, year = {1999}, volume = {68}, pages = {411--415}, number = {225}, coden = {MCMPAF}, doi = {10.1090/S0025-5718-99-01037-6}, fjournal = {Mathematics of Computation}, issn = {0025-5718}, url = {https://doi.org/10.1090/S0025-5718-99-01037-6} } @ARTICLE{GowWag2008, author = {Gower, Jason E. and Wagstaff, Jr., Samuel S.}, title = {Square form factorization}, journal = {Math. Comp.}, year = {2008}, volume = {77}, pages = {551--588}, number = {261}, coden = {MCMPAF}, doi = {10.1090/S0025-5718-07-02010-8}, fjournal = {Mathematics of Computation}, issn = {0025-5718}, url = {https://doi.org/10.1090/S0025-5718-07-02010-8} } @ARTICLE{GraMon1994, author = {Granlund, Torbj\"{o}rn and Montgomery, Peter L.}, title = {Division by invariant integers using multiplication}, journal = {SIGPLAN Not.}, volume = {29}, issue = {6}, month = {June}, year = {1994}, issn = {0362-1340}, pages = {61--72}, numpages = {12}, url = {https://doi.org/10.1145/773473.178249}, doi = {10.1145/773473.178249}, acmid = {178249}, publisher = {ACM}, address = {New York, NY, USA}, } @ARTICLE{GraMol2010, author = {Torbj\"orn Granlund and Niels M\"oller}, title = {Improved Division by Invariant Integers}, journal = {IEEE Transactions on Computers}, year = {2010}, volume = {99}, number = {PrePrints}, note = {draft version available at \url{https://www.lysator.liu.se/~nisse/archive/draft-division-paper.pdf}}, address = {Los Alamitos, CA, USA}, url = {https://doi.org/10.1109/TC.2010.143}, doi = {10.1109/TC.2010.143}, issn = {0018-9340}, publisher = {IEEE Computer Society}, } @UNPUBLISHED{Kahan1991, author = {W. Kahan}, title = {Computing a Real Cube Root}, note = {\url{https://csclub.uwaterloo.ca/~pbarfuss/qbrt.pdf}}, year = {1991}, } @UNPUBLISHED{GouSeb2004, author = {Xavier Gourdon and Pascal Sebah}, title = {The Euler constant: $\gamma$}, year = {2004}, note = {\url{http://numbers.computation.free.fr/Constants/Gamma/gamma.html}}, } @ARTICLE{HaiPap1998, author = {Bruno Haible and Thomas Papanikolau}, title = {Fast multiprecision evaluation of series of rational numbers}, journal = {Algorithmic Number Theory}, year = {1998}, published = {Springer}, } @UNPUBLISHED{HanZim2004, author = {Guillaume Hanrot and Paul Zimmermann}, title = {Newton Iteration Revisited}, note = {\url{http://www.loria.fr/~zimmerma/papers/fastnewton.ps.gz}}, year = {2004}, } @UNPUBLISHED{Har2009, author = {William Hart}, title = {A one line factoring algorithm}, note = {\url{http://sage.math.washington.edu/home/wbhart/onelinefactor.pdf}}, year = {2009}, } @ARTICLE{Hen1956, author = {Peter Henrici}, title = {A Subroutine for Computations with Rational Numbers}, journal = {J. ACM}, year = {1956}, volume = {3}, pages = {6--9}, number = {1}, note = {\url{https://doi.org/10.1145/320815.320818}}, } @ARTICLE{Hor1972, author = {Ellis Horowitz}, title = {Algorithms for Rational Function Arithmetic Operations}, journal = {Annual ACM Symposium on Theory of Computing: Proceedings of the Fourth Annual ACM Symposium on Theory of Computing (Denver)}, year = {1972}, pages = {108--118}, note = {\url{https://doi.org/10.1145/800152.804903}}, } @ARTICLE{Iliopoulos1989, author = {Iliopoulos, C. S.}, title = {Worst-Case Complexity Bounds on Algorithms for Computing the Canonical Structure of Finite Abelian Groups and the Hermite and Smith Normal Forms of an Integer Matrix}, journal = {SIAM J. Computation}, year = {1989}, volume = {18}, number = {4}, pages = {658--669}, } @ARTICLE{KanBac1979, author = {Kannan, R. and Bachem, A.}, title = {Polynomial algorithms for computing and the Smith and Hermite normal forms of an integer matrix}, journal = {SIAM J. Computation}, year = {1979}, volume = {9}, pages = {499--507}, } @BOOK{Knu1997, author = {Donald Knuth}, title = {The Art of Computer Programming Vol.~2, Seminumerical Algorithms}, edition = {third}, publisher = {Addison--Wesley}, address = {Reading, Massachusetts}, year = {1997}, } @ARTICLE{Knuth1977, author = {Donald Knuth}, title = {Notes on Generalized Dedekind Sums}, journal = {Acta Arithmetica}, year = {1977}, volume = {33}, pages = {297--325}, } @ARTICLE{LukPatWil1996, author = {Lukes, R. F. and Patterson, C. D. and Williams, H. C.}, title = {Some results on pseudosquares}, journal = {Math. Comp.}, year = {1996}, volume = {65}, pages = {361--372, S25--S27}, number = {213}, note = {available at \url{http://www.ams.org/journals/mcom/1996-65-213/S0025-5718-96-00678-3/S0025-5718-96-00678-3.pdf}}, coden = {MCMPAF}, doi = {10.1090/S0025-5718-96-00678-3}, fjournal = {Mathematics of Computation}, issn = {0025-5718}, url = {https://doi.org/10.1090/S0025-5718-96-00678-3} } @ARTICLE{MasRob1996, author = {Massias, Jean-Pierre and Robin, Guy}, title = {Bornes effectives pour certaines fonctions concernant les nombres premiers}, journal = {J. Th\'eor. Nombres Bordeaux}, year = {1996}, volume = {8}, pages = {215--242}, number = {1}, fjournal = {Journal de Th\'eorie des Nombres de Bordeaux}, issn = {1246-7405}, url = {http://jtnb.cedram.org/item?id=JTNB_1996__8_1_215_0} } @ARTICLE{Mul2000, author = {Thom Mulders}, title = {On Short Multiplications and Divisions}, journal = {AAECC}, year = {2000}, volume = {11}, pages = {69--88} } @ARTICLE{NakTurWil1997, author = {Nakos, George and Turner, Peter and Williams, Robert}, title = {Fraction-free algorithms for linear and polynomial equations}, journal = {ACM SIGSAM Bull.}, year = {1997}, volume = {31}, number = {3}, pages = {11--19}, } @ARTICLE{PernetStein2010, author = {Pernet, C. and Stein, W.}, title = {Fast computation of Hermite normal forms of random integer matrices}, journal = {J. Number Theory}, volume = {130}, number = {7}, year = {2010}, pages = {1675--1683} } @ARTICLE{Rademacher1937, author = {Rademacher, Hans}, title = {On the partition function $p(n)$}, journal = {Proc. London Math. Soc}, volume = {43}, year = {1937}, pages = {241--254} } @ARTICLE{RosSch1962, author = {Rosser, J. Barkley and Schoenfeld, Lowell}, title = {Approximate formulas for some functions of prime numbers}, journal = {Illinois J. Math.}, year = {1962}, volume = {6}, pages = {64--94}, fjournal = {Illinois Journal of Mathematics}, issn = {0019-2082}, } @BOOK{Stein2007, author = {Stein, William A.}, title = {Modular forms, a computational approach}, year = {2007}, publisher = {American Mathematical Society}, series = {Graduate studies in mathematics}, isbn = {9780821839607}, } @ARTICLE{ThullYap1990, author = {Thull, K. and Yap, C.}, title = {A Unified Approach to {HGCD} Algorithms for Polynomials and Integers}, year = {1990} } @ARTICLE{Zei1995, author = {D.~Zeilberger}, title = {The {J}.{C}.{P}.~{M}iller Recurrence for Exponentiating a Polynomial, and its $q$-Analog}, journal = {Journal of Difference Equations and Applications}, year = {1995}, volume = {1}, pages = {57--60}, } @ARTICLE{WaktinsZeitlin1993, author = {Watkins, W. and Zeitlin, J.}, title = {The minimal polynomial of $\cos(2\pi/n)$}, journal = {The American Mathematical Monthly}, volume = {100}, number = {5}, year = {1993}, pages = {471--474}, } @ARTICLE{Whiteman1956, author = {Whiteman, A. L.}, title = {A sum connected with the series for the partition function}, journal = {Pacific Journal of Mathematics}, year = {1956}, volume = {6}, number = {1}, pages = {159--176}, } @INCOLLECTION{Stehle2010, author = {Stehl\'e, Damien}, title = {Floating-Point LLL: Theoretical and Practical Aspects}, editor = {Nguyen, Phong Q. and Vall\'ee, Brigitte}, booktitle = {The LLL Algorithm: Survey and Applications}, publisher = {Springer}, address = {Heidelberg}, year = {2010}, pages = {179--213}, } @INPROCEEDINGS{Villard2007, author = {Villard, Gilles}, title = {Certification of the QR Factor R and of Lattice Basis Reducedness}, booktitle = {In proceedings of ACM International Symposium on Symbolic and Algebraic Computation}, year = {2007}, pages = {361--368}, publisher = {ACM Press}, } @ARTICLE{Bodrato2010, author = {Bodrato, Marco}, title = {A Strassen-like matrix multiplication suited for squaring and higher power computation}, journal = {ISSAC '10 Proceedings of the 2010 International Symposium on Symbolic and Algebraic Computation}, year = {2010}, pages = {273-280}, publisher = {ACM}, } @ARTICLE{Paterson1973, author = {Michael S. Paterson and Larry J. Stockmeyer}, title = {On the number of nonscalar multiplications necessary to evaluate polynomials}, journal = {SIAM Journal on Computing}, year = {1973} } @incollection {StoMul1998, author = {Storjohann, Arne and Mulders, Thom}, title = {Fast algorithms for linear algebra modulo {$N$}}, booktitle = {Algorithms---{ESA} '98 ({V}enice)}, series = {Lecture Notes in Comput. Sci.}, volume = {1461}, pages = {139--150}, publisher = {Springer}, year = {1998}, doi = {10.1007/3-540-68530-8_12}, url = {https://doi.org/10.1007/3-540-68530-8_12}, } @article {FieHof2014, author = {Fieker, Claus and Hofmann, Tommy}, title = {Computing in quotients of rings of integers}, journal = {LMS J. Comput. Math.}, fjournal = {LMS Journal of Computation and Mathematics}, volume = {17}, year = {2014}, number = {suppl. A}, pages = {349--365}, ISSN = {1461-1570}, doi = {10.1112/S1461157014000291}, url = {https://doi.org/10.1112/S1461157014000291}, } flint-3.1.3/doc/profiler.txt000066400000000000000000000121041461254215100157610ustar00rootroot00000000000000******************************************************************************* Timer based on the cycle counter ******************************************************************************* void timeit_start(timeit_t t) void timeit_stop(timeit_t t) Gives wall and user time - useful for parallel programming. Example usage: \begin{lstlisting}[language=c] timeit_t t0; // ... timeit_start(t0); // do stuff, take some time timeit_stop(t0); flint_printf("cpu = %wd ms wall = %wd ms\n", t0->cpu, t0->wall); \end{lstlisting} void start_clock(int n) void stop_clock(int n) double get_clock(int n) Gives time based on cycle counter. First one must ensure the processor speed in cycles per second is set correctly in \code{profiler.h}, in the macro definition \code{#define FLINT_CLOCKSPEED}. One can access the cycle counter directly by \code{get_cycle_counter()} which returns the current cycle counter as a \code{double}. A sample usage of clocks is: \begin{lstlisting}[language=c] init_all_clocks(); start_clock(n); // do something stop_clock(n); flint_printf("Time in seconds is %f.3\n", get_clock(n)); \end{lstlisting} where \code{n} is a clock number (from 0-19 by default). The number of clocks can be changed by altering \code{FLINT_NUM_CLOCKS}. One can also initialise an individual clock with \code{init_clock(n)}. ******************************************************************************* Framework for repeatedly sampling a single target ******************************************************************************* void prof_repeat(double *min, double *max, profile_target_t target, void *arg) Allows one to automatically time a given function. Here is a sample usage: Suppose one has a function one wishes to profile: \begin{lstlisting}[language=c] void myfunc(ulong a, ulong b); \end{lstlisting} One creates a struct for passing arguments to our function: \begin{lstlisting}[language=c] typedef struct { ulong a, b; } myfunc_t; \end{lstlisting} a sample function: \begin{lstlisting}[language=c] void sample_myfunc(void * arg, ulong count) { myfunc_t * params = (myfunc_t *) arg; ulong a = params->a; ulong b = params->b; for (ulong i = 0; i < count; i++) { prof_start(); myfunc(a, b); prof_stop(); } } \end{lstlisting} Then we do the profile \begin{lstlisting}[language=c] double min, max; myfunc_t params; params.a = 3; params.b = 4; prof_repeat(&min, &max, sample_myfunc, ¶ms); flint_printf("Min time is %lf.3s, max time is %lf.3s\n", min, max); \end{lstlisting} If either of the first two parameters to \code{prof_repeat} are \code{NULL}, that value is not stored. One may set the minimum time in microseconds for a timing run by adjusting\\ \code{DURATION_THRESHOLD} and one may set a target duration in microseconds by adjusting \code{DURATION_TARGET} in \code{profiler.h}. ******************************************************************************* Memory usage ******************************************************************************* void get_memory_usage(meminfo_t meminfo) Obtains information about the memory usage of the current process. The meminfo object contains the slots \code{size} (virtual memory size), \code{peak} (peak virtual memory size), \code{rss} (resident set size), \code{hwm} (peak resident set size). The values are stored in kilobytes (1024 bytes). This function currently only works on Linux. ******************************************************************************* Simple profiling macros ******************************************************************************* macro TIMEIT_REPEAT(timer, reps) macro TIMEIT_END_REPEAT(timer, reps) Repeatedly runs the code between the \code{TIMEIT_REPEAT} and the \code{TIMEIT_END_REPEAT} markers, automatically increasing the number of repetitions until the elapsed time exceeds the timer resolution. The macro takes as input a predefined \code{timeit_t} object and an integer variable to hold the number of repetitions. macro TIMEIT_START macro TIMEIT_STOP Repeatedly runs the code between the \code{TIMEIT_START} and the \code{TIMEIT_STOP} markers, automatically increasing the number of repetitions until the elapsed time exceeds the timer resolution, and then prints the average elapsed cpu and wall time for a single repetition. macro TIMEIT_ONCE_START macro TIMEIT_ONCE_STOP Runs the code between the \code{TIMEIT_ONCE_START} and the \code{TIMEIT_ONCE_STOP} markers exactly once and then prints the elapsed cpu and wall time. This does not give a precise measurement if the elapsed time is short compared to the timer resolution. macro SHOW_MEMORY_USAGE Retrieves memory usage information via \code{get_memory_usage} and prints the results. flint-3.1.3/doc/source/000077500000000000000000000000001461254215100147005ustar00rootroot00000000000000flint-3.1.3/doc/source/_static/000077500000000000000000000000001461254215100163265ustar00rootroot00000000000000flint-3.1.3/doc/source/_static/default.css000066400000000000000000000006271461254215100204710ustar00rootroot00000000000000@import url("pygments.css"); @import url("classic.css"); body { font-family: "arial", sans-serif; } div .toctree-wrapper { column-count: 2; } div .toctree-wrapper > ul { margin: 0; } ul .toctree-l1 { margin: 0; -webkit-column-break-inside: avoid; page-break-inside: avoid; break-inside: avoid-column; } div.body { min-width: 450px; max-width: 100%; } li p { margin: 0.2em; } flint-3.1.3/doc/source/acb.rst000066400000000000000000001452741461254215100161740ustar00rootroot00000000000000.. _acb: **acb.h** -- complex numbers =============================================================================== An :type:`acb_t` represents a complex number with error bounds. An :type:`acb_t` consists of a pair of real number balls of type :type:`arb_struct`, representing the real and imaginary part with separate error bounds. An :type:`acb_t` thus represents a rectangle `[m_1-r_1, m_1+r_1] + [m_2-r_2, m_2+r_2] i` in the complex plane. This is used instead of a disk or square representation (consisting of a complex floating-point midpoint with a single radius), since it allows implementing many operations more conveniently by splitting into ball operations on the real and imaginary parts. It also allows tracking when complex numbers have an exact (for example exactly zero) real part and an inexact imaginary part, or vice versa. The interface for the :type:`acb_t` type is slightly less developed than that for the :type:`arb_t` type. In many cases, the user can easily perform missing operations by directly manipulating the real and imaginary parts. Types, macros and constants ------------------------------------------------------------------------------- .. type:: acb_struct .. type:: acb_t An *acb_struct* consists of a pair of *arb_struct*:s. An *acb_t* is defined as an array of length one of type *acb_struct*, permitting an *acb_t* to be passed by reference. .. type:: acb_ptr Alias for ``acb_struct *``, used for vectors of numbers. .. type:: acb_srcptr Alias for ``const acb_struct *``, used for vectors of numbers when passed as constant input to functions. .. macro:: acb_realref(x) Macro returning a pointer to the real part of *x* as an *arb_t*. .. macro:: acb_imagref(x) Macro returning a pointer to the imaginary part of *x* as an *arb_t*. Memory management ------------------------------------------------------------------------------- .. function:: void acb_init(acb_t x) Initializes the variable *x* for use, and sets its value to zero. .. function:: void acb_clear(acb_t x) Clears the variable *x*, freeing or recycling its allocated memory. .. function:: acb_ptr _acb_vec_init(slong n) Returns a pointer to an array of *n* initialized *acb_struct*:s. .. function:: void _acb_vec_clear(acb_ptr v, slong n) Clears an array of *n* initialized *acb_struct*:s. .. function:: slong acb_allocated_bytes(const acb_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(acb_struct)`` to get the size of the object as a whole. .. function:: slong _acb_vec_allocated_bytes(acb_srcptr vec, slong len) Returns the total number of bytes allocated for this vector, i.e. the space taken up by the vector itself plus the sum of the internal heap allocation sizes for all its member elements. .. function:: double _acb_vec_estimate_allocated_bytes(slong len, slong prec) Estimates the number of bytes that need to be allocated for a vector of *len* elements with *prec* bits of precision, including the space for internal limb data. See comments for :func:`_arb_vec_estimate_allocated_bytes`. Basic manipulation ------------------------------------------------------------------------------- .. function:: void acb_zero(acb_t z) .. function:: void acb_one(acb_t z) .. function:: void acb_onei(acb_t z) Sets *z* respectively to 0, 1, `i = \sqrt{-1}`. .. function:: void acb_set(acb_t z, const acb_t x) .. function:: void acb_set_ui(acb_t z, ulong x) .. function:: void acb_set_si(acb_t z, slong x) .. function:: void acb_set_d(acb_t z, double x) .. function:: void acb_set_fmpz(acb_t z, const fmpz_t x) .. function:: void acb_set_arb(acb_t z, const arb_t c) Sets *z* to the value of *x*. .. function:: void acb_set_si_si(acb_t z, slong x, slong y) .. function:: void acb_set_d_d(acb_t z, double x, double y) .. function:: void acb_set_fmpz_fmpz(acb_t z, const fmpz_t x, const fmpz_t y) .. function:: void acb_set_arb_arb(acb_t z, const arb_t x, const arb_t y) Sets the real and imaginary part of *z* to the values *x* and *y* respectively .. function:: void acb_set_fmpq(acb_t z, const fmpq_t x, slong prec) .. function:: void acb_set_round(acb_t z, const acb_t x, slong prec) .. function:: void acb_set_round_fmpz(acb_t z, const fmpz_t x, slong prec) .. function:: void acb_set_round_arb(acb_t z, const arb_t x, slong prec) Sets *z* to *x*, rounded to *prec* bits. .. function:: void acb_swap(acb_t z, acb_t x) Swaps *z* and *x* efficiently. .. function:: void acb_add_error_arf(acb_t x, const arf_t err) .. function:: void acb_add_error_mag(acb_t x, const mag_t err) .. function:: void acb_add_error_arb(acb_t x, const arb_t err) Adds *err* to the error bounds of both the real and imaginary parts of *x*, modifying *x* in-place. .. function:: void acb_get_mid(acb_t m, const acb_t x) Sets *m* to the midpoint of *x*. Input and output ------------------------------------------------------------------------------- The *acb_print...* functions print to standard output, while *acb_fprint...* functions print to the stream *file*. .. function:: void acb_print(const acb_t x) .. function:: void acb_fprint(FILE * file, const acb_t x) Prints the internal representation of *x*. .. function:: void acb_printd(const acb_t x, slong digits) .. function:: void acb_fprintd(FILE * file, const acb_t x, slong digits) Prints *x* in decimal. The printed value of the radius is not adjusted to compensate for the fact that the binary-to-decimal conversion of both the midpoint and the radius introduces additional error. .. function:: void acb_printn(const acb_t x, slong digits, ulong flags) .. function:: void acb_fprintn(FILE * file, const acb_t x, slong digits, ulong flags) Prints a nice decimal representation of *x*, using the format of :func:`arb_get_str` (or the corresponding :func:`arb_printn`) for the real and imaginary parts. By default, the output shows the midpoint of both the real and imaginary parts with a guaranteed error of at most one unit in the last decimal place. In addition, explicit error bounds are printed so that the displayed decimal interval is guaranteed to enclose *x*. Any flags understood by :func:`arb_get_str` can be passed via *flags* to control the format of the real and imaginary parts. Random number generation ------------------------------------------------------------------------------- .. function:: void acb_randtest(acb_t z, flint_rand_t state, slong prec, slong mag_bits) Generates a random complex number by generating separate random real and imaginary parts. .. function:: void acb_randtest_special(acb_t z, flint_rand_t state, slong prec, slong mag_bits) Generates a random complex number by generating separate random real and imaginary parts. Also generates NaNs and infinities. .. function:: void acb_randtest_precise(acb_t z, flint_rand_t state, slong prec, slong mag_bits) Generates a random complex number with precise real and imaginary parts. .. function:: void acb_randtest_param(acb_t z, flint_rand_t state, slong prec, slong mag_bits) Generates a random complex number, with very high probability of generating integers and half-integers. .. function:: void acb_urandom(acb_t z, flint_rand_t state, slong prec) Generates a random complex number with precise real and imaginary parts, uniformly chosen in the unit disk. Precision and comparisons ------------------------------------------------------------------------------- .. function:: int acb_is_zero(const acb_t z) Returns nonzero iff *z* is zero. .. function:: int acb_is_one(const acb_t z) Returns nonzero iff *z* is exactly 1. .. function:: int acb_is_finite(const acb_t z) Returns nonzero iff *z* certainly is finite. .. function:: int acb_is_exact(const acb_t z) Returns nonzero iff *z* is exact. .. function:: int acb_is_int(const acb_t z) Returns nonzero iff *z* is an exact integer. .. function:: int acb_is_int_2exp_si(const acb_t x, slong e) Returns nonzero iff *z* exactly equals `n 2^e` for some integer *n*. .. function:: int acb_equal(const acb_t x, const acb_t y) Returns nonzero iff *x* and *y* are identical as sets, i.e. if the real and imaginary parts are equal as balls. Note that this is not the same thing as testing whether both *x* and *y* certainly represent the same complex number, unless either *x* or *y* is exact (and neither contains NaN). To test whether both operands *might* represent the same mathematical quantity, use :func:`acb_overlaps` or :func:`acb_contains`, depending on the circumstance. .. function:: int acb_equal_si(const acb_t x, slong y) Returns nonzero iff *x* is equal to the integer *y*. .. function:: int acb_eq(const acb_t x, const acb_t y) Returns nonzero iff *x* and *y* are certainly equal, as determined by testing that :func:`arb_eq` holds for both the real and imaginary parts. .. function:: int acb_ne(const acb_t x, const acb_t y) Returns nonzero iff *x* and *y* are certainly not equal, as determined by testing that :func:`arb_ne` holds for either the real or imaginary parts. .. function:: int acb_overlaps(const acb_t x, const acb_t y) Returns nonzero iff *x* and *y* have some point in common. .. function:: void acb_union(acb_t z, const acb_t x, const acb_t y, slong prec) Sets *z* to a complex interval containing both *x* and *y*. .. function:: void acb_get_abs_ubound_arf(arf_t u, const acb_t z, slong prec) Sets *u* to an upper bound for the absolute value of *z*, computed using a working precision of *prec* bits. .. function:: void acb_get_abs_lbound_arf(arf_t u, const acb_t z, slong prec) Sets *u* to a lower bound for the absolute value of *z*, computed using a working precision of *prec* bits. .. function:: void acb_get_rad_ubound_arf(arf_t u, const acb_t z, slong prec) Sets *u* to an upper bound for the error radius of *z* (the value is currently not computed tightly). .. function:: void acb_get_mag(mag_t u, const acb_t x) Sets *u* to an upper bound for the absolute value of *x*. .. function:: void acb_get_mag_lower(mag_t u, const acb_t x) Sets *u* to a lower bound for the absolute value of *x*. .. function:: int acb_contains_fmpq(const acb_t x, const fmpq_t y) .. function:: int acb_contains_fmpz(const acb_t x, const fmpz_t y) .. function:: int acb_contains(const acb_t x, const acb_t y) Returns nonzero iff *y* is contained in *x*. .. function:: int acb_contains_zero(const acb_t x) Returns nonzero iff zero is contained in *x*. .. function:: int acb_contains_int(const acb_t x) Returns nonzero iff the complex interval represented by *x* contains an integer. .. function:: int acb_contains_interior(const acb_t x, const acb_t y) Tests if *y* is contained in the interior of *x*. This predicate always evaluates to false if *x* and *y* are both real-valued, since an imaginary part of 0 is not considered contained in the interior of the point interval 0. More generally, the same problem occurs for intervals with an exact real or imaginary part. Such intervals must be handled specially by the user where a different interpretation is intended. .. function:: slong acb_rel_error_bits(const acb_t x) Returns the effective relative error of *x* measured in bits. This is computed as if calling :func:`arb_rel_error_bits` on the real ball whose midpoint is the larger out of the real and imaginary midpoints of *x*, and whose radius is the larger out of the real and imaginary radiuses of *x*. .. function:: slong acb_rel_accuracy_bits(const acb_t x) Returns the effective relative accuracy of *x* measured in bits, equal to the negative of the return value from :func:`acb_rel_error_bits`. .. function:: slong acb_rel_one_accuracy_bits(const acb_t x) Given a ball with midpoint *m* and radius *r*, returns an approximation of the relative accuracy of `[\max(1,|m|) \pm r]` measured in bits. .. function:: slong acb_bits(const acb_t x) Returns the maximum of *arb_bits* applied to the real and imaginary parts of *x*, i.e. the minimum precision sufficient to represent *x* exactly. .. function:: void acb_indeterminate(acb_t x) Sets *x* to `[\operatorname{NaN} \pm \infty] + [\operatorname{NaN} \pm \infty]i`, representing an indeterminate result. .. function:: void acb_trim(acb_t y, const acb_t x) Sets *y* to a a copy of *x* with both the real and imaginary parts trimmed (see :func:`arb_trim`). .. function:: int acb_is_real(const acb_t x) Returns nonzero iff the imaginary part of *x* is zero. It does not test whether the real part of *x* also is finite. .. function:: int acb_get_unique_fmpz(fmpz_t z, const acb_t x) If *x* contains a unique integer, sets *z* to that value and returns nonzero. Otherwise (if *x* represents no integers or more than one integer), returns zero. Complex parts ------------------------------------------------------------------------------- .. function:: void acb_get_real(arb_t re, const acb_t z) Sets *re* to the real part of *z*. .. function:: void acb_get_imag(arb_t im, const acb_t z) Sets *im* to the imaginary part of *z*. .. function:: void acb_arg(arb_t r, const acb_t z, slong prec) Sets *r* to a real interval containing the complex argument (phase) of *z*. We define the complex argument have a discontinuity on `(-\infty,0]`, with the special value `\operatorname{arg}(0) = 0`, and `\operatorname{arg}(a+0i) = \pi` for `a < 0`. Equivalently, if `z = a+bi`, the argument is given by `\operatorname{atan2}(b,a)` (see :func:`arb_atan2`). .. function:: void acb_abs(arb_t r, const acb_t z, slong prec) Sets *r* to the absolute value of *z*. .. function:: void acb_sgn(acb_t r, const acb_t z, slong prec) Sets *r* to the complex sign of *z*, defined as 0 if *z* is exactly zero and the projection onto the unit circle `z / |z| = \exp(i \arg(z))` otherwise. .. function:: void acb_csgn(arb_t r, const acb_t z) Sets *r* to the extension of the real sign function taking the value 1 for *z* strictly in the right half plane, -1 for *z* strictly in the left half plane, and the sign of the imaginary part when *z* is on the imaginary axis. Equivalently, `\operatorname{csgn}(z) = z / \sqrt{z^2}` except that the value is 0 when *z* is exactly zero. Arithmetic ------------------------------------------------------------------------------- .. function:: void acb_neg(acb_t z, const acb_t x) .. function:: void acb_neg_round(acb_t z, const acb_t x, slong prec) Sets *z* to the negation of *x*. .. function:: void acb_conj(acb_t z, const acb_t x) Sets *z* to the complex conjugate of *x*. .. function:: void acb_add_ui(acb_t z, const acb_t x, ulong y, slong prec) .. function:: void acb_add_si(acb_t z, const acb_t x, slong y, slong prec) .. function:: void acb_add_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) .. function:: void acb_add_arb(acb_t z, const acb_t x, const arb_t y, slong prec) .. function:: void acb_add(acb_t z, const acb_t x, const acb_t y, slong prec) Sets *z* to the sum of *x* and *y*. .. function:: void acb_sub_ui(acb_t z, const acb_t x, ulong y, slong prec) .. function:: void acb_sub_si(acb_t z, const acb_t x, slong y, slong prec) .. function:: void acb_sub_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) .. function:: void acb_sub_arb(acb_t z, const acb_t x, const arb_t y, slong prec) .. function:: void acb_sub(acb_t z, const acb_t x, const acb_t y, slong prec) Sets *z* to the difference of *x* and *y*. .. function:: void acb_mul_onei(acb_t z, const acb_t x) Sets *z* to *x* multiplied by the imaginary unit. .. function:: void acb_div_onei(acb_t z, const acb_t x) Sets *z* to *x* divided by the imaginary unit. .. function:: void acb_mul_i_pow_si(acb_t z, const acb_t x, slong k) Sets *z* to *x* multiplied by `i^k`, where *i* denotes the imaginary unit. .. function:: void acb_mul_ui(acb_t z, const acb_t x, ulong y, slong prec) .. function:: void acb_mul_si(acb_t z, const acb_t x, slong y, slong prec) .. function:: void acb_mul_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) .. function:: void acb_mul_arb(acb_t z, const acb_t x, const arb_t y, slong prec) Sets *z* to the product of *x* and *y*. .. function:: void acb_mul(acb_t z, const acb_t x, const acb_t y, slong prec) Sets *z* to the product of *x* and *y*. If at least one part of *x* or *y* is zero, the operations is reduced to two real multiplications. If *x* and *y* are the same pointers, they are assumed to represent the same mathematical quantity and the squaring formula is used. .. function:: void acb_mul_2exp_si(acb_t z, const acb_t x, slong e) .. function:: void acb_mul_2exp_fmpz(acb_t z, const acb_t x, const fmpz_t e) Sets *z* to *x* multiplied by `2^e`, without rounding. .. function:: void acb_sqr(acb_t z, const acb_t x, slong prec) Sets *z* to *x* squared. .. function:: void acb_cube(acb_t z, const acb_t x, slong prec) Sets *z* to *x* cubed, computed efficiently using two real squarings, two real multiplications, and scalar operations. .. function:: void acb_addmul(acb_t z, const acb_t x, const acb_t y, slong prec) .. function:: void acb_addmul_ui(acb_t z, const acb_t x, ulong y, slong prec) .. function:: void acb_addmul_si(acb_t z, const acb_t x, slong y, slong prec) .. function:: void acb_addmul_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) .. function:: void acb_addmul_arb(acb_t z, const acb_t x, const arb_t y, slong prec) Sets *z* to *z* plus the product of *x* and *y*. .. function:: void acb_submul(acb_t z, const acb_t x, const acb_t y, slong prec) .. function:: void acb_submul_ui(acb_t z, const acb_t x, ulong y, slong prec) .. function:: void acb_submul_si(acb_t z, const acb_t x, slong y, slong prec) .. function:: void acb_submul_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) .. function:: void acb_submul_arb(acb_t z, const acb_t x, const arb_t y, slong prec) Sets *z* to *z* minus the product of *x* and *y*. .. function:: void acb_inv(acb_t z, const acb_t x, slong prec) Sets *z* to the multiplicative inverse of *x*. .. function:: void acb_div_ui(acb_t z, const acb_t x, ulong y, slong prec) .. function:: void acb_div_si(acb_t z, const acb_t x, slong y, slong prec) .. function:: void acb_div_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) .. function:: void acb_div_arb(acb_t z, const acb_t x, const arb_t y, slong prec) .. function:: void acb_div(acb_t z, const acb_t x, const acb_t y, slong prec) Sets *z* to the quotient of *x* and *y*. Dot product ------------------------------------------------------------------------------- .. function:: void acb_dot_precise(acb_t res, const acb_t s, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) void acb_dot_simple(acb_t res, const acb_t s, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) void acb_dot(acb_t res, const acb_t s, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) Computes the dot product of the vectors *x* and *y*, setting *res* to `s + (-1)^{subtract} \sum_{i=0}^{len-1} x_i y_i`. The initial term *s* is optional and can be omitted by passing *NULL* (equivalently, `s = 0`). The parameter *subtract* must be 0 or 1. The length *len* is allowed to be negative, which is equivalent to a length of zero. The parameters *xstep* or *ystep* specify a step length for traversing subsequences of the vectors *x* and *y*; either can be negative to step in the reverse direction starting from the initial pointer. Aliasing is allowed between *res* and *s* but not between *res* and the entries of *x* and *y*. The default version determines the optimal precision for each term and performs all internal calculations using mpn arithmetic with minimal overhead. This is the preferred way to compute a dot product; it is generally much faster and more precise than a simple loop. The *simple* version performs fused multiply-add operations in a simple loop. This can be used for testing purposes and is also used as a fallback by the default version when the exponents are out of range for the optimized code. The *precise* version computes the dot product exactly up to the final rounding. This can be extremely slow and is only intended for testing. .. function:: void acb_approx_dot(acb_t res, const acb_t s, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) Computes an approximate dot product *without error bounds*. The radii of the inputs are ignored (only the midpoints are read) and only the midpoint of the output is written. .. function:: void acb_dot_ui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) void acb_dot_si(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const slong * y, slong ystep, slong len, slong prec) void acb_dot_uiui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) void acb_dot_siui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) void acb_dot_fmpz(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const fmpz * y, slong ystep, slong len, slong prec) Equivalent to :func:`acb_dot`, but with integers in the array *y*. The *uiui* and *siui* versions take an array of double-limb integers as input; the *siui* version assumes that these represent signed integers in two's complement form. Mathematical constants ------------------------------------------------------------------------------- .. function:: void acb_const_pi(acb_t y, slong prec) Sets *y* to the constant `\pi`. Powers and roots ------------------------------------------------------------------------------- .. function:: void acb_sqrt(acb_t r, const acb_t z, slong prec) Sets *r* to the square root of *z*. If either the real or imaginary part is exactly zero, only a single real square root is needed. Generally, we use the formula `\sqrt{a+bi} = u/2 + ib/u, u = \sqrt{2(|a+bi|+a)}`, requiring two real square root extractions. .. function:: void acb_sqrt_analytic(acb_t r, const acb_t z, int analytic, slong prec) Computes the square root. If *analytic* is set, gives a NaN-containing result if *z* touches the branch cut. .. function:: void acb_rsqrt(acb_t r, const acb_t z, slong prec) Sets *r* to the reciprocal square root of *z*. If either the real or imaginary part is exactly zero, only a single real reciprocal square root is needed. Generally, we use the formula `1/\sqrt{a+bi} = ((a+r) - bi)/v, r = |a+bi|, v = \sqrt{r |a+bi+r|^2}`, requiring one real square root and one real reciprocal square root. .. function:: void acb_rsqrt_analytic(acb_t r, const acb_t z, int analytic, slong prec) Computes the reciprocal square root. If *analytic* is set, gives a NaN-containing result if *z* touches the branch cut. .. function:: void acb_sqrts(acb_t y1, acb_t y2, const acb_t x, slong prec) Sets *y1* and *y2* to the two square roots of *x*, without any precision loss due to branch cuts. The order in which the square roots appear is not specified. .. function:: void acb_quadratic_roots_fmpz(acb_t r1, acb_t r2, const fmpz_t a, const fmpz_t b, const fmpz_t c, slong prec) Sets *r1* and *r2* to the roots of the quadratic polynomial `ax^2 + bx + c`. Requires that *a* is nonzero. This function is implemented so that both roots are computed accurately even when direct use of the quadratic formula would lose accuracy. .. function:: void acb_root_ui(acb_t r, const acb_t z, ulong k, slong prec) Sets *r* to the principal *k*-th root of *z*. .. function:: void acb_pow_fmpz(acb_t y, const acb_t b, const fmpz_t e, slong prec) .. function:: void acb_pow_ui(acb_t y, const acb_t b, ulong e, slong prec) .. function:: void acb_pow_si(acb_t y, const acb_t b, slong e, slong prec) Sets `y = b^e` using binary exponentiation (with an initial division if `e < 0`). Note that these functions can get slow if the exponent is extremely large (in such cases :func:`acb_pow` may be superior). .. function:: void acb_pow_arb(acb_t z, const acb_t x, const arb_t y, slong prec) .. function:: void acb_pow(acb_t z, const acb_t x, const acb_t y, slong prec) Sets `z = x^y`, computed using binary exponentiation if `y` if a small exact integer, as `z = (x^{1/2})^{2y}` if `y` is a small exact half-integer, and generally as `z = \exp(y \log x)`. .. function:: void acb_pow_analytic(acb_t r, const acb_t x, const acb_t y, int analytic, slong prec) Computes the power `x^y`. If *analytic* is set, gives a NaN-containing result if *x* touches the branch cut (unless *y* is an integer). .. function:: void acb_unit_root(acb_t res, ulong order, slong prec) Sets *res* to `\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. Exponentials and logarithms ------------------------------------------------------------------------------- .. function:: void acb_exp(acb_t y, const acb_t z, slong prec) Sets *y* to the exponential function of *z*, computed as `\exp(a+bi) = \exp(a) \left( \cos(b) + \sin(b) i \right)`. .. function:: void acb_exp_pi_i(acb_t y, const acb_t z, slong prec) Sets *y* to `\exp(\pi i z)`. .. function:: void acb_exp_invexp(acb_t s, acb_t t, const acb_t z, slong prec) Sets `s = \exp(z)` and `t = \exp(-z)`. .. function:: void acb_expm1(acb_t res, const acb_t z, slong prec) Sets *res* to `\exp(z)-1`, using a more accurate method when `z \approx 0`. .. function:: void acb_log(acb_t y, const acb_t z, slong prec) Sets *y* to the principal branch of the natural logarithm of *z*, computed as `\log(a+bi) = \frac{1}{2} \log(a^2 + b^2) + i \operatorname{arg}(a+bi)`. .. function:: void acb_log_analytic(acb_t r, const acb_t z, int analytic, slong prec) Computes the natural logarithm. If *analytic* is set, gives a NaN-containing result if *z* touches the branch cut. .. function:: void acb_log1p(acb_t z, const acb_t x, slong prec) Sets `z = \log(1+x)`, computed accurately when `x \approx 0`. Trigonometric functions ------------------------------------------------------------------------------- .. function:: void acb_sin(acb_t s, const acb_t z, slong prec) .. function:: void acb_cos(acb_t c, const acb_t z, slong prec) .. function:: void acb_sin_cos(acb_t s, acb_t c, const acb_t z, slong prec) Sets `s = \sin(z)`, `c = \cos(z)`, evaluated as `\sin(a+bi) = \sin(a)\cosh(b) + i \cos(a)\sinh(b)`, `\cos(a+bi) = \cos(a)\cosh(b) - i \sin(a)\sinh(b)`. .. function:: void acb_tan(acb_t s, const acb_t z, slong prec) Sets `s = \tan(z) = \sin(z) / \cos(z)`. For large imaginary parts, the function is evaluated in a numerically stable way as `\pm i` plus a decreasing exponential factor. .. function:: void acb_cot(acb_t s, const acb_t z, slong prec) Sets `s = \cot(z) = \cos(z) / \sin(z)`. For large imaginary parts, the function is evaluated in a numerically stable way as `\pm i` plus a decreasing exponential factor. .. function:: void acb_sin_pi(acb_t s, const acb_t z, slong prec) .. function:: void acb_cos_pi(acb_t s, const acb_t z, slong prec) .. function:: void acb_sin_cos_pi(acb_t s, acb_t c, const acb_t z, slong prec) Sets `s = \sin(\pi z)`, `c = \cos(\pi z)`, evaluating the trigonometric factors of the real and imaginary part accurately via :func:`arb_sin_cos_pi`. .. function:: void acb_tan_pi(acb_t s, const acb_t z, slong prec) Sets `s = \tan(\pi z)`. Uses the same algorithm as :func:`acb_tan`, but evaluates the sine and cosine accurately via :func:`arb_sin_cos_pi`. .. function:: void acb_cot_pi(acb_t s, const acb_t z, slong prec) Sets `s = \cot(\pi z)`. Uses the same algorithm as :func:`acb_cot`, but evaluates the sine and cosine accurately via :func:`arb_sin_cos_pi`. .. function:: void acb_sec(acb_t res, const acb_t z, slong prec) Computes `\sec(z) = 1 / \cos(z)`. .. function:: void acb_csc(acb_t res, const acb_t z, slong prec) Computes `\csc(x) = 1 / \sin(z)`. .. function:: void acb_csc_pi(acb_t res, const acb_t z, slong prec) Computes `\csc(\pi x) = 1 / \sin(\pi z)`. Evaluates the sine accurately via :func:`acb_sin_pi`. .. function:: void acb_sinc(acb_t s, const acb_t z, slong prec) Sets `s = \operatorname{sinc}(x) = \sin(z) / z`. .. function:: void acb_sinc_pi(acb_t s, const acb_t z, slong prec) Sets `s = \operatorname{sinc}(\pi x) = \sin(\pi z) / (\pi z)`. Inverse trigonometric functions ------------------------------------------------------------------------------- .. function:: void acb_asin(acb_t res, const acb_t z, slong prec) Sets *res* to `\operatorname{asin}(z) = -i \log(iz + \sqrt{1-z^2})`. .. function:: void acb_acos(acb_t res, const acb_t z, slong prec) Sets *res* to `\operatorname{acos}(z) = \tfrac{1}{2} \pi - \operatorname{asin}(z)`. .. function:: void acb_atan(acb_t res, const acb_t z, slong prec) Sets *res* to `\operatorname{atan}(z) = \tfrac{1}{2} i (\log(1-iz)-\log(1+iz))`. Hyperbolic functions ------------------------------------------------------------------------------- .. function:: void acb_sinh(acb_t s, const acb_t z, slong prec) .. function:: void acb_cosh(acb_t c, const acb_t z, slong prec) .. function:: void acb_sinh_cosh(acb_t s, acb_t c, const acb_t z, slong prec) .. function:: void acb_tanh(acb_t s, const acb_t z, slong prec) .. function:: void acb_coth(acb_t s, const acb_t z, slong prec) Respectively computes `\sinh(z) = -i\sin(iz)`, `\cosh(z) = \cos(iz)`, `\tanh(z) = -i\tan(iz)`, `\coth(z) = i\cot(iz)`. .. function:: void acb_sech(acb_t res, const acb_t z, slong prec) Computes `\operatorname{sech}(z) = 1 / \cosh(z)`. .. function:: void acb_csch(acb_t res, const acb_t z, slong prec) Computes `\operatorname{csch}(z) = 1 / \sinh(z)`. Inverse hyperbolic functions ------------------------------------------------------------------------------- .. function:: void acb_asinh(acb_t res, const acb_t z, slong prec) Sets *res* to `\operatorname{asinh}(z) = -i \operatorname{asin}(iz)`. .. function:: void acb_acosh(acb_t res, const acb_t z, slong prec) Sets *res* to `\operatorname{acosh}(z) = \log(z + \sqrt{z+1} \sqrt{z-1})`. .. function:: void acb_atanh(acb_t res, const acb_t z, slong prec) Sets *res* to `\operatorname{atanh}(z) = -i \operatorname{atan}(iz)`. Lambert W function ------------------------------------------------------------------------------- .. function:: void acb_lambertw_asymp(acb_t res, const acb_t z, const fmpz_t k, slong L, slong M, slong prec) Sets *res* to the Lambert W function `W_k(z)` computed using *L* and *M* terms in the bivariate series giving the asymptotic expansion at zero or infinity. This algorithm is valid everywhere, but the error bound is only finite when `|\log(z)|` is sufficiently large. .. function:: int acb_lambertw_check_branch(const acb_t w, const fmpz_t k, slong prec) Tests if *w* definitely lies in the image of the branch `W_k(z)`. This function is used internally to verify that a computed approximation of the Lambert W function lies on the intended branch. Note that this will necessarily evaluate to false for points exactly on (or overlapping) the branch cuts, where a different algorithm has to be used. .. function:: void acb_lambertw_bound_deriv(mag_t res, const acb_t z, const acb_t ez1, const fmpz_t k) Sets *res* to an upper bound for `|W_k'(z)|`. The input *ez1* should contain the precomputed value of `ez+1`. Along the real line, the directional derivative of `W_k(z)` is understood to be taken. As a result, the user must handle the branch cut discontinuity separately when using this function to bound perturbations in the value of `W_k(z)`. .. function:: void acb_lambertw(acb_t res, const acb_t z, const fmpz_t k, int flags, slong prec) Sets *res* to the Lambert W function `W_k(z)` where the index *k* selects the branch (with `k = 0` giving the principal branch). The placement of branch cuts follows [CGHJK1996]_. If *flags* is nonzero, nonstandard branch cuts are used. If *flags* is set to *ACB_LAMBERTW_LEFT*, computes `W_{\mathrm{left}|k}(z)` which corresponds to `W_k(z)` in the upper half plane and `W_{k+1}(z)` in the lower half plane, connected continuously to the left of the branch points. In other words, the branch cut on `(-\infty,0)` is rotated counterclockwise to `(0,+\infty)`. (For `k = -1` and `k = 0`, there is also a branch cut on `(-1/e,0)`, continuous from below instead of from above to maintain counterclockwise continuity.) If *flags* is set to *ACB_LAMBERTW_MIDDLE*, computes `W_{\mathrm{middle}}(z)` which corresponds to `W_{-1}(z)` in the upper half plane and `W_{1}(z)` in the lower half plane, connected continuously through `(-1/e,0)` with branch cuts on `(-\infty,-1/e)` and `(0,+\infty)`. `W_{\mathrm{middle}}(z)` extends the real analytic function `W_{-1}(x)` defined on `(-1/e,0)` to a complex analytic function, whereas the standard branch `W_{-1}(z)` has a branch cut along the real segment. The algorithm used to compute the Lambert W function is described in [Joh2017b]_. Rising factorials ------------------------------------------------------------------------------- .. function:: void acb_rising_ui(acb_t z, const acb_t x, ulong n, slong prec) void acb_rising(acb_t z, const acb_t x, const acb_t n, slong prec) Computes the rising factorial `z = x (x+1) (x+2) \cdots (x+n-1)`. These functions are aliases for :func:`acb_hypgeom_rising_ui` and :func:`acb_hypgeom_rising`. .. function:: void acb_rising2_ui(acb_t u, acb_t v, const acb_t x, ulong n, slong prec) Letting `u(x) = x (x+1) (x+2) \cdots (x+n-1)`, simultaneously compute `u(x)` and `v(x) = u'(x)`. This function is a wrapper of :func:`acb_hypgeom_rising_ui_jet`. .. function:: void acb_rising_ui_get_mag(mag_t bound, const acb_t x, ulong n) Computes an upper bound for the absolute value of the rising factorial `z = x (x+1) (x+2) \cdots (x+n-1)`. Not currently optimized for large *n*. Gamma function ------------------------------------------------------------------------------- .. function:: void acb_gamma(acb_t y, const acb_t x, slong prec) Computes the gamma function `y = \Gamma(x)`. This is an alias for :func:`acb_hypgeom_gamma`. .. function:: void acb_rgamma(acb_t y, const acb_t x, slong prec) Computes the reciprocal gamma function `y = 1/\Gamma(x)`, avoiding division by zero at the poles of the gamma function. This is an alias for :func:`acb_hypgeom_rgamma`. .. function:: void acb_lgamma(acb_t y, const acb_t x, slong prec) Computes the logarithmic gamma function `y = \log \Gamma(x)`. This is an alias for :func:`acb_hypgeom_lgamma`. The branch cut of the logarithmic gamma function is placed on the negative half-axis, which means that `\log \Gamma(z) + \log z = \log \Gamma(z+1)` holds for all `z`, whereas `\log \Gamma(z) \ne \log(\Gamma(z))` in general. In the left half plane, the reflection formula with correct branch structure is evaluated via :func:`acb_log_sin_pi`. .. function:: void acb_digamma(acb_t y, const acb_t x, slong prec) Computes the digamma function `y = \psi(x) = (\log \Gamma(x))' = \Gamma'(x) / \Gamma(x)`. .. function:: void acb_log_sin_pi(acb_t res, const acb_t z, slong prec) Computes the logarithmic sine function defined by .. math:: S(z) = \log(\pi) - \log \Gamma(z) + \log \Gamma(1-z) which is equal to .. math:: S(z) = \int_{1/2}^z \pi \cot(\pi t) dt where the path of integration goes through the upper half plane if `0 < \arg(z) \le \pi` and through the lower half plane if `-\pi < \arg(z) \le 0`. Equivalently, .. math:: S(z) = \log(\sin(\pi(z-n))) \mp n \pi i, \quad n = \lfloor \operatorname{re}(z) \rfloor where the negative sign is taken if `0 < \arg(z) \le \pi` and the positive sign is taken otherwise (if the interval `\arg(z)` does not certainly satisfy either condition, the union of both cases is computed). After subtracting *n*, we have `0 \le \operatorname{re}(z) < 1`. In this strip, we use use `S(z) = \log(\sin(\pi(z)))` if the imaginary part of *z* is small. Otherwise, we use `S(z) = i \pi (z-1/2) + \log((1+e^{-2i\pi z})/2)` in the lower half-plane and the conjugated expression in the upper half-plane to avoid exponent overflow. The function is evaluated at the midpoint and the propagated error is computed from `S'(z)` to get a continuous change when `z` is non-real and `n` spans more than one possible integer value. .. function:: void acb_polygamma(acb_t res, const acb_t s, const acb_t z, slong prec) Sets *res* to the value of the generalized polygamma function `\psi(s,z)`. If *s* is a nonnegative order, this is simply the *s*-order derivative of the digamma function. If `s = 0`, this function simply calls the digamma function internally. For integers `s \ge 1`, it calls the Hurwitz zeta function. Note that for small integers `s \ge 1`, it can be faster to use :func:`acb_poly_digamma_series` and read off the coefficients. The generalization to other values of *s* is due to Espinosa and Moll [EM2004]_: .. math:: \psi(s,z) = \frac{\zeta'(s+1,z) + (\gamma + \psi(-s)) \zeta(s+1,z)}{\Gamma(-s)} .. function:: void acb_barnes_g(acb_t res, const acb_t z, slong prec) .. function:: void acb_log_barnes_g(acb_t res, const acb_t z, slong prec) Computes Barnes *G*-function or the logarithmic Barnes *G*-function, respectively. The logarithmic version has branch cuts on the negative real axis and is continuous elsewhere in the complex plane, in analogy with the logarithmic gamma function. The functional equation .. math:: \log G(z+1) = \log \Gamma(z) + \log G(z). holds for all *z*. For small integers, we directly use the recurrence relation `G(z+1) = \Gamma(z) G(z)` together with the initial value `G(1) = 1`. For general *z*, we use the formula .. math:: \log G(z) = (z-1) \log \Gamma(z) - \zeta'(-1,z) + \zeta'(-1). Zeta function ------------------------------------------------------------------------------- .. function:: void acb_zeta(acb_t z, const acb_t s, slong prec) Sets *z* to the value of the Riemann zeta function `\zeta(s)`. Note: for computing derivatives with respect to `s`, use :func:`acb_poly_zeta_series` or related methods. This is a wrapper of :func:`acb_dirichlet_zeta`. .. function:: void acb_hurwitz_zeta(acb_t z, const acb_t s, const acb_t a, slong prec) Sets *z* to the value of the Hurwitz zeta function `\zeta(s, a)`. Note: for computing derivatives with respect to `s`, use :func:`acb_poly_zeta_series` or related methods. This is a wrapper of :func:`acb_dirichlet_hurwitz`. .. function:: void acb_bernoulli_poly_ui(acb_t res, ulong n, const acb_t x, slong prec) Sets *res* to the value of the Bernoulli polynomial `B_n(x)`. Warning: this function is only fast if either *n* or *x* is a small integer. This function reads Bernoulli numbers from the global cache if they are already cached, but does not automatically extend the cache by itself. Polylogarithms ------------------------------------------------------------------------------- .. function:: void acb_polylog(acb_t w, const acb_t s, const acb_t z, slong prec) .. function:: void acb_polylog_si(acb_t w, slong s, const acb_t z, slong prec) Sets *w* to the polylogarithm `\operatorname{Li}_s(z)`. Arithmetic-geometric mean ------------------------------------------------------------------------------- See :ref:`algorithms_agm` for implementation details. .. function:: void acb_agm1(acb_t m, const acb_t z, slong prec) Sets *m* to the arithmetic-geometric mean `M(z) = \operatorname{agm}(1,z)`, defined such that the function is continuous in the complex plane except for a branch cut along the negative half axis (where it is continuous from above). This corresponds to always choosing an "optimal" branch for the square root in the arithmetic-geometric mean iteration. .. function:: void acb_agm1_cpx(acb_ptr m, const acb_t z, slong len, slong prec) Sets the coefficients in the array *m* to the power series expansion of the arithmetic-geometric mean at the point *z* truncated to length *len*, i.e. `M(z+x) \in \mathbb{C}[[x]]`. .. function:: void acb_agm(acb_t m, const acb_t x, const acb_t y, slong prec) Sets *m* to the arithmetic-geometric mean of *x* and *y*. The square roots in the AGM iteration are chosen so as to form the "optimal" AGM sequence. This gives a well-defined function of *x* and *y* except when `x / y` is a negative real number, in which case there are two optimal AGM sequences. In that case, an arbitrary but consistent choice is made (if a decision cannot be made due to inexact arithmetic, the union of both choices is returned). Other special functions ------------------------------------------------------------------------------- .. function:: void acb_chebyshev_t_ui(acb_t a, ulong n, const acb_t x, slong prec) .. function:: void acb_chebyshev_u_ui(acb_t a, ulong n, const acb_t x, slong prec) Evaluates the Chebyshev polynomial of the first kind `a = T_n(x)` or the Chebyshev polynomial of the second kind `a = U_n(x)`. .. function:: void acb_chebyshev_t2_ui(acb_t a, acb_t b, ulong n, const acb_t x, slong prec) .. function:: void acb_chebyshev_u2_ui(acb_t a, acb_t b, ulong n, const acb_t x, slong prec) Simultaneously evaluates `a = T_n(x), b = T_{n-1}(x)` or `a = U_n(x), b = U_{n-1}(x)`. Aliasing between *a*, *b* and *x* is not permitted. Piecewise real functions ------------------------------------------------------------------------------- The following methods extend common piecewise real functions to piecewise complex analytic functions, useful together with the :ref:`acb_calc.h ` module. If *analytic* is set, evaluation on a discontinuity or non-analytic point gives a NaN result. .. function:: void acb_real_abs(acb_t res, const acb_t z, int analytic, slong prec) The absolute value is extended to `+z` in the right half plane and `-z` in the left half plane, with a discontinuity on the vertical line `\operatorname{Re}(z) = 0`. .. function:: void acb_real_sgn(acb_t res, const acb_t z, int analytic, slong prec) The sign function is extended to `+1` in the right half plane and `-1` in the left half plane, with a discontinuity on the vertical line `\operatorname{Re}(z) = 0`. If *analytic* is not set, this is effectively the same function as :func:`acb_csgn`. .. function:: void acb_real_heaviside(acb_t res, const acb_t z, int analytic, slong prec) The Heaviside step function (or unit step function) is extended to `+1` in the right half plane and `0` in the left half plane, with a discontinuity on the vertical line `\operatorname{Re}(z) = 0`. .. function:: void acb_real_floor(acb_t res, const acb_t z, int analytic, slong prec) The floor function is extended to a piecewise constant function equal to `n` in the strips with real part `(n,n+1)`, with discontinuities on the vertical lines `\operatorname{Re}(z) = n`. .. function:: void acb_real_ceil(acb_t res, const acb_t z, int analytic, slong prec) The ceiling function is extended to a piecewise constant function equal to `n+1` in the strips with real part `(n,n+1)`, with discontinuities on the vertical lines `\operatorname{Re}(z) = n`. .. function:: void acb_real_max(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec) The real function `\max(x,y)` is extended to a piecewise analytic function of two variables by returning `x` when `\operatorname{Re}(x) \ge \operatorname{Re}(y)` and returning `y` when `\operatorname{Re}(x) < \operatorname{Re}(y)`, with discontinuities where `\operatorname{Re}(x) = \operatorname{Re}(y)`. .. function:: void acb_real_min(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec) The real function `\min(x,y)` is extended to a piecewise analytic function of two variables by returning `x` when `\operatorname{Re}(x) \le \operatorname{Re}(y)` and returning `y` when `\operatorname{Re}(x) > \operatorname{Re}(y)`, with discontinuities where `\operatorname{Re}(x) = \operatorname{Re}(y)`. .. function:: void acb_real_sqrtpos(acb_t res, const acb_t z, int analytic, slong prec) Extends the real square root function on `[0,+\infty)` to the usual complex square root on the cut plane. Like :func:`arb_sqrtpos`, only the nonnegative part of *z* is considered if *z* is purely real and *analytic* is not set. This is useful for integrating `\sqrt{f(x)}` where it is known that `f(x) \ge 0`: unlike :func:`acb_sqrt_analytic`, no spurious imaginary terms `[\pm \varepsilon] i` are created when the balls computed for `f(x)` straddle zero. Vector functions ------------------------------------------------------------------------------- .. function:: void _acb_vec_zero(acb_ptr A, slong n) Sets all entries in *vec* to zero. .. function:: int _acb_vec_is_zero(acb_srcptr vec, slong len) Returns nonzero iff all entries in *x* are zero. .. function:: int _acb_vec_is_real(acb_srcptr v, slong len) Returns nonzero iff all entries in *x* have zero imaginary part. .. function:: int _acb_vec_is_finite(acb_srcptr vec, slong len) Returns nonzero iff all entries in *x* certainly are finite. .. function:: int _acb_vec_equal(acb_srcptr vec1, acb_srcptr vec2, slong len) Returns nonzero iff *vec1* and *vec2* are equal in the sense of :func:`acb_equal`, i.e. have both the same midpoint and radius elementwise. .. function:: int _acb_vec_overlaps(acb_srcptr vec1, acb_srcptr vec2, slong len) Returns true iff *vec1* overlaps *vec2* elementwise. .. function:: int _acb_vec_contains(acb_srcptr vec1, acb_srcptr vec2, slong len) Returns true iff *vec1* contains *vec2* elementwise. .. function:: void _acb_vec_set(acb_ptr res, acb_srcptr vec, slong len) Sets *res* to a copy of *vec*. .. function:: void _acb_vec_set_round(acb_ptr res, acb_srcptr vec, slong len, slong prec) Sets *res* to a copy of *vec*, rounding each entry to *prec* bits. .. function:: void _acb_vec_swap(acb_ptr vec1, acb_ptr vec2, slong len) Swaps the entries of *vec1* and *vec2*. .. function:: void _acb_vec_get_real(arb_ptr re, acb_srcptr vec, slong len) .. function:: void _acb_vec_get_imag(arb_ptr im, acb_srcptr vec, slong len) Sets each entry of *re* (resp. *im*) to the real (resp. imaginary) part of the corresponding entry of *vec*. .. function:: void _acb_vec_set_real_imag(acb_ptr vec, arb_srcptr re, arb_srcptr im, slong len) Sets *vec* to the vector with real part *re* and imaginary part *im*. .. function:: void _acb_vec_neg(acb_ptr res, acb_srcptr vec, slong len) .. function:: void _acb_vec_add(acb_ptr res, acb_srcptr vec1, acb_srcptr vec2, slong len, slong prec) .. function:: void _acb_vec_sub(acb_ptr res, acb_srcptr vec1, acb_srcptr vec2, slong len, slong prec) .. function:: void _acb_vec_scalar_submul(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) .. function:: void _acb_vec_scalar_addmul(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) .. function:: void _acb_vec_scalar_mul(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) .. function:: void _acb_vec_scalar_mul_ui(acb_ptr res, acb_srcptr vec, slong len, ulong c, slong prec) .. function:: void _acb_vec_scalar_mul_2exp_si(acb_ptr res, acb_srcptr vec, slong len, slong c) .. function:: void _acb_vec_scalar_mul_onei(acb_ptr res, acb_srcptr vec, slong len) .. function:: void _acb_vec_scalar_div_ui(acb_ptr res, acb_srcptr vec, slong len, ulong c, slong prec) .. function:: void _acb_vec_scalar_div(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) .. function:: void _acb_vec_scalar_mul_arb(acb_ptr res, acb_srcptr vec, slong len, const arb_t c, slong prec) .. function:: void _acb_vec_scalar_div_arb(acb_ptr res, acb_srcptr vec, slong len, const arb_t c, slong prec) .. function:: void _acb_vec_scalar_mul_fmpz(acb_ptr res, acb_srcptr vec, slong len, const fmpz_t c, slong prec) .. function:: void _acb_vec_scalar_div_fmpz(acb_ptr res, acb_srcptr vec, slong len, const fmpz_t c, slong prec) Performs the respective scalar operation elementwise. .. function:: void _acb_vec_sqr(acb_ptr res, acb_srcptr vec, slong len, slong prec) Sets *res* to the square of *vec* elementwise. .. function:: slong _acb_vec_bits(acb_srcptr vec, slong len) Returns the maximum of :func:`arb_bits` for all entries in *vec*. .. function:: void _acb_vec_set_powers(acb_ptr xs, const acb_t x, slong len, slong prec) Sets *xs* to the powers `1, x, x^2, \ldots, x^{len-1}`. .. function:: void _acb_vec_unit_roots(acb_ptr z, slong order, slong len, slong prec) Sets *z* to the powers `1,z,z^2,\dots z^{\mathrm{len}-1}` where `z=\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. *order* can be taken negative. In order to avoid precision loss, this function does not simply compute powers of a primitive root. .. function:: void _acb_vec_add_error_arf_vec(acb_ptr res, arf_srcptr err, slong len) .. function:: void _acb_vec_add_error_mag_vec(acb_ptr res, mag_srcptr err, slong len) Adds the magnitude of each entry in *err* to the radius of the corresponding entry in *res*. .. function:: void _acb_vec_indeterminate(acb_ptr vec, slong len) Applies :func:`acb_indeterminate` elementwise. .. function:: void _acb_vec_trim(acb_ptr res, acb_srcptr vec, slong len) Applies :func:`acb_trim` elementwise. .. function:: int _acb_vec_get_unique_fmpz_vec(fmpz * res, acb_srcptr vec, slong len) Calls :func:`acb_get_unique_fmpz` elementwise and returns nonzero if all entries can be rounded uniquely to integers. If any entry in *vec* cannot be rounded uniquely to an integer, returns zero. .. function:: void _acb_vec_sort_pretty(acb_ptr vec, slong len) Sorts the vector of complex numbers based on the real and imaginary parts. This is intended to reveal structure when printing a set of complex numbers, not to apply an order relation in a rigorous way. .. function:: void _acb_vec_printd(acb_srcptr vec, slong len, slong digits) .. function:: void _acb_vec_printn(acb_srcptr vec, slong len, slong digits, ulong flags) Prints *vec* in decimal using :func:`acb_printd` or :func:`acb_printn` on each entry. flint-3.1.3/doc/source/acb_calc.rst000066400000000000000000000427431461254215100171530ustar00rootroot00000000000000.. _acb-calc: **acb_calc.h** -- calculus with complex-valued functions =============================================================================== This module provides functions for operations of calculus over the complex numbers (intended to include root-finding, integration, and so on). The numerical integration code is described in [Joh2018a]_. Types, macros and constants ------------------------------------------------------------------------------- .. type:: acb_calc_func_t Typedef for a pointer to a function with signature:: int func(acb_ptr out, const acb_t inp, void * param, slong order, slong prec) implementing a univariate complex function `f(z)`. The *param* argument may be used to pass through additional parameters to the function. The return value is reserved for future use as an error code. It can be assumed that *out* and *inp* are not aliased. When called with *order* = 0, *func* should write to *out* the value of `f(z)` at the point *inp*, evaluated at a precision of *prec* bits. In this case, *f* can be an arbitrary complex function, which may have branch cuts or even be non-holomorphic. When called with *order* = *n* for `n \ge 1`, *func* should write to *out* the first *n* coefficients in the Taylor series expansion of `f(z)` at the point *inp*, evaluated at a precision of *prec* bits. In this case, the implementation of *func* must verify that *f* is holomorphic on the complex interval defined by *z*, and set the coefficients in *out* to non-finite values otherwise. For algorithms that do not rely on derivatives, *func* will always get called with *order* = 0 or *order* = 1, in which case the user only needs to implement evaluation of the direct function value `f(z)` (without derivatives). With *order* = 1, *func* must verify holomorphicity (unlike the *order* = 0 case). If *f* is built from field operations and meromorphic functions, then no special action is necessary when *order* is positive since division by zero or evaluation of builtin functions at poles automatically produces infinite enclosures. However, manual action is needed for bounded functions with branch cuts. For example, when evaluating `\sqrt{z}`, the output must be set to an non-finite value if `z` overlaps with the branch cut `[-\infty,0]`. The easiest way to accomplish this is to use versions of basic functions (sqrt, log, pow, etc.) that test holomorphicity of their arguments individually. Some functions with branch cut detection are available as builtins: see :func:`acb_sqrt_analytic`, :func:`acb_rsqrt_analytic`, :func:`acb_log_analytic`, :func:`acb_pow_analytic`. It is not difficult to write custom functions of this type, using the following pattern:: /* Square root function on C with detection of the branch cut. */ void sqrt_analytic(acb_t res, const acb_t z, int analytic, slong prec) { if (analytic && arb_contains_zero(acb_imagref(z)) && arb_contains_nonpositive(acb_realref(z)))) { acb_indeterminate(res); } else { acb_sqrt(res, z, prec); } } The built-in methods :func:`acb_real_abs`, :func:`acb_real_sgn`, :func:`acb_real_heaviside`, :func:`acb_real_floor`, :func:`acb_real_ceil`, :func:`acb_real_max`, :func:`acb_real_min` provide piecewise holomorphic functions that are useful for integrating piecewise-defined real functions. For example, here we define a piecewise holomorphic extension of the function `f(z) = \sqrt{\lfloor z \rfloor}` (for simplicity, without implementing derivatives):: int func(acb_ptr out, const acb_t inp, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* derivatives not implemented */ acb_real_floor(out, inp, order != 0, prec); acb_sqrt_analytic(out, out, order != 0, prec); return 0; } (Here, :func:`acb_real_sqrtpos` may be slightly better if it is known that *z* will be nonnegative on the path.) See the demo program ``examples/integrals.c`` for more examples. Integration ------------------------------------------------------------------------------- .. function:: int acb_calc_integrate(acb_t res, acb_calc_func_t func, void * param, const acb_t a, const acb_t b, slong rel_goal, const mag_t abs_tol, const acb_calc_integrate_opt_t options, slong prec) Computes a rigorous enclosure of the integral .. math:: I = \int_a^b f(t) dt where *f* is specified by (*func*, *param*), following a straight-line path between the complex numbers *a* and *b*. For finite results, *a*, *b* must be finite and *f* must be bounded on the path of integration. To compute improper integrals, the user should therefore truncate the path of integration manually (or make a regularizing change of variables, if possible). Returns *ARB_CALC_SUCCESS* if the integration converged to the target accuracy on all subintervals, and returns *ARB_CALC_NO_CONVERGENCE* otherwise. By default, the integrand *func* will only be called with *order* = 0 or *order* = 1; that is, derivatives are not required. - The integrand will be called with *order* = 0 to evaluate *f* normally on the integration path (either at a single point or on a subinterval). In this case, *f* is treated as a pointwise defined function and can have arbitrary discontinuities. - The integrand will be called with *order* = 1 to evaluate *f* on a domain surrounding a segment of the integration path for the purpose of bounding the error of a quadrature formula. In this case, *func* must verify that *f* is holomorphic on this domain (and output a non-finite value if it is not). The integration algorithm combines direct interval enclosures, Gauss-Legendre quadrature where *f* is holomorphic, and adaptive subdivision. This strategy supports integrands with discontinuities while providing exponential convergence for typical piecewise holomorphic integrands. The following parameters control accuracy: - *rel_goal* - relative accuracy goal as a number of bits, i.e. target a relative error less than `\varepsilon_{rel} = 2^{-r}` where *r* = *rel_goal* (note the sign: *rel_goal* should be nonnegative). - *abs_tol* - absolute accuracy goal as a :type:`mag_t` describing the error tolerance, i.e. target an absolute error less than `\varepsilon_{abs}` = *abs_tol*. - *prec* - working precision. This is the working precision used to evaluate the integrand and manipulate interval endpoints. As currently implemented, the algorithm does not attempt to adjust the working precision by itself, and adaptive control of the working precision must be handled by the user. For typical usage, set *rel_goal* = *prec* and *abs_tol* = `2^{-prec}`. It usually only makes sense to have *rel_goal* between 0 and *prec*. The algorithm attempts to achieve an error of `\max(\varepsilon_{abs}, M \varepsilon_{rel})` on each subinterval, where *M* is the magnitude of the integral. These parameters are only guidelines; the cumulative error may be larger than both the prescribed absolute and relative error goals, depending on the number of subdivisions, cancellation between segments of the integral, and numerical errors in the evaluation of the integrand. To compute tiny integrals with high relative accuracy, one should set `\varepsilon_{abs} \approx M \varepsilon_{rel}` where *M* is a known estimate of the magnitude. Setting `\varepsilon_{abs}` to 0 is also allowed, forcing use of a relative instead of an absolute tolerance goal. This can be handy for exponentially small or large functions of unknown magnitude. It is recommended to avoid setting `\varepsilon_{abs}` very small if possible since the algorithm might need many extra subdivisions to estimate *M* automatically; if the approximate magnitude can be estimated by some external means (for example if a midpoint-width or endpoint-width estimate is known to be accurate), providing an appropriate `\varepsilon_{abs} \approx M \varepsilon_{rel}` will be more efficient. If the integral has very large magnitude, setting the absolute tolerance to a corresponding large value is recommended for best performance, but it is not necessary for convergence since the absolute tolerance is increased automatically during the execution of the algorithm if the partial integrals are found to have larger error. Additional options for the integration can be provided via the *options* parameter (documented below). To use all defaults, *NULL* can be passed for *options*. Options for integration ............................................................................... .. type:: acb_calc_integrate_opt_struct .. type:: acb_calc_integrate_opt_t This structure contains several fields, explained below. An *acb_calc_integrate_opt_t* is defined as an array of *acb_calc_integrate_opt_struct* of length 1, permitting it to be passed by reference. An *acb_calc_integrate_opt_t* must be initialized before use, which sets all fields to 0 or *NULL*. For fields that have not been set to other values, the integration algorithm will choose defaults automatically (based on the precision and accuracy goals). This structure will most likely be extended in the future to accommodate more options. .. member:: slong deg_limit Maximum quadrature degree for each subinterval. If a zero or negative value is provided, the limit is set to a default value which currently equals `0.5 \cdot \min(prec, rel\_goal) + 60` for Gauss-Legendre quadrature. A higher quadrature degree can be beneficial for functions that are holomorphic on a large domain around the integration path and yet behave irregularly, such as oscillatory entire functions. The drawback of increasing the degree is that the precomputation time for quadrature nodes increases. .. member:: slong eval_limit Maximum number of function evaluations. If a zero or negative value is provided, the limit is set to a default value which currently equals `1000 \cdot prec + prec^2`. This is the main parameter used to limit the amount of work before aborting due to possible slow convergence or non-convergence. A lower limit allows aborting faster. A higher limit may be needed for integrands with many discontinuities or many singularities close to the integration path. This limit is only taken as a rough guideline, and the actual number of function evaluations may be slightly higher depending on the actual subdivisions. .. member:: slong depth_limit Maximum search depth for adaptive subdivision. Technically, this is not the limit on the local bisection depth but the limit on the number of simultaneously queued subintervals. If a zero or negative value is provided, the limit is set to the default value `2 \cdot \text{prec}`. Warning: memory usage may increase in proportion to this limit. .. member:: int use_heap By default (if set to 0), new subintervals generated by adaptive bisection will be appended to the top of a stack. If set to 1, a binary heap will be used to maintain a priority queue where the subintervals with larger error have higher priority. This sometimes gives better results in case of convergence failure, but can lead to a much larger array of subintervals (requiring a higher *depth_limit*) when many global bisections are needed. .. member:: int verbose If set to 1, some information about the overall integration process is printed to standard output. If set to 2, information about each subinterval is printed. .. function:: void acb_calc_integrate_opt_init(acb_calc_integrate_opt_t options) Initializes *options* for use, setting all fields to 0 indicating default values. Local integration algorithms ------------------------------------------------------------------------------- .. function:: int acb_calc_integrate_gl_auto_deg(acb_t res, slong * num_eval, acb_calc_func_t func, void * param, const acb_t a, const acb_t b, const mag_t tol, slong deg_limit, int flags, slong prec) Attempts to compute `I = \int_a^b f(t) dt` using a single application of Gauss-Legendre quadrature with automatic determination of the quadrature degree so that the error is smaller than *tol*. Returns *ARB_CALC_SUCCESS* if the integral has been evaluated successfully or *ARB_CALC_NO_CONVERGENCE* if the tolerance could not be met. The total number of function evaluations is written to *num_eval*. For the interval `[-1,1]`, the error of the *n*-point Gauss-Legendre rule is bounded by .. math:: \left| I - \sum_{k=0}^{n-1} w_k f(x_k) \right| \le \frac{64 M}{15 (\rho-1) \rho^{2n-1}} if `f` is holomorphic with `|f(z)| \le M` inside the ellipse *E* with foci `\pm 1` and semiaxes `X` and `Y = \sqrt{X^2 - 1}` such that `\rho = X + Y` with `\rho > 1` [Tre2008]_. For an arbitrary interval, we use `\int_a^b f(t) dt = \int_{-1}^1 g(t) dt` where `g(t) = \Delta f(\Delta t + m)`, `\Delta = \tfrac{1}{2}(b-a)`, `m = \tfrac{1}{2}(a+b)`. With `I = [\pm X] + [\pm Y]i`, this means that we evaluate `\Delta f(\Delta I + m)` to get the bound `M`. (An improvement would be to reduce the wrapping effect of rotating the ellipse when the path is not rectilinear). We search for an `X` that makes the error small by trying steps `2^{2^k}`. Larger `X` will give smaller `1 / \rho^{2n-1}` but larger `M`. If we try successive larger values of `k`, we can abort when `M = \infty` since this either means that we have hit a singularity or a branch cut or that overestimation in the evaluation of `f` is becoming too severe. Integration (old) ------------------------------------------------------------------------------- .. function:: void acb_calc_cauchy_bound(arb_t bound, acb_calc_func_t func, void * param, const acb_t x, const arb_t radius, slong maxdepth, slong prec) Sets *bound* to a ball containing the value of the integral .. math:: C(x,r) = \frac{1}{2 \pi r} \oint_{|z-x| = r} |f(z)| dz = \int_0^1 |f(x+re^{2\pi i t})| dt where *f* is specified by (*func*, *param*) and *r* is given by *radius*. The integral is computed using a simple step sum. The integration range is subdivided until the order of magnitude of *b* can be determined (i.e. its error bound is smaller than its midpoint), or until the step length has been cut in half *maxdepth* times. This function is currently implemented completely naively, and repeatedly subdivides the whole integration range instead of performing adaptive subdivisions. .. function:: int acb_calc_integrate_taylor(acb_t res, acb_calc_func_t func, void * param, const acb_t a, const acb_t b, const arf_t inner_radius, const arf_t outer_radius, slong accuracy_goal, slong prec) Computes the integral .. math:: I = \int_a^b f(t) dt where *f* is specified by (*func*, *param*), following a straight-line path between the complex numbers *a* and *b* which both must be finite. The integral is approximated by piecewise centered Taylor polynomials. Rigorous truncation error bounds are calculated using the Cauchy integral formula. More precisely, if the Taylor series of *f* centered at the point *m* is `f(m+x) = \sum_{n=0}^{\infty} a_n x^n`, then .. math:: \int f(m+x) = \left( \sum_{n=0}^{N-1} a_n \frac{x^{n+1}}{n+1} \right) + \left( \sum_{n=N}^{\infty} a_n \frac{x^{n+1}}{n+1} \right). For sufficiently small *x*, the second series converges and its absolute value is bounded by .. math:: \sum_{n=N}^{\infty} \frac{C(m,R)}{R^n} \frac{|x|^{n+1}}{N+1} = \frac{C(m,R) R x}{(R-x)(N+1)} \left( \frac{x}{R} \right)^N. It is required that any singularities of *f* are isolated from the path of integration by a distance strictly greater than the positive value *outer_radius* (which is the integration radius used for the Cauchy bound). Taylor series step lengths are chosen so as not to exceed *inner_radius*, which must be strictly smaller than *outer_radius* for convergence. A smaller *inner_radius* gives more rapid convergence of each Taylor series but means that more series might have to be used. A reasonable choice might be to set *inner_radius* to half the value of *outer_radius*, giving roughly one accurate bit per term. The truncation point of each Taylor series is chosen so that the absolute truncation error is roughly `2^{-p}` where *p* is given by *accuracy_goal* (in the future, this might change to a relative accuracy). Arithmetic operations and function evaluations are performed at a precision of *prec* bits. Note that due to accumulation of numerical errors, both values may have to be set higher (and the endpoints may have to be computed more accurately) to achieve a desired accuracy. This function chooses the evaluation points uniformly rather than implementing adaptive subdivision. flint-3.1.3/doc/source/acb_dft.rst000066400000000000000000000235421461254215100170220ustar00rootroot00000000000000.. _acb-dft: **acb_dft.h** -- Discrete Fourier transform =================================================================================== *Warning: the interfaces in this module are experimental and may change without notice.* All functions support aliasing. Let *G* be a finite abelian group, and `\chi` a character of *G*. For any map `f:G\to\mathbb C`, the discrete fourier transform `\hat f:\hat G\to \mathbb C` is defined by .. math:: \hat f(\chi) = \sum_{x\in G}\overline{\chi(x)}f(x) Note that by the inversion formula .. math:: \widehat{\hat f}(\chi) = \#G\times f(\chi^{-1}) it is straightforward to recover `f` from its DFT `\hat f`. Main DFT functions ------------------------------------------------------------------------------- If `G=\mathbb Z/n\mathbb Z`, we compute the DFT according to the usual convention .. math:: w_x = \sum_{y\bmod n} v_y e^{-\frac{2i \pi}nxy} .. function:: void acb_dft(acb_ptr w, acb_srcptr v, slong n, slong prec) Set *w* to the DFT of *v* of length *len*, using an automatic choice of algorithm. .. function:: void acb_dft_inverse(acb_ptr w, acb_srcptr v, slong n, slong prec) Compute the inverse DFT of *v* into *w*. If several computations are to be done on the same group, the FFT scheme should be reused. .. type:: acb_dft_pre_struct .. type:: acb_dft_pre_t Stores a fast DFT scheme on :math:`\mathbb Z/n\mathbb Z` as a recursive decomposition into simpler DFT with some tables of roots of unity. An *acb_dft_pre_t* is defined as an array of *acb_dft_pre_struct* of length 1, permitting it to be passed by reference. .. function:: void acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec) Initializes the fast DFT scheme of length *len*, using an automatic choice of algorithms depending on the factorization of *len*. The length *len* is stored as *pre->n*. .. function:: void acb_dft_precomp_clear(acb_dft_pre_t pre) Clears *pre*. .. function:: void acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec) Computes the DFT of the sequence *v* into *w* by applying the precomputed scheme *pre*. Both *v* and *w* must have length *pre->n*. .. function:: void acb_dft_inverse_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec) Compute the inverse DFT of *v* into *w*. DFT on products ------------------------------------------------------------------------------- A finite abelian group is isomorphic to a product of cyclic components .. math:: G = \bigoplus_{i=1}^r \mathbb Z/n_i\mathbb Z Characters are product of component characters and the DFT reads .. math:: \hat f(x_1,\dots x_r) = \sum_{y_1\dots y_r} f(y_1,\dots y_r) e^{-2i \pi \sum\frac{x_i y_i}{n_i}} We assume that `f` is given by a vector of length `\prod n_i` corresponding to a lexicographic ordering of the values `y_1,\dots y_r`, and the computation returns the same indexing for values of `\hat f`. .. function:: void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) Computes the DFT on the group product of *num* cyclic components of sizes *cyc*. Assume the entries of *v* are indexed according to lexicographic ordering of the cyclic components. .. type:: acb_dft_prod_struct .. type:: acb_dft_prod_t Stores a fast DFT scheme on a product of cyclic groups. An *acb_dft_prod_t* is defined as an array of *acb_dft_prod_struct* of length 1, permitting it to be passed by reference. .. function:: void acb_dft_prod_init(acb_dft_prod_t t, slong * cyc, slong num, slong prec) Stores in *t* a DFT scheme for the product of *num* cyclic components whose sizes are given in the array *cyc*. .. function:: void acb_dft_prod_clear(acb_dft_prod_t t) Clears *t*. .. function:: void acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dft_prod_t prod, slong prec) Sets *w* to the DFT of *v*. Assume the entries are lexicographically ordered according to the product of cyclic groups initialized in *t*. Convolution ------------------------------------------------------------------------------- For functions `f` and `g` on `G` we consider the convolution .. math:: (f \star g)(x) = \sum_{y\in G} f(x-y)g(y) .. function:: void acb_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) .. function:: void acb_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) .. function:: void acb_dft_convol(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) Sets *w* to the convolution of *f* and *g* of length *len*. The *naive* version simply uses the definition. The *rad2* version embeds the sequence into a power of 2 length and uses the formula .. math:: \widehat{f \star g}(\chi) = \hat f(\chi)\hat g(\chi) to compute it using three radix 2 FFT. The default version uses radix 2 FFT unless *len* is a product of small primes where a non padded FFT is faster. FFT algorithms ------------------------------------------------------------------------------- Fast Fourier transform techniques allow to compute efficiently all values `\hat f(\chi)` by reusing common computations. Specifically, if `H\triangleleft G` is a subgroup of size `M` and index `[G:H]=m`, then writing `f_x(h)=f(xh)` the translate of `f` by representatives `x` of `G/H`, one has a decomposition .. math:: \hat f(\chi) = \sum_{x\in G/H} \overline{\chi(x)} \hat{f_x}(\chi_{H}) so that the DFT on `G` can be computed using `m` DFT on `H` (of appropriate translates of `f`), then `M` DFT on `G/H`, one for each restriction `\chi_{H}`. This decomposition can be done recursively. Naive algorithm ............................................................................... .. function:: void acb_dft_naive(acb_ptr w, acb_srcptr v, slong n, slong prec) Computes the DFT of *v* into *w*, where *v* and *w* have size *n*, using the naive `O(n^2)` algorithm. .. type:: acb_dft_naive_struct .. type:: acb_dft_naive_t .. function:: void acb_dft_naive_init(acb_dft_naive_t t, slong len, slong prec) .. function:: void acb_dft_naive_clear(acb_dft_naive_t t) Stores a table of roots of unity in *t*. The length *len* is stored as *t->n*. .. function:: void acb_dft_naive_precomp(acb_ptr w, acb_srcptr v, const acb_dft_naive_t t, slong prec) Sets *w* to the DFT of *v* of size *t->n*, using the naive algorithm data *t*. CRT decomposition ............................................................................... .. function:: void acb_dft_crt(acb_ptr w, acb_srcptr v, slong n, slong prec) Computes the DFT of *v* into *w*, where *v* and *w* have size *len*, using CRT to express `\mathbb Z/n\mathbb Z` as a product of cyclic groups. .. type:: acb_dft_crt_struct .. type:: acb_dft_crt_t .. function:: void acb_dft_crt_init(acb_dft_crt_t t, slong len, slong prec) .. function:: void acb_dft_crt_clear(acb_dft_crt_t t) Initialize a CRT decomposition of `\mathbb Z/n\mathbb Z` as a direct product of cyclic groups. The length *len* is stored as *t->n*. .. function:: void acb_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dft_crt_t t, slong prec) Sets *w* to the DFT of *v* of size *t->n*, using the CRT decomposition scheme *t*. Cooley-Tukey decomposition ............................................................................... .. function:: void acb_dft_cyc(acb_ptr w, acb_srcptr v, slong n, slong prec) Computes the DFT of *v* into *w*, where *v* and *w* have size *n*, using each prime factor of `m` of `n` to decompose with the subgroup `H=m\mathbb Z/n\mathbb Z`. .. type:: acb_dft_cyc_struct .. type:: acb_dft_cyc_t .. function:: void acb_dft_cyc_init(acb_dft_cyc_t t, slong len, slong prec) .. function:: void acb_dft_cyc_clear(acb_dft_cyc_t t) Initialize a decomposition of `\mathbb Z/n\mathbb Z` into cyclic subgroups. The length *len* is stored as *t->n*. .. function:: void acb_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dft_cyc_t t, slong prec) Sets *w* to the DFT of *v* of size *t->n*, using the cyclic decomposition scheme *t*. Radix 2 decomposition ............................................................................... .. function:: void acb_dft_rad2(acb_ptr w, acb_srcptr v, int e, slong prec) Computes the DFT of *v* into *w*, where *v* and *w* have size `2^e`, using a radix 2 FFT. .. function:: void acb_dft_inverse_rad2(acb_ptr w, acb_srcptr v, int e, slong prec) Computes the inverse DFT of *v* into *w*, where *v* and *w* have size `2^e`, using a radix 2 FFT. .. type:: acb_dft_rad2_struct .. type:: acb_dft_rad2_t .. function:: void acb_dft_rad2_init(acb_dft_rad2_t t, int e, slong prec) .. function:: void acb_dft_rad2_clear(acb_dft_rad2_t t) Initialize and clear a radix 2 FFT of size `2^e`, stored as *t->n*. .. function:: void acb_dft_rad2_precomp(acb_ptr w, acb_srcptr v, const acb_dft_rad2_t t, slong prec) Sets *w* to the DFT of *v* of size *t->n*, using the precomputed radix 2 scheme *t*. Bluestein transform ............................................................................... .. function:: void acb_dft_bluestein(acb_ptr w, acb_srcptr v, slong n, slong prec) Computes the DFT of *v* into *w*, where *v* and *w* have size *n*, by conversion to a radix 2 one using Bluestein's convolution trick. .. type:: acb_dft_bluestein_struct .. type:: acb_dft_bluestein_t Stores a Bluestein scheme for some length *n* : that is a :type:`acb_dft_rad2_t` of size `2^e \geq 2n-1` and a size *n* array of convolution factors. .. function:: void acb_dft_bluestein_init(acb_dft_bluestein_t t, slong len, slong prec) .. function:: void acb_dft_bluestein_clear(acb_dft_bluestein_t t) Initialize and clear a Bluestein scheme to compute DFT of size *len*. .. function:: void acb_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dft_bluestein_t t, slong prec) Sets *w* to the DFT of *v* of size *t->n*, using the precomputed Bluestein scheme *t*. flint-3.1.3/doc/source/acb_dirichlet.rst000066400000000000000000001161101461254215100202060ustar00rootroot00000000000000.. _acb-dirichlet: **acb_dirichlet.h** -- Dirichlet L-functions, Riemann zeta and related functions =================================================================================== This module allows working with values of Dirichlet characters, Dirichlet L-functions, and related functions. A Dirichlet L-function is the analytic continuation of an L-series .. math:: L(s,\chi) = \sum_{k=1}^\infty \frac{\chi(k)}{k^s} where `\chi(k)` is a Dirichlet character. The trivial character `\chi(k) = 1` gives the Riemann zeta function. Working with Dirichlet characters is documented in :ref:`dirichlet`. The code in other modules for computing the Riemann zeta function, Hurwitz zeta function and polylogarithm will possibly be migrated to this module in the future. Roots of unity ------------------------------------------------------------------------------- .. type:: acb_dirichlet_roots_struct .. type:: acb_dirichlet_roots_t .. function:: void acb_dirichlet_roots_init(acb_dirichlet_roots_t roots, ulong n, slong num, slong prec) Initializes *roots* with precomputed data for fast evaluation of roots of unity `e^{2\pi i k/n}` of a fixed order *n*. The precomputation is optimized for *num* evaluations. For very small *num*, only the single root `e^{2\pi i/n}` will be precomputed, which can then be raised to a power. For small *prec* and large *n*, this method might even skip precomputing this single root if it estimates that evaluating roots of unity from scratch will be faster than powering. If *num* is large enough, the whole set of roots in the first quadrant will be precomputed at once. However, this is automatically avoided for large *n* if too much memory would be used. For intermediate *num*, baby-step giant-step tables are computed. .. function:: void acb_dirichlet_roots_clear(acb_dirichlet_roots_t roots) Clears the structure. .. function:: void acb_dirichlet_root(acb_t res, const acb_dirichlet_roots_t roots, ulong k, slong prec) Computes `e^{2\pi i k/n}`. Truncated L-series and power sums ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_powsum_term(acb_ptr res, arb_t log_prev, ulong * prev, const acb_t s, ulong k, int integer, int critical_line, slong len, slong prec) Sets *res* to `k^{-(s+x)}` as a power series in *x* truncated to length *len*. The flags *integer* and *critical_line* respectively specify optimizing for *s* being an integer or having real part 1/2. On input *log_prev* should contain the natural logarithm of the integer at *prev*. If *prev* is close to *k*, this can be used to speed up computations. If `\log(k)` is computed internally by this function, then *log_prev* is overwritten by this value, and the integer at *prev* is overwritten by *k*, allowing *log_prev* to be recycled for the next term when evaluating a power sum. .. function:: void acb_dirichlet_powsum_sieved(acb_ptr res, const acb_t s, ulong n, slong len, slong prec) Sets *res* to `\sum_{k=1}^n k^{-(s+x)}` as a power series in *x* truncated to length *len*. This function stores a table of powers that have already been calculated, computing `(ij)^r` as `i^r j^r` whenever `k = ij` is composite. As a further optimization, it groups all even `k` and evaluates the sum as a polynomial in `2^{-(s+x)}`. This scheme requires about `n / \log n` powers, `n / 2` multiplications, and temporary storage of `n / 6` power series. Due to the extra power series multiplications, it is only faster than the naive algorithm when *len* is small. .. function:: void acb_dirichlet_powsum_smooth(acb_ptr res, const acb_t s, ulong n, slong len, slong prec) Sets *res* to `\sum_{k=1}^n k^{-(s+x)}` as a power series in *x* truncated to length *len*. This function performs partial sieving by adding multiples of 5-smooth *k* into separate buckets. Asymptotically, this requires computing 4/15 of the powers, which is slower than *sieved*, but only requires logarithmic extra space. It is also faster for large *len*, since most power series multiplications are traded for additions. A slightly bigger gain for larger *n* could be achieved by using more small prime factors, at the expense of space. Riemann zeta function ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_zeta(acb_t res, const acb_t s, slong prec) Computes `\zeta(s)` using an automatic choice of algorithm. .. function:: void acb_dirichlet_zeta_jet(acb_t res, const acb_t s, int deflate, slong len, slong prec) Computes the first *len* terms of the Taylor series of the Riemann zeta function at *s*. If *deflate* is nonzero, computes the deflated function `\zeta(s) - 1/(s-1)` instead. .. function:: void acb_dirichlet_zeta_bound(mag_t res, const acb_t s) Computes an upper bound for `|\zeta(s)|` quickly. On the critical strip (and slightly outside of it), formula (43.3) in [Rad1973]_ is used. To the right, evaluating at the real part of *s* gives a trivial bound. To the left, the functional equation is used. .. function:: void acb_dirichlet_zeta_deriv_bound(mag_t der1, mag_t der2, const acb_t s) Sets *der1* to a bound for `|\zeta'(s)|` and *der2* to a bound for `|\zeta''(s)|`. These bounds are mainly intended for use in the critical strip and will not be tight. .. function:: void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec) Sets *res* to the Dirichlet eta function `\eta(s) = \sum_{k=1}^{\infty} (-1)^{k+1} / k^s = (1-2^{1-s}) \zeta(s)`, also known as the alternating zeta function. Note that the alternating character `\{1,-1\}` is not itself a Dirichlet character. .. function:: void acb_dirichlet_xi(acb_t res, const acb_t s, slong prec) Sets *res* to the Riemann xi function `\xi(s) = \frac{1}{2} s (s-1) \pi^{-s/2} \Gamma(\frac{1}{2} s) \zeta(s)`. The functional equation for xi is `\xi(1-s) = \xi(s)`. Riemann-Siegel formula ------------------------------------------------------------------------------- The Riemann-Siegel (RS) formula is implemented closely following J. Arias de Reyna [Ari2011]_. For `s = \sigma + it` with `t > 0`, the expansion takes the form .. math:: \zeta(s) = \mathcal{R}(s) + X(s) \overline{\mathcal{R}}(1-s), \quad X(s) = \pi^{s-1/2} \frac{\Gamma((1-s)/2)}{\Gamma(s/2)} where .. math:: \mathcal{R}(s) = \sum_{k=1}^N \frac{1}{k^s} + (-1)^{N-1} U a^{-\sigma} \left[ \sum_{k=0}^K \frac{C_k(p)}{a^k} + RS_K \right] .. math:: U = \exp\left(-i\left[ \frac{t}{2} \log\left(\frac{t}{2\pi}\right)-\frac{t}{2}-\frac{\pi}{8} \right]\right), \quad a = \sqrt{\frac{t}{2\pi}}, \quad N = \lfloor a \rfloor, \quad p = 1-2(a-N). The coefficients `C_k(p)` in the asymptotic part of the expansion are expressed in terms of certain auxiliary coefficients `d_j^{(k)}` and `F^{(j)}(p)`. Because of artificial discontinuities, *s* should be exact inside the evaluation. .. function:: void acb_dirichlet_zeta_rs_f_coeffs(acb_ptr f, const arb_t p, slong n, slong prec) Computes the coefficients `F^{(j)}(p)` for `0 \le j < n`. Uses power series division. This method breaks down when `p = \pm 1/2` (which is not problem if *s* is an exact floating-point number). .. function:: void acb_dirichlet_zeta_rs_d_coeffs(arb_ptr d, const arb_t sigma, slong k, slong prec) Computes the coefficients `d_j^{(k)}` for `0 \le j \le \lfloor 3k/2 \rfloor + 1`. On input, the array *d* must contain the coefficients for `d_j^{(k-1)}` unless `k = 0`, and these coefficients will be updated in-place. .. function:: void acb_dirichlet_zeta_rs_bound(mag_t err, const acb_t s, slong K) Bounds the error term `RS_K` following Theorem 4.2 in Arias de Reyna. .. function:: void acb_dirichlet_zeta_rs_r(acb_t res, const acb_t s, slong K, slong prec) Computes `\mathcal{R}(s)` in the upper half plane. Uses precisely *K* asymptotic terms in the RS formula if this input parameter is positive; otherwise chooses the number of terms automatically based on *s* and the precision. .. function:: void acb_dirichlet_zeta_rs(acb_t res, const acb_t s, slong K, slong prec) Computes `\zeta(s)` using the Riemann-Siegel formula. Uses precisely *K* asymptotic terms in the RS formula if this input parameter is positive; otherwise chooses the number of terms automatically based on *s* and the precision. .. function:: void acb_dirichlet_zeta_jet_rs(acb_ptr res, const acb_t s, slong len, slong prec) Computes the first *len* terms of the Taylor series of the Riemann zeta function at *s* using the Riemann Siegel formula. This function currently only supports *len* = 1 or *len* = 2. A finite difference is used to compute the first derivative. Hurwitz zeta function ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_hurwitz(acb_t res, const acb_t s, const acb_t a, slong prec) Computes the Hurwitz zeta function `\zeta(s, a)`. This function automatically delegates to the code for the Riemann zeta function when `a = 1`. Some other special cases may also be handled by direct formulas. In general, Euler-Maclaurin summation is used. Hurwitz zeta function precomputation ------------------------------------------------------------------------------- .. type:: acb_dirichlet_hurwitz_precomp_struct .. type:: acb_dirichlet_hurwitz_precomp_t .. function:: void acb_dirichlet_hurwitz_precomp_init(acb_dirichlet_hurwitz_precomp_t pre, const acb_t s, int deflate, slong A, slong K, slong N, slong prec) Precomputes a grid of Taylor polynomials for fast evaluation of `\zeta(s,a)` on `a \in (0,1]` with fixed *s*. *A* is the initial shift to apply to *a*, *K* is the number of Taylor terms, *N* is the number of grid points. The precomputation requires *NK* evaluations of the Hurwitz zeta function, and each subsequent evaluation requires *2K* simple arithmetic operations (polynomial evaluation) plus *A* powers. As *K* grows, the error is at most `O(1/(2AN)^K)`. This function can be called with *A* set to zero, in which case no Taylor series precomputation is performed. This means that evaluation will be identical to calling :func:`acb_dirichlet_hurwitz` directly. Otherwise, we require that *A*, *K* and *N* are all positive. For a finite error bound, we require `K+\operatorname{re}(s) > 1`. To avoid an initial "bump" that steals precision and slows convergence, *AN* should be at least roughly as large as `|s|`, e.g. it is a good idea to have at least `AN > 0.5 |s|`. If *deflate* is set, the deflated Hurwitz zeta function is used, removing the pole at `s = 1`. .. function:: void acb_dirichlet_hurwitz_precomp_init_num(acb_dirichlet_hurwitz_precomp_t pre, const acb_t s, int deflate, double num_eval, slong prec) Initializes *pre*, choosing the parameters *A*, *K*, and *N* automatically to minimize the cost of *num_eval* evaluations of the Hurwitz zeta function at argument *s* to precision *prec*. .. function:: void acb_dirichlet_hurwitz_precomp_clear(acb_dirichlet_hurwitz_precomp_t pre) Clears the precomputed data. .. function:: void acb_dirichlet_hurwitz_precomp_choose_param(ulong * A, ulong * K, ulong * N, const acb_t s, double num_eval, slong prec) Chooses precomputation parameters *A*, *K* and *N* to minimize the cost of *num_eval* evaluations of the Hurwitz zeta function at argument *s* to precision *prec*. If it is estimated that evaluating each Hurwitz zeta function from scratch would be better than performing a precomputation, *A*, *K* and *N* are all set to 0. .. function:: void acb_dirichlet_hurwitz_precomp_bound(mag_t res, const acb_t s, slong A, slong K, slong N) Computes an upper bound for the truncation error (not accounting for roundoff error) when evaluating `\zeta(s,a)` with precomputation parameters *A*, *K*, *N*, assuming that `0 < a \le 1`. For details, see :ref:`algorithms_hurwitz`. .. function:: void acb_dirichlet_hurwitz_precomp_eval(acb_t res, const acb_dirichlet_hurwitz_precomp_t pre, ulong p, ulong q, slong prec) Evaluates `\zeta(s,p/q)` using precomputed data, assuming that `0 < p/q \le 1`. Lerch transcendent ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_lerch_phi_integral(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec) void acb_dirichlet_lerch_phi_direct(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec) void acb_dirichlet_lerch_phi(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec) Computes the Lerch transcendent .. math:: \Phi(z,s,a) = \sum_{k=0}^{\infty} \frac{z^k}{(k+a)^s} which is analytically continued for `|z| \ge 1`. The *direct* version evaluates a truncation of the defining series. The *integral* version uses the Hankel contour integral .. math:: \Phi(z,s,a) = -\frac{\Gamma(1-s)}{2 \pi i} \int_C \frac{(-t)^{s-1} e^{-a t}}{1 - z e^{-t}} dt where the path is deformed as needed to avoid poles and branch cuts of the integrand. The default method chooses an algorithm automatically and also checks for some special cases where the function can be expressed in terms of simpler functions (Hurwitz zeta, polylogarithms). Stieltjes constants ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_stieltjes(acb_t res, const fmpz_t n, const acb_t a, slong prec) Given a nonnegative integer *n*, sets *res* to the generalized Stieltjes constant `\gamma_n(a)` which is the coefficient in the Laurent series of the Hurwitz zeta function at the pole .. math:: \zeta(s,a) = \frac{1}{s-1} + \sum_{n=0}^\infty \frac{(-1)^n}{n!} \gamma_n(a) (s-1)^n. With `a = 1`, this gives the ordinary Stieltjes constants for the Riemann zeta function. This function uses an integral representation to permit fast computation for extremely large *n* [JB2018]_. If *n* is moderate and the precision is high enough, it falls back to evaluating the Hurwitz zeta function of a power series and reading off the last coefficient. Note that for computing a range of values `\gamma_0(a), \ldots, \gamma_n(a)`, it is generally more efficient to evaluate the Hurwitz zeta function series expansion once at `s = 1` than to call this function repeatedly, unless *n* is extremely large (at least several hundred). Dirichlet character evaluation ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec) Sets *res* to `\chi(n)`, the value of the Dirichlet character *chi* at the integer *n*. .. function:: void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec) Compute the *nv* first Dirichlet values. .. function:: void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec) .. function:: void acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec) Sets *res* to the value of the Dirichlet pairing `\chi(m,n)` at numbers `m` and `n`. The second form takes two characters as input. Dirichlet character Gauss, Jacobi and theta sums ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) .. function:: void acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) .. function:: void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) .. function:: void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) .. function:: void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Sets *res* to the Gauss sum .. math:: G_q(a) = \sum_{x \bmod q} \chi_q(a, x) e^{\frac{2i\pi x}q} - the *naive* version computes the sum as defined. - the *factor* version writes it as a product of local Gauss sums by chinese remainder theorem. - the *order2* version assumes *chi* is real and primitive and returns `i^p\sqrt q` where `p` is the parity of `\chi`. - the *theta* version assumes that *chi* is primitive to obtain the Gauss sum by functional equation of the theta series at `t=1`. An abort will be raised if the theta series vanishes at `t=1`. Only 4 exceptional characters of conductor 300 and 600 are known to have this particularity, and none with primepower modulus. - the default version automatically combines the above methods. - the *ui* version only takes the Conrey number *a* as parameter. .. function:: void acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) .. function:: void acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) .. function:: void acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) .. function:: void acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) .. function:: void acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec) Computes the Jacobi sum .. math:: J_q(a,b) = \sum_{x \bmod q} \chi_q(a, x)\chi_q(b, 1-x) - the *naive* version computes the sum as defined. - the *factor* version writes it as a product of local Jacobi sums - the *gauss* version assumes `ab` is primitive and uses the formula `J_q(a,b)G_q(ab) = G_q(a)G_q(b)` - the default version automatically combines the above methods. - the *ui* version only takes the Conrey numbers *a* and *b* as parameters. .. function:: void acb_dirichlet_chi_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec) .. function:: void acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec) Compute the theta series `\Theta_q(a,t)` for real argument `t>0`. Beware that if `t<1` the functional equation .. math:: t \theta(a,t) = \epsilon(\chi) \theta\left(\frac1a, \frac1t\right) should be used, which is not done automatically (to avoid recomputing the Gauss sum). We call *theta series* of a Dirichlet character the quadratic series .. math:: \Theta_q(a) = \sum_{n\geq 0} \chi_q(a, n) n^p x^{n^2} where `p` is the parity of the character `\chi_q(a,\cdot)`. For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define .. math:: \Theta_q(a,t) = \sum_{n\geq 0} \chi_q(a, n) x(t)^{n^2}. .. function:: ulong acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec) Compute the number of terms to be summed in the theta series of argument *t* so that the tail is less than `2^{-\mathrm{prec}}`. .. function:: void acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int p, const ulong * a, const acb_dirichlet_roots_t z, slong len, slong prec) .. function:: void acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int p, const ulong * a, const acb_dirichlet_roots_t z, slong len, slong prec) Compute the series `\sum n^p z^{a_n} x^{n^2}` for exponent list *a*, precomputed powers *z* and parity *p* (being 0 or 1). The *naive* version sums the series as defined, while the *smallorder* variant evaluates the series on the quotient ring by a cyclotomic polynomial before evaluating at the root of unity, ignoring its argument *z*. Discrete Fourier transforms ------------------------------------------------------------------------------- If `f` is a function `\mathbb Z/q\mathbb Z\to \mathbb C`, its discrete Fourier transform is the function defined on Dirichlet characters mod `q` by .. math:: \hat f(\chi) = \sum_{x\mod q}\overline{\chi(x)}f(x) See the :ref:`acb-dft` module. Here we take advantage of the Conrey isomorphism `G \to \hat G` to consider the Fourier transform on Conrey labels as .. math:: g(a) = \sum_{b\bmod q}\overline{\chi_q(a,b)}f(b) .. function:: void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) Compute the DFT of *v* using Conrey indices. This function assumes *v* and *w* are vectors of size *G->phi_q*, whose values correspond to a lexicographic ordering of Conrey logs (as obtained using :func:`dirichlet_char_next` or by :func:`dirichlet_char_index`). For example, if `q=15`, the Conrey elements are stored in following order ======= ============= ===================== index log = [e,f] number = 7^e 11^f ======= ============= ===================== 0 [0, 0] 1 1 [0, 1] 7 2 [0, 2] 4 3 [0, 3] 13 4 [0, 4] 1 5 [1, 0] 11 6 [1, 1] 2 7 [1, 2] 14 8 [1, 3] 8 9 [1, 4] 11 ======= ============= ===================== .. function:: void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) Compute the DFT of *v* using Conrey numbers. This function assumes *v* and *w* are vectors of size *G->q*. All values at index not coprime to *G->q* are ignored. Dirichlet L-functions ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) .. function:: void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Sets *res* to the root number `\epsilon(\chi)` for a primitive character *chi*, which appears in the functional equation (where `p` is the parity of `\chi`): .. math:: \left(\frac{q}{\pi}\right)^{\frac{s+p}2}\Gamma\left(\frac{s+p}2\right) L(s, \chi) = \epsilon(\chi) \left(\frac{q}{\pi}\right)^{\frac{1-s+p}2}\Gamma\left(\frac{1-s+p}2\right) L(1 - s, \overline\chi) - The *theta* variant uses the evaluation at `t=1` of the Theta series. - The default version computes it via the gauss sum. .. function:: void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_hurwitz_precomp_t precomp, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Computes `L(s,\chi)` using decomposition in terms of the Hurwitz zeta function .. math:: L(s,\chi) = q^{-s}\sum_{k=1}^q \chi(k) \,\zeta\!\left(s,\frac kq\right). If `s = 1` and `\chi` is non-principal, the deflated Hurwitz zeta function is used to avoid poles. If *precomp* is *NULL*, each Hurwitz zeta function value is computed directly. If a pre-initialized *precomp* object is provided, this will be used instead to evaluate the Hurwitz zeta function. .. function:: void acb_dirichlet_l_euler_product(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) .. function:: void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, const signed char * chi, int mod, int reciprocal, slong prec) Computes `L(s,\chi)` directly using the Euler product. This is efficient if *s* has large positive real part. As implemented, this function only gives a finite result if `\operatorname{re}(s) \ge 2`. An error bound is computed via :func:`mag_hurwitz_zeta_uiui`. If *s* is complex, replace it with its real part. Since .. math:: \frac{1}{L(s,\chi)} = \prod_{p} \left(1 - \frac{\chi(p)}{p^s}\right) = \sum_{k=1}^{\infty} \frac{\mu(k)\chi(k)}{k^s} and the truncated product gives all smooth-index terms in the series, we have .. math:: \left|\prod_{p < N} \left(1 - \frac{\chi(p)}{p^s}\right) - \frac{1}{L(s,\chi)}\right| \le \sum_{k=N}^{\infty} \frac{1}{k^s} = \zeta(s,N). The underscore version specialized for integer *s* assumes that `\chi` is a real Dirichlet character given by the explicit list *chi* of character values at 0, 1, ..., *mod* - 1. If *reciprocal* is set, it computes `1 / L(s,\chi)` (this is faster if the reciprocal can be used directly). .. function:: void acb_dirichlet_l(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Computes `L(s,\chi)` using a default choice of algorithm. .. function:: void acb_dirichlet_l_fmpq(acb_t res, const fmpq_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) void acb_dirichlet_l_fmpq_afe(acb_t res, const fmpq_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Computes `L(s,\chi)` where *s* is a rational number. The *afe* version uses the approximate functional equation; the default version chooses an algorithm automatically. .. function:: void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_hurwitz_precomp_t precomp, const dirichlet_group_t G, slong prec) Compute all values `L(s,\chi)` for `\chi` mod `q`, using the Hurwitz zeta function and a discrete Fourier transform. The output *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered Conrey logs. See :func:`acb_dirichlet_dft_conrey`. If *precomp* is *NULL*, each Hurwitz zeta function value is computed directly. If a pre-initialized *precomp* object is provided, this will be used instead to evaluate the Hurwitz zeta function. .. function:: void acb_dirichlet_l_jet(acb_ptr res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec) Computes the Taylor expansion of `L(s,\chi)` to length *len*, i.e. `L(s), L'(s), \ldots, L^{(len-1)}(s) / (len-1)!`. If *deflate* is set, computes the expansion of .. math:: L(s,\chi) - \frac{\sum_{k=1}^q \chi(k)}{(s-1)q} instead. If *chi* is a principal character, then this has the effect of subtracting the pole with residue `\sum_{k=1}^q \chi(k) = \phi(q) / q` that is located at `s = 1`. In particular, when evaluated at `s = 1`, this gives the regular part of the Laurent expansion. When *chi* is non-principal, *deflate* has no effect. .. function:: void _acb_dirichlet_l_series(acb_ptr res, acb_srcptr s, slong slen, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec) .. function:: void acb_dirichlet_l_series(acb_poly_t res, const acb_poly_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec) Sets *res* to the power series `L(s,\chi)` where *s* is a given power series, truncating the result to length *len*. See :func:`acb_dirichlet_l_jet` for the meaning of the *deflate* flag. Hardy Z-functions ------------------------------------------------------------------------------- For convenience, setting both *G* and *chi* to *NULL* in the following methods selects the Riemann zeta function. Currently, these methods require *chi* to be a primitive character. .. function:: void acb_dirichlet_hardy_theta(acb_ptr res, const acb_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) Computes the phase function used to construct the Z-function. We have .. math:: \theta(t) = -\frac{t}{2} \log(\pi/q) - \frac{i \log(\epsilon)}{2} + \frac{\log \Gamma((s+\delta)/2) - \log \Gamma((1-s+\delta)/2)}{2i} where `s = 1/2+it`, `\delta` is the parity of *chi*, and `\epsilon` is the root number as computed by :func:`acb_dirichlet_root_number`. The first *len* terms in the Taylor expansion are written to the output. .. function:: void acb_dirichlet_hardy_z(acb_ptr res, const acb_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) Computes the Hardy Z-function, also known as the Riemann-Siegel Z-function `Z(t) = e^{i \theta(t)} L(1/2+it)`, which is real-valued for real *t*. The first *len* terms in the Taylor expansion are written to the output. .. function:: void _acb_dirichlet_hardy_theta_series(acb_ptr res, acb_srcptr t, slong tlen, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) .. function:: void acb_dirichlet_hardy_theta_series(acb_poly_t res, const acb_poly_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) Sets *res* to the power series `\theta(t)` where *t* is a given power series, truncating the result to length *len*. .. function:: void _acb_dirichlet_hardy_z_series(acb_ptr res, acb_srcptr t, slong tlen, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) .. function:: void acb_dirichlet_hardy_z_series(acb_poly_t res, const acb_poly_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) Sets *res* to the power series `Z(t)` where *t* is a given power series, truncating the result to length *len*. Gram points ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_gram_point(arb_t res, const fmpz_t n, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Sets *res* to the *n*-th Gram point `g_n`, defined as the unique solution in `[7, \infty)` of `\theta(g_n) = \pi n`. Currently only the Gram points corresponding to the Riemann zeta function are supported and *G* and *chi* must both be set to *NULL*. Requires `n \ge -1`. Riemann zeta function zeros ------------------------------------------------------------------------------- The following functions for counting and isolating zeros of the Riemann zeta function use the ideas from the implementation of Turing's method in mpmath [Joh2018b]_ by Juan Arias de Reyna, described in [Ari2012]_. .. function:: ulong acb_dirichlet_turing_method_bound(const fmpz_t p) Computes an upper bound *B* for the minimum number of consecutive good Gram blocks sufficient to count nontrivial zeros of the Riemann zeta function using Turing's method [Tur1953]_ as updated by [Leh1970]_, [Bre1979]_, and [Tru2011]_. Let `N(T)` denote the number of zeros (counted according to their multiplicities) of `\zeta(s)` in the region `0 < \operatorname{Im}(s) \le T`. If at least *B* consecutive Gram blocks with union `[g_n, g_p)` satisfy Rosser's rule, then `N(g_n) \le n + 1` and `N(g_p) \ge p + 1`. .. function:: int _acb_dirichlet_definite_hardy_z(arb_t res, const arf_t t, slong * pprec) Sets *res* to the Hardy Z-function `Z(t)`. The initial precision (* *pprec*) is increased as necessary to determine the sign of `Z(t)`. The sign is returned. .. function:: void _acb_dirichlet_isolate_gram_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) Uses Gram's law to compute an interval `(a, b)` that contains the *n*-th zero of the Hardy Z-function and no other zero. Requires `1 \le n \le 126`. .. function:: void _acb_dirichlet_isolate_rosser_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) Uses Rosser's rule to compute an interval `(a, b)` that contains the *n*-th zero of the Hardy Z-function and no other zero. Requires `1 \le n \le 13999526`. .. function:: void _acb_dirichlet_isolate_turing_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) Computes an interval `(a, b)` that contains the *n*-th zero of the Hardy Z-function and no other zero, following Turing's method. Requires `n \ge 2`. .. function:: void acb_dirichlet_isolate_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) Computes an interval `(a, b)` that contains the *n*-th zero of the Hardy Z-function and contains no other zero, using the most appropriate underscore version of this function. Requires `n \ge 1`. .. function:: void _acb_dirichlet_refine_hardy_z_zero(arb_t res, const arf_t a, const arf_t b, slong prec) Sets *res* to the unique zero of the Hardy Z-function in the interval `(a, b)`. .. function:: void acb_dirichlet_hardy_z_zero(arb_t res, const fmpz_t n, slong prec) Sets *res* to the *n*-th zero of the Hardy Z-function, requiring `n \ge 1`. .. function:: void acb_dirichlet_hardy_z_zeros(arb_ptr res, const fmpz_t n, slong len, slong prec) Sets the entries of *res* to *len* consecutive zeros of the Hardy Z-function, beginning with the *n*-th zero. Requires positive *n*. .. function:: void acb_dirichlet_zeta_zero(acb_t res, const fmpz_t n, slong prec) Sets *res* to the *n*-th nontrivial zero of `\zeta(s)`, requiring `n \ge 1`. .. function:: void acb_dirichlet_zeta_zeros(acb_ptr res, const fmpz_t n, slong len, slong prec) Sets the entries of *res* to *len* consecutive nontrivial zeros of `\zeta(s)` beginning with the *n*-th zero. Requires positive *n*. .. function:: void _acb_dirichlet_exact_zeta_nzeros(fmpz_t res, const arf_t t) .. function:: void acb_dirichlet_zeta_nzeros(arb_t res, const arb_t t, slong prec) Compute the number of zeros (counted according to their multiplicities) of `\zeta(s)` in the region `0 < \operatorname{Im}(s) \le t`. .. function:: void acb_dirichlet_backlund_s(arb_t res, const arb_t t, slong prec) Compute `S(t) = \frac{1}{\pi}\operatorname{arg}\zeta(\frac{1}{2} + it)` where the argument is defined by continuous variation of `s` in `\zeta(s)` starting at `s = 2`, then vertically to `s = 2 + it`, then horizontally to `s = \frac{1}{2} + it`. In particular `\operatorname{arg}` in this context is not the principal value of the argument, and it cannot be computed directly by :func:`acb_arg`. In practice `S(t)` is computed as `S(t) = N(t) - \frac{1}{\pi}\theta(t) - 1` where `N(t)` is :func:`acb_dirichlet_zeta_nzeros` and `\theta(t)` is :func:`acb_dirichlet_hardy_theta`. .. function:: void acb_dirichlet_backlund_s_bound(mag_t res, const arb_t t) Compute an upper bound for `|S(t)|` quickly. Theorem 1 and the bounds in (1.2) in [Tru2014]_ are used. .. function:: void acb_dirichlet_zeta_nzeros_gram(fmpz_t res, const fmpz_t n) Compute `N(g_n)`. That is, compute the number of zeros (counted according to their multiplicities) of `\zeta(s)` in the region `0 < \operatorname{Im}(s) \le g_n` where `g_n` is the *n*-th Gram point. Requires `n \ge -1`. .. function:: slong acb_dirichlet_backlund_s_gram(const fmpz_t n) Compute `S(g_n)` where `g_n` is the *n*-th Gram point. Requires `n \ge -1`. Riemann zeta function zeros (Platt's method) ------------------------------------------------------------------------------- The following functions related to the Riemann zeta function use the ideas and formulas described by David J. Platt in [Pla2017]_. .. function:: void acb_dirichlet_platt_scaled_lambda(arb_t res, const arb_t t, slong prec) Compute `\Lambda(t) e^{\pi t/4}` where .. math:: \Lambda(t) = \pi^{-\frac{it}{2}} \Gamma\left(\frac{\frac{1}{2}+it}{2}\right) \zeta\left(\frac{1}{2} + it\right) is defined in the beginning of section 3 of [Pla2017]_. As explained in [Pla2011]_ this function has the same zeros as `\zeta(1/2 + it)` and is real-valued by the functional equation, and the exponential factor is designed to counteract the decay of the gamma factor as `t` increases. .. function:: void acb_dirichlet_platt_scaled_lambda_vec(arb_ptr res, const fmpz_t T, slong A, slong B, slong prec) .. function:: void acb_dirichlet_platt_multieval(arb_ptr res, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec) .. function:: void acb_dirichlet_platt_multieval_threaded(arb_ptr res, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec) Compute :func:`acb_dirichlet_platt_scaled_lambda` at `N=AB` points on a grid, following the notation of [Pla2017]_. The first point on the grid is `T - B/2` and the distance between grid points is `1/A`. The product `N=AB` must be an even integer. The multieval versions evaluate the function at all points on the grid simultaneously using discrete Fourier transforms, and they require the four additional tuning parameters *h*, *J*, *K*, and *sigma*. The *threaded* multieval version splits the computation over the number of threads returned by *flint_get_num_threads()*, while the default multieval version chooses whether to use multithreading automatically. .. function:: void acb_dirichlet_platt_ws_interpolation(arb_t res, arf_t deriv, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong Ns_max, const arb_t H, slong sigma, slong prec) Compute :func:`acb_dirichlet_platt_scaled_lambda` at *t0* by Gaussian-windowed Whittaker-Shannon interpolation of points evaluated by :func:`acb_dirichlet_platt_scaled_lambda_vec`. The derivative is also approximated if the output parameter *deriv* is not *NULL*. *Ns_max* defines the maximum number of supporting points to be used in the interpolation on either side of *t0*. *H* is the standard deviation of the Gaussian window centered on *t0* to be applied before the interpolation. *sigma* is an odd positive integer tuning parameter `\sigma \in 2\mathbb{Z}_{>0}+1` used in computing error bounds. .. function:: slong _acb_dirichlet_platt_local_hardy_z_zeros(arb_ptr res, const fmpz_t n, slong len, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma_grid, slong Ns_max, const arb_t H, slong sigma_interp, slong prec) .. function:: slong acb_dirichlet_platt_local_hardy_z_zeros(arb_ptr res, const fmpz_t n, slong len, slong prec) .. function:: slong acb_dirichlet_platt_hardy_z_zeros(arb_ptr res, const fmpz_t n, slong len, slong prec) Sets at most the first *len* entries of *res* to consecutive zeros of the Hardy Z-function starting with the *n*-th zero. The number of obtained consecutive zeros is returned. The first two function variants each make a single call to Platt's grid evaluation of the scaled Lambda function, whereas the third variant performs as many evaluations as necessary to obtain *len* consecutive zeros. The final several parameters of the underscored local variant have the same meanings as in the functions :func:`acb_dirichlet_platt_multieval` and :func:`acb_dirichlet_platt_ws_interpolation`. The non-underscored variants currently expect `10^4 \leq n \leq 10^{23}`. The user has the option of multi-threading through *flint_set_num_threads(numthreads)*. .. function:: slong acb_dirichlet_platt_zeta_zeros(acb_ptr res, const fmpz_t n, slong len, slong prec) Sets at most the first *len* entries of *res* to consecutive zeros of the Riemann zeta function starting with the *n*-th zero. The number of obtained consecutive zeros is returned. It currently expects `10^4 \leq n \leq 10^{23}`. The user has the option of multi-threading through *flint_set_num_threads(numthreads)*. flint-3.1.3/doc/source/acb_elliptic.rst000066400000000000000000000353111461254215100200470ustar00rootroot00000000000000.. _acb-elliptic: **acb_elliptic.h** -- elliptic integrals and functions of complex variables =============================================================================== This module supports computation of elliptic (doubly periodic) functions, and their inverses, elliptic integrals. See :ref:`acb_modular.h ` for the closely related modular forms and Jacobi theta functions. Warning: incomplete elliptic integrals have very complicated branch structure when extended to complex variables. For some functions in this module, branch cuts may be artifacts of the evaluation algorithm rather than having a natural mathematical justification. The user should, accordingly, watch out for edge cases where the functions implemented here may differ from other systems or literature. There may also exist points where a function should be well-defined but the implemented algorithm fails to produce a finite result due to artificial internal singularities. Complete elliptic integrals ------------------------------------------------------------------------------- .. function:: void acb_elliptic_k(acb_t res, const acb_t m, slong prec) Computes the complete elliptic integral of the first kind .. math:: K(m) = \int_0^{\pi/2} \frac{dt}{\sqrt{1-m \sin^2 t}} = \int_0^1 \frac{dt}{\left(\sqrt{1-t^2}\right)\left(\sqrt{1-mt^2}\right)} using the arithmetic-geometric mean: `K(m) = \pi / (2 M(\sqrt{1-m}))`. .. function:: void acb_elliptic_k_jet(acb_ptr res, const acb_t m, slong len, slong prec) Sets the coefficients in the array *res* to the power series expansion of the complete elliptic integral of the first kind at the point *m* truncated to length *len*, i.e. `K(m+x) \in \mathbb{C}[[x]]`. .. function:: void _acb_elliptic_k_series(acb_ptr res, acb_srcptr m, slong mlen, slong len, slong prec) .. function:: void acb_elliptic_k_series(acb_poly_t res, const acb_poly_t m, slong len, slong prec) Sets *res* to the complete elliptic integral of the first kind of the power series *m*, truncated to length *len*. .. function:: void acb_elliptic_e(acb_t res, const acb_t m, slong prec) Computes the complete elliptic integral of the second kind .. math:: E(m) = \int_0^{\pi/2} \sqrt{1-m \sin^2 t} \, dt = \int_0^1 \frac{\sqrt{1-mt^2}}{\sqrt{1-t^2}} \, dt using `E(m) = (1-m)(2m K'(m) + K(m))` (where the prime denotes a derivative, not a complementary integral). .. function:: void acb_elliptic_pi(acb_t res, const acb_t n, const acb_t m, slong prec) Evaluates the complete elliptic integral of the third kind .. math:: \Pi(n, m) = \int_0^{\pi/2} \frac{dt}{(1-n \sin^2 t) \sqrt{1-m \sin^2 t}} = \int_0^1 \frac{dt}{(1-nt^2) \sqrt{1-t^2} \sqrt{1-mt^2}}. This implementation currently uses the same algorithm as the corresponding incomplete integral. It is therefore less efficient than the implementations of the first two complete elliptic integrals which use the AGM. Legendre incomplete elliptic integrals ------------------------------------------------------------------------------- .. function:: void acb_elliptic_f(acb_t res, const acb_t phi, const acb_t m, int pi, slong prec) Evaluates the Legendre incomplete elliptic integral of the first kind, given by .. math:: F(\phi,m) = \int_0^{\phi} \frac{dt}{\sqrt{1-m \sin^2 t}} = \int_0^{\sin \phi} \frac{dt}{\left(\sqrt{1-t^2}\right)\left(\sqrt{1-mt^2}\right)} on the standard strip `-\pi/2 \le \operatorname{Re}(\phi) \le \pi/2`. Outside this strip, the function extends quasiperiodically as .. math:: F(\phi + n \pi, m) = 2 n K(m) + F(\phi,m), n \in \mathbb{Z}. Inside the standard strip, the function is computed via the symmetric integral `R_F`. If the flag *pi* is set to 1, the variable `\phi` is replaced by `\pi \phi`, changing the quasiperiod to 1. The function reduces to a complete elliptic integral of the first kind when `\phi = \frac{\pi}{2}`; that is, `F\left(\frac{\pi}{2}, m\right) = K(m)`. .. function:: void acb_elliptic_e_inc(acb_t res, const acb_t phi, const acb_t m, int pi, slong prec) Evaluates the Legendre incomplete elliptic integral of the second kind, given by .. math:: E(\phi,m) = \int_0^{\phi} \sqrt{1-m \sin^2 t} \, dt = \int_0^{\sin \phi} \frac{\sqrt{1-mt^2}}{\sqrt{1-t^2}} \, dt on the standard strip `-\pi/2 \le \operatorname{Re}(\phi) \le \pi/2`. Outside this strip, the function extends quasiperiodically as .. math:: E(\phi + n \pi, m) = 2 n E(m) + E(\phi,m), n \in \mathbb{Z}. Inside the standard strip, the function is computed via the symmetric integrals `R_F` and `R_D`. If the flag *pi* is set to 1, the variable `\phi` is replaced by `\pi \phi`, changing the quasiperiod to 1. The function reduces to a complete elliptic integral of the second kind when `\phi = \frac{\pi}{2}`; that is, `E\left(\frac{\pi}{2}, m\right) = E(m)`. .. function:: void acb_elliptic_pi_inc(acb_t res, const acb_t n, const acb_t phi, const acb_t m, int pi, slong prec) Evaluates the Legendre incomplete elliptic integral of the third kind, given by .. math:: \Pi(n, \phi, m) = \int_0^{\phi} \frac{dt}{(1-n \sin^2 t) \sqrt{1-m \sin^2 t}} = \int_0^{\sin \phi} \frac{dt}{(1-nt^2) \sqrt{1-t^2} \sqrt{1-mt^2}} on the standard strip `-\pi/2 \le \operatorname{Re}(\phi) \le \pi/2`. Outside this strip, the function extends quasiperiodically as .. math:: \Pi(n, \phi + k \pi, m) = 2 k \Pi(n,m) + \Pi(n,\phi,m), k \in \mathbb{Z}. Inside the standard strip, the function is computed via the symmetric integrals `R_F` and `R_J`. If the flag *pi* is set to 1, the variable `\phi` is replaced by `\pi \phi`, changing the quasiperiod to 1. The function reduces to a complete elliptic integral of the third kind when `\phi = \frac{\pi}{2}`; that is, `\Pi\left(n, \frac{\pi}{2}, m\right) = \Pi(n, m)`. Carlson symmetric elliptic integrals ------------------------------------------------------------------------------- Carlson symmetric forms are the preferred form of incomplete elliptic integrals, due to their neat properties and relatively simple computation based on duplication theorems. There are five named functions: `R_F, R_G, R_J`, and `R_C`, `R_D` which are special cases of `R_F` and `R_J` respectively. We largely follow the definitions and algorithms in [Car1995]_ and chapter 19 in [NIST2012]_. .. function:: void acb_elliptic_rf(acb_t res, const acb_t x, const acb_t y, const acb_t z, int flags, slong prec) Evaluates the Carlson symmetric elliptic integral of the first kind .. math:: R_F(x,y,z) = \frac{1}{2} \int_0^{\infty} \frac{dt}{\sqrt{(t+x)(t+y)(t+z)}} where the square root extends continuously from positive infinity. The integral is well-defined for `x,y,z \notin (-\infty,0)`, and with at most one of `x,y,z` being zero. When some parameters are negative real numbers, the function is still defined by analytic continuation. In general, one or more duplication steps are applied until `x,y,z` are close enough to use a multivariate Taylor series. The special case `R_C(x, y) = R_F(x, y, y) = \frac{1}{2} \int_0^{\infty} (t+x)^{-1/2} (t+y)^{-1} dt` may be computed by setting *y* and *z* to the same variable. (This case is not yet handled specially, but might be optimized in the future.) The *flags* parameter is reserved for future use and currently does nothing. Passing 0 results in default behavior. .. function:: void acb_elliptic_rg(acb_t res, const acb_t x, const acb_t y, const acb_t z, int flags, slong prec) Evaluates the Carlson symmetric elliptic integral of the second kind .. math:: R_G(x,y,z) = \frac{1}{4} \int_0^{\infty} \frac{t}{\sqrt{(t+x)(t+y)(t+z)}} \left( \frac{x}{t+x} + \frac{y}{t+y} + \frac{z}{t+z}\right) dt where the square root is taken continuously as in `R_F`. The evaluation is done by expressing `R_G` in terms of `R_F` and `R_D`. There are no restrictions on the variables. .. function:: void acb_elliptic_rj(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec) .. function:: void acb_elliptic_rj_carlson(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec) .. function:: void acb_elliptic_rj_integration(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec) Evaluates the Carlson symmetric elliptic integral of the third kind .. math:: R_J(x,y,z,p) = \frac{3}{2} \int_0^{\infty} \frac{dt}{(t+p)\sqrt{(t+x)(t+y)(t+z)}} where the square root is taken continuously as in `R_F`. Three versions of this function are available: the *carlson* version applies one or more duplication steps until `x,y,z,p` are close enough to use a multivariate Taylor series. The duplication algorithm is not correct for all possible combinations of complex variables, since the square roots taken during the computation can introduce spurious branch cuts. According to [Car1995]_, a sufficient (but not necessary) condition for correctness is that *x*, *y*, *z* have nonnegative real part and that *p* has positive real part. In other cases, the algorithm *might* still be correct, but no attempt is made to check this; it is up to the user to verify that the duplication algorithm is appropriate for the given parameters before calling this function. The *integration* algorithm uses explicit numerical integration to translate the parameters to the right half-plane. This is reliable but can be slow. The default method uses the *carlson* algorithm when it is certain to be correct, and otherwise falls back to the slow *integration* algorithm. The special case `R_D(x, y, z) = R_J(x, y, z, z)` may be computed by setting *z* and *p* to the same variable. This case is handled specially to avoid redundant arithmetic operations. In this case, the *carlson* algorithm is correct for all *x*, *y* and *z*. The *flags* parameter is reserved for future use and currently does nothing. Passing 0 results in default behavior. .. function:: void acb_elliptic_rc1(acb_t res, const acb_t x, slong prec) This helper function computes the special case `R_C(1, 1+x) = \operatorname{atan}(\sqrt{x})/\sqrt{x} = {}_2F_1(1,1/2,3/2,-x)`, which is needed in the evaluation of `R_J`. Weierstrass elliptic functions ------------------------------------------------------------------------------- Elliptic functions may be defined on a general lattice `\Lambda = \{m 2\omega_1 + n 2\omega_2\ : m, n \in \mathbb{Z}\}` with half-periods `\omega_1, \omega_2`. We simplify by setting `2\omega_1 = 1, 2\omega_2 = \tau` with `\operatorname{im}(\tau) > 0`. To evaluate the functions on a general lattice, it is enough to make a linear change of variables. The main reference is chapter 23 in [NIST2012]_. .. function:: void acb_elliptic_p(acb_t res, const acb_t z, const acb_t tau, slong prec) Computes Weierstrass's elliptic function .. math:: \wp(z, \tau) = \frac{1}{z^2} + \sum_{n^2+m^2 \ne 0} \left[ \frac{1}{(z+m+n\tau)^2} - \frac{1}{(m+n\tau)^2} \right] which satisfies `\wp(z, \tau) = \wp(z + 1, \tau) = \wp(z + \tau, \tau)`. To evaluate the function efficiently, we use the formula .. math:: \wp(z, \tau) = \pi^2 \theta_2^2(0,\tau) \theta_3^2(0,\tau) \frac{\theta_4^2(z,\tau)}{\theta_1^2(z,\tau)} - \frac{\pi^2}{3} \left[ \theta_2^4(0,\tau) + \theta_3^4(0,\tau)\right]. .. function:: void acb_elliptic_p_prime(acb_t res, const acb_t z, const acb_t tau, slong prec) Computes the derivative `\wp'(z, \tau)` of Weierstrass's elliptic function `\wp(z, \tau)`. .. function:: void acb_elliptic_p_jet(acb_ptr res, const acb_t z, const acb_t tau, slong len, slong prec) Computes the formal power series `\wp(z + x, \tau) \in \mathbb{C}[[x]]`, truncated to length *len*. In particular, with *len* = 2, simultaneously computes `\wp(z, \tau), \wp'(z, \tau)` which together generate the field of elliptic functions with periods 1 and `\tau`. .. function:: void _acb_elliptic_p_series(acb_ptr res, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec) .. function:: void acb_elliptic_p_series(acb_poly_t res, const acb_poly_t z, const acb_t tau, slong len, slong prec) Sets *res* to the Weierstrass elliptic function of the power series *z*, with periods 1 and *tau*, truncated to length *len*. .. function:: void acb_elliptic_invariants(acb_t g2, acb_t g3, const acb_t tau, slong prec) Computes the lattice invariants `g_2, g_3`. The Weierstrass elliptic function satisfies the differential equation `[\wp'(z, \tau)]^2 = 4 [\wp(z,\tau)]^3 - g_2 \wp(z,\tau) - g_3`. Up to constant factors, the lattice invariants are the first two Eisenstein series (see :func:`acb_modular_eisenstein`). .. function:: void acb_elliptic_roots(acb_t e1, acb_t e2, acb_t e3, const acb_t tau, slong prec) Computes the lattice roots `e_1, e_2, e_3`, which are the roots of the polynomial `4z^3 - g_2 z - g_3`. .. function:: void acb_elliptic_inv_p(acb_t res, const acb_t z, const acb_t tau, slong prec) Computes the inverse of the Weierstrass elliptic function, which satisfies `\wp(\wp^{-1}(z, \tau), \tau) = z`. This function is given by the elliptic integral .. math:: \wp^{-1}(z, \tau) = \frac{1}{2} \int_z^{\infty} \frac{dt}{\sqrt{(t-e_1)(t-e_2)(t-e_3)}} = R_F(z-e_1,z-e_2,z-e_3). .. function:: void acb_elliptic_zeta(acb_t res, const acb_t z, const acb_t tau, slong prec) Computes the Weierstrass zeta function .. math:: \zeta(z, \tau) = \frac{1}{z} + \sum_{n^2+m^2 \ne 0} \left[ \frac{1}{z-m-n\tau} + \frac{1}{m+n\tau} + \frac{z}{(m+n\tau)^2} \right] which is quasiperiodic with `\zeta(z + 1, \tau) = \zeta(z, \tau) + \zeta(1/2, \tau)` and `\zeta(z + \tau, \tau) = \zeta(z, \tau) + \zeta(\tau/2, \tau)`. .. function:: void acb_elliptic_sigma(acb_t res, const acb_t z, const acb_t tau, slong prec) Computes the Weierstrass sigma function .. math:: \sigma(z, \tau) = z \prod_{n^2+m^2 \ne 0} \left[ \left(1-\frac{z}{m+n\tau}\right) \exp\left(\frac{z}{m+n\tau} + \frac{z^2}{2(m+n\tau)^2} \right) \right] which is quasiperiodic with `\sigma(z + 1, \tau) = -e^{2 \zeta(1/2, \tau) (z+1/2)} \sigma(z, \tau)` and `\sigma(z + \tau, \tau) = -e^{2 \zeta(\tau/2, \tau) (z+\tau/2)} \sigma(z, \tau)`. flint-3.1.3/doc/source/acb_hypgeom.rst000066400000000000000000001616651461254215100177260ustar00rootroot00000000000000.. _acb-hypgeom: **acb_hypgeom.h** -- hypergeometric functions of complex variables ================================================================================== The generalized hypergeometric function is formally defined by .. math:: {}_pF_q(a_1,\ldots,a_p;b_1,\ldots,b_q;z) = \sum_{k=0}^\infty \frac{(a_1)_k\dots(a_p)_k}{(b_1)_k\dots(b_q)_k} \frac {z^k} {k!}. It can be interpreted using analytic continuation or regularization when the sum does not converge. In a looser sense, we understand "hypergeometric functions" to be linear combinations of generalized hypergeometric functions with prefactors that are products of exponentials, powers, and gamma functions. Rising factorials ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_rising_ui_forward(acb_t res, const acb_t x, ulong n, slong prec) void acb_hypgeom_rising_ui_bs(acb_t res, const acb_t x, ulong n, slong prec) void acb_hypgeom_rising_ui_rs(acb_t res, const acb_t x, ulong n, ulong m, slong prec) void acb_hypgeom_rising_ui_rec(acb_t res, const acb_t x, ulong n, slong prec) void acb_hypgeom_rising_ui(acb_t res, const acb_t x, ulong n, slong prec) void acb_hypgeom_rising(acb_t res, const acb_t x, const acb_t n, slong prec) Computes the rising factorial `(x)_n`. The *forward* version uses the forward recurrence. The *bs* version uses binary splitting. The *rs* version uses rectangular splitting. It takes an extra tuning parameter *m* which can be set to zero to choose automatically. The *rec* version chooses an algorithm automatically, avoiding use of the gamma function (so that it can be used in the computation of the gamma function). The default versions (*rising_ui* and *rising_ui*) choose an algorithm automatically and may additionally fall back on the gamma function. .. function:: void acb_hypgeom_rising_ui_jet_powsum(acb_ptr res, const acb_t x, ulong n, slong len, slong prec) void acb_hypgeom_rising_ui_jet_bs(acb_ptr res, const acb_t x, ulong n, slong len, slong prec) void acb_hypgeom_rising_ui_jet_rs(acb_ptr res, const acb_t x, ulong n, ulong m, slong len, slong prec) void acb_hypgeom_rising_ui_jet(acb_ptr res, const acb_t x, ulong n, slong len, slong prec) Computes the jet of the rising factorial `(x)_n`, truncated to length *len*. In other words, constructs the polynomial `(X + x)_n \in \mathbb{R}[X]`, truncated if `\operatorname{len} < n + 1` (and zero-extended if `\operatorname{len} > n + 1`). The *powsum* version computes the sequence of powers of *x* and forms integral linear combinations of these. The *bs* version uses binary splitting. The *rs* version uses rectangular splitting. It takes an extra tuning parameter *m* which can be set to zero to choose automatically. The default version chooses an algorithm automatically. .. function:: void acb_hypgeom_log_rising_ui(acb_ptr res, const acb_t x, ulong n, slong prec) Computes the log-rising factorial `\log \, (x)_n = \sum_{k=0}^{n-1} \log(x+k)`. This first computes the ordinary rising factorial and then determines the branch correction `2 \pi i m` with respect to the principal logarithm. The correction is computed using Hare's algorithm in floating-point arithmetic if this is safe; otherwise, a direct computation of `\sum_{k=0}^{n-1} \arg(x+k)` is used as a fallback. .. function:: void acb_hypgeom_log_rising_ui_jet(acb_ptr res, const acb_t x, ulong n, slong len, slong prec) Computes the jet of the log-rising factorial `\log \, (x)_n`, truncated to length *len*. Gamma function ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_gamma_stirling_sum_horner(acb_t s, const acb_t z, slong N, slong prec) void acb_hypgeom_gamma_stirling_sum_improved(acb_t s, const acb_t z, slong N, slong K, slong prec) Sets *res* to the final sum in the Stirling series for the gamma function truncated before the term with index *N*, i.e. computes `\sum_{n=1}^{N-1} B_{2n} / (2n(2n-1) z^{2n-1})`. The *horner* version uses Horner scheme with gradual precision adjustments. The *improved* version uses rectangular splitting for the low-index terms and reexpands the high-index terms as hypergeometric polynomials, using a splitting parameter *K* (which can be set to 0 to use a default value). .. function:: void acb_hypgeom_gamma_stirling(acb_t res, const acb_t x, int reciprocal, slong prec) Sets *res* to the gamma function of *x* computed using the Stirling series together with argument reduction. If *reciprocal* is set, the reciprocal gamma function is computed instead. .. function:: int acb_hypgeom_gamma_taylor(acb_t res, const acb_t x, int reciprocal, slong prec) Attempts to compute the gamma function of *x* using Taylor series together with argument reduction. This is only supported if *x* and *prec* are both small enough. If successful, returns 1; otherwise, does nothing and returns 0. If *reciprocal* is set, the reciprocal gamma function is computed instead. .. function:: void acb_hypgeom_gamma(acb_t res, const acb_t x, slong prec) Sets *res* to the gamma function of *x* computed using a default algorithm choice. .. function:: void acb_hypgeom_rgamma(acb_t res, const acb_t x, slong prec) Sets *res* to the reciprocal gamma function of *x* computed using a default algorithm choice. .. function:: void acb_hypgeom_lgamma(acb_t res, const acb_t x, slong prec) Sets *res* to the principal branch of the log-gamma function of *x* computed using a default algorithm choice. Convergent series ------------------------------------------------------------------------------- In this section, we define .. math:: T(k) = \frac{\prod_{i=0}^{p-1} (a_i)_k}{\prod_{i=0}^{q-1} (b_i)_k} z^k and .. math:: {}_pf_{q}(a_0,\ldots,a_{p-1}; b_0 \ldots b_{q-1}; z) = {}_{p+1}F_{q}(a_0,\ldots,a_{p-1},1; b_0 \ldots b_{q-1}; z) = \sum_{k=0}^{\infty} T(k) For the conventional generalized hypergeometric function `{}_pF_{q}`, compute `{}_pf_{q+1}` with the explicit parameter `b_q = 1`, or remove a 1 from the `a_i` parameters if there is one. .. function:: void acb_hypgeom_pfq_bound_factor(mag_t C, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, ulong n) Computes a factor *C* such that `\left|\sum_{k=n}^{\infty} T(k)\right| \le C |T(n)|`. See :ref:`algorithms_hypergeometric_convergent`. As currently implemented, the bound becomes infinite when `n` is too small, even if the series converges. .. function:: slong acb_hypgeom_pfq_choose_n(acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong prec) Heuristically attempts to choose a number of terms *n* to sum of a hypergeometric series at a working precision of *prec* bits. Uses double precision arithmetic internally. As currently implemented, it can fail to produce a good result if the parameters are extremely large or extremely close to nonpositive integers. Numerical cancellation is assumed to be significant, so truncation is done when the current term is *prec* bits smaller than the largest encountered term. This function will also attempt to pick a reasonable truncation point for divergent series. .. function:: void acb_hypgeom_pfq_sum_forward(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) .. function:: void acb_hypgeom_pfq_sum_rs(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) .. function:: void acb_hypgeom_pfq_sum_bs(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) .. function:: void acb_hypgeom_pfq_sum_fme(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) .. function:: void acb_hypgeom_pfq_sum(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) Computes `s = \sum_{k=0}^{n-1} T(k)` and `t = T(n)`. Does not allow aliasing between input and output variables. We require `n \ge 0`. The *forward* version computes the sum using forward recurrence. The *bs* version computes the sum using binary splitting. The *rs* version computes the sum in reverse order using rectangular splitting. It only computes a magnitude bound for the value of *t*. The *fme* version uses fast multipoint evaluation. The default version automatically chooses an algorithm depending on the inputs. .. function:: void acb_hypgeom_pfq_sum_bs_invz(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t w, slong n, slong prec) .. function:: void acb_hypgeom_pfq_sum_invz(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, const acb_t w, slong n, slong prec) Like :func:`acb_hypgeom_pfq_sum`, but taking advantage of `w = 1/z` possibly having few bits. .. function:: void acb_hypgeom_pfq_direct(acb_t res, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) Computes .. math:: {}_pf_{q}(z) = \sum_{k=0}^{\infty} T(k) = \sum_{k=0}^{n-1} T(k) + \varepsilon directly from the defining series, including a rigorous bound for the truncation error `\varepsilon` in the output. If `n < 0`, this function chooses a number of terms automatically using :func:`acb_hypgeom_pfq_choose_n`. .. function:: void acb_hypgeom_pfq_series_sum_forward(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) .. function:: void acb_hypgeom_pfq_series_sum_bs(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) .. function:: void acb_hypgeom_pfq_series_sum_rs(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) .. function:: void acb_hypgeom_pfq_series_sum(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) Computes `s = \sum_{k=0}^{n-1} T(k)` and `t = T(n)` given parameters and argument that are power series. Does not allow aliasing between input and output variables. We require `n \ge 0` and that *len* is positive. If *regularized* is set, the regularized sum is computed, avoiding division by zero at the poles of the gamma function. The *forward*, *bs*, *rs* and default versions use forward recurrence, binary splitting, rectangular splitting, and an automatic algorithm choice. .. function:: void acb_hypgeom_pfq_series_direct(acb_poly_t res, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) Computes `{}_pf_{q}(z)` directly using the defining series, given parameters and argument that are power series. The result is a power series of length *len*. We require that *len* is positive. An error bound is computed automatically as a function of the number of terms *n*. If `n < 0`, the number of terms is chosen automatically. If *regularized* is set, the regularized hypergeometric function is computed instead. Asymptotic series ------------------------------------------------------------------------------- `U(a,b,z)` is the confluent hypergeometric function of the second kind with the principal branch cut, and `U^{*} = z^a U(a,b,z)`. For details about how error bounds are computed, see :ref:`algorithms_hypergeometric_asymptotic_confluent`. .. function:: void acb_hypgeom_u_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong n, slong prec) Sets *res* to `U^{*}(a,b,z)` computed using *n* terms of the asymptotic series, with a rigorous bound for the error included in the output. We require `n \ge 0`. .. function:: int acb_hypgeom_u_use_asymp(const acb_t z, slong prec) Heuristically determines whether the asymptotic series can be used to evaluate `U(a,b,z)` to *prec* accurate bits (assuming that *a* and *b* are small). Generalized hypergeometric function ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_pfq(acb_t res, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, int regularized, slong prec) Computes the generalized hypergeometric function `{}_pF_{q}(z)`, or the regularized version if *regularized* is set. This function automatically delegates to a specialized implementation when the order (*p*, *q*) is one of (0,0), (1,0), (0,1), (1,1), (2,1). Otherwise, it falls back to direct summation. While this is a top-level function meant to take care of special cases automatically, it does not generally perform the optimization of deleting parameters that appear in both *a* and *b*. This can be done ahead of time by the user in applications where duplicate parameters are likely to occur. Confluent hypergeometric functions ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_u_1f1_series(acb_poly_t res, const acb_poly_t a, const acb_poly_t b, const acb_poly_t z, slong len, slong prec) Computes `U(a,b,z)` as a power series truncated to length *len*, given `a, b, z \in \mathbb{C}[[x]]`. If `b[0] \in \mathbb{Z}`, it computes one extra derivative and removes the singularity (it is then assumed that `b[1] \ne 0`). As currently implemented, the output is indeterminate if `b` is nonexact and contains an integer. .. function:: void acb_hypgeom_u_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec) Computes `U(a,b,z)` as a sum of two convergent hypergeometric series. If `b \in \mathbb{Z}`, it computes the limit value via :func:`acb_hypgeom_u_1f1_series`. As currently implemented, the output is indeterminate if `b` is nonexact and contains an integer. .. function:: void acb_hypgeom_u(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec) Computes `U(a,b,z)` using an automatic algorithm choice. The function :func:`acb_hypgeom_u_asymp` is used if `a` or `a-b+1` is a nonpositive integer (in which case the asymptotic series terminates), or if *z* is sufficiently large. Otherwise :func:`acb_hypgeom_u_1f1` is used. .. function:: void acb_hypgeom_m_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) Computes the confluent hypergeometric function `M(a,b,z) = {}_1F_1(a,b,z)`, or `\mathbf{M}(a,b,z) = \frac{1}{\Gamma(b)} {}_1F_1(a,b,z)` if *regularized* is set. .. function:: void acb_hypgeom_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) Alias for :func:`acb_hypgeom_m`. .. function:: void acb_hypgeom_0f1_asymp(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_0f1_direct(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_0f1(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec) Computes the confluent hypergeometric function `{}_0F_1(a,z)`, or `\frac{1}{\Gamma(a)} {}_0F_1(a,z)` if *regularized* is set, using asymptotic expansions, direct summation, or an automatic algorithm choice. The *asymp* version uses the asymptotic expansions of Bessel functions, together with the connection formulas .. math:: \frac{{}_0F_1(a,z)}{\Gamma(a)} = (-z)^{(1-a)/2} J_{a-1}(2 \sqrt{-z}) = z^{(1-a)/2} I_{a-1}(2 \sqrt{z}). The Bessel-*J* function is used in the left half-plane and the Bessel-*I* function is used in the right half-plane, to avoid loss of accuracy due to evaluating the square root on the branch cut. Error functions and Fresnel integrals ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_erf_propagated_error(mag_t re, mag_t im, const acb_t z) Sets *re* and *im* to upper bounds for the error in the real and imaginary part resulting from approximating the error function of *z* by the error function evaluated at the midpoint of *z*. Uses the first derivative. .. function:: void acb_hypgeom_erf_1f1a(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_erf_1f1b(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_erf_asymp(acb_t res, const acb_t z, int complementary, slong prec, slong prec2) Computes the error function respectively using .. math:: \operatorname{erf}(z) &= \frac{2z}{\sqrt{\pi}} {}_1F_1(\tfrac{1}{2}, \tfrac{3}{2}, -z^2) \operatorname{erf}(z) &= \frac{2z e^{-z^2}}{\sqrt{\pi}} {}_1F_1(1, \tfrac{3}{2}, z^2) \operatorname{erf}(z) &= \frac{z}{\sqrt{z^2}} \left(1 - \frac{e^{-z^2}}{\sqrt{\pi}} U(\tfrac{1}{2}, \tfrac{1}{2}, z^2)\right) = \frac{z}{\sqrt{z^2}} - \frac{e^{-z^2}}{z \sqrt{\pi}} U^{*}(\tfrac{1}{2}, \tfrac{1}{2}, z^2). The *asymp* version takes a second precision to use for the *U* term. It also takes an extra flag *complementary*, computing the complementary error function if set. .. function:: void acb_hypgeom_erf(acb_t res, const acb_t z, slong prec) Computes the error function using an automatic algorithm choice. If *z* is too small to use the asymptotic expansion, a working precision sufficient to circumvent cancellation in the hypergeometric series is determined automatically, and a bound for the propagated error is computed with :func:`acb_hypgeom_erf_propagated_error`. .. function:: void _acb_hypgeom_erf_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_erf_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the error function of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_erfc(acb_t res, const acb_t z, slong prec) Computes the complementary error function `\operatorname{erfc}(z) = 1 - \operatorname{erf}(z)`. This function avoids catastrophic cancellation for large positive *z*. .. function:: void _acb_hypgeom_erfc_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_erfc_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the complementary error function of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_erfi(acb_t res, const acb_t z, slong prec) Computes the imaginary error function `\operatorname{erfi}(z) = -i\operatorname{erf}(iz)`. This is a trivial wrapper of :func:`acb_hypgeom_erf`. .. function:: void _acb_hypgeom_erfi_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_erfi_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the imaginary error function of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_fresnel(acb_t res1, acb_t res2, const acb_t z, int normalized, slong prec) Sets *res1* to the Fresnel sine integral `S(z)` and *res2* to the Fresnel cosine integral `C(z)`. Optionally, just a single function can be computed by passing *NULL* as the other output variable. The definition `S(z) = \int_0^z \sin(t^2) dt` is used if *normalized* is 0, and `S(z) = \int_0^z \sin(\tfrac{1}{2} \pi t^2) dt` is used if *normalized* is 1 (the latter is the Abramowitz & Stegun convention). `C(z)` is defined analogously. .. function:: void _acb_hypgeom_fresnel_series(acb_ptr res1, acb_ptr res2, acb_srcptr z, slong zlen, int normalized, slong len, slong prec) .. function:: void acb_hypgeom_fresnel_series(acb_poly_t res1, acb_poly_t res2, const acb_poly_t z, int normalized, slong len, slong prec) Sets *res1* to the Fresnel sine integral and *res2* to the Fresnel cosine integral of the power series *z*, truncated to length *len*. Optionally, just a single function can be computed by passing *NULL* as the other output variable. Bessel functions ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_bessel_j_asymp(acb_t res, const acb_t nu, const acb_t z, slong prec) Computes the Bessel function of the first kind via :func:`acb_hypgeom_u_asymp`. For all complex `\nu, z`, we have .. math:: J_{\nu}(z) = \frac{z^{\nu}}{2^{\nu} e^{iz} \Gamma(\nu+1)} {}_1F_1(\nu+\tfrac{1}{2}, 2\nu+1, 2iz) = A_{+} B_{+} + A_{-} B_{-} where .. math:: A_{\pm} = z^{\nu} (z^2)^{-\tfrac{1}{2}-\nu} (\mp i z)^{\tfrac{1}{2}+\nu} (2 \pi)^{-1/2} = (\pm iz)^{-1/2-\nu} z^{\nu} (2 \pi)^{-1/2} .. math:: B_{\pm} = e^{\pm i z} U^{*}(\nu+\tfrac{1}{2}, 2\nu+1, \mp 2iz). Nicer representations of the factors `A_{\pm}` can be given depending conditionally on the parameters. If `\nu + \tfrac{1}{2} = n \in \mathbb{Z}`, we have `A_{\pm} = (\pm i)^{n} (2 \pi z)^{-1/2}`. And if `\operatorname{Re}(z) > 0`, we have `A_{\pm} = \exp(\mp i [(2\nu+1)/4] \pi) (2 \pi z)^{-1/2}`. .. function:: void acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, slong prec) Computes the Bessel function of the first kind from .. math:: J_{\nu}(z) = \frac{1}{\Gamma(\nu+1)} \left(\frac{z}{2}\right)^{\nu} {}_0F_1\left(\nu+1, -\frac{z^2}{4}\right). .. function:: void acb_hypgeom_bessel_j(acb_t res, const acb_t nu, const acb_t z, slong prec) Computes the Bessel function of the first kind `J_{\nu}(z)` using an automatic algorithm choice. .. function:: void acb_hypgeom_bessel_y(acb_t res, const acb_t nu, const acb_t z, slong prec) Computes the Bessel function of the second kind `Y_{\nu}(z)` from the formula .. math:: Y_{\nu}(z) = \frac{\cos(\nu \pi) J_{\nu}(z) - J_{-\nu}(z)}{\sin(\nu \pi)} unless `\nu = n` is an integer in which case the limit value .. math:: Y_n(z) = -\frac{2}{\pi} \left( i^n K_n(iz) + \left[\log(iz)-\log(z)\right] J_n(z) \right) is computed. As currently implemented, the output is indeterminate if `\nu` is nonexact and contains an integer. .. function:: void acb_hypgeom_bessel_jy(acb_t res1, acb_t res2, const acb_t nu, const acb_t z, slong prec) Sets *res1* to `J_{\nu}(z)` and *res2* to `Y_{\nu}(z)`, computed simultaneously. From these values, the user can easily construct the Bessel functions of the third kind (Hankel functions) `H_{\nu}^{(1)}(z), H_{\nu}^{(2)}(z) = J_{\nu}(z) \pm i Y_{\nu}(z)`. Modified Bessel functions ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_bessel_i_asymp(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) .. function:: void acb_hypgeom_bessel_i_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) .. function:: void acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, slong prec) .. function:: void acb_hypgeom_bessel_i_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec) Computes the modified Bessel function of the first kind `I_{\nu}(z) = z^{\nu} (iz)^{-\nu} J_{\nu}(iz)` respectively using asymptotic series (see :func:`acb_hypgeom_bessel_j_asymp`), the convergent series .. math:: I_{\nu}(z) = \frac{1}{\Gamma(\nu+1)} \left(\frac{z}{2}\right)^{\nu} {}_0F_1\left(\nu+1, \frac{z^2}{4}\right), or an automatic algorithm choice. The *scaled* version computes the function `e^{-z} I_{\nu}(z)`. The *asymp* and *0f1* functions implement both variants and allow choosing with a flag. .. function:: void acb_hypgeom_bessel_k_asymp(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) Computes the modified Bessel function of the second kind via via :func:`acb_hypgeom_u_asymp`. For all `\nu` and all `z \ne 0`, we have .. math:: K_{\nu}(z) = \left(\frac{2z}{\pi}\right)^{-1/2} e^{-z} U^{*}(\nu+\tfrac{1}{2}, 2\nu+1, 2z). If *scaled* is set, computes the function `e^{z} K_{\nu}(z)`. .. function:: void acb_hypgeom_bessel_k_0f1_series(acb_poly_t res, const acb_poly_t nu, const acb_poly_t z, int scaled, slong len, slong prec) Computes the modified Bessel function of the second kind `K_{\nu}(z)` as a power series truncated to length *len*, given `\nu, z \in \mathbb{C}[[x]]`. Uses the formula .. math:: K_{\nu}(z) = \frac{1}{2} \frac{\pi}{\sin(\pi \nu)} \left[ \left(\frac{z}{2}\right)^{-\nu} {}_0{\widetilde F}_1\left(1-\nu, \frac{z^2}{4}\right) - \left(\frac{z}{2}\right)^{\nu} {}_0{\widetilde F}_1\left(1+\nu, \frac{z^2}{4}\right) \right]. If `\nu[0] \in \mathbb{Z}`, it computes one extra derivative and removes the singularity (it is then assumed that `\nu[1] \ne 0`). As currently implemented, the output is indeterminate if `\nu[0]` is nonexact and contains an integer. If *scaled* is set, computes the function `e^{z} K_{\nu}(z)`. .. function:: void acb_hypgeom_bessel_k_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) Computes the modified Bessel function of the second kind from .. math:: K_{\nu}(z) = \frac{1}{2} \left[ \left(\frac{z}{2}\right)^{-\nu} \Gamma(\nu) {}_0F_1\left(1-\nu, \frac{z^2}{4}\right) - \left(\frac{z}{2}\right)^{\nu} \frac{\pi}{\nu \sin(\pi \nu) \Gamma(\nu)} {}_0F_1\left(\nu+1, \frac{z^2}{4}\right) \right] if `\nu \notin \mathbb{Z}`. If `\nu \in \mathbb{Z}`, it computes the limit value via :func:`acb_hypgeom_bessel_k_0f1_series`. As currently implemented, the output is indeterminate if `\nu` is nonexact and contains an integer. If *scaled* is set, computes the function `e^{z} K_{\nu}(z)`. .. function:: void acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, slong prec) Computes the modified Bessel function of the second kind `K_{\nu}(z)` using an automatic algorithm choice. .. function:: void acb_hypgeom_bessel_k_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec) Computes the function `e^{z} K_{\nu}(z)`. Airy functions ------------------------------------------------------------------------------- The Airy functions are linearly independent solutions of the differential equation `y'' - zy = 0`. All solutions are entire functions. The standard solutions are denoted `\operatorname{Ai}(z), \operatorname{Bi}(z)`. For negative *z*, both functions are oscillatory. For positive *z*, the first function decreases exponentially while the second increases exponentially. The Airy functions can be expressed in terms of Bessel functions of fractional order, but this is inconvenient since such formulas only hold piecewise (due to the Stokes phenomenon). Computation of the Airy functions can also be optimized more than Bessel functions in general. We therefore provide a dedicated interface for evaluating Airy functions. The following methods optionally compute `(\operatorname{Ai}(z), \operatorname{Ai}'(z), \operatorname{Bi}(z), \operatorname{Bi}'(z))` simultaneously. Any of the four function values can be omitted by passing *NULL* for the unwanted output variables, speeding up the evaluation. .. function:: void acb_hypgeom_airy_direct(acb_t ai, acb_t ai_prime, acb_t bi, acb_t bi_prime, const acb_t z, slong n, slong prec) Computes the Airy functions using direct series expansions truncated at *n* terms. Error bounds are included in the output. .. function:: void acb_hypgeom_airy_asymp(acb_t ai, acb_t ai_prime, acb_t bi, acb_t bi_prime, const acb_t z, slong n, slong prec) Computes the Airy functions using asymptotic expansions truncated at *n* terms. Error bounds are included in the output. For details about how the error bounds are computed, see :ref:`algorithms_hypergeometric_asymptotic_airy`. .. function:: void acb_hypgeom_airy_bound(mag_t ai, mag_t ai_prime, mag_t bi, mag_t bi_prime, const acb_t z) Computes bounds for the Airy functions using first-order asymptotic expansions together with error bounds. This function uses some shortcuts to make it slightly faster than calling :func:`acb_hypgeom_airy_asymp` with `n = 1`. .. function:: void acb_hypgeom_airy(acb_t ai, acb_t ai_prime, acb_t bi, acb_t bi_prime, const acb_t z, slong prec) Computes Airy functions using an automatic algorithm choice. We use :func:`acb_hypgeom_airy_asymp` whenever this gives full accuracy and :func:`acb_hypgeom_airy_direct` otherwise. In the latter case, we first use hardware double precision arithmetic to determine an accurate estimate of the working precision needed to compute the Airy functions accurately for given *z*. This estimate is obtained by comparing the leading-order asymptotic estimate of the Airy functions with the magnitude of the largest term in the power series. The estimate is generic in the sense that it does not take into account vanishing near the roots of the functions. We subsequently evaluate the power series at the midpoint of *z* and bound the propagated error using derivatives. Derivatives are bounded using :func:`acb_hypgeom_airy_bound`. .. function:: void acb_hypgeom_airy_jet(acb_ptr ai, acb_ptr bi, const acb_t z, slong len, slong prec) Writes to *ai* and *bi* the respective Taylor expansions of the Airy functions at the point *z*, truncated to length *len*. Either of the outputs can be *NULL* to avoid computing that function. The variable *z* is not allowed to be aliased with the outputs. To simplify the implementation, this method does not compute the series expansions of the primed versions directly; these are easily obtained by computing one extra coefficient and differentiating the output with :func:`_acb_poly_derivative`. .. function:: void _acb_hypgeom_airy_series(acb_ptr ai, acb_ptr ai_prime, acb_ptr bi, acb_ptr bi_prime, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_airy_series(acb_poly_t ai, acb_poly_t ai_prime, acb_poly_t bi, acb_poly_t bi_prime, const acb_poly_t z, slong len, slong prec) Computes the Airy functions evaluated at the power series *z*, truncated to length *len*. As with the other Airy methods, any of the outputs can be *NULL*. Coulomb wave functions ------------------------------------------------------------------------------- Coulomb wave functions are solutions of the Coulomb wave equation .. math:: y'' + \left(1 - \frac{2 \eta}{z} - \frac{\ell(\ell+1)}{z^2}\right) y = 0 which is the radial Schrödinger equation for a charged particle in a Coulomb potential `1/z`, where `\ell` is the orbital angular momentum and `\eta` is the Sommerfeld parameter. The standard solutions are named `F_{\ell}(\eta,z)` (regular at the origin `z = 0`) and `G_{\ell}(\eta,z)` (irregular at the origin). The irregular solutions `H^{\pm}_{\ell}(\eta,z) = G_{\ell}(\eta,z) \pm i F_{\ell}(\eta,z)` are also used. Coulomb wave functions are special cases of confluent hypergeometric functions. The normalization constants and connection formulas are discussed in [DYF1999]_, [Gas2018]_, [Mic2007]_ and chapter 33 in [NIST2012]_. In this implementation, we define the analytic continuations of all the functions so that the branch cut with respect to *z* is placed on the negative real axis. Precise definitions are given in http://fungrim.org/topic/Coulomb_wave_functions/ The following methods optionally compute `F_{\ell}(\eta,z), G_{\ell}(\eta,z), H^{+}_{\ell}(\eta,z), H^{-}_{\ell}(\eta,z)` simultaneously. Any of the four function values can be omitted by passing *NULL* for the unwanted output variables. The redundant functions `H^{\pm}` are provided explicitly since taking the linear combination of *F* and *G* suffers from cancellation in parts of the complex plane. .. function:: void acb_hypgeom_coulomb(acb_t F, acb_t G, acb_t Hpos, acb_t Hneg, const acb_t l, const acb_t eta, const acb_t z, slong prec) Writes to *F*, *G*, *Hpos*, *Hneg* the values of the respective Coulomb wave functions. Any of the outputs can be *NULL*. .. function:: void acb_hypgeom_coulomb_jet(acb_ptr F, acb_ptr G, acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta, const acb_t z, slong len, slong prec) Writes to *F*, *G*, *Hpos*, *Hneg* the respective Taylor expansions of the Coulomb wave functions at the point *z*, truncated to length *len*. Any of the outputs can be *NULL*. .. function:: void _acb_hypgeom_coulomb_series(acb_ptr F, acb_ptr G, acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_coulomb_series(acb_poly_t F, acb_poly_t G, acb_poly_t Hpos, acb_poly_t Hneg, const acb_t l, const acb_t eta, const acb_poly_t z, slong len, slong prec) Computes the Coulomb wave functions evaluated at the power series *z*, truncated to length *len*. Any of the outputs can be *NULL*. Incomplete gamma and beta functions ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_gamma_upper_asymp(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_gamma_upper_1f1a(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_gamma_upper_1f1b(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_gamma_upper_singular(acb_t res, slong s, const acb_t z, int regularized, slong prec) .. function:: void acb_hypgeom_gamma_upper(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) If *regularized* is 0, computes the upper incomplete gamma function `\Gamma(s,z)`. If *regularized* is 1, computes the regularized upper incomplete gamma function `Q(s,z) = \Gamma(s,z) / \Gamma(s)`. If *regularized* is 2, computes the generalized exponential integral `z^{-s} \Gamma(s,z) = E_{1-s}(z)` instead (this option is mainly intended for internal use; :func:`acb_hypgeom_expint` is the intended interface for computing the exponential integral). The different methods respectively implement the formulas .. math:: \Gamma(s,z) = e^{-z} U(1-s,1-s,z) .. math:: \Gamma(s,z) = \Gamma(s) - \frac{z^s}{s} {}_1F_1(s, s+1, -z) .. math:: \Gamma(s,z) = \Gamma(s) - \frac{z^s e^{-z}}{s} {}_1F_1(1, s+1, z) .. math:: \Gamma(s,z) = \frac{(-1)^n}{n!} (\psi(n+1) - \log(z)) + \frac{(-1)^n}{(n+1)!} z \, {}_2F_2(1,1,2,2+n,-z) - z^{-n} \sum_{k=0}^{n-1} \frac{(-z)^k}{(k-n) k!}, \quad n = -s \in \mathbb{Z}_{\ge 0} and an automatic algorithm choice. The automatic version also handles other special input such as `z = 0` and `s = 1, 2, 3`. The *singular* version evaluates the finite sum directly and therefore assumes that *s* is not too large. .. function:: void _acb_hypgeom_gamma_upper_series(acb_ptr res, const acb_t s, acb_srcptr z, slong zlen, int regularized, slong n, slong prec) .. function:: void acb_hypgeom_gamma_upper_series(acb_poly_t res, const acb_t s, const acb_poly_t z, int regularized, slong n, slong prec) Sets *res* to an upper incomplete gamma function where *s* is a constant and *z* is a power series, truncated to length *n*. The *regularized* argument has the same interpretation as in :func:`acb_hypgeom_gamma_upper`. .. function:: void acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) If *regularized* is 0, computes the lower incomplete gamma function `\gamma(s,z) = \frac{z^s}{s} {}_1F_1(s, s+1, -z)`. If *regularized* is 1, computes the regularized lower incomplete gamma function `P(s,z) = \gamma(s,z) / \Gamma(s)`. If *regularized* is 2, computes a further regularized lower incomplete gamma function `\gamma^{*}(s,z) = z^{-s} P(s,z)`. .. function:: void _acb_hypgeom_gamma_lower_series(acb_ptr res, const acb_t s, acb_srcptr z, slong zlen, int regularized, slong n, slong prec) .. function:: void acb_hypgeom_gamma_lower_series(acb_poly_t res, const acb_t s, const acb_poly_t z, int regularized, slong n, slong prec) Sets *res* to an lower incomplete gamma function where *s* is a constant and *z* is a power series, truncated to length *n*. The *regularized* argument has the same interpretation as in :func:`acb_hypgeom_gamma_lower`. .. function:: void acb_hypgeom_beta_lower(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) Computes the (lower) incomplete beta function, defined by `B(a,b;z) = \int_0^z t^{a-1} (1-t)^{b-1}`, optionally the regularized incomplete beta function `I(a,b;z) = B(a,b;z) / B(a,b;1)`. In general, the integral must be interpreted using analytic continuation. The precise definitions for all parameter values are .. math:: B(a,b;z) = \frac{z^a}{a} {}_2F_1(a, 1-b, a+1, z) .. math:: I(a,b;z) = \frac{\Gamma(a+b)}{\Gamma(b)} z^a {}_2{\widetilde F}_1(a, 1-b, a+1, z). Note that both functions with this definition are undefined for nonpositive integer *a*, and *I* is undefined for nonpositive integer `a + b`. .. function:: void _acb_hypgeom_beta_lower_series(acb_ptr res, const acb_t a, const acb_t b, acb_srcptr z, slong zlen, int regularized, slong n, slong prec) .. function:: void acb_hypgeom_beta_lower_series(acb_poly_t res, const acb_t a, const acb_t b, const acb_poly_t z, int regularized, slong n, slong prec) Sets *res* to the lower incomplete beta function `B(a,b;z)` (optionally the regularized version `I(a,b;z)`) where *a* and *b* are constants and *z* is a power series, truncating the result to length *n*. The underscore method requires positive lengths and does not support aliasing. Exponential and trigonometric integrals ------------------------------------------------------------------------------- The branch cut conventions of the following functions match Mathematica. .. function:: void acb_hypgeom_expint(acb_t res, const acb_t s, const acb_t z, slong prec) Computes the generalized exponential integral `E_s(z)`. This is a trivial wrapper of :func:`acb_hypgeom_gamma_upper`. .. function:: void acb_hypgeom_ei_asymp(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_ei_2f2(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_ei(acb_t res, const acb_t z, slong prec) Computes the exponential integral `\operatorname{Ei}(z)`, respectively using .. math:: \operatorname{Ei}(z) = -e^z U(1,1,-z) - \log(-z) + \frac{1}{2} \left(\log(z) - \log\left(\frac{1}{z}\right) \right) .. math:: \operatorname{Ei}(z) = z {}_2F_2(1, 1; 2, 2; z) + \gamma + \frac{1}{2} \left(\log(z) - \log\left(\frac{1}{z}\right) \right) and an automatic algorithm choice. .. function:: void _acb_hypgeom_ei_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_ei_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the exponential integral of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_si_asymp(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_si_1f2(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_si(acb_t res, const acb_t z, slong prec) Computes the sine integral `\operatorname{Si}(z)`, respectively using .. math:: \operatorname{Si}(z) = \frac{i}{2} \left[ e^{iz} U(1,1,-iz) - e^{-iz} U(1,1,iz) + \log(-iz) - \log(iz) \right] .. math:: \operatorname{Si}(z) = z {}_1F_2(\tfrac{1}{2}; \tfrac{3}{2}, \tfrac{3}{2}; -\tfrac{z^2}{4}) and an automatic algorithm choice. .. function:: void _acb_hypgeom_si_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_si_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the sine integral of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_ci_asymp(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_ci_2f3(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_ci(acb_t res, const acb_t z, slong prec) Computes the cosine integral `\operatorname{Ci}(z)`, respectively using .. math:: \operatorname{Ci}(z) = \log(z) - \frac{1}{2} \left[ e^{iz} U(1,1,-iz) + e^{-iz} U(1,1,iz) + \log(-iz) + \log(iz) \right] .. math:: \operatorname{Ci}(z) = -\tfrac{z^2}{4} {}_2F_3(1, 1; 2, 2, \tfrac{3}{2}; -\tfrac{z^2}{4}) + \log(z) + \gamma and an automatic algorithm choice. .. function:: void _acb_hypgeom_ci_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_ci_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the cosine integral of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_shi(acb_t res, const acb_t z, slong prec) Computes the hyperbolic sine integral `\operatorname{Shi}(z) = -i \operatorname{Si}(iz)`. This is a trivial wrapper of :func:`acb_hypgeom_si`. .. function:: void _acb_hypgeom_shi_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_shi_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the hyperbolic sine integral of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_chi_asymp(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_chi_2f3(acb_t res, const acb_t z, slong prec) .. function:: void acb_hypgeom_chi(acb_t res, const acb_t z, slong prec) Computes the hyperbolic cosine integral `\operatorname{Chi}(z)`, respectively using .. math:: \operatorname{Chi}(z) = -\frac{1}{2} \left[ e^{z} U(1,1,-z) + e^{-z} U(1,1,z) + \log(-z) - \log(z) \right] .. math:: \operatorname{Chi}(z) = \tfrac{z^2}{4} {}_2F_3(1, 1; 2, 2, \tfrac{3}{2}; \tfrac{z^2}{4}) + \log(z) + \gamma and an automatic algorithm choice. .. function:: void _acb_hypgeom_chi_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_hypgeom_chi_series(acb_poly_t res, const acb_poly_t z, slong len, slong prec) Computes the hyperbolic cosine integral of the power series *z*, truncated to length *len*. .. function:: void acb_hypgeom_li(acb_t res, const acb_t z, int offset, slong prec) If *offset* is zero, computes the logarithmic integral `\operatorname{li}(z) = \operatorname{Ei}(\log(z))`. If *offset* is nonzero, computes the offset logarithmic integral `\operatorname{Li}(z) = \operatorname{li}(z) - \operatorname{li}(2)`. .. function:: void _acb_hypgeom_li_series(acb_ptr res, acb_srcptr z, slong zlen, int offset, slong len, slong prec) .. function:: void acb_hypgeom_li_series(acb_poly_t res, const acb_poly_t z, int offset, slong len, slong prec) Computes the logarithmic integral (optionally the offset version) of the power series *z*, truncated to length *len*. Gauss hypergeometric function ------------------------------------------------------------------------------- The following methods compute the Gauss hypergeometric function .. math:: F(z) = {}_2F_1(a,b,c,z) = \sum_{k=0}^{\infty} \frac{(a)_k (b)_k}{(c)_k} \frac{z^k}{k!} or the regularized version `\operatorname{\mathbf{F}}(z) = \operatorname{\mathbf{F}}(a,b,c,z) = {}_2F_1(a,b,c,z) / \Gamma(c)` if the flag *regularized* is set. .. function:: void acb_hypgeom_2f1_continuation(acb_t res0, acb_t res1, const acb_t a, const acb_t b, const acb_t c, const acb_t z0, const acb_t z1, const acb_t f0, const acb_t f1, slong prec) Given `F(z_0), F'(z_0)` in *f0*, *f1*, sets *res0* and *res1* to `F(z_1), F'(z_1)` by integrating the hypergeometric differential equation along a straight-line path. The evaluation points should be well-isolated from the singular points 0 and 1. .. function:: void acb_hypgeom_2f1_series_direct(acb_poly_t res, const acb_poly_t a, const acb_poly_t b, const acb_poly_t c, const acb_poly_t z, int regularized, slong len, slong prec) Computes `F(z)` of the given power series truncated to length *len*, using direct summation of the hypergeometric series. .. function:: void acb_hypgeom_2f1_direct(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, slong prec) Computes `F(z)` using direct summation of the hypergeometric series. .. function:: void acb_hypgeom_2f1_transform(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int flags, int which, slong prec) .. function:: void acb_hypgeom_2f1_transform_limit(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, int which, slong prec) Computes `F(z)` using an argument transformation determined by the flag *which*. Legal values are 1 for `z/(z-1)`, 2 for `1/z`, 3 for `1/(1-z)`, 4 for `1-z`, and 5 for `1-1/z`. The *transform_limit* version assumes that *which* is not 1. If *which* is 2 or 3, it assumes that `b-a` represents an exact integer. If *which* is 4 or 5, it assumes that `c-a-b` represents an exact integer. In these cases, it computes the correct limit value. See :func:`acb_hypgeom_2f1` for the meaning of *flags*. .. function:: void acb_hypgeom_2f1_corner(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, slong prec) Computes `F(z)` near the corner cases `\exp(\pm \pi i \sqrt{3})` by analytic continuation. .. function:: int acb_hypgeom_2f1_choose(const acb_t z) Chooses a method to compute the function based on the location of *z* in the complex plane. If the return value is 0, direct summation should be used. If the return value is 1 to 5, the transformation with this index in :func:`acb_hypgeom_2f1_transform` should be used. If the return value is 6, the corner case algorithm should be used. .. function:: void acb_hypgeom_2f1(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int flags, slong prec) Computes `F(z)` or `\operatorname{\mathbf{F}}(z)` using an automatic algorithm choice. The following bit fields can be set in *flags*: - *ACB_HYPGEOM_2F1_REGULARIZED* - computes the regularized hypergeometric function `\operatorname{\mathbf{F}}(z)`. Setting *flags* to 1 is the same as just toggling this option. - *ACB_HYPGEOM_2F1_AB* - `a-b` is an integer. - *ACB_HYPGEOM_2F1_ABC* - `a+b-c` is an integer. - *ACB_HYPGEOM_2F1_AC* - `a-c` is an integer. - *ACB_HYPGEOM_2F1_BC* - `b-c` is an integer. The last four flags can be set to indicate that the respective parameter differences are known to represent exact integers, even if the input intervals are inexact. This allows the correct limits to be evaluated when applying transformation formulas. For example, to evaluate `{}_2F_1(\sqrt{2}, 1/2, \sqrt{2}+3/2, 9/10)`, the *ABC* flag should be set. If not set, the result will be an indeterminate interval due to internally dividing by an interval containing zero. If the parameters are exact floating-point numbers (including exact integers or half-integers), then the limits are computed automatically, and setting these flags is unnecessary. Currently, only the *AB* and *ABC* flags are used this way; the *AC* and *BC* flags might be used in the future. Orthogonal polynomials and functions ------------------------------------------------------------------------------- .. function:: void acb_hypgeom_chebyshev_t(acb_t res, const acb_t n, const acb_t z, slong prec) .. function:: void acb_hypgeom_chebyshev_u(acb_t res, const acb_t n, const acb_t z, slong prec) Computes the Chebyshev polynomial (or Chebyshev function) of first or second kind .. math:: T_n(z) = {}_2F_1\left(-n,n,\frac{1}{2},\frac{1-z}{2}\right) .. math:: U_n(z) = (n+1) {}_2F_1\left(-n,n+2,\frac{3}{2},\frac{1-z}{2}\right). The hypergeometric series definitions are only used for computation near the point 1. In general, trigonometric representations are used. For word-size integer *n*, :func:`acb_chebyshev_t_ui` and :func:`acb_chebyshev_u_ui` are called. .. function:: void acb_hypgeom_jacobi_p(acb_t res, const acb_t n, const acb_t a, const acb_t b, const acb_t z, slong prec) Computes the Jacobi polynomial (or Jacobi function) .. math:: P_n^{(a,b)}(z)=\frac{(a+1)_n}{\Gamma(n+1)} {}_2F_1\left(-n,n+a+b+1,a+1,\frac{1-z}{2}\right). For nonnegative integer *n*, this is a polynomial in *a*, *b* and *z*, even when the parameters are such that the hypergeometric series is undefined. In such cases, the polynomial is evaluated using direct methods. .. function:: void acb_hypgeom_gegenbauer_c(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) Computes the Gegenbauer polynomial (or Gegenbauer function) .. math:: C_n^{m}(z)=\frac{(2m)_n}{\Gamma(n+1)} {}_2F_1\left(-n,2m+n,m+\frac{1}{2},\frac{1-z}{2}\right). For nonnegative integer *n*, this is a polynomial in *m* and *z*, even when the parameters are such that the hypergeometric series is undefined. In such cases, the polynomial is evaluated using direct methods. .. function:: void acb_hypgeom_laguerre_l(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) Computes the Laguerre polynomial (or Laguerre function) .. math:: L_n^{m}(z)=\frac{(m+1)_n}{\Gamma(n+1)} {}_1F_1\left(-n,m+1,z\right). For nonnegative integer *n*, this is a polynomial in *m* and *z*, even when the parameters are such that the hypergeometric series is undefined. In such cases, the polynomial is evaluated using direct methods. There are at least two incompatible ways to define the Laguerre function when *n* is a negative integer. One possibility when `m = 0` is to define `L_{-n}^0(z) = e^z L_{n-1}^0(-z)`. Another possibility is to cover this case with the recurrence relation `L_{n-1}^m(z) + L_n^{m-1}(z) = L_n^m(z)`. Currently, we leave this case undefined (returning indeterminate). .. function:: void acb_hypgeom_hermite_h(acb_t res, const acb_t n, const acb_t z, slong prec) Computes the Hermite polynomial (or Hermite function) .. math:: H_n(z) = 2^n \sqrt{\pi} \left( \frac{1}{\Gamma((1-n)/2)} {}_1F_1\left(-\frac{n}{2},\frac{1}{2},z^2\right) - \frac{2z}{\Gamma(-n/2)} {}_1F_1\left(\frac{1-n}{2},\frac{3}{2},z^2\right)\right). .. function:: void acb_hypgeom_legendre_p(acb_t res, const acb_t n, const acb_t m, const acb_t z, int type, slong prec) Sets *res* to the associated Legendre function of the first kind evaluated for degree *n*, order *m*, and argument *z*. When *m* is zero, this reduces to the Legendre polynomial `P_n(z)`. Many different branch cut conventions appear in the literature. If *type* is 0, the version .. math:: P_n^m(z) = \frac{(1+z)^{m/2}}{(1-z)^{m/2}} \mathbf{F}\left(-n, n+1, 1-m, \frac{1-z}{2}\right) is computed, and if *type* is 1, the alternative version .. math:: {\mathcal P}_n^m(z) = \frac{(z+1)^{m/2}}{(z-1)^{m/2}} \mathbf{F}\left(-n, n+1, 1-m, \frac{1-z}{2}\right). is computed. Type 0 and type 1 respectively correspond to type 2 and type 3 in *Mathematica* and *mpmath*. .. function:: void acb_hypgeom_legendre_q(acb_t res, const acb_t n, const acb_t m, const acb_t z, int type, slong prec) Sets *res* to the associated Legendre function of the second kind evaluated for degree *n*, order *m*, and argument *z*. When *m* is zero, this reduces to the Legendre function `Q_n(z)`. Many different branch cut conventions appear in the literature. If *type* is 0, the version .. math:: Q_n^m(z) = \frac{\pi}{2 \sin(\pi m)} \left( \cos(\pi m) P_n^m(z) - \frac{\Gamma(1+m+n)}{\Gamma(1-m+n)} P_n^{-m}(z)\right) is computed, and if *type* is 1, the alternative version .. math:: \mathcal{Q}_n^m(z) = \frac{\pi}{2 \sin(\pi m)} e^{\pi i m} \left( \mathcal{P}_n^m(z) - \frac{\Gamma(1+m+n)}{\Gamma(1-m+n)} \mathcal{P}_n^{-m}(z)\right) is computed. Type 0 and type 1 respectively correspond to type 2 and type 3 in *Mathematica* and *mpmath*. When *m* is an integer, either expression is interpreted as a limit. We make use of the connection formulas [WQ3a]_, [WQ3b]_ and [WQ3c]_ to allow computing the function even in the limiting case. (The formula [WQ3d]_ would be useful, but is incorrect in the lower half plane.) .. [WQ3a] http://functions.wolfram.com/07.11.26.0033.01 .. [WQ3b] http://functions.wolfram.com/07.12.27.0014.01 .. [WQ3c] http://functions.wolfram.com/07.12.26.0003.01 .. [WQ3d] http://functions.wolfram.com/07.12.26.0088.01 .. function:: void acb_hypgeom_legendre_p_uiui_rec(acb_t res, ulong n, ulong m, const acb_t z, slong prec) For nonnegative integer *n* and *m*, uses recurrence relations to evaluate `(1-z^2)^{-m/2} P_n^m(z)` which is a polynomial in *z*. .. function:: void acb_hypgeom_spherical_y(acb_t res, slong n, slong m, const acb_t theta, const acb_t phi, slong prec) Computes the spherical harmonic of degree *n*, order *m*, latitude angle *theta*, and longitude angle *phi*, normalized such that .. math:: Y_n^m(\theta, \phi) = \sqrt{\frac{2n+1}{4\pi} \frac{(n-m)!}{(n+m)!}} e^{im\phi} P_n^m(\cos(\theta)). The definition is extended to negative *m* and *n* by symmetry. This function is a polynomial in `\cos(\theta)` and `\sin(\theta)`. We evaluate it using :func:`acb_hypgeom_legendre_p_uiui_rec`. Dilogarithm ------------------------------------------------------------------------------- The dilogarithm function is given by `\operatorname{Li}_2(z) = -\int_0^z \frac{\log(1-t)}{t} dt = z {}_3F_2(1,1,1,2,2,z)`. .. function:: void acb_hypgeom_dilog_bernoulli(acb_t res, const acb_t z, slong prec) Computes the dilogarithm using a series expansion in `w = \log(z)`, with rate of convergence `|w/(2\pi)|^n`. This provides good convergence near `z = e^{\pm i \pi / 3}`, where hypergeometric series expansions fail. Since the coefficients involve Bernoulli numbers, this method should only be used at moderate precision. .. function:: void acb_hypgeom_dilog_zero_taylor(acb_t res, const acb_t z, slong prec) Computes the dilogarithm for *z* close to 0 using the hypergeometric series (effective only when `|z| \ll 1`). .. function:: void acb_hypgeom_dilog_zero(acb_t res, const acb_t z, slong prec) Computes the dilogarithm for *z* close to 0, using the bit-burst algorithm instead of the hypergeometric series directly at very high precision. .. function:: void acb_hypgeom_dilog_transform(acb_t res, const acb_t z, int algorithm, slong prec) Computes the dilogarithm by applying one of the transformations `1/z`, `1-z`, `z/(z-1)`, `1/(1-z)`, indexed by *algorithm* from 1 to 4, and calling :func:`acb_hypgeom_dilog_zero` with the reduced variable. Alternatively, for *algorithm* between 5 and 7, starts from the respective point `\pm i`, `(1\pm i)/2`, `(1\pm i)/2` (with the sign chosen according to the midpoint of *z*) and computes the dilogarithm by the bit-burst method. .. function:: void acb_hypgeom_dilog_continuation(acb_t res, const acb_t a, const acb_t z, slong prec) Computes `\operatorname{Li}_2(z) - \operatorname{Li}_2(a)` using Taylor expansion at *a*. Binary splitting is used. Both *a* and *z* should be well isolated from the points 0 and 1, except that *a* may be exactly 0. If the straight line path from *a* to *b* crosses the branch cut, this method provides continuous analytic continuation instead of computing the principal branch. .. function:: void acb_hypgeom_dilog_bitburst(acb_t res, acb_t z0, const acb_t z, slong prec) Sets *z0* to a point with short bit expansion close to *z* and sets *res* to `\operatorname{Li}_2(z) - \operatorname{Li}_2(z_0)`, computed using the bit-burst algorithm. .. function:: void acb_hypgeom_dilog(acb_t res, const acb_t z, slong prec) Computes the dilogarithm using a default algorithm choice. flint-3.1.3/doc/source/acb_mat.rst000066400000000000000000001070131461254215100170220ustar00rootroot00000000000000.. _acb-mat: **acb_mat.h** -- matrices over the complex numbers =============================================================================== An :type:`acb_mat_t` represents a dense matrix over the complex numbers, implemented as an array of entries of type :type:`acb_struct`. The dimension (number of rows and columns) of a matrix is fixed at initialization, and the user must ensure that inputs and outputs to an operation have compatible dimensions. The number of rows or columns in a matrix can be zero. .. note:: Methods prefixed with *acb_mat_approx* treat all input entries as floating-point numbers (ignoring the radii of the balls) and compute floating-point output (balls with zero radius) representing approximate solutions *without error bounds*. All other methods compute rigorous error bounds. The *approx* methods are typically useful for computing initial values or preconditioners for rigorous solvers. Some users may also find *approx* methods useful for doing ordinary numerical linear algebra in applications where error bounds are not needed. Types, macros and constants ------------------------------------------------------------------------------- .. type:: acb_mat_struct .. type:: acb_mat_t Contains a pointer to a flat array of the entries (entries), an array of pointers to the start of each row (rows), and the number of rows (r) and columns (c). An *acb_mat_t* is defined as an array of length one of type *acb_mat_struct*, permitting an *acb_mat_t* to be passed by reference. .. macro:: acb_mat_entry(mat, i, j) Macro giving a pointer to the entry at row *i* and column *j*. .. macro:: acb_mat_nrows(mat) Returns the number of rows of the matrix. .. macro:: acb_mat_ncols(mat) Returns the number of columns of the matrix. Memory management ------------------------------------------------------------------------------- .. function:: void acb_mat_init(acb_mat_t mat, slong r, slong c) Initializes the matrix, setting it to the zero matrix with *r* rows and *c* columns. .. function:: void acb_mat_clear(acb_mat_t mat) Clears the matrix, deallocating all entries. .. function:: slong acb_mat_allocated_bytes(const acb_mat_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(acb_mat_struct)`` to get the size of the object as a whole. .. function:: void acb_mat_window_init(acb_mat_t window, const acb_mat_t mat, slong r1, slong c1, slong r2, slong c2) Initializes *window* to a window matrix into the submatrix of *mat* starting at the corner at row *r1* and column *c1* (inclusive) and ending at row *r2* and column *c2* (exclusive). .. function:: void acb_mat_window_clear(acb_mat_t window) Frees the window matrix. Conversions ------------------------------------------------------------------------------- .. function:: void acb_mat_set(acb_mat_t dest, const acb_mat_t src) .. function:: void acb_mat_set_fmpz_mat(acb_mat_t dest, const fmpz_mat_t src) .. function:: void acb_mat_set_round_fmpz_mat(acb_mat_t dest, const fmpz_mat_t src, slong prec) .. function:: void acb_mat_set_fmpq_mat(acb_mat_t dest, const fmpq_mat_t src, slong prec) .. function:: void acb_mat_set_arb_mat(acb_mat_t dest, const arb_mat_t src) .. function:: void acb_mat_set_round_arb_mat(acb_mat_t dest, const arb_mat_t src, slong prec) Sets *dest* to *src*. The operands must have identical dimensions. .. function:: void acb_mat_get_real(arb_mat_t re, const arb_mat_t mat) .. function:: void acb_mat_get_imag(arb_mat_t im, const arb_mat_t mat) Sets *re* or *im* to the real or imaginary part of *mat*, respectively. The operands must have identical dimensions. .. function:: void acb_mat_set_real_imag(acb_mat_t mat, const arb_mat_t re, const arb_mat_t im) Sets *mat* to the complex matrix with real and imaginary parts *re*, *im*. The operands must have identical dimensions. Random generation ------------------------------------------------------------------------------- .. function:: void acb_mat_randtest(acb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) Sets *mat* to a random matrix with up to *prec* bits of precision and with exponents of width up to *mag_bits*. .. function:: void acb_mat_randtest_eig(acb_mat_t mat, flint_rand_t state, acb_srcptr E, slong prec) Sets *mat* to a random matrix with the prescribed eigenvalues supplied as the vector *E*. The output matrix is required to be square. We generate a random unitary matrix via a matrix exponential, and then evaluate an inverse Schur decomposition. Input and output ------------------------------------------------------------------------------- .. function:: void acb_mat_printd(const acb_mat_t mat, slong digits) Prints each entry in the matrix with the specified number of decimal digits. .. function:: void acb_mat_fprintd(FILE * file, const acb_mat_t mat, slong digits) Prints each entry in the matrix with the specified number of decimal digits to the stream *file*. Comparisons ------------------------------------------------------------------------------- Predicate methods return 1 if the property certainly holds and 0 otherwise. .. function:: int acb_mat_equal(const acb_mat_t mat1, const acb_mat_t mat2) Returns whether the matrices have the same dimensions and identical intervals as entries. .. function:: int acb_mat_overlaps(const acb_mat_t mat1, const acb_mat_t mat2) Returns whether the matrices have the same dimensions and each entry in *mat1* overlaps with the corresponding entry in *mat2*. .. function:: int acb_mat_contains(const acb_mat_t mat1, const acb_mat_t mat2) .. function:: int acb_mat_contains_fmpz_mat(const acb_mat_t mat1, const fmpz_mat_t mat2) .. function:: int acb_mat_contains_fmpq_mat(const acb_mat_t mat1, const fmpq_mat_t mat2) Returns whether the matrices have the same dimensions and each entry in *mat2* is contained in the corresponding entry in *mat1*. .. function:: int acb_mat_eq(const acb_mat_t mat1, const acb_mat_t mat2) Returns whether *mat1* and *mat2* certainly represent the same matrix. .. function:: int acb_mat_ne(const acb_mat_t mat1, const acb_mat_t mat2) Returns whether *mat1* and *mat2* certainly do not represent the same matrix. .. function:: int acb_mat_is_real(const acb_mat_t mat) Returns whether all entries in *mat* have zero imaginary part. .. function:: int acb_mat_is_empty(const acb_mat_t mat) Returns whether the number of rows or the number of columns in *mat* is zero. .. function:: int acb_mat_is_square(const acb_mat_t mat) Returns whether the number of rows is equal to the number of columns in *mat*. .. function:: int acb_mat_is_exact(const acb_mat_t mat) Returns whether all entries in *mat* have zero radius. .. function:: int acb_mat_is_zero(const acb_mat_t mat) Returns whether all entries in *mat* are exactly zero. .. function:: int acb_mat_is_finite(const acb_mat_t mat) Returns whether all entries in *mat* are finite. .. function:: int acb_mat_is_triu(const acb_mat_t mat) Returns whether *mat* is upper triangular; that is, all entries below the main diagonal are exactly zero. .. function:: int acb_mat_is_tril(const acb_mat_t mat) Returns whether *mat* is lower triangular; that is, all entries above the main diagonal are exactly zero. .. function:: int acb_mat_is_diag(const acb_mat_t mat) Returns whether *mat* is a diagonal matrix; that is, all entries off the main diagonal are exactly zero. Special matrices ------------------------------------------------------------------------------- .. function:: void acb_mat_zero(acb_mat_t mat) Sets all entries in mat to zero. .. function:: void acb_mat_one(acb_mat_t mat) Sets the entries on the main diagonal to ones, and all other entries to zero. .. function:: void acb_mat_ones(acb_mat_t mat) Sets all entries in the matrix to ones. .. function:: void acb_mat_onei(acb_mat_t mat) Sets the entries of the main diagonal to `i = \sqrt{-1}` and all other entries to zero. .. function:: void acb_mat_indeterminate(acb_mat_t mat) Sets all entries in the matrix to indeterminate (NaN). .. function:: void acb_mat_dft(acb_mat_t mat, int type, slong prec) Sets *mat* to the DFT (discrete Fourier transform) matrix of order *n* where *n* is the smallest dimension of *mat* (if *mat* is not square, the matrix is extended periodically along the larger dimension). Here, we use the normalized DFT matrix .. math:: A_{j,k} = \frac{\omega^{jk}}{\sqrt{n}}, \quad \omega = e^{-2\pi i/n}. The *type* parameter is currently ignored and should be set to 0. In the future, it might be used to select a different convention. Transpose ------------------------------------------------------------------------------- .. function:: void acb_mat_transpose(acb_mat_t dest, const acb_mat_t src) Sets *dest* to the exact transpose *src*. The operands must have compatible dimensions. Aliasing is allowed. .. function:: void acb_mat_conjugate_transpose(acb_mat_t dest, const acb_mat_t src) Sets *dest* to the conjugate transpose of *src*. The operands must have compatible dimensions. Aliasing is allowed. .. function:: void acb_mat_conjugate(acb_mat_t dest, const acb_mat_t src) Sets *dest* to the elementwise complex conjugate of *src*. Norms ------------------------------------------------------------------------------- .. function:: void acb_mat_bound_inf_norm(mag_t b, const acb_mat_t A) Sets *b* to an upper bound for the infinity norm (i.e. the largest absolute value row sum) of *A*. .. function:: void acb_mat_frobenius_norm(arb_t res, const acb_mat_t A, slong prec) Sets *res* to the Frobenius norm (i.e. the square root of the sum of squares of entries) of *A*. .. function:: void acb_mat_bound_frobenius_norm(mag_t res, const acb_mat_t A) Sets *res* to an upper bound for the Frobenius norm of *A*. Arithmetic ------------------------------------------------------------------------------- .. function:: void acb_mat_neg(acb_mat_t dest, const acb_mat_t src) Sets *dest* to the exact negation of *src*. The operands must have the same dimensions. .. function:: void acb_mat_add(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) Sets res to the sum of *mat1* and *mat2*. The operands must have the same dimensions. .. function:: void acb_mat_sub(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) Sets *res* to the difference of *mat1* and *mat2*. The operands must have the same dimensions. .. function:: void acb_mat_mul_classical(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) .. function:: void acb_mat_mul_threaded(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) .. function:: void acb_mat_mul_reorder(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) .. function:: void acb_mat_mul(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) Sets *res* to the matrix product of *mat1* and *mat2*. The operands must have compatible dimensions for matrix multiplication. The *classical* version performs matrix multiplication in the trivial way. The *threaded* version performs classical multiplication but splits the computation over the number of threads returned by *flint_get_num_threads()*. The *reorder* version reorders the data and performs one to four real matrix multiplications via :func:`arb_mat_mul`. The default version chooses an algorithm automatically. .. function:: void acb_mat_mul_entrywise(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) Sets *res* to the entrywise product of *mat1* and *mat2*. The operands must have the same dimensions. .. function:: void acb_mat_sqr_classical(acb_mat_t res, const acb_mat_t mat, slong prec) .. function:: void acb_mat_sqr(acb_mat_t res, const acb_mat_t mat, slong prec) Sets *res* to the matrix square of *mat*. The operands must both be square with the same dimensions. .. function:: void acb_mat_pow_ui(acb_mat_t res, const acb_mat_t mat, ulong exp, slong prec) Sets *res* to *mat* raised to the power *exp*. Requires that *mat* is a square matrix. .. function:: void acb_mat_approx_mul(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) Approximate matrix multiplication. The input radii are ignored and the output matrix is set to an approximate floating-point result. For performance reasons, the radii in the output matrix will *not* necessarily be written (zeroed), but will remain zero if they are already zeroed in *res* before calling this function. Scalar arithmetic ------------------------------------------------------------------------------- .. function:: void acb_mat_scalar_mul_2exp_si(acb_mat_t B, const acb_mat_t A, slong c) Sets *B* to *A* multiplied by `2^c`. .. function:: void acb_mat_scalar_addmul_si(acb_mat_t B, const acb_mat_t A, slong c, slong prec) .. function:: void acb_mat_scalar_addmul_fmpz(acb_mat_t B, const acb_mat_t A, const fmpz_t c, slong prec) .. function:: void acb_mat_scalar_addmul_arb(acb_mat_t B, const acb_mat_t A, const arb_t c, slong prec) .. function:: void acb_mat_scalar_addmul_acb(acb_mat_t B, const acb_mat_t A, const acb_t c, slong prec) Sets *B* to `B + A \times c`. .. function:: void acb_mat_scalar_mul_si(acb_mat_t B, const acb_mat_t A, slong c, slong prec) .. function:: void acb_mat_scalar_mul_fmpz(acb_mat_t B, const acb_mat_t A, const fmpz_t c, slong prec) .. function:: void acb_mat_scalar_mul_arb(acb_mat_t B, const acb_mat_t A, const arb_t c, slong prec) .. function:: void acb_mat_scalar_mul_acb(acb_mat_t B, const acb_mat_t A, const acb_t c, slong prec) Sets *B* to `A \times c`. .. function:: void acb_mat_scalar_div_si(acb_mat_t B, const acb_mat_t A, slong c, slong prec) .. function:: void acb_mat_scalar_div_fmpz(acb_mat_t B, const acb_mat_t A, const fmpz_t c, slong prec) .. function:: void acb_mat_scalar_div_arb(acb_mat_t B, const acb_mat_t A, const arb_t c, slong prec) .. function:: void acb_mat_scalar_div_acb(acb_mat_t B, const acb_mat_t A, const acb_t c, slong prec) Sets *B* to `A / c`. Vector arithmetic ------------------------------------------------------------------------------- .. function:: void _acb_mat_vector_mul_row(acb_ptr res, acb_srcptr v, const acb_mat_t A, slong prec) .. function:: void _acb_mat_vector_mul_col(acb_ptr res, const acb_mat_t A, acb_srcptr v, slong prec) .. function:: void acb_mat_vector_mul_row(acb_ptr res, acb_srcptr v, const acb_mat_t A, slong prec) .. function:: void acb_mat_vector_mul_col(acb_ptr res, const acb_mat_t A, acb_srcptr v, slong prec) Sets *res* to the product `vA`, (resp. `Av`), where *res* and *v* are seen as row (resp. column) vectors. The lengths of the vectors must match the dimensions of *A*. The underscore methods do not allow aliasing between *res* and *v*. Gaussian elimination and solving ------------------------------------------------------------------------------- .. function:: int acb_mat_lu_classical(slong * perm, acb_mat_t LU, const acb_mat_t A, slong prec) .. function:: int acb_mat_lu_recursive(slong * perm, acb_mat_t LU, const acb_mat_t A, slong prec) .. function:: int acb_mat_lu(slong * perm, acb_mat_t LU, const acb_mat_t A, slong prec) Given an `n \times n` matrix `A`, computes an LU decomposition `PLU = A` using Gaussian elimination with partial pivoting. The input and output matrices can be the same, performing the decomposition in-place. Entry `i` in the permutation vector perm is set to the row index in the input matrix corresponding to row `i` in the output matrix. The algorithm succeeds and returns nonzero if it can find `n` invertible (i.e. not containing zero) pivot entries. This guarantees that the matrix is invertible. The algorithm fails and returns zero, leaving the entries in `P` and `LU` undefined, if it cannot find `n` invertible pivot elements. In this case, either the matrix is singular, the input matrix was computed to insufficient precision, or the LU decomposition was attempted at insufficient precision. The *classical* version uses Gaussian elimination directly while the *recursive* version performs the computation in a block recursive way to benefit from fast matrix multiplication. The default version chooses an algorithm automatically. .. function:: void acb_mat_solve_tril_classical(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) .. function:: void acb_mat_solve_tril_recursive(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) .. function:: void acb_mat_solve_tril(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) .. function:: void acb_mat_solve_triu_classical(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) .. function:: void acb_mat_solve_triu_recursive(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) .. function:: void acb_mat_solve_triu(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) Solves the lower triangular system `LX = B` or the upper triangular system `UX = B`, respectively. If *unit* is set, the main diagonal of *L* or *U* is taken to consist of all ones, and in that case the actual entries on the diagonal are not read at all and can contain other data. The *classical* versions perform the computations iteratively while the *recursive* versions perform the computations in a block recursive way to benefit from fast matrix multiplication. The default versions choose an algorithm automatically. .. function:: void acb_mat_solve_lu_precomp(acb_mat_t X, const slong * perm, const acb_mat_t LU, const acb_mat_t B, slong prec) Solves `AX = B` given the precomputed nonsingular LU decomposition `A = PLU`. The matrices `X` and `B` are allowed to be aliased with each other, but `X` is not allowed to be aliased with `LU`. .. function:: int acb_mat_solve(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) .. function:: int acb_mat_solve_lu(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) .. function:: int acb_mat_solve_precond(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) Solves `AX = B` where `A` is a nonsingular `n \times n` matrix and `X` and `B` are `n \times m` matrices. If `m > 0` and `A` cannot be inverted numerically (indicating either that `A` is singular or that the precision is insufficient), the values in the output matrix are left undefined and zero is returned. A nonzero return value guarantees that `A` is invertible and that the exact solution matrix is contained in the output. Three algorithms are provided: * The *lu* version performs LU decomposition directly in ball arithmetic. This is fast, but the bounds typically blow up exponentially with *n*, even if the system is well-conditioned. This algorithm is usually the best choice at very high precision. * The *precond* version computes an approximate inverse to precondition the system. This is usually several times slower than direct LU decomposition, but the bounds do not blow up with *n* if the system is well-conditioned. This algorithm is usually the best choice for large systems at low to moderate precision. * The default version selects between *lu* and *precomp* automatically. The automatic choice should be reasonable most of the time, but users may benefit from trying either *lu* or *precond* in specific applications. For example, the *lu* solver often performs better for ill-conditioned systems where use of very high precision is unavoidable. .. function:: int acb_mat_inv(acb_mat_t X, const acb_mat_t A, slong prec) Sets `X = A^{-1}` where `A` is a square matrix, computed by solving the system `AX = I`. If `A` cannot be inverted numerically (indicating either that `A` is singular or that the precision is insufficient), the values in the output matrix are left undefined and zero is returned. A nonzero return value guarantees that the matrix is invertible and that the exact inverse is contained in the output. .. function:: void acb_mat_det_lu(acb_t det, const acb_mat_t A, slong prec) .. function:: void acb_mat_det_precond(acb_t det, const acb_mat_t A, slong prec) .. function:: void acb_mat_det(acb_t det, const acb_mat_t A, slong prec) Sets *det* to the determinant of the matrix *A*. The *lu* version uses Gaussian elimination with partial pivoting. If at some point an invertible pivot element cannot be found, the elimination is stopped and the magnitude of the determinant of the remaining submatrix is bounded using Hadamard's inequality. The *precond* version computes an approximate LU factorization of *A* and multiplies by the inverse *L* and *U* martices as preconditioners to obtain a matrix close to the identity matrix [Rum2010]_. An enclosure for this determinant is computed using Gershgorin circles. This is about four times slower than direct Gaussian elimination, but much more numerically stable. The default version automatically selects between the *lu* and *precond* versions and additionally handles small or triangular matrices by direct formulas. .. function:: void acb_mat_approx_solve_triu(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) .. function:: void acb_mat_approx_solve_tril(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) .. function:: int acb_mat_approx_lu(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec) .. function:: void acb_mat_approx_solve_lu_precomp(acb_mat_t X, const slong * perm, const acb_mat_t A, const acb_mat_t B, slong prec) .. function:: int acb_mat_approx_solve(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) .. function:: int acb_mat_approx_inv(acb_mat_t X, const acb_mat_t A, slong prec) These methods perform approximate solving *without any error control*. The radii in the input matrices are ignored, the computations are done numerically with floating-point arithmetic (using ordinary Gaussian elimination and triangular solving, accelerated through the use of block recursive strategies for large matrices), and the output matrices are set to the approximate floating-point results with zeroed error bounds. Characteristic polynomial and companion matrix ------------------------------------------------------------------------------- .. function:: void _acb_mat_charpoly(acb_ptr poly, const acb_mat_t mat, slong prec) .. function:: void acb_mat_charpoly(acb_poly_t poly, const acb_mat_t mat, slong prec) Sets *poly* to the characteristic polynomial of *mat* which must be a square matrix. If the matrix has *n* rows, the underscore method requires space for `n + 1` output coefficients. Employs a division-free algorithm using `O(n^4)` operations. .. function:: void _acb_mat_companion(acb_mat_t mat, acb_srcptr poly, slong prec) .. function:: void acb_mat_companion(acb_mat_t mat, const acb_poly_t poly, slong prec) Sets the *n* by *n* matrix *mat* to the companion matrix of the polynomial *poly* which must have degree *n*. The underscore method reads `n + 1` input coefficients. Special functions ------------------------------------------------------------------------------- .. function:: void acb_mat_exp_taylor_sum(acb_mat_t S, const acb_mat_t A, slong N, slong prec) Sets *S* to the truncated exponential Taylor series `S = \sum_{k=0}^{N-1} A^k / k!`. See :func:`arb_mat_exp_taylor_sum` for implementation notes. .. function:: void acb_mat_exp(acb_mat_t B, const acb_mat_t A, slong prec) Sets *B* to the exponential of the matrix *A*, defined by the Taylor series .. math:: \exp(A) = \sum_{k=0}^{\infty} \frac{A^k}{k!}. The function is evaluated as `\exp(A/2^r)^{2^r}`, where `r` is chosen to give rapid convergence of the Taylor series. Error bounds are computed as for :func:`arb_mat_exp`. .. function:: void acb_mat_trace(acb_t trace, const acb_mat_t mat, slong prec) Sets *trace* to the trace of the matrix, i.e. the sum of entries on the main diagonal of *mat*. The matrix is required to be square. .. function:: void _acb_mat_diag_prod(acb_t res, const acb_mat_t mat, slong a, slong b, slong prec) .. function:: void acb_mat_diag_prod(acb_t res, const acb_mat_t mat, slong prec) Sets *res* to the product of the entries on the main diagonal of *mat*. The underscore method computes the product of the entries between index *a* inclusive and *b* exclusive (the indices must be in range). Component and error operations ------------------------------------------------------------------------------- .. function:: void acb_mat_get_mid(acb_mat_t B, const acb_mat_t A) Sets the entries of *B* to the exact midpoints of the entries of *A*. .. function:: void acb_mat_add_error_mag(acb_mat_t mat, const mag_t err) Adds *err* in-place to the radii of the entries of *mat*. .. _acb-mat-eigenvalues: Eigenvalues and eigenvectors ------------------------------------------------------------------------------- The functions in this section are experimental. There are classes of matrices where the algorithms fail to converge even as *prec* is increased, or for which the error bounds are much worse than necessary. In some cases, it can help to manually precondition the matrix *A* by applying a similarity transformation `T^{-1} A T`. * If *A* is badly scaled, take `T` to be a matrix such that the entries of `T^{-1} A T` are more uniform (this is known as balancing). * Simply taking `T` to be a random invertible matrix can help if an algorithm fails to converge despite `A` being well-scaled. (This can be the case when dealing with multiple eigenvalues.) .. function:: int acb_mat_approx_eig_qr(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, const mag_t tol, slong maxiter, slong prec) Computes floating-point approximations of all the *n* eigenvalues (and optionally eigenvectors) of the given *n* by *n* matrix *A*. The approximations of the eigenvalues are written to the vector *E*, in no particular order. If *L* is not *NULL*, approximations of the corresponding left eigenvectors are written to the rows of *L*. If *R* is not *NULL*, approximations of the corresponding right eigenvectors are written to the columns of *R*. The parameters *tol* and *maxiter* can be used to control the target numerical error and the maximum number of iterations allowed before giving up. Passing *NULL* and 0 respectively results in default values being used. Uses the implicitly shifted QR algorithm with reduction to Hessenberg form. No guarantees are made about the accuracy of the output. A nonzero return value indicates that the QR iteration converged numerically, but this is only a heuristic termination test and does not imply any statement whatsoever about error bounds. The output may also be accurate even if this function returns zero. .. function:: void acb_mat_eig_global_enclosure(mag_t eps, const acb_mat_t A, acb_srcptr E, const acb_mat_t R, slong prec) Given an *n* by *n* matrix *A*, a length-*n* vector *E* containing approximations of the eigenvalues of *A*, and an *n* by *n* matrix *R* containing approximations of the corresponding right eigenvectors, computes a rigorous bound `\varepsilon` such that every eigenvalue `\lambda` of *A* satisfies `|\lambda - \hat \lambda_k| \le \varepsilon` for some `\hat \lambda_k` in *E*. In other words, the union of the balls `B_k = \{z : |z - \hat \lambda_k| \le \varepsilon\}` is guaranteed to be an enclosure of all eigenvalues of *A*. Note that there is no guarantee that each ball `B_k` can be identified with a single eigenvalue: it is possible that some balls contain several eigenvalues while other balls contain no eigenvalues. In other words, this method is not powerful enough to compute isolating balls for the individual eigenvalues (or even for clusters of eigenvalues other than the whole spectrum). Nevertheless, in practice the balls `B_k` will represent eigenvalues one-to-one with high probability if the given approximations are good. The output can be used to certify that all eigenvalues of *A* lie in some region of the complex plane (such as a specific half-plane, strip, disk, or annulus) without the need to certify the individual eigenvalues. The output is easily converted into lower or upper bounds for the absolute values or real or imaginary parts of the spectrum, and with high probability these bounds will be tight. Using :func:`acb_add_error_mag` and :func:`acb_union`, the output can also be converted to a single :type:`acb_t` enclosing the whole spectrum of *A* in a rectangle, but note that to test whether a condition holds for all eigenvalues of *A*, it is typically better to iterate over the individual balls `B_k`. This function implements the fast algorithm in Theorem 1 in [Miy2010]_ which extends the Bauer-Fike theorem. Approximations *E* and *R* can, for instance, be computed using :func:`acb_mat_approx_eig_qr`. No assumptions are made about the structure of *A* or the quality of the given approximations. .. function:: void acb_mat_eig_enclosure_rump(acb_t lambda, acb_mat_t J, acb_mat_t R, const acb_mat_t A, const acb_t lambda_approx, const acb_mat_t R_approx, slong prec) Given an *n* by *n* matrix *A* and an approximate eigenvalue-eigenvector pair *lambda_approx* and *R_approx* (where *R_approx* is an *n* by 1 matrix), computes an enclosure *lambda* guaranteed to contain at least one of the eigenvalues of *A*, along with an enclosure *R* for a corresponding right eigenvector. More generally, this function can handle clustered (or repeated) eigenvalues. If *R_approx* is an *n* by *k* matrix containing approximate eigenvectors for a presumed cluster of *k* eigenvalues near *lambda_approx*, this function computes an enclosure *lambda* guaranteed to contain at least *k* eigenvalues of *A* along with a matrix *R* guaranteed to contain a basis for the *k*-dimensional invariant subspace associated with these eigenvalues. Note that for multiple eigenvalues, determining the individual eigenvectors is an ill-posed problem; describing an enclosure of the invariant subspace is the best we can hope for. For `k = 1`, it is guaranteed that `AR - R \lambda` contains the zero matrix. For `k > 2`, this cannot generally be guaranteed (in particular, *A* might not diagonalizable). In this case, we can still compute an approximately diagonal *k* by *k* interval matrix `J \approx \lambda I` such that `AR - RJ` is guaranteed to contain the zero matrix. This matrix has the property that the Jordan canonical form of (any exact matrix contained in) *A* has a *k* by *k* submatrix equal to the Jordan canonical form of (some exact matrix contained in) *J*. The output *J* is optional (the user can pass *NULL* to omit it). The algorithm follows section 13.4 in [Rum2010]_, corresponding to the ``verifyeig()`` routine in INTLAB. The initial approximations can, for instance, be computed using :func:`acb_mat_approx_eig_qr`. No assumptions are made about the structure of *A* or the quality of the given approximations. .. function:: int acb_mat_eig_simple_rump(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) .. function:: int acb_mat_eig_simple_vdhoeven_mourrain(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) .. function:: int acb_mat_eig_simple(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) Computes all the eigenvalues (and optionally corresponding eigenvectors) of the given *n* by *n* matrix *A*. Attempts to prove that *A* has *n* simple (isolated) eigenvalues, returning 1 if successful and 0 otherwise. On success, isolating complex intervals for the eigenvalues are written to the vector *E*, in no particular order. If *L* is not *NULL*, enclosures of the corresponding left eigenvectors are written to the rows of *L*. If *R* is not *NULL*, enclosures of the corresponding right eigenvectors are written to the columns of *R*. The left eigenvectors are normalized so that `L = R^{-1}`. This produces a diagonalization `LAR = D` where *D* is the diagonal matrix with the entries in *E* on the diagonal. The user supplies approximations *E_approx* and *R_approx* of the eigenvalues and the right eigenvectors. The initial approximations can, for instance, be computed using :func:`acb_mat_approx_eig_qr`. No assumptions are made about the structure of *A* or the quality of the given approximations. Two algorithms are implemented: * The *rump* version calls :func:`acb_mat_eig_enclosure_rump` repeatedly to certify eigenvalue-eigenvector pairs one by one. The iteration is stopped to return non-success if a new eigenvalue overlaps with previously computed one. Finally, *L* is computed by a matrix inversion. This has complexity `O(n^4)`. * The *vdhoeven_mourrain* version uses the algorithm in [HM2017]_ to certify all eigenvalues and eigenvectors in one step. This has complexity `O(n^3)`. The default version currently uses *vdhoeven_mourrain*. By design, these functions terminate instead of attempting to compute eigenvalue clusters if some eigenvalues cannot be isolated. To compute all eigenvalues of a matrix allowing for overlap, :func:`acb_mat_eig_multiple_rump` may be used as a fallback, or :func:`acb_mat_eig_multiple` may be used in the first place. .. function:: int acb_mat_eig_multiple_rump(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) .. function:: int acb_mat_eig_multiple(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) Computes all the eigenvalues of the given *n* by *n* matrix *A*. On success, the output vector *E* contains *n* complex intervals, each representing one eigenvalue of *A* with the correct multiplicities in case of overlap. The output intervals are either disjoint or identical, and identical intervals are guaranteed to be grouped consecutively. Each complete run of *k* identical intervals thus represents a cluster of exactly *k* eigenvalues which could not be separated from each other at the current precision, but which could be isolated from the other `n - k` eigenvalues of the matrix. The user supplies approximations *E_approx* and *R_approx* of the eigenvalues and the right eigenvectors. The initial approximations can, for instance, be computed using :func:`acb_mat_approx_eig_qr`. No assumptions are made about the structure of *A* or the quality of the given approximations. The *rump* algorithm groups approximate eigenvalues that are close and calls :func:`acb_mat_eig_enclosure_rump` repeatedly to validate each cluster. The complexity is `O(m n^3)` for *m* clusters. The default version, as currently implemented, first attempts to call :func:`acb_mat_eig_simple_vdhoeven_mourrain` hoping that the eigenvalues are actually simple. It then uses the *rump* algorithm as a fallback. flint-3.1.3/doc/source/acb_modular.rst000066400000000000000000000566361461254215100177220ustar00rootroot00000000000000.. _acb-modular: **acb_modular.h** -- modular forms of complex variables =============================================================================== This module provides methods for numerical evaluation of modular forms and Jacobi theta functions. See :ref:`acb_elliptic.h ` for the closely related elliptic functions and integrals. In the context of this module, *tau* or `\tau` always denotes an element of the complex upper half-plane `\mathbb{H} = \{z \in \mathbb{C} : \operatorname{Im}(z) > 0\}`. We also often use the variable `q`, variously defined as `q = e^{2 \pi i \tau}` (usually in relation to modular forms) or `q = e^{\pi i \tau}` (usually in relation to theta functions) and satisfying `|q| < 1`. We will clarify the local meaning of `q` every time such a quantity appears as a function of `\tau`. As usual, the numerical functions in this module compute strict error bounds: if *tau* is represented by an :type:`acb_t` whose content overlaps with the real line (or lies in the lower half-plane), and *tau* is passed to a function defined only on `\mathbb{H}`, then the output will have an infinite radius. The analogous behavior holds for functions requiring `|q| < 1`. The modular group ------------------------------------------------------------------------------- .. type:: psl2z_struct .. type:: psl2z_t Represents an element of the modular group `\text{PSL}(2, \mathbb{Z})`, namely an integer matrix .. math:: \begin{pmatrix} a & b \\ c & d \end{pmatrix} with `ad-bc = 1`, and with signs canonicalized such that `c \ge 0`, and `d > 0` if `c = 0`. The struct members *a*, *b*, *c*, *d* are of type *fmpz*. .. function:: void psl2z_init(psl2z_t g) Initializes *g* and set it to the identity element. .. function:: void psl2z_clear(psl2z_t g) Clears *g*. .. function:: void psl2z_swap(psl2z_t f, psl2z_t g) Swaps *f* and *g* efficiently. .. function:: void psl2z_set(psl2z_t f, const psl2z_t g) Sets *f* to a copy of *g*. .. function:: void psl2z_one(psl2z_t g) Sets *g* to the identity element. .. function:: int psl2z_is_one(const psl2z_t g) Returns nonzero iff *g* is the identity element. .. function:: void psl2z_print(const psl2z_t g) Prints *g* to standard output. .. function:: void psl2z_fprint(FILE * file, const psl2z_t g) Prints *g* to the stream *file*. .. function:: int psl2z_equal(const psl2z_t f, const psl2z_t g) Returns nonzero iff *f* and *g* are equal. .. function:: void psl2z_mul(psl2z_t h, const psl2z_t f, const psl2z_t g) Sets *h* to the product of *f* and *g*, namely the matrix product with the signs canonicalized. .. function:: void psl2z_inv(psl2z_t h, const psl2z_t g) Sets *h* to the inverse of *g*. .. function:: int psl2z_is_correct(const psl2z_t g) Returns nonzero iff *g* contains correct data, i.e. satisfying `ad-bc = 1`, `c \ge 0`, and `d > 0` if `c = 0`. .. function:: void psl2z_randtest(psl2z_t g, flint_rand_t state, slong bits) Sets *g* to a random element of `\text{PSL}(2, \mathbb{Z})` with entries of bit length at most *bits* (or 1, if *bits* is not positive). We first generate *a* and *d*, compute their Bezout coefficients, divide by the GCD, and then correct the signs. Modular transformations ------------------------------------------------------------------------------- .. function:: void acb_modular_transform(acb_t w, const psl2z_t g, const acb_t z, slong prec) Applies the modular transformation *g* to the complex number *z*, evaluating .. math:: w = g z = \frac{az+b}{cz+d}. .. function:: void acb_modular_fundamental_domain_approx_d(psl2z_t g, double x, double y, double one_minus_eps) .. function:: void acb_modular_fundamental_domain_approx_arf(psl2z_t g, const arf_t x, const arf_t y, const arf_t one_minus_eps, slong prec) Attempts to determine a modular transformation *g* that maps the complex number `x+yi` to the fundamental domain or just slightly outside the fundamental domain, where the target tolerance (not a strict bound) is specified by *one_minus_eps*. The inputs are assumed to be finite numbers, with *y* positive. Uses floating-point iteration, repeatedly applying either the transformation `z \gets z + b` or `z \gets -1/z`. The iteration is terminated if `|x| \le 1/2` and `x^2 + y^2 \ge 1 - \varepsilon` where `1 - \varepsilon` is passed as *one_minus_eps*. It is also terminated if too many steps have been taken without convergence, or if the numbers end up too large or too small for the working precision. The algorithm can fail to produce a satisfactory transformation. The output *g* is always set to *some* correct modular transformation, but it is up to the user to verify a posteriori that *g* maps `x+yi` close enough to the fundamental domain. .. function:: void acb_modular_fundamental_domain_approx(acb_t w, psl2z_t g, const acb_t z, const arf_t one_minus_eps, slong prec) Attempts to determine a modular transformation *g* that maps the complex number `z` to the fundamental domain or just slightly outside the fundamental domain, where the target tolerance (not a strict bound) is specified by *one_minus_eps*. It also computes the transformed value `w = gz`. This function first tries to use :func:`acb_modular_fundamental_domain_approx_d` and checks if the result is acceptable. If this fails, it calls :func:`acb_modular_fundamental_domain_approx_arf` with higher precision. Finally, `w = gz` is evaluated by a single application of *g*. The algorithm can fail to produce a satisfactory transformation. The output *g* is always set to *some* correct modular transformation, but it is up to the user to verify a posteriori that `w` is close enough to the fundamental domain. .. function:: int acb_modular_is_in_fundamental_domain(const acb_t z, const arf_t tol, slong prec) Returns nonzero if it is certainly true that `|z| \ge 1 - \varepsilon` and `|\operatorname{Re}(z)| \le 1/2 + \varepsilon` where `\varepsilon` is specified by *tol*. Returns zero if this is false or cannot be determined. Addition sequences ------------------------------------------------------------------------------- .. function:: void acb_modular_fill_addseq(slong * tab, slong len) Builds a near-optimal addition sequence for a sequence of integers which is assumed to be reasonably dense. As input, the caller should set each entry in *tab* to `-1` if that index is to be part of the addition sequence, and to 0 otherwise. On output, entry *i* in *tab* will either be zero (if the number is not part of the sequence), or a value *j* such that both *j* and `i - j` are also marked. The first two entries in *tab* are ignored (the number 1 is always assumed to be part of the sequence). Jacobi theta functions ------------------------------------------------------------------------------- Unfortunately, there are many inconsistent notational variations for Jacobi theta functions in the literature. Unless otherwise noted, we use the functions .. math:: \theta_1(z,\tau) = -i \sum_{n=-\infty}^{\infty} (-1)^n \exp(\pi i [(n + 1/2)^2 \tau + (2n + 1) z]) = 2 q_{1/4} \sum_{n=0}^{\infty} (-1)^n q^{n(n+1)} \sin((2n+1) \pi z) .. math:: \theta_2(z,\tau) = \sum_{n=-\infty}^{\infty} \exp(\pi i [(n + 1/2)^2 \tau + (2n + 1) z]) = 2 q_{1/4} \sum_{n=0}^{\infty} q^{n(n+1)} \cos((2n+1) \pi z) .. math:: \theta_3(z,\tau) = \sum_{n=-\infty}^{\infty} \exp(\pi i [n^2 \tau + 2n z]) = 1 + 2 \sum_{n=1}^{\infty} q^{n^2} \cos(2n \pi z) .. math:: \theta_4(z,\tau) = \sum_{n=-\infty}^{\infty} (-1)^n \exp(\pi i [n^2 \tau + 2n z]) = 1 + 2 \sum_{n=1}^{\infty} (-1)^n q^{n^2} \cos(2n \pi z) where `q = \exp(\pi i \tau)` and `q_{1/4} = \exp(\pi i \tau / 4)`. Note that many authors write `q_{1/4}` as `q^{1/4}`, but the principal fourth root `(q)^{1/4} = \exp(\frac{1}{4} \log q)` differs from `q_{1/4}` in general and some formulas are only correct if one reads "`q^{1/4} = \exp(\pi i \tau / 4)`". To avoid confusion, we only write `q^k` when `k` is an integer. .. function:: void acb_modular_theta_transform(int * R, int * S, int * C, const psl2z_t g) We wish to write a theta function with quasiperiod `\tau` in terms of a theta function with quasiperiod `\tau' = g \tau`, given some `g = (a, b; c, d) \in \text{PSL}(2, \mathbb{Z})`. For `i = 0, 1, 2, 3`, this function computes integers `R_i` and `S_i` (*R* and *S* should be arrays of length 4) and `C \in \{0, 1\}` such that .. math:: \theta_{1+i}(z,\tau) = \exp(\pi i R_i / 4) \cdot A \cdot B \cdot \theta_{1+S_i}(z',\tau') where `z' = z, A = B = 1` if `C = 0`, and .. math:: z' = \frac{-z}{c \tau + d}, \quad A = \sqrt{\frac{i}{c \tau + d}}, \quad B = \exp\left(-\pi i c \frac{z^2}{c \tau + d}\right) if `C = 1`. Note that `A` is well-defined with the principal branch of the square root since `A^2 = i/(c \tau + d)` lies in the right half-plane. Firstly, if `c = 0`, we have `\theta_i(z, \tau) = \exp(-\pi i b / 4) \theta_i(z, \tau+b)` for `i = 1, 2`, whereas `\theta_3` and `\theta_4` remain unchanged when `b` is even and swap places with each other when `b` is odd. In this case we set `C = 0`. For an arbitrary `g` with `c > 0`, we set `C = 1`. The general transformations are given by Rademacher [Rad1973]_. We need the function `\theta_{m,n}(z,\tau)` defined for `m, n \in \mathbb{Z}` by (beware of the typos in [Rad1973]_) .. math:: \theta_{0,0}(z,\tau) = \theta_3(z,\tau), \quad \theta_{0,1}(z,\tau) = \theta_4(z,\tau) .. math:: \theta_{1,0}(z,\tau) = \theta_2(z,\tau), \quad \theta_{1,1}(z,\tau) = i \theta_1(z,\tau) .. math:: \theta_{m+2,n}(z,\tau) = (-1)^n \theta_{m,n}(z,\tau) .. math:: \theta_{m,n+2}(z,\tau) = \theta_{m,n}(z,\tau). Then we may write .. math:: \theta_1(z,\tau) &= \varepsilon_1 A B \theta_1(z', \tau') \theta_2(z,\tau) &= \varepsilon_2 A B \theta_{1-c,1+a}(z', \tau') \theta_3(z,\tau) &= \varepsilon_3 A B \theta_{1+d-c,1-b+a}(z', \tau') \theta_4(z,\tau) &= \varepsilon_4 A B \theta_{1+d,1-b}(z', \tau') where `\varepsilon_i` is an 8th root of unity. Specifically, if we denote the 24th root of unity in the transformation formula of the Dedekind eta function by `\varepsilon(a,b,c,d) = \exp(\pi i R(a,b,c,d) / 12)` (see :func:`acb_modular_epsilon_arg`), then: .. math:: \varepsilon_1(a,b,c,d) &= \exp(\pi i [R(-d,b,c,-a) + 1] / 4) \varepsilon_2(a,b,c,d) &= \exp(\pi i [-R(a,b,c,d) + (5+(2-c)a)] / 4) \varepsilon_3(a,b,c,d) &= \exp(\pi i [-R(a,b,c,d) + (4+(c-d-2)(b-a))] / 4) \varepsilon_4(a,b,c,d) &= \exp(\pi i [-R(a,b,c,d) + (3-(2+d)b)] / 4) These formulas are easily derived from the formulas in [Rad1973]_ (Rademacher has the transformed/untransformed variables exchanged, and his "`\varepsilon`" differs from ours by a constant offset in the phase). .. function:: void acb_modular_addseq_theta(slong * exponents, slong * aindex, slong * bindex, slong num) Constructs an addition sequence for the first *num* squares and triangular numbers interleaved (excluding zero), i.e. 1, 2, 4, 6, 9, 12, 16, 20, 25, 30 etc. .. function:: void acb_modular_theta_sum(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t w, int w_is_unit, const acb_t q, slong len, slong prec) Simultaneously computes the first *len* coefficients of each of the formal power series .. math:: \theta_1(z+x,\tau) / q_{1/4} \in \mathbb{C}[[x]] \theta_2(z+x,\tau) / q_{1/4} \in \mathbb{C}[[x]] \theta_3(z+x,\tau) \in \mathbb{C}[[x]] \theta_4(z+x,\tau) \in \mathbb{C}[[x]] given `w = \exp(\pi i z)` and `q = \exp(\pi i \tau)`, by summing a finite truncation of the respective theta function series. In particular, with *len* equal to 1, computes the respective value of the theta function at the point *z*. We require *len* to be positive. If *w_is_unit* is nonzero, *w* is assumed to lie on the unit circle, i.e. *z* is assumed to be real. Note that the factor `q_{1/4}` is removed from `\theta_1` and `\theta_2`. To get the true theta function values, the user has to multiply this factor back. This convention avoids unnecessary computations, since the user can compute `q_{1/4} = \exp(\pi i \tau / 4)` followed by `q = (q_{1/4})^4`, and in many cases when computing products or quotients of theta functions, the factor `q_{1/4}` can be eliminated entirely. This function is intended for `|q| \ll 1`. It can be called with any `q`, but will return useless intervals if convergence is not rapid. For general evaluation of theta functions, the user should only call this function after applying a suitable modular transformation. We consider the sums together, alternatingly updating `(\theta_1, \theta_2)` or `(\theta_3, \theta_4)`. For `k = 0, 1, 2, \ldots`, the powers of `q` are `\lfloor (k+2)^2 / 4 \rfloor = 1, 2, 4, 6, 9` etc. and the powers of `w` are `\pm (k+2) = \pm 2, \pm 3, \pm 4, \ldots` etc. The scheme is illustrated by the following table: .. math:: \begin{array}{llll} & \theta_1, \theta_2 & q^0 & (w^1 \pm w^{-1}) \\ k = 0 & \theta_3, \theta_4 & q^1 & (w^2 \pm w^{-2}) \\ k = 1 & \theta_1, \theta_2 & q^2 & (w^3 \pm w^{-3}) \\ k = 2 & \theta_3, \theta_4 & q^4 & (w^4 \pm w^{-4}) \\ k = 3 & \theta_1, \theta_2 & q^6 & (w^5 \pm w^{-5}) \\ k = 4 & \theta_3, \theta_4 & q^9 & (w^6 \pm w^{-6}) \\ k = 5 & \theta_1, \theta_2 & q^{12} & (w^7 \pm w^{-7}) \\ \end{array} For some integer `N \ge 1`, the summation is stopped just before term `k = N`. Let `Q = |q|`, `W = \max(|w|,|w^{-1}|)`, `E = \lfloor (N+2)^2 / 4 \rfloor` and `F = \lfloor (N+1)/2 \rfloor + 1`. The error of the zeroth derivative can be bounded as .. math:: 2 Q^E W^{N+2} \left[ 1 + Q^F W + Q^{2F} W^2 + \ldots \right] = \frac{2 Q^E W^{N+2}}{1 - Q^F W} provided that the denominator is positive (otherwise we set the error bound to infinity). When *len* is greater than 1, consider the derivative of order *r*. The term of index *k* and order *r* picks up a factor of magnitude `(k+2)^r` from differentiation of `w^{k+2}` (it also picks up a factor `\pi^r`, but we omit this until we rescale the coefficients at the end of the computation). Thus we have the error bound .. math:: 2 Q^E W^{N+2} (N+2)^r \left[ 1 + Q^F W \frac{(N+3)^r}{(N+2)^r} + Q^{2F} W^2 \frac{(N+4)^r}{(N+2)^r} + \ldots \right] which by the inequality `(1 + m/(N+2))^r \le \exp(mr/(N+2))` can be bounded as .. math:: \frac{2 Q^E W^{N+2} (N+2)^r}{1 - Q^F W \exp(r/(N+2))}, again valid when the denominator is positive. To actually evaluate the series, we write the even cosine terms as `w^{2n} + w^{-2n}`, the odd cosine terms as `w (w^{2n} + w^{-2n-2})`, and the sine terms as `w (w^{2n} - w^{-2n-2})`. This way we only need even powers of `w` and `w^{-1}`. The implementation is not yet optimized for real `z`, in which case further work can be saved. This function does not permit aliasing between input and output arguments. .. function:: void acb_modular_theta_const_sum_basecase(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong N, slong prec) .. function:: void acb_modular_theta_const_sum_rs(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong N, slong prec) Computes the truncated theta constant sums `\theta_2 = \sum_{k(k+1) < N} q^{k(k+1)}`, `\theta_3 = \sum_{k^2 < N} q^{k^2}`, `\theta_4 = \sum_{k^2 < N} (-1)^k q^{k^2}`. The *basecase* version uses a short addition sequence. The *rs* version uses rectangular splitting. The algorithms are described in [EHJ2016]_. .. function:: void acb_modular_theta_const_sum(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong prec) Computes the respective theta constants by direct summation (without applying modular transformations). This function selects an appropriate *N*, calls either :func:`acb_modular_theta_const_sum_basecase` or :func:`acb_modular_theta_const_sum_rs` or depending on *N*, and adds a bound for the truncation error. .. function:: void acb_modular_theta_notransform(acb_t theta1, acb_t theta2, acb_t theta3, acb_t theta4, const acb_t z, const acb_t tau, slong prec) Evaluates the Jacobi theta functions `\theta_i(z,\tau)`, `i = 1, 2, 3, 4` simultaneously. This function does not move `\tau` to the fundamental domain. This is generally worse than :func:`acb_modular_theta`, but can be slightly better for moderate input. .. function:: void acb_modular_theta(acb_t theta1, acb_t theta2, acb_t theta3, acb_t theta4, const acb_t z, const acb_t tau, slong prec) Evaluates the Jacobi theta functions `\theta_i(z,\tau)`, `i = 1, 2, 3, 4` simultaneously. This function moves `\tau` to the fundamental domain and then also reduces `z` modulo `\tau` before calling :func:`acb_modular_theta_sum`. .. function:: void acb_modular_theta_jet_notransform(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t z, const acb_t tau, slong len, slong prec) .. function:: void acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t z, const acb_t tau, slong len, slong prec) Evaluates the Jacobi theta functions along with their derivatives with respect to *z*, writing the first *len* coefficients in the power series `\theta_i(z+x,\tau) \in \mathbb{C}[[x]]` to each respective output variable. The *notransform* version does not move `\tau` to the fundamental domain or reduce `z` during the computation. .. function:: void _acb_modular_theta_series(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec) .. function:: void acb_modular_theta_series(acb_poly_t theta1, acb_poly_t theta2, acb_poly_t theta3, acb_poly_t theta4, const acb_poly_t z, const acb_t tau, slong len, slong prec) Evaluates the respective Jacobi theta functions of the power series *z*, truncated to length *len*. Either of the output variables can be *NULL*. Dedekind eta function ------------------------------------------------------------------------------- .. function:: void acb_modular_addseq_eta(slong * exponents, slong * aindex, slong * bindex, slong num) Constructs an addition sequence for the first *num* generalized pentagonal numbers (excluding zero), i.e. 1, 2, 5, 7, 12, 15, 22, 26, 35, 40 etc. .. function:: void acb_modular_eta_sum(acb_t eta, const acb_t q, slong prec) Evaluates the Dedekind eta function without the leading 24th root, i.e. .. math:: \exp(-\pi i \tau/12) \eta(\tau) = \sum_{n=-\infty}^{\infty} (-1)^n q^{(3n^2-n)/2} given `q = \exp(2 \pi i \tau)`, by summing the defining series. This function is intended for `|q| \ll 1`. It can be called with any `q`, but will return useless intervals if convergence is not rapid. For general evaluation of the eta function, the user should only call this function after applying a suitable modular transformation. The series is evaluated using either a short addition sequence or rectangular splitting, depending on the number of terms. The algorithms are described in [EHJ2016]_. .. function:: int acb_modular_epsilon_arg(const psl2z_t g) Given `g = (a, b; c, d)`, computes an integer `R` such that `\varepsilon(a,b,c,d) = \exp(\pi i R / 12)` is the 24th root of unity in the transformation formula for the Dedekind eta function, .. math:: \eta\left(\frac{a\tau+b}{c\tau+d}\right) = \varepsilon (a,b,c,d) \sqrt{c\tau+d} \eta(\tau). .. function:: void acb_modular_eta(acb_t r, const acb_t tau, slong prec) Computes the Dedekind eta function `\eta(\tau)` given `\tau` in the upper half-plane. This function applies the functional equation to move `\tau` to the fundamental domain before calling :func:`acb_modular_eta_sum`. Modular forms ------------------------------------------------------------------------------- .. function:: void acb_modular_j(acb_t r, const acb_t tau, slong prec) Computes Klein's j-invariant `j(\tau)` given `\tau` in the upper half-plane. The function is normalized so that `j(i) = 1728`. We first move `\tau` to the fundamental domain, which does not change the value of the function. Then we use the formula `j(\tau) = 32 (\theta_2^8+\theta_3^8+\theta_4^8)^3 / (\theta_2 \theta_3 \theta_4)^8` where `\theta_i = \theta_i(0,\tau)`. .. function:: void acb_modular_lambda(acb_t r, const acb_t tau, slong prec) Computes the lambda function `\lambda(\tau) = \theta_2^4(0,\tau) / \theta_3^4(0,\tau)`, which is invariant under modular transformations `(a, b; c, d)` where `a, d` are odd and `b, c` are even. .. function:: void acb_modular_delta(acb_t r, const acb_t tau, slong prec) Computes the modular discriminant `\Delta(\tau) = \eta(\tau)^{24}`, which transforms as .. math:: \Delta\left(\frac{a\tau+b}{c\tau+d}\right) = (c\tau+d)^{12} \Delta(\tau). The modular discriminant is sometimes defined with an extra factor `(2\pi)^{12}`, which we omit in this implementation. .. function:: void acb_modular_eisenstein(acb_ptr r, const acb_t tau, slong len, slong prec) Computes simultaneously the first *len* entries in the sequence of Eisenstein series `G_4(\tau), G_6(\tau), G_8(\tau), \ldots`, defined by .. math:: G_{2k}(\tau) = \sum_{m^2 + n^2 \ne 0} \frac{1}{(m+n\tau )^{2k}} and satisfying .. math:: G_{2k} \left(\frac{a\tau+b}{c\tau+d}\right) = (c\tau+d)^{2k} G_{2k}(\tau). We first evaluate `G_4(\tau)` and `G_6(\tau)` on the fundamental domain using theta functions, and then compute the Eisenstein series of higher index using a recurrence relation. Elliptic integrals and functions ------------------------------------------------------------------------------- See the :ref:`acb_elliptic.h ` module for elliptic integrals and functions. The following wrappers are available for backwards compatibility. .. function:: void acb_modular_elliptic_k(acb_t w, const acb_t m, slong prec) .. function:: void acb_modular_elliptic_k_cpx(acb_ptr w, const acb_t m, slong len, slong prec) .. function:: void acb_modular_elliptic_e(acb_t w, const acb_t m, slong prec) .. function:: void acb_modular_elliptic_p(acb_t wp, const acb_t z, const acb_t tau, slong prec) .. function:: void acb_modular_elliptic_p_zpx(acb_ptr wp, const acb_t z, const acb_t tau, slong len, slong prec) Class polynomials ------------------------------------------------------------------------------- .. function:: void acb_modular_hilbert_class_poly(fmpz_poly_t res, slong D) Sets *res* to the Hilbert class polynomial of discriminant *D*, defined as .. math:: H_D(x) = \prod_{(a,b,c)} \left(x - j\left(\frac{-b+\sqrt{D}}{2a}\right)\right) where `(a,b,c)` ranges over the primitive reduced positive definite binary quadratic forms of discriminant `b^2 - 4ac = D`. The Hilbert class polynomial is only defined if `D < 0` and *D* is congruent to 0 or 1 mod 4. If some other value of *D* is passed as input, *res* is set to the zero polynomial. flint-3.1.3/doc/source/acb_poly.rst000066400000000000000000001501051461254215100172240ustar00rootroot00000000000000.. _acb-poly: **acb_poly.h** -- polynomials over the complex numbers =============================================================================== An :type:`acb_poly_t` represents a polynomial over the complex numbers, implemented as an array of coefficients of type :type:`acb_struct`. Most functions are provided in two versions: an underscore method which operates directly on pre-allocated arrays of coefficients and generally has some restrictions (such as requiring the lengths to be nonzero and not supporting aliasing of the input and output arrays), and a non-underscore method which performs automatic memory management and handles degenerate cases. Types, macros and constants ------------------------------------------------------------------------------- .. type:: acb_poly_struct .. type:: acb_poly_t Contains a pointer to an array of coefficients (coeffs), the used length (length), and the allocated size of the array (alloc). An *acb_poly_t* is defined as an array of length one of type *acb_poly_struct*, permitting an *acb_poly_t* to be passed by reference. Memory management ------------------------------------------------------------------------------- .. function:: void acb_poly_init(acb_poly_t poly) Initializes the polynomial for use, setting it to the zero polynomial. .. function:: void acb_poly_clear(acb_poly_t poly) Clears the polynomial, deallocating all coefficients and the coefficient array. .. function:: void acb_poly_fit_length(acb_poly_t poly, slong len) Makes sure that the coefficient array of the polynomial contains at least *len* initialized coefficients. .. function:: void _acb_poly_set_length(acb_poly_t poly, slong len) Directly changes the length of the polynomial, without allocating or deallocating coefficients. The value should not exceed the allocation length. .. function:: void _acb_poly_normalise(acb_poly_t poly) Strips any trailing coefficients which are identical to zero. .. function:: void acb_poly_swap(acb_poly_t poly1, acb_poly_t poly2) Swaps *poly1* and *poly2* efficiently. .. function:: slong acb_poly_allocated_bytes(const acb_poly_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(acb_poly_struct)`` to get the size of the object as a whole. Basic properties and manipulation ------------------------------------------------------------------------------- .. function:: slong acb_poly_length(const acb_poly_t poly) Returns the length of *poly*, i.e. zero if *poly* is identically zero, and otherwise one more than the index of the highest term that is not identically zero. .. function:: slong acb_poly_degree(const acb_poly_t poly) Returns the degree of *poly*, defined as one less than its length. Note that if one or several leading coefficients are balls containing zero, this value can be larger than the true degree of the exact polynomial represented by *poly*, so the return value of this function is effectively an upper bound. .. function:: int acb_poly_is_zero(const acb_poly_t poly) .. function:: int acb_poly_is_one(const acb_poly_t poly) .. function:: int acb_poly_is_x(const acb_poly_t poly) Returns 1 if *poly* is exactly the polynomial 0, 1 or *x* respectively. Returns 0 otherwise. .. function:: void acb_poly_zero(acb_poly_t poly) Sets *poly* to the zero polynomial. .. function:: void acb_poly_one(acb_poly_t poly) Sets *poly* to the constant polynomial 1. .. function:: void acb_poly_set(acb_poly_t dest, const acb_poly_t src) Sets *dest* to a copy of *src*. .. function:: void acb_poly_set_round(acb_poly_t dest, const acb_poly_t src, slong prec) Sets *dest* to a copy of *src*, rounded to *prec* bits. .. function:: void acb_poly_set_trunc(acb_poly_t dest, const acb_poly_t src, slong n) .. function:: void acb_poly_set_trunc_round(acb_poly_t dest, const acb_poly_t src, slong n, slong prec) Sets *dest* to a copy of *src*, truncated to length *n* and rounded to *prec* bits. .. function:: void acb_poly_set_coeff_si(acb_poly_t poly, slong n, slong c) .. function:: void acb_poly_set_coeff_acb(acb_poly_t poly, slong n, const acb_t c) Sets the coefficient with index *n* in *poly* to the value *c*. We require that *n* is nonnegative. .. function:: void acb_poly_get_coeff_acb(acb_t v, const acb_poly_t poly, slong n) Sets *v* to the value of the coefficient with index *n* in *poly*. We require that *n* is nonnegative. .. macro:: acb_poly_get_coeff_ptr(poly, n) Given `n \ge 0`, returns a pointer to coefficient *n* of *poly*, or *NULL* if *n* exceeds the length of *poly*. .. function:: void _acb_poly_shift_right(acb_ptr res, acb_srcptr poly, slong len, slong n) .. function:: void acb_poly_shift_right(acb_poly_t res, const acb_poly_t poly, slong n) Sets *res* to *poly* divided by `x^n`, throwing away the lower coefficients. We require that *n* is nonnegative. .. function:: void _acb_poly_shift_left(acb_ptr res, acb_srcptr poly, slong len, slong n) .. function:: void acb_poly_shift_left(acb_poly_t res, const acb_poly_t poly, slong n) Sets *res* to *poly* multiplied by `x^n`. We require that *n* is nonnegative. .. function:: void acb_poly_truncate(acb_poly_t poly, slong n) Truncates *poly* to have length at most *n*, i.e. degree strictly smaller than *n*. We require that *n* is nonnegative. .. function:: slong acb_poly_valuation(const acb_poly_t poly) Returns the degree of the lowest term that is not exactly zero in *poly*. Returns -1 if *poly* is the zero polynomial. Input and output ------------------------------------------------------------------------------- .. function:: void acb_poly_printd(const acb_poly_t poly, slong digits) Prints the polynomial as an array of coefficients, printing each coefficient using *acb_printd*. .. function:: void acb_poly_fprintd(FILE * file, const acb_poly_t poly, slong digits) Prints the polynomial as an array of coefficients to the stream *file*, printing each coefficient using *acb_fprintd*. Random generation ------------------------------------------------------------------------------- .. function:: void acb_poly_randtest(acb_poly_t poly, flint_rand_t state, slong len, slong prec, slong mag_bits) Creates a random polynomial with length at most *len*. Comparisons ------------------------------------------------------------------------------- .. function:: int acb_poly_equal(const acb_poly_t A, const acb_poly_t B) Returns nonzero iff *A* and *B* are identical as interval polynomials. .. function:: int acb_poly_contains(const acb_poly_t poly1, const acb_poly_t poly2) .. function:: int acb_poly_contains_fmpz_poly(const acb_poly_t poly1, const fmpz_poly_t poly2) .. function:: int acb_poly_contains_fmpq_poly(const acb_poly_t poly1, const fmpq_poly_t poly2) Returns nonzero iff *poly2* is contained in *poly1*. .. function:: int _acb_poly_overlaps(acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2) .. function:: int acb_poly_overlaps(const acb_poly_t poly1, const acb_poly_t poly2) Returns nonzero iff *poly1* overlaps with *poly2*. The underscore function requires that *len1* is at least as large as *len2*. .. function:: int acb_poly_get_unique_fmpz_poly(fmpz_poly_t z, const acb_poly_t x) If *x* contains a unique integer polynomial, sets *z* to that value and returns nonzero. Otherwise (if *x* represents no integers or more than one integer), returns zero, possibly partially modifying *z*. .. function:: int acb_poly_is_real(const acb_poly_t poly) Returns nonzero iff all coefficients in *poly* have zero imaginary part. Conversions ------------------------------------------------------------------------------- .. function:: void acb_poly_set_fmpz_poly(acb_poly_t poly, const fmpz_poly_t re, slong prec) .. function:: void acb_poly_set2_fmpz_poly(acb_poly_t poly, const fmpz_poly_t re, const fmpz_poly_t im, slong prec) .. function:: void acb_poly_set_arb_poly(acb_poly_t poly, const arb_poly_t re) .. function:: void acb_poly_set2_arb_poly(acb_poly_t poly, const arb_poly_t re, const arb_poly_t im) .. function:: void acb_poly_set_fmpq_poly(acb_poly_t poly, const fmpq_poly_t re, slong prec) .. function:: void acb_poly_set2_fmpq_poly(acb_poly_t poly, const fmpq_poly_t re, const fmpq_poly_t im, slong prec) Sets *poly* to the given real part *re* plus the imaginary part *im*, both rounded to *prec* bits. .. function:: void acb_poly_set_acb(acb_poly_t poly, const acb_t src) .. function:: void acb_poly_set_si(acb_poly_t poly, slong src) Sets *poly* to *src*. Bounds ------------------------------------------------------------------------------- .. function:: void _acb_poly_majorant(arb_ptr res, acb_srcptr poly, slong len, slong prec) .. function:: void acb_poly_majorant(arb_poly_t res, const acb_poly_t poly, slong prec) Sets *res* to an exact real polynomial whose coefficients are upper bounds for the absolute values of the coefficients in *poly*, rounded to *prec* bits. Arithmetic ------------------------------------------------------------------------------- .. function:: void _acb_poly_add(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) Sets *{C, max(lenA, lenB)}* to the sum of *{A, lenA}* and *{B, lenB}*. Allows aliasing of the input and output operands. .. function:: void acb_poly_add(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong prec) .. function:: void acb_poly_add_si(acb_poly_t C, const acb_poly_t A, slong B, slong prec) Sets *C* to the sum of *A* and *B*. .. function:: void _acb_poly_sub(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) Sets *{C, max(lenA, lenB)}* to the difference of *{A, lenA}* and *{B, lenB}*. Allows aliasing of the input and output operands. .. function:: void acb_poly_sub(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong prec) Sets *C* to the difference of *A* and *B*. .. function:: void acb_poly_add_series(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong len, slong prec) Sets *C* to the sum of *A* and *B*, truncated to length *len*. .. function:: void acb_poly_sub_series(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong len, slong prec) Sets *C* to the difference of *A* and *B*, truncated to length *len*. .. function:: void acb_poly_neg(acb_poly_t C, const acb_poly_t A) Sets *C* to the negation of *A*. .. function:: void acb_poly_scalar_mul_2exp_si(acb_poly_t C, const acb_poly_t A, slong c) Sets *C* to *A* multiplied by `2^c`. .. function:: void acb_poly_scalar_mul(acb_poly_t C, const acb_poly_t A, const acb_t c, slong prec) Sets *C* to *A* multiplied by *c*. .. function:: void acb_poly_scalar_div(acb_poly_t C, const acb_poly_t A, const acb_t c, slong prec) Sets *C* to *A* divided by *c*. .. function:: void _acb_poly_mullow_classical(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong n, slong prec) .. function:: void _acb_poly_mullow_transpose(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong n, slong prec) .. function:: void _acb_poly_mullow_transpose_gauss(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong n, slong prec) .. function:: void _acb_poly_mullow(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong n, slong prec) Sets *{C, n}* to the product of *{A, lenA}* and *{B, lenB}*, truncated to length *n*. The output is not allowed to be aliased with either of the inputs. We require `\mathrm{lenA} \ge \mathrm{lenB} > 0`, `n > 0`, `\mathrm{lenA} + \mathrm{lenB} - 1 \ge n`. The *classical* version uses a plain loop. The *transpose* version evaluates the product using four real polynomial multiplications (via :func:`_arb_poly_mullow`). The *transpose_gauss* version evaluates the product using three real polynomial multiplications. This is almost always faster than *transpose*, but has worse numerical stability when the coefficients vary in magnitude. The default function :func:`_acb_poly_mullow` automatically switches been *classical* and *transpose* multiplication. If the input pointers are identical (and the lengths are the same), they are assumed to represent the same polynomial, and its square is computed. .. function:: void acb_poly_mullow_classical(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong n, slong prec) .. function:: void acb_poly_mullow_transpose(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong n, slong prec) .. function:: void acb_poly_mullow_transpose_gauss(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong n, slong prec) .. function:: void acb_poly_mullow(acb_poly_t C, const acb_poly_t A, const acb_poly_t B, slong n, slong prec) Sets *C* to the product of *A* and *B*, truncated to length *n*. If the same variable is passed for *A* and *B*, sets *C* to the square of *A* truncated to length *n*. .. function:: void _acb_poly_mul(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) Sets *{C, lenA + lenB - 1}* to the product of *{A, lenA}* and *{B, lenB}*. The output is not allowed to be aliased with either of the inputs. We require `\mathrm{lenA} \ge \mathrm{lenB} > 0`. This function is implemented as a simple wrapper for :func:`_acb_poly_mullow`. If the input pointers are identical (and the lengths are the same), they are assumed to represent the same polynomial, and its square is computed. .. function:: void acb_poly_mul(acb_poly_t C, const acb_poly_t A1, const acb_poly_t B2, slong prec) Sets *C* to the product of *A* and *B*. If the same variable is passed for *A* and *B*, sets *C* to the square of *A*. .. function:: void _acb_poly_inv_series(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong len, slong prec) Sets *{Qinv, len}* to the power series inverse of *{Q, Qlen}*. Uses Newton iteration. .. function:: void acb_poly_inv_series(acb_poly_t Qinv, const acb_poly_t Q, slong n, slong prec) Sets *Qinv* to the power series inverse of *Q*. .. function:: void _acb_poly_div_series(acb_ptr Q, acb_srcptr A, slong Alen, acb_srcptr B, slong Blen, slong n, slong prec) Sets *{Q, n}* to the power series quotient of *{A, Alen}* by *{B, Blen}*. Uses Newton iteration followed by multiplication. .. function:: void acb_poly_div_series(acb_poly_t Q, const acb_poly_t A, const acb_poly_t B, slong n, slong prec) Sets *Q* to the power series quotient *A* divided by *B*, truncated to length *n*. .. function:: void _acb_poly_div(acb_ptr Q, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) .. function:: void _acb_poly_rem(acb_ptr R, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) .. function:: void _acb_poly_divrem(acb_ptr Q, acb_ptr R, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) .. function:: int acb_poly_divrem(acb_poly_t Q, acb_poly_t R, const acb_poly_t A, const acb_poly_t B, slong prec) Performs polynomial division with remainder, computing a quotient `Q` and a remainder `R` such that `A = BQ + R`. The implementation reverses the inputs and performs power series division. If the leading coefficient of `B` contains zero (or if `B` is identically zero), returns 0 indicating failure without modifying the outputs. Otherwise returns nonzero. .. function:: void _acb_poly_div_root(acb_ptr Q, acb_t R, acb_srcptr A, slong len, const acb_t c, slong prec) Divides `A` by the polynomial `x - c`, computing the quotient `Q` as well as the remainder `R = f(c)`. Composition ------------------------------------------------------------------------------- .. function:: void _acb_poly_taylor_shift(acb_ptr g, const acb_t c, slong n, slong prec) void acb_poly_taylor_shift(acb_poly_t g, const acb_poly_t f, const acb_t c, slong prec) Sets *g* to the Taylor shift `f(x+c)`. The underscore methods act in-place on *g* = *f* which has length *n*. .. function:: void _acb_poly_compose(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec) void acb_poly_compose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec) Sets *res* to the composition `h(x) = f(g(x))` where `f` is given by *poly1* and `g` is given by *poly2*. The underscore method does not support aliasing of the output with either input polynomial. .. function:: void _acb_poly_compose_series(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) void acb_poly_compose_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec) Sets *res* to the power series composition `h(x) = f(g(x))` truncated to order `O(x^n)` where `f` is given by *poly1* and `g` is given by *poly2*. Wraps :func:`_gr_poly_compose_series` which chooses automatically between various algorithms. We require that the constant term in `g(x)` is exactly zero. The underscore method does not support aliasing of the output with either input polynomial. .. function:: void _acb_poly_revert_series(acb_ptr h, acb_srcptr f, slong flen, slong n, slong prec) void acb_poly_revert_series(acb_poly_t h, const acb_poly_t f, slong n, slong prec) Sets `h` to the power series reversion of `f`, i.e. the expansion of the compositional inverse function `f^{-1}(x)`, truncated to order `O(x^n)`. Wraps :func:`_gr_poly_revert_series` which chooses automatically between various algorithms. We require that the constant term in `f` is exactly zero and that the linear term is nonzero. The underscore method assumes that *flen* is at least 2, and do not support aliasing. Evaluation ------------------------------------------------------------------------------- .. function:: void _acb_poly_evaluate_horner(acb_t y, acb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void acb_poly_evaluate_horner(acb_t y, const acb_poly_t f, const acb_t x, slong prec) .. function:: void _acb_poly_evaluate_rectangular(acb_t y, acb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void acb_poly_evaluate_rectangular(acb_t y, const acb_poly_t f, const acb_t x, slong prec) .. function:: void _acb_poly_evaluate(acb_t y, acb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void acb_poly_evaluate(acb_t y, const acb_poly_t f, const acb_t x, slong prec) Sets `y = f(x)`, evaluated respectively using Horner's rule, rectangular splitting, and an automatic algorithm choice. .. function:: void _acb_poly_evaluate2_horner(acb_t y, acb_t z, acb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void acb_poly_evaluate2_horner(acb_t y, acb_t z, const acb_poly_t f, const acb_t x, slong prec) .. function:: void _acb_poly_evaluate2_rectangular(acb_t y, acb_t z, acb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void acb_poly_evaluate2_rectangular(acb_t y, acb_t z, const acb_poly_t f, const acb_t x, slong prec) .. function:: void _acb_poly_evaluate2(acb_t y, acb_t z, acb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void acb_poly_evaluate2(acb_t y, acb_t z, const acb_poly_t f, const acb_t x, slong prec) Sets `y = f(x), z = f'(x)`, evaluated respectively using Horner's rule, rectangular splitting, and an automatic algorithm choice. When Horner's rule is used, the only advantage of evaluating the function and its derivative simultaneously is that one does not have to generate the derivative polynomial explicitly. With the rectangular splitting algorithm, the powers can be reused, making simultaneous evaluation slightly faster. Product trees ------------------------------------------------------------------------------- .. function:: void _acb_poly_product_roots(acb_ptr poly, acb_srcptr xs, slong n, slong prec) .. function:: void acb_poly_product_roots(acb_poly_t poly, acb_srcptr xs, slong n, slong prec) Generates the polynomial `(x-x_0)(x-x_1)\cdots(x-x_{n-1})`. .. function:: acb_ptr * _acb_poly_tree_alloc(slong len) Returns an initialized data structured capable of representing a remainder tree (product tree) of *len* roots. .. function:: void _acb_poly_tree_free(acb_ptr * tree, slong len) Deallocates a tree structure as allocated using *_acb_poly_tree_alloc*. .. function:: void _acb_poly_tree_build(acb_ptr * tree, acb_srcptr roots, slong len, slong prec) Constructs a product tree from a given array of *len* roots. The tree structure must be pre-allocated to the specified length using :func:`_acb_poly_tree_alloc`. Multipoint evaluation ------------------------------------------------------------------------------- .. function:: void _acb_poly_evaluate_vec_iter(acb_ptr ys, acb_srcptr poly, slong plen, acb_srcptr xs, slong n, slong prec) .. function:: void acb_poly_evaluate_vec_iter(acb_ptr ys, const acb_poly_t poly, acb_srcptr xs, slong n, slong prec) Evaluates the polynomial simultaneously at *n* given points, calling :func:`_acb_poly_evaluate` repeatedly. .. function:: void _acb_poly_evaluate_vec_fast_precomp(acb_ptr vs, acb_srcptr poly, slong plen, acb_ptr * tree, slong len, slong prec) .. function:: void _acb_poly_evaluate_vec_fast(acb_ptr ys, acb_srcptr poly, slong plen, acb_srcptr xs, slong n, slong prec) .. function:: void acb_poly_evaluate_vec_fast(acb_ptr ys, const acb_poly_t poly, acb_srcptr xs, slong n, slong prec) Evaluates the polynomial simultaneously at *n* given points, using fast multipoint evaluation. Interpolation ------------------------------------------------------------------------------- .. function:: void _acb_poly_interpolate_newton(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) .. function:: void acb_poly_interpolate_newton(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) Recovers the unique polynomial of length at most *n* that interpolates the given *x* and *y* values. This implementation first interpolates in the Newton basis and then converts back to the monomial basis. .. function:: void _acb_poly_interpolate_barycentric(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) .. function:: void acb_poly_interpolate_barycentric(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) Recovers the unique polynomial of length at most *n* that interpolates the given *x* and *y* values. This implementation uses the barycentric form of Lagrange interpolation. .. function:: void _acb_poly_interpolation_weights(acb_ptr w, acb_ptr * tree, slong len, slong prec) .. function:: void _acb_poly_interpolate_fast_precomp(acb_ptr poly, acb_srcptr ys, acb_ptr * tree, acb_srcptr weights, slong len, slong prec) .. function:: void _acb_poly_interpolate_fast(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong len, slong prec) .. function:: void acb_poly_interpolate_fast(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) Recovers the unique polynomial of length at most *n* that interpolates the given *x* and *y* values, using fast Lagrange interpolation. The precomp function takes a precomputed product tree over the *x* values and a vector of interpolation weights as additional inputs. Differentiation ------------------------------------------------------------------------------- .. function:: void _acb_poly_derivative(acb_ptr res, acb_srcptr poly, slong len, slong prec) Sets *{res, len - 1}* to the derivative of *{poly, len}*. Allows aliasing of the input and output. .. function:: void acb_poly_derivative(acb_poly_t res, const acb_poly_t poly, slong prec) Sets *res* to the derivative of *poly*. .. function:: void _acb_poly_nth_derivative(acb_ptr res, acb_srcptr poly, ulong n, slong len, slong prec) Sets *{res, len - n}* to the nth derivative of *{poly, len}*. Does nothing if *len <= n*. Allows aliasing of the input and output. .. function:: void acb_poly_nth_derivative(acb_poly_t res, const acb_poly_t poly, ulong n, slong prec) Sets *res* to the nth derivative of *poly*. .. function:: void _acb_poly_integral(acb_ptr res, acb_srcptr poly, slong len, slong prec) Sets *{res, len}* to the integral of *{poly, len - 1}*. Allows aliasing of the input and output. .. function:: void acb_poly_integral(acb_poly_t res, const acb_poly_t poly, slong prec) Sets *res* to the integral of *poly*. Transforms ------------------------------------------------------------------------------- .. function:: void _acb_poly_borel_transform(acb_ptr res, acb_srcptr poly, slong len, slong prec) .. function:: void acb_poly_borel_transform(acb_poly_t res, const acb_poly_t poly, slong prec) Computes the Borel transform of the input polynomial, mapping `\sum_k a_k x^k` to `\sum_k (a_k / k!) x^k`. The underscore method allows aliasing. .. function:: void _acb_poly_inv_borel_transform(acb_ptr res, acb_srcptr poly, slong len, slong prec) .. function:: void acb_poly_inv_borel_transform(acb_poly_t res, const acb_poly_t poly, slong prec) Computes the inverse Borel transform of the input polynomial, mapping `\sum_k a_k x^k` to `\sum_k a_k k! x^k`. The underscore method allows aliasing. .. function:: void _acb_poly_binomial_transform_basecase(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec) .. function:: void acb_poly_binomial_transform_basecase(acb_poly_t b, const acb_poly_t a, slong len, slong prec) .. function:: void _acb_poly_binomial_transform_convolution(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec) .. function:: void acb_poly_binomial_transform_convolution(acb_poly_t b, const acb_poly_t a, slong len, slong prec) .. function:: void _acb_poly_binomial_transform(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec) .. function:: void acb_poly_binomial_transform(acb_poly_t b, const acb_poly_t a, slong len, slong prec) Computes the binomial transform of the input polynomial, truncating the output to length *len*. See :func:`arb_poly_binomial_transform` for details. The underscore methods do not support aliasing, and assume that the lengths are nonzero. .. function:: void _acb_poly_graeffe_transform(acb_ptr b, acb_srcptr a, slong len, slong prec) .. function:: void acb_poly_graeffe_transform(acb_poly_t b, const acb_poly_t a, slong prec) Computes the Graeffe transform of input polynomial, which is of length *len*. See :func:`arb_poly_graeffe_transform` for details. The underscore method assumes that *a* and *b* are initialized, *a* is of length *len*, and *b* is of length at least *len*. Both methods allow aliasing. Elementary functions ------------------------------------------------------------------------------- .. function:: void _acb_poly_pow_ui_trunc_binexp(acb_ptr res, acb_srcptr f, slong flen, ulong exp, slong len, slong prec) Sets *{res, len}* to *{f, flen}* raised to the power *exp*, truncated to length *len*. Requires that *len* is no longer than the length of the power as computed without truncation (i.e. no zero-padding is performed). Does not support aliasing of the input and output, and requires that *flen* and *len* are positive. Uses binary exponentiation. .. function:: void acb_poly_pow_ui_trunc_binexp(acb_poly_t res, const acb_poly_t poly, ulong exp, slong len, slong prec) Sets *res* to *poly* raised to the power *exp*, truncated to length *len*. Uses binary exponentiation. .. function:: void _acb_poly_pow_ui(acb_ptr res, acb_srcptr f, slong flen, ulong exp, slong prec) Sets *res* to *{f, flen}* raised to the power *exp*. Does not support aliasing of the input and output, and requires that *flen* is positive. .. function:: void acb_poly_pow_ui(acb_poly_t res, const acb_poly_t poly, ulong exp, slong prec) Sets *res* to *poly* raised to the power *exp*. .. function:: void _acb_poly_pow_series(acb_ptr h, acb_srcptr f, slong flen, acb_srcptr g, slong glen, slong len, slong prec) Sets *{h, len}* to the power series `f(x)^{g(x)} = \exp(g(x) \log f(x))` truncated to length *len*. This function detects special cases such as *g* being an exact small integer or `\pm 1/2`, and computes such powers more efficiently. This function does not support aliasing of the output with either of the input operands. It requires that all lengths are positive, and assumes that *flen* and *glen* do not exceed *len*. .. function:: void acb_poly_pow_series(acb_poly_t h, const acb_poly_t f, const acb_poly_t g, slong len, slong prec) Sets *h* to the power series `f(x)^{g(x)} = \exp(g(x) \log f(x))` truncated to length *len*. This function detects special cases such as *g* being an exact small integer or `\pm 1/2`, and computes such powers more efficiently. .. function:: void _acb_poly_pow_acb_series(acb_ptr h, acb_srcptr f, slong flen, const acb_t g, slong len, slong prec) Sets *{h, len}* to the power series `f(x)^g = \exp(g \log f(x))` truncated to length *len*. This function detects special cases such as *g* being an exact small integer or `\pm 1/2`, and computes such powers more efficiently. This function does not support aliasing of the output with either of the input operands. It requires that all lengths are positive, and assumes that *flen* does not exceed *len*. .. function:: void acb_poly_pow_acb_series(acb_poly_t h, const acb_poly_t f, const acb_t g, slong len, slong prec) Sets *h* to the power series `f(x)^g = \exp(g \log f(x))` truncated to length *len*. .. function:: void _acb_poly_sqrt_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sqrt_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) Sets *g* to the power series square root of *h*, truncated to length *n*. Uses division-free Newton iteration for the reciprocal square root, followed by a multiplication. The underscore method does not support aliasing of the input and output arrays. It requires that *hlen* and *n* are greater than zero. .. function:: void _acb_poly_rsqrt_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_rsqrt_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) Sets *g* to the reciprocal power series square root of *h*, truncated to length *n*. Uses division-free Newton iteration. The underscore method does not support aliasing of the input and output arrays. It requires that *hlen* and *n* are greater than zero. .. function:: void _acb_poly_log_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec) .. function:: void acb_poly_log_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) Sets *res* to the power series logarithm of *f*, truncated to length *n*. Uses the formula `\log(f(x)) = \int f'(x) / f(x) dx`, adding the logarithm of the constant term in *f* as the constant of integration. The underscore method supports aliasing of the input and output arrays. It requires that *flen* and *n* are greater than zero. .. function:: void _acb_poly_log1p_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec) .. function:: void acb_poly_log1p_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) Computes the power series `\log(1+f)`, with better accuracy when the constant term of *f* is small. .. function:: void _acb_poly_atan_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec) .. function:: void acb_poly_atan_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) Sets *res* the power series inverse tangent of *f*, truncated to length *n*. Uses the formula .. math:: \tan^{-1}(f(x)) = \int f'(x) / (1+f(x)^2) dx, adding the function of the constant term in *f* as the constant of integration. The underscore method supports aliasing of the input and output arrays. It requires that *flen* and *n* are greater than zero. .. function:: void _acb_poly_exp_series_basecase(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_exp_series_basecase(acb_poly_t f, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_exp_series(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_exp_series(acb_poly_t f, const acb_poly_t h, slong n, slong prec) Sets `f` to the power series exponential of `h`, truncated to length `n`. The basecase version uses a simple recurrence for the coefficients, requiring `O(nm)` operations where `m` is the length of `h`. The main implementation uses Newton iteration, starting from a small number of terms given by the basecase algorithm. The complexity is `O(M(n))`. Redundant operations in the Newton iteration are avoided by using the scheme described in [HZ2004]_. The underscore methods support aliasing and allow the input to be shorter than the output, but require the lengths to be nonzero. .. function:: void _acb_poly_exp_pi_i_series(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_exp_pi_i_series(acb_poly_t f, const acb_poly_t h, slong n, slong prec) Sets *f* to the power series `\exp(\pi i h)` truncated to length *n*. The underscore method supports aliasing and allows the input to be shorter than the output, but requires the lengths to be nonzero. .. function:: void _acb_poly_sin_cos_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) void acb_poly_sin_cos_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) Sets *s* and *c* to the power series sine and cosine of *h*, computed simultaneously. The underscore method supports aliasing and requires the lengths to be nonzero. .. function:: void _acb_poly_sin_series(acb_ptr s, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sin_series(acb_poly_t s, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_cos_series(acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_cos_series(acb_poly_t c, const acb_poly_t h, slong n, slong prec) Respectively evaluates the power series sine or cosine. These functions simply wrap :func:`_acb_poly_sin_cos_series`. The underscore methods support aliasing and require the lengths to be nonzero. .. function:: void _acb_poly_tan_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) .. function:: void acb_poly_tan_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) Sets *g* to the power series tangent of *h*. For small *n* takes the quotient of the sine and cosine as computed using the basecase algorithm. For large *n*, uses Newton iteration to invert the inverse tangent series. The complexity is `O(M(n))`. The underscore version does not support aliasing, and requires the lengths to be nonzero. .. function:: void _acb_poly_sin_cos_pi_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sin_cos_pi_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_sin_pi_series(acb_ptr s, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sin_pi_series(acb_poly_t s, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_cos_pi_series(acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_cos_pi_series(acb_poly_t c, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_cot_pi_series(acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_cot_pi_series(acb_poly_t c, const acb_poly_t h, slong n, slong prec) Compute the respective trigonometric functions of the input multiplied by `\pi`. .. function:: void _acb_poly_sinh_cosh_series_basecase(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sinh_cosh_series_basecase(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_sinh_cosh_series_exponential(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sinh_cosh_series_exponential(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_sinh_cosh_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sinh_cosh_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_sinh_series(acb_ptr s, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sinh_series(acb_poly_t s, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_cosh_series(acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_cosh_series(acb_poly_t c, const acb_poly_t h, slong n, slong prec) Sets *s* and *c* respectively to the hyperbolic sine and cosine of the power series *h*, truncated to length *n*. The implementations mirror those for sine and cosine, except that the *exponential* version computes both functions using the exponential function instead of the hyperbolic tangent. .. function:: void _acb_poly_sinc_series(acb_ptr s, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_sinc_series(acb_poly_t s, const acb_poly_t h, slong n, slong prec) Sets *s* to the sinc function of the power series *h*, truncated to length *n*. Lambert W function ------------------------------------------------------------------------------- .. function:: void _acb_poly_lambertw_series(acb_ptr res, acb_srcptr z, slong zlen, const fmpz_t k, int flags, slong len, slong prec) .. function:: void acb_poly_lambertw_series(acb_poly_t res, const acb_poly_t z, const fmpz_t k, int flags, slong len, slong prec) Sets *res* to branch *k* of the Lambert W function of the power series *z*. The argument *flags* is reserved for future use. The underscore method allows aliasing, but assumes that the lengths are nonzero. Gamma function ------------------------------------------------------------------------------- .. function:: void _acb_poly_gamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_gamma_series(acb_poly_t res, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_rgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_rgamma_series(acb_poly_t res, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_lgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_lgamma_series(acb_poly_t res, const acb_poly_t h, slong n, slong prec) .. function:: void _acb_poly_digamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong n, slong prec) .. function:: void acb_poly_digamma_series(acb_poly_t res, const acb_poly_t h, slong n, slong prec) Sets *res* to the series expansion of `\Gamma(h(x))`, `1/\Gamma(h(x))`, or `\log \Gamma(h(x))`, `\psi(h(x))`, truncated to length *n*. These functions first generate the Taylor series at the constant term of *h*, and then call :func:`_acb_poly_compose_series`. The Taylor coefficients are generated using Stirling's series. The underscore methods support aliasing of the input and output arrays, and require that *hlen* and *n* are greater than zero. .. function:: void _acb_poly_rising_ui_series(acb_ptr res, acb_srcptr f, slong flen, ulong r, slong trunc, slong prec) .. function:: void acb_poly_rising_ui_series(acb_poly_t res, const acb_poly_t f, ulong r, slong trunc, slong prec) Sets *res* to the rising factorial `(f) (f+1) (f+2) \cdots (f+r-1)`, truncated to length *trunc*. The underscore method assumes that *flen*, *r* and *trunc* are at least 1, and does not support aliasing. Uses binary splitting. Power sums ------------------------------------------------------------------------------- .. function:: void _acb_poly_powsum_series_naive(acb_ptr z, const acb_t s, const acb_t a, const acb_t q, slong n, slong len, slong prec) .. function:: void _acb_poly_powsum_series_naive_threaded(acb_ptr z, const acb_t s, const acb_t a, const acb_t q, slong n, slong len, slong prec) Computes .. math:: z = S(s,a,n) = \sum_{k=0}^{n-1} \frac{q^k}{(k+a)^{s+t}} as a power series in `t` truncated to length *len*. This function evaluates the sum naively term by term. The *threaded* version splits the computation over the number of threads returned by *flint_get_num_threads()*. .. function:: void _acb_poly_powsum_one_series_sieved(acb_ptr z, const acb_t s, slong n, slong len, slong prec) Computes .. math:: z = S(s,1,n) \sum_{k=1}^n \frac{1}{k^{s+t}} as a power series in `t` truncated to length *len*. This function stores a table of powers that have already been calculated, computing `(ij)^r` as `i^r j^r` whenever `k = ij` is composite. As a further optimization, it groups all even `k` and evaluates the sum as a polynomial in `2^{-(s+t)}`. This scheme requires about `n / \log n` powers, `n / 2` multiplications, and temporary storage of `n / 6` power series. Due to the extra power series multiplications, it is only faster than the naive algorithm when *len* is small. Zeta function ------------------------------------------------------------------------------- .. function:: void _acb_poly_zeta_em_choose_param(mag_t bound, ulong * N, ulong * M, const acb_t s, const acb_t a, slong d, slong target, slong prec) Chooses *N* and *M* for Euler-Maclaurin summation of the Hurwitz zeta function, using a default algorithm. .. function:: void _acb_poly_zeta_em_bound1(mag_t bound, const acb_t s, const acb_t a, slong N, slong M, slong d, slong wp) .. function:: void _acb_poly_zeta_em_bound(arb_ptr vec, const acb_t s, const acb_t a, ulong N, ulong M, slong d, slong wp) Compute bounds for Euler-Maclaurin evaluation of the Hurwitz zeta function or its power series, using the formulas in [Joh2013]_. .. function:: void _acb_poly_zeta_em_tail_naive(acb_ptr z, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong len, slong prec) .. function:: void _acb_poly_zeta_em_tail_bsplit(acb_ptr z, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong len, slong prec) Evaluates the tail in the Euler-Maclaurin sum for the Hurwitz zeta function, respectively using the naive recurrence and binary splitting. .. function:: void _acb_poly_zeta_em_sum(acb_ptr z, const acb_t s, const acb_t a, int deflate, ulong N, ulong M, slong d, slong prec) Evaluates the truncated Euler-Maclaurin sum of order `N, M` for the length-*d* truncated Taylor series of the Hurwitz zeta function `\zeta(s,a)` at `s`, using a working precision of *prec* bits. With `a = 1`, this gives the usual Riemann zeta function. If *deflate* is nonzero, `\zeta(s,a) - 1/(s-1)` is evaluated (which permits series expansion at `s = 1`). .. function:: void _acb_poly_zeta_cpx_series(acb_ptr z, const acb_t s, const acb_t a, int deflate, slong d, slong prec) Computes the series expansion of `\zeta(s+x,a)` (or `\zeta(s+x,a) - 1/(s+x-1)` if *deflate* is nonzero) to order *d*. This function wraps :func:`_acb_poly_zeta_em_sum`, automatically choosing default values for `N, M` using :func:`_acb_poly_zeta_em_choose_param` to target an absolute truncation error of `2^{-\operatorname{prec}}`. .. function:: void _acb_poly_zeta_series(acb_ptr res, acb_srcptr h, slong hlen, const acb_t a, int deflate, slong len, slong prec) .. function:: void acb_poly_zeta_series(acb_poly_t res, const acb_poly_t f, const acb_t a, int deflate, slong n, slong prec) Sets *res* to the Hurwitz zeta function `\zeta(s,a)` where `s` a power series and `a` is a constant, truncated to length *n*. To evaluate the usual Riemann zeta function, set `a = 1`. If *deflate* is nonzero, evaluates `\zeta(s,a) + 1/(1-s)`, which is well-defined as a limit when the constant term of `s` is 1. In particular, expanding `\zeta(s,a) + 1/(1-s)` with `s = 1+x` gives the Stieltjes constants .. math:: \sum_{k=0}^{n-1} \frac{(-1)^k}{k!} \gamma_k(a) x^k`. If `a = 1`, this implementation uses the reflection formula if the midpoint of the constant term of `s` is negative. Other special functions ------------------------------------------------------------------------------- .. function:: void _acb_poly_polylog_cpx_small(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec) .. function:: void _acb_poly_polylog_cpx_zeta(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec) .. function:: void _acb_poly_polylog_cpx(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec) Sets *w* to the Taylor series with respect to *x* of the polylogarithm `\operatorname{Li}_{s+x}(z)`, where *s* and *z* are given complex constants. The output is computed to length *len* which must be positive. Aliasing between *w* and *s* or *z* is not permitted. The *small* version uses the standard power series expansion with respect to *z*, convergent when `|z| < 1`. The *zeta* version evaluates the polylogarithm as a sum of two Hurwitz zeta functions. The default version automatically delegates to the *small* version when *z* is close to zero, and the *zeta* version otherwise. For further details, see :ref:`algorithms_polylogarithms`. .. function:: void _acb_poly_polylog_series(acb_ptr w, acb_srcptr s, slong slen, const acb_t z, slong len, slong prec) .. function:: void acb_poly_polylog_series(acb_poly_t w, const acb_poly_t s, const acb_t z, slong len, slong prec) Sets *w* to the polylogarithm `\operatorname{Li}_{s}(z)` where *s* is a given power series, truncating the output to length *len*. The underscore method requires all lengths to be positive and supports aliasing between all inputs and outputs. .. function:: void _acb_poly_erf_series(acb_ptr res, acb_srcptr z, slong zlen, slong n, slong prec) .. function:: void acb_poly_erf_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec) Sets *res* to the error function of the power series *z*, truncated to length *n*. These methods are provided for backwards compatibility. See :func:`acb_hypgeom_erf_series`, :func:`acb_hypgeom_erfc_series`, :func:`acb_hypgeom_erfi_series`. .. function:: void _acb_poly_agm1_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_poly_agm1_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec) Sets *res* to the arithmetic-geometric mean of 1 and the power series *z*, truncated to length *n*. See the :ref:`acb_elliptic.h ` module for power series of elliptic functions. The following wrappers are available for backwards compatibility. .. function:: void _acb_poly_elliptic_k_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) .. function:: void acb_poly_elliptic_k_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec) .. function:: void _acb_poly_elliptic_p_series(acb_ptr res, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec) .. function:: void acb_poly_elliptic_p_series(acb_poly_t res, const acb_poly_t z, const acb_t tau, slong n, slong prec) Root-finding ------------------------------------------------------------------------------- .. function:: void _acb_poly_root_bound_fujiwara(mag_t bound, acb_srcptr poly, slong len) .. function:: void acb_poly_root_bound_fujiwara(mag_t bound, acb_poly_t poly) Sets *bound* to an upper bound for the magnitude of all the complex roots of *poly*. Uses Fujiwara's bound .. math:: 2 \max \left\{\left|\frac{a_{n-1}}{a_n}\right|, \left|\frac{a_{n-2}}{a_n}\right|^{1/2}, \cdots, \left|\frac{a_1}{a_n}\right|^{1/(n-1)}, \left|\frac{a_0}{2a_n}\right|^{1/n} \right\} where `a_0, \ldots, a_n` are the coefficients of *poly*. .. function:: void _acb_poly_root_inclusion(acb_t r, const acb_t m, acb_srcptr poly, acb_srcptr polyder, slong len, slong prec) Given any complex number `m`, and a nonconstant polynomial `f` and its derivative `f'`, sets *r* to a complex interval centered on `m` that is guaranteed to contain at least one root of `f`. Such an interval is obtained by taking a ball of radius `|f(m)/f'(m)| n` where `n` is the degree of `f`. Proof: assume that the distance to the nearest root exceeds `r = |f(m)/f'(m)| n`. Then .. math:: \left|\frac{f'(m)}{f(m)}\right| = \left|\sum_i \frac{1}{m-\zeta_i}\right| \le \sum_i \frac{1}{|m-\zeta_i|} < \frac{n}{r} = \left|\frac{f'(m)}{f(m)}\right| which is a contradiction (see [Kob2010]_). .. function:: slong _acb_poly_validate_roots(acb_ptr roots, acb_srcptr poly, slong len, slong prec) Given a list of approximate roots of the input polynomial, this function sets a rigorous bounding interval for each root, and determines which roots are isolated from all the other roots. It then rearranges the list of roots so that the isolated roots are at the front of the list, and returns the count of isolated roots. If the return value equals the degree of the polynomial, then all roots have been found. If the return value is smaller, all the remaining output intervals are guaranteed to contain roots, but it is possible that not all of the polynomial's roots are contained among them. .. function:: void _acb_poly_refine_roots_durand_kerner(acb_ptr roots, acb_srcptr poly, slong len, slong prec) Refines the given roots simultaneously using a single iteration of the Durand-Kerner method. The radius of each root is set to an approximation of the correction, giving a rough estimate of its error (not a rigorous bound). .. function:: slong _acb_poly_find_roots(acb_ptr roots, acb_srcptr poly, acb_srcptr initial, slong len, slong maxiter, slong prec) .. function:: slong acb_poly_find_roots(acb_ptr roots, const acb_poly_t poly, acb_srcptr initial, slong maxiter, slong prec) Attempts to compute all the roots of the given nonzero polynomial *poly* using a working precision of *prec* bits. If *n* denotes the degree of *poly*, the function writes *n* approximate roots with rigorous error bounds to the preallocated array *roots*, and returns the number of roots that are isolated. If the return value equals the degree of the polynomial, then all roots have been found. If the return value is smaller, all the output intervals are guaranteed to contain roots, but it is possible that not all of the polynomial's roots are contained among them. The roots are computed numerically by performing several steps with the Durand-Kerner method and terminating if the estimated accuracy of the roots approaches the working precision or if the number of steps exceeds *maxiter*, which can be set to zero in order to use a default value. Finally, the approximate roots are validated rigorously. Initial values for the iteration can be provided as the array *initial*. If *initial* is set to *NULL*, default values `(0.4+0.9i)^k` are used. The polynomial is assumed to be squarefree. If there are repeated roots, the iteration is likely to find them (with low numerical accuracy), but the error bounds will not converge as the precision increases. .. function:: int _acb_poly_validate_real_roots(acb_srcptr roots, acb_srcptr poly, slong len, slong prec) .. function:: int acb_poly_validate_real_roots(acb_srcptr roots, const acb_poly_t poly, slong prec) Given a strictly real polynomial *poly* (of length *len*) and isolating intervals for all its complex roots, determines if all the real roots are separated from the non-real roots. If this function returns nonzero, every root enclosure that touches the real axis (as tested by applying :func:`arb_contains_zero` to the imaginary part) corresponds to a real root (its imaginary part can be set to zero), and every other root enclosure corresponds to a non-real root (with known sign for the imaginary part). If this function returns zero, then the signs of the imaginary parts are not known for certain, based on the accuracy of the inputs and the working precision *prec*. flint-3.1.3/doc/source/acb_theta.rst000066400000000000000000002753771461254215100173710ustar00rootroot00000000000000.. _acb-theta: **acb_theta.h** -- Riemann theta functions =============================================================================== This module provides methods for the numerical evaluation of theta functions in any dimension `g\geq 1`. The algorithms will be detailed in the forthcoming paper [EK2023]_. In the case `g=1`, we rely on, but also improve on functionality from :ref:`acb_modular.h `. In the context of this module, *tau* or `\tau` always denotes an element of the Siegel upper half-space `\mathbb{H}_g`, which consists of all symmetric `g\times g` complex matrices with positive definite imaginary part. The letter `z` denotes an element of `\mathbb{C}^g`. For each `a,b\in \{0,1\}^g`, the Riemann theta function of characteristic `(a,b)` is the following analytic function in `\tau\in \mathbb{H}_g` and `z\in \mathbb{C}^g`: .. math:: \theta_{a,b}(z,\tau) = \sum_{n\in \mathbb{Z}^{g} + \tfrac a2} \exp(\pi i n^T\tau n + 2\pi i n^T (z + \tfrac b2)), considering `a`, `b` and `z` as column vectors. We encode a theta characteristic `a\in \{0,1\}^g` as the :type:`ulong` between `0` and `2^g-1` that has the corresponding expansion in base 2: thus `a = (1,0,0)` for `g = 3` will be numbered `8`. We also use this encoding to order vectors of theta values throughout. Similarly, a pair of characteristics `(a,b)` is encoded as an :type:`ulong` between `0` and `2^{2g}-1`, where `a` corresponds to the `g` more significant bits. With these conventions, the output of :func:`acb_modular_theta` is `(-\theta_3,\theta_2,\theta_0,\theta_1)`. The main user-facing function to evaluate theta functions is :func:`acb_theta_all`. This function first reduces the input `(z,\tau)` using the action of the Siegel modular group `\mathrm{Sp}_{2g}(\mathbb{Z})` on `\mathbb{C}^g\times \mathbb{H}_g`, then uses a quasi-linear algorithm to compute theta values on the reduced domain. At low precisions and when `\tau` is reasonably reduced, one may also consider using "naive algorithms" directly, which consist in evaluating a partial sum of the theta series. The main functions to do so are :func:`acb_theta_naive_fixed_ab` and :func:`acb_theta_naive_all`. We also provide functionality to evaluate derivatives of theta functions, and to evaluate Siegel modular forms in terms of theta functions when `g=2`. The numerical functions in this module compute certified error bounds: for instance, if `\tau` is represented by an :type:`acb_mat_t` which is not certainly positive definite at the chosen working precision, the output will have an infinite radius. Throughout, `g` must be at least 1 (this is not checked.) Main user functions ------------------------------------------------------------------------------- .. function:: void acb_theta_all(acb_ptr th, acb_srcptr z, const acb_mat_t tau, int sqr, slong prec) Sets *th* to the vector of theta values `\theta_{a,b}(z,\tau)` or `\theta_{a,b}(z,\tau)^2` for all `a,b\in \{0,1\}^g`, depending on whether *sqr* is 0 (false) or nonzero (true). .. function:: void acb_theta_naive_fixed_ab(acb_ptr th, ulong ab, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) .. function:: void acb_theta_naive_all(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) Assuming that *zs* is the concatenation of *nb* vectors `z` of length `g`, evaluates `\theta_{a,b}(z, \tau)` using the naive algorithm, for either the given value of `(a,b)` or all `(a,b)\in\{0,1\}^{2g}`. The result *th* will be a concatenation of *nb* vectors of length `1` or `2^{2g}` respectively. The user should ensure that `\tau` is reasonably reduced before calling these functions. .. function:: void acb_theta_jet_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) Sets *dth* to the partial derivatives with respect to `z` up to total order *ord* of all functions `\theta_{a,b}` for `a,b\in \{0,1\}^g` at the given point `(z,\tau)`, as a concatenation of `2^{2g}` vectors. (See below for conventions on the numbering and normalization of derivatives.) .. function:: void acb_theta_jet_naive_fixed_ab(acb_ptr dth, ulong ab, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) .. function:: void acb_theta_jet_naive_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) Sets *dth* to the partial derivatives with respect to `z` up to total order *ord* of `\theta_{a,b}` for the given (resp. all) `(a,b)\in \{0,1\}^g` at the given point `(z,\tau)` using the naive algorithm. The user should ensure that `\tau` is reasonably reduced before calling these functions. Example of usage ------------------------------------------------------------------------------- The following code snippet constructs the period matrix `\tau = iI_2` for `g = 2`, computes the associated theta values at `z = 0` at 10000 bits of precision in roughly 0.1s, and prints them. .. code-block:: c #include "acb_theta.h" int main() { acb_mat_t tau; acb_ptr th, z; slong prec = 10000; acb_mat_init(tau, 2, 2); z = _acb_vec_init(2); th = _acb_vec_init(16); acb_mat_onei(tau); acb_theta_all(th, z, tau, 0, prec); _acb_vec_printd(th, 16, 5); acb_mat_clear(tau); _acb_vec_clear(z, 2); _acb_vec_clear(th, 16); flint_cleanup(); return 0; } :: (1.1803 + 0j) +/- (2.23e-3010, 1.23e-3010j), (0.99254 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0.99254 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0.83463 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0.99254 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0 + 0j) +/- (1.23e-3010, 1.23e-3010j), (0.83463 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0 + 0j) +/- (1.23e-3010, 1.23e-3010j), (0.99254 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0.83463 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0 + 0j) +/- (1.23e-3010, 1.23e-3010j), (0 + 0j) +/- (1.23e-3010, 1.23e-3010j), (0.83463 + 0j) +/- (1.73e-3010, 1.23e-3010j), (0 + 0j) +/- (1.23e-3010, 1.23e-3010j), (0 + 0j) +/- (1.23e-3010, 1.23e-3010j), (0 + 0j) +/- (1.23e-3010, 1.23e-3010j) The Siegel modular group ------------------------------------------------------------------------------- We use the type :type:`fmpz_mat_t` to handle matrices in `\operatorname{Sp}_{2g}(\mathbb{Z})`. In addition to the functions in this section, methods from :ref:`fmpz_mat.h ` such as :func:`fmpz_mat_equal` can thus be used on symplectic matrices directly. In the following functions (with the exception of :func:`sp2gz_is_correct`) we always assume that the input matrix *mat* is square of even size `2g`, and write it as .. math:: m = \begin{pmatrix} \alpha&\beta\\ \gamma&\delta \end{pmatrix} where `\alpha,\beta,\gamma,\delta` are `g\times g` blocks. .. function:: slong sp2gz_dim(const fmpz_mat_t mat) Returns `g`, which is half the number of rows (or columns) of *mat*. This is an inline function only. .. function:: void sp2gz_set_blocks(fmpz_mat_t mat, const fmpz_mat_t alpha, const fmpz_mat_t beta, const fmpz_mat_t gamma, const fmpz_mat_t delta) Sets *mat* to `\bigl(\begin{smallmatrix} \alpha&\beta\\ \gamma&\delta \end{smallmatrix}\bigr)`. The dimensions must match. .. function:: void sp2gz_j(fmpz_mat_t mat) Sets *mat* to the symplectic matrix `J = \Bigl(\begin{smallmatrix} 0&I_g\\-I_g&0 \end{smallmatrix}\Bigr)`. .. function:: void sp2gz_block_diag(fmpz_mat_t mat, const fmpz_mat_t U) Sets *mat* to the symplectic matrix `\Bigl(\begin{smallmatrix} U&0\\0&U^{-T} \end{smallmatrix}\Bigr)`. We require that `U\in \operatorname{GL}_g(\mathbb{Z})`. .. function:: void sp2gz_trig(fmpz_mat_t mat, const fmpz_mat_t S) Sets *mat* to `\Bigl(\begin{smallmatrix} I_g&S\\0&I_g \end{smallmatrix}\Bigr)`, where *S* is a symmetric `g\times g` matrix. .. function:: void sp2gz_embed(fmpz_mat_t res, const fmpz_mat_t mat) Assuming that *mat* is a symplectic matrix of size `2r\times 2r` and *res* is square of size `2g\times 2g` for some `g\geq r`, sets *res* to the symplectic matrix .. math:: \begin{pmatrix} \alpha && \beta & \\ & I_{g-r} && 0_{g-r} \\ \gamma &&\delta &\\ & 0_{g-r} && I_{g-r} \end{pmatrix} where `\alpha,\beta,\gamma,\delta` are the `r\times r` blocks of *mat*. .. function:: void sp2gz_restrict(fmpz_mat_t res, const fmpz_mat_t mat) Assuming that *mat* is a symplectic matrix of size `2g\times 2g` and *res* is square of size `2r\times 2r` for some `r\leq g`, sets *res* to the matrix whose `r\times r` blocks are the upper left corners of the corresponding `g\times g` block of *mat*. The result may not be a symplectic matrix. .. function:: slong sp2gz_nb_fundamental(slong g) Returns the number of fundamental symplectic matrices used in the reduction algorithm on `\mathbb{H}_g`. This number is 1 when `g=1` (the `J` matrix) and 19 when `g=2` [Got1959]_. When `g>2`, a complete set of matrices defining the boundary of a fundamental domain for the action of `\mathrm{Sp}_{2g}(\mathbb{Z})` is not currently known. As a substitute, we consider two types of matrices: the `19 g(g-1)/2` matrices obtained by mimicking the `g=2` matrices on any pair of indices between 0 and `g-1`, and the `2^g` matrices obtained by embedding a copy of a lower-dimensional `J` matrix on any subset of indices. .. function:: void sp2gz_fundamental(fmpz_mat_t mat, slong j) Sets *mat* to the `j^{\text{th}}` fundamental symplectic matrix as defined above. .. function:: int sp2gz_is_correct(const fmpz_mat_t mat) Returns true (nonzero) iff *mat* is a symplectic matrix. .. function:: int sp2gz_is_j(const fmpz_mat_t mat) Returns true (nonzero) iff the symplectic matrix *mat* is the `J` matrix. .. function:: int sp2gz_is_block_diag(const fmpz_mat_t mat) Returns true (nonzero) iff the symplectic matrix *mat* is of block-diagonal form as in :func:`sp2gz_block_diag`. .. function:: int sp2gz_is_trig(const fmpz_mat_t mat) Returns true (nonzero) iff the sympletic matrix *mat* is of trigonal form as in :func:`sp2gz_trig`. .. function:: int sp2gz_is_embedded(fmpz_mat_t res, const fmpz_mat_t mat) Assuming that *mat* is a `2g\times 2g` symplectic matrix and *res* is square of size `2r` for some `r\leq g`, returns true (nonzero) iff *mat* can be obtained as the result of :func:`sp2gz_embed` from a `2r\times 2r` symplectic matrix, and store this matrix in *res*. Otherwise, returns false (0) and leaves *res* undefined. .. function:: void sp2gz_inv(fmpz_mat_t inv, const fmpz_mat_t mat) Sets *inv* to the inverse of the symplectic matrix *mat*. .. function:: fmpz_mat_struct * sp2gz_decompose(slong * nb, const fmpz_mat_t mat) Returns a vector *res* of symplectic matrices and store its length in *nb* such that the following holds: *mat* is the product of the elements of *res* from left to right, and each element of *res* is block-diagonal, trigonal, the `J` matrix, an embedded `J` matrix from a lower dimension, or an embedded matrix from dimension 1. The output vector *res* will need to be freed by the user as follows: .. code-block:: c slong k; for (k = 0; k < *nb; k++) { fmpz_mat_clear(&res[k]); } flint_free(res); .. function:: void sp2gz_randtest(fmpz_mat_t mat, flint_rand_t state, slong bits) Sets *mat* to a random symplectic matrix whose coefficients have length approximately *bits*, obtained as a product of block-diagonal and trigonal symplectic matrices and the `J` matrix. The Siegel half space ------------------------------------------------------------------------------- We continue to denote by `\alpha,\beta,\gamma,\delta` the `g\times g` blocks of *mat*, which is always assumed to be symplectic. .. function:: void acb_siegel_cocycle(acb_mat_t c, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) Sets *c* to `\gamma\tau + \delta`. .. function:: void acb_siegel_transform_cocycle_inv(acb_mat_t w, acb_mat_t c, acb_mat_t cinv, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) Sets *w*, *c* and *cinv* to `(\alpha\tau + \beta)(\gamma\tau + \delta)^{-1}`, `\gamma\tau + \delta` and `(\gamma\tau + \delta)^{-1}` respectively. .. function:: void acb_siegel_transform(acb_mat_t w, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) Sets *w* to `(\alpha\tau + \beta)(\gamma\tau + \delta)^{-1}`. .. function:: void acb_siegel_transform_z(acb_ptr r, acb_mat_t w, const fmpz_mat_t mat, acb_srcptr z, const acb_mat_t tau, slong prec) Sets *w* to `(\alpha\tau + \beta)(\gamma\tau + \delta)^{-1}` and *r* to `(\gamma\tau + \delta)^{-T}z`. .. function:: void acb_siegel_cho(arb_mat_t C, const acb_mat_t tau, slong prec) Sets *C* to an upper-triangular Cholesky matrix such that `\pi \mathrm{Im}(\tau) = C^T C`. If one cannot determine that `\mathrm{Im}(\tau)` is positive definite at the current working precision, *C* is set to an indeterminate matrix. .. function:: void acb_siegel_yinv(arb_mat_t Yinv, const acb_mat_t tau, slong prec) Sets *Yinv* to the inverse of `\mathrm{Im}(\tau)`. If one cannot determine that `\mathrm{Im}(\tau)` is invertible at the current working precision, *Yinv* is set to an indeterminate matrix. .. function:: void acb_siegel_reduce(fmpz_mat_t mat, const acb_mat_t tau, slong prec) Sets *mat* to a symplectic matrix such that `\mathit{mat}\cdot\tau` is as reduced as possible, repeatedly reducing the imaginary and real parts of `\tau` and applying fundamental symplectic matrices. If the coefficients of `\tau` do not have a reasonable size or if `\det \mathrm{Im}(\tau)` is vanishingly small, we simply set *mat* to the identity. .. function:: int acb_siegel_is_reduced(const acb_mat_t tau, slong tol_exp, slong prec) Returns true (nonzero) iff it is certainly true that `\tau` belongs to the reduced domain defined by the tolerance parameter `\varepsilon = 2^{\mathit{tol\_exp}}`. This means the following: `|\mathrm{Re}(\tau_{j,k})| < \frac12 + \varepsilon` for all `0\leq j,k < g`; the imaginary part of `\tau` passes :func:`arb_mat_spd_is_lll_reduced` with the same parameters; and for every matrix obtained from :func:`sp2gz_fundamental`, the determinant of the corresponding cocycle is at least `1-\varepsilon`. .. function:: void acb_siegel_randtest(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits) Sets *tau* to a random matrix in `\mathbb{H}_g`, possibly far from being reduced. .. function:: void acb_siegel_randtest_reduced(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits) Sets *tau* to a random reduced matrix in `\mathbb{H}_g` that is likely to trigger corner cases for several functions in this module. .. function:: void acb_siegel_randtest_vec(acb_ptr z, flint_rand_t state, slong g, slong prec) Sets *z* to a random vector of length *g* that is likely to trigger corner cases for several functions in this module. Theta characteristics ------------------------------------------------------------------------------- .. function:: void acb_theta_char_get_slong(slong * n, ulong a, slong g) Sets each entry of *n* to the corresponding bit of *a*. .. function:: ulong acb_theta_char_get_a(const slong * n, slong g) Returns the unique characteristic *a* such that `n\in 2\mathbb{Z}^g + a`. .. function:: void acb_theta_char_get_arb(arb_ptr v, ulong a, slong g) .. function:: void acb_theta_char_get_acb(acb_ptr v, ulong a, slong g) Sets *v* to `a/2` seen as an element of `\mathbb{R}^g` or `\mathbb{C}^g` respectively. .. function:: slong acb_theta_char_dot(ulong a, ulong b, slong g) Returns `\sum_{i=0}^{g-1} a_i b_i` modulo 4 as an integer between 0 and 3, where `a_i, b_i` for `0\leq i < g` denote the bits of `a` and `b` respectively. .. function:: slong acb_theta_char_dot_slong(ulong a, const slong * n, slong g) Returns `\sum_{i=0}^{g-1} a_i n_i` modulo 4 as an integer between 0 and 3. .. function:: void acb_theta_char_dot_acb(acb_t x, ulong a, acb_srcptr z, slong g, slong prec) Sets *x* to `\sum_{i=0}^{g-1} a_i z_i`. .. function:: int acb_theta_char_is_even(ulong ab, slong g) Returns true iff the characteristic `(a,b)` is even, i.e. `a^Tb` is divisible by 2. .. function:: int acb_theta_char_is_goepel(ulong ch1, ulong ch2, ulong ch3, ulong ch4, slong g) Returns true iff the given characteristics define a Göpel quadruple, i.e. they are distinct even characteristics whose sum belongs to `2\mathbb{Z}^g`. .. function:: int acb_theta_char_is_syzygous(ulong ch1, ulong ch2, ulong ch3, slong g) Returns true iff the given characteristics define a syzygous triple, i.e. they can be completed into a Göpel quadruple. Ellipsoids: types and macros ------------------------------------------------------------------------------- Following [DHBHS2004]_, naive algorithms will compute a partial sum of theta series over points `n` in the lattice `\mathbb{Z}^g` contained in certain ellipsoids, and finally add an error bound coming from the tail. We first gather methods to compute with ellipsoids themselves. Fix an upper-triangular matrix `C` with positive diagonal entries (henceforth called a "Cholesky matrix"), a radius `R\geq 0`, a vector `v\in \mathbb{R}^g`, and `1\leq d\leq g`. Consider the ellipsoid `E` consisting of points `n = (n_0,\ldots,n_{g-1})` satisfying `(v + Cn)^T(v + Cn)\leq R^2` and such that their last coordinates `n_{d},\ldots, n_{g-1}` are fixed. We encode `E` as follows: we store the endpoints and midpoint of the interval of allowed values for `n_{d-1}` as :type:`slong`'s, and if `d\geq 1`, we store a `(d-1)`-dimensional "child" of `E` for each value of `n_{d-1}` as another ellipsoid in a recursive way. Children are partitioned between left and right children depending on the position of `n_{d-1}` relative to the midpoint (by convention, the midpoint is a right child). When `d=g` and for a fixed Cholesky matrix `C`, this representation uses `O(R^{g-1})` space for an ellipsoid of radius `R` containing approximately `O(R^{g})` points. .. type:: acb_theta_eld_struct .. type:: acb_theta_eld_t An :type:`acb_theta_eld_t` is an array of length one of type :type:`acb_theta_eld_struct` encoding an ellipsoid as described above, permitting it to be passed by reference. The following macros are available after *E* of type :type:`acb_theta_eld_t` has been initialized using :func:`acb_theta_eld_init` below. .. macro:: acb_theta_eld_dim(E) Macro returning `d`. .. macro:: acb_theta_eld_ambient_dim(E) Macro returning `g`. The following macros are available after *E* has been initialized and then computed using :func:`acb_theta_eld_set` below. .. macro:: acb_theta_eld_coord(E, k) Macro returning the common coordinate `n_k` of the points in `E`. This requires `d \leq k < g`. .. macro:: acb_theta_eld_min(E) .. macro:: acb_theta_eld_mid(E) .. macro:: acb_theta_eld_max(E) Macros returning the minimum, midpoint, and maximum of `n_{d-1}` in `E` respectively. .. macro:: acb_theta_eld_nr(E) .. macro:: acb_theta_eld_nl(E) Macros returning the number of right and left children of `E` respectively. .. macro:: acb_theta_eld_rchild(E, k) .. macro:: acb_theta_eld_lchild(E, k) Macros returning a pointer to the `k^{\text{th}}` right (resp. left) child of `E` as an :type:`acb_theta_eld_t`. .. macro:: acb_theta_eld_nb_pts(E) Macro returning the number of points contained in `E`. .. macro:: acb_theta_eld_nb_border(E) Macro returning the number of points in the border of `E`, defined as follows. If `d=1`, then it consists of the two points with `n_0` equal to `m - 1` and `M + 1`, where `m` and `M` are the result of :macro:`acb_theta_eld_max` and :macro:`acb_theta_eld_min` respectively. If `d\geq 2`, then it is the reunion of the borders of all children of `E`. This is only used for testing. .. macro:: acb_theta_eld_box(E, k) Macro returning the smallest nonnegative integer `M_k` such that all the points in `E` satisfy `|n_k|\leq M_k`. This requires `0\leq k < d`. Ellipsoids: memory management and computations ------------------------------------------------------------------------------- .. function:: void acb_theta_eld_init(acb_theta_eld_t E, slong d, slong g) Initializes *E* as a *d*-dimensional ellipsoid in ambient dimension *g*. We require `1\leq d\leq g`. .. function:: void acb_theta_eld_clear(acb_theta_eld_t E) Clears *E* as well as any recursive data contained in it. .. function:: int acb_theta_eld_set(acb_theta_eld_t E, const arb_mat_t C, const arf_t R2, arb_srcptr v) Assuming that *C* is upper-triangular with positive diagonal entries, attempts to set *E* to represent an ellipsoid as defined above, where *R2* indicates `R^2`, and returns 1 upon success. If the ellipsoid points do not fit in :type:`slong`'s or if the ellipsoid is unreasonably large, returns 0 instead and leaves *E* undefined. The following functions are available after :func:`acb_theta_eld_set` has been called successfully. .. function:: void acb_theta_eld_points(slong * pts, const acb_theta_eld_t E) Sets *pts* to the list of all the points in `E`, as a concatenation of vectors of length *g*. .. function:: void acb_theta_eld_border(slong * pts, const acb_theta_eld_t E) Sets *pts* to the list of all the points in the border of `E`. .. function:: int acb_theta_eld_contains(const acb_theta_eld_t E, slong * pt) Returns true (nonzero) iff *pt* is contained in `E`. The vector *pt* must be of length *g*. .. function:: void acb_theta_eld_print(const acb_theta_eld_t E) Prints a faithful description of `E`. This may be unwieldy in high dimensions. Naive algorithms: error bounds ------------------------------------------------------------------------------- By [EK2023]_, for any `v\in \mathbb{R}^g` and any upper-triangular Cholesky matrix `C`, and any `R` such that `R^2 \geq\max(4,\mathit{ord})`, we have .. math:: \sum_{n\in C\mathbb{Z}^g + v,\ \lVert n\rVert^2 \geq R^2} \lVert n\rVert^{\mathit{ord}} e^{-\lVert n\rVert^2} \leq 2^{2g+2} R^{g-1+p} e^{-R^2} \prod_{j=0}^{g-1} (1 + \gamma_j^{-1}) where `\gamma_0,\ldots, \gamma_{g-1}` are the diagonal coefficients of `C`. We use this to bound the contribution from the tail of the theta series in naive algorithms, and thus to find out which ellipsoid to consider at a given precision. When several vectors `z` are present, we first reduce them to a common compact domain and use only one ellipsoid, following [DHBHS2004]_. .. function:: void acb_theta_naive_radius(arf_t R2, arf_t eps, const arb_mat_t C, slong ord, slong prec) Sets *R2* and *eps* such that the above upper bound for *R2* and the given *ord* is at most *eps*. We choose *eps* so that the relative error on the output of the naive algorithm should be roughly `2^{-\mathit{prec}}` if no cancellations occur in the sum, i.e. `\mathit{eps} \simeq 2^{-\mathit{prec}} \prod_{j=0}^{g-1} (1 + \gamma_j^{-1})`. .. function:: void acb_theta_naive_reduce(arb_ptr v, acb_ptr new_zs, arb_ptr as, acb_ptr cs, arb_ptr us, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) Given *zs*, a concatenation of *nb* vectors of length `g`, performs the simultaneous reduction of these vectors with respect to the matrix `\tau`. This means the following. Let `0\leq k< \mathit{nb}`, let `z` denote the `k^{\mathrm{th}}` vector stored in *zs*, and let `X,Y` (resp. `x,y`) be the real and imaginary parts of `\tau` (resp. `z`). Write `Y^{-1}y = r + a` where `a` is an even integral vector and `r` is bounded. (We set `a=0` instead if the entries of this vector have an unreasonably large magnitude.) Then .. math:: \begin{aligned} \theta_{0,b}(z,\tau) &= e^{\pi y^T Y^{-1} y} \sum_{n\in \mathbb{Z}^g} e^{\pi i ((n - a)^T X (n - a) + 2(n - a)^T (x + \tfrac b2))} e^{-\pi (n + r)^T Y (n + r)}\\ &= e^{\pi y^T Y^{-1} y} e^{\pi i (a^T X a - 2a^T x + i r^T Y r)} \theta_{0,b}((x - Xa) + iYr, \tau). \end{aligned} The reduction of `z` is defined as `(x - Xa) + i Y r`, which has a bounded imaginary part, and this vector is stored as the `k^{\mathrm{th}}` vector of *new_zs*. The vector `a` is stored as the `k^{\mathrm{th}}` vector of *as*. The quantity `u = \exp(\pi y^T Y^{-1} y)` is a multiplicative factor for the error bound, and is stored as the `k^{\mathrm{th}}` entry of *us*. The quantity .. math:: c = u \exp(\pi i (a^T X a - 2a^T x + i r^T Y r)) is a multiplicative factor for the theta values, and is stored as the `k^{\mathrm{th}}` entry of *cs*. The offset for the corresponding ellipsoid is `v^{(k)} = C r` which is also bounded independently of `k`, and *v* is set to the :func:`acb_union` of the `v^{(k)}` for `0\leq k< \mathit{nb}`. .. function:: void acb_theta_naive_term(acb_t res, acb_srcptr z, const acb_mat_t tau, slong * tup, slong * n, slong prec) Sets *res* to `n_0^{k_0} \cdots n_{g-1}^{k_{g-1}}\exp(\pi i(n^T\tau n + 2 n^Tz))`, where the `k_j` and `n_j` denotes the `j^{\mathrm{th}}` entry in *tup* and *n* respectively. The vector *tup* may be *NULL*, which is understood to mean the zero tuple. This is only used for testing. Naive algorithms: main functions ------------------------------------------------------------------------------- The main worker inside each version of the naive algorithm will process one line inside the computed ellipsoid. Before calling this worker, for fixed `\tau` and `z` and fixed coordinates `n_1,\ldots n_{g-1}` defining a line inside the ellipsoid, if `n_{\mathrm{min}}` are `n_{\mathrm{max}}` are the endpoints of the interval of allowed values for `n_0`, we (efficiently) compute: - the vector `v_1` with entries `\exp(\pi i j^2 \tau_{0,0})` for `n_{\mathrm{min}}\leq j\leq n_{\mathrm{max}}`, - the vector `v_2` with entries `x^j` for `n_{\mathrm{min}}\leq j\leq n_{\mathrm{max}}`, where .. math:: x = \exp(2 \pi i z_0) \prod_{k = 1}^{g-1} \exp(2 \pi i n_k \tau_{0,k}), - the cofactor `c\in \mathbb{C}` given by .. math:: c = \prod_{k = 1}^{g-1} \exp(2 \pi i n_k z_k) \cdot \prod_{1\leq j\leq k < g} \exp(\pi i (2 - \delta_{j,k}) n_j n_k \tau_{j,k}). This allow us to use :func:`acb_dot` in the workers while maintaining reasonable memory costs, and to use an average of strictly less than two complex multiplications per lattice point as `R\to \infty`. Moreover, these multiplications are performed at only a fraction of the full precision for lattice points far from the ellipsoid center. Different versions of the naive algorithm will rely on slightly different workers, so introducing a function pointer type is helpful to avoid code duplication. The methods in this section are only used when `g\geq 2`: when `g=1`, the naive algorithms will call functions from :ref:`acb_modular.h ` directly. .. type:: acb_theta_naive_worker_t A function pointer type. A function *worker* of this type has the following signature: .. function:: void worker(acb_ptr th, acb_srcptr v1, acb_srcptr v2, const slong * precs, slong len, const acb_t c, const slong * coords, slong ord, slong g, slong prec, slong fullprec) where: - *th* denotes the output vector of theta values to which terms will be added, - *v1*, *v2* and *c* are precomputed as above, - *precs* contains working precisions for each term `n_{\mathrm{min}}\leq j\leq n_{\mathrm{max}}`, - *len* `= n_{\mathrm{max}} - n_{\mathrm{min}} + 1` is the common length of *v1*, *v2* and *precs*, - *coords* is `(n_{\mathrm{min}}, n_1, \ldots, n_{g-1})`, - *ord* is the maximal derivation order, - *prec* is the working precision for this line inside the ellipsoid, and finally - *fullprec* is the working precision for summing into *th*. .. function:: void acb_theta_naive_worker(acb_ptr th, slong len, acb_srcptr zs, slong nb, const acb_mat_t tau, const acb_theta_eld_t E, slong ord, slong prec, acb_theta_naive_worker_t worker) Runs the naive algorithm by calling *worker* on each line in the ellipsoid *E*. The argument *zs* is a concatenation of *nb* vectors `z\in \mathbb{C}^g`, *len* is the number of theta values computed by *worker* for each `z`, and *ord* is passed as an argument to *worker*. No error bound coming from the tail is added. Considering several vectors `z` at the same time allows for a faster computation of `\theta_{a,b}(z,\tau)` for many values of `z` and a fixed `\tau`, since exponentials of the entries of `\tau` can be computed only once. .. function:: void acb_theta_naive_00(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) .. function:: void acb_theta_naive_0b(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) Evaluates either `\theta_{0,0}(z^{(k)}, \tau)`, or alternatively `\theta_{0,b}(z^{(k)}, \tau)` for each `b\in \{0,1\}^g`, for each `0\leq k < \mathit{nb}`. The result *th* will be a concatenation of *nb* vectors of length `1` or `2^g` respectively. The associated worker performs one :func:`acb_dot` operation. .. function:: void acb_theta_naive_fixed_a(acb_ptr th, ulong a, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) Evaluates `\theta_{a,b}(z^{(k)}, \tau)` for all `(a,b)` where `b\in \{0,1\}^g` and `a` is fixed, for each `0\leq k< \mathit{nb}`. The result *th* will be a concatenation of *nb* vectors of length `2^g`. We reduce to calling :func:`acb_theta_naive_0b` by writing .. math:: \theta_{a,b}(z,\tau) = \exp(\pi i \tfrac{a^T}{2} \tau \tfrac a2) \exp(\pi i a^T(z + \tfrac b 2)) \theta_{0,b}(z + \tau \tfrac{a}{2}, \tau). We proceed similarly in :func:`acb_theta_naive_fixed_ab` and :func:`acb_theta_naive_all`, using :func:`acb_theta_naive_00` for the former. Naive algorithms for derivatives ------------------------------------------------------------------------------- This section contains methods to evaluate the successive partial derivatives of `\theta_{a,b}(z,\tau)` with respect to the `g` coordinates of `z`. Derivatives with respect to `\tau` are accounted for by the heat equation .. math:: \frac{\partial\theta_{a,b}}{\partial \tau_{j,k}} = \frac{1}{2\pi i(1 +\delta_{j,k})} \frac{\partial^2\theta_{a,b}}{\partial z_j \partial z_k}. We encode tuples of derivation orders, henceforth called "derivation tuples", as vectors of type :type:`slong` and length `g`. In agreement with :ref:`acb_modular.h `, we also normalize derivatives in the same way as in the Taylor expansion, so that the tuple `(k_0,\ldots,k_{g-1})` corresponds to the differential operator .. math:: \frac{1}{k_0!}\cdots\frac{1}{k_{g-1}!} \cdot \frac{\partial^{|k|}}{\partial z_0^{k_0}\cdots \partial z_{g-1}^{k_{g-1}}}, where `|k|:=\sum k_i`. We always consider all derivation tuples up to a total order *ord*, and order them first by their total order, then reverse-lexicographically. For example, in the case `g=2`, the sequence of orders is `(0,0)`, `(1,0)`, `(0,1)`, `(2,0)`, `(1,1)`, etc. The naive algorithms for derivatives will evaluate a partial sum of the differentiated series: .. math:: \frac{\partial^{|k|}\theta_{a,b}}{\partial z_0^{k_0}\cdots \partial z_{g-1}^{k_{g-1}}}(z,\tau) = (2\pi i)^{|k|} \sum_{n\in \mathbb{Z}^g + \tfrac a2} n_0^{k_0} \cdots n_{g-1}^{k_{g-1}} e^{\pi i n^T \tau n + 2\pi i n^T (z + \tfrac b2)}. .. function:: slong acb_theta_jet_nb(slong ord, slong g) Returns the number of derivation tuples with total order at most *ord*. The result will be zero if *ord* is negative. .. function:: slong acb_theta_jet_total_order(const slong * tup, slong g) Returns the total derivation order for the given tuple *tup* of length *g*. .. function:: void acb_theta_jet_tuples(slong * tups, slong ord, slong g) Sets *tups* to the concatenation of all derivation tuples up to total order *ord*. .. function:: slong acb_theta_jet_index(const slong * tup, slong g) Returns *n* such that *tup* is the `n^{\mathrm{th}}` derivation tuple of length *g*. .. function:: void acb_theta_jet_mul(acb_ptr res, acb_srcptr v1, acb_srcptr v2, slong ord, slong g, slong prec) Sets *res* to the vector of derivatives of the product `fg`, assuming that *v1* and *v2* contains the derivatives of `f` and `g` respectively. .. function:: void acb_theta_jet_compose(acb_ptr res, acb_srcptr v, const acb_mat_t N, slong ord, slong prec) Sets *res* to the vector of derivatives of the composition `f(Nz)`, assuming that *v* contains the derivatives of *f* at the point `Nz`. .. function:: void acb_theta_jet_exp_pi_i(acb_ptr res, arb_srcptr a, slong ord, slong g, slong prec) Sets *res* to the vector of derivatives of the function `\exp(\pi i (a_0 z_1 + \cdots + a_{g-1} z_{g-1}))` at `z = 0`, where `a_0,\ldots a_{g-1}` are the entries of *a*. .. function:: void acb_theta_jet_naive_radius(arf_t R2, arf_t eps, arb_srcptr v, const arb_mat_t C, slong ord, slong prec) Assuming that *C* is the upper-triangular Cholesky matrix for `\pi Y` and `v = C Y^{-1} y` where `y, Y` are the imaginary parts of `z` and `\tau` respectively, returns *R2* and *eps* so that, when summing the above series on terms `n\in \mathbb{Z}^g` such that `(v + C n)^T(v + C n)\leq R^2`, the absolute value of the tail of the series (before multiplying by the leading factor `(2\pi i)^{|k|} e^{\pi y^T Y^{-1} y}`, see below) will be bounded above by *eps*, for any derivation tuple `k` with `|k|\leq \mathit{ord}`. We can rewrite the above sum as .. math:: (2\pi i)^{|k|} e^{\pi y^T Y^{-1} y} \sum_{n\in \mathbb{Z}^g + \tfrac a2} n_0^{k_0} \cdots n_{g-1}^{k_{g-1}} e^{\pi i(\cdots)} e^{-\pi (n + Y^{-1}y)^T Y (n + Y^{-1}y)}. We ignore the leading multiplicative factor. Writing `m = C n + v`, we have .. math:: n_0^{k_0}\cdots n_{g-1}^{k_{g-1}}\leq (\lVert C^{-1}\rVert_\infty \lVert n\rVert_2 + \lVert Y^{-1}y\rVert_\infty)^{|k|}. Using the upper bound from :func:`acb_theta_naive_radius`, we see that the absolute value of the tail of the series is bounded above by .. math:: (\lVert C^{-1} \rVert_\infty R + \lVert Y^{-1}y \rVert_\infty)^{|k|} 2^{2g+2} R^{g-1} e^{-R^2} \prod_{j=0}^{g-1} (1 + \gamma_j^{-1}). Thus, we proceed as follows. We first compute *R2* and *eps* using :func:`acb_theta_naive_radius` with *ord* = 0. If `R\leq \lVert Y^{-1}y\rVert_\infty/\lVert C^{-1}\rVert_\infty`, we simply multiply *eps* by `\max\{1, 2 \lVert Y^{-1}y \rVert\}^{\mathit{ord}}`. Otherwise, we compute *R2* and *eps* using :func:`acb_theta_naive_radius` with the given value of *ord*. We can then set *R2* to the maximum of *R2* and `\lVert Y^{-1}y \rVert_\infty /\lVert C^{-1} \rVert_\infty`, and multiply *eps* by `\max\{1, 2\lVert C^{-1}\rVert\}^{\mathit{ord}}`. .. function:: void acb_theta_jet_naive_00(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) Sets *dth* to the vector of derivatives of `\theta_{0,0}` at the given point `(z,\tau)` up to total order *ord*. In :func:`acb_theta_jet_naive_fixed_ab`, we reduce to this function using the same formula as in :func:`acb_theta_naive_fixed_ab`, making suitable linear combinations of the derivatives. In :func:`acb_theta_jet_naive_all`, we instead use an ellipsoid to encode points in `\tfrac 12 \mathbb{Z}^g`, and divide `\tau` by 4 and `z` by 2 to sum the correct terms. The bounds output by :func:`acb_theta_jet_naive_radius` are still valid, since this just has the effect of multiplying `\lVert C^{-1} \rVert` and each `\gamma_j^{-1}` by `2`. .. function:: void acb_theta_jet_error_bounds(arb_ptr err, acb_srcptr z, const acb_mat_t tau, acb_srcptr dth, slong ord, slong prec) Assuming that *dth* contains the derivatives of a function `\theta_{a,b}` up to total order `\mathit{ord} + 2`, sets *err* to a vector with the following property. Let `(z_0,\tau_0)` be the midpoint of `(z,\tau)`, and let `(z_1,\tau_1)` be any point inside the ball specified by the given *z* and *tau*. Then the vectors of derivatives of `\theta_{a,b}` at `(z_0,\tau_0)` and `(z_1,\tau_1)` up to total order *ord* differ by at most *err* elementwise. Quasi-linear algorithms: presentation ------------------------------------------------------------------------------- We refer to [EK2023]_ for a detailed description of the quasi-linear algorithm implemented here. In a nutshell, the algorithm relies on the following duplication formula: for all `z,z'\in \mathbb{C}^g` and `\tau\in \mathbb{H}_g`, .. math:: \theta_{a,0}(z,\tau) \theta_{a,0}(z',\tau) = \sum_{a'\in(\mathbb{Z}/2\mathbb{Z})^g} \theta_{a',0}(z+z',2\tau) \theta_{a+a',0}(z-z',2\tau). In particular, .. math:: \begin{aligned} \theta_{a,0}(z,\tau)^2 &= \sum_{a'\in (\mathbb{Z}/2\mathbb{Z})^g} \theta_{a',0}(2z,2\tau) \theta_{a+a',0}(0,2\tau),\\ \theta_{a,0}(0,\tau)\theta_{a,0}(z,\tau) &= \sum_{a'\in(\mathbb{Z}/2\mathbb{Z})^g} \theta_{a',0}(z,2\tau) \theta_{a+a',0}(z,2\tau), \\ \theta_{a,0}(0,\tau)^2 &= \sum_{a'\in (\mathbb{Z}/2\mathbb{Z})^g} \theta_{a',0}(0,2\tau) \theta_{a+a',0}(0,2\tau). \end{aligned} Applying one of these duplication formulas amounts to taking a step in a (generalized) AGM sequence. These formulas also have analogues for all theta values, not just `\theta_{a,0}`: for instance, we have .. math:: \theta_{a,b}(0,\tau)^2 = \sum_{a'\in (\mathbb{Z}/2\mathbb{Z})^g} (-1)^{a'^Tb} \theta_{a',0}(0,2\tau)\theta_{a+a',0}(0,2\tau). Suppose that we wish to compute `\theta_{a,0}(0,\tau)` for all `a\in \{0,1\}^g` and a reduced matrix `\tau\in \mathbb{H}_g`. Applying the last formula `n` times, we reduce to evaluating `\theta_{a,0}(0,2^n\tau)`. We expect that the absolute value of this complex number is roughly `\exp(-d^2)` for `d = 2^n\mathrm{Dist}_\tau(0, \mathbb{Z}^g + \tfrac a2))`, where `\mathrm{Dist}_\tau` denotes the distance in `\mathbb{R}^g` attached to the quadratic form `\mathrm{Im}(\tau)`. Provided that `n \simeq \log_2(\mathit{prec})`, we have to sum only `O_g(1)` terms in the naive algorithm to evaluate `\theta_{a,0}(0,2^n\tau)` at "shifted absolute precision" *prec*, i.e. absolute precision `\mathit{prec} + d^2/\log(2)`. In order to recover `\theta_{a,0}(0,\tau)`, we then perform `n` AGM steps. Assuming that each `|\theta_{a,0}(0, 2^k\tau)|` is indeed of the expected order of magnitude, we can ensure that the precision loss is `O_g(1)` bits at each step in terms of shifted absolute precision, and we can calculate the correct sign choices of square roots at each step with the naive algorithm. However, depending on the choice of `\tau`, this assumption may not always hold. We make the following adjustments to make the algorithm work for all `\tau`, as well as for theta values at `z\neq 0`: - If we discover (after applying the naive algorithm) that some value `\theta_{a,0}(0,2^k\tau)` is too small, we introduce an auxiliary real vector `t`. At each step, starting from `\theta_{a,0}(0,2^{k+1}\tau)`, `\theta_{a,0}(2^{k+1}t, 2^{k+1}\tau)` and `\theta_{a,0}(2^{k+2}t, 2^{k+1}\tau)`, we compute `\theta_{a,0}(2^{k}t, 2^k\tau)` and `\theta_{a,0}(2^{k+1}t, 2^k\tau)` using square roots (second formula above), then `\theta_{a,0}(0, 2^k\tau)` using divisions (third formula). For a huge majority of such `t`, none of the values `\theta_{a,0}(2^kt, 2^k\tau)` and `\theta_{a,0}(2^{k+1}t, 2^k\tau)` will be too small [EK2023]_. In practice, we choose `t` at random and obtain a probabilistic algorithm with a negligible failure probability. - When computing `\theta_{a,0}(z,\tau)` for a nonzero `z`, we compute `\theta_{a,0}(0, 2^k\tau)` and `\theta_{a,0}(2^k z, 2^k\tau)` using the second and fourth formulas at each step. We actually replace each occurrence of `\theta_{a,0}(z,\tau)` by `e^{-\pi y^T Y^{-1} y}\theta_{a,0}(z,\tau)`, as the absolute values of the latter quantities do not increase as `y` gets farther from zero, and they still satisfy the duplication formulas. - These two techniques can be combined by evaluating theta values at the six vectors `2^k v` for `v = 0, t, 2t, z, z + t, z + 2t`. Note that we only have to compute `\theta_{a,0}(2^kz, 2^k\tau)` at the last step `k=0`. - Finally, if the eigenvalues of `\mathrm{Im}(\tau)` have different orders of magnitude, then the ellipsoid we have to sum on for the naive algorithm will become very thin in one direction while still being thick in other directions. In such a case, we can split the total sum and compute `O(1)` theta values in a lower dimension. This increases the efficiency of the algorithm while ensuring that the absolute precisions we consider are always in `O(\mathit{prec})`. Quasi-linear algorithms: distances ------------------------------------------------------------------------------- .. function:: void acb_theta_dist_pt(arb_t d, arb_srcptr v, const arb_mat_t C, slong * n, slong prec) Sets *d* to `\lVert v + Cn\rVert^2` for the usual Euclidean norm. .. function:: void acb_theta_dist_lat(arb_t d, arb_srcptr v, const arb_mat_t C, slong prec) Sets *d* to `\mathrm{Dist}(v, C \mathbb{Z}^g)^2` for the usual Euclidean norm. We first compute an upper bound on the result by considering the `2^g` vectors obtained by rounding the entries of `C^{-1}v` to integers up or down, then compute an ellipsoid to find the minimum distance. .. function:: void acb_theta_dist_a0(arb_ptr d, acb_srcptr z, const acb_mat_t tau, slong prec) Sets *d* to the vector containing `\mathrm{Dist}(C \cdot(Y^{-1}y + \tfrac a2), C\cdot \mathbb{Z}^g)^2` for `a\in \{0,1\}^g`, where `y, Y` are the imaginary parts of `z, \tau` respectively and `C` is the upper-triangular Cholesky matrix for `\pi Y`. The `a^{\mathrm{th}}` entry of *d* is also `\mathrm{Dist}_\tau(-Y^{-1}y, \mathbb{Z}^g + \tfrac a2)^2`, where `\mathrm{Dist}_\tau` denotes the distance attached to the quadratic form `\mathrm{Im}(\tau)`. .. function:: slong acb_theta_dist_addprec(const arb_t d) Returns an integer that is close to *d* divided by `\log(2)` if *d* is finite and of reasonable size, and otherwise returns 0. Quasi-linear algorithms: AGM steps ------------------------------------------------------------------------------- .. function:: void acb_theta_agm_hadamard(acb_ptr res, acb_srcptr a, slong g, slong prec) Sets *res* to the product of the Hadamard matrix `\bigl(\begin{smallmatrix} 1 & 1 \\ 1 & -1\end{smallmatrix}\bigr)^{\otimes g}` and the vector `a`. Both *res* and `a` must be vectors of length `2^g`. In other words, for each `k\in \{0,1\}^g`, this sets the `k^{\mathrm{th}}` entry of *res* to `\sum_{j\in \{0,1\}^g} (-1)^{k^T j} a_j`. .. function:: void acb_theta_agm_sqrt(acb_ptr res, acb_srcptr a, acb_srcptr rts, slong nb, slong prec) Sets the `k^{\mathrm{th}}` entry `r_k` of *res* for `0\leq k < \mathit{nb}` to a square root of the corresponding entry `a_k` of `a`. The choice of sign is determined by *rts*: each `r_k` will overlap the corresponding entry of *rts* but not its opposite. Exceptional cases are handled as follows: if both square roots of `a_k` overlap *rts*, then `r_k` is set to their :func:`acb_union`; if none ovelaps *rts*, then `r_k` is set to an indeterminate value. .. function:: void acb_theta_agm_mul(acb_ptr res, acb_srcptr a1, acb_srcptr a2, slong g, slong prec) For each `0\leq k < 2^g`, sets the `k^{\mathrm{th}}` entry of *res* to `2^{-g}\sum_{b\in \{0,1\}^g} a_{1,b}\, a_{2, b + k}`, where addition is meant in `(\mathbb{Z}/2\mathbb{Z}^g)` (a bitwise xor). Following [LT2016]_, we apply the Hadamard matrix twice with multiplications in-between. This causes precision losses when the absolute values of the entries of *a1* and/or *a2* are of different orders of magnitude. This function is faster when *a1* and *a2* are equal as pointers, as we can use squarings instead of multiplications. .. function:: void acb_theta_agm_mul_tight(acb_ptr res, acb_srcptr a0, acb_srcptr a, arb_srcptr d0, arb_srcptr d, slong g, slong prec) Assuming that *d0* and *d* are obtained as the result of :func:`acb_theta_dist_a0` on `(0,\tau)` and `(z,\tau)` respectively, performs the same computation as :func:`acb_theta_agm_mul` on the vectors *a0* and *a* with a different management of error bounds. The resulting error bounds on *res* will be tighter when the absolute value of `a_k` is roughly `e^{-d_k}` for each `0\leq k < 2^g`, and similarly for *a0* and *d0*. When `g>1`, we manage the error bounds as follows. We compute `m, \varepsilon` such that the following holds: for each `0\leq k < \mathit{nb}`, if `d_k` (resp. `a_k`) denotes the `k^{\mathrm{th}}` entry of *d* (resp. *a*), then the absolute value of `a_k` is at most `m \cdot e^{-d_k}` and the radius of the complex ball `a_k` is at most `\mathit{eps}\cdot e^{-d_k}`. We proceed similarly on *a0* and *d0* to obtain `m_0, \varepsilon_0`. Then we call :func:`acb_theta_agm_mul` on the midpoints of *a0* and *a* at a higher working precision, and finally add `e^{-d_k} (m_0 \varepsilon + m \varepsilon_0 + \varepsilon\varepsilon_0)` to the error bound on the `k^\mathrm{th}` entry of *res*. This is valid for the following reason: keeping notation from :func:`acb_theta_dist_a0`, for each `b\in \{0,1\}^g`, the sum .. math:: \mathrm{Dist}_\tau(-Y^{-1}y, \mathbb{Z}^g + \tfrac b2)^2 + \mathrm{Dist}_\tau(-Y^{-1} y, \mathbb{Z}^g + \tfrac{b + k}{2})^2 is at most `\mathrm{Dist}_\tau(-Y^{-1}y, \mathbb{Z}^g + \tfrac{k}{2})^2` by the parallelogram identity. Quasi-linear algorithms: main functions ------------------------------------------------------------------------------- The functions in this section will work best when `\tau` lies in the reduced domain, however `\mathrm{Im}(\tau)` may have large eigenvalues. .. type:: acb_theta_ql_worker_t A function pointer type. A function *worker* of this type has the following signature: .. function:: int worker(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_scptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec) Such a worker will attempt to set *th* to the values `\theta_{a,0}(v,\tau)` for `v = 0,t,2t,z,z+t,z+2t` and `a\in \{0,1\}^g` at shifted absolute precision *prec*, and return `1` on success and `0` on failure. The vectors *d0* and *d* must contain the result of :func:`acb_theta_dist_a0` on `(0,\tau)` and `(z,\tau)`. If `z = 0`, `t = 0`, or both, we only compute `3`, `2`, or `1` vectors of `2^g` values respectively. Two functions of this type are available: :func:`acb_theta_ql_a0_naive` and the main function :func:`acb_theta_ql_a0`. Using function pointers allows us to write independent test code for the main workhorses :func:`acb_theta_ql_a0_steps` and :func:`acb_theta_ql_a0_split` below. .. function:: int acb_theta_ql_a0_naive(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec) Follows the specifications of a function of type :type:`acb_theta_ql_worker_t` using the naive algorithm only. The return value is `1` iff the output vector *th* contains finite values. .. function:: int acb_theta_ql_a0_split(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d, const acb_mat_t tau, slong s, slong guard, slong prec, acb_theta_ql_worker_t worker) Follows the specifications of a function of type :type:`acb_theta_ql_worker_t`, except for the additional arguments *s* and *worker*. We split the theta series according to the first `s` coordinates of `n\in \mathbb{Z}^g`, writing `n = (n_0,n_1)` where `n_0\in \mathbb{Z}^s` and `n_1\in \mathbb{Z}^{g - s}`. We must have `1\leq s\leq g -1`. Then *worker* is called to evaluate the sum corresponding to each `n_1`. The return value is 1 iff all the calls to *worker* succeed. For each `0\leq a < 2^g`, we compute *R2* and *eps* as in :func:`acb_theta_naive_radius` at shifted absolte precision *prec*. Note that `n^T \mathrm{Im}(\tau) n\geq \lVert C_1 n_1\rVert^2`, where `C_1` denotes the lower-right block of `C` of dimensions `(g-s)\times(g-s)`. Thus, in order to compute `\theta_{a,0}(z, 2^n\tau)` at shifted absolute precision *prec*, it is enough to consider those `n_1\in \mathbb{Z}^{g - s}` in an ellipsoid `E_1` of radius *R2* for the Cholesky matrix `C_1`. This ellipsoid is meant to contain very few points, and we list all of them. Then, for a given choice of `n_1`, the sum of the corresponding terms in the theta series is .. math:: e^{\pi i \bigl((n_1 + \tfrac{a_1}{2})\tau_1 (n_1 + \tfrac{a_1}{2}) + 2 (n_1 + \tfrac{a_1}{2}) z_1\bigr)} \theta_{a_0,0}(z_0 + x (n_1 + \tfrac{a_1}{2}), \tau_0). where `\tau = \Bigl(\begin{smallmatrix} \tau_0 & x\\x^T & \tau_1\end{smallmatrix}\Bigr)` and `z = (z_0,z_1)`. When calling *worker*, we adjust the shifted absolute precision according to the distance between `n_1` and the center of `E_1`. .. function:: int acb_theta_ql_a0_steps(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong nb_steps, slong s, slong guard, slong prec, acb_theta_ql_worker_t worker) Follows the specifications of a function of type :type:`acb_theta_ql_worker_t`, except for the additional arguments *nb_steps*, *s* and *worker*. We first compute low-precision approximations (more precisely, at shifted absolute precision *guard*) of the square roots we must take to perform *nb_steps* AGM steps; we hope that none of these approximations contains zero. Then we call :func:`acb_theta_ql_a0_naive` or :func:`acb_theta_ql_a0_split` (with the given *worker*) depending on whether *s* is zero or not, and finally perform the AGM steps. The return value is 1 iff each subprocedure succeeds. The user should ensure that the eigenvalues of `2^{\mathit{nb\_steps}}\mathrm{Im}(\tau)` are not too large when calling this function. .. function:: slong acb_theta_ql_a0_nb_steps(const arb_mat_t C, slong s, slong prec) Returns an integer `n` such that `2^n \gamma_s^2 \simeq \mathit{prec}` where `\gamma_0,\ldots,\gamma_{g-1}` denote the diagonal coefficients of `C`. This `n` is meant to be the number of AGM steps to use in :func:`acb_theta_ql_a0_steps`, and its precise value is chosen to optimize performance. We require `0\leq s < g`. .. function:: int acb_theta_ql_a0(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec) Follows the specifications of a function of type :type:`acb_theta_ql_worker_t`. We first decide how many AGM steps we should use and whether we should use the splitting strategy. Then we run :func:`acb_theta_ql_a0_steps` on the midpoints of `t,z` and `\tau` at a slightly higher precision to account for precision losses in the duplication formulas, using a recursive call to :func:`acb_theta_ql_a0` as *worker*. If the return value is 1, we finally compute provable error bounds on the result using :func:`acb_theta_jet_naive_fixed_ab` and :func:`acb_theta_jet_error_bounds`. The function :func:`acb_theta_ql_a0` may fail for an unlucky choice of auxiliary vector `t` or when *guard* is too small. Thus, we implement a probabilistic algorithm where we gradually increase *guard* and first choose `t = 0`, then make a random choice of `t` at each step. .. function:: slong acb_theta_ql_reduce(acb_ptr new_z, acb_t c, arb_t u, slong * n1, acb_srcptr z, const acb_mat_t tau, slong prec) Sets *new_z*, *c*, *u*, *n1* and returns `-1\leq s\leq g` such that the following holds. If `s\geq 0` is returned, then `z'` = *new_z* is a vector of length `s` and `n_1` is a vector of length `g-s`, and for each characteristic `(a,b)`, we have (borrowing notation from :func:`acb_theta_ql_a0_split`): either .. math:: |\theta_{a,b}(z,\tau) - c i^{\,n_1^Tb_1} \theta_{a_0,b_0}(z', \tau_0)| \leq u when the last `g-s` coordinates of `a` equal `n_1` modulo 2, or .. math:: |\theta_{a,b}(z,\tau)|\leq u otherwise. If `s=-1` is returned, then *n1*, *c* and *new_z* are left undefined and we have `\theta_{a,b}(z,\tau)\leq u` for all characteristics `(a,b)`. This filters out very large eigenvalues of `\mathrm{Im}(\tau)` that have a negligible impact on theta values but would give rise to unreasonable choices of precisions in the final duplication formula for computing all theta values `\theta_{a,b}`. This works as follows. We first compute *R2* and *eps* as in :func:`acb_theta_naive_radius`, then set *c*, *u* and *new_z* as in :func:`acb_theta_naive_reduce` in dimension `g`. We then set `s` such that the ellipsoid `E` of radius `R^2` that we are interested in is either empty or contains points whose `g-s` last coordinates are fixed. In the former case, we return `s = -1`. Now assume that `E` is not empty, let `n_1` be the vector of these fixed last `g-s` coordinates, and let `a_1\in \{0,1\}^{g-s}` be the corresponding characteristic. We can then write the sum defining `\theta_{a,b}` over `E` as .. math:: e^{\pi i (\tfrac{n_1^T}{2} \tau_1 \tfrac{n_1}{2} + n_1^T(z_1 + \tfrac{b_1}{2}))} \sum_{n_0\in E_0 \cap (\mathbb{Z}^s + \tfrac{a_0}{2})} e^{\pi i (n_0^T \tau_0 n_0 + 2n_0^T(z_0 + x \tfrac{n_1}{2} + \tfrac{b_0}{2}))} if the last `g-s` coordinates of `a` are equal to `n_1` modulo 2; the sum is zero otherwise. Thus we can set `z'` to `z_0 + x\tfrac{n_1}{2}` and multiply `c` by `\exp(\pi i (\tfrac{n_1^T}{2}\tau_1\tfrac{n_1}{2} + n_1^Tz_1))`. .. function:: void acb_theta_ql_all(acb_ptr th, acb_srcptr z, const acb_mat_t tau, int sqr, slong prec) Sets *th* to the collection of `\theta_{a,b}(z,\tau)` or `\theta_{a,b}(z,\tau)^2` for all `a,b\in \{0,1\}^g`, depending on whether *sqr* is 0 (false) or nonzero (true). After calling :func:`acb_theta_ql_reduce`, we generally use the duplication formula on the result of :func:`acb_theta_ql_a0` at `2\tau`. When *sqr* is zero, we add a final square-root step. Quasi-linear algorithms: derivatives ------------------------------------------------------------------------------- We implement an algorithm for derivatives of theta functions on the reduced domain based on finite differences. Consider the Taylor expansion: .. math:: \theta_{a,b}(z + h, \tau) = \sum_{k\in \mathbb{Z}^g,\ k\geq 0} a_k\, h_0^{k_0}\cdots h_{g-1}^{k_{g-1}}. If one chooses `h = h_n = (\varepsilon \zeta^{n_0},\ldots, \varepsilon \zeta^{n_{g-1}})` where `\varepsilon > 0` and `\zeta` is a primitive `m^{\mathrm{th}}` root of unity and lets `n` run through all vectors in `\{0,\ldots, m - 1\}^g`, then taking a discrete Fourier transform of the resulting values will compute the individual Taylor coefficient for each derivation tuple that is bounded by `m-1` elementwise. A constant proportion, for fixed `g`, of this set consists of all tuples of total order at most `m-1`. More precisely, fix `p\in \mathbb{Z}^g`. Then .. math:: \sum_{n\in \{0,\ldots,m-1\}^g} \zeta^{-p^T n} \theta_{a,b}(z + h_n, \tau) = m^g \sum_{\substack{k\in \mathbb{Z}^g,\ k\geq 0,\\ k = p\ (\text{mod } m)}} a_k\,\varepsilon^{|k|}. We obtain an upper bound on the tail of this series from the Cauchy integration formula: if `|\theta_{a,b}(z,\tau)|\leq c` uniformly on a ball of radius `\rho` centered in `z` for `\lVert\cdot\rVert_\infty`, then the sum is `m^g (a_p\,\varepsilon^{|p|} + T)` with .. math:: |T|\leq 2c g\,\frac{\varepsilon^{|p|+m}}{\rho^m}. Since we divide by `\varepsilon^{|p|}` to get `a_p`, we will add an error of `2c g \varepsilon^m/\rho^{m+|p|}` to the result of the discrete Fourier transform. .. function:: void acb_theta_jet_ql_bounds(arb_t c, arb_t rho, acb_srcptr z, const acb_mat_t tau, slong ord) Sets *c* and *rho* such that on every ball centered at (a point contained in) *z* of radius *rho*, the functions `|\theta_{a,b}|` for all characteristics `(a,b)` are uniformly bounded by `c`. The choice of *rho* is tuned to get interesting upper bounds on derivatives of `\theta_{a,b}` up to order *ord*. We proceed as follows. First, we compute `c_0`, `c_1`, `c_2` such that for any choice of `\rho`, one can take `c = c_0\exp((c_1 + c_2\rho)^2)` above. We can take .. math:: c_0 = 2^g \prod_{j=0}^{g-1} (1 + 2\gamma_j^{-1}), .. math:: c_1 = \sqrt{\pi y^T Y^{-1} y}, .. math:: c_2 = \sup_{\lVert x \rVert_\infty\leq 1} \sqrt{\pi x^T \mathrm{Im}(\tau)^{-1} x}. One can easily compute an upper bound on `c_2` from the Cholesky decomposition of `\pi \mathrm{Im}(\tau)^{-1}`. We then look for a value of `\rho` that minimizes `\exp((c_1 + c_2\rho)^2)/\rho^{2m-1}` where `m = \mathit{ord}+1`, i.e. we set `\rho` to the positive root of `2c_2\rho (c_1 + c_2\rho) = 2m-1`. .. function:: void acb_theta_jet_ql_radius(arf_t eps, arf_t err, const arb_t c, const arb_t rho, slong ord, slong g, slong prec) Sets *eps* and *err* to be a suitable radius and error bound for computing derivatives up to total order *ord* at precision *prec*, given *c* and *rho* as above. We set `varepsilon` such that `(2 g)^{1/m} \varepsilon \leq \rho` and `2 c g \varepsilon^m/\rho^{m+|p|} \leq 2^{-\mathit{prec}}` where `m = \mathit{ord} + 1`. We also set *err* to `2^{-\mathit{prec}}`. .. function:: void acb_theta_jet_ql_finite_diff(acb_ptr dth, const arf_t eps, const arf_t err, acb_srcptr val, slong ord, slong g, slong prec) Assuming that *val* contains the values `\theta_{a,b}(z + h_n,\tau)` where `h_n = (\varepsilon \zeta^{n_0},\ldots, \varepsilon \zeta^{n_{g-1}})` for a root of unity `\zeta` of order `\mathit{ord} + 1`, and assuming that *eps* and *err* has been computed as in :func:`acb_theta_jet_ql_radius`, sets *dth* to the vector of partial derivatives of `\theta_{a,b}` at `(z,\tau)` up to total order *ord*. The vector *val* should be indexed in lexicographic order as in :func:`acb_dft`, i.e. writing `j = \overline{a_{g-1}\cdots a_0}` in basis `m`, the `j^{\mathrm{th}}` entry of *val* corresponds to `n = (a_0,\ldots, a_{g-1})`. The output derivatives are normalized as in the Taylor expansion. .. function:: void acb_theta_jet_ql_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) Sets *dth* to the derivatives of all functions `\theta_{a,b}` for `a,b\in \{0,1\}^g` at `(z,\tau)`, as a concatenation of `2^{2g}` vectors of length `N`, the total number of derivation tuples of total order at most *ord*. This algorithm runs in quasi-linear time in `\mathit{prec}\cdot \mathit{ord}^{\,g}` for any fixed `g` provided that `(z,\tau)` is reduced. We first compute *c*, *rho*, *err* and *eps* as above, then compute theta values `\theta_{a,b}(z + h_n,\tau)` at a higher precision at the midpoints of `z` and `\tau` to account for division by `\varepsilon^{\mathit{ord}}\cdot (\mathit{ord}+1)^g`. Finally, we adjust the error bounds using :func:`acb_theta_jet_error_bounds` and the naive algorithm for derivatives of order at most `\mathit{ord} + 2`. The transformation formula ------------------------------------------------------------------------------- The functions in this section implement the theta transformation formula of [Igu1972]_, p. 176 and [Mum1983]_, p. 189: for any symplectic matrix `m`, any `(z,\tau)\in \mathbb{C}^g\times \mathbb{H}_g`, and any characteristic `(a,b)`, we have .. math:: \theta_{a,b}(m\cdot(z,\tau)) = \kappa(m) \zeta_8^{e(m, a, b)} \det(\gamma\tau + \delta)^{1/2} e^{\pi i z^T (\gamma\tau + \delta)^{-1} \gamma z} \theta_{a',b'}(z,\tau) where - `\gamma,\delta` are the lower `g\times g` blocks of `m`, - `a',b'` is another characteristic depending on `m,a,b`, - `\zeta_8=\exp(i\pi/4)`, - `e(m,a,b)` is an integer given by an explicit formula in terms of `m,a,b` (this is `\phi_m` in Igusa's notation), and - `\kappa(m)` is an `8^{\mathrm{th}}` root of unity, only well-defined up to sign unless we choose a particular branch of `\det(\gamma\tau + \delta)^{1/2}` on `\mathbb{H}_g`. .. function:: ulong acb_theta_transform_char(slong * e, const fmpz_mat_t mat, ulong ab) Returns the theta characteristic `(a',b')` and sets *e* to `e(\mathit{mat},a,b)`. .. function:: void acb_theta_transform_sqrtdet(acb_t res, const acb_mat_t tau, slong prec) Sets *res* to `\det(\tau)^{1/2}`, where the branch of the square root is chosen such that the result is `i^{g/2}\det(Y)` when `\tau = iY` is purely imaginary. We pick a purely imaginary matrix *A* and consider the polynomial `P(t) = \det(A + \tfrac{t+1}{2} (\tau - A))`. Up to choosing another `A`, we may assume that it has degree `g` and that its roots (as complex balls) do not intersect the segment `[-1,1]\subset \mathbb{C}`. We then find the correct branch of `P(t)^{1/2}` between `t=-1` and `t=1` following [MN2019]_. .. function:: slong acb_theta_transform_kappa(acb_t sqrtdet, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) Returns `0\leq r < 8` such that `\kappa(m) = \zeta_8^r` and sets *sqrtdet* to the corresponding square root of `\det(\gamma\tau + \delta)`. After applying :func:`sp2gz_decompose`, we only have to consider four special cases for *mat*. If *mat* is trigonal or block-diagonal, one can compute its action on `\theta_{0,0}` directly. If *mat* is an embedded matrix from `\mathrm{SL}_2(\mathbb{Z})`, we rely on :func:`acb_modular_theta_transform`. Finally, if *mat* is an embedded `J` matrix from dimension `0\leq r\leq g`, then `\kappa(m) \zeta_8^{e(m,0,0)} i^{r/2} \det(\tau_0)^{1/2} = 1`, where `\tau_0` denotes the upper left `r\times r` submatrix of `\tau` and the square root is computed as in :func:`acb_theta_transform_sqrtdet`. .. function:: slong acb_theta_transform_kappa2(const fmpz_mat_t mat) Returns `0\leq r < 3` such that `\kappa(m)^2 = i^r`, which makes sense without reference to a branch of `\det(\gamma\tau + \delta)^{1/2}`. We adopt a similar strategy to :func:`acb_theta_transform_kappa` but do not call :func:`acb_theta_transform_sqrtdet`. .. function:: void acb_theta_transform_proj(acb_ptr res, const fmpz_mat_t mat, acb_srcptr th, int sqr, slong prec) Assuming that *sqr* is 0 (false) and that *th* contains `\theta_{a,b}(z,\tau)` for some `(z,\tau)`, sets *res* to contain the values `\theta_{a,b}(\mathit{mat}\cdot (z,\tau))` up to a common scalar factor in `\mathbb{C}^\times`. This only permutes the theta values and multiplies them by a suitable `8^{\mathrm{th}}` root of unity. If *sqr* is nonzero (true), does the same computation for squared theta values `\theta_{a,b}(z,\tau)^2` instead. In :func:`acb_theta_all` and :func:`acb_theta_jet_all`, we first reduce `\tau` using :func:`acb_siegel_reduce`, then call :func:`acb_theta_ql_all`, or :func:`acb_theta_jet_ql_all` on the reduced matrix, and finally apply the transformation formula. If the reduction step is not successful, we set the result to indeterminate values. Dimension 2 specifics ------------------------------------------------------------------------------- In the `g=2` case, one can use theta functions to evaluate many fundamental Siegel modular forms. This section contains methods to do so, in analogy with :func:`acb_modular_delta` or :func:`acb_modular_eisenstein` when `g=1`. We use the following notation. Fix `k,j\geq 0`. A Siegel modular form of weight `\det^k\otimes \mathrm{Sym}^j` is by definition an analytic function `f: \mathbb{H}_g\to \mathbb{C}_j[X]` (the vector space of polynomials of degree at most `j`) such that for any `\tau\in \mathbb{H}_g` and `m\in \mathrm{Sp}_4(\mathbb{Z})`, we have .. math:: f((\alpha\tau + \beta)(\gamma\tau + \delta)^{-1}) = \det(\gamma\tau + \delta)^k\cdot \mathrm{Sym}^j(\gamma\tau + \delta)(f(\tau)). Here `\alpha,\beta,\gamma,\delta` are the `g\times g` blocks of `m`, and the notation `\mathrm{Sym}^j(r)` where `r = \bigl(\begin{smallmatrix} a & b\\ c & d\end{smallmatrix}\bigr)\in \mathrm{GL}_2(\mathbb{C})` stands for the map .. math:: P(X) \mapsto (b X + d)^j P\bigl(\tfrac{a X + c}{b X + d}\bigr). For a nonzero `f` to exist, `j` must be even. Siegel modular forms generate a bi-graded ring which is not finitely generated. However, if we relax the definition of a Siegel modular form and allow them to have a pole along the diagonal `\mathbb{H}_1^2 = \bigl\{\bigl(\begin{smallmatrix} \tau_1 & 0 \\ 0 & \tau_2\end{smallmatrix}\bigr)\bigr\}\subset \mathbb{H}_2` of a certain order (depending on the weight), we indeed find a finitely generated ring corresponding to classical "covariants" of a binary sextic. Historically, covariants are classified in terms of their degree `k` and index `j`, corresponding to Siegel modular functions of weight `\det^{k - j/2}\otimes \mathrm{Sym}^j`. See [CFG2017]_ for more details on the correspondence between modular forms and covariants. .. macro:: ACB_THETA_G2_COV_NB Macro giving the number of generators of the ring of covariants, equal to 26. .. function:: void acb_theta_g2_jet_naive_1(acb_ptr dth, const acb_mat_t tau, slong prec) Sets *dth* in the same way as :func:`acb_theta_jet_naive_all` at order 1 for `z=0`. We take advantage of the fact that the value (resp. gradients) of `\theta_{a,b}(z,\tau)` at `z = 0` vanish if `(a,b)` is an odd (resp. even) characteristic. The attached worker of type :type:`acb_theta_naive_worker_t` uses one of two available strategies (doing multiplications and then summing, or calling :func:`acb_dot` twice) depending on *prec*. .. function:: void acb_theta_g2_detk_symj(acb_poly_t res, const acb_mat_t m, const acb_poly_t f, slong k, slong j, slong prec) Sets *res* to `\det(m)^k \mathrm{Sym}^j(m)(f)`. The polynomial `f` should be of degree at most `j` (any coefficients of larger degree are ignored). .. function:: void acb_theta_g2_transvectant(acb_poly_t res, const acb_poly_t g, const acb_poly_t h, slong m, slong n, slong k, slong prec) Sets *res* to the `k^{\mathrm{th}}` transvectant of the polynomials `g` and `h` of degrees `m` and `n`: considering `g` and `h` as homogeneous polynomials of degree `m` (resp. `n`) in `x_1,x_2`, this sets *res* to .. math:: (g,h)_k := \frac{(m-k)!(n-k)!}{m!n!} \sum_{j=0}^{k} (-1)^{k-j} \binom{k}{j} \frac{\partial^k g}{\partial x_1^{k-j}\partial x_2^j} \frac{\partial^k h}{\partial x_1^{j}\partial x_2^{k-j}}. Any coefficients of `g` or `h` of larger degree than `m` (resp. `n`) are ignored. .. function:: void acb_theta_g2_transvectant_lead(acb_t res, const acb_poly_t g, const acb_poly_t h, slong m, slong n, slong k, slong prec) Sets *res* to the leading coefficient of `(g,h)_k` in `x_1`, with the same conventions as in :func:`acb_theta_g2_transvectant`. .. function:: slong acb_theta_g2_character(const fmpz_mat_t mat) Returns the value in `\mathbb{Z}/2\mathbb{Z}` (0 or 1) of the unique nontrivial character of `\mathrm{Sp}_4(\mathbb{Z})` at *mat*, following [CFG2019]_, §12. .. function:: void acb_theta_g2_psi4(acb_t res, acb_srcptr th2, slong prec) .. function:: void acb_theta_g2_psi6(acb_t res, acb_srcptr th2, slong prec) .. function:: void acb_theta_g2_chi10(acb_t res, acb_srcptr th2, slong prec) .. function:: void acb_theta_g2_chi12(acb_t res, acb_srcptr th2, slong prec) Sets *res* to the value of the Eisenstein series `\psi_4`, `\psi_6` or the cusp forms `\chi_{10}, \chi_{12}` corresponding to the given vector *th2* of squared theta values (of length 16). We use the formulas from §7.1 in [Str2014]_, with the following normalizations: .. math:: \psi_4 = h_4/4, \quad \psi_6 = h_6/4,\quad \chi_{10} = -2^{-12} h_{10}, \quad \chi_{12} = 2^{-15}h_{12}. We warn that `\chi_{10}` and `\chi_{12}` differ from the classical notation of Igusa [Igu1979]_ by scalar factors. Writing `\tau = \bigl(\begin{smallmatrix} \tau_1 & \tau_2 \\ \tau_2 & \tau_3\end{smallmatrix}\bigr)` and `q_j = \exp(2\pi i \tau_j)`, the Fourier expansions of these modular forms begin as follows: .. math:: \begin{aligned} \psi_4(\tau) &= 1 + 240(q_1 + q_3) + \cdots\\ \psi_6(\tau) &= 1 - 504(q_1 + q_3) + \cdots\\ \chi_{10}(\tau) &= (q_2 - 2 + q_2^{-1}) q_1 q_3 + \cdots\\ \chi_{12}(\tau) &= (q_2 + 10 + q_2^{-1}) q_1 q_3 + \cdots. \end{aligned} .. function:: void acb_theta_g2_chi5(acb_t res, acb_srcptr th, slong prec) Sets *res* to the value of `\chi_5 = - 2^{-6} \prod_{(a,b)\text{ even}} \theta_{a,b}` corresponding to the given theta values *th*. The form `\chi_5` is a Siegel cusp form with character: see [CFG2019]_ for more details. .. function:: void acb_theta_g2_chi35(acb_t res, acb_srcptr th, slong prec) Sets *res* to the value of the cusp form `\chi_{35}` corresponding to the vector of theta values *th*. The form `\chi_{35}` is the unique scalar-valued Siegel modular form of weight `\det^{35}\otimes \mathrm{Sym}^0` up to scalars, and is normalized as follows: .. math:: \chi_{35}(\tau) = q_1^2 q_3^2 (q_1 - q_3 )(q_2 - q_2^{-1}) + \cdots An explicit formula for `\chi_{35}` in terms of theta values is given in [Bol1887]_. See also [Mum1984]_, Prop. 6.2 p. 98 for how to translate Bolza's notation in terms of theta characteristics. .. function:: void acb_theta_g2_chi3_6(acb_poly_t res, acb_srcptr dth, slong prec) Sets *res* to the value of the vector-valued cusp form with character `\chi_{6,3}` of weight `\det^3\otimes \mathrm{Sym}^6` corresponding to the given values of *dth*, computed as in e.g. :func:`acb_theta_g2_jet_naive_1`. We have by [CFG2017]_: .. math:: \chi_{3,6}(\tau) = \frac{1}{64\pi^6} \prod_{(a,b) \text{ odd}} \left(\frac{\partial \theta_{a,b}}{\partial z_1}(0,\tau) x_1 + \frac{\partial\theta_{a,b}}{\partial z_2}(0,\tau) x_2\right). .. function:: void acb_theta_g2_sextic(acb_poly_t res, const acb_mat_t tau, slong prec) Sets *res* to the value of `\chi_{-2,6}:=\chi_{3,6}/\chi_5` at `\tau`. We reduce `\tau` to the Siegel fundamental domain and call either :func:`acb_theta_g2_jet_naive_1` or :func:`acb_theta_jet_ql_all` to compute theta gradients, depending on *prec*. Under the correspondence between Siegel modular functions and covariants of binary sextics, `\chi_{-2,6}` corresponds to the binary sextic itself, hence the name. .. function:: void acb_theta_g2_sextic_chi5(acb_poly_t res, acb_t chi5, const acb_mat_t tau, slong prec) Sets *res* and *chi5* to the values of `\chi_{-2,6}` and `\chi_5` at `\tau`. Theta values are computed only once. .. function:: void acb_theta_g2_covariants(acb_poly_struct * res, const acb_poly_t f, slong prec) Sets *res* to the vector of 26 generators of the ring of covariants evaluated at the sextic *f* (any terms of degree `>6` are ignored), in the following order: 0. `C_{1,6}=f` 1. `C_{2,0}= 60(f,f)_6` 2. `C_{2,4}= 75(f,f)_4` 3. `C_{2,8}= 90(f,f)_2` 4. `C_{3,2}= 30(f,C_{2,4})_4` 5. `C_{3,6}= 30(f,C_{2,4})_2` 6. `C_{3,8}= 6(f,C_{2,4})_1` 7. `C_{3,12}= 6 (f,C_{2,8})_1` 8. `C_{4,0}= 2 (C_{2,4},C_{2,4})_4` 9. `C_{4,4}= 30 (f,C_{3,2})_2` 10. `C_{4,6}= 6(f,C_{3,2})_1` 11. `C_{4,10}= 2(C_{2,8},C_{2,4})_1` 12. `C_{5,2}=(C_{2,4},C_{3,2})_2` 13. `C_{5,4}=\frac 25 (C_{2,4},C_{3,2})_1` 14. `C_{5,8}= 2(C_{2,8},C_{3,2})_1` 15. `C_{6,0}= 2(C_{3,2},C_{3,2})_2` 16. `C_{6,6}^{(1)}= \frac 25(C_{3,6},C_{3,2})_1` 17. `C_{6,6}^{(2)}= \frac 83(C_{3,8},C_{3,2})_2` 18. `C_{7,2}= 30(f,C_{3,2}^2)_4` 19. `C_{7,4}= 12(f,C_{3,2}^2)_3` 20. `C_{8,2}= \frac 25(C_{2,4},C_{3,2}^2)_3` 21. `C_{9,4}= 4(C_{3,8},C_{3,2}^2)_4` 22. `C_{10,0}= 20(f,C_{3,2}^3)_6` 23. `C_{10,2}= \frac 65(f,C_{3,2}^3)_5` 24. `C_{12,2}= \frac 85(C_{3,8},C_{3,2}^3)_6` 25. `C_{15,0}= \frac{1}{30000} (C_{3,8},C_{3,2}^4)_8`. The scalar factors are chosen so that when evaluated at a formal sextic `f = \sum a_i x_1^{6-i}x_2^i`, the covariants are integral and primitive as multivariate polynomials in `a_0,\ldots,a_6,x_1,x_2`. .. function:: void acb_theta_g2_covariants_lead(acb_ptr res, const acb_poly_t f, slong prec) Sets *res* to the vector of leading coefficients in `x_1` of the 26 covariants evaluated at *f*. This is more efficient than taking leading coefficients of :func:`acb_theta_g2_covariants`, since we can use :func:`acb_theta_g2_transvectant_lead` instead of :func:`acb_theta_g2_transvectant`. Tests ------------------------------------------------------------------------------- .. code-block:: bash ./build/acb_theta/test/main sp2gz_set_blocks Generates a random `2g\times 2g` matrix, calls :func:`sp2gz_set_blocks` on its four `g\times g` windows, and checks that the result equals the original matrix. .. code-block:: bash ./build/acb_theta/test/main sp2gz_is_correct Checks that the return value of :func:`sp2gz_is_correct` is 1 on matrices generated by :func:`sp2gz_j`, :func:`sp2gz_block_diag`, :func:`sp2gz_trig` and :func:`sp2gz_fundamental`, and 0 on the identity matrix if it is not square of even size. .. code-block:: bash ./build/acb_theta/test/main sp2gz_inv Checks that the result of :func:`sp2gz_inv` agrees with :func:`fmpz_mat_inv` on random input. .. code-block:: bash ./build/acb_theta/test/main sp2gz_decompose Checks that the result of :func:`sp2gz_decompose` on random input only consists of symplectic matrices of the allowed types, and that their product equals the original matrix. .. code-block:: bash ./build/acb_theta/test/main acb_siegel_cocycle Checks that the chain rule holds: if `m'' = m'm` is a product of two symplectic matrices and `\tau\in \mathbb{H}_g`, then `\gamma''\tau + \delta'' = (\gamma'\tau' + \delta')(\gamma\tau+\delta)` where `\tau' = m\tau`. These quantities are computed using :func:`acb_siegel_cocycle` and :func:`acb_siegel_transform`. .. code-block:: bash ./build/acb_theta/test/main acb_siegel_transform Checks that the chain rule holds, i.e. :func:`acb_siegel_transform` defines an action of the group `\mathrm{Sp}_{2g}(\mathbb{Z})` on `\mathbb{H}_g`. .. code-block:: bash ./build/acb_theta/test/main acb_siegel_transform_z Checks that :func:`acb_siegel_transform` and :func:`acb_siegel_transform_z` agree on random input, and that :func:`acb_siegel_transform_z` on the inverse of any matrix yields the inverse transformation. .. code-block:: bash ./build/acb_theta/test/main acb_siegel_reduce Generates an input matrix `\tau` at a working precision that is not too low compared to the size of its coefficients, and calls :func:`acb_siegel_reduce`. Checks that the resulting matrix `m` is symplectic and that `m\tau` is reduced with a tolerance of `2^{-10}` using :func:`acb_siegel_is_reduced`. .. code-block:: bash ./build/acb_theta/test/main acb_siegel_is_reduced Checks that :func:`acb_siegel_is_reduced` returns 1 on the matrix `i I_g`, but 0 on other matrices specially constructed to not be reduced. .. code-block:: bash ./build/acb_theta/test/main acb_theta_char_get_a Generates a random characteristic *a*, sets *n* to the result of :func:`acb_theta_char_get_slong` on *a*, and checks that the result of :func:`acb_theta_char_get_a` on *n* gives back *a*. .. code-block:: bash ./build/acb_theta/test/main acb_theta_char_dot Checks that dot products computed by :func:`acb_theta_char_dot`, :func:`acb_theta_char_dot_slong` and :func:`acb_theta_char_dot_acb` agree on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_char_is_even Checks that the 10 even theta characteristics for `g=2` are 0, 1, 2, 3, 4, 6, 8, 9, 12, 15. .. code-block:: bash ./build/acb_theta/test/main acb_theta_char_is_goepel Checks that there are exactly 15 Göpel quadruples for `g=2`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_char_is_syzygous Checks that there are exactly 60 syzygous triples for `g=2`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_eld_points Generates a random ellipsoid *E* using :func:`acb_theta_eld_set`, computes its points using :func:`acb_theta_eld_points`, and checks that each of these points lies within the box specified by :macro:`acb_theta_eld_box`. Then, generates random points *pt*: if *pt* is in *E* according to :func:`acb_theta_eld_contains`, then *pt* must appear in the list of points, otherwise the norm of *pt* according to the chosen Cholesky matrix must be at least the radius of *E*. .. code-block:: bash ./build/acb_theta/test/main acb_theta_eld_border Generates a random ellipsoid *E*, computes its border using :func:`acb_theta_eld_border`, and checks that none of these border points lie in *E* nor any of its children. .. code-block:: bash ./build/acb_theta/test/main acb_theta_naive_radius Generates a reduced matrix `\tau` in `\mathbb{H}_g` and vector `z\in \mathbb{C}^g`, calls :func:`acb_theta_naive_radius`, constructs the associated ellipsoid *E*, and checks that the sums of absolute values of terms of the theta series on the border of *E* is at most the specified bound. .. code-block:: bash ./build/acb_theta/test/main acb_theta_naive_reduce Checks that the results of :func:`acb_theta_naive_reduce` are sound on some special values of the input, namely when *zs* has only real entries and when `\mathrm{Im}(z) = -\mathrm{Im}(\tau) n + \varepsilon` where *n* is an even integral vector and `\varepsilon` is small. .. code-block:: bash ./build/acb_theta/test/main acb_theta_naive_term Checks that the result of :func:`acb_theta_naive_term` is `n^k \exp(i\pi(n^2\tau + 2nz))` in the `g=1` case. .. code-block:: bash ./build/acb_theta/test/main acb_theta_naive_00 Checks that the ouput of :func:`acb_theta_naive_00` overlaps the first entry of the output of :func:`acb_theta_naive_0b`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_naive_all Checks that the results of :func:`acb_theta_naive_all` agree with :func:`acb_modular_theta` as follows: if the input matrix `\tau` is diagonal with coefficients `\tau_0,\ldots, \tau_{g-1}`, then for all characteristics `(a,b)` and vectors `z`, we have .. math:: \theta_{a,b}(z,\tau) = \prod_{j=0}^{g-1} \theta_{a_j,b_j}(z_j,\tau_j). .. code-block:: bash ./build/acb_theta/test/main acb_theta_naive_fixed_a Checks that the output of :func:`acb_theta_naive_fixed_a` overlaps the relevant entries of :func:`acb_theta_naive_all` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_naive_fixed_ab Checks that the output of :func:`acb_theta_naive_fixed_ab` overlaps the relevant entries of :func:`acb_theta_naive_all` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_tuples For random *g* and *ord*, generates the list of derivation tuples using :func:`acb_theta_jet_tuples`, picks an index `i` at random, and checks that the result of :func:`acb_theta_jet_index` on the `i^{\mathrm{th}}` tuple is indeed `i`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_mul Checks that the results of :func:`acb_theta_jet_mul` agrees with the result of :func:`fmpz_mpoly_mul` on any input with integral entries. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_compose Checks that the chain rule holds: if `N_3 = N_2 N_1`, then applying :func:`acb_theta_jet_compose` with `N_2`, then `N_1` corresponds to applying :func:`acb_theta_jet_compose` with `N_3` directly. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_naive_radius Generates a reduced matrix `\tau` in `\mathbb{H}_g` and vector `z\in \mathbb{C}^g`, chooses a random order of derivation, calls :func:`acb_theta_jet_naive_radius`, constructs the associated ellipsoid *E*, and checks that the sums of absolute values of terms of the differentiated theta series on the border of *E* is at most the specified bound. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_naive_all Checks that the results of :func:`acb_theta_jet_naive_all` agree with :func:`acb_modular_theta_jet` as follows: if the input matrix `\tau` is diagonal with coefficients `\tau_0,\ldots, \tau_{g-1}`, then for all characteristics `(a,b)`, any vector `z`, and any derivation tuple `(k_0,\ldots,k_{g-1})`, we have .. math:: \frac{\partial^{|k|} \theta_{a,b}} {\partial z_0^{k_0}\cdots \partial z_{g-1}^{k-1}}(z,\tau) = \prod_{j=0}^{g-1} \frac{\partial^{k_j}\theta_{a_j,b_j}}{\partial z^{k_j}}(z_j,\tau_j). .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_naive_00 Checks that the output of :func:`acb_theta_jet_naive_00` agrees with the relevant entries of :func:`acb_theta_jet_naive_all` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_naive_fixed_ab Checks that the output of :func:`acb_theta_jet_naive_fixed_ab` agrees with the relevant entries of :func:`acb_theta_jet_naive_all` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_error_bounds Generates two pairs `(z_1,\tau_1)` and `(z_2,\tau_2)` close to each other but not overlapping, sets `(z,\tau)` to be their reunion (as complex balls on each coefficient), and calls :func:`acb_theta_jet_error_bounds` on `(z,\tau)` for some choice of derivation order. The difference between the results of :func:`acb_theta_jet_naive_all` on `(z_1,\tau_1)` and `(z_2,\tau_2)` must then be at most two times the computed error. .. code-block:: bash ./build/acb_theta/test/main acb_theta_dist_pt Checks that for a random Cholesky matrix `C` and integral vectors `n_1,n_2`, the results of :func:`acb_theta_dist_pt` on `(v,n) = (Cn_1, n_2)` and `(Cn_2, n_1)` agree. .. code-block:: bash ./build/acb_theta/test/main acb_theta_dist_lat Picks a random Cholesky matrix `C` and vector `v`, calls :func:`acb_theta_dist_lat`, and computes the ellipsoid *E* whose radius is the computed distance. Checks that *E* contains at least one point and that the minimum distance is correct by looping over all the points in *E*. .. code-block:: bash ./build/acb_theta/test/main acb_theta_dist_a0 Checks that when `z = \mathrm{Im}(\tau) \tfrac{a}{2}` for some theta characteristic `a`, the result of :func:`acb_theta_dist_a0` on `(z,\tau)` contains zero in its `a^{\mathrm{th}}` entry. .. code-block:: bash ./build/acb_theta/test/main acb_theta_agm_hadamard Checks that calling :func:`acb_theta_agm_hadamard` twice on random input is equivalent to multiplying by `2^g`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_agm_sqrt Generates a random complex number *t*, sets *rts* to a low-precision rounding of *t* (possibly containing zero), and sets *a* to the square of *t*. Checks that the result of :func:`acb_theta_agm_sqrt` on this input is finite, contains *t*, and that the precision loss is small when *rts* does not contain zero. .. code-block:: bash ./build/acb_theta/test/main acb_theta_agm_mul Checks that the duplication formula holds: the result of :func:`acb_theta_agm_mul` on vectors containing `\theta_{0,b}(0,\tau)` and `\theta_{0,b}(z,\tau)` for all `b\in\{0,1\}^g` and any choice of `(z,\tau)` contains the squared theta values `\theta_{0,b}^2(2z,2\tau)`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_agm_mul_tight Generates random `\tau` and `z` at working precision *prec*, computes the associated vectors of distances *d0* and *d* using :func:`acb_theta_dist_a0`, and constructs vectors *a0* and *a* with entries of the form `x e^{-t}` where `x` is uniformly random with `|x|\leq 1` (generated by :func:`acb_urandom`) and *t* is the corresponding entry of *d0* (resp. *d*). Calls :func:`acb_theta_agm_mul_tight` at a lower precision *mprec*. For each `0\leq k< 2^g`, checks that the absolute value of `k^{\mathrm{th}}` entry of the result *res* is at most `e^{-d_k}`, and that the error bound on that entry is at most `2^{-\mathit{mprec} + \delta} e^{-d_k}` for a reasonable value of `\delta` (e.g. 25). .. code-block:: bash ./build/acb_theta/test/main acb_theta_ql_a0_split Checks that the result of :func:`acb_theta_ql_a0_split` (using :func:`acb_theta_ql_a0_naive` as *worker*) agrees with that of :func:`acb_theta_ql_a0_naive` in case of success. .. code-block:: bash ./build/acb_theta/test/main acb_theta_ql_a0_steps Checks that the result of :func:`acb_theta_ql_a0_steps` (using :func:`acb_theta_ql_a0_naive` as *worker*) agrees with that of :func:`acb_theta_ql_a0_naive` in case of success. .. code-block:: bash ./build/acb_theta/test/main acb_theta_ql_a0 Checks that :func:`acb_theta_ql_a0`, if successful, agrees with :func:`acb_theta_ql_a0_naive` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_ql_reduce Generates random values `\tau` and `z` in such a way that :func:`acb_theta_ql_reduce` is likely to output `s < g` and a nonzero *n1*, and checks that the claimed inequalities in that function's documentation hold when computing theta values using :func:`acb_theta_naive_all`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_ql_all Checks that :func:`acb_theta_ql_all` agrees with :func:`acb_theta_naive_all` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_ql_bounds Generates random `(z,\tau)` at a working precision that is not too low and calls :func:`acb_theta_jet_ql_bounds` to compute the bounds *c* and *rho*. Checks that they are finite and that their definition is satisfied by sampling theta values on the corresponding neighborhood of `z` at low precisions with :func:`acb_theta_naive_all`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_ql_radius Checks that the result of :func:`acb_theta_jet_ql_radius` on random input satisfies the required inequalities. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_ql_finite_diff Checks that :func:`acb_theta_jet_ql_finite_diff` computes the correct Taylor coefficients for the function `\exp(z_0+\cdots+z_{g-1})` at zero. Correct input can be generated by :func:`acb_theta_jet_ql_radius`, as the bounds *c* and *rho* can be computed directly for this function. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_ql_all Checks that :func:`acb_theta_jet_ql_all` agrees with :func:`acb_theta_jet_naive_all` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_transform_char Checks that the `a` component of any theta characteristic remains the same after applying :func:`acb_theta_transform_char` when the symplectic matrix is trigonal as in :func:`sp2gz_trig`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_transform_sqrtdet Checks that the result of :func:`acb_theta_transform_sqrtdet` on any input `\tau\in \mathbb{H}_g` squares to `\det(\tau)`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_transform_kappa Checks that :func:`acb_theta_transform_kappa` and :func:`acb_theta_transform_kappa2` agree on random input (i.e. they are congruent modulo 4). .. code-block:: bash ./build/acb_theta/test/main acb_theta_transform_proj Checks that applying :func:`acb_theta_transform_proj` with a random symplectic matrix, then its inverse gives back the initial vector up to scaling. .. code-block:: bash ./build/acb_theta/test/main acb_theta_all Checks that :func:`acb_theta_all` agrees with :func:`acb_theta_naive_all` on random input. The matrix `\tau` is chosen to be a priori non-reduced but still reasonably close to the reduced domain. .. code-block:: bash ./build/acb_theta/test/main acb_theta_jet_all Checks that :func:`acb_theta_jet_all` agrees with :func:`acb_theta_jet_naive_all` on random input. The matrix `\tau` is chosen to be a priori non-reduced but still reasonably close to the reduced domain. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_jet_naive_1 Checks that :func:`acb_theta_g2_jet_naive_1` agrees with :func:`acb_theta_jet_naive_all` with `g=2`, `z = 0` and `\mathit{ord} = 1` on a random matrix `\tau`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_detk_symj Checks that the chain rule holds for the representation `\det^k \mathrm{Sym}^j` of `\mathrm{GL}_2(\mathbb{C})` as computed by :func:`acb_theta_g2_detk_symj`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_transvectant Checks that on any sextic polynomial `f = \sum_{j=0}^6 a_j x^{6-j}`, the transvectant `(f,f)_6` as computed by :func:`acb_theta_g2_transvectant` is `-3a_2^3 + 8a_2 a_4 - 20a_1 a_5 + 120a_0 a_6`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_transvectant_lead Checks that the result of :func:`acb_theta_g2_transvectant_lead` is indeed the leading term of the result of :func:`acb_theta_g2_transvectant` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_character Checks that the results of :func:`acb_theta_g2_character` and :func:`acb_theta_transform_kappa2` for `g=2` are compatible, using the fact that the product `\chi_5` of the ten even theta constants is a Siegel modular form with character. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_psi4 Checks that the result of :func:`acb_theta_g2_psi4` is invariant when applying :func:`acb_theta_transform_proj` on any input vector. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_psi6 Checks that the result of :func:`acb_theta_g2_psi6` is multiplied by `\pm 1` when applying :func:`acb_theta_transform_proj` on any input vector. The correct sign is given by :func:`acb_theta_transform_kappa2`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_chi10 Checks that the result of :func:`acb_theta_g2_chi10` is multiplied by `\pm 1` when applying :func:`acb_theta_transform_proj` on any input vector. The correct sign is given by :func:`acb_theta_transform_kappa2`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_chi12 Checks that the result of :func:`acb_theta_g2_chi12` is invariant when applying :func:`acb_theta_transform_proj` on any input vector. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_chi5 Checks that the result of :func:`acb_theta_g2_chi5` squares to the result of :func:`acb_theta_g2_chi10` on any input vector. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_chi35 Checks that the result of :func:`acb_theta_g2_chi35` is multiplied by `i^k` when applying :func:`acb_theta_transform_proj` on an input vector of theta values. The exponent `k` is given by :func:`acb_theta_transform_kappa2`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_chi3_6 Checks that the product `\chi_{8,6} = \chi_{5}\chi_{3,6}`, computed using :func:`acb_theta_g2_chi5` and :func:`acb_theta_g2_chi3_6`, indeed defines a modular form of weight `\det^8\mathrm{Sym}^6` by evaluating both sides of the transformation law on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_sextic Checks that the discriminant of the result of :func:`acb_theta_g2_sextic` on a random matrix `\tau` is `2^{12}\chi_{10}(\tau)`, as computed by :func:`acb_theta_g2_chi10`. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_sextic_chi5 Checks that the results of :func:`acb_theta_g2_sextic_chi5` agree with those of :func:`acb_theta_g2_sextic` and :func:`acb_theta_g2_chi5` on random input. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_covariants Checks that the output of :func:`acb_theta_g2_covariants` agrees with that of :func:`acb_theta_g2_psi4` using the relation `20\psi_4 = - C_{2,0} + 3 C_{4,0})`. Also checks that each covariant, when evaluated on the result of :func:`acb_theta_g2_sextic`, defines a Siegel modular function of the correct weight by evaluating the transformation law, and that covariants take integral values when the input polynomial is integral. .. code-block:: bash ./build/acb_theta/test/main acb_theta_g2_covariants_lead Checks that the results of :func:`acb_theta_g2_covariants_lead` are indeed the leading terms of the results of :func:`acb_theta_g2_covariants` on random input. Profiling ------------------------------------------------------------------------------- .. code-block:: bash ./build/acb_theta/profile/p-siegel_reduce g pstep pmax dstep dmax Prints quick performance measurements for :func:`acb_siegel_reduce`: for the given `g`, for *d* `\leq` *dmax* by steps of *dstep*, and *prec* `\leq` *pmax* by steps of *pstep*, constructs an input matrix `w` as `\tau/d` where `\tau` is generated by :func:`acb_siegel_randtest_reduced` and runs :func:`acb_siegel_reduce` on `w` at working precision *prec*. This is meant to show that reduction is generally not a critical step when evaluating theta functions. .. code-block:: bash ./build/acb_theta/profile/p-ql_a0_split g prec cstep cmax Prints quick performance measurements for :func:`acb_theta_ql_a0_split`: for the given `g` and at the given working precision *prec*, generates an input matrix `\tau` as in :func:`acb_siegel_randtest_reduced`, but whose lower right `(g-s)\times (g-s)` submatrix is subsequently multiplied by `c`, where `s` runs between `1` and `g-1` and `c\leq` *cmax* is increased by steps of *cstep*. The running times of :func:`acb_theta_ql_a0_steps` with or without splitting at `s` are then compared on each of these matrices, as well as the running time of :func:`acb_theta_ql_a0`. This is meant to provide information on how the choice of splitting in :func:`acb_theta_ql_a0` should be made. .. code-block:: bash ./build/acb_theta/profile/p-ql_a0_steps g pstep pmax Prints quick performance measurements for :func:`acb_theta_ql_a0_steps`: for the given `g` and for a working precision *prec* `\leq` *pmax* increasing by steps of *pstep*, generates a random matrix `\tau` in the reduced domain and compares the running time of :func:`acb_theta_ql_a0_steps` with different parameters *nb_steps*. This is meant to provide information on the correct value to return in :func:`acb_theta_ql_a0_nb_steps`. .. code-block:: bash ./build/acb_theta/profile/p-all g nb_steps hasz Prints quick performance measurements for the functions :func:`acb_theta_all`, :func:`acb_theta_ql_a0`, :func:`acb_theta_ql_all` and :func:`acb_theta_naive_all` at different precisions on a specific input matrix of the specified dimension *g*. We start at precision 32, then double it *nb_steps* times. The parameter *hasz* should be either 0 (theta constants) or 1 (theta values at a nonzero point). This is meant to show whether the main user function is slower than naive algorithms at low precisions. (This is currently the case.) .. code-block:: bash ./build/acb_theta/profile/p-jet_all Prints quick performance measurements for the functions :func:`acb_theta_jet_all` and :func:`acb_theta_jet_naive_all` at different precisions and order 1 on a specific input matrix for `g=2`. This is meant to show whether the main user function is slower than naive algorithms at low precisions. (This is currently the case.) flint-3.1.3/doc/source/acf.rst000066400000000000000000000067661461254215100162020ustar00rootroot00000000000000.. _acf: **acf.h** -- complex floating-point numbers =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: acf_struct .. type:: acf_t An *acf_struct* consists of a pair of *arf_struct*:s. An *acf_t* is defined as an array of length one of type *acf_struct*, permitting an *acf_t* to be passed by reference. .. type:: acf_ptr Alias for ``acf_struct *``, used for vectors of numbers. .. type:: acf_srcptr Alias for ``const acf_struct *``, used for vectors of numbers when passed as constant input to functions. .. macro:: acf_realref(x) Macro returning a pointer to the real part of *x* as an *arf_t*. .. macro:: acf_imagref(x) Macro returning a pointer to the imaginary part of *x* as an *arf_t*. Memory management ------------------------------------------------------------------------------- .. function:: void acf_init(acf_t x) Initializes the variable *x* for use, and sets its value to zero. .. function:: void acf_clear(acf_t x) Clears the variable *x*, freeing or recycling its allocated memory. .. function:: void acf_swap(acf_t z, acf_t x) Swaps *z* and *x* efficiently. .. function:: slong acf_allocated_bytes(const acf_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(acf_struct)`` to get the size of the object as a whole. Basic manipulation ------------------------------------------------------------------------------- .. function:: arf_ptr acf_real_ptr(acf_t z) arf_ptr acf_imag_ptr(acf_t z) Returns a pointer to the real or imaginary part of *z*. .. function:: void acf_set(acf_t z, const acf_t x) Sets *z* to the value *x*. .. function:: int acf_equal(const acf_t x, const acf_t y) Returns whether *x* and *y* are equal. Arithmetic ------------------------------------------------------------------------------- .. function:: int acf_add(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) .. function:: int acf_sub(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) .. function:: int acf_mul(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) Sets *res* to the sum, difference or product of *x* or *y*, correctly rounding the real and imaginary parts in direction *rnd*. The return flag has the least significant bit set if the real part is inexact, and the second least significant bit set if the imaginary part is inexact. Approximate arithmetic ------------------------------------------------------------------------------- The following operations are *not* correctly rounded. The ``rnd`` parameter specifies the final direction of rounding, but intermediate roundings are implementation-defined. .. function:: void acf_approx_inv(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd) void acf_approx_div(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) void acf_approx_sqrt(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd) Computes an approximate inverse, quotient or square root. .. function:: void acf_approx_dot(acf_t res, const acf_t initial, int subtract, acf_srcptr x, slong xstep, acf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd) Computes an approximate dot product, with the same meaning of the parameters as :func:`arb_dot`. flint-3.1.3/doc/source/agm.rst000066400000000000000000000103231461254215100161750ustar00rootroot00000000000000.. _algorithms_agm: Algorithms for the arithmetic-geometric mean =============================================================================== With complex variables, it is convenient to work with the univariate function `M(z) = \operatorname{agm}(1,z)`. The general case is given by `\operatorname{agm}(a,b) = a M(1,b/a)`. Functional equation ------------------------------------------------------------------------------ If the real part of *z* initially is not completely nonnegative, we apply the functional equation `M(z) = (z+1) M(u) / 2` where `u = \sqrt{z} / (z+1)`. Note that *u* has nonnegative real part, absent rounding error. It is not a problem for correctness if rounding makes the interval contain negative points, as this just inflates the final result. For the derivative, the functional equation becomes `M'(z) = [M(u) - (z-1) M'(u) / ((1+z) \sqrt{z})] / 2`. AGM iteration ------------------------------------------------------------------------------ Once *z* is in the right half plane, we can apply the AGM iteration (`2a_{n+1} = a_n + b_n, b_{n+1}^2 = a_n b_n`) directly. The correct square root is given by `\sqrt{a} \sqrt{b}`, which is computed as `\sqrt{ab}, i \sqrt{-ab}, -i \sqrt{-ab}, \sqrt{a} \sqrt{b}` respectively if both *a* and *b* have positive real part, nonnegative imaginary part, nonpositive imaginary part, or otherwise. The iteration should be terminated when `a_n` and `b_n` are close enough. For positive real variables, we can simply take lower and upper bounds to get a correct enclosure at this point. For complex variables, it is shown in [Dup2006]_, p. 87 that, for *z* with nonnegative real part, `|M(z) - a_n| \le |a_n - b_n|`, giving a convenient error bound. Rather than running the AGM iteration until `a_n` and `b_n` agree to `p` bits, it is slightly more efficient to iterate until they agree to about `p/10` bits and finish with a series expansion. With `z = (a-b)/(a+b)`, we have .. math:: \operatorname{agm}(a,b) = \frac{(a+b) \pi}{4 K(z^2)}, valid at least when `|z| < 1` and `a, b` have nonnegative real part, and .. math:: \frac{\pi}{4 K(z^2)} = \tfrac{1}{2} - \tfrac{1}{8} z^2 - \tfrac{5}{128} z^4 - \tfrac{11}{512} z^6 - \tfrac{469}{32768} z^8 + \ldots where the tail is bounded by `\sum_{k=10}^{\infty} |z|^k/64`. First derivative ------------------------------------------------------------------------------ Assuming that *z* is exact and that `|\arg(z)| \le 3 \pi / 4`, we compute `(M(z), M'(z))` simultaneously using a finite difference. The basic inequality we need is `|M(z)| \le \max(1, |z|)`, which is an immediate consequence of the AGM iteration. By Cauchy's integral formula, `|M^{(k)}(z) / k!| \le C D^k` where `C = \max(1, |z| + r)` and `D = 1/r`, for any `0 < r < |z|` (we choose *r* to be of the order `|z| / 4`). Taylor expansion now gives .. math:: \left|\frac{M(z+h) - M(z)}{h} - M'(z)\right| \le \frac{C D^2 h}{1 - D h} \left|\frac{M(z+h) - M(z-h)}{2h} - M'(z)\right| \le \frac{C D^3 h^2}{1 - D h} \left|\frac{M(z+h) + M(z-h)}{2} - M(z)\right| \le \frac{C D^2 h^2}{1 - D h} assuming that *h* is chosen so that it satisfies `h D < 1`. The forward finite difference would require two function evaluations at doubled precision. We use the central difference as it only requires 1.5 times the precision. When *z* is not exact, we evaluate at the midpoint as above and bound the propagated error using derivatives. Again by Cauchy's integral formula, we have .. math:: |M'(z+\varepsilon)| \le \frac{\max(1, |z|+|\varepsilon|+r)}{r} |M''(z+\varepsilon)| \le \frac{2 \max(1, |z|+|\varepsilon|+r)}{r^2} assuming that the circle centered on *z* with radius `|\varepsilon| + r` does not cross the negative half axis. We choose *r* of order `|z| / 2` and verify that all assumptions hold. Higher derivatives ------------------------------------------------------------------------------- The function `W(z) = 1 / M(z)` is D-finite. The coefficients of `W(z+x) = \sum_{k=0}^{\infty} c_k x^k` satisfy .. math:: -2 z (z^2-1) c_2 = (3z^2-1) c_1 + z c_0, .. math:: -(k+2)(k+3) z (z^2-1) c_{k+3} = (k+2)^2 (3z^2-1) c_{k+2} + (3k(k+3)+7)z c_{k+1} + (k+1)^2 c_{k} in general, and .. math:: -(k+2)^2 c_{k+2} = (3k(k+3)+7) c_{k+1} + (k+1)^2 c_{k} when `z = 1`. flint-3.1.3/doc/source/aprcl.rst000066400000000000000000000343321461254215100165400ustar00rootroot00000000000000.. _aprcl: **aprcl.h** -- APRCL primality testing ======================================================================================== This module implements the rigorous APRCL primality test, suitable for integers up to a few thousand digits. The APR-CL test uses the Jacobi sums that belong to `\mathbb{Z}[\zeta]/(n)`, so we have :type:`unity_zp` struct and some useful operations. :type:`unity_zp` is just a wrapper over :type:`fmpz_mod_poly` with additional fields. Also provides Gauss sum test, which is not very useful in practice, but can be useful for people who want to see an implementation of these. Gauss sums belong `\mathbb{Z}[\zeta_q, \zeta_p]/(n)` and implemented in :type:`unity_zpq` struct. Authors: * Vladimir Glazachev (Google Summer of Code, 2015) Primality test functions -------------------------------------------------------------------------------- .. function:: int aprcl_is_prime(const fmpz_t n) Tests `n` for primality using the APRCL test. This is the same as :func:`aprcl_is_prime_jacobi`. .. function:: int aprcl_is_prime_jacobi(const fmpz_t n) If `n` is prime returns 1; otherwise returns 0. The algorithm is well described in "Implementation of a New Primality Test" by H. Cohen and A.K. Lenstra and "A Course in Computational Algebraic Number Theory" by H. Cohen. It is theoretically possible that this function fails to prove that `n` is prime. In this event, :func:`flint_abort` is called. To handle this condition, the :func:`_aprcl_is_prime_jacobi` function can be used. .. function:: int aprcl_is_prime_gauss(const fmpz_t n) If `n` is prime returns 1; otherwise returns 0. Uses the cyclotomic primality testing algorithm described in "Four primality testing algorithms" by Rene Schoof. The minimum required numbers `s` and `R` are computed automatically. By default `R \ge 180`. In some cases this function fails to prove that `n` is prime. This means that we select a too small `R` value. In this event, :func:`flint_abort` is called. To handle this condition, the :func:`_aprcl_is_prime_jacobi` function can be used. .. function:: primality_test_status _aprcl_is_prime_jacobi(const fmpz_t n, const aprcl_config config) Jacobi sum test for `n`. Possible return values: ``PRIME``, ``COMPOSITE`` and ``UNKNOWN`` (if we cannot prove primality). .. function:: primality_test_status _aprcl_is_prime_gauss(const fmpz_t n, const aprcl_config config) Tests `n` for primality with fixed ``config``. Possible return values: ``PRIME``, ``COMPOSITE`` and ``PROBABPRIME`` (if we cannot prove primality). .. function:: int aprcl_is_prime_gauss_min_R(const fmpz_t n, ulong R) Same as :func:`aprcl_is_prime_gauss` with fixed minimum value of `R`. .. function:: int aprcl_is_prime_final_division(const fmpz_t n, const fmpz_t s, ulong r) Returns 0 if for some `a = n^k \bmod s`, where `k \in [1, r - 1]`, we have that `a \mid n`; otherwise returns 1. Configuration functions -------------------------------------------------------------------------------- .. type:: _aprcl_config .. type:: aprcl_config Holds precomputed parameters. .. function:: void aprcl_config_gauss_init(aprcl_config conf, const fmpz_t n) Computes the `s` and `R` values used in the cyclotomic primality test, `s^2 > n` and `s=\prod\limits_{\substack{q-1\mid R \\ q \text{ prime}}}q`. Also stores factors of `R` and `s`. .. function:: void aprcl_config_gauss_init_min_R(aprcl_config conf, const fmpz_t n, ulong R) Computes the `s` with fixed minimum `R` such that `a^R \equiv 1 \mod{s}` for all integers `a` coprime to `s`. .. function:: void aprcl_config_gauss_clear(aprcl_config conf) Clears the given ``aprcl_config`` element. It must be reinitialised in order to be used again. .. function:: ulong aprcl_R_value(const fmpz_t n) Returns a precomputed `R` value for APRCL, such that the corresponding `s` value is greater than `\sqrt{n}`. The maximum stored value `6983776800` allows to test numbers up to `6000` digits. .. function:: void aprcl_config_jacobi_init(aprcl_config conf, const fmpz_t n) Computes the `s` and `R` values used in the cyclotomic primality test, `s^2 > n` and `a^R \equiv 1 \mod{s}` for all `a` coprime to `s`. Also stores factors of `R` and `s`. .. function:: void aprcl_config_jacobi_clear(aprcl_config conf) Clears the given ``aprcl_config`` element. It must be reinitialised in order to be used again. Cyclotomic arithmetic -------------------------------------------------------------------------------- This code implements arithmetic in cyclotomic rings. Types ................................................................................ .. type:: _unity_zp .. type:: unity_zp Represents an element of `\mathbb{Z}[\zeta_{p^{exp}}]/(n)` as an :type:`fmpz_mod_poly_t` reduced modulo a cyclotomic polynomial. .. type:: _unity_zpq .. type:: unity_zpq Represents an element of `\mathbb{Z}[\zeta_q, \zeta_p]/(n)` as an array of :type:`fmpz_mod_poly_t`. Memory management ................................................................................ .. function:: void unity_zp_init(unity_zp f, ulong p, ulong exp, const fmpz_t n) Initializes `f` as an element of `\mathbb{Z}[\zeta_{p^{exp}}]/(n)`. .. function:: void unity_zp_clear(unity_zp f) Clears the given element. It must be reinitialised in order to be used again. .. function:: void unity_zp_copy(unity_zp f, const unity_zp g) Sets `f` to `g`. `f` and `g` must be initialized with same `p` and `n`. .. function:: void unity_zp_swap(unity_zp f, unity_zp q) Swaps `f` and `g`. `f` and `g` must be initialized with same `p` and `n`. .. function:: void unity_zp_set_zero(unity_zp f) Sets `f` to zero. Comparison ................................................................................ .. function:: slong unity_zp_is_unity(unity_zp f) If `f = \zeta^h` returns h; otherwise returns -1. .. function:: int unity_zp_equal(unity_zp f, unity_zp g) Returns nonzero if `f = g` reduced by the `p^{exp}`-th cyclotomic polynomial. Coefficient management ................................................................................ .. function:: void unity_zp_coeff_set_fmpz(unity_zp f, ulong ind, const fmpz_t x) void unity_zp_coeff_set_ui(unity_zp f, ulong ind, ulong x) Sets the coefficient of `\zeta^{ind}` to `x`. `ind` must be less than `p^{exp}`. .. function:: void unity_zp_coeff_add_fmpz(unity_zp f, ulong ind, const fmpz_t x) void unity_zp_coeff_add_ui(unity_zp f, ulong ind, ulong x) Adds `x` to the coefficient of `\zeta^{ind}`. `x` must be less than `n`. `ind` must be less than `p^{exp}`. .. function:: void unity_zp_coeff_inc(unity_zp f, ulong ind) Increments the coefficient of `\zeta^{ind}`. `ind` must be less than `p^{exp}`. .. function:: void unity_zp_coeff_dec(unity_zp f, ulong ind) Decrements the coefficient of `\zeta^{ind}`. `ind` must be less than `p^{exp}`. Scalar multiplication ................................................................................ .. function:: void unity_zp_mul_scalar_ui(unity_zp f, const unity_zp g, ulong s) Sets `f` to `s \cdot g`. `f` and `g` must be initialized with same `p`, `exp` and `n`. Addition and multiplication ................................................................................ .. function:: void unity_zp_add(unity_zp f, const unity_zp g, const unity_zp h) Sets `f` to `g + h`. `f`, `g` and `h` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_mul(unity_zp f, const unity_zp g, const unity_zp h) Sets `f` to `g \cdot h`. `f`, `g` and `h` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_sqr(unity_zp f, const unity_zp g) Sets `f` to `g \cdot g`. `f`, `g` and `h` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_mul_inplace(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) Sets `f` to `g \cdot h`. If `p^{exp} = 3, 4, 5, 7, 8, 9, 11, 16` special multiplication functions are used. The preallocated array `t` of ``fmpz_t`` is used for all computations in this case. `f`, `g` and `h` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_sqr_inplace(unity_zp f, const unity_zp g, fmpz_t * t) Sets `f` to `g \cdot g`. If `p^{exp} = 3, 4, 5, 7, 8, 9, 11, 16` special multiplication functions are used. The preallocated array `t` of ``fmpz_t`` is used for all computations in this case. `f` and `g` must be initialized with same `p`, `exp` and `n`. Powering functions ................................................................................ .. function:: void unity_zp_pow_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow) Sets `f` to `g^{pow}`. `f` and `g` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_pow_ui(unity_zp f, const unity_zp g, ulong pow) Sets `f` to `g^{pow}`. `f` and `g` must be initialized with same `p`, `exp` and `n`. .. function:: ulong _unity_zp_pow_select_k(const fmpz_t n) Returns the smallest integer `k` satisfying `\log (n) < (k(k + 1)2^{2k}) / (2^{k + 1} - k - 2) + 1` .. function:: void unity_zp_pow_2k_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow) Sets `f` to `g^{pow}` using the `2^k`-ary exponentiation method. `f` and `g` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_pow_2k_ui(unity_zp f, const unity_zp g, ulong pow) Sets `f` to `g^{pow}` using the `2^k`-ary exponentiation method. `f` and `g` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_pow_sliding_fmpz(unity_zp f, unity_zp g, const fmpz_t pow) Sets `f` to `g^{pow}` using the sliding window exponentiation method. `f` and `g` must be initialized with same `p`, `exp` and `n`. Cyclotomic reduction ................................................................................ .. function:: void _unity_zp_reduce_cyclotomic_divmod(unity_zp f) void _unity_zp_reduce_cyclotomic(unity_zp f) Sets `f = f \bmod \Phi_{p^{exp}}`. `\Phi_{p^{exp}}` is the `p^{exp}`-th cyclotomic polynomial. `g` must be reduced by `x^{p^{exp}}-1` poly. `f` and `g` must be initialized with same `p`, `exp` and `n`. .. function:: void unity_zp_reduce_cyclotomic(unity_zp f, const unity_zp g) Sets `f = g \bmod \Phi_{p^{exp}}`. `\Phi_{p^{exp}}` is the `p^{exp}`-th cyclotomic polynomial. Automorphism and inverse ................................................................................ .. function:: void unity_zp_aut(unity_zp f, const unity_zp g, ulong x) Sets `f = \sigma_x(g)`, the automorphism `\sigma_x(\zeta)=\zeta^x`. `f` and `g` must be initialized with the same `p`, `exp` and `n`. .. function:: void unity_zp_aut_inv(unity_zp f, const unity_zp g, ulong x) Sets `f = \sigma_x^{-1}(g)`, so `\sigma_x(f) = g`. `g` must be reduced by `\Phi_{p^{exp}}`. `f` and `g` must be initialized with the same `p`, `exp` and `n`. Jacobi sum ................................................................................ Here `\chi_{p, q}` is the character defined by `\chi_{p, q}(g^x) = \zeta_{p^k}^x`, where `g` is a primitive root modulo `q`. .. function:: void unity_zp_jacobi_sum_pq(unity_zp f, ulong q, ulong p) Sets `f` to the Jacobi sum `J(p, q) = j(\chi_{p, q}, \chi_{p, q})`. .. function:: void unity_zp_jacobi_sum_2q_one(unity_zp f, ulong q) Sets `f` to the Jacobi sum `J_2(q) = j(\chi_{2, q}^{2^{k - 3}}, \chi_{2, q}^{3 \cdot 2^{k - 3}}))^2`. .. function:: void unity_zp_jacobi_sum_2q_two(unity_zp f, ulong q) Sets `f` to the Jacobi sum `J_3(1) = j(\chi_{2, q}, \chi_{2, q}, \chi_{2, q}) = J(2, q) \cdot j(\chi_{2, q}^2, \chi_{2, q})`. Extended rings ................................................................................ .. function:: void unity_zpq_init(unity_zpq f, ulong q, ulong p, const fmpz_t n) Initializes `f` as an element of `\mathbb{Z}[\zeta_q, \zeta_p]/(n)`. .. function:: void unity_zpq_clear(unity_zpq f) Clears the given element. It must be reinitialized in order to be used again. .. function:: void unity_zpq_copy(unity_zpq f, const unity_zpq g) Sets `f` to `g`. `f` and `g` must be initialized with same `p`, `q` and `n`. .. function:: void unity_zpq_swap(unity_zpq f, unity_zpq q) Swaps `f` and `g`. `f` and `g` must be initialized with same `p`, `q` and `n`. .. function:: int unity_zpq_equal(const unity_zpq f, const unity_zpq g) Returns nonzero if `f = g`. .. function:: void unity_zpq_coeff_set_fmpz(unity_zpq f, slong i, slong j, const fmpz_t x) Sets the coefficient of `\zeta_q^i \zeta_p^j` to `x`. `i` must be less than `q` and `j` must be less than `p`. .. function:: void unity_zpq_coeff_set_ui(unity_zpq f, slong i, slong j, ulong x) Sets the coefficient of `\zeta_q^i \zeta_p^j` to `x`. `i` must be less than `q` and `j` must be less then `p`. .. function:: void unity_zpq_coeff_add(unity_zpq f, slong i, slong j, const fmpz_t x) Adds `x` to the coefficient of `\zeta_p^i \zeta_q^j`. `x` must be less than `n`. .. function:: void unity_zpq_add(unity_zpq f, const unity_zpq g, const unity_zpq h) Sets `f` to `g + h`. `f`, `g` and `h` must be initialized with same `q`, `p` and `n`. .. function:: void unity_zpq_mul(unity_zpq f, const unity_zpq g, const unity_zpq h) Sets the `f` to `g \cdot h`. `f`, `g` and `h` must be initialized with same `q`, `p` and `n`. .. function:: void _unity_zpq_mul_unity_p(unity_zpq f) Sets `f = f \cdot \zeta_p`. .. function:: void unity_zpq_mul_unity_p_pow(unity_zpq f, const unity_zpq g, slong k) Sets `f` to `g \cdot \zeta_p^k`. .. function:: void unity_zpq_pow(unity_zpq f, const unity_zpq g, const fmpz_t p) Sets `f` to `g^p`. `f` and `g` must be initialized with same `p`, `q` and `n`. .. function:: void unity_zpq_pow_ui(unity_zpq f, const unity_zpq g, ulong p) Sets `f` to `g^p`. `f` and `g` must be initialized with same `p`, `q` and `n`. .. function:: void unity_zpq_gauss_sum(unity_zpq f, ulong q, ulong p) Sets `f = \tau(\chi_{p, q})`. .. function:: void unity_zpq_gauss_sum_sigma_pow(unity_zpq f, ulong q, ulong p) Sets `f = \tau^{\sigma_n}(\chi_{p, q})`. flint-3.1.3/doc/source/arb.rst000066400000000000000000002430011461254215100161760ustar00rootroot00000000000000.. _arb: **arb.h** -- real numbers =============================================================================== An :type:`arb_t` represents a ball over the real numbers, that is, an interval `[m \pm r] \equiv [m-r, m+r]` where the midpoint `m` and the radius `r` are (extended) real numbers and `r` is nonnegative (possibly infinite). The result of an (approximate) operation done on :type:`arb_t` variables is a ball which contains the result of the (mathematically exact) operation applied to any choice of points in the input balls. In general, the output ball is not the smallest possible. The precision parameter passed to each function roughly indicates the precision to which calculations on the midpoint are carried out (operations on the radius are always done using a fixed, small precision.) For arithmetic operations, the precision parameter currently simply specifies the precision of the corresponding :type:`arf_t` operation. In the future, the arithmetic might be made faster by incorporating sloppy rounding (typically equivalent to a loss of 1-2 bits of effective working precision) when the result is known to be inexact (while still propagating errors rigorously, of course). Arithmetic operations done on exact input with exactly representable output are always guaranteed to produce exact output. For more complex operations, the precision parameter indicates a minimum working precision (algorithms might allocate extra internal precision to attempt to produce an output accurate to the requested number of bits, especially when the required precision can be estimated easily, but this is not generally required). If the precision is increased and the inputs either are exact or are computed with increased accuracy as well, the output should converge proportionally, absent any bugs. The general intended strategy for using ball arithmetic is to add a few guard bits, and then repeat the calculation as necessary with an exponentially increasing number of guard bits (Ziv's strategy) until the result is exact enough for one's purposes (typically the first attempt will be successful). The following balls with an infinite or NaN component are permitted, and may be returned as output from functions. * The ball `[+\infty \pm c]`, where `c` is finite, represents the point at positive infinity. Such a ball can always be replaced by `[+\infty \pm 0]` while preserving mathematical correctness (this is currently not done automatically by the library). * The ball `[-\infty \pm c]`, where `c` is finite, represents the point at negative infinity. Such a ball can always be replaced by `[-\infty \pm 0]` while preserving mathematical correctness (this is currently not done automatically by the library). * The ball `[c \pm \infty]`, where `c` is finite or infinite, represents the whole extended real line `[-\infty,+\infty]`. Such a ball can always be replaced by `[0 \pm \infty]` while preserving mathematical correctness (this is currently not done automatically by the library). Note that there is no way to represent a half-infinite interval such as `[0,\infty]`. * The ball `[\operatorname{NaN} \pm c]`, where `c` is finite or infinite, represents an indeterminate value (the value could be any extended real number, or it could represent a function being evaluated outside its domain of definition, for example where the result would be complex). Such an indeterminate ball can always be replaced by `[\operatorname{NaN} \pm \infty]` while preserving mathematical correctness (this is currently not done automatically by the library). Types, macros and constants ------------------------------------------------------------------------------- .. type:: arb_struct .. type:: arb_t An :type:`arb_struct` consists of an :type:`arf_struct` (the midpoint) and a :type:`mag_struct` (the radius). An :type:`arb_t` is defined as an array of length one of type :type:`arb_struct`, permitting an :type:`arb_t` to be passed by reference. .. type:: arb_ptr Alias for ``arb_struct *``, used for vectors of numbers. .. type:: arb_srcptr Alias for ``const arb_struct *``, used for vectors of numbers when passed as constant input to functions. .. macro:: arb_midref(x) Macro returning a pointer to the midpoint of *x* as an :type:`arf_t`. .. macro:: arb_radref(x) Macro returning a pointer to the radius of *x* as a :type:`mag_t`. Memory management ------------------------------------------------------------------------------- .. function:: void arb_init(arb_t x) Initializes the variable *x* for use. Its midpoint and radius are both set to zero. .. function:: void arb_clear(arb_t x) Clears the variable *x*, freeing or recycling its allocated memory. .. function:: arb_ptr _arb_vec_init(slong n) Returns a pointer to an array of *n* initialized :type:`arb_struct` entries. .. function:: void _arb_vec_clear(arb_ptr v, slong n) Clears an array of *n* initialized :type:`arb_struct` entries. .. function:: void arb_swap(arb_t x, arb_t y) Swaps *x* and *y* efficiently. .. function:: slong arb_allocated_bytes(const arb_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(arb_struct)`` to get the size of the object as a whole. .. function:: slong _arb_vec_allocated_bytes(arb_srcptr vec, slong len) Returns the total number of bytes allocated for this vector, i.e. the space taken up by the vector itself plus the sum of the internal heap allocation sizes for all its member elements. .. function:: double _arb_vec_estimate_allocated_bytes(slong len, slong prec) Estimates the number of bytes that need to be allocated for a vector of *len* elements with *prec* bits of precision, including the space for internal limb data. This function returns a *double* to avoid overflow issues when both *len* and *prec* are large. This is only an approximation of the physical memory that will be used by an actual vector. In practice, the space varies with the content of the numbers; for example, zeros and small integers require no internal heap allocation even if the precision is huge. The estimate assumes that exponents will not be bignums. The actual amount may also be higher or lower due to overhead in the memory allocator or overcommitment by the operating system. Assignment and rounding ------------------------------------------------------------------------------- .. function:: void arb_set(arb_t y, const arb_t x) .. function:: void arb_set_arf(arb_t y, const arf_t x) .. function:: void arb_set_si(arb_t y, slong x) .. function:: void arb_set_ui(arb_t y, ulong x) .. function:: void arb_set_fmpz(arb_t y, const fmpz_t x) .. function:: void arb_set_d(arb_t y, double x) Sets *y* to the value of *x* without rounding. .. note:: Be cautious when using :func:`arb_set_d` as it does not impose any error bounds and will only convert a ``double`` to an ``arb_t``. For instance, ``arb_set_d(x, 1.1)`` and ``arb_set_str(x, "1.1", prec)`` work very differently, where the former will first create a ``double`` whose value is the approximation of `1.1` (without any error bounds) which then sets *x* to this approximated value with no error. This differs from ``arb_set_str`` which will impose an error bound based on the precision. .. function:: void arb_set_fmpz_2exp(arb_t y, const fmpz_t x, const fmpz_t e) Sets *y* to `x \cdot 2^e`. .. function:: void arb_set_round(arb_t y, const arb_t x, slong prec) .. function:: void arb_set_round_fmpz(arb_t y, const fmpz_t x, slong prec) Sets *y* to the value of *x*, rounded to *prec* bits in the direction towards zero. .. function:: void arb_set_round_fmpz_2exp(arb_t y, const fmpz_t x, const fmpz_t e, slong prec) Sets *y* to `x \cdot 2^e`, rounded to *prec* bits in the direction towards zero. .. function:: void arb_set_fmpq(arb_t y, const fmpq_t x, slong prec) Sets *y* to the rational number *x*, rounded to *prec* bits in the direction towards zero. .. function:: int arb_set_str(arb_t res, const char * inp, slong prec) Sets *res* to the value specified by the human-readable string *inp*. The input may be a decimal floating-point literal, such as "25", "0.001", "7e+141" or "-31.4159e-1", and may also consist of two such literals separated by the symbol "+/-" and optionally enclosed in brackets, e.g. "[3.25 +/- 0.0001]", or simply "[+/- 10]" with an implicit zero midpoint. The output is rounded to *prec* bits, and if the binary-to-decimal conversion is inexact, the resulting error is added to the radius. The symbols "inf" and "nan" are recognized (a nan midpoint results in an indeterminate interval, with infinite radius). Returns 0 if successful and nonzero if unsuccessful. If unsuccessful, the result is set to an indeterminate interval. .. function:: char * arb_get_str(const arb_t x, slong n, ulong flags) Returns a nice human-readable representation of *x*, with at most *n* digits of the midpoint printed. With default flags, the output can be parsed back with :func:`arb_set_str`, and this is guaranteed to produce an interval containing the original interval *x*. By default, the output is rounded so that the value given for the midpoint is correct up to 1 ulp (unit in the last decimal place). If *ARB_STR_MORE* is added to *flags*, more (possibly incorrect) digits may be printed. If *ARB_STR_NO_RADIUS* is added to *flags*, the radius is not included in the output. Unless *ARB_STR_MORE* is set, the output is rounded so that the midpoint is correct to 1 ulp. As a special case, if there are no significant digits after rounding, the result will be shown as ``0e+n``, meaning that the result is between ``-1e+n`` and ``1e+n`` (following the contract that the output is correct to within one unit in the only shown digit). By adding a multiple *m* of *ARB_STR_CONDENSE* to *flags*, strings of more than three times *m* consecutive digits are condensed, only printing the leading and trailing *m* digits along with brackets indicating the number of digits omitted (useful when computing values to extremely high precision). Assignment of special values ------------------------------------------------------------------------------- .. function:: void arb_zero(arb_t x) Sets *x* to zero. .. function:: void arb_one(arb_t f) Sets *x* to the exact integer 1. .. function:: void arb_pos_inf(arb_t x) Sets *x* to positive infinity, with a zero radius. .. function:: void arb_neg_inf(arb_t x) Sets *x* to negative infinity, with a zero radius. .. function:: void arb_zero_pm_inf(arb_t x) Sets *x* to `[0 \pm \infty]`, representing the whole extended real line. .. function:: void arb_indeterminate(arb_t x) Sets *x* to `[\operatorname{NaN} \pm \infty]`, representing an indeterminate result. .. function:: void arb_zero_pm_one(arb_t x) Sets *x* to the interval `[0 \pm 1]`. .. function:: void arb_unit_interval(arb_t x) Sets *x* to the interval `[0, 1]`. Input and output ------------------------------------------------------------------------------- The *arb_print...* functions print to standard output, while *arb_fprint...* functions print to the stream *file*. .. function:: void arb_print(const arb_t x) .. function:: void arb_fprint(FILE * file, const arb_t x) Prints the internal representation of *x*. .. function:: void arb_printd(const arb_t x, slong digits) .. function:: void arb_fprintd(FILE * file, const arb_t x, slong digits) Prints *x* in decimal. The printed value of the radius is not adjusted to compensate for the fact that the binary-to-decimal conversion of both the midpoint and the radius introduces additional error. .. function:: void arb_printn(const arb_t x, slong digits, ulong flags) .. function:: void arb_fprintn(FILE * file, const arb_t x, slong digits, ulong flags) Prints a nice decimal representation of *x*. By default, the output shows the midpoint with a guaranteed error of at most one unit in the last decimal place. In addition, an explicit error bound is printed so that the displayed decimal interval is guaranteed to enclose *x*. See :func:`arb_get_str` for details. .. function:: char * arb_dump_str(const arb_t x) Returns a serialized representation of *x* as a null-terminated ASCII string that can be read by :func:`arb_load_str`. The format consists of four hexadecimal integers representing the midpoint mantissa, midpoint exponent, radius mantissa and radius exponent (with special values to indicate zero, infinity and NaN values), separated by single spaces. The returned string needs to be deallocated with *flint_free*. .. function:: int arb_load_str(arb_t x, const char * str) Sets *x* to the serialized representation given in *str*. Returns a nonzero value if *str* is not formatted correctly (see :func:`arb_dump_str`). .. function:: int arb_dump_file(FILE * stream, const arb_t x) Writes a serialized ASCII representation of *x* to *stream* in a form that can be read by :func:`arb_load_file`. Returns a nonzero value if the data could not be written. .. function:: int arb_load_file(arb_t x, FILE * stream) Reads *x* from a serialized ASCII representation in *stream*. Returns a nonzero value if the data is not formatted correctly or the read failed. Note that the data is assumed to be delimited by a whitespace or end-of-file, i.e., when writing multiple values with :func:`arb_dump_file` make sure to insert a whitespace to separate consecutive values. It is possible to serialize and deserialize a vector as follows (warning: without error handling): .. code-block:: c fp = fopen("data.txt", "w"); for (i = 0; i < n; i++) { arb_dump_file(fp, vec + i); fprintf(fp, "\n"); // or any whitespace character } fclose(fp); fp = fopen("data.txt", "r"); for (i = 0; i < n; i++) { arb_load_file(vec + i, fp); } fclose(fp); Random number generation ------------------------------------------------------------------------------- .. function:: void arb_randtest(arb_t x, flint_rand_t state, slong prec, slong mag_bits) Generates a random ball. The midpoint and radius will both be finite. .. function:: void arb_randtest_exact(arb_t x, flint_rand_t state, slong prec, slong mag_bits) Generates a random number with zero radius. .. function:: void arb_randtest_precise(arb_t x, flint_rand_t state, slong prec, slong mag_bits) Generates a random number with radius around `2^{-\text{prec}}` the magnitude of the midpoint. .. function:: void arb_randtest_positive(arb_t x, flint_rand_t state, slong prec, slong mag_bits) Generates a random precise number which is guaranteed to be positive. .. function:: void arb_randtest_wide(arb_t x, flint_rand_t state, slong prec, slong mag_bits) Generates a random number with midpoint and radius chosen independently, possibly giving a very large interval. .. function:: void arb_randtest_special(arb_t x, flint_rand_t state, slong prec, slong mag_bits) Generates a random interval, possibly having NaN or an infinity as the midpoint and possibly having an infinite radius. .. function:: void arb_get_rand_fmpq(fmpq_t q, flint_rand_t state, const arb_t x, slong bits) Sets *q* to a random rational number from the interval represented by *x*. A denominator is chosen by multiplying the binary denominator of *x* by a random integer up to *bits* bits. The outcome is undefined if the midpoint or radius of *x* is non-finite, or if the exponent of the midpoint or radius is so large or small that representing the endpoints as exact rational numbers would cause overflows. .. function:: void arb_urandom(arb_t x, flint_rand_t state, slong prec) Sets *x* to a uniformly distributed random number in the interval `[0, 1]`. The method uses rounding from integers to floats, hence the radius might not be `0`. Radius and interval operations ------------------------------------------------------------------------------- .. function:: void arb_get_mid_arb(arb_t m, const arb_t x) Sets *m* to the midpoint of *x*. .. function:: void arb_get_rad_arb(arb_t r, const arb_t x) Sets *r* to the radius of *x*. .. function:: void arb_add_error_arf(arb_t x, const arf_t err) .. function:: void arb_add_error_mag(arb_t x, const mag_t err) .. function:: void arb_add_error(arb_t x, const arb_t err) Adds the absolute value of *err* to the radius of *x* (the operation is done in-place). .. function:: void arb_add_error_2exp_si(arb_t x, slong e) .. function:: void arb_add_error_2exp_fmpz(arb_t x, const fmpz_t e) Adds `2^e` to the radius of *x*. .. function:: void arb_union(arb_t z, const arb_t x, const arb_t y, slong prec) Sets *z* to a ball containing both *x* and *y*. .. function:: int arb_intersection(arb_t z, const arb_t x, const arb_t y, slong prec) If *x* and *y* overlap according to :func:`arb_overlaps`, then *z* is set to a ball containing the intersection of *x* and *y* and a nonzero value is returned. Otherwise zero is returned and the value of *z* is undefined. If *x* or *y* contains NaN, the result is NaN. .. function:: void arb_nonnegative_part(arb_t res, const arb_t x) Sets *res* to the intersection of *x* with `[0,\infty]`. If *x* is nonnegative, an exact copy is made. If *x* is finite and contains negative numbers, an interval of the form `[r/2 \pm r/2]` is produced, which certainly contains no negative points. In the special case when *x* is strictly negative, *res* is set to zero. .. function:: void arb_get_abs_ubound_arf(arf_t u, const arb_t x, slong prec) Sets *u* to the upper bound for the absolute value of *x*, rounded up to *prec* bits. If *x* contains NaN, the result is NaN. .. function:: void arb_get_abs_lbound_arf(arf_t u, const arb_t x, slong prec) Sets *u* to the lower bound for the absolute value of *x*, rounded down to *prec* bits. If *x* contains NaN, the result is NaN. .. function:: void arb_get_ubound_arf(arf_t u, const arb_t x, slong prec) Sets *u* to the upper bound for the value of *x*, rounded up to *prec* bits. If *x* contains NaN, the result is NaN. .. function:: void arb_get_lbound_arf(arf_t u, const arb_t x, slong prec) Sets *u* to the lower bound for the value of *x*, rounded down to *prec* bits. If *x* contains NaN, the result is NaN. .. function:: void arb_get_mag(mag_t z, const arb_t x) Sets *z* to an upper bound for the absolute value of *x*. If *x* contains NaN, the result is positive infinity. .. function:: void arb_get_mag_lower(mag_t z, const arb_t x) Sets *z* to a lower bound for the absolute value of *x*. If *x* contains NaN, the result is zero. .. function:: void arb_get_mag_lower_nonnegative(mag_t z, const arb_t x) Sets *z* to a lower bound for the signed value of *x*, or zero if *x* overlaps with the negative half-axis. If *x* contains NaN, the result is zero. .. function:: void arb_get_interval_fmpz_2exp(fmpz_t a, fmpz_t b, fmpz_t exp, const arb_t x) Computes the exact interval represented by *x*, in the form of an integer interval multiplied by a power of two, i.e. `x = [a, b] \times 2^{\text{exp}}`. The result is normalized by removing common trailing zeros from *a* and *b*. This method aborts if *x* is infinite or NaN, or if the difference between the exponents of the midpoint and the radius is so large that allocating memory for the result fails. Warning: this method will allocate a huge amount of memory to store the result if the exponent difference is huge. Memory allocation could succeed even if the required space is far larger than the physical memory available on the machine, resulting in swapping. It is recommended to check that the midpoint and radius of *x* both are within a reasonable range before calling this method. .. function:: void arb_set_interval_mag(arb_t x, const mag_t a, const mag_t b, slong prec) .. function:: void arb_set_interval_arf(arb_t x, const arf_t a, const arf_t b, slong prec) .. function:: void arb_set_interval_mpfr(arb_t x, const mpfr_t a, const mpfr_t b, slong prec) Sets *x* to a ball containing the interval `[a, b]`. We require that `a \le b`. .. function:: void arb_set_interval_neg_pos_mag(arb_t x, const mag_t a, const mag_t b, slong prec) Sets *x* to a ball containing the interval `[-a, b]`. .. function:: void arb_get_interval_arf(arf_t a, arf_t b, const arb_t x, slong prec) .. function:: void arb_get_interval_mpfr(mpfr_t a, mpfr_t b, const arb_t x) Constructs an interval `[a, b]` containing the ball *x*. The MPFR version uses the precision of the output variables. .. function:: slong arb_rel_error_bits(const arb_t x) Returns the effective relative error of *x* measured in bits, defined as the difference between the position of the top bit in the radius and the top bit in the midpoint, plus one. The result is clamped between plus/minus *ARF_PREC_EXACT*. .. function:: slong arb_rel_accuracy_bits(const arb_t x) Returns the effective relative accuracy of *x* measured in bits, equal to the negative of the return value from :func:`arb_rel_error_bits`. .. function:: slong arb_rel_one_accuracy_bits(const arb_t x) Given a ball with midpoint *m* and radius *r*, returns an approximation of the relative accuracy of `[\max(1,|m|) \pm r]` measured in bits. .. function:: slong arb_bits(const arb_t x) Returns the number of bits needed to represent the absolute value of the mantissa of the midpoint of *x*, i.e. the minimum precision sufficient to represent *x* exactly. Returns 0 if the midpoint of *x* is a special value. .. function:: void arb_trim(arb_t y, const arb_t x) Sets *y* to a trimmed copy of *x*: rounds *x* to a number of bits equal to the accuracy of *x* (as indicated by its radius), plus a few guard bits. The resulting ball is guaranteed to contain *x*, but is more economical if *x* has less than full accuracy. .. function:: int arb_get_unique_fmpz(fmpz_t z, const arb_t x) If *x* contains a unique integer, sets *z* to that value and returns nonzero. Otherwise (if *x* represents no integers or more than one integer), returns zero. This method aborts if there is a unique integer but that integer is so large that allocating memory for the result fails. Warning: this method will allocate a huge amount of memory to store the result if there is a unique integer and that integer is huge. Memory allocation could succeed even if the required space is far larger than the physical memory available on the machine, resulting in swapping. It is recommended to check that the midpoint of *x* is within a reasonable range before calling this method. .. function:: void arb_floor(arb_t y, const arb_t x, slong prec) void arb_ceil(arb_t y, const arb_t x, slong prec) void arb_trunc(arb_t y, const arb_t x, slong prec) void arb_nint(arb_t y, const arb_t x, slong prec) Sets *y* to a ball containing respectively, `\lfloor x \rfloor` and `\lceil x \rceil`, `\operatorname{trunc}(x)`, `\operatorname{nint}(x)`, with the midpoint of *y* rounded to at most *prec* bits. .. function:: void arb_get_fmpz_mid_rad_10exp(fmpz_t mid, fmpz_t rad, fmpz_t exp, const arb_t x, slong n) Assuming that *x* is finite and not exactly zero, computes integers *mid*, *rad*, *exp* such that `x \in [m-r, m+r] \times 10^e` and such that the larger out of *mid* and *rad* has at least *n* digits plus a few guard digits. If *x* is infinite or exactly zero, the outputs are all set to zero. .. function:: int arb_can_round_arf(const arb_t x, slong prec, arf_rnd_t rnd) .. function:: int arb_can_round_mpfr(const arb_t x, slong prec, mpfr_rnd_t rnd) Returns nonzero if rounding the midpoint of *x* to *prec* bits in the direction *rnd* is guaranteed to give the unique correctly rounded floating-point approximation for the real number represented by *x*. In other words, if this function returns nonzero, applying :func:`arf_set_round`, or :func:`arf_get_mpfr`, or :func:`arf_get_d` to the midpoint of *x* is guaranteed to return a correctly rounded *arf_t*, *mpfr_t* (provided that *prec* is the precision of the output variable), or *double* (provided that *prec* is 53). Moreover, :func:`arf_get_mpfr` is guaranteed to return the correct ternary value according to MPFR semantics. Note that the *mpfr* version of this function takes an MPFR rounding mode symbol as input, while the *arf* version takes an *arf* rounding mode symbol. Otherwise, the functions are identical. This function may perform a fast, inexact test; that is, it may return zero in some cases even when correct rounding actually is possible. To be conservative, zero is returned when *x* is non-finite, even if it is an "exact" infinity. Comparisons ------------------------------------------------------------------------------- .. function:: int arb_is_zero(const arb_t x) Returns nonzero iff the midpoint and radius of *x* are both zero. .. function:: int arb_is_nonzero(const arb_t x) Returns nonzero iff zero is not contained in the interval represented by *x*. .. function:: int arb_is_one(const arb_t f) Returns nonzero iff *x* is exactly 1. .. function:: int arb_is_finite(const arb_t x) Returns nonzero iff the midpoint and radius of *x* are both finite floating-point numbers, i.e. not infinities or NaN. .. function:: int arb_is_exact(const arb_t x) Returns nonzero iff the radius of *x* is zero. .. function:: int arb_is_int(const arb_t x) Returns nonzero iff *x* is an exact integer. .. function:: int arb_is_int_2exp_si(const arb_t x, slong e) Returns nonzero iff *x* exactly equals `n 2^e` for some integer *n*. .. function:: int arb_equal(const arb_t x, const arb_t y) Returns nonzero iff *x* and *y* are equal as balls, i.e. have both the same midpoint and radius. Note that this is not the same thing as testing whether both *x* and *y* certainly represent the same real number, unless either *x* or *y* is exact (and neither contains NaN). To test whether both operands *might* represent the same mathematical quantity, use :func:`arb_overlaps` or :func:`arb_contains`, depending on the circumstance. .. function:: int arb_equal_si(const arb_t x, slong y) Returns nonzero iff *x* is equal to the integer *y*. .. function:: int arb_is_positive(const arb_t x) .. function:: int arb_is_nonnegative(const arb_t x) .. function:: int arb_is_negative(const arb_t x) .. function:: int arb_is_nonpositive(const arb_t x) Returns nonzero iff all points *p* in the interval represented by *x* satisfy, respectively, `p > 0`, `p \ge 0`, `p < 0`, `p \le 0`. If *x* contains NaN, returns zero. .. function:: int arb_overlaps(const arb_t x, const arb_t y) Returns nonzero iff *x* and *y* have some point in common. If either *x* or *y* contains NaN, this function always returns nonzero (as a NaN could be anything, it could in particular contain any number that is included in the other operand). .. function:: int arb_contains_arf(const arb_t x, const arf_t y) .. function:: int arb_contains_fmpq(const arb_t x, const fmpq_t y) .. function:: int arb_contains_fmpz(const arb_t x, const fmpz_t y) .. function:: int arb_contains_si(const arb_t x, slong y) .. function:: int arb_contains_mpfr(const arb_t x, const mpfr_t y) .. function:: int arb_contains(const arb_t x, const arb_t y) Returns nonzero iff the given number (or ball) *y* is contained in the interval represented by *x*. If *x* contains NaN, this function always returns nonzero (as it could represent anything, and in particular could represent all the points included in *y*). If *y* contains NaN and *x* does not, it always returns zero. .. function:: int arb_contains_int(const arb_t x) Returns nonzero iff the interval represented by *x* contains an integer. .. function:: int arb_contains_zero(const arb_t x) .. function:: int arb_contains_negative(const arb_t x) .. function:: int arb_contains_nonpositive(const arb_t x) .. function:: int arb_contains_positive(const arb_t x) .. function:: int arb_contains_nonnegative(const arb_t x) Returns nonzero iff there is any point *p* in the interval represented by *x* satisfying, respectively, `p = 0`, `p < 0`, `p \le 0`, `p > 0`, `p \ge 0`. If *x* contains NaN, returns nonzero. .. function:: int arb_contains_interior(const arb_t x, const arb_t y) Tests if *y* is contained in the interior of *x*; that is, contained in *x* and not touching either endpoint. .. function:: int arb_eq(const arb_t x, const arb_t y) .. function:: int arb_ne(const arb_t x, const arb_t y) .. function:: int arb_lt(const arb_t x, const arb_t y) .. function:: int arb_le(const arb_t x, const arb_t y) .. function:: int arb_gt(const arb_t x, const arb_t y) .. function:: int arb_ge(const arb_t x, const arb_t y) Respectively performs the comparison `x = y`, `x \ne y`, `x < y`, `x \le y`, `x > y`, `x \ge y` in a mathematically meaningful way. If the comparison `t \, (\operatorname{op}) \, u` holds for all `t \in x` and all `u \in y`, returns 1. Otherwise, returns 0. The balls *x* and *y* are viewed as subintervals of the extended real line. Note that balls that are formally different can compare as equal under this definition: for example, `[-\infty \pm 3] = [-\infty \pm 0]`. Also `[-\infty] \le [\infty \pm \infty]`. The output is always 0 if either input has NaN as midpoint. Arithmetic ------------------------------------------------------------------------------- .. function:: void arb_neg(arb_t y, const arb_t x) .. function:: void arb_neg_round(arb_t y, const arb_t x, slong prec) Sets *y* to the negation of *x*. .. function:: void arb_abs(arb_t y, const arb_t x) Sets *y* to the absolute value of *x*. No attempt is made to improve the interval represented by *x* if it contains zero. .. function:: void arb_nonnegative_abs(arb_t y, const arb_t x) Sets *y* to the absolute value of *x*. If *x* is finite and it contains zero, sets *y* to some interval `[r \pm r]` that contains the absolute value of *x*. .. function:: void arb_sgn(arb_t y, const arb_t x) Sets *y* to the sign function of *x*. The result is `[0 \pm 1]` if *x* contains both zero and nonzero numbers. .. function:: int arb_sgn_nonzero(const arb_t x) Returns 1 if *x* is strictly positive, -1 if *x* is strictly negative, and 0 if *x* is zero or a ball containing zero so that its sign is not determined. .. function:: void arb_min(arb_t z, const arb_t x, const arb_t y, slong prec) .. function:: void arb_max(arb_t z, const arb_t x, const arb_t y, slong prec) Sets *z* respectively to the minimum and the maximum of *x* and *y*. .. function:: void arb_minmax(arb_t z1, arb_t z2, const arb_t x, const arb_t y, slong prec) Sets *z1* and *z2* respectively to the minimum and the maximum of *x* and *y*. .. function:: void arb_add(arb_t z, const arb_t x, const arb_t y, slong prec) .. function:: void arb_add_arf(arb_t z, const arb_t x, const arf_t y, slong prec) .. function:: void arb_add_ui(arb_t z, const arb_t x, ulong y, slong prec) .. function:: void arb_add_si(arb_t z, const arb_t x, slong y, slong prec) .. function:: void arb_add_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) Sets `z = x + y`, rounded to *prec* bits. The precision can be *ARF_PREC_EXACT* provided that the result fits in memory. .. function:: void arb_add_fmpz_2exp(arb_t z, const arb_t x, const fmpz_t m, const fmpz_t e, slong prec) Sets `z = x + m \cdot 2^e`, rounded to *prec* bits. The precision can be *ARF_PREC_EXACT* provided that the result fits in memory. .. function:: void arb_sub(arb_t z, const arb_t x, const arb_t y, slong prec) .. function:: void arb_sub_arf(arb_t z, const arb_t x, const arf_t y, slong prec) .. function:: void arb_sub_ui(arb_t z, const arb_t x, ulong y, slong prec) .. function:: void arb_sub_si(arb_t z, const arb_t x, slong y, slong prec) .. function:: void arb_sub_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) Sets `z = x - y`, rounded to *prec* bits. The precision can be *ARF_PREC_EXACT* provided that the result fits in memory. .. function:: void arb_mul(arb_t z, const arb_t x, const arb_t y, slong prec) .. function:: void arb_mul_arf(arb_t z, const arb_t x, const arf_t y, slong prec) .. function:: void arb_mul_si(arb_t z, const arb_t x, slong y, slong prec) .. function:: void arb_mul_ui(arb_t z, const arb_t x, ulong y, slong prec) .. function:: void arb_mul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) Sets `z = x \cdot y`, rounded to *prec* bits. The precision can be *ARF_PREC_EXACT* provided that the result fits in memory. .. function:: void arb_mul_2exp_si(arb_t y, const arb_t x, slong e) .. function:: void arb_mul_2exp_fmpz(arb_t y, const arb_t x, const fmpz_t e) Sets *y* to *x* multiplied by `2^e`. .. function:: void arb_addmul(arb_t z, const arb_t x, const arb_t y, slong prec) .. function:: void arb_addmul_arf(arb_t z, const arb_t x, const arf_t y, slong prec) .. function:: void arb_addmul_si(arb_t z, const arb_t x, slong y, slong prec) .. function:: void arb_addmul_ui(arb_t z, const arb_t x, ulong y, slong prec) .. function:: void arb_addmul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) Sets `z = z + x \cdot y`, rounded to prec bits. The precision can be *ARF_PREC_EXACT* provided that the result fits in memory. .. function:: void arb_submul(arb_t z, const arb_t x, const arb_t y, slong prec) .. function:: void arb_submul_arf(arb_t z, const arb_t x, const arf_t y, slong prec) .. function:: void arb_submul_si(arb_t z, const arb_t x, slong y, slong prec) .. function:: void arb_submul_ui(arb_t z, const arb_t x, ulong y, slong prec) .. function:: void arb_submul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) Sets `z = z - x \cdot y`, rounded to prec bits. The precision can be *ARF_PREC_EXACT* provided that the result fits in memory. .. function:: void arb_fma(arb_t res, const arb_t x, const arb_t y, const arb_t z, slong prec) void arb_fma_arf(arb_t res, const arb_t x, const arf_t y, const arb_t z, slong prec) void arb_fma_si(arb_t res, const arb_t x, slong y, const arb_t z, slong prec) void arb_fma_ui(arb_t res, const arb_t x, ulong y, const arb_t z, slong prec) void arb_fma_fmpz(arb_t res, const arb_t x, const fmpz_t y, const arb_t z, slong prec) Sets *res* to `x \cdot y + z`. This is equivalent to an *addmul* except that *res* and *z* can be separate variables. .. function:: void arb_inv(arb_t z, const arb_t x, slong prec) Sets *z* to `1 / x`. .. function:: void arb_div(arb_t z, const arb_t x, const arb_t y, slong prec) .. function:: void arb_div_arf(arb_t z, const arb_t x, const arf_t y, slong prec) .. function:: void arb_div_si(arb_t z, const arb_t x, slong y, slong prec) .. function:: void arb_div_ui(arb_t z, const arb_t x, ulong y, slong prec) .. function:: void arb_div_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) .. function:: void arb_fmpz_div_fmpz(arb_t z, const fmpz_t x, const fmpz_t y, slong prec) .. function:: void arb_ui_div(arb_t z, ulong x, const arb_t y, slong prec) Sets `z = x / y`, rounded to *prec* bits. If *y* contains zero, *z* is set to `0 \pm \infty`. Otherwise, error propagation uses the rule .. math:: \left| \frac{x}{y} - \frac{x+\xi_1 a}{y+\xi_2 b} \right| = \left|\frac{x \xi_2 b - y \xi_1 a}{y (y+\xi_2 b)}\right| \le \frac{|xb|+|ya|}{|y| (|y|-b)} where `-1 \le \xi_1, \xi_2 \le 1`, and where the triangle inequality has been applied to the numerator and the reverse triangle inequality has been applied to the denominator. .. function:: void arb_div_2expm1_ui(arb_t z, const arb_t x, ulong n, slong prec) Sets `z = x / (2^n - 1)`, rounded to *prec* bits. Dot product ------------------------------------------------------------------------------- .. function:: void arb_dot_precise(arb_t res, const arb_t s, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) void arb_dot_simple(arb_t res, const arb_t s, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) void arb_dot(arb_t res, const arb_t s, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) Computes the dot product of the vectors *x* and *y*, setting *res* to `s + (-1)^{subtract} \sum_{i=0}^{len-1} x_i y_i`. The initial term *s* is optional and can be omitted by passing *NULL* (equivalently, `s = 0`). The parameter *subtract* must be 0 or 1. The length *len* is allowed to be negative, which is equivalent to a length of zero. The parameters *xstep* or *ystep* specify a step length for traversing subsequences of the vectors *x* and *y*; either can be negative to step in the reverse direction starting from the initial pointer. Aliasing is allowed between *res* and *s* but not between *res* and the entries of *x* and *y*. The default version determines the optimal precision for each term and performs all internal calculations using mpn arithmetic with minimal overhead. This is the preferred way to compute a dot product; it is generally much faster and more precise than a simple loop. The *simple* version performs fused multiply-add operations in a simple loop. This can be used for testing purposes and is also used as a fallback by the default version when the exponents are out of range for the optimized code. The *precise* version computes the dot product exactly up to the final rounding. This can be extremely slow and is only intended for testing. .. function:: void arb_approx_dot(arb_t res, const arb_t s, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) Computes an approximate dot product *without error bounds*. The radii of the inputs are ignored (only the midpoints are read) and only the midpoint of the output is written. .. function:: void arb_dot_ui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) void arb_dot_si(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const slong * y, slong ystep, slong len, slong prec) void arb_dot_uiui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) void arb_dot_siui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) void arb_dot_fmpz(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const fmpz * y, slong ystep, slong len, slong prec) Equivalent to :func:`arb_dot`, but with integers in the array *y*. The *uiui* and *siui* versions take an array of double-limb integers as input; the *siui* version assumes that these represent signed integers in two's complement form. Powers and roots ------------------------------------------------------------------------------- .. function:: void arb_sqrt(arb_t z, const arb_t x, slong prec) .. function:: void arb_sqrt_arf(arb_t z, const arf_t x, slong prec) .. function:: void arb_sqrt_fmpz(arb_t z, const fmpz_t x, slong prec) .. function:: void arb_sqrt_ui(arb_t z, ulong x, slong prec) Sets *z* to the square root of *x*, rounded to *prec* bits. If `x = m \pm x` where `m \ge r \ge 0`, the propagated error is bounded by `\sqrt{m} - \sqrt{m-r} = \sqrt{m} (1 - \sqrt{1 - r/m}) \le \sqrt{m} (r/m + (r/m)^2)/2`. .. function:: void arb_sqrtpos(arb_t z, const arb_t x, slong prec) Sets *z* to the square root of *x*, assuming that *x* represents a nonnegative number (i.e. discarding any negative numbers in the input interval). .. function:: void arb_hypot(arb_t z, const arb_t x, const arb_t y, slong prec) Sets *z* to `\sqrt{x^2 + y^2}`. .. function:: void arb_rsqrt(arb_t z, const arb_t x, slong prec) .. function:: void arb_rsqrt_ui(arb_t z, ulong x, slong prec) Sets *z* to the reciprocal square root of *x*, rounded to *prec* bits. At high precision, this is faster than computing a square root. .. function:: void arb_sqrt1pm1(arb_t z, const arb_t x, slong prec) Sets `z = \sqrt{1+x}-1`, computed accurately when `x \approx 0`. .. function:: void arb_root_ui(arb_t z, const arb_t x, ulong k, slong prec) Sets *z* to the *k*-th root of *x*, rounded to *prec* bits. This function selects between different algorithms. For large *k*, it evaluates `\exp(\log(x)/k)`. For small *k*, it uses :func:`arf_root` at the midpoint and computes a propagated error bound as follows: if input interval is `[m-r, m+r]` with `r \le m`, the error is largest at `m-r` where it satisfies .. math:: m^{1/k} - (m-r)^{1/k} = m^{1/k} [1 - (1-r/m)^{1/k}] = m^{1/k} [1 - \exp(\log(1-r/m)/k)] \le m^{1/k} \min(1, -\log(1-r/m)/k) = m^{1/k} \min(1, \log(1+r/(m-r))/k). This is evaluated using :func:`mag_log1p`. .. function:: void arb_root(arb_t z, const arb_t x, ulong k, slong prec) Alias for :func:`arb_root_ui`, provided for backwards compatibility. .. function:: void arb_sqr(arb_t y, const arb_t x, slong prec) Sets *y* to be the square of *x*. .. function:: void arb_pow_fmpz_binexp(arb_t y, const arb_t b, const fmpz_t e, slong prec) .. function:: void arb_pow_fmpz(arb_t y, const arb_t b, const fmpz_t e, slong prec) .. function:: void arb_pow_ui(arb_t y, const arb_t b, ulong e, slong prec) .. function:: void arb_ui_pow_ui(arb_t y, ulong b, ulong e, slong prec) .. function:: void arb_si_pow_ui(arb_t y, slong b, ulong e, slong prec) Sets `y = b^e` using binary exponentiation (with an initial division if `e < 0`). Provided that *b* and *e* are small enough and the exponent is positive, the exact power can be computed by setting the precision to *ARF_PREC_EXACT*. Note that these functions can get slow if the exponent is extremely large (in such cases :func:`arb_pow` may be superior). .. function:: void arb_pow_fmpq(arb_t y, const arb_t x, const fmpq_t a, slong prec) Sets `y = b^e`, computed as `y = (b^{1/q})^p` if the denominator of `e = p/q` is small, and generally as `y = \exp(e \log b)`. Note that this function can get slow if the exponent is extremely large (in such cases :func:`arb_pow` may be superior). .. function:: void arb_pow(arb_t z, const arb_t x, const arb_t y, slong prec) Sets `z = x^y`, computed using binary exponentiation if `y` is a small exact integer, as `z = (x^{1/2})^{2y}` if `y` is a small exact half-integer, and generally as `z = \exp(y \log x)`, except giving the obvious finite result if `x` is `a \pm a` and `y` is positive. Exponentials and logarithms ------------------------------------------------------------------------------- .. function:: void arb_log_ui(arb_t z, ulong x, slong prec) .. function:: void arb_log_fmpz(arb_t z, const fmpz_t x, slong prec) .. function:: void arb_log_arf(arb_t z, const arf_t x, slong prec) .. function:: void arb_log(arb_t z, const arb_t x, slong prec) Sets `z = \log(x)`. At low to medium precision (up to about 4096 bits), :func:`arb_log_arf` uses table-based argument reduction and fast Taylor series evaluation via :func:`_arb_atan_taylor_rs`. At high precision, it falls back to MPFR. The function :func:`arb_log` simply calls :func:`arb_log_arf` with the midpoint as input, and separately adds the propagated error. .. function:: void arb_log_ui_from_prev(arb_t log_k1, ulong k1, arb_t log_k0, ulong k0, slong prec) Computes `\log(k_1)`, given `\log(k_0)` where `k_0 < k_1`. At high precision, this function uses the formula `\log(k_1) = \log(k_0) + 2 \operatorname{atanh}((k_1-k_0)/(k_1+k_0))`, evaluating the inverse hyperbolic tangent using binary splitting (for best efficiency, `k_0` should be large and `k_1 - k_0` should be small). Otherwise, it ignores `\log(k_0)` and evaluates the logarithm the usual way. .. function:: void arb_log1p(arb_t z, const arb_t x, slong prec) Sets `z = \log(1+x)`, computed accurately when `x \approx 0`. .. function:: void arb_log_base_ui(arb_t res, const arb_t x, ulong b, slong prec) Sets *res* to `\log_b(x)`. The result is computed exactly when possible. .. function:: void arb_log_hypot(arb_t res, const arb_t x, const arb_t y, slong prec) Sets *res* to `\log(\sqrt{x^2+y^2})`. .. function:: void arb_exp(arb_t z, const arb_t x, slong prec) Sets `z = \exp(x)`. Error propagation is done using the following rule: assuming `x = m \pm r`, the error is largest at `m + r`, and we have `\exp(m+r) - \exp(m) = \exp(m) (\exp(r)-1) \le r \exp(m+r)`. .. function:: void arb_expm1(arb_t z, const arb_t x, slong prec) Sets `z = \exp(x)-1`, using a more accurate method when `x \approx 0`. .. function:: void arb_exp_invexp(arb_t z, arb_t w, const arb_t x, slong prec) Sets `z = \exp(x)` and `w = \exp(-x)`. The second exponential is computed from the first using a division, but propagated error bounds are computed separately. Trigonometric functions ------------------------------------------------------------------------------- .. function:: void arb_sin(arb_t s, const arb_t x, slong prec) .. function:: void arb_cos(arb_t c, const arb_t x, slong prec) .. function:: void arb_sin_cos(arb_t s, arb_t c, const arb_t x, slong prec) Sets `s = \sin(x)`, `c = \cos(x)`. .. function:: void arb_sin_pi(arb_t s, const arb_t x, slong prec) .. function:: void arb_cos_pi(arb_t c, const arb_t x, slong prec) .. function:: void arb_sin_cos_pi(arb_t s, arb_t c, const arb_t x, slong prec) Sets `s = \sin(\pi x)`, `c = \cos(\pi x)`. .. function:: void arb_tan(arb_t y, const arb_t x, slong prec) Sets `y = \tan(x) = \sin(x) / \cos(y)`. .. function:: void arb_cot(arb_t y, const arb_t x, slong prec) Sets `y = \cot(x) = \cos(x) / \sin(y)`. .. function:: void arb_sin_cos_pi_fmpq(arb_t s, arb_t c, const fmpq_t x, slong prec) .. function:: void arb_sin_pi_fmpq(arb_t s, const fmpq_t x, slong prec) .. function:: void arb_cos_pi_fmpq(arb_t c, const fmpq_t x, slong prec) Sets `s = \sin(\pi x)`, `c = \cos(\pi x)` where `x` is a rational number (whose numerator and denominator are assumed to be reduced). We first use trigonometric symmetries to reduce the argument to the octant `[0, 1/4]`. Then we either multiply by a numerical approximation of `\pi` and evaluate the trigonometric function the usual way, or we use algebraic methods, depending on which is estimated to be faster. Since the argument has been reduced to the first octant, the first of these two methods gives full accuracy even if the original argument is close to some root other the origin. .. function:: void arb_tan_pi(arb_t y, const arb_t x, slong prec) Sets `y = \tan(\pi x)`. .. function:: void arb_cot_pi(arb_t y, const arb_t x, slong prec) Sets `y = \cot(\pi x)`. .. function:: void arb_sec(arb_t res, const arb_t x, slong prec) Computes `\sec(x) = 1 / \cos(x)`. .. function:: void arb_csc(arb_t res, const arb_t x, slong prec) Computes `\csc(x) = 1 / \sin(x)`. .. function:: void arb_csc_pi(arb_t res, const arb_t x, slong prec) Computes `\csc(\pi x) = 1 / \sin(\pi x)`. .. function:: void arb_sinc(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{sinc}(x) = \sin(x) / x`. .. function:: void arb_sinc_pi(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{sinc}(\pi x) = \sin(\pi x) / (\pi x)`. Inverse trigonometric functions ------------------------------------------------------------------------------- .. function:: void arb_atan_arf(arb_t z, const arf_t x, slong prec) .. function:: void arb_atan(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{atan}(x)`. At low to medium precision (up to about 4096 bits), :func:`arb_atan_arf` uses table-based argument reduction and fast Taylor series evaluation via :func:`_arb_atan_taylor_rs`. At high precision, it falls back to MPFR. The function :func:`arb_atan` simply calls :func:`arb_atan_arf` with the midpoint as input, and separately adds the propagated error. The function :func:`arb_atan_arf` uses lookup tables if possible, and otherwise falls back to :func:`arb_atan_arf_bb`. .. function:: void arb_atan2(arb_t z, const arb_t b, const arb_t a, slong prec) Sets *r* to an the argument (phase) of the complex number `a + bi`, with the branch cut discontinuity on `(-\infty,0]`. We define `\operatorname{atan2}(0,0) = 0`, and for `a < 0`, `\operatorname{atan2}(0,a) = \pi`. .. function:: void arb_asin(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{asin}(x) = \operatorname{atan}(x / \sqrt{1-x^2})`. If `x` is not contained in the domain `[-1,1]`, the result is an indeterminate interval. .. function:: void arb_acos(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{acos}(x) = \pi/2 - \operatorname{asin}(x)`. If `x` is not contained in the domain `[-1,1]`, the result is an indeterminate interval. Hyperbolic functions ------------------------------------------------------------------------------- .. function:: void arb_sinh(arb_t s, const arb_t x, slong prec) .. function:: void arb_cosh(arb_t c, const arb_t x, slong prec) .. function:: void arb_sinh_cosh(arb_t s, arb_t c, const arb_t x, slong prec) Sets `s = \sinh(x)`, `c = \cosh(x)`. If the midpoint of `x` is close to zero and the hyperbolic sine is to be computed, evaluates `(e^{2x}\pm1) / (2e^x)` via :func:`arb_expm1` to avoid loss of accuracy. Otherwise evaluates `(e^x \pm e^{-x}) / 2`. .. function:: void arb_tanh(arb_t y, const arb_t x, slong prec) Sets `y = \tanh(x) = \sinh(x) / \cosh(x)`, evaluated via :func:`arb_expm1` as `\tanh(x) = (e^{2x} - 1) / (e^{2x} + 1)` if `|x|` is small, and as `\tanh(\pm x) = 1 - 2 e^{\mp 2x} / (1 + e^{\mp 2x})` if `|x|` is large. .. function:: void arb_coth(arb_t y, const arb_t x, slong prec) Sets `y = \coth(x) = \cosh(x) / \sinh(x)`, evaluated using the same strategy as :func:`arb_tanh`. .. function:: void arb_sech(arb_t res, const arb_t x, slong prec) Computes `\operatorname{sech}(x) = 1 / \cosh(x)`. .. function:: void arb_csch(arb_t res, const arb_t x, slong prec) Computes `\operatorname{csch}(x) = 1 / \sinh(x)`. Inverse hyperbolic functions ------------------------------------------------------------------------------- .. function:: void arb_atanh(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{atanh}(x)`. .. function:: void arb_asinh(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{asinh}(x)`. .. function:: void arb_acosh(arb_t z, const arb_t x, slong prec) Sets `z = \operatorname{acosh}(x)`. If `x < 1`, the result is an indeterminate interval. Constants ------------------------------------------------------------------------------- The following functions cache the computed values to speed up repeated calls at the same or lower precision. For further implementation details, see :ref:`algorithms_constants`. .. function:: void arb_const_pi(arb_t z, slong prec) Computes `\pi`. .. function:: void arb_const_sqrt_pi(arb_t z, slong prec) Computes `\sqrt{\pi}`. .. function:: void arb_const_log_sqrt2pi(arb_t z, slong prec) Computes `\log \sqrt{2 \pi}`. .. function:: void arb_const_log2(arb_t z, slong prec) Computes `\log(2)`. .. function:: void arb_const_log10(arb_t z, slong prec) Computes `\log(10)`. .. function:: void arb_const_euler(arb_t z, slong prec) Computes Euler's constant `\gamma = \lim_{k \rightarrow \infty} (H_k - \log k)` where `H_k = 1 + 1/2 + \ldots + 1/k`. .. function:: void arb_const_catalan(arb_t z, slong prec) Computes Catalan's constant `C = \sum_{n=0}^{\infty} (-1)^n / (2n+1)^2`. .. function:: void arb_const_e(arb_t z, slong prec) Computes `e = \exp(1)`. .. function:: void arb_const_khinchin(arb_t z, slong prec) Computes Khinchin's constant `K_0`. .. function:: void arb_const_glaisher(arb_t z, slong prec) Computes the Glaisher-Kinkelin constant `A = \exp(1/12 - \zeta'(-1))`. .. function:: void arb_const_apery(arb_t z, slong prec) Computes Apery's constant `\zeta(3)`. .. function:: void arb_const_reciprocal_fibonacci(arb_t z, slong prec) Computes the reciprocal Fibonacci constant `\sum_{n=1}^{\infty} 1/F_n`. Lambert W function ------------------------------------------------------------------------------- .. function:: void arb_lambertw(arb_t res, const arb_t x, int flags, slong prec) Computes the Lambert W function, which solves the equation `w e^w = x`. The Lambert W function has infinitely many complex branches `W_k(x)`, two of which are real on a part of the real line. The principal branch `W_0(x)` is selected by setting *flags* to 0, and the `W_{-1}` branch is selected by setting *flags* to 1. The principal branch is real-valued for `x \ge -1/e` (taking values in `[-1,+\infty)`) and the `W_{-1}` branch is real-valued for `-1/e \le x < 0` and takes values in `(-\infty,-1]`. Elsewhere, the Lambert W function is complex and :func:`acb_lambertw` should be used. The implementation first computes a floating-point approximation heuristically and then computes a rigorously certified enclosure around this approximation. Some asymptotic cases are handled specially. The algorithm used to compute the Lambert W function is described in [Joh2017b]_, which follows the main ideas in [CGHJK1996]_. Gamma function and factorials ------------------------------------------------------------------------------- .. function:: void arb_rising_ui(arb_t z, const arb_t x, ulong n, slong prec) void arb_rising(arb_t z, const arb_t x, const arb_t n, slong prec) Computes the rising factorial `z = x (x+1) (x+2) \cdots (x+n-1)`. These functions are aliases for :func:`arb_hypgeom_rising_ui` and :func:`arb_hypgeom_rising`. .. function:: void arb_rising_fmpq_ui(arb_t z, const fmpq_t x, ulong n, slong prec) Computes the rising factorial `z = x (x+1) (x+2) \cdots (x+n-1)` using binary splitting. If the denominator or numerator of *x* is large compared to *prec*, it is more efficient to convert *x* to an approximation and use :func:`arb_rising_ui`. .. function:: void arb_rising2_ui(arb_t u, arb_t v, const arb_t x, ulong n, slong prec) Letting `u(x) = x (x+1) (x+2) \cdots (x+n-1)`, simultaneously compute `u(x)` and `v(x) = u'(x)`. This function is a wrapper of :func:`arb_hypgeom_rising_ui_jet`. .. function:: void arb_fac_ui(arb_t z, ulong n, slong prec) Computes the factorial `z = n!` via the gamma function. .. function:: void arb_doublefac_ui(arb_t z, ulong n, slong prec) Computes the double factorial `z = n!!` via the gamma function. .. function:: void arb_bin_ui(arb_t z, const arb_t n, ulong k, slong prec) .. function:: void arb_bin_uiui(arb_t z, ulong n, ulong k, slong prec) Computes the binomial coefficient `z = {n \choose k}`, via the rising factorial as `{n \choose k} = (n-k+1)_k / k!`. .. function:: void arb_gamma(arb_t z, const arb_t x, slong prec) void arb_gamma_fmpq(arb_t z, const fmpq_t x, slong prec) void arb_gamma_fmpz(arb_t z, const fmpz_t x, slong prec) Computes the gamma function `z = \Gamma(x)`. These functions are aliases for :func:`arb_hypgeom_gamma`, :func:`arb_hypgeom_gamma_fmpq`, :func:`arb_hypgeom_gamma_fmpz`. .. function:: void arb_lgamma(arb_t z, const arb_t x, slong prec) Computes the logarithmic gamma function `z = \log \Gamma(x)`. The complex branch structure is assumed, so if `x \le 0`, the result is an indeterminate interval. This function is an alias for :func:`arb_hypgeom_lgamma`. .. function:: void arb_rgamma(arb_t z, const arb_t x, slong prec) Computes the reciprocal gamma function `z = 1/\Gamma(x)`, avoiding division by zero at the poles of the gamma function. This function is an alias for :func:`arb_hypgeom_rgamma`. .. function:: void arb_digamma(arb_t y, const arb_t x, slong prec) Computes the digamma function `z = \psi(x) = (\log \Gamma(x))' = \Gamma'(x) / \Gamma(x)`. Zeta function ------------------------------------------------------------------------------- .. function:: void arb_zeta_ui_vec_borwein(arb_ptr z, ulong start, slong num, ulong step, slong prec) Evaluates `\zeta(s)` at `\mathrm{num}` consecutive integers *s* beginning with *start* and proceeding in increments of *step*. Uses Borwein's formula ([Bor2000]_, [GS2003]_), implemented to support fast multi-evaluation (but also works well for a single *s*). Requires `\mathrm{start} \ge 2`. For efficiency, the largest *s* should be at most about as large as *prec*. Arguments approaching *LONG_MAX* will cause overflows. One should therefore only use this function for *s* up to about *prec*, and then switch to the Euler product. The algorithm for single *s* is basically identical to the one used in MPFR (see [MPFR2012]_ for a detailed description). In particular, we evaluate the sum backwards to avoid storing more than one `d_k` coefficient, and use integer arithmetic throughout since it is convenient and the terms turn out to be slightly larger than `2^\mathrm{prec}`. The only numerical error in the main loop comes from the division by `k^s`, which adds less than 1 unit of error per term. For fast multi-evaluation, we repeatedly divide by `k^{\mathrm{step}}`. Each division reduces the input error and adds at most 1 unit of additional rounding error, so by induction, the error per term is always smaller than 2 units. .. function:: void arb_zeta_ui_asymp(arb_t x, ulong s, slong prec) .. function:: void arb_zeta_ui_euler_product(arb_t z, ulong s, slong prec) Computes `\zeta(s)` using the Euler product. This is fast only if *s* is large compared to the precision. Both methods are trivial wrappers for :func:`_acb_dirichlet_euler_product_real_ui`. .. function:: void arb_zeta_ui_bernoulli(arb_t x, ulong s, slong prec) Computes `\zeta(s)` for even *s* via the corresponding Bernoulli number. .. function:: void arb_zeta_ui_borwein_bsplit(arb_t x, ulong s, slong prec) Computes `\zeta(s)` for arbitrary `s \ge 2` using a binary splitting implementation of Borwein's algorithm. This has quasilinear complexity with respect to the precision (assuming that `s` is fixed). .. function:: void arb_zeta_ui_vec(arb_ptr x, ulong start, slong num, slong prec) .. function:: void arb_zeta_ui_vec_even(arb_ptr x, ulong start, slong num, slong prec) .. function:: void arb_zeta_ui_vec_odd(arb_ptr x, ulong start, slong num, slong prec) Computes `\zeta(s)` at *num* consecutive integers (respectively *num* even or *num* odd integers) beginning with `s = \mathrm{start} \ge 2`, automatically choosing an appropriate algorithm. .. function:: void arb_zeta_ui(arb_t x, ulong s, slong prec) Computes `\zeta(s)` for nonnegative integer `s \ne 1`, automatically choosing an appropriate algorithm. This function is intended for numerical evaluation of isolated zeta values; for multi-evaluation, the vector versions are more efficient. .. function:: void arb_zeta(arb_t z, const arb_t s, slong prec) Sets *z* to the value of the Riemann zeta function `\zeta(s)`. For computing derivatives with respect to `s`, use :func:`arb_poly_zeta_series`. .. function:: void arb_hurwitz_zeta(arb_t z, const arb_t s, const arb_t a, slong prec) Sets *z* to the value of the Hurwitz zeta function `\zeta(s,a)`. For computing derivatives with respect to `s`, use :func:`arb_poly_zeta_series`. Bernoulli numbers and polynomials ------------------------------------------------------------------------------- .. function:: void arb_bernoulli_ui(arb_t b, ulong n, slong prec) .. function:: void arb_bernoulli_fmpz(arb_t b, const fmpz_t n, slong prec) Sets `b` to the numerical value of the Bernoulli number `B_n` approximated to *prec* bits. The internal precision is increased automatically to give an accurate result. Note that, with huge *fmpz* input, the output will have a huge exponent and evaluation will accordingly be slower. A single division from the exact fraction of `B_n` is used if this value is in the global cache or the exact numerator roughly is larger than *prec* bits. Otherwise, the Riemann zeta function is used (see :func:`arb_bernoulli_ui_zeta`). This function reads `B_n` from the global cache if the number is already cached, but does not automatically extend the cache by itself. .. function:: void arb_bernoulli_ui_zeta(arb_t b, ulong n, slong prec) Sets `b` to the numerical value of `B_n` accurate to *prec* bits, computed using the formula `B_{2n} = (-1)^{n+1} 2 (2n)! \zeta(2n) / (2 \pi)^n`. To avoid potential infinite recursion, we explicitly call the Euler product implementation of the zeta function. This method will only give high accuracy if the precision is small enough compared to `n` for the Euler product to converge rapidly. .. function:: void arb_bernoulli_poly_ui(arb_t res, ulong n, const arb_t x, slong prec) Sets *res* to the value of the Bernoulli polynomial `B_n(x)`. Warning: this function is only fast if either *n* or *x* is a small integer. This function reads Bernoulli numbers from the global cache if they are already cached, but does not automatically extend the cache by itself. .. function:: void arb_power_sum_vec(arb_ptr res, const arb_t a, const arb_t b, slong len, slong prec) For *n* from 0 to *len* - 1, sets entry *n* in the output vector *res* to .. math:: S_n(a,b) = \frac{1}{n+1}\left(B_{n+1}(b) - B_{n+1}(a)\right) where `B_n(x)` is a Bernoulli polynomial. If *a* and *b* are integers and `b \ge a`, this is equivalent to .. math:: S_n(a,b) = \sum_{k=a}^{b-1} k^n. The computation uses the generating function for Bernoulli polynomials. Polylogarithms ------------------------------------------------------------------------------- .. function:: void arb_polylog(arb_t w, const arb_t s, const arb_t z, slong prec) .. function:: void arb_polylog_si(arb_t w, slong s, const arb_t z, slong prec) Sets *w* to the polylogarithm `\operatorname{Li}_s(z)`. Other special functions ------------------------------------------------------------------------------- .. function:: void arb_fib_fmpz(arb_t z, const fmpz_t n, slong prec) void arb_fib_ui(arb_t z, ulong n, slong prec) Computes the Fibonacci number `F_n` using binary squaring. .. function:: void arb_agm(arb_t z, const arb_t x, const arb_t y, slong prec) Sets *z* to the arithmetic-geometric mean of *x* and *y*. .. function:: void arb_chebyshev_t_ui(arb_t a, ulong n, const arb_t x, slong prec) .. function:: void arb_chebyshev_u_ui(arb_t a, ulong n, const arb_t x, slong prec) Evaluates the Chebyshev polynomial of the first kind `a = T_n(x)` or the Chebyshev polynomial of the second kind `a = U_n(x)`. .. function:: void arb_chebyshev_t2_ui(arb_t a, arb_t b, ulong n, const arb_t x, slong prec) .. function:: void arb_chebyshev_u2_ui(arb_t a, arb_t b, ulong n, const arb_t x, slong prec) Simultaneously evaluates `a = T_n(x), b = T_{n-1}(x)` or `a = U_n(x), b = U_{n-1}(x)`. Aliasing between *a*, *b* and *x* is not permitted. .. function:: void arb_bell_sum_bsplit(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, slong prec) .. function:: void arb_bell_sum_taylor(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, slong prec) Helper functions for Bell numbers, evaluating the sum `\sum_{k=a}^{b-1} k^n / k!`. If *mmag* is non-NULL, it may be used to indicate that the target error tolerance should be `2^{mmag - prec}`. .. function:: void arb_bell_fmpz(arb_t res, const fmpz_t n, slong prec) .. function:: void arb_bell_ui(arb_t res, ulong n, slong prec) Sets *res* to the Bell number `B_n`. If the number is too large to fit exactly in *prec* bits, a numerical approximation is computed efficiently. The algorithm to compute Bell numbers, including error analysis, is described in detail in [Joh2015]_. .. function:: void arb_euler_number_fmpz(arb_t res, const fmpz_t n, slong prec) void arb_euler_number_ui(arb_t res, ulong n, slong prec) Sets *res* to the Euler number `E_n`, which is defined by the exponential generating function `1 / \cosh(x)`. The result will be exact if `E_n` is exactly representable at the requested precision. .. function:: void arb_fmpz_euler_number_ui_multi_mod(fmpz_t res, ulong n, double alpha) void arb_fmpz_euler_number_ui(fmpz_t res, ulong n) Computes the Euler number `E_n` as an exact integer. The default algorithm uses a table lookup, the Dirichlet beta function or a hybrid modular algorithm depending on the size of *n*. The *multi_mod* algorithm accepts a tuning parameter *alpha* which can be set to a negative value to use defaults. .. function:: void arb_partitions_fmpz(arb_t res, const fmpz_t n, slong prec) .. function:: void arb_partitions_ui(arb_t res, ulong n, slong prec) Sets *res* to the partition function `p(n)`. When *n* is large and `\log_2 p(n)` is more than twice *prec*, the leading term in the Hardy-Ramanujan asymptotic series is used together with an error bound. Otherwise, the exact value is computed and rounded. .. function:: void arb_primorial_nth_ui(arb_t res, ulong n, slong prec) Sets *res* to the *nth* primorial, defined as the product of the first *n* prime numbers. The running time is quasilinear in *n*. .. function:: void arb_primorial_ui(arb_t res, ulong n, slong prec) Sets *res* to the primorial defined as the product of the positive integers up to and including *n*. The running time is quasilinear in *n*. Internals for computing elementary functions ------------------------------------------------------------------------------- .. function:: void _arb_atan_taylor_naive(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int alternating) .. function:: void _arb_atan_taylor_rs(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int alternating) Computes an approximation of `y = \sum_{k=0}^{N-1} x^{2k+1} / (2k+1)` (if *alternating* is 0) or `y = \sum_{k=0}^{N-1} (-1)^k x^{2k+1} / (2k+1)` (if *alternating* is 1). Used internally for computing arctangents and logarithms. The *naive* version uses the forward recurrence, and the *rs* version uses a division-avoiding rectangular splitting scheme. Requires `N \le 255`, `0 \le x \le 1/16`, and *xn* positive. The input *x* and output *y* are fixed-point numbers with *xn* fractional limbs. A bound for the ulp error is written to *error*. .. function:: void _arb_exp_taylor_naive(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N) .. function:: void _arb_exp_taylor_rs(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N) Computes an approximation of `y = \sum_{k=0}^{N-1} x^k / k!`. Used internally for computing exponentials. The *naive* version uses the forward recurrence, and the *rs* version uses a division-avoiding rectangular splitting scheme. Requires `N \le 287`, `0 \le x \le 1/16`, and *xn* positive. The input *x* is a fixed-point number with *xn* fractional limbs, and the output *y* is a fixed-point number with *xn* fractional limbs plus one extra limb for the integer part of the result. A bound for the ulp error is written to *error*. .. function:: void _arb_sin_cos_taylor_naive(mp_ptr ysin, mp_ptr ycos, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N) .. function:: void _arb_sin_cos_taylor_rs(mp_ptr ysin, mp_ptr ycos, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int sinonly, int alternating) Computes approximations of `y_s = \sum_{k=0}^{N-1} (-1)^k x^{2k+1} / (2k+1)!` and `y_c = \sum_{k=0}^{N-1} (-1)^k x^{2k} / (2k)!`. Used internally for computing sines and cosines. The *naive* version uses the forward recurrence, and the *rs* version uses a division-avoiding rectangular splitting scheme. Requires `N \le 143`, `0 \le x \le 1/16`, and *xn* positive. The input *x* and outputs *ysin*, *ycos* are fixed-point numbers with *xn* fractional limbs. A bound for the ulp error is written to *error*. If *sinonly* is 1, only the sine is computed; if *sinonly* is 0 both the sine and cosine are computed. To compute sin and cos, *alternating* should be 1. If *alternating* is 0, the hyperbolic sine is computed (this is currently only intended to be used together with *sinonly*). .. function:: int _arb_get_mpn_fixed_mod_log2(mp_ptr w, fmpz_t q, mp_limb_t * error, const arf_t x, mp_size_t wn) Attempts to write `w = x - q \log(2)` with `0 \le w < \log(2)`, where *w* is a fixed-point number with *wn* limbs and ulp error *error*. Returns success. .. function:: int _arb_get_mpn_fixed_mod_pi4(mp_ptr w, fmpz_t q, int * octant, mp_limb_t * error, const arf_t x, mp_size_t wn) Attempts to write `w = |x| - q \pi/4` with `0 \le w < \pi/4`, where *w* is a fixed-point number with *wn* limbs and ulp error *error*. Returns success. The value of *q* mod 8 is written to *octant*. The output variable *q* can be NULL, in which case the full value of *q* is not stored. .. function:: slong _arb_exp_taylor_bound(slong mag, slong prec) Returns *n* such that `\left|\sum_{k=n}^{\infty} x^k / k!\right| \le 2^{-\mathrm{prec}}`, assuming `|x| \le 2^{\mathrm{mag}} \le 1/4`. .. function:: void arb_exp_arf_bb(arb_t z, const arf_t x, slong prec, int m1) Computes the exponential function using the bit-burst algorithm. If *m1* is nonzero, the exponential function minus one is computed accurately. Aborts if *x* is extremely small or large (where another algorithm should be used). For large *x*, repeated halving is used. In fact, we always do argument reduction until `|x|` is smaller than about `2^{-d}` where `d \approx 16` to speed up convergence. If `|x| \approx 2^m`, we thus need about `m+d` squarings. Computing `\log(2)` costs roughly 100-200 multiplications, so is not usually worth the effort at very high precision. However, this function could be improved by using `\log(2)` based reduction at precision low enough that the value can be assumed to be cached. .. function:: void _arb_exp_sum_bs_simple(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) .. function:: void _arb_exp_sum_bs_powtab(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) Computes *T*, *Q* and *Qexp* such that `T / (Q 2^{\text{Qexp}}) = \sum_{k=1}^N (x/2^r)^k/k!` using binary splitting. Note that the sum is taken to *N* inclusive and omits the constant term. The *powtab* version precomputes a table of powers of *x*, resulting in slightly higher memory usage but better speed. For best efficiency, *N* should have many trailing zero bits. .. function:: void arb_exp_arf_rs_generic(arb_t res, const arf_t x, slong prec, int minus_one) Computes the exponential function using a generic version of the rectangular splitting strategy, intended for intermediate precision. .. function:: void _arb_atan_sum_bs_simple(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) .. function:: void _arb_atan_sum_bs_powtab(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) Computes *T*, *Q* and *Qexp* such that `T / (Q 2^{\text{Qexp}}) = \sum_{k=1}^N (-1)^k (x/2^r)^{2k} / (2k+1)` using binary splitting. Note that the sum is taken to *N* inclusive, omits the linear term, and requires a final multiplication by `(x/2^r)` to give the true series for atan. The *powtab* version precomputes a table of powers of *x*, resulting in slightly higher memory usage but better speed. For best efficiency, *N* should have many trailing zero bits. .. function:: void arb_atan_arf_bb(arb_t z, const arf_t x, slong prec) Computes the arctangent of *x*. Initially, the argument-halving formula .. math:: \operatorname{atan}(x) = 2 \operatorname{atan}\left(\frac{x}{1+\sqrt{1+x^2}}\right) is applied up to 8 times to get a small argument. Then a version of the bit-burst algorithm is used. The functional equation .. math:: \operatorname{atan}(x) = \operatorname{atan}(p/q) + \operatorname{atan}(w), \quad w = \frac{qx-p}{px+q}, \quad p = \lfloor qx \rfloor is applied repeatedly instead of integrating a differential equation for the arctangent, as this appears to be more efficient. .. function:: void arb_atan_frac_bsplit(arb_t s, const fmpz_t p, const fmpz_t q, int hyperbolic, slong prec) Computes the arctangent of `p/q`, optionally the hyperbolic arctangent, using direct series summation with binary splitting. .. function:: void arb_sin_cos_arf_generic(arb_t s, arb_t c, const arf_t x, slong prec) Computes the sine and cosine of *x* using a generic strategy. This function gets called internally by the main sin and cos functions when the precision for argument reduction or series evaluation based on lookup tables is exhausted. This function first performs a cheap test to see if `|x| < \pi / 2 - \varepsilon`. If the test fails, it uses `\pi` to reduce the argument to the first octant, and then evaluates the sin and cos functions recursively (this call cannot result in infinite recursion). If no argument reduction is needed, this function uses a generic version of the rectangular splitting algorithm if the precision is not too high, and otherwise invokes the asymptotically fast bit-burst algorithm. .. function:: void arb_sin_cos_arf_bb(arb_t s, arb_t c, const arf_t x, slong prec) Computes the sine and cosine of *x* using the bit-burst algorithm. It is required that `|x| < \pi / 2` (this is not checked). .. function:: void arb_sin_cos_wide(arb_t s, arb_t c, const arb_t x, slong prec) Computes an accurate enclosure (with both endpoints optimal to within about `2^{-30}` as afforded by the radius format) of the range of sine and cosine on a given wide interval. The computation is done by evaluating the sine and cosine at the interval endpoints and determining whether peaks of -1 or 1 occur between the endpoints. The interval is then converted back to a ball. The internal computations are done with doubles, using a simple floating-point algorithm to approximate the sine and cosine. It is easy to see that the cumulative errors in this algorithm add up to less than `2^{-30}`, with the dominant source of error being a single approximate reduction by `\pi/2`. This reduction is done safely using doubles up to a magnitude of about `2^{20}`. For larger arguments, a slower reduction using :type:`arb_t` arithmetic is done as a preprocessing step. .. function:: void arb_sin_cos_generic(arb_t s, arb_t c, const arb_t x, slong prec) Computes the sine and cosine of *x* by taking care of various special cases and computing the propagated error before calling :func:`arb_sin_cos_arf_generic`. This is used as a fallback inside :func:`arb_sin_cos` to take care of all cases without a fast path in that function. .. function:: void arb_log_primes_vec_bsplit(arb_ptr res, slong n, slong prec) Sets *res* to a vector containing the natural logarithms of the first *n* prime numbers, computed using binary splitting applied to simultaneous Machine-type formulas. This function is not optimized for large *n* or small *prec*. .. macro:: ARB_LOG_PRIME_CACHE_NUM Number of logarithms of small prime numbers to cache automatically. .. macro:: ARB_LOG_REDUCTION_DEFAULT_MAX_PREC Maximum precision to cache logarithms of small prime numbers automatically. .. function:: void _arb_log_p_ensure_cached(slong prec) Ensure that the internal cache of logarithms of small prime numbers has entries to at least *prec* bits. .. function:: void arb_exp_arf_log_reduction(arb_t res, const arf_t x, slong prec, int minus_one) Computes the exponential function using log reduction. .. function:: void arb_exp_arf_generic(arb_t z, const arf_t x, slong prec, int minus_one) Computes the exponential function using an automatic choice between rectangular splitting and the bit-burst algorithm, without precomputation. .. function:: void arb_exp_arf(arb_t z, const arf_t x, slong prec, int minus_one, slong maglim) Computes the exponential function using an automatic choice between all implemented algorithms. .. function:: void arb_log_newton(arb_t res, const arb_t x, slong prec) void arb_log_arf_newton(arb_t res, const arf_t x, slong prec) Computes the logarithm using Newton iteration. .. macro:: ARB_ATAN_GAUSS_PRIME_CACHE_NUM Number of primitive arctangents to cache automatically. .. function:: void arb_atan_gauss_primes_vec_bsplit(arb_ptr res, slong n, slong prec) Sets *res* to the primitive angles corresponding to the first *n* nonreal Gaussian primes (ignoring symmetries), computed using binary splitting applied to simultaneous Machine-type formulas. This function is not optimized for large *n* or small *prec*. .. function:: void _arb_atan_gauss_p_ensure_cached(slong prec) .. function:: void arb_sin_cos_arf_atan_reduction(arb_t res1, arb_t res2, const arf_t x, slong prec) Computes sin and/or cos using reduction by primitive angles. .. function:: void arb_atan_newton(arb_t res, const arb_t x, slong prec) void arb_atan_arf_newton(arb_t res, const arf_t x, slong prec) Computes the arctangent using Newton iteration. Vector functions ------------------------------------------------------------------------------- .. function:: void _arb_vec_zero(arb_ptr vec, slong n) Sets all entries in *vec* to zero. .. function:: int _arb_vec_is_zero(arb_srcptr vec, slong len) Returns nonzero iff all entries in *x* are zero. .. function:: int _arb_vec_is_finite(arb_srcptr x, slong len) Returns nonzero iff all entries in *x* certainly are finite. .. function:: int _arb_vec_equal(arb_srcptr vec1, arb_srcptr vec2, slong len) Returns nonzero iff *vec1* and *vec2* are equal in the sense of :func:`arb_equal`, i.e. have both the same midpoint and radius elementwise. .. function:: int _arb_vec_overlaps(arb_srcptr vec1, arb_srcptr vec2, slong len) Returns nonzero iff *vec1* overlaps *vec2* elementwise. .. function:: int _arb_vec_contains(arb_srcptr vec1, arb_srcptr vec2, slong len) Returns nonzero iff *vec1* contains *vec2* elementwise. .. function:: void _arb_vec_set(arb_ptr res, arb_srcptr vec, slong len) Sets *res* to a copy of *vec*. .. function:: void _arb_vec_set_round(arb_ptr res, arb_srcptr vec, slong len, slong prec) Sets *res* to a copy of *vec*, rounding each entry to *prec* bits. .. function:: void _arb_vec_swap(arb_ptr vec1, arb_ptr vec2, slong len) Swaps the entries of *vec1* and *vec2*. .. function:: void _arb_vec_neg(arb_ptr B, arb_srcptr A, slong n) .. function:: void _arb_vec_sub(arb_ptr C, arb_srcptr A, arb_srcptr B, slong n, slong prec) .. function:: void _arb_vec_add(arb_ptr C, arb_srcptr A, arb_srcptr B, slong n, slong prec) .. function:: void _arb_vec_scalar_mul(arb_ptr res, arb_srcptr vec, slong len, const arb_t c, slong prec) .. function:: void _arb_vec_scalar_div(arb_ptr res, arb_srcptr vec, slong len, const arb_t c, slong prec) .. function:: void _arb_vec_scalar_mul_fmpz(arb_ptr res, arb_srcptr vec, slong len, const fmpz_t c, slong prec) .. function:: void _arb_vec_scalar_mul_2exp_si(arb_ptr res, arb_srcptr src, slong len, slong c) .. function:: void _arb_vec_scalar_addmul(arb_ptr res, arb_srcptr vec, slong len, const arb_t c, slong prec) Performs the respective scalar operation elementwise. .. function:: void _arb_vec_get_mag(mag_t bound, arb_srcptr vec, slong len) Sets *bound* to an upper bound for the entries in *vec*. .. function:: slong _arb_vec_bits(arb_srcptr x, slong len) Returns the maximum of :func:`arb_bits` for all entries in *vec*. .. function:: void _arb_vec_set_powers(arb_ptr xs, const arb_t x, slong len, slong prec) Sets *xs* to the powers `1, x, x^2, \ldots, x^{len-1}`. .. function:: void _arb_vec_add_error_arf_vec(arb_ptr res, arf_srcptr err, slong len) .. function:: void _arb_vec_add_error_mag_vec(arb_ptr res, mag_srcptr err, slong len) Adds the magnitude of each entry in *err* to the radius of the corresponding entry in *res*. .. function:: void _arb_vec_indeterminate(arb_ptr vec, slong len) Applies :func:`arb_indeterminate` elementwise. .. function:: void _arb_vec_trim(arb_ptr res, arb_srcptr vec, slong len) Applies :func:`arb_trim` elementwise. .. function:: int _arb_vec_get_unique_fmpz_vec(fmpz * res, arb_srcptr vec, slong len) Calls :func:`arb_get_unique_fmpz` elementwise and returns nonzero if all entries can be rounded uniquely to integers. If any entry in *vec* cannot be rounded uniquely to an integer, returns zero. .. function:: void _arb_vec_printn(arb_srcptr vec, slong len, slong digits, ulong flags) .. function:: void _arb_vec_printd(arb_srcptr vec, slong len, slong ndigits) Prints *vec* in decimal using :func:`arb_printn` or :func:`arb_printd` on each entry. flint-3.1.3/doc/source/arb_calc.rst000066400000000000000000000244661461254215100171740ustar00rootroot00000000000000.. _arb-calc: **arb_calc.h** -- calculus with real-valued functions =============================================================================== This module provides functions for operations of calculus over the real numbers (intended to include root-finding, optimization, integration, and so on). It is planned that the module will include two types of algorithms: * Interval algorithms that give provably correct results. An example would be numerical integration on an interval by dividing the interval into small balls and evaluating the function on each ball, giving rigorous upper and lower bounds. * Conventional numerical algorithms that use heuristics to estimate the accuracy of a result, without guaranteeing that it is correct. An example would be numerical integration based on pointwise evaluation, where the error is estimated by comparing the results with two different sets of evaluation points. Ball arithmetic then still tracks the accuracy of the function evaluations. Any algorithms of the second kind will be clearly marked as such. Types, macros and constants ------------------------------------------------------------------------------- .. type:: arb_calc_func_t Typedef for a pointer to a function with signature:: int func(arb_ptr out, const arb_t inp, void * param, slong order, slong prec) implementing a univariate real function `f(x)`. When called, *func* should write to *out* the first *order* coefficients in the Taylor series expansion of `f(x)` at the point *inp*, evaluated at a precision of *prec* bits. The *param* argument may be used to pass through additional parameters to the function. The return value is reserved for future use as an error code. It can be assumed that *out* and *inp* are not aliased and that *order* is positive. .. macro:: ARB_CALC_SUCCESS Return value indicating that an operation is successful. .. macro:: ARB_CALC_IMPRECISE_INPUT Return value indicating that the input to a function probably needs to be computed more accurately. .. macro:: ARB_CALC_NO_CONVERGENCE Return value indicating that an algorithm has failed to convergence, possibly due to the problem not having a solution, the algorithm not being applicable, or the precision being insufficient Debugging ------------------------------------------------------------------------------- .. var:: int arb_calc_verbose If set, enables printing information about the calculation to standard output. Subdivision-based root finding ------------------------------------------------------------------------------- .. type:: arf_interval_struct .. type:: arf_interval_t An :type:`arf_interval_struct` consists of a pair of :type:`arf_struct`, representing an interval used for subdivision-based root-finding. An :type:`arf_interval_t` is defined as an array of length one of type :type:`arf_interval_struct`, permitting an :type:`arf_interval_t` to be passed by reference. .. type:: arf_interval_ptr Alias for ``arf_interval_struct *``, used for vectors of intervals. .. type:: arf_interval_srcptr Alias for ``const arf_interval_struct *``, used for vectors of intervals. .. function:: void arf_interval_init(arf_interval_t v) .. function:: void arf_interval_clear(arf_interval_t v) .. function:: arf_interval_ptr _arf_interval_vec_init(slong n) .. function:: void _arf_interval_vec_clear(arf_interval_ptr v, slong n) .. function:: void arf_interval_set(arf_interval_t v, const arf_interval_t u) .. function:: void arf_interval_swap(arf_interval_t v, arf_interval_t u) .. function:: void arf_interval_get_arb(arb_t x, const arf_interval_t v, slong prec) .. function:: void arf_interval_printd(const arf_interval_t v, slong n) Helper functions for endpoint-based intervals. .. function:: void arf_interval_fprintd(FILE * file, const arf_interval_t v, slong n) Helper functions for endpoint-based intervals. .. function:: slong arb_calc_isolate_roots(arf_interval_ptr * found, int ** flags, arb_calc_func_t func, void * param, const arf_interval_t interval, slong maxdepth, slong maxeval, slong maxfound, slong prec) Rigorously isolates single roots of a real analytic function on the interior of an interval. This routine writes an array of *n* interesting subintervals of *interval* to *found* and corresponding flags to *flags*, returning the integer *n*. The output has the following properties: * The function has no roots on *interval* outside of the output subintervals. * Subintervals are sorted in increasing order (with no overlap except possibly starting and ending with the same point). * Subintervals with a flag of 1 contain exactly one (single) root. * Subintervals with any other flag may or may not contain roots. If no flags other than 1 occur, all roots of the function on *interval* have been isolated. If there are output subintervals on which the existence or nonexistence of roots could not be determined, the user may attempt further searches on those subintervals (possibly with increased precision and/or increased bounds for the breaking criteria). Note that roots of multiplicity higher than one and roots located exactly at endpoints cannot be isolated by the algorithm. The following breaking criteria are implemented: * At most *maxdepth* recursive subdivisions are attempted. The smallest details that can be distinguished are therefore about `2^{-\text{maxdepth}}` times the width of *interval*. A typical, reasonable value might be between 20 and 50. * If the total number of tested subintervals exceeds *maxeval*, the algorithm is terminated and any untested subintervals are added to the output. The total number of calls to *func* is thereby restricted to a small multiple of *maxeval* (the actual count can be slightly higher depending on implementation details). A typical, reasonable value might be between 100 and 100000. * The algorithm terminates if *maxfound* roots have been isolated. In particular, setting *maxfound* to 1 can be used to locate just one root of the function even if there are numerous roots. To try to find all roots, *LONG_MAX* may be passed. The argument *prec* denotes the precision used to evaluate the function. It is possibly also used for some other arithmetic operations performed internally by the algorithm. Note that it probably does not make sense for *maxdepth* to exceed *prec*. Warning: it is assumed that subdivision points of *interval* can be represented exactly as floating-point numbers in memory. Do not pass `1 \pm 2^{-10^{100}}` as input. .. function:: int arb_calc_refine_root_bisect(arf_interval_t r, arb_calc_func_t func, void * param, const arf_interval_t start, slong iter, slong prec) Given an interval *start* known to contain a single root of *func*, refines it using *iter* bisection steps. The algorithm can return a failure code if the sign of the function at an evaluation point is ambiguous. The output *r* is set to a valid isolating interval (possibly just *start*) even if the algorithm fails. Newton-based root finding ------------------------------------------------------------------------------- .. function:: void arb_calc_newton_conv_factor(arf_t conv_factor, arb_calc_func_t func, void * param, const arb_t conv_region, slong prec) Given an interval `I` specified by *conv_region*, evaluates a bound for `C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|`, where `f` is the function specified by *func* and *param*. The bound is obtained by evaluating `f'(I)` and `f''(I)` directly. If `f` is ill-conditioned, `I` may need to be extremely precise in order to get an effective, finite bound for *C*. .. function:: int arb_calc_newton_step(arb_t xnew, arb_calc_func_t func, void * param, const arb_t x, const arb_t conv_region, const arf_t conv_factor, slong prec) Performs a single step with an interval version of Newton's method. The input consists of the function `f` specified by *func* and *param*, a ball `x = [m-r, m+r]` known to contain a single root of `f`, a ball `I` (*conv_region*) containing `x` with an associated bound (*conv_factor*) for `C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|`, and a working precision *prec*. The Newton update consists of setting `x' = [m'-r', m'+r']` where `m' = m - f(m) / f'(m)` and `r' = C r^2`. The expression `m - f(m) / f'(m)` is evaluated using ball arithmetic at a working precision of *prec* bits, and the rounding error during this evaluation is accounted for in the output. We now check that `x' \in I` and `r' < r`. If both conditions are satisfied, we set *xnew* to `x'` and return *ARB_CALC_SUCCESS*. If either condition fails, we set *xnew* to `x` and return *ARB_CALC_NO_CONVERGENCE*, indicating that no progress is made. .. function:: int arb_calc_refine_root_newton(arb_t r, arb_calc_func_t func, void * param, const arb_t start, const arb_t conv_region, const arf_t conv_factor, slong eval_extra_prec, slong prec) Refines a precise estimate of a single root of a function to high precision by performing several Newton steps, using nearly optimally chosen doubling precision steps. The inputs are defined as for *arb_calc_newton_step*, except for the precision parameters: *prec* is the target accuracy and *eval_extra_prec* is the estimated number of guard bits that need to be added to evaluate the function accurately close to the root (for example, if the function is a polynomial with large coefficients of alternating signs and Horner's rule is used to evaluate it, the extra precision should typically be approximately the bit size of the coefficients). This function returns *ARB_CALC_SUCCESS* if all attempted Newton steps are successful (note that this does not guarantee that the computed root is accurate to *prec* bits, which has to be verified by the user), only that it is more accurate than the starting ball. On failure, *ARB_CALC_IMPRECISE_INPUT* or *ARB_CALC_NO_CONVERGENCE* may be returned. In this case, *r* is set to a ball for the root which is valid but likely does have full accuracy (it can possibly just be equal to the starting ball). flint-3.1.3/doc/source/arb_fmpz_poly.rst000066400000000000000000000136611461254215100203040ustar00rootroot00000000000000.. _arb_fmpz_poly: **arb_fmpz_poly.h** -- extra methods for integer polynomials ========================================================================================= This module provides methods for FLINT polynomials with integer and rational coefficients (:type:`fmpz_poly_t`) and (:type:`fmpq_poly_t`) requiring use of Arb real or complex numbers. Some methods output real or complex numbers while others use real and complex numbers internally to produce an exact result. This module also contains some useful helper functions not specifically related to real and complex numbers. Note that methods that combine Arb *polynomials* and FLINT polynomials are found in the respective Arb polynomial modules, such as :func:`arb_poly_set_fmpz_poly` and :func:`arb_poly_get_unique_fmpz_poly`. Evaluation ------------------------------------------------------------------------------- .. function:: void _arb_fmpz_poly_evaluate_arb_horner(arb_t res, const fmpz * poly, slong len, const arb_t x, slong prec) .. function:: void arb_fmpz_poly_evaluate_arb_horner(arb_t res, const fmpz_poly_t poly, const arb_t x, slong prec) .. function:: void _arb_fmpz_poly_evaluate_arb_rectangular(arb_t res, const fmpz * poly, slong len, const arb_t x, slong prec) .. function:: void arb_fmpz_poly_evaluate_arb_rectangular(arb_t res, const fmpz_poly_t poly, const arb_t x, slong prec) .. function:: void _arb_fmpz_poly_evaluate_arb(arb_t res, const fmpz * poly, slong len, const arb_t x, slong prec) .. function:: void arb_fmpz_poly_evaluate_arb(arb_t res, const fmpz_poly_t poly, const arb_t x, slong prec) .. function:: void _arb_fmpz_poly_evaluate_acb_horner(acb_t res, const fmpz * poly, slong len, const acb_t x, slong prec) .. function:: void arb_fmpz_poly_evaluate_acb_horner(acb_t res, const fmpz_poly_t poly, const acb_t x, slong prec) .. function:: void _arb_fmpz_poly_evaluate_acb_rectangular(acb_t res, const fmpz * poly, slong len, const acb_t x, slong prec) .. function:: void arb_fmpz_poly_evaluate_acb_rectangular(acb_t res, const fmpz_poly_t poly, const acb_t x, slong prec) .. function:: void _arb_fmpz_poly_evaluate_acb(acb_t res, const fmpz * poly, slong len, const acb_t x, slong prec) .. function:: void arb_fmpz_poly_evaluate_acb(acb_t res, const fmpz_poly_t poly, const acb_t x, slong prec) Evaluates *poly* (given by a polynomial object or an array with *len* coefficients) at the given real or complex number, respectively using Horner's rule, rectangular splitting, or a default algorithm choice. Utility methods ------------------------------------------------------------------------------- .. function:: ulong arb_fmpz_poly_deflation(const fmpz_poly_t poly) Finds the maximal exponent by which *poly* can be deflated. .. function:: void arb_fmpz_poly_deflate(fmpz_poly_t res, const fmpz_poly_t poly, ulong deflation) Sets *res* to a copy of *poly* deflated by the exponent *deflation*. Polynomial roots ------------------------------------------------------------------------------- .. function:: void arb_fmpz_poly_complex_roots(acb_ptr roots, const fmpz_poly_t poly, int flags, slong prec) Writes to *roots* all the real and complex roots of the polynomial *poly*, computed to at least *prec* accurate bits. The root enclosures are guaranteed to be disjoint, so that all roots are isolated. The real roots are written first in ascending order (with the imaginary parts set exactly to zero). The following nonreal roots are written in arbitrary order, but with conjugate pairs grouped together (the root in the upper plane leading the root in the lower plane). The input polynomial *must* be squarefree. For a general polynomial, compute the squarefree part `f / \gcd(f,f')` or do a full squarefree factorization to obtain the multiplicities of the roots:: fmpz_poly_factor_t fac; fmpz_poly_factor_init(fac); fmpz_poly_factor_squarefree(fac, poly); for (i = 0; i < fac->num; i++) { deg = fmpz_poly_degree(fac->p + i); flint_printf("%wd roots of multiplicity %wd\n", deg, fac->exp[i]); roots = _acb_vec_init(deg); arb_fmpz_poly_complex_roots(roots, fac->p + i, 0, prec); _acb_vec_clear(roots, deg); } fmpz_poly_factor_clear(fac); All roots are refined to a relative accuracy of at least *prec* bits. The output values will generally have higher actual precision, depending on the precision needed for isolation and the precision used internally by the algorithm. This implementation should be adequate for general use, but it is not currently competitive with state-of-the-art isolation methods for finding real roots alone. The following *flags* are supported: * *ARB_FMPZ_POLY_ROOTS_VERBOSE* Special polynomials ------------------------------------------------------------------------------- Note: see also the methods available in FLINT (e.g. for cyclotomic polynomials). .. function:: void arb_fmpz_poly_gauss_period_minpoly(fmpz_poly_t res, ulong q, ulong n) Sets *res* to the minimal polynomial of the Gaussian periods `\sum_{a \in H} \zeta^a` where `\zeta = \exp(2 \pi i / q)` and *H* are the cosets of the subgroups of order `d = (q - 1) / n` of `(\mathbb{Z}/q\mathbb{Z})^{\times}`. The resulting polynomial has degree *n*. When `d = 1`, the result is the cyclotomic polynomial `\Phi_q`. The implementation assumes that *q* is prime, and that *n* is a divisor of `q - 1` such that *n* is coprime with *d*. If any condition is not met, *res* is set to the zero polynomial. This method provides a fast (in practice) way to construct finite field extensions of prescribed degree. If *q* satisfies the conditions stated above and `(q-1)/f` additionally is coprime with *n*, where *f* is the multiplicative order of *p* mod *q*, then the Gaussian period minimal polynomial is irreducible over `\operatorname{GF}(p)` [CP2005]_. flint-3.1.3/doc/source/arb_fpwrap.rst000066400000000000000000000734111461254215100175630ustar00rootroot00000000000000.. _arb_fpwrap: **arb_fpwrap.h** -- floating-point wrappers of Arb mathematical functions ========================================================================================= This module provides wrappers of Arb functions intended users who want accurate floating-point mathematical functions without necessarily caring about ball arithmetic. The wrappers take floating-point input, give floating-point output, and automatically increase the internal working precision to ensure that the output is accurate (in the rare case of failure, they output NaN along with an error code). **Warning:** This module is experimental (as of Arb 2.21). It has not been extensively tested, and interfaces may change in the future. Supported types: * ``double`` and ``complex_double`` (53-bit precision) Limitations: * The wrappers currently only handle finite input and points where function value is finite. For example, they do not know that `\log(0) = -\infty` or that `\exp(-\infty) = 0`. Singular input or output result in ``FPWRAP_UNABLE`` and a NaN output value. Evaluation of limit values may be implemented in the future for some functions. * The wrappers currently treat ``-0.0`` as ``+0.0``. Users who need to distinguish signs of zero, e.g. on branch cuts, currently need to do so manually. * When requesting *correct rounding*, the wrappers can fail to converge in asymptotic or exact cases (where special algorithms are required). * If the value is computed accurately internally but is too small to represent as a floating-point number, the result will be ``-0.0`` or ``+0.0`` (on underflow) or ``-Inf`` or ``+Inf`` (on overflow). Since the underflowed or overflowed result is the best possible floating-point approximation of the true value, this outcome is considered correct and the flag ``FPWRAP_SUCCESS`` is returned. In the future, return status flags may be added to indicate that underflow or overflow has occurred. * Different rounding modes are not yet implemented. Option and return flags ------------------------------------------------------------------------------- Functions return an ``int`` flag indicating the status. .. macro:: FPWRAP_SUCCESS Indicates an accurate result. (Up to inevitable underflow or overflow in the final conversion to a floating-point result; see above.) This flag has the numerical value 0. .. macro:: FPWRAP_UNABLE Indicates failure (unable to achieve to target accuracy, possibly because of a singularity). The output is set to NaN. This flag has the numerical value 1. Functions take a *flags* parameter specifying optional rounding and termination behavior. This can be set to 0 to use defaults. .. macro:: FPWRAP_ACCURATE_PARTS For complex output, compute both real and imaginary parts to full relative accuracy. By default (if this flag is not set), complex results are computed to at least 53-bit accuracy as a whole, but if either the real or imaginary part is much smaller than the other, that part can have a large relative error. Setting this flag can result in slower evaluation or failure to converge in some cases. This flag has the numerical value 1. .. macro:: FPWRAP_CORRECT_ROUNDING Guarantees *correct rounding*. By default (if this flag is not set), real results are accurate up to the rounding of the last bit, but the last bit is not guaranteed to be rounded optimally. Setting this flag can result in slower evaluation or failure to converge in some cases. Correct rounding automatically applies to both real and imaginary parts of complex numbers, so it is unnecessary to set both this flag and *FPWRAP_ACCURATE_PARTS*. This flag has the numerical value 2. .. macro:: FPWRAP_WORK_LIMIT Multiplied by an integer, specifies the maximum working precision to use before giving up. With ``n * FPWRAP_WORK_LIMIT`` added to *flags*, `n` levels of precision will be used. The default `n = 0` is equivalent to `n = 8`, which for ``double`` means trying with a working precision of 64, 128, 256, 512, 1024, 2048, 4096, 8192 bits. With ``flags = 2 * FPWRAP_WORK_LIMIT``, we only try 64 and 128 bits, and with ``flags = 16 * FPWRAP_WORK_LIMIT`` we go up to 2097152 bits. This flag has the numerical value 65536. Types ------------------------------------------------------------------------------- Outputs are passed by reference so that we can return status flags and so that the interface is uniform for functions with multiple outputs. .. type:: complex_double A struct of two ``double`` components (``real`` and ``imag``), used to represent a machine-precision complex number. We use this custom type instead of the complex types defined in ```` since Arb does not depend on C99. Users should easily be able to convert to the C99 complex type since the layout in memory is identical. Functions ------------------------------------------------------------------------------- Elementary functions ............................................................................... .. function:: int arb_fpwrap_double_exp(double * res, double x, int flags) int arb_fpwrap_cdouble_exp(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_expm1(double * res, double x, int flags) int arb_fpwrap_cdouble_expm1(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_log(double * res, double x, int flags) int arb_fpwrap_cdouble_log(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_log1p(double * res, double x, int flags) int arb_fpwrap_cdouble_log1p(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_pow(double * res, double x, double y, int flags) int arb_fpwrap_cdouble_pow(complex_double * res, complex_double x, complex_double y, int flags) .. function:: int arb_fpwrap_double_sqrt(double * res, double x, int flags) int arb_fpwrap_cdouble_sqrt(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_rsqrt(double * res, double x, int flags) int arb_fpwrap_cdouble_rsqrt(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_cbrt(double * res, double x, int flags) int arb_fpwrap_cdouble_cbrt(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_sin(double * res, double x, int flags) int arb_fpwrap_cdouble_sin(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_cos(double * res, double x, int flags) int arb_fpwrap_cdouble_cos(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_tan(double * res, double x, int flags) int arb_fpwrap_cdouble_tan(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_cot(double * res, double x, int flags) int arb_fpwrap_cdouble_cot(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_sec(double * res, double x, int flags) int arb_fpwrap_cdouble_sec(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_csc(double * res, double x, int flags) int arb_fpwrap_cdouble_csc(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_sinc(double * res, double x, int flags) int arb_fpwrap_cdouble_sinc(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_sin_pi(double * res, double x, int flags) int arb_fpwrap_cdouble_sin_pi(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_cos_pi(double * res, double x, int flags) int arb_fpwrap_cdouble_cos_pi(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_tan_pi(double * res, double x, int flags) int arb_fpwrap_cdouble_tan_pi(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_cot_pi(double * res, double x, int flags) int arb_fpwrap_cdouble_cot_pi(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_sinc_pi(double * res, double x, int flags) int arb_fpwrap_cdouble_sinc_pi(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_asin(double * res, double x, int flags) int arb_fpwrap_cdouble_asin(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_acos(double * res, double x, int flags) int arb_fpwrap_cdouble_acos(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_atan(double * res, double x, int flags) int arb_fpwrap_cdouble_atan(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_atan2(double * res, double x1, double x2, int flags) .. function:: int arb_fpwrap_double_asinh(double * res, double x, int flags) int arb_fpwrap_cdouble_asinh(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_acosh(double * res, double x, int flags) int arb_fpwrap_cdouble_acosh(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_atanh(double * res, double x, int flags) int arb_fpwrap_cdouble_atanh(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_lambertw(double * res, double x, slong branch, int flags) int arb_fpwrap_cdouble_lambertw(complex_double * res, complex_double x, slong branch, int flags) Gamma, zeta and related functions ............................................................................... .. function:: int arb_fpwrap_double_rising(double * res, double x, double n, int flags) int arb_fpwrap_cdouble_rising(complex_double * res, complex_double x, complex_double n, int flags) Rising factorial. .. function:: int arb_fpwrap_double_gamma(double * res, double x, int flags) int arb_fpwrap_cdouble_gamma(complex_double * res, complex_double x, int flags) Gamma function. .. function:: int arb_fpwrap_double_rgamma(double * res, double x, int flags) int arb_fpwrap_cdouble_rgamma(complex_double * res, complex_double x, int flags) Reciprocal gamma function. .. function:: int arb_fpwrap_double_lgamma(double * res, double x, int flags) int arb_fpwrap_cdouble_lgamma(complex_double * res, complex_double x, int flags) Log-gamma function. .. function:: int arb_fpwrap_double_digamma(double * res, double x, int flags) int arb_fpwrap_cdouble_digamma(complex_double * res, complex_double x, int flags) Digamma function. .. function:: int arb_fpwrap_double_zeta(double * res, double x, int flags) int arb_fpwrap_cdouble_zeta(complex_double * res, complex_double x, int flags) Riemann zeta function. .. function:: int arb_fpwrap_double_hurwitz_zeta(double * res, double s, double z, int flags) int arb_fpwrap_cdouble_hurwitz_zeta(complex_double * res, complex_double s, complex_double z, int flags) Hurwitz zeta function. .. function:: int arb_fpwrap_double_lerch_phi(double * res, double z, double s, double a, int flags) int arb_fpwrap_cdouble_lerch_phi(complex_double * res, complex_double z, complex_double s, complex_double a, int flags) Lerch transcendent. .. function:: int arb_fpwrap_double_barnes_g(double * res, double x, int flags) int arb_fpwrap_cdouble_barnes_g(complex_double * res, complex_double x, int flags) Barnes G-function. .. function:: int arb_fpwrap_double_log_barnes_g(double * res, double x, int flags) int arb_fpwrap_cdouble_log_barnes_g(complex_double * res, complex_double x, int flags) Logarithmic Barnes G-function. .. function:: int arb_fpwrap_double_polygamma(double * res, double s, double z, int flags) int arb_fpwrap_cdouble_polygamma(complex_double * res, complex_double s, complex_double z, int flags) Polygamma function. .. function:: int arb_fpwrap_double_polylog(double * res, double s, double z, int flags) int arb_fpwrap_cdouble_polylog(complex_double * res, complex_double s, complex_double z, int flags) Polylogarithm. .. function:: int arb_fpwrap_cdouble_dirichlet_eta(complex_double * res, complex_double s, int flags) .. function:: int arb_fpwrap_cdouble_riemann_xi(complex_double * res, complex_double s, int flags) .. function:: int arb_fpwrap_cdouble_hardy_theta(complex_double * res, complex_double z, int flags) .. function:: int arb_fpwrap_cdouble_hardy_z(complex_double * res, complex_double z, int flags) .. function:: int arb_fpwrap_cdouble_zeta_zero(complex_double * res, ulong n, int flags) Error functions and exponential integrals ............................................................................... .. function:: int arb_fpwrap_double_erf(double * res, double x, int flags) int arb_fpwrap_cdouble_erf(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_erfc(double * res, double x, int flags) int arb_fpwrap_cdouble_erfc(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_erfi(double * res, double x, int flags) int arb_fpwrap_cdouble_erfi(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_erfinv(double * res, double x, int flags) .. function:: int arb_fpwrap_double_erfcinv(double * res, double x, int flags) .. function:: int arb_fpwrap_double_fresnel_s(double * res, double x, int normalized, int flags) int arb_fpwrap_cdouble_fresnel_s(complex_double * res, complex_double x, int normalized, int flags) .. function:: int arb_fpwrap_double_fresnel_c(double * res, double x, int normalized, int flags) int arb_fpwrap_cdouble_fresnel_c(complex_double * res, complex_double x, int normalized, int flags) .. function:: int arb_fpwrap_double_gamma_upper(double * res, double s, double z, int regularized, int flags) int arb_fpwrap_cdouble_gamma_upper(complex_double * res, complex_double s, complex_double z, int regularized, int flags) .. function:: int arb_fpwrap_double_gamma_lower(double * res, double s, double z, int regularized, int flags) int arb_fpwrap_cdouble_gamma_lower(complex_double * res, complex_double s, complex_double z, int regularized, int flags) .. function:: int arb_fpwrap_double_beta_lower(double * res, double a, double b, double z, int regularized, int flags) int arb_fpwrap_cdouble_beta_lower(complex_double * res, complex_double a, complex_double b, complex_double z, int regularized, int flags) .. function:: int arb_fpwrap_double_exp_integral_e(double * res, double s, double z, int flags) int arb_fpwrap_cdouble_exp_integral_e(complex_double * res, complex_double s, complex_double z, int flags) .. function:: int arb_fpwrap_double_exp_integral_ei(double * res, double x, int flags) int arb_fpwrap_cdouble_exp_integral_ei(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_sin_integral(double * res, double x, int flags) int arb_fpwrap_cdouble_sin_integral(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_cos_integral(double * res, double x, int flags) int arb_fpwrap_cdouble_cos_integral(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_sinh_integral(double * res, double x, int flags) int arb_fpwrap_cdouble_sinh_integral(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_cosh_integral(double * res, double x, int flags) int arb_fpwrap_cdouble_cosh_integral(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_log_integral(double * res, double x, int offset, int flags) int arb_fpwrap_cdouble_log_integral(complex_double * res, complex_double x, int offset, int flags) .. function:: int arb_fpwrap_double_dilog(double * res, double x, int flags) int arb_fpwrap_cdouble_dilog(complex_double * res, complex_double x, int flags) Bessel, Airy and Coulomb functions ............................................................................... .. function:: int arb_fpwrap_double_bessel_j(double * res, double nu, double x, int flags) int arb_fpwrap_cdouble_bessel_j(complex_double * res, complex_double nu, complex_double x, int flags) .. function:: int arb_fpwrap_double_bessel_y(double * res, double nu, double x, int flags) int arb_fpwrap_cdouble_bessel_y(complex_double * res, complex_double nu, complex_double x, int flags) .. function:: int arb_fpwrap_double_bessel_i(double * res, double nu, double x, int flags) int arb_fpwrap_cdouble_bessel_i(complex_double * res, complex_double nu, complex_double x, int flags) .. function:: int arb_fpwrap_double_bessel_k(double * res, double nu, double x, int flags) int arb_fpwrap_cdouble_bessel_k(complex_double * res, complex_double nu, complex_double x, int flags) .. function:: int arb_fpwrap_double_bessel_k_scaled(double * res, double nu, double x, int flags) int arb_fpwrap_cdouble_bessel_k_scaled(complex_double * res, complex_double nu, complex_double x, int flags) .. function:: int arb_fpwrap_double_airy_ai(double * res, double x, int flags) int arb_fpwrap_cdouble_airy_ai(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_airy_ai_prime(double * res, double x, int flags) int arb_fpwrap_cdouble_airy_ai_prime(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_airy_bi(double * res, double x, int flags) int arb_fpwrap_cdouble_airy_bi(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_airy_bi_prime(double * res, double x, int flags) int arb_fpwrap_cdouble_airy_bi_prime(complex_double * res, complex_double x, int flags) .. function:: int arb_fpwrap_double_airy_ai_zero(double * res, ulong n, int flags) .. function:: int arb_fpwrap_double_airy_ai_prime_zero(double * res, ulong n, int flags) .. function:: int arb_fpwrap_double_airy_bi_zero(double * res, ulong n, int flags) .. function:: int arb_fpwrap_double_airy_bi_prime_zero(double * res, ulong n, int flags) .. function:: int arb_fpwrap_double_coulomb_f(double * res, double l, double eta, double x, int flags) int arb_fpwrap_cdouble_coulomb_f(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags) .. function:: int arb_fpwrap_double_coulomb_g(double * res, double l, double eta, double x, int flags) int arb_fpwrap_cdouble_coulomb_g(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags) .. function:: int arb_fpwrap_cdouble_coulomb_hpos(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags) int arb_fpwrap_cdouble_coulomb_hneg(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags) Orthogonal polynomials ............................................................................... .. function:: int arb_fpwrap_double_chebyshev_t(double * res, double n, double x, int flags) int arb_fpwrap_cdouble_chebyshev_t(complex_double * res, complex_double n, complex_double x, int flags) .. function:: int arb_fpwrap_double_chebyshev_u(double * res, double n, double x, int flags) int arb_fpwrap_cdouble_chebyshev_u(complex_double * res, complex_double n, complex_double x, int flags) .. function:: int arb_fpwrap_double_jacobi_p(double * res, double n, double a, double b, double x, int flags) int arb_fpwrap_cdouble_jacobi_p(complex_double * res, complex_double n, complex_double a, complex_double b, complex_double x, int flags) .. function:: int arb_fpwrap_double_gegenbauer_c(double * res, double n, double m, double x, int flags) int arb_fpwrap_cdouble_gegenbauer_c(complex_double * res, complex_double n, complex_double m, complex_double x, int flags) .. function:: int arb_fpwrap_double_laguerre_l(double * res, double n, double m, double x, int flags) int arb_fpwrap_cdouble_laguerre_l(complex_double * res, complex_double n, complex_double m, complex_double x, int flags) .. function:: int arb_fpwrap_double_hermite_h(double * res, double n, double x, int flags) int arb_fpwrap_cdouble_hermite_h(complex_double * res, complex_double n, complex_double x, int flags) .. function:: int arb_fpwrap_double_legendre_p(double * res, double n, double m, double x, int type, int flags) int arb_fpwrap_cdouble_legendre_p(complex_double * res, complex_double n, complex_double m, complex_double x, int type, int flags) .. function:: int arb_fpwrap_double_legendre_q(double * res, double n, double m, double x, int type, int flags) int arb_fpwrap_cdouble_legendre_q(complex_double * res, complex_double n, complex_double m, complex_double x, int type, int flags) .. function:: int arb_fpwrap_double_legendre_root(double * res1, double * res2, ulong n, ulong k, int flags) Sets *res1* to the index *k* root of the Legendre polynomial `P_n(x)`, and simultaneously sets *res2* to the corresponding weight for Gauss-Legendre quadrature. .. function:: int arb_fpwrap_cdouble_spherical_y(complex_double * res, slong n, slong m, complex_double x1, complex_double x2, int flags) Hypergeometric functions ............................................................................... .. function:: int arb_fpwrap_double_hypgeom_0f1(double * res, double a, double x, int regularized, int flags) int arb_fpwrap_cdouble_hypgeom_0f1(complex_double * res, complex_double a, complex_double x, int regularized, int flags) .. function:: int arb_fpwrap_double_hypgeom_1f1(double * res, double a, double b, double x, int regularized, int flags) int arb_fpwrap_cdouble_hypgeom_1f1(complex_double * res, complex_double a, complex_double b, complex_double x, int regularized, int flags) .. function:: int arb_fpwrap_double_hypgeom_u(double * res, double a, double b, double x, int flags) int arb_fpwrap_cdouble_hypgeom_u(complex_double * res, complex_double a, complex_double b, complex_double x, int flags) .. function:: int arb_fpwrap_double_hypgeom_2f1(double * res, double a, double b, double c, double x, int regularized, int flags) int arb_fpwrap_cdouble_hypgeom_2f1(complex_double * res, complex_double a, complex_double b, complex_double c, complex_double x, int regularized, int flags) .. function:: int arb_fpwrap_double_hypgeom_pfq(double * res, const double * a, slong p, const double * b, slong q, double z, int regularized, int flags) int arb_fpwrap_cdouble_hypgeom_pfq(complex_double * res, const complex_double * a, slong p, const complex_double * b, slong q, complex_double z, int regularized, int flags) Elliptic integrals, elliptic functions and modular forms ............................................................................... .. function:: int arb_fpwrap_double_agm(double * res, double x, double y, int flags) int arb_fpwrap_cdouble_agm(complex_double * res, complex_double x, complex_double y, int flags) Arithmetic-geometric mean. .. function:: int arb_fpwrap_cdouble_elliptic_k(complex_double * res, complex_double m, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_e(complex_double * res, complex_double m, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_pi(complex_double * res, complex_double n, complex_double m, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_f(complex_double * res, complex_double phi, complex_double m, int pi, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_e_inc(complex_double * res, complex_double phi, complex_double m, int pi, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_pi_inc(complex_double * res, complex_double n, complex_double phi, complex_double m, int pi, int flags) Complete and incomplete elliptic integrals. .. function:: int arb_fpwrap_cdouble_elliptic_rf(complex_double * res, complex_double x, complex_double y, complex_double z, int option, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_rg(complex_double * res, complex_double x, complex_double y, complex_double z, int option, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_rj(complex_double * res, complex_double x, complex_double y, complex_double z, complex_double w, int option, int flags) Carlson symmetric elliptic integrals. .. function:: int arb_fpwrap_cdouble_elliptic_p(complex_double * res, complex_double z, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_p_prime(complex_double * res, complex_double z, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_inv_p(complex_double * res, complex_double z, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_zeta(complex_double * res, complex_double z, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_elliptic_sigma(complex_double * res, complex_double z, complex_double tau, int flags) Weierstrass elliptic functions. .. function:: int arb_fpwrap_cdouble_jacobi_theta_1(complex_double * res, complex_double z, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_jacobi_theta_2(complex_double * res, complex_double z, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_jacobi_theta_3(complex_double * res, complex_double z, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_jacobi_theta_4(complex_double * res, complex_double z, complex_double tau, int flags) Jacobi theta functions. .. function:: int arb_fpwrap_cdouble_dedekind_eta(complex_double * res, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_modular_j(complex_double * res, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_modular_lambda(complex_double * res, complex_double tau, int flags) .. function:: int arb_fpwrap_cdouble_modular_delta(complex_double * res, complex_double tau, int flags) Calling from C ------------------------------------------------------------------------------- The program ``examples/fpwrap.c`` provides a usage example:: #include "arb_fpwrap.h" int main() { double x, y; complex_double cx, cy; int flags = 0; /* default options */ x = 2.0; cx.real = 0.5; cx.imag = 123.0; arb_fpwrap_double_zeta(&y, x, flags); arb_fpwrap_cdouble_zeta(&cy, cx, flags); printf("zeta(%g) = %.16g\n", x, y); printf("zeta(%g + %gi) = %.16g + %.16gi\n", cx.real, cx.imag, cy.real, cy.imag); flint_cleanup(); return 0; } .. highlight:: text This should print:: > build/examples/fpwrap zeta(2) = 1.644934066848226 zeta(0.5 + 123i) = 0.006252861175594465 + 0.08206030514520983i Note that this program does not check the return flag to perform error handling. Interfacing from Python ------------------------------------------------------------------------------- .. highlight:: python This illustrates how to call functions from Python using ``ctypes``:: import ctypes import ctypes.util libarb_path = ctypes.util.find_library('arb') libarb = ctypes.CDLL(libarb_path) class _complex_double(ctypes.Structure): _fields_ = [('real', ctypes.c_double), ('imag', ctypes.c_double)] def wrap_double_fun(fun): def f(x): y = ctypes.c_double() if fun(ctypes.byref(y), ctypes.c_double(x), 0): raise ValueError(f"unable to evaluate function accurately at {x}") return y.value return f def wrap_cdouble_fun(fun): def f(x): x = complex(x) cx = _complex_double() cy = _complex_double() cx.real = x.real cx.imag = x.imag if fun(ctypes.byref(cy), cx, 0): raise ValueError(f"unable to evaluate function accurately at {x}") return complex(cy.real, cy.imag) return f zeta = wrap_double_fun(libarb.arb_fpwrap_double_zeta) czeta = wrap_cdouble_fun(libarb.arb_fpwrap_cdouble_zeta) print(zeta(2.0)) print(czeta(0.5+1e9j)) print(zeta(1.0)) # pole, where wrapper throws exception .. highlight:: text This should print:: 1.6449340668482264 (-2.761748029838061-1.6775122409894598j) Traceback (most recent call last): ... ValueError: unable to evaluate function accurately at 1.0 Interfacing from Julia ------------------------------------------------------------------------------- .. highlight:: julia This illustrates how to call functions from Julia using ``ccall``:: using Libdl dlopen("/home/fredrik/src/arb/libarb.so") function zeta(x::Float64) cy = Ref{Float64}() if Bool(ccall((:arb_fpwrap_double_zeta, :libarb), Cint, (Ptr{Float64}, Float64, Cint), cy, x, 0)) error("unable to evaluate accurately at ", x) end return cy[] end function zeta(x::Complex{Float64}) cy = Ref{Complex{Float64}}() if Bool(ccall((:arb_fpwrap_cdouble_zeta, :libarb), Cint, (Ptr{Complex{Float64}}, Complex{Float64}, Cint), cy, x, 0)) error("unable to evaluate accurately at ", x) end return cy[] end println(zeta(2.0)) println(zeta(0.5 + 1e9im)) println(zeta(1.0)) # pole, where wrapper throws exception .. highlight:: text This should print:: 1.6449340668482264 -2.761748029838061 - 1.6775122409894598im ERROR: unable to evaluate accurately at 1.0 Stacktrace: ... .. highlight:: c flint-3.1.3/doc/source/arb_hypgeom.rst000066400000000000000000001044301461254215100177300ustar00rootroot00000000000000.. _arb-hypgeom: **arb_hypgeom.h** -- hypergeometric functions of real variables ================================================================================== See :ref:`acb-hypgeom` for the general implementation of hypergeometric functions. For convenience, this module provides versions of the same functions for real variables represented using :type:`arb_t` and :type:`arb_poly_t`. Most methods are simple wrappers around the complex versions, but some of the functions in this module have been further optimized specifically for real variables. This module also provides certain functions exclusive to real variables, such as functions for computing real roots of common special functions. Rising factorials ------------------------------------------------------------------------------- .. function:: void _arb_hypgeom_rising_coeffs_1(ulong * c, ulong k, slong n) void _arb_hypgeom_rising_coeffs_2(ulong * c, ulong k, slong n) void _arb_hypgeom_rising_coeffs_fmpz(fmpz * c, ulong k, slong n) Sets *c* to the coefficients of the rising factorial polynomial `(X+k)_n`. The *1* and *2* versions respectively compute single-word and double-word coefficients, without checking for overflow, while the *fmpz* version allows arbitrarily large coefficients. These functions are mostly intended for internal use; the *fmpz* version does not use an asymptotically fast algorithm. The degree *n* must be at least 2. .. function:: void arb_hypgeom_rising_ui_forward(arb_t res, const arb_t x, ulong n, slong prec) void arb_hypgeom_rising_ui_bs(arb_t res, const arb_t x, ulong n, slong prec) void arb_hypgeom_rising_ui_rs(arb_t res, const arb_t x, ulong n, ulong m, slong prec) void arb_hypgeom_rising_ui_rec(arb_t res, const arb_t x, ulong n, slong prec) void arb_hypgeom_rising_ui(arb_t res, const arb_t x, ulong n, slong prec) void arb_hypgeom_rising(arb_t res, const arb_t x, const arb_t n, slong prec) Computes the rising factorial `(x)_n`. The *forward* version uses the forward recurrence. The *bs* version uses binary splitting. The *rs* version uses rectangular splitting. It takes an extra tuning parameter *m* which can be set to zero to choose automatically. The *rec* version chooses an algorithm automatically, avoiding use of the gamma function (so that it can be used in the computation of the gamma function). The default versions (*rising_ui* and *rising_ui*) choose an algorithm automatically and may additionally fall back on the gamma function. .. function:: void arb_hypgeom_rising_ui_jet_powsum(arb_ptr res, const arb_t x, ulong n, slong len, slong prec) void arb_hypgeom_rising_ui_jet_bs(arb_ptr res, const arb_t x, ulong n, slong len, slong prec) void arb_hypgeom_rising_ui_jet_rs(arb_ptr res, const arb_t x, ulong n, ulong m, slong len, slong prec) void arb_hypgeom_rising_ui_jet(arb_ptr res, const arb_t x, ulong n, slong len, slong prec) Computes the jet of the rising factorial `(x)_n`, truncated to length *len*. In other words, constructs the polynomial `(X + x)_n \in \mathbb{R}[X]`, truncated if `\operatorname{len} < n + 1` (and zero-extended if `\operatorname{len} > n + 1`). The *powsum* version computes the sequence of powers of *x* and forms integral linear combinations of these. The *bs* version uses binary splitting. The *rs* version uses rectangular splitting. It takes an extra tuning parameter *m* which can be set to zero to choose automatically. The default version chooses an algorithm automatically. Gamma function ------------------------------------------------------------------------------- .. function:: void _arb_hypgeom_gamma_stirling_term_bounds(slong * bound, const mag_t zinv, slong N) For `1 \le n < N`, sets *bound* to an exponent bounding the *n*-th term in the Stirling series for the gamma function, given a precomputed upper bound for `|z|^{-1}`. This function is intended for internal use and does not check for underflow or underflow in the exponents. .. function:: void arb_hypgeom_gamma_stirling_sum_horner(arb_t res, const arb_t z, slong N, slong prec) void arb_hypgeom_gamma_stirling_sum_improved(arb_t res, const arb_t z, slong N, slong K, slong prec) Sets *res* to the final sum in the Stirling series for the gamma function truncated before the term with index *N*, i.e. computes `\sum_{n=1}^{N-1} B_{2n} / (2n(2n-1) z^{2n-1})`. The *horner* version uses Horner scheme with gradual precision adjustments. The *improved* version uses rectangular splitting for the low-index terms and reexpands the high-index terms as hypergeometric polynomials, using a splitting parameter *K* (which can be set to 0 to use a default value). .. function:: void arb_hypgeom_gamma_stirling(arb_t res, const arb_t x, int reciprocal, slong prec) Sets *res* to the gamma function of *x* computed using the Stirling series together with argument reduction. If *reciprocal* is set, the reciprocal gamma function is computed instead. .. function:: int arb_hypgeom_gamma_taylor(arb_t res, const arb_t x, int reciprocal, slong prec) Attempts to compute the gamma function of *x* using Taylor series together with argument reduction. This is only supported if *x* and *prec* are both small enough. If successful, returns 1; otherwise, does nothing and returns 0. If *reciprocal* is set, the reciprocal gamma function is computed instead. .. function:: void arb_hypgeom_gamma(arb_t res, const arb_t x, slong prec) void arb_hypgeom_gamma_fmpq(arb_t res, const fmpq_t x, slong prec) void arb_hypgeom_gamma_fmpz(arb_t res, const fmpz_t x, slong prec) Sets *res* to the gamma function of *x* computed using a default algorithm choice. .. function:: void arb_hypgeom_rgamma(arb_t res, const arb_t x, slong prec) Sets *res* to the reciprocal gamma function of *x* computed using a default algorithm choice. .. function:: void arb_hypgeom_lgamma(arb_t res, const arb_t x, slong prec) Sets *res* to the log-gamma function of *x* computed using a default algorithm choice. Binomial coefficients ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_central_bin_ui(arb_t res, ulong n, slong prec) Computes the central binomial coefficient `{2n \choose n}`. Generalized hypergeometric function ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_pfq(arb_t res, arb_srcptr a, slong p, arb_srcptr b, slong q, const arb_t z, int regularized, slong prec) Computes the generalized hypergeometric function `{}_pF_{q}(z)`, or the regularized version if *regularized* is set. Confluent hypergeometric functions ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_0f1(arb_t res, const arb_t a, const arb_t z, int regularized, slong prec) Computes the confluent hypergeometric limit function `{}_0F_1(a,z)`, or `\frac{1}{\Gamma(a)} {}_0F_1(a,z)` if *regularized* is set. .. function:: void arb_hypgeom_m(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) Computes the confluent hypergeometric function `M(a,b,z) = {}_1F_1(a,b,z)`, or `\mathbf{M}(a,b,z) = \frac{1}{\Gamma(b)} {}_1F_1(a,b,z)` if *regularized* is set. .. function:: void arb_hypgeom_1f1(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) Alias for :func:`arb_hypgeom_m`. .. function:: void arb_hypgeom_1f1_integration(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) Computes the confluent hypergeometric function using numerical integration of the representation .. math:: {}_1F_1(a,b,z) = \frac{\Gamma(b)}{\Gamma(a) \Gamma(b-a)} \int_0^1 e^{zt} t^{a-1} (1-t)^{b-a-1} dt. This algorithm can be useful if the parameters are large. This will currently only return a finite enclosure if `a \ge 1` and `b - a \ge 1`. .. function:: void arb_hypgeom_u(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec) Computes the confluent hypergeometric function `U(a,b,z)`. .. function:: void arb_hypgeom_u_integration(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec) Computes the confluent hypergeometric function `U(a,b,z)` using numerical integration of the representation .. math:: U(a,b,z) = \frac{1}{\Gamma(a)} \int_0^{\infty} e^{-zt} t^{a-1} (1+t)^{b-a-1} dt. This algorithm can be useful if the parameters are large. This will currently only return a finite enclosure if `a \ge 1` and `z > 0`. Gauss hypergeometric function ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_2f1(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec) Computes the Gauss hypergeometric function `{}_2F_1(a,b,c,z)`, or `\mathbf{F}(a,b,c,z) = \frac{1}{\Gamma(c)} {}_2F_1(a,b,c,z)` if *regularized* is set. Additional evaluation flags can be passed via the *regularized* argument; see :func:`acb_hypgeom_2f1` for documentation. .. function:: void arb_hypgeom_2f1_integration(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec) Computes the Gauss hypergeometric function using numerical integration of the representation .. math:: {}_2F_1(a,b,c,z) = \frac{\Gamma(a)}{\Gamma(b) \Gamma(c-b)} \int_0^1 t^{b-1} (1-t)^{c-b-1} (1-zt)^{-a} dt. This algorithm can be useful if the parameters are large. This will currently only return a finite enclosure if `b \ge 1` and `c - b \ge 1` and `z < 1`, possibly with *a* and *b* exchanged. Error functions and Fresnel integrals ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_erf(arb_t res, const arb_t z, slong prec) Computes the error function `\operatorname{erf}(z)`. .. function:: void _arb_hypgeom_erf_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_erf_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the error function of the power series *z*, truncated to length *len*. .. function:: void arb_hypgeom_erfc(arb_t res, const arb_t z, slong prec) Computes the complementary error function `\operatorname{erfc}(z) = 1 - \operatorname{erf}(z)`. This function avoids catastrophic cancellation for large positive *z*. .. function:: void _arb_hypgeom_erfc_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_erfc_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the complementary error function of the power series *z*, truncated to length *len*. .. function:: void arb_hypgeom_erfi(arb_t res, const arb_t z, slong prec) Computes the imaginary error function `\operatorname{erfi}(z) = -i\operatorname{erf}(iz)`. .. function:: void _arb_hypgeom_erfi_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_erfi_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the imaginary error function of the power series *z*, truncated to length *len*. .. function:: void arb_hypgeom_erfinv(arb_t res, const arb_t z, slong prec) void arb_hypgeom_erfcinv(arb_t res, const arb_t z, slong prec) Computes the inverse error function `\operatorname{erf}^{-1}(z)` or inverse complementary error function `\operatorname{erfc}^{-1}(z)`. .. function:: void arb_hypgeom_fresnel(arb_t res1, arb_t res2, const arb_t z, int normalized, slong prec) Sets *res1* to the Fresnel sine integral `S(z)` and *res2* to the Fresnel cosine integral `C(z)`. Optionally, just a single function can be computed by passing *NULL* as the other output variable. The definition `S(z) = \int_0^z \sin(t^2) dt` is used if *normalized* is 0, and `S(z) = \int_0^z \sin(\tfrac{1}{2} \pi t^2) dt` is used if *normalized* is 1 (the latter is the Abramowitz & Stegun convention). `C(z)` is defined analogously. .. function:: void _arb_hypgeom_fresnel_series(arb_ptr res1, arb_ptr res2, arb_srcptr z, slong zlen, int normalized, slong len, slong prec) void arb_hypgeom_fresnel_series(arb_poly_t res1, arb_poly_t res2, const arb_poly_t z, int normalized, slong len, slong prec) Sets *res1* to the Fresnel sine integral and *res2* to the Fresnel cosine integral of the power series *z*, truncated to length *len*. Optionally, just a single function can be computed by passing *NULL* as the other output variable. Incomplete gamma and beta functions ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_gamma_upper(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec) If *regularized* is 0, computes the upper incomplete gamma function `\Gamma(s,z)`. If *regularized* is 1, computes the regularized upper incomplete gamma function `Q(s,z) = \Gamma(s,z) / \Gamma(s)`. If *regularized* is 2, computes the generalized exponential integral `z^{-s} \Gamma(s,z) = E_{1-s}(z)` instead (this option is mainly intended for internal use; :func:`arb_hypgeom_expint` is the intended interface for computing the exponential integral). .. function:: void arb_hypgeom_gamma_upper_integration(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec) Computes the upper incomplete gamma function using numerical integration. .. function:: void _arb_hypgeom_gamma_upper_series(arb_ptr res, const arb_t s, arb_srcptr z, slong zlen, int regularized, slong n, slong prec) void arb_hypgeom_gamma_upper_series(arb_poly_t res, const arb_t s, const arb_poly_t z, int regularized, slong n, slong prec) Sets *res* to an upper incomplete gamma function where *s* is a constant and *z* is a power series, truncated to length *n*. The *regularized* argument has the same interpretation as in :func:`arb_hypgeom_gamma_upper`. .. function:: void arb_hypgeom_gamma_lower(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec) If *regularized* is 0, computes the lower incomplete gamma function `\gamma(s,z) = \frac{z^s}{s} {}_1F_1(s, s+1, -z)`. If *regularized* is 1, computes the regularized lower incomplete gamma function `P(s,z) = \gamma(s,z) / \Gamma(s)`. If *regularized* is 2, computes a further regularized lower incomplete gamma function `\gamma^{*}(s,z) = z^{-s} P(s,z)`. .. function:: void _arb_hypgeom_gamma_lower_series(arb_ptr res, const arb_t s, arb_srcptr z, slong zlen, int regularized, slong n, slong prec) void arb_hypgeom_gamma_lower_series(arb_poly_t res, const arb_t s, const arb_poly_t z, int regularized, slong n, slong prec) Sets *res* to an lower incomplete gamma function where *s* is a constant and *z* is a power series, truncated to length *n*. The *regularized* argument has the same interpretation as in :func:`arb_hypgeom_gamma_lower`. .. function:: void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) Computes the (lower) incomplete beta function, defined by `B(a,b;z) = \int_0^z t^{a-1} (1-t)^{b-1}`, optionally the regularized incomplete beta function `I(a,b;z) = B(a,b;z) / B(a,b;1)`. .. function:: void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, slong zlen, int regularized, slong n, slong prec) void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, slong n, slong prec) Sets *res* to the lower incomplete beta function `B(a,b;z)` (optionally the regularized version `I(a,b;z)`) where *a* and *b* are constants and *z* is a power series, truncating the result to length *n*. The underscore method requires positive lengths and does not support aliasing. Internal evaluation functions ................................................................................ .. function:: void _arb_hypgeom_gamma_lower_sum_rs_1(arb_t res, ulong p, ulong q, const arb_t z, slong N, slong prec) Computes `\sum_{k=0}^{N-1} z^k / (a)_k` where `a = p/q` using rectangular splitting. It is assumed that `p + qN` fits in a limb. .. function:: void _arb_hypgeom_gamma_upper_sum_rs_1(arb_t res, ulong p, ulong q, const arb_t z, slong N, slong prec) Computes `\sum_{k=0}^{N-1} (a)_k / z^k` where `a = p/q` using rectangular splitting. It is assumed that `p + qN` fits in a limb. .. function:: slong _arb_hypgeom_gamma_upper_fmpq_inf_choose_N(mag_t err, const fmpq_t a, const arb_t z, const mag_t abs_tol) Returns number of terms *N* and sets *err* to the truncation error for evaluating `\Gamma(a,z)` using the asymptotic series at infinity, targeting an absolute tolerance of *abs_tol*. The error may be set to *err* if the tolerance cannot be achieved. Assumes that *z* is positive. .. function:: void _arb_hypgeom_gamma_upper_fmpq_inf_bsplit(arb_t res, const fmpq_t a, const arb_t z, slong N, slong prec) Sets *res* to the approximation of `\Gamma(a,z)` obtained by truncating the asymptotic series at infinity before term *N*. The truncation error bound has to be added separately. .. function:: slong _arb_hypgeom_gamma_lower_fmpq_0_choose_N(mag_t err, const fmpq_t a, const arb_t z, const mag_t abs_tol) Returns number of terms *N* and sets *err* to the truncation error for evaluating `\gamma(a,z)` using the Taylor series at zero, targeting an absolute tolerance of *abs_tol*. Assumes that *z* is positive. .. function:: void _arb_hypgeom_gamma_lower_fmpq_0_bsplit(arb_t res, const fmpq_t a, const arb_t z, slong N, slong prec) Sets *res* to the approximation of `\gamma(a,z)` obtained by truncating the Taylor series at zero before term *N*. The truncation error bound has to be added separately. .. function:: slong _arb_hypgeom_gamma_upper_singular_si_choose_N(mag_t err, slong n, const arb_t z, const mag_t abs_tol) Returns number of terms *N* and sets *err* to the truncation error for evaluating `\Gamma(-n,z)` using the Taylor series at zero, targeting an absolute tolerance of *abs_tol*. .. function:: void _arb_hypgeom_gamma_upper_singular_si_bsplit(arb_t res, slong n, const arb_t z, slong N, slong prec) Sets *res* to the approximation of `\Gamma(-n,z)` obtained by truncating the Taylor series at zero before term *N*. The truncation error bound has to be added separately. .. function:: void _arb_gamma_upper_fmpq_step_bsplit(arb_t Gz1, const fmpq_t a, const arb_t z0, const arb_t z1, const arb_t Gz0, const arb_t expmz0, const mag_t abs_tol, slong prec) Given *Gz0* and *expmz0* representing the values `\Gamma(a,z_0)` and `\exp(-z_0)`, computes `\Gamma(a,z_1)` using the Taylor series at `z_0` evaluated using binary splitting, targeting an absolute error of *abs_tol*. Assumes that `z_0` and `z_1` are positive. Exponential and trigonometric integrals ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_expint(arb_t res, const arb_t s, const arb_t z, slong prec) Computes the generalized exponential integral `E_s(z)`. .. function:: void arb_hypgeom_ei(arb_t res, const arb_t z, slong prec) Computes the exponential integral `\operatorname{Ei}(z)`. .. function:: void _arb_hypgeom_ei_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_ei_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the exponential integral of the power series *z*, truncated to length *len*. .. function:: void _arb_hypgeom_si_asymp(arb_t res, const arb_t z, slong N, slong prec) void _arb_hypgeom_si_1f2(arb_t res, const arb_t z, slong N, slong wp, slong prec) void arb_hypgeom_si(arb_t res, const arb_t z, slong prec) Computes the sine integral `\operatorname{Si}(z)`. .. function:: void _arb_hypgeom_si_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_si_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the sine integral of the power series *z*, truncated to length *len*. .. function:: void _arb_hypgeom_ci_asymp(arb_t res, const arb_t z, slong N, slong prec) void _arb_hypgeom_ci_2f3(arb_t res, const arb_t z, slong N, slong wp, slong prec) void arb_hypgeom_ci(arb_t res, const arb_t z, slong prec) Computes the cosine integral `\operatorname{Ci}(z)`. The result is indeterminate if `z < 0` since the value of the function would be complex. .. function:: void _arb_hypgeom_ci_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_ci_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the cosine integral of the power series *z*, truncated to length *len*. .. function:: void arb_hypgeom_shi(arb_t res, const arb_t z, slong prec) Computes the hyperbolic sine integral `\operatorname{Shi}(z) = -i \operatorname{Si}(iz)`. .. function:: void _arb_hypgeom_shi_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_shi_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the hyperbolic sine integral of the power series *z*, truncated to length *len*. .. function:: void arb_hypgeom_chi(arb_t res, const arb_t z, slong prec) Computes the hyperbolic cosine integral `\operatorname{Chi}(z)`. The result is indeterminate if `z < 0` since the value of the function would be complex. .. function:: void _arb_hypgeom_chi_series(arb_ptr res, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_chi_series(arb_poly_t res, const arb_poly_t z, slong len, slong prec) Computes the hyperbolic cosine integral of the power series *z*, truncated to length *len*. .. function:: void arb_hypgeom_li(arb_t res, const arb_t z, int offset, slong prec) If *offset* is zero, computes the logarithmic integral `\operatorname{li}(z) = \operatorname{Ei}(\log(z))`. If *offset* is nonzero, computes the offset logarithmic integral `\operatorname{Li}(z) = \operatorname{li}(z) - \operatorname{li}(2)`. The result is indeterminate if `z < 0` since the value of the function would be complex. .. function:: void _arb_hypgeom_li_series(arb_ptr res, arb_srcptr z, slong zlen, int offset, slong len, slong prec) void arb_hypgeom_li_series(arb_poly_t res, const arb_poly_t z, int offset, slong len, slong prec) Computes the logarithmic integral (optionally the offset version) of the power series *z*, truncated to length *len*. Bessel functions ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_bessel_j(arb_t res, const arb_t nu, const arb_t z, slong prec) Computes the Bessel function of the first kind `J_{\nu}(z)`. .. function:: void arb_hypgeom_bessel_y(arb_t res, const arb_t nu, const arb_t z, slong prec) Computes the Bessel function of the second kind `Y_{\nu}(z)`. .. function:: void arb_hypgeom_bessel_jy(arb_t res1, arb_t res2, const arb_t nu, const arb_t z, slong prec) Sets *res1* to `J_{\nu}(z)` and *res2* to `Y_{\nu}(z)`, computed simultaneously. .. function:: void arb_hypgeom_bessel_i(arb_t res, const arb_t nu, const arb_t z, slong prec) Computes the modified Bessel function of the first kind `I_{\nu}(z) = z^{\nu} (iz)^{-\nu} J_{\nu}(iz)`. .. function:: void arb_hypgeom_bessel_i_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec) Computes the function `e^{-z} I_{\nu}(z)`. .. function:: void arb_hypgeom_bessel_k(arb_t res, const arb_t nu, const arb_t z, slong prec) Computes the modified Bessel function of the second kind `K_{\nu}(z)`. .. function:: void arb_hypgeom_bessel_k_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec) Computes the function `e^{z} K_{\nu}(z)`. .. function:: void arb_hypgeom_bessel_i_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec) void arb_hypgeom_bessel_k_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec) Computes the modified Bessel functions using numerical integration. Airy functions ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_airy(arb_t ai, arb_t ai_prime, arb_t bi, arb_t bi_prime, const arb_t z, slong prec) Computes the Airy functions `(\operatorname{Ai}(z), \operatorname{Ai}'(z), \operatorname{Bi}(z), \operatorname{Bi}'(z))` simultaneously. Any of the four function values can be omitted by passing *NULL* for the unwanted output variables, speeding up the evaluation. .. function:: void arb_hypgeom_airy_jet(arb_ptr ai, arb_ptr bi, const arb_t z, slong len, slong prec) Writes to *ai* and *bi* the respective Taylor expansions of the Airy functions at the point *z*, truncated to length *len*. Either of the outputs can be *NULL* to avoid computing that function. The variable *z* is not allowed to be aliased with the outputs. To simplify the implementation, this method does not compute the series expansions of the primed versions directly; these are easily obtained by computing one extra coefficient and differentiating the output with :func:`_arb_poly_derivative`. .. function:: void _arb_hypgeom_airy_series(arb_ptr ai, arb_ptr ai_prime, arb_ptr bi, arb_ptr bi_prime, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_airy_series(arb_poly_t ai, arb_poly_t ai_prime, arb_poly_t bi, arb_poly_t bi_prime, const arb_poly_t z, slong len, slong prec) Computes the Airy functions evaluated at the power series *z*, truncated to length *len*. As with the other Airy methods, any of the outputs can be *NULL*. .. function:: void arb_hypgeom_airy_zero(arb_t a, arb_t a_prime, arb_t b, arb_t b_prime, const fmpz_t n, slong prec) Computes the *n*-th real zero `a_n`, `a'_n`, `b_n`, or `b'_n` for the respective Airy function or Airy function derivative. Any combination of the four output variables can be *NULL*. The zeros are indexed by increasing magnitude, starting with `n = 1` to follow the convention in the literature. An index *n* that is not positive is invalid input. The implementation uses asymptotic expansions for the zeros [PS1991]_ together with the interval Newton method for refinement. Coulomb wave functions ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_coulomb(arb_t F, arb_t G, const arb_t l, const arb_t eta, const arb_t z, slong prec) Writes to *F*, *G* the values of the respective Coulomb wave functions `F_{\ell}(\eta,z)` and `G_{\ell}(\eta,z)`. Either of the outputs can be *NULL*. .. function:: void arb_hypgeom_coulomb_jet(arb_ptr F, arb_ptr G, const arb_t l, const arb_t eta, const arb_t z, slong len, slong prec) Writes to *F*, *G* the respective Taylor expansions of the Coulomb wave functions at the point *z*, truncated to length *len*. Either of the outputs can be *NULL*. .. function:: void _arb_hypgeom_coulomb_series(arb_ptr F, arb_ptr G, const arb_t l, const arb_t eta, arb_srcptr z, slong zlen, slong len, slong prec) void arb_hypgeom_coulomb_series(arb_poly_t F, arb_poly_t G, const arb_t l, const arb_t eta, const arb_poly_t z, slong len, slong prec) Computes the Coulomb wave functions evaluated at the power series *z*, truncated to length *len*. Either of the outputs can be *NULL*. Orthogonal polynomials and functions ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_chebyshev_t(arb_t res, const arb_t nu, const arb_t z, slong prec) void arb_hypgeom_chebyshev_u(arb_t res, const arb_t nu, const arb_t z, slong prec) void arb_hypgeom_jacobi_p(arb_t res, const arb_t n, const arb_t a, const arb_t b, const arb_t z, slong prec) void arb_hypgeom_gegenbauer_c(arb_t res, const arb_t n, const arb_t m, const arb_t z, slong prec) void arb_hypgeom_laguerre_l(arb_t res, const arb_t n, const arb_t m, const arb_t z, slong prec) void arb_hypgeom_hermite_h(arb_t res, const arb_t nu, const arb_t z, slong prec) Computes Chebyshev, Jacobi, Gegenbauer, Laguerre or Hermite polynomials, or their extensions to non-integer orders. .. function:: void arb_hypgeom_legendre_p(arb_t res, const arb_t n, const arb_t m, const arb_t z, int type, slong prec) void arb_hypgeom_legendre_q(arb_t res, const arb_t n, const arb_t m, const arb_t z, int type, slong prec) Computes Legendre functions of the first and second kind. See :func:`acb_hypgeom_legendre_p` and :func:`acb_hypgeom_legendre_q` for definitions. .. function:: void arb_hypgeom_legendre_p_ui_deriv_bound(mag_t dp, mag_t dp2, ulong n, const arb_t x, const arb_t x2sub1) Sets *dp* to an upper bound for `P'_n(x)` and *dp2* to an upper bound for `P''_n(x)` given *x* assumed to represent a real number with `|x| \le 1`. The variable *x2sub1* must contain the precomputed value `1-x^2` (or `x^2-1`). This method is used internally to bound the propagated error for Legendre polynomials. .. function:: void arb_hypgeom_legendre_p_ui_zero(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong K, slong prec) void arb_hypgeom_legendre_p_ui_one(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong K, slong prec) void arb_hypgeom_legendre_p_ui_asymp(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong K, slong prec) void arb_hypgeom_legendre_p_ui_rec(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong prec) void arb_hypgeom_legendre_p_ui(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong prec) Evaluates the ordinary Legendre polynomial `P_n(x)`. If *res_prime* is non-NULL, simultaneously evaluates the derivative `P'_n(x)`. The overall algorithm is described in [JM2018]_. The versions *zero*, *one* respectively use the hypergeometric series expansions at `x = 0` and `x = 1` while the *asymp* version uses an asymptotic series on `(-1,1)` intended for large *n*. The parameter *K* specifies the exact number of expansion terms to use (if the series expansion truncated at this point does not give the exact polynomial, an error bound is computed automatically). The asymptotic expansion with error bounds is given in [Bog2012]_. The *rec* version uses the forward recurrence implemented using fixed-point arithmetic; it is only intended for the interval `(-1,1)`, moderate *n* and modest precision. The default version attempts to choose the best algorithm automatically. It also estimates the amount of cancellation in the hypergeometric series and increases the working precision to compensate, bounding the propagated error using derivative bounds. .. function:: void arb_hypgeom_legendre_p_ui_root(arb_t res, arb_t weight, ulong n, ulong k, slong prec) Sets *res* to the *k*-th root of the Legendre polynomial `P_n(x)`. We index the roots in decreasing order .. math:: 1 > x_0 > x_1 > \ldots > x_{n-1} > -1 (which corresponds to ordering the roots of `P_n(\cos(\theta))` in order of increasing `\theta`). If *weight* is non-NULL, it is set to the weight corresponding to the node `x_k` for Gaussian quadrature on `[-1,1]`. Note that only `\lceil n / 2 \rceil` roots need to be computed, since the remaining roots are given by `x_k = -x_{n-1-k}`. We compute an enclosing interval using an asymptotic approximation followed by some number of Newton iterations, using the error bounds given in [Pet1999]_. If very high precision is requested, the root is subsequently refined using interval Newton steps with doubling working precision. Dilogarithm ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_dilog(arb_t res, const arb_t z, slong prec) Computes the dilogarithm `\operatorname{Li}_2(z)`. Hypergeometric sums ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_sum_fmpq_arb_forward(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) void arb_hypgeom_sum_fmpq_arb_rs(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) void arb_hypgeom_sum_fmpq_arb(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) Sets *res* to the finite hypergeometric sum `\sum_{n=0}^{N-1} (\textbf{a})_n z^n / (\textbf{b})_n` where `\textbf{x}_n = (x_1)_n (x_2)_n \cdots`, given vectors of rational parameters *a* (of length *alen*) and *b* (of length *blen*). If *reciprocal* is set, replace `z` by `1 / z`. The *forward* version uses the forward recurrence, optimized by delaying divisions, the *rs* version uses rectangular splitting, and the default version uses an automatic algorithm choice. .. function:: void arb_hypgeom_sum_fmpq_imag_arb_forward(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) void arb_hypgeom_sum_fmpq_imag_arb_rs(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) void arb_hypgeom_sum_fmpq_imag_arb_bs(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) void arb_hypgeom_sum_fmpq_imag_arb(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) Sets *res1* and *res2* to the real and imaginary part of the finite hypergeometric sum `\sum_{n=0}^{N-1} (\textbf{a})_n (i z)^n / (\textbf{b})_n`. If *reciprocal* is set, replace `z` by `1 / z`. flint-3.1.3/doc/source/arb_mat.rst000066400000000000000000001065501461254215100170460ustar00rootroot00000000000000.. _arb-mat: **arb_mat.h** -- matrices over the real numbers =============================================================================== An :type:`arb_mat_t` represents a dense matrix over the real numbers, implemented as an array of entries of type :type:`arb_struct`. The dimension (number of rows and columns) of a matrix is fixed at initialization, and the user must ensure that inputs and outputs to an operation have compatible dimensions. The number of rows or columns in a matrix can be zero. .. note:: Methods prefixed with *arb_mat_approx* treat all input entries as floating-point numbers (ignoring the radii of the balls) and compute floating-point output (balls with zero radius) representing approximate solutions *without error bounds*. All other methods compute rigorous error bounds. The *approx* methods are typically useful for computing initial values or preconditioners for rigorous solvers. Some users may also find *approx* methods useful for doing ordinary numerical linear algebra in applications where error bounds are not needed. Types, macros and constants ------------------------------------------------------------------------------- .. type:: arb_mat_struct .. type:: arb_mat_t Contains a pointer to a flat array of the entries (entries), an array of pointers to the start of each row (rows), and the number of rows (r) and columns (c). An *arb_mat_t* is defined as an array of length one of type *arb_mat_struct*, permitting an *arb_mat_t* to be passed by reference. .. macro:: arb_mat_entry(mat, i, j) Macro giving a pointer to the entry at row *i* and column *j*. .. macro:: arb_mat_nrows(mat) Returns the number of rows of the matrix. .. macro:: arb_mat_ncols(mat) Returns the number of columns of the matrix. Memory management ------------------------------------------------------------------------------- .. function:: void arb_mat_init(arb_mat_t mat, slong r, slong c) Initializes the matrix, setting it to the zero matrix with *r* rows and *c* columns. .. function:: void arb_mat_clear(arb_mat_t mat) Clears the matrix, deallocating all entries. .. function:: slong arb_mat_allocated_bytes(const arb_mat_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(arb_mat_struct)`` to get the size of the object as a whole. .. function:: void arb_mat_window_init(arb_mat_t window, const arb_mat_t mat, slong r1, slong c1, slong r2, slong c2) Initializes *window* to a window matrix into the submatrix of *mat* starting at the corner at row *r1* and column *c1* (inclusive) and ending at row *r2* and column *c2* (exclusive). .. function:: void arb_mat_window_clear(arb_mat_t window) Frees the window matrix. Conversions ------------------------------------------------------------------------------- .. function:: void arb_mat_set(arb_mat_t dest, const arb_mat_t src) .. function:: void arb_mat_set_fmpz_mat(arb_mat_t dest, const fmpz_mat_t src) .. function:: void arb_mat_set_round_fmpz_mat(arb_mat_t dest, const fmpz_mat_t src, slong prec) .. function:: void arb_mat_set_fmpq_mat(arb_mat_t dest, const fmpq_mat_t src, slong prec) Sets *dest* to *src*. The operands must have identical dimensions. Random generation ------------------------------------------------------------------------------- .. function:: void arb_mat_randtest(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) Sets *mat* to a random matrix with up to *prec* bits of precision and with exponents of width up to *mag_bits*. .. function:: void arb_mat_randtest_cho(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) Sets *mat* to a random lower-triangular matrix with precise entries and positive diagonal entries. Requires that *mat* is square. .. function:: void arb_mat_randtest_spd(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) Sets *mat* to a random symmetric positive definite matrix, obtained as a product `L L^T` where *L* is a random Cholesky matrix. Requires that *mat* is square. Input and output ------------------------------------------------------------------------------- .. function:: void arb_mat_printd(const arb_mat_t mat, slong digits) Prints each entry in the matrix with the specified number of decimal digits. .. function:: void arb_mat_fprintd(FILE * file, const arb_mat_t mat, slong digits) Prints each entry in the matrix with the specified number of decimal digits to the stream *file*. Comparisons ------------------------------------------------------------------------------- Predicate methods return 1 if the property certainly holds and 0 otherwise. .. function:: int arb_mat_equal(const arb_mat_t mat1, const arb_mat_t mat2) Returns whether the matrices have the same dimensions and identical intervals as entries. .. function:: int arb_mat_overlaps(const arb_mat_t mat1, const arb_mat_t mat2) Returns whether the matrices have the same dimensions and each entry in *mat1* overlaps with the corresponding entry in *mat2*. .. function:: int arb_mat_contains(const arb_mat_t mat1, const arb_mat_t mat2) .. function:: int arb_mat_contains_fmpz_mat(const arb_mat_t mat1, const fmpz_mat_t mat2) .. function:: int arb_mat_contains_fmpq_mat(const arb_mat_t mat1, const fmpq_mat_t mat2) Returns whether the matrices have the same dimensions and each entry in *mat2* is contained in the corresponding entry in *mat1*. .. function:: int arb_mat_eq(const arb_mat_t mat1, const arb_mat_t mat2) Returns whether *mat1* and *mat2* certainly represent the same matrix. .. function:: int arb_mat_ne(const arb_mat_t mat1, const arb_mat_t mat2) Returns whether *mat1* and *mat2* certainly do not represent the same matrix. .. function:: int arb_mat_is_empty(const arb_mat_t mat) Returns whether the number of rows or the number of columns in *mat* is zero. .. function:: int arb_mat_is_square(const arb_mat_t mat) Returns whether the number of rows is equal to the number of columns in *mat*. .. function:: int arb_mat_is_exact(const arb_mat_t mat) Returns whether all entries in *mat* have zero radius. .. function:: int arb_mat_is_zero(const arb_mat_t mat) Returns whether all entries in *mat* are exactly zero. .. function:: int arb_mat_is_finite(const arb_mat_t mat) Returns whether all entries in *mat* are finite. .. function:: int arb_mat_is_triu(const arb_mat_t mat) Returns whether *mat* is upper triangular; that is, all entries below the main diagonal are exactly zero. .. function:: int arb_mat_is_tril(const arb_mat_t mat) Returns whether *mat* is lower triangular; that is, all entries above the main diagonal are exactly zero. .. function:: int arb_mat_is_diag(const arb_mat_t mat) Returns whether *mat* is a diagonal matrix; that is, all entries off the main diagonal are exactly zero. Special matrices ------------------------------------------------------------------------------- .. function:: void arb_mat_zero(arb_mat_t mat) Sets all entries in mat to zero. .. function:: void arb_mat_one(arb_mat_t mat) Sets the entries on the main diagonal to ones, and all other entries to zero. .. function:: void arb_mat_ones(arb_mat_t mat) Sets all entries in the matrix to ones. .. function:: void arb_mat_indeterminate(arb_mat_t mat) Sets all entries in the matrix to indeterminate (NaN). .. function:: void arb_mat_hilbert(arb_mat_t mat, slong prec) Sets *mat* to the Hilbert matrix, which has entries `A_{j,k} = 1/(j+k+1)`. .. function:: void arb_mat_pascal(arb_mat_t mat, int triangular, slong prec) Sets *mat* to a Pascal matrix, whose entries are binomial coefficients. If *triangular* is 0, constructs a full symmetric matrix with the rows of Pascal's triangle as successive antidiagonals. If *triangular* is 1, constructs the upper triangular matrix with the rows of Pascal's triangle as columns, and if *triangular* is -1, constructs the lower triangular matrix with the rows of Pascal's triangle as rows. The entries are computed using recurrence relations. When the dimensions get large, some precision loss is possible; in that case, the user may wish to create the matrix at slightly higher precision and then round it to the final precision. .. function:: void arb_mat_stirling(arb_mat_t mat, int kind, slong prec) Sets *mat* to a Stirling matrix, whose entries are Stirling numbers. If *kind* is 0, the entries are set to the unsigned Stirling numbers of the first kind. If *kind* is 1, the entries are set to the signed Stirling numbers of the first kind. If *kind* is 2, the entries are set to the Stirling numbers of the second kind. The entries are computed using recurrence relations. When the dimensions get large, some precision loss is possible; in that case, the user may wish to create the matrix at slightly higher precision and then round it to the final precision. .. function:: void arb_mat_dct(arb_mat_t mat, int type, slong prec) Sets *mat* to the DCT (discrete cosine transform) matrix of order *n* where *n* is the smallest dimension of *mat* (if *mat* is not square, the matrix is extended periodically along the larger dimension). There are many different conventions for defining DCT matrices; here, we use the normalized "DCT-II" transform matrix .. math:: A_{j,k} = \sqrt{\frac{2}{n}} \cos\left(\frac{\pi j}{n} \left(k+\frac{1}{2}\right)\right) which satisfies `A^{-1} = A^T`. The *type* parameter is currently ignored and should be set to 0. In the future, it might be used to select a different convention. Transpose ------------------------------------------------------------------------------- .. function:: void arb_mat_transpose(arb_mat_t dest, const arb_mat_t src) Sets *dest* to the exact transpose *src*. The operands must have compatible dimensions. Aliasing is allowed. Norms ------------------------------------------------------------------------------- .. function:: void arb_mat_bound_inf_norm(mag_t b, const arb_mat_t A) Sets *b* to an upper bound for the infinity norm (i.e. the largest absolute value row sum) of *A*. .. function:: void arb_mat_frobenius_norm(arb_t res, const arb_mat_t A, slong prec) Sets *res* to the Frobenius norm (i.e. the square root of the sum of squares of entries) of *A*. .. function:: void arb_mat_bound_frobenius_norm(mag_t res, const arb_mat_t A) Sets *res* to an upper bound for the Frobenius norm of *A*. Arithmetic ------------------------------------------------------------------------------- .. function:: void arb_mat_neg(arb_mat_t dest, const arb_mat_t src) Sets *dest* to the exact negation of *src*. The operands must have the same dimensions. .. function:: void arb_mat_add(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) Sets res to the sum of *mat1* and *mat2*. The operands must have the same dimensions. .. function:: void arb_mat_sub(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) Sets *res* to the difference of *mat1* and *mat2*. The operands must have the same dimensions. .. function:: void arb_mat_mul_classical(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) .. function:: void arb_mat_mul_threaded(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) .. function:: void arb_mat_mul_block(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) .. function:: void arb_mat_mul(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) Sets *res* to the matrix product of *mat1* and *mat2*. The operands must have compatible dimensions for matrix multiplication. The *classical* version performs matrix multiplication in the trivial way. The *block* version decomposes the input matrices into one or several blocks of uniformly scaled matrices and multiplies large blocks via *fmpz_mat_mul*. It also invokes :func:`_arb_mat_addmul_rad_mag_fast` for the radius matrix multiplications. The *threaded* version performs classical multiplication but splits the computation over the number of threads returned by *flint_get_num_threads()*. The default version chooses an algorithm automatically. .. function:: void arb_mat_mul_entrywise(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) Sets *C* to the entrywise product of *A* and *B*. The operands must have the same dimensions. .. function:: void arb_mat_sqr_classical(arb_mat_t B, const arb_mat_t A, slong prec) .. function:: void arb_mat_sqr(arb_mat_t res, const arb_mat_t mat, slong prec) Sets *res* to the matrix square of *mat*. The operands must both be square with the same dimensions. .. function:: void arb_mat_pow_ui(arb_mat_t res, const arb_mat_t mat, ulong exp, slong prec) Sets *res* to *mat* raised to the power *exp*. Requires that *mat* is a square matrix. .. function:: void _arb_mat_addmul_rad_mag_fast(arb_mat_t C, mag_srcptr A, mag_srcptr B, slong ar, slong ac, slong bc) Helper function for matrix multiplication. Adds to the radii of *C* the matrix product of the matrices represented by *A* and *B*, where *A* is a linear array of coefficients in row-major order and *B* is a linear array of coefficients in column-major order. This function assumes that all exponents are small and is unsafe for general use. .. function:: void arb_mat_approx_mul(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) Approximate matrix multiplication. The input radii are ignored and the output matrix is set to an approximate floating-point result. The radii in the output matrix will *not* necessarily be zeroed. Scalar arithmetic ------------------------------------------------------------------------------- .. function:: void arb_mat_scalar_mul_2exp_si(arb_mat_t B, const arb_mat_t A, slong c) Sets *B* to *A* multiplied by `2^c`. .. function:: void arb_mat_scalar_addmul_si(arb_mat_t B, const arb_mat_t A, slong c, slong prec) .. function:: void arb_mat_scalar_addmul_fmpz(arb_mat_t B, const arb_mat_t A, const fmpz_t c, slong prec) .. function:: void arb_mat_scalar_addmul_arb(arb_mat_t B, const arb_mat_t A, const arb_t c, slong prec) Sets *B* to `B + A \times c`. .. function:: void arb_mat_scalar_mul_si(arb_mat_t B, const arb_mat_t A, slong c, slong prec) .. function:: void arb_mat_scalar_mul_fmpz(arb_mat_t B, const arb_mat_t A, const fmpz_t c, slong prec) .. function:: void arb_mat_scalar_mul_arb(arb_mat_t B, const arb_mat_t A, const arb_t c, slong prec) Sets *B* to `A \times c`. .. function:: void arb_mat_scalar_div_si(arb_mat_t B, const arb_mat_t A, slong c, slong prec) .. function:: void arb_mat_scalar_div_fmpz(arb_mat_t B, const arb_mat_t A, const fmpz_t c, slong prec) .. function:: void arb_mat_scalar_div_arb(arb_mat_t B, const arb_mat_t A, const arb_t c, slong prec) Sets *B* to `A / c`. Vector arithmetic ------------------------------------------------------------------------------- .. function:: void _arb_mat_vector_mul_row(arb_ptr res, arb_srcptr v, const arb_mat_t A, slong prec) .. function:: void _arb_mat_vector_mul_col(arb_ptr res, const arb_mat_t A, arb_srcptr v, slong prec) .. function:: void arb_mat_vector_mul_row(arb_ptr res, arb_srcptr v, const arb_mat_t A, slong prec) .. function:: void arb_mat_vector_mul_col(arb_ptr res, const arb_mat_t A, arb_srcptr v, slong prec) Sets *res* to the product `vA`, (resp. `Av`), where *res* and *v* are seen as row (resp. column) vectors. The lengths of the vectors must match the dimensions of *A*. The underscore methods do not allow aliasing between *res* and *v*. Gaussian elimination and solving ------------------------------------------------------------------------------- .. function:: int arb_mat_lu_classical(slong * perm, arb_mat_t LU, const arb_mat_t A, slong prec) .. function:: int arb_mat_lu_recursive(slong * perm, arb_mat_t LU, const arb_mat_t A, slong prec) .. function:: int arb_mat_lu(slong * perm, arb_mat_t LU, const arb_mat_t A, slong prec) Given an `n \times n` matrix `A`, computes an LU decomposition `PLU = A` using Gaussian elimination with partial pivoting. The input and output matrices can be the same, performing the decomposition in-place. Entry `i` in the permutation vector perm is set to the row index in the input matrix corresponding to row `i` in the output matrix. The algorithm succeeds and returns nonzero if it can find `n` invertible (i.e. not containing zero) pivot entries. This guarantees that the matrix is invertible. The algorithm fails and returns zero, leaving the entries in `P` and `LU` undefined, if it cannot find `n` invertible pivot elements. In this case, either the matrix is singular, the input matrix was computed to insufficient precision, or the LU decomposition was attempted at insufficient precision. The *classical* version uses Gaussian elimination directly while the *recursive* version performs the computation in a block recursive way to benefit from fast matrix multiplication. The default version chooses an algorithm automatically. .. function:: void arb_mat_solve_tril_classical(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) .. function:: void arb_mat_solve_tril_recursive(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) .. function:: void arb_mat_solve_tril(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) .. function:: void arb_mat_solve_triu_classical(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) .. function:: void arb_mat_solve_triu_recursive(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) .. function:: void arb_mat_solve_triu(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) Solves the lower triangular system `LX = B` or the upper triangular system `UX = B`, respectively. If *unit* is set, the main diagonal of *L* or *U* is taken to consist of all ones, and in that case the actual entries on the diagonal are not read at all and can contain other data. The *classical* versions perform the computations iteratively while the *recursive* versions perform the computations in a block recursive way to benefit from fast matrix multiplication. The default versions choose an algorithm automatically. .. function:: void arb_mat_solve_lu_precomp(arb_mat_t X, const slong * perm, const arb_mat_t LU, const arb_mat_t B, slong prec) Solves `AX = B` given the precomputed nonsingular LU decomposition `A = PLU`. The matrices `X` and `B` are allowed to be aliased with each other, but `X` is not allowed to be aliased with `LU`. .. function:: int arb_mat_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) .. function:: int arb_mat_solve_lu(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) .. function:: int arb_mat_solve_precond(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) Solves `AX = B` where `A` is a nonsingular `n \times n` matrix and `X` and `B` are `n \times m` matrices. If `m > 0` and `A` cannot be inverted numerically (indicating either that `A` is singular or that the precision is insufficient), the values in the output matrix are left undefined and zero is returned. A nonzero return value guarantees that `A` is invertible and that the exact solution matrix is contained in the output. Three algorithms are provided: * The *lu* version performs LU decomposition directly in ball arithmetic. This is fast, but the bounds typically blow up exponentially with *n*, even if the system is well-conditioned. This algorithm is usually the best choice at very high precision. * The *precond* version computes an approximate inverse to precondition the system [HS1967]_. This is usually several times slower than direct LU decomposition, but the bounds do not blow up with *n* if the system is well-conditioned. This algorithm is usually the best choice for large systems at low to moderate precision. * The default version selects between *lu* and *precomp* automatically. The automatic choice should be reasonable most of the time, but users may benefit from trying either *lu* or *precond* in specific applications. For example, the *lu* solver often performs better for ill-conditioned systems where use of very high precision is unavoidable. .. function:: int arb_mat_solve_preapprox(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, const arb_mat_t R, const arb_mat_t T, slong prec) Solves `AX = B` where `A` is a nonsingular `n \times n` matrix and `X` and `B` are `n \times m` matrices, given an approximation `R` of the matrix inverse of `A`, and given the approximation `T` of the solution `X`. If `m > 0` and `A` cannot be inverted numerically (indicating either that `A` is singular or that the precision is insufficient, or that `R` is not a close enough approximation of the inverse of `A`), the values in the output matrix are left undefined and zero is returned. A nonzero return value guarantees that `A` is invertible and that the exact solution matrix is contained in the output. .. function:: int arb_mat_inv(arb_mat_t X, const arb_mat_t A, slong prec) Sets `X = A^{-1}` where `A` is a square matrix, computed by solving the system `AX = I`. If `A` cannot be inverted numerically (indicating either that `A` is singular or that the precision is insufficient), the values in the output matrix are left undefined and zero is returned. A nonzero return value guarantees that the matrix is invertible and that the exact inverse is contained in the output. .. function:: void arb_mat_det_lu(arb_t det, const arb_mat_t A, slong prec) .. function:: void arb_mat_det_precond(arb_t det, const arb_mat_t A, slong prec) .. function:: void arb_mat_det(arb_t det, const arb_mat_t A, slong prec) Sets *det* to the determinant of the matrix *A*. The *lu* version uses Gaussian elimination with partial pivoting. If at some point an invertible pivot element cannot be found, the elimination is stopped and the magnitude of the determinant of the remaining submatrix is bounded using Hadamard's inequality. The *precond* version computes an approximate LU factorization of *A* and multiplies by the inverse *L* and *U* martices as preconditioners to obtain a matrix close to the identity matrix [Rum2010]_. An enclosure for this determinant is computed using Gershgorin circles. This is about four times slower than direct Gaussian elimination, but much more numerically stable. The default version automatically selects between the *lu* and *precond* versions and additionally handles small or triangular matrices by direct formulas. .. function:: void arb_mat_approx_solve_triu(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) .. function:: void arb_mat_approx_solve_tril(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) .. function:: int arb_mat_approx_lu(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec) .. function:: void arb_mat_approx_solve_lu_precomp(arb_mat_t X, const slong * perm, const arb_mat_t A, const arb_mat_t B, slong prec) .. function:: int arb_mat_approx_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) .. function:: int arb_mat_approx_inv(arb_mat_t X, const arb_mat_t A, slong prec) These methods perform approximate solving *without any error control*. The radii in the input matrices are ignored, the computations are done numerically with floating-point arithmetic (using ordinary Gaussian elimination and triangular solving, accelerated through the use of block recursive strategies for large matrices), and the output matrices are set to the approximate floating-point results with zeroed error bounds. Approximate solutions are useful for computing preconditioning matrices for certified solutions. Some users may also find these methods useful for doing ordinary numerical linear algebra in applications where error bounds are not needed. Cholesky decomposition and solving ------------------------------------------------------------------------------- .. function:: int _arb_mat_cholesky_banachiewicz(arb_mat_t A, slong prec) .. function:: int arb_mat_cho(arb_mat_t L, const arb_mat_t A, slong prec) Computes the Cholesky decomposition of *A*, returning nonzero iff the symmetric matrix defined by the lower triangular part of *A* is certainly positive definite. If a nonzero value is returned, then *L* is set to the lower triangular matrix such that `A = L * L^T`. If zero is returned, then either the matrix is not symmetric positive definite, the input matrix was computed to insufficient precision, or the decomposition was attempted at insufficient precision. The underscore method computes *L* from *A* in-place, leaving the strict upper triangular region undefined. .. function:: void arb_mat_solve_cho_precomp(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, slong prec) Solves `AX = B` given the precomputed Cholesky decomposition `A = L L^T`. The matrices *X* and *B* are allowed to be aliased with each other, but *X* is not allowed to be aliased with *L*. .. function:: int arb_mat_spd_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) Solves `AX = B` where *A* is a symmetric positive definite matrix and *X* and *B* are `n \times m` matrices, using Cholesky decomposition. If `m > 0` and *A* cannot be factored using Cholesky decomposition (indicating either that *A* is not symmetric positive definite or that the precision is insufficient), the values in the output matrix are left undefined and zero is returned. A nonzero return value guarantees that the symmetric matrix defined through the lower triangular part of *A* is invertible and that the exact solution matrix is contained in the output. .. function:: void arb_mat_inv_cho_precomp(arb_mat_t X, const arb_mat_t L, slong prec) Sets `X = A^{-1}` where `A` is a symmetric positive definite matrix whose Cholesky decomposition *L* has been computed with :func:`arb_mat_cho`. The inverse is calculated using the method of [Kri2013]_ which is more efficient than solving `AX = I` with :func:`arb_mat_solve_cho_precomp`. .. function:: int arb_mat_spd_inv(arb_mat_t X, const arb_mat_t A, slong prec) Sets `X = A^{-1}` where *A* is a symmetric positive definite matrix. It is calculated using the method of [Kri2013]_ which computes fewer intermediate results than solving `AX = I` with :func:`arb_mat_spd_solve`. If *A* cannot be factored using Cholesky decomposition (indicating either that *A* is not symmetric positive definite or that the precision is insufficient), the values in the output matrix are left undefined and zero is returned. A nonzero return value guarantees that the symmetric matrix defined through the lower triangular part of *A* is invertible and that the exact inverse is contained in the output. .. function:: int _arb_mat_ldl_inplace(arb_mat_t A, slong prec) .. function:: int _arb_mat_ldl_golub_and_van_loan(arb_mat_t A, slong prec) .. function:: int arb_mat_ldl(arb_mat_t res, const arb_mat_t A, slong prec) Computes the `LDL^T` decomposition of *A*, returning nonzero iff the symmetric matrix defined by the lower triangular part of *A* is certainly positive definite. If a nonzero value is returned, then *res* is set to a lower triangular matrix that encodes the `L * D * L^T` decomposition of *A*. In particular, `L` is a lower triangular matrix with ones on its diagonal and whose strictly lower triangular region is the same as that of *res*. `D` is a diagonal matrix with the same diagonal as that of *res*. If zero is returned, then either the matrix is not symmetric positive definite, the input matrix was computed to insufficient precision, or the decomposition was attempted at insufficient precision. The underscore methods compute *res* from *A* in-place, leaving the strict upper triangular region undefined. The default method uses algorithm 4.1.2 from [GVL1996]_. .. function:: void arb_mat_solve_ldl_precomp(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, slong prec) Solves `AX = B` given the precomputed `A = LDL^T` decomposition encoded by *L*. The matrices *X* and *B* are allowed to be aliased with each other, but *X* is not allowed to be aliased with *L*. .. function:: void arb_mat_inv_ldl_precomp(arb_mat_t X, const arb_mat_t L, slong prec) Sets `X = A^{-1}` where `A` is a symmetric positive definite matrix whose `LDL^T` decomposition encoded by *L* has been computed with :func:`arb_mat_ldl`. The inverse is calculated using the method of [Kri2013]_ which is more efficient than solving `AX = I` with :func:`arb_mat_solve_ldl_precomp`. Characteristic polynomial and companion matrix ------------------------------------------------------------------------------- .. function:: void _arb_mat_charpoly(arb_ptr poly, const arb_mat_t mat, slong prec) .. function:: void arb_mat_charpoly(arb_poly_t poly, const arb_mat_t mat, slong prec) Sets *poly* to the characteristic polynomial of *mat* which must be a square matrix. If the matrix has *n* rows, the underscore method requires space for `n + 1` output coefficients. Employs a division-free algorithm using `O(n^4)` operations. .. function:: void _arb_mat_companion(arb_mat_t mat, arb_srcptr poly, slong prec) .. function:: void arb_mat_companion(arb_mat_t mat, const arb_poly_t poly, slong prec) Sets the *n* by *n* matrix *mat* to the companion matrix of the polynomial *poly* which must have degree *n*. The underscore method reads `n + 1` input coefficients. Special functions ------------------------------------------------------------------------------- .. function:: void arb_mat_exp_taylor_sum(arb_mat_t S, const arb_mat_t A, slong N, slong prec) Sets *S* to the truncated exponential Taylor series `S = \sum_{k=0}^{N-1} A^k / k!`. Uses rectangular splitting to compute the sum using `O(\sqrt{N})` matrix multiplications. The recurrence relation for factorials is used to get scalars that are small integers instead of full factorials. As in [Joh2014b]_, all divisions are postponed to the end by computing partial factorials of length `O(\sqrt{N})`. The scalars could be reduced by doing more divisions, but this appears to be slower in most cases. .. function:: void arb_mat_exp(arb_mat_t B, const arb_mat_t A, slong prec) Sets *B* to the exponential of the matrix *A*, defined by the Taylor series .. math:: \exp(A) = \sum_{k=0}^{\infty} \frac{A^k}{k!}. The function is evaluated as `\exp(A/2^r)^{2^r}`, where `r` is chosen to give rapid convergence. The elementwise error when truncating the Taylor series after *N* terms is bounded by the error in the infinity norm, for which we have .. math:: \left\|\exp(2^{-r}A) - \sum_{k=0}^{N-1} \frac{\left(2^{-r} A\right)^k}{k!} \right\|_{\infty} = \left\|\sum_{k=N}^{\infty} \frac{\left(2^{-r} A\right)^k}{k!}\right\|_{\infty} \le \sum_{k=N}^{\infty} \frac{(2^{-r} \|A\|_{\infty})^k}{k!}. We bound the sum on the right using :func:`mag_exp_tail`. Truncation error is not added to entries whose values are determined by the sparsity structure of `A`. .. function:: void arb_mat_trace(arb_t trace, const arb_mat_t mat, slong prec) Sets *trace* to the trace of the matrix, i.e. the sum of entries on the main diagonal of *mat*. The matrix is required to be square. .. function:: void _arb_mat_diag_prod(arb_t res, const arb_mat_t mat, slong a, slong b, slong prec) .. function:: void arb_mat_diag_prod(arb_t res, const arb_mat_t mat, slong prec) Sets *res* to the product of the entries on the main diagonal of *mat*. The underscore method computes the product of the entries between index *a* inclusive and *b* exclusive (the indices must be in range). Sparsity structure ------------------------------------------------------------------------------- .. function:: void arb_mat_entrywise_is_zero(fmpz_mat_t dest, const arb_mat_t src) Sets each entry of *dest* to indicate whether the corresponding entry of *src* is certainly zero. If the entry of *src* at row `i` and column `j` is zero according to :func:`arb_is_zero` then the entry of *dest* at that row and column is set to one, otherwise that entry of *dest* is set to zero. .. function:: void arb_mat_entrywise_not_is_zero(fmpz_mat_t dest, const arb_mat_t src) Sets each entry of *dest* to indicate whether the corresponding entry of *src* is not certainly zero. This the complement of :func:`arb_mat_entrywise_is_zero`. .. function:: slong arb_mat_count_is_zero(const arb_mat_t mat) Returns the number of entries of *mat* that are certainly zero according to :func:`arb_is_zero`. .. function:: slong arb_mat_count_not_is_zero(const arb_mat_t mat) Returns the number of entries of *mat* that are not certainly zero. Component and error operations ------------------------------------------------------------------------------- .. function:: void arb_mat_get_mid(arb_mat_t B, const arb_mat_t A) Sets the entries of *B* to the exact midpoints of the entries of *A*. .. function:: void arb_mat_add_error_mag(arb_mat_t mat, const mag_t err) Adds *err* in-place to the radii of the entries of *mat*. Eigenvalues and eigenvectors ------------------------------------------------------------------------------- To compute eigenvalues and eigenvectors, one can convert to an :type:`acb_mat_t` and use the functions in :ref:`acb_mat.h: Eigenvalues and eigenvectors`. In the future dedicated methods for real matrices will be added here. LLL reduction ------------------------------------------------------------------------------- .. function:: int arb_mat_spd_get_fmpz_mat(fmpz_mat_t B, const arb_mat_t A, slong prec) Attempts to set *B* to a symmetric and positive definite matrix obtained by rounding the midpoints of entries of `2^{\mathit{prec}}\cdot A` to integers. Returns 1 on success. Returns 0 and leaves *B* undefined if *A* is not symmetric or the result of rounding is not a positive definite matrix. The warnings of :func:`arf_get_fmpz` apply. .. function:: void arb_mat_spd_lll_reduce(fmpz_mat_t U, const arb_mat_t A, slong prec) Given a symmetric positive definite matrix *A*, sets *U* to an invertible matrix such that `U^T A U` is close to being LLL-reduced. If :func:`arb_mat_spd_get_fmpz_mat` succeeds at the chosen precision, we call :func:`fmpz_lll`, and otherwise set *U* to the identity matrix. The warnings of :func:`arf_get_fmpz` apply. .. function:: int arb_mat_spd_is_lll_reduced(const arb_mat_t A, slong tol_exp, slong prec) Given a symmetric positive definite matrix *A*, returns nonzero iff *A* is certainly LLL-reduced with a tolerance of `\varepsilon = 2^{tol\_exp}`, meaning that it satisfies the inequalities `|\mu_{j,k}|\leq \eta + \varepsilon` and `(\delta - \varepsilon) \lVert b_{k-1}^*\rVert^2 \leq \lVert b_k^*\rVert^2 + \mu_{k,k-1}^2 \lVert b_{k-1}^*\rVert^2` (with the usual notation) for the default parameters `\eta = 0.51`, `\delta = 0.99`. flint-3.1.3/doc/source/arb_poly.rst000066400000000000000000001432511461254215100172470ustar00rootroot00000000000000.. _arb-poly: **arb_poly.h** -- polynomials over the real numbers =============================================================================== An :type:`arb_poly_t` represents a polynomial over the real numbers, implemented as an array of coefficients of type :type:`arb_struct`. Most functions are provided in two versions: an underscore method which operates directly on pre-allocated arrays of coefficients and generally has some restrictions (such as requiring the lengths to be nonzero and not supporting aliasing of the input and output arrays), and a non-underscore method which performs automatic memory management and handles degenerate cases. Types, macros and constants ------------------------------------------------------------------------------- .. type:: arb_poly_struct .. type:: arb_poly_t Contains a pointer to an array of coefficients (coeffs), the used length (length), and the allocated size of the array (alloc). An *arb_poly_t* is defined as an array of length one of type *arb_poly_struct*, permitting an *arb_poly_t* to be passed by reference. Memory management ------------------------------------------------------------------------------- .. function:: void arb_poly_init(arb_poly_t poly) Initializes the polynomial for use, setting it to the zero polynomial. .. function:: void arb_poly_clear(arb_poly_t poly) Clears the polynomial, deallocating all coefficients and the coefficient array. .. function:: void arb_poly_fit_length(arb_poly_t poly, slong len) Makes sure that the coefficient array of the polynomial contains at least *len* initialized coefficients. .. function:: void _arb_poly_set_length(arb_poly_t poly, slong len) Directly changes the length of the polynomial, without allocating or deallocating coefficients. The value should not exceed the allocation length. .. function:: void _arb_poly_normalise(arb_poly_t poly) Strips any trailing coefficients which are identical to zero. .. function:: slong arb_poly_allocated_bytes(const arb_poly_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(arb_poly_struct)`` to get the size of the object as a whole. Basic manipulation ------------------------------------------------------------------------------- .. function:: slong arb_poly_length(const arb_poly_t poly) Returns the length of *poly*, i.e. zero if *poly* is identically zero, and otherwise one more than the index of the highest term that is not identically zero. .. function:: slong arb_poly_degree(const arb_poly_t poly) Returns the degree of *poly*, defined as one less than its length. Note that if one or several leading coefficients are balls containing zero, this value can be larger than the true degree of the exact polynomial represented by *poly*, so the return value of this function is effectively an upper bound. .. function:: int arb_poly_is_zero(const arb_poly_t poly) .. function:: int arb_poly_is_one(const arb_poly_t poly) .. function:: int arb_poly_is_x(const arb_poly_t poly) Returns 1 if *poly* is exactly the polynomial 0, 1 or *x* respectively. Returns 0 otherwise. .. function:: void arb_poly_zero(arb_poly_t poly) .. function:: void arb_poly_one(arb_poly_t poly) Sets *poly* to the constant 0 respectively 1. .. function:: void arb_poly_set(arb_poly_t dest, const arb_poly_t src) Sets *dest* to a copy of *src*. .. function:: void arb_poly_set_round(arb_poly_t dest, const arb_poly_t src, slong prec) Sets *dest* to a copy of *src*, rounded to *prec* bits. .. function:: void arb_poly_set_trunc(arb_poly_t dest, const arb_poly_t src, slong n) .. function:: void arb_poly_set_trunc_round(arb_poly_t dest, const arb_poly_t src, slong n, slong prec) Sets *dest* to a copy of *src*, truncated to length *n* and rounded to *prec* bits. .. function:: void arb_poly_set_coeff_si(arb_poly_t poly, slong n, slong c) .. function:: void arb_poly_set_coeff_arb(arb_poly_t poly, slong n, const arb_t c) Sets the coefficient with index *n* in *poly* to the value *c*. We require that *n* is nonnegative. .. function:: void arb_poly_get_coeff_arb(arb_t v, const arb_poly_t poly, slong n) Sets *v* to the value of the coefficient with index *n* in *poly*. We require that *n* is nonnegative. .. macro:: arb_poly_get_coeff_ptr(poly, n) Given `n \ge 0`, returns a pointer to coefficient *n* of *poly*, or *NULL* if *n* exceeds the length of *poly*. .. function:: void _arb_poly_shift_right(arb_ptr res, arb_srcptr poly, slong len, slong n) .. function:: void arb_poly_shift_right(arb_poly_t res, const arb_poly_t poly, slong n) Sets *res* to *poly* divided by `x^n`, throwing away the lower coefficients. We require that *n* is nonnegative. .. function:: void _arb_poly_shift_left(arb_ptr res, arb_srcptr poly, slong len, slong n) .. function:: void arb_poly_shift_left(arb_poly_t res, const arb_poly_t poly, slong n) Sets *res* to *poly* multiplied by `x^n`. We require that *n* is nonnegative. .. function:: void arb_poly_truncate(arb_poly_t poly, slong n) Truncates *poly* to have length at most *n*, i.e. degree strictly smaller than *n*. We require that *n* is nonnegative. .. function:: slong arb_poly_valuation(const arb_poly_t poly) Returns the degree of the lowest term that is not exactly zero in *poly*. Returns -1 if *poly* is the zero polynomial. Conversions ------------------------------------------------------------------------------- .. function:: void arb_poly_set_fmpz_poly(arb_poly_t poly, const fmpz_poly_t src, slong prec) .. function:: void arb_poly_set_fmpq_poly(arb_poly_t poly, const fmpq_poly_t src, slong prec) .. function:: void arb_poly_set_si(arb_poly_t poly, slong src) Sets *poly* to *src*, rounding the coefficients to *prec* bits. Input and output ------------------------------------------------------------------------------- .. function:: void arb_poly_printd(const arb_poly_t poly, slong digits) Prints the polynomial as an array of coefficients, printing each coefficient using *arb_printd*. .. function:: void arb_poly_fprintd(FILE * file, const arb_poly_t poly, slong digits) Prints the polynomial as an array of coefficients to the stream *file*, printing each coefficient using *arb_fprintd*. Random generation ------------------------------------------------------------------------------- .. function:: void arb_poly_randtest(arb_poly_t poly, flint_rand_t state, slong len, slong prec, slong mag_bits) Creates a random polynomial with length at most *len*. Comparisons ------------------------------------------------------------------------------- .. function:: int arb_poly_contains(const arb_poly_t poly1, const arb_poly_t poly2) .. function:: int arb_poly_contains_fmpz_poly(const arb_poly_t poly1, const fmpz_poly_t poly2) .. function:: int arb_poly_contains_fmpq_poly(const arb_poly_t poly1, const fmpq_poly_t poly2) Returns nonzero iff *poly1* contains *poly2*. .. function:: int arb_poly_equal(const arb_poly_t A, const arb_poly_t B) Returns nonzero iff *A* and *B* are equal as polynomial balls, i.e. all coefficients have equal midpoint and radius. .. function:: int _arb_poly_overlaps(arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2) .. function:: int arb_poly_overlaps(const arb_poly_t poly1, const arb_poly_t poly2) Returns nonzero iff *poly1* overlaps with *poly2*. The underscore function requires that *len1* is at least as large as *len2*. .. function:: int arb_poly_get_unique_fmpz_poly(fmpz_poly_t z, const arb_poly_t x) If *x* contains a unique integer polynomial, sets *z* to that value and returns nonzero. Otherwise (if *x* represents no integers or more than one integer), returns zero, possibly partially modifying *z*. Bounds ------------------------------------------------------------------------------- .. function:: void _arb_poly_majorant(arb_ptr res, arb_srcptr poly, slong len, slong prec) .. function:: void arb_poly_majorant(arb_poly_t res, const arb_poly_t poly, slong prec) Sets *res* to an exact real polynomial whose coefficients are upper bounds for the absolute values of the coefficients in *poly*, rounded to *prec* bits. Arithmetic ------------------------------------------------------------------------------- .. function:: void _arb_poly_add(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) Sets *{C, max(lenA, lenB)}* to the sum of *{A, lenA}* and *{B, lenB}*. Allows aliasing of the input and output operands. .. function:: void arb_poly_add(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong prec) .. function:: void arb_poly_add_si(arb_poly_t C, const arb_poly_t A, slong B, slong prec) Sets *C* to the sum of *A* and *B*. .. function:: void _arb_poly_sub(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) Sets *{C, max(lenA, lenB)}* to the difference of *{A, lenA}* and *{B, lenB}*. Allows aliasing of the input and output operands. .. function:: void arb_poly_sub(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong prec) Sets *C* to the difference of *A* and *B*. .. function:: void arb_poly_add_series(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong len, slong prec) Sets *C* to the sum of *A* and *B*, truncated to length *len*. .. function:: void arb_poly_sub_series(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong len, slong prec) Sets *C* to the difference of *A* and *B*, truncated to length *len*. .. function:: void arb_poly_neg(arb_poly_t C, const arb_poly_t A) Sets *C* to the negation of *A*. .. function:: void arb_poly_scalar_mul_2exp_si(arb_poly_t C, const arb_poly_t A, slong c) Sets *C* to *A* multiplied by `2^c`. .. function:: void arb_poly_scalar_mul(arb_poly_t C, const arb_poly_t A, const arb_t c, slong prec) Sets *C* to *A* multiplied by *c*. .. function:: void arb_poly_scalar_div(arb_poly_t C, const arb_poly_t A, const arb_t c, slong prec) Sets *C* to *A* divided by *c*. .. function:: void _arb_poly_mullow_classical(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong n, slong prec) .. function:: void _arb_poly_mullow_block(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong n, slong prec) .. function:: void _arb_poly_mullow(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong n, slong prec) Sets *{C, n}* to the product of *{A, lenA}* and *{B, lenB}*, truncated to length *n*. The output is not allowed to be aliased with either of the inputs. We require `\mathrm{lenA} \ge \mathrm{lenB} > 0`, `n > 0`, `\mathrm{lenA} + \mathrm{lenB} - 1 \ge n`. The *classical* version uses a plain loop. This has good numerical stability but gets slow for large *n*. The *block* version decomposes the product into several subproducts which are computed exactly over the integers. It first attempts to find an integer `c` such that `A(2^c x)` and `B(2^c x)` have slowly varying coefficients, to reduce the number of blocks. The scaling factor `c` is chosen in a quick, heuristic way by picking the first and last nonzero terms in each polynomial. If the indices in `A` are `a_2, a_1` and the log-2 magnitudes are `e_2, e_1`, and the indices in `B` are `b_2, b_1` with corresponding magnitudes `f_2, f_1`, then we compute `c` as the weighted arithmetic mean of the slopes, rounded to the nearest integer: .. math:: c = \left\lfloor \frac{(e_2 - e_1) + (f_2 + f_1)}{(a_2 - a_1) + (b_2 - b_1)} + \frac{1}{2} \right \rfloor. This strategy is used because it is simple. It is not optimal in all cases, but will typically give good performance when multiplying two power series with a similar decay rate. The default algorithm chooses the *classical* algorithm for short polynomials and the *block* algorithm for long polynomials. If the input pointers are identical (and the lengths are the same), they are assumed to represent the same polynomial, and its square is computed. .. function:: void arb_poly_mullow_classical(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong n, slong prec) .. function:: void arb_poly_mullow_ztrunc(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong n, slong prec) .. function:: void arb_poly_mullow_block(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong n, slong prec) .. function:: void arb_poly_mullow(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong n, slong prec) Sets *C* to the product of *A* and *B*, truncated to length *n*. If the same variable is passed for *A* and *B*, sets *C* to the square of *A* truncated to length *n*. .. function:: void _arb_poly_mul(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) Sets *{C, lenA + lenB - 1}* to the product of *{A, lenA}* and *{B, lenB}*. The output is not allowed to be aliased with either of the inputs. We require `\mathrm{lenA} \ge \mathrm{lenB} > 0`. This function is implemented as a simple wrapper for :func:`_arb_poly_mullow`. If the input pointers are identical (and the lengths are the same), they are assumed to represent the same polynomial, and its square is computed. .. function:: void arb_poly_mul(arb_poly_t C, const arb_poly_t A, const arb_poly_t B, slong prec) Sets *C* to the product of *A* and *B*. If the same variable is passed for *A* and *B*, sets *C* to the square of *A*. .. function:: void _arb_poly_inv_series(arb_ptr Q, arb_srcptr A, slong Alen, slong len, slong prec) Sets *{Q, len}* to the power series inverse of *{A, Alen}*. Uses Newton iteration. .. function:: void arb_poly_inv_series(arb_poly_t Q, const arb_poly_t A, slong n, slong prec) Sets *Q* to the power series inverse of *A*, truncated to length *n*. .. function:: void _arb_poly_div_series(arb_ptr Q, arb_srcptr A, slong Alen, arb_srcptr B, slong Blen, slong n, slong prec) Sets *{Q, n}* to the power series quotient of *{A, Alen}* by *{B, Blen}*. Uses Newton iteration followed by multiplication. .. function:: void arb_poly_div_series(arb_poly_t Q, const arb_poly_t A, const arb_poly_t B, slong n, slong prec) Sets *Q* to the power series quotient *A* divided by *B*, truncated to length *n*. .. function:: void _arb_poly_div(arb_ptr Q, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) .. function:: void _arb_poly_rem(arb_ptr R, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) .. function:: void _arb_poly_divrem(arb_ptr Q, arb_ptr R, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) .. function:: int arb_poly_divrem(arb_poly_t Q, arb_poly_t R, const arb_poly_t A, const arb_poly_t B, slong prec) Performs polynomial division with remainder, computing a quotient `Q` and a remainder `R` such that `A = BQ + R`. The implementation reverses the inputs and performs power series division. If the leading coefficient of `B` contains zero (or if `B` is identically zero), returns 0 indicating failure without modifying the outputs. Otherwise returns nonzero. .. function:: void _arb_poly_div_root(arb_ptr Q, arb_t R, arb_srcptr A, slong len, const arb_t c, slong prec) Divides `A` by the polynomial `x - c`, computing the quotient `Q` as well as the remainder `R = f(c)`. Composition ------------------------------------------------------------------------------- .. function:: void _arb_poly_taylor_shift(arb_ptr g, const arb_t c, slong n, slong prec) void arb_poly_taylor_shift(arb_poly_t g, const arb_poly_t f, const arb_t c, slong prec) Sets *g* to the Taylor shift `f(x+c)`. The underscore methods act in-place on *g* = *f* which has length *n*. .. function:: void _arb_poly_compose(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec) void arb_poly_compose(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec) Sets *res* to the composition `h(x) = f(g(x))` where `f` is given by *poly1* and `g` is given by *poly2*. The underscore method does not support aliasing of the output with either input polynomial. .. function:: void _arb_poly_compose_series(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, slong prec) void arb_poly_compose_series(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec) Sets *res* to the power series composition `h(x) = f(g(x))` truncated to order `O(x^n)` where `f` is given by *poly1* and `g` is given by *poly2*. Wraps :func:`_gr_poly_compose_series` which chooses automatically between various algorithms. We require that the constant term in `g(x)` is exactly zero. The underscore method does not support aliasing of the output with either input polynomial. .. function:: void _arb_poly_revert_series(arb_ptr h, arb_srcptr f, slong flen, slong n, slong prec) void arb_poly_revert_series(arb_poly_t h, const arb_poly_t f, slong n, slong prec) Sets `h` to the power series reversion of `f`, i.e. the expansion of the compositional inverse function `f^{-1}(x)`, truncated to order `O(x^n)`. Wraps :func:`_gr_poly_revert_series` which chooses automatically between various algorithms. We require that the constant term in `f` is exactly zero and that the linear term is nonzero. The underscore methods assume that *flen* is at least 2, and do not support aliasing. Evaluation ------------------------------------------------------------------------------- .. function:: void _arb_poly_evaluate_horner(arb_t y, arb_srcptr f, slong len, const arb_t x, slong prec) .. function:: void arb_poly_evaluate_horner(arb_t y, const arb_poly_t f, const arb_t x, slong prec) .. function:: void _arb_poly_evaluate_rectangular(arb_t y, arb_srcptr f, slong len, const arb_t x, slong prec) .. function:: void arb_poly_evaluate_rectangular(arb_t y, const arb_poly_t f, const arb_t x, slong prec) .. function:: void _arb_poly_evaluate(arb_t y, arb_srcptr f, slong len, const arb_t x, slong prec) .. function:: void arb_poly_evaluate(arb_t y, const arb_poly_t f, const arb_t x, slong prec) Sets `y = f(x)`, evaluated respectively using Horner's rule, rectangular splitting, and an automatic algorithm choice. .. function:: void _arb_poly_evaluate_acb_horner(acb_t y, arb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void arb_poly_evaluate_acb_horner(acb_t y, const arb_poly_t f, const acb_t x, slong prec) .. function:: void _arb_poly_evaluate_acb_rectangular(acb_t y, arb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void arb_poly_evaluate_acb_rectangular(acb_t y, const arb_poly_t f, const acb_t x, slong prec) .. function:: void _arb_poly_evaluate_acb(acb_t y, arb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void arb_poly_evaluate_acb(acb_t y, const arb_poly_t f, const acb_t x, slong prec) Sets `y = f(x)` where `x` is a complex number, evaluating the polynomial respectively using Horner's rule, rectangular splitting, and an automatic algorithm choice. .. function:: void _arb_poly_evaluate2_horner(arb_t y, arb_t z, arb_srcptr f, slong len, const arb_t x, slong prec) .. function:: void arb_poly_evaluate2_horner(arb_t y, arb_t z, const arb_poly_t f, const arb_t x, slong prec) .. function:: void _arb_poly_evaluate2_rectangular(arb_t y, arb_t z, arb_srcptr f, slong len, const arb_t x, slong prec) .. function:: void arb_poly_evaluate2_rectangular(arb_t y, arb_t z, const arb_poly_t f, const arb_t x, slong prec) .. function:: void _arb_poly_evaluate2(arb_t y, arb_t z, arb_srcptr f, slong len, const arb_t x, slong prec) .. function:: void arb_poly_evaluate2(arb_t y, arb_t z, const arb_poly_t f, const arb_t x, slong prec) Sets `y = f(x), z = f'(x)`, evaluated respectively using Horner's rule, rectangular splitting, and an automatic algorithm choice. When Horner's rule is used, the only advantage of evaluating the function and its derivative simultaneously is that one does not have to generate the derivative polynomial explicitly. With the rectangular splitting algorithm, the powers can be reused, making simultaneous evaluation slightly faster. .. function:: void _arb_poly_evaluate2_acb_horner(acb_t y, acb_t z, arb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void arb_poly_evaluate2_acb_horner(acb_t y, acb_t z, const arb_poly_t f, const acb_t x, slong prec) .. function:: void _arb_poly_evaluate2_acb_rectangular(acb_t y, acb_t z, arb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void arb_poly_evaluate2_acb_rectangular(acb_t y, acb_t z, const arb_poly_t f, const acb_t x, slong prec) .. function:: void _arb_poly_evaluate2_acb(acb_t y, acb_t z, arb_srcptr f, slong len, const acb_t x, slong prec) .. function:: void arb_poly_evaluate2_acb(acb_t y, acb_t z, const arb_poly_t f, const acb_t x, slong prec) Sets `y = f(x), z = f'(x)`, evaluated respectively using Horner's rule, rectangular splitting, and an automatic algorithm choice. Product trees ------------------------------------------------------------------------------- .. function:: void _arb_poly_product_roots(arb_ptr poly, arb_srcptr xs, slong n, slong prec) .. function:: void arb_poly_product_roots(arb_poly_t poly, arb_srcptr xs, slong n, slong prec) Generates the polynomial `(x-x_0)(x-x_1)\cdots(x-x_{n-1})`. .. function:: void _arb_poly_product_roots_complex(arb_ptr poly, arb_srcptr r, slong rn, acb_srcptr c, slong cn, slong prec) .. function:: void arb_poly_product_roots_complex(arb_poly_t poly, arb_srcptr r, slong rn, acb_srcptr c, slong cn, slong prec) Generates the polynomial .. math:: \left(\prod_{i=0}^{rn-1} (x-r_i)\right) \left(\prod_{i=0}^{cn-1} (x-c_i)(x-\bar{c_i})\right) having *rn* real roots given by the array *r* and having `2cn` complex roots in conjugate pairs given by the length-*cn* array *c*. Either *rn* or *cn* or both may be zero. Note that only one representative from each complex conjugate pair is supplied (unless a pair is supposed to be repeated with higher multiplicity). To construct a polynomial from complex roots where the conjugate pairs have not been distinguished, use :func:`acb_poly_product_roots` instead. .. function:: arb_ptr * _arb_poly_tree_alloc(slong len) Returns an initialized data structured capable of representing a remainder tree (product tree) of *len* roots. .. function:: void _arb_poly_tree_free(arb_ptr * tree, slong len) Deallocates a tree structure as allocated using *_arb_poly_tree_alloc*. .. function:: void _arb_poly_tree_build(arb_ptr * tree, arb_srcptr roots, slong len, slong prec) Constructs a product tree from a given array of *len* roots. The tree structure must be pre-allocated to the specified length using :func:`_arb_poly_tree_alloc`. Multipoint evaluation ------------------------------------------------------------------------------- .. function:: void _arb_poly_evaluate_vec_iter(arb_ptr ys, arb_srcptr poly, slong plen, arb_srcptr xs, slong n, slong prec) .. function:: void arb_poly_evaluate_vec_iter(arb_ptr ys, const arb_poly_t poly, arb_srcptr xs, slong n, slong prec) Evaluates the polynomial simultaneously at *n* given points, calling :func:`_arb_poly_evaluate` repeatedly. .. function:: void _arb_poly_evaluate_vec_fast_precomp(arb_ptr vs, arb_srcptr poly, slong plen, arb_ptr * tree, slong len, slong prec) .. function:: void _arb_poly_evaluate_vec_fast(arb_ptr ys, arb_srcptr poly, slong plen, arb_srcptr xs, slong n, slong prec) .. function:: void arb_poly_evaluate_vec_fast(arb_ptr ys, const arb_poly_t poly, arb_srcptr xs, slong n, slong prec) Evaluates the polynomial simultaneously at *n* given points, using fast multipoint evaluation. Interpolation ------------------------------------------------------------------------------- .. function:: void _arb_poly_interpolate_newton(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) .. function:: void arb_poly_interpolate_newton(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) Recovers the unique polynomial of length at most *n* that interpolates the given *x* and *y* values. This implementation first interpolates in the Newton basis and then converts back to the monomial basis. .. function:: void _arb_poly_interpolate_barycentric(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) .. function:: void arb_poly_interpolate_barycentric(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) Recovers the unique polynomial of length at most *n* that interpolates the given *x* and *y* values. This implementation uses the barycentric form of Lagrange interpolation. .. function:: void _arb_poly_interpolation_weights(arb_ptr w, arb_ptr * tree, slong len, slong prec) .. function:: void _arb_poly_interpolate_fast_precomp(arb_ptr poly, arb_srcptr ys, arb_ptr * tree, arb_srcptr weights, slong len, slong prec) .. function:: void _arb_poly_interpolate_fast(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong len, slong prec) .. function:: void arb_poly_interpolate_fast(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) Recovers the unique polynomial of length at most *n* that interpolates the given *x* and *y* values, using fast Lagrange interpolation. The precomp function takes a precomputed product tree over the *x* values and a vector of interpolation weights as additional inputs. Differentiation ------------------------------------------------------------------------------- .. function:: void _arb_poly_derivative(arb_ptr res, arb_srcptr poly, slong len, slong prec) Sets *{res, len - 1}* to the derivative of *{poly, len}*. Allows aliasing of the input and output. .. function:: void arb_poly_derivative(arb_poly_t res, const arb_poly_t poly, slong prec) Sets *res* to the derivative of *poly*. .. function:: void _arb_poly_nth_derivative(arb_ptr res, arb_srcptr poly, ulong n, slong len, slong prec) Sets *{res, len - n}* to the nth derivative of *{poly, len}*. Does nothing if *len <= n*. Allows aliasing of the input and output. .. function:: void arb_poly_nth_derivative(arb_poly_t res, const arb_poly_t poly, ulong n, slong prec) Sets *res* to the nth derivative of *poly*. .. function:: void _arb_poly_integral(arb_ptr res, arb_srcptr poly, slong len, slong prec) Sets *{res, len}* to the integral of *{poly, len - 1}*. Allows aliasing of the input and output. .. function:: void arb_poly_integral(arb_poly_t res, const arb_poly_t poly, slong prec) Sets *res* to the integral of *poly*. Transforms ------------------------------------------------------------------------------- .. function:: void _arb_poly_borel_transform(arb_ptr res, arb_srcptr poly, slong len, slong prec) .. function:: void arb_poly_borel_transform(arb_poly_t res, const arb_poly_t poly, slong prec) Computes the Borel transform of the input polynomial, mapping `\sum_k a_k x^k` to `\sum_k (a_k / k!) x^k`. The underscore method allows aliasing. .. function:: void _arb_poly_inv_borel_transform(arb_ptr res, arb_srcptr poly, slong len, slong prec) .. function:: void arb_poly_inv_borel_transform(arb_poly_t res, const arb_poly_t poly, slong prec) Computes the inverse Borel transform of the input polynomial, mapping `\sum_k a_k x^k` to `\sum_k a_k k! x^k`. The underscore method allows aliasing. .. function:: void _arb_poly_binomial_transform_basecase(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec) .. function:: void arb_poly_binomial_transform_basecase(arb_poly_t b, const arb_poly_t a, slong len, slong prec) .. function:: void _arb_poly_binomial_transform_convolution(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec) .. function:: void arb_poly_binomial_transform_convolution(arb_poly_t b, const arb_poly_t a, slong len, slong prec) .. function:: void _arb_poly_binomial_transform(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec) .. function:: void arb_poly_binomial_transform(arb_poly_t b, const arb_poly_t a, slong len, slong prec) Computes the binomial transform of the input polynomial, truncating the output to length *len*. The binomial transform maps the coefficients `a_k` in the input polynomial to the coefficients `b_k` in the output polynomial via `b_n = \sum_{k=0}^n (-1)^k {n \choose k} a_k`. The binomial transform is equivalent to the power series composition `f(x) \to (1-x)^{-1} f(x/(x-1))`, and is its own inverse. The *basecase* version evaluates coefficients one by one from the definition, generating the binomial coefficients by a recurrence relation. The *convolution* version uses the identity `T(f(x)) = B^{-1}(e^x B(f(-x)))` where `T` denotes the binomial transform operator and `B` denotes the Borel transform operator. This only costs a single polynomial multiplication, plus some scalar operations. The default version automatically chooses an algorithm. The underscore methods do not support aliasing, and assume that the lengths are nonzero. .. function:: void _arb_poly_graeffe_transform(arb_ptr b, arb_srcptr a, slong len, slong prec) .. function:: void arb_poly_graeffe_transform(arb_poly_t b, const arb_poly_t a, slong prec) Computes the Graeffe transform of input polynomial. The Graeffe transform `G` of a polynomial `P` is defined through the equation `G(x^2) = \pm P(x)P(-x)`. The sign is given by `(-1)^d`, where `d = deg(P)`. The Graeffe transform has the property that its roots are exactly the squares of the roots of P. The underscore method assumes that *a* and *b* are initialized, *a* is of length *len*, and *b* is of length at least *len*. Both methods allow aliasing. Powers and elementary functions ------------------------------------------------------------------------------- .. function:: void _arb_poly_pow_ui_trunc_binexp(arb_ptr res, arb_srcptr f, slong flen, ulong exp, slong len, slong prec) Sets *{res, len}* to *{f, flen}* raised to the power *exp*, truncated to length *len*. Requires that *len* is no longer than the length of the power as computed without truncation (i.e. no zero-padding is performed). Does not support aliasing of the input and output, and requires that *flen* and *len* are positive. Uses binary exponentiation. .. function:: void arb_poly_pow_ui_trunc_binexp(arb_poly_t res, const arb_poly_t poly, ulong exp, slong len, slong prec) Sets *res* to *poly* raised to the power *exp*, truncated to length *len*. Uses binary exponentiation. .. function:: void _arb_poly_pow_ui(arb_ptr res, arb_srcptr f, slong flen, ulong exp, slong prec) Sets *res* to *{f, flen}* raised to the power *exp*. Does not support aliasing of the input and output, and requires that *flen* is positive. .. function:: void arb_poly_pow_ui(arb_poly_t res, const arb_poly_t poly, ulong exp, slong prec) Sets *res* to *poly* raised to the power *exp*. .. function:: void _arb_poly_pow_series(arb_ptr h, arb_srcptr f, slong flen, arb_srcptr g, slong glen, slong len, slong prec) Sets *{h, len}* to the power series `f(x)^{g(x)} = \exp(g(x) \log f(x))` truncated to length *len*. This function detects special cases such as *g* being an exact small integer or `\pm 1/2`, and computes such powers more efficiently. This function does not support aliasing of the output with either of the input operands. It requires that all lengths are positive, and assumes that *flen* and *glen* do not exceed *len*. .. function:: void arb_poly_pow_series(arb_poly_t h, const arb_poly_t f, const arb_poly_t g, slong len, slong prec) Sets *h* to the power series `f(x)^{g(x)} = \exp(g(x) \log f(x))` truncated to length *len*. This function detects special cases such as *g* being an exact small integer or `\pm 1/2`, and computes such powers more efficiently. .. function:: void _arb_poly_pow_arb_series(arb_ptr h, arb_srcptr f, slong flen, const arb_t g, slong len, slong prec) Sets *{h, len}* to the power series `f(x)^g = \exp(g \log f(x))` truncated to length *len*. This function detects special cases such as *g* being an exact small integer or `\pm 1/2`, and computes such powers more efficiently. This function does not support aliasing of the output with either of the input operands. It requires that all lengths are positive, and assumes that *flen* does not exceed *len*. .. function:: void arb_poly_pow_arb_series(arb_poly_t h, const arb_poly_t f, const arb_t g, slong len, slong prec) Sets *h* to the power series `f(x)^g = \exp(g \log f(x))` truncated to length *len*. .. function:: void _arb_poly_sqrt_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sqrt_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) Sets *g* to the power series square root of *h*, truncated to length *n*. Uses division-free Newton iteration for the reciprocal square root, followed by a multiplication. The underscore method does not support aliasing of the input and output arrays. It requires that *hlen* and *n* are greater than zero. .. function:: void _arb_poly_rsqrt_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_rsqrt_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) Sets *g* to the reciprocal power series square root of *h*, truncated to length *n*. Uses division-free Newton iteration. The underscore method does not support aliasing of the input and output arrays. It requires that *hlen* and *n* are greater than zero. .. function:: void _arb_poly_log_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) .. function:: void arb_poly_log_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) Sets *res* to the power series logarithm of *f*, truncated to length *n*. Uses the formula `\log(f(x)) = \int f'(x) / f(x) dx`, adding the logarithm of the constant term in *f* as the constant of integration. The underscore method supports aliasing of the input and output arrays. It requires that *flen* and *n* are greater than zero. .. function:: void _arb_poly_log1p_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) .. function:: void arb_poly_log1p_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) Computes the power series `\log(1+f)`, with better accuracy when the constant term of *f* is small. .. function:: void _arb_poly_atan_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) .. function:: void arb_poly_atan_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) .. function:: void _arb_poly_asin_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) .. function:: void arb_poly_asin_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) .. function:: void _arb_poly_acos_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) .. function:: void arb_poly_acos_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) Sets *res* respectively to the power series inverse tangent, inverse sine and inverse cosine of *f*, truncated to length *n*. Uses the formulas .. math:: \tan^{-1}(f(x)) = \int f'(x) / (1+f(x)^2) dx, \sin^{-1}(f(x)) = \int f'(x) / (1-f(x)^2)^{1/2} dx, \cos^{-1}(f(x)) = -\int f'(x) / (1-f(x)^2)^{1/2} dx, adding the inverse function of the constant term in *f* as the constant of integration. The underscore methods supports aliasing of the input and output arrays. They require that *flen* and *n* are greater than zero. .. function:: void _arb_poly_exp_series_basecase(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_exp_series_basecase(arb_poly_t f, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_exp_series(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_exp_series(arb_poly_t f, const arb_poly_t h, slong n, slong prec) Sets `f` to the power series exponential of `h`, truncated to length `n`. The basecase version uses a simple recurrence for the coefficients, requiring `O(nm)` operations where `m` is the length of `h`. The main implementation uses Newton iteration, starting from a small number of terms given by the basecase algorithm. The complexity is `O(M(n))`. Redundant operations in the Newton iteration are avoided by using the scheme described in [HZ2004]_. The underscore methods support aliasing and allow the input to be shorter than the output, but require the lengths to be nonzero. .. function:: void _arb_poly_sin_cos_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) void arb_poly_sin_cos_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) Sets *s* and *c* to the power series sine and cosine of *h*, computed simultaneously. The underscore method supports aliasing and requires the lengths to be nonzero. .. function:: void _arb_poly_sin_series(arb_ptr s, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sin_series(arb_poly_t s, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_cos_series(arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_cos_series(arb_poly_t c, const arb_poly_t h, slong n, slong prec) Respectively evaluates the power series sine or cosine. These functions simply wrap :func:`_arb_poly_sin_cos_series`. The underscore methods support aliasing and require the lengths to be nonzero. .. function:: void _arb_poly_tan_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) .. function:: void arb_poly_tan_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) Sets *g* to the power series tangent of *h*. For small *n* takes the quotient of the sine and cosine as computed using the basecase algorithm. For large *n*, uses Newton iteration to invert the inverse tangent series. The complexity is `O(M(n))`. The underscore version does not support aliasing, and requires the lengths to be nonzero. .. function:: void _arb_poly_sin_cos_pi_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sin_cos_pi_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_sin_pi_series(arb_ptr s, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sin_pi_series(arb_poly_t s, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_cos_pi_series(arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_cos_pi_series(arb_poly_t c, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_cot_pi_series(arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_cot_pi_series(arb_poly_t c, const arb_poly_t h, slong n, slong prec) Compute the respective trigonometric functions of the input multiplied by `\pi`. .. function:: void _arb_poly_sinh_cosh_series_basecase(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sinh_cosh_series_basecase(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_sinh_cosh_series_exponential(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sinh_cosh_series_exponential(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_sinh_cosh_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sinh_cosh_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_sinh_series(arb_ptr s, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sinh_series(arb_poly_t s, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_cosh_series(arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_cosh_series(arb_poly_t c, const arb_poly_t h, slong n, slong prec) Sets *s* and *c* respectively to the hyperbolic sine and cosine of the power series *h*, truncated to length *n*. The implementations mirror those for sine and cosine, except that the *exponential* version computes both functions using the exponential function instead of the hyperbolic tangent. .. function:: void _arb_poly_sinc_series(arb_ptr s, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sinc_series(arb_poly_t s, const arb_poly_t h, slong n, slong prec) Sets *c* to the sinc function of the power series *h*, truncated to length *n*. .. function:: void _arb_poly_sinc_pi_series(arb_ptr s, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_sinc_pi_series(arb_poly_t s, const arb_poly_t h, slong n, slong prec) Compute the sinc function of the input multiplied by `\pi`. Lambert W function ------------------------------------------------------------------------------- .. function:: void _arb_poly_lambertw_series(arb_ptr res, arb_srcptr z, slong zlen, int flags, slong len, slong prec) .. function:: void arb_poly_lambertw_series(arb_poly_t res, const arb_poly_t z, int flags, slong len, slong prec) Sets *res* to the Lambert W function of the power series *z*. If *flags* is 0, the principal branch is computed; if *flags* is 1, the second real branch `W_{-1}(z)` is computed. The underscore method allows aliasing, but assumes that the lengths are nonzero. Gamma function and factorials ------------------------------------------------------------------------------- .. function:: void _arb_poly_gamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_gamma_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_rgamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_rgamma_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_lgamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_lgamma_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec) .. function:: void _arb_poly_digamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_digamma_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec) Sets *res* to the series expansion of `\Gamma(h(x))`, `1/\Gamma(h(x))`, or `\log \Gamma(h(x))`, `\psi(h(x))`, truncated to length *n*. These functions first generate the Taylor series at the constant term of *h*, and then call :func:`_arb_poly_compose_series`. The Taylor coefficients are generated using the Riemann zeta function if the constant term of *h* is a small integer, and with Stirling's series otherwise. The underscore methods support aliasing of the input and output arrays, and require that *hlen* and *n* are greater than zero. .. function:: void _arb_poly_rising_ui_series(arb_ptr res, arb_srcptr f, slong flen, ulong r, slong trunc, slong prec) .. function:: void arb_poly_rising_ui_series(arb_poly_t res, const arb_poly_t f, ulong r, slong trunc, slong prec) Sets *res* to the rising factorial `(f) (f+1) (f+2) \cdots (f+r-1)`, truncated to length *trunc*. The underscore method assumes that *flen*, *r* and *trunc* are at least 1, and does not support aliasing. Uses binary splitting. Zeta function ------------------------------------------------------------------------------- .. function:: void arb_poly_zeta_series(arb_poly_t res, const arb_poly_t s, const arb_t a, int deflate, slong n, slong prec) Sets *res* to the Hurwitz zeta function `\zeta(s,a)` where `s` a power series and `a` is a constant, truncated to length *n*. To evaluate the usual Riemann zeta function, set `a = 1`. If *deflate* is nonzero, evaluates `\zeta(s,a) + 1/(1-s)`, which is well-defined as a limit when the constant term of `s` is 1. In particular, expanding `\zeta(s,a) + 1/(1-s)` with `s = 1+x` gives the Stieltjes constants .. math:: \sum_{k=0}^{n-1} \frac{(-1)^k}{k!} \gamma_k(a) x^k. If `a = 1`, this implementation uses the reflection formula if the midpoint of the constant term of `s` is negative. .. function:: void _arb_poly_riemann_siegel_theta_series(arb_ptr res, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_riemann_siegel_theta_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec) Sets *res* to the series expansion of the Riemann-Siegel theta function .. math:: \theta(h) = \arg \left(\Gamma\left(\frac{2ih+1}{4}\right)\right) - \frac{\log \pi}{2} h where the argument of the gamma function is chosen continuously as the imaginary part of the log gamma function. The underscore method does not support aliasing of the input and output arrays, and requires that the lengths are greater than zero. .. function:: void _arb_poly_riemann_siegel_z_series(arb_ptr res, arb_srcptr h, slong hlen, slong n, slong prec) .. function:: void arb_poly_riemann_siegel_z_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec) Sets *res* to the series expansion of the Riemann-Siegel Z-function .. math:: Z(h) = e^{i\theta(h)} \zeta(1/2+ih). The zeros of the Z-function on the real line precisely correspond to the imaginary parts of the zeros of the Riemann zeta function on the critical line. The underscore method supports aliasing of the input and output arrays, and requires that the lengths are greater than zero. Root-finding ------------------------------------------------------------------------------- .. function:: void _arb_poly_root_bound_fujiwara(mag_t bound, arb_srcptr poly, slong len) .. function:: void arb_poly_root_bound_fujiwara(mag_t bound, arb_poly_t poly) Sets *bound* to an upper bound for the magnitude of all the complex roots of *poly*. Uses Fujiwara's bound .. math:: 2 \max \left\{\left|\frac{a_{n-1}}{a_n}\right|, \left|\frac{a_{n-2}}{a_n}\right|^{1/2}, \cdots, \left|\frac{a_1}{a_n}\right|^{1/(n-1)}, \left|\frac{a_0}{2a_n}\right|^{1/n} \right\} where `a_0, \ldots, a_n` are the coefficients of *poly*. .. function:: void _arb_poly_newton_convergence_factor(arf_t convergence_factor, arb_srcptr poly, slong len, const arb_t convergence_interval, slong prec) Given an interval `I` specified by *convergence_interval*, evaluates a bound for `C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|`, where `f` is the polynomial defined by the coefficients *{poly, len}*. The bound is obtained by evaluating `f'(I)` and `f''(I)` directly. If `f` has large coefficients, `I` must be extremely precise in order to get a finite factor. .. function:: int _arb_poly_newton_step(arb_t xnew, arb_srcptr poly, slong len, const arb_t x, const arb_t convergence_interval, const arf_t convergence_factor, slong prec) Performs a single step with Newton's method. The input consists of the polynomial `f` specified by the coefficients *{poly, len}*, an interval `x = [m-r, m+r]` known to contain a single root of `f`, an interval `I` (*convergence_interval*) containing `x` with an associated bound (*convergence_factor*) for `C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|`, and a working precision *prec*. The Newton update consists of setting `x' = [m'-r', m'+r']` where `m' = m - f(m) / f'(m)` and `r' = C r^2`. The expression `m - f(m) / f'(m)` is evaluated using ball arithmetic at a working precision of *prec* bits, and the rounding error during this evaluation is accounted for in the output. We now check that `x' \in I` and `m' < m`. If both conditions are satisfied, we set *xnew* to `x'` and return nonzero. If either condition fails, we set *xnew* to `x` and return zero, indicating that no progress was made. .. function:: void _arb_poly_newton_refine_root(arb_t r, arb_srcptr poly, slong len, const arb_t start, const arb_t convergence_interval, const arf_t convergence_factor, slong eval_extra_prec, slong prec) Refines a precise estimate of a polynomial root to high precision by performing several Newton steps, using nearly optimally chosen doubling precision steps. The inputs are defined as for *_arb_poly_newton_step*, except for the precision parameters: *prec* is the target accuracy and *eval_extra_prec* is the estimated number of guard bits that need to be added to evaluate the polynomial accurately close to the root (typically, if the polynomial has large coefficients of alternating signs, this needs to be approximately the bit size of the coefficients). Other special polynomials ------------------------------------------------------------------------------- .. function:: void _arb_poly_swinnerton_dyer_ui(arb_ptr poly, ulong n, slong trunc, slong prec) .. function:: void arb_poly_swinnerton_dyer_ui(arb_poly_t poly, ulong n, slong prec) Computes the Swinnerton-Dyer polynomial `S_n`, which has degree `2^n` and is the rational minimal polynomial of the sum of the square roots of the first *n* prime numbers. If *prec* is set to zero, a precision is chosen automatically such that :func:`arb_poly_get_unique_fmpz_poly` should be successful. Otherwise a working precision of *prec* bits is used. The underscore version accepts an additional *trunc* parameter. Even when computing a truncated polynomial, the array *poly* must have room for `2^n + 1` coefficients, used as temporary space. flint-3.1.3/doc/source/arf.rst000066400000000000000000000754441461254215100162200ustar00rootroot00000000000000.. _arf: **arf.h** -- arbitrary-precision floating-point numbers =============================================================================== A variable of type :type:`arf_t` holds an arbitrary-precision binary floating-point number: that is, a rational number of the form `x \cdot 2^y` where `x, y \in \mathbb{Z}` and `x` is odd, or one of the special values zero, plus infinity, minus infinity, or NaN (not-a-number). There is currently no support for negative zero, unsigned infinity, or a NaN with a payload. The *exponent* of a finite and nonzero floating-point number can be defined in different ways: for example, as the component *y* above, or as the unique integer *e* such that `x \cdot 2^y = m \cdot 2^e` where `0.5 \le |m| < 1`. The internal representation of an :type:`arf_t` stores the exponent in the latter format. Except where otherwise noted, functions have the following semantics: * Functions taking *prec* and *rnd* parameters at the end of the argument list and returning an ``int`` flag round the result in the output variable to *prec* bits in the direction specified by *rnd*. The return flag is 0 if the result is exact (not rounded) and 1 if the result is inexact (rounded). Correct rounding is guaranteed: the result is the floating-point number obtained by viewing the inputs as exact numbers, in principle carrying out the mathematical operation exactly, and rounding the resulting real number to the nearest representable floating-point number whose mantissa has at most the specified number of bits, in the specified direction of rounding. In particular, the error is at most 1 ulp with directed rounding modes and 0.5 ulp when rounding to nearest. * Other functions perform the operation exactly. Since exponents are bignums, overflow or underflow cannot occur. Types, macros and constants ------------------------------------------------------------------------------- .. type:: arf_struct .. type:: arf_t An :type:`arf_struct` contains four words: an :type:`fmpz` exponent (*exp*), a *size* field tracking the number of limbs used (one bit of this field is also used for the sign of the number), and two more words. The last two words hold the value directly if there are at most two limbs, and otherwise contain one *alloc* field (tracking the total number of allocated limbs, not all of which might be used) and a pointer to the actual limbs. Thus, up to 128 bits on a 64-bit machine and 64 bits on a 32-bit machine, no space outside of the :type:`arf_struct` is used. An :type:`arf_t` is defined as an array of length one of type :type:`arf_struct`, permitting an :type:`arf_t` to be passed by reference. .. type:: arf_rnd_t Specifies the rounding mode for the result of an approximate operation. .. macro:: ARF_RND_DOWN Specifies that the result of an operation should be rounded to the nearest representable number in the direction towards zero. .. macro:: ARF_RND_UP Specifies that the result of an operation should be rounded to the nearest representable number in the direction away from zero. .. macro:: ARF_RND_FLOOR Specifies that the result of an operation should be rounded to the nearest representable number in the direction towards minus infinity. .. macro:: ARF_RND_CEIL Specifies that the result of an operation should be rounded to the nearest representable number in the direction towards plus infinity. .. macro:: ARF_RND_NEAR Specifies that the result of an operation should be rounded to the nearest representable number, rounding to even if there is a tie between two values. .. macro:: ARF_PREC_EXACT If passed as the precision parameter to a function, indicates that no rounding is to be performed. **Warning**: use of this value is unsafe in general. It must only be passed as input under the following two conditions: * The operation in question can inherently be viewed as an exact operation in `\mathbb{Z}[\tfrac{1}{2}]` for all possible inputs, provided that the precision is large enough. Examples include addition, multiplication, conversion from integer types to arbitrary-precision floating-point types, and evaluation of some integer-valued functions. * The exact result of the operation will certainly fit in memory. Note that, for example, adding two numbers whose exponents are far apart can easily produce an exact result that is far too large to store in memory. The typical use case is to work with small integer values, double precision constants, and the like. It is also useful when writing test code. If in doubt, simply try with some convenient high precision instead of using this special value, and check that the result is exact. Memory management ------------------------------------------------------------------------------- .. function:: void arf_init(arf_t x) Initializes the variable *x* for use. Its value is set to zero. .. function:: void arf_clear(arf_t x) Clears the variable *x*, freeing or recycling its allocated memory. .. function:: slong arf_allocated_bytes(const arf_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(arf_struct)`` to get the size of the object as a whole. Special values ------------------------------------------------------------------------------- .. function:: void arf_zero(arf_t res) .. function:: void arf_one(arf_t res) .. function:: void arf_pos_inf(arf_t res) .. function:: void arf_neg_inf(arf_t res) .. function:: void arf_nan(arf_t res) Sets *res* respectively to 0, 1, `+\infty`, `-\infty`, NaN. .. function:: int arf_is_zero(const arf_t x) .. function:: int arf_is_one(const arf_t x) .. function:: int arf_is_pos_inf(const arf_t x) .. function:: int arf_is_neg_inf(const arf_t x) .. function:: int arf_is_nan(const arf_t x) Returns nonzero iff *x* respectively equals 0, 1, `+\infty`, `-\infty`, NaN. .. function:: int arf_is_inf(const arf_t x) Returns nonzero iff *x* equals either `+\infty` or `-\infty`. .. function:: int arf_is_normal(const arf_t x) Returns nonzero iff *x* is a finite, nonzero floating-point value, i.e. not one of the special values 0, `+\infty`, `-\infty`, NaN. .. function:: int arf_is_special(const arf_t x) Returns nonzero iff *x* is one of the special values 0, `+\infty`, `-\infty`, NaN, i.e. not a finite, nonzero floating-point value. .. function:: int arf_is_finite(const arf_t x) Returns nonzero iff *x* is a finite floating-point value, i.e. not one of the values `+\infty`, `-\infty`, NaN. (Note that this is not equivalent to the negation of :func:`arf_is_inf`.) Assignment, rounding and conversions ------------------------------------------------------------------------------- .. function:: void arf_set(arf_t res, const arf_t x) .. function:: void arf_set_mpz(arf_t res, const mpz_t x) .. function:: void arf_set_fmpz(arf_t res, const fmpz_t x) .. function:: void arf_set_ui(arf_t res, ulong x) .. function:: void arf_set_si(arf_t res, slong x) .. function:: void arf_set_mpfr(arf_t res, const mpfr_t x) .. function:: void arf_set_d(arf_t res, double x) Sets *res* to the exact value of *x*. .. function:: void arf_swap(arf_t x, arf_t y) Swaps *x* and *y* efficiently. .. function:: void arf_init_set_ui(arf_t res, ulong x) .. function:: void arf_init_set_si(arf_t res, slong x) Initializes *res* and sets it to *x* in a single operation. .. function:: int arf_set_round(arf_t res, const arf_t x, slong prec, arf_rnd_t rnd) .. function:: int arf_set_round_si(arf_t res, slong x, slong prec, arf_rnd_t rnd) .. function:: int arf_set_round_ui(arf_t res, ulong x, slong prec, arf_rnd_t rnd) .. function:: int arf_set_round_mpz(arf_t res, const mpz_t x, slong prec, arf_rnd_t rnd) .. function:: int arf_set_round_fmpz(arf_t res, const fmpz_t x, slong prec, arf_rnd_t rnd) Sets *res* to *x*, rounded to *prec* bits in the direction specified by *rnd*. .. function:: void arf_set_si_2exp_si(arf_t res, slong m, slong e) .. function:: void arf_set_ui_2exp_si(arf_t res, ulong m, slong e) .. function:: void arf_set_fmpz_2exp(arf_t res, const fmpz_t m, const fmpz_t e) Sets *res* to `m \cdot 2^e`. .. function:: int arf_set_round_fmpz_2exp(arf_t res, const fmpz_t x, const fmpz_t e, slong prec, arf_rnd_t rnd) Sets *res* to `x \cdot 2^e`, rounded to *prec* bits in the direction specified by *rnd*. .. function:: void arf_get_fmpz_2exp(fmpz_t m, fmpz_t e, const arf_t x) Sets *m* and *e* to the unique integers such that `x = m \cdot 2^e` and *m* is odd, provided that *x* is a nonzero finite fraction. If *x* is zero, both *m* and *e* are set to zero. If *x* is infinite or NaN, the result is undefined. .. function:: void arf_frexp(arf_t m, fmpz_t e, const arf_t x) Writes *x* as `m \cdot 2^e`, where `0.5 \le |m| < 1` if *x* is a normal value. If *x* is a special value, copies this to *m* and sets *e* to zero. Note: for the inverse operation (*ldexp*), use :func:`arf_mul_2exp_fmpz`. .. function:: double arf_get_d(const arf_t x, arf_rnd_t rnd) Returns *x* rounded to a double in the direction specified by *rnd*. This method rounds correctly when overflowing or underflowing the double exponent range (this was not the case in an earlier version). .. function:: int arf_get_mpfr(mpfr_t res, const arf_t x, mpfr_rnd_t rnd) Sets the MPFR variable *res* to the value of *x*. If the precision of *x* is too small to allow *res* to be represented exactly, it is rounded in the specified MPFR rounding mode. The return value (-1, 0 or 1) indicates the direction of rounding, following the convention of the MPFR library. If *x* has an exponent too large or small to fit in the MPFR type, the result overflows to an infinity or underflows to a (signed) zero, and the corresponding MPFR exception flags are set. .. function:: int arf_get_fmpz(fmpz_t res, const arf_t x, arf_rnd_t rnd) Sets *res* to *x* rounded to the nearest integer in the direction specified by *rnd*. If rnd is *ARF_RND_NEAR*, rounds to the nearest even integer in case of a tie. Returns inexact (beware: accordingly returns whether *x* is *not* an integer). This method aborts if *x* is infinite or NaN, or if the exponent of *x* is so large that allocating memory for the result fails. Warning: this method will allocate a huge amount of memory to store the result if the exponent of *x* is huge. Memory allocation could succeed even if the required space is far larger than the physical memory available on the machine, resulting in swapping. It is recommended to check that *x* is within a reasonable range before calling this method. .. function:: slong arf_get_si(const arf_t x, arf_rnd_t rnd) Returns *x* rounded to the nearest integer in the direction specified by *rnd*. If *rnd* is *ARF_RND_NEAR*, rounds to the nearest even integer in case of a tie. Aborts if *x* is infinite, NaN, or the value is too large to fit in a slong. .. function:: int arf_get_fmpz_fixed_fmpz(fmpz_t res, const arf_t x, const fmpz_t e) .. function:: int arf_get_fmpz_fixed_si(fmpz_t res, const arf_t x, slong e) Converts *x* to a mantissa with predetermined exponent, i.e. sets *res* to an integer *y* such that `y \times 2^e \approx x`, truncating if necessary. Returns 0 if exact and 1 if truncation occurred. The warnings for :func:`arf_get_fmpz` apply. .. function:: void arf_floor(arf_t res, const arf_t x) .. function:: void arf_ceil(arf_t res, const arf_t x) Sets *res* to `\lfloor x \rfloor` and `\lceil x \rceil` respectively. The result is always represented exactly, requiring no more bits to store than the input. To round the result to a floating-point number with a lower precision, call :func:`arf_set_round` afterwards. .. function:: void arf_get_fmpq(fmpq_t res, const arf_t x) Set *res* to the exact rational value of *x*. This method aborts if *x* is infinite or NaN, or if the exponent of *x* is so large that allocating memory for the result fails. Comparisons and bounds ------------------------------------------------------------------------------- .. function:: int arf_equal(const arf_t x, const arf_t y) int arf_equal_si(const arf_t x, slong y) int arf_equal_ui(const arf_t x, ulong y) int arf_equal_d(const arf_t x, double y) Returns nonzero iff *x* and *y* are exactly equal. NaN is not treated specially, i.e. NaN compares as equal to itself. For comparison with a *double*, the values -0 and +0 are both treated as zero, and all NaN values are treated as identical. .. function:: int arf_cmp(const arf_t x, const arf_t y) .. function:: int arf_cmp_si(const arf_t x, slong y) .. function:: int arf_cmp_ui(const arf_t x, ulong y) .. function:: int arf_cmp_d(const arf_t x, double y) Returns negative, zero, or positive, depending on whether *x* is respectively smaller, equal, or greater compared to *y*. Comparison with NaN is undefined. .. function:: int arf_cmpabs(const arf_t x, const arf_t y) .. function:: int arf_cmpabs_ui(const arf_t x, ulong y) .. function:: int arf_cmpabs_d(const arf_t x, double y) .. function:: int arf_cmpabs_mag(const arf_t x, const mag_t y) Compares the absolute values of *x* and *y*. .. function:: int arf_cmp_2exp_si(const arf_t x, slong e) .. function:: int arf_cmpabs_2exp_si(const arf_t x, slong e) Compares *x* (respectively its absolute value) with `2^e`. .. function:: int arf_sgn(const arf_t x) Returns `-1`, `0` or `+1` according to the sign of *x*. The sign of NaN is undefined. .. function:: void arf_min(arf_t res, const arf_t a, const arf_t b) .. function:: void arf_max(arf_t res, const arf_t a, const arf_t b) Sets *res* respectively to the minimum and the maximum of *a* and *b*. .. function:: slong arf_bits(const arf_t x) Returns the number of bits needed to represent the absolute value of the mantissa of *x*, i.e. the minimum precision sufficient to represent *x* exactly. Returns 0 if *x* is a special value. .. function:: int arf_is_int(const arf_t x) Returns nonzero iff *x* is integer-valued. .. function:: int arf_is_int_2exp_si(const arf_t x, slong e) Returns nonzero iff *x* equals `n 2^e` for some integer *n*. .. function:: void arf_abs_bound_lt_2exp_fmpz(fmpz_t res, const arf_t x) Sets *res* to the smallest integer *b* such that `|x| < 2^b`. If *x* is zero, infinity or NaN, the result is undefined. .. function:: void arf_abs_bound_le_2exp_fmpz(fmpz_t res, const arf_t x) Sets *res* to the smallest integer *b* such that `|x| \le 2^b`. If *x* is zero, infinity or NaN, the result is undefined. .. function:: slong arf_abs_bound_lt_2exp_si(const arf_t x) Returns the smallest integer *b* such that `|x| < 2^b`, clamping the result to lie between -*ARF_PREC_EXACT* and *ARF_PREC_EXACT* inclusive. If *x* is zero, -*ARF_PREC_EXACT* is returned, and if *x* is infinity or NaN, *ARF_PREC_EXACT* is returned. Magnitude functions ------------------------------------------------------------------------------- .. function:: void arf_get_mag(mag_t res, const arf_t x) Sets *res* to an upper bound for the absolute value of *x*. .. function:: void arf_get_mag_lower(mag_t res, const arf_t x) Sets *res* to a lower bound for the absolute value of *x*. .. function:: void arf_set_mag(arf_t res, const mag_t x) Sets *res* to *x*. This operation is exact. .. function:: void mag_init_set_arf(mag_t res, const arf_t x) Initializes *res* and sets it to an upper bound for *x*. .. function:: void mag_fast_init_set_arf(mag_t res, const arf_t x) Initializes *res* and sets it to an upper bound for *x*. Assumes that the exponent of *res* is small (this function is unsafe). .. function:: void arf_mag_set_ulp(mag_t res, const arf_t x, slong prec) Sets *res* to the magnitude of the unit in the last place (ulp) of *x* at precision *prec*. .. function:: void arf_mag_add_ulp(mag_t res, const mag_t x, const arf_t y, slong prec) Sets *res* to an upper bound for the sum of *x* and the magnitude of the unit in the last place (ulp) of *y* at precision *prec*. .. function:: void arf_mag_fast_add_ulp(mag_t res, const mag_t x, const arf_t y, slong prec) Sets *res* to an upper bound for the sum of *x* and the magnitude of the unit in the last place (ulp) of *y* at precision *prec*. Assumes that all exponents are small. Shallow assignment ------------------------------------------------------------------------------- .. function:: void arf_init_set_shallow(arf_t z, const arf_t x) .. function:: void arf_init_set_mag_shallow(arf_t z, const mag_t x) Initializes *z* to a shallow copy of *x*. A shallow copy just involves copying struct data (no heap allocation is performed). The target variable *z* may not be cleared or modified in any way (it can only be used as constant input to functions), and may not be used after *x* has been cleared. Moreover, after *x* has been assigned shallowly to *z*, no modification of *x* is permitted as slong as *z* is in use. .. function:: void arf_init_neg_shallow(arf_t z, const arf_t x) .. function:: void arf_init_neg_mag_shallow(arf_t z, const mag_t x) Initializes *z* shallowly to the negation of *x*. Random number generation ------------------------------------------------------------------------------- .. function:: void arf_randtest(arf_t res, flint_rand_t state, slong bits, slong mag_bits) Generates a finite random number whose mantissa has precision at most *bits* and whose exponent has at most *mag_bits* bits. The values are distributed non-uniformly: special bit patterns are generated with high probability in order to allow the test code to exercise corner cases. .. function:: void arf_randtest_not_zero(arf_t res, flint_rand_t state, slong bits, slong mag_bits) Identical to :func:`arf_randtest`, except that zero is never produced as an output. .. function:: void arf_randtest_special(arf_t res, flint_rand_t state, slong bits, slong mag_bits) Identical to :func:`arf_randtest`, except that the output occasionally is set to an infinity or NaN. .. function:: void arf_urandom(arf_t res, flint_rand_t state, slong bits, arf_rnd_t rnd) Sets *res* to a uniformly distributed random number in the interval `[0, 1]`. The method uses rounding from integers to floats based on the rounding mode *rnd*. Input and output ------------------------------------------------------------------------------- .. function:: void arf_debug(const arf_t x) Prints information about the internal representation of *x*. .. function:: void arf_print(const arf_t x) Prints *x* as an integer mantissa and exponent. .. function:: void arf_printd(const arf_t x, slong d) Prints *x* as a decimal floating-point number, rounding to *d* digits. Rounding is faithful (at most 1 ulp error). .. function:: char * arf_get_str(const arf_t x, slong d) Returns *x* as a decimal floating-point number, rounding to *d* digits. Rounding is faithful (at most 1 ulp error). .. function:: void arf_fprint(FILE * file, const arf_t x) Prints *x* as an integer mantissa and exponent to the stream *file*. .. function:: void arf_fprintd(FILE * file, const arf_t y, slong d) Prints *x* as a decimal floating-point number to the stream *file*, rounding to *d* digits. Rounding is faithful (at most 1 ulp error). .. function:: char * arf_dump_str(const arf_t x) Allocates a string and writes a binary representation of *x* to it that can be read by :func:`arf_load_str`. The returned string needs to be deallocated with *flint_free*. .. function:: int arf_load_str(arf_t x, const char * str) Parses *str* into *x*. Returns a nonzero value if *str* is not formatted correctly. .. function:: int arf_dump_file(FILE * stream, const arf_t x) Writes a binary representation of *x* to *stream* that can be read by :func:`arf_load_file`. Returns a nonzero value if the data could not be written. .. function:: int arf_load_file(arf_t x, FILE * stream) Reads *x* from *stream*. Returns a nonzero value if the data is not formatted correctly or the read failed. Note that the data is assumed to be delimited by a whitespace or end-of-file, i.e., when writing multiple values with :func:`arf_dump_file` make sure to insert a whitespace to separate consecutive values. Addition and multiplication ------------------------------------------------------------------------------- .. function:: void arf_abs(arf_t res, const arf_t x) Sets *res* to the absolute value of *x* exactly. .. function:: void arf_neg(arf_t res, const arf_t x) Sets *res* to `-x` exactly. .. function:: int arf_neg_round(arf_t res, const arf_t x, slong prec, arf_rnd_t rnd) Sets *res* to `-x`. .. function:: int arf_add(arf_t res, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_add_si(arf_t res, const arf_t x, slong y, slong prec, arf_rnd_t rnd) .. function:: int arf_add_ui(arf_t res, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) .. function:: int arf_add_fmpz(arf_t res, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) Sets *res* to `x + y`. .. function:: int arf_add_fmpz_2exp(arf_t res, const arf_t x, const fmpz_t y, const fmpz_t e, slong prec, arf_rnd_t rnd) Sets *res* to `x + y 2^e`. .. function:: int arf_sub(arf_t res, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_sub_si(arf_t res, const arf_t x, slong y, slong prec, arf_rnd_t rnd) .. function:: int arf_sub_ui(arf_t res, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) .. function:: int arf_sub_fmpz(arf_t res, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) Sets *res* to `x - y`. .. function:: void arf_mul_2exp_si(arf_t res, const arf_t x, slong e) .. function:: void arf_mul_2exp_fmpz(arf_t res, const arf_t x, const fmpz_t e) Sets *res* to `x 2^e` exactly. .. function:: int arf_mul(arf_t res, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_mul_ui(arf_t res, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) .. function:: int arf_mul_si(arf_t res, const arf_t x, slong y, slong prec, arf_rnd_t rnd) .. function:: int arf_mul_mpz(arf_t res, const arf_t x, const mpz_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_mul_fmpz(arf_t res, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) Sets *res* to `x \cdot y`. .. function:: int arf_addmul(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_addmul_ui(arf_t z, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) .. function:: int arf_addmul_si(arf_t z, const arf_t x, slong y, slong prec, arf_rnd_t rnd) .. function:: int arf_addmul_mpz(arf_t z, const arf_t x, const mpz_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_addmul_fmpz(arf_t z, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) Performs a fused multiply-add `z = z + x \cdot y`, updating *z* in-place. .. function:: int arf_submul(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_submul_ui(arf_t z, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) .. function:: int arf_submul_si(arf_t z, const arf_t x, slong y, slong prec, arf_rnd_t rnd) .. function:: int arf_submul_mpz(arf_t z, const arf_t x, const mpz_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_submul_fmpz(arf_t z, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) Performs a fused multiply-subtract `z = z - x \cdot y`, updating *z* in-place. .. function:: int arf_fma(arf_t res, const arf_t x, const arf_t y, const arf_t z, slong prec, arf_rnd_t rnd) Sets *res* to `x \cdot y + z`. This is equivalent to an *addmul* except that *res* and *z* can be separate variables. .. function:: int arf_sosq(arf_t res, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) Sets *res* to `x^2 + y^2`, rounded to *prec* bits in the direction specified by *rnd*. Summation ------------------------------------------------------------------------------- .. function:: int arf_sum(arf_t res, arf_srcptr terms, slong len, slong prec, arf_rnd_t rnd) Sets *res* to the sum of the array *terms* of length *len*, rounded to *prec* bits in the direction specified by *rnd*. The sum is computed as if done without any intermediate rounding error, with only a single rounding applied to the final result. Unlike repeated calls to :func:`arf_add` with infinite precision, this function does not overflow if the magnitudes of the terms are far apart. Warning: this function is implemented naively, and the running time is quadratic with respect to *len* in the worst case. Dot products ------------------------------------------------------------------------------- .. function:: void arf_approx_dot(arf_t res, const arf_t initial, int subtract, arf_srcptr x, slong xstep, arf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd) Computes an approximate dot product, with the same meaning of the parameters as :func:`arb_dot`. This operation is not correctly rounded: the final rounding is done in the direction ``rnd`` but intermediate roundings are implementation-defined. Division ------------------------------------------------------------------------------- .. function:: int arf_div(arf_t res, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_div_ui(arf_t res, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) .. function:: int arf_ui_div(arf_t res, ulong x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_div_si(arf_t res, const arf_t x, slong y, slong prec, arf_rnd_t rnd) .. function:: int arf_si_div(arf_t res, slong x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_div_fmpz(arf_t res, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_fmpz_div(arf_t res, const fmpz_t x, const arf_t y, slong prec, arf_rnd_t rnd) .. function:: int arf_fmpz_div_fmpz(arf_t res, const fmpz_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) Sets *res* to `x / y`, rounded to *prec* bits in the direction specified by *rnd*, returning nonzero iff the operation is inexact. The result is NaN if *y* is zero. Square roots ------------------------------------------------------------------------------- .. function:: int arf_sqrt(arf_t res, const arf_t x, slong prec, arf_rnd_t rnd) .. function:: int arf_sqrt_ui(arf_t res, ulong x, slong prec, arf_rnd_t rnd) .. function:: int arf_sqrt_fmpz(arf_t res, const fmpz_t x, slong prec, arf_rnd_t rnd) Sets *res* to `\sqrt{x}`. The result is NaN if *x* is negative. .. function:: int arf_rsqrt(arf_t res, const arf_t x, slong prec, arf_rnd_t rnd) Sets *res* to `1/\sqrt{x}`. The result is NaN if *x* is negative, and `+\infty` if *x* is zero. .. function:: int arf_root(arf_t res, const arf_t x, ulong k, slong prec, arf_rnd_t rnd) Sets *res* to `x^{1/k}`. The result is NaN if *x* is negative. Warning: this function is a wrapper around the MPFR root function. It gets slow and uses much memory for large *k*. Consider working with :func:`arb_root_ui` for large *k* instead of using this function directly. Complex arithmetic ------------------------------------------------------------------------------- .. function:: int arf_complex_mul(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d, slong prec, arf_rnd_t rnd) .. function:: int arf_complex_mul_fallback(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d, slong prec, arf_rnd_t rnd) Computes the complex product `e + fi = (a + bi)(c + di)`, rounding both `e` and `f` correctly to *prec* bits in the direction specified by *rnd*. The first bit in the return code indicates inexactness of `e`, and the second bit indicates inexactness of `f`. If any of the components *a*, *b*, *c*, *d* is zero, two real multiplications and no additions are done. This convention is used even if any other part contains an infinity or NaN, and the behavior with infinite/NaN input is defined accordingly. The *fallback* version is implemented naively, for testing purposes. No squaring optimization is implemented. .. function:: int arf_complex_sqr(arf_t e, arf_t f, const arf_t a, const arf_t b, slong prec, arf_rnd_t rnd) Computes the complex square `e + fi = (a + bi)^2`. This function has identical semantics to :func:`arf_complex_mul` (with `c = a, b = d`), but is faster. Low-level methods ------------------------------------------------------------------------------- .. function:: int _arf_get_integer_mpn(mp_ptr y, mp_srcptr xp, mp_size_t xn, slong exp) Given a floating-point number *x* represented by *xn* limbs at *xp* and an exponent *exp*, writes the integer part of *x* to *y*, returning whether the result is inexact. The correct number of limbs is written (no limbs are written if the integer part of *x* is zero). Assumes that ``xp[0]`` is nonzero and that the top bit of ``xp[xn-1]`` is set. .. function:: int _arf_set_mpn_fixed(arf_t z, mp_srcptr xp, mp_size_t xn, mp_size_t fixn, int negative, slong prec, arf_rnd_t rnd) Sets *z* to the fixed-point number having *xn* total limbs and *fixn* fractional limbs, negated if *negative* is set, rounding *z* to *prec* bits in the direction *rnd* and returning whether the result is inexact. Both *xn* and *fixn* must be nonnegative and not so large that the bit shift would overflow an *slong*, but otherwise no assumptions are made about the input. .. function:: int _arf_set_round_ui(arf_t z, ulong x, int sgnbit, slong prec, arf_rnd_t rnd) Sets *z* to the integer *x*, negated if *sgnbit* is 1, rounded to *prec* bits in the direction specified by *rnd*. There are no assumptions on *x*. .. function:: int _arf_set_round_uiui(arf_t z, slong * fix, mp_limb_t hi, mp_limb_t lo, int sgnbit, slong prec, arf_rnd_t rnd) Sets the mantissa of *z* to the two-limb mantissa given by *hi* and *lo*, negated if *sgnbit* is 1, rounded to *prec* bits in the direction specified by *rnd*. Requires that not both *hi* and *lo* are zero. Writes the exponent shift to *fix* without writing the exponent of *z* directly. .. function:: int _arf_set_round_mpn(arf_t z, slong * exp_shift, mp_srcptr x, mp_size_t xn, int sgnbit, slong prec, arf_rnd_t rnd) Sets the mantissa of *z* to the mantissa given by the *xn* limbs in *x*, negated if *sgnbit* is 1, rounded to *prec* bits in the direction specified by *rnd*. Returns the inexact flag. Requires that *xn* is positive and that the top limb of *x* is nonzero. If *x* has leading zero bits, writes the shift to *exp_shift*. This method does not write the exponent of *z* directly. Requires that *x* does not point to the limbs of *z*. flint-3.1.3/doc/source/arith.rst000066400000000000000000000541071461254215100165500ustar00rootroot00000000000000.. _arith: **arith.h** -- arithmetic and special functions ================================================================================ This module implements arithmetic functions, number-theoretic and combinatorial special number sequences and polynomials. Primorials -------------------------------------------------------------------------------- .. function:: void arith_primorial(fmpz_t res, slong n) Sets ``res`` to ``n`` primorial or `n \#`, the product of all prime numbers less than or equal to `n`. Harmonic numbers -------------------------------------------------------------------------------- .. function:: void _arith_harmonic_number(fmpz_t num, fmpz_t den, slong n) void arith_harmonic_number(fmpq_t x, slong n) These are aliases for the functions in the fmpq module. Stirling numbers -------------------------------------------------------------------------------- .. function:: void arith_stirling_number_1u(fmpz_t s, ulong n, ulong k) .. function:: void arith_stirling_number_1(fmpz_t s, ulong n, ulong k) .. function:: void arith_stirling_number_2(fmpz_t s, ulong n, ulong k) Sets `s` to `S(n,k)` where `S(n,k)` denotes an unsigned Stirling number of the first kind `|S_1(n, k)|`, a signed Stirling number of the first kind `S_1(n, k)`, or a Stirling number of the second kind `S_2(n, k)`. The Stirling numbers are defined using the generating functions .. math:: x_{(n)} = \sum_{k=0}^n S_1(n,k) x^k x^{(n)} = \sum_{k=0}^n |S_1(n,k)| x^k x^n = \sum_{k=0}^n S_2(n,k) x_{(k)} where `x_{(n)} = x(x-1)(x-2) \dotsm (x-n+1)` is a falling factorial and `x^{(n)} = x(x+1)(x+2) \dotsm (x+n-1)` is a rising factorial. `S(n,k)` is taken to be zero if `n < 0` or `k < 0`. These three functions are useful for computing isolated Stirling numbers efficiently. To compute a range of numbers, the vector or matrix versions should generally be used. .. function:: void arith_stirling_number_1u_vec(fmpz * row, ulong n, slong klen) .. function:: void arith_stirling_number_1_vec(fmpz * row, ulong n, slong klen) .. function:: void arith_stirling_number_2_vec(fmpz * row, ulong n, slong klen) Computes the row of Stirling numbers ``S(n,0), S(n,1), S(n,2), ..., S(n,klen-1)``. To compute a full row, this function can be called with ``klen = n+1``. It is assumed that ``klen`` is at most `n + 1`. .. function:: void arith_stirling_number_1u_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen) .. function:: void arith_stirling_number_1_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen) .. function:: void arith_stirling_number_2_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen) Given the vector ``prev`` containing a row of Stirling numbers ``S(n-1,0), S(n-1,1), S(n-1,2), ..., S(n-1,klen-1)``, computes and stores in the row argument ``S(n,0), S(n,1), S(n,2), ..., S(n,klen-1)``. If ``klen`` is greater than ``n``, the output ends with ``S(n,n) = 1`` followed by ``S(n,n+1) = S(n,n+2) = ... = 0``. In this case, the input only needs to have length ``n-1``; only the input entries up to ``S(n-1,n-2)`` are read. The ``row`` and ``prev`` arguments are permitted to be the same, meaning that the row will be updated in-place. .. function:: void arith_stirling_matrix_1u(fmpz_mat_t mat) .. function:: void arith_stirling_matrix_1(fmpz_mat_t mat) .. function:: void arith_stirling_matrix_2(fmpz_mat_t mat) For an arbitrary `m`-by-`n` matrix, writes the truncation of the infinite Stirling number matrix:: row 0 : S(0,0) row 1 : S(1,0), S(1,1) row 2 : S(2,0), S(2,1), S(2,2) row 3 : S(3,0), S(3,1), S(3,2), S(3,3) up to row `m-1` and column `n-1` inclusive. The upper triangular part of the matrix is zeroed. For any `n`, the `S_1` and `S_2` matrices thus obtained are inverses of each other. Bell numbers -------------------------------------------------------------------------------- .. function:: void arith_bell_number(fmpz_t b, ulong n) void arith_bell_number_dobinski(fmpz_t res, ulong n) void arith_bell_number_multi_mod(fmpz_t res, ulong n) Sets `b` to the Bell number `B_n`, defined as the number of partitions of a set with `n` members. Equivalently, `B_n = \sum_{k=0}^n S_2(n,k)` where `S_2(n,k)` denotes a Stirling number of the second kind. The default version automatically selects between table lookup, Dobinski's formula, and the multimodular algorithm. The ``dobinski`` version evaluates a precise truncation of the series `B_n = e^{-1} \sum_{k=0}^{\infty} \frac{k^n}{k!}` (Dobinski's formula). In fact, we compute `P = N! \sum_{k=0}^N \frac{k^n}{k!}` and `Q = N! \sum_{k=0}^N \frac{1}{k!} \approx N! e` and evaluate `B_n = \lceil P / Q \rceil`, avoiding the use of floating-point arithmetic. The ``multi_mod`` version computes the result modulo several limb-size primes and reconstructs the integer value using the fast Chinese remainder algorithm. A bound for the number of needed primes is computed using ``arith_bell_number_size``. .. function:: void arith_bell_number_vec(fmpz * b, slong n) void arith_bell_number_vec_recursive(fmpz * b, slong n) void arith_bell_number_vec_multi_mod(fmpz * b, slong n) Sets `b` to the vector of Bell numbers `B_0, B_1, \ldots, B_{n-1}` inclusive. The ``recursive`` version uses the `O(n^3 \log n)` triangular recurrence, while the ``multi_mod`` version implements multimodular evaluation of the exponential generating function, running in time `O(n^2 \log^{O(1)} n)`. The default version chooses an algorithm automatically. .. function:: mp_limb_t arith_bell_number_nmod(ulong n, nmod_t mod) Computes the Bell number `B_n` modulo an integer given by ``mod``. After handling special cases, we use the formula .. math:: B_n = \sum_{k=0}^n \frac{(n-k)^n}{(n-k)!} \sum_{j=0}^k \frac{(-1)^j}{j!}. We arrange the operations in such a way that we only have to multiply (and not divide) in the main loop. As a further optimisation, we use sieving to reduce the number of powers that need to be evaluated. This results in `O(n)` memory usage. If the divisions by factorials are impossible, we fall back to calling ``arith_bell_number_nmod_vec`` and reading the last coefficient. .. function:: void arith_bell_number_nmod_vec(mp_ptr b, slong n, nmod_t mod) void arith_bell_number_nmod_vec_recursive(mp_ptr b, slong n, nmod_t mod) void arith_bell_number_nmod_vec_ogf(mp_ptr b, slong n, nmod_t mod) int arith_bell_number_nmod_vec_series(mp_ptr b, slong n, nmod_t mod) Sets `b` to the vector of Bell numbers `B_0, B_1, \ldots, B_{n-1}` inclusive modulo an integer given by ``mod``. The *recursive* version uses the `O(n^2)` triangular recurrence. The *ogf* version expands the ordinary generating function using binary splitting, which is `O(n \log^2 n)`. The *series* version uses the exponential generating function `\sum_{k=0}^{\infty} \frac{B_n}{n!} x^n = \exp(e^x-1)`, running in `O(n \log n)`. This only works if division by `n!` is possible, and the function returns whether it is successful. All other versions support any modulus. The default version of this function selects an algorithm automatically. .. function:: double arith_bell_number_size(ulong n) Returns `b` such that `B_n < 2^{\lfloor b \rfloor}`. A previous version of this function used the inequality `B_n < \left(\frac{0.792n}{\log(n+1)}\right)^n` which is given in [BerTas2010]_; we now use a slightly better bound based on an asymptotic expansion. Bernoulli numbers and polynomials -------------------------------------------------------------------------------- .. function:: void _arith_bernoulli_number(fmpz_t num, fmpz_t den, ulong n) Sets ``(num, den)`` to the reduced numerator and denominator of the `n`-th Bernoulli number. .. function:: void arith_bernoulli_number(fmpq_t x, ulong n) Sets ``x`` to the `n`-th Bernoulli number. This function is equivalent to ``_arith_bernoulli_number`` apart from the output being a single ``fmpq_t`` variable. .. function:: void _arith_bernoulli_number_vec(fmpz * num, fmpz * den, slong n) Sets the elements of ``num`` and ``den`` to the reduced numerators and denominators of the Bernoulli numbers `B_0, B_1, B_2, \ldots, B_{n-1}` inclusive. This function automatically chooses between the ``recursive``, ``zeta`` and ``multi_mod`` algorithms according to the size of `n`. .. function:: void arith_bernoulli_number_vec(fmpq * x, slong n) Sets the ``x`` to the vector of Bernoulli numbers `B_0, B_1, B_2, \ldots, B_{n-1}` inclusive. This function is equivalent to ``_arith_bernoulli_number_vec`` apart from the output being a single ``fmpq`` vector. .. function:: void arith_bernoulli_number_denom(fmpz_t den, ulong n) Sets ``den`` to the reduced denominator of the `n`-th Bernoulli number `B_n`. For even `n`, the denominator is computed as the product of all primes `p` for which `p - 1` divides `n`; this property is a consequence of the von Staudt-Clausen theorem. For odd `n`, the denominator is trivial (``den`` is set to 1 whenever `B_n = 0`). The initial sequence of values smaller than `2^{32}` are looked up directly from a table. .. function:: double arith_bernoulli_number_size(ulong n) Returns `b` such that `|B_n| < 2^{\lfloor b \rfloor}`, using the inequality `|B_n| < \frac{4 n!}{(2\pi)^n}` and `n! \le (n+1)^{n+1} e^{-n}`. No special treatment is given to odd `n`. Accuracy is not guaranteed if `n > 10^{14}`. .. function:: void arith_bernoulli_polynomial(fmpq_poly_t poly, ulong n) Sets ``poly`` to the Bernoulli polynomial of degree `n`, `B_n(x) = \sum_{k=0}^n \binom{n}{k} B_k x^{n-k}` where `B_k` is a Bernoulli number. This function basically calls ``arith_bernoulli_number_vec`` and then rescales the coefficients efficiently. .. function:: void _arith_bernoulli_number_vec_recursive(fmpz * num, fmpz * den, slong n) Sets the elements of ``num`` and ``den`` to the reduced numerators and denominators of `B_0, B_1, B_2, \ldots, B_{n-1}` inclusive. The first few entries are computed using ``arith_bernoulli_number``, and then Ramanujan's recursive formula expressing `B_m` as a sum over `B_k` for `k` congruent to `m` modulo 6 is applied repeatedly. To avoid costly GCDs, the numerators are transformed internally to a common denominator and all operations are performed using integer arithmetic. This makes the algorithm fast for small `n`, say `n < 1000`. The common denominator is calculated directly as the primorial of `n + 1`. %[1] https://en.wikipedia.org/w/index.php?title=Bernoulli_number&oldid=405938876 .. function:: void _arith_bernoulli_number_vec_multi_mod(fmpz * num, fmpz * den, slong n) Sets the elements of ``num`` and ``den`` to the reduced numerators and denominators of `B_0, B_1, B_2, \ldots, B_{n-1}` inclusive. Uses the generating function .. math:: \frac{x^2}{\cosh(x)-1} = \sum_{k=0}^{\infty} \frac{(2-4k) B_{2k}}{(2k)!} x^{2k} which is evaluated modulo several limb-size primes using ``nmod_poly`` arithmetic to yield the numerators of the Bernoulli numbers after multiplication by the denominators and CRT reconstruction. This formula, given (incorrectly) in [BuhlerCrandallSompolski1992]_, saves about half of the time compared to the usual generating function `x/(e^x-1)` since the odd terms vanish. Euler numbers and polynomials -------------------------------------------------------------------------------- Euler numbers are the integers `E_n` defined by `\frac{1}{\cosh(t)} = \sum_{n=0}^{\infty} \frac{E_n}{n!} t^n.` With this convention, the odd-indexed numbers are zero and the even ones alternate signs, viz. `E_0, E_1, E_2, \ldots = 1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, \ldots`. The corresponding Euler polynomials are defined by `\frac{2e^{xt}}{e^t+1} = \sum_{n=0}^{\infty} \frac{E_n(x)}{n!} t^n.` .. function:: void arith_euler_number(fmpz_t res, ulong n) Sets ``res`` to the Euler number `E_n`. .. function:: void arith_euler_number_vec(fmpz * res, slong n) Computes the Euler numbers `E_0, E_1, \dotsc, E_{n-1}` for `n \geq 0` and stores the result in ``res``, which must be an initialised ``fmpz`` vector of sufficient size. This function evaluates the even-index `E_k` modulo several limb-size primes using the generating function and ``nmod_poly`` arithmetic. A tight bound for the number of needed primes is computed using ``arith_euler_number_size``, and the final integer values are recovered using balanced CRT reconstruction. .. function:: double arith_euler_number_size(ulong n) Returns `b` such that `|E_n| < 2^{\lfloor b \rfloor}`, using the inequality ``|E_n| < \frac{2^{n+2} n!}{\pi^{n+1}}`` and `n! \le (n+1)^{n+1} e^{-n}`. No special treatment is given to odd `n`. Accuracy is not guaranteed if `n > 10^{14}`. .. function:: void arith_euler_polynomial(fmpq_poly_t poly, ulong n) Sets ``poly`` to the Euler polynomial `E_n(x)`. Uses the formula .. math:: E_n(x) = \frac{2}{n+1}\left(B_{n+1}(x) - 2^{n+1}B_{n+1}\left(\frac{x}{2}\right)\right), with the Bernoulli polynomial `B_{n+1}(x)` evaluated once using ``bernoulli_polynomial`` and then rescaled. Multiplicative functions -------------------------------------------------------------------------------- .. function:: void arith_euler_phi(fmpz_t res, const fmpz_t n) int arith_moebius_mu(const fmpz_t n) void arith_divisor_sigma(fmpz_t res, ulong k, const fmpz_t n) These are aliases for the functions in the fmpz module. .. function:: void arith_divisors(fmpz_poly_t res, const fmpz_t n) Set the coefficients of the polynomial ``res`` to the divisors of `n`, including `1` and `n` itself, in ascending order. .. function:: void arith_ramanujan_tau(fmpz_t res, const fmpz_t n) Sets ``res`` to the Ramanujan tau function `\tau(n)` which is the coefficient of `q^n` in the series expansion of `f(q) = q \prod_{k \geq 1} \bigl(1 - q^k\bigr)^{24}`. We factor `n` and use the identity `\tau(pq) = \tau(p) \tau(q)` along with the recursion `\tau(p^{r+1}) = \tau(p) \tau(p^r) - p^{11} \tau(p^{r-1})` for prime powers. The base values `\tau(p)` are obtained using the function ``arith_ramanujan_tau_series()``. Thus the speed of ``arith_ramanujan_tau()`` depends on the largest prime factor of `n`. Future improvement: optimise this function for small `n`, which could be accomplished using a lookup table or by calling ``arith_ramanujan_tau_series()`` directly. .. function:: void arith_ramanujan_tau_series(fmpz_poly_t res, slong n) Sets ``res`` to the polynomial with coefficients `\tau(0),\tau(1), \dotsc, \tau(n-1)`, giving the initial `n` terms in the series expansion of `f(q) = q \prod_{k \geq 1} \bigl(1-q^k\bigr)^{24}`. We use the theta function identity .. math:: f(q) = q \Biggl( \sum_{k \geq 0} (-1)^k (2k+1) q^{k(k+1)/2} \Biggr)^8 which is evaluated using three squarings. The first squaring is done directly since the polynomial is very sparse at this point. Landau's function -------------------------------------------------------------------------------- .. function:: void arith_landau_function_vec(fmpz * res, slong len) Computes the first ``len`` values of Landau's function `g(n)` starting with `g(0)`. Landau's function gives the largest order of an element of the symmetric group `S_n`. Implements the "basic algorithm" given in [DelegliseNicolasZimmermann2009]_. The running time is `O(n^{3/2} / \sqrt{\log n})`. Dedekind sums -------------------------------------------------------------------------------- .. function:: void arith_dedekind_sum_naive(fmpq_t s, const fmpz_t h, const fmpz_t k) double arith_dedekind_sum_coprime_d(double h, double k) void arith_dedekind_sum_coprime_large(fmpq_t s, const fmpz_t h, const fmpz_t k) void arith_dedekind_sum_coprime(fmpq_t s, const fmpz_t h, const fmpz_t k) void arith_dedekind_sum(fmpq_t s, const fmpz_t h, const fmpz_t k) These are aliases for the functions in the fmpq module. Number of partitions -------------------------------------------------------------------------------- .. function:: void arith_number_of_partitions_vec(fmpz * res, slong len) Computes first ``len`` values of the partition function `p(n)` starting with `p(0)`. Uses inversion of Euler's pentagonal series. .. function:: void arith_number_of_partitions_nmod_vec(mp_ptr res, slong len, nmod_t mod) Computes first ``len`` values of the partition function `p(n)` starting with `p(0)`, modulo the modulus defined by ``mod``. Uses inversion of Euler's pentagonal series. .. function:: void trig_prod_init(trig_prod_t prod) Initializes ``prod``. This is an inline function only. .. function:: void arith_hrr_expsum_factored(trig_prod_t prod, mp_limb_t k, mp_limb_t n) Symbolically evaluates the exponential sum .. math:: A_k(n) = \sum_{h=0}^{k-1} \exp\left(\pi i \left[ s(h,k) - \frac{2hn}{k}\right]\right) appearing in the Hardy-Ramanujan-Rademacher formula, where `s(h,k)` is a Dedekind sum. Rather than evaluating the sum naively, we factor `A_k(n)` into a product of cosines based on the prime factorisation of `k`. This process is based on the identities given in [Whiteman1956]_. The special ``trig_prod_t`` structure ``prod`` represents a product of cosines of rational arguments, multiplied by an algebraic prefactor. It must be pre-initialised with ``trig_prod_init``. This function assumes that `24k` and `24n` do not overflow a single limb. If `n` is larger, it can be pre-reduced modulo `k`, since `A_k(n)` only depends on the value of `n \bmod k`. .. function:: void arith_number_of_partitions_mpfr(mpfr_t x, ulong n) Sets the pre-initialised MPFR variable `x` to the exact value of `p(n)`. The value is computed using the Hardy-Ramanujan-Rademacher formula. The precision of `x` will be changed to allow `p(n)` to be represented exactly. The interface of this function may be updated in the future to allow computing an approximation of `p(n)` to smaller precision. The Hardy-Ramanujan-Rademacher formula is given with error bounds in [Rademacher1937]_. We evaluate it in the form .. math:: p(n) = \sum_{k=1}^N B_k(n) U(C/k) + R(n,N) where .. math:: U(x) = \cosh(x) + \frac{\sinh(x)}{x}, \quad C = \frac{\pi}{6} \sqrt{24n-1} B_k(n) = \sqrt{\frac{3}{k}} \frac{4}{24n-1} A_k(n) and where `A_k(n)` is a certain exponential sum. The remainder satisfies .. math:: |R(n,N)| < \frac{44 \pi^2}{225 \sqrt{3}} N^{-1/2} + \frac{\pi \sqrt{2}}{75} \left(\frac{N}{n-1}\right)^{1/2} \sinh\left(\pi \sqrt{\frac{2}{3}} \frac{\sqrt{n}}{N} \right). We choose `N` such that `|R(n,N)| < 0.25`, and a working precision at term `k` such that the absolute error of the term is expected to be less than `0.25 / N`. We also use a summation variable with increased precision, essentially making additions exact. Thus the sum of errors adds up to less than 0.5, giving the correct value of `p(n)` when rounding to the nearest integer. The remainder estimate at step `k` provides an upper bound for the size of the `k`-th term. We add `\log_2 N` bits to get low bits in the terms below `0.25 / N` in magnitude. Using ``arith_hrr_expsum_factored``, each `B_k(n)` evaluation is broken down to a product of cosines of exact rational multiples of `\pi`. We transform all angles to `(0, \pi/4)` for optimal accuracy. Since the evaluation of each term involves only `O(\log k)` multiplications and evaluations of trigonometric functions of small angles, the relative rounding error is at most a few bits. We therefore just add an additional `\log_2 (C/k)` bits for the `U(x)` when `x` is large. The cancellation of terms in `U(x)` is of no concern, since Rademacher's bound allows us to terminate before `x` becomes small. This analysis should be performed in more detail to give a rigorous error bound, but the precision currently implemented is almost certainly sufficient, not least considering that Rademacher's remainder bound significantly overshoots the actual values. To improve performance, we switch to doubles when the working precision becomes small enough. We also use a separate accumulator variable which gets added to the main sum periodically, in order to avoid costly updates of the full-precision result when `n` is large. .. function:: void arith_number_of_partitions(fmpz_t x, ulong n) Sets `x` to `p(n)`, the number of ways that `n` can be written as a sum of positive integers without regard to order. This function uses a lookup table for `n < 128` (where `p(n) < 2^{32}`), and otherwise calls ``arith_number_of_partitions_mpfr``. Sums of squares -------------------------------------------------------------------------------- .. function:: void arith_sum_of_squares(fmpz_t r, ulong k, const fmpz_t n) Sets `r` to the number of ways `r_k(n)` in which `n` can be represented as a sum of `k` squares. If `k = 2` or `k = 4`, we write `r_k(n)` as a divisor sum. Otherwise, we either recurse on `k` or compute the theta function expansion up to `O(x^{n+1})` and read off the last coefficient. This is generally optimal. .. function:: void arith_sum_of_squares_vec(fmpz * r, ulong k, slong n) For `i = 0, 1, \ldots, n-1`, sets `r_i` to the number of representations of `i` a sum of `k` squares, `r_k(i)`. This effectively computes the `q`-expansion of `\vartheta_3(q)` raised to the `k`-th power, i.e. .. math:: \vartheta_3^k(q) = \left( \sum_{i=-\infty}^{\infty} q^{i^2} \right)^k. flint-3.1.3/doc/source/bernoulli.rst000066400000000000000000000134651461254215100174360ustar00rootroot00000000000000.. _bernoulli: **bernoulli.h** -- support for Bernoulli numbers =============================================================================== This module provides helper functions for exact or approximate calculation of the Bernoulli numbers, which are defined by the exponential generating function .. math:: \frac{x}{e^x-1} = \sum_{n=0}^{\infty} B_n \frac{x^n}{n!}. Efficient algorithms are implemented for both multi-evaluation and calculation of isolated Bernoulli numbers. A global (or thread-local) cache is also provided, to support fast repeated evaluation of various special functions that depend on the Bernoulli numbers (including the gamma function and the Riemann zeta function). Generation of Bernoulli numbers -------------------------------------------------------------------------------- .. type:: bernoulli_rev_t An iterator object for generating a range of even-indexed Bernoulli numbers exactly in reverse order, i.e. computing the exact fractions `B_n, B_{n-2}, B_{n-4}, \ldots, B_0`. The Bernoulli numbers are generated from scratch, i.e. no caching is performed. The Bernoulli numbers are computed by direct summation of the zeta series. This is made fast by storing a table of powers (as done by [Blo2009]_). As an optimization, we only include the odd powers, and use fixed-point arithmetic. The reverse iteration order is preferred for performance reasons, as the powers can be updated using multiplications instead of divisions, and we avoid having to periodically recompute terms to higher precision. To generate Bernoulli numbers in the forward direction without having to store all of them, one can split the desired range into smaller blocks and compute each block with a single reverse pass. .. function:: void bernoulli_rev_init(bernoulli_rev_t iter, ulong n) Initializes the iterator *iter*. The first Bernoulli number to be generated by calling :func:`bernoulli_rev_next` is `B_n`. It is assumed that `n` is even. .. function:: void bernoulli_rev_next(fmpz_t numer, fmpz_t denom, bernoulli_rev_t iter) Sets *numer* and *denom* to the exact, reduced numerator and denominator of the Bernoulli number `B_k` and advances the state of *iter* so that the next invocation generates `B_{k-2}`. .. function:: void bernoulli_rev_clear(bernoulli_rev_t iter) Frees all memory allocated internally by *iter*. .. function:: void bernoulli_fmpq_vec_no_cache(fmpq * res, ulong a, slong num) Writes *num* consecutive Bernoulli numbers to *res* starting with `B_a`. This function is not currently optimized for a small count *num*. The entries are not read from or written to the Bernoulli number cache; if retrieving a vector of Bernoulli numbers is needed more than once, use :func:`bernoulli_cache_compute` followed by :func:`bernoulli_fmpq_ui` instead. This function is a wrapper for the *rev* iterators. It can use multiple threads internally. Caching ------------------------------------------------------------------------------- .. var:: slong bernoulli_cache_num .. var:: fmpq * bernoulli_cache Cache of Bernoulli numbers. Uses thread-local storage if enabled in FLINT. .. function:: void bernoulli_cache_compute(slong n) Makes sure that the Bernoulli numbers up to at least `B_{n-1}` are cached. Calling :func:`flint_cleanup()` frees the cache. The cache is extended by calling :func:`bernoulli_fmpq_vec_no_cache` internally. Bounding ------------------------------------------------------------------------------- .. function:: slong bernoulli_bound_2exp_si(ulong n) Returns an integer `b` such that `|B_n| \le 2^b`. Uses a lookup table for small `n`, and for larger `n` uses the inequality `|B_n| < 4 n! / (2 \pi)^n < 4 (n+1)^{n+1} e^{-n} / (2 \pi)^n`. Uses integer arithmetic throughout, with the bound for the logarithm being looked up from a table. If `|B_n| = 0`, returns *LONG_MIN*. Otherwise, the returned exponent `b` is never more than one percent larger than the true magnitude. This function is intended for use when `n` small enough that one might comfortably compute `B_n` exactly. It aborts if `n` is so large that internal overflow occurs. Isolated Bernoulli numbers ------------------------------------------------------------------------------- .. function:: ulong bernoulli_mod_p_harvey(ulong n, ulong p) Returns the `B_n` modulo the prime number *p*, computed using Harvey's algorithm [Har2010]_. The running time is linear in *p*. If *p* divides the numerator of `B_n`, *UWORD_MAX* is returned as an error code. .. function:: void _bernoulli_fmpq_ui_zeta(fmpz_t num, fmpz_t den, ulong n) void _bernoulli_fmpq_ui_multi_mod(fmpz_t num, fmpz_t den, ulong n, double alpha) Sets *num* and *den* to the reduced numerator and denominator of the Bernoulli number `B_n`. The *zeta* version computes the denominator `d` using the von Staudt-Clausen theorem, numerically approximates `B_n` using :func:`arb_bernoulli_ui_zeta`, and then rounds `d B_n` to the correct numerator. The *multi_mod* version reconstructs `B_n` by computing the high bits via the Riemann zeta function and the low bits via Harvey's multimodular algorithm. The tuning parameter *alpha* should be a fraction between 0 and 1 controlling the number of bits to compute by the multimodular algorithm. If set to a negative number, a default value will be used. .. function:: void _bernoulli_fmpq_ui(fmpz_t num, fmpz_t den, ulong n) void bernoulli_fmpq_ui(fmpq_t b, ulong n) Computes the Bernoulli number `B_n` as an exact fraction, for an isolated integer `n`. This function reads `B_n` from the global cache if the number is already cached, but does not automatically extend the cache by itself. flint-3.1.3/doc/source/bool_mat.rst000066400000000000000000000217121461254215100172310ustar00rootroot00000000000000.. _bool-mat: **bool_mat.h** -- matrices over booleans =============================================================================== A :type:`bool_mat_t` represents a dense matrix over the boolean semiring `\langle \left\{0, 1\right\}, \vee, \wedge \rangle`, implemented as an array of entries of type ``int``. The dimension (number of rows and columns) of a matrix is fixed at initialization, and the user must ensure that inputs and outputs to an operation have compatible dimensions. The number of rows or columns in a matrix can be zero. Types, macros and constants ------------------------------------------------------------------------------- .. type:: bool_mat_struct .. type:: bool_mat_t Contains a pointer to a flat array of the entries (entries), an array of pointers to the start of each row (rows), and the number of rows (r) and columns (c). An *bool_mat_t* is defined as an array of length one of type *bool_mat_struct*, permitting an *bool_mat_t* to be passed by reference. .. function:: int bool_mat_get_entry(const bool_mat_t mat, slong i, slong j) Returns the entry of matrix *mat* at row *i* and column *j*. .. function:: void bool_mat_set_entry(bool_mat_t mat, slong i, slong j, int x) Sets the entry of matrix *mat* at row *i* and column *j* to *x*. .. macro:: bool_mat_nrows(mat) Returns the number of rows of the matrix. .. macro:: bool_mat_ncols(mat) Returns the number of columns of the matrix. Memory management ------------------------------------------------------------------------------- .. function:: void bool_mat_init(bool_mat_t mat, slong r, slong c) Initializes the matrix, setting it to the zero matrix with *r* rows and *c* columns. .. function:: void bool_mat_clear(bool_mat_t mat) Clears the matrix, deallocating all entries. .. function:: int bool_mat_is_empty(const bool_mat_t mat) Returns nonzero iff the number of rows or the number of columns in *mat* is zero. Note that this does not depend on the entry values of *mat*. .. function:: int bool_mat_is_square(const bool_mat_t mat) Returns nonzero iff the number of rows is equal to the number of columns in *mat*. Conversions ------------------------------------------------------------------------------- .. function:: void bool_mat_set(bool_mat_t dest, const bool_mat_t src) Sets *dest* to *src*. The operands must have identical dimensions. Input and output ------------------------------------------------------------------------------- .. function:: void bool_mat_print(const bool_mat_t mat) Prints each entry in the matrix. .. function:: void bool_mat_fprint(FILE * file, const bool_mat_t mat) Prints each entry in the matrix to the stream *file*. Value comparisons ------------------------------------------------------------------------------- .. function:: int bool_mat_equal(const bool_mat_t mat1, const bool_mat_t mat2) Returns nonzero iff the matrices have the same dimensions and identical entries. .. function:: int bool_mat_any(const bool_mat_t mat) Returns nonzero iff *mat* has a nonzero entry. .. function:: int bool_mat_all(const bool_mat_t mat) Returns nonzero iff all entries of *mat* are nonzero. .. function:: int bool_mat_is_diagonal(const bool_mat_t A) Returns nonzero iff `i \ne j \implies \bar{A_{ij}}`. .. function:: int bool_mat_is_lower_triangular(const bool_mat_t A) Returns nonzero iff `i < j \implies \bar{A_{ij}}`. .. function:: int bool_mat_is_transitive(const bool_mat_t mat) Returns nonzero iff `A_{ij} \wedge A_{jk} \implies A_{ik}`. .. function:: int bool_mat_is_nilpotent(const bool_mat_t A) Returns nonzero iff some positive matrix power of `A` is zero. Random generation ------------------------------------------------------------------------------- .. function:: void bool_mat_randtest(bool_mat_t mat, flint_rand_t state) Sets *mat* to a random matrix. .. function:: void bool_mat_randtest_diagonal(bool_mat_t mat, flint_rand_t state) Sets *mat* to a random diagonal matrix. .. function:: void bool_mat_randtest_nilpotent(bool_mat_t mat, flint_rand_t state) Sets *mat* to a random nilpotent matrix. Special matrices ------------------------------------------------------------------------------- .. function:: void bool_mat_zero(bool_mat_t mat) Sets all entries in mat to zero. .. function:: void bool_mat_one(bool_mat_t mat) Sets the entries on the main diagonal to ones, and all other entries to zero. .. function:: void bool_mat_directed_path(bool_mat_t A) Sets `A_{ij}` to `j = i + 1`. Requires that `A` is a square matrix. .. function:: void bool_mat_directed_cycle(bool_mat_t A) Sets `A_{ij}` to `j = (i + 1) \mod n` where `n` is the order of the square matrix `A`. Transpose ------------------------------------------------------------------------------- .. function:: void bool_mat_transpose(bool_mat_t dest, const bool_mat_t src) Sets *dest* to the transpose of *src*. The operands must have compatible dimensions. Aliasing is allowed. Arithmetic ------------------------------------------------------------------------------- .. function:: void bool_mat_complement(bool_mat_t B, const bool_mat_t A) Sets *B* to the logical complement of *A*. That is `B_{ij}` is set to `\bar{A_{ij}}`. The operands must have the same dimensions. .. function:: void bool_mat_add(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2) Sets *res* to the sum of *mat1* and *mat2*. The operands must have the same dimensions. .. function:: void bool_mat_mul(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2) Sets *res* to the matrix product of *mat1* and *mat2*. The operands must have compatible dimensions for matrix multiplication. .. function:: void bool_mat_mul_entrywise(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2) Sets *res* to the entrywise product of *mat1* and *mat2*. The operands must have the same dimensions. .. function:: void bool_mat_sqr(bool_mat_t B, const bool_mat_t A) Sets *B* to the matrix square of *A*. The operands must both be square with the same dimensions. .. function:: void bool_mat_pow_ui(bool_mat_t B, const bool_mat_t A, ulong exp) Sets *B* to *A* raised to the power *exp*. Requires that *A* is a square matrix. Special functions ------------------------------------------------------------------------------- .. function:: int bool_mat_trace(const bool_mat_t mat) Returns the trace of the matrix, i.e. the sum of entries on the main diagonal of *mat*. The matrix is required to be square. The sum is in the boolean semiring, so this function returns nonzero iff any entry on the diagonal of *mat* is nonzero. .. function:: slong bool_mat_nilpotency_degree(const bool_mat_t A) Returns the nilpotency degree of the `n \times n` matrix *A*. It returns the smallest positive `k` such that `A^k = 0`. If no such `k` exists then the function returns `-1` if `n` is positive, and otherwise it returns `0`. .. function:: void bool_mat_transitive_closure(bool_mat_t B, const bool_mat_t A) Sets *B* to the transitive closure `\sum_{k=1}^\infty A^k`. The matrix *A* is required to be square. .. function:: slong bool_mat_get_strongly_connected_components(slong * p, const bool_mat_t A) Partitions the `n` row and column indices of the `n \times n` matrix *A* according to the strongly connected components (SCC) of the graph for which *A* is the adjacency matrix. If the graph has `k` SCCs then the function returns `k`, and for each vertex `i \in [0, n-1]`, `p_i` is set to the index of the SCC to which the vertex belongs. The SCCs themselves can be considered as nodes in a directed acyclic graph (DAG), and the SCCs are indexed in postorder with respect to that DAG. .. function:: slong bool_mat_all_pairs_longest_walk(fmpz_mat_t B, const bool_mat_t A) Sets `B_{ij}` to the length of the longest walk with endpoint vertices `i` and `j` in the graph whose adjacency matrix is *A*. The matrix *A* must be square. Empty walks with zero length which begin and end at the same vertex are allowed. If `j` is not reachable from `i` then no walk from `i` to `j` exists and `B_{ij}` is set to the special value `-1`. If arbitrarily long walks from `i` to `j` exist then `B_{ij}` is set to the special value `-2`. The function returns `-2` if any entry of `B_{ij}` is `-2`, and otherwise it returns the maximum entry in `B`, except if `A` is empty in which case `-1` is returned. Note that the returned value is one less than that of :func:`nilpotency_degree`. This function can help quantify entrywise errors in a truncated evaluation of a matrix power series. If *A* is an indicator matrix with the same sparsity pattern as a matrix `M` over the real or complex numbers, and if `B_{ij}` does not take the special value `-2`, then the tail `\left[ \sum_{k=N}^\infty a_k M^k \right]_{ij}` vanishes when `N > B_{ij}`. flint-3.1.3/doc/source/bug_reporting.rst000066400000000000000000000014501461254215100203000ustar00rootroot00000000000000.. _bug_reporting: **Bug reporting** =============================================================================== Reporting bugs ------------------------------------------------------------------------------- The maintainers wishes to be made aware of any and all bugs. Please open an issue at the GitHub repository (https://github.com/flintlib/flint) or send an email with your bug report to the FLINT devel list https://groups.google.com/group/flint-devel. If possible please include details of your system, how Flint was complied/installed, the versions of GMP and MPFR as well as precise details of how to replicate the bug. Note that FLINT needs to be linked against version 6.2.1 or later of GMP, version 4.1.0 or later of MPFR. Version 4.8 or later of GCC is recommended for parallel builds. flint-3.1.3/doc/source/building.rst000066400000000000000000000235571461254215100172430ustar00rootroot00000000000000.. _building: **Building, testing and installing** =============================================================================== Quick start ------------------------------------------------------------------------------- Building FLINT requires: * GMP, at least version 6.2.1 (https://gmplib.org/) * MPFR, at least version 4.1.0 (https://mpfr.org/) * Either of the following build systems: * GNU Make together with GNU Autotools (Recommended) * CMake (Recommended only for Windows users) On a typical Linux or Unix-like system where Autotools is available (see below for instructions using CMake), FLINT can be built and installed as follows: .. code-block:: bash ./bootstrap.sh ./configure --disable-static make -j N make install where ``N`` is the number of jobs number allowed to run parallel. Typically, the fastest way to build is to let ``N`` be the number of threads your CPU plus one, which can be obtained in Bash through ``$(expr $(nproc) + 1)``. We also recommend that you check that the library works as it should through ``make check``, or ``make -j N check`` for a parallel check, before installing. For a complete list of build settings, type .. code-block:: bash ./configure --help An example of a custom configuration command would be .. code-block:: bash ./configure \ --enable-assert \ --enable-avx2 \ --disable-static \ --with-gmp-include=/home/user1/builds/includes/ \ --with-gmp-lib=/home/user1/builds/lib/ \ --with-mpfr=/usr \ --prefix=/home/user1/installations/ \ CC=clang \ CFLAGS="-Wall -O3 -march=alderlake" Library and install paths ------------------------------------------------------------------------------- If you intend to install the FLINT library and header files, you can specify where they should be placed by passing ``--prefix=path`` to ``configure``, where ``path`` is the directory under which the ``lib`` and ``include`` directories exist into which you wish to place the FLINT files when it is installed. If GMP and MPFR are not installed in the default search path of your compiler (e.g. ``/usr/include/`` and ``/usr/lib/``), you must specify where they are by passing their location to configure ``--with-gmp=ABSOLUTE_PATH`` for GMP and ``--with-mpfr=ABSOLUTE_PATH`` for MPFR. Note that the FLINT build system can handle GMP and MPFR as installed at some location and as source builds (built from source but not installed). Though, to run the FLINT tests, GMP and MPFR needs to be properly installed. Testing FLINT ------------------------------------------------------------------------------- The full FLINT test suite can be run using .. code-block:: bash make check or in parallel on a multicore system using .. code-block:: bash make -j check Here, ``make -j N check`` is typically the fastest way to build when ``N`` equals to the number of threads your system's CPU has plus one, that is, ``make -j $(expr $(nproc) + 1) check`` typically is the fastest way to check FLINT. Number of test iterations ............................................................................... The number of test iterations can be changed with the ``FLINT_TEST_MULTIPLIER`` environment variable. For example, the following will only run 10% of the default iterations:: export FLINT_TEST_MULTIPLIER=0.1 make check Conversely, ``FLINT_TEST_MULTIPLIER=10`` will stress test FLINT by performing 10x the default number of iterations. Testing single modules ............................................................................... If you wish to simply check a single module of FLINT you can pass the option ``MOD=modname`` to ``make check``. You can also pass a list of module names: .. code-block:: bash make check MOD=ulong_extras make -j N check MOD="fft fmpz_mat" Testing single functions ............................................................................... Testing a single function is also possible, although one cannot utilize ``make`` all the way through for this. For example, if you would like to test the function ``fmpz_add`` and ``fmpz_sub`` in the module ``fmpz``, you run .. code-block:: bash # Build all tests make tests # Run the test executable for `fmpz' with `fmpz_add' and `fmpz_sub' as inputs ./build/fmpz/test/main fmpz_add fmpz_sub Test coverage ............................................................................... To obtain coverage statistics for the FLINT test suite, assuming that ``gcov`` and ``lcov`` are installed, configure FLINT with ``--enable-coverage``. Then run: .. code-block:: bash make -j N check make coverage_html This will place a coverage report in ``build/coverage``. Static or dynamic library only ------------------------------------------------------------------------------- FLINT builds static and shared libraries by default, except on platforms where this is not supported. If you do not require either a shared or static library then you may pass ``--disable-static`` or ``--disable-shared`` to ``configure``. This can substantially speed up the build. AVX2 instructions ------------------------------------------------------------------------------- On x86-64 machines with AVX2 support, compiling FLINT with the ``--enable-avx2`` option can improve performance substantially, notably by enabling the small-prime FFT. Currently this option is not enabled by default. TLS, reentrancy and single mode ------------------------------------------------------------------------------- FLINT uses thread local storage by default (``--enable-tls``). However, if reentrancy is required on systems that do not support this, one can pass ``--disable-tls`` and mutexes will be used instead (requires POSIX). As most modern systems support thread local storage, it is not recommended to build FLINT without TLS. There are two modes in which FLINT may installed: the default "single" mode, which is faster, but makes use of thread local storage for its memory manager and to handle threading, and a slower but less complicated "reentrant" mode. The later is useful when debugging a program where tracing allocations is important. If you wish to select the single mode, pass the ``--disable-reentrant`` option to configure, though note that this is the default. The reentrant mode is selected by passing the option ``--enable-reentrant`` to configure. ABI and architecture support ------------------------------------------------------------------------------- On some systems, e.g. Sparc and some Macs, more than one ABI is available. FLINT chooses the ABI based on the CPU type available, however its default choice can be overridden by passing either ``ABI=64`` or ``ABI=32`` to configure. To build on MinGW64 it is necessary to pass ``ABI=64`` to configure, as FLINT is otherwise unable to distinguish it from MinGW32. In some cases, it is necessary to override the CPU/OS defaults. This can be done by specifying the build system triplet to ``configure`` via ``--build=arch-vendor-os``. It is also possible to override the default CC, AR and CFLAGS used by FLINT by passing ``CC=full_path_to_compiler``, etc., to FLINT's configure. CMake build for Windows users ------------------------------------------------------------------------------- For Windows users, we also provide a way to install FLINT using CMake. Note, however, that FLINT's CMake script only exists to provide Windows users a way to install FLINT. For UNIX-type systems, please use Autotools along with GNU Make instead, as described at the top of this page. If you wish to install FLINT with CMake on Windows, simply type: .. code-block:: bash mkdir build && cd build cmake .. -DBUILD_SHARED_LIBS=ON cmake --build . --target install Uninstalling FLINT ------------------------------------------------------------------------------- To uninstall FLINT with GNU make, type: .. code-block:: bash make uninstall Now to use FLINT, simply include the appropriate header files for the FLINT modules you wish to use in your C program. Then compile your program, linking against the FLINT library, GMP, MPFR and pthreads with the options ``-lflint -lmpfr -lgmp -lpthread``. To clean up the local build files, use: .. code-block:: bash make clean make distclean Assertion checking ------------------------------------------------------------------------------- FLINT has an assert system. If you want a debug build you can pass ``--enable-assert`` to configure. However, this will slow FLINT considerably, so asserts should not be enabled (``--disable-assert``, the default) for deployment. Linking and running code ------------------------------------------------------------------------------- Here is an example program to get started using FLINT: .. code-block:: c #include "flint/flint.h" #include "flint/arb.h" int main() { arb_t x; arb_init(x); arb_const_pi(x, 50 * 3.33); arb_printn(x, 50, 0); flint_printf("\n"); flint_printf("Computed with FLINT-%s\n", flint_version); arb_clear(x); } Compile it with:: gcc test.c -lflint You may also have to pass the flags ``-lmpfr`` and ``-lgmp`` to the compiler. If the FLINT header and library files are not in a standard location such as ``/usr/local``, you may also have to provide flags such as:: -I/path/to/flint -L/path/to/flint Finally, to run the program, make sure that the linker can find ``libflint``. If it is installed in a nonstandard location, you can for example add this path to the ``LD_LIBRARY_PATH`` environment variable. The output of the example program should be something like the following:: [3.1415926535897932384626433832795028841971693993751 +/- 4.43e-50] Computed with flint-3.0.0 flint-3.1.3/doc/source/ca.rst000066400000000000000000001727411461254215100160310ustar00rootroot00000000000000.. _ca: **ca.h** -- exact real and complex numbers =============================================================================== A :type:`ca_t` represents a real or complex number in a form suitable for exact field arithmetic or comparison. Exceptionally, a :type:`ca_t` may represent a special nonnumerical value, such as an infinity. Introduction: numbers ------------------------------------------------------------------------------- A *Calcium number* is a real or complex number represented as an element of a formal field `K = \mathbb{Q}(a_1, \ldots, a_n)` where the symbols `a_k` denote fixed algebraic or transcendental numbers called *extension numbers*. For example, `e^{-2 \pi} - 3 i` may be represented as `(1 - 3 a_2^2 a_1) / a_2^2` in the field `\mathbb{Q}(a_1,a_2)` with `a_1 = i, a_2 = e^{\pi}`. Extension numbers and fields are documented in the following separate modules: * :ref:`ca-ext` * :ref:`ca-field` The user does not need to construct extension numbers or formal extension fields explicitly: each :type:`ca_t` contains an internal pointer to its formal field, and operations on Calcium numbers generate and cache fields automatically as needed to express the results. This representation is not canonical (in general). A given complex number can be represented in different ways depending on the choice of formal field *K*. Even within a fixed field *K*, a number can have different representations if there are algebraic relations between the extension numbers. Two numbers *x* and *y* can be tested for inequality using numerical evaluation; to test for equality, it may be necessary to eliminate dependencies between extension numbers. One of the central goals of Calcium will be to implement heuristics for such elimination. Together with each formal field *K*, Calcium stores a *reduction ideal* `I = \{g_1,\ldots,g_m\}` with `g_i \in \mathbb{Z}[a_1,\ldots,a_n]`, defining a set of algebraic relations `g_i(a_1,\ldots,a_n) = 0`. Relations can be absolute, say `g_i = a_j^2 + 1`, or relative, say `g_i = 2 a_j - 4 a_k - a_l a_m`. The reduction ideal effectively partitions `K` into equivalence classes of complex numbers (e.g. `i^2 = -1` or `2 \log(\pi i) = 4 \log(\sqrt{\pi}) + \pi i`), enabling simplifications and equality proving. Extension numbers are always sorted `a_1 \succ a_2 \succ \ldots \succ a_n` where `\succ` denotes a structural ordering (see :func:`ca_cmp_repr`). If the reduction ideal is triangular and the multivariate polynomial arithmetic uses lexicographic ordering, reduction by *I* eliminates numbers `a_i` with higher complexity in the sense of `\succ`. The reduction ideal is an imperfect computational crutch: it is not guaranteed to capture *all* algebraic relations, and reduction is not guaranteed to produce uniquely defined representatives. However, in the specific case of an absolute number field `K = \mathbb{Q}(a)` where *a* is a :type:`qqbar_t` extension, the reduction ideal (consisting of a single minimal polynomial) is canonical and field elements of *K* can be chosen canonically. Introduction: special values ------------------------------------------------------------------------------- In order to provide a closed arithmetic system and express limiting cases of operators and special functions, a :type:`ca_t` can hold any of the following special values besides ordinary numbers: * *Unsigned infinity*, a formal object `{\tilde \infty}` representing the value of `1 / 0`. More generally, this is the value of meromorphic functions at poles. * *Signed infinity*, a formal object `a \cdot \infty` where the sign `a` is a Calcium number with `|a| = 1`. The most common values are `+\infty, -\infty, +i \infty, -i \infty`. Signed infinities are used to denote directional limits and logarithmic singularities (for example, `\log(0) = -\infty`). * *Undefined*, a formal object representing the value of indeterminate forms such as `0 / 0` and essential singularities such as `\exp(\tilde \infty)`, where a number or infinity would not make sense as an answer. * *Unknown*, a meta-value used to signal that the actual desired value could not be computed, either because Calcium does not (yet) have a data structure or algorithm for that case, or because doing so would be unreasonably expensive. This occurs, for example, if Calcium performs a division and is unable to decide whether the result is a number, unsigned infinity or undefined (because testing for zero fails). Wrappers may want to check output variables for *Unknown* and throw an exception (e.g. *NotImplementedError* in Python). The distinction between *Calcium numbers* (which must represent elements of `\mathbb{C}`) and the different kinds of nonnumerical values (infinities, Undefined or Unknown) is essential. Nonnumerical values may not be used as field extension numbers `a_k`, and the denominator of a formal field element must always represent a nonzero complex number. Accordingly, for any given Calcium value *x* that is not *Unknown*, it is exactly known whether *x* represents A) a number, B) unsigned infinity, C) a signed infinity, or D) Undefined. Number objects ------------------------------------------------------------------------------- For all types, a *type_t* is defined as an array of length one of type *type_struct*, permitting a *type_t* to be passed by reference. .. type:: ca_struct .. type:: ca_t A :type:`ca_t` contains an index to a field *K*, and data representing an element *x* of *K*. The data is either an inline rational number (:type:`fmpq_t`), an inline Antic number field element (:type:`nf_elem_t`) when *K* is an absolute algebraic number field `\mathbb{Q}(a)`, or a pointer to a heap-allocated :type:`fmpz_mpoly_q_t` representing an element of a generic field `\mathbb{Q}(a_1,\ldots,a_n)`. Special values are encoded using magic bits in the field index. .. type:: ca_ptr Alias for ``ca_struct *``, used for vectors of numbers. .. type:: ca_srcptr Alias for ``const ca_struct *``, used for vectors of numbers when passed as constant input to functions. Context objects ------------------------------------------------------------------------------- .. type:: ca_ctx_struct .. type:: ca_ctx_t A :type:`ca_ctx_t` context object holds a cache of fields *K* and constituent extension numbers `a_k`. The field index in an individual :type:`ca_t` instance represents a shallow reference to the object defining the field *K* within the context object, so creating many elements of the same field is cheap. Since context objects are mutable (and may be mutated even when performing read-only operations on :type:`ca_t` instances), they must not be accessed simultaneously by different threads: in multithreaded environments, the user must use a separate context object for each thread. .. function:: void ca_ctx_init(ca_ctx_t ctx) Initializes the context object *ctx* for use. Any evaluation options stored in the context object are set to default values. .. function:: void ca_ctx_clear(ca_ctx_t ctx) Clears the context object *ctx*, freeing any memory allocated internally. This function should only be called after all :type:`ca_t` instances referring to this context have been cleared. .. function:: void ca_ctx_print(ca_ctx_t ctx) Prints a description of the context *ctx* to standard output. This will give a complete listing of the cached fields in *ctx*. Memory management for numbers ------------------------------------------------------------------------------- .. function:: void ca_init(ca_t x, ca_ctx_t ctx) Initializes the variable *x* for use, associating it with the context object *ctx*. The value of *x* is set to the rational number 0. .. function:: void ca_clear(ca_t x, ca_ctx_t ctx) Clears the variable *x*. .. function:: void ca_swap(ca_t x, ca_t y, ca_ctx_t ctx) Efficiently swaps the variables *x* and *y*. Symbolic expressions ------------------------------------------------------------------------------- .. function:: void ca_get_fexpr(fexpr_t res, const ca_t x, ulong flags, ca_ctx_t ctx) Sets *res* to a symbolic expression representing *x*. .. function:: int ca_set_fexpr(ca_t res, const fexpr_t expr, ca_ctx_t ctx) Sets *res* to the value represented by the symbolic expression *expr*. Returns 1 on success and 0 on failure. This function essentially just traverses the expression tree using ``ca`` arithmetic; it does not provide advanced symbolic evaluation. It is guaranteed to at least be able to parse the output of :func:`ca_get_fexpr`. .. _ca-printing: Printing ------------------------------------------------------------------------------- The style of printed output is controlled by ``ctx->options[CA_OPT_PRINT_FLAGS]`` (see :ref:`context-options`) which can be set to any combination of the following flags: .. macro:: CA_PRINT_N Print a decimal approximation of the number. The approximation is guaranteed to be correctly rounded to within one unit in the last place. If combined with ``CA_PRINT_REPR``, numbers appearing within the symbolic representation will also be printed with decimal approximations. Warning: printing a decimal approximation requires a computation, which can be expensive. It can also mutate cached data (numerical enclosures of extension numbers), affecting subsequent computations. .. macro:: CA_PRINT_DIGITS Multiplied by a positive integer, specifies the number of decimal digits to show with ``CA_PRINT_N``. If not given, the default precision is six digits. .. macro:: CA_PRINT_REPR Print the symbolic representation of the number (including its recursive elements). If used together with ``CA_PRINT_N``, field elements will print as ``decimal {symbolic}`` while extension numbers will print as ``decimal [symbolic]``. All extension numbers appearing in the field defining ``x`` and in the inner constructions of those extension numbers will be given local labels ``a``, ``b``, etc. for this printing. .. macro:: CA_PRINT_FIELD For each field element, explicitly print its formal field along with its reduction ideal if present, e.g. ``QQ`` or ``QQ(a,b,c) / ``. .. macro:: CA_PRINT_DEFAULT The default print style. Equivalent to ``CA_PRINT_N | CA_PRINT_REPR``. .. macro:: CA_PRINT_DEBUG Verbose print style for debugging. Equivalent to ``CA_PRINT_N | CA_PRINT_REPR | CA_PRINT_FIELD``. As a special case, small integers are always printed as simple literals. As illustration, here are the numbers `-7`, `2/3`, `(\sqrt{3}+5)/2` and `\sqrt{2} (\log(\pi) + \pi i)` printed in various styles:: # CA_PRINT_DEFAULT -7 0.666667 {2/3} 3.36603 {(a+5)/2 where a = 1.73205 [a^2-3=0]} 1.61889 + 4.44288*I {a*c+b*c*d where a = 1.14473 [Log(3.14159 {b})], b = 3.14159 [Pi], c = 1.41421 [c^2-2=0], d = I [d^2+1=0]} # CA_PRINT_N -7 0.666667 3.36603 1.61889 + 4.44288*I # CA_PRINT_N | (CA_PRINT_DIGITS * 20) -7 0.66666666666666666667 3.3660254037844386468 1.6188925298220266685 + 4.4428829381583662470*I # CA_PRINT_REPR -7 2/3 (a+5)/2 where a = [a^2-3=0] a*c+b*c*d where a = Log(b), b = Pi, c = [c^2-2=0], d = [d^2+1=0] # CA_PRINT_DEBUG -7 0.666667 {2/3 in QQ} 3.36603 {(a+5)/2 in QQ(a)/ where a = 1.73205 [a^2-3=0]} 1.61889 + 4.44288*I {a*c+b*c*d in QQ(a,b,c,d)/ where a = 1.14473 [Log(3.14159 {b in QQ(b)})], b = 3.14159 [Pi], c = 1.41421 [c^2-2=0], d = I [d^2+1=0]} .. function:: void ca_print(const ca_t x, ca_ctx_t ctx) Prints *x* to standard output. .. function:: void ca_fprint(FILE * fp, const ca_t x, ca_ctx_t ctx) Prints *x* to the file *fp*. .. function:: char * ca_get_str(const ca_t x, ca_ctx_t ctx) Prints *x* to a string which is returned. The user should free this string by calling ``flint_free``. .. function:: void ca_printn(const ca_t x, slong n, ca_ctx_t ctx) Prints an *n*-digit numerical representation of *x* to standard output. Special values ------------------------------------------------------------------------------- .. function:: void ca_zero(ca_t res, ca_ctx_t ctx) void ca_one(ca_t res, ca_ctx_t ctx) void ca_neg_one(ca_t res, ca_ctx_t ctx) Sets *res* to the integer 0, 1 or -1. This creates a canonical representation of this number as an element of the trivial field `\mathbb{Q}`. .. function:: void ca_i(ca_t res, ca_ctx_t ctx) void ca_neg_i(ca_t res, ca_ctx_t ctx) Sets *res* to the imaginary unit `i = \sqrt{-1}`, or its negation `-i`. This creates a canonical representation of `i` as the generator of the algebraic number field `\mathbb{Q}(i)`. .. function:: void ca_pi(ca_t res, ca_ctx_t ctx) Sets *res* to the constant `\pi`. This creates an element of the transcendental number field `\mathbb{Q}(\pi)`. .. function:: void ca_pi_i(ca_t res, ca_ctx_t ctx) Sets *res* to the constant `\pi i`. This creates an element of the composite field `\mathbb{Q}(i,\pi)` rather than representing `\pi i` (or even `2 \pi i`, which for some purposes would be more elegant) as an atomic quantity. .. function:: void ca_euler(ca_t res, ca_ctx_t ctx) Sets *res* to Euler's constant `\gamma`. This creates an element of the (transcendental?) number field `\mathbb{Q}(\gamma)`. .. function:: void ca_unknown(ca_t res, ca_ctx_t ctx) Sets *res* to the meta-value *Unknown*. .. function:: void ca_undefined(ca_t res, ca_ctx_t ctx) Sets *res* to *Undefined*. .. function:: void ca_uinf(ca_t res, ca_ctx_t ctx) Sets *res* to unsigned infinity `{\tilde \infty}`. .. function:: void ca_pos_inf(ca_t res, ca_ctx_t ctx) void ca_neg_inf(ca_t res, ca_ctx_t ctx) void ca_pos_i_inf(ca_t res, ca_ctx_t ctx) void ca_neg_i_inf(ca_t res, ca_ctx_t ctx) Sets *res* to the signed infinity `+\infty`, `-\infty`, `+i \infty` or `-i \infty`. Assignment and conversion ------------------------------------------------------------------------------- .. function:: void ca_set(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to a copy of *x*. .. function:: void ca_set_si(ca_t res, slong v, ca_ctx_t ctx) void ca_set_ui(ca_t res, ulong v, ca_ctx_t ctx) void ca_set_fmpz(ca_t res, const fmpz_t v, ca_ctx_t ctx) void ca_set_fmpq(ca_t res, const fmpq_t v, ca_ctx_t ctx) Sets *res* to the integer or rational number *v*. This creates a canonical representation of this number as an element of the trivial field `\mathbb{Q}`. .. function:: void ca_set_d(ca_t res, double x, ca_ctx_t ctx) void ca_set_d_d(ca_t res, double x, double y, ca_ctx_t ctx) Sets *res* to the value of *x*, or the complex value `x + yi`. NaN is interpreted as *Unknown* (not *Undefined*). .. function:: void ca_transfer(ca_t res, ca_ctx_t res_ctx, const ca_t src, ca_ctx_t src_ctx) Sets *res* to *src* where the corresponding context objects *res_ctx* and *src_ctx* may be different. This operation preserves the mathematical value represented by *src*, but may result in a different internal representation depending on the settings of the context objects. Conversion of algebraic numbers ------------------------------------------------------------------------------- .. function:: void ca_set_qqbar(ca_t res, const qqbar_t x, ca_ctx_t ctx) Sets *res* to the algebraic number *x*. If *x* is rational, *res* is set to the canonical representation as an element in the trivial field `\mathbb{Q}`. If *x* is irrational, this function always sets *res* to an element of a univariate number field `\mathbb{Q}(a)`. It will not, for example, identify `\sqrt{2} + \sqrt{3}` as an element of `\mathbb{Q}(\sqrt{2}, \sqrt{3})`. However, it may attempt to find a simpler number field than that generated by *x* itself. For example: * If *x* is quadratic, it will be expressed as an element of `\mathbb{Q}(\sqrt{N})` where *N* has no small repeated factors (obtained by performing a smooth factorization of the discriminant). * TODO: if possible, coerce *x* to a low-degree cyclotomic field. .. function:: int ca_get_fmpz(fmpz_t res, const ca_t x, ca_ctx_t ctx) int ca_get_fmpq(fmpq_t res, const ca_t x, ca_ctx_t ctx) int ca_get_qqbar(qqbar_t res, const ca_t x, ca_ctx_t ctx) Attempts to evaluate *x* to an explicit integer, rational or algebraic number. If successful, sets *res* to this number and returns 1. If unsuccessful, returns 0. The conversion certainly fails if *x* does not represent an integer, rational or algebraic number (respectively), but can also fail if *x* is too expensive to compute under the current evaluation limits. In particular, the evaluation will be aborted if an intermediate algebraic number (or more precisely, the resultant polynomial prior to factorization) exceeds ``CA_OPT_QQBAR_DEG_LIMIT`` or the coefficients exceed some multiple of ``CA_OPT_PREC_LIMIT``. Note that evaluation may hit those limits even if the minimal polynomial for *x* itself is small. The conversion can also fail if no algorithm has been implemented for the functions appearing in the construction of *x*. .. function:: int ca_can_evaluate_qqbar(const ca_t x, ca_ctx_t ctx) Checks if :func:`ca_get_qqbar` has a chance to succeed. In effect, this checks if all extension numbers are manifestly algebraic numbers (without doing any evaluation). Random generation ------------------------------------------------------------------------------- .. function:: void ca_randtest_rational(ca_t res, flint_rand_t state, slong bits, ca_ctx_t ctx) Sets *res* to a random rational number with numerator and denominator up to *bits* bits in size. .. function:: void ca_randtest(ca_t res, flint_rand_t state, slong depth, slong bits, ca_ctx_t ctx) Sets *res* to a random number generated by evaluating a random expression. The algorithm randomly selects between generating a "simple" number (a random rational number or quadratic field element with coefficients up to *bits* in size, or a random builtin constant), or if *depth* is nonzero, applying a random arithmetic operation or function to operands produced through recursive calls with *depth* - 1. The output is guaranteed to be a number, not a special value. .. function:: void ca_randtest_special(ca_t res, flint_rand_t state, slong depth, slong bits, ca_ctx_t ctx) Randomly generates either a special value or a number. .. function:: void ca_randtest_same_nf(ca_t res, flint_rand_t state, const ca_t x, slong bits, slong den_bits, ca_ctx_t ctx) Sets *res* to a random element in the same number field as *x*, with numerator coefficients up to *bits* in size and denominator up to *den_bits* in size. This function requires that *x* is an element of an absolute number field. Representation properties ------------------------------------------------------------------------------- The following functions deal with the representation of a :type:`ca_t` and hence can always be decided quickly and unambiguously. The return value for predicates is 0 for false and 1 for true. .. function:: int ca_equal_repr(const ca_t x, const ca_t y, ca_ctx_t ctx) Returns whether *x* and *y* have identical representation. For field elements, this checks if *x* and *y* belong to the same formal field (with generators having identical representation) and are represented by the same rational function within that field. For special values, this tests equality of the special values, with *Unknown* handled as if it were a value rather than a meta-value: that is, *Unknown* = *Unknown* gives 1, and *Unknown* = *y* gives 0 for any other kind of value *y*. If neither *x* nor *y* is *Unknown*, then representation equality implies that *x* and *y* describe to the same mathematical value, but if either operand is *Unknown*, the result is meaningless for mathematical comparison. .. function:: int ca_cmp_repr(const ca_t x, const ca_t y, ca_ctx_t ctx) Compares the representations of *x* and *y* in a canonical sort order, returning -1, 0 or 1. This only performs a lexicographic comparison of the representations of *x* and *y*; the return value does not say anything meaningful about the numbers represented by *x* and *y*. .. function:: ulong ca_hash_repr(const ca_t x, ca_ctx_t ctx) Hashes the representation of *x*. .. function:: int ca_is_unknown(const ca_t x, ca_ctx_t ctx) Returns whether *x* is Unknown. .. function:: int ca_is_special(const ca_t x, ca_ctx_t ctx) Returns whether *x* is a special value or metavalue (not a field element). .. function:: int ca_is_qq_elem(const ca_t x, ca_ctx_t ctx) Returns whether *x* is represented as an element of the rational field `\mathbb{Q}`. .. function:: int ca_is_qq_elem_zero(const ca_t x, ca_ctx_t ctx) int ca_is_qq_elem_one(const ca_t x, ca_ctx_t ctx) int ca_is_qq_elem_integer(const ca_t x, ca_ctx_t ctx) Returns whether *x* is represented as the element 0, 1 or any integer in the rational field `\mathbb{Q}`. .. function:: int ca_is_nf_elem(const ca_t x, ca_ctx_t ctx) Returns whether *x* is represented as an element of a univariate algebraic number field `\mathbb{Q}(a)`. .. function:: int ca_is_cyclotomic_nf_elem(slong * p, ulong * q, const ca_t x, ca_ctx_t ctx) Returns whether *x* is represented as an element of a univariate cyclotomic field, i.e. `\mathbb{Q}(a)` where *a* is a root of unity. If *p* and *q* are not *NULL* and *x* is represented as an element of a cyclotomic field, this also sets *p* and *q* to the minimal integers with `0 \le p < q` such that the generating root of unity is `a = e^{2 \pi i p / q}`. Note that the answer 0 does not prove that *x* is not a cyclotomic number, and the order *q* is also not necessarily the generator of the *smallest* cyclotomic field containing *x*. For the purposes of this function, only nontrivial cyclotomic fields count; the return value is 0 if *x* is represented as a rational number. .. function:: int ca_is_generic_elem(const ca_t x, ca_ctx_t ctx) Returns whether *x* is represented as a generic field element; i.e. it is not a special value, not represented as an element of the rational field, and not represented as an element of a univariate algebraic number field. Value predicates ------------------------------------------------------------------------------- The following predicates check a mathematical property which might not be effectively decidable. The result is a :type:`truth_t` to allow representing an unknown outcome. .. function:: truth_t ca_check_is_number(const ca_t x, ca_ctx_t ctx) Tests if *x* is a number. The result is ``T_TRUE`` is *x* is a field element (and hence a complex number), ``T_FALSE`` if *x* is an infinity or *Undefined*, and ``T_UNKNOWN`` if *x* is *Unknown*. .. function:: truth_t ca_check_is_zero(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_one(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_neg_one(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_i(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_neg_i(const ca_t x, ca_ctx_t ctx) Tests if *x* is equal to the number `0`, `1`, `-1`, `i`, or `-i`. .. function:: truth_t ca_check_is_algebraic(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_rational(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_integer(const ca_t x, ca_ctx_t ctx) Tests if *x* is respectively an algebraic number, a rational number, or an integer. .. function:: truth_t ca_check_is_real(const ca_t x, ca_ctx_t ctx) Tests if *x* is a real number. Warning: this returns ``T_FALSE`` if *x* is an infinity with real sign. .. function:: truth_t ca_check_is_negative_real(const ca_t x, ca_ctx_t ctx) Tests if *x* is a negative real number. Warning: this returns ``T_FALSE`` if *x* is negative infinity. .. function:: truth_t ca_check_is_imaginary(const ca_t x, ca_ctx_t ctx) Tests if *x* is an imaginary number. Warning: this returns ``T_FALSE`` if *x* is an infinity with imaginary sign. .. function:: truth_t ca_check_is_undefined(const ca_t x, ca_ctx_t ctx) Tests if *x* is the special value *Undefined*. .. function:: truth_t ca_check_is_infinity(const ca_t x, ca_ctx_t ctx) Tests if *x* is any infinity (unsigned or signed). .. function:: truth_t ca_check_is_uinf(const ca_t x, ca_ctx_t ctx) Tests if *x* is unsigned infinity `{\tilde \infty}`. .. function:: truth_t ca_check_is_signed_inf(const ca_t x, ca_ctx_t ctx) Tests if *x* is any signed infinity. .. function:: truth_t ca_check_is_pos_inf(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_neg_inf(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_pos_i_inf(const ca_t x, ca_ctx_t ctx) truth_t ca_check_is_neg_i_inf(const ca_t x, ca_ctx_t ctx) Tests if *x* is equal to the signed infinity `+\infty`, `-\infty`, `+i \infty`, `-i \infty`, respectively. Comparisons ------------------------------------------------------------------------------- .. function:: truth_t ca_check_equal(const ca_t x, const ca_t y, ca_ctx_t ctx) Tests `x = y` as a mathematical equality. The result is ``T_UNKNOWN`` if either operand is *Unknown*. The result may also be ``T_UNKNOWN`` if *x* and *y* are numerically indistinguishable and cannot be proved equal or unequal by an exact computation. .. function:: truth_t ca_check_lt(const ca_t x, const ca_t y, ca_ctx_t ctx) truth_t ca_check_le(const ca_t x, const ca_t y, ca_ctx_t ctx) truth_t ca_check_gt(const ca_t x, const ca_t y, ca_ctx_t ctx) truth_t ca_check_ge(const ca_t x, const ca_t y, ca_ctx_t ctx) Compares *x* and *y*, implementing the respective operations `x < y`, `x \le y`, `x > y`, `x \ge y`. Only real numbers and `-\infty` and `+\infty` are considered comparable. The result is ``T_FALSE`` (not ``T_UNKNOWN``) if either operand is not comparable (being a nonreal complex number, unsigned infinity, or undefined). Field structure operations ------------------------------------------------------------------------------- .. function:: void ca_merge_fields(ca_t resx, ca_t resy, const ca_t x, const ca_t y, ca_ctx_t ctx) Sets *resx* and *resy* to copies of *x* and *y* coerced to a common field. Both *x* and *y* must be field elements (not special values). In the present implementation, this simply merges the lists of generators, avoiding duplication. In the future, it will be able to eliminate generators satisfying algebraic relations. .. function:: void ca_condense_field(ca_t res, ca_ctx_t ctx) Attempts to demote the value of *res* to a trivial subfield of its current field by removing unused generators. In particular, this demotes any obviously rational value to the trivial field `\mathbb{Q}`. This function is applied automatically in most operations (arithmetic operations, etc.). .. function:: ca_ext_ptr ca_is_gen_as_ext(const ca_t x, ca_ctx_t ctx) If *x* is a generator of its formal field, `x = a_k \in \mathbb{Q}(a_1,\ldots,a_n)`, returns a pointer to the extension number defining `a_k`. If *x* is not a generator, returns *NULL*. Arithmetic ------------------------------------------------------------------------------- .. function:: void ca_neg(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the negation of *x*. For numbers, this operation amounts to a direct negation within the formal field. For a signed infinity `c \infty`, negation gives `(-c) \infty`; all other special values are unchanged. .. function:: void ca_add_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) void ca_add_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) void ca_add_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) void ca_add_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) void ca_add(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) Sets *res* to the sum of *x* and *y*. For special values, the following rules apply (`c \infty` denotes a signed infinity, `|c| = 1`): * `c \infty + d \infty = c \infty` if `c = d` * `c \infty + d \infty = \text{Undefined}` if `c \ne d` * `\tilde \infty + c \infty = \tilde \infty + \tilde \infty = \text{Undefined}` * `c \infty + z = c \infty` if `z \in \mathbb{C}` * `\tilde \infty + z = \tilde \infty` if `z \in \mathbb{C}` * `z + \text{Undefined} = \text{Undefined}` for any value *z* (including *Unknown*) In any other case involving special values, or if the specific case cannot be distinguished, the result is *Unknown*. .. function:: void ca_sub_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) void ca_sub_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) void ca_sub_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) void ca_sub_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) void ca_fmpq_sub(ca_t res, const fmpq_t x, const ca_t y, ca_ctx_t ctx) void ca_fmpz_sub(ca_t res, const fmpz_t x, const ca_t y, ca_ctx_t ctx) void ca_ui_sub(ca_t res, ulong x, const ca_t y, ca_ctx_t ctx) void ca_si_sub(ca_t res, slong x, const ca_t y, ca_ctx_t ctx) void ca_sub(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) Sets *res* to the difference of *x* and *y*. This is equivalent to computing `x + (-y)`. .. function:: void ca_mul_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) void ca_mul_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) void ca_mul_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) void ca_mul_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) void ca_mul(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) Sets *res* to the product of *x* and *y*. For special values, the following rules apply (`c \infty` denotes a signed infinity, `|c| = 1`): * `c \infty \cdot d \infty = c d \infty` * `c \infty \cdot \tilde \infty = \tilde \infty` * `\tilde \infty \cdot \tilde \infty = \tilde \infty` * `c \infty \cdot z = \operatorname{sgn}(z) c \infty` if `z \in \mathbb{C} \setminus \{0\}` * `c \infty \cdot 0 = \text{Undefined}` * `\tilde \infty \cdot 0 = \text{Undefined}` * `z \cdot \text{Undefined} = \text{Undefined}` for any value *z* (including *Unknown*) In any other case involving special values, or if the specific case cannot be distinguished, the result is *Unknown*. .. function:: void ca_inv(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the multiplicative inverse of *x*. In a univariate algebraic number field, this always produces a rational denominator, but the denominator might not be rationalized in a multivariate field. For special values and zero, the following rules apply: * `1 / (c \infty) = 1 / \tilde \infty = 0` * `1 / 0 = \tilde \infty` * `1 / \text{Undefined} = \text{Undefined}` * `1 / \text{Unknown} = \text{Unknown}` If it cannot be determined whether *x* is zero or nonzero, the result is *Unknown*. .. function:: void ca_fmpq_div(ca_t res, const fmpq_t x, const ca_t y, ca_ctx_t ctx) void ca_fmpz_div(ca_t res, const fmpz_t x, const ca_t y, ca_ctx_t ctx) void ca_ui_div(ca_t res, ulong x, const ca_t y, ca_ctx_t ctx) void ca_si_div(ca_t res, slong x, const ca_t y, ca_ctx_t ctx) void ca_div_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) void ca_div_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) void ca_div_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) void ca_div_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) void ca_div(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) Sets *res* to the quotient of *x* and *y*. This is equivalent to computing `x \cdot (1 / y)`. For special values and division by zero, this implies the following rules (`c \infty` denotes a signed infinity, `|c| = 1`): * `(c \infty) / (d \infty) = (c \infty) / \tilde \infty = \tilde \infty / (c \infty) = \tilde \infty / \tilde \infty = \text{Undefined}` * `c \infty / z = (c / \operatorname{sgn}(z)) \infty` if `z \in \mathbb{C} \setminus \{0\}` * `c \infty / 0 = \tilde \infty / 0 = \tilde \infty` * `z / (c \infty) = z / \tilde \infty = 0` if `z \in \mathbb{C}` * `z / 0 = \tilde \infty` if `z \in \mathbb{C} \setminus \{0\}` * `0 / 0 = \text{Undefined}` * `z / \text{Undefined} = \text{Undefined}` for any value *z* (including *Unknown*) * `\text{Undefined} / z = \text{Undefined}` for any value *z* (including *Unknown*) In any other case involving special values, or if the specific case cannot be distinguished, the result is *Unknown*. .. function:: void ca_dot(ca_t res, const ca_t initial, int subtract, ca_srcptr x, slong xstep, ca_srcptr y, slong ystep, slong len, ca_ctx_t ctx) Computes the dot product of the vectors *x* and *y*, setting *res* to `s + (-1)^{subtract} \sum_{i=0}^{len-1} x_i y_i`. The initial term *s* is optional and can be omitted by passing *NULL* (equivalently, `s = 0`). The parameter *subtract* must be 0 or 1. The length *len* is allowed to be negative, which is equivalent to a length of zero. The parameters *xstep* or *ystep* specify a step length for traversing subsequences of the vectors *x* and *y*; either can be negative to step in the reverse direction starting from the initial pointer. Aliasing is allowed between *res* and *s* but not between *res* and the entries of *x* and *y*. .. function:: void ca_fmpz_poly_evaluate(ca_t res, const fmpz_poly_t poly, const ca_t x, ca_ctx_t ctx) void ca_fmpq_poly_evaluate(ca_t res, const fmpq_poly_t poly, const ca_t x, ca_ctx_t ctx) Sets *res* to the polynomial *poly* evaluated at *x*. .. function:: void ca_fmpz_mpoly_evaluate_horner(ca_t res, const fmpz_mpoly_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) void ca_fmpz_mpoly_evaluate_iter(ca_t res, const fmpz_mpoly_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) void ca_fmpz_mpoly_evaluate(ca_t res, const fmpz_mpoly_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) Sets *res* to the multivariate polynomial *f* evaluated at the vector of arguments *x*. .. function:: void ca_fmpz_mpoly_q_evaluate(ca_t res, const fmpz_mpoly_q_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) Sets *res* to the multivariate rational function *f* evaluated at the vector of arguments *x*. .. function:: void ca_fmpz_mpoly_q_evaluate_no_division_by_zero(ca_t res, const fmpz_mpoly_q_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) void ca_inv_no_division_by_zero(ca_t res, const ca_t x, ca_ctx_t ctx) These functions behave like the normal arithmetic functions, but assume (and do not check) that division by zero cannot occur. Division by zero will result in undefined behavior. Powers and roots ------------------------------------------------------------------------------- .. function:: void ca_sqr(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the square of *x*. .. function:: void ca_pow_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) void ca_pow_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) void ca_pow_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) void ca_pow_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) void ca_pow(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) Sets *res* to *x* raised to the power *y*. Handling of special values is not yet implemented. .. function:: void ca_pow_si_arithmetic(ca_t res, const ca_t x, slong n, ca_ctx_t ctx) Sets *res* to *x* raised to the power *n*. Whereas :func:`ca_pow`, :func:`ca_pow_si` etc. may create `x^n` as an extension number if *n* is large, this function always perform the exponentiation using field arithmetic. .. function:: void ca_sqrt_inert(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_sqrt_nofactor(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_sqrt_factor(ca_t res, const ca_t x, ulong flags, ca_ctx_t ctx) void ca_sqrt(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the principal square root of *x*. For special values, the following definitions apply: * `\sqrt{c \infty} = \sqrt{c} \infty` * `\sqrt{\tilde \infty} = \tilde \infty`. * Both *Undefined* and *Unknown* map to themselves. The *inert* version outputs the generator in the formal field `\mathbb{Q}(\sqrt{x})` without simplifying. The *factor* version writes `x = A^2 B` in `K` where `K` is the field of *x*, and outputs `A \sqrt{B}` or `-A \sqrt{B}` (whichever gives the correct sign) as an element of `K(\sqrt{B})` or some subfield thereof. This factorization is only a heuristic and is not guaranteed to make `B` minimal. Factorization options can be passed through to *flags*: see :func:`ca_factor` for details. The *nofactor* version will not perform a general factorization, but may still perform other simplifications. It may in particular attempt to simplify `\sqrt{x}` to a single element in `\overline{\mathbb{Q}}`. .. function:: void ca_sqrt_ui(ca_t res, ulong n, ca_ctx_t ctx) Sets *res* to the principal square root of *n*. Complex parts ------------------------------------------------------------------------------- .. function:: void ca_abs(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the absolute value of *x*. For special values, the following definitions apply: * `|c \infty| = |\tilde \infty| = +\infty`. * Both *Undefined* and *Unknown* map to themselves. This function will attempt to simplify its argument through an exact computation. It may in particular attempt to simplify `|x|` to a single element in `\overline{\mathbb{Q}}`. In the generic case, this function outputs an element of the formal field `\mathbb{Q}(|x|)`. .. function:: void ca_sgn(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the sign of *x*, defined by .. math:: \operatorname{sgn}(x) = \begin{cases} 0 & x = 0 \\ \frac{x}{|x|} & x \ne 0 \end{cases} for numbers. For special values, the following definitions apply: * `\operatorname{sgn}(c \infty) = c`. * `\operatorname{sgn}(\tilde \infty) = \operatorname{Undefined}`. * Both *Undefined* and *Unknown* map to themselves. This function will attempt to simplify its argument through an exact computation. It may in particular attempt to simplify `\operatorname{sgn}(x)` to a single element in `\overline{\mathbb{Q}}`. In the generic case, this function outputs an element of the formal field `\mathbb{Q}(\operatorname{sgn}(x))`. .. function:: void ca_csgn(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the extension of the real sign function taking the value 1 for *z* strictly in the right half plane, -1 for *z* strictly in the left half plane, and the sign of the imaginary part when *z* is on the imaginary axis. Equivalently, `\operatorname{csgn}(z) = z / \sqrt{z^2}` except that the value is 0 when *z* is exactly zero. This function gives *Undefined* for unsigned infinity and `\operatorname{csgn}(\operatorname{sgn}(c \infty)) = \operatorname{csgn}(c)` for signed infinities. .. function:: void ca_arg(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the complex argument (phase) of *x*, normalized to the range `(-\pi, +\pi]`. The argument of 0 is defined as 0. For special values, the following definitions apply: * `\operatorname{arg}(c \infty) = \operatorname{arg}(c)`. * `\operatorname{arg}(\tilde \infty) = \operatorname{Undefined}`. * Both *Undefined* and *Unknown* map to themselves. .. function:: void ca_re(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the real part of *x*. The result is *Undefined* if *x* is any infinity (including a real infinity). .. function:: void ca_im(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the imaginary part of *x*. The result is *Undefined* if *x* is any infinity (including an imaginary infinity). .. function:: void ca_conj_deep(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_conj_shallow(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_conj(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the complex conjugate of *x*. The *shallow* version creates a new extension element `\overline{x}` unless *x* can be trivially conjugated in-place in the existing field. The *deep* version recursively conjugates the extension numbers in the field of *x*. .. function:: void ca_floor(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the floor function of *x*. The result is *Undefined* if *x* is any infinity (including a real infinity). For complex numbers, this is presently defined to take the floor of the real part. .. function:: void ca_ceil(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the ceiling function of *x*. The result is *Undefined* if *x* is any infinity (including a real infinity). For complex numbers, this is presently defined to take the ceiling of the real part. Exponentials and logarithms ------------------------------------------------------------------------------- .. function:: void ca_exp(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the exponential function of *x*. For special values, the following definitions apply: * `e^{+\infty} = +\infty` * `e^{c \infty} = \tilde \infty` if `0 < \operatorname{Re}(c) < 1`. * `e^{c \infty} = 0` if `\operatorname{Re}(c) < 0`. * `e^{c \infty} = \text{Undefined}` if `\operatorname{Re}(c) = 0`. * `e^{\tilde \infty} = \text{Undefined}`. * Both *Undefined* and *Unknown* map to themselves. The following symbolic simplifications are performed automatically: * `e^0 = 1` * `e^{\log(z)} = z` * `e^{(p/q) \log(z)} = z^{p/q}` (for rational `p/q`) * `e^{(p/q) \pi i}` = algebraic root of unity (for small rational `p/q`) In the generic case, this function outputs an element of the formal field `\mathbb{Q}(e^x)`. .. function:: void ca_log(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the natural logarithm of *x*. For special values and at the origin, the following definitions apply: * For any infinity, `\log(c\infty) = \log(\tilde \infty) = +\infty`. * `\log(0) = -\infty`. The result is *Unknown* if deciding `x = 0` fails. * Both *Undefined* and *Unknown* map to themselves. The following symbolic simplifications are performed automatically: * `\log(1) = 0` * `\log\left(e^z\right) = z + 2 \pi i k` * `\log\left(\sqrt{z}\right) = \tfrac{1}{2} \log(z) + 2 \pi i k` * `\log\left(z^a\right) = a \log(z) + 2 \pi i k` * `\log(x) = \log(-x) + \pi i` for negative real *x* In the generic case, this function outputs an element of the formal field `\mathbb{Q}(\log(x))`. Trigonometric functions ------------------------------------------------------------------------------- .. function:: void ca_sin_cos_exponential(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) void ca_sin_cos_direct(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) void ca_sin_cos_tangent(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) void ca_sin_cos(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) Sets *res1* to the sine of *x* and *res2* to the cosine of *x*. Either *res1* or *res2* can be *NULL* to compute only the other function. Various representations are implemented: * The *exponential* version expresses the sine and cosine in terms of complex exponentials. Simple algebraic values will simplify to rational numbers or elements of cyclotomic fields. * The *direct* method expresses the sine and cosine in terms of the original functions (perhaps after applying some symmetry transformations, which may interchange sin and cos). Extremely simple algebraic values will automatically simplify to elements of real algebraic number fields. * The *tangent* version expresses the sine and cosine in terms of `\tan(x/2)`, perhaps after applying some symmetry transformations. Extremely simple algebraic values will automatically simplify to elements of real algebraic number fields. By default, the standard function uses the *exponential* representation as this typically works best for field arithmetic and simplifications, although it has the disadvantage of introducing complex numbers where real numbers would be sufficient. The behavior of the standard function can be changed using the :macro:`CA_OPT_TRIG_FORM` context setting. For special values, the following definitions apply: * `\sin(\pm i \infty) = \pm i \infty` * `\cos(\pm i \infty) = +\infty` * All other infinities give `\operatorname{Undefined}` .. function:: void ca_sin(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_cos(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the sine or cosine of *x*. These functions are shortcuts for :func:`ca_sin_cos`. .. function:: void ca_tan_sine_cosine(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_tan_exponential(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_tan_direct(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_tan(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the tangent of *x*. The *sine_cosine* version evaluates the tangent as a quotient of a sine and cosine, the *direct* version evaluates it directly as a tangent (possibly after transforming the variable), and the *exponential* version evaluates it in terms of complex exponentials. Simple algebraic values will automatically simplify to elements of trigonometric or cyclotomic number fields. By default, the standard function uses the *exponential* representation as this typically works best for field arithmetic and simplifications, although it has the disadvantage of introducing complex numbers where real numbers would be sufficient. The behavior of the standard function can be changed using the :macro:`CA_OPT_TRIG_FORM` context setting. For special values, the following definitions apply: * At poles, `\tan((n+\tfrac{1}{2}) \pi) = \tilde \infty` * `\tan(e^{i \theta} \infty) = +i, \quad 0 < \theta < \pi` * `\tan(e^{i \theta} \infty) = -i, \quad -\pi < \theta < 0` * `\tan(\pm \infty) = \tan(\tilde \infty) = \operatorname{Undefined}` .. function:: void ca_cot(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the cotangent *x*. This is equivalent to computing the reciprocal of the tangent. .. function:: void ca_atan_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_atan_direct(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_atan(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the inverse tangent of *x*. The *direct* version expresses the result as an inverse tangent (possibly after transforming the variable). The *logarithm* version expresses it in terms of complex logarithms. Simple algebraic inputs will automatically simplify to rational multiples of `\pi`. By default, the standard function uses the *logarithm* representation as this typically works best for field arithmetic and simplifications, although it has the disadvantage of introducing complex numbers where real numbers would be sufficient. The behavior of the standard function can be changed using the :macro:`CA_OPT_TRIG_FORM` context setting (exponential mode results in logarithmic forms). For special values, the following definitions apply: * `\operatorname{atan}(\pm i) = \pm i \infty` * `\operatorname{atan}(c \infty) = \operatorname{csgn}(c) \pi / 2` * `\operatorname{atan}(\tilde \infty) = \operatorname{Undefined}` .. function:: void ca_asin_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_acos_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_asin_direct(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_acos_direct(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_asin(ca_t res, const ca_t x, ca_ctx_t ctx) void ca_acos(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the inverse sine (respectively, cosine) of *x*. The *direct* version expresses the result as an inverse sine or cosine (possibly after transforming the variable). The *logarithm* version expresses it in terms of complex logarithms. Simple algebraic inputs will automatically simplify to rational multiples of `\pi`. By default, the standard function uses the *logarithm* representation as this typically works best for field arithmetic and simplifications, although it has the disadvantage of introducing complex numbers where real numbers would be sufficient. The behavior of the standard function can be changed using the :macro:`CA_OPT_TRIG_FORM` context setting (exponential mode results in logarithmic forms). The inverse cosine is presently implemented as `\operatorname{acos}(x) = \pi/2 - \operatorname{asin}(x)`. Special functions ------------------------------------------------------------------------------- .. function:: void ca_gamma(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the gamma function of *x*. .. function:: void ca_erf(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the error function of *x*. .. function:: void ca_erfc(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the complementary error function of *x*. .. function:: void ca_erfi(ca_t res, const ca_t x, ca_ctx_t ctx) Sets *res* to the imaginary error function of *x*. Numerical evaluation ------------------------------------------------------------------------------- .. function:: void ca_get_acb_raw(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx) Sets *res* to an enclosure of the numerical value of *x*. A working precision of *prec* bits is used internally for the evaluation, without adaptive refinement. If *x* is any special value, *res* is set to *acb_indeterminate*. .. function:: void ca_get_acb(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx) void ca_get_acb_accurate_parts(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx) Sets *res* to an enclosure of the numerical value of *x*. The working precision is increased adaptively to try to ensure *prec* accurate bits in the output. The *accurate_parts* version tries to ensure *prec* accurate bits for both the real and imaginary part separately. The refinement is stopped if the working precision exceeds ``CA_OPT_PREC_LIMIT`` (or twice the initial precision, if this is larger). The user may call *acb_rel_accuracy_bits* to check is the calculation was successful. The output is not rounded down to *prec* bits (to avoid unnecessary double rounding); the user may call *acb_set_round* when rounding is desired. .. function:: char * ca_get_decimal_str(const ca_t x, slong digits, ulong flags, ca_ctx_t ctx) Returns a decimal approximation of *x* with precision up to *digits*. The output is guaranteed to be correct within 1 ulp in the returned digits, but the number of returned digits may be smaller than *digits* if the numerical evaluation does not succeed. If *flags* is set to 1, attempts to achieve full accuracy for both the real and imaginary parts separately. If *x* is not finite or a finite enclosure cannot be produced, returns the string "?". The user should free the returned string with ``flint_free``. Rewriting and simplification ------------------------------------------------------------------------------- .. function:: void ca_rewrite_complex_normal_form(ca_t res, const ca_t x, int deep, ca_ctx_t ctx) Sets *res* to *x* rewritten using standardizing transformations over the complex numbers: * Elementary functions are rewritten in terms of (complex) exponentials, roots and logarithms * Complex parts are rewritten using logarithms, square roots, and (deep) complex conjugates * Algebraic numbers are rewritten in terms of cyclotomic fields where applicable If *deep* is set, the rewriting is applied recursively to the tower of extension numbers; otherwise, the rewriting is only applied to the top-level extension numbers. The result is not a normal form in the strong sense (the same number can have many possible representations even after applying this transformation), but in practice this is a powerful heuristic for simplification. Factorization ------------------------------------------------------------------------------- .. type:: ca_factor_struct .. type:: ca_factor_t Represents a real or complex number in factored form `b_1^{e_1} b_2^{e_2} \cdots b_n^{e_n}` where `b_i` and `e_i` are :type:`ca_t` numbers (the exponents need not be integers). .. function:: void ca_factor_init(ca_factor_t fac, ca_ctx_t ctx) Initializes *fac* and sets it to the empty factorization (equivalent to the number 1). .. function:: void ca_factor_clear(ca_factor_t fac, ca_ctx_t ctx) Clears the factorization structure *fac*. .. function:: void ca_factor_one(ca_factor_t fac, ca_ctx_t ctx) Sets *fac* to the empty factorization (equivalent to the number 1). .. function:: void ca_factor_print(const ca_factor_t fac, ca_ctx_t ctx) Prints a description of *fac* to standard output. .. function:: void ca_factor_insert(ca_factor_t fac, const ca_t base, const ca_t exp, ca_ctx_t ctx) Inserts `b^e` into *fac* where *b* is given by *base* and *e* is given by *exp*. If a base element structurally identical to *base* already exists in *fac*, the corresponding exponent is incremented by *exp*; otherwise, this factor is appended. .. function:: void ca_factor_get_ca(ca_t res, const ca_factor_t fac, ca_ctx_t ctx) Expands *fac* back to a single :type:`ca_t` by evaluating the powers and multiplying out the result. .. function:: void ca_factor(ca_factor_t res, const ca_t x, ulong flags, ca_ctx_t ctx) Sets *res* to a factorization of *x* of the form `x = b_1^{e_1} b_2^{e_2} \cdots b_n^{e_n}`. Requires that *x* is not a special value. The type of factorization is controlled by *flags*, which can be set to a combination of constants in the following section. Factorization options ................................................................................ The following flags select the structural polynomial factorization to perform over formal fields `\mathbb{Q}(a_1,\ldots,a_n)`. Each flag in the list strictly encompasses the factorization power of the preceding flag, so it is unnecessary to pass more than one flag. .. macro:: CA_FACTOR_POLY_NONE No polynomial factorization at all. .. macro:: CA_FACTOR_POLY_CONTENT Only extract the rational content. .. macro:: CA_FACTOR_POLY_SQF Perform a squarefree factorization in addition to extracting the rational content. .. macro:: CA_FACTOR_POLY_FULL Perform a full multivariate polynomial factorization. The following flags select the factorization to perform over `\mathbb{Z}`. Integer factorization is applied if *x* is an element of `\mathbb{Q}`, and to the extracted rational content of polynomials. Each flag in the list strictly encompasses the factorization power of the preceding flag, so it is unnecessary to pass more than one flag. .. macro:: CA_FACTOR_ZZ_NONE No integer factorization at all. .. macro:: CA_FACTOR_ZZ_SMOOTH Perform a smooth factorization to extract small prime factors (heuristically up to ``CA_OPT_SMOOTH_LIMIT`` bits) in addition to identifying perfect powers. .. macro:: CA_FACTOR_ZZ_FULL Perform a complete integer factorization into prime numbers. This is prohibitively slow for general integers exceeding 70-80 digits. .. _context-options: Context options ------------------------------------------------------------------------------- The *options* member of a :type:`ca_ctx_t` object is an array of *slong* values controlling simplification behavior and various other settings. The values of the array at the following indices can be changed by the user (example: ``ctx->options[CA_OPT_PREC_LIMIT] = 65536``). It is recommended to set options controlling evaluation only at the time when a context object is created. Changing such options later should normally be harmless, but since the update will not apply retroactively to objects that have already been computed and cached, one might not see the expected behavior. Superficial options (printing) can be changed at any time. .. macro:: CA_OPT_VERBOSE Whether to print debug information. Default value: 0. .. macro:: CA_OPT_PRINT_FLAGS Printing style. See :ref:`ca-printing` for details. Default value: ``CA_PRINT_DEFAULT``. .. macro:: CA_OPT_MPOLY_ORD Monomial ordering to use for multivariate polynomials. Possible values are ``ORD_LEX``, ``ORD_DEGLEX`` and ``ORD_DEGREVLEX``. Default value: ``ORD_LEX``. This option must be set before doing any computations. .. macro:: CA_OPT_PREC_LIMIT Maximum precision to use internally for numerical evaluation with Arb, and in some cases for the magntiude of exact coefficients. This parameter affects the possibility to prove inequalities and find simplifications between related extension numbers. This is not a strict limit; some calculations may use higher precision when there is a good reason to do so. Default value: 4096. .. macro:: CA_OPT_QQBAR_DEG_LIMIT Maximum degree of :type:`qqbar_t` elements allowed internally during simplification of algebraic numbers. This limit may be exceeded when the user provides explicit :type:`qqbar_t` input of higher degree. Default value: 120. .. macro:: CA_OPT_LOW_PREC Numerical precision to use for fast checks (typically, before attempting more expensive operations). Default value: 64. .. macro:: CA_OPT_SMOOTH_LIMIT Size in bits for factors in smooth integer factorization. Default value: 32. .. macro:: CA_OPT_LLL_PREC Precision to use to find integer relations using LLL. Default value: 128. .. macro:: CA_OPT_POW_LIMIT Largest exponent to expand powers automatically. This only applies in multivariate and transcendental fields: in number fields, ``CA_OPT_PREC_LIMIT`` applies instead. Default value: 20. .. macro:: CA_OPT_USE_GROEBNER Boolean flag for whether to use Gröbner basis computation. This flag and the following limits affect the ability to prove multivariate identities. Default value: 1. .. macro:: CA_OPT_GROEBNER_LENGTH_LIMIT Maximum length of ideal basis allowed in Buchberger's algorithm. Default value: 100. .. macro:: CA_OPT_GROEBNER_POLY_LENGTH_LIMIT Maximum length of polynomials allowed in Buchberger's algorithm. Default value: 1000. .. macro:: CA_OPT_GROEBNER_POLY_BITS_LIMIT Maximum coefficient size in bits of polynomials allowed in Buchberger's algorithm. Default value: 10000. .. macro:: CA_OPT_VIETA_LIMIT Maximum degree *n* of algebraic numbers for which to add Vieta's formulas to the reduction ideal. This must be set relatively low since the number of terms in Vieta's formulas is `O(2^n)` and the resulting Gröbner basis computations can be expensive. Default value: 6. .. macro:: CA_OPT_TRIG_FORM Default representation of trigonometric functions. The following values are possible: .. macro:: CA_TRIG_DIRECT Use the direct functions (with some exceptions). .. macro:: CA_TRIG_EXPONENTIAL Use complex exponentials. .. macro:: CA_TRIG_SINE_COSINE Use sines and cosines. .. macro:: CA_TRIG_TANGENT Use tangents. Default value: ``CA_TRIG_EXPONENTIAL``. The *exponential* representation is currently used by default as typically works best for field arithmetic and simplifications, although it has the disadvantage of introducing complex numbers where real numbers would be sufficient. This may change in the future. Internal representation ------------------------------------------------------------------------------- .. macro:: CA_FMPQ(x) .. macro:: CA_FMPQ_NUMREF(x) .. macro:: CA_FMPQ_DENREF(x) Assuming that *x* holds an element of the trivial field `\mathbb{Q}`, this macro returns a pointer which can be used as an :type:`fmpq_t`, or respectively to the numerator or denominator as an :type:`fmpz_t`. .. macro:: CA_MPOLY_Q(x) Assuming that *x* holds a generic field element as data, this macro returns a pointer which can be used as an :type:`fmpz_mpoly_q_t`. .. macro:: CA_NF_ELEM(x) Assuming that *x* holds an Antic number field element as data, this macro returns a pointer which can be used as an :type:`nf_elem_t`. .. function:: void _ca_make_field_element(ca_t x, ca_field_srcptr new_index, ca_ctx_t ctx) Changes the internal representation of *x* to that of an element of the field with index *new_index* in the context object *ctx*. This may destroy the value of *x*. .. function:: void _ca_make_fmpq(ca_t x, ca_ctx_t ctx) Changes the internal representation of *x* to that of an element of the trivial field `\mathbb{Q}`. This may destroy the value of *x*. .. raw:: latex \newpage flint-3.1.3/doc/source/ca_ext.rst000066400000000000000000000175621461254215100167100ustar00rootroot00000000000000.. _ca-ext: **ca_ext.h** -- real and complex extension numbers =============================================================================== A :type:`ca_ext_t` represents a fixed real or complex number *a*. The content of a :type:`ca_ext_t` can be one of the following: * An algebraic constant represented in canonical form by a :type:`qqbar_t` instance (example: `i`, represented as the root of `x^2+1` with positive imaginary part). * A constant of the form `f(x_1, \ldots, x_n)` where *f* is a builtin symbolic function and `x_1, \ldots, x_n` are given :type:`ca_t` instances. * A builtin symbolic constant such as `\pi`. (This is just a special case of the above with a zero-length argument list.) * (Not implemented): a user-defined constant or function defined by suppling a function pointer for Arb numerical evaluation to specified precision. The :type:`ca_ext_t` structure is heavy-weight object, not just meant to act as a node in a symbolic expression. It will cache various data to support repeated computation with this particular number, including its numerical enclosure and number field data in the case of algebraic numbers. Extension numbers are used internally by the :type:`ca_t` type to define the embeddings `\mathbb{Q}(a) \to \mathbb{C}` of formal fields. The user does not normally need to create :type:`ca_ext_t` instances directly; the intended way for the user to work with the extension number *a* is to create a :type:`ca_t` representing the field element `1 \cdot a`. The underlying :type:`ca_ext_t` may be accessed to determine symbolic and numerical properties of this number. Since extension numbers may depend recursively on nontrivial fields for function arguments, :type:`ca_ext_t` operations require a :type:`ca_ctx_t` context object. Type and macros ------------------------------------------------------------------------------- For all types, a *type_t* is defined as an array of length one of type *type_struct*, permitting a *type_t* to be passed by reference. .. type:: ca_ext_struct .. type:: ca_ext_t An extension number object contains a header, a hash value, data (a :type:`qqbar_t` instance and an Antic :type:`nf_t` in the case of algebraic numbers, and a pointer to arguments in the case of a symbolic function), and a cached :type:`acb_t` enclosure (in the case of a :type:`qqbar_t`, the enclosure internal to that structure is used). .. type:: ca_ext_ptr Alias for ``ca_ext_struct *``. .. type:: ca_ext_srcptr Alias for ``const ca_ext_struct *``. .. macro:: CA_EXT_HEAD(x) Accesses the head (a :type:`calcium_func_code`) of *x*. This is *CA_QQBar* if *x* represents an algebraic constant in canonical form, and *CA_Exp*, *CA_Pi*, etc. for symbolic functions and constants. .. macro:: CA_EXT_HASH(x) Accesses the hash value of *x*. .. macro:: CA_EXT_QQBAR(x) Assuming that *x* represents an algebraic constant in canonical form, accesses this :type:`qqbar_t` object. .. macro:: CA_EXT_QQBAR_NF(x) Assuming that *x* represents an algebraic constant in canonical form, accesses the corresponding Antic number field :type:`nf_t` object. .. macro:: CA_EXT_FUNC_ARGS(x) Assuming that *x* represents a symbolic constant or function, accesses the argument list (as a :type:`ca_ptr`). .. macro:: CA_EXT_FUNC_NARGS(x) Assuming that *x* represents a symbolic constant or function, accesses the number of function arguments. .. macro:: CA_EXT_FUNC_ENCLOSURE(x) Assuming that *x* represents a symbolic constant or function, accesses the cached :type:`acb_t` numerical enclosure. .. macro:: CA_EXT_FUNC_PREC(x) Assuming that *x* represents a symbolic constant or function, accesses the working precision of the cached numerical enclosure. Memory management ------------------------------------------------------------------------------- .. function:: void ca_ext_init_qqbar(ca_ext_t res, const qqbar_t x, ca_ctx_t ctx) Initializes *res* and sets it to the algebraic constant *x*. .. function:: void ca_ext_init_const(ca_ext_t res, calcium_func_code func, ca_ctx_t ctx) Initializes *res* and sets it to the constant defined by *func* (example: *func* = *CA_Pi* for `x = \pi`). .. function:: void ca_ext_init_fx(ca_ext_t res, calcium_func_code func, const ca_t x, ca_ctx_t ctx) Initializes *res* and sets it to the univariate function value `f(x)` where *f* is defined by *func* (example: *func* = *CA_Exp* for `e^x`). .. function:: void ca_ext_init_fxy(ca_ext_t res, calcium_func_code func, const ca_t x, const ca_t y, ca_ctx_t ctx) Initializes *res* and sets it to the bivariate function value `f(x, y)` where *f* is defined by *func* (example: *func* = *CA_Pow* for `x^y`). .. function:: void ca_ext_init_fxn(ca_ext_t res, calcium_func_code func, ca_srcptr x, slong nargs, ca_ctx_t ctx) Initializes *res* and sets it to the multivariate function value `f(x_1, \ldots, x_n)` where *f* is defined by *func* and *n* is given by *nargs*. .. function:: void ca_ext_init_set(ca_ext_t res, const ca_ext_t x, ca_ctx_t ctx) Initializes *res* and sets it to a copy of *x*. .. function:: void ca_ext_clear(ca_ext_t res, ca_ctx_t ctx) Clears *res*. Structure ------------------------------------------------------------------------------- .. function:: slong ca_ext_nargs(const ca_ext_t x, ca_ctx_t ctx) Returns the number of function arguments of *x*. The return value is 0 for any algebraic constant and for any built-in symbolic constant such as `\pi`. .. function:: void ca_ext_get_arg(ca_t res, const ca_ext_t x, slong i, ca_ctx_t ctx) Sets *res* to argument *i* (indexed from zero) of *x*. This calls *flint_abort* if *i* is out of range. .. function:: ulong ca_ext_hash(const ca_ext_t x, ca_ctx_t ctx) Returns a hash of the structural representation of *x*. .. function:: int ca_ext_equal_repr(const ca_ext_t x, const ca_ext_t y, ca_ctx_t ctx) Tests *x* and *y* for structural equality, returning 0 (false) or 1 (true). .. function:: int ca_ext_cmp_repr(const ca_ext_t x, const ca_ext_t y, ca_ctx_t ctx) Compares the representations of *x* and *y* in a canonical sort order, returning -1, 0 or 1. This only performs a structural comparison of the symbolic representations; the return value does not say anything meaningful about the numbers represented by *x* and *y*. Input and output ------------------------------------------------------------------------------- .. function:: void ca_ext_print(const ca_ext_t x, ca_ctx_t ctx) Prints a description of *x* to standard output. Numerical evaluation ------------------------------------------------------------------------------- .. function:: void ca_ext_get_acb_raw(acb_t res, ca_ext_t x, slong prec, ca_ctx_t ctx) Sets *res* to an enclosure of the numerical value of *x*. A working precision of *prec* bits is used for the evaluation, without adaptive refinement. Cache ------------------------------------------------------------------------------- .. type:: ca_ext_cache_struct .. type:: ca_ext_cache_t Represents a set of structurally distinct :type:`ca_ext_t` instances. This object contains an array of pointers to individual heap-allocated :type:`ca_ext_struct` objects as well as a hash table for quick lookup. .. function:: void ca_ext_cache_init(ca_ext_cache_t cache, ca_ctx_t ctx) Initializes *cache* for use. .. function:: void ca_ext_cache_clear(ca_ext_cache_t cache, ca_ctx_t ctx) Clears *cache*, freeing the memory allocated internally. .. function:: ca_ext_ptr ca_ext_cache_insert(ca_ext_cache_t cache, const ca_ext_t x, ca_ctx_t ctx) Adds *x* to *cache* without duplication. If a structurally identical instance already exists in *cache*, a pointer to that instance is returned. Otherwise, a copy of *x* is inserted into *cache* and a pointer to that new instance is returned. .. raw:: latex \newpage flint-3.1.3/doc/source/ca_field.rst000066400000000000000000000174571461254215100171760ustar00rootroot00000000000000.. _ca-field: **ca_field.h** -- extension fields =============================================================================== A :type:`ca_field_t` represents the parent field `K = \mathbb{Q}(a_1,\ldots,a_n)` of a :type:`ca_t` element. A :type:`ca_field_t` contains a list of pointers to :type:`ca_ext_t` objects as well as a reduction ideal. The user does not normally need to create :type:`ca_field_t` objects manually: a :type:`ca_ctx_t` context object manages a cache of fields automatically. Internally, three types of field representation are used: * The trivial field `\mathbb{Q}`. * An Antic number field `\mathbb{Q}(a)` where *a* is defined by a :type:`qqbar_t` * A generic field `\mathbb{Q}(a_1,\ldots,a_n)` where `n \ge 1`, and `a_1` is not defined by a :type:`qqbar_t` if `n = 1`. The field type mainly affects the internal storage of the field elements; the distinction is mostly transparent to the external interface. Type and macros ------------------------------------------------------------------------------- For all types, a *type_t* is defined as an array of length one of type *type_struct*, permitting a *type_t* to be passed by reference. .. type:: ca_field_struct .. type:: ca_field_t Represents a formal field. .. type:: ca_field_ptr Alias for ``ca_field_struct *``. .. type:: ca_field_srcptr Alias for ``const ca_field_struct *``. .. macro:: CA_FIELD_LENGTH(K) Accesses the number *n* of extension numbers of *K*. This is 0 if `K = \mathbb{Q}`. .. macro:: CA_FIELD_EXT(K) Accesses the array of extension numbers as a :type:`ca_ext_ptr`. .. macro:: CA_FIELD_EXT_ELEM(K, i) Accesses the extension number at position *i* (indexed from zero) as a :type:`ca_ext_t`. .. macro:: CA_FIELD_HASH(K) Accesses the hash value of *K*. .. macro:: CA_FIELD_IS_QQ(K) Returns whether *K* is the trivial field `\mathbb{Q}`. .. macro:: CA_FIELD_IS_NF(K) Returns whether *K* represents an Antic number field `K = \mathbb{Q}(a)` where *a* is represented by a :type:`qqbar_t`. .. macro:: CA_FIELD_IS_GENERIC(K) Returns whether *K* represents a generic field. .. macro:: CA_FIELD_NF(K) Assuming that *K* represents an Antic number field `K = \mathbb{Q}(a)`, accesses the :type:`nf_t` object representing this field. .. macro:: CA_FIELD_NF_QQBAR(K) Assuming that *K* represents an Antic number field `K = \mathbb{Q}(a)`, accesses the :type:`qqbar_t` object representing *a*. .. macro:: CA_FIELD_IDEAL(K) Assuming that *K* represents a multivariate field, accesses the reduction ideal as a :type:`fmpz_mpoly_t` array. .. macro:: CA_FIELD_IDEAL_ELEM(K, i) Assuming that *K* represents a multivariate field, accesses element *i* (indexed from zero) of the reduction ideal as a :type:`fmpz_mpoly_t`. .. macro:: CA_FIELD_IDEAL_LENGTH(K) Assuming that *K* represents a multivariate field, accesses the number of polynomials in the reduction ideal. .. macro:: CA_FIELD_MCTX(K, ctx) Assuming that *K* represents a multivariate field, accesses the :type:`fmpz_mpoly_ctx_t` context object for multivariate polynomial arithmetic on the internal representation of elements in this field. Memory management ------------------------------------------------------------------------------- .. function:: void ca_field_init_qq(ca_field_t K, ca_ctx_t ctx) Initializes *K* to represent the trivial field `\mathbb{Q}`. .. function:: void ca_field_init_nf(ca_field_t K, const qqbar_t x, ca_ctx_t ctx) Initializes *K* to represent the algebraic number field `\mathbb{Q}(x)`. .. function:: void ca_field_init_const(ca_field_t K, calcium_func_code func, ca_ctx_t ctx) Initializes *K* to represent the field `\mathbb{Q}(x)` where *x* is a builtin constant defined by *func* (example: *func* = *CA_Pi* for `x = \pi`). .. function:: void ca_field_init_fx(ca_field_t K, calcium_func_code func, const ca_t x, ca_ctx_t ctx) Initializes *K* to represent the field `\mathbb{Q}(a)` where `a = f(x)`, given a number *x* and a builtin univariate function *func* (example: *func* = *CA_Exp* for `e^x`). .. function:: void ca_field_init_fxy(ca_field_t K, calcium_func_code func, const ca_t x, const ca_t y, ca_ctx_t ctx) Initializes *K* to represent the field `\mathbb{Q}(a,b)` where `a = f(x, y)`. .. function:: void ca_field_init_multi(ca_field_t K, slong len, ca_ctx_t ctx) Initializes *K* to represent a multivariate field `\mathbb{Q}(a_1, \ldots, a_n)` in *n* extension numbers. The extension numbers must subsequently be assigned one by one using :func:`ca_field_set_ext`. .. function:: void ca_field_set_ext(ca_field_t K, slong i, ca_ext_srcptr x_index, ca_ctx_t ctx) Sets the extension number at position *i* (here indexed from 0) of *K* to the generator of the field with index *x_index* in *ctx*. (It is assumed that the generating field is a univariate field.) This only inserts a shallow reference: the field at index *x_index* must be kept alive until *K* has been cleared. .. function:: void ca_field_clear(ca_field_t K, ca_ctx_t ctx) Clears the field *K*. This does not clear the individual extension numbers, which are only held as references. Input and output ------------------------------------------------------------------------------- .. function:: void ca_field_print(const ca_field_t K, ca_ctx_t ctx) Prints a description of the field *K* to standard output. Ideal ------------------------------------------------------------------------------- .. function:: void ca_field_build_ideal(ca_field_t K, ca_ctx_t ctx) Given *K* with assigned extension numbers, builds the reduction ideal in-place. .. function:: void ca_field_build_ideal_erf(ca_field_t K, ca_ctx_t ctx) Builds relations for error functions present among the extension numbers in *K*. This heuristic adds relations that are consequences of the functional equations `\operatorname{erf}(x) = -\operatorname{erf}(-x)`, `\operatorname{erfc}(x) = 1-\operatorname{erf}(x)`, `\operatorname{erfi}(x) = -i\operatorname{erf}(ix)`. Structure operations ------------------------------------------------------------------------------- .. function:: int ca_field_cmp(const ca_field_t K1, const ca_field_t K2, ca_ctx_t ctx) Compares the field objects *K1* and *K2* in a canonical sort order, returning -1, 0 or 1. This only performs a lexicographic comparison of the representations of *K1* and *K2*; the return value does not say anything meaningful about the relative structures of *K1* and *K2* as mathematical fields. Cache ------------------------------------------------------------------------------- .. type:: ca_field_cache_struct .. type:: ca_field_cache_t Represents a set of distinct :type:`ca_field_t` instances. This object contains an array of pointers to individual heap-allocated :type:`ca_field_struct` objects as well as a hash table for quick lookup. .. function:: void ca_field_cache_init(ca_field_cache_t cache, ca_ctx_t ctx) Initializes *cache* for use. .. function:: void ca_field_cache_clear(ca_field_cache_t cache, ca_ctx_t ctx) Clears *cache*, freeing the memory allocated internally. This does not clear the individual extension numbers, which are only held as references. .. function:: ca_field_ptr ca_field_cache_insert_ext(ca_field_cache_t cache, ca_ext_struct ** x, slong len, ca_ctx_t ctx) Adds the field defined by the length-*len* list of extension numbers *x* to *cache* without duplication. If such a field already exists in *cache*, a pointer to that instance is returned. Otherwise, a field with extension numbers *x* is inserted into *cache* and a pointer to that new instance is returned. Upon insertion of a new field, the reduction ideal is constructed via :func:`ca_field_build_ideal`. .. raw:: latex \newpage flint-3.1.3/doc/source/ca_mat.rst000066400000000000000000000702751461254215100166710ustar00rootroot00000000000000.. _ca-mat: **ca_mat.h** -- matrices over the real and complex numbers =============================================================================== A :type:`ca_mat_t` represents a dense matrix over the real or complex numbers, implemented as an array of entries of type :type:`ca_struct`. The dimension (number of rows and columns) of a matrix is fixed at initialization, and the user must ensure that inputs and outputs to an operation have compatible dimensions. The number of rows or columns in a matrix can be zero. Types, macros and constants ------------------------------------------------------------------------------- .. type:: ca_mat_struct .. type:: ca_mat_t Contains a pointer to a flat array of the entries (*entries*), an array of pointers to the start of each row (*rows*), and the number of rows (*r*) and columns (*c*). A *ca_mat_t* is defined as an array of length one of type *ca_mat_struct*, permitting a *ca_mat_t* to be passed by reference. .. macro:: ca_mat_entry(mat, i, j) Macro giving a pointer to the entry at row *i* and column *j*. .. macro:: ca_mat_nrows(mat) Returns the number of rows of the matrix. .. macro:: ca_mat_ncols(mat) Returns the number of columns of the matrix. .. function:: ca_ptr ca_mat_entry_ptr(ca_mat_t mat, slong i, slong j) Returns a pointer to the entry at row *i* and column *j*. Equivalent to :macro:`ca_mat_entry` but implemented as a function. Memory management ------------------------------------------------------------------------------- .. function:: void ca_mat_init(ca_mat_t mat, slong r, slong c, ca_ctx_t ctx) Initializes the matrix, setting it to the zero matrix with *r* rows and *c* columns. .. function:: void ca_mat_clear(ca_mat_t mat, ca_ctx_t ctx) Clears the matrix, deallocating all entries. .. function:: void ca_mat_swap(ca_mat_t mat1, ca_mat_t mat2, ca_ctx_t ctx) Efficiently swaps *mat1* and *mat2*. .. function:: void ca_mat_window_init(ca_mat_t window, const ca_mat_t mat, slong r1, slong c1, slong r2, slong c2, ca_ctx_t ctx) Initializes *window* to a window matrix into the submatrix of *mat* starting at the corner at row *r1* and column *c1* (inclusive) and ending at row *r2* and column *c2* (exclusive). .. function:: void ca_mat_window_clear(ca_mat_t window, ca_ctx_t ctx) Frees the window matrix. Assignment and conversions ------------------------------------------------------------------------------- .. function:: void ca_mat_set(ca_mat_t dest, const ca_mat_t src, ca_ctx_t ctx) void ca_mat_set_fmpz_mat(ca_mat_t dest, const fmpz_mat_t src, ca_ctx_t ctx) void ca_mat_set_fmpq_mat(ca_mat_t dest, const fmpq_mat_t src, ca_ctx_t ctx) Sets *dest* to *src*. The operands must have identical dimensions. .. function:: void ca_mat_set_ca(ca_mat_t mat, const ca_t c, ca_ctx_t ctx) Sets *mat* to the matrix with the scalar *c* on the main diagonal and zeros elsewhere. .. function:: void ca_mat_transfer(ca_mat_t res, ca_ctx_t res_ctx, const ca_mat_t src, ca_ctx_t src_ctx) Sets *res* to *src* where the corresponding context objects *res_ctx* and *src_ctx* may be different. This operation preserves the mathematical value represented by *src*, but may result in a different internal representation depending on the settings of the context objects. Random generation ------------------------------------------------------------------------------- .. function:: void ca_mat_randtest(ca_mat_t mat, flint_rand_t state, slong depth, slong bits, ca_ctx_t ctx) Sets *mat* to a random matrix with entries having complexity up to *depth* and *bits* (see :func:`ca_randtest`). .. function:: void ca_mat_randtest_rational(ca_mat_t mat, flint_rand_t state, slong bits, ca_ctx_t ctx) Sets *mat* to a random rational matrix with entries up to *bits* bits in size. .. function:: void ca_mat_randops(ca_mat_t mat, flint_rand_t state, slong count, ca_ctx_t ctx) Randomizes *mat* in-place by performing elementary row or column operations. More precisely, at most count random additions or subtractions of distinct rows and columns will be performed. This leaves the rank (and for square matrices, the determinant) unchanged. Input and output ------------------------------------------------------------------------------- .. function:: void ca_mat_print(const ca_mat_t mat, ca_ctx_t ctx) Prints *mat* to standard output. The entries are printed on separate lines. .. function:: void ca_mat_printn(const ca_mat_t mat, slong digits, ca_ctx_t ctx) Prints a decimal representation of *mat* with precision specified by *digits*. The entries are comma-separated with square brackets and comma separation for the rows. Special matrices ------------------------------------------------------------------------------- .. function:: void ca_mat_zero(ca_mat_t mat, ca_ctx_t ctx) Sets all entries in *mat* to zero. .. function:: void ca_mat_one(ca_mat_t mat, ca_ctx_t ctx) Sets the entries on the main diagonal of *mat* to one, and all other entries to zero. .. function:: void ca_mat_ones(ca_mat_t mat, ca_ctx_t ctx) Sets all entries in *mat* to one. .. function:: void ca_mat_pascal(ca_mat_t mat, int triangular, ca_ctx_t ctx) Sets *mat* to a Pascal matrix, whose entries are binomial coefficients. If *triangular* is 0, constructs a full symmetric matrix with the rows of Pascal's triangle as successive antidiagonals. If *triangular* is 1, constructs the upper triangular matrix with the rows of Pascal's triangle as columns, and if *triangular* is -1, constructs the lower triangular matrix with the rows of Pascal's triangle as rows. .. function:: void ca_mat_stirling(ca_mat_t mat, int kind, ca_ctx_t ctx) Sets *mat* to a Stirling matrix, whose entries are Stirling numbers. If *kind* is 0, the entries are set to the unsigned Stirling numbers of the first kind. If *kind* is 1, the entries are set to the signed Stirling numbers of the first kind. If *kind* is 2, the entries are set to the Stirling numbers of the second kind. .. function:: void ca_mat_hilbert(ca_mat_t mat, ca_ctx_t ctx) Sets *mat* to the Hilbert matrix, which has entries `A_{i,j} = 1/(i+j+1)`. .. function:: void ca_mat_dft(ca_mat_t mat, int type, ca_ctx_t ctx) Sets *mat* to the DFT (discrete Fourier transform) matrix of order *n* where *n* is the smallest dimension of *mat* (if *mat* is not square, the matrix is extended periodically along the larger dimension). The *type* parameter selects between four different versions of the DFT matrix (in which `\omega = e^{2\pi i/n}`): * Type 0 -- entries `A_{j,k} = \omega^{-jk}` * Type 1 -- entries `A_{j,k} = \omega^{jk} / n` * Type 2 -- entries `A_{j,k} = \omega^{-jk} / \sqrt{n}` * Type 3 -- entries `A_{j,k} = \omega^{jk} / \sqrt{n}` The type 0 and 1 matrices are inverse pairs, and similarly for the type 2 and 3 matrices. Comparisons and properties ------------------------------------------------------------------------------- .. function:: truth_t ca_mat_check_equal(const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) Compares *A* and *B* for equality. .. function:: truth_t ca_mat_check_is_zero(const ca_mat_t A, ca_ctx_t ctx) Tests if *A* is the zero matrix. .. function:: truth_t ca_mat_check_is_one(const ca_mat_t A, ca_ctx_t ctx) Tests if *A* has ones on the main diagonal and zeros elsewhere. Conjugate and transpose ------------------------------------------------------------------------------- .. function:: void ca_mat_transpose(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) Sets *res* to the transpose of *A*. .. function:: void ca_mat_conj(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) Sets *res* to the entrywise complex conjugate of *A*. .. function:: void ca_mat_conj_transpose(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) Sets *res* to the conjugate transpose (Hermitian transpose) of *A*. Arithmetic ------------------------------------------------------------------------------- .. function:: void ca_mat_neg(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) Sets *res* to the negation of *A*. .. function:: void ca_mat_add(ca_mat_t res, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) Sets *res* to the sum of *A* and *B*. .. function:: void ca_mat_sub(ca_mat_t res, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) Sets *res* to the difference of *A* and *B*. .. function:: void ca_mat_mul_classical(ca_mat_t res, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) void ca_mat_mul_same_nf(ca_mat_t res, const ca_mat_t A, const ca_mat_t B, ca_field_t K, ca_ctx_t ctx) void ca_mat_mul(ca_mat_t res, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) Sets *res* to the matrix product of *A* and *B*. The *classical* version uses classical multiplication. The *same_nf* version assumes (not checked) that both *A* and *B* have coefficients in the same simple algebraic number field *K* or in `\mathbb{Q}`. The default version chooses an algorithm automatically. .. function:: void ca_mat_mul_si(ca_mat_t B, const ca_mat_t A, slong c, ca_ctx_t ctx) void ca_mat_mul_fmpz(ca_mat_t B, const ca_mat_t A, const fmpz_t c, ca_ctx_t ctx) void ca_mat_mul_fmpq(ca_mat_t B, const ca_mat_t A, const fmpq_t c, ca_ctx_t ctx) void ca_mat_mul_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) Sets *B* to *A* multiplied by the scalar *c*. .. function:: void ca_mat_div_si(ca_mat_t B, const ca_mat_t A, slong c, ca_ctx_t ctx) void ca_mat_div_fmpz(ca_mat_t B, const ca_mat_t A, const fmpz_t c, ca_ctx_t ctx) void ca_mat_div_fmpq(ca_mat_t B, const ca_mat_t A, const fmpq_t c, ca_ctx_t ctx) void ca_mat_div_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) Sets *B* to *A* divided by the scalar *c*. .. function:: void ca_mat_add_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) void ca_mat_sub_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) Sets *B* to *A* plus or minus the scalar *c* (interpreted as a diagonal matrix). .. function:: void ca_mat_addmul_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) void ca_mat_submul_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) Sets the matrix *B* to *B* plus (or minus) the matrix *A* multiplied by the scalar *c*. Powers ------------------------------------------------------------------------------- .. function:: void ca_mat_sqr(ca_mat_t B, const ca_mat_t A, ca_ctx_t ctx) Sets *B* to the square of *A*. .. function:: void ca_mat_pow_ui_binexp(ca_mat_t B, const ca_mat_t A, ulong exp, ca_ctx_t ctx) Sets *B* to *A* raised to the power *exp*, evaluated using binary exponentiation. Polynomial evaluation ------------------------------------------------------------------------------- .. function:: void _ca_mat_ca_poly_evaluate(ca_mat_t res, ca_srcptr poly, slong len, const ca_mat_t A, ca_ctx_t ctx) void ca_mat_ca_poly_evaluate(ca_mat_t res, const ca_poly_t poly, const ca_mat_t A, ca_ctx_t ctx) Sets *res* to `f(A)` where *f* is the polynomial given by *poly* and *A* is a square matrix. Uses the Paterson-Stockmeyer algorithm. Gaussian elimination and LU decomposition ------------------------------------------------------------------------------- .. function:: truth_t ca_mat_find_pivot(slong * pivot_row, ca_mat_t mat, slong start_row, slong end_row, slong column, ca_ctx_t ctx) Attempts to find a nonzero entry in *mat* with column index *column* and row index between *start_row* (inclusive) and *end_row* (exclusive). If the return value is ``T_TRUE``, such an element exists, and *pivot_row* is set to the row index. If the return value is ``T_FALSE``, no such element exists (all entries in this part of the column are zero). If the return value is ``T_UNKNOWN``, it is unknown whether such an element exists (zero certification failed). This function is destructive: any elements that are nontrivially zero but can be certified zero will be overwritten by exact zeros. .. function:: int ca_mat_lu_classical(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx) int ca_mat_lu_recursive(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx) int ca_mat_lu(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx) Computes a generalized LU decomposition `A = PLU` of a given matrix *A*, writing the rank of *A* to *rank*. If *A* is a nonsingular square matrix, *LU* will be set to a unit diagonal lower triangular matrix *L* and an upper triangular matrix *U* (the diagonal of *L* will not be stored explicitly). If *A* is an arbitrary matrix of rank *r*, *U* will be in row echelon form having *r* nonzero rows, and *L* will be lower triangular but truncated to *r* columns, having implicit ones on the *r* first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and set the rank to 0 if *A* is detected to be rank-deficient. The algorithm can fail if it fails to certify that a pivot element is zero or nonzero, in which case the correct rank cannot be determined. The return value is 1 on success and 0 on failure. On failure, the data in the output variables ``rank``, ``P`` and ``LU`` will be meaningless. The *classical* version uses iterative Gaussian elimination. The *recursive* version uses a block recursive algorithm to take advantage of fast matrix multiplication. .. function:: int ca_mat_fflu(slong * rank, slong * P, ca_mat_t LU, ca_t den, const ca_mat_t A, int rank_check, ca_ctx_t ctx) Similar to :func:`ca_mat_lu`, but computes a fraction-free LU decomposition using the Bareiss algorithm. The denominator is written to *den*. Note that despite being "fraction-free", this algorithm may introduce fractions due to incomplete symbolic simplifications. .. function:: truth_t ca_mat_nonsingular_lu(slong * P, ca_mat_t LU, const ca_mat_t A, ca_ctx_t ctx) Wrapper for :func:`ca_mat_lu`. If *A* can be proved to be invertible/nonsingular, returns ``T_TRUE`` and sets *P* and *LU* to a LU decomposition `A = PLU`. If *A* can be proved to be singular, returns ``T_FALSE``. If *A* cannot be proved to be either singular or nonsingular, returns ``T_UNKNOWN``. When the return value is ``T_FALSE`` or ``T_UNKNOWN``, the LU factorization is not completed and the values of *P* and *LU* are arbitrary. .. function:: truth_t ca_mat_nonsingular_fflu(slong * P, ca_mat_t LU, ca_t den, const ca_mat_t A, ca_ctx_t ctx) Wrapper for :func:`ca_mat_fflu`. Similar to :func:`ca_mat_nonsingular_lu`, but computes a fraction-free LU decomposition using the Bareiss algorithm. The denominator is written to *den*. Note that despite being "fraction-free", this algorithm may introduce fractions due to incomplete symbolic simplifications. Solving and inverse ------------------------------------------------------------------------------- .. function:: truth_t ca_mat_inv(ca_mat_t X, const ca_mat_t A, ca_ctx_t ctx) Determines if the square matrix *A* is nonsingular, and if successful, sets `X = A^{-1}` and returns ``T_TRUE``. Returns ``T_FALSE`` if *A* is singular, and ``T_UNKNOWN`` if the rank of *A* cannot be determined. .. function:: truth_t ca_mat_nonsingular_solve_adjugate(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) truth_t ca_mat_nonsingular_solve_fflu(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) truth_t ca_mat_nonsingular_solve_lu(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) truth_t ca_mat_nonsingular_solve(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) Determines if the square matrix *A* is nonsingular, and if successful, solves `AX = B` and returns ``T_TRUE``. Returns ``T_FALSE`` if *A* is singular, and ``T_UNKNOWN`` if the rank of *A* cannot be determined. .. function:: void ca_mat_solve_tril_classical(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx) void ca_mat_solve_tril_recursive(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx) void ca_mat_solve_tril(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx) void ca_mat_solve_triu_classical(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx) void ca_mat_solve_triu_recursive(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx) void ca_mat_solve_triu(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx) Solves the lower triangular system `LX = B` or the upper triangular system `UX = B`, respectively. It is assumed (not checked) that the diagonal entries are nonzero. If *unit* is set, the main diagonal of *L* or *U* is taken to consist of all ones, and in that case the actual entries on the diagonal are not read at all and can contain other data. The *classical* versions perform the computations iteratively while the *recursive* versions perform the computations in a block recursive way to benefit from fast matrix multiplication. The default versions choose an algorithm automatically. .. function:: void ca_mat_solve_fflu_precomp(ca_mat_t X, const slong * perm, const ca_mat_t A, const ca_t den, const ca_mat_t B, ca_ctx_t ctx) void ca_mat_solve_lu_precomp(ca_mat_t X, const slong * P, const ca_mat_t LU, const ca_mat_t B, ca_ctx_t ctx) Solves `AX = B` given the precomputed nonsingular LU decomposition `A = PLU` or fraction-free LU decomposition with denominator *den*. The matrices `X` and `B` are allowed to be aliased with each other, but `X` is not allowed to be aliased with `LU`. Rank and echelon form ------------------------------------------------------------------------------- .. function:: int ca_mat_rank(slong * rank, const ca_mat_t A, ca_ctx_t ctx) Computes the rank of the matrix *A*. If successful, returns 1 and writes the rank to ``rank``. If unsuccessful, returns 0. .. function:: int ca_mat_rref_fflu(slong * rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx) int ca_mat_rref_lu(slong * rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx) int ca_mat_rref(slong * rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx) Computes the reduced row echelon form (rref) of a given matrix. On success, sets *R* to the rref of *A*, writes the rank to *rank*, and returns 1. On failure to certify the correct rank, returns 0, leaving the data in *rank* and *R* meaningless. The *fflu* version computes a fraction-free LU decomposition and then converts the output ro rref form. The *lu* version computes a regular LU decomposition and then converts the output to rref form. The default version uses an automatic algorithm choice and may implement additional methods for special cases. .. function:: int ca_mat_right_kernel(ca_mat_t X, const ca_mat_t A, ca_ctx_t ctx) Sets *X* to a basis of the right kernel (nullspace) of *A*. The output matrix *X* will be resized in-place to have a number of columns equal to the nullity of *A*. Returns 1 on success. On failure, returns 0 and leaves the data in *X* meaningless. Determinant and trace ------------------------------------------------------------------------------- .. function:: void ca_mat_trace(ca_t trace, const ca_mat_t mat, ca_ctx_t ctx) Sets *trace* to the sum of the entries on the main diagonal of *mat*. .. function:: void ca_mat_det_berkowitz(ca_t det, const ca_mat_t A, ca_ctx_t ctx) int ca_mat_det_lu(ca_t det, const ca_mat_t A, ca_ctx_t ctx) int ca_mat_det_bareiss(ca_t det, const ca_mat_t A, ca_ctx_t ctx) void ca_mat_det_cofactor(ca_t det, const ca_mat_t A, ca_ctx_t ctx) void ca_mat_det(ca_t det, const ca_mat_t A, ca_ctx_t ctx) Sets *det* to the determinant of the square matrix *A*. Various algorithms are available: * The *berkowitz* version uses the division-free Berkowitz algorithm performing `O(n^4)` operations. Since no zero tests are required, it is guaranteed to succeed. * The *cofactor* version performs cofactor expansion. This is currently only supported for matrices up to size 4. * The *lu* and *bareiss* versions use rational LU decomposition and fraction-free LU decomposition (Bareiss algorithm) respectively, requiring `O(n^3)` operations. These algorithms can fail if zero certification fails (see :func:`ca_mat_nonsingular_lu`); they return 1 for success and 0 for failure. Note that the Bareiss algorithm, despite being "fraction-free", may introduce fractions due to incomplete symbolic simplifications. The default function chooses an algorithm automatically. It will, in addition, recognize trivially rational and integer matrices and evaluate those determinants using :type:`fmpq_mat_t` or :type:`fmpz_mat_t`. The various algorithms can produce different symbolic forms of the same determinant. Which algorithm performs better depends strongly and sometimes unpredictably on the structure of the matrix. .. function:: void ca_mat_adjugate_cofactor(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx) void ca_mat_adjugate_charpoly(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx) void ca_mat_adjugate(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx) Sets *adj* to the adjuate matrix of *A* and *det* to the determinant of *A*, both computed simultaneously. The *cofactor* version uses cofactor expansion. The *charpoly* version computes and evaluates the characteristic polynomial. The default version uses an automatic algorithm choice. Characteristic polynomial ------------------------------------------------------------------------------- .. function:: void _ca_mat_charpoly_berkowitz(ca_ptr cp, const ca_mat_t mat, ca_ctx_t ctx) void ca_mat_charpoly_berkowitz(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx) int _ca_mat_charpoly_danilevsky(ca_ptr cp, const ca_mat_t mat, ca_ctx_t ctx) int ca_mat_charpoly_danilevsky(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx) void _ca_mat_charpoly(ca_ptr cp, const ca_mat_t mat, ca_ctx_t ctx) void ca_mat_charpoly(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx) Sets *poly* to the characteristic polynomial of *mat* which must be a square matrix. If the matrix has *n* rows, the underscore method requires space for `n + 1` output coefficients. The *berkowitz* version uses a division-free algorithm requiring `O(n^4)` operations. The *danilevsky* version only performs `O(n^3)` operations, but performs divisions and needs to check for zero which can fail. This version returns 1 on success and 0 on failure. The default version chooses an algorithm automatically. .. function:: int ca_mat_companion(ca_mat_t mat, const ca_poly_t poly, ca_ctx_t ctx) Sets *mat* to the companion matrix of *poly*. This function verifies that the leading coefficient of *poly* is provably nonzero and that the output matrix has the right size, returning 1 on success. It returns 0 if the leading coefficient of *poly* cannot be proved nonzero or if the size of the output matrix does not match. Eigenvalues and eigenvectors ------------------------------------------------------------------------------- .. function:: int ca_mat_eigenvalues(ca_vec_t lambda, ulong * exp, const ca_mat_t mat, ca_ctx_t ctx) Attempts to compute all complex eigenvalues of the given matrix *mat*. On success, returns 1 and sets *lambda* to the distinct eigenvalues with corresponding multiplicities in *exp*. The eigenvalues are returned in arbitrary order. On failure, returns 0 and leaves the values in *lambda* and *exp* arbitrary. This function effectively computes the characteristic polynomial and then calls :type:`ca_poly_roots`. .. function:: truth_t ca_mat_diagonalization(ca_mat_t D, ca_mat_t P, const ca_mat_t A, ca_ctx_t ctx) Matrix diagonalization: attempts to compute a diagonal matrix *D* and an invertible matrix *P* such that `A = PDP^{-1}`. Returns ``T_TRUE`` if *A* is diagonalizable and the computation succeeds, ``T_FALSE`` if *A* is provably not diagonalizable, and ``T_UNKNOWN`` if it is unknown whether *A* is diagonalizable. If the return value is not ``T_TRUE``, the values in *D* and *P* are arbitrary. Jordan canonical form ------------------------------------------------------------------------------- .. function:: int ca_mat_jordan_blocks(ca_vec_t lambda, slong * num_blocks, slong * block_lambda, slong * block_size, const ca_mat_t A, ca_ctx_t ctx) Computes the blocks of the Jordan canonical form of *A*. On success, returns 1 and sets *lambda* to the unique eigenvalues of *A*, sets *num_blocks* to the number of Jordan blocks, entry *i* of *block_lambda* to the index of the eigenvalue in Jordan block *i*, and entry *i* of *block_size* to the size of Jordan block *i*. On failure, returns 0, leaving arbitrary values in the output variables. The user should allocate space in *block_lambda* and *block_size* for up to *n* entries where *n* is the size of the matrix. The Jordan form is unique up to the ordering of blocks, which is arbitrary. .. function:: void ca_mat_set_jordan_blocks(ca_mat_t mat, const ca_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, ca_ctx_t ctx) Sets *mat* to the concatenation of the Jordan blocks given in *lambda*, *num_blocks*, *block_lambda* and *block_size*. See :func:`ca_mat_jordan_blocks` for an explanation of these variables. .. function:: int ca_mat_jordan_transformation(ca_mat_t mat, const ca_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, const ca_mat_t A, ca_ctx_t ctx) Given the precomputed Jordan block decomposition (*lambda*, *num_blocks*, *block_lambda*, *block_size*) of the square matrix *A*, computes the corresponding transformation matrix *P* such that `A = P J P^{-1}`. On success, writes *P* to *mat* and returns 1. On failure, returns 0, leaving the value of *mat* arbitrary. .. function:: int ca_mat_jordan_form(ca_mat_t J, ca_mat_t P, const ca_mat_t A, ca_ctx_t ctx) Computes the Jordan decomposition `A = P J P^{-1}` of the given square matrix *A*. The user can pass *NULL* for the output variable *P*, in which case only *J* is computed. On success, returns 1. On failure, returns 0, leaving the values of *J* and *P* arbitrary. This function is a convenience wrapper around :func:`ca_mat_jordan_blocks`, :func:`ca_mat_set_jordan_blocks` and :func:`ca_mat_jordan_transformation`. For computations with the Jordan decomposition, it is often better to use those methods directly since they give direct access to the spectrum and block structure. Matrix functions ------------------------------------------------------------------------------- .. function:: int ca_mat_exp(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) Matrix exponential: given a square matrix *A*, sets *res* to `e^A` and returns 1 on success. If unsuccessful, returns 0, leaving the values in *res* arbitrary. This function uses Jordan decomposition. The matrix exponential always exists, but computation can fail if computing the Jordan decomposition fails. .. function:: truth_t ca_mat_log(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) Matrix logarithm: given a square matrix *A*, sets *res* to a logarithm `\log(A)` and returns ``T_TRUE`` on success. If *A* can be proved to have no logarithm, returns ``T_FALSE``. If the existence of a logarithm cannot be proved, returns ``T_UNKNOWN``. This function uses the Jordan decomposition, and the branch of the matrix logarithm is defined by taking the principal values of the logarithms of all eigenvalues. flint-3.1.3/doc/source/ca_poly.rst000066400000000000000000000461731461254215100170730ustar00rootroot00000000000000.. _ca-poly: **ca_poly.h** -- dense univariate polynomials over the real and complex numbers =============================================================================== A :type:`ca_poly_t` represents a univariate polynomial over the real or complex numbers (an element of `\mathbb{R}[X]` or `\mathbb{C}[X]`), implemented as an array of coefficients of type :type:`ca_struct`. Most functions are provided in two versions: an underscore method which operates directly on pre-allocated arrays of coefficients and generally has some restrictions (such as requiring the lengths to be nonzero and not supporting aliasing of the input and output arrays), and a non-underscore method which performs automatic memory management and handles degenerate cases. Warnings: * A polynomial is always normalised by removing zero coefficients at the top. Coefficients will not be removed when Calcium is unable to prove that they are zero. The represented degree can therefore be larger than the degree of the mathematical polynomial. When the correct degree is needed, it is important to verify the leading coefficient. (Of course, this will never be an issue with polynomials that are explicitly monic, for example.) * The special values *Undefined*, unsigned infinity and signed infinity supported by the scalar :type:`ca_t` type are not really meaningful as coefficients of polynomials. We normally assume that the user does not assign those values to coefficients of polynomials, and the functions in this module will likewise normally not generate such coefficients. *Unknown* can still appear as a coefficient representing a number that is inaccessible for computation. A polynomial with numerical coefficients and with a nonzero leading coefficient is called *proper*. The function :func:`ca_poly_is_proper` can be used to check for violations. Types, macros and constants ------------------------------------------------------------------------------- .. type:: ca_poly_struct .. type:: ca_poly_t Contains a pointer to an array of coefficients (*coeffs*), the used length (*length*), and the allocated size of the array (*alloc*). A *ca_poly_t* is defined as an array of length one of type *ca_poly_struct*, permitting an *ca_poly_t* to be passed by reference. Memory management ------------------------------------------------------------------------------- .. function:: void ca_poly_init(ca_poly_t poly, ca_ctx_t ctx) Initializes the polynomial for use, setting it to the zero polynomial. .. function:: void ca_poly_clear(ca_poly_t poly, ca_ctx_t ctx) Clears the polynomial, deallocating all coefficients and the coefficient array. .. function:: void ca_poly_fit_length(ca_poly_t poly, slong len, ca_ctx_t ctx) Makes sure that the coefficient array of the polynomial contains at least *len* initialized coefficients. .. function:: void _ca_poly_set_length(ca_poly_t poly, slong len, ca_ctx_t ctx) Directly changes the length of the polynomial, without allocating or deallocating coefficients. The value should not exceed the allocation length. .. function:: void _ca_poly_normalise(ca_poly_t poly, ca_ctx_t ctx) Strips any top coefficients which can be proved identical to zero. Assignment and simple values ------------------------------------------------------------------------------- .. function:: void ca_poly_zero(ca_poly_t poly, ca_ctx_t ctx) Sets *poly* to the zero polynomial. .. function:: void ca_poly_one(ca_poly_t poly, ca_ctx_t ctx) Sets *poly* to the constant polynomial 1. .. function:: void ca_poly_x(ca_poly_t poly, ca_ctx_t ctx) Sets *poly* to the monomial *x*. .. function:: void ca_poly_set_ca(ca_poly_t poly, const ca_t c, ca_ctx_t ctx) void ca_poly_set_si(ca_poly_t poly, slong c, ca_ctx_t ctx) Sets *poly* to the constant polynomial *c*. .. function:: void ca_poly_set(ca_poly_t res, const ca_poly_t src, ca_ctx_t ctx) void ca_poly_set_fmpz_poly(ca_poly_t res, const fmpz_poly_t src, ca_ctx_t ctx) void ca_poly_set_fmpq_poly(ca_poly_t res, const fmpq_poly_t src, ca_ctx_t ctx) Sets *poly* the polynomial *src*. .. function:: void ca_poly_set_coeff_ca(ca_poly_t poly, slong n, const ca_t x, ca_ctx_t ctx) Sets the coefficient at position *n* in *poly* to *x*. .. function:: void ca_poly_transfer(ca_poly_t res, ca_ctx_t res_ctx, const ca_poly_t src, ca_ctx_t src_ctx) Sets *res* to *src* where the corresponding context objects *res_ctx* and *src_ctx* may be different. This operation preserves the mathematical value represented by *src*, but may result in a different internal representation depending on the settings of the context objects. Random generation ------------------------------------------------------------------------------- .. function:: void ca_poly_randtest(ca_poly_t poly, flint_rand_t state, slong len, slong depth, slong bits, ca_ctx_t ctx) Sets *poly* to a random polynomial of length up to *len* and with entries having complexity up to *depth* and *bits* (see :func:`ca_randtest`). .. function:: void ca_poly_randtest_rational(ca_poly_t poly, flint_rand_t state, slong len, slong bits, ca_ctx_t ctx) Sets *poly* to a random rational polynomial of length up to *len* and with entries up to *bits* bits in size. Input and output ------------------------------------------------------------------------------- .. function:: void ca_poly_print(const ca_poly_t poly, ca_ctx_t ctx) Prints *poly* to standard output. The coefficients are printed on separate lines. .. function:: void ca_poly_printn(const ca_poly_t poly, slong digits, ca_ctx_t ctx) Prints a decimal representation of *poly* with precision specified by *digits*. The coefficients are comma-separated and the whole list is enclosed in square brackets. Degree and leading coefficient ------------------------------------------------------------------------------- .. function:: int ca_poly_is_proper(const ca_poly_t poly, ca_ctx_t ctx) Checks that *poly* represents an element of `\mathbb{C}[X]` with well-defined degree. This returns 1 if the leading coefficient of *poly* is nonzero and all coefficients of *poly* are numbers (not special values). It returns 0 otherwise. It returns 1 when *poly* is precisely the zero polynomial (which does not have a leading coefficient). .. function:: int ca_poly_make_monic(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) Makes *poly* monic by dividing by the leading coefficient if possible and returns 1. Returns 0 if the leading coefficient cannot be certified to be nonzero, or if *poly* is the zero polynomial. .. function:: void _ca_poly_reverse(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx) .. function:: void ca_poly_reverse(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx) Sets *res* to the reversal of *poly* considered as a polynomial of length *n*, zero-padding if needed. The underscore method assumes that *len* is positive and less than or equal to *n*. Comparisons ------------------------------------------------------------------------------- .. function:: truth_t _ca_poly_check_equal(ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) truth_t ca_poly_check_equal(const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) Checks if *poly1* and *poly2* represent the same polynomial. The underscore method assumes that *len1* is at least as large as *len2*. .. function:: truth_t ca_poly_check_is_zero(const ca_poly_t poly, ca_ctx_t ctx) Checks if *poly* is the zero polynomial. .. function:: truth_t ca_poly_check_is_one(const ca_poly_t poly, ca_ctx_t ctx) Checks if *poly* is the constant polynomial 1. Arithmetic ------------------------------------------------------------------------------- .. function:: void _ca_poly_shift_left(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx) void ca_poly_shift_left(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx) Sets *res* to *poly* shifted *n* coefficients to the left; that is, multiplied by `x^n`. .. function:: void _ca_poly_shift_right(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx) void ca_poly_shift_right(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx) Sets *res* to *poly* shifted *n* coefficients to the right; that is, divided by `x^n`. .. function:: void ca_poly_neg(ca_poly_t res, const ca_poly_t src, ca_ctx_t ctx) Sets *res* to the negation of *src*. .. function:: void _ca_poly_add(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) void ca_poly_add(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) Sets *res* to the sum of *poly1* and *poly2*. .. function:: void _ca_poly_sub(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) void ca_poly_sub(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) Sets *res* to the difference of *poly1* and *poly2*. .. function:: void _ca_poly_mul(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) void ca_poly_mul(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) Sets *res* to the product of *poly1* and *poly2*. .. function:: void _ca_poly_mullow(ca_ptr C, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, slong n, ca_ctx_t ctx) void ca_poly_mullow(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, slong n, ca_ctx_t ctx) Sets *res* to the product of *poly1* and *poly2* truncated to length *n*. .. function:: void ca_poly_mul_ca(ca_poly_t res, const ca_poly_t poly, const ca_t c, ca_ctx_t ctx) Sets *res* to *poly* multiplied by the scalar *c*. .. function:: void ca_poly_div_ca(ca_poly_t res, const ca_poly_t poly, const ca_t c, ca_ctx_t ctx) Sets *res* to *poly* divided by the scalar *c*. .. function:: void _ca_poly_divrem_basecase(ca_ptr Q, ca_ptr R, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, const ca_t invB, ca_ctx_t ctx) int ca_poly_divrem_basecase(ca_poly_t Q, ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) void _ca_poly_divrem(ca_ptr Q, ca_ptr R, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, const ca_t invB, ca_ctx_t ctx) int ca_poly_divrem(ca_poly_t Q, ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) int ca_poly_div(ca_poly_t Q, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) int ca_poly_rem(ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) If the leading coefficient of *B* can be proved invertible, sets *Q* and *R* to the quotient and remainder of polynomial division of *A* by *B* and returns 1. If the leading coefficient cannot be proved invertible, returns 0. The underscore method takes a precomputed inverse of the leading coefficient of *B*. .. function:: void _ca_poly_pow_ui_trunc(ca_ptr res, ca_srcptr f, slong flen, ulong exp, slong len, ca_ctx_t ctx) void ca_poly_pow_ui_trunc(ca_poly_t res, const ca_poly_t poly, ulong exp, slong len, ca_ctx_t ctx) Sets *res* to *poly* raised to the power *exp*, truncated to length *len*. .. function:: void _ca_poly_pow_ui(ca_ptr res, ca_srcptr f, slong flen, ulong exp, ca_ctx_t ctx) void ca_poly_pow_ui(ca_poly_t res, const ca_poly_t poly, ulong exp, ca_ctx_t ctx) Sets *res* to *poly* raised to the power *exp*. Evaluation and composition ------------------------------------------------------------------------------- .. function:: void _ca_poly_evaluate_horner(ca_t res, ca_srcptr f, slong len, const ca_t x, ca_ctx_t ctx) void ca_poly_evaluate_horner(ca_t res, const ca_poly_t f, const ca_t a, ca_ctx_t ctx) void _ca_poly_evaluate(ca_t res, ca_srcptr f, slong len, const ca_t x, ca_ctx_t ctx) void ca_poly_evaluate(ca_t res, const ca_poly_t f, const ca_t a, ca_ctx_t ctx) Sets *res* to *f* evaluated at the point *a*. .. function:: void _ca_poly_compose(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) void ca_poly_compose(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) Sets *res* to the composition of *poly1* with *poly2*. Derivative and integral ------------------------------------------------------------------------------- .. function:: void _ca_poly_derivative(ca_ptr res, ca_srcptr poly, slong len, ca_ctx_t ctx) void ca_poly_derivative(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) Sets *res* to the derivative of *poly*. The underscore method needs one less coefficient than *len* for the output array. .. function:: void _ca_poly_integral(ca_ptr res, ca_srcptr poly, slong len, ca_ctx_t ctx) void ca_poly_integral(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) Sets *res* to the integral of *poly*. The underscore method needs one more coefficient than *len* for the output array. Power series division ------------------------------------------------------------------------------- .. function:: void _ca_poly_inv_series(ca_ptr res, ca_srcptr f, slong flen, slong len, ca_ctx_t ctx) void ca_poly_inv_series(ca_poly_t res, const ca_poly_t f, slong len, ca_ctx_t ctx) Sets *res* to the power series inverse of *f* truncated to length *len*. .. function:: void _ca_poly_div_series(ca_ptr res, ca_srcptr f, slong flen, ca_srcptr g, slong glen, slong len, ca_ctx_t ctx) void ca_poly_div_series(ca_poly_t res, const ca_poly_t f, const ca_poly_t g, slong len, ca_ctx_t ctx) Sets *res* to the power series quotient of *f* and *g* truncated to length *len*. This function divides by zero if *g* has constant term zero; the user should manually remove initial zeros when an exact cancellation is required. Elementary functions ------------------------------------------------------------------------------- .. function:: void _ca_poly_exp_series(ca_ptr res, ca_srcptr f, slong flen, slong len, ca_ctx_t ctx) void ca_poly_exp_series(ca_poly_t res, const ca_poly_t f, slong len, ca_ctx_t ctx) Sets *res* to the power series exponential of *f* truncated to length *len*. .. function:: void _ca_poly_log_series(ca_ptr res, ca_srcptr f, slong flen, slong len, ca_ctx_t ctx) void ca_poly_log_series(ca_poly_t res, const ca_poly_t f, slong len, ca_ctx_t ctx) Sets *res* to the power series logarithm of *f* truncated to length *len*. Greatest common divisor ------------------------------------------------------------------------------- .. function:: slong _ca_poly_gcd_euclidean(ca_ptr res, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx) int ca_poly_gcd_euclidean(ca_poly_t res, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) slong _ca_poly_gcd(ca_ptr res, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx) int ca_poly_gcd(ca_poly_t res, const ca_poly_t A, const ca_poly_t g, ca_ctx_t ctx) Sets *res* to the GCD of *A* and *B* and returns 1 on success. On failure, returns 0 leaving the value of *res* arbitrary. The computation can fail if testing a leading coefficient for zero fails in the execution of the GCD algorithm. The output is normalized to be monic if it is not the zero polynomial. The underscore methods assume `\text{lenA} \ge \text{lenB} \ge 1`, and that both *A* and *B* have nonzero leading coefficient. They return the length of the GCD, or 0 if the computation fails. The *euclidean* version implements the standard Euclidean algorithm. The default version first checks for rational polynomials or attempts to certify numerically that the polynomials are coprime and otherwise falls back to an automatic choice of algorithm (currently only the Euclidean algorithm). Roots and factorization ------------------------------------------------------------------------------- .. function:: int ca_poly_factor_squarefree(ca_t c, ca_poly_vec_t fac, ulong * exp, const ca_poly_t F, ca_ctx_t ctx) Computes the squarefree factorization of *F*, giving a product `F = c f_1 f_2^2 \ldots f_n^n` where all `f_i` with `f_i \ne 1` are squarefree and pairwise coprime. The nontrivial factors `f_i` are written to *fac* and the corresponding exponents are written to *exp*. This algorithm can fail if GCD computation fails internally. Returns 1 on success and 0 on failure. .. function:: int ca_poly_squarefree_part(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) Sets *res* to the squarefree part of *poly*, normalized to be monic. This algorithm can fail if GCD computation fails internally. Returns 1 on success and 0 on failure. .. function:: void _ca_poly_set_roots(ca_ptr poly, ca_srcptr roots, const ulong * exp, slong n, ca_ctx_t ctx) void ca_poly_set_roots(ca_poly_t poly, ca_vec_t roots, const ulong * exp, ca_ctx_t ctx) Sets *poly* to the monic polynomial with the *n* roots given in the vector *roots*, with multiplicities given in the vector *exp*. In other words, this constructs the polynomial `(x-r_0)^{e_0} (x-r_1)^{e_1} \cdots (x-r_{n-1})^{e_{n-1}}`. Uses binary splitting. .. function:: int _ca_poly_roots(ca_ptr roots, ca_srcptr poly, slong len, ca_ctx_t ctx) int ca_poly_roots(ca_vec_t roots, ulong * exp, const ca_poly_t poly, ca_ctx_t ctx) Attempts to compute all complex roots of the given polynomial *poly*. On success, returns 1 and sets *roots* to a vector containing all the distinct roots with corresponding multiplicities in *exp*. On failure, returns 0 and leaves the values in *roots* arbitrary. The roots are returned in arbitrary order. Failure will occur if the leading coefficient of *poly* cannot be proved to be nonzero, if determining the correct multiplicities fails, or if the builtin algorithms do not have a means to represent the roots symbolically. The underscore method assumes that the polynomial is squarefree. The non-underscore method performs a squarefree factorization. Vectors of polynomials -------------------------------------------------------------------------------- .. type:: ca_poly_vec_struct .. type:: ca_poly_vec_t Represents a vector of polynomials. .. function:: ca_poly_struct * _ca_poly_vec_init(slong len, ca_ctx_t ctx) void ca_poly_vec_init(ca_poly_vec_t res, slong len, ca_ctx_t ctx) Initializes a vector with *len* polynomials. .. function:: void _ca_poly_vec_fit_length(ca_poly_vec_t vec, slong len, ca_ctx_t ctx) Allocates space for *len* polynomials in *vec*. .. function:: void ca_poly_vec_set_length(ca_poly_vec_t vec, slong len, ca_ctx_t ctx) Resizes *vec* to length *len*, zero-extending if needed. .. function:: void _ca_poly_vec_clear(ca_poly_struct * vec, slong len, ca_ctx_t ctx) void ca_poly_vec_clear(ca_poly_vec_t vec, ca_ctx_t ctx) Clears the vector *vec*. .. function:: void ca_poly_vec_append(ca_poly_vec_t vec, const ca_poly_t poly, ca_ctx_t ctx) Appends *poly* to the end of the vector *vec*. .. raw:: latex \newpage flint-3.1.3/doc/source/ca_vec.rst000066400000000000000000000151411461254215100166540ustar00rootroot00000000000000.. _ca-vec: **ca_vec.h** -- vectors of real and complex numbers =============================================================================== A :type:`ca_vec_t` represents a vector of real or complex numbers, implemented as an array of coefficients of type :type:`ca_struct`. Most functions are provided in two versions: an underscore method which operates directly on pre-allocated arrays of coefficients (taking :type:`ca_ptr` and :type:`ca_srcptr` arguments), and a non-underscore method which takes :type:`ca_vec_t` input and performs automatic memory management. Unlike :type:`ca_poly_t`, a :type:`ca_vec_t` is not normalised by removing zero coefficients; it retains the exact length assigned by the user. Types, macros and constants ------------------------------------------------------------------------------- .. type:: ca_vec_struct .. type:: ca_vec_t Contains a pointer to an array of entries (*coeffs*), the used length (*length*), and the allocated size of the array (*alloc*). A *ca_vec_t* is defined as an array of length one of type *ca_vec_struct*, permitting an *ca_vec_t* to be passed by reference. .. macro:: ca_vec_entry(vec, i) Macro returning a pointer to entry *i* in the vector *vec*. The index must be in bounds. Memory management ------------------------------------------------------------------------------- .. function:: ca_ptr _ca_vec_init(slong len, ca_ctx_t ctx) Returns a pointer to an array of *len* coefficients initialized to zero. .. function:: void ca_vec_init(ca_vec_t vec, slong len, ca_ctx_t ctx) Initializes *vec* to a length *len* vector. All entries are set to zero. .. function:: void _ca_vec_clear(ca_ptr vec, slong len, ca_ctx_t ctx) Clears all *len* entries in *vec* and frees the pointer *vec* itself. .. function:: void ca_vec_clear(ca_vec_t vec, ca_ctx_t ctx) Clears the vector *vec*. .. function:: void _ca_vec_swap(ca_ptr vec1, ca_ptr vec2, slong len, ca_ctx_t ctx) Swaps the entries in *vec1* and *vec2* efficiently. .. function:: void ca_vec_swap(ca_vec_t vec1, ca_vec_t vec2, ca_ctx_t ctx) Swaps the vectors *vec1* and *vec2* efficiently. Length ------------------------------------------------------------------------------- .. function:: slong ca_vec_length(const ca_vec_t vec, ca_ctx_t ctx) Returns the length of *vec*. .. function:: void _ca_vec_fit_length(ca_vec_t vec, slong len, ca_ctx_t ctx) Allocates space in *vec* for *len* elements. .. function:: void ca_vec_set_length(ca_vec_t vec, slong len, ca_ctx_t ctx) Sets the length of *vec* to *len*. If *vec* is shorter on input, it will be zero-extended. If *vec* is longer on input, it will be truncated. Assignment ------------------------------------------------------------------------------- .. function:: void _ca_vec_set(ca_ptr res, ca_srcptr src, slong len, ca_ctx_t ctx) Sets *res* to a copy of *src* of length *len*. .. function:: void ca_vec_set(ca_vec_t res, const ca_vec_t src, ca_ctx_t ctx) Sets *res* to a copy of *src*. Special vectors ------------------------------------------------------------------------------- .. function:: void _ca_vec_zero(ca_ptr res, slong len, ca_ctx_t ctx) Sets the *len* entries in *res* to zeros. .. function:: void ca_vec_zero(ca_vec_t res, slong len, ca_ctx_t ctx) Sets *res* to the length *len* zero vector. Input and output ------------------------------------------------------------------------------- .. function:: void ca_vec_print(const ca_vec_t vec, ca_ctx_t ctx) Prints *vec* to standard output. The coefficients are printed on separate lines. .. function:: void ca_vec_printn(const ca_vec_t poly, slong digits, ca_ctx_t ctx) Prints a decimal representation of *vec* with precision specified by *digits*. The coefficients are comma-separated and the whole list is enclosed in square brackets. List operations ------------------------------------------------------------------------------- .. function:: void ca_vec_append(ca_vec_t vec, const ca_t f, ca_ctx_t ctx) Appends *f* to the end of *vec*. Arithmetic ------------------------------------------------------------------------------- .. function:: void _ca_vec_neg(ca_ptr res, ca_srcptr src, slong len, ca_ctx_t ctx) .. function:: void ca_vec_neg(ca_vec_t res, const ca_vec_t src, ca_ctx_t ctx) Sets *res* to the negation of *src*. .. function:: void _ca_vec_add(ca_ptr res, ca_srcptr vec1, ca_srcptr vec2, slong len, ca_ctx_t ctx) .. function:: void _ca_vec_sub(ca_ptr res, ca_srcptr vec1, ca_srcptr vec2, slong len, ca_ctx_t ctx) Sets *res* to the sum or difference of *vec1* and *vec2*, all vectors having length *len*. .. function:: void _ca_vec_scalar_mul_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx) Sets *res* to *src* multiplied by *c*, all vectors having length *len*. .. function:: void _ca_vec_scalar_div_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx) Sets *res* to *src* divided by *c*, all vectors having length *len*. .. function:: void _ca_vec_scalar_addmul_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx) Adds *src* multiplied by *c* to the vector *res*, all vectors having length *len*. .. function:: void _ca_vec_scalar_submul_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx) Subtracts *src* multiplied by *c* from the vector *res*, all vectors having length *len*. Comparisons and properties --------------------------------------------------------------------------------- .. function:: truth_t _ca_vec_check_is_zero(ca_srcptr vec, slong len, ca_ctx_t ctx) Returns whether *vec* is the zero vector. Internal representation --------------------------------------------------------------------------------- .. function:: int _ca_vec_is_fmpq_vec(ca_srcptr vec, slong len, ca_ctx_t ctx) Checks if all elements of *vec* are structurally rational numbers. .. function:: int _ca_vec_fmpq_vec_is_fmpz_vec(ca_srcptr vec, slong len, ca_ctx_t ctx) Assuming that all elements of *vec* are structurally rational numbers, checks if all elements are integers. .. function:: void _ca_vec_fmpq_vec_get_fmpz_vec_den(fmpz * c, fmpz_t den, ca_srcptr vec, slong len, ca_ctx_t ctx) Assuming that all elements of *vec* are structurally rational numbers, converts them to a vector of integers *c* on a common denominator *den*. .. function:: void _ca_vec_set_fmpz_vec_div_fmpz(ca_ptr res, const fmpz * v, const fmpz_t den, slong len, ca_ctx_t ctx) Sets *res* to the rational vector given by numerators *v* and the common denominator *den*. .. raw:: latex \newpage flint-3.1.3/doc/source/calcium.rst000066400000000000000000000057361461254215100170620ustar00rootroot00000000000000.. _calcium: **calcium.h** -- global definitions =============================================================================== Version ------------------------------------------------------------------------------- .. function:: const char * calcium_version(void) Returns a pointer to the version of the library as a string ``X.Y.Z``. Triple-valued logic ------------------------------------------------------------------------------- The Calcium modules use two kinds of predicate functions: * Predicates with signature ``int foo_is_X(const foo_t x)`` return the usual C boolean values ``1`` for true and ``0`` for false, unless otherwise documented. Some functions may return ``0`` also when truth cannot be certified (this will be documented explicitly). * Predicates with signature ``truth_t foo_check_is_X(const foo_t x)`` check a mathematical property that may not be decidable (or may be too costly to decide). The return value is a :type:`truth_t` (``T_TRUE``, ``T_FALSE`` or ``T_UNKNOWN``). Flint, Arb and Antic extras ------------------------------------------------------------------------------- Here we collect various utility methods for Flint, Arb and Antic types that are missing in those libraries. Some of these functions may be migrated upstream in the future. .. function:: ulong calcium_fmpz_hash(const fmpz_t x) Hash function for integers. The algorithm may change; presently, this simply extracts the low word (with sign). Input and output ------------------------------------------------------------------------------- .. type:: calcium_stream_struct .. type:: calcium_stream_t A stream object which can hold either a file pointer or a string (with automatic resizing). .. function:: void calcium_stream_init_file(calcium_stream_t out, FILE * fp) Initializes the stream *out* for writing to the file *fp*. The file can be *stdout*, *stderr*, or any file opened for writing by the user. .. function:: void calcium_stream_init_str(calcium_stream_t out) Initializes the stream *out* for writing to a string in memory. When finished, the user should free the string (the *s* member of *out* with ``flint_free()``). .. function:: void calcium_write(calcium_stream_t out, const char * s) Writes the string *s* to *out*. .. function:: void calcium_write_free(calcium_stream_t out, char * s) Writes *s* to *out* and then frees *s* by calling ``flint_free()``. .. function:: void calcium_write_si(calcium_stream_t out, slong x) void calcium_write_fmpz(calcium_stream_t out, const fmpz_t x) Writes the integer *x* to *out*. .. function:: void calcium_write_arb(calcium_stream_t out, const arb_t z, slong digits, ulong flags) void calcium_write_acb(calcium_stream_t out, const acb_t z, slong digits, ulong flags) Writes the Arb number *z* to *out*, showing *digits* digits and with the display style specified by *flags* (``ARB_STR_NO_RADIUS``, etc.). .. raw:: latex \newpage flint-3.1.3/doc/source/conf.py000066400000000000000000000131741461254215100162050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # https://www.sphinx-doc.org/en/stable/config # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. import os import sys sys.path.insert(0, os.path.abspath('../..')) sys.path.append(os.path.abspath(".")) sys.path.append(os.path.abspath('../../src/python')) # -- Project information ----------------------------------------------------- project = u'Flint' copyright = u'2009-2023, The Flint development team' author = u'The Flint development team' # The full version, including alpha/beta/rc tags with open("../../VERSION") as f: release = f.read().rstrip() # The short X.Y version version = '.'.join(release.split('.')[0:2]) # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.mathjax', 'sphinx.ext.autodoc', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path . exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' default_role = 'math' latex_preamble = r""" \usepackage{amsmath,amssymb} \usepackage{breakurl} \setcounter{tocdepth}{2} """ primary_domain = 'c' # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'default' html_context = { 'css_files': ['_static/default.css'], } # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = { 'sidebarwidth' : 300, 'collapsiblesidebar': True, 'bodyfont': "'arial', sans-serif", 'headfont': "'arial', sans-serif", 'sidebarbtncolor': '#666', 'sidebarbgcolor': '#444', 'sidebarlinkcolor': '#ddd', 'relbarbgcolor': '#333', 'footerbgcolor': '#333', 'headbgcolor': '#fff', } # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # The default sidebars (for documents that don't match any pattern) are # defined by theme itself. Builtin themes are using these templates by # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', # 'searchbox.html']``. # # html_sidebars = {} # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'Flintdoc' # -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'a4paper', 'fontpkg': '', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', 'preamble': '\\usepackage{lmodern}\n\\setcounter{tocdepth}{2}\n\\urlstyle{tt}', 'preamble': '\\usepackage{mathrsfs}\n\\usepackage{lmodern}\n\\setcounter{tocdepth}{2}\n\\urlstyle{tt}', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'Flint.tex', u'Flint Documentation', u'The Flint development team', 'manual'), ] # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'flint', u'Flint Documentation', [author], 1) ] # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'Flint', u'Flint Documentation', author, 'Flint', 'One line description of project.', 'Miscellaneous'), ] # -- Extension configuration ------------------------------------------------- flint-3.1.3/doc/source/constants.rst000066400000000000000000000133561461254215100174560ustar00rootroot00000000000000.. _algorithms_constants: Algorithms for mathematical constants =============================================================================== Most mathematical constants are evaluated using the generic hypergeometric summation code. Pi ------------------------------------------------------------------------------- `\pi` is computed using the Chudnovsky series .. math:: \frac{1}{\pi} = 12 \sum^\infty_{k=0} \frac{(-1)^k (6k)! (13591409 + 545140134k)}{(3k)!(k!)^3 640320^{3k + 3/2}} which is hypergeometric and adds roughly 14 digits per term. Methods based on the arithmetic-geometric mean seem to be slower by a factor three in practice. A small trick is to compute `1/\sqrt{640320}` instead of `\sqrt{640320}` at the end. Logarithms of integers ------------------------------------------------------------------------------- The standalone constant `\log(2)` is computed using Zuniga's series [Zun2023b]_ .. math:: \log(2) = \frac{1}{2} \sum_{n=1}^\infty \frac{1}{3888^n} \frac{(1794 n-297)}{n(2n-1)} \frac{n! (\tfrac{1}{2})_n}{(\tfrac{1}{6})_n (\tfrac{5}{6})_n}. Logarithms of other small integers are in certain situations computed using Machin-like formulas, e.g.: .. math:: \log(10) = 46 \operatorname{atanh}(1/31) + 34 \operatorname{atanh}(1/49) + 20 \operatorname{atanh}(1/161) Euler's constant ------------------------------------------------------------------------------- Euler's constant `\gamma` is computed using the Brent-McMillan formula ([BM1980]_, [MPFR2012]_) .. math:: \gamma = \frac{S_0(2n) - K_0(2n)}{I_0(2n)} - \log(n) in which `n` is a free parameter and .. math:: S_0(x) = \sum_{k=0}^{\infty} \frac{H_k}{(k!)^2} \left(\frac{x}{2}\right)^{2k}, \quad I_0(x) = \sum_{k=0}^{\infty} \frac{1}{(k!)^2} \left(\frac{x}{2}\right)^{2k} .. math:: 2x I_0(x) K_0(x) \sim \sum_{k=0}^{\infty} \frac{[(2k)!]^3}{(k!)^4 8^{2k} x^{2k}}. All series are evaluated using binary splitting. The first two series are evaluated simultaneously, with the summation taken up to `k = N - 1` inclusive where `N \ge \alpha n + 1` and `\alpha \approx 4.9706257595442318644` satisfies `\alpha (\log \alpha - 1) = 3`. The third series is taken up to `k = 2n-1` inclusive. With these parameters, it is shown in [BJ2013]_ that the error is bounded by `24e^{-8n}`. Catalan's constant ------------------------------------------------------------------------------- Catalan's constant is computed using the hypergeometric series .. math:: C = \frac{1}{768} \sum_{k=1}^{\infty} \frac{(-4096)^k P(k)} {k^3 (2k-1)(3k-1)(3k-2)(6k-1)(6k-5) {5k \choose k} {10k \choose 5k} {12k \choose 6k}} where .. math:: \begin{matrix} P(k) & = -43203456k^6 + 92809152k^5 - 76613904k^4 \\ & + 30494304k^3 - 6004944k^2 + 536620^k - 17325, \end{matrix} discovered by Zuniga [Zun2023]_. It was previously computed using a series given in [PP2010]_. Apery's constant ------------------------------------------------------------------------------- Apery's constant `\zeta(3)` is computed using the hypergeometric series .. math:: \zeta(3) = \frac{1}{48} \sum_{k=1}^{\infty} \frac{(-1)^{k-1} P(k)}{k^5 (2k-1)^3(3k-1)(3k-2)(4k-1)(4k-3)(6k-1)(6k-5){5k \choose k}{5k \choose 2k}{9k \choose 4k}{10k \choose 5k}{12k \choose 6k}} where .. math:: \begin{matrix} P(k) & = 1565994397644288k^{11} - 6719460725627136k^{10} + 12632254526031264k^9 \\ & - 13684352515879536k^8 + 9451223531851808k^7 - 4348596587040104k^6 \\ & + 1352700034136826k^5 - 282805786014979k^4 + 38721705264979k^3 \\ & - 3292502315430k^2 + 156286859400k - 3143448000, \end{matrix} discovered by Zuniga [Zun2023]_. Khinchin's constant ------------------------------------------------------------------------------- Khinchin's constant `K_0` is computed using the formula .. math:: \log K_0 = \frac{1}{\log 2} \left[ \sum_{k=2}^{N-1} \log \left(\frac{k-1}{k} \right) \log \left(\frac{k+1}{k} \right) + \sum_{n=1}^\infty \frac {\zeta (2n,N)}{n} \sum_{k=1}^{2n-1} \frac{(-1)^{k+1}}{k} \right] where `N \ge 2` is a free parameter that can be used for tuning [BBC1997]_. If the infinite series is truncated after `n = M`, the remainder is smaller in absolute value than .. math:: \sum_{n=M+1}^{\infty} \zeta(2n, N) = \sum_{n=M+1}^{\infty} \sum_{k=0}^{\infty} (k+N)^{-2n} \le \sum_{n=M+1}^{\infty} \left( N^{-2n} + \int_0^{\infty} (t+N)^{-2n} dt \right) = \sum_{n=M+1}^{\infty} \frac{1}{N^{2n}} \left(1 + \frac{N}{2n-1}\right) \le \sum_{n=M+1}^{\infty} \frac{N+1}{N^{2n}} = \frac{1}{N^{2M} (N-1)} \le \frac{1}{N^{2M}}. Thus, for an error of at most `2^{-p}` in the series, it is sufficient to choose `M \ge p / (2 \log_2 N)`. Glaisher's constant ------------------------------------------------------------------------------- Glaisher's constant `A = \exp(1/12 - \zeta'(-1))` is computed directly from this formula. We don't use the reflection formula for the zeta function, as the arithmetic in Euler-Maclaurin summation is faster at `s = -1` than at `s = 2`. Reciprocal Fibonacci constant ------------------------------------------------------------------------------- We use Gosper's series ([Gos1974]_, corrected in [Arn2012]_) .. math:: \sum_{n=1}^{\infty} \frac{1}{F_n} = \sum_{n=0}^{\infty} \frac{(-1)^{n(n-1)/2} (F_{4n+3} + (-1)^n F_{2n+2})}{F_{2n+1} F_{2n+2} L_1 L_3 \cdots L_{2n+1}} where `L_n = 2F_{n-1} + F_n` denotes a Lucas number. The truncation error after `N \ge 1` terms is bounded by `(1 / \phi)^{N^2}`. The series is not of hypergeometric type, but we can evaluate it in quasilinar time using binary splitting; factoring out a multiplicative recurrence for `L_1 L_3 \cdots` allows computing the series as a product of `O(\sqrt{p})` matrices with `O(\sqrt{p})`-bit entries. flint-3.1.3/doc/source/contributing.rst000066400000000000000000000077451461254215100201560ustar00rootroot00000000000000.. _contributing: **Contributing to FLINT** =============================================================================== Code conventions ------------------------------------------------------------------------------- Four steps are needed to add a new function: * Add the function ``module_foo()`` in a new file ``src/module/foo.c``. * Add a corresponding test program in a new file ``src/module/test/t-foo.c``. * Add the function prototype to ``src/module.h``. * Document the function in ``doc/source/module.rst``. The build system takes care of everything else automatically. Test code (see below) can be omitted if ``module_foo()`` is a trivial helper function, but it should at least be tested indirectly via another function in that case. Auxiliary functions needed to implement ``module_foo()`` but which have no use elsewhere should be declared as ``static`` in ``src/module/foo.c``. If ``module_foo()`` is very short, it can be declared inline directly in ``module.h`` with the ``MODULE_INLINE`` macro. Use the following checklist regarding code style: * Try to keep names and function arguments consistent with existing code. * Follow the conventions regarding types, aliasing rules, etc. described in :ref:`issues` and in ``code_conventions.txt``. * Use basic FLINT constants, types and functions: ``FLINT_BITS``, ``flint_malloc``/``flint_free``, ``flint_abort``, ``flint_printf``, etc. * Complex macros should be avoided. * Indentation is four spaces. * Curly braces normally go on a new line. * Binary operators are surrounded by spaces (but parentheses and brackets are not). * Logically distinct chunks of code (variable declarations, initialization, precomputations, the main loop, cleanup, etc.) should be separated by a single blank line. * Lines are up to 79 characters long, but this rule can be broken if it helps readability. * Add correct copyright notices at the top of each file. Test code ------------------------------------------------------------------------------- The easiest way to write a test program for a new function is to adapt the test code for an existing, similar function. Most of the test code in FLINT uses the strategy of computing the same result in two or more different ways (for example, using functional equations, interchanging the order of parameter, or varying the precision and other algorithm parameters) and verifying that the results are consistent. It is also a good idea to test that aliasing works. Input data is usually generated randomly, but in some cases including precomputed reference values also makes sense. Faster test code is better. A single test program should not take more than 1 seconds to run with the default number of iterations, and preferably no more than 0.1 seconds. Most functions can be tested effectively in a few milliseconds. Think of what the corner cases are and try to generate random input biased toward such cases. The ``randtest()`` functions attempt to generate corner cases automatically, but some thought may be needed to use them optimally. Try to ensure that the test code fails if you deliberately break the tested function in any way. It is also a good idea to run the test code once with ``FLINT_TEST_MULTIPLIER=10.0`` or higher. If a function's input space is too large to probe effectively for corner cases with random input, that can be a hint that the function should be split into smaller logical parts that can be tested separately. The test code must complete without errors when run with ``valgrind``. The most common mistake leading to memory corruption or memory leaks is to miss or duplicate an ``init()`` or ``clear()`` call. Check that the ``init()`` and ``clear()`` calls exactly match the variable declarations in each code block, including the test code itself. Profiling code is not needed in most cases, but it is often a good idea to run some benchmarks at least during the initial development of a new feature. The ``TIMEIT_START``/``TIMEIT_STOP`` and ``SHOW_MEMORY_USAGE`` macros in FLINT are useful for quick measurements. flint-3.1.3/doc/source/contributors.rst000066400000000000000000000011421461254215100201650ustar00rootroot00000000000000.. _contributors: **Contributors** =============================================================================== Contributors ------------------------------------------------------------------------------- FLINT has only been possible due to an extraordinary number of high quality contributions from a vast array of people. A complete list of contributors is available on the FLINT website at: https://flintlib.org/authors.html If you believe your name is missing from this list, please contact us immediately on the ``flint-devel`` list. The list is updated at the time of each new release of FLINT. flint-3.1.3/doc/source/d_mat.rst000066400000000000000000000070311461254215100165170ustar00rootroot00000000000000.. _d-mat: **d_mat.h** -- double precision matrices =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: void d_mat_init(d_mat_t mat, slong rows, slong cols) Initialises a matrix with the given number of rows and columns for use. .. function:: void d_mat_clear(d_mat_t mat) Clears the given matrix. Basic assignment and manipulation -------------------------------------------------------------------------------- .. function:: void d_mat_set(d_mat_t mat1, const d_mat_t mat2) Sets ``mat1`` to a copy of ``mat2``. The dimensions of ``mat1`` and ``mat2`` must be the same. .. function:: void d_mat_swap_entrywise(d_mat_t mat1, d_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: double d_mat_entry(d_mat_t mat, slong i, slong j) Returns the entry of ``mat`` at row `i` and column `j`. Both `i` and `j` must not exceed the dimensions of the matrix. This function is implemented as a macro. .. function:: double d_mat_get_entry(const d_mat_t mat, slong i, slong j) Returns the entry of ``mat`` at row `i` and column `j`. Both `i` and `j` must not exceed the dimensions of the matrix. .. function:: double * d_mat_entry_ptr(const d_mat_t mat, slong i, slong j) Returns a pointer to the entry of ``mat`` at row `i` and column `j`. Both `i` and `j` must not exceed the dimensions of the matrix. .. function:: void d_mat_zero(d_mat_t mat) Sets all entries of ``mat`` to 0. Random matrix generation -------------------------------------------------------------------------------- .. function:: void d_mat_randtest(d_mat_t mat, flint_rand_t state, slong minexp, slong maxexp) Sets the entries of ``mat`` to random signed numbers with exponents between ``minexp`` and ``maxexp`` or zero. Input and output -------------------------------------------------------------------------------- .. function:: void d_mat_print(const d_mat_t mat) Prints the given matrix to the stream ``stdout``. Comparison -------------------------------------------------------------------------------- .. function:: int d_mat_equal(const d_mat_t mat1, const d_mat_t mat2) Returns a non-zero value if ``mat1`` and ``mat2`` have the same dimensions and entries, and zero otherwise. .. function:: int d_mat_approx_equal(const d_mat_t mat1, const d_mat_t mat2, double eps) Returns a non-zero value if ``mat1`` and ``mat2`` have the same dimensions and entries within ``eps`` of each other, and zero otherwise. .. function:: int d_mat_is_square(const d_mat_t mat) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. Transpose -------------------------------------------------------------------------------- .. function:: void d_mat_transpose(d_mat_t B, const d_mat_t A) Sets `B` to `A^T`, the transpose of `A`. Dimensions must be compatible. `A` and `B` are allowed to be the same object if `A` is a square matrix. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void d_mat_mul_classical(d_mat_t C, const d_mat_t A, const d_mat_t B) Sets ``C`` to the matrix product `C = A B`. The matrices must have compatible dimensions for matrix multiplication (an exception is raised otherwise). Aliasing is allowed. flint-3.1.3/doc/source/d_vec.rst000066400000000000000000000075471461254215100165270ustar00rootroot00000000000000.. _d-vec: **d_vec.h** -- double precision vectors =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: double * _d_vec_init(slong len) Returns an initialised vector of ``double``\s of given length. The entries are not zeroed. .. function:: void _d_vec_clear(double * vec) Frees the space allocated for ``vec``. Randomisation -------------------------------------------------------------------------------- .. function:: void _d_vec_randtest(double * f, flint_rand_t state, slong len, slong minexp, slong maxexp) Sets the entries of a vector of the given length to random signed numbers with exponents between ``minexp`` and ``maxexp`` or zero. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _d_vec_set(double * vec1, const double * vec2, slong len2) Makes a copy of ``(vec2, len2)`` into ``vec1``. .. function:: void _d_vec_zero(double * vec, slong len) Zeros the entries of ``(vec, len)``. Comparison -------------------------------------------------------------------------------- .. function:: int _d_vec_equal(const double * vec1, const double * vec2, slong len) Compares two vectors of the given length and returns `1` if they are equal, otherwise returns `0`. .. function:: int _d_vec_is_zero(const double * vec, slong len) Returns `1` if ``(vec, len)`` is zero, and `0` otherwise. .. function:: int _d_vec_is_approx_zero(const double * vec, slong len, double eps) Returns `1` if the entries of ``(vec, len)`` are zero to within ``eps``, and `0` otherwise. .. function:: int _d_vec_approx_equal(const double * vec1, const double * vec2, slong len, double eps) Compares two vectors of the given length and returns `1` if their entries are within ``eps`` of each other, otherwise returns `0`. Arithmetic -------------------------------------------------------------------------------- .. function:: void _d_vec_add(double * res, const double * vec1, const double * vec2, slong len2) Sets ``(res, len2)`` to the sum of ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _d_vec_sub(double * res, const double * vec1, const double * vec2, slong len2) Sets ``(res, len2)`` to ``(vec1, len2)`` minus ``(vec2, len2)``. .. function:: void _d_vec_mul_2exp(double * res, const double * vec, slong len, int e) Sets ``(res, len)`` to ``(vec, len)`` multiplied by `2^e`. Dot product and norm -------------------------------------------------------------------------------- .. function:: double _d_vec_dot(const double * vec1, const double * vec2, slong len2) Returns the dot product of ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: double _d_vec_norm(const double * vec, slong len) Returns the square of the Euclidean norm of ``(vec, len)``. .. function:: double _d_vec_dot_heuristic(const double * vec1, const double * vec2, slong len2, double * err) Returns the dot product of ``(vec1, len2)`` and ``(vec2, len2)`` by adding up the positive and negative products, and doing a single subtraction of the two sums at the end. ``err`` is a pointer to a double in which an error bound for the operation will be stored. .. function:: double _d_vec_dot_thrice(const double * vec1, const double * vec2, slong len2, double * err) Returns the dot product of ``(vec1, len2)`` and ``(vec2, len2)`` using error-free floating point sums and products to compute the dot product with three times (thrice) the working precision. ``err`` is a pointer to a double in which an error bound for the operation will be stored. This implements the algorithm of Ogita-Rump-Oishi. See http://www.ti3.tuhh.de/paper/rump/OgRuOi05.pdf. flint-3.1.3/doc/source/dirichlet.rst000066400000000000000000000270371461254215100174120ustar00rootroot00000000000000.. _dirichlet: **dirichlet.h** -- Dirichlet characters =================================================================================== *Warning: the interfaces in this module are experimental and may change without notice.* This module allows working with Dirichlet characters algebraically. For evaluations of characters as complex numbers, see :ref:`acb-dirichlet`. Dirichlet characters ------------------------------------------------------------------------------- Working with Dirichlet characters mod *q* consists mainly in going from residue classes mod *q* to exponents on a set of generators of the group. This implementation relies on the Conrey numbering scheme introduced in the `L-functions and Modular Forms DataBase `_, which is an explicit choice of generators allowing to represent Dirichlet characters via the pairing .. math:: \begin{array}{ccccc} (\mathbb Z/q\mathbb Z)^\times \times (\mathbb Z/q\mathbb Z)^\times & \to & \bigoplus_i \mathbb Z/\phi_i\mathbb Z \times \mathbb Z/\phi_i\mathbb Z & \to &\mathbb C \\ (m,n) & \mapsto& (a_i,b_i) &\mapsto& \chi_q(m,n) = \exp(2i\pi\sum \frac{a_ib_i}{\phi_i} ) \end{array} We call *number* a residue class `m` modulo *q*, and *log* the corresponding vector `(a_i)` of exponents of Conrey generators. Going from a *log* to the corresponding *number* is a cheap operation we call exponential, while the converse requires computing discrete logarithms. Multiplicative group modulo *q* ------------------------------------------------------------------------------- .. type:: dirichlet_group_struct .. type:: dirichlet_group_t Represents the group of Dirichlet characters mod *q*. An *dirichlet_group_t* is defined as an array of *dirichlet_group_struct* of length 1, permitting it to be passed by reference. .. function:: int dirichlet_group_init(dirichlet_group_t G, ulong q) Initializes *G* to the group of Dirichlet characters mod *q*. This method computes a canonical decomposition of *G* in terms of cyclic groups, which are the mod `p^e` subgroups for `p^e\|q`, plus the specific generator described by Conrey for each subgroup. In particular *G* contains: - the number *num* of components - the generators - the exponent *expo* of the group It does *not* automatically precompute lookup tables of discrete logarithms or numerical roots of unity, and can therefore safely be called even with large *q*. For implementation reasons, the largest prime factor of *q* must not exceed `10^{16}`. This restriction could be removed in the future. The function returns 1 on success and 0 if a factor is too large. .. function:: void dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h) Given an already computed group *G* mod `q`, initialize its subgroup *H* defined mod `h\mid q`. Precomputed discrete log tables are inherited. .. function:: void dirichlet_group_clear(dirichlet_group_t G) Clears *G*. Remark this function does *not* clear the discrete logarithm tables stored in *G* (which may be shared with another group). .. function:: ulong dirichlet_group_size(const dirichlet_group_t G) Returns the number of elements in *G*, i.e. `\varphi(q)`. .. function:: ulong dirichlet_group_num_primitive(const dirichlet_group_t G) Returns the number of primitive elements in *G*. .. function:: void dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num) Precompute decomposition and tables for discrete log computations in *G*, so as to minimize the complexity of *num* calls to discrete logarithms. If *num* gets very large, the entire group may be indexed. .. function:: void dirichlet_group_dlog_clear(dirichlet_group_t G) Clear discrete logarithm tables in *G*. When discrete logarithm tables are shared with subgroups, those subgroups must be cleared before clearing the tables. Character type ------------------------------------------------------------------------------- .. type:: dirichlet_char_struct .. type:: dirichlet_char_t Represents a Dirichlet character. This structure contains both a *number* (residue class) and the corresponding *log* (exponents on the group generators). An *dirichlet_char_t* is defined as an array of *dirichlet_char_struct* of length 1, permitting it to be passed by reference. .. function:: void dirichlet_char_init(dirichlet_char_t chi, const dirichlet_group_t G) Initializes *chi* to an element of the group *G* and sets its value to the principal character. .. function:: void dirichlet_char_clear(dirichlet_char_t chi) Clears *chi*. .. function:: void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t chi) Prints the array of exponents representing this character. .. function:: void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m) Sets *x* to the character of number *m*, computing its log using discrete logarithm in *G*. .. function:: ulong dirichlet_char_exp(const dirichlet_group_t G, const dirichlet_char_t x) Returns the number *m* corresponding to exponents in *x*. .. function:: ulong _dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G) Computes and returns the number *m* corresponding to exponents in *x*. This function is for internal use. .. function:: void dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G) Sets *x* to the principal character in *G*, having *log* `[0,\dots 0]`. .. function:: void dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G) Sets *x* to the first primitive character of *G*, having *log* `[1,\dots 1]`, or `[0, 1, \dots 1]` if `8\mid q`. .. function:: void dirichlet_char_set(dirichlet_char_t x, const dirichlet_group_t G, const dirichlet_char_t y) Sets *x* to the element *y*. .. function:: int dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G) Sets *x* to the next character in *G* according to lexicographic ordering of *log*. The return value is the index of the last updated exponent of *x*, or *-1* if the last element has been reached. This function allows to iterate on all elements of *G* looping on their *log*. Note that it produces elements in seemingly random *number* order. The following template can be used for such a loop:: dirichlet_char_one(chi, G); do { /* use character chi */ } while (dirichlet_char_next(chi, G) >= 0); .. function:: int dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G) Same as :func:`dirichlet_char_next`, but jumps to the next primitive character of *G*. .. function:: ulong dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x) Returns the lexicographic index of the *log* of *x* as an integer in `0\dots \varphi(q)`. .. function:: void dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j) Sets *x* to the character whose *log* has lexicographic index *j*. .. function:: int dirichlet_char_eq(const dirichlet_char_t x, const dirichlet_char_t y) .. function:: int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y) Return 1 if *x* equals *y*. The second version checks every byte of the representation and is intended for testing only. Character properties ------------------------------------------------------------------------------- As a consequence of the Conrey numbering, all these numbers are available at the level of *number* and *char* object. Both case require no discrete log computation. .. function:: int dirichlet_char_is_principal(const dirichlet_group_t G, const dirichlet_char_t chi) Returns 1 if *chi* is the principal character mod *q*. .. function:: ulong dirichlet_conductor_ui(const dirichlet_group_t G, ulong a) .. function:: ulong dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x) Returns the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` such `\chi_q(a,\cdot)` can be obtained as a character mod `r`. .. function:: int dirichlet_parity_ui(const dirichlet_group_t G, ulong a) .. function:: int dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x) Returns the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that `\chi_q(a,-1)=(-1)^\lambda`. .. function:: ulong dirichlet_order_ui(const dirichlet_group_t G, ulong a) .. function:: ulong dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x) Returns the order of `\chi_q(a,\cdot)` which is the order of `a\bmod q`. .. function:: int dirichlet_char_is_real(const dirichlet_group_t G, const dirichlet_char_t chi) Returns 1 if *chi* is a real character (iff it has order `\leq 2`). .. function:: int dirichlet_char_is_primitive(const dirichlet_group_t G, const dirichlet_char_t chi) Returns 1 if *chi* is primitive (iff its conductor is exactly *q*). Character evaluation ------------------------------------------------------------------------------- Dirichlet characters take value in a finite cyclic group of roots of unity plus zero. Evaluation functions return a *ulong*, this number corresponds to the power of a primitive root of unity, the special value *DIRICHLET_CHI_NULL* encoding the zero value. .. function:: ulong dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n) .. function:: ulong dirichlet_pairing_char(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_char_t psi) Compute the value of the Dirichlet pairing on numbers *m* and *n*, as exponent modulo *G->expo*. The *char* variant takes as input two characters, so that no discrete logarithm is computed. The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. .. function:: ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) Compute the value `\chi(n)` as the exponent modulo *G->expo*. .. function:: void dirichlet_chi_vec(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) Compute the list of exponent values *v[k]* for `0\leq k < nv`, as exponents modulo *G->expo*. .. function:: void dirichlet_chi_vec_order(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) Compute the list of exponent values *v[k]* for `0\leq k < nv`, as exponents modulo *order*, which is assumed to be a multiple of the order of *chi*. Character operations ------------------------------------------------------------------------------- .. function:: void dirichlet_char_mul(dirichlet_char_t chi12, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) Multiply two characters of the same group *G*. .. function:: void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n) Take the power of a character. .. function:: void dirichlet_char_lift(dirichlet_char_t chi_G, const dirichlet_group_t G, const dirichlet_char_t chi_H, const dirichlet_group_t H) If *H* is a subgroup of *G*, computes the character in *G* corresponding to *chi_H* in *H*. .. function:: void dirichlet_char_lower(dirichlet_char_t chi_H, const dirichlet_group_t H, const dirichlet_char_t chi_G, const dirichlet_group_t G) If *chi_G* is a character of *G* which factors through *H*, sets *chi_H* to the corresponding restriction in *H*. This requires `c(\chi_G)\mid q_H\mid q_G`, where `c(\chi_G)` is the conductor of `\chi_G` and `q_G, q_H` are the moduli of G and H. flint-3.1.3/doc/source/dlog.rst000066400000000000000000000244141461254215100163640ustar00rootroot00000000000000.. _dlog: **dlog.h** -- discrete logarithms mod ulong primes =============================================================================== This module implements discrete logarithms, with the application to Dirichlet characters in mind. In particular, this module defines a :type:`dlog_precomp_t` structure permitting to describe a discrete log problem in some subgroup of `(\mathbb Z/p^e \mathbb Z)^\times` for primepower moduli `p^e`, and store precomputed data for faster computation of several such discrete logarithms. When initializing this data, the user provides both a group description and the expected number of subsequent discrete logarithms calls. The choice of algorithm and the amount of stored data depend both on the structure of the group and this number. No particular effort has been made towards single discrete logarithm computation. Currently only machine size primepower moduli are supported. Types, macros and constants ------------------------------------------------------------------------------- .. macro:: DLOG_NONE Return value when the discrete logarithm does not exist .. type:: dlog_precomp_struct .. type:: dlog_precomp_t Structure for discrete logarithm precomputed data. A :type:`dlog_precomp_t` is defined as an array of length one of type :type:`dlog_precomp_struct`, permitting a :type:`dlog_precomp_t` to be passed by reference. Single evaluation ------------------------------------------------------------------------------- .. function:: ulong dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) Return `x` such that `b = a^x` in `(\mathbb Z/mod \mathbb Z)^\times`, where *a* is known to have order *n*. Precomputations ------------------------------------------------------------------------------- .. function:: void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) Precompute data for *num* discrete logarithms evaluations in the subgroup generated by *a* modulo *mod*, where *a* is known to have order *n*. .. function:: ulong dlog_precomp(const dlog_precomp_t pre, ulong b) Return `\log(b)` for the group described in *pre*. .. function:: void dlog_precomp_clear(dlog_precomp_t pre) Clears *t*. Specialized versions of :func:`dlog_precomp_n_init` are available when specific information is known about the group: .. function:: void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) Assume that *a* generates the group of residues modulo *pe* equal `p^e` for prime *p*. .. function:: void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) Assume that *a* has prime order *p*. .. function:: void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) Assume that *a* has primepower order *pe* `p^e`. .. function:: void dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) Make a complete lookup table of size *n*. If *mod* is small, this is done using an element-indexed array (see :type:`dlog_table_t`), otherwise with a sorted array allowing binary search. Vector evaluations ------------------------------------------------------------------------------- These functions compute all logarithms of successive integers `1\dots n`. .. function:: void dlog_vec_fill(ulong * v, ulong nv, ulong x) Sets values *v[k]* to *x* for all *k* less than *nv*. .. function:: void dlog_vec_set_not_found(ulong * v, ulong nv, nmod_t mod) Sets values *v[k]* to :macro:`DLOG_NONE` for all *k* not coprime to *mod*. .. function:: void dlog_vec(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) Sets *v[k]* to `\log(k,a)` times value *va* for `0\leq k < nv`, where *a* has order *na*. *va* should be *1* for usual log computation. .. function:: void dlog_vec_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) Same parameters as before, but adds `\log(k,a)\times v_a` to *v[k]* and reduce modulo *order* instead of replacing the value. Indices *k* such that *v[k]* equals *DLOG_NONE* are ignored. Depending on the relative size of *nv* and *na*, these two *dlog_vec* functions call one of the following functions. .. function:: void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) .. function:: void dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) Perform a complete loop of size *na* on powers of *a* to fill the logarithm values, discarding powers outside the bounds of *v*. This requires no discrete logarithm computation. .. function:: void dlog_vec_eratos(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) .. function:: void dlog_vec_eratos_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) Compute discrete logarithms of prime numbers less than *nv* and propagate to composite numbers. .. function:: void dlog_vec_sieve_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) .. function:: void dlog_vec_sieve(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) Compute the discrete logarithms of the first few prime numbers, then use them as a factor base to obtain the logarithms of larger primes by sieving techniques. In the the present implementation, the full index-calculus method is not implemented. Internal discrete logarithm strategies ------------------------------------------------------------------------------- Several discrete logarithms strategies are implemented: - Complete lookup table for small groups. - Baby-step giant-step table. combined with mathematical reductions: - Pohlig-Hellman decomposition (Chinese remainder decomposition on the order of the group and base `p` decomposition for primepower order). - p-adic log for primepower modulus `p^e`. The *dlog_precomp* structure makes recursive use of the following method-specific structures. Complete table ............................................................................... .. type:: dlog_table_struct .. type:: dlog_table_t Structure for complete lookup table. .. function:: ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod) Initialize a table of powers of *a* modulo *mod*, storing all elements in an array of size *mod*. .. function:: void dlog_table_clear(dlog_table_t t) Clears *t*. .. function:: ulong dlog_table(const dlog_table_t t, ulong b) Return `\log(b,a)` using the precomputed data *t*. Baby-step giant-step table ............................................................................... .. type:: dlog_bsgs_struct .. type:: dlog_bsgs_t Structure for Baby-Step Giant-Step decomposition. .. function:: ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) Initialize *t* and store the first *m* powers of *a* in a sorted array. The return value is a rought measure of the cost of each logarithm using this table. The user should take `m\approx\sqrt{kn}` to compute k logarithms in a group of size n. .. function:: void dlog_bsgs_clear(dlog_bsgs_t t) Clears *t*. .. function:: ulong dlog_bsgs(const dlog_bsgs_t t, ulong b) Return `\log(b,a)` using the precomputed data *t*. Prime-power modulus decomposition ............................................................................... .. type:: dlog_modpe_struct .. type:: dlog_modpe_t Structure for discrete logarithm modulo primepower `p^e`. A :type:`dlog_modpe_t` is defined as an array of length one of type :type:`dlog_modpe_struct`, permitting a :type:`dlog_modpe_t` to be passed by reference. .. function:: ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) .. function:: void dlog_modpe_clear(dlog_modpe_t t) Clears *t*. .. function:: ulong dlog_modpe(const dlog_modpe_t t, ulong b) Return `\log(b,a)` using the precomputed data *t*. CRT decomposition ............................................................................... .. type:: dlog_crt_struct .. type:: dlog_crt_t Structure for discrete logarithm for groups of composite order. A :type:`dlog_crt_t` is defined as an array of length one of type :type:`dlog_crt_struct`, permitting a :type:`dlog_crt_t` to be passed by reference. .. function:: ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) Precompute data for *num* evaluations of discrete logarithms in base *a* modulo *mod*, where *a* has composite order *n*, using chinese remainder decomposition. .. function:: void dlog_crt_clear(dlog_crt_t t) Clears *t*. .. function:: ulong dlog_crt(const dlog_crt_t t, ulong b) Return `\log(b,a)` using the precomputed data *t*. padic decomposition ............................................................................... .. type:: dlog_power_struct .. type:: dlog_power_t Structure for discrete logarithm for groups of primepower order. A :type:`dlog_power_t` is defined as an array of length one of type :type:`dlog_power_struct`, permitting a :type:`dlog_power_t` to be passed by reference. .. function:: ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) Precompute data for *num* evaluations of discrete logarithms in base *a* modulo *mod*, where *a* has prime power order *pe* equals `p^e`, using decomposition in base *p*. .. function:: void dlog_power_clear(dlog_power_t t) Clears *t*. .. function:: ulong dlog_power(const dlog_power_t t, ulong b) Return `\log(b,a)` using the precomputed data *t*. Pollard rho method ............................................................................... .. type:: dlog_rho_struct .. type:: dlog_rho_t Structure for discrete logarithm using Pollard rho. A :type:`dlog_rho_t` is defined as an array of length one of type :type:`dlog_rho_struct`, permitting a :type:`dlog_rho_t` to be passed by reference. .. function:: void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) Initialize random walks for evaluations of discrete logarithms in base *a* modulo *mod*, where *a* has order *n*. .. function:: void dlog_rho_clear(dlog_rho_t t) Clears *t*. .. function:: ulong dlog_rho(const dlog_rho_t t, ulong b) Return `\log(b,a)` by the rho method in the group described by *t*. flint-3.1.3/doc/source/double_extras.rst000066400000000000000000000053331461254215100202760ustar00rootroot00000000000000.. _double-extras: **double_extras.h** -- support functions for double arithmetic =============================================================================== Random functions -------------------------------------------------------------------------------- .. function:: double d_randtest(flint_rand_t state) Returns a random number in the interval `[0.5, 1)`. .. function:: double d_randtest_signed(flint_rand_t state, slong minexp, slong maxexp) Returns a random signed number with exponent between ``minexp`` and ``maxexp`` or zero. .. function:: double d_randtest_special(flint_rand_t state, slong minexp, slong maxexp) Returns a random signed number with exponent between ``minexp`` and ``maxexp``, zero, ``D_NAN`` or `\pm`\ ``D_INF``. Arithmetic -------------------------------------------------------------------------------- .. function:: double d_polyval(const double * poly, int len, double x) Uses Horner's rule to evaluate the polynomial defined by the given ``len`` coefficients. Requires that ``len`` is nonzero. .. function:: double d_mul_2exp_inrange(double x, int i) double d_mul_2exp_inrange2(double x, int i) double d_mul_2exp(double x, int i) Returns `x \cdot 2^i`. The *inrange* version requires that `2^i` is in the normal exponent range. The *inrange2* version additionally requires that both `x` and `x \cdot 2^i` are in the normal exponent range, and in particular also assumes that `x \ne 0`. Special functions -------------------------------------------------------------------------------- .. function:: double d_lambertw(double x) Computes the principal branch of the Lambert W function, solving the equation `x = W(x) \exp(W(x))`. If `x < -1/e`, the solution is complex, and NaN is returned. Depending on the magnitude of `x`, we start from a piecewise rational approximation or a zeroth-order truncation of the asymptotic expansion at infinity, and perform 0, 1 or 2 iterations with Halley's method to obtain full accuracy. A test of `10^7` random inputs showed a maximum relative error smaller than 0.95 times ``DBL_EPSILON`` (`2^{-52}`) for positive `x`. Accuracy for negative `x` is slightly worse, and can grow to about 10 times ``DBL_EPSILON`` close to `-1/e`. However, accuracy may be worse depending on compiler flags and the accuracy of the system libm functions. .. function:: int d_is_nan(double x) Returns a nonzero integral value if ``x`` is ``D_NAN``, and otherwise returns 0. .. function:: double d_log2(double x) Returns the base 2 logarithm of ``x`` provided ``x`` is positive. If a domain or pole error occurs, the appropriate error value is returned. flint-3.1.3/doc/source/double_interval.rst000066400000000000000000000061351461254215100206150ustar00rootroot00000000000000.. _double_interval: **double_interval.h** -- double-precision interval arithmetic and helpers =============================================================================== This module provides helper functions for computing fast enclosures using ``double`` arithmetic. Types, macros and constants ------------------------------------------------------------------------------- .. type:: di_t Holds two ``double`` endpoints ``a`` and ``b`` representing the extended real interval `[a, b]`. We generally assume that `a \le b` and that neither endpoint is NaN. Basic manipulation ------------------------------------------------------------------------------- .. function:: di_t di_interval(double a, double b) Returns the interval `[a, b]`. We require that the endpoints are ordered and not NaN. .. function:: di_t arb_get_di(const arb_t x) Returns the ball *x* converted to a double-precision interval. .. function:: void arb_set_di(arb_t res, di_t x, slong prec) Sets the ball *res* to the double-precision interval *x*, rounded to *prec* bits. .. function:: void di_print(di_t x) Prints *x* to standard output. This simply prints decimal representations of the floating-point endpoints; the decimals are not guaranteed to be rounded outward. .. function:: double d_randtest2(flint_rand_t state) Returns a random non-NaN ``double`` with any exponent. The value can be infinite or subnormal. .. function:: di_t di_randtest(flint_rand_t state) Returns an interval with random endpoints. Arithmetic ------------------------------------------------------------------------------- .. function:: di_t di_neg(di_t x) Returns the exact negation of *x*. Fast arithmetic ------------------------------------------------------------------------------- The following methods perform fast but sloppy interval arithmetic: we manipulate the endpoints with default rounding and then add or subtract generic perturbations regardless of whether the operations were exact. It is currently assumed that the CPU rounding mode is to nearest. .. function:: di_t di_fast_add(di_t x, di_t y) di_t di_fast_sub(di_t x, di_t y) di_t di_fast_mul(di_t x, di_t y) di_t di_fast_div(di_t x, di_t y) Returns the sum, difference, product or quotient of *x* and *y*. Division by zero is currently defined to return `[-\infty, +\infty]`. .. function:: di_t di_fast_sqr(di_t x) Returns the square of *x*. The output is clamped to be nonnegative. .. function:: di_t di_fast_add_d(di_t x, double y) di_t di_fast_sub_d(di_t x, double y) di_t di_fast_mul_d(di_t x, double y) di_t di_fast_div_d(di_t x, double y) Arithmetic with an exact ``double`` operand. .. function:: di_t di_fast_log_nonnegative(di_t x) Returns an enclosure of `\log(x)`. The lower endpoint of *x* is rounded up to 0 if it is negative. .. function:: di_t di_fast_mid(di_t x) Returns an enclosure of the midpoint of *x*. .. function:: double di_fast_ubound_radius(di_t x) Returns an upper bound for the radius of *x*. flint-3.1.3/doc/source/examples.rst000066400000000000000000000040321461254215100172470ustar00rootroot00000000000000.. _examples: **Examples** =============================================================================== Example programs ------------------------------------------------------------------------------- FLINT comes with example programs to demonstrate current and future FLINT features. To build the example programs run:: make examples The example programs are built in the ``build/examples`` directory. For Arb and Calcium there are separate example pages :ref:`examples-arb` and :ref:`examples-calcium`. Below are some general examples. - ``partitions`` Demonstrates the partition counting code, e.g. ``build/examples/partitions 1000000000`` will compute the number of partitions of ``10^9``. - ``delta_qexp`` Computes the `n`-th term of the delta function, e.g. ``build/examples/delta_qexp 1000000`` will compute the one million-th term of the `q`-expansion of delta. - ``crt`` Demonstrates the integer Chinese Remainder code, e.g. ``build/examples/crt 10382788`` will build up the given integer from its value mod various primes. - ``multi_crt`` Demonstrates the fast tree version of the integer Chinese Remainder code, e.g. ``build/examples/multi_crt 100493287498239 13`` will build up the given integer from its value mod the given number of primes. - ``stirling_matrix`` Generates Stirling number matrices of the first and second kind and computes their product, which should come out as the identity matrix. The matrices are printed to standard output. For example ``build/examples/stirling_matrix 10`` does this with 10 by 10 matrices. - ``fmpz_poly_factor_zassenhaus`` Demonstrates the factorisation of a small polynomial. A larger polynomial is also provided on disk and a small (obvious) change to the example program will read this file instead of using the hard coded polynomial. - ``padic`` Gives examples of the usage of many functions in the padic module. - ``fmpz_poly_q`` Gives a very simple example of the ``fmpz_poly_q`` module. - ``fmpq_poly`` Gives a very simple example of the ``fmpq_poly`` module. flint-3.1.3/doc/source/examples_arb.rst000066400000000000000000001007621461254215100201020ustar00rootroot00000000000000.. _examples-arb: Arb example programs =============================================================================== .. highlight:: text See :ref:`examples` for general information about example programs. Running:: make examples will compile the programs and place the binaries in ``build/examples``. The examples related to the Arb module are documented below. pi.c ------------------------------------------------------------------------------- This program computes `\pi` to an accuracy of roughly *n* decimal digits by calling the :func:`arb_const_pi` function with a working precision of roughly `n \log_2(10)` bits. Sample output, computing `\pi` to one million digits:: > build/examples/pi 1000000 precision = 3321933 bits... cpu/wall(s): 0.243 0.244 virt/peak/res/peak(MB): 24.46 30.44 8.73 14.42 [3.14159265358979323846{...999959 digits...}42209010610577945815 +/- 1.38e-1000000] The program prints an interval guaranteed to contain `\pi`, and where all displayed digits are correct up to an error of plus or minus one unit in the last place (see :func:`arb_printn`). By default, only the first and last few digits are printed. Pass 0 as a second argument to print all digits (or pass *m* to print *m* + 1 leading and *m* trailing digits, as above with the default *m* = 20). The program can optionally compute various other constants, and can use multiple threads:: > build/examples/pi 1000000 -threads 4 precision = 3321933 bits... cpu/wall(s): 0.265 0.147 virt/peak/res/peak(MB): 241.95 422.15 13.33 17.54 [3.14159265358979323846{...999959 digits...}42209010610577945815 +/- 1.38e-1000000] > build/examples/pi 1000000 -constant e precision = 3321933 bits... cpu/wall(s): 0.09 0.09 virt/peak/res/peak(MB): 25.56 29.19 9.58 13.11 [2.71828182845904523536{...999959 digits...}01379817644769422819 +/- 1.39e-1000000] zeta_zeros.c ------------------------------------------------------------------------------- This program computes one or several consecutive zeros of the Riemann zeta function on the critical line:: > build/examples/zeta_zeros -n 1 -count 10 -digits 30 1 14.1347251417346937904572519836 2 21.0220396387715549926284795939 3 25.0108575801456887632137909926 4 30.4248761258595132103118975306 5 32.9350615877391896906623689641 6 37.5861781588256712572177634807 7 40.9187190121474951873981269146 8 43.3270732809149995194961221654 9 48.0051508811671597279424727494 10 49.7738324776723021819167846786 cpu/wall(s): 0.01 0.01 virt/peak/res/peak(MB): 21.28 21.28 7.29 7.29 Five zeros starting with the millionth:: > build/examples/zeta_zeros -n 1000000 -count 5 -digits 20 1000000 600269.67701244495552 1000001 600270.30109071169866 1000002 600270.74787059436613 1000003 600271.48637367364820 1000004 600271.76148042593778 cpu/wall(s): 0.03 0.03 virt/peak/res/peak(MB): 21.41 21.41 7.41 7.41 The program supports the following options:: zeta_zeros [-n n] [-count n] [-prec n] [-digits n] [-threads n] [-platt] [-noplatt] [-v] [-verbose] [-h] [-help] With ``-platt``, Platt's algorithm is used, which may be faster when computing many zeros of large index simultaneously. bernoulli.c ------------------------------------------------------------------------------- This program benchmarks computing the nth Bernoulli number exactly:: > build/examples/bernoulli 1000000 -threads 8 cpu/wall(s): 27.227 5.836 virt/peak/res/peak(MB): 573.47 731.39 73.23 165.13 class_poly.c ------------------------------------------------------------------------------- This program benchmarks computing Hilbert class polynomials:: > build/examples/class_poly -1000004 -threads 8 cpu/wall(s): 6.932 1.478 virt/peak/res/peak(MB): 535.27 653.18 71.02 100.65 degree = 624, bits = -37823 hilbert_matrix.c ------------------------------------------------------------------------------- Given an input integer *n*, this program accurately computes the determinant of the *n* by *n* Hilbert matrix. Hilbert matrices are notoriously ill-conditioned: although the entries are close to unit magnitude, the determinant `h_n` decreases superexponentially (nearly as `1/4^{n^2}`) as a function of *n*. This program automatically doubles the working precision until the ball computed for `h_n` by :func:`arb_mat_det` does not contain zero. Sample output:: $ build/examples/hilbert_matrix 200 prec=20: [+/- 1.32e-335] prec=40: [+/- 1.63e-545] prec=80: [+/- 1.30e-933] prec=160: [+/- 3.62e-1926] prec=320: [+/- 1.81e-4129] prec=640: [+/- 3.84e-8838] prec=1280: [2.955454297e-23924 +/- 8.29e-23935] success! cpu/wall(s): 8.494 8.513 virt/peak/res/peak(MB): 134.98 134.98 111.57 111.57 Called with ``-eig n``, instead of computing the determinant, the program computes the smallest eigenvalue of the Hilbert matrix (in fact, it isolates all eigenvalues and prints the smallest eigenvalue):: $ build/examples/hilbert_matrix -eig 50 prec=20: nan prec=40: nan prec=80: nan prec=160: nan prec=320: nan prec=640: [1.459157797e-74 +/- 2.49e-84] success! cpu/wall(s): 1.84 1.841 virt/peak/res/peak(MB): 33.97 33.97 10.51 10.51 keiper_li.c ------------------------------------------------------------------------------- Given an input integer *n*, this program rigorously computes numerical values of the Keiper-Li coefficients `\lambda_0, \ldots, \lambda_n`. The Keiper-Li coefficients have the property that `\lambda_n > 0` for all `n > 0` if and only if the Riemann hypothesis is true. This program was used for the record computations described in [Joh2013]_ (the paper describes the algorithm in some more detail). The program takes the following parameters:: keiper_li n [-prec prec] [-threads num_threads] [-out out_file] The program prints the first and last few coefficients. It can optionally write all the computed data to a file. The working precision defaults to a value that should give all the coefficients to a few digits of accuracy, but can optionally be set higher (or lower). On a multicore system, using several threads results in faster execution. Sample output:: > build/examples/keiper_li 1000 -threads 2 zeta: cpu/wall(s): 0.4 0.244 virt/peak/res/peak(MB): 167.98 294.69 5.09 7.43 log: cpu/wall(s): 0.03 0.038 gamma: cpu/wall(s): 0.02 0.016 binomial transform: cpu/wall(s): 0.01 0.018 0: -0.69314718055994530941723212145817656807550013436026 +/- 6.5389e-347 1: 0.023095708966121033814310247906495291621932127152051 +/- 2.0924e-345 2: 0.046172867614023335192864243096033943387066108314123 +/- 1.674e-344 3: 0.0692129735181082679304973488726010689942120263932 +/- 5.0219e-344 4: 0.092197619873060409647627872409439018065541673490213 +/- 2.0089e-343 5: 0.11510854289223549048622128109857276671349132303596 +/- 1.0044e-342 6: 0.13792766871372988290416713700341666356138966078654 +/- 6.0264e-342 7: 0.16063715965299421294040287257385366292282442046163 +/- 2.1092e-341 8: 0.18321945964338257908193931774721859848998098273432 +/- 8.4368e-341 9: 0.20565733870917046170289387421343304741236553410044 +/- 7.5931e-340 10: 0.22793393631931577436930340573684453380748385942738 +/- 7.5931e-339 991: 2.3196617961613367928373899656994682562101430813341 +/- 2.461e-11 992: 2.3203766239254884035349896518332550233162909717288 +/- 9.5363e-11 993: 2.321092061239733282811659116333262802034375592414 +/- 1.8495e-10 994: 2.3218073540188462110258826121503870112747188888893 +/- 3.5907e-10 995: 2.3225217392815185726928702951225314023773358152533 +/- 6.978e-10 996: 2.3232344485814623873333223609413703912358283071281 +/- 1.3574e-09 997: 2.3239447114886014522889542667580382034526509232475 +/- 2.6433e-09 998: 2.3246517591032700808344143240352605148856869322209 +/- 5.1524e-09 999: 2.3253548275861382119812576052060526988544993162101 +/- 1.0053e-08 1000: 2.3260531616864664574065046940832238158044982041872 +/- 3.927e-08 virt/peak/res/peak(MB): 170.18 294.69 7.51 7.51 logistic.c ------------------------------------------------------------------------------- This program computes the *n*-th iterate of the logistic map defined by `x_{n+1} = r x_n (1 - x_n)` where `r` and `x_0` are given. It takes the following parameters:: logistic n [x_0] [r] [digits] The inputs `x_0`, *r* and *digits* default to 0.5, 3.75 and 10 respectively. The computation is automatically restarted with doubled precision until the result is accurate to *digits* decimal digits. Sample output:: > build/examples/logistic 10 Trying prec=64 bits...success! cpu/wall(s): 0 0.001 x_10 = [0.6453672908 +/- 3.10e-11] > build/examples/logistic 100 Trying prec=64 bits...ran out of accuracy at step 18 Trying prec=128 bits...ran out of accuracy at step 53 Trying prec=256 bits...success! cpu/wall(s): 0 0 x_100 = [0.8882939923 +/- 1.60e-11] > build/examples/logistic 10000 Trying prec=64 bits...ran out of accuracy at step 18 Trying prec=128 bits...ran out of accuracy at step 53 Trying prec=256 bits...ran out of accuracy at step 121 Trying prec=512 bits...ran out of accuracy at step 256 Trying prec=1024 bits...ran out of accuracy at step 525 Trying prec=2048 bits...ran out of accuracy at step 1063 Trying prec=4096 bits...ran out of accuracy at step 2139 Trying prec=8192 bits...ran out of accuracy at step 4288 Trying prec=16384 bits...ran out of accuracy at step 8584 Trying prec=32768 bits...success! cpu/wall(s): 0.859 0.858 x_10000 = [0.8242048008 +/- 4.35e-11] > build/examples/logistic 1234 0.1 3.99 30 Trying prec=64 bits...ran out of accuracy at step 0 Trying prec=128 bits...ran out of accuracy at step 10 Trying prec=256 bits...ran out of accuracy at step 76 Trying prec=512 bits...ran out of accuracy at step 205 Trying prec=1024 bits...ran out of accuracy at step 461 Trying prec=2048 bits...ran out of accuracy at step 974 Trying prec=4096 bits...success! cpu/wall(s): 0.009 0.009 x_1234 = [0.256445391958651410579677945635 +/- 3.92e-31] real_roots.c ------------------------------------------------------------------------------- This program isolates the roots of a function on the interval `(a,b)` (where *a* and *b* are input as double-precision literals) using the routines in the :ref:`arb_calc ` module. The program takes the following arguments:: real_roots function a b [-refine d] [-verbose] [-maxdepth n] [-maxeval n] [-maxfound n] [-prec n] The following functions (specified by an integer code) are implemented: * 0 - `Z(x)` (Riemann-Siegel Z-function) * 1 - `\sin(x)` * 2 - `\sin(x^2)` * 3 - `\sin(1/x)` * 4 - `\operatorname{Ai}(x)` (Airy function) * 5 - `\operatorname{Ai}'(x)` (Airy function) * 6 - `\operatorname{Bi}(x)` (Airy function) * 7 - `\operatorname{Bi}'(x)` (Airy function) The following options are available: * ``-refine d``: If provided, after isolating the roots, attempt to refine the roots to *d* digits of accuracy using a few bisection steps followed by Newton's method with adaptive precision, and then print them. * ``-verbose``: Print more information. * ``-maxdepth n``: Stop searching after *n* recursive subdivisions. * ``-maxeval n``: Stop searching after approximately *n* function evaluations (the actual number evaluations will be a small multiple of this). * ``-maxfound n``: Stop searching after having found *n* isolated roots. * ``-prec n``: Working precision to use for the root isolation. With *function* 0, the program isolates roots of the Riemann zeta function on the critical line, and guarantees that no roots are missed (see `zeta_zeros.c` for a far more efficient way to do this):: > build/examples/real_roots 0 0.0 50.0 -verbose interval: [0, 50] maxdepth = 30, maxeval = 100000, maxfound = 100000, low_prec = 30 found isolated root in: [14.111328125, 14.16015625] found isolated root in: [20.99609375, 21.044921875] found isolated root in: [25, 25.048828125] found isolated root in: [30.419921875, 30.4443359375] found isolated root in: [32.91015625, 32.958984375] found isolated root in: [37.548828125, 37.59765625] found isolated root in: [40.91796875, 40.966796875] found isolated root in: [43.310546875, 43.3349609375] found isolated root in: [47.998046875, 48.0224609375] found isolated root in: [49.755859375, 49.7802734375] --------------------------------------------------------------- Found roots: 10 Subintervals possibly containing undetected roots: 0 Function evaluations: 3058 cpu/wall(s): 0.202 0.202 virt/peak/res/peak(MB): 26.12 26.14 2.76 2.76 Find just one root and refine it to approximately 75 digits:: > build/examples/real_roots 0 0.0 50.0 -maxfound 1 -refine 75 interval: [0, 50] maxdepth = 30, maxeval = 100000, maxfound = 1, low_prec = 30 refined root (0/8): [14.134725141734693790457251983562470270784257115699243175685567460149963429809 +/- 2.57e-76] --------------------------------------------------------------- Found roots: 1 Subintervals possibly containing undetected roots: 7 Function evaluations: 761 cpu/wall(s): 0.055 0.056 virt/peak/res/peak(MB): 26.12 26.14 2.75 2.75 Find the first few roots of an Airy function and refine them to 50 digits each:: > build/examples/real_roots 4 -10 0 -refine 50 interval: [-10, 0] maxdepth = 30, maxeval = 100000, maxfound = 100000, low_prec = 30 refined root (0/6): [-9.022650853340980380158190839880089256524677535156083 +/- 4.85e-52] refined root (1/6): [-7.944133587120853123138280555798268532140674396972215 +/- 1.92e-52] refined root (2/6): [-6.786708090071758998780246384496176966053882477393494 +/- 3.84e-52] refined root (3/6): [-5.520559828095551059129855512931293573797214280617525 +/- 1.05e-52] refined root (4/6): [-4.087949444130970616636988701457391060224764699108530 +/- 2.46e-52] refined root (5/6): [-2.338107410459767038489197252446735440638540145672388 +/- 1.48e-52] --------------------------------------------------------------- Found roots: 6 Subintervals possibly containing undetected roots: 0 Function evaluations: 200 cpu/wall(s): 0.003 0.003 virt/peak/res/peak(MB): 26.12 26.14 2.24 2.24 Find roots of `\sin(x^2)` on `(0,100)`. The algorithm cannot isolate the root at `x = 0` (it is at the endpoint of the interval, and in any case a root of multiplicity higher than one). The failure is reported:: > build/examples/real_roots 2 0 100 interval: [0, 100] maxdepth = 30, maxeval = 100000, maxfound = 100000, low_prec = 30 --------------------------------------------------------------- Found roots: 3183 Subintervals possibly containing undetected roots: 1 Function evaluations: 34058 cpu/wall(s): 0.032 0.032 virt/peak/res/peak(MB): 26.32 26.37 2.04 2.04 This does not miss any roots:: > build/examples/real_roots 2 1 100 interval: [1, 100] maxdepth = 30, maxeval = 100000, maxfound = 100000, low_prec = 30 --------------------------------------------------------------- Found roots: 3183 Subintervals possibly containing undetected roots: 0 Function evaluations: 34039 cpu/wall(s): 0.023 0.023 virt/peak/res/peak(MB): 26.32 26.37 2.01 2.01 Looking for roots of `\sin(1/x)` on `(0,1)`, the algorithm finds many roots, but will never find all of them since there are infinitely many:: > build/examples/real_roots 3 0.0 1.0 interval: [0, 1] maxdepth = 30, maxeval = 100000, maxfound = 100000, low_prec = 30 --------------------------------------------------------------- Found roots: 10198 Subintervals possibly containing undetected roots: 24695 Function evaluations: 202587 cpu/wall(s): 0.171 0.171 virt/peak/res/peak(MB): 28.39 30.38 4.05 4.05 Remark: the program always computes rigorous containing intervals for the roots, but the accuracy after refinement could be less than *d* digits. poly_roots.c ------------------------------------------------------------------------------- This program finds the complex roots of an integer polynomial by calling :func:`arb_fmpz_poly_complex_roots`, which in turn calls :func:`acb_poly_find_roots` with increasing precision until the roots certainly have been isolated. The program takes the following arguments:: poly_roots [-refine d] [-print d] Isolates all the complex roots of a polynomial with integer coefficients. If -refine d is passed, the roots are refined to a relative tolerance better than 10^(-d). By default, the roots are only computed to sufficient accuracy to isolate them. The refinement is not currently done efficiently. If -print d is passed, the computed roots are printed to d decimals. By default, the roots are not printed. The polynomial can be specified by passing the following as : a Easy polynomial 1 + 2x + ... + (n+1)x^n t Chebyshev polynomial T_n u Chebyshev polynomial U_n p Legendre polynomial P_n c Cyclotomic polynomial Phi_n s Swinnerton-Dyer polynomial S_n b Bernoulli polynomial B_n w Wilkinson polynomial W_n e Taylor series of exp(x) truncated to degree n m The Mignotte-like polynomial x^n + (100x+1)^m, n > m coeffs c0 + c1 x + ... + cn x^n Concatenate to multiply polynomials, e.g.: p 5 t 6 coeffs 1 2 3 for P_5(x)*T_6(x)*(1+2x+3x^2) This finds the roots of the Wilkinson polynomial with roots at the positive integers 1, 2, ..., 100:: > build/examples/poly_roots -print 15 w 100 computing squarefree factorization... cpu/wall(s): 0.001 0.001 roots with multiplicity 1 searching for 100 roots, 100 deflated prec=32: 0 isolated roots | cpu/wall(s): 0.098 0.098 prec=64: 0 isolated roots | cpu/wall(s): 0.247 0.247 prec=128: 0 isolated roots | cpu/wall(s): 0.498 0.497 prec=256: 0 isolated roots | cpu/wall(s): 0.713 0.713 prec=512: 100 isolated roots | cpu/wall(s): 0.104 0.105 done! [1.00000000000000 +/- 3e-20] [2.00000000000000 +/- 3e-19] [3.00000000000000 +/- 1e-19] [4.00000000000000 +/- 1e-19] [5.00000000000000 +/- 1e-19] ... [96.0000000000000 +/- 1e-17] [97.0000000000000 +/- 1e-17] [98.0000000000000 +/- 3e-17] [99.0000000000000 +/- 3e-17] [100.000000000000 +/- 3e-17] cpu/wall(s): 1.664 1.664 This finds the roots of a Bernoulli polynomial which has both real and complex roots:: > build/examples/poly_roots -refine 100 -print 20 b 16 computing squarefree factorization... cpu/wall(s): 0.001 0 roots with multiplicity 1 searching for 16 roots, 16 deflated prec=32: 16 isolated roots | cpu/wall(s): 0.006 0.006 prec=64: 16 isolated roots | cpu/wall(s): 0.001 0.001 prec=128: 16 isolated roots | cpu/wall(s): 0.001 0.001 prec=256: 16 isolated roots | cpu/wall(s): 0.001 0.002 prec=512: 16 isolated roots | cpu/wall(s): 0.002 0.001 done! [-0.94308706466055783383 +/- 2.02e-21] [-0.75534059252067985752 +/- 2.70e-21] [-0.24999757119077421009 +/- 4.27e-21] [0.24999757152512726002 +/- 4.43e-21] [0.75000242847487273998 +/- 4.43e-21] [1.2499975711907742101 +/- 1.43e-20] [1.7553405925206798575 +/- 1.74e-20] [1.9430870646605578338 +/- 3.21e-20] [-0.99509334829256233279 +/- 9.42e-22] + [0.44547958157103608805 +/- 3.59e-21]*I [-0.99509334829256233279 +/- 9.42e-22] + [-0.44547958157103608805 +/- 3.59e-21]*I [1.9950933482925623328 +/- 1.10e-20] + [0.44547958157103608805 +/- 3.59e-21]*I [1.9950933482925623328 +/- 1.10e-20] + [-0.44547958157103608805 +/- 3.59e-21]*I [-0.92177327714429290564 +/- 4.68e-21] + [-1.0954360955079385542 +/- 1.71e-21]*I [-0.92177327714429290564 +/- 4.68e-21] + [1.0954360955079385542 +/- 1.71e-21]*I [1.9217732771442929056 +/- 3.54e-20] + [1.0954360955079385542 +/- 1.71e-21]*I [1.9217732771442929056 +/- 3.54e-20] + [-1.0954360955079385542 +/- 1.71e-21]*I cpu/wall(s): 0.011 0.012 Roots are automatically separated by multiplicity by performing an initial squarefree factorization:: > build/examples/poly_roots -print 5 p 5 p 5 t 7 coeffs 1 5 10 10 5 1 computing squarefree factorization... cpu/wall(s): 0 0 roots with multiplicity 1 searching for 6 roots, 3 deflated prec=32: 3 isolated roots | cpu/wall(s): 0 0.001 done! [-0.97493 +/- 2.10e-6] [-0.78183 +/- 1.49e-6] [-0.43388 +/- 3.75e-6] [0.43388 +/- 3.75e-6] [0.78183 +/- 1.49e-6] [0.97493 +/- 2.10e-6] roots with multiplicity 2 searching for 4 roots, 2 deflated prec=32: 2 isolated roots | cpu/wall(s): 0 0 done! [-0.90618 +/- 1.56e-7] [-0.53847 +/- 6.91e-7] [0.53847 +/- 6.91e-7] [0.90618 +/- 1.56e-7] roots with multiplicity 3 searching for 1 roots, 0 deflated prec=32: 0 isolated roots | cpu/wall(s): 0 0 done! 0 roots with multiplicity 5 searching for 1 roots, 1 deflated prec=32: 1 isolated roots | cpu/wall(s): 0 0 done! -1.0000 cpu/wall(s): 0 0.001 zeta_zeros.c ------------------------------------------------------------------------------- This program finds the imaginary parts of consecutive nontrivial zeros of the Riemann zeta function by calling either :func:`acb_dirichlet_hardy_z_zeros` or :func:`acb_dirichlet_platt_local_hardy_z_zeros` depending on the height of the zeros and the number of zeros requested. The program takes the following arguments:: zeta_zeros [-n n] [-count n] [-prec n] [-threads n] [-platt] [-noplatt] [-v] [-verbose] [-h] [-help] > build/examples/zeta_zeros -n 1048449114 -count 2 1048449114 [388858886.0022851217767970582 +/- 7.46e-20] 1048449115 [388858886.0023936897027167201 +/- 7.59e-20] cpu/wall(s): 0.255 0.255 virt/peak/res/peak(MB): 26.77 26.77 7.88 7.88 complex_plot.c ------------------------------------------------------------------------------- This program plots one of the predefined functions over a complex interval `[x_a, x_b] + [y_a, y_b]i` using domain coloring, at a resolution of *xn* times *yn* pixels. The program takes the parameters:: complex_plot [-range xa xb ya yb] [-size xn yn] [-color n] [-threads n] Defaults parameters are `[-10,10] + [-10,10]i` and *xn* = *yn* = 512. A color function can be selected with -color. Valid options are 0 (phase=hue, magnitude=brightness) and 1 (phase only, white-gold-black-blue-white counterclockwise). The output is written to ``arbplot.ppm``. If you have ImageMagick, run ``convert arbplot.ppm arbplot.png`` to get a PNG. Function codes ```` are: * ``gamma`` - Gamma function * ``digamma`` - Digamma function * ``lgamma`` - Logarithmic gamma function * ``zeta`` - Riemann zeta function * ``erf`` - Error function * ``ai`` - Airy function Ai * ``bi`` - Airy function Bi * ``besselj`` - Bessel function `J_0` * ``bessely`` - Bessel function `Y_0` * ``besseli`` - Bessel function `I_0` * ``besselk`` - Bessel function `K_0` * ``modj`` - Modular j-function * ``modeta`` - Dedekind eta function * ``barnesg`` - Barnes G-function * ``agm`` - Arithmetic geometric mean The function is just sampled at point values; no attempt is made to resolve small features by adaptive subsampling. For example, the following plots the Riemann zeta function around a portion of the critical strip with imaginary part between 100 and 140:: > build/examples/complex_plot zeta -range -10 10 100 140 -size 256 512 For parallel computation on a multicore system, use ``-threads n``. lvalue.c ------------------------------------------------------------------------------- This program evaluates Dirichlet L-functions. It takes the following input:: > build/examples/lvalue lvalue [-character q n] [-re a] [-im b] [-prec p] [-z] [-deflate] [-len l] Print value of Dirichlet L-function at s = a+bi. Default a = 0.5, b = 0, p = 53, (q, n) = (1, 0) (Riemann zeta) [-z] - compute Z(s) instead of L(s) [-deflate] - remove singular term at s = 1 [-len l] - compute l terms in Taylor series at s Evaluating the Riemann zeta function and the Dirichlet beta function at `s = 2`:: > build/examples/lvalue -re 2 -prec 128 L(s) = [1.64493406684822643647241516664602518922 +/- 4.37e-39] cpu/wall(s): 0.001 0.001 virt/peak/res/peak(MB): 26.86 26.88 2.05 2.05 > build/examples/lvalue -character 4 3 -re 2 -prec 128 L(s) = [0.91596559417721901505460351493238411077 +/- 7.86e-39] cpu/wall(s): 0.002 0.003 virt/peak/res/peak(MB): 26.86 26.88 2.31 2.31 Evaluating the L-function for character number 101 modulo 1009 at `s = 1/2` and `s = 1`:: > build/examples/lvalue -character 1009 101 L(s) = [-0.459256562383872 +/- 5.24e-16] + [1.346937111206009 +/- 3.03e-16]*I cpu/wall(s): 0.012 0.012 virt/peak/res/peak(MB): 26.86 26.88 2.30 2.30 > build/examples/lvalue -character 1009 101 -re 1 L(s) = [0.657952586112728 +/- 6.02e-16] + [1.004145273214022 +/- 3.10e-16]*I cpu/wall(s): 0.017 0.018 virt/peak/res/peak(MB): 26.86 26.88 2.30 2.30 Computing the first few coefficients in the Laurent series of the Riemann zeta function at `s = 1`:: > build/examples/lvalue -re 1 -deflate -len 8 L(s) = [0.577215664901532861 +/- 5.29e-19] L'(s) = [0.072815845483676725 +/- 2.68e-19] [x^2] L(s+x) = [-0.004845181596436159 +/- 3.87e-19] [x^3] L(s+x) = [-0.000342305736717224 +/- 4.20e-19] [x^4] L(s+x) = [9.6890419394471e-5 +/- 2.40e-19] [x^5] L(s+x) = [-6.6110318108422e-6 +/- 4.51e-20] [x^6] L(s+x) = [-3.316240908753e-7 +/- 3.85e-20] [x^7] L(s+x) = [1.0462094584479e-7 +/- 7.78e-21] cpu/wall(s): 0.003 0.004 virt/peak/res/peak(MB): 26.86 26.88 2.30 2.30 Evaluating the Riemann zeta function near the first nontrivial root:: > build/examples/lvalue -re 0.5 -im 14.134725 L(s) = [1.76743e-8 +/- 1.93e-14] + [-1.110203e-7 +/- 2.84e-14]*I cpu/wall(s): 0.001 0.001 virt/peak/res/peak(MB): 26.86 26.88 2.31 2.31 > build/examples/lvalue -z -re 14.134725 -prec 200 Z(s) = [-1.12418349839417533300111494358128257497862927935658e-7 +/- 4.62e-58] cpu/wall(s): 0.001 0.001 virt/peak/res/peak(MB): 26.86 26.88 2.57 2.57 > build/examples/lvalue -z -re 14.134725 -len 4 Z(s) = [-1.124184e-7 +/- 7.00e-14] Z'(s) = [0.793160414884 +/- 4.09e-13] [x^2] Z(s+x) = [0.065164586492 +/- 5.39e-13] [x^3] Z(s+x) = [-0.020707762705 +/- 5.37e-13] cpu/wall(s): 0.002 0.003 virt/peak/res/peak(MB): 26.86 26.88 2.57 2.57 lcentral.c ------------------------------------------------------------------------------- This program computes the central value `L(1/2)` for each Dirichlet L-function character modulo *q* for each *q* in the range *qmin* to *qmax*. Usage:: > build/examples/lcentral Computes central values (s = 0.5) of Dirichlet L-functions. usage: build/examples/lcentral [--quiet] [--check] [--prec ] qmin qmax The first few values:: > build/examples/lcentral 1 8 3,2: [0.48086755769682862618122006324 +/- 7.35e-30] 4,3: [0.66769145718960917665869092930 +/- 1.62e-30] 5,2: [0.76374788011728687822451215264 +/- 2.32e-30] + [0.21696476751886069363858659310 +/- 3.06e-30]*I 5,4: [0.23175094750401575588338366176 +/- 2.21e-30] 5,3: [0.76374788011728687822451215264 +/- 2.32e-30] + [-0.21696476751886069363858659310 +/- 3.06e-30]*I 7,3: [0.71394334376831949285993820742 +/- 1.21e-30] + [0.47490218277139938263745243935 +/- 4.52e-30]*I 7,2: [0.31008936259836766059195052534 +/- 5.29e-30] + [-0.07264193137017790524562171245 +/- 5.48e-30]*I 7,6: [1.14658566690370833367712697646 +/- 1.95e-30] 7,4: [0.31008936259836766059195052534 +/- 5.29e-30] + [0.07264193137017790524562171245 +/- 5.48e-30]*I 7,5: [0.71394334376831949285993820742 +/- 1.21e-30] + [-0.47490218277139938263745243935 +/- 4.52e-30]*I 8,5: [0.37369171291254730738158695002 +/- 4.01e-30] 8,3: [1.10042140952554837756713576997 +/- 3.37e-30] cpu/wall(s): 0.002 0.003 virt/peak/res/peak(MB): 26.32 26.34 2.35 2.35 Testing a large *q*:: > build/examples/lcentral --quiet --check --prec 256 100000 100000 cpu/wall(s): 1.668 1.667 virt/peak/res/peak(MB): 35.67 46.66 11.67 22.61 It is conjectured that the central value never vanishes. Running with ``--check`` verifies that the interval certainly is nonzero. This can fail with insufficient precision:: > build/examples/lcentral --check --prec 15 100000 100000 100000,71877: [0.1 +/- 0.0772] + [+/- 0.136]*I 100000,90629: [2e+0 +/- 0.106] + [+/- 0.920]*I 100000,28133: [+/- 0.811] + [-2e+0 +/- 0.501]*I 100000,3141: [0.8 +/- 0.0407] + [-0.1 +/- 0.0243]*I 100000,53189: [4.0 +/- 0.0826] + [+/- 0.107]*I 100000,53253: [1.9 +/- 0.0855] + [-3.9 +/- 0.0681]*I Value could be zero! 100000,53381: [+/- 0.0329] + [+/- 0.0413]*I Aborted integrals.c ------------------------------------------------------------------------------- This program computes integrals using :func:`acb_calc_integrate`. Invoking the program without parameters shows usage:: > build/examples/integrals Compute integrals using acb_calc_integrate. Usage: integrals -i n [-prec p] [-tol eps] [-twice] [...] -i n - compute integral n (0 <= n <= 23), or "-i all" -prec p - precision in bits (default p = 64) -goal p - approximate relative accuracy goal (default p) -tol eps - approximate absolute error goal (default 2^-p) -twice - run twice (to see overhead of computing nodes) -heap - use heap for subinterval queue -verbose - show information -verbose2 - show more information -deg n - use quadrature degree up to n -eval n - limit number of function evaluations to n -depth n - limit subinterval queue size to n -threads n - use parallel computation with n threads Implemented integrals: I0 = int_0^100 sin(x) dx I1 = 4 int_0^1 1/(1+x^2) dx I2 = 2 int_0^{inf} 1/(1+x^2) dx (using domain truncation) I3 = 4 int_0^1 sqrt(1-x^2) dx I4 = int_0^8 sin(x+exp(x)) dx I5 = int_1^101 floor(x) dx I6 = int_0^1 |x^4+10x^3+19x^2-6x-6| exp(x) dx I7 = 1/(2 pi i) int zeta(s) ds (closed path around s = 1) I8 = int_0^1 sin(1/x) dx (slow convergence, use -heap and/or -tol) I9 = int_0^1 x sin(1/x) dx (slow convergence, use -heap and/or -tol) I10 = int_0^10000 x^1000 exp(-x) dx I11 = int_1^{1+1000i} gamma(x) dx I12 = int_{-10}^{10} sin(x) + exp(-200-x^2) dx I13 = int_{-1020}^{-1010} exp(x) dx (use -tol 0 for relative error) I14 = int_0^{inf} exp(-x^2) dx (using domain truncation) I15 = int_0^1 sech(10(x-0.2))^2 + sech(100(x-0.4))^4 + sech(1000(x-0.6))^6 dx I16 = int_0^8 (exp(x)-floor(exp(x))) sin(x+exp(x)) dx (use higher -eval) I17 = int_0^{inf} sech(x) dx (using domain truncation) I18 = int_0^{inf} sech^3(x) dx (using domain truncation) I19 = int_0^1 -log(x)/(1+x) dx (using domain truncation) I20 = int_0^{inf} x exp(-x)/(1+exp(-x)) dx (using domain truncation) I21 = int_C wp(x)/x^(11) dx (contour for 10th Laurent coefficient of Weierstrass p-function) I22 = N(1000) = count zeros with 0 < t <= 1000 of zeta(s) using argument principle I23 = int_0^{1000} W_0(x) dx I24 = int_0^pi max(sin(x), cos(x)) dx I25 = int_{-1}^1 erf(x/sqrt(0.0002)*0.5+1.5)*exp(-x) dx I26 = int_{-10}^10 Ai(x) dx I27 = int_0^10 (x-floor(x)-1/2) max(sin(x),cos(x)) dx I28 = int_{-1-i}^{-1+i} sqrt(x) dx I29 = int_0^{inf} exp(-x^2+ix) dx (using domain truncation) I30 = int_0^{inf} exp(-x) Ai(-x) dx (using domain truncation) I31 = int_0^pi x sin(x) / (1 + cos(x)^2) dx A few examples:: build/examples/integrals -i 4 I4 = int_0^8 sin(x+exp(x)) dx ... cpu/wall(s): 0.02 0.02 I4 = [0.34740017265725 +/- 3.95e-15] > build/examples/integrals -i 3 -prec 333 -tol 1e-80 I3 = 4 int_0^1 sqrt(1-x^2) dx ... cpu/wall(s): 0.024 0.024 I3 = [3.141592653589793238462643383279502884197169399375105820974944592307816406286209 +/- 4.24e-79] > build/examples/integrals -i 9 -heap I9 = int_0^1 x sin(1/x) dx (slow convergence, use -heap and/or -tol) ... cpu/wall(s): 0.019 0.018 I9 = [0.3785300 +/- 3.17e-8] fpwrap.c ------------------------------------------------------------------------------- This program demonstrates calling the floating-point wrapper:: > build/examples/fpwrap zeta(2) = 1.644934066848226 zeta(0.5 + 123i) = 0.006252861175594465 + 0.08206030514520983i functions_benchmark.c ------------------------------------------------------------------------------- This program benchmarks performance of some standard functions. .. highlight:: c flint-3.1.3/doc/source/examples_calcium.rst000066400000000000000000000313531461254215100207520ustar00rootroot00000000000000.. _examples-calcium: Calcium example programs =============================================================================== .. highlight:: text See :ref:`examples` for general information about example programs. Running:: make examples will compile the programs and place the binaries in ``build/examples``. The examples related to the Calcium module are documented below. elementary.c ------------------------------------------------------------------------------- This program evaluates several elementary expressions. For some inputs, Calcium's arithmetic should produce a simplified result automatically. Some inputs do not yet automatically simplify as much as one might hope. Calcium may still able to prove that such a number is zero or nonzero; the output of :func:`ca_check_is_zero` is then ``T_TRUE`` or ``T_FALSE``. Sample output:: > build/examples/elementary >>> Exp(Pi*I) + 1 0 >>> Log(-1) / (Pi*I) 1 >>> Log(-I) / (Pi*I) -0.500000 {-1/2} >>> Log(1 / 10^123) / Log(100) -61.5000 {-123/2} >>> Log(1 + Sqrt(2)) / Log(3 + 2*Sqrt(2)) 0.500000 {1/2} >>> Sqrt(2)*Sqrt(3) - Sqrt(6) 0 >>> Exp(1+Sqrt(2)) * Exp(1-Sqrt(2)) / (Exp(1)^2) 1 >>> I^I - Exp(-Pi/2) 0 >>> Exp(Sqrt(3))^2 - Exp(Sqrt(12)) 0 >>> 2*Log(Pi*I) - 4*Log(Sqrt(Pi)) - Pi*I 0 >>> -I*Pi/8*Log(2/3-2*I/3)^2 + I*Pi/8*Log(2/3+2*I/3)^2 + Pi^2/12*Log(-1-I) + Pi^2/12*Log(-1+I) + Pi^2/12*Log(1/3-I/3) + Pi^2/12*Log(1/3+I/3) - Pi^2/48*Log(18) 0 >>> Sqrt(5 + 2*Sqrt(6)) - Sqrt(2) - Sqrt(3) 0e-1126 {a-c-d where a = 3.14626 [Sqrt(9.89898 {2*b+5})], b = 2.44949 [b^2-6=0], c = 1.73205 [c^2-3=0], d = 1.41421 [d^2-2=0]} >>> Is zero? T_TRUE >>> Sqrt(I) - (1+I)/Sqrt(2) 0e-1126 + 0e-1126*I {(2*a-b*c-b)/2 where a = 0.707107 + 0.707107*I [Sqrt(1.00000*I {c})], b = 1.41421 [b^2-2=0], c = I [c^2+1=0]} >>> Is zero? T_TRUE >>> Exp(Pi*Sqrt(163)) - (640320^3 + 744) -7.49927e-13 {a-262537412640768744 where a = 2.62537e+17 [Exp(40.1092 {b*c})], b = 3.14159 [Pi], c = 12.7671 [c^2-163=0]} >>> Erf(2*Log(Sqrt(1/2-Sqrt(2)/4))+Log(4)) - Erf(Log(2-Sqrt(2))) 0 cpu/wall(s): 0.022 0.022 virt/peak/res/peak(MB): 36.45 36.47 9.37 9.37 binet.c ------------------------------------------------------------------------------- This program computes the *n*-th Fibonacci number using Binet's formula `F_n = (\varphi^n - (1-\varphi)^n)/\sqrt{5}` where `\varphi = \tfrac{1}{2} (1+\sqrt{5})`. The program takes *n* as input. Sample output:: > build/examples/binet 250 7.89633e+51 {7896325826131730509282738943634332893686268675876375} cpu/wall(s): 0.002 0.001 virt/peak/res/peak(MB): 36.14 36.14 5.81 5.81 This illustrates exact arithmetic in algebraic number fields. The program also illustrates another aspect of Calcium arithmetic: evaluation limits. For example, trying to compute the index `n = 10^6` Fibonacci number hits an evaluation limit, so the value is not expanded to an explicit integer:: > build/examples/binet 1000000 1.95328e+208987 {(a*c-b*c)/5 where a = 4.36767e+208987 [Pow(1.61803 {(c+1)/2}, 1.00000e+6 {1000000})], b = 2.28955e-208988 [Pow(-0.618034 {(-c+1)/2}, 1.00000e+6 {1000000})], c = 2.23607 [c^2-5=0]} cpu/wall(s): 0.006 0.005 virt/peak/res/peak(MB): 36.14 36.14 9.05 9.05 Calling the program with ``-limit B n`` raises the bit evaluation limit to *B*. Setting this large enough allows `F_{10^6}` to expand to an integer (the following output has been truncated to avoid reproducing all 208988 digits):: > build/examples/binet -limit 10000000 1000000 1.95328e+208987 {1953282128...8242546875} cpu/wall(s): 0.229 0.242 virt/peak/res/peak(MB): 36.79 37.29 7.13 7.13 The exact mechanisms and interfaces for evaluation limits are still a work in progress. machin.c ------------------------------------------------------------------------------- This program checks several variations of Machin's formula .. math:: \frac{\pi}{4} = 4 \operatorname{atan}\left(\frac{1}{5}\right) - \operatorname{atan}\left(\frac{1}{239}\right) expressing `\pi` or logarithms of small integers in terms of arctangents or hyperbolic arctangents of rational numbers. The program actually evaluates `4 \operatorname{atan}\left(\tfrac{1}{5}\right) - \operatorname{atan}\left(\tfrac{1}{239}\right) - \tfrac{\pi}{4}` (etc.) and prints the result, which should be precisely 0, proving the identity. Inverse trigonometric functions are not yet implemented in Calcium, so the example program evaluates them using logarithms. Sample output:: > build/examples/machin [(1)*Atan(1/1) - Pi/4] = 0 [(1)*Atan(1/2) + (1)*Atan(1/3) - Pi/4] = 0 [(2)*Atan(1/2) + (-1)*Atan(1/7) - Pi/4] = 0 [(2)*Atan(1/3) + (1)*Atan(1/7) - Pi/4] = 0 [(4)*Atan(1/5) + (-1)*Atan(1/239) - Pi/4] = 0 [(1)*Atan(1/2) + (1)*Atan(1/5) + (1)*Atan(1/8) - Pi/4] = 0 [(1)*Atan(1/3) + (1)*Atan(1/4) + (1)*Atan(1/7) + (1)*Atan(1/13) - Pi/4] = 0 [(12)*Atan(1/49) + (32)*Atan(1/57) + (-5)*Atan(1/239) + (12)*Atan(1/110443) - Pi/4] = 0 [(14)*Atanh(1/31) + (10)*Atanh(1/49) + (6)*Atanh(1/161) - Log(2)] = 0 [(22)*Atanh(1/31) + (16)*Atanh(1/49) + (10)*Atanh(1/161) - Log(3)] = 0 [(32)*Atanh(1/31) + (24)*Atanh(1/49) + (14)*Atanh(1/161) - Log(5)] = 0 [(144)*Atanh(1/251) + (54)*Atanh(1/449) + (-38)*Atanh(1/4801) + (62)*Atanh(1/8749) - Log(2)] = 0 [(228)*Atanh(1/251) + (86)*Atanh(1/449) + (-60)*Atanh(1/4801) + (98)*Atanh(1/8749) - Log(3)] = 0 [(334)*Atanh(1/251) + (126)*Atanh(1/449) + (-88)*Atanh(1/4801) + (144)*Atanh(1/8749) - Log(5)] = 0 [(404)*Atanh(1/251) + (152)*Atanh(1/449) + (-106)*Atanh(1/4801) + (174)*Atanh(1/8749) - Log(7)] = 0 cpu/wall(s): 0.016 0.016 virt/peak/res/peak(MB): 35.57 35.57 8.80 8.80 swinnerton_dyer_poly.c ------------------------------------------------------------------------------- This program computes the coefficients of the Swinnerton-Dyer polynomial .. math:: S_n = \prod (x \pm \sqrt{2} \pm \sqrt{3} \pm \sqrt{5} \pm \ldots \pm \sqrt{p_n}) where `p_n` denotes the `n`-th prime number and all combinations of signs are taken. This polynomial has degree `2^n`. The polynomial is expanded from its roots using naive polynomial multiplication over :type:`ca_t` coefficients. There are far more efficient ways to construct this polynomial; this program simply illustrates that arithmetic in multivariate number fields works smoothly. The program prints the coefficients of `S_n`, from the constant term to the coefficient of `x^{2^n}`. Sample output:: > build/examples/swinnerton_dyer_poly 3 576 0 -960 0 352 0 -40 0 1 cpu/wall(s): 0.002 0.002 virt/peak/res/peak(MB): 35.07 35.11 5.40 5.40 A big benchmark problem (output truncated):: > build/examples/swinnerton_dyer_poly 10 4.35675e+809 {43567450015...212890625} 0 ... 0 1 cpu/wall(s): 9.296 9.307 virt/peak/res/peak(MB): 38.95 38.95 10.01 10.01 huge_expr.c ------------------------------------------------------------------------------- This program proves equality of two complicated algebraic numbers. More precisely, the program verifies that `N = -(1 - |M|^2)^2` where *N* and *M* are given by huge symbolic expressions involving nested square roots (about 7000 operations in total). By default, the program runs the computation using :type:`qqbar_t` arithmetic:: > build/examples/huge_expr Evaluating N... cpu/wall(s): 7.205 7.206 Evaluating M... cpu/wall(s): 0.933 0.934 Evaluating E = -(1-|M|^2)^2... cpu/wall(s): 0.391 0.391 N ~ -0.16190853053311203695842869991458578203473645660641 E ~ -0.16190853053311203695842869991458578203473645660641 Testing E = N... cpu/wall(s): 0.001 0 Equal = T_TRUE Total: cpu/wall(s): 8.53 8.531 virt/peak/res/peak(MB): 54.50 64.56 24.64 34.61 To run the computation using :type:`ca_t` arithmetic instead, pass the -ca flag:: > build/examples/huge_expr -ca Evaluating N... cpu/wall(s): 0.193 0.193 Evaluating M... cpu/wall(s): 0.024 0.024 Evaluating E = -(1-|M|^2)^2... cpu/wall(s): 0.008 0.009 N ~ -0.16190853053311203695842869991458578203473645660641 E ~ -0.16190853053311203695842869991458578203473645660641 Testing E = N... cpu/wall(s): 8.017 8.019 Equal = T_TRUE Total: cpu/wall(s): 8.243 8.246 virt/peak/res/peak(MB): 61.67 65.29 33.97 37.54 This simplification problem was posted in a help request for Sage (https://ask.sagemath.org/question/52653). The C code has been generated from the symbolic expressions using a Python script. hilbert_matrix.c ------------------------------------------------------------------------------- This program constructs the Hilbert matrix `H_n = (1/(i+j-1))_{i=1,j=1}^n`, computes its eigenvalues `\lambda_1, \ldots, \lambda_n`, as exact algebraic numbers, and verifies the exact trace and determinant formulas .. math:: \lambda_1 + \lambda_2 + \ldots + \lambda_n = \operatorname{tr}(H_n), \quad \lambda_1 \lambda_2 \cdots \lambda_n = \operatorname{det}(H_n). Sample output:: > build/examples/hilbert_matrix 6 Trace: 1.87821 {6508/3465} 1.87821 {6508/3465} Equal: T_TRUE Det: 5.36730e-18 {1/186313420339200000} 5.36730e-18 {1/186313420339200000} Equal: T_TRUE cpu/wall(s): 0.07 0.069 virt/peak/res/peak(MB): 36.56 36.66 9.69 9.69 The program accepts the following optional arguments: * With ``-vieta``, force use of Vieta's formula internally (by default, Calcium uses Vieta's formulas when working with algebraic conjugates, but only up to some bound on the degree). * With ``-novieta``, force Calcium not to use Vieta's formulas internally. * With ``-qqbar``, do a similar computation using :type:`qqbar_t` arithmetic. dft.c ------------------------------------------------------------------------------- This program demonstrates the discrete Fourier transform (DFT) in exact arithmetic. For the input vector `\textbf{x} = (x_n)_{n=0}^{N-1}`, it verifies the identity .. math:: \textbf{x} - \operatorname{DFT}^{-1}(\operatorname{DFT}(\textbf{x})) = 0 where .. math:: \operatorname{DFT}(\textbf{x})_n = \sum_{k=0}^{N-1} \omega^{-kn} x_k, \quad \operatorname{DFT}^{-1}(\textbf{x})_n = \frac{1}{N} \sum_{k=0}^{N-1} \omega^{kn} x_k, \quad \omega = e^{2 \pi i / N}. The program computes the DFT by naive `O(N^2)` summation (not using FFT). It uses repeated multiplication of `\omega` to precompute an array of roots of unity `1,\omega,\omega^2,\ldots,\omega^{2N-1}` for use in both the DFT and the inverse DFT. Usage:: build/examples/dft [-verbose] [-input i] [-limit B] [-timing T] N The required parameter ``N`` selects the length of the vector. The optional flag ``-verbose`` chooses whether to print the arrays. The optional parameter ``-timing T`` selects a timing method (default = 0). * 0: run the computation once and time it * 1: run the computation repeatedly if needed to get an accurate timing, creating a new context object for each iteration so that fields are not cached * 2: run the computation once, then run the computation at least one more time (repeatedly if needed to get an accurate timing), recycling the same context object to measure the performance with cached fields The optional parameter ``-input i`` selects an input sequence (default = 0). * 0: `x_n = n+2` * 1: `x_n = \sqrt{n+2}` * 2: `x_n = \log(n+2)` * 3: `x_n = e^{2 \pi i / (n+2)}` The optional parameter ``-limit B`` sets the internal degree limit for algebraic numbers. Sample output:: > build/examples/dft 4 -input 1 -verbose DFT benchmark, length N = 4 [x] = 1.41421 {a where a = 1.41421 [a^2-2=0]} 1.73205 {a where a = 1.73205 [a^2-3=0]} 2 2.23607 {a where a = 2.23607 [a^2-5=0]} DFT([x]) = 7.38233 {a+b+c+2 where a = 2.23607 [a^2-5=0], b = 1.73205 [b^2-3=0], c = 1.41421 [c^2-2=0]} -0.585786 + 0.504017*I {a*d-b*d+c-2 where a = 2.23607 [a^2-5=0], b = 1.73205 [b^2-3=0], c = 1.41421 [c^2-2=0], d = I [d^2+1=0]} -0.553905 {-a-b+c+2 where a = 2.23607 [a^2-5=0], b = 1.73205 [b^2-3=0], c = 1.41421 [c^2-2=0]} -0.585786 - 0.504017*I {-a*d+b*d+c-2 where a = 2.23607 [a^2-5=0], b = 1.73205 [b^2-3=0], c = 1.41421 [c^2-2=0], d = I [d^2+1=0]} IDFT(DFT([x])) = 1.41421 {c where a = 2.23607 [a^2-5=0], b = 1.73205 [b^2-3=0], c = 1.41421 [c^2-2=0], d = I [d^2+1=0]} 1.73205 {b where a = 2.23607 [a^2-5=0], b = 1.73205 [b^2-3=0], c = 1.41421 [c^2-2=0], d = I [d^2+1=0]} 2 2.23607 {a where a = 2.23607 [a^2-5=0], b = 1.73205 [b^2-3=0], c = 1.41421 [c^2-2=0], d = I [d^2+1=0]} [x] - IDFT(DFT([x])) = 0 (= 0 T_TRUE) 0 (= 0 T_TRUE) 0 (= 0 T_TRUE) 0 (= 0 T_TRUE) cpu/wall(s): 0.009 0.009 virt/peak/res/peak(MB): 36.28 36.28 9.14 9.14 .. raw:: latex \newpage flint-3.1.3/doc/source/fexpr.rst000066400000000000000000000556541461254215100165750ustar00rootroot00000000000000.. _fexpr: **fexpr.h** -- flat-packed symbolic expressions =============================================================================== This module supports working with symbolic expressions. Introduction ----------------------------------------------------------------------- Formally, a symbolic expression is either: * An atom, being one of the following: * An integer, for example 0 or -34. * A symbol, for example ``x``, ``Mul``, ``SomeUserNamedSymbol``. Symbols should be valid C identifiers (containing only the characters ``A-Z``, ``a-z``, ``0-9``, ``_``, and not starting with a digit). * A string, for example ``"Hello, world!"``. For the moment, we only consider ASCII strings, but there is no obstacle in principle to supporting UTF-8. * A non-atomic expression, representing a function call `e_0(e_1, \ldots, e_n)` where `e_0, \ldots, e_n` are symbolic expressions. The meaning of an expression depends on the interpretation of symbols in a given context. For example, with a standard interpretation (used within Calcium) of the symbols ``Mul``, ``Add`` and ``Neg``, the expression ``Mul(3, Add(Neg(x), y))`` encodes the formula `3 \cdot ((-x)+y)` where ``x`` and ``y`` are symbolic variables. See :ref:`fexpr-builtin` for documentation of builtin symbols. Computing and embedding data ....................................................................... Symbolic expressions are usually not the best data structure to use directly for heavy-duty computations. Functions acting on symbolic expressions will typically convert to a dedicated data structure (e.g. polynomials) internally and (optionally) convert the final result back to a symbolic expression. Symbolic expressions do not allow embedding arbitrary binary objects such as Flint/Arb/Antic/Calcium types as atoms. This is done on purpose to make symbolic expressions easy to use as a data exchange format. To embed an object in an expression, one has the following options: * Represent the object structurally using atoms supported natively by symbolic expressions (for example, an integer polynomial can be represented as a list of coefficients or as an arithmetic expression tree). * Introduce a dummy symbol to represent the object, maintaining an external translation table mapping this symbol to the intended value. * Encode the object using a string or symbol name. This is generally not recommended, as it requires parsing; properly used, symbolic expressions have the benefit of being able to represent the parsed structure. Flat-packed representation ....................................................................... Symbolic expressions are often implemented using trees of pointers (often together with hash tables for uniqueness), requiring some form of memory management. The :type:`fexpr_t` type, by contrast, stores a symbolic expression using a "flat-packed" representation without internal pointers. The expression data is just an array of words (``ulong``). The first word is a header encoding type information (whether the expression is a function call or an atom, and the type of the atom) and the total number of words in the expression. For atoms, the data is stored either in the header word itself (small integers and short symbols/strings) or in the following words. For function calls, the header is followed by the expressions `e_0`, ..., `e_n` packed contiguously in memory. Pros: * Memory management is trivial. * Copying an expression is just copying an array of words. * Comparing expressions for equality is just comparing arrays of words. * Merging expressions is basically just concatenating arrays of words. * Expression data can be shared freely in binary form between threads and even between machines (as long as all machines have the same word size and endianness). Cons: * Repeated instances of the same subexpression cannot share memory (a workaround is to introduce local dummy symbols for repeated subexpressions). * Extracting a subexpression for modification generally requires making a complete copy of that subxepression (however, for read-only access to subexpressions, one can use "view" expressions which have zero overhead). * Manipulating a part of an expression generally requires rebuilding the whole expression. * Building an expression incrementally is typically `O(n^2)`. As a workaround, it is a good idea to work with balanced (low-depth) expressions and try to construct an expression in one go (for example, to create a sum, create a single ``Add`` expression with many arguments instead of chaining binary ``Add`` operations). Types and macros ------------------------------------------------------------------------------- .. type:: fexpr_struct .. type:: fexpr_t An *fexpr_struct* consists of a pointer to an array of words along with a record of the number of allocated words. An *fexpr_t* is defined as an array of length one of type *fexpr_struct*, permitting an *fexpr_t* to be passed by reference. .. type:: fexpr_ptr Alias for ``fexpr_struct *``, used for arrays of expressions. .. type:: fexpr_srcptr Alias for ``const fexpr_struct *``, used for arrays of expressions when passed as constant input to functions. .. type:: fexpr_vec_struct .. type:: fexpr_vec_t A type representing a vector of expressions with managed length. The structure contains an :type:`fexpr_ptr` *entries* for the entries, an integer *length* (the size of the vector), and an integer *alloc* (the number of allocated entries). .. macro:: fexpr_vec_entry(vec, i) Returns a pointer to entry *i* in the vector *vec*. Memory management ------------------------------------------------------------------------------- .. function:: void fexpr_init(fexpr_t expr) Initializes *expr* for use. Its value is set to the atomic integer 0. .. function:: void fexpr_clear(fexpr_t expr) Clears *expr*, freeing its allocated memory. .. function:: fexpr_ptr _fexpr_vec_init(slong len) Returns a heap-allocated vector of *len* initialized expressions. .. function:: void _fexpr_vec_clear(fexpr_ptr vec, slong len) Clears the *len* expressions in *vec* and frees *vec* itself. .. function:: void fexpr_fit_size(fexpr_t expr, slong size) Ensures that *expr* has room for *size* words. .. function:: void fexpr_set(fexpr_t res, const fexpr_t expr) Sets *res* to the a copy of *expr*. .. function:: void fexpr_swap(fexpr_t a, fexpr_t b) Swaps *a* and *b* efficiently. Size information ------------------------------------------------------------------------------- .. function:: slong fexpr_depth(const fexpr_t expr) Returns the depth of *expr* as a symbolic expression tree. .. function:: slong fexpr_num_leaves(const fexpr_t expr) Returns the number of leaves (atoms, counted with repetition) in the expression *expr*. .. function:: slong fexpr_size(const fexpr_t expr) Returns the number of words in the internal representation of *expr*. .. function:: slong fexpr_size_bytes(const fexpr_t expr) Returns the number of bytes in the internal representation of *expr*. The count excludes the size of the structure itself. Add ``sizeof(fexpr_struct)`` to get the size of the object as a whole. .. function:: slong fexpr_allocated_bytes(const fexpr_t expr) Returns the number of allocated bytes in the internal representation of *expr*. The count excludes the size of the structure itself. Add ``sizeof(fexpr_struct)`` to get the size of the object as a whole. Comparisons ------------------------------------------------------------------------------- .. function:: int fexpr_equal(const fexpr_t a, const fexpr_t b) Checks if *a* and *b* are exactly equal as expressions. .. function:: int fexpr_equal_si(const fexpr_t expr, slong c) .. function:: int fexpr_equal_ui(const fexpr_t expr, ulong c) Checks if *expr* is an atomic integer exactly equal to *c*. .. function:: ulong fexpr_hash(const fexpr_t expr) Returns a hash of the expression *expr*. .. function:: int fexpr_cmp_fast(const fexpr_t a, const fexpr_t b) Compares *a* and *b* using an ordering based on the internal representation, returning -1, 0 or 1. This can be used, for instance, to maintain sorted arrays of expressions for binary search; the sort order has no mathematical significance. Atoms ------------------------------------------------------------------------------- .. function:: int fexpr_is_integer(const fexpr_t expr) Returns whether *expr* is an atomic integer .. function:: int fexpr_is_symbol(const fexpr_t expr) Returns whether *expr* is an atomic symbol. .. function:: int fexpr_is_string(const fexpr_t expr) Returns whether *expr* is an atomic string. .. function:: int fexpr_is_atom(const fexpr_t expr) Returns whether *expr* is any atom. .. function:: void fexpr_zero(fexpr_t res) Sets *res* to the atomic integer 0. .. function:: int fexpr_is_zero(const fexpr_t expr) Returns whether *expr* is the atomic integer 0. .. function:: int fexpr_is_neg_integer(const fexpr_t expr) Returns whether *expr* is any negative atomic integer. .. function:: void fexpr_set_si(fexpr_t res, slong c) void fexpr_set_ui(fexpr_t res, ulong c) void fexpr_set_fmpz(fexpr_t res, const fmpz_t c) Sets *res* to the atomic integer *c*. .. function:: int fexpr_get_fmpz(fmpz_t res, const fexpr_t expr) Sets *res* to the atomic integer in *expr*. This aborts if *expr* is not an atomic integer. .. function:: void fexpr_set_symbol_builtin(fexpr_t res, slong id) Sets *res* to the builtin symbol with internal index *id* (see :ref:`fexpr-builtin`). .. function:: int fexpr_is_builtin_symbol(const fexpr_t expr, slong id) Returns whether *expr* is the builtin symbol with index *id* (see :ref:`fexpr-builtin`). .. function:: int fexpr_is_any_builtin_symbol(const fexpr_t expr) Returns whether *expr* is any builtin symbol (see :ref:`fexpr-builtin`). .. function:: void fexpr_set_symbol_str(fexpr_t res, const char * s) Sets *res* to the symbol given by *s*. .. function:: char * fexpr_get_symbol_str(const fexpr_t expr) Returns the symbol in *expr* as a string. The string must be freed with :func:`flint_free`. This aborts if *expr* is not an atomic symbol. .. function:: void fexpr_set_string(fexpr_t res, const char * s) Sets *res* to the atomic string *s*. .. function:: char * fexpr_get_string(const fexpr_t expr) Assuming that *expr* is an atomic string, returns a copy of this string. The string must be freed with :func:`flint_free`. Input and output ------------------------------------------------------------------------ .. function:: void fexpr_write(calcium_stream_t stream, const fexpr_t expr) Writes *expr* to *stream*. .. function:: void fexpr_print(const fexpr_t expr) Prints *expr* to standard output. .. function:: char * fexpr_get_str(const fexpr_t expr) Returns a string representation of *expr*. The string must be freed with :func:`flint_free`. Warning: string literals appearing in expressions are currently not escaped. LaTeX output ------------------------------------------------------------------------ .. function:: void fexpr_write_latex(calcium_stream_t stream, const fexpr_t expr, ulong flags) Writes the LaTeX representation of *expr* to *stream*. .. function:: void fexpr_print_latex(const fexpr_t expr, ulong flags) Prints the LaTeX representation of *expr* to standard output. .. function:: char * fexpr_get_str_latex(const fexpr_t expr, ulong flags) Returns a string of the LaTeX representation of *expr*. The string must be freed with :func:`flint_free`. Warning: string literals appearing in expressions are currently not escaped. The *flags* parameter allows specifying options for LaTeX output. The following flags are supported: .. macro:: FEXPR_LATEX_SMALL Generate more compact formulas, most importantly by printing fractions inline as `p/q` instead of as `\displaystyle{\frac{p}{q}}`. This flag is automatically activated within subscripts and superscripts and in certain other parts of formulas. .. macro:: FEXPR_LATEX_LOGIC Use symbols for logical operators such as Not, And, Or, which by default are rendered as words for legibility. Function call structure ------------------------------------------------------------------------ .. function:: slong fexpr_nargs(const fexpr_t expr) Returns the number of arguments *n* in the function call `f(e_1,\ldots,e_n)` represented by *expr*. If *expr* is an atom, returns -1. .. function:: void fexpr_func(fexpr_t res, const fexpr_t expr) Assuming that *expr* represents a function call `f(e_1,\ldots,e_n)`, sets *res* to the function expression *f*. .. function:: void fexpr_view_func(fexpr_t view, const fexpr_t expr) As :func:`fexpr_func`, but sets *view* to a shallow view instead of copying the expression. The variable *view* must not be initialized before use or cleared after use, and *expr* must not be modified or cleared as long as *view* is in use. .. function:: void fexpr_arg(fexpr_t res, const fexpr_t expr, slong i) Assuming that *expr* represents a function call `f(e_1,\ldots,e_n)`, sets *res* to the argument `e_{i+1}`. Note that indexing starts from 0. The index must be in bounds, with `0 \le i < n`. .. function:: void fexpr_view_arg(fexpr_t view, const fexpr_t expr, slong i) As :func:`fexpr_arg`, but sets *view* to a shallow view instead of copying the expression. The variable *view* must not be initialized before use or cleared after use, and *expr* must not be modified or cleared as long as *view* is in use. .. function:: void fexpr_view_next(fexpr_t view) Assuming that *view* is a shallow view of a function argument `e_i` in a function call `f(e_1,\ldots,e_n)`, sets *view* to a view of the next argument `e_{i+1}`. This function can be called when *view* refers to the last argument `e_n`, provided that *view* is not used afterwards. This function can also be called when *view* refers to the function *f*, in which case it will make *view* point to `e_1`. .. function:: int fexpr_is_builtin_call(const fexpr_t expr, slong id) Returns whether *expr* has the form `f(\ldots)` where *f* is a builtin function defined by *id* (see :ref:`fexpr-builtin`). .. function:: int fexpr_is_any_builtin_call(const fexpr_t expr) Returns whether *expr* has the form `f(\ldots)` where *f* is any builtin function (see :ref:`fexpr-builtin`). Composition ------------------------------------------------------------------------ .. function:: void fexpr_call0(fexpr_t res, const fexpr_t f) void fexpr_call1(fexpr_t res, const fexpr_t f, const fexpr_t x1) void fexpr_call2(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2) void fexpr_call3(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3) void fexpr_call4(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3, const fexpr_t x4) void fexpr_call_vec(fexpr_t res, const fexpr_t f, fexpr_srcptr args, slong len) Creates the function call `f(x_1,\ldots,x_n)`. The *vec* version takes the arguments as an array *args* and *n* is given by *len*. Warning: aliasing between inputs and outputs is not implemented. .. function:: void fexpr_call_builtin1(fexpr_t res, slong f, const fexpr_t x1) void fexpr_call_builtin2(fexpr_t res, slong f, const fexpr_t x1, const fexpr_t x2) Creates the function call `f(x_1,\ldots,x_n)`, where *f* defines a builtin symbol. Subexpressions and replacement ------------------------------------------------------------------------ .. function:: int fexpr_contains(const fexpr_t expr, const fexpr_t x) Returns whether *expr* contains the expression *x* as a subexpression (this includes the case where *expr* and *x* are equal). .. function:: int fexpr_replace(fexpr_t res, const fexpr_t expr, const fexpr_t x, const fexpr_t y) Sets *res* to the expression *expr* with all occurrences of the subexpression *x* replaced by the expression *y*. Returns a boolean value indicating whether any replacements have been performed. Aliasing is allowed between *res* and *expr* but not between *res* and *x* or *y*. .. function:: int fexpr_replace2(fexpr_t res, const fexpr_t expr, const fexpr_t x1, const fexpr_t y1, const fexpr_t x2, const fexpr_t y2) Like :func:`fexpr_replace`, but simultaneously replaces *x1* by *y1* and *x2* by *y2*. .. function:: int fexpr_replace_vec(fexpr_t res, const fexpr_t expr, const fexpr_vec_t xs, const fexpr_vec_t ys) Sets *res* to the expression *expr* with all occurrences of the subexpressions given by entries in *xs* replaced by the corresponding expressions in *ys*. It is required that *xs* and *ys* have the same length. Returns a boolean value indicating whether any replacements have been performed. Aliasing is allowed between *res* and *expr* but not between *res* and the entries of *xs* or *ys*. Arithmetic expressions ------------------------------------------------------------------------ .. function:: void fexpr_set_fmpq(fexpr_t res, const fmpq_t x) Sets *res* to the rational number *x*. This creates an atomic integer if the denominator of *x* is one, and otherwise creates a division expression. .. function:: void fexpr_set_arf(fexpr_t res, const arf_t x) void fexpr_set_d(fexpr_t res, double x) Sets *res* to an expression for the value of the floating-point number *x*. NaN is represented as ``Undefined``. For a regular value, this creates an atomic integer or a rational fraction if the exponent is small, and otherwise creates an expression of the form ``Mul(m, Pow(2, e))``. .. function:: void fexpr_set_re_im_d(fexpr_t res, double x, double y) Sets *res* to an expression for the complex number with real part *x* and imaginary part *y*. .. function:: void fexpr_neg(fexpr_t res, const fexpr_t a) void fexpr_add(fexpr_t res, const fexpr_t a, const fexpr_t b) void fexpr_sub(fexpr_t res, const fexpr_t a, const fexpr_t b) void fexpr_mul(fexpr_t res, const fexpr_t a, const fexpr_t b) void fexpr_div(fexpr_t res, const fexpr_t a, const fexpr_t b) void fexpr_pow(fexpr_t res, const fexpr_t a, const fexpr_t b) Constructs an arithmetic expression with given arguments. No simplifications whatsoever are performed. .. function:: int fexpr_is_arithmetic_operation(const fexpr_t expr) Returns whether *expr* is of the form `f(e_1,\ldots,e_n)` where *f* is one of the arithmetic operators ``Pos``, ``Neg``, ``Add``, ``Sub``, ``Mul``, ``Div``. .. function:: void fexpr_arithmetic_nodes(fexpr_vec_t nodes, const fexpr_t expr) Sets *nodes* to a vector of subexpressions of *expr* such that *expr* is an arithmetic expression with *nodes* as leaves. More precisely, *expr* will be constructed out of nested application the arithmetic operators ``Pos``, ``Neg``, ``Add``, ``Sub``, ``Mul``, ``Div`` with integers and expressions in *nodes* as leaves. Powers ``Pow`` with an atomic integer exponent are also allowed. The nodes are output without repetition but are not automatically sorted in a canonical order. .. function:: int fexpr_get_fmpz_mpoly_q(fmpz_mpoly_q_t res, const fexpr_t expr, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx) Sets *res* to the expression *expr* as a formal rational function of the subexpressions in *vars*. The vector *vars* must have the same length as the number of variables specified in *ctx*. To build *vars* automatically for a given expression, :func:`fexpr_arithmetic_nodes` may be used. Returns 1 on success and 0 on failure. Failure can occur for the following reasons: * A subexpression is encountered that cannot be interpreted as an arithmetic operation and does not appear (exactly) in *vars*. * Overflow (too many terms or too large exponent). * Division by zero (a zero denominator is encountered). It is important to note that this function views *expr* as a formal rational function with *vars* as formal indeterminates. It does thus not check for algebraic relations between *vars* and can implicitly divide by zero if *vars* are not algebraically independent. .. function:: void fexpr_set_fmpz_mpoly(fexpr_t res, const fmpz_mpoly_t poly, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx) void fexpr_set_fmpz_mpoly_q(fexpr_t res, const fmpz_mpoly_q_t frac, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx) Sets *res* to an expression for the multivariate polynomial *poly* (or rational function *frac*), using the expressions in *vars* as the variables. The length of *vars* must agree with the number of variables in *ctx*. If *NULL* is passed for *vars*, a default choice of symbols is used. .. function:: int fexpr_expanded_normal_form(fexpr_t res, const fexpr_t expr, ulong flags) Sets *res* to *expr* converted to expanded normal form viewed as a formal rational function with its non-arithmetic subexpressions as terminal nodes. This function first computes nodes with :func:`fexpr_arithmetic_nodes`, sorts the nodes, evaluates to a rational function with :func:`fexpr_get_fmpz_mpoly_q`, and then converts back to an expression with :func:`fexpr_set_fmpz_mpoly_q`. Optional *flags* are reserved for future use. Vectors ------------------------------------------------------------------------ .. function:: void fexpr_vec_init(fexpr_vec_t vec, slong len) Initializes *vec* to a vector of length *len*. All entries are set to the atomic integer 0. .. function:: void fexpr_vec_clear(fexpr_vec_t vec) Clears the vector *vec*. .. function:: void fexpr_vec_print(const fexpr_vec_t vec) Prints *vec* to standard output. .. function:: void fexpr_vec_swap(fexpr_vec_t x, fexpr_vec_t y) Swaps *x* and *y* efficiently. .. function:: void fexpr_vec_fit_length(fexpr_vec_t vec, slong len) Ensures that *vec* has space for *len* entries. .. function:: void fexpr_vec_set(fexpr_vec_t dest, const fexpr_vec_t src) Sets *dest* to a copy of *src*. .. function:: void fexpr_vec_append(fexpr_vec_t vec, const fexpr_t expr) Appends *expr* to the end of the vector *vec*. .. function:: slong fexpr_vec_insert_unique(fexpr_vec_t vec, const fexpr_t expr) Inserts *expr* without duplication into vec, returning its position. If this expression already exists, *vec* is unchanged. If this expression does not exist in *vec*, it is appended. .. function:: void fexpr_vec_set_length(fexpr_vec_t vec, slong len) Sets the length of *vec* to *len*, truncating or zero-extending as needed. .. function:: void _fexpr_vec_sort_fast(fexpr_ptr vec, slong len) Sorts the *len* entries in *vec* using the comparison function :func:`fexpr_cmp_fast`. .. raw:: latex \newpage flint-3.1.3/doc/source/fexpr_builtin.rst000066400000000000000000000645101461254215100203120ustar00rootroot00000000000000.. _fexpr-builtin: **fexpr_builtin.h** -- builtin symbols =============================================================================== This module defines symbol names with a predefined meaning for use in symbolic expressions. These symbols will eventually all support LaTeX rendering as well as symbolic and numerical evaluation (where applicable). By convention, all builtin symbol names are at least two characters long and start with an uppercase letter. Single-letter symbol names and symbol names beginning with a lowercase letter are reserved for variables. For any builtin symbol name ``Symbol``, the header file ``fexpr_builtin.h`` defines a C constant ``FEXPR_Symbol`` as an index to a builtin symbol table. The symbol will be documented as ``Symbol`` below. C helper functions ------------------------------------------------------------------------ .. function:: slong fexpr_builtin_lookup(const char * s) Returns the internal index used to encode the builtin symbol with name *s* in expressions. If *s* is not the name of a builtin symbol, returns -1. .. function:: const char * fexpr_builtin_name(slong n) Returns a read-only pointer for a string giving the name of the builtin symbol with index *n*. .. function:: slong fexpr_builtin_length(void) Returns the number of builtin symbols. Variables and iteration ------------------------------------------------------------------------ Expressions involving the following symbols have a special role in binding variables. .. macro:: For Generator expression. This is a syntactical construct which does not represent a mathematical object on its own. In general, ``For(x, ...)`` defines the symbol ``x`` as a locally bound variable in the scope of the parent expression. The following arguments ``...`` specify an evaluation range, set or point. Their interpretation depends on the parent operator. The following cases are possible. Case 1: ``For(x, S)`` specifies iteration or comprehension for ``x`` ranging over the values of the set ``S``. This interpretation is used in operators that aggregate values over a set. The ``For`` expression may be followed by a filter predicate ``P(x)`` restricting the range to a subset of ``S``. Examples: ``Set(f(x), For(x, S))`` denotes `\{f(x) : x \in S\}`. ``Set(f(x), For(x, S), P(x))`` denotes `\{f(x) : x \in S \operatorname{and} P(x)\}`. ``Sum(f(x), For(x, S))`` denotes `\sum_{x \in S} f(x)`. ``Sum(f(x), For(x, S), P(x))`` denotes `\sum_{x \in S, \, P(x)} f(x)`. Case 2: ``For(x, a, b)`` specifies that ``x`` ranges between the endpoints ``a`` and ``b`` in the context of ``Sum``, ``Product``, ``Integral``, and similar operators. Examples: ``Sum(f(n), For(n, a, b))`` denotes `\sum_{n=a}^b f(n)`. The iteration is empty if `b < a`. ``Integral(f(x), For(x, a, b))`` denotes `\int_a^b f(x) dx`, where the integral follows a straight-line path from *a* to *b*. Swapping *a* and *b* negates the value. Case 3: ``For(x, a)`` specifies that ``x`` approaches the point ``a`` in the context of ``Limit``-type operator, or differentiation with respect to ``x`` at the point ``a`` in the context of a ``Derivative``-type operator. Examples: ``Derivative(f(x), For(x, a))`` denotes `f'(a)`. ``Limit(f(x), For(x, a))`` denotes `\lim_{x \to a} f(x)`. Case 4: ``For(x, a, n)`` specifies differentiation with respect to ``x`` at the point ``a`` to order ``n`` in the context of a ``Derivative``-type operator. Examples: ``Derivative(f(x), For(x, a, n))`` denotes `f^{(n)}(a)`. .. macro:: Where ``Where(f(x), Def(x, a))`` defines the symbol ``x`` as an alias for the expression ``a`` and evaluates the expression ``f(x)`` with this bound value of ``x``. This is equivalent to ``f(a)``. This may be rendered as `f(x) \; \operatorname{where} x = a`. ``Where(f(x), Def(f(t), a))`` defines the symbol ``f`` as a function mapping the dummy variable ``t`` to ``a``. ``Where(Add(a, b), Def(Tuple(a, b), T))`` is a destructuring assignment. .. macro:: Def Definition expression. This is a syntactical construct which does not represent a mathematical object on its own. The ``Def`` expression is used only within a ``Where``-expression; see that documentation of that symbol for more examples. ``Def(x, a)`` defines the symbol ``x`` as an alias for the expression ``a``. ``Def(f(x, y, z), a)`` defines the symbol ``f`` as a function of three variables. The dummy variables ``x``, ``y`` and ``z`` may appear within the expression ``a``. .. macro:: Fun ``Fun(x, expr)`` defines an anonymous univariate function mapping the symbol ``x`` to the expression ``expr``. The symbol ``x`` becomes locally bound within this ``Fun`` expression. .. macro:: Step .. macro:: Repeat Booleans and logic ------------------------------------------------------------------------ .. macro:: Equal ``Equal(a, b)``, signifying `a = b`, is ``True`` if ``a`` and ``b`` represent the same object, and ``False`` otherwise. This operator can be called with any number of arguments, in which case it evaluates whether all arguments are equal. .. macro:: NotEqual ``NotEqual(a, b)``, signifying `a \ne b`, is equivalent to ``Not(Equal(a, b))``. .. macro:: Same ``Same(a, b)`` gives ``a`` (or equivalently ``b``) if ``a`` and ``b`` represent the same object, and ``Undefined`` otherwise. This can be used to assert or emphasize that two expressions represent the same value within a formula. This operator can be called with any number of arguments, in which case it asserts that all arguments are equal. .. macro:: True ``True`` is a logical constant. .. macro:: False ``False`` is a logical constant. .. macro:: Not ``Not(x)`` is the logical negation of ``x``. .. macro:: And ``And(x, y)`` is the logical AND of ``x`` and ``y``. This function can be called with any number of arguments. .. macro:: Or ``Or(x, y)`` is the logical OR of ``x`` and ``y``. This function can be called with any number of arguments. .. macro:: Equivalent ``Equivalent(x, y)`` denotes the logical equivalence `x \Leftrightarrow y`. Semantically, this is the same as ``Equal`` called with logical arguments. .. macro:: Implies ``Implies(x, y)`` denotes the logical implication `x \implies y`. .. macro:: Exists Existence quantifier. ``Exists(f(x), For(x, S))`` denotes `f(x) \;\text{ for some } x \in S`. ``Exists(f(x), For(x, S), P(x))`` denotes `f(x) \;\text{ for some } x \in S \text{ with } P(x)`. .. macro:: All Universal quantifier. ``All(f(x), For(x, S))`` denotes `f(x) \;\text{ for all } x \in S`. ``All(f(x), For(x, S), P(x))`` denotes `f(x) \;\text{ for all } x \in S \text{ with } P(x)`. .. macro:: Cases ``Cases(Case(f(x), P(x)), Case(g(x), Otherwise))`` denotes: .. math:: \begin{cases} f(x), & P(x)\\g(x), & \text{otherwise}\\ \end{cases} ``Cases(Case(f(x), P(x)), Case(g(x), Q(x)), Case(h(x), Otherwise))`` denotes: .. math:: \begin{cases} f(x), & P(x)\\g(x), & Q(x)\\h(x), & \text{otherwise}\\ \end{cases} If both `P(x)` and `Q(x)` are true simultaneously, no ordering is implied; it is assumed that `f(x)` and `g(x)` give the same value for any such `x`. More generally, this operator can be called with any number of case distinctions. If the *Otherwise* case is omitted, the result is undefined if neither predicate is true. .. macro:: Case See ``Cases``. .. macro:: Otherwise See ``Cases``. Tuples, lists and sets ------------------------------------------------------------------------ .. macro:: Tuple .. macro:: List .. macro:: Set .. macro:: Item .. macro:: Element .. macro:: NotElement .. macro:: EqualAndElement .. macro:: Length .. macro:: Cardinality .. macro:: Concatenation .. macro:: Union .. macro:: Intersection .. macro:: SetMinus .. macro:: Subset .. macro:: SubsetEqual .. macro:: CartesianProduct .. macro:: CartesianPower .. macro:: Subsets ``Subsets(S)`` is the power set `\mathscr{P}(S)` comprising all subsets of the set ``S``. .. macro:: Sets ``Sets`` is the class `\operatorname{Sets}` of all sets. .. macro:: Tuples ``Tuples`` is the class of all tuples. ``Tuples(S)`` is the set of all tuples with elements in the set ``S``. ``Tuples(S, n)`` is the set of all length-``n`` tuples with elements in the set ``S``. Numbers and arithmetic ------------------------------------------------------------------------ Undefined ........................................................................ .. macro:: Undefined ``Undefined`` is the special value `\mathfrak{u}` (undefined). Particular numbers ........................................................................ .. macro:: Pi ``Pi`` is the constant `\pi`. .. macro:: NumberI ``NumberI`` is the imaginary unit `i`. The verbose name leaves ``i`` and ``I`` to be used as a variable names. .. macro:: NumberE ``NumberE`` is the base of the natural logarithm `e`. The verbose name leaves ``e`` and ``E`` to be used as a variable names. .. macro:: GoldenRatio ``GoldenRatio`` is the golden ratio `\varphi`. .. macro:: Euler ``Euler`` is Euler's constant `\gamma`. .. macro:: CatalanConstant ``CatalanConstant`` is Catalan's constant `G`. .. macro:: KhinchinConstant ``KhinchinConstant`` is Khinchin's constant `K`. .. macro:: GlaisherConstant ``GlaisherConstant`` is Glaisher's constant `A`. .. macro:: RootOfUnity ``RootOfUnity(n)`` is the principal complex *n*-th root of unity `\zeta_n = e^{2 \pi i / n}`. ``RootOfUnity(n, k)`` is the complex *n*-th root of unity `\zeta_n^k`. Number constructors ........................................................................ Remark: the rational number with numerator *p* and denominator *q* can be constructed as ``Div(p, q)``. .. macro:: Decimal ``Decimal(str)`` gives the rational number specified by the string *str* in ordinary decimal floating-point notation (for example ``-3.25e-725``). .. macro:: AlgebraicNumberSerialized .. macro:: PolynomialRootIndexed .. macro:: PolynomialRootNearest .. macro:: Enclosure .. macro:: Approximation .. macro:: Guess .. macro:: Unknown Arithmetic operations ........................................................................ .. macro:: Pos .. macro:: Neg .. macro:: Add .. macro:: Sub .. macro:: Mul .. macro:: Div .. macro:: Pow .. macro:: Sqrt .. macro:: Root Inequalities ........................................................................ .. macro:: Less .. macro:: LessEqual .. macro:: Greater .. macro:: GreaterEqual .. macro:: EqualNearestDecimal Sets of numbers ........................................................................ .. macro:: NN ``NN`` is the set of natural numbers (including 0), `\mathbb{N}`. .. macro:: ZZ ``ZZ`` is the set of integers, `\mathbb{Z}`. .. macro:: QQ ``QQ`` is the set of rational numbers, `\mathbb{Q}`. .. macro:: RR ``RR`` is the set of real numbers, `\mathbb{R}`. .. macro:: CC ``CC`` is the set of complex numbers, `\mathbb{C}`. .. macro:: Primes ``Primes`` is the set of positive prime numbers, `\mathbb{P}` .. macro:: IntegersGreaterEqual ``IntegersGreaterEqual(x)``, given an extended real number *x*, gives the set `\mathbb{Z}_{\ge x}` of integers greater than or equal to *x*. .. macro:: IntegersLessEqual ``IntegersLessEqual(x)``, given an extended real number *x*, gives the set `\mathbb{Z}_{\le x}` of integers less than or equal to *x*. .. macro:: Range ``Range(a, b)``, given integers *a* and *b*, gives the set `\{a, a+1, \ldots, b\}` of integers between *a* and *b*. This is the empty set if *a* is greater than *b*. .. macro:: AlgebraicNumbers The set of complex algebraic numbers `\overline{\mathbb{Q}}`. .. macro:: RealAlgebraicNumbers The set of real algebraic numbers `\overline{\mathbb{Q}}_{\mathbb{R}}`. .. macro:: Interval ``Interval(a, b)``, given extended real numbers *a* and *b*, gives the closed interval `[a, b]`. .. macro:: OpenInterval ``OpenInterval(a, b)``, given extended real numbers *a* and *b*, gives the open interval `(a, b)`. .. macro:: ClosedOpenInterval ``ClosedOpenInterval(a, b)``, given extended real numbers *a* and *b*, gives the closed-open interval `[a, b)`. .. macro:: OpenClosedInterval ``OpenClosedInterval(a, b)``, given extended real numbers *a* and *b*, gives the closed-open interval `(a, b]`. .. macro:: RealBall ``RealBall(m, r)``, given a real number *m* and an extended real number *r*, gives the the closed real ball `[m \pm r]` with center *m* and radius *r*. .. macro:: OpenRealBall ``OpenRealBall(m, r)``, given a real number *m* and an extended real number *r*, gives the the open real ball `(m \pm r)` with center *m* and radius *r*. .. macro:: OpenComplexDisk ``OpenComplexDisk(m, r)``, given a complex number *m* and an extended real number *r*, gives the open complex disk `D(m, r)` with center *m* and radius *r*. .. macro:: ClosedComplexDisk ``ClosedComplexDisk(m, r)``, given a complex number *m* and a real number *r*, gives the closed complex disk `\overline{D}(m, r)` with center *m* and radius *r*. .. macro:: UpperHalfPlane ``UpperHalfPlane`` is the set `\mathbb{H}` of complex numbers with positive imaginary part. .. macro:: UnitCircle .. macro:: BernsteinEllipse .. macro:: Lattice Infinities and extended numbers ........................................................................ .. macro:: Infinity ``Infinity`` is the positive signed infinity `\infty`. .. macro:: UnsignedInfinity ``UnsignedInfinity`` is the unsigned infinity `\tilde \infty`. .. macro:: RealSignedInfinities ``RealSignedInfinities`` is the set of real signed infinities `\{+\infty, -\infty\}`. .. macro:: ComplexSignedInfinities ``ComplexSignedInfinities`` is the set of complex signed infinities `\{e^{i \theta} \cdot \infty : \theta \in \mathbb{R}\}`. .. macro:: RealInfinities ``RealInfinities`` is the set of real infinities (signed and unsigned) `\{+\infty, -\infty\} \cup \{\tilde \infty\}`. .. macro:: ComplexInfinities ``ComplexInfinities`` is the set of complex infinities (signed and unsigned) `\{e^{i \theta} \cdot \infty : \theta \in \mathbb{R}\} \cup \{\tilde \infty\}`. .. macro:: ExtendedRealNumbers ``ExtendedRealNumbers`` is the set of extended real numbers `\mathbb{R} \cup \{+\infty, -\infty\}`. .. macro:: ProjectiveRealNumbers ``ProjectiveRealNumbers`` is the set of projectively extended real numbers `\mathbb{R} \cup \{\tilde \infty\}`. .. macro:: SignExtendedComplexNumbers ``SignExtendedComplexNumbers`` is the set of complex numbers extended with signed infinities `\mathbb{C} \cup \{e^{i \theta} \cdot \infty : \theta \in \mathbb{R}\}`. .. macro:: ProjectiveComplexNumbers ``ProjectiveComplexNumbers`` is the set of projectively extended complex numbers (also known as the Riemann sphere) `\mathbb{C} \cup \{\tilde \infty\}`. .. macro:: RealSingularityClosure ``RealSingularityClosure`` is the Calcium singularity closure for real functions, encompassing real numbers, signed infinities, unsigned infinity, and *undefined* (u). This set is defined as `\mathbb{R}_{\text{Sing}} = \mathbb{R} \cup \{+\infty, -\infty\} \cup \{\tilde \infty\} \cup \{ \mathfrak{u} \}`. .. macro:: ComplexSingularityClosure ``ComplexSingularityClosure`` is the Calcium singularity closure for complex functions, encompassing complex numbers, signed infinities, unsigned infinity, and *undefined* (u). This set is defined as `\mathbb{C}_{\text{Sing}} = \mathbb{C} \cup \{e^{i \theta} \cdot \infty : \theta \in \mathbb{R}\} \cup \{\tilde \infty\} \cup \{ \mathfrak{u} \}`. Operators and calculus ------------------------------------------------------------------------ Sums and products ........................................................................ .. macro:: Sum .. macro:: Product .. macro:: PrimeSum .. macro:: PrimeProduct .. macro:: DivisorSum .. macro:: DivisorProduct Solutions and zeros ........................................................................ .. macro:: Zeros .. macro:: UniqueZero .. macro:: Solutions .. macro:: UniqueSolution Extreme values ........................................................................ .. macro:: Supremum .. macro:: Infimum .. macro:: Minimum .. macro:: Maximum .. macro:: ArgMin .. macro:: ArgMax .. macro:: ArgMinUnique .. macro:: ArgMaxUnique Limits ........................................................................ .. macro:: Limit .. macro:: SequenceLimit .. macro:: RealLimit .. macro:: LeftLimit .. macro:: RightLimit .. macro:: ComplexLimit .. macro:: MeromorphicLimit .. macro:: SequenceLimitInferior .. macro:: SequenceLimitSuperior .. macro:: AsymptoticTo Derivatives ........................................................................ .. macro:: Derivative .. macro:: RealDerivative .. macro:: ComplexDerivative .. macro:: ComplexBranchDerivative .. macro:: MeromorphicDerivative Integrals ........................................................................ .. macro:: Integral Complex analysis ........................................................................ .. macro:: Path .. macro:: CurvePath .. macro:: Poles .. macro:: IsHolomorphicOn .. macro:: IsMeromorphicOn .. macro:: Residue .. macro:: ComplexZeroMultiplicity .. macro:: AnalyticContinuation Matrices and linear algebra ------------------------------------------------------------------------ .. macro:: Matrix .. macro:: Row .. macro:: Column .. macro:: RowMatrix .. macro:: ColumnMatrix .. macro:: DiagonalMatrix .. macro:: Matrix2x2 .. macro:: ZeroMatrix .. macro:: IdentityMatrix .. macro:: Det .. macro:: Spectrum .. macro:: SingularValues .. macro:: Matrices .. macro:: SL2Z .. macro:: PSL2Z .. macro:: SpecialLinearGroup .. macro:: GeneralLinearGroup .. macro:: HilbertMatrix Polynomials, series and rings ------------------------------------------------------------------------ .. macro:: Pol .. macro:: Ser .. macro:: Polynomial .. macro:: Coefficient .. macro:: PolynomialDegree .. macro:: Polynomials .. macro:: PolynomialFractions .. macro:: FormalPowerSeries .. macro:: FormalLaurentSeries .. macro:: FormalPuiseuxSeries .. macro:: Zero .. macro:: One .. macro:: Characteristic .. macro:: Rings .. macro:: CommutativeRings .. macro:: Fields .. macro:: QuotientRing .. macro:: FiniteField .. macro:: EqualQSeriesEllipsis .. macro:: IndefiniteIntegralEqual .. macro:: QSeriesCoefficient .. macro:: Call .. macro:: CallIndeterminate Special functions ------------------------------------------------------------------------ Number parts and step functions ........................................................................ .. macro:: Abs .. macro:: Sign .. macro:: Re .. macro:: Im .. macro:: Arg .. macro:: Conjugate .. macro:: Csgn .. macro:: RealAbs .. macro:: Max .. macro:: Min .. macro:: Floor .. macro:: Ceil .. macro:: KroneckerDelta Primes and divisibility ........................................................................ .. macro:: IsOdd .. macro:: IsEven .. macro:: CongruentMod .. macro:: Divides .. macro:: Mod .. macro:: GCD .. macro:: LCM .. macro:: XGCD .. macro:: IsPrime .. macro:: Prime .. macro:: PrimePi .. macro:: DivisorSigma .. macro:: MoebiusMu .. macro:: EulerPhi .. macro:: DiscreteLog .. macro:: LegendreSymbol .. macro:: JacobiSymbol .. macro:: KroneckerSymbol .. macro:: SquaresR .. macro:: LiouvilleLambda Elementary functions ........................................................................ .. macro:: Exp .. macro:: Log .. macro:: Sin .. macro:: Cos .. macro:: Tan .. macro:: Cot .. macro:: Sec .. macro:: Csc .. macro:: Sinh .. macro:: Cosh .. macro:: Tanh .. macro:: Coth .. macro:: Sech .. macro:: Csch .. macro:: Asin .. macro:: Acos .. macro:: Atan .. macro:: Acot .. macro:: Asec .. macro:: Acsc .. macro:: Asinh .. macro:: Acosh .. macro:: Atanh .. macro:: Acoth .. macro:: Asech .. macro:: Acsch .. macro:: Atan2 .. macro:: Sinc .. macro:: LambertW Combinatorial functions ........................................................................ .. macro:: SloaneA .. macro:: SymmetricPolynomial .. macro:: Cyclotomic .. macro:: Fibonacci .. macro:: BernoulliB .. macro:: BernoulliPolynomial .. macro:: StirlingCycle .. macro:: StirlingS1 .. macro:: StirlingS2 .. macro:: EulerE .. macro:: EulerPolynomial .. macro:: BellNumber .. macro:: PartitionsP .. macro:: LandauG Gamma function and factorials ........................................................................ .. macro:: Factorial .. macro:: Binomial .. macro:: Gamma .. macro:: LogGamma .. macro:: DoubleFactorial .. macro:: RisingFactorial .. macro:: FallingFactorial .. macro:: HarmonicNumber .. macro:: DigammaFunction .. macro:: DigammaFunctionZero .. macro:: BetaFunction .. macro:: BarnesG .. macro:: LogBarnesG .. macro:: StirlingSeriesRemainder .. macro:: LogBarnesGRemainder Orthogonal polynomials ........................................................................ .. macro:: ChebyshevT .. macro:: ChebyshevU .. macro:: LegendreP .. macro:: JacobiP .. macro:: HermiteH .. macro:: LaguerreL .. macro:: GegenbauerC .. macro:: SphericalHarmonicY .. macro:: LegendrePolynomialZero .. macro:: GaussLegendreWeight Exponential integrals ........................................................................ .. macro:: Erf .. macro:: Erfc .. macro:: Erfi .. macro:: UpperGamma .. macro:: LowerGamma .. macro:: IncompleteBeta .. macro:: IncompleteBetaRegularized .. macro:: LogIntegral .. macro:: ExpIntegralE .. macro:: ExpIntegralEi .. macro:: SinIntegral .. macro:: SinhIntegral .. macro:: CosIntegral .. macro:: CoshIntegral .. macro:: FresnelC .. macro:: FresnelS Bessel and Airy functions ........................................................................ .. macro:: AiryAi .. macro:: AiryBi .. macro:: AiryAiZero .. macro:: AiryBiZero .. macro:: BesselJ .. macro:: BesselI .. macro:: BesselY .. macro:: BesselK .. macro:: HankelH1 .. macro:: HankelH2 .. macro:: BesselJZero .. macro:: BesselYZero .. macro:: CoulombF .. macro:: CoulombG .. macro:: CoulombH .. macro:: CoulombC .. macro:: CoulombSigma Hypergeometric functions ........................................................................ .. macro:: Hypergeometric0F1 .. macro:: Hypergeometric1F1 .. macro:: Hypergeometric1F2 .. macro:: Hypergeometric2F1 .. macro:: Hypergeometric2F2 .. macro:: Hypergeometric2F0 .. macro:: Hypergeometric3F2 .. macro:: HypergeometricU .. macro:: HypergeometricUStar .. macro:: HypergeometricUStarRemainder .. macro:: Hypergeometric0F1Regularized .. macro:: Hypergeometric1F1Regularized .. macro:: Hypergeometric1F2Regularized .. macro:: Hypergeometric2F1Regularized .. macro:: Hypergeometric2F2Regularized .. macro:: Hypergeometric3F2Regularized Zeta and L-functions ........................................................................ .. macro:: RiemannZeta .. macro:: RiemannZetaZero .. macro:: RiemannHypothesis .. macro:: RiemannXi .. macro:: HurwitzZeta .. macro:: LerchPhi .. macro:: PolyLog .. macro:: MultiZetaValue .. macro:: DirichletL .. macro:: DirichletLZero .. macro:: DirichletLambda .. macro:: DirichletCharacter .. macro:: DirichletGroup .. macro:: PrimitiveDirichletCharacters .. macro:: GeneralizedRiemannHypothesis .. macro:: ConreyGenerator .. macro:: GeneralizedBernoulliB .. macro:: StieltjesGamma .. macro:: KeiperLiLambda .. macro:: GaussSum Elliptic integrals ........................................................................ .. macro:: AGM .. macro:: AGMSequence .. macro:: EllipticK .. macro:: EllipticE .. macro:: EllipticPi .. macro:: IncompleteEllipticF .. macro:: IncompleteEllipticE .. macro:: IncompleteEllipticPi .. macro:: CarlsonRF .. macro:: CarlsonRG .. macro:: CarlsonRJ .. macro:: CarlsonRD .. macro:: CarlsonRC .. macro:: CarlsonHypergeometricR .. macro:: CarlsonHypergeometricT Elliptic, theta and modular functions ........................................................................ .. macro:: JacobiTheta .. macro:: JacobiThetaQ .. macro:: DedekindEta .. macro:: ModularJ .. macro:: ModularLambda .. macro:: EisensteinG .. macro:: EisensteinE .. macro:: DedekindSum .. macro:: WeierstrassP .. macro:: WeierstrassZeta .. macro:: WeierstrassSigma .. macro:: EllipticRootE .. macro:: HilbertClassPolynomial .. macro:: EulerQSeries .. macro:: DedekindEtaEpsilon .. macro:: ModularGroupAction .. macro:: ModularGroupFundamentalDomain .. macro:: ModularLambdaFundamentalDomain .. macro:: PrimitiveReducedPositiveIntegralBinaryQuadraticForms .. macro:: JacobiThetaEpsilon .. macro:: JacobiThetaPermutation Nonsemantic markup ........................................................................ .. macro:: Ellipsis ``Ellipsis`` renders as `\ldots` in LaTeX. It can be used to indicate missing function arguments for display purposes, but it has no predefined builtin semantics. .. macro:: Parentheses ``Parentheses(x)`` semantically represents ``x``, but renders with parentheses (`\left(x\right)`) when converted to LaTeX. .. macro:: Brackets ``Brackets(x)`` semantically represents ``x``, but renders with brackets (`\left[x\right]`) when converted to LaTeX. .. macro:: Braces ``Braces(x)`` semantically represents ``x``, but renders with braces (`\left\{x\right\}`) when converted to LaTeX. .. macro:: AngleBrackets ``AngleBrackets(x)`` semantically represents ``x``, but renders with angle brackets (`\left\langle x\right\rangle`) when converted to LaTeX. .. macro:: Logic ``Logic(x)`` semantically represents ``x``, but forces logical expressions within *x* to be rendered using symbols instead of text. .. macro:: ShowExpandedNormalForm ``ShowExpandedNormalForm(x)`` semantically represents ``x``, but displays the expanded normal form of the expression instead of rendering the expression verbatim. Warning: this triggers a nontrivial (potentially very expensive) computation. .. macro:: Subscript .. raw:: latex \newpage flint-3.1.3/doc/source/fft.rst000066400000000000000000000712461461254215100162230ustar00rootroot00000000000000.. _fft: **fft.h** -- Schoenhage-Strassen FFT ================================================================================ Split/combine FFT coefficients -------------------------------------------------------------------------------- .. function:: mp_size_t fft_split_limbs(mp_limb_t ** poly, mp_srcptr limbs, mp_size_t total_limbs, mp_size_t coeff_limbs, mp_size_t output_limbs) Split an integer ``(limbs, total_limbs)`` into coefficients of length ``coeff_limbs`` limbs and store as the coefficients of ``poly`` which are assumed to have space for ``output_limbs + 1`` limbs per coefficient. The coefficients of the polynomial do not need to be zeroed before calling this function, however the number of coefficients written is returned by the function and any coefficients beyond this point are not touched. .. function:: mp_size_t fft_split_bits(mp_limb_t ** poly, mp_srcptr limbs, mp_size_t total_limbs, flint_bitcnt_t bits, mp_size_t output_limbs) Split an integer ``(limbs, total_limbs)`` into coefficients of the given number of ``bits`` and store as the coefficients of ``poly`` which are assumed to have space for ``output_limbs + 1`` limbs per coefficient. The coefficients of the polynomial do not need to be zeroed before calling this function, however the number of coefficients written is returned by the function and any coefficients beyond this point are not touched. .. function:: void fft_combine_limbs(mp_limb_t * res, mp_limb_t ** poly, slong length, mp_size_t coeff_limbs, mp_size_t output_limbs, mp_size_t total_limbs) Evaluate the polynomial ``poly`` of the given ``length`` at ``B^coeff_limbs``, where ``B = 2^FLINT_BITS``, and add the result to the integer ``(res, total_limbs)`` throwing away any bits that exceed the given number of limbs. The polynomial coefficients are assumed to have at least ``output_limbs`` limbs each, however any additional limbs are ignored. If the integer is initially zero the result will just be the evaluation of the polynomial. .. function:: void fft_combine_bits(mp_limb_t * res, mp_limb_t ** poly, slong length, flint_bitcnt_t bits, mp_size_t output_limbs, mp_size_t total_limbs) Evaluate the polynomial ``poly`` of the given ``length`` at ``2^bits`` and add the result to the integer ``(res, total_limbs)`` throwing away any bits that exceed the given number of limbs. The polynomial coefficients are assumed to have at least ``output_limbs`` limbs each, however any additional limbs are ignored. If the integer is initially zero the result will just be the evaluation of the polynomial. Test helper functions -------------------------------------------------------------------------------- .. function:: void fermat_to_mpz(mpz_t m, mp_limb_t * i, mp_size_t limbs) Convert the Fermat number ``(i, limbs)`` modulo ``B^limbs + 1`` to an ``mpz_t m``. Assumes ``m`` has been initialised. This function is used only in test code. Arithmetic modulo a generalised Fermat number -------------------------------------------------------------------------------- .. function:: void mpn_negmod_2expp1(mp_limb_t * z, const mp_limb_t * a, mp_size_t limbs) Set ``z`` to the negation of the Fermat number `a` modulo ``B^limbs + 1``. The input ``a`` is expected to be fully reduced, and the output is fully reduced. Aliasing is permitted. .. function:: void mpn_addmod_2expp1_1(mp_limb_t * r, mp_size_t limbs, mp_limb_signed_t c) Adds the signed limb ``c`` to the generalised Fermat number ``r`` modulo ``B^limbs + 1``. The compiler should be able to inline this for the case that there is no overflow from the first limb. .. function:: void mpn_normmod_2expp1(mp_limb_t * t, mp_size_t limbs) Given ``t`` a signed integer of ``limbs + 1`` limbs in two's complement format, reduce ``t`` to the corresponding value modulo the generalised Fermat number ``B^limbs + 1``, where ``B = 2^FLINT_BITS``. .. function:: void mpn_mul_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d) Given ``i1`` a signed integer of ``limbs + 1`` limbs in two's complement format reduced modulo ``B^limbs + 1`` up to some overflow, compute ``t = i1*2^d`` modulo `p`. The result will not necessarily be fully reduced. The number of bits ``d`` must be nonnegative and less than ``FLINT_BITS``. Aliasing is permitted. .. function:: void mpn_div_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d) Given ``i1`` a signed integer of ``limbs + 1`` limbs in two's complement format reduced modulo ``B^limbs + 1`` up to some overflow, compute ``t = i1/2^d`` modulo `p`. The result will not necessarily be fully reduced. The number of bits ``d`` must be nonnegative and less than ``FLINT_BITS``. Aliasing is permitted. Generic butterflies -------------------------------------------------------------------------------- .. function:: void fft_adjust(mp_limb_t * r, mp_limb_t * i1, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w) Set ``r`` to ``i1`` times `z^i` modulo ``B^limbs + 1`` where `z` corresponds to multiplication by `2^w`. This can be thought of as part of a butterfly operation. We require `0 \leq i < n` where `nw =` ``limbs*FLINT_BITS``. Aliasing is not supported. .. function:: void fft_adjust_sqrt2(mp_limb_t * r, mp_limb_t * i1, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp) Set ``r`` to ``i1`` times `z^i` modulo ``B^limbs + 1`` where `z` corresponds to multiplication by `\sqrt{2}^w`. This can be thought of as part of a butterfly operation. We require `0 \leq i < 2\cdot n` and odd where `nw =` ``limbs*FLINT_BITS``. .. function:: void butterfly_lshB(mp_limb_t * t, mp_limb_t * u, mp_limb_t * i1, mp_limb_t * i2, mp_size_t limbs, mp_size_t x, mp_size_t y) We are given two integers ``i1`` and ``i2`` modulo ``B^limbs + 1`` which are not necessarily normalised. We compute ``t = (i1 + i2)*B^x`` and ``u = (i1 - i2)*B^y`` modulo `p`. Aliasing between inputs and outputs is not permitted. We require ``x`` and ``y`` to be less than ``limbs`` and nonnegative. .. function:: void butterfly_rshB(mp_limb_t * t, mp_limb_t * u, mp_limb_t * i1, mp_limb_t * i2, mp_size_t limbs, mp_size_t x, mp_size_t y) We are given two integers ``i1`` and ``i2`` modulo ``B^limbs + 1`` which are not necessarily normalised. We compute ``t = (i1 + i2)/B^x`` and ``u = (i1 - i2)/B^y`` modulo `p`. Aliasing between inputs and outputs is not permitted. We require ``x`` and ``y`` to be less than ``limbs`` and nonnegative. Radix 2 transforms -------------------------------------------------------------------------------- .. function:: void fft_butterfly(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w) Set ``s = i1 + i2``, ``t = z1^i*(i1 - i2)`` modulo ``B^limbs + 1`` where ``z1 = exp(Pi*I/n)`` corresponds to multiplication by `2^w`. Requires `0 \leq i < n` where `nw =` ``limbs*FLINT_BITS``. .. function:: void ifft_butterfly(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w) Set ``s = i1 + z1^i*i2``, ``t = i1 - z1^i*i2`` modulo ``B^limbs + 1`` where ``z1 = exp(-Pi*I/n)`` corresponds to division by `2^w`. Requires `0 \leq i < 2n` where `nw =` ``limbs*FLINT_BITS``. .. function:: void fft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2) The radix 2 DIF FFT works as follows: Input: ``[i0, i1, ..., i(m-1)]``, for `m = 2n` a power of `2`. Output: ``[r0, r1, ..., r(m-1)]`` ``= FFT[i0, i1, ..., i(m-1)]``. Algorithm: | `\bullet` Recursively compute ``[r0, r2, r4, ...., r(m-2)]`` | ``= FFT[i0+i(m/2), i1+i(m/2+1), ..., i(m/2-1)+i(m-1)]`` | | `\bullet` Let ``[t0, t1, ..., t(m/2-1)]`` | ``= [i0-i(m/2), i1-i(m/2+1), ..., i(m/2-1)-i(m-1)]`` | | `\bullet` Let ``[u0, u1, ..., u(m/2-1)]`` | ``= [z1^0*t0, z1^1*t1, ..., z1^(m/2-1)*t(m/2-1)]`` | where ``z1 = exp(2*Pi*I/m)`` corresponds to multiplication by `2^w`. | | `\bullet` Recursively compute ``[r1, r3, ..., r(m-1)]`` | ``= FFT[u0, u1, ..., u(m/2-1)]`` The parameters are as follows: `\bullet` ``2*n`` is the length of the input and output arrays `\bullet` `w` is such that `2^w` is an `2n`-th root of unity in the ring `\mathbf{Z}/p\mathbf{Z}` that we are working in, i.e. `p = 2^{wn} + 1` (here `n` is divisible by ``GMP_LIMB_BITS``) `\bullet` ``ii`` is the array of inputs (each input is an array of limbs of length ``wn/GMP_LIMB_BITS + 1`` (the extra limbs being a "carry limb"). Outputs are written in-place. We require `nw` to be at least 64 and the two temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. .. function:: void fft_truncate(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) As for ``fft_radix2`` except that only the first ``trunc`` coefficients of the output are computed and the input is regarded as having (implied) zero coefficients from coefficient ``trunc`` onwards. The coefficients must exist as the algorithm needs to use this extra space, but their value is irrelevant. The value of ``trunc`` must be divisible by 2. .. function:: void fft_truncate1(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) As for ``fft_radix2`` except that only the first ``trunc`` coefficients of the output are computed. The transform still needs all `2n` input coefficients to be specified. .. function:: void ifft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2) The radix 2 DIF IFFT works as follows: Input: ``[i0, i1, ..., i(m-1)]``, for `m = 2n` a power of `2`. Output: ``[r0, r1, ..., r(m-1)]`` ``= IFFT[i0, i1, ..., i(m-1)]``. Algorithm: `\bullet` Recursively compute ``[s0, s1, ...., s(m/2-1)]`` ``= IFFT[i0, i2, ..., i(m-2)]`` `\bullet` Recursively compute ``[t(m/2), t(m/2+1), ..., t(m-1)]`` ``= IFFT[i1, i3, ..., i(m-1)]`` `\bullet` Let ``[r0, r1, ..., r(m/2-1)]`` ``= [s0+z1^0*t0, s1+z1^1*t1, ..., s(m/2-1)+z1^(m/2-1)*t(m/2-1)]`` where ``z1 = exp(-2*Pi*I/m)`` corresponds to division by `2^w`. `\bullet` Let ``[r(m/2), r(m/2+1), ..., r(m-1)]`` ``= [s0-z1^0*t0, s1-z1^1*t1, ..., s(m/2-1)-z1^(m/2-1)*t(m/2-1)]`` The parameters are as follows: `\bullet` ``2*n`` is the length of the input and output arrays `\bullet` `w` is such that `2^w` is an `2n`-th root of unity in the ring `\mathbf{Z}/p\mathbf{Z}` that we are working in, i.e. `p = 2^{wn} + 1` (here `n` is divisible by ``GMP_LIMB_BITS``) `\bullet` ``ii`` is the array of inputs (each input is an array of limbs of length ``wn/GMP_LIMB_BITS + 1`` (the extra limbs being a "carry limb"). Outputs are written in-place. We require `nw` to be at least 64 and the two temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. .. function:: void ifft_truncate(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) As for ``ifft_radix2`` except that the output is assumed to have zeros from coefficient trunc onwards and only the first trunc coefficients of the input are specified. The remaining coefficients need to exist as the extra space is needed, but their value is irrelevant. The value of ``trunc`` must be divisible by 2. Although the implementation does not require it, we assume for simplicity that ``trunc`` is greater than `n`. The algorithm begins by computing the inverse transform of the first `n` coefficients of the input array. The unspecified coefficients of the second half of the array are then written: coefficient ``trunc + i`` is computed as a twist of coefficient ``i`` by a root of unity. The values of these coefficients are then equal to what they would have been if the inverse transform of the right hand side of the input array had been computed with full data from the start. The function ``ifft_truncate1`` is then called on the entire right half of the input array with this auxiliary data filled in. Finally a single layer of the IFFT is completed on all the coefficients up to ``trunc`` being careful to note that this involves doubling the coefficients from ``trunc - n`` up to ``n``. .. function:: void ifft_truncate1(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) Computes the first ``trunc`` coefficients of the radix 2 inverse transform assuming the first ``trunc`` coefficients are given and that the remaining coefficients have been set to the value they would have if an inverse transform had already been applied with full data. The algorithm is the same as for ``ifft_truncate`` except that the coefficients from ``trunc`` onwards after the inverse transform are not inferred to be zero but the supplied values. .. function:: void fft_butterfly_sqrt2(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp) Let `w = 2k + 1`, `i = 2j + 1`. Set ``s = i1 + i2``, ``t = z1^i*(i1 - i2)`` modulo ``B^limbs + 1`` where ``z1^2 = exp(Pi*I/n)`` corresponds to multiplication by `2^w`. Requires `0 \leq i < 2n` where `nw =` ``limbs*FLINT_BITS``. Here ``z1`` corresponds to multiplication by `2^k` then multiplication by ``(2^(3nw/4) - 2^(nw/4))``. We see ``z1^i`` corresponds to multiplication by ``(2^(3nw/4) - 2^(nw/4))*2^(j+ik)``. We first multiply by ``2^(j + ik + wn/4)`` then multiply by an additional ``2^(nw/2)`` and subtract. .. function:: void ifft_butterfly_sqrt2(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp) Let `w = 2k + 1`, `i = 2j + 1`. Set ``s = i1 + z1^i*i2``, ``t = i1 - z1^i*i2`` modulo ``B^limbs + 1`` where ``z1^2 = exp(-Pi*I/n)`` corresponds to division by `2^w`. Requires `0 \leq i < 2n` where `nw =` ``limbs*FLINT_BITS``. Here ``z1`` corresponds to division by `2^k` then division by ``(2^(3nw/4) - 2^(nw/4))``. We see ``z1^i`` corresponds to division by ``(2^(3nw/4) - 2^(nw/4))*2^(j+ik)`` which is the same as division by ``2^(j+ik + 1)`` then multiplication by ``(2^(3nw/4) - 2^(nw/4))``. Of course, division by ``2^(j+ik + 1)`` is the same as multiplication by ``2^(2*wn - j - ik - 1)``. The exponent is positive as `i \leq 2\cdot n`, `j < n`, `k < w/2`. We first multiply by ``2^(2*wn - j - ik - 1 + wn/4)`` then multiply by an additional ``2^(nw/2)`` and subtract. .. function:: void fft_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t trunc) As per ``fft_truncate`` except that the transform is twice the usual length, i.e. length `4n` rather than `2n`. This is achieved by making use of twiddles by powers of a square root of 2, not powers of 2 in the first layer of the transform. We require `nw` to be at least 64 and the three temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. .. function:: void ifft_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t trunc) As per ``ifft_truncate`` except that the transform is twice the usual length, i.e. length `4n` instead of `2n`. This is achieved by making use of twiddles by powers of a square root of 2, not powers of 2 in the final layer of the transform. We require `nw` to be at least 64 and the three temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. Matrix Fourier Transforms -------------------------------------------------------------------------------- .. function:: void fft_butterfly_twiddle(mp_limb_t * u, mp_limb_t * v, mp_limb_t * s, mp_limb_t * t, mp_size_t limbs, flint_bitcnt_t b1, flint_bitcnt_t b2) Set ``u = 2^b1*(s + t)``, ``v = 2^b2*(s - t)`` modulo ``B^limbs + 1``. This is used to compute ``u = 2^(ws*tw1)*(s + t)``, ``v = 2^(w+ws*tw2)*(s - t)`` in the matrix Fourier algorithm, i.e. effectively computing an ordinary butterfly with additional twiddles by ``z1^rc`` for row `r` and column `c` of the matrix of coefficients. Aliasing is not allowed. .. function:: void ifft_butterfly_twiddle(mp_limb_t * u, mp_limb_t * v, mp_limb_t * s, mp_limb_t * t, mp_size_t limbs, flint_bitcnt_t b1, flint_bitcnt_t b2) Set ``u = s/2^b1 + t/2^b1)``, ``v = s/2^b1 - t/2^b1`` modulo ``B^limbs + 1``. This is used to compute ``u = 2^(-ws*tw1)*s + 2^(-ws*tw2)*t)``, ``v = 2^(-ws*tw1)*s + 2^(-ws*tw2)*t)`` in the matrix Fourier algorithm, i.e. effectively computing an ordinary butterfly with additional twiddles by ``z1^(-rc)`` for row `r` and column `c` of the matrix of coefficients. Aliasing is not allowed. .. function:: void fft_radix2_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs) As for ``fft_radix2`` except that the coefficients are spaced by ``is`` in the array ``ii`` and an additional twist by ``z^c*i`` is applied to each coefficient where `i` starts at `r` and increases by ``rs`` as one moves from one coefficient to the next. Here ``z`` corresponds to multiplication by ``2^ws``. .. function:: void ifft_radix2_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs) As for ``ifft_radix2`` except that the coefficients are spaced by ``is`` in the array ``ii`` and an additional twist by ``z^(-c*i)`` is applied to each coefficient where `i` starts at `r` and increases by ``rs`` as one moves from one coefficient to the next. Here ``z`` corresponds to multiplication by ``2^ws``. .. function:: void fft_truncate1_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs, mp_size_t trunc) As per ``fft_radix2_twiddle`` except that the transform is truncated as per ``fft_truncate1``. .. function:: void ifft_truncate1_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs, mp_size_t trunc) As per ``ifft_radix2_twiddle`` except that the transform is truncated as per ``ifft_truncate1``. .. function:: void fft_mfa_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) This is as per the ``fft_truncate_sqrt2`` function except that the matrix Fourier algorithm is used for the left and right FFTs. The total transform length is `4n` where ``n = 2^depth`` so that the left and right transforms are both length `2n`. We require ``trunc > 2*n`` and that ``trunc`` is divisible by ``2*n1`` (explained below). The coefficients are produced in an order different from ``fft_truncate_sqrt2``. The matrix Fourier algorithm, which is applied to each transform of length `2n`, works as follows. We set ``n1`` to a power of 2 about the square root of `n`. The data is then thought of as a set of ``n2`` rows each with ``n1`` columns (so that ``n1*n2 = 2n``). The length `2n` transform is then computed using a whole pile of short transforms. These comprise ``n1`` column transforms of length ``n2`` followed by some twiddles by roots of unity (namely ``z^rc`` where `r` is the row and `c` the column within the data) followed by ``n2`` row transforms of length ``n1``. Along the way the data needs to be rearranged due to the fact that the short transforms output the data in binary reversed order compared with what is needed. The matrix Fourier algorithm provides better cache locality by decomposing the long length `2n` transforms into many transforms of about the square root of the original length. For better cache locality the sqrt2 layer of the full length `4n` transform is folded in with the column FFTs performed as part of the first matrix Fourier algorithm on the left half of the data. The second half of the data requires a truncated version of the matrix Fourier algorithm. This is achieved by truncating to an exact multiple of the row length so that the row transforms are full length. Moreover, the column transforms will then be truncated transforms and their truncated length needs to be a multiple of 2. This explains the condition on ``trunc`` given above. To improve performance, the extra twiddles by roots of unity are combined with the butterflies performed at the last layer of the column transforms. We require `nw` to be at least 64 and the three temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. .. function:: void ifft_mfa_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) This is as per the ``ifft_truncate_sqrt2`` function except that the matrix Fourier algorithm is used for the left and right IFFTs. The total transform length is `4n` where ``n = 2^depth`` so that the left and right transforms are both length `2n`. We require ``trunc > 2*n`` and that ``trunc`` is divisible by ``2*n1``. We set ``n1`` to a power of 2 about the square root of `n`. As per the matrix fourier FFT the sqrt2 layer is folded into the final column IFFTs for better cache locality and the extra twiddles that occur in the matrix Fourier algorithm are combined with the butterflied performed at the first layer of the final column transforms. We require `nw` to be at least 64 and the three temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. .. function:: void fft_mfa_truncate_sqrt2_outer(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) Just the outer layers of ``fft_mfa_truncate_sqrt2``. .. function:: void fft_mfa_truncate_sqrt2_inner(mp_limb_t ** ii, mp_limb_t ** jj, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc, mp_limb_t ** tt) The inner layers of ``fft_mfa_truncate_sqrt2`` and ``ifft_mfa_truncate_sqrt2`` combined with pointwise mults. .. function:: void ifft_mfa_truncate_sqrt2_outer(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) The outer layers of ``ifft_mfa_truncate_sqrt2`` combined with normalisation. Negacyclic multiplication -------------------------------------------------------------------------------- .. function:: void fft_negacyclic(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp) As per ``fft_radix2`` except that it performs a sqrt2 negacyclic transform of length `2n`. This is the same as the radix 2 transform except that the `i`-th coefficient of the input is first multiplied by `\sqrt{2}^{iw}`. We require `nw` to be at least 64 and the two temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. .. function:: void ifft_negacyclic(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp) As per ``ifft_radix2`` except that it performs a sqrt2 negacyclic inverse transform of length `2n`. This is the same as the radix 2 inverse transform except that the `i`-th coefficient of the output is finally divided by `\sqrt{2}^{iw}`. We require `nw` to be at least 64 and the two temporary space pointers to point to blocks of size ``n*w + FLINT_BITS`` bits. .. function:: void fft_naive_convolution_1(mp_limb_t * r, mp_limb_t * ii, mp_limb_t * jj, mp_size_t m) Performs a naive negacyclic convolution of ``ii`` with ``jj``, both of length `m`, and sets `r` to the result. This is essentially multiplication of polynomials modulo `x^m + 1`. .. function:: void _fft_mulmod_2expp1(mp_limb_t * r1, mp_limb_t * i1, mp_limb_t * i2, mp_size_t r_limbs, flint_bitcnt_t depth, flint_bitcnt_t w) Multiply ``i1`` by ``i2`` modulo ``B^r_limbs + 1`` where ``r_limbs = nw/FLINT_BITS`` with ``n = 2^depth``. Uses the negacyclic FFT convolution CRT'd with a 1 limb naive convolution. We require that ``depth`` and ``w`` have been selected as per the wrapper ``fft_mulmod_2expp1`` below. .. function:: slong fft_adjust_limbs(mp_size_t limbs) Given a number of limbs, returns a new number of limbs (no more than the next power of 2) which will work with the Nussbaumer code. It is only necessary to make this adjustment if ``limbs > FFT_MULMOD_2EXPP1_CUTOFF``. .. function:: void fft_mulmod_2expp1(mp_limb_t * r, mp_limb_t * i1, mp_limb_t * i2, mp_size_t n, mp_size_t w, mp_limb_t * tt) As per ``_fft_mulmod_2expp1`` but with a tuned cutoff below which more classical methods are used for the convolution. The temporary space is required to fit ``n*w + FLINT_BITS`` bits. There are no restrictions on `n`, but if ``limbs = n*w/FLINT_BITS`` then if ``limbs`` exceeds ``FFT_MULMOD_2EXPP1_CUTOFF`` the function ``fft_adjust_limbs`` must be called to increase the number of limbs to an appropriate value. Integer multiplication -------------------------------------------------------------------------------- .. function:: void mul_truncate_sqrt2(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2, flint_bitcnt_t depth, flint_bitcnt_t w) Integer multiplication using the radix 2 truncated sqrt2 transforms. Set ``(r1, n1 + n2)`` to the product of ``(i1, n1)`` by ``(i2, n2)``. This is achieved through an FFT convolution of length at most ``2^(depth + 2)`` with coefficients of size `nw` bits where ``n = 2^depth``. We require ``depth >= 6``. The input data is broken into chunks of data not exceeding ``(nw - (depth + 1))/2`` bits. If breaking the first integer into chunks of this size results in ``j1`` coefficients and breaking the second integer results in ``j2`` chunks then ``j1 + j2 - 1 <= 2^(depth + 2)``. If ``n = 2^depth`` then we require `nw` to be at least 64. .. function:: void mul_mfa_truncate_sqrt2(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2, flint_bitcnt_t depth, flint_bitcnt_t w) As for ``mul_truncate_sqrt2`` except that the cache friendly matrix Fourier algorithm is used. If ``n = 2^depth`` then we require `nw` to be at least 64. Here we also require `w` to be `2^i` for some `i \geq 0`. .. function:: void flint_mpn_mul_fft_main(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2) The main integer multiplication routine. Sets ``(r1, n1 + n2)`` to ``(i1, n1)`` times ``(i2, n2)``. We require ``n1 >= n2 > 0``. Convolution -------------------------------------------------------------------------------- .. function:: void fft_convolution(mp_limb_t ** ii, mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1, mp_limb_t ** tt) Perform an FFT convolution of ``ii`` with ``jj``, both of length ``4*n`` where ``n = 2^depth``. Assume that all but the first ``trunc`` coefficients of the output (placed in ``ii``) are zero. Each coefficient is taken modulo ``B^limbs + 1``. The temporary spaces ``t1``, ``t2`` and ``s1`` must have ``limbs + 1`` limbs of space and ``tt`` must have ``2*(limbs + 1)`` of free space. FFT Precaching ------------------------------------------------------------------------------- .. function:: void fft_precache(mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1) Precompute the FFT of ``jj`` for use with precache functions. The parameters are as for ``fft_convolution``. .. function:: void fft_convolution_precache(mp_limb_t ** ii, mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1, mp_limb_t ** tt) As per ``fft_convolution`` except that it is assumed ``fft_precache`` has been called on ``jj`` with the same parameters. This will then run faster than if ``fft_convolution`` had been run with the original ``jj``. flint-3.1.3/doc/source/fft_small.rst000066400000000000000000000102271461254215100174030ustar00rootroot00000000000000.. _fft-small: **fft_small.h** -- FFT modulo word-size primes =============================================================================== This module currently requires building FLINT with support for AVX2 or NEON instructions. Integer multiplication -------------------------------------------------------------------------------- .. type:: mpn_ctx_struct mpn_ctx_t Context object for multiplications allowing non-FFT moduli. The structure contains FFT context objects for multiple FFT primes (currently 8) together with tables for Chinese remaindering. .. function:: void mpn_ctx_init(mpn_ctx_t R, ulong p) Initialize multiplication context object with initial prime ``p``. .. function:: void mpn_ctx_clear(mpn_ctx_t R) Free memory allocated by the context object. .. function:: mpn_ctx_struct * get_default_mpn_ctx(void) Return a pointer to a cached thread-local context object used by default for multiplications. Calling :func:`flint_cleanup` or :func:`flint_cleanup_master` frees the cache. .. function:: void mpn_ctx_mpn_mul(mpn_ctx_t R, ulong * r1, const ulong * i1, ulong n1, const ulong * i2, ulong n2) void mpn_mul_default_mpn_ctx(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2) Writes to ``r1`` the product of the integers ``(i1, n1)`` and ``(i2, n2)``. Assumes that `n_1 \ge n_2 \ge 1`, respectively using a given context object ``R`` or the default thread-local object. Polynomial arithmetic --------------------------------------------------------------------------------- .. function:: void _nmod_poly_mul_mid_mpn_ctx(ulong * z, ulong zl, ulong zh, const ulong * a, ulong an, const ulong * b, ulong bn, nmod_t mod, mpn_ctx_t R) void _nmod_poly_mul_mid_default_mpn_ctx(mp_ptr res, slong zl, slong zh, mp_srcptr a, slong an, mp_srcptr b, slong bn, nmod_t mod) Writes to ``z`` the middle product containing coefficients in the range `[zl, zh)` of the product of the polynomials ``(a, an)`` and ``(b, bn)``, respectively using a given context object ``R`` or the default thread-local object. Assumes that `an \ge bn \ge 1`. .. function:: int _fmpz_poly_mul_mid_mpn_ctx(fmpz * z, ulong zl, ulong zh, const fmpz * a, ulong an, const fmpz * b, ulong bn, mpn_ctx_t R) int _fmpz_poly_mul_mid_default_mpn_ctx(fmpz * z, ulong zl, ulong zh, const fmpz * a, ulong an, const fmpz * b, ulong bn) Like the ``nmod`` functions. Performs the multiplication and returns 1 if there are sufficiently many primes ``R`` to compute the result; otherwise returns 0 without touching the output. .. function:: void _nmod_poly_divrem_mpn_ctx(ulong * q, ulong * r, const ulong * a, ulong an, const ulong * b, ulong bn, nmod_t mod, mpn_ctx_t R) Polynomial division with remainder. Preconditioned polynomial arithmetic --------------------------------------------------------------------------------- .. type:: mul_precomp_struct .. function:: void _mul_precomp_init(mul_precomp_struct * M, const ulong * b, ulong bn, ulong btrunc, ulong depth, nmod_t mod, mpn_ctx_t R) void _mul_precomp_clear(mul_precomp_struct * M) Represents ``(b, bn)`` in transformed form for preconditioned multiplication. .. function:: int _nmod_poly_mul_mid_precomp(ulong * z, ulong zl, ulong zh, const ulong * a, ulong an, mul_precomp_struct * M, nmod_t mod, mpn_ctx_t R) Polynomial multiplication given a precomputed transform ``M``. Returns 1 if successful, 0 if the precomputed transform is too short. .. type:: nmod_poly_divrem_precomp_struct .. function:: void _nmod_poly_divrem_precomp_init(nmod_poly_divrem_precomp_struct * M, const ulong * b, ulong bn, ulong Bn, nmod_t mod, mpn_ctx_t R) void _nmod_poly_divrem_precomp_clear(nmod_poly_divrem_precomp_struct * M) Represents ``(b, bn)`` and its inverse in transformed form for preconditioned multiplication. .. function:: int _nmod_poly_divrem_precomp(ulong * q, ulong * r, const ulong * a, ulong an, nmod_poly_divrem_precomp_struct * M, nmod_t mod, mpn_ctx_t R) Polynomial multiplication given a precomputed transform ``M``. Returns 1 if successful, 0 if the precomputed transform is too short. flint-3.1.3/doc/source/flint.rst000066400000000000000000000364061461254215100165570ustar00rootroot00000000000000.. _flint: **flint.h** -- global definitions =============================================================================== Macros ----------------------------------------------- The file ``flint.h`` contains various useful macros. The macro constant ``FLINT_BITS`` is set at compile time to be the number of bits per limb on the machine. FLINT requires it to be either 32 or 64 bits. Other architectures are not currently supported. The macro constant ``FLINT_D_BITS`` is set at compile time to be the number of bits per double on the machine or one less than the number of bits per limb, whichever is smaller. This will have the value `53` or `31` on currently supported architectures. Numerous internal functions using precomputed inverses only support operands up to ``FLINT_D_BITS`` bits, hence the macro. The macro ``FLINT_ABS(x)`` returns the absolute value of `x` for primitive signed numerical types. It might fail for least negative values such as ``INT_MIN`` and ``WORD_MIN``. The macro ``FLINT_MIN(x, y)`` returns the minimum of `x` and `y` for primitive signed or unsigned numerical types. This macro is only safe to use when `x` and `y` are of the same type, to avoid problems with integer promotion. Similar to the previous macro, ``FLINT_MAX(x, y)`` returns the maximum of `x` and `y`. The macro ``FLINT_SWAP(T, x, y)`` swaps ``x`` and ``y``, where ``x`` and ``y`` are of type ``T``. For instance, with ``x`` and ``y`` of type ``fmpz_poly_t`` , one can write ``FLINT_SWAP(fmpz_poly_struct, *x, *y)`` to swap the content of ``x`` with the content of ``y``. .. macro:: FLINT_SGN(x) Returns the sign of `x` where `x` is interpreted as a :type:`slong`, that is, returns `-1` if `x < 0`, `0` if `x = 0` and `1` if `x > 0`. .. function:: mp_limb_t FLINT_BIT_COUNT(mp_limb_t x) Returns the number of binary bits required to represent an ``ulong x``. If `x` is zero, returns `0`. Derived from this there are the two macros ``FLINT_FLOG2(x)`` and ``FLINT_CLOG2(x)`` which, for any `x \geq 1`, compute `\lfloor \log_2 x \rfloor` and `\lceil \log_2 x \rceil`. To determine the current FLINT version a number of macros are available. For example, if the current FLINT version is ``2.4.0`` then ``__FLINT_VERSION`` will have the value `2`, ``__FLINT_MINOR`` will have the value `4` and ``__FLINT_PATCHLEVEL`` will have the value `0`. The ``__FLINT_RELEASE`` macro gives a single number representing the FLINT version. For example, it will have the value ``20400`` for version ``2.4.0``. The ``FLINT_VERSION`` macro is a static text string giving the version number, e.g. "2.4" or "2.4.1". Note that if the final digit is a zero it is suppressed. Integer types ----------------------------------------------- The *char*, *short* and *int* types are assumed to be two's complement types with exactly 8, 16 and 32 bits. This is not technically guaranteed by the C standard, but it is true on mainstream platforms. Since the C types *long* and *unsigned long* do not have a standardized size in practice, FLINT defines *slong* and *ulong* types which are guaranteed to be 32 bits on a 32-bit system and 64 bits on a 64-bit system. They are also guaranteed to have the same size as GMP's :type:`mp_limb_t`. GMP builds with a different limb size configuration are not supported at all. For convenience, the macro *FLINT_BITS* specifies the word length (32 or 64) of the system. .. type:: slong The *slong* type is used for precisions, bit counts, loop indices, array sizes, and the like, even when those values are known to be nonnegative. It is also used for small integer-valued coefficients. In method names, an *slong* parameter is denoted by *si*, for example :func:`arb_add_si`. The constants *WORD_MIN* and *WORD_MAX* give the range of this type. This type can be printed with *flint_printf* using the format string ``%wd``. .. type:: ulong The *ulong* type is used for integer-valued coefficients that are known to be unsigned, and for values that require the full 32-bit or 64-bit range. In method names, a *ulong* parameter is denoted by *ui*, for example :func:`arb_add_ui`. The constant *UWORD_MAX* gives the range of this type. This type can be printed with *flint_printf* using the format string ``%wu``. The following GMP-defined types are used in methods that manipulate the internal representation of numbers (using limb arrays). .. type:: mp_limb_t A single limb. .. type:: mp_ptr Pointer to a writable array of limbs. .. type:: mp_srcptr Pointer to a read-only array of limbs. .. type:: mp_size_t A limb count (always nonnegative). .. type:: flint_bitcnt_t A bit offset within an array of limbs (always nonnegative). Allocation Functions ----------------------------------------------- .. function:: void * flint_malloc(size_t size) Allocate ``size`` bytes of memory. .. function:: void * flint_realloc(void * ptr, size_t size) Reallocate an area of memory previously allocated by :func:`flint_malloc`, :func:`flint_realloc`, or :func:`flint_calloc`. .. function:: void * flint_calloc(size_t num, size_t size) Allocate ``num`` objects of ``size`` bytes each, and zero the allocated memory. .. function:: void flint_free(void * ptr) Free a section of memory allocated by :func:`flint_malloc`, :func:`flint_realloc`, or :func:`flint_calloc`. Random Numbers ------------------ .. type:: flint_rand_s A structure holding the state of a flint pseudo random number generator. .. type:: flint_rand_t An array of length 1 of :type:`flint_rand_s`. .. function:: flint_rand_s * flint_rand_alloc(void) Allocates a ``flint_rand_t`` object to be used like a heap-allocated ``flint_rand_t`` in external libraries. The random state is not initialised. .. function:: void flint_rand_free(flint_rand_s * state) Frees a random state object as allocated using :func:`flint_rand_alloc`. .. function:: void flint_randinit(flint_rand_t state) Initialize a :type:`flint_rand_t`. .. function:: void flint_randclear(flint_rand_t state) Free all memory allocated by :func:`flint_rand_init`. Thread functions ----------------------- .. function:: void flint_set_num_threads(int num_threads) Set up a thread pool of ``num_threads - 1`` worker threads (in addition to the master thread) and set the maximum number of worker threads the master thread can start to ``num_threads - 1``. This function may only be called globally from the master thread. It can also be called at a global level to change the size of the thread pool, but an exception is raised if the thread pool is in use (threads have been woken but not given back). The function cannot be called from inside worker threads. .. function:: int flint_get_num_threads(void) When called at the global level, this function returns one more than the number of worker threads in the Flint thread pool, i.e. it returns the number of workers in the thread pool plus one for the master thread. In general, this function returns one more than the number of additional worker threads that can be started by the current thread. Use :func:`thread_pool_wake` to set this number for a given worker thread. See also: :func:`flint_get_num_available_threads`. .. function:: int flint_set_num_workers(int num_workers) Restricts the number of worker threads that can be started by the current thread to ``num_workers``. This function can be called from any thread. Assumes that the Flint thread pool is already set up. The function returns the old number of worker threads that can be started. The function can only be used to reduce the number of workers that can be started from a thread. It cannot be used to increase the number. If a higher number is passed, the function has no effect. The number of workers must be restored to the original value by a call to :func:`flint_reset_num_workers` before the thread is returned to the thread pool. The main use of this function and :func:`flint_reset_num_workers` is to cheaply and temporarily restrict the number of workers that can be started, e.g. by a function that one wishes to call from a thread, and cheaply restore the number of workers to its original value before exiting the current thread. .. function:: void flint_reset_num_workers(int num_workers) After a call to :func:`flint_set_num_workers` this function must be called to set the number of workers that may be started by the current thread back to its original value. Input/Output ----------------- .. function:: int flint_printf(const char * format, ...) int flint_fprintf(FILE * fs, const char * format, ...) int flint_vprintf(const char * format, va_list vlist) int flint_vfprintf(FILE * fs, const char * format, va_list vlist) These functions are extensions of the C standard library functions ``printf``, ``fprintf``, ``vprintf``, and ``vfprintf``. The first extension is the addition of the length modifier ``w``, used for printing the types :type:`ulong`, :type:`slong` and :type:`mp_limb_t`. As these types are either defined as signed and unsigned ``long int`` or ``long long int``, this comes in handy. Just like ``long int`` and ``long long int``, the conversion format specifier are allowed to be ``d``, ``i``, ``o``, ``x``, ``X`` and ``u``. The second and final extension is printing of FLINT types. Currently supported types are the base types :type:`ulong`, :type:`slong`, :type:`fmpz_t`, :type:`fmpq_t`, :type:`mag_t`, :type:`arf_t`, :type:`arb_t` and :type:`acb_t` as well as the context structures for modulo arithmetic :type:`nmod_t` and :type:`fmpz_mod_ctx_t`. We also support the GMP types ``mpz_t`` and ``mpq_t``. We currently support printing vectors of pointers to the following base types: :type:`slong`, :type:`ulong`, :type:`fmpz`, :type:`fmpq`, :type:`mag_struct`, :type:`arf_struct`, :type:`arb_struct` and :type:`acb_struct`. We also support printing matrices of the following types: :type:`nmod_mat_t`, :type:`fmpz_mat_t`, :type:`fmpq_mat_t`, :type:`arb_mat_t` and :type:`acb_mat_t`. Finally, we currently support printing polynomial of the following types: :type:`nmod_poly_t`, :type:`fmpz_poly_t`, :type:`fmpq_poly_t`, :type:`arb_poly_t` and :type:`acb_poly_t`. .. code-block:: c ulong bulong; slong bslong; fmpz_t bfmpz; fmpq_t bfmpq; mag_t bmag; arf_t barf; arb_t barb; acb_t bacb; nmod_t bnmod; fmpz_mod_ctx_t bfmpz_mod_ctx; mpz_t bmpz; mpq_t bmpq; /* Initialize and set variables */ flint_printf( "ulong: %{ulong}\n" "slong: %{slong}\n" "fmpz: %{fmpz}\n" "fmpq: %{fmpq}\n" "mag: %{mag}\n" "arf: %{arf}\n" "arb: %{arb}\n" "acb: %{acb}\n" "nmod: %{nmod}\n" "fmpz_mod_ctx: %{fmpz_mod_ctx}\n" "mpz: %{mpz}\n" "mpq: %{mpq}\n", bulong, bslong, bfmpz, bfmpq, bmag, barf, barb, bacb, bnmod, bfmpz_mod_ctx, bmpz, bmpq); .. code-block:: c slong * vslong; slong vslong_len; mp_ptr vnmod; slong vnmod_len; /* The base type for nmod is ulong */ fmpz * vfmpz; slong vfmpz_len; /* fmpz_mod vectors are given by the type `fmpz *' */ fmpq * vfmpq; slong vfmpq_len; mag_ptr vmag; slong vmag_len; arf_ptr varf; slong varf_len; arb_ptr varb; slong varb_len; acb_ptr vacb; slong vacb_len; /* Initialize and set variables */ flint_printf( "slong vector: %{slong*}\n" "nmod vector: %{ulong*}\n" "fmpz vector: %{fmpz*}\n" "fmpq vector: %{fmpq*}\n" "mag vector: %{mag*}\n" "arf vector: %{arf*}\n" "arb vector: %{arb*}\n" "acb vector: %{acb*}\n" vslong, vslong_len, /* They require a vector length specifier */ vnmod, vnmod_len, vfmpz, vfmpz_len, vfmpq, vfmpq_len, vmag, vmag_len, varf, varf_len, varb, varb_len, vacb, vacb_len); .. code-block:: c nmod_mat_t mnmod; fmpz_mat_t mfmpz; fmpz_mod_mat_t mfmpz_mod; fmpq_mat_t mfmpq; arb_mat_t marb; acb_mat_t macb; /* Initialize and set variables */ flint_printf( "nmod matrix: %{nmod_mat}\n" "fmpz matrix: %{fmpz_mat}\n" "fmpz_mod matrix: %{fmpz_mod_mat}\n" "fmpq matrix: %{fmpq_mat}\n" "arb vector: %{arb_mat}\n" "acb vector: %{acb_mat}\n" mnmod, mfmpz, mfmpz_mod, mfmpq, marb, macb); .. code-block:: c nmod_poly_t pnmod; fmpz_poly_t pfmpz; fmpz_mod_poly_t pfmpz_mod; fmpq_poly_t pfmpq; arb_poly_t parb; acb_poly_t pacb; /* Initialize and set variables */ flint_printf( "nmod polynomial: %{nmod_poly}\n" "fmpz polynomial: %{fmpz_poly}\n" "fmpz_mod polynomial: %{fmpz_mod_poly}\n" "fmpq polynomial: %{fmpq_poly}\n" "arb polynomial: %{arb_poly}\n" "acb polynomial: %{acb_poly}\n" pnmod, pfmpz, pfmpz_mod, pfmpq, parb, pacb); .. note:: Printing of FLINT types does not currently support any flags. .. note:: Any use of ``%n`` flags will be invalid, but will not generate any error. .. note:: Invalid formats using variable minimum field width and/or precision such as ``"%* p"`` may be wrongly parsed, and may result in a different result compared to the C standard library functions. .. function:: int flint_sprintf(char * s, const char * str, ...) This functions is an extensions of the C standard library functions ``sprintf``. It is currently advised to not use this function as it is currently not coherent with :func:`flint_printf`. .. function:: int flint_scanf(const char * str, ...) int flint_fscanf(FILE * f, const char * str, ...) int flint_sscanf(const char * s, const char * str, ...) These are equivalent to the standard library functions ``scanf``, ``fscanf``, and ``sscanf`` with an additional length modifier "w" for reading an :type:`mp_limb_t` type. Exceptions ----------------- .. function:: void flint_abort(void) FLINT version of the C standard function ``abort``. .. function:: void flint_set_abort(void (* func)(void)) Sets the :func:`flint_abort` function to call ``func`` instead of ``abort``. .. enum:: flint_err_t An error code with one of the following values .. macro:: FLINT_ERROR Describes a generic error. .. macro:: FLINT_OVERFLOW Describes an overflow. .. macro:: FLINT_IMPINV Describes an impossible inversion. .. macro:: FLINT_DOMERR Describes a domain error. .. macro:: FLINT_DIVZERO Describes a division by zero. .. macro:: FLINT_EXPOF Describes a exponent overflow. .. macro:: FLINT_INEXACT Describes an inexact operation. .. macro:: FLINT_TEST_FAIL Describes a test fail. .. function:: void flint_throw(flint_err_t exc, const char * msg, ...) Throws an error of type ``exc`` with message ``msg`` and aborts via :func:`flint_abort`. The printing back-end function is :func:`flint_fprintf`, and so it allows for printing of FLINT types as well. flint-3.1.3/doc/source/fmpq.rst000066400000000000000000000752401461254215100164050ustar00rootroot00000000000000.. _fmpq: **fmpq.h** -- rational numbers =============================================================================== The :type:`fmpq_t` data type represents rational numbers as fractions of multiprecision integers. An :type:`fmpq_t` is an array of length 1 of type :type:`fmpq`, with :type:`fmpq` being implemented as a pair of :type:`fmpz`'s representing numerator and denominator. This format is designed to allow rational numbers with small numerators or denominators to be stored and manipulated efficiently. When components no longer fit in single machine words, the cost of :type:`fmpq_t` arithmetic is roughly the same as that of ``mpq_t`` arithmetic, plus a small amount of overhead. A fraction is said to be in canonical form if the numerator and denominator have no common factor and the denominator is positive. Except where otherwise noted, all functions in the :type:`fmpq` module assume that inputs are in canonical form, and produce outputs in canonical form. The user can manipulate the numerator and denominator of an :type:`fmpq_t` as arbitrary integers, but then becomes responsible for canonicalising the number (for example by calling ``fmpq_canonicalise``) before passing it to any library function. For most operations, both a function operating on :type:`fmpq_t`'s and an underscore version operating on :type:`fmpz_t` components are provided. The underscore functions may perform less error checking, and may impose limitations on aliasing between the input and output variables, but generally assume that the components are in canonical form just like the non-underscore functions. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpq An fmpq is implemented as a struct containing two fmpz's, one for the numerator, and one for the denominator. .. type:: fmpq_t An array of length 1 of fmpq's. This is used to pass fmpq's around by reference without fuss, similar to the way mpq_t's work. .. function:: fmpz * fmpq_numref(const fmpq_t x) fmpz * fmpq_denref(const fmpq_t x) Returns respectively a pointer to the numerator and denominator of x. Memory management -------------------------------------------------------------------------------- .. function:: void fmpq_init(fmpq_t x) Initialises the ``fmpq_t`` variable ``x`` for use. Its value is set to 0. .. function:: void fmpq_clear(fmpq_t x) Clears the ``fmpq_t`` variable ``x``. To use the variable again, it must be re-initialised with ``fmpq_init``. Canonicalisation -------------------------------------------------------------------------------- .. function:: void fmpq_canonicalise(fmpq_t res) Puts ``res`` in canonical form: the numerator and denominator are reduced to lowest terms, and the denominator is made positive. If the numerator is zero, the denominator is set to one. If the denominator is zero, the outcome of calling this function is undefined, regardless of the value of the numerator. .. function:: void _fmpq_canonicalise(fmpz_t num, fmpz_t den) Does the same thing as ``fmpq_canonicalise``, but for numerator and denominator given explicitly as ``fmpz_t`` variables. Aliasing of ``num`` and ``den`` is not allowed. .. function:: int fmpq_is_canonical(const fmpq_t x) Returns nonzero if ``fmpq_t`` x is in canonical form (as produced by ``fmpq_canonicalise``), and zero otherwise. .. function:: int _fmpq_is_canonical(const fmpz_t num, const fmpz_t den) Does the same thing as ``fmpq_is_canonical``, but for numerator and denominator given explicitly as ``fmpz_t`` variables. Basic assignment -------------------------------------------------------------------------------- .. function:: void fmpq_set(fmpq_t dest, const fmpq_t src) Sets ``dest`` to a copy of ``src``. No canonicalisation is performed. .. function:: void fmpq_swap(fmpq_t op1, fmpq_t op2) Swaps the two rational numbers ``op1`` and ``op2``. .. function:: void fmpq_neg(fmpq_t dest, const fmpq_t src) Sets ``dest`` to the additive inverse of ``src``. .. function:: void fmpq_abs(fmpq_t dest, const fmpq_t src) Sets ``dest`` to the absolute value of ``src``. .. function:: void fmpq_zero(fmpq_t res) Sets the value of ``res`` to 0. .. function:: void fmpq_one(fmpq_t res) Sets the value of ``res`` to `1`. Comparison -------------------------------------------------------------------------------- .. function:: int fmpq_is_zero(const fmpq_t res) Returns nonzero if ``res`` has value 0, and returns zero otherwise. .. function:: int fmpq_is_one(const fmpq_t res) Returns nonzero if ``res`` has value `1`, and returns zero otherwise. .. function:: int fmpq_is_pm1(const fmpq_t res) Returns nonzero if ``res`` has value `\pm{1}` and zero otherwise. .. function:: int fmpq_equal(const fmpq_t x, const fmpq_t y) int fmpq_equal_fmpz(const fmpq_t x, const fmpz_t y) int fmpq_equal_si(fmpq_t x, slong y) int fmpq_equal_ui(fmpq_t x, ulong y) Returns nonzero if ``x`` and ``y`` are equal, and zero otherwise. .. function:: int fmpq_sgn(const fmpq_t x) Returns the sign of the rational number `x`. That is, returns `-1` if `x < 0`, `1` if `x > 0` and `0` if `x = 0`. .. function:: int fmpq_cmp(const fmpq_t x, const fmpq_t y) int fmpq_cmp_fmpz(const fmpq_t x, const fmpz_t y) int fmpq_cmp_si(const fmpq_t x, slong y) int fmpq_cmp_ui(const fmpq_t x, ulong y) Returns negative if `x < y`, zero if `x = y`, and positive if `x > y`. .. function:: void fmpq_height(fmpz_t height, const fmpq_t x) Sets ``height`` to the height of `x`, defined as the larger of the absolute values of the numerator and denominator of `x`. .. function:: flint_bitcnt_t fmpq_height_bits(const fmpq_t x) Returns the number of bits in the height of `x`. Conversion -------------------------------------------------------------------------------- .. function:: void fmpq_set_fmpz_frac(fmpq_t res, const fmpz_t p, const fmpz_t q) Sets ``res`` to the canonical form of the fraction ``p / q``. This is equivalent to assigning the numerator and denominator separately and calling ``fmpq_canonicalise``. .. function:: void fmpq_get_mpz_frac(mpz_t a, mpz_t b, fmpq_t c) Sets ``a``, ``b`` to the numerator and denominator of ``c`` respectively. .. function:: void fmpq_set_si(fmpq_t res, slong p, ulong q) Sets ``res`` to the canonical form of the fraction ``p / q``. .. function:: void _fmpq_set_si(fmpz_t rnum, fmpz_t rden, slong p, ulong q) Sets ``(rnum, rden)`` to the canonical form of the fraction ``p / q``. ``rnum`` and ``rden`` may not be aliased. .. function:: void fmpq_set_ui(fmpq_t res, ulong p, ulong q) Sets ``res`` to the canonical form of the fraction ``p / q``. .. function:: void _fmpq_set_ui(fmpz_t rnum, fmpz_t rden, ulong p, ulong q) Sets ``(rnum, rden)`` to the canonical form of the fraction ``p / q``. ``rnum`` and ``rden`` may not be aliased. .. function:: void fmpq_set_mpq(fmpq_t dest, const mpq_t src) Sets the value of ``dest`` to that of the ``mpq_t`` variable ``src``. .. function:: int fmpq_set_str(fmpq_t dest, const char * s, int base) Sets the value of ``dest`` to the value represented in the string ``s`` in base ``base``. Returns 0 if no error occurs. Otherwise returns -1 and ``dest`` is set to zero. .. function:: double fmpq_get_d(const fmpq_t f) Returns `f` as a ``double``, rounding towards zero if ``f`` cannot be represented exactly. The return is system dependent if ``f`` is too large or too small to fit in a ``double``. .. function:: void fmpq_get_mpq(mpq_t dest, const fmpq_t src) Sets the value of ``dest`` .. function:: int fmpq_get_mpfr(mpfr_t dest, const fmpq_t src, mpfr_rnd_t rnd) Sets the MPFR variable ``dest`` to the value of ``src``, rounded to the nearest representable binary floating-point value in direction ``rnd``. Returns the sign of the rounding, according to MPFR conventions. **Note:** Requires that ``mpfr.h`` has been included before any FLINT header is included. .. function:: char * _fmpq_get_str(char * str, int b, const fmpz_t num, const fmpz_t den) char * fmpq_get_str(char * str, int b, const fmpq_t x) Prints the string representation of `x` in base `b \in [2, 36]` to a suitable buffer. If ``str`` is not ``NULL``, this is used as the buffer and also the return value. If ``str`` is ``NULL``, allocates sufficient space and returns a pointer to the string. .. function:: void flint_mpq_init_set_readonly(mpq_t z, const fmpq_t f) Sets the uninitialised ``mpq_t`` `z` to the value of the readonly ``fmpq_t`` `f`. Note that it is assumed that `f` does not change during the lifetime of `z`. The rational `z` has to be cleared by a call to :func:`flint_mpq_clear_readonly`. The suggested use of the two functions is as follows:: fmpq_t f; ... { mpq_t z; flint_mpq_init_set_readonly(z, f); foo(..., z); flint_mpq_clear_readonly(z); } This provides a convenient function for user code, only requiring to work with the types ``fmpq_t`` and ``mpq_t``. .. function:: void flint_mpq_clear_readonly(mpq_t z) Clears the readonly ``mpq_t`` `z`. .. function:: void fmpq_init_set_readonly(fmpq_t f, const mpq_t z) Sets the uninitialised ``fmpq_t`` `f` to a readonly version of the rational `z`. Note that the value of `z` is assumed to remain constant throughout the lifetime of `f`. The ``fmpq_t`` `f` has to be cleared by calling the function :func:`fmpq_clear_readonly`. The suggested use of the two functions is as follows:: mpq_t z; ... { fmpq_t f; fmpq_init_set_readonly(f, z); foo(..., f); fmpq_clear_readonly(f); } .. function:: void fmpq_clear_readonly(fmpq_t f) Clears the readonly ``fmpq_t`` `f`. Input and output -------------------------------------------------------------------------------- .. function:: int fmpq_fprint(FILE * file, const fmpq_t x) Prints ``x`` as a fraction to the stream ``file``. The numerator and denominator are printed verbatim as integers, with a forward slash (/) printed in between. In case of success, returns a positive number. In case of failure, returns a non-positive number. .. function:: int _fmpq_fprint(FILE * file, const fmpz_t num, const fmpz_t den) Does the same thing as ``fmpq_fprint``, but for numerator and denominator given explicitly as ``fmpz_t`` variables. In case of success, returns a positive number. In case of failure, returns a non-positive number. .. function:: int fmpq_print(const fmpq_t x) Prints ``x`` as a fraction. The numerator and denominator are printed verbatim as integers, with a forward slash (/) printed in between. In case of success, returns a positive number. In case of failure, returns a non-positive number. .. function:: int _fmpq_print(const fmpz_t num, const fmpz_t den) Does the same thing as ``fmpq_print``, but for numerator and denominator given explicitly as ``fmpz_t`` variables. In case of success, returns a positive number. In case of failure, returns a non-positive number. Random number generation -------------------------------------------------------------------------------- .. function:: void fmpq_randtest(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits) Sets ``res`` to a random value, with numerator and denominator having up to ``bits`` bits. The resulting fraction will be in canonical form. This function has an increased probability of generating special values which are likely to trigger corner cases. .. function:: void _fmpq_randtest(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits) Does the same thing as ``fmpq_randtest``, but for numerator and denominator given explicitly as ``fmpz_t`` variables. Aliasing of ``num`` and ``den`` is not allowed. .. function:: void fmpq_randtest_not_zero(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits) As per ``fmpq_randtest``, but the result will not be `0`. If ``bits`` is set to `0`, an exception will result. .. function:: void fmpq_randbits(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits) Sets ``res`` to a random value, with numerator and denominator both having exactly ``bits`` bits before canonicalisation, and then puts ``res`` in canonical form. Note that as a result of the canonicalisation, the resulting numerator and denominator can be slightly smaller than ``bits`` bits. .. function:: void _fmpq_randbits(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits) Does the same thing as ``fmpq_randbits``, but for numerator and denominator given explicitly as ``fmpz_t`` variables. Aliasing of ``num`` and ``den`` is not allowed. Arithmetic -------------------------------------------------------------------------------- .. function:: void fmpq_add(fmpq_t res, const fmpq_t op1, const fmpq_t op2) void fmpq_sub(fmpq_t res, const fmpq_t op1, const fmpq_t op2) void fmpq_mul(fmpq_t res, const fmpq_t op1, const fmpq_t op2) void fmpq_div(fmpq_t res, const fmpq_t op1, const fmpq_t op2) Sets ``res`` respectively to ``op1 + op2``, ``op1 - op2``, ``op1 * op2``, or ``op1 / op2``. Division by zero results in an error. Aliasing between any combination of the variables is allowed. .. function:: void _fmpq_add(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) void _fmpq_sub(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) void _fmpq_mul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) void _fmpq_div(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) Sets ``(rnum, rden)`` to the canonical form of the sum, difference, product or quotient respectively of the fractions represented by ``(op1num, op1den)`` and ``(op2num, op2den)``. Aliasing between any combination of the variables is allowed, whilst no numerator is aliased with a denominator. .. function:: void _fmpq_add_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r) void _fmpq_sub_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r) void _fmpq_add_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r) void _fmpq_sub_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r) void _fmpq_add_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r) void _fmpq_sub_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r) Sets ``(rnum, rden)`` to the canonical form of the sum or difference respectively of the fractions represented by ``(p, q)`` and ``(r, 1)``. Numerators may not be aliased with denominators. .. function:: void fmpq_add_si(fmpq_t res, const fmpq_t op1, slong c) void fmpq_sub_si(fmpq_t res, const fmpq_t op1, slong c) void fmpq_add_ui(fmpq_t res, const fmpq_t op1, ulong c) void fmpq_sub_ui(fmpq_t res, const fmpq_t op1, ulong c) void fmpq_add_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c) void fmpq_sub_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c) Sets ``res`` to the sum or difference respectively of the fraction ``op1`` and the integer `c`. .. function:: void _fmpq_mul_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r) Sets ``(rnum, rden)`` to the product of ``(p, q)`` and the integer `r`. .. function:: void fmpq_mul_si(fmpq_t res, const fmpq_t op1, slong c) Sets ``res`` to the product of ``op1`` and the integer `c`. .. function:: void _fmpq_mul_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r) Sets ``(rnum, rden)`` to the product of ``(p, q)`` and the integer `r`. .. function:: void fmpq_mul_ui(fmpq_t res, const fmpq_t op1, ulong c) Sets ``res`` to the product of ``op1`` and the integer `c`. .. function:: void fmpq_addmul(fmpq_t res, const fmpq_t op1, const fmpq_t op2) void fmpq_submul(fmpq_t res, const fmpq_t op1, const fmpq_t op2) Sets ``res`` to ``res + op1 * op2`` or ``res - op1 * op2``, respectively. Aliasing between any combination of the variables is allowed. .. function:: void _fmpq_addmul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) void _fmpq_submul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) Sets ``(rnum, rden)`` to the canonical form of the fraction ``(rnum, rden) + (op1num, op1den) * (op2num, op2den)`` or ``(rnum, rden) - (op1num, op1den) * (op2num, op2den)`` respectively. Aliasing between any combination of the variables is allowed, whilst no numerator is aliased with a denominator. .. function:: void fmpq_inv(fmpq_t dest, const fmpq_t src) Sets ``dest`` to ``1 / src``. .. function:: void _fmpq_pow_si(fmpz_t rnum, fmpz_t rden, const fmpz_t opnum, const fmpz_t opden, slong e) void fmpq_pow_si(fmpq_t res, const fmpq_t op, slong e) Sets ``res`` to ``op`` raised to the power `e`, where `e` is a ``slong``. If `e` is `0` and ``op`` is `0`, then ``res`` will be set to `1`. .. function:: int fmpq_pow_fmpz(fmpq_t a, const fmpq_t b, const fmpz_t e) Set ``res`` to ``op`` raised to the power `e`. Return `1` for success and `0` for failure. .. function:: void fmpq_mul_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x) Sets ``res`` to the product of the rational number ``op`` and the integer ``x``. .. function:: void fmpq_div_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x) Sets ``res`` to the quotient of the rational number ``op`` and the integer ``x``. .. function:: void fmpq_mul_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp) Sets ``res`` to ``x`` multiplied by ``2^exp``. .. function:: void fmpq_div_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp) Sets ``res`` to ``x`` divided by ``2^exp``. .. function:: void _fmpq_gcd(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s) Set ``(rnum, rden)`` to the gcd of ``(p, q)`` and ``(r, s)`` which we define to be the canonicalisation of `\operatorname{gcd}(ps, qr)/(qs)`. Does not assume that ``(rnum, rden)``, ``(p, q)`` or ``(r, s)`` are canonical. (This is apparently Euclid's original definition and is stable under scaling of numerator and denominator. It also agrees with the gcd on the integers. Note that it does not agree with gcd as defined in ``fmpq_poly``.) This definition agrees with the result as output by Sage and Pari/GP. .. function:: void fmpq_gcd(fmpq_t res, const fmpq_t op1, const fmpq_t op2) Set ``res`` to the gcd of ``op1`` and ``op2``. See the low level function ``_fmpq_gcd`` for our definition of gcd. .. function:: void _fmpq_gcd_cofactors(fmpz_t gnum, fmpz_t gden, fmpz_t abar, fmpz_t bbar, const fmpz_t anum, const fmpz_t aden, const fmpz_t bnum, const fmpz_t bden) void fmpq_gcd_cofactors(fmpq_t g, fmpz_t abar, fmpz_t bbar, const fmpq_t a, const fmpq_t b) Set `g` to `\operatorname{gcd}(a,b)` as per :func:`fmpq_gcd` and also compute `\overline{a} = a/g` and `\overline{b} = b/g`. Unlike :func:`_fmpq_gcd`, :func:`_fmpq_gcd_cofactors` requires canonical inputs. .. function:: void _fmpq_add_small(fmpz_t rnum, fmpz_t rden, slong p1, ulong q1, slong p2, ulong q2) Sets ``(rnum, rden)`` to the sum of ``(p1, q1)`` and ``(p2, q2)``. Assumes that ``(p1, q1)`` and ``(p2, q2)`` are in canonical form and that all inputs are between ``COEFF_MIN`` and ``COEFF_MAX``. .. function:: void _fmpq_mul_small(fmpz_t rnum, fmpz_t rden, slong p1, ulong q1, slong p2, ulong q2) Sets ``(rnum, rden)`` to the product of ``(p1, q1)`` and ``(p2, q2)``. Assumes that ``(p1, q1)`` and ``(p2, q2)`` are in canonical form and that all inputs are between ``COEFF_MIN`` and ``COEFF_MAX``. Modular reduction and rational reconstruction -------------------------------------------------------------------------------- .. function:: int _fmpq_mod_fmpz(fmpz_t res, const fmpz_t num, const fmpz_t den, const fmpz_t mod) int fmpq_mod_fmpz(fmpz_t res, const fmpq_t x, const fmpz_t mod) Sets the integer ``res`` to the residue `a` of `x = n/d` = ``(num, den)`` modulo the positive integer `m` = ``mod``, defined as the `0 \le a < m` satisfying `n \equiv a d \pmod m`. If such an `a` exists, 1 will be returned, otherwise 0 will be returned. .. function:: int _fmpq_reconstruct_fmpz_2_naive(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D) int _fmpq_reconstruct_fmpz_2(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D) int fmpq_reconstruct_fmpz_2(fmpq_t res, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D) Reconstructs a rational number from its residue `a` modulo `m`. Given a modulus `m > 2`, a residue `0 \le a < m`, and positive `N, D` satisfying `2ND < m`, this function attempts to find a fraction `n/d` with `0 \le |n| \le N` and `0 < d \le D` such that `\gcd(n,d) = 1` and `n \equiv ad \pmod m`. If a solution exists, then it is also unique. The function returns 1 if successful, and 0 to indicate that no solution exists. .. function:: int _fmpq_reconstruct_fmpz(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m) int fmpq_reconstruct_fmpz(fmpq_t res, const fmpz_t a, const fmpz_t m) Reconstructs a rational number from its residue `a` modulo `m`, returning 1 if successful and 0 if no solution exists. Uses the balanced bounds `N = D = \lfloor\sqrt{\frac{m-1}{2}}\rfloor`. Rational enumeration -------------------------------------------------------------------------------- .. function:: void _fmpq_next_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) void fmpq_next_minimal(fmpq_t res, const fmpq_t x) Given `x = \mathtt{num} / \mathtt{den}`, assumed to be nonnegative and in canonical form, sets ``res`` to the next rational number in the sequence obtained by enumerating all positive denominators `q`, for each `q` enumerating the numerators `1 \le p < q` in order and generating both `p/q` and `q/p`, but skipping all `\gcd(p,q) \ne 1`. Starting with zero, this generates every nonnegative rational number once and only once, with the first few entries being: `0, 1, 1/2, 2, 1/3, 3, 2/3, 3/2, 1/4, 4, 3/4, 4/3, 1/5, 5, 2/5, \ldots.` This enumeration produces the rational numbers in order of minimal height. It has the disadvantage of being somewhat slower to compute than the Calkin-Wilf enumeration. .. function:: void _fmpq_next_signed_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) void fmpq_next_signed_minimal(fmpq_t res, const fmpq_t x) Given a signed rational number `x = \mathtt{num} / \mathtt{den}`, assumed to be in canonical form, sets ``res`` to the next element in the minimal-height sequence generated by ``fmpq_next_minimal`` but with negative numbers interleaved: `0, 1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, \ldots.` Starting with zero, this generates every rational number once and only once, in order of minimal height. .. function:: void _fmpq_next_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) void fmpq_next_calkin_wilf(fmpq_t res, const fmpq_t x) Given `x = \mathtt{num} / \mathtt{den}`, which is assumed to be nonnegative and in canonical form, sets ``res`` to the next number in the breadth-first traversal of the Calkin-Wilf tree. Starting with zero, this generates every nonnegative rational number once and only once, with the first few entries being: `0, 1, 1/2, 2, 1/3, 3/2, 2/3, 3, 1/4, 4/3, 3/5, 5/2, 2/5, \ldots.` Despite the appearance of the initial entries, the Calkin-Wilf enumeration does not produce the rational numbers in order of height: some small fractions will appear late in the sequence. This order has the advantage of being faster to produce than the minimal-height order. .. function:: void _fmpq_next_signed_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) void fmpq_next_signed_calkin_wilf(fmpq_t res, const fmpq_t x) Given a signed rational number `x = \mathtt{num} / \mathtt{den}`, assumed to be in canonical form, sets ``res`` to the next element in the Calkin-Wilf sequence with negative numbers interleaved: `0, 1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, \ldots.` Starting with zero, this generates every rational number once and only once, but not in order of minimal height. .. function:: void fmpq_farey_neighbors(fmpq_t l, fmpq_t r, const fmpq_t x, const fmpz_t Q) Set `l` and `r` to the fractions directly below and above `x` in the Farey sequence of order `Q`. This function will throw if `Q` is less than the denominator of `x`. .. function:: void _fmpq_simplest_between(fmpz_t x_num, fmpz_t x_den, const fmpz_t l_num, const fmpz_t l_den, const fmpz_t r_num, const fmpz_t r_den) void fmpq_simplest_between(fmpq_t x, const fmpq_t l, const fmpq_t r) Set `x` to the simplest fraction in the closed interval `[l, r]`. The underscore version makes the additional assumption that `l \le r`. The endpoints `l` and `r` do not need to be canonical, but their denominators do need to be positive. `x` will always be returned in canonical form. A canonical fraction `a_1/b_1` is defined to be simpler than `a_2/b_2` iff `b_1 0`), ``rem`` will finite and the return is `0 < k \le n`. Essentially, if this function is called with canonical `x` and `n > 0`, then ``rem`` will be canonical. Therefore, applications relying on canonical ``fmpq_t``'s should not call this function with `n \le 0`. .. function:: void fmpq_set_cfrac(fmpq_t x, const fmpz * c, slong n) Sets `x` to the value of the continued fraction .. math:: x = c_0 + \cfrac{1}{c_1 + \cfrac{1}{c_2 + \cfrac{1}{ \ddots + \cfrac{1}{c_{n-1}}}}} where all `c_i` except `c_0` should be nonnegative. It is assumed that `n > 0`. For large `n`, this function implements a subquadratic algorithm. The convergents are given by a chain product of 2 by 2 matrices. This product is split in half recursively to balance the size of the coefficients. .. function:: slong fmpq_cfrac_bound(const fmpq_t x) Returns an upper bound for the number of terms in the continued fraction expansion of `x`. The computed bound is not necessarily sharp. We use the fact that the smallest denominator that can give a continued fraction of length `n` is the Fibonacci number `F_{n+1}`. Special functions -------------------------------------------------------------------------------- .. function:: void _fmpq_harmonic_ui(fmpz_t num, fmpz_t den, ulong n) void fmpq_harmonic_ui(fmpq_t x, ulong n) Computes the harmonic number `H_n = 1 + 1/2 + 1/3 + \dotsb + 1/n`. Table lookup is used for `H_n` whose numerator and denominator fit in single limb. For larger `n`, a divide and conquer strategy is used. Dedekind sums -------------------------------------------------------------------------------- Most of the definitions and relations used in the following section are given by Apostol [Apostol1997]_. The Dedekind sum `s(h,k)` is defined for all integers `h` and `k` as .. math:: s(h,k) = \sum_{i=1}^{k-1} \left(\left(\frac{i}{k}\right)\right) \left(\left(\frac{hi}{k}\right)\right) where .. math:: ((x))=\begin{cases} x-\lfloor x\rfloor-1/2 &\mbox{if } x\in\mathbf{Q}\setminus\mathbf{Z}\\ 0 &\mbox{if }x\in\mathbf{Z}. \end{cases} If `0 < h < k` and `(h,k) = 1`, this reduces to .. math:: s(h,k) = \sum_{i=1}^{k-1} \frac{i}{k} \left(\frac{hi}{k}-\left\lfloor\frac{hi}{k}\right\rfloor -\frac{1}{2}\right). The main formula for evaluating the series above is the following. Letting `r_0 = k`, `r_1 = h`, `r_2, r_3, \ldots, r_n, r_{n+1} = 1` be the remainder sequence in the Euclidean algorithm for computing GCD of `h` and `k`, .. math:: s(h,k) = \frac{1-(-1)^n}{8} - \frac{1}{12} \sum_{i=1}^{n+1} (-1)^i \left(\frac{1+r_i^2+r_{i-1}^2}{r_i r_{i-1}}\right). Writing `s(h,k) = p/q`, some useful properties employed are `|s| < k / 12`, `q \mid 6k` and `2|p| < k^2`. .. function:: void fmpq_dedekind_sum(fmpq_t s, const fmpz_t h, const fmpz_t k) void fmpq_dedekind_sum_naive(fmpq_t s, const fmpz_t h, const fmpz_t k) Computes `s(h,k)` for arbitrary `h` and `k`. The naive version uses a straightforward implementation of the defining sum using ``fmpz`` arithmetic and is slow for large `k`. flint-3.1.3/doc/source/fmpq_mat.rst000066400000000000000000000600461461254215100172440ustar00rootroot00000000000000.. _fmpq-mat: **fmpq_mat.h** -- matrices over the rational numbers =============================================================================== The :type:`fmpq_mat_t` data type represents matrices over `\mathbb{Q}`. A rational matrix is stored as an array of ``fmpq`` elements in order to allow convenient and efficient manipulation of individual entries. In general, ``fmpq_mat`` functions assume that input entries are in canonical form, and produce output with entries in canonical form. Since rational arithmetic is expensive, computations are typically performed by clearing denominators, performing the heavy work over the integers, and converting the final result back to a rational matrix. The ``fmpq_mat`` functions take care of such conversions transparently. For users who need fine-grained control, various functions for conversion between rational and integer matrices are provided. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpq_mat_struct .. type:: fmpq_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void fmpq_mat_init(fmpq_mat_t mat, slong rows, slong cols) Initialises a matrix with the given number of rows and columns for use. .. function:: void fmpq_mat_init_set(fmpq_mat_t mat1, const fmpq_mat_t mat2) Initialises ``mat1`` and sets it equal to ``mat2``. .. function:: void fmpq_mat_clear(fmpq_mat_t mat) Frees all memory associated with the matrix. The matrix must be reinitialised if it is to be used again. .. function:: void fmpq_mat_swap(fmpq_mat_t mat1, fmpq_mat_t mat2) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. function:: void fmpq_mat_swap_entrywise(fmpq_mat_t mat1, fmpq_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. Entry access -------------------------------------------------------------------------------- .. function:: fmpq * fmpq_mat_entry(const fmpq_mat_t mat, slong i, slong j) Gives a reference to the entry at row ``i`` and column ``j``. The reference can be passed as an input or output variable to any ``fmpq`` function for direct manipulation of the matrix element. No bounds checking is performed. .. function:: fmpz * fmpq_mat_entry_num(const fmpq_mat_t mat, slong i, slong j) Gives a reference to the numerator of the entry at row ``i`` and column ``j``. The reference can be passed as an input or output variable to any ``fmpz`` function for direct manipulation of the matrix element. No bounds checking is performed. .. function:: fmpz * fmpq_mat_entry_den(const fmpq_mat_t mat, slong i, slong j) Gives a reference to the denominator of the entry at row ``i`` and column ``j``. The reference can be passed as an input or output variable to any ``fmpz`` function for direct manipulation of the matrix element. No bounds checking is performed. .. function:: slong fmpq_mat_nrows(const fmpq_mat_t mat) Return the number of rows of the matrix ``mat``. .. function:: slong fmpq_mat_ncols(const fmpq_mat_t mat) Return the number of columns of the matrix ``mat``. Basic assignment -------------------------------------------------------------------------------- .. function:: void fmpq_mat_set(fmpq_mat_t dest, const fmpq_mat_t src) Sets the entries in ``dest`` to the same values as in ``src``, assuming the two matrices have the same dimensions. .. function:: void fmpq_mat_zero(fmpq_mat_t mat) Sets ``mat`` to the zero matrix. .. function:: void fmpq_mat_one(fmpq_mat_t mat) Let `m` be the minimum of the number of rows and columns in the matrix ``mat``. This function sets the first `m \times m` block to the identity matrix, and the remaining block to zero. .. function:: void fmpq_mat_transpose(fmpq_mat_t rop, const fmpq_mat_t op) Sets the matrix ``rop`` to the transpose of the matrix ``op``, assuming that their dimensions are compatible. .. function:: void fmpq_mat_swap_rows(fmpq_mat_t mat, slong * perm, slong r, slong s) Swaps rows ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fmpq_mat_swap_cols(fmpq_mat_t mat, slong * perm, slong r, slong s) Swaps columns ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: void fmpq_mat_invert_rows(fmpq_mat_t mat, slong * perm) Swaps rows ``i`` and ``r - i`` of ``mat`` for ``0 <= i < r/2``, where ``r`` is the number of rows of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fmpq_mat_invert_cols(fmpq_mat_t mat, slong * perm) Swaps columns ``i`` and ``c - i`` of ``mat`` for ``0 <= i < c/2``, where ``c`` is the number of columns of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. Addition, scalar multiplication -------------------------------------------------------------------------------- .. function:: void fmpq_mat_add(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2) Sets ``mat`` to the sum of ``mat1`` and ``mat2``, assuming that all three matrices have the same dimensions. .. function:: void fmpq_mat_sub(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2) Sets ``mat`` to the difference of ``mat1`` and ``mat2``, assuming that all three matrices have the same dimensions. .. function:: void fmpq_mat_neg(fmpq_mat_t rop, const fmpq_mat_t op) Sets ``rop`` to the negative of ``op``, assuming that the two matrices have the same dimensions. .. function:: void fmpq_mat_scalar_mul_fmpq(fmpq_mat_t rop, const fmpq_mat_t op, const fmpq_t x) Sets ``rop`` to ``op`` multiplied by the rational `x`, assuming that the two matrices have the same dimensions. Note that the rational ``x`` may not be aliased with any part of the entries of ``rop``. .. function:: void fmpq_mat_scalar_mul_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x) Sets ``rop`` to ``op`` multiplied by the integer `x`, assuming that the two matrices have the same dimensions. Note that the integer `x` may not be aliased with any part of the entries of ``rop``. .. function:: void fmpq_mat_scalar_div_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x) Sets ``rop`` to ``op`` divided by the integer `x`, assuming that the two matrices have the same dimensions and that `x` is non-zero. Note that the integer `x` may not be aliased with any part of the entries of ``rop``. Input and output -------------------------------------------------------------------------------- .. function:: void fmpq_mat_print(const fmpq_mat_t mat) Prints the matrix ``mat`` to standard output. Random matrix generation -------------------------------------------------------------------------------- .. function:: void fmpq_mat_randbits(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) This is equivalent to applying ``fmpq_randbits`` to all entries in the matrix. .. function:: void fmpq_mat_randtest(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) This is equivalent to applying ``fmpq_randtest`` to all entries in the matrix. Window -------------------------------------------------------------------------------- .. function:: void fmpq_mat_window_init(fmpq_mat_t window, const fmpq_mat_t mat, slong r1, slong c1, slong r2, slong c2) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0,0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void fmpq_mat_window_clear(fmpq_mat_t window) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. Concatenate -------------------------------------------------------------------------------- .. function:: void fmpq_mat_concat_vertical(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2) Sets ``res`` to vertical concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions: ``mat1``: `m \times n`, ``mat2``: `k \times n`, ``res``: `(m + k) \times n`. .. function:: void fmpq_mat_concat_horizontal(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions: ``mat1``: `m \times n`, ``mat2``: `m \times k`, ``res``: `m \times (n + k)`. Special matrices -------------------------------------------------------------------------------- .. function:: void fmpq_mat_hilbert_matrix(fmpq_mat_t mat) Sets ``mat`` to a Hilbert matrix of the given size. That is, the entry at row `i` and column `j` is set to `1/(i+j+1)`. Basic comparison and properties -------------------------------------------------------------------------------- .. function:: int fmpq_mat_equal(const fmpq_mat_t mat1, const fmpq_mat_t mat2) Returns nonzero if ``mat1`` and ``mat2`` have the same shape and all their entries agree, and returns zero otherwise. Assumes the entries in both ``mat1`` and ``mat2`` are in canonical form. .. function:: int fmpq_mat_is_integral(const fmpq_mat_t mat) Returns nonzero if all entries in ``mat`` are integer-valued, and returns zero otherwise. Assumes that the entries in ``mat`` are in canonical form. .. function:: int fmpq_mat_is_zero(const fmpq_mat_t mat) Returns nonzero if all entries in ``mat`` are zero, and returns zero otherwise. .. function:: int fmpq_mat_is_one(const fmpq_mat_t mat) Returns nonzero if ``mat`` ones along the diagonal and zeros elsewhere, and returns zero otherwise. .. function:: int fmpq_mat_is_empty(const fmpq_mat_t mat) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int fmpq_mat_is_square(const fmpq_mat_t mat) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. Integer matrix conversion -------------------------------------------------------------------------------- .. function:: int fmpq_mat_get_fmpz_mat(fmpz_mat_t dest, const fmpq_mat_t mat) Sets ``dest`` to ``mat`` and returns nonzero if all entries in ``mat`` are integer-valued. If not all entries in ``mat`` are integer-valued, sets ``dest`` to an undefined matrix and returns zero. Assumes that the entries in ``mat`` are in canonical form. .. function:: void fmpq_mat_get_fmpz_mat_entrywise(fmpz_mat_t num, fmpz_mat_t den, const fmpq_mat_t mat) Sets the integer matrices ``num`` and ``den`` respectively to the numerators and denominators of the entries in ``mat``. .. function:: void fmpq_mat_get_fmpz_mat_matwise(fmpz_mat_t num, fmpz_t den, const fmpq_mat_t mat) Converts all entries in ``mat`` to a common denominator, storing the rescaled numerators in ``num`` and the denominator in ``den``. The denominator will be minimal if the entries in ``mat`` are in canonical form. .. function:: void fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat) Clears denominators in ``mat`` row by row. The rescaled numerators are written to ``num``, and the denominator of row ``i`` is written to position ``i`` in ``den`` which can be a preinitialised ``fmpz`` vector. Alternatively, ``NULL`` can be passed as the ``den`` variable, in which case the denominators will not be stored. .. function:: void fmpq_mat_get_fmpz_mat_rowwise_2(fmpz_mat_t num, fmpz_mat_t num2, fmpz * den, const fmpq_mat_t mat, const fmpq_mat_t mat2) Clears denominators row by row of both ``mat`` and ``mat2``, writing the respective numerators to ``num`` and ``num2``. This is equivalent to concatenating ``mat`` and ``mat2`` horizontally, calling ``fmpq_mat_get_fmpz_mat_rowwise``, and extracting the two submatrices in the result. .. function:: void fmpq_mat_get_fmpz_mat_colwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat) Clears denominators in ``mat`` column by column. The rescaled numerators are written to ``num``, and the denominator of column ``i`` is written to position ``i`` in ``den`` which can be a preinitialised ``fmpz`` vector. Alternatively, ``NULL`` can be passed as the ``den`` variable, in which case the denominators will not be stored. .. function:: void fmpq_mat_set_fmpz_mat(fmpq_mat_t dest, const fmpz_mat_t src) Sets ``dest`` to ``src``. .. function:: void fmpq_mat_set_fmpz_mat_div_fmpz(fmpq_mat_t mat, const fmpz_mat_t num, const fmpz_t den) Sets ``mat`` to the integer matrix ``num`` divided by the common denominator ``den``. Modular reduction and rational reconstruction -------------------------------------------------------------------------------- .. function:: void fmpq_mat_get_fmpz_mat_mod_fmpz(fmpz_mat_t dest, const fmpq_mat_t mat, const fmpz_t mod) Sets each entry in ``dest`` to the corresponding entry in ``mat``, reduced modulo ``mod``. .. function:: int fmpq_mat_set_fmpz_mat_mod_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t mod) Sets ``X`` to the entrywise rational reconstruction integer matrix ``Xmod`` modulo ``mod``, and returns nonzero if the reconstruction is successful. If rational reconstruction fails for any element, returns zero and sets the entries in ``X`` to undefined values. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void fmpq_mat_mul_direct(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) Sets ``C`` to the matrix product ``AB``, computed naively using rational arithmetic. This is typically very slow and should only be used in circumstances where clearing denominators would consume too much memory. .. function:: void fmpq_mat_mul_cleared(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) Sets ``C`` to the matrix product ``AB``, computed by clearing denominators and multiplying over the integers. .. function:: void fmpq_mat_mul(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) Sets ``C`` to the matrix product ``AB``. This simply calls ``fmpq_mat_mul_cleared``. .. function:: void fmpq_mat_mul_fmpz_mat(fmpq_mat_t C, const fmpq_mat_t A, const fmpz_mat_t B) Sets ``C`` to the matrix product ``AB``, with ``B`` an integer matrix. This function works efficiently by clearing denominators of ``A``. .. function:: void fmpq_mat_mul_r_fmpz_mat(fmpq_mat_t C, const fmpz_mat_t A, const fmpq_mat_t B) Sets ``C`` to the matrix product ``AB``, with ``A`` an integer matrix. This function works efficiently by clearing denominators of ``B``. .. function:: void fmpq_mat_mul_fmpq_vec(fmpq * c, const fmpq_mat_t A, const fmpq * b, slong blen) void fmpq_mat_mul_fmpz_vec(fmpq * c, const fmpq_mat_t A, const fmpz * b, slong blen) void fmpq_mat_mul_fmpq_vec_ptr(fmpq * const * c, const fmpq_mat_t A, const fmpq * const * b, slong blen) void fmpq_mat_mul_fmpz_vec_ptr(fmpq * const * c, const fmpq_mat_t A, const fmpz * const * b, slong blen) Compute a matrix-vector product of ``A`` and ``(b, blen)`` and store the result in ``c``. The vector ``(b, blen)`` is either truncated or zero-extended to the number of columns of ``A``. The number entries written to ``c`` is always equal to the number of rows of ``A``. .. function:: void fmpq_mat_fmpq_vec_mul(fmpq * c, const fmpq * a, slong alen, const fmpq_mat_t B) void fmpq_mat_fmpz_vec_mul(fmpq * c, const fmpz * a, slong alen, const fmpq_mat_t B) void fmpq_mat_fmpq_vec_mul_ptr(fmpq * const * c, const fmpq * const * a, slong alen, const fmpq_mat_t B) void fmpq_mat_fmpz_vec_mul_ptr(fmpq * const * c, const fmpz * const * a, slong alen, const fmpq_mat_t B) Compute a vector-matrix product of ``(a, alen)`` and ``B`` and and store the result in ``c``. The vector ``(a, alen)`` is either truncated or zero-extended to the number of rows of ``B``. The number entries written to ``c`` is always equal to the number of columns of ``B``. Kronecker product -------------------------------------------------------------------------------- .. function:: void fmpq_mat_kronecker_product(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) Sets ``C`` to the Kronecker product of ``A`` and ``B``. Trace -------------------------------------------------------------------------------- .. function:: void fmpq_mat_trace(fmpq_t trace, const fmpq_mat_t mat) Computes the trace of the matrix, i.e. the sum of the entries on the main diagonal. The matrix is required to be square. Determinant -------------------------------------------------------------------------------- .. function:: void fmpq_mat_det(fmpq_t det, const fmpq_mat_t mat) Sets ``det`` to the determinant of ``mat``. In the general case, the determinant is computed by clearing denominators and computing a determinant over the integers. Matrices of size 0, 1 or 2 are handled directly. Nonsingular solving -------------------------------------------------------------------------------- .. function:: int fmpq_mat_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) int fmpq_mat_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) int fmpq_mat_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) int fmpq_mat_solve(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) Solves ``AX = B`` for nonsingular ``A``. Returns nonzero if ``A`` is nonsingular or if the right hand side is empty, and zero otherwise. All algorithms clear denominators to obtain a rescaled system over the integers. The *fraction_free* algorithm uses FFLU solving over the integers. The *dixon* and *multi_mod* algorithms use Dixon p-adic lifting or multimodular solving, followed by rational reconstruction with an adaptive stopping test. The *dixon* and *multi_mod* algorithms are generally the best choice for large systems. The default method chooses an algorithm automatically. .. function:: int fmpq_mat_solve_fmpz_mat_fraction_free(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) int fmpq_mat_solve_fmpz_mat_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) int fmpq_mat_solve_fmpz_mat_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) int fmpq_mat_solve_fmpz_mat(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) Solves ``AX = B`` for nonsingular ``A``, where *A* and *B* are integer matrices. Returns nonzero if ``A`` is nonsingular or if the right hand side is empty, and zero otherwise. .. function:: int fmpq_mat_can_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) Returns `1` if ``AX = B`` has a solution and if so, sets ``X`` to one such solution. The matrices can have any shape but must have the same number of rows. .. function:: int fmpq_mat_can_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) Returns `1` if ``AX = B`` has a solution and if so, sets ``X`` to one such solution. The matrices can have any shape but must have the same number of rows. int fmpq_mat_can_solve_fmpz_mat_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) Returns `1` if ``AX = B`` has a solution and if so, sets ``X`` to one such solution. The matrices can have any shape but must have the same number of rows. The input matrices must have integer entries and `A` cannot be an empty matrix. int fmpq_mat_can_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) Returns `1` if ``AX = B`` has a solution and if so, sets ``X`` to one such solution. The matrices can have any shape but must have the same number of rows. .. function:: int fmpq_mat_can_solve(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) Returns `1` if ``AX = B`` has a solution and if so, sets ``X`` to one such solution. The matrices can have any shape but must have the same number of rows. Inverse -------------------------------------------------------------------------------- .. function:: int fmpq_mat_inv(fmpq_mat_t B, const fmpq_mat_t A) Sets ``B`` to the inverse matrix of ``A`` and returns nonzero. Returns zero if ``A`` is singular. ``A`` must be a square matrix. Echelon form -------------------------------------------------------------------------------- .. function:: int fmpq_mat_pivot(slong * perm, fmpq_mat_t mat, slong r, slong c) Helper function for row reduction. Returns 1 if the entry of ``mat`` at row `r` and column `c` is nonzero. Otherwise searches for a nonzero entry in the same column among rows `r+1, r+2, \ldots`. If a nonzero entry is found at row `s`, swaps rows `r` and `s` and the corresponding entries in ``perm`` (unless ``NULL``) and returns -1. If no nonzero pivot entry is found, leaves the inputs unchanged and returns 0. .. function:: slong fmpq_mat_rref_classical(fmpq_mat_t B, const fmpq_mat_t A) Sets ``B`` to the reduced row echelon form of ``A`` and returns the rank. Performs Gauss-Jordan elimination directly over the rational numbers. This algorithm is usually inefficient and is mainly intended to be used for testing purposes. .. function:: slong fmpq_mat_rref_fraction_free(fmpq_mat_t B, const fmpq_mat_t A) Sets ``B`` to the reduced row echelon form of ``A`` and returns the rank. Clears denominators and performs fraction-free Gauss-Jordan elimination using ``fmpz_mat`` functions. .. function:: slong fmpq_mat_rref(fmpq_mat_t B, const fmpq_mat_t A) Sets ``B`` to the reduced row echelon form of ``A`` and returns the rank. This function automatically chooses between the classical and fraction-free algorithms depending on the size of the matrix. Gram-Schmidt Orthogonalisation -------------------------------------------------------------------------------- .. function:: void fmpq_mat_gso(fmpq_mat_t B, const fmpq_mat_t A) Takes a subset of `\mathbb{Q}^m` `S = \{a_1, a_2, \ldots ,a_n\}` (as the columns of a `m \times n` matrix ``A``) and generates an orthogonal set `S' = \{b_1, b_2, \ldots ,b_n\}` (as the columns of the `m \times n` matrix ``B``) that spans the same subspace of `\mathbb{Q}^m` as `S`. Transforms -------------------------------------------------------------------------------- .. function:: void fmpq_mat_similarity(fmpq_mat_t A, slong r, fmpq_t d) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void _fmpq_mat_charpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat) Set ``(coeffs, den)`` to the characteristic polynomial of the given `n\times n` matrix. .. function:: void fmpq_mat_charpoly(fmpq_poly_t pol, const fmpq_mat_t mat) Set ``pol`` to the characteristic polynomial of the given `n\times n` matrix. If ``mat`` is not square, an exception is raised. Minimal polynomial -------------------------------------------------------------------------------- .. function:: slong _fmpq_mat_minpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat) Set ``(coeffs, den)`` to the minimal polynomial of the given `n\times n` matrix and return the length of the polynomial. .. function:: void fmpq_mat_minpoly(fmpq_poly_t pol, const fmpq_mat_t mat) Set ``pol`` to the minimal polynomial of the given `n\times n` matrix. If ``mat`` is not square, an exception is raised. flint-3.1.3/doc/source/fmpq_mpoly.rst000066400000000000000000001021231461254215100176140ustar00rootroot00000000000000.. _fmpq-mpoly: **fmpq_mpoly.h** -- multivariate polynomials over the rational numbers =============================================================================== The exponents follow the ``mpoly`` interface. No references to the coefficients are available. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpq_mpoly_struct A structure holding a multivariate rational polynomial. It is implemented as a ``fmpq_t`` holding the content of the polynomial and a primitive integer polynomial. .. type:: fmpq_mpoly_t An array of length `1` of ``fmpq_mpoly_struct``. .. type:: fmpq_mpoly_ctx_struct Context structure representing the parent ring of an ``fmpq_mpoly``. .. type:: fmpq_mpoly_ctx_t An array of length `1` of ``fmpq_mpoly_ctx_struct``. Context object -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_ctx_init(fmpq_mpoly_ctx_t ctx, slong nvars, const ordering_t ord) Initialise a context object for a polynomial ring with the given number of variables and the given ordering. The possibilities for the ordering are ``ORD_LEX``, ``ORD_DEGLEX`` and ``ORD_DEGREVLEX``. .. function:: slong fmpq_mpoly_ctx_nvars(const fmpq_mpoly_ctx_t ctx) Return the number of variables used to initialize the context. .. function:: ordering_t fmpq_mpoly_ctx_ord(const fmpq_mpoly_ctx_t ctx) Return the ordering used to initialize the context. .. function:: void fmpq_mpoly_ctx_clear(fmpq_mpoly_ctx_t ctx) Release up any space allocated by *ctx*. Memory management -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_init(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Initialise *A* for use with the given and initialised context object. Its value is set to zero. .. function:: void fmpq_mpoly_init2(fmpq_mpoly_t A, slong alloc, const fmpq_mpoly_ctx_t ctx) Initialise *A* for use with the given and initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and at least ``MPOLY_MIN_BITS`` bits for the exponents. .. function:: void fmpq_mpoly_init3(fmpq_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpq_mpoly_ctx_t ctx) Initialise *A* for use with the given and initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and *bits* bits for the exponents. .. function:: void fmpq_mpoly_fit_length(fmpq_mpoly_t A, slong len, const fmpq_mpoly_ctx_t ctx) Ensure that *A* has space for at least *len* terms. .. function:: void fmpq_mpoly_fit_bits(fmpq_mpoly_t A, flint_bitcnt_t bits, const fmpq_mpoly_ctx_t ctx) Ensure that the exponent fields of *A* have at least *bits* bits. .. function:: void fmpq_mpoly_realloc(fmpq_mpoly_t A, slong alloc, const fmpq_mpoly_ctx_t ctx) Reallocate *A* to have space for *alloc* terms. Assumes the current length of the polynomial is not greater than *alloc*. .. function:: void fmpq_mpoly_clear(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Release any space allocated for *A*. Input/Output -------------------------------------------------------------------------------- The variable strings in ``x`` start with the variable of most significance at index `0`. If ``x`` is ``NULL``, the variables are named ``x1``, ``x2``, etc. .. function:: char * fmpq_mpoly_get_str_pretty(const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx) Return a string, which the user is responsible for cleaning up, representing *A*, given an array of variable strings ``x``. .. function:: int fmpq_mpoly_fprint_pretty(FILE * file, const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx) Print a string representing *A* to *file*. .. function:: int fmpq_mpoly_print_pretty(const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx) Print a string representing *A* to ``stdout``. .. function:: int fmpq_mpoly_set_str_pretty(fmpq_mpoly_t A, const char * str, const char ** x, const fmpq_mpoly_ctx_t ctx) Set *A* to the polynomial in the null-terminates string ``str`` given an array ``x`` of variable strings. If parsing ``str`` fails, *A* is set to zero, and `-1` is returned. Otherwise, `0` is returned. The operations ``+``, ``-``, ``*``, and ``/`` are permitted along with integers and the variables in ``x``. The character ``^`` must be immediately followed by the (integer) exponent. If any division is not exact, parsing fails. Basic manipulation -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_gen(fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) Set *A* to the variable of index *var*, where ``var = 0`` corresponds to the variable with the most significance with respect to the ordering. .. function:: int fmpq_mpoly_is_gen(const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) If `var \ge 0`, return `1` if *A* is equal to the `var`-th generator, otherwise return `0`. If `var < 0`, return `1` if the polynomial is equal to any generator, otherwise return `0`. .. function:: void fmpq_mpoly_set(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Set *A* to *B*. .. function:: int fmpq_mpoly_equal(const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Return `1` if *A* is equal to *B*, else return `0`. .. function:: void fmpq_mpoly_swap(fmpq_mpoly_t A, fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Efficiently swap *A* and *B*. Constants -------------------------------------------------------------------------------- .. function:: int fmpq_mpoly_is_fmpq(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if *A* is a constant, else return `0`. .. function:: void fmpq_mpoly_get_fmpq(fmpq_t c, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Assuming that *A* is a constant, set *c* to this constant. This function throws if *A* is not a constant. .. function:: void fmpq_mpoly_set_fmpq(fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_set_fmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_set_ui(fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_set_si(fmpq_mpoly_t A, slong c, const fmpq_mpoly_ctx_t ctx) Set *A* to the constant *c*. .. function:: void fmpq_mpoly_zero(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *A* to the constant `0`. .. function:: void fmpq_mpoly_one(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *A* to the constant `1`. .. function:: int fmpq_mpoly_equal_fmpq(const fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_equal_fmpz(const fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_equal_ui(const fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_equal_si(const fmpq_mpoly_t A, slong c, const fmpq_mpoly_ctx_t ctx) Return `1` if *A* is equal to the constant *c*, else return `0`. .. function:: int fmpq_mpoly_is_zero(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if *A* is equal to the constant `0`, else return `0`. .. function:: int fmpq_mpoly_is_one(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if *A* is equal to the constant `1`, else return `0`. Degrees -------------------------------------------------------------------------------- .. function:: int fmpq_mpoly_degrees_fit_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if the degrees of *A* with respect to each variable fit into an ``slong``, otherwise return `0`. .. function:: void fmpq_mpoly_degrees_fmpz(fmpz ** degs, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_degrees_si(slong * degs, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *degs* to the degrees of *A* with respect to each variable. If *A* is zero, all degrees are set to `-1`. .. function:: void fmpq_mpoly_degree_fmpz(fmpz_t deg, const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) slong fmpq_mpoly_degree_si(const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) Either return or set *deg* to the degree of *A* with respect to the variable of index *var*. If *A* is zero, the degree is defined to be `-1`. .. function:: int fmpq_mpoly_total_degree_fits_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if the total degree of *A* fits into an ``slong``, otherwise return `0`. .. function:: void fmpq_mpoly_total_degree_fmpz(fmpz_t tdeg, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) slong fmpq_mpoly_total_degree_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Either return or set *tdeg* to the total degree of *A*. If *A* is zero, the total degree is defined to be `-1`. .. function:: void fmpq_mpoly_used_vars(int * used, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) For each variable index *i*, set ``used[i]`` to nonzero if the variable of index *i* appears in *A* and to zero otherwise. Coefficients -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_get_denominator(fmpz_t d, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *d* to the denominator of *A*, the smallest positive integer `d` such that `d \times A` has integer coefficients. .. function:: void fmpq_mpoly_get_coeff_fmpq_monomial(fmpq_t c, const fmpq_mpoly_t A, const fmpq_mpoly_t M, const fmpq_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set *c* to the coefficient of the corresponding monomial in *A*. This function throws if *M* is not a monomial. .. function:: void fmpq_mpoly_set_coeff_fmpq_monomial(fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_t M, const fmpq_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set the coefficient of the corresponding monomial in *A* to *c*. This function throws if *M* is not a monomial. .. function:: void fmpq_mpoly_get_coeff_fmpq_fmpz(fmpq_t c, const fmpq_mpoly_t A, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_get_coeff_fmpq_ui(fmpq_t c, const fmpq_mpoly_t A, const ulong * exp, const fmpq_mpoly_ctx_t ctx) Set *c* to the coefficient of the monomial with exponent *exp*. .. function:: void fmpq_mpoly_set_coeff_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_set_coeff_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) Set the coefficient of the monomial with exponent *exp* to *c*. .. function:: void fmpq_mpoly_get_coeff_vars_ui(fmpq_mpoly_t C, const fmpq_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpq_mpoly_ctx_t ctx) Set *C* to the coefficient of *A* with respect to the variables in *vars* with powers in the corresponding array *exps*. Both *vars* and *exps* point to array of length *length*. It is assumed that `0 < length \le nvars(A)` and that the variables in *vars* are distinct. Comparison -------------------------------------------------------------------------------- .. function:: int fmpq_mpoly_cmp(const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Return `1` (resp. `-1`, or `0`) if *A* is after (resp. before, same as) *B* in some arbitrary but fixed total ordering of the polynomials. This ordering agrees with the usual ordering of monomials when *A* and *B* are both monomials. Container operations -------------------------------------------------------------------------------- These functions try to deal efficiently with violations of the internal canonical representation. If a term index is negative or not strictly less than the length of the polynomial, the function will throw. The mutating functions here are not guaranteed to leave the polynomial in reduced form (see :func:`fmpq_mpoly_is_canonical` for a definition of reduced). This means that even if nonzero terms with distinct exponents have been constructed in the correct order, a call to :func:`fmpq_mpoly_reduce` is necessary to ensure that the polynomial is in canonical form. As with the ``fmpz_mpoly`` module, a call to :func:`fmpq_mpoly_sort_terms` followed by a call to :func:`fmpq_mpoly_combine_like_terms` should leave the polynomial in canonical form. .. function:: fmpq * fmpq_mpoly_content_ref(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return a reference to the content of *A*. .. function:: fmpz_mpoly_struct * fmpq_mpoly_zpoly_ref(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return a reference to the integer polynomial of *A*. .. function:: fmpz * fmpq_mpoly_zpoly_term_coeff_ref(fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) Return a reference to the coefficient of index *i* of the integer polynomial of *A*. .. function:: int fmpq_mpoly_is_canonical(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if *A* is in canonical form. Otherwise, return `0`. An ``fmpq_mpoly_t`` is represented as the product of an ``fmpq_t content`` and an ``fmpz_mpoly_t zpoly``. The representation is considered canonical when either (1) both ``content`` and ``zpoly`` are zero, or (2) both ``content`` and ``zpoly`` are nonzero and canonical and ``zpoly`` is reduced. A nonzero ``zpoly`` is considered reduced when the coefficients have GCD one and the leading coefficient is positive. .. function:: slong fmpq_mpoly_length(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return the number of terms stored in *A*. If the polynomial is in canonical form, this will be the number of nonzero coefficients. .. function:: void fmpq_mpoly_resize(fmpq_mpoly_t A, slong new_length, const fmpq_mpoly_ctx_t ctx) Set the length of *A* to ``new_length``. Terms are either deleted from the end, or new zero terms are appended. .. function:: void fmpq_mpoly_get_term_coeff_fmpq(fmpq_t c, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) Set *c* to coefficient of index *i* .. function:: void fmpq_mpoly_set_term_coeff_fmpq(fmpq_mpoly_t A, slong i, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) Set the coefficient of index *i* to *c*. .. function:: int fmpq_mpoly_term_exp_fits_si(const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_term_exp_fits_ui(const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) Return `1` if all entries of the exponent vector of the term of index *i* fit into an ``slong`` (resp. a ``ulong``). Otherwise, return `0`. .. function:: void fmpq_mpoly_get_term_exp_fmpz(fmpz ** exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_get_term_exp_ui(ulong * exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_get_term_exp_si(slong * exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) Set *exp* to the exponent vector of the term of index *i*. The ``_ui`` (resp. ``_si``) version throws if any entry does not fit into a ``ulong`` (resp. ``slong``). .. function:: ulong fmpq_mpoly_get_term_var_exp_ui(const fmpq_mpoly_t A, slong i, slong var, const fmpq_mpoly_ctx_t ctx) slong fmpq_mpoly_get_term_var_exp_si(const fmpq_mpoly_t A, slong i, slong var, const fmpq_mpoly_ctx_t ctx) Return the exponent of the variable *var* of the term of index *i*. This function throws if the exponent does not fit into a ``ulong`` (resp. ``slong``). .. function:: void fmpq_mpoly_set_term_exp_fmpz(fmpq_mpoly_t A, slong i, fmpz * const * exps, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_set_term_exp_ui(fmpq_mpoly_t A, slong i, const ulong * exps, const fmpq_mpoly_ctx_t ctx) Set the exponent vector of the term of index *i* to *exp*. .. function:: void fmpq_mpoly_get_term(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) Set *M* to the term of index *i* in *A*. .. function:: void fmpq_mpoly_get_term_monomial(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void fmpq_mpoly_push_term_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpq_ffmpz(fmpq_mpoly_t A, const fmpq_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpz_ffmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, ulong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_ui_ffmpz(fmpq_mpoly_t A, ulong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, slong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_si_ffmpz(fmpq_mpoly_t A, slong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpz_ui(fmpq_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_ui_ui(fmpq_mpoly_t A, ulong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_si_ui(fmpq_mpoly_t A, slong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) Append a term to *A* with coefficient *c* and exponent vector *exp*. This function should run in constant average time if the terms pushed have bounded denominator. .. function:: void fmpq_mpoly_reduce(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Factor out necessary content from ``A->zpoly`` so that it is reduced. If the terms of *A* were nonzero and sorted with distinct exponents to begin with, the result will be in canonical form. .. function:: void fmpq_mpoly_sort_terms(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Sort the internal ``A->zpoly`` into the canonical ordering dictated by the ordering in *ctx*. This function does not combine like terms, nor does it delete terms with coefficient zero, nor does it reduce. .. function:: void fmpq_mpoly_combine_like_terms(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Combine adjacent like terms in the internal ``A->zpoly`` and then factor out content via a call to :func:`fmpq_mpoly_reduce`. If the terms of *A* were sorted to begin with, the result will be in canonical form. .. function:: void fmpq_mpoly_reverse(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Set *A* to the reversal of *B*. Random generation -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_randtest_bound(fmpq_mpoly_t A, flint_rand_t state, slong length, mp_limb_t coeff_bits, ulong exp_bound, const fmpq_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bound - 1]``. The exponents of each variable are generated by calls to ``n_randint(state, exp_bound)``. .. function:: void fmpq_mpoly_randtest_bounds(fmpq_mpoly_t A, flint_rand_t state, slong length, mp_limb_t coeff_bits, ulong * exp_bounds, const fmpq_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bounds[i] - 1]``. The exponents of the variable of index *i* are generated by calls to ``n_randint(state, exp_bounds[i])``. .. function:: void fmpq_mpoly_randtest_bits(fmpq_mpoly_t A, flint_rand_t state, slong length, mp_limb_t coeff_bits, mp_limb_t exp_bits, const fmpq_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents whose packed form does not exceed the given bit count. The parameter ``coeff_bits`` to the three functions ``fmpq_mpoly_randtest_{bound|bounds|bits}`` is merely a suggestion for the approximate bit count of the resulting coefficients. Addition/Subtraction -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_add_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_add_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_add_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_add_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) Set *A* to `B + c`. .. function:: void fmpq_mpoly_sub_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_sub_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_sub_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_sub_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) Set *A* to `B - c`. .. function:: void fmpq_mpoly_add(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx) Set *A* to `B + C`. .. function:: void fmpq_mpoly_sub(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx) Set *A* to `B - C`. Scalar operations -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_neg(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Set *A* to `-B`. .. function:: void fmpq_mpoly_scalar_mul_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_scalar_mul_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_scalar_mul_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_scalar_mul_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) Set *A* to `B \times c`. .. function:: void fmpq_mpoly_scalar_div_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_scalar_div_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_scalar_div_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_scalar_div_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) Set *A* to `B/c`. .. function:: void fmpq_mpoly_make_monic(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Set *A* to *B* divided by the leading coefficient of *B*. This throws if *B* is zero. All of these functions run quickly if *A* and *B* are aliased. Differentiation/Integration -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_derivative(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx) Set *A* to the derivative of *B* with respect to the variable of index *var*. .. function:: void fmpq_mpoly_integral(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx) Set *A* to the integral with the fewest number of terms of *B* with respect to the variable of index *var*. Evaluation -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: int fmpq_mpoly_evaluate_all_fmpq(fmpq_t ev, const fmpq_mpoly_t A, fmpq * const * vals, const fmpq_mpoly_ctx_t ctx) Set ``ev`` to the evaluation of *A* where the variables are replaced by the corresponding elements of the array ``vals``. Return `1` for success and `0` for failure. .. function:: int fmpq_mpoly_evaluate_one_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_t val, const fmpq_mpoly_ctx_t ctx) Set *A* to the evaluation of *B* where the variable of index *var* is replaced by ``val``. Return `1` for success and `0` for failure. .. function:: int fmpq_mpoly_compose_fmpq_poly(fmpq_poly_t A, const fmpq_mpoly_t B, fmpq_poly_struct * const * C, const fmpq_mpoly_ctx_t ctxB) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. The context object of *B* is *ctxB*. Return `1` for success and `0` for failure. .. function:: int fmpq_mpoly_compose_fmpq_mpoly(fmpq_mpoly_t A, const fmpq_mpoly_t B, fmpq_mpoly_struct * const * C, const fmpq_mpoly_ctx_t ctxB, const fmpq_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. Both *A* and the elements of *C* have context object *ctxAC*, while *B* has context object *ctxB*. Neither *A* nor *B* is allowed to alias any other polynomial. Return `1` for success and `0` for failure. .. function:: void fmpq_mpoly_compose_fmpq_mpoly_gen(fmpq_mpoly_t A, const fmpq_mpoly_t B, const slong * c, const fmpq_mpoly_ctx_t ctxB, const fmpq_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variable of index *i* in *ctxB* is replaced by the variable of index ``c[i]`` in *ctxAC*. The length of the array *C* is the number of variables in *ctxB*. If any ``c[i]`` is negative, the corresponding variable of *B* is replaced by zero. Otherwise, it is expected that ``c[i]`` is less than the number of variables in *ctxAC*. Multiplication -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_mul(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx) Set *A* to `B \times C`. Powering -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: int fmpq_mpoly_pow_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t k, const fmpq_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power. Return `1` for success and `0` for failure. .. function:: int fmpq_mpoly_pow_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong k, const fmpq_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power. Return `1` for success and `0` for failure. Division -------------------------------------------------------------------------------- .. function:: int fmpq_mpoly_divides(fmpq_mpoly_t Q, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) If *A* is divisible by *B*, set *Q* to the exact quotient and return `1`. Otherwise, set *Q* to zero and return `0`. Note that the function :func:`fmpq_mpoly_div` may be faster if the quotient is known to be exact. .. function:: void fmpq_mpoly_div(fmpq_mpoly_t Q, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Set *Q* to the quotient of *A* by *B*, discarding the remainder. .. function:: void fmpq_mpoly_divrem(fmpq_mpoly_t Q, fmpq_mpoly_t R, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Set *Q* and *R* to the quotient and remainder of *A* divided by *B*. .. function:: void fmpq_mpoly_divrem_ideal(fmpq_mpoly_struct ** Q, fmpq_mpoly_t R, const fmpq_mpoly_t A, fmpq_mpoly_struct * const * B, slong len, const fmpq_mpoly_ctx_t ctx) This function is as per :func:`fmpq_mpoly_divrem` except that it takes an array of divisor polynomials *B* and it returns an array of quotient polynomials *Q*. The number of divisor (and hence quotient) polynomials is given by *len*. Greatest Common Divisor -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_content(fmpq_t g, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *g* to the (nonnegative) gcd of the coefficients of *A*. .. function:: void fmpq_mpoly_term_content(fmpq_mpoly_t M, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *M* to the GCD of the terms of *A*. If *A* is zero, *M* will be zero. Otherwise, *M* will be a monomial with coefficient one. .. function:: int fmpq_mpoly_content_vars(fmpq_mpoly_t g, const fmpq_mpoly_t A, slong * vars, slong vars_length, const fmpq_mpoly_ctx_t ctx) Set *g* to the GCD of the coefficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon success, *g* will be independent of the variables *vars*. .. function:: int fmpq_mpoly_gcd(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Try to set *G* to the monic GCD of *A* and *B*. The GCD of zero and zero is defined to be zero. If the return is `1` the function was successful. Otherwise the return is `0` and *G* is left untouched. .. function:: int fmpq_mpoly_gcd_cofactors(fmpq_mpoly_t G, fmpq_mpoly_t Abar, fmpq_mpoly_t Bbar, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Do the operation of :func:`fmpq_mpoly_gcd` and also compute `Abar = A/G` and `Bbar = B/G` if successful. .. function:: int fmpq_mpoly_gcd_brown(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_gcd_hensel(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_gcd_subresultant(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_gcd_zippel(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_gcd_zippel2(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) Try to set *G* to the GCD of *A* and *B* using various algorithms. .. function:: int fmpq_mpoly_resultant(fmpq_mpoly_t R, const fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx) Try to set *R* to the resultant of *A* and *B* with respect to the variable of index *var*. .. function:: int fmpq_mpoly_discriminant(fmpq_mpoly_t D, const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) Try to set *D* to the discriminant of *A* with respect to the variable of index *var*. Square Root -------------------------------------------------------------------------------- .. function:: int fmpq_mpoly_sqrt(fmpq_mpoly_t Q, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) If *A* is a perfect square return `1` and set *Q* to the square root with positive leading coefficient. Otherwise return `0` and set *Q* to zero. .. function:: int fmpq_mpoly_is_square(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if *A* is a perfect square, otherwise return `0`. Univariate Functions -------------------------------------------------------------------------------- An ``fmpq_mpoly_univar_t`` holds a univariate polynomial in some main variable with ``fmpq_mpoly_t`` coefficients in the remaining variables. These functions are useful when one wants to rewrite an element of `\mathbb{Q}[x_1, \dots, x_m]` as an element of `(\mathbb{Q}[x_1, \dots, x_{v-1}, x_{v+1}, \dots, x_m])[x_v]` and vice versa. .. function:: void fmpq_mpoly_univar_init(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) Initialize *A*. .. function:: void fmpq_mpoly_univar_clear(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) Clear *A*. .. function:: void fmpq_mpoly_univar_swap(fmpq_mpoly_univar_t A, fmpq_mpoly_univar_t B, const fmpq_mpoly_ctx_t ctx) Swap *A* and *B*. .. function:: void fmpq_mpoly_to_univar(fmpq_mpoly_univar_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx) Set *A* to a univariate form of *B* by pulling out the variable of index *var*. The coefficients of *A* will still belong to the content *ctx* but will not depend on the variable of index *var*. .. function:: void fmpq_mpoly_from_univar(fmpq_mpoly_t A, const fmpq_mpoly_univar_t B, slong var, const fmpq_mpoly_ctx_t ctx) Set *A* to the normal form of *B* by putting in the variable of index *var*. This function is undefined if the coefficients of *B* depend on the variable of index *var*. .. function:: int fmpq_mpoly_univar_degree_fits_si(const fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) Return `1` if the degree of *A* with respect to the main variable fits an ``slong``. Otherwise, return `0`. .. function:: slong fmpq_mpoly_univar_length(const fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) Return the number of terms in *A* with respect to the main variable. .. function:: slong fmpq_mpoly_univar_get_term_exp_si(fmpq_mpoly_univar_t A, slong i, const fmpq_mpoly_ctx_t ctx) Return the exponent of the term of index *i* of *A*. .. function:: void fmpq_mpoly_univar_get_term_coeff(fmpq_mpoly_t c, const fmpq_mpoly_univar_t A, slong i, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_univar_swap_term_coeff(fmpq_mpoly_t c, fmpq_mpoly_univar_t A, slong i, const fmpq_mpoly_ctx_t ctx) Set (resp. swap) *c* to (resp. with) the coefficient of the term of index *i* of *A*. flint-3.1.3/doc/source/fmpq_mpoly_factor.rst000066400000000000000000000067361461254215100211670ustar00rootroot00000000000000.. _fmpq-mpoly-factor: **fmpq_mpoly_factor.h** -- factorisation of multivariate polynomials over the rational numbers ============================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpq_mpoly_factor_struct A struct for holding a factored rational polynomial. There is a single constant and a product of bases to corresponding exponents. .. type:: fmpq_mpoly_factor_t An array of length `1` of ``fmpq_mpoly_factor_struct``. Memory management -------------------------------------------------------------------------------- .. function:: void fmpq_mpoly_factor_init(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) Initialise *f*. .. function:: void fmpq_mpoly_factor_clear(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) Clear *f*. Basic manipulation -------------------------------------------------------------------------------- .. function:: slong fmpq_mpoly_factor_length(const fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) Return the length of the product in *f*. .. function:: void fmpq_mpoly_factor_get_constant_fmpq(fmpq_t c, const fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) Set *c* to the constant of *f*. .. function:: void fmpq_mpoly_factor_get_base(fmpq_mpoly_t B, const fmpq_mpoly_factor_t f, slong i, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_factor_swap_base(fmpq_mpoly_t B, fmpq_mpoly_factor_t f, slong i, const fmpq_mpoly_ctx_t ctx) Set (resp. swap) *B* to (resp. with) the base of the term of index *i* in *A*. .. function:: slong fmpq_mpoly_factor_get_exp_si(fmpq_mpoly_factor_t f, slong i, const fmpq_mpoly_ctx_t ctx) Return the exponent of the term of index *i* in *A*. It is assumed to fit an ``slong``. .. function:: void fmpq_mpoly_factor_sort(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) Sort the product of *f* first by exponent and then by base. .. function:: int fmpq_mpoly_factor_make_monic(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_factor_make_integral(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) Make the bases in *f* monic (resp. integral and primitive with positive leading coefficient). Return `1` for success, `0` for failure. Factorisation -------------------------------------------------------------------------------- A return of `1` indicates that the function was successful. Otherwise, the return is `0` and *f* is undefined. None of these functions multiply *f* by *A*: *f* is simply set to a factorisation of *A*, and thus these functions should not depend on the initial value of the output *f*. The normalization of the factors is not yet specified: use :func:`fmpq_mpoly_factor_make_monic` or :func:`fmpq_mpoly_factor_make_integral` for common normalizations. .. function:: int fmpq_mpoly_factor_squarefree(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are primitive and pairwise relatively prime. If the product of all irreducible factors with a given exponent is desired, it is recommended to call :func:`fmpq_mpoly_factor_sort` and then multiply the bases with the desired exponent. .. function:: int fmpq_mpoly_factor(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are irreducible. flint-3.1.3/doc/source/fmpq_poly.rst000066400000000000000000002253211461254215100174450ustar00rootroot00000000000000.. _fmpq-poly: **fmpq_poly.h** -- univariate polynomials over the rational numbers =============================================================================== The :type:`fmpq_poly_t` data type represents elements of `\mathbb{Q}[x]`. The ``fmpq_poly`` module provides routines for memory management, basic arithmetic, and conversions from or to other types. A rational polynomial is stored as the quotient of an integer polynomial and an integer denominator. To be more precise, the coefficient vector of the numerator can be accessed with the function ``fmpq_poly_numref()`` and the denominator with ``fmpq_poly_denref()``. Although one can construct use cases in which a representation as a list of rational coefficients would be beneficial, the choice made here is typically more efficient. We can obtain a unique representation based on this choice by enforcing, for non-zero polynomials, that the numerator and denominator are coprime and that the denominator is positive. The unique representation of the zero polynomial is chosen as $0/1$. Similar to the situation in the :type:`fmpz_poly_t` case, an :type:`fmpq_poly_t` object also has a ``length`` parameter, which denotes the length of the vector of coefficients of the numerator. We say a polynomial is *normalised* either if this length is zero or if the leading coefficient is non-zero. We say a polynomial is in *canonical* form if it is given in the unique representation discussed above and normalised. The functions provided in this module roughly fall into two categories: On the one hand, there are functions mainly provided for the user, whose names do not begin with an underscore. These typically operate on polynomials of type :type:`fmpq_poly_t` in canonical form and, unless specified otherwise, permit aliasing between their input arguments and between their output arguments. On the other hand, there are versions of these functions whose names are prefixed with a single underscore. These typically operate on polynomials given in the form of a triple of object of types ``fmpz *``, :type:`fmpz_t`, and :type:`slong`, containing the numerator, denominator and length, respectively. In general, these functions expect their input to be normalised, i.e. they do not allow zero padding, and to be in lowest terms, and they do not allow their input and output arguments to be aliased. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpq_poly_struct .. type:: fmpq_poly_t Memory management -------------------------------------------------------------------------------- .. function:: void fmpq_poly_init(fmpq_poly_t poly) Initialises the polynomial for use. The length is set to zero. .. function:: void fmpq_poly_init2(fmpq_poly_t poly, slong alloc) Initialises the polynomial with space for at least ``alloc`` coefficients and sets the length to zero. The ``alloc`` coefficients are all set to zero. .. function:: void fmpq_poly_realloc(fmpq_poly_t poly, slong alloc) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero then the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` then ``poly`` is first truncated to length ``alloc``. Note that this might leave the rational polynomial in non-canonical form. .. function:: void fmpq_poly_fit_length(fmpq_poly_t poly, slong len) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where :func:`fit_length` is called many times in small increments by at least doubling the number of allocated coefficients when ``len`` is larger than the number of coefficients currently allocated. .. function:: void _fmpq_poly_set_length(fmpq_poly_t poly, slong len) Sets the length of the numerator polynomial to ``len``, demoting coefficients beyond the new length. Note that this method does not guarantee that the rational polynomial is in canonical form. .. function:: void fmpq_poly_clear(fmpq_poly_t poly) Clears the given polynomial, releasing any memory used. The polynomial must be reinitialised in order to be used again. .. function:: void _fmpq_poly_normalise(fmpq_poly_t poly) Sets the length of ``poly`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. Note that this function does not guarantee the coprimality of the numerator polynomial and the integer denominator. .. function:: void _fmpq_poly_canonicalise(fmpz * poly, fmpz_t den, slong len) Puts ``(poly, den)`` of length ``len`` into canonical form. It is assumed that the array ``poly`` contains a non-zero entry in position ``len - 1`` whenever ``len > 0``. Assumes that ``den`` is non-zero. .. function:: void fmpq_poly_canonicalise(fmpq_poly_t poly) Puts the polynomial ``poly`` into canonical form. Firstly, the length is set to the actual length of the numerator polynomial. For non-zero polynomials, it is then ensured that the numerator and denominator are coprime and that the denominator is positive. The canonical form of the zero polynomial is a zero numerator polynomial and a one denominator. .. function:: int _fmpq_poly_is_canonical(const fmpz * poly, const fmpz_t den, slong len) Returns whether the polynomial is in canonical form. .. function:: int fmpq_poly_is_canonical(const fmpq_poly_t poly) Returns whether the polynomial is in canonical form. Polynomial parameters -------------------------------------------------------------------------------- .. function:: slong fmpq_poly_degree(const fmpq_poly_t poly) Returns the degree of ``poly``, which is one less than its length, as a ``slong``. .. function:: slong fmpq_poly_length(const fmpq_poly_t poly) Returns the length of ``poly``. Accessing the numerator and denominator -------------------------------------------------------------------------------- .. function:: fmpz * fmpq_poly_numref(fmpq_poly_t poly) Returns a reference to the numerator polynomial as an array. Note that, because of a delayed initialisation approach, this might be ``NULL`` for zero polynomials. This situation can be salvaged by calling either :func:`fmpq_poly_fit_length` or :func:`fmpq_poly_realloc`. This function is implemented as a macro returning ``(poly)->coeffs``. .. function:: fmpz_t fmpq_poly_denref(fmpq_poly_t poly) Returns a reference to the denominator as a ``fmpz_t``. The integer is guaranteed to be properly initialised. This function is implemented as a macro returning ``(poly)->den``. .. function:: void fmpq_poly_get_numerator(fmpz_poly_t res, const fmpq_poly_t poly) Sets ``res`` to the numerator of ``poly``, e.g. the primitive part as an ``fmpz_poly_t`` if it is in canonical form. .. function:: void fmpq_poly_get_denominator(fmpz_t den, const fmpq_poly_t poly) Sets ``res`` to the denominator of ``poly``. Random testing -------------------------------------------------------------------------------- The functions :func:`fmpq_poly_randtest_foo` provide random polynomials suitable for testing. On an integer level, this means that long strings of zeros and ones in the binary representation are favoured as well as the special absolute values `0`, `1`, ``COEFF_MAX``, and ``WORD_MAX``. On a polynomial level, the integer numerator has a reasonable chance to have a non-trivial content. .. function:: void fmpq_poly_randtest(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets `f` to a random polynomial with coefficients up to the given length and where each coefficient has up to the given number of bits. The coefficients are signed randomly. One must call :func:`flint_randinit` before calling this function. .. function:: void fmpq_poly_randtest_unsigned(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets `f` to a random polynomial with coefficients up to the given length and where each coefficient has up to the given number of bits. One must call :func:`flint_randinit` before calling this function. .. function:: void fmpq_poly_randtest_not_zero(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) As for :func:`fmpq_poly_randtest` except that ``len`` and ``bits`` may not be zero and the polynomial generated is guaranteed not to be the zero polynomial. One must call :func:`flint_randinit` before calling this function. Assignment, swap, negation -------------------------------------------------------------------------------- .. function:: void fmpq_poly_set(fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``poly1`` to equal ``poly2``. .. function:: void fmpq_poly_set_si(fmpq_poly_t poly, slong x) Sets ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_ui(fmpq_poly_t poly, ulong x) Sets ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_fmpz(fmpq_poly_t poly, const fmpz_t x) Sets ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_fmpq(fmpq_poly_t poly, const fmpq_t x) Sets ``poly`` to the rational `x`, which is assumed to be given in lowest terms. .. function:: void fmpq_poly_set_fmpz_poly(fmpq_poly_t rop, const fmpz_poly_t op) Sets the rational polynomial ``rop`` to the same value as the integer polynomial ``op``. .. function:: void fmpq_poly_set_nmod_poly(fmpq_poly_t rop, const nmod_poly_t op) Sets the coefficients of ``rop`` to the residues in ``op``, normalised to the interval `-m/2 \le r < m/2` where `m` is the modulus. .. function:: void fmpq_poly_get_nmod_poly(nmod_poly_t rop, const fmpq_poly_t op) Sets the coefficients of ``rop`` to the coefficients in the denominator of ``op``, reduced by the modulus of ``rop``. The result is multiplied by the inverse of the denominator of ``op``. It is assumed that the reduction of the denominator of ``op`` is invertible. .. function:: void fmpq_poly_get_nmod_poly_den(nmod_poly_t rop, const fmpq_poly_t op, int den) Sets the coefficients of ``rop`` to the coefficients in the denominator of ``op``, reduced by the modulus of ``rop``. If ``den == 1``, the result is multiplied by the inverse of the denominator of ``op``. In this case it is assumed that the reduction of the denominator of ``op`` is invertible. .. function:: int _fmpq_poly_set_str(fmpz * poly, fmpz_t den, const char * str, slong len) Sets ``(poly, den)`` to the polynomial specified by the null-terminated string ``str`` of ``len`` coefficients. The input format is a sequence of coefficients separated by one space. The result is only guaranteed to be in lowest terms if all coefficients in the input string are in lowest terms. Returns `0` if no error occurred. Otherwise, returns -1 in which case the resulting value of ``(poly, den)`` is undefined. If ``str`` is not null-terminated, calling this method might result in a segmentation fault. .. function:: int fmpq_poly_set_str(fmpq_poly_t poly, const char * str) Sets ``poly`` to the polynomial specified by the null-terminated string ``str``. The input format is the same as the output format of ``fmpq_poly_get_str``: the length given as a decimal integer, then two spaces, then the list of coefficients separated by one space. The result is only guaranteed to be in canonical form if all coefficients in the input string are in lowest terms. Returns `0` if no error occurred. Otherwise, returns -1 in which case the resulting value of ``poly`` is set to zero. If ``str`` is not null-terminated, calling this method might result in a segmentation fault. .. function:: char * fmpq_poly_get_str(const fmpq_poly_t poly) Returns the string representation of ``poly``. .. function:: char * fmpq_poly_get_str_pretty(const fmpq_poly_t poly, const char * var) Returns the pretty representation of ``poly``, using the null-terminated string ``var`` not equal to ``"\0"`` as the variable name. .. function:: void fmpq_poly_zero(fmpq_poly_t poly) Sets ``poly`` to zero. .. function:: void fmpq_poly_one(fmpq_poly_t poly) Sets ``poly`` to the constant polynomial `1`. .. function:: void fmpq_poly_neg(fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``poly1`` to the additive inverse of ``poly2``. .. function:: void fmpq_poly_inv(fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``poly1`` to the multiplicative inverse of ``poly2`` if possible. Otherwise, if ``poly2`` is not a unit, leaves ``poly1`` unmodified and calls :func:`abort`. .. function:: void fmpq_poly_swap(fmpq_poly_t poly1, fmpq_poly_t poly2) Efficiently swaps the polynomials ``poly1`` and ``poly2``. .. function:: void fmpq_poly_truncate(fmpq_poly_t poly, slong n) If the current length of ``poly`` is greater than `n`, it is truncated to the given length. Discarded coefficients are demoted, but they are not necessarily set to zero. .. function:: void fmpq_poly_set_trunc(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Sets ``res`` to a copy of ``poly``, truncated to length ``n``. .. function:: void fmpq_poly_get_slice(fmpq_poly_t rop, const fmpq_poly_t op, slong i, slong j) Returns the slice with coefficients from `x^i` (including) to `x^j` (excluding). .. function:: void fmpq_poly_reverse(fmpq_poly_t res, const fmpq_poly_t poly, slong n) This function considers the polynomial ``poly`` to be of length `n`, notionally truncating and zero padding if required, and reverses the result. Since the function normalises its result ``res`` may be of length less than `n`. Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void fmpq_poly_get_coeff_fmpz(fmpz_t x, const fmpq_poly_t poly, slong n) Retrieves the `n`\th coefficient of the numerator of ``poly``. .. function:: void fmpq_poly_get_coeff_fmpq(fmpq_t x, const fmpq_poly_t poly, slong n) Retrieves the `n`\th coefficient of ``poly``, in lowest terms. .. function:: void fmpq_poly_set_coeff_si(fmpq_poly_t poly, slong n, slong x) Sets the `n`\th coefficient in ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_coeff_ui(fmpq_poly_t poly, slong n, ulong x) Sets the `n`\th coefficient in ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_coeff_fmpz(fmpq_poly_t poly, slong n, const fmpz_t x) Sets the `n`\th coefficient in ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_coeff_fmpq(fmpq_poly_t poly, slong n, const fmpq_t x) Sets the `n`\th coefficient in ``poly`` to the rational `x`. Comparison -------------------------------------------------------------------------------- .. function:: int fmpq_poly_equal(const fmpq_poly_t poly1, const fmpq_poly_t poly2) Returns `1` if ``poly1`` is equal to ``poly2``, otherwise returns `0`. .. function:: int _fmpq_poly_equal_trunc(const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) Returns `1` if ``poly1`` and ``poly2`` notionally truncated to length `n` are equal, otherwise returns `0`. .. function:: int fmpq_poly_equal_trunc(const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) Returns `1` if ``poly1`` and ``poly2`` notionally truncated to length `n` are equal, otherwise returns `0`. .. function:: int _fmpq_poly_cmp(const fmpz * lpoly, const fmpz_t lden, const fmpz * rpoly, const fmpz_t rden, slong len) Compares two non-zero polynomials, assuming they have the same length ``len > 0``. The polynomials are expected to be provided in canonical form. .. function:: int fmpq_poly_cmp(const fmpq_poly_t left, const fmpq_poly_t right) Compares the two polynomials ``left`` and ``right``. Compares the two polynomials ``left`` and ``right``, returning `-1`, `0`, or `1` as ``left`` is less than, equal to, or greater than ``right``. The comparison is first done by the degree, and then, in case of a tie, by the individual coefficients from highest to lowest. .. function:: int fmpq_poly_is_one(const fmpq_poly_t poly) Returns `1` if ``poly`` is the constant polynomial `1`, otherwise returns `0`. .. function:: int fmpq_poly_is_zero(const fmpq_poly_t poly) Returns `1` if ``poly`` is the zero polynomial, otherwise returns `0`. .. function:: int fmpq_poly_is_gen(const fmpq_poly_t poly) Returns `1` if ``poly`` is the degree `1` polynomial `x`, otherwise returns `0`. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_add(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) Forms the sum ``(rpoly, rden)`` of ``(poly1, den1, len1)`` and ``(poly2, den2, len2)``, placing the result into canonical form. Assumes that ``rpoly`` is an array of length the maximum of ``len1`` and ``len2``. The input operands are assumed to be in canonical form and are also allowed to be of length `0`. ``(rpoly, rden)`` and ``(poly1, den1)`` may be aliased, but ``(rpoly, rden)`` and ``(poly2, den2)`` may *not* be aliased. .. function:: void _fmpq_poly_add_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, int can) As per ``_fmpq_poly_add`` except that one can specify whether to canonicalise the output or not. This function is intended to be used with weak canonicalisation to prevent explosion in memory usage. It exists for performance reasons. .. function:: void fmpq_poly_add(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``res`` to the sum of ``poly1`` and ``poly2``, using Henrici's algorithm. .. function:: void fmpq_poly_add_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can) As per ``mpq_poly_add`` except that one can specify whether to canonicalise the output or not. This function is intended to be used with weak canonicalisation to prevent explosion in memory usage. It exists for performance reasons. .. function:: void _fmpq_poly_add_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) As per ``_fmpq_poly_add`` but the inputs are first notionally truncated to length `n`. If `n` is less than ``len1`` or ``len2`` then the output only needs space for `n` coefficients. We require `n \geq 0`. .. function:: void _fmpq_poly_add_series_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n, int can) As per ``_fmpq_poly_add_can`` but the inputs are first notionally truncated to length `n`. If `n` is less than ``len1`` or ``len2`` then the output only needs space for `n` coefficients. We require `n \geq 0`. .. function:: void fmpq_poly_add_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) As per ``fmpq_poly_add`` but the inputs are first notionally truncated to length `n`. .. function:: void fmpq_poly_add_series_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n, int can) As per ``fmpq_poly_add_can`` but the inputs are first notionally truncated to length `n`. .. function:: void _fmpq_poly_sub(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) Forms the difference ``(rpoly, rden)`` of ``(poly1, den1, len1)`` and ``(poly2, den2, len2)``, placing the result into canonical form. Assumes that ``rpoly`` is an array of length the maximum of ``len1`` and ``len2``. The input operands are assumed to be in canonical form and are also allowed to be of length `0`. ``(rpoly, rden)`` and ``(poly1, den1, len1)`` may be aliased, but ``(rpoly, rden)`` and ``(poly2, den2, len2)`` may *not* be aliased. .. function:: void _fmpq_poly_sub_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, int can) As per ``_fmpq_poly_sub`` except that one can specify whether to canonicalise the output or not. This function is intended to be used with weak canonicalisation to prevent explosion in memory usage. It exists for performance reasons. .. function:: void fmpq_poly_sub(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``res`` to the difference of ``poly1`` and ``poly2``, using Henrici's algorithm. .. function:: void fmpq_poly_sub_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can) As per ``_fmpq_poly_sub`` except that one can specify whether to canonicalise the output or not. This function is intended to be used with weak canonicalisation to prevent explosion in memory usage. It exists for performance reasons. .. function:: void _fmpq_poly_sub_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) As per ``_fmpq_poly_sub`` but the inputs are first notionally truncated to length `n`. If `n` is less than ``len1`` or ``len2`` then the output only needs space for `n` coefficients. We require `n \geq 0`. .. function:: void _fmpq_poly_sub_series_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n, int can) As per ``_fmpq_poly_sub_can`` but the inputs are first notionally truncated to length `n`. If `n` is less than ``len1`` or ``len2`` then the output only needs space for `n` coefficients. We require `n \geq 0`. .. function:: void fmpq_poly_sub_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) As per ``fmpq_poly_sub`` but the inputs are first notionally truncated to length `n`. .. function:: void fmpq_poly_sub_series_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n, int can) As per ``fmpq_poly_sub_can`` but the inputs are first notionally truncated to length `n`. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_scalar_mul_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c) Sets ``(rpoly, rden, len)`` to the product of `c` of ``(poly, den, len)``. If the input is normalised, then so is the output, provided it is non-zero. If the input is in lowest terms, then so is the output. However, even if neither of these conditions are met, the result will be (mathematically) correct. Supports exact aliasing between ``(rpoly, den)`` and ``(poly, den)``. .. function:: void _fmpq_poly_scalar_mul_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c) Sets ``(rpoly, rden, len)`` to the product of `c` of ``(poly, den, len)``. If the input is normalised, then so is the output, provided it is non-zero. If the input is in lowest terms, then so is the output. However, even if neither of these conditions are met, the result will be (mathematically) correct. Supports exact aliasing between ``(rpoly, den)`` and ``(poly, den)``. .. function:: void _fmpq_poly_scalar_mul_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c) Sets ``(rpoly, rden, len)`` to the product of `c` of ``(poly, den, len)``. If the input is normalised, then so is the output, provided it is non-zero. If the input is in lowest terms, then so is the output. However, even if neither of these conditions are met, the result will be (mathematically) correct. Supports exact aliasing between ``(rpoly, den)`` and ``(poly, den)``. .. function:: void _fmpq_poly_scalar_mul_fmpq(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t r, const fmpz_t s) Sets ``(rpoly, rden)`` to the product of `r/s` and ``(poly, den, len)``, in lowest terms. Assumes that ``(poly, den, len)`` and `r/s` are provided in lowest terms. Assumes that ``rpoly`` is an array of length ``len``. Supports aliasing of ``(rpoly, den)`` and ``(poly, den)``. The ``fmpz_t``'s `r` and `s` may not be part of ``(rpoly, rden)``. .. function:: void fmpq_poly_scalar_mul_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c) void fmpq_poly_scalar_mul_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c) void fmpq_poly_scalar_mul_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c) Sets ``rop`` to `c` times ``op``. .. function:: void fmpq_poly_scalar_mul_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c) Sets ``rop`` to `c` times ``op``. Assumes that the ``fmpz_t c`` is not part of ``rop``. .. function:: void _fmpq_poly_scalar_div_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c) Sets ``(rpoly, rden, len)`` to ``(poly, den, len)`` divided by `c`, in lowest terms. Assumes that ``len`` is positive. Assumes that `c` is non-zero. Supports aliasing between ``(rpoly, rden)`` and ``(poly, den)``. Assumes that `c` is not part of ``(rpoly, rden)``. .. function:: void _fmpq_poly_scalar_div_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c) Sets ``(rpoly, rden, len)`` to ``(poly, den, len)`` divided by `c`, in lowest terms. Assumes that ``len`` is positive. Assumes that `c` is non-zero. Supports aliasing between ``(rpoly, rden)`` and ``(poly, den)``. .. function:: void _fmpq_poly_scalar_div_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c) Sets ``(rpoly, rden, len)`` to ``(poly, den, len)`` divided by `c`, in lowest terms. Assumes that ``len`` is positive. Assumes that `c` is non-zero. Supports aliasing between ``(rpoly, rden)`` and ``(poly, den)``. .. function:: void _fmpq_poly_scalar_div_fmpq(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t r, const fmpz_t s) Sets ``(rpoly, rden, len)`` to ``(poly, den, len)`` divided by `r/s`, in lowest terms. Assumes that ``len`` is positive. Assumes that `r/s` is non-zero and in lowest terms. Supports aliasing between ``(rpoly, rden)`` and ``(poly, den)``. The ``fmpz_t``'s `r` and `s` may not be part of ``(rpoly, poly)``. .. function:: void fmpq_poly_scalar_div_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c) void fmpq_poly_scalar_div_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c) void fmpq_poly_scalar_div_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c) void fmpq_poly_scalar_div_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c) Sets ``rop`` to ``op`` divided by the scalar ``c``. Multiplication -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_mul(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) Sets ``(rpoly, rden, len1 + len2 - 1)`` to the product of ``(poly1, den1, len1)`` and ``(poly2, den2, len2)``. If the input is provided in canonical form, then so is the output. Assumes ``len1 >= len2 > 0``. Allows zero-padding in the input. Does not allow aliasing between the inputs and outputs. .. function:: void fmpq_poly_mul(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _fmpq_poly_mullow(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) Sets ``(rpoly, rden, n)`` to the low `n` coefficients of ``(poly1, den1)`` and ``(poly2, den2)``. The output is not guaranteed to be in canonical form. Assumes ``len1 >= len2 > 0`` and ``0 < n <= len1 + len2 - 1``. Allows for zero-padding in the inputs. Does not allow aliasing between the inputs and outputs. .. function:: void fmpq_poly_mullow(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) Sets ``res`` to the product of ``poly1`` and ``poly2``, truncated to length `n`. .. function:: void fmpq_poly_addmul(fmpq_poly_t rop, const fmpq_poly_t op1, const fmpq_poly_t op2) Adds the product of ``op1`` and ``op2`` to ``rop``. .. function:: void fmpq_poly_submul(fmpq_poly_t rop, const fmpq_poly_t op1, const fmpq_poly_t op2) Subtracts the product of ``op1`` and ``op2`` from ``rop``. Powering -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_pow(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong e) Sets ``(rpoly, rden)`` to ``(poly, den)^e``, assuming ``e, len > 0``. Assumes that ``rpoly`` is an array of length at least ``e * (len - 1) + 1``. Supports aliasing of ``(rpoly, den)`` and ``(poly, den)``. .. function:: void fmpq_poly_pow(fmpq_poly_t res, const fmpq_poly_t poly, ulong e) Sets ``res`` to ``poly^e``, where the only special case `0^0` is defined as `1`. .. function:: void _fmpq_poly_pow_trunc(fmpz * res, fmpz_t rden, const fmpz * f, const fmpz_t fden, slong flen, ulong exp, slong len) Sets ``(rpoly, rden, len)`` to ``(poly, den)^e`` truncated to length ``len``, where ``len`` is at most ``e * (flen - 1) + 1``. .. function:: void fmpq_poly_pow_trunc(fmpq_poly_t res, const fmpq_poly_t poly, ulong e, slong n) Sets ``res`` to ``poly^e`` truncated to length ``n``. Shifting -------------------------------------------------------------------------------- .. function:: void fmpq_poly_shift_left(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Set ``res`` to ``poly`` shifted left by `n` coefficients. Zero coefficients are inserted. .. function:: void fmpq_poly_shift_right(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Set ``res`` to ``poly`` shifted right by `n` coefficients. If `n` is equal to or greater than the current length of ``poly``, ``res`` is set to the zero polynomial. Euclidean division -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_divrem(fmpz * Q, fmpz_t q, fmpz * R, fmpz_t r, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv) Finds the quotient ``(Q, q)`` and remainder ``(R, r)`` of the Euclidean division of ``(A, a)`` by ``(B, b)``. Assumes that ``lenA >= lenB > 0``. Assumes that `R` has space for ``lenA`` coefficients, although only the bottom ``lenB - 1`` will carry meaningful data on exit. Supports no aliasing between the two outputs, or between the inputs and the outputs. An optional precomputed inverse of the leading coefficient of `B` from ``fmpz_preinvn_init`` can be supplied. Otherwise ``inv`` should be ``NULL``. Note: ``fmpz.h`` has to be included before ``fmpq_poly.h`` in order for the latter to declare this function. .. function:: void fmpq_poly_divrem(fmpq_poly_t Q, fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Finds the quotient `Q` and remainder `R` of the Euclidean division of ``poly1`` by ``poly2``. .. function:: void _fmpq_poly_div(fmpz * Q, fmpz_t q, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv) Finds the quotient ``(Q, q)`` of the Euclidean division of ``(A, a)`` by ``(B, b)``. Assumes that ``lenA >= lenB > 0``. Supports no aliasing between the inputs and the outputs. An optional precomputed inverse of the leading coefficient of `B` from ``fmpz_preinvn_init`` can be supplied. Otherwise ``inv`` should be ``NULL``. Note: ``fmpz.h`` has to be included before ``fmpq_poly.h`` in order for the latter to declare this function. .. function:: void fmpq_poly_div(fmpq_poly_t Q, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Finds the quotient `Q` and remainder `R` of the Euclidean division of ``poly1`` by ``poly2``. .. function:: void _fmpq_poly_rem(fmpz * R, fmpz_t r, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv) Finds the remainder ``(R, r)`` of the Euclidean division of ``(A, a)`` by ``(B, b)``. Assumes that ``lenA >= lenB > 0``. Supports no aliasing between the inputs and the outputs. An optional precomputed inverse of the leading coefficient of `B` from ``fmpz_preinvn_init`` can be supplied. Otherwise ``inv`` should be ``NULL``. Note: ``fmpz.h`` has to be included before ``fmpq_poly.h`` in order for the latter to declare this function. .. function:: void fmpq_poly_rem(fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Finds the remainder `R` of the Euclidean division of ``poly1`` by ``poly2``. Powering -------------------------------------------------------------------------------- .. function:: fmpq_poly_struct * _fmpq_poly_powers_precompute(const fmpz * B, const fmpz_t denB, slong len) Computes ``2*len - 1`` powers of `x` modulo the polynomial `B` of the given length. This is used as a kind of precomputed inverse in the remainder routine below. .. function:: void fmpq_poly_powers_precompute(fmpq_poly_powers_precomp_t pinv, fmpq_poly_t poly) Computes ``2*len - 1`` powers of `x` modulo the polynomial `B` of the given length. This is used as a kind of precomputed inverse in the remainder routine below. .. function:: void _fmpq_poly_powers_clear(fmpq_poly_struct * powers, slong len) Clean up resources used by precomputed powers which have been computed by ``_fmpq_poly_powers_precompute``. .. function:: void fmpq_poly_powers_clear(fmpq_poly_powers_precomp_t pinv) Clean up resources used by precomputed powers which have been computed by ``fmpq_poly_powers_precompute``. .. function:: void _fmpq_poly_rem_powers_precomp(fmpz * A, fmpz_t denA, slong m, const fmpz * B, const fmpz_t denB, slong n, fmpq_poly_struct * const powers) Set `A` to the remainder of `A` divide `B` given precomputed powers mod `B` provided by ``_fmpq_poly_powers_precompute``. No aliasing is allowed. This function is only faster if `m \leq 2\cdot n - 1`. The output of this function is *not* canonicalised. .. function:: void fmpq_poly_rem_powers_precomp(fmpq_poly_t R, const fmpq_poly_t A, const fmpq_poly_t B, const fmpq_poly_powers_precomp_t B_inv) Set `R` to the remainder of `A` divide `B` given precomputed powers mod `B` provided by ``fmpq_poly_powers_precompute``. This function is only faster if ``A->length <= 2*B->length - 1``. The output of this function is *not* canonicalised. Divisibility testing -------------------------------------------------------------------------------- .. function:: int _fmpq_poly_divides(fmpz * qpoly, fmpz_t qden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) Return `1` if ``(poly2, den2, len2)`` divides ``(poly1, den1, len1)`` and set ``(qpoly, qden, len1 - len2 + 1)`` to the quotient. Otherwise return `0`. Requires that ``qpoly`` has space for ``len1 - len2 + 1`` coefficients and that ``len1 >= len2 > 0``. .. function:: int fmpq_poly_divides(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Return `1` if ``poly2`` divides ``poly1`` and set ``q`` to the quotient. Otherwise return `0`. .. function:: slong fmpq_poly_remove(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``q`` to the quotient of ``poly1`` by the highest power of ``poly2`` which divides it, and returns the power. The divisor ``poly2`` must not be constant or an exception is raised. Power series division -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_inv_series_newton(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong n) Computes the first `n` terms of the inverse power series of ``(poly, den, len)`` using Newton iteration. The result is produced in canonical form. Assumes that `n \geq 1` and that ``poly`` has non-zero constant term. Does not support aliasing. .. function:: void fmpq_poly_inv_series_newton(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Computes the first `n` terms of the inverse power series of ``poly`` using Newton iteration, assuming that ``poly`` has non-zero constant term and `n \geq 1`. .. function:: void _fmpq_poly_inv_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong den_len, slong n) Computes the first `n` terms of the inverse power series of ``(poly, den, len)``. The result is produced in canonical form. Assumes that `n \geq 1` and that ``poly`` has non-zero constant term. Does not support aliasing. .. function:: void fmpq_poly_inv_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Computes the first `n` terms of the inverse power series of ``poly``, assuming that ``poly`` has non-zero constant term and `n \geq 1`. .. function:: void _fmpq_poly_div_series(fmpz * Q, fmpz_t denQ, const fmpz * A, const fmpz_t denA, slong lenA, const fmpz * B, const fmpz_t denB, slong lenB, slong n) Divides ``(A, denA, lenA)`` by ``(B, denB, lenB)`` as power series over `\mathbb{Q}`, assuming `B` has non-zero constant term and that all lengths are positive. Aliasing is not supported. This function ensures that the numerator and denominator are coprime on exit. .. function:: void fmpq_poly_div_series(fmpq_poly_t Q, const fmpq_poly_t A, const fmpq_poly_t B, slong n) Performs power series division in `\mathbb{Q}[[x]] / (x^n)`. The function considers the polynomials `A` and `B` as power series of length `n` starting with the constant terms. The function assumes that `B` has non-zero constant term and `n \geq 1`. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_gcd(fmpz * G, fmpz_t denG, const fmpz * A, slong lenA, const fmpz * B, slong lenB) Computes the monic greatest common divisor `G` of `A` and `B`. Assumes that `G` has space for `\operatorname{len}(B)` coefficients, where `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Aliasing between the output and input arguments is not supported. Does not support zero-padding. .. function:: void fmpq_poly_gcd(fmpq_poly_t G, const fmpq_poly_t A, const fmpq_poly_t B) Computes the monic greatest common divisor `G` of `A` and `B`. In the special case when `A = B = 0`, sets `G = 0`. .. function:: void _fmpq_poly_xgcd(fmpz * G, fmpz_t denG, fmpz * S, fmpz_t denS, fmpz * T, fmpz_t denT, const fmpz * A, const fmpz_t denA, slong lenA, const fmpz * B, const fmpz_t denB, slong lenB) Computes polynomials `G`, `S`, and `T` such that `G = \gcd(A, B) = S A + T B`, where `G` is the monic greatest common divisor of `A` and `B`. Assumes that `G`, `S`, and `T` have space for `\operatorname{len}(B)`, `\operatorname{len}(B)`, and `\operatorname{len}(A)` coefficients, respectively, where it is also assumed that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Does not support zero padding of the input arguments. .. function:: void fmpq_poly_xgcd(fmpq_poly_t G, fmpq_poly_t S, fmpq_poly_t T, const fmpq_poly_t A, const fmpq_poly_t B) Computes polynomials `G`, `S`, and `T` such that `G = \gcd(A, B) = S A + T B`, where `G` is the monic greatest common divisor of `A` and `B`. Corner cases are handled as follows. If `A = B = 0`, returns `G = S = T = 0`. If `A \neq 0`, `B = 0`, returns the suitable scalar multiple of `G = A`, `S = 1`, and `T = 0`. The case when `A = 0`, `B \neq 0` is handled similarly. .. function:: void _fmpq_poly_lcm(fmpz * L, fmpz_t denL, const fmpz * A, slong lenA, const fmpz * B, slong lenB) Computes the monic least common multiple `L` of `A` and `B`. Assumes that `L` has space for `\operatorname{len}(A) + \operatorname{len}(B) - 1` coefficients, where `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Aliasing between the output and input arguments is not supported. Does not support zero-padding. .. function:: void fmpq_poly_lcm(fmpq_poly_t L, const fmpq_poly_t A, const fmpq_poly_t B) Computes the monic least common multiple `L` of `A` and `B`. In the special case when `A = B = 0`, sets `L = 0`. .. function:: void _fmpq_poly_resultant(fmpz_t rnum, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) Sets ``(rnum, rden)`` to the resultant of the two input polynomials. Assumes that ``len1 >= len2 > 0``. Does not support zero-padding of the input polynomials. Does not support aliasing of the input and output arguments. .. function:: void fmpq_poly_resultant(fmpq_t r, const fmpq_poly_t f, const fmpq_poly_t g) Returns the resultant of `f` and `g`. Enumerating the roots of `f` and `g` over `\bar{\mathbf{Q}}` as `r_1, \dotsc, r_m` and `s_1, \dotsc, s_n`, respectively, and letting `x` and `y` denote the leading coefficients, the resultant is defined as .. math:: x^{\deg(f)} y^{\deg(g)} \prod_{1 \leq i, j \leq n} (r_i - s_j). We handle special cases as follows: if one of the polynomials is zero, the resultant is zero. Note that otherwise if one of the polynomials is constant, the last term in the above expression is the empty product. .. function:: void fmpq_poly_resultant_div(fmpq_t r, const fmpq_poly_t f, const fmpq_poly_t g, const fmpz_t div, slong nbits) Returns the resultant of `f` and `g` divided by ``div`` under the assumption that the result has at most ``nbits`` bits. The result must be an integer. Derivative and integral -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) Sets ``(rpoly, rden, len - 1)`` to the derivative of ``(poly, den, len)``. Does nothing if ``len <= 1``. Supports aliasing between the two polynomials. .. function:: void fmpq_poly_derivative(fmpq_poly_t res, const fmpq_poly_t poly) Sets ``res`` to the derivative of ``poly``. .. function:: void _fmpq_poly_nth_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, ulong n, slong len) Sets ``(rpoly, rden, len - n)`` to the nth derivative of ``(poly, den, len)``. Does nothing if ``len <= n``. Supports aliasing between the two polynomials. .. function:: void fmpq_poly_nth_derivative(fmpq_poly_t res, const fmpq_poly_t poly, ulong n) Sets ``res`` to the nth derivative of ``poly``. .. function:: void _fmpq_poly_integral(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) Sets ``(rpoly, rden, len)`` to the integral of ``(poly, den, len - 1)``. Assumes ``len >= 0``. Supports aliasing between the two polynomials. The output will be in canonical form if the input is in canonical form. .. function:: void fmpq_poly_integral(fmpq_poly_t res, const fmpq_poly_t poly) Sets ``res`` to the integral of ``poly``. The constant term is set to zero. In particular, the integral of the zero polynomial is the zero polynomial. Square roots -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_sqrt_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the square root of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 1. Does not support aliasing between the input and output polynomials. .. function:: void fmpq_poly_sqrt_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the square root of ``f`` to order ``n > 1``. Requires ``f`` to have constant term 1. .. function:: void _fmpq_poly_invsqrt_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the inverse square root of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 1. Does not support aliasing between the input and output polynomials. .. function:: void fmpq_poly_invsqrt_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the inverse square root of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 1. Power sums -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_power_sums(fmpz * res, fmpz_t rden, const fmpz * poly, slong len, slong n) Compute the (truncated) power sums series of the polynomial ``(poly,len)`` up to length `n` using Newton identities. .. function:: void fmpq_poly_power_sums(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Compute the (truncated) power sum series of the monic polynomial ``poly`` up to length `n` using Newton identities. That is the power series whose coefficient of degree `i` is the sum of the `i`-th power of all (complex) roots of the polynomial ``poly``. .. function:: void _fmpq_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, const fmpz_t den, slong len) Compute an integer polynomial given by its power sums series ``(poly,den,len)``. .. function:: void fmpq_poly_power_sums_to_fmpz_poly(fmpz_poly_t res, const fmpq_poly_t Q) Compute the integer polynomial with content one and positive leading coefficient given by its power sums series ``Q``. .. function:: void fmpq_poly_power_sums_to_poly(fmpq_poly_t res, const fmpq_poly_t Q) Compute the monic polynomial from its power sums series ``Q``. Transcendental functions -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_log_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the logarithm of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 1. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_log_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the logarithm of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 1. .. function:: void _fmpq_poly_exp_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) Sets ``(g, gden, n)`` to the series expansion of the exponential function of ``(h, hden, hlen)``. Assumes ``n > 0, hlen > 0`` and that ``(h, hden, hlen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_exp_series(fmpq_poly_t res, const fmpq_poly_t h, slong n) Sets ``res`` to the series expansion of the exponential function of ``h`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_exp_expinv_series(fmpz * res1, fmpz_t res1den, fmpz * res2, fmpz_t res2den, const fmpz * h, const fmpz_t hden, slong hlen, slong n) The same as ``fmpq_poly_exp_series``, but simultaneously computes the exponential (in ``res1``, ``res1den``) and its multiplicative inverse (in ``res2``, ``res2den``). Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_exp_expinv_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t h, slong n) The same as ``fmpq_poly_exp_series``, but simultaneously computes the exponential (in ``res1``) and its multiplicative inverse (in ``res2``). .. function:: void _fmpq_poly_atan_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the inverse tangent of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_atan_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the inverse tangent of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_atanh_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the inverse hyperbolic tangent of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_atanh_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the inverse hyperbolic tangent of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_asin_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the inverse sine of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_asin_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the inverse sine of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_asinh_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the inverse hyperbolic sine of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_asinh_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the inverse hyperbolic sine of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_tan_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the tangent function of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Does not support aliasing between the input and output polynomials. .. function:: void fmpq_poly_tan_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the tangent function of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_sin_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the sine of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_sin_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the sine of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_cos_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the cosine of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_cos_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the cosine of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_sin_cos_series(fmpz * s, fmpz_t sden, fmpz * c, fmpz_t cden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(s, sden, n)`` to the series expansion of the sine of ``(f, fden, flen)``, and ``(c, cden, n)`` to the series expansion of the cosine. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_sin_cos_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t f, slong n) Sets ``res1`` to the series expansion of the sine of ``f`` to order ``n > 0``, and ``res2`` to the series expansion of the cosine. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_sinh_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the hyperbolic sine of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Does not support aliasing between the input and output polynomials. .. function:: void fmpq_poly_sinh_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the hyperbolic sine of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_cosh_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the hyperbolic cosine of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Does not support aliasing between the input and output polynomials. .. function:: void fmpq_poly_cosh_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the hyperbolic cosine of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_sinh_cosh_series(fmpz * s, fmpz_t sden, fmpz * c, fmpz_t cden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(s, sden, n)`` to the series expansion of the hyperbolic sine of ``(f, fden, flen)``, and ``(c, cden, n)`` to the series expansion of the hyperbolic cosine. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Supports aliasing between the input and output polynomials. .. function:: void fmpq_poly_sinh_cosh_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t f, slong n) Sets ``res1`` to the series expansion of the hyperbolic sine of ``f`` to order ``n > 0``, and ``res2`` to the series expansion of the hyperbolic cosine. Requires ``f`` to have constant term 0. .. function:: void _fmpq_poly_tanh_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) Sets ``(g, gden, n)`` to the series expansion of the hyperbolic tangent of ``(f, fden, flen)``. Assumes ``n > 0`` and that ``(f, fden, flen)`` has constant term 0. Does not support aliasing between the input and output polynomials. .. function:: void fmpq_poly_tanh_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) Sets ``res`` to the series expansion of the hyperbolic tangent of ``f`` to order ``n > 0``. Requires ``f`` to have constant term 0. Orthogonal polynomials -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_legendre_p(fmpz * coeffs, fmpz_t den, ulong n) Sets ``coeffs`` to the coefficient array of the Legendre polynomial `P_n(x)`, defined by `(n+1) P_{n+1}(x) = (2n+1) x P_n(x) - n P_{n-1}(x)`, for `n\ge0`. Sets ``den`` to the overall denominator. The coefficients are calculated using a hypergeometric recurrence. The length of the array will be ``n+1``. To improve performance, the common denominator is computed in one step and the coefficients are evaluated using integer arithmetic. The denominator is given by `\gcd(n!,2^n) = 2^{\lfloor n/2 \rfloor + \lfloor n/4 \rfloor + \ldots}.` See ``fmpz_poly`` for the shifted Legendre polynomials. .. function:: void fmpq_poly_legendre_p(fmpq_poly_t poly, ulong n) Sets ``poly`` to the Legendre polynomial `P_n(x)`, defined by `(n+1) P_{n+1}(x) = (2n+1) x P_n(x) - n P_{n-1}(x)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. To improve performance, the common denominator is computed in one step and the coefficients are evaluated using integer arithmetic. The denominator is given by `\gcd(n!,2^n) = 2^{\lfloor n/2 \rfloor + \lfloor n/4 \rfloor + \ldots}.` See ``fmpz_poly`` for the shifted Legendre polynomials. .. function:: void _fmpq_poly_laguerre_l(fmpz * coeffs, fmpz_t den, ulong n) Sets ``coeffs`` to the coefficient array of the Laguerre polynomial `L_n(x)`, defined by `(n+1) L_{n+1}(x) = (2n+1-x) L_n(x) - n L_{n-1}(x)`, for `n\ge0`. Sets ``den`` to the overall denominator. The coefficients are calculated using a hypergeometric recurrence. The length of the array will be ``n+1``. .. function:: void fmpq_poly_laguerre_l(fmpq_poly_t poly, ulong n) Sets ``poly`` to the Laguerre polynomial `L_n(x)`, defined by `(n+1) L_{n+1}(x) = (2n+1-x) L_n(x) - n L_{n-1}(x)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. .. function:: void _fmpq_poly_gegenbauer_c(fmpz * coeffs, fmpz_t den, ulong n, const fmpq_t a) Sets ``coeffs`` to the coefficient array of the Gegenbauer (ultraspherical) polynomial `C^{(\alpha)}_n(x) = \frac{(2\alpha)_n}{n!}{}_2F_1\left(-n,2\alpha+n; \alpha+\frac12;\frac{1-x}{2}\right)`, for integer `n\ge0` and rational `\alpha>0`. Sets ``den`` to the overall denominator. The coefficients are calculated using a hypergeometric recurrence. .. function:: void fmpq_poly_gegenbauer_c(fmpq_poly_t poly, ulong n, const fmpq_t a) Sets ``poly`` to the Gegenbauer (ultraspherical) polynomial `C^{(\alpha)}_n(x) = \frac{(2\alpha)_n}{n!}{}_2F_1\left(-n,2\alpha+n; \alpha+\frac12;\frac{1-x}{2}\right)`, for integer `n\ge0` and rational `\alpha>0`. The coefficients are calculated using a hypergeometric recurrence. Evaluation -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_evaluate_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t a) Evaluates the polynomial ``(poly, den, len)`` at the integer `a` and sets ``(rnum, rden)`` to the result in lowest terms. .. function:: void fmpq_poly_evaluate_fmpz(fmpq_t res, const fmpq_poly_t poly, const fmpz_t a) Evaluates the polynomial ``poly`` at the integer `a` and sets ``res`` to the result. .. function:: void _fmpq_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t anum, const fmpz_t aden) Evaluates the polynomial ``(poly, den, len)`` at the rational ``(anum, aden)`` and sets ``(rnum, rden)`` to the result in lowest terms. Aliasing between ``(rnum, rden)`` and ``(anum, aden)`` is not supported. .. function:: void fmpq_poly_evaluate_fmpq(fmpq_t res, const fmpq_poly_t poly, const fmpq_t a) Evaluates the polynomial ``poly`` at the rational `a` and sets ``res`` to the result. Interpolation -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_interpolate_fmpz_vec(fmpz * poly, fmpz_t den, const fmpz * xs, const fmpz * ys, slong n) Sets ``poly`` / ``den`` to the unique interpolating polynomial of degree at most `n - 1` satisfying `f(x_i) = y_i` for every pair `x_i, y_i` in ``xs`` and ``ys``. The vector ``poly`` must have room for ``n+1`` coefficients, even if the interpolating polynomial is shorter. Aliasing of ``poly`` or ``den`` with any other argument is not allowed. It is assumed that the `x` values are distinct. This function uses a simple `O(n^2)` implementation of Lagrange interpolation, clearing denominators to avoid working with fractions. It is currently not designed to be efficient for large `n`. .. function:: void fmpq_poly_interpolate_fmpz_vec(fmpq_poly_t poly, const fmpz * xs, const fmpz * ys, slong n) Sets ``poly`` to the unique interpolating polynomial of degree at most `n - 1` satisfying `f(x_i) = y_i` for every pair `x_i, y_i` in ``xs`` and ``ys``. It is assumed that the `x` values are distinct. Composition -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_compose(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) Sets ``(res, den)`` to the composition of ``(poly1, den1, len1)`` and ``(poly2, den2, len2)``, assuming ``len1, len2 > 0``. Assumes that ``res`` has space for ``(len1 - 1) * (len2 - 1) + 1`` coefficients. Does not support aliasing. .. function:: void fmpq_poly_compose(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) Sets ``res`` to the composition of ``poly1`` and ``poly2``. .. function:: void _fmpq_poly_rescale(fmpz * res, fmpz_t denr, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t anum, const fmpz_t aden) Sets ``(res, denr, len)`` to ``(poly, den, len)`` with the indeterminate rescaled by ``(anum, aden)``. Assumes that ``len > 0`` and that ``(anum, aden)`` is non-zero and in lowest terms. Supports aliasing between ``(res, denr, len)`` and ``(poly, den, len)``. .. function:: void fmpq_poly_rescale(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t a) Sets ``res`` to ``poly`` with the indeterminate rescaled by `a`. Power series composition -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_compose_series_horner(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) Sets ``(res, den, n)`` to the composition of ``(poly1, den1, len1)`` and ``(poly2, den2, len2)`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Assumes that ``len1, len2, n > 0``, that ``len1, len2 <= n``, that ``(len1-1) * (len2-1) + 1 <= n``, and that ``res`` has space for ``n`` coefficients. Does not support aliasing between any of the inputs and the output. This implementation uses the Horner scheme. The default ``fmpz_poly`` composition algorithm is automatically used when the composition can be performed over the integers. .. function:: void fmpq_poly_compose_series_horner(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. This implementation uses the Horner scheme. The default ``fmpz_poly`` composition algorithm is automatically used when the composition can be performed over the integers. .. function:: void _fmpq_poly_compose_series_brent_kung(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) Sets ``(res, den, n)`` to the composition of ``(poly1, den1, len1)`` and ``(poly2, den2, len2)`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Assumes that ``len1, len2, n > 0``, that ``len1, len2 <= n``, that ``(len1-1) * (len2-1) + 1 <= n``, and that ``res`` has space for ``n`` coefficients. Does not support aliasing between any of the inputs and the output. This implementation uses Brent-Kung algorithm 2.1 [BrentKung1978]_. The default ``fmpz_poly`` composition algorithm is automatically used when the composition can be performed over the integers. .. function:: void fmpq_poly_compose_series_brent_kung(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. This implementation uses Brent-Kung algorithm 2.1 [BrentKung1978]_. The default ``fmpz_poly`` composition algorithm is automatically used when the composition can be performed over the integers. .. function:: void _fmpq_poly_compose_series(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) Sets ``(res, den, n)`` to the composition of ``(poly1, den1, len1)`` and ``(poly2, den2, len2)`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Assumes that ``len1, len2, n > 0``, that ``len1, len2 <= n``, that ``(len1-1) * (len2-1) + 1 <= n``, and that ``res`` has space for ``n`` coefficients. Does not support aliasing between any of the inputs and the output. This implementation automatically switches between the Horner scheme and Brent-Kung algorithm 2.1 depending on the size of the inputs. The default ``fmpz_poly`` composition algorithm is automatically used when the composition can be performed over the integers. .. function:: void fmpq_poly_compose_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. This implementation automatically switches between the Horner scheme and Brent-Kung algorithm 2.1 depending on the size of the inputs. The default ``fmpz_poly`` composition algorithm is automatically used when the composition can be performed over the integers. Power series reversion -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_revert_series_lagrange(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n) Sets ``(res, den)`` to the power series reversion of ``(poly1, den1, len1)`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. Assumes that `n > 0`. Does not support aliasing between any of the inputs and the output. This implementation uses the Lagrange inversion formula. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. .. function:: void fmpq_poly_revert_series_lagrange(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Sets ``res`` to the power series reversion of ``poly1`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. This implementation uses the Lagrange inversion formula. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. .. function:: void _fmpq_poly_revert_series_lagrange_fast(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n) Sets ``(res, den)`` to the power series reversion of ``(poly1, den1, len1)`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. Assumes that `n > 0`. Does not support aliasing between any of the inputs and the output. This implementation uses a reduced-complexity implementation of the Lagrange inversion formula. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. .. function:: void fmpq_poly_revert_series_lagrange_fast(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Sets ``res`` to the power series reversion of ``poly1`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. This implementation uses a reduced-complexity implementation of the Lagrange inversion formula. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. .. function:: void _fmpq_poly_revert_series_newton(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n) Sets ``(res, den)`` to the power series reversion of ``(poly1, den1, len1)`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. Assumes that `n > 0`. Does not support aliasing between any of the inputs and the output. This implementation uses Newton iteration. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. .. function:: void fmpq_poly_revert_series_newton(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Sets ``res`` to the power series reversion of ``poly1`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. This implementation uses Newton iteration. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. .. function:: void _fmpq_poly_revert_series(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n) Sets ``(res, den)`` to the power series reversion of ``(poly1, den1, len1)`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. Assumes that `n > 0`. Does not support aliasing between any of the inputs and the output. This implementation defaults to using Newton iteration. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. .. function:: void fmpq_poly_revert_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) Sets ``res`` to the power series reversion of ``poly1`` modulo `x^n`. The constant term of ``poly2`` is required to be zero and the linear term is required to be nonzero. This implementation defaults to using Newton iteration. The default ``fmpz_poly`` reversion algorithm is automatically used when the reversion can be performed over the integers. Gaussian content -------------------------------------------------------------------------------- .. function:: void _fmpq_poly_content(fmpq_t res, const fmpz * poly, const fmpz_t den, slong len) Sets ``res`` to the content of ``(poly, den, len)``. If ``len == 0``, sets ``res`` to zero. .. function:: void fmpq_poly_content(fmpq_t res, const fmpq_poly_t poly) Sets ``res`` to the content of ``poly``. The content of the zero polynomial is defined to be zero. .. function:: void _fmpq_poly_primitive_part(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) Sets ``(rpoly, rden, len)`` to the primitive part, with non-negative leading coefficient, of ``(poly, den, len)``. Assumes that ``len > 0``. Supports aliasing between the two polynomials. .. function:: void fmpq_poly_primitive_part(fmpq_poly_t res, const fmpq_poly_t poly) Sets ``res`` to the primitive part, with non-negative leading coefficient, of ``poly``. .. function:: int _fmpq_poly_is_monic(const fmpz * poly, const fmpz_t den, slong len) Returns whether the polynomial ``(poly, den, len)`` is monic. The zero polynomial is not monic by definition. .. function:: int fmpq_poly_is_monic(const fmpq_poly_t poly) Returns whether the polynomial ``poly`` is monic. The zero polynomial is not monic by definition. .. function:: void _fmpq_poly_make_monic(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) Sets ``(rpoly, rden, len)`` to the monic scalar multiple of ``(poly, den, len)``. Assumes that ``len > 0``. Supports aliasing between the two polynomials. .. function:: void fmpq_poly_make_monic(fmpq_poly_t res, const fmpq_poly_t poly) Sets ``res`` to the monic scalar multiple of ``poly`` whenever ``poly`` is non-zero. If ``poly`` is the zero polynomial, sets ``res`` to zero. Square-free -------------------------------------------------------------------------------- .. function:: int fmpq_poly_is_squarefree(const fmpq_poly_t poly) Returns whether the polynomial ``poly`` is square-free. A non-zero polynomial is defined to be square-free if it has no non-unit square factors. We also define the zero polynomial to be square-free. Input and output -------------------------------------------------------------------------------- .. function:: int _fmpq_poly_print(const fmpz * poly, const fmpz_t den, slong len) Prints the polynomial ``(poly, den, len)`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpq_poly_print(const fmpq_poly_t poly) Prints the polynomial to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpq_poly_print_pretty(const fmpz * poly, const fmpz_t den, slong len, const char * x) .. function:: int fmpq_poly_print_pretty(const fmpq_poly_t poly, const char * var) Prints the pretty representation of ``poly`` to ``stdout``, using the null-terminated string ``var`` not equal to ``"\0"`` as the variable name. In the current implementation always returns `1`. .. function:: int _fmpq_poly_fprint(FILE * file, const fmpz * poly, const fmpz_t den, slong len) Prints the polynomial ``(poly, den, len)`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpq_poly_fprint(FILE * file, const fmpq_poly_t poly) Prints the polynomial to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpq_poly_fprint_pretty(FILE * file, const fmpz * poly, const fmpz_t den, slong len, const char * x) .. function:: int fmpq_poly_fprint_pretty(FILE * file, const fmpq_poly_t poly, const char * var) Prints the pretty representation of ``poly`` to ``stdout``, using the null-terminated string ``var`` not equal to ``"\0"`` as the variable name. In the current implementation, always returns `1`. .. function:: int fmpq_poly_read(fmpq_poly_t poly) Reads a polynomial from ``stdin``, storing the result in ``poly``. In case of success, returns a positive number. In case of failure, returns a non-positive value. .. function:: int fmpq_poly_fread(FILE * file, fmpq_poly_t poly) Reads a polynomial from the stream ``file``, storing the result in ``poly``. In case of success, returns a positive number. In case of failure, returns a non-positive value. flint-3.1.3/doc/source/fmpq_vec.rst000066400000000000000000000054651461254215100172440ustar00rootroot00000000000000.. _fmpq-vec: **fmpq_vec.h** -- vectors over rational numbers =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: fmpq * _fmpq_vec_init(slong n) Initialises a vector of ``fmpq`` values of length `n` and sets all values to 0. This is equivalent to generating a ``fmpz`` vector of length `2n` with ``_fmpz_vec_init`` and setting all denominators to 1. .. function:: void _fmpq_vec_clear(fmpq * vec, slong n) Frees an ``fmpq`` vector. Randomisation -------------------------------------------------------------------------------- .. function:: void _fmpq_vec_randtest(fmpq * f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets the entries of a vector of the given length to random rationals with numerator and denominator having up to the given number of bits per entry. .. function:: void _fmpq_vec_randtest_uniq_sorted(fmpq * vec, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets the entries of a vector of the given length to random distinct rationals with numerator and denominator having up to the given number of bits per entry. The entries in the vector are sorted. Sorting -------------------------------------------------------------------------------- .. function:: void _fmpq_vec_sort(fmpq * vec, slong len) Sorts the entries of ``(vec, len)``. Conversions -------------------------------------------------------------------------------- .. function:: void _fmpq_vec_set_fmpz_vec(fmpq * res, const fmpz * vec, slong len) Sets ``(res, len)`` to ``(vec, len)``. .. function:: void _fmpq_vec_get_fmpz_vec_fmpz(fmpz * num, fmpz_t den, const fmpq * a, slong len) Find a common denominator ``den`` of the entries of ``a`` and set ``(num, len)`` to the corresponding numerators. Dot product -------------------------------------------------------------------------------- .. function:: void _fmpq_vec_dot(fmpq_t res, const fmpq * vec1, const fmpq * vec2, slong len) Sets ``res`` to the dot product of the vectors ``(vec1, len)`` and ``(vec2, len)``. Input and output -------------------------------------------------------------------------------- .. function:: int _fmpq_vec_fprint(FILE * file, const fmpq * vec, slong len) Prints the vector of given length to the stream ``file``. The format is the length followed by two spaces, then a space separated list of coefficients. If the length is zero, only `0` is printed. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpq_vec_print(const fmpq * vec, slong len) Prints the vector of given length to ``stdout``. For further details, see :func:`_fmpq_vec_fprint()`. flint-3.1.3/doc/source/fmpz.rst000066400000000000000000001723711461254215100164210ustar00rootroot00000000000000.. _fmpz: **fmpz.h** -- integers =============================================================================== By default, an :type:`fmpz_t` is implemented as an array of :type:`fmpz`'s of length one to allow passing by reference as one can do with GMP's :type:`mpz_t` type. The :type:`fmpz_t` type is simply a single limb, though the user does not need to be aware of this except in one specific case outlined below. In all respects, :type:`fmpz_t`'s act precisely like GMP's ``mpz_t``'s, with automatic memory management, however, in the first place only one limb is used to implement them. Once an :type:`fmpz_t` overflows a limb then a multiprecision integer is automatically allocated and instead of storing the actual integer data the :type:`slong` which implements the type becomes an index into a FLINT wide array of :type:`mpz_t`'s. These internal implementation details are not important for the user to understand, except for three important things. Firstly, :type:`fmpz_t`'s will be more efficient than :type:`mpz_t`'s for single limb operations, or more precisely for signed quantities whose absolute value does not exceed ``FLINT_BITS - 2``` bits. Secondly, for small integers that fit into ```FLINT_BITS - 2``` bits much less memory will be used than for an :type:`mpz_t`. When very many :type:`fmpz_t`'s are used, there can be important cache benefits on account of this. Thirdly, it is important to understand how to deal with arrays of :type:`fmpz_t`'s. As for :type:`mpz_t`'s, there is an underlying type, an :type:`fmpz`, which can be used to create the array, e.g. :: fmpz myarr[100]; Now recall that an :type:`fmpz_t` is an array of length one of :type:`fmpz`'s. Thus, a pointer to an :type:`fmpz` can be used in place of an :type:`fmpz_t`. For example, to find the sign of the third integer in our array we would write :: int sign = fmpz_sgn(myarr + 2); The :type:`fmpz` module provides routines for memory management, basic manipulation and basic arithmetic. Unless otherwise specified, all functions in this section permit aliasing between their input arguments and between their input and output arguments. Simple example -------------- The following example computes the square of the integer `7` and prints the result. .. code-block:: c #include "fmpz.h" int main() { fmpz_t x, y; fmpz_init(x); fmpz_init(y); fmpz_set_ui(x, 7); fmpz_mul(y, x, x); fmpz_print(x); flint_printf("^2 = "); fmpz_print(y); flint_printf("\n"); fmpz_clear(x); fmpz_clear(y); } :: 7^2 = 49 Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz The FLINT multi-precision integer type uses an inline representation for small integers, specifically when the absolute value is at most `2^{62}-1` (on 64-bit machines) or `2^{30}-1` (on 32-bit machines). It switches automatically to a GMP integer for larger values. An ``fmpz`` is implemented as an ``slong``. When its second most significant bit is `0` the ``fmpz`` represents an ordinary ``slong`` integer whose absolute value is at most ``FLINT_BITS - 2`` bits. When the second most significant bit is `1` then the value represents a pointer (the pointer is shifted right `2` bits and the second most significant bit is set to `1`. This relies on the fact that ``malloc`` always allocates memory blocks on a `4` or `8` byte boundary). .. type:: fmpz_t An array of length 1 of ``fmpz``'s. This is used to pass ``fmpz``'s around by reference without fuss, similar to the way ``mpz_t`` works. .. macro:: COEFF_MAX The largest (positive) value an ``fmpz`` can be if just an ``slong``. .. macro:: COEFF_MIN The smallest (negative) value an ``fmpz`` can be if just an ``slong``. .. function:: fmpz PTR_TO_COEFF(__mpz_struct * ptr) A macro to convert an ``mpz_t`` (or more generally any ``__mpz_struct *``) to an ``fmpz`` (shifts the pointer right by `2` and sets the second most significant bit). .. function:: __mpz_struct * COEFF_TO_PTR(fmpz f) A macro to convert an ``fmpz`` which represents a pointer into an actual pointer to an ``__mpz_struct`` (i.e. to an ``mpz_t``). .. macro:: COEFF_IS_MPZ(f) A macro which returns `1` if `f` represents an ``mpz_t``, otherwise `0` is returned. .. function:: __mpz_struct * _fmpz_new_mpz(void) Initialises a new ``mpz_t`` and returns a pointer to it. This is only used internally. .. function:: void _fmpz_clear_mpz(fmpz f) Clears the ``mpz_t`` "pointed to" by the ``fmpz`` `f`. This is only used internally. .. function:: void _fmpz_cleanup_mpz_content() This function does nothing in the reentrant version of ``fmpz``. .. function:: void _fmpz_cleanup() This function does nothing in the reentrant version of ``fmpz``. .. function:: __mpz_struct * _fmpz_promote(fmpz_t f) If `f` doesn't represent an ``mpz_t``, initialise one and associate it to `f`. .. function:: __mpz_struct * _fmpz_promote_val(fmpz_t f) If `f` doesn't represent an ``mpz_t``, initialise one and associate it to `f`, but preserve the value of `f`. This function is for internal use. The resulting ``fmpz`` will be backed by an ``mpz_t`` that can be passed to GMP, but the ``fmpz`` will be in an inconsistent state with respect to the other Flint ``fmpz`` functions such as ``fmpz_is_zero``, etc. .. function:: void _fmpz_demote(fmpz_t f) If `f` represents an ``mpz_t`` clear it and make `f` just represent an ``slong``. .. function:: void _fmpz_demote_val(fmpz_t f) If `f` represents an ``mpz_t`` and its value will fit in an ``slong``, preserve the value in `f` which we make to represent an ``slong``, and clear the ``mpz_t``. .. function:: int _fmpz_is_canonical(const fmpz_t f) Returns 1 if the internal representation of `f` is correctly normalised and demoted; 0 otherwise. Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_init(fmpz_t f) A small ``fmpz_t`` is initialised, i.e. just a ``slong``. The value is set to zero. .. function:: void fmpz_init2(fmpz_t f, ulong limbs) Initialises the given ``fmpz_t`` to have space for the given number of limbs. If ``limbs`` is zero then a small ``fmpz_t`` is allocated, i.e. just a ``slong``. The value is also set to zero. It is not necessary to call this function except to save time. A call to ``fmpz_init`` will do just fine. .. function:: void fmpz_clear(fmpz_t f) Clears the given ``fmpz_t``, releasing any memory associated with it, either back to the stack or the OS, depending on whether the reentrant or non-reentrant version of FLINT is built. .. function:: void fmpz_init_set(fmpz_t f, const fmpz_t g) .. function:: void fmpz_init_set_ui(fmpz_t f, ulong g) .. function:: void fmpz_init_set_si(fmpz_t f, slong g) Initialises `f` and sets it to the value of `g`. Random generation -------------------------------------------------------------------------------- For thread-safety, the randomisation methods take as one of their parameters an object of type ``flint_rand_t``. Before calling any of the randomisation functions such an object first has to be initialised with a call to :func:`flint_randinit`. When one is finished generating random numbers, one should call :func:`flint_randclear` to clean up. .. function:: void fmpz_randbits(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) Generates a random signed integer whose absolute value has precisely the given number of bits. .. function:: void fmpz_randtest(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) Generates a random signed integer whose absolute value has a number of bits which is random from `0` up to ``bits`` inclusive. .. function:: void fmpz_randtest_unsigned(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) Generates a random unsigned integer whose value has a number of bits which is random from `0` up to ``bits`` inclusive. .. function:: void fmpz_randtest_not_zero(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) As per ``fmpz_randtest``, but the result will not be `0`. If ``bits`` is set to `0`, an exception will result. .. function:: void fmpz_randm(fmpz_t f, flint_rand_t state, const fmpz_t m) Generates a random integer in the range `0` to `m - 1` inclusive. .. function:: void fmpz_randtest_mod(fmpz_t f, flint_rand_t state, const fmpz_t m) Generates a random integer in the range `0` to `m - 1` inclusive, with an increased probability of generating values close to the endpoints. .. function:: void fmpz_randtest_mod_signed(fmpz_t f, flint_rand_t state, const fmpz_t m) Generates a random integer in the range `(-m/2, m/2]`, with an increased probability of generating values close to the endpoints or close to zero. .. function:: void fmpz_randprime(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits, int proved) Generates a random prime number with the given number of bits. The generation is performed by choosing a random number and then finding the next largest prime, and therefore does not quite give a uniform distribution over the set of primes with that many bits. Random number generation is performed using the standard Flint random number generator, which is not suitable for cryptographic use. If ``proved`` is nonzero, then the integer returned is guaranteed to actually be prime. Conversion -------------------------------------------------------------------------------- .. function:: slong fmpz_get_si(const fmpz_t f) Returns `f` as a ``slong``. The result is undefined if `f` does not fit into a ``slong``. .. function:: ulong fmpz_get_ui(const fmpz_t f) Returns `f` as an ``ulong``. The result is undefined if `f` does not fit into an ``ulong`` or is negative. .. function:: void fmpz_get_uiui(mp_limb_t * hi, mp_limb_t * low, const fmpz_t f) If `f` consists of two limbs, then ``*hi`` and ``*low`` are set to the high and low limbs, otherwise ``*low`` is set to the low limb and ``*hi`` is set to `0`. .. function:: mp_limb_t fmpz_get_nmod(const fmpz_t f, nmod_t mod) Returns `f \mod n`. .. function:: double fmpz_get_d(const fmpz_t f) Returns `f` as a ``double``, rounding down towards zero if `f` cannot be represented exactly. The outcome is undefined if `f` is too large to fit in the normal range of a double. .. function:: void fmpz_set_mpf(fmpz_t f, const mpf_t x) Sets `f` to the ``mpf_t`` `x`, rounding down towards zero if the value of `x` is fractional. .. function:: void fmpz_get_mpf(mpf_t x, const fmpz_t f) Sets the value of the ``mpf_t`` `x` to the value of `f`. .. function:: void fmpz_get_mpfr(mpfr_t x, const fmpz_t f, mpfr_rnd_t rnd) Sets the value of `x` from `f`, rounded toward the given direction ``rnd``. **Note:** Requires that ``mpfr.h`` has been included before any FLINT header is included. .. function:: double fmpz_get_d_2exp(slong * exp, const fmpz_t f) Returns `f` as a normalized ``double`` along with a `2`-exponent ``exp``, i.e. if `r` is the return value then `f = r 2^{exp}`, to within 1 ULP. .. function:: void fmpz_get_mpz(mpz_t x, const fmpz_t f) Sets the ``mpz_t`` `x` to the same value as `f`. .. function:: int fmpz_get_mpn(mp_ptr * n, fmpz_t n_in) Sets the ``mp_ptr`` `n` to the same value as `n_{in}`. Returned integer is number of limbs allocated to `n`, minimum number of limbs required to hold the value stored in `n_{in}`. .. function:: char * fmpz_get_str(char * str, int b, const fmpz_t f) Returns the representation of `f` in base `b`, which can vary between `2` and `62`, inclusive. If ``str`` is ``NULL``, the result string is allocated by the function. Otherwise, it is up to the caller to ensure that the allocated block of memory is sufficiently large. .. function:: void fmpz_set_si(fmpz_t f, slong val) Sets `f` to the given ``slong`` value. .. function:: void fmpz_set_ui(fmpz_t f, ulong val) Sets `f` to the given ``ulong`` value. .. function:: void fmpz_set_d(fmpz_t f, double c) Sets `f` to the ``double`` `c`, rounding down towards zero if the value of `c` is fractional. The outcome is undefined if `c` is infinite, not-a-number, or subnormal. .. function:: void fmpz_set_d_2exp(fmpz_t f, double d, slong exp) Sets `f` to the nearest integer to `d 2^{exp}`. .. function:: void fmpz_neg_ui(fmpz_t f, ulong val) Sets `f` to the given ``ulong`` value, and then negates `f`. .. function:: void fmpz_set_uiui(fmpz_t f, mp_limb_t hi, mp_limb_t lo) Sets `f` to ``lo``, plus ``hi`` shifted to the left by ``FLINT_BITS``. .. function:: void fmpz_neg_uiui(fmpz_t f, mp_limb_t hi, mp_limb_t lo) Sets `f` to ``lo``, plus ``hi`` shifted to the left by ``FLINT_BITS``, and then negates `f`. .. function:: void fmpz_set_signed_uiui(fmpz_t f, ulong hi, ulong lo) Sets `f` to ``lo``, plus ``hi`` shifted to the left by ``FLINT_BITS``, interpreted as a signed two's complement integer with ``2 * FLINT_BITS`` bits. .. function:: void fmpz_set_signed_uiuiui(fmpz_t f, ulong hi, ulong mid, ulong lo) Sets `f` to ``lo``, plus ``mid`` shifted to the left by ``FLINT_BITS``, plus ``hi`` shifted to the left by ``2*FLINT_BITS`` bits, interpreted as a signed two's complement integer with ``3 * FLINT_BITS`` bits. .. function:: void fmpz_set_ui_array(fmpz_t out, const ulong * in, slong n) Sets ``out`` to the nonnegative integer ``in[0] + in[1]*X + ... + in[n - 1]*X^(n - 1)`` where ``X = 2^FLINT_BITS``. It is assumed that ``n > 0``. .. function:: void fmpz_set_signed_ui_array(fmpz_t out, const ulong * in, slong n) Sets ``out`` to the integer represented in ``in[0], ..., in[n - 1]`` as a signed two's complement integer with ``n * FLINT_BITS`` bits. It is assumed that ``n > 0``. The function operates as a call to :func:`fmpz_set_ui_array` followed by a symmetric remainder modulo `2^{n\cdot FLINT\_BITS}`. .. function:: void fmpz_get_ui_array(ulong * out, slong n, const fmpz_t in) Assuming that the nonnegative integer ``in`` can be represented in the form ``out[0] + out[1]*X + ... + out[n - 1]*X^(n - 1)``, where `X = 2^{FLINT\_BITS}`, sets the corresponding elements of ``out`` so that this is true. It is assumed that ``n > 0``. .. function:: void fmpz_get_signed_ui_array(ulong * out, slong n, const fmpz_t in) Retrieves the value of `in` modulo `2^{n * FLINT\_BITS}` and puts the `n` words of the result in ``out[0], ..., out[n-1]``. This will give a signed two's complement representation of `in` (assuming `in` doesn't overflow the array). .. function:: void fmpz_get_signed_uiui(ulong * hi, ulong * lo, const fmpz_t in) Retrieves the value of `in` modulo `2^{2 * FLINT\_BITS}` and puts the high and low words into ``*hi`` and ``*lo`` respectively. .. function:: void fmpz_set_mpz(fmpz_t f, const mpz_t x) Sets `f` to the given ``mpz_t`` value. .. function:: int fmpz_set_str(fmpz_t f, const char * str, int b) Sets `f` to the value given in the null-terminated string ``str``, in base `b`. The base `b` can vary between `2` and `62`, inclusive. Returns `0` if the string contains a valid input and `-1` otherwise. .. function:: void fmpz_set_ui_smod(fmpz_t f, mp_limb_t x, mp_limb_t m) Sets `f` to the signed remainder `y \equiv x \bmod m` satisfying `-m/2 < y \leq m/2`, given `x` which is assumed to satisfy `0 \leq x < m`. .. function:: void flint_mpz_init_set_readonly(mpz_t z, const fmpz_t f) Sets the uninitialised ``mpz_t`` `z` to the value of the readonly ``fmpz_t`` `f`. Note that it is assumed that `f` does not change during the lifetime of `z`. The integer `z` has to be cleared by a call to :func:`flint_mpz_clear_readonly`. The suggested use of the two functions is as follows:: fmpz_t f; ... { mpz_t z; flint_mpz_init_set_readonly(z, f); foo(..., z); flint_mpz_clear_readonly(z); } This provides a convenient function for user code, only requiring to work with the types ``fmpz_t`` and ``mpz_t``. In critical code, the following approach may be favourable:: fmpz_t f; ... { __mpz_struct *z; z = _fmpz_promote_val(f); foo(..., z); _fmpz_demote_val(f); } .. function:: void flint_mpz_clear_readonly(mpz_t z) Clears the readonly ``mpz_t`` `z`. .. function:: void fmpz_init_set_readonly(fmpz_t f, const mpz_t z) Sets the uninitialised ``fmpz_t`` `f` to a readonly version of the integer `z`. Note that the value of `z` is assumed to remain constant throughout the lifetime of `f`. The ``fmpz_t`` `f` has to be cleared by calling the function :func:`fmpz_clear_readonly`. The suggested use of the two functions is as follows:: mpz_t z; ... { fmpz_t f; fmpz_init_set_readonly(f, z); foo(..., f); fmpz_clear_readonly(f); } .. function:: void fmpz_clear_readonly(fmpz_t f) Clears the readonly ``fmpz_t`` `f`. Input and output -------------------------------------------------------------------------------- .. function:: int fmpz_read(fmpz_t f) Reads a multiprecision integer from ``stdin``. The format is an optional minus sign, followed by one or more digits. The first digit should be non-zero unless it is the only digit. In case of success, returns a positive number. In case of failure, returns a non-positive number. This convention is adopted in light of the return values of ``scanf`` from the standard library and ``mpz_inp_str`` from GMP. .. function:: int fmpz_fread(FILE * file, fmpz_t f) Reads a multiprecision integer from the stream ``file``. The format is an optional minus sign, followed by one or more digits. The first digit should be non-zero unless it is the only digit. In case of success, returns a positive number. In case of failure, returns a non-positive number. This convention is adopted in light of the return values of ``scanf`` from the standard library and ``mpz_inp_str`` from GMP. .. function:: size_t fmpz_inp_raw(fmpz_t x, FILE * fin) Reads a multiprecision integer from the stream ``file``. The format is raw binary format write by :func:`fmpz_out_raw`. In case of success, return a positive number, indicating number of bytes read. In case of failure 0. This function calls the ``mpz_inp_raw`` function in library gmp. So that it can read the raw data written by ``mpz_inp_raw`` directly. .. function:: int fmpz_fprint(FILE * fs, const fmpz_t x) int fmpz_print(const fmpz_t x) Prints the value `x` to ``fs`` or ``stdout``, without a carriage return. The value is printed as either `0`, the decimal digits of a positive integer, or a minus sign followed by the digits of a negative integer. Returns the number of characters written to file stream. .. function:: size_t fmpz_out_raw(FILE * fout, const fmpz_t x ) Writes the value `x` to ``file``. The value is written in raw binary format. The integer is written in portable format, with 4 bytes of size information, and that many bytes of limbs. Both the size and the limbs are written in decreasing significance order (i.e., in big-endian). The output can be read with ``fmpz_inp_raw``. In case of success, return a positive number, indicating number of bytes written. In case of failure, return 0. The output of this can also be read by ``mpz_inp_raw`` from GMP, since this function calls the ``mpz_inp_raw`` function in library gmp. Basic properties and manipulation -------------------------------------------------------------------------------- .. function:: size_t fmpz_sizeinbase(const fmpz_t f, int b) Returns the size of the absolute value of `f` in base `b`, measured in numbers of digits. The base `b` can be between `2` and `62`, inclusive. .. function:: flint_bitcnt_t fmpz_bits(const fmpz_t f) Returns the number of bits required to store the absolute value of `f`. If `f` is `0` then `0` is returned. .. function:: mp_size_t fmpz_size(const fmpz_t f) Returns the number of limbs required to store the absolute value of `f`. If `f` is zero then `0` is returned. .. function:: int fmpz_sgn(const fmpz_t f) Returns `-1` if the sign of `f` is negative, `+1` if it is positive, otherwise returns `0`. .. function:: flint_bitcnt_t fmpz_val2(const fmpz_t f) Returns the exponent of the largest power of two dividing `f`, or equivalently the number of trailing zeros in the binary expansion of `f`. If `f` is zero then `0` is returned. .. function:: void fmpz_swap(fmpz_t f, fmpz_t g) Efficiently swaps `f` and `g`. No data is copied. .. function:: void fmpz_set(fmpz_t f, const fmpz_t g) Sets `f` to the same value as `g`. .. function:: void fmpz_zero(fmpz_t f) Sets `f` to zero. .. function:: void fmpz_one(fmpz_t f) Sets `f` to one. .. function:: int fmpz_abs_fits_ui(const fmpz_t f) Returns whether the absolute value of `f` fits into an ``ulong``. .. function:: int fmpz_fits_si(const fmpz_t f) Returns whether the value of `f` fits into a ``slong``. .. function:: void fmpz_setbit(fmpz_t f, ulong i) Sets bit index `i` of `f`. .. function:: int fmpz_tstbit(const fmpz_t f, ulong i) Test bit index `i` of `f` and return `0` or `1`, accordingly. .. function:: mp_limb_t fmpz_abs_lbound_ui_2exp(slong * exp, const fmpz_t x, int bits) For nonzero `x`, returns a mantissa `m` with exactly ``bits`` bits and sets ``exp`` to an exponent `e`, such that `|x| \ge m 2^e`. The number of bits must be between 1 and ``FLINT_BITS`` inclusive. The mantissa is guaranteed to be correctly rounded. .. function:: mp_limb_t fmpz_abs_ubound_ui_2exp(slong * exp, const fmpz_t x, int bits) For nonzero `x`, returns a mantissa `m` with exactly ``bits`` bits and sets ``exp`` to an exponent `e`, such that `|x| \le m 2^e`. The number of bits must be between 1 and ``FLINT_BITS`` inclusive. The mantissa is either correctly rounded or one unit too large (possibly meaning that the exponent is one too large, if the mantissa is a power of two). Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_cmp(const fmpz_t f, const fmpz_t g) .. function:: int fmpz_cmp_ui(const fmpz_t f, ulong g) .. function:: int fmpz_cmp_si(const fmpz_t f, slong g) Returns a negative value if `f < g`, positive value if `g < f`, otherwise returns `0`. .. function:: int fmpz_cmpabs(const fmpz_t f, const fmpz_t g) Returns a negative value if `\lvert f\rvert < \lvert g\rvert`, positive value if `\lvert g\rvert < \lvert f \rvert`, otherwise returns `0`. .. function:: int fmpz_cmp2abs(const fmpz_t f, const fmpz_t g) Returns a negative value if `\lvert f\rvert < \lvert 2g\rvert`, positive value if `\lvert 2g\rvert < \lvert f \rvert`, otherwise returns `0`. .. function:: int fmpz_equal(const fmpz_t f, const fmpz_t g) .. function:: int fmpz_equal_ui(const fmpz_t f, ulong g) .. function:: int fmpz_equal_si(const fmpz_t f, slong g) Returns `1` if `f` is equal to `g`, otherwise returns `0`. .. function:: int fmpz_is_zero(const fmpz_t f) Returns `1` if `f` is `0`, otherwise returns `0`. .. function:: int fmpz_is_one(const fmpz_t f) Returns `1` if `f` is equal to one, otherwise returns `0`. .. function:: int fmpz_is_pm1(const fmpz_t f) Returns `1` if `f` is equal to one or minus one, otherwise returns `0`. .. function:: int fmpz_is_even(const fmpz_t f) Returns whether the integer `f` is even. .. function:: int fmpz_is_odd(const fmpz_t f) Returns whether the integer `f` is odd. Basic arithmetic -------------------------------------------------------------------------------- .. function:: void fmpz_neg(fmpz_t f1, const fmpz_t f2) Sets `f_1` to `-f_2`. .. function:: void fmpz_abs(fmpz_t f1, const fmpz_t f2) Sets `f_1` to the absolute value of `f_2`. .. function:: void fmpz_add(fmpz_t f, const fmpz_t g, const fmpz_t h) void fmpz_add_ui(fmpz_t f, const fmpz_t g, ulong h) void fmpz_add_si(fmpz_t f, const fmpz_t g, slong h) Sets `f` to `g + h`. .. function:: void fmpz_sub(fmpz_t f, const fmpz_t g, const fmpz_t h) void fmpz_sub_ui(fmpz_t f, const fmpz_t g, ulong h) void fmpz_sub_si(fmpz_t f, const fmpz_t g, slong h) Sets `f` to `g - h`. .. function:: void fmpz_mul(fmpz_t f, const fmpz_t g, const fmpz_t h) void fmpz_mul_ui(fmpz_t f, const fmpz_t g, ulong h) void fmpz_mul_si(fmpz_t f, const fmpz_t g, slong h) Sets `f` to `g \times h`. .. function:: void fmpz_mul2_uiui(fmpz_t f, const fmpz_t g, ulong x, ulong y) Sets `f` to `g \times x \times y` where `x` and `y` are of type ``ulong``. .. function:: void fmpz_mul_2exp(fmpz_t f, const fmpz_t g, ulong e) Sets `f` to `g \times 2^e`. Note: Assumes that ``e + FLINT_BITS`` does not overflow. .. function:: void fmpz_one_2exp(fmpz_t f, ulong e) Sets `f` to `2^e`. .. function:: void fmpz_addmul(fmpz_t f, const fmpz_t g, const fmpz_t h) void fmpz_addmul_ui(fmpz_t f, const fmpz_t g, ulong h) void fmpz_addmul_si(fmpz_t f, const fmpz_t g, slong h) Sets `f` to `f + g \times h`. .. function:: void fmpz_submul(fmpz_t f, const fmpz_t g, const fmpz_t h) void fmpz_submul_ui(fmpz_t f, const fmpz_t g, ulong h) void fmpz_submul_si(fmpz_t f, const fmpz_t g, slong h) Sets `f` to `f - g \times h`. .. function:: void fmpz_fmma(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d) Sets `f` to `a \times b + c \times d`. .. function:: void fmpz_fmms(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d) Sets `f` to `a \times b - c \times d`. .. function:: void fmpz_cdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_fdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_tdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_ndiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_cdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_tdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_cdiv_q_si(fmpz_t f, const fmpz_t g, slong h) .. function:: void fmpz_fdiv_q_si(fmpz_t f, const fmpz_t g, slong h) .. function:: void fmpz_tdiv_q_si(fmpz_t f, const fmpz_t g, slong h) .. function:: void fmpz_cdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) .. function:: void fmpz_fdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) .. function:: void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) .. function:: void fmpz_cdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) .. function:: void fmpz_fdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) .. function:: void fmpz_tdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) .. function:: void fmpz_fdiv_r(fmpz_t s, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_cdiv_r_2exp(fmpz_t s, const fmpz_t g, ulong exp) .. function:: void fmpz_fdiv_r_2exp(fmpz_t s, const fmpz_t g, ulong exp) .. function:: void fmpz_tdiv_r_2exp(fmpz_t s, const fmpz_t g, ulong exp) Sets `f` to the quotient of `g` by `h` and/or `s` to the remainder. For the ``2exp`` functions, ``g = 2^exp``. `If `h` is `0` an exception is raised. Rounding is made in the following way: * ``fdiv`` rounds the quotient via floor rounding. * ``cdiv`` rounds the quotient via ceil rounding. * ``tdiv`` rounds the quotient via truncation, i.e. rounding towards zero. * ``ndiv`` rounds the quotient such that the remainder has the smallest absolute value. In case of ties, it rounds the quotient towards zero. .. function:: ulong fmpz_cdiv_ui(const fmpz_t g, ulong h) .. function:: ulong fmpz_fdiv_ui(const fmpz_t g, ulong h) .. function:: ulong fmpz_tdiv_ui(const fmpz_t g, ulong h) Returns the absolute value remainder of `g` divided by `h`, following the convention of rounding as seen above. If `h` is zero an exception is raised. .. function:: void fmpz_divexact(fmpz_t f, const fmpz_t g, const fmpz_t h) .. function:: void fmpz_divexact_si(fmpz_t f, const fmpz_t g, slong h) .. function:: void fmpz_divexact_ui(fmpz_t f, const fmpz_t g, ulong h) Sets `f` to the quotient of `g` and `h`, assuming that the division is exact, i.e. `g` is a multiple of `h`. If `h` is `0` an exception is raised. .. function:: void fmpz_divexact2_uiui(fmpz_t f, const fmpz_t g, ulong x, ulong y) Sets `f` to the quotient of `g` and `h = x \times y`, assuming that the division is exact, i.e. `g` is a multiple of `h`. If `x` or `y` is `0` an exception is raised. .. function:: int fmpz_divisible(const fmpz_t f, const fmpz_t g) .. function:: int fmpz_divisible_si(const fmpz_t f, slong g) Returns `1` if there is an integer `q` with `f = q g` and `0` if there is none. .. function:: int fmpz_divides(fmpz_t q, const fmpz_t g, const fmpz_t h) Returns `1` if there is an integer `q` with `f = q g` and sets `q` to the quotient. Otherwise returns `0` and sets `q` to `0`. .. function:: void fmpz_mod(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the remainder of `g` divided by `h` such that the remainder is positive. Assumes that `h` is not zero. .. function:: ulong fmpz_mod_ui(fmpz_t f, const fmpz_t g, ulong h) Sets `f` to the remainder of `g` divided by `h` such that the remainder is positive and also returns this value. Raises an exception if `h` is zero. .. function:: void fmpz_smod(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the signed remainder `y \equiv g \bmod h` satisfying `-\lvert h \rvert/2 < y \leq \lvert h\rvert/2`. .. function:: void fmpz_preinvn_init(fmpz_preinvn_t inv, const fmpz_t f) Compute a precomputed inverse ``inv`` of ``f`` for use in the ``preinvn`` functions listed below. .. function:: void fmpz_preinvn_clear(fmpz_preinvn_t inv) Clean up the resources used by a precomputed inverse created with the :func:`fmpz_preinvn_init` function. .. function:: void fmpz_fdiv_qr_preinvn(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h, const fmpz_preinvn_t hinv) As per :func:`fmpz_fdiv_qr`, but takes a precomputed inverse ``hinv`` of `h` constructed using :func:`fmpz_preinvn`. This function will be faster than :func:`fmpz_fdiv_qr_preinvn` when the number of limbs of `h` is at least ``PREINVN_CUTOFF``. .. function:: void fmpz_pow_ui(fmpz_t f, const fmpz_t g, ulong x) void fmpz_ui_pow_ui(fmpz_t f, ulong g, ulong x) Sets `f` to `g^x`. Defines `0^0 = 1`. .. function:: int fmpz_pow_fmpz(fmpz_t f, const fmpz_t g, const fmpz_t x) Sets `f` to `g^x`. Defines `0^0 = 1`. Return `1` for success and `0` for failure. The function throws only if `x` is negative. .. function:: void fmpz_powm_ui(fmpz_t f, const fmpz_t g, ulong e, const fmpz_t m) .. function:: void fmpz_powm(fmpz_t f, const fmpz_t g, const fmpz_t e, const fmpz_t m) Sets `f` to `g^e \bmod{m}`. If `e = 0`, sets `f` to `1`. Assumes that `m \neq 0`, raises an ``abort`` signal otherwise. .. function:: slong fmpz_clog(const fmpz_t x, const fmpz_t b) slong fmpz_clog_ui(const fmpz_t x, ulong b) Returns `\lceil\log_b x\rceil`. Assumes that `x \geq 1` and `b \geq 2` and that the return value fits into a signed ``slong``. .. function:: slong fmpz_flog(const fmpz_t x, const fmpz_t b) slong fmpz_flog_ui(const fmpz_t x, ulong b) Returns `\lfloor\log_b x\rfloor`. Assumes that `x \geq 1` and `b \geq 2` and that the return value fits into a signed ``slong``. .. function:: double fmpz_dlog(const fmpz_t x) Returns a double precision approximation of the natural logarithm of `x`. The accuracy depends on the implementation of the floating-point logarithm provided by the C standard library. The result can typically be expected to have a relative error no greater than 1-2 bits. .. function:: int fmpz_sqrtmod(fmpz_t b, const fmpz_t a, const fmpz_t p) If `p` is prime, set `b` to a square root of `a` modulo `p` if `a` is a quadratic residue modulo `p` and return `1`, otherwise return `0`. If `p` is not prime the return value is with high probability `0`, indicating that `p` is not prime, or `a` is not a square modulo `p`. If `p` is not prime and the return value is `1`, the value of `b` is meaningless. .. function:: void fmpz_sqrt(fmpz_t f, const fmpz_t g) Sets `f` to the integer part of the square root of `g`, where `g` is assumed to be non-negative. If `g` is negative, an exception is raised. .. function:: void fmpz_sqrtrem(fmpz_t f, fmpz_t r, const fmpz_t g) Sets `f` to the integer part of the square root of `g`, where `g` is assumed to be non-negative, and sets `r` to the remainder, that is, the difference `g - f^2`. If `g` is negative, an exception is raised. The behaviour is undefined if `f` and `r` are aliases. .. function:: int fmpz_is_square(const fmpz_t f) Returns nonzero if `f` is a perfect square and zero otherwise. .. function:: int fmpz_root(fmpz_t r, const fmpz_t f, slong n) Set `r` to the integer part of the `n`-th root of `f`. Requires that `n > 0` and that if `n` is even then `f` be non-negative, otherwise an exception is raised. The function returns `1` if the root was exact, otherwise `0`. .. function:: int fmpz_is_perfect_power(fmpz_t root, const fmpz_t f) If `f` is a perfect power `r^k` set ``root`` to `r` and return `k`, otherwise return `0`. Note that `-1, 0, 1` are all considered perfect powers. No guarantee is made about `r` or `k` being the smallest possible value. Negative values of `f` are permitted. .. function:: void fmpz_fac_ui(fmpz_t f, ulong n) Sets `f` to the factorial `n!` where `n` is an ``ulong``. .. function:: void fmpz_fib_ui(fmpz_t f, ulong n) Sets `f` to the Fibonacci number `F_n` where `n` is an ``ulong``. .. function:: void fmpz_bin_uiui(fmpz_t f, ulong n, ulong k) Sets `f` to the binomial coefficient `{n \choose k}`. .. function:: void _fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong a, ulong b) Sets `r` to the rising factorial `(x+a) (x+a+1) (x+a+2) \cdots (x+b-1)`. Assumes `b > a`. .. function:: void fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong k) Sets `r` to the rising factorial `x (x+1) (x+2) \cdots (x+k-1)`. .. function:: void fmpz_rfac_uiui(fmpz_t r, ulong x, ulong k) Sets `r` to the rising factorial `x (x+1) (x+2) \cdots (x+k-1)`. .. function:: void fmpz_mul_tdiv_q_2exp(fmpz_t f, const fmpz_t g, const fmpz_t h, ulong exp) Sets `f` to the product of `g` and `h` divided by ``2^exp``, rounding down towards zero. .. function:: void fmpz_mul_si_tdiv_q_2exp(fmpz_t f, const fmpz_t g, slong x, ulong exp) Sets `f` to the product of `g` and `x` divided by ``2^exp``, rounding down towards zero. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void fmpz_gcd_ui(fmpz_t f, const fmpz_t g, ulong h) .. function:: void fmpz_gcd(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the greatest common divisor of `g` and `h`. The result is always positive, even if one of `g` and `h` is negative. .. function:: void fmpz_gcd3(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c) Sets `f` to the greatest common divisor of `a`, `b` and `c`. This is equivalent to calling ``fmpz_gcd`` twice, but may be faster. .. function:: void fmpz_lcm(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the least common multiple of `g` and `h`. The result is always nonnegative, even if one of `g` and `h` is negative. .. function:: void fmpz_gcdinv(fmpz_t d, fmpz_t a, const fmpz_t f, const fmpz_t g) Given integers `f, g` with `0 \leq f < g`, computes the greatest common divisor `d = \gcd(f, g)` and the modular inverse `a = f^{-1} \pmod{g}`, whenever `f \neq 0`. Assumes that `d` and `a` are not aliased. .. function:: void fmpz_xgcd(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g) Computes the extended GCD of `f` and `g`, i.e. the values `a` and `b` such that `af + bg = d`, where `d = \gcd(f, g)`. Here `a` will be the same as calling ``fmpz_gcdinv`` when `f < g` (or vice versa for `b` when `g < f`). To obtain the canonical solution to Bézout's identity, call ``fmpz_xgcd_canonical_bezout`` instead. This is also faster. Assumes that there is no aliasing among the outputs. .. function:: void fmpz_xgcd_canonical_bezout(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g) Computes the extended GCD `\operatorname{xgcd}(f, g) = (d, a, b)` such that the solution is the canonical solution to Bézout's identity. We define the canonical solution to satisfy one of the following if one of the given conditions apply: .. math:: \operatorname{xgcd}(\pm g, g) &= \bigl(|g|, 0, \operatorname{sgn}(g)\bigr) \operatorname{xgcd}(f, 0) &= \bigl(|f|, \operatorname{sgn}(f), 0\bigr) \operatorname{xgcd}(0, g) &= \bigl(|g|, 0, \operatorname{sgn}(g)\bigr) \operatorname{xgcd}(f, \mp 1) &= (1, 0, \mp 1) \operatorname{xgcd}(\mp 1, g) &= (1, \mp 1, 0)\quad g \neq 0, \pm 1 \operatorname{xgcd}(\mp 2 d, g) &= \bigl(d, {\textstyle\frac{d - |g|}{\mp 2 d}}, \operatorname{sgn}(g)\bigr) \operatorname{xgcd}(f, \mp 2 d) &= \bigl(d, \operatorname{sgn}(f), {\textstyle\frac{d - |g|}{\mp 2 d}}\bigr). If the pair `(f, g)` does not satisfy any of these conditions, the solution `(d, a, b)` will satisfy the following: .. math:: |a| < \Bigl| \frac{g}{2 d} \Bigr|, \qquad |b| < \Bigl| \frac{f}{2 d} \Bigr|. Assumes that there is no aliasing among the outputs. .. function:: void fmpz_xgcd_partial(fmpz_t co2, fmpz_t co1, fmpz_t r2, fmpz_t r1, const fmpz_t L) This function is an implementation of Lehmer extended GCD with early termination, as used in the ``qfb`` module. It terminates early when remainders fall below the specified bound. The initial values ``r1`` and ``r2`` are treated as successive remainders in the Euclidean algorithm and are replaced with the last two remainders computed. The values ``co1`` and ``co2`` are the last two cofactors and satisfy the identity ``co2*r1 - co1*r2 == +/- r2_orig`` upon termination, where ``r2_orig`` is the starting value of ``r2`` supplied, and ``r1`` and ``r2`` are the final values. Aliasing of inputs is not allowed. Similarly aliasing of inputs and outputs is not allowed. Modular arithmetic -------------------------------------------------------------------------------- .. function:: slong _fmpz_remove(fmpz_t x, const fmpz_t f, double finv) Removes all factors `f` from `x` and returns the number of such. Assumes that `x` is non-zero, that `f > 1` and that ``finv`` is the precomputed ``double`` inverse of `f` whenever `f` is a small integer and `0` otherwise. Does not support aliasing. .. function:: slong fmpz_remove(fmpz_t rop, const fmpz_t op, const fmpz_t f) Remove all occurrences of the factor `f > 1` from the integer ``op`` and sets ``rop`` to the resulting integer. If ``op`` is zero, sets ``rop`` to ``op`` and returns `0`. Returns an ``abort`` signal if any of the assumptions are violated. .. function:: int fmpz_invmod(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the inverse of `g` modulo `h`. The value of `h` may not be `0` otherwise an exception results. If the inverse exists the return value will be non-zero, otherwise the return value will be `0` and the value of `f` undefined. As a special case, we consider any number invertible modulo `h = \pm 1`, with inverse 0. .. function:: void fmpz_negmod(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to `-g \pmod{h}`, assuming `g` is reduced modulo `h`. .. function:: int fmpz_jacobi(const fmpz_t a, const fmpz_t n) Computes the Jacobi symbol `\left(\frac{a}{n}\right)` for any `a` and odd positive `n`. .. function:: int fmpz_kronecker(const fmpz_t a, const fmpz_t n) Computes the Kronecker symbol `\left(\frac{a}{n}\right)` for any `a` and any `n`. .. function:: void fmpz_divides_mod_list(fmpz_t xstart, fmpz_t xstride, fmpz_t xlength, const fmpz_t a, const fmpz_t b, const fmpz_t n) Set `xstart`, `xstride`, and `xlength` so that the solution set for `x` modulo `n` in `a x = b \bmod n` is exactly `\{xstart + xstride\,i \mid 0 \le i < xlength\}`. This function essentially gives a list of possibilities for the fraction `a/b` modulo `n`. The outputs may not be aliased, and `n` should be positive. Bit packing and unpacking -------------------------------------------------------------------------------- .. function:: int fmpz_bit_pack(mp_limb_t * arr, flint_bitcnt_t shift, flint_bitcnt_t bits, const fmpz_t coeff, int negate, int borrow) Shifts the given coefficient to the left by ``shift`` bits and adds it to the integer in ``arr`` in a field of the given number of bits:: shift bits -------------- X X X C C C C 0 0 0 0 0 0 0 An optional borrow of `1` can be subtracted from ``coeff`` before it is packed. If ``coeff`` is negative after the borrow, then a borrow will be returned by the function. The value of ``shift`` is assumed to be less than ``FLINT_BITS``. All but the first ``shift`` bits of ``arr`` are assumed to be zero on entry to the function. The value of ``coeff`` may also be optionally (and notionally) negated before it is used, by setting the ``negate`` parameter to `-1`. .. function:: int fmpz_bit_unpack(fmpz_t coeff, mp_limb_t * arr, flint_bitcnt_t shift, flint_bitcnt_t bits, int negate, int borrow) A bit field of the given number of bits is extracted from ``arr``, starting after ``shift`` bits, and placed into ``coeff``. An optional borrow of `1` may be added to the coefficient. If the result is negative, a borrow of `1` is returned. Finally, the resulting ``coeff`` may be negated by setting the ``negate`` parameter to `-1`. The value of ``shift`` is expected to be less than ``FLINT_BITS``. .. function:: void fmpz_bit_unpack_unsigned(fmpz_t coeff, const mp_limb_t * arr, flint_bitcnt_t shift, flint_bitcnt_t bits) A bit field of the given number of bits is extracted from ``arr``, starting after ``shift`` bits, and placed into ``coeff``. The value of ``shift`` is expected to be less than ``FLINT_BITS``. Logic Operations -------------------------------------------------------------------------------- .. function:: void fmpz_complement(fmpz_t r, const fmpz_t f) The variable ``r`` is set to the ones-complement of ``f``. .. function:: void fmpz_clrbit(fmpz_t f, ulong i) Sets the ``i``\th bit in ``f`` to zero. .. function:: void fmpz_combit(fmpz_t f, ulong i) Complements the ``i``\th bit in ``f``. .. function:: void fmpz_and(fmpz_t r, const fmpz_t a, const fmpz_t b) Sets ``r`` to the bit-wise logical ``and`` of ``a`` and ``b``. .. function:: void fmpz_or(fmpz_t r, const fmpz_t a, const fmpz_t b) Sets ``r`` to the bit-wise logical (inclusive) ``or`` of ``a`` and ``b``. .. function:: void fmpz_xor(fmpz_t r, const fmpz_t a, const fmpz_t b) Sets ``r`` to the bit-wise logical exclusive ``or`` of ``a`` and ``b``. .. function:: ulong fmpz_popcnt(const fmpz_t a) Returns the number of '1' bits in the given Z (aka Hamming weight or population count). The return value is undefined if the input is negative. Chinese remaindering -------------------------------------------------------------------------------- The following functions can be used to reconstruct an integer from its residues modulo a set of prime numbers. The first two functions, :func:`fmpz_CRT_ui` and :func:`fmpz_CRT`, are easy to use and allow building the result one residue at a time, which is useful when the number of needed primes is not known in advance. The remaining functions support performing the modular reductions and reconstruction using balanced subdivision. This greatly improves efficiency for large integers but assumes that the basis of primes is known in advance. The user must precompute a ``comb`` structure and temporary working space with :func:`fmpz_comb_init` and :func:`fmpz_comb_temp_init`, and free this data afterwards. For simple demonstration programs showing how to use the CRT functions, see ``crt.c`` and ``multi_crt.c`` in the ``examples`` directory. The ``fmpz_multi_CRT`` class is similar to ``fmpz_multi_CRT_ui`` except that it performs error checking and works with arbitrary moduli. .. function:: void fmpz_CRT_ui(fmpz_t out, const fmpz_t r1, const fmpz_t m1, ulong r2, ulong m2, int sign) Uses the Chinese Remainder Theorem to compute the unique integer `0 \le x < M` (if sign = 0) or `-M/2 < x \le M/2` (if sign = 1) congruent to `r_1` modulo `m_1` and `r_2` modulo `m_2`, where `M = m_1 \times m_2`. The result `x` is stored in ``out``. It is assumed that `m_1` and `m_2` are positive coprime integers. If sign = 0, it is assumed that `0 \le r_1 < m_1` and `0 \le r_2 < m_2`. Otherwise, it is assumed that `-m_1 \le r_1 < m_1` and `0 \le r_2 < m_2`. .. function:: void fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2, int sign) Use the Chinese Remainder Theorem to set ``out`` to the unique value `0 \le x < M` (if sign = 0) or `-M/2 < x \le M/2` (if sign = 1) congruent to `r_1` modulo `m_1` and `r_2` modulo `m_2`, where `M = m_1 \times m_2`. It is assumed that `m_1` and `m_2` are positive coprime integers. If sign = 0, it is assumed that `0 \le r_1 < m_1` and `0 \le r_2 < m_2`. Otherwise, it is assumed that `-m_1 \le r_1 < m_1` and `0 \le r_2 < m_2`. .. function:: void fmpz_multi_mod_ui(mp_limb_t * out, const fmpz_t in, const fmpz_comb_t comb, fmpz_comb_temp_t temp) Reduces the multiprecision integer ``in`` modulo each of the primes stored in the ``comb`` structure. The array ``out`` will be filled with the residues modulo these primes. The structure ``temp`` is temporary space which must be provided by :func:`fmpz_comb_temp_init` and cleared by :func:`fmpz_comb_temp_clear`. .. function:: void fmpz_multi_CRT_ui(fmpz_t output, mp_srcptr residues, const fmpz_comb_t comb, fmpz_comb_temp_t ctemp, int sign) This function takes a set of residues modulo the list of primes contained in the ``comb`` structure and reconstructs a multiprecision integer modulo the product of the primes which has these residues modulo the corresponding primes. If `N` is the product of all the primes then ``out`` is normalised to be in the range `[0, N)` if sign = 0 and the range `[-(N-1)/2, N/2]` if sign = 1. The array ``temp`` is temporary space which must be provided by :func:`fmpz_comb_temp_init` and cleared by :func:`fmpz_comb_temp_clear`. .. function:: void fmpz_comb_init(fmpz_comb_t comb, mp_srcptr primes, slong num_primes) Initialises a ``comb`` structure for multimodular reduction and recombination. The array ``primes`` is assumed to contain ``num_primes`` primes each of ``FLINT_BITS - 1`` bits. Modular reductions and recombinations will be done modulo this list of primes. The ``primes`` array must not be ``free``'d until the ``comb`` structure is no longer required and must be cleared by the user. .. function:: void fmpz_comb_temp_init(fmpz_comb_temp_t temp, const fmpz_comb_t comb) Creates temporary space to be used by multimodular and CRT functions based on an initialised ``comb`` structure. .. function:: void fmpz_comb_clear(fmpz_comb_t comb) Clears the given ``comb`` structure, releasing any memory it uses. .. function:: void fmpz_comb_temp_clear(fmpz_comb_temp_t temp) Clears temporary space ``temp`` used by multimodular and CRT functions using the given ``comb`` structure. .. function:: void fmpz_multi_CRT_init(fmpz_multi_CRT_t CRT) Initialize ``CRT`` for Chinese remaindering. .. function:: int fmpz_multi_CRT_precompute(fmpz_multi_CRT_t CRT, const fmpz * moduli, slong len) Configure ``CRT`` for repeated Chinese remaindering of ``moduli``. The number of moduli, ``len``, should be positive. A return of ``0`` indicates that the compilation failed and future calls to :func:`fmpz_multi_CRT_precomp` will leave the output undefined. A return of ``1`` indicates that the compilation was successful, which occurs if and only if either (1) ``len == 1`` and ``modulus + 0`` is nonzero, or (2) no modulus is `0,1,-1` and all moduli are pairwise relatively prime. .. function:: void fmpz_multi_CRT_precomp(fmpz_t output, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign) Set ``output`` to an integer of smallest absolute value that is congruent to ``values + i`` modulo the ``moduli + i`` in ``P``. .. function:: int fmpz_multi_CRT(fmpz_t output, const fmpz * moduli, const fmpz * values, slong len, int sign) Perform the same operation as :func:`fmpz_multi_CRT_precomp` while internally constructing and destroying the precomputed data. All of the remarks in :func:`fmpz_multi_CRT_precompute` apply. .. function:: void fmpz_multi_CRT_clear(fmpz_multi_CRT_t P) Free all space used by ``CRT``. Primality testing -------------------------------------------------------------------------------- .. function:: int fmpz_is_strong_probabprime(const fmpz_t n, const fmpz_t a) Returns `1` if `n` is a strong probable prime to base `a`, otherwise it returns `0`. .. function:: int fmpz_is_probabprime_lucas(const fmpz_t n) Performs a Lucas probable prime test with parameters chosen by Selfridge's method `A` as per [BaiWag1980]_. Return `1` if `n` is a Lucas probable prime, otherwise return `0`. This function declares some composites probably prime, but no primes composite. .. function:: int fmpz_is_probabprime_BPSW(const fmpz_t n) Perform a Baillie-PSW probable prime test with parameters chosen by Selfridge's method `A` as per [BaiWag1980]_. Return `1` if `n` is a Lucas probable prime, otherwise return `0`. There are no known composites passed as prime by this test, though infinitely many probably exist. The test will declare no primes composite. .. function:: int fmpz_is_probabprime(const fmpz_t p) Performs some trial division and then some probabilistic primality tests. If `p` is definitely composite, the function returns `0`, otherwise it is declared probably prime, i.e. prime for most practical purposes, and the function returns `1`. The chance of declaring a composite prime is very small. Subsequent calls to the same function do not increase the probability of the number being prime. .. function:: int fmpz_is_prime_pseudosquare(const fmpz_t n) Return `0` is `n` is composite. If `n` is too large (greater than about `94` bits) the function fails silently and returns `-1`, otherwise, if `n` is proven prime by the pseudosquares method, return `1`. Tests if `n` is a prime according to [Theorem 2.7] [LukPatWil1996]_. We first factor `N` using trial division up to some limit `B`. In fact, the number of primes used in the trial factoring is at most ``FLINT_PSEUDOSQUARES_CUTOFF``. Next we compute `N/B` and find the next pseudosquare `L_p` above this value, using a static table as per https://oeis.org/A002189/b002189.txt. As noted in the text, if `p` is prime then Step 3 will pass. This test rejects many composites, and so by this time we suspect that `p` is prime. If `N` is `3` or `7` modulo `8`, we are done, and `N` is prime. We now run a probable prime test, for which no known counterexamples are known, to reject any composites. We then proceed to prove `N` prime by executing Step 4. In the case that `N` is `1` modulo `8`, if Step 4 fails, we extend the number of primes `p_i` at Step 3 and hope to find one which passes Step 4. We take the test one past the largest `p` for which we have pseudosquares `L_p` tabulated, as this already corresponds to the next `L_p` which is bigger than `2^{64}` and hence larger than any prime we might be testing. As explained in the text, Condition 4 cannot fail if `N` is prime. The possibility exists that the probable prime test declares a composite prime. However in that case an error is printed, as that would be of independent interest. .. function:: int fmpz_is_prime_pocklington(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pm1, slong num_pm1) Applies the Pocklington primality test. The test computes a product `F` of prime powers which divide `n - 1`. The function then returns either `0` if `n` is definitely composite or it returns `1` if all factors of `n` are `1 \pmod{F}`. Also in that case, `R` is set to `(n - 1)/F`. NB: a return value of `1` only proves `n` prime if `F \ge \sqrt{n}`. The function does not compute which primes divide `n - 1`. Instead, these must be supplied as an array ``pm1`` of length ``num_pm1``. It does not matter how many prime factors are supplied, but the more that are supplied, the larger F will be. There is a balance between the amount of time spent looking for factors of `n - 1` and the usefulness of the output (`F` may be as low as `2` in some cases). A reasonable heuristic seems to be to choose ``limit`` to be some small multiple of `\log^3(n)/10` (e.g. `1, 2, 5` or `10`) depending on how long one is prepared to wait, then to trial factor up to the limit. (See ``_fmpz_nm1_trial_factors``.) Requires `n` to be odd. .. function:: void _fmpz_nm1_trial_factors(const fmpz_t n, mp_ptr pm1, slong * num_pm1, ulong limit) Trial factors `n - 1` up to the given limit (approximately) and stores the factors in an array ``pm1`` whose length is written out to ``num_pm1``. One can use `\log(n) + 2` as a bound on the number of factors which might be produced (and hence on the length of the array that needs to be supplied). .. function:: int fmpz_is_prime_morrison(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pp1, slong num_pp1) Applies the Morrison `p + 1` primality test. The test computes a product `F` of primes which divide `n + 1`. The function then returns either `0` if `n` is definitely composite or it returns `1` if all factors of `n` are `\pm 1 \pmod{F}`. Also in that case, `R` is set to `(n + 1)/F`. NB: a return value of `1` only proves `n` prime if `F > \sqrt{n} + 1`. The function does not compute which primes divide `n + 1`. Instead, these must be supplied as an array ``pp1`` of length ``num_pp1``. It does not matter how many prime factors are supplied, but the more that are supplied, the larger `F` will be. There is a balance between the amount of time spent looking for factors of `n + 1` and the usefulness of the output (`F` may be as low as `2` in some cases). A reasonable heuristic seems to be to choose ``limit`` to be some small multiple of `\log^3(n)/10` (e.g. `1, 2, 5` or `10`) depending on how long one is prepared to wait, then to trial factor up to the limit. (See ``_fmpz_np1_trial_factors``.) Requires `n` to be odd and non-square. .. function:: void _fmpz_np1_trial_factors(const fmpz_t n, mp_ptr pp1, slong * num_pp1, ulong limit) Trial factors `n + 1` up to the given limit (approximately) and stores the factors in an array ``pp1`` whose length is written out to ``num_pp1``. One can use `\log(n) + 2` as a bound on the number of factors which might be produced (and hence on the length of the array that needs to be supplied). .. function:: int fmpz_is_prime(const fmpz_t n) Attempts to prove `n` prime. If `n` is proven prime, the function returns `1`. If `n` is definitely composite, the function returns `0`. This function calls :func:`n_is_prime` for `n` that fits in a single word. For `n` larger than one word, it tests divisibility by a few small primes and whether `n` is a perfect square to rule out trivial composites. For `n` up to about 81 bits, it then uses a strong probable prime test (Miller-Rabin test) with the first 13 primes as witnesses. This has been shown to prove primality [SorWeb2016]_. For larger `n`, it does a single base-2 strong probable prime test to eliminate most composite numbers. If `n` passes, it does a combination of Pocklington, Morrison and Brillhart, Lehmer, Selfridge tests. If any of these tests fails to give a proof, it falls back to performing an APRCL test. The APRCL test could theoretically fail to prove that `n` is prime or composite. In that case, the program aborts. This is not expected to occur in practice. .. function:: void fmpz_lucas_chain(fmpz_t Vm, fmpz_t Vm1, const fmpz_t A, const fmpz_t m, const fmpz_t n) Given `V_0 = 2`, `V_1 = A` compute `V_m, V_{m + 1} \pmod{n}` from the recurrences `V_j = AV_{j - 1} - V_{j - 2} \pmod{n}`. This is computed efficiently using `V_{2j} = V_j^2 - 2 \pmod{n}` and `V_{2j + 1} = V_jV_{j + 1} - A \pmod{n}`. No aliasing is permitted. .. function:: void fmpz_lucas_chain_full(fmpz_t Vm, fmpz_t Vm1, const fmpz_t A, const fmpz_t B, const fmpz_t m, const fmpz_t n) Given `V_0 = 2`, `V_1 = A` compute `V_m, V_{m + 1} \pmod{n}` from the recurrences `V_j = AV_{j - 1} - BV_{j - 2} \pmod{n}`. This is computed efficiently using double and add formulas. No aliasing is permitted. .. function:: void fmpz_lucas_chain_double(fmpz_t U2m, fmpz_t U2m1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t A, const fmpz_t B, const fmpz_t n) Given `U_m, U_{m + 1} \pmod{n}` compute `U_{2m}, U_{2m + 1} \pmod{n}`. Aliasing of `U_{2m}` and `U_m` and aliasing of `U_{2m + 1}` and `U_{m + 1}` is permitted. No other aliasing is allowed. .. function:: void fmpz_lucas_chain_add(fmpz_t Umn, fmpz_t Umn1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t Un, const fmpz_t Un1, const fmpz_t A, const fmpz_t B, const fmpz_t n) Given `U_m, U_{m + 1} \pmod{n}` and `U_n, U_{n + 1} \pmod{n}` compute `U_{m + n}, U_{m + n + 1} \pmod{n}`. Aliasing of `U_{m + n}` with `U_m` or `U_n` and aliasing of `U_{m + n + 1}` with `U_{m + 1}` or `U_{n + 1}` is permitted. No other aliasing is allowed. .. function:: void fmpz_lucas_chain_mul(fmpz_t Ukm, fmpz_t Ukm1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t A, const fmpz_t B, const fmpz_t k, const fmpz_t n) Given `U_m, U_{m + 1} \pmod{n}` compute `U_{km}, U_{km + 1} \pmod{n}`. Aliasing of `U_{km}` and `U_m` and aliasing of `U_{km + 1}` and `U_{m + 1}` is permitted. No other aliasing is allowed. .. function:: void fmpz_lucas_chain_VtoU(fmpz_t Um, fmpz_t Um1, const fmpz_t Vm, const fmpz_t Vm1, const fmpz_t A, const fmpz_t B, const fmpz_t Dinv, const fmpz_t n) Given `V_m, V_{m + 1} \pmod{n}` compute `U_m, U_{m + 1} \pmod{n}`. Aliasing of `V_m` and `U_m` and aliasing of `V_{m + 1}` and `U_{m + 1}` is permitted. No other aliasing is allowed. .. function:: int fmpz_divisor_in_residue_class_lenstra(fmpz_t fac, const fmpz_t n, const fmpz_t r, const fmpz_t s) If there exists a proper divisor of `n` which is `r \pmod{s}` for `0 < r < s < n`, this function returns `1` and sets ``fac`` to such a divisor. Otherwise the function returns `0` and the value of ``fac`` is undefined. We require `\gcd(r, s) = 1`. This is efficient if `s^3 > n`. .. function:: void fmpz_nextprime(fmpz_t res, const fmpz_t n, int proved) Finds the next prime number larger than `n`. If ``proved`` is nonzero, then the integer returned is guaranteed to actually be prime. Otherwise if `n` fits in ``FLINT_BITS - 3`` bits ``n_nextprime`` is called, and if not then the GMP ``mpz_nextprime`` function is called which uses a BPSW test. Special functions -------------------------------------------------------------------------------- .. function:: void fmpz_primorial(fmpz_t res, ulong n) Sets ``res`` to ``n`` primorial or `n \#`, the product of all prime numbers less than or equal to `n`. .. function:: void fmpz_factor_euler_phi(fmpz_t res, const fmpz_factor_t fac) void fmpz_euler_phi(fmpz_t res, const fmpz_t n) Sets ``res`` to the Euler totient function `\phi(n)`, counting the number of positive integers less than or equal to `n` that are coprime to `n`. The factor version takes a precomputed factorisation of `n`. .. function:: int fmpz_factor_moebius_mu(const fmpz_factor_t fac) int fmpz_moebius_mu(const fmpz_t n) Computes the Moebius function `\mu(n)`, which is defined as `\mu(n) = 0` if `n` has a prime factor of multiplicity greater than `1`, `\mu(n) = -1` if `n` has an odd number of distinct prime factors, and `\mu(n) = 1` if `n` has an even number of distinct prime factors. By convention, `\mu(0) = 0`. The factor version takes a precomputed factorisation of `n`. .. function:: void fmpz_factor_divisor_sigma(fmpz_t res, ulong k, const fmpz_factor_t fac) void fmpz_divisor_sigma(fmpz_t res, ulong k, const fmpz_t n) Sets ``res`` to `\sigma_k(n)`, the sum of `k`\th powers of all divisors of `n`. The factor version takes a precomputed factorisation of `n`. flint-3.1.3/doc/source/fmpz_extras.rst000066400000000000000000000105651461254215100200030ustar00rootroot00000000000000.. _fmpz_extras: **fmpz_extras.h** -- extra methods for FLINT integers =============================================================================== This module implements a few utility methods for the FLINT multiprecision integer type (*fmpz_t*). It is mainly intended for internal use. Memory-related methods ------------------------------------------------------------------------------- .. function:: slong fmpz_allocated_bytes(const fmpz_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(fmpz)`` to get the size of the object as a whole. Convenience methods ------------------------------------------------------------------------------- .. function:: void fmpz_adiv_q_2exp(fmpz_t z, const fmpz_t x, flint_bitcnt_t exp) Sets *z* to `x / 2^{exp}`, rounded away from zero. .. function:: void fmpz_ui_mul_ui(fmpz_t x, ulong a, ulong b) Sets *x* to *a* times *b*. .. function:: void fmpz_max(fmpz_t z, const fmpz_t x, const fmpz_t y) .. function:: void fmpz_min(fmpz_t z, const fmpz_t x, const fmpz_t y) Sets *z* to the maximum (respectively minimum) of *x* and *y*. Inlined arithmetic ------------------------------------------------------------------------------- The *fmpz_t* bignum type uses an immediate representation for small integers, specifically when the absolute value is at most `2^{62}-1` (on 64-bit machines) or `2^{30}-1` (on 32-bit machines). The following methods completely inline the case where all operands (and possibly some intermediate values in the calculation) are known to be small. This is faster in code where all values *almost certainly will be much smaller than a full word*. In particular, these methods are used within Arb for manipulating exponents of floating-point numbers. Inlining slows down the general case, and increases code size, so these methods should not be used gratuitously. .. function:: void fmpz_add_inline(fmpz_t z, const fmpz_t x, const fmpz_t y) .. function:: void fmpz_add_si_inline(fmpz_t z, const fmpz_t x, slong y) .. function:: void fmpz_add_ui_inline(fmpz_t z, const fmpz_t x, ulong y) Sets *z* to the sum of *x* and *y*. .. function:: void fmpz_sub_si_inline(fmpz_t z, const fmpz_t x, slong y) Sets *z* to the difference of *x* and *y*. .. function:: void fmpz_add2_fmpz_si_inline(fmpz_t z, const fmpz_t x, const fmpz_t y, slong c) Sets *z* to the sum of *x*, *y*, and *c*. .. function:: mp_size_t _fmpz_size(const fmpz_t x) Returns the number of limbs required to represent *x*. .. function:: slong _fmpz_sub_small(const fmpz_t x, const fmpz_t y) Computes the difference of *x* and *y* and returns the result as an *slong*. The result is clamped between -*WORD_MAX* and *WORD_MAX*, i.e. between `\pm (2^{63}-1)` inclusive on a 64-bit machine. .. function:: void _fmpz_set_si_small(fmpz_t x, slong v) Sets *x* to the integer *v* which is required to be a value between *COEFF_MIN* and *COEFF_MAX* so that promotion to a bignum cannot occur. Low-level conversions ------------------------------------------------------------------------------- .. function:: void fmpz_set_mpn_large(fmpz_t z, mp_srcptr src, mp_size_t n, int negative) Sets *z* to the integer represented by the *n* limbs in the array *src*, or minus this value if *negative* is 1. Requires `n \ge 2` and that the top limb of *src* is nonzero. Note that *fmpz_set_ui*, *fmpz_neg_ui* can be used for single-limb integers. .. macro:: FMPZ_GET_MPN_READONLY(zsign, zn, zptr, ztmp, zv) Given an *fmpz_t* *zv*, this macro sets *zptr* to a pointer to the limbs of *zv*, *zn* to the number of limbs, and *zsign* to a sign bit (0 if nonnegative, 1 if negative). The variable *ztmp* must be a single *mp_limb_t*, which is used as a buffer. If *zv* is a small value, *zv* itself contains no limb array that *zptr* could point to, so the single limb is copied to *ztmp* and *zptr* is set to point to *ztmp*. The case where *zv* is zero is not handled specially, and *zn* is set to 1. .. function:: void fmpz_lshift_mpn(fmpz_t z, mp_srcptr src, mp_size_t n, int negative, flint_bitcnt_t shift) Sets *z* to the integer represented by the *n* limbs in the array *src*, or minus this value if *negative* is 1, shifted left by *shift* bits. Requires `n \ge 1` and that the top limb of *src* is nonzero. flint-3.1.3/doc/source/fmpz_factor.rst000066400000000000000000000331601461254215100177470ustar00rootroot00000000000000.. _fmpz-factor: **fmpz_factor.h** -- integer factorisation =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_factor_struct .. type:: fmpz_factor_t Factoring integers -------------------------------------------------------------------------------- An integer may be represented in factored form using the ``fmpz_factor_t`` data structure. This consists of two ``fmpz`` vectors representing bases and exponents, respectively. Canonically, the bases will be prime numbers sorted in ascending order and the exponents will be positive. A separate ``int`` field holds the sign, which may be `-1`, `0` or `1`. .. function:: void fmpz_factor_init(fmpz_factor_t factor) Initialises an ``fmpz_factor_t`` structure. .. function:: void fmpz_factor_clear(fmpz_factor_t factor) Clears an ``fmpz_factor_t`` structure. .. function:: void _fmpz_factor_append_ui(fmpz_factor_t factor, mp_limb_t p, ulong exp) Append a factor `p` to the given exponent to the ``fmpz_factor_t`` structure ``factor``. .. function:: void _fmpz_factor_append(fmpz_factor_t factor, const fmpz_t p, ulong exp) Append a factor `p` to the given exponent to the ``fmpz_factor_t`` structure ``factor``. .. function:: void fmpz_factor(fmpz_factor_t factor, const fmpz_t n) Factors `n` into prime numbers. If `n` is zero or negative, the sign field of the ``factor`` object will be set accordingly. .. function:: int fmpz_factor_smooth(fmpz_factor_t factor, const fmpz_t n, slong bits, int proved) Factors `n` into prime numbers up to approximately the given number of bits and possibly one additional cofactor, which may or may not be prime. If the number is definitely factored fully, the return value is `1`, otherwise the final factor (which may have exponent greater than `1`) is composite and needs to be factored further. If the number has a factor of around the given number of bits, there is at least a two-thirds chance of finding it. Smaller factors should be found with a much higher probability. The amount of time spent factoring can be controlled by lowering or increasing ``bits``. However, the quadratic sieve may be faster if ``bits`` is set to more than one third of the number of bits of `n`. The function uses trial factoring up to ``bits = 15``, followed by a primality test and a perfect power test to check if the factorisation is complete. If ``bits`` is at least 16, it proceeds to use the elliptic curve method to look for larger factors. The behavior of primality testing is determined by the ``proved`` parameter: If ``proved`` is set to `1` the function will prove all factors prime (other than the last factor, if the return value is `0`). If ``proved`` is set to `0`, the function will only check that factors are probable primes. If ``proved`` is set to `-1`, the function will not test primality after performing trial division. A perfect power test is still performed. As an exception to the rules stated above, this function will call ``n_factor`` internally if `n` or the remainder after trial division is smaller than one word, guaranteeing a complete factorisation. .. function:: void fmpz_factor_si(fmpz_factor_t factor, slong n) Like ``fmpz_factor``, but takes a machine integer `n` as input. .. function:: int fmpz_factor_trial_range(fmpz_factor_t factor, const fmpz_t n, ulong start, ulong num_primes) Factors `n` into prime factors using trial division. If `n` is zero or negative, the sign field of the ``factor`` object will be set accordingly. The algorithm starts with the given start index in the ``flint_primes`` table and uses at most ``num_primes`` primes from that point. The function returns 1 if `n` is completely factored, otherwise it returns `0`. .. function:: int fmpz_factor_trial(fmpz_factor_t factor, const fmpz_t n, slong num_primes) Factors `n` into prime factors using trial division. If `n` is zero or negative, the sign field of the ``factor`` object will be set accordingly. The algorithm uses the given number of primes, which must be in the range `[0, 3512]`. An exception is raised if a number outside this range is passed. The function returns 1 if `n` is completely factored, otherwise it returns `0`. The final entry in the factor struct is set to the cofactor after removing prime factors, if this is not `1`. .. function:: void fmpz_factor_refine(fmpz_factor_t res, const fmpz_factor_t f) Attempts to improve a partial factorization of an integer by "refining" the factorization ``f`` to a more complete factorization ``res`` whose bases are pairwise relatively prime. This function does not require its input to be in canonical form, nor does it guarantee that the resulting factorization will be canonical. .. function:: void fmpz_factor_expand_iterative(fmpz_t n, const fmpz_factor_t factor) Evaluates an integer in factored form back to an ``fmpz_t``. This currently exponentiates the bases separately and multiplies them together one by one, although much more efficient algorithms exist. .. function:: int fmpz_factor_pp1(fmpz_t factor, const fmpz_t n, ulong B1, ulong B2_sqrt, ulong c) Use Williams' `p + 1` method to factor `n`, using a prime bound in stage 1 of ``B1`` and a prime limit in stage 2 of at least the square of ``B2_sqrt``. If a factor is found, the function returns `1` and ``factor`` is set to the factor that is found. Otherwise, the function returns `0`. The value `c` should be a random value greater than `2`. Successive calls to the function with different values of `c` give additional chances to factor `n` with roughly exponentially decaying probability of finding a factor which has been missed (if `p+1` or `p-1` is not smooth for any prime factors `p` of `n` then the function will not ever succeed). .. function:: int fmpz_factor_pollard_brent_single(fmpz_t p_factor, fmpz_t n_in, fmpz_t yi, fmpz_t ai, mp_limb_t max_iters) Pollard Rho algorithm for integer factorization. Assumes that the `n` is not prime. ``factor`` is set as the factor if found. Takes as input the initial value `y`, to start polynomial evaluation, and `a`, the constant of the polynomial used. It is not assured that the factor found will be prime. Does not compute the complete factorization, just one factor. Returns the number of limbs of factor if factorization is successful (non trivial factor is found), else returns 0. ``max_iters`` is the number of iterations tried in process of finding the cycle. If the algorithm fails to find a non trivial factor in one call, it tries again (this time with a different set of random values). .. function:: int fmpz_factor_pollard_brent(fmpz_t factor, flint_rand_t state, fmpz_t n, mp_limb_t max_tries, mp_limb_t max_iters) Pollard Rho algorithm for integer factorization. Assumes that the `n` is not prime. ``factor`` is set as the factor if found. It is not assured that the factor found will be prime. Does not compute the complete factorization, just one factor. Returns the number of limbs of factor if factorization is successful (non trivial factor is found), else returns 0. ``max_iters`` is the number of iterations tried in process of finding the cycle. If the algorithm fails to find a non trivial factor in one call, it tries again (this time with a different set of random values). This process is repeated a maximum of ``max_tries`` times. The algorithm used is a modification of the original Pollard Rho algorithm, suggested by Richard Brent. It can be found in the paper available at https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf Input and output -------------------------------------------------------------------------------- .. function:: int fmpz_factor_fprint(FILE * fs, const fmpz_factor_t factor) int fmpz_factor_print(const fmpz_factor_t factor) Prints the factorization ``factor`` into ``fs`` or ``stdout``. If ``factor`` is zero, it prints ``0``. Else, it prints the factorization as ``f_{1}^e_{1} * ... * f_{n}^e_{n}``, where ``f_{i}`` and ``e_{i}`` are the `i`-th factor and exponent, where ``^e_{i}`` is omitted if `e_{i} = 1`. In particular, if ``factor`` is `1` or `-1`, it prints ``1`` or ``-1``, respectively. Returns the number of characters written to file stream. Elliptic curve (ECM) method -------------------------------------------------------------------------------- Factoring of ``fmpz`` integers using ECM .. function:: void fmpz_factor_ecm_init(ecm_t ecm_inf, mp_limb_t sz) Initializes the ``ecm_t`` struct. This is needed in some functions and carries data between subsequent calls. .. function:: void fmpz_factor_ecm_clear(ecm_t ecm_inf) Clears the ``ecm_t`` struct. .. function:: void fmpz_factor_ecm_addmod(mp_ptr a, mp_ptr b, mp_ptr c, mp_ptr n, mp_limb_t n_size) Sets `a` to `(b + c)` ``%`` `n`. This is not a normal add mod function, it assumes `n` is normalized (highest bit set) and `b` and `c` are reduced modulo `n`. Used for arithmetic operations in ``fmpz_factor_ecm``. .. function:: void fmpz_factor_ecm_submod(mp_ptr x, mp_ptr a, mp_ptr b, mp_ptr n, mp_limb_t n_size) Sets `x` to `(a - b)` ``%`` `n`. This is not a normal subtract mod function, it assumes `n` is normalized (highest bit set) and `b` and `c` are reduced modulo `n`. Used for arithmetic operations in ``fmpz_factor_ecm``. .. function:: void fmpz_factor_ecm_double(mp_ptr x, mp_ptr z, mp_ptr x0, mp_ptr z0, mp_ptr n, ecm_t ecm_inf) Sets the point `(x : z)` to two times `(x_0 : z_0)` modulo `n` according to the formula .. math:: x = (x_0 + z_0)^2 \cdot (x_0 - z_0)^2 \mod n, .. math:: z = 4 x_0 z_0 \left((x_0 - z_0)^2 + 4a_{24}x_0z_0\right) \mod n. ``ecm_inf`` is used just to use temporary ``mp_ptr``'s in the structure. This group doubling is valid only for points expressed in Montgomery projective coordinates. .. function:: void fmpz_factor_ecm_add(mp_ptr x, mp_ptr z, mp_ptr x1, mp_ptr z1, mp_ptr x2, mp_ptr z2, mp_ptr x0, mp_ptr z0, mp_ptr n, ecm_t ecm_inf) Sets the point `(x : z)` to the sum of `(x_1 : z_1)` and `(x_2 : z_2)` modulo `n`, given the difference `(x_0 : z_0)` according to the formula .. math:: x = 4z_0(x_1x_2 - z_1z_2)^2 \mod n, \\ z = 4x_0(x_2z_1 - x_1z_2)^2 \mod n. ``ecm_inf`` is used just to use temporary ``mp_ptr``'s in the structure. This group addition is valid only for points expressed in Montgomery projective coordinates. .. function:: void fmpz_factor_ecm_mul_montgomery_ladder(mp_ptr x, mp_ptr z, mp_ptr x0, mp_ptr z0, mp_limb_t k, mp_ptr n, ecm_t ecm_inf) Montgomery ladder algorithm for scalar multiplication of elliptic points. Sets the point `(x : z)` to `k(x_0 : z_0)` modulo `n`. ``ecm_inf`` is used just to use temporary ``mp_ptr``'s in the structure. Valid only for points expressed in Montgomery projective coordinates. .. function:: int fmpz_factor_ecm_select_curve(mp_ptr f, mp_ptr sigma, mp_ptr n, ecm_t ecm_inf) Selects a random elliptic curve given a random integer ``sigma``, according to Suyama's parameterization. If the factor is found while selecting the curve, the number of limbs required to store the factor is returned, otherwise `0`. It could be possible that the selected curve is unsuitable for further computations, in such a case, `-1` is returned. Also selects the initial point `x_0`, and the value of `(a + 2)/4`, where `a` is a curve parameter. Sets `z_0` as `1`. All these are stored in the ``ecm_t`` struct. The curve selected is of Montgomery form, the points selected satisfy the curve and are projective coordinates. .. function:: int fmpz_factor_ecm_stage_I(mp_ptr f, const mp_limb_t * prime_array, mp_limb_t num, mp_limb_t B1, mp_ptr n, ecm_t ecm_inf) Stage I implementation of the ECM algorithm. ``f`` is set as the factor if found. ``num`` is number of prime numbers `\le` the bound ``B1``. ``prime_array`` is an array of first ``B1`` primes. `n` is the number being factored. If the factor is found, number of words required to store the factor is returned, otherwise `0`. .. function:: int fmpz_factor_ecm_stage_II(mp_ptr f, mp_limb_t B1, mp_limb_t B2, mp_limb_t P, mp_ptr n, ecm_t ecm_inf) Stage II implementation of the ECM algorithm. ``f`` is set as the factor if found. ``B1``, ``B2`` are the two bounds. ``P`` is the primorial (approximately equal to `\sqrt{B2}`). `n` is the number being factored. If the factor is found, number of words required to store the factor is returned, otherwise `0`. .. function:: int fmpz_factor_ecm(fmpz_t f, mp_limb_t curves, mp_limb_t B1, mp_limb_t B2, flint_rand_t state, const fmpz_t n_in) Outer wrapper function for the ECM algorithm. In case ``f`` can fit in a single unsigned word, a call to ``n_factor_ecm`` is made. The function calls stage I and II, and the precomputations (builds ``prime_array`` for stage I, ``GCD_table`` and ``prime_table`` for stage II). ``f`` is set as the factor if found. ``curves`` is the number of random curves being tried. ``B1``, ``B2`` are the two bounds or stage I and stage II. `n` is the number being factored. If a factor is found in stage I, `1` is returned. If a factor is found in stage II, `2` is returned. If a factor is found while selecting the curve, `-1` is returned. Otherwise `0` is returned. flint-3.1.3/doc/source/fmpz_lll.rst000066400000000000000000000437361461254215100172660ustar00rootroot00000000000000.. _fmpz-lll: **fmpz_lll.h** -- LLL reduction ================================================================================================== Parameter manipulation -------------------------------------------------------------------------------- These functions are used to initialise LLL context objects which are of the type ``fmpz_lll_t``. These objects contain all information about the options governing the reduction using this module's functions including the LLL parameters \delta and \eta, the representation type of the input matrix (whether it is a lattice basis or a Gram matrix), and the type of Gram matrix to be used during L^2 (approximate or exact). .. function:: void fmpz_lll_context_init_default(fmpz_lll_t fl) Sets ``fl->delta``, ``fl->eta``, ``fl->rt`` and ``fl->gt`` to their default values, 0.99, 0.51, `Z\_BASIS` and `APPROX` respectively. .. function:: void fmpz_lll_context_init(fmpz_lll_t fl, double delta, double eta, rep_type rt, gram_type gt) Sets ``fl->delta``, ``fl->eta``, ``fl->rt`` and ``fl->gt`` to ``delta``, ``eta``, ``rt`` and ``gt`` (given as input) respectively. ``delta`` and ``eta`` are the L^2 parameters. ``delta`` and ``eta`` must lie in the intervals `(0.25, 1)` and `(0.5, \sqrt{\mathtt{delta}})` respectively. The representation type is input using ``rt`` and can have the values `Z\_BASIS` for a lattice basis and `GRAM` for a Gram matrix. The Gram type to be used during computation can be specified using ``gt`` which can assume the values `APPROX` and `EXACT`. Note that ``gt`` has meaning only when ``rt`` is `Z\_BASIS`. Random parameter generation -------------------------------------------------------------------------------- .. function:: void fmpz_lll_randtest(fmpz_lll_t fl, flint_rand_t state) Sets ``fl->delta`` and ``fl->eta`` to random values in the interval `(0.25, 1)` and `(0.5, \sqrt{\mathtt{delta}})` respectively. ``fl->rt`` is set to `GRAM` or `Z\_BASIS` and ``fl->gt`` is set to `APPROX` or `EXACT` in a pseudo random way. Heuristic dot product -------------------------------------------------------------------------------- .. function:: double fmpz_lll_heuristic_dot(const double * vec1, const double * vec2, slong len2, const fmpz_mat_t B, slong k, slong j, slong exp_adj) Computes the dot product of two vectors of doubles ``vec1`` and ``vec2``, which are respectively ``double`` approximations (up to scaling by a power of 2) to rows ``k`` and ``j`` in the exact integer matrix ``B``. If massive cancellation is detected an exact computation is made. The exact computation is scaled by `2^{-\mathtt{exp_adj}}`, where ``exp_adj = r2 + r1`` where `r2` is the exponent for row ``j`` and `r1` is the exponent for row ``k`` (i.e. row ``j`` is notionally thought of as being multiplied by `2^{r2}`, etc.). The final dot product computed by this function is then notionally the return value times `2^{\mathtt{exp_adj}}`. The various Babai's -------------------------------------------------------------------------------- .. function:: int fmpz_lll_check_babai(int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double * s, d_mat_t appB, int * expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) Performs floating point size reductions of the ``kappa``-th row of ``B`` by all of the previous rows, uses d_mats ``mu`` and ``r`` for storing the GSO data. ``U`` is used to capture the unimodular transformations if it is not `NULL`. The ``double`` array ``s`` will contain the size of the ``kappa``-th row if it were moved into position `i`. The d_mat ``appB`` is an approximation of ``B`` with each row receiving an exponent stored in ``expo`` which gets populated only when needed. The d_mat ``A->appSP`` is an approximation of the Gram matrix whose entries are scalar products of the rows of ``B`` and is used when ``fl->gt`` == `APPROX`. When ``fl->gt`` == `EXACT` the fmpz_mat ``A->exactSP`` (the exact Gram matrix) is used. The index ``a`` is the smallest row index which will be reduced from the ``kappa``-th row. Index ``zeros`` is the number of zero rows in the matrix. ``kappamax`` is the highest index which has been size-reduced so far, and ``n`` is the number of columns you want to consider. ``fl`` is an LLL (L^2) context object. The output is the value -1 if the process fails (usually due to insufficient precision) or 0 if everything was successful. These descriptions will be true for the future Babai procedures as well. .. function:: int fmpz_lll_check_babai_heuristic_d(int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double * s, d_mat_t appB, int * expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) Same as :func:`fmpz_lll_check_babai` but using the heuristic inner product rather than a purely floating point inner product. The heuristic will compute at full precision when there is cancellation. .. function:: int fmpz_lll_check_babai_heuristic(int kappa, fmpz_mat_t B, fmpz_mat_t U, mpf_mat_t mu, mpf_mat_t r, mpf * s, mpf_mat_t appB, fmpz_gram_t A, int a, int zeros, int kappamax, int n, mpf_t tmp, mpf_t rtmp, flint_bitcnt_t prec, const fmpz_lll_t fl) This function is like the ``mpf`` version of :func:`fmpz_lll_check_babai_heuristic_d`. However, it also inherits some temporary ``mpf_t`` variables ``tmp`` and ``rtmp``. .. function:: int fmpz_lll_advance_check_babai(int cur_kappa, int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double * s, d_mat_t appB, int * expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) This is a Babai procedure which is used when size reducing a vector beyond an index which LLL has reached. ``cur_kappa`` is the index behind which we can assume ``B`` is LLL reduced, while ``kappa`` is the vector to be reduced. This procedure only size reduces the ``kappa``-th row by vectors up to ``cur_kappa``, **not** ``kappa - 1``. .. function:: int fmpz_lll_advance_check_babai_heuristic_d(int cur_kappa, int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double * s, d_mat_t appB, int * expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) Same as :func:`fmpz_lll_advance_check_babai` but using the heuristic inner product rather than a purely floating point inner product. The heuristic will compute at full precision when there is cancellation. Shift -------------------------------------------------------------------------------- .. function:: int fmpz_lll_shift(const fmpz_mat_t B) Computes the largest number of non-zero entries after the diagonal in ``B``. Varieties of LLL -------------------------------------------------------------------------------- These programs implement ideas from the book chapter [Stehle2010]_. The list of function here that are heuristic in nature and may return with `B` unreduced - that is to say, not do their job - includes (but is not necessarily limited to): * :func:`fmpz_lll_d` * :func:`fmpz_lll_d_heuristic` * :func:`fmpz_lll_d_heuristic_with_removal` * :func:`fmpz_lll_d_with_removal` * :func:`fmpz_lll_d_with_removal_knapsack` .. function:: int fmpz_lll_d(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) This is a mildly greedy version of floating point LLL using doubles only. It tries the fast version of the Babai algorithm (:func:`fmpz_lll_check_babai`). If that fails, then it switches to the heuristic version (:func:`fmpz_lll_check_babai_heuristic_d`) for only one loop and switches right back to the fast version. It reduces ``B`` in place. ``U`` is the matrix used to capture the unimodular transformations if it is not `NULL`. An exception is raised if `U` != `NULL` and ``U->r`` != `d`, where `d` is the lattice dimension. ``fl`` is the context object containing information containing the LLL parameters \delta and \eta. The function can perform reduction on both the lattice basis as well as its Gram matrix. The type of lattice representation can be specified via the parameter ``fl->rt``. The type of Gram matrix to be used in computation (approximate or exact) can also be specified through the variable ``fl->gt`` (applies only if ``fl->rt`` == `Z\_BASIS`). .. function:: int fmpz_lll_d_heuristic(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) This LLL reduces ``B`` in place using doubles only. It is similar to :func:`fmpz_lll_d` but only uses the heuristic inner products which attempt to detect cancellations. .. function:: int fmpz_lll_mpf2(fmpz_mat_t B, fmpz_mat_t U, flint_bitcnt_t prec, const fmpz_lll_t fl) This is LLL using ``mpf`` with the given precision, ``prec`` for the underlying GSO. It reduces ``B`` in place like the other LLL functions. The `mpf2` in the function name refers to the way the ``mpf_t``'s are initialised. .. function:: int fmpz_lll_mpf(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) A wrapper of :func:`fmpz_lll_mpf2`. This currently begins with `prec == D\_BITS`, then for the first 20 loops, increases the precision one limb at a time. After 20 loops, it doubles the precision each time. There is a proof that this will eventually work. The return value of this function is 0 if the LLL is successful or -1 if the precision maxes out before ``B`` is LLL-reduced. .. function:: int fmpz_lll_wrapper(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) A wrapper of the above procedures. It begins with the greediest version (:func:`fmpz_lll_d`), then adapts to the version using heuristic inner products only (:func:`fmpz_lll_d_heuristic`) if ``fl->rt`` == `Z\_BASIS` and ``fl->gt`` == `APPROX`, and finally to the mpf version (:func:`fmpz_lll_mpf`) if needed. ``U`` is the matrix used to capture the unimodular transformations if it is not `NULL`. An exception is raised if `U` != `NULL` and ``U->r`` != `d`, where `d` is the lattice dimension. ``fl`` is the context object containing information containing the LLL parameters \delta and \eta. The function can perform reduction on both the lattice basis as well as its Gram matrix. The type of lattice representation can be specified via the parameter ``fl->rt``. The type of Gram matrix to be used in computation (approximate or exact) can also be specified through the variable ``fl->gt`` (applies only if ``fl->rt`` == `Z\_BASIS`). .. function:: int fmpz_lll_d_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) Same as :func:`fmpz_lll_d` but with a removal bound, ``gs_B``. The return value is the new dimension of ``B`` if removals are desired. .. function:: int fmpz_lll_d_heuristic_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) Same as :func:`fmpz_lll_d_heuristic` but with a removal bound, ``gs_B``. The return value is the new dimension of ``B`` if removals are desired. .. function:: int fmpz_lll_mpf2_with_removal(fmpz_mat_t B, fmpz_mat_t U, flint_bitcnt_t prec, const fmpz_t gs_B, const fmpz_lll_t fl) Same as :func:`fmpz_lll_mpf2` but with a removal bound, ``gs_B``. The return value is the new dimension of ``B`` if removals are desired. .. function:: int fmpz_lll_mpf_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) A wrapper of :func:`fmpz_lll_mpf2_with_removal`. This currently begins with `prec == D\_BITS`, then for the first 20 loops, increases the precision one limb at a time. After 20 loops, it doubles the precision each time. There is a proof that this will eventually work. The return value of this function is the new dimension of ``B`` if removals are desired or -1 if the precision maxes out before ``B`` is LLL-reduced. .. function:: int fmpz_lll_wrapper_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) A wrapper of the procedures implementing the base case LLL with the addition of the removal boundary. It begins with the greediest version (:func:`fmpz_lll_d_with_removal`), then adapts to the version using heuristic inner products only (:func:`fmpz_lll_d_heuristic_with_removal`) if ``fl->rt`` == `Z\_BASIS` and ``fl->gt`` == `APPROX`, and finally to the mpf version (:func:`fmpz_lll_mpf_with_removal`) if needed. .. function:: int fmpz_lll_d_with_removal_knapsack(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) This is floating point LLL specialized to knapsack-type lattices. It performs early size reductions occasionally which makes things faster in the knapsack case. Otherwise, it is similar to ``fmpz_lll_d_with_removal``. .. function:: int fmpz_lll_wrapper_with_removal_knapsack(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) A wrapper of the procedures implementing the LLL specialized to knapsack-type lattices. It begins with the greediest version and the engine of this version, (:func:`fmpz_lll_d_with_removal_knapsack`), then adapts to the version using heuristic inner products only (:func:`fmpz_lll_d_heuristic_with_removal`) if ``fl->rt`` == `Z\_BASIS` and ``fl->gt`` == `APPROX`, and finally to the mpf version (:func:`fmpz_lll_mpf_with_removal`) if needed. ULLL -------------------------------------------------------------------------------- .. function:: int fmpz_lll_with_removal_ulll(fmpz_mat_t FM, fmpz_mat_t UM, slong new_size, const fmpz_t gs_B, const fmpz_lll_t fl) ULLL is a new style of LLL which adjoins an identity matrix to the input lattice ``FM``, then scales the lattice down to ``new_size`` bits and reduces this augmented lattice. This tends to be more stable numerically than traditional LLL which means higher dimensions can be attacked using doubles. In each iteration a new identity matrix is adjoined to the truncated lattice. ``UM`` is used to capture the unimodular transformations, while ``gs_B`` and ``fl`` have the same role as in the previous routines. The function is optimised for factoring polynomials. LLL-reducedness -------------------------------------------------------------------------------- These programs implement ideas from the paper [Villard2007]_. See https://arxiv.org/abs/cs/0701183 for the algorithm of Villard. .. function:: int fmpz_lll_is_reduced_d(const fmpz_mat_t B, const fmpz_lll_t fl) int fmpz_lll_is_reduced_mpfr(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) int fmpz_lll_is_reduced_d_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd) int fmpz_lll_is_reduced_mpfr_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd, flint_bitcnt_t prec) A non-zero return indicates the matrix is definitely reduced, that is, that * :func:`fmpz_mat_is_reduced` or :func:`fmpz_mat_is_reduced_gram` (for the first two) * :func:`fmpz_mat_is_reduced_with_removal` or :func:`fmpz_mat_is_reduced_gram_with_removal` (for the last two) return non-zero. A zero return value is inconclusive. The `_d` variants are performed in machine precision, while the `_mpfr` uses a precision of `prec` bits. .. function:: int fmpz_lll_is_reduced(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) int fmpz_lll_is_reduced_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd, flint_bitcnt_t prec) The return from these functions is always conclusive: the functions * :func:`fmpz_mat_is_reduced` or :func:`fmpz_mat_is_reduced_gram` * :func:`fmpz_mat_is_reduced_with_removal` or :func:`fmpz_mat_is_reduced_gram_with_removal` are optimzied by calling the above heuristics first and returning right away if they give a conclusive answer. Modified ULLL -------------------------------------------------------------------------------- .. function:: void fmpz_lll_storjohann_ulll(fmpz_mat_t FM, slong new_size, const fmpz_lll_t fl) Performs ULLL using :func:`fmpz_mat_lll_storjohann` as the LLL function. .. note:: This function is currently not tested. Use at your own risk. Main LLL functions -------------------------------------------------------------------------------- .. function:: void fmpz_lll(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) Reduces ``B`` in place according to the parameters specified by the LLL context object ``fl``. This is the main LLL function which should be called by the user. It currently calls the ULLL algorithm (without removals). The ULLL function in turn calls a LLL wrapper which tries to choose an optimal LLL algorithm, starting with a version using just doubles (ULLL tries to maximise usage of this), then a heuristic LLL followed by a full precision floating point LLL if required. ``U`` is the matrix used to capture the unimodular transformations if it is not `NULL`. An exception is raised if `U` != `NULL` and ``U->r`` != `d`, where `d` is the lattice dimension. ``fl`` is the context object containing information containing the LLL parameters \delta and \eta. The function can perform reduction on both the lattice basis as well as its Gram matrix. The type of lattice representation can be specified via the parameter ``fl->rt``. The type of Gram matrix to be used in computation (approximate or exact) can also be specified through the variable ``fl->gt`` (applies only if ``fl->rt`` == `Z\_BASIS`). .. function:: int fmpz_lll_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) Reduces ``B`` in place according to the parameters specified by the LLL context object ``fl`` and removes vectors whose squared Gram-Schmidt length is greater than the bound ``gs_B``. The return value is the new dimension of ``B`` to be considered for further computation. This is the main LLL with removals function which should be called by the user. Like ``fmpz_lll`` it calls ULLL, but it also sets the Gram-Schmidt bound to that supplied and does removals. flint-3.1.3/doc/source/fmpz_mat.rst000066400000000000000000001706611461254215100172620ustar00rootroot00000000000000.. _fmpz-mat: **fmpz_mat.h** -- matrices over the integers =============================================================================== The :type:`fmpz_mat_t` data type represents dense matrices of multiprecision integers, implemented using :type:`fmpz` vectors. No automatic resizing is performed: in general, the user must provide matrices of correct dimensions for both input and output variables. Output variables are *not* allowed to be aliased with input variables unless otherwise noted. Matrices are indexed from zero: an `m \times n` matrix has rows of index `0,1,\ldots,m-1` and columns of index `0,1,\ldots,n-1`. One or both of `m` and `n` may be zero. Elements of a matrix can be read or written using the ``fmpz_mat_entry`` macro, which returns a reference to the entry at a given row and column index. This reference can be passed as an input or output :type:`fmpz_t` variable to any function in the ``fmpz`` module for direct manipulation. Simple example -------------- The following example creates the `2 \times 2` matrix `A` with value `2i+j` at row `i` and column `j`, computes `B = A^2`, and prints both matrices. .. code:: c #include "fmpz.h" #include "fmpz_mat.h" int main() { long i, j; fmpz_mat_t A; fmpz_mat_t B; fmpz_mat_init(A, 2, 2); fmpz_mat_init(B, 2, 2); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) fmpz_set_ui(fmpz_mat_entry(A, i, j), 2*i+j); fmpz_mat_mul(B, A, A); flint_printf("A = \n"); fmpz_mat_print_pretty(A); flint_printf("A^2 = \n"); fmpz_mat_print_pretty(B); fmpz_mat_clear(A); fmpz_mat_clear(B); } The output is: :: A = [[0 1] [2 3]] A^2 = [[2 3] [6 11]] Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mat_struct .. type:: fmpz_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_mat_init(fmpz_mat_t mat, slong rows, slong cols) Initialises a matrix with the given number of rows and columns for use. .. function:: void fmpz_mat_clear(fmpz_mat_t mat) Clears the given matrix. Basic assignment and manipulation -------------------------------------------------------------------------------- .. function:: void fmpz_mat_set(fmpz_mat_t mat1, const fmpz_mat_t mat2) Sets ``mat1`` to a copy of ``mat2``. The dimensions of ``mat1`` and ``mat2`` must be the same. .. function:: void fmpz_mat_init_set(fmpz_mat_t mat, const fmpz_mat_t src) Initialises the matrix ``mat`` to the same size as ``src`` and sets it to a copy of ``src``. .. function:: slong fmpz_mat_nrows(const fmpz_mat_t mat) slong fmpz_mat_ncols(const fmpz_mat_t mat) Returns respectively the number of rows and columns of the matrix. .. function:: void fmpz_mat_swap(fmpz_mat_t mat1, fmpz_mat_t mat2) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. function:: void fmpz_mat_swap_entrywise(fmpz_mat_t mat1, fmpz_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: fmpz * fmpz_mat_entry(const fmpz_mat_t mat, slong i, slong j) Returns a reference to the entry of ``mat`` at row `i` and column `j`. This reference can be passed as an input or output variable to any function in the ``fmpz`` module for direct manipulation. Both `i` and `j` must not exceed the dimensions of the matrix. This function is implemented as a macro. .. function:: void fmpz_mat_zero(fmpz_mat_t mat) Sets all entries of ``mat`` to 0. .. function:: void fmpz_mat_one(fmpz_mat_t mat) Sets ``mat`` to the unit matrix, having ones on the main diagonal and zeroes elsewhere. If ``mat`` is nonsquare, it is set to the truncation of a unit matrix. .. function:: void fmpz_mat_swap_rows(fmpz_mat_t mat, slong * perm, slong r, slong s) Swaps rows ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fmpz_mat_swap_cols(fmpz_mat_t mat, slong * perm, slong r, slong s) Swaps columns ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: void fmpz_mat_invert_rows(fmpz_mat_t mat, slong * perm) Swaps rows ``i`` and ``r - i`` of ``mat`` for ``0 <= i < r/2``, where ``r`` is the number of rows of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fmpz_mat_invert_cols(fmpz_mat_t mat, slong * perm) Swaps columns ``i`` and ``c - i`` of ``mat`` for ``0 <= i < c/2``, where ``c`` is the number of columns of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. Window -------------------------------------------------------------------------------- .. function:: void fmpz_mat_window_init(fmpz_mat_t window, const fmpz_mat_t mat, slong r1, slong c1, slong r2, slong c2) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0,0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void fmpz_mat_window_clear(fmpz_mat_t window) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. Random matrix generation -------------------------------------------------------------------------------- .. function:: void fmpz_mat_randbits(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) Sets the entries of ``mat`` to random signed integers whose absolute values have the given number of binary bits. .. function:: void fmpz_mat_randtest(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) Sets the entries of ``mat`` to random signed integers whose absolute values have a random number of bits up to the given number of bits inclusive. .. function:: void fmpz_mat_randintrel(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) Sets ``mat`` to be a random *integer relations* matrix, with signed entries up to the given number of bits. The number of columns of ``mat`` must be equal to one more than the number of rows. The format of the matrix is a set of random integers in the left hand column and an identity matrix in the remaining square submatrix. .. function:: void fmpz_mat_randsimdioph(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, flint_bitcnt_t bits2) Sets ``mat`` to a random *simultaneous diophantine* matrix. The matrix must be square. The top left entry is set to ``2^bits2``. The remainder of that row is then set to signed random integers of the given number of binary bits. The remainder of the first column is zero. Running down the rest of the diagonal are the values ``2^bits`` with all remaining entries zero. .. function:: void fmpz_mat_randntrulike(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q) Sets a square matrix ``mat`` of even dimension to a random *NTRU like* matrix. The matrix is broken into four square submatrices. The top left submatrix is set to the identity. The bottom left submatrix is set to the zero matrix. The bottom right submatrix is set to `q` times the identity matrix. Finally the top right submatrix has the following format. A random vector `h` of length `r/2` is created, with random signed entries of the given number of bits. Then entry `(i, j)` of the submatrix is set to `h[i + j \bmod{r/2}]`. .. function:: void fmpz_mat_randntrulike2(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q) Sets a square matrix ``mat`` of even dimension to a random *NTRU like* matrix. The matrix is broken into four square submatrices. The top left submatrix is set to `q` times the identity matrix. The top right submatrix is set to the zero matrix. The bottom right submatrix is set to the identity matrix. Finally the bottom left submatrix has the following format. A random vector `h` of length `r/2` is created, with random signed entries of the given number of bits. Then entry `(i, j)` of the submatrix is set to `h[i + j \bmod{r/2}]`. .. function:: void fmpz_mat_randajtai(fmpz_mat_t mat, flint_rand_t state, double alpha) Sets a square matrix ``mat`` to a random *ajtai* matrix. The diagonal entries `(i, i)` are set to a random entry in the range `[1, 2^{b-1}]` inclusive where `b = \lfloor(2 r - i)^\alpha\rfloor` for some double parameter `\alpha`. The entries below the diagonal in column `i` are set to a random entry in the range `(-2^b + 1, 2^b - 1)` whilst the entries to the right of the diagonal in row `i` are set to zero. .. function:: int fmpz_mat_randpermdiag(fmpz_mat_t mat, flint_rand_t state, const fmpz * diag, slong n) Sets ``mat`` to a random permutation of the rows and columns of a given diagonal matrix. The diagonal matrix is specified in the form of an array of the `n` initial entries on the main diagonal. The return value is `0` or `1` depending on whether the permutation is even or odd. .. function:: void fmpz_mat_randrank(fmpz_mat_t mat, flint_rand_t state, slong rank, flint_bitcnt_t bits) Sets ``mat`` to a random sparse matrix with the given rank, having exactly as many non-zero elements as the rank, with the nonzero elements being random integers of the given bit size. The matrix can be transformed into a dense matrix with unchanged rank by subsequently calling :func:`fmpz_mat_randops`. .. function:: void fmpz_mat_randdet(fmpz_mat_t mat, flint_rand_t state, const fmpz_t det) Sets ``mat`` to a random sparse matrix with minimal number of nonzero entries such that its determinant has the given value. Note that the matrix will be zero if ``det`` is zero. In order to generate a non-zero singular matrix, the function :func:`fmpz_mat_randrank` can be used. The matrix can be transformed into a dense matrix with unchanged determinant by subsequently calling :func:`fmpz_mat_randops`. .. function:: void fmpz_mat_randops(fmpz_mat_t mat, flint_rand_t state, slong count) Randomises ``mat`` by performing elementary row or column operations. More precisely, at most ``count`` random additions or subtractions of distinct rows and columns will be performed. This leaves the rank (and for square matrices, the determinant) unchanged. Input and output -------------------------------------------------------------------------------- .. function:: int fmpz_mat_fprint(FILE * file, const fmpz_mat_t mat) Prints the given matrix to the stream ``file``. The format is the number of rows, a space, the number of columns, two spaces, then a space separated list of coefficients, one row after the other. In case of success, returns a positive value; otherwise, returns a non-positive value. .. function:: int fmpz_mat_fprint_pretty(FILE * file, const fmpz_mat_t mat) Prints the given matrix to the stream ``file``. The format is an opening square bracket, then on each line a row of the matrix, followed by a closing square bracket. Each row is written as an opening square bracket followed by a space separated list of coefficients followed by a closing square bracket. In case of success, returns a positive value; otherwise, returns a non-positive value. .. function:: int fmpz_mat_print(const fmpz_mat_t mat) Prints the given matrix to the stream ``stdout``. For further details, see :func:`fmpz_mat_fprint`. .. function:: int fmpz_mat_print_pretty(const fmpz_mat_t mat) Prints the given matrix to ``stdout``. For further details, see :func:`fmpz_mat_fprint_pretty`. .. function:: int fmpz_mat_fread(FILE * file, fmpz_mat_t mat) Reads a matrix from the stream ``file``, storing the result in ``mat``. The expected format is the number of rows, a space, the number of columns, two spaces, then a space separated list of coefficients, one row after the other. In case of success, returns a positive number. In case of failure, returns a non-positive value. .. function:: int fmpz_mat_read(fmpz_mat_t mat) Reads a matrix from ``stdin``, storing the result in ``mat``. In case of success, returns a positive number. In case of failure, returns a non-positive value. Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_mat_equal(const fmpz_mat_t mat1, const fmpz_mat_t mat2) Returns a non-zero value if ``mat1`` and ``mat2`` have the same dimensions and entries, and zero otherwise. .. function:: int fmpz_mat_is_zero(const fmpz_mat_t mat) Returns a non-zero value if all entries ``mat`` are zero, and otherwise returns zero. .. function:: int fmpz_mat_is_one(const fmpz_mat_t mat) Returns a non-zero value if ``mat`` is the unit matrix or the truncation of a unit matrix, and otherwise returns zero. .. function:: int fmpz_mat_is_empty(const fmpz_mat_t mat) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int fmpz_mat_is_square(const fmpz_mat_t mat) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. .. function:: int fmpz_mat_is_zero_row(const fmpz_mat_t mat, slong i) Returns a non-zero value if row `i` of ``mat`` is zero. .. function:: int fmpz_mat_equal_col(fmpz_mat_t M, slong m, slong n) Returns `1` if columns `m` and `n` of the matrix `M` are equal, otherwise returns `0`. .. function:: int fmpz_mat_equal_row(fmpz_mat_t M, slong m, slong n) Returns `1` if rows `m` and `n` of the matrix `M` are equal, otherwise returns `0`. Transpose -------------------------------------------------------------------------------- .. function:: void fmpz_mat_transpose(fmpz_mat_t B, const fmpz_mat_t A) Sets `B` to `A^T`, the transpose of `A`. Dimensions must be compatible. `A` and `B` are allowed to be the same object if `A` is a square matrix. Concatenate -------------------------------------------------------------------------------- .. function:: void fmpz_mat_concat_vertical(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2) Sets ``res`` to vertical concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions: ``mat1``: `m \times n`, ``mat2``: `k \times n`, ``res``: `(m + k) \times n`. .. function:: void fmpz_mat_concat_horizontal(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions: ``mat1``: `m \times n`, ``mat2``: `m \times k`, ``res``: `m \times (n + k)`. Modular reduction and reconstruction -------------------------------------------------------------------------------- .. function:: void fmpz_mat_get_nmod_mat(nmod_mat_t Amod, const fmpz_mat_t A) Sets the entries of ``Amod`` to the entries of ``A`` reduced by the modulus of ``Amod``. .. function:: void fmpz_mat_set_nmod_mat(fmpz_mat_t A, const nmod_mat_t Amod) Sets the entries of ``Amod`` to the residues in ``Amod``, normalised to the interval `-m/2 <= r < m/2` where `m` is the modulus. .. function:: void fmpz_mat_set_nmod_mat_unsigned(fmpz_mat_t A, const nmod_mat_t Amod) Sets the entries of ``Amod`` to the residues in ``Amod``, normalised to the interval `0 <= r < m` where `m` is the modulus. .. function:: void fmpz_mat_CRT_ui(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_t m1, const nmod_mat_t mat2, int sign) Given ``mat1`` with entries modulo ``m`` and ``mat2`` with modulus `n`, sets ``res`` to the CRT reconstruction modulo `mn` with entries satisfying `-mn/2 <= c < mn/2` (if sign = 1) or `0 <= c < mn` (if sign = 0). .. function:: void fmpz_mat_multi_mod_ui_precomp(nmod_mat_t * residues, slong nres, const fmpz_mat_t mat, const fmpz_comb_t comb, fmpz_comb_temp_t temp) Sets each of the ``nres`` matrices in ``residues`` to ``mat`` reduced modulo the modulus of the respective matrix, given precomputed ``comb`` and ``comb_temp`` structures. Note: ``fmpz.h`` must be included **before** ``fmpz_mat.h`` in order for this function to be declared. .. function:: void fmpz_mat_multi_mod_ui(nmod_mat_t * residues, slong nres, const fmpz_mat_t mat) Sets each of the ``nres`` matrices in ``residues`` to ``mat`` reduced modulo the modulus of the respective matrix. This function is provided for convenience purposes. For reducing or reconstructing multiple integer matrices over the same set of moduli, it is faster to use ``fmpz_mat_multi_mod_precomp``. .. function:: void fmpz_mat_multi_CRT_ui_precomp(fmpz_mat_t mat, nmod_mat_t * const residues, slong nres, const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign) Reconstructs ``mat`` from its images modulo the ``nres`` matrices in ``residues``, given precomputed ``comb`` and ``comb_temp`` structures. Note: ``fmpz.h`` must be included **before** ``fmpz_mat.h`` in order for this function to be declared. .. function:: void fmpz_mat_multi_CRT_ui(fmpz_mat_t mat, nmod_mat_t * const residues, slong nres, int sign) Reconstructs ``mat`` from its images modulo the ``nres`` matrices in ``residues``. This function is provided for convenience purposes. For reducing or reconstructing multiple integer matrices over the same set of moduli, it is faster to use :func:`fmpz_mat_multi_CRT_ui_precomp`. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void fmpz_mat_add(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets ``C`` to the elementwise sum `A + B`. All inputs must be of the same size. Aliasing is allowed. .. function:: void fmpz_mat_sub(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets ``C`` to the elementwise difference `A - B`. All inputs must be of the same size. Aliasing is allowed. .. function:: void fmpz_mat_neg(fmpz_mat_t B, const fmpz_mat_t A) Sets ``B`` to the elementwise negation of ``A``. Both inputs must be of the same size. Aliasing is allowed. Matrix-scalar arithmetic -------------------------------------------------------------------------------- .. function:: void fmpz_mat_scalar_mul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) void fmpz_mat_scalar_mul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) void fmpz_mat_scalar_mul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) Set ``B = A*c`` where ``A`` is an ``fmpz_mat_t`` and ``c`` is a scalar respectively of type ``slong``, ``ulong``, or ``fmpz_t``. The dimensions of ``A`` and ``B`` must be compatible. .. function:: void fmpz_mat_scalar_addmul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) void fmpz_mat_scalar_addmul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) void fmpz_mat_scalar_addmul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) Set ``B = B + A*c`` where ``A`` is an ``fmpz_mat_t`` and ``c`` is a scalar respectively of type ``slong``, ``ulong``, or ``fmpz_t``. The dimensions of ``A`` and ``B`` must be compatible. .. function:: void fmpz_mat_scalar_submul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) void fmpz_mat_scalar_submul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) void fmpz_mat_scalar_submul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) Set ``B = B - A*c`` where ``A`` is an ``fmpz_mat_t`` and ``c`` is a scalar respectively of type ``slong``, ``ulong``, or ``fmpz_t``. The dimensions of ``A`` and ``B`` must be compatible. .. function:: void fmpz_mat_scalar_addmul_nmod_mat_ui(fmpz_mat_t B, const nmod_mat_t A, ulong c) void fmpz_mat_scalar_addmul_nmod_mat_fmpz(fmpz_mat_t B, const nmod_mat_t A, const fmpz_t c) Set ``B = B + A*c`` where ``A`` is an ``nmod_mat_t`` and ``c`` is a scalar respectively of type ``ulong`` or ``fmpz_t``. The dimensions of ``A`` and ``B`` must be compatible. .. function:: void fmpz_mat_scalar_divexact_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) void fmpz_mat_scalar_divexact_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) void fmpz_mat_scalar_divexact_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) Set ``A = B / c``, where ``B`` is an ``fmpz_mat_t`` and ``c`` is a scalar respectively of type ``slong``, ``ulong``, or ``fmpz_t``, which is assumed to divide all elements of ``B`` exactly. .. function:: void fmpz_mat_scalar_mul_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp) Set the matrix ``B`` to the matrix ``A``, of the same dimensions, multiplied by `2^{exp}`. .. function:: void fmpz_mat_scalar_tdiv_q_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp) Set the matrix ``B`` to the matrix ``A``, of the same dimensions, divided by `2^{exp}`, rounding down towards zero. .. function:: void fmpz_mat_scalar_smod(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t P) Set the matrix ``B`` to the matrix ``A``, of the same dimensions, with each entry reduced modulo `P` in the symmetric moduli system. We require `P > 0`. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void fmpz_mat_mul(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets ``C`` to the matrix product `C = A B`. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. This function automatically switches between classical and multimodular multiplication, based on a heuristic comparison of the dimensions and entry sizes. .. function:: void fmpz_mat_mul_classical(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets ``C`` to the matrix product `C = A B` computed using classical matrix algorithm. The matrices must have compatible dimensions for matrix multiplication. No aliasing is allowed. .. function:: void fmpz_mat_mul_waksman(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets ``C`` to the matrix product `C = A B` computed using Waksman multiplication, which does only `n^3/2 + O(n^2)` products, but many additions. This is good for small matrices with large entries. The matrices must have compatible dimensions for matrix multiplication. No aliasing is allowed. .. function:: void fmpz_mat_mul_strassen(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses Strassen multiplication (the Strassen-Winograd variant). .. function:: void _fmpz_mat_mul_multi_mod(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, int sign, flint_bitcnt_t bits) void fmpz_mat_mul_multi_mod(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets ``C`` to the matrix product `C = AB` computed using a multimodular algorithm. `C` is computed modulo several small prime numbers and reconstructed using the Chinese Remainder Theorem. This generally becomes more efficient than classical multiplication for large matrices. The absolute value of the elements of `C` should be `< 2^{\text{bits}}`, and ``sign`` should be `0` if the entries of `C` are known to be nonnegative and `1` otherwise. The function :func:`fmpz_mat_mul_multi_mod` calculates a rigorous bound automatically. If the default bound is too pessimistic, :func:`_fmpz_mat_mul_multi_mod` can be used with a custom bound. The matrices must have compatible dimensions for matrix multiplication. No aliasing is allowed. .. function:: int fmpz_mat_mul_blas(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Tries to set `C = AB` using BLAS and returns `1` for success and `0` for failure. Dimensions must be compatible for matrix multiplication. No aliasing is allowed. This function currently will fail if the matrices are empty, their dimensions are too large, or their max bits size is over one million bits. .. function:: void fmpz_mat_mul_fft(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Aliasing is allowed. .. function:: void fmpz_mat_sqr(fmpz_mat_t B, const fmpz_mat_t A) Sets ``B`` to the square of the matrix ``A``, which must be a square matrix. Aliasing is allowed. The function calls :func:`fmpz_mat_mul` for dimensions less than 12 and calls :func:`fmpz_mat_sqr_bodrato` for cases in which the latter is faster. .. function:: void fmpz_mat_sqr_bodrato(fmpz_mat_t B, const fmpz_mat_t A) Sets ``B`` to the square of the matrix ``A``, which must be a square matrix. Aliasing is allowed. The Bodrato algorithm is described in [Bodrato2010]_. It is highly efficient for squaring matrices which satisfy both the following conditions: (a) large elements, (b) dimensions less than 150. .. function:: void fmpz_mat_pow(fmpz_mat_t B, const fmpz_mat_t A, ulong e) Sets ``B`` to the matrix ``A`` raised to the power ``e``, where ``A`` must be a square matrix. Aliasing is allowed. .. function:: void _fmpz_mat_mul_small(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) This internal function sets `C` to the matrix product `C = A B` computed using classical matrix algorithm assuming that all entries of `A` and `B` are small, that is, have bits `\le FLINT\_BITS - 2`. No aliasing is allowed. .. function:: void _fmpz_mat_mul_double_word(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) This function is only for internal use and assumes that either: - the entries of `A` and `B` are all nonnegative and strictly less than `2^{2*FLINT\_BITS}`, or - the entries of `A` and `B` are all strictly less than `2^{2*FLINT\_BITS - 1}` in absolute value. .. function:: void fmpz_mat_mul_fmpz_vec(fmpz * c, const fmpz_mat_t A, const fmpz * b, slong blen) void fmpz_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mat_t A, const fmpz * const * b, slong blen) Compute a matrix-vector product of ``A`` and ``(b, blen)`` and store the result in ``c``. The vector ``(b, blen)`` is either truncated or zero-extended to the number of columns of ``A``. The number of entries written to ``c`` is always equal to the number of rows of ``A``. .. function:: void fmpz_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mat_t B) void fmpz_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mat_t B) Compute a vector-matrix product of ``(a, alen)`` and ``B`` and store the result in ``c``. The vector ``(a, alen)`` is either truncated or zero-extended to the number of rows of ``B``. The number of entries written to ``c`` is always equal to the number of columns of ``B``. Inverse -------------------------------------------------------------------------------- .. function:: int fmpz_mat_inv(fmpz_mat_t Ainv, fmpz_t den, const fmpz_mat_t A) Sets (``Ainv``, ``den``) to the inverse matrix of ``A``. Returns 1 if ``A`` is nonsingular and 0 if ``A`` is singular. Aliasing of ``Ainv`` and ``A`` is allowed. The denominator is not guaranteed to be minimal, but is guaranteed to be a divisor of the determinant of ``A``. This function uses a direct formula for matrices of size two or less, and otherwise solves for the identity matrix using fraction-free LU decomposition. Kronecker product -------------------------------------------------------------------------------- .. function:: void fmpz_mat_kronecker_product(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) Sets ``C`` to the Kronecker product of ``A`` and ``B``. Content -------------------------------------------------------------------------------- .. function:: void fmpz_mat_content(fmpz_t mat_gcd, const fmpz_mat_t A) Sets ``mat_gcd`` as the gcd of all the elements of the matrix ``A``. Returns 0 if the matrix is empty. Trace -------------------------------------------------------------------------------- .. function:: void fmpz_mat_trace(fmpz_t trace, const fmpz_mat_t mat) Computes the trace of the matrix, i.e. the sum of the entries on the main diagonal. The matrix is required to be square. Determinant -------------------------------------------------------------------------------- .. function:: void fmpz_mat_det(fmpz_t det, const fmpz_mat_t A) Sets ``det`` to the determinant of the square matrix `A`. The matrix of dimension `0 \times 0` is defined to have determinant 1. This function automatically chooses between :func:`fmpz_mat_det_cofactor`, :func:`fmpz_mat_det_bareiss`, :func:`fmpz_mat_det_modular` and :func:`fmpz_mat_det_modular_accelerated` (with ``proved`` = 1), depending on the size of the matrix and its entries. .. function:: void fmpz_mat_det_cofactor(fmpz_t det, const fmpz_mat_t A) Sets ``det`` to the determinant of the square matrix `A` computed using direct cofactor expansion. This function only supports matrices up to size `4 \times 4`. .. function:: void fmpz_mat_det_bareiss(fmpz_t det, const fmpz_mat_t A) Sets ``det`` to the determinant of the square matrix `A` computed using the Bareiss algorithm. A copy of the input matrix is row reduced using fraction-free Gaussian elimination, and the determinant is read off from the last element on the main diagonal. .. function:: void fmpz_mat_det_modular(fmpz_t det, const fmpz_mat_t A, int proved) Sets ``det`` to the determinant of the square matrix `A` (if ``proved`` = 1), or a probabilistic value for the determinant (``proved`` = 0), computed using a multimodular algorithm. The determinant is computed modulo several small primes and reconstructed using the Chinese Remainder Theorem. With ``proved`` = 1, sufficiently many primes are chosen to satisfy the bound computed by ``fmpz_mat_det_bound``. With ``proved`` = 0, the determinant is considered determined if it remains unchanged modulo several consecutive primes (currently if their product exceeds `2^{100}`). .. function:: void fmpz_mat_det_modular_accelerated(fmpz_t det, const fmpz_mat_t A, int proved) Sets ``det`` to the determinant of the square matrix `A` (if ``proved`` = 1), or a probabilistic value for the determinant (``proved`` = 0), computed using a multimodular algorithm. This function uses the same basic algorithm as ``fmpz_mat_det_modular``, but instead of computing `\det(A)` directly, it generates a divisor `d` of `\det(A)` and then computes `x = \det(A) / d` modulo several small primes not dividing `d`. This typically accelerates the computation by requiring fewer primes for large matrices, since `d` with high probability will be nearly as large as the determinant. This trick is described in [AbbottBronsteinMulders1999]_. .. function:: void fmpz_mat_det_modular_given_divisor(fmpz_t det, const fmpz_mat_t A, const fmpz_t d, int proved) Given a positive divisor `d` of `\det(A)`, sets ``det`` to the determinant of the square matrix `A` (if ``proved`` = 1), or a probabilistic value for the determinant (``proved`` = 0), computed using a multimodular algorithm. .. function:: void fmpz_mat_det_bound(fmpz_t bound, const fmpz_mat_t A) Sets ``bound`` to a nonnegative integer `B` such that `|\det(A)| \le B`. Assumes `A` to be a square matrix. The bound is computed from the Hadamard inequality `|\det(A)| \le \prod \|a_i\|_2` where the product is taken over the rows `a_i` of `A`. .. function:: void fmpz_mat_det_bound_nonzero(fmpz_t bound, const fmpz_mat_t A) As per ``fmpz_mat_det_bound()`` but excludes zero columns. For use with non-square matrices. .. function:: void fmpz_mat_det_divisor(fmpz_t d, const fmpz_mat_t A) Sets `d` to some positive divisor of the determinant of the given square matrix `A`, if the determinant is nonzero. If `|\det(A)| = 0`, `d` will always be set to zero. A divisor is obtained by solving `Ax = b` for an arbitrarily chosen right-hand side `b` using Dixon's algorithm and computing the least common multiple of the denominators in `x`. This yields a divisor `d` such that `|\det(A)| / d` is tiny with very high probability. Transforms -------------------------------------------------------------------------------- .. function:: void fmpz_mat_similarity(fmpz_mat_t A, slong r, fmpz_t d) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void _fmpz_mat_charpoly_berkowitz(fmpz * cp, const fmpz_mat_t mat) Sets ``(cp, n+1)`` to the characteristic polynomial of an `n \times n` square matrix. .. function:: void fmpz_mat_charpoly_berkowitz(fmpz_poly_t cp, const fmpz_mat_t mat) Computes the characteristic polynomial of length `n + 1` of an `n \times n` square matrix. Uses an `O(n^4)` algorithm based on the method of Berkowitz. .. function:: void _fmpz_mat_charpoly_modular(fmpz * cp, const fmpz_mat_t mat) Sets ``(cp, n+1)`` to the characteristic polynomial of an `n \times n` square matrix. .. function:: void fmpz_mat_charpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat) Computes the characteristic polynomial of length `n + 1` of an `n \times n` square matrix. Uses a modular method based on an `O(n^3)` method over `\mathbb{Z}/n\mathbb{Z}`. .. function:: void _fmpz_mat_charpoly(fmpz * cp, const fmpz_mat_t mat) Sets ``(cp, n+1)`` to the characteristic polynomial of an `n \times n` square matrix. .. function:: void fmpz_mat_charpoly(fmpz_poly_t cp, const fmpz_mat_t mat) Computes the characteristic polynomial of length `n + 1` of an `n \times n` square matrix. Minimal polynomial -------------------------------------------------------------------------------- .. function:: slong _fmpz_mat_minpoly_modular(fmpz * cp, const fmpz_mat_t mat) Sets ``(cp, n+1)`` to the modular polynomial of an `n \times n` square matrix and returns its length. .. function:: void fmpz_mat_minpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat) Computes the minimal polynomial of an `n \times n` square matrix. Uses a modular method based on an average time `O(n^3)`, worst case `O(n^4)` method over `\mathbb{Z}/n\mathbb{Z}`. .. function:: slong _fmpz_mat_minpoly(fmpz * cp, const fmpz_mat_t mat) Sets ``cp`` to the minimal polynomial of an `n \times n` square matrix and returns its length. .. function:: void fmpz_mat_minpoly(fmpz_poly_t cp, const fmpz_mat_t mat) Computes the minimal polynomial of an `n \times n` square matrix. Rank -------------------------------------------------------------------------------- .. function:: slong fmpz_mat_rank(const fmpz_mat_t A) Returns the rank, that is, the number of linearly independent columns (equivalently, rows), of `A`. The rank is computed by row reducing a copy of `A`. Column partitioning -------------------------------------------------------------------------------- .. function:: int fmpz_mat_col_partition(slong * part, fmpz_mat_t M, int short_circuit) Returns the number `p` of distinct columns of `M` (or `0` if the flag ``short_circuit`` is set and this number is greater than the number of rows of `M`). The entries of array ``part`` are set to values in `[0, p)` such that two entries of part are equal iff the corresponding columns of `M` are equal. This function is used in van Hoeij polynomial factoring. Nonsingular solving -------------------------------------------------------------------------------- The following functions allow solving matrix-matrix equations `AX = B` where the system matrix `A` is square and has full rank. The solving is implicitly done over the field of rational numbers: except where otherwise noted, an integer matrix `\hat X` and a separate denominator `d` (``den``) are computed such that `A(\hat X/d) = b`, equivalently such that `A\hat X = bd` holds over the integers. No guarantee is made that the numerators and denominator are reduced to lowest terms, but the denominator is always guaranteed to be a divisor of the determinant of `A`. If `A` is singular, ``den`` will be set to zero and the elements of the solution vector or matrix will have undefined values. No aliasing is allowed between arguments. .. function:: int fmpz_mat_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. This function uses Cramer's rule for small systems and fraction-free LU decomposition followed by fraction-free forward and back substitution for larger systems. Note that for very large systems, it is faster to compute a modular solution using ``fmpz_mat_solve_dixon``. .. function:: int fmpz_mat_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. Uses fraction-free LU decomposition followed by fraction-free forward and back substitution. .. function:: int fmpz_mat_solve_fflu_precomp(fmpz_mat_t X, const slong * perm, const fmpz_mat_t FFLU, const fmpz_mat_t B) Performs fraction-free forward and back substitution given a precomputed fraction-free LU decomposition and corresponding permutation. If no impossible division is encountered, the function returns `1`. This does not mean the system has a solution, however a return value of `0` can only occur if the system is insoluble. If the return value is `1` and `r` is the rank of the matrix `A` whose FFLU we have, then the first `r` rows of `p(A)y = p(b)d` hold, where `d` is the denominator of the FFLU. The remaining rows must be checked by the caller. .. function:: int fmpz_mat_solve_cramer(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. Uses Cramer's rule. Only systems of size up to `3 \times 3` are allowed. .. function:: void fmpz_mat_solve_bound(fmpz_t N, fmpz_t D, const fmpz_mat_t A, const fmpz_mat_t B) Assuming that `A` is nonsingular, computes integers `N` and `D` such that the reduced numerators and denominators `n/d` in `A^{-1} B` satisfy the bounds `0 \le |n| \le N` and `0 \le d \le D`. .. function:: int fmpz_mat_solve_dixon(fmpz_mat_t X, fmpz_t M, const fmpz_mat_t A, const fmpz_mat_t B) Solves `AX = B` given a nonsingular square matrix `A` and a matrix `B` of compatible dimensions, using a modular algorithm. In particular, Dixon's p-adic lifting algorithm is used (currently a non-adaptive version). This is generally the preferred method for large dimensions. More precisely, this function computes an integer `M` and an integer matrix `X` such that `AX = B \bmod M` and such that all the reduced numerators and denominators of the elements `x = p/q` in the full solution satisfy `2|p|q < M`. As such, the explicit rational solution matrix can be recovered uniquely by passing the output of this function to ``fmpq_mat_set_fmpz_mat_mod``. A nonzero value is returned if `A` is nonsingular. If `A` is singular, zero is returned and the values of the output variables will be undefined. Aliasing between input and output matrices is allowed. .. function:: void _fmpz_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B, const nmod_mat_t Ainv, mp_limb_t p, const fmpz_t N, const fmpz_t D) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}` using a ``p``-adic algorithm for the supplied prime ``p``. The values ``N`` and ``D`` are absolute value bounds for the numerator and denominator of the solution. Uses the Dixon lifting algorithm with early termination once the lifting stabilises. .. function:: int fmpz_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. Uses the Dixon lifting algorithm with early termination once the lifting stabilises. .. function:: int fmpz_mat_solve_multi_mod_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. Uses a Chinese remainder algorithm with early termination once the lifting stabilises. .. function:: int fmpz_mat_can_solve_multi_mod_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Returns `1` if the system `AX = B` can be solved. If so it computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. The computed denominator will not generally be minimal. Uses a Chinese remainder algorithm. Note that the matrices `A` and `B` may have any shape as long as they have the same number of rows. .. function:: int fmpz_mat_can_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Returns `1` if the system `AX = B` can be solved. If so it computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. The computed denominator will not generally be minimal. Uses a fraction free LU decomposition algorithm. Note that the matrices `A` and `B` may have any shape as long as they have the same number of rows. .. function:: int fmpz_mat_can_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) Returns `1` if the system `AX = B` can be solved. If so it computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. The computed denominator will not generally be minimal. Note that the matrices `A` and `B` may have any shape as long as they have the same number of rows. Row reduction -------------------------------------------------------------------------------- .. function:: slong fmpz_mat_find_pivot_any(const fmpz_mat_t mat, slong start_row, slong end_row, slong c) Attempts to find a pivot entry for row reduction. Returns a row index `r` between ``start_row`` (inclusive) and ``stop_row`` (exclusive) such that column `c` in ``mat`` has a nonzero entry on row `r`, or returns -1 if no such entry exists. This implementation simply chooses the first nonzero entry it encounters. This is likely to be a nearly optimal choice if all entries in the matrix have roughly the same size, but can lead to unnecessary coefficient growth if the entries vary in size. .. function:: slong fmpz_mat_fflu(fmpz_mat_t B, fmpz_t den, slong * perm, const fmpz_mat_t A, int rank_check) Uses fraction-free Gaussian elimination to set (``B``, ``den``) to a fraction-free LU decomposition of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. Pivot elements are chosen with ``fmpz_mat_find_pivot_any``. If ``perm`` is non-``NULL``, the permutation of rows in the matrix will also be applied to ``perm``. If ``rank_check`` is set, the function aborts and returns 0 if the matrix is detected not to have full rank without completing the elimination. The denominator ``den`` is set to `\pm \operatorname{det}(S)` where `S` is an appropriate submatrix of `A` (`S = A` if `A` is square) and the sign is decided by the parity of the permutation. Note that the determinant is not generally the minimal denominator. The fraction-free LU decomposition is defined in [NakTurWil1997]_. .. function:: slong fmpz_mat_rref(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A) Sets (``B``, ``den``) to the reduced row echelon form of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. The algorithm used chooses between ``fmpz_mat_rref_fflu`` and ``fmpz_mat_rref_mul`` based on the dimensions of the input matrix. .. function:: slong fmpz_mat_rref_fflu(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A) Sets (``B``, ``den``) to the reduced row echelon form of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. The algorithm proceeds by first computing a row echelon form using ``fmpz_mat_fflu``. Letting the upper part of this matrix be `(U | V) P` where `U` is full rank upper triangular and `P` is a permutation matrix, we obtain the rref by setting `V` to `U^{-1} V` using back substitution. Scaling each completed row in the back substitution to the denominator ``den``, we avoid introducing new fractions. This strategy is equivalent to the fraction-free Gauss-Jordan elimination in [NakTurWil1997]_, but faster since only the part `V` corresponding to the null space has to be updated. The denominator ``den`` is set to `\pm \operatorname{det}(S)` where `S` is an appropriate submatrix of `A` (`S = A` if `A` is square). Note that the determinant is not generally the minimal denominator. .. function:: slong fmpz_mat_rref_mul(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A) Sets (``B``, ``den``) to the reduced row echelon form of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. The algorithm works by computing the reduced row echelon form of ``A`` modulo a prime `p` using ``nmod_mat_rref``. The pivot columns and rows of this matrix will then define a non-singular submatrix of ``A``, nonsingular solving and matrix multiplication can then be used to determine the reduced row echelon form of the whole of ``A``. This procedure is described in [Stein2007]_. .. function:: int fmpz_mat_is_in_rref_with_rank(const fmpz_mat_t A, const fmpz_t den, slong rank) Checks that the matrix `A/den` is in reduced row echelon form of rank ``rank``, returns 1 if so and 0 otherwise. Strong echelon form and Howell form -------------------------------------------------------------------------------- .. function:: void fmpz_mat_strong_echelon_form_mod(fmpz_mat_t A, const fmpz_t mod) Transforms `A` such that `A` modulo ``mod`` is the strong echelon form of the input matrix modulo ``mod``. The Howell form and the strong echelon form are equal up to permutation of the rows, see [FieHof2014]_ for a definition of the strong echelon form and the algorithm used here. `A` must have at least as many rows as columns. .. function:: slong fmpz_mat_howell_form_mod(fmpz_mat_t A, const fmpz_t mod) Transforms `A` such that `A` modulo ``mod`` is the Howell form of the input matrix modulo ``mod``. For a definition of the Howell form see [StoMul1998]_. The Howell form is computed by first putting `A` into strong echelon form and then ordering the rows. `A` must have at least as many rows as columns. Nullspace -------------------------------------------------------------------------------- .. function:: slong fmpz_mat_nullspace(fmpz_mat_t B, const fmpz_mat_t A) Computes a basis for the right rational nullspace of `A` and returns the dimension of the nullspace (or nullity). `B` is set to a matrix with linearly independent columns and maximal rank such that `AB = 0` (i.e. `Ab = 0` for each column `b` in `B`), and the rank of `B` is returned. In general, the entries in `B` will not be minimal: in particular, the pivot entries in `B` will generally differ from unity. `B` must be allocated with sufficient space to represent the result (at most `n \times n` where `n` is the number of columns of `A`). Echelon form -------------------------------------------------------------------------------- .. function:: slong fmpz_mat_rref_fraction_free(slong * perm, fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A) Computes an integer matrix ``B`` and an integer ``den`` such that ``B / den`` is the unique row reduced echelon form (RREF) of ``A`` and returns the rank, i.e. the number of nonzero rows in ``B``. Aliasing of ``B`` and ``A`` is allowed, with an in-place computation being more efficient. The size of ``B`` must be the same as that of ``A``. The permutation order will be written to ``perm`` unless this argument is ``NULL``. That is, row ``i`` of the output matrix will correspond to row ``perm[i]`` of the input matrix. The denominator will always be a divisor of the determinant of (some submatrix of) `A`, but is not guaranteed to be minimal or canonical in any other sense. Hermite normal form -------------------------------------------------------------------------------- .. function:: void fmpz_mat_hnf(fmpz_mat_t H, const fmpz_mat_t A) Computes an integer matrix ``H`` such that ``H`` is the unique (row) Hermite normal form of ``A``. The algorithm used is selected from the implementations in FLINT to be the one most likely to be optimal, based on the characteristics of the input matrix. Aliasing of ``H`` and ``A`` is allowed. The size of ``H`` must be the same as that of ``A``. .. function:: void fmpz_mat_hnf_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A) Computes an integer matrix ``H`` such that ``H`` is the unique (row) Hermite normal form of ``A`` along with the transformation matrix ``U`` such that `UA = H`. The algorithm used is selected from the implementations in FLINT as per ``fmpz_mat_hnf``. Aliasing of ``H`` and ``A`` is allowed. The size of ``H`` must be the same as that of ``A`` and ``U`` must be square of \compatible dimension (having the same number of rows as ``A``). .. function:: void fmpz_mat_hnf_classical(fmpz_mat_t H, const fmpz_mat_t A) Computes an integer matrix ``H`` such that ``H`` is the unique (row) Hermite normal form of ``A``. The algorithm used is straightforward and is described, for example, in [Algorithm 2.4.4] [Coh1996]_. Aliasing of ``H`` and ``A`` is allowed. The size of ``H`` must be the same as that of ``A``. .. function:: void fmpz_mat_hnf_xgcd(fmpz_mat_t H, const fmpz_mat_t A) Computes an integer matrix ``H`` such that ``H`` is the unique (row) Hermite normal form of ``A``. The algorithm used is an improvement on the basic algorithm and uses extended gcds to speed up computation, this method is described, for example, in [Algorithm 2.4.5] [Coh1996]_. Aliasing of ``H`` and ``A`` is allowed. The size of ``H`` must be the same as that of ``A``. .. function:: void fmpz_mat_hnf_modular(fmpz_mat_t H, const fmpz_mat_t A, const fmpz_t D) Computes an integer matrix ``H`` such that ``H`` is the unique (row) Hermite normal form of the `m\times n` matrix ``A``, where ``A`` is assumed to be of rank `n` and ``D`` is known to be a positive multiple of the determinant of the non-zero rows of ``H``. The algorithm used here is due to Domich, Kannan and Trotter [DomKanTro1987]_ and is also described in [Algorithm 2.4.8] [Coh1996]_. Aliasing of ``H`` and ``A`` is allowed. The size of ``H`` must be the same as that of ``A``. .. function:: void fmpz_mat_hnf_modular_eldiv(fmpz_mat_t A, const fmpz_t D) Transforms the `m\times n` matrix ``A`` into Hermite normal form, where ``A`` is assumed to be of rank `n` and ``D`` is known to be a positive multiple of the largest elementary divisor of ``A``. The algorithm used here is described in [FieHof2014]_. .. function:: void fmpz_mat_hnf_minors(fmpz_mat_t H, const fmpz_mat_t A) Computes an integer matrix ``H`` such that ``H`` is the unique (row) Hermite normal form of the `m\times n` matrix ``A``, where ``A`` is assumed to be of rank `n`. The algorithm used here is due to Kannan and Bachem [KanBac1979]_ and takes the principal minors to Hermite normal form in turn. Aliasing of ``H`` and ``A`` is allowed. The size of ``H`` must be the same as that of ``A``. .. function:: void fmpz_mat_hnf_pernet_stein(fmpz_mat_t H, const fmpz_mat_t A, flint_rand_t state) Computes an integer matrix ``H`` such that ``H`` is the unique (row) Hermite normal form of the `m\times n` matrix ``A``. The algorithm used here is due to Pernet and Stein [PernetStein2010]_. Aliasing of ``H`` and ``A`` is allowed. The size of ``H`` must be the same as that of ``A``. .. function:: int fmpz_mat_is_in_hnf(const fmpz_mat_t A) Checks that the given matrix is in Hermite normal form, returns 1 if so and 0 otherwise. Smith normal form -------------------------------------------------------------------------------- .. function:: void fmpz_mat_snf(fmpz_mat_t S, const fmpz_mat_t A) Computes an integer matrix ``S`` such that ``S`` is the unique Smith normal form of ``A``. The algorithm used is selected from the implementations in FLINT to be the one most likely to be optimal, based on the characteristics of the input matrix. Aliasing of ``S`` and ``A`` is allowed. The size of ``S`` must be the same as that of ``A``. .. function:: void fmpz_mat_snf_diagonal(fmpz_mat_t S, const fmpz_mat_t A) Computes an integer matrix ``S`` such that ``S`` is the unique Smith normal form of the diagonal matrix ``A``. The algorithm used simply takes gcds of pairs on the diagonal in turn until the Smith form is obtained. Aliasing of ``S`` and ``A`` is allowed. The size of ``S`` must be the same as that of ``A``. .. function:: void fmpz_mat_snf_kannan_bachem(fmpz_mat_t S, const fmpz_mat_t A) Computes an integer matrix ``S`` such that ``S`` is the unique Smith normal form of the diagonal matrix ``A``. The algorithm used here is due to Kannan and Bachem [KanBac1979]_ Aliasing of ``S`` and ``A`` is allowed. The size of ``S`` must be the same as that of ``A``. .. function:: void fmpz_mat_snf_iliopoulos(fmpz_mat_t S, const fmpz_mat_t A, const fmpz_t mod) Computes an integer matrix ``S`` such that ``S`` is the unique Smith normal form of the nonsingular `n\times n` matrix ``A``. The algorithm used is due to Iliopoulos [Iliopoulos1989]_. Aliasing of ``S`` and ``A`` is allowed. The size of ``S`` must be the same as that of ``A``. .. function:: int fmpz_mat_is_in_snf(const fmpz_mat_t A) Checks that the given matrix is in Smith normal form, returns 1 if so and 0 otherwise. Special matrices -------------------------------------------------------------------------------- .. function:: void fmpz_mat_gram(fmpz_mat_t B, const fmpz_mat_t A) Sets ``B`` to the Gram matrix of the `m`-dimensional lattice ``L`` in `n`-dimensional Euclidean space `R^n` spanned by the rows of the `m \times n` matrix ``A``. Dimensions must be compatible. ``A`` and ``B`` are allowed to be the same object if ``A`` is a square matrix. .. function:: int fmpz_mat_is_hadamard(const fmpz_mat_t H) Returns nonzero iff `H` is a Hadamard matrix, meaning that it is a square matrix, only has entries that are `\pm 1`, and satisfies `H^T = n H^{-1}` where `n` is the matrix size. .. function:: int fmpz_mat_hadamard(fmpz_mat_t H) Attempts to set the matrix `H` to a Hadamard matrix, returning 1 if successful and 0 if unsuccessful. A Hadamard matrix of size `n` can only exist if `n` is 1, 2, or a multiple of 4. It is not known whether a Hadamard matrix exists for every size that is a multiple of 4. This function uses the Paley construction, which succeeds for all `n` of the form `n = 2^e` or `n = 2^e (q + 1)` where `q` is an odd prime power. Orders `n` for which Hadamard matrices are known to exist but for which this construction fails are 92, 116, 156, ... (OEIS A046116). Conversions -------------------------------------------------------------------------------- .. function:: int fmpz_mat_get_d_mat(d_mat_t B, const fmpz_mat_t A) Sets the entries of ``B`` as doubles corresponding to the entries of ``A``, rounding down towards zero if the latter cannot be represented exactly. The return value is -1 if any entry of ``A`` is too large to fit in the normal range of a double, and 0 otherwise. .. function:: int fmpz_mat_get_d_mat_transpose(d_mat_t B, const fmpz_mat_t A) Sets the entries of ``B`` as doubles corresponding to the entries of the transpose of ``A``, rounding down towards zero if the latter cannot be represented exactly. The return value is -1 if any entry of ``A`` is too large to fit in the normal range of a double, and 0 otherwise. Cholesky Decomposition -------------------------------------------------------------------------------- .. function:: void fmpz_mat_is_spd(const fmpz_mat_t A) Returns true iff ``A`` is symmetric and positive definite (in particular square). We first attempt a numerical `LDL^T` decomposition using :func:`arb_mat_ldl`. If we cannot guarantee that `A` is positive definite, we use an exact method instead, computing the characteristic polynomial of `A` and applying Descartes' rule of signs. .. function:: void fmpz_mat_chol_d(d_mat_t R, const fmpz_mat_t A) Computes ``R``, the Cholesky factor of a symmetric, positive definite matrix ``A`` using the Cholesky decomposition process. (Sets ``R`` such that `A = RR^{T}` where ``R`` is a lower triangular matrix.) LLL -------------------------------------------------------------------------------- .. function:: int fmpz_mat_is_reduced(const fmpz_mat_t A, double delta, double eta) int fmpz_mat_is_reduced_gram(const fmpz_mat_t A, double delta, double eta) Returns a non-zero value if the basis ``A`` is LLL-reduced with factor (``delta``, ``eta``), and otherwise returns zero. The second version assumes ``A`` is the Gram matrix of the basis. .. function:: int fmpz_mat_is_reduced_with_removal(const fmpz_mat_t A, double delta, double eta, const fmpz_t gs_B, int newd) int fmpz_mat_is_reduced_gram_with_removal(const fmpz_mat_t A, double delta, double eta, const fmpz_t gs_B, int newd) Returns a non-zero value if the basis ``A`` is LLL-reduced with factor (``delta``, ``eta``) for each of the first ``newd`` vectors and the squared Gram-Schmidt length of each of the remaining `i`-th vectors (where `i \ge` ``newd``) is greater than ``gs_B``, and otherwise returns zero. The second version assumes ``A`` is the Gram matrix of the basis. Classical LLL -------------------------------------------------------------------------------- .. function:: void fmpz_mat_lll_original(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta) Takes a basis `x_1, x_2, \ldots, x_m` of the lattice `L \subset R^n` (as the rows of a `m \times n` matrix ``A``). The output is a (``delta``, ``eta``)-reduced basis `y_1, y_2, \ldots, y_m` of the lattice `L` (as the rows of the same `m \times n` matrix ``A``). Modified LLL -------------------------------------------------------------------------------- .. function:: void fmpz_mat_lll_storjohann(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta) Takes a basis `x_1, x_2, \ldots, x_m` of the lattice `L \subset R^n` (as the rows of a `m \times n` matrix ``A``). The output is an (``delta``, ``eta``)-reduced basis `y_1, y_2, \ldots, y_m` of the lattice `L` (as the rows of the same `m \times n` matrix ``A``). Uses a modified version of LLL, which has better complexity in terms of the lattice dimension, introduced by Storjohann. See "Faster Algorithms for Integer Lattice Basis Reduction." Technical Report 249. Zurich, Switzerland: Department Informatik, ETH. July 30, 1996. flint-3.1.3/doc/source/fmpz_mod.rst000066400000000000000000000135451461254215100172550ustar00rootroot00000000000000.. _fmpz-mod: **fmpz_mod.h** -- arithmetic modulo integers =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mod_ctx_struct .. type:: fmpz_mod_ctx_t The context object for arithmetic modulo integers. Context object -------------------------------------------------------------------------------- .. function:: void fmpz_mod_ctx_init(fmpz_mod_ctx_t ctx, const fmpz_t n) Initialise ``ctx`` for arithmetic modulo ``n``, which is expected to be positive. .. function:: void fmpz_mod_ctx_clear(fmpz_mod_ctx_t ctx) Free any memory used by ``ctx``. .. function:: void fmpz_mod_ctx_set_modulus(fmpz_mod_ctx_t ctx, const fmpz_t n) Reconfigure ``ctx`` for arithmetic modulo ``n``. Conversions ----------------------------------------------------------------------------------------------------------------------- .. function:: void fmpz_mod_set_fmpz(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) Set ``a`` to ``b`` after reduction modulo the modulus. Arithmetic -------------------------------------------------------------------------------- Unless specified otherwise all functions here expect their relevant arguments to be in the canonical range `[0,n)`. Comparison of elements against each other or against zero can be accomplished with func::fmpz_equal or func::fmpz_is_zero without a context. .. function:: int fmpz_mod_is_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx) Return ``1`` if `a` is in the canonical range `[0,n)` and ``0`` otherwise. .. function:: int fmpz_mod_is_one(const fmpz_t a, const fmpz_mod_ctx_t ctx) Return ``1`` if `a` is `1` modulo `n` and return ``0`` otherwise. .. function:: void fmpz_mod_add(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) Set `a` to `b+c` modulo `n`. .. function:: void fmpz_mod_add_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) void fmpz_mod_add_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx) void fmpz_mod_add_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx) Set `a` to `b+c` modulo `n` where only `b` is assumed to be canonical. .. function:: void fmpz_mod_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) Set `a` to `b-c` modulo `n`. .. function:: void fmpz_mod_sub_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) void fmpz_mod_sub_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx) void fmpz_mod_sub_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx) Set `a` to `b-c` modulo `n` where only `b` is assumed to be canonical. .. function:: void fmpz_mod_fmpz_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) void fmpz_mod_ui_sub(fmpz_t a, ulong b, const fmpz_t c, const fmpz_mod_ctx_t ctx) void fmpz_mod_si_sub(fmpz_t a, slong b, const fmpz_t c, const fmpz_mod_ctx_t ctx) Set `a` to `b-c` modulo `n` where only `c` is assumed to be canonical. .. function:: void fmpz_mod_neg(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) Set `a` to `-b` modulo `n`. .. function:: void fmpz_mod_mul(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) Set `a` to `b\cdot c` modulo `n`. .. function:: void fmpz_mod_inv(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) Set `a` to `b^{-1}` modulo `n`. This function expects that `b` is invertible modulo `n` and throws if this not the case. Invertibility may be tested with :func:`fmpz_mod_pow_fmpz` or :func:`fmpz_mod_divides`. .. function:: int fmpz_mod_divides(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) If `a\cdot c = b \mod n` has a solution for `a` return `1` and set `a` to such a solution. Otherwise return `0` and leave `a` undefined. .. function:: void fmpz_mod_pow_ui(fmpz_t a, const fmpz_t b, ulong e, const fmpz_mod_ctx_t ctx) Set `a` to `b^e` modulo `n`. .. function:: int fmpz_mod_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t e, const fmpz_mod_ctx_t ctx) Try to set `a` to `b^e` modulo `n`. If `e < 0` and `b` is not invertible modulo `n`, the return is `0`. Otherwise, the return is `1`. Discrete Logarithms via Pohlig-Hellman -------------------------------------------------------------------------------- .. function:: void fmpz_mod_discrete_log_pohlig_hellman_init(fmpz_mod_discrete_log_pohlig_hellman_t L) Initialize ``L``. Upon initialization ``L`` is not ready for computation. .. function:: void fmpz_mod_discrete_log_pohlig_hellman_clear(fmpz_mod_discrete_log_pohlig_hellman_t L) Free any space used by ``L``. .. function:: double fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t p) Configure ``L`` for discrete logarithms modulo ``p`` to an internally chosen base. It is assumed that ``p`` is prime. The return is an estimate on the number of multiplications needed for one run. .. function:: const fmpz * fmpz_mod_discrete_log_pohlig_hellman_primitive_root(fmpz_mod_discrete_log_pohlig_hellman_t L) Return the internally stored base. .. function:: void fmpz_mod_discrete_log_pohlig_hellman_run(fmpz_t x, const fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t y) Set ``x`` to the logarithm of ``y`` with respect to the internally stored base. ``y`` is expected to be reduced modulo the ``p``. The function is undefined if the logarithm does not exist. .. function:: int fmpz_next_smooth_prime(fmpz_t a, const fmpz_t b) Either return `1` and set `a` to a smooth prime strictly greater than `b`, or return `0` and set `a` to `0`. The smooth primes returned by this function currently have no prime factor of `a-1` greater than `23`, but this should not be relied upon. flint-3.1.3/doc/source/fmpz_mod_mat.rst000066400000000000000000000411501461254215100201070ustar00rootroot00000000000000.. _fmpz_mod_mat: **fmpz_mod_mat.h** -- matrices over integers mod n =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mod_mat_struct .. type:: fmpz_mod_mat_t Element access -------------------------------------------------------------------------------- .. function:: fmpz * fmpz_mod_mat_entry(const fmpz_mod_mat_t mat, slong i, slong j) Return a reference to the element at row ``i`` and column ``j`` of ``mat``. .. function:: void fmpz_mod_mat_set_entry(fmpz_mod_mat_t mat, slong i, slong j, const fmpz_t val, const fmpz_mod_ctx_t ctx) Set the entry at row ``i`` and column ``j`` of ``mat`` to ``val``. Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_init(fmpz_mod_mat_t mat, slong rows, slong cols, const fmpz_mod_ctx_t ctx) Initialise ``mat`` as a matrix with the given number of ``rows`` and ``cols`` and modulus defined by ``ctx``. .. function:: void fmpz_mod_mat_init_set(fmpz_mod_mat_t mat, const fmpz_mod_mat_t src, const fmpz_mod_ctx_t ctx) Initialise ``mat`` and set it equal to the matrix ``src``, including the number of rows and columns and the modulus. .. function:: void fmpz_mod_mat_clear(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Clear ``mat`` and release any memory it used. Basic manipulation -------------------------------------------------------------------------------- .. function:: slong fmpz_mod_mat_nrows(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Return the number of rows of ``mat``. .. function:: slong fmpz_mod_mat_ncols(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Return the number of columns of ``mat``. .. function:: void _fmpz_mod_mat_set_mod(fmpz_mod_mat_t mat, const fmpz_t n, const fmpz_mod_ctx_t ctx) Set the modulus of the matrix ``mat`` to ``n``. .. function:: void fmpz_mod_mat_one(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Set ``mat`` to the identity matrix (ones down the diagonal). .. function:: void fmpz_mod_mat_zero(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Set ``mat`` to the zero matrix. .. function:: void fmpz_mod_mat_swap(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) Efficiently swap the matrices ``mat1`` and ``mat2``. .. function:: void fmpz_mod_mat_swap_entrywise(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: int fmpz_mod_mat_is_empty(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Return `1` if ``mat`` has either zero rows or columns. .. function:: int fmpz_mod_mat_is_square(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Return `1` if ``mat`` has the same number of rows and columns. .. function:: void _fmpz_mod_mat_reduce(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Reduce all the entries of ``mat`` by the modulus ``n``. This function is only needed internally. Random generation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_randtest(fmpz_mod_mat_t mat, flint_rand_t state, const fmpz_mod_ctx_t ctx) Generate a random matrix with the existing dimensions and entries in `[0, n)` where ``n`` is the modulus. Windows and concatenation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_window_init(fmpz_mod_mat_t window, const fmpz_mod_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fmpz_mod_ctx_t ctx) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0, 0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void fmpz_mod_mat_window_clear(fmpz_mod_mat_t window, const fmpz_mod_ctx_t ctx) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. .. function:: void fmpz_mod_mat_concat_horizontal(fmpz_mod_mat_t res, const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) Sets ``res`` to vertical concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `k \times n`, ``res`` : `(m + k) \times n`. .. function:: void fmpz_mod_mat_concat_vertical(fmpz_mod_mat_t res, const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `m \times k`, ``res`` : `m \times (n + k)`. Input and output -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_print_pretty(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Prints the given matrix to ``stdout``. The format is an opening square bracket then on each line a row of the matrix, followed by a closing square bracket. Each row is written as an opening square bracket followed by a space separated list of coefficients followed by a closing square bracket. Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_mod_mat_is_zero(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Return `1` if ``mat`` is the zero matrix. Set and transpose -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_set(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) Set ``B`` to equal ``A``. .. function:: void fmpz_mod_mat_transpose(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) Set ``B`` to the transpose of ``A``. Conversions ------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_set_fmpz_mat(fmpz_mod_mat_t A, const fmpz_mat_t B, const fmpz_mod_ctx_t ctx) Set ``A`` to the matrix ``B`` reducing modulo the modulus of ``A``. .. function:: void fmpz_mod_mat_get_fmpz_mat(fmpz_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Set ``A`` to a lift of ``B``. Addition and subtraction ------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_add(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Set ``C`` to `A + B`. .. function:: void fmpz_mod_mat_sub(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Set ``C`` to `A - B`. .. function:: void fmpz_mod_mat_neg(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) Set ``B`` to `-A`. Scalar arithmetic -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_scalar_mul_si(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, slong c, const fmpz_mod_ctx_t ctx) Set ``B`` to `cA` where ``c`` is a constant. .. function:: void fmpz_mod_mat_scalar_mul_ui(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, ulong c, const fmpz_mod_ctx_t ctx) Set ``B`` to `cA` where ``c`` is a constant. .. function:: void fmpz_mod_mat_scalar_mul_fmpz(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, fmpz_t c, const fmpz_mod_ctx_t ctx) Set ``B`` to `cA` where ``c`` is a constant. Matrix multiplication --------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_mul(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Set ``C`` to ``A\times B``. The number of rows of ``B`` must match the number of columns of ``A``. .. function:: void _fmpz_mod_mat_mul_classical_threaded_pool_op(fmpz_mod_mat_t D, const fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, int op, thread_pool_handle * threads, slong num_threads, const fmpz_mod_ctx_t ctx) Set ``D`` to ``A\times B + op*C`` where ``op`` is ``+1``, ``-1`` or ``0``. .. function:: void _fmpz_mod_mat_mul_classical_threaded_op(fmpz_mod_mat_t D, const fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, int op, const fmpz_mod_ctx_t ctx) Set ``D`` to ``A\times B + op*C`` where ``op`` is ``+1``, ``-1`` or ``0``. .. function:: void fmpz_mod_mat_mul_classical_threaded(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Set ``C`` to ``A\times B``. The number of rows of ``B`` must match the number of columns of ``A``. .. function:: void fmpz_mod_mat_sqr(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) Set ``B`` to ``A^2``. The matrix ``A`` must be square. .. function:: void fmpz_mod_mat_mul_fmpz_vec(fmpz * c, const fmpz_mod_mat_t A, const fmpz * b, slong blen, const fmpz_mod_ctx_t ctx) void fmpz_mod_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mod_mat_t A, const fmpz * const * b, slong blen, const fmpz_mod_ctx_t ctx) Compute a matrix-vector product of ``A`` and ``(b, blen)`` and store the result in ``c``. The vector ``(b, blen)`` is either truncated or zero-extended to the number of columns of ``A``. The number entries written to ``c`` is always equal to the number of rows of ``A``. .. function:: void fmpz_mod_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) void fmpz_mod_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Compute a vector-matrix product of ``(a, alen)`` and ``B`` and and store the result in ``c``. The vector ``(a, alen)`` is either truncated or zero-extended to the number of rows of ``B``. The number entries written to ``c`` is always equal to the number of columns of ``B``. Trace --------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_trace(fmpz_t trace, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Set ``trace`` to the trace of the matrix ``mat``. Gaussian elimination -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_det(fmpz_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Set ``res`` to the determinant of the matrix ``mat``. .. function:: slong fmpz_mod_mat_rref(fmpz_mod_mat_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Sets ``res`` to the reduced row echelon form of ``mat`` and returns the rank. The modulus is assumed to be prime. Strong echelon form and Howell form -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_strong_echelon_form(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Transforms `mat` into the strong echelon form of `mat`. The Howell form and the strong echelon form are equal up to permutation of the rows, see [FieHof2014]_ for a definition of the strong echelon form and the algorithm used here. `mat` must have at least as many rows as columns. .. function:: slong fmpz_mod_mat_howell_form(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) Transforms `mat` into the Howell form of `mat`. For a definition of the Howell form see [StoMul1998]_. The Howell form is computed by first putting `mat` into strong echelon form and then ordering the rows. `mat` must have at least as many rows as columns. Inverse -------------------------------------------------------------------------------- .. function:: int fmpz_mod_mat_inv(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) Sets `B = A^{-1}` and returns `1` if `A` is invertible. If `A` is singular, returns `0` and sets the elements of `B` to undefined values. `A` and `B` must be square matrices with the same dimensions. The modulus is assumed to be prime. LU decomposition -------------------------------------------------------------------------------- .. function:: slong fmpz_mod_mat_lu(slong * P, fmpz_mod_mat_t A, int rank_check, const fmpz_mod_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. If `A` is a nonsingular square matrix, it will be overwritten with a unit diagonal lower triangular matrix `L` and an upper triangular matrix `U` (the diagonal of `L` will not be stored explicitly). If `A` is an arbitrary matrix of rank `r`, `U` will be in row echelon form having `r` nonzero rows, and `L` will be lower triangular but truncated to `r` columns, having implicit ones on the `r` first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and return 0 if `A` is detected to be rank-deficient. The modulus is assumed to be prime. Triangular solving -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_solve_tril(fmpz_mod_mat_t X, const fmpz_mod_mat_t L, const fmpz_mod_mat_t B, int unit, const fmpz_mod_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. The modulus is assumed to be prime. .. function:: void fmpz_mod_mat_solve_triu(fmpz_mod_mat_t X, const fmpz_mod_mat_t U, const fmpz_mod_mat_t B, int unit, const fmpz_mod_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. The modulus is assumed to be prime. Solving -------------------------------------------------------------------------------- .. function:: int fmpz_mod_mat_solve(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Solves the matrix-matrix equation `AX = B`. Returns `1` if `A` has full rank; otherwise returns `0` and sets the elements of `X` to undefined values. The matrix `A` must be square. The modulus is assumed to be prime. .. function:: int fmpz_mod_mat_can_solve(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) Solves the matrix-matrix equation `AX = B` over `Fp`. Returns `1` if a solution exists; otherwise returns `0` and sets the elements of `X` to zero. If more than one solution exists, one of the valid solutions is given. There are no restrictions on the shape of `A` and it may be singular. The modulus is assumed to be prime. Transforms -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_similarity(fmpz_mod_mat_t M, slong r, fmpz_t d, const fmpz_mod_ctx_t ctx) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. The value `d` is required to be reduced modulo the modulus of the entries in the matrix. The modulus is assumed to be prime. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_charpoly(fmpz_mod_poly_t p, const fmpz_mod_mat_t M, const fmpz_mod_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. Minimal polynomial -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_minpoly(fmpz_mod_poly_t p, const fmpz_mod_mat_t M, const fmpz_mod_ctx_t ctx) Compute the minimal polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. The modulus is assumed to be prime. flint-3.1.3/doc/source/fmpz_mod_mpoly.rst000066400000000000000000001050661461254215100204750ustar00rootroot00000000000000.. _fmpz-mod-mpoly: **fmpz_mod_mpoly.h** -- polynomials over the integers mod n =============================================================================== The exponents follow the ``mpoly`` interface. A coefficient may be referenced as a ``fmpz *``, but this may disappear in a future version. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mod_mpoly_struct A structure holding a multivariate polynomial over the integers mod n. .. type:: fmpz_mod_mpoly_t An array of length `1` of ``fmpz_mod_mpoly_ctx_struct``. .. type:: fmpz_mod_mpoly_ctx_struct Context structure representing the parent ring of an ``fmpz_mod_mpoly``. .. type:: fmpz_mod_mpoly_ctx_t An array of length `1` of ``fmpz_mod_mpoly_struct``. Context object -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_ctx_init(fmpz_mod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fmpz_t p) Initialise a context object for a polynomial ring modulo *n* with *nvars* variables and ordering *ord*. The possibilities for the ordering are ``ORD_LEX``, ``ORD_DEGLEX`` and ``ORD_DEGREVLEX``. .. function:: slong fmpz_mod_mpoly_ctx_nvars(const fmpz_mod_mpoly_ctx_t ctx) Return the number of variables used to initialize the context. .. function:: ordering_t fmpz_mod_mpoly_ctx_ord(const fmpz_mod_mpoly_ctx_t ctx) Return the ordering used to initialize the context. .. function:: void fmpz_mod_mpoly_ctx_get_modulus(fmpz_t n, const fmpz_mod_mpoly_ctx_t ctx) Set *n* to the modulus used to initialize the context. .. function:: void fmpz_mod_mpoly_ctx_clear(fmpz_mod_mpoly_ctx_t ctx) Release up any space allocated by an *ctx*. Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_init(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. .. function:: void fmpz_mod_mpoly_init2(fmpz_mod_mpoly_t A, slong alloc, const fmpz_mod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and at least ``MPOLY_MIN_BITS`` bits for the exponents. .. function:: void fmpz_mod_mpoly_init3(fmpz_mod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and *bits* bits for the exponents. .. function:: void fmpz_mod_mpoly_clear(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Release any space allocated for *A*. Input/Output -------------------------------------------------------------------------------- The variable strings in *x* start with the variable of most significance at index `0`. If *x* is ``NULL``, the variables are named ``x1``, ``x2``, etc. .. function:: char * fmpz_mod_mpoly_get_str_pretty(const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) Return a string, which the user is responsible for cleaning up, representing *A*, given an array of variable strings *x*. .. function:: int fmpz_mod_mpoly_fprint_pretty(FILE * file, const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) Print a string representing *A* to *file*. .. function:: int fmpz_mod_mpoly_print_pretty(const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) Print a string representing *A* to ``stdout``. .. function:: int fmpz_mod_mpoly_set_str_pretty(fmpz_mod_mpoly_t A, const char * str, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the polynomial in the null-terminates string *str* given an array *x* of variable strings. If parsing *str* fails, *A* is set to zero, and `-1` is returned. Otherwise, `0` is returned. The operations ``+``, ``-``, ``*``, and ``/`` are permitted along with integers and the variables in *x*. The character ``^`` must be immediately followed by the (integer) exponent. If any division is not exact, parsing fails. Basic manipulation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_gen(fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the variable of index *var*, where `var = 0` corresponds to the variable with the most significance with respect to the ordering. .. function:: int fmpz_mod_mpoly_is_gen(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) If `var \ge 0`, return `1` if *A* is equal to the `var`-th generator, otherwise return `0`. If `var < 0`, return `1` if the polynomial is equal to any generator, otherwise return `0`. .. function:: void fmpz_mod_mpoly_set(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to *B*. .. function:: int fmpz_mod_mpoly_equal(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if *A* is equal to *B*, else return `0`. .. function:: void fmpz_mod_mpoly_swap(fmpz_mod_mpoly_t poly1, fmpz_mod_mpoly_t poly2, const fmpz_mod_mpoly_ctx_t ctx) Efficiently swap *A* and *B*. Constants -------------------------------------------------------------------------------- .. function:: int fmpz_mod_mpoly_is_fmpz(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if *A* is a constant, else return `0`. .. function:: void fmpz_mod_mpoly_get_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Assuming that *A* is a constant, set *c* to this constant. This function throws if *A* is not a constant. .. function:: void fmpz_mod_mpoly_set_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_ui(fmpz_mod_mpoly_t A, ulong c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_si(fmpz_mod_mpoly_t A, slong c, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the constant *c*. .. function:: void fmpz_mod_mpoly_zero(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the constant `0`. .. function:: void fmpz_mod_mpoly_one(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the constant `1`. .. function:: int fmpz_mod_mpoly_equal_fmpz(const fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) int fmpz_mod_mpoly_equal_ui(const fmpz_mod_mpoly_t A, ulong c, const fmpz_mod_mpoly_ctx_t ctx) int fmpz_mod_mpoly_equal_si(const fmpz_mod_mpoly_t A, slong c, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if *A* is equal to the constant *c*, else return `0`. .. function:: int fmpz_mod_mpoly_is_zero(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if *A* is the constant `0`, else return `0`. .. function:: int fmpz_mod_mpoly_is_one(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if *A* is the constant `1`, else return `0`. Degrees -------------------------------------------------------------------------------- .. function:: int fmpz_mod_mpoly_degrees_fit_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if the degrees of *A* with respect to each variable fit into an ``slong``, otherwise return `0`. .. function:: void fmpz_mod_mpoly_degrees_fmpz(fmpz ** degs, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_degrees_si(slong * degs, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Set *degs* to the degrees of *A* with respect to each variable. If *A* is zero, all degrees are set to `-1`. .. function:: void fmpz_mod_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) slong fmpz_mod_mpoly_degree_si(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) Either return or set *deg* to the degree of *A* with respect to the variable of index *var*. If *A* is zero, the degree is defined to be `-1`. .. function:: int fmpz_mod_mpoly_total_degree_fits_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if the total degree of *A* fits into an ``slong``, otherwise return `0`. .. function:: void fmpz_mod_mpoly_total_degree_fmpz(fmpz_t tdeg, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) slong fmpz_mod_mpoly_total_degree_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Either return or set *tdeg* to the total degree of *A*. If *A* is zero, the total degree is defined to be `-1`. .. function:: void fmpz_mod_mpoly_used_vars(int * used, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) For each variable index *i*, set ``used[i]`` to nonzero if the variable of index *i* appears in *A* and to zero otherwise. Coefficients -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_get_coeff_fmpz_monomial(fmpz_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set *c* to the coefficient of the corresponding monomial in *A*. This function throws if *M* is not a monomial. .. function:: void fmpz_mod_mpoly_set_coeff_fmpz_monomial(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set the coefficient of the corresponding monomial in *A* to *c*. This function throws if *M* is not a monomial. .. function:: void fmpz_mod_mpoly_get_coeff_fmpz_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_get_coeff_fmpz_ui(fmpz_t c, const fmpz_mod_mpoly_t A, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) Set *c* to the coefficient of the monomial with exponent vector *exp*. .. function:: void fmpz_mod_mpoly_set_coeff_fmpz_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_coeff_ui_fmpz(fmpz_mod_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_coeff_si_fmpz(fmpz_mod_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_coeff_fmpz_ui(fmpz_mod_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_coeff_ui_ui(fmpz_mod_mpoly_t A, ulong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_coeff_si_ui(fmpz_mod_mpoly_t A, slong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) Set the coefficient of the monomial with exponent vector *exp* to *c*. .. function:: void fmpz_mod_mpoly_get_coeff_vars_ui(fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpz_mod_mpoly_ctx_t ctx) Set *C* to the coefficient of *A* with respect to the variables in *vars* with powers in the corresponding array *exps*. Both *vars* and *exps* point to array of length *length*. It is assumed that `0 < length \le nvars(A)` and that the variables in *vars* are distinct. Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_mod_mpoly_cmp(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Return `1` (resp. `-1`, or `0`) if *A* is after (resp. before, same as) *B* in some arbitrary but fixed total ordering of the polynomials. This ordering agrees with the usual ordering of monomials when *A* and *B* are both monomials. Container operations -------------------------------------------------------------------------------- These functions deal with violations of the internal canonical representation. If a term index is negative or not strictly less than the length of the polynomial, the function will throw. .. function:: int fmpz_mod_mpoly_is_canonical(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if *A* is in canonical form. Otherwise, return `0`. To be in canonical form, all of the terms must have nonzero coefficient, and the terms must be sorted from greatest to least. .. function:: slong fmpz_mod_mpoly_length(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return the number of terms in *A*. If the polynomial is in canonical form, this will be the number of nonzero coefficients. .. function:: void fmpz_mod_mpoly_resize(fmpz_mod_mpoly_t A, slong new_length, const fmpz_mod_mpoly_ctx_t ctx) Set the length of *A* to ``new_length``. Terms are either deleted from the end, or new zero terms are appended. .. function:: void fmpz_mod_mpoly_get_term_coeff_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) Set *c* to the coefficient of the term of index *i*. .. function:: void fmpz_mod_mpoly_set_term_coeff_fmpz(fmpz_mod_mpoly_t A, slong i, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_term_coeff_ui(fmpz_mod_mpoly_t A, slong i, ulong c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_term_coeff_si(fmpz_mod_mpoly_t A, slong i, slong c, const fmpz_mod_mpoly_ctx_t ctx) Set the coefficient of the term of index *i* to *c*. .. function:: int fmpz_mod_mpoly_term_exp_fits_si(const fmpz_mod_mpoly_t poly, slong i, const fmpz_mod_mpoly_ctx_t ctx) int fmpz_mod_mpoly_term_exp_fits_ui(const fmpz_mod_mpoly_t poly, slong i, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if all entries of the exponent vector of the term of index *i* fit into an ``slong`` (resp. a ``ulong``). Otherwise, return `0`. .. function:: void fmpz_mod_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_get_term_exp_ui(ulong * exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_get_term_exp_si(slong * exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) Set *exp* to the exponent vector of the term of index *i*. The ``_ui`` (resp. ``_si``) version throws if any entry does not fit into a ``ulong`` (resp. ``slong``). .. function:: ulong fmpz_mod_mpoly_get_term_var_exp_ui(const fmpz_mod_mpoly_t A, slong i, slong var, const fmpz_mod_mpoly_ctx_t ctx) slong fmpz_mod_mpoly_get_term_var_exp_si(const fmpz_mod_mpoly_t A, slong i, slong var, const fmpz_mod_mpoly_ctx_t ctx) Return the exponent of the variable *var* of the term of index *i*. This function throws if the exponent does not fit into a ``ulong`` (resp. ``slong``). .. function:: void fmpz_mod_mpoly_set_term_exp_fmpz(fmpz_mod_mpoly_t A, slong i, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_term_exp_ui(fmpz_mod_mpoly_t A, slong i, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) Set the exponent vector of the term of index *i* to *exp*. .. function:: void fmpz_mod_mpoly_get_term(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) Set *M* to the term of index *i* in *A*. .. function:: void fmpz_mod_mpoly_get_term_monomial(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void fmpz_mod_mpoly_push_term_fmpz_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_fmpz_ffmpz(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_ui_fmpz(fmpz_mod_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_ui_ffmpz(fmpz_mod_mpoly_t A, ulong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_si_fmpz(fmpz_mod_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_si_ffmpz(fmpz_mod_mpoly_t A, slong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_fmpz_ui(fmpz_mod_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_ui_ui(fmpz_mod_mpoly_t A, ulong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_si_ui(fmpz_mod_mpoly_t A, slong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) Append a term to *A* with coefficient *c* and exponent vector *exp*. This function runs in constant average time. .. function:: void fmpz_mod_mpoly_sort_terms(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Sort the terms of *A* into the canonical ordering dictated by the ordering in *ctx*. This function simply reorders the terms: It does not combine like terms, nor does it delete terms with coefficient zero. This function runs in linear time in the size of *A*. .. function:: void fmpz_mod_mpoly_combine_like_terms(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Combine adjacent like terms in *A* and delete terms with coefficient zero. If the terms of *A* were sorted to begin with, the result will be in canonical form. This function runs in linear time in the size of *A*. .. function:: void fmpz_mod_mpoly_reverse(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the reversal of *B*. Random generation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_randtest_bound(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const fmpz_mod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bound - 1]``. The exponents of each variable are generated by calls to ``n_randint(state, exp_bound)``. .. function:: void fmpz_mod_mpoly_randtest_bounds(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const fmpz_mod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bounds[i] - 1]``. The exponents of the variable of index *i* are generated by calls to ``n_randint(state, exp_bounds[i])``. .. function:: void fmpz_mod_mpoly_randtest_bits(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, mp_limb_t exp_bits, const fmpz_mod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents whose packed form does not exceed the given bit count. Addition/Subtraction -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_add_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_add_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_add_si(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `B + c`. .. function:: void fmpz_mod_mpoly_sub_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_sub_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_sub_si(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `B - c`. .. function:: void fmpz_mod_mpoly_add(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `B + C`. .. function:: void fmpz_mod_mpoly_sub(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `B - C`. Scalar operations -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_neg(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `-B`. .. function:: void fmpz_mod_mpoly_scalar_mul_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_scalar_mul_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_scalar_mul_si(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `B \times c`. .. function:: void fmpz_mod_mpoly_scalar_addmul_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_t d, const fmpz_mod_mpoly_ctx_t ctx) Sets *A* to `B + C \times d`. .. function:: void fmpz_mod_mpoly_make_monic(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to *B* divided by the leading coefficient of *B*. This throws if *B* is zero or the leading coefficient is not invertible. Differentiation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_derivative(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the derivative of *B* with respect to the variable of index *var*. Evaluation -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: void fmpz_mod_mpoly_evaluate_all_fmpz(fmpz_t eval, const fmpz_mod_mpoly_t A, fmpz * const * vals, const fmpz_mod_mpoly_ctx_t ctx) Set *ev* to the evaluation of *A* where the variables are replaced by the corresponding elements of the array *vals*. .. function:: void fmpz_mod_mpoly_evaluate_one_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_t val, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the evaluation of *B* where the variable of index *var* is replaced by *val*. Return `1` for success and `0` for failure. .. function:: int fmpz_mod_mpoly_compose_fmpz_poly(fmpz_poly_t A, const fmpz_mod_mpoly_t B, fmpz_poly_struct * const * C, const fmpz_mod_mpoly_ctx_t ctxB) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. The context object of *B* is *ctxB*. Return `1` for success and `0` for failure. .. function:: int fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz_mod_mpoly_struct * const * C, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC) int fmpz_mod_mpoly_compose_fmpz_mod_mpoly(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz_mod_mpoly_struct * const * C, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. Both *A* and the elements of *C* have context object *ctxAC*, while *B* has context object *ctxB*. The length of the array *C* is the number of variables in *ctxB*. Neither *A* nor *B* is allowed to alias any other polynomial. Return `1` for success and `0` for failure. The main method attempts to perform the calculation using matrices and chooses heuristically between the ``geobucket`` and ``horner`` methods if needed. .. function:: void fmpz_mod_mpoly_compose_fmpz_mod_mpoly_gen(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const slong * c, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variable of index *i* in *ctxB* is replaced by the variable of index ``c[i]`` in *ctxAC*. The length of the array *C* is the number of variables in *ctxB*. If any ``c[i]`` is negative, the corresponding variable of *B* is replaced by zero. Otherwise, it is expected that ``c[i]`` is less than the number of variables in *ctxAC*. Multiplication -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_mul(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `B \times C`. .. function:: void fmpz_mod_mpoly_mul_johnson(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to `B \times C` using Johnson's heap-based method. .. function:: int fmpz_mod_mpoly_mul_dense(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) Try to set *A* to `B \times C` using dense arithmetic. If the return is `0`, the operation was unsuccessful. Otherwise, it was successful and the return is `1`. Powering -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: int fmpz_mod_mpoly_pow_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t k, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to *B* raised to the `k`-th power. Return `1` for success and `0` for failure. .. function:: int fmpz_mod_mpoly_pow_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong k, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to *B* raised to the `k`-th power. Return `1` for success and `0` for failure. Division -------------------------------------------------------------------------------- The division functions assume that the modulus is prime. .. function:: int fmpz_mod_mpoly_divides(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) If *A* is divisible by *B*, set *Q* to the exact quotient and return `1`. Otherwise, set *Q* to zero and return `0`. .. function:: void fmpz_mod_mpoly_div(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Set *Q* to the quotient of *A* by *B*, discarding the remainder. .. function:: void fmpz_mod_mpoly_divrem(fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Set *Q* and *R* to the quotient and remainder of *A* divided by *B*. .. function:: void fmpz_mod_mpoly_divrem_ideal(fmpz_mod_mpoly_struct ** Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, fmpz_mod_mpoly_struct * const * B, slong len, const fmpz_mod_mpoly_ctx_t ctx) This function is as per :func:`fmpz_mod_mpoly_divrem` except that it takes an array of divisor polynomials *B* and it returns an array of quotient polynomials *Q*. The number of divisor (and hence quotient) polynomials, is given by *len*. Greatest Common Divisor -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_term_content(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Set *M* to the GCD of the terms of *A*. If *A* is zero, *M* will be zero. Otherwise, *M* will be a monomial with coefficient one. .. function:: int fmpz_mod_mpoly_content_vars(fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_t A, slong * vars, slong vars_length, const fmpz_mod_mpoly_ctx_t ctx) Set *g* to the GCD of the coefficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon success, *g* will be independent of the variables *vars*. .. function:: int fmpz_mod_mpoly_gcd(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Try to set *G* to the monic GCD of *A* and *B*. The GCD of zero and zero is defined to be zero. If the return is `1` the function was successful. Otherwise the return is `0` and *G* is left untouched. .. function:: int fmpz_mod_mpoly_gcd_cofactors(fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Do the operation of :func:`fmpz_mod_mpoly_gcd` and also compute `Abar = A/G` and `Bbar = B/G` if successful. .. function:: int fmpz_mod_mpoly_gcd_brown(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) int fmpz_mod_mpoly_gcd_hensel(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) int fmpz_mod_mpoly_gcd_subresultant(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) int fmpz_mod_mpoly_gcd_zippel(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) int fmpz_mod_mpoly_gcd_zippel2(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) Try to set *G* to the GCD of *A* and *B* using various algorithms. .. function:: int fmpz_mod_mpoly_resultant(fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) Try to set *R* to the resultant of *A* and *B* with respect to the variable of index *var*. .. function:: int fmpz_mod_mpoly_discriminant(fmpz_mod_mpoly_t D, const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) Try to set *D* to the discriminant of *A* with respect to the variable of index *var*. Square Root -------------------------------------------------------------------------------- The square root functions assume that the modulus is prime for correct operation. .. function:: int fmpz_mod_mpoly_sqrt(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) If `Q^2=A` has a solution, set *Q* to a solution and return `1`, otherwise return `0` and set *Q* to zero. .. function:: int fmpz_mod_mpoly_is_square(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if *A* is a perfect square, otherwise return `0`. .. function:: int fmpz_mod_mpoly_quadratic_root(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) If `Q^2+AQ=B` has a solution, set *Q* to a solution and return `1`, otherwise return `0`. Univariate Functions -------------------------------------------------------------------------------- An ``fmpz_mod_mpoly_univar_t`` holds a univariate polynomial in some main variable with ``fmpz_mod_mpoly_t`` coefficients in the remaining variables. These functions are useful when one wants to rewrite an element of `\mathbb{Z}/n\mathbb{Z}[x_1, \dots, x_m]` as an element of `(\mathbb{Z}/n\mathbb{Z}[x_1, \dots, x_{v-1}, x_{v+1}, \dots, x_m])[x_v]` and vice versa. .. function:: void fmpz_mod_mpoly_univar_init(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) Initialize *A*. .. function:: void fmpz_mod_mpoly_univar_clear(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) Clear *A*. .. function:: void fmpz_mod_mpoly_univar_swap(fmpz_mod_mpoly_univar_t A, fmpz_mod_mpoly_univar_t B, const fmpz_mod_mpoly_ctx_t ctx) Swap *A* and *B*. .. function:: void fmpz_mod_mpoly_to_univar(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to a univariate form of *B* by pulling out the variable of index *var*. The coefficients of *A* will still belong to the content *ctx* but will not depend on the variable of index *var*. .. function:: void fmpz_mod_mpoly_from_univar(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_univar_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) Set *A* to the normal form of *B* by putting in the variable of index *var*. This function is undefined if the coefficients of *B* depend on the variable of index *var*. .. function:: int fmpz_mod_mpoly_univar_degree_fits_si(const fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) Return `1` if the degree of *A* with respect to the main variable fits an ``slong``. Otherwise, return `0`. .. function:: slong fmpz_mod_mpoly_univar_length(const fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) Return the number of terms in *A* with respect to the main variable. .. function:: slong fmpz_mod_mpoly_univar_get_term_exp_si(fmpz_mod_mpoly_univar_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) Return the exponent of the term of index *i* of *A*. .. function:: void fmpz_mod_mpoly_univar_get_term_coeff(fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_univar_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_univar_swap_term_coeff(fmpz_mod_mpoly_t c, fmpz_mod_mpoly_univar_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) Set (resp. swap) *c* to (resp. with) the coefficient of the term of index *i* of *A*. .. function:: void fmpz_mod_mpoly_univar_set_coeff_ui(fmpz_mod_mpoly_univar_t Ax, ulong e, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx) Set the coefficient of `X^e` in *Ax* to *c*. .. function:: int fmpz_mod_mpoly_univar_resultant(fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_univar_t Ax, const fmpz_mod_mpoly_univar_t Bx, const fmpz_mod_mpoly_ctx_t ctx) Try to set *R* to the resultant of *Ax* and *Bx*. .. function:: int fmpz_mod_mpoly_univar_discriminant(fmpz_mod_mpoly_t D, const fmpz_mod_mpoly_univar_t Ax, const fmpz_mod_mpoly_ctx_t ctx) Try to set *D* to the discriminant of *Ax*. Internal Functions -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_inflate(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mod_mpoly_ctx_t ctx) Apply the function ``e -> shift[v] + stride[v]*e`` to each exponent ``e`` corresponding to the variable ``v``. It is assumed that each shift and stride is not negative. .. function:: void fmpz_mod_mpoly_deflate(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mod_mpoly_ctx_t ctx) Apply the function ``e -> (e - shift[v])/stride[v]`` to each exponent ``e`` corresponding to the variable ``v``. If any ``stride[v]`` is zero, the corresponding numerator ``e - shift[v]`` is assumed to be zero, and the quotient is defined as zero. This allows the function to undo the operation performed by :func:`fmpz_mod_mpoly_inflate` when possible. .. function:: void fmpz_mod_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) For each variable `v` let `S_v` be the set of exponents appearing on `v`. Set ``shift[v]`` to `\operatorname{min}(S_v)` and set ``stride[v]`` to `\operatorname{gcd}(S-\operatorname{min}(S_v))`. If *A* is zero, all shifts and strides are set to zero. flint-3.1.3/doc/source/fmpz_mod_mpoly_factor.rst000066400000000000000000000064571461254215100220370ustar00rootroot00000000000000.. _fmpz-mod-mpoly-factor: **fmpz_mod_mpoly_factor.h** -- factorisation of multivariate polynomials over the integers mod n ================================================================================================ Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mod_mpoly_factor_struct A struct for holding a factored polynomial over the integers mod n. There is a single constant and a product of bases to corresponding exponents. .. type:: fmpz_mod_mpoly_factor_t An array of length `1` of ``fmpz_mod_mpoly_factor_struct``. Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_factor_init(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) Initialise *f*. .. function:: void fmpz_mod_mpoly_factor_clear(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) Clear *f*. Basic manipulation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mpoly_factor_swap(fmpz_mod_mpoly_factor_t f, fmpz_mod_mpoly_factor_t g, const fmpz_mod_mpoly_ctx_t ctx) Efficiently swap *f* and *g*. .. function:: slong fmpz_mod_mpoly_factor_length(const fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) Return the length of the product in *f*. .. function:: void fmpz_mod_mpoly_factor_get_constant_fmpz(fmpz_t c, const fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) Set *c* to the constant of *f*. .. function:: void fmpz_mod_mpoly_factor_get_base(fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_factor_t f, slong i, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_factor_swap_base(fmpz_mod_mpoly_t B, fmpz_mod_mpoly_factor_t f, slong i, const fmpz_mod_mpoly_ctx_t ctx) Set (resp. swap) *B* to (resp. with) the base of the term of index *i* in *f*. .. function:: slong fmpz_mod_mpoly_factor_get_exp_si(fmpz_mod_mpoly_factor_t f, slong i, const fmpz_mod_mpoly_ctx_t ctx) Return the exponent of the term of index *i* in *f*. It is assumed to fit an ``slong``. .. function:: void fmpz_mod_mpoly_factor_sort(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) Sort the product of *f* first by exponent and then by base. Factorisation -------------------------------------------------------------------------------- A return of `1` indicates that the function was successful. Otherwise, the return is `0` and *f* is undefined. None of these functions multiply *f* by *A*: *f* is simply set to a factorisation of *A*, and thus these functions should not depend on the initial value of the output *f*. .. function:: int fmpz_mod_mpoly_factor_squarefree(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are primitive and pairwise relatively prime. If the product of all irreducible factors with a given exponent is desired, it is recommended to call :func:`fmpz_mod_mpoly_factor_sort` and then multiply the bases with the desired exponent. .. function:: int fmpz_mod_mpoly_factor(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are irreducible. flint-3.1.3/doc/source/fmpz_mod_poly.rst000066400000000000000000002616521461254215100203240ustar00rootroot00000000000000.. _fmpz-mod-poly: **fmpz_mod_poly.h** -- polynomials over integers mod n =============================================================================== The :type:`fmpz_mod_poly_t` data type represents elements of `\mathbb{Z}/n\mathbb{Z}[x]` for a fixed modulus `n`. The :type:`fmpz_mod_poly` module provides routines for memory management, basic arithmetic and some higher level functions such as GCD, etc. Each coefficient of an :type:`fmpz_mod_poly_t` is of type :type:`fmpz` and represents an integer reduced modulo the fixed modulus `n` in the range `[0,n)`. Unless otherwise specified, all functions in this section permit aliasing between their input arguments and between their input and output arguments. The :type:`fmpz_mod_poly_t` type is a typedef for an array of length 1 of :type:`fmpz_mod_poly_struct`'s. This permits passing parameters of type :type:`fmpz_mod_poly_t` by reference. In reality one never deals directly with the ``struct`` and simply deals with objects of type :type:`fmpz_mod_poly_t`. For simplicity we will think of an :type:`fmpz_mod_poly_t` as a ``struct``, though in practice to access fields of this ``struct``, one needs to dereference first, e.g. to access the ``length`` field of an :type:`fmpz_mod_poly_t` called ``poly1`` one writes ``poly1->length``. An :type:`fmpz_mod_poly_t` is said to be *normalised* if either ``length`` is zero, or if the leading coefficient of the polynomial is non-zero. All :type:`fmpz_mod_poly` functions expect their inputs to be normalised and all coefficients to be reduced modulo `n`, and unless otherwise specified they produce output that is normalised with coefficients reduced modulo `n`. Simple example -------------- The following example computes the square of the polynomial `5x^3 + 6` in `\mathbb{Z}/7\mathbb Z[x]`. .. code:: c #include "fmpz_mod_poly.h" int main() { fmpz_t n; fmpz_mod_poly_t x, y; fmpz_init_set_ui(n, 7); fmpz_mod_poly_init(x, n); fmpz_mod_poly_init(y, n); fmpz_mod_poly_set_coeff_ui(x, 3, 5); fmpz_mod_poly_set_coeff_ui(x, 0, 6); fmpz_mod_poly_sqr(y, x); fmpz_mod_poly_print(x); flint_printf("\n"); fmpz_mod_poly_print(y); flint_printf("\n"); fmpz_mod_poly_clear(x); fmpz_mod_poly_clear(y); fmpz_clear(n); } The output is: :: 4 7 6 0 0 5 7 7 1 0 0 4 0 0 4 Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mod_poly_struct A structure holding a polynomial over the integers modulo `n`. .. type:: fmpz_mod_poly_t An array of length 1 of ``fmpz_mod_poly_struct``. Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_init(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Initialises ``poly`` for use with context ``ctx`` and set it to zero. A corresponding call to :func:`fmpz_mod_poly_clear` must be made to free the memory used by the polynomial. .. function:: void fmpz_mod_poly_init2(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx) Initialises ``poly`` with space for at least ``alloc`` coefficients and sets the length to zero. The allocated coefficients are all set to zero. .. function:: void fmpz_mod_poly_clear(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Clears the given polynomial, releasing any memory used. It must be reinitialised in order to be used again. .. function:: void fmpz_mod_poly_realloc(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` the polynomial is first truncated to length ``alloc``. .. function:: void fmpz_mod_poly_fit_length(fmpz_mod_poly_t poly, slong len, const fmpz_mod_ctx_t ctx) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where it is called many times in small increments by at least doubling the number of allocated coefficients when length is larger than the number of coefficients currently allocated. .. function:: void _fmpz_mod_poly_normalise(fmpz_mod_poly_t poly) Sets the length of ``poly`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void _fmpz_mod_poly_set_length(fmpz_mod_poly_t poly, slong len) Demotes the coefficients of ``poly`` beyond ``len`` and sets the length of ``poly`` to ``len``. .. function:: void fmpz_mod_poly_truncate(fmpz_mod_poly_t poly, slong len, const fmpz_mod_ctx_t ctx) If the current length of ``poly`` is greater than ``len``, it is truncated to have the given length. Discarded coefficients are not necessarily set to zero. .. function:: void fmpz_mod_poly_set_trunc(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) Notionally truncate ``poly`` to length `n` and set ``res`` to the result. The result is normalised. Randomisation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_randtest(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Sets the polynomial~`f` to a random polynomial of length up~``len``. .. function:: void fmpz_mod_poly_randtest_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Sets the polynomial~`f` to a random irreducible polynomial of length up~``len``, assuming ``len`` is positive. .. function:: void fmpz_mod_poly_randtest_not_zero(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Sets the polynomial~`f` to a random polynomial of length up~``len``, assuming ``len`` is positive. .. function:: void fmpz_mod_poly_randtest_monic(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Generates a random monic polynomial with length ``len``. .. function:: void fmpz_mod_poly_randtest_monic_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Generates a random monic irreducible polynomial with length ``len``. .. function:: void fmpz_mod_poly_randtest_monic_primitive(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Generates a random monic irreducible primitive polynomial with length ``len``. .. function:: void fmpz_mod_poly_randtest_trinomial(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Generates a random monic trinomial of length ``len``. .. function:: int fmpz_mod_poly_randtest_trinomial_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, slong max_attempts, const fmpz_mod_ctx_t ctx) Attempts to set ``poly`` to a monic irreducible trinomial of length ``len``. It will generate up to ``max_attempts`` trinomials in attempt to find an irreducible one. If ``max_attempts`` is ``0``, then it will keep generating trinomials until an irreducible one is found. Returns `1` if one is found and `0` otherwise. .. function:: void fmpz_mod_poly_randtest_pentomial(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Generates a random monic pentomial of length ``len``. .. function:: int fmpz_mod_poly_randtest_pentomial_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, slong max_attempts, const fmpz_mod_ctx_t ctx) Attempts to set ``poly`` to a monic irreducible pentomial of length ``len``. It will generate up to ``max_attempts`` pentomials in attempt to find an irreducible one. If ``max_attempts`` is ``0``, then it will keep generating pentomials until an irreducible one is found. Returns `1` if one is found and `0` otherwise. .. function:: void fmpz_mod_poly_randtest_sparse_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) Attempts to set ``poly`` to a sparse, monic irreducible polynomial with length ``len``. It attempts to find an irreducible trinomial. If that does not succeed, it attempts to find a irreducible pentomial. If that fails, then ``poly`` is just set to a random monic irreducible polynomial. Attributes -------------------------------------------------------------------------------- .. function:: slong fmpz_mod_poly_degree(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Returns the degree of the polynomial. The degree of the zero polynomial is defined to be `-1`. .. function:: slong fmpz_mod_poly_length(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Returns the length of the polynomial, which is one more than its degree. .. function:: fmpz * fmpz_mod_poly_lead(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Returns a pointer to the first leading coefficient of ``poly`` if this is non-zero, otherwise returns ``NULL``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_set(fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) Sets the polynomial ``poly1`` to the value of ``poly2``. .. function:: void fmpz_mod_poly_swap(fmpz_mod_poly_t poly1, fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) Swaps the two polynomials. This is done efficiently by swapping pointers rather than individual coefficients. .. function:: void fmpz_mod_poly_zero(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Sets ``poly`` to the zero polynomial. .. function:: void fmpz_mod_poly_one(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Sets ``poly`` to the constant polynomial `1`. .. function:: void fmpz_mod_poly_zero_coeffs(fmpz_mod_poly_t poly, slong i, slong j, const fmpz_mod_ctx_t ctx) Sets the coefficients of `X^k` for `k \in [i, j)` in the polynomial to zero. .. function:: void fmpz_mod_poly_reverse(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) This function considers the polynomial ``poly`` to be of length `n`, notionally truncating and zero padding if required, and reverses the result. Since the function normalises its result ``res`` may be of length less than `n`. Conversion -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_set_ui(fmpz_mod_poly_t f, ulong c, const fmpz_mod_ctx_t ctx) Sets the polynomial `f` to the constant `c` reduced modulo `p`. .. function:: void fmpz_mod_poly_set_fmpz(fmpz_mod_poly_t f, const fmpz_t c, const fmpz_mod_ctx_t ctx) Sets the polynomial `f` to the constant `c` reduced modulo `p`. .. function:: void fmpz_mod_poly_set_fmpz_poly(fmpz_mod_poly_t f, const fmpz_poly_t g, const fmpz_mod_ctx_t ctx) Sets `f` to `g` reduced modulo `p`, where `p` is the modulus that is part of the data structure of `f`. .. function:: void fmpz_mod_poly_get_fmpz_poly(fmpz_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) Sets `f` to `g`. This is done simply by lifting the coefficients of `g` taking representatives `[0, p) \subset \mathbf{Z}`. .. function:: void fmpz_mod_poly_get_nmod_poly(nmod_poly_t f, const fmpz_mod_poly_t g) Sets `f` to `g` assuming the modulus of both polynomials is the same (no checking is performed). .. function:: void fmpz_mod_poly_set_nmod_poly(fmpz_mod_poly_t f, const nmod_poly_t g) Sets `f` to `g` assuming the modulus of both polynomials is the same (no checking is performed). Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_mod_poly_equal(const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) Returns non-zero if the two polynomials are equal, otherwise returns zero. .. function:: int fmpz_mod_poly_equal_trunc(const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) Notionally truncates the two polynomials to length `n` and returns non-zero if the two polynomials are equal, otherwise returns zero. .. function:: int fmpz_mod_poly_is_zero(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Returns non-zero if the polynomial is zero. .. function:: int fmpz_mod_poly_is_one(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Returns non-zero if the polynomial is the constant `1`. .. function:: int fmpz_mod_poly_is_gen(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Returns non-zero if the polynomial is the degree `1` polynomial `x`. Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_set_coeff_fmpz(fmpz_mod_poly_t poly, slong n, const fmpz_t x, const fmpz_mod_ctx_t ctx) Sets the coefficient of `X^n` in the polynomial to `x`, assuming `n \geq 0`. .. function:: void fmpz_mod_poly_set_coeff_ui(fmpz_mod_poly_t poly, slong n, ulong x, const fmpz_mod_ctx_t ctx) Sets the coefficient of `X^n` in the polynomial to `x`, assuming `n \geq 0`. .. function:: void fmpz_mod_poly_get_coeff_fmpz(fmpz_t x, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) Sets `x` to the coefficient of `X^n` in the polynomial, assuming `n \geq 0`. .. function:: void fmpz_mod_poly_set_coeff_mpz(fmpz_mod_poly_t poly, slong n, const mpz_t x, const fmpz_mod_ctx_t ctx) Sets the coefficient of `X^n` in the polynomial to `x`, assuming `n \geq 0`. .. function:: void fmpz_mod_poly_get_coeff_mpz(mpz_t x, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) Sets `x` to the coefficient of `X^n` in the polynomial, assuming `n \geq 0`. Shifting -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, len + n)`` to ``(poly, len)`` shifted left by `n` coefficients. Inserts zero coefficients at the lower end. Assumes that ``len`` and `n` are positive, and that ``res`` fits ``len + n`` elements. Supports aliasing between ``res`` and ``poly``. .. function:: void fmpz_mod_poly_shift_left(fmpz_mod_poly_t f, const fmpz_mod_poly_t g, slong n, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` shifted left by `n` coeffs. Zero coefficients are inserted. .. function:: void _fmpz_mod_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, len - n)`` to ``(poly, len)`` shifted right by `n` coefficients. Assumes that ``len`` and `n` are positive, that ``len > n``, and that ``res`` fits ``len - n`` elements. Supports aliasing between ``res`` and ``poly``, although in this case the top coefficients of ``poly`` are not set to zero. .. function:: void fmpz_mod_poly_shift_right(fmpz_mod_poly_t f, const fmpz_mod_poly_t g, slong n, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` shifted right by `n` coefficients. If `n` is equal to or greater than the current length of ``poly``, ``res`` is set to the zero polynomial. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_add(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx) Sets ``res`` to the sum of ``(poly1, len1)`` and ``(poly2, len2)``. It is assumed that ``res`` has sufficient space for the longer of the two polynomials. .. function:: void fmpz_mod_poly_add(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``poly2``. .. function:: void fmpz_mod_poly_add_series(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length `n` and set ``res`` to the sum. .. function:: void _fmpz_mod_poly_sub(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``(poly1, len1)`` minus ``(poly2, len2)``. It is assumed that ``res`` has sufficient space for the longer of the two polynomials. .. function:: void fmpz_mod_poly_sub(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly1`` minus ``poly2``. .. function:: void fmpz_mod_poly_sub_series(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length `n` and set ``res`` to the difference. .. function:: void _fmpz_mod_poly_neg(fmpz * res, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx) Sets ``(res, len)`` to the negative of ``(poly, len)`` modulo `p`. .. function:: void fmpz_mod_poly_neg(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Sets ``res`` to the negative of ``poly`` modulo `p`. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_scalar_mul_fmpz(fmpz * res, const fmpz * poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx) Sets ``(res, len``) to ``(poly, len)`` multiplied by `x`, reduced modulo `p`. .. function:: void fmpz_mod_poly_scalar_mul_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t x, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` multiplied by `x`. .. function:: void fmpz_mod_poly_scalar_addmul_fmpz(fmpz_mod_poly_t rop, const fmpz_mod_poly_t op, const fmpz_t x, const fmpz_mod_ctx_t ctx) Adds to ``rop`` the product of ``op`` by the scalar ``x``. .. function:: void _fmpz_mod_poly_scalar_div_fmpz(fmpz * res, const fmpz * poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx) Sets ``(res, len``) to ``(poly, len)`` divided by `x` (i.e. multiplied by the inverse of `x \pmod{p}`). The result is reduced modulo `p`. .. function:: void fmpz_mod_poly_scalar_div_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t x, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` divided by `x`, (i.e. multiplied by the inverse of `x \pmod{p}`). The result is reduced modulo `p`. Multiplication -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_mul(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx) Sets ``(res, len1 + len2 - 1)`` to the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes ``len1 >= len2 > 0``. Allows zero-padding of the two input polynomials. .. function:: void fmpz_mod_poly_mul(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _fmpz_mod_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n, const fmpz_mod_ctx_t ctx) Sets ``(res, n)`` to the lowest `n` coefficients of the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes ``len1 >= len2 > 0`` and ``0 < n <= len1 + len2 - 1``. Allows for zero-padding in the inputs. Does not support aliasing between the inputs and the output. .. function:: void fmpz_mod_poly_mullow(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) Sets ``res`` to the lowest `n` coefficients of the product of ``poly1`` and ``poly2``. .. function:: void _fmpz_mod_poly_sqr(fmpz * res, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx) Sets ``res`` to the square of ``poly``. .. function:: void fmpz_mod_poly_sqr(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Computes ``res`` as the square of ``poly``. .. function:: void fmpz_mod_poly_mulhigh(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong start, const fmpz_mod_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary. .. function:: void _fmpz_mod_poly_mulmod(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx) Sets ``res, len1 + len2 - 1`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``len1 + len2 - lenf > 0``, which is equivalent to requiring that the result will actually be reduced. Otherwise, simply use ``_fmpz_mod_poly_mul`` instead. Aliasing of ``f`` and ``res`` is not permitted. .. function:: void fmpz_mod_poly_mulmod(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. .. function:: void _fmpz_mod_poly_mulmod_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz * finv, slong lenfinv, const fmpz_mod_ctx_t ctx) Sets ``res, len1 + len2 - 1`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``finv`` is the inverse of the reverse of ``f`` mod ``x^lenf``. It is required that ``len1 + len2 - lenf > 0``, which is equivalent to requiring that the result will actually be reduced. It is required that ``len1 < lenf`` and ``len2 < lenf``. Otherwise, simply use ``_fmpz_mod_poly_mul`` instead. Aliasing of ``f`` or ``finv`` and ``res`` is not permitted. .. function:: void fmpz_mod_poly_mulmod_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. ``finv`` is the inverse of the reverse of ``f``. It is required that ``poly1`` and ``poly2`` are reduced modulo ``f``. Products -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Sets ``(poly, n + 1)`` to the monic polynomial which is the product of `(x - x_0)(x - x_1) \cdots (x - x_{n-1})`, the roots `x_i` being given by ``xs``. It is required that the roots are canonical. Aliasing of the input and output is not allowed. .. function:: void fmpz_mod_poly_product_roots_fmpz_vec(fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Sets ``poly`` to the monic polynomial which is the product of `(x - x_0)(x - x_1) \cdots (x - x_{n-1})`, the roots `x_i` being given by ``xs``. It is required that the roots are canonical. .. function:: int fmpz_mod_poly_find_distinct_nonzero_roots(fmpz * roots, const fmpz_mod_poly_t A, const fmpz_mod_ctx_t ctx) If ``A`` has `\deg(A)` distinct nonzero roots in `\mathbb{F}_p`, write these roots out to ``roots[0]`` to ``roots[deg(A) - 1]`` and return ``1``. Otherwise, return ``0``. It is assumed that ``A`` is nonzero and that the modulus of ``A`` is prime. This function uses Rabin's probabilistic method via gcd's with `(x + \delta)^{\frac{p-1}{2}} - 1`. Powering -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_pow(fmpz * rop, const fmpz * op, slong len, ulong e, const fmpz_mod_ctx_t ctx) Sets ``rop = poly^e``, assuming that `e > 1` and ``elen > 0``, and that ``res`` has space for ``e*(len - 1) + 1`` coefficients. Does not support aliasing. .. function:: void fmpz_mod_poly_pow(fmpz_mod_poly_t rop, const fmpz_mod_poly_t op, ulong e, const fmpz_mod_ctx_t ctx) Computes ``rop = poly^e``. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void _fmpz_mod_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. .. function:: void fmpz_mod_poly_pow_trunc(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. .. function:: void _fmpz_mod_poly_pow_trunc_binexp(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. Uses the binary exponentiation method. .. function:: void fmpz_mod_poly_pow_trunc_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Uses the binary exponentiation method. .. function:: void _fmpz_mod_poly_powmod_ui_binexp(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fmpz_mod_poly_powmod_ui_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz * finv, slong lenfinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fmpz_mod_poly_powmod_fmpz_binexp(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fmpz_mod_poly_powmod_fmpz_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz * finv, slong lenfinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz * res, const fmpz_t e, const fmpz * f, slong lenf, const fmpz * finv, slong lenfinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 2``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz_mod_poly_t res, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of `` .. function:: void _fmpz_mod_poly_powers_mod_preinv_naive(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t ctx) Compute ``f^0, f^1, ..., f^(n-1) mod g``, where ``g`` has length ``glen`` and ``f`` is reduced mod ``g`` and has length ``flen`` (possibly zero spaced). Assumes ``res`` is an array of ``n`` arrays each with space for at least ``glen - 1`` coefficients and that ``flen > 0``. We require that ``ginv`` of length ``ginvlen`` is set to the power series inverse of the reverse of ``g``. .. function:: void fmpz_mod_poly_powers_mod_naive(fmpz_mod_poly_struct * res, const fmpz_mod_poly_t f, slong n, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) Set the entries of the array ``res`` to ``f^0, f^1, ..., f^(n-1) mod g``. No aliasing is permitted between the entries of ``res`` and either of the inputs. .. function:: void _fmpz_mod_poly_powers_mod_preinv_threaded_pool(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t p, thread_pool_handle * threads, slong num_threads) Compute ``f^0, f^1, ..., f^(n-1) mod g``, where ``g`` has length ``glen`` and ``f`` is reduced mod ``g`` and has length ``flen`` (possibly zero spaced). Assumes ``res`` is an array of ``n`` arrays each with space for at least ``glen - 1`` coefficients and that ``flen > 0``. We require that ``ginv`` of length ``ginvlen`` is set to the power series inverse of the reverse of ``g``. .. function:: void fmpz_mod_poly_powers_mod_bsgs(fmpz_mod_poly_struct * res, const fmpz_mod_poly_t f, slong n, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) Set the entries of the array ``res`` to ``f^0, f^1, ..., f^(n-1) mod g``. No aliasing is permitted between the entries of ``res`` and either of the inputs. .. function:: void fmpz_mod_poly_frobenius_powers_2exp_precomp(fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, ulong m, const fmpz_mod_ctx_t ctx) If ``p = f->p``, compute `x^{(p^1)}`, `x^{(p^2)}`, `x^{(p^4)}`, ..., `x^{(p^{(2^l)})} \pmod{f}` where `2^l` is the greatest power of `2` less than or equal to `m`. Allows construction of `x^{(p^k)}` for `k = 0`, `1`, ..., `x^{(p^m)} \pmod{f}` using :func:`fmpz_mod_poly_frobenius_power`. Requires precomputed inverse of `f`, i.e. newton inverse. .. function:: void fmpz_mod_poly_frobenius_powers_2exp_clear(fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_ctx_t ctx) Clear resources used by the ``fmpz_mod_poly_frobenius_powers_2exp_t`` struct. .. function:: void fmpz_mod_poly_frobenius_power(fmpz_mod_poly_t res, fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_poly_t f, ulong m, const fmpz_mod_ctx_t ctx) If ``p = f->p``, compute `x^{(p^m)} \pmod{f}`. Requires precomputed frobenius powers supplied by ``fmpz_mod_poly_frobenius_powers_2exp_precomp``. If `m == 0` and `f` has degree `0` or `1`, this performs a division. However an impossible inverse by the leading coefficient of `f` will have been caught by ``fmpz_mod_poly_frobenius_powers_2exp_precomp``. .. function:: void fmpz_mod_poly_frobenius_powers_precomp(fmpz_mod_poly_frobenius_powers_t pow, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, ulong m, const fmpz_mod_ctx_t ctx) If ``p = f->p``, compute `x^{(p^0)}`, `x^{(p^1)}`, `x^{(p^2)}`, `x^{(p^3)}`, ..., `x^{(p^m)} \pmod{f}`. Requires precomputed inverse of `f`, i.e. newton inverse. .. function:: void fmpz_mod_poly_frobenius_powers_clear(fmpz_mod_poly_frobenius_powers_t pow, const fmpz_mod_ctx_t ctx) Clear resources used by the ``fmpz_mod_poly_frobenius_powers_t`` struct. Division -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible modulo `p`, and that ``invB`` is the inverse. Assumes that `\operatorname{len}(A), \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. `R` and `A` may be aliased, but apart from this no aliasing of input and output operands is allowed. .. function:: void fmpz_mod_poly_divrem_basecase(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible modulo `p`. .. function:: void _fmpz_mod_poly_divrem_newton_n_preinv (fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz * Binv, slong lenBinv, const fmpz_mod_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where `A` is of length ``lenA`` and `B` is of length ``lenB``. We require that `Q` have space for ``lenA - lenB + 1`` coefficients. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to call :func:`div_newton_n_preinv` and then multiply out and compute the remainder. .. function:: void fmpz_mod_poly_divrem_newton_n_preinv(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. We assume `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to call :func:`div_newton_n` and then multiply out and compute the remainder. .. function:: void _fmpz_mod_poly_div_newton_n_preinv (fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz * Binv, slong lenBinv, const fmpz_mod_ctx_t ctx) Notionally computes polynomials `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where ``A`` is of length ``lenA`` and ``B`` is of length ``lenB``, but return only `Q`. We require that `Q` have space for ``lenA - lenB + 1`` coefficients and assume that the leading coefficient of `B` is a unit. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void fmpz_mod_poly_div_newton_n_preinv(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx) Notionally computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only `Q`. We assume that the leading coefficient of `B` is a unit and that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: ulong fmpz_mod_poly_remove(fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) Removes the highest possible power of ``g`` from ``f`` and returns the exponent. .. function:: void _fmpz_mod_poly_rem_basecase(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)` but only sets ``(R, lenB - 1)``. Allows aliasing only between `A` and `R`. Allows zero-padding in `A` but not in `B`. Assumes that the leading coefficient of `B` is a unit modulo `p`. .. function:: void fmpz_mod_poly_rem_basecase(fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)` assuming that the leading term of `B` is a unit. .. function:: void _fmpz_mod_poly_div(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)` but only sets ``(Q, lenA - lenB + 1)``. Assumes that the leading coefficient of `B` is a unit modulo `p`. .. function:: void fmpz_mod_poly_div(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)` assuming that the leading term of `B` is a unit. .. function:: void _fmpz_mod_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenB - 1)`` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that `B` is non-zero, that the leading coefficient of `B` is invertible modulo `p` and that ``invB`` is the inverse. Assumes `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. No aliasing of input and output operands is allowed. .. function:: void fmpz_mod_poly_divrem(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Computes `Q`, `R` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that `B` is non-zero and that the leading coefficient of `B` is invertible modulo `p`. .. function:: void fmpz_mod_poly_divrem_f(fmpz_t f, fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Either finds a non-trivial factor~`f` of the modulus~`p`, or computes `Q`, `R` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. If the leading coefficient of `B` is invertible in `\mathbf{Z}/(p)`, the division with remainder operation is carried out, `Q` and `R` are computed correctly, and `f` is set to `1`. Otherwise, `f` is set to a non-trivial factor of `p` and `Q` and `R` are not touched. Assumes that `B` is non-zero. .. function:: void _fmpz_mod_poly_rem(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) Notationally, computes ``(Q, lenA - lenB + 1)``, ``(R, lenB - 1)`` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`, returning only the remainder part. Assumes that `B` is non-zero, that the leading coefficient of `B` is invertible modulo `p` and that ``invB`` is the inverse. Assumes `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. No aliasing of input and output operands is allowed. .. function:: void fmpz_mod_poly_rem_f(fmpz_t f, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) If `f` returns with the value `1` then the function operates as ``_fmpz_mod_poly_rem``, otherwise `f` will be set to a nontrivial factor of `p`. .. function:: void fmpz_mod_poly_rem(fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`, returning only the remainder part. Assumes that `B` is non-zero and that the leading coefficient of `B` is invertible modulo `p`. Divisibility testing -------------------------------------------------------------------------------- .. function:: int _fmpz_mod_poly_divides_classical(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) Returns `1` if `(B, lenB)` divides `(A, lenA)` and sets `(Q, lenA - lenB + 1)` to the quotient. Otherwise, returns `0` and sets `(Q, lenA - lenB + 1)` to zero. We require that `lenA >= lenB > 0`. .. function:: int fmpz_mod_poly_divides_classical(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Returns `1` if `B` divides `A` and sets `Q` to the quotient. Otherwise returns `0` and sets `Q` to zero. .. function:: int _fmpz_mod_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) Returns `1` if `(B, lenB)` divides `(A, lenA)` and sets `(Q, lenA - lenB + 1)` to the quotient. Otherwise, returns `0` and sets `(Q, lenA - lenB + 1)` to zero. We require that `lenA >= lenB > 0`. .. function:: int fmpz_mod_poly_divides(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Returns `1` if `B` divides `A` and sets `Q` to the quotient. Otherwise returns `0` and sets `Q` to zero. Power series inversion -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n, const fmpz_mod_ctx_t ctx) Sets ``(Qinv, n)`` to the inverse of ``(Q, n)`` modulo `x^n`, where `n \geq 1`, assuming that the bottom coefficient of `Q` is invertible modulo `p` and that its inverse is ``cinv``. .. function:: void fmpz_mod_poly_inv_series(fmpz_mod_poly_t Qinv, const fmpz_mod_poly_t Q, slong n, const fmpz_mod_ctx_t ctx) Sets ``Qinv`` to the inverse of ``Q`` modulo `x^n`, where `n \geq 1`, assuming that the bottom coefficient of `Q` is a unit. .. function:: void fmpz_mod_poly_inv_series_f(fmpz_t f, fmpz_mod_poly_t Qinv, const fmpz_mod_poly_t Q, slong n, const fmpz_mod_ctx_t ctx) Either sets `f` to a nontrivial factor of `p` with the value of ``Qinv`` undefined, or sets ``Qinv`` to the inverse of ``Q`` modulo `x^n`, where `n \geq 1`. Power series division -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n, const fmpz_mod_ctx_t ctx) Set ``(Q, n)`` to the quotient of the series ``(A, Alen``) and ``(B, Blen)`` assuming ``Alen, Blen <= n``. We assume the bottom coefficient of ``B`` is invertible modulo `p`. .. function:: void fmpz_mod_poly_div_series(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, slong n, const fmpz_mod_ctx_t ctx) Set `Q` to the quotient of the series `A` by `B`, thinking of the series as though they were of length `n`. We assume that the bottom coefficient of `B` is a unit. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_make_monic(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) If ``poly`` is non-zero, sets ``res`` to ``poly`` divided by its leading coefficient. This assumes that the leading coefficient of ``poly`` is invertible modulo `p`. Otherwise, if ``poly`` is zero, sets ``res`` to zero. .. function:: void fmpz_mod_poly_make_monic_f(fmpz_t f, fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Either set `f` to `1` and ``res`` to ``poly`` divided by its leading coefficient or set `f` to a nontrivial factor of `p` and leave ``res`` undefined. .. function:: slong _fmpz_mod_poly_gcd(fmpz * G, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) Sets `G` to the greatest common divisor of `(A, \operatorname{len}(A))` and `(B, \operatorname{len}(B))` and returns its length. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that the vector `G` has space for sufficiently many coefficients. Assumes that ``invB`` is the inverse of the leading coefficients of `B` modulo the prime number `p`. .. function:: void fmpz_mod_poly_gcd(fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Sets `G` to the greatest common divisor of `A` and `B`. In general, the greatest common divisor is defined in the polynomial ring `(\mathbf{Z}/(p \mathbf{Z}))[X]` if and only if `p` is a prime number. Thus, this function assumes that `p` is prime. .. function:: slong _fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz * G, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `(A, \operatorname{len}(A))` and `(B, \operatorname{len}(B))` and returns its length, or sets `f \in (1,p)` to a non-trivial factor of `p` and leaves the contents of the vector `(G, lenB)` undefined. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that the vector `G` has space for sufficiently many coefficients. Does not support aliasing of any of the input arguments with any of the output argument. .. function:: void fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `A` and `B`, or ` \in (1,p)` to a non-trivial factor of `p`. In general, the greatest common divisor is defined in the polynomial ring `(\mathbf{Z}/(p \mathbf{Z}))[X]` if and only if `p` is a prime number. .. function:: slong _fmpz_mod_poly_gcd_f(fmpz_t f, fmpz * G, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `(A, \operatorname{len}(A))` and `(B, \operatorname{len}(B))` and returns its length, or sets `f \in (1,p)` to a non-trivial factor of `p` and leaves the contents of the vector `(G, lenB)` undefined. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that the vector `G` has space for sufficiently many coefficients. Does not support aliasing of any of the input arguments with any of the output arguments. .. function:: void fmpz_mod_poly_gcd_f(fmpz_t f, fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `A` and `B`, or `f \in (1,p)` to a non-trivial factor of `p`. In general, the greatest common divisor is defined in the polynomial ring `(\mathbf{Z}/(p \mathbf{Z}))[X]` if and only if `p` is a prime number. .. function:: slong _fmpz_mod_poly_hgcd(fmpz **M, slong * lenM, fmpz * A, slong * lenA, fmpz * B, slong * lenB, const fmpz * a, slong lena, const fmpz * b, slong lenb, const fmpz_mod_ctx_t ctx) Computes the HGCD of `a` and `b`, that is, a matrix~`M`, a sign~`\sigma` and two polynomials `A` and `B` such that .. math:: (A,B)^t = \sigma M^{-1} (a,b)^t. Assumes that `\operatorname{len}(a) > \operatorname{len}(b) > 0`. Assumes that `A` and `B` have space of size at least `\operatorname{len}(a)` and `\operatorname{len}(b)`, respectively. On exit, ``*lenA`` and ``*lenB`` will contain the correct lengths of `A` and `B`. Assumes that ``M[0]``, ``M[1]``, ``M[2]``, and ``M[3]`` each point to a vector of size at least `\operatorname{len}(a)`. .. function:: slong _fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz * G, fmpz * S, fmpz * T, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) If `f` returns with the value `1` then the function operates as per ``_fmpz_mod_poly_xgcd_euclidean``, otherwise `f` is set to a nontrivial factor of `p`. .. function:: void fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) If `f` returns with the value `1` then the function operates as per ``fmpz_mod_poly_xgcd_euclidean``, otherwise `f` is set to a nontrivial factor of `p`. .. function:: slong _fmpz_mod_poly_xgcd(fmpz * G, fmpz * S, fmpz * T, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) Computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void fmpz_mod_poly_xgcd(fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. .. function:: void fmpz_mod_poly_xgcd_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) If `f` returns with the value `1` then the function operates as per ``fmpz_mod_poly_xgcd``, otherwise `f` is set to a nontrivial factor of `p`. .. function:: slong _fmpz_mod_poly_gcdinv_euclidean(fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx) Computes ``(G, lenA)``, ``(S, lenB-1)`` such that `G \cong S A \pmod{B}`, returning the actual length of `G`. Assumes that `0 < \operatorname{len}(A) < \operatorname{len}(B)`. .. function:: void fmpz_mod_poly_gcdinv_euclidean(fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Computes polynomials `G` and `S`, both reduced modulo~`B`, such that `G \cong S A \pmod{B}`, where `B` is assumed to have `\operatorname{len}(B) \geq 2`. In the case that `A = 0 \pmod{B}`, returns `G = S = 0`. .. function:: slong _fmpz_mod_poly_gcdinv_euclidean_f(fmpz_t f, fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx) If `f` returns with value `1` then the function operates as per :func:`_fmpz_mod_poly_gcdinv_euclidean`, otherwise `f` is set to a nontrivial factor of `p`. .. function:: void fmpz_mod_poly_gcdinv_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) If `f` returns with value `1` then the function operates as per :func:`fmpz_mod_poly_gcdinv_euclidean`, otherwise `f` is set to a nontrivial factor of the modulus of `A`. .. function:: slong _fmpz_mod_poly_gcdinv(fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) Computes ``(G, lenA)``, ``(S, lenB-1)`` such that `G \cong S A \pmod{B}`, returning the actual length of `G`. Assumes that `0 < \operatorname{len}(A) < \operatorname{len}(B)`. .. function:: slong _fmpz_mod_poly_gcdinv_f(fmpz_t f, fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) If `f` returns with value `1` then the function operates as per :func:`_fmpz_mod_poly_gcdinv`, otherwise `f` will be set to a nontrivial factor of `p`. .. function:: void fmpz_mod_poly_gcdinv(fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) Computes polynomials `G` and `S`, both reduced modulo~`B`, such that `G \cong S A \pmod{B}`, where `B` is assumed to have `\operatorname{len}(B) \geq 2`. In the case that `A = 0 \pmod{B}`, returns `G = S = 0`. .. function:: void fmpz_mod_poly_gcdinv_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) If `f` returns with value `1` then the function operates as per :func:`fmpz_mod_poly_gcdinv`, otherwise `f` will be set to a nontrivial factor of `p`. .. function:: int _fmpz_mod_poly_invmod(fmpz * A, const fmpz * B, slong lenB, const fmpz * P, slong lenP, const fmpz_mod_ctx_t ctx) Attempts to set ``(A, lenP-1)`` to the inverse of ``(B, lenB)`` modulo the polynomial ``(P, lenP)``. Returns `1` if ``(B, lenB)`` is invertible and `0` otherwise. Assumes that `0 < \operatorname{len}(B) < \operatorname{len}(P)`, and hence also `\operatorname{len}(P) \geq 2`, but supports zero-padding in ``(B, lenB)``. Does not support aliasing. Assumes that `p` is a prime number. .. function:: int _fmpz_mod_poly_invmod_f(fmpz_t f, fmpz * A, const fmpz * B, slong lenB, const fmpz * P, slong lenP, const fmpz_mod_ctx_t ctx) If `f` returns with the value `1`, then the function operates as per :func:`_fmpz_mod_poly_invmod`. Otherwise `f` is set to a nontrivial factor of `p`. .. function:: int fmpz_mod_poly_invmod(fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx) Attempts to set `A` to the inverse of `B` modulo `P` in the polynomial ring `(\mathbf{Z}/p\mathbf{Z})[X]`, where we assume that `p` is a prime number. If `\deg(P) < 2`, raises an exception. If the greatest common divisor of `B` and `P` is~`1`, returns~`1` and sets `A` to the inverse of `B`. Otherwise, returns~`0` and the value of `A` on exit is undefined. .. function:: int fmpz_mod_poly_invmod_f(fmpz_t f, fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx) If `f` returns with the value `1`, then the function operates as per :func:`fmpz_mod_poly_invmod`. Otherwise `f` is set to a nontrivial factor of `p`. Minpoly -------------------------------------------------------------------------------- .. function:: slong _fmpz_mod_poly_minpoly_bm(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) Sets ``poly`` to the coefficients of a minimal generating polynomial for sequence ``(seq, len)`` modulo `p`. The return value equals the length of ``poly``. It is assumed that `p` is prime and ``poly`` has space for at least `len+1` coefficients. No aliasing between inputs and outputs is allowed. .. function:: void fmpz_mod_poly_minpoly_bm(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) Sets ``poly`` to a minimal generating polynomial for sequence ``seq`` of length ``len``. Assumes that the modulus is prime. This version uses the Berlekamp-Massey algorithm, whose running time is proportional to ``len`` times the size of the minimal generator. .. function:: slong _fmpz_mod_poly_minpoly_hgcd(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) Sets ``poly`` to the coefficients of a minimal generating polynomial for sequence ``(seq, len)`` modulo `p`. The return value equals the length of ``poly``. It is assumed that `p` is prime and ``poly`` has space for at least `len+1` coefficients. No aliasing between inputs and outputs is allowed. .. function:: void fmpz_mod_poly_minpoly_hgcd(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) Sets ``poly`` to a minimal generating polynomial for sequence ``seq`` of length ``len``. Assumes that the modulus is prime. This version uses the HGCD algorithm, whose running time is `O(n \log^2 n)` field operations, regardless of the actual size of the minimal generator. .. function:: slong _fmpz_mod_poly_minpoly(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) Sets ``poly`` to the coefficients of a minimal generating polynomial for sequence ``(seq, len)`` modulo `p`. The return value equals the length of ``poly``. It is assumed that `p` is prime and ``poly`` has space for at least `len+1` coefficients. No aliasing between inputs and outputs is allowed. .. function:: void fmpz_mod_poly_minpoly(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) Sets ``poly`` to a minimal generating polynomial for sequence ``seq`` of length ``len``. A minimal generating polynomial is a monic polynomial `f = x^d + c_{d-1}x^{d-1} + \cdots + c_1 x + c_0`, of minimal degree `d`, that annihilates any consecutive `d+1` terms in ``seq``. That is, for any `i < len - d`, `seq_i = -\sum_{j=0}^{d-1} seq_{i+j}*f_j.` Assumes that the modulus is prime. This version automatically chooses the fastest underlying implementation based on ``len`` and the size of the modulus. Resultant -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx) Returns the resultant of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``len1 >= len2 > 0``. The complexity is only guaranteed to be quasilinear if the modulus is prime. .. function:: void fmpz_mod_poly_resultant(fmpz_t res, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) Computes the resultant of $f$ and $g$. Discriminant -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx) Set `d` to the discriminant of ``(poly, len)``. Assumes ``len > 1``. .. function:: void fmpz_mod_poly_discriminant(fmpz_t d, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Set `d` to the discriminant of `f`. We normalise the discriminant so that `\operatorname{disc}(f) = (-1)^(n(n-1)/2) \operatorname{res}(f, f') / \operatorname{lc}(f)^(n - m - 2)`, where ``n = len(f)`` and ``m = len(f')``. Thus `\operatorname{disc}(f) = \operatorname{lc}(f)^(2n - 2) \prod_{i < j} (r_i - r_j)^2`, where `\operatorname{lc}(f)` is the leading coefficient of `f` and `r_i` are the roots of `f`. Derivative -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_derivative(fmpz * res, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx) Sets ``(res, len - 1)`` to the derivative of ``(poly, len)``. Also handles the cases where ``len`` is `0` or `1` correctly. Supports aliasing of ``res`` and ``poly``. .. function:: void fmpz_mod_poly_derivative(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Sets ``res`` to the derivative of ``poly``. Evaluation -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz * poly, slong len, const fmpz_t a, const fmpz_mod_ctx_t ctx) Evaluates the polynomial ``(poly, len)`` at the integer `a` and sets ``res`` to the result. Aliasing between ``res`` and `a` or any of the coefficients of ``poly`` is not supported. .. function:: void fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz_mod_poly_t poly, const fmpz_t a, const fmpz_mod_ctx_t ctx) Evaluates the polynomial ``poly`` at the integer `a` and sets ``res`` to the result. As expected, aliasing between ``res`` and `a` is supported. However, ``res`` may not be aliased with a coefficient of ``poly``. Multipoint evaluation -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Evaluates (``coeffs``, ``len``) at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses Horner's method iteratively. .. function:: void fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Evaluates ``poly`` at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses Horner's method iteratively. .. function:: void _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp(fmpz * vs, const fmpz * poly, slong plen, fmpz_poly_struct * const * tree, slong len, const fmpz_mod_ctx_t ctx) Evaluates (``poly``, ``plen``) at the ``len`` values given by the precomputed subproduct tree ``tree``. .. function:: void _fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz * poly, slong plen, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Evaluates (``coeffs``, ``len``) at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses fast multipoint evaluation, building a temporary subproduct tree. .. function:: void fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Evaluates ``poly`` at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses fast multipoint evaluation, building a temporary subproduct tree. .. function:: void _fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Evaluates (``coeffs``, ``len``) at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. .. function:: void fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) Evaluates ``poly`` at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Composition -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_compose(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``res`` has space for ``(len1-1)*(len2-1) + 1`` coefficients, although in `\mathbf{Z}_p[X]` this might not actually be the length of the resulting polynomial when `p` is not a prime. Assumes that ``poly1`` and ``poly2`` are non-zero polynomials. Does not support aliasing between any of the inputs and the output. .. function:: void fmpz_mod_poly_compose(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition of ``poly1`` and ``poly2``. To be precise about the order of composition, denoting ``res``, ``poly1``, and ``poly2`` by `f`, `g`, and `h`, respectively, sets `f(t) = g(h(t))`. Square roots -------------------------------------------------------------------------------- The series expansions for `\sqrt{h}` and `1/\sqrt{h}` are defined by means of the generalised binomial theorem ``h^r = (1+y)^r = \sum_{k=0}^{\infty} {r \choose k} y^k.`` It is assumed that `h` has constant term `1` and that the coefficients `2^{-k}` exist in the coefficient ring (i.e. `2` must be invertible). .. function:: void _fmpz_mod_poly_invsqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t ctx) Set the first `n` terms of `g` to the series expansion of `1/\sqrt{h}`. It is assumed that `n > 0` and `h > 0`. Aliasing is not permitted. .. function:: void fmpz_mod_poly_invsqrt_series(fmpz_mod_poly_t g, const fmpz_mod_poly_t h, slong n, const fmpz_mod_ctx_t ctx) Set `g` to the series expansion of `1/\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: void _fmpz_mod_poly_sqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t ctx) Set the first `n` terms of `g` to the series expansion of `\sqrt{h}`. It is assumed that `n > 0` and `h > 0`. Aliasing is not permitted. .. function:: void fmpz_mod_poly_sqrt_series(fmpz_mod_poly_t g, const fmpz_mod_poly_t h, slong n, const fmpz_mod_ctx_t ctx) Set `g` to the series expansion of `\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: int _fmpz_mod_poly_sqrt(fmpz * s, const fmpz * p, slong n, const fmpz_mod_ctx_t ctx) If ``(p, n)`` is a perfect square, sets ``(s, n / 2 + 1)`` to a square root of `p` and returns 1. Otherwise returns 0. .. function:: int fmpz_mod_poly_sqrt(fmpz_mod_poly_t s, const fmpz_mod_poly_t p, const fmpz_mod_ctx_t ctx) If `p` is a perfect square, sets `s` to a square root of `p` and returns 1. Otherwise returns 0. Modular composition -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_compose_mod(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. .. function:: void fmpz_mod_poly_compose_mod(fmpz_mod_poly_t res, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_poly_t h, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. .. function:: void _fmpz_mod_poly_compose_mod_horner(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void fmpz_mod_poly_compose_mod_horner(fmpz_mod_poly_t res, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_poly_t h, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. The algorithm used is Horner's rule. .. function:: void _fmpz_mod_poly_compose_mod_brent_kung(fmpz * res, const fmpz * f, slong len1, const fmpz * g, const fmpz * h, slong len3, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fmpz_mod_poly_compose_mod_brent_kung(fmpz_mod_poly_t res, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_poly_t h, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fmpz_mod_poly_reduce_matrix_mod_poly (fmpz_mat_t A, const fmpz_mat_t B, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Sets the ith row of ``A`` to the reduction of the ith row of `B` modulo `f` for `i=1,\ldots,\sqrt{\deg(f)}`. We require `B` to be at least a `\sqrt{\deg(f)}\times \deg(f)` matrix and `f` to be nonzero. .. function:: void _fmpz_mod_poly_precompute_matrix_worker(void * arg_ptr) Worker function version of ``_fmpz_mod_poly_precompute_matrix``. Input/output is stored in ``fmpz_mod_poly_matrix_precompute_arg_t``. .. function:: void _fmpz_mod_poly_precompute_matrix (fmpz_mat_t A, const fmpz * f, const fmpz * g, slong leng, const fmpz * ginv, slong lenginv, const fmpz_mod_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g`` and `g` to be nonzero. ``f`` has to be reduced modulo ``g`` and of length one less than ``leng`` (possibly with zero padding). .. function:: void fmpz_mod_poly_precompute_matrix(fmpz_mat_t A, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_poly_t ginv, const fmpz_mod_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g``. .. function:: void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr) Worker function version of :func:`_fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv`. Input/output is stored in ``fmpz_mod_poly_compose_mod_precomp_preinv_arg_t``. .. function:: void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz * res, const fmpz * f, slong lenf, const fmpz_mat_t A, const fmpz * h, slong lenh, const fmpz * hinv, slong lenhinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t f, const fmpz_mat_t A, const fmpz_mod_poly_t h, const fmpz_mod_poly_t hinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. This version of Brent-Kung modular composition is particularly useful if one has to perform several modular composition of the form `f(g)` modulo `h` for fixed `g` and `h`. .. function:: void _fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz * hinv, slong lenhinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_poly_t h, const fmpz_mod_poly_t hinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong l, const fmpz * g, slong glen, const fmpz * h, slong lenh, const fmpz * hinv, slong lenhinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f_i(g)` modulo `h` for `1\leq i \leq l`, where `f_i` are the ``l`` elements of ``polys``. We require that `h` is nonzero and that the length of `g` is less than the length of `h`. We also require that the length of `f_i` is less than the length of `h`. We require ``res`` to have enough memory allocated to hold ``l`` ``fmpz_mod_poly_struct``'s. The entries of ``res`` need to be initialised and ``l`` needs to be less than ``len1`` Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t h, const fmpz_mod_poly_t hinv, const fmpz_mod_ctx_t ctx) Sets ``res`` to the composition `f_i(g)` modulo `h` for `1\leq i \leq n` where `f_i` are the ``n`` elements of ``polys``. We require ``res`` to have enough memory allocated to hold ``n`` ``fmpz_mod_poly_struct``'s. The entries of ``res`` need to be initialised and ``n`` needs to be less than ``len1``. We require that `h` is nonzero and that `f_i` and `g` have smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. No aliasing of ``res`` and ``polys`` is allowed. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong lenpolys, slong l, const fmpz * g, slong glen, const fmpz * poly, slong len, const fmpz * polyinv, slong leninv, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads) Multithreaded version of :func:`_fmpz_mod_poly_compose_mod_brent_kung_vec_preinv`. Distributing the Horner evaluations across :func:`flint_get_num_threads` threads. .. function:: void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads) Multithreaded version of :func:`fmpz_mod_poly_compose_mod_brent_kung_vec_preinv`. Distributing the Horner evaluations across :func:`flint_get_num_threads` threads. .. function:: void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx) Multithreaded version of :func:`fmpz_mod_poly_compose_mod_brent_kung_vec_preinv`. Distributing the Horner evaluations across :func:`flint_get_num_threads` threads. Subproduct trees -------------------------------------------------------------------------------- .. function:: fmpz_poly_struct ** _fmpz_mod_poly_tree_alloc(slong len) Allocates space for a subproduct tree of the given length, having linear factors at the lowest level. .. function:: void _fmpz_mod_poly_tree_free(fmpz_poly_struct ** tree, slong len) Free the allocated space for the subproduct. .. function:: void _fmpz_mod_poly_tree_build(fmpz_poly_struct ** tree, const fmpz * roots, slong len, const fmpz_mod_ctx_t ctx) Builds a subproduct tree in the preallocated space from the ``len`` monic linear factors `(x-r_i)` where `r_i` are given by ``roots``. The top level product is not computed. Radix conversion -------------------------------------------------------------------------------- The following functions provide the functionality to solve the radix conversion problems for polynomials, which is to express a polynomial `f(X)` with respect to a given radix `r(X)` as .. math:: f(X) = \sum_{i = 0}^{N} b_i(X) r(X)^i where `N = \lfloor\deg(f) / \deg(r)\rfloor`. The algorithm implemented here is a recursive one, which performs Euclidean divisions by powers of `r` of the form `r^{2^i}`, and it has time complexity `\Theta(\deg(f) \log \deg(f))`. It facilitates the repeated use of precomputed data, namely the powers of `r` and their power series inverses. This data is stored in objects of type ``fmpz_mod_poly_radix_t`` and it is computed using the function :func:`fmpz_mod_poly_radix_init`, which only depends on~`r` and an upper bound on the degree of~`f`. .. function:: void _fmpz_mod_poly_radix_init(fmpz **Rpow, fmpz **Rinv, const fmpz * R, slong lenR, slong k, const fmpz_t invL, const fmpz_mod_ctx_t ctx) Computes powers of `R` of the form `R^{2^i}` and their Newton inverses modulo `x^{2^{i} \deg(R)}` for `i = 0, \dotsc, k-1`. Assumes that the vectors ``Rpow[i]`` and ``Rinv[i]`` have space for `2^i \deg(R) + 1` and `2^i \deg(R)` coefficients, respectively. Assumes that the polynomial `R` is non-constant, i.e. `\deg(R) \geq 1`. Assumes that the leading coefficient of `R` is a unit and that the argument ``invL`` is the inverse of the coefficient modulo~`p`. The argument~`p` is the modulus, which in `p`-adic applications is typically a prime power, although this is not necessary. Here, we only assume that `p \geq 2`. Note that this precomputed data can be used for any `F` such that `\operatorname{len}(F) \leq 2^k \deg(R)`. .. function:: void fmpz_mod_poly_radix_init(fmpz_mod_poly_radix_t D, const fmpz_mod_poly_t R, slong degF, const fmpz_mod_ctx_t ctx) Carries out the precomputation necessary to perform radix conversion to radix~`R` for polynomials~`F` of degree at most ``degF``. Assumes that `R` is non-constant, i.e. `\deg(R) \geq 1`, and that the leading coefficient is a unit. .. function:: void _fmpz_mod_poly_radix(fmpz **B, const fmpz * F, fmpz **Rpow, fmpz **Rinv, slong degR, slong k, slong i, fmpz * W, const fmpz_mod_ctx_t ctx) This is the main recursive function used by the function :func:`fmpz_mod_poly_radix`. Assumes that, for all `i = 0, \dotsc, N`, the vector ``B[i]`` has space for `\deg(R)` coefficients. The variable `k` denotes the factors of `r` that have previously been counted for the polynomial `F`, which is assumed to have length `2^{i+1} \deg(R)`, possibly including zero-padding. Assumes that `W` is a vector providing temporary space of length `\operatorname{len}(F) = 2^{i+1} \deg(R)`. The entire computation takes place over `\mathbf{Z} / p \mathbf{Z}`, where `p \geq 2` is a natural number. Thus, the top level call will have `F` as in the original problem, and `k = 0`. .. function:: void fmpz_mod_poly_radix(fmpz_mod_poly_struct **B, const fmpz_mod_poly_t F, const fmpz_mod_poly_radix_t D, const fmpz_mod_ctx_t ctx) Given a polynomial `F` and the precomputed data `D` for the radix `R`, computes polynomials `B_0, \dotsc, B_N` of degree less than `\deg(R)` such that .. math:: F = B_0 + B_1 R + \dotsb + B_N R^N, where necessarily `N = \lfloor\deg(F) / \deg(R)\rfloor`. Assumes that `R` is non-constant, i.e.\ `\deg(R) \geq 1`, and that the leading coefficient is a unit. Input and output -------------------------------------------------------------------------------- The printing options supported by this module are very similar to what can be found in the two related modules ``fmpz_poly`` and ``nmod_poly``. Consider, for example, the polynomial `f(x) = 5x^3 + 2x + 1` in `(\mathbf{Z}/6\mathbf{Z})[x]`. Its simple string representation is ``"4 6 1 2 0 5"``, where the first two numbers denote the length of the polynomial and the modulus. The pretty string representation is ``"5*x^3+2*x+1"``. .. function:: int _fmpz_mod_poly_fprint(FILE * file, const fmpz * poly, slong len, const fmpz_t p) Prints the polynomial ``(poly, len)`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_mod_poly_fprint(FILE * file, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Prints the polynomial to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_mod_poly_fprint_pretty(FILE * file, const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_mod_poly_print(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Prints the polynomial to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_mod_poly_print_pretty(const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx) Prints the pretty representation of ``poly`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. Inflation and deflation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_inflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong inflation, const fmpz_mod_ctx_t ctx) Sets ``result`` to the inflated polynomial `p(x^n)` where `p` is given by ``input`` and `n` is given by ``inflation``. .. function:: void fmpz_mod_poly_deflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong deflation, const fmpz_mod_ctx_t ctx) Sets ``result`` to the deflated polynomial `p(x^{1/n})` where `p` is given by ``input`` and `n` is given by ``deflation``. Requires `n > 0`. .. function:: ulong fmpz_mod_poly_deflation(const fmpz_mod_poly_t input, const fmpz_mod_ctx_t ctx) Returns the largest integer by which ``input`` can be deflated. As special cases, returns 0 if ``input`` is the zero polynomial and 1 of ``input`` is a constant polynomial. Berlekamp-Massey Algorithm -------------------------------------------------------------------------------- The fmpz_mod_berlekamp_massey_t manages an unlimited stream of points `a_1, a_2, \dots .` At any point in time, after, say, `n` points have been added, a call to :func:`fmpz_mod_berlekamp_massey_reduce` will calculate the polynomials `U`, `V` and `R` in the extended euclidean remainder sequence with .. math:: U*x^n + V*(a_1*x^{n-1} + \cdots + a_{n-1}*x + a_n) = R, \quad \deg(U) < \deg(V) \le n/2, \quad \deg(R) < n/2. The polynomials `V` and `R` may be obtained with :func:`fmpz_mod_berlekamp_massey_V_poly` and :func:`fmpz_mod_berlekamp_massey_R_poly`. This class differs from :func:`fmpz_mod_poly_minpoly` in the following respect. Let `v_i` denote the coefficient of `x^i` in `V`. :func:`fmpz_mod_poly_minpoly` will return a polynomial `V` of lowest degree that annihilates the whole sequence `a_1, \dots, a_n` as .. math:: \sum_{i} v_i a_{j + i} = 0, \quad 1 \le j \le n - \deg(V). The cost is that a polynomial of degree `n-1` might be returned and the return is not generally uniquely determined by the input sequence. For the fmpz_mod_berlekamp_massey_t we have .. math:: \sum_{i,j} v_i a_{j+i} x^{-j} = -U + \frac{R}{x^n}\text{,} and it can be seen that `\sum_{i} v_i a_{j + i}` is zero for `1 \le j < n - \deg(R)`. Thus whether or not `V` has annihilated the whole sequence may be checked by comparing the degrees of `V` and `R`. .. function:: void fmpz_mod_berlekamp_massey_init(fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) Initialize ``B`` with an empty stream. .. function:: void fmpz_mod_berlekamp_massey_clear(fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) Free any space used by ``B``. .. function:: void fmpz_mod_berlekamp_massey_start_over(fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) Empty the stream of points in ``B``. .. function:: void fmpz_mod_berlekamp_massey_add_points(fmpz_mod_berlekamp_massey_t B, const fmpz * a, slong count, const fmpz_mod_ctx_t ctx) void fmpz_mod_berlekamp_massey_add_zeros(fmpz_mod_berlekamp_massey_t B, slong count, const fmpz_mod_ctx_t ctx) void fmpz_mod_berlekamp_massey_add_point(fmpz_mod_berlekamp_massey_t B, const fmpz_t a, const fmpz_mod_ctx_t ctx) Add point(s) to the stream processed by ``B``. The addition of any number of points will not update the `V` and `R` polynomial. .. function:: int fmpz_mod_berlekamp_massey_reduce(fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) Ensure that the polynomials `V` and `R` are up to date. The return value is ``1`` if this function changed `V` and ``0`` otherwise. For example, if this function is called twice in a row without adding any points in between, the return of the second call should be ``0``. As another example, suppose the object is emptied, the points `1, 1, 2, 3` are added, then reduce is called. This reduce should return ``1`` with `\deg(R) < \deg(V) = 2` because the Fibonacci sequence has been recognized. The further addition of the two points `5, 8` and a reduce will result in a return value of ``0``. .. function:: slong fmpz_mod_berlekamp_massey_point_count(const fmpz_mod_berlekamp_massey_t B) Return the number of points stored in ``B``. .. function:: const fmpz * fmpz_mod_berlekamp_massey_points(const fmpz_mod_berlekamp_massey_t B) Return a pointer the array of points stored in ``B``. This may be ``NULL`` if func::fmpz_mod_berlekamp_massey_point_count returns ``0``. .. function:: const fmpz_mod_poly_struct * fmpz_mod_berlekamp_massey_V_poly(const fmpz_mod_berlekamp_massey_t B) Return the polynomial ``V`` in ``B``. .. function:: const fmpz_mod_poly_struct * fmpz_mod_berlekamp_massey_R_poly(const fmpz_mod_berlekamp_massey_t B) Return the polynomial ``R`` in ``B``. flint-3.1.3/doc/source/fmpz_mod_poly_factor.rst000066400000000000000000000232161461254215100216520ustar00rootroot00000000000000.. _fmpz-mod-poly-factor: **fmpz_mod_poly_factor.h** -- factorisation of polynomials over integers mod n ================================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mod_poly_factor_struct A structure representing a polynomial in factorised form as a product of polynomials with associated exponents. .. type:: fmpz_mod_poly_factor_t An array of length 1 of ``fmpz_mpoly_factor_struct``. Factorisation -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_factor_init(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) Initialises ``fac`` for use. .. function:: void fmpz_mod_poly_factor_clear(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) Frees all memory associated with ``fac``. .. function:: void fmpz_mod_poly_factor_realloc(fmpz_mod_poly_factor_t fac, slong alloc, const fmpz_mod_ctx_t ctx) Reallocates the factor structure to provide space for precisely ``alloc`` factors. .. function:: void fmpz_mod_poly_factor_fit_length(fmpz_mod_poly_factor_t fac, slong len, const fmpz_mod_ctx_t ctx) Ensures that the factor structure has space for at least ``len`` factors. This function takes care of the case of repeated calls by always at least doubling the number of factors the structure can hold. .. function:: void fmpz_mod_poly_factor_set(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) Sets ``res`` to the same factorisation as ``fac``. .. function:: void fmpz_mod_poly_factor_print(const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) Prints the entries of ``fac`` to standard output. .. function:: void fmpz_mod_poly_factor_insert(fmpz_mod_poly_factor_t fac, const fmpz_mod_poly_t poly, slong exp, const fmpz_mod_ctx_t ctx) Inserts the factor ``poly`` with multiplicity ``exp`` into the factorisation ``fac``. If ``fac`` already contains ``poly``, then ``exp`` simply gets added to the exponent of the existing entry. .. function:: void fmpz_mod_poly_factor_concat(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) Concatenates two factorisations. This is equivalent to calling :func:`fmpz_mod_poly_factor_insert` repeatedly with the individual factors of ``fac``. Does not support aliasing between ``res`` and ``fac``. .. function:: void fmpz_mod_poly_factor_pow(fmpz_mod_poly_factor_t fac, slong exp, const fmpz_mod_ctx_t ctx) Raises ``fac`` to the power ``exp``. .. function:: int fmpz_mod_poly_is_irreducible(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. .. function:: int fmpz_mod_poly_is_irreducible_ddf(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses fast distinct-degree factorisation. .. function:: int fmpz_mod_poly_is_irreducible_rabin(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses Rabin irreducibility test. .. function:: int fmpz_mod_poly_is_irreducible_rabin_f(fmpz_t r, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Either sets `r` to `1` and returns 1 if the polynomial ``f`` is irreducible or `0` otherwise, or sets `r` to a nontrivial factor of `p`. This algorithm correctly determines whether `f` is irreducible over `\mathbb{Z}/p\mathbb{Z}`, even for composite `f`, or it finds a factor of `p`. .. function:: int _fmpz_mod_poly_is_squarefree(const fmpz * f, slong len, const fmpz_mod_ctx_t ctx) Returns 1 if ``(f, len)`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. There are no restrictions on the length. .. function:: int _fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz * f, slong len, const fmpz_mod_ctx_t ctx) If `fac` returns with the value `1` then the function operates as per :func:`_fmpz_mod_poly_is_squarefree`, otherwise `f` is set to a nontrivial factor of `p`. .. function:: int fmpz_mod_poly_is_squarefree(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Returns 1 if ``f`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. .. function:: int fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) If `fac` returns with the value `1` then the function operates as per :func:`fmpz_mod_poly_is_squarefree`, otherwise `f` is set to a nontrivial factor of `p`. .. function:: int fmpz_mod_poly_factor_equal_deg_prob(fmpz_mod_poly_t factor, flint_rand_t state, const fmpz_mod_poly_t pol, slong d, const fmpz_mod_ctx_t ctx) Probabilistic equal degree factorisation of ``pol`` into irreducible factors of degree ``d``. If it passes, a factor is placed in ``factor`` and 1 is returned, otherwise 0 is returned and the value of factor is undetermined. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fmpz_mod_poly_factor_equal_deg(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t pol, slong d, const fmpz_mod_ctx_t ctx) Assuming ``pol`` is a product of irreducible factors all of degree ``d``, finds all those factors and places them in factors. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fmpz_mod_poly_factor_distinct_deg(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const * degs, const fmpz_mod_ctx_t ctx) Factorises a monic non-constant squarefree polynomial ``poly`` of degree `n` into factors `f[d]` such that for `1 \leq d \leq n` `f[d]` is the product of the monic irreducible factors of ``poly`` of degree `d`. Factors `f[d]` are stored in ``res``, and the degree `d` of the irreducible factors is stored in ``degs`` in the same order as the factors. Requires that ``degs`` has enough space for `(n/2)+1 * sizeof(slong)`. .. function:: void fmpz_mod_poly_factor_distinct_deg_threaded(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const * degs, const fmpz_mod_ctx_t ctx) Multithreaded version of :func:`fmpz_mod_poly_factor_distinct_deg`. .. function:: void fmpz_mod_poly_factor_squarefree(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Sets ``res`` to a squarefree factorization of ``f``. .. function:: void fmpz_mod_poly_factor(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors choosing the best algorithm for given modulo and degree. Choice is based on heuristic measurements. .. function:: void fmpz_mod_poly_factor_cantor_zassenhaus(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Cantor-Zassenhaus algorithm. .. function:: void fmpz_mod_poly_factor_kaltofen_shoup(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) Factorises a non-constant polynomial ``poly`` into monic irreducible factors using the fast version of Cantor-Zassenhaus algorithm proposed by Kaltofen and Shoup (1998). More precisely this algorithm uses a baby step/giant step strategy for the distinct-degree factorization step. If :func:`flint_get_num_threads` is greater than one :func:`fmpz_mod_poly_factor_distinct_deg_threaded` is used. .. function:: void fmpz_mod_poly_factor_berlekamp(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Berlekamp algorithm. .. function:: void _fmpz_mod_poly_interval_poly_worker(void * arg_ptr) Worker function to compute interval polynomials in distinct degree factorisation. Input/output is stored in :type:`fmpz_mod_poly_interval_poly_arg_t`. Root Finding -------------------------------------------------------------------------------- .. function:: void fmpz_mod_poly_roots(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_mod_ctx_t ctx) Fill `r` with factors of the form `x - r_i` where the `r_i` are the distinct roots of a nonzero `f` in `Z/pZ`. It is expected and not checked that the modulus of `ctx` is prime. If `with\_multiplicity` is zero, the exponent `e_i` of the factor `x - r_i` is `1`. Otherwise, it is the largest `e_i` such that `(x-r_i)^e_i` divides `f`. This function throws if `f` is zero, but is otherwise always successful. .. function:: int fmpz_mod_poly_roots_factored(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_factor_t n, const fmpz_mod_ctx_t ctx) Fill `r` with factors of the form `x - r_i` where the `r_i` are the distinct roots of a nonzero `f` in `Z/nZ`. It is expected and not checked that `n` is a prime factorization of the modulus of `ctx`. If `with\_multiplicity` is zero, the exponent `e_i` of the factor `x - r_i` is `1`. Otherwise, it is the largest `e_i` such that `(x-r_i)^e_i` divides `f`. The roots are first found modulo the primes in `n`, then lifted to the corresponding prime powers, then combined into roots of the original polynomial `f`. A return of `1` indicates the function was successful. A return of `0` indicates the function was not able to find the roots, possibly because there are too many of them. This function throws if `f` is zero. flint-3.1.3/doc/source/fmpz_mod_vec.rst000066400000000000000000000046321461254215100201070ustar00rootroot00000000000000.. _fmpz-mod-vec: **fmpz_mod_vec.h** -- vectors over integers mod n =============================================================================== Conversions -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_vec_set_fmpz_vec(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) Set the `fmpz_mod_vec` `(A, len)` to the `fmpz_vec` `(B, len)` after reduction of each entry modulo the modulus.. Arithmetic -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_vec_neg(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) Set `(A, len)` to `-(B, len)`. .. function:: void _fmpz_mod_vec_add(fmpz * a, const fmpz * b, const fmpz * c, slong n, const fmpz_mod_ctx_t ctx) Set (A, len)` to `(B, len) + (C, len)`. .. function:: void _fmpz_mod_vec_sub(fmpz * a, const fmpz * b, const fmpz * c, slong n, const fmpz_mod_ctx_t ctx) Set (A, len)` to `(B, len) - (C, len)`. Scalar Multiplication -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_vec_scalar_mul_fmpz_mod(fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx) Set `(A, len)` to `(B, len)*c`. .. function:: void _fmpz_mod_vec_scalar_addmul_fmpz_mod(fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx) Set `(A, len)` to `(A, len) + (B, len)*c`. .. function:: void _fmpz_mod_vec_scalar_div_fmpz_mod(fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx) Set `(A, len)` to `(B, len)/c` assuming `c` is nonzero. Dot Product -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_vec_dot(fmpz_t d, const fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) Set `d` to the dot product of `(A, len)` with `(B, len)`. .. function:: void _fmpz_mod_vec_dot_rev(fmpz_t d, const fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) Set `d` to the dot product of `(A, len)` with the reverse of the vector `(B, len)`. Multiplication -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_vec_mul(fmpz * A, const fmpz * B, const fmpz * C, slong len, const fmpz_mod_ctx_t ctx) Set `(A, len)` the pointwise multiplication of `(B, len)` and `(C, len)`. flint-3.1.3/doc/source/fmpz_mpoly.rst000066400000000000000000001560351461254215100176400ustar00rootroot00000000000000.. _fmpz-mpoly: **fmpz_mpoly.h** -- multivariate polynomials over the integers =============================================================================== The exponents follow the ``mpoly`` interface. A coefficient may be referenced as a ``fmpz *``. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mpoly_struct A structure holding a multivariate integer polynomial. .. type:: fmpz_mpoly_t An array of length `1` of ``fmpz_mpoly_struct``. .. type:: fmpz_mpoly_ctx_struct Context structure representing the parent ring of an ``fmpz_mpoly``. .. type:: fmpz_mpoly_ctx_t An array of length `1` of ``fmpz_mpoly_ctx_struct``. Context object -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_ctx_init(fmpz_mpoly_ctx_t ctx, slong nvars, const ordering_t ord) Initialise a context object for a polynomial ring with the given number of variables and the given ordering. The possibilities for the ordering are ``ORD_LEX``, ``ORD_DEGLEX`` and ``ORD_DEGREVLEX``. .. function:: slong fmpz_mpoly_ctx_nvars(const fmpz_mpoly_ctx_t ctx) Return the number of variables used to initialize the context. .. function:: ordering_t fmpz_mpoly_ctx_ord(const fmpz_mpoly_ctx_t ctx) Return the ordering used to initialize the context. .. function:: void fmpz_mpoly_ctx_clear(fmpz_mpoly_ctx_t ctx) Release up any space allocated by *ctx*. Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_init(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Initialise *A* for use with the given and initialised context object. Its value is set to zero. .. function:: void fmpz_mpoly_init2(fmpz_mpoly_t A, slong alloc, const fmpz_mpoly_ctx_t ctx) Initialise *A* for use with the given and initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and at least ``MPOLY_MIN_BITS`` bits for the exponents. .. function:: void fmpz_mpoly_init3(fmpz_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx) Initialise *A* for use with the given and initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and *bits* bits for the exponents. .. function:: void fmpz_mpoly_fit_length(fmpz_mpoly_t A, slong len, const fmpz_mpoly_ctx_t ctx) Ensure that *A* has space for at least *len* terms. .. function:: void fmpz_mpoly_fit_bits(fmpz_mpoly_t A, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx) Ensure that the exponent fields of *A* have at least *bits* bits. .. function:: void fmpz_mpoly_realloc(fmpz_mpoly_t A, slong alloc, const fmpz_mpoly_ctx_t ctx) Reallocate *A* to have space for *alloc* terms. Assumes the current length of the polynomial is not greater than *alloc*. .. function:: void fmpz_mpoly_clear(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Release any space allocated for *A*. Input/Output -------------------------------------------------------------------------------- The variable strings in *x* start with the variable of most significance at index `0`. If *x* is ``NULL``, the variables are named ``x1``, ``x2``, etc. .. function:: char * fmpz_mpoly_get_str_pretty(const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx) Return a string, which the user is responsible for cleaning up, representing *A*, given an array of variable strings *x*. .. function:: int fmpz_mpoly_fprint_pretty(FILE * file, const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx) Print a string representing *A* to *file*. .. function:: int fmpz_mpoly_print_pretty(const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx) Print a string representing *A* to ``stdout``. .. function:: int fmpz_mpoly_set_str_pretty(fmpz_mpoly_t A, const char * str, const char ** x, const fmpz_mpoly_ctx_t ctx) Set *A* to the polynomial in the null-terminates string *str* given an array *x* of variable strings. If parsing *str* fails, *A* is set to zero, and `-1` is returned. Otherwise, `0` is returned. The operations ``+``, ``-``, ``*``, and ``/`` are permitted along with integers and the variables in *x*. The character ``^`` must be immediately followed by the (integer) exponent. If any division is not exact, parsing fails. Basic manipulation -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_gen(fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) Set *A* to the variable of index *var*, where `var = 0` corresponds to the variable with the most significance with respect to the ordering. .. function:: int fmpz_mpoly_is_gen(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) If `var \ge 0`, return `1` if *A* is equal to the `var`-th generator, otherwise return `0`. If `var < 0`, return `1` if the polynomial is equal to any generator, otherwise return `0`. .. function:: void fmpz_mpoly_set(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Set *A* to *B*. .. function:: int fmpz_mpoly_equal(const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Return `1` if *A* is equal to *B*, else return `0`. .. function:: void fmpz_mpoly_swap(fmpz_mpoly_t poly1, fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) Efficiently swap *A* and *B*. .. function:: int _fmpz_mpoly_fits_small(const fmpz * poly, slong len) Return 1 if the array of coefficients of length *len* consists entirely of values that are small ``fmpz`` values, i.e. of at most ``FLINT_BITS - 2`` bits plus a sign bit. .. function:: slong fmpz_mpoly_max_bits(const fmpz_mpoly_t A) Computes the maximum number of bits `b` required to represent the absolute values of the coefficients of *A*. If all of the coefficients are positive, `b` is returned, otherwise `-b` is returned. Constants -------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_is_fmpz(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if *A* is a constant, else return `0`. .. function:: void fmpz_mpoly_get_fmpz(fmpz_t c, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Assuming that *A* is a constant, set *c* to this constant. This function throws if *A* is not a constant. .. function:: void fmpz_mpoly_set_fmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_ui(fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_si(fmpz_mpoly_t A, slong c, const fmpz_mpoly_ctx_t ctx) Set *A* to the constant *c*. .. function:: void fmpz_mpoly_zero(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Set *A* to the constant `0`. .. function:: void fmpz_mpoly_one(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Set *A* to the constant `1`. .. function:: int fmpz_mpoly_equal_fmpz(const fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_equal_ui(const fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_equal_si(const fmpz_mpoly_t A, slong c, const fmpz_mpoly_ctx_t ctx) Return `1` if *A* is equal to the constant *c*, else return `0`. .. function:: int fmpz_mpoly_is_zero(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if *A* is the constant `0`, else return `0`. .. function:: int fmpz_mpoly_is_one(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if *A* is the constant `1`, else return `0`. Degrees -------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_degrees_fit_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if the degrees of *A* with respect to each variable fit into an ``slong``, otherwise return `0`. .. function:: void fmpz_mpoly_degrees_fmpz(fmpz ** degs, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_degrees_si(slong * degs, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Set *degs* to the degrees of *A* with respect to each variable. If *A* is zero, all degrees are set to `-1`. .. function:: void fmpz_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) slong fmpz_mpoly_degree_si(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) Either return or set *deg* to the degree of *A* with respect to the variable of index *var*. If *A* is zero, the degree is defined to be `-1`. .. function:: int fmpz_mpoly_total_degree_fits_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if the total degree of *A* fits into an ``slong``, otherwise return `0`. .. function:: void fmpz_mpoly_total_degree_fmpz(fmpz_t tdeg, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) slong fmpz_mpoly_total_degree_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Either return or set *tdeg* to the total degree of *A*. If *A* is zero, the total degree is defined to be `-1`. .. function:: void fmpz_mpoly_used_vars(int * used, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) For each variable index *i*, set ``used[i]`` to nonzero if the variable of index *i* appears in *A* and to zero otherwise. Coefficients -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_get_coeff_fmpz_monomial(fmpz_t c, const fmpz_mpoly_t A, const fmpz_mpoly_t M, const fmpz_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set *c* to the coefficient of the corresponding monomial in *A*. This function throws if *M* is not a monomial. .. function:: void fmpz_mpoly_set_coeff_fmpz_monomial(fmpz_mpoly_t poly, const fmpz_t c, const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set the coefficient of the corresponding monomial in *A* to *c*. This function throws if *M* is not a monomial. .. function:: void fmpz_mpoly_get_coeff_fmpz_fmpz(fmpz_t c, const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) ulong fmpz_mpoly_get_coeff_ui_fmpz(const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) slong fmpz_mpoly_get_coeff_si_fmpz(const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_get_coeff_fmpz_ui(fmpz_t c, const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx) ulong fmpz_mpoly_get_coeff_ui_ui(const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx) slong fmpz_mpoly_get_coeff_si_ui(const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx) Either return or set *c* to the coefficient of the monomial with exponent vector *exp*. .. function:: void fmpz_mpoly_set_coeff_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_coeff_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_coeff_si_fmpz(fmpz_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_coeff_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_coeff_ui_ui(fmpz_mpoly_t A, ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_coeff_si_ui(fmpz_mpoly_t A, slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) Set the coefficient of the monomial with exponent vector *exp* to *c*. .. function:: void fmpz_mpoly_get_coeff_vars_ui(fmpz_mpoly_t C, const fmpz_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpz_mpoly_ctx_t ctx) Set *C* to the coefficient of *A* with respect to the variables in *vars* with powers in the corresponding array *exps*. Both *vars* and *exps* point to array of length *length*. It is assumed that `0 < length \le nvars(A)` and that the variables in *vars* are distinct. Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_cmp(const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Return `1` (resp. `-1`, or `0`) if *A* is after (resp. before, same as) *B* in some arbitrary but fixed total ordering of the polynomials. This ordering agrees with the usual ordering of monomials when *A* and *B* are both monomials. Conversion -------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_is_fmpz_poly(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) Return whether *A* is a univariate polynomial in the variable with index *var*. .. function:: int fmpz_mpoly_get_fmpz_poly(fmpz_poly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) If *B* is a univariate polynomial in the variable with index *var*, set *A* to this polynomial and return 1; otherwise return 0. .. function:: void fmpz_mpoly_set_fmpz_poly(fmpz_mpoly_t A, const fmpz_poly_t B, slong var, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_gen_fmpz_poly(fmpz_mpoly_t A, slong var, const fmpz_poly_t B, const fmpz_mpoly_ctx_t ctx) Set *A* to the univariate polynomial *B* in the variable with index *var*. Container operations -------------------------------------------------------------------------------- These functions deal with violations of the internal canonical representation. If a term index is negative or not strictly less than the length of the polynomial, the function will throw. .. function:: fmpz * fmpz_mpoly_term_coeff_ref(fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) Return a reference to the coefficient of index *i* of *A*. .. function:: int fmpz_mpoly_is_canonical(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if *A* is in canonical form. Otherwise, return `0`. To be in canonical form, all of the terms must have nonzero coefficient, and the terms must be sorted from greatest to least. .. function:: slong fmpz_mpoly_length(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return the number of terms in *A*. If the polynomial is in canonical form, this will be the number of nonzero coefficients. .. function:: void fmpz_mpoly_resize(fmpz_mpoly_t A, slong new_length, const fmpz_mpoly_ctx_t ctx) Set the length of *A* to `new\_length`. Terms are either deleted from the end, or new zero terms are appended. .. function:: void fmpz_mpoly_get_term_coeff_fmpz(fmpz_t c, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) ulong fmpz_mpoly_get_term_coeff_ui(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) slong fmpz_mpoly_get_term_coeff_si(const fmpz_mpoly_t poly, slong i, const fmpz_mpoly_ctx_t ctx) Either return or set *c* to the coefficient of the term of index *i*. .. function:: void fmpz_mpoly_set_term_coeff_fmpz(fmpz_mpoly_t A, slong i, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_term_coeff_ui(fmpz_mpoly_t A, slong i, ulong c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_term_coeff_si(fmpz_mpoly_t A, slong i, slong c, const fmpz_mpoly_ctx_t ctx) Set the coefficient of the term of index *i* to *c*. .. function:: int fmpz_mpoly_term_exp_fits_si(const fmpz_mpoly_t poly, slong i, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_term_exp_fits_ui(const fmpz_mpoly_t poly, slong i, const fmpz_mpoly_ctx_t ctx) Return `1` if all entries of the exponent vector of the term of index *i* fit into an ``slong`` (resp. a ``ulong``). Otherwise, return `0`. .. function:: void fmpz_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_get_term_exp_ui(ulong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_get_term_exp_si(slong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) Set *exp* to the exponent vector of the term of index *i*. The ``_ui`` (resp. ``_si``) version throws if any entry does not fit into a ``ulong`` (resp. ``slong``). .. function:: ulong fmpz_mpoly_get_term_var_exp_ui(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx) slong fmpz_mpoly_get_term_var_exp_si(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx) Return the exponent of the variable `var` of the term of index *i*. This function throws if the exponent does not fit into a ``ulong`` (resp. ``slong``). .. function:: void fmpz_mpoly_set_term_exp_fmpz(fmpz_mpoly_t A, slong i, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_term_exp_ui(fmpz_mpoly_t A, slong i, const ulong * exp, const fmpz_mpoly_ctx_t ctx) Set the exponent vector of the term of index *i* to *exp*. .. function:: void fmpz_mpoly_get_term(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) Set `M` to the term of index *i* in *A*. .. function:: void fmpz_mpoly_get_term_monomial(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) Set `M` to the monomial of the term of index *i* in *A*. The coefficient of `M` will be one. .. function:: void fmpz_mpoly_push_term_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_fmpz_ffmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_ui_ffmpz(fmpz_mpoly_t A, ulong c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_si_ffmpz(fmpz_mpoly_t A, slong c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_ui_ui(fmpz_mpoly_t A, ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_si_ui(fmpz_mpoly_t A, slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) Append a term to *A* with coefficient *c* and exponent vector *exp*. This function runs in constant average time. .. function:: void fmpz_mpoly_sort_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Sort the terms of *A* into the canonical ordering dictated by the ordering in *ctx*. This function simply reorders the terms: It does not combine like terms, nor does it delete terms with coefficient zero. This function runs in linear time in the size of *A*. .. function:: void fmpz_mpoly_combine_like_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Combine adjacent like terms in *A* and delete terms with coefficient zero. If the terms of *A* were sorted to begin with, the result will be in canonical form. This function runs in linear time in the size of *A*. .. function:: void fmpz_mpoly_reverse(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Set *A* to the reversal of *B*. Random generation -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_randtest_bound(fmpz_mpoly_t A, flint_rand_t state, slong length, mp_limb_t coeff_bits, ulong exp_bound, const fmpz_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bound - 1]``. The exponents of each variable are generated by calls to ``n_randint(state, exp_bound)``. .. function:: void fmpz_mpoly_randtest_bounds(fmpz_mpoly_t A, flint_rand_t state, slong length, mp_limb_t coeff_bits, ulong * exp_bounds, const fmpz_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bounds[i] - 1]``. The exponents of the variable of index *i* are generated by calls to ``n_randint(state, exp_bounds[i])``. .. function:: void fmpz_mpoly_randtest_bits(fmpz_mpoly_t A, flint_rand_t state, slong length, mp_limb_t coeff_bits, mp_limb_t exp_bits, const fmpz_mpoly_ctx_t ctx) Generate a random polynomial with length up to the given length and exponents whose packed form does not exceed the given bit count. The parameter ``coeff_bits`` to the three functions ``fmpz_mpoly_randtest_{bound|bounds|bits}`` is merely a suggestion for the approximate bit count of the resulting signed coefficients. The function :func:`fmpz_mpoly_max_bits` will give the exact bit count of the result. Addition/Subtraction -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_add_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_add_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_add_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) Set *A* to `B + c`. If *A* and *B* are aliased, this function will probably run quickly. .. function:: void fmpz_mpoly_sub_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_sub_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_sub_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) Set *A* to `B - c`. If *A* and *B* are aliased, this function will probably run quickly. .. function:: void fmpz_mpoly_add(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) Set *A* to `B + C`. If *A* and *B* are aliased, this function might run in time proportional to the size of `C`. .. function:: void fmpz_mpoly_sub(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) Set *A* to `B - C`. If *A* and *B* are aliased, this function might run in time proportional to the size of `C`. Scalar operations -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_neg(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Set *A* to `-B`. .. function:: void fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_scalar_mul_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_scalar_mul_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) Set *A* to `B \times c`. .. function:: void fmpz_mpoly_scalar_fmma(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_t D, const fmpz_t e, const fmpz_mpoly_ctx_t ctx) Sets *A* to `B \times c + D \times e`. .. function:: void fmpz_mpoly_scalar_divexact_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_scalar_divexact_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_scalar_divexact_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) Set *A* to *B* divided by *c*. The division is assumed to be exact. .. function:: int fmpz_mpoly_scalar_divides_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_scalar_divides_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_scalar_divides_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) If *B* is divisible by *c*, set *A* to the exact quotient and return `1`, otherwise set *A* to zero and return `0`. Differentiation/Integration -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_derivative(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) Set *A* to the derivative of *B* with respect to the variable of index `var`. .. function:: void fmpz_mpoly_integral(fmpz_mpoly_t A, fmpz_t scale, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) Set *A* and *scale* so that *A* is an integral of `scale \times B` with respect to the variable of index *var*, where *scale* is positive and as small as possible. Evaluation -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: int fmpz_mpoly_evaluate_all_fmpz(fmpz_t ev, const fmpz_mpoly_t A, fmpz * const * vals, const fmpz_mpoly_ctx_t ctx) Set *ev* to the evaluation of *A* where the variables are replaced by the corresponding elements of the array *vals*. Return `1` for success and `0` for failure. .. function:: int fmpz_mpoly_evaluate_one_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_t val, const fmpz_mpoly_ctx_t ctx) Set *A* to the evaluation of *B* where the variable of index *var* is replaced by ``val``. Return `1` for success and `0` for failure. .. function:: int fmpz_mpoly_compose_fmpz_poly(fmpz_poly_t A, const fmpz_mpoly_t B, fmpz_poly_struct * const * C, const fmpz_mpoly_ctx_t ctxB) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. The context object of *B* is *ctxB*. Return `1` for success and `0` for failure. .. function:: int fmpz_mpoly_compose_fmpz_mpoly_geobucket(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) int fmpz_mpoly_compose_fmpz_mpoly_horner(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) int fmpz_mpoly_compose_fmpz_mpoly(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. Both *A* and the elements of *C* have context object *ctxAC*, while *B* has context object *ctxB*. The length of the array *C* is the number of variables in *ctxB*. Neither *A* nor *B* is allowed to alias any other polynomial. Return `1` for success and `0` for failure. The main method attempts to perform the calculation using matrices and chooses heuristically between the ``geobucket`` and ``horner`` methods if needed. .. function:: void fmpz_mpoly_compose_fmpz_mpoly_gen(fmpz_mpoly_t A, const fmpz_mpoly_t B, const slong * c, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variable of index *i* in *ctxB* is replaced by the variable of index ``c[i]`` in *ctxAC*. The length of the array *C* is the number of variables in *ctxB*. If any ``c[i]`` is negative, the corresponding variable of *B* is replaced by zero. Otherwise, it is expected that ``c[i]`` is less than the number of variables in *ctxAC*. Multiplication -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_mul(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_mul_threaded(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx, slong thread_limit) Set *A* to `B \times C`. .. function:: void fmpz_mpoly_mul_johnson(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_mul_heap_threaded(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) Set *A* to `B \times C` using Johnson's heap-based method. The first version always uses one thread. .. function:: int fmpz_mpoly_mul_array(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_mul_array_threaded(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) Try to set *A* to `B \times C` using arrays. If the return is `0`, the operation was unsuccessful. Otherwise, it was successful and the return is `1`. The first version always uses one thread. .. function:: int fmpz_mpoly_mul_dense(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) Try to set *A* to `B \times C` using dense arithmetic. If the return is `0`, the operation was unsuccessful. Otherwise, it was successful and the return is `1`. Powering -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: int fmpz_mpoly_pow_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t k, const fmpz_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power. Return `1` for success and `0` for failure. .. function:: int fmpz_mpoly_pow_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power. Return `1` for success and `0` for failure. Division -------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_divides(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) If *A* is divisible by *B*, set *Q* to the exact quotient and return `1`. Otherwise, set `Q` to zero and return `0`. .. function:: void fmpz_mpoly_divrem(fmpz_mpoly_t Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Set `Q` and `R` to the quotient and remainder of *A* divided by *B*. The monomials in *R* divisible by the leading monomial of *B* will have coefficients reduced modulo the absolute value of the leading coefficient of *B*. Note that this function is not very useful if the leading coefficient *B* is not a unit. .. function:: void fmpz_mpoly_quasidivrem(fmpz_t scale, fmpz_mpoly_t Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Set *scale*, *Q* and *R* so that *Q* and *R* are the quotient and remainder of `scale \times A` divided by *B*. No monomials in *R* will be divisible by the leading monomial of *B*. .. function:: void fmpz_mpoly_div(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Perform the operation of :func:`fmpz_mpoly_divrem` and discard *R*. Note that this function is not very useful if the division is not exact and the leading coefficient *B* is not a unit. .. function:: void fmpz_mpoly_quasidiv(fmpz_t scale, fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Perform the operation of :func:`fmpz_mpoly_quasidivrem` and discard *R*. .. function:: void fmpz_mpoly_divrem_ideal(fmpz_mpoly_struct ** Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, fmpz_mpoly_struct * const * B, slong len, const fmpz_mpoly_ctx_t ctx) This function is as per :func:`fmpz_mpoly_divrem` except that it takes an array of divisor polynomials *B* and it returns an array of quotient polynomials *Q*. The number of divisor (and hence quotient) polynomials is given by *len*. Note that this function is not very useful if there is no unit among the leading coefficients in the array *B*. .. function:: void fmpz_mpoly_quasidivrem_ideal(fmpz_t scale, fmpz_mpoly_struct ** Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, fmpz_mpoly_struct * const * B, slong len, const fmpz_mpoly_ctx_t ctx) This function is as per :func:`fmpz_mpoly_quasidivrem` except that it takes an array of divisor polynomials *B* and it returns an array of quotient polynomials *Q*. The number of divisor (and hence quotient) polynomials is given by *len*. Greatest Common Divisor -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_term_content(fmpz_mpoly_t M, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Set *M* to the GCD of the terms of *A*. If *A* is zero, *M* will be zero. Otherwise, *M* will be a monomial with positive coefficient. .. function:: int fmpz_mpoly_content_vars(fmpz_mpoly_t g, const fmpz_mpoly_t A, slong * vars, slong vars_length, const fmpz_mpoly_ctx_t ctx) Set *g* to the GCD of the coefficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon success, *g* will be independent of the variables *vars*. .. function:: int fmpz_mpoly_gcd(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Try to set *G* to the GCD of *A* and *B* with positive leading coefficient. The GCD of zero and zero is defined to be zero. If the return is `1` the function was successful. Otherwise the return is `0` and *G* is left untouched. .. function:: int fmpz_mpoly_gcd_cofactors(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Do the operation of :func:`fmpz_mpoly_gcd` and also compute `Abar = A/G` and `Bbar = B/G` if successful. .. function:: int fmpz_mpoly_gcd_brown(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_gcd_hensel(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_gcd_subresultant(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_gcd_zippel(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) int fmpz_mpoly_gcd_zippel2(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) Try to set *G* to the GCD of *A* and *B* using various algorithms. .. function:: int fmpz_mpoly_resultant(fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) Try to set *R* to the resultant of *A* and *B* with respect to the variable of index *var*. .. function:: int fmpz_mpoly_discriminant(fmpz_mpoly_t D, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) Try to set *D* to the discriminant of *A* with respect to the variable of index *var*. .. function:: void fmpz_mpoly_primitive_part(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx) Sets *res* to the primitive part of *f*, obtained by dividing out the content of all coefficients and normalizing the leading coefficient to be positive. The zero polynomial is unchanged. Square Root -------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_sqrt_heap(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, int check) If *A* is a perfect square return `1` and set *Q* to the square root with positive leading coefficient. Otherwise return `0` and set *Q* to the zero polynomial. If `check = 0` the polynomial is assumed to be a perfect square. This can be significantly faster, but it will not detect non-squares with any reliability, and in the event of being passed a non-square the result is meaningless. .. function:: int fmpz_mpoly_sqrt(fmpz_mpoly_t q, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) If *A* is a perfect square return `1` and set *Q* to the square root with positive leading coefficient. Otherwise return `0` and set *Q* to zero. .. function:: int fmpz_mpoly_is_square(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if *A* is a perfect square, otherwise return `0`. Univariate Functions -------------------------------------------------------------------------------- An ``fmpz_mpoly_univar_t`` holds a univariate polynomial in some main variable with ``fmpz_mpoly_t`` coefficients in the remaining variables. These functions are useful when one wants to rewrite an element of `\mathbb{Z}[x_1, \dots, x_m]` as an element of `(\mathbb{Z}[x_1, \dots, x_{v-1}, x_{v+1}, \dots, x_m])[x_v]` and vice versa. .. function:: void fmpz_mpoly_univar_init(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) Initialize *A*. .. function:: void fmpz_mpoly_univar_clear(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) Clear *A*. .. function:: void fmpz_mpoly_univar_swap(fmpz_mpoly_univar_t A, fmpz_mpoly_univar_t B, const fmpz_mpoly_ctx_t ctx) Swap *A* and *B*. .. function:: void fmpz_mpoly_to_univar(fmpz_mpoly_univar_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) Set *A* to a univariate form of *B* by pulling out the variable of index *var*. The coefficients of *A* will still belong to the content *ctx* but will not depend on the variable of index *var*. .. function:: void fmpz_mpoly_from_univar(fmpz_mpoly_t A, const fmpz_mpoly_univar_t B, slong var, const fmpz_mpoly_ctx_t ctx) Set *A* to the normal form of *B* by putting in the variable of index *var*. This function is undefined if the coefficients of *B* depend on the variable of index *var*. .. function:: int fmpz_mpoly_univar_degree_fits_si(const fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) Return `1` if the degree of *A* with respect to the main variable fits an ``slong``. Otherwise, return `0`. .. function:: slong fmpz_mpoly_univar_length(const fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) Return the number of terms in *A* with respect to the main variable. .. function:: slong fmpz_mpoly_univar_get_term_exp_si(fmpz_mpoly_univar_t A, slong i, const fmpz_mpoly_ctx_t ctx) Return the exponent of the term of index *i* of *A*. .. function:: void fmpz_mpoly_univar_get_term_coeff(fmpz_mpoly_t c, const fmpz_mpoly_univar_t A, slong i, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_univar_swap_term_coeff(fmpz_mpoly_t c, fmpz_mpoly_univar_t A, slong i, const fmpz_mpoly_ctx_t ctx) Set (resp. swap) *c* to (resp. with) the coefficient of the term of index *i* of *A*. Internal Functions -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_inflate(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mpoly_ctx_t ctx) Apply the function ``e -> shift[v] + stride[v]*e`` to each exponent ``e`` corresponding to the variable ``v``. It is assumed that each shift and stride is not negative. .. function:: void fmpz_mpoly_deflate(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mpoly_ctx_t ctx) Apply the function ``e -> (e - shift[v])/stride[v]`` to each exponent ``e`` corresponding to the variable ``v``. If any ``stride[v]`` is zero, the corresponding numerator ``e - shift[v]`` is assumed to be zero, and the quotient is defined as zero. This allows the function to undo the operation performed by :func:`fmpz_mpoly_inflate` when possible. .. function:: void fmpz_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) For each variable `v` let `S_v` be the set of exponents appearing on `v`. Set ``shift[v]`` to `\operatorname{min}(S_v)` and set ``stride[v]`` to `\operatorname{gcd}(S-\operatorname{min}(S_v))`. If *A* is zero, all shifts and strides are set to zero. .. function:: void fmpz_mpoly_pow_fps(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power, using the Monagan and Pearce FPS algorithm. It is assumed that *B* is not zero and `k \geq 2`. .. function:: slong _fmpz_mpoly_divides_array(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits) Use dense array exact division to set ``(poly1, exp1, alloc)`` to ``(poly2, exp3, len2)`` divided by ``(poly3, exp3, len3)`` in ``num`` variables, given a list of multipliers to tightly pack exponents and a number of bits for the fields of the exponents of the result. The array "mults" is a list of bases to be used in encoding the array indices from the exponents. The function reallocates its output, hence the double indirection, and returns the length of its output if the quotient is exact, or zero if not. It is assumed that ``poly2`` is not zero. No aliasing is allowed. .. function:: int fmpz_mpoly_divides_array(fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) Set ``poly1`` to ``poly2`` divided by ``poly3``, using a big dense array to accumulate coefficients, and return 1 if the quotient is exact. Otherwise, return 0 if the quotient is not exact. If the array will be larger than some internally set parameter, the function fails silently and returns `-1` so that some other method may be called. This function is most efficient on dense inputs. Note that the function ``fmpz_mpoly_div_monagan_pearce`` below may be much faster if the quotient is known to be exact. .. function:: slong _fmpz_mpoly_divides_monagan_pearce(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, ulong bits, slong N, const mp_limb_t * cmpmask) Set ``(poly1, exp1, alloc)`` to ``(poly2, exp3, len2)`` divided by ``(poly3, exp3, len3)`` and return 1 if the quotient is exact. Otherwise return 0. The function assumes exponent vectors that each fit in `N` words, and are packed into fields of the given number of bits. Assumes input polys are nonzero. Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce. No aliasing is allowed. .. function:: int fmpz_mpoly_divides_monagan_pearce(fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) Set ``poly1`` to ``poly2`` divided by ``poly3`` and return 1 if the quotient is exact. Otherwise return 0. The function uses the algorithm of Michael Monagan and Roman Pearce. Note that the function ``fmpz_mpoly_div_monagan_pearce`` below may be much faster if the quotient is known to be exact. .. function:: int fmpz_mpoly_divides_heap_threaded(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) The same method as used as in :func:`fmpz_mpoly_divides_monagan_pearce`, but is also multi-threaded. .. note:: This function is only defined if the machine is known to be strongly ordered during the configuration. To check whether this function is defined during compilation-time, use the C preprocessor macro ``#ifdef fmpz_mpoly_divides_heap_threaded``. Note that, if the system is known to be strongly ordered, the underlying algorithm for this function is utilized in :func:`fmpz_mpoly_divides`. Hence, you may find it easier to use this function instead if the C preprocessor is not available. .. function:: slong _fmpz_mpoly_div_monagan_pearce(fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const mp_limb_t * cmpmask) Set ``(polyq, expq, allocq)`` to the quotient of ``(poly2, exp2, len2)`` by ``(poly3, exp3, len3)`` discarding remainder (with notional remainder coefficients reduced modulo the leading coefficient of ``(poly3, exp3, len3)``), and return the length of the quotient. The function reallocates its output, hence the double indirection. The function assumes the exponent vectors all fit in `N` words. The exponent vectors are assumed to have fields with the given number of bits. Assumes input polynomials are nonzero. Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce. No aliasing is allowed. .. function:: void fmpz_mpoly_div_monagan_pearce(fmpz_mpoly_t polyq, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) Set ``polyq`` to the quotient of ``poly2`` by ``poly3``, discarding the remainder (with notional remainder coefficients reduced modulo the leading coefficient of ``poly3``). Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce. This function is exceptionally efficient if the division is known to be exact. .. function:: slong _fmpz_mpoly_divrem_monagan_pearce(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const mp_limb_t * cmpmask) Set ``(polyq, expq, allocq)`` and ``(polyr, expr, allocr)`` to the quotient and remainder of ``(poly2, exp2, len2)`` by ``(poly3, exp3, len3)`` (with remainder coefficients reduced modulo the leading coefficient of ``(poly3, exp3, len3)``), and return the length of the quotient. The function reallocates its outputs, hence the double indirection. The function assumes the exponent vectors all fit in `N` words. The exponent vectors are assumed to have fields with the given number of bits. Assumes input polynomials are nonzero. Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce. No aliasing is allowed. .. function:: void fmpz_mpoly_divrem_monagan_pearce(fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) Set ``polyq`` and ``polyr`` to the quotient and remainder of ``poly2`` divided by ``poly3`` (with remainder coefficients reduced modulo the leading coefficient of ``poly3``). Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce. .. function:: slong _fmpz_mpoly_divrem_array(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits) Use dense array division to set ``(polyq, expq, allocq)`` and ``(polyr, expr, allocr)`` to the quotient and remainder of ``(poly2, exp2, len2)`` divided by ``(poly3, exp3, len3)`` in ``num`` variables, given a list of multipliers to tightly pack exponents and a number of bits for the fields of the exponents of the result. The function reallocates its outputs, hence the double indirection. The array ``mults`` is a list of bases to be used in encoding the array indices from the exponents. The function returns the length of the quotient. It is assumed that the input polynomials are not zero. No aliasing is allowed. .. function:: int fmpz_mpoly_divrem_array(fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) Set ``polyq`` and ``polyr`` to the quotient and remainder of ``poly2`` divided by ``poly3`` (with remainder coefficients reduced modulo the leading coefficient of ``poly3``). The function is implemented using dense arrays, and is efficient when the inputs are fairly dense. If the array will be larger than some internally set parameter, the function silently returns 0 so that another function can be called, otherwise it returns 1. .. function:: void fmpz_mpoly_quasidivrem_heap(fmpz_t scale, fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) Set ``scale``, ``q`` and ``r`` so that ``scale*poly2 = q*poly3 + r`` and no monomial in ``r`` is divisible by the leading monomial of ``poly3``, where ``scale`` is positive and as small as possible. This function throws an exception if ``poly3`` is zero or if an exponent overflow occurs. .. function:: slong _fmpz_mpoly_divrem_ideal_monagan_pearce(fmpz_mpoly_struct ** polyq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, fmpz_mpoly_struct * const * poly3, ulong * const * exp3, slong len, slong N, slong bits, const fmpz_mpoly_ctx_t ctx, const mp_limb_t * cmpmask) This function is as per ``_fmpz_mpoly_divrem_monagan_pearce`` except that it takes an array of divisor polynomials ``poly3`` and an array of repacked exponent arrays ``exp3``, which may alias the exponent arrays of ``poly3``, and it returns an array of quotient polynomials ``polyq``. The number of divisor (and hence quotient) polynomials is given by ``len``. The function computes polynomials `q_i` such that `r = a - \sum_{i=0}^{\mbox{len - 1}} q_ib_i`, where the `q_i` are the quotient polynomials and the `b_i` are the divisor polynomials. .. function:: void fmpz_mpoly_divrem_ideal_monagan_pearce(fmpz_mpoly_struct ** q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, fmpz_mpoly_struct * const * poly3, slong len, const fmpz_mpoly_ctx_t ctx) This function is as per ``fmpz_mpoly_divrem_monagan_pearce`` except that it takes an array of divisor polynomials ``poly3``, and it returns an array of quotient polynomials ``q``. The number of divisor (and hence quotient) polynomials is given by ``len``. The function computes polynomials `q_i = q[i]` such that ``poly2`` is `r + \sum_{i=0}^{\mbox{len - 1}} q_ib_i`, where `b_i =` ``poly3[i]``. Vectors -------------------------------------------------------------------------------- .. type:: fmpz_mpoly_vec_struct .. type:: fmpz_mpoly_vec_t A type holding a vector of :type:`fmpz_mpoly_t`. .. macro:: fmpz_mpoly_vec_entry(vec, i) Macro for accessing the entry at position *i* in *vec*. .. function:: void fmpz_mpoly_vec_init(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx) Initializes *vec* to a vector of length *len*, setting all entries to the zero polynomial. .. function:: void fmpz_mpoly_vec_clear(fmpz_mpoly_vec_t vec, const fmpz_mpoly_ctx_t ctx) Clears *vec*, freeing its allocated memory. .. function:: void fmpz_mpoly_vec_print(const fmpz_mpoly_vec_t vec, const fmpz_mpoly_ctx_t ctx) Prints *vec* to standard output. .. function:: void fmpz_mpoly_vec_swap(fmpz_mpoly_vec_t x, fmpz_mpoly_vec_t y, const fmpz_mpoly_ctx_t ctx) Swaps *x* and *y* efficiently. .. function:: void fmpz_mpoly_vec_fit_length(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx) Allocates room for *len* entries in *vec*. .. function:: void fmpz_mpoly_vec_set(fmpz_mpoly_vec_t dest, const fmpz_mpoly_vec_t src, const fmpz_mpoly_ctx_t ctx) Sets *dest* to a copy of *src*. .. function:: void fmpz_mpoly_vec_append(fmpz_mpoly_vec_t vec, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx) Appends *f* to the end of *vec*. .. function:: slong fmpz_mpoly_vec_insert_unique(fmpz_mpoly_vec_t vec, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx) Inserts *f* without duplication into *vec* and returns its index. If this polynomial already exists, *vec* is unchanged. If this polynomial does not exist in *vec*, it is appended. .. function:: void fmpz_mpoly_vec_set_length(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx) Sets the length of *vec* to *len*, truncating or zero-extending as needed. .. function:: void fmpz_mpoly_vec_randtest_not_zero(fmpz_mpoly_vec_t vec, flint_rand_t state, slong len, slong poly_len, slong bits, ulong exp_bound, fmpz_mpoly_ctx_t ctx) Sets *vec* to a random vector with exactly *len* entries, all nonzero, with random parameters defined by *poly_len*, *bits* and *exp_bound*. .. function:: void fmpz_mpoly_vec_set_primitive_unique(fmpz_mpoly_vec_t res, const fmpz_mpoly_vec_t src, const fmpz_mpoly_ctx_t ctx) Sets *res* to a vector containing all polynomials in *src* reduced to their primitive parts, without duplication. The zero polynomial is skipped if present. The output order is arbitrary. Ideals and Gröbner bases ------------------------------------------------------------------------------- The following methods deal with ideals in `\mathbb{Q}[X_1,\ldots,X_n]`. We use primitive integer polynomials as normalised generators in place of monic rational polynomials. .. function:: void fmpz_mpoly_spoly(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx) Sets *res* to the *S*-polynomial of *f* and *g*, scaled to an integer polynomial by computing the LCM of the leading coefficients. .. function:: void fmpz_mpoly_reduction_primitive_part(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_vec_t vec, const fmpz_mpoly_ctx_t ctx) Sets *res* to the primitive part of the reduction (remainder of multivariate quasidivision with remainder) with respect to the polynomials *vec*. .. function:: int fmpz_mpoly_vec_is_groebner(const fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) If *F* is *NULL*, checks if *G* is a Gröbner basis. If *F* is not *NULL*, checks if *G* is a Gröbner basis for *F*. .. function:: int fmpz_mpoly_vec_is_autoreduced(const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) Checks whether the vector *F* is autoreduced (or inter-reduced). .. function:: void fmpz_mpoly_vec_autoreduction(fmpz_mpoly_vec_t H, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) Sets *H* to the autoreduction (inter-reduction) of *F*. .. function:: void fmpz_mpoly_vec_autoreduction_groebner(fmpz_mpoly_vec_t H, const fmpz_mpoly_vec_t G, const fmpz_mpoly_ctx_t ctx) Sets *H* to the autoreduction (inter-reduction) of *G*. Assumes that *G* is a Gröbner basis. This produces a reduced Gröbner basis, which is unique (up to the sort order of the entries in the vector). .. function:: void fmpz_mpoly_buchberger_naive(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) Sets *G* to a Gröbner basis for *F*, computed using a naive implementation of Buchberger's algorithm. .. function:: int fmpz_mpoly_buchberger_naive_with_limits(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, slong ideal_len_limit, slong poly_len_limit, slong poly_bits_limit, const fmpz_mpoly_ctx_t ctx) As :func:`fmpz_mpoly_buchberger_naive`, but halts if during the execution of Buchberger's algorithm the length of the ideal basis set exceeds *ideal_len_limit*, the length of any polynomial exceeds *poly_len_limit*, or the size of the coefficients of any polynomial exceeds *poly_bits_limit*. Returns 1 for success and 0 for failure. On failure, *G* is a valid basis for *F* but it might not be a Gröbner basis. Special polynomials -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_symmetric_gens(fmpz_mpoly_t res, ulong k, slong * vars, slong n, const fmpz_mpoly_ctx_t ctx) .. function:: void fmpz_mpoly_symmetric(fmpz_mpoly_t res, ulong k, const fmpz_mpoly_ctx_t ctx) Sets *res* to the elementary symmetric polynomial `e_k(X_1,\ldots,X_n)`. The *gens* version takes `X_1,\ldots,X_n` to be the subset of generators given by *vars* and *n*. The indices in *vars* start from zero. Currently, the indices in *vars* must be distinct. flint-3.1.3/doc/source/fmpz_mpoly_factor.rst000066400000000000000000000063311461254215100211670ustar00rootroot00000000000000.. _fmpz-mpoly-factor: **fmpz_mpoly_factor.h** -- factorisation of multivariate polynomials over the integers ====================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mpoly_factor_struct A struct for holding a factored integer polynomial. There is a single constant and a product of bases to corresponding exponents. .. type:: fmpz_mpoly_factor_t An array of length `1` of ``fmpz_mpoly_factor_struct``. Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_factor_init(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) Initialise *f*. .. function:: void fmpz_mpoly_factor_clear(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) Clear *f*. Basic manipulation -------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_factor_swap(fmpz_mpoly_factor_t f, fmpz_mpoly_factor_t g, const fmpz_mpoly_ctx_t ctx) Efficiently swap *f* and *g*. .. function:: slong fmpz_mpoly_factor_length(const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) Return the length of the product in *f*. .. function:: void fmpz_mpoly_factor_get_constant_fmpz(fmpz_t c, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_factor_get_constant_fmpq(fmpq_t c, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) Set `c` to the constant of *f*. .. function:: void fmpz_mpoly_factor_get_base(fmpz_mpoly_t B, const fmpz_mpoly_factor_t f, slong i, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_factor_swap_base(fmpz_mpoly_t B, fmpz_mpoly_factor_t f, slong i, const fmpz_mpoly_ctx_t ctx) Set (resp. swap) *B* to (resp. with) the base of the term of index `i` in *A*. .. function:: slong fmpz_mpoly_factor_get_exp_si(fmpz_mpoly_factor_t f, slong i, const fmpz_mpoly_ctx_t ctx) Return the exponent of the term of index `i` in *A*. It is assumed to fit an ``slong``. .. function:: void fmpz_mpoly_factor_sort(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) Sort the product of *f* first by exponent and then by base. Factorisation -------------------------------------------------------------------------------- A return of `1` indicates that the function was successful. Otherwise, the return is `0` and *f* is undefined. None of these functions multiply *f* by *A*: *f* is simply set to a factorisation of *A*, and thus these functions should not depend on the initial value of the output *f*. .. function:: int fmpz_mpoly_factor_squarefree(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are primitive and pairwise relatively prime. If the product of all irreducible factors with a given exponent is desired, it is recommended to call :func:`fmpz_mpoly_factor_sort` and then multiply the bases with the desired exponent. .. function:: int fmpz_mpoly_factor(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are irreducible. flint-3.1.3/doc/source/fmpz_mpoly_q.rst000066400000000000000000000232231461254215100201500ustar00rootroot00000000000000.. _fmpz-mpoly-q: **fmpz_mpoly_q.h** -- multivariate rational functions over Q =============================================================================== An :type:`fmpz_mpoly_q_t` represents an element of `\mathbb{Q}(x_1,\ldots,x_n)` for fixed *n* as a pair of Flint multivariate polynomials (:type:`fmpz_mpoly_t`). Instances are always kept in canonical form by ensuring that the GCD of numerator and denominator is 1 and that the coefficient of the leading term of the denominator is positive. The user must create a multivariate polynomial context (:type:`fmpz_mpoly_ctx_t`) specifying the number of variables *n* and the monomial ordering. Types and macros ------------------------------------------------------------------------------- .. type:: fmpz_mpoly_q_struct .. type:: fmpz_mpoly_q_t An *fmpz_mpoly_q_struct* consists of a pair of *fmpz_mpoly_struct*:s. An *fmpz_mpoly_q_t* is defined as an array of length one of type *fmpz_mpoly_q_struct*, permitting an *fmpz_mpoly_q_t* to be passed by reference. .. macro:: fmpz_mpoly_q_numref(x) Macro returning a pointer to the numerator of *x* which can be used as an *fmpz_mpoly_t*. .. macro:: fmpz_mpoly_q_denref(x) Macro returning a pointer to the denominator of *x* which can be used as an *fmpz_mpoly_t*. Memory management ------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_q_init(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) Initializes *res* for use, and sets its value to zero. .. function:: void fmpz_mpoly_q_clear(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) Clears *res*, freeing or recycling its allocated memory. Assignment ------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_q_swap(fmpz_mpoly_q_t x, fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) Swaps the values of *x* and *y* efficiently. .. function:: void fmpz_mpoly_q_set(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_set_fmpq(fmpz_mpoly_q_t res, const fmpq_t x, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_set_fmpz(fmpz_mpoly_q_t res, const fmpz_t x, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_set_si(fmpz_mpoly_q_t res, slong x, const fmpz_mpoly_ctx_t ctx) Sets *res* to the value *x*. Canonicalisation ------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_q_canonicalise(fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) Puts the numerator and denominator of *x* in canonical form by removing common content and making the leading term of the denominator positive. .. function:: int fmpz_mpoly_q_is_canonical(const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) Returns whether *x* is in canonical form. In addition to verifying that the numerator and denominator have no common content and that the leading term of the denominator is positive, this function checks that the denominator is nonzero and that the numerator and denominator have correctly sorted terms (these properties should normally hold; verifying them provides an extra consistency check for test code). Properties ------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_q_is_zero(const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) Returns whether *x* is the constant 0. .. function:: int fmpz_mpoly_q_is_one(const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) Returns whether *x* is the constant 1. .. function:: void fmpz_mpoly_q_used_vars(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_used_vars_num(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_used_vars_den(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx) For each variable, sets the corresponding entry in *used* to the boolean flag indicating whether that variable appears in the rational function (respectively its numerator or denominator). Special values ------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_q_zero(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) Sets *res* to the constant 0. .. function:: void fmpz_mpoly_q_one(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) Sets *res* to the constant 1. .. function:: void fmpz_mpoly_q_gen(fmpz_mpoly_q_t res, slong i, const fmpz_mpoly_ctx_t ctx) Sets *res* to the generator `x_{i+1}`. Requires `0 \le i < n` where *n* is the number of variables of *ctx*. Input and output ------------------------------------------------------------------------------- The variable strings in *x* start with the variable of most significance at index `0`. If *x* is ``NULL``, the variables are named ``x1``, ``x2``, etc. .. function:: void fmpz_mpoly_q_print_pretty(const fmpz_mpoly_q_t f, const char ** x, const fmpz_mpoly_ctx_t ctx) Prints *res* to standard output. If *x* is not *NULL*, the strings in *x* are used as the symbols for the variables. .. function:: char * fmpz_mpoly_q_get_str_pretty(const fmpz_mpoly_q_t f, const char ** x, const fmpz_mpoly_ctx_t ctx) Return a string, which the user is responsible for cleaning up, representing *f*, given an array of variable strings *x*. .. function:: int fmpz_mpoly_q_set_str_pretty(fmpz_mpoly_q_t res, const char * s, const char ** x, fmpz_mpoly_ctx_t ctx) Set *res* to the fraction in the null-terminated string *str* given an array *x* of variable strings. If parsing *str* fails, *res* is set to zero, and `-1` is returned. Otherwise, `0` is returned. The operations ``+``, ``-``, ``*``, and ``/`` are permitted along with integers and the variables in *x*. The character ``^`` must be immediately followed by the (integer) exponent. If division by zero occurs, parsing fails. Random generation ------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_q_randtest(fmpz_mpoly_q_t res, flint_rand_t state, slong length, mp_limb_t coeff_bits, slong exp_bound, const fmpz_mpoly_ctx_t ctx) Sets *res* to a random rational function where both numerator and denominator have up to *length* terms, coefficients up to size *coeff_bits*, and exponents strictly smaller than *exp_bound*. Comparisons ------------------------------------------------------------------------------- .. function:: int fmpz_mpoly_q_equal(const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) Returns whether *x* and *y* are equal. Arithmetic ------------------------------------------------------------------------------- .. function:: void fmpz_mpoly_q_neg(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) Sets *res* to the negation of *x*. .. function:: void fmpz_mpoly_q_add(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_add_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_add_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_add_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong y, const fmpz_mpoly_ctx_t ctx) Sets *res* to the sum of *x* and *y*. .. function:: void fmpz_mpoly_q_sub(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_sub_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_sub_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong y, const fmpz_mpoly_ctx_t ctx) Sets *res* to the difference of *x* and *y*. .. function:: void fmpz_mpoly_q_mul(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_mul_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_mul_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong y, const fmpz_mpoly_ctx_t ctx) Sets *res* to the product of *x* and *y*. .. function:: void fmpz_mpoly_q_div(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_div_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_div_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_div_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong y, const fmpz_mpoly_ctx_t ctx) Sets *res* to the quotient of *x* and *y*. Division by zero calls *flint_abort*. .. function:: void fmpz_mpoly_q_inv(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) Sets *res* to the inverse of *x*. Division by zero calls *flint_abort*. Content ------------------------------------------------------------------------------- .. function:: void _fmpz_mpoly_q_content(fmpz_t num, fmpz_t den, const fmpz_mpoly_t xnum, const fmpz_mpoly_t xden, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_q_content(fmpq_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) Sets *res* to the content of the coefficients of *x*. .. raw:: latex \newpage flint-3.1.3/doc/source/fmpz_poly.rst000066400000000000000000004442171461254215100174650ustar00rootroot00000000000000.. _fmpz-poly: **fmpz_poly.h** -- univariate polynomials over the integers =============================================================================== Introduction ------------ The :type:`fmpz_poly_t` data type represents elements of `\mathbb{Z}[x]`. The :type:`fmpz_poly` module provides routines for memory management, basic arithmetic, and conversions from or to other types. Each coefficient of an :type:`fmpz_poly_t` is an integer of the FLINT :type:`fmpz_t` type. There are two advantages of this model. Firstly, the :type:`fmpz_t` type is memory managed, so the user can manipulate individual coefficients of a polynomial without having to deal with tedious memory management. Secondly, a coefficient of an :type:`fmpz_poly_t` can be changed without changing the size of any of the other coefficients. Unless otherwise specified, all functions in this section permit aliasing between their input arguments and between their input and output arguments. .. _simple-example-2: Simple example -------------- The following example computes the square of the polynomial `5x^3 - 1`. .. code:: c #include "fmpz_poly.h" int main() { fmpz_poly_t x, y; fmpz_poly_init(x); fmpz_poly_init(y); fmpz_poly_set_coeff_ui(x, 3, 5); fmpz_poly_set_coeff_si(x, 0, -1); fmpz_poly_mul(y, x, x); fmpz_poly_print(x); flint_printf("\n"); fmpz_poly_print(y); flint_printf("\n"); fmpz_poly_clear(x); fmpz_poly_clear(y); } The output is: :: 4 -1 0 0 5 7 1 0 0 -10 0 0 25 Definition of the fmpz_poly_t type ---------------------------------- The :type:`fmpz_poly_t` type is a typedef for an array of length 1 of :type:`fmpz_poly_struct`'s. This permits passing parameters of type :type:`fmpz_poly_t` by reference in a manner similar to the way GMP integers of type ``mpz_t`` can be passed by reference. In reality one never deals directly with the ``struct`` and simply deals with objects of type :type:`fmpz_poly_t`. For simplicity we will think of an :type:`fmpz_poly_t` as a ``struct``, though in practice to access fields of this ``struct``, one needs to dereference first, e.g. to access the ``length`` field of an :type:`fmpz_poly_t` called ``poly1`` one writes ``poly1->length``. An :type:`fmpz_poly_t` is said to be *normalised* if either ``length`` is zero, or if the leading coefficient of the polynomial is non-zero. All :type:`fmpz_poly` functions expect their inputs to be normalised, and unless otherwise specified they produce output that is normalised. It is recommended that users do not access the fields of an :type:`fmpz_poly_t` or its coefficient data directly, but make use of the functions designed for this purpose, detailed below. Functions in ``fmpz_poly`` do all the memory management for the user. One does not need to specify the maximum length or number of limbs per coefficient in advance before using a polynomial object. FLINT reallocates space automatically as the computation proceeds, if more space is required. Each coefficient is also managed separately, being resized as needed, independently of the other coefficients. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_struct .. type:: fmpz_poly_t Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_poly_init(fmpz_poly_t poly) Initialises ``poly`` for use, setting its length to zero. A corresponding call to :func:`fmpz_poly_clear` must be made after finishing with the ``fmpz_poly_t`` to free the memory used by the polynomial. .. function:: void fmpz_poly_init2(fmpz_poly_t poly, slong alloc) Initialises ``poly`` with space for at least ``alloc`` coefficients and sets the length to zero. The allocated coefficients are all set to zero. .. function:: void fmpz_poly_realloc(fmpz_poly_t poly, slong alloc) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` the polynomial is first truncated to length ``alloc``. .. function:: void fmpz_poly_fit_length(fmpz_poly_t poly, slong len) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where ``fit_length`` is called many times in small increments by at least doubling the number of allocated coefficients when length is larger than the number of coefficients currently allocated. .. function:: void fmpz_poly_clear(fmpz_poly_t poly) Clears the given polynomial, releasing any memory used. It must be reinitialised in order to be used again. .. function:: void _fmpz_poly_normalise(fmpz_poly_t poly) Sets the length of ``poly`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void _fmpz_poly_set_length(fmpz_poly_t poly, slong newlen) Demotes the coefficients of ``poly`` beyond ``newlen`` and sets the length of ``poly`` to ``newlen``. .. function:: void fmpz_poly_attach_truncate(fmpz_poly_t trunc, const fmpz_poly_t poly, slong n) This function sets the uninitialised polynomial ``trunc`` to the low `n` coefficients of ``poly``, or to ``poly`` if the latter doesn't have `n` coefficients. The polynomial ``trunc`` not be cleared or used as the output of any Flint functions. .. function:: void fmpz_poly_attach_shift(fmpz_poly_t trunc, const fmpz_poly_t poly, slong n) This function sets the uninitialised polynomial ``trunc`` to the high coefficients of ``poly``, i.e. the coefficients not among the low `n` coefficients of ``poly``. If the latter doesn't have `n` coefficients ``trunc`` is set to the zero polynomial. The polynomial ``trunc`` not be cleared or used as the output of any Flint functions. Polynomial parameters -------------------------------------------------------------------------------- .. function:: slong fmpz_poly_length(const fmpz_poly_t poly) Returns the length of ``poly``. The zero polynomial has length zero. .. function:: slong fmpz_poly_degree(const fmpz_poly_t poly) Returns the degree of ``poly``, which is one less than its length. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void fmpz_poly_set(fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``poly1`` to equal ``poly2``. .. function:: void fmpz_poly_set_si(fmpz_poly_t poly, slong c) Sets ``poly`` to the signed integer ``c``. .. function:: void fmpz_poly_set_ui(fmpz_poly_t poly, ulong c) Sets ``poly`` to the unsigned integer ``c``. .. function:: void fmpz_poly_set_fmpz(fmpz_poly_t poly, const fmpz_t c) Sets ``poly`` to the integer ``c``. .. function:: int _fmpz_poly_set_str(fmpz * poly, const char * str) Sets ``poly`` to the polynomial encoded in the null-terminated string ``str``. Assumes that ``poly`` is allocated as a sufficiently large array suitable for the number of coefficients present in ``str``. Returns `0` if no error occurred. Otherwise, returns a non-zero value, in which case the resulting value of ``poly`` is undefined. If ``str`` is not null-terminated, calling this method might result in a segmentation fault. .. function:: int fmpz_poly_set_str(fmpz_poly_t poly, const char * str) Imports a polynomial from a null-terminated string. If the string ``str`` represents a valid polynomial returns `0`, otherwise returns `1`. Returns `0` if no error occurred. Otherwise, returns a non-zero value, in which case the resulting value of ``poly`` is undefined. If ``str`` is not null-terminated, calling this method might result in a segmentation fault. .. function:: char * _fmpz_poly_get_str(const fmpz * poly, slong len) Returns the plain FLINT string representation of the polynomial ``(poly, len)``. .. function:: char * fmpz_poly_get_str(const fmpz_poly_t poly) Returns the plain FLINT string representation of the polynomial ``poly``. .. function:: char * _fmpz_poly_get_str_pretty(const fmpz * poly, slong len, const char * x) Returns a pretty representation of the polynomial ``(poly, len)`` using the null-terminated string ``x`` as the variable name. .. function:: char * fmpz_poly_get_str_pretty(const fmpz_poly_t poly, const char * x) Returns a pretty representation of the polynomial ``poly`` using the null-terminated string ``x`` as the variable name. .. function:: void fmpz_poly_zero(fmpz_poly_t poly) Sets ``poly`` to the zero polynomial. .. function:: void fmpz_poly_one(fmpz_poly_t poly) Sets ``poly`` to the constant polynomial one. .. function:: void fmpz_poly_zero_coeffs(fmpz_poly_t poly, slong i, slong j) Sets the coefficients of `x^i, \dotsc, x^{j-1}` to zero. .. function:: void fmpz_poly_swap(fmpz_poly_t poly1, fmpz_poly_t poly2) Swaps ``poly1`` and ``poly2``. This is done efficiently without copying data by swapping pointers, etc. .. function:: void _fmpz_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, n)`` to the reverse of ``(poly, n)``, where ``poly`` is in fact an array of length ``len``. Assumes that ``0 < len <= n``. Supports aliasing of ``res`` and ``poly``, but the behaviour is undefined in case of partial overlap. .. function:: void fmpz_poly_reverse(fmpz_poly_t res, const fmpz_poly_t poly, slong n) This function considers the polynomial ``poly`` to be of length `n`, notionally truncating and zero padding if required, and reverses the result. Since the function normalises its result ``res`` may be of length less than `n`. .. function:: void fmpz_poly_truncate(fmpz_poly_t poly, slong newlen) If the current length of ``poly`` is greater than ``newlen``, it is truncated to have the given length. Discarded coefficients are not necessarily set to zero. .. function:: void fmpz_poly_set_trunc(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Sets ``res`` to a copy of ``poly``, truncated to length ``n``. Randomisation -------------------------------------------------------------------------------- .. function:: void fmpz_poly_randtest(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets `f` to a random polynomial with up to the given length and where each coefficient has up to the given number of bits. The coefficients are signed randomly. .. function:: void fmpz_poly_randtest_unsigned(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets `f` to a random polynomial with up to the given length and where each coefficient has up to the given number of bits. .. function:: void fmpz_poly_randtest_not_zero(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) As for :func:`fmpz_poly_randtest` except that ``len`` and bits may not be zero and the polynomial generated is guaranteed not to be the zero polynomial. .. function:: void fmpz_poly_randtest_no_real_root(fmpz_poly_t p, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets ``p`` to a random polynomial without any real root, whose length is up to ``len`` and where each coefficient has up to the given number of bits. .. function:: void fmpz_poly_randtest_irreducible1(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits) void fmpz_poly_randtest_irreducible2(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits) void fmpz_poly_randtest_irreducible(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits) Sets ``p`` to a random irreducible polynomial, whose length is up to ``len`` and where each coefficient has up to the given number of bits. There are two algorithms: *irreducible1* generates an irreducible polynomial modulo a random prime number and lifts it to the integers; *irreducible2* generates a random integer polynomial, factors it, and returns a random factor. The default function chooses randomly between these methods. Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void fmpz_poly_get_coeff_fmpz(fmpz_t x, const fmpz_poly_t poly, slong n) Sets `x` to the `n`-th coefficient of ``poly``. Coefficient numbering is from zero and if `n` is set to a value beyond the end of the polynomial, zero is returned. .. function:: slong fmpz_poly_get_coeff_si(const fmpz_poly_t poly, slong n) Returns coefficient `n` of ``poly`` as a ``slong``. The result is undefined if the value does not fit into a ``slong``. Coefficient numbering is from zero and if `n` is set to a value beyond the end of the polynomial, zero is returned. .. function:: ulong fmpz_poly_get_coeff_ui(const fmpz_poly_t poly, slong n) Returns coefficient `n` of ``poly`` as a ``ulong``. The result is undefined if the value does not fit into a ``ulong``. Coefficient numbering is from zero and if `n` is set to a value beyond the end of the polynomial, zero is returned. .. function:: fmpz * fmpz_poly_get_coeff_ptr(const fmpz_poly_t poly, slong n) Returns a reference to the coefficient of `x^n` in the polynomial, as an ``fmpz *``. This function is provided so that individual coefficients can be accessed and operated on by functions in the ``fmpz`` module. This function does not make a copy of the data, but returns a reference to the actual coefficient. Returns ``NULL`` when `n` exceeds the degree of the polynomial. This function is implemented as a macro. .. function:: fmpz * fmpz_poly_lead(const fmpz_poly_t poly) Returns a reference to the leading coefficient of the polynomial, as an ``fmpz *``. This function is provided so that the leading coefficient can be easily accessed and operated on by functions in the ``fmpz`` module. This function does not make a copy of the data, but returns a reference to the actual coefficient. Returns ``NULL`` when the polynomial is zero. This function is implemented as a macro. .. function:: void fmpz_poly_set_coeff_fmpz(fmpz_poly_t poly, slong n, const fmpz_t x) Sets coefficient `n` of ``poly`` to the ``fmpz`` value ``x``. Coefficient numbering starts from zero and if `n` is beyond the current length of ``poly`` then the polynomial is extended and zero coefficients inserted if necessary. .. function:: void fmpz_poly_set_coeff_si(fmpz_poly_t poly, slong n, slong x) Sets coefficient `n` of ``poly`` to the ``slong`` value ``x``. Coefficient numbering starts from zero and if `n` is beyond the current length of ``poly`` then the polynomial is extended and zero coefficients inserted if necessary. .. function:: void fmpz_poly_set_coeff_ui(fmpz_poly_t poly, slong n, ulong x) Sets coefficient `n` of ``poly`` to the ``ulong`` value ``x``. Coefficient numbering starts from zero and if `n` is beyond the current length of ``poly`` then the polynomial is extended and zero coefficients inserted if necessary. Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_poly_equal(const fmpz_poly_t poly1, const fmpz_poly_t poly2) Returns `1` if ``poly1`` is equal to ``poly2``, otherwise returns `0`. The polynomials are assumed to be normalised. .. function:: int fmpz_poly_equal_trunc(const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Return `1` if ``poly1`` and ``poly2``, notionally truncated to length `n` are equal, otherwise return `0`. .. function:: int fmpz_poly_is_zero(const fmpz_poly_t poly) Returns `1` if the polynomial is zero and `0` otherwise. This function is implemented as a macro. .. function:: int fmpz_poly_is_one(const fmpz_poly_t poly) Returns `1` if the polynomial is one and `0` otherwise. .. function:: int fmpz_poly_is_unit(const fmpz_poly_t poly) Returns `1` if the polynomial is the constant polynomial `\pm 1`, and `0` otherwise. .. function:: int fmpz_poly_is_gen(const fmpz_poly_t poly) Returns `1` if the polynomial is the degree `1` polynomial `x`, and `0` otherwise. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_add(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to the sum of ``(poly1, len1)`` and ``(poly2, len2)``. It is assumed that ``res`` has sufficient space for the longer of the two polynomials. .. function:: void fmpz_poly_add(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the sum of ``poly1`` and ``poly2``. .. function:: void fmpz_poly_add_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Notionally truncate ``poly1`` and ``poly2`` to length `n` and then set ``res`` to the sum. .. function:: void _fmpz_poly_sub(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to ``(poly1, len1)`` minus ``(poly2, len2)``. It is assumed that ``res`` has sufficient space for the longer of the two polynomials. .. function:: void fmpz_poly_sub(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to ``poly1`` minus ``poly2``. .. function:: void fmpz_poly_sub_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Notionally truncate ``poly1`` and ``poly2`` to length `n` and then set ``res`` to the sum. .. function:: void fmpz_poly_neg(fmpz_poly_t res, const fmpz_poly_t poly) Sets ``res`` to ``-poly``. Scalar absolute value, multiplication and division -------------------------------------------------------------------------------- .. function:: void fmpz_poly_scalar_abs(fmpz_poly_t res, const fmpz_poly_t poly) Sets ``poly1`` to the polynomial whose coefficients are the absolute value of those of ``poly2``. .. function:: void fmpz_poly_scalar_mul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) Sets ``poly1`` to ``poly2`` times `x`. .. function:: void fmpz_poly_scalar_mul_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) Sets ``poly1`` to ``poly2`` times the signed ``slong x``. .. function:: void fmpz_poly_scalar_mul_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) Sets ``poly1`` to ``poly2`` times the ``ulong x``. .. function:: void fmpz_poly_scalar_mul_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp) Sets ``poly1`` to ``poly2`` times ``2^exp``. .. function:: void fmpz_poly_scalar_addmul_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) .. function:: void fmpz_poly_scalar_addmul_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) .. function:: void fmpz_poly_scalar_addmul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) Sets ``poly1`` to ``poly1 + x * poly2``. .. function:: void fmpz_poly_scalar_submul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) Sets ``poly1`` to ``poly1 - x * poly2``. .. function:: void fmpz_poly_scalar_fdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) Sets ``poly1`` to ``poly2`` divided by the ``fmpz_t x``, rounding coefficients down toward `- \infty`. .. function:: void fmpz_poly_scalar_fdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) Sets ``poly1`` to ``poly2`` divided by the ``slong x``, rounding coefficients down toward `- \infty`. .. function:: void fmpz_poly_scalar_fdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) Sets ``poly1`` to ``poly2`` divided by the ``ulong x``, rounding coefficients down toward `- \infty`. .. function:: void fmpz_poly_scalar_fdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) Sets ``poly1`` to ``poly2`` divided by ``2^x``, rounding coefficients down toward `- \infty`. .. function:: void fmpz_poly_scalar_tdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) Sets ``poly1`` to ``poly2`` divided by the ``fmpz_t x``, rounding coefficients toward `0`. .. function:: void fmpz_poly_scalar_tdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) Sets ``poly1`` to ``poly2`` divided by the ``slong x``, rounding coefficients toward `0`. .. function:: void fmpz_poly_scalar_tdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) Sets ``poly1`` to ``poly2`` divided by the ``ulong x``, rounding coefficients toward `0`. .. function:: void fmpz_poly_scalar_tdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) Sets ``poly1`` to ``poly2`` divided by ``2^x``, rounding coefficients toward `0`. .. function:: void fmpz_poly_scalar_divexact_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) Sets ``poly1`` to ``poly2`` divided by the ``fmpz_t x``, assuming the division is exact for every coefficient. .. function:: void fmpz_poly_scalar_divexact_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) Sets ``poly1`` to ``poly2`` divided by the ``slong x``, assuming the coefficient is exact for every coefficient. .. function:: void fmpz_poly_scalar_divexact_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) Sets ``poly1`` to ``poly2`` divided by the ``ulong x``, assuming the coefficient is exact for every coefficient. .. function:: void fmpz_poly_scalar_mod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t p) Sets ``poly1`` to ``poly2``, reducing each coefficient modulo `p > 0`. .. function:: void fmpz_poly_scalar_smod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t p) Sets ``poly1`` to ``poly2``, symmetrically reducing each coefficient modulo `p > 0`, that is, choosing the unique representative in the interval `(-p/2, p/2]`. .. function:: slong _fmpz_poly_remove_content_2exp(fmpz * pol, slong len) Remove the 2-content of ``pol`` and return the number `k` that is the maximal non-negative integer so that `2^k` divides all coefficients of the polynomial. For the zero polynomial, `0` is returned. .. function:: void _fmpz_poly_scale_2exp(fmpz * pol, slong len, slong k) Scale ``(pol, len)`` to `p(2^k X)` in-place and divide by the 2-content (so that the gcd of coefficients is odd). If ``k`` is negative the polynomial is multiplied by `2^{kd}`. Bit packing -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_bit_pack(mp_ptr arr, const fmpz * poly, slong len, flint_bitcnt_t bit_size, int negate) Packs the coefficients of ``poly`` into bitfields of the given ``bit_size``, negating the coefficients before packing if ``negate`` is set to `-1`. .. function:: int _fmpz_poly_bit_unpack(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size, int negate) Unpacks the polynomial of given length from the array as packed into fields of the given ``bit_size``, finally negating the coefficients if ``negate`` is set to `-1`. Returns borrow, which is nonzero if a leading term with coefficient `\pm1` should be added at position ``len`` of ``poly``. .. function:: void _fmpz_poly_bit_unpack_unsigned(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size) Unpacks the polynomial of given length from the array as packed into fields of the given ``bit_size``. The coefficients are assumed to be unsigned. .. function:: void fmpz_poly_bit_pack(fmpz_t f, const fmpz_poly_t poly, flint_bitcnt_t bit_size) Packs ``poly`` into bitfields of size ``bit_size``, writing the result to ``f``. The sign of ``f`` will be the same as that of the leading coefficient of ``poly``. .. function:: void fmpz_poly_bit_unpack(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size) Unpacks the polynomial with signed coefficients packed into fields of size ``bit_size`` as represented by the integer ``f``. .. function:: void fmpz_poly_bit_unpack_unsigned(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size) Unpacks the polynomial with unsigned coefficients packed into fields of size ``bit_size`` as represented by the integer ``f``. It is required that ``f`` is nonnegative. Multiplication -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``(res, len1 + len2 - 1)`` to the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes ``len1`` and ``len2`` are positive. Allows zero-padding of the two input polynomials. No aliasing of inputs with outputs is allowed. .. function:: void fmpz_poly_mul_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``, computed using the classical or schoolbook method. .. function:: void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) Sets ``(res, n)`` to the first `n` coefficients of ``(poly1, len1)`` multiplied by ``(poly2, len2)``. Assumes ``0 < n <= len1 + len2 - 1``. Assumes neither ``len1`` nor ``len2`` is zero. .. function:: void fmpz_poly_mullow_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the first `n` coefficients of ``poly1 * poly2``. .. function:: void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start) Sets the first ``start`` coefficients of ``res`` to zero and the remainder to the corresponding coefficients of ``(poly1, len1) * (poly2, len2)``. Assumes ``start <= len1 + len2 - 1``. Assumes neither ``len1`` nor ``len2`` is zero. .. function:: void fmpz_poly_mulhigh_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong start) Sets the first ``start`` coefficients of ``res`` to zero and the remainder to the corresponding coefficients of the product of ``poly1`` and ``poly2``. .. function:: void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to the middle ``len1 - len2 + 1`` coefficients of the product of ``(poly1, len1)`` and ``(poly2, len2)``, i.e. the coefficients from degree ``len2 - 1`` to ``len1 - 1`` inclusive. Assumes that ``len1 >= len2 > 0``. .. function:: void fmpz_poly_mulmid_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the middle ``len(poly1) - len(poly2) + 1`` coefficients of ``poly1 * poly2``, i.e. the coefficient from degree ``len2 - 1`` to ``len1 - 1`` inclusive. Assumes that ``len1 >= len2``. .. function:: void _fmpz_poly_mul_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``(res, len1 + len2 - 1)`` to the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes ``len1 >= len2 > 0``. Allows zero-padding of the two input polynomials. No aliasing of inputs with outputs is allowed. .. function:: void fmpz_poly_mul_karatsuba(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _fmpz_poly_mullow_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong n) Sets ``res`` to the product of ``poly1`` and ``poly2`` and truncates to the given length. It is assumed that ``poly1`` and ``poly2`` are precisely the given length, possibly zero padded. Assumes `n` is not zero. .. function:: void fmpz_poly_mullow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the product of ``poly1`` and ``poly2`` and truncates to the given length. .. function:: void _fmpz_poly_mulhigh_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong len) Sets ``res`` to the product of ``poly1`` and ``poly2`` and truncates at the top to the given length. The first ``len - 1`` coefficients are set to zero. It is assumed that ``poly1`` and ``poly2`` are precisely the given length, possibly zero padded. Assumes ``len`` is not zero. .. function:: void fmpz_poly_mulhigh_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong len) Sets the first ``len - 1`` coefficients of the result to zero and the remaining coefficients to the corresponding coefficients of the product of ``poly1`` and ``poly2``. Assumes ``poly1`` and ``poly2`` are at most of the given length. .. function:: void _fmpz_poly_mul_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``(res, len1 + len2 - 1)`` to the product of ``(poly1, len1)`` and ``(poly2, len2)``. Places no assumptions on ``len1`` and ``len2``. Allows zero-padding of the two input polynomials. Supports aliasing of inputs and outputs. .. function:: void fmpz_poly_mul_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _fmpz_poly_mullow_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) Sets ``(res, n)`` to the lowest `n` coefficients of the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``len1`` and ``len2`` are positive, but does allow for the polynomials to be zero-padded. The polynomials may be zero, too. Assumes `n` is positive. Supports aliasing between ``res``, ``poly1`` and ``poly2``. .. function:: void fmpz_poly_mullow_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the lowest `n` coefficients of the product of ``poly1`` and ``poly2``. .. function:: void _fmpz_poly_mul_SS(fmpz * output, const fmpz * input1, slong length1, const fmpz * input2, slong length2) Sets ``(output, length1 + length2 - 1)`` to the product of ``(input1, length1)`` and ``(input2, length2)``. We must have ``len1 > 1`` and ``len2 > 1``. Allows zero-padding of the two input polynomials. Supports aliasing of inputs and outputs. .. function:: void fmpz_poly_mul_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. Uses the Schönhage-Strassen algorithm. .. function:: void _fmpz_poly_mullow_SS(fmpz * output, const fmpz * input1, slong length1, const fmpz * input2, slong length2, slong n) Sets ``(res, n)`` to the lowest `n` coefficients of the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``len1`` and ``len2`` are positive, but does allow for the polynomials to be zero-padded. We must have ``len1 > 1`` and ``len2 > 1``. Assumes `n` is positive. Supports aliasing between ``res``, ``poly1`` and ``poly2``. .. function:: void fmpz_poly_mullow_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the lowest `n` coefficients of the product of ``poly1`` and ``poly2``. .. function:: void _fmpz_poly_mul(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``(res, len1 + len2 - 1)`` to the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes ``len1 >= len2 > 0``. Allows zero-padding of the two input polynomials. Does not support aliasing between the inputs and the output. .. function:: void fmpz_poly_mul(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. Chooses an optimal algorithm from the choices above. .. function:: void _fmpz_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) Sets ``(res, n)`` to the lowest `n` coefficients of the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes ``len1 >= len2 > 0`` and ``0 < n <= len1 + len2 - 1``. Allows for zero-padding in the inputs. Does not support aliasing between the inputs and the output. .. function:: void fmpz_poly_mullow(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the lowest `n` coefficients of the product of ``poly1`` and ``poly2``. .. function:: void fmpz_poly_mulhigh_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets the high `n` coefficients of ``res`` to the high `n` coefficients of the product of ``poly1`` and ``poly2``, assuming the latter are precisely `n` coefficients in length, zero padded if necessary. The remaining `n - 1` coefficients may be arbitrary. .. function:: void _fmpz_poly_mulhigh(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start) Sets all but the low `n` coefficients of `res` to the corresponding coefficients of the product of `poly1` of length `len1` and `poly2` of length `len2`, the remaining coefficients being arbitrary. It is assumed that `len1 >= len2 > 0` and that `0 < n < len1 + len2 - 1`. Aliasing of inputs is not permitted. FFT precached multiplication -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mul_SS_precache_init(fmpz_poly_mul_precache_t pre, slong len1, slong bits1, const fmpz_poly_t poly2) Precompute the FFT of ``poly2`` to enable repeated multiplication of ``poly2`` by polynomials whose length does not exceed ``len1`` and whose number of bits per coefficient does not exceed ``bits1``. The value ``bits1`` may be negative, i.e. it may be the result of calling ``fmpz_poly_max_bits``. The function only considers the absolute value of ``bits1``. Suppose ``len2`` is the length of ``poly2`` and ``len = len1 + len2 - 1`` is the maximum output length of a polynomial multiplication using ``pre``. Then internally ``len`` is rounded up to a power of two, `2^n` say. The truncated FFT algorithm is used to smooth performance but note that it can only do this in the range `(2^{n-1}, 2^n]`. Therefore, it may be more efficient to recompute `pre` for cases where the output length will fall below `2^{n-1} + 1`. Otherwise the implementation will zero pad them up to that length. Note that the Schoenhage-Strassen algorithm is only efficient for polynomials with relatively large coefficients relative to the length of the polynomials. Also note that there are no restrictions on the polynomials. In particular the polynomial whose FFT is being precached does not have to be either longer or shorter than the polynomials it is to be multiplied by. .. function:: void fmpz_poly_mul_precache_clear(fmpz_poly_mul_precache_t pre) Clear the space allocated by ``fmpz_poly_mul_SS_precache_init``. .. function:: void _fmpz_poly_mullow_SS_precache(fmpz * output, const fmpz * input1, slong len1, fmpz_poly_mul_precache_t pre, slong trunc) Write into ``output`` the first ``trunc`` coefficients of the polynomial ``(input1, len1)`` by the polynomial whose FFT was precached by ``fmpz_poly_mul_SS_precache_init`` and stored in ``pre``. For performance reasons it is recommended that all polynomials be truncated to at most ``trunc`` coefficients if possible. .. function:: void fmpz_poly_mullow_SS_precache(fmpz_poly_t res, const fmpz_poly_t poly1, fmpz_poly_mul_precache_t pre, slong n) Set ``res`` to the product of ``poly1`` by the polynomial whose FFT was precached by ``fmpz_poly_mul_SS_precache_init`` (and stored in pre). The result is truncated to `n` coefficients (and normalised). There are no restrictions on the length of ``poly1`` other than those given in the call to ``fmpz_poly_mul_SS_precache_init``. .. function:: void fmpz_poly_mul_SS_precache(fmpz_poly_t res, const fmpz_poly_t poly1, fmpz_poly_mul_precache_t pre) Set ``res`` to the product of ``poly1`` by the polynomial whose FFT was precached by ``fmpz_poly_mul_SS_precache_init`` (and stored in pre). There are no restrictions on the length of ``poly1`` other than those given in the call to ``fmpz_poly_mul_SS_precache_init``. Squaring -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_sqr_KS(fmpz * rop, const fmpz * op, slong len) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``, assuming that ``len > 0``. Supports zero-padding in ``(op, len)``. Does not support aliasing. .. function:: void fmpz_poly_sqr_KS(fmpz_poly_t rop, const fmpz_poly_t op) Sets ``rop`` to the square of the polynomial ``op`` using Kronecker segmentation. .. function:: void _fmpz_poly_sqr_karatsuba(fmpz * rop, const fmpz * op, slong len) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``, assuming that ``len > 0``. Supports zero-padding in ``(op, len)``. Does not support aliasing. .. function:: void fmpz_poly_sqr_karatsuba(fmpz_poly_t rop, const fmpz_poly_t op) Sets ``rop`` to the square of the polynomial ``op`` using the Karatsuba multiplication algorithm. .. function:: void _fmpz_poly_sqr_classical(fmpz * rop, const fmpz * op, slong len) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``, assuming that ``len > 0``. Supports zero-padding in ``(op, len)``. Does not support aliasing. .. function:: void fmpz_poly_sqr_classical(fmpz_poly_t rop, const fmpz_poly_t op) Sets ``rop`` to the square of the polynomial ``op`` using the classical or schoolbook method. .. function:: void _fmpz_poly_sqr(fmpz * rop, const fmpz * op, slong len) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``, assuming that ``len > 0``. Supports zero-padding in ``(op, len)``. Does not support aliasing. .. function:: void fmpz_poly_sqr(fmpz_poly_t rop, const fmpz_poly_t op) Sets ``rop`` to the square of the polynomial ``op``. .. function:: void _fmpz_poly_sqrlow_KS(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, n)`` to the lowest `n` coefficients of the square of ``(poly, len)``. Assumes that ``len`` is positive, but does allow for the polynomial to be zero-padded. The polynomial may be zero, too. Assumes `n` is positive. Supports aliasing between ``res`` and ``poly``. .. function:: void fmpz_poly_sqrlow_KS(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Sets ``res`` to the lowest `n` coefficients of the square of ``poly``. .. function:: void _fmpz_poly_sqrlow_karatsuba_n(fmpz * res, const fmpz * poly, slong n) Sets ``(res, n)`` to the square of ``(poly, n)`` truncated to length `n`, which is assumed to be positive. Allows for ``poly`` to be zero-padded. .. function:: void fmpz_poly_sqrlow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Sets ``res`` to the square of ``poly`` and truncates to the given length. .. function:: void _fmpz_poly_sqrlow_classical(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, n)`` to the first `n` coefficients of the square of ``(poly, len)``. Assumes that ``0 < n <= 2 * len - 1``. .. function:: void fmpz_poly_sqrlow_classical(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Sets ``res`` to the first `n` coefficients of the square of ``poly``. .. function:: void _fmpz_poly_sqrlow(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, n)`` to the lowest `n` coefficients of the square of ``(poly, len)``. Assumes ``len1 >= len2 > 0`` and ``0 < n <= 2 * len - 1``. Allows for zero-padding in the input. Does not support aliasing between the input and the output. .. function:: void fmpz_poly_sqrlow(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Sets ``res`` to the lowest `n` coefficients of the square of ``poly``. Powering -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_pow_multinomial(fmpz * res, const fmpz * poly, slong len, ulong e) Computes ``res = poly^e``. This uses the J.C.P. Miller pure recurrence as follows: If `\ell` is the index of the lowest non-zero coefficient in ``poly``, as a first step this method zeros out the lowest `e \ell` coefficients of ``res``. The recurrence above is then used to compute the remaining coefficients. Assumes ``len > 0``, ``e > 0``. Does not support aliasing. .. function:: void fmpz_poly_pow_multinomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) Computes ``res = poly^e`` using a generalisation of binomial expansion called the J.C.P. Miller pure recurrence [1], [2]. If `e` is zero, returns one, so that in particular ``0^0 = 1``. The formal statement of the recurrence is as follows. Write the input polynomial as `P(x) = p_0 + p_1 x + \dotsb + p_m x^m` with `p_0 \neq 0` and let .. math:: P(x)^n = a(n, 0) + a(n, 1) x + \dotsb + a(n, mn) x^{mn}. Then `a(n, 0) = p_0^n` and, for all `1 \leq k \leq mn`, .. math:: a(n, k) = (k p_0)^{-1} \sum_{i = 1}^m p_i \bigl( (n + 1) i - k \bigr) a(n, k-i). [1] D. Knuth, The Art of Computer Programming Vol. 2, Seminumerical Algorithms, Third Edition (Reading, Massachusetts: Addison-Wesley, 1997) [2] D. Zeilberger, The J.C.P. Miller Recurrence for Exponentiating a Polynomial, and its q-Analog, Journal of Difference Equations and Applications, 1995, Vol. 1, pp. 57--60 .. function:: void _fmpz_poly_pow_binomial(fmpz * res, const fmpz * poly, ulong e) Computes ``res = poly^e`` when poly is of length 2, using binomial expansion. Assumes `e > 0`. Does not support aliasing. .. function:: void fmpz_poly_pow_binomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) Computes ``res = poly^e`` when ``poly`` is of length `2`, using binomial expansion. If the length of ``poly`` is not `2`, raises an exception and aborts. .. function:: void _fmpz_poly_pow_addchains(fmpz * res, const fmpz * poly, slong len, const int * a, int n) Given a star chain `1 = a_0 < a_1 < \dotsb < a_n = e` computes ``res = poly^e``. A star chain is an addition chain `1 = a_0 < a_1 < \dotsb < a_n` such that, for all `i > 0`, `a_i = a_{i-1} + a_j` for some `j < i`. Assumes that `e > 2`, or equivalently `n > 1`, and ``len > 0``. Does not support aliasing. .. function:: void fmpz_poly_pow_addchains(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) Computes ``res = poly^e`` using addition chains whenever `0 \leq e \leq 148`. If `e > 148`, raises an exception and aborts. .. function:: void _fmpz_poly_pow_binexp(fmpz * res, const fmpz * poly, slong len, ulong e) Sets ``res = poly^e`` using left-to-right binary exponentiation as described on p. 461 of [Knu1997]_. Assumes that ``len > 0``, ``e > 1``. Assumes that ``res`` is an array of length at least ``e*(len - 1) + 1``. Does not support aliasing. .. function:: void fmpz_poly_pow_binexp(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) Computes ``res = poly^e`` using the binary exponentiation algorithm. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void _fmpz_poly_pow_small(fmpz * res, const fmpz * poly, slong len, ulong e) Sets ``res = poly^e`` whenever `0 \leq e \leq 4`. Assumes that ``len > 0`` and that ``res`` is an array of length at least ``e*(len - 1) + 1``. Does not support aliasing. .. function:: void _fmpz_poly_pow(fmpz * res, const fmpz * poly, slong len, ulong e) Sets ``res = poly^e``, assuming that ``e, len > 0`` and that ``res`` has space for ``e*(len - 1) + 1`` coefficients. Does not support aliasing. .. function:: void fmpz_poly_pow(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) Computes ``res = poly^e``. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void _fmpz_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong n) Sets ``(res, n)`` to ``(poly, n)`` raised to the power `e` and truncated to length `n`. Assumes that `e, n > 0`. Allows zero-padding of ``(poly, n)``. Does not support aliasing of any inputs and outputs. .. function:: void fmpz_poly_pow_trunc(fmpz_poly_t res, const fmpz_poly_t poly, ulong e, slong n) Notationally raises ``poly`` to the power `e`, truncates the result to length `n` and writes the result in ``res``. This is computed much more efficiently than simply powering the polynomial and truncating. Thus, if `n = 0` the result is zero. Otherwise, whenever `e = 0` the result will be the constant polynomial equal to `1`. This function can be used to raise power series to a power in an efficient way. Shifting -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, len + n)`` to ``(poly, len)`` shifted left by `n` coefficients. Inserts zero coefficients at the lower end. Assumes that ``len`` and `n` are positive, and that ``res`` fits ``len + n`` elements. Supports aliasing between ``res`` and ``poly``. .. function:: void fmpz_poly_shift_left(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Sets ``res`` to ``poly`` shifted left by `n` coeffs. Zero coefficients are inserted. .. function:: void _fmpz_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n) Sets ``(res, len - n)`` to ``(poly, len)`` shifted right by `n` coefficients. Assumes that ``len`` and `n` are positive, that ``len > n``, and that ``res`` fits ``len - n`` elements. Supports aliasing between ``res`` and ``poly``, although in this case the top coefficients of ``poly`` are not set to zero. .. function:: void fmpz_poly_shift_right(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Sets ``res`` to ``poly`` shifted right by `n` coefficients. If `n` is equal to or greater than the current length of ``poly``, ``res`` is set to the zero polynomial. Bit sizes and norms -------------------------------------------------------------------------------- .. function:: ulong fmpz_poly_max_limbs(const fmpz_poly_t poly) Returns the maximum number of limbs required to store the absolute value of coefficients of ``poly``. If ``poly`` is zero, returns `0`. .. function:: slong fmpz_poly_max_bits(const fmpz_poly_t poly) Computes the maximum number of bits `b` required to store the absolute value of coefficients of ``poly``. If all the coefficients of ``poly`` are non-negative, `b` is returned, otherwise `-b` is returned. .. function:: void fmpz_poly_height(fmpz_t height, const fmpz_poly_t poly) Computes the height of ``poly``, defined as the largest of the absolute values of the coefficients of ``poly``. Equivalently, this gives the infinity norm of the coefficients. If ``poly`` is zero, the height is `0`. .. function:: void _fmpz_poly_2norm(fmpz_t res, const fmpz * poly, slong len) Sets ``res`` to the Euclidean norm of ``(poly, len)``, that is, the integer square root of the sum of the squares of the coefficients of ``poly``. .. function:: void fmpz_poly_2norm(fmpz_t res, const fmpz_poly_t poly) Sets ``res`` to the Euclidean norm of ``poly``, that is, the integer square root of the sum of the squares of the coefficients of ``poly``. .. function:: mp_limb_t _fmpz_poly_2norm_normalised_bits(const fmpz * poly, slong len) Returns an upper bound on the number of bits of the normalised Euclidean norm of ``(poly, len)``, i.e. the number of bits of the Euclidean norm divided by the absolute value of the leading coefficient. The returned value will be no more than 1 bit too large. This is used in the computation of the Landau-Mignotte bound. It is assumed that ``len > 0``. The result only makes sense if the leading coefficient is nonzero. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_gcd_subresultant(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Computes the greatest common divisor ``(res, len2)`` of ``(poly1, len1)`` and ``(poly2, len2)``, assuming ``len1 >= len2 > 0``. The result is normalised to have positive leading coefficient. Aliasing between ``res``, ``poly1`` and ``poly2`` is supported. .. function:: void fmpz_poly_gcd_subresultant(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Computes the greatest common divisor ``res`` of ``poly1`` and ``poly2``, normalised to have non-negative leading coefficient. This function uses the subresultant algorithm as described in Algorithm 3.3.1 of [Coh1996]_. .. function:: int _fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Computes the greatest common divisor ``(res, len2)`` of ``(poly1, len1)`` and ``(poly2, len2)``, assuming ``len1 >= len2 > 0``. The result is normalised to have positive leading coefficient. Aliasing between ``res``, ``poly1`` and ``poly2`` is not supported. The function may not always succeed in finding the GCD. If it fails, the function returns 0, otherwise it returns 1. .. function:: int fmpz_poly_gcd_heuristic(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Computes the greatest common divisor ``res`` of ``poly1`` and ``poly2``, normalised to have non-negative leading coefficient. The function may not always succeed in finding the GCD. If it fails, the function returns 0, otherwise it returns 1. This function uses the heuristic GCD algorithm (GCDHEU). The basic strategy is to remove the content of the polynomials, pack them using Kronecker segmentation (given a bound on the size of the coefficients of the GCD) and take the integer GCD. Unpack the result and test divisibility. .. function:: void _fmpz_poly_gcd_modular(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Computes the greatest common divisor ``(res, len2)`` of ``(poly1, len1)`` and ``(poly2, len2)``, assuming ``len1 >= len2 > 0``. The result is normalised to have positive leading coefficient. Aliasing between ``res``, ``poly1`` and ``poly2`` is not supported. .. function:: void fmpz_poly_gcd_modular(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Computes the greatest common divisor ``res`` of ``poly1`` and ``poly2``, normalised to have non-negative leading coefficient. This function uses the modular GCD algorithm. The basic strategy is to remove the content of the polynomials, reduce them modulo sufficiently many primes and do CRT reconstruction until some bound is reached (or we can prove with trial division that we have the GCD). .. function:: void _fmpz_poly_gcd(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Computes the greatest common divisor ``res`` of ``(poly1, len1)`` and ``(poly2, len2)``, assuming ``len1 >= len2 > 0``. The result is normalised to have positive leading coefficient. Assumes that ``res`` has space for ``len2`` coefficients. Aliasing between ``res``, ``poly1`` and ``poly2`` is not supported. .. function:: void fmpz_poly_gcd(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Computes the greatest common divisor ``res`` of ``poly1`` and ``poly2``, normalised to have non-negative leading coefficient. .. function:: void _fmpz_poly_xgcd_modular(fmpz_t r, fmpz * s, fmpz * t, const fmpz * f, slong len1, const fmpz * g, slong len2) Set `r` to the resultant of ``(f, len1)`` and ``(g, len2)``. If the resultant is zero, the function returns immediately. Otherwise it finds polynomials `s` and `t` such that ``s*f + t*g = r``. The length of `s` will be no greater than ``len2`` and the length of `t` will be no greater than ``len1`` (both are zero padded if necessary). It is assumed that ``len1 >= len2 > 0``. No aliasing of inputs and outputs is permitted. The function assumes that `f` and `g` are primitive (have Gaussian content equal to 1). The result is undefined otherwise. Uses a multimodular algorithm. The resultant is first computed and extended GCDs modulo various primes `p` are computed and combined using CRT. When the CRT stabilises the resulting polynomials are simply reduced modulo further primes until a proven bound is reached. .. function:: void fmpz_poly_xgcd_modular(fmpz_t r, fmpz_poly_t s, fmpz_poly_t t, const fmpz_poly_t f, const fmpz_poly_t g) Set `r` to the resultant of `f` and `g`. If the resultant is zero, the function then returns immediately, otherwise `s` and `t` are found such that ``s*f + t*g = r``. The function assumes that `f` and `g` are primitive (have Gaussian content equal to 1). The result is undefined otherwise. Uses the multimodular algorithm. .. function:: void _fmpz_poly_xgcd(fmpz_t r, fmpz * s, fmpz * t, const fmpz * f, slong len1, const fmpz * g, slong len2) Set `r` to the resultant of ``(f, len1)`` and ``(g, len2)``. If the resultant is zero, the function returns immediately. Otherwise it finds polynomials `s` and `t` such that ``s*f + t*g = r``. The length of `s` will be no greater than ``len2`` and the length of `t` will be no greater than ``len1`` (both are zero padded if necessary). The function assumes that `f` and `g` are primitive (have Gaussian content equal to 1). The result is undefined otherwise. It is assumed that ``len1 >= len2 > 0``. No aliasing of inputs and outputs is permitted. .. function:: void fmpz_poly_xgcd(fmpz_t r, fmpz_poly_t s, fmpz_poly_t t, const fmpz_poly_t f, const fmpz_poly_t g) Set `r` to the resultant of `f` and `g`. If the resultant is zero, the function then returns immediately, otherwise `s` and `t` are found such that ``s*f + t*g = r``. The function assumes that `f` and `g` are primitive (have Gaussian content equal to 1). The result is undefined otherwise. .. function:: void _fmpz_poly_lcm(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``(res, len1 + len2 - 1)`` to the least common multiple of the two polynomials ``(poly1, len1)`` and ``(poly2, len2)``, normalised to have non-negative leading coefficient. Assumes that ``len1 >= len2 > 0``. Does not support aliasing. .. function:: void fmpz_poly_lcm(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the least common multiple of the two polynomials ``poly1`` and ``poly2``, normalised to have non-negative leading coefficient. If either of the two polynomials is zero, sets ``res`` to zero. This ensures that the equality .. math:: f g = \gcd(f, g) \operatorname{lcm}(f, g) holds up to sign. .. function:: void _fmpz_poly_resultant_modular(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to the resultant of ``(poly1, len1)`` and ``(poly2, len2)``, assuming that ``len1 >= len2 > 0``. .. function:: void fmpz_poly_resultant_modular(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Computes the resultant of ``poly1`` and ``poly2``. For two non-zero polynomials `f(x) = a_m x^m + \dotsb + a_0` and `g(x) = b_n x^n + \dotsb + b_0` of degrees `m` and `n`, the resultant is defined to be .. math:: a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y). For convenience, we define the resultant to be equal to zero if either of the two polynomials is zero. This function uses the modular algorithm described in [Col1971]_. .. function:: void fmpz_poly_resultant_modular_div(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t div, slong nbits) Computes the resultant of ``poly1`` and ``poly2`` divided by ``div`` using a slight modification of the above function. It is assumed that the resultant is exactly divisible by ``div`` and the result ``res`` has at most ``nbits`` bits. This bypasses the computation of general bounds. .. function:: void _fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to the resultant of ``(poly1, len1)`` and ``(poly2, len2)``, assuming that ``len1 >= len2 > 0``. .. function:: void fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Computes the resultant of ``poly1`` and ``poly2``. For two non-zero polynomials `f(x) = a_m x^m + \dotsb + a_0` and `g(x) = b_n x^n + \dotsb + b_0` of degrees `m` and `n`, the resultant is defined to be .. math:: a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y). For convenience, we define the resultant to be equal to zero if either of the two polynomials is zero. This function uses the algorithm described in Algorithm 3.3.7 of [Coh1996]_. .. function:: void _fmpz_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to the resultant of ``(poly1, len1)`` and ``(poly2, len2)``, assuming that ``len1 >= len2 > 0``. .. function:: void fmpz_poly_resultant(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Computes the resultant of ``poly1`` and ``poly2``. For two non-zero polynomials `f(x) = a_m x^m + \dotsb + a_0` and `g(x) = b_n x^n + \dotsb + b_0` of degrees `m` and `n`, the resultant is defined to be .. math:: a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y). For convenience, we define the resultant to be equal to zero if either of the two polynomials is zero. Discriminant -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_discriminant(fmpz_t res, const fmpz * poly, slong len) Set ``res`` to the discriminant of ``(poly, len)``. Assumes ``len > 1``. .. function:: void fmpz_poly_discriminant(fmpz_t res, const fmpz_poly_t poly) Set ``res`` to the discriminant of ``poly``. We normalise the discriminant so that `\operatorname{disc}(f) = (-1)^{(n(n-1)/2)} \operatorname{res}(f, f')/\operatorname{lc}(f)`, thus `\operatorname{disc}(f) = \operatorname{lc}(f)^{(2n - 2)} \prod_{i < j} (r_i - r_j)^2`, where `\operatorname{lc}(f)` is the leading coefficient of `f`, `n` is the degree of `f` and `r_i` are the roots of `f`. Gaussian content -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_content(fmpz_t res, const fmpz * poly, slong len) Sets ``res`` to the non-negative content of ``(poly, len)``. Aliasing between ``res`` and the coefficients of ``poly`` is not supported. .. function:: void fmpz_poly_content(fmpz_t res, const fmpz_poly_t poly) Sets ``res`` to the non-negative content of ``poly``. The content of the zero polynomial is defined to be zero. Supports aliasing, that is, ``res`` is allowed to be one of the coefficients of ``poly``. .. function:: void _fmpz_poly_primitive_part(fmpz * res, const fmpz * poly, slong len) Sets ``(res, len)`` to ``(poly, len)`` divided by the content of ``(poly, len)``, and normalises the result to have non-negative leading coefficient. Assumes that ``(poly, len)`` is non-zero. Supports aliasing of ``res`` and ``poly``. .. function:: void fmpz_poly_primitive_part(fmpz_poly_t res, const fmpz_poly_t poly) Sets ``res`` to ``poly`` divided by the content of ``poly``, and normalises the result to have non-negative leading coefficient. If ``poly`` is zero, sets ``res`` to zero. Square-free -------------------------------------------------------------------------------- .. function:: int _fmpz_poly_is_squarefree(const fmpz * poly, slong len) Returns whether the polynomial ``(poly, len)`` is square-free. .. function:: int fmpz_poly_is_squarefree(const fmpz_poly_t poly) Returns whether the polynomial ``poly`` is square-free. A non-zero polynomial is defined to be square-free if it has no non-unit square factors. We also define the zero polynomial to be square-free. Returns `1` if the length of ``poly`` is at most `2`. Returns whether the discriminant is zero for quadratic polynomials. Otherwise, returns whether the greatest common divisor of ``poly`` and its derivative has length `1`. Euclidean division -------------------------------------------------------------------------------- .. function:: int _fmpz_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `A = B Q + R` and each coefficient of `R` beyond ``lenB`` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same thing as division over `\mathbb{Q}`. Assumes that `\operatorname{len}(A), \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. `R` and `A` may be aliased, but apart from this no aliasing of input and output operands is allowed. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: void fmpz_poly_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) Computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same thing as division over `\mathbb{Q}`. An exception is raised if `B` is zero. .. function:: int _fmpz_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, int exact) Computes ``(Q, lenB)``, ``(BQ, 2 lenB - 1)`` such that `BQ = B \times Q` and `A = B Q + R` where each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. We assume that `\operatorname{len}(A) = 2 \operatorname{len}(B) - 1`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. Assumes `\operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. Requires a temporary array ``(W, 2 lenB - 1)``. No aliasing of input and output operands is allowed. This function does not read the bottom `\operatorname{len}(B) - 1` coefficients from `A`, which means that they might not even need to exist in allocated memory. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: int _fmpz_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. Assumes `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. No aliasing of input and output operands is allowed. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: void fmpz_poly_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) Computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. An exception is raised if `B` is zero. .. function:: int _fmpz_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same thing as division over `\mathbb{Q}`. Assumes `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. No aliasing of input and output operands is allowed. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: void fmpz_poly_divrem(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) Computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. An exception is raised if `B` is zero. .. function:: int _fmpz_poly_div_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) Computes the quotient ``(Q, lenA - lenB + 1)`` of ``(A, lenA)`` divided by ``(B, lenB)``. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. Assumes `\operatorname{len}(A), \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. Requires a temporary array `R` of size at least the (actual) length of `A`. For convenience, `R` may be ``NULL``. `R` and `A` may be aliased, but apart from this no aliasing of input and output operands is allowed. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: void fmpz_poly_div_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) Computes the quotient `Q` of `A` divided by `Q`. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. An exception is raised if `B` is zero. .. function:: int _fmpz_poly_divremlow_divconquer_recursive(fmpz * Q, fmpz * BQ, const fmpz * A, const fmpz * B, slong lenB, int exact) Divide and conquer division of ``(A, 2 lenB - 1)`` by ``(B, lenB)``, computing only the bottom `\operatorname{len}(B) - 1` coefficients of `B Q`. Assumes `\operatorname{len}(B) > 0`. Requires `B Q` to have length at least `2 \operatorname{len}(B) - 1`, although only the bottom `\operatorname{len}(B) - 1` coefficients will carry meaningful output. Does not support any aliasing. Allows zero-padding in `A`, but not in `B`. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: int _fmpz_poly_div_divconquer_recursive(fmpz * Q, fmpz * temp, const fmpz * A, const fmpz * B, slong lenB, int exact) Recursive short division in the balanced case. Computes the quotient ``(Q, lenB)`` of ``(A, 2 lenB - 1)`` upon division by ``(B, lenB)``. Requires `\operatorname{len}(B) > 0`. Needs a temporary array ``temp`` of length `2 \operatorname{len}(B) - 1`. Does not support any aliasing. For further details, see [Mul2000]_. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: int _fmpz_poly_div_divconquer(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) Computes the quotient ``(Q, lenA - lenB + 1)`` of ``(A, lenA)`` upon division by ``(B, lenB)``. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Does not support aliasing. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: void fmpz_poly_div_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) Computes the quotient `Q` of `A` divided by `B`. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. An exception is raised if `B` is zero. .. function:: int _fmpz_poly_div(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) Computes the quotient ``(Q, lenA - lenB + 1)`` of ``(A, lenA)`` divided by ``(B, lenB)``. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. Assumes `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. Aliasing of input and output operands is not allowed. If the flag ``exact`` is `1`, the function stops if an inexact division is encountered, upon which the function will return `0`. If no inexact division is encountered, the function returns `1`. Note that this does not guarantee the remainder of the polynomial division is zero, merely that its length is less than that of B. This feature is useful for series division and for divisibility testing (upon testing the remainder). For ordinary use set the flag ``exact`` to `0`. In this case, no checks or early aborts occur and the function always returns `1`. .. function:: void fmpz_poly_div(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) Computes the quotient `Q` of `A` divided by `B`. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `Q`. An exception is raised if `B` is zero. .. function:: void _fmpz_poly_rem_basecase(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) Computes the remainder ``(R, lenA)`` of ``(A, lenA)`` upon division by ``(B, lenB)``. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same thing as division over `\mathbb{Q}`. Assumes that `\operatorname{len}(A), \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. `R` and `A` may be aliased, but apart from this no aliasing of input and output operands is allowed. .. function:: void fmpz_poly_rem_basecase(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) Computes the remainder `R` of `A` upon division by `B`. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. An exception is raised if `B` is zero. .. function:: void _fmpz_poly_rem(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) Computes the remainder ``(R, lenA)`` of ``(A, lenA)`` upon division by ``(B, lenB)``. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same thing as division over `\mathbb{Q}`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. Aliasing of input and output operands is not allowed. .. function:: void fmpz_poly_rem(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) Computes the remainder `R` of `A` upon division by `B`. Notationally, computes `Q`, `R` such that `A = B Q + R` and each coefficient of `R` beyond `\operatorname{len}(B) - 1` is reduced modulo the leading coefficient of `B`. If the leading coefficient of `B` is `\pm 1` or the division is exact, this is the same as division over `\mathbb{Q}`. An exception is raised if `B` is zero. .. function:: void _fmpz_poly_div_root(fmpz * Q, const fmpz * A, slong len, const fmpz_t c) Computes the quotient ``(Q, len-1)`` of ``(A, len)`` upon division by `x - c`. Supports aliasing of ``Q`` and ``A``, but the result is undefined in case of partial overlap. .. function:: void fmpz_poly_div_root(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_t c) Computes the quotient ``(Q, len-1)`` of ``(A, len)`` upon division by `x - c`. .. function:: void _fmpz_poly_divexact(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB) void fmpz_poly_divexact(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) Like :func:`fmpz_poly_div`, but assumes that the division is exact. Division with precomputed inverse -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_preinvert(fmpz * B_inv, const fmpz * B, slong n) Given a monic polynomial ``B`` of length ``n``, compute a precomputed inverse ``B_inv`` of length ``n`` for use in the functions below. No aliasing of ``B`` and ``B_inv`` is permitted. We assume ``n`` is not zero. .. function:: void fmpz_poly_preinvert(fmpz_poly_t B_inv, const fmpz_poly_t B) Given a monic polynomial ``B``, compute a precomputed inverse ``B_inv`` for use in the functions below. An exception is raised if ``B`` is zero. .. function:: void _fmpz_poly_div_preinv(fmpz * Q, const fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2) Given a precomputed inverse ``B_inv`` of the polynomial ``B`` of length ``len2``, compute the quotient ``Q`` of ``A`` by ``B``. We assume the length ``len1`` of ``A`` is at least ``len2``. The polynomial ``Q`` must have space for ``len1 - len2 + 1`` coefficients. No aliasing of operands is permitted. .. function:: void fmpz_poly_div_preinv(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv) Given a precomputed inverse ``B_inv`` of the polynomial ``B``, compute the quotient ``Q`` of ``A`` by ``B``. Aliasing of ``B`` and ``B_inv`` is not permitted. .. function:: void _fmpz_poly_divrem_preinv(fmpz * Q, fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2) Given a precomputed inverse ``B_inv`` of the polynomial ``B`` of length ``len2``, compute the quotient ``Q`` of ``A`` by ``B``. The remainder is then placed in ``A``. We assume the length ``len1`` of ``A`` is at least ``len2``. The polynomial ``Q`` must have space for ``len1 - len2 + 1`` coefficients. No aliasing of operands is permitted. .. function:: void fmpz_poly_divrem_preinv(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv) Given a precomputed inverse ``B_inv`` of the polynomial ``B``, compute the quotient ``Q`` of ``A`` by ``B`` and the remainder ``R``. Aliasing of ``B`` and ``B_inv`` is not permitted. .. function:: fmpz ** _fmpz_poly_powers_precompute(const fmpz * B, slong len) Computes ``2*len - 1`` powers of `x` modulo the polynomial `B` of the given length. This is used as a kind of precomputed inverse in the remainder routine below. .. function:: void fmpz_poly_powers_precompute(fmpz_poly_powers_precomp_t pinv, fmpz_poly_t poly) Computes ``2*len - 1`` powers of `x` modulo the polynomial `B` of the given length. This is used as a kind of precomputed inverse in the remainder routine below. .. function:: void _fmpz_poly_powers_clear(fmpz ** powers, slong len) Clean up resources used by precomputed powers which have been computed by ``_fmpz_poly_powers_precompute``. .. function:: void fmpz_poly_powers_clear(fmpz_poly_powers_precomp_t pinv) Clean up resources used by precomputed powers which have been computed by ``fmpz_poly_powers_precompute``. .. function:: void _fmpz_poly_rem_powers_precomp(fmpz * A, slong m, const fmpz * B, slong n, fmpz ** const powers) Set `A` to the remainder of `A` divide `B` given precomputed powers mod `B` provided by ``_fmpz_poly_powers_precompute``. No aliasing is allowed. .. function:: void fmpz_poly_rem_powers_precomp(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_powers_precomp_t B_inv) Set `R` to the remainder of `A` divide `B` given precomputed powers mod `B` provided by ``fmpz_poly_powers_precompute``. Divisibility testing -------------------------------------------------------------------------------- .. function:: int _fmpz_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB) Returns 1 if ``(B, lenB)`` divides ``(A, lenA)`` exactly and sets `Q` to the quotient, otherwise returns 0. It is assumed that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that `Q` has space for `\operatorname{len}(A) - \operatorname{len}(B) + 1` coefficients. Aliasing of `Q` with either of the inputs is not permitted. This function is currently unoptimised and provided for convenience only. .. function:: int fmpz_poly_divides(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) Returns 1 if `B` divides `A` exactly and sets `Q` to the quotient, otherwise returns 0. This function is currently unoptimised and provided for convenience only. .. function:: slong fmpz_poly_remove(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Set ``res`` to ``poly1`` divided by the highest power of ``poly2`` that divides it and return the power. The divisor ``poly2`` must not be zero or `\pm 1`, otherwise an exception is raised. Division mod p -------------------------------------------------------------------------------- .. function:: void fmpz_poly_divlow_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n) Compute the `n` lowest coefficients of `f` divided by `g`, assuming the division is exact modulo `p`. The computed coefficients are reduced modulo `p` using the symmetric remainder system. We require `f` to be at least `n` in length. The function can handle trailing zeroes, but the low nonzero coefficient of `g` must be coprime to `p`. This is a bespoke function used by factoring. .. function:: void fmpz_poly_divhigh_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n) Compute the `n` highest coefficients of `f` divided by `g`, assuming the division is exact modulo `p`. The computed coefficients are reduced modulo `p` using the symmetric remainder system. We require `f` to be as output by ``fmpz_poly_mulhigh_n`` given polynomials `g` and a polynomial of length `n` as inputs. The leading coefficient of `g` must be coprime to `p`. This is a bespoke function used by factoring. Power series division -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_inv_series_basecase(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) Computes the first `n` terms of the inverse power series of ``(Q, lenQ)`` using a recurrence. Assumes that `n \geq 1` and that `Q` has constant term `\pm 1`. Does not support aliasing. .. function:: void fmpz_poly_inv_series_basecase(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) Computes the first `n` terms of the inverse power series of `Q` using a recurrence, assuming that `Q` has constant term `\pm 1` and `n \geq 1`. .. function:: void _fmpz_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) Computes the first `n` terms of the inverse power series of ``(Q, lenQ)`` using Newton iteration. Assumes that `n \geq 1` and that `Q` has constant term `\pm 1`. Does not support aliasing. .. function:: void fmpz_poly_inv_series_newton(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) Computes the first `n` terms of the inverse power series of `Q` using Newton iteration, assuming `Q` has constant term `\pm 1` and `n \geq 1`. .. function:: void _fmpz_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) Computes the first `n` terms of the inverse power series of ``(Q, lenQ)``. Assumes that `n \geq 1` and that `Q` has constant term `\pm 1`. Does not support aliasing. .. function:: void fmpz_poly_inv_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) Computes the first `n` terms of the inverse power series of `Q`, assuming `Q` has constant term `\pm 1` and `n \geq 1`. .. function:: void _fmpz_poly_div_series_basecase(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n) .. function:: void _fmpz_poly_div_series_divconquer(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n) .. function:: void _fmpz_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n) Divides ``(A, Alen)`` by ``(B, Blen)`` as power series over `\mathbb{Z}`, assuming `B` has constant term `\pm 1` and `n \geq 1`. Aliasing is not supported. .. function:: void fmpz_poly_div_series_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n) .. function:: void fmpz_poly_div_series_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n) .. function:: void fmpz_poly_div_series(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n) Performs power series division in `\mathbb{Z}[[x]] / (x^n)`. The function considers the polynomials `A` and `B` as power series of length `n` starting with the constant terms. The function assumes that `B` has constant term `\pm 1` and `n \geq 1`. Pseudo division -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_pseudo_divrem_basecase(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) If `\ell` is the leading coefficient of `B`, then computes `Q`, `R` such that `\ell^d A = Q B + R`. This function is used for simulating division over `\mathbb{Q}`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Assumes that `Q` can fit `\operatorname{len}(A) - \operatorname{len}(B) + 1` coefficients, and that `R` can fit `\operatorname{len}(A)` coefficients. Supports aliasing of ``(R, lenA)`` and ``(A, lenA)``. But other than this, no aliasing of the inputs and outputs is supported. An optional precomputed inverse of the leading coefficient of `B` from ``fmpz_preinvn_init`` can be supplied. Otherwise ``inv`` should be ``NULL``. Note: ``fmpz.h`` has to be included before ``fmpz_poly.h`` in order for ``fmpz_poly.h`` to declare this function. .. function:: void fmpz_poly_pseudo_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) If `\ell` is the leading coefficient of `B`, then computes `Q`, `R` such that `\ell^d A = Q B + R`. This function is used for simulating division over `\mathbb{Q}`. .. function:: void _fmpz_poly_pseudo_divrem_divconquer(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `\ell^d A = B Q + R`, only setting the bottom `\operatorname{len}(B) - 1` coefficients of `R` to their correct values. The remaining top coefficients of ``(R, lenA)`` may be arbitrary. Assumes `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. No aliasing of input and output operands is allowed. An optional precomputed inverse of the leading coefficient of `B` from ``fmpz_preinvn_init`` can be supplied. Otherwise ``inv`` should be ``NULL``. Note: ``fmpz.h`` has to be included before ``fmpz_poly.h`` in order for ``fmpz_poly.h`` to declare this function. .. function:: void fmpz_poly_pseudo_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) Computes `Q`, `R`, and `d` such that `\ell^d A = B Q + R`, where `R` has length less than the length of `B` and `\ell` is the leading coefficient of `B`. An exception is raised if `B` is zero. .. function:: void _fmpz_poly_pseudo_divrem_cohen(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Assumes that `Q` can fit `\operatorname{len}(A) - \operatorname{len}(B) + 1` coefficients, and that `R` can fit `\operatorname{len}(A)` coefficients. Supports aliasing of ``(R, lenA)`` and ``(A, lenA)``. But other than this, no aliasing of the inputs and outputs is supported. .. function:: void fmpz_poly_pseudo_divrem_cohen(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) This is a variant of ``fmpz_poly_pseudo_divrem`` which computes polynomials `Q` and `R` such that `\ell^d A = B Q + R`. However, the value of `d` is fixed at `\max{\{0, \operatorname{len}(A) - \operatorname{len}(B) + 1\}}`. This function is faster when the remainder is not well behaved, i.e. where it is not expected to be close to zero. Note that this function is not asymptotically fast. It is efficient only for short polynomials, e.g. when `\operatorname{len}(B) < 32`. .. function:: void _fmpz_poly_pseudo_rem_cohen(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Assumes that `R` can fit `\operatorname{len}(A)` coefficients. Supports aliasing of ``(R, lenA)`` and ``(A, lenA)``. But other than this, no aliasing of the inputs and outputs is supported. .. function:: void fmpz_poly_pseudo_rem_cohen(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) This is a variant of :func:`fmpz_poly_pseudo_rem` which computes polynomials `Q` and `R` such that `\ell^d A = B Q + R`, but only returns `R`. However, the value of `d` is fixed at `\max{\{0, \operatorname{len}(A) - \operatorname{len}(B) + 1\}}`. This function is faster when the remainder is not well behaved, i.e. where it is not expected to be close to zero. Note that this function is not asymptotically fast. It is efficient only for short polynomials, e.g. when `\operatorname{len}(B) < 32`. This function uses the algorithm described in Algorithm 3.1.2 of [Coh1996]_. .. function:: void _fmpz_poly_pseudo_divrem(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) If `\ell` is the leading coefficient of `B`, then computes ``(Q, lenA - lenB + 1)``, ``(R, lenB - 1)`` and `d` such that `\ell^d A = B Q + R`. This function is used for simulating division over `\mathbb{Q}`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Assumes that `Q` can fit `\operatorname{len}(A) - \operatorname{len}(B) + 1` coefficients, and that `R` can fit `\operatorname{len}(A)` coefficients, although on exit only the bottom `\operatorname{len}(B)` coefficients will carry meaningful data. Supports aliasing of ``(R, lenA)`` and ``(A, lenA)``. But other than this, no aliasing of the inputs and outputs is supported. An optional precomputed inverse of the leading coefficient of `B` from ``fmpz_preinvn_init`` can be supplied. Otherwise ``inv`` should be ``NULL``. Note: ``fmpz.h`` has to be included before ``fmpz_poly.h`` in order for ``fmpz_poly.h`` to declare this function. .. function:: void fmpz_poly_pseudo_divrem(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) Computes `Q`, `R`, and `d` such that `\ell^d A = B Q + R`. .. function:: void _fmpz_poly_pseudo_div(fmpz * Q, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) Pseudo-division, only returning the quotient. Note: ``fmpz.h`` has to be included before ``fmpz_poly.h`` in order for ``fmpz_poly.h`` to declare this function. .. function:: void fmpz_poly_pseudo_div(fmpz_poly_t Q, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) Pseudo-division, only returning the quotient. .. function:: void _fmpz_poly_pseudo_rem(fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) Pseudo-division, only returning the remainder. Note: ``fmpz.h`` has to be included before ``fmpz_poly.h`` in order for ``fmpz_poly.h`` to declare this function. .. function:: void fmpz_poly_pseudo_rem(fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) Pseudo-division, only returning the remainder. Derivative -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_derivative(fmpz * rpoly, const fmpz * poly, slong len) Sets ``(rpoly, len - 1)`` to the derivative of ``(poly, len)``. Also handles the cases where ``len`` is `0` or `1` correctly. Supports aliasing of ``rpoly`` and ``poly``. .. function:: void fmpz_poly_derivative(fmpz_poly_t res, const fmpz_poly_t poly) Sets ``res`` to the derivative of ``poly``. .. function:: void _fmpz_poly_nth_derivative(fmpz * rpoly, const fmpz * poly, ulong n, slong len) Sets ``(rpoly, len - n)`` to the nth derivative of ``(poly, len)``. Also handles the cases where ``len <= n`` correctly. Supports aliasing of ``rpoly`` and ``poly``. .. function:: void fmpz_poly_nth_derivative(fmpz_poly_t res, const fmpz_poly_t poly, ulong n) Sets ``res`` to the nth derivative of ``poly``. Evaluation -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz * poly, slong len, const fmpz_t a) Evaluates the polynomial ``(poly, len)`` at the integer `a` using a divide and conquer approach. Assumes that the length of the polynomial is at least one. Allows zero padding. Does not allow aliasing between ``res`` and ``x``. .. function:: void fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz_poly_t poly, const fmpz_t a) Evaluates the polynomial ``poly`` at the integer `a` using a divide and conquer approach. Aliasing between ``res`` and ``a`` is supported, however, ``res`` may not be part of ``poly``. .. function:: void _fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a) Evaluates the polynomial ``(f, len)`` at the integer `a` using Horner's rule, and sets ``res`` to the result. Aliasing between ``res`` and `a` or any of the coefficients of `f` is not supported. .. function:: void fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a) Evaluates the polynomial `f` at the integer `a` using Horner's rule, and sets ``res`` to the result. As expected, aliasing between ``res`` and ``a`` is supported. However, ``res`` may not be aliased with a coefficient of `f`. .. function:: void _fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a) Evaluates the polynomial ``(f, len)`` at the integer `a` and sets ``res`` to the result. Aliasing between ``res`` and `a` or any of the coefficients of `f` is not supported. .. function:: void fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a) Evaluates the polynomial `f` at the integer `a` and sets ``res`` to the result. As expected, aliasing between ``res`` and `a` is supported. However, ``res`` may not be aliased with a coefficient of `f`. .. function:: void _fmpz_poly_evaluate_divconquer_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden) Evaluates the polynomial ``(f, len)`` at the rational ``(anum, aden)`` using a divide and conquer approach, and sets ``(rnum, rden)`` to the result in lowest terms. Assumes that the length of the polynomial is at least one. Aliasing between ``(rnum, rden)`` and ``(anum, aden)`` or any of the coefficients of `f` is not supported. .. function:: void fmpz_poly_evaluate_divconquer_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a) Evaluates the polynomial `f` at the rational `a` using a divide and conquer approach, and sets ``res`` to the result. .. function:: void _fmpz_poly_evaluate_horner_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden) Evaluates the polynomial ``(f, len)`` at the rational ``(anum, aden)`` using Horner's rule, and sets ``(rnum, rden)`` to the result in lowest terms. Aliasing between ``(rnum, rden)`` and ``(anum, aden)`` or any of the coefficients of `f` is not supported. .. function:: void fmpz_poly_evaluate_horner_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a) Evaluates the polynomial `f` at the rational `a` using Horner's rule, and sets ``res`` to the result. .. function:: void _fmpz_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden) Evaluates the polynomial ``(f, len)`` at the rational ``(anum, aden)`` and sets ``(rnum, rden)`` to the result in lowest terms. Aliasing between ``(rnum, rden)`` and ``(anum, aden)`` or any of the coefficients of `f` is not supported. .. function:: void fmpz_poly_evaluate_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a) Evaluates the polynomial `f` at the rational `a`, and sets ``res`` to the result. .. function:: mp_limb_t _fmpz_poly_evaluate_mod(const fmpz * poly, slong len, mp_limb_t a, mp_limb_t n, mp_limb_t ninv) Evaluates ``(poly, len)`` at the value `a` modulo `n` and returns the result. The last argument ``ninv`` must be set to the precomputed inverse of `n`, which can be obtained using the function :func:`n_preinvert_limb`. .. function:: mp_limb_t fmpz_poly_evaluate_mod(const fmpz_poly_t poly, mp_limb_t a, mp_limb_t n) Evaluates ``poly`` at the value `a` modulo `n` and returns the result. .. function:: void fmpz_poly_evaluate_fmpz_vec(fmpz * res, const fmpz_poly_t f, const fmpz * a, slong n) Evaluates ``f`` at the `n` values given in the vector ``f``, writing the results to ``res``. .. function:: double _fmpz_poly_evaluate_horner_d(const fmpz * poly, slong n, double d) Evaluate ``(poly, n)`` at the double `d`. No attempt is made to do this efficiently or in a numerically stable way. It is currently only used in Flint for quick and dirty evaluations of polynomials with all coefficients positive. .. function:: double fmpz_poly_evaluate_horner_d(const fmpz_poly_t poly, double d) Evaluate ``poly`` at the double `d`. No attempt is made to do this efficiently or in a numerically stable way. It is currently only used in Flint for quick and dirty evaluations of polynomials with all coefficients positive. .. function:: double _fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz * poly, slong n, double d) Evaluate ``(poly, n)`` at the double `d`. Return the result as a double and an exponent ``exp`` combination. No attempt is made to do this efficiently or in a numerically stable way. It is currently only used in Flint for quick and dirty evaluations of polynomials with all coefficients positive. .. function:: double fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz_poly_t poly, double d) Evaluate ``poly`` at the double `d`. Return the result as a double and an exponent ``exp`` combination. No attempt is made to do this efficiently or in a numerically stable way. It is currently only used in Flint for quick and dirty evaluations of polynomials with all coefficients positive. .. function:: double _fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz * poly, slong n, double d, slong dexp) Evaluate ``poly`` at ``d*2^dexp``. Return the result as a double and an exponent ``exp`` combination. No attempt is made to do this efficiently or in a numerically stable way. It is currently only used in Flint for quick and dirty evaluations of polynomials with all coefficients positive. Newton basis -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_monomial_to_newton(fmpz * poly, const fmpz * roots, slong n) Converts ``(poly, n)`` in-place from its coefficients given in the standard monomial basis to the Newton basis for the roots `r_0, r_1, \ldots, r_{n-2}`. In other words, this determines output coefficients `c_i` such that `c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})` is equal to the input polynomial. Uses repeated polynomial division. .. function:: void _fmpz_poly_newton_to_monomial(fmpz * poly, const fmpz * roots, slong n) Converts ``(poly, n)`` in-place from its coefficients given in the Newton basis for the roots `r_0, r_1, \ldots, r_{n-2}` to the standard monomial basis. In other words, this evaluates `c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})` where `c_i` are the input coefficients for ``poly``. Uses Horner's rule. Interpolation -------------------------------------------------------------------------------- .. function:: void fmpz_poly_interpolate_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n) Sets ``poly`` to the unique interpolating polynomial of degree at most `n - 1` satisfying `f(x_i) = y_i` for every pair `x_i, y_u` in ``xs`` and ``ys``, assuming that this polynomial has integer coefficients. If an interpolating polynomial with integer coefficients does not exist, a ``FLINT_INEXACT`` exception is thrown. It is assumed that the `x` values are distinct. Composition -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_compose_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to the composition of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``res`` has space for ``(len1-1)*(len2-1) + 1`` coefficients. Assumes that ``poly1`` and ``poly2`` are non-zero polynomials. Does not support aliasing between any of the inputs and the output. .. function:: void fmpz_poly_compose_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the composition of ``poly1`` and ``poly2``. To be more precise, denoting ``res``, ``poly1``, and ``poly2`` by `f`, `g`, and `h`, sets `f(t) = g(h(t))`. This implementation uses Horner's method. .. function:: void _fmpz_poly_compose_divconquer(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Computes the composition of ``(poly1, len1)`` and ``(poly2, len2)`` using a divide and conquer approach and places the result into ``res``, assuming ``res`` can hold the output of length ``(len1 - 1) * (len2 - 1) + 1``. Assumes ``len1, len2 > 0``. Does not support aliasing between ``res`` and any of ``(poly1, len1)`` and ``(poly2, len2)``. .. function:: void fmpz_poly_compose_divconquer(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the composition of ``poly1`` and ``poly2``. To be precise about the order of composition, denoting ``res``, ``poly1``, and ``poly2`` by `f`, `g`, and `h`, respectively, sets `f(t) = g(h(t))`. .. function:: void _fmpz_poly_compose(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) Sets ``res`` to the composition of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``res`` has space for ``(len1-1)*(len2-1) + 1`` coefficients. Assumes that ``poly1`` and ``poly2`` are non-zero polynomials. Does not support aliasing between any of the inputs and the output. .. function:: void fmpz_poly_compose(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) Sets ``res`` to the composition of ``poly1`` and ``poly2``. To be precise about the order of composition, denoting ``res``, ``poly1``, and ``poly2`` by `f`, `g`, and `h`, respectively, sets `f(t) = g(h(t))`. Inflation and deflation -------------------------------------------------------------------------------- .. function:: void fmpz_poly_inflate(fmpz_poly_t result, const fmpz_poly_t input, ulong inflation) Sets ``result`` to the inflated polynomial `p(x^n)` where `p` is given by ``input`` and `n` is given by ``inflation``. .. function:: void fmpz_poly_deflate(fmpz_poly_t result, const fmpz_poly_t input, ulong deflation) Sets ``result`` to the deflated polynomial `p(x^{1/n})` where `p` is given by ``input`` and `n` is given by ``deflation``. Requires `n > 0`. .. function:: ulong fmpz_poly_deflation(const fmpz_poly_t input) Returns the largest integer by which ``input`` can be deflated. As special cases, returns 0 if ``input`` is the zero polynomial and 1 if ``input`` is a constant polynomial. Taylor shift -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_taylor_shift_horner(fmpz * poly, const fmpz_t c, slong n) Performs the Taylor shift composing ``poly`` by `x+c` in-place. Uses an efficient version Horner's rule. .. function:: void fmpz_poly_taylor_shift_horner(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) Performs the Taylor shift composing ``f`` by `x+c`. .. function:: void _fmpz_poly_taylor_shift_divconquer(fmpz * poly, const fmpz_t c, slong n) Performs the Taylor shift composing ``poly`` by `x+c` in-place. Uses the divide-and-conquer polynomial composition algorithm. .. function:: void fmpz_poly_taylor_shift_divconquer(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) Performs the Taylor shift composing ``f`` by `x+c`. Uses the divide-and-conquer polynomial composition algorithm. .. function:: void _fmpz_poly_taylor_shift_multi_mod(fmpz * poly, const fmpz_t c, slong n) Performs the Taylor shift composing ``poly`` by `x+c` in-place. Uses a multimodular algorithm, distributing the computation across :func:`flint_get_num_threads` threads. .. function:: void fmpz_poly_taylor_shift_multi_mod(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) Performs the Taylor shift composing ``f`` by `x+c`. Uses a multimodular algorithm, distributing the computation across :func:`flint_get_num_threads` threads. .. function:: void _fmpz_poly_taylor_shift(fmpz * poly, const fmpz_t c, slong n) Performs the Taylor shift composing ``poly`` by `x+c` in-place. .. function:: void fmpz_poly_taylor_shift(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) Performs the Taylor shift composing ``f`` by `x+c`. Power series composition -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_compose_series_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Assumes that ``len1, len2, n > 0``, that ``len1, len2 <= n``, and that ``(len1-1) * (len2-1) + 1 <= n``, and that ``res`` has space for ``n`` coefficients. Does not support aliasing between any of the inputs and the output. This implementation uses the Horner scheme. .. function:: void fmpz_poly_compose_series_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. This implementation uses the Horner scheme. .. function:: void _fmpz_poly_compose_series_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Assumes that ``len1, len2, n > 0``, that ``len1, len2 <= n``, and that ``(len1-1) * (len2-1) + 1 <= n``, and that ``res`` has space for ``n`` coefficients. Does not support aliasing between any of the inputs and the output. This implementation uses Brent-Kung algorithm 2.1 [BrentKung1978]_. .. function:: void fmpz_poly_compose_series_brent_kung(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. This implementation uses Brent-Kung algorithm 2.1 [BrentKung1978]_. .. function:: void _fmpz_poly_compose_series(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Assumes that ``len1, len2, n > 0``, that ``len1, len2 <= n``, and that ``(len1-1) * (len2-1) + 1 <= n``, and that ``res`` has space for ``n`` coefficients. Does not support aliasing between any of the inputs and the output. This implementation automatically switches between the Horner scheme and Brent-Kung algorithm 2.1 depending on the size of the inputs. .. function:: void fmpz_poly_compose_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. This implementation automatically switches between the Horner scheme and Brent-Kung algorithm 2.1 depending on the size of the inputs. Power series reversion -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) void fmpz_poly_revert_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) Sets ``Qinv`` to the compositional inverse or reversion of ``Q`` as a power series, i.e. computes `Q^{-1}` such that `Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n`. It is required that `Q_0 = 0` and `Q_1 = \pm 1`. Wraps :func:`_gr_poly_revert_series` which chooses automatically between various algorithms. Square root -------------------------------------------------------------------------------- .. function:: int _fmpz_poly_sqrtrem_classical(fmpz * res, fmpz * r, const fmpz * poly, slong len) Returns 1 if ``(poly, len)`` can be written in the form `A^2 + R` where deg(`R`) < deg(``poly``), otherwise returns `0`. If it can be so written, ``(res, m - 1)`` is set to `A` and ``(res, m)`` is set to `R`, where `m = \deg(\mathtt{poly})/2 + 1`. For efficiency reasons, ``r`` must have room for ``len`` coefficients, and may alias ``poly``. .. function:: int fmpz_poly_sqrtrem_classical(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a) If `a` can be written as `b^2 + r` with `\deg(r) < \deg(a)/2`, return `1` and set `b` and `r` appropriately. Otherwise return `0`. .. function:: int _fmpz_poly_sqrtrem_divconquer(fmpz * res, fmpz * r, const fmpz * poly, slong len, fmpz * temp) Returns 1 if ``(poly, len)`` can be written in the form `A^2 + R` where deg(`R`) < deg(``poly``), otherwise returns `0`. If it can be so written, ``(res, m - 1)`` is set to `A` and ``(res, m)`` is set to `R`, where `m = \deg(\mathtt{poly})/2 + 1`. For efficiency reasons, ``r`` must have room for ``len`` coefficients, and may alias ``poly``. Temporary space of ``len`` coefficients is required. .. function:: int fmpz_poly_sqrtrem_divconquer(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a) If `a` can be written as `b^2 + r` with `\deg(r) < \deg(a)/2`, return `1` and set `b` and `r` appropriately. Otherwise return `0`. .. function:: int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, slong len, int exact) If ``exact`` is `1` and ``(poly, len)`` is a perfect square, sets ``(res, len / 2 + 1)`` to the square root of ``poly`` with positive leading coefficient and returns 1. Otherwise returns 0. If ``exact`` is `0`, allows a remainder after the square root, which is not computed. This function first uses various tests to detect nonsquares quickly. Then, it computes the square root iteratively from top to bottom, requiring `O(n^2)` coefficient operations. .. function:: int fmpz_poly_sqrt_classical(fmpz_poly_t b, const fmpz_poly_t a) If ``a`` is a perfect square, sets ``b`` to the square root of ``a`` with positive leading coefficient and returns 1. Otherwise returns 0. .. function:: int _fmpz_poly_sqrt_KS(fmpz * res, const fmpz * poly, slong len) Heuristic square root. If the return value is `-1`, the function failed, otherwise it succeeded and the following applies. If ``(poly, len)`` is a perfect square, sets ``(res, len / 2 + 1)`` to the square root of ``poly`` with positive leading coefficient and returns 1. Otherwise returns 0. This function first uses various tests to detect nonsquares quickly. Then, it computes the square root iteratively from top to bottom. .. function:: int fmpz_poly_sqrt_KS(fmpz_poly_t b, const fmpz_poly_t a) Heuristic square root. If the return value is `-1`, the function failed, otherwise it succeeded and the following applies. If ``a`` is a perfect square, sets ``b`` to the square root of ``a`` with positive leading coefficient and returns 1. Otherwise returns 0. .. function:: int _fmpz_poly_sqrt_divconquer(fmpz * res, const fmpz * poly, slong len, int exact) If ``exact`` is `1` and ``(poly, len)`` is a perfect square, sets ``(res, len / 2 + 1)`` to the square root of ``poly`` with positive leading coefficient and returns 1. Otherwise returns 0. If ``exact`` is `0`, allows a remainder after the square root, which is not computed. This function first uses various tests to detect nonsquares quickly. Then, it computes the square root iteratively from top to bottom. .. function:: int fmpz_poly_sqrt_divconquer(fmpz_poly_t b, const fmpz_poly_t a) If ``a`` is a perfect square, sets ``b`` to the square root of ``a`` with positive leading coefficient and returns 1. Otherwise returns 0. .. function:: int _fmpz_poly_sqrt(fmpz * res, const fmpz * poly, slong len) If ``(poly, len)`` is a perfect square, sets ``(res, len / 2 + 1)`` to the square root of ``poly`` with positive leading coefficient and returns 1. Otherwise returns 0. .. function:: int fmpz_poly_sqrt(fmpz_poly_t b, const fmpz_poly_t a) If ``a`` is a perfect square, sets ``b`` to the square root of ``a`` with positive leading coefficient and returns 1. Otherwise returns 0. .. function:: int _fmpz_poly_sqrt_series(fmpz * res, const fmpz * poly, slong len, slong n) Set ``(res, n)`` to the square root of the series ``(poly, n)``, if it exists, and return `1`, otherwise, return `0`. If the valuation of ``poly`` is not zero, ``res`` is zero padded to make up for the fact that the square root may not be known to precision `n`. .. function:: int fmpz_poly_sqrt_series(fmpz_poly_t b, const fmpz_poly_t a, slong n) Set ``b`` to the square root of the series ``a``, where the latter is taken to be a series of precision `n`. If such a square root exists, return `1`, otherwise, return `0`. Note that if the valuation of ``a`` is not zero, ``b`` will not have precision ``n``. It is given only to the precision to which the square root can be computed. Power sums -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_power_sums_naive(fmpz * res, const fmpz * poly, slong len, slong n) Compute the (truncated) power sums series of the monic polynomial ``(poly,len)`` up to length `n` using Newton identities. .. function:: void fmpz_poly_power_sums_naive(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Compute the (truncated) power sum series of the monic polynomial ``poly`` up to length `n` using Newton identities. .. function:: void fmpz_poly_power_sums(fmpz_poly_t res, const fmpz_poly_t poly, slong n) Compute the (truncated) power sums series of the monic polynomial ``poly`` up to length `n`. That is the power series whose coefficient of degree `i` is the sum of the `i`-th power of all (complex) roots of the polynomial ``poly``. .. function:: void _fmpz_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, slong len) Compute the (monic) polynomial given by its power sums series ``(poly,len)``. .. function:: void fmpz_poly_power_sums_to_poly(fmpz_poly_t res, const fmpz_poly_t Q) Compute the (monic) polynomial given its power sums series ``(Q)``. Signature -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_signature(slong * r1, slong * r2, const fmpz * poly, slong len) Computes the signature `(r_1, r_2)` of the polynomial ``(poly, len)``. Assumes that the polynomial is squarefree over `\mathbb{Q}`. .. function:: void fmpz_poly_signature(slong * r1, slong * r2, const fmpz_poly_t poly) Computes the signature `(r_1, r_2)` of the polynomial ``poly``, which is assumed to be square-free over `\mathbb{Q}`. The values of `r_1` and `2 r_2` are the number of real and complex roots of the polynomial, respectively. For convenience, the zero polynomial is allowed, in which case the output is `(0, 0)`. If the polynomial is not square-free, the behaviour is undefined and an exception may be raised. This function uses the algorithm described in Algorithm 4.1.11 of [Coh1996]_. Hensel lifting -------------------------------------------------------------------------------- .. function:: void fmpz_poly_hensel_build_tree(slong * link, fmpz_poly_t * v, fmpz_poly_t * w, const nmod_poly_factor_t fac) Initialises and builds a Hensel tree consisting of two arrays `v`, `w` of polynomials and an array of links, called ``link``. The caller supplies a set of `r` local factors (in the factor structure ``fac``) of some polynomial `F` over `\mathbf{Z}`. They also supply two arrays of initialised polynomials `v` and `w`, each of length `2r - 2` and an array ``link``, also of length `2r - 2`. We will have five arrays: a `v` of ``fmpz_poly_t``'s and a `V` of ``nmod_poly_t``'s and also a `w` and a `W` and ``link``. Here's the idea: we sort each leaf and node of a factor tree by degree, in fact choosing to multiply the two smallest factors, then the next two smallest (factors or products) etc. until a tree is made. The tree will be stored in the `v`'s. The first two elements of `v` will be the smallest modular factors, the last two elements of `v` will multiply to form `F` itself. Since `v` will be rearranging the original factors we will need to be able to recover the original order. For this we use the array ``link`` which has nonnegative even numbers and negative numbers. It is an array of ``slong``\s which aligns with `V` and `v` if ``link`` has a negative number in spot `j` that means `V_j` is an original modular factor which has been lifted, if ``link[j]`` is a nonnegative even number then `V_j` stores a product of the two entries at ``V[link[j]]`` and ``V[link[j]+1]``. `W` and `w` play the role of the extended GCD, at `V_0`, `V_2`, `V_4`, etc. we have a new product, `W_0`, `W_2`, `W_4`, etc. are the XGCD cofactors of the `V`'s. For example, `V_0 W_0 + V_1 W_1 \equiv 1 \pmod{p^{\ell}}` for some `\ell`. These will be lifted along with the entries in `V`. It is not enough to just lift each factor, we have to lift the entire tree and the tree of XGCD cofactors. .. function:: void fmpz_poly_hensel_lift(fmpz_poly_t G, fmpz_poly_t H, fmpz_poly_t A, fmpz_poly_t B, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1) This is the main Hensel lifting routine, which performs a Hensel step from polynomials mod `p` to polynomials mod `P = p p_1`. One starts with polynomials `f`, `g`, `h` such that `f = gh \pmod p`. The polynomials `a`, `b` satisfy `ag + bh = 1 \pmod p`. The lifting formulae are .. math:: G = \biggl( \bigl( \frac{f-gh}{p} \bigr) b \bmod g \biggr) p + g H = \biggl( \bigl( \frac{f-gh}{p} \bigr) a \bmod h \biggr) p + h B = \biggl( \bigl( \frac{1-aG-bH}{p} \bigr) b \bmod g \biggr) p + b A = \biggl( \bigl( \frac{1-aG-bH}{p} \bigr) a \bmod h \biggr) p + a Upon return we have `A G + B H = 1 \pmod P` and `f = G H \pmod P`, where `G = g \pmod p` etc. We require that `1 < p_1 \leq p` and that the input polynomials `f, g, h` have degree at least `1` and that the input polynomials `a` and `b` are non-zero. The output arguments `G, H, A, B` may only be aliased with the input arguments `g, h, a, b`, respectively. .. function:: void fmpz_poly_hensel_lift_without_inverse(fmpz_poly_t Gout, fmpz_poly_t Hout, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1) Given polynomials such that `f = gh \pmod p` and `ag + bh = 1 \pmod p`, lifts only the factors `g` and `h` modulo `P = p p_1`. See :func:`fmpz_poly_hensel_lift`. .. function:: void fmpz_poly_hensel_lift_only_inverse(fmpz_poly_t Aout, fmpz_poly_t Bout, const fmpz_poly_t G, const fmpz_poly_t H, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1) Given polynomials such that `f = gh \pmod p` and `ag + bh = 1 \pmod p`, lifts only the cofactors `a` and `b` modulo `P = p p_1`. See :func:`fmpz_poly_hensel_lift`. .. function:: void fmpz_poly_hensel_lift_tree_recursive(slong * link, fmpz_poly_t * v, fmpz_poly_t * w, fmpz_poly_t f, slong j, slong inv, const fmpz_t p0, const fmpz_t p1) Takes a current Hensel tree ``(link, v, w)`` and a pair `(j,j+1)` of entries in the tree and lifts the tree from mod `p_0` to mod `P = p_0 p_1`, where `1 < p_1 \leq p_0`. Set ``inv`` to `-1` if restarting Hensel lifting, `0` if stopping and `1` otherwise. Here `f = g h` is the polynomial whose factors we are trying to lift. We will have that ``v[j]`` is the product of ``v[link[j]]`` and ``v[link[j] + 1]`` as described above. Does support aliasing of `f` with one of the polynomials in the lists `v` and `w`. But the polynomials in these two lists are not allowed to be aliases of each other. .. function:: void fmpz_poly_hensel_lift_tree(slong * link, fmpz_poly_t * v, fmpz_poly_t * w, fmpz_poly_t f, slong r, const fmpz_t p, slong e0, slong e1, slong inv) Computes `p_0 = p^{e_0}` and `p_1 = p^{e_1 - e_0}` for a small prime `p` and `P = p^{e_1}`. If we aim to lift to `p^b` then `f` is the polynomial whose factors we wish to lift, made monic mod `p^b`. As usual, ``(link, v, w)`` is an initialised tree. This starts the recursion on lifting the *product tree* for lifting from `p^{e_0}` to `p^{e_1}`. The value of ``inv`` corresponds to that given for the function :func:`fmpz_poly_hensel_lift_tree_recursive`. We set `r` to the number of local factors of `f`. In terms of the notation, above `P = p^{e_1}`, `p_0 = p^{e_0}` and `p_1 = p^{e_1-e_0}`. Assumes that `f` is monic. Assumes that `1 < p_1 \leq p_0`, that is, `0 < e_1 \leq e_0`. .. function:: slong _fmpz_poly_hensel_start_lift(fmpz_poly_factor_t lifted_fac, slong * link, fmpz_poly_t * v, fmpz_poly_t * w, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, slong N) This function takes the local factors in ``local_fac`` and Hensel lifts them until they are known mod `p^N`, where `N \geq 1`. These lifted factors will be stored (in the same ordering) in ``lifted_fac``. It is assumed that ``link``, ``v``, and ``w`` are initialized arrays of ``fmpz_poly_t``'s with at least `2*r - 2` entries and that `r \geq 2`. This is done outside of this function so that you can keep them for restarting Hensel lifting later. The product of local factors must be squarefree. The return value is an exponent which must be passed to the function :func:`_fmpz_poly_hensel_continue_lift` as ``prev_exp`` if the Hensel lifting is to be resumed. Currently, supports the case when `N = 1` for convenience, although it is preferable in this case to simply iterate over the local factors and convert them to polynomials over `\mathbf{Z}`. .. function:: slong _fmpz_poly_hensel_continue_lift(fmpz_poly_factor_t lifted_fac, slong * link, fmpz_poly_t * v, fmpz_poly_t * w, const fmpz_poly_t f, slong prev, slong curr, slong N, const fmpz_t p) This function restarts a stopped Hensel lift. It lifts from ``curr`` to `N`. It also requires ``prev`` (to lift the cofactors) given as the return value of the function :func:`_fmpz_poly_hensel_start_lift` or the function :func:`_fmpz_poly_hensel_continue_lift`. The current lifted factors are supplied in ``lifted_fac`` and upon return are updated there. As usual ``link``, ``v``, and ``w`` describe the current Hensel tree, `r` is the number of local factors and `p` is the small prime modulo whose power we are lifting to. It is required that ``curr`` be at least `1` and that ``N > curr``. Currently, supports the case when ``prev`` and ``curr`` are equal. .. function:: void fmpz_poly_hensel_lift_once(fmpz_poly_factor_t lifted_fac, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, slong N) This function does a Hensel lift. It lifts local factors stored in ``local_fac`` of `f` to `p^N`, where `N \geq 2`. The lifted factors will be stored in ``lifted_fac``. This lift cannot be restarted. This function is a convenience function intended for end users. The product of local factors must be squarefree. Input and output -------------------------------------------------------------------------------- The functions in this section are not intended to be particularly fast. They are intended mainly as a debugging aid. For the string output functions there are two variants. The first uses a simple string representation of polynomials which prints only the length of the polynomial and the integer coefficients, whilst the latter variant, appended with ``_pretty``, uses a more traditional string representation of polynomials which prints a variable name as part of the representation. The first string representation is given by a sequence of integers, in decimal notation, separated by white space. The first integer gives the length of the polynomial; the remaining integers are the coefficients. For example `5x^3 - x + 1` is represented by the string ``"4 1 -1 0 5"``, and the zero polynomial is represented by ``"0"``. The coefficients may be signed and arbitrary precision. The string representation of the functions appended by ``_pretty`` includes only the non-zero terms of the polynomial, starting with the one of highest degree. Each term starts with a coefficient, prepended with a sign, followed by the character ``*``, followed by a variable name, which must be passed as a string parameter to the function, followed by a caret ``^`` followed by a non-negative exponent. If the sign of the leading coefficient is positive, it is omitted. Also the exponents of the degree 1 and 0 terms are omitted, as is the variable and the ``*`` character in the case of the degree 0 coefficient. If the coefficient is plus or minus one, the coefficient is omitted, except for the sign. Some examples of the ``_pretty`` representation are:: 5*x^3+7*x-4 x^2+3 -x^4+2*x-1 x+1 5 .. function:: int _fmpz_poly_print(const fmpz * poly, slong len) Prints the polynomial ``(poly, len)`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_poly_print(const fmpz_poly_t poly) Prints the polynomial to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpz_poly_print_pretty(const fmpz * poly, slong len, const char * x) Prints the pretty representation of ``(poly, len)`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_poly_print_pretty(const fmpz_poly_t poly, const char * x) Prints the pretty representation of ``poly`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpz_poly_fprint(FILE * file, const fmpz * poly, slong len) Prints the polynomial ``(poly, len)`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_poly_fprint(FILE * file, const fmpz_poly_t poly) Prints the polynomial to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpz_poly_fprint_pretty(FILE * file, const fmpz * poly, slong len, const char * x) Prints the pretty representation of ``(poly, len)`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_poly_fprint_pretty(FILE * file, const fmpz_poly_t poly, const char * x) Prints the pretty representation of ``poly`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fmpz_poly_read(fmpz_poly_t poly) Reads a polynomial from ``stdin``, storing the result in ``poly``. In case of success, returns a positive number. In case of failure, returns a non-positive value. .. function:: int fmpz_poly_read_pretty(fmpz_poly_t poly, char **x) Reads a polynomial in pretty format from ``stdin``. For further details, see the documentation for the function :func:`fmpz_poly_fread_pretty`. .. function:: int fmpz_poly_fread(FILE * file, fmpz_poly_t poly) Reads a polynomial from the stream ``file``, storing the result in ``poly``. In case of success, returns a positive number. In case of failure, returns a non-positive value. .. function:: int fmpz_poly_fread_pretty(FILE * file, fmpz_poly_t poly, char **x) Reads a polynomial from the file ``file`` and sets ``poly`` to this polynomial. The string ``*x`` is set to the variable name that is used in the input. Returns a positive value, equal to the number of characters read from the file, in case of success. Returns a non-positive value in case of failure, which could either be a read error or the indicator of a malformed input. Modular reduction and reconstruction -------------------------------------------------------------------------------- .. function:: void fmpz_poly_get_nmod_poly(nmod_poly_t Amod, const fmpz_poly_t A) Sets the coefficients of ``Amod`` to the coefficients in ``A``, reduced by the modulus of ``Amod``. .. function:: void fmpz_poly_set_nmod_poly(fmpz_poly_t A, const nmod_poly_t Amod) Sets the coefficients of ``A`` to the residues in ``Amod``, normalised to the interval `-m/2 \le r < m/2` where `m` is the modulus. .. function:: void fmpz_poly_set_nmod_poly_unsigned(fmpz_poly_t A, const nmod_poly_t Amod) Sets the coefficients of ``A`` to the residues in ``Amod``, normalised to the interval `0 \le r < m` where `m` is the modulus. .. function:: void _fmpz_poly_CRT_ui_precomp(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2, mp_limb_t m2inv, fmpz_t m1m2, mp_limb_t c, int sign) Sets the coefficients in ``res`` to the CRT reconstruction modulo `m_1m_2` of the residues ``(poly1, len1)`` and ``(poly2, len2)`` which are images modulo `m_1` and `m_2` respectively. The caller must supply the precomputed product of the input moduli as `m_1m_2`, the inverse of `m_1` modulo `m_2` as `c`, and the precomputed inverse of `m_2` (in the form computed by ``n_preinvert_limb``) as ``m2inv``. If ``sign`` = 0, residues `0 \le r < m_1 m_2` are computed, while if ``sign`` = 1, residues `-m_1 m_2/2 \le r < m_1 m_2/2` are computed. Coefficients of ``res`` are written up to the maximum of ``len1`` and ``len2``. .. function:: void _fmpz_poly_CRT_ui(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2, mp_limb_t m2inv, int sign) This function is identical to ``_fmpz_poly_CRT_ui_precomp``, apart from automatically computing `m_1m_2` and `c`. It also aborts if `c` cannot be computed. .. function:: void fmpz_poly_CRT_ui(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_t m, const nmod_poly_t poly2, int sign) Given ``poly1`` with coefficients modulo ``m`` and ``poly2`` with modulus `n`, sets ``res`` to the CRT reconstruction modulo `mn` with coefficients satisfying `-mn/2 \le c < mn/2` (if sign = 1) or `0 \le c < mn` (if sign = 0). Products -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n) Sets ``(poly, n + 1)`` to the monic polynomial which is the product of `(x - x_0)(x - x_1) \cdots (x - x_{n-1})`, the roots `x_i` being given by ``xs``. Aliasing of the input and output is not allowed. .. function:: void fmpz_poly_product_roots_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, slong n) Sets ``poly`` to the monic polynomial which is the product of `(x - x_0)(x - x_1) \cdots (x - x_{n-1})`, the roots `x_i` being given by ``xs``. .. function:: void _fmpz_poly_product_roots_fmpq_vec(fmpz * poly, const fmpq * xs, slong n) Sets ``(poly, n + 1)`` to the product of `(q_0 x - p_0)(q_1 x - p_1) \cdots (q_{n-1} x - p_{n-1})`, the roots `p_i/q_i` being given by ``xs``. .. function:: void fmpz_poly_product_roots_fmpq_vec(fmpz_poly_t poly, const fmpq * xs, slong n) Sets ``poly`` to the polynomial which is the product of `(q_0 x - p_0)(q_1 x - p_1) \cdots (q_{n-1} x - p_{n-1})`, the roots `p_i/q_i` being given by ``xs``. Roots -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_bound_roots(fmpz_t bound, const fmpz * poly, slong len) void fmpz_poly_bound_roots(fmpz_t bound, const fmpz_poly_t poly) Computes a nonnegative integer ``bound`` that bounds the absolute value of all complex roots of ``poly``. Uses Fujiwara's bound .. math:: 2 \max \left( \left|\frac{a_{n-1}}{a_n}\right|, \left|\frac{a_{n-2}}{a_n}\right|^{\frac{1}{2}}, \dotsc, \left|\frac{a_1}{a_n}\right|^{\frac{1}{n-1}}, \left|\frac{a_0}{2a_n}\right|^{\frac{1}{n}} \right) where the coefficients of the polynomial are `a_0, \ldots, a_n`. .. function:: void _fmpz_poly_num_real_roots_sturm(slong * n_neg, slong * n_pos, const fmpz * pol, slong len) Sets ``n_neg`` and ``n_pos`` to the number of negative and positive roots of the polynomial ``(pol, len)`` using Sturm sequence. The Sturm sequence is computed via subresultant remainders obtained by repeated call to the function ``_fmpz_poly_pseudo_rem_cohen``. The polynomial is assumed to be squarefree, of degree larger than 1 and with non-zero constant coefficient. .. function:: slong fmpz_poly_num_real_roots_sturm(const fmpz_poly_t pol) Returns the number of real roots of the squarefree polynomial ``pol`` using Sturm sequence. The polynomial is assumed to be squarefree. .. function:: slong _fmpz_poly_num_real_roots(const fmpz * pol, slong len) Returns the number of real roots of the squarefree polynomial ``(pol, len)``. The polynomial is assumed to be squarefree. .. function:: slong fmpz_poly_num_real_roots(const fmpz_poly_t pol) Returns the number of real roots of the squarefree polynomial ``pol``. The polynomial is assumed to be squarefree. Minimal polynomials -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_cyclotomic(fmpz * a, ulong n, mp_ptr factors, slong num_factors, ulong phi) Sets ``a`` to the lower half of the cyclotomic polynomial `\Phi_n(x)`, given `n \ge 3` which must be squarefree. A precomputed array containing the prime factors of `n` must be provided, as well as the value of the Euler totient function `\phi(n)` as ``phi``. If `n` is even, 2 must be the first factor in the list. The degree of `\Phi_n(x)` is exactly `\phi(n)`. Only the low `(\phi(n) + 1) / 2` coefficients are written; the high coefficients can be obtained afterwards by copying the low coefficients in reverse order, since `\Phi_n(x)` is a palindrome for `n \ne 1`. We use the sparse power series algorithm described as Algorithm 4 [ArnoldMonagan2011]_. The algorithm is based on the identity .. math:: \Phi_n(x) = \prod_{d|n} (x^d - 1)^{\mu(n/d)}. Treating the polynomial as a power series, the multiplications and divisions can be done very cheaply using repeated additions and subtractions. The complexity is `O(2^k \phi(n))` where `k` is the number of prime factors in `n`. To improve efficiency for small `n`, we treat the ``fmpz`` coefficients as machine integers when there is no risk of overflow. The following bounds are given in Table 6 of [ArnoldMonagan2011]_: For `n < 10163195`, the largest coefficient in any `\Phi_n(x)` has 27 bits, so machine arithmetic is safe on 32 bits. For `n < 169828113`, the largest coefficient in any `\Phi_n(x)` has 60 bits, so machine arithmetic is safe on 64 bits. Further, the coefficients are always `\pm 1` or 0 if there are exactly two prime factors, so in this case machine arithmetic can be used as well. Finally, we handle two special cases: if there is exactly one prime factor `n = p`, then `\Phi_n(x) = 1 + x + x^2 + \ldots + x^{n-1}`, and if `n = 2m`, we use `\Phi_n(x) = \Phi_m(-x)` to fall back to the case when `n` is odd. .. function:: void fmpz_poly_cyclotomic(fmpz_poly_t poly, ulong n) Sets ``poly`` to the `n`-th cyclotomic polynomial, defined as `\Phi_n(x) = \prod_{\omega} (x-\omega)` where `\omega` runs over all the `n`-th primitive roots of unity. We factor `n` into `n = qs` where `q` is squarefree, and compute `\Phi_q(x)`. Then `\Phi_n(x) = \Phi_q(x^s)`. .. function:: ulong _fmpz_poly_is_cyclotomic(const fmpz * poly, slong len) ulong fmpz_poly_is_cyclotomic(const fmpz_poly_t poly) If ``poly`` is a cyclotomic polynomial, returns the index `n` of this cyclotomic polynomial. If ``poly`` is not a cyclotomic polynomial, returns 0. .. function:: void _fmpz_poly_cos_minpoly(fmpz * coeffs, ulong n) void fmpz_poly_cos_minpoly(fmpz_poly_t poly, ulong n) Sets ``poly`` to the minimal polynomial of `2 \cos(2 \pi / n)`. For suitable choice of `n`, this gives the minimal polynomial of `2 \cos(a \pi)` or `2 \sin(a \pi)` for any rational `a`. The cosine is multiplied by a factor two since this gives a monic polynomial with integer coefficients. One can obtain the minimal polynomial for `\cos(2 \pi / n)` by making the substitution `x \to x / 2`. For `n > 2`, the degree of the polynomial is `\varphi(n) / 2`. For `n = 1, 2`, the degree is 1. For `n = 0`, we define the output to be the constant polynomial 1. See [WaktinsZeitlin1993]_. .. function:: void _fmpz_poly_swinnerton_dyer(fmpz * coeffs, ulong n) void fmpz_poly_swinnerton_dyer(fmpz_poly_t poly, ulong n) Sets ``poly`` to the Swinnerton-Dyer polynomial `S_n`, defined as the integer polynomial `S_n = \prod (x \pm \sqrt{2} \pm \sqrt{3} \pm \sqrt{5} \pm \ldots \pm \sqrt{p_n})` where `p_n` denotes the `n`-th prime number and all combinations of signs are taken. This polynomial has degree `2^n` and is irreducible over the integers (it is the minimal polynomial of `\sqrt{2} + \ldots + \sqrt{p_n}`). Orthogonal polynomials -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_chebyshev_t(fmpz * coeffs, ulong n) void fmpz_poly_chebyshev_t(fmpz_poly_t poly, ulong n) Sets ``poly`` to the Chebyshev polynomial of the first kind `T_n(x)`, defined by `T_n(x) = \cos(n \cos^{-1}(x))`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. .. function:: void _fmpz_poly_chebyshev_u(fmpz * coeffs, ulong n) void fmpz_poly_chebyshev_u(fmpz_poly_t poly, ulong n) Sets ``poly`` to the Chebyshev polynomial of the first kind `U_n(x)`, defined by `(n+1) U_n(x) = T'_{n+1}(x)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. .. function:: void _fmpz_poly_legendre_pt(fmpz * coeffs, ulong n) Sets ``coeffs`` to the coefficient array of the shifted Legendre polynomial `\tilde{P_n}(x)`, defined by `\tilde{P_n}(x) = P_n(2x-1)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. The length of the array will be ``n+1``. See ``fmpq_poly`` for the Legendre polynomials. .. function:: void fmpz_poly_legendre_pt(fmpz_poly_t poly, ulong n) Sets ``poly`` to the shifted Legendre polynomial `\tilde{P_n}(x)`, defined by `\tilde{P_n}(x) = P_n(2x-1)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. See ``fmpq_poly`` for the Legendre polynomials. .. function:: void _fmpz_poly_hermite_h(fmpz * coeffs, ulong n) Sets ``coeffs`` to the coefficient array of the Hermite polynomial `H_n(x)`, defined by `H'_n(x) = 2nH_{n-1}(x)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. The length of the array will be ``n+1``. .. function:: void fmpz_poly_hermite_h(fmpz_poly_t poly, ulong n) Sets ``poly`` to the Hermite polynomial `H_n(x)`, defined by `H'_n(x) = 2nH_{n-1}(x)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. .. function:: void _fmpz_poly_hermite_he(fmpz * coeffs, ulong n) Sets ``coeffs`` to the coefficient array of the Hermite polynomial `He_n(x)`, defined by `He_n(x) = 2^{-\tfrac{n}{2}}H_n\left(\frac{x}{\sqrt2}\right)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. The length of the array will be ``n+1``. .. function:: void fmpz_poly_hermite_he(fmpz_poly_t poly, ulong n) Sets ``poly`` to the Hermite polynomial `He_n(x)`, defined by `He_n(x) = 2^{-\tfrac{n}{2}}H_n\left(\frac{x}{\sqrt2}\right)`, for `n\ge0`. The coefficients are calculated using a hypergeometric recurrence. Fibonacci polynomials -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_fibonacci(fmpz * coeffs, ulong n) Sets ``coeffs`` to the coefficient array of the `n`-th Fibonacci polynomial. The coefficients are calculated using a hypergeometric recurrence. .. function:: void fmpz_poly_fibonacci(fmpz_poly_t poly, ulong n) Sets ``poly`` to the `n`-th Fibonacci polynomial. The coefficients are calculated using a hypergeometric recurrence. Eulerian numbers and polynomials -------------------------------------------------------------------------------- Eulerian numbers are the coefficients to the Eulerian polynomials .. math:: A_n(x) = \sum_{m = 0}^{n} A(n, m) x^m, where the Eulerian polynomials are defined by the exponential generating function .. math:: \frac{x - 1}{x - e^{(x - 1) t}} = \sum_{n = 0}^{\infty} A_n(x) \frac{t^n}{n!}. The Eulerian numbers can be expressed explicitly via the formula .. math:: A(n, m) = \sum_{k = 0}^{m + 1} (-1)^k \binom{n + 1}{k} (m + 1 - k)^n. Note: Not to be confused with Euler numbers and polynomials. .. function:: void arith_eulerian_polynomial(fmpz_poly_t res, ulong n) Sets ``res`` to the Eulerian polynomial `A_n(x)`, where we define `A_0(x) = 1`. The polynomial is calculated via a recursive relation. Modular forms and q-series -------------------------------------------------------------------------------- .. function:: void _fmpz_poly_eta_qexp(fmpz * f, slong r, slong len) void fmpz_poly_eta_qexp(fmpz_poly_t f, slong r, slong n) Sets `f` to the `q`-expansion to length `n` of the Dedekind eta function (without the leading factor `q^{1/24}`) raised to the power `r`, i.e. `(q^{-1/24} \eta(q))^r = \prod_{k=1}^{\infty} (1 - q^k)^r`. In particular, `r = -1` gives the generating function of the partition function `p(k)`, and `r = 24` gives, after multiplication by `q`, the modular discriminant `\Delta(q)` which generates the Ramanujan tau function `\tau(k)`. This function uses sparse formulas for `r = 1, 2, 3, 4, 6` and otherwise reduces to one of those cases using power series arithmetic. .. function:: void _fmpz_poly_theta_qexp(fmpz * f, slong r, slong len) void fmpz_poly_theta_qexp(fmpz_poly_t f, slong r, slong n) Sets `f` to the `q`-expansion to length `n` of the Jacobi theta function raised to the power `r`, i.e. `\vartheta(q)^r` where `\vartheta(q) = 1 + 2 \sum_{k=1}^{\infty} q^{k^2}`. This function uses sparse formulas for `r = 1, 2` and otherwise reduces to those cases using power series arithmetic. CLD bounds -------------------------------------------------------------------------------- .. function:: void fmpz_poly_CLD_bound(fmpz_t res, const fmpz_poly_t f, slong n) Compute a bound on the `n` coefficient of `fg'/g` where `g` is any factor of `f`. flint-3.1.3/doc/source/fmpz_poly_factor.rst000066400000000000000000000131661461254215100210160ustar00rootroot00000000000000.. _fmpz-poly-factor: **fmpz_poly_factor.h** -- factorisation of polynomials over the integers =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_factor_struct .. type:: fmpz_poly_factor_t Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_poly_factor_init(fmpz_poly_factor_t fac) Initialises a new factor structure. .. function:: void fmpz_poly_factor_init2(fmpz_poly_factor_t fac, slong alloc) Initialises a new factor structure, providing space for at least ``alloc`` factors. .. function:: void fmpz_poly_factor_realloc(fmpz_poly_factor_t fac, slong alloc) Reallocates the factor structure to provide space for precisely ``alloc`` factors. .. function:: void fmpz_poly_factor_fit_length(fmpz_poly_factor_t fac, slong len) Ensures that the factor structure has space for at least ``len`` factors. This functions takes care of the case of repeated calls by always at least doubling the number of factors the structure can hold. .. function:: void fmpz_poly_factor_clear(fmpz_poly_factor_t fac) Releases all memory occupied by the factor structure. Manipulating factors -------------------------------------------------------------------------------- .. function:: void fmpz_poly_factor_set(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac) Sets ``res`` to the same factorisation as ``fac``. .. function:: void fmpz_poly_factor_insert(fmpz_poly_factor_t fac, const fmpz_poly_t p, slong e) Adds the primitive polynomial `p^e` to the factorisation ``fac``. Assumes that `\deg(p) \geq 2` and `e \neq 0`. .. function:: void fmpz_poly_factor_concat(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac) Concatenates two factorisations. This is equivalent to calling :func:`fmpz_poly_factor_insert` repeatedly with the individual factors of ``fac``. Does not support aliasing between ``res`` and ``fac``. Input and output -------------------------------------------------------------------------------- .. function:: void fmpz_poly_factor_print(const fmpz_poly_factor_t fac) Prints the entries of ``fac`` to standard output. Factoring algorithms -------------------------------------------------------------------------------- .. function:: void fmpz_poly_factor_squarefree(fmpz_poly_factor_t fac, const fmpz_poly_t F) Takes as input a polynomial `F` and a freshly initialized factor structure ``fac``. Updates ``fac`` to contain a factorization of `F` into (not necessarily irreducible) factors that themselves have no repeated factors. None of the returned factors will have the same exponent. That is we return `g_i` and unique `e_i` such that .. math:: F = c \prod_{i} g_i^{e_i} where `c` is the signed content of `F` and `\gcd(g_i, g_i') = 1`. .. function:: void fmpz_poly_factor_zassenhaus_recombination(fmpz_poly_factor_t final_fac, const fmpz_poly_factor_t lifted_fac, const fmpz_poly_t F, const fmpz_t P, slong exp) Takes as input a factor structure ``lifted_fac`` containing a squarefree factorization of the polynomial `F \bmod p`. The algorithm does a brute force search for irreducible factors of `F` over the integers, and each factor is raised to the power ``exp``. The impact of the algorithm is to augment a factorization of ``F^exp`` to the factor structure ``final_fac``. .. function:: void _fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t final_fac, slong exp, const fmpz_poly_t f, slong cutoff, int use_van_hoeij) This is the internal wrapper of Zassenhaus. It will attempt to find a small prime such that `f` modulo `p` has a minimal number of factors. If it cannot find a prime giving less than ``cutoff`` factors it aborts. Then it decides a `p`-adic precision to lift the factors to, Hensel lifts, and finally calls Zassenhaus recombination. Assumes that `\operatorname{len}(f) \geq 2`. Assumes that `f` is primitive. Assumes that the constant coefficient of `f` is non-zero. Note that this can be easily achieved by taking out factors of the form `x^k` before calling this routine. If the final flag is set, the function will use the van Hoeij factorisation algorithm with gradual feeding and mod `2^k` data truncation to find factors when the number of local factors is large. .. function:: void fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t final_fac, const fmpz_poly_t F) A wrapper of the Zassenhaus factoring algorithm, which takes as input any polynomial `F`, and stores a factorization in ``final_fac``. The complexity will be exponential in the number of local factors we find for the components of a squarefree factorization of `F`. .. function:: void _fmpz_poly_factor_quadratic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp) void _fmpz_poly_factor_cubic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp) Inserts the factorisation of the quadratic (resp. cubic) polynomial *f* into *fac* with multiplicity *exp*. This function requires that the content of *f* has been removed, and does not update the content of *fac*. The factorization is calculated over `\mathbb{R}` or `\mathbb{Q}_2` and then tested over `\mathbb{Z}`. .. function:: void fmpz_poly_factor(fmpz_poly_factor_t final_fac, const fmpz_poly_t F) A wrapper of the Zassenhaus and van Hoeij factoring algorithms, which takes as input any polynomial `F`, and stores a factorization in ``final_fac``. flint-3.1.3/doc/source/fmpz_poly_mat.rst000066400000000000000000000452071461254215100203220ustar00rootroot00000000000000.. _fmpz-poly-mat: **fmpz_poly_mat.h** -- matrices of polynomials over the integers =============================================================================== The :type:`fmpz_poly_mat_t` data type represents matrices whose entries are integer polynomials. The :type:`fmpz_poly_mat_t` type is defined as an array of :type:`fmpz_poly_mat_struct`'s of length one. This permits passing parameters of type :type:`fmpz_poly_mat_t` by reference. An integer polynomial matrix internally consists of a single array of :type:`fmpz_poly_struct`'s, representing a dense matrix in row-major order. This array is only directly indexed during memory allocation and deallocation. A separate array holds pointers to the start of each row, and is used for all indexing. This allows the rows of a matrix to be permuted quickly by swapping pointers. Matrices having zero rows or columns are allowed. The shape of a matrix is fixed upon initialisation. The user is assumed to provide input and output variables whose dimensions are compatible with the given operation. Simple example -------------- The following example constructs the matrix `\begin{pmatrix} 2x+1 & x \\ 1-x & -1 \end{pmatrix}` and computes its determinant. .. code:: c #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main() { fmpz_poly_mat_t A; fmpz_poly_t P; fmpz_poly_mat_init(A, 2, 2); fmpz_poly_init(P); fmpz_poly_set_str(fmpz_poly_mat_entry(A, 0, 0), "2 1 2"); fmpz_poly_set_str(fmpz_poly_mat_entry(A, 0, 1), "2 0 1"); fmpz_poly_set_str(fmpz_poly_mat_entry(A, 1, 0), "2 1 -1"); fmpz_poly_set_str(fmpz_poly_mat_entry(A, 1, 1), "1 -1"); fmpz_poly_mat_det(P, A); fmpz_poly_print_pretty(P, "x"); fmpz_poly_clear(P); fmpz_poly_mat_clear(A); } The output is: :: x^2-3*x-1 Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_mat_struct .. type:: fmpz_poly_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_init(fmpz_poly_mat_t mat, slong rows, slong cols) Initialises a matrix with the given number of rows and columns for use. .. function:: void fmpz_poly_mat_init_set(fmpz_poly_mat_t mat, const fmpz_poly_mat_t src) Initialises a matrix ``mat`` of the same dimensions as ``src``, and sets it to a copy of ``src``. .. function:: void fmpz_poly_mat_clear(fmpz_poly_mat_t mat) Frees all memory associated with the matrix. The matrix must be reinitialised if it is to be used again. Basic properties -------------------------------------------------------------------------------- .. function:: slong fmpz_poly_mat_nrows(const fmpz_poly_mat_t mat) Returns the number of rows in ``mat``. .. function:: slong fmpz_poly_mat_ncols(const fmpz_poly_mat_t mat) Returns the number of columns in ``mat``. Basic assignment and manipulation -------------------------------------------------------------------------------- .. function:: fmpz_poly_struct * fmpz_poly_mat_entry(const fmpz_poly_mat_t mat, slong i, slong j) Gives a reference to the entry at row ``i`` and column ``j``. The reference can be passed as an input or output variable to any ``fmpz_poly`` function for direct manipulation of the matrix element. No bounds checking is performed. .. function:: void fmpz_poly_mat_set(fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2) Sets ``mat1`` to a copy of ``mat2``. .. function:: void fmpz_poly_mat_swap(fmpz_poly_mat_t mat1, fmpz_poly_mat_t mat2) Swaps ``mat1`` and ``mat2`` efficiently. .. function:: void fmpz_poly_mat_swap_entrywise(fmpz_poly_mat_t mat1, fmpz_poly_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. Input and output -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_print(const fmpz_poly_mat_t mat, const char * x) Prints the matrix ``mat`` to standard output, using the variable ``x``. Random matrix generation -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_randtest(fmpz_poly_mat_t mat, flint_rand_t state, slong len, flint_bitcnt_t bits) This is equivalent to applying ``fmpz_poly_randtest`` to all entries in the matrix. .. function:: void fmpz_poly_mat_randtest_unsigned(fmpz_poly_mat_t mat, flint_rand_t state, slong len, flint_bitcnt_t bits) This is equivalent to applying ``fmpz_poly_randtest_unsigned`` to all entries in the matrix. .. function:: void fmpz_poly_mat_randtest_sparse(fmpz_poly_mat_t A, flint_rand_t state, slong len, flint_bitcnt_t bits, float density) Creates a random matrix with the amount of nonzero entries given approximately by the ``density`` variable, which should be a fraction between 0 (most sparse) and 1 (most dense). The nonzero entries will have random lengths between 1 and ``len``. Special matrices -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_zero(fmpz_poly_mat_t mat) Sets ``mat`` to the zero matrix. .. function:: void fmpz_poly_mat_one(fmpz_poly_mat_t mat) Sets ``mat`` to the unit or identity matrix of given shape, having the element 1 on the main diagonal and zeros elsewhere. If ``mat`` is nonsquare, it is set to the truncation of a unit matrix. Basic comparison and properties -------------------------------------------------------------------------------- .. function:: int fmpz_poly_mat_equal(const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2) Returns nonzero if ``mat1`` and ``mat2`` have the same shape and all their entries agree, and returns zero otherwise. .. function:: int fmpz_poly_mat_is_zero(const fmpz_poly_mat_t mat) Returns nonzero if all entries in ``mat`` are zero, and returns zero otherwise. .. function:: int fmpz_poly_mat_is_one(const fmpz_poly_mat_t mat) Returns nonzero if all entries of ``mat`` on the main diagonal are the constant polynomial 1 and all remaining entries are zero, and returns zero otherwise. The matrix need not be square. .. function:: int fmpz_poly_mat_is_empty(const fmpz_poly_mat_t mat) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int fmpz_poly_mat_is_square(const fmpz_poly_mat_t mat) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. Norms -------------------------------------------------------------------------------- .. function:: slong fmpz_poly_mat_max_bits(const fmpz_poly_mat_t A) Returns the maximum number of bits among the coefficients of the entries in ``A``, or the negative of that value if any coefficient is negative. .. function:: slong fmpz_poly_mat_max_length(const fmpz_poly_mat_t A) Returns the maximum polynomial length among all the entries in ``A``. Transpose -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_transpose(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) Sets `B` to `A^t`. Evaluation -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_evaluate_fmpz(fmpz_mat_t B, const fmpz_poly_mat_t A, const fmpz_t x) Sets the ``fmpz_mat_t`` ``B`` to ``A`` evaluated entrywise at the point ``x``. Arithmetic -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_scalar_mul_fmpz_poly(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_poly_t c) Sets ``B`` to ``A`` multiplied entrywise by the polynomial ``c``. .. function:: void fmpz_poly_mat_scalar_mul_fmpz(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_t c) Sets ``B`` to ``A`` multiplied entrywise by the integer ``c``. .. function:: void fmpz_poly_mat_add(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) Sets ``C`` to the sum of ``A`` and ``B``. All matrices must have the same shape. Aliasing is allowed. .. function:: void fmpz_poly_mat_sub(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) Sets ``C`` to the sum of ``A`` and ``B``. All matrices must have the same shape. Aliasing is allowed. .. function:: void fmpz_poly_mat_neg(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) Sets ``B`` to the negation of ``A``. The matrices must have the same shape. Aliasing is allowed. .. function:: void fmpz_poly_mat_mul(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) Sets ``C`` to the matrix product of ``A`` and ``B``. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. This function automatically chooses between classical and KS multiplication. .. function:: void fmpz_poly_mat_mul_classical(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) Sets ``C`` to the matrix product of ``A`` and ``B``, computed using the classical algorithm. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. .. function:: void fmpz_poly_mat_mul_KS(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) Sets ``C`` to the matrix product of ``A`` and ``B``, computed using Kronecker segmentation. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. .. function:: void fmpz_poly_mat_mullow(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B, slong len) Sets ``C`` to the matrix product of ``A`` and ``B``, truncating each entry in the result to length ``len``. Uses classical matrix multiplication. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. .. function:: void fmpz_poly_mat_sqr(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) Sets ``B`` to the square of ``A``, which must be a square matrix. Aliasing is allowed. This function automatically chooses between classical and KS squaring. .. function:: void fmpz_poly_mat_sqr_classical(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) Sets ``B`` to the square of ``A``, which must be a square matrix. Aliasing is allowed. This function uses direct formulas for very small matrices, and otherwise classical matrix multiplication. .. function:: void fmpz_poly_mat_sqr_KS(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) Sets ``B`` to the square of ``A``, which must be a square matrix. Aliasing is allowed. This function uses Kronecker segmentation. .. function:: void fmpz_poly_mat_sqrlow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, slong len) Sets ``B`` to the square of ``A``, which must be a square matrix, truncating all entries to length ``len``. Aliasing is allowed. This function uses direct formulas for very small matrices, and otherwise classical matrix multiplication. .. function:: void fmpz_poly_mat_pow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp) Sets ``B`` to ``A`` raised to the power ``exp``, where ``A`` is a square matrix. Uses exponentiation by squaring. Aliasing is allowed. .. function:: void fmpz_poly_mat_pow_trunc(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp, slong len) Sets ``B`` to ``A`` raised to the power ``exp``, truncating all entries to length ``len``, where ``A`` is a square matrix. Uses exponentiation by squaring. Aliasing is allowed. .. function:: void fmpz_poly_mat_prod(fmpz_poly_mat_t res, fmpz_poly_mat_t * const factors, slong n) Sets ``res`` to the product of the ``n`` matrices given in the vector ``factors``, all of which must be square and of the same size. Uses binary splitting. Row reduction -------------------------------------------------------------------------------- .. function:: slong fmpz_poly_mat_find_pivot_any(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c) Attempts to find a pivot entry for row reduction. Returns a row index `r` between ``start_row`` (inclusive) and ``stop_row`` (exclusive) such that column `c` in ``mat`` has a nonzero entry on row `r`, or returns -1 if no such entry exists. This implementation simply chooses the first nonzero entry it encounters. This is likely to be a nearly optimal choice if all entries in the matrix have roughly the same size, but can lead to unnecessary coefficient growth if the entries vary in size. .. function:: slong fmpz_poly_mat_find_pivot_partial(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c) Attempts to find a pivot entry for row reduction. Returns a row index `r` between ``start_row`` (inclusive) and ``stop_row`` (exclusive) such that column `c` in ``mat`` has a nonzero entry on row `r`, or returns -1 if no such entry exists. This implementation searches all the rows in the column and chooses the nonzero entry of smallest degree. If there are several entries with the same minimal degree, it chooses the entry with the smallest coefficient bit bound. This heuristic typically reduces coefficient growth when the matrix entries vary in size. .. function:: slong fmpz_poly_mat_fflu(fmpz_poly_mat_t B, fmpz_poly_t den, slong * perm, const fmpz_poly_mat_t A, int rank_check) Uses fraction-free Gaussian elimination to set (``B``, ``den``) to a fraction-free LU decomposition of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. Pivot elements are chosen with ``fmpz_poly_mat_find_pivot_partial``. If ``perm`` is non-``NULL``, the permutation of rows in the matrix will also be applied to ``perm``. If ``rank_check`` is set, the function aborts and returns 0 if the matrix is detected not to have full rank without completing the elimination. The denominator ``den`` is set to `\pm \operatorname{det}(A)`, where the sign is decided by the parity of the permutation. Note that the determinant is not generally the minimal denominator. .. function:: slong fmpz_poly_mat_rref(fmpz_poly_mat_t B, fmpz_poly_t den, const fmpz_poly_mat_t A) Sets (``B``, ``den``) to the reduced row echelon form of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. The denominator ``den`` is set to `\pm \operatorname{det}(A)`. Note that the determinant is not generally the minimal denominator. Trace -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_trace(fmpz_poly_t trace, const fmpz_poly_mat_t mat) Computes the trace of the matrix, i.e. the sum of the entries on the main diagonal. The matrix is required to be square. Determinant and rank -------------------------------------------------------------------------------- .. function:: void fmpz_poly_mat_det(fmpz_poly_t det, const fmpz_poly_mat_t A) Sets ``det`` to the determinant of the square matrix ``A``. Uses a direct formula, fraction-free LU decomposition, or interpolation, depending on the size of the matrix. .. function:: void fmpz_poly_mat_det_fflu(fmpz_poly_t det, const fmpz_poly_mat_t A) Sets ``det`` to the determinant of the square matrix ``A``. The determinant is computed by performing a fraction-free LU decomposition on a copy of ``A``. .. function:: void fmpz_poly_mat_det_interpolate(fmpz_poly_t det, const fmpz_poly_mat_t A) Sets ``det`` to the determinant of the square matrix ``A``. The determinant is computed by determining a bound `n` for its length, evaluating the matrix at `n` distinct points, computing the determinant of each integer matrix, and forming the interpolating polynomial. .. function:: slong fmpz_poly_mat_rank(const fmpz_poly_mat_t A) Returns the rank of ``A``. Performs fraction-free LU decomposition on a copy of ``A``. Inverse -------------------------------------------------------------------------------- .. function:: int fmpz_poly_mat_inv(fmpz_poly_mat_t Ainv, fmpz_poly_t den, const fmpz_poly_mat_t A) Sets (``Ainv``, ``den``) to the inverse matrix of ``A``. Returns 1 if ``A`` is nonsingular and 0 if ``A`` is singular. Aliasing of ``Ainv`` and ``A`` is allowed. More precisely, ``det`` will be set to the determinant of ``A`` and ``Ainv`` will be set to the adjugate matrix of ``A``. Note that the determinant is not necessarily the minimal denominator. Uses fraction-free LU decomposition, followed by solving for the identity matrix. Nullspace -------------------------------------------------------------------------------- .. function:: slong fmpz_poly_mat_nullspace(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat) Computes the right rational nullspace of the matrix ``mat`` and returns the nullity. More precisely, assume that ``mat`` has rank `r` and nullity `n`. Then this function sets the first `n` columns of ``res`` to linearly independent vectors spanning the nullspace of ``mat``. As a result, we always have rank(``res``) `= n`, and ``mat`` `\times` ``res`` is the zero matrix. The computed basis vectors will not generally be in a reduced form. In general, the polynomials in each column vector in the result will have a nontrivial common GCD. Solving -------------------------------------------------------------------------------- .. function:: int fmpz_poly_mat_solve(fmpz_poly_mat_t X, fmpz_poly_t den, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. Uses fraction-free LU decomposition followed by fraction-free forward and back substitution. .. function:: int fmpz_poly_mat_solve_fflu(fmpz_poly_mat_t X, fmpz_poly_t den, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. Uses fraction-free LU decomposition followed by fraction-free forward and back substitution. .. function:: void fmpz_poly_mat_solve_fflu_precomp(fmpz_poly_mat_t X, const slong * perm, const fmpz_poly_mat_t FFLU, const fmpz_poly_mat_t B) Performs fraction-free forward and back substitution given a precomputed fraction-free LU decomposition and corresponding permutation. flint-3.1.3/doc/source/fmpz_poly_q.rst000066400000000000000000000266451461254215100200060ustar00rootroot00000000000000.. _fmpz-poly-q: **fmpz_poly_q.h** -- rational functions over the rational numbers =============================================================================== The module :type:`fmpz_poly_q` provides functions for performing arithmetic on rational functions in `\mathbf{Q}(t)`, represented as quotients of integer polynomials of type :type:`fmpz_poly_t`. These functions start with the prefix :type:`fmpz_poly_q_`. Rational functions are stored in objects of type :type:`fmpz_poly_q_t`, which is an array of :type:`fmpz_poly_q_struct`'s of length one. This permits passing parameters of type :type:`fmpz_poly_q_t` by reference. The representation of a rational function as the quotient of two integer polynomials can be made canonical by demanding the numerator and denominator to be coprime (as integer polynomials) and the denominator to have positive leading coefficient. As the only special case, we represent the zero function as `0/1`. All arithmetic functions assume that the operands are in this canonical form, and canonicalize their result. If the numerator or denominator is modified individually, for example using the macros ``fmpz_poly_q_numref()`` and ``fmpz_poly_q_denref()``, it is the user's responsibility to canonicalise the rational function using the function ``fmpz_poly_q_canonicalise()`` if necessary. All methods support aliasing of their inputs and outputs *unless* explicitly stated otherwise, subject to the following caveat. If different rational functions (as objects in memory, not necessarily in the mathematical sense) share some of the underlying integer polynomial objects, the behaviour is undefined. The basic arithmetic operations, addition, subtraction and multiplication, are all implemented using adapted versions of Henrici's algorithms, see [Hen1956]_. Differentiation is implemented in a way slightly improving on the algorithm described in [Hor1972]_. Simple example -------------- The following example computes the product of two rational functions and prints the result: .. code:: c #include "fmpz_poly_q.h" int main() { char * str, * strf, * strg; fmpz_poly_q_t f, g; fmpz_poly_q_init(f); fmpz_poly_q_init(g); fmpz_poly_q_set_str(f, "2 1 3/1 2"); fmpz_poly_q_set_str(g, "1 3/2 2 7"); strf = fmpz_poly_q_get_str_pretty(f, "t"); strg = fmpz_poly_q_get_str_pretty(g, "t"); fmpz_poly_q_mul(f, f, g); str = fmpz_poly_q_get_str_pretty(f, "t"); flint_printf("%s * %s = %s\n", strf, strg, str); free(str); free(strf); free(strg); fmpz_poly_q_clear(f); fmpz_poly_q_clear(g); } The output is: :: (3*t+1)/2 * 3/(7*t+2) = (9*t+3)/(14*t+4) Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_q_struct .. type:: fmpz_poly_q_t Memory management -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_init(fmpz_poly_q_t rop) Initialises ``rop``. .. function:: void fmpz_poly_q_clear(fmpz_poly_q_t rop) Clears the object ``rop``. .. function:: fmpz_poly_struct * fmpz_poly_q_numref(const fmpz_poly_q_t op) Returns a reference to the numerator of ``op``. .. function:: fmpz_poly_struct * fmpz_poly_q_denref(const fmpz_poly_q_t op) Returns a reference to the denominator of ``op``. .. function:: void fmpz_poly_q_canonicalise(fmpz_poly_q_t rop) Brings ``rop`` into canonical form, only assuming that the denominator is non-zero. .. function:: int fmpz_poly_q_is_canonical(const fmpz_poly_q_t op) Checks whether the rational function ``op`` is in canonical form. Randomisation -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_randtest(fmpz_poly_q_t poly, flint_rand_t state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2) Sets ``poly`` to a random rational function. .. function:: void fmpz_poly_q_randtest_not_zero(fmpz_poly_q_t poly, flint_rand_t state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2) Sets ``poly`` to a random non-zero rational function. Assignment -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_set(fmpz_poly_q_t rop, const fmpz_poly_q_t op) Sets the element ``rop`` to the same value as the element ``op``. .. function:: void fmpz_poly_q_set_si(fmpz_poly_q_t rop, slong op) Sets the element ``rop`` to the value given by the ``slong`` ``op``. .. function:: void fmpz_poly_q_swap(fmpz_poly_q_t op1, fmpz_poly_q_t op2) Swaps the elements ``op1`` and ``op2``. This is done efficiently by swapping pointers. .. function:: void fmpz_poly_q_zero(fmpz_poly_q_t rop) Sets ``rop`` to zero. .. function:: void fmpz_poly_q_one(fmpz_poly_q_t rop) Sets ``rop`` to one. .. function:: void fmpz_poly_q_neg(fmpz_poly_q_t rop, const fmpz_poly_q_t op) Sets the element ``rop`` to the additive inverse of ``op``. .. function:: void fmpz_poly_q_inv(fmpz_poly_q_t rop, const fmpz_poly_q_t op) Sets the element ``rop`` to the multiplicative inverse of ``op``. Assumes that the element ``op`` is non-zero. Comparison -------------------------------------------------------------------------------- .. function:: int fmpz_poly_q_is_zero(const fmpz_poly_q_t op) Returns whether the element ``op`` is zero. .. function:: int fmpz_poly_q_is_one(const fmpz_poly_q_t op) Returns whether the element ``rop`` is equal to the constant polynomial `1`. .. function:: int fmpz_poly_q_equal(const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) Returns whether the two elements ``op1`` and ``op2`` are equal. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_add(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) Sets ``rop`` to the sum of ``op1`` and ``op2``. .. function:: void fmpz_poly_q_sub(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) Sets ``rop`` to the difference of ``op1`` and ``op2``. .. function:: void fmpz_poly_q_addmul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) Adds the product of ``op1`` and ``op2`` to ``rop``. .. function:: void fmpz_poly_q_submul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) Subtracts the product of ``op1`` and ``op2`` from ``rop``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_scalar_mul_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x) Sets ``rop`` to the product of the rational function ``op`` and the ``slong`` integer `x`. .. function:: void fmpz_poly_q_scalar_mul_fmpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpz_t x) Sets ``rop`` to the product of the rational function ``op`` and the ``fmpz_t`` integer `x`. .. function:: void fmpz_poly_q_scalar_mul_fmpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpq_t x) Sets ``rop`` to the product of the rational function ``op`` and the ``fmpq_t`` rational `x`. .. function:: void fmpz_poly_q_scalar_div_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x) Sets ``rop`` to the quotient of the rational function ``op`` and the ``slong`` integer `x`. .. function:: void fmpz_poly_q_scalar_div_fmpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpz_t x) Sets ``rop`` to the quotient of the rational function ``op`` and the ``fmpz_t`` integer `x`. .. function:: void fmpz_poly_q_scalar_div_fmpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpq_t x) Sets ``rop`` to the quotient of the rational function ``op`` and the ``fmpq_t`` rational `x`. Multiplication and division -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_mul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) Sets ``rop`` to the product of ``op1`` and ``op2``. .. function:: void fmpz_poly_q_div(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) Sets ``rop`` to the quotient of ``op1`` and ``op2``. Powering -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_pow(fmpz_poly_q_t rop, const fmpz_poly_q_t op, ulong exp) Sets ``rop`` to the ``exp``-th power of ``op``. The corner case of ``exp == 0`` is handled by setting ``rop`` to the constant function `1`. Note that this includes the case `0^0 = 1`. Derivative -------------------------------------------------------------------------------- .. function:: void fmpz_poly_q_derivative(fmpz_poly_q_t rop, const fmpz_poly_q_t op) Sets ``rop`` to the derivative of ``op``. Evaluation -------------------------------------------------------------------------------- .. function:: int fmpz_poly_q_evaluate_fmpq(fmpq_t rop, const fmpz_poly_q_t f, const fmpq_t a) Sets ``rop`` to `f` evaluated at the rational `a`. If the denominator evaluates to zero at `a`, returns non-zero and does not modify any of the variables. Otherwise, returns `0` and sets ``rop`` to the rational `f(a)`. Input and output -------------------------------------------------------------------------------- The following three methods enable users to construct elements of type ``fmpz_poly_q_t`` from strings or to obtain string representations of such elements. The format used is based on the FLINT format for integer polynomials of type ``fmpz_poly_t``, which we recall first: A non-zero polynomial `a_0 + a_1 X + \dotsb + a_n X^n` of length `n + 1` is represented by the string ``"n+1 a_0 a_1 ... a_n"``, where there are two space characters following the length and single space characters separating the individual coefficients. There is no leading or trailing white-space. The zero polynomial is simply represented by ``"0"``. We adapt this notation for rational functions as follows. We denote the zero function by ``"0"``. Given a non-zero function with numerator and denominator string representations ``num`` and ``den``, respectively, we use the string ``num/den`` to represent the rational function, unless the denominator is equal to one, in which case we simply use ``num``. There is also a ``_pretty`` variant available, which bases the string parts for the numerator and denominator on the output of the function ``fmpz_poly_get_str_pretty`` and introduces parentheses where necessary. Note that currently these functions are not optimised for performance and are intended to be used only for debugging purposes or one-off input and output, rather than as a low-level parser. .. function:: int fmpz_poly_q_set_str(fmpz_poly_q_t rop, const char * s) Sets ``rop`` to the rational function given by the string ``s``. .. function:: char * fmpz_poly_q_get_str(const fmpz_poly_q_t op) Returns the string representation of the rational function ``op``. .. function:: char * fmpz_poly_q_get_str_pretty(const fmpz_poly_q_t op, const char * x) Returns the pretty string representation of the rational function ``op``. .. function:: int fmpz_poly_q_print(const fmpz_poly_q_t op) Prints the representation of the rational function ``op`` to ``stdout``. .. function:: int fmpz_poly_q_print_pretty(const fmpz_poly_q_t op, const char * x) Prints the pretty representation of the rational function ``op`` to ``stdout``. flint-3.1.3/doc/source/fmpz_vec.rst000066400000000000000000000415131461254215100172470ustar00rootroot00000000000000.. _fmpz-vec: **fmpz_vec.h** -- vectors of integers ================================================================================================== Memory management -------------------------------------------------------------------------------- .. function:: fmpz * _fmpz_vec_init(slong len) Returns an initialised vector of ``fmpz``'s of given length. .. function:: void _fmpz_vec_clear(fmpz * vec, slong len) Clears the entries of ``(vec, len)`` and frees the space allocated for ``vec``. Randomisation -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_randtest(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets the entries of a vector of the given length to random integers with up to the given number of bits per entry. .. function:: void _fmpz_vec_randtest_unsigned(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets the entries of a vector of the given length to random unsigned integers with up to the given number of bits per entry. Bit sizes and norms -------------------------------------------------------------------------------- .. function:: slong _fmpz_vec_max_bits(const fmpz * vec, slong len) If `b` is the maximum number of bits of the absolute value of any coefficient of ``vec``, then if any coefficient of ``vec`` is negative, `-b` is returned, else `b` is returned. .. function:: slong _fmpz_vec_max_bits_ref(const fmpz * vec, slong len) If `b` is the maximum number of bits of the absolute value of any coefficient of ``vec``, then if any coefficient of ``vec`` is negative, `-b` is returned, else `b` is returned. This is a slower reference implementation of ``_fmpz_vec_max_bits``. .. function:: void _fmpz_vec_sum_max_bits(slong * sumabs, slong * maxabs, const fmpz * vec, slong len) Sets ``sumabs`` to the bit count of the sum of the absolute values of the elements of ``vec``. Sets ``maxabs`` to the bit count of the maximum of the absolute values of the elements of ``vec``. .. function:: mp_size_t _fmpz_vec_max_limbs(const fmpz * vec, slong len) Returns the maximum number of limbs needed to store the absolute value of any entry in ``(vec, len)``. If all entries are zero, returns zero. .. function:: void _fmpz_vec_height(fmpz_t height, const fmpz * vec, slong len) Computes the height of ``(vec, len)``, defined as the largest of the absolute values the coefficients. Equivalently, this gives the infinity norm of the vector. If ``len`` is zero, the height is `0`. .. function:: slong _fmpz_vec_height_index(const fmpz * vec, slong len) Returns the index of an entry of maximum absolute value in the vector. The length must be at least 1. Input and output -------------------------------------------------------------------------------- .. function:: int _fmpz_vec_fread(FILE * file, fmpz ** vec, slong * len) Reads a vector from the stream ``file`` and stores it at ``*vec``. The format is the same as the output format of ``_fmpz_vec_fprint()``, followed by either any character or the end of the file. The interpretation of the various input arguments depends on whether or not ``*vec`` is ``NULL``: If ``*vec == NULL``, the value of ``*len`` on input is ignored. Once the length has been read from ``file``, ``*len`` is set to that value and a vector of this length is allocated at ``*vec``. Finally, ``*len`` coefficients are read from the input stream. In case of a file or parsing error, clears the vector and sets ``*vec`` and ``*len`` to ``NULL`` and ``0``, respectively. Otherwise, if ``*vec != NULL``, it is assumed that ``(*vec, *len)`` is a properly initialised vector. If the length on the input stream does not match ``*len``, a parsing error is raised. Attempts to read the right number of coefficients from the input stream. In case of a file or parsing error, leaves the vector ``(*vec, *len)`` in its current state. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpz_vec_read(fmpz ** vec, slong * len) Reads a vector from ``stdin`` and stores it at ``*vec``. For further details, see ``_fmpz_vec_fread()``. .. function:: int _fmpz_vec_fprint(FILE * file, const fmpz * vec, slong len) Prints the vector of given length to the stream ``file``. The format is the length followed by two spaces, then a space separated list of coefficients. If the length is zero, only `0` is printed. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fmpz_vec_print(const fmpz * vec, slong len) Prints the vector of given length to ``stdout``. For further details, see ``_fmpz_vec_fprint()``. Conversions -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_get_nmod_vec(mp_ptr res, const fmpz * poly, slong len, nmod_t mod) Reduce the coefficients of ``(poly, len)`` modulo the given modulus and set ``(res, len)`` to the result. .. function:: void _fmpz_vec_set_nmod_vec(fmpz * res, mp_srcptr poly, slong len, nmod_t mod) Set the coefficients of ``(res, len)`` to the symmetric modulus of the coefficients of ``(poly, len)``, i.e. convert the given coefficients modulo the given modulus `n` to their signed integer representatives in the range `[-n/2, n/2)`. .. function:: void _fmpz_vec_get_fft(mp_limb_t ** coeffs_f, const fmpz * coeffs_m, slong l, slong length) Convert the vector of coeffs ``coeffs_m`` to an fft vector ``coeffs_f`` of the given ``length`` with ``l`` limbs per coefficient with an additional limb for overflow. .. function:: void _fmpz_vec_set_fft(fmpz * coeffs_m, slong length, const mp_ptr * coeffs_f, slong limbs, slong sign) Convert an fft vector ``coeffs_f`` of fully reduced Fermat numbers of the given ``length`` to a vector of ``fmpz``'s. Each is assumed to be the given number of limbs in length with an additional limb for overflow. If the output coefficients are to be signed then set ``sign``, otherwise clear it. The resulting ``fmpz``s will be in the range `[-n,n]` in the signed case and in the range `[0,2n]` in the unsigned case where ``n = 2^(FLINT_BITS*limbs - 1)``. .. function:: slong _fmpz_vec_get_d_vec_2exp(double * appv, const fmpz * vec, slong len) Export the array of ``len`` entries starting at the pointer ``vec`` to an array of doubles ``appv``, each entry of which is notionally multiplied by a single returned exponent to give the original entry. The returned exponent is set to be the maximum exponent of all the original entries so that all the doubles in ``appv`` have a maximum absolute value of 1.0. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_set(fmpz * vec1, const fmpz * vec2, slong len2) Makes a copy of ``(vec2, len2)`` into ``vec1``. .. function:: void _fmpz_vec_swap(fmpz * vec1, fmpz * vec2, slong len2) Swaps the integers in ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fmpz_vec_zero(fmpz * vec, slong len) Zeros the entries of ``(vec, len)``. .. function:: void _fmpz_vec_neg(fmpz * vec1, const fmpz * vec2, slong len2) Negates ``(vec2, len2)`` and places it into ``vec1``. .. function:: void _fmpz_vec_scalar_abs(fmpz * vec1, const fmpz * vec2, slong len2) Takes the absolute value of entries in ``(vec2, len2)`` and places the result into ``vec1``. Comparison -------------------------------------------------------------------------------- .. function:: int _fmpz_vec_equal(const fmpz * vec1, const fmpz * vec2, slong len) Compares two vectors of the given length and returns `1` if they are equal, otherwise returns `0`. .. function:: int _fmpz_vec_is_zero(const fmpz * vec, slong len) Returns `1` if ``(vec, len)`` is zero, and `0` otherwise. .. function:: void _fmpz_vec_max(fmpz * vec1, const fmpz * vec2, const fmpz * vec3, slong len) Sets ``vec1`` to the pointwise maximum of ``vec2`` and ``vec3``. .. function:: void _fmpz_vec_max_inplace(fmpz * vec1, const fmpz * vec2, slong len) Sets ``vec1`` to the pointwise maximum of ``vec1`` and ``vec2``. Sorting -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_sort(fmpz * vec, slong len) Sorts the coefficients of ``vec`` in ascending order. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_add(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2) Sets ``(res, len2)`` to the sum of ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fmpz_vec_sub(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2) Sets ``(res, len2)`` to ``(vec1, len2)`` minus ``(vec2, len2)``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_scalar_mul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x) Sets ``(vec1, len2)`` to ``(vec2, len2)`` multiplied by `c`, where `c` is an ``fmpz_t``. .. function:: void _fmpz_vec_scalar_mul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` multiplied by `c`, where `c` is a ``slong``. .. function:: void _fmpz_vec_scalar_mul_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` multiplied by `c`, where `c` is an ``ulong``. .. function:: void _fmpz_vec_scalar_mul_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) Sets ``(vec1, len2)`` to ``(vec2, len2)`` multiplied by ``2^exp``. .. function:: void _fmpz_vec_scalar_divexact_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `x`, where the division is assumed to be exact for every entry in ``vec2``. .. function:: void _fmpz_vec_scalar_divexact_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `x`, where the division is assumed to be exact for every entry in ``vec2``. .. function:: void _fmpz_vec_scalar_divexact_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `x`, where the division is assumed to be exact for every entry in ``vec2``. .. function:: void _fmpz_vec_scalar_fdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `c`, rounding down towards minus infinity whenever the division is not exact. .. function:: void _fmpz_vec_scalar_fdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `c`, rounding down towards minus infinity whenever the division is not exact. .. function:: void _fmpz_vec_scalar_fdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `c`, rounding down towards minus infinity whenever the division is not exact. .. function:: void _fmpz_vec_scalar_fdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by ``2^exp``, rounding down towards minus infinity whenever the division is not exact. .. function:: void _fmpz_vec_scalar_fdiv_r_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) Sets ``(vec1, len2)`` to the remainder of ``(vec2, len2)`` divided by ``2^exp``, rounding down the quotient towards minus infinity whenever the division is not exact. .. function:: void _fmpz_vec_scalar_tdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `c`, rounding towards zero whenever the division is not exact. .. function:: void _fmpz_vec_scalar_tdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `c`, rounding towards zero whenever the division is not exact. .. function:: void _fmpz_vec_scalar_tdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by `c`, rounding towards zero whenever the division is not exact. .. function:: void _fmpz_vec_scalar_tdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) Sets ``(vec1, len2)`` to ``(vec2, len2)`` divided by ``2^exp``, rounding down towards zero whenever the division is not exact. .. function:: void _fmpz_vec_scalar_addmul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) .. function:: void _fmpz_vec_scalar_addmul_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) .. function:: void _fmpz_vec_scalar_addmul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c) Adds ``(vec2, len2)`` times `c` to ``(vec1, len2)``. .. function:: void _fmpz_vec_scalar_addmul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong exp) Adds ``(vec2, len2)`` times ``c * 2^exp`` to ``(vec1, len2)``, where `c` is a ``slong``. .. function:: void _fmpz_vec_scalar_submul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x) Subtracts ``(vec2, len2)`` times `c` from ``(vec1, len2)``, where `c` is a ``fmpz_t``. .. function:: void _fmpz_vec_scalar_submul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) Subtracts ``(vec2, len2)`` times `c` from ``(vec1, len2)``, where `c` is a ``slong``. .. function:: void _fmpz_vec_scalar_submul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong e) Subtracts ``(vec2, len2)`` times `c \times 2^e` from ``(vec1, len2)``, where `c` is a ``slong``. Sums and products -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_sum(fmpz_t res, const fmpz * vec, slong len) Sets ``res`` to the sum of the entries in ``(vec, len)``. Aliasing of ``res`` with the entries in ``vec`` is not permitted. .. function:: void _fmpz_vec_prod(fmpz_t res, const fmpz * vec, slong len) Sets ``res`` to the product of the entries in ``(vec, len)``. Aliasing of ``res`` with the entries in ``vec`` is not permitted. Uses binary splitting. Reduction mod `p` -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_scalar_mod_fmpz(fmpz * res, const fmpz * vec, slong len, const fmpz_t p) Reduces all entries in ``(vec, len)`` modulo `p > 0`. .. function:: void _fmpz_vec_scalar_smod_fmpz(fmpz * res, const fmpz * vec, slong len, const fmpz_t p) Reduces all entries in ``(vec, len)`` modulo `p > 0`, choosing the unique representative in `(-p/2, p/2]`. Gaussian content -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_content(fmpz_t res, const fmpz * vec, slong len) Sets ``res`` to the non-negative content of the entries in ``vec``. The content of a zero vector, including the case when the length is zero, is defined to be zero. .. function:: void _fmpz_vec_content_chained(fmpz_t res, const fmpz * vec, slong len, const fmpz_t input) Sets ``res`` to the non-negative content of ``input`` and the entries in ``vec``. This is useful for calculating the common content of several vectors. .. function:: void _fmpz_vec_lcm(fmpz_t res, const fmpz * vec, slong len) Sets ``res`` to the nonnegative least common multiple of the entries in ``vec``. The least common multiple is zero if any entry in the vector is zero. The least common multiple of a length zero vector is defined to be one. Dot product -------------------------------------------------------------------------------- .. function:: void _fmpz_vec_dot_general_naive(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * a, const fmpz * b, int reverse, slong len) void _fmpz_vec_dot_general(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * a, const fmpz * b, int reverse, slong len) Computes the dot product of the vectors *a* and *b*, setting *res* to `s + (-1)^{subtract} \sum_{i=0}^{len-1} a_i b_i`. The initial term *s* is optional and can be omitted by passing *NULL* (equivalently, `s = 0`). The parameter *subtract* must be 0 or 1. If the *reverse* flag is 1, the second vector is reversed. Aliasing is allowed between ``res`` and ``initial`` but not between ``res`` and the entries of ``a`` and ``b``. The *naive* version is used for testing purposes. .. function:: void _fmpz_vec_dot(fmpz_t res, const fmpz * vec1, const fmpz * vec2, slong len2) Sets ``res`` to the dot product of ``(vec1, len2)`` and ``(vec2, len2)``. flint-3.1.3/doc/source/fmpzi.rst000066400000000000000000000117771461254215100165740ustar00rootroot00000000000000.. _fmpzi: **fmpzi.h** -- Gaussian integers =============================================================================== This module allows working with elements of the ring `\mathbb{Z}[i]`. At present, only a minimal interface is provided. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpzi_struct .. type:: fmpzi_t Contains a pairs of integers representing the real and imaginary parts. An *fmpzi_t* is defined as an array of length one of type *fmpzi_struct*, permitting an *fmpzi_t* to be passed by reference. .. macro:: fmpzi_realref(x) Macro giving a pointer to the real part of *x*. .. macro:: fmpzi_imagref(x) Macro giving a pointer to the imaginary part of *x*. Basic manipulation ------------------------------------------------------------------------------- .. function:: void fmpzi_init(fmpzi_t x) .. function:: void fmpzi_clear(fmpzi_t x) .. function:: void fmpzi_swap(fmpzi_t x, fmpzi_t y) .. function:: void fmpzi_zero(fmpzi_t x) .. function:: void fmpzi_one(fmpzi_t x) .. function:: void fmpzi_set(fmpzi_t res, const fmpzi_t x) .. function:: void fmpzi_set_si_si(fmpzi_t res, slong a, slong b) Input and output ------------------------------------------------------------------------------- .. function:: void fmpzi_print(const fmpzi_t x) Random number generation ------------------------------------------------------------------------------- .. function:: void fmpzi_randtest(fmpzi_t res, flint_rand_t state, mp_bitcnt_t bits) Properties ------------------------------------------------------------------------------- .. function:: int fmpzi_equal(const fmpzi_t x, const fmpzi_t y) .. function:: int fmpzi_is_zero(const fmpzi_t x) .. function:: int fmpzi_is_one(const fmpzi_t x) Units ------------------------------------------------------------------------------- .. function:: int fmpzi_is_unit(const fmpzi_t x) .. function:: slong fmpzi_canonical_unit_i_pow(const fmpzi_t x) .. function:: void fmpzi_canonicalise_unit(fmpzi_t res, const fmpzi_t x) Norms ------------------------------------------------------------------------------- .. function:: slong fmpzi_bits(const fmpzi_t x) .. function:: void fmpzi_norm(fmpz_t res, const fmpzi_t x) Arithmetic ------------------------------------------------------------------------------- .. function:: void fmpzi_conj(fmpzi_t res, const fmpzi_t x) .. function:: void fmpzi_neg(fmpzi_t res, const fmpzi_t x) .. function:: void fmpzi_add(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) .. function:: void fmpzi_sub(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) .. function:: void fmpzi_sqr(fmpzi_t res, const fmpzi_t x) .. function:: void fmpzi_mul(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) .. function:: void fmpzi_pow_ui(fmpzi_t res, const fmpzi_t x, ulong exp) Division ------------------------------------------------------------------------------- .. function:: void fmpzi_divexact(fmpzi_t q, const fmpzi_t x, const fmpzi_t y) Sets *q* to the quotient of *x* and *y*, assuming that the division is exact. .. function:: void fmpzi_divrem(fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y) Computes a quotient and remainder satisfying `x = q y + r` with `N(r) \le N(y)/2`, with a canonical choice of remainder when breaking ties. .. function:: void fmpzi_divrem_approx(fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y) Computes a quotient and remainder satisfying `x = q y + r` with `N(r) < N(y)`, with an implementation-defined, non-canonical choice of remainder. .. function:: slong fmpzi_remove_one_plus_i(fmpzi_t res, const fmpzi_t x) Divide *x* exactly by the largest possible power `(1+i)^k` and return the exponent *k*. GCD ------------------------------------------------------------------------------- .. function:: void fmpzi_gcd_euclidean(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) void fmpzi_gcd_euclidean_improved(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) void fmpzi_gcd_binary(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) void fmpzi_gcd_shortest(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) void fmpzi_gcd(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) Computes the GCD of *x* and *y*. The result is in canonical unit form. The *euclidean* version is a straightforward implementation of Euclid's algorithm. The *euclidean_improved* version is optimized by performing approximate divisions. The *binary* version uses a (1+i)-ary analog of the binary GCD algorithm for integers [Wei2000]_. The *shortest* version finds the GCD as the shortest vector in a lattice. The default version chooses an algorithm automatically. Primality testing -------------------------------------------------------------------------------- .. function:: int fmpzi_is_prime(const fmpzi_t n) Check whether `n` is a Gaussian prime. .. function:: int fmpzi_is_probabprime(const fmpzi_t n) Check whether `n` is a probable Gaussian prime. flint-3.1.3/doc/source/formulas.rst000066400000000000000000000126471461254215100172740ustar00rootroot00000000000000.. _general_formulas: General formulas and bounds =============================================================================== This section collects some results from real and complex analysis that are useful when deriving error bounds. Beware of typos. Error propagation ------------------------------------------------------------------------------- We want to bound the error when `f(x+a)` is approximated by `f(x)`. Specifically, the goal is to bound `f(x + a) - f(x)` in terms of `r` for the set of values `a` with `|a| \le r`. Most bounds will be monotone increasing with `|a|` (assuming that `x` is fixed), so for brevity we simply express the bounds in terms of `|a|`. **Theorem (generic first-order bound)**: .. math:: |f(x+a) - f(x)| \le \min(2 C_0, C_1 |a|) where .. math:: C_0 = \sup_{|t| \le |a|} |f(x+t)|, \quad C_1 = \sup_{|t| \le |a|} |f'(x+t)|. The statement is valid with either `a, t \in \mathbb{R}` or `a, t \in \mathbb{C}`. **Theorem (product)**: For `x, y \in \mathbb{C}` and `a, b \in \mathbb{C}`, .. math:: \left| (x+a)(y+b) - x y \right| \le |xb| + |ya| + |ab|. **Theorem (quotient)**: For `x, y \in \mathbb{C}` and `a, b \in \mathbb{C}` with `|b| < |y|`, .. math:: \left| \frac{x}{y} - \frac{x+a}{y+b} \right| \le \frac{|xb|+|ya|}{|y| (|y|-|b|)}. **Theorem (square root)**: For `x, a \in \mathbb{R}` with `0 \le |a| \le x`, .. math:: \left| \sqrt{x+a} - \sqrt{x} \right| \le \sqrt{x} \left(1 - \sqrt{1-\frac{|a|}{x}}\right) \le \frac{\sqrt{x}}{2} \left(\frac{|a|}{x} + \frac{|a|^2}{x^2}\right) where the first inequality is an equality if `a \le 0`. (When `x = a = 0`, the limiting value is 0.) **Theorem (reciprocal square root)**: For `x, a \in \mathbb{R}` with `0 \le |a| < x`, .. math:: \left| \frac{1}{\sqrt{x+a}} - \frac{1}{\sqrt{x}} \right| \le \frac{|a|}{2 (x-|a|)^{3/2}}. **Theorem (k-th root)**: For `k > 1` and `x, a \in \mathbb{R}` with `0 \le |a| \le x`, .. math:: \left| (x+a)^{1/k} - x^{1/k} \right| \le x^{1/k} \min\left(1, \frac{1}{k} \, \log\left(1+\frac{|a|}{x-|a|}\right)\right). *Proof*: The error is largest when `a = -r` is negative, and .. math:: x^{1/k} - (x-r)^{1/k} &= x^{1/k} [1 - (1-r/x)^{1/k}] &= x^{1/k} [1 - \exp(\log(1-r/x)/k)] \le x^{1/k} \min(1, -\log(1-r/x)/k) &= x^{1/k} \min(1, \log(1+r/(x-r))/k). **Theorem (sine, cosine)**: For `x, a \in \mathbb{R}`, `|\sin(x+a) - \sin(x)| \le \min(2, |a|)`. **Theorem (logarithm)**: For `x, a \in \mathbb{R}` with `0 \le |a| < x`, .. math:: |\log(x+a) - \log(x)| \le \log\left(1 + \frac{|a|}{x-|a|}\right), with equality if `a \le 0`. **Theorem (exponential)**: For `x, a \in \mathbb{R}`, `|e^{x+a} - e^x| = e^x (e^a-1) \le e^x (e^{|a|}-1)`, with equality if `a \ge 0`. **Theorem (inverse tangent)**: For `x, a \in \mathbb{R}`, .. math:: |\operatorname{atan}(x+a) - \operatorname{atan}(x)| \le \min(\pi, C_1 |a|). where .. math:: C_1 = \sup_{|t| \le |a|} \frac{1}{1 + (x+t)^2}. If `|a| < |x|`, then `C_1 = (1 + (|x| - |a|)^2)^{-1}` gives a monotone bound. An exact bound: if `|a| < |x|` or `|x(x+a)| < 1`, then .. math:: |\operatorname{atan}(x+a) - \operatorname{atan}(x)| = \operatorname{atan}\left(\frac{|a|}{1 + x(x+a)}\right). In the last formula, a case distinction has to be made depending on the signs of *x* and *a*. Sums and series ------------------------------------------------------------------------------- **Theorem (geometric bound)**: If `|c_k| \le C` and `|z| \le D < 1`, then .. math:: \left| \sum_{k=N}^{\infty} c_k z^k \right| \le \frac{C D^N}{1 - D}. **Theorem (integral bound)**: If `f(x)` is nonnegative and monotone decreasing, then .. math:: \int_N^{\infty} f(x) \le \sum_{k=N}^{\infty} f(k) \le f(N) + \int_N^{\infty} f(x) dx. Complex analytic functions ------------------------------------------------------------------------------- **Theorem (Cauchy's integral formula)**: If `f(z) = \sum_{k=0}^{\infty} c_k z^k` is analytic (on an open subset of `\mathbb{C}` containing the disk `D = \{ z : |z| \le R \}` in its interior, where `R > 0`), then .. math:: c_k = \frac{1}{2\pi i} \int_{|z|=R} \frac{f(z)}{z^{k+1}}\, dz. **Corollary (derivative bound)**: .. math:: |c_k| \le \frac{C}{R^k}, \quad C = \max_{|z|=R} |f(z)|. **Corollary (Taylor series tail)**: If `0 \le r < R` and `|z| \le r`, then .. math:: \left|\sum_{k=N}^{\infty} c_k z^k\right| \le \frac{C D^N}{1-D}, \quad D = \left|\frac{r}{R}\right|. Euler-Maclaurin formula ------------------------------------------------------------------------------- **Theorem (Euler-Maclaurin)**: If `f(t)` is `2M`-times differentiable, then .. math:: \sum_{k=L}^U f(k) = S + I + T + R .. math:: S = \sum_{k=L}^{N-1} f(k), \quad I = \int_N^U f(t) dt, .. math:: T = \frac{1}{2} \left( f(N) + f(U) \right) + \sum_{k=1}^M \frac{B_{2k}}{(2k)!} \left(f^{(2k-1)}(U) - f^{(2k-1)}(N)\right), .. math:: R = -\int_N^U \frac{B_{2M}(t - \lfloor t \rfloor)}{(2M)!} f^{(2M)}(t) dt. **Lemma (Bernoulli polynomials)**: `|B_n(t - \lfloor t \rfloor)| \le 4 n! / (2 \pi)^n`. **Theorem (remainder bound)**: .. math:: |R| \le \frac{4}{(2\pi)^{2M}} \int_N^U \left| f^{(2M)}(t) \right| dt. **Theorem (parameter derivatives)**: If `f(t) = f(t,x) = \sum_{k=0}^{\infty} a_k(t) x^k` and `R = R(x) = \sum_{k=0}^{\infty} c_k x^k` are analytic functions of `x`, then .. math:: |c_k| \le \frac{4}{(2\pi)^{2M}} \int_N^U |a_k^{(2M)}(t)| dt. flint-3.1.3/doc/source/fq.rst000066400000000000000000000450441461254215100160470ustar00rootroot00000000000000.. _fq: **fq.h** -- finite fields =============================================================================== We represent an element of the finite field `\mathbf{F}_{p^n} \cong \mathbf{F}_p[X]/(f(X))`, where `f(X) \in \mathbf{F}_p[X]` is a monic, irreducible polynomial of degree `n`, as a polynomial in `\mathbf{F}_p[X]` of degree less than `n`. The underlying data structure is an :type:`fmpz_poly_t`. The default choice for `f(X)` is the Conway polynomial for the pair `(p,n)`, enabled by Frank Lübeck's data base of Conway polynomials using the :func:`_nmod_poly_conway` function. If a Conway polynomial is not available, then a random irreducible polynomial will be chosen for `f(X)`. Additionally, the user is able to supply their own `f(X)`. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_ctx_struct .. type:: fq_ctx_t .. type:: fq_struct .. type:: fq_t Context Management -------------------------------------------------------------------------------- .. function:: void fq_ctx_init(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator. By default, it will try use a Conway polynomial; if one is not available, a random irreducible polynomial will be used. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: int _fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var) Attempts to initialise the context for prime `p` and extension degree `d`, with name ``var`` for the generator using a Conway polynomial for the modulus. Returns `1` if the Conway polynomial is in the database for the given size and the initialization is successful; otherwise, returns `0`. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator using a Conway polynomial for the modulus. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_ctx_init_modulus(fq_ctx_t ctx, const fmpz_mod_poly_t modulus, const fmpz_mod_ctx_t ctxp, const char * var) Initialises the context for given ``modulus`` with name ``var`` for the generator. Assumes that ``modulus`` is an irreducible polynomial over the finite field `\mathbf{F}_{p}` in ``ctxp``. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_ctx_init_randtest(fq_ctx_t ctx, flint_rand_t state, int type) Initialises ``ctx`` to a random finite field, where the prime and degree is set according to ``type``. To see what prime and degrees may be output, see ``type`` in :func:`_nmod_poly_conway_rand`. .. function:: void fq_ctx_init_randtest_reducible(fq_ctx_t ctx, flint_rand_t state, int type) Initializes ``ctx`` to a random extension of a prime field, where the prime and degree is set according to ``type``. If ``type`` is `0` the prime and degree may be large, else if ``type`` is `1` the degree is small but the prime may be large, else if ``type`` is `2` the prime is small but the degree may be large, else if ``type`` is `3` both prime and degree are small. The modulus may or may not be irreducible. .. function:: void fq_ctx_clear(fq_ctx_t ctx) Clears all memory that has been allocated as part of the context. .. function:: const fmpz_mod_poly_struct* fq_ctx_modulus(const fq_ctx_t ctx) Returns a pointer to the modulus in the context. .. function:: slong fq_ctx_degree(const fq_ctx_t ctx) Returns the degree of the field extension `[\mathbf{F}_{q} : \mathbf{F}_{p}]`, which is equal to `\log_{p} q`. .. function:: const fmpz * fq_ctx_prime(const fq_ctx_t ctx) Returns a pointer to the prime `p` in the context. .. function:: void fq_ctx_order(fmpz_t f, const fq_ctx_t ctx) Sets `f` to be the size of the finite field. .. function:: int fq_ctx_fprint(FILE * file, const fq_ctx_t ctx) Prints the context information to ``file``. Returns 1 for a success and a negative number for an error. .. function:: void fq_ctx_print(const fq_ctx_t ctx) Prints the context information to ``stdout``. Memory management -------------------------------------------------------------------------------- .. function:: void fq_init(fq_t rop, const fq_ctx_t ctx) Initialises the element ``rop``, setting its value to `0`. .. function:: void fq_init2(fq_t rop, const fq_ctx_t ctx) Initialises ``poly`` with at least enough space for it to be an element of ``ctx`` and sets it to `0`. .. function:: void fq_clear(fq_t rop, const fq_ctx_t ctx) Clears the element ``rop``. .. function:: void _fq_sparse_reduce(fmpz * R, slong lenR, const fq_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx``. .. function:: void _fq_dense_reduce(fmpz * R, slong lenR, const fq_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx`` using Newton division. .. function:: void _fq_reduce(fmpz * r, slong lenR, const fq_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx``. Does either sparse or dense reduction based on ``ctx->sparse_modulus``. .. function:: void fq_reduce(fq_t rop, const fq_ctx_t ctx) Reduces the polynomial ``rop`` as an element of `\mathbf{F}_p[X] / (f(X))`. Basic arithmetic -------------------------------------------------------------------------------- .. function:: void fq_add(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx) Sets ``rop`` to the sum of ``op1`` and ``op2``. .. function:: void fq_sub(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and ``op2``. .. function:: void fq_sub_one(fq_t rop, const fq_t op1, const fq_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and `1`. .. function:: void fq_neg(fq_t rop, const fq_t op, const fq_ctx_t ctx) Sets ``rop`` to the negative of ``op``. .. function:: void fq_mul(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void fq_mul_fmpz(fq_t rop, const fq_t op, const fmpz_t x, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_mul_si(fq_t rop, const fq_t op, slong x, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_mul_ui(fq_t rop, const fq_t op, ulong x, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_sqr(fq_t rop, const fq_t op, const fq_ctx_t ctx) Sets ``rop`` to the square of ``op``, reducing the output in the given context. .. function:: void fq_div(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx) Sets ``rop`` to the quotient of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void _fq_inv(fmpz * rop, const fmpz * op, slong len, const fq_ctx_t ctx) Sets ``(rop, d)`` to the inverse of the non-zero element ``(op, len)``. .. function:: void fq_inv(fq_t rop, const fq_t op, const fq_ctx_t ctx) Sets ``rop`` to the inverse of the non-zero element ``op``. .. function:: void fq_gcdinv(fq_t f, fq_t inv, const fq_t op, const fq_ctx_t ctx) Sets ``inv`` to be the inverse of ``op`` modulo the modulus of ``ctx``. If ``op`` is not invertible, then ``f`` is set to a factor of the modulus; otherwise, it is set to one. .. function:: void _fq_pow(fmpz * rop, const fmpz * op, slong len, const fmpz_t e, const fq_ctx_t ctx) Sets ``(rop, 2*d-1)`` to ``(op,len)`` raised to the power `e`, reduced modulo `f(X)`, the modulus of ``ctx``. Assumes that `e \geq 0` and that ``len`` is positive and at most `d`. Although we require that ``rop`` provides space for `2d - 1` coefficients, the output will be reduced modulo `f(X)`, which is a polynomial of degree `d`. Does not support aliasing. .. function:: void fq_pow(fq_t rop, const fq_t op, const fmpz_t e, const fq_ctx_t ctx) Sets ``rop`` the ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. .. function:: void fq_pow_ui(fq_t rop, const fq_t op, const ulong e, const fq_ctx_t ctx) Sets ``rop`` the ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. Roots -------------------------------------------------------------------------------- .. function:: int fq_sqrt(fq_t rop, const fq_t op1, const fq_ctx_t ctx) Sets ``rop`` to the square root of ``op1`` if it is a square, and return `1`, otherwise return `0`. .. function:: void fq_pth_root(fq_t rop, const fq_t op1, const fq_ctx_t ctx) Sets ``rop`` to a `p^{th}` root root of ``op1``. Currently, this computes the root by raising ``op1`` to `p^{d-1}` where `d` is the degree of the extension. .. function:: int fq_is_square(const fq_t op, const fq_ctx_t ctx) Return ``1`` if ``op`` is a square. Output -------------------------------------------------------------------------------- .. function:: int fq_fprint_pretty(FILE * file, const fq_t op, const fq_ctx_t ctx) Prints a pretty representation of ``op`` to ``file``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. .. function:: int fq_print_pretty(const fq_t op, const fq_ctx_t ctx) Prints a pretty representation of ``op`` to ``stdout``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. .. function:: int fq_fprint(FILE * file, const fq_t op, const fq_ctx_t ctx) Prints a representation of ``op`` to ``file``. For further details on the representation used, see :func:`fmpz_mod_poly_fprint`. .. function:: void fq_print(const fq_t op, const fq_ctx_t ctx) Prints a representation of ``op`` to ``stdout``. For further details on the representation used, see :func:`fmpz_mod_poly_print`. .. function:: char * fq_get_str(const fq_t op, const fq_ctx_t ctx) Returns the plain FLINT string representation of the element ``op``. .. function:: char * fq_get_str_pretty(const fq_t op, const fq_ctx_t ctx) Returns a pretty representation of the element ``op`` using the null-terminated string ``x`` as the variable name. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_randtest(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) Generates a random element of `\mathbf{F}_q`. .. function:: void fq_randtest_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) Generates a random non-zero element of `\mathbf{F}_q`. .. function:: void fq_randtest_dense(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) Generates a random element of `\mathbf{F}_q` which has an underlying polynomial with dense coefficients. .. function:: void fq_rand(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) Generates a high quality random element of `\mathbf{F}_q`. .. function:: void fq_rand_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) Generates a high quality non-zero random element of `\mathbf{F}_q`. Assignments and conversions -------------------------------------------------------------------------------- .. function:: void fq_set(fq_t rop, const fq_t op, const fq_ctx_t ctx) Sets ``rop`` to ``op``. .. function:: void fq_set_si(fq_t rop, const slong x, const fq_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_set_ui(fq_t rop, const ulong x, const fq_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_set_fmpz(fq_t rop, const fmpz_t x, const fq_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_swap(fq_t op1, fq_t op2, const fq_ctx_t ctx) Swaps the two elements ``op1`` and ``op2``. .. function:: void fq_zero(fq_t rop, const fq_ctx_t ctx) Sets ``rop`` to zero. .. function:: void fq_one(fq_t rop, const fq_ctx_t ctx) Sets ``rop`` to one, reduced in the given context. .. function:: void fq_gen(fq_t rop, const fq_ctx_t ctx) Sets ``rop`` to a generator for the finite field. There is no guarantee this is a multiplicative generator of the finite field. .. function:: int fq_get_fmpz(fmpz_t rop, const fq_t op, const fq_ctx_t ctx) If ``op`` has a lift to the integers, return `1` and set ``rop`` to the lift in `[0,p)`. Otherwise, return `0` and leave `rop` undefined. .. function:: void fq_get_fmpz_poly(fmpz_poly_t a, const fq_t b, const fq_ctx_t ctx) .. function:: void fq_get_fmpz_mod_poly(fmpz_mod_poly_t a, const fq_t b, const fq_ctx_t ctx) Set ``a`` to a representative of ``b`` in ``ctx``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. .. function:: void fq_set_fmpz_poly(fq_t a, const fmpz_poly_t b, const fq_ctx_t ctx) .. function:: void fq_set_fmpz_mod_poly(fq_t a, const fmpz_mod_poly_t b, const fq_ctx_t ctx) Set ``a`` to the element in ``ctx`` with representative ``b``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. .. function:: void fq_get_fmpz_mod_mat(fmpz_mod_mat_t col, const fq_t a, const fq_ctx_t ctx) Convert ``a`` to a column vector of length ``degree(ctx)``. .. function:: void fq_set_fmpz_mod_mat(fq_t a, const fmpz_mod_mat_t col, const fq_ctx_t ctx) Convert a column vector ``col`` of length ``degree(ctx)`` to an element of ``ctx``. Comparison -------------------------------------------------------------------------------- .. function:: int fq_is_zero(const fq_t op, const fq_ctx_t ctx) Returns whether ``op`` is equal to zero. .. function:: int fq_is_one(const fq_t op, const fq_ctx_t ctx) Returns whether ``op`` is equal to one. .. function:: int fq_equal(const fq_t op1, const fq_t op2, const fq_ctx_t ctx) Returns whether ``op1`` and ``op2`` are equal. .. function:: int fq_is_invertible(const fq_t op, const fq_ctx_t ctx) Returns whether ``op`` is an invertible element. .. function:: int fq_is_invertible_f(fq_t f, const fq_t op, const fq_ctx_t ctx) Returns whether ``op`` is an invertible element. If it is not, then ``f`` is set of a factor of the modulus. Special functions -------------------------------------------------------------------------------- .. function:: void _fq_trace(fmpz_t rop, const fmpz * op, slong len, const fq_ctx_t ctx) Sets ``rop`` to the trace of the non-zero element ``(op, len)`` in `\mathbf{F}_{q}`. .. function:: void fq_trace(fmpz_t rop, const fq_t op, const fq_ctx_t ctx) Sets ``rop`` to the trace of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the trace of `a` as the trace of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\sum_{i=0}^{d-1} \Sigma^i (a)`, where `d = \log_{p} q`. .. function:: void _fq_norm(fmpz_t rop, const fmpz * op, slong len, const fq_ctx_t ctx) Sets ``rop`` to the norm of the non-zero element ``(op, len)`` in `\mathbf{F}_{q}`. .. function:: void fq_norm(fmpz_t rop, const fq_t op, const fq_ctx_t ctx) Computes the norm of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the norm of `a` as the determinant of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\prod_{i=0}^{d-1} \Sigma^i (a)`, where `d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)`. Algorithm selection is automatic depending on the input. .. function:: void _fq_frobenius(fmpz * rop, const fmpz * op, slong len, slong e, const fq_ctx_t ctx) Sets ``(rop, 2d-1)`` to the image of ``(op, len)`` under the Frobenius operator raised to the e-th power, assuming that neither ``op`` nor ``e`` are zero. .. function:: void fq_frobenius(fq_t rop, const fq_t op, slong e, const fq_ctx_t ctx) Evaluates the homomorphism `\Sigma^e` at ``op``. Recall that `\mathbf{F}_q / \mathbf{F}_p` is Galois with Galois group `\langle \sigma \rangle`, which is also isomorphic to `\mathbf{Z}/d\mathbf{Z}`, where `\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)` is the Frobenius element `\sigma \colon x \mapsto x^p`. .. function:: int fq_multiplicative_order(fmpz * ord, const fq_t op, const fq_ctx_t ctx) Computes the order of ``op`` as an element of the multiplicative group of ``ctx``. Returns 0 if ``op`` is 0, otherwise it returns 1 if ``op`` is a generator of the multiplicative group, and -1 if it is not. This function can also be used to check primitivity of a generator of a finite field whose defining polynomial is not primitive. .. function:: int fq_is_primitive(const fq_t op, const fq_ctx_t ctx) Returns whether ``op`` is primitive, i.e., whether it is a generator of the multiplicative group of ``ctx``. Bit packing -------------------------------------------------------------------------------- .. function:: void fq_bit_pack(fmpz_t f, const fq_t op, flint_bitcnt_t bit_size, const fq_ctx_t ctx) Packs ``op`` into bitfields of size ``bit_size``, writing the result to ``f``. .. function:: void fq_bit_unpack(fq_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_ctx_t ctx) Unpacks into ``rop`` the element with coefficients packed into fields of size ``bit_size`` as represented by the integer ``f``. flint-3.1.3/doc/source/fq_default.rst000066400000000000000000000417071461254215100175550ustar00rootroot00000000000000.. _fq_default_default: **fq_default_default.h** -- unified finite fields =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_default_ctx_t .. type:: fq_default_default_t Context Management -------------------------------------------------------------------------------- .. function:: void fq_default_ctx_init(fq_default_ctx_t ctx, const fmpz_t p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator. By default, it will try use a Conway polynomial; if one is not available, a random irreducible polynomial will be used. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_default_ctx_init_type(fq_default_ctx_t ctx, const fmpz_t p, slong d, const char * var, int type) As per the previous function except that if ``type == 1`` an ``fq_zech`` context is created, if ``type == 2`` an ``fq_nmod`` and if ``type == 3`` an ``fq``. If ``type == 0`` the functionality is as per the previous function. .. function:: void fq_default_ctx_init_modulus(fq_default_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var) Initialises the context for the finite field defined by the given polynomial ``modulus``. The characteristic will be the modulus of the polynomial and the degree equal to its degree. Assumes that the characteristic is prime and the polynomial irreducible. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_default_ctx_init_modulus_type(fq_default_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var, int type) As per the previous function except that if ``type == 1`` an ``fq_zech`` context is created, if ``type == 2`` an ``fq_nmod`` and if ``type == 3`` an ``fq``. If ``type == 0`` the functionality is as per the previous function. .. function:: void fq_default_ctx_init_modulus_nmod(fq_default_ctx_t ctx, const nmod_poly_t modulus, const char * var) Initialises the context for the finite field defined by the given polynomial ``modulus``. The characteristic will be the modulus of the polynomial and the degree equal to its degree. Assumes that the characteristic is prime and the polynomial irreducible. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_default_ctx_init_modulus_nmod_type(fq_default_ctx_t ctx, const nmod_poly_t modulus, const char * var, int type) As per the previous function except that if ``type == 1`` an ``fq_zech`` context is created, if ``type == 2`` an ``fq_nmod`` and if ``type == 3`` an ``fq``. If ``type == 0`` the functionality is as per the previous function. .. function:: void fq_default_ctx_clear(fq_default_ctx_t ctx) Clears all memory that has been allocated as part of the context. .. function:: int fq_default_ctx_type(const fq_default_ctx_t ctx) Returns `1` if the context contains an ``fq_zech`` context, `2` if it contains an ``fq_mod`` context and `3` if it contains an ``fq`` context. .. function:: void * fq_default_ctx_inner(const fq_default_ctx_t ctx) Returns a pointer to the internal context object of type ``fq_ctx_t``, ``fq_zech_ctx_t``, ``fmpz_mod_ctx_t``, etc. .. function:: slong fq_default_ctx_degree(const fq_default_ctx_t ctx) Returns the degree of the field extension `[\mathbf{F}_{q} : \mathbf{F}_{p}]`, which is equal to `\log_{p} q`. .. function:: void fq_default_ctx_prime(fmpz_t prime, const fq_default_ctx_t ctx) Sets `prime` to the prime `p` in the context. .. function:: void fq_default_ctx_order(fmpz_t f, const fq_default_ctx_t ctx) Sets `f` to be the size of the finite field. .. function:: void fq_default_ctx_modulus(fmpz_mod_poly_t p, const fq_default_ctx_t ctx) Sets `p` to the defining polynomial of the finite field.. .. function:: int fq_default_ctx_fprint(FILE * file, const fq_default_ctx_t ctx) Prints the context information to ``file``. Returns 1 for a success and a negative number for an error. .. function:: void fq_default_ctx_print(const fq_default_ctx_t ctx) Prints the context information to ``stdout``. .. function:: void fq_default_ctx_randtest(fq_default_ctx_t ctx) Initializes ``ctx`` to a random finite field. Assumes that ``fq_default_ctx_init`` has not been called on ``ctx`` already. .. function:: void fq_default_get_coeff_fmpz(fmpz_t c, fq_default_t op, slong n, const fq_default_ctx_t ctx) Set `c` to the degree `n` coefficient of the polynomial representation of the finite field element ``op``. Memory management -------------------------------------------------------------------------------- .. function:: void fq_default_init(fq_default_t rop, const fq_default_ctx_t ctx) Initialises the element ``rop``, setting its value to `0`. .. function:: void fq_default_init2(fq_default_t rop, const fq_default_ctx_t ctx) Initialises ``poly`` with at least enough space for it to be an element of ``ctx`` and sets it to `0`. .. function:: void fq_default_clear(fq_default_t rop, const fq_default_ctx_t ctx) Clears the element ``rop``. Predicates -------------------------------------------------------------------------------- .. function:: int fq_default_is_invertible(const fq_default_t op, const fq_default_ctx_t ctx) Return ``1`` if ``op`` is an invertible element. Basic arithmetic -------------------------------------------------------------------------------- .. function:: void fq_default_add(fq_default_t rop, const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) Sets ``rop`` to the sum of ``op1`` and ``op2``. .. function:: void fq_default_sub(fq_default_t rop, const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and ``op2``. .. function:: void fq_default_sub_one(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and `1`. .. function:: void fq_default_neg(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) Sets ``rop`` to the negative of ``op``. .. function:: void fq_default_mul(fq_default_t rop, const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void fq_default_mul_fmpz(fq_default_t rop, const fq_default_t op, const fmpz_t x, const fq_default_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_default_mul_si(fq_default_t rop, const fq_default_t op, slong x, const fq_default_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_default_mul_ui(fq_default_t rop, const fq_default_t op, ulong x, const fq_default_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_default_sqr(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) Sets ``rop`` to the square of ``op``, reducing the output in the given context. .. function:: void fq_default_div(fq_default_t rop, fq_default_t op1, fq_default_t op2, const fq_default_ctx_t ctx) Sets ``rop`` to the quotient of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void fq_default_inv(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) Sets ``rop`` to the inverse of the non-zero element ``op``. .. function:: void fq_default_pow(fq_default_t rop, const fq_default_t op, const fmpz_t e, const fq_default_ctx_t ctx) Sets ``rop`` the ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. .. function:: void fq_default_pow_ui(fq_default_t rop, const fq_default_t op, const ulong e, const fq_default_ctx_t ctx) Sets ``rop`` the ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. Roots -------------------------------------------------------------------------------- .. function:: int fq_default_sqrt(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) Sets ``rop`` to the square root of ``op1`` if it is a square, and return `1`, otherwise return `0`. .. function:: void fq_default_pth_root(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) Sets ``rop`` to a `p^{th}` root root of ``op1``. Currently, this computes the root by raising ``op1`` to `p^{d-1}` where `d` is the degree of the extension. .. function:: int fq_default_is_square(const fq_default_t op, const fq_default_ctx_t ctx) Return ``1`` if ``op`` is a square. Output -------------------------------------------------------------------------------- .. function:: int fq_default_fprint_pretty(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx) Prints a pretty representation of ``op`` to ``file``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. .. function:: void fq_default_print_pretty(const fq_default_t op, const fq_default_ctx_t ctx) Prints a pretty representation of ``op`` to ``stdout``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. .. function:: int fq_default_fprint(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx) Prints a representation of ``op`` to ``file``. .. function:: void fq_default_print(const fq_default_t op, const fq_default_ctx_t ctx) Prints a representation of ``op`` to ``stdout``. .. function:: char * fq_default_get_str(const fq_default_t op, const fq_default_ctx_t ctx) Returns the plain FLINT string representation of the element ``op``. .. function:: char * fq_default_get_str_pretty(const fq_default_t op, const fq_default_ctx_t ctx) Returns a pretty representation of the element ``op`` using the null-terminated string ``x`` as the variable name. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_default_randtest(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) Generates a random element of `\mathbf{F}_q`. .. function:: void fq_default_randtest_not_zero(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) Generates a random non-zero element of `\mathbf{F}_q`. .. function:: void fq_default_rand(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) Generates a high quality random element of `\mathbf{F}_q`. .. function:: void fq_default_rand_not_zero(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) Generates a high quality non-zero random element of `\mathbf{F}_q`. Assignments and conversions -------------------------------------------------------------------------------- .. function:: void fq_default_set(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) Sets ``rop`` to ``op``. .. function:: void fq_default_set_si(fq_default_t rop, const slong x, const fq_default_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_default_set_ui(fq_default_t rop, const ulong x, const fq_default_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_default_set_fmpz(fq_default_t rop, const fmpz_t x, const fq_default_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_default_swap(fq_default_t op1, fq_default_t op2, const fq_default_ctx_t ctx) Swaps the two elements ``op1`` and ``op2``. .. function:: void fq_default_zero(fq_default_t rop, const fq_default_ctx_t ctx) Sets ``rop`` to zero. .. function:: void fq_default_one(fq_default_t rop, const fq_default_ctx_t ctx) Sets ``rop`` to one, reduced in the given context. .. function:: void fq_default_gen(fq_default_t rop, const fq_default_ctx_t ctx) Sets ``rop`` to a generator for the finite field. There is no guarantee this is a multiplicative generator of the finite field. .. function:: int fq_default_get_fmpz(fmpz_t rop, const fq_default_t op, const fq_default_ctx_t ctx) If ``op`` has a lift to the integers, return `1` and set ``rop`` to the lift in `[0,p)`. Otherwise, return `0` and leave `rop` undefined. .. function:: void fq_default_get_nmod_poly(nmod_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx) Sets ``poly`` to the polynomial representation of ``op``. Assumes the characteristic of the field and the modulus of the polynomial are the same. No checking of this occurs. .. function:: void fq_default_set_nmod_poly(fq_default_t op, const nmod_poly_t poly, const fq_default_ctx_t ctx) Sets ``op`` to the finite field element represented by the polynomial ``poly``. Assumes the characteristic of the field and the modulus of the polynomial are the same. No checking of this occurs. .. function:: void fq_default_get_fmpz_mod_poly(fmpz_mod_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx) Sets ``poly`` to the polynomial representation of ``op``. Assumes the characteristic of the field and the modulus of the polynomial are the same. No checking of this occurs. .. function:: void fq_default_set_fmpz_mod_poly(fq_default_t op, const fmpz_mod_poly_t poly, const fq_default_ctx_t ctx) Sets ``op`` to the finite field element represented by the polynomial ``poly``. Assumes the characteristic of the field and the modulus of the polynomial are the same. No checking of this occurs. .. function:: void fq_default_get_fmpz_poly(fmpz_poly_t a, const fq_default_t b, const fq_default_ctx_t ctx) Set ``a`` to a representative of ``b`` in ``ctx``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. .. function:: void fq_default_set_fmpz_poly(fq_default_t a, const fmpz_poly_t b, const fq_default_ctx_t ctx) Set ``a`` to the element in ``ctx`` with representative ``b``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. Comparison -------------------------------------------------------------------------------- .. function:: int fq_default_is_zero(const fq_default_t op, const fq_default_ctx_t ctx) Returns whether ``op`` is equal to zero. .. function:: int fq_default_is_one(const fq_default_t op, const fq_default_ctx_t ctx) Returns whether ``op`` is equal to one. .. function:: int fq_default_equal(const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) Returns whether ``op1`` and ``op2`` are equal. Special functions -------------------------------------------------------------------------------- .. function:: void fq_default_trace(fmpz_t rop, const fq_default_t op, const fq_default_ctx_t ctx) Sets ``rop`` to the trace of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the trace of `a` as the trace of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\sum_{i=0}^{d-1} \Sigma^i (a)`, where `d = \log_{p} q`. .. function:: void fq_default_norm(fmpz_t rop, const fq_default_t op, const fq_default_ctx_t ctx) Computes the norm of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the norm of `a` as the determinant of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\prod_{i=0}^{d-1} \Sigma^i (a)`, where `d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)`. Algorithm selection is automatic depending on the input. .. function:: void fq_default_frobenius(fq_default_t rop, const fq_default_t op, slong e, const fq_default_ctx_t ctx) Evaluates the homomorphism `\Sigma^e` at ``op``. Recall that `\mathbf{F}_q / \mathbf{F}_p` is Galois with Galois group `\langle \sigma \rangle`, which is also isomorphic to `\mathbf{Z}/d\mathbf{Z}`, where `\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)` is the Frobenius element `\sigma \colon x \mapsto x^p`. flint-3.1.3/doc/source/fq_default_mat.rst000066400000000000000000000426241461254215100204150ustar00rootroot00000000000000.. _fq_default_mat: **fq_default_mat.h** -- matrices over finite fields =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_default_mat_init(fq_default_mat_t mat, slong rows, slong cols, const fq_default_ctx_t ctx) Initialises ``mat`` to a ``rows``-by-``cols`` matrix with coefficients in `\mathbf{F}_{q}` given by ``ctx``. All elements are set to zero. .. function:: void fq_default_mat_init_set(fq_default_mat_t mat, const fq_default_mat_t src, const fq_default_ctx_t ctx) Initialises ``mat`` and sets its dimensions and elements to those of ``src``. .. function:: void fq_default_mat_clear(fq_default_mat_t mat, const fq_default_ctx_t ctx) Clears the matrix and releases any memory it used. The matrix cannot be used again until it is initialised. This function must be called exactly once when finished using an ``fq_default_mat_t`` object. .. function:: void fq_default_mat_set(fq_default_mat_t mat, const fq_default_mat_t src, const fq_default_ctx_t ctx) Sets ``mat`` to a copy of ``src``. It is assumed that ``mat`` and ``src`` have identical dimensions. Basic properties and manipulation -------------------------------------------------------------------------------- .. function:: void fq_default_mat_entry(fq_default_t val, const fq_default_mat_t mat, slong i, slong j, const fq_default_ctx_t ctx) Directly accesses the entry in ``mat`` in row `i` and column `j`, indexed from zero by setting ``val`` to the value of that entry. No bounds checking is performed. .. function:: void fq_default_mat_entry_set(fq_default_mat_t mat, slong i, slong j, const fq_default_t x, const fq_default_ctx_t ctx) Sets the entry in ``mat`` in row `i` and column `j` to ``x``. .. function:: void fq_default_mat_entry_set_fmpz(fq_default_mat_t mat, slong i, slong j, const fmpz_t x, const fq_default_ctx_t ctx) Sets the entry in ``mat`` in row `i` and column `j` to ``x``. .. function:: slong fq_default_mat_nrows(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_default_mat_ncols(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Returns the number of columns in ``mat``. .. function:: void fq_default_mat_swap(fq_default_mat_t mat1, fq_default_mat_t mat2, const fq_default_ctx_t ctx) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. function:: void fq_default_mat_zero(fq_default_mat_t mat, const fq_default_ctx_t ctx) Sets all entries of ``mat`` to 0. .. function:: void fq_default_mat_one(fq_default_mat_t mat, const fq_default_ctx_t ctx) Sets the diagonal entries of ``mat`` to 1 and all other entries to 0. .. function:: void fq_default_mat_swap_rows(fq_default_mat_t mat, slong * perm, slong r, slong s, const fq_default_ctx_t ctx) Swaps rows ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fq_default_mat_swap_cols(fq_default_mat_t mat, slong * perm, slong r, slong s, const fq_default_ctx_t ctx) Swaps columns ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: void fq_default_mat_invert_rows(fq_default_mat_t mat, slong * perm, const fq_default_ctx_t ctx) Swaps rows ``i`` and ``r - i`` of ``mat`` for ``0 <= i < r/2``, where ``r`` is the number of rows of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fq_default_mat_invert_cols(fq_default_mat_t mat, slong * perm, const fq_default_ctx_t ctx) Swaps columns ``i`` and ``c - i`` of ``mat`` for ``0 <= i < c/2``, where ``c`` is the number of columns of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. Conversions -------------------------------------------------------------------------------- .. function:: void fq_default_mat_set_nmod_mat(fq_default_mat_t mat1, const nmod_mat_t mat2, const fq_default_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. .. function:: void fq_default_mat_set_fmpz_mod_mat(fq_default_mat_t mat1, const fmpz_mod_mat_t mat2, const fq_default_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. .. function:: void fq_default_mat_set_fmpz_mat(fq_default_mat_t mat1, const fmpz_mat_t mat2, const fq_default_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``, reducing the entries modulo the characteristic of the finite field. Concatenate -------------------------------------------------------------------------------- .. function:: void fq_default_mat_concat_vertical(fq_default_mat_t res, const fq_default_mat_t mat1, const fq_default_mat_t mat2, const fq_default_ctx_t ctx) Sets ``res`` to vertical concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `k \times n`, ``res`` : `(m + k) \times n`. .. function:: void fq_default_mat_concat_horizontal(fq_default_mat_t res, const fq_default_mat_t mat1, const fq_default_mat_t mat2, const fq_default_ctx_t ctx) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `m \times k`, ``res`` : `m \times (n + k)`. Printing -------------------------------------------------------------------------------- .. function:: int fq_default_mat_print_pretty(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Pretty-prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_default_mat_fprint_pretty(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx) Pretty-prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_default_mat_print(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_default_mat_fprint(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx) Prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. Window -------------------------------------------------------------------------------- .. function:: void fq_default_mat_window_init(fq_default_mat_t window, const fq_default_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fq_default_ctx_t ctx) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0,0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void fq_default_mat_window_clear(fq_default_mat_t window, const fq_default_ctx_t ctx) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. Random matrix generation -------------------------------------------------------------------------------- .. function:: void fq_default_mat_randtest(fq_default_mat_t mat, flint_rand_t state, const fq_default_ctx_t ctx) Sets the elements of ``mat`` to random elements of `\mathbf{F}_{q}`, given by ``ctx``. .. function:: int fq_default_mat_randpermdiag(fq_mat_t mat, flint_rand_t state, fq_struct * diag, slong n, const fq_ctx_t ctx) Sets ``mat`` to a random permutation of the diagonal matrix with `n` leading entries given by the vector ``diag``. It is assumed that the main diagonal of ``mat`` has room for at least `n` entries. Returns `0` or `1`, depending on whether the permutation is even or odd respectively. .. function:: void fq_default_mat_randrank(fq_default_mat_t mat, flint_rand_t state, slong rank, const fq_default_ctx_t ctx) Sets ``mat`` to a random sparse matrix with the given rank, having exactly as many non-zero elements as the rank, with the non-zero elements being uniformly random elements of `\mathbf{F}_{q}`. The matrix can be transformed into a dense matrix with unchanged rank by subsequently calling :func:`fq_default_mat_randops`. .. function:: void fq_default_mat_randops(fq_default_mat_t mat, flint_rand_t state, slong count, const fq_default_ctx_t ctx) Randomises ``mat`` by performing elementary row or column operations. More precisely, at most ``count`` random additions or subtractions of distinct rows and columns will be performed. This leaves the rank (and for square matrices, determinant) unchanged. .. function:: void fq_default_mat_randtril(fq_default_mat_t mat, flint_rand_t state, int unit, const fq_default_ctx_t ctx) Sets ``mat`` to a random lower triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. .. function:: void fq_default_mat_randtriu(fq_default_mat_t mat, flint_rand_t state, int unit, const fq_default_ctx_t ctx) Sets ``mat`` to a random upper triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. Comparison -------------------------------------------------------------------------------- .. function:: int fq_default_mat_equal(const fq_default_mat_t mat1, const fq_default_mat_t mat2, const fq_default_ctx_t ctx) Returns nonzero if mat1 and mat2 have the same dimensions and elements, and zero otherwise. .. function:: int fq_default_mat_is_zero(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Returns a non-zero value if all entries of ``mat`` are zero, and otherwise returns zero. .. function:: int fq_default_mat_is_one(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Returns a non-zero value if all diagonal entries of ``mat`` are one and all other entries are zero, and otherwise returns zero. .. function:: int fq_default_mat_is_empty(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int fq_default_mat_is_square(const fq_default_mat_t mat, const fq_default_ctx_t ctx) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void fq_default_mat_add(fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) Computes `C = A + B`. Dimensions must be identical. .. function:: void fq_default_mat_sub(fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) Computes `C = A - B`. Dimensions must be identical. .. function:: void fq_default_mat_neg(fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) Sets `B = -A`. Dimensions must be identical. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void fq_default_mat_mul(fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. Aliasing is allowed. This function automatically chooses between classical and KS multiplication. .. function:: void fq_default_mat_submul(fq_default_mat_t D, const fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) Sets `D = C + AB`. `C` and `D` may be aliased with each other but not with `A` or `B`. Inverse -------------------------------------------------------------------------------- .. function:: int fq_default_mat_inv(fq_default_mat_t B, fq_default_mat_t A, const fq_default_ctx_t ctx) Sets `B = A^{-1}` and returns `1` if `A` is invertible. If `A` is singular, returns `0` and sets the elements of `B` to undefined values. `A` and `B` must be square matrices with the same dimensions. LU decomposition -------------------------------------------------------------------------------- .. function:: slong fq_default_mat_lu(slong * P, fq_default_mat_t A, int rank_check, const fq_default_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. If `A` is a nonsingular square matrix, it will be overwritten with a unit diagonal lower triangular matrix `L` and an upper triangular matrix `U` (the diagonal of `L` will not be stored explicitly). If `A` is an arbitrary matrix of rank `r`, `U` will be in row echelon form having `r` nonzero rows, and `L` will be lower triangular but truncated to `r` columns, having implicit ones on the `r` first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and return 0 if `A` is detected to be rank-deficient. This function calls ``fq_default_mat_lu_recursive``. Reduced row echelon form -------------------------------------------------------------------------------- .. function:: slong fq_default_mat_rref(fq_default_mat_t B, const fq_default_mat_t A, const fq_default_ctx_t ctx) Puts `B` in reduced row echelon form and returns the rank of `A`. The rref is computed by first obtaining an unreduced row echelon form via LU decomposition and then solving an additional triangular system. Triangular solving -------------------------------------------------------------------------------- .. function:: void fq_default_mat_solve_tril(fq_default_mat_t X, const fq_default_mat_t L, const fq_default_mat_t B, int unit, const fq_default_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void fq_default_mat_solve_triu(fq_default_mat_t X, const fq_default_mat_t U, const fq_default_mat_t B, int unit, const fq_default_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. Solving -------------------------------------------------------------------------------- .. function:: int fq_default_mat_solve(fq_default_mat_t X, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) Solves the matrix-matrix equation `AX = B`. Returns `1` if `A` has full rank; otherwise returns `0` and sets the elements of `X` to undefined values. The matrix `A` must be square. .. function:: int fq_default_mat_can_solve(fq_default_mat_t X, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) Solves the matrix-matrix equation `AX = B` over `Fq`. Returns `1` if a solution exists; otherwise returns `0` and sets the elements of `X` to zero. If more than one solution exists, one of the valid solutions is given. There are no restrictions on the shape of `A` and it may be singular. Transforms -------------------------------------------------------------------------------- .. function:: void fq_default_mat_similarity(fq_default_mat_t M, slong r, fq_default_t d, const fq_default_ctx_t ctx) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. The value `d` is required to be reduced modulo the modulus of the entries in the matrix. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void fq_default_mat_charpoly(fq_default_poly_t p, const fq_default_mat_t M, const fq_default_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. Minimal polynomial -------------------------------------------------------------------------------- .. function:: void fq_default_mat_minpoly(fq_default_poly_t p, const fq_default_mat_t M, const fq_default_ctx_t ctx) Compute the minimal polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. flint-3.1.3/doc/source/fq_default_poly.rst000066400000000000000000000556671461254215100206320ustar00rootroot00000000000000.. _fq_default_poly: **fq_default_poly.h** -- univariate polynomials over finite fields =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_poly_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_default_poly_init(fq_default_poly_t poly, const fq_default_ctx_t ctx) Initialises ``poly`` for use, with context ctx, and setting its length to zero. A corresponding call to :func:`fq_default_poly_clear` must be made after finishing with the ``fq_default_poly_t`` to free the memory used by the polynomial. .. function:: void fq_default_poly_init2(fq_default_poly_t poly, slong alloc, const fq_default_ctx_t ctx) Initialises ``poly`` with space for at least ``alloc`` coefficients and sets the length to zero. The allocated coefficients are all set to zero. A corresponding call to :func:`fq_default_poly_clear` must be made after finishing with the ``fq_default_poly_t`` to free the memory used by the polynomial. .. function:: void fq_default_poly_realloc(fq_default_poly_t poly, slong alloc, const fq_default_ctx_t ctx) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` the polynomial is first truncated to length ``alloc``. .. function:: void fq_default_poly_fit_length(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where ``fit_length`` is called many times in small increments by at least doubling the number of allocated coefficients when length is larger than the number of coefficients currently allocated. .. function:: void fq_default_poly_clear(fq_default_poly_t poly, const fq_default_ctx_t ctx) Clears the given polynomial, releasing any memory used. It must be reinitialised in order to be used again. .. function:: void _fq_default_poly_set_length(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) Set the length of ``poly`` to ``len``. .. function:: void fq_default_poly_truncate(fq_default_poly_t poly, slong newlen, const fq_default_ctx_t ctx) Truncates the polynomial to length at most `n`. .. function:: void fq_default_poly_set_trunc(fq_default_poly_t poly1, fq_default_poly_t poly2, slong newlen, const fq_default_ctx_t ctx) Sets ``poly1`` to ``poly2`` truncated to length `n`. .. function:: void fq_default_poly_reverse(fq_default_poly_t output, const fq_default_poly_t input, slong m, const fq_default_ctx_t ctx) Sets ``output`` to the reverse of ``input``, thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary). The length ``m`` must be non-negative, but there are no other restrictions. The output polynomial will be set to length ``m`` and then normalised. Polynomial parameters -------------------------------------------------------------------------------- .. function:: slong fq_default_poly_degree(const fq_default_poly_t poly, const fq_default_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: slong fq_default_poly_length(const fq_default_poly_t poly, const fq_default_ctx_t ctx) Returns the length of the polynomial ``poly``. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_default_poly_randtest(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) Sets `f` to a random polynomial of length at most ``len`` with entries in the field described by ``ctx``. .. function:: void fq_default_poly_randtest_not_zero(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) Same as ``fq_default_poly_randtest`` but guarantees that the polynomial is not zero. .. function:: void fq_default_poly_randtest_monic(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) Sets `f` to a random monic polynomial of length ``len`` with entries in the field described by ``ctx``. .. function:: void fq_default_poly_randtest_irreducible(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) Sets `f` to a random monic, irreducible polynomial of length ``len`` with entries in the field described by ``ctx``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void fq_default_poly_set(fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_ctx_t ctx) Sets the polynomial ``poly1`` to the polynomial ``poly2``. .. function:: void fq_default_poly_set_fq_default(fq_default_poly_t poly, const fq_default_t c, const fq_default_ctx_t ctx) Sets the polynomial ``poly`` to ``c``. .. function:: void fq_default_poly_swap(fq_default_poly_t op1, fq_default_poly_t op2, const fq_default_ctx_t ctx) Swaps the two polynomials ``op1`` and ``op2``. .. function:: void fq_default_poly_zero(fq_default_poly_t poly, const fq_default_ctx_t ctx) Sets ``poly`` to the zero polynomial. .. function:: void fq_default_poly_one(fq_default_poly_t poly, const fq_default_ctx_t ctx) Sets ``poly`` to the constant polynomial `1`. .. function:: void fq_default_poly_gen(fq_default_poly_t poly, const fq_default_ctx_t ctx) Sets ``poly`` to the polynomial `x`. .. function:: void fq_default_poly_make_monic(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) Sets ``rop`` to ``op``, normed to have leading coefficient 1. .. function:: void fq_default_poly_set_nmod_poly(fq_default_poly_t rop, const nmod_poly_t op, const fq_default_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op``. .. function:: void fq_default_poly_set_fmpz_mod_poly(fq_default_poly_t rop, const fmpz_mod_poly_t op, const fq_default_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op``. .. function:: void fq_default_poly_set_fmpz_poly(fq_default_poly_t rop, const fmpz_poly_t op, const fq_default_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op``. Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void fq_default_poly_get_coeff(fq_default_t x, const fq_default_poly_t poly, slong n, const fq_default_ctx_t ctx) Sets `x` to the coefficient of `X^n` in ``poly``. .. function:: void fq_default_poly_set_coeff(fq_default_poly_t poly, slong n, const fq_default_t x, const fq_default_ctx_t ctx) Sets the coefficient of `X^n` in ``poly`` to `x`. .. function:: void fq_default_poly_set_coeff_fmpz(fq_default_poly_t poly, slong n, const fmpz_t x, const fq_default_ctx_t ctx) Sets the coefficient of `X^n` in the polynomial to `x`, assuming `n \geq 0`. Comparison -------------------------------------------------------------------------------- .. function:: int fq_default_poly_equal(const fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_ctx_t ctx) Returns nonzero if the two polynomials ``poly1`` and ``poly2`` are equal, otherwise returns zero. .. function:: int fq_default_poly_equal_trunc(const fq_default_poly_t poly1, const fq_default_poly_t poly2, slong n, const fq_default_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length `n` and return nonzero if they are equal, otherwise return zero. .. function:: int fq_default_poly_is_zero(const fq_default_poly_t poly, const fq_default_ctx_t ctx) Returns whether the polynomial ``poly`` is the zero polynomial. .. function:: int fq_default_poly_is_one(const fq_default_poly_t op, const fq_default_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the constant polynomial `1`. .. function:: int fq_default_poly_is_gen(const fq_default_poly_t op, const fq_default_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the polynomial `x`. .. function:: int fq_default_poly_is_unit(const fq_default_poly_t op, const fq_default_ctx_t ctx) Returns whether the polynomial ``poly`` is a unit in the polynomial ring `\mathbf{F}_q[X]`, i.e. if it has degree `0` and is non-zero. .. function:: int fq_default_poly_equal_fq_default(const fq_default_poly_t poly, const fq_default_t c, const fq_default_ctx_t ctx) Returns whether the polynomial ``poly`` is equal the (constant) `\mathbf{F}_q` element ``c`` Addition and subtraction -------------------------------------------------------------------------------- .. function:: void fq_default_poly_add(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``poly2``. .. function:: void fq_default_poly_add_si(fq_default_poly_t res, const fq_default_poly_t poly1, slong c, const fq_default_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``c``. .. function:: void fq_default_poly_add_series(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, slong n, const fq_default_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the sum. .. function:: void fq_default_poly_sub(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_ctx_t ctx) Sets ``res`` to the difference of ``poly1`` and ``poly2``. .. function:: void fq_default_poly_sub_series(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, slong n, const fq_default_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the difference. .. function:: void fq_default_poly_neg(fq_default_poly_t res, const fq_default_poly_t poly, const fq_default_ctx_t ctx) Sets ``res`` to the additive inverse of ``poly``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void fq_default_poly_scalar_mul_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) Sets ``rop`` to the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void fq_default_poly_scalar_addmul_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) Adds to ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void fq_default_poly_scalar_submul_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) Subtracts from ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void fq_default_poly_scalar_div_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) Sets ``rop`` to the quotient of ``op`` by the scalar ``x``, in the context defined by ``ctx``. An exception is raised if ``x`` is zero. Multiplication -------------------------------------------------------------------------------- .. function:: void fq_default_poly_mul(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, choosing an appropriate algorithm. .. function:: void fq_default_poly_mullow(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, slong n, const fq_default_ctx_t ctx) Sets ``rop`` to the lowest `n` coefficients of the product of ``op1`` and ``op2``. .. function:: void fq_default_poly_mulhigh(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, slong start, const fq_default_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. .. function:: void fq_default_poly_mulmod(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_poly_t f, const fq_default_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. Squaring -------------------------------------------------------------------------------- .. function:: void fq_default_poly_sqr(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) Sets ``rop`` to the square of ``op``, choosing an appropriate algorithm. Powering -------------------------------------------------------------------------------- .. function:: void fq_default_poly_pow(fq_default_poly_t rop, const fq_default_poly_t op, ulong e, const fq_default_ctx_t ctx) Computes ``rop = op^e``. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void fq_default_poly_powmod_ui_binexp(fq_default_poly_t res, const fq_default_poly_t poly, ulong e, const fq_default_poly_t f, const fq_default_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void fq_default_poly_powmod_fmpz_binexp(fq_default_poly_t res, const fq_default_poly_t poly, const fmpz_t e, const fq_default_poly_t f, const fq_default_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void fq_default_poly_pow_trunc(fq_default_poly_t res, const fq_default_poly_t poly, ulong e, slong trunc, const fq_default_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Shifting -------------------------------------------------------------------------------- .. function:: void fq_default_poly_shift_left(fq_default_poly_t rop, const fq_default_poly_t op, slong n, const fq_default_ctx_t ctx) Sets ``rop`` to ``op`` shifted left by `n` coeffs. Zero coefficients are inserted. .. function:: void fq_default_poly_shift_right(fq_default_poly_t rop, const fq_default_poly_t op, slong n, const fq_default_ctx_t ctx) Sets ``rop`` to ``op`` shifted right by `n` coefficients. If `n` is equal to or greater than the current length of ``op``, ``rop`` is set to the zero polynomial. Norms -------------------------------------------------------------------------------- .. function:: slong fq_default_poly_hamming_weight(const fq_default_poly_t op, const fq_default_ctx_t ctx) Returns the number of non-zero entries in the polynomial ``op``. Euclidean division -------------------------------------------------------------------------------- .. function:: void fq_default_poly_divrem(fq_default_poly_t Q, fq_default_poly_t R, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) Computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible. This can be taken for granted the context is for a finite field, that is, when `p` is prime and `f(X)` is irreducible. .. function:: void fq_default_poly_rem(fq_default_poly_t R, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) Sets ``R`` to the remainder of the division of ``A`` by ``B`` in the context described by ``ctx``. .. function:: void fq_default_poly_inv_series(fq_default_poly_t Qinv, const fq_default_poly_t Q, slong n, const fq_default_ctx_t ctx) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. .. function:: void fq_default_poly_div_series(fq_default_poly_t Q, const fq_default_poly_t A, const fq_default_poly_t B, slong n, const fq_default_ctx_t ctx) Set `Q` to the quotient of the series `A` by `B`, thinking of the series as though they were of length `n`. We assume that the bottom coefficient of `B` is invertible. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void fq_default_poly_gcd(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) Sets ``rop`` to the greatest common divisor of ``op1`` and ``op2``, using the either the Euclidean or HGCD algorithm. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. .. function:: void fq_default_poly_xgcd(fq_default_poly_t G, fq_default_poly_t S, fq_default_poly_t T, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. Divisibility testing -------------------------------------------------------------------------------- .. function:: int fq_default_poly_divides(fq_default_poly_t Q, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) Returns `1` if `B` divides `A` exactly and sets `Q` to the quotient, otherwise returns `0`. This function is currently unoptimised and provided for convenience only. Derivative -------------------------------------------------------------------------------- .. function:: void fq_default_poly_derivative(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) Sets ``rop`` to the derivative of ``op``. Square root -------------------------------------------------------------------------------- .. function:: void fq_default_poly_invsqrt_series(fq_default_poly_t g, const fq_default_poly_t h, slong n, fq_default_ctx_t ctx) Set `g` to the series expansion of `1/\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: void fq_default_poly_sqrt_series(fq_default_poly_t g, const fq_default_poly_t h, slong n, fq_default_ctx_t ctx) Set `g` to the series expansion of `\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: int fq_default_poly_sqrt(fq_default_poly_t s, const fq_default_poly_t p, fq_default_ctx_t mod) If `p` is a perfect square, sets `s` to a square root of `p` and returns 1. Otherwise returns 0. Evaluation -------------------------------------------------------------------------------- .. function:: void fq_default_poly_evaluate_fq_default(fq_default_t rop, const fq_default_poly_t f, const fq_default_t a, const fq_default_ctx_t ctx) Sets ``rop`` to the value of `f(a)`. As the coefficient ring `\mathbf{F}_q` is finite, Horner's method is sufficient. Composition -------------------------------------------------------------------------------- .. function:: void fq_default_poly_compose(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) Sets ``rop`` to the composition of ``op1`` and ``op2``. To be precise about the order of composition, denoting ``rop``, ``op1``, and ``op2`` by `f`, `g`, and `h`, respectively, sets `f(t) = g(h(t))`. .. function:: void fq_default_poly_compose_mod(fq_default_poly_t res, const fq_default_poly_t f, const fq_default_poly_t g, const fq_default_poly_t h, const fq_default_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. Output -------------------------------------------------------------------------------- .. function:: int fq_default_poly_fprint_pretty(FILE * file, const fq_default_poly_t poly, const char * x, const fq_default_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_default_poly_print_pretty(const fq_default_poly_t poly, const char * x, const fq_default_ctx_t ctx) Prints the pretty representation of ``poly`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_default_poly_fprint(FILE * file, const fq_default_poly_t poly, const fq_default_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_default_poly_print(const fq_default_poly_t poly, const fq_default_ctx_t ctx) Prints the representation of ``poly`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: char * fq_default_poly_get_str(const fq_default_poly_t poly, const fq_default_ctx_t ctx) Returns the plain FLINT string representation of the polynomial ``poly``. .. function:: char * fq_default_poly_get_str_pretty(const fq_default_poly_t poly, const char * x, const fq_default_ctx_t ctx) Returns a pretty representation of the polynomial ``poly`` using the null-terminated string ``x`` as the variable name Inflation and deflation -------------------------------------------------------------------------------- .. function:: void fq_default_poly_inflate(fq_default_poly_t result, const fq_default_poly_t input, ulong inflation, const fq_default_ctx_t ctx) Sets ``result`` to the inflated polynomial `p(x^n)` where `p` is given by ``input`` and `n` is given by ``inflation``. .. function:: void fq_default_poly_deflate(fq_default_poly_t result, const fq_default_poly_t input, ulong deflation, const fq_default_ctx_t ctx) Sets ``result`` to the deflated polynomial `p(x^{1/n})` where `p` is given by ``input`` and `n` is given by ``deflation``. Requires `n > 0`. .. function:: ulong fq_default_poly_deflation(const fq_default_poly_t input, const fq_default_ctx_t ctx) Returns the largest integer by which ``input`` can be deflated. As special cases, returns 0 if ``input`` is the zero polynomial and 1 of ``input`` is a constant polynomial. flint-3.1.3/doc/source/fq_default_poly_factor.rst000066400000000000000000000154751461254215100221610ustar00rootroot00000000000000.. _fq-poly_factor: **fq_default_poly_factor.h** -- factorisation of univariate polynomials over finite fields ========================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_poly_factor_t Memory Management -------------------------------------------------------------------------------- .. function:: void fq_default_poly_factor_init(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) Initialises ``fac`` for use. An :type:`fq_default_poly_factor_t` represents a polynomial in factorised form as a product of polynomials with associated exponents. .. function:: void fq_default_poly_factor_clear(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) Frees all memory associated with ``fac``. .. function:: void fq_default_poly_factor_realloc(fq_default_poly_factor_t fac, slong alloc, const fq_default_ctx_t ctx) Reallocates the factor structure to provide space for precisely ``alloc`` factors. .. function:: void fq_default_poly_factor_fit_length(fq_default_poly_factor_t fac, slong len, const fq_default_ctx_t ctx) Ensures that the factor structure has space for at least ``len`` factors. This function takes care of the case of repeated calls by always at least doubling the number of factors the structure can hold. Basic Operations -------------------------------------------------------------------------------- .. function:: void fq_default_poly_factor_set(fq_default_poly_factor_t res, const fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) Sets ``res`` to the same factorisation as ``fac``. .. function:: void fq_default_poly_factor_print_pretty(const fq_default_poly_factor_t fac, const char * var, const fq_default_ctx_t ctx) Pretty-prints the entries of ``fac`` to standard output. .. function:: void fq_default_poly_factor_print(const fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) Prints the entries of ``fac`` to standard output. .. function:: void fq_default_poly_factor_insert(fq_default_poly_factor_t fac, const fq_default_poly_t poly, slong exp, const fq_default_ctx_t ctx) Inserts the factor ``poly`` with multiplicity ``exp`` into the factorisation ``fac``. If ``fac`` already contains ``poly``, then ``exp`` simply gets added to the exponent of the existing entry. .. function:: void fq_default_poly_factor_concat(fq_default_poly_factor_t res, const fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) Concatenates two factorisations. This is equivalent to calling :func:`fq_default_poly_factor_insert` repeatedly with the individual factors of ``fac``. Does not support aliasing between ``res`` and ``fac``. .. function:: void fq_default_poly_factor_pow(fq_default_poly_factor_t fac, slong exp, const fq_default_ctx_t ctx) Raises ``fac`` to the power ``exp``. .. function:: ulong fq_default_poly_remove(fq_default_poly_t f, const fq_default_poly_t p, const fq_default_ctx_t ctx) Removes the highest possible power of ``p`` from ``f`` and returns the exponent. .. function:: slong fq_default_poly_factor_length(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) Return the number of factors, not including the unit. .. function:: void fq_default_poly_factor_get_poly(fq_default_poly_t poly, const fq_default_poly_factor_t fac, slong i, const fq_default_ctx_t ctx) Set ``poly`` to factor ``i`` of ``fac`` (numbering starts at zero). .. function:: slong fq_default_poly_factor_exp(fq_default_poly_factor_t fac, slong i, const fq_default_ctx_t ctx) Return the exponent of factor ``i`` of ``fac``. Irreducibility Testing -------------------------------------------------------------------------------- .. function:: int fq_default_poly_is_irreducible(const fq_default_poly_t f, const fq_default_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. .. function:: int fq_default_poly_is_squarefree(const fq_default_poly_t f, const fq_default_ctx_t ctx) Returns 1 if ``f`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. Factorisation -------------------------------------------------------------------------------- .. function:: void fq_default_poly_factor_equal_deg(fq_default_poly_factor_t factors, const fq_default_poly_t pol, slong d, const fq_default_ctx_t ctx) Assuming ``pol`` is a product of irreducible factors all of degree ``d``, finds all those factors and places them in factors. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fq_default_poly_factor_split_single(fq_default_poly_t linfactor, const fq_default_poly_t input, const fq_default_ctx_t ctx) Assuming ``input`` is a product of factors all of degree 1, finds a single linear factor of ``input`` and places it in ``linfactor``. Requires that ``input`` be monic and non-constant. .. function:: void fq_default_poly_factor_distinct_deg(fq_default_poly_factor_t res, const fq_default_poly_t poly, slong * const * degs, const fq_default_ctx_t ctx) Factorises a monic non-constant squarefree polynomial ``poly`` of degree `n` into factors `f[d]` such that for `1 \leq d \leq n` `f[d]` is the product of the monic irreducible factors of ``poly`` of degree `d`. Factors are stored in ``res``, associated powers of irreducible polynomials are stored in ``degs`` in the same order as factors. Requires that ``degs`` have enough space for irreducible polynomials' powers (maximum space required is ``n * sizeof(slong)``). .. function:: void fq_default_poly_factor_squarefree(fq_default_poly_factor_t res, const fq_default_poly_t f, const fq_default_ctx_t ctx) Sets ``res`` to a squarefree factorization of ``f``. .. function:: void fq_default_poly_factor(fq_default_poly_factor_t res, fq_default_t lead, const fq_default_poly_t f, const fq_default_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors choosing the best algorithm for given modulo and degree. The output ``lead`` is set to the leading coefficient of `f` upon return. Choice of algorithm is based on heuristic measurements. Root Finding -------------------------------------------------------------------------------- .. function:: void fq_default_poly_roots(fq_default_poly_factor_t r, const fq_default_poly_t f, int with_multiplicity, const fq_default_ctx_t ctx) Fill `r` with factors of the form `x - r_i` where the `r_i` are the distinct roots of a nonzero `f` in `F_q`. If `with\_multiplicity` is zero, the exponent `e_i` of the factor `x - r_i` is `1`. Otherwise, it is the largest `e_i` such that `(x-r_i)^e_i` divides `f`. This function throws if `f` is zero, but is otherwise always successful. flint-3.1.3/doc/source/fq_embed.rst000066400000000000000000000106221461254215100171750ustar00rootroot00000000000000.. _fq-embed: **fq_embed.h** -- Computing isomorphisms and embeddings of finite fields -------------------------------------------------------------------------------- .. function:: void fq_embed_gens(fq_t gen_sub, fq_t gen_sup, fmpz_mod_poly_t minpoly, const fq_ctx_t sub_ctx, const fq_ctx_t sup_ctx) Given two contexts ``sub_ctx`` and ``sup_ctx``, such that ``degree(sub_ctx)`` divides ``degree(sup_ctx)``, compute: * an element ``gen_sub`` in ``sub_ctx`` such that ``gen_sub`` generates the finite field defined by ``sub_ctx``, * its minimal polynomial ``minpoly``, * a root ``gen_sup`` of ``minpoly`` inside the field defined by ``sup_ctx``. These data uniquely define an embedding of ``sub_ctx`` into ``sup_ctx``. .. function:: void _fq_embed_gens_naive(fq_t gen_sub, fq_t gen_sup, fmpz_mod_poly_t minpoly, const fq_ctx_t sub_ctx, const fq_ctx_t sup_ctx) Given two contexts ``sub_ctx`` and ``sup_ctx``, such that ``degree(sub_ctx)`` divides ``degree(sup_ctx)``, compute an embedding of ``sub_ctx`` into ``sup_ctx`` defined as follows: * ``gen_sub`` is the canonical generator of ``sup_ctx`` (i.e., the class of `X`), * ``minpoly`` is the defining polynomial of ``sub_ctx``, * ``gen_sup`` is a root of ``minpoly`` inside the field defined by ``sup_ctx``. .. function:: void fq_embed_matrices(fmpz_mod_mat_t embed, fmpz_mod_mat_t project, const fq_t gen_sub, const fq_ctx_t sub_ctx, const fq_t gen_sup, const fq_ctx_t sup_ctx, const fmpz_mod_poly_t gen_minpoly) Given: * two contexts ``sub_ctx`` and ``sup_ctx``, of respective degrees `m` and `n`, such that `m` divides `n`; * a generator ``gen_sub`` of ``sub_ctx``, its minimal polynomial ``gen_minpoly``, and a root ``gen_sup`` of ``gen_minpoly`` in ``sup_ctx``, as returned by :func:`fq_embed_gens`; Compute: * the `n\times m` matrix ``embed`` mapping ``gen_sub`` to ``gen_sup``, and all their powers accordingly; * an `m\times n` matrix ``project`` such that ``project`` `\times` ``embed`` is the `m\times m` identity matrix. .. function:: void fq_embed_trace_matrix(fmpz_mod_mat_t res, const fmpz_mod_mat_t basis, const fq_ctx_t sub_ctx, const fq_ctx_t sup_ctx) Given: * two contexts ``sub_ctx`` and ``sup_ctx``, of degrees `m` and `n`, such that `m` divides `n`; * an `n\times m` matrix ``basis`` that maps ``sub_ctx`` to an isomorphic subfield in ``sup_ctx``; Compute the `m\times n` matrix of the trace from ``sup_ctx`` to ``sub_ctx``. This matrix is computed as ``embed_dual_to_mono_matrix(_, sub_ctx)`` `\times` ``basis``:sup:`t` `\times` ``embed_mono_to_dual_matrix(_, sup_ctx)``. **Note:** if `m=n`, ``basis`` represents a Frobenius, and the result is its inverse matrix. .. function:: void fq_embed_composition_matrix(fmpz_mod_mat_t matrix, const fq_t gen, const fq_ctx_t ctx) Compute the *composition matrix* of ``gen``. For an element `a\in\mathbf{F}_{p^n}`, its composition matrix is the matrix whose columns are `a^0, a^1, \ldots, a^{n-1}`. .. function:: void fq_embed_composition_matrix_sub(fmpz_mod_mat_t matrix, const fq_t gen, const fq_ctx_t ctx, slong trunc) Compute the *composition matrix* of ``gen``, truncated to ``trunc`` columns. .. function:: void fq_embed_mul_matrix(fmpz_mod_mat_t matrix, const fq_t gen, const fq_ctx_t ctx) Compute the *multiplication matrix* of ``gen``. For an element `a` in `\mathbf{F}_{p^n}=\mathbf{F}_p[x]`, its multiplication matrix is the matrix whose columns are `a, ax, \dots, ax^{n-1}`. .. function:: void fq_embed_mono_to_dual_matrix(fmpz_mod_mat_t res, const fq_ctx_t ctx) Compute the change of basis matrix from the monomial basis of ``ctx`` to its dual basis. .. function:: void fq_embed_dual_to_mono_matrix(fmpz_mod_mat_t res, const fq_ctx_t ctx) Compute the change of basis matrix from the dual basis of ``ctx`` to its monomial basis. .. function:: void fq_modulus_pow_series_inv(fmpz_mod_poly_t res, const fq_ctx_t ctx, slong trunc) Compute the power series inverse of the reverse of the modulus of ``ctx`` up to `O(x^\texttt{trunc})`. .. function:: void fq_modulus_derivative_inv(fq_t m_prime, fq_t m_prime_inv, const fq_ctx_t ctx) Compute the derivative ``m_prime`` of the modulus of ``ctx`` as an element of ``ctx``, and its inverse ``m_prime_inv``. flint-3.1.3/doc/source/fq_mat.rst000066400000000000000000000526131461254215100167100ustar00rootroot00000000000000.. _fq-mat: **fq_mat.h** -- matrices over finite fields =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_mat_struct .. type:: fq_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_mat_init(fq_mat_t mat, slong rows, slong cols, const fq_ctx_t ctx) Initialises ``mat`` to a ``rows``-by-``cols`` matrix with coefficients in `\mathbf{F}_{q}` given by ``ctx``. All elements are set to zero. .. function:: void fq_mat_init_set(fq_mat_t mat, const fq_mat_t src, const fq_ctx_t ctx) Initialises ``mat`` and sets its dimensions and elements to those of ``src``. .. function:: void fq_mat_clear(fq_mat_t mat, const fq_ctx_t ctx) Clears the matrix and releases any memory it used. The matrix cannot be used again until it is initialised. This function must be called exactly once when finished using an ``fq_mat_t`` object. .. function:: void fq_mat_set(fq_mat_t mat, const fq_mat_t src, const fq_ctx_t ctx) Sets ``mat`` to a copy of ``src``. It is assumed that ``mat`` and ``src`` have identical dimensions. Basic properties and manipulation -------------------------------------------------------------------------------- .. function:: fq_struct * fq_mat_entry(const fq_mat_t mat, slong i, slong j) Directly accesses the entry in ``mat`` in row `i` and column `j`, indexed from zero. No bounds checking is performed. .. function:: void fq_mat_entry_set(fq_mat_t mat, slong i, slong j, const fq_t x, const fq_ctx_t ctx) Sets the entry in ``mat`` in row `i` and column `j` to ``x``. .. function:: slong fq_mat_nrows(const fq_mat_t mat, const fq_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_mat_ncols(const fq_mat_t mat, const fq_ctx_t ctx) Returns the number of columns in ``mat``. .. function:: void fq_mat_swap(fq_mat_t mat1, fq_mat_t mat2, const fq_ctx_t ctx) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. function:: void fq_mat_swap_entrywise(fq_mat_t mat1, fq_mat_t mat2, const fq_ctx_t ctx) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: void fq_mat_zero(fq_mat_t mat, const fq_ctx_t ctx) Sets all entries of ``mat`` to 0. .. function:: void fq_mat_one(fq_mat_t mat, const fq_ctx_t ctx) Sets all the diagonal entries of ``mat`` to 1 and all other entries to 0. .. function:: void fq_mat_swap_rows(fq_mat_t mat, slong * perm, slong r, slong s, const fq_ctx_t ctx) Swaps rows ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fq_mat_swap_cols(fq_mat_t mat, slong * perm, slong r, slong s, const fq_ctx_t ctx) Swaps columns ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: void fq_mat_invert_rows(fq_mat_t mat, slong * perm, const fq_ctx_t ctx) Swaps rows ``i`` and ``r - i`` of ``mat`` for ``0 <= i < r/2``, where ``r`` is the number of rows of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fq_mat_invert_cols(fq_mat_t mat, slong * perm, const fq_ctx_t ctx) Swaps columns ``i`` and ``c - i`` of ``mat`` for ``0 <= i < c/2``, where ``c`` is the number of columns of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. Conversions -------------------------------------------------------------------------------- .. function:: void fq_mat_set_nmod_mat(fq_mat_t mat1, const nmod_mat_t mat2, const fq_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. .. function:: void fq_mat_set_fmpz_mod_mat(fq_mat_t mat1, const fmpz_mod_mat_t mat2, const fq_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. Concatenate -------------------------------------------------------------------------------- .. function:: void fq_mat_concat_vertical(fq_mat_t res, const fq_mat_t mat1, const fq_mat_t mat2, const fq_ctx_t ctx) Sets ``res`` to vertical concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `k \times n`, ``res`` : `(m + k) \times n`. .. function:: void fq_mat_concat_horizontal(fq_mat_t res, const fq_mat_t mat1, const fq_mat_t mat2, const fq_ctx_t ctx) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `m \times k`, ``res`` : `m \times (n + k)`. Printing -------------------------------------------------------------------------------- .. function:: int fq_mat_print_pretty(const fq_mat_t mat, const fq_ctx_t ctx) Pretty-prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_mat_fprint_pretty(FILE * file, const fq_mat_t mat, const fq_ctx_t ctx) Pretty-prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_mat_print(const fq_mat_t mat, const fq_ctx_t ctx) Prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_mat_fprint(FILE * file, const fq_mat_t mat, const fq_ctx_t ctx) Prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. Window -------------------------------------------------------------------------------- .. function:: void fq_mat_window_init(fq_mat_t window, const fq_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fq_ctx_t ctx) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0,0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void fq_mat_window_clear(fq_mat_t window, const fq_ctx_t ctx) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. Random matrix generation -------------------------------------------------------------------------------- .. function:: void fq_mat_randtest(fq_mat_t mat, flint_rand_t state, const fq_ctx_t ctx) Sets the elements of ``mat`` to random elements of `\mathbf{F}_{q}`, given by ``ctx``. .. function:: int fq_mat_randpermdiag(fq_mat_t mat, flint_rand_t state, fq_struct * diag, slong n, const fq_ctx_t ctx) Sets ``mat`` to a random permutation of the diagonal matrix with `n` leading entries given by the vector ``diag``. It is assumed that the main diagonal of ``mat`` has room for at least `n` entries. Returns `0` or `1`, depending on whether the permutation is even or odd respectively. .. function:: void fq_mat_randrank(fq_mat_t mat, flint_rand_t state, slong rank, const fq_ctx_t ctx) Sets ``mat`` to a random sparse matrix with the given rank, having exactly as many non-zero elements as the rank, with the non-zero elements being uniformly random elements of `\mathbf{F}_{q}`. The matrix can be transformed into a dense matrix with unchanged rank by subsequently calling :func:`fq_mat_randops`. .. function:: void fq_mat_randops(fq_mat_t mat, flint_rand_t state, slong count, const fq_ctx_t ctx) Randomises ``mat`` by performing elementary row or column operations. More precisely, at most ``count`` random additions or subtractions of distinct rows and columns will be performed. This leaves the rank (and for square matrices, determinant) unchanged. .. function:: void fq_mat_randtril(fq_mat_t mat, flint_rand_t state, int unit, const fq_ctx_t ctx) Sets ``mat`` to a random lower triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. .. function:: void fq_mat_randtriu(fq_mat_t mat, flint_rand_t state, int unit, const fq_ctx_t ctx) Sets ``mat`` to a random upper triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. Comparison -------------------------------------------------------------------------------- .. function:: int fq_mat_equal(const fq_mat_t mat1, const fq_mat_t mat2, const fq_ctx_t ctx) Returns nonzero if mat1 and mat2 have the same dimensions and elements, and zero otherwise. .. function:: int fq_mat_is_zero(const fq_mat_t mat, const fq_ctx_t ctx) Returns a non-zero value if all entries of ``mat`` are zero, and otherwise returns zero. .. function:: int fq_mat_is_one(const fq_mat_t mat, const fq_ctx_t ctx) Returns a non-zero value if all entries ``mat`` are zero except the diagonal entries which must be one, otherwise returns zero.. .. function:: int fq_mat_is_empty(const fq_mat_t mat, const fq_ctx_t ctx) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int fq_mat_is_square(const fq_mat_t mat, const fq_ctx_t ctx) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void fq_mat_add(fq_mat_t C, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Computes `C = A + B`. Dimensions must be identical. .. function:: void fq_mat_sub(fq_mat_t C, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Computes `C = A - B`. Dimensions must be identical. .. function:: void fq_mat_neg(fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Sets `B = -A`. Dimensions must be identical. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void fq_mat_mul(fq_mat_t C, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. Aliasing is allowed. This function automatically chooses between classical and KS multiplication. .. function:: void fq_mat_mul_classical(fq_mat_t C, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses classical matrix multiplication. .. function:: void fq_mat_mul_KS(fq_mat_t C, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses Kronecker substitution to perform the multiplication over the integers. .. function:: void fq_mat_submul(fq_mat_t D, const fq_mat_t C, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Sets `D = C + AB`. `C` and `D` may be aliased with each other but not with `A` or `B`. .. function:: void fq_mat_mul_vec(fq_struct * c, const fq_mat_t A, const fq_struct * b, slong blen, const fq_ctx_t ctx) void fq_mat_mul_vec_ptr(fq_struct * const * c, const fq_mat_t A, const fq_struct * const * b, slong blen, const fq_ctx_t ctx) Compute a matrix-vector product of ``A`` and ``(b, blen)`` and store the result in ``c``. The vector ``(b, blen)`` is either truncated or zero-extended to the number of columns of ``A``. The number entries written to ``c`` is always equal to the number of rows of ``A``. .. function:: void fq_mat_vec_mul(fq_struct * c, const fq_struct * a, slong alen, const fq_mat_t B, const fq_ctx_t ctx) void fq_mat_vec_mul_ptr(fq_struct * const * c, const fq_struct * const * a, slong alen, const fq_mat_t B, const fq_ctx_t ctx) Compute a vector-matrix product of ``(a, alen)`` and ``B`` and and store the result in ``c``. The vector ``(a, alen)`` is either truncated or zero-extended to the number of rows of ``B``. The number entries written to ``c`` is always equal to the number of columns of ``B``. Inverse -------------------------------------------------------------------------------- .. function:: int fq_mat_inv(fq_mat_t B, fq_mat_t A, const fq_ctx_t ctx) Sets `B = A^{-1}` and returns `1` if `A` is invertible. If `A` is singular, returns `0` and sets the elements of `B` to undefined values. `A` and `B` must be square matrices with the same dimensions. LU decomposition -------------------------------------------------------------------------------- .. function:: slong fq_mat_lu(slong * P, fq_mat_t A, int rank_check, const fq_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. If `A` is a nonsingular square matrix, it will be overwritten with a unit diagonal lower triangular matrix `L` and an upper triangular matrix `U` (the diagonal of `L` will not be stored explicitly). If `A` is an arbitrary matrix of rank `r`, `U` will be in row echelon form having `r` nonzero rows, and `L` will be lower triangular but truncated to `r` columns, having implicit ones on the `r` first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and return 0 if `A` is detected to be rank-deficient. This function calls ``fq_mat_lu_recursive``. .. function:: slong fq_mat_lu_classical(slong * P, fq_mat_t A, int rank_check, const fq_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. The behavior of this function is identical to that of ``fq_mat_lu``. Uses Gaussian elimination. .. function:: slong fq_mat_lu_recursive(slong * P, fq_mat_t A, int rank_check, const fq_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. The behavior of this function is identical to that of ``fq_mat_lu``. Uses recursive block decomposition, switching to classical Gaussian elimination for sufficiently small blocks. Reduced row echelon form -------------------------------------------------------------------------------- .. function:: slong fq_mat_rref(fq_mat_t B, const fq_mat_t A, const fq_ctx_t ctx) Puts `B` in reduced row echelon form and returns the rank of `A`. The rref is computed by first obtaining an unreduced row echelon form via LU decomposition and then solving an additional triangular system. .. function:: slong fq_mat_reduce_row(fq_mat_t A, slong * P, slong * L, slong n, const fq_ctx_t ctx) Reduce row n of the matrix `A`, assuming the prior rows are in Gauss form. However those rows may not be in order. The entry `i` of the array `P` is the row of `A` which has a pivot in the `i`-th column. If no such row exists, the entry of `P` will be `-1`. The function returns the column in which the `n`-th row has a pivot after reduction. This will always be chosen to be the first available column for a pivot from the left. This information is also updated in `P`. Entry `i` of the array `L` contains the number of possibly nonzero columns of `A` row `i`. This speeds up reduction in the case that `A` is chambered on the right. Otherwise the entries of `L` can all be set to the number of columns of `A`. We require the entries of `L` to be monotonic increasing. Triangular solving -------------------------------------------------------------------------------- .. function:: void fq_mat_solve_tril(fq_mat_t X, const fq_mat_t L, const fq_mat_t B, int unit, const fq_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void fq_mat_solve_tril_classical(fq_mat_t X, const fq_mat_t L, const fq_mat_t B, int unit, const fq_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void fq_mat_solve_tril_recursive(fq_mat_t X, const fq_mat_t L, const fq_mat_t B, int unit, const fq_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. .. function:: void fq_mat_solve_triu(fq_mat_t X, const fq_mat_t U, const fq_mat_t B, int unit, const fq_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void fq_mat_solve_triu_classical(fq_mat_t X, const fq_mat_t U, const fq_mat_t B, int unit, const fq_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void fq_mat_solve_triu_recursive(fq_mat_t X, const fq_mat_t U, const fq_mat_t B, int unit, const fq_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. Solving -------------------------------------------------------------------------------- .. function:: int fq_mat_solve(fq_mat_t X, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Solves the matrix-matrix equation `AX = B`. Returns `1` if `A` has full rank; otherwise returns `0` and sets the elements of `X` to undefined values. The matrix `A` must be square. .. function:: int fq_mat_can_solve(fq_mat_t X, const fq_mat_t A, const fq_mat_t B, const fq_ctx_t ctx) Solves the matrix-matrix equation `AX = B` over `Fq`. Returns `1` if a solution exists; otherwise returns `0` and sets the elements of `X` to zero. If more than one solution exists, one of the valid solutions is given. There are no restrictions on the shape of `A` and it may be singular. Transforms -------------------------------------------------------------------------------- .. function:: void fq_mat_similarity(fq_mat_t M, slong r, fq_t d, const fq_ctx_t ctx) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. The value `d` is required to be reduced modulo the modulus of the entries in the matrix. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void fq_mat_charpoly_danilevsky(fq_poly_t p, const fq_mat_t M, const fq_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is assumed to be square. .. function:: void fq_mat_charpoly(fq_poly_t p, const fq_mat_t M, const fq_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. Minimal polynomial -------------------------------------------------------------------------------- .. function:: void fq_mat_minpoly(fq_poly_t p, const fq_mat_t M, const fq_ctx_t ctx) Compute the minimal polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. flint-3.1.3/doc/source/fq_nmod.rst000066400000000000000000000467431461254215100170730ustar00rootroot00000000000000.. _fq-nmod: **fq_nmod.h** -- finite fields (word-size characteristic) =============================================================================== We represent an element of the finite field `\mathbf{F}_{p^n} \cong \mathbf{F}_p[X]/(f(X))`, where `f(X) \in \mathbf{F}_p[X]` is a monic, irreducible polynomial of degree `n`, as a polynomial in `\mathbf{F}_p[X]` of degree less than `n`. The underlying data structure is an :type:`nmod_poly_t`. The default choice for `f(X)` is the Conway polynomial for the pair `(p,n)`, enabled by Frank Lübeck's data base of Conway polynomials using the :func:`_nmod_poly_conway` function. If a Conway polynomial is not available, then a random irreducible polynomial will be chosen for `f(X)`. Additionally, the user is able to supply their own `f(X)`. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_ctx_struct .. type:: fq_nmod_ctx_t .. type:: fq_nmod_struct .. type:: fq_nmod_t Context Management -------------------------------------------------------------------------------- .. function:: void fq_nmod_ctx_init_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator. By default, it will try use a Conway polynomial; if one is not available, a random irreducible polynomial will be used. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: int _fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char * var) Attempts to initialise the context for prime `p` and extension degree `d`, with name ``var`` for the generator using a Conway polynomial for the modulus. Returns `1` if the Conway polynomial is in the database for the given size and the initialization is successful; otherwise, returns `0`. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator using a Conway polynomial for the modulus. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_nmod_ctx_init_modulus(fq_nmod_ctx_t ctx, const nmod_poly_t modulus, const char * var) Initialises the context for given ``modulus`` with name ``var`` for the generator. Assumes that ``modulus`` is an irreducible polynomial over `\mathbf{F}_{p}`. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_nmod_ctx_init_randtest(fq_nmod_ctx_t ctx, flint_rand_t state, int type) Initialises ``ctx`` to a random finite field, where the prime and degree is set according to ``type``. To see what prime and degrees may be output, see ``type`` in :func:`_nmod_poly_conway_rand`. .. function:: void fq_nmod_ctx_init_randtest_reducible(fq_nmod_ctx_t ctx, flint_rand_t state, int type) Initializes ``ctx`` to a random extension of a word-sized prime field, where the prime and degree is set according to ``type``. If ``type`` is `0` the prime and degree may be large, else if ``type`` is `1` the degree is small but the prime may be large, else if ``type`` is `2` the prime is small but the degree may be large, else if ``type`` is `3` both prime and degree are small. The modulus may or may not be irreducible. .. function:: void fq_nmod_ctx_clear(fq_nmod_ctx_t ctx) Clears all memory that has been allocated as part of the context. .. function:: const nmod_poly_struct* fq_nmod_ctx_modulus(const fq_nmod_ctx_t ctx) Returns a pointer to the modulus in the context. .. function:: slong fq_nmod_ctx_degree(const fq_nmod_ctx_t ctx) Returns the degree of the field extension `[\mathbf{F}_{q} : \mathbf{F}_{p}]`, which is equal to `\log_{p} q`. .. function:: ulong fq_nmod_ctx_prime(const fq_nmod_ctx_t ctx) Returns the prime `p` of the context. .. function:: void fq_nmod_ctx_order(fmpz_t f, const fq_nmod_ctx_t ctx) Sets `f` to be the size of the finite field. .. function:: int fq_nmod_ctx_fprint(FILE * file, const fq_nmod_ctx_t ctx) Prints the context information to ``file``. Returns 1 for a success and a negative number for an error. .. function:: void fq_nmod_ctx_print(const fq_nmod_ctx_t ctx) Prints the context information to ``stdout``. Memory management -------------------------------------------------------------------------------- .. function:: void fq_nmod_init(fq_nmod_t rop, const fq_nmod_ctx_t ctx) Initialises the element ``rop``, setting its value to `0`. Currently, the behaviour is identical to ``fq_nmod_init2``, as it also ensures ``rop`` has enough space for it to be an element of ``ctx``, this may change in the future. .. function:: void fq_nmod_init2(fq_nmod_t rop, const fq_nmod_ctx_t ctx) Initialises ``rop`` with at least enough space for it to be an element of ``ctx`` and sets it to `0`. .. function:: void fq_nmod_clear(fq_nmod_t rop, const fq_nmod_ctx_t ctx) Clears the element ``rop``. .. function:: void _fq_nmod_sparse_reduce(mp_limb_t * R, slong lenR, const fq_nmod_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx``. .. function:: void _fq_nmod_dense_reduce(mp_limb_t * R, slong lenR, const fq_nmod_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx`` using Newton division. .. function:: void _fq_nmod_reduce(mp_limb_t * r, slong lenR, const fq_nmod_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx``. Does either sparse or dense reduction based on ``ctx->sparse_modulus``. .. function:: void fq_nmod_reduce(fq_nmod_t rop, const fq_nmod_ctx_t ctx) Reduces the polynomial ``rop`` as an element of `\mathbf{F}_p[X] / (f(X))`. Basic arithmetic -------------------------------------------------------------------------------- .. function:: void fq_nmod_add(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the sum of ``op1`` and ``op2``. .. function:: void fq_nmod_sub(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and ``op2``. .. function:: void fq_nmod_sub_one(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and `1`. .. function:: void fq_nmod_neg(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the negative of ``op``. .. function:: void fq_nmod_mul(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void fq_nmod_mul_fmpz(fq_nmod_t rop, const fq_nmod_t op, const fmpz_t x, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_nmod_mul_si(fq_nmod_t rop, const fq_nmod_t op, slong x, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_nmod_mul_ui(fq_nmod_t rop, const fq_nmod_t op, ulong x, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_nmod_sqr(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the square of ``op``, reducing the output in the given context. .. function:: void _fq_nmod_inv(mp_ptr * rop, mp_srcptr * op, slong len, const fq_nmod_ctx_t ctx) Sets ``(rop, d)`` to the inverse of the non-zero element ``(op, len)``. .. function:: void fq_nmod_inv(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the inverse of the non-zero element ``op``. .. function:: void fq_nmod_gcdinv(fq_nmod_t f, fq_nmod_t inv, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Sets ``inv`` to be the inverse of ``op`` modulo the modulus of ``ctx``. If ``op`` is not invertible, then ``f`` is set to a factor of the modulus; otherwise, it is set to one. .. function:: void _fq_nmod_pow(mp_limb_t * rop, const mp_limb_t * op, slong len, const fmpz_t e, const fq_nmod_ctx_t ctx) Sets ``(rop, 2*d-1)`` to ``(op,len)`` raised to the power `e`, reduced modulo `f(X)`, the modulus of ``ctx``. Assumes that `e \geq 0` and that ``len`` is positive and at most `d`. Although we require that ``rop`` provides space for `2d - 1` coefficients, the output will be reduced modulo `f(X)`, which is a polynomial of degree `d`. Does not support aliasing. .. function:: void fq_nmod_pow(fq_nmod_t rop, const fq_nmod_t op, const fmpz_t e, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. .. function:: void fq_nmod_pow_ui(fq_nmod_t rop, const fq_nmod_t op, const ulong e, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. Roots -------------------------------------------------------------------------------- .. function:: int fq_nmod_sqrt(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx) Sets ``rop`` to the square root of ``op1`` if it is a square, and return `1`, otherwise return `0`. .. function:: void fq_nmod_pth_root(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx) Sets ``rop`` to a `p^{\textrm{th}}` root of ``op1``. Currently, this computes the root by raising ``op1`` to `p^{d-1}` where `d` is the degree of the extension. .. function:: int fq_nmod_is_square(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Return ``1`` if ``op`` is a square. Output -------------------------------------------------------------------------------- .. function:: int fq_nmod_fprint_pretty(FILE * file, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Prints a pretty representation of ``op`` to ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: void fq_nmod_print_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Prints a pretty representation of ``op`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_nmod_fprint(FILE * file, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Prints a representation of ``op`` to ``file``. For further details on the representation used, see ``nmod_poly_fprint()``. .. function:: void fq_nmod_print(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Prints a representation of ``op`` to ``stdout``. For further details on the representation used, see ``nmod_poly_print()``. .. function:: char * fq_nmod_get_str(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Returns the plain FLINT string representation of the element ``op``. .. function:: char * fq_nmod_get_str_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Returns a pretty representation of the element ``op`` using the null-terminated string ``x`` as the variable name. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_nmod_randtest(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) Generates a random element of `\mathbf{F}_q`. .. function:: void fq_nmod_randtest_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) Generates a random non-zero element of `\mathbf{F}_q`. .. function:: void fq_nmod_randtest_dense(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) Generates a random element of `\mathbf{F}_q` which has an underlying polynomial with dense coefficients. .. function:: void fq_nmod_rand(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) Generates a high quality random element of `\mathbf{F}_q`. .. function:: void fq_nmod_rand_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) Generates a high quality non-zero random element of `\mathbf{F}_q`. Assignments and conversions -------------------------------------------------------------------------------- .. function:: void fq_nmod_set(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``op``. .. function:: void fq_nmod_set_si(fq_nmod_t rop, const slong x, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_nmod_set_ui(fq_nmod_t rop, const ulong x, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_nmod_set_fmpz(fq_nmod_t rop, const fmpz_t x, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_nmod_swap(fq_nmod_t op1, fq_nmod_t op2, const fq_nmod_ctx_t ctx) Swaps the two elements ``op1`` and ``op2``. .. function:: void fq_nmod_zero(fq_nmod_t rop, const fq_nmod_ctx_t ctx) Sets ``rop`` to zero. .. function:: void fq_nmod_one(fq_nmod_t rop, const fq_nmod_ctx_t ctx) Sets ``rop`` to one, reduced in the given context. .. function:: void fq_nmod_gen(fq_nmod_t rop, const fq_nmod_ctx_t ctx) Sets ``rop`` to a generator for the finite field. There is no guarantee this is a multiplicative generator of the finite field. .. function:: int fq_nmod_get_fmpz(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) If ``op`` has a lift to the integers, return `1` and set ``rop`` to the lift in `[0,p)`. Otherwise, return `0` and leave `rop` undefined. .. function:: void fq_nmod_get_nmod_poly(nmod_poly_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx) Set ``a`` to a representative of ``b`` in ``ctx``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. .. function:: void fq_nmod_set_nmod_poly(fq_nmod_t a, const nmod_poly_t b, const fq_nmod_ctx_t ctx) Set ``a`` to the element in ``ctx`` with representative ``b``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. .. function:: void fq_nmod_get_nmod_mat(nmod_mat_t col, const fq_nmod_t a, const fq_nmod_ctx_t ctx) Convert ``a`` to a column vector of length ``degree(ctx)``. .. function:: void fq_nmod_set_nmod_mat(fq_nmod_t a, const nmod_mat_t col, const fq_nmod_ctx_t ctx) Convert a column vector ``col`` of length ``degree(ctx)`` to an element of ``ctx``. Comparison -------------------------------------------------------------------------------- .. function:: int fq_nmod_is_zero(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Returns whether ``op`` is equal to zero. .. function:: int fq_nmod_is_one(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Returns whether ``op`` is equal to one. .. function:: int fq_nmod_equal(const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) Returns whether ``op1`` and ``op2`` are equal. .. function:: int fq_nmod_is_invertible(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Returns whether ``op`` is an invertible element. .. function:: int fq_nmod_is_invertible_f(fq_nmod_t f, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Returns whether ``op`` is an invertible element. If it is not, then ``f`` is set to a factor of the modulus. .. function:: int fq_nmod_cmp(const fq_nmod_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx) Return ``1`` (resp. ``-1``, or ``0``) if ``a`` is after (resp. before, same as) ``b`` in some arbitrary but fixed total ordering of the elements. Special functions -------------------------------------------------------------------------------- .. function:: void _fq_nmod_trace(fmpz_t rop, const mp_limb_t * op, slong len, const fq_nmod_ctx_t ctx) Sets ``rop`` to the trace of the non-zero element ``(op, len)`` in `\mathbf{F}_{q}`. .. function:: void fq_nmod_trace(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the trace of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the trace of `a` as the trace of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\sum_{i=0}^{d-1} \Sigma^i (a)`, where `d = \log_{p} q`. .. function:: void _fq_nmod_norm(fmpz_t rop, const mp_limb_t * op, slong len, const fq_nmod_ctx_t ctx) Sets ``rop`` to the norm of the non-zero element ``(op, len)`` in `\mathbf{F}_{q}`. .. function:: void fq_nmod_norm(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Computes the norm of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the norm of `a` as the determinant of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\prod_{i=0}^{d-1} \Sigma^i (a)`, where `d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)`. Algorithm selection is automatic depending on the input. .. function:: void _fq_nmod_frobenius(mp_limb_t * rop, const mp_limb_t * op, slong len, slong e, const fq_nmod_ctx_t ctx) Sets ``(rop, 2d-1)`` to the image of ``(op, len)`` under the Frobenius operator raised to the e-th power, assuming that neither ``op`` nor ``e`` are zero. .. function:: void fq_nmod_frobenius(fq_nmod_t rop, const fq_nmod_t op, slong e, const fq_nmod_ctx_t ctx) Evaluates the homomorphism `\Sigma^e` at ``op``. Recall that `\mathbf{F}_q / \mathbf{F}_p` is Galois with Galois group `\langle \sigma \rangle`, which is also isomorphic to `\mathbf{Z}/d\mathbf{Z}`, where `\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)` is the Frobenius element `\sigma \colon x \mapsto x^p`. .. function:: int fq_nmod_multiplicative_order(fmpz * ord, const fq_nmod_t op, const fq_nmod_ctx_t ctx) Computes the order of ``op`` as an element of the multiplicative group of ``ctx``. Returns 0 if ``op`` is 0, otherwise it returns 1 if ``op`` is a generator of the multiplicative group, and -1 if it is not. This function can also be used to check primitivity of a generator of a finite field whose defining polynomial is not primitive. .. function:: int fq_nmod_is_primitive(const fq_nmod_t op, const fq_nmod_ctx_t ctx) Returns whether ``op`` is primitive, i.e., whether it is a generator of the multiplicative group of ``ctx``. Bit packing -------------------------------------------------------------------------------- .. function:: void fq_nmod_bit_pack(fmpz_t f, const fq_nmod_t op, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx) Packs ``op`` into bitfields of size ``bit_size``, writing the result to ``f``. .. function:: void fq_nmod_bit_unpack(fq_nmod_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx) Unpacks into ``rop`` the element with coefficients packed into fields of size ``bit_size`` as represented by the integer ``f``. flint-3.1.3/doc/source/fq_nmod_embed.rst000066400000000000000000000110531461254215100202110ustar00rootroot00000000000000.. _fq-nmod-embed: **fq_nmod_embed.h** -- Computing isomorphisms and embeddings of finite fields -------------------------------------------------------------------------------- .. function:: void fq_nmod_embed_gens(fq_nmod_t gen_sub, fq_nmod_t gen_sup, nmod_poly_t minpoly, const fq_nmod_ctx_t sub_ctx, const fq_nmod_ctx_t sup_ctx) Given two contexts ``sub_ctx`` and ``sup_ctx``, such that ``degree(sub_ctx)`` divides ``degree(sup_ctx)``, compute: * an element ``gen_sub`` in ``sub_ctx`` such that ``gen_sub`` generates the finite field defined by ``sub_ctx``, * its minimal polynomial ``minpoly``, * a root ``gen_sup`` of ``minpoly`` inside the field defined by ``sup_ctx``. These data uniquely define an embedding of ``sub_ctx`` into ``sup_ctx``. .. function:: void _fq_nmod_embed_gens_naive(fq_nmod_t gen_sub, fq_nmod_t gen_sup, nmod_poly_t minpoly, const fq_nmod_ctx_t sub_ctx, const fq_nmod_ctx_t sup_ctx) Given two contexts ``sub_ctx`` and ``sup_ctx``, such that ``degree(sub_ctx)`` divides ``degree(sup_ctx)``, compute an embedding of ``sub_ctx`` into ``sup_ctx`` defined as follows: * ``gen_sub`` is the canonical generator of ``sup_ctx`` (i.e., the class of `X`), * ``minpoly`` is the defining polynomial of ``sub_ctx``, * ``gen_sup`` is a root of ``minpoly`` inside the field defined by ``sup_ctx``. .. function:: void fq_nmod_embed_matrices(nmod_mat_t embed, nmod_mat_t project, const fq_nmod_t gen_sub, const fq_nmod_ctx_t sub_ctx, const fq_nmod_t gen_sup, const fq_nmod_ctx_t sup_ctx, const nmod_poly_t gen_minpoly) Given: * two contexts ``sub_ctx`` and ``sup_ctx``, of respective degrees `m` and `n`, such that `m` divides `n`; * a generator ``gen_sub`` of ``sub_ctx``, its minimal polynomial ``gen_minpoly``, and a root ``gen_sup`` of ``gen_minpoly`` in ``sup_ctx``, as returned by ``fq_nmod_embed_gens``; Compute: * the `n\times m` matrix ``embed`` mapping ``gen_sub`` to ``gen_sup``, and all their powers accordingly; * an `m\times n` matrix ``project`` such that ``project`` `\times` ``embed`` is the `m\times m` identity matrix. .. function:: void fq_nmod_embed_trace_matrix(nmod_mat_t res, const nmod_mat_t basis, const fq_nmod_ctx_t sub_ctx, const fq_nmod_ctx_t sup_ctx) Given: * two contexts ``sub_ctx`` and ``sup_ctx``, of degrees `m` and `n`, such that `m` divides `n`; * an `n\times m` matrix ``basis`` that maps ``sub_ctx`` to an isomorphic subfield in ``sup_ctx``; Compute the `m\times n` matrix of the trace from ``sup_ctx`` to ``sub_ctx``. This matrix is computed as ``embed_dual_to_mono_matrix(_, sub_ctx)`` `\times` ``basis``:sup:`t` `\times` ``embed_mono_to_dual_matrix(_, sup_ctx)}``. **Note:** if `m=n`, ``basis`` represents a Frobenius, and the result is its inverse matrix. .. function:: void fq_nmod_embed_composition_matrix(nmod_mat_t matrix, const fq_nmod_t gen, const fq_nmod_ctx_t ctx) Compute the *composition matrix* of ``gen``. For an element `a\in\mathbf{F}_{p^n}`, its composition matrix is the matrix whose columns are `a^0, a^1, \ldots, a^{n-1}`. .. function:: void fq_nmod_embed_composition_matrix_sub(nmod_mat_t matrix, const fq_nmod_t gen, const fq_nmod_ctx_t ctx, slong trunc) Compute the *composition matrix* of ``gen``, truncated to ``trunc`` columns. .. function:: void fq_nmod_embed_mul_matrix(nmod_mat_t matrix, const fq_nmod_t gen, const fq_nmod_ctx_t ctx) Compute the *multiplication matrix* of ``gen``. For an element `a` in `\mathbf{F}_{p^n}=\mathbf{F}_p[x]`, its multiplication matrix is the matrix whose columns are `a, ax, \dots, ax^{n-1}`. .. function:: void fq_nmod_embed_mono_to_dual_matrix(nmod_mat_t res, const fq_nmod_ctx_t ctx) Compute the change of basis matrix from the monomial basis of ``ctx`` to its dual basis. .. function:: void fq_nmod_embed_dual_to_mono_matrix(nmod_mat_t res, const fq_nmod_ctx_t ctx) Compute the change of basis matrix from the dual basis of ``ctx`` to its monomial basis. .. function:: void fq_nmod_modulus_pow_series_inv(nmod_poly_t res, const fq_nmod_ctx_t ctx, slong trunc) Compute the power series inverse of the reverse of the modulus of ``ctx`` up to `O(x^\texttt{trunc})`. .. function:: void fq_nmod_modulus_derivative_inv(fq_nmod_t m_prime, fq_nmod_t m_prime_inv, const fq_nmod_ctx_t ctx) Compute the derivative ``m_prime`` of the modulus of ``ctx`` as an element of ``ctx``, and its inverse ``m_prime_inv``. flint-3.1.3/doc/source/fq_nmod_mat.rst000066400000000000000000000553051461254215100177260ustar00rootroot00000000000000.. _fq-nmod-mat: **fq_nmod_mat.h** -- matrices over finite fields (word-size characteristic) =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_mat_struct .. type:: fq_nmod_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_init(fq_nmod_mat_t mat, slong rows, slong cols, const fq_nmod_ctx_t ctx) Initialises ``mat`` to a ``rows``-by-``cols`` matrix with coefficients in `\mathbf{F}_{q}` given by ``ctx``. All elements are set to zero. .. function:: void fq_nmod_mat_init_set(fq_nmod_mat_t mat, const fq_nmod_mat_t src, const fq_nmod_ctx_t ctx) Initialises ``mat`` and sets its dimensions and elements to those of ``src``. .. function:: void fq_nmod_mat_clear(fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Clears the matrix and releases any memory it used. The matrix cannot be used again until it is initialised. This function must be called exactly once when finished using an :type:`fq_nmod_mat_t` object. .. function:: void fq_nmod_mat_set(fq_nmod_mat_t mat, const fq_nmod_mat_t src, const fq_nmod_ctx_t ctx) Sets ``mat`` to a copy of ``src``. It is assumed that ``mat`` and ``src`` have identical dimensions. Basic properties and manipulation -------------------------------------------------------------------------------- .. function:: fq_nmod_struct * fq_nmod_mat_entry(const fq_nmod_mat_t mat, slong i, slong j) Directly accesses the entry in ``mat`` in row `i` and column `j`, indexed from zero. No bounds checking is performed. .. function:: void fq_nmod_mat_entry_set(fq_nmod_mat_t mat, slong i, slong j, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Sets the entry in ``mat`` in row `i` and column `j` to ``x``. .. function:: slong fq_nmod_mat_nrows(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_nmod_mat_ncols(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Returns the number of columns in ``mat``. .. function:: void fq_nmod_mat_swap(fq_nmod_mat_t mat1, fq_nmod_mat_t mat2, const fq_nmod_ctx_t ctx) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. function:: void fq_nmod_mat_swap_entrywise(fq_nmod_mat_t mat1, fq_nmod_mat_t mat2, const fq_nmod_ctx_t ctx) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: void fq_nmod_mat_zero(fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Sets all entries of ``mat`` to 0. .. function:: void fq_nmod_mat_one(fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Sets all diagonal entries of ``mat`` to 1 and all other entries to 0. .. function:: void fq_nmod_mat_swap_rows(fq_nmod_mat_t mat, slong * perm, slong r, slong s, const fq_nmod_ctx_t ctx) Swaps rows ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fq_nmod_mat_swap_cols(fq_nmod_mat_t mat, slong * perm, slong r, slong s, const fq_nmod_ctx_t ctx) Swaps columns ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: void fq_nmod_mat_invert_rows(fq_nmod_mat_t mat, slong * perm, const fq_nmod_ctx_t ctx) Swaps rows ``i`` and ``r - i`` of ``mat`` for ``0 <= i < r/2``, where ``r`` is the number of rows of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void fq_nmod_mat_invert_cols(fq_nmod_mat_t mat, slong * perm, const fq_nmod_ctx_t ctx) Swaps columns ``i`` and ``c - i`` of ``mat`` for ``0 <= i < c/2``, where ``c`` is the number of columns of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. Conversions -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_set_nmod_mat(fq_nmod_mat_t mat1, const nmod_mat_t mat2, const fq_nmod_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. .. function:: void fq_nmod_mat_set_fmpz_mod_mat(fq_nmod_mat_t mat1, const fmpz_mod_mat_t mat2, const fq_nmod_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. Concatenate -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_concat_vertical(fq_nmod_mat_t res, const fq_nmod_mat_t mat1, const fq_nmod_mat_t mat2, const fq_nmod_ctx_t ctx) Sets ``res`` to vertical concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `k \times n`, ``res`` : `(m + k) \times n`. .. function:: void fq_nmod_mat_concat_horizontal(fq_nmod_mat_t res, const fq_nmod_mat_t mat1, const fq_nmod_mat_t mat2, const fq_nmod_ctx_t ctx) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `m \times k`, ``res`` : `m \times (n + k)`. Printing -------------------------------------------------------------------------------- .. function:: int fq_nmod_mat_print_pretty(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Pretty-prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_nmod_mat_fprint_pretty(FILE * file, const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Pretty-prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_nmod_mat_print(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_nmod_mat_fprint(FILE * file, const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. Window -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_window_init(fq_nmod_mat_t window, const fq_nmod_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fq_nmod_ctx_t ctx) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0,0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void fq_nmod_mat_window_clear(fq_nmod_mat_t window, const fq_nmod_ctx_t ctx) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. Random matrix generation -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_randtest(fq_nmod_mat_t mat, flint_rand_t state, const fq_nmod_ctx_t ctx) Sets the elements of ``mat`` to random elements of `\mathbf{F}_{q}`, given by ``ctx``. .. function:: int fq_nmod_mat_randpermdiag(fq_nmod_mat_t mat, flint_rand_t state, fq_nmod_struct * diag, slong n, const fq_nmod_ctx_t ctx) Sets ``mat`` to a random permutation of the diagonal matrix with `n` leading entries given by the vector ``diag``. It is assumed that the main diagonal of ``mat`` has room for at least `n` entries. Returns `0` or `1`, depending on whether the permutation is even or odd respectively. .. function:: void fq_nmod_mat_randrank(fq_nmod_mat_t mat, flint_rand_t state, slong rank, const fq_nmod_ctx_t ctx) Sets ``mat`` to a random sparse matrix with the given rank, having exactly as many non-zero elements as the rank, with the non-zero elements being uniformly random elements of `\mathbf{F}_{q}`. The matrix can be transformed into a dense matrix with unchanged rank by subsequently calling :func:`fq_nmod_mat_randops`. .. function:: void fq_nmod_mat_randops(fq_nmod_mat_t mat, flint_rand_t state, slong count, const fq_nmod_ctx_t ctx) Randomises ``mat`` by performing elementary row or column operations. More precisely, at most ``count`` random additions or subtractions of distinct rows and columns will be performed. This leaves the rank (and for square matrices, determinant) unchanged. .. function:: void fq_nmod_mat_randtril(fq_nmod_mat_t mat, flint_rand_t state, int unit, const fq_nmod_ctx_t ctx) Sets ``mat`` to a random lower triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. .. function:: void fq_nmod_mat_randtriu(fq_nmod_mat_t mat, flint_rand_t state, int unit, const fq_nmod_ctx_t ctx) Sets ``mat`` to a random upper triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. Comparison -------------------------------------------------------------------------------- .. function:: int fq_nmod_mat_equal(const fq_nmod_mat_t mat1, const fq_nmod_mat_t mat2, const fq_nmod_ctx_t ctx) Returns nonzero if mat1 and mat2 have the same dimensions and elements, and zero otherwise. .. function:: int fq_nmod_mat_is_zero(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Returns a non-zero value if all entries ``mat`` are zero, and otherwise returns zero. .. function:: int fq_nmod_mat_is_one(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Returns a non-zero value if all entries ``mat`` are zero except the diagonal entries which must be one, otherwise returns zero. .. function:: int fq_nmod_mat_is_empty(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int fq_nmod_mat_is_square(const fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_add(fq_nmod_mat_t C, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Computes `C = A + B`. Dimensions must be identical. .. function:: void fq_nmod_mat_sub(fq_nmod_mat_t C, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Computes `C = A - B`. Dimensions must be identical. .. function:: void fq_nmod_mat_neg(fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Sets `B = -A`. Dimensions must be identical. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_mul(fq_nmod_mat_t C, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. Aliasing is allowed. This function automatically chooses between classical and KS multiplication. .. function:: void fq_nmod_mat_mul_classical(fq_nmod_mat_t C, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses classical matrix multiplication. .. function:: void fq_nmod_mat_mul_KS(fq_nmod_mat_t C, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses Kronecker substitution to perform the multiplication over the integers. .. function:: void fq_nmod_mat_submul(fq_nmod_mat_t D, const fq_nmod_mat_t C, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Sets `D = C + AB`. `C` and `D` may be aliased with each other but not with `A` or `B`. .. function:: void fq_nmod_mat_mul_vec(fq_nmod_struct * c, const fq_nmod_mat_t A, const fq_nmod_struct * b, slong blen, const fq_nmod_ctx_t ctx) void fq_nmod_mat_mul_vec_ptr(fq_nmod_struct * const * c, const fq_nmod_mat_t A, const fq_nmod_struct * const * b, slong blen, const fq_nmod_ctx_t ctx) Compute a matrix-vector product of ``A`` and ``(b, blen)`` and store the result in ``c``. The vector ``(b, blen)`` is either truncated or zero-extended to the number of columns of ``A``. The number entries written to ``c`` is always equal to the number of rows of ``A``. .. function:: void fq_nmod_mat_vec_mul(fq_nmod_struct * c, const fq_nmod_struct * a, slong alen, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) void fq_nmod_mat_vec_mul_ptr(fq_nmod_struct * const * c, const fq_nmod_struct * const * a, slong alen, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Compute a vector-matrix product of ``(a, alen)`` and ``B`` and and store the result in ``c``. The vector ``(a, alen)`` is either truncated or zero-extended to the number of rows of ``B``. The number entries written to ``c`` is always equal to the number of columns of ``B``. Inverse -------------------------------------------------------------------------------- .. function:: int fq_nmod_mat_inv(fq_nmod_mat_t B, fq_nmod_mat_t A, const fq_nmod_ctx_t ctx) Sets `B = A^{-1}` and returns `1` if `A` is invertible. If `A` is singular, returns `0` and sets the elements of `B` to undefined values. `A` and `B` must be square matrices with the same dimensions. LU decomposition -------------------------------------------------------------------------------- .. function:: slong fq_nmod_mat_lu(slong * P, fq_nmod_mat_t A, int rank_check, const fq_nmod_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. If `A` is a nonsingular square matrix, it will be overwritten with a unit diagonal lower triangular matrix `L` and an upper triangular matrix `U` (the diagonal of `L` will not be stored explicitly). If `A` is an arbitrary matrix of rank `r`, `U` will be in row echelon form having `r` nonzero rows, and `L` will be lower triangular but truncated to `r` columns, having implicit ones on the `r` first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and return 0 if `A` is detected to be rank-deficient. This function calls ``fq_nmod_mat_lu_recursive``. .. function:: slong fq_nmod_mat_lu_classical(slong * P, fq_nmod_mat_t A, int rank_check, const fq_nmod_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. The behavior of this function is identical to that of ``fq_nmod_mat_lu``. Uses Gaussian elimination. .. function:: slong fq_nmod_mat_lu_recursive(slong * P, fq_nmod_mat_t A, int rank_check, const fq_nmod_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. The behavior of this function is identical to that of ``fq_nmod_mat_lu``. Uses recursive block decomposition, switching to classical Gaussian elimination for sufficiently small blocks. Reduced row echelon form -------------------------------------------------------------------------------- .. function:: slong fq_nmod_mat_rref(fq_nmod_mat_t B, const fq_nmod_mat_t A, const fq_nmod_ctx_t ctx) Puts `B` in reduced row echelon form and returns the rank of `A`. The rref is computed by first obtaining an unreduced row echelon form via LU decomposition and then solving an additional triangular system. .. function:: slong fq_nmod_mat_reduce_row(fq_nmod_mat_t A, slong * P, slong * L, slong n, const fq_nmod_ctx_t ctx) Reduce row n of the matrix `A`, assuming the prior rows are in Gauss form. However those rows may not be in order. The entry `i` of the array `P` is the row of `A` which has a pivot in the `i`-th column. If no such row exists, the entry of `P` will be `-1`. The function returns the column in which the `n`-th row has a pivot after reduction. This will always be chosen to be the first available column for a pivot from the left. This information is also updated in `P`. Entry `i` of the array `L` contains the number of possibly nonzero columns of `A` row `i`. This speeds up reduction in the case that `A` is chambered on the right. Otherwise the entries of `L` can all be set to the number of columns of `A`. We require the entries of `L` to be monotonic increasing. Triangular solving -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_solve_tril(fq_nmod_mat_t X, const fq_nmod_mat_t L, const fq_nmod_mat_t B, int unit, const fq_nmod_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void fq_nmod_mat_solve_tril_classical(fq_nmod_mat_t X, const fq_nmod_mat_t L, const fq_nmod_mat_t B, int unit, const fq_nmod_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void fq_nmod_mat_solve_tril_recursive(fq_nmod_mat_t X, const fq_nmod_mat_t L, const fq_nmod_mat_t B, int unit, const fq_nmod_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. .. function:: void fq_nmod_mat_solve_triu(fq_nmod_mat_t X, const fq_nmod_mat_t U, const fq_nmod_mat_t B, int unit, const fq_nmod_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void fq_nmod_mat_solve_triu_classical(fq_nmod_mat_t X, const fq_nmod_mat_t U, const fq_nmod_mat_t B, int unit, const fq_nmod_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void fq_nmod_mat_solve_triu_recursive(fq_nmod_mat_t X, const fq_nmod_mat_t U, const fq_nmod_mat_t B, int unit, const fq_nmod_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. Solving -------------------------------------------------------------------------------- .. function:: int fq_nmod_mat_solve(fq_nmod_mat_t X, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Solves the matrix-matrix equation `AX = B`. Returns `1` if `A` has full rank; otherwise returns `0` and sets the elements of `X` to undefined values. The matrix `A` must be square. .. function:: int fq_nmod_mat_can_solve(fq_nmod_mat_t X, const fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_ctx_t ctx) Solves the matrix-matrix equation `AX = B` over `Fq`. Returns `1` if a solution exists; otherwise returns `0` and sets the elements of `X` to zero. If more than one solution exists, one of the valid solutions is given. There are no restrictions on the shape of `A` and it may be singular. Transforms -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_similarity(fq_nmod_mat_t M, slong r, fq_nmod_t d, const fq_nmod_ctx_t ctx) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. The value `d` is required to be reduced modulo the modulus of the entries in the matrix. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_charpoly_danilevsky(fq_nmod_poly_t p, const fq_nmod_mat_t M, const fq_nmod_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is assumed to be square. .. function:: void fq_nmod_mat_charpoly(fq_nmod_poly_t p, const fq_nmod_mat_t M, const fq_nmod_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. Minimal polynomial -------------------------------------------------------------------------------- .. function:: void fq_nmod_mat_minpoly(fq_nmod_poly_t p, const fq_nmod_mat_t M, const fq_nmod_ctx_t ctx) Compute the minimal polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. flint-3.1.3/doc/source/fq_nmod_mpoly.rst000066400000000000000000000710361461254215100203040ustar00rootroot00000000000000.. _fq_nmod-mpoly: **fq_nmod_mpoly.h** -- multivariate polynomials over finite fields of word-sized characteristic ================================================================================================ The exponents follow the ``mpoly`` interface. No references to the coefficients are available. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_mpoly_struct A structure holding a multivariate polynomial over a finite field of word-sized characteristic. .. type:: fq_nmod_mpoly_t An array of length `1` of ``fq_nmod_mpoly_struct``. .. type:: fq_nmod_mpoly_ctx_struct Context structure representing the parent ring of an ``fq_nmod_mpoly``. .. type:: fq_nmod_mpoly_ctx_t An array of length `1` of ``fq_nmod_mpoly_ctx_struct``. Context object -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_ctx_init(fq_nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fq_nmod_ctx_t fqctx) Initialise a context object for a polynomial ring with the given number of variables and the given ordering. It will have coefficients in the finite field *fqctx*. The possibilities for the ordering are ``ORD_LEX``, ``ORD_DEGLEX`` and ``ORD_DEGREVLEX``. .. function:: slong fq_nmod_mpoly_ctx_nvars(const fq_nmod_mpoly_ctx_t ctx) Return the number of variables used to initialize the context. .. function:: ordering_t fq_nmod_mpoly_ctx_ord(const fq_nmod_mpoly_ctx_t ctx) Return the ordering used to initialize the context. .. function:: void fq_nmod_mpoly_ctx_clear(fq_nmod_mpoly_ctx_t ctx) Release any space allocated by an *ctx*. Memory management -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_init(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. .. function:: void fq_nmod_mpoly_init2(fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and at least ``MPOLY_MIN_BITS`` bits for the exponents. .. function:: void fq_nmod_mpoly_init3(fq_nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and *bits* bits for the exponents. .. function:: void fq_nmod_mpoly_fit_length(fq_nmod_mpoly_t A, slong len, const fq_nmod_mpoly_ctx_t ctx) Ensure that *A* has space for at least *len* terms. .. function:: void fq_nmod_mpoly_realloc(fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx) Reallocate *A* to have space for *alloc* terms. Assumes the current length of the polynomial is not greater than *alloc*. .. function:: void fq_nmod_mpoly_clear(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Release any space allocated for *A*. Input/Output -------------------------------------------------------------------------------- The variable strings in *x* start with the variable of most significance at index `0`. If *x* is ``NULL``, the variables are named ``x1``, ``x2``, etc. .. function:: char * fq_nmod_mpoly_get_str_pretty(const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx) Return a string, which the user is responsible for cleaning up, representing *A*, given an array of variable strings *x*. .. function:: int fq_nmod_mpoly_fprint_pretty(FILE * file, const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx) Print a string representing *A* to *file*. .. function:: int fq_nmod_mpoly_print_pretty(const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx) Print a string representing *A* to ``stdout``. .. function:: int fq_nmod_mpoly_set_str_pretty(fq_nmod_mpoly_t A, const char * str, const char ** x, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the polynomial in the null-terminates string *str* given an array *x* of variable strings. If parsing *str* fails, *A* is set to zero, and `-1` is returned. Otherwise, `0` is returned. The operations ``+``, ``-``, ``*``, and ``/`` are permitted along with integers and the variables in *x*. The character ``^`` must be immediately followed by the (integer) exponent. If any division is not exact, parsing fails. Basic manipulation -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_gen(fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the variable of index *var*, where `var = 0` corresponds to the variable with the most significance with respect to the ordering. .. function:: int fq_nmod_mpoly_is_gen(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) If `var \ge 0`, return `1` if *A* is equal to the `var`-th generator, otherwise return `0`. If `var < 0`, return `1` if the polynomial is equal to any generator, otherwise return `0`. .. function:: void fq_nmod_mpoly_set(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Set *A* to *B*. .. function:: int fq_nmod_mpoly_equal(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Return `1` if *A* is equal to *B*, else return `0`. .. function:: void fq_nmod_mpoly_swap(fq_nmod_mpoly_t A, fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Efficiently swap *A* and *B*. Constants -------------------------------------------------------------------------------- .. function:: int fq_nmod_mpoly_is_fq_nmod(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if *A* is a constant, else return `0`. .. function:: void fq_nmod_mpoly_get_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Assuming that *A* is a constant, set *c* to this constant. This function throws if *A* is not a constant. .. function:: void fq_nmod_mpoly_set_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_set_ui(fq_nmod_mpoly_t A, ulong c, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the constant *c*. .. function:: void fq_nmod_mpoly_set_fq_nmod_gen(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the constant given by :func:`fq_nmod_gen`. .. function:: void fq_nmod_mpoly_zero(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the constant `0`. .. function:: void fq_nmod_mpoly_one(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the constant `1`. .. function:: int fq_nmod_mpoly_equal_fq_nmod(const fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) Return `1` if *A* is equal to the constant *c*, else return `0`. .. function:: int fq_nmod_mpoly_is_zero(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if *A* is the constant `0`, else return `0`. .. function:: int fq_nmod_mpoly_is_one(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if *A* is the constant `1`, else return `0`. Degrees -------------------------------------------------------------------------------- .. function:: int fq_nmod_mpoly_degrees_fit_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if the degrees of *A* with respect to each variable fit into an ``slong``, otherwise return `0`. .. function:: void fq_nmod_mpoly_degrees_fmpz(fmpz ** degs, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_degrees_si(slong * degs, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Set *degs* to the degrees of *A* with respect to each variable. If *A* is zero, all degrees are set to `-1`. .. function:: void fq_nmod_mpoly_degree_fmpz(fmpz_t deg, const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) slong fq_nmod_mpoly_degree_si(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) Either return or set *deg* to the degree of *A* with respect to the variable of index *var*. If *A* is zero, the degree is defined to be `-1`. .. function:: int fq_nmod_mpoly_total_degree_fits_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if the total degree of *A* fits into an ``slong``, otherwise return `0`. .. function:: void fq_nmod_mpoly_total_degree_fmpz(fmpz_t tdeg, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) slong fq_nmod_mpoly_total_degree_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Either return or set *tdeg* to the total degree of *A*. If *A* is zero, the total degree is defined to be `-1`. .. function:: void fq_nmod_mpoly_used_vars(int * used, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) For each variable index `i`, set ``used[i]`` to nonzero if the variable of index `i` appears in *A* and to zero otherwise. Coefficients -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_get_coeff_fq_nmod_monomial(fq_nmod_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t M, const fq_nmod_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set *c* to the coefficient of the corresponding monomial in *A*. This function throws if *M* is not a monomial. .. function:: void fq_nmod_mpoly_set_coeff_fq_nmod_monomial(fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_t M, const fq_nmod_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set the coefficient of the corresponding monomial in *A* to *c*. This function throws if *M* is not a monomial. .. function:: void fq_nmod_mpoly_get_coeff_fq_nmod_fmpz(fq_nmod_t c, const fq_nmod_mpoly_t A, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_get_coeff_fq_nmod_ui(fq_nmod_t c, const fq_nmod_mpoly_t A, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) Set *c* to the coefficient of the monomial with exponent vector *exp*. .. function:: void fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_set_coeff_fq_nmod_ui(fq_nmod_mpoly_t A, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) Set the coefficient of the monomial with exponent *exp* to *c*. .. function:: void fq_nmod_mpoly_get_coeff_vars_ui(fq_nmod_mpoly_t C, const fq_nmod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fq_nmod_mpoly_ctx_t ctx) Set *C* to the coefficient of *A* with respect to the variables in *vars* with powers in the corresponding array *exps*. Both *vars* and *exps* point to array of length *length*. It is assumed that `0 < length \le nvars(A)` and that the variables in *vars* are distinct. Comparison -------------------------------------------------------------------------------- .. function:: int fq_nmod_mpoly_cmp(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Return `1` (resp. `-1`, or `0`) if *A* is after (resp. before, same as) *B* in some arbitrary but fixed total ordering of the polynomials. This ordering agrees with the usual ordering of monomials when *A* and *B* are both monomials. Container operations -------------------------------------------------------------------------------- These functions deal with violations of the internal canonical representation. If a term index is negative or not strictly less than the length of the polynomial, the function will throw. .. function:: int fq_nmod_mpoly_is_canonical(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if *A* is in canonical form. Otherwise, return `0`. To be in canonical form, all of the terms must have nonzero coefficients, and the terms must be sorted from greatest to least. .. function:: slong fq_nmod_mpoly_length(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return the number of terms in *A*. If the polynomial is in canonical form, this will be the number of nonzero coefficients. .. function:: void fq_nmod_mpoly_resize(fq_nmod_mpoly_t A, slong new_length, const fq_nmod_mpoly_ctx_t ctx) Set the length of *A* to ``new_length``. Terms are either deleted from the end, or new zero terms are appended. .. function:: void fq_nmod_mpoly_get_term_coeff_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) Set *c* to the coefficient of the term of index *i*. .. function:: void fq_nmod_mpoly_set_term_coeff_ui(fq_nmod_mpoly_t A, slong i, ulong c, const fq_nmod_mpoly_ctx_t ctx) Set the coefficient of the term of index *i* to *c*. .. function:: int fq_nmod_mpoly_term_exp_fits_si(const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) int fq_nmod_mpoly_term_exp_fits_ui(const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) Return `1` if all entries of the exponent vector of the term of index `i` fit into an ``slong`` (resp. a ``ulong``). Otherwise, return `0`. .. function:: void fq_nmod_mpoly_get_term_exp_fmpz(fmpz ** exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_get_term_exp_ui(ulong * exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_get_term_exp_si(slong * exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) Set *exp* to the exponent vector of the term of index *i*. The ``_ui`` (resp. ``_si``) version throws if any entry does not fit into a ``ulong`` (resp. ``slong``). .. function:: ulong fq_nmod_mpoly_get_term_var_exp_ui(const fq_nmod_mpoly_t A, slong i, slong var, const fq_nmod_mpoly_ctx_t ctx) slong fq_nmod_mpoly_get_term_var_exp_si(const fq_nmod_mpoly_t A, slong i, slong var, const fq_nmod_mpoly_ctx_t ctx) Return the exponent of the variable *var* of the term of index *i*. This function throws if the exponent does not fit into a ``ulong`` (resp. ``slong``). .. function:: void fq_nmod_mpoly_set_term_exp_fmpz(fq_nmod_mpoly_t A, slong i, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_set_term_exp_ui(fq_nmod_mpoly_t A, slong i, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) Set the exponent of the term of index *i* to *exp*. .. function:: void fq_nmod_mpoly_get_term(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) Set *M* to the term of index *i* in *A*. .. function:: void fq_nmod_mpoly_get_term_monomial(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void fq_nmod_mpoly_push_term_fq_nmod_fmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_push_term_fq_nmod_ffmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_push_term_fq_nmod_ui(fq_nmod_mpoly_t A, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) Append a term to *A* with coefficient *c* and exponent vector *exp*. This function runs in constant average time. .. function:: void fq_nmod_mpoly_sort_terms(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Sort the terms of *A* into the canonical ordering dictated by the ordering in *ctx*. This function simply reorders the terms: It does not combine like terms, nor does it delete terms with coefficient zero. This function runs in linear time in the bit size of *A*. .. function:: void fq_nmod_mpoly_combine_like_terms(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Combine adjacent like terms in *A* and delete terms with coefficient zero. If the terms of *A* were sorted to begin with, the result will be in canonical form. This function runs in linear time in the bit size of *A*. .. function:: void fq_nmod_mpoly_reverse(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the reversal of *B*. Random generation -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_randtest_bound(fq_nmod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const fq_nmod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bound - 1]``. The exponents of each variable are generated by calls to ``n_randint(state, exp_bound)``. .. function:: void fq_nmod_mpoly_randtest_bounds(fq_nmod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const fq_nmod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bounds[i] - 1]``. The exponents of the variable of index *i* are generated by calls to ``n_randint(state, exp_bounds[i])``. .. function:: void fq_nmod_mpoly_randtest_bits(fq_nmod_mpoly_t A, flint_rand_t state, slong length, mp_limb_t exp_bits, const fq_nmod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents whose packed form does not exceed the given bit count. Addition/Subtraction -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_add_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t C, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `B + c`. .. function:: void fq_nmod_mpoly_sub_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t C, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `B - c`. .. function:: void fq_nmod_mpoly_add(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `B + C`. .. function:: void fq_nmod_mpoly_sub(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `B - C`. Scalar operations -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_neg(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `-B`. .. function:: void fq_nmod_mpoly_scalar_mul_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `B \times c`. .. function:: void fq_nmod_mpoly_make_monic(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Set *A* to *B* divided by the leading coefficient of *B*. This throws if *B* is zero. Differentiation -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_derivative(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the derivative of *B* with respect to the variable of index *var*. Evaluation -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: void fq_nmod_mpoly_evaluate_all_fq_nmod(fq_nmod_t ev, const fq_nmod_mpoly_t A, fq_nmod_struct * const * vals, const fq_nmod_mpoly_ctx_t ctx) Set *ev* the evaluation of *A* where the variables are replaced by the corresponding elements of the array *vals*. .. function:: void fq_nmod_mpoly_evaluate_one_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_t val, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the evaluation of *B* where the variable of index *var* is replaced by *val*. .. function:: int fq_nmod_mpoly_compose_fq_nmod_poly(fq_nmod_poly_t A, const fq_nmod_mpoly_t B, fq_nmod_poly_struct * const * C, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. The context object of *B* is *ctxB*. Return `1` for success and `0` for failure. .. function:: int fq_nmod_mpoly_compose_fq_nmod_mpoly(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, fq_nmod_mpoly_struct * const * C, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. Both *A* and the elements of *C* have context object *ctxAC*, while *B* has context object *ctxB*. Neither *A* nor *B* is allowed to alias any other polynomial. Return `1` for success and `0` for failure. .. function:: void fq_nmod_mpoly_compose_fq_nmod_mpoly_gen(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const slong * c, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variable of index *i* in *ctxB* is replaced by the variable of index ``c[i]`` in *ctxAC*. The length of the array *C* is the number of variables in *ctxB*. If any ``c[i]`` is negative, the corresponding variable of *B* is replaced by zero. Otherwise, it is expected that ``c[i]`` is less than the number of variables in *ctxAC*. Multiplication -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_mul(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx) Set *A* to *B* times *C*. Powering -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: int fq_nmod_mpoly_pow_fmpz(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz_t k, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `B` raised to the *k*-th power. Return `1` for success and `0` for failure. .. function:: int fq_nmod_mpoly_pow_ui(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, ulong k, const fq_nmod_mpoly_ctx_t ctx) Set *A* to `B` raised to the *k*-th power. Return `1` for success and `0` for failure. Division -------------------------------------------------------------------------------- .. function:: int fq_nmod_mpoly_divides(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) If *A* is divisible by *B*, set *Q* to the exact quotient and return `1`. Otherwise, set *Q* to zero and return `0`. .. function:: void fq_nmod_mpoly_div(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Set *Q* to the quotient of *A* by *B*, discarding the remainder. .. function:: void fq_nmod_mpoly_divrem(fq_nmod_mpoly_t Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Set *Q* and *R* to the quotient and remainder of *A* divided by *B*. .. function:: void fq_nmod_mpoly_divrem_ideal(fq_nmod_mpoly_struct ** Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, fq_nmod_mpoly_struct * const * B, slong len, const fq_nmod_mpoly_ctx_t ctx) This function is as per :func:`fq_nmod_mpoly_divrem` except that it takes an array of divisor polynomials *B* and it returns an array of quotient polynomials *Q*. The number of divisor (and hence quotient) polynomials, is given by *len*. Greatest Common Divisor -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_term_content(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Set *M* to the GCD of the terms of *A*. If *A* is zero, *M* will be zero. Otherwise, *M* will be a monomial with coefficient one. .. function:: int fq_nmod_mpoly_content_vars(fq_nmod_mpoly_t g, const fq_nmod_mpoly_t A, slong * vars, slong vars_length, const fq_nmod_mpoly_ctx_t ctx) Set *g* to the GCD of the coefficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon success, *g* will be independent of the variables *vars*. .. function:: int fq_nmod_mpoly_gcd(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Try to set *G* to the monic GCD of *A* and *B*. The GCD of zero and zero is defined to be zero. If the return is `1` the function was successful. Otherwise the return is `0` and *G* is left untouched. .. function:: int fq_nmod_mpoly_gcd_cofactors(fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Do the operation of :func:`fq_nmod_mpoly_gcd` and also compute `Abar = A/G` and `Bbar = B/G` if successful. .. function:: int fq_nmod_mpoly_gcd_brown(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) int fq_nmod_mpoly_gcd_hensel(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) int fq_nmod_mpoly_gcd_zippel(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) Try to set *G* to the GCD of *A* and *B* using various algorithms. .. function:: int fq_nmod_mpoly_resultant(fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) Try to set *R* to the resultant of *A* and *B* with respect to the variable of index *var*. .. function:: int fq_nmod_mpoly_discriminant(fq_nmod_mpoly_t D, const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) Try to set *D* to the discriminant of *A* with respect to the variable of index *var*. Square Root -------------------------------------------------------------------------------- .. function:: int fq_nmod_mpoly_sqrt(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) If `Q^2=A` has a solution, set `Q` to a solution and return `1`, otherwise return `0` and set `Q` to zero. .. function:: int fq_nmod_mpoly_is_square(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if *A* is a perfect square, otherwise return `0`. .. function:: int fq_nmod_mpoly_quadratic_root(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) If `Q^2+AQ=B` has a solution, set `Q` to a solution and return `1`, otherwise return `0`. Univariate Functions -------------------------------------------------------------------------------- An ``fq_nmod_mpoly_univar_t`` holds a univariate polynomial in some main variable with ``fq_nmod_mpoly_t`` coefficients in the remaining variables. These functions are useful when one wants to rewrite an element of `\mathbb{F}_q[x_1, \dots, x_m]` as an element of `(\mathbb{F}_q[x_1, \dots, x_{v-1}, x_{v+1}, \dots, x_m])[x_v]` and vice versa. .. function:: void fq_nmod_mpoly_univar_init(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) Initialize *A*. .. function:: void fq_nmod_mpoly_univar_clear(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) Clear *A*. .. function:: void fq_nmod_mpoly_univar_swap(fq_nmod_mpoly_univar_t A, fq_nmod_mpoly_univar_t B, const fq_nmod_mpoly_ctx_t ctx) Swap *A* and `B`. .. function:: void fq_nmod_mpoly_to_univar(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) Set *A* to a univariate form of *B* by pulling out the variable of index *var*. The coefficients of *A* will still belong to the content *ctx* but will not depend on the variable of index *var*. .. function:: void fq_nmod_mpoly_from_univar(fq_nmod_mpoly_t A, const fq_nmod_mpoly_univar_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) Set *A* to the normal form of *B* by putting in the variable of index *var*. This function is undefined if the coefficients of *B* depend on the variable of index *var*. .. function:: int fq_nmod_mpoly_univar_degree_fits_si(const fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) Return `1` if the degree of *A* with respect to the main variable fits an ``slong``. Otherwise, return `0`. .. function:: slong fq_nmod_mpoly_univar_length(const fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) Return the number of terms in *A* with respect to the main variable. .. function:: slong fq_nmod_mpoly_univar_get_term_exp_si(fq_nmod_mpoly_univar_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) Return the exponent of the term of index *i* of *A*. .. function:: void fq_nmod_mpoly_univar_get_term_coeff(fq_nmod_mpoly_t c, const fq_nmod_mpoly_univar_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_univar_swap_term_coeff(fq_nmod_mpoly_t c, fq_nmod_mpoly_univar_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) Set (resp. swap) *c* to (resp. with) the coefficient of the term of index *i* of *A*. flint-3.1.3/doc/source/fq_nmod_mpoly_factor.rst000066400000000000000000000064461461254215100216450ustar00rootroot00000000000000.. _fq_nmod-mpoly-factor: **fq_nmod_mpoly_factor.h** -- factorisation of multivariate polynomials over finite fields of word-sized characteristic ======================================================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_mpoly_factor_struct A struct for holding a factored polynomial. There is a single constant and a product of bases to corresponding exponents. .. type:: fq_nmod_mpoly_factor_t An array of length `1` of ``fq_nmod_mpoly_factor_struct``. Memory management -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_factor_init(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) Initialise *f*. .. function:: void fq_nmod_mpoly_factor_clear(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) Clear *f*. Basic manipulation -------------------------------------------------------------------------------- .. function:: void fq_nmod_mpoly_factor_swap(fq_nmod_mpoly_factor_t f, fq_nmod_mpoly_factor_t g, const fq_nmod_mpoly_ctx_t ctx) Efficiently swap *f* and *g*. .. function:: slong fq_nmod_mpoly_factor_length(const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) Return the length of the product in *f*. .. function:: void fq_nmod_mpoly_factor_get_constant_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) Set `c` to the constant of *f*. .. function:: void fq_nmod_mpoly_factor_get_base(fq_nmod_mpoly_t p, const fq_nmod_mpoly_factor_t f, slong i, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_factor_swap_base(fq_nmod_mpoly_t p, const fq_nmod_mpoly_factor_t f, slong i, const fq_nmod_mpoly_ctx_t ctx) Set (resp. swap) *B* to (resp. with) the base of the term of index *i* in *A*. .. function:: slong fq_nmod_mpoly_factor_get_exp_si(fq_nmod_mpoly_factor_t f, slong i, const fq_nmod_mpoly_ctx_t ctx) Return the exponent of the term of index *i* in *A*. It is assumed to fit an ``slong``. .. function:: void fq_nmod_mpoly_factor_sort(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) Sort the product of *f* first by exponent and then by base. Factorisation -------------------------------------------------------------------------------- A return of `1` indicates that the function was successful. Otherwise, the return is `0` and *f* is undefined. None of these functions multiply *f* by *A*: *f* is simply set to a factorisation of *A*, and thus these functions should not depend on the initial value of the output *f*. .. function:: int fq_nmod_mpoly_factor_squarefree(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are primitive and pairwise relatively prime. If the product of all irreducible factors with a given exponent is desired, it is recommended to call :func:`fq_nmod_mpoly_factor_sort` and then multiply the bases with the desired exponent. .. function:: int fq_nmod_mpoly_factor(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are irreducible. flint-3.1.3/doc/source/fq_nmod_poly.rst000066400000000000000000002112231461254215100201210ustar00rootroot00000000000000.. _fq-nmod-poly: **fq_nmod_poly.h** -- univariate polynomials over finite fields (word-size characteristic) ========================================================================================== We represent a polynomial in `\mathbf{F}_q[X]` as a ``struct`` which includes an array ``coeffs`` with the coefficients, as well as the length ``length`` and the number ``alloc`` of coefficients for which memory has been allocated. As a data structure, we call this polynomial *normalised* if the top coefficient is non-zero. Unless otherwise stated here, all functions that deal with polynomials assume that the `\mathbf{F}_q` context of said polynomials are compatible, i.e., it assumes that the fields are generated by the same polynomial. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_poly_struct .. type:: fq_nmod_poly_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_init(fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Initialises ``poly`` for use, with context ctx, and setting its length to zero. A corresponding call to :func:`fq_nmod_poly_clear` must be made after finishing with the ``fq_nmod_poly_t`` to free the memory used by the polynomial. .. function:: void fq_nmod_poly_init2(fq_nmod_poly_t poly, slong alloc, const fq_nmod_ctx_t ctx) Initialises ``poly`` with space for at least ``alloc`` coefficients and sets the length to zero. The allocated coefficients are all set to zero. A corresponding call to :func:`fq_nmod_poly_clear` must be made after finishing with the ``fq_nmod_poly_t`` to free the memory used by the polynomial. .. function:: void fq_nmod_poly_realloc(fq_nmod_poly_t poly, slong alloc, const fq_nmod_ctx_t ctx) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` the polynomial is first truncated to length ``alloc``. .. function:: void fq_nmod_poly_fit_length(fq_nmod_poly_t poly, slong len, const fq_nmod_ctx_t ctx) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where ``fit_length`` is called many times in small increments by at least doubling the number of allocated coefficients when length is larger than the number of coefficients currently allocated. .. function:: void _fq_nmod_poly_set_length(fq_nmod_poly_t poly, slong newlen, const fq_nmod_ctx_t ctx) Sets the coefficients of ``poly`` beyond ``len`` to zero and sets the length of ``poly`` to ``len``. .. function:: void fq_nmod_poly_clear(fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Clears the given polynomial, releasing any memory used. It must be reinitialised in order to be used again. .. function:: void _fq_nmod_poly_normalise(fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Sets the length of ``poly`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void _fq_nmod_poly_normalise2(const fq_nmod_struct * poly, slong * length, const fq_nmod_ctx_t ctx) Sets the length ``length`` of ``(poly,length)`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void fq_nmod_poly_truncate(fq_nmod_poly_t poly, slong newlen, const fq_nmod_ctx_t ctx) Truncates the polynomial to length at most ``n``. .. function:: void fq_nmod_poly_set_trunc(fq_nmod_poly_t poly1, fq_nmod_poly_t poly2, slong newlen, const fq_nmod_ctx_t ctx) Sets ``poly1`` to ``poly2`` truncated to length `n`. .. function:: void _fq_nmod_poly_reverse(fq_nmod_struct * output, const fq_nmod_struct * input, slong len, slong m, const fq_nmod_ctx_t ctx) Sets ``output`` to the reverse of ``input``, which is of length ``len``, but thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary. The length ``m`` must be non-negative, but there are no other restrictions. The polynomial ``output`` must have space for ``m`` coefficients. .. function:: void fq_nmod_poly_reverse(fq_nmod_poly_t output, const fq_nmod_poly_t input, slong m, const fq_nmod_ctx_t ctx) Sets ``output`` to the reverse of ``input``, thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary). The length ``m`` must be non-negative, but there are no other restrictions. The output polynomial will be set to length ``m`` and then normalised. Polynomial parameters -------------------------------------------------------------------------------- .. function:: slong fq_nmod_poly_degree(const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: slong fq_nmod_poly_length(const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Returns the length of the polynomial ``poly``. .. function:: fq_nmod_struct * fq_nmod_poly_lead(const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Returns a pointer to the leading coefficient of ``poly``, or ``NULL`` if ``poly`` is the zero polynomial. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_randtest(fq_nmod_poly_t f, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx) Sets `f` to a random polynomial of length at most ``len`` with entries in the field described by ``ctx``. .. function:: void fq_nmod_poly_randtest_not_zero(fq_nmod_poly_t f, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx) Same as ``fq_nmod_poly_randtest`` but guarantees that the polynomial is not zero. .. function:: void fq_nmod_poly_randtest_monic(fq_nmod_poly_t f, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx) Sets `f` to a random monic polynomial of length ``len`` with entries in the field described by ``ctx``. .. function:: void fq_nmod_poly_randtest_irreducible(fq_nmod_poly_t f, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx) Sets `f` to a random monic, irreducible polynomial of length ``len`` with entries in the field described by ``ctx``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_set(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_ctx_t ctx) Sets ``(rop, len``) to ``(op, len)``. .. function:: void fq_nmod_poly_set(fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, const fq_nmod_ctx_t ctx) Sets the polynomial ``poly1`` to the polynomial ``poly2``. .. function:: void fq_nmod_poly_set_fq_nmod(fq_nmod_poly_t poly, const fq_nmod_t c, const fq_nmod_ctx_t ctx) Sets the polynomial ``poly`` to ``c``. .. function:: void fq_nmod_poly_set_fmpz_mod_poly(fq_nmod_poly_t rop, const fmpz_mod_poly_t op, const fq_nmod_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op`` .. function:: void fq_nmod_poly_set_nmod_poly(fq_nmod_poly_t rop, const nmod_poly_t op, const fq_nmod_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op`` .. function:: void fq_nmod_poly_swap(fq_nmod_poly_t op1, fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Swaps the two polynomials ``op1`` and ``op2``. .. function:: void _fq_nmod_poly_zero(fq_nmod_struct * rop, slong len, const fq_nmod_ctx_t ctx) Sets ``(rop, len)`` to the zero polynomial. .. function:: void fq_nmod_poly_zero(fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Sets ``poly`` to the zero polynomial. .. function:: void fq_nmod_poly_one(fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Sets ``poly`` to the constant polynomial `1`. .. function:: void fq_nmod_poly_gen(fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Sets ``poly`` to the polynomial `x`. .. function:: void fq_nmod_poly_make_monic(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``op``, normed to have leading coefficient 1. .. function:: void _fq_nmod_poly_make_monic(fq_nmod_struct * rop, const fq_nmod_struct * op, slong length, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``(op,length)``, normed to have leading coefficient 1. Assumes that ``rop`` has enough space for the polynomial, assumes that ``op`` is not zero (and thus has an invertible leading coefficient). Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_get_coeff(fq_nmod_t x, const fq_nmod_poly_t poly, slong n, const fq_nmod_ctx_t ctx) Sets `x` to the coefficient of `X^n` in ``poly``. .. function:: void fq_nmod_poly_set_coeff(fq_nmod_poly_t poly, slong n, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Sets the coefficient of `X^n` in ``poly`` to `x`. .. function:: void fq_nmod_poly_set_coeff_fmpz(fq_nmod_poly_t poly, slong n, const fmpz_t x, const fq_nmod_ctx_t ctx) Sets the coefficient of `X^n` in the polynomial to `x`, assuming `n \geq 0`. Comparison -------------------------------------------------------------------------------- .. function:: int fq_nmod_poly_equal(const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, const fq_nmod_ctx_t ctx) Returns nonzero if the two polynomials ``poly1`` and ``poly2`` are equal, otherwise return zero. .. function:: int fq_nmod_poly_equal_trunc(const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, slong n, const fq_nmod_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length `n` and return nonzero if they are equal, otherwise return zero. .. function:: int fq_nmod_poly_is_zero(const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Returns whether the polynomial ``poly`` is the zero polynomial. .. function:: int fq_nmod_poly_is_one(const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the constant polynomial `1`. .. function:: int fq_nmod_poly_is_gen(const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the polynomial `x`. .. function:: int fq_nmod_poly_is_unit(const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Returns whether the polynomial ``poly`` is a unit in the polynomial ring `\mathbf{F}_q[X]`, i.e. if it has degree `0` and is non-zero. .. function:: int fq_nmod_poly_equal_fq_nmod(const fq_nmod_poly_t poly, const fq_nmod_t c, const fq_nmod_ctx_t ctx) Returns whether the polynomial ``poly`` is equal the (constant) `\mathbf{F}_q` element ``c`` Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_add(fq_nmod_struct * res, const fq_nmod_struct * poly1, slong len1, const fq_nmod_struct * poly2, slong len2, const fq_nmod_ctx_t ctx) Sets ``res`` to the sum of ``(poly1,len1)`` and ``(poly2,len2)``. .. function:: void fq_nmod_poly_add(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, const fq_nmod_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``poly2``. .. function:: void fq_nmod_poly_add_si(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, slong c, const fq_nmod_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``c``. .. function:: void fq_nmod_poly_add_series(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, slong n, const fq_nmod_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the sum. .. function:: void _fq_nmod_poly_sub(fq_nmod_struct * res, const fq_nmod_struct * poly1, slong len1, const fq_nmod_struct * poly2, slong len2, const fq_nmod_ctx_t ctx) Sets ``res`` to the difference of ``(poly1,len1)`` and ``(poly2,len2)``. .. function:: void fq_nmod_poly_sub(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, const fq_nmod_ctx_t ctx) Sets ``res`` to the difference of ``poly1`` and ``poly2``. .. function:: void fq_nmod_poly_sub_series(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, slong n, const fq_nmod_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the difference. .. function:: void _fq_nmod_poly_neg(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_ctx_t ctx) Sets ``rop`` to the additive inverse of ``(poly,len)``. .. function:: void fq_nmod_poly_neg(fq_nmod_poly_t res, const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Sets ``res`` to the additive inverse of ``poly``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_scalar_mul_fq_nmod(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Sets ``(rop,len)`` to the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void fq_nmod_poly_scalar_mul_fq_nmod(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_nmod_poly_scalar_addmul_fq_nmod(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Adds to ``(rop,len)`` the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. In particular, assumes the same length for ``op`` and ``rop``. .. function:: void fq_nmod_poly_scalar_addmul_fq_nmod(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Adds to ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_nmod_poly_scalar_submul_fq_nmod(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Subtracts from ``(rop,len)`` the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. In particular, assumes the same length for ``op`` and ``rop``. .. function:: void fq_nmod_poly_scalar_submul_fq_nmod(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Subtracts from ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_nmod_poly_scalar_div_fq(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Sets ``(rop,len)`` to the quotient of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. An exception is raised if ``x`` is zero. .. function:: void fq_nmod_poly_scalar_div_fq(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_t x, const fq_nmod_ctx_t ctx) Sets ``rop`` to the quotient of ``op`` by the scalar ``x``, in the context defined by ``ctx``. An exception is raised if ``x`` is zero. Multiplication -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_mul_classical(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, assuming that ``len1`` is at least ``len2`` and neither is zero. Permits zero padding. Does not support aliasing of ``rop`` with either ``op1`` or ``op2``. .. function:: void fq_nmod_poly_mul_classical(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using classical polynomial multiplication. .. function:: void _fq_nmod_poly_mul_reorder(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, assuming that ``len1`` and ``len2`` are non-zero. Permits zero padding. Supports aliasing. .. function:: void fq_nmod_poly_mul_reorder(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reordering the two indeterminates `X` and `Y` when viewing the polynomials as elements of `\mathbf{F}_p[X,Y]`. Suppose `\mathbf{F}_q = \mathbf{F}_p[X]/ (f(X))` and recall that elements of `\mathbf{F}_q` are internally represented by elements of type ``fmpz_poly``. For small degree extensions but polynomials in `\mathbf{F}_q[Y]` of large degree `n`, we change the representation to .. math:: \begin{split} g(Y) & = \sum_{i=0}^{n} a_i(X) Y^i \\ & = \sum_{j=0}^{d} \sum_{i=0}^{n} \text{Coeff}(a_i(X), j) Y^i. \end{split} This allows us to use a poor algorithm (such as classical multiplication) in the `X`-direction and leverage the existing fast integer multiplication routines in the `Y`-direction where the polynomial degree `n` is large. .. function:: void _fq_nmod_poly_mul_univariate(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``. Permits zero padding and makes no assumptions on ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_nmod_poly_mul_univariate(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using a bivariate to univariate transformation and reducing this problem to multiplying two univariate polynomials. .. function:: void _fq_nmod_poly_mul_KS(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``. Permits zero padding and places no assumptions on the lengths ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_nmod_poly_mul_KS(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using Kronecker substitution, that is, by encoding each coefficient in `\mathbf{F}_{q}` as an integer and reducing this problem to multiplying two polynomials over the integers. .. function:: void _fq_nmod_poly_mul(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, choosing an appropriate algorithm. Permits zero padding. Does not support aliasing. .. function:: void fq_nmod_poly_mul(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, choosing an appropriate algorithm. .. function:: void _fq_nmod_poly_mullow_classical(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, slong n, const fq_nmod_ctx_t ctx) Sets ``(rop, n)`` to the first `n` coefficients of ``(op1, len1)`` multiplied by ``(op2, len2)``. Assumes ``0 < n <= len1 + len2 - 1``. Assumes neither ``len1`` nor ``len2`` is zero. .. function:: void fq_nmod_poly_mullow_classical(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, slong n, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, computed using the classical or schoolbook method. .. function:: void _fq_nmod_poly_mullow_univariate(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, slong n, const fq_nmod_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``, computed using a bivariate to univariate transformation. Assumes that ``len1`` and ``len2`` are positive, but does allow for the polynomials to be zero-padded. The polynomials may be zero, too. Assumes `n` is positive. Supports aliasing between ``rop``, ``op1`` and ``op2``. .. function:: void fq_nmod_poly_mullow_univariate(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, slong n, const fq_nmod_ctx_t ctx) Sets ``rop`` to the lowest `n` coefficients of the product of ``poly1`` and ``poly2``, computed using a bivariate to univariate transformation. .. function:: void _fq_nmod_poly_mullow_KS(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, slong n, const fq_nmod_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``. Assumes that ``len1`` and ``len2`` are positive, but does allow for the polynomials to be zero-padded. The polynomials may be zero, too. Assumes `n` is positive. Supports aliasing between ``rop``, ``op1`` and ``op2``. .. function:: void fq_nmod_poly_mullow_KS(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, slong n, const fq_nmod_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``. .. function:: void _fq_nmod_poly_mullow(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, slong n, const fq_nmod_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``. Assumes ``0 < n <= len1 + len2 - 1``. Allows for zero-padding in the inputs. Does not support aliasing between the inputs and the output. .. function:: void fq_nmod_poly_mullow(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, slong n, const fq_nmod_ctx_t ctx) Sets ``rop`` to the lowest `n` coefficients of the product of ``op1`` and ``op2``. .. function:: void _fq_nmod_poly_mulhigh_classical(fq_nmod_struct * res, const fq_nmod_struct * poly1, slong len1, const fq_nmod_struct * poly2, slong len2, slong start, const fq_nmod_ctx_t ctx) Computes the product of ``(poly1, len1)`` and ``(poly2, len2)`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Assumes that ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. Algorithm is classical multiplication. .. function:: void fq_nmod_poly_mulhigh_classical(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, slong start, const fq_nmod_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Algorithm is classical multiplication. .. function:: void _fq_nmod_poly_mulhigh(fq_nmod_struct * res, const fq_nmod_struct * poly1, slong len1, const fq_nmod_struct * poly2, slong len2, slong start, fq_nmod_ctx_t ctx) Computes the product of ``(poly1, len1)`` and ``(poly2, len2)`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Assumes that ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. .. function:: void fq_nmod_poly_mulhigh(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, slong start, const fq_nmod_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. .. function:: void _fq_nmod_poly_mulmod(fq_nmod_struct * res, const fq_nmod_struct * poly1, slong len1, const fq_nmod_struct * poly2, slong len2, const fq_nmod_struct * f, slong lenf, const fq_nmod_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``len1 + len2 - lenf > 0``, which is equivalent to requiring that the result will actually be reduced. Otherwise, simply use ``_fq_nmod_poly_mul`` instead. Aliasing of ``f`` and ``res`` is not permitted. .. function:: void fq_nmod_poly_mulmod(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. .. function:: void _fq_nmod_poly_mulmod_preinv(fq_nmod_struct * res, const fq_nmod_struct * poly1, slong len1, const fq_nmod_struct * poly2, slong len2, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * finv, slong lenfinv, const fq_nmod_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``finv`` is the inverse of the reverse of ``f`` mod ``x^lenf``. Aliasing of ``res`` with any of the inputs is not permitted. .. function:: void fq_nmod_poly_mulmod_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t poly1, const fq_nmod_poly_t poly2, const fq_nmod_poly_t f, const fq_nmod_poly_t finv, const fq_nmod_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. ``finv`` is the inverse of the reverse of ``f``. Squaring -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_sqr_classical(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_ctx_t ctx) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``, assuming that ``(op,len)`` is not zero and using classical polynomial multiplication. Permits zero padding. Does not support aliasing of ``rop`` with either ``op1`` or ``op2``. .. function:: void fq_nmod_poly_sqr_classical(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the square of ``op`` using classical polynomial multiplication. .. function:: void _fq_nmod_poly_sqr_KS(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_ctx_t ctx) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``. Permits zero padding and places no assumptions on the lengths ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_nmod_poly_sqr_KS(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the square ``op`` using Kronecker substitution, that is, by encoding each coefficient in `\mathbf{F}_{q}` as an integer and reducing this problem to multiplying two polynomials over the integers. .. function:: void _fq_nmod_poly_sqr(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_ctx_t ctx) Sets ``(rop, 2 * len - 1)`` to the square of ``(op, len)``, choosing an appropriate algorithm. Permits zero padding. Does not support aliasing. .. function:: void fq_nmod_poly_sqr(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the square of ``op``, choosing an appropriate algorithm. Powering -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_pow(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, ulong e, const fq_nmod_ctx_t ctx) Sets ``rop = op^e``, assuming that ``e, len > 0`` and that ``rop`` has space for ``e*(len - 1) + 1`` coefficients. Does not support aliasing. .. function:: void fq_nmod_poly_pow(fq_nmod_poly_t rop, const fq_nmod_poly_t op, ulong e, const fq_nmod_ctx_t ctx) Computes ``rop = op^e``. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void _fq_nmod_poly_powmod_ui_binexp(fq_nmod_struct * res, const fq_nmod_struct * poly, ulong e, const fq_nmod_struct * f, slong lenf, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_nmod_poly_powmod_ui_binexp(fq_nmod_poly_t res, const fq_nmod_poly_t poly, ulong e, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fq_nmod_poly_powmod_ui_binexp_preinv(fq_nmod_struct * res, const fq_nmod_struct * poly, ulong e, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * finv, slong lenfinv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_nmod_poly_powmod_ui_binexp_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t poly, ulong e, const fq_nmod_poly_t f, const fq_nmod_poly_t finv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_nmod_poly_powmod_fmpz_binexp(fq_nmod_struct * res, const fq_nmod_struct * poly, const fmpz_t e, const fq_nmod_struct * f, slong lenf, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_nmod_poly_powmod_fmpz_binexp(fq_nmod_poly_t res, const fq_nmod_poly_t poly, const fmpz_t e, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fq_nmod_poly_powmod_fmpz_binexp_preinv(fq_nmod_struct * res, const fq_nmod_struct * poly, const fmpz_t e, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * finv, slong lenfinv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_nmod_poly_powmod_fmpz_binexp_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t poly, const fmpz_t e, const fq_nmod_poly_t f, const fq_nmod_poly_t finv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_nmod_poly_powmod_fmpz_sliding_preinv(fq_nmod_struct * res, const fq_nmod_struct * poly, const fmpz_t e, ulong k, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * finv, slong lenfinv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using sliding-window exponentiation with window size ``k``. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. If ``k`` is set to zero, then an "optimum" size will be selected automatically base on ``e``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_nmod_poly_powmod_fmpz_sliding_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t poly, const fmpz_t e, ulong k, const fq_nmod_poly_t f, const fq_nmod_poly_t finv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using sliding-window exponentiation with window size ``k``. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. If ``k`` is set to zero, then an "optimum" size will be selected automatically base on ``e``. .. function:: void _fq_nmod_poly_powmod_x_fmpz_preinv(fq_nmod_struct * res, const fmpz_t e, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * finv, slong lenfinv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 2``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_nmod_poly_powmod_x_fmpz_preinv(fq_nmod_poly_t res, const fmpz_t e, const fq_nmod_poly_t f, const fq_nmod_poly_t finv, const fq_nmod_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_nmod_poly_pow_trunc_binexp(fq_nmod_struct * res, const fq_nmod_struct * poly, ulong e, slong trunc, const fq_nmod_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. Uses the binary exponentiation method. .. function:: void fq_nmod_poly_pow_trunc_binexp(fq_nmod_poly_t res, const fq_nmod_poly_t poly, ulong e, slong trunc, const fq_nmod_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Uses the binary exponentiation method. .. function:: void _fq_nmod_poly_pow_trunc(fq_nmod_struct * res, const fq_nmod_struct * poly, ulong e, slong trunc, const fq_nmod_ctx_t mod) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. .. function:: void fq_nmod_poly_pow_trunc(fq_nmod_poly_t res, const fq_nmod_poly_t poly, ulong e, slong trunc, const fq_nmod_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Shifting -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_shift_left(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, slong n, const fq_nmod_ctx_t ctx) Sets ``(rop, len + n)`` to ``(op, len)`` shifted left by `n` coefficients. Inserts zero coefficients at the lower end. Assumes that ``len`` and `n` are positive, and that ``rop`` fits ``len + n`` elements. Supports aliasing between ``rop`` and ``op``. .. function:: void fq_nmod_poly_shift_left(fq_nmod_poly_t rop, const fq_nmod_poly_t op, slong n, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``op`` shifted left by `n` coeffs. Zero coefficients are inserted. .. function:: void _fq_nmod_poly_shift_right(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, slong n, const fq_nmod_ctx_t ctx) Sets ``(rop, len - n)`` to ``(op, len)`` shifted right by `n` coefficients. Assumes that ``len`` and `n` are positive, that ``len > n``, and that ``rop`` fits ``len - n`` elements. Supports aliasing between ``rop`` and ``op``, although in this case the top coefficients of ``op`` are not set to zero. .. function:: void fq_nmod_poly_shift_right(fq_nmod_poly_t rop, const fq_nmod_poly_t op, slong n, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``op`` shifted right by `n` coefficients. If `n` is equal to or greater than the current length of ``op``, ``rop`` is set to the zero polynomial. Norms -------------------------------------------------------------------------------- .. function:: slong _fq_nmod_poly_hamming_weight(const fq_nmod_struct * op, slong len, const fq_nmod_ctx_t ctx) Returns the number of non-zero entries in ``(op, len)``. .. function:: slong fq_nmod_poly_hamming_weight(const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Returns the number of non-zero entries in the polynomial ``op``. Euclidean division -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_divrem(fq_nmod_struct * Q, fq_nmod_struct * R, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_t invB, const fq_nmod_ctx_t ctx) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible and that ``invB`` is its inverse. Assumes that `\operatorname{len}(A), \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. `R` and `A` may be aliased, but apart from this no aliasing of input and output operands is allowed. .. function:: void fq_nmod_poly_divrem(fq_nmod_poly_t Q, fq_nmod_poly_t R, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible. This can be taken for granted the context is for a finite field, that is, when `p` is prime and `f(X)` is irreducible. .. function:: void fq_nmod_poly_divrem_f(fq_nmod_t f, fq_nmod_poly_t Q, fq_nmod_poly_t R, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Either finds a non-trivial factor `f` of the modulus of ``ctx``, or computes `Q`, `R` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. If the leading coefficient of `B` is invertible, the division with remainder operation is carried out, `Q` and `R` are computed correctly, and `f` is set to `1`. Otherwise, `f` is set to a non-trivial factor of the modulus and `Q` and `R` are not touched. Assumes that `B` is non-zero. .. function:: void _fq_nmod_poly_rem(fq_nmod_struct * R, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_t invB, const fq_nmod_ctx_t ctx) Sets ``R`` to the remainder of the division of ``(A,lenA)`` by ``(B,lenB)``. Assumes that the leading coefficient of ``(B,lenB)`` is invertible and that ``invB`` is its inverse. .. function:: void fq_nmod_poly_rem(fq_nmod_poly_t R, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Sets ``R`` to the remainder of the division of ``A`` by ``B`` in the context described by ``ctx``. .. function:: void _fq_nmod_poly_div(fq_nmod_struct * Q, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_t invB, const fq_nmod_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)` but only sets ``(Q, lenA - lenB + 1)``. Allows zero-padding in `A` but not in `B`. Assumes that the leading coefficient of `B` is a unit. .. function:: void fq_nmod_poly_div(fq_nmod_poly_t Q, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Notionally finds polynomials `Q` and `R` such that `A = B Q + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only ``Q``. If `\operatorname{len}(B) = 0` an exception is raised. .. function:: void _fq_nmod_poly_div_newton_n_preinv(fq_nmod_struct * Q, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_struct * Binv, slong lenBinv, const fq_nmod_ctx_t ctx) Notionally computes polynomials `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where ``A`` is of length ``lenA`` and ``B`` is of length ``lenB``, but return only `Q`. We require that `Q` have space for ``lenA - lenB + 1`` coefficients and assume that the leading coefficient of `B` is a unit. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void fq_nmod_poly_div_newton_n_preinv(fq_nmod_poly_t Q, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_poly_t Binv, const fq_nmod_ctx_t ctx) Notionally computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only `Q`. We assume that the leading coefficient of `B` is a unit and that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void _fq_nmod_poly_divrem_newton_n_preinv(fq_nmod_struct * Q, fq_nmod_struct * R, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_struct * Binv, slong lenBinv, const fq_nmod_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where `A` is of length ``lenA`` and `B` is of length ``lenB``. We require that `Q` have space for ``lenA - lenB + 1`` coefficients. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to call :func:`div_newton_preinv` and then multiply out and compute the remainder. .. function:: void fq_nmod_poly_divrem_newton_n_preinv(fq_nmod_poly_t Q, fq_nmod_poly_t R, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_poly_t Binv, const fq_nmod_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. We assume `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to call :func:`div_newton` and then multiply out and compute the remainder. .. function:: void _fq_nmod_poly_inv_series_newton(fq_nmod_struct * Qinv, const fq_nmod_struct * Q, slong n, const fq_nmod_t cinv, const fq_nmod_ctx_t ctx) Given ``Q`` of length ``n`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void fq_nmod_poly_inv_series_newton(fq_nmod_poly_t Qinv, const fq_nmod_poly_t Q, slong n, const fq_nmod_ctx_t ctx) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void _fq_nmod_poly_inv_series(fq_nmod_struct * Qinv, const fq_nmod_struct * Q, slong n, const fq_nmod_t cinv, const fq_nmod_ctx_t ctx) Given ``Q`` of length ``n`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. .. function:: void fq_nmod_poly_inv_series(fq_nmod_poly_t Qinv, const fq_nmod_poly_t Q, slong n, const fq_nmod_ctx_t ctx) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. .. function:: void _fq_nmod_poly_div_series(fq_nmod_struct * Q, const fq_nmod_struct * A, mp_limb_signed_t Alen, const fq_nmod_struct * B, mp_limb_signed_t Blen, mp_limb_signed_t n, const fq_nmod_ctx_t ctx) Set ``(Q, n)`` to the quotient of the series ``(A, Alen``) and ``(B, Blen)`` assuming ``Alen, Blen <= n``. We assume the bottom coefficient of ``B`` is invertible. .. function:: void fq_nmod_poly_div_series(fq_nmod_poly_t Q, const fq_nmod_poly_t A, const fq_nmod_poly_t B, slong n, fq_nmod_ctx_t ctx) Set `Q` to the quotient of the series `A` by `B`, thinking of the series as though they were of length `n`. We assume that the bottom coefficient of `B` is invertible. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_gcd(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the greatest common divisor of ``op1`` and ``op2``, using the either the Euclidean or HGCD algorithm. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. .. function:: slong _fq_nmod_poly_gcd(fq_nmod_struct * G, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_ctx_t ctx) Computes the GCD of `A` of length ``lenA`` and `B` of length ``lenB``, where ``lenA >= lenB > 0`` and sets `G` to it. The length of the GCD `G` is returned by the function. No attempt is made to make the GCD monic. It is required that `G` have space for ``lenB`` coefficients. .. function:: slong _fq_nmod_poly_gcd_euclidean_f(fq_nmod_t f, fq_nmod_struct * G, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `(A,\operatorname{len}(A))` and `(B, \operatorname{len}(B))` and returns its length, or sets `f` to a non-trivial factor of the modulus of ``ctx`` and leaves the contents of the vector `(G, lenB)` undefined. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that the vector `G` has space for sufficiently many coefficients. .. function:: void fq_nmod_poly_gcd_euclidean_f(fq_nmod_t f, fq_nmod_poly_t G, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `A` and `B` or sets `f` to a factor of the modulus of ``ctx``. .. function:: slong _fq_nmod_poly_xgcd(fq_nmod_struct * G, fq_nmod_struct * S, fq_nmod_struct * T, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_ctx_t ctx) Computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void fq_nmod_poly_xgcd(fq_nmod_poly_t G, fq_nmod_poly_t S, fq_nmod_poly_t T, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. .. function:: slong _fq_nmod_poly_xgcd_euclidean_f(fq_nmod_t f, fq_nmod_struct * G, fq_nmod_struct * S, fq_nmod_struct * T, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_ctx_t ctx) Either sets `f = 1` and computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`; otherwise, sets `f` to a non-trivial factor of the modulus of ``ctx`` and leaves `G`, `S`, and `T` undefined. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void fq_nmod_poly_xgcd_euclidean_f(fq_nmod_t f, fq_nmod_poly_t G, fq_nmod_poly_t S, fq_nmod_poly_t T, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Either sets `f = 1` and computes the GCD of `A` and `B` or sets `f` to a non-trivial factor of the modulus of ``ctx``. If the GCD is computed, polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``; otherwise, they are undefined. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Divisibility testing -------------------------------------------------------------------------------- .. function:: int _fq_nmod_poly_divides(fq_nmod_struct * Q, const fq_nmod_struct * A, slong lenA, const fq_nmod_struct * B, slong lenB, const fq_nmod_t invB, const fq_nmod_ctx_t ctx) Returns `1` if ``(B, lenB)`` divides ``(A, lenA)`` exactly and sets `Q` to the quotient, otherwise returns `0`. It is assumed that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that `Q` has space for `\operatorname{len}(A) - \operatorname{len}(B) + 1` coefficients. Aliasing of `Q` with either of the inputs is not permitted. This function is currently unoptimised and provided for convenience only. .. function:: int fq_nmod_poly_divides(fq_nmod_poly_t Q, const fq_nmod_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) Returns `1` if `B` divides `A` exactly and sets `Q` to the quotient, otherwise returns `0`. This function is currently unoptimised and provided for convenience only. Derivative -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_derivative(fq_nmod_struct * rop, const fq_nmod_struct * op, slong len, const fq_nmod_ctx_t ctx) Sets ``(rop, len - 1)`` to the derivative of ``(op, len)``. Also handles the cases where ``len`` is `0` or `1` correctly. Supports aliasing of ``rop`` and ``op``. .. function:: void fq_nmod_poly_derivative(fq_nmod_poly_t rop, const fq_nmod_poly_t op, const fq_nmod_ctx_t ctx) Sets ``rop`` to the derivative of ``op``. Square root -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_invsqrt_series(fq_nmod_struct * g, const fq_nmod_struct * h, slong n, fq_nmod_ctx_t mod) Set the first `n` terms of `g` to the series expansion of `1/\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1 and that `h` is zero-padded as necessary to length `n`. Aliasing is not permitted. .. function:: void fq_nmod_poly_invsqrt_series(fq_nmod_poly_t g, const fq_nmod_poly_t h, slong n, fq_nmod_ctx_t ctx) Set `g` to the series expansion of `1/\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: void _fq_nmod_poly_sqrt_series(fq_nmod_struct * g, const fq_nmod_struct * h, slong n, fq_nmod_ctx_t ctx) Set the first `n` terms of `g` to the series expansion of `\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1 and that `h` is zero-padded as necessary to length `n`. Aliasing is not permitted. .. function:: void fq_nmod_poly_sqrt_series(fq_nmod_poly_t g, const fq_nmod_poly_t h, slong n, fq_nmod_ctx_t ctx) Set `g` to the series expansion of `\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: int _fq_nmod_poly_sqrt(fq_nmod_struct * s, const fq_nmod_struct * p, slong n, fq_nmod_ctx_t mod) If ``(p, n)`` is a perfect square, sets ``(s, n / 2 + 1)`` to a square root of `p` and returns 1. Otherwise returns 0. .. function:: int fq_nmod_poly_sqrt(fq_nmod_poly_t s, const fq_nmod_poly_t p, fq_nmod_ctx_t mod) If `p` is a perfect square, sets `s` to a square root of `p` and returns 1. Otherwise returns 0. Evaluation -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_evaluate_fq_nmod(fq_nmod_t rop, const fq_nmod_struct * op, slong len, const fq_nmod_t a, const fq_nmod_ctx_t ctx) Sets ``rop`` to ``(op, len)`` evaluated at `a`. Supports zero padding. There are no restrictions on ``len``, that is, ``len`` is allowed to be zero, too. .. function:: void fq_nmod_poly_evaluate_fq_nmod(fq_nmod_t rop, const fq_nmod_poly_t f, const fq_nmod_t a, const fq_nmod_ctx_t ctx) Sets ``rop`` to the value of `f(a)`. As the coefficient ring `\mathbf{F}_q` is finite, Horner's method is sufficient. Composition -------------------------------------------------------------------------------- .. function:: void _fq_nmod_poly_compose(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the composition of ``(op1, len1)`` and ``(op2, len2)``. Assumes that ``rop`` has space for ``(len1-1)*(len2-1) + 1`` coefficients. Assumes that ``op1`` and ``op2`` are non-zero polynomials. Does not support aliasing between any of the inputs and the output. .. function:: void fq_nmod_poly_compose(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) Sets ``rop`` to the composition of ``op1`` and ``op2``. To be precise about the order of composition, denoting ``rop``, ``op1``, and ``op2`` by `f`, `g`, and `h`, respectively, sets `f(t) = g(h(t))`. .. function:: void _fq_nmod_poly_compose_mod_horner(fq_nmod_struct * res, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * g, const fq_nmod_struct * h, slong lenh, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void fq_nmod_poly_compose_mod_horner(fq_nmod_poly_t res, const fq_nmod_poly_t f, const fq_nmod_poly_t g, const fq_nmod_poly_t h, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. The algorithm used is Horner's rule. .. function:: void _fq_nmod_poly_compose_mod_horner_preinv(fq_nmod_struct * res, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * g, const fq_nmod_struct * h, slong lenh, const fq_nmod_struct * hinv, slong lenhiv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void fq_nmod_poly_compose_mod_horner_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t f, const fq_nmod_poly_t g, const fq_nmod_poly_t h, const fq_nmod_poly_t hinv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is Horner's rule. .. function:: void _fq_nmod_poly_compose_mod_brent_kung(fq_nmod_struct * res, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * g, const fq_nmod_struct * h, slong lenh, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_nmod_poly_compose_mod_brent_kung(fq_nmod_poly_t res, const fq_nmod_poly_t f, const fq_nmod_poly_t g, const fq_nmod_poly_t h, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fq_nmod_poly_compose_mod_brent_kung_preinv(fq_nmod_struct * res, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * g, const fq_nmod_struct * h, slong lenh, const fq_nmod_struct * hinv, slong lenhiv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_nmod_poly_compose_mod_brent_kung_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t f, const fq_nmod_poly_t g, const fq_nmod_poly_t h, const fq_nmod_poly_t hinv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fq_nmod_poly_compose_mod(fq_nmod_struct * res, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * g, const fq_nmod_struct * h, slong lenh, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. .. function:: void fq_nmod_poly_compose_mod(fq_nmod_poly_t res, const fq_nmod_poly_t f, const fq_nmod_poly_t g, const fq_nmod_poly_t h, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. .. function:: void _fq_nmod_poly_compose_mod_preinv(fq_nmod_struct * res, const fq_nmod_struct * f, slong lenf, const fq_nmod_struct * g, const fq_nmod_struct * h, slong lenh, const fq_nmod_struct * hinv, slong lenhiv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. .. function:: void fq_nmod_poly_compose_mod_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t f, const fq_nmod_poly_t g, const fq_nmod_poly_t h, const fq_nmod_poly_t hinv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. .. function:: void _fq_nmod_poly_reduce_matrix_mod_poly (fq_nmod_mat_t A, const fq_nmod_mat_t B, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Sets the ith row of ``A`` to the reduction of the ith row of `B` modulo `f` for `i=1,\ldots,\sqrt{\deg(f)}`. We require `B` to be at least a `\sqrt{\deg(f)}\times \deg(f)` matrix and `f` to be nonzero. .. function:: void _fq_nmod_poly_precompute_matrix (fq_nmod_mat_t A, const fq_nmod_struct * f, const fq_nmod_struct * g, slong leng, const fq_nmod_struct * ginv, slong lenginv, const fq_nmod_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g`` and `g` to be nonzero. .. function:: void fq_nmod_poly_precompute_matrix (fq_nmod_mat_t A, const fq_nmod_poly_t f, const fq_nmod_poly_t g, const fq_nmod_poly_t ginv, const fq_nmod_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g``. .. function:: void _fq_nmod_poly_compose_mod_brent_kung_precomp_preinv(fq_nmod_struct * res, const fq_nmod_struct * f, slong lenf, const fq_nmod_mat_t A, const fq_nmod_struct * h, slong lenh, const fq_nmod_struct * hinv, slong lenhinv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_nmod_poly_compose_mod_brent_kung_precomp_preinv(fq_nmod_poly_t res, const fq_nmod_poly_t f, const fq_nmod_mat_t A, const fq_nmod_poly_t h, const fq_nmod_poly_t hinv, const fq_nmod_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. This version of Brent-Kung modular composition is particularly useful if one has to perform several modular composition of the form `f(g)` modulo `h` for fixed `g` and `h`. Output -------------------------------------------------------------------------------- .. function:: int _fq_nmod_poly_fprint_pretty(FILE * file, const fq_nmod_struct * poly, slong len, const char * x, const fq_nmod_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_nmod_poly_fprint_pretty(FILE * file, const fq_nmod_poly_t poly, const char * x, const fq_nmod_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_nmod_poly_print_pretty(const fq_nmod_struct * poly, slong len, const char * x, const fq_nmod_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_nmod_poly_print_pretty(const fq_nmod_poly_t poly, const char * x, const fq_nmod_ctx_t ctx) Prints the pretty representation of ``poly`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_nmod_poly_fprint(FILE * file, const fq_nmod_struct * poly, slong len, const fq_nmod_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_nmod_poly_fprint(FILE * file, const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_nmod_poly_print(const fq_nmod_struct * poly, slong len, const fq_nmod_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_nmod_poly_print(const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Prints the representation of ``poly`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: char * _fq_nmod_poly_get_str(const fq_nmod_struct * poly, slong len, const fq_nmod_ctx_t ctx) Returns the plain FLINT string representation of the polynomial ``(poly, len)``. .. function:: char * fq_nmod_poly_get_str(const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Returns the plain FLINT string representation of the polynomial ``poly``. .. function:: char * _fq_nmod_poly_get_str_pretty(const fq_nmod_struct * poly, slong len, const char * x, const fq_nmod_ctx_t ctx) Returns a pretty representation of the polynomial ``(poly, len)`` using the null-terminated string ``x`` as the variable name. .. function:: char * fq_nmod_poly_get_str_pretty(const fq_nmod_poly_t poly, const char * x, const fq_nmod_ctx_t ctx) Returns a pretty representation of the polynomial ``poly`` using the null-terminated string ``x`` as the variable name Inflation and deflation -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_inflate(fq_nmod_poly_t result, const fq_nmod_poly_t input, ulong inflation, const fq_nmod_ctx_t ctx) Sets ``result`` to the inflated polynomial `p(x^n)` where `p` is given by ``input`` and `n` is given by ``inflation``. .. function:: void fq_nmod_poly_deflate(fq_nmod_poly_t result, const fq_nmod_poly_t input, ulong deflation, const fq_nmod_ctx_t ctx) Sets ``result`` to the deflated polynomial `p(x^{1/n})` where `p` is given by ``input`` and `n` is given by ``deflation``. Requires `n > 0`. .. function:: ulong fq_nmod_poly_deflation(const fq_nmod_poly_t input, const fq_nmod_ctx_t ctx) Returns the largest integer by which ``input`` can be deflated. As special cases, returns 0 if ``input`` is the zero polynomial and 1 of ``input`` is a constant polynomial. flint-3.1.3/doc/source/fq_nmod_poly_factor.rst000066400000000000000000000244311461254215100214620ustar00rootroot00000000000000.. _fq-nmod-poly-factor: **fq_nmod_poly_factor.h** -- factorisation of univariate polynomials over finite fields (word-size characteristic) ================================================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_poly_factor_struct .. type:: fq_nmod_poly_factor_t Memory Management -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_factor_init(fq_nmod_poly_factor_t fac, const fq_nmod_ctx_t ctx) Initialises ``fac`` for use. An :type:`fq_nmod_poly_factor_t` represents a polynomial in factorised form as a product of polynomials with associated exponents. .. function:: void fq_nmod_poly_factor_clear(fq_nmod_poly_factor_t fac, const fq_nmod_ctx_t ctx) Frees all memory associated with ``fac``. .. function:: void fq_nmod_poly_factor_realloc(fq_nmod_poly_factor_t fac, slong alloc, const fq_nmod_ctx_t ctx) Reallocates the factor structure to provide space for precisely ``alloc`` factors. .. function:: void fq_nmod_poly_factor_fit_length(fq_nmod_poly_factor_t fac, slong len, const fq_nmod_ctx_t ctx) Ensures that the factor structure has space for at least ``len`` factors. This function takes care of the case of repeated calls by always at least doubling the number of factors the structure can hold. Basic Operations -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_factor_set(fq_nmod_poly_factor_t res, const fq_nmod_poly_factor_t fac, const fq_nmod_ctx_t ctx) Sets ``res`` to the same factorisation as ``fac``. .. function:: void fq_nmod_poly_factor_print_pretty(const fq_nmod_poly_factor_t fac, const char * var, const fq_nmod_ctx_t ctx) Pretty-prints the entries of ``fac`` to standard output. .. function:: void fq_nmod_poly_factor_print(const fq_nmod_poly_factor_t fac, const fq_nmod_ctx_t ctx) Prints the entries of ``fac`` to standard output. .. function:: void fq_nmod_poly_factor_insert(fq_nmod_poly_factor_t fac, const fq_nmod_poly_t poly, slong exp, const fq_nmod_ctx_t ctx) Inserts the factor ``poly`` with multiplicity ``exp`` into the factorisation ``fac``. If ``fac`` already contains ``poly``, then ``exp`` simply gets added to the exponent of the existing entry. .. function:: void fq_nmod_poly_factor_concat(fq_nmod_poly_factor_t res, const fq_nmod_poly_factor_t fac, const fq_nmod_ctx_t ctx) Concatenates two factorisations. This is equivalent to calling :func:`fq_nmod_poly_factor_insert` repeatedly with the individual factors of ``fac``. Does not support aliasing between ``res`` and ``fac``. .. function:: void fq_nmod_poly_factor_pow(fq_nmod_poly_factor_t fac, slong exp, const fq_nmod_ctx_t ctx) Raises ``fac`` to the power ``exp``. .. function:: ulong fq_nmod_poly_remove(fq_nmod_poly_t f, const fq_nmod_poly_t p, const fq_nmod_ctx_t ctx) Removes the highest possible power of ``p`` from ``f`` and returns the exponent. Irreducibility Testing -------------------------------------------------------------------------------- .. function:: int fq_nmod_poly_is_irreducible(const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. .. function:: int fq_nmod_poly_is_irreducible_ddf(const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses fast distinct-degree factorisation. .. function:: int fq_nmod_poly_is_irreducible_ben_or(const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses Ben-Or's irreducibility test. .. function:: int _fq_nmod_poly_is_squarefree(const fq_nmod_struct * f, slong len, const fq_nmod_ctx_t ctx) Returns 1 if ``(f, len)`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. There are no restrictions on the length. .. function:: int fq_nmod_poly_is_squarefree(const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Returns 1 if ``f`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. Factorisation -------------------------------------------------------------------------------- .. function:: int fq_nmod_poly_factor_equal_deg_prob(fq_nmod_poly_t factor, flint_rand_t state, const fq_nmod_poly_t pol, slong d, const fq_nmod_ctx_t ctx) Probabilistic equal degree factorisation of ``pol`` into irreducible factors of degree ``d``. If it passes, a factor is placed in factor and 1 is returned, otherwise 0 is returned and the value of factor is undetermined. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fq_nmod_poly_factor_equal_deg(fq_nmod_poly_factor_t factors, const fq_nmod_poly_t pol, slong d, const fq_nmod_ctx_t ctx) Assuming ``pol`` is a product of irreducible factors all of degree ``d``, finds all those factors and places them in factors. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fq_nmod_poly_factor_split_single(fq_nmod_poly_t linfactor, const fq_nmod_poly_t input, const fq_nmod_ctx_t ctx) Assuming ``input`` is a product of factors all of degree 1, finds a single linear factor of ``input`` and places it in ``linfactor``. Requires that ``input`` be monic and non-constant. .. function:: void fq_nmod_poly_factor_distinct_deg(fq_nmod_poly_factor_t res, const fq_nmod_poly_t poly, slong * const * degs, const fq_nmod_ctx_t ctx) Factorises a monic non-constant squarefree polynomial ``poly`` of degree `n` into factors `f[d]` such that for `1 \leq d \leq n` `f[d]` is the product of the monic irreducible factors of ``poly`` of degree `d`. Factors are stored in ``res``, associated powers of irreducible polynomials are stored in ``degs`` in the same order as factors. Requires that ``degs`` have enough space for irreducible polynomials' powers (maximum space required is `n * sizeof(slong)`). .. function:: void fq_nmod_poly_factor_squarefree(fq_nmod_poly_factor_t res, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Sets ``res`` to a squarefree factorization of ``f``. .. function:: void fq_nmod_poly_factor(fq_nmod_poly_factor_t res, fq_nmod_t lead, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors choosing the best algorithm for given modulo and degree. The output ``lead`` is set to the leading coefficient of `f` upon return. Choice of algorithm is based on heuristic measurements. .. function:: void fq_nmod_poly_factor_cantor_zassenhaus(fq_nmod_poly_factor_t res, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Cantor-Zassenhaus algorithm. .. function:: void fq_nmod_poly_factor_kaltofen_shoup(fq_nmod_poly_factor_t res, const fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the fast version of Cantor-Zassenhaus algorithm proposed by Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby step/giant step” strategy for the distinct-degree factorization step. .. function:: void fq_nmod_poly_factor_berlekamp(fq_nmod_poly_factor_t factors, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Berlekamp algorithm. .. function:: void fq_nmod_poly_factor_with_berlekamp(fq_nmod_poly_factor_t res, fq_nmod_t leading_coeff, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Berlekamp on all the individual square-free factors. .. function:: void fq_nmod_poly_factor_with_cantor_zassenhaus(fq_nmod_poly_factor_t res, fq_nmod_t leading_coeff, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Cantor-Zassenhaus on all the individual square-free factors. .. function:: void fq_nmod_poly_factor_with_kaltofen_shoup(fq_nmod_poly_factor_t res, fq_nmod_t leading_coeff, const fq_nmod_poly_t f, const fq_nmod_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Kaltofen-Shoup on all the individual square-free factors. .. function:: void fq_nmod_poly_iterated_frobenius_preinv(fq_nmod_poly_t * rop, slong n, const fq_nmod_poly_t v, const fq_nmod_poly_t vinv, const fq_nmod_ctx_t ctx) Sets ``rop[i]`` to be `x^{q^i} \bmod v` for `0 \le i < n`. It is required that ``vinv`` is the inverse of the reverse of ``v`` mod ``x^lenv``. Root Finding -------------------------------------------------------------------------------- .. function:: void fq_nmod_poly_roots(fq_nmod_poly_factor_t r, const fq_nmod_poly_t f, int with_multiplicity, const fq_nmod_ctx_t ctx) Fill `r` with factors of the form `x - r_i` where the `r_i` are the distinct roots of a nonzero `f` in `F_q`. If `with\_multiplicity` is zero, the exponent `e_i` of the factor `x - r_i` is `1`. Otherwise, it is the largest `e_i` such that `(x-r_i)^e_i` divides `f`. This function throws if `f` is zero, but is otherwise always successful. flint-3.1.3/doc/source/fq_nmod_vec.rst000066400000000000000000000106421461254215100177150ustar00rootroot00000000000000.. _fq-nmod-vec: **fq_nmod_vec.h** -- vectors over finite fields (word-size characteristic) =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: fq_nmod_struct * _fq_nmod_vec_init(slong len, const fq_nmod_ctx_t ctx) Returns an initialised vector of ``fq_nmod``'s of given length. .. function:: void _fq_nmod_vec_clear(fq_nmod_struct * vec, slong len, const fq_nmod_ctx_t ctx) Clears the entries of ``(vec, len)`` and frees the space allocated for ``vec``. Randomisation -------------------------------------------------------------------------------- .. function:: void _fq_nmod_vec_randtest(fq_nmod_struct * f, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx) Sets the entries of a vector of the given length to elements of the finite field. Input and output -------------------------------------------------------------------------------- .. function:: int _fq_nmod_vec_fprint(FILE * file, const fq_nmod_struct * vec, slong len, const fq_nmod_ctx_t ctx) Prints the vector of given length to the stream ``file``. The format is the length followed by two spaces, then a space separated list of coefficients. If the length is zero, only `0` is printed. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_nmod_vec_print(const fq_nmod_struct * vec, slong len, const fq_nmod_ctx_t ctx) Prints the vector of given length to ``stdout``. For further details, see ``_fq_nmod_vec_fprint()``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _fq_nmod_vec_set(fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_ctx_t ctx) Makes a copy of ``(vec2, len2)`` into ``vec1``. .. function:: void _fq_nmod_vec_swap(fq_nmod_struct * vec1, fq_nmod_struct * vec2, slong len2, const fq_nmod_ctx_t ctx) Swaps the elements in ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fq_nmod_vec_zero(fq_nmod_struct * vec, slong len, const fq_nmod_ctx_t ctx) Zeros the entries of ``(vec, len)``. .. function:: void _fq_nmod_vec_neg(fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_ctx_t ctx) Negates ``(vec2, len2)`` and places it into ``vec1``. Comparison -------------------------------------------------------------------------------- .. function:: int _fq_nmod_vec_equal(const fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len, const fq_nmod_ctx_t ctx) Compares two vectors of the given length and returns `1` if they are equal, otherwise returns `0`. .. function:: int _fq_nmod_vec_is_zero(const fq_nmod_struct * vec, slong len, const fq_nmod_ctx_t ctx) Returns `1` if ``(vec, len)`` is zero, and `0` otherwise. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fq_nmod_vec_add(fq_nmod_struct * res, const fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_ctx_t ctx) Sets ``(res, len2)`` to the sum of ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fq_nmod_vec_sub(fq_nmod_struct * res, const fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_ctx_t ctx) Sets ``(res, len2)`` to ``(vec1, len2)`` minus ``(vec2, len2)``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fq_nmod_vec_scalar_addmul_fq_nmod(fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_t c, const fq_nmod_ctx_t ctx) Adds ``(vec2, len2)`` times `c` to ``(vec1, len2)``, where `c` is a ``fq_nmod_t``. .. function:: void _fq_nmod_vec_scalar_submul_fq_nmod(fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_t c, const fq_nmod_ctx_t ctx) Subtracts ``(vec2, len2)`` times `c` from ``(vec1, len2)``, where `c` is a ``fq_nmod_t``. Dot products -------------------------------------------------------------------------------- .. function:: void _fq_nmod_vec_dot(fq_nmod_t res, const fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_ctx_t ctx) Sets ``res`` to the dot product of (``vec1``, ``len``) and (``vec2``, ``len``). flint-3.1.3/doc/source/fq_poly.rst000066400000000000000000002020141461254215100171020ustar00rootroot00000000000000.. _fq-poly: **fq_poly.h** -- univariate polynomials over finite fields =============================================================================== We represent a polynomial in `\mathbf{F}_q[X]` as a ``struct`` which includes an array ``coeffs`` with the coefficients, as well as the length ``length`` and the number ``alloc`` of coefficients for which memory has been allocated. As a data structure, we call this polynomial *normalised* if the top coefficient is non-zero. Unless otherwise stated here, all functions that deal with polynomials assume that the `\mathbf{F}_q` context of said polynomials are compatible, i.e., it assumes that the fields are generated by the same polynomial. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_poly_struct .. type:: fq_poly_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_poly_init(fq_poly_t poly, const fq_ctx_t ctx) Initialises ``poly`` for use, with context ctx, and setting its length to zero. A corresponding call to :func:`fq_poly_clear` must be made after finishing with the ``fq_poly_t`` to free the memory used by the polynomial. .. function:: void fq_poly_init2(fq_poly_t poly, slong alloc, const fq_ctx_t ctx) Initialises ``poly`` with space for at least ``alloc`` coefficients and sets the length to zero. The allocated coefficients are all set to zero. A corresponding call to :func:`fq_poly_clear` must be made after finishing with the ``fq_poly_t`` to free the memory used by the polynomial. .. function:: void fq_poly_realloc(fq_poly_t poly, slong alloc, const fq_ctx_t ctx) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` the polynomial is first truncated to length ``alloc``. .. function:: void fq_poly_fit_length(fq_poly_t poly, slong len, const fq_ctx_t ctx) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where ``fit_length`` is called many times in small increments by at least doubling the number of allocated coefficients when length is larger than the number of coefficients currently allocated. .. function:: void _fq_poly_set_length(fq_poly_t poly, slong newlen, const fq_ctx_t ctx) Sets the coefficients of ``poly`` beyond ``len`` to zero and sets the length of ``poly`` to ``len``. .. function:: void fq_poly_clear(fq_poly_t poly, const fq_ctx_t ctx) Clears the given polynomial, releasing any memory used. It must be reinitialised in order to be used again. .. function:: void _fq_poly_normalise(fq_poly_t poly, const fq_ctx_t ctx) Sets the length of ``poly`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void _fq_poly_normalise2(const fq_struct * poly, slong * length, const fq_ctx_t ctx) Sets the length ``length`` of ``(poly,length)`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void fq_poly_truncate(fq_poly_t poly, slong newlen, const fq_ctx_t ctx) Truncates the polynomial to length at most `n`. .. function:: void fq_poly_set_trunc(fq_poly_t poly1, fq_poly_t poly2, slong newlen, const fq_ctx_t ctx) Sets ``poly1`` to ``poly2`` truncated to length `n`. .. function:: void _fq_poly_reverse(fq_struct * output, const fq_struct * input, slong len, slong m, const fq_ctx_t ctx) Sets ``output`` to the reverse of ``input``, which is of length ``len``, but thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary. The length ``m`` must be non-negative, but there are no other restrictions. The polynomial ``output`` must have space for ``m`` coefficients. .. function:: void fq_poly_reverse(fq_poly_t output, const fq_poly_t input, slong m, const fq_ctx_t ctx) Sets ``output`` to the reverse of ``input``, thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary). The length ``m`` must be non-negative, but there are no other restrictions. The output polynomial will be set to length ``m`` and then normalised. Polynomial parameters -------------------------------------------------------------------------------- .. function:: slong fq_poly_degree(const fq_poly_t poly, const fq_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: slong fq_poly_length(const fq_poly_t poly, const fq_ctx_t ctx) Returns the length of the polynomial ``poly``. .. function:: fq_struct * fq_poly_lead(const fq_poly_t poly, const fq_ctx_t ctx) Returns a pointer to the leading coefficient of ``poly``, or ``NULL`` if ``poly`` is the zero polynomial. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_poly_randtest(fq_poly_t f, flint_rand_t state, slong len, const fq_ctx_t ctx) Sets `f` to a random polynomial of length at most ``len`` with entries in the field described by ``ctx``. .. function:: void fq_poly_randtest_not_zero(fq_poly_t f, flint_rand_t state, slong len, const fq_ctx_t ctx) Same as ``fq_poly_randtest`` but guarantees that the polynomial is not zero. .. function:: void fq_poly_randtest_monic(fq_poly_t f, flint_rand_t state, slong len, const fq_ctx_t ctx) Sets `f` to a random monic polynomial of length ``len`` with entries in the field described by ``ctx``. .. function:: void fq_poly_randtest_irreducible(fq_poly_t f, flint_rand_t state, slong len, const fq_ctx_t ctx) Sets `f` to a random monic, irreducible polynomial of length ``len`` with entries in the field described by ``ctx``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _fq_poly_set(fq_struct * rop, const fq_struct * op, slong len, const fq_ctx_t ctx) Sets ``(rop, len``) to ``(op, len)``. .. function:: void fq_poly_set(fq_poly_t poly1, const fq_poly_t poly2, const fq_ctx_t ctx) Sets the polynomial ``poly1`` to the polynomial ``poly2``. .. function:: void fq_poly_set_fq(fq_poly_t poly, const fq_t c, const fq_ctx_t ctx) Sets the polynomial ``poly`` to ``c``. .. function:: void fq_poly_set_fmpz_mod_poly(fq_poly_t rop, const fmpz_mod_poly_t op, const fq_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op`` .. function:: void fq_poly_set_nmod_poly(fq_poly_t rop, const nmod_poly_t op, const fq_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op`` .. function:: void fq_poly_swap(fq_poly_t op1, fq_poly_t op2, const fq_ctx_t ctx) Swaps the two polynomials ``op1`` and ``op2``. .. function:: void _fq_poly_zero(fq_struct * rop, slong len, const fq_ctx_t ctx) Sets ``(rop, len)`` to the zero polynomial. .. function:: void fq_poly_zero(fq_poly_t poly, const fq_ctx_t ctx) Sets ``poly`` to the zero polynomial. .. function:: void fq_poly_one(fq_poly_t poly, const fq_ctx_t ctx) Sets ``poly`` to the constant polynomial `1`. .. function:: void fq_poly_gen(fq_poly_t poly, const fq_ctx_t ctx) Sets ``poly`` to the polynomial `x`. .. function:: void fq_poly_make_monic(fq_poly_t rop, const fq_poly_t op, const fq_ctx_t ctx) Sets ``rop`` to ``op``, normed to have leading coefficient 1. .. function:: void _fq_poly_make_monic(fq_struct * rop, const fq_struct * op, slong length, const fq_ctx_t ctx) Sets ``rop`` to ``(op,length)``, normed to have leading coefficient 1. Assumes that ``rop`` has enough space for the polynomial, assumes that ``op`` is not zero (and thus has an invertible leading coefficient). Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void fq_poly_get_coeff(fq_t x, const fq_poly_t poly, slong n, const fq_ctx_t ctx) Sets `x` to the coefficient of `X^n` in ``poly``. .. function:: void fq_poly_set_coeff(fq_poly_t poly, slong n, const fq_t x, const fq_ctx_t ctx) Sets the coefficient of `X^n` in ``poly`` to `x`. .. function:: void fq_poly_set_coeff_fmpz(fq_poly_t poly, slong n, const fmpz_t x, const fq_ctx_t ctx) Sets the coefficient of `X^n` in the polynomial to `x`, assuming `n \geq 0`. Comparison -------------------------------------------------------------------------------- .. function:: int fq_poly_equal(const fq_poly_t poly1, const fq_poly_t poly2, const fq_ctx_t ctx) Returns nonzero if the two polynomials ``poly1`` and ``poly2`` are equal, otherwise returns zero. .. function:: int fq_poly_equal_trunc(const fq_poly_t poly1, const fq_poly_t poly2, slong n, const fq_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length `n` and return nonzero if they are equal, otherwise return zero. .. function:: int fq_poly_is_zero(const fq_poly_t poly, const fq_ctx_t ctx) Returns whether the polynomial ``poly`` is the zero polynomial. .. function:: int fq_poly_is_one(const fq_poly_t op, const fq_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the constant polynomial `1`. .. function:: int fq_poly_is_gen(const fq_poly_t op, const fq_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the polynomial `x`. .. function:: int fq_poly_is_unit(const fq_poly_t op, const fq_ctx_t ctx) Returns whether the polynomial ``poly`` is a unit in the polynomial ring `\mathbf{F}_q[X]`, i.e. if it has degree `0` and is non-zero. .. function:: int fq_poly_equal_fq(const fq_poly_t poly, const fq_t c, const fq_ctx_t ctx) Returns whether the polynomial ``poly`` is equal the (constant) `\mathbf{F}_q` element ``c`` Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fq_poly_add(fq_struct * res, const fq_struct * poly1, slong len1, const fq_struct * poly2, slong len2, const fq_ctx_t ctx) Sets ``res`` to the sum of ``(poly1,len1)`` and ``(poly2,len2)``. .. function:: void fq_poly_add(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, const fq_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``poly2``. .. function:: void fq_poly_add_si(fq_poly_t res, const fq_poly_t poly1, slong c, const fq_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``c``. .. function:: void fq_poly_add_series(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, slong n, const fq_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the sum. .. function:: void _fq_poly_sub(fq_struct * res, const fq_struct * poly1, slong len1, const fq_struct * poly2, slong len2, const fq_ctx_t ctx) Sets ``res`` to the difference of ``(poly1,len1)`` and ``(poly2,len2)``. .. function:: void fq_poly_sub(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, const fq_ctx_t ctx) Sets ``res`` to the difference of ``poly1`` and ``poly2``. .. function:: void fq_poly_sub_series(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, slong n, const fq_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the difference. .. function:: void _fq_poly_neg(fq_struct * rop, const fq_struct * op, slong len, const fq_ctx_t ctx) Sets ``rop`` to the additive inverse of ``(poly,len)``. .. function:: void fq_poly_neg(fq_poly_t res, const fq_poly_t poly, const fq_ctx_t ctx) Sets ``res`` to the additive inverse of ``poly``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fq_poly_scalar_mul_fq(fq_struct * rop, const fq_struct * op, slong len, const fq_t x, const fq_ctx_t ctx) Sets ``(rop,len)`` to the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void fq_poly_scalar_mul_fq(fq_poly_t rop, const fq_poly_t op, const fq_t x, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_poly_scalar_addmul_fq(fq_struct * rop, const fq_struct * op, slong len, const fq_t x, const fq_ctx_t ctx) Adds to ``(rop,len)`` the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. In particular, assumes the same length for ``op`` and ``rop``. .. function:: void fq_poly_scalar_addmul_fq(fq_poly_t rop, const fq_poly_t op, const fq_t x, const fq_ctx_t ctx) Adds to ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_poly_scalar_submul_fq(fq_struct * rop, const fq_struct * op, slong len, const fq_t x, const fq_ctx_t ctx) Subtracts from ``(rop,len)`` the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. In particular, assumes the same length for ``op`` and ``rop``. .. function:: void fq_poly_scalar_submul_fq(fq_poly_t rop, const fq_poly_t op, const fq_t x, const fq_ctx_t ctx) Subtracts from ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_poly_scalar_div_fq(fq_struct * rop, const fq_struct * op, slong len, const fq_t x, const fq_ctx_t ctx) Sets ``(rop,len)`` to the quotient of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. An exception is raised if ``x`` is zero. .. function:: void fq_poly_scalar_div_fq(fq_poly_t rop, const fq_poly_t op, const fq_t x, const fq_ctx_t ctx) Sets ``rop`` to the quotient of ``op`` by the scalar ``x``, in the context defined by ``ctx``. An exception is raised if ``x`` is zero. Multiplication -------------------------------------------------------------------------------- .. function:: void _fq_poly_mul_classical(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, assuming that ``len1`` is at least ``len2`` and neither is zero. Permits zero padding. Does not support aliasing of ``rop`` with either ``op1`` or ``op2``. .. function:: void fq_poly_mul_classical(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using classical polynomial multiplication. .. function:: void _fq_poly_mul_reorder(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, assuming that ``len1`` and ``len2`` are non-zero. Permits zero padding. Supports aliasing. .. function:: void fq_poly_mul_reorder(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reordering the two indeterminates `X` and `Y` when viewing the polynomials as elements of `\mathbf{F}_p[X,Y]`. Suppose `\mathbf{F}_q = \mathbf{F}_p[X]/ (f(X))` and recall that elements of `\mathbf{F}_q` are internally represented by elements of type ``fmpz_poly``. For small degree extensions but polynomials in `\mathbf{F}_q[Y]` of large degree `n`, we change the representation to .. math:: \begin{split} g(Y) & = \sum_{i=0}^{n} a_i(X) Y^i \\ & = \sum_{j=0}^{d} \sum_{i=0}^{n} \text{Coeff}(a_i(X), j) Y^i. \end{split} This allows us to use a poor algorithm (such as classical multiplication) in the `X`-direction and leverage the existing fast integer multiplication routines in the `Y`-direction where the polynomial degree `n` is large. .. function:: void _fq_poly_mul_univariate(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``. Permits zero padding and places no assumptions on the lengths ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_poly_mul_univariate(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using a bivariate to univariate transformation and reducing this problem to multiplying two univariate polynomials. .. function:: void _fq_poly_mul_KS(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``. Permits zero padding and places no assumptions on the lengths ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_poly_mul_KS(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using Kronecker substitution, that is, by encoding each coefficient in `\mathbf{F}_{q}` as an integer and reducing this problem to multiplying two polynomials over the integers. .. function:: void _fq_poly_mul(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, choosing an appropriate algorithm. Permits zero padding. Does not support aliasing. .. function:: void fq_poly_mul(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, choosing an appropriate algorithm. .. function:: void _fq_poly_mullow_classical(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, slong n, const fq_ctx_t ctx) Sets ``(rop, n)`` to the first `n` coefficients of ``(op1, len1)`` multiplied by ``(op2, len2)``. Assumes ``0 < n <= len1 + len2 - 1``. Assumes neither ``len1`` nor ``len2`` is zero. .. function:: void fq_poly_mullow_classical(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, slong n, const fq_ctx_t ctx) Sets ``rop`` to the product of ``poly1`` and ``poly2``, computed using the classical or schoolbook method. .. function:: void _fq_poly_mullow_univariate(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, slong n, const fq_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``, computed using a bivariate to univariate transformation. Assumes that ``len1`` and ``len2`` are positive, but does allow for the polynomials to be zero-padded. The polynomials may be zero, too. Assumes `n` is positive. Supports aliasing between ``res``, ``poly1`` and ``poly2``. .. function:: void fq_poly_mullow_univariate(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, slong n, const fq_ctx_t ctx) Sets ``rop`` to the lowest `n` coefficients of the product of ``op1`` and ``op2``, computed using a bivariate to univariate transformation. .. function:: void _fq_poly_mullow_KS(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, slong n, const fq_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``. Assumes that ``len1`` and ``len2`` are positive, but does allow for the polynomials to be zero-padded. The polynomials may be zero, too. Assumes `n` is positive. Supports aliasing between ``rop``, ``op1`` and ``op2``. .. function:: void fq_poly_mullow_KS(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, slong n, const fq_ctx_t ctx) Sets ``rop`` to the lowest `n` coefficients of the product of ``op1`` and ``op2``. .. function:: void _fq_poly_mullow(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, slong n, const fq_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``. Assumes ``0 < n <= len1 + len2 - 1``. Allows for zero-padding in the inputs. Does not support aliasing between the inputs and the output. .. function:: void fq_poly_mullow(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, slong n, const fq_ctx_t ctx) Sets ``rop`` to the lowest `n` coefficients of the product of ``op1`` and ``op2``. .. function:: void _fq_poly_mulhigh_classical(fq_struct * res, const fq_struct * poly1, slong len1, const fq_struct * poly2, slong len2, slong start, const fq_ctx_t ctx) Computes the product of ``(poly1, len1)`` and ``(poly2, len2)`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Assumes that ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. Algorithm is classical multiplication. .. function:: void fq_poly_mulhigh_classical(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, slong start, const fq_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Algorithm is classical multiplication. .. function:: void _fq_poly_mulhigh(fq_struct * res, const fq_struct * poly1, slong len1, const fq_struct * poly2, slong len2, slong start, fq_ctx_t ctx) Computes the product of ``(poly1, len1)`` and ``(poly2, len2)`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Assumes that ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. .. function:: void fq_poly_mulhigh(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, slong start, const fq_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. .. function:: void _fq_poly_mulmod(fq_struct * res, const fq_struct * poly1, slong len1, const fq_struct * poly2, slong len2, const fq_struct * f, slong lenf, const fq_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``len1 + len2 - lenf > 0``, which is equivalent to requiring that the result will actually be reduced. Otherwise, simply use ``_fq_poly_mul`` instead. Aliasing of ``f`` and ``res`` is not permitted. .. function:: void fq_poly_mulmod(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, const fq_poly_t f, const fq_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. .. function:: void _fq_poly_mulmod_preinv(fq_struct * res, const fq_struct * poly1, slong len1, const fq_struct * poly2, slong len2, const fq_struct * f, slong lenf, const fq_struct * finv, slong lenfinv, const fq_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``finv`` is the inverse of the reverse of ``f`` mod ``x^lenf``. Aliasing of ``res`` with any of the inputs is not permitted. .. function:: void fq_poly_mulmod_preinv(fq_poly_t res, const fq_poly_t poly1, const fq_poly_t poly2, const fq_poly_t f, const fq_poly_t finv, const fq_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. ``finv`` is the inverse of the reverse of ``f``. Squaring -------------------------------------------------------------------------------- .. function:: void _fq_poly_sqr_classical(fq_struct * rop, const fq_struct * op, slong len, const fq_ctx_t ctx) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``, assuming that ``(op,len)`` is not zero and using classical polynomial multiplication. Permits zero padding. Does not support aliasing of ``rop`` with either ``op1`` or ``op2``. .. function:: void fq_poly_sqr_classical(fq_poly_t rop, const fq_poly_t op, const fq_ctx_t ctx) Sets ``rop`` to the square of ``op`` using classical polynomial multiplication. .. function:: void _fq_poly_sqr_reorder(fq_struct * rop, const fq_struct * op, slong len, const fq_ctx_t ctx) Sets ``(rop, 2*len- 1)`` to the square of ``(op, len)``, assuming that ``len`` is not zero reordering the two indeterminates `X` and `Y` when viewing the polynomials as elements of `\mathbf{F}_p[X,Y]`. Permits zero padding. Supports aliasing. .. function:: void fq_poly_sqr_reorder(fq_poly_t rop, const fq_poly_t op, const fq_ctx_t ctx) Sets ``rop`` to the square of ``op``, assuming that ``len`` is not zero reordering the two indeterminates `X` and `Y` when viewing the polynomials as elements of `\mathbf{F}_p[X,Y]`. See ``fq_poly_mul_reorder``. .. function:: void _fq_poly_sqr_KS(fq_struct * rop, const fq_struct * op, slong len, const fq_ctx_t ctx) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``. Permits zero padding and places no assumptions on the lengths ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_poly_sqr_KS(fq_poly_t rop, const fq_poly_t op, const fq_ctx_t ctx) Sets ``rop`` to the square ``op`` using Kronecker substitution, that is, by encoding each coefficient in `\mathbf{F}_{q}` as an integer and reducing this problem to multiplying two polynomials over the integers. .. function:: void _fq_poly_sqr(fq_struct * rop, const fq_struct * op, slong len, const fq_ctx_t ctx) Sets ``(rop, 2 * len - 1)`` to the square of ``(op, len)``, choosing an appropriate algorithm. Permits zero padding. Does not support aliasing. .. function:: void fq_poly_sqr(fq_poly_t rop, const fq_poly_t op, const fq_ctx_t ctx) Sets ``rop`` to the square of ``op``, choosing an appropriate algorithm. Powering -------------------------------------------------------------------------------- .. function:: void _fq_poly_pow(fq_struct * rop, const fq_struct * op, slong len, ulong e, const fq_ctx_t ctx) Sets ``rop = op^e``, assuming that ``e, len > 0`` and that ``rop`` has space for ``e*(len - 1) + 1`` coefficients. Does not support aliasing. .. function:: void fq_poly_pow(fq_poly_t rop, const fq_poly_t op, ulong e, const fq_ctx_t ctx) Computes ``rop = op^e``. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void _fq_poly_powmod_ui_binexp(fq_struct * res, const fq_struct * poly, ulong e, const fq_struct * f, slong lenf, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_poly_powmod_ui_binexp(fq_poly_t res, const fq_poly_t poly, ulong e, const fq_poly_t f, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fq_poly_powmod_ui_binexp_preinv(fq_struct * res, const fq_struct * poly, ulong e, const fq_struct * f, slong lenf, const fq_struct * finv, slong lenfinv, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_poly_powmod_ui_binexp_preinv(fq_poly_t res, const fq_poly_t poly, ulong e, const fq_poly_t f, const fq_poly_t finv, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_poly_powmod_fmpz_binexp(fq_struct * res, const fq_struct * poly, const fmpz_t e, const fq_struct * f, slong lenf, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_poly_powmod_fmpz_binexp(fq_poly_t res, const fq_poly_t poly, const fmpz_t e, const fq_poly_t f, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fq_poly_powmod_fmpz_binexp_preinv(fq_struct * res, const fq_struct * poly, const fmpz_t e, const fq_struct * f, slong lenf, const fq_struct * finv, slong lenfinv, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_poly_powmod_fmpz_binexp_preinv(fq_poly_t res, const fq_poly_t poly, const fmpz_t e, const fq_poly_t f, const fq_poly_t finv, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_poly_powmod_fmpz_sliding_preinv(fq_struct * res, const fq_struct * poly, const fmpz_t e, ulong k, const fq_struct * f, slong lenf, const fq_struct * finv, slong lenfinv, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using sliding-window exponentiation with window size ``k``. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. If ``k`` is set to zero, then an "optimum" size will be selected automatically base on ``e``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_poly_powmod_fmpz_sliding_preinv(fq_poly_t res, const fq_poly_t poly, const fmpz_t e, ulong k, const fq_poly_t f, const fq_poly_t finv, const fq_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using sliding-window exponentiation with window size ``k``. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. If ``k`` is set to zero, then an "optimum" size will be selected automatically base on ``e``. .. function:: void _fq_poly_powmod_x_fmpz_preinv(fq_struct * res, const fmpz_t e, const fq_struct * f, slong lenf, const fq_struct * finv, slong lenfinv, const fq_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 2``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_poly_powmod_x_fmpz_preinv(fq_poly_t res, const fmpz_t e, const fq_poly_t f, const fq_poly_t finv, const fq_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_poly_pow_trunc_binexp(fq_struct * res, const fq_struct * poly, ulong e, slong trunc, const fq_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. Uses the binary exponentiation method. .. function:: void fq_poly_pow_trunc_binexp(fq_poly_t res, const fq_poly_t poly, ulong e, slong trunc, const fq_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Uses the binary exponentiation method. .. function:: void _fq_poly_pow_trunc(fq_struct * res, const fq_struct * poly, ulong e, slong trunc, const fq_ctx_t mod) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. .. function:: void fq_poly_pow_trunc(fq_poly_t res, const fq_poly_t poly, ulong e, slong trunc, const fq_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Shifting -------------------------------------------------------------------------------- .. function:: void _fq_poly_shift_left(fq_struct * rop, const fq_struct * op, slong len, slong n, const fq_ctx_t ctx) Sets ``(rop, len + n)`` to ``(op, len)`` shifted left by `n` coefficients. Inserts zero coefficients at the lower end. Assumes that ``len`` and `n` are positive, and that ``rop`` fits ``len + n`` elements. Supports aliasing between ``rop`` and ``op``. .. function:: void fq_poly_shift_left(fq_poly_t rop, const fq_poly_t op, slong n, const fq_ctx_t ctx) Sets ``rop`` to ``op`` shifted left by `n` coeffs. Zero coefficients are inserted. .. function:: void _fq_poly_shift_right(fq_struct * rop, const fq_struct * op, slong len, slong n, const fq_ctx_t ctx) Sets ``(rop, len - n)`` to ``(op, len)`` shifted right by `n` coefficients. Assumes that ``len`` and `n` are positive, that ``len > n``, and that ``rop`` fits ``len - n`` elements. Supports aliasing between ``rop`` and ``op``, although in this case the top coefficients of ``op`` are not set to zero. .. function:: void fq_poly_shift_right(fq_poly_t rop, const fq_poly_t op, slong n, const fq_ctx_t ctx) Sets ``rop`` to ``op`` shifted right by `n` coefficients. If `n` is equal to or greater than the current length of ``op``, ``rop`` is set to the zero polynomial. Norms -------------------------------------------------------------------------------- .. function:: slong _fq_poly_hamming_weight(const fq_struct * op, slong len, const fq_ctx_t ctx) Returns the number of non-zero entries in ``(op, len)``. .. function:: slong fq_poly_hamming_weight(const fq_poly_t op, const fq_ctx_t ctx) Returns the number of non-zero entries in the polynomial ``op``. Euclidean division -------------------------------------------------------------------------------- .. function:: void _fq_poly_divrem(fq_struct * Q, fq_struct * R, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_t invB, const fq_ctx_t ctx) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible and that ``invB`` is its inverse. Assumes that `\operatorname{len}(A), \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. `R` and `A` may be aliased, but apart from this no aliasing of input and output operands is allowed. .. function:: void fq_poly_divrem(fq_poly_t Q, fq_poly_t R, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible. This can be taken for granted the context is for a finite field, that is, when `p` is prime and `f(X)` is irreducible. .. function:: void fq_poly_divrem_f(fq_t f, fq_poly_t Q, fq_poly_t R, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Either finds a non-trivial factor `f` of the modulus of ``ctx``, or computes `Q`, `R` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. If the leading coefficient of `B` is invertible, the division with remainder operation is carried out, `Q` and `R` are computed correctly, and `f` is set to `1`. Otherwise, `f` is set to a non-trivial factor of the modulus and `Q` and `R` are not touched. Assumes that `B` is non-zero. .. function:: void _fq_poly_rem(fq_struct * R, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_t invB, const fq_ctx_t ctx) Sets ``R`` to the remainder of the division of ``(A,lenA)`` by ``(B,lenB)``. Assumes that the leading coefficient of ``(B,lenB)`` is invertible and that ``invB`` is its inverse. .. function:: void fq_poly_rem(fq_poly_t R, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Sets ``R`` to the remainder of the division of ``A`` by ``B`` in the context described by ``ctx``. .. function:: void _fq_poly_div(fq_struct * Q, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_t invB, const fq_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)` but only sets ``(Q, lenA - lenB + 1)``. Allows zero-padding in `A` but not in `B`. Assumes that the leading coefficient of `B` is a unit. .. function:: void fq_poly_div(fq_poly_t Q, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Notionally finds polynomials `Q` and `R` such that `A = B Q + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only ``Q``. If `\operatorname{len}(B) = 0` an exception is raised. .. function:: void _fq_poly_div_newton_n_preinv(fq_struct * Q, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_struct * Binv, slong lenBinv, const fq_ctx_t ctx) Notionally computes polynomials `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where ``A`` is of length ``lenA`` and ``B`` is of length ``lenB``, but return only `Q`. We require that `Q` have space for ``lenA - lenB + 1`` coefficients and assume that the leading coefficient of `B` is a unit. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void fq_poly_div_newton_n_preinv(fq_poly_t Q, const fq_poly_t A, const fq_poly_t B, const fq_poly_t Binv, const fq_ctx_t ctx) Notionally computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only `Q`. We assume that the leading coefficient of `B` is a unit and that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void _fq_poly_divrem_newton_n_preinv(fq_struct * Q, fq_struct * R, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_struct * Binv, slong lenBinv, const fq_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where `A` is of length ``lenA`` and `B` is of length ``lenB``. We require that `Q` have space for ``lenA - lenB + 1`` coefficients. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to call :func:`div_newton_n_preinv` and then multiply out and compute the remainder. .. function:: void fq_poly_divrem_newton_n_preinv(fq_poly_t Q, fq_poly_t R, const fq_poly_t A, const fq_poly_t B, const fq_poly_t Binv, const fq_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. We assume `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to call :func:`div_newton_n` and then multiply out and compute the remainder. .. function:: void _fq_poly_inv_series_newton(fq_struct * Qinv, const fq_struct * Q, slong n, const fq_t cinv, const fq_ctx_t ctx) Given ``Q`` of length ``n`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void fq_poly_inv_series_newton(fq_poly_t Qinv, const fq_poly_t Q, slong n, const fq_ctx_t ctx) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void _fq_poly_inv_series(fq_struct * Qinv, const fq_struct * Q, slong n, const fq_t cinv, const fq_ctx_t ctx) Given ``Q`` of length ``n`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. .. function:: void fq_poly_inv_series(fq_poly_t Qinv, const fq_poly_t Q, slong n, const fq_ctx_t ctx) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. .. function:: void _fq_poly_div_series(fq_struct * Q, const fq_struct * A, slong Alen, const fq_struct * B, slong Blen, slong n, const fq_ctx_t ctx) Set ``(Q, n)`` to the quotient of the series ``(A, Alen``) and ``(B, Blen)`` assuming ``Alen, Blen <= n``. We assume the bottom coefficient of ``B`` is invertible. .. function:: void fq_poly_div_series(fq_poly_t Q, const fq_poly_t A, const fq_poly_t B, slong n, const fq_ctx_t ctx) Set `Q` to the quotient of the series `A` by `B`, thinking of the series as though they were of length `n`. We assume that the bottom coefficient of `B` is invertible. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void fq_poly_gcd(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) Sets ``rop`` to the greatest common divisor of ``op1`` and ``op2``, using the either the Euclidean or HGCD algorithm. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. .. function:: slong _fq_poly_gcd(fq_struct * G, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_ctx_t ctx) Computes the GCD of `A` of length ``lenA`` and `B` of length ``lenB``, where ``lenA >= lenB > 0`` and sets `G` to it. The length of the GCD `G` is returned by the function. No attempt is made to make the GCD monic. It is required that `G` have space for ``lenB`` coefficients. .. function:: slong _fq_poly_gcd_euclidean_f(fq_t f, fq_struct * G, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `(A,\operatorname{len}(A))` and `(B, \operatorname{len}(B))` and returns its length, or sets `f` to a non-trivial factor of the modulus of ``ctx`` and leaves the contents of the vector `(G, lenB)` undefined. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that the vector `G` has space for sufficiently many coefficients. .. function:: void fq_poly_gcd_euclidean_f(fq_t f, fq_poly_t G, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `A` and `B` or sets `f` to a factor of the modulus of ``ctx``. .. function:: slong _fq_poly_xgcd(fq_struct * G, fq_struct * S, fq_struct * T, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_ctx_t ctx) Computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void fq_poly_xgcd(fq_poly_t G, fq_poly_t S, fq_poly_t T, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. .. function:: slong _fq_poly_xgcd_euclidean_f(fq_t f, fq_struct * G, fq_struct * S, fq_struct * T, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_ctx_t ctx) Either sets `f = 1` and computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`; otherwise, sets `f` to a non-trivial factor of the modulus of ``ctx`` and leaves `G`, `S`, and `T` undefined. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void fq_poly_xgcd_euclidean_f(fq_t f, fq_poly_t G, fq_poly_t S, fq_poly_t T, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Either sets `f = 1` and computes the GCD of `A` and `B` or sets `f` to a non-trivial factor of the modulus of ``ctx``. If the GCD is computed, polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``; otherwise, they are undefined. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Divisibility testing -------------------------------------------------------------------------------- .. function:: int _fq_poly_divides(fq_struct * Q, const fq_struct * A, slong lenA, const fq_struct * B, slong lenB, const fq_t invB, const fq_ctx_t ctx) Returns `1` if ``(B, lenB)`` divides ``(A, lenA)`` exactly and sets `Q` to the quotient, otherwise returns `0`. It is assumed that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that `Q` has space for `\operatorname{len}(A) - \operatorname{len}(B) + 1` coefficients. Aliasing of `Q` with either of the inputs is not permitted. This function is currently unoptimised and provided for convenience only. .. function:: int fq_poly_divides(fq_poly_t Q, const fq_poly_t A, const fq_poly_t B, const fq_ctx_t ctx) Returns `1` if `B` divides `A` exactly and sets `Q` to the quotient, otherwise returns `0`. This function is currently unoptimised and provided for convenience only. Derivative -------------------------------------------------------------------------------- .. function:: void _fq_poly_derivative(fq_struct * rop, const fq_struct * op, slong len, const fq_ctx_t ctx) Sets ``(rop, len - 1)`` to the derivative of ``(op, len)``. Also handles the cases where ``len`` is `0` or `1` correctly. Supports aliasing of ``rop`` and ``op``. .. function:: void fq_poly_derivative(fq_poly_t rop, const fq_poly_t op, const fq_ctx_t ctx) Sets ``rop`` to the derivative of ``op``. Square root -------------------------------------------------------------------------------- .. function:: void _fq_poly_invsqrt_series(fq_struct * g, const fq_struct * h, slong n, fq_ctx_t mod) Set the first `n` terms of `g` to the series expansion of `1/\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1 and that `h` is zero-padded as necessary to length `n`. Aliasing is not permitted. .. function:: void fq_poly_invsqrt_series(fq_poly_t g, const fq_poly_t h, slong n, fq_ctx_t ctx) Set `g` to the series expansion of `1/\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: void _fq_poly_sqrt_series(fq_struct * g, const fq_struct * h, slong n, fq_ctx_t ctx) Set the first `n` terms of `g` to the series expansion of `\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1 and that `h` is zero-padded as necessary to length `n`. Aliasing is not permitted. .. function:: void fq_poly_sqrt_series(fq_poly_t g, const fq_poly_t h, slong n, fq_ctx_t ctx) Set `g` to the series expansion of `\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: int _fq_poly_sqrt(fq_struct * s, const fq_struct * p, slong n, fq_ctx_t mod) If ``(p, n)`` is a perfect square, sets ``(s, n / 2 + 1)`` to a square root of `p` and returns 1. Otherwise returns 0. .. function:: int fq_poly_sqrt(fq_poly_t s, const fq_poly_t p, fq_ctx_t mod) If `p` is a perfect square, sets `s` to a square root of `p` and returns 1. Otherwise returns 0. Evaluation -------------------------------------------------------------------------------- .. function:: void _fq_poly_evaluate_fq(fq_t rop, const fq_struct * op, slong len, const fq_t a, const fq_ctx_t ctx) Sets ``rop`` to ``(op, len)`` evaluated at `a`. Supports zero padding. There are no restrictions on ``len``, that is, ``len`` is allowed to be zero, too. .. function:: void fq_poly_evaluate_fq(fq_t rop, const fq_poly_t f, const fq_t a, const fq_ctx_t ctx) Sets ``rop`` to the value of `f(a)`. As the coefficient ring `\mathbf{F}_q` is finite, Horner's method is sufficient. Composition -------------------------------------------------------------------------------- .. function:: void _fq_poly_compose(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) Sets ``rop`` to the composition of ``(op1, len1)`` and ``(op2, len2)``. Assumes that ``rop`` has space for ``(len1-1)*(len2-1) + 1`` coefficients. Assumes that ``op1`` and ``op2`` are non-zero polynomials. Does not support aliasing between any of the inputs and the output. .. function:: void fq_poly_compose(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) Sets ``rop`` to the composition of ``op1`` and ``op2``. To be precise about the order of composition, denoting ``rop``, ``op1``, and ``op2`` by `f`, `g`, and `h`, respectively, sets `f(t) = g(h(t))`. .. function:: void _fq_poly_compose_mod_horner(fq_struct * res, const fq_struct * f, slong lenf, const fq_struct * g, const fq_struct * h, slong lenh, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void fq_poly_compose_mod_horner(fq_poly_t res, const fq_poly_t f, const fq_poly_t g, const fq_poly_t h, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. The algorithm used is Horner's rule. .. function:: void _fq_poly_compose_mod_horner_preinv(fq_struct * res, const fq_struct * f, slong lenf, const fq_struct * g, const fq_struct * h, slong lenh, const fq_struct * hinv, slong lenhiv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void fq_poly_compose_mod_horner_preinv(fq_poly_t res, const fq_poly_t f, const fq_poly_t g, const fq_poly_t h, const fq_poly_t hinv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is Horner's rule. .. function:: void _fq_poly_compose_mod_brent_kung(fq_struct * res, const fq_struct * f, slong lenf, const fq_struct * g, const fq_struct * h, slong lenh, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_poly_compose_mod_brent_kung(fq_poly_t res, const fq_poly_t f, const fq_poly_t g, const fq_poly_t h, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fq_poly_compose_mod_brent_kung_preinv(fq_struct * res, const fq_struct * f, slong lenf, const fq_struct * g, const fq_struct * h, slong lenh, const fq_struct * hinv, slong lenhiv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_poly_compose_mod_brent_kung_preinv(fq_poly_t res, const fq_poly_t f, const fq_poly_t g, const fq_poly_t h, const fq_poly_t hinv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fq_poly_compose_mod(fq_struct * res, const fq_struct * f, slong lenf, const fq_struct * g, const fq_struct * h, slong lenh, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. .. function:: void fq_poly_compose_mod(fq_poly_t res, const fq_poly_t f, const fq_poly_t g, const fq_poly_t h, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. .. function:: void _fq_poly_compose_mod_preinv(fq_struct * res, const fq_struct * f, slong lenf, const fq_struct * g, const fq_struct * h, slong lenh, const fq_struct * hinv, slong lenhiv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. .. function:: void fq_poly_compose_mod_preinv(fq_poly_t res, const fq_poly_t f, const fq_poly_t g, const fq_poly_t h, const fq_poly_t hinv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. .. function:: void _fq_poly_reduce_matrix_mod_poly (fq_mat_t A, const fq_mat_t B, const fq_poly_t f, const fq_ctx_t ctx) Sets the ith row of ``A`` to the reduction of the ith row of `B` modulo `f` for `i=1,\ldots,\sqrt{\deg(f)}`. We require `B` to be at least a `\sqrt{\deg(f)}\times \deg(f)` matrix and `f` to be nonzero. .. function:: void _fq_poly_precompute_matrix (fq_mat_t A, const fq_struct * f, const fq_struct * g, slong leng, const fq_struct * ginv, slong lenginv, const fq_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g`` and `g` to be nonzero. .. function:: void fq_poly_precompute_matrix (fq_mat_t A, const fq_poly_t f, const fq_poly_t g, const fq_poly_t ginv, const fq_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g``. .. function:: void _fq_poly_compose_mod_brent_kung_precomp_preinv(fq_struct * res, const fq_struct * f, slong lenf, const fq_mat_t A, const fq_struct * h, slong lenh, const fq_struct * hinv, slong lenhinv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_poly_compose_mod_brent_kung_precomp_preinv(fq_poly_t res, const fq_poly_t f, const fq_mat_t A, const fq_poly_t h, const fq_poly_t hinv, const fq_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. This version of Brent-Kung modular composition is particularly useful if one has to perform several modular composition of the form `f(g)` modulo `h` for fixed `g` and `h`. Output -------------------------------------------------------------------------------- .. function:: int _fq_poly_fprint_pretty(FILE * file, const fq_struct * poly, slong len, const char * x, const fq_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_poly_fprint_pretty(FILE * file, const fq_poly_t poly, const char * x, const fq_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_poly_print_pretty(const fq_struct * poly, slong len, const char * x, const fq_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_poly_print_pretty(const fq_poly_t poly, const char * x, const fq_ctx_t ctx) Prints the pretty representation of ``poly`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_poly_fprint(FILE * file, const fq_struct * poly, slong len, const fq_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_poly_fprint(FILE * file, const fq_poly_t poly, const fq_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_poly_print(const fq_struct * poly, slong len, const fq_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_poly_print(const fq_poly_t poly, const fq_ctx_t ctx) Prints the representation of ``poly`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: char * _fq_poly_get_str(const fq_struct * poly, slong len, const fq_ctx_t ctx) Returns the plain FLINT string representation of the polynomial ``(poly, len)``. .. function:: char * fq_poly_get_str(const fq_poly_t poly, const fq_ctx_t ctx) Returns the plain FLINT string representation of the polynomial ``poly``. .. function:: char * _fq_poly_get_str_pretty(const fq_struct * poly, slong len, const char * x, const fq_ctx_t ctx) Returns a pretty representation of the polynomial ``(poly, len)`` using the null-terminated string ``x`` as the variable name. .. function:: char * fq_poly_get_str_pretty(const fq_poly_t poly, const char * x, const fq_ctx_t ctx) Returns a pretty representation of the polynomial ``poly`` using the null-terminated string ``x`` as the variable name Inflation and deflation -------------------------------------------------------------------------------- .. function:: void fq_poly_inflate(fq_poly_t result, const fq_poly_t input, ulong inflation, const fq_ctx_t ctx) Sets ``result`` to the inflated polynomial `p(x^n)` where `p` is given by ``input`` and `n` is given by ``inflation``. .. function:: void fq_poly_deflate(fq_poly_t result, const fq_poly_t input, ulong deflation, const fq_ctx_t ctx) Sets ``result`` to the deflated polynomial `p(x^{1/n})` where `p` is given by ``input`` and `n` is given by ``deflation``. Requires `n > 0`. .. function:: ulong fq_poly_deflation(const fq_poly_t input, const fq_ctx_t ctx) Returns the largest integer by which ``input`` can be deflated. As special cases, returns 0 if ``input`` is the zero polynomial and 1 of ``input`` is a constant polynomial. flint-3.1.3/doc/source/fq_poly_factor.rst000066400000000000000000000232331461254215100204440ustar00rootroot00000000000000.. _fq-poly-factor: **fq_poly_factor.h** -- factorisation of univariate polynomials over finite fields ================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_poly_factor_struct .. type:: fq_poly_factor_t Memory Management -------------------------------------------------------------------------------- .. function:: void fq_poly_factor_init(fq_poly_factor_t fac, const fq_ctx_t ctx) Initialises ``fac`` for use. An :type:`fq_poly_factor_t` represents a polynomial in factorised form as a product of polynomials with associated exponents. .. function:: void fq_poly_factor_clear(fq_poly_factor_t fac, const fq_ctx_t ctx) Frees all memory associated with ``fac``. .. function:: void fq_poly_factor_realloc(fq_poly_factor_t fac, slong alloc, const fq_ctx_t ctx) Reallocates the factor structure to provide space for precisely ``alloc`` factors. .. function:: void fq_poly_factor_fit_length(fq_poly_factor_t fac, slong len, const fq_ctx_t ctx) Ensures that the factor structure has space for at least ``len`` factors. This function takes care of the case of repeated calls by always at least doubling the number of factors the structure can hold. Basic Operations -------------------------------------------------------------------------------- .. function:: void fq_poly_factor_set(fq_poly_factor_t res, const fq_poly_factor_t fac, const fq_ctx_t ctx) Sets ``res`` to the same factorisation as ``fac``. .. function:: void fq_poly_factor_print_pretty(const fq_poly_factor_t fac, const char * var, const fq_ctx_t ctx) Pretty-prints the entries of ``fac`` to standard output. .. function:: void fq_poly_factor_print(const fq_poly_factor_t fac, const fq_ctx_t ctx) Prints the entries of ``fac`` to standard output. .. function:: void fq_poly_factor_insert(fq_poly_factor_t fac, const fq_poly_t poly, slong exp, const fq_ctx_t ctx) Inserts the factor ``poly`` with multiplicity ``exp`` into the factorisation ``fac``. If ``fac`` already contains ``poly``, then ``exp`` simply gets added to the exponent of the existing entry. .. function:: void fq_poly_factor_concat(fq_poly_factor_t res, const fq_poly_factor_t fac, const fq_ctx_t ctx) Concatenates two factorisations. This is equivalent to calling :func:`fq_poly_factor_insert` repeatedly with the individual factors of ``fac``. Does not support aliasing between ``res`` and ``fac``. .. function:: void fq_poly_factor_pow(fq_poly_factor_t fac, slong exp, const fq_ctx_t ctx) Raises ``fac`` to the power ``exp``. .. function:: ulong fq_poly_remove(fq_poly_t f, const fq_poly_t p, const fq_ctx_t ctx) Removes the highest possible power of ``p`` from ``f`` and returns the exponent. Irreducibility Testing -------------------------------------------------------------------------------- .. function:: int fq_poly_is_irreducible(const fq_poly_t f, const fq_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. .. function:: int fq_poly_is_irreducible_ddf(const fq_poly_t f, const fq_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses fast distinct-degree factorisation. .. function:: int fq_poly_is_irreducible_ben_or(const fq_poly_t f, const fq_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses Ben-Or's irreducibility test. .. function:: int _fq_poly_is_squarefree(const fq_struct * f, slong len, const fq_ctx_t ctx) Returns 1 if ``(f, len)`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. There are no restrictions on the length. .. function:: int fq_poly_is_squarefree(const fq_poly_t f, const fq_ctx_t ctx) Returns 1 if ``f`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. Factorisation -------------------------------------------------------------------------------- .. function:: int fq_poly_factor_equal_deg_prob(fq_poly_t factor, flint_rand_t state, const fq_poly_t pol, slong d, const fq_ctx_t ctx) Probabilistic equal degree factorisation of ``pol`` into irreducible factors of degree ``d``. If it passes, a factor is placed in factor and 1 is returned, otherwise 0 is returned and the value of factor is undetermined. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fq_poly_factor_equal_deg(fq_poly_factor_t factors, const fq_poly_t pol, slong d, const fq_ctx_t ctx) Assuming ``pol`` is a product of irreducible factors all of degree ``d``, finds all those factors and places them in factors. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fq_poly_factor_split_single(fq_poly_t linfactor, const fq_poly_t input, const fq_ctx_t ctx) Assuming ``input`` is a product of factors all of degree 1, finds a single linear factor of ``input`` and places it in ``linfactor``. Requires that ``input`` be monic and non-constant. .. function:: void fq_poly_factor_distinct_deg(fq_poly_factor_t res, const fq_poly_t poly, slong * const * degs, const fq_ctx_t ctx) Factorises a monic non-constant squarefree polynomial ``poly`` of degree `n` into factors `f[d]` such that for `1 \leq d \leq n` `f[d]` is the product of the monic irreducible factors of ``poly`` of degree `d`. Factors are stored in ``res``, associated powers of irreducible polynomials are stored in ``degs`` in the same order as factors. Requires that ``degs`` have enough space for irreducible polynomials' powers (maximum space required is ``n * sizeof(slong)``). .. function:: void fq_poly_factor_squarefree(fq_poly_factor_t res, const fq_poly_t f, const fq_ctx_t ctx) Sets ``res`` to a squarefree factorization of ``f``. .. function:: void fq_poly_factor(fq_poly_factor_t res, fq_t lead, const fq_poly_t f, const fq_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors choosing the best algorithm for given modulo and degree. The output ``lead`` is set to the leading coefficient of `f` upon return. Choice of algorithm is based on heuristic measurements. .. function:: void fq_poly_factor_cantor_zassenhaus(fq_poly_factor_t res, const fq_poly_t f, const fq_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Cantor-Zassenhaus algorithm. .. function:: void fq_poly_factor_kaltofen_shoup(fq_poly_factor_t res, const fq_poly_t poly, const fq_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the fast version of Cantor-Zassenhaus algorithm proposed by Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby step/giant step” strategy for the distinct-degree factorization step. .. function:: void fq_poly_factor_berlekamp(fq_poly_factor_t factors, const fq_poly_t f, const fq_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Berlekamp algorithm. .. function:: void fq_poly_factor_with_berlekamp(fq_poly_factor_t res, fq_t leading_coeff, const fq_poly_t f, const fq_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Berlekamp factorisation on all the individual square-free factors. .. function:: void fq_poly_factor_with_cantor_zassenhaus(fq_poly_factor_t res, fq_t leading_coeff, const fq_poly_t f, const fq_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Cantor-Zassenhaus on all the individual square-free factors. .. function:: void fq_poly_factor_with_kaltofen_shoup(fq_poly_factor_t res, fq_t leading_coeff, const fq_poly_t f, const fq_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Kaltofen-Shoup on all the individual square-free factors. .. function:: void fq_poly_iterated_frobenius_preinv(fq_poly_t * rop, slong n, const fq_poly_t v, const fq_poly_t vinv, const fq_ctx_t ctx) Sets ``rop[i]`` to be `x^{q^i}\bmod v` for `0 \le i < n`. It is required that ``vinv`` is the inverse of the reverse of ``v`` mod ``x^lenv``. Root Finding -------------------------------------------------------------------------------- .. function:: void fq_poly_roots(fq_poly_factor_t r, const fq_poly_t f, int with_multiplicity, const fq_ctx_t ctx) Fill `r` with factors of the form `x - r_i` where the `r_i` are the distinct roots of a nonzero `f` in `F_q`. If `with\_multiplicity` is zero, the exponent `e_i` of the factor `x - r_i` is `1`. Otherwise, it is the largest `e_i` such that `(x-r_i)^e_i` divides `f`. This function throws if `f` is zero, but is otherwise always successful. flint-3.1.3/doc/source/fq_vec.rst000066400000000000000000000100511461254215100166720ustar00rootroot00000000000000.. _fq-vec: **fq_vec.h** -- vectors over finite fields =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: fq_struct * _fq_vec_init(slong len, const fq_ctx_t ctx) Returns an initialised vector of ``fq``'s of given length. .. function:: void _fq_vec_clear(fq_struct * vec, slong len, const fq_ctx_t ctx) Clears the entries of ``(vec, len)`` and frees the space allocated for ``vec``. Randomisation -------------------------------------------------------------------------------- .. function:: void _fq_vec_randtest(fq_struct * f, flint_rand_t state, slong len, const fq_ctx_t ctx) Sets the entries of a vector of the given length to elements of the finite field. Input and output -------------------------------------------------------------------------------- .. function:: int _fq_vec_fprint(FILE * file, const fq_struct * vec, slong len, const fq_ctx_t ctx) Prints the vector of given length to the stream ``file``. The format is the length followed by two spaces, then a space separated list of coefficients. If the length is zero, only `0` is printed. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_vec_print(const fq_struct * vec, slong len, const fq_ctx_t ctx) Prints the vector of given length to ``stdout``. For further details, see ``_fq_vec_fprint()``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _fq_vec_set(fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_ctx_t ctx) Makes a copy of ``(vec2, len2)`` into ``vec1``. .. function:: void _fq_vec_swap(fq_struct * vec1, fq_struct * vec2, slong len2, const fq_ctx_t ctx) Swaps the elements in ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fq_vec_zero(fq_struct * vec, slong len, const fq_ctx_t ctx) Zeros the entries of ``(vec, len)``. .. function:: void _fq_vec_neg(fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_ctx_t ctx) Negates ``(vec2, len2)`` and places it into ``vec1``. Comparison -------------------------------------------------------------------------------- .. function:: int _fq_vec_equal(const fq_struct * vec1, const fq_struct * vec2, slong len, const fq_ctx_t ctx) Compares two vectors of the given length and returns `1` if they are equal, otherwise returns `0`. .. function:: int _fq_vec_is_zero(const fq_struct * vec, slong len, const fq_ctx_t ctx) Returns `1` if ``(vec, len)`` is zero, and `0` otherwise. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fq_vec_add(fq_struct * res, const fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_ctx_t ctx) Sets ``(res, len2)`` to the sum of ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fq_vec_sub(fq_struct * res, const fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_ctx_t ctx) Sets ``(res, len2)`` to ``(vec1, len2)`` minus ``(vec2, len2)``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fq_vec_scalar_addmul_fq(fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_t c, const fq_ctx_t ctx) Adds ``(vec2, len2)`` times `c` to ``(vec1, len2)``, where `c` is a ``fq_t``. .. function:: void _fq_vec_scalar_submul_fq(fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_t c, const fq_ctx_t ctx) Subtracts ``(vec2, len2)`` times `c` from ``(vec1, len2)``, where `c` is a ``fq_t``. Dot products -------------------------------------------------------------------------------- .. function:: void _fq_vec_dot(fq_t res, const fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_ctx_t ctx) Sets ``res`` to the dot product of (``vec1``, ``len``) and (``vec2``, ``len``). flint-3.1.3/doc/source/fq_zech.rst000066400000000000000000000515171461254215100170620ustar00rootroot00000000000000.. _fq-zech: **fq_zech.h** -- finite fields (Zech logarithm representation) =============================================================================== We represent an element of the finite field as a power of a generator for the multiplicative group of the finite field. In particular, we use a root of `f(x)`, where `f(X) \in \mathbf{F}_p[X]` is a monic, irreducible polynomial of degree `n`, as a polynomial in `\mathbf{F}_p[X]` of degree less than `n`. The underlying data structure is just an ``mp_limb_t``. The default choice for `f(X)` is the Conway polynomial for the pair `(p,n)`, enabled by Frank Lübeck's data base of Conway polynomials using the :func:`_nmod_poly_conway` function. If a Conway polynomial is not available, then a random irreducible polynomial will be chosen for `f(X)`. Additionally, the user is able to supply their own `f(X)`. We required that the order of the field fits inside of an ``mp_limb_t``; however, it is recommended that `p^n < 2^{20}` due to the time and memory needed to compute the Zech logarithm table. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_ctx_struct .. type:: fq_zech_ctx_t .. type:: fq_zech_struct .. type:: fq_zech_t Context Management -------------------------------------------------------------------------------- .. function:: void fq_zech_ctx_init_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator. By default, it will try use a Conway polynomial; if one is not available, a random primitive polynomial will be used. Assumes that `p` is a prime and :math:`p^d < 2^{\mathtt{FLINT\_BITS}}`. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: int _fq_zech_ctx_init_conway_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var) Attempts to initialise the context for prime `p` and extension degree `d`, with name ``var`` for the generator using a Conway polynomial for the modulus. Returns `1` if the Conway polynomial is in the database for the given size and the initialization is successful; otherwise, returns `0`. Assumes that `p` is a prime and `p^d < 2^\mathtt{FLINT\_BITS}`. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_zech_ctx_init_conway_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator using a Conway polynomial for the modulus. Assumes that `p` is a prime and `p^d < 2^\mathtt{FLINT\_BITS}`. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_zech_ctx_init_random_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var) Initialises the context for prime `p` and extension degree `d`, with name ``var`` for the generator using a random primitive polynomial. Assumes that `p` is a prime and `p^d < 2^\mathtt{FLINT\_BITS}`. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: void fq_zech_ctx_init_modulus(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char * var) Initialises the context for given ``modulus`` with name ``var`` for the generator. Assumes that ``modulus`` is an primitive polynomial over `\mathbf{F}_{p}`. An exception is raised if a non-primitive modulus is detected. Assumes that the string ``var`` is a null-terminated string of length at least one. .. function:: int fq_zech_ctx_init_modulus_check(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char * var) As per the previous function, but returns `0` if the modulus was not primitive and `1` if the context was successfully initialised with the given modulus. No exception is raised. .. function:: void fq_zech_ctx_init_fq_nmod_ctx(fq_zech_ctx_t ctx, fq_nmod_ctx_t ctxn) Initializes the context ``ctx`` to be the Zech representation for the finite field given by ``ctxn``. .. function:: int fq_zech_ctx_init_fq_nmod_ctx_check(fq_zech_ctx_t ctx, fq_nmod_ctx_t ctxn) As per the previous function but returns `0` if a non-primitive modulus is detected. Returns `0` if the Zech representation was successfully initialised. .. function:: void fq_zech_ctx_init_randtest(fq_zech_ctx_t ctx, flint_rand_t state, int type) Initialises ``ctx`` to a random finite field, where the prime and degree is set according to ``type``. If ``type`` is `0` the prime and degree may be large, else if ``type`` is `1` the degree is small but the prime may be large, else if ``type`` is `2` the prime is small but the degree may be large, else if ``type`` is `3` both prime and degree are small. .. function:: void fq_zech_ctx_init_randtest_reducible(fq_zech_ctx_t ctx, flint_rand_t state, int type) Since the Zech logarithm representation does not work with a non-irreducible modulus, this function does the same as :func:`fq_zech_ctx_init_randtest`. .. function:: void fq_zech_ctx_clear(fq_zech_ctx_t ctx) Clears all memory that has been allocated as part of the context. .. function:: const nmod_poly_struct * fq_zech_ctx_modulus(const fq_zech_ctx_t ctx) Returns a pointer to the modulus in the context. .. function:: slong fq_zech_ctx_degree(const fq_zech_ctx_t ctx) Returns the degree of the field extension `[\mathbf{F}_{q} : \mathbf{F}_{p}]`, which is equal to `\log_{p} q`. .. function:: ulong fq_zech_ctx_prime(const fq_zech_ctx_t ctx) Returns the prime `p` of the context. .. function:: void fq_zech_ctx_order(fmpz_t f, const fq_zech_ctx_t ctx) Sets `f` to be the size of the finite field. .. function:: mp_limb_t fq_zech_ctx_order_ui(const fq_zech_ctx_t ctx) Returns the size of the finite field. .. function:: int fq_zech_ctx_fprint(FILE * file, const fq_zech_ctx_t ctx) Prints the context information to {\tt{file}}. Returns 1 for a success and a negative number for an error. .. function:: void fq_zech_ctx_print(const fq_zech_ctx_t ctx) Prints the context information to {\tt{stdout}}. Memory management -------------------------------------------------------------------------------- .. function:: void fq_zech_init(fq_zech_t rop, const fq_zech_ctx_t ctx) Initialises the element ``rop``, setting its value to `0`. .. function:: void fq_zech_init2(fq_zech_t rop, const fq_zech_ctx_t ctx) Initialises ``poly`` with at least enough space for it to be an element of ``ctx`` and sets it to `0`. .. function:: void fq_zech_clear(fq_zech_t rop, const fq_zech_ctx_t ctx) Clears the element ``rop``. .. function:: void _fq_zech_sparse_reduce(mp_ptr R, slong lenR, const fq_zech_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx``. .. function:: void _fq_zech_dense_reduce(mp_ptr R, slong lenR, const fq_zech_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx`` using Newton division. .. function:: void _fq_zech_reduce(mp_ptr r, slong lenR, const fq_zech_ctx_t ctx) Reduces ``(R, lenR)`` modulo the polynomial `f` given by the modulus of ``ctx``. Does either sparse or dense reduction based on ``ctx->sparse_modulus``. .. function:: void fq_zech_reduce(fq_zech_t rop, const fq_zech_ctx_t ctx) Reduces the polynomial ``rop`` as an element of `\mathbf{F}_p[X] / (f(X))`. Basic arithmetic -------------------------------------------------------------------------------- .. function:: void fq_zech_add(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the sum of ``op1`` and ``op2``. .. function:: void fq_zech_sub(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and ``op2``. .. function:: void fq_zech_sub_one(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and `1`. .. function:: void fq_zech_neg(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the negative of ``op``. .. function:: void fq_zech_mul(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void fq_zech_mul_fmpz(fq_zech_t rop, const fq_zech_t op, const fmpz_t x, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_zech_mul_si(fq_zech_t rop, const fq_zech_t op, slong x, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_zech_mul_ui(fq_zech_t rop, const fq_zech_t op, ulong x, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `x`, reducing the output in the given context. .. function:: void fq_zech_sqr(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the square of ``op``, reducing the output in the given context. .. function:: void fq_zech_div(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the quotient of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void _fq_zech_inv(mp_ptr * rop, mp_srcptr * op, slong len, const fq_zech_ctx_t ctx) Sets ``(rop, d)`` to the inverse of the non-zero element ``(op, len)``. .. function:: void fq_zech_inv(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the inverse of the non-zero element ``op``. .. function:: void fq_zech_gcdinv(fq_zech_t f, fq_zech_t inv, const fq_zech_t op, const fq_zech_ctx_t ctx) Sets ``inv`` to be the inverse of ``op`` modulo the modulus of ``ctx`` and sets ``f`` to one. Since the modulus for ``ctx`` is always irreducible, ``op`` is always invertible. .. function:: void _fq_zech_pow(fmpz * rop, const fmpz * op, slong len, const fmpz_t e, const fmpz * a, const slong * j, slong lena, const fmpz_t p) Sets ``(rop, 2*d-1)`` to ``(op,len)`` raised to the power `e`, reduced modulo `f(X)`, the modulus of ``ctx``. Assumes that `e \geq 0` and that ``len`` is positive and at most `d`. Although we require that ``rop`` provides space for `2d - 1` coefficients, the output will be reduced modulo `f(X)`, which is a polynomial of degree `d`. Does not support aliasing. .. function:: void fq_zech_pow(fq_zech_t rop, const fq_zech_t op, const fmpz_t e, const fq_zech_ctx_t ctx) Sets ``rop`` the ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. .. function:: void fq_zech_pow_ui(fq_zech_t rop, const fq_zech_t op, const ulong e, const fq_zech_ctx_t ctx) Sets ``rop`` the ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to `1` whenever `e = 0`. Roots -------------------------------------------------------------------------------- .. function:: int fq_zech_sqrt(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx) Sets ``rop`` to the square root of ``op1`` if it is a square, and return `1`, otherwise return `0`. .. function:: void fq_zech_pth_root(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx) Sets ``rop`` to a `p^{th}` root root of ``op1``. Currently, this computes the root by raising ``op1`` to `p^{d-1}` where `d` is the degree of the extension. .. function:: int fq_zech_is_square(const fq_zech_t op, const fq_zech_ctx_t ctx) Return ``1`` if ``op`` is a square. Output -------------------------------------------------------------------------------- .. function:: int fq_zech_fprint_pretty(FILE * file, const fq_zech_t op, const fq_zech_ctx_t ctx) Prints a pretty representation of ``op`` to ``file``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. .. function:: void fq_zech_print_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx) Prints a pretty representation of ``op`` to ``stdout``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. .. function:: int fq_zech_fprint(FILE * file, const fq_zech_t op, const fq_zech_ctx_t ctx) Prints a representation of ``op`` to ``file``. .. function:: void fq_zech_print(const fq_zech_t op, const fq_zech_ctx_t ctx) Prints a representation of ``op`` to ``stdout``. .. function:: char * fq_zech_get_str(const fq_zech_t op, const fq_zech_ctx_t ctx) Returns the plain FLINT string representation of the element ``op``. .. function:: char * fq_zech_get_str_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx) Returns a pretty representation of the element ``op`` using the null-terminated string ``x`` as the variable name. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_zech_randtest(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) Generates a random element of `\mathbf{F}_q`. .. function:: void fq_zech_randtest_not_zero(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) Generates a random non-zero element of `\mathbf{F}_q`. .. function:: void fq_zech_randtest_dense(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) Generates a random element of `\mathbf{F}_q` which has an underlying polynomial with dense coefficients. .. function:: void fq_zech_rand(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) Generates a high quality random element of `\mathbf{F}_q`. .. function:: void fq_zech_rand_not_zero(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) Generates a high quality non-zero random element of `\mathbf{F}_q`. Assignments and conversions -------------------------------------------------------------------------------- .. function:: void fq_zech_set(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to ``op``. .. function:: void fq_zech_set_si(fq_zech_t rop, const slong x, const fq_zech_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_zech_set_ui(fq_zech_t rop, const ulong x, const fq_zech_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_zech_set_fmpz(fq_zech_t rop, const fmpz_t x, const fq_zech_ctx_t ctx) Sets ``rop`` to ``x``, considered as an element of `\mathbf{F}_p`. .. function:: void fq_zech_swap(fq_zech_t op1, fq_zech_t op2, const fq_zech_ctx_t ctx) Swaps the two elements ``op1`` and ``op2``. .. function:: void fq_zech_zero(fq_zech_t rop, const fq_zech_ctx_t ctx) Sets ``rop`` to zero. .. function:: void fq_zech_one(fq_zech_t rop, const fq_zech_ctx_t ctx) Sets ``rop`` to one, reduced in the given context. .. function:: void fq_zech_gen(fq_zech_t rop, const fq_zech_ctx_t ctx) Sets ``rop`` to a generator for the finite field. There is no guarantee this is a multiplicative generator of the finite field. .. function:: int fq_zech_get_fmpz(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) If ``op`` has a lift to the integers, return `1` and set ``rop`` to the lift in `[0,p)`. Otherwise, return `0` and leave `rop` undefined. .. function:: void fq_zech_get_fq_nmod(fq_nmod_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the ``fq_nmod_t`` element corresponding to ``op``. .. function:: void fq_zech_set_fq_nmod(fq_zech_t rop, const fq_nmod_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the ``fq_zech_t`` element corresponding to ``op``. .. function:: void fq_zech_get_nmod_poly(nmod_poly_t a, const fq_zech_t b, const fq_zech_ctx_t ctx) Set ``a`` to a representative of ``b`` in ``ctx``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. .. function:: void fq_zech_set_nmod_poly(fq_zech_t a, const nmod_poly_t b, const fq_zech_ctx_t ctx) Set ``a`` to the element in ``ctx`` with representative ``b``. The representatives are taken in `(\mathbb{Z}/p\mathbb{Z})[x]/h(x)` where `h(x)` is the defining polynomial in ``ctx``. .. function:: void fq_zech_get_nmod_mat(nmod_mat_t col, const fq_zech_t a, const fq_zech_ctx_t ctx) Convert ``a`` to a column vector of length ``degree(ctx)``. .. function:: void fq_zech_set_nmod_mat(fq_zech_t a, const nmod_mat_t col, const fq_zech_ctx_t ctx) Convert a column vector ``col`` of length ``degree(ctx)`` to an element of ``ctx``. Comparison -------------------------------------------------------------------------------- .. function:: int fq_zech_is_zero(const fq_zech_t op, const fq_zech_ctx_t ctx) Returns whether ``op`` is equal to zero. .. function:: int fq_zech_is_one(const fq_zech_t op, const fq_zech_ctx_t ctx) Returns whether ``op`` is equal to one. .. function:: int fq_zech_equal(const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) Returns whether ``op1`` and ``op2`` are equal. .. function:: int fq_zech_is_invertible(const fq_zech_t op, const fq_zech_ctx_t ctx) Returns whether ``op`` is an invertible element. .. function:: int fq_zech_is_invertible_f(fq_zech_t f, const fq_zech_t op, const fq_zech_ctx_t ctx) Returns whether ``op`` is an invertible element. If it is not, then ``f`` is set of a factor of the modulus. Since the modulus for an ``fq_zech_ctx_t`` is always irreducible, then any non-zero ``op`` will be invertible. Special functions -------------------------------------------------------------------------------- .. function:: void fq_zech_trace(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the trace of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the trace of `a` as the trace of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\sum_{i=0}^{d-1} \Sigma^i (a)`, where `d = \log_{p} q`. .. function:: void fq_zech_norm(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) Computes the norm of ``op``. For an element `a \in \mathbf{F}_q`, multiplication by `a` defines a `\mathbf{F}_p`-linear map on `\mathbf{F}_q`. We define the norm of `a` as the determinant of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)` then the trace of `a` is equal to `\prod_{i=0}^{d-1} \Sigma^i (a)`, where `d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)`. Algorithm selection is automatic depending on the input. .. function:: void fq_zech_frobenius(fq_zech_t rop, const fq_zech_t op, slong e, const fq_zech_ctx_t ctx) Evaluates the homomorphism `\Sigma^e` at ``op``. Recall that `\mathbf{F}_q / \mathbf{F}_p` is Galois with Galois group `\langle \sigma \rangle`, which is also isomorphic to `\mathbf{Z}/d\mathbf{Z}`, where `\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)` is the Frobenius element `\sigma \colon x \mapsto x^p`. .. function:: int fq_zech_multiplicative_order(fmpz * ord, const fq_zech_t op, const fq_zech_ctx_t ctx) Computes the order of ``op`` as an element of the multiplicative group of ``ctx``. Returns 0 if ``op`` is 0, otherwise it returns 1 if ``op`` is a generator of the multiplicative group, and -1 if it is not. Note that ``ctx`` must already correspond to a finite field defined by a primitive polynomial and so this function cannot be used to check primitivity of the generator, but can be used to check that other elements are primitive. .. function:: int fq_zech_is_primitive(const fq_zech_t op, const fq_zech_ctx_t ctx) Returns whether ``op`` is primitive, i.e., whether it is a generator of the multiplicative group of ``ctx``. Bit packing -------------------------------------------------------------------------------- .. function:: void fq_zech_bit_pack(fmpz_t f, const fq_zech_t op, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx) Packs ``op`` into bitfields of size ``bit_size``, writing the result to ``f``. .. function:: void fq_zech_bit_unpack(fq_zech_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx) Unpacks into ``rop`` the element with coefficients packed into fields of size ``bit_size`` as represented by the integer ``f``. flint-3.1.3/doc/source/fq_zech_embed.rst000066400000000000000000000110501461254215100202020ustar00rootroot00000000000000.. _fq-zech-embed: **fq_zech_embed.h** -- Computing isomorphisms and embeddings of finite fields ------------------------------------------------------------------------------- .. function:: void fq_zech_embed_gens(fq_zech_t gen_sub, fq_zech_t gen_sup, nmod_poly_t minpoly, const fq_zech_ctx_t sub_ctx, const fq_zech_ctx_t sup_ctx) Given two contexts ``sub_ctx`` and ``sup_ctx``, such that ``degree(sub_ctx)`` divides ``degree(sup_ctx)``, compute: * an element ``gen_sub`` in ``sub_ctx`` such that ``gen_sub`` generates the finite field defined by ``sub_ctx``, * its minimal polynomial ``minpoly``, * a root ``gen_sup`` of ``minpoly`` inside the field defined by ``sup_ctx``. These data uniquely define an embedding of ``sub_ctx`` into ``sup_ctx``. .. function:: void _fq_zech_embed_gens_naive(fq_zech_t gen_sub, fq_zech_t gen_sup, nmod_poly_t minpoly, const fq_zech_ctx_t sub_ctx, const fq_zech_ctx_t sup_ctx) Given two contexts ``sub_ctx`` and ``sup_ctx``, such that ``degree(sub_ctx)`` divides ``degree(sup_ctx)``, compute an embedding of ``sub_ctx`` into ``sup_ctx`` defined as follows: * ``gen_sub`` is the canonical generator of ``sup_ctx`` (i.e., the class of `X`), * ``minpoly`` is the defining polynomial of ``sub_ctx``, * ``gen_sup`` is a root of ``minpoly`` inside the field defined by ``sup_ctx``. .. function:: void fq_zech_embed_matrices(nmod_mat_t embed, nmod_mat_t project, const fq_zech_t gen_sub, const fq_zech_ctx_t sub_ctx, const fq_zech_t gen_sup, const fq_zech_ctx_t sup_ctx, const nmod_poly_t gen_minpoly) Given: * two contexts ``sub_ctx`` and ``sup_ctx``, of respective degrees `m` and `n`, such that `m` divides `n`; * a generator ``gen_sub`` of ``sub_ctx``, its minimal polynomial ``gen_minpoly``, and a root ``gen_sup`` of ``gen_minpoly`` in ``sup_ctx``, as returned by ``fq_zech_embed_gens``; Compute: * the `n\times m` matrix ``embed`` mapping ``gen_sub`` to ``gen_sup``, and all their powers accordingly; * an `m\times n` matrix ``project`` such that ``project`` `\times` ``embed`` is the `m\times m` identity matrix. .. function:: void fq_zech_embed_trace_matrix(nmod_mat_t res, const nmod_mat_t basis, const fq_zech_ctx_t sub_ctx, const fq_zech_ctx_t sup_ctx) Given: * two contexts ``sub_ctx`` and ``sup_ctx``, of degrees `m` and `n`, such that `m` divides `n`; * an `n\times m` matrix ``basis`` that maps ``sub_ctx`` to an isomorphic subfield in ``sup_ctx``; Compute the `m\times n` matrix of the trace from ``sup_ctx`` to ``sub_ctx``. This matrix is computed as ``embed_dual_to_mono_matrix(_, sub_ctx)`` `\times` ``basis``:sup:`t` `\times` ``embed_mono_to_dual_matrix(_, sup_ctx)}``. **Note:** if `m=n`, ``basis`` represents a Frobenius, and the result is its inverse matrix. .. function:: void fq_zech_embed_composition_matrix(nmod_mat_t matrix, const fq_zech_t gen, const fq_zech_ctx_t ctx) Compute the *composition matrix* of ``gen``. For an element `a\in\mathbf{F}_{p^n}`, its composition matrix is the matrix whose columns are `a^0, a^1, \ldots, a^{n-1}`. .. function:: void fq_zech_embed_composition_matrix_sub(nmod_mat_t matrix, const fq_zech_t gen, const fq_zech_ctx_t ctx, slong trunc) Compute the *composition matrix* of ``gen``, truncated to ``trunc`` columns. .. function:: void fq_zech_embed_mul_matrix(nmod_mat_t matrix, const fq_zech_t gen, const fq_zech_ctx_t ctx) Compute the *multiplication matrix* of ``gen``. For an element `a` in `\mathbf{F}_{p^n}=\mathbf{F}_p[x]`, its multiplication matrix is the matrix whose columns are `a, ax, \dots, ax^{n-1}`. .. function:: void fq_zech_embed_mono_to_dual_matrix(nmod_mat_t res, const fq_zech_ctx_t ctx) Compute the change of basis matrix from the monomial basis of ``ctx`` to its dual basis. .. function:: void fq_zech_embed_dual_to_mono_matrix(nmod_mat_t res, const fq_zech_ctx_t ctx) Compute the change of basis matrix from the dual basis of ``ctx`` to its monomial basis. .. function:: void fq_zech_modulus_pow_series_inv(nmod_poly_t res, const fq_zech_ctx_t ctx, slong trunc) Compute the power series inverse of the reverse of the modulus of ``ctx`` up to `O(x^\texttt{trunc})`. .. function:: void fq_zech_modulus_derivative_inv(fq_zech_t m_prime, fq_zech_t m_prime_inv, const fq_zech_ctx_t ctx) Compute the derivative ``m_prime`` of the modulus of ``ctx`` as an element of ``ctx``, and its inverse ``m_prime_inv``. flint-3.1.3/doc/source/fq_zech_mat.rst000066400000000000000000000523051461254215100177170ustar00rootroot00000000000000.. _fq-zech-mat: **fq_zech_mat.h** -- matrices over finite fields (Zech logarithm representation) ================================================================================ Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_mat_struct .. type:: fq_zech_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_init(fq_zech_mat_t mat, slong rows, slong cols, const fq_zech_ctx_t ctx) Initialises ``mat`` to a ``rows``-by-``cols`` matrix with coefficients in `\mathbf{F}_{q}` given by ``ctx``. All elements are set to zero. .. function:: void fq_zech_mat_init_set(fq_zech_mat_t mat, const fq_zech_mat_t src, const fq_zech_ctx_t ctx) Initialises ``mat`` and sets its dimensions and elements to those of ``src``. .. function:: void fq_zech_mat_clear(fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Clears the matrix and releases any memory it used. The matrix cannot be used again until it is initialised. This function must be called exactly once when finished using an ``fq_zech_mat_t`` object. .. function:: void fq_zech_mat_set(fq_zech_mat_t mat, const fq_zech_mat_t src, const fq_zech_ctx_t ctx) Sets ``mat`` to a copy of ``src``. It is assumed that ``mat`` and ``src`` have identical dimensions. Basic properties and manipulation -------------------------------------------------------------------------------- .. function:: fq_zech_struct * fq_zech_mat_entry(const fq_zech_mat_t mat, slong i, slong j) Directly accesses the entry in ``mat`` in row `i` and column `j`, indexed from zero. No bounds checking is performed. .. function:: void fq_zech_mat_entry_set(fq_zech_mat_t mat, slong i, slong j, const fq_zech_t x, const fq_zech_ctx_t ctx) Sets the entry in ``mat`` in row `i` and column `j` to ``x``. .. function:: slong fq_zech_mat_nrows(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_zech_mat_ncols(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Returns the number of columns in ``mat``. .. function:: void fq_zech_mat_swap(fq_zech_mat_t mat1, fq_zech_mat_t mat2, const fq_zech_ctx_t ctx) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. function:: void fq_zech_mat_swap_entrywise(fq_zech_mat_t mat1, fq_zech_mat_t mat2, const fq_zech_ctx_t ctx) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: void fq_zech_mat_zero(fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Sets all entries of ``mat`` to 0. .. function:: void fq_zech_mat_one(fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Sets all diagonal entries of ``mat`` to 1 and all other entries to 0. Conversions -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_set_nmod_mat(fq_zech_mat_t mat1, const nmod_mat_t mat2, const fq_zech_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. .. function:: void fq_zech_mat_set_fmpz_mod_mat(fq_zech_mat_t mat1, const fmpz_mod_mat_t mat2, const fq_zech_ctx_t ctx) Sets the matrix ``mat1`` to the matrix ``mat2``. Concatenate -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_concat_vertical(fq_zech_mat_t res, const fq_zech_mat_t mat1, const fq_zech_mat_t mat2, const fq_zech_ctx_t ctx) Sets ``res`` to vertical concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `k \times n`, ``res`` : `(m + k) \times n`. .. function:: void fq_zech_mat_concat_horizontal(fq_zech_mat_t res, const fq_zech_mat_t mat1, const fq_zech_mat_t mat2, const fq_zech_ctx_t ctx) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `m \times k`, ``res`` : `m \times (n + k)`. Printing -------------------------------------------------------------------------------- .. function:: int fq_zech_mat_print_pretty(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Pretty-prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_zech_mat_fprint_pretty(FILE * file, const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Pretty-prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_zech_mat_print(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. .. function:: int fq_zech_mat_fprint(FILE * file, const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Prints ``mat`` to ``file``. A header is printed followed by the rows enclosed in brackets. In case of success, returns a positive value. In case of failure, returns a non-positive value. Window -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_window_init(fq_zech_mat_t window, const fq_zech_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fq_zech_ctx_t ctx) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0,0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void fq_zech_mat_window_clear(fq_zech_mat_t window, const fq_zech_ctx_t ctx) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. Random matrix generation -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_randtest(fq_zech_mat_t mat, flint_rand_t state, const fq_zech_ctx_t ctx) Sets the elements of ``mat`` to random elements of `\mathbf{F}_{q}`, given by ``ctx``. .. function:: int fq_zech_mat_randpermdiag(fq_zech_mat_t mat, flint_rand_t state, fq_zech_struct * diag, slong n, const fq_zech_ctx_t ctx) Sets ``mat`` to a random permutation of the diagonal matrix with `n` leading entries given by the vector ``diag``. It is assumed that the main diagonal of ``mat`` has room for at least `n` entries. Returns `0` or `1`, depending on whether the permutation is even or odd respectively. .. function:: void fq_zech_mat_randrank(fq_zech_mat_t mat, flint_rand_t state, slong rank, const fq_zech_ctx_t ctx) Sets ``mat`` to a random sparse matrix with the given rank, having exactly as many non-zero elements as the rank, with the non-zero elements being uniformly random elements of `\mathbf{F}_{q}`. The matrix can be transformed into a dense matrix with unchanged rank by subsequently calling :func:`fq_zech_mat_randops`. .. function:: void fq_zech_mat_randops(fq_zech_mat_t mat, flint_rand_t state, slong count, const fq_zech_ctx_t ctx) Randomises ``mat`` by performing elementary row or column operations. More precisely, at most ``count`` random additions or subtractions of distinct rows and columns will be performed. This leaves the rank (and for square matrices, determinant) unchanged. .. function:: void fq_zech_mat_randtril(fq_zech_mat_t mat, flint_rand_t state, int unit, const fq_zech_ctx_t ctx) Sets ``mat`` to a random lower triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. .. function:: void fq_zech_mat_randtriu(fq_zech_mat_t mat, flint_rand_t state, int unit, const fq_zech_ctx_t ctx) Sets ``mat`` to a random upper triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. Comparison -------------------------------------------------------------------------------- .. function:: int fq_zech_mat_equal(const fq_zech_mat_t mat1, const fq_zech_mat_t mat2, const fq_zech_ctx_t ctx) Returns nonzero if mat1 and mat2 have the same dimensions and elements, and zero otherwise. .. function:: int fq_zech_mat_is_zero(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Returns a non-zero value if all entries ``mat`` are zero, and otherwise returns zero. .. function:: int fq_zech_mat_is_one(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Returns a non-zero value if all entries ``mat`` are zero except the diagonal entries which must be one, otherwise returns zero. .. function:: int fq_zech_mat_is_empty(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int fq_zech_mat_is_square(const fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_add(fq_zech_mat_t C, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Computes `C = A + B`. Dimensions must be identical. .. function:: void fq_zech_mat_sub(fq_zech_mat_t C, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Computes `C = A - B`. Dimensions must be identical. .. function:: void fq_zech_mat_neg(fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Sets `B = -A`. Dimensions must be identical. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_mul(fq_zech_mat_t C, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. This function automatically chooses between classical and KS multiplication. .. function:: void fq_zech_mat_mul_classical(fq_zech_mat_t C, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses classical matrix multiplication. .. function:: void fq_zech_mat_mul_KS(fq_zech_mat_t C, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses Kronecker substitution to perform the multiplication over the integers. .. function:: void fq_zech_mat_submul(fq_zech_mat_t D, const fq_zech_mat_t C, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Sets `D = C + AB`. `C` and `D` may be aliased with each other but not with `A` or `B`. .. function:: void fq_zech_mat_mul_vec(fq_zech_struct * c, const fq_zech_mat_t A, const fq_zech_struct * b, slong blen, const fq_zech_ctx_t ctx) void fq_zech_mat_mul_vec_ptr(fq_zech_struct * const * c, const fq_zech_mat_t A, const fq_zech_struct * const * b, slong blen, const fq_zech_ctx_t ctx) Compute a matrix-vector product of ``A`` and ``(b, blen)`` and store the result in ``c``. The vector ``(b, blen)`` is either truncated or zero-extended to the number of columns of ``A``. The number entries written to ``c`` is always equal to the number of rows of ``A``. .. function:: void fq_zech_mat_vec_mul(fq_zech_struct * c, const fq_zech_struct * a, slong alen, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) void fq_zech_mat_vec_mul_ptr(fq_zech_struct * const * c, const fq_zech_struct * const * a, slong alen, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Compute a vector-matrix product of ``(a, alen)`` and ``B`` and and store the result in ``c``. The vector ``(a, alen)`` is either truncated or zero-extended to the number of rows of ``B``. The number entries written to ``c`` is always equal to the number of columns of ``B``. LU decomposition -------------------------------------------------------------------------------- .. function:: slong fq_zech_mat_lu(slong * P, fq_zech_mat_t A, int rank_check, const fq_zech_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. If `A` is a nonsingular square matrix, it will be overwritten with a unit diagonal lower triangular matrix `L` and an upper triangular matrix `U` (the diagonal of `L` will not be stored explicitly). If `A` is an arbitrary matrix of rank `r`, `U` will be in row echelon form having `r` nonzero rows, and `L` will be lower triangular but truncated to `r` columns, having implicit ones on the `r` first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and return 0 if `A` is detected to be rank-deficient. This function calls ``fq_zech_mat_lu_recursive``. .. function:: slong fq_zech_mat_lu_classical(slong * P, fq_zech_mat_t A, int rank_check, const fq_zech_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. The behavior of this function is identical to that of ``fq_zech_mat_lu``. Uses Gaussian elimination. .. function:: slong fq_zech_mat_lu_recursive(slong * P, fq_zech_mat_t A, int rank_check, const fq_zech_ctx_t ctx) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. The behavior of this function is identical to that of ``fq_zech_mat_lu``. Uses recursive block decomposition, switching to classical Gaussian elimination for sufficiently small blocks. Reduced row echelon form -------------------------------------------------------------------------------- .. function:: slong fq_zech_mat_rref(fq_zech_mat_t B, const fq_zech_mat_t A, const fq_zech_ctx_t ctx) Puts `B` in reduced row echelon form and returns the rank of `A`. The rref is computed by first obtaining an unreduced row echelon form via LU decomposition and then solving an additional triangular system. .. function:: slong fq_zech_mat_reduce_row(fq_zech_mat_t A, slong * P, slong * L, slong n, const fq_zech_ctx_t ctx) Reduce row n of the matrix `A`, assuming the prior rows are in Gauss form. However those rows may not be in order. The entry `i` of the array `P` is the row of `A` which has a pivot in the `i`-th column. If no such row exists, the entry of `P` will be `-1`. The function returns the column in which the `n`-th row has a pivot after reduction. This will always be chosen to be the first available column for a pivot from the left. This information is also updated in `P`. Entry `i` of the array `L` contains the number of possibly nonzero columns of `A` row `i`. This speeds up reduction in the case that `A` is chambered on the right. Otherwise the entries of `L` can all be set to the number of columns of `A`. We require the entries of `L` to be monotonic increasing. Triangular solving -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_solve_tril(fq_zech_mat_t X, const fq_zech_mat_t L, const fq_zech_mat_t B, int unit, const fq_zech_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void fq_zech_mat_solve_tril_classical(fq_zech_mat_t X, const fq_zech_mat_t L, const fq_zech_mat_t B, int unit, const fq_zech_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void fq_zech_mat_solve_tril_recursive(fq_zech_mat_t X, const fq_zech_mat_t L, const fq_zech_mat_t B, int unit, const fq_zech_ctx_t ctx) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. .. function:: void fq_zech_mat_solve_triu(fq_zech_mat_t X, const fq_zech_mat_t U, const fq_zech_mat_t B, int unit, const fq_zech_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void fq_zech_mat_solve_triu_classical(fq_zech_mat_t X, const fq_zech_mat_t U, const fq_zech_mat_t B, int unit, const fq_zech_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void fq_zech_mat_solve_triu_recursive(fq_zech_mat_t X, const fq_zech_mat_t U, const fq_zech_mat_t B, int unit, const fq_zech_ctx_t ctx) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. Solving -------------------------------------------------------------------------------- .. function:: int fq_zech_mat_solve(fq_zech_mat_t X, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Solves the matrix-matrix equation `AX = B`. Returns `1` if `A` has full rank; otherwise returns `0` and sets the elements of `X` to undefined values. The matrix `A` must be square. .. function:: int fq_zech_mat_can_solve(fq_zech_mat_t X, const fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_ctx_t ctx) Solves the matrix-matrix equation `AX = B` over `Fq`. Returns `1` if a solution exists; otherwise returns `0` and sets the elements of `X` to zero. If more than one solution exists, one of the valid solutions is given. There are no restrictions on the shape of `A` and it may be singular. Transforms -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_similarity(fq_zech_mat_t M, slong r, fq_zech_t d, const fq_zech_ctx_t ctx) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. The value `d` is required to be reduced modulo the modulus of the entries in the matrix. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_charpoly_danilevsky(fq_zech_poly_t p, const fq_zech_mat_t M, const fq_zech_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is assumed to be square. .. function:: void fq_zech_mat_charpoly(fq_zech_poly_t p, const fq_zech_mat_t M, const fq_zech_ctx_t ctx) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. Minimal polynomial -------------------------------------------------------------------------------- .. function:: void fq_zech_mat_minpoly(fq_zech_poly_t p, const fq_zech_mat_t M, const fq_zech_ctx_t ctx) Compute the minimal polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. flint-3.1.3/doc/source/fq_zech_poly.rst000066400000000000000000002062241461254215100201220ustar00rootroot00000000000000.. _fq-zech-poly: **fq_zech_poly.h** -- univariate polynomials over finite fields (Zech logarithm representation) =============================================================================================== We represent a polynomial in `\mathbf{F}_q[X]` as a ``struct`` which includes an array ``coeffs`` with the coefficients, as well as the length ``length`` and the number ``alloc`` of coefficients for which memory has been allocated. As a data structure, we call this polynomial *normalised* if the top coefficient is non-zero. Unless otherwise stated here, all functions that deal with polynomials assume that the `\mathbf{F}_q` context of said polynomials are compatible, i.e., it assumes that the fields are generated by the same polynomial. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_poly_struct .. type:: fq_zech_poly_t Memory management -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_init(fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Initialises ``poly`` for use, with context ctx, and setting its length to zero. A corresponding call to :func:`fq_zech_poly_clear` must be made after finishing with the ``fq_zech_poly_t`` to free the memory used by the polynomial. .. function:: void fq_zech_poly_init2(fq_zech_poly_t poly, slong alloc, const fq_zech_ctx_t ctx) Initialises ``poly`` with space for at least ``alloc`` coefficients and sets the length to zero. The allocated coefficients are all set to zero. A corresponding call to :func:`fq_zech_poly_clear` must be made after finishing with the ``fq_zech_poly_t`` to free the memory used by the polynomial. .. function:: void fq_zech_poly_realloc(fq_zech_poly_t poly, slong alloc, const fq_zech_ctx_t ctx) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` the polynomial is first truncated to length ``alloc``. .. function:: void fq_zech_poly_fit_length(fq_zech_poly_t poly, slong len, const fq_zech_ctx_t ctx) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where ``fit_length`` is called many times in small increments by at least doubling the number of allocated coefficients when length is larger than the number of coefficients currently allocated. .. function:: void _fq_zech_poly_set_length(fq_zech_poly_t poly, slong newlen, const fq_zech_ctx_t ctx) Sets the coefficients of ``poly`` beyond ``len`` to zero and sets the length of ``poly`` to ``len``. .. function:: void fq_zech_poly_clear(fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Clears the given polynomial, releasing any memory used. It must be reinitialised in order to be used again. .. function:: void _fq_zech_poly_normalise(fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Sets the length of ``poly`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void _fq_zech_poly_normalise2(const fq_zech_struct * poly, slong * length, const fq_zech_ctx_t ctx) Sets the length ``length`` of ``(poly,length)`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void fq_zech_poly_truncate(fq_zech_poly_t poly, slong newlen, const fq_zech_ctx_t ctx) Truncates the polynomial to length at most `n`. .. function:: void fq_zech_poly_set_trunc(fq_zech_poly_t poly1, fq_zech_poly_t poly2, slong newlen, const fq_zech_ctx_t ctx) Sets ``poly1`` to ``poly2`` truncated to length `n`. .. function:: void _fq_zech_poly_reverse(fq_zech_struct * output, const fq_zech_struct * input, slong len, slong m, const fq_zech_ctx_t ctx) Sets ``output`` to the reverse of ``input``, which is of length ``len``, but thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary. The length ``m`` must be non-negative, but there are no other restrictions. The polynomial ``output`` must have space for ``m`` coefficients. .. function:: void fq_zech_poly_reverse(fq_zech_poly_t output, const fq_zech_poly_t input, slong m, const fq_zech_ctx_t ctx) Sets ``output`` to the reverse of ``input``, thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary). The length ``m`` must be non-negative, but there are no other restrictions. The output polynomial will be set to length ``m`` and then normalised. Polynomial parameters -------------------------------------------------------------------------------- .. function:: slong fq_zech_poly_degree(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: slong fq_zech_poly_length(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Returns the length of the polynomial ``poly``. .. function:: fq_zech_struct * fq_zech_poly_lead(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Returns a pointer to the leading coefficient of ``poly``, or ``NULL`` if ``poly`` is the zero polynomial. Randomisation -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_randtest(fq_zech_poly_t f, flint_rand_t state, slong len, const fq_zech_ctx_t ctx) Sets `f` to a random polynomial of length at most ``len`` with entries in the field described by ``ctx``. .. function:: void fq_zech_poly_randtest_not_zero(fq_zech_poly_t f, flint_rand_t state, slong len, const fq_zech_ctx_t ctx) Same as ``fq_zech_poly_randtest`` but guarantees that the polynomial is not zero. .. function:: void fq_zech_poly_randtest_monic(fq_zech_poly_t f, flint_rand_t state, slong len, const fq_zech_ctx_t ctx) Sets `f` to a random monic polynomial of length ``len`` with entries in the field described by ``ctx``. .. function:: void fq_zech_poly_randtest_irreducible(fq_zech_poly_t f, flint_rand_t state, slong len, const fq_zech_ctx_t ctx) Sets `f` to a random monic, irreducible polynomial of length ``len`` with entries in the field described by ``ctx``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_set(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_ctx_t ctx) Sets ``(rop, len``) to ``(op, len)``. .. function:: void fq_zech_poly_set(fq_zech_poly_t poly1, const fq_zech_poly_t poly2, const fq_zech_ctx_t ctx) Sets the polynomial ``poly1`` to the polynomial ``poly2``. .. function:: void fq_zech_poly_set_fq_zech(fq_zech_poly_t poly, const fq_zech_t c, const fq_zech_ctx_t ctx) Sets the polynomial ``poly`` to ``c``. .. function:: void fq_zech_poly_set_fmpz_mod_poly(fq_zech_poly_t rop, const fmpz_mod_poly_t op, const fq_zech_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op`` .. function:: void fq_zech_poly_set_nmod_poly(fq_zech_poly_t rop, const nmod_poly_t op, const fq_zech_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op`` .. function:: void fq_zech_poly_swap(fq_zech_poly_t op1, fq_zech_poly_t op2, const fq_zech_ctx_t ctx) Swaps the two polynomials ``op1`` and ``op2``. .. function:: void _fq_zech_poly_zero(fq_zech_struct * rop, slong len, const fq_zech_ctx_t ctx) Sets ``(rop, len)`` to the zero polynomial. .. function:: void fq_zech_poly_zero(fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Sets ``poly`` to the zero polynomial. .. function:: void fq_zech_poly_one(fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Sets ``poly`` to the constant polynomial `1`. .. function:: void fq_zech_poly_gen(fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Sets ``poly`` to the polynomial `x`. .. function:: void fq_zech_poly_make_monic(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to ``op``, normed to have leading coefficient 1. .. function:: void _fq_zech_poly_make_monic(fq_zech_struct * rop, const fq_zech_struct * op, slong length, const fq_zech_ctx_t ctx) Sets ``rop`` to ``(op,length)``, normed to have leading coefficient 1. Assumes that ``rop`` has enough space for the polynomial, assumes that ``op`` is not zero (and thus has an invertible leading coefficient). Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_get_coeff(fq_zech_t x, const fq_zech_poly_t poly, slong n, const fq_zech_ctx_t ctx) Sets `x` to the coefficient of `X^n` in ``poly``. .. function:: void fq_zech_poly_set_coeff(fq_zech_poly_t poly, slong n, const fq_zech_t x, const fq_zech_ctx_t ctx) Sets the coefficient of `X^n` in ``poly`` to `x`. .. function:: void fq_zech_poly_set_coeff_fmpz(fq_zech_poly_t poly, slong n, const fmpz_t x, const fq_zech_ctx_t ctx) Sets the coefficient of `X^n` in the polynomial to `x`, assuming `n \geq 0`. Comparison -------------------------------------------------------------------------------- .. function:: int fq_zech_poly_equal(const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, const fq_zech_ctx_t ctx) Returns nonzero if the two polynomials ``poly1`` and ``poly2`` are equal, otherwise return zero. .. function:: int fq_zech_poly_equal_trunc(const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, slong n, const fq_zech_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length `n` and return nonzero if they are equal, otherwise return zero. .. function:: int fq_zech_poly_is_zero(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Returns whether the polynomial ``poly`` is the zero polynomial. .. function:: int fq_zech_poly_is_one(const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the constant polynomial `1`. .. function:: int fq_zech_poly_is_gen(const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Returns whether the polynomial ``poly`` is equal to the polynomial `x`. .. function:: int fq_zech_poly_is_unit(const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Returns whether the polynomial ``poly`` is a unit in the polynomial ring `\mathbf{F}_q[X]`, i.e. if it has degree `0` and is non-zero. .. function:: int fq_zech_poly_equal_fq_zech(const fq_zech_poly_t poly, const fq_zech_t c, const fq_zech_ctx_t ctx) Returns whether the polynomial ``poly`` is equal the (constant) `\mathbf{F}_q` element ``c`` Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_add(fq_zech_struct * res, const fq_zech_struct * poly1, slong len1, const fq_zech_struct * poly2, slong len2, const fq_zech_ctx_t ctx) Sets ``res`` to the sum of ``(poly1,len1)`` and ``(poly2,len2)``. .. function:: void fq_zech_poly_add(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, const fq_zech_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``poly2``. .. function:: void fq_zech_poly_add_si(fq_zech_poly_t res, const fq_zech_poly_t poly1, slong c, const fq_zech_ctx_t ctx) Sets ``res`` to the sum of ``poly1`` and ``c``. .. function:: void fq_zech_poly_add_series(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, slong n, const fq_zech_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the sum. .. function:: void _fq_zech_poly_sub(fq_zech_struct * res, const fq_zech_struct * poly1, slong len1, const fq_zech_struct * poly2, slong len2, const fq_zech_ctx_t ctx) Sets ``res`` to the difference of ``(poly1,len1)`` and ``(poly2,len2)``. .. function:: void fq_zech_poly_sub(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, const fq_zech_ctx_t ctx) Sets ``res`` to the difference of ``poly1`` and ``poly2``. .. function:: void fq_zech_poly_sub_series(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, slong n, const fq_zech_ctx_t ctx) Notionally truncate ``poly1`` and ``poly2`` to length ``n`` and set ``res`` to the difference. .. function:: void _fq_zech_poly_neg(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_ctx_t ctx) Sets ``rop`` to the additive inverse of ``(op,len)``. .. function:: void fq_zech_poly_neg(fq_zech_poly_t res, const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Sets ``res`` to the additive inverse of ``poly``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_scalar_mul_fq_zech(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_t x, const fq_zech_ctx_t ctx) Sets ``(rop,len)`` to the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void fq_zech_poly_scalar_mul_fq_zech(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_t x, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_zech_poly_scalar_addmul_fq_zech(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_t x, const fq_zech_ctx_t ctx) Adds to ``(rop,len)`` the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. In particular, assumes the same length for ``op`` and ``rop``. .. function:: void fq_zech_poly_scalar_addmul_fq_zech(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_t x, const fq_zech_ctx_t ctx) Adds to ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_zech_poly_scalar_submul_fq_zech(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_t x, const fq_zech_ctx_t ctx) Subtracts from ``(rop,len)`` the product of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. In particular, assumes the same length for ``op`` and ``rop``. .. function:: void fq_zech_poly_scalar_submul_fq_zech(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_t x, const fq_zech_ctx_t ctx) Subtracts from ``rop`` the product of ``op`` by the scalar ``x``, in the context defined by ``ctx``. .. function:: void _fq_zech_poly_scalar_div_fq_zech(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_t x, const fq_zech_ctx_t ctx) Sets ``(rop,len)`` to the quotient of ``(op,len)`` by the scalar ``x``, in the context defined by ``ctx``. An exception is raised if ``x`` is zero. .. function:: void fq_zech_poly_scalar_div_fq_zech(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_t x, const fq_zech_ctx_t ctx) Sets ``rop`` to the quotient of ``op`` by the scalar ``x``, in the context defined by ``ctx``. An exception is raised if ``x`` is zero. Multiplication -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_mul_classical(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, const fq_zech_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, assuming that ``len1`` is at least ``len2`` and neither is zero. Permits zero padding. Does not support aliasing of ``rop`` with either ``op1`` or ``op2``. .. function:: void fq_zech_poly_mul_classical(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using classical polynomial multiplication. .. function:: void _fq_zech_poly_mul_reorder(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, const fq_zech_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, assuming that ``len1`` and ``len2`` are non-zero. Permits zero padding. Supports aliasing. .. function:: void fq_zech_poly_mul_reorder(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reordering the two indeterminates `X` and `Y` when viewing the polynomials as elements of `\mathbf{F}_p[X,Y]`. Suppose `\mathbf{F}_q = \mathbf{F}_p[X]/ (f(X))` and recall that elements of `\mathbf{F}_q` are internally represented by elements of type ``fmpz_poly``. For small degree extensions but polynomials in `\mathbf{F}_q[Y]` of large degree `n`, we change the representation to .. math:: \begin{split} g(Y) & = \sum_{i=0}^{n} a_i(X) Y^i \\ & = \sum_{j=0}^{d} \sum_{i=0}^{n} \text{Coeff}(a_i(X), j) Y^i. \end{split} This allows us to use a poor algorithm (such as classical multiplication) in the `X`-direction and leverage the existing fast integer multiplication routines in the `Y`-direction where the polynomial degree `n` is large. .. function:: void _fq_zech_poly_mul_KS(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, const fq_zech_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``. Permits zero padding and places no assumptions on the lengths ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_zech_poly_mul_KS(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2`` using Kronecker substitution, that is, by encoding each coefficient in `\mathbf{F}_{q}` as an integer and reducing this problem to multiplying two polynomials over the integers. .. function:: void _fq_zech_poly_mul(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, const fq_zech_ctx_t ctx) Sets ``(rop, len1 + len2 - 1)`` to the product of ``(op1, len1)`` and ``(op2, len2)``, choosing an appropriate algorithm. Permits zero padding. Does not support aliasing. .. function:: void fq_zech_poly_mul(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, choosing an appropriate algorithm. .. function:: void _fq_zech_poly_mullow_classical(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, slong n, const fq_zech_ctx_t ctx) Sets ``(rop, n)`` to the first `n` coefficients of ``(op1, len1)`` multiplied by ``(op2, len2)``. Assumes ``0 < n <= len1 + len2 - 1``. Assumes neither ``len1`` nor ``len2`` is zero. .. function:: void fq_zech_poly_mullow_classical(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, slong n, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, computed using the classical or schoolbook method. .. function:: void _fq_zech_poly_mullow_KS(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, slong n, const fq_zech_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``. Assumes that ``len1`` and ``len2`` are positive, but does allow for the polynomials to be zero-padded. The polynomials may be zero, too. Assumes `n` is positive. Supports aliasing between ``rop``, ``op1`` and ``op2``. .. function:: void fq_zech_poly_mullow_KS(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, slong n, const fq_zech_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``. .. function:: void _fq_zech_poly_mullow(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, slong n, const fq_zech_ctx_t ctx) Sets ``(rop, n)`` to the lowest `n` coefficients of the product of ``(op1, len1)`` and ``(op2, len2)``. Assumes ``0 < n <= len1 + len2 - 1``. Allows for zero-padding in the inputs. Does not support aliasing between the inputs and the output. .. function:: void fq_zech_poly_mullow(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, slong n, const fq_zech_ctx_t ctx) Sets ``rop`` to the lowest `n` coefficients of the product of ``op1`` and ``op2``. .. function:: void _fq_zech_poly_mulhigh_classical(fq_zech_struct * res, const fq_zech_struct * poly1, slong len1, const fq_zech_struct * poly2, slong len2, slong start, const fq_zech_ctx_t ctx) Computes the product of ``(poly1, len1)`` and ``(poly2, len2)`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Assumes that ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. Algorithm is classical multiplication. .. function:: void fq_zech_poly_mulhigh_classical(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, slong start, const fq_zech_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Algorithm is classical multiplication. .. function:: void _fq_zech_poly_mulhigh(fq_zech_struct * res, const fq_zech_struct * poly1, slong len1, const fq_zech_struct * poly2, slong len2, slong start, fq_zech_ctx_t ctx) Computes the product of ``(poly1, len1)`` and ``(poly2, len2)`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Assumes that ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. .. function:: void fq_zech_poly_mulhigh(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, slong start, const fq_zech_ctx_t ctx) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. .. function:: void _fq_zech_poly_mulmod(fq_zech_struct * res, const fq_zech_struct * poly1, slong len1, const fq_zech_struct * poly2, slong len2, const fq_zech_struct * f, slong lenf, const fq_zech_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``len1 + len2 - lenf > 0``, which is equivalent to requiring that the result will actually be reduced. Otherwise, simply use ``_fq_zech_poly_mul`` instead. Aliasing of ``f`` and ``res`` is not permitted. .. function:: void fq_zech_poly_mulmod(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. .. function:: void _fq_zech_poly_mulmod_preinv(fq_zech_struct * res, const fq_zech_struct * poly1, slong len1, const fq_zech_struct * poly2, slong len2, const fq_zech_struct * f, slong lenf, const fq_zech_struct * finv, slong lenfinv, const fq_zech_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``finv`` is the inverse of the reverse of ``f`` mod ``x^lenf``. Aliasing of ``res`` with any of the inputs is not permitted. .. function:: void fq_zech_poly_mulmod_preinv(fq_zech_poly_t res, const fq_zech_poly_t poly1, const fq_zech_poly_t poly2, const fq_zech_poly_t f, const fq_zech_poly_t finv, const fq_zech_ctx_t ctx) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. ``finv`` is the inverse of the reverse of ``f``. Squaring -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_sqr_classical(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_ctx_t ctx) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``, assuming that ``(op,len)`` is not zero and using classical polynomial multiplication. Permits zero padding. Does not support aliasing of ``rop`` with either ``op1`` or ``op2``. .. function:: void fq_zech_poly_sqr_classical(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the square of ``op`` using classical polynomial multiplication. .. function:: void _fq_zech_poly_sqr_KS(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_ctx_t ctx) Sets ``(rop, 2*len - 1)`` to the square of ``(op, len)``. Permits zero padding and places no assumptions on the lengths ``len1`` and ``len2``. Supports aliasing. .. function:: void fq_zech_poly_sqr_KS(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the square ``op`` using Kronecker substitution, that is, by encoding each coefficient in `\mathbf{F}_{q}` as an integer and reducing this problem to multiplying two polynomials over the integers. .. function:: void _fq_zech_poly_sqr(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_ctx_t ctx) Sets ``(rop, 2 * len - 1)`` to the square of ``(op, len)``, choosing an appropriate algorithm. Permits zero padding. Does not support aliasing. .. function:: void fq_zech_poly_sqr(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the square of ``op``, choosing an appropriate algorithm. Powering -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_pow(fq_zech_struct * rop, const fq_zech_struct * op, slong len, ulong e, const fq_zech_ctx_t ctx) Sets ``rop = op^e``, assuming that ``e, len > 0`` and that ``res`` has space for ``e*(len - 1) + 1`` coefficients. Does not support aliasing. .. function:: void fq_zech_poly_pow(fq_zech_poly_t rop, const fq_zech_poly_t op, ulong e, const fq_zech_ctx_t ctx) Computes ``rop = op^e``. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void _fq_zech_poly_powmod_ui_binexp(fq_zech_struct * res, const fq_zech_struct * poly, ulong e, const fq_zech_struct * f, slong lenf, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_zech_poly_powmod_ui_binexp(fq_zech_poly_t res, const fq_zech_poly_t poly, ulong e, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fq_zech_poly_powmod_ui_binexp_preinv(fq_zech_struct * res, const fq_zech_struct * poly, ulong e, const fq_zech_struct * f, slong lenf, const fq_zech_struct * finv, slong lenfinv, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_zech_poly_powmod_ui_binexp_preinv(fq_zech_poly_t res, const fq_zech_poly_t poly, ulong e, const fq_zech_poly_t f, const fq_zech_poly_t finv, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_zech_poly_powmod_fmpz_binexp(fq_zech_struct * res, const fq_zech_struct * poly, const fmpz_t e, const fq_zech_struct * f, slong lenf, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_zech_poly_powmod_fmpz_binexp(fq_zech_poly_t res, const fq_zech_poly_t poly, const fmpz_t e, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _fq_zech_poly_powmod_fmpz_binexp_preinv(fq_zech_struct * res, const fq_zech_struct * poly, const fmpz_t e, const fq_zech_struct * f, slong lenf, const fq_zech_struct * finv, slong lenfinv, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_zech_poly_powmod_fmpz_binexp_preinv(fq_zech_poly_t res, const fq_zech_poly_t poly, const fmpz_t e, const fq_zech_poly_t f, const fq_zech_poly_t finv, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_zech_poly_powmod_fmpz_sliding_preinv(fq_zech_struct * res, const fq_zech_struct * poly, const fmpz_t e, ulong k, const fq_zech_struct * f, slong lenf, const fq_zech_struct * finv, slong lenfinv, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using sliding-window exponentiation with window size ``k``. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. If ``k`` is set to zero, then an "optimum" size will be selected automatically base on ``e``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_zech_poly_powmod_fmpz_sliding_preinv(fq_zech_poly_t res, const fq_zech_poly_t poly, const fmpz_t e, ulong k, const fq_zech_poly_t f, const fq_zech_poly_t finv, const fq_zech_ctx_t ctx) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using sliding-window exponentiation with window size ``k``. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. If ``k`` is set to zero, then an "optimum" size will be selected automatically base on ``e``. .. function:: void _fq_zech_poly_powmod_x_fmpz_preinv(fq_zech_struct * res, const fmpz_t e, const fq_zech_struct * f, slong lenf, const fq_zech_struct * finv, slong lenfinv, const fq_zech_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 2``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void fq_zech_poly_powmod_x_fmpz_preinv(fq_zech_poly_t res, const fmpz_t e, const fq_zech_poly_t f, const fq_zech_poly_t finv, const fq_zech_ctx_t ctx) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _fq_zech_poly_pow_trunc_binexp(fq_zech_struct * res, const fq_zech_struct * poly, ulong e, slong trunc, const fq_zech_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. Uses the binary exponentiation method. .. function:: void fq_zech_poly_pow_trunc_binexp(fq_zech_poly_t res, const fq_zech_poly_t poly, ulong e, slong trunc, const fq_zech_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Uses the binary exponentiation method. .. function:: void _fq_zech_poly_pow_trunc(fq_zech_struct * res, const fq_zech_struct * poly, ulong e, slong trunc, const fq_zech_ctx_t mod) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. .. function:: void fq_zech_poly_pow_trunc(fq_zech_poly_t res, const fq_zech_poly_t poly, ulong e, slong trunc, const fq_zech_ctx_t ctx) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Shifting -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_shift_left(fq_zech_struct * rop, const fq_zech_struct * op, slong len, slong n, const fq_zech_ctx_t ctx) Sets ``(rop, len + n)`` to ``(op, len)`` shifted left by `n` coefficients. Inserts zero coefficients at the lower end. Assumes that ``len`` and `n` are positive, and that ``rop`` fits ``len + n`` elements. Supports aliasing between ``rop`` and ``op``. .. function:: void fq_zech_poly_shift_left(fq_zech_poly_t rop, const fq_zech_poly_t op, slong n, const fq_zech_ctx_t ctx) Sets ``rop`` to ``op`` shifted left by `n` coeffs. Zero coefficients are inserted. .. function:: void _fq_zech_poly_shift_right(fq_zech_struct * rop, const fq_zech_struct * op, slong len, slong n, const fq_zech_ctx_t ctx) Sets ``(rop, len - n)`` to ``(op, len)`` shifted right by `n` coefficients. Assumes that ``len`` and `n` are positive, that ``len > n``, and that ``rop`` fits ``len - n`` elements. Supports aliasing between ``rop`` and ``op``, although in this case the top coefficients of ``op`` are not set to zero. .. function:: void fq_zech_poly_shift_right(fq_zech_poly_t rop, const fq_zech_poly_t op, slong n, const fq_zech_ctx_t ctx) Sets ``rop`` to ``op`` shifted right by `n` coefficients. If `n` is equal to or greater than the current length of ``op``, ``rop`` is set to the zero polynomial. Norms -------------------------------------------------------------------------------- .. function:: slong _fq_zech_poly_hamming_weight(const fq_zech_struct * op, slong len, const fq_zech_ctx_t ctx) Returns the number of non-zero entries in ``(op, len)``. .. function:: slong fq_zech_poly_hamming_weight(const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Returns the number of non-zero entries in the polynomial ``op``. Euclidean division -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_divrem(fq_zech_struct * Q, fq_zech_struct * R, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_t invB, const fq_zech_ctx_t ctx) Computes ``(Q, lenA - lenB + 1)``, ``(R, lenA)`` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible and that ``invB`` is its inverse. Assumes that `\operatorname{len}(A), \operatorname{len}(B) > 0`. Allows zero-padding in ``(A, lenA)``. `R` and `A` may be aliased, but apart from this no aliasing of input and output operands is allowed. .. function:: void fq_zech_poly_divrem(fq_zech_poly_t Q, fq_zech_poly_t R, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible. This can be taken for granted the context is for a finite field, that is, when `p` is prime and `f(X)` is irreducible. .. function:: void fq_zech_poly_divrem_f(fq_zech_t f, fq_zech_poly_t Q, fq_zech_poly_t R, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Either finds a non-trivial factor `f` of the modulus of ``ctx``, or computes `Q`, `R` such that `A = B Q + R` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. If the leading coefficient of `B` is invertible, the division with remainder operation is carried out, `Q` and `R` are computed correctly, and `f` is set to `1`. Otherwise, `f` is set to a non-trivial factor of the modulus and `Q` and `R` are not touched. Assumes that `B` is non-zero. .. function:: void _fq_zech_poly_rem(fq_zech_struct * R, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_t invB, const fq_zech_ctx_t ctx) Sets ``R`` to the remainder of the division of ``(A,lenA)`` by ``(B,lenB)``. Assumes that the leading coefficient of ``(B,lenB)`` is invertible and that ``invB`` is its inverse. .. function:: void fq_zech_poly_rem(fq_zech_poly_t R, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Sets ``R`` to the remainder of the division of ``A`` by ``B`` in the context described by ``ctx``. .. function:: void _fq_zech_poly_div(fq_zech_struct * Q, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_t invB, const fq_zech_ctx_t ctx) Notationally, computes `Q`, `R` such that `A = B Q + R` with `0 \leq \operatorname{len}(R) < \operatorname{len}(B)` but only sets ``(Q, lenA - lenB + 1)``. Allows zero-padding in `A` but not in `B`. Assumes that the leading coefficient of `B` is a unit. .. function:: void fq_zech_poly_div(fq_zech_poly_t Q, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Notionally finds polynomials `Q` and `R` such that `A = B Q + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only ``Q``. If `\operatorname{len}(B) = 0` an exception is raised. .. function:: void _fq_zech_poly_div_newton_n_preinv(fq_zech_struct * Q, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_struct * Binv, slong lenBinv, const fq_zech_ctx_t ctx) Notionally computes polynomials `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where ``A`` is of length ``lenA`` and ``B`` is of length ``lenB``, but return only `Q`. We require that `Q` have space for ``lenA - lenB + 1`` coefficients and assume that the leading coefficient of `B` is a unit. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void fq_zech_poly_div_newton_n_preinv(fq_zech_poly_t Q, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_poly_t Binv, const fq_zech_ctx_t ctx) Notionally computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only `Q`. We assume that the leading coefficient of `B` is a unit and that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void _fq_zech_poly_divrem_newton_n_preinv(fq_zech_struct * Q, fq_zech_struct * R, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_struct * Binv, slong lenBinv, const fq_zech_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where `A` is of length ``lenA`` and `B` is of length ``lenB``. We require that `Q` have space for ``lenA - lenB + 1`` coefficients. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to call :func:`div_newton_preinv` and then multiply out and compute the remainder. .. function:: void fq_zech_poly_divrem_newton_n_preinv(fq_zech_poly_t Q, fq_zech_poly_t R, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_poly_t Binv, const fq_zech_ctx_t ctx) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. We assume `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to call :func:`div_newton` and then multiply out and compute the remainder. .. function:: void _fq_zech_poly_inv_series_newton(fq_zech_struct * Qinv, const fq_zech_struct * Q, slong n, const fq_zech_t cinv, const fq_zech_ctx_t ctx) Given ``Q`` of length ``n`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void fq_zech_poly_inv_series_newton(fq_zech_poly_t Qinv, const fq_zech_poly_t Q, slong n, const fq_zech_ctx_t ctx) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void _fq_zech_poly_inv_series(fq_zech_struct * Qinv, const fq_zech_struct * Q, slong n, const fq_zech_t cinv, const fq_zech_ctx_t ctx) Given ``Q`` of length ``n`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. .. function:: void fq_zech_poly_inv_series(fq_zech_poly_t Qinv, const fq_zech_poly_t Q, slong n, const fq_zech_ctx_t ctx) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. .. function:: void _fq_zech_poly_div_series(fq_zech_struct * Q, const fq_zech_struct * A, slong Alen, const fq_zech_struct * B, slong Blen, slong n, const fq_zech_ctx_t ctx) Set ``(Q, n)`` to the quotient of the series ``(A, Alen``) and ``(B, Blen)`` assuming ``Alen, Blen <= n``. We assume the bottom coefficient of ``B`` is invertible. .. function:: void fq_zech_poly_div_series(fq_zech_poly_t Q, const fq_zech_poly_t A, const fq_zech_poly_t B, slong n, const fq_zech_ctx_t ctx) Set `Q` to the quotient of the series `A` by `B`, thinking of the series as though they were of length `n`. We assume that the bottom coefficient of `B` is invertible. Greatest common divisor -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_gcd(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the greatest common divisor of ``op1`` and ``op2``, using the either the Euclidean or HGCD algorithm. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. .. function:: slong _fq_zech_poly_gcd(fq_zech_struct * G, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_ctx_t ctx) Computes the GCD of `A` of length ``lenA`` and `B` of length ``lenB``, where ``lenA >= lenB > 0`` and sets `G` to it. The length of the GCD `G` is returned by the function. No attempt is made to make the GCD monic. It is required that `G` have space for ``lenB`` coefficients. .. function:: slong _fq_zech_poly_gcd_euclidean_f(fq_zech_t f, fq_zech_struct * G, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `(A,\operatorname{len}(A))` and `(B, \operatorname{len}(B))` and returns its length, or sets `f` to a non-trivial factor of the modulus of ``ctx`` and leaves the contents of the vector `(G, lenB)` undefined. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that the vector `G` has space for sufficiently many coefficients. .. function:: void fq_zech_poly_gcd_euclidean_f(fq_zech_t f, fq_zech_poly_t G, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Either sets `f = 1` and `G` to the greatest common divisor of `A` and `B` or sets `f` to a factor of the modulus of ``ctx``. .. function:: slong _fq_zech_poly_xgcd(fq_zech_struct * G, fq_zech_struct * S, fq_zech_struct * T, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_ctx_t ctx) Computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void fq_zech_poly_xgcd(fq_zech_poly_t G, fq_zech_poly_t S, fq_zech_poly_t T, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. .. function:: slong _fq_zech_poly_xgcd_euclidean_f(fq_zech_t f, fq_zech_struct * G, fq_zech_struct * S, fq_zech_struct * T, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_ctx_t ctx) Either sets `f = 1` and computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`; otherwise, sets `f` to a non-trivial factor of the modulus of ``ctx`` and leaves `G`, `S`, and `T` undefined. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void fq_zech_poly_xgcd_euclidean_f(fq_zech_t f, fq_zech_poly_t G, fq_zech_poly_t S, fq_zech_poly_t T, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Either sets `f = 1` and computes the GCD of `A` and `B` or sets `f` to a non-trivial factor of the modulus of ``ctx``. If the GCD is computed, polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``; otherwise, they are undefined. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Divisibility testing -------------------------------------------------------------------------------- .. function:: int _fq_zech_poly_divides(fq_zech_struct * Q, const fq_zech_struct * A, slong lenA, const fq_zech_struct * B, slong lenB, const fq_zech_t invB, const fq_zech_ctx_t ctx) Returns `1` if ``(B, lenB)`` divides ``(A, lenA)`` exactly and sets `Q` to the quotient, otherwise returns `0`. It is assumed that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0` and that `Q` has space for `\operatorname{len}(A) - \operatorname{len}(B) + 1` coefficients. Aliasing of `Q` with either of the inputs is not permitted. This function is currently unoptimised and provided for convenience only. .. function:: int fq_zech_poly_divides(fq_zech_poly_t Q, const fq_zech_poly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) Returns `1` if `B` divides `A` exactly and sets `Q` to the quotient, otherwise returns `0`. This function is currently unoptimised and provided for convenience only. Derivative -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_derivative(fq_zech_struct * rop, const fq_zech_struct * op, slong len, const fq_zech_ctx_t ctx) Sets ``(rop, len - 1)`` to the derivative of ``(op, len)``. Also handles the cases where ``len`` is `0` or `1` correctly. Supports aliasing of ``rop`` and ``op``. .. function:: void fq_zech_poly_derivative(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_ctx_t ctx) Sets ``rop`` to the derivative of ``op``. Square root -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_invsqrt_series(fq_zech_struct * g, const fq_zech_struct * h, slong n, fq_zech_ctx_t mod) Set the first `n` terms of `g` to the series expansion of `1/\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1 and that `h` is zero-padded as necessary to length `n`. Aliasing is not permitted. .. function:: void fq_zech_poly_invsqrt_series(fq_zech_poly_t g, const fq_zech_poly_t h, slong n, fq_zech_ctx_t ctx) Set `g` to the series expansion of `1/\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: void _fq_zech_poly_sqrt_series(fq_zech_struct * g, const fq_zech_struct * h, slong n, fq_zech_ctx_t ctx) Set the first `n` terms of `g` to the series expansion of `\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1 and that `h` is zero-padded as necessary to length `n`. Aliasing is not permitted. .. function:: void fq_zech_poly_sqrt_series(fq_zech_poly_t g, const fq_zech_poly_t h, slong n, fq_zech_ctx_t ctx) Set `g` to the series expansion of `\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: int _fq_zech_poly_sqrt(fq_zech_struct * s, const fq_zech_struct * p, slong n, fq_zech_ctx_t mod) If ``(p, n)`` is a perfect square, sets ``(s, n / 2 + 1)`` to a square root of `p` and returns 1. Otherwise returns 0. .. function:: int fq_zech_poly_sqrt(fq_zech_poly_t s, const fq_zech_poly_t p, fq_zech_ctx_t mod) If `p` is a perfect square, sets `s` to a square root of `p` and returns 1. Otherwise returns 0. Evaluation -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_evaluate_fq_zech(fq_zech_t rop, const fq_zech_struct * op, slong len, const fq_zech_t a, const fq_zech_ctx_t ctx) Sets ``rop`` to ``(op, len)`` evaluated at `a`. Supports zero padding. There are no restrictions on ``len``, that is, ``len`` is allowed to be zero, too. .. function:: void fq_zech_poly_evaluate_fq_zech(fq_zech_t rop, const fq_zech_poly_t f, const fq_zech_t a, const fq_zech_ctx_t ctx) Sets ``rop`` to the value of `f(a)`. As the coefficient ring `\mathbf{F}_q` is finite, Horner's method is sufficient. Composition -------------------------------------------------------------------------------- .. function:: void _fq_zech_poly_compose(fq_zech_struct * rop, const fq_zech_struct * op1, slong len1, const fq_zech_struct * op2, slong len2, const fq_zech_ctx_t ctx) Sets ``rop`` to the composition of ``(op1, len1)`` and ``(op2, len2)``. Assumes that ``rop`` has space for ``(len1-1)*(len2-1) + 1`` coefficients. Assumes that ``op1`` and ``op2`` are non-zero polynomials. Does not support aliasing between any of the inputs and the output. .. function:: void fq_zech_poly_compose(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2, const fq_zech_ctx_t ctx) Sets ``rop`` to the composition of ``op1`` and ``op2``. To be precise about the order of composition, denoting ``rop``, ``op1``, and ``op2`` by `f`, `g`, and `h`, respectively, sets `f(t) = g(h(t))`. .. function:: void _fq_zech_poly_compose_mod_horner(fq_zech_struct * res, const fq_zech_struct * f, slong lenf, const fq_zech_struct * g, const fq_zech_struct * h, slong lenh, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void fq_zech_poly_compose_mod_horner(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_poly_t g, const fq_zech_poly_t h, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. The algorithm used is Horner's rule. .. function:: void _fq_zech_poly_compose_mod_horner_preinv(fq_zech_struct * res, const fq_zech_struct * f, slong lenf, const fq_zech_struct * g, const fq_zech_struct * h, slong lenh, const fq_zech_struct * hinv, slong lenhiv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void fq_zech_poly_compose_mod_horner_preinv(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_poly_t g, const fq_zech_poly_t h, const fq_zech_poly_t hinv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is Horner's rule. .. function:: void _fq_zech_poly_compose_mod_brent_kung(fq_zech_struct * res, const fq_zech_struct * f, slong lenf, const fq_zech_struct * g, const fq_zech_struct * h, slong lenh, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_zech_poly_compose_mod_brent_kung(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_poly_t g, const fq_zech_poly_t h, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fq_zech_poly_compose_mod_brent_kung_preinv(fq_zech_struct * res, const fq_zech_struct * f, slong lenf, const fq_zech_struct * g, const fq_zech_struct * h, slong lenh, const fq_zech_struct * hinv, slong lenhiv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_zech_poly_compose_mod_brent_kung_preinv(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_poly_t g, const fq_zech_poly_t h, const fq_zech_poly_t hinv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _fq_zech_poly_compose_mod(fq_zech_struct * res, const fq_zech_struct * f, slong lenf, const fq_zech_struct * g, const fq_zech_struct * h, slong lenh, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. .. function:: void fq_zech_poly_compose_mod(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_poly_t g, const fq_zech_poly_t h, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. .. function:: void _fq_zech_poly_compose_mod_preinv(fq_zech_struct * res, const fq_zech_struct * f, slong lenf, const fq_zech_struct * g, const fq_zech_struct * h, slong lenh, const fq_zech_struct * hinv, slong lenhiv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. .. function:: void fq_zech_poly_compose_mod_preinv(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_poly_t g, const fq_zech_poly_t h, const fq_zech_poly_t hinv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. .. function:: void _fq_zech_poly_reduce_matrix_mod_poly (fq_zech_mat_t A, const fq_zech_mat_t B, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Sets the ith row of ``A`` to the reduction of the ith row of `B` modulo `f` for `i=1,\ldots,\sqrt{\deg(f)}`. We require `B` to be at least a `\sqrt{\deg(f)}\times \deg(f)` matrix and `f` to be nonzero. .. function:: void _fq_zech_poly_precompute_matrix (fq_zech_mat_t A, const fq_zech_struct * f, const fq_zech_struct * g, slong leng, const fq_zech_struct * ginv, slong lenginv, const fq_zech_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g`` and `g` to be nonzero. .. function:: void fq_zech_poly_precompute_matrix (fq_zech_mat_t A, const fq_zech_poly_t f, const fq_zech_poly_t g, const fq_zech_poly_t ginv, const fq_zech_ctx_t ctx) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g``. .. function:: void _fq_zech_poly_compose_mod_brent_kung_precomp_preinv(fq_zech_struct * res, const fq_zech_struct * f, slong lenf, const fq_zech_mat_t A, const fq_zech_struct * h, slong lenh, const fq_zech_struct * hinv, slong lenhinv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void fq_zech_poly_compose_mod_brent_kung_precomp_preinv(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_mat_t A, const fq_zech_poly_t h, const fq_zech_poly_t hinv, const fq_zech_ctx_t ctx) Sets ``res`` to the composition `f(g)` modulo `h`. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. This version of Brent-Kung modular composition is particularly useful if one has to perform several modular composition of the form `f(g)` modulo `h` for fixed `g` and `h`. Output -------------------------------------------------------------------------------- .. function:: int _fq_zech_poly_fprint_pretty(FILE * file, const fq_zech_struct * poly, slong len, const char * x, const fq_zech_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_zech_poly_fprint_pretty(FILE * file, const fq_zech_poly_t poly, const char * x, const fq_zech_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_zech_poly_print_pretty(const fq_zech_struct * poly, slong len, const char * x, const fq_zech_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_zech_poly_print_pretty(const fq_zech_poly_t poly, const char * x, const fq_zech_ctx_t ctx) Prints the pretty representation of ``poly`` to ``stdout``, using the string ``x`` to represent the indeterminate. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_zech_poly_fprint(FILE * file, const fq_zech_struct * poly, slong len, const fq_zech_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_zech_poly_fprint(FILE * file, const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Prints the pretty representation of ``poly`` to the stream ``file``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_zech_poly_print(const fq_zech_struct * poly, slong len, const fq_zech_ctx_t ctx) Prints the pretty representation of ``(poly, len)`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int fq_zech_poly_print(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Prints the representation of ``poly`` to ``stdout``. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: char * _fq_zech_poly_get_str(const fq_zech_struct * poly, slong len, const fq_zech_ctx_t ctx) Returns the plain FLINT string representation of the polynomial ``(poly, len)``. .. function:: char * fq_zech_poly_get_str(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Returns the plain FLINT string representation of the polynomial ``poly``. .. function:: char * _fq_zech_poly_get_str_pretty(const fq_zech_struct * poly, slong len, const char * x, const fq_zech_ctx_t ctx) Returns a pretty representation of the polynomial ``(poly, len)`` using the null-terminated string ``x`` as the variable name. .. function:: char * fq_zech_poly_get_str_pretty(const fq_zech_poly_t poly, const char * x, const fq_zech_ctx_t ctx) Returns a pretty representation of the polynomial ``poly`` using the null-terminated string ``x`` as the variable name Inflation and deflation -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_inflate(fq_zech_poly_t result, const fq_zech_poly_t input, ulong inflation, const fq_zech_ctx_t ctx) Sets ``result`` to the inflated polynomial `p(x^n)` where `p` is given by ``input`` and `n` is given by ``inflation``. .. function:: void fq_zech_poly_deflate(fq_zech_poly_t result, const fq_zech_poly_t input, ulong deflation, const fq_zech_ctx_t ctx) Sets ``result`` to the deflated polynomial `p(x^{1/n})` where `p` is given by ``input`` and `n` is given by ``deflation``. Requires `n > 0`. .. function:: ulong fq_zech_poly_deflation(const fq_zech_poly_t input, const fq_zech_ctx_t ctx) Returns the largest integer by which ``input`` can be deflated. As special cases, returns 0 if ``input`` is the zero polynomial and 1 of ``input`` is a constant polynomial. flint-3.1.3/doc/source/fq_zech_poly_factor.rst000066400000000000000000000244361461254215100214630ustar00rootroot00000000000000.. _fq-zech-poly-factor: **fq_zech_poly_factor.h** -- factorisation of univariate polynomials over finite fields (Zech logarithm representation) ======================================================================================================================= Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_poly_factor_struct .. type:: fq_zech_poly_factor_t Memory Management -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_factor_init(fq_zech_poly_factor_t fac, const fq_zech_ctx_t ctx) Initialises ``fac`` for use. An ``fq_zech_poly_factor_t`` represents a polynomial in factorised form as a product of polynomials with associated exponents. .. function:: void fq_zech_poly_factor_clear(fq_zech_poly_factor_t fac, const fq_zech_ctx_t ctx) Frees all memory associated with ``fac``. .. function:: void fq_zech_poly_factor_realloc(fq_zech_poly_factor_t fac, slong alloc, const fq_zech_ctx_t ctx) Reallocates the factor structure to provide space for precisely ``alloc`` factors. .. function:: void fq_zech_poly_factor_fit_length(fq_zech_poly_factor_t fac, slong len, const fq_zech_ctx_t ctx) Ensures that the factor structure has space for at least ``len`` factors. This function takes care of the case of repeated calls by always at least doubling the number of factors the structure can hold. Basic Operations -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_factor_set(fq_zech_poly_factor_t res, const fq_zech_poly_factor_t fac, const fq_zech_ctx_t ctx) Sets ``res`` to the same factorisation as ``fac``. .. function:: void fq_zech_poly_factor_print_pretty(const fq_zech_poly_factor_t fac, const char * var, const fq_zech_ctx_t ctx) Pretty-prints the entries of ``fac`` to standard output. .. function:: void fq_zech_poly_factor_print(const fq_zech_poly_factor_t fac, const fq_zech_ctx_t ctx) Prints the entries of ``fac`` to standard output. .. function:: void fq_zech_poly_factor_insert(fq_zech_poly_factor_t fac, const fq_zech_poly_t poly, slong exp, const fq_zech_ctx_t ctx) Inserts the factor ``poly`` with multiplicity ``exp`` into the factorisation ``fac``. If ``fac`` already contains ``poly``, then ``exp`` simply gets added to the exponent of the existing entry. .. function:: void fq_zech_poly_factor_concat(fq_zech_poly_factor_t res, const fq_zech_poly_factor_t fac, const fq_zech_ctx_t ctx) Concatenates two factorisations. This is equivalent to calling ``fq_zech_poly_factor_insert()`` repeatedly with the individual factors of ``fac``. Does not support aliasing between ``res`` and ``fac``. .. function:: void fq_zech_poly_factor_pow(fq_zech_poly_factor_t fac, slong exp, const fq_zech_ctx_t ctx) Raises ``fac`` to the power ``exp``. .. function:: ulong fq_zech_poly_remove(fq_zech_poly_t f, const fq_zech_poly_t p, const fq_zech_ctx_t ctx) Removes the highest possible power of ``p`` from ``f`` and returns the exponent. Irreducibility Testing -------------------------------------------------------------------------------- .. function:: int fq_zech_poly_is_irreducible(const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. .. function:: int fq_zech_poly_is_irreducible_ddf(const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses fast distinct-degree factorisation. .. function:: int fq_zech_poly_is_irreducible_ben_or(const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses Ben-Or's irreducibility test. .. function:: int _fq_zech_poly_is_squarefree(const fq_zech_struct * f, slong len, const fq_zech_ctx_t ctx) Returns 1 if ``(f, len)`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. There are no restrictions on the length. .. function:: int fq_zech_poly_is_squarefree(const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Returns 1 if ``f`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. Factorisation -------------------------------------------------------------------------------- .. function:: int fq_zech_poly_factor_equal_deg_prob(fq_zech_poly_t factor, flint_rand_t state, const fq_zech_poly_t pol, slong d, const fq_zech_ctx_t ctx) Probabilistic equal degree factorisation of ``pol`` into irreducible factors of degree ``d``. If it passes, a factor is placed in factor and 1 is returned, otherwise 0 is returned and the value of factor is undetermined. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fq_zech_poly_factor_equal_deg(fq_zech_poly_factor_t factors, const fq_zech_poly_t pol, slong d, const fq_zech_ctx_t ctx) Assuming ``pol`` is a product of irreducible factors all of degree ``d``, finds all those factors and places them in factors. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void fq_zech_poly_factor_split_single(fq_zech_poly_t linfactor, const fq_zech_poly_t input, const fq_zech_ctx_t ctx) Assuming ``input`` is a product of factors all of degree 1, finds a single linear factor of ``input`` and places it in ``linfactor``. Requires that ``input`` be monic and non-constant. .. function:: void fq_zech_poly_factor_distinct_deg(fq_zech_poly_factor_t res, const fq_zech_poly_t poly, slong * const * degs, const fq_zech_ctx_t ctx) Factorises a monic non-constant squarefree polynomial ``poly`` of degree `n` into factors `f[d]` such that for `1 \leq d \leq n` `f[d]` is the product of the monic irreducible factors of ``poly`` of degree `d`. Factors are stored in ``res``, associated powers of irreducible polynomials are stored in ``degs`` in the same order as factors. Requires that ``degs`` have enough space for irreducible polynomials' powers (maximum space required is `n * sizeof(slong)`). .. function:: void fq_zech_poly_factor_squarefree(fq_zech_poly_factor_t res, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Sets ``res`` to a squarefree factorization of ``f``. .. function:: void fq_zech_poly_factor(fq_zech_poly_factor_t res, fq_zech_t lead, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors choosing the best algorithm for given modulo and degree. The output ``lead`` is set to the leading coefficient of `f` upon return. Choice of algorithm is based on heuristic measurements. .. function:: void fq_zech_poly_factor_cantor_zassenhaus(fq_zech_poly_factor_t res, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Cantor-Zassenhaus algorithm. .. function:: void fq_zech_poly_factor_kaltofen_shoup(fq_zech_poly_factor_t res, const fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the fast version of Cantor-Zassenhaus algorithm proposed by Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby step/giant step” strategy for the distinct-degree factorization step. .. function:: void fq_zech_poly_factor_berlekamp(fq_zech_poly_factor_t factors, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Berlekamp algorithm. .. function:: void fq_zech_poly_factor_with_berlekamp(fq_zech_poly_factor_t res, fq_zech_t leading_coeff, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Berlekamp on all the individual square-free factors. .. function:: void fq_zech_poly_factor_with_cantor_zassenhaus(fq_zech_poly_factor_t res, fq_zech_t leading_coeff, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Cantor-Zassenhaus on all the individual square-free factors. .. function:: void fq_zech_poly_factor_with_kaltofen_shoup(fq_zech_poly_factor_t res, fq_zech_t leading_coeff, const fq_zech_poly_t f, const fq_zech_ctx_t ctx) Factorises a general polynomial ``f`` into monic irreducible factors and sets ``leading_coeff`` to the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Kaltofen-Shoup on all the individual square-free factors. .. function:: void fq_zech_poly_iterated_frobenius_preinv(fq_zech_poly_t * rop, slong n, const fq_zech_poly_t v, const fq_zech_poly_t vinv, const fq_zech_ctx_t ctx) Sets ``rop[i]`` to be `x^{q^i} \bmod v` for `0 \le i < n`. It is required that ``vinv`` is the inverse of the reverse of ``v`` mod ``x^lenv``. Root Finding -------------------------------------------------------------------------------- .. function:: void fq_zech_poly_roots(fq_zech_poly_factor_t r, const fq_zech_poly_t f, int with_multiplicity, const fq_zech_ctx_t ctx) Fill `r` with factors of the form `x - r_i` where the `r_i` are the distinct roots of a nonzero `f` in `F_q`. If `with\_multiplicity` is zero, the exponent `e_i` of the factor `x - r_i` is `1`. Otherwise, it is the largest `e_i` such that `(x-r_i)^e_i` divides `f`. This function throws if `f` is zero, but is otherwise always successful. flint-3.1.3/doc/source/fq_zech_vec.rst000066400000000000000000000106471461254215100177160ustar00rootroot00000000000000.. _fq-zech-vec: **fq_zech_vec.h** -- vectors over finite fields (Zech logarithm representation) =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: fq_zech_struct * _fq_zech_vec_init(slong len, const fq_zech_ctx_t ctx) Returns an initialised vector of ``fq_zech``'s of given length. .. function:: void _fq_zech_vec_clear(fq_zech_struct * vec, slong len, const fq_zech_ctx_t ctx) Clears the entries of ``(vec, len)`` and frees the space allocated for ``vec``. Randomisation -------------------------------------------------------------------------------- .. function:: void _fq_zech_vec_randtest(fq_zech_struct * f, flint_rand_t state, slong len, const fq_zech_ctx_t ctx) Sets the entries of a vector of the given length to elements of the finite field. Input and output -------------------------------------------------------------------------------- .. function:: int _fq_zech_vec_fprint(FILE * file, const fq_zech_struct * vec, slong len, const fq_zech_ctx_t ctx) Prints the vector of given length to the stream ``file``. The format is the length followed by two spaces, then a space separated list of coefficients. If the length is zero, only `0` is printed. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int _fq_zech_vec_print(const fq_zech_struct * vec, slong len, const fq_zech_ctx_t ctx) Prints the vector of given length to ``stdout``. For further details, see ``_fq_zech_vec_fprint()``. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _fq_zech_vec_set(fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len2, const fq_zech_ctx_t ctx) Makes a copy of ``(vec2, len2)`` into ``vec1``. .. function:: void _fq_zech_vec_swap(fq_zech_struct * vec1, fq_zech_struct * vec2, slong len2, const fq_zech_ctx_t ctx) Swaps the elements in ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fq_zech_vec_zero(fq_zech_struct * vec, slong len, const fq_zech_ctx_t ctx) Zeros the entries of ``(vec, len)``. .. function:: void _fq_zech_vec_neg(fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len2, const fq_zech_ctx_t ctx) Negates ``(vec2, len2)`` and places it into ``vec1``. Comparison -------------------------------------------------------------------------------- .. function:: int _fq_zech_vec_equal(const fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len, const fq_zech_ctx_t ctx) Compares two vectors of the given length and returns `1` if they are equal, otherwise returns `0`. .. function:: int _fq_zech_vec_is_zero(const fq_zech_struct * vec, slong len, const fq_zech_ctx_t ctx) Returns `1` if ``(vec, len)`` is zero, and `0` otherwise. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _fq_zech_vec_add(fq_zech_struct * res, const fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len2, const fq_zech_ctx_t ctx) Sets ``(res, len2)`` to the sum of ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fq_zech_vec_sub(fq_zech_struct * res, const fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len2, const fq_zech_ctx_t ctx) Sets ``(res, len2)`` to ``(vec1, len2)`` minus ``(vec2, len2)``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void _fq_zech_vec_scalar_addmul_fq_zech(fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len2, const fq_zech_t c, const fq_zech_ctx_t ctx) Adds ``(vec2, len2)`` times `c` to ``(vec1, len2)``, where `c` is a ``fq_zech_t``. .. function:: void _fq_zech_vec_scalar_submul_fq_zech(fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len2, const fq_zech_t c, const fq_zech_ctx_t ctx) Subtracts ``(vec2, len2)`` times `c` from ``(vec1, len2)``, where `c` is a ``fq_zech_t``. Dot products -------------------------------------------------------------------------------- .. function:: void _fq_zech_vec_dot(fq_zech_t res, const fq_zech_struct * vec1, const fq_zech_struct * vec2, slong len2, const fq_zech_ctx_t ctx) Sets ``res`` to the dot product of (``vec1``, ``len``) and (``vec2``, ``len``). flint-3.1.3/doc/source/gamma.rst000066400000000000000000000065621461254215100165250ustar00rootroot00000000000000.. _algorithms_gamma: Algorithms for the gamma function =============================================================================== The Stirling series ------------------------------------------------------------------------------- In general, the gamma function is computed via the Stirling series .. math:: \log \Gamma(z) = \left(z-\frac{1}{2}\right)\log z - z + \frac{\ln {2 \pi}}{2} + \sum_{k=1}^{n-1} \frac{B_{2k}}{2k(2k-1)z^{2k-1}} + R(n,z) where ([Olv1997]_ pp. 293-295) the remainder term is exactly .. math:: R_n(z) = \int_0^{\infty} \frac{B_{2n} - {\tilde B}_{2n}(x)}{2n(x+z)^{2n}} dx. To evaluate the gamma function of a power series argument, we substitute `z \to z + t \in \mathbb{C}[[t]]`. Using the bound for `|x+z|` given by [Olv1997]_ and the fact that the numerator of the integrand is bounded in absolute value by `2 |B_{2n}|`, the remainder can be shown to satisfy the bound .. math:: |[t^k] R_n(z+t)| \le 2 |B_{2n}| \frac{\Gamma(2n+k-1)}{\Gamma(k+1) \Gamma(2n+1)} \; |z| \; \left(\frac{b}{|z|}\right)^{2n+k} where `b = 1/\cos(\operatorname{arg}(z)/2)`. Note that by trigonometric identities, assuming that `z = x+yi`, we have `b = \sqrt{1 + u^2}` where .. math:: u = \frac{y}{\sqrt{x^2 + y^2} + x} = \frac{\sqrt{x^2 + y^2} - x}{y}. To use the Stirling series at `p`-bit precision, we select parameters `r`, `n` such that the remainder `R(n,z)` approximately is bounded by `2^{-p}`. If `|z|` is too small for the Stirling series to give sufficient accuracy directly, we first translate to `z + r` using the formula `\Gamma(z) = \Gamma(z+r) / (z (z+1) (z+2) \cdots (z+r-1))`. To obtain a remainder smaller than `2^{-p}`, we must choose an `r` such that, in the real case, `z + r > \beta p`, where `\beta > \log(2) / (2 \pi) \approx 0.11`. In practice, a slightly larger factor `\beta \approx 0.2` more closely balances `n` and `r`. A much larger `\beta` (e.g. `\beta = 1`) could be used to reduce the number of Bernoulli numbers that have to be precomputed, at the expense of slower repeated evaluation. Rational arguments ------------------------------------------------------------------------------- We use efficient methods to compute `y = \Gamma(p/q)` where `q` is one of `1, 2, 3, 4, 6` and `p` is a small integer. The cases `\Gamma(1) = 1` and `\Gamma(1/2) = \sqrt \pi` are trivial. We reduce all remaining cases to `\Gamma(1/3)` or `\Gamma(1/4)` using the following relations: .. math:: \Gamma(2/3) = \frac{2 \pi}{3^{1/2} \Gamma(1/3)}, \quad \quad \Gamma(3/4) = \frac{2^{1/2} \pi}{\Gamma(1/4)}, .. math:: \Gamma(1/6) = \frac{\Gamma(1/3)^2}{(\pi/3)^{1/2} 2^{1/3}}, \quad \quad \Gamma(5/6) = \frac{2 \pi (\pi/3)^{1/2} 2^{1/3}}{\Gamma(1/3)^2}. We compute `\Gamma(1/3)` and `\Gamma(1/4)` rapidly to high precision using .. math:: \frac{\pi}{\Gamma(1/3)^3} = \frac{1}{960 \cdot 10^{1/4}} \sum_{k=0}^{\infty} \left(-\frac{3^2}{2^9 \cdot 5^3}\right)^k (9108 k + 279) \frac{(1/12)_k (5/12)_k}{(k!)^2}, \quad \quad \Gamma(1/4) = \sqrt{\frac{(2\pi)^{3/2}}{\operatorname{agm}(1, \sqrt 2)}}. where the infinite series is due to Guillera. An alternative formula which could be used for `\Gamma(1/3)` is .. math:: \Gamma(1/3) = \frac{2^{4/9} \pi^{2/3}}{3^{1/12} \left( \operatorname{agm}\left(1,\frac{1}{2} \sqrt{2+\sqrt{3}}\right)\right)^{1/3}}, but this appears to be slightly slower in practice. flint-3.1.3/doc/source/gr.rst000066400000000000000000001071601461254215100160470ustar00rootroot00000000000000.. _gr: **gr.h** -- generic structures and their elements =============================================================================== Introduction ------------------------------------------------------------------------------- Parents and elements ............................................................................... To work with an element `x \in R` of a particular mathematical structure *R*, we use a context object to represent *R* (the "parent" of `x`). Elements are passed around as pointers. Note: * Parents are not stored as part of the elements; the user must track the context objects for all variables. * Operations are strictly type-stable: elements only change parent when performing an explicit conversion. The structure *R* will typically be a *ring*, but the framework supports general objects (including groups, monoids, and sets without any particular structure whatsoever). We use these terms in a strict mathematical sense: a "ring" must exactly satisfy the ring axioms. It can have inexact *representations*, but this inexactness must be handled rigorously. To give an idea of how the interface works, this example program computes `3^{100}` in the ring of integers and prints the value:: #include "gr.h" int main() { int status; gr_ctx_t ZZ; /* a parent (context object) */ gr_ptr x; /* an element */ gr_ctx_init_fmpz(ZZ); /* ZZ = ring of integers with fmpz_t elements */ GR_TMP_INIT(x, ZZ) /* allocate element on the stack */ status = gr_set_ui(x, 3, ZZ); /* x = 3 */ status |= gr_pow_ui(x, x, 100, ZZ); /* x = x ^ 100 */ status |= gr_println(x, ZZ); GR_TMP_CLEAR(x, ZZ) gr_ctx_clear(ZZ); return status; } Parent and element types ............................................................................... .. type:: gr_ptr Pointer to a ring element or array of contiguous ring elements. This is an alias for ``void *`` so that it can be used with any C type. .. type:: gr_srcptr Pointer to a read-only ring element or read-only array of contiguous ring elements. This is an alias for ``const void *`` so that it can be used with any C type. .. type:: gr_ctx_struct .. type:: gr_ctx_t A context object representing a mathematical structure *R*. It contains the following data: * The size (number of bytes) of each element. * A pointer to a method table. * Optionally a pointer to data defining parameters of the ring (e.g. modulus of a residue ring; element ring and dimensions of a matrix ring; precision of an inexact ring). A :type:`gr_ctx_t` is defined as an array of length one of type :type:`gr_ctx_struct`, permitting a :type:`gr_ctx_t` to be passed by reference. Context objects are not normally passed as ``const`` in order to allow storing mutable caches, additional debugging information, etc. .. type:: gr_ctx_ptr Pointer to a context object. There is no type to represent a single generic element as a struct since we do not know the size of a generic element at compile time. Memory for single elements can either be allocated on the stack with the special macros provided below, or as usual with ``malloc``. Methods can also be used with particular C types like ``fmpz_t`` when the user knows the type. Users may wish to define their own union types when only some particular types will appear in an application. Error handling ............................................................................... To compute over a structure `R`, it is useful to conceptually extend to a larger set `R' = R \cup \{ \text{undefined}, \text{unknown} \}`. * Adding an *undefined* (error) value allows us to extend partial functions to total functions. * An *unknown* value is useful in cases where a result may exist in principle but cannot be computed. An alternative to having an *undefined* value is to choose some arbitrary default value in `R`, say `\text{undefined} = 0` in a ring. This is often done in proof assistants, but in a regular programming environment, we typically want some way to detect domain errors. Representing `R'` as a type-level extension of `R` is tricky in C since we would either have to wrap elements in a larger structure or reserve bit patterns in each type for special values. In any case, it is useful to assume in low-level code that elements *really represent elements of the intended structure* so that there are fewer special cases to handle. We also need some form of error handling for conversions to standard C types. For these reasons, we handle special values (undefined, unknown) using return codes. Functions can return a combination of the following status flags: .. macro:: GR_SUCCESS The operation finished as expected, i.e. the result is a correct element of the target type. .. macro:: GR_DOMAIN The result does not have a value in the domain of the target ring or type, i.e. the result is mathematically undefined. This occurs, for example, on division by zero or when attempting to compute the square root of a non-square. It also occurs when attempting to convert a too large value to a bounded type (example: ``get_ui()`` with input `n \ge 2^{64}`). .. macro:: GR_UNABLE The operation could not be performed because of limitations of the implementation or the data representation, i.e. the result is unknown. Typical reasons: * The result would be too large to fit in memory * The inputs are inexact and an exact comparison is needed * The computation would take too long * An algorithm is not yet implemented for this case If this flag is set, there is also potentially a domain error (but this is unknown). .. macro:: GR_TEST_FAIL Test failure. This is only used in test code. When the status code is any other value than ``GR_SUCCESS``, any output variables may be set to meaningless values. C functions that return a status code are marked with the ``WARN_UNUSED_RESULT`` attribute. This allows compilers to emit warnings when the status code is ignored. Flags can be OR'ed and checked only at the top level of a computation to avoid complex control flow:: status = GR_SUCCESS; gr |= gr_add(res, a, b, ctx); gr |= gr_pow_ui(res, res, 2, ctx); ... If we do not care about recovering from *undefined*/*unknown* results, the following macro is useful: .. macro:: GR_MUST_SUCCEED(expr) Evaluates *expr* and asserts that the return value is ``GR_SUCCESS``. On failure, calls ``flint_abort()``. For uniformity, most operations return a status code, even operations that are not typically expected to fail. Exceptions include the following: * Pure "container" operations like ``init``, ``clear`` and ``swap`` do not return a status code. * Pure predicate functions (see below) return ``T_TRUE`` / ``T_FALSE`` / ``T_UNKNOWN`` instead of computing a separate boolean value and error code. Predicates ............................................................................... We use the following type (borrowed from Calcium) instead of a C int to represent boolean results, allowing the possibility that the value is not computable: .. enum:: truth_t Represents one of the following truth values: .. macro:: T_TRUE .. macro:: T_FALSE .. macro:: T_UNKNOWN Warning: the constants ``T_TRUE`` and ``T_FALSE`` do not correspond to 1 and 0. It is erroneous to write, for example ``!t`` if ``t`` is a :type:`truth_t`. One should instead write ``t != T_TRUE``, ``t == T_FALSE``, etc. depending on whether the unknown case should be included or excluded. Context operations ------------------------------------------------------------------------------- .. function:: slong gr_ctx_sizeof_elem(gr_ctx_t ctx) Return ``sizeof(type)`` where ``type`` is the underlying C type for elements of *ctx*. .. function:: int gr_ctx_clear(gr_ctx_t ctx) Clears the context object *ctx*, freeing any memory allocated by this object. Some context objects may require that no elements are cleared after calling this method, and may leak memory if not all elements have been cleared when calling this method. If *ctx* is derived from a base ring, the base ring context may also be required to stay alive until after this method is called. .. function:: int gr_ctx_write(gr_stream_t out, gr_ctx_t ctx) int gr_ctx_print(gr_ctx_t ctx) int gr_ctx_println(gr_ctx_t ctx) int gr_ctx_get_str(char ** s, gr_ctx_t ctx) Writes a description of the structure *ctx* to the stream *out*, prints it to *stdout*, or sets *s* to a pointer to a heap-allocated string of the description (the user must free the string with ``flint_free``). The *println* version prints a trailing newline. .. function:: int gr_ctx_set_gen_name(gr_ctx_t ctx, const char * s) int gr_ctx_set_gen_names(gr_ctx_t ctx, const char ** s) Set the name of the generator (univariate polynomial ring, finite field, etc.) or generators (multivariate). The name is used when printing and may be used to choose coercions. Element operations -------------------------------------------------------------------------------- Memory management ................................................................................ .. function:: void gr_init(gr_ptr res, gr_ctx_t ctx) Initializes *res* to a valid variable and sets it to the zero element of the ring *ctx*. .. function:: void gr_clear(gr_ptr res, gr_ctx_t ctx) Clears *res*, freeing any memory allocated by this object. .. function:: void gr_swap(gr_ptr x, gr_ptr y, gr_ctx_t ctx) Swaps *x* and *y* efficiently. .. function:: void gr_set_shallow(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to a shallow copy of *x*, copying the struct data. .. function:: gr_ptr gr_heap_init(gr_ctx_t ctx) Return a pointer to a single new heap-allocated element of *ctx* set to 0. .. function:: void gr_heap_clear(gr_ptr x, gr_ctx_t ctx) Free the single heap-allocated element *x* of *ctx* which should have been created with :func:`gr_heap_init`. .. function:: gr_ptr gr_heap_init_vec(slong len, gr_ctx_t ctx) Return a pointer to a new heap-allocated vector of *len* initialized elements. .. function:: void gr_heap_clear_vec(gr_ptr x, slong len, gr_ctx_t ctx) Clear the *len* elements in the heap-allocated vector *len* and free the vector itself. The following macros support allocating temporary variables efficiently. Data will be allocated on the stack using ``alloca`` unless the size is excessive (risking stack overflow), in which case the implementation transparently switches to ``malloc``/``free`` instead. The usage pattern is as follows:: { gr_ptr x, y; GR_TMP_INIT2(x1, x2, ctx); /* do computations with x1, x2 */ GR_TMP_CLEAR2(x1, x2, ctx); } Init and clear macros must match exactly, as variables may be allocated contiguously in a block. *Warning:* never use these macros directly inside a loop. This is likely to overflow the stack, as memory will not be reclaimed until the function exits. Instead, allocate the needed space before entering any loops, move the loop body to a separate function, or allocate the memory on the heap if needed. .. macro:: GR_TMP_INIT_VEC(vec, len, ctx) GR_TMP_CLEAR_VEC(vec, len, ctx) Allocates and frees a vector of *len* contiguous elements, all initialized to the value 0, assigning the first element to the pointer *vec*. .. macro:: GR_TMP_INIT(x1, ctx) GR_TMP_INIT2(x1, x2, ctx) GR_TMP_INIT3(x1, x2, x3, ctx) GR_TMP_INIT4(x1, x2, x3, x4, ctx) GR_TMP_INIT5(x1, x2, x3, x4, x5, ctx) Allocates one or several temporary elements, all initialized to the value 0, assigning the elements to the pointers *x1*, *x2*, etc. .. macro:: GR_TMP_CLEAR(x1, ctx) GR_TMP_CLEAR2(x1, x2, ctx) GR_TMP_CLEAR3(x1, x2, x3, ctx) GR_TMP_CLEAR4(x1, x2, x3, x4, ctx) GR_TMP_CLEAR5(x1, x2, x3, x4, x5, ctx) Corresponding macros to clear temporary variables. Random elements ................................................................................ .. function:: int gr_randtest(gr_ptr res, flint_rand_t state, gr_ctx_t ctx) Sets *res* to a random element of the domain *ctx*. The distribution is determined by the implementation. Typically the distribution is non-uniform in order to find corner cases more easily in test code. .. function:: int gr_randtest_not_zero(gr_ptr res, flint_rand_t state, gr_ctx_t ctx) Sets *res* to a random nonzero element of the domain *ctx*. This operation will fail and return ``GR_DOMAIN`` in the zero ring. .. function:: int gr_randtest_small(gr_ptr res, flint_rand_t state, gr_ctx_t ctx) Sets *res* to a "small" element of the domain *ctx*. This is suitable for randomized testing where a "large" argument could result in excessive computation time. Input, output and string conversion ................................................................................ .. function:: int gr_write(gr_stream_t out, gr_srcptr x, gr_ctx_t ctx) int gr_print(gr_srcptr x, gr_ctx_t ctx) int gr_println(gr_srcptr x, gr_ctx_t ctx) int gr_get_str(char ** s, gr_srcptr x, gr_ctx_t ctx) Writes a description of the element *x* to the stream *out*, or prints it to *stdout*, or sets *s* to a pointer to a heap-allocated string of the description (the user must free the string with ``flint_free``). The *println* version prints a trailing newline. .. function:: int gr_set_str(gr_ptr res, const char * x, gr_ctx_t ctx) Sets *res* to the string description in *x*. .. function:: int gr_write_n(gr_stream_t out, gr_srcptr x, slong n, gr_ctx_t ctx) int gr_get_str_n(char ** s, gr_srcptr x, slong n, gr_ctx_t ctx) String conversion where real and complex numbers may be rounded to *n* digits. Assignment and conversions ................................................................................ .. function:: int gr_set(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to a copy of the element *x*. .. function:: int gr_set_other(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) Sets *res* to the element *x* of the structure *x_ctx* which may be different from *ctx*. This returns the ``GR_DOMAIN`` flag if *x* is not an element of *ctx* or cannot be converted unambiguously to *ctx*. The ``GR_UNABLE`` flag is returned if the conversion is not implemented. .. function:: int gr_set_ui(gr_ptr res, ulong x, gr_ctx_t ctx) int gr_set_si(gr_ptr res, slong x, gr_ctx_t ctx) int gr_set_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) int gr_set_fmpq(gr_ptr res, const fmpq_t x, gr_ctx_t ctx) int gr_set_d(gr_ptr res, double x, gr_ctx_t ctx) Sets *res* to the value *x*. If no reasonable conversion to the domain *ctx* is possible, returns ``GR_DOMAIN``. .. function:: int gr_get_si(slong * res, gr_srcptr x, gr_ctx_t ctx) int gr_get_ui(ulong * res, gr_srcptr x, gr_ctx_t ctx) int gr_get_fmpz(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) int gr_get_fmpq(fmpq_t res, gr_srcptr x, gr_ctx_t ctx) int gr_get_d(double * res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to the value *x*. This returns the ``GR_DOMAIN`` flag if *x* cannot be converted to the target type. For floating-point output types, the output may be rounded. .. function:: int gr_set_fmpz_2exp_fmpz(gr_ptr res, const fmpz_t a, const fmpz_t b, gr_ctx_t ctx) int gr_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, gr_srcptr x, gr_ctx_t ctx) Set or retrieve a dyadic number `a \cdot 2^b`. .. function:: int gr_set_fmpz_10exp_fmpz(gr_ptr res, const fmpz_t a, const fmpz_t b, gr_ctx_t ctx) Set to a decimal number `a \cdot 10^b`. .. function:: int gr_get_fexpr(fexpr_t res, gr_srcptr x, gr_ctx_t ctx) int gr_get_fexpr_serialize(fexpr_t res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to a symbolic expression representing *x*. The *serialize* version may generate a representation of the internal representation which is not intended to be human-readable. .. function:: int gr_set_fexpr(gr_ptr res, fexpr_vec_t inputs, gr_vec_t outputs, const fexpr_t x, gr_ctx_t ctx) Sets *res* to the evaluation of the expression *x* in the given ring or structure. The user must provide vectors *inputs* and *outputs* which may be empty initially and which may be used as scratch space during evaluation. Non-empty vectors may be given to map symbols to predefined values. Special values ................................................................................ .. function:: int gr_zero(gr_ptr res, gr_ctx_t ctx) int gr_one(gr_ptr res, gr_ctx_t ctx) int gr_neg_one(gr_ptr res, gr_ctx_t ctx) Sets *res* to the ring element 0, 1 or -1. .. function:: int gr_gen(gr_ptr res, gr_ctx_t ctx) Sets *res* to a generator of this domain. The meaning of "generator" depends on the domain. .. function:: int gr_gens(gr_vec_t res, gr_ctx_t ctx) int gr_gens_recursive(gr_vec_t res, gr_ctx_t ctx) Sets *res* to a vector containing the generators of this domain where this makes sense, for example in a multivariate polynomial ring. The *recursive* version also includes any generators of the base ring, and of any recursive base rings. Basic properties ........................................................................ .. function:: truth_t gr_is_zero(gr_srcptr x, gr_ctx_t ctx) truth_t gr_is_one(gr_srcptr x, gr_ctx_t ctx) truth_t gr_is_neg_one(gr_srcptr x, gr_ctx_t ctx) Returns whether *x* is equal to the ring element 0, 1 or -1, respectively. .. function:: truth_t gr_equal(gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) Returns whether the elements *x* and *y* are equal. .. function:: truth_t gr_is_integer(gr_srcptr x, gr_ctx_t ctx) Returns whether *x* represents an integer. .. function:: truth_t gr_is_rational(gr_srcptr x, gr_ctx_t ctx) Returns whether *x* represents a rational number. Arithmetic ........................................................................ User-defined rings should supply ``neg``, ``add``, ``sub`` and ``mul`` methods; the variants with other operand types have generic fallbacks that may be overridden for performance. The ``fmpq`` versions may return ``GR_DOMAIN`` if the denominator is not invertible. The *other* versions accept operands belonging to a different domain, attempting to perform a coercion into the target domain. .. function:: int gr_neg(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to `-x`. .. function:: int gr_add(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_add_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_add_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_add_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_add_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_add_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_other_add(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) Sets *res* to `x + y`. .. function:: int gr_sub(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_sub_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_sub_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_sub_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_sub_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_sub_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_other_sub(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) Sets *res* to `x - y`. .. function:: int gr_mul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_mul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_mul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_mul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_mul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_mul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_other_mul(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) Sets *res* to `x \cdot y`. .. function:: int gr_addmul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_addmul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_addmul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_addmul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_addmul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_addmul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) Sets *res* to `\mathrm{res } + x \cdot y`. Rings may override the default implementation to perform this operation in one step without allocating a temporary variable, without intermediate rounding, etc. .. function:: int gr_submul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_submul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_submul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_submul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_submul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_submul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) Sets *res* to `\mathrm{res } - x \cdot y`. Rings may override the default implementation to perform this operation in one step without allocating a temporary variable, without intermediate rounding, etc. .. function:: int gr_mul_two(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to `2x`. The default implementation adds *x* to itself. .. function:: int gr_sqr(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to `x ^ 2`. The default implementation multiplies *x* with itself. .. function:: int gr_mul_2exp_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_mul_2exp_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) Sets *res* to `x \cdot 2^y`. This may perform `x \cdot 2^{-y}` when *y* is negative, allowing exact division by powers of two even if `2^{y}` is not representable. Iterated arithmetic operations are best performed using vector functions. See in particular :func:`_gr_vec_dot` and :func:`_gr_vec_dot_rev`. Division ........................................................................ The default implementations of the following methods check for divisors 0, 1, -1 and otherwise return ``GR_UNABLE``. Particular rings should override the methods when an inversion or division algorithm is available. .. function:: truth_t gr_is_invertible(gr_srcptr x, gr_ctx_t ctx) Returns whether *x* has a multiplicative inverse in the present ring, i.e. whether *x* is a unit. .. function:: int gr_inv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to the multiplicative inverse of *x* in the present ring, if such an element exists. Returns the flag ``GR_DOMAIN`` if *x* is not invertible, or ``GR_UNABLE`` if the implementation is unable to perform the computation. .. function:: int gr_div(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_div_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_div_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_div_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_div_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_div_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_other_div(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) Sets *res* to the quotient `x / y`. In a field, this returns ``GR_DOMAIN`` if `y` is zero; in an integral domain, it returns ``GR_DOMAIN`` if `y` is zero or if the quotient does not exist. In a non-integral domain, we consider a quotient to exist only if it is unique, and otherwise return ``GR_DOMAIN``; see :func:`gr_div_nonunique` for a different behavior. Returns the flag ``GR_UNABLE`` if the implementation is unable to perform the computation. .. function:: int gr_div_nonunique(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) Sets *res* to an arbitrary solution `q` of the equation `x = q y`. Returns the flag ``GR_DOMAIN`` if no such solution exists. Returns the flag ``GR_UNABLE`` if the implementation is unable to perform the computation. This method allows dividing `x / y` in some cases where :func:`gr_div` fails: * `0 / 0` has solutions (for example, 0) in any ring. * It allows solving division problems in nonintegral domains. For example, it allows assigning a value to `6 / 2` in `R = \mathbb{Z}/10\mathbb{Z}` even though `2^{-1}` does not exist in `R`. In this case, both 3 and 8 are possible solutions, and which one is chosen is unpredictable. .. function:: truth_t gr_divides(gr_srcptr d, gr_srcptr x, gr_ctx_t ctx) Returns whether `d \mid x`; that is, whether there is an element `q` such that `x = dq`. Note that this corresponds to divisibility in the sense of :func:`gr_div_nonunique`, which is weaker than that of :func:`gr_div`. For example, `0 \mid 0` is true even in rings where `0 / 0` is undefined. .. function:: int gr_divexact(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_divexact_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_divexact_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_divexact_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_divexact_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_other_divexact(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) Sets *res* to the quotient `x / y`, assuming that this quotient is exact in the present ring. Rings may optimize this operation by not verifying that the division is possible. If the division is not actually exact, the implementation may set *res* to a nonsense value and still return the ``GR_SUCCESS`` flag. .. function:: int gr_euclidean_div(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_euclidean_rem(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_euclidean_divrem(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) In a Euclidean ring, these functions perform some version of Euclidean division with remainder, where the choice of quotient is implementation-defined. For example, it is standard to use the round-to-floor quotient in `\mathbb{Z}` and a round-to-nearest quotient in `\mathbb{Z}[i]`. In non-Euclidean rings, these functions may implement some generalization of Euclidean division with remainder. Powering ........................................................................ .. function:: int gr_pow(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_pow_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_pow_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_pow_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_pow_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_pow_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_other_pow(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) Sets *res* to the power `x ^ y`, the interpretation of which depends on the ring when `y \not \in \mathbb{Z}`. Returns the flag ``GR_DOMAIN`` if this power cannot be assigned a meaningful value in the present ring, or ``GR_UNABLE`` if the implementation is unable to perform the computation. For subrings of `\mathbb{C}`, it is implied that the principal power `x^y = \exp(y \log(x))` is computed for `x \ne 0`. Default implementations of the powering methods support raising elements to integer powers using a generic implementation of exponentiation by squaring. Particular rings should override these methods with faster versions or to support more general notions of exponentiation when possible. Square roots ........................................................................ The default implementations of the following methods check for the elements 0 and 1 and otherwise return ``GR_UNABLE``. Particular rings should override the methods when a square root algorithm is available. In subrings of `\mathbb{C}`, it is implied that the principal square root is computed; in other cases (e.g. in finite fields), the choice of root is implementation-dependent. .. function:: truth_t gr_is_square(gr_srcptr x, gr_ctx_t ctx) Returns whether *x* is a perfect square in the present ring. .. function:: int gr_sqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_rsqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to a square root of *x* (respectively reciprocal square root) in the present ring, if such an element exists. Returns the flag ``GR_DOMAIN`` if *x* is not a perfect square (also for zero, when computing the reciprocal square root), or ``GR_UNABLE`` if the implementation is unable to perform the computation. Greatest common divisors ........................................................................ .. function:: int gr_gcd(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) Sets *res* to a greatest common divisor (GCD) of *x* and *y*. Since the GCD is unique only up to multiplication by a unit, an implementation-defined representative is chosen. .. function:: int gr_lcm(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) Sets *res* to a least common multiple (LCM) of *x* and *y*. Since the LCM is unique only up to multiplication by a unit, an implementation-defined representative is chosen. Factorization ........................................................................ .. function:: int gr_factor(gr_ptr c, gr_vec_t factors, gr_vec_t exponents, gr_srcptr x, int flags, gr_ctx_t ctx) Given `x \in R`, computes a factorization `x = c {f_1}^{e_1} \ldots {f_n}^{e_n}` where `f_k` will be irreducible or prime (depending on `R`). The prefactor `c` stores a unit, sign, or coefficient, e.g.\ the sign `-1`, `0` or `+1` in `\mathbb{Z}`, or a sign multiplied by the coefficient content in `\mathbb{Z}[x]`. Note that this function outputs `c` as an element of the same ring as the input: for example, in `\mathbb{Z}[x]`, `c` will be a constant polynomial rather than an element of the coefficient ring. The exponents `e_k` are output as a vector of ``fmpz`` elements. The factors `f_k` are guaranteed to be distinct, but they are not guaranteed to be sorted in any particular order. Fractions ........................................................................ .. function:: int gr_numerator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_denominator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Return a numerator `p` and denominator `q` such that `x = p/q`. For typical fraction fields, the denominator will be minimal and canonical. However, some rings may return an arbitrary denominator as long as the numerator matches. The default implementations simply return `p = x` and `q = 1`. Integer and complex parts ........................................................................ .. function:: int gr_floor(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_ceil(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_trunc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_nint(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) In the real and complex numbers, sets *res* to the integer closest to *x*, respectively rounding towards minus infinity, plus infinity, zero, or the nearest integer (with tie-to-even). .. function:: int gr_abs(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Sets *res* to the absolute value of *x*, which maybe defined both in complex rings and in any ordered ring. .. function:: int gr_i(gr_ptr res, gr_ctx_t ctx) Sets *res* to the imaginary unit. .. function:: int gr_conj(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_re(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_im(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sgn(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_csgn(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_arg(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) These methods may return the flag ``GR_DOMAIN`` (or ``GR_UNABLE``) when the ring is not a subring of the real or complex numbers. Infinities and extended values ........................................................................ .. function:: int gr_pos_inf(gr_ptr res, gr_ctx_t ctx) int gr_neg_inf(gr_ptr res, gr_ctx_t ctx) int gr_uinf(gr_ptr res, gr_ctx_t ctx) int gr_undefined(gr_ptr res, gr_ctx_t ctx) int gr_unknown(gr_ptr res, gr_ctx_t ctx) Ordering methods ........................................................................ .. function:: int gr_cmp(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_cmp_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) Sets *res* to -1, 0 or 1 according to whether *x* is less than, equal or greater than the absolute value of *y*. This may return ``GR_DOMAIN`` if the ring is not an ordered ring. .. function:: int gr_cmpabs(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_cmpabs_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) Sets *res* to -1, 0 or 1 according to whether the absolute value of *x* is less than, equal or greater than the absolute value of *y*. This may return ``GR_DOMAIN`` if the ring is not an ordered ring. Enclosure and interval methods ........................................................................ .. function:: int gr_set_interval_mid_rad(gr_ptr res, gr_srcptr m, gr_srcptr r, gr_ctx_t ctx) In ball representations of the real numbers, sets *res* to the interval `m \pm r`. In vector spaces over the real numbers represented using balls, intervals are handled independently for the generators; for example, in the complex numbers, `a + b i \pm (0.1 + 0.2 i)` is equivalent to `(a \pm 0.1) + (b \pm 0.2) i`. Finite field methods ........................................................................ .. function:: int gr_ctx_fq_prime(fmpz_t p, gr_ctx_t ctx) .. function:: int gr_ctx_fq_degree(slong * deg, gr_ctx_t ctx) .. function:: int gr_ctx_fq_order(fmpz_t q, gr_ctx_t ctx) .. function:: int gr_fq_frobenius(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx) .. function:: int gr_fq_multiplicative_order(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_fq_norm(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_fq_trace(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) .. function:: truth_t gr_fq_is_primitive(gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_fq_pth_root(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. raw:: latex \newpage flint-3.1.3/doc/source/gr_domains.rst000066400000000000000000000301411461254215100175530ustar00rootroot00000000000000.. _gr-domains: **gr.h (continued)** -- builtin domains and types =============================================================================== Coercions ------------------------------------------------------------------------------- .. function:: int gr_ctx_cmp_coercion(gr_ctx_t ctx1, gr_ctx_t ctx2) Returns 1 if coercing elements into *ctx1* is more meaningful, and returns -1 otherwise. Domain properties ------------------------------------------------------------------------------- .. function:: truth_t gr_ctx_is_finite(gr_ctx_t ctx) truth_t gr_ctx_is_multiplicative_group(gr_ctx_t ctx) truth_t gr_ctx_is_ring(gr_ctx_t ctx) truth_t gr_ctx_is_commutative_ring(gr_ctx_t ctx) truth_t gr_ctx_is_integral_domain(gr_ctx_t ctx) truth_t gr_ctx_is_unique_factorization_domain(gr_ctx_t ctx) truth_t gr_ctx_is_field(gr_ctx_t ctx) truth_t gr_ctx_is_algebraically_closed(gr_ctx_t ctx) truth_t gr_ctx_is_finite_characteristic(gr_ctx_t ctx) truth_t gr_ctx_is_ordered_ring(gr_ctx_t ctx) truth_t gr_ctx_is_zero_ring(gr_ctx_t ctx) Returns whether the structure satisfies the respective mathematical property. The result can be ``T_UNKNOWN``. .. function:: truth_t gr_ctx_is_exact(gr_ctx_t ctx) Returns whether the representation of elements is always exact. .. function:: truth_t gr_ctx_is_canonical(gr_ctx_t ctx) Returns whether the representation of elements is always canonical. .. function:: truth_t gr_ctx_has_real_prec(gr_ctx_t ctx) Returns whether *ctx* or a base field thereof represents real or complex numbers using finite-precision approximations. This returns ``T_TRUE`` both for floating-point approximate fields and for rigorous fields based on ball or interval arithmetic. .. function:: int gr_ctx_set_real_prec(gr_ctx_t ctx, slong prec) int gr_ctx_get_real_prec(slong * prec, gr_ctx_t ctx) Sets or retrieves the floating-point precision in bits. Groups ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_perm(gr_ctx_t ctx, ulong n) Initializes *ctx* to the symmetric group `S_n` representing permutations of `[0, 1, \ldots, n - 1]`. Elements are currently represented as pointers (the representation may change in the future). .. function:: void gr_ctx_init_psl2z(gr_ctx_t ctx) Initializes *ctx* to the modular group `\text{PSL}(2, \mathbb{Z})` with elements of type :type:`psl2z_t`. .. function:: int gr_ctx_init_dirichlet_group(gr_ctx_t ctx, ulong q) Initializes *ctx* to the Dirichlet group `G_q` with elements of type :type:`dirichlet_char_t`. Fails and returns ``GR_DOMAIN`` if *q* is zero. Fails and returns ``GR_UNABLE`` if *q* has a prime factor larger than `10^{16}`, which is currently unsupported by the implementation. Base rings and fields ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_random(gr_ctx_t ctx, flint_rand_t state) Initializes *ctx* to a random ring. This will currently only generate base rings and composite rings over certain simple base rings. .. function:: void gr_ctx_init_fmpz(gr_ctx_t ctx) Initializes *ctx* to the ring of integers `\mathbb{Z}` with elements of type :type:`fmpz`. .. function:: void gr_ctx_init_fmpq(gr_ctx_t ctx) Initializes *ctx* to the field of rational numbers `\mathbb{Q}` with elements of type :type:`fmpq`. .. function:: void gr_ctx_init_fmpzi(gr_ctx_t ctx) Initializes *ctx* to the ring of Gaussian integers `\mathbb{Z}[i]` with elements of type :type:`fmpzi_t`. .. function:: void gr_ctx_init_nmod8(gr_ctx_t ctx, unsigned char n) void gr_ctx_init_nmod32(gr_ctx_t ctx, unsigned int n) Initializes *ctx* to the ring `\mathbb{Z}/n\mathbb{Z}` of integers modulo *n* where elements have type :type:`uint8` or :type:`uint32`. The modulus must be nonzero. .. function:: void gr_ctx_init_nmod(gr_ctx_t ctx, ulong n) Initializes *ctx* to the ring `\mathbb{Z}/n\mathbb{Z}` of integers modulo *n* where elements have type :type:`ulong`. We require `n \ne 0`. .. function:: void gr_ctx_init_fmpz_mod(gr_ctx_t ctx, const fmpz_t n) Initializes *ctx* to the ring `\mathbb{Z}/n\mathbb{Z}` of integers modulo *n* where elements have type :type:`fmpz`. The modulus must be positive. .. function:: void gr_ctx_nmod_set_primality(gr_ctx_t ctx, truth_t is_prime) void gr_ctx_fmpz_mod_set_primality(gr_ctx_t ctx, truth_t is_prime) For a ring initialized with :func:`gr_ctx_init_nmod` or :func:`gr_ctx_init_fmpz_mod` respectively, indicate whether the modulus is prime. This can speed up some computations. .. function:: void gr_ctx_init_fq(gr_ctx_t ctx, const fmpz_t p, slong d, const char * var) void gr_ctx_init_fq_nmod(gr_ctx_t ctx, ulong p, slong d, const char * var) void gr_ctx_init_fq_zech(gr_ctx_t ctx, ulong p, slong d, const char * var) Initializes *ctx* to the finite field `\mathbb{F}_q` where `q = p^d`. It is assumed (not checked) that *p* is prime. The variable name *var* can be ``NULL`` to use a default. The corresponding element types are ``fq_t``, ``fq_nmod_t``, ``fq_zech_t``. The ``fq_zech`` context requires `q < 2^{64}` (and in practice a much smaller value than this). .. function:: void gr_ctx_init_nf(gr_ctx_t ctx, const fmpq_poly_t poly) void gr_ctx_init_nf_fmpz_poly(gr_ctx_t ctx, const fmpz_poly_t poly) Initializes *ctx* to the number field with defining polynomial ``poly`` which *must* be irreducible (this is not checked). The elements have type :type:`nf_elem_t`. .. function:: void gr_ctx_init_real_qqbar(gr_ctx_t ctx) void gr_ctx_init_complex_qqbar(gr_ctx_t ctx) Initializes *ctx* to the field of real or complex algebraic numbers with elements of type :type:`qqbar_t`. .. function:: void _gr_ctx_qqbar_set_limits(gr_ctx_t ctx, slong deg_limit, slong bits_limit) Limit degrees of intermediate operands of a *qqbar* context to *deg_limit* and their bit sizes to *bits_limit* (approximately). The limits refer to the sizes of resultants prior to factorization (see :func:`qqbar_binop_within_limits`), so for example adding two degree-100 algebraic numbers requires a degree limit of at least 10000. Warning: currently not all methods respect these limits. .. function:: void gr_ctx_init_real_arb(gr_ctx_t ctx, slong prec) void gr_ctx_init_complex_acb(gr_ctx_t ctx, slong prec) Initializes *ctx* to the field of real or complex numbers represented by elements of type :type:`arb_t` and :type:`acb_t`. .. function:: void gr_ctx_arb_set_prec(gr_ctx_t ctx, slong prec) slong gr_ctx_arb_get_prec(gr_ctx_t ctx) Sets or retrieves the bit precision of *ctx* which must be an Arb context (this is currently not checked). .. function:: void gr_ctx_init_real_ca(gr_ctx_t ctx) void gr_ctx_init_complex_ca(gr_ctx_t ctx) void gr_ctx_init_real_algebraic_ca(gr_ctx_t ctx) void gr_ctx_init_complex_algebraic_ca(gr_ctx_t ctx) Initializes *ctx* to the field of real, complex, real algebraic or complex algebraic numbers represented by elements of type :type:`ca_t`. .. function:: void gr_ctx_ca_set_option(gr_ctx_t ctx, slong option, slong value) slong gr_ctx_ca_get_option(gr_ctx_t ctx, slong option) Sets or retrieves options of a Calcium context object. Extended number sets ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_complex_extended_ca(gr_ctx_t ctx) Like :func:`gr_ctx_init_complex_ca` but allows special values (infinities, undefined). Floating-point arithmetic ------------------------------------------------------------------------------- Although domains of floating-point numbers approximate real and complex fields, they are not rings or fields. Floating-point arithmetic can be used in many places where a ring or field is normally assumed, but predicates like "is field" return false. * Equality compares equality of floating-point numbers, with the special rule that NaN is not equal to itself. * In general, the following implementations do not currently guarantee correct rounding except for atomic arithmetic operations (add, sub, mul, div, sqrt) on real floating-point numbers. .. function:: void gr_ctx_init_real_float_arf(gr_ctx_t ctx, slong prec) Initializes *ctx* to the floating-point arithmetic with elements of type :type:`arf_t` and a default precision of *prec* bits. .. function:: void gr_ctx_init_complex_float_acf(gr_ctx_t ctx, slong prec) Initializes *ctx* to the complex floating-point arithmetic with elements of type :type:`acf_t` and a default precision of *prec* bits. Vectors ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_vector_gr_vec(gr_ctx_t ctx, gr_ctx_t base_type) Initializes *ctx* to the domain of all vectors (of any length) over the given *base_type*. Elements have type :type:`gr_vec_struct`. .. function:: void gr_ctx_init_vector_space_gr_vec(gr_ctx_t ctx, gr_ctx_t base_type, slong n) Initializes *ctx* to the space of all vectors of length *n* over the given *base_type*. Elements have type :type:`gr_vec_struct`. Matrices ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_matrix_domain(gr_ctx_t ctx, gr_ctx_t base_ring) Initializes *ctx* to the domain of all matrices (of any shape) over the given *base_ring*. Elements have type :type:`gr_mat_struct`. .. function:: void gr_ctx_init_matrix_space(gr_ctx_t ctx, gr_ctx_t base_ring, slong n, slong m) Initializes *ctx* to the space of matrices over *base_ring* with *n* rows and *m* columns. Elements have type :type:`gr_mat_struct`. .. function:: void gr_ctx_init_matrix_ring(gr_ctx_t ctx, gr_ctx_t base_ring, slong n) Initializes *ctx* to the ring of matrices over *base_ring* with *n* rows columns. Elements have type :type:`gr_mat_struct`. Polynomial rings ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_fmpz_poly(gr_ctx_t ctx) Initializes *ctx* to a ring of integer polynomials of type :type:`fmpz_poly_struct`. .. function:: void gr_ctx_init_fmpq_poly(gr_ctx_t ctx) Initializes *ctx* to a ring of rational polynomials of type :type:`fmpq_poly_struct`. .. function:: void gr_ctx_init_gr_poly(gr_ctx_t ctx, gr_ctx_t base_ring) Initializes *ctx* to a ring of densely represented univariate polynomials over the given *base_ring*. Elements have type :type:`gr_poly_struct`. .. function:: void gr_ctx_init_fmpz_mpoly(gr_ctx_t ctx, slong nvars, const ordering_t ord) Initializes *ctx* to a ring of sparsely represented multivariate polynomials in *nvars* variables over the integers, with monomial ordering *ord*. Elements have type :type:`fmpz_mpoly_struct`. .. function:: void gr_ctx_init_gr_mpoly(gr_ctx_t ctx, gr_ctx_t base_ring, slong nvars, const ordering_t ord) Initializes *ctx* to a ring of sparsely represented multivariate polynomials in *nvars* variables over the given *base_ring*, with monomial ordering *ord*. Elements have type :type:`gr_mpoly_struct`. Fraction fields ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_fmpz_mpoly_q(gr_ctx_t ctx, slong nvars, const ordering_t ord) Initializes *ctx* to a ring of sparsely represented multivariate fractions in *nvars* variables over the integers (equivalently, rationals), with monomial ordering *ord*. Elements have type :type:`fmpz_mpoly_q_struct`. Symbolic expressions ------------------------------------------------------------------------------- .. function:: void gr_ctx_init_fexpr(gr_ctx_t ctx) Initializes *ctx* to handle symbolic expressions. Elements have type :type:`fexpr_struct`. .. raw:: latex \newpage flint-3.1.3/doc/source/gr_generic.rst000066400000000000000000000524121461254215100175420ustar00rootroot00000000000000.. _gr-generic: **gr_generic.h** -- basic algorithms and fallback implementations for generic elements ====================================================================================== .. function:: void gr_generic_init(void) void gr_generic_clear(void) void gr_generic_swap(void) void gr_generic_randtest(void) void gr_generic_write(void) void gr_generic_zero(void) void gr_generic_one(void) void gr_generic_equal(void) void gr_generic_set(void) void gr_generic_set_si(void) void gr_generic_set_ui(void) void gr_generic_set_fmpz(void) void gr_generic_neg(void) void gr_generic_add(void) void gr_generic_sub(void) void gr_generic_mul(void) .. function:: int gr_generic_ctx_clear(gr_ctx_t ctx) .. function:: void gr_generic_set_shallow(gr_ptr res, gr_srcptr x, const gr_ctx_t ctx) .. function:: int gr_generic_write_n(gr_stream_t out, gr_srcptr x, slong n, gr_ctx_t ctx) .. function:: int gr_generic_randtest_not_zero(gr_ptr x, flint_rand_t state, gr_ctx_t ctx) .. function:: int gr_generic_randtest_small(gr_ptr x, flint_rand_t state, gr_ctx_t ctx) .. function:: truth_t gr_generic_is_zero(gr_srcptr x, gr_ctx_t ctx) truth_t gr_generic_is_one(gr_srcptr x, gr_ctx_t ctx) truth_t gr_generic_is_neg_one(gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_generic_neg_one(gr_ptr res, gr_ctx_t ctx) .. function:: int gr_generic_set_other(gr_ptr res, gr_srcptr x, gr_ctx_t xctx, gr_ctx_t ctx) int gr_generic_set_fmpq(gr_ptr res, const fmpq_t y, gr_ctx_t ctx) Generic string parsing ----------------------------------------------------------------------------------------- .. macro :: GR_PARSE_BALANCE_ADDITIONS .. macro :: GR_PARSE_RING_EXPONENTS .. function:: int gr_generic_set_str_expr(gr_ptr res, const char * s, int flags, gr_ctx_t ctx) int gr_generic_set_str(gr_ptr res, const char * s, gr_ctx_t ctx) int gr_generic_set_str_balance_additions(gr_ptr res, const char * s, gr_ctx_t ctx) int gr_generic_set_str_ring_exponents(gr_ptr res, const char * s, gr_ctx_t ctx) Parses expression string. Generators returned by :func:`gr_gens_recursive` are handled automatically. We have the following flags: * ``GR_PARSE_RING_EXPONENTS`` - by default, only (nonnegative) integer literals are allowed for exponents. If this flag is set, exponents are parsed as arbitrary subexpressions within the same ring. * ``GR_PARSE_BALANCE_ADDITIONS`` - attempt to improve performance for huge sums by reording additions (useful for polynomials) Generic arithmetic ----------------------------------------------------------------------------------------- .. function:: int gr_generic_add_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_generic_add_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_generic_add_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_generic_add_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_generic_add_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_generic_other_add(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_generic_sub_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_generic_sub_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_generic_sub_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_generic_sub_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_generic_sub_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_generic_other_sub(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_generic_mul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_generic_mul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_generic_mul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_generic_mul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_generic_mul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_generic_other_mul(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_generic_addmul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_generic_addmul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_generic_addmul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_generic_addmul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_generic_addmul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_generic_addmul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) .. function:: int gr_generic_submul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_generic_submul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_generic_submul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_generic_submul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_generic_submul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_generic_submul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) .. function:: int gr_generic_mul_two(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_generic_sqr(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_generic_mul_2exp_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_generic_mul_2exp_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) .. function:: int gr_generic_set_fmpz_2exp_fmpz(gr_ptr res, const fmpz_t x, const fmpz_t y, gr_ctx_t ctx) .. function:: int gr_generic_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, gr_ptr x, gr_ctx_t ctx) .. function:: int gr_generic_inv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: truth_t gr_generic_is_invertible(gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_generic_div_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) int gr_generic_div_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_generic_div_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) int gr_generic_div_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_generic_div_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_generic_other_div(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_generic_divexact(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_generic_pow_fmpz_sliding(gr_ptr f, gr_srcptr g, const fmpz_t pow, gr_ctx_t ctx) int gr_generic_pow_ui_sliding(gr_ptr f, gr_srcptr g, ulong pow, gr_ctx_t ctx) int gr_generic_pow_fmpz_binexp(gr_ptr res, gr_srcptr x, const fmpz_t exp, gr_ctx_t ctx) int gr_generic_pow_ui_binexp(gr_ptr res, gr_srcptr x, ulong e, gr_ctx_t ctx) .. function:: int gr_generic_pow_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t e, gr_ctx_t ctx) int gr_generic_pow_si(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx) int gr_generic_pow_ui(gr_ptr res, gr_srcptr x, ulong e, gr_ctx_t ctx) int gr_generic_pow_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) int gr_generic_pow_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_generic_other_pow(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) .. function:: int _gr_fmpz_poly_evaluate_horner(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx) int gr_fmpz_poly_evaluate_horner(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx) int _gr_fmpz_poly_evaluate_rectangular(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx) int gr_fmpz_poly_evaluate_rectangular(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx) int _gr_fmpz_poly_evaluate(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx) int gr_fmpz_poly_evaluate(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx) Sets *res* to the value of the integer polynomial *f* evaluated at the argument *x*. .. function:: int gr_fmpz_mpoly_evaluate_iter(gr_ptr res, const fmpz_mpoly_t f, gr_srcptr x, const fmpz_mpoly_ctx_t mctx, gr_ctx_t ctx) int gr_fmpz_mpoly_evaluate_horner(gr_ptr res, const fmpz_mpoly_t f, gr_srcptr x, const fmpz_mpoly_ctx_t mctx, gr_ctx_t ctx) int gr_fmpz_mpoly_evaluate(gr_ptr res, const fmpz_mpoly_t f, gr_srcptr x, const fmpz_mpoly_ctx_t mctx, gr_ctx_t ctx) Sets *res* to value of the multivariate polynomial *f* (with corresponding context object *mctx*) evaluated at the vector of arguments in *x*. .. function:: truth_t gr_generic_is_square(gr_srcptr x, gr_ctx_t ctx) int gr_generic_sqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_generic_rsqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Currently these methods check for the special values 0 and 1. .. function:: int gr_generic_numerator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_generic_denominator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_generic_cmp(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_generic_cmpabs(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_generic_cmp_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) int gr_generic_cmpabs_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) Generic special functions ----------------------------------------------------------------------------------------- To do: move to ``gr_special`` .. function:: int gr_generic_bernoulli_ui(gr_ptr res, ulong n, gr_ctx_t ctx) int gr_generic_bernoulli_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_generic_bernoulli_vec(gr_ptr res, slong len, gr_ctx_t ctx) int gr_generic_eulernum_ui(gr_ptr res, ulong n, gr_ctx_t ctx) int gr_generic_eulernum_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_generic_eulernum_vec(gr_ptr res, slong len, gr_ctx_t ctx) int gr_generic_stirling_s1u_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) int gr_generic_stirling_s1_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) int gr_generic_stirling_s2_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) int gr_generic_stirling_s1u_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) int gr_generic_stirling_s1_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) int gr_generic_stirling_s2_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) Generic vector methods ----------------------------------------------------------------------------------------- To do: move to ``gr_vec`` .. function:: void gr_generic_vec_init(gr_ptr vec, slong len, gr_ctx_t ctx) .. function:: void gr_generic_vec_clear(gr_ptr vec, slong len, gr_ctx_t ctx) .. function:: void gr_generic_vec_swap(gr_ptr vec1, gr_ptr vec2, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_zero(gr_ptr vec, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_set(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_neg(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_normalise(slong * res, gr_srcptr vec, slong len, gr_ctx_t ctx) .. function:: slong gr_generic_vec_normalise_weak(gr_srcptr vec, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_mul_scalar_2exp_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) .. function:: int gr_generic_vec_scalar_addmul(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) .. function:: int gr_generic_vec_scalar_submul(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) .. function:: int gr_generic_vec_scalar_addmul_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) .. function:: int gr_generic_vec_scalar_submul_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) .. function:: truth_t gr_generic_vec_equal(gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_is_zero(gr_srcptr vec, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_dot(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_dot_rev(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_dot_ui(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const ulong * vec2, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_dot_si(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const slong * vec2, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_dot_fmpz(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_set_powers(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_reciprocals(gr_ptr res, slong len, gr_ctx_t ctx) .. function:: int gr_generic_vec_add(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int gr_generic_vec_sub(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int gr_generic_vec_mul(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int gr_generic_vec_div(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int gr_generic_vec_divexact(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int gr_generic_vec_pow(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int gr_generic_vec_add_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_generic_vec_sub_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_generic_vec_mul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_generic_vec_div_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_generic_vec_divexact_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_generic_vec_pow_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_generic_vec_add_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int gr_generic_vec_sub_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int gr_generic_vec_mul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int gr_generic_vec_div_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int gr_generic_vec_divexact_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int gr_generic_vec_pow_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int gr_generic_vec_add_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int gr_generic_vec_sub_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int gr_generic_vec_mul_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int gr_generic_vec_div_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int gr_generic_vec_divexact_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int gr_generic_vec_pow_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int gr_generic_vec_add_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int gr_generic_vec_sub_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int gr_generic_vec_mul_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int gr_generic_vec_div_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int gr_generic_vec_divexact_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int gr_generic_vec_pow_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int gr_generic_vec_add_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int gr_generic_vec_sub_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int gr_generic_vec_mul_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int gr_generic_vec_div_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int gr_generic_vec_divexact_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int gr_generic_vec_pow_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int gr_generic_scalar_add_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_sub_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_mul_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_div_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_pow_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_vec_add_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int gr_generic_vec_sub_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int gr_generic_vec_mul_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int gr_generic_vec_div_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int gr_generic_vec_divexact_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int gr_generic_vec_pow_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int gr_generic_other_add_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int gr_generic_other_sub_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int gr_generic_other_mul_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int gr_generic_other_div_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int gr_generic_other_divexact_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int gr_generic_other_pow_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int gr_generic_vec_add_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int gr_generic_vec_sub_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int gr_generic_vec_mul_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int gr_generic_vec_div_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int gr_generic_vec_divexact_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int gr_generic_vec_pow_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int gr_generic_scalar_other_add_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_other_sub_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_other_mul_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_other_div_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_other_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int gr_generic_scalar_other_pow_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) .. raw:: latex \newpage flint-3.1.3/doc/source/gr_implementing.rst000066400000000000000000000130011461254215100206050ustar00rootroot00000000000000.. _gr-implementing: **gr.h (continued)** -- implementing rings =============================================================================== .. highlight:: c Defining a ring requires putting appropriate data into a :type:`gr_ctx_t` parent object, most importantly the method table and the size of elements. Example -------------------------------------------------------------------------------- This is an extract from the ``fmpz`` wrapper in ``gr/fmpz.c``:: /* Some methods */ ... int _gr_fmpz_add(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_add(res, x, y); return GR_SUCCESS; } ... /* The method table */ int _fmpz_methods_initialized = 0; gr_static_method_table _fmpz_methods; gr_method_tab_input _fmpz_methods_input[] = { {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, ... {GR_METHOD_INIT, (gr_funcptr) _gr_fmpz_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpz_clear}, ... {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_fmpz_add}, ... {0, (gr_funcptr) NULL}, }; /* Context object initializer */ void gr_ctx_init_fmpz(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_FMPZ; ctx->sizeof_elem = sizeof(fmpz); ctx->size_limit = WORD_MAX; ctx->methods = _fmpz_methods; if (!_fmpz_methods_initialized) { gr_method_tab_init(_fmpz_methods, _fmpz_methods_input); _fmpz_methods_initialized = 1; } } Note that the method table only has to be constructed once, allowing new context objects for the same domain to be initialized cheaply. Method table -------------------------------------------------------------------------------- .. type:: gr_funcptr Typedef for a pointer to a function with signature ``int func(void)``, used to represent method table entries. .. type:: gr_method Enumeration type for indexing method tables. Enum values named ``GR_METHOD_INIT``, ``GR_METHOD_ADD_UI``, etc. correspond to methods ``gr_init``, ``gr_add_ui``, etc. The number of methods is given by ``GR_METHOD_TAB_SIZE``, which can be used to declare static method tables. .. type:: gr_static_method_table Typedef for an array of length ``GR_METHOD_TAB_SIZE`` with :type:`gr_funcptr` entries. .. type:: gr_method_tab_input Typedef representing a (index, function pointer) pair. .. function:: void gr_method_tab_init(gr_funcptr * methods, gr_method_tab_input * tab) Initializes the method table *methods*. This first inserts default and generic methods in all slots, and then overwrites with the specialized methods listed in *tab*. Placeholder and trivial methods -------------------------------------------------------------------------------- .. function:: int gr_not_implemented(void) This function does nothing and returns ``GR_UNABLE``. It is used as a generic fallback method when no implementation is available. .. function:: int gr_not_in_domain(void) This function does nothing and returns ``GR_DOMAIN``. It can be used for an operation that never makes sense in the present domain, e.g.\ for the constant `\pi` in the rational numbers. .. function:: truth_t gr_generic_ctx_predicate(gr_ctx_t ctx) Does nothing and returns ``T_UNKNOWN``, used as a generic fallback for predicate methods. .. function:: truth_t gr_generic_ctx_predicate_true(gr_ctx_t ctx) A predicate that does nothing and returns ``T_TRUE``. .. function:: truth_t gr_generic_ctx_predicate_false(gr_ctx_t ctx) A predicate that does nothing and returns ``T_FALSE``. Required methods -------------------------------------------------------------------------------- A context object must at minimum define the following methods for a ring: * ``init`` * ``clear`` * ``swap`` * ``randtest`` * ``write`` * ``zero`` * ``one`` * ``equal`` * ``set`` * ``set_si`` * ``set_ui`` * ``set_fmpz`` * ``neg`` * ``add`` * ``sub`` * ``mul`` Other methods have generic defaults which may be overridden for performance or completeness. Implementing context predicates (``ctx_is_integral_domain``, ``ctx_is_field``, etc.) is strongly recommended so that the most appropriate algorithms can be used in generic implementations. Rings with cheap operations on single elements should also provide non-generic versions of performance-critical vector operations to minimize overhead. The most important vector operations include: * ``vec_init`` * ``vec_clear`` * ``vec_swap`` * ``vec_zero`` * ``vec_neg`` * ``vec_add`` * ``vec_sub`` * ``vec_mul_scalar_ui``/``si`` * ``vec_addmul_scalar_ui``/``si`` * ``vec_dot`` * ``vec_dot_rev`` Dot products, for example, are the main building block for classical polynomial multiplication and matrix multiplication. The methods * ``poly_mullow`` * ``matrix_mul`` should be overridden for rings where faster-than-classical polynomial and matrix multiplication is possible. Other higher-complexity generic algorithms will try to reduce to polynomial and matrix multiplication automatically, but may in turn need to be overridden to select accurate cutoffs between different algorithms. Testing rings -------------------------------------------------------------------------------- .. function:: void gr_test_ring(gr_ctx_t R, slong iters, int test_flags) Test correctness of the ring *R*. This calls test functions for various methods, each being repeated up to *iters* times. .. raw:: latex \newpage flint-3.1.3/doc/source/gr_mat.rst000066400000000000000000001110671461254215100167110ustar00rootroot00000000000000.. _gr-mat: **gr_mat.h** -- dense matrices over generic rings =============================================================================== A :type:`gr_mat_t` represents a matrix implemented as a dense array of entries in a generic ring *R*. * In this module, the context object ``ctx`` always represents the coefficient ring *R* unless otherwise stated. Creating a context object representing a matrix space only becomes necessary when one wants to manipulate matrices using generic ring methods like ``gr_add`` instead of the designated matrix methods like ``gr_mat_add``. * Matrix functions generally assume that input as well as output operands have compatible shapes. Some functions return ``GR_DOMAIN`` for matrices with the wrong shape, but this is not always consistent. * Some operations (like rank, LU factorization) generally only make sense when the base ring is an integral domain. Typically the algorithms designed for integral domains also work over non-integral domains as long as all inversions of nonzero elements succeed. If an inversion fails, the algorithm will return the ``GR_DOMAIN`` or ``GR_UNABLE`` flag. This might not yet be entirely consistent. Type compatibility ------------------------------------------------------------------------------- The ``gr_mat`` type has the same data layout as most Flint, Arb and Calcium matrix types. Methods in this module can therefore be mixed freely with methods in the corresponding Flint, Arb and Calcium modules when the underlying coefficient type is the same. It is not directly compatible with the ``nmod_mat`` type, which stores modulus data as part of the matrix object. Types, macros and constants ------------------------------------------------------------------------------- .. type:: gr_mat_struct .. type:: gr_mat_t Contains a pointer to an array of coefficients (``entries``), the number of rows (``r``), the number of columns (``c``), and an array to pointers marking the start of each row (``rows``). A ``gr_mat_t`` is defined as an array of length one of type ``gr_mat_struct``, permitting a ``gr_mat_t`` to be passed by reference. .. macro:: GR_MAT_ENTRY(mat, i, j, sz) Macro to access the entry at row *i* and column *j* of the matrix *mat* whose entries have size *sz* bytes. .. function:: gr_ptr gr_mat_entry_ptr(gr_mat_t mat, slong i, slong j, gr_ctx_t ctx) Function returning a pointer to the entry at row *i* and column *j* of the matrix *mat*. The indices must be in bounds. .. macro:: gr_mat_nrows(mat, ctx) Macro accessing the number of rows of *mat*. .. macro:: gr_mat_ncols(mat, ctx) Macro accessing the number of columns of *mat*. Memory management ------------------------------------------------------------------------------- .. function:: void gr_mat_init(gr_mat_t mat, slong rows, slong cols, gr_ctx_t ctx) Initializes *mat* to a matrix with the given number of rows and columns. .. function:: int gr_mat_init_set(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) Initializes *res* to a copy of the matrix *mat*. .. function:: void gr_mat_clear(gr_mat_t mat, gr_ctx_t ctx) Clears the matrix. .. function:: void gr_mat_swap(gr_mat_t mat1, gr_mat_t mat2, gr_ctx_t ctx) Swaps *mat1* and *mat12* efficiently. .. function:: int gr_mat_swap_entrywise(gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) Performs a deep swap of *mat1* and *mat2*, swapping the individual entries rather than the top-level structures. Window matrices ------------------------------------------------------------------------------- .. function:: void gr_mat_window_init(gr_mat_t window, const gr_mat_t mat, slong r1, slong c1, slong r2, slong c2, gr_ctx_t ctx) Initializes *window* to a window matrix into the submatrix of *mat* starting at the corner at row *r1* and column *c1* (inclusive) and ending at row *r2* and column *c2* (exclusive). The indices must be within bounds. .. function:: void gr_mat_window_clear(gr_mat_t window, gr_ctx_t ctx) Frees the window matrix. Input and output ------------------------------------------------------------------------------- .. function:: int gr_mat_write(gr_stream_t out, const gr_mat_t mat, gr_ctx_t ctx) Write *mat* to the stream *out*. .. function:: int gr_mat_print(const gr_mat_t mat, gr_ctx_t ctx) Prints *mat* to standard output. Comparisons ------------------------------------------------------------------------------- .. function:: truth_t gr_mat_equal(const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) Returns whether *mat1* and *mat2* are equal. Assignment and special values ------------------------------------------------------------------------------- .. function:: truth_t gr_mat_is_zero(const gr_mat_t mat, gr_ctx_t ctx) truth_t gr_mat_is_one(const gr_mat_t mat, gr_ctx_t ctx) truth_t gr_mat_is_neg_one(const gr_mat_t mat, gr_ctx_t ctx) Returns whether *mat* respectively is the zero matrix or the scalar matrix with 1 or -1 on the main diagonal. .. function:: truth_t gr_mat_is_scalar(const gr_mat_t mat, gr_ctx_t ctx) Returns whether *mat* is a scalar matrix, being a diagonal matrix with identical elements on the main diagonal. .. function:: int gr_mat_zero(gr_mat_t res, gr_ctx_t ctx) Sets *res* to the zero matrix. .. function:: int gr_mat_one(gr_mat_t res, gr_ctx_t ctx) Sets *res* to the scalar matrix with 1 on the main diagonal and zero elsewhere. .. function:: int gr_mat_set(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_set_fmpz_mat(gr_mat_t res, const fmpz_mat_t mat, gr_ctx_t ctx) int gr_mat_set_fmpq_mat(gr_mat_t res, const fmpq_mat_t mat, gr_ctx_t ctx) Sets *res* to the value of *mat*. .. function:: int gr_mat_set_scalar(gr_mat_t res, gr_srcptr c, gr_ctx_t ctx) int gr_mat_set_ui(gr_mat_t res, ulong c, gr_ctx_t ctx) int gr_mat_set_si(gr_mat_t res, slong c, gr_ctx_t ctx) int gr_mat_set_fmpz(gr_mat_t res, const fmpz_t c, gr_ctx_t ctx) int gr_mat_set_fmpq(gr_mat_t res, const fmpq_t c, gr_ctx_t ctx) Set *res* to the scalar matrix with *c* on the main diagonal and zero elsewhere. Basic row, column and entry operations ------------------------------------------------------------------------------- .. function:: int gr_mat_concat_horizontal(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) .. function:: int gr_mat_concat_vertical(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) .. function:: int gr_mat_transpose(gr_mat_t B, const gr_mat_t A, gr_ctx_t ctx) Sets *B* to the transpose of *A*. .. function:: int gr_mat_swap_rows(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx) Swaps rows ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: int gr_mat_swap_cols(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx) Swaps columns ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: int gr_mat_invert_rows(gr_mat_t mat, slong * perm, gr_ctx_t ctx) Swaps rows ``i`` and ``r - i`` of ``mat`` for ``0 <= i < r/2``, where ``r`` is the number of rows of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: int gr_mat_invert_cols(gr_mat_t mat, slong * perm, gr_ctx_t ctx) Swaps columns ``i`` and ``c - i`` of ``mat`` for ``0 <= i < c/2``, where ``c`` is the number of columns of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: truth_t gr_mat_is_empty(const gr_mat_t mat, gr_ctx_t ctx) Returns whether *mat* is an empty matrix, having either zero rows or zero column. This predicate is always decidable (even if the underlying ring is not computable), returning ``T_TRUE`` or ``T_FALSE``. .. function:: truth_t gr_mat_is_square(const gr_mat_t mat, gr_ctx_t ctx) Returns whether *mat* is a square matrix, having the same number of rows as columns (not the same thing as being a perfect square!). This predicate is always decidable (even if the underlying ring is not computable), returning ``T_TRUE`` or ``T_FALSE``. Arithmetic ------------------------------------------------------------------------------- .. function:: int gr_mat_neg(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) .. function:: int gr_mat_add(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) .. function:: int gr_mat_sub(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) .. function:: int gr_mat_mul_classical(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) int gr_mat_mul_strassen(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) int gr_mat_mul_generic(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) int gr_mat_mul(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) Matrix multiplication. The default function can be overloaded by specific rings; otherwise, it falls back to :func:`gr_mat_mul_generic` which currently only performs classical multiplication. .. function:: int gr_mat_sqr(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) .. function:: int gr_mat_add_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr c, gr_ctx_t ctx) int gr_mat_sub_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr c, gr_ctx_t ctx) int gr_mat_mul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr c, gr_ctx_t ctx) int gr_mat_addmul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr c, gr_ctx_t ctx) int gr_mat_submul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr c, gr_ctx_t ctx) int gr_mat_div_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr c, gr_ctx_t ctx) .. function:: int _gr_mat_gr_poly_evaluate(gr_mat_t res, gr_srcptr poly, slong len, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_gr_poly_evaluate(gr_mat_t res, const gr_poly_t poly, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the matrix obtained by evaluating the scalar polynomial *poly* with matrix argument *mat*. Diagonal and triangular matrices ------------------------------------------------------------------------------- .. function:: truth_t gr_mat_is_upper_triangular(const gr_mat_t mat, gr_ctx_t ctx) truth_t gr_mat_is_lower_triangular(const gr_mat_t mat, gr_ctx_t ctx) Returns whether *mat* is upper (respectively lower) triangular, having zeros everywhere below (respectively above) the main diagonal. The matrix need not be square. .. function:: truth_t gr_mat_is_diagonal(const gr_mat_t mat, gr_ctx_t ctx) Returns whether *mat* is a diagonal matrix, having zeros everywhere except on the main diagonal. The matrix need not be square. .. function:: int gr_mat_mul_diag(gr_mat_t res, const gr_mat_t A, const gr_vec_t D, gr_ctx_t ctx) int gr_mat_diag_mul(gr_mat_t res, const gr_vec_t D, const gr_mat_t A, gr_ctx_t ctx) Set *res* to the product `AD` or `DA` respectively, where `D` is a diagonal matrix represented as a vector of entries. Gaussian elimination ------------------------------------------------------------------------------- .. function:: int gr_mat_find_nonzero_pivot_large_abs(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx) int gr_mat_find_nonzero_pivot_generic(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx) int gr_mat_find_nonzero_pivot(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx) Attempts to find a nonzero element in column number *column* of the matrix *mat* in a row between *start_row* (inclusive) and *end_row* (exclusive). On success, sets ``pivot_row`` to the row index and returns ``GR_SUCCESS``. If no nonzero pivot element exists, returns ``GR_DOMAIN``. If no nonzero pivot element exists and zero-testing fails for some element, returns the flag ``GR_UNABLE``. This function may be destructive: any elements that are nontrivially zero but can be certified zero may be overwritten by exact zeros. .. function:: int gr_mat_lu_classical(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx) int gr_mat_lu_recursive(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, slong cutoff, gr_ctx_t ctx) int gr_mat_lu_generic(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx) int gr_mat_lu(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx) Computes a generalized LU decomposition `A = PLU` of a given matrix *A*, writing the rank of *A* to *rank*. If *A* is a nonsingular square matrix, *LU* will be set to a unit diagonal lower triangular matrix *L* and an upper triangular matrix *U* (the diagonal of *L* will not be stored explicitly). If *A* is an arbitrary matrix of rank *r*, *U* will be in row echelon form having *r* nonzero rows, and *L* will be lower triangular but truncated to *r* columns, having implicit ones on the *r* first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and set the rank to 0 if *A* is detected to be rank-deficient. This currently only works as expected for square matrices. The algorithm can fail if it fails to certify that a pivot element is zero or nonzero, in which case the correct rank cannot be determined. It can also fail if a pivot element is not invertible. In these cases the ``GR_UNABLE`` and/or ``GR_DOMAIN`` flags will be returned. On failure, the data in the output variables ``rank``, ``P`` and ``LU`` will be meaningless. The *classical* version uses iterative Gaussian elimination. The *recursive* version uses a block recursive algorithm to take advantage of fast matrix multiplication. The *cutoff* for switching to the classical algorithm is given as an explicit input. The *generic* version calls the recursive algorithm with a default cutoff. .. function:: int gr_mat_fflu(slong * rank, slong * P, gr_mat_t LU, gr_ptr den, const gr_mat_t A, int rank_check, gr_ctx_t ctx) Similar to :func:`gr_mat_lu`, but computes a fraction-free LU decomposition using the Bareiss algorithm. The denominator is written to *den*. Solving ------------------------------------------------------------------------------- .. function:: int gr_mat_nonsingular_solve_tril_classical(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx) int gr_mat_nonsingular_solve_tril_recursive(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx) int gr_mat_nonsingular_solve_tril(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx) int gr_mat_nonsingular_solve_triu_classical(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx) int gr_mat_nonsingular_solve_triu_recursive(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx) int gr_mat_nonsingular_solve_triu(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx) Solves the lower triangular system `LX = B` or the upper triangular system `UX = B`, respectively. Division by the the diagonal entries must be possible; if not a division fails, ``GR_DOMAIN`` is returned even if the system is solvable. If *unit* is set, the main diagonal of *L* or *U* is taken to consist of all ones, and in that case the actual entries on the diagonal are not read at all and can contain other data. The *classical* versions perform the computations iteratively while the *recursive* versions perform the computations in a block recursive way to benefit from fast matrix multiplication. The default versions choose an algorithm automatically. .. function:: int gr_mat_nonsingular_solve_fflu(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) int gr_mat_nonsingular_solve_lu(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) int gr_mat_nonsingular_solve(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) Solves `AX = B`. If *A* is not invertible, returns ``GR_DOMAIN`` even if the system has a solution. .. function:: int gr_mat_nonsingular_solve_fflu_precomp(gr_mat_t X, const slong * perm, const gr_mat_t LU, const gr_mat_t B, gr_ctx_t ctx) int gr_mat_nonsingular_solve_lu_precomp(gr_mat_t X, const slong * perm, const gr_mat_t LU, const gr_mat_t B, gr_ctx_t ctx) Solves `AX = B` given a precomputed FFLU or LU factorization of *A*. .. function:: int gr_mat_nonsingular_solve_den_fflu(gr_mat_t X, gr_ptr den, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) int gr_mat_nonsingular_solve_den(gr_mat_t X, gr_ptr den, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) Solves `AX = B` over the fraction field of the present ring (assumed to be an integral domain), returning `X` with an implied denominator *den*. If *A* is not invertible over the fraction field, returns ``GR_DOMAIN`` even if the system has a solution. .. function:: int gr_mat_solve_field(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) Solves `AX = B` where *A* is not necessarily square and not necessarily invertible. Assuming that the ring is a field, a return value of ``GR_DOMAIN`` indicates that the system has no solution. If there are multiple solutions, an arbitrary solution is returned. Determinant and trace ------------------------------------------------------------------------------- .. function:: int gr_mat_det_fflu(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_det_berkowitz(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_det_lu(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_det_cofactor(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_det_generic_field(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_det_generic_integral_domain(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_det_generic(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_det(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the determinant of the square matrix *mat*. Various algorithms are available: * The *berkowitz* version uses the division-free Berkowitz algorithm performing `O(n^4)` operations. Since no zero tests are required, it is guaranteed to succeed if the ring arithmetic succeeds. * The *cofactor* version performs cofactor expansion. This is currently only supported for matrices up to size 4, and for larger matrices returns the ``GR_UNABLE`` flag. * The *lu* and *fflu* versions use rational LU decomposition and fraction-free LU decomposition (Bareiss algorithm) respectively, requiring `O(n^3)` operations. These algorithms can fail if zero certification or inversion fails, in which case the ``GR_UNABLE`` flag is returned. * The *generic*, *generic_field* and *generic_integral_domain* versions choose an appropriate algorithm for a generic ring depending on the availability of division. * The *default* method can be overloaded. If the matrix is not square, ``GR_DOMAIN`` is returned. .. function:: int gr_mat_trace(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the trace (sum of entries on the main diagonal) of the square matrix *mat*. If the matrix is not square, ``GR_DOMAIN`` is returned. Rank ------------------------------------------------------------------------------- .. function:: int gr_mat_rank_fflu(slong * rank, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_rank_lu(slong * rank, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_rank(slong * rank, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the rank of *mat*. The default method returns ``GR_DOMAIN`` if the element ring is not an integral domain, in which case the usual rank is not well-defined. The *fflu* and *lu* variants currently do not check the element domain, and simply return this flag if they encounter an impossible inverse in the execution of the respective algorithms. Row echelon form ------------------------------------------------------------------------------- .. function:: int gr_mat_rref_lu(slong * rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_rref_fflu(slong * rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_rref(slong * rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx) Sets *R* to the reduced row echelon form of *A*, also setting *rank* to its rank. .. function:: int gr_mat_rref_den_fflu(slong * rank, gr_mat_t R, gr_ptr den, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_rref_den(slong * rank, gr_mat_t R, gr_ptr den, const gr_mat_t A, gr_ctx_t ctx) Like *rref*, but computes the reduced row echelon multiplied by a common (not necessarily minimal) denominator which is written to *den*. This can be used to compute the rref over an integral domain which is not a field. Nullspace ------------------------------------------------------------------------------- .. function:: int gr_mat_nullspace(gr_mat_t X, const gr_mat_t A, gr_ctx_t ctx) Sets *X* to a basis for the (right) nullspace of *A*. On success, the output matrix will be resized to the correct number of columns. The basis is not guaranteed to be presented in a canonical or minimal form. If the ring is not a field, this is implied to compute a nullspace basis over the fraction field. The result may be meaningless if the ring is not an integral domain. Inverse and adjugate ------------------------------------------------------------------------------- .. function:: int gr_mat_inv(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the inverse of *mat*, computed by solving `A A^{-1} = I`. Returns ``GR_DOMAIN`` if it can be determined that *mat* is not invertible over the present ring (warning: this may not work over non-integral domains). If invertibility cannot be proved, returns ``GR_UNABLE``. To compute the inverse over the fraction field, one may use :func:`gr_mat_nonsingular_solve_den` or :func:`gr_mat_adjugate`. .. function:: int gr_mat_adjugate_charpoly(gr_mat_t adj, gr_ptr det, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_adjugate_cofactor(gr_mat_t adj, gr_ptr det, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_adjugate(gr_mat_t adj, gr_ptr det, const gr_mat_t mat, gr_ctx_t ctx) Sets *adj* to the adjugate matrix of *mat*, simultaneously setting *det* to the determinant of *mat*. We have `\operatorname{adj}(A) A = A \operatorname{adj}(A) = \det(A) I`, and `A^{-1} = \operatorname{adj}(A) / \det(A)` when *A* is invertible. The *cofactor* version uses cofactor expansion, requiring the evaluation of `n^2` determinants. The *charpoly* version computes and then evaluates the characteristic polynomial, requiring `O(n^{1/2})` matrix multiplications plus `O(n^3)` or `O(n^4)` operations for the characteristic polynomial itself depending on the algorithm used. Characteristic polynomial ------------------------------------------------------------------------------- .. function:: int _gr_mat_charpoly(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx) Computes the characteristic polynomial using a default algorithm choice. The underscore method assumes that *res* is a preallocated array of `n + 1` coefficients. .. function:: int _gr_mat_charpoly_berkowitz(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly_berkowitz(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the characteristic polynomial of the square matrix *mat*, computed using the division-free Berkowitz algorithm. The number of operations is `O(n^4)` where *n* is the size of the matrix. .. function:: int _gr_mat_charpoly_danilevsky_inplace(gr_ptr res, gr_mat_t mat, gr_ctx_t ctx) int _gr_mat_charpoly_danilevsky(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly_danilevsky(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx) int _gr_mat_charpoly_gauss(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly_gauss(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx) int _gr_mat_charpoly_householder(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly_householder(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the characteristic polynomial of the square matrix *mat*, computed using the Danilevsky algorithm, Hessenberg reduction using Gaussian elimination, and Hessenberg reduction using Householder reflections. The number of operations of each method is `O(n^3)` where *n* is the size of the matrix. The *inplace* version overwrites the input matrix. These methods require divisions and can therefore fail when the ring is not a field. They also require zero tests. The *householder* version also requires square roots. The flags ``GR_UNABLE`` or ``GR_DOMAIN`` are returned when an impossible division or square root is encountered or when a comparison cannot be performed. .. function:: int _gr_mat_charpoly_faddeev(gr_ptr res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly_faddeev(gr_poly_t res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx) int _gr_mat_charpoly_faddeev_bsgs(gr_ptr res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly_faddeev_bsgs(gr_poly_t res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the characteristic polynomial of the square matrix *mat*, computed using the Faddeev-LeVerrier algorithm. If the optional output argument *adj* is not *NULL*, it is set to the adjugate matrix, which is computed free of charge. The *bsgs* version uses a baby-step giant-step strategy, also known as the Preparata-Sarwate algorithm. This reduces the complexity from `O(n^4)` to `O(n^{3.5})` operations at the cost of requiring `n^{0.5}` temporary matrices to be stored. This method requires divisions by small integers and can therefore fail (returning the ``GR_UNABLE`` or ``GR_DOMAIN`` flags) in finite characteristic or when the underlying ring does not implement a division algorithm. .. function:: int _gr_mat_charpoly_from_hessenberg(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_charpoly_from_hessenberg(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to the characteristic polynomial of the square matrix *mat*, which is assumed to be in Hessenberg form (this is currently not checked). Minimal polynomial ------------------------------------------------------------------------------- .. function:: int gr_mat_minpoly_field(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx) Compute the minimal polynomial of the matrix *mat*. The algorithm assumes that the coefficient ring is a field. Similarity transformations ------------------------------------------------------------------------------- .. function:: int gr_mat_apply_row_similarity(gr_mat_t M, slong r, gr_ptr d, gr_ctx_t ctx) Applies an elementary similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. Eigenvalues ------------------------------------------------------------------------------- .. function:: int gr_mat_eigenvalues(gr_vec_t lambda, gr_vec_t mult, const gr_mat_t mat, int flags, gr_ctx_t ctx) int gr_mat_eigenvalues_other(gr_vec_t lambda, gr_vec_t mult, const gr_mat_t mat, gr_ctx_t mat_ctx, int flags, gr_ctx_t ctx) Finds all eigenvalues of the given matrix in the ring defined by *ctx*, storing the eigenvalues without duplication in *lambda* (a vector with elements of type ``ctx``) and the corresponding multiplicities in *mult* (a vector with elements of type ``fmpz``). The interface is essentially the same as that of :func:`gr_poly_roots`; see its documentation for details. .. function:: int gr_mat_diagonalization_precomp(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, const gr_vec_t eigenvalues, const gr_vec_t mult, gr_ctx_t ctx) int gr_mat_diagonalization_generic(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, int flags, gr_ctx_t ctx) int gr_mat_diagonalization(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, int flags, gr_ctx_t ctx) Computes a diagonalization `LAR = D` given a square matrix `A`, where `D` is a diagonal matrix (returned as a vector) of the eigenvalues repeated according to their multiplicities, `L` is a matrix of left eigenvectors, and `R` is a matrix of right eigenvectors, normalized such that `L = R^{-1}`. This implies that `A = RDL = RDR^{-1}`. Either `L` or `R` (or both) can be set to ``NULL`` to omit computing the respective matrix. If the matrix has entries in a field then a return flag of ``GR_DOMAIN`` indicates that the matrix is non-diagonalizable over this field. The *precomp* version requires as input a precomputed set of eigenvalues with corresponding multiplicities, which can be computed with :func:`gr_mat_eigenvalues`. Jordan decomposition ------------------------------------------------------------------------------- .. function:: int gr_mat_set_jordan_blocks(gr_mat_t mat, const gr_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, gr_ctx_t ctx) int gr_mat_jordan_blocks(gr_vec_t lambda, slong * num_blocks, slong * block_lambda, slong * block_size, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_jordan_transformation(gr_mat_t mat, const gr_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_jordan_form(gr_mat_t J, gr_mat_t P, const gr_mat_t A, gr_ctx_t ctx) Matrix functions ------------------------------------------------------------------------------- .. function:: int gr_mat_exp_jordan(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_exp(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) .. function:: int gr_mat_log_jordan(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) int gr_mat_log(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) Hessenberg form ------------------------------------------------------------------------------- .. function:: truth_t gr_mat_is_hessenberg(const gr_mat_t mat, gr_ctx_t ctx) Returns whether *mat* is in upper Hessenberg form. .. function:: int gr_mat_hessenberg_gauss(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_hessenberg_householder(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) int gr_mat_hessenberg(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) Sets *res* to an upper Hessenberg form of *mat*. The *gauss* version uses Gaussian elimination. The *householder* version uses Householder reflections. These methods require divisions and zero testing and can therefore fail (returning ``GR_UNABLE`` or ``GR_DOMAIN``) when the ring is not a field. The *householder* version additionally requires complex conjugation and the ability to compute square roots. Random matrices ------------------------------------------------------------------------------- .. function:: int gr_mat_randtest(gr_mat_t res, flint_rand_t state, gr_ctx_t ctx) Sets *res* to a random matrix. The distribution is nonuniform. .. function:: int gr_mat_randops(gr_mat_t mat, flint_rand_t state, slong count, gr_ctx_t ctx) Randomises *mat* in-place by performing elementary row or column operations. More precisely, at most *count* random additions or subtractions of distinct rows and columns will be performed. .. function:: int gr_mat_randpermdiag(int * parity, gr_mat_t mat, flint_rand_t state, gr_ptr diag, slong n, gr_ctx_t ctx) Sets mat to a random permutation of the diagonal matrix with *n* leading entries given by the vector ``diag``. Returns ``GR_DOMAIN`` if the main diagonal of ``mat`` does not have room for at least *n* entries. The parity (0 or 1) of the permutation is written to ``parity``. .. function:: int gr_mat_randrank(gr_mat_t mat, flint_rand_t state, slong rank, gr_ctx_t ctx) Sets ``mat`` to a random sparse matrix with the given rank, having exactly as many non-zero elements as the rank. The matrix can be transformed into a dense matrix with unchanged rank by subsequently calling :func:`gr_mat_randops`. This operation only makes sense over integral domains (currently not checked). Special matrices ------------------------------------------------------------------------------- For the following functions, the user supplies an output matrix with the intended number of rows and columns. .. function:: int gr_mat_ones(gr_mat_t res, gr_ctx_t ctx) Sets all entries in *res* to one. .. function:: int gr_mat_pascal(gr_mat_t res, int triangular, gr_ctx_t ctx) Sets *res* to a Pascal matrix, whose entries are binomial coefficients. If *triangular* is 0, constructs a full symmetric matrix with the rows of Pascal's triangle as successive antidiagonals. If *triangular* is 1, constructs the upper triangular matrix with the rows of Pascal's triangle as columns, and if *triangular* is -1, constructs the lower triangular matrix with the rows of Pascal's triangle as rows. .. function:: int gr_mat_stirling(gr_mat_t res, int kind, gr_ctx_t ctx) Sets *res* to a Stirling matrix, whose entries are Stirling numbers. If *kind* is 0, the entries are set to the unsigned Stirling numbers of the first kind. If *kind* is 1, the entries are set to the signed Stirling numbers of the first kind. If *kind* is 2, the entries are set to the Stirling numbers of the second kind. .. function:: int gr_mat_hilbert(gr_mat_t res, gr_ctx_t ctx) Sets *res* to the Hilbert matrix, which has entries `1/(i+j+1)` for `i, j \ge 0`. .. function:: int gr_mat_hadamard(gr_mat_t res, gr_ctx_t ctx) If possible, sets *res* to a Hadamard matrix of the provided size and returns ``GR_SUCCESS``. Returns ``GR_DOMAIN`` if no Hadamard matrix of the given size exists, and ``GR_UNABLE`` if the implementation does not know how to construct a Hadamard matrix of the given size. A Hadamard matrix of size *n* can only exist if *n* is 0, 1, 2, or a multiple of 4. It is not known whether a Hadamard matrix exists for every size that is a multiple of 4. This function uses the Paley construction, which succeeds for all *n* of the form `n = 2^e` or `n = 2^e (q + 1)` where *q* is an odd prime power. Orders *n* for which Hadamard matrices are known to exist but for which this construction fails are 92, 116, 156, ... (OEIS A046116). Helper functions for reduction ------------------------------------------------------------------------------- .. function:: int gr_mat_reduce_row(slong * column, gr_mat_t A, slong * P, slong * L, slong m, gr_ctx_t ctx) Reduce row n of the matrix `A`, assuming the prior rows are in Gauss form. However those rows may not be in order. The entry `i` of the array `P` is the row of `A` which has a pivot in the `i`-th column. If no such row exists, the entry of `P` will be `-1`. The function sets *column* to the column in which the `n`-th row has a pivot after reduction. This will always be chosen to be the first available column for a pivot from the left. This information is also updated in `P`. Entry `i` of the array `L` contains the number of possibly nonzero columns of `A` row `i`. This speeds up reduction in the case that `A` is chambered on the right. Otherwise the entries of `L` can all be set to the number of columns of `A`. We require the entries of `L` to be monotonic increasing. .. raw:: latex \newpage flint-3.1.3/doc/source/gr_mpoly.rst000066400000000000000000000225711461254215100172710ustar00rootroot00000000000000.. _gr-mpoly: **gr_mpoly.h** -- sparse multivariate polynomials over generic rings =============================================================================== A :type:`gr_mpoly_t` represents a multivariate polynomial `f \in R[X_1,\ldots,X_n]` implemented as an array of coefficients in a generic ring *R* together with an array of packed exponents. Weak normalization ------------------------------------------------------------------------------- A :type:`gr_mpoly_t` is always normalised by removing zero coefficients. For rings without decidable equality (e.g. rings with inexact representation), only coefficients that are provably zero will be removed, and there can thus be spurious zeros in the internal representation. Methods that depend on knowing the exact structure of a polynomial will act appropriately, typically by returning ``GR_UNABLE`` when it is unknown whether any stored coefficients are nonzero. Types, macros and constants ------------------------------------------------------------------------------- .. type:: gr_mpoly_struct .. type:: gr_mpoly_t A ``gr_mpoly_t`` is defined as an array of length one of type ``gr_mpoly_struct``, permitting a ``gr_mpoly_t`` to be passed by reference. Memory management ------------------------------------------------------------------------------- .. function:: void gr_mpoly_init(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) Initializes and sets *A* to the zero polynomial. .. function:: void gr_mpoly_init3(gr_mpoly_t A, slong alloc, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) void gr_mpoly_init2(gr_mpoly_t A, slong alloc, const mpoly_ctx_t mctx, gr_ctx_t cctx) Initializes *A* with space allocated for the given number of coefficients and exponents with the given number of bits. .. function:: void gr_mpoly_clear(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) Clears *A*, freeing all allocated data. Basic manipulation ------------------------------------------------------------------------------- .. function:: void gr_mpoly_swap(gr_mpoly_t A, gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) Swaps *A* and *B* efficiently. .. function:: int gr_mpoly_set(gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to *B*. .. function:: int gr_mpoly_zero(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to the zero polynomial. .. function:: truth_t gr_mpoly_is_zero(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) Returns whether *A* is the zero polynomial. .. function:: int gr_mpoly_gen(gr_mpoly_t A, slong var, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to the generator with index *var* (indexed from zero). .. function:: truth_t gr_mpoly_is_gen(const gr_mpoly_t A, slong var, const mpoly_ctx_t mctx, gr_ctx_t cctx) Returns whether *A* is the generator with index *var* (indexed from zero). Comparisons ------------------------------------------------------------------------------- .. function:: truth_t gr_mpoly_equal(const gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) Returns whether *A* and *B* are equal. Random generation ------------------------------------------------------------------------------- .. function:: int gr_mpoly_randtest_bits(gr_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to a random polynomial with up to *length* terms and up to *exp_bits* bits in the exponents. Input and output ------------------------------------------------------------------------------- .. function:: int gr_mpoly_write_pretty(gr_stream_t out, const gr_mpoly_t A, const char ** x, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_print_pretty(const gr_mpoly_t A, const char ** x, const mpoly_ctx_t mctx, gr_ctx_t cctx) Prints *A* using the strings in *x* for the variables. If *x* is *NULL*, defaults are used. Coefficient and exponent access ------------------------------------------------------------------------------- .. function:: int gr_mpoly_get_coeff_scalar_fmpz(gr_ptr c, const gr_mpoly_t A, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_get_coeff_scalar_ui(gr_ptr c, const gr_mpoly_t A, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *c* to the coefficient in *A* with exponents *exp*. .. function:: int gr_mpoly_set_coeff_scalar_fmpz(gr_mpoly_t A, gr_srcptr c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_ui_fmpz(gr_mpoly_t A, ulong c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_si_fmpz(gr_mpoly_t A, slong c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_fmpz_fmpz(gr_mpoly_t A, const fmpz_t c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_fmpq_fmpz(gr_mpoly_t A, const fmpq_t c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: int gr_mpoly_set_coeff_scalar_ui(gr_mpoly_t poly, gr_srcptr c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_ui_ui(gr_mpoly_t A, ulong c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_si_ui(gr_mpoly_t A, slong c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_fmpz_ui(gr_mpoly_t A, const fmpz_t c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_set_coeff_fmpq_ui(gr_mpoly_t A, const fmpq_t c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets the coefficient with exponents *exp* in *A* to the scalar *c* which must be an element of or coercible to the coefficient ring. Arithmetic ------------------------------------------------------------------------------- .. function:: int gr_mpoly_neg(gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to the negation of *B*. .. function:: int gr_mpoly_add(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to the difference of *B* and *C*. .. function:: int gr_mpoly_sub(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to the difference of *B* and *C*. .. function:: int gr_mpoly_mul(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_mul_johnson(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_mul_monomial(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to the product of *B* and *C*. The *monomial* version assumes that *C* is a monomial. .. function:: int gr_mpoly_mul_scalar(gr_mpoly_t A, const gr_mpoly_t B, gr_srcptr c, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_mul_si(gr_mpoly_t A, const gr_mpoly_t B, slong c, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_mul_ui(gr_mpoly_t A, const gr_mpoly_t B, ulong c, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_mul_fmpz(gr_mpoly_t A, const gr_mpoly_t B, const fmpz_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx) int gr_mpoly_mul_fmpq(gr_mpoly_t A, const gr_mpoly_t B, const fmpq_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx) Sets *A* to *B* multiplied by the scalar *c* which must be an element of or coercible to the coefficient ring. Container operations ------------------------------------------------------------------------------- Mostly intended for internal use. .. function:: void _gr_mpoly_fit_length(gr_ptr * coeffs, slong * coeffs_alloc, ulong ** exps, slong * exps_alloc, slong N, slong length, gr_ctx_t cctx) .. function:: void gr_mpoly_fit_length(gr_mpoly_t A, slong len, const mpoly_ctx_t mctx, gr_ctx_t cctx) Ensures that *A* has space for *len* coefficients and exponents. .. function:: void gr_mpoly_fit_bits(gr_mpoly_t A, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: void gr_mpoly_fit_length_fit_bits(gr_mpoly_t A, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: void gr_mpoly_fit_length_reset_bits(gr_mpoly_t A, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: void _gr_mpoly_set_length(gr_mpoly_t A, slong newlen, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: void _gr_mpoly_push_exp_ui(gr_mpoly_t A, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: int gr_mpoly_push_term_scalar_ui(gr_mpoly_t A, gr_srcptr c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: void _gr_mpoly_push_exp_fmpz(gr_mpoly_t A, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: int gr_mpoly_push_term_scalar_fmpz(gr_mpoly_t A, gr_srcptr c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: void gr_mpoly_sort_terms(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: int gr_mpoly_combine_like_terms(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: truth_t gr_mpoly_is_canonical(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. function:: void gr_mpoly_assert_canonical(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) .. raw:: latex \newpage flint-3.1.3/doc/source/gr_poly.rst000066400000000000000000001276611461254215100171220ustar00rootroot00000000000000.. _gr-poly: **gr_poly.h** -- dense univariate polynomials over generic rings =============================================================================== A :type:`gr_poly_t` represents a univariate polynomial `f \in R[X]` implemented as a dense array of coefficients in a generic ring *R*. In this module, the context object ``ctx`` always represents the coefficient ring *R* unless otherwise stated. Creating a context object representing the polynomial ring `R[X]` only becomes necessary when one wants to manipulate polynomials using generic ring methods like ``gr_add`` instead of the designated polynomial methods like ``gr_poly_add``. Most functions are provided in two versions: an underscore method which operates directly on pre-allocated arrays of coefficients and generally has some restrictions (often requiring the lengths to be nonzero and not supporting aliasing of the input and output arrays), and a non-underscore method which performs automatic memory management and handles degenerate cases. Type compatibility ------------------------------------------------------------------------------- The ``gr_poly`` type has the same data layout as the following polynomial types: ``fmpz_poly``, ``fq_poly``, ``fq_nmod_poly``, ``fq_zech_poly``, ``arb_poly``, ``acb_poly``, ``ca_poly``. Methods in this module can therefore be mixed freely with methods in the corresponding FLINT modules when the underlying coefficient type is the same. It is not directly compatible with the following types: ``fmpq_poly`` (coefficients are stored with a common denominator), ``nmod_poly`` (modulus data is stored as part of the polynomial object). Weak normalization ------------------------------------------------------------------------------- A :type:`gr_poly_t` is always normalised by removing leading zeros. For rings without decidable equality (e.g. rings with inexact representation), only coefficients that are provably zero will be removed, and there can thus be spurious leading zeros in the internal representation. Methods that depend on knowing the exact degree of a polynomial will act appropriately, typically by returning ``GR_UNABLE`` when it is unknown whether the leading stored coefficient is nonzero. Types, macros and constants ------------------------------------------------------------------------------- .. type:: gr_poly_struct .. type:: gr_poly_t Contains a pointer to an array of coefficients (``coeffs``), the used length (``length``), and the allocated size of the array (``alloc``). A ``gr_poly_t`` is defined as an array of length one of type ``gr_poly_struct``, permitting a ``gr_poly_t`` to be passed by reference. Memory management ------------------------------------------------------------------------------- .. function:: void gr_poly_init(gr_poly_t poly, gr_ctx_t ctx) .. function:: void gr_poly_init2(gr_poly_t poly, slong len, gr_ctx_t ctx) .. function:: void gr_poly_clear(gr_poly_t poly, gr_ctx_t ctx) .. function:: gr_ptr gr_poly_entry_ptr(gr_poly_t poly, slong i, gr_ctx_t ctx) gr_srcptr gr_poly_entry_srcptr(const gr_poly_t poly, slong i, gr_ctx_t ctx) .. function:: slong gr_poly_length(const gr_poly_t poly, gr_ctx_t ctx) .. function:: void gr_poly_swap(gr_poly_t poly1, gr_poly_t poly2, gr_ctx_t ctx) .. function:: void gr_poly_fit_length(gr_poly_t poly, slong len, gr_ctx_t ctx) .. function:: void _gr_poly_set_length(gr_poly_t poly, slong len, gr_ctx_t ctx) Basic manipulation ------------------------------------------------------------------------------- .. function:: void _gr_poly_normalise(gr_poly_t poly, gr_ctx_t ctx) .. function:: int gr_poly_set(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx) int gr_poly_get_fmpz_poly(gr_poly_t res, const fmpz_poly_t src, gr_ctx_t ctx) int gr_poly_set_fmpq_poly(gr_poly_t res, const fmpq_poly_t src, gr_ctx_t ctx) int gr_poly_set_gr_poly_other(gr_poly_t res, const gr_poly_t x, gr_ctx_t x_ctx, gr_ctx_t ctx) .. function:: int _gr_poly_reverse(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx) int gr_poly_reverse(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx) .. function:: int gr_poly_truncate(gr_poly_t res, const gr_poly_t poly, slong newlen, gr_ctx_t ctx) .. function:: int gr_poly_zero(gr_poly_t poly, gr_ctx_t ctx) int gr_poly_one(gr_poly_t poly, gr_ctx_t ctx) int gr_poly_neg_one(gr_poly_t poly, gr_ctx_t ctx) int gr_poly_gen(gr_poly_t poly, gr_ctx_t ctx) .. function:: int gr_poly_write(gr_stream_t out, const gr_poly_t poly, const char * x, gr_ctx_t ctx) int gr_poly_print(const gr_poly_t poly, gr_ctx_t ctx) .. function:: int gr_poly_randtest(gr_poly_t poly, flint_rand_t state, slong len, gr_ctx_t ctx) .. function:: truth_t _gr_poly_equal(gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) truth_t gr_poly_equal(const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) .. function:: truth_t gr_poly_is_zero(const gr_poly_t poly, gr_ctx_t ctx) truth_t gr_poly_is_one(const gr_poly_t poly, gr_ctx_t ctx) truth_t gr_poly_is_gen(const gr_poly_t poly, gr_ctx_t ctx) truth_t gr_poly_is_scalar(const gr_poly_t poly, gr_ctx_t ctx) .. function:: int gr_poly_set_scalar(gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) int gr_poly_set_si(gr_poly_t poly, slong c, gr_ctx_t ctx) int gr_poly_set_ui(gr_poly_t poly, ulong c, gr_ctx_t ctx) int gr_poly_set_fmpz(gr_poly_t poly, const fmpz_t c, gr_ctx_t ctx) int gr_poly_set_fmpq(gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx) .. function:: int gr_poly_set_coeff_scalar(gr_poly_t poly, slong n, gr_srcptr c, gr_ctx_t ctx) int gr_poly_set_coeff_si(gr_poly_t poly, slong n, slong c, gr_ctx_t ctx) int gr_poly_set_coeff_ui(gr_poly_t poly, slong n, ulong c, gr_ctx_t ctx) int gr_poly_set_coeff_fmpz(gr_poly_t poly, slong n, const fmpz_t c, gr_ctx_t ctx) int gr_poly_set_coeff_fmpq(gr_poly_t poly, slong n, const fmpq_t c, gr_ctx_t ctx) .. function:: int gr_poly_get_coeff_scalar(gr_ptr res, const gr_poly_t poly, slong n, gr_ctx_t ctx) Arithmetic ------------------------------------------------------------------------------- .. function:: int gr_poly_neg(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx) .. function:: int _gr_poly_add(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_add(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) .. function:: int _gr_poly_sub(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_sub(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) .. function:: int _gr_poly_mul(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_mul(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) .. function:: int _gr_poly_mullow_generic(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong len, gr_ctx_t ctx) int _gr_poly_mullow(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong len, gr_ctx_t ctx) int gr_poly_mullow(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong len, gr_ctx_t ctx) .. function:: int gr_poly_mul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) Powering -------------------------------------------------------------------------------- .. function:: int _gr_poly_pow_series_ui_binexp(gr_ptr res, gr_srcptr f, slong flen, ulong exp, slong len, gr_ctx_t ctx) int gr_poly_pow_series_ui_binexp(gr_poly_t res, const gr_poly_t poly, ulong exp, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_pow_series_ui(gr_ptr res, gr_srcptr f, slong flen, ulong exp, slong len, gr_ctx_t ctx) int gr_poly_pow_series_ui(gr_poly_t res, const gr_poly_t poly, ulong exp, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_pow_ui_binexp(gr_ptr res, gr_srcptr f, slong flen, ulong exp, gr_ctx_t ctx) int gr_poly_pow_ui_binexp(gr_poly_t res, const gr_poly_t poly, ulong exp, gr_ctx_t ctx) .. function:: int _gr_poly_pow_ui(gr_ptr res, gr_srcptr f, slong flen, ulong exp, gr_ctx_t ctx) int gr_poly_pow_ui(gr_poly_t res, const gr_poly_t poly, ulong exp, gr_ctx_t ctx) .. function:: int gr_poly_pow_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t exp, gr_ctx_t ctx) .. function:: int _gr_poly_pow_series_fmpq_recurrence(gr_ptr h, gr_srcptr f, slong flen, const fmpq_t exp, slong len, int precomp, gr_ctx_t ctx) int gr_poly_pow_series_fmpq_recurrence(gr_poly_t res, const gr_poly_t poly, const fmpq_t exp, slong len, gr_ctx_t ctx) Shifting ------------------------------------------------------------------------------- .. function:: int _gr_poly_shift_left(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx) int gr_poly_shift_left(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx) .. function:: int _gr_poly_shift_right(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx) int gr_poly_shift_right(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx) Scalar division -------------------------------------------------------------------------------- .. function:: int gr_poly_div_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) Division with remainder -------------------------------------------------------------------------------- .. function:: int _gr_poly_divrem_divconquer_preinv1(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) int _gr_poly_divrem_divconquer_noinv(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) int _gr_poly_divrem_divconquer(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) int gr_poly_divrem_divconquer(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, slong cutoff, gr_ctx_t ctx) int _gr_poly_divrem_basecase_preinv1(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, gr_ctx_t ctx) int _gr_poly_divrem_basecase_noinv(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int _gr_poly_divrem_basecase(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_divrem_basecase(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) int _gr_poly_divrem_newton(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_divrem_newton(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) int _gr_poly_divrem(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_divrem(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) These functions implement Euclidean division with remainder: given polynomials `A, B \in K[x]` where `K` is a field, with `B \ne 0`, there is a unique quotient `Q` and remainder `R` such that `A = BQ + R` and either `R = 0` or `\deg(R) < \deg(B)`. If *B* is provably zero, ``GR_DOMAIN`` is returned. When `K` is a commutative ring and `\operatorname{lc}(B)` is a unit in `K`, the situation is the same as over fields. In particular, Euclidean division with remainder always makes sense over commutative rings when `B` is monic. If `\operatorname{lc}(B)` is not a unit, the division still makes sense if the coefficient quotient `\operatorname{lc}(r)` / `\operatorname{lc}(B)` exists for each partial remainder `r`. Indeed, the *basecase* and *divconquer* algorithms return ``GR_DOMAIN`` precisely when encountering a leading quotient `\operatorname{lc}(r)` / `\operatorname{lc}(B) \not \in K`. However, the *newton* algorithm as currently implemented returns ``GR_DOMAIN`` when `\operatorname{lc}(B)^{-1} \not \in K`. The underscore methods make the following assumptions: * *Q* has room for ``lenA - lenB + 1`` coefficients. * *R* has room for ``lenB - 1`` coefficients. * ``lenA >= lenB >= 1``. * *Q* is not aliased with either *A* or *B*. * *R* is not aliased with *B*. * *R* may be aliased with *A*, in which case all ``lenA`` entries may be used as scratch space. Note that in this case, only the low ``lenB - 1`` coefficients of *R* actually represent valid coefficients on output: the higher scratch coefficients will not necessarily be zeroed. * The divisor *B* is normalized to have nonzero leading coefficient. (The non-underscore methods check for leading coefficients that are not provably nonzero and return ``GR_UNABLE``.) The *preinv1* functions take a precomputed inverse of the leading coefficient as input. The *noinv* versions perform repeated checked divisions by the leading coefficient. .. function:: int _gr_poly_div_divconquer_preinv1(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) int _gr_poly_div_divconquer_noinv(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) int _gr_poly_div_divconquer(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) int gr_poly_div_divconquer(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong cutoff, gr_ctx_t ctx) int _gr_poly_div_basecase_preinv1(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, gr_ctx_t ctx) int _gr_poly_div_basecase_noinv(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int _gr_poly_div_basecase(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_div_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) int _gr_poly_div_newton(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_div_newton(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) int _gr_poly_div(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_div(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) Versions of the *divrem* functions which output only the quotient. These are generally faster. .. function:: int _gr_poly_rem(gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_rem(gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) Versions of the *divrem* functions which output only the remainder. Power series division -------------------------------------------------------------------------------- For divide-and-conquer (including Newton-like) algorithms, *cutoff* has the following meaning: we use the basecase algorithm for lengths `n < \operatorname{cutoff}` and the divide-and-conquer algorithm for `n \ge \operatorname{cutoff}`. Using `\operatorname{cutoff} = n` thus results in exactly one divide-and-conquer step with a basecase length of `\lceil n / 2 \rceil`. One should **avoid** calling the Newton methods with `n < \operatorname{cutoff}` as this may result in much worse performance if those methods do not have a specific escape check for that case. The *newton* versions uses Newton iteration, switching to a basecase algorithm when the length is smaller than the specified *cutoff*. Division uses the Karp-Markstein algorithm. .. function:: int _gr_poly_inv_series_newton(gr_ptr res, gr_srcptr A, slong Alen, slong len, slong cutoff, gr_ctx_t ctx) int gr_poly_inv_series_newton(gr_poly_t res, const gr_poly_t A, slong len, slong cutoff, gr_ctx_t ctx) int _gr_poly_inv_series_basecase_preinv1(gr_ptr res, gr_srcptr A, slong Alen, gr_srcptr Ainv, slong len, gr_ctx_t ctx) int _gr_poly_inv_series_basecase(gr_ptr res, gr_srcptr A, slong Alen, slong len, gr_ctx_t ctx) int gr_poly_inv_series_basecase(gr_poly_t res, const gr_poly_t A, slong len, gr_ctx_t ctx) int _gr_poly_inv_series(gr_ptr res, gr_srcptr A, slong Alen, slong len, gr_ctx_t ctx) int gr_poly_inv_series(gr_poly_t res, const gr_poly_t A, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_div_series_newton(gr_ptr res, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, slong cutoff, gr_ctx_t ctx) int gr_poly_div_series_newton(gr_poly_t res, const gr_poly_t A, const gr_poly_t B, slong len, slong cutoff, gr_ctx_t ctx) int _gr_poly_div_series_divconquer(gr_ptr res, gr_srcptr B, slong Blen, gr_srcptr A, slong Alen, slong len, slong cutoff, gr_ctx_t ctx) int gr_poly_div_series_divconquer(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, slong cutoff, gr_ctx_t ctx) int _gr_poly_div_series_invmul(gr_ptr res, gr_srcptr B, slong Blen, gr_srcptr A, slong Alen, slong len, gr_ctx_t ctx) int gr_poly_div_series_invmul(gr_poly_t res, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) int _gr_poly_div_series_basecase_preinv1(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_srcptr Binv, slong len, gr_ctx_t ctx) int _gr_poly_div_series_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) int _gr_poly_div_series_basecase(gr_ptr res, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) int gr_poly_div_series_basecase(gr_poly_t res, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) int _gr_poly_div_series(gr_ptr res, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) int gr_poly_div_series(gr_poly_t res, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) Exact division -------------------------------------------------------------------------------- These functions compute a quotient `Q = A / B` which is known to be exact (without remainder) in `R[x]` (or in `R[[x]] / x^n` in the case of series division). Given a nonexact division, they are allowed to set `Q` to an arbitrary polynomial and return ``GR_SUCCESS`` instead of returning an error flag. `R` is assumed to be an integral domain (this is not checked). For exact division, we have the choice of starting the division from the most significant terms (classical division) or the least significant (power series division). Which direction is more efficient depends in part on whether the leading or trailing coefficient of `B` is cheaper to use for divisions. In a generic setting, this is hard to predict. The *bidirectional* algorithms combine two half-divisions from both ends. This halves the number of operations in the basecase regime, though an extra coefficient inversion may be needed. The ``noinv`` versions perform repeated ``divexact`` operations in the scalar domain without attempting to invert the leading (or trailing) coefficient, while other versions check invertibility first. There are no ``divexact_preinv1`` versions because those are identical to the ``div_preinv1`` counterparts. .. function:: int _gr_poly_divexact_basecase_bidirectional(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) int gr_poly_divexact_basecase_bidirectional(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) int _gr_poly_divexact_bidirectional(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) int gr_poly_divexact_bidirectional(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) int _gr_poly_divexact_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) int _gr_poly_divexact_basecase(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) int gr_poly_divexact_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) .. function:: int _gr_poly_divexact_series_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) int _gr_poly_divexact_series_basecase(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) int gr_poly_divexact_series_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) Square roots -------------------------------------------------------------------------------- .. function:: int _gr_poly_sqrt_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong len, slong cutoff, gr_ctx_t ctx) int gr_poly_sqrt_series_newton(gr_poly_t res, const gr_poly_t f, slong len, slong cutoff, gr_ctx_t ctx) int _gr_poly_sqrt_series_basecase(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_sqrt_series_basecase(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_sqrt_series_miller(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_sqrt_series_miller(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_sqrt_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_sqrt_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_rsqrt_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong len, slong cutoff, gr_ctx_t ctx) int gr_poly_rsqrt_series_newton(gr_poly_t res, const gr_poly_t f, slong len, slong cutoff, gr_ctx_t ctx) int _gr_poly_rsqrt_series_basecase(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_rsqrt_series_basecase(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_rsqrt_series_miller(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_rsqrt_series_miller(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_rsqrt_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_rsqrt_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) Evaluation ------------------------------------------------------------------------------- .. function:: int _gr_poly_evaluate_rectangular(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx) int gr_poly_evaluate_rectangular(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx) .. function:: int _gr_poly_evaluate_modular(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx) int gr_poly_evaluate_modular(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx) .. function:: int _gr_poly_evaluate_horner(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx) int gr_poly_evaluate_horner(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx) .. function:: int _gr_poly_evaluate(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx) int gr_poly_evaluate(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx) Set *res* to *poly* evaluated at *x*. .. function:: int _gr_poly_evaluate_other_horner(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) int gr_poly_evaluate_other_horner(gr_ptr res, const gr_poly_t f, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) int _gr_poly_evaluate_other_rectangular(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) int gr_poly_evaluate_other_rectangular(gr_ptr res, const gr_poly_t f, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) int _gr_poly_evaluate_other(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) int gr_poly_evaluate_other(gr_ptr res, const gr_poly_t f, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) Set *res* to *poly* evaluated at *x*, where the coefficients of *f* belong to *ctx* while both *x* and *res* belong to *x_ctx*. Multipoint evaluation and interpolation ------------------------------------------------------------------------------- .. function:: gr_ptr * _gr_poly_tree_alloc(slong len, gr_ctx_t ctx) .. function:: void _gr_poly_tree_free(gr_ptr * tree, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_tree_build(gr_ptr * tree, gr_srcptr roots, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_evaluate_vec_fast_precomp(gr_ptr vs, gr_srcptr poly, slong plen, gr_ptr * tree, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_evaluate_vec_fast(gr_ptr ys, gr_srcptr poly, slong plen, gr_srcptr xs, slong n, gr_ctx_t ctx) .. function:: int gr_poly_evaluate_vec_fast(gr_vec_t ys, const gr_poly_t poly, const gr_vec_t xs, gr_ctx_t ctx) .. function:: int _gr_poly_evaluate_vec_iter(gr_ptr ys, gr_srcptr poly, slong plen, gr_srcptr xs, slong n, gr_ctx_t ctx) .. function:: int gr_poly_evaluate_vec_iter(gr_vec_t ys, const gr_poly_t poly, const gr_vec_t xs, gr_ctx_t ctx) Composition ------------------------------------------------------------------------------- .. function:: int _gr_poly_taylor_shift_horner(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_poly_taylor_shift_horner(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) int _gr_poly_taylor_shift_divconquer(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_poly_taylor_shift_divconquer(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) int _gr_poly_taylor_shift_convolution(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_poly_taylor_shift_convolution(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) int _gr_poly_taylor_shift(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) int gr_poly_taylor_shift(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) Sets *res* to the Taylor shift `f(x+c)`, where *f* is given by *poly*, computed respectively using an optimized form of Horner's rule, divide-and-conquer, a single convolution, and an automatic choice between the three algorithms. The underscore methods support aliasing. .. function:: int _gr_poly_compose_horner(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_compose_horner(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) int _gr_poly_compose_divconquer(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_compose_divconquer(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) int _gr_poly_compose(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_compose(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) Sets *res* to the composition `f(g(x))` where *f* is given by *poly1* and *g* is given by *poly2*, respectively using Horner's rule, divide-and-conquer, and an automatic choice between the two algorithms. The default algorithm also handles special-form input `g = ax^n + c` efficiently by performing a Taylor shift followed by a rescaling. The underscore methods do not support aliasing of the output with either input polynomial. Power series composition and reversion ------------------------------------------------------------------------------- .. function:: int _gr_poly_compose_series_horner(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) int gr_poly_compose_series_horner(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) int _gr_poly_compose_series_brent_kung(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) int gr_poly_compose_series_brent_kung(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) int _gr_poly_compose_series_divconquer(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) int gr_poly_compose_series_divconquer(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) int _gr_poly_compose_series(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) int gr_poly_compose_series(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) Sets *res* to the power series composition `h(x) = f(g(x))` truncated to order `O(x^n)` where `f` is given by *poly1* and `g` is given by *poly2*, respectively using Horner's rule, the Brent-Kung baby step-giant step algorithm [BrentKung1978]_, divide-and-conquer, and an automatic choice between the algorithms. The default algorithm also handles short input and special-form input `g = ax^n` efficiently. We require that the constant term in `g(x)` is exactly zero. The underscore methods do not support aliasing of the output with either input polynomial, and do not zero-pad the result. .. function:: int _gr_poly_revert_series_lagrange(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) int gr_poly_revert_series_lagrange(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) int _gr_poly_revert_series_lagrange_fast(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) int gr_poly_revert_series_lagrange_fast(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) int _gr_poly_revert_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) int gr_poly_revert_series_newton(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) int _gr_poly_revert_series(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) int gr_poly_revert_series(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) Sets *res* to the power series reversion `f^{-1}(x)` which satisfies `f^{-1}(f(x)) = f(f^{-1}(x)) = x` mod `x^n`. For the series reversion to exist, we require that the constant term in `f` is zero and that the linear coefficient is invertible. The flag ``GR_DOMAIN`` is returned otherwise. The *lagrange* and *lagrange_fast* algorithms require the ability to divide by `2, 3, \ldots, n-1` and will return the ``GR_UNABLE`` flag in too small characteristic. The underscore methods do not support aliasing of the output with the input. The Newton method is described in [BrentKung1978]_; the *lagrange* algorithm implements the Lagrange inversion formula, while the *lagrange_fast* algorithm implements the baby-step giant-step algorithm described in [Joh2015b]_. Derivative and integral ------------------------------------------------------------------------------- .. function:: int _gr_poly_derivative(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx) int gr_poly_derivative(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) .. function:: int _gr_poly_nth_derivative(gr_ptr res, gr_srcptr poly, ulong n, slong len, gr_ctx_t ctx) int gr_poly_nth_derivative(gr_poly_t res, const gr_poly_t poly, ulong n, gr_ctx_t ctx) .. function:: int _gr_poly_integral(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx) int gr_poly_integral(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) Monic polynomials ------------------------------------------------------------------------------- .. function:: int _gr_poly_make_monic(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx) int gr_poly_make_monic(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx) .. function:: truth_t _gr_poly_is_monic(gr_srcptr poly, slong len, gr_ctx_t ctx) truth_t gr_poly_is_monic(const gr_poly_t res, gr_ctx_t ctx) GCD ------------------------------------------------------------------------------- .. function:: int _gr_poly_hgcd(gr_ptr r, slong * sgn, gr_ptr * M, slong * lenM, gr_ptr A, slong * lenA, gr_ptr B, slong * lenB, gr_srcptr a, slong lena, gr_srcptr b, slong lenb, slong cutoff, gr_ctx_t ctx) Computes the HGCD of `a` and `b`, that is, a matrix `M`, a sign `\sigma` and two polynomials `A` and `B` such that .. math:: (A,B)^t = \sigma M^{-1} (a,b)^t. Assumes that `\operatorname{len}(a) > \operatorname{len}(b) > 0`. Assumes that `A` and `B` have space of size at least `\operatorname{len}(a)` and `\operatorname{len}(b)`, respectively. On exit, ``*lenA`` and ``*lenB`` will contain the correct lengths of `A` and `B`. Assumes that ``M[0]``, ``M[1]``, ``M[2]``, and ``M[3]`` each point to a vector of size at least `\operatorname{len}(a)`. If `r` is not ``NULL``, writes to that variable the corresponding value for computing resultants using the HGCD algorithm. .. function:: int _gr_poly_gcd_hgcd(gr_ptr G, slong * _lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) int gr_poly_gcd_hgcd(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) int _gr_poly_gcd_euclidean(gr_ptr G, slong * lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_gcd_euclidean(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) int _gr_poly_gcd(gr_ptr G, slong * lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_gcd(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) Polynomial GCD. Currently only useful over fields. The underscore methods assume ``lenA >= lenB >= 1`` and that both *A* and *B* have nonzero leading coefficient. The underscore methods do not attempt to make the result monic. The time complexity of the half-GCD algorithm is `\mathcal{O}(n \log^2 n)` ring operations. For further details, see [ThullYap1990]_. .. function:: int _gr_poly_xgcd_euclidean(slong * lenG, gr_ptr G, gr_ptr S, gr_ptr T, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) int gr_poly_xgcd_euclidean(gr_poly_t G, gr_poly_t S, gr_poly_t T, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) .. function:: int _gr_poly_xgcd_hgcd(slong * Glen, gr_ptr G, gr_ptr S, gr_ptr T, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong hgcd_cutoff, slong cutoff, gr_ctx_t ctx) int gr_poly_xgcd_hgcd(gr_poly_t G, gr_poly_t S, gr_poly_t T, const gr_poly_t A, const gr_poly_t B, slong hgcd_cutoff, slong cutoff, gr_ctx_t ctx) Resultant ------------------------------------------------------------------------------- For two non-zero polynomials `f(x) = a_m x^m + \dotsb + a_0` and `g(x) = b_n x^n + \dotsb + b_0` of degrees `m` and `n`, the resultant is defined to be .. math:: a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y). For convenience, we define the resultant to be equal to zero if either of the two polynomials is zero. .. function:: int _gr_poly_resultant_euclidean(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_resultant_euclidean(gr_ptr res, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) int _gr_poly_resultant_hgcd(gr_ptr res, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) int gr_poly_resultant_hgcd(gr_ptr res, const gr_poly_t f, const gr_poly_t g, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) int _gr_poly_resultant_sylvester(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_resultant_sylvester(gr_ptr res, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) int _gr_poly_resultant_small(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_resultant_small(gr_ptr res, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) int _gr_poly_resultant(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) int gr_poly_resultant(gr_ptr res, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) Sets *res* to the resultant of *poly1* and *poly2*. The underscore methods assume that `len1 \ge len2 \ge 1` and that the leading coefficients are nonzero. The *euclidean* algorithm is the ordinary Euclidean algorithm. The *hgcd* version uses the quasilinear half-GCD algorithm. It requires two extra tuning parameters ``inner_cutoff`` (recursion threshold passed forward to the HGCD algorithm) and ``cutoff``. Both algorithms can fail when run over non-fields; they will return ``GR_DOMAIN`` when encountering an impossible inverse. The *small* version uses division-free straight-line programs optimized for short polynomials. It returns ``GR_UNABLE`` if the polynomials are too large. Currently this function handles the cases where `len1 \le 2` or `len2 \le 3`. The *sylvester* version constructs the Sylvester matrix and computes its determinant. This is useful over inexact rings and as a fallback for rings without division. The default version attempts to choose an appropriate algorithm automatically. Currently no algorithm has been implemented that is appropriate for integral domains. Squarefree factorization ------------------------------------------------------------------------------- TODO: currently only fields of characteristic 0 are supported. .. function:: int gr_poly_factor_squarefree(gr_ptr c, gr_vec_t fac, gr_vec_t exp, const gr_poly_t poly, gr_ctx_t ctx) Computes a squarefree factorization of *poly*. The constant *c* is set to an element of the scalar ring. The factors in *fac* are set to polynomials; the user must thus initialize it to a vector of polynomials of the same type as *poly* (and *not* to the parent *ctx*). The exponent vector *exp* must be initialized to the *fmpz* type. .. function:: int gr_poly_squarefree_part(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) Sets *res* to the squarefreepart of *poly*. Roots ------------------------------------------------------------------------------- .. function:: int gr_poly_roots(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx) int gr_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t poly_ctx, int flags, gr_ctx_t ctx) Finds all roots of the given polynomial in the ring defined by *ctx*, storing the roots without duplication in *roots* (a vector with elements of type ``ctx``) and the corresponding multiplicities in *mult* (a vector with elements of type ``fmpz``). If the target ring is not an algebraically closed field, then the sum of multiplicities can be smaller than the degree of the polynomial. For example, with ``fmpz`` coefficients, we only find integer roots. The *other* version of this function takes as input a polynomial with entries in a different ring ``poly_ctx``. For example, we can compute ``qqbar`` or ``arb`` roots for a polynomial with ``fmpz`` coefficients. Whether the roots are sorted in any particular order is ring-dependent. We consider roots of the zero polynomial to be ill-defined and return ``GR_DOMAIN`` in that case. Power series special functions -------------------------------------------------------------------------------- .. function:: int _gr_poly_asin_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_asin_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_asinh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_asinh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_acos_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_acos_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_acosh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_acosh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_atan_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_atan_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_atanh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_atanh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_log_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_log_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) int _gr_poly_log1p_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_log1p_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) .. function:: int _gr_poly_exp_series_basecase(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) int gr_poly_exp_series_basecase(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) int _gr_poly_exp_series_basecase_mul(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) int gr_poly_exp_series_basecase_mul(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) int _gr_poly_exp_series_newton(gr_ptr f, gr_ptr g, gr_srcptr h, slong hlen, slong n, slong cutoff, gr_ctx_t ctx) int gr_poly_exp_series_newton(gr_poly_t f, const gr_poly_t h, slong n, slong cutoff, gr_ctx_t ctx) int _gr_poly_exp_series_generic(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) int _gr_poly_exp_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) int gr_poly_exp_series(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) .. function:: int _gr_poly_sin_cos_series_basecase(gr_ptr s, gr_ptr c, gr_srcptr h, slong hlen, slong n, int times_pi, gr_ctx_t ctx) int gr_poly_sin_cos_series_basecase(gr_poly_t s, gr_poly_t c, const gr_poly_t h, slong n, int times_pi, gr_ctx_t ctx) int _gr_poly_sin_cos_series_tangent(gr_ptr s, gr_ptr c, gr_srcptr h, slong hlen, slong n, int times_pi, gr_ctx_t ctx) int gr_poly_sin_cos_series_tangent(gr_poly_t s, gr_poly_t c, const gr_poly_t h, slong n, int times_pi, gr_ctx_t ctx) The *basecase* version uses a simple recurrence for the coefficients, requiring `O(nm)` operations where `m` is the length of `h`. The *tangent* version uses the tangent half-angle formulas to compute the sine and cosine via :func:`_acb_poly_tan_series`. This requires `O(M(n))` operations. When `h = h_0 + h_1` where the constant term `h_0` is nonzero, the evaluation is done as `\sin(h_0 + h_1) = \cos(h_0) \sin(h_1) + \sin(h_0) \cos(h_1)`, `\cos(h_0 + h_1) = \cos(h_0) \cos(h_1) - \sin(h_0) \sin(h_1)`. The *basecase* and *tangent* versions take a flag *times_pi* specifying that the input is to be multiplied by `\pi`. .. function:: int _gr_poly_tan_series_basecase(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) int gr_poly_tan_series_basecase(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) int _gr_poly_tan_series_newton(gr_ptr f, gr_srcptr h, slong hlen, slong n, slong cutoff, gr_ctx_t ctx) int gr_poly_tan_series_newton(gr_poly_t f, const gr_poly_t h, slong n, slong cutoff, gr_ctx_t ctx) int _gr_poly_tan_series(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) int gr_poly_tan_series(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) .. raw:: latex \newpage flint-3.1.3/doc/source/gr_special.rst000066400000000000000000000510701461254215100175450ustar00rootroot00000000000000.. _gr-special: **gr_special.h** -- special arithmetic and transcendental functions =============================================================================== Mathematical constants -------------------------------------------------------------------------------- .. function:: int gr_pi(gr_ptr res, gr_ctx_t ctx) int gr_euler(gr_ptr res, gr_ctx_t ctx) int gr_catalan(gr_ptr res, gr_ctx_t ctx) int gr_khinchin(gr_ptr res, gr_ctx_t ctx) int gr_glaisher(gr_ptr res, gr_ctx_t ctx) Standard real constants: `\pi`, Euler's constant `\gamma`, Catalan's constant, Khinchin's constant, Glaisher's constant. Elementary functions -------------------------------------------------------------------------------- .. function:: int gr_exp(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_expm1(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_exp2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_exp10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_exp_pi_i(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_log(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_log1p(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_log2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_log10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_log_pi_i(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_sin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_cos(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sin_cos(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx) int gr_tan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_cot(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sec(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_csc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_sin_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_cos_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sin_cos_pi(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx) int gr_tan_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_cot_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sec_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_csc_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_sinc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sinc_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_sinh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_cosh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sinh_cosh(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx) int gr_tanh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_coth(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sech(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_csch(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_asin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acos(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_atan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_atan2(gr_ptr res, gr_srcptr y, gr_srcptr x, gr_ctx_t ctx) int gr_acot(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_asec(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acsc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_asin_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acos_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_atan_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acot_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_asec_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acsc_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_asinh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acosh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_atanh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acoth(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_asech(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_acsch(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_lambertw(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_lambertw_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t k, gr_ctx_t ctx) Factorials and gamma functions -------------------------------------------------------------------------------- .. function:: int gr_fac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_fac_ui(gr_ptr res, ulong x, gr_ctx_t ctx) int gr_fac_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) int gr_fac_vec(gr_ptr res, slong len, gr_ctx_t ctx) Factorial `x!`. The *vec* version writes the first *len* consecutive values `1, 1, 2, 6, \ldots, (len-1)!` to the preallocated vector *res*. .. function:: int gr_rfac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_rfac_ui(gr_ptr res, ulong x, gr_ctx_t ctx) int gr_rfac_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) int gr_rfac_vec(gr_ptr res, slong len, gr_ctx_t ctx) Reciprocal factorial. The *vec* version writes the first *len* consecutive values `1, 1, 1/2, 1/6, \ldots, 1/(len-1)!` to the preallocated vector *res*. .. function:: int gr_bin(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_bin_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_bin_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) int gr_bin_vec(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx) int gr_bin_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) Binomial coefficient `{x \choose y}`. The *vec* versions write the first *len* consecutive values `{x \choose 0}, {x \choose 1}, \ldots, {x \choose len-1}` to the preallocated vector *res*. For constructing a two-dimensional array of binomial coefficients (Pascal's triangle), it is more efficient to call :func:`gr_mat_pascal` than to call these functions repeatedly. .. function:: int gr_rising(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_rising_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) int gr_falling(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_falling_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) Rising and falling factorials `x (x+1) \cdots (x+y-1)` and `x (x-1) \cdots (x-y+1)`, or their generalizations to non-integer `y` via the gamma function. .. function:: int gr_gamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_gamma_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) int gr_gamma_fmpq(gr_ptr res, const fmpq_t x, gr_ctx_t ctx) int gr_rgamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_lgamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_digamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Gamma function `\Gamma(x)`, its reciprocal `1 / \Gamma(x)`, the log-gamma function `\log \Gamma(x)`, and the digamma function `\psi(x)`. .. function:: int gr_barnes_g(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_log_barnes_g(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Barnes G-function. .. function:: int gr_beta(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) Beta function `B(x,y)`. .. function:: int gr_doublefac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_doublefac_ui(gr_ptr res, ulong x, gr_ctx_t ctx) Double factorial `x!!`. .. function:: int gr_harmonic(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_harmonic_ui(gr_ptr res, ulong x, gr_ctx_t ctx) Harmonic number `H_x`. Combinatorial numbers -------------------------------------------------------------------------------- The *vec* version of functions for number sequences `c_n` write the *len* consecutive values `c_0, c_1, \ldots, c_{len-1}` to the preallocated vector *res*. .. function:: int gr_bernoulli_ui(gr_ptr res, ulong n, gr_ctx_t ctx) int gr_bernoulli_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_bernoulli_vec(gr_ptr res, slong len, gr_ctx_t ctx) Bernoulli numbers `B_n`. .. function:: int gr_eulernum_ui(gr_ptr res, ulong x, gr_ctx_t ctx) int gr_eulernum_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) int gr_eulernum_vec(gr_ptr res, slong len, gr_ctx_t ctx) Euler numbers `E_n`. .. function:: int gr_fib_ui(gr_ptr res, ulong n, gr_ctx_t ctx) int gr_fib_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_fib_vec(gr_ptr res, slong len, gr_ctx_t ctx) Fibonacci numbers `F_n`. .. function:: int gr_stirling_s1u_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) int gr_stirling_s1_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) int gr_stirling_s2_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) int gr_stirling_s1u_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) int gr_stirling_s1_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) int gr_stirling_s2_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) Stirling numbers `S(x,y)`: unsigned of the first kind, signed of the first kind, and second kind. The *vec* versions write the *len* consecutive values `S(x,0), S(x,1), \ldots, S(x, len-1)` to the preallocated vector *res*. For constructing a two-dimensional array of Stirling numbers, it is more efficient to call :func:`gr_mat_stirling` than to call these functions repeatedly. .. function:: int gr_bellnum_ui(gr_ptr res, ulong x, gr_ctx_t ctx) int gr_bellnum_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) int gr_bellnum_vec(gr_ptr res, slong len, gr_ctx_t ctx) Bell numbers `B_n`. .. function:: int gr_partitions_ui(gr_ptr res, ulong x, gr_ctx_t ctx) int gr_partitions_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) int gr_partitions_vec(gr_ptr res, slong len, gr_ctx_t ctx) Partition numbers `p(n)`. Error function and exponential integrals -------------------------------------------------------------------------------- .. function:: int gr_erf(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_erfc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_erfcx(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_erfi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_erfinv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_erfcinv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_fresnel_s(gr_ptr res, gr_srcptr x, int normalized, gr_ctx_t ctx) int gr_fresnel_c(gr_ptr res, gr_srcptr x, int normalized, gr_ctx_t ctx) int gr_fresnel(gr_ptr res1, gr_ptr res2, gr_srcptr x, int normalized, gr_ctx_t ctx) .. function:: int gr_gamma_upper(gr_ptr res, gr_srcptr x, gr_srcptr y, int regularized, gr_ctx_t ctx) int gr_gamma_lower(gr_ptr res, gr_srcptr x, gr_srcptr y, int regularized, gr_ctx_t ctx) int gr_beta_lower(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int regularized, gr_ctx_t ctx) .. function:: int gr_exp_integral(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_exp_integral_ei(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sin_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_cos_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_sinh_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_cosh_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_log_integral(gr_ptr res, gr_srcptr x, int offset, gr_ctx_t ctx) int gr_dilog(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) Orthogonal polynomials -------------------------------------------------------------------------------- .. function:: int gr_chebyshev_t_fmpz(gr_ptr res, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) int gr_chebyshev_t(gr_ptr res, gr_srcptr n, gr_srcptr x, gr_ctx_t ctx) int gr_chebyshev_u_fmpz(gr_ptr res, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) int gr_chebyshev_u(gr_ptr res, gr_srcptr n, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_jacobi_p(gr_ptr res, gr_srcptr n, gr_srcptr a, gr_srcptr b, gr_srcptr z, gr_ctx_t ctx) int gr_gegenbauer_c(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, gr_ctx_t ctx) int gr_laguerre_l(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, gr_ctx_t ctx) int gr_hermite_h(gr_ptr res, gr_srcptr n, gr_srcptr z, gr_ctx_t ctx) int gr_legendre_p(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, int type, gr_ctx_t ctx) int gr_legendre_q(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, int type, gr_ctx_t ctx) int gr_spherical_y_si(gr_ptr res, slong n, slong m, gr_srcptr theta, gr_srcptr phi, gr_ctx_t ctx) int gr_legendre_p_root_ui(gr_ptr root, gr_ptr weight, ulong n, ulong k, gr_ctx_t ctx) Bessel, Airy and Coulomb functions -------------------------------------------------------------------------------- .. function:: int gr_bessel_j(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_bessel_y(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_bessel_i(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_bessel_k(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_bessel_j_y(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_bessel_i_scaled(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_bessel_k_scaled(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_airy(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr x, gr_ctx_t ctx) int gr_airy_ai(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_airy_bi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_airy_ai_prime(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_airy_bi_prime(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_airy_ai_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_airy_bi_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_airy_ai_prime_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_airy_bi_prime_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) .. function:: int gr_coulomb(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) int gr_coulomb_f(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) int gr_coulomb_g(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) int gr_coulomb_hpos(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) int gr_coulomb_hneg(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) Hypergeometric functions -------------------------------------------------------------------------------- .. function:: int gr_hypgeom_0f1(gr_ptr res, gr_srcptr a, gr_srcptr z, int flags, gr_ctx_t ctx) int gr_hypgeom_1f1(gr_ptr res, gr_srcptr a, gr_srcptr b, gr_srcptr z, int flags, gr_ctx_t ctx) int gr_hypgeom_u(gr_ptr res, gr_srcptr a, gr_srcptr b, gr_srcptr z, int flags, gr_ctx_t ctx) int gr_hypgeom_2f1(gr_ptr res, gr_srcptr a, gr_srcptr b, gr_srcptr c, gr_srcptr z, int flags, gr_ctx_t ctx) int gr_hypgeom_pfq(gr_ptr res, const gr_vec_t a, const gr_vec_t b, gr_srcptr z, int flags, gr_ctx_t ctx) Riemann zeta, polylogarithms and Dirichlet L-functions -------------------------------------------------------------------------------- .. function:: int gr_zeta(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_zeta_ui(gr_ptr res, ulong x, gr_ctx_t ctx) int gr_hurwitz_zeta(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_polygamma(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_polylog(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) int gr_lerch_phi(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) int gr_stieltjes(gr_ptr res, const fmpz_t x, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_dirichlet_eta(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_riemann_xi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_zeta_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) int gr_zeta_zero_vec(gr_ptr res, const fmpz_t n, slong len, gr_ctx_t ctx) int gr_zeta_nzeros(gr_ptr res, gr_srcptr t, gr_ctx_t ctx) .. function:: int gr_dirichlet_chi_fmpz(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, const fmpz_t n, gr_ctx_t ctx) int gr_dirichlet_chi_vec(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, gr_ctx_t ctx) int gr_dirichlet_l(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr s, gr_ctx_t ctx) int gr_dirichlet_l_all(gr_vec_t res, const dirichlet_group_t G, gr_srcptr s, gr_ctx_t ctx) int gr_dirichlet_hardy_theta(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr t, gr_ctx_t ctx) int gr_dirichlet_hardy_z(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr t, gr_ctx_t ctx) Elliptic integrals -------------------------------------------------------------------------------- .. function:: int gr_agm1(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) int gr_agm(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) .. function:: int gr_elliptic_k(gr_ptr res, gr_srcptr m, gr_ctx_t ctx) int gr_elliptic_e(gr_ptr res, gr_srcptr m, gr_ctx_t ctx) int gr_elliptic_pi(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_ctx_t ctx) int gr_elliptic_f(gr_ptr res, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) int gr_elliptic_e_inc(gr_ptr res, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) int gr_elliptic_pi_inc(gr_ptr res, gr_srcptr n, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) .. function:: int gr_carlson_rc(gr_ptr res, gr_srcptr x, gr_srcptr y, int flags, gr_ctx_t ctx) int gr_carlson_rf(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) int gr_carlson_rd(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) int gr_carlson_rg(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) int gr_carlson_rj(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_srcptr w, int flags, gr_ctx_t ctx) Elliptic, modular and theta functions -------------------------------------------------------------------------------- .. function:: int gr_jacobi_theta(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_jacobi_theta_1(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_jacobi_theta_2(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_jacobi_theta_3(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_jacobi_theta_4(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) .. function:: int gr_dedekind_eta(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) int gr_dedekind_eta_q(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) .. function:: int gr_modular_j(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) int gr_modular_lambda(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) int gr_modular_delta(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) .. function:: int gr_hilbert_class_poly(gr_ptr res, slong D, gr_srcptr x, gr_ctx_t ctx) .. function:: int gr_eisenstein_e(gr_ptr res, ulong n, gr_srcptr tau, gr_ctx_t ctx) int gr_eisenstein_g(gr_ptr res, ulong n, gr_srcptr tau, gr_ctx_t ctx) int gr_eisenstein_g_vec(gr_ptr res, gr_srcptr tau, slong len, gr_ctx_t ctx) .. function:: int gr_elliptic_invariants(gr_ptr res1, gr_ptr res2, gr_srcptr tau, gr_ctx_t ctx) int gr_elliptic_roots(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_srcptr tau, gr_ctx_t ctx) .. function:: int gr_weierstrass_p(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_weierstrass_p_prime(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_weierstrass_p_inv(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_weierstrass_zeta(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) int gr_weierstrass_sigma(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) .. raw:: latex \newpage flint-3.1.3/doc/source/gr_vec.rst000066400000000000000000000321461461254215100167050ustar00rootroot00000000000000.. _gr-vec: **gr_vec.h** -- vectors over generic rings =============================================================================== Types and basic operations -------------------------------------------------------------------------------- .. type:: gr_vec_struct .. type:: gr_vec_t .. function:: void gr_vec_init(gr_vec_t vec, slong len, gr_ctx_t ctx) Initializes *vec* to a vector of length *len* with elements in the ring *ctx*. The length must be nonnegative. All entries are set to zero. .. function:: void gr_vec_clear(gr_vec_t vec, gr_ctx_t ctx) Clears the vector *vec*. .. macro:: GR_VEC_ENTRY(vec, i, sz) Macro to access the *i*-th element in the vector *vec*, indexed from zero, assuming that entries have size ``sz``. The index must be in bounds. .. function:: gr_ptr gr_vec_entry_ptr(gr_vec_t vec, slong i, gr_ctx_t ctx) Returns a pointer to the *i*-th element in the vector *vec*, indexed from zero. The index must be in bounds. .. function:: slong gr_vec_length(const gr_vec_t vec, gr_ctx_t ctx) Returns the length of the vector *vec*. .. function:: void gr_vec_fit_length(gr_vec_t vec, slong len, gr_ctx_t ctx) Allocates space for at least *len* elements in the vector *vec*. This does not change the size of the vector. .. function:: void gr_vec_set_length(gr_vec_t vec, slong len, gr_ctx_t ctx) Resizes the vector to length *len*, which must be nonnegative. The vector will be extended with zeros. .. function:: int gr_vec_set(gr_vec_t res, const gr_vec_t src, gr_ctx_t ctx) Sets *res* to a copy of the vector *src*. .. function:: int gr_vec_append(gr_vec_t vec, gr_srcptr x, gr_ctx_t ctx) Appends the element *x* to the end of vector *vec*. .. function:: int _gr_vec_write(gr_stream_t out, gr_srcptr vec, slong len, gr_ctx_t ctx) int gr_vec_write(gr_stream_t out, const gr_vec_t vec, gr_ctx_t ctx) int gr_vec_print(const gr_vec_t vec, gr_ctx_t ctx) .. macro:: GR_ENTRY(vec, i, size) Macro to access the *i*-th entry of a ``gr_ptr`` or ``gr_srcptr`` vector *vec*, where each element is ``size`` bytes. .. function:: void _gr_vec_init(gr_ptr vec, slong len, gr_ctx_t ctx) Initialize *len* elements of *vec* to the value 0. The pointer *vec* must already refer to allocated memory. .. function:: void _gr_vec_clear(gr_ptr vec, slong len, gr_ctx_t ctx) Clears *len* elements of *vec*. This frees memory allocated by individual elements, but does not free the memory allocated by *vec* itself. .. function:: void _gr_vec_swap(gr_ptr vec1, gr_ptr vec2, slong len, gr_ctx_t ctx) Swap the entries of *vec1* and *vec2*. .. function:: int _gr_vec_randtest(gr_ptr res, flint_rand_t state, slong len, gr_ctx_t ctx) .. function:: int _gr_vec_set(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) .. function:: truth_t _gr_vec_equal(gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) .. function:: int _gr_vec_zero(gr_ptr vec, slong len, gr_ctx_t ctx) .. function:: truth_t _gr_vec_is_zero(gr_srcptr vec, slong len, gr_ctx_t ctx) .. function:: int _gr_vec_normalise(slong * res, gr_srcptr vec, slong len, gr_ctx_t ctx) .. function:: slong _gr_vec_normalise_weak(gr_srcptr vec, slong len, gr_ctx_t ctx) Arithmetic -------------------------------------------------------------------------------- .. function:: int _gr_vec_neg(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) .. function:: int _gr_vec_add(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int _gr_vec_sub(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int _gr_vec_mul(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int _gr_vec_div(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int _gr_vec_divexact(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) int _gr_vec_pow(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) Binary operations applied elementwise. .. function:: int _gr_vec_add_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_vec_sub_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_vec_mul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_vec_div_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_vec_divexact_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_vec_pow_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_scalar_add_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_sub_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_mul_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_div_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_pow_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) Binary operations applied elementwise with a fixed scalar operand. .. function:: int _gr_vec_add_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int _gr_vec_sub_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int _gr_vec_mul_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int _gr_vec_div_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int _gr_vec_divexact_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int _gr_vec_pow_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) int _gr_other_add_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int _gr_other_sub_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int _gr_other_mul_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int _gr_other_div_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int _gr_other_divexact_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) int _gr_other_pow_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) Binary operations applied elementwise, allowing a different type for one of the vectors. .. function:: int _gr_vec_add_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int _gr_vec_sub_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int _gr_vec_mul_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int _gr_vec_div_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int _gr_vec_divexact_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int _gr_vec_pow_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) int _gr_scalar_other_add_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_other_sub_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_other_mul_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_other_div_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_other_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_scalar_other_pow_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_vec_add_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int _gr_vec_sub_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int _gr_vec_mul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int _gr_vec_div_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int _gr_vec_divexact_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int _gr_vec_pow_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int _gr_vec_add_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int _gr_vec_sub_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int _gr_vec_mul_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int _gr_vec_div_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int _gr_vec_divexact_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int _gr_vec_pow_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) int _gr_vec_add_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int _gr_vec_sub_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int _gr_vec_mul_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int _gr_vec_div_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int _gr_vec_divexact_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int _gr_vec_pow_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) int _gr_vec_add_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int _gr_vec_sub_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int _gr_vec_mul_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int _gr_vec_div_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int _gr_vec_divexact_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) int _gr_vec_pow_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) Binary operations applied elementwise with a fixed scalar operand, allowing a different type for the scalar. .. function:: int _gr_vec_addmul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_vec_submul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) int _gr_vec_addmul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) int _gr_vec_submul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) .. function:: int _gr_vec_mul_scalar_2exp_si(gr_ptr res, gr_srcptr vec, slong len, slong c, gr_ctx_t ctx) Sums and products -------------------------------------------------------------------------------- .. function:: int _gr_vec_sum(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) .. function:: int _gr_vec_product(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) Dot products -------------------------------------------------------------------------------- .. function:: int _gr_vec_dot(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) int _gr_vec_dot_si(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const slong * vec2, slong len, gr_ctx_t ctx) int _gr_vec_dot_ui(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const ulong * vec2, slong len, gr_ctx_t ctx) int _gr_vec_dot_fmpz(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) Sets *res* to `c \pm \sum_{i=0}^{n-1} a_i b_i`. .. function:: int _gr_vec_dot_rev(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) Sets *res* to `c \pm \sum_{i=0}^{n-1} a_i b_{n-1-i}`. Other functions -------------------------------------------------------------------------------- .. function:: int _gr_vec_step(gr_ptr vec, gr_srcptr start, gr_srcptr step, slong len, gr_ctx_t ctx) .. function:: int _gr_vec_reciprocals(gr_ptr res, slong len, gr_ctx_t ctx) Sets *res* to the vector of reciprocals of the positive integers 1, 2, ... up to *len* inclusive. .. function:: int _gr_vec_set_powers(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx) .. raw:: latex \newpage flint-3.1.3/doc/source/history.rst000066400000000000000000005711501461254215100171440ustar00rootroot00000000000000.. _history: History and changes =============================================================================== FLINT version history ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 2024-02-25 -- FLINT 3.1.0 ------------------------------------------------------------------------------- Main contributors: Fredrik Johansson (FJ), Albin Ahlbäck (AA), Jean Kieffer (JK). * License * Changed license from "LGPL 2.1 or later" to "LGPL 3 or later". * Major interface changes * The methods in the ``fmpz_mod_mat`` module now use a context object (FJ). * Changed ``fq_mat_rref`` and others to allow separate input and output matrices (FJ). * Features * New module ``acb_theta`` for computing complex Riemann theta functions with characteristics in any dimension (JK). * ``flint_printf`` and related functions now supports printing common FLINT types, e.g. using the format string ``%{fmpz}`` for ``fmpz_t`` (AA). * Generic expression parsing: ``gr_set_str`` supports parsing expressions like ``a*x^2+1/3`` or ``(0.1 + 0.2*i) +/- (0.001 + 0.001*i)`` in any ring (FJ). * Added ``fmpz_mpoly_q_set_str_pretty`` and ``fmpz_mpoly_q_get_str_pretty``. * Added ``flint_mpn_mulhigh`` (AA). * Primality testing for Gaussian integers (``fmpzi_is_prime``, ``fmpzi_is_probabprime``) (Mathieu Gouttenoire). * Modular splitting evaluation of polynomials (``_gr_poly_evaluate_modular``) (David Berghaus). * Reversion of generic power series (``gr_poly_revert_series`` and variants) (FJ). * Support inversion for ``gr`` vectors (FJ). * Split generic division into ``gr_div`` and ``gr_div_nonunique`` to make the semantics of division more precise (FJ). * Added ``gr_ctx_is_zero_ring`` (FJ). * Added ``nmod_divides`` (FJ). * Reciprocal Fibonacci constant (``arb_const_reciprocal_fibonacci``) (FJ). * Added functions for working with symmetric positive-definite matrices (``fmpz_mat_is_spd``, ``arb_mat_spd_get_fmpz_mat``, ``arb_mat_spd_is_lll_reduced``, ``arb_mat_spd_lll_reduce``, ``arb_mat_randtest_cho``, ``arb_mat_randtest_spd``) (JK). * Added several helper functions for ``arb`` and ``acb`` vectors and matrices (``_arb_vec_contains``, ``_arb_vec_equal``, ``_arb_vec_overlaps``, ``_arb_vec_printd``, ``_acb_vec_contains``, ``_acb_vec_equal``, ``_acb_vec_get_imag``, ``_acb_vec_get_real``, ``_acb_vec_overlaps``, ``_acb_vec_printd``, ``_acb_vec_set_real_imag``, ``_acb_vec_sqr``, ``arb_mat_vector_mul_col``, ``arb_mat_vector_mul_row`` ``acb_mat_vector_mul_col``, ``acb_mat_vector_mul_row`` ``acb_mat_get_imag``, ``acb_mat_get_real``, ``acb_mat_onei``) (JK). * Added ``acb_urandom`` and ``arb_randtest_positive`` (JK). * Added ``acb_mul_i_pow_si`` (JK). * Handle modulus 1 in ``fmpz_CRT`` functions (Fabian Gundlach). * Added ``_nmod_poly_conway`` and ``_nmod_poly_conway_rand`` (AA). * Added ``fft_small_mulmod_satisfies_bounds``. The function ``sd_fft_ctx_init`` now verifies that the modulus satisfies the assumptions for correct modular arithmetic. (Daniel Schultz). * Allow setting generator names for ``gr_mpoly``, ``gr_series``, ``fmpz_mpoly`` and ``fmpz_mpoly_q`` generic rings (FJ). * Added ``gr_gens_recursive`` (FJ). * Allow overriding ``flint_aligned_alloc`` (AA). * Added ``_fmpz_vec_dot_general`` (FJ). * Allow setting degree and bit size evaluation limits for the ``gr`` ``qqbar`` context (FJ). * Added ``nmod_poly_divexact`` and use this instead of ``nmod_poly_div`` where an exact division is intended to improve performance (FJ). * Added ``fmpz_poly_divexact`` and use this instead of ``fmpz_poly_div`` where an exact division is intended to improve performance (FJ). * Added ``fq_default_ctx_inner`` to access the internal context object of a ``fq_default_ctx`` (FJ). * Implemented ``gr_is_ring`` and ``gr_ctx_is_commutative_ring`` properly (FJ). * Added ``d_mul_2exp_inrange``, ``d_mul_2exp_inrange2``, ``d_mul_2exp`` and ``_d_vec_mul_2exp`` (FJ). * Added ``fmpz_mod_mat_det`` (FJ). * Allow overriding ``gr_mat_lu`` (FJ). * Bugs * Fixed threading problem in ``gr_method_tab_init``: FLINT would occasionally crash when calling generics-based internal code when using a large number of threads (FJ, after debugging by Alexander Smirnov). * Fixed comparison of ``gr`` vectors with ``fmpq`` elements (FJ). * Fixed allocation bug in ``gr_mpoly_mul_monomial`` (FJ). * Fixed aliasing in ``fmpzi_divrem_approx`` (FJ). * Avoid division by zero in ``acb_poly_refine_roots_durand_kerner``: in rare instances, computing roots of an integer polynomial could hang (FJ). * Allow large arguments in ``arb_atan_frac_bsplit`` (FJ). * Fixed printing large coefficients in ``nmod_mpoly`` (Alexander Smirnov, AA). * Fixed ``fq_*_poly_powmod`` (AA). * Fixed initialization of ``fq_default_ctx`` (Claus Fieker, Tommy Hofmann). * Fixed memory leak in ``gr_poly_write`` (FJ). * Fixed printing ``nmod32`` elements on 32-bit systems (FJ). * Fixed ``ldconfig`` for BSD systems (AA). * Fixed ``FLINT_WANT_ASSERT`` for CMake (AA). * Fixed memory leak in ``arb_nint`` (FJ). * Performance * FLINT is now built with ``-O3 -march=native`` by default (AA). * FLINT is no longer built with ``-funroll-loops`` by default except for select modules. This reduces the library size by more than 20%. (AA). * Assembly routines are now used as intended on ARM64 when compiling with GCC (AA). * New basecase code for ``flint_mpn_mul``, ``flint_mpn_mul_n`` and ``flint_mpn_sqr`` (generic C versions, assembly for x86-64). This can yield up to a 2x speedup over GMP for short integer multiplications when calling ``mpn`` functions directly, though few applications currently benefit significantly due to wrapper overheads (some Arb benchmarks run ~5% faster with this change) (AA, FJ). * Added hardcoded low-level routines for high multiplications of two operands of the same size for Broadwell-type CPUs -- ``flint_mpn_mulhigh_*`` and ``flint_mpn_sqrhigh_*`` (AA). * Added hardcoded low-level routines for high normalised multiplications of two normalised operands of the same size for Broadwell-type CPUs -- ``flint_mpn_mulhigh_normalised_*`` (AA). * Added ``flint_mpn_mulhigh_basecase`` and ``flint_mpn_sqrhigh_basecase`` for Broadwell-type CPUs (AA). * Use toom22 on top of custom basecase code for intermediate operands in ``flint_mpn_mul`` (FJ, based on GMP code). * Use ``mulx`` in ``umul_ppmm`` when available (AA). * Faster ``_fmpz_vec_dot`` (FJ). * Faster ``_fmpz_mod_vec_dot`` (FJ). * Faster ``fmpz_poly`` and ``fmpz_mat`` basecase algorithms based on dot products (FJ). * Optimized ``fmpz_mat_mul_classical`` (FJ). * Added ``fmpz_mat_mul_waksman``, speeding up ``fmpz_mat`` multiplication for balanced matrices with huge entries (Éric Schost, Vincent Neiger, FJ). * Tweaks to improve GCC's code generation for ``fmpz_mpoly`` and ``nmod_mpoly`` multiplication (FJ). * Improved ``fmpz_mod_mat_set_fmpz_mat`` (FJ). * Improved tuning for ``fmpz_mat_sqr`` (FJ). * Improved ``fmpz_mat_sqr_bodrato`` with small coefficients (Marco Bodrato). * Squaring optimizations in ``fmpz_mat_mul_multi_mod`` (FJ). * Use Bodrato's sequence for Strassen multiplication (Marco Bodrato). * Strip trailing zeros in ``fmpz_poly_gcd``: this gives a 50x speedup computing ``gcd(x^1000, x^1001)`` (FJ). * Faster CLD bound computation, speeding up ``fmpz_poly_factor`` for some polynomials (FJ). * Use new formulas from Jorge Zuniga and Jesús Guillera to compute log(2), Catalan's constant, zeta(3) and gamma(1/3) faster (FJ). * Compressed the database of Conway polynomials to 10% of the original size (AA). * Optimized context initializers for ``fq``, ``fq_zech``, ``fq_nmod`` and ``qadic`` (AA). * Avoid calls to the slow standard library function ``ldexp`` (FJ). * Improved ``fmpz_is_probabprime`` for word-size input (FJ). * Make ``gr_poly_resultant`` use the quasilinear hgcd algorithm by default over finite rings and remove obsolete ``fmpz_mod_poly`` implementations (FJ). * Optimized header files (AA). * Changed several internal helper functions to forced inlines (AA). * Merged some sources files to speed up compilation (AA). * Faster computation of Swinnerton-Dyer polynomials (FJ). * Added benchmark script (``dev/bench.py``) that should be used to check performance increases and regressions (FJ). * Add special cases for Clang and MSVC in ``longlong.h`` (AA). * Test code * Unified test programs per module: compiling FLINT's test suite is now an order of magnitude faster (AA). * Added pretty-printing and timing output for unit tests (AA). * Improve use of test multiplier in some long-running unit tests (AA, FJ). * Improved test coverage (AA, FJ). * Allow ``gr_ctx_init_random`` to generate composite rings (FJ). * Fixed the test code of ``fq_*_poly_powmod`` (AA). * Maintenance * Require GMP >= 6.2.1 and MPFR >= 4.1.0 (AA). * Drop support for Itanium (AA). * Drop support for MPIR (AA). * Cleaned up ``longlong.h`` (AA). * Removed ``ARB_VERSION``, ``ANTIC_VERSION``, ``CALCIUM_VERSION`` and associated constants (AA). * Removed ``_long_vec_print`` and ``_perm_print`` (use ``flint_printf`` instead) (AA). * Removed unused functions in the ``d_mat`` and ``aprcl`` modules (AA). * Removed ``fmpq_get_mpz_frac`` (AA). * Removed ``arb_fmpz_poly_cos_minpoly`` (AA). * Removed ``fmpz_mat_mul_classical_inline`` (FJ). * Removed ``fmpz_mat_rref_mod`` (use ``fmpz_mod_mat_rref`` instead) (FJ). * Introduce ``FLINT_SWAP`` macro to replace several older macros (FJ). * Replaced ``invert_limb`` by ``n_preinvert_limb_prenorm`` (AA). * Renamed ``_perm_set_one`` to ``_perm_one`` (AA). * Only define some multithreaded "divides" function when the CPU is strongly ordered (AA). * Enable ``fft_small`` for MSVC builds (AA). * Use binary format instead of decimal format in ``qsieve``, removing the need of conversions between said formats (AA). * Use C11 atomics in the ``fmpz`` memory manager (AA). * Merged some repeated code in the ``mpoly`` modules (FJ). * Refactored ``fq_default`` to use ``gr`` generics internally (FJ). * Replaced more functions by generics-based versions (FJ). * Do not include ``pthread.h`` when opted out (AA). * Test ARM NEON in CI via Github's Apple M1 runner (AA). * Test examples in CI (AA). * Detect MPFR and GMP internals in configure (AA). * Add ``-lflint`` to PKG-CONFIG (Josh Rickmar). * Silence GCC compiler warnings (AA). * Unified exception handling (AA). * Corrected some function signatures in the documentation (Vincent Delecroix, Joel-Dahne, Edgar Costa). * Rename the default Git-branch from ``trunk`` to ``main`` (FJ). * Document some macros defined in ``flint.h`` (AA). * Other code cleanup and modernisation (AA). * Major cleanup in ``configure.ac`` and ``acinclude.m4``. * Use parts of GMP's configuration to configure assembly properly. * Change instances of ``#ifdef FLINT_WANT_ASSERT`` to ``#if FLINT_WANT_ASSERT`` (AA). 2023-11-10 -- FLINT 3.0.1 ------------------------------------------------------------------------------- * Build issues * Fix LIBS2 order for static linking (Tomás Oliveira e Silva). * Fix substitution of version number for older autotools (Albin Ahlbäck). * Fix use of AC_SEARCH_LIBS to find cblas_dgemm (Gonzalo Tornaría). * Add FlexiBLAS as a cblas option (Mahrud Sayrafi). * Don't use deprecated PythonInterp in CMake build (Mahrud Sayrafi). * Fix setting version numbers and strings in CMake build (Mahrud Sayrafi). * Only link with NTL for the tests on CMake (Mahrud Sayrafi). * Bugs * Fix bug in nmod32 on 32-bit systems. * Fix missing modulus assignment in nmod_poly_mat_window_init (Vincent Neiger). * Fix tmp allocation size in _fmpz_set_str_basecase. * Fix rare arithmetic bug and memory leak in n_factor_ecm_select_curve. * Other * Some corrections to the documentation. 2023-10-20 -- FLINT 3.0.0 ------------------------------------------------------------------------------- Merged libraries and reorganisation ................................... * The following libraries have been merged into FLINT: * Arb 2.23 (arbitrary-precision ball arithmetic) * Calcium 0.4 (exact real and complex arithmetic) * Antic 0.2.5 (number fields, binary quadratic forms) * Arb, Calcium and Antic will no longer be maintained as separate libraries. Users upgrading to FLINT 3.0 should ensure that they no longer link to the old Arb, Calcium or Antic library files or include any header files from those libraries which may be incompatible. * The FLINT 3.0 API is largely backwards-compatible with FLINT 2.9, Arb 2.23, Calcium 0.4 and Antic 0.2.5, except for changes to rarely-used and internal functions documented below. However, the following changes to the handling of header files are likely to require (trivial) patches in many downstream codebases: * Header files belonging to Arb, Calcium and Antic now appear in the ``flint/`` subdirectory. For example, instead of ``#include "arb.h"``, it is necessary to ``#include "flint/arb.h"`` unless ``/flint`` has been added to the include path. * Most header files no longer include their implicit dependencies. For example, ``fmpz_poly.h`` no longer includes ``fmpz.h``. Code that used functions from the ``fmpz`` module but only included ``fmpz_poly.h`` may thus now need to include ``fmpz.h`` explicitly. Likewise, many inclusions of system libraries like ``stdlib.h`` have been removed. * The following people helped with the merge: Fredrik Johansson, Isuru Fernando, Albin Ahlbäck. * FLINT 3.0 has a new build system based on Autotools, contributed by Albin Ahlbäck. Among other improvements, parallel builds are much faster and it is possible to build individual targets. Additional build system and CI improvements have been made by Marc Mezzarobba, Max Horn, Edgar Costa, Alex Best, Andreas Enge, and others. * It is now necessary to run ``bootstrap.sh`` to generate the ``configure`` script in order to build FLINT from the git repository. * Some ``configure`` options have changed: for example, ``--reentrant`` is now ``--enable-reentrant``. * The root directory has been cleaned up by moving all source code into the ``src`` directory. This should not affect any users. * The NTL interface has been moved to a single header file. The ``--with-ntl`` build flag is now only needed to build the test code for this interface. * The C++ interface (flintxx) has been removed. This interface is now maintained in the separate repository https://github.com/flintlib/flintxx (Edgar Costa). Generic rings .................. * The new ``gr`` module supports generic programming. It provides wrappers for most builtin FLINT types and allows constructing generic structures (polynomials, matrices, etc.) over arbitrary base rings. The following modules are available: * ``gr_generic`` (various generic algorithms) * ``gr_mat`` (matrices with generic elements) * ``gr_mpoly`` (multivariate polynomials with generic elements) * ``gr_poly`` (univariate polynomials with generic elements) * ``gr_special`` (special functions for generic elements) * ``gr_vec`` (vectors with generic elements) This feature is experimental: it is highly likely that some interfaces will change in a future FLINT release. * There is also a Python wrapper (``flint_ctypes``) included with FLINT available in the ``src/python`` directory. Unlike other third-party FLINT wrappers available currently, this wrapper uses the ``gr`` interface to wrap (nearly) all FLINT types at once. This wrapper is not officially supported and will likely be deprecated in the future, but it can be useful for experimenting with FLINT. * The generics system supports certain representations that do not have dedicated FLINT modules, for example 8-bit and 32-bit nmods. Small-prime FFT .................. * The new ``fft_small`` module implements FFTs modulo word-size primes and multiplication based on such FFTs. This module requires AVX2 or NEON vector instructions and will not be built on targets that do not support them. The small-prime FFT speeds up the following functions for huge input, sometimes by a factor 2x to 10x: * ``flint_mpn_mul`` and variants, and indirectly any function based on FLINT's integer multiplication for large inputs. For example, ``fmpz_mul`` and ``arb_mul`` are faster, but ``fmpz_gcd`` is currently unaffected since it calls GMP. * ``nmod_poly_mul`` and variants, and indirectly any function based on ``nmod_poly`` multiplication. * ``fmpz_poly_mul`` and variants, and indirectly any function based on ``fmpz_poly`` multiplication. * Division functions for ``fmpz`` and ``arb``, which now use Newton iteration instead of calling GMP for huge input. * ``fmpz_mod`` arithmetic. * Radix conversion functions like ``fmpz_get_str``, ``fmpz_set_str`` and ``arb_get_str``. * The FFT was contributed by Daniel Schultz, with final integration work and adaptations for other FLINT functions (Newton iteration implementations, etc.) done by Fredrik Johansson. Other changes .................. * Changed the order of the ``alloc`` and ``length`` fields in ``arb_poly_t``, ``acb_poly_t`` and ``ca_poly_t`` to match the FLINT types. * Added ``fmpzi`` division, norm and GCD functions (gcd_shortest by Daniel Schultz). * Added an ``acf`` type for complex floating-point numbers. * Added error handling to ``dirichlet_group_init``. * Increased the prime factor limit in ``dirichlet_group_init`` from 1e12 to 1e16. * Added ``arb_nonnegative_abs`` (Erik Postma). * Fixed ``arb_pow`` for x just barely containing 0, y > 0 (Erik Postma). * Improved precision handling in ``arb_gamma`` for huge input. * Faster ``arb_contains_arf``, ``arb_overlaps``, ``arb_gt``, ``arb_lt``. * Changed the argument order of ``_fmpz_mod_poly_mullow`` and ``_fmpz_mod_poly_div_series``. * Changed the call signature of many ``_fmpz_mod_poly`` methods to take a context object as input instead of the raw modulus. * Support test coverage reports (``--enable-coverage``). * Added ``fmpz_poly_randtest_irreducible``. * Improved tuning for various ``nmod_poly`` functions. * Most Newton polynomial division and square root functions now use the Karp-Markstein algorithm. * Replaced ``count_leading_zeros`` and ``count_trailing_zeros`` macros with ``flint_clz`` and ``flint_ctz``. * Fixed ``nmod_poly_compose`` which was not using an asymptotically fast algorithm. * Various functions in the ``nmod``, ``fmpz_mod``, ``fq`` modules and elsewhere have been rewritten to use algorithms in the generics module. In many cases the corresponding type-specific algorithm implementation has been removed entirely (for example, ``nmod_poly_divrem_newton`` no longer exists). * Fixed ``fmpz_mod_poly_factor_squarefree``, ``nmod_poly_factor_squarefree`` and ``fq_*_poly_factor_squarefree`` sometimes returning non-monic factors. Among other consequences, this could lead to functions like ``fq_poly_roots`` returning incorrect roots * Fixed several bugs in the ``fq_default`` modules (Tommy Hofmann). * Fixed stack overflow in ``mpoly_divrem_ideal`` functions. * Handle the the zero polynomial correctly in ``nmod_poly_shift_left`` (Vincent Neiger). * Fixed handling of permutations in ``invert_cols`` matrix methods (Vincent Neiger). * Added ``nmod_mat_permute_rows`` (Vincent Neiger). * Fixed bug in ``mpoly_monomial_halves`` (Daniel Schultz). * Fixed overflow bug in ``fmpz_mod_mpoly_divrem_ideal`` (Daniel Schultz). * Optimized ``fmpz_addmul``, ``fmpz_addmul_ui``, ``fmpz_submul``, ``fmpz_submul_ui`` for small arguments. * Fixed demotion bug in ``fmpz_addmul_si`` and ``fmpz_submul_si``. * Optimized ``fmpq_cmp``, ``fmpq_cmp_ui``, ``fmpq_cmp_si``, ``fmpq_cmp_fmpz`` for small arguments. * Optimized ``fmpz_poly_resultant_modular`` by using a tighter bound. * Allow lll to work with rank deficient Z basis (Daniel Schultz). * Added ``fmpq_mat_can_solve_dixon`` (William Hart). * Inlined ``n_gcd`` (Albin Ahlbäck). * Fixed fallback code for ``sub_ddmmss`` when given signed arguments. * Many documentation fixes (Håvard Damm-Johnsen, Joel Dahne, Albin Ahlbäck, David Einstein, Alex Best, and others). * Code simplifications (Vincent Neiger). * Fixed several type signatures (Ricardo Buring). * Fixed several memory leaks (Ricardo Buring). * Fixed ``fmpz_poly_factor_squarefree`` crashing when given the zero polynomial. * Added ``arb_minmax`` (Joel Dahne). * Added ``_push_term_ffmpz`` functions to mpoly types (David Einstein). * Added functions for printing nmod vectors (Vincent Neiger). * Added ``nmod_poly_is_monic`` (Vincent Neiger). * Fixed threaded Arb functions to use the thread pool (Albin Ahlbäck). * Removed nmod_poly mpz functions (Ricardo Buring). * Fixed file handling in qsieve (Michiel de Wilde, Oscar Benjamin). * Free memory in case of failure in ``fq_zech_ctx_init`` (Claus Fieker). * Fixed corrupted output in ``fmpz_or``. * Added several ``nmod_poly_mat`` utility functions (Vincent Neiger). List of additions ................. * FLINT 3.0 includes all functions in FLINT 2.9, Arb 2.23, Calcium 0.4 and Antic 0.2.5 except those listed under "list of removals". On top of this, the following functions have been added. This list is incomplete; many internal functions and functions starting with an underscore have been omitted. * ``mpn_mul_default_mpn_ctx``, ``_nmod_poly_mul_mid_default_mpn_ctx``, ``_fmpz_poly_mul_mid_default_mpn_ctx`` and many internal functions in the new ``fft_small`` module * ``acb_poly_nth_derivative, arb_div_arf_newton, arb_div_newton, arb_fmpz_divapprox, arb_nint, arb_poly_nth_derivative, arb_rsqrt_arf, arb_rsqrt_arf_newton, arb_sqrt_arf_newton, arb_sqrt_newton, arb_trunc, arb_minmax`` * ``ca_set_fmpzi`` * ``flint_aligned_alloc, flint_aligned_free`` * ``flint_get_num_available_threads`` * ``flint_mpn_add_inplace_c, flint_mpn_cmp_ui_2exp, flint_mpn_mul_large, flint_mpn_nbits`` * ``fmpz_get_str_bsplit_threaded`` * ``fmpz_mat_equal_col, fmpz_mat_equal_row, fmpz_neg_ui_array`` * ``fmpz_poly_randtest_irreducible`` * ``fmpz_poly_q_evaluate_fmpq, fmpz_poly_q_scalar_div_fmpq, fmpz_poly_q_scalar_div_fmpz, fmpz_poly_q_scalar_mul_fmpq, fmpz_poly_q_scalar_mul_fmpz`` * ``fmpz_ui_pow_ui`` * ``fmpzi_set_qqbar`` * ``get_default_mpn_ctx`` * ``gr_abs, gr_acos, gr_acos_pi, gr_acosh, gr_acot, gr_acot_pi, gr_acoth, gr_acsc, gr_acsc_pi, gr_acsch, gr_add, gr_add_fmpq, gr_add_fmpz, gr_add_other, gr_add_si, gr_add_ui, gr_addmul, gr_addmul_fmpq, gr_addmul_fmpz, gr_addmul_other, gr_addmul_si, gr_addmul_ui, gr_agm, gr_agm1, gr_airy, gr_airy_ai, gr_airy_ai_prime, gr_airy_ai_prime_zero, gr_airy_ai_zero, gr_airy_bi, gr_airy_bi_prime, gr_airy_bi_prime_zero, gr_airy_bi_zero, gr_asec, gr_asec_pi, gr_asech, gr_asin, gr_asin_pi, gr_asinh, gr_atan, gr_atan2, gr_atan_pi, gr_atanh, gr_barnes_g, gr_bellnum_fmpz, gr_bellnum_ui, gr_bellnum_vec, gr_bernoulli_fmpz, gr_bernoulli_ui, gr_bernoulli_vec, gr_bernpoly_ui, gr_bessel_i, gr_bessel_i_scaled, gr_bessel_j, gr_bessel_j_y, gr_bessel_k, gr_bessel_k_scaled, gr_bessel_y, gr_beta, gr_beta_lower, gr_bin, gr_bin_ui, gr_bin_ui_vec, gr_bin_uiui, gr_bin_vec, gr_carlson_rc, gr_carlson_rd, gr_carlson_rf, gr_carlson_rg, gr_carlson_rj, gr_catalan, gr_ceil, gr_chebyshev_t, gr_chebyshev_t_fmpz, gr_chebyshev_u, gr_chebyshev_u_fmpz, gr_clear, gr_cmp, gr_cmp_other, gr_cmpabs, gr_cmpabs_other, gr_conj, gr_cos, gr_cos_integral, gr_cos_pi, gr_cosh, gr_cosh_integral, gr_cot, gr_cot_pi, gr_coth, gr_coulomb, gr_coulomb_f, gr_coulomb_g, gr_coulomb_hneg, gr_coulomb_hpos, gr_csc, gr_csc_pi, gr_csch, gr_csgn, gr_ctx_ca_get_option, gr_ctx_ca_set_option, gr_ctx_clear, gr_ctx_cmp_coercion, gr_ctx_data_as_ptr, gr_ctx_data_ptr, gr_ctx_fmpz_mod_set_primality, gr_ctx_fq_degree, gr_ctx_fq_order, gr_ctx_fq_prime, gr_ctx_get_real_prec, gr_ctx_get_str, gr_ctx_has_real_prec, gr_ctx_init_complex_acb, gr_ctx_init_complex_algebraic_ca, gr_ctx_init_complex_ca, gr_ctx_init_complex_float_acf, gr_ctx_init_complex_qqbar, gr_ctx_init_dirichlet_group, gr_ctx_init_fmpq, gr_ctx_init_fmpz, gr_ctx_init_fmpz_mod, gr_ctx_init_fmpz_poly, gr_ctx_init_fmpzi, gr_ctx_init_fq, gr_ctx_init_fq_nmod, gr_ctx_init_fq_zech, gr_ctx_init_gr_series, gr_ctx_init_gr_series_mod, gr_ctx_init_matrix_domain, gr_ctx_init_matrix_ring, gr_ctx_init_matrix_space, gr_ctx_init_gr_mpoly, gr_ctx_init_nf, gr_ctx_init_nf_fmpq_poly, gr_ctx_init_nmod, gr_ctx_init_nmod8, gr_ctx_init_nmod32, gr_ctx_init_perm, gr_ctx_init_gr_poly, gr_ctx_init_psl2z, gr_ctx_init_random, gr_ctx_init_real_algebraic_ca, gr_ctx_init_real_arb, gr_ctx_init_real_ca, gr_ctx_init_real_float_arf, gr_ctx_init_real_qqbar, gr_ctx_init_vector_gr_vec, gr_ctx_init_vector_space_gr_vec, gr_ctx_is_algebraically_closed, gr_ctx_is_canonical, gr_ctx_is_commutative_ring, gr_ctx_is_exact, gr_ctx_is_field, gr_ctx_is_finite, gr_ctx_is_finite_characteristic, gr_ctx_is_integral_domain, gr_ctx_is_multiplicative_group, gr_ctx_is_ordered_ring, gr_ctx_is_ring, gr_ctx_is_threadsafe, gr_ctx_is_unique_factorization_domain, gr_ctx_matrix_is_fixed_size, gr_ctx_print, gr_ctx_println, gr_ctx_set_real_prec, gr_ctx_sizeof_ctx, gr_ctx_sizeof_elem, gr_ctx_vector_gr_vec_is_fixed_size, gr_ctx_write, gr_dedekind_eta, gr_dedekind_eta_q, gr_digamma, gr_dilog, gr_dirichlet_beta, gr_dirichlet_chi_fmpz, gr_dirichlet_chi_vec, gr_dirichlet_eta, gr_dirichlet_hardy_theta, gr_dirichlet_hardy_z, gr_dirichlet_l, gr_div, gr_div_fmpq, gr_div_fmpz, gr_div_other, gr_div_si, gr_div_ui, gr_divexact, gr_divexact_fmpq, gr_divexact_fmpz, gr_divexact_other, gr_divexact_si, gr_divexact_ui, gr_divides, gr_dot_other, gr_doublefac, gr_doublefac_ui, gr_eisenstein_e, gr_eisenstein_g, gr_eisenstein_g_vec, gr_elliptic_e, gr_elliptic_e_inc, gr_elliptic_f, gr_elliptic_invariants, gr_elliptic_k, gr_elliptic_pi, gr_elliptic_pi_inc, gr_elliptic_roots, gr_equal, gr_erf, gr_erfc, gr_erfcinv, gr_erfcx, gr_erfi, gr_erfinv, gr_euclidean_div, gr_euclidean_divrem, gr_euclidean_rem, gr_euler, gr_eulernum_fmpz, gr_eulernum_ui, gr_eulernum_vec, gr_eulerpoly_ui, gr_evaluate_fmpz_mpoly_iter, gr_exp, gr_exp10, gr_exp2, gr_exp_integral, gr_exp_integral_ei, gr_exp_pi_i, gr_expm1, gr_fac, gr_fac_fmpz, gr_fac_ui, gr_fac_vec, gr_factor, gr_falling, gr_falling_ui, gr_fib_fmpz, gr_fib_ui, gr_fib_vec, gr_floor, gr_fmms, gr_fmpz_mpoly_evaluate, gr_fmpz_mpoly_evaluate_horner, gr_fmpz_poly_evaluate, gr_fmpz_poly_evaluate_horner, gr_fmpz_poly_evaluate_rectangular, gr_fq_frobenius, gr_fq_is_primitive, gr_fq_multiplicative_order, gr_fq_norm, gr_fq_pth_root, gr_fq_trace, gr_fresnel, gr_fresnel_c, gr_fresnel_s, gr_gamma, gr_gamma_fmpq, gr_gamma_fmpz, gr_gamma_lower, gr_gamma_upper, gr_gcd, gr_gegenbauer_c, gr_gen, gr_generic_acot, gr_generic_acoth, gr_generic_acsc, gr_generic_acsch, gr_generic_add_fmpq, gr_generic_add_fmpz, gr_generic_add_other, gr_generic_add_si, gr_generic_add_ui, gr_generic_addmul, gr_generic_addmul_fmpq, gr_generic_addmul_fmpz, gr_generic_addmul_other, gr_generic_addmul_si, gr_generic_addmul_ui, gr_generic_asec, gr_generic_asech, gr_generic_asin, gr_generic_asinh, gr_generic_atan, gr_generic_atanh, gr_generic_bellnum_fmpz, gr_generic_bellnum_ui, gr_generic_bellnum_vec, gr_generic_bernoulli_fmpz, gr_generic_bernoulli_ui, gr_generic_bernoulli_vec, gr_generic_beta, gr_generic_bin, gr_generic_bin_ui, gr_generic_bin_ui_vec, gr_generic_bin_uiui, gr_generic_bin_vec, gr_generic_chebyshev_t2_fmpz, gr_generic_chebyshev_t_fmpz, gr_generic_chebyshev_u2_fmpz, gr_generic_chebyshev_u_fmpz, gr_generic_cmp, gr_generic_cmp_other, gr_generic_cmpabs, gr_generic_cmpabs_other, gr_generic_cos, gr_generic_ctx_clear, gr_generic_ctx_predicate, gr_generic_ctx_predicate_false, gr_generic_ctx_predicate_true, gr_generic_div_fmpq, gr_generic_div_fmpz, gr_generic_div_other, gr_generic_div_si, gr_generic_div_ui, gr_generic_divexact, gr_generic_doublefac, gr_generic_doublefac_ui, gr_generic_erfcx, gr_generic_eulernum_fmpz, gr_generic_eulernum_ui, gr_generic_eulernum_vec, gr_generic_exp, gr_generic_exp10, gr_generic_exp2, gr_generic_expm1, gr_generic_fac, gr_generic_fac_fmpz, gr_generic_fac_ui, gr_generic_fac_vec, gr_generic_falling, gr_generic_falling_ui, gr_generic_fib2_fmpz, gr_generic_fib_fmpz, gr_generic_fib_ui, gr_generic_fib_vec, gr_generic_get_fmpz_2exp_fmpz, gr_generic_harmonic, gr_generic_harmonic_ui, gr_generic_hilbert_class_poly, gr_generic_inv, gr_generic_is_invertible, gr_generic_is_neg_one, gr_generic_is_one, gr_generic_is_square, gr_generic_is_zero, gr_generic_log, gr_generic_log10, gr_generic_log1p, gr_generic_log2, gr_generic_mul_2exp_fmpz, gr_generic_mul_2exp_si, gr_generic_mul_fmpq, gr_generic_mul_fmpz, gr_generic_mul_other, gr_generic_mul_si, gr_generic_mul_two, gr_generic_mul_ui, gr_generic_mul_ui_via_ZZ, gr_generic_neg_one, gr_generic_other_add, gr_generic_other_add_vec, gr_generic_other_div, gr_generic_other_div_vec, gr_generic_other_divexact_vec, gr_generic_other_mul, gr_generic_other_mul_vec, gr_generic_other_pow, gr_generic_other_pow_vec, gr_generic_other_sub, gr_generic_other_sub_vec, gr_generic_partitions_fmpz, gr_generic_partitions_ui, gr_generic_partitions_vec, gr_generic_pow_fmpq, gr_generic_pow_fmpz, gr_generic_pow_fmpz_binexp, gr_generic_pow_other, gr_generic_pow_si, gr_generic_pow_ui, gr_generic_pow_ui_binexp, gr_generic_randtest_not_zero, gr_generic_rfac, gr_generic_rfac_fmpz, gr_generic_rfac_ui, gr_generic_rfac_vec, gr_generic_rising, gr_generic_rising_ui, gr_generic_rsqrt, gr_generic_scalar_add_vec, gr_generic_scalar_div_vec, gr_generic_scalar_divexact_vec, gr_generic_scalar_mul_vec, gr_generic_scalar_other_add_vec, gr_generic_scalar_other_div_vec, gr_generic_scalar_other_divexact_vec, gr_generic_scalar_other_mul_vec, gr_generic_scalar_other_pow_vec, gr_generic_scalar_other_sub_vec, gr_generic_scalar_pow_vec, gr_generic_scalar_sub_vec, gr_generic_set_fmpq, gr_generic_set_fmpz_2exp_fmpz, gr_generic_set_other, gr_generic_set_shallow, gr_generic_sin, gr_generic_sin_cos, gr_generic_sqr, gr_generic_sqrt, gr_generic_stirling_s1_ui_vec, gr_generic_stirling_s1_uiui, gr_generic_stirling_s1u_ui_vec, gr_generic_stirling_s1u_uiui, gr_generic_stirling_s2_ui_vec, gr_generic_stirling_s2_uiui, gr_generic_sub_fmpq, gr_generic_sub_fmpz, gr_generic_sub_other, gr_generic_sub_si, gr_generic_sub_ui, gr_generic_submul, gr_generic_submul_fmpq, gr_generic_submul_fmpz, gr_generic_submul_other, gr_generic_submul_si, gr_generic_submul_ui, gr_generic_tan, gr_generic_vec_add, gr_generic_vec_add_other, gr_generic_vec_add_scalar, gr_generic_vec_add_scalar_fmpq, gr_generic_vec_add_scalar_fmpz, gr_generic_vec_add_scalar_other, gr_generic_vec_add_scalar_si, gr_generic_vec_add_scalar_ui, gr_generic_vec_clear, gr_generic_vec_div, gr_generic_vec_div_other, gr_generic_vec_div_scalar, gr_generic_vec_div_scalar_fmpq, gr_generic_vec_div_scalar_fmpz, gr_generic_vec_div_scalar_other, gr_generic_vec_div_scalar_si, gr_generic_vec_div_scalar_ui, gr_generic_vec_divexact, gr_generic_vec_divexact_other, gr_generic_vec_divexact_scalar, gr_generic_vec_divexact_scalar_fmpq, gr_generic_vec_divexact_scalar_fmpz, gr_generic_vec_divexact_scalar_other, gr_generic_vec_divexact_scalar_si, gr_generic_vec_divexact_scalar_ui, gr_generic_vec_dot, gr_generic_vec_dot_fmpz, gr_generic_vec_dot_rev, gr_generic_vec_dot_si, gr_generic_vec_dot_ui, gr_generic_vec_equal, gr_generic_vec_init, gr_generic_vec_is_zero, gr_generic_vec_mul, gr_generic_vec_mul_other, gr_generic_vec_mul_scalar, gr_generic_vec_mul_scalar_2exp_si, gr_generic_vec_mul_scalar_fmpq, gr_generic_vec_mul_scalar_fmpz, gr_generic_vec_mul_scalar_other, gr_generic_vec_mul_scalar_si, gr_generic_vec_mul_scalar_ui, gr_generic_vec_neg, gr_generic_vec_normalise, gr_generic_vec_normalise_weak, gr_generic_vec_pow, gr_generic_vec_pow_other, gr_generic_vec_pow_scalar, gr_generic_vec_pow_scalar_fmpq, gr_generic_vec_pow_scalar_fmpz, gr_generic_vec_pow_scalar_other, gr_generic_vec_pow_scalar_si, gr_generic_vec_pow_scalar_ui, gr_generic_vec_reciprocals, gr_generic_vec_scalar_addmul, gr_generic_vec_scalar_addmul_si, gr_generic_vec_scalar_submul, gr_generic_vec_scalar_submul_si, gr_generic_vec_set, gr_generic_vec_set_powers, gr_generic_vec_sub, gr_generic_vec_sub_other, gr_generic_vec_sub_scalar, gr_generic_vec_sub_scalar_fmpq, gr_generic_vec_sub_scalar_fmpz, gr_generic_vec_sub_scalar_other, gr_generic_vec_sub_scalar_si, gr_generic_vec_sub_scalar_ui, gr_generic_vec_swap, gr_generic_vec_zero, gr_generic_write_n, gr_get_d, gr_get_fmpq, gr_get_fmpz, gr_get_fmpz_2exp_fmpz, gr_get_si, gr_get_str, gr_get_str_n, gr_get_ui, gr_glaisher, gr_harmonic, gr_harmonic_ui, gr_heap_clear, gr_heap_clear_vec, gr_heap_init, gr_heap_init_vec, gr_hermite_h, gr_hilbert_class_poly, gr_hurwitz_zeta, gr_hypgeom_0f1, gr_hypgeom_1f1, gr_hypgeom_2f1, gr_hypgeom_pfq, gr_hypgeom_u, gr_i, gr_im, gr_init, gr_inv, gr_is_invertible, gr_is_neg_one, gr_is_one, gr_is_square, gr_is_zero, gr_jacobi_p, gr_jacobi_theta, gr_jacobi_theta_1, gr_jacobi_theta_2, gr_jacobi_theta_3, gr_jacobi_theta_4, gr_khinchin, gr_laguerre_l, gr_lambertw, gr_lambertw_fmpz, gr_lcm, gr_legendre_p, gr_legendre_p_root_ui, gr_legendre_q, gr_lerch_phi, gr_lgamma, gr_log, gr_log10, gr_log1p, gr_log2, gr_log_barnes_g, gr_log_integral, gr_log_pi_i, gr_mat_add, gr_mat_add_scalar, gr_mat_addmul_scalar, gr_mat_adjugate, gr_mat_adjugate_charpoly, gr_mat_adjugate_cofactor, gr_mat_apply_row_similarity, gr_mat_charpoly, gr_mat_charpoly_berkowitz, gr_mat_charpoly_danilevsky, gr_mat_charpoly_faddeev, gr_mat_charpoly_faddeev_bsgs, gr_mat_charpoly_from_hessenberg, gr_mat_charpoly_gauss, gr_mat_charpoly_householder, gr_mat_clear, gr_mat_concat_horizontal, gr_mat_concat_vertical, gr_mat_det, gr_mat_det_berkowitz, gr_mat_det_cofactor, gr_mat_det_fflu, gr_mat_det_generic, gr_mat_det_generic_field, gr_mat_det_generic_integral_domain, gr_mat_det_lu, gr_mat_diag_mul, gr_mat_diagonalization, gr_mat_diagonalization_generic, gr_mat_diagonalization_precomp, gr_mat_div_scalar, gr_mat_eigenvalues, gr_mat_eigenvalues_other, gr_mat_entry_ptr, gr_mat_entry_srcptr, gr_mat_equal, gr_mat_exp, gr_mat_exp_jordan, gr_mat_fflu, gr_mat_find_nonzero_pivot, gr_mat_find_nonzero_pivot_generic, gr_mat_find_nonzero_pivot_large_abs, gr_mat_gr_poly_evaluate, gr_mat_hadamard, gr_mat_hessenberg, gr_mat_hessenberg_gauss, gr_mat_hessenberg_householder, gr_mat_hilbert, gr_mat_init, gr_mat_init_set, gr_mat_inv, gr_mat_invert_cols, gr_mat_invert_rows, gr_mat_is_diagonal, gr_mat_is_empty, gr_mat_is_hessenberg, gr_mat_is_lower_triangular, gr_mat_is_neg_one, gr_mat_is_one, gr_mat_is_scalar, gr_mat_is_square, gr_mat_is_upper_triangular, gr_mat_is_zero, gr_mat_jordan_blocks, gr_mat_jordan_form, gr_mat_jordan_transformation, gr_mat_log, gr_mat_log_jordan, gr_mat_lu, gr_mat_lu_classical, gr_mat_lu_recursive, gr_mat_minpoly_field, gr_mat_mul, gr_mat_mul_classical, gr_mat_mul_diag, gr_mat_mul_generic, gr_mat_mul_scalar, gr_mat_mul_strassen, gr_mat_neg, gr_mat_nonsingular_solve, gr_mat_nonsingular_solve_den, gr_mat_nonsingular_solve_den_fflu, gr_mat_nonsingular_solve_fflu, gr_mat_nonsingular_solve_fflu_precomp, gr_mat_nonsingular_solve_lu, gr_mat_nonsingular_solve_lu_precomp, gr_mat_nonsingular_solve_tril, gr_mat_nonsingular_solve_tril_classical, gr_mat_nonsingular_solve_tril_recursive, gr_mat_nonsingular_solve_triu, gr_mat_nonsingular_solve_triu_classical, gr_mat_nonsingular_solve_triu_recursive, gr_mat_nullspace, gr_mat_one, gr_mat_ones, gr_mat_pascal, gr_mat_print, gr_mat_randops, gr_mat_randpermdiag, gr_mat_randrank, gr_mat_randtest, gr_mat_rank, gr_mat_rank_fflu, gr_mat_rank_lu, gr_mat_reduce_row, gr_mat_rref, gr_mat_rref_den, gr_mat_rref_den_fflu, gr_mat_rref_fflu, gr_mat_rref_lu, gr_mat_set, gr_mat_set_fmpq, gr_mat_set_fmpq_mat, gr_mat_set_fmpz, gr_mat_set_fmpz_mat, gr_mat_set_jordan_blocks, gr_mat_set_scalar, gr_mat_set_si, gr_mat_set_ui, gr_mat_solve_field, gr_mat_sqr, gr_mat_stirling, gr_mat_sub, gr_mat_sub_scalar, gr_mat_submul_scalar, gr_mat_swap, gr_mat_swap_cols, gr_mat_swap_entrywise, gr_mat_swap_rows, gr_mat_trace, gr_mat_trace_prod2, gr_mat_transpose, gr_mat_transpose_resize, gr_mat_window_clear, gr_mat_window_init, gr_mat_write, gr_mat_zero, gr_method_tab_init, gr_modular_delta, gr_modular_j, gr_modular_lambda, gr_mpoly_add, gr_mpoly_assert_canonical, gr_mpoly_clear, gr_mpoly_combine_like_terms, gr_mpoly_equal, gr_mpoly_fit_bits, gr_mpoly_fit_length, gr_mpoly_fit_length_fit_bits, gr_mpoly_fit_length_reset_bits, gr_mpoly_gen, gr_mpoly_get_coeff_scalar_fmpz, gr_mpoly_get_coeff_scalar_ui, gr_mpoly_init, gr_mpoly_init2, gr_mpoly_init3, gr_mpoly_is_canonical, gr_mpoly_is_gen, gr_mpoly_is_one, gr_mpoly_is_zero, gr_mpoly_mul, gr_mpoly_mul_fmpq, gr_mpoly_mul_fmpz, gr_mpoly_mul_johnson, gr_mpoly_mul_monomial, gr_mpoly_mul_scalar, gr_mpoly_mul_si, gr_mpoly_mul_ui, gr_mpoly_neg, gr_mpoly_one, gr_mpoly_print_pretty, gr_mpoly_push_term_scalar_fmpz, gr_mpoly_push_term_scalar_ui, gr_mpoly_randtest_bits, gr_mpoly_randtest_bound, gr_mpoly_set, gr_mpoly_set_coeff_fmpq_fmpz, gr_mpoly_set_coeff_fmpq_ui, gr_mpoly_set_coeff_fmpz_fmpz, gr_mpoly_set_coeff_fmpz_ui, gr_mpoly_set_coeff_scalar_fmpz, gr_mpoly_set_coeff_scalar_ui, gr_mpoly_set_coeff_si_fmpz, gr_mpoly_set_coeff_si_ui, gr_mpoly_set_coeff_ui_fmpz, gr_mpoly_set_coeff_ui_ui, gr_mpoly_set_fmpq, gr_mpoly_set_fmpz, gr_mpoly_set_scalar, gr_mpoly_set_si, gr_mpoly_set_ui, gr_mpoly_sort_terms, gr_mpoly_sub, gr_mpoly_swap, gr_mpoly_write_pretty, gr_mpoly_zero, gr_mul, gr_mul_2exp_fmpz, gr_mul_2exp_si, gr_mul_fmpq, gr_mul_fmpz, gr_mul_other, gr_mul_si, gr_mul_two, gr_mul_ui, gr_neg, gr_neg_one, gr_nint, gr_not_equal, gr_not_implemented, gr_not_in_domain, gr_one, gr_other_add, gr_other_div, gr_other_divexact, gr_other_mul, gr_other_pow, gr_other_sub, gr_partitions_fmpz, gr_partitions_ui, gr_partitions_vec, gr_pi, gr_poly_acos_series, gr_poly_acosh_series, gr_poly_add, gr_poly_add_series, gr_poly_asin_series, gr_poly_asinh_series, gr_poly_atan_series, gr_poly_atanh_series, gr_poly_clear, gr_poly_compose, gr_poly_compose_divconquer, gr_poly_compose_horner, gr_poly_compose_series, gr_poly_compose_series_brent_kung, gr_poly_compose_series_divconquer, gr_poly_compose_series_horner, gr_poly_derivative, gr_poly_div, gr_poly_div_basecase, gr_poly_div_divconquer, gr_poly_div_newton, gr_poly_div_series, gr_poly_div_series_basecase, gr_poly_div_series_invmul, gr_poly_div_series_newton, gr_poly_divrem, gr_poly_divrem_basecase, gr_poly_divrem_divconquer, gr_poly_divrem_newton, gr_poly_entry_ptr, gr_poly_equal, gr_poly_evaluate, gr_poly_evaluate_horner, gr_poly_evaluate_other, gr_poly_evaluate_other_horner, gr_poly_evaluate_other_rectangular, gr_poly_evaluate_rectangular, gr_poly_evaluate_vec_fast, gr_poly_evaluate_vec_iter, gr_poly_exp_series, gr_poly_exp_series_basecase, gr_poly_exp_series_basecase_mul, gr_poly_exp_series_newton, gr_poly_factor_squarefree, gr_poly_fit_length, gr_poly_gcd, gr_poly_gcd_euclidean, gr_poly_gcd_hgcd, gr_poly_gen, gr_poly_get_coeff_scalar, gr_poly_init, gr_poly_init2, gr_poly_integral, gr_poly_inv, gr_poly_inv_series, gr_poly_inv_series_basecase, gr_poly_inv_series_newton, gr_poly_is_gen, gr_poly_is_monic, gr_poly_is_one, gr_poly_is_zero, gr_poly_length, gr_poly_log1p_series, gr_poly_log_series, gr_poly_make_monic, gr_poly_mul, gr_poly_mul_scalar, gr_poly_mullow, gr_poly_neg, gr_poly_neg_one, gr_poly_nth_derivative, gr_poly_one, gr_poly_pow_fmpz, gr_poly_pow_series_fmpq_recurrence, gr_poly_pow_series_ui, gr_poly_pow_series_ui_binexp, gr_poly_pow_ui, gr_poly_pow_ui_binexp, gr_poly_print, gr_poly_randtest, gr_poly_rem, gr_poly_resultant, gr_poly_resultant_euclidean, gr_poly_resultant_hgcd, gr_poly_resultant_small, gr_poly_resultant_sylvester, gr_poly_reverse, gr_poly_roots, gr_poly_roots_other, gr_poly_rsqrt_series, gr_poly_rsqrt_series_basecase, gr_poly_rsqrt_series_miller, gr_poly_rsqrt_series_newton, gr_poly_set, gr_poly_set_coeff_fmpq, gr_poly_set_coeff_fmpz, gr_poly_set_coeff_scalar, gr_poly_set_coeff_si, gr_poly_set_coeff_ui, gr_poly_set_fmpq, gr_poly_set_fmpq_poly, gr_poly_set_fmpz, gr_poly_set_fmpz_poly, gr_poly_set_gr_poly_other, gr_poly_set_scalar, gr_poly_set_si, gr_poly_set_ui, gr_poly_shift_left, gr_poly_shift_right, gr_poly_sin_cos_series_basecase, gr_poly_sin_cos_series_tangent, gr_poly_sqrt_series, gr_poly_sqrt_series_basecase, gr_poly_sqrt_series_miller, gr_poly_sqrt_series_newton, gr_poly_squarefree_part, gr_poly_sub, gr_poly_sub_series, gr_poly_swap, gr_poly_tan_series, gr_poly_tan_series_basecase, gr_poly_tan_series_newton, gr_poly_taylor_shift, gr_poly_taylor_shift_convolution, gr_poly_taylor_shift_divconquer, gr_poly_taylor_shift_horner, gr_poly_truncate, gr_poly_write, gr_poly_xgcd_euclidean, gr_poly_xgcd_hgcd, gr_poly_zero, gr_polygamma, gr_polylog, gr_pow, gr_pow_fmpq, gr_pow_fmpz, gr_pow_other, gr_pow_si, gr_pow_ui, gr_print, gr_println, gr_randtest, gr_randtest_not_zero, gr_randtest_small, gr_re, gr_rfac, gr_rfac_fmpz, gr_rfac_ui, gr_rfac_vec, gr_rgamma, gr_riemann_xi, gr_rising, gr_rising_ui, gr_rising_ui_forward, gr_rsqrt, gr_sec, gr_sec_pi, gr_sech, gr_series_acos, gr_series_acosh, gr_series_add, gr_series_agm1, gr_series_airy, gr_series_airy_ai, gr_series_airy_ai_prime, gr_series_airy_bi, gr_series_airy_bi_prime, gr_series_asin, gr_series_asinh, gr_series_atan, gr_series_atanh, gr_series_beta_lower, gr_series_clear, gr_series_cos_integral, gr_series_cosh_integral, gr_series_digamma, gr_series_dirichlet_hardy_theta, gr_series_dirichlet_hardy_z, gr_series_dirichlet_l, gr_series_div, gr_series_elliptic_k, gr_series_equal, gr_series_erf, gr_series_erfc, gr_series_erfi, gr_series_exp, gr_series_exp_integral_ei, gr_series_fresnel, gr_series_fresnel_c, gr_series_fresnel_s, gr_series_gamma, gr_series_gamma_lower, gr_series_gamma_upper, gr_series_gen, gr_series_hurwitz_zeta, gr_series_hypgeom_pfq, gr_series_init, gr_series_inv, gr_series_is_one, gr_series_is_zero, gr_series_jacobi_theta, gr_series_jacobi_theta_1, gr_series_jacobi_theta_2, gr_series_jacobi_theta_3, gr_series_jacobi_theta_4, gr_series_lgamma, gr_series_log, gr_series_log_integral, gr_series_make_exact, gr_series_mul, gr_series_neg, gr_series_one, gr_series_polylog, gr_series_randtest, gr_series_rgamma, gr_series_rsqrt, gr_series_set, gr_series_set_fmpq, gr_series_set_fmpz, gr_series_set_gr_poly, gr_series_set_scalar, gr_series_set_si, gr_series_set_ui, gr_series_sin_integral, gr_series_sinh_integral, gr_series_sqrt, gr_series_sub, gr_series_swap, gr_series_tan, gr_series_weierstrass_p, gr_series_write, gr_series_zero, gr_set, gr_set_d, gr_set_fmpq, gr_set_fmpz, gr_set_fmpz_2exp_fmpz, gr_set_other, gr_set_shallow, gr_set_si, gr_set_str, gr_set_ui, gr_sgn, gr_sin, gr_sin_cos, gr_sin_cos_pi, gr_sin_integral, gr_sin_pi, gr_sinc, gr_sinc_pi, gr_sinh, gr_sinh_cosh, gr_sinh_integral, gr_spherical_y_si, gr_sqr, gr_sqrt, gr_stieltjes, gr_stirling_s1_ui_vec, gr_stirling_s1_uiui, gr_stirling_s1u_ui_vec, gr_stirling_s1u_uiui, gr_stirling_s2_ui_vec, gr_stirling_s2_uiui, gr_stream_init_file, gr_stream_init_str, gr_stream_write, gr_stream_write_fmpz, gr_stream_write_free, gr_stream_write_si, gr_stream_write_ui, gr_sub, gr_sub_fmpq, gr_sub_fmpz, gr_sub_other, gr_sub_si, gr_sub_ui, gr_submul, gr_submul_fmpq, gr_submul_fmpz, gr_submul_other, gr_submul_si, gr_submul_ui, gr_swap, gr_swap2, gr_tan, gr_tan_pi, gr_tanh, gr_test_add_aliasing, gr_test_add_associative, gr_test_add_commutative, gr_test_add_type_variants, gr_test_addmul_submul, gr_test_addmul_type_variants, gr_test_binary_op_aliasing, gr_test_binary_op_associative, gr_test_binary_op_commutative, gr_test_binary_op_left_distributive, gr_test_binary_op_right_distributive, gr_test_binary_op_type_variants, gr_test_complex_parts, gr_test_div_right_distributive, gr_test_div_then_mul, gr_test_div_type_variants, gr_test_divexact, gr_test_divexact_type_variants, gr_test_equal, gr_test_field, gr_test_get_fmpq, gr_test_get_fmpz, gr_test_get_fmpz_2exp_fmpz, gr_test_get_si, gr_test_get_ui, gr_test_init_clear, gr_test_integral_domain, gr_test_inv_involution, gr_test_inv_multiplication, gr_test_iter, gr_test_mat_mul_classical_associative, gr_test_mul_2exp_fmpz, gr_test_mul_2exp_si, gr_test_mul_aliasing, gr_test_mul_associative, gr_test_mul_commutative, gr_test_mul_left_distributive, gr_test_mul_right_distributive, gr_test_mul_then_div, gr_test_mul_type_variants, gr_test_multiplicative_group, gr_test_neg, gr_test_one, gr_test_ordered_ring_cmp, gr_test_ordered_ring_cmpabs, gr_test_pow_fmpz_exponent_addition, gr_test_pow_ui_aliasing, gr_test_pow_ui_base_multiplication, gr_test_pow_ui_base_scalar_multiplication, gr_test_pow_ui_exponent_addition, gr_test_randtest_not_zero, gr_test_ring, gr_test_rsqrt, gr_test_set_fmpq, gr_test_set_fmpz, gr_test_set_si, gr_test_set_ui, gr_test_sqrt, gr_test_sub_aliasing, gr_test_sub_equal_neg_add, gr_test_sub_type_variants, gr_test_submul_type_variants, gr_test_swap, gr_test_vec_add, gr_test_vec_binary_op, gr_test_vec_div, gr_test_vec_divexact, gr_test_vec_dot, gr_test_vec_mul, gr_test_vec_pow, gr_test_vec_sub, gr_test_zero_one, gr_trunc, gr_vec_append, gr_vec_clear, gr_vec_entry_ptr, gr_vec_entry_srcptr, gr_vec_fit_length, gr_vec_init, gr_vec_length, gr_vec_print, gr_vec_set, gr_vec_set_length, gr_vec_write, gr_weierstrass_p, gr_weierstrass_p_inv, gr_weierstrass_p_prime, gr_weierstrass_sigma, gr_weierstrass_zeta, gr_write, gr_write_n, gr_zero, gr_zeta, gr_zeta_nzeros, gr_zeta_ui, gr_zeta_zero, gr_zeta_zero_vec`` * ``gr_pos_inf, gr_neg_inf, gr_uinf, gr_undefined, gr_unknown, gr_arg, gr_ctx_init_complex_extended_ca, gr_poly_divexact_basecase_bidirectional, gr_poly_divexact_bidirectional, gr_poly_divexact_basecase, gr_poly_is_scalar, gr_poly_div_series_divconquer, gr_poly_divexact_series_basecase`` * ``nmod_mat_fprint_pretty, nmod_mat_print, nmod_mat_fprint, nmod_poly_is_monic`` * ``nmod_poly_mat_set_trunc, nmod_poly_mat_truncate, nmod_poly_mat_shift_left, nmod_poly_mat_shift_right, nmod_poly_mat_get_coeff_mat, nmod_poly_mat_set_coeff_mat, nmod_poly_mat_set_nmod_mat, nmod_poly_mat_equal_nmod_mat, nmod_poly_mat_degree`` * ``qqbar_set_fmpzi`` * ``fmpq_mpoly_push_term_fmpq_ffmpz, fmpq_mpoly_push_term_fmpz_ffmpz, fmpq_mpoly_push_term_ui_ffmpz, fmpq_mpoly_push_term_si_ffmpz, fmpz_mod_mpoly_push_term_fmpz_ffmpz, fmpz_mod_mpoly_push_term_ui_ffmpz, fmpz_mod_mpoly_push_term_si_ffmpz, fmpz_mpoly_push_term_fmpz_ffmpz, fmpz_mpoly_push_term_ui_ffmpz, fmpz_mpoly_push_term_si_ffmpz, fq_nmod_mpoly_push_term_fq_nmod_ffmpz, nmod_mpoly_push_term_ui_ffmpz, fmpq_mpoly_push_term_fmpz_ffmpz, fmpq_mpoly_push_term_fmpq_ffmpz, fmpq_mpoly_push_term_ui_ffmpz, fmpq_mpoly_push_term_si_ffmpz, fmpq_mpoly_push_term_fmpq_ffmpz`` List of removals ................ * The following functions that were present in FLINT 2.9, Arb 2.23 or Calcium 0.4 have been removed, deprecated, or replaced. Most are algorithms obsoleted by new gr implementations, functions dealing with removed types (fmpr) or GMP types (mpz, etc.), and internal functions that are no longer needed. * ``__fmpz_clear, __fmpz_eq, __fmpz_gt, __fmpz_gte, __fmpz_init, __fmpz_init_set, __fmpz_init_set_ui, __fmpz_lt, __fmpz_lte, __fmpz_neg, __fmpz_neq, __fmpz_set_si, __fmpz_set_ui`` * ``__fmpz_mod_poly_div_divconquer, __fmpz_mod_poly_divrem_divconquer, __fq_nmod_poly_divrem_divconquer, __fq_poly_divrem_divconquer, __fq_zech_poly_divrem_divconquer`` * ``__nmod_poly_div_divconquer, __nmod_poly_divrem_divconquer, __nmod_poly_invsqrt_series_prealloc`` * ``_acb_poly_compose_axnc, _acb_poly_compose_divconquer, _acb_poly_compose_horner, _acb_poly_compose_series_brent_kung, _acb_poly_compose_series_horner, _acb_poly_sin_cos_series_basecase, _acb_poly_sin_cos_series_tangent, _acb_poly_taylor_shift_convolution, _acb_poly_taylor_shift_divconquer, _acb_poly_taylor_shift_horner`` * ``acb_rising_ui_bs, acb_rising_ui_rs, acb_rising_ui_rec`` * ``_arb_poly_compose_axnc, _arb_poly_compose_divconquer, _arb_poly_compose_horner, _arb_poly_compose_series_brent_kung, _arb_poly_compose_series_horner, _arb_poly_sin_cos_series_basecase, _arb_poly_sin_cos_series_tangent, _arb_poly_taylor_shift_convolution, _arb_poly_taylor_shift_divconquer, _arb_poly_taylor_shift_horner`` * ``arb_rising_ui_bs, arb_rising_ui_rs, arb_rising_ui_rec, arb_rising2_ui_bs, arb_rising2_ui_rs, arb_rising2_ui`` * ``_arith_bernoulli_number_vec_zeta, _arith_bernoulli_number_zeta, _arith_cos_minpoly, _arith_euler_number_zeta, _arith_number_of_partitions_mpfr`` * ``_ca_poly_atan_series, _ca_poly_compose_divconquer, _ca_poly_compose_horner`` * ``_fmpq_poly_set_array_mpq`` * ``_fmpr_add_1x1, _fmpr_add_eps, _fmpr_add_mpn, _fmpr_mul_1x1, _fmpr_mul_mpn, _fmpr_normalise_naive, _fmpr_set_round, _fmpr_set_round_mpn`` * ``_fmpz_deprecated_multi_crt_local_size, _fmpz_deprecated_multi_crt_run, _fmpz_deprecated_multi_crt_run_p, _fmpz_mod_poly_compose_divconquer, _fmpz_mod_poly_compose_divconquer_recursive, _fmpz_mod_poly_compose_horner, _fmpz_mod_poly_div_basecase, _fmpz_mod_poly_div_divconquer, _fmpz_mod_poly_div_divconquer_recursive, _fmpz_mod_poly_div_newton, _fmpz_mod_poly_divrem_divconquer, _fmpz_mod_poly_divrem_divconquer_recursive, _fmpz_mod_poly_gcd_cofactors, _fmpz_mod_poly_gcd_euclidean, _fmpz_mod_poly_gcd_hgcd, _fmpz_mod_poly_hgcd_recursive, _fmpz_mod_poly_hgcd_recursive_iter, _fmpz_mod_poly_hgcd_res, _fmpz_mod_poly_xgcd_euclidean, _fmpz_mod_poly_xgcd_hgcd, _fmpz_poly_evaluate_mpfr`` * ``_fmpz_ui_pow_ui, _fmpz_vec_get_mpf_vec`` * ``_fq_nmod_poly_compose_divconquer, _fq_nmod_poly_compose_horner, _fq_nmod_poly_div_basecase, _fq_nmod_poly_divrem_basecase, _fq_nmod_poly_divrem_divconquer, _fq_nmod_poly_divrem_divconquer_recursive, _fq_nmod_poly_gcd_euclidean, _fq_nmod_poly_gcd_hgcd, _fq_nmod_poly_hgcd, _fq_nmod_poly_hgcd_recursive, _fq_nmod_poly_hgcd_recursive_iter, _fq_nmod_poly_xgcd_euclidean`` * ``_fq_poly_compose_divconquer, _fq_poly_compose_horner, _fq_poly_div_basecase, _fq_poly_divrem_basecase, _fq_poly_divrem_divconquer, _fq_poly_divrem_divconquer_recursive, _fq_poly_gcd_euclidean, _fq_poly_gcd_hgcd, _fq_poly_hgcd, _fq_poly_hgcd_recursive, _fq_poly_hgcd_recursive_iter, _fq_poly_xgcd_euclidean`` * ``_fq_zech_poly_compose_divconquer, _fq_zech_poly_compose_horner, _fq_zech_poly_div_basecase, _fq_zech_poly_divrem_basecase, _fq_zech_poly_divrem_divconquer, _fq_zech_poly_divrem_divconquer_recursive, _fq_zech_poly_gcd_euclidean, _fq_zech_poly_gcd_hgcd, _fq_zech_poly_hgcd, _fq_zech_poly_hgcd_recursive, _fq_zech_poly_hgcd_recursive_iter, _fq_zech_poly_xgcd_euclidean`` * ``_nmod_mat_set_mod`` * ``_nmod_poly_compose_divconquer, _nmod_poly_compose_series_brent_kung, _nmod_poly_compose_series_divconquer, _nmod_poly_compose_series_horner, _nmod_poly_div_basecase, _nmod_poly_div_basecase_1, _nmod_poly_div_basecase_2, _nmod_poly_div_basecase_3, _nmod_poly_div_divconquer, _nmod_poly_div_divconquer_recursive, _nmod_poly_div_newton, _nmod_poly_divrem_basecase_1, _nmod_poly_divrem_basecase_2, _nmod_poly_divrem_basecase_3, _nmod_poly_divrem_divconquer, _nmod_poly_divrem_divconquer_recursive, _nmod_poly_divrem_newton, _nmod_poly_divrem_q0, _nmod_poly_divrem_q1, _nmod_poly_exp_series_basecase, _nmod_poly_exp_series_monomial_ui, _nmod_poly_exp_series_newton, _nmod_poly_hgcd_recursive, _nmod_poly_hgcd_recursive_iter, _nmod_poly_hgcd_res, _nmod_poly_integral_offset, _nmod_poly_log_series_monomial_ui, _nmod_poly_rem_basecase, _nmod_poly_rem_basecase_1, _nmod_poly_rem_basecase_2, _nmod_poly_rem_basecase_3`` * ``acb_poly_compose_divconquer, acb_poly_compose_horner, acb_poly_compose_series_brent_kung, acb_poly_compose_series_horner, acb_poly_sin_cos_series_basecase, acb_poly_sin_cos_series_tangent, acb_poly_taylor_shift_convolution, acb_poly_taylor_shift_divconquer, acb_poly_taylor_shift_horner`` * ``arb_flint_get_num_available_threads`` * ``arb_poly_compose_divconquer, arb_poly_compose_horner, arb_poly_compose_series_brent_kung, arb_poly_compose_series_horner, arb_poly_sin_cos_series_basecase, arb_poly_sin_cos_series_tangent, arb_poly_taylor_shift_convolution, arb_poly_taylor_shift_divconquer, arb_poly_taylor_shift_horner`` * ``arb_test_multiplier`` * ``arb_thread_pool_num_available`` * ``arf_get_fmpr, arf_set_fmpr`` * ``arith_cos_minpoly, arith_number_of_partitions_mpfr`` * ``ca_mat_transpose_resize, ca_poly_atan_series, ca_poly_compose_divconquer, ca_poly_compose_horner, calcium_test_multiplier`` * ``cos_minpoly, cos_pi_pq`` * ``fmpq_poly_evaluate_mpq, fmpq_poly_evaluate_mpz, fmpq_poly_get_coeff_mpq, fmpq_poly_scalar_div_mpq, fmpq_poly_scalar_div_mpz, fmpq_poly_scalar_mul_mpq, fmpq_poly_scalar_mul_mpz, fmpq_poly_set_array_mpq, fmpq_poly_set_coeff_mpq, fmpq_poly_set_coeff_mpz, fmpq_poly_set_mpq, fmpq_poly_set_mpz`` * ``fmpr_add, fmpr_add_fmpz, fmpr_add_naive, fmpr_add_si, fmpr_add_ui, fmpr_addmul, fmpr_addmul_fmpz, fmpr_addmul_si, fmpr_addmul_ui, fmpr_check_ulp, fmpr_cmp, fmpr_cmp_2exp_si, fmpr_cmpabs, fmpr_cmpabs_2exp_si, fmpr_cmpabs_ui, fmpr_div, fmpr_div_fmpz, fmpr_div_si, fmpr_div_ui, fmpr_exp, fmpr_expm1, fmpr_fmpz_div, fmpr_fmpz_div_fmpz, fmpr_get_d, fmpr_get_fmpq, fmpr_get_fmpz, fmpr_get_fmpz_2exp, fmpr_get_fmpz_fixed_fmpz, fmpr_get_fmpz_fixed_si, fmpr_get_mpfr, fmpr_get_si, fmpr_log, fmpr_log1p, fmpr_mul, fmpr_mul_fmpz, fmpr_mul_naive, fmpr_mul_si, fmpr_mul_ui, fmpr_pow_sloppy_fmpz, fmpr_pow_sloppy_si, fmpr_pow_sloppy_ui, fmpr_print, fmpr_printd, fmpr_randtest, fmpr_randtest_not_zero, fmpr_randtest_special, fmpr_root, fmpr_rsqrt, fmpr_set_d, fmpr_set_fmpq, fmpr_set_fmpz_2exp, fmpr_set_mpfr, fmpr_set_round_ui_2exp_fmpz, fmpr_set_round_uiui_2exp_fmpz, fmpr_si_div, fmpr_sqrt, fmpr_sub, fmpr_sub_fmpz, fmpr_sub_si, fmpr_sub_ui, fmpr_submul, fmpr_submul_fmpz, fmpr_submul_si, fmpr_submul_ui, fmpr_ui_div, fmpr_ulp`` * ``fmpz_deprecated_multi_crt, fmpz_deprecated_multi_crt_clear, fmpz_deprecated_multi_crt_init, fmpz_deprecated_multi_crt_precomp, fmpz_deprecated_multi_crt_precomp_p, fmpz_deprecated_multi_crt_precompute, fmpz_deprecated_multi_crt_precompute_p`` * ``fmpz_mat_col_equal, fmpz_mat_get_mpf_mat, fmpz_mat_row_equal`` * ``fmpz_mod_ctx_get_modulus_mpz_read_only`` * ``fmpz_mod_poly_compose_divconquer, fmpz_mod_poly_compose_horner, fmpz_mod_poly_div_basecase, fmpz_mod_poly_div_divconquer, fmpz_mod_poly_div_newton, fmpz_mod_poly_divrem_divconquer, fmpz_mod_poly_gcd_euclidean, fmpz_mod_poly_gcd_hgcd, fmpz_mod_poly_get_coeff_mpz, fmpz_mod_poly_set_coeff_mpz, fmpz_mod_poly_xgcd_euclidean, fmpz_mod_poly_xgcd_hgcd`` * ``fmpz_poly_evaluate_mpfr, fmpz_poly_evaluate_mpq, fmpz_poly_get_coeff_mpz, fmpz_poly_q_evaluate, fmpz_poly_q_scalar_div_mpq, fmpz_poly_q_scalar_div_mpz, fmpz_poly_q_scalar_mul_mpq, fmpz_poly_q_scalar_mul_mpz, fmpz_poly_scalar_divexact_mpz, fmpz_poly_scalar_fdiv_mpz, fmpz_poly_scalar_mul_mpz, fmpz_poly_set_coeff_mpz, fmpz_poly_set_mpz`` * ``fq_nmod_poly_compose_divconquer, fq_nmod_poly_compose_horner, fq_nmod_poly_divrem_basecase, fq_nmod_poly_divrem_divconquer, fq_nmod_poly_gcd_euclidean, fq_nmod_poly_gcd_hgcd, fq_nmod_poly_xgcd_euclidean, fq_poly_compose_divconquer, fq_poly_compose_horner, fq_poly_divrem_basecase, fq_poly_divrem_divconquer, fq_poly_gcd_euclidean, fq_poly_gcd_hgcd, fq_poly_xgcd_euclidean, fq_zech_poly_compose_divconquer, fq_zech_poly_compose_horner, fq_zech_poly_divrem_basecase, fq_zech_poly_divrem_divconquer, fq_zech_poly_gcd_euclidean, fq_zech_poly_gcd_hgcd, fq_zech_poly_xgcd_euclidean`` * ``mag_get_fmpr, mag_set_fmpr`` * ``mpfr_cos_pi_pq, mpfr_zeta_inv_euler_product`` * ``nmod_poly_compose_divconquer, nmod_poly_compose_series_brent_kung, nmod_poly_compose_series_divconquer, nmod_poly_compose_series_horner, nmod_poly_div_basecase, nmod_poly_div_divconquer, nmod_poly_div_newton, nmod_poly_divrem_divconquer, nmod_poly_divrem_newton, nmod_poly_exp_series_basecase, nmod_poly_exp_series_monomial_ui, nmod_poly_factor_get_nmod_poly, nmod_poly_log_series_monomial_ui, nmod_poly_rem_basecase, nmod_poly_set_fmpz_poly, sinh_cosh_divk_precomp`` * ``_nmod_poly_powmod_mpz_binexp, nmod_poly_powmod_mpz_binexp, _nmod_poly_powmod_mpz_binexp_preinv, nmod_poly_powmod_mpz_binexp_preinv, _nmod_poly_powmod_mpz_binexp, nmod_poly_powmod_mpz_binexp, _nmod_poly_powmod_mpz_binexp_preinv, nmod_poly_powmod_mpz_binexp_preinv`` 2022-06-24 -- FLINT 2.9.0 ------------------------------------------------------------------------------- * Add fmpz_mod_poly_div function * Add _flint_get_memory function * Add Eulerian polynomials * Support "multivariate" polynomials with zero variables * Improve Stirling numbers of both kinds * Speed up numerous fmpz functions for small inputs * Improve Bell numbers * Speedups to nmod arithmetic * Improve nmod_mat LU decomposition * Fully separate nmod module from nmod_vec * Speed up Hermite polynomials * Add n-th derivative for Z[x] and Q[x] * Improve fq_default module (nmod is now used where optimal) * Add sqrt functions for numerous polynomial/series modules and finite fields * Add FFT matrix multiplication * Improve CI * Improve LLL for general use * Add matrix-vector products over Q * Add can_solve function for fmpq_mat, handling non-square/singular matrices * Document fmpz_mod_vec module * Fix and document qadic_sqrt function * Add parallel programming helpers 2022-04-25 -- FLINT 2.8.5 ------------------------------------------------------------------------------- * Fix a serious bug in LLL 2021-11-17 -- FLINT 2.8.4 ------------------------------------------------------------------------------- * Fix a serious bug in fmpz_mod_poly_xgcd for polynomials of large length * Fix an assertion failure in fmpz_mat_solve_fflu (only relevant if asserts enabled) * Fix some bugs on 32 bit machines * Work around a compiler bug on Apple M1 * Fix bug in nmod_mpoly_factor (returned 0 for some factorisations) * Fix some documentation build errors and some doc formatting issues 2021-11-03 -- FLINT 2.8.3 ------------------------------------------------------------------------------- * Fix a serious bug in nmod_poly_xgcd_hgcd, nmod_poly_xgcd, fmpz_poly_xgcd_modular, fmpz_poly_xgcd, fmpq_poly_xgcd for polynomials of length >= 340. * Fix some copyright assignments * Fix some documentation errors 2021-10-15 -- FLINT 2.8.2 ------------------------------------------------------------------------------- * Fix an issue with --disable-dependency-tracking on some distributions 2021-10-01 -- FLINT 2.8.1 ------------------------------------------------------------------------------- * Numerous bug fixes * Adjust soname on android * Allow disabling of dependency tracking 2021-07-23 -- FLINT 2.8.0 ------------------------------------------------------------------------------- * New fq_default module which combines existing finite fields * Speedups for linear algebra when using BLAS and/or threading * New series expansions with coefficients in QQ * Faster CRT * New fmpz_mod_mpoly module * Polynomial factoring improvements over ZZ * Fixed bugs in gmpcompat on Windows * Add fmpz_mat_can_solve_fflu and fmpz_mat_can_solve * Cleanup of the nmod_poly and nmod_poly_factor code * Implement nmod_mat_det_howell * Add fmpz_mod_poly_divides, fmpz_divides, n_divides, nmod_poly_divides * Interface for multiplying matrices by vectors and arrays * Nearest Euclidean division * Subresultant GCD * XGCD over ZZ with canonical Bezout coefficients * Add fmpz_mpoly resultant and discriminant * Add deprecations list * Add FLINT_SGN macro * Speedups for series computations * Switch to GitHub Actions for CI * Improve Taylor shift * Numerous bug fixes and speedups 2021-01-18 -- FLINT 2.7.1 ------------------------------------------------------------------------------- * Fix build bug due to missing test files * Fix bug in fmpz_mod_poly_factor when there are more than five factors * Fix issue when using MPIR 3.0.0 on Win64 with command line build * Fix bug in fmpz_mod_poly_div_series * Fix some broken asserts * Support standard GNU installation directories in CMake build * Fix stack overflow with ICC 2020-12-18 -- FLINT 2.7.0 ------------------------------------------------------------------------------- * Multivariate factorisation * Square root and square testing for finite fields * Square root and square testing for multivariates * Zassenhaus factoring speedups (incl. degree pruning) * Fast factorisation of cubic univariate polynomials * Add context objects to fmpz_mod_poly functions * Use BLAS for matrix multiplication over Z/nZ (small n) * Linear solving for non-square/singular matrices (can_solve) * Speed up factorisation over Z/nZ (for multiprecision n) 2020-08-12 -- FLINT 2.6.3 ------------------------------------------------------------------------------- * Fix a bug in generator of finite field in characteristic 2 * Allow Flint to work with GMP 6.1.2 and 6.2.0 interchangeably * Fix some old license headers 2020-07-31 -- FLINT 2.6.2 ------------------------------------------------------------------------------- * Fix for choice of generator in an fq finite field of degree one * Fix an incorrectly written test 2020-07-23 -- FLINT 2.6.1 ------------------------------------------------------------------------------- * Fix issues on Debian major architectures * Fix numerous reported bugs (mpoly, fq_poly, mpn_mul_1, mod 2 code, etc.) 2020-06-05 -- FLINT 2.6.0 ------------------------------------------------------------------------------- * multivariate polynomials over most standard rings (sparse distributed) * APR-CL primality proving * elliptic curve integer factoring * minpoly and charpoly * improved quadratic sieve for integer factoring * embeddings of finite fields * pollard rho integer factoring * p+1 integer factoring * best of breed smooth integer factoring routine * best of breed general integer factoring routine * howell and strong echelon form * large speedups for solve and hence inverse over Z and Q * randprime and nextprime functions * pernet-stein HNF improvements * moller-granlund precomputed inverses * resultant_modular_div * fibonacci polynomials * exception mechanism/flint_abort * sqrt of series and polynomials * division of series over Z * power sums * improved base cases of various power series functions * ability to switch memory allocators * fast recurrence for Hermite polys * shifted Legendre polynomials * Laguerre polynomials * Gegenbauer polys * sphinx documentation * van hoeij with gradual feeding implementation of polynomial factoring over Z * perfect power detection * divisibility testing for polynomials * fast block based memory manager for bundling fmpz allocations * uniform random generation * CMake build system * linear algebra speedups when everything can be kept in longs * nmod module for integers mod (small) n * fmpz_mod_mat module for matrices over integers mod multiprecision n * kronecker product (tensor product) * random primitive polys (for finite fields) * thread pool implementation * threading of FFT for integer and polynomial multiplication over Z * threading of quadratic sieve for integer factoring * improved threading of factoring of polynomials mod p * threading for multivariate polynomial multiplication, division and GCD * threaded multiplication of matrices mod p * Berlekamp-Massey (nmod) * fmpz_mod module for integers mod multiprecision n * Pohlig-Hellman (discrete log) * farey_neighbours * remove openMP option * additional integer division variants * speed up mpn_mulmod_preinv * fft precaching * cyclotomic polynomial detection * polynomial root finding over finite fields * GMP 6.2 support * MPIR 3.0.0 support * many small speedups and additional convenience functions added 2015-08-13 -- FLINT 2.5.2 ------------------------------------------------------------------------------- * Fix further issues with soname versioning and ldconfig * Fix a bug when using GMP instead of MPIR. 2015-08-12 -- FLINT 2.5.1 ------------------------------------------------------------------------------- * Fix some build bugs related to soname versioning and ldconfig * Fix issue with Windows MSVC build 2015-08-07 -- FLINT 2.5.0 ------------------------------------------------------------------------------- * LLL (rational, Nguyen-Stehle, from Gram matrix, with_removal, Storjohann/ULLL) * Hermite normal form (naive, xgcd, Domich-Kannan-Trotter, Kannan-Bachem, Pernet-Stein) * Smith normal form (diagonal, Kannan-Bachem, Iliopoulos) * Paterson-Stockmeyer algorithm * modular resultant * hgcd resultant * polynomial discriminant * multithreaded multimodular Taylor shift * multithreaded Brent-Kung composition * multithreaded Kaltofen-Shoup distinct degree factorisation * multiplication based reduced row echelon form * place inline functions in library for foreign function interfaces * Primality tests for large integers (Pocklington, Morrison) * Probable prime tests for large integers (Lucas, Baillie-PSW, strong-psp, Brillhart-Lehmer-Selfridge) * CRT for large integers * Dixon algorithm for nullspace * Brent-Kung composition in irreducibility and distinct degree factorisation * floating point QR decomposition * Schwarz-Rutishauser Gram-Schmidt algorithm * Ogita-Rump-Oishi dot product * matrix window functions * MSVC support (Brian Gladman) * fast cube/nth-root (Newton, Kahan, magic number, Chebyshev) * Bodrato matrix squaring * matrix concatenation functions * matrix content * faster n_gcd * faster n_sqrtmod and fmpz_sqrtmod * additional functions for returning factor of modulus in polys over Z/nZ * Hadamard matrix construction * series addition/subtraction * faster prime_pi bounds * speedup creation of sparse polynomials * speedup n_isprime n_nextprime * speedup n_isprime_pocklington * speedups to fmpq_poly and fmpz_poly arithmetic * speedup polynomial irreducibility testing over Z/pZ * speedup of rank computation over ZZ * made CPimport compile time dependency only * teach flint_printf/sprintf about explicit width format specifiers * support relative paths in configure * library soname versioning * ARM64 patches * Support MSYS2 * Progress towards supporting MIPS64 * Fix a serious bug in fmpz_poly_signature ????-??-?? -- FLINT 2.4.5 ------------------------------------------------------------------------------- * fixed a severe bug in flint's fmpz_poly_gcd_heuristic, reported by Anton Mellit. ????-??-?? -- FLINT 2.4.4 ------------------------------------------------------------------------------- * fixed a severe bug in flint's primality code (n_is_prime() affecting n_factor()) 2014-04-01 -- FLINT 2.4.3 ------------------------------------------------------------------------------- * Fix a linker issue on Mac OSX. 2014-03-11 -- FLINT 2.4.2 ------------------------------------------------------------------------------- * Fix bug in ARM assembly 2012-11-20 -- FLINT 2.4 ------------------------------------------------------------------------------- * C++ expressions template wrapper * Fast factorisation of polynomials over Z/nZ * improved p-adics * polynomials/matrices over p-adics * qadics * Finite fields (small and large F_q), polynomials/matrices over F_q * Finite fields with Zech logarithm representation * Fast factorisation of polynomials over F_q * Faster Brent-Kung modular composition * New prime sieving code * Lambert-W function * Precomputed inverses for polynomials and large integers * Williams' P+1 integer factoring algorithm * Harvey's KS2/KS4 polynomial multiplication * Faster primality testing up to 64 bits * Support for Cygwin64 and MinGW64 * Support for Clang * Support for GMP * Support for Boehm-Demers-Weiser GC * Support for flint extension modules 2012-07-01 -- FLINT 2.3 ------------------------------------------------------------------------------- * general * many changes to the build system * added NTL interface * switched to custom memory allocation functions flint_malloc etc * in addition to the entries below, fixed a large number of memory leaks, problems with the test code, and bugs in corner cases of various functions * added _fmpz_cleanup_mpz_content as an alternative to _fmpz_cleanup * support MinGW32 * support Cygwin * bugfix on ia64 * support sparc32/sparc64 * support OSX * support Solaris, NetBSD, OpenBSD, etc (if bash, GNU Make present) * ulong_extras * implemented the improved Lehman algorithm * added n_jacobi_unsigned to allow n > WORD_MAX * fixed n_sqrtmod for n > WORD_MAX * fixed bug causing n_sqrtmod to hang * added sublinear algorithm for computing factorials mod p * added n_sqrtmod_primepow, n_sqrtmodn and associated functions for computing square roots modulo composite integers * fixed bugs in n_is_prime_pocklington * fixed UWORD_MAX case in powmod and powmod2 * fixed problems with the random number generators * fixed rare bug in n_mod_precomp * fixed rare bug in n_is_prime_pseudosquare * long_extras * added z_sizeinbase * qsieve * new module implementing a quadratic sieve for numbers up to two limbs * fft * new module providing an efficient Schoenhage-Strassen FFT * longlong * added assembly code for ia64 and ARM * fixed bug in fallback version of add_sssaaaaaa * fmpz * added fmpz_fib_ui * added double precision natural logarithm * added fmpz_val2 for 2-valuation * added mul_2exp, div_2exp, cdiv_q_2exp, tdiv_q_2exp, fdiv_r, fdiv_r_2exp, tdiv_ui, mul_tdiv_q_2exp * added get_d/set_d * added fmpz_divisible, divisible_si * optimised fmpz_powm and fmpz_powm_ui * added clog, clog_ui, flog, flog_ui for computing logarithms * added abs_lbound_ui_2exp, ubound_ui_2exp * added fmpz_rfac_ui and fmpz_rfac_uiui for rising factorials * added functions to obtain read-only fmpz_t's from mpz_t's * added fmpz_init_set, init_set_ui * added fmpz_gcdinv * added fmpz_is_square * added fmpz_tstbit, setbit, clrbit, complement, combit, and, or, xor, popcnt * added a sign flag for CRT instead of using separate methods * fixed bugs in fmpz_sqrtmod * fixed a bug in fmpz_bit_unpack that could cause corruption of the global fmpz array when compiled in single mode * fixed a bug in fmpz_sub_ui that could cause memory corruption * fmpz_vec * added functions for obtaining the largest absolute value coefficient * added functions for computing the sum and product of an integer vector * made max_bits much faster * added _fmpz_vec_mod_fmpz * made randtest produce sparse output * fmpz_poly * added fmpz_poly_sqr, fmpz_poly_sqrlow for squaring a polynomial * added fmpz_poly_lcm * made multipoint interpolation faster by using the Newton basis * added a function for fast division by a linear polynomial * added power series composition (classical and Brent-Kung) * added power series reversion (classical, Newton, fast Lagrange) * added a function for obtaining the largest absolute value coefficient * fixed quadratic memory usage and stack overflow when performing unbalanced division or pseudo division using the divconquer algorithm * fixed a bug in poly_zero_coeffs * fixed a bug in xgcd_modular * allowing +/-1 in the constant term of power series inversion * fixed aliasing bug in divrem * added restartable Hensel lifting and associated utility functions * fixed rem, which used to only call the basecase algorithm * fixed pseudo_divrem, which used to only call the basecase algorithm * implemented Schoenhage-Strassen multiplication (mul_SS, mullow_SS) and enabled this by default * fixed a bug in the heuristic GCD algorithm * added functions for Newton basis conversion * added functions for fast Taylor shift * added fmpz_poly_sqrt implementing a basecase algorithm * added scalar mul_2exp, fdiv_2exp, tdiv_2exp * made randtest produce sparse output * added fmpz_poly_equal_fmpz * improved performance by always using basecase multiplication when one polynomial is short * improved algorithm selection for fmpz_poly_gcd * fixed several bugs in gcd_modular * improved performance of gcd_modular * fmpz_poly_factor * new module for factorisation of fmpz_polys * added a naive implementation of the Zassenhaus algorithm * fmpz_mod_poly * new module for polynomials modulo over Z/nZ for arbitrary-precision n * multiplication, powering * classical and divconquer division * series inversion * Euclidean GCD and XGCD * invmod * radix conversion * divconquer composition * GCD and division functions that test invertibility of the leading coefficient * fmpz_mat * added det_divisor for computing a random divisor of the determinant * faster determinant computation using divisor trick * faster determinant computation by using multimodular updates * fixed n x 0 x m product not zeroing the result * various interface improvements * faster implementation of Cramer's rule for multiple right hand sides * added fmpz_mat_fread and read * added multi CRT/mod functions * added trace * fmpz_poly_mat * fixed n x 0 x m product not zeroing the result * added inverse * added rank computation * added reduced row echelon form and nullspace computation * added more utility functions * added squaring and exponentiation * added balanced product of a sequence of matrices * added truncate, mullow, sqrlow, pow_trunc * added trace * fmpz_factor * new module providing interface for integer factorisation * fast expansion of a factored integer * fmpq * cleaned up and improved performance of rational reconstruction code * allow separate numerator and denominator bounds for rational reconstruction * added continued fraction expansion * added functions for summation using binary splitting * added fmpq_swap * added fmpq_print, fmpq_get_str * added fmpq_pow_si * added functions to obtain read-only fmpq_t's from mpq_t's * added fmpq_cmp * fmpq_mat * fixed n x 0 x m product not zeroing the result * added fmpq_mat_transpose * added trace * fmpq_poly * improved speed of multipoint interpolation using _fmpz_poly_div_root * fmpq_poly: added power series composition (classical and Brent-Kung) * fmpq_poly: added power series reversion (classical, Newton, fast Lagrange) * fixed bug wherein set_array_mpq modified the input * added gcd, xgcd, lcm, resultant * added fmpq_poly_set_fmpq * added fmpq_poly_get_slice, fmpq_poly_reverse * fixed aliasing bug in divrem * changed some functions to use FLINT scalar types instead of MPIR data types * added fmpq_poly_get_numerator * nmod_poly * implemented the half gcd algorithm for subquadratic gcd and xgcd * added multipoint evaluation and interpolation * added asymptotically fast multipoint evaluation and interpolation * added a function for forming the product of linear factors * added a function for fast division by a linear polynomial * added power series composition (classical and Brent-Kung) * added power series reversion (classical, Newton, fast Lagrange) * added nmod_poly_mulmod, powmod and related functions (ported from flint1) * added squarefree, irreducibility tests (ported from flint1) * added Berlekamp and Cantor-Zassenhaus factoring (ported from flint1) * fixed quadratic memory usage and stack overflow when performing unbalanced division using the divconquer algorithm * added compose_series_divconquer * added resultant * fixed aliasing bug in divrem * added rem functions * added divrem_q0, q1 for special cases of division * added functions for fast Taylor shift * added nmod_poly_sqrt * made fread read the modulus from the file * made randtest produce sparse output * fixed bug in xgcd_euclidean with scalar inputs * nmod_vec * added functions and macros for computing dot products * made randtest produce sparse output * nmod_mat * added addmul/submul functions * asymptotically fast solving of triangular systems * asymptotically fast LUP decomposition * asymptotically fast determinant and rank computation * asymptotically fast reduced row echelon form and nullspace * asymptotically fast nonsingular solving * asymptotically fast inverse * tidied some interfaces * fixed n x 0 x m product not zeroing the result * added trace * made multiplication faster for tiny moduli by means of bit packing * nmod_poly_mat * new module for matrices over Z/nZ[x], with similar functionality as the fmpz_poly_mat module * determinant, rank, solving, reduced echelon form, nullspace * fraction-free Gaussian elimination * multiplication using bit packing * multiplication using evaluation-interpolation * determinant using evaluation-interpolation * padic * restructured and improved much of the code * added padic_log * improved log and exp using rectangular splitting * added asymptotically fast log and exp based on binary splitting * perm * added the perm module for permutation matrices * computing the parity of a permutation * inverting a permutation * arith * added generation of cyclotomic polynomials * added functions for evaluating Dedekind sums * fast computation of the partition function * added a function for factoring a Hardy-Ramanujan-Rademacher type exponential sum * added Chebyshev polynomials T and U * added computation of the minimal polynomial of cos(2pi/n) * added asymptotically fast high-precision approximation of zeta(n) * added asymptotically fast computation of Euler's constant * added new algorithms and functions for computing Bell numbers * fast computation of pi (adapting code written by Hanhong Xue) * added functions for computing the number of sum of squares representations of an integer * renamed functions to have an arith prefix 2011-06-04 -- FLINT 2.2 ------------------------------------------------------------------------------- * fmpq (multiprecision rational numbers) * Basic arithmetic functions * Utility functions * Rational reconstruction * Functions for enumerating the rationals * fmpq_mat (matrices over Q) * Basic arithmetic functions * Utility functions * Fast multiplication * Classical and fraction-free reduced row echelon form * Determinants * Fast non-singular solving * fmpz_poly_mat (matrices over Z[x] * Basic arithmetic functions * Utility functions * Fraction-free row reduction and determinants * Fast determinants (experimental) * fmpz_mat * Added more utility functions (scalar multiplication, etc) * Added Dixon's p-adic algorithm (used by fast nonsingular rational system solving) * Added reduced row echelon form * Added conversions between fmpz_mat and nmod_mat * Added CRT functions for fmpz_mats * Faster matrix multiplication for small to medium dimensions * longlong.h * Added x86 assembly macros for accumulating sums of two limb operands * nmod_mat * Sped up arithmetic for moduli close to FLINT_BITS * arith * Changed interface of various functions to use new fmpq type * fmpz * Added fmpz_set_ui_mod * Inlined fmpz_neg, fmpz_set_si, fmpz_set_ui for better performance * Added fmpz_lcm * Small performance improvement to fmpz_CRT_ui * fmpz_vec * Added _fmpz_vec_lcm * fmpz_poly_q (rational functions over Q, modeled as quotients of fmpz_polys) * Basic arithmetic functions * Conversion and IO functions * Evaluation * padic (p-adic numbers -- experimental) * Basic arithmetic * Data conversion and IO * Inverse and square root using Newton iteration * Teichmuller lifts (not optimised) * p-adic exponential function (not optimised) * fmpz_poly * Added fmpz_poly_gcd_modular (and fmpz_poly_gcd wrapper) * Added fmpz_poly_xgcd_modular (and fmpz_poly_xgcd wrapper) * Added conversions between fmpz_poly and nmod_poly * Added CRT functions * Added multipoint evaluation and interpolation * nmod_poly * Added nmod_poly_xgcd_euclidean (and nmod_poly_xgcd wrapper) * nmod_poly_gcd wrapper * mpn_extras * Added MPN_NORM and MPN_SWAP macros. * Added mpn_gcd_full to remove some of the restrictions from the usual mpn_gcd * build fixes * fixed make install to create nonexistent dirs (reported by Serge Torres) * -L use /usr instead of /usr/local by default (reported by Serge Torres) * guards for system headers because of flint's use of ulong 2011-03-09 -- FLINT 2.1 ------------------------------------------------------------------------------- * fmpz * Simplified interface for fast multimodular reduction and CRT reconstruction * Fixed segmentation fault in fmpz_multi_mod_ui when the input exceeds the product of the moduli * Added simple incremental CRT functions (fmpz_CRT_ui, fmpz_CRT_ui_unsigned) to complement the existing fast ones * Added example programs for CRT * Added random number generators designed for testing modular code (fmpz_randtest_mod, fmpz_randtest_mod_signed) * Added fmpz_fdiv_ui for remainder on division by an ulong * Added fmpz_bin_uiui for computing binomial coefficients * Added fmpz_mul2_uiui and fmpz_divexact2_uiui for multiplying or dividing an fmpz by a pair of ulongs (efficiently when their product fits in a single limb) * fmpz_mat * Added utility functions for basic arithmetic and creating unit matrices * Added multimodular determinant computation (certified or heuristic) * Added support for computing right nullspaces (fmpz_mat_kernel). Fast only for small matrices. * Some internal code cleanup and various small fixes * nmod_mat * Faster Gaussian elimination for small moduli * Faster determinants * Faster matrix inversion and nonsingular solving * nmod_poly * Added nmod_poly_integral for computing integrals * Added fast square root and inverse square root of power series * Added fast transcendental functions of power series (log, exp, sin, cos, tan, sinh, cosh, tanh, asin, atan, asinh, atanh) * Made nmod_poly_inv_series_newton more memory efficient * fmpq_poly * Added fmpq_poly_integral for computing integrals * Added fast transcendental functions of power series (log, exp, sin, cos, tan, sinh, cosh, tanh, asin, atan, asinh, atanh) * arith * Made computation of vectors of Bernoulli numbers faster * Added fast computation of single Bernoulli numbers * Added a separate function for computing denominators of Bernoulli numbers * Added fast computation of Bell numbers (vector and single) * Added fast computation of Euler numbers (vector and single) * Added fast computation of Euler polynomials * Added fast computation of Swinnerton-Dyer polynomials * Added fast computation of Legendre polynomials * Added fast vector computation of the partition function * Added fast vector computation of Landau's function * ulong_extras * Added a function for computing factorials mod n * build system * Added support for building static and shared libraries * All object files and test/profile/example binaries now build in separate build directory * documentation * Large number of corrections 2011-01-16 -- FLINT 2.0 ------------------------------------------------------------------------------- N.B: FLINT 2 is a complete rewrite of flint from scratch It includes the following modules: * ulong_extras: (word sized integers and modular arithmetic) * random numbers (randint, randbits, randprime, randint) * powering * reverse binary * mod, divrem, mulmod all with precomputed inverses * gcd, invgcd, xgcd * jacobi symbols * addmod, submod, invmod, powmod * prime sieve, nextprime, prime-pi, nth-prime * primality testing (small, binary search, Pocklington-Lehmer, Pseudosquare) * probably prime tests (strong base-a, Fermat, Fibonacci, BPSW, Lucas) * sqrt, sqrtrem, is-square, perfect-power (2,3,5) * remove, is-squarefree * factorisation (trial-range, trial, power (2,3,5), one-line, SQUFOF) * Moebius mu, Euler phi * fmpz: (memory managed multiple precision integers) * memory management (init, clear) * random numbers (randbits, randm) * conversion to and from long, ulong, doubles, mpz's, strings * read/write to file, stdin, stdout * sizeinbase, bits, size, sgn, swap, set, zero * cmp, cmp-ui, cmpabs, equal, is-zero, is-one * neg, abs, add, add-ui, sub, sub-ui, mul, mul-si, mul-ui, mul-2exp * addmul, addmul-ui, submul, submul-ui * cdiv-q, cdiv-q-si, cdiv-q-ui * fdiv-q, fdiv-q-si, fdiv-q-ui, fdiv-qr, fdiv-q-2exp * tdiv-q, tdiv-q-si * divexact, divexact-si, divexact-ui * mod, mod-ui * powering * sqrt, sqrt-rem * factorial * gcd, invmod * bit-pack, bit-unpack * multimodular reduction, CRT * fmpz_vec: (vectors over fmpz's) * memory management (init, clear) * random vectors * max-bits, max-limbs * read/write to file/stdin/stdout * set, swap, zero, neg * equal, is-zero * sort * add, sub * scalar multiplication by fmpz, ulong, long, 2exp * exact division by fmpz, long, ulong * fdiv-q by fmpz, long, ulong, 2exp * tdiv-q by fmpq, long, ulong * addmul by fmpz, long, long by 2exp * submul by fmpz, long, long by 2exp * Gaussian content * fmpz_poly: (polys over fmpz's) * memory management (init, realloc, fit-length, clear) * random polys * normalise, set-length, truncate * length, degree, max-limbs, max-bits * set, set-si, set-ui, set-fmpz, set-str * get-str, get-str-pretty * zero, one, zero-coeffs * swap, reverse * get/set coeffs from fmpz, long, ulong * get-coeff-ptr, lead * equal, is-zero * add, sub * scalar multiplication by fmpz, long, ulong * scalar addmul/submul by fmpz * scalar fdiv by fmpz, long, ulong * scalar tdiv by fmpz, long, ulong * scalar divexact by fmpz, long, ulong * bit pack, bit unpack * multiplication (classical, karatsuba, KS) * mullow (classical, karatsuba, KS) * mulhigh (classical, karatsuba) * middle product (classical) * powering (small, binary exponent, binomial, multinomial, addition chains) * truncated powering (binary exponent) * shift left/right * euclidean norm * gcd (subresultant) * resultant * content, primitive part * divrem (basecase, divide-and-conquer) * div (basecase, divide-and-conquer) * rem (basecase) * invert series (basecase, Newton) * div series * pseudo divrem (basecase, divide-and-conquer, Cohen) * rem (Cohen) * div * evaluate (Horner) at fmpz, mpq, a mod n * composition (Horner, divide-and-conquer) * signature * read/write to file/stdin/stdout * fmpq_poly: (polynomials over Q stored as poly over fmpz with fmpz denominator) * memory management (init, realloc, fit-length, clear) * random polys * set-length, canonicalise, normalise, truncate * is-canonical, length, degree * reference to numerator, denominator * set, set-si, set-ui, set-fmpz, set-mpz, set-mpq * set-array-mpq, set-str * get-str, get-str-pretty * zero, neg, swap * invert * set coefficient to mpq, long, ulong, fmpz, mpz * get coefficient as mpq * equal, cmp, is-one, is-zero * add, sub * scalar multiplication by long, ulong, fmpz, mpq * scalar division by fmpz, long, ulong, mpq * multiplication, mullow * powering * shift left/right * divrem, div, rem * invert series (Newton iteration) * divide series * derivative * evaluate at fmpz, mpq * composition, scale by constant * content, primitive part * make-monic, is-monic * is-squarefree * read/write to file/stdin/stdout * nmod_vec: (vectors over Z/nZ for n fitting in a machine word) * memory management (init/clear) * macros for efficient reduction of 1, 2 and 3 limb integers mod n * macro for addmul mod n * add/sub/neg individual coefficients mod n * random vectors * set, zero, swap * reduce, max-bits * equal * add, sub, neg * scalar multiplication by a value reduced mod n * scalar addmul by a value reduced mod n * nmod_poly: (polynomials over Z/nZ for n fitting in a machine word) * memory management (init, realloc, fit-length, clear) * random polys * normalise, truncate * length, degree, modulus, max-bits * set, swap, zero, reverse * get/set coefficients as ulongs, strings * read/write to file, stdin, stdout * equal, is-zero * shift left/right * add, sub, neg * scalar multiplication by a value reduced mod n * make-monic * bit pack, bit unpack * multiplication (classical, KS) * mullow (classical, KS) * mulhigh (classical) * powering (binary exponent) * pow-trunc (binary exponent) * divrem (basecase, divide-and-conquer, Newton iteration) * div (basecase, divide-and-conquer, Newton iteration) * invert series (basecase, Newton iteration) * divide series (Newton iteration) * derivative * evaluation at a value taken mod n * composition (Horner, divide-and-conquer) * gcd (euclidean) * fmpz_mat: (matrices over fmpz's) * memory management (init, clear) * random matrices (bits, integer relations, simultaneous diophantine equations NTRU-like, ajtai, permutation of rows and cols of a diagonal matrix, random of given rank, random of given determinant, random elementary operations) * set, init-set, swap, entry pointer * write to file or stdout * equal * transpose * multiplication (classical, multimodular) * inverse * determinant * row reduce (Gaussian and Gauss-Jordan fraction-free elimination) * rank * solve Ax = b, solve AX = B * fraction free LU decomposition * nmod_mat: (matrices over Z/nZ for n fitting in a machine word) * memory management (init, clear) * random matrices (uniform, full, permutations of diagonal matrix, random of given rank, random elementary operations) * set, equal * print to stdout * add * transpose * multiplication (classical, Strassen, A*B^T) * row reduction (Gaussian and Gauss-Jordan) * determinant * rank * solve (Ax = b, AX = B, solve with precomputed LU) * invert * arith: (arithmetic functions) * Bernoulli numbers * Bernoulli polynomials * primorials (product of primes up to n) * harmonic numbers * Stirling numbers * Euler phi function * Moebius mu function * Sigma (sum of powers of divisors) * Ramanujan tau function * examples: (example programs) * compute coefficients of q-series of Delta function * mpfr_vec: (vectors over mpfr reals) * memory management (init, clear) * add * set, zero * scalar multiplication by mpfr, 2exp * scalar product * mpfr_mat: (matrices over mpfr reals) * memory management (init, clear) 2010-12-24 -- FLINT 1.6.0 ------------------------------------------------------------------------------- * Bugs: * Fixed a memory leak in mpz_poly_to_string_pretty * Fixed a bug inherited from an old version of fpLLL * Makefile to respect CC and CXX * Fixed bug in F_mpz_set_si * Fixed bug in F_mpz_equal * Most for loops to C90 standard (for easier MSVC porting) * Better Cygwin support * Fixed a bug in zmod_poly_resultant * Fixed bug in F_mpz_mul_KS/2 * Fixed bug in tinyQS * Worked around some known bugs in older GMP/MPIR's * Major new functionality * F_mpz_poly_factor_zassenhaus * F_mpz_poly_factor (incl. fmpz_poly_factor wrapper) using new vH-N approach (see the paper of van Hoeij and Novocin and the paper of van Hoeij, Novocin and Hart) * Implementation of new CLD bounds function for polynomial factors (see the paper of van Hoeij, Novocin and Hart * Restartable Hensel lifting * Heuristic LLL implementations using doubles and mpfr * LLL implementations optimised for knapsack lattices * New (probably subquadratic) LLL implementation (ULLL) * zmod_poly_factor_cantor_zassenhaus * New F_mpz_mod_poly module for polynomials over Z/pZ for multiprec. p * Some of the other new functions added * F_mpz * F_mpz_gcd * F_mpz_smod * F_mpz_mod_preinv * F_mpz_fdiv_qr * F_mpz_get/set_mpfr/2exp * F_mpz_sscanf * F_mpz_set_d * F_mpz_poly: * read F_mpz_poly to_string/from_string/fprint/print/fread/pretty * F_mpz_poly_to/from_zmod_poly * F_mpz_poly_scalar_div_exact * F_mpz_poly_smod * F_mpz_poly_derivative, F_mpz_poly_content, F_mpz_poly_eval_horner_d/2exp * F_mpz_poly_scalar_abs * F_mpz_poly_set_d_2exp * F_mpz_poly_div/divrem * F_mpz_poly_gcd * F_mpz_poly_is_squarefree * F_mpz_poly_factor_squarefree * F_mpz_poly_mul_trunc_left * F_mpz_poly_pseudo_div * F_mpz_poly_set_coeff * F_mpz_poly_pow_ui * Inflation/deflation trick for factorisation * zmod_poly: * Inflation/deflation trick for factorisation * mpz_mat: * mpz_mat_from_string/to_string/fprint/fread/pretty * mpq_mat: * mpq_mat_init/clear * Gramm-schmidt Orthogonalisation * F_mpz_mat: * F_mpz_mat_print/fprint/fread/pretty * F_mpz_mat_mul_classical * F_mpz_mat_max_bits/2 * F_mpz_mat_scalar_mul/div_2exp * F_mpz_mat_col_equal * F_mpz_mat_smod * F_mpz_vec_scalar_product/norm * F_mpz_vec_add/submul_ui/si/F_mpz/2exp * zmod_mat: * classical multiplication * strassen multiplication * scalar multiplication * zmod_mat_equal * zmod_mat_add/sub * zmod_mat_addmul_classical * d_mat: * d_vec_norm, d_vec_scalar_product * mpfr_mat: * mpfr_vec_scalar_product/norm 2009-09-22 -- FLINT 1.5.0 ------------------------------------------------------------------------------- * Added multimodular reduction and CRT to F_mpz module * Fixed some bugs in F_mpz module and numerous bugs in test code * Added zmod_poly_compose * Added zmod_poly_evaluate * Added functions for reduced evaluation and composition to fmpz_poly module (contributed by Burcin Erocal) * Fixed bugs in the primality tests in long_extras * Removed all polynomial multimodular multiplication functions * Added new thetaproduct code used in the 1 trillion triangles computation * Fixed a severe bug in the fmpz_poly_pseudo_div function reported by Sebastian Pancratz * Added fmpz_comb_temp_init/clear functions * Fixed a normalisation buglet in fmpz_poly_pack_bytes * Added F_mpz_pow_ui function (contributed by Andy Novocin) * Fixed a severe bug in the FFT reported by William Stein and Mariah Lennox (fix contributed by David Harvey) * Removed some memory leaks from F_mpz test code * Fixed bug in zmod_poly_evaluate test code 2009-07-06 -- FLINT 1.4.0 ------------------------------------------------------------------------------- * Sped up zmod_poly division in case where operands are the same length * Sped up zmod_poly division in case where operands have lengths differing by 1 * Fixed a bug in zmod_poly_gcd for polynomials of zero length * Sped up zmod_poly_gcd considerably (both euclidean and half gcd) * Sped up zmod_poly_gcd_invert and zmod_poly_xgcd considerably * Made zmod_poly_gcd_invert and zmod_poly_xgcd asymptotically fast * Made zmod_poly_resultant asymptotically fast * Added optimised zmod_poly_rem function * Fixed a divide by zero bug in zmod_poly_factor_berlekamp * Added test code for z_factor_tinyQS and z_factor_HOLF * Fixed many bugs in the z_factor code, tinyQS and mpQS * Corrected numerous typos in the documentation and added missing descriptions * Added F_mpz_cmp function * Added documentation to the manual for the new F_mpz module 2009-06-09 -- FLINT 1.3.0 ------------------------------------------------------------------------------- * Added new code for checking 2nd, 3rd and 5th roots * Fixed a bug in z_factor * Connected quadratic sieve for factoring large ulongs * Added one line factor algorithm * constructed best of breed factor algorithm * Fixed termination conditions for z_intcuberoot and z_intfifthroot which were broken * Added some code for special cases which cause infinite loops in cuberoot and fifthroot * Went back to ceil(pow(n, 0.33333333)) and ceil(pow(n, 0.2)) for initial guesses in cube and fifth root functions as these were about 50% faster than sqrt(n) and sqrt(sqrt(n)) respectively. * Added test code for z_intfifthroot * Added test code for z_factor_235power * Fixed some uninitialised data found by valgrind in intcuberoot and intfifthroot * Fixed multiply defined PRIME_COUNT in long_extras-test * Got rid of gotos in some functions in long_extras * Knocked optimisation level back to -O2 because it miscompiles on sage.math * Changed tables to use uint64_t's instead of ulongs which are not 64 bits on a 32 bit machine * Only checked MAX_HOLF on 64 bit machine * Changed MAX_SQUFOF to WORD(-1) * Check constant 0x3FFFFFFFFUL only on a 64 bit machine * Fixed a bug in z_oddprime_lt_4096 on 32 bit machines * Fixed some TLS issues with Cygwin * Fixed some typos in makefile * Fixed a wrong path in fmpz.c 2009-04-18 -- FLINT 1.2.5 ------------------------------------------------------------------------------- * Upgraded to zn_poly-0.9 to avoid a serious error in squaring of large polynomials over Z/nZ 2009-04-04 -- FLINT 1.2.4 ------------------------------------------------------------------------------- * Defined THREAD to be blank on Apple CC and __thread for thread local storage on other gcc's (where it's defined) * #undef ulong in profiler.h where time.h and other system time headers are included (both reported by M. Abshoff) 2009-03-31 -- FLINT 1.2.3 ------------------------------------------------------------------------------- * Fixed bugs in all fmpz_poly evaluation functions, identified by Burcin Erocal. 2009-03-20 -- FLINT 1.2.2 ------------------------------------------------------------------------------- * Fixed a memory leak in zmod_poly_factor * Fixed zmod_poly-profile build 2009-03-14 -- FLINT 1.2.1 ------------------------------------------------------------------------------- * Removed some FLINT 2.0 code which was interfering with the build of the NTL-interface * Removed an omp.h from fmpz_poly.c. 2009-03-10 -- FLINT 1.2.0 ------------------------------------------------------------------------------- * made memory manager, fmpz and fmpz_poly threadsafe * Code for running tests in parallel (not activated) * Sped up fmpz_poly_scalar_div_ui/si when scalar is 1/-1 * Parallelise _fmpz_poly_mul_modular * fmpz_mul_modular_packed to pack coefficients to the byte before running _fmpz_poly_mul_modular * fmpz_poly_pseudo_rem_cohen (not documented) * special case for leading coeff 1/-1 in fmpz_poly_pseudo_divrem_basecase * removed a memory allocation bug which caused a massive slowdown in fmpz_poly_pseudo_divrem_basecase * fmpz_poly_pseudo_rem_basecase (not documented) * fmpz_poly_pseudo_rem (not asymptotically fast) * fmpz_poly_signature (not asymptotically fast) * basic fmpz_poly_is_squarefree function * included zn_poly in trunk and made FLINT build zn_poly as part of its build process * switched to using zn_poly for polynomial multiplication, newton inversion, scalar multiplication in zmod_poly * Integer cube root of word sized integers * Fibonacci pseudoprime test * BSPW probable prime test * n - 1 primality test * Complete implementation of z_issquarefree * Significantly improved the thetaproduct example program. * Fixed bug in fmpz_poly_byte_pack which is triggered when trying to pack into fields a multiple of 8 bytes (could cause a segfault) * Fixed a bug in fmpz_poly_pseudo_divrem (relied on an uninitialised poly to have length 0) * Fixed bug in fmpz_multi_CRT_ui (could segfault) * Fixed bug in fmpz_multi_mod_ui (could segfault) * Fixed memory leak in zmod_poly_factor_squarefree * Fixed memory leak in zmod_poly_from_string 2009-03-01 -- FLINT 1.1.3 ------------------------------------------------------------------------------- * Inserted some missing return values in zmod_poly test code. 2009-03-01 -- FLINT 1.1.2 ------------------------------------------------------------------------------- * Fixed some memory allocation slowdowns and bugs in fmpz_poly division and pseudo division functions (reported by William Stein). 2009-02-11 -- FLINT 1.1.1 ------------------------------------------------------------------------------- * Fixed bugs in _fmpz_poly_scalar_mul_fmpz, fmpz_poly_gcd_heuristic and fmpz_poly_gcd_subresultant and fixed bugs in test__fmpz_poly_scalar_div_fmpz, test_fmpz_poly_scalar_div_fmpz and test_fmpz_poly_scalar_div_mpz. 2008-12-21 -- FLINT 1.1.0 ------------------------------------------------------------------------------- Some of the following features were previewed in FLINT 1.0.11. * integer gcd (this just wraps the GMP gcd code) * polynomial content * primitive part * convert to and from FLINT and NTL integers and polynomials * get a coefficient of a polynomial efficiently as a read only mpz_t * print polynomials in a prettified format with a specified variable * Sped up integer multiplication * Convert to and from zmod_polys from fmpz_polys * Chinese remainder for fmpz_polys * Leading coeff macro * Euclidean norm of polynomials * Exact division testing of polynomials * Polynomial GCD (subresultant, heuristic, modular) * Modular inversion of polynomials * Resultant * XGCD (Pohst-Zassenhaus) * Multimodular polynomial multiplication * Rewritten karatsuba_trunc function * Rewritten division functions * Polynomial derivative * Polynomial evaluation * Polynomial composition * Addition and subtraction of zmod_polys * Sped up multiplication of zmod_polys * Extended multiplication of zmod_polys to allow up to 63 bit moduli * zmod_poly subpolynomials * zmod_poly reverse * Truncated multiplication for zmod_polys (left, right, classical and KS) * Scalar multiplication * Division for zmod_polys (divrem and div, classical, divide and conquer and newton) * Series inversion for zmod_polys * Series division for zmod_polys * Resultant for zmod_polys * GCD for zmod_polys including half-gcd * Inversion modulo a polynomial for zmod_polys * XGCD for zmod_polys * Squarefree factorisation for zmod_polys * Berlekamp factorisation for zmod_polys * Irreducibility testing for zmod_polys * Derivative for zmod_polys * Middle product for zmod_polys (sped up newton division) * addmod, submod and divmod for ulongs * Sped up limb sized integer square root * Partial factoring of ulongs * z_randbits * Pocklington-Lehmer primality testing * BSPW pseudo-primality testing * Fermat pseudo-primality testing * Fast Legendre symbol computation * Chinese remainder for fmpzs * Square root with remainder for fmpzs * Left and right shift for fmpzs * Reduction modulo a ulong for fmpzs * Montgomery redc, mulmod, divmod and mod for fmpzs * Multimodular reduction and CRT for fmpzs * fmpz_mulmod and fmpz_divmod * fmpz_invert for inversion modulo an fmpz * Dramatically sped up gcd for small fmpzs * Computation of 1D, 2D and some 3D theta functions * Example program for multiplying theta functions * Test code now times test functions * Quick and dirty timing function for profiler * Tiny quadratic sieve for small one and two limb integers * Completely rewritten self initialising multiple polynomial quadratic sieve * Build fix for 64 bit OSX dylibs (reported by Michael Abshoff) 2008-12-25 -- FLINT 1.0.21 ------------------------------------------------------------------------------- * Fixed the Christmas bug reported by Michael Abshoff which causes a test failure in fmpz_poly_gcd_modular and a hang in fmpz_poly_invmod_modular on 32 bit machines 2008-12-13 -- FLINT 1.0.20 ------------------------------------------------------------------------------- * Fixed some bugs in conversion of zmod_poly's to and from strings 2008-12-12 -- FLINT 1.0.19 ------------------------------------------------------------------------------- * Fixed a bug in z_remove_precomp 2008-12-05 -- FLINT 1.0.18 ------------------------------------------------------------------------------- * Fixed another bug in the fmpz_poly_set_coeff_* functions which resulted in dirty coefficients 2008-11-30 -- FLINT 1.0.17 ------------------------------------------------------------------------------- * Fixed a segfault caused by left shifting of polynomials with zero limbs allocated in division and pseudo division functions. * Fixed a bound used in fmpz_gcd_modular to use a proven bound * Fixed a bug in fmpz_poly-profile where the top bit of random coefficients of n bits was always set 2008-10-22 -- FLINT 1.0.16 ------------------------------------------------------------------------------- * Fixed a segfault when trying to truncate a polynomial to an longer length than it currently is, with the function fmpz_poly_truncate (reported by Craig Citro) 2008-10-15 -- FLINT 1.0.15 ------------------------------------------------------------------------------- * Fixed a bug which causes a segfault when setting a coefficient of the zero polynomial to zero * Fixed build bug in longlong.h on s390 platform 2008-09-23 -- FLINT 1.0.14 ------------------------------------------------------------------------------- * Update long_extras and test code for the sake of new quadratic sieve (new functions in long_extras remain undocumented) * Removed many bugs from tinyQS and mpQS and joined them into a single program for factoring integers 2008-07-13 -- FLINT 1.0.13 ------------------------------------------------------------------------------- * Fixed memory leaks and dirty memory issues in test code for numerous modules. * Removed further issues with cache prefetching in mpn_extras.c 2008-07-11 -- FLINT 1.0.12 ------------------------------------------------------------------------------- * Removed some Opteron tuning flags which cause illegal instruction errors on Pentium4 * Fixed numerous memory leaks in fmpz_poly test code * Fixed memory leak in fmpz_poly_power_trunc_n * Fixed major memory leaks in fmpz_poly_xgcd_modular * Rewrote __fmpz_poly_mul_karatrunc_recursive and _fmpz_poly_mul_karatsuba_trunc to "prove code" and got rid of some dirty memory issues * Fixed some potential illegal memory accesses to do with cache prefetching in fmpz_poly.c 2008-07-09 -- FLINT 1.0.11 ------------------------------------------------------------------------------- * Fixed a bug in z_ll_mod_precomp on ia64 (reported by Michael Abshoff and William Stein) 2008-06-16 -- FLINT 1.0.10 ------------------------------------------------------------------------------- * integer gcd (this just wraps the GMP gcd code) * polynomial content * convert to and from FLINT and NTL integers and polynomials * get a coefficient of a polynomial efficiently as a read only mpz_t * print polynomials in a prettified format with a specified variable 2008-03-11 -- FLINT 1.0.9 ------------------------------------------------------------------------------- * Fixed a memory allocation bug in fmpz_poly_power 2008-02-15 -- FLINT 1.0.8 ------------------------------------------------------------------------------- * Fixed a bug in fmpz_poly_right_shift (reported by Kiran Kedlaya) 2008-01-22 -- FLINT 1.0.7 ------------------------------------------------------------------------------- * Made F_mpn_mul binary compatible with the way mpn_mul *operates* in practice. 2008-01-17 -- FLINT 1.0.6 ------------------------------------------------------------------------------- * Fixed an issue with FLINT_BIT_COUNT on certain machines (probably due to arithmetic shift issues) 2008-01-05 -- FLINT 1.0.5 ------------------------------------------------------------------------------- * Fixed some inline issues which cause problems because of the C99 inline rules (reported by David Harvey). * Fixed a makefile issue reported (and solved) by David Harvey when *not* linking against NTL. 2008-01-04 -- FLINT 1.0.4 ------------------------------------------------------------------------------- * Fixed a bug in the bernoulli_zmod example program and associated polynomial zmod code which caused memory corruption. * Fixed a bug in the fmpz-test code which manifested on 32 bit machines, reported by David Harvey. * Fixed some bugs in the pari profiling code. 2007-12-16 -- FLINT 1.0.3 ------------------------------------------------------------------------------- * Fixed a bug in the polynomial memory management code which caused a segfault * Fixed a bug in the pseudo division code which caused a block overrun 2007-12-10 -- FLINT 1.0.2 ------------------------------------------------------------------------------- * Rewrote tuning code for integer multiplication functions, making it more robust and fixing a bug which showed up on 32 bit machines (reported by Michael Abshoff and Jaap Spies). Factored the tuning code out into a number of macros. 2007-12-07 -- FLINT 1.0.1 ------------------------------------------------------------------------------- * Fixed a bug in _fmpz_poly_maxbits1 on 32 bit machines, reported by Michael Abshoff and Carl Witty * Removed some instances of u_int64_t and replaced them with uint64_t, reported by Michael Abshoff * Replaced sys/types.h with stdint.h * Added FLINT macros to documentation * Corrected numerous typos in documentation 2007-12-02 -- FLINT 1.0 ------------------------------------------------------------------------------- * First version of FLINT, includes fmpz_poly, fmpz and mpQS Antic version history ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 2021-06-24 -- Antic 0.2.5 ------------------------------------------------------------------------------- * TODO: list changes here 2021-04-15 -- Antic 0.2.4 ------------------------------------------------------------------------------- * TODO: list changes here 2020-12-11 -- Antic 0.2.3 ------------------------------------------------------------------------------- * TODO: list changes here 2020-06-30 -- Antic 0.2.2 ------------------------------------------------------------------------------- * TODO: list changes here 2020-06-16 -- Antic 0.2.1 ------------------------------------------------------------------------------- * TODO: list changes here 2019-02-12 -- Antic 0.2 ------------------------------------------------------------------------------- * Many bug fixes, standalone build system, continuous integration. 2013-05-12 -- Antic 0.1 ------------------------------------------------------------------------------- * First version of antic, including a qfb module for (positive definite) binary quadratic forms. Calcium version history ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 2021-05-28 -- Calcium 0.4 ------------------------------------------------------------------------------- * Algebraic numbers * Fixed bug in special-casing of roots of unity in qqbar_root_ui. * Fixed qqbar_randtest with bits == 1. * Faster qqbar_cmp_re for nearby reals. * Faster qqbar polynomial evaluation and powering using linear algebra. * Improved qqbar_abs, qqbar_abs2 to produce cleaner enclosures. * Use a slightly better method to detect real numbers in qqbar_sgn_im. * Added qqbar_hash. * Added qqbar_get_fmpq, qqbar_get_fmpz. * Added qqbar_pow_fmpq, qqbar_pow_fmpz, qqbar_pow_si. * Added qqbar_numerator, qqbar_denominator. * Basic arithmetic and elementary functions * Improved ca_condense_field: automatically demote to a simple number field when the only used extension number is algebraic. * Improved multivariate field arithmetic to automatically remove algebraic or redundant monomial factors from denominators. * Added ca_pow_si_arithmetic (guaranteed in-field exponentiation). * Added polynomial evaluation functions (ca_fmpz_poly_evaluate, ca_fmpq_poly_evaluate, ca_fmpz_poly_evaluate, ca_fmpz_mpoly_q_evaluate). * Added several helper functions (ca_is_special, ca_is_qq_elem, ca_is_qq_elem_zero, ca_is_qq_elem_one, ca_is_qq_elem_integer, ca_is_nf_elem, ca_is_cyclotomic_nf_elem, ca_is_generic_elem). * Added ca_rewrite_complex_normal_form. * Perform direct complex conjugation in cyclotomic fields. * Use ca_get_acb_raw instead of ca_get_acb when printing to avoid expensive recomputations. * Added alternative algorithms for various basic functions. * Deep complex conjugation. * Use complex conjugation in is_real, is_imaginary, is_negative_real. * Added functions for unsafe inversion for internal use. * Significantly stronger zero testing in mixed algebraic-transcendental fields. * Added ca_arg. * Added special case for testing equality between number field elements and rationals. * Added ca_sin_cos, ca_sin, ca_cos, ca_tan and variants. * Added ca_atan, ca_asin, ca_acos and variants. * Added ca_csgn. * Improved ca_get_acb and ca_get_acb_accurate_parts to fall back on exact zero tests when direct numerical evaluation does not give precise enclosures. * Added ca_get_decimal_str. * More automatic simplifications of logarithms (simplify logarithms of exponentials, square roots and powers raised to integer powers). * More automatic simplifications of square roots (simplify square roots of exponentials, square roots and powers raised to integer powers). * Improved order comparisons (ca_check_ge etc.) to handle special values and to fall back on strong equality tests. * Fixed a test failure in the ca_mat module. * Polynomials * Added ca_poly_inv_series, ca_poly_div_series (power series division). * Added ca_poly_exp_series (power series exponential). * Added ca_poly_log_series (power series logarithm). * Added ca_poly_atan_series (power series arctangent). * Other * Added fmpz_mpoly_q_used_vars. * Remove useless rpath line from configure (reported by Julien Puydt). * Added missing declaration of fexpr_hash. * Fixed crashes on OS X in Python interface (contributed by deinst). * Fixed memory leaks in Python string conversions (contributed by deinst). * Reserve I, E for symbolic expressions in Python interface. 2021-04-23 -- Calcium 0.3 ------------------------------------------------------------------------------- * Symbolic expressions * Added the fexpr module for flat-packed unevaluated symbolic expressions. * LaTeX output. * Basic manipulation (construction, replacement, accessing subexpressions). * Numerical evaluation with Arb. * Expanded normal form. * Conversion methods for other types. * Enable LaTeX rendering of objects in Jupyter notebooks. * Algebraic numbers * Fix a major performance issue (slow root refinement) that made Calcium as a whole far slower than necessary. * Added qqbar_cmp_root_order; sort polynomial roots consistently by default. * Added qqbar_get_quadratic. * Added qqbar_equal_fmpq_poly_val and use it to speed up checking guessed values. * Conversion of qqbar_t to and from symbolic expression (qqbar_set_fexpr, qqbar_get_fexpr_repr, qqbar_get_fexpr_root_nearest, qqbar_get_fexpr_root_indexed, qqbar_get_fexpr_formula). * Fixed bugs in qqbar_cmpabs_re, cmpabs_im. * Optimized qqbar_cmp_im and qqbar_cmpabs_im for conjugates with mirror symmetry. * Added qqbar_pow (taking a qqbar exponent). * Special-case roots of unity in qqbar_pow_ui, qqbar_root_ui, qqbar_abs and qqbar_abs2. * Wrapped qqbar in Python. * Polynomials * Added several utility functions. * Optimized polynomial multiplication with rational entries. * Fast polynomial multiplication over number fields. * Matrices * Fast matrix multiplication over number fields. * Right kernel (ca_mat_right_kernel). * Matrix diagonalization (ca_mat_diagonalization). * Jordan normal form (ca_mat_jordan_form, ca_mat_jordan_transformation, ca_mat_jordan_blocks). * Matrix exponential (ca_mat_exp). * Matrix logarithm (ca_mat_log). * Polynomial evaluation (ca_mat_ca_poly_evaluate). * Cofactor expansion algorithm for determinant and adjugate (ca_mat_adjugate_cofactor). * Added several utility functions. * Improved algorithm selection in ca_mat_inv. * Solving using the adjugate matrix. * Danilevsky characteristic polynomial algorithm (ca_mat_charpoly_danilevsky). * Field elements * Use factoring in ca_sqrt to enable more simplifications. * Simplify square roots and logarithms of negative real numbers. * Optimized ca_sub. * Conversion of ca_t to and from symbolic expressions (ca_set_fexpr, ca_get_fexpr). * Added function for assigning elements between context objects (ca_transfer). * Fixed a possible memory corruption bug when Vieta's formulas are used. * Optimized constructing square roots of rational numbers. * Other * Added demonstration notebook to documentation. * Fixed OSX compatibility in Python wrapper (contributed by deinst). * Fixed bug in calcium_write_acb. * Fixed bug in fmpz_mpoly_vec_set_primitive_unique (contributed by gbunting). 2020-10-16 -- Calcium 0.2 ------------------------------------------------------------------------------- * Basic arithmetic and expression simplification * Use Gröbner basis for reduction ideals, making simplification much more robust. * Compute all linear relations with LLL simultaneously instead of piecemeal. * Make monomial ordering configurable (default is lex as before). * Use Vieta's formulas to simplify expressions involving conjugate algebraic numbers. * Denest exponentials of symbolic logarithms. * Denest logarithms of symbolic powers and square roots. * Denest powers of symbolic powers. * Simplify exponentials that evaluate to roots of unity. * Simplify logarithms of roots of unity. * Improve ideal reduction to avoid some unnecessary GCD computations. * Python wrapper * Calcium now includes a minimal ctypes-based Python wrapper for testing. * New ca_mat module for matrices * Mostly using naive basecase algorithms. * Matrix arithmetic, basic manipulation. * Construction of special matrices (Hilbert, Pascal, Stirling, DFT). * LU factorization. * Fraction-free LU decomposition. * Nonsingular solving and inverse. * Reduced row echelon form. * Rank. * Trace and determinant. * Characteristic polynomial. * Computation of eigenvalues with multiplicities. * New ca_poly module for polynomials * Mostly using naive basecase algorithms. * Polynomial arithmetic, basic manipulation. * Polynomial division. * Evaluation and composition. * Derivative and integral. * GCD (Euclidean algorithm). * Squarefree factorization. * Computation of roots with multiplicities. * Construction from given roots. * New ca_vec module for vectors. * Memory management and basic scalar operations. * Bug fixes * Fix bug in powering number field elements. * Fix bug in qqbar_log_pi_i. * Fix aliasing bug in ca_pow. * New basic functions * Conversion from double: ca_set_d, ca_set_d_d. * Special functions: ca_erf, ca_erfi, ca_erfc, with algebraic relations. * Special functions: ca_gamma (incomplete simplification algorithms). * New utils_flint module for Flint utilities * Vectors of multivariate polynomials. * Construction of elementary symmetric polynomials. * Gröbner basis computation (naive Buchberger algorithm). * Documentation and presentation * Various improvements to the documentation. * DFT example program. 2020-09-08 -- Calcium 0.1 ------------------------------------------------------------------------------- * Initial test release. * ca module (exact real and complex numbers). * fmpz_mpoly_q module (multivariate rational functions over Q). * qqbar module (algebraic numbers represented by minimal polynomials). * Example programs. Arb version history ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 2022-06-29 -- Arb 2.23.0 ------------------------------------------------------------------------------- * Performance * Multithreaded numerical integration. * Multithreaded binary splitting computation of mathematical constants. * Multithreaded computation of Bernoulli numbers. * Multithreaded computation of Euler numbers. * Multithreaded refinement of Riemann zeta zeros. * Multithreaded complex_plot example program. * Multithreaded elementary functions. * Multithreaded computation of Hilbert class polynomials. * Improved multithreaded partition function. * Use FLINT's FFT multiplication instead of GMP in appropriate ranges. * New, faster algorithm for elementary functions between roughly 10^3 and 10^6 digits. * Faster computation of log using Newton-like iteration instead of using MPFR. * Faster computation of atan using Newton-like iteration instead of the bit-burst algorithm. * Fix performance bug in atan() leading to quadratic running time with large arguments in high precision. * Optimized high-precision complex squaring. * Added internal function arb_flint_get_num_available_threads() to improve tuning for multithreaded algorithms * Fixed performance bug making erf() slower at high precision with multiple threads. * Features * Implemented the Lerch transcendent (acb_dirichlet_lerch_phi()). * fpwrap wrapper for Lerch transcendent (contributed by Valentin Boettcher). * Added a rudimentary module for Gaussian integers (fmpzi.h). * Added zeta_zeros example program (contributed by D.H.J. Polymath). * Added functions for simultaneous high-precision computation of logarithms of primes and arctangents for primitive angles. * Added bernoulli, class_poly, functions_benchmark example programs for benchmarking use. * Multiplying a signed number by an infinity yields an infinity instead of [0 +/- inf] (contributed by Erik Postma). * Miscellaneous * Deprecated doubles version of partition function. * Fix crash in erf on some systems including mips64el (reported by Julien Puydt). * Fixed MINGW64 build (contributed by Massoud Mazar). * Avoid deprecated FLINT function n_gcd_full. * Documentation fixes. 2022-01-25 -- Arb 2.22.1 ------------------------------------------------------------------------------- * Fixed bugs causing some hypergeometric functions hang or crash for some input on various non-x86 architectures. * Fixed a minor bug in acb_hypgeom_m (NaN result sometimes only set the real part to NaN). 2022-01-15 -- Arb 2.22.0 ------------------------------------------------------------------------------- * Special functions * Use numerical integration in some cases to compute the hypergeometric functions 0F1, 1F1, U, 2F1, incomplete gamma and beta, modified Bessel, etc. with real parameters and argument, improving performance and accuracy when the parameters are large. * Much faster computation of Bernoulli numbers using hybrid numerical-modular algorithm (modular code adapted from bernmm by David Harvey). * Faster computation of Euler numbers using hybrid algorithm; added arb_fmpz_euler_number_ui. * Added inverse error function (arb_hypgeom_erfinv, arb_hypgeom_erfcinv). * New (faster, more accurate) implementations of real error functions (arb_hypgeom_erf, arb_hypgeom_erfc) and trigonometric integrals (arb_hypgeom_si, arb_hypgeom_ci). * Added acb_dirichlet_l_fmpq and acb_dirichlet_l_fmpq_afe: reduced-complexity evaluation of L-functions at rational points. * Added functions for computing primorials (arb_primorial_ui, arb_primorial_nth_ui). * New, highly optimized internal code for real hypergeometric series (arb_hypgeom_sum_fmpq_arb, etc.; currently only used in some functions). * Fix arb_fpwrap_double_hypgeom_2f1 which computed the wrong thing. * Core arithmetic and functions * Faster implementation of arb_ui_pow_ui. * Added arb_fma_si, arb_fma_fmpz. * Added arf_equal_ui, arf_equal_d. * Added arf_get_str. * Use arb-based printing code instead of MPFR in arf_printd and mag_printd so that large exponents work. * Fixed bug in arb_get_str that caused loss of precision when printing more than about 10^6 digits. * Allow negative exponents in mag_pow_fmpz. * Added the double_interval module for fast machine-precision interval arithmetic (experimental, intended for internal use). 2021-10-20 -- Arb 2.21.1 ------------------------------------------------------------------------------- * Fixed 32-bit test failures for arb_hypgeom_gamma_fmpq. * Added pow function to the fpwrap module. * Added missing header file includes. * Do not encode the library version in the SONAME on Android (contributed by Andreas Enge). 2021-09-25 -- Arb 2.21.0 ------------------------------------------------------------------------------- * Experimental new arb_fpwrap module: accurate floating-point wrappers of Arb mathematical functions (supersedes the external arbcmath.h). * Fixed memory leak in arf_load_file (reported by Dave Platt). * New and faster gamma function code. * Most gamma function internals are now located in the arb_hypgeom and acb_hypgeom modules. The user-facing functions (arb_gamma, etc.) are still available under the old names for compatibility. The internal algorithms for rising factorials (binary splitting, etc.) have been moved without aliases. * Added arb_fma, arb_fma_arf, arb_fma_ui (like addmul, but take a separate input and output). * Slightly faster internal Bernoulli number generation for small n. * Better enclosures for acb_barnes_g at negative reals. * Added Graeffe transforms (arb_poly_graeffe_transform, acb_poly_graeffe_transform) (contributed by Matthias Gessinger). * Fixed conflict with musl libc (reported by Gonzalo Tornaría). * Added acb_add_error_arb (contributed by Albin Ahlbäck). 2021-07-25 -- Arb 2.20.0 ------------------------------------------------------------------------------- * Flint 2.8 support. * Change arb_get_str with ARB_STR_NO_RADIUS: [+/- 1.20e-15] now prints as 0e-14. * Uniformly distributed random number functions arf_urandom, arb_urandom (contributed by Albin Ahlbäck). * Use quasilinear algorithm in arb_gamma_fmpq for all small fractions. * Added derivative of Weierstrass elliptic function (acb_elliptic_p_prime) (contributed by Daniel Schultz). * Added dot products with integer coefficients: arb_dot_fmpz, arb_dot_siui, arb_dot_uiui, arb_dot_si, arb_dot_ui, acb_dot_fmpz, acb_dot_siui, acb_dot_uiui, acb_dot_si, acb_dot_ui. * Faster arb_fmpz_poly_evaluate_arb and arb_fmpz_poly_evaluate_acb. * Explicitly guarantee that roots are isolated in arb_fmpz_poly_complex_roots (could previously theoretically fail when using the deflation hack). * Use GNUInstallDirs in CMakeLists.txt to support standard GNU installation directories (contributed by Michael Orlitzky). * Fixed bug for aliased multiplication of window matrices (contributed by David Berghaus). * Documentation fixes (contributed by Joel Dahne, Hanno Rein). 2020-12-06 -- Arb 2.19.0 ------------------------------------------------------------------------------- * Significant improvements to the implementation of Platt's algorithm for computing Riemann zeta function zeros at large height (contributed by p15-git-acc). * Better criterion for selecting asymptotic expansion of incomplete gamma function (contributed by p15-git-acc). * Multithreaded acb_dft for power-of-two lengths (contributed by p15-git-acc). * Added acb_csc_pi, arb_csc_pi (contributed by p15-git-acc). * Fixed segfault in acb_mat_eig_simple_rump when called with L non-NULL and R NULL (contributed by p15-git-acc). * Fixed bug in acb_real_abs (contributed by Joel Dahne). * Changed several functions to more consistently return infinities instead of NaNs where reasonable (contributed by p15-git-acc). * Added Fransen-Robinson as an integral example (contributed by p15-git-acc). * Cleaned up makefile (contributed by p15-git-acc). * Fixed several typos and some omitted functions in the documentation (contributed by Joel-Dahne, p15-git-acc). 2020-06-25 -- Arb 2.18.1 ------------------------------------------------------------------------------- * Support MinGW64. * Added version numbers (__ARB_VERSION, __ARB_RELEASE, ARB_VERSION) to arb.h. 2020-06-09 -- Arb 2.18.0 ------------------------------------------------------------------------------- * General * Flint 2.6 support. * Several build system improvements (contributed by Isuru Fernando). * Changed arf_get_mpfr to return an MPFR underflow/overflow result (rounding to 0 or infinity with the right sign and MPFR overflow flags) instead of throwing flint_abort() if the exponent is out of bounds for MPFR. * Documentation and type corrections (contributed by Joel Dahne). * Arithmetic * The number of iterations per precision level in arb_fmpz_poly_complex_roots has been tweaked to avoid extreme slowdown for some polynomials with closely clustered roots. * Added arb_contains_interior, acb_contains_interior. * Special functions * Fixed unsafe shifts causing Dirichlet characters for certain moduli exceeding 32 bits to crash. * Added acb_agm for computing the arithmetic-geometric mean of two complex numbers. * acb_elliptic_rj now uses a slow fallback algorithm in cases where Carlson's algorithm is not known to be valid. This fixes instances where acb_elliptic_pi, acb_elliptic_pi_inc and acb_elliptic_rj previously ended up on the wrong branch. Users should be cautioned that the new version can give worse enclosures and sometimes fails to converge in some cases where the old algorithm did (the pi flag for acb_elliptic_pi_inc is useful as a workaround). * Optimized some special cases in acb_hurwitz_zeta. 2019-10-16 -- Arb 2.17.0 ------------------------------------------------------------------------------- * General * Added exact serialization methods (arb_dump_str, arb_load_str, arb_dump_file, arb_load_file, arf_dump_str, arf_load_str, arf_dump_file, arf_load_file, mag_dump_str, mag_load_str, mag_dump_file, mag_load_file) (contributed by Julian Rüth). * Removed many obsolete fmpr methods and de-inlined several helper functions to slightly improve compile time and library size. * Fixed a namespace clash for an internal function (contributed by Julian Rüth). * Added the helper function arb_sgn_nonzero. * Added the helper function acb_rel_one_accuracy_bits. * Riemann zeta function * Added a function for efficiently computing individual zeros of the Riemann zeta function using Turing's method (acb_dirichlet_zeta_zero) (contributed by D.H.J. Polymath). * Added a function for counting zeros of the Riemann zeta function up to given height using Turing's method (acb_dirichlet_zeta_nzeros) (contributed by D.H.J. Polymath). * Added the Backlund S function (acb_dirichlet_backlund_s). * Added a function for computing Gram points (acb_dirichlet_gram_point). * Added acb_dirichlet_zeta_deriv_bound for quickly bounding the derivative of the Riemann zeta function. * Fast multi-evaluation of the Riemann zeta function using Platt's algorithm (acb_dirichlet_platt_multieval) (contributed by D.H.J. Polymath). * Other special functions * Improved the algorithm in acb_hypgeom_u to estimate precision loss more accurately. * Implemented Coulomb wave functions (acb_hypgeom_coulomb, acb_hypgeom_coulomb_series and other functions). * Faster algorithm for Catalan's constant. * Added acb_modular_theta_series. * Added arb_poly_sinc_pi_series (contributed by D.H.J. Polymath). * Improved tuning in acb_hypgeom_pfq_series_sum for higher derivatives at high precision (reported by Mark Watkins). 2018-12-07 -- Arb 2.16.0 ------------------------------------------------------------------------------- * Linear algebra and arithmetic * Added acb_mat_approx_eig_qr for approximate computation of eigenvalues and eigenvectors of complex matrices. * Added acb_mat_eig_enclosure_rump implementing Rump's algorithm for certification of eigenvalue-eigenvector pairs as well as clusters. * Added acb_mat_eig_simple_rump for certified diagonalization of matrices with simple eigenvalues. * Added acb_mat_eig_simple_vdhoeven_mourrain, acb_mat_eig_simple for fast certified diagonalization of matrices with simple eigenvalues. * Added acb_mat_eig_multiple_rump, acb_mat_eig_multiple for certified computation of eigenvalues with possible overlap. * Added acb_mat_eig_global_enclosure for fast global inclusion of eigenvalues without isolation. * Added arb_mat_companion, acb_mat_companion for constructing companion matrices. * Added several arb_mat and acb_mat helper functions: indeterminate, is_exact, is_zero, is_finite, is_triu, is_tril, is_diag, diag_prod. * Added arb_mat_approx_inv, acb_mat_approx_inv. * Optimized arb_mat_mul_block by using arb_dot when the blocks are small. * Added acb_get_mid. * Updated hilbert_matrix example program. 2018-10-25 -- Arb 2.15.1 ------------------------------------------------------------------------------- * Fixed precision issue leading to spurious NaN results in incomplete elliptic integrals 2018-09-18 -- Arb 2.15.0 ------------------------------------------------------------------------------- * Arithmetic * Added arb_dot and acb_dot for efficient evaluation of dot products. * Added arb_approx_dot and acb_approx_dot for efficient evaluation of dot products without error bounds. * Converted loops to arb_dot and acb_dot in the arb_poly and acb_poly methods mullow_classical, inv_series, div_series, exp_series_basecase, sin_cos_series_basecase, sinh_cosh_series_basecase, evaluate_rectangular, evaluate2_rectangular, revert_series_lagrange_fast. Also changed the algorithm cutoffs for mullow, exp_series, sin_cos_series, sinh_cosh_series. * Converted loops to arb_dot and acb_dot in the arb_mat and acb_mat methods mul_classical, mul_threaded, solve_tril, solve_triu, charpoly. Also changed the algorithm cutoffs for mul, solve_tril, solve_triu. * Converted loops to arb_approx_dot and acb_approx_dot in the arb_mat and acb_mat methods approx_solve_tril, approx_solve_triu. Also changed the algorithm cutoffs. * Added arb_mat_approx_mul and acb_mat_approx_mul for matrix multiplication without error bounds. * Miscellaneous * Added arb_hypgeom_airy_zero for computing zeros of Airy functions. * Added arb_hypgeom_dilog wrapper. * Optimized arb_const_pi and arb_const_log2 by using a static table at low precision, giving a small speedup and avoiding common recomputation when starting threads. * Optimized mag_set_ui_2exp_si. * Remove obsolete and unused function _arb_vec_dot. * Converted some inline functions to ordinary functions to reduce library size. * Fixed acb_dirichlet_stieltjes to use the integration algorithm also when a != 1. * Fixed test failure for acb_dirichlet_stieltjes on ARM64 (reported by Gianfranco Costamagna). Special thanks to Julien Puydt for assistance with debugging. * Fixed crash in acb_dft_bluestein with zero length (reported by Gianfranco Costamagna). 2018-07-22 -- Arb 2.14.0 ------------------------------------------------------------------------------- * Linear algebra * Faster and more accurate real matrix multiplication using block decomposition, scaling, and multiplying via FLINT integer matrices in combination with safe use of doubles for radius matrix multiplications. * Faster and more accurate complex matrix multiplication by reordering and taking advantage of real matrix multiplication. * The new multiplication algorithm methods (arb_mat_mul_block, acb_mat_mul_reorder) are used automatically by the main multiplication methods. * Faster and more accurate LU factorization by using a block recursive algorithm that takes advantage of matrix multiplication. Added separate algorithm methods (arb/acb)_mat_lu_(recursive/classical) with an automatic algorithm choice in the default lu methods. * Added methods (arb/acb)_mat_solve_(tril/triu) (and variants) for solving upper or lower triangular systems using a block recursive algorithm taking advantage of matrix multiplication. * Improved linear solving and inverse for large well-conditioned matrices by using a preconditioning algorithm. Added separate solving algorithm methods (arb/acb)_mat_solve_(lu/precond) with an automatic algorithm choice in the default solve methods (contributed by anonymous user arbguest). * Improved determinants using a preconditioning algorithm. Added separate determinant algorithm methods (arb/acb)_mat_det_(lu/precond) with an automatic algorithm choice in the default det methods. * Added automatic detection of triangular matrices in arb_mat_det and acb_mat_det. * Added arb_mat_solve_preapprox which allows certifying a precomputed approximate solution (contributed by anonymous user arbguest). * Added methods for constructing various useful test matrices: arb_mat_ones, arb_mat_hilbert, arb_mat_pascal, arb_mat_stirling, arb_mat_dct, acb_mat_ones, acb_mat_dft. * Added support for window matrices (arb/acb_mat_window_init/clear). * Changed random test matrix generation (arb/acb_mat_randtest) to produce sparse matrices with higher probability. * Added acb_mat_conjugate and acb_mat_conjugate_transpose. * Arithmetic and elementary functions * Improved arb_sin_cos, arb_sin and arb_cos to produce more accurate enclosures for wide input intervals. The working precision is also reduced automatically based on the accuracy of the input to improve efficiency. * Improved arb_sinh_cosh, arb_sinh and arb_cosh to produce more accurate enclosures for wide input intervals. The working precision is also reduced automatically based on the accuracy of the input to improve efficiency. * Improved arb_exp_invexp and arb_expm1 to produce more accurate enclosures for wide input intervals. The working precision is also reduced automatically based on the accuracy of the input to improve efficiency. * Improved acb_rsqrt to produce more accurate enclosures for wide intervals. * Made mag_add_ui_lower public. * Added mag_sinh, mag_cosh, mag_sinh_lower, mag_cosh_lower. * Fixed minor precision loss near -1 in arb_log_hypot and acb_log. * Return imaginary numbers with exact zero real part when possible in acb_acos and acb_acosh (contributed by Ralf Stephan). * Improved special cases in arb_set_interval_arf (reported by Marc Mezzarobba). * Special functions * Added a function for computing isolated generalized Stieltjes constants (acb_dirichlet_stieltjes). * Added scaled versions of Bessel functions (acb_hypgeom_bessel_i_scaled, acb_hypgeom_bessel_k_scaled). * The interface for the internal methods computing Bessel functions (i_asymp, k_asymp, etc.) has been changed to accommodate computing scaled versions. * Added Riemann xi function (acb_dirichlet_xi) (contributed by D.H.J Polymath). * Fixed infinite error bounds in the Riemann zeta function when evaluating at a ball containing zero centered in the left plane (contributed by D.H.J Polymath). * Fixed precision loss in Airy functions with huge input and high precision. * Legendre functions of the first kind (legendre_p): handle inexact integer a+b-c in 2F1 better (contributed by Joel Dahne). * Example programs and documentation * Added more color functions to complex_plot.c. * Added more example integrals suggested by Nicolas Brisebarre and Bruno Salvy to integrals.c * Changed Sphinx style and redesigned the documentation front page. * Miscellaneous documentation cleanups. * Added documentation page about contributing. * Other * Fixed a crash on some systems when calling acb_dft methods with a length of zero. * Fixed issue with setting rpath in configure (contributed by Vincent Delecroix). 2018-02-23 -- Arb 2.13.0 ------------------------------------------------------------------------------- * Major bugs * Fixed rounding direction in arb_get_abs_lbound_arf() which in some cases could result in an invalid lower bound being returned, and added forgotten test code for this and related functions (reported by deinst). Although this bug could lead to incorrect results, it probably had limited impact in practice (explaining why it was not caught indirectly by other test code) since a single rounding in the wrong direction in this operation generally will be dwarfed by multiple roundings in the correct direction in surrounding operations. * Important notes about bounds * Many functions have been modified to compute tighter enclosures when the input balls are wide. In most cases the bounds should be improved, but there may be some regressions. Bug reports about any significant regressions are welcome. * Division by zero in arb_div() has been changed to return [NaN +/- inf] instead of [+/- inf]. This change might be reverted in the future if it proves to be too inconvenient. In either case, users should only assume that division by zero produces something non-finite, and user code that depends on division by zero to produce [0 +/- inf] should be modified to handle zero-containing denominators as a separate case. * Improvements to arithmetic and elementary functions * Faster implementation of acb_get_mag_lower(). * Optimized arb_get_mag_lower(), arb_get_mag_lower_nonnegative(). * Added arb_set_interval_mag() and arb_set_interval_neg_pos_mag() for constructing an arb_t from a pair of mag_t endpoints. * Added mag_const_pi_lower(), mag_atan(), mag_atan_lower(). * Added mag_div_lower(), mag_inv(), mag_inv_lower(). * Added mag_sqrt_lower() and mag_rsqrt_lower(). * Added mag_log(), mag_log_lower(), mag_neg_log(), mag_neg_log_lower(). * Added mag_exp_lower(), mag_expinv_lower() and tweaked mag_exp(). * Added mag_pow_fmpz_lower(), mag_get_fmpz(), mag_get_fmpz_lower(). * Improved arb_exp() for wide input. * Improved arb_log() for wide input. * Improved arb_sqrt() for wide input. * Improved arb_rsqrt() for wide input. * Improved arb_div() for wide input. * Improved arb_atan() for wide input and slightly optimized arb_atan2() for input spanning multiple signs. * Improved acb_rsqrt() for wide input and improved stability of this function generally in the left half plane. * Added arb_log_hypot() and improved acb_log() for wide input. * Slightly optimized trigonometric functions (acb_sin(), acb_sin_pi(), acb_cos(), acb_cos_pi(), acb_sin_cos(), acb_sin_cos_pi()) for pure real or imaginary input. * Special functions * Slightly improved bounds for gamma function (arb_gamma(), acb_gamma(), arb_rgamma(), acb_rgamma()) for wide input. * Improved bounds for Airy functions for wide input. * Simplifications to code for computing Gauss period minimal polynomials (contributed by Jean-Pierre Flori). * Optimized arb_hypgeom_legendre_p_ui() further by avoiding divisions in the basecase recurrence and computing the prefactor more quickly in the asymptotic series (contributed by Marc Mezzarobba). * Small further optimization of arb_hypgeom_legendre_p_ui_root() (contributed by Marc Mezzarobba). * Improved derivative bounds for Legendre polynomials (contributed by Marc Mezzarobba). * Numerical integration * Increased default quadrature deg_limit at low precision to improve performance for integration of functions without singularities near the path. * Added several more integrals to examples/integrals.c * Added utility functions acb_real_abs(), acb_real_sgn(), acb_real_heaviside(), acb_real_floor(), acb_real_ceil(), acb_real_min(), acb_real_max(), acb_real_sqrtpos(), useful for numerical integration. * Added utility functions acb_sqrt_analytic(), acb_rsqrt_analytic(), acb_log_analytic(), acb_pow_analytic() with branch cut detection, useful for numerical integration. * Build system and compatibility issues * Removed -Wl flag from Makefile.subdirs to fix "-r and -pie may not be used together" compilation error on some newer Linux distributions (reported by many users). * Fixed broken test code for l_vec_hurwitz which resulted in spurious failures on 32-bit systems (originally reported by Thierry Monteil on Sage trac). * Avoid using deprecated MPFR function mpfr_root() with MPFR versions >= 4.0.0. * Remark: the recently released MPFR 4.0.0 has a bug in mpfr_div() leading to test failures in Arb (though not affecting correctness of Arb itself). Users should make sure to install the patched version MPFR 4.0.1. * Added missing C++ include guards in arb_fmpz_poly.h and dlog.h (reported by Marc Mezzarobba). * Fixed Travis builds on Mac OS again (contributed by Isuru Fernando). * Added missing declaration for arb_bell_ui() (reported by numsys). 2017-11-29 -- Arb 2.12.0 ------------------------------------------------------------------------------- * Numerical integration * Added a new function (acb_calc_integrate) for rigorous numerical integration using adaptive subdivision and Gauss-Legendre quadrature. This largely obsoletes the old integration code using Taylor series. * Added new integrals.c example program (old example program moved to integrals_taylor.c). * Discrete Fourier transforms * Added acb_dft module with various FFT algorithm implementations, including top level O(n log n) acb_dft and acb_dft_inverse functions (contributed by Pascal Molin). * Legendre polynomials * Added arb_hypgeom_legendre_p_ui for fast and accurate evaluation of Legendre polynomials. This is also used automatically by the Legendre functions, where it is substantially faster and gives better error bounds than the generic algorithm. * Added arb_hypgeom_legendre_p_ui_root for fast computation of Legendre polynomial roots and Gauss-Legendre quadrature nodes (used internally by the new integration code). * Added arb_hypgeom_central_bin_ui for fast computation of central binomial coefficients (used internally for Legendre polynomials). * Dirichlet L-functions and zeta functions * Fixed a bug in the Riemann zeta function involving a too small error bound in the implementation of the Riemann-Siegel formula for inexact input. This bug could result in a too small enclosure when evaluating the Riemann zeta function at an argument of large imaginary height without also computing derivatives, if the input interval was very wide. * Add acb_dirichlet_zeta_jet; also made computation of the first derivative of Riemann zeta function use the Riemann-Siegel formula where appropriate. * Added acb_dirichlet_l_vec_hurwitz for fast simultaneous evaluation of Dirichlet L-functions for multiple characters using Hurwitz zeta function and FFT (contributed by Pascal Molin). * Simplified interface for using hurwitz_precomp functions. * Added lcentral.c example program (contributed by Pascal Molin). * Improved error bounds when evaluating Dirichlet L-functions using Euler product. * Elementary functions * Faster custom implementation of sin, cos at 4600 bits and above instead of using MPFR (30-40% asymptotic improvement, up to a factor two speedup). * Faster code for exp between 4600 and 19000 bits. * Improved error bounds for acb_atan by using derivative. * Improved error bounds for arb_sinh_cosh, arb_sinh and arb_cosh when the input has a small midpoint and large radius. * Added reciprocal trigonometric and hyperbolic functions (arb_sec, arb_csc, arb_sech, arb_csch, acb_sec, acb_csc, acb_sech, acb_csch). * Changed the interface of _acb_vec_unit_roots to take an extra length parameter (compatibility-breaking change). * Improved arb_pow and acb_pow with an inexact base and a negative integer or negative half-integer exponent; the inverse is now computed before performing binary exponentiation in this case to avoid spurious blow-up. * Elliptic functions * Improved Jacobi theta functions to reduce the argument modulo the lattice parameter, greatly improving speed and numerical stability for large input. * Optimized arb_agm by using a final series expansion and using special code for wide intervals. * Optimized acb_agm1 by using a final series expansion and using special code for positive real input. * Optimized derivative of AGM for high precision by using a central difference instead of a forward difference. * Optimized acb_elliptic_rf and acb_elliptic_rj for high precision by using a variable length series expansion. * Other * Fixed incorrect handling of subnormals in arf_set_d. * Added mag_bin_uiui for bounding binomial coefficients. * Added mag_set_d_lower, mag_sqrt_lower, mag_set_d_2exp_fmpz_lower. * Implemented multithreaded complex matrix multiplication. * Optimized arb_rel_accuracy_bits by adding fast path. * Fixed a spurious floating-point exception (division by zero) in the t-gauss_period_minpoly test program triggered by new code optimizations in recent versions of GCC that are unsafe together with FLINT inline assembly functions (a workaround was added to the test code, and a proper fix for the assembly code has been added to FLINT). 2017-07-10 -- Arb 2.11.1 ------------------------------------------------------------------------------- * Avoid use of a function that was unavailable in the latest public FLINT release 2017-07-09 -- Arb 2.11.0 ------------------------------------------------------------------------------- * Special functions * Added the Lambert W function (arb_lambertw, acb_lambertw, arb_poly_lambertw_series, acb_poly_lambertw_series). All complex branches and evaluation of derivatives are supported. * Added the acb_expm1 method, complementing arb_expm1. * Added arb_sinc_pi, acb_sinc_pi. * Optimized handling of more special cases in the Hurwitz zeta function. * Polynomials * Added the arb_fmpz_poly module to provide Arb methods for FLINT integer polynomials. * Added methods for evaluating an fmpz_poly at arb_t and acb_t arguments. * Added arb_fmpz_poly_complex_roots for computing the real and complex roots of an integer polynomial, turning the functionality previously available in the poly_roots.c example program into a proper library function. * Added a method (arb_fmpz_poly_gauss_period_minpoly) for constructing minimal polynomials of Gaussian periods. * Added arb_poly_product_roots_complex for constructing a real polynomial from complex conjugate roots. * Miscellaneous * Fixed test code in the dirichlet module for 32-bit systems (contributed by Pascal Molin). * Use flint_abort() instead of abort() (contributed by Tommy Hofmann). * Fixed the static library install path (contributed by François Bissey). * Made arb_nonnegative_part() a publicly documented method. * Arb now requires FLINT version 2.5 or later. 2017-02-27 -- Arb 2.10.0 ------------------------------------------------------------------------------- * General * Changed a large number of methods from inline functions to normal functions, substantially reducing the size of the built library. * Fixed a few minor memory leaks (missing clear() calls). * Basic arithmetic * Added arb_is_int_2exp_si and acb_is_int_2exp_si. * Added arf_sosq for computing x^2+y^2 of floating-point numbers. * Improved error bounds for complex square roots in the left half plane. * Improved error bounds for complex reciprocal (acb_inv) and division. * Added the internal helper mag_get_d_log2_approx as a public method. * Elliptic functions and integrals * New module acb_elliptic.h for elliptic functions and integrals. * Added complete elliptic integral of the third kind. * Added Legendre incomplete elliptic integrals (first, second, third kinds). * Added Carlson symmetric incomplete elliptic integrals (RF, RC, RG, RJ, RD). * Added Weierstrass elliptic zeta and sigma functions. * Added inverse Weierstrass elliptic p-function. * Added utility functions for computing the Weierstrass invariants and lattice roots. * Improved computation of derivatives of Jacobi theta functions by using modular transformations, and added a main evaluation function (acb_modular_theta_jet). * Improved detection of pure real or pure imaginary parts in various cases of evaluating theta and modular functions. * Other special functions * New, far more efficient implementation of the dilogarithm function (acb_polylog with s = 2). * Fixed an issue in the Hurwitz zeta function leading to unreasonable slowdown for certain complex input. * Added add acb_poly_exp_pi_i_series. * Added arb_poly_log1p_series, acb_poly_log1p_series. 2016-12-02 -- Arb 2.9.0 ------------------------------------------------------------------------------- * License * Changed license from GPL to LGPL. * Build system and compatibility * Fixed FLINT includes to use flint/foo.h instead of foo.h, simplifying compilation on many systems. * Added another alias for the dynamic library to fix make check on certain systems (contributed by Andreas Enge). * Travis CI support (contributed by Isuru Fernando). * Added support for ARB_TEST_MULTIPLIER environment variable to control the number of test iterations. * Support building with CMake (contributed by Isuru Fernando). * Support building with MSVC on Windows (contributed by Isuru Fernando). * Fixed unsafe use of FLINT_ABS for slong -> ulong conversion in arf.h, which caused failures on MIPS and ARM systems. * Basic arithmetic and methods * Fixed mag_addmul(x,x,x) with x having a mantissa of all ones. This could produce a non-normalized mag_t value, potentially leading to incorrect results in arb and acb level arithmetic. This bug was caught by new test code, and fortunately would have been hard to trigger accidentally. * Added fasth paths for error bound calculations in arb_sqrt and arb_div, speeding up these operations significantly at low precision * Added support for round-to-nearest in all arf methods. * Added fprint methods (contributed by Alex Griffing). * Added acb_printn and acb_fprintn methods to match arb_printn. * Added arb_equal_si and acb_equal_si. * Added arb_can_round_mpfr. * Added arb_get_ubound_arf, arb_get_lbound_arf (contributed by Tommy Hofmann). * Added sign function (arb_sgn). * Added complex sign functions (acb_sgn, acb_csgn). * Rewrote arb_contains_fmpq to make the test exact. * Optimized mag_get_fmpq. * Optimized arf_get_fmpz and added more robust test code. * Rewrote arb_get_unique_fmpz and arb_get_interval_fmpz_2exp, reducing overhead, making them more robust with huge exponents, and documenting their behavior more carefully. * Optimized arb_union. * Optimized arf_is_int, arf_is_int_2exp_si and changed these from inline to normal functions. * Added mag_const_pi, mag_sub, mag_expinv. * Optimized binary-to-decimal conversion for huge exponents by using exponential function instead of binary powering. * Added arb_intersection (contributed by Alex Griffing). * Added arb_min, arb_max (contributed by Alex Griffing). * Fixed a bug in arb_log and in test code on 64-bit Windows due to unsafe use of MPFR which only uses 32-bit exponents on Win64. * Improved some test functions to reduce the chance of reporting spurious failures. * Added squaring functions (arb_sqr, acb_sqr) (contributed by Ricky Farr). * Added arf_frexp. * Added arf_cmp_si, arf_cmp_ui, arf_cmp_d. * Added methods to count allocated bytes (arb_allocated_bytes, _arb_vec_allocated_bytes, etc.). * Added methods to predict memory usage for large vectors (_arb/_acb_vec_estimate_allocated_bytes). * Changed clear() methods from inline to normal functions, giving 8% faster compilation and 25% smaller libarb.so. * Added acb_unit_root and _acb_vec_unit_roots (contributed by Pascal Molin). * Polynomials * Added sinh and cosh functions of power series (arb/acb_poly_sinh/cosh_series and sinh_cosh_series). * Use basecase series inversion algorithm to improve speed and error bounds in arb/acb_poly_inv_series. * Added functions for fast polynomial Taylor shift (arb_poly_taylor_shift, acb_poly_taylor_shift and variants). * Fast handling of special cases in polynomial composition. * Added acb_poly scalar mul and div convenience methods (contributed by Alex Griffing). * Added set_trunc, set_trunc_round convenience methods. * Added add_series, sub_series methods for truncating addition. * Added polynomial is_zero, is_one, is_x, valuation convenience methods. * Added hack to arb_poly_mullow and acb_poly_mullow to avoid overhead when doing an in-place multiplication with length at most 2. * Added binomial and Borel transform methods for acb_poly. * Matrices * Added Cholesky decomposition plus solving and inverse for positive definite matrices (arb_mat_cho, arb_mat_spd_solve, arb_mat_spd_inv and related methods) (contributed by Alex Griffing). * Added LDL decomposition and inverse and solving based on LDL decomposition for real matrices (arb_mat_ldl, arb_mat_solve_ldl_precomp, arb_mat_inv_ldl_precomp) (contributed by Alex Griffing). * Improved the entrywise error bounds in matrix exponential computation to preserve sparsity and give exact entries where possible in many cases (contributed by Alex Griffing). * Added public functions for computing the truncated matrix exponential Taylor series (arb_mat_exp_taylor_sum, acb_mat_exp_taylor_sum). * Added functions related to sparsity structure (arb_mat_entrywise_is_zero, arb_mat_count_is_zero, etc.) (contributed by Alex Griffing). * Entrywise multiplication (arb_mat_mul_entrywise, acb_mat_mul_entrywise) (contributed by Alex Griffing). * Added is_empty and is_square convenience methods (contributed by Alex Griffing). * Added the bool_mat helper module for matrices over the boolean semiring (contributed by Alex Griffing). * Added Frobenius norm computation (contributed by Alex Griffing). * Miscellaneous special functions * Added evaluation of Bernoulli polynomials (arb_bernoulli_poly_ui, acb_bernoulli_poly_ui). * Added convenience function for evaluation of huge Bernoulli numbers (arb_bernoulli_fmpz). * Added Euler numbers (arb_euler_number_ui, arb_euler_number_fmpz). * Added fast approximate partition function (arb_partitions_fmpz/ui). * Optimized partition function for n < 1000 by using recurrence for the low 64 bits. * Improved the worst-case error bound in arb_atan. * Added arb_log_base_ui. * Added complex sinc function (acb_sinc). * Special handling of z = 1 when computing polylogarithms. * Fixed agm(-1,-1) to output 0 instead of indeterminate. * Made working precision in arb_gamma and acb_gamma more sensitive to the input accuracy. * Hypergeometric functions * Compute erf and erfc without cancellation problems for large or complex z. * Avoid re-computing the square root of pi in several places. * Added generalized hypergeometric function (acb_hypgeom_pfq). * Implement binary splitting and rectangular splitting for evaluation of hypergeometric series with a power series parameter, greatly speeding up Y_n, K_n and other functions at high precision, as well as speeding up high-order parameter derivatives. * Use binary splitting more aggressively in acb_hypgeom_pfq_sum to reduce error bound inflation. * Asymptotic expansions of hypergeometric functions: more accurate parameter selection, and better handling of terminating cases. * Tweaked algorithm selection and working precision in acb_hypgeom_m. * Avoid dividing by the denominator of the next term in acb_hypgeom_sum, which would lead to a division by zero when evaluating hypergeometric polynomials. * Fixed a bug in hypergeometric series evaluation resulting in near-integers not being skipped in some cases, leading to unnecessary loss of precision. * Added series expansions of Airy functions (acb_hypgeom_airy_series, acb_hypgeom_airy_jet). * Fixed a case where Airy functions accidentally chose the worst algorithm instead of the best one. * Added functions for computing erf, erfc, erfi of power series in the acb_hypgeom module. * Added series expansion of the logarithmic integral (acb_hypgeom_li_series). * Added Fresnel integrals (acb_hypgeom_fresnel, acb_hypgeom_fresnel_series). * Added the lower incomplete gamma function (acb_hypgeom_gamma_lower) (contributed by Alex Griffing). * Added series expansion of the lower incomplete gamma function (acb_hypgeom_gamma_lower_series) (contributed by Alex Griffing). * Added support for computing the regularized incomplete gamma functions. * Use slightly sharper error bound for analytic continuation of 2F1. * Added support for computing finite limits of 2F1 with inexact parameters differing by integers. * Added the incomplete beta function (acb_hypgeom_beta_lower, acb_hypgeom_beta_lower_series) * Improved acb_hypgeom_u to use a division-avoiding algorithm for small polynomial cases. * Added arb_hypgeom module, wrapping the complex hypergeometric functions for more convenient use with the arb_t type. * Dirichlet L-functions and Riemann zeta function * New module dirichlet for working algebraically with Dirichlet groups and characters (contributed by Pascal Molin). * New module acb_dirichlet for numerical evaluation of Dirichlet characters and L-functions (contributed by Pascal Molin). * Efficient representation and manipulation of Dirichlet characters using the Conrey representation (contributed by Pascal Molin). * New module dlog for word-size discrete logarithm evaluation, used to support algorithms on Dirichlet characters (contributed by Pascal Molin). * Methods for properties, evaluation, iteration, pairing, lift, lowering etc. of Dirichlet characters (contributed by Pascal Molin). * Added acb_dirichlet_roots methods for fast evaluation of many roots of unity (contributed by Pascal Molin). * Added acb_dirichlet_hurwitz_precomp methods for fast multi-evaluation of the Hurwitz zeta function for many parameter values. * Added methods for computing Gauss, Jacobi and theta sums over Dirichlet characters (contributed by Pascal Molin). * Added methods (acb_dirichlet_l, acb_dirichlet_l_jet, acb_dirichlet_l_series) for evaluation of Dirichlet L-functions and their derivatives. * Implemented multiple algorithms for evaluation of Dirichlet L-functions depending on the argument (Hurwitz zeta function decomposition, Euler product, functional equation). * Added methods (acb_dirichlet_hardy_z, acb_dirichlet_hardy_z_series, etc.) for computing the Hardy Z-function corresponding to a Dirichlet L-function. * Added fast bound for Hurwitz zeta function (mag_hurwitz_zeta_uiui). * Improved parameter selection in Hurwitz zeta function to target relative instead of absolute error for large positive s. * Improved parameter selection in Hurwitz zeta function to avoid computing unnecessary Bernoulli numbers for large imaginary s. * Added Dirichlet eta function (acb_dirichlet_eta). * Implemented the Riemann-Siegel formula for faster evaluation of the Riemann zeta function at large height. * Added smooth-index algorithm for the main sum when evaluating the Riemann zeta function, avoiding the high memory usage of the full sieving algorithm when the number of terms gets huge. * Improved tuning for using the Euler product when computing the Riemann zeta function. * Example programs * Added logistic map example program. * Added lvalue example program. * Improved poly_roots in several ways: identify roots that are exactly real, automatically perform squarefree factorization, use power hack, and allow specifying a product of polynomials as input on the command line. * Housekeeping * New section in the documentation giving an introduction to ball arithmetic and using the library. * Tidied, documented and added test code for the fmpz_extras module. * Added proper documentation and test code for many helper methods. * Removed the obsolete fmprb module entirely. * Documented more algorithms and formulas. * Clarified integer overflow issues and use of ARF_PREC_EXACT in the documentation. * Added .gitignore file. * Miscellaneous improvements to the documentation. 2015-12-31 -- Arb 2.8.1 ------------------------------------------------------------------------------- * Fixed 32-bit test failure for the Laguerre function. * Made the Laguerre function indeterminate at negative integer orders, to be consistent with the test code. 2015-12-29 -- Arb 2.8.0 ------------------------------------------------------------------------------- * Compatibility and build system * Windows64 support (contributed by Bill Hart). * Fixed a bug that broke basic arithmetic on targets where FLINT uses fallback code instead of assembly code, such as PPC64 (contributed by Jeroen Demeyer). * Fixed configure to use EXTRA_SHARED_FLAGS/LDFLAGS, and other build system fixes (contributed by Tommy Hofmann, Bill Hart). * Added soname versioning (contributed by Julien Puydt). * Fixed test code on MinGW (contributed by Hrvoje Abraham). * Miscellaneous fixes to simplify interfacing Arb from Julia. * Arithmetic and elementary functions * Fixed arf_get_d to handle underflow/overflow correctly and to support round-to-nearest. * Added more complex inverse hyperbolic functions (acb_asin, acb_acos, acb_asinh, acb_acosh, acb_atanh). * Added arb_contains_int and acb_contains_int for testing whether an interval contains any integer. * Added acb_quadratic_roots_fmpz. * Improved arb_sinh to use a more accurate formula for x < 0. * Added sinc function (arb_sinc) (contributed by Alex Griffing). * Fixed bug in arb_exp affecting convergence for huge input. * Faster implementation of arb_div_2expm1_ui. * Added mag_root, mag_geom_series. * Improved and added test code for arb_add_error functions. * Changed arb_pow and acb_pow to make pow(0,positive) = 0 instead of nan. * Improved acb_sqrt to return finite output for finite input straddling the branch cut. * Improved arb_set_interval_arf so that [inf,inf] = inf instead of an infinite interval. * Added computation of Bell numbers (arb_bell_fmpz). * Added arb_power_sum_vec for computing power sums using Bernoulli numbers. * Added computation of the Fujiwara root bound for acb_poly. * Added code to identify all the real roots of a real polynomial (acb_poly_validate_real_roots). * Added several convenient assignment functions, including arb_set_d, acb_set_d, acb_set_d_d, acb_set_fmpz_fmpz (contributed by Ricky Farr). * Added many accessor functions (_arb/acb_vec_entry_ptr, arb_get_mid/rad_arb, acb_real/imag_ptr, arb_mid/rad_ptr, acb_get_real/imag). * Added missing functions acb_add_si, acb_sub_si. * Renamed arb_root to arb_root_ui (keeping alias) and added acb_root_ui. * Special functions * Implemented the Gauss hypergeometric function 2F1 and its regularized version. * Fixed two bugs in acb_hypgeom_pfq_series_direct discovered while implementing 2F1. In rare cases, these could lead to incorrect values for functions depending on parameter derivatives of hypergeometric series. * The first bug involved incorrect handling of negative integer parameters. The bug only affected 2F1 and higher functions; it did not affect correctness of any previously implemented functions that relied on acb_hypgeom_pfq_series_direct (such as Bessel Y and K functions of integer order). * The second bug involved a too small bound being computed for the sum of a geometric series. The geometric series bound is nearly tight for 2F1, and the incorrect version caused immediate test failures for that function. Theoretically, this bug affected correctness of some previously-implemented functions that relied on acb_hypgeom_pfq_series_direct (such as Bessel Y and K functions of integer order), but since the geometric bound is not as tight in those cases, those functions were still reliable in practice (no failing test case has been found). * Implemented Airy functions and their derivatives (acb_hypgeom_airy). * Implemented the confluent hypergeometric function 0F1 (acb_hypgeom_0f1). * Implemented associated Legendre functions P and Q. * Implemented Chebyshev, Jacobi, Gegenbauer, Laguerre, Hermite functions. * Implemented spherical harmonics. * Added function for computing Bessel J and Y functions simultaneously. * Added rising factorials for non-integer n (arb_rising, acb_rising). * Made rising factorials use gamma function for large integer n. * Faster algorithm for theta constants and Dedekind eta function at very high precision. * Fixed erf to give finite values instead of +/-inf for big imaginary input. * Improved acb_zeta (and arb_zeta) to automatically use fast code for integer zeta values. * Added double factorial (arb_doublefac_ui). * Added code for generating Hilbert class polynomials (acb_modular_hilbert_class_poly). * Matrices * Added faster matrix squaring (arb/acb_mat_sqr) (contributed by Alex Griffing). * Added matrix trace (arb/acb_mat_trace) (contributed by Alex Griffing). * Added arb/acb_mat_set_round_fmpz_mat, acb_mat_set(_round)_arb_mat (contributed by Tommy Hofmann). * Added arb/acb_mat_transpose (contributed by Tommy Hofmann). * Added comparison methods arb/acb_mat_eq/ne (contributed by Tommy Hofmann). * Other * Added complex_plot example program. * Added Airy functions to real_roots example program. * Other minor patches were contributed by Alexander Kobel, Marc Mezzarobba, Julien Puydt. * Removed obsolete file config.h. 2015-07-14 -- Arb 2.7.0 ------------------------------------------------------------------------------- * Hypergeometric functions * Implemented Bessel I and Y functions (acb_hypgeom_bessel_i, acb_hypgeom_bessel_y). * Fixed bug in Bessel K function giving the wrong branch for negative real arguments. * Added code for evaluating complex hypergeometric series binary splitting. * Added code for evaluating complex hypergeometric series using fast multipoint evaluation. * Gamma related functions * Implemented the Barnes G-function and its continuous logarithm (acb_barnes_g, acb_log_barnes_g). * Implemented the generalized polygamma function (acb_polygamma). * Implemented the reflection formula for the logarithmic gamma function (acb_lgamma, acb_poly_lgamma_series). * Implemented the digamma function of power series (arb_poly_digamma_series, acb_poly_digamma_series). * Improved acb_poly_zeta_series to produce exact zero imaginary parts in most cases when the result should be real-valued. * Made the real logarithmic gamma function (arb_lgamma, arb_poly_lgamma_series) abort more quickly for negative input. * Elementary functions * Added arb_exp_expinv and acb_exp_expinv functions for simultaneously computing exp(x), exp(-x). * Improved acb_tan, acb_tan_pi, acb_cot and acb_cot_pi for input with large imaginary parts. * Added complex hyperbolic functions (acb_sinh, acb_cosh, acb_sinh_cosh, acb_tanh, acb_coth). * Added acb_log_sin_pi for computing the logarithmic sine function without branch cuts away from the real line. * Added arb_poly_cot_pi_series, acb_poly_cot_pi_series. * Added arf_root and improved speed of arb_root. * Tuned algorithm selection in arb_pow_fmpq. * Other * Added documentation for arb and acb vector functions. 2015-04-19 -- Arb 2.6.0 ------------------------------------------------------------------------------- * Special functions * Added the Bessel K function. * Added the confluent hypergeometric functions M and U. * Added exponential, trigonometric and logarithmic integrals ei, si, shi, ci, chi, li. * Added the complete elliptic integral of the second kind E. * Added support for computing hypergeometric functions with power series as parameters. * Fixed special cases in Bessel J function returning useless output. * Fixed precision of zeta function accidentally being capped at 7000 digits (bug in 2.5). * Special-cased real input in the gamma functions for complex types. * Fixed exp of huge numbers outputting unnecessarily useless intervals. * Fixed broken code in erf that sometimes gave useless output. * Made selection of number of terms in hypergeometric series more robust. * Polynomials and power series. * Added sin_pi, cos_pi and sin_cos_pi for real and complex power series. * Speeded up series reciprocal and division for length = 2. * Added add_si methods for polynomials. * Made inv_series and div_series with zero input produce indeterminates instead of aborting. * Added arb_poly_majorant, acb_poly_majorant. * Basic functions * Added comparison methods arb_eq, arb_ne, arb_lt, arb_le, arb_gt, arb_ge, acb_eq, acb_ne. * Added acb_rel_accuracy_bits and improved the real version. * Fixed precision of constants like pi behaving more nondeterministically than necessary. * Fixed arf_get_mag_lower(nan) to output 0 instead of inf. * Other * Removed call to fmpq_dedekind_sum which only exists in the git version of flint. * Fixed a test code bug that could cause crashes on some systems. * Added fix for static build on OS X (thanks Marcello Seri). * Miscellaneous corrections to the documentation. 2015-01-28 -- Arb 2.5.0 ------------------------------------------------------------------------------- * String conversion * Added arb_set_str. * Added arb_get_str and arb_printn for pretty-printed rigorous decimal output. * Added helper functions for binary to decimal conversion. * Core arithmetic * Improved speed of division when using GMP instead of MPIR. * Improved complex division with a small denominator. * Removed a little bit of overhead for complex squaring. * Special functions * Faster code for atan at very high precision, used instead of mpfr_atan. * Optimized elementary functions slightly for small input. * Added modified error functions erfc and erfi. * Added the generalized exponential integral. * Added the upper incomplete gamma function. * Implemented the complete elliptic integral of the first kind. * Implemented the arithmetic-geometric mean of complex numbers. * Optimized arb_digamma for small integers. * Made mag_log_ui, mag_binpow_uiui and mag_polylog_tail proper functions. * Added pow, agm, erf, elliptic_k, elliptic_p as functions of complex power series. * Added incomplete gamma function of complex power series. * Improved code for bounding complex rising factorials (the old code could potentially have given wrong results in degenerate cases). * Added arb_sqrt1pm1, arb_atanh, arb_asinh, arb_atanh. * Added arb_log1p, acb_log1p, acb_atan. * Added arb_hurwitz_zeta. * Improved parameter selection in the Hurwitz zeta function to try to avoid stalling when given enormous input. * Optimized sqrt and rsqrt of power series when given a binomial as input. * Made arb_bernoulli_ui(2^64-2) not crash. * Fixed rgamma of negative integers returning indeterminate. * Polynomials and matrices * Added characteristic polynomial computation for real and complex matrices. * Added polynomial set_round methods. * Added is_real methods for more types. * Added more get_unique_fmpz methods. * Added code for generating Swinnerton-Dyer polynomials. * Improved error bounding in det() and exp() of complex matrices to recognize when the result is real-valued. * Changed polynomial divrem to return success/fail instead of aborting on divide by zero. * Miscellaneous * Added logo to documentation. * Made inlined functions build as part of the library. * Silenced a clang warning. * Made _acb_vec_sort_pretty a library function. 2014-11-15 -- Arb 2.4.0 ------------------------------------------------------------------------------- * Arithmetic and core functions * Made evaluation of sin, cos and exp at medium precision faster using the sqrt trick. * Optimized arb_sinh and arb_sinh_cosh. * Optimized complex division with a small denominator. * Optimized cubing of complex numbers. * Added floor and ceil functions for the arf and arb types. * Added acb_poly powering functions. * Added acb_exp_pi_i. * Added functions for evaluation of Chebyshev polynomials. * Fixed arb_div to output nan for input containing nan. * Added a module acb_hypgeom for hypergeometric functions * Evaluation of the generalized hypergeometric function in convergent cases. * Evaluation of confluent hypergeometric functions using asymptotic expansions. * The Bessel function of the first kind for complex input. * The error function for complex input. * Added a module acb_modular for modular forms and elliptic functions * Support for working with modular transformations. * Mapping a point to the fundamental domain. * Evaluation of Jacobi theta functions and their series expansions. * The Dedekind eta function. * The j-invariant and the modular lambda and delta function. * Eisenstein series. * The Weierstrass elliptic function and its series expansion. * Miscellaneous * Fixed mag_print printing a too large exponent. * Fixed printd methods to use a fallback instead of aborting when printing numbers too large for MPFR. * Added version number string (arb_version). * Various additions to the documentation. 2014-09-25 -- Arb 2.3.0 ------------------------------------------------------------------------------- * Removed most of the legacy (Arb 1.x) modules. * Updated build scripts, hopefully fixing various issues. * New implementations of arb_sin, arb_cos, arb_sin_cos, arb_atan, arb_log, arb_exp, arb_expm1, much faster up to a few thousand bits. * Ported the bit-burst code for high-precision exponentials to the arb type. * Speeded up arb_log_ui_from_prev. * Added mag_exp, mag_expm1, mag_exp_tail, mag_pow_fmpz. * Improved various mag functions. * Added arb_get/set_interval_mpfr, arb_get_interval_arf, and improved arb_set_interval_arf. * Improved arf_get_fmpz. * Prettier printing of complex numbers with negative imaginary part. * Changed some frequently-used functions from inline to non-inline to reduce code size. 2014-08-01 -- Arb 2.2.0 ------------------------------------------------------------------------------- * Added functions for computing polylogarithms and order expansions of polylogarithms, with support for real and complex s, z. * Added a missing cast affecting C++ compatibility. * Generalized powsum functions to allow a geometric factor. * Improved powsum functions slightly when the exponent is an integer. * Faster arb_log_ui_from_prev. * Added mag_sqrt and mag_rsqrt functions. * Fixed various minor bugs and added missing tests and documentation entries. 2014-06-20 -- Arb 2.1.0 ------------------------------------------------------------------------------- * Ported most of the remaining functions to the new arb/acb types, including: * Elementary functions (log, atan, etc.). * Hypergeometric series summation. * The gamma function. * The Riemann zeta function and related functions. * Bernoulli numbers. * The partition function. * The calculus modules (rigorous real root isolation, rigorous numerical integration of complex-valued functions). * Example programs. * Added several missing utility functions to the arf and mag modules. 2014-05-27 -- Arb 2.0.0 ------------------------------------------------------------------------------- * New modules mag, arf, arb, arb_poly, arb_mat, acb, acb_poly, acb_mat for higher-performance ball arithmetic. * Poly_roots2 and hilbert_matrix2 example programs. * Vector dot product and norm functions (contributed by Abhinav Baid). 2014-05-03 -- Arb 1.1.0 ------------------------------------------------------------------------------- * Faster and more accurate error bounds for polynomial multiplication (error bounds are now always as good as with classical multiplication, and multiplying high-degree polynomials with approximately equal coefficients now has proper quasilinear complexity). * Faster and much less memory-hungry exponentials at very high precision. * Improved the partition function to support n bigger than a single word, and enabled the possibility to use two threads for the computation. * Fixed a bug in floating-point arithmetic that caused a too small bound for the rounding error to be reported when the result of an inexact operation was rounded up to a power of two (this bug did not affect the correctness of ball arithmetic, because operations on ball midpoints always round down). * Minor optimizations to floating-point arithmetic. * Improved argument reduction of the digamma function and short series expansions of the rising factorial. * Removed the holonomic module for now, as it did not really do anything very useful. 2013-12-21 -- Arb 1.0.0 ------------------------------------------------------------------------------- * New example programs directory * poly_roots example program. * real_roots example program. * pi_digits example program. * hilbert_matrix example program. * keiper_li example program. * New fmprb_calc module for calculus with real functions * Bisection-based root isolation. * Asymptotically fast Newton root refinement. * New fmpcb_calc module for calculus with complex functions * Numerical integration using Taylor series. * Scalar functions * Simplified fmprb_const_euler using published error bound. * Added fmprb_inv. * Added fmprb_trim, fmpcb_trim. * Added fmpcb_rsqrt (complex reciprocal square root). * Fixed bug in fmprb_sqrtpos with nonfinite input. * Slightly improved fmprb powering code. * Added various functions for bounding fmprs by powers of two. * Added fmpr_is_int. * Polynomials and power series * Implemented scaling to speed up blockwise multiplication. * Slightly faster basecase power series exponentials. * Improved sin/cos/tan/exp for short power series. * Added complex sqrt_series, rsqrt_series. * Implemented the Riemann-Siegel Z and theta functions for real power series. * Added fmprb_poly_pow_series, fmprb_poly_pow_ui and related methods. * Added fmprb/fmpcb_poly_contains_fmpz_poly. * Faster composition by monomials. * Implemented Borel transform and binomial transform for real power series. * Matrices * Implemented matrix exponentials. * Multithreaded fmprb_mat_mul. * Added matrix infinity norm functions. * Added some more matrix-scalar functions. * Added matrix contains and overlaps methods. * Zeta function evaluation * Multithreaded power sum evaluation. * Faster parameter selection when computing many derivatives. * Implemented binary splitting to speed up computing many derivatives. * Miscellaneous * Corrections for C++ compatibility (contributed by Jonathan Bober). * Several minor bugfixes and test code enhancements. 2013-08-07 -- Arb 0.7 ------------------------------------------------------------------------------- * Floating-point and ball functions * Documented, added test code, and fixed bugs for various operations involving a ball containing an infinity or NaN. * Added reciprocal square root functions (fmpr_rsqrt, fmprb_rsqrt) based on mpfr_rec_sqrt. * Faster high-precision division by not computing an explicit remainder. * Slightly faster computation of pi by using new reciprocal square root and division code. * Added an fmpr function for approximate division to speed up certain radius operations. * Added fmpr_set_d for conversion from double. * Allow use of doubles to optionally compute the partition function faster but without an error bound. * Bypass mpfr overflow when computing the exponential function to extremely high precision (approximately 1 billion digits). * Made fmprb_exp faster for large numbers at extremely high precision by skipping the log(2) removal. * Made fmpcb_lgamma faster at high precision by speeding up the argument reduction branch computation. * Added fmprb_asin, fmprb_acos. * Added various other utility functions to the fmprb module. * Added a function for computing the Glaisher constant. * Optimized evaluation of the Riemann zeta function at high precision. * Polynomials and power series * Made squaring of polynomials faster than generic multiplication. * Implemented power series reversion (various algorithms) for the fmprb_poly type. * Added many fmprb_poly utility functions (shifting, truncating, setting/getting coefficients, etc.). * Improved power series division when either operand is short * Improved power series logarithm when the input is short. * Improved power series exponential to use the basecase algorithm for short input regardless of the output size. * Added power series square root and reciprocal square root. * Added atan, tan, sin, cos, sin_cos, asin, acos fmprb_poly power series functions. * Added Newton iteration macros to simplify various functions. * Added gamma functions of real and complex power series ([fmprb/fmpcb]_poly_[gamma/rgamma/lgamma]_series). * Added wrappers for computing the Hurwitz zeta function of a power series ([fmprb/fmpcb]_poly_zeta_series). * Implemented sieving and other optimizations to improve performance for evaluating the zeta function of a short power series. * Improved power series composition when the inner series is linear. * Added many fmpcb_poly versions of nearly all fmprb_poly functions. * Improved speed and stability of series composition/reversion by balancing the power table exponents. * Other * Added support for freeing all cached data by calling flint_cleanup(). * Introduced fmprb_ptr, fmprb_srcptr, fmpcb_ptr, fmpcb_srcptr typedefs for cleaner function signatures. * Various bug fixes and general cleanup. 2013-05-31 -- Arb 0.6 ------------------------------------------------------------------------------- * Made fast polynomial multiplication over the reals numerically stable by using a blockwise algorithm. * Disabled default use of the Gauss formula for multiplication of complex polynomials, to improve numerical stability. * Added division and remainder for complex polynomials. * Added fast multipoint evaluation and interpolation for complex polynomials. * Added missing fmprb_poly_sub and fmpcb_poly_sub functions. * Faster exponentials (fmprb_exp and dependent functions) at low precision, using precomputation. * Rewrote fmpr_add and fmpr_sub using mpn level code, improving efficiency at low precision. * Ported the partition function implementation from flint (using ball arithmetic in all steps of the calculation to guarantee correctness). * Ported algorithm for computing the cosine minimal polynomial from flint (using ball arithmetic to guarantee correctness). * Support using GMP instead of MPIR. * Only use thread-local storage when enabled in flint. * Slightly faster error bounding for the zeta function. * Added some other helper functions. 2013-03-28 -- Arb 0.5 ------------------------------------------------------------------------------- * Arithmetic and elementary functions * Added fmpr_get_fmpz, fmpr_get_si. * Fixed accuracy problem with fmprb_div_2expm1. * Special-cased squaring of complex numbers. * Added various fmpcb convenience functions (addmul_ui, etc). * Optimized fmpr_cmp_2exp_si and fmpr_cmpabs_2exp_si, and added test code for comparison functions. * Added fmprb_atan2, also fixing a bug in fmpcb_arg. * Added fmprb_sin_pi, cos_pi, sin_cos_pi, etc. * Added fmprb_sin_pi_fmpq (etc.) using algebraic methods for fast evaluation of roots of unity. * Faster fmprb_poly_evaluate and evaluate_fmpcb using rectangular splitting. * Added fmprb_poly_evaluate2, evaluate2_fmpcb for simultaneously evaluating the derivative. * Added fmprb_poly root polishing code using near-optimal Newton steps (experimental). * Added fmpr_root, fmprb_root (currently based on MPFR). * Added fmpr_min, fmpr_max. * Added fmprb_set_interval_fmpr, fmprb_union. * Added fmpr_bits, fmprb_bits, fmpcb_bits for obtaining the mantissa width. * Added fmprb_hypot. * Added complex square roots. * Improved fmprb_log to slightly improve speed, and properly support huge arguments. * Fixed exp, cosh, sinh to work with huge arguments. * Added fmprb_expm1. * Fixed sin, cos, atan to work with huge arguments. * Improved fmprb_pow and fmpcb_pow, including automatic detection of small integer and half-integer exponents. * Added many more elementary functions: fmprb_tan/cot/tanh/coth, fmpcb_tan/cot, and pi versions. * Added fmprb const_e, const_log2, const_log10, const_catalan. * Fixed ball containment/overlap checking to work operate efficiently and correctly with huge exponents. * Strengthened test code for many core operations. * Special functions * Reorganized zeta function related code. * Faster evaluation of the Riemann zeta function via sieving. * Documented and improved efficiency of the zeta constant binary splitting code. * Calculate error bound in Borwein's algorithm with fmprs instead of using doubles. * Optimized divisions in zeta evaluation via the Euler product. * Use functional equation for Riemann zeta function of a negative argument. * Compute single Bernoulli numbers using ball arithmetic instead of relying on the floating-point code in flint. * Initial code for evaluating the gamma function using its Taylor series. * Much faster rising factorials at high precision, using difference polynomials. * Much faster gamma function at high precision. * Added complex gamma function, log gamma function, and other versions. * Added fmprb_agm (real arithmetic-geometric mean). * Added fmprb_gamma_fmpq, supporting rapid computation of gamma(p/q) for q = 1,2,3,4,6. * Added real and complex digamma function. * Fixed unnecessary recomputation of Bernoulli numbers. * Optimized computation of Euler's constant, and added proper error bounds. * Avoid reliance on doubles in the hypergeometric series tail bound. * Cleaned up factorials and binomials, computing factorials via gamma. * Other * Added an fmpz_extras module to collect various internal fmpz helper functions. * Fixed detection of flint header files. * Fixed various other small bugs. 2013-01-26 -- Arb 0.4 ------------------------------------------------------------------------------- * Much faster fmpr_mul, fmprb_mul and set_round, resulting in general speed improvements. * Code for computing the complex Hurwitz zeta function with derivatives. * Fixed and documented error bounds for hypergeometric series. * Better algorithm for series evaluation of the gamma function at a rational point. * Much faster generation of Bernoulli numbers. * Complex log, exp, pow, trigonometric functions (currently based on MPFR). * Complex nth roots via Newton iteration. * Added code for arithmetic on fmpcb_polys. * Code for computing Khinchin's constant. * Code for rising factorials of polynomials or power series * Faster sin_cos. * Better div_2expm1. * Many other new helper functions. * Improved thread safety. * More test code for core operations. 2012-11-07 -- Arb 0.3 ------------------------------------------------------------------------------- * Converted documentation to Sphinx. * New module fmpcb for ball interval arithmetic over the complex numbers * Conversions, utility functions and arithmetic operations. * New module fmpcb_mat for matrices over the complex numbers * Conversions, utility functions and arithmetic operations. * Multiplication, LU decomposition, solving, inverse and determinant. * New module fmpcb_poly for polynomials over the complex numbers * Root isolation for complex polynomials. * New module fmpz_holonomic for functions/sequences defined by linear differential/difference equations with polynomial coefficients * Functions for creating various special sequences and functions. * Some closure properties for sequences. * Taylor series expansion for differential equations. * Computing the nth entry of a sequence using binary splitting. * Computing the nth entry mod p using fast multipoint evaluation. * Generic binary splitting code with automatic error bounding is now used for evaluating hypergeometric series. * Matrix powering. * Various other helper functions. 2012-09-29 -- Arb 0.2 ------------------------------------------------------------------------------- * Code for computing the gamma function (Karatsuba, Stirling's series). * Rising factorials. * Fast exp_series using Newton iteration. * Improved multiplication of small polynomials by using classical multiplication. * Implemented error propagation for square roots. * Polynomial division (Newton-based). * Polynomial evaluation (Horner) and composition (divide-and-conquer). * Product trees, fast multipoint evaluation and interpolation (various algorithms). * Power series composition (Horner, Brent-Kung). * Added the fmprb_mat module for matrices of balls of real numbers. * Matrix multiplication. * Interval-aware LU decomposition, solving, inverse and determinant. * Many helper functions and small bugfixes. 2012-09-14 -- Arb 0.1 ------------------------------------------------------------------------------- * 2012-08-05 - Began simplified rewrite. * 2012-04-05 - Experimental ball and polynomial code (first commit). flint-3.1.3/doc/source/hurwitz.rst000066400000000000000000000027761461254215100171620ustar00rootroot00000000000000.. _algorithms_hurwitz: Algorithms for the Hurwitz zeta function =============================================================================== Euler-Maclaurin summation ------------------------------------------------------------------------------- The Euler-Maclaurin formula allows evaluating the Hurwitz zeta function and its derivatives for general complex input. The algorithm is described in [Joh2013]_. Parameter Taylor series ------------------------------------------------------------------------------- To evaluate `\zeta(s,a)` for several nearby parameter values, the following Taylor expansion is useful: .. math:: \zeta(s,a+x) = \sum_{k=0}^{\infty} (-x)^k \frac{(s)_k}{k!} \zeta(s+k,a) We assume that `a \ge 1` is real and that `\sigma = \operatorname{re}(s)` with `K + \sigma > 1`. The tail is bounded by .. math:: \sum_{k=K}^{\infty} |x|^k \frac{|(s)_k|}{k!} \zeta(\sigma+k,a) \le \sum_{k=K}^{\infty} |x|^k \frac{|(s)_k|}{k!} \left[ \frac{1}{a^{\sigma+k}} + \frac{1}{(\sigma+k-1) a^{\sigma+k-1}} \right]. Denote the term on the right by `T(k)`. Then .. math:: \left|\frac{T(k+1)}{T(k)}\right| = \frac{|x|}{a} \frac{(k+\sigma-1)}{(k+\sigma)} \frac{(k+\sigma+a)}{(k+\sigma+a-1)} \frac{|k+s|}{(k+1)} \le \frac{|x|}{a} \left(1 + \frac{1}{K+\sigma+a-1}\right) \left(1 + \frac{|s-1|}{K+1}\right) = C and if `C < 1`, .. math:: \sum_{k=K}^{\infty} T(k) \le \frac{T(K)}{1-C}. flint-3.1.3/doc/source/hypergeometric.rst000066400000000000000000000241671461254215100204720ustar00rootroot00000000000000.. _algorithms_hypergeometric: Algorithms for hypergeometric functions =============================================================================== The algorithms used to compute hypergeometric functions are described in [Joh2016]_. Here, we state the most important error bounds. .. _algorithms_hypergeometric_convergent: Convergent series ------------------------------------------------------------------------------- Let .. math:: T(k) = \frac{\prod_{i=0}^{p-1} (a_i)_k}{\prod_{i=0}^{q-1} (b_i)_k} z^k. We compute a factor *C* such that .. math:: \left|\sum_{k=n}^{\infty} T(k)\right| \le C |T(n)|. We check that `\operatorname{Re}(b+n) > 0` for all lower parameters *b*. If this does not hold, *C* is set to infinity. Otherwise, we cancel out pairs of parameters `a` and `b` against each other. We have .. math:: \left|\frac{a+k}{b+k}\right| = \left|1 + \frac{a-b}{b+k}\right| \le 1 + \frac{|a-b|}{|b+n|} and .. math:: \left|\frac{1}{b+k}\right| \le \frac{1}{|b+n|} for all `k \ge n`. This gives us a constant *D* such that `T(k+1) \le D T(k)` for all `k \ge n`. If `D \ge 1`, we set *C* to infinity. Otherwise, we take `C = \sum_{k=0}^{\infty} D^k = (1-D)^{-1}`. Convergent series of power series ------------------------------------------------------------------------------- The same principle is used to get tail bounds for with `a_i, b_i, z \in \mathbb{C}[[x]]`, or more precisely, bounds for each coefficient in `\sum_{k=N}^{\infty} T(k) \in \mathbb{C}[[x]] / \langle x^n \rangle` given `a_i, b_i, z \in \mathbb{C}[[x]] / \langle x^n \rangle`. First, we fix some notation, assuming that `A` and `B` are power series: * `A_{[k]}` denotes the coefficient of `x^k` in `A`, and `A_{[m:n]}` denotes the power series `\sum_{k=m}^{n-1} A_{[k]} x^k`. * `|A|` denotes `\sum_{k=0}^{\infty} |A_{[k]}| x^k` (this can be viewed as an element of `\mathbb{R}_{\ge 0}[[x]]`). * `A \le B` signifies that `|A|_{[k]} \le |B|_{[k]}` holds for all `k`. * We define `\mathcal{R}(B) = |B_{[0]}| - |B_{[1:\infty]}|`. Using the formulas .. math:: (A B)_{[k]} = \sum_{j=0}^k A_{[j]} B_{[k-j]}, \quad (1 / B)_{[k]} = \frac{1}{B_{[0]}} \sum_{j=1}^k -B_{[j]} (1/B)_{[k-j]}, it is easy prove the following bounds for the coefficients of sums, products and quotients of formal power series: .. math:: |A + B| \le |A| + |B|, \quad |A B| \le |A| |B|, \quad |A / B| \le |A| / \mathcal{R}(B). If `p \le q` and `\operatorname{Re}({b_i}_{[0]}+N) > 0` for all `b_i`, then we may take .. math:: D = |z| \, \prod_{i=1}^p \left(1 + \frac{|a_i-b_i|}{\mathcal{R}(b_i+N)}\right) \prod_{i=p+1}^{q} \frac{1}{\mathcal{R}(b_i + N)}. If `D_{[0]} < 1`,then `(1 - D)^{-1} |T(n)|` gives the error bound. Note when adding and multiplying power series with (complex) interval coefficients, we can use point-valued upper bounds for the absolute values instead of performing interval arithmetic throughout. For `\mathcal{R}(B)`, we must then pick a lower bound for `|B_{[0]}|` and upper bounds for the coefficients of `|B_{[1:\infty]}|`. .. _algorithms_hypergeometric_asymptotic_confluent: Asymptotic series for the confluent hypergeometric function ------------------------------------------------------------------------------- Let `U(a,b,z)` denote the confluent hypergeometric function of the second kind with the principal branch cut, and let `U^{*} = z^a U(a,b,z)`. For all `z \ne 0` and `b \notin \mathbb{Z}` (but valid for all `b` as a limit), we have (DLMF 13.2.42) .. math:: U(a,b,z) = \frac{\Gamma(1-b)}{\Gamma(a-b+1)} M(a,b,z) + \frac{\Gamma(b-1)}{\Gamma(a)} z^{1-b} M(a-b+1,2-b,z). Moreover, for all `z \ne 0` we have .. math:: \frac{{}_1F_1(a,b,z)}{\Gamma(b)} = \frac{(-z)^{-a}}{\Gamma(b-a)} U^{*}(a,b,z) + \frac{z^{a-b} e^z}{\Gamma(a)} U^{*}(b-a,b,-z) which is equivalent to DLMF 13.2.41 (but simpler in form). We have the asymptotic expansion .. math:: U^{*}(a,b,z) \sim {}_2F_0(a, a-b+1, -1/z) where `{}_2F_0(a,b,z)` denotes a formal hypergeometric series, i.e. .. math:: U^{*}(a,b,z) = \sum_{k=0}^{n-1} \frac{(a)_k (a-b+1)_k}{k! (-z)^k} + \varepsilon_n(z). The error term `\varepsilon_n(z)` is bounded according to DLMF 13.7. A case distinction is made depending on whether `z` lies in one of three regions which we index by `R`. Our formula for the error bound increases with the value of `R`, so we can always choose the larger out of two indices if `z` lies in the union of two regions. Let `r = |b-2a|`. If `\operatorname{Re}(z) \ge r`, set `R = 1`. Otherwise, if `\operatorname{Im}(z) \ge r` or `\operatorname{Re}(z) \ge 0 \land |z| \ge r`, set `R = 2`. Otherwise, if `|z| \ge 2r`, set `R = 3`. Otherwise, the bound is infinite. If the bound is finite, we have .. math:: |\varepsilon_n(z)| \le 2 \alpha C_n \left|\frac{(a)_n (a-b+1)_n}{n! z^n} \right| \exp(2 \alpha \rho C_1 / |z|) in terms of the following auxiliary quantities .. math:: \sigma = |(b-2a)/z| .. math:: C_n = \begin{cases} 1 & \text{if } R = 1 \\ \chi(n) & \text{if } R = 2 \\ (\chi(n) + \sigma \nu^2 n) \nu^n & \text{if } R = 3 \end{cases} .. math:: \nu = \left(\tfrac{1}{2} + \tfrac{1}{2}\sqrt{1-4\sigma^2}\right)^{-1/2} \le 1 + 2 \sigma^2 .. math:: \chi(n) = \sqrt{\pi} \Gamma(\tfrac{1}{2}n+1) / \Gamma(\tfrac{1}{2} n + \tfrac{1}{2}) .. math:: \sigma' = \begin{cases} \sigma & \text{if } R \ne 3 \\ \nu \sigma & \text{if } R = 3 \end{cases} .. math:: \alpha = (1 - \sigma')^{-1} .. math:: \rho = \tfrac{1}{2} |2a^2-2ab+b| + \sigma' (1+ \tfrac{1}{4} \sigma') (1-\sigma')^{-2} .. _algorithms_hypergeometric_asymptotic_airy: Asymptotic series for Airy functions ------------------------------------------------------------------------------- Error bounds are based on Olver (DLMF section 9.7). For `\arg(z) < \pi` and `\zeta = (2/3) z^{3/2}`, we have .. math:: \operatorname{Ai}(z) = \frac{e^{-\zeta}}{2 \sqrt{\pi} z^{1/4}} \left[S_n(\zeta) + R_n(z)\right], \quad \operatorname{Ai}'(z) = -\frac{z^{1/4} e^{-\zeta}}{2 \sqrt{\pi}} \left[(S'_n(\zeta) + R'_n(z)\right] .. math:: S_n(\zeta) = \sum_{k=0}^{n-1} (-1)^k \frac{u(k)}{\zeta^k}, \quad S'_n(\zeta) = \sum_{k=0}^{n-1} (-1)^k \frac{v(k)}{\zeta^k} .. math:: u(k) = \frac{(1/6)_k (5/6)_k}{2^k k!}, \quad v(k) = \frac{6k+1}{1-6k} u(k). Assuming that *n* is positive, the error terms are bounded by .. math:: |R_n(z)| \le C |u(n)| |\zeta|^{-n}, \quad |R'_n(z)| \le C |v(n)| |\zeta|^{-n} where .. math:: C = \begin{cases} 2 \exp(7 / (36 |\zeta|)) & |\arg(z)| \le \pi/3 \\ 2 \chi(n) \exp(7 \pi / (72 |\zeta|)) & \pi/3 \le |\arg(z)| \le 2\pi/3 \\ 4 \chi(n) \exp(7 \pi / (36 |\operatorname{re}(\zeta)|)) |\cos(\arg(\zeta))|^{-n} & 2\pi/3 \le |\arg(z)| < \pi. \end{cases} For computing Bi when *z* is roughly in the positive half-plane, we use the connection formulas .. math:: \operatorname{Bi}(z) = -i (2 w^{+1} \operatorname{Ai}(z w^{-2}) - \operatorname{Ai}(z)) \operatorname{Bi}(z) = +i (2 w^{-1} \operatorname{Ai}(z w^{+2}) - \operatorname{Ai}(z)) where `w = \exp(\pi i/3)`. Combining roots of unity gives .. math:: \operatorname{Bi}(z) = \frac{1}{2 \sqrt{\pi} z^{1/4}} [2X + iY] .. math:: \operatorname{Bi}(z) = \frac{1}{2 \sqrt{\pi} z^{1/4}} [2X - iY] .. math:: X = \exp(+\zeta) [S_n(-\zeta) + R_n(z w^{\mp 2})], \quad Y = \exp(-\zeta) [S_n(\zeta) + R_n(z)] where the upper formula is valid for `-\pi/3 < \arg(z) < \pi` and the lower formula is valid for `-\pi < \arg(z) < \pi/3`. We proceed analogously for the derivative of Bi. In the negative half-plane, we use the connection formulas .. math:: \operatorname{Ai}(z) = e^{+\pi i/3} \operatorname{Ai}(z_1) + e^{-\pi i/3} \operatorname{Ai}(z_2) .. math:: \operatorname{Bi}(z) = e^{-\pi i/6} \operatorname{Ai}(z_1) + e^{+\pi i/6} \operatorname{Ai}(z_2) where `z_1 = -z e^{+\pi i/3}`, `z_2 = -z e^{-\pi i/3}`. Provided that `|\arg(-z)| < 2 \pi / 3`, we have `|\arg(z_1)|, |\arg(z_2)| < \pi`, and thus the asymptotic expansion for Ai can be used. As before, we collect roots of unity to obtain .. math:: \operatorname{Ai}(z) = A_1 [S_n(i \zeta) + R_n(z_1)] + A_2 [S_n(-i \zeta) + R_n(z_2)] .. math:: \operatorname{Bi}(z) = A_3 [S_n(i \zeta) + R_n(z_1)] + A_4 [S_n(-i \zeta) + R_n(z_2)] where `\zeta = (2/3) (-z)^{3/2}` and .. math:: A_1 = \frac{\exp(-i (\zeta - \pi/4))}{2 \sqrt{\pi} (-z)^{1/4}}, \quad A_2 = \frac{\exp(+i (\zeta - \pi/4))}{2 \sqrt{\pi} (-z)^{1/4}}, \quad A_3 = -i A_1, \quad A_4 = +i A_2. The differentiated formulas are analogous. Corner case of the Gauss hypergeometric function ------------------------------------------------------------------------------- In the corner case where `z` is near `\exp(\pm \pi i / 3)`, none of the linear fractional transformations is effective. In this case, we use Taylor series to analytically continue the solution of the hypergeometric differential equation from the origin. The function `f(z) = {}_2F_1(a,b,c,z_0+z)` satisfies .. math:: f''(z) = -\frac{((z_0+z)(a+b+1)-c)}{(z_0+z)(z_0-1+z)} f'(z) - \frac{a b}{(z_0+z)(z_0-1+z)} f(z). Knowing `f(0), f'(0)`, we can compute the consecutive derivatives recursively, and evaluating the truncated Taylor series allows us to compute `f(z), f'(z)` to high accuracy for sufficiently small `z`. Some experimentation showed that two continuation steps .. math:: 0 \quad \to \quad 0.375 \pm 0.625i \quad \to \quad 0.5 \pm 0.8125i \quad \to \quad z gives good performance. Error bounds for the truncated Taylor series are obtained using the Cauchy-Kovalevskaya majorant method, following the outline in [Hoe2001]_. The differential equation is majorized by .. math:: g''(z) = \frac{N+1}{2} \left( \frac{\nu}{1-\nu z} \right) g'(z) + \frac{(N+1)N}{2} \left( \frac{\nu}{1-\nu z} \right)^2 g(z) provided that `N` and `\nu \ge \max(1/|z_0|, 1/|z_0-1|)` are chosen sufficiently large. It follows that we can compute explicit numbers `A, N, \nu` such that the simple solution `g(z) = A (1-\nu z)^{-N}` of the differential equation provides the bound .. math:: |f_{[k]}| \le g_{[k]} = A {{N+k} \choose k} \nu^k. flint-3.1.3/doc/source/hypgeom.rst000066400000000000000000000146501461254215100171100ustar00rootroot00000000000000.. _hypgeom: **hypgeom.h** -- support for hypergeometric series =============================================================================== This module provides functions for high-precision evaluation of series of the form .. math:: \sum_{k=0}^{n-1} \frac{A(k)}{B(k)} \prod_{j=1}^k \frac{P(k)}{Q(k)} z^k where `A, B, P, Q` are polynomials. The present version only supports `A, B, P, Q \in \mathbb{Z}[k]` (represented using the FLINT *fmpz_poly_t* type). This module also provides functions for high-precision evaluation of infinite series (`n \to \infty`), with automatic, rigorous error bounding. Note that we can standardize to `A = B = 1` by setting `\tilde P(k) = P(k) A(k) B(k-1), \tilde Q(k) = Q(k) A(k-1) B(k)`. However, separating out `A` and `B` is convenient and improves efficiency during evaluation. Strategy for error bounding ------------------------------------------------------------------------------- We wish to evaluate `S(z) = \sum_{k=0}^{\infty} T(k) z^k` where `T(k)` satisfies `T(0) = 1` and .. math:: T(k) = R(k) T(k-1) = \left( \frac{P(k)}{Q(k)} \right) T(k-1) for given polynomials .. math:: P(k) = a_p k^p + a_{p-1} k^{p-1} + \ldots a_0 Q(k) = b_q k^q + b_{q-1} k^{q-1} + \ldots b_0. For convergence, we require `p < q`, or `p = q` with `|z| |a_p| < |b_q|`. We also assume that `P(k)` and `Q(k)` have no roots among the positive integers (if there are positive integer roots, the sum is either finite or undefined). With these conditions satisfied, our goal is to find a parameter `n \ge 0` such that .. math:: \left\lvert \sum_{k=n}^{\infty} T(k) z^k \right\rvert \le 2^{-d}. We can rewrite the hypergeometric term ratio as .. math:: z R(k) = z \frac{P(k)}{Q(k)} = z \left( \frac{a_p}{b_q} \right) \frac{1}{k^{q-p}} F(k) where .. math:: F(k) = \frac{ 1 + \tilde a_{1} / k + \tilde a_{2} / k^2 + \ldots + \tilde a_q / k^p }{ 1 + \tilde b_{1} / k + \tilde b_{2} / k^2 + \ldots + \tilde b_q / k^q } = 1 + O(1/k) and where `\tilde a_i = a_{p-i} / a_p`, `\tilde b_i = b_{q-i} / b_q`. Next, we define .. math:: C = \max_{1 \le i \le p} |\tilde a_i|^{(1/i)}, \quad D = \max_{1 \le i \le q} |\tilde b_i|^{(1/i)}. Now, if `k > C`, the magnitude of the numerator of `F(k)` is bounded from above by .. math:: 1 + \sum_{i=1}^p \left(\frac{C}{k}\right)^i \le 1 + \frac{C}{k-C} and if `k > 2D`, the magnitude of the denominator of `F(k)` is bounded from below by .. math:: 1 - \sum_{i=1}^q \left(\frac{D}{k}\right)^i \ge 1 + \frac{D}{D-k}. Putting the inequalities together gives the following bound, valid for `k > K = \max(C, 2D)`: .. math:: |F(k)| \le \frac{k (k-D)}{(k-C)(k-2D)} = \left(1 + \frac{C}{k-C} \right) \left(1 + \frac{D}{k-2D} \right). Let `r = q-p` and `\tilde z = |z a_p / b_q|`. Assuming `k > \max(C, 2D, {\tilde z}^{1/r})`, we have .. math:: |z R(k)| \le G(k) = \frac{\tilde z F(k)}{k^r} where `G(k)` is monotonically decreasing. Now we just need to find an `n` such that `G(n) < 1` and for which `|T(n)| / (1 - G(n)) \le 2^{-d}`. This can be done by computing a floating-point guess for `n` then trying successively larger values. This strategy leaves room for some improvement. For example, if `\tilde b_1` is positive and large, the bound `B` becomes very pessimistic (a larger positive `\tilde b_1` causes faster convergence, not slower convergence). Types, macros and constants ------------------------------------------------------------------------------- .. type:: hypgeom_struct .. type:: hypgeom_t Stores polynomials *A*, *B*, *P*, *Q* and precomputed bounds, representing a fixed hypergeometric series. Memory management ------------------------------------------------------------------------------- .. function:: void hypgeom_init(hypgeom_t hyp) .. function:: void hypgeom_clear(hypgeom_t hyp) Error bounding ------------------------------------------------------------------------------- .. function:: slong hypgeom_estimate_terms(const mag_t z, int r, slong d) Computes an approximation of the largest `n` such that `|z|^n/(n!)^r = 2^{-d}`, giving a first-order estimate of the number of terms needed to approximate the sum of a hypergeometric series of weight `r \ge 0` and argument `z` to an absolute precision of `d \ge 0` bits. If `r = 0`, the direct solution of the equation is given by `n = (\log(1-z) - d \log 2) / \log z`. If `r > 0`, using `\log n! \approx n \log n - n` gives an equation that can be solved in terms of the Lambert *W*-function as `n = (d \log 2) / (r\,W\!(t))` where `t = (d \log 2) / (e r z^{1/r})`. The evaluation is done using double precision arithmetic. The function aborts if the computed value of `n` is greater than or equal to LONG_MAX / 2. .. function:: slong hypgeom_bound(mag_t error, int r, slong C, slong D, slong K, const mag_t TK, const mag_t z, slong prec) Computes a truncation parameter sufficient to achieve *prec* bits of absolute accuracy, according to the strategy described above. The input consists of `r`, `C`, `D`, `K`, precomputed bound for `T(K)`, and `\tilde z = z (a_p / b_q)`, such that for `k > K`, the hypergeometric term ratio is bounded by .. math:: \frac{\tilde z}{k^r} \frac{k(k-D)}{(k-C)(k-2D)}. Given this information, we compute a `\varepsilon` and an integer `n` such that `\left| \sum_{k=n}^{\infty} T(k) \right| \le \varepsilon \le 2^{-\mathrm{prec}}`. The output variable *error* is set to the value of `\varepsilon`, and `n` is returned. .. function:: void hypgeom_precompute(hypgeom_t hyp) Precomputes the bounds data `C`, `D`, `K` and an upper bound for `T(K)`. Summation ------------------------------------------------------------------------------- .. function:: void arb_hypgeom_sum(arb_t P, arb_t Q, const hypgeom_t hyp, slong n, slong prec) Computes `P, Q` such that `P / Q = \sum_{k=0}^{n-1} T(k)` where `T(k)` is defined by *hyp*, using binary splitting and a working precision of *prec* bits. .. function:: void arb_hypgeom_infsum(arb_t P, arb_t Q, hypgeom_t hyp, slong tol, slong prec) Computes `P, Q` such that `P / Q = \sum_{k=0}^{\infty} T(k)` where `T(k)` is defined by *hyp*, using binary splitting and working precision of *prec* bits. The number of terms is chosen automatically to bound the truncation error by at most `2^{-\mathrm{tol}}`. The bound for the truncation error is included in the output as part of *P*. flint-3.1.3/doc/source/index.rst000066400000000000000000000121141461254215100165400ustar00rootroot00000000000000.. FLINT documentation master file, created by sphinx-quickstart on Fri Nov 16 21:59:21 2018. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. FLINT: Fast Library for Number Theory ====================================== Welcome to FLINT's documentation! FLINT is a C library for doing number theory. * Website: https://flintlib.org * Source code on GitHub: https://github.com/flintlib/flint * Issue tracker: https://github.com/flintlib/flint/issues * Mailing list: https://groups.google.com/group/flint-devel FLINT is free software distributed under the GNU Lesser General Public License (LGPL), version 3 or later. Introduction ------------ .. toctree:: :maxdepth: 1 introduction.rst building.rst bug_reporting.rst contributing.rst contributors.rst examples.rst memory.rst portability.rst threading.rst General utilities ----------------- .. toctree:: :maxdepth: 1 flint.rst profiler.rst thread_pool.rst mpoly.rst machine_vectors.rst Generic rings ----------------------------------------------------------------------- .. toctree:: :maxdepth: 1 gr.rst gr_implementing.rst gr_domains.rst gr_generic.rst gr_special.rst gr_vec.rst gr_mat.rst gr_poly.rst gr_mpoly.rst .. only:: not latex .. toctree:: :maxdepth: 1 index_generic.rst Integers --------------- .. toctree:: :maxdepth: 1 ulong_extras.rst fmpz.rst fmpz_vec.rst fmpz_factor.rst fmpz_mat.rst fmpz_lll.rst fmpz_poly.rst fmpz_poly_mat.rst fmpz_poly_factor.rst fmpz_mpoly.rst fmpz_mpoly_factor.rst long_extras.rst longlong.rst mpn_extras.rst aprcl.rst arith.rst fft.rst fft_small.rst qsieve.rst .. only:: not latex .. toctree:: :maxdepth: 1 index_integers.rst Rational numbers ---------------- .. toctree:: :maxdepth: 1 fmpq.rst fmpq_vec.rst fmpq_mat.rst fmpq_poly.rst fmpq_mpoly_factor.rst fmpq_mpoly.rst fmpz_poly_q.rst fmpz_mpoly_q.rst .. only:: not latex .. toctree:: :maxdepth: 1 index_rationals.rst Integers mod n --------------- .. toctree:: :maxdepth: 1 nmod.rst nmod_vec.rst nmod_mat.rst nmod_poly.rst nmod_poly_mat.rst nmod_poly_factor.rst nmod_mpoly.rst nmod_mpoly_factor.rst fmpz_mod.rst fmpz_mod_vec.rst fmpz_mod_mat.rst fmpz_mod_poly.rst fmpz_mod_poly_factor.rst fmpz_mod_mpoly.rst fmpz_mod_mpoly_factor.rst .. only:: not latex .. toctree:: :maxdepth: 1 index_integers_mod.rst Groups and other structures --------------------------- .. toctree:: :maxdepth: 1 perm.rst qfb.rst dirichlet.rst dlog.rst bool_mat.rst Number fields and algebraic numbers ----------------------------------- .. toctree:: :maxdepth: 1 nf.rst nf_elem.rst fmpzi.rst qqbar.rst Real and complex numbers ---------------------------------------- .. toctree:: :maxdepth: 1 overview.rst using.rst issues.rst examples_arb.rst mag.rst arf.rst acf.rst arb.rst acb.rst arb_poly.rst acb_poly.rst arb_fmpz_poly.rst acb_dft.rst arb_mat.rst acb_mat.rst acb_hypgeom.rst arb_hypgeom.rst acb_elliptic.rst acb_modular.rst acb_theta.rst acb_dirichlet.rst bernoulli.rst hypgeom.rst partitions.rst arb_calc.rst acb_calc.rst arb_fpwrap.rst fmpz_extras.rst formulas.rst constants.rst gamma.rst hurwitz.rst polylogarithms.rst hypergeometric.rst agm.rst .. only:: not latex .. toctree:: :maxdepth: 1 index_arb.rst Exact real and complex numbers ---------------------------------------- .. toctree:: :maxdepth: 1 introduction_calcium.rst examples_calcium.rst calcium.rst ca.rst ca_vec.rst ca_poly.rst ca_mat.rst ca_ext.rst ca_field.rst fexpr.rst fexpr_builtin.rst Finite fields --------------- .. toctree:: :maxdepth: 1 fq.rst fq_default.rst fq_vec.rst fq_mat.rst fq_default_mat.rst fq_poly.rst fq_default_poly.rst fq_poly_factor.rst fq_default_poly_factor.rst fq_embed.rst .. toctree:: :maxdepth: 1 fq_nmod.rst fq_nmod_vec.rst fq_nmod_mat.rst fq_nmod_poly.rst fq_nmod_poly_factor.rst fq_nmod_embed.rst fq_nmod_mpoly.rst fq_nmod_mpoly_factor.rst .. toctree:: :maxdepth: 1 fq_zech.rst fq_zech_vec.rst fq_zech_mat.rst fq_zech_poly.rst fq_zech_poly_factor.rst fq_zech_embed.rst p-adic numbers --------------- .. toctree:: :maxdepth: 1 padic.rst padic_poly.rst padic_mat.rst qadic.rst Floating-point support code ----------------------------------- .. toctree:: :maxdepth: 1 double_extras.rst double_interval.rst d_vec.rst d_mat.rst mpfr_vec.rst mpfr_mat.rst Interfaces ----------------------------------- .. toctree:: :maxdepth: 1 python_flint.rst References ----------------------------------- .. toctree:: :maxdepth: 1 references.rst Version history ----------------------------------- .. toctree:: :maxdepth: 1 history.rst flint-3.1.3/doc/source/index_arb.rst000066400000000000000000000071271461254215100173740ustar00rootroot00000000000000.. _index-arb: **Real and complex numbers (Arb)** : *detailed table of contents* ================================================================= .. only:: html General information :::::::::::::::::::: .. toctree:: :maxdepth: 2 overview.rst using.rst issues.rst Example programs :::::::::::::::::::: .. toctree:: :maxdepth: 2 examples_arb.rst Floating-point numbers :::::::::::::::::::::::::::::::::::: Arb uses two custom floating-point types in its implementation of ball arithmetic. The radius of a ball is represented using the type *mag_t* which is unsigned and has a fixed precision. The midpoint is represented using the type *arf_t* which has arbitrary precision. .. toctree:: :maxdepth: 2 mag.rst arf.rst Real and complex numbers :::::::::::::::::::::::::::::::::::: Real numbers (*arb_t*) are represented as midpoint-radius intervals, also known as balls. Complex numbers (*acb_t*) are represented in rectangular form, with *arb_t* balls for the real and imaginary parts. .. toctree:: :maxdepth: 2 arb.rst acb.rst Polynomials and power series :::::::::::::::::::::::::::::::::::: These modules implement dense univariate polynomials with real and complex coefficients. Truncated power series are supported via methods acting on polynomials, without introducing a separate power series type. .. toctree:: :maxdepth: 2 arb_poly.rst acb_poly.rst .. toctree:: :maxdepth: 2 arb_fmpz_poly.rst Transforms :::::::::::::::::::::::::::::::::::: .. toctree:: :maxdepth: 2 acb_dft.rst Matrices :::::::::::::::::::::::::::::::::::: These modules implement dense matrices with real and complex coefficients. Rudimentary linear algebra is supported. .. toctree:: :maxdepth: 2 arb_mat.rst acb_mat.rst Special functions :::::::::::::::::::::::::::::::::::: These modules implement mathematical functions with complexity that goes beyond the basics covered directly in the *arb* and *acb* modules. .. toctree:: :maxdepth: 2 acb_hypgeom.rst arb_hypgeom.rst acb_elliptic.rst acb_modular.rst acb_theta.rst dirichlet.rst acb_dirichlet.rst bernoulli.rst hypgeom.rst partitions.rst Calculus :::::::::::::::::::::::::::::::::::: Using ball arithmetic, it is possible to do rigorous root-finding and integration (among other operations) with generic functions. This code should be considered experimental. .. toctree:: :maxdepth: 2 arb_calc.rst acb_calc.rst Wrappers :::::::::::::::::::::::::::::::::::: Floating-point wrappers for Arb functions. .. toctree:: :maxdepth: 2 arb_fpwrap.rst Extra utility modules :::::::::::::::::::::::::::::::::::: Mainly for internal use. .. toctree:: :maxdepth: 1 fmpzi.rst acf.rst double_interval.rst fmpz_extras.rst bool_mat.rst dlog.rst Supplementary algorithm notes :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Here, we give extra proofs, error bounds, and formulas that would be too lengthy to reproduce in the documentation for each module. .. toctree:: :maxdepth: 1 formulas.rst constants.rst gamma.rst hurwitz.rst polylogarithms.rst hypergeometric.rst agm.rst flint-3.1.3/doc/source/index_generic.rst000066400000000000000000000005371461254215100202420ustar00rootroot00000000000000.. _index-generic: **Generic rings** : *detailed table of contents* ================================================================= .. only:: html .. toctree:: :maxdepth: 3 gr.rst gr_implementing.rst gr_domains.rst gr_special.rst gr_vec.rst gr_mat.rst gr_poly.rst gr_mpoly.rst flint-3.1.3/doc/source/index_integers.rst000066400000000000000000000010411461254215100204350ustar00rootroot00000000000000.. _index-integers: **Integers** : *detailed table of contents* ============================================ .. only:: html .. toctree:: :maxdepth: 3 ulong_extras.rst fmpz.rst fmpz_vec.rst fmpz_factor.rst fmpz_mat.rst fmpz_lll.rst fmpz_poly.rst fmpz_poly_mat.rst fmpz_poly_factor.rst fmpz_mpoly.rst fmpz_mpoly_factor.rst long_extras.rst longlong.rst mpn_extras.rst aprcl.rst arith.rst fft.rst qsieve.rst flint-3.1.3/doc/source/index_integers_mod.rst000066400000000000000000000010421461254215100212750ustar00rootroot00000000000000.. _index-integers-mod: **Integers mod n** : *detailed table of contents* ================================================== .. only:: html .. toctree:: :maxdepth: 3 nmod.rst nmod_vec.rst nmod_mat.rst nmod_poly.rst nmod_poly_mat.rst nmod_poly_factor.rst nmod_mpoly.rst nmod_mpoly_factor.rst fmpz_mod.rst fmpz_mod_vec.rst fmpz_mod_mat.rst fmpz_mod_poly.rst fmpz_mod_poly_factor.rst fmpz_mod_mpoly.rst fmpz_mod_mpoly_factor.rst flint-3.1.3/doc/source/index_rationals.rst000066400000000000000000000005151461254215100206160ustar00rootroot00000000000000.. _index-rationals: **Rational numbers** : *detailed table of contents* ==================================================== .. only:: html .. toctree:: :maxdepth: 3 fmpq.rst fmpq_vec.rst fmpq_mat.rst fmpq_poly.rst fmpq_mpoly_factor.rst fmpq_mpoly.rst fmpz_poly_q.rst flint-3.1.3/doc/source/introduction.rst000066400000000000000000000062041461254215100201550ustar00rootroot00000000000000.. _introduction: **Introduction** =============================================================================== What is Flint? ------------------------------------------------------------------------------- FLINT is a C library of functions for doing basic arithmetic in support of computational number theory and other areas of computer algebra. It is highly optimised and can be compiled on numerous platforms. FLINT provides highly optimised implementations of basic rings, such as the integers, rationals, `p`-adics, finite fields, etc., and linear algebra and univariate and multivariate polynomials over most of these rings. FLINT also has some multithreading capabilities. To this end, the library is threadsafe, with few exceptions noted in the appropriate place, and a number of key functions have multithreaded implementations. Maintainers and Authors ------------------------------------------------------------------------------- FLINT is currently maintained by Fredrik Johansson of INRIA Bordeaux. FLINT was originally designed by William Hart and David Harvey. Since then FLINT was rewritten as FLINT 2 by William Hart, Fredrik Johansson and Sebastian Pancratz. Many other substantial contributions have been made by other authors, e.g. Tom Bachmann, Mike Hansen, Daniel Schultz and Andy Novocin. There have been a great number of other contributors, listed on the main Flint website and the contributors section of this documentation. Requirements ------------------------------------------------------------------------------- FLINT and following should compile on any machine with GCC and a standard GNU toolchain, though GCC 4.8 and following are recommended. FLINT is specially optimised for x86 (32 and 64 bit) machines. There is also limited optimisation for ARM machines. As of version 3.0, FLINT requires GMP 6.2.1 or later, and MPFR 4.1.0 or later. Note that earlier, MPIR, a fork of GMP, was supported. However, as of FLINT 3.0, this support has been dropped. It is also required that the platform provide a ``uint64_t`` type if a native 64 bit type is not available. Full C99 compliance is not required. Structure of Flint ----------------------------------------------------------------------------- FLINT is supplied as a set of modules, ``fmpz``, ``fmpz_poly``, etc., each of which can be linked to a C program making use of their functionality. All of the functions in FLINT have a corresponding test function provided in an appropriately named test file. For example, the function ``fmpz_poly_add`` located in ``src/fmpz_poly/add.c`` has test code in the file ``src/fmpz_poly/test/t-add.c``. Some modules have a ``profile`` directory in which profile programs can be found. Documentation exists in the ``doc/source`` directory in a series of ``.rst`` files. License ----------------------------------------------------------------------------- FLINT is distributed under the GNU Lesser General Public License (LGPL) version 3 or later. There is a copy of the license included in the repository and distribution tarballs. Note, however, that between FLINT version 2.6 and 3.1, it was distributed with LGPL version 2, and before that GPL version 2. flint-3.1.3/doc/source/introduction_calcium.rst000066400000000000000000000152421461254215100216540ustar00rootroot00000000000000.. _introduction-calcium: Introduction =============================================================================== Exact numbers in Calcium ----------------------------------------------------------------------- The core idea behind Calcium is to represent real and complex numbers as elements of extension fields .. math:: \mathbb{Q}(a_1, \ldots, a_n) of the rational numbers, where the extension numbers `a_k` are described by symbolic expressions (which may depend on other fields recursively). The system constructs such fields automatically as needed to represent the results of computations. Any extension field is isomorphic to a formal field .. math:: \mathbb{Q}(a_1,\ldots,a_n) \;\; \cong \;\; K_{\text{formal}} := \operatorname{Frac}(\mathbb{Q}[X_1,\ldots,X_n] / I) where *I* is the ideal of algebraic relations among the extension numbers. The relations may involve algebraic numbers (for example: `i^2 + 1 = 0`), transcendental numbers (for example: `e^{-\pi} \cdot e^{\pi} = 1`), or combinations thereof. Computation in the formal field depends (in general) on multivariate polynomial arithmetic together with use of a Gröbner basis for the ideal. The map from the formal field to the true complex field is maintained using arbitrary-precision ball arithmetic where necessary. As an important special case, Calcium can be used for arithmetic in algebraic number fields (embedded explicitly in `\mathbb{C}`) .. math:: \mathbb{Q}(a) \cong \mathbb{Q}[X] / \langle f(X) \rangle with excellent performance thanks to internal use of the Antic library. It will not always work perfectly: although Calcium by design should never give a mathematically erroneous answer, it may be unable to simplify a result as much as expected and it may be unable to decide a predicate (in which case it can return "Unknown"). Equality is at least decidable over the algebraic numbers `\overline{\mathbb{Q}}` (for practical degrees and bit sizes of the numbers!), and in certain cases involving transcendentals. We hope to improve Calcium's capabilities gradually through enhancements to its built-in algorithms and through customization options. Usage details ....................................................................... To understand how Calcium works more concretely, see :ref:`examples-calcium` and the documentation for the main Calcium number type (:type:`ca_t`): * :ref:`ca` Implementation details for extension numbers and formal fields can be found in the documentation of the corresponding modules: * :ref:`ca-ext` * :ref:`ca-field` The following modules are used internally for arithmetic in transcendental number fields (rational function fields) `\mathbb{Q}(x_1,\ldots,x_n)` and over the field of algebraic numbers `\overline{\mathbb{Q}}`, respectively. They may be of independent interest: * :ref:`fmpz-mpoly-q` * :ref:`qqbar` FAQ ----------------------------------------------------------------------- **Isn't x = 0 undecidable?** In general, yes: equality over the reals is undecidable. In practice, much of calculus and elementary number theory can be done with numbers that are simple algebraic combinations of well-known elementary and special functions, and there are heuristics that work quite well for deciding predicates about such numbers. Calcium will be able to give a definitive answer at least in simple cases (for example, proving `16 \operatorname{atan}(\tfrac{1}{5}) - 4 \operatorname{atan}(\tfrac{1}{239}) = \pi` or `\sqrt{5+2\sqrt{6}} = \sqrt{2}+\sqrt{3}`), and will simply answer "Unknown" when its heuristics are not powerful enough. **How does Calcium compare to ordinary numerical computing?** Calcium is far too slow to replace floating-point numbers for 99.93% of scientific computing. The target is symbolic and algebraic computation. Nevertheless, Calcium may well be useful as a tool to test and enhance the capabilities of numerical programs. **How does Calcium compare to Arb arithmetic?** The main advantage of Calcium over ball arithmetic alone is the ability to do exact comparisons. The automatic precision management in Calcium can also be convenient. Calcium will usually be slower than Arb arithmetic. If a computation is mostly numerical, it is probably better to try using Arb first, and fall back on an exact calculation with Calcium only if that fails because an exact comparison is needed. **How does Calcium compare to symbolic computation systems (Mathematica, SymPy, etc.)?** Calculating with constant values is only a small part of what such systems have to do, but it is one of the most complex parts. Existing computer algebra systems sometimes manage this very well, and sometimes fail horribly. The most common problems are 1) getting numerical error bounds or branch cuts wrong, and 2) slowing down too much when the expressions get large. Calcium is intended to address both problems (through rigorous numerical evaluation and use of fast polynomial arithmetic). Ultimately, Calcium will no doubt handle some problems better and others worse, and it should be considered a complement to existing computer algebra systems rather than a replacement. A symbolic expression simplifier may use Calcium evaluation as one of its tools, but this probably needs to be done selectively and in combination with many other heuristics. **Why is Calcium written in C?** The main advantage of developing Calcium as a C library is that it will not be tied to a particular programming language ecosystem: C is uniquely easy to interface from almost any other language. The second most important reason is familiarity: Calcium follows the design of Flint and Arb (coding style, naming, module layout, memory management, test code, etc.) which has proved to work quite well for libraries of this type. There is also the performance argument. Some core functions will benefit from optimizations that are natural in C such as in-place operations and fine-grained manual memory management. However, the performance aspect should not be overemphasized: Calcium will spend most of its time in Flint and Arb kernel functions and this would probably still be true even if it were written in a slower language. There are certainly types of mathematical functionality that will be too inconvenient to implement in C. Our intention is indeed to leave such functionality to projects written in Python, Julia, etc. which may then opt to depend on Calcium for basic operations. **What is the development status of Calcium?** Calcium is presently in early development and should be considered experimental software. The interfaces are subject to change and many important functions and optimizations have not been implemented. A more stable and functional release can be expected in late 2021. .. raw:: latex \newpage flint-3.1.3/doc/source/issues.rst000066400000000000000000000242031461254215100167460ustar00rootroot00000000000000.. _issues: Technical conventions and potential issues =============================================================================== Integer overflow ------------------------------------------------------------------------------- When machine-size integers are used for precisions, sizes of integers in bits, lengths of polynomials, and similar quantities that relate to sizes in memory, very few internal checks are performed to verify that such quantities do not overflow. Precisions and lengths exceeding a small fraction of *LONG_MAX*, say `2^{24} \approx 10^7` on 32-bit systems, should be regarded as resulting in undefined behavior. On 64-bit systems this should generally not be an issue, since most calculations will exhaust the available memory (or the user's patience waiting for the computation to complete) long before running into integer overflows. However, the user needs to be wary of unintentionally passing input parameters of order *LONG_MAX* or negative parameters where positive parameters are expected, for example due to a runaway loop that repeatedly increases the precision. Currently, no hard upper limit on the precision is defined, but `2^{24} \approx 10^7` bits on 32-bit system and `2^{36} \approx 10^{11}` bits on a 64-bit system can be considered safe for most purposes. The relatively low limit on 64-bit systems is due to the fact that GMP integers are used internally in some algorithms, and GMP integers are limited to `2^{37}` bits. The minimum allowed precision is 2 bits. This caveat does not apply to exponents of floating-point numbers, which are represented as arbitrary-precision integers, nor to integers used as numerical scalars (e.g. :func:`arb_mul_si`). However, it still applies to conversions and operations where the result is requested exactly and sizes become an issue. For example, trying to convert the floating-point number `2^{2^{100}}` to an integer could result in anything from a silent wrong value to thrashing followed by a crash, and it is the user's responsibility not to attempt such a thing. Aliasing ------------------------------------------------------------------------------- As a rule, Arb allows aliasing of operands. For example, in the function call ``arb_add(z, x, y, prec)``, which performs `z \gets x + y`, any two (or all three) of the variables *x*, *y* and *z* are allowed to be the same. Exceptions to this rule are documented explicitly. The general rule that input and output variables can be aliased with each other only applies to variables *of the same type* (ignoring *const* qualifiers on input variables -- a special case is that :type:`arb_srcptr` is considered the *const* version of :type:`arb_ptr`). This is a natural extension of the so-called *strict aliasing rule* in C. For example, in :func:`arb_poly_evaluate` which evaluates `y = f(x)` for a polynomial *f*, the output variable *y* is not allowed to be a pointer to one of the coefficients of *f* (but aliasing between *x* and *y* or between *x* and the coefficients of *f* is allowed). This also applies to :func:`_arb_poly_evaluate`: for the purposes of aliasing, :type:`arb_srcptr` (the type of the coefficient array within *f*) and :type:`arb_t` (the type of *x*) are *not* considered to be the same type, and therefore must not be aliased with each other, even though an :type:`arb_ptr`/:type:`arb_srcptr` variable pointing to a length 1 array would otherwise be interchangeable with an :type:`arb_t`/*const* :type:`arb_t`. Moreover, in functions that allow aliasing between an input array and an output array, the arrays must either be identical or completely disjoint, never partially overlapping. There are natural exceptions to these aliasing restrictions, which may used internally without being documented explicitly. However, third party code should avoid relying on such exceptions. An important caveat applies to **aliasing of input variables**. Identical pointers are understood to give permission for **algebraic simplification**. This assumption is made to improve performance. For example, the call ``arb_mul(z, x, x, prec)`` sets *z* to a ball enclosing the set .. math:: \{ t^2 \,:\, t \in x \} and not the (generally larger) set .. math:: \{ t u \,:\, t \in x, u \in x \}. If the user knows that two values *x* and *y* both lie in the interval `[-1,1]` and wants to compute an enclosure for `f(x,y)`, then it would be a mistake to create an :type:`arb_t` variable *x* enclosing `[-1,1]` and reusing the same variable for *y*, calling `f(x,x)`. Instead, the user has to create a distinct variable *y* also enclosing `[-1,1]`. Algebraic simplification is not guaranteed to occur. For example, ``arb_add(z, x, x, prec)`` and ``arb_sub(z, x, x, prec)`` currently do not implement this optimization. It is better to use ``arb_mul_2exp_si(z, x, 1)`` and ``arb_zero(z)``, respectively. Thread safety and caches ------------------------------------------------------------------------------- Arb should be fully threadsafe, provided that both MPFR and FLINT have been built in threadsafe mode. Use ``flint_set_num_threads()`` to set the number of threads that Arb is allowed to use internally for single computations (this is currently only exploited by a handful of operations). Please note that thread safety is only tested minimally, and extra caution when developing multithreaded code is therefore recommended. Arb may cache some data (such as the value of `\pi` and Bernoulli numbers) to speed up various computations. In threadsafe mode, caches use thread-local storage. There is currently no way to save memory and avoid recomputation by having several threads share the same cache. Caches can be freed by calling the ``flint_cleanup()`` function. To avoid memory leaks, the user should call ``flint_cleanup()`` when exiting a thread. It is also recommended to call ``flint_cleanup()`` when exiting the main program (this should result in a clean output when running `Valgrind `_, and can help catching memory issues). There does not seem to be an obvious way to make sure that ``flint_cleanup()`` is called when exiting a thread using OpenMP. A possible solution to this problem is to use OpenMP sections, or to use C++ and create a thread-local object whose destructor invokes ``flint_cleanup()``. Use of hardware floating-point arithmetic ------------------------------------------------------------------------------- Arb uses hardware floating-point arithmetic (the ``double`` type in C) in two different ways. First, ``double`` arithmetic as well as transcendental ``libm`` functions (such as ``exp``, ``log``) are used to select parameters heuristically in various algorithms. Such heuristic use of approximate arithmetic does not affect correctness: when any error bounds depend on the parameters, the error bounds are evaluated separately using rigorous methods. At worst, flaws in the floating-point arithmetic on a particular machine could cause an algorithm to become inefficient due to inefficient parameters being selected. Second, ``double`` arithmetic is used internally for some rigorous error bound calculations. To guarantee correctness, we make the following assumptions. With the stated exceptions, these should hold on all commonly used platforms. * A ``double`` uses the standard IEEE 754 format (with a 53-bit significand, 11-bit exponent, encoding of infinities and NaNs, etc.) * We assume that the compiler does not perform "unsafe" floating-point optimizations, such as reordering of operations. Unsafe optimizations are disabled by default in most modern C compilers, including GCC and Clang. The exception appears to be the Intel C++ compiler, which does some unsafe optimizations by default. These must be disabled by the user. * We do not assume that floating-point operations are correctly rounded (a counterexample is the x87 FPU), or that rounding is done in any particular direction (the rounding mode may have been changed by the user). We assume that any floating-point operation is done with at most 1.1 ulp error. * We do not assume that underflow or overflow behaves in a particular way (we only use doubles that fit in the regular exponent range, or explicit infinities). * We do not use transcendental ``libm`` functions, since these can have errors of several ulps, and there is unfortunately no way to get guaranteed bounds. However, we do use functions such as ``ldexp`` and ``sqrt``, which we assume to be correctly implemented. Interface changes ------------------------------------------------------------------------------- Most of the core API should be stable at this point, and significant compatibility-breaking changes will be specified in the release notes. In general, Arb does not distinguish between "private" and "public" parts of the API. The implementation is meant to be transparent by design. All methods are intended to be fully documented and tested (exceptions to this are mainly due to lack of time on part of the author). The user should use common sense to determine whether a function is concerned with implementation details, making it likely to change as the implementation changes in the future. The interface of :func:`arb_add` is probably not going to change in the next version, but :func:`_arb_get_mpn_fixed_mod_pi4` just might. General note on correctness ------------------------------------------------------------------------------- Except where otherwise specified, Arb is designed to produce provably correct error bounds. The code has been written carefully, and the library is extensively tested. However, like any complex mathematical software, Arb is virtually certain to contain bugs, so the usual precautions are advised: * Do sanity checks. For example, check that the result satisfies an expected mathematical relation, or compute the same result in two different ways, with different settings, and with different levels of precision. Arb's unit tests already do such checks, but they are not guaranteed to catch every possible bug, and they provide no protection against the user accidentally using the interface incorrectly. * Compare results with other mathematical software. * Read the source code to verify that it really does what it is supposed to do. All bug reports are highly appreciated. flint-3.1.3/doc/source/long_extras.rst000066400000000000000000000033761461254215100177700ustar00rootroot00000000000000.. _long-extras: **long_extras.h** -- support functions for signed word arithmetic =============================================================================== Properties -------------------------------------------------------------------------------- .. function:: size_t z_sizeinbase(slong n, int b) Returns the number of digits in the base `b` representation of the absolute value of the integer `n`. Assumes that `b \geq 2`. Checked Arithmetic -------------------------------------------------------------------------------- .. function:: int z_mul_checked(slong * a, slong b, slong c) Set `*a` to `b` times `c` and return `1` if the product overflowed. Otherwise, return `0`. Random functions -------------------------------------------------------------------------------- .. function:: mp_limb_signed_t z_randtest(flint_rand_t state) Returns a pseudo random number with a random number of bits, from `0` to ``FLINT_BITS``. The probability of the special values `0`, `\pm 1`, ``COEFF_MAX``, ``COEFF_MIN``, ``WORD_MAX`` and ``WORD_MIN`` is increased. This random function is mainly used for testing purposes. .. function:: mp_limb_signed_t z_randtest_not_zero(flint_rand_t state) As for ``z_randtest(state)``, but does not return `0`. .. function:: mp_limb_signed_t z_randint(flint_rand_t state, mp_limb_t limit) Returns a pseudo random number of absolute value less than ``limit``. If ``limit`` is zero or exceeds ``WORD_MAX``, it is interpreted as ``WORD_MAX``. Modular arithmetic -------------------------------------------------------------------------------- .. function:: int z_kronecker(slong a, slong n) Return the Kronecker symbol `\left(\frac{a}{n}\right)` for any `a` and any `n`. flint-3.1.3/doc/source/longlong.rst000066400000000000000000000071541461254215100172600ustar00rootroot00000000000000.. _longlong: **longlong.h** -- support functions for multi-word arithmetic =============================================================================== Auxiliary asm macros -------------------------------------------------------------------------------- .. macro:: umul_ppmm(high_prod, low_prod, multiplier, multiplicand) Multiplies two single limb integers ``MULTIPLIER`` and ``MULTIPLICAND``, and generates a two limb product in ``HIGH_PROD`` and ``LOW_PROD``. .. macro:: smul_ppmm(high_prod, low_prod, multiplier, multiplicand) As for ``umul_ppmm()`` but the numbers are signed. .. macro:: udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator) Divides an unsigned integer, composed by the limb integers ``HIGH_NUMERATOR`` and ``LOW_NUMERATOR``, by ``DENOMINATOR`` and places the quotient in ``QUOTIENT`` and the remainder in ``REMAINDER``. ``HIGH_NUMERATOR`` must be less than ``DENOMINATOR`` for correct operation. .. macro:: sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator) As for ``udiv_qrnnd()`` but the numbers are signed. The quotient is rounded towards `0`. Note that as the quotient is signed it must lie in the range `[-2^63, 2^63)`. .. macro:: flint_clz(x) Returns the number of zero-bits from the msb to the first non-zero bit in the limb ``x``. This is the number of steps ``x`` needs to be shifted left to set the msb. If ``x`` is `0` then the return value is undefined. .. macro:: flint_ctz(x) As for ``flint_clz()``, but counts from the least significant end. If ``x`` is zero then the return value is undefined. .. macro:: add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, high_addend_2, low_addend_2) Adds two limb integers, composed by ``HIGH_ADDEND_1`` and ``LOW_ADDEND_1``, and ``HIGH_ADDEND_2`` and ``LOW_ADDEND_2``, respectively. The result is placed in ``HIGH_SUM`` and ``LOW_SUM``. Overflow, i.e. carry out, is not stored anywhere, and is lost. .. macro:: add_sssaaaaaa(high_sum, mid_sum, low_sum, high_addend_1, mid_addend_1, low_addend_1, high_addend_2, mid_addend_2, low_addend_2) Adds two three limb integers. Carry out is lost. .. macro:: sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, high_subtrahend, low_subtrahend) Subtracts two limb integers, composed by ``HIGH_MINUEND_1`` and ``LOW_MINUEND_1``, and ``HIGH_SUBTRAHEND_2`` and ``LOW_SUBTRAHEND_2``, respectively. The result is placed in ``HIGH_DIFFERENCE`` and ``LOW_DIFFERENCE``. Overflow, i.e. carry out is not stored anywhere, and is lost. .. macro:: sub_dddmmmsss(high_diff, mid_diff, low_diff, high_minuend_1, mid_minuend_1, low_minuend_1, high_subtrahend_2, mid_subtrahend_2, low_subtrahend_2) Subtracts two three limb integers. Borrow out is lost. .. macro:: byte_swap(x) Swap the order of the bytes in the word `x`, i.e. most significant byte becomes least significant byte, etc. .. macro:: invert_limb(invxl, xl) Deprecated: see :func:`n_preinvert_limb_prenorm`. .. macro:: udiv_qrnnd_preinv(q, r, nh, nl, d, di) As for ``udiv_qrnnd()`` but takes a precomputed inverse ``di`` as computed by ``invert_limb()``. The algorithm, in terms of the theorem above, is:: nadj = n1*(d-B/2) + n0 xh, xl = (n2+n1)*(m-B) xh, xl += nadj + n2*B ( xh, xl = n2*B + (n2+n1)*(m-B) + n1*(d-B/2) + n0 ) _q1 = B - xh - 1 xh, xl = _q1*d + nh, nl - B*d = nh, nl - q1*d - d so that xh = 0 or -1 r = xl + xh*d where xh is 0 if q1 is off by 1, otherwise -1 q = xh - _q1 = xh + 1 + n2 flint-3.1.3/doc/source/machine_vectors.rst000066400000000000000000000240551461254215100206110ustar00rootroot00000000000000.. _machine-vectors: **machine_vectors.h** -- SIMD-accelerated operations on fixed-length vectors =============================================================================== This module currently requires building FLINT with support for AVX2 or NEON instructions. Some functions may require that vectors are aligned in memory. Types ------------------------------------------------------------------------------- .. type:: vec1n vec2n vec4n vec8n Vector with 1, 2, 4, or 8 :type:`ulong` entries. .. type:: vec1d vec2d vec4d vec8d Vector with 1, 2, 4, or 8 ``double`` entries. Printing ------------------------------------------------------------------------------- .. function:: void vec4d_print(vec4d a) void vec4n_print(vec4n a) Access and conversions ------------------------------------------------------------------------------- .. function:: vec1d vec1d_load(const double * a) vec4d vec4d_load(const double * a) vec8d vec8d_load(const double * a) .. function:: vec1d vec1d_load_aligned(const double * a) vec4d vec4d_load_aligned(const double * a) vec8d vec8d_load_aligned(const double * a) .. function:: vec1d vec1d_load_unaligned(const double * a) vec4d vec4d_load_unaligned(const double * a) vec8d vec8d_load_unaligned(const double * a) vec4n vec4n_load_unaligned(const ulong * a) vec8n vec8n_load_unaligned(const ulong * a) .. function:: void vec1d_store(double * z, vec1d a) void vec4d_store(double * z, vec4d a) void vec8d_store(double * z, vec8d a) .. function:: void vec1d_store_aligned(double * z, vec1d a) void vec4d_store_aligned(double * z, vec4d a) void vec8d_store_aligned(double * z, vec8d a) .. function:: void vec1d_store_unaligned(double * z, vec1d a) void vec4d_store_unaligned(double * z, vec4d a) void vec4n_store_unaligned(ulong * z, vec4n a) void vec8d_store_unaligned(double * z, vec8d a) .. function:: double vec4d_get_index(vec4d a, const int i) double vec8d_get_index(vec8d a, int i) Extract the entry at index `i`. .. function:: vec1d vec1d_set_d(double a) vec4d vec4d_set_d(double a) vec4n vec4n_set_n(ulong a) vec8d vec8d_set_d(double a) vec8n vec8n_set_n(ulong a) Set all entries to the same value. .. function:: vec4d vec4d_set_d4(double a0, double a1, double a2, double a3) vec4n vec4n_set_n4(ulong a0, ulong a1, ulong a2, ulong a3) vec8d vec8d_set_d8(double a0, double a1, double a2, double a3, double a4, double a5, double a6, double a7) Create vector from distinct entries. .. function:: vec4n vec4d_convert_limited_vec4n(vec4d a) vec8d vec8n_convert_limited_vec8d(vec8n a) Permutations ------------------------------------------------------------------------------- .. function:: vec4d vec4d_unpacklo(vec4d a, vec4d b) vec4d vec4d_unpackhi(vec4d a, vec4d b) vec4d vec4d_permute_0_2_1_3(vec4d a) vec4d vec4d_permute_3_1_2_0(vec4d a) vec4d vec4d_permute_3_2_1_0(vec4d a) vec4d vec4d_permute2_0_2(vec4d a, vec4d b) vec4d vec4d_permute2_1_3(vec4d a, vec4d b) vec4d vec4d_unpack_lo_permute_0_2_1_3(vec4d u, vec4d v) vec4d vec4d_unpack_hi_permute_0_2_1_3(vec4d u, vec4d v) vec4d vec4d_unpackhi_permute_3_1_2_0(vec4d u, vec4d v) vec4d vec4d_unpacklo_permute_3_1_2_0(vec4d u, vec4d v) .. macro:: VEC4D_TRANSPOSE(z0, z1, z2, z3, a0, a1, a2, a3) Sets the rows ``z`` to the transpose of the 4x4 matrix given by rows ``a``. Comparisons ------------------------------------------------------------------------------- .. function:: int vec1d_same(double a, double b) int vec4d_same(vec4d a, vec4d b) int vec8d_same(vec8d a, vec8d b) Check whether the vectors are equal. .. function:: vec4d vec4d_cmp_ge(vec4d a, vec4d b) vec4d vec4d_cmp_gt(vec4d a, vec4d b) Entrywise comparisons. Arithmetic and basic operations ------------------------------------------------------------------------------- .. function:: vec1d vec1d_round(vec1d a) vec4d vec4d_round(vec4d a) vec8d vec8d_round(vec8d a) .. function:: vec1d vec1d_zero() vec4d vec4d_zero() vec8d vec8d_zero() .. function:: vec1d vec1d_one() vec4d vec4d_one() vec8d vec8d_one() .. function:: vec1d vec1d_add(vec1d a, vec1d b) vec1d vec1d_sub(vec1d a, vec1d b) vec4d vec4d_add(vec4d a, vec4d b) vec4d vec4d_sub(vec4d a, vec4d b) vec4n vec4n_add(vec4n a, vec4n b) vec4n vec4n_sub(vec4n a, vec4n b) vec8d vec8d_add(vec8d a, vec8d b) vec8d vec8d_sub(vec8d a, vec8d b) .. function:: vec1d vec1d_addsub(vec1d a, vec1d b) vec4d vec4d_addsub(vec4d a, vec4d b) .. function:: vec1d vec1d_neg(vec1d a) vec4d vec4d_neg(vec4d a) vec8d vec8d_neg(vec8d a) .. function:: vec1d vec1d_abs(vec1d a) vec4d vec4d_abs(vec4d a) .. function:: vec1d vec1d_max(vec1d a, vec1d b) vec1d vec1d_min(vec1d a, vec1d b) vec4d vec4d_max(vec4d a, vec4d b) vec4d vec4d_min(vec4d a, vec4d b) vec8d vec8d_max(vec8d a, vec8d b) vec8d vec8d_min(vec8d a, vec8d b) .. function:: vec1d vec1d_mul(vec1d a, vec1d b) vec4d vec4d_mul(vec4d a, vec4d b) vec8d vec8d_mul(vec8d a, vec8d b) .. function:: vec1d vec1d_half(vec1d a) vec4d vec4d_half(vec4d a) .. function:: vec1d vec1d_div(vec1d a, vec1d b) vec4d vec4d_div(vec4d a, vec4d b) vec8d vec8d_div(vec8d a, vec8d b) .. function:: vec1d vec1d_fmadd(vec1d a, vec1d b, vec1d c) vec4d vec4d_fmadd(vec4d a, vec4d b, vec4d c) vec8d vec8d_fmadd(vec8d a, vec8d b, vec8d c) .. function:: vec1d vec1d_fmsub(vec1d a, vec1d b, vec1d c) vec4d vec4d_fmsub(vec4d a, vec4d b, vec4d c) vec8d vec8d_fmsub(vec8d a, vec8d b, vec8d c) .. function:: vec1d vec1d_fnmadd(vec1d a, vec1d b, vec1d c) vec4d vec4d_fnmadd(vec4d a, vec4d b, vec4d c) vec8d vec8d_fnmadd(vec8d a, vec8d b, vec8d c) .. function:: vec1d vec1d_fnmsub(vec1d a, vec1d b, vec1d c) vec4d vec4d_fnmsub(vec4d a, vec4d b, vec4d c) vec8d vec8d_fnmsub(vec8d a, vec8d b, vec8d c) .. function:: vec1d vec1d_blendv(vec1d a, vec1d b, vec1d c) vec4d vec4d_blendv(vec4d a, vec4d b, vec4d c) vec8d vec8d_blendv(vec8d a, vec8d b, vec8d c) .. function:: vec4n vec4n_bit_shift_right(vec4n a, ulong b) vec8n vec8n_bit_shift_right(vec8n a, ulong b) .. function:: vec4n vec4n_bit_and(vec4n a, vec4n b) vec8n vec8n_bit_and(vec8n a, vec8n b) Modular arithmetic ------------------------------------------------------------------------------- These functions are used internally by the small-prime FFT. Some ``double`` variants assume an odd modulus `n < 2^{50}`. Other assumptions are not yet documented. .. function:: int vec1d_same_mod(vec1d a, vec1d b, vec1d n, vec1d ninv) int vec4d_same_mod(vec4d a, vec4d b, vec4d n, vec4d ninv) Return whether `a` and `b` are the same mod `n`. .. function:: vec1d vec1d_reduce_pm1no_to_0n(vec1d a, vec1d n) vec1d vec4d_reduce_pm1no_to_0n(vec4d a, vec4d n) vec8d vec8d_reduce_pm1no_to_0n(vec8d a, vec8d n) Return `a \bmod n` reduced to `[0,n)` assuming `a \in (-n,n)`. .. function:: vec1d vec1d_reduce_to_pm1n(vec1d a, vec1d n, vec1d ninv) vec4d vec4d_reduce_to_pm1n(vec4d a, vec4d n, vec4d ninv) vec8d vec8d_reduce_to_pm1n(vec8d a, vec8d n, vec8d ninv) Return `a \bmod n` reduced to `[-n,n]`. .. function:: vec1d vec1d_reduce_to_pm1no(vec1d a, vec1d n, vec1d ninv) vec4d vec4d_reduce_to_pm1no(vec4d a, vec4d n, vec4d ninv) vec8d vec8d_reduce_to_pm1no(vec8d a, vec8d n, vec8d ninv) Return `a \bmod n` reduced to `(-n,n)`. .. function:: vec1d vec1d_reduce_0n_to_pmhn(vec1d a, vec1d n) vec4d vec4d_reduce_0n_to_pmhn(vec4d a, vec4d n) Return `a \bmod n` reduced to `[-n/2, n/2]` given `a \in [0,n]`. .. function:: vec1d vec1d_reduce_pm1n_to_pmhn(vec1d a, vec1d n) vec4d vec4d_reduce_pm1n_to_pmhn(vec4d a, vec4d n) vec8d vec8d_reduce_pm1n_to_pmhn(vec8d a, vec8d n) Return `a \bmod n` reduced to `[-n/2, n/2]` given given `a \in [-n,n]`. .. function:: vec1d vec1d_reduce_2n_to_n(vec1d a, vec1d n) vec4d vec4d_reduce_2n_to_n(vec4d a, vec4d n) vec8d vec8d_reduce_2n_to_n(vec8d a, vec8d n) Return `a \bmod n` reduced to `[0,n)` given given `a \in [0,2n)`. .. function:: vec1d vec1d_reduce_to_0n(vec1d a, vec1d n, vec1d ninv) vec4d vec4d_reduce_to_0n(vec4d a, vec4d n, vec4d ninv) vec8d vec8d_reduce_to_0n(vec8d a, vec8d n, vec8d ninv) Return `a \bmod n` reduced to `[0,n)`. .. function:: vec1d vec1d_mulmod(vec1d a, vec1d b, vec1d n, vec1d ninv) vec4d vec4d_mulmod(vec4d a, vec4d b, vec4d n, vec4d ninv) vec8d vec8d_mulmod(vec8d a, vec8d b, vec8d n, vec8d ninv) Return `ab \bmod n` in `[-n,n]` with assumptions. .. function:: vec1d vec1d_nmulmod(vec1d a, vec1d b, vec1d n, vec1d ninv) vec4d vec4d_nmulmod(vec4d a, vec4d b, vec4d n, vec4d ninv) vec8d vec8d_nmulmod(vec8d a, vec8d b, vec8d n, vec8d ninv) Return `ab \bmod n` in `[-n,n]` with assumptions. .. function:: vec4n vec4n_addmod(vec4n a, vec4n b, vec4n n) vec8n vec8n_addmod(vec8n a, vec8n b, vec8n n) Return `a + b \bmod n` in `[0,n)` .. function:: vec4n vec4n_addmod_limited(vec4n a, vec4n b, vec4n n) vec8n vec8n_addmod_limited(vec8n a, vec8n b, vec8n n) Return `a + b \bmod n` in `[0,n)`, assuming that `n < 2^{63}`. flint-3.1.3/doc/source/mag.rst000066400000000000000000000423071461254215100162040ustar00rootroot00000000000000.. _mag: **mag.h** -- fixed-precision unsigned floating-point numbers for bounds =============================================================================== The :type:`mag_t` type holds an unsigned floating-point number with a fixed-precision mantissa (30 bits) and an arbitrary-precision exponent (represented as an :type:`fmpz_t`), suited for representing magnitude bounds. The special values zero and positive infinity are supported, but not NaN. Operations that involve rounding will always produce a valid upper bound, or a lower bound if the function name has the suffix *lower*. For performance reasons, no attempt is made to compute the best possible bounds: in general, a bound may be several ulps larger/smaller than the optimal bound. Some functions such as :func:`mag_set` and :func:`mag_mul_2exp_si` are always exact and therefore do not require separate *lower* versions. A common mistake is to forget computing a lower bound for the argument of a decreasing function that is meant to be bounded from above, or vice versa. For example, to compute an upper bound for `(x+1)/(y+1)`, the parameter *x* should initially be an upper bound while *y* should be a lower bound, and one should do:: mag_add_ui(tmp1, x, 1); mag_add_ui_lower(tmp2, y, 1); mag_div(res, tmp1, tmp2); For a lower bound of the same expression, *x* should be a lower bound while *y* should be an upper bound, and one should do:: mag_add_ui_lower(tmp1, x, 1); mag_add_ui(tmp2, y, 1); mag_div_lower(res, tmp1, tmp2); Applications requiring floating-point arithmetic with more flexibility (such as correct rounding, or higher precision) should use the :type:`arf_t` type instead. For calculations where a complex alternation between upper and lower bounds is necessary, it may be cleaner to use :type:`arb_t` arithmetic and convert to a :type:`mag_t` bound only in the end. Types, macros and constants ------------------------------------------------------------------------------- .. type:: mag_struct A :type:`mag_struct` holds a mantissa and an exponent. Special values are encoded by the mantissa being set to zero. .. type:: mag_t A :type:`mag_t` is defined as an array of length one of type :type:`mag_struct`, permitting a :type:`mag_t` to be passed by reference. Memory management ------------------------------------------------------------------------------- .. function:: void mag_init(mag_t x) Initializes the variable *x* for use. Its value is set to zero. .. function:: void mag_clear(mag_t x) Clears the variable *x*, freeing or recycling its allocated memory. .. function:: void mag_swap(mag_t x, mag_t y) Swaps *x* and *y* efficiently. .. function:: mag_ptr _mag_vec_init(slong n) Allocates a vector of length *n*. All entries are set to zero. .. function:: void _mag_vec_clear(mag_ptr v, slong n) Clears a vector of length *n*. .. function:: slong mag_allocated_bytes(const mag_t x) Returns the total number of bytes heap-allocated internally by this object. The count excludes the size of the structure itself. Add ``sizeof(mag_struct)`` to get the size of the object as a whole. Special values ------------------------------------------------------------------------------- .. function:: void mag_zero(mag_t res) Sets *res* to zero. .. function:: void mag_one(mag_t res) Sets *res* to one. .. function:: void mag_inf(mag_t res) Sets *res* to positive infinity. .. function:: int mag_is_special(const mag_t x) Returns nonzero iff *x* is zero or positive infinity. .. function:: int mag_is_zero(const mag_t x) Returns nonzero iff *x* is zero. .. function:: int mag_is_inf(const mag_t x) Returns nonzero iff *x* is positive infinity. .. function:: int mag_is_finite(const mag_t x) Returns nonzero iff *x* is not positive infinity (since there is no NaN value, this function is exactly the logical negation of :func:`mag_is_inf`). Assignment and conversions ------------------------------------------------------------------------------- .. function:: void mag_init_set(mag_t res, const mag_t x) Initializes *res* and sets it to the value of *x*. This operation is always exact. .. function:: void mag_set(mag_t res, const mag_t x) Sets *res* to the value of *x*. This operation is always exact. .. function:: void mag_set_d(mag_t res, double x) .. function:: void mag_set_ui(mag_t res, ulong x) .. function:: void mag_set_fmpz(mag_t res, const fmpz_t x) Sets *res* to an upper bound for `|x|`. The operation may be inexact even if *x* is exactly representable. .. function:: void mag_set_d_lower(mag_t res, double x) .. function:: void mag_set_ui_lower(mag_t res, ulong x) .. function:: void mag_set_fmpz_lower(mag_t res, const fmpz_t x) Sets *res* to a lower bound for `|x|`. The operation may be inexact even if *x* is exactly representable. .. function:: void mag_set_d_2exp_fmpz(mag_t res, double x, const fmpz_t y) .. function:: void mag_set_fmpz_2exp_fmpz(mag_t res, const fmpz_t x, const fmpz_t y) .. function:: void mag_set_ui_2exp_si(mag_t res, ulong x, slong y) Sets *res* to an upper bound for `|x| \cdot 2^y`. .. function:: void mag_set_d_2exp_fmpz_lower(mag_t res, double x, const fmpz_t y) .. function:: void mag_set_fmpz_2exp_fmpz_lower(mag_t res, const fmpz_t x, const fmpz_t y) Sets *res* to a lower bound for `|x| \cdot 2^y`. .. function:: double mag_get_d(const mag_t x) Returns a *double* giving an upper bound for *x*. .. function:: double mag_get_d_log2_approx(const mag_t x) Returns a *double* approximating `\log_2(x)`, suitable for estimating magnitudes (warning: not a rigorous bound). The value is clamped between *COEFF_MIN* and *COEFF_MAX*. .. function:: void mag_get_fmpq(fmpq_t res, const mag_t x) .. function:: void mag_get_fmpz(fmpz_t res, const mag_t x) .. function:: void mag_get_fmpz_lower(fmpz_t res, const mag_t x) Sets *res*, respectively, to the exact rational number represented by *x*, the integer exactly representing the ceiling function of *x*, or the integer exactly representing the floor function of *x*. These functions are unsafe: the user must check in advance that *x* is of reasonable magnitude. If *x* is infinite or has a bignum exponent, an abort will be raised. If the exponent otherwise is too large or too small, the available memory could be exhausted resulting in undefined behavior. Comparisons ------------------------------------------------------------------------------- .. function:: int mag_equal(const mag_t x, const mag_t y) Returns nonzero iff *x* and *y* have the same value. .. function:: int mag_cmp(const mag_t x, const mag_t y) Returns negative, zero, or positive, depending on whether *x* is smaller, equal, or larger than *y*. .. function:: int mag_cmp_2exp_si(const mag_t x, slong y) Returns negative, zero, or positive, depending on whether *x* is smaller, equal, or larger than `2^y`. .. function:: void mag_min(mag_t res, const mag_t x, const mag_t y) .. function:: void mag_max(mag_t res, const mag_t x, const mag_t y) Sets *res* respectively to the smaller or the larger of *x* and *y*. Input and output ------------------------------------------------------------------------------- .. function:: void mag_print(const mag_t x) Prints *x* to standard output. .. function:: void mag_fprint(FILE * file, const mag_t x) Prints *x* to the stream *file*. .. function:: char * mag_dump_str(const mag_t x) Allocates a string and writes a binary representation of *x* to it that can be read by :func:`mag_load_str`. The returned string needs to be deallocated with *flint_free*. .. function:: int mag_load_str(mag_t x, const char * str) Parses *str* into *x*. Returns a nonzero value if *str* is not formatted correctly. .. function:: int mag_dump_file(FILE * stream, const mag_t x) Writes a binary representation of *x* to *stream* that can be read by :func:`mag_load_file`. Returns a nonzero value if the data could not be written. .. function:: int mag_load_file(mag_t x, FILE * stream) Reads *x* from *stream*. Returns a nonzero value if the data is not formatted correctly or the read failed. Note that the data is assumed to be delimited by a whitespace or end-of-file, i.e., when writing multiple values with :func:`mag_dump_file` make sure to insert a whitespace to separate consecutive values. Random generation ------------------------------------------------------------------------------- .. function:: void mag_randtest(mag_t res, flint_rand_t state, slong expbits) Sets *res* to a random finite value, with an exponent up to *expbits* bits large. .. function:: void mag_randtest_special(mag_t res, flint_rand_t state, slong expbits) Like :func:`mag_randtest`, but also sometimes sets *res* to infinity. Arithmetic ------------------------------------------------------------------------------- .. function:: void mag_add(mag_t res, const mag_t x, const mag_t y) .. function:: void mag_add_ui(mag_t res, const mag_t x, ulong y) Sets *res* to an upper bound for `x + y`. .. function:: void mag_add_lower(mag_t res, const mag_t x, const mag_t y) .. function:: void mag_add_ui_lower(mag_t res, const mag_t x, ulong y) Sets *res* to a lower bound for `x + y`. .. function:: void mag_add_2exp_fmpz(mag_t res, const mag_t x, const fmpz_t e) Sets *res* to an upper bound for `x + 2^e`. .. function:: void mag_add_ui_2exp_si(mag_t res, const mag_t x, ulong y, slong e) Sets *res* to an upper bound for `x + y 2^e`. .. function:: void mag_sub(mag_t res, const mag_t x, const mag_t y) Sets *res* to an upper bound for `\max(x-y, 0)`. .. function:: void mag_sub_lower(mag_t res, const mag_t x, const mag_t y) Sets *res* to a lower bound for `\max(x-y, 0)`. .. function:: void mag_mul_2exp_si(mag_t res, const mag_t x, slong y) .. function:: void mag_mul_2exp_fmpz(mag_t res, const mag_t x, const fmpz_t y) Sets *res* to `x \cdot 2^y`. This operation is exact. .. function:: void mag_mul(mag_t res, const mag_t x, const mag_t y) .. function:: void mag_mul_ui(mag_t res, const mag_t x, ulong y) .. function:: void mag_mul_fmpz(mag_t res, const mag_t x, const fmpz_t y) Sets *res* to an upper bound for `xy`. .. function:: void mag_mul_lower(mag_t res, const mag_t x, const mag_t y) .. function:: void mag_mul_ui_lower(mag_t res, const mag_t x, ulong y) .. function:: void mag_mul_fmpz_lower(mag_t res, const mag_t x, const fmpz_t y) Sets *res* to a lower bound for `xy`. .. function:: void mag_addmul(mag_t z, const mag_t x, const mag_t y) Sets *z* to an upper bound for `z + xy`. .. function:: void mag_div(mag_t res, const mag_t x, const mag_t y) .. function:: void mag_div_ui(mag_t res, const mag_t x, ulong y) .. function:: void mag_div_fmpz(mag_t res, const mag_t x, const fmpz_t y) Sets *res* to an upper bound for `x / y`. .. function:: void mag_div_lower(mag_t res, const mag_t x, const mag_t y) Sets *res* to a lower bound for `x / y`. .. function:: void mag_inv(mag_t res, const mag_t x) Sets *res* to an upper bound for `1 / x`. .. function:: void mag_inv_lower(mag_t res, const mag_t x) Sets *res* to a lower bound for `1 / x`. Fast, unsafe arithmetic ------------------------------------------------------------------------------- The following methods assume that all inputs are finite and that all exponents (in all inputs as well as the final result) fit as *fmpz* inline values. They also assume that the output variables do not have promoted exponents, as they will be overwritten directly (thus leaking memory). .. function:: void mag_fast_init_set(mag_t x, const mag_t y) Initialises *x* and sets it to the value of *y*. .. function:: void mag_fast_zero(mag_t res) Sets *res* to zero. .. function:: int mag_fast_is_zero(const mag_t x) Returns nonzero iff *x* to zero. .. function:: void mag_fast_mul(mag_t res, const mag_t x, const mag_t y) Sets *res* to an upper bound for `xy`. .. function:: void mag_fast_addmul(mag_t z, const mag_t x, const mag_t y) Sets *z* to an upper bound for `z + xy`. .. function:: void mag_fast_add_2exp_si(mag_t res, const mag_t x, slong e) Sets *res* to an upper bound for `x + 2^e`. .. function:: void mag_fast_mul_2exp_si(mag_t res, const mag_t x, slong e) Sets *res* to an upper bound for `x 2^e`. Powers and logarithms ------------------------------------------------------------------------------- .. function:: void mag_pow_ui(mag_t res, const mag_t x, ulong e) .. function:: void mag_pow_fmpz(mag_t res, const mag_t x, const fmpz_t e) Sets *res* to an upper bound for `x^e`. .. function:: void mag_pow_ui_lower(mag_t res, const mag_t x, ulong e) .. function:: void mag_pow_fmpz_lower(mag_t res, const mag_t x, const fmpz_t e) Sets *res* to a lower bound for `x^e`. .. function:: void mag_sqrt(mag_t res, const mag_t x) Sets *res* to an upper bound for `\sqrt{x}`. .. function:: void mag_sqrt_lower(mag_t res, const mag_t x) Sets *res* to a lower bound for `\sqrt{x}`. .. function:: void mag_rsqrt(mag_t res, const mag_t x) Sets *res* to an upper bound for `1/\sqrt{x}`. .. function:: void mag_rsqrt_lower(mag_t res, const mag_t x) Sets *res* to an lower bound for `1/\sqrt{x}`. .. function:: void mag_hypot(mag_t res, const mag_t x, const mag_t y) Sets *res* to an upper bound for `\sqrt{x^2 + y^2}`. .. function:: void mag_root(mag_t res, const mag_t x, ulong n) Sets *res* to an upper bound for `x^{1/n}`. .. function:: void mag_log(mag_t res, const mag_t x) Sets *res* to an upper bound for `\log(\max(1,x))`. .. function:: void mag_log_lower(mag_t res, const mag_t x) Sets *res* to a lower bound for `\log(\max(1,x))`. .. function:: void mag_neg_log(mag_t res, const mag_t x) Sets *res* to an upper bound for `-\log(\min(1,x))`, i.e. an upper bound for `|\log(x)|` for `x \le 1`. .. function:: void mag_neg_log_lower(mag_t res, const mag_t x) Sets *res* to a lower bound for `-\log(\min(1,x))`, i.e. a lower bound for `|\log(x)|` for `x \le 1`. .. function:: void mag_log_ui(mag_t res, ulong n) Sets *res* to an upper bound for `\log(n)`. .. function:: void mag_log1p(mag_t res, const mag_t x) Sets *res* to an upper bound for `\log(1+x)`. The bound is computed accurately for small *x*. .. function:: void mag_exp(mag_t res, const mag_t x) Sets *res* to an upper bound for `\exp(x)`. .. function:: void mag_exp_lower(mag_t res, const mag_t x) Sets *res* to a lower bound for `\exp(x)`. .. function:: void mag_expinv(mag_t res, const mag_t x) Sets *res* to an upper bound for `\exp(-x)`. .. function:: void mag_expinv_lower(mag_t res, const mag_t x) Sets *res* to a lower bound for `\exp(-x)`. .. function:: void mag_expm1(mag_t res, const mag_t x) Sets *res* to an upper bound for `\exp(x) - 1`. The bound is computed accurately for small *x*. .. function:: void mag_exp_tail(mag_t res, const mag_t x, ulong N) Sets *res* to an upper bound for `\sum_{k=N}^{\infty} x^k / k!`. .. function:: void mag_binpow_uiui(mag_t res, ulong m, ulong n) Sets *res* to an upper bound for `(1 + 1/m)^n`. .. function:: void mag_geom_series(mag_t res, const mag_t x, ulong N) Sets *res* to an upper bound for `\sum_{k=N}^{\infty} x^k`. Special functions ------------------------------------------------------------------------------- .. function:: void mag_const_pi(mag_t res) .. function:: void mag_const_pi_lower(mag_t res) Sets *res* to an upper (respectively lower) bound for `\pi`. .. function:: void mag_atan(mag_t res, const mag_t x) .. function:: void mag_atan_lower(mag_t res, const mag_t x) Sets *res* to an upper (respectively lower) bound for `\operatorname{atan}(x)`. .. function:: void mag_cosh(mag_t res, const mag_t x) .. function:: void mag_cosh_lower(mag_t res, const mag_t x) .. function:: void mag_sinh(mag_t res, const mag_t x) .. function:: void mag_sinh_lower(mag_t res, const mag_t x) Sets *res* to an upper or lower bound for `\cosh(x)` or `\sinh(x)`. .. function:: void mag_fac_ui(mag_t res, ulong n) Sets *res* to an upper bound for `n!`. .. function:: void mag_rfac_ui(mag_t res, ulong n) Sets *res* to an upper bound for `1/n!`. .. function:: void mag_bin_uiui(mag_t res, ulong n, ulong k) Sets *res* to an upper bound for the binomial coefficient `{n \choose k}`. .. function:: void mag_bernoulli_div_fac_ui(mag_t res, ulong n) Sets *res* to an upper bound for `|B_n| / n!` where `B_n` denotes a Bernoulli number. .. function:: void mag_polylog_tail(mag_t res, const mag_t z, slong s, ulong d, ulong N) Sets *res* to an upper bound for .. math:: \sum_{k=N}^{\infty} \frac{z^k \log^d(k)}{k^s}. The bounding strategy is described in :ref:`algorithms_polylogarithms`. Note: in applications where `s` in this formula may be real or complex, the user can simply substitute any convenient integer `s'` such that `s' \le \operatorname{Re}(s)`. .. function:: void mag_hurwitz_zeta_uiui(mag_t res, ulong s, ulong a) Sets *res* to an upper bound for `\zeta(s,a) = \sum_{k=0}^{\infty} (k+a)^{-s}`. We use the formula .. math:: \zeta(s,a) \le \frac{1}{a^s} + \frac{1}{(s-1) a^{s-1}} which is obtained by estimating the sum by an integral. If `s \le 1` or `a = 0`, the bound is infinite. flint-3.1.3/doc/source/memory.rst000066400000000000000000000056471461254215100167560ustar00rootroot00000000000000.. _memory: **Memory management** =============================================================================== Memory allocation functions ------------------------------------------------------------------------------- The file ``flint.h`` defines functions ``flint_malloc``, ``flint_realloc``, ``flint_calloc`` and ``flint_free``. They have the same interface as the standard library functions, but may perform additional error checking. By default the memory allocation functions wrap the system's ``malloc``, ``realloc``, ``calloc`` and ``free``. The user can override this behaviour by calling ``__flint_set_memory_functions`` passing the ``malloc``, ``realloc``, ``calloc`` and ``free`` function pointers as parameters (see ``flint.h`` for the exact prototype). The current memory functions can be returned in a similar manner by calling ``__flint_get_memory_functions`` passing the address of pointers in which the function pointers can be stored. Memory allocated with ``flint_malloc`` must be freed with ``flint_free`` and not with ``free``. Global caches and cleanup ------------------------------------------------------------------------------- FLINT may cache some data (such as allocated integers and tables of prime numbers) to speed up various computations. If FLINT is built in threadsafe mode, most caches are thread-local (some are always global and shared among the threads). Data cached by the current thread can be freed by calling the ``flint_cleanup()`` function. The user can register additional cleanup functions to be invoked by ``flint_cleanup()`` by passing a pointer to a function with signature ``void cleanup_function(void)`` to ``flint_register_cleanup_function()``. The user should call ``flint_cleanup_master()`` exactly once right before exiting a program. This cleans up all caches in all threads and should result in a clean output with tools like ``valgrind`` if there are no memory leaks. Temporary allocation ------------------------------------------------------------------------------- FLINT allows for temporary allocation of memory using ``alloca`` to allocate on the stack if the allocation is small enough. The following program demonstrates how to use this facility to allocate two different arrays. .. code-block:: C #include #include "flint.h" void myfun(void) { /* other variable declarations */ mp_ptr a, b; TMP_INIT; /* arbitrary code */ TMP_START; /* we are about to do some allocation */ /* arbitrary code */ a = TMP_ALLOC(32*sizeof(mp_limb_t)); b = TMP_ALLOC(64*sizeof(mp_limb_t)); /* arbitrary code */ TMP_END; /* cleans up a and b */ /* arbitrary code */ } It is very important to note that temporary allocations should not be made in recursive functions or in loop bodies, as many small allocations on the stack can exhaust the stack causing a stack overflow. flint-3.1.3/doc/source/mpfr_mat.rst000066400000000000000000000045141461254215100172430ustar00rootroot00000000000000.. _mpfr-mat: **mpfr_mat.h** -- matrices of MPFR floating-point numbers =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: void mpfr_mat_init(mpfr_mat_t mat, slong rows, slong cols, mpfr_prec_t prec) Initialises a matrix with the given number of rows and columns and the given precision for use. The precision is the exact precision of the entries. .. function:: void mpfr_mat_clear(mpfr_mat_t mat) Clears the given matrix. Basic manipulation -------------------------------------------------------------------------------- .. function:: __mpfr_struct * mpfr_mat_entry(const mpfr_mat_t mat, slong i, slong j) Return a reference to the entry at row `i` and column `j` of the given matrix. The values `i` and `j` must be within the bounds for the matrix. The reference can be used to either return or set the given entry. .. function:: void mpfr_mat_swap(mpfr_mat_t mat1, mpfr_mat_t mat2) Efficiently swap matrices ``mat1`` and ``mat2``. .. function:: void mpfr_mat_swap_entrywise(mpfr_mat_t mat1, mpfr_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: void mpfr_mat_set(mpfr_mat_t mat1, const mpfr_mat_t mat2) Set ``mat1`` to the value of ``mat2``. .. function:: void mpfr_mat_zero(mpfr_mat_t mat) Set ``mat`` to the zero matrix. Comparison -------------------------------------------------------------------------------- .. function:: int mpfr_mat_equal(const mpfr_mat_t mat1, const mpfr_mat_t mat2) Return `1` if the two given matrices are equal, otherwise return `0`. Randomisation -------------------------------------------------------------------------------- .. function:: void mpfr_mat_randtest(mpfr_mat_t mat, flint_rand_t state) Generate a random matrix with random number of rows and columns and random entries for use in test code. Basic arithmetic -------------------------------------------------------------------------------- .. function:: void mpfr_mat_mul_classical(mpfr_mat_t C, const mpfr_mat_t A, const mpfr_mat_t B, mpfr_rnd_t rnd) Set `C` to the product of `A` and `B` with the given rounding mode, using the classical algorithm. flint-3.1.3/doc/source/mpfr_vec.rst000066400000000000000000000032461461254215100172400ustar00rootroot00000000000000.. _mpfr-vec: **mpfr_vec.h** -- vectors of MPFR floating-point numbers =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: mpfr_ptr _mpfr_vec_init(slong len, flint_bitcnt_t prec) Returns a vector of the given length of initialised ``mpfr``'s with the given exact precision. .. function:: void _mpfr_vec_clear(mpfr_ptr vec, slong len) Clears the given vector. Arithmetic -------------------------------------------------------------------------------- .. function:: void _mpfr_vec_zero(mpfr_ptr vec, slong len) Zeros the vector ``(vec, len)``. .. function:: void _mpfr_vec_set(mpfr_ptr vec1, mpfr_srcptr vec2, slong len) Copies the vector ``vec2`` of the given length into ``vec1``. No check is made to ensure ``vec1`` and ``vec2`` are different. .. function:: void _mpfr_vec_add(mpfr_ptr res, mpfr_srcptr vec1, mpfr_srcptr vec2, slong len) Adds the given vectors of the given length together and stores the result in ``res``. .. function:: void _mpfr_vec_scalar_mul_mpfr(mpfr_ptr res, mpfr_srcptr vec, slong len, mpfr_t c) Multiplies the vector with given length by the scalar `c` and sets ``res`` to the result. .. function:: void _mpfr_vec_scalar_mul_2exp(mpfr_ptr res, mpfr_srcptr vec, slong len, flint_bitcnt_t exp) Multiplies the given vector of the given length by ``2^exp``. .. function:: void _mpfr_vec_scalar_product(mpfr_t res, mpfr_srcptr vec1, mpfr_srcptr vec2, slong len) Sets ``res`` to the scalar product of ``(vec1, len)`` with ``(vec2, len)``. Assumes ``len > 0``. flint-3.1.3/doc/source/mpn_extras.rst000066400000000000000000000275421461254215100176240ustar00rootroot00000000000000.. _mpn-extras: **mpn_extras.h** -- support functions for limb arrays =============================================================================== Macros -------------------------------------------------------------------------------- .. macro:: MPN_NORM(a, an) Normalise ``(a, an)`` so that either ``an`` is zero or ``a[an - 1]`` is nonzero. .. macro:: MPN_SWAP(a, an, b, bn) Swap ``(a, an)`` and ``(b, bn)``, i.e. swap pointers and sizes. Utility functions -------------------------------------------------------------------------------- .. function:: void flint_mpn_debug(mp_srcptr x, mp_size_t xsize) Prints debug information about ``(x, xsize)`` to ``stdout``. In particular, this will print binary representations of all the limbs. .. function:: int flint_mpn_zero_p(mp_srcptr x, mp_size_t xsize) Returns `1` if all limbs of ``(x, xsize)`` are zero, otherwise `0`. .. function:: mp_limb_t flint_mpn_sumdiff_n(mp_ptr s, mp_ptr d, mp_srcptr x, mp_srcptr y, mp_size_t n) Simultaneously computes the sum ``s`` and difference ``d`` of ``(x, n)`` and ``(y, n)``, returning carry multiplied by two plus borrow. Multiplication -------------------------------------------------------------------------------- .. function:: mp_limb_t flint_mpn_mul(mp_ptr z, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn) Sets ``(z, xn+yn)`` to the product of ``(x, xn)`` and ``(y, yn)`` and returns the top limb of the result. We require `xn \ge yn \ge 1` and that ``z`` is not aliased with either input operand. This function uses FFT multiplication if the operands are large enough and otherwise calls ``mpn_mul``. .. function:: void flint_mpn_mul_n(mp_ptr z, mp_srcptr x, mp_srcptr y, mp_size_t n) Sets ``z`` to the product of ``(x, n)`` and ``(y, n)``. We require `n \ge 1` and that ``z`` is not aliased with either input operand. This function uses FFT multiplication if the operands are large enough and otherwise calls ``mpn_mul_n``. .. function:: void flint_mpn_sqr(mp_ptr z, mp_srcptr x, mp_size_t n) Sets ``z`` to the square of ``(x, n)``. We require `n \ge 1` and that ``z`` is not aliased with either input operand. This function uses FFT multiplication if the operands are large enough and otherwise calls ``mpn_sqr``. .. function:: mp_size_t flint_mpn_fmms1(mp_ptr y, mp_limb_t a1, mp_srcptr x1, mp_limb_t a2, mp_srcptr x2, mp_size_t n) Given not-necessarily-normalized `x_1` and `x_2` of length `n > 0` and output `y` of length `n`, try to compute `y = a_1\cdot x_1 - a_2\cdot x_2`. Return the normalized length of `y` if `y \ge 0` and `y` fits into `n` limbs. Otherwise, return `-1`. `y` may alias `x_1` but is not allowed to alias `x_2`. .. function:: mp_limb_t flint_mpn_mulhigh_n(mp_ptr rp, mp_srcptr xp, mp_srcptr yp, mp_size_t n) Sets *{rp, n}* to the "high part" of *{xp, n}* times *{yp, n}* and returns the *n*-th least significant limb, in the sense that the multiplication of the *n - 1* lower limbs are never accounted for. Hence, the multiplication is typically non-exact for sizes larger than one. The highest error is *n + 2* ULP in the returned limb. .. note:: This function may not exist on processors not supporting the ADX instruction set. .. function:: void flint_mpn_mul_toom22(mp_ptr pp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn, mp_ptr scratch) Toom-22 (Karatsuba) multiplication. The *scratch* space must have room for `2 an + k` limbs where `k` is the number of limbs. If *NULL* is passed, space will be allocated internally. Divisibility -------------------------------------------------------------------------------- .. function:: int flint_mpn_divisible_1_odd(mp_srcptr x, mp_size_t xsize, mp_limb_t d) Expression determining whether ``(x, xsize)`` is divisible by the ``mp_limb_t d`` which is assumed to be odd-valued and at least `3`. This function is implemented as a macro. .. function:: mp_size_t flint_mpn_divexact_1(mp_ptr x, mp_size_t xsize, mp_limb_t d) Divides `x` once by a known single-limb divisor, returns the new size. .. function:: mp_size_t flint_mpn_remove_2exp(mp_ptr x, mp_size_t xsize, flint_bitcnt_t * bits) Divides ``(x, xsize)`` by `2^n` where `n` is the number of trailing zero bits in `x`. The new size of `x` is returned, and `n` is stored in the bits argument. `x` may not be zero. .. function:: mp_size_t flint_mpn_remove_power_ascending(mp_ptr x, mp_size_t xsize, mp_ptr p, mp_size_t psize, ulong * exp) Divides ``(x, xsize)`` by the largest power `n` of ``(p, psize)`` that is an exact divisor of `x`. The new size of `x` is returned, and `n` is stored in the ``exp`` argument. `x` may not be zero, and `p` must be greater than `2`. This function works by testing divisibility by ascending squares `p, p^2, p^4, p^8, \dotsc`, making it efficient for removing potentially large powers. Because of its high overhead, it should not be used as the first stage of trial division. .. function:: int flint_mpn_factor_trial(mp_srcptr x, mp_size_t xsize, slong start, slong stop) Searches for a factor of ``(x, xsize)`` among the primes in positions ``start, ..., stop-1`` of ``flint_primes``. Returns `i` if ``flint_primes[i]`` is a factor, otherwise returns `0` if no factor is found. It is assumed that ``start >= 1``. .. function:: int flint_mpn_factor_trial_tree(slong * factors, mp_srcptr x, mp_size_t xsize, slong num_primes) Searches for a factor of ``(x, xsize)`` among the primes in positions approximately in the range ``0, ..., num_primes - 1`` of ``flint_primes``. Returns the number of prime factors found and fills ``factors`` with their indices in ``flint_primes``. It is assumed that ``num_primes`` is in the range ``0, ..., 3512``. If the input fits in a small ``fmpz`` the number is fully factored instead. The algorithm used is a tree based gcd with a product of primes, the tree for which is cached globally (it is threadsafe). Division -------------------------------------------------------------------------------- .. function:: int flint_mpn_divides(mp_ptr q, mp_srcptr array1, mp_size_t limbs1, mp_srcptr arrayg, mp_size_t limbsg, mp_ptr temp) If ``(arrayg, limbsg)`` divides ``(array1, limbs1)`` then ``(q, limbs1 - limbsg + 1)`` is set to the quotient and 1 is returned, otherwise 0 is returned. The temporary space ``temp`` must have space for ``limbsg`` limbs. Assumes ``limbs1 >= limbsg > 0``. .. function:: mp_limb_t flint_mpn_preinv1(mp_limb_t d, mp_limb_t d2) Computes a precomputed inverse from the leading two limbs of the divisor ``b, n`` to be used with the ``preinv1`` functions. We require the most significant bit of ``b, n`` to be 1. .. function:: mp_limb_t flint_mpn_divrem_preinv1(mp_ptr q, mp_ptr a, mp_size_t m, mp_srcptr b, mp_size_t n, mp_limb_t dinv) Divide ``a, m`` by ``b, n``, returning the high limb of the quotient (which will either be 0 or 1), storing the remainder in-place in ``a, n`` and the rest of the quotient in ``q, m - n``. We require the most significant bit of ``b, n`` to be 1. ``dinv`` must be computed from ``b[n - 1]``, ``b[n - 2]`` by ``flint_mpn_preinv1``. We also require ``m >= n >= 2``. .. function:: void flint_mpn_mulmod_preinv1(mp_ptr r, mp_srcptr a, mp_srcptr b, mp_size_t n, mp_srcptr d, mp_limb_t dinv, ulong norm) Given a normalised integer `d` with precomputed inverse ``dinv`` provided by ``flint_mpn_preinv1``, computes `ab \pmod{d}` and stores the result in `r`. Each of `a`, `b` and `r` is expected to have `n` limbs of space, with zero padding if necessary. The value ``norm`` is provided for convenience. If `a`, `b` and `d` have been shifted left by ``norm`` bits so that `d` is normalised, then `r` will be shifted right by ``norm`` bits so that it has the same shift as all the inputs. We require `a` and `b` to be reduced modulo `n` before calling the function. .. function:: void flint_mpn_preinvn(mp_ptr dinv, mp_srcptr d, mp_size_t n) Compute an `n` limb precomputed inverse ``dinv`` of the `n` limb integer `d`. We require that `d` is normalised, i.e. with the most significant bit of the most significant limb set. .. function:: void flint_mpn_mod_preinvn(mp_ptr r, mp_srcptr a, mp_size_t m, mp_srcptr d, mp_size_t n, mp_srcptr dinv) Given a normalised integer `d` of `n` limbs, with precomputed inverse ``dinv`` provided by ``flint_mpn_preinvn`` and integer `a` of `m` limbs, computes `a \pmod{d}` and stores the result in-place in the lower `n` limbs of `a`. The remaining limbs of `a` are destroyed. We require `m \geq n`. No aliasing of `a` with any of the other operands is permitted. Note that this function is not always as fast as ordinary division. .. function:: mp_limb_t flint_mpn_divrem_preinvn(mp_ptr q, mp_ptr r, mp_srcptr a, mp_size_t m, mp_srcptr d, mp_size_t n, mp_srcptr dinv) Given a normalised integer `d` with precomputed inverse ``dinv`` provided by ``flint_mpn_preinvn``, computes the quotient of `a` by `d` and stores the result in `q` and the remainder in the lower `n` limbs of `a`. The remaining limbs of `a` are destroyed. The value `q` is expected to have space for `m - n` limbs and we require `m \ge n`. No aliasing is permitted between `q` and `a` or between these and any of the other operands. Note that this function is not always as fast as ordinary division. .. function:: void flint_mpn_mulmod_preinvn(mp_ptr r, mp_srcptr a, mp_srcptr b, mp_size_t n, mp_srcptr d, mp_srcptr dinv, ulong norm) Given a normalised integer `d` with precomputed inverse ``dinv`` provided by ``flint_mpn_preinvn``, computes `ab \pmod{d}` and stores the result in `r`. Each of `a`, `b` and `r` is expected to have `n` limbs of space, with zero padding if necessary. The value ``norm`` is provided for convenience. If `a`, `b` and `d` have been shifted left by ``norm`` bits so that `d` is normalised, then `r` will be shifted right by ``norm`` bits so that it has the same shift as all the inputs. We require `a` and `b` to be reduced modulo `n` before calling the function. Note that this function is not always as fast as ordinary division. GCD -------------------------------------------------------------------------------- .. function:: mp_size_t flint_mpn_gcd_full2(mp_ptr arrayg, mp_srcptr array1, mp_size_t limbs1, mp_srcptr array2, mp_size_t limbs2, mp_ptr temp) Sets ``(arrayg, retvalue)`` to the gcd of ``(array1, limbs1)`` and ``(array2, limbs2)``. The only assumption is that neither ``limbs1`` nor ``limbs2`` is zero. The function must be supplied with ``limbs1 + limbs2`` limbs of temporary space, or ``NULL`` must be passed to ``temp`` if the function should allocate its own space. .. function:: mp_size_t flint_mpn_gcd_full(mp_ptr arrayg, mp_srcptr array1, mp_size_t limbs1, mp_srcptr array2, mp_size_t limbs2) Sets ``(arrayg, retvalue)`` to the gcd of ``(array1, limbs1)`` and ``(array2, limbs2)``. The only assumption is that neither ``limbs1`` nor ``limbs2`` is zero. Random Number Generation -------------------------------------------------------------------------------- .. function:: void flint_mpn_rrandom(mp_limb_t * rp, gmp_randstate_t state, mp_size_t n) Generates a random number with ``n`` limbs and stores it on ``rp``. The number it generates will tend to have long strings of zeros and ones in the binary representation. Useful for testing functions and algorithms, since this kind of random numbers have proven to be more likely to trigger corner-case bugs. .. function:: void flint_mpn_urandomb(mp_limb_t * rp, gmp_randstate_t state, flint_bitcnt_t n) Generates a uniform random number of ``n`` bits and stores it on ``rp``. flint-3.1.3/doc/source/mpoly.rst000066400000000000000000000453171461254215100166040ustar00rootroot00000000000000.. _mpoly: **mpoly.h** -- support functions for multivariate polynomials =============================================================================== An array of type ``ulong *`` or ``fmpz **`` is used to communicate exponent vectors. These exponent vectors must have length equal to the number of variables in the polynomial ring. The element of this exponent vector at index `0` corresponds to the most significant variable in the monomial ordering. For example, if the polynomial is `7\cdot x^2\cdot y+8\cdot y\cdot z+9` and the variables are ordered so that `x>y>z`, the degree function will return `\{2,1,1\}`. Similarly, the exponent vector of the `0`-index term of this polynomial is `\{2,1,0\}`, while the `2`-index term has exponent vector `\{0,0,0\}` and coefficient `9`. Orderings -------------------------------------------------------------------------------- .. type:: ordering_t An enumeration of supported term orderings. Currently one of ``ORD_LEX``, ``ORD_DEGLEX`` or ``ORD_DEGREVLEX``. .. type:: mpoly_ctx_struct mpoly_ctx_t An mpoly_ctx_struct is a structure holding information about the number of variables and the term ordering of a multivariate polynomial. .. function:: void mpoly_ctx_init(mpoly_ctx_t ctx, slong nvars, const ordering_t ord) Initialize a context for specified number of variables and ordering. .. function:: void mpoly_ctx_clear(mpoly_ctx_t mctx) Clean up any space used by a context object. .. function:: ordering_t mpoly_ordering_randtest(flint_rand_t state) Return a random ordering. The possibilities are ``ORD_LEX``, ``ORD_DEGLEX`` and ``ORD_DEGREVLEX``. .. function:: void mpoly_ctx_init_rand(mpoly_ctx_t mctx, flint_rand_t state, slong max_nvars) Initialize a context with a random choice for the ordering. .. function:: int mpoly_ordering_isdeg(const mpoly_ctx_t ctx) Return 1 if the ordering of the given context is a degree ordering (deglex or degrevlex). .. function:: int mpoly_ordering_isrev(const mpoly_ctx_t cth) Return 1 if the ordering of the given context is a reverse ordering (currently only degrevlex). .. function:: void mpoly_ordering_print(ordering_t ord) Print a string (either "lex", "deglex" or "degrevlex") to standard output, corresponding to the given ordering. Monomial arithmetic -------------------------------------------------------------------------------- These functions in this section are **only provided as inline functions** as they are somewhat trivial. This is in order to minimize the FLINT binary. .. function:: void mpoly_monomial_add(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) Set ``(exp_ptr, N)`` to the sum of the monomials ``(exp2, N)`` and ``(exp3, N)``, assuming ``bits <= FLINT_BITS``. .. function:: void mpoly_monomial_add_mp(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) Set ``(exp_ptr, N)`` to the sum of the monomials ``(exp2, N)`` and ``(exp3, N)``. .. function:: void mpoly_monomial_sub(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) Set ``(exp_ptr, N)`` to the difference of the monomials ``(exp2, N)`` and ``(exp3, N)``, assuming ``bits <= FLINT_BITS`` .. function:: void mpoly_monomial_sub_mp(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) Set ``(exp_ptr, N)`` to the difference of the monomials ``(exp2, N)`` and ``(exp3, N)``. .. function:: int mpoly_monomial_overflows(ulong * exp2, slong N, ulong mask) Return true if any of the fields of the given monomial ``(exp2, N)`` has overflowed (or is negative). The ``mask`` is a word with the high bit of each field set to 1. In other words, the function returns 1 if any word of ``exp2`` has any of the nonzero bits in ``mask`` set. Assumes that ``bits <= FLINT_BITS``. .. function:: int mpoly_monomial_overflows_mp(ulong * exp_ptr, slong N, flint_bitcnt_t bits) Return true if any of the fields of the given monomial ``(exp_ptr, N)`` has overflowed. Assumes that ``bits >= FLINT_BITS``. .. function:: int mpoly_monomial_overflows1(ulong exp, ulong mask) As per ``mpoly_monomial_overflows`` with ``N = 1``. .. function:: void mpoly_monomial_set(ulong * exp2, const ulong * exp3, slong N) Set the monomial ``(exp2, N)`` to ``(exp3, N)``. .. function:: void mpoly_monomial_swap(ulong * exp2, ulong * exp3, slong N) Swap the words in ``(exp2, N)`` and ``(exp3, N)``. .. function:: void mpoly_monomial_mul_ui(ulong * exp2, const ulong * exp3, slong N, ulong c) Set the words of ``(exp2, N)`` to the words of ``(exp3, N)`` multiplied by ``c``. Monomial comparison -------------------------------------------------------------------------------- These functions in this section are **only provided as inline functions** as they are somewhat trivial. This is in order to minimize the FLINT binary. .. function:: int mpoly_monomial_is_zero(const ulong * exp, slong N) Return 1 if ``(exp, N)`` is zero. .. function:: int mpoly_monomial_equal(const ulong * exp2, const ulong * exp3, slong N) Return 1 if the monomials ``(exp2, N)`` and ``(exp3, N)`` are equal. .. function:: void mpoly_get_cmpmask(ulong * cmpmask, slong N, ulong bits, const mpoly_ctx_t mctx) Get the mask ``(cmpmask, N)`` for comparisons. ``bits`` should be set to the number of bits in the exponents to be compared. Any function that compares monomials should use this comparison mask. .. function:: int mpoly_monomial_lt(const ulong * exp2, const ulong * exp3, slong N, const ulong * cmpmask) Return 1 if ``(exp2, N)`` is less than ``(exp3, N)``. .. function:: int mpoly_monomial_gt(const ulong * exp2, const ulong * exp3, slong N, const ulong * cmpmask) Return 1 if ``(exp2, N)`` is greater than ``(exp3, N)``. .. function:: int mpoly_monomial_cmp(const ulong * exp2, const ulong * exp3, slong N, const ulong * cmpmask) Return `1` if ``(exp2, N)`` is greater than, `0` if it is equal to and `-1` if it is less than ``(exp3, N)``. Monomial divisibility -------------------------------------------------------------------------------- These functions in this section are **only provided as inline functions** as they are somewhat trivial. This is in order to minimize the FLINT binary. .. function:: int mpoly_monomial_divides(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N, ulong mask) Return 1 if the monomial ``(exp3, N)`` divides ``(exp2, N)``. If so set ``(exp_ptr, N)`` to the quotient monomial. The ``mask`` is a word with the high bit of each bit field set to 1. Assumes that ``bits <= FLINT_BITS``. .. function:: int mpoly_monomial_divides_mp(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N, flint_bitcnt_t bits) Return 1 if the monomial ``(exp3, N)`` divides ``(exp2, N)``. If so set ``(exp_ptr, N)`` to the quotient monomial. Assumes that ``bits >= FLINT_BITS``. .. function:: int mpoly_monomial_divides1(ulong * exp_ptr, const ulong exp2, const ulong exp3, ulong mask) As per ``mpoly_monomial_divides`` with ``N = 1``. .. function:: int mpoly_monomial_divides_tight(slong e1, slong e2, slong * prods, slong num) Return 1 if the monomial ``e2`` divides the monomial ``e1``, where the monomials are stored using factorial representation. The array ``(prods, num)`` should consist of `1`, `b_1, b_1\times b_2, \ldots`, where the `b_i` are the bases of the factorial number representation. Basic manipulation -------------------------------------------------------------------------------- .. function:: flint_bitcnt_t mpoly_exp_bits_required_ui(const ulong * user_exp, const mpoly_ctx_t mctx) Returns the number of bits required to store ``user_exp`` in packed format. The returned number of bits includes space for a zeroed signed bit. .. function:: flint_bitcnt_t mpoly_exp_bits_required_ffmpz(const fmpz * user_exp, const mpoly_ctx_t mctx) Returns the number of bits required to store ``user_exp`` in packed format. The returned number of bits includes space for a zeroed signed bit. .. function:: flint_bitcnt_t mpoly_exp_bits_required_pfmpz(fmpz * const * user_exp, const mpoly_ctx_t mctx) Returns the number of bits required to store ``user_exp`` in packed format. The returned number of bits includes space for a zeroed signed bit. .. function:: void mpoly_max_fields_ui_sp(ulong * max_fields, const ulong * poly_exps, slong len, ulong bits, const mpoly_ctx_t mctx) Compute the field-wise maximum of packed exponents from ``poly_exps`` of length ``len`` and unpack the result into ``max_fields``. The maximums are assumed to fit a ulong. .. function:: void mpoly_max_fields_fmpz(fmpz * max_fields, const ulong * poly_exps, slong len, ulong bits, const mpoly_ctx_t mctx) Compute the field-wise maximum of packed exponents from ``poly_exps`` of length ``len`` and unpack the result into ``max_fields``. .. function:: void mpoly_max_degrees_tight(slong * max_exp, ulong * exps, slong len, slong * prods, slong num) Return an array of ``num`` integers corresponding to the maximum degrees of the exponents in the array of exponent vectors ``(exps, len)``, assuming that the exponent are packed in a factorial representation. The array ``(prods, num)`` should consist of `1`, `b_1`, `b_1\times b_2, \ldots`, where the `b_i` are the bases of the factorial number representation. The results are stored in the array ``max_exp``, with the entry corresponding to the most significant base of the factorial representation first in the array. .. function:: int mpoly_monomial_exists(slong * index, const ulong * poly_exps, const ulong * exp, slong len, slong N, const ulong * cmpmask) Returns true if the given exponent vector ``exp`` exists in the array of exponent vectors ``(poly_exps, len)``, otherwise, returns false. If the exponent vector is found, its index into the array of exponent vectors is returned. Otherwise, ``index`` is set to the index where this exponent could be inserted to preserve the ordering. The index can be in the range ``[0, len]``. .. function:: void mpoly_search_monomials(slong ** e_ind, ulong * e, slong * e_score, slong * t1, slong * t2, slong * t3, slong lower, slong upper, const ulong * a, slong a_len, const ulong * b, slong b_len, slong N, const ulong * cmpmask) Given packed exponent vectors ``a`` and ``b``, compute a packed exponent ``e`` such that the number of monomials in the cross product ``a`` X ``b`` that are less than or equal to ``e`` is between ``lower`` and ``upper``. This number is stored in ``e_store``. If no such monomial exists, one is chosen so that the number of monomials is as close as possible. This function assumes that ``1`` is the smallest monomial and needs three arrays ``t1``, ``t2``, and ``t3`` of the size as ``a`` for workspace. The parameter ``e_ind`` is set to one of ``t1``, ``t2``, and ``t3`` and gives the locations of the monomials in ``a`` X ``b``. Setting and getting monomials -------------------------------------------------------------------------------- .. function:: int mpoly_term_exp_fits_ui(ulong * exps, ulong bits, slong n, const mpoly_ctx_t mctx) Return whether every entry of the exponent vector of index `n` in ``exps`` fits into a ``ulong``. .. function:: int mpoly_term_exp_fits_si(ulong * exps, ulong bits, slong n, const mpoly_ctx_t mctx) Return whether every entry of the exponent vector of index `n` in ``exps`` fits into a ``slong``. .. function:: void mpoly_get_monomial_ui(ulong * exps, const ulong * poly_exps, ulong bits, const mpoly_ctx_t mctx) Convert the packed exponent ``poly_exps`` of bit count ``bits`` to a monomial from the user's perspective. The exponents are assumed to fit a ulong. .. function:: void mpoly_get_monomial_ffmpz(fmpz * exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) Convert the packed exponent ``poly_exps`` of bit count ``bits`` to a monomial from the user's perspective. .. function:: void mpoly_get_monomial_pfmpz(fmpz ** exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) Convert the packed exponent ``poly_exps`` of bit count ``bits`` to a monomial from the user's perspective. .. function:: void mpoly_set_monomial_ui(ulong * exp1, const ulong * exp2, ulong bits, const mpoly_ctx_t mctx) Convert the user monomial ``exp2`` to packed format using ``bits``. .. function:: void mpoly_set_monomial_ffmpz(ulong * exp1, const fmpz * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx) Convert the user monomial ``exp2`` to packed format using ``bits``. .. function:: void mpoly_set_monomial_pfmpz(ulong * exp1, fmpz * const * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx) Convert the user monomial ``exp2`` to packed format using ``bits``. Packing and unpacking monomials -------------------------------------------------------------------------------- .. function:: void mpoly_pack_vec_ui(ulong * exp1, const ulong * exp2, ulong bits, slong nfields, slong len) Packs a vector ``exp2`` into \{exp1} using a bit count of ``bits``. No checking is done to ensure that the vector actually fits into ``bits`` bits. The number of fields in each vector is ``nfields`` and the total number of vectors to unpack is ``len``. .. function:: void mpoly_pack_vec_fmpz(ulong * exp1, const fmpz * exp2, flint_bitcnt_t bits, slong nfields, slong len) Packs a vector ``exp2`` into \{exp1} using a bit count of ``bits``. No checking is done to ensure that the vector actually fits into ``bits`` bits. The number of fields in each vector is ``nfields`` and the total number of vectors to unpack is ``len``. .. function:: void mpoly_unpack_vec_ui(ulong * exp1, const ulong * exp2, ulong bits, slong nfields, slong len) Unpacks vector ``exp2`` of bit count ``bits`` into ``exp1``. The number of fields in each vector is ``nfields`` and the total number of vectors to unpack is ``len``. .. function:: void mpoly_unpack_vec_fmpz(fmpz * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len) Unpacks vector ``exp2`` of bit count ``bits`` into ``exp1``. The number of fields in each vector is ``nfields`` and the total number of vectors to unpack is ``len``. .. function:: int mpoly_repack_monomials(ulong * exps1, ulong bits1, const ulong * exps2, ulong bits2, slong len, const mpoly_ctx_t mctx) Convert an array of length ``len`` of exponents ``exps2`` packed using bits ``bits2`` into an array ``exps1`` using bits ``bits1``. No checking is done to ensure that the result fits into bits ``bits1``. .. function:: void mpoly_pack_monomials_tight(ulong * exp1, const ulong * exp2, slong len, const slong * mults, slong num, slong bits) Given an array of possibly packed exponent vectors ``exp2`` of length ``len``, where each field of each exponent vector is packed into the given number of bits, return the corresponding array of monomial vectors packed using a factorial numbering scheme. The "bases" for the factorial numbering scheme are given as an array of integers ``mults``, the first entry of which corresponds to the field of least significance in each input exponent vector. Obviously the maximum exponent to be packed must be less than the corresponding base in ``mults``. The number of multipliers is given by ``num``. The code only considers least significant ``num`` fields of each exponent vectors and ignores the rest. The number of ignored fields should be passed in ``extras``. .. function:: void mpoly_unpack_monomials_tight(ulong * e1, ulong * e2, slong len, slong * mults, slong num, slong bits) Given an array of exponent vectors ``e2`` of length ``len`` packed using a factorial numbering scheme, unpack the monomials into an array ``e1`` of exponent vectors in standard packed format, where each field has the given number of bits. The "bases" for the factorial numbering scheme are given as an array of integers ``mults``, the first entry of which corresponds to the field of least significance in each exponent vector. The number of multipliers is given by ``num``. The code only considers least significant ``num`` fields of each exponent vectors and ignores the rest. The number of ignored fields should be passed in ``extras``. Chunking -------------------------------------------------------------------------------- .. function:: void mpoly_main_variable_terms1(slong * i1, slong * n1, const ulong * exp1, slong l1, slong len1, slong k, slong num, slong bits) Given an array of exponent vectors ``(exp1, len1)``, each exponent vector taking one word of space, with each exponent being packed into the given number of bits, compute ``l1`` starting offsets ``i1`` and lengths ``n1`` (which may be zero) to break the exponents into chunks. Each chunk consists of exponents have the same degree in the main variable. The index of the main variable is given by `k`. The variables are indexed from the variable of least significance, starting from `0`. The value ``l1`` should be the degree in the main variable, plus one. Chained heap functions -------------------------------------------------------------------------------- .. function:: int _mpoly_heap_insert(mpoly_heap_s * heap, ulong * exp, void * x, slong * next_loc, slong * heap_len, slong N, const ulong * cmpmask) Given a heap, insert a new node `x` corresponding to the given exponent into the heap. Heap elements are ordered by the exponent ``(exp, N)``, with the largest element at the head of the heap. A pointer to the current heap length must be passed in via ``heap_len``. This will be updated by the function. Note that the index 0 position in the heap is not used, so the length is always one greater than the number of elements. .. function:: void _mpoly_heap_insert1(mpoly_heap1_s * heap, ulong exp, void * x, slong * next_loc, slong * heap_len, ulong maskhi) As per ``_mpoly_heap_insert`` except that ``N = 1``, and ``maskhi = cmpmask[0]``. .. function:: void * _mpoly_heap_pop(mpoly_heap_s * heap, slong * heap_len, slong N, const ulong * cmpmask) Pop the head of the heap. It is cast to a ``void *``. A pointer to the current heap length must be passed in via ``heap_len``. This will be updated by the function. Note that the index 0 position in the heap is not used, so the length is always one greater than the number of elements. The ``maskhi`` and ``masklo`` values are zero except for degrevlex ordering, where they are as per the monomial comparison operations above. .. function:: void * _mpoly_heap_pop1(mpoly_heap1_s * heap, slong * heap_len, ulong maskhi) As per ``_mpoly_heap_pop1`` except that ``N = 1``, and ``maskhi = cmpmask[0]``. flint-3.1.3/doc/source/nf.rst000066400000000000000000000010401461254215100160300ustar00rootroot00000000000000.. _nf: **nf.h** -- number fields ======================================================================================== .. type:: nf_struct .. type:: nf_t Represents a number field. .. function:: void nf_init(nf_t nf, const fmpq_poly_t pol) Perform basic initialisation of a number field (for element arithmetic) given a defining polynomial over `\mathbb{Q}`. .. function:: void nf_clear(nf_t nf) Release resources used by a number field object. The object will need initialisation again before it can be used. flint-3.1.3/doc/source/nf_elem.rst000066400000000000000000000362551461254215100170520ustar00rootroot00000000000000.. _nf_elem: **nf_elem.h** -- number field elements ======================================================================================== Authors: * William Hart Initialisation -------------------------------------------------------------------------------- .. type:: nf_elem_struct .. type:: nf_elem_t Represents a number field element. .. function:: void nf_elem_init(nf_elem_t a, const nf_t nf) Initialise a number field element to belong to the given number field ``nf``. The element is set to zero. .. function:: void nf_elem_clear(nf_elem_t a, const nf_t nf) Clear resources allocated by the given number field element in the given number field. .. function:: void nf_elem_randtest(nf_elem_t a, flint_rand_t state, mp_bitcnt_t bits, const nf_t nf) Generate a random number field element `a` in the number field ``nf`` whose coefficients have up to the given number of bits. .. function:: void nf_elem_canonicalise(nf_elem_t a, const nf_t nf) Canonicalise a number field element, i.e. reduce numerator and denominator to lowest terms. If the numerator is `0`, set the denominator to `1`. .. function:: void _nf_elem_reduce(nf_elem_t a, const nf_t nf) Reduce a number field element modulo the defining polynomial. This is used with functions such as ``nf_elem_mul_red`` which allow reduction to be delayed. Does not canonicalise. .. function:: void nf_elem_reduce(nf_elem_t a, const nf_t nf) Reduce a number field element modulo the defining polynomial. This is used with functions such as ``nf_elem_mul_red`` which allow reduction to be delayed. .. function:: int _nf_elem_invertible_check(nf_elem_t a, const nf_t nf) Whilst the defining polynomial for a number field should by definition be irreducible, it is not enforced. Thus in test code, it is convenient to be able to check that a given number field element is invertible modulo the defining polynomial of the number field. This function does precisely this. If `a` is invertible modulo the defining polynomial of ``nf`` the value `1` is returned, otherwise `0` is returned. The function is only intended to be used in test code. Conversion -------------------------------------------------------------------------------- .. function:: void nf_elem_set_fmpz_mat_row(nf_elem_t b, const fmpz_mat_t M, const slong i, fmpz_t den, const nf_t nf) Set `b` to the element specified by row `i` of the matrix `M` and with the given denominator `d`. Column `0` of the matrix corresponds to the constant coefficient of the number field element. .. function:: void nf_elem_get_fmpz_mat_row(fmpz_mat_t M, const slong i, fmpz_t den, const nf_elem_t b, const nf_t nf) Set the row `i` of the matrix `M` to the coefficients of the numerator of the element `b` and `d` to the denominator of `b`. Column `0` of the matrix corresponds to the constant coefficient of the number field element. .. function:: void nf_elem_set_fmpq_poly(nf_elem_t a, const fmpq_poly_t pol, const nf_t nf) Set `a` to the element corresponding to the polynomial ``pol``. .. function:: void nf_elem_get_fmpq_poly(fmpq_poly_t pol, const nf_elem_t a, const nf_t nf) Set ``pol`` to a polynomial corresponding to `a`, reduced modulo the defining polynomial of ``nf``. .. function:: void nf_elem_get_nmod_poly_den(nmod_poly_t pol, const nf_elem_t a, const nf_t nf, int den) Set ``pol`` to the reduction of the polynomial corresponding to the numerator of `a`. If ``den == 1``, the result is multiplied by the inverse of the denominator of `a`. In this case it is assumed that the reduction of the denominator of `a` is invertible. .. function:: void nf_elem_get_nmod_poly(nmod_poly_t pol, const nf_elem_t a, const nf_t nf) Set ``pol`` to the reduction of the polynomial corresponding to the numerator of `a`. The result is multiplied by the inverse of the denominator of `a`. It is assumed that the reduction of the denominator of `a` is invertible. .. function:: void nf_elem_get_fmpz_mod_poly_den(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, int den, const fmpz_mod_ctx_t ctx) Set ``pol`` to the reduction of the polynomial corresponding to the numerator of `a`. If ``den == 1``, the result is multiplied by the inverse of the denominator of `a`. In this case it is assumed that the reduction of the denominator of `a` is invertible. .. function:: void nf_elem_get_fmpz_mod_poly(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, const fmpz_mod_ctx_t ctx) Set ``pol`` to the reduction of the polynomial corresponding to the numerator of `a`. The result is multiplied by the inverse of the denominator of `a`. It is assumed that the reduction of the denominator of `a` is invertible. Basic manipulation -------------------------------------------------------------------------------- .. function:: void nf_elem_set_den(nf_elem_t b, fmpz_t d, const nf_t nf) Set the denominator of the ``nf_elem_t b`` to the given integer `d`. Assumes `d > 0`. .. function:: void nf_elem_get_den(fmpz_t d, const nf_elem_t b, const nf_t nf) Set `d` to the denominator of the ``nf_elem_t b``. .. function:: void _nf_elem_set_coeff_num_fmpz(nf_elem_t a, slong i, const fmpz_t d, const nf_t nf) Set the `i`-th coefficient of the denominator of `a` to the given integer `d`. Comparison -------------------------------------------------------------------------------- .. function:: int _nf_elem_equal(const nf_elem_t a, const nf_elem_t b, const nf_t nf) Return `1` if the given number field elements are equal in the given number field ``nf``. This function does \emph{not} assume `a` and `b` are canonicalised. .. function:: int nf_elem_equal(const nf_elem_t a, const nf_elem_t b, const nf_t nf) Return `1` if the given number field elements are equal in the given number field ``nf``. This function assumes `a` and `b` \emph{are} canonicalised. .. function:: int nf_elem_is_zero(const nf_elem_t a, const nf_t nf) Return `1` if the given number field element is equal to zero, otherwise return `0`. .. function:: int nf_elem_is_one(const nf_elem_t a, const nf_t nf) Return `1` if the given number field element is equal to one, otherwise return `0`. I/O -------------------------------------------------------------------------------- .. function:: void nf_elem_print_pretty(const nf_elem_t a, const nf_t nf, const char * var) Print the given number field element to ``stdout`` using the null-terminated string ``var`` not equal to ``"\0"`` as the name of the primitive element. Arithmetic -------------------------------------------------------------------------------- .. function:: void nf_elem_zero(nf_elem_t a, const nf_t nf) Set the given number field element to zero. .. function:: void nf_elem_one(nf_elem_t a, const nf_t nf) Set the given number field element to one. .. function:: void nf_elem_set(nf_elem_t a, const nf_elem_t b, const nf_t nf) Set the number field element `a` to equal the number field element `b`, i.e. set `a = b`. .. function:: void nf_elem_neg(nf_elem_t a, const nf_elem_t b, const nf_t nf) Set the number field element `a` to minus the number field element `b`, i.e. set `a = -b`. .. function:: void nf_elem_swap(nf_elem_t a, nf_elem_t b, const nf_t nf) Efficiently swap the two number field elements `a` and `b`. .. function:: void nf_elem_mul_gen(nf_elem_t a, const nf_elem_t b, const nf_t nf) Multiply the element `b` with the generator of the number field. .. function:: void _nf_elem_add(nf_elem_t r, const nf_elem_t a, const nf_elem_t b, const nf_t nf) Add two elements of a number field ``nf``, i.e. set `r = a + b`. Canonicalisation is not performed. .. function:: void nf_elem_add(nf_elem_t r, const nf_elem_t a, const nf_elem_t b, const nf_t nf) Add two elements of a number field ``nf``, i.e. set `r = a + b`. .. function:: void _nf_elem_sub(nf_elem_t r, const nf_elem_t a, const nf_elem_t b, const nf_t nf) Subtract two elements of a number field ``nf``, i.e. set `r = a - b`. Canonicalisation is not performed. .. function:: void nf_elem_sub(nf_elem_t r, const nf_elem_t a, const nf_elem_t b, const nf_t nf) Subtract two elements of a number field ``nf``, i.e. set `r = a - b`. .. function:: void _nf_elem_mul(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) Multiply two elements of a number field ``nf``, i.e. set `r = a * b`. Does not canonicalise. Aliasing of inputs with output is not supported. .. function:: void _nf_elem_mul_red(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int red) As per ``_nf_elem_mul``, but reduction modulo the defining polynomial of the number field is only carried out if ``red == 1``. Assumes both inputs are reduced. .. function:: void nf_elem_mul(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) Multiply two elements of a number field ``nf``, i.e. set `r = a * b`. .. function:: void nf_elem_mul_red(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int red) As per ``nf_elem_mul``, but reduction modulo the defining polynomial of the number field is only carried out if ``red == 1``. Assumes both inputs are reduced. .. function:: void _nf_elem_inv(nf_elem_t r, const nf_elem_t a, const nf_t nf) Invert an element of a number field ``nf``, i.e. set `r = a^{-1}`. Aliasing of the input with the output is not supported. .. function:: void nf_elem_inv(nf_elem_t r, const nf_elem_t a, const nf_t nf) Invert an element of a number field ``nf``, i.e. set `r = a^{-1}`. .. function:: void _nf_elem_div(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) Set `a` to `b/c` in the given number field. Aliasing of `a` and `b` is not permitted. .. function:: void nf_elem_div(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) Set `a` to `b/c` in the given number field. .. function:: void _nf_elem_pow(nf_elem_t res, const nf_elem_t a, ulong e, const nf_t nf) Set ``res`` to `a^e` using left-to-right binary exponentiation as described on p. 461 of [Knu1997]_. Assumes that `a \neq 0` and `e > 1`. Does not support aliasing. .. function:: void nf_elem_pow(nf_elem_t res, const nf_elem_t a, ulong e, const nf_t nf) Set ``res`` = ``a^e`` using the binary exponentiation algorithm. If `e` is zero, returns one, so that in particular ``0^0 = 1``. .. function:: void _nf_elem_norm(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf) Set ``rnum, rden`` to the absolute norm of the given number field element `a`. .. function:: void nf_elem_norm(fmpq_t res, const nf_elem_t a, const nf_t nf) Set ``res`` to the absolute norm of the given number field element `a`. .. function:: void nf_elem_norm_div(fmpq_t res, const nf_elem_t a, const nf_t nf, const fmpz_t div, slong nbits) Set ``res`` to the absolute norm of the given number field element `a`, divided by ``div`` . Assumes the result to be an integer and having at most ``nbits`` bits. .. function:: void _nf_elem_norm_div(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf, const fmpz_t divisor, slong nbits) Set ``rnum, rden`` to the absolute norm of the given number field element `a`, divided by ``div`` . Assumes the result to be an integer and having at most ``nbits`` bits. .. function:: void _nf_elem_trace(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf) Set ``rnum, rden`` to the absolute trace of the given number field element `a`. .. function:: void nf_elem_trace(fmpq_t res, const nf_elem_t a, const nf_t nf) Set ``res`` to the absolute trace of the given number field element `a`. Representation matrix -------------------------------------------------------------------------------- .. function:: void nf_elem_rep_mat(fmpq_mat_t res, const nf_elem_t a, const nf_t nf) Set ``res`` to the matrix representing the multiplication with `a` with respect to the basis `1, a, \dotsc, a^{d - 1}`, where `a` is the generator of the number field of `d` is its degree. .. function:: void nf_elem_rep_mat_fmpz_mat_den(fmpz_mat_t res, fmpz_t den, const nf_elem_t a, const nf_t nf) Return a tuple `M, d` such that `M/d` is the matrix representing the multiplication with `a` with respect to the basis `1, a, \dotsc, a^{d - 1}`, where `a` is the generator of the number field of `d` is its degree. The integral matrix `M` is primitive. Modular reduction -------------------------------------------------------------------------------- .. function:: void nf_elem_mod_fmpz_den(nf_elem_t z, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int den) If ``den == 0``, return an element `z` with denominator `1`, such that the coefficients of `z - da` are divisble by ``mod``, where `d` is the denominator of `a`. The coefficients of `z` are reduced modulo ``mod``. If ``den == 1``, return an element `z`, such that `z - a` has denominator `1` and the coefficients of `z - a` are divisible by ``mod``. The coefficients of `z` are reduced modulo `\mathtt{mod} \cdot d`, where `d` is the denominator of `a`. Reduction takes place with respect to the positive residue system. .. function:: void nf_elem_smod_fmpz_den(nf_elem_t z, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int den) If ``den == 0``, return an element `z` with denominator `1`, such that the coefficients of `z - da` are divisble by ``mod``, where `d` is the denominator of `a`. The coefficients of `z` are reduced modulo ``mod``. If ``den == 1``, return an element `z`, such that `z - a` has denominator `1` and the coefficients of `z - a` are divisible by ``mod``. The coefficients of `z` are reduced modulo `\mathtt{mod} \cdot d`, where `d` is the denominator of `a`. Reduction takes place with respect to the symmetric residue system. .. function:: void nf_elem_mod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) Return an element `z` such that `z - a` has denominator `1` and the coefficients of `z - a` are divisible by ``mod``. The coefficients of `z` are reduced modulo `\mathtt{mod} \cdot d`, where `d` is the denominator of `b`. Reduction takes place with respect to the positive residue system. .. function:: void nf_elem_smod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) Return an element `z` such that `z - a` has denominator `1` and the coefficients of `z - a` are divisible by ``mod``. The coefficients of `z` are reduced modulo `\mathtt{mod} \cdot d`, where `d` is the denominator of `b`. Reduction takes place with respect to the symmetric residue system. .. function:: void nf_elem_coprime_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) Return an element `z` such that the denominator of `z - a` is coprime to ``mod``. Reduction takes place with respect to the positive residue system. .. function:: void nf_elem_coprime_den_signed(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) Return an element `z` such that the denominator of `z - a` is coprime to ``mod``. Reduction takes place with respect to the symmetric residue system. flint-3.1.3/doc/source/nmod.rst000066400000000000000000000144321461254215100163730ustar00rootroot00000000000000.. _nmod: **nmod.h** -- integers mod n (word-size n) =============================================================================== Modular reduction and arithmetic -------------------------------------------------------------------------------- .. function:: void nmod_init(nmod_t * mod, mp_limb_t n) Initialises the given ``nmod_t`` structure for reduction modulo `n` with a precomputed inverse. .. macro:: NMOD_BITS(mod) Macro giving the number of bits in ``mod.n``. .. macro:: NMOD_CAN_USE_SHOUP(mod) Macro returning whether Shoup's algorithm can be used for preconditioned multiplication mod ``mod.n``. .. macro:: NMOD_RED2(r, a_hi, a_lo, mod) Macro to set `r` to `a` reduced modulo ``mod.n``, where `a` consists of two limbs ``(a_hi, a_lo)``. The ``mod`` parameter must be a valid ``nmod_t`` structure. It is assumed that ``a_hi`` is already reduced modulo ``mod.n``. .. macro:: NMOD_RED(r, a, mod) Macro to set `r` to `a` reduced modulo ``mod.n``. The ``mod`` parameter must be a valid ``nmod_t`` structure. .. macro:: NMOD2_RED2(r, a_hi, a_lo, mod) Macro to set `r` to `a` reduced modulo ``mod.n``, where `a` consists of two limbs ``(a_hi, a_lo)``. The ``mod`` parameter must be a valid ``nmod_t`` structure. No assumptions are made about ``a_hi``. .. macro:: NMOD_RED3(r, a_hi, a_me, a_lo, mod) Macro to set `r` to `a` reduced modulo ``mod.n``, where `a` consists of three limbs ``(a_hi, a_me, a_lo)``. The ``mod`` parameter must be a valid ``nmod_t`` structure. It is assumed that ``a_hi`` is already reduced modulo ``mod.n``. .. macro:: NMOD_MUL_PRENORM(res, a, b, mod) Macro to set `r` to `ab` modulo ``mod.n``. The ``mod`` parameter must be a valid ``nmod_t`` structure. It is assumed that `a`, `b` are already reduced modulo ``mod.n`` and that either `a` or `b` is prenormalised by left-shifting by ``mod.norm``. .. macro:: NMOD_MUL_FULLWORD(res, a, b, mod) Macro to set `r` to `ab` modulo ``mod.n``. The ``mod`` parameter must be a valid ``nmod_t`` structure. It is assumed that `a`, `b` are already reduced modulo ``mod.n`` and that ``mod.n`` is exactly ``FLINT_BITS`` bits large. .. macro:: NMOD_ADDMUL(r, a, b, mod) Macro to set `r` to `r + ab` reduced modulo ``mod.n``. The ``mod`` parameter must be a valid ``nmod_t`` structure. It is assumed that `r`, `a`, `b` are already reduced modulo ``mod.n``. .. function:: mp_limb_t _nmod_add(mp_limb_t a, mp_limb_t b, nmod_t mod) Returns `a + b` modulo ``mod.n``. It is assumed that ``mod`` is no more than ``FLINT_BITS - 1`` bits. It is assumed that `a` and `b` are already reduced modulo ``mod.n``. .. function:: mp_limb_t nmod_add(mp_limb_t a, mp_limb_t b, nmod_t mod) Returns `a + b` modulo ``mod.n``. No assumptions are made about ``mod.n``. It is assumed that `a` and `b` are already reduced modulo ``mod.n``. .. function:: mp_limb_t _nmod_sub(mp_limb_t a, mp_limb_t b, nmod_t mod) Returns `a - b` modulo ``mod.n``. It is assumed that ``mod`` is no more than ``FLINT_BITS - 1`` bits. It is assumed that `a` and `b` are already reduced modulo ``mod.n``. .. function:: mp_limb_t nmod_sub(mp_limb_t a, mp_limb_t b, nmod_t mod) Returns `a - b` modulo ``mod.n``. No assumptions are made about ``mod.n``. It is assumed that `a` and `b` are already reduced modulo ``mod.n``. .. function:: mp_limb_t nmod_neg(mp_limb_t a, nmod_t mod) Returns `-a` modulo ``mod.n``. It is assumed that `a` is already reduced modulo ``mod.n``, but no assumptions are made about the latter. .. function:: mp_limb_t nmod_mul(mp_limb_t a, mp_limb_t b, nmod_t mod) Returns `ab` modulo ``mod.n``. No assumptions are made about ``mod.n``. It is assumed that `a` and `b` are already reduced modulo ``mod.n``. .. function:: mp_limb_t _nmod_mul_fullword(mp_limb_t a, mp_limb_t b, nmod_t mod) Returns `ab` modulo ``mod.n``. Requires that ``mod.n`` is exactly ``FLINT_BITS`` large. It is assumed that `a` and `b` are already reduced modulo ``mod.n``. .. function:: mp_limb_t nmod_inv(mp_limb_t a, nmod_t mod) Returns `a^{-1}` modulo ``mod.n``. The inverse is assumed to exist. .. function:: mp_limb_t nmod_div(mp_limb_t a, mp_limb_t b, nmod_t mod) Returns `ab^{-1}` modulo ``mod.n``. The inverse of `b` is assumed to exist. It is assumed that `a` is already reduced modulo ``mod.n``. .. function:: int nmod_divides(mp_limb_t * a, mp_limb_t b, mp_limb_t c, nmod_t mod) If `a\cdot c = b \mod n` has a solution for `a` return `1` and set `a` to such a solution. Otherwise return `0` and leave `a` undefined. .. function:: mp_limb_t nmod_pow_ui(mp_limb_t a, ulong e, nmod_t mod) Returns `a^e` modulo ``mod.n``. No assumptions are made about ``mod.n``. It is assumed that `a` is already reduced modulo ``mod.n``. .. function:: mp_limb_t nmod_pow_fmpz(mp_limb_t a, const fmpz_t e, nmod_t mod) Returns `a^e` modulo ``mod.n``. No assumptions are made about ``mod.n``. It is assumed that `a` is already reduced modulo ``mod.n`` and that `e` is not negative. Discrete Logarithms via Pohlig-Hellman -------------------------------------------------------------------------------- .. function:: void nmod_discrete_log_pohlig_hellman_init(nmod_discrete_log_pohlig_hellman_t L) Initialize ``L``. Upon initialization ``L`` is not ready for computation. .. function:: void nmod_discrete_log_pohlig_hellman_clear(nmod_discrete_log_pohlig_hellman_t L) Free any space used by ``L``. .. function:: double nmod_discrete_log_pohlig_hellman_precompute_prime(nmod_discrete_log_pohlig_hellman_t L, mp_limb_t p) Configure ``L`` for discrete logarithms modulo ``p`` to an internally chosen base. It is assumed that ``p`` is prime. The return is an estimate on the number of multiplications needed for one run. .. function:: mp_limb_t nmod_discrete_log_pohlig_hellman_primitive_root(const nmod_discrete_log_pohlig_hellman_t L) Return the internally stored base. .. function:: ulong nmod_discrete_log_pohlig_hellman_run(const nmod_discrete_log_pohlig_hellman_t L, mp_limb_t y) Return the logarithm of ``y`` with respect to the internally stored base. ``y`` is expected to be reduced modulo the ``p``. The function is undefined if the logarithm does not exist. flint-3.1.3/doc/source/nmod_mat.rst000066400000000000000000000707701461254215100172430ustar00rootroot00000000000000.. _nmod-mat: **nmod_mat.h** -- matrices over integers mod n (word-size n) =============================================================================== An :type:`nmod_mat_t` represents a matrix of integers modulo `n`, for any non-zero modulus `n` that fits in a single limb, up to `2^{32}-1` or `2^{64}-1`. The :type:`nmod_mat_t` type is defined as an array of :type:`nmod_mat_struct`'s of length one. This permits passing parameters of type :type:`nmod_mat_t` by reference. An :type:`nmod_mat_t` internally consists of a single array of ``mp_limb_t``'s, representing a dense matrix in row-major order. This array is only directly indexed during memory allocation and deallocation. A separate array holds pointers to the start of each row, and is used for all indexing. This allows the rows of a matrix to be permuted quickly by swapping pointers. Matrices having zero rows or columns are allowed. The shape of a matrix is fixed upon initialisation. The user is assumed to provide input and output variables whose dimensions are compatible with the given operation. It is assumed that all matrices passed to a function have the same modulus. The modulus is assumed to be a prime number in functions that perform some kind of division, solving, or Gaussian elimination (including computation of rank and determinant), but can be composite in functions that only perform basic manipulation and ring operations (e.g. transpose and matrix multiplication). The user can manipulate matrix entries directly, but must assume responsibility for normalising all values to the range `[0, n)`. Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_mat_struct .. type:: nmod_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void nmod_mat_init(nmod_mat_t mat, slong rows, slong cols, mp_limb_t n) Initialises ``mat`` to a ``rows``-by-``cols`` matrix with coefficients modulo `n`, where `n` can be any nonzero integer that fits in a limb. All elements are set to zero. .. function:: void nmod_mat_init_set(nmod_mat_t mat, const nmod_mat_t src) Initialises ``mat`` and sets its dimensions, modulus and elements to those of ``src``. .. function:: void nmod_mat_clear(nmod_mat_t mat) Clears the matrix and releases any memory it used. The matrix cannot be used again until it is initialised. This function must be called exactly once when finished using an ``nmod_mat_t`` object. .. function:: void nmod_mat_set(nmod_mat_t mat, const nmod_mat_t src) Sets ``mat`` to a copy of ``src``. It is assumed that ``mat`` and ``src`` have identical dimensions. .. function:: void nmod_mat_swap(nmod_mat_t mat1, nmod_mat_t mat2) Exchanges ``mat1`` and ``mat2``. .. function:: void nmod_mat_swap_entrywise(nmod_mat_t mat1, nmod_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. Basic properties and manipulation -------------------------------------------------------------------------------- .. macro:: nmod_mat_entry(mat, i, j) Directly accesses the entry in ``mat`` in row `i` and column `j`, indexed from zero. No bounds checking is performed. This macro can be used both for reading and writing coefficients. .. function:: mp_limb_t nmod_mat_get_entry(const nmod_mat_t mat, slong i, slong j) Get the entry at row `i` and column `j` of the matrix ``mat``. .. function:: mp_limb_t * nmod_mat_entry_ptr(const nmod_mat_t mat, slong i, slong j) Return a pointer to the entry at row `i` and column `j` of the matrix ``mat``. .. function:: void nmod_mat_set_entry(nmod_mat_t mat, slong i, slong j, mp_limb_t x) Set the entry at row `i` and column `j` of the matrix ``mat`` to ``x``. .. function:: slong nmod_mat_nrows(const nmod_mat_t mat) Returns the number of rows in ``mat``. .. function:: slong nmod_mat_ncols(const nmod_mat_t mat) Returns the number of columns in ``mat``. .. function:: void nmod_mat_zero(nmod_mat_t mat) Sets all entries of the matrix ``mat`` to zero. .. function:: int nmod_mat_is_zero(const nmod_mat_t mat) Returns `1` if all entries of the matrix ``mat`` are zero. Window -------------------------------------------------------------------------------- .. function:: void nmod_mat_window_init(nmod_mat_t window, const nmod_mat_t mat, slong r1, slong c1, slong r2, slong c2) Initializes the matrix ``window`` to be an ``r2 - r1`` by ``c2 - c1`` submatrix of ``mat`` whose ``(0,0)`` entry is the ``(r1, c1)`` entry of ``mat``. The memory for the elements of ``window`` is shared with ``mat``. .. function:: void nmod_mat_window_clear(nmod_mat_t window) Clears the matrix ``window`` and releases any memory that it uses. Note that the memory to the underlying matrix that ``window`` points to is not freed. Concatenate -------------------------------------------------------------------------------- .. function:: void nmod_mat_concat_vertical(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2) Sets ``res`` to vertical concatenation of (`mat1`, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `k \times n`, ``res`` : `(m + k) \times n`. .. function:: void nmod_mat_concat_horizontal(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2) Sets ``res`` to horizontal concatenation of (``mat1``, ``mat2``) in that order. Matrix dimensions : ``mat1`` : `m \times n`, ``mat2`` : `m \times k`, ``res`` : `m \times (n + k)`. Printing -------------------------------------------------------------------------------- .. function:: void nmod_mat_print_pretty(const nmod_mat_t mat) Pretty-prints ``mat`` to ``stdout``. A header is printed followed by the rows enclosed in brackets. Each column is right-aligned to the width of the modulus written in decimal, and the columns are separated by spaces. For example:: <2 x 3 integer matrix mod 2903> [ 0 0 2607] [ 622 0 0] .. function:: int nmod_mat_fprint_pretty(FILE * file, const nmod_mat_t mat) Same as ``nmod_mat_print_pretty`` but printing to ``file``. .. function:: int nmod_mat_print(const nmod_mat_t mat) Currently, same as ``nmod_mat_print_pretty``. .. function:: int nmod_mat_fprint(FILE * f, const nmod_mat_t mat) Currently, same as ``nmod_mat_fprint_pretty``. Random matrix generation -------------------------------------------------------------------------------- .. function:: void nmod_mat_randtest(nmod_mat_t mat, flint_rand_t state) Sets the elements to a random matrix with entries between `0` and `m-1` inclusive, where `m` is the modulus of ``mat``. A sparse matrix is generated with increased probability. .. function:: void nmod_mat_randfull(nmod_mat_t mat, flint_rand_t state) Sets the element to random numbers likely to be close to the modulus of the matrix. This is used to test potential overflow-related bugs. .. function:: int nmod_mat_randpermdiag(nmod_mat_t mat, flint_rand_t state, mp_srcptr diag, slong n) Sets ``mat`` to a random permutation of the diagonal matrix with `n` leading entries given by the vector ``diag``. It is assumed that the main diagonal of ``mat`` has room for at least `n` entries. Returns `0` or `1`, depending on whether the permutation is even or odd respectively. .. function:: void nmod_mat_randrank(nmod_mat_t mat, flint_rand_t state, slong rank) Sets ``mat`` to a random sparse matrix with the given rank, having exactly as many non-zero elements as the rank, with the non-zero elements being uniformly random integers between `0` and `m-1` inclusive, where `m` is the modulus of ``mat``. The matrix can be transformed into a dense matrix with unchanged rank by subsequently calling :func:`nmod_mat_randops`. .. function:: void nmod_mat_randops(nmod_mat_t mat, flint_rand_t state, slong count) Randomises ``mat`` by performing elementary row or column operations. More precisely, at most ``count`` random additions or subtractions of distinct rows and columns will be performed. This leaves the rank (and for square matrices, determinant) unchanged. .. function:: void nmod_mat_randtril(nmod_mat_t mat, flint_rand_t state, int unit) Sets ``mat`` to a random lower triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. .. function:: void nmod_mat_randtriu(nmod_mat_t mat, flint_rand_t state, int unit) Sets ``mat`` to a random upper triangular matrix. If ``unit`` is 1, it will have ones on the main diagonal, otherwise it will have random nonzero entries on the main diagonal. Comparison -------------------------------------------------------------------------------- .. function:: int nmod_mat_equal(const nmod_mat_t mat1, const nmod_mat_t mat2) Returns nonzero if ``mat1`` and ``mat2`` have the same dimensions and elements, and zero otherwise. The moduli are ignored. .. function:: int nmod_mat_is_zero_row(const nmod_mat_t mat, slong i) Returns a non-zero value if row `i` of ``mat`` is zero. Transposition and permutations -------------------------------------------------------------------------------- .. function:: void nmod_mat_transpose(nmod_mat_t B, const nmod_mat_t A) Sets `B` to the transpose of `A`. Dimensions must be compatible. `B` and `A` may be the same object if and only if the matrix is square. .. function:: void nmod_mat_swap_rows(nmod_mat_t mat, slong * perm, slong r, slong s) Swaps rows ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void nmod_mat_swap_cols(nmod_mat_t mat, slong * perm, slong r, slong s) Swaps columns ``r`` and ``s`` of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: void nmod_mat_invert_rows(nmod_mat_t mat, slong * perm) Swaps rows ``i`` and ``r - i`` of ``mat`` for ``0 <= i < r/2``, where ``r`` is the number of rows of ``mat``. If ``perm`` is non-``NULL``, the permutation of the rows will also be applied to ``perm``. .. function:: void nmod_mat_invert_cols(nmod_mat_t mat, slong * perm) Swaps columns ``i`` and ``c - i`` of ``mat`` for ``0 <= i < c/2``, where ``c`` is the number of columns of ``mat``. If ``perm`` is non-``NULL``, the permutation of the columns will also be applied to ``perm``. .. function:: void nmod_mat_permute_rows(nmod_mat_t mat, const slong * perm_act, slong * perm_store) Permutes rows of the matrix ``mat`` according to permutation ``perm_act`` and, if ``perm_store`` is not ``NULL``, apply the same permutation to it. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void nmod_mat_add(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Computes `C = A + B`. Dimensions must be identical. .. function:: void nmod_mat_sub(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Computes `C = A - B`. Dimensions must be identical. .. function:: void nmod_mat_neg(nmod_mat_t A, const nmod_mat_t B) Sets `B = -A`. Dimensions must be identical. Matrix-scalar arithmetic -------------------------------------------------------------------------------- .. function:: void nmod_mat_scalar_mul(nmod_mat_t B, const nmod_mat_t A, mp_limb_t c) Sets `B = cA`, where the scalar `c` is assumed to be reduced modulo the modulus. Dimensions of `A` and `B` must be identical. .. function:: void nmod_mat_scalar_addmul_ui(nmod_mat_t dest, const nmod_mat_t X, const nmod_mat_t Y, const mp_limb_t b) Sets `dest = X + bY`, where the scalar `b` is assumed to be reduced modulo the modulus. Dimensions of dest, X and Y must be identical. dest can be aliased with X or Y. .. function:: void nmod_mat_scalar_mul_fmpz(nmod_mat_t res, const nmod_mat_t M, const fmpz_t c) Sets `B = cA`, where the scalar `c` is of type ``fmpz_t``. Dimensions of `A` and `B` must be identical. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void nmod_mat_mul(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. Aliasing is allowed. This function automatically chooses between classical and Strassen multiplication. .. function:: void _nmod_mat_mul_classical_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op) Sets ``D = A*B op C`` where ``op`` is ``+1`` for addition, ``-1`` for subtraction and ``0`` to ignore ``C``. .. function:: void nmod_mat_mul_classical(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses classical matrix multiplication, creating a temporary transposed copy of `B` to improve memory locality if the matrices are large enough, and packing several entries of `B` into each word if the modulus is very small. .. function:: void _nmod_mat_mul_classical_threaded_pool_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op, thread_pool_handle * threads, slong num_threads) Multithreaded version of ``_nmod_mat_mul_classical``. .. function:: void _nmod_mat_mul_classical_threaded_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op) Multithreaded version of ``_nmod_mat_mul_classical``. .. function:: void nmod_mat_mul_classical_threaded(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Multithreaded version of ``nmod_mat_mul_classical``. .. function:: void nmod_mat_mul_strassen(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Sets `C = AB`. Dimensions must be compatible for matrix multiplication. `C` is not allowed to be aliased with `A` or `B`. Uses Strassen multiplication (the Strassen-Winograd variant). .. function:: int nmod_mat_mul_blas(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Tries to set `C = AB` using BLAS and returns `1` for success and `0` for failure. Dimensions must be compatible for matrix multiplication. .. function:: void nmod_mat_addmul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Sets `D = C + AB`. `C` and `D` may be aliased with each other but not with `A` or `B`. Automatically selects between classical and Strassen multiplication. .. function:: void nmod_mat_submul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) Sets `D = C + AB`. `C` and `D` may be aliased with each other but not with `A` or `B`. .. function:: void nmod_mat_mul_nmod_vec(mp_limb_t * c, const nmod_mat_t A, const mp_limb_t * b, slong blen) void nmod_mat_mul_nmod_vec_ptr(mp_limb_t * const * c, const nmod_mat_t A, const mp_limb_t * const * b, slong blen) Compute a matrix-vector product of ``A`` and ``(b, blen)`` and store the result in ``c``. The vector ``(b, blen)`` is either truncated or zero-extended to the number of columns of ``A``. The number entries written to ``c`` is always equal to the number of rows of ``A``. .. function:: void nmod_mat_nmod_vec_mul(mp_limb_t * c, const mp_limb_t * a, slong alen, const nmod_mat_t B) void nmod_mat_nmod_vec_mul_ptr(mp_limb_t * const * c, const mp_limb_t * const * a, slong alen, const nmod_mat_t B) Compute a vector-matrix product of ``(a, alen)`` and ``B`` and and store the result in ``c``. The vector ``(a, alen)`` is either truncated or zero-extended to the number of rows of ``B``. The number entries written to ``c`` is always equal to the number of columns of ``B``. Matrix Exponentiation -------------------------------------------------------------------------------- .. function:: void _nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow) Sets `dest = mat^{pow}`. ``dest`` and ``mat`` cannot be aliased. Implements exponentiation by squaring. .. function:: void nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow) Sets `dest = mat^{pow}`. ``dest`` and ``mat`` may be aliased. Implements exponentiation by squaring. Trace -------------------------------------------------------------------------------- .. function:: mp_limb_t nmod_mat_trace(const nmod_mat_t mat) Computes the trace of the matrix, i.e. the sum of the entries on the main diagonal. The matrix is required to be square. Determinant and rank -------------------------------------------------------------------------------- .. function:: mp_limb_t nmod_mat_det_howell(const nmod_mat_t A) Returns the determinant of `A`. .. function:: mp_limb_t nmod_mat_det(const nmod_mat_t A) Returns the determinant of `A`. .. function:: slong nmod_mat_rank(const nmod_mat_t A) Returns the rank of `A`. The modulus of `A` must be a prime number. Inverse -------------------------------------------------------------------------------- .. function:: int nmod_mat_inv(nmod_mat_t B, const nmod_mat_t A) Sets `B = A^{-1}` and returns `1` if `A` is invertible. If `A` is singular, returns `0` and sets the elements of `B` to undefined values. `A` and `B` must be square matrices with the same dimensions and modulus. The modulus must be prime. Triangular solving -------------------------------------------------------------------------------- .. function:: void nmod_mat_solve_tril(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void nmod_mat_solve_tril_classical(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void nmod_mat_solve_tril_recursive(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit) Sets `X = L^{-1} B` where `L` is a full rank lower triangular square matrix. If ``unit`` = 1, `L` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. .. function:: void nmod_mat_solve_triu(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Automatically chooses between the classical and recursive algorithms. .. function:: void nmod_mat_solve_triu_classical(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses forward substitution. .. function:: void nmod_mat_solve_triu_recursive(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit) Sets `X = U^{-1} B` where `U` is a full rank upper triangular square matrix. If ``unit`` = 1, `U` is assumed to have ones on its main diagonal, and the main diagonal will not be read. `X` and `B` are allowed to be the same matrix, but no other aliasing is allowed. Uses the block inversion formula .. math:: \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1} \begin{pmatrix} X \\ Y \end{pmatrix} = \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix} to reduce the problem to matrix multiplication and triangular solving of smaller systems. Nonsingular square solving -------------------------------------------------------------------------------- .. function:: int nmod_mat_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B) Solves the matrix-matrix equation `AX = B` over `\mathbb{Z} / p \mathbb{Z}` where `p` is the modulus of `X` which must be a prime number. `X`, `A`, and `B` should have the same moduli. Returns `1` if `A` has full rank; otherwise returns `0` and sets the elements of `X` to undefined values. The matrix `A` must be square. .. function:: int nmod_mat_can_solve_inner(slong * rank, slong * perm, slong * pivots, nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B) As for :func:`nmod_mat_can_solve` except that if `rank` is not `NULL` the value it points to will be set to the rank of `A`. If `perm` is not `NULL` then it must be a valid initialised permutation whose length is the number of rows of `A`. After the function call it will be set to the row permutation given by LU decomposition of `A`. If `pivots` is not `NULL` then it must an initialised vector. Only the first `*rank` of these will be set by the function call. They are set to the columns of the pivots chosen by the LU decomposition of `A`. .. function:: int nmod_mat_can_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B) Solves the matrix-matrix equation `AX = B` over `\mathbb{Z} / p \mathbb{Z}` where `p` is the modulus of `X` which must be a prime number. `X`, `A`, and `B` should have the same moduli. Returns `1` if a solution exists; otherwise returns `0` and sets the elements of `X` to zero. If more than one solution exists, one of the valid solutions is given. There are no restrictions on the shape of `A` and it may be singular. .. function:: int nmod_mat_solve_vec(mp_ptr x, const nmod_mat_t A, mp_srcptr b) Solves the matrix-vector equation `Ax = b` over `\mathbb{Z} / p \mathbb{Z}` where `p` is the modulus of `A` which must be a prime number. Returns `1` if `A` has full rank; otherwise returns `0` and sets the elements of `x` to undefined values. LU decomposition -------------------------------------------------------------------------------- .. function:: slong nmod_mat_lu(slong * P, nmod_mat_t A, int rank_check) slong nmod_mat_lu_classical(slong * P, nmod_mat_t A, int rank_check) slong nmod_mat_lu_classical_delayed(slong * P, nmod_mat_t A, int rank_check) slong nmod_mat_lu_recursive(slong * P, nmod_mat_t A, int rank_check) Computes a generalised LU decomposition `LU = PA` of a given matrix `A`, returning the rank of `A`. If `A` is a nonsingular square matrix, it will be overwritten with a unit diagonal lower triangular matrix `L` and an upper triangular matrix `U` (the diagonal of `L` will not be stored explicitly). If `A` is an arbitrary matrix of rank `r`, `U` will be in row echelon form having `r` nonzero rows, and `L` will be lower triangular but truncated to `r` columns, having implicit ones on the `r` first entries of the main diagonal. All other entries will be zero. If a nonzero value for ``rank_check`` is passed, the function will abandon the output matrix in an undefined state and return 0 if `A` is detected to be rank-deficient. The *classical* version uses direct Gaussian elimination. The *classical_delayed* version also uses Gaussian elimination, but performs delayed modular reductions. The *recursive* version uses block recursive decomposition. The default function chooses an algorithm automatically. Reduced row echelon form -------------------------------------------------------------------------------- .. function:: slong nmod_mat_rref(nmod_mat_t A) Puts `A` in reduced row echelon form and returns the rank of `A`. The rref is computed by first obtaining an unreduced row echelon form via LU decomposition and then solving an additional triangular system. .. function:: slong nmod_mat_reduce_row(nmod_mat_t A, slong * P, slong * L, slong n) Reduce row n of the matrix `A`, assuming the prior rows are in Gauss form. However those rows may not be in order. The entry `i` of the array `P` is the row of `A` which has a pivot in the `i`-th column. If no such row exists, the entry of `P` will be `-1`. The function returns the column in which the `n`-th row has a pivot after reduction. This will always be chosen to be the first available column for a pivot from the left. This information is also updated in `P`. Entry `i` of the array `L` contains the number of possibly nonzero columns of `A` row `i`. This speeds up reduction in the case that `A` is chambered on the right. Otherwise the entries of `L` can all be set to the number of columns of `A`. We require the entries of `L` to be monotonic increasing. Nullspace -------------------------------------------------------------------------------- .. function:: slong nmod_mat_nullspace(nmod_mat_t X, const nmod_mat_t A) Computes the nullspace of `A` and returns the nullity. More precisely, this function sets `X` to a maximum rank matrix such that `AX = 0` and returns the rank of `X`. The columns of `X` will form a basis for the nullspace of `A`. `X` must have sufficient space to store all basis vectors in the nullspace. This function computes the reduced row echelon form and then reads off the basis vectors. Transforms -------------------------------------------------------------------------------- .. function:: void nmod_mat_similarity(nmod_mat_t M, slong r, ulong d) Applies a similarity transform to the `n\times n` matrix `M` in-place. If `P` is the `n\times n` identity matrix the zero entries of whose row `r` (`0`-indexed) have been replaced by `d`, this transform is equivalent to `M = P^{-1}MP`. Similarity transforms preserve the determinant, characteristic polynomial and minimal polynomial. The value `d` is required to be reduced modulo the modulus of the entries in the matrix. Characteristic polynomial -------------------------------------------------------------------------------- .. function:: void nmod_mat_charpoly_berkowitz(nmod_poly_t p, const nmod_mat_t M) void nmod_mat_charpoly_danilevsky(nmod_poly_t p, const nmod_mat_t M) void nmod_mat_charpoly(nmod_poly_t p, const nmod_mat_t M) Compute the characteristic polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. The *danilevsky* algorithm assumes that the modulus is prime. Minimal polynomial -------------------------------------------------------------------------------- .. function:: void nmod_mat_minpoly(nmod_poly_t p, const nmod_mat_t M) Compute the minimal polynomial `p` of the matrix `M`. The matrix is required to be square, otherwise an exception is raised. Strong echelon form and Howell form -------------------------------------------------------------------------------- .. function:: void nmod_mat_strong_echelon_form(nmod_mat_t A) Puts `A` into strong echelon form. The Howell form and the strong echelon form are equal up to permutation of the rows, see [FieHof2014]_ for a definition of the strong echelon form and the algorithm used here. Note that [FieHof2014]_ defines strong echelon form as a lower left normal form, while the implemented version returns an upper right normal form, agreeing with the definition of Howell form in [StoMul1998]_. `A` must have at least as many rows as columns. .. function:: slong nmod_mat_howell_form(nmod_mat_t A) Puts `A` into Howell form and returns the number of non-zero rows. For a definition of the Howell form see [StoMul1998]_. The Howell form is computed by first putting `A` into strong echelon form and then ordering the rows. `A` must have at least as many rows as columns. flint-3.1.3/doc/source/nmod_mpoly.rst000066400000000000000000001005501461254215100176100ustar00rootroot00000000000000.. _nmod-mpoly: **nmod_mpoly.h** -- multivariate polynomials over integers mod n (word-size n) =============================================================================== The exponents follow the ``mpoly`` interface. A coefficient may be referenced as a ``mp_limb_t *``. Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_mpoly_struct A structure holding a multivariate polynomial over the integers modulo *n* for word-sized *n*. .. type:: nmod_mpoly_t An array of length `1` of ``nmod_mpoly_struct``. .. type:: nmod_mpoly_ctx_struct Context structure representing the parent ring of an ``nmod_mpoly``. .. type:: nmod_mpoly_ctx_t An array of length `1` of ``nmod_mpoly_ctx_struct``. Context object -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_ctx_init(nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t n) Initialise a context object for a polynomial ring with the given number of variables and the given ordering. It will have coefficients modulo *n*. Setting `n = 0` will give undefined behavior. The possibilities for the ordering are ``ORD_LEX``, ``ORD_DEGLEX`` and ``ORD_DEGREVLEX``. .. function:: slong nmod_mpoly_ctx_nvars(const nmod_mpoly_ctx_t ctx) Return the number of variables used to initialize the context. .. function:: ordering_t nmod_mpoly_ctx_ord(const nmod_mpoly_ctx_t ctx) Return the ordering used to initialize the context. .. function:: mp_limb_t nmod_mpoly_ctx_modulus(const nmod_mpoly_ctx_t ctx) Return the modulus used to initialize the context. .. function:: void nmod_mpoly_ctx_clear(nmod_mpoly_ctx_t ctx) Release any space allocated by *ctx*. Memory management -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_init(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. .. function:: void nmod_mpoly_init2(nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and at least ``MPOLY_MIN_BITS`` bits for the exponent widths. .. function:: void nmod_mpoly_init3(nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) Initialise *A* for use with the given an initialised context object. Its value is set to zero. It is allocated with space for *alloc* terms and *bits* bits for the exponents. .. function:: void nmod_mpoly_fit_length(nmod_mpoly_t A, slong len, const nmod_mpoly_ctx_t ctx) Ensure that *A* has space for at least *len* terms. .. function:: void nmod_mpoly_realloc(nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx) Reallocate *A* to have space for *alloc* terms. Assumes the current length of the polynomial is not greater than *alloc*. .. function:: void nmod_mpoly_clear(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Release any space allocated for *A*. Input/Output -------------------------------------------------------------------------------- The variable strings in *x* start with the variable of most significance at index `0`. If *x* is ``NULL``, the variables are named ``x1``, ``x2``, etc. .. function:: char * nmod_mpoly_get_str_pretty(const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx) Return a string, which the user is responsible for cleaning up, representing *A*, given an array of variable strings *x*. .. function:: int nmod_mpoly_fprint_pretty(FILE * file, const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx) Print a string representing *A* to *file*. .. function:: int nmod_mpoly_print_pretty(const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx) Print a string representing *A* to ``stdout``. .. function:: int nmod_mpoly_set_str_pretty(nmod_mpoly_t A, const char * str, const char ** x, const nmod_mpoly_ctx_t ctx) Set *A* to the polynomial in the null-terminates string *str* given an array *x* of variable strings. If parsing *str* fails, *A* is set to zero, and `-1` is returned. Otherwise, `0` is returned. The operations ``+``, ``-``, ``*``, and ``/`` are permitted along with integers and the variables in *x*. The character ``^`` must be immediately followed by the (integer) exponent. If any division is not exact, parsing fails. Basic manipulation -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_gen(nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) Set *A* to the variable of index *var*, where `var = 0` corresponds to the variable with the most significance with respect to the ordering. .. function:: int nmod_mpoly_is_gen(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) If `var \ge 0`, return `1` if *A* is equal to the `var`-th generator, otherwise return `0`. If `var < 0`, return `1` if the polynomial is equal to any generator, otherwise return `0`. .. function:: void nmod_mpoly_set(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Set *A* to *B*. .. function:: int nmod_mpoly_equal(const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Return `1` if *A* is equal to *B*, else return `0`. .. function:: void nmod_mpoly_swap(nmod_mpoly_t A, nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Efficiently swap *A* and *B*. Constants -------------------------------------------------------------------------------- .. function:: int nmod_mpoly_is_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return `1` if *A* is a constant, else return `0`. .. function:: ulong nmod_mpoly_get_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Assuming that *A* is a constant, return this constant. This function throws if *A* is not a constant. .. function:: void nmod_mpoly_set_ui(nmod_mpoly_t A, ulong c, const nmod_mpoly_ctx_t ctx) Set *A* to the constant *c*. .. function:: void nmod_mpoly_zero(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Set *A* to the constant `0`. .. function:: void nmod_mpoly_one(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Set *A* to the constant `1`. .. function:: int nmod_mpoly_equal_ui(const nmod_mpoly_t A, ulong c, const nmod_mpoly_ctx_t ctx) Return `1` if *A* is equal to the constant *c*, else return `0`. .. function:: int nmod_mpoly_is_zero(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return `1` if *A* is the constant `0`, else return `0`. .. function:: int nmod_mpoly_is_one(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return `1` if *A* is the constant `1`, else return `0`. Degrees -------------------------------------------------------------------------------- .. function:: int nmod_mpoly_degrees_fit_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return `1` if the degrees of *A* with respect to each variable fit into an ``slong``, otherwise return `0`. .. function:: void nmod_mpoly_degrees_fmpz(fmpz ** degs, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_degrees_si(slong * degs, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Set *degs* to the degrees of *A* with respect to each variable. If *A* is zero, all degrees are set to `-1`. .. function:: void nmod_mpoly_degree_fmpz(fmpz_t deg, const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) slong nmod_mpoly_degree_si(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) Either return or set *deg* to the degree of *A* with respect to the variable of index *var*. If *A* is zero, the degree is defined to be `-1`. .. function:: int nmod_mpoly_total_degree_fits_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return `1` if the total degree of *A* fits into an ``slong``, otherwise return `0`. .. function:: void nmod_mpoly_total_degree_fmpz(fmpz_t tdeg, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) slong nmod_mpoly_total_degree_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Either return or set *tdeg* to the total degree of *A*. If *A* is zero, the total degree is defined to be `-1`. .. function:: void nmod_mpoly_used_vars(int * used, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) For each variable index *i*, set ``used[i]`` to nonzero if the variable of index *i* appears in *A* and to zero otherwise. Coefficients -------------------------------------------------------------------------------- .. function:: ulong nmod_mpoly_get_coeff_ui_monomial(const nmod_mpoly_t A, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx) Assuming that *M* is a monomial, return the coefficient of the corresponding monomial in *A*. This function throws if *M* is not a monomial. .. function:: void nmod_mpoly_set_coeff_ui_monomial(nmod_mpoly_t A, ulong c, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx) Assuming that *M* is a monomial, set the coefficient of the corresponding monomial in *A* to *c*. This function throws if *M* is not a monomial. .. function:: ulong nmod_mpoly_get_coeff_ui_fmpz(const nmod_mpoly_t A, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) ulong nmod_mpoly_get_coeff_ui_ui(const nmod_mpoly_t A, const ulong * exp, const nmod_mpoly_ctx_t ctx) Return the coefficient of the monomial with exponent *exp*. .. function:: void nmod_mpoly_set_coeff_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_set_coeff_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx) Set the coefficient of the monomial with exponent *exp* to `c`. .. function:: void nmod_mpoly_get_coeff_vars_ui(nmod_mpoly_t C, const nmod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const nmod_mpoly_ctx_t ctx) Set *C* to the coefficient of *A* with respect to the variables in *vars* with powers in the corresponding array *exps*. Both *vars* and *exps* point to array of length *length*. It is assumed that ``0 < length \le nvars(A)`` and that the variables in *vars* are distinct. Comparison -------------------------------------------------------------------------------- .. function:: int nmod_mpoly_cmp(const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Return `1` (resp. `-1`, or `0`) if *A* is after (resp. before, same as) *B* in some arbitrary but fixed total ordering of the polynomials. This ordering agrees with the usual ordering of monomials when *A* and *B* are both monomials. Container operations -------------------------------------------------------------------------------- These functions deal with violations of the internal canonical representation. If a term index is negative or not strictly less than the length of the polynomial, the function will throw. .. function:: mp_limb_t * nmod_mpoly_term_coeff_ref(nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) Return a reference to the coefficient of index *i* of *A*. .. function:: int nmod_mpoly_is_canonical(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return `1` if *A* is in canonical form. Otherwise, return `0`. To be in canonical form, all of the terms must have nonzero coefficients, and the terms must be sorted from greatest to least. .. function:: slong nmod_mpoly_length(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return the number of terms in *A*. If the polynomial is in canonical form, this will be the number of nonzero coefficients. .. function:: void nmod_mpoly_resize(nmod_mpoly_t A, slong new_length, const nmod_mpoly_ctx_t ctx) Set the length of *A* to ``new_length``. Terms are either deleted from the end, or new zero terms are appended. .. function:: ulong nmod_mpoly_get_term_coeff_ui(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) Return the coefficient of the term of index *i*. .. function:: void nmod_mpoly_set_term_coeff_ui(nmod_mpoly_t A, slong i, ulong c, const nmod_mpoly_ctx_t ctx) Set the coefficient of the term of index *i* to *c*. .. function:: int nmod_mpoly_term_exp_fits_si(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) int nmod_mpoly_term_exp_fits_ui(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) Return `1` if all entries of the exponent vector of the term of index *i* fit into an ``slong`` (resp. a ``ulong``). Otherwise, return `0`. .. function:: void nmod_mpoly_get_term_exp_fmpz(fmpz ** exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_get_term_exp_ui(ulong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) .. function:: void nmod_mpoly_get_term_exp_si(slong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) Set *exp* to the exponent vector of the term of index *i*. The ``_ui`` (resp. ``_si``) version throws if any entry does not fit into a ``ulong`` (resp. ``slong``). .. function:: ulong nmod_mpoly_get_term_var_exp_ui(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx) slong nmod_mpoly_get_term_var_exp_si(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx) Return the exponent of the variable *var* of the term of index *i*. This function throws if the exponent does not fit into a ``ulong`` (resp. ``slong``). .. function:: void nmod_mpoly_set_term_exp_fmpz(nmod_mpoly_t A, slong i, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_set_term_exp_ui(nmod_mpoly_t A, slong i, const ulong * exp, const nmod_mpoly_ctx_t ctx) Set the exponent of the term of index *i* to *exp*. .. function:: void nmod_mpoly_get_term(nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) Set *M* to the term of index *i* in *A*. .. function:: void nmod_mpoly_get_term_monomial(nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void nmod_mpoly_push_term_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_push_term_ui_ffmpz(nmod_mpoly_t A, ulong c, const fmpz * exp, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_push_term_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx) Append a term to *A* with coefficient *c* and exponent vector *exp*. This function runs in constant average time. .. function:: void nmod_mpoly_sort_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Sort the terms of *A* into the canonical ordering dictated by the ordering in *ctx*. This function simply reorders the terms: It does not combine like terms, nor does it delete terms with coefficient zero. This function runs in linear time in the bit size of *A*. .. function:: void nmod_mpoly_combine_like_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Combine adjacent like terms in *A* and delete terms with coefficient zero. If the terms of *A* were sorted to begin with, the result will be in canonical form. This function runs in linear time in the bit size of *A*. .. function:: void nmod_mpoly_reverse(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Set *A* to the reversal of *B*. Random generation -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_randtest_bound(nmod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const nmod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bound - 1]``. The exponents of each variable are generated by calls to ``n_randint(state, exp_bound)``. .. function:: void nmod_mpoly_randtest_bounds(nmod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const nmod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents in the range ``[0, exp_bounds[i] - 1]``. The exponents of the variable of index *i* are generated by calls to ``n_randint(state, exp_bounds[i])``. .. function:: void nmod_mpoly_randtest_bits(nmod_mpoly_t A, flint_rand_t state, slong length, mp_limb_t exp_bits, const nmod_mpoly_ctx_t ctx) Generate a random polynomial with length up to *length* and exponents whose packed form does not exceed the given bit count. Addition/Subtraction -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_add_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx) Set *A* to `B + c`. .. function:: void nmod_mpoly_sub_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx) Set *A* to `B - c`. .. function:: void nmod_mpoly_add(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) Set *A* to `B + C`. .. function:: void nmod_mpoly_sub(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) Set *A* to `B - C`. Scalar operations -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_neg(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Set *A* to `-B`. .. function:: void nmod_mpoly_scalar_mul_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx) Set *A* to `B \times c`. .. function:: void nmod_mpoly_make_monic(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Set *A* to *B* divided by the leading coefficient of *B*. This throws if *B* is zero or the leading coefficient is not invertible. Differentiation -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_derivative(nmod_mpoly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) Set *A* to the derivative of *B* with respect to the variable of index *var*. Evaluation -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: ulong nmod_mpoly_evaluate_all_ui(const nmod_mpoly_t A, const ulong * vals, const nmod_mpoly_ctx_t ctx) Return the evaluation of *A* where the variables are replaced by the corresponding elements of the array *vals*. .. function:: void nmod_mpoly_evaluate_one_ui(nmod_mpoly_t A, const nmod_mpoly_t B, slong var, ulong val, const nmod_mpoly_ctx_t ctx) Set *A* to the evaluation of *B* where the variable of index *var* is replaced by *val*. .. function:: int nmod_mpoly_compose_nmod_poly(nmod_poly_t A, const nmod_mpoly_t B, nmod_poly_struct * const * C, const nmod_mpoly_ctx_t ctx) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. The context object of *B* is *ctxB*. Return `1` for success and `0` for failure. .. function:: int nmod_mpoly_compose_nmod_mpoly_geobucket(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) int nmod_mpoly_compose_nmod_mpoly_horner(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) int nmod_mpoly_compose_nmod_mpoly(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variables are replaced by the corresponding elements of the array *C*. Both *A* and the elements of *C* have context object *ctxAC*, while *B* has context object *ctxB*. Neither of *A* and *B* is allowed to alias any other polynomial. Return `1` for success and `0` for failure. The main method attempts to perform the calculation using matrices and chooses heuristically between the ``geobucket`` and ``horner`` methods if needed. .. function:: void nmod_mpoly_compose_nmod_mpoly_gen(nmod_mpoly_t A, const nmod_mpoly_t B, const slong * c, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) Set *A* to the evaluation of *B* where the variable of index *i* in *ctxB* is replaced by the variable of index ``c[i]`` in *ctxAC*. The length of the array *C* is the number of variables in *ctxB*. If any ``c[i]`` is negative, the corresponding variable of *B* is replaced by zero. Otherwise, it is expected that ``c[i]`` is less than the number of variables in *ctxAC*. Multiplication -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_mul(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) Set *A* to `B \times C`. .. function:: void nmod_mpoly_mul_johnson(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_mul_heap_threaded(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) Set *A* to `B \times C` using Johnson's heap-based method. The first version always uses one thread. .. function:: int nmod_mpoly_mul_array(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) int nmod_mpoly_mul_array_threaded(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) Try to set *A* to `B \times C` using arrays. If the return is `0`, the operation was unsuccessful. Otherwise, it was successful, and the return is `1`. The first version always uses one thread. .. function:: int nmod_mpoly_mul_dense(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) Try to set *A* to `B \times C` using univariate arithmetic. If the return is `0`, the operation was unsuccessful. Otherwise, it was successful and the return is `1`. Powering -------------------------------------------------------------------------------- These functions return `0` when the operation would imply unreasonable arithmetic. .. function:: int nmod_mpoly_pow_fmpz(nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz_t k, const nmod_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power. Return `1` for success and `0` for failure. .. function:: int nmod_mpoly_pow_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power. Return `1` for success and `0` for failure. Division -------------------------------------------------------------------------------- The division functions assume that the modulus is prime. .. function:: int nmod_mpoly_divides(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) If *A* is divisible by *B*, set *Q* to the exact quotient and return `1`. Otherwise, set *Q* to zero and return `0`. Note that the function ``nmod_mpoly_div`` below may be faster if the quotient is known to be exact. .. function:: void nmod_mpoly_div(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Set *Q* to the quotient of *A* by *B*, discarding the remainder. .. function:: void nmod_mpoly_divrem(nmod_mpoly_t Q, nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Set *Q* and *R* to the quotient and remainder of *A* divided by *B*. .. function:: void nmod_mpoly_divrem_ideal(nmod_mpoly_struct ** Q, nmod_mpoly_t R, const nmod_mpoly_t A, nmod_mpoly_struct * const * B, slong len, const nmod_mpoly_ctx_t ctx) This function is as per :func:`nmod_mpoly_divrem` except that it takes an array of divisor polynomials *B* and it returns an array of quotient polynomials *Q*. The number of divisor (and hence quotient) polynomials, is given by *len*. .. function:: int nmod_mpoly_divides_dense(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Try to do the operation of ``nmod_mpoly_divides`` using univariate arithmetic. If the return is `-1`, the operation was unsuccessful. Otherwise, it was successful and the return is `0` or `1`. .. function:: int nmod_mpoly_divides_monagan_pearce(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Do the operation of ``nmod_mpoly_divides`` using the algorithm of Michael Monagan and Roman Pearce. .. function:: int nmod_mpoly_divides_heap_threaded(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Do the operation of ``nmod_mpoly_divides`` using the heap and multiple threads. This function should only be called once ``global_thread_pool`` has been initialized. .. note:: This function is only defined if the machine is known to be strongly ordered during the configuration. To check whether this function is defined during compilation-time, use the C preprocessor macro ``#ifdef nmod_mpoly_divides_heap_threaded``. Note that, if the system is known to be strongly ordered, the underlying algorithm for this function is utilized in :func:`nmod_mpoly_divides`. Hence, you may find it easier to use this function instead if the C preprocessor is not available. Greatest Common Divisor -------------------------------------------------------------------------------- The greatest common divisor functions assume that the modulus is prime. .. function:: void nmod_mpoly_term_content(nmod_mpoly_t M, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Set *M* to the GCD of the terms of *A*. If *A* is zero, *M* will be zero. Otherwise, *M* will be a monomial with coefficient one. .. function:: int nmod_mpoly_content_vars(nmod_mpoly_t g, const nmod_mpoly_t A, slong * vars, slong vars_length, const nmod_mpoly_ctx_t ctx) Set *g* to the GCD of the coefficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon success, *g* will be independent of the variables *vars*. .. function:: int nmod_mpoly_gcd(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Try to set *G* to the monic GCD of *A* and *B*. The GCD of zero and zero is defined to be zero. If the return is `1` the function was successful. Otherwise the return is `0` and *G* is left untouched. .. function:: int nmod_mpoly_gcd_cofactors(nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Do the operation of :func:`nmod_mpoly_gcd` and also compute `Abar = A/G` and `Bbar = B/G` if successful. .. function:: int nmod_mpoly_gcd_brown(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) int nmod_mpoly_gcd_hensel(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) int nmod_mpoly_gcd_zippel(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) Try to set *G* to the GCD of *A* and *B* using various algorithms. .. function:: int nmod_mpoly_resultant(nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) Try to set *R* to the resultant of *A* and *B* with respect to the variable of index *var*. .. function:: int nmod_mpoly_discriminant(nmod_mpoly_t D, const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) Try to set *D* to the discriminant of *A* with respect to the variable of index *var*. Square Root -------------------------------------------------------------------------------- The square root functions assume that the modulus is prime for correct operation. .. function:: int nmod_mpoly_sqrt(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) If `Q^2=A` has a solution, set *Q* to a solution and return `1`, otherwise return `0` and set *Q* to zero. .. function:: int nmod_mpoly_is_square(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Return `1` if *A* is a perfect square, otherwise return `0`. .. function:: int nmod_mpoly_quadratic_root(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) If `Q^2+AQ=B` has a solution, set *Q* to a solution and return `1`, otherwise return `0`. Univariate Functions -------------------------------------------------------------------------------- An ``nmod_mpoly_univar_t`` holds a univariate polynomial in some main variable with ``nmod_mpoly_t`` coefficients in the remaining variables. These functions are useful when one wants to rewrite an element of `\mathbb{Z}/n\mathbb{Z}[x_1, \dots, x_m]` as an element of `(\mathbb{Z}/n\mathbb{Z}[x_1, \dots, x_{v-1}, x_{v+1}, \dots, x_m])[x_v]` and vice versa. .. function:: void nmod_mpoly_univar_init(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) Initialize *A*. .. function:: void nmod_mpoly_univar_clear(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) Clear *A*. .. function:: void nmod_mpoly_univar_swap(nmod_mpoly_univar_t A, nmod_mpoly_univar_t B, const nmod_mpoly_ctx_t ctx) Swap *A* and *B*. .. function:: void nmod_mpoly_to_univar(nmod_mpoly_univar_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) Set *A* to a univariate form of *B* by pulling out the variable of index *var*. The coefficients of *A* will still belong to the content *ctx* but will not depend on the variable of index *var*. .. function:: void nmod_mpoly_from_univar(nmod_mpoly_t A, const nmod_mpoly_univar_t B, slong var, const nmod_mpoly_ctx_t ctx) Set *A* to the normal form of *B* by putting in the variable of index *var*. This function is undefined if the coefficients of *B* depend on the variable of index *var*. .. function:: int nmod_mpoly_univar_degree_fits_si(const nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) Return `1` if the degree of *A* with respect to the main variable fits an ``slong``. Otherwise, return `0`. .. function:: slong nmod_mpoly_univar_length(const nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) Return the number of terms in *A* with respect to the main variable. .. function:: slong nmod_mpoly_univar_get_term_exp_si(nmod_mpoly_univar_t A, slong i, const nmod_mpoly_ctx_t ctx) Return the exponent of the term of index *i* of *A*. .. function:: void nmod_mpoly_univar_get_term_coeff(nmod_mpoly_t c, const nmod_mpoly_univar_t A, slong i, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_univar_swap_term_coeff(nmod_mpoly_t c, nmod_mpoly_univar_t A, slong i, const nmod_mpoly_ctx_t ctx) Set (resp. swap) *c* to (resp. with) the coefficient of the term of index *i* of *A*. Internal Functions -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_pow_rmul(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx) Set *A* to *B* raised to the *k*-th power using repeated multiplications. .. function:: void nmod_mpoly_div_monagan_pearce(nmod_mpoly_t polyq, const nmod_mpoly_t poly2, const nmod_mpoly_t poly3, const nmod_mpoly_ctx_t ctx) Set ``polyq`` to the quotient of ``poly2`` by ``poly3``, discarding the remainder (with notional remainder coefficients reduced modulo the leading coefficient of ``poly3``). Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce. This function is exceptionally efficient if the division is known to be exact. .. function:: void nmod_mpoly_divrem_monagan_pearce(nmod_mpoly_t q, nmod_mpoly_t r, const nmod_mpoly_t poly2, const nmod_mpoly_t poly3, const nmod_mpoly_ctx_t ctx) Set ``polyq`` and ``polyr`` to the quotient and remainder of ``poly2`` divided by ``poly3``, (with remainder coefficients reduced modulo the leading coefficient of ``poly3``). Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce. .. function:: void nmod_mpoly_divrem_ideal_monagan_pearce(nmod_mpoly_struct ** q, nmod_mpoly_t r, const nmod_mpoly_t poly2, nmod_mpoly_struct * const * poly3, slong len, const nmod_mpoly_ctx_t ctx) This function is as per ``nmod_mpoly_divrem_monagan_pearce`` except that it takes an array of divisor polynomials ``poly3``, and it returns an array of quotient polynomials ``q``. The number of divisor (and hence quotient) polynomials, is given by *len*. The function computes polynomials `q_i = q[i]` such that ``poly2`` is `r + \sum_{i=0}^{\mbox{len - 1}} q_ib_i`, where `b_i =` ``poly3[i]``. flint-3.1.3/doc/source/nmod_mpoly_factor.rst000066400000000000000000000061501461254215100211470ustar00rootroot00000000000000.. _nmod-mpoly-factor: **nmod_mpoly_factor.h** -- factorisation of multivariate polynomials over integers mod n (word-size n) ====================================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_mpoly_factor_struct A struct for holding a factored polynomial. There is a single constant and a product of bases to corresponding exponents. .. type:: nmod_mpoly_factor_t An array of length `1` of ``nmod_mpoly_factor_struct``. Memory management -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_factor_init(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) Initialise *f*. .. function:: void nmod_mpoly_factor_clear(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) Clear *f*. Basic manipulation -------------------------------------------------------------------------------- .. function:: void nmod_mpoly_factor_swap(nmod_mpoly_factor_t f, nmod_mpoly_factor_t g, const nmod_mpoly_ctx_t ctx) Efficiently swap *f* and *g*. .. function:: slong nmod_mpoly_factor_length(const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) Return the length of the product in *f*. .. function:: ulong nmod_mpoly_factor_get_constant_ui(const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) Return the constant of *f*. .. function:: void nmod_mpoly_factor_get_base(nmod_mpoly_t p, const nmod_mpoly_factor_t f, slong i, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_factor_swap_base(nmod_mpoly_t p, nmod_mpoly_factor_t f, slong i, const nmod_mpoly_ctx_t ctx) Set (resp. swap) *B* to (resp. with) the base of the term of index `i` in *A*. .. function:: slong nmod_mpoly_factor_get_exp_si(nmod_mpoly_factor_t f, slong i, const nmod_mpoly_ctx_t ctx) Return the exponent of the term of index `i` in *A*. It is assumed to fit an ``slong``. .. function:: void nmod_mpoly_factor_sort(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) Sort the product of *f* first by exponent and then by base. Factorisation -------------------------------------------------------------------------------- A return of `1` indicates that the function was successful. Otherwise, the return is `0` and *f* is undefined. None of these functions multiply *f* by *A*: *f* is simply set to a factorisation of *A*, and thus these functions should not depend on the initial value of the output *f*. .. function:: int nmod_mpoly_factor_squarefree(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are primitive and pairwise relatively prime. If the product of all irreducible factors with a given exponent is desired, it is recommended to call :func:`nmod_mpoly_factor_sort` and then multiply the bases with the desired exponent. .. function:: int nmod_mpoly_factor(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) Set *f* to a factorization of *A* where the bases are irreducible. flint-3.1.3/doc/source/nmod_poly.rst000066400000000000000000003403421461254215100174400ustar00rootroot00000000000000.. _nmod-poly: **nmod_poly.h** -- univariate polynomials over integers mod n (word-size n) =============================================================================== The :type:`nmod_poly_t` data type represents elements of `\mathbb{Z}/n\mathbb{Z}[x]` for a fixed modulus `n`. The ``nmod_poly`` module provides routines for memory management, basic arithmetic and some higher level functions such as GCD, etc. Each coefficient of an :type:`nmod_poly_t` is of type ``mp_limb_t`` and represents an integer reduced modulo the fixed modulus `n`. Unless otherwise specified, all functions in this section permit aliasing between their input arguments and between their input and output arguments. The :type:`nmod_poly_t` type is a typedef for an array of length 1 of :type:`nmod_poly_struct`'s. This permits passing parameters of type :type:`nmod_poly_t` by reference. In reality one never deals directly with the ``struct`` and simply deals with objects of type :type:`nmod_poly_t`. For simplicity we will think of an :type:`nmod_poly_t` as a ``struct``, though in practice to access fields of this ``struct``, one needs to dereference first, e.g.\ to access the ``length`` field of an :type:`nmod_poly_t` called ``poly1`` one writes ``poly1->length``. An :type:`nmod_poly_t` is said to be *normalised* if either ``length`` is zero, or if the leading coefficient of the polynomial is non-zero. All ``nmod_poly`` functions expect their inputs to be normalised and for all coefficients to be reduced modulo `n` and unless otherwise specified they produce output that is normalised with coefficients reduced modulo `n`. It is recommended that users do not access the fields of an :type:`nmod_poly_t` or its coefficient data directly, but make use of the functions designed for this purpose, detailed below. Functions in ``nmod_poly`` do all the memory management for the user. One does not need to specify the maximum length in advance before using a polynomial object. FLINT reallocates space automatically as the computation proceeds, if more space is required. Simple example -------------- The following example computes the square of the polynomial `5x^3 + 6` in `\mathbb{Z}/7\mathbb{Z}[x]`. .. code:: c #include "nmod_poly.h" int main() { nmod_poly_t x, y; nmod_poly_init(x, 7); nmod_poly_init(y, 7); nmod_poly_set_coeff_ui(x, 3, 5); nmod_poly_set_coeff_ui(x, 0, 6); nmod_poly_mul(y, x, x); nmod_poly_print(x); flint_printf("\n"); nmod_poly_print(y); flint_printf("\n"); nmod_poly_clear(x); nmod_poly_clear(y); } The output is: :: 4 7 6 0 0 5 7 7 1 0 0 4 0 0 4 Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_poly_struct .. type:: nmod_poly_t Helper functions -------------------------------------------------------------------------------- .. function:: int signed_mpn_sub_n(mp_ptr res, mp_srcptr op1, mp_srcptr op2, slong n) If ``op1 >= op2`` return 0 and set ``res`` to ``op1 - op2`` else return 1 and set ``res`` to ``op2 - op1``. Memory management -------------------------------------------------------------------------------- .. function:: void nmod_poly_init(nmod_poly_t poly, mp_limb_t n) Initialises ``poly``. It will have coefficients modulo `n`. .. function:: void nmod_poly_init_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv) Initialises ``poly``. It will have coefficients modulo `n`. The caller supplies a precomputed inverse limb generated by :func:`n_preinvert_limb`. .. function:: void nmod_poly_init_mod(nmod_poly_t poly, const nmod_t mod) Initialises ``poly`` using an already initialised modulus ``mod``. .. function:: void nmod_poly_init2(nmod_poly_t poly, mp_limb_t n, slong alloc) Initialises ``poly``. It will have coefficients modulo `n`. Up to ``alloc`` coefficients may be stored in ``poly``. .. function:: void nmod_poly_init2_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv, slong alloc) Initialises ``poly``. It will have coefficients modulo `n`. The caller supplies a precomputed inverse limb generated by :func:`n_preinvert_limb`. Up to ``alloc`` coefficients may be stored in ``poly``. .. function:: void nmod_poly_realloc(nmod_poly_t poly, slong alloc) Reallocates ``poly`` to the given length. If the current length is less than ``alloc``, the polynomial is truncated and normalised. If ``alloc`` is zero, the polynomial is cleared. .. function:: void nmod_poly_clear(nmod_poly_t poly) Clears the polynomial and releases any memory it used. The polynomial cannot be used again until it is initialised. .. function:: void nmod_poly_fit_length(nmod_poly_t poly, slong alloc) Ensures ``poly`` has space for at least ``alloc`` coefficients. This function only ever grows the allocated space, so no data loss can occur. .. function:: void _nmod_poly_normalise(nmod_poly_t poly) Internal function for normalising a polynomial so that the top coefficient, if there is one at all, is not zero. Polynomial properties -------------------------------------------------------------------------------- .. function:: slong nmod_poly_length(const nmod_poly_t poly) Returns the length of the polynomial ``poly``. The zero polynomial has length zero. .. function:: slong nmod_poly_degree(const nmod_poly_t poly) Returns the degree of the polynomial ``poly``. The zero polynomial is deemed to have degree `-1`. .. function:: mp_limb_t nmod_poly_modulus(const nmod_poly_t poly) Returns the modulus of the polynomial ``poly``. This will be a positive integer. .. function:: flint_bitcnt_t nmod_poly_max_bits(const nmod_poly_t poly) Returns the maximum number of bits of any coefficient of ``poly``. .. function:: int nmod_poly_is_unit(const nmod_poly_t poly) Returns `1` if the polynomial is a nonzero constant (in the case of prime modulus, this is equivalent to being a unit), otherwise `0`. .. function:: int nmod_poly_is_monic(const nmod_poly_t poly) Returns `1` if the polynomial is monic, i.e. nonzero with leading coefficient `1`, otherwise `0`. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void nmod_poly_set(nmod_poly_t a, const nmod_poly_t b) Sets ``a`` to a copy of ``b``. .. function:: void nmod_poly_swap(nmod_poly_t poly1, nmod_poly_t poly2) Efficiently swaps ``poly1`` and ``poly2`` by swapping pointers internally. .. function:: void nmod_poly_zero(nmod_poly_t res) Sets ``res`` to the zero polynomial. .. function:: void nmod_poly_truncate(nmod_poly_t poly, slong len) Truncates ``poly`` to the given length and normalises it. If ``len`` is greater than the current length of ``poly``, then nothing happens. .. function:: void nmod_poly_set_trunc(nmod_poly_t res, const nmod_poly_t poly, slong len) Notionally truncate ``poly`` to length ``len`` and set ``res`` to the result. The result is normalised. .. function:: void _nmod_poly_reverse(mp_ptr output, mp_srcptr input, slong len, slong m) Sets ``output`` to the reverse of ``input``, which is of length ``len``, but thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary. The length ``m`` must be non-negative, but there are no other restrictions. The polynomial ``output`` must have space for ``m`` coefficients. Supports aliasing of ``output`` and ``input``, but the behaviour is undefined in case of partial overlap. .. function:: void nmod_poly_reverse(nmod_poly_t output, const nmod_poly_t input, slong m) Sets ``output`` to the reverse of ``input``, thinking of it as a polynomial of length ``m``, notionally zero-padded if necessary). The length ``m`` must be non-negative, but there are no other restrictions. The output polynomial will be set to length ``m`` and then normalised. Randomization -------------------------------------------------------------------------------- .. function:: void nmod_poly_randtest(nmod_poly_t poly, flint_rand_t state, slong len) Generates a random polynomial with length up to ``len``. .. function:: void nmod_poly_randtest_irreducible(nmod_poly_t poly, flint_rand_t state, slong len) Generates a random irreducible polynomial with length up to ``len``. .. function:: void nmod_poly_randtest_monic(nmod_poly_t poly, flint_rand_t state, slong len) Generates a random monic polynomial with length ``len``. .. function:: void nmod_poly_randtest_monic_irreducible(nmod_poly_t poly, flint_rand_t state, slong len) Generates a random monic irreducible polynomial with length ``len``. .. function:: void nmod_poly_randtest_monic_primitive(nmod_poly_t poly, flint_rand_t state, slong len) Generates a random monic irreducible primitive polynomial with length ``len``. .. function:: void nmod_poly_randtest_trinomial(nmod_poly_t poly, flint_rand_t state, slong len) Generates a random monic trinomial of length ``len``. .. function:: int nmod_poly_randtest_trinomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts) Attempts to set ``poly`` to a monic irreducible trinomial of length ``len``. It will generate up to ``max_attempts`` trinomials in attempt to find an irreducible one. If ``max_attempts`` is ``0``, then it will keep generating trinomials until an irreducible one is found. Returns `1` if one is found and `0` otherwise. .. function:: void nmod_poly_randtest_pentomial(nmod_poly_t poly, flint_rand_t state, slong len) Generates a random monic pentomial of length ``len``. .. function:: int nmod_poly_randtest_pentomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts) Attempts to set ``poly`` to a monic irreducible pentomial of length ``len``. It will generate up to ``max_attempts`` pentomials in attempt to find an irreducible one. If ``max_attempts`` is ``0``, then it will keep generating pentomials until an irreducible one is found. Returns `1` if one is found and `0` otherwise. .. function:: void nmod_poly_randtest_sparse_irreducible(nmod_poly_t poly, flint_rand_t state, slong len) Attempts to set ``poly`` to a sparse, monic irreducible polynomial with length ``len``. It attempts to find an irreducible trinomial. If that does not succeed, it attempts to find a irreducible pentomial. If that fails, then ``poly`` is just set to a random monic irreducible polynomial. Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: ulong nmod_poly_get_coeff_ui(const nmod_poly_t poly, slong j) Returns the coefficient of ``poly`` at index ``j``, where coefficients are numbered with zero being the constant coefficient, and returns it as an ``ulong``. If ``j`` refers to a coefficient beyond the end of ``poly``, zero is returned. .. function:: void nmod_poly_set_coeff_ui(nmod_poly_t poly, slong j, ulong c) Sets the coefficient of ``poly`` at index ``j``, where coefficients are numbered with zero being the constant coefficient, to the value ``c`` reduced modulo the modulus of ``poly``. If ``j`` refers to a coefficient beyond the current end of ``poly``, the polynomial is first resized, with intervening coefficients being set to zero. Input and output -------------------------------------------------------------------------------- .. function:: char * nmod_poly_get_str(const nmod_poly_t poly) Writes ``poly`` to a string representation. The format is as described for :func:`nmod_poly_print`. The string must be freed by the user when finished. For this it is sufficient to call :func:`flint_free`. .. function:: char * nmod_poly_get_str_pretty(const nmod_poly_t poly, const char * x) Writes ``poly`` to a pretty string representation. The format is as described for :func:`nmod_poly_print_pretty`. The string must be freed by the user when finished. For this it is sufficient to call :func:`flint_free`. It is assumed that the top coefficient is non-zero. .. function:: int nmod_poly_set_str(nmod_poly_t poly, const char * s) Reads ``poly`` from a string ``s``. The format is as described for :func:`nmod_poly_print`. If a polynomial in the correct format is read, a positive value is returned, otherwise a non-positive value is returned. .. function:: int nmod_poly_print(const nmod_poly_t a) Prints the polynomial to ``stdout``. The length is printed, followed by a space, then the modulus. If the length is zero this is all that is printed, otherwise two spaces followed by a space separated list of coefficients is printed, beginning with the constant coefficient. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int nmod_poly_print_pretty(const nmod_poly_t a, const char * x) Prints the polynomial to ``stdout`` using the string ``x`` to represent the indeterminate. It is assumed that the top coefficient is non-zero. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int nmod_poly_fread(FILE * f, nmod_poly_t poly) Reads ``poly`` from the file stream ``f``. If this is a file that has just been written, the file should be closed then opened again. The format is as described for :func:`nmod_poly_print`. If a polynomial in the correct format is read, a positive value is returned, otherwise a non-positive value is returned. .. function:: int nmod_poly_fprint(FILE * f, const nmod_poly_t poly) Writes a polynomial to the file stream ``f``. If this is a file then the file should be closed and reopened before being read. The format is as described for :func:`nmod_poly_print`. If the polynomial is written correctly, a positive value is returned, otherwise a non-positive value is returned. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int nmod_poly_fprint_pretty(FILE * f, const nmod_poly_t poly, const char * x) Writes a polynomial to the file stream ``f``. If this is a file then the file should be closed and reopened before being read. The format is as described for :func:`nmod_poly_print_pretty`. If the polynomial is written correctly, a positive value is returned, otherwise a non-positive value is returned. It is assumed that the top coefficient is non-zero. In case of success, returns a positive value. In case of failure, returns a non-positive value. .. function:: int nmod_poly_read(nmod_poly_t poly) Read ``poly`` from ``stdin``. The format is as described for :func:`nmod_poly_print`. If a polynomial in the correct format is read, a positive value is returned, otherwise a non-positive value is returned. Comparison -------------------------------------------------------------------------------- .. function:: int nmod_poly_equal(const nmod_poly_t a, const nmod_poly_t b) Returns `1` if the polynomials are equal, otherwise `0`. .. function:: int nmod_poly_equal_nmod(const nmod_poly_t poly, ulong cst) Returns `1` if the polynomial ``poly`` is constant, equal to ``cst``, otherwise `0`. ``cst`` is assumed to be already reduced, i.e. less than the modulus of ``poly``. .. function:: int nmod_poly_equal_ui(const nmod_poly_t poly, ulong cst) Returns `1` if the polynomial ``poly`` is constant and equal to ``cst`` up to reduction modulo the modulus of ``poly``, otherwise returns `0`. .. function:: int nmod_poly_equal_trunc(const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) Notionally truncate ``poly1`` and ``poly2`` to length `n` and return `1` if the truncations are equal, otherwise return `0`. .. function:: int nmod_poly_is_zero(const nmod_poly_t poly) Returns `1` if the polynomial ``poly`` is the zero polynomial, otherwise returns `0`. .. function:: int nmod_poly_is_one(const nmod_poly_t poly) Returns `1` if the polynomial ``poly`` is the constant polynomial 1, otherwise returns `0`. .. function:: int nmod_poly_is_gen(const nmod_poly_t poly) Returns `1` if the polynomial is the generating indeterminate (i.e. has degree `1`, constant coefficient `0`, and leading coefficient `1`), otherwise returns `0`. Shifting -------------------------------------------------------------------------------- .. function:: void _nmod_poly_shift_left(mp_ptr res, mp_srcptr poly, slong len, slong k) Sets ``(res, len + k)`` to ``(poly, len)`` shifted left by ``k`` coefficients. Assumes that ``res`` has space for ``len + k`` coefficients. .. function:: void nmod_poly_shift_left(nmod_poly_t res, const nmod_poly_t poly, slong k) Sets ``res`` to ``poly`` shifted left by ``k`` coefficients, i.e. multiplied by `x^k`. .. function:: void _nmod_poly_shift_right(mp_ptr res, mp_srcptr poly, slong len, slong k) Sets ``(res, len - k)`` to ``(poly, len)`` shifted left by ``k`` coefficients. It is assumed that ``k <= len`` and that ``res`` has space for at least ``len - k`` coefficients. .. function:: void nmod_poly_shift_right(nmod_poly_t res, const nmod_poly_t poly, slong k) Sets ``res`` to ``poly`` shifted right by ``k`` coefficients, i.e. divide by `x^k` and throw away the remainder. If ``k`` is greater than or equal to the length of ``poly``, the result is the zero polynomial. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _nmod_poly_add(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Sets ``res`` to the sum of ``(poly1, len1)`` and ``(poly2, len2)``. There are no restrictions on the lengths. .. function:: void nmod_poly_add(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Sets ``res`` to the sum of ``poly1`` and ``poly2``. .. function:: void nmod_poly_add_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) Notionally truncate ``poly1`` and ``poly2`` to length `n` and set ``res`` to the sum. .. function:: void _nmod_poly_sub(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Sets ``res`` to the difference of ``(poly1, len1)`` and ``(poly2, len2)``. There are no restrictions on the lengths. .. function:: void nmod_poly_sub(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Sets ``res`` to the difference of ``poly1`` and ``poly2``. .. function:: void nmod_poly_sub_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) Notionally truncate ``poly1`` and ``poly2`` to length `n` and set ``res`` to the difference. .. function:: void nmod_poly_neg(nmod_poly_t res, const nmod_poly_t poly) Sets ``res`` to the negation of ``poly``. Scalar multiplication and division -------------------------------------------------------------------------------- .. function:: void nmod_poly_scalar_mul_nmod(nmod_poly_t res, const nmod_poly_t poly, ulong c) Sets ``res`` to ``poly`` multiplied by `c`. The element `c` is assumed to be less than the modulus of ``poly``. .. function:: void nmod_poly_scalar_addmul_nmod(nmod_poly_t res, const nmod_poly_t poly, ulong c) Adds ``poly`` multiplied by `c` to ``res``. The element `c` is assumed to be less than the modulus of ``poly``. .. function:: void _nmod_poly_make_monic(mp_ptr output, mp_srcptr input, slong len, nmod_t mod) Sets ``output`` to be the scalar multiple of ``input`` of length ``len > 0`` that has leading coefficient one, if such a polynomial exists. If the leading coefficient of ``input`` is not invertible, ``output`` is set to the multiple of ``input`` whose leading coefficient is the greatest common divisor of the leading coefficient and the modulus of ``input``. .. function:: void nmod_poly_make_monic(nmod_poly_t output, const nmod_poly_t input) Sets ``output`` to be the scalar multiple of ``input`` with leading coefficient one, if such a polynomial exists. If ``input`` is zero an exception is raised. If the leading coefficient of ``input`` is not invertible, ``output`` is set to the multiple of ``input`` whose leading coefficient is the greatest common divisor of the leading coefficient and the modulus of ``input``. Bit packing and unpacking -------------------------------------------------------------------------------- .. function:: void _nmod_poly_bit_pack(mp_ptr res, mp_srcptr poly, slong len, flint_bitcnt_t bits) Packs ``len`` coefficients of ``poly`` into fields of the given number of bits in the large integer ``res``, i.e. evaluates ``poly`` at ``2^bits`` and store the result in ``res``. Assumes ``len > 0`` and ``bits > 0``. Also assumes that no coefficient of ``poly`` is bigger than ``bits/2`` bits. We also assume ``bits < 3 * FLINT_BITS``. .. function:: void _nmod_poly_bit_unpack(mp_ptr res, slong len, mp_srcptr mpn, ulong bits, nmod_t mod) Unpacks ``len`` coefficients stored in the big integer ``mpn`` in bit fields of the given number of bits, reduces them modulo the given modulus, then stores them in the polynomial ``res``. We assume ``len > 0`` and ``3 * FLINT_BITS > bits > 0``. There are no restrictions on the size of the actual coefficients as stored within the bitfields. .. function:: void nmod_poly_bit_pack(fmpz_t f, const nmod_poly_t poly, flint_bitcnt_t bit_size) Packs ``poly`` into bitfields of size ``bit_size``, writing the result to ``f``. .. function:: void nmod_poly_bit_unpack(nmod_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size) Unpacks the polynomial from fields of size ``bit_size`` as represented by the integer ``f``. .. function:: void _nmod_poly_KS2_pack1(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r) Same as ``_nmod_poly_KS2_pack``, but requires ``b <= FLINT_BITS``. .. function:: void _nmod_poly_KS2_pack(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r) Bit packing routine used by KS2 and KS4 multiplication. .. function:: void _nmod_poly_KS2_unpack1(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) Same as ``_nmod_poly_KS2_unpack``, but requires ``b <= FLINT_BITS`` (i.e. writes one word per coefficient). .. function:: void _nmod_poly_KS2_unpack2(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) Same as ``_nmod_poly_KS2_unpack``, but requires ``FLINT_BITS < b <= 2 * FLINT_BITS`` (i.e. writes two words per coefficient). .. function:: void _nmod_poly_KS2_unpack3(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) Same as ``_nmod_poly_KS2_unpack``, but requires ``2 * FLINT_BITS < b < 3 * FLINT_BITS`` (i.e. writes three words per coefficient). .. function:: void _nmod_poly_KS2_unpack(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) Bit unpacking code used by KS2 and KS4 multiplication. KS2/KS4 Reduction -------------------------------------------------------------------------------- .. function:: void _nmod_poly_KS2_reduce(mp_ptr res, slong s, mp_srcptr op, slong n, ulong w, nmod_t mod) Reduction code used by KS2 and KS4 multiplication. .. function:: void _nmod_poly_KS2_recover_reduce1(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) Same as ``_nmod_poly_KS2_recover_reduce``, but requires ``0 < 2 * b <= FLINT_BITS``. .. function:: void _nmod_poly_KS2_recover_reduce2(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) Same as ``_nmod_poly_KS2_recover_reduce``, but requires ``FLINT_BITS < 2 * b < 2*FLINT_BITS``. .. function:: void _nmod_poly_KS2_recover_reduce2b(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) Same as ``_nmod_poly_KS2_recover_reduce``, but requires ``b == FLINT_BITS``. .. function:: void _nmod_poly_KS2_recover_reduce3(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) Same as ``_nmod_poly_KS2_recover_reduce``, but requires ``2 * FLINT_BITS < 2 * b <= 3 * FLINT_BITS``. .. function:: void _nmod_poly_KS2_recover_reduce(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) Reduction code used by KS4 multiplication. Multiplication -------------------------------------------------------------------------------- .. function:: void _nmod_poly_mul_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Sets ``(res, len1 + len2 - 1)`` to the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. .. function:: void nmod_poly_mul_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _nmod_poly_mullow_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong trunc, nmod_t mod) Sets ``res`` to the lower ``trunc`` coefficients of the product of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``len1 >= len2 > 0`` and ``trunc > 0``. Aliasing of inputs and output is not permitted. .. function:: void nmod_poly_mullow_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc) Sets ``res`` to the lower ``trunc`` coefficients of the product of ``poly1`` and ``poly2``. .. function:: void _nmod_poly_mulhigh_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong start, nmod_t mod) Computes the product of ``(poly1, len1)`` and ``(poly2, len2)`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. Assumes that ``len1 >= len2 > 0``. Aliasing of inputs and output is not permitted. .. function:: void nmod_poly_mulhigh_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong start) Computes the product of ``poly1`` and ``poly2`` and writes the coefficients from ``start`` onwards into the high coefficients of ``res``, the remaining coefficients being arbitrary but reduced. .. function:: void _nmod_poly_mul_KS(mp_ptr out, mp_srcptr in1, slong len1, mp_srcptr in2, slong len2, flint_bitcnt_t bits, nmod_t mod) Sets ``res`` to the product of ``in1`` and ``in2`` assuming the output coefficients are at most the given number of bits wide. If ``bits`` is set to `0` an appropriate value is computed automatically. Assumes that ``len1 >= len2 > 0``. .. function:: void nmod_poly_mul_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, flint_bitcnt_t bits) Sets ``res`` to the product of ``poly1`` and ``poly2`` assuming the output coefficients are at most the given number of bits wide. If ``bits`` is set to `0` an appropriate value is computed automatically. .. function:: void _nmod_poly_mul_KS2(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod) Sets ``res`` to the product of ``op1`` and ``op2``. Assumes that ``len1 >= len2 > 0``. .. function:: void nmod_poly_mul_KS2(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _nmod_poly_mul_KS4(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod) Sets ``res`` to the product of ``op1`` and ``op2``. Assumes that ``len1 >= len2 > 0``. .. function:: void nmod_poly_mul_KS4(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _nmod_poly_mullow_KS(mp_ptr out, mp_srcptr in1, slong len1, mp_srcptr in2, slong len2, flint_bitcnt_t bits, slong n, nmod_t mod) Sets ``out`` to the low `n` coefficients of ``in1`` of length ``len1`` times ``in2`` of length ``len2``. The output must have space for ``n`` coefficients. We assume that ``len1 >= len2 > 0`` and that ``0 < n <= len1 + len2 - 1``. .. function:: void nmod_poly_mullow_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, flint_bitcnt_t bits, slong n) Set ``res`` to the low `n` coefficients of ``in1`` of length ``len1`` times ``in2`` of length ``len2``. .. function:: void _nmod_poly_mul(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Sets ``res`` to the product of ``poly1`` of length ``len1`` and ``poly2`` of length ``len2``. Assumes ``len1 >= len2 > 0``. No aliasing is permitted between the inputs and the output. .. function:: void nmod_poly_mul(nmod_poly_t res, const nmod_poly_t poly, const nmod_poly_t poly2) Sets ``res`` to the product of ``poly1`` and ``poly2``. .. function:: void _nmod_poly_mullow(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) Sets ``res`` to the first ``n`` coefficients of the product of ``poly1`` of length ``len1`` and ``poly2`` of length ``len2``. It is assumed that ``0 < n <= len1 + len2 - 1`` and that ``len1 >= len2 > 0``. No aliasing of inputs and output is permitted. .. function:: void nmod_poly_mullow(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc) Sets ``res`` to the first ``trunc`` coefficients of the product of ``poly1`` and ``poly2``. .. function:: void _nmod_poly_mulhigh(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) Sets all but the low `n` coefficients of ``res`` to the corresponding coefficients of the product of ``poly1`` of length ``len1`` and ``poly2`` of length ``len2``, the other coefficients being arbitrary. It is assumed that ``len1 >= len2 > 0`` and that ``0 < n <= len1 + len2 - 1``. Aliasing of inputs and output is not permitted. .. function:: void nmod_poly_mulhigh(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) Sets all but the low `n` coefficients of ``res`` to the corresponding coefficients of the product of ``poly1`` and ``poly2``, the remaining coefficients being arbitrary. .. function:: void _nmod_poly_mulmod(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, mp_srcptr f, slong lenf, nmod_t mod) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``len1 + len2 - lenf > 0``, which is equivalent to requiring that the result will actually be reduced. Otherwise, simply use ``_nmod_poly_mul`` instead. Aliasing of ``f`` and ``res`` is not permitted. .. function:: void nmod_poly_mulmod(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. .. function:: void _nmod_poly_mulmod_preinv(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. It is required that ``finv`` is the inverse of the reverse of ``f`` mod ``x^lenf``. It is required that ``len1 + len2 - lenf > 0``, which is equivalent to requiring that the result will actually be reduced. It is required that ``len1 < lenf`` and ``len2 < lenf``. Otherwise, simply use ``_nmod_poly_mul`` instead. Aliasing of ```res`` with any of the inputs is not permitted. .. function:: void nmod_poly_mulmod_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f, const nmod_poly_t finv) Sets ``res`` to the remainder of the product of ``poly1`` and ``poly2`` upon polynomial division by ``f``. ``finv`` is the inverse of the reverse of ``f``. It is required that ``poly1`` and ``poly2`` are reduced modulo ``f``. Powering -------------------------------------------------------------------------------- .. function:: void _nmod_poly_pow_binexp(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod) Raises ``poly`` of length ``len`` to the power ``e`` and sets ``res`` to the result. We require that ``res`` has enough space for ``(len - 1)*e + 1`` coefficients. Assumes that ``len > 0``, ``e > 1``. Aliasing is not permitted. Uses the binary exponentiation method. .. function:: void nmod_poly_pow_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e) Raises ``poly`` to the power ``e`` and sets ``res`` to the result. Uses the binary exponentiation method. .. function:: void _nmod_poly_pow(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod) Raises ``poly`` of length ``len`` to the power ``e`` and sets ``res`` to the result. We require that ``res`` has enough space for ``(len - 1)*e + 1`` coefficients. Assumes that ``len > 0``, ``e > 1``. Aliasing is not permitted. .. function:: void nmod_poly_pow(nmod_poly_t res, const nmod_poly_t poly, ulong e) Raises ``poly`` to the power ``e`` and sets ``res`` to the result. .. function:: void _nmod_poly_pow_trunc_binexp(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. Uses the binary exponentiation method. .. function:: void nmod_poly_pow_trunc_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. Uses the binary exponentiation method. .. function:: void _nmod_poly_pow_trunc(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` (assumed to be zero padded if necessary to length ``trunc``) to the power ``e``. This is equivalent to doing a powering followed by a truncation. We require that ``res`` has enough space for ``trunc`` coefficients, that ``trunc > 0`` and that ``e > 1``. Aliasing is not permitted. .. function:: void nmod_poly_pow_trunc(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc) Sets ``res`` to the low ``trunc`` coefficients of ``poly`` to the power ``e``. This is equivalent to doing a powering followed by a truncation. .. function:: void _nmod_poly_powmod_ui_binexp(mp_ptr res, mp_srcptr poly, ulong e, mp_srcptr f, slong lenf, nmod_t mod) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void nmod_poly_powmod_ui_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, const nmod_poly_t f) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _nmod_poly_powmod_fmpz_binexp(mp_ptr res, mp_srcptr poly, fmpz_t e, mp_srcptr f, slong lenf, nmod_t mod) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void nmod_poly_powmod_fmpz_binexp(nmod_poly_t res, const nmod_poly_t poly, fmpz_t e, const nmod_poly_t f) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. .. function:: void _nmod_poly_powmod_ui_binexp_preinv (mp_ptr res, mp_srcptr poly, ulong e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void nmod_poly_powmod_ui_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, ulong e, const nmod_poly_t f, const nmod_poly_t finv) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _nmod_poly_powmod_fmpz_binexp_preinv (mp_ptr res, mp_srcptr poly, fmpz_t e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 1``. It is assumed that ``poly`` is already reduced modulo ``f`` and zero-padded as necessary to have length exactly ``lenf - 1``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void nmod_poly_powmod_fmpz_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, fmpz_t e, const nmod_poly_t f, const nmod_poly_t finv) Sets ``res`` to ``poly`` raised to the power ``e`` modulo ``f``, using binary exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _nmod_poly_powmod_x_ui_preinv (mp_ptr res, ulong e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 2``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void nmod_poly_powmod_x_ui_preinv(nmod_poly_t res, ulong e, const nmod_poly_t f, const nmod_poly_t finv) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _nmod_poly_powmod_x_fmpz_preinv (mp_ptr res, fmpz_t e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e > 0``. We require ``finv`` to be the inverse of the reverse of ``f``. We require ``lenf > 2``. The output ``res`` must have room for ``lenf - 1`` coefficients. .. function:: void nmod_poly_powmod_x_fmpz_preinv(nmod_poly_t res, fmpz_t e, const nmod_poly_t f, const nmod_poly_t finv) Sets ``res`` to ``x`` raised to the power ``e`` modulo ``f``, using sliding window exponentiation. We require ``e >= 0``. We require ``finv`` to be the inverse of the reverse of ``f``. .. function:: void _nmod_poly_powers_mod_preinv_naive(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod) Compute ``f^0, f^1, ..., f^(n-1) mod g``, where ``g`` has length ``glen`` and ``f`` is reduced mod ``g`` and has length ``flen`` (possibly zero spaced). Assumes ``res`` is an array of ``n`` arrays each with space for at least ``glen - 1`` coefficients and that ``flen > 0``. We require that ``ginv`` of length ``ginvlen`` is set to the power series inverse of the reverse of ``g``. .. function:: void nmod_poly_powers_mod_naive(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g) Set the entries of the array ``res`` to ``f^0, f^1, ..., f^(n-1) mod g``. No aliasing is permitted between the entries of ``res`` and either of the inputs. .. function:: void _nmod_poly_powers_mod_preinv_threaded_pool(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod, thread_pool_handle * threads, slong num_threads) Compute ``f^0, f^1, ..., f^(n-1) mod g``, where ``g`` has length ``glen`` and ``f`` is reduced mod ``g`` and has length ``flen`` (possibly zero spaced). Assumes ``res`` is an array of ``n`` arrays each with space for at least ``glen - 1`` coefficients and that ``flen > 0``. We require that ``ginv`` of length ``ginvlen`` is set to the power series inverse of the reverse of ``g``. .. function:: void _nmod_poly_powers_mod_preinv_threaded(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod) Compute ``f^0, f^1, ..., f^(n-1) mod g``, where ``g`` has length ``glen`` and ``f`` is reduced mod ``g`` and has length ``flen`` (possibly zero spaced). Assumes ``res`` is an array of ``n`` arrays each with space for at least ``glen - 1`` coefficients and that ``flen > 0``. We require that ``ginv`` of length ``ginvlen`` is set to the power series inverse of the reverse of ``g``. .. function:: void nmod_poly_powers_mod_bsgs(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g) Set the entries of the array ``res`` to ``f^0, f^1, ..., f^(n-1) mod g``. No aliasing is permitted between the entries of ``res`` and either of the inputs. Division -------------------------------------------------------------------------------- .. function:: void _nmod_poly_divrem_basecase(mp_ptr Q, mp_ptr R, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) Finds `Q` and `R` such that `A = B Q + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. If `\operatorname{len}(B) = 0` an exception is raised. We require that ``W`` is temporary space of ``NMOD_DIVREM_BC_ITCH(A_len, B_len, mod)`` coefficients. .. function:: void nmod_poly_divrem_basecase(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) Finds `Q` and `R` such that `A = B Q + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. If `\operatorname{len}(B) = 0` an exception is raised. .. function:: void _nmod_poly_divrem(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where ``A`` is of length ``lenA`` and ``B`` is of length ``lenB``. We require that ``Q`` have space for ``lenA - lenB + 1`` coefficients. .. function:: void nmod_poly_divrem(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. .. function:: void _nmod_poly_div(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Notionally computes polynomials `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where ``A`` is of length ``lenA`` and ``B`` is of length ``lenB``, but returns only ``Q``. We require that ``Q`` have space for ``lenA - lenB + 1`` coefficients. .. function:: void nmod_poly_div(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) Computes the quotient `Q` on polynomial division of `A` and `B`. .. function:: void _nmod_poly_rem_q1(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) .. function:: void _nmod_poly_rem(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Computes the remainder `R` on polynomial division of `A` by `B`. .. function:: void nmod_poly_rem(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) Computes the remainder `R` on polynomial division of `A` by `B`. .. function:: void _nmod_poly_divexact(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) void nmod_poly_divexact(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) Computes the quotient `Q` of `A` and `B` assuming that the division is exact. .. function:: void _nmod_poly_inv_series_basecase(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) Given ``Q`` of length ``Qlen`` whose leading coefficient is invertible modulo the given modulus, finds a polynomial ``Qinv`` of length ``n`` such that the top ``n`` coefficients of the product ``Q * Qinv`` is `x^{n - 1}`. Requires that ``n > 0``. This function can be viewed as inverting a power series. .. function:: void nmod_poly_inv_series_basecase(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) Given ``Q`` of length at least ``n`` find ``Qinv`` of length ``n`` such that the top ``n`` coefficients of the product ``Q * Qinv`` is `x^{n - 1}`. An exception is raised if ``n = 0`` or if the length of ``Q`` is less than ``n``. The leading coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. This function can be viewed as inverting a power series. .. function:: void _nmod_poly_inv_series_newton(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) Given ``Q`` of length ``Qlen`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void nmod_poly_inv_series_newton(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. This function can be viewed as inverting a power series via Newton iteration. .. function:: void _nmod_poly_inv_series(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) Given ``Q`` of length ``Qlenn`` whose constant coefficient is invertible modulo the given modulus, find a polynomial ``Qinv`` of length ``n`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. Requires ``n > 0``. This function can be viewed as inverting a power series. .. function:: void nmod_poly_inv_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) Given ``Q`` find ``Qinv`` such that ``Q * Qinv`` is ``1`` modulo `x^n`. The constant coefficient of ``Q`` must be invertible modulo the modulus of ``Q``. An exception is raised if this is not the case or if ``n = 0``. This function can be viewed as inverting a power series. .. function:: void _nmod_poly_div_series_basecase(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, slong n, nmod_t mod) Given polynomials ``A`` and ``B`` of length ``Alen`` and ``Blen``, finds the polynomial ``Q`` of length ``n`` such that ``Q * B = A`` modulo `x^n`. We assume ``n > 0`` and that the constant coefficient of ``B`` is invertible modulo the given modulus. The polynomial ``Q`` must have space for ``n`` coefficients. .. function:: void nmod_poly_div_series_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n) Given polynomials ``A`` and ``B`` considered modulo ``n``, finds the polynomial ``Q`` of length at most ``n`` such that ``Q * B = A`` modulo `x^n`. We assume ``n > 0`` and that the constant coefficient of ``B`` is invertible modulo the modulus. An exception is raised if ``n == 0`` or the constant coefficient of ``B`` is zero. .. function:: void _nmod_poly_div_series(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, slong n, nmod_t mod) Given polynomials ``A`` and ``B`` of length ``Alen`` and ``Blen``, finds the polynomial ``Q`` of length ``n`` such that ``Q * B = A`` modulo `x^n`. We assume ``n > 0`` and that the constant coefficient of ``B`` is invertible modulo the given modulus. The polynomial ``Q`` must have space for ``n`` coefficients. .. function:: void nmod_poly_div_series(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n) Given polynomials ``A`` and ``B`` considered modulo ``n``, finds the polynomial ``Q`` of length at most ``n`` such that ``Q * B = A`` modulo `x^n`. We assume ``n > 0`` and that the constant coefficient of ``B`` is invertible modulo the modulus. An exception is raised if ``n == 0`` or the constant coefficient of ``B`` is zero. .. function:: void _nmod_poly_div_newton_n_preinv (mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_srcptr Binv, slong lenBinv, nmod_t mod) Notionally computes polynomials `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where ``A`` is of length ``lenA`` and ``B`` is of length ``lenB``, but return only `Q`. We require that `Q` have space for ``lenA - lenB + 1`` coefficients and assume that the leading coefficient of `B` is a unit. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void nmod_poly_div_newton_n_preinv (nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t Binv) Notionally computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only `Q`. We assume that the leading coefficient of `B` is a unit and that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void _nmod_poly_divrem_newton_n_preinv (mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_srcptr Binv, slong lenBinv, nmod_t mod) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R)` less than ``lenB``, where `A` is of length ``lenA`` and `B` is of length ``lenB``. We require that `Q` have space for ``lenA - lenB + 1`` coefficients. Furthermore, we assume that `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. The algorithm used is to call :func:`div_newton_n_preinv` and then multiply out and compute the remainder. .. function:: void nmod_poly_divrem_newton_n_preinv(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t Binv) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`. We assume `Binv` is the inverse of the reverse of `B` mod `x^{\operatorname{len}(B)}`. It is required that the length of `A` is less than or equal to 2*the length of `B` - 2. The algorithm used is to call :func:`div_newton_n` and then multiply out and compute the remainder. .. function:: mp_limb_t _nmod_poly_div_root(mp_ptr Q, mp_srcptr A, slong len, mp_limb_t c, nmod_t mod) Sets ``(Q, len-1)`` to the quotient of ``(A, len)`` on division by `(x - c)`, and returns the remainder, equal to the value of `A` evaluated at `c`. `A` and `Q` are allowed to be the same, but may not overlap partially in any other way. .. function:: mp_limb_t nmod_poly_div_root(nmod_poly_t Q, const nmod_poly_t A, mp_limb_t c) Sets `Q` to the quotient of `A` on division by `(x - c)`, and returns the remainder, equal to the value of `A` evaluated at `c`. Divisibility testing -------------------------------------------------------------------------------- .. function:: int _nmod_poly_divides_classical(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Returns `1` if `(B, lenB)` divides `(A, lenA)` and sets `(Q, lenA - lenB + 1)` to the quotient. Otherwise, returns `0` and sets `(Q, lenA - lenB + 1)` to zero. We require that `lenA >= lenB > 0`. .. function:: int nmod_poly_divides_classical(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) Returns `1` if `B` divides `A` and sets `Q` to the quotient. Otherwise returns `0` and sets `Q` to zero. .. function:: int _nmod_poly_divides(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Returns `1` if `(B, lenB)` divides `(A, lenA)` and sets `(Q, lenA - lenB + 1)` to the quotient. Otherwise, returns `0` and sets `(Q, lenA - lenB + 1)` to zero. We require that `lenA >= lenB > 0`. .. function:: int nmod_poly_divides(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) Returns `1` if `B` divides `A` and sets `Q` to the quotient. Otherwise returns `0` and sets `Q` to zero. .. function:: ulong nmod_poly_remove(nmod_poly_t f, const nmod_poly_t p) Removes the highest possible power of ``p`` from ``f`` and returns the exponent. Derivative and integral -------------------------------------------------------------------------------- .. function:: void _nmod_poly_derivative(mp_ptr x_prime, mp_srcptr x, slong len, nmod_t mod) Sets the first ``len - 1`` coefficients of ``x_prime`` to the derivative of ``x`` which is assumed to be of length ``len``. It is assumed that ``len > 0``. .. function:: void nmod_poly_derivative(nmod_poly_t x_prime, const nmod_poly_t x) Sets ``x_prime`` to the derivative of ``x``. .. function:: void _nmod_poly_integral(mp_ptr x_int, mp_srcptr x, slong len, nmod_t mod) Set the first ``len`` coefficients of ``x_int`` to the integral of ``x`` which is assumed to be of length ``len - 1``. The constant term of ``x_int`` is set to zero. It is assumed that ``len > 0``. The result is only well-defined if the modulus is a prime number strictly larger than the degree of ``x``. Supports aliasing between the two polynomials. .. function:: void nmod_poly_integral(nmod_poly_t x_int, const nmod_poly_t x) Set ``x_int`` to the indefinite integral of ``x`` with constant term zero. The result is only well-defined if the modulus is a prime number strictly larger than the degree of ``x``. Evaluation -------------------------------------------------------------------------------- .. function:: mp_limb_t _nmod_poly_evaluate_nmod(mp_srcptr poly, slong len, mp_limb_t c, nmod_t mod) Evaluates ``poly`` at the value ``c`` and reduces modulo the given modulus of ``poly``. The value ``c`` should be reduced modulo the modulus. The algorithm used is Horner's method. .. function:: mp_limb_t nmod_poly_evaluate_nmod(const nmod_poly_t poly, mp_limb_t c) Evaluates ``poly`` at the value ``c`` and reduces modulo the modulus of ``poly``. The value ``c`` should be reduced modulo the modulus. The algorithm used is Horner's method. .. function:: void nmod_poly_evaluate_mat_horner(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c) Evaluates ``poly`` with matrix as an argument at the value ``c`` and stores the result in ``dest``. The dimension and modulus of ``dest`` is assumed to be same as that of ``c``. ``dest`` and ``c`` may be aliased. Horner's Method is used to compute the result. .. function:: void nmod_poly_evaluate_mat_paterson_stockmeyer(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c) Evaluates ``poly`` with matrix as an argument at the value ``c`` and stores the result in ``dest``. The dimension and modulus of ``dest`` is assumed to be same as that of ``c``. ``dest`` and ``c`` may be aliased. Paterson-Stockmeyer algorithm is used to compute the result. The algorithm is described in [Paterson1973]_. .. function:: void nmod_poly_evaluate_mat(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c) Evaluates ``poly`` with matrix as an argument at the value ``c`` and stores the result in ``dest``. The dimension and modulus of ``dest`` is assumed to be same as that of ``c``. ``dest`` and ``c`` may be aliased. This function automatically switches between Horner's method and the Paterson-Stockmeyer algorithm. Multipoint evaluation -------------------------------------------------------------------------------- .. function:: void _nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, mp_srcptr poly, slong len, mp_srcptr xs, slong n, nmod_t mod) Evaluates (``coeffs``, ``len``) at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses Horner's method iteratively. .. function:: void nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n) Evaluates ``poly`` at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses Horner's method iteratively. .. function:: void _nmod_poly_evaluate_nmod_vec_fast_precomp(mp_ptr vs, mp_srcptr poly, slong plen, const mp_ptr * tree, slong len, nmod_t mod) Evaluates (``poly``, ``plen``) at the ``len`` values given by the precomputed subproduct tree ``tree``. .. function:: void _nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, mp_srcptr poly, slong len, mp_srcptr xs, slong n, nmod_t mod) Evaluates (``coeffs``, ``len``) at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses fast multipoint evaluation, building a temporary subproduct tree. .. function:: void nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n) Evaluates ``poly`` at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Uses fast multipoint evaluation, building a temporary subproduct tree. .. function:: void _nmod_poly_evaluate_nmod_vec(mp_ptr ys, mp_srcptr poly, slong len, mp_srcptr xs, slong n, nmod_t mod) Evaluates (``poly``, ``len``) at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. .. function:: void nmod_poly_evaluate_nmod_vec(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n) Evaluates ``poly`` at the ``n`` values given in the vector ``xs``, writing the output values to ``ys``. The values in ``xs`` should be reduced modulo the modulus. Interpolation -------------------------------------------------------------------------------- .. function:: void _nmod_poly_interpolate_nmod_vec(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) Sets ``poly`` to the unique polynomial of length at most ``n`` that interpolates the ``n`` given evaluation points ``xs`` and values ``ys``. If the interpolating polynomial is shorter than length ``n``, the leading coefficients are set to zero. The values in ``xs`` and ``ys`` should be reduced modulo the modulus, and all ``xs`` must be distinct. Aliasing between ``poly`` and ``xs`` or ``ys`` is not allowed. .. function:: void nmod_poly_interpolate_nmod_vec(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) Sets ``poly`` to the unique polynomial of length ``n`` that interpolates the ``n`` given evaluation points ``xs`` and values ``ys``. The values in ``xs`` and ``ys`` should be reduced modulo the modulus, and all ``xs`` must be distinct. .. function:: void _nmod_poly_interpolation_weights(mp_ptr w, const mp_ptr * tree, slong len, nmod_t mod) Sets ``w`` to the barycentric interpolation weights for fast Lagrange interpolation with respect to a given subproduct tree. .. function:: void _nmod_poly_interpolate_nmod_vec_fast_precomp(mp_ptr poly, mp_srcptr ys, const mp_ptr * tree, mp_srcptr weights, slong len, nmod_t mod) Performs interpolation using the fast Lagrange interpolation algorithm, generating a temporary subproduct tree. The function values are given as ``ys``. The function takes a precomputed subproduct tree ``tree`` and barycentric interpolation weights ``weights`` corresponding to the roots. .. function:: void _nmod_poly_interpolate_nmod_vec_fast(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) Performs interpolation using the fast Lagrange interpolation algorithm, generating a temporary subproduct tree. .. function:: void nmod_poly_interpolate_nmod_vec_fast(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) Performs interpolation using the fast Lagrange interpolation algorithm, generating a temporary subproduct tree. .. function:: void _nmod_poly_interpolate_nmod_vec_newton(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) Forms the interpolating polynomial in the Newton basis using the method of divided differences and then converts it to monomial form. .. function:: void nmod_poly_interpolate_nmod_vec_newton(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) Forms the interpolating polynomial in the Newton basis using the method of divided differences and then converts it to monomial form. .. function:: void _nmod_poly_interpolate_nmod_vec_barycentric(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) Forms the interpolating polynomial using a naive implementation of the barycentric form of Lagrange interpolation. .. function:: void nmod_poly_interpolate_nmod_vec_barycentric(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) Forms the interpolating polynomial using a naive implementation of the barycentric form of Lagrange interpolation. Composition -------------------------------------------------------------------------------- .. function:: void _nmod_poly_compose_horner(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Composes ``poly1`` of length ``len1`` with ``poly2`` of length ``len2`` and sets ``res`` to the result, i.e. evaluates ``poly1`` at ``poly2``. The algorithm used is Horner's algorithm. We require that ``res`` have space for ``(len1 - 1)*(len2 - 1) + 1`` coefficients. It is assumed that ``len1 > 0`` and ``len2 > 0``. .. function:: void nmod_poly_compose_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Composes ``poly1`` with ``poly2`` and sets ``res`` to the result, i.e. evaluates ``poly1`` at ``poly2``. The algorithm used is Horner's algorithm. .. function:: void _nmod_poly_compose_divconquer(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Composes ``poly1`` of length ``len1`` with ``poly2`` of length ``len2`` and sets ``res`` to the result, i.e. evaluates ``poly1`` at ``poly2``. The algorithm used is the divide and conquer algorithm. We require that ``res`` have space for ``(len1 - 1)*(len2 - 1) + 1`` coefficients. It is assumed that ``len1 > 0`` and ``len2 > 0``. .. function:: void nmod_poly_compose_divconquer(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Composes ``poly1`` with ``poly2`` and sets ``res`` to the result, i.e. evaluates ``poly1`` at ``poly2``. The algorithm used is the divide and conquer algorithm. .. function:: void _nmod_poly_compose(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Composes ``poly1`` of length ``len1`` with ``poly2`` of length ``len2`` and sets ``res`` to the result, i.e. evaluates ``poly1`` at ``poly2``. We require that ``res`` have space for ``(len1 - 1)*(len2 - 1) + 1`` coefficients. It is assumed that ``len1 > 0`` and ``len2 > 0``. .. function:: void nmod_poly_compose(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) Composes ``poly1`` with ``poly2`` and sets ``res`` to the result, that is, evaluates ``poly1`` at ``poly2``. Taylor shift -------------------------------------------------------------------------------- .. function:: void _nmod_poly_taylor_shift_horner(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod) Performs the Taylor shift composing ``poly`` by `x+c` in-place. Uses an efficient version Horner's rule. .. function:: void nmod_poly_taylor_shift_horner(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c) Performs the Taylor shift composing ``f`` by `x+c`. .. function:: void _nmod_poly_taylor_shift_convolution(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod) Performs the Taylor shift composing ``poly`` by `x+c` in-place. Writes the composition as a single convolution with cost `O(M(n))`. We require that the modulus is a prime at least as large as the length. .. function:: void nmod_poly_taylor_shift_convolution(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c) Performs the Taylor shift composing ``f`` by `x+c`. Writes the composition as a single convolution with cost `O(M(n))`. We require that the modulus is a prime at least as large as the length. .. function:: void _nmod_poly_taylor_shift(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod) Performs the Taylor shift composing ``poly`` by `x+c` in-place. We require that the modulus is a prime. .. function:: void nmod_poly_taylor_shift(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c) Performs the Taylor shift composing ``f`` by `x+c`. We require that the modulus is a prime. Modular composition -------------------------------------------------------------------------------- .. function:: void _nmod_poly_compose_mod_horner(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. The algorithm used is Horner's rule. .. function:: void nmod_poly_compose_mod_horner(nmod_poly_t res, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t h) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. The algorithm used is Horner's rule. .. function:: void _nmod_poly_compose_mod_brent_kung(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void nmod_poly_compose_mod_brent_kung(nmod_poly_t res, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t h) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _nmod_poly_compose_mod_brent_kung_preinv(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, mp_srcptr hinv, slong lenhinv, nmod_t mod) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void nmod_poly_compose_mod_brent_kung_preinv(nmod_poly_t res, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t h, const nmod_poly_t hinv) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _nmod_poly_reduce_matrix_mod_poly (nmod_mat_t A, const nmod_mat_t B, const nmod_poly_t f) Sets the ith row of ``A`` to the reduction of the ith row of `B` modulo `f` for `i=1,\ldots,\sqrt{\deg(f)}`. We require `B` to be at least a `\sqrt{\deg(f)}\times \deg(f)` matrix and `f` to be nonzero. .. function:: void _nmod_poly_precompute_matrix_worker (void * arg_ptr) Worker function version of ``_nmod_poly_precompute_matrix``. Input/output is stored in ``nmod_poly_matrix_precompute_arg_t``. .. function:: void _nmod_poly_precompute_matrix (nmod_mat_t A, mp_srcptr f, mp_srcptr g, slong leng, mp_srcptr ginv, slong lenginv, nmod_t mod) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g`` and `g` to be nonzero. ``f`` has to be reduced modulo ``g`` and of length one less than ``leng`` (possibly with zero padding). .. function:: void nmod_poly_precompute_matrix (nmod_mat_t A, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t ginv) Sets the ith row of ``A`` to `f^i` modulo `g` for `i=1,\ldots,\sqrt{\deg(g)}`. We require `A` to be a `\sqrt{\deg(g)}\times \deg(g)` matrix. We require ``ginv`` to be the inverse of the reverse of ``g``. .. function:: void _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr) Worker function version of ``_nmod_poly_compose_mod_brent_kung_precomp_preinv``. Input/output is stored in ``nmod_poly_compose_mod_precomp_preinv_arg_t``. .. function:: void _nmod_poly_compose_mod_brent_kung_precomp_preinv(mp_ptr res, mp_srcptr f, slong lenf, const nmod_mat_t A, mp_srcptr h, slong lenh, mp_srcptr hinv, slong lenhinv, nmod_t mod) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We also require that the length of `f` is less than the length of `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void nmod_poly_compose_mod_brent_kung_precomp_preinv(nmod_poly_t res, const nmod_poly_t f, const nmod_mat_t A, const nmod_poly_t h, const nmod_poly_t hinv) Sets ``res`` to the composition `f(g)` modulo `h`. We require that the ith row of `A` contains `g^i` for `i=1,\ldots,\sqrt{\deg(h)}`, i.e. `A` is a `\sqrt{\deg(h)}\times \deg(h)` matrix. We require that `h` is nonzero and that `f` has smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. This version of Brent-Kung modular composition is particularly useful if one has to perform several modular composition of the form `f(g)` modulo `h` for fixed `g` and `h`. .. function:: void _nmod_poly_compose_mod_brent_kung_vec_preinv(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong l, mp_srcptr g, slong leng, mp_srcptr h, slong lenh, mp_srcptr hinv, slong lenhinv, nmod_t mod) Sets ``res`` to the composition `f_i(g)` modulo `h` for `1\leq i \leq l`, where `f_i` are the first ``l`` elements of ``polys``. We require that `h` is nonzero and that the length of `g` is less than the length of `h`. We also require that the length of `f_i` is less than the length of `h`. We require ``res`` to have enough memory allocated to hold ``l`` ``nmod_poly_struct``'s. The entries of ``res`` need to be initialised and ``l`` needs to be less than ``len1`` Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. The output is not allowed to be aliased with any of the inputs. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void nmod_poly_compose_mod_brent_kung_vec_preinv(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t h, const nmod_poly_t hinv) Sets ``res`` to the composition `f_i(g)` modulo `h` for `1\leq i \leq n` where `f_i` are the first ``n`` elements of ``polys``. We require ``res`` to have enough memory allocated to hold ``n`` ``nmod_poly_struct``. The entries of ``res`` need to be initialised and ``n`` needs to be less than ``len1``. We require that `h` is nonzero and that `f_i` and `g` have smaller degree than `h`. Furthermore, we require ``hinv`` to be the inverse of the reverse of ``h``. No aliasing of ``res`` and ``polys`` is allowed. The algorithm used is the Brent-Kung matrix algorithm. .. function:: void _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(nmod_poly_struct * res, const nmod_poly_struct * polys, slong lenpolys, slong l, mp_srcptr g, slong glen, mp_srcptr poly, slong len, mp_srcptr polyinv, slong leninv, nmod_t mod, thread_pool_handle * threads, slong num_threads) Multithreaded version of :func:`_nmod_poly_compose_mod_brent_kung_vec_preinv`. Distributing the Horner evaluations across :func:`flint_get_num_threads` threads. .. function:: void nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv, thread_pool_handle * threads, slong num_threads) Multithreaded version of :func:`nmod_poly_compose_mod_brent_kung_vec_preinv`. Distributing the Horner evaluations across :func:`flint_get_num_threads` threads. .. function:: void nmod_poly_compose_mod_brent_kung_vec_preinv_threaded(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv) Multithreaded version of :func:`nmod_poly_compose_mod_brent_kung_vec_preinv`. Distributing the Horner evaluations across :func:`flint_get_num_threads` threads. .. function:: void _nmod_poly_compose_mod(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero and that the length of `g` is one less than the length of `h` (possibly with zero padding). The output is not allowed to be aliased with any of the inputs. .. function:: void nmod_poly_compose_mod(nmod_poly_t res, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t h) Sets ``res`` to the composition `f(g)` modulo `h`. We require that `h` is nonzero. Greatest common divisor -------------------------------------------------------------------------------- .. function:: slong _nmod_poly_gcd_euclidean(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Computes the GCD of `A` of length ``lenA`` and `B` of length ``lenB``, where ``lenA >= lenB > 0``. The length of the GCD `G` is returned by the function. No attempt is made to make the GCD monic. It is required that `G` have space for ``lenB`` coefficients. .. function:: void nmod_poly_gcd_euclidean(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. .. function:: slong _nmod_poly_hgcd(mp_ptr * M, slong * lenM, mp_ptr A, slong * lenA, mp_ptr B, slong * lenB, mp_srcptr a, slong lena, mp_srcptr b, slong lenb, nmod_t mod) Computes the HGCD of `a` and `b`, that is, a matrix `M`, a sign `\sigma` and two polynomials `A` and `B` such that .. math:: (A,B)^t = M^{-1} (a,b)^t, \sigma = \det(M), and `A` and `B` are consecutive remainders in the Euclidean remainder sequence for the division of `a` by `b` satisfying \deg(A) \ge \frac{\deg(a)}{2} > \deg(B). Furthermore, `M` will be the product of ``[[q 1][1 0]]`` for the quotients ``q`` generated by such a remainder sequence. Assumes that `\operatorname{len}(a) > \operatorname{len}(b) > 0`, i.e. `\deg(a) > `deg(b) > 1`. Assumes that `A` and `B` have space of size at least `\operatorname{len}(a)` and `\operatorname{len}(b)`, respectively. On exit, ``*lenA`` and ``*lenB`` will contain the correct lengths of `A` and `B`. Assumes that ``M[0]``, ``M[1]``, ``M[2]``, and ``M[3]`` each point to a vector of size at least `\operatorname{len}(a)`. .. function:: slong _nmod_poly_gcd_hgcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Computes the monic GCD of `A` and `B`, assuming that `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`. Assumes that `G` has space for `\operatorname{len}(B)` coefficients and returns the length of `G` on output. .. function:: void nmod_poly_gcd_hgcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B) Computes the monic GCD of `A` and `B` using the HGCD algorithm. As a special case, the GCD of two zero polynomials is defined to be the zero polynomial. The time complexity of the algorithm is `\mathcal{O}(n \log^2 n)`. For further details, see [ThullYap1990]_. .. function:: slong _nmod_poly_gcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Computes the GCD of `A` of length ``lenA`` and `B` of length ``lenB``, where ``lenA >= lenB > 0``. The length of the GCD `G` is returned by the function. No attempt is made to make the GCD monic. It is required that `G` have space for ``lenB`` coefficients. .. function:: void nmod_poly_gcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. .. function:: slong _nmod_poly_xgcd_euclidean(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) Computes the GCD of `A` and `B` together with cofactors `S` and `T` such that `S A + T B = G`. Returns the length of `G`. Assumes that `\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1` and `(\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B)-1` and `\operatorname{len}(A)-1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)` and `\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)`. No aliasing of input and output operands is permitted. .. function:: void nmod_poly_xgcd_euclidean(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. .. function:: slong _nmod_poly_xgcd_hgcd(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) Computes the GCD of `A` and `B`, where `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`, together with cofactors `S` and `T` such that `S A + T B = G`. Returns the length of `G`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B) - 1` and `\operatorname{len}(A) - 1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \operatorname{len}(B) - \operatorname{len}(G)` and `\operatorname{len}(T) \leq \operatorname{len}(A) - \operatorname{len}(G)`. Both `S` and `T` must have space for at least `2` coefficients. No aliasing of input and output operands is permitted. .. function:: void nmod_poly_xgcd_hgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. Polynomials ``S`` and ``T`` are computed such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. .. function:: slong _nmod_poly_xgcd(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Computes the GCD of `A` and `B`, where `\operatorname{len}(A) \geq \operatorname{len}(B) > 0`, together with cofactors `S` and `T` such that `S A + T B = G`. Returns the length of `G`. No attempt is made to make the GCD monic. Requires that `G` have space for `\operatorname{len}(B)` coefficients. Writes `\operatorname{len}(B) - 1` and `\operatorname{len}(A) - 1` coefficients to `S` and `T`, respectively. Note that, in fact, `\operatorname{len}(S) \leq \operatorname{len}(B) - \operatorname{len}(G)` and `\operatorname{len}(T) \leq \operatorname{len}(A) - \operatorname{len}(G)`. No aliasing of input and output operands is permitted. .. function:: void nmod_poly_xgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) Computes the GCD of `A` and `B`. The GCD of zero polynomials is defined to be zero, whereas the GCD of the zero polynomial and some other polynomial `P` is defined to be `P`. Except in the case where the GCD is zero, the GCD `G` is made monic. The polynomials ``S`` and ``T`` are set such that ``S*A + T*B = G``. The length of ``S`` will be at most ``lenB`` and the length of ``T`` will be at most ``lenA``. .. function:: mp_limb_t _nmod_poly_resultant_euclidean(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Returns the resultant of ``(poly1, len1)`` and ``(poly2, len2)`` using the Euclidean algorithm. Assumes that ``len1 >= len2 > 0``. Assumes that the modulus is prime. .. function:: mp_limb_t nmod_poly_resultant_euclidean(const nmod_poly_t f, const nmod_poly_t g) Computes the resultant of `f` and `g` using the Euclidean algorithm. For two non-zero polynomials `f(x) = a_m x^m + \dotsb + a_0` and `g(x) = b_n x^n + \dotsb + b_0` of degrees `m` and `n`, the resultant is defined to be .. math:: a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y). For convenience, we define the resultant to be equal to zero if either of the two polynomials is zero. .. function:: mp_limb_t _nmod_poly_resultant_hgcd(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Returns the resultant of ``(poly1, len1)`` and ``(poly2, len2)`` using the half-gcd algorithm. This algorithm computes the half-gcd as per :func:`_nmod_poly_gcd_hgcd` but additionally updates the resultant every time a division occurs. The half-gcd algorithm computes the GCD recursively. Given inputs `a` and `b` it lets ``m = len(a)/2`` and (recursively) performs all quotients in the Euclidean algorithm which do not require the low `m` coefficients of `a` and `b`. This performs quotients in exactly the same order as the ordinary Euclidean algorithm except that the low `m` coefficients of the polynomials in the remainder sequence are not computed. A correction step after hgcd has been called computes these low `m` coefficients (by matrix multiplication by a transformation matrix also computed by hgcd). This means that from the point of view of the resultant, all but the last quotient performed by a recursive call to hgcd is an ordinary quotient as per the usual Euclidean algorithm. However, the final quotient may give a remainder of less than `m + 1` coefficients, which won't be corrected until the hgcd correction step is performed afterwards. To compute the adjustments to the resultant coming from this corrected quotient, we save the relevant information in an :type:`nmod_poly_res_t` struct at the time the quotient is performed so that when the correction step is performed later, the adjustments to the resultant can be computed at that time also. The only time an adjustment to the resultant is not required after a call to hgcd is if hgcd does nothing (the remainder may already have had less than `m + 1` coefficients when hgcd was called). Assumes that ``len1 >= len2 > 0``. Assumes that the modulus is prime. .. function:: mp_limb_t nmod_poly_resultant_hgcd(const nmod_poly_t f, const nmod_poly_t g) Computes the resultant of `f` and `g` using the half-gcd algorithm. For two non-zero polynomials `f(x) = a_m x^m + \dotsb + a_0` and `g(x) = b_n x^n + \dotsb + b_0` of degrees `m` and `n`, the resultant is defined to be .. math:: a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y). For convenience, we define the resultant to be equal to zero if either of the two polynomials is zero. .. function:: mp_limb_t _nmod_poly_resultant(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) Returns the resultant of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``len1 >= len2 > 0``. Assumes that the modulus is prime. .. function:: mp_limb_t nmod_poly_resultant(const nmod_poly_t f, const nmod_poly_t g) Computes the resultant of `f` and `g`. For two non-zero polynomials `f(x) = a_m x^m + \dotsb + a_0` and `g(x) = b_n x^n + \dotsb + b_0` of degrees `m` and `n`, the resultant is defined to be .. math:: a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y). For convenience, we define the resultant to be equal to zero if either of the two polynomials is zero. .. function:: slong _nmod_poly_gcdinv(mp_limb_t * G, mp_limb_t * S, const mp_limb_t * A, slong lenA, const mp_limb_t * B, slong lenB, const nmod_t mod) Computes ``(G, lenA)``, ``(S, lenB-1)`` such that `G \cong S A \pmod{B}`, returning the actual length of `G`. Assumes that `0 < \operatorname{len}(A) < \operatorname{len}(B)`. .. function:: void nmod_poly_gcdinv(nmod_poly_t G, nmod_poly_t S, const nmod_poly_t A, const nmod_poly_t B) Computes polynomials `G` and `S`, both reduced modulo `B`, such that `G \cong S A \pmod{B}`, where `B` is assumed to have `\operatorname{len}(B) \geq 2`. In the case that `A = 0 \pmod{B}`, returns `G = S = 0`. .. function:: int _nmod_poly_invmod(mp_limb_t * A, const mp_limb_t * B, slong lenB, const mp_limb_t * P, slong lenP, const nmod_t mod) Attempts to set ``(A, lenP-1)`` to the inverse of ``(B, lenB)`` modulo the polynomial ``(P, lenP)``. Returns `1` if ``(B, lenB)`` is invertible and `0` otherwise. Assumes that `0 < \operatorname{len}(B) < \operatorname{len}(P)`, and hence also `\operatorname{len}(P) \geq 2`, but supports zero-padding in ``(B, lenB)``. Does not support aliasing. Assumes that `mod` is a prime number. .. function:: int nmod_poly_invmod(nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t P) Attempts to set `A` to the inverse of `B` modulo `P` in the polynomial ring `(\mathbf{Z}/p\mathbf{Z})[X]`, where we assume that `p` is a prime number. If `\operatorname{len}(P) < 2`, raises an exception. If the greatest common divisor of `B` and `P` is `1`, returns `1` and sets `A` to the inverse of `B`. Otherwise, returns `0` and the value of `A` on exit is undefined. Discriminant -------------------------------------------------------------------------------- .. function:: mp_limb_t _nmod_poly_discriminant(mp_srcptr poly, slong len, nmod_t mod) Return the discriminant of ``(poly, len)``. Assumes ``len > 1``. .. function:: mp_limb_t nmod_poly_discriminant(const nmod_poly_t f) Return the discriminant of `f`. We normalise the discriminant so that `\operatorname{disc}(f) = (-1)^{n(n-1)/2} \operatorname{res}(f, f') / \operatorname{lc}(f)^{n - m - 2}`, where ``n = len(f)`` and ``m = len(f')``. Thus `\operatorname{disc}(f) = \operatorname{lc}(f)^{2n - 2} \prod_{i < j} (r_i - r_j)^2`, where `\operatorname{lc}(f)` is the leading coefficient of `f` and `r_i` are the roots of `f`. Power series composition -------------------------------------------------------------------------------- .. function:: void _nmod_poly_compose_series(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Assumes that ``len1, len2, n > 0``, that ``len1, len2 <= n``, and that ``(len1-1) * (len2-1) + 1 <= n``, and that ``res`` has space for ``n`` coefficients. Does not support aliasing between any of the inputs and the output. Wraps :func:`_gr_poly_compose_series` which chooses automatically between various algorithms. .. function:: void nmod_poly_compose_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) Sets ``res`` to the composition of ``poly1`` and ``poly2`` modulo `x^n`, where the constant term of ``poly2`` is required to be zero. Power series reversion -------------------------------------------------------------------------------- .. function:: void _nmod_poly_revert_series(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) void nmod_poly_revert_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) Sets ``Qinv`` to the compositional inverse or reversion of ``Q`` as a power series, i.e. computes `Q^{-1}` such that `Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n`. It is required that `Q_0 = 0` and that `Q_1` as well as the integers `1, 2, \ldots, n-1` are invertible modulo the modulus. Wraps :func:`_gr_poly_revert_series` which chooses automatically between various algorithms. Square roots -------------------------------------------------------------------------------- The series expansions for `\sqrt{h}` and `1/\sqrt{h}` are defined by means of the generalised binomial theorem ``h^r = (1+y)^r = \sum_{k=0}^{\infty} {r \choose k} y^k.`` It is assumed that `h` has constant term `1` and that the coefficients `2^{-k}` exist in the coefficient ring (i.e. `2` must be invertible). .. function:: void _nmod_poly_invsqrt_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set the first `n` terms of `g` to the series expansion of `1/\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1. Aliasing is not permitted. .. function:: void nmod_poly_invsqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g` to the series expansion of `1/\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: void _nmod_poly_sqrt_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set the first `n` terms of `g` to the series expansion of `\sqrt{h}`. It is assumed that `n > 0`, that `h` has constant term 1. Aliasing is not permitted. .. function:: void nmod_poly_sqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g` to the series expansion of `\sqrt{h}` to order `O(x^n)`. It is assumed that `h` has constant term 1. .. function:: int _nmod_poly_sqrt(mp_ptr s, mp_srcptr p, slong n, nmod_t mod) If ``(p, n)`` is a perfect square, sets ``(s, n / 2 + 1)`` to a square root of `p` and returns 1. Otherwise returns 0. .. function:: int nmod_poly_sqrt(nmod_poly_t s, const nmod_poly_t p) If `p` is a perfect square, sets `s` to a square root of `p` and returns 1. Otherwise returns 0. Power sums -------------------------------------------------------------------------------- .. function:: void _nmod_poly_power_sums_naive(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod) Compute the (truncated) power sums series of the polynomial ``(poly,len)`` up to length `n` using Newton identities. .. function:: void nmod_poly_power_sums_naive(nmod_poly_t res, const nmod_poly_t poly, slong n) Compute the (truncated) power sum series of the polynomial ``poly`` up to length `n` using Newton identities. .. function:: void _nmod_poly_power_sums_schoenhage(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod) Compute the (truncated) power sums series of the polynomial ``(poly,len)`` up to length `n` using a series expansion (a formula due to Schoenhage). .. function:: void nmod_poly_power_sums_schoenhage(nmod_poly_t res, const nmod_poly_t poly, slong n) Compute the (truncated) power sums series of the polynomial ``poly`` up to length `n` using a series expansion (a formula due to Schoenhage). .. function:: void _nmod_poly_power_sums(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod) Compute the (truncated) power sums series of the polynomial ``(poly,len)`` up to length `n`. .. function:: void nmod_poly_power_sums(nmod_poly_t res, const nmod_poly_t poly, slong n) Compute the (truncated) power sums series of the polynomial ``poly`` up to length `n`. .. function:: void _nmod_poly_power_sums_to_poly_naive(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod) Compute the (monic) polynomial given by its power sums series ``(poly,len)`` using Newton identities. .. function:: void nmod_poly_power_sums_to_poly_naive(nmod_poly_t res, const nmod_poly_t Q) Compute the (monic) polynomial given by its power sums series ``Q`` using Newton identities. .. function:: void _nmod_poly_power_sums_to_poly_schoenhage(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod) Compute the (monic) polynomial given by its power sums series ``(poly,len)`` using series expansion (a formula due to Schoenhage). .. function:: void nmod_poly_power_sums_to_poly_schoenhage(nmod_poly_t res, const nmod_poly_t Q) Compute the (monic) polynomial given by its power sums series ``Q`` using series expansion (a formula due to Schoenhage). .. function:: void _nmod_poly_power_sums_to_poly(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod) Compute the (monic) polynomial given by its power sums series ``(poly,len)``. .. function:: void nmod_poly_power_sums_to_poly(nmod_poly_t res, const nmod_poly_t Q) Compute the (monic) polynomial given by its power sums series ``Q``. Transcendental functions -------------------------------------------------------------------------------- The elementary transcendental functions of a formal power series `h` are defined as `\exp(h(x)) = \sum_{k=0}^{\infty} \frac{(h(x))^k}{k!}` `\log(h(x)) = \int_0^x \frac{h'(t)}{h(t)} dt` `\operatorname{atan}(h(x)) = \int_0^x\frac{h'(t)}{1+(h(t))^2} dt` `\operatorname{atanh}(h(x)) = \int_0^x\frac{h'(t)}{1-(h(t))^2} dt` `\operatorname{asin}(h(x)) = \int_0^x\frac{h'(t)}{\sqrt{1-(h(t))^2}} dt` `\operatorname{asinh}(h(x)) = \int_0^x\frac{h'(t)}{\sqrt{1+(h(t))^2}} dt` The functions sin, cos, tan, etc. are defined using standard inverse or functional relations. The logarithm function assumes that `h` has constant term `1`. All other functions assume that `h` has constant term `0`. All functions assume that the coefficient `1/k` or `1/k!` exists for all indices `k`. When computing to order `O(x^n)`, the modulus `p` must therefore be a prime satisfying `p \ge n`. Further, we always require that `p > 2` in order to be able to multiply by `1/2` for internal purposes. If the input does not satisfy all these conditions, results are undefined. Except where otherwise noted, functions are implemented with optimal (up to constants) complexity `O(M(n))`, where `M(n)` is the cost of polynomial multiplication. .. function:: void _nmod_poly_log_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `g = \log(h) + O(x^n)`. Assumes `n > 0` and ``hlen > 0``. Aliasing of `g` and `h` is allowed. .. function:: void nmod_poly_log_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \log(h) + O(x^n)`. The case `h = 1+cx^r` is automatically detected and handled efficiently. .. function:: void _nmod_poly_exp_series(mp_ptr f, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `f = \exp(h) + O(x^n)` where ``h`` is a polynomial. Assume `n > 0`. Aliasing of `g` and `h` is not allowed. Uses Newton iteration (an improved version of the algorithm in [HanZim2004]_). For small `n`, falls back to the basecase algorithm. .. function:: void _nmod_poly_exp_expinv_series(mp_ptr f, mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `f = \exp(h) + O(x^n)` and `g = \exp(-h) + O(x^n)`, more efficiently for large `n` than performing a separate inversion to obtain `g`. Assumes `n > 0` and that `h` is zero-padded as necessary to length `n`. Aliasing is not allowed. Uses Newton iteration (the version given in [HanZim2004]_). For small `n`, falls back to the basecase algorithm. .. function:: void nmod_poly_exp_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \exp(h) + O(x^n)`. The case `h = cx^r` is automatically detected and handled efficiently. Otherwise this function automatically uses the basecase algorithm for small `n` and Newton iteration otherwise. .. function:: void _nmod_poly_atan_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `g = \operatorname{atan}(h) + O(x^n)`. Assumes `n > 0`. Aliasing of `g` and `h` is allowed. .. function:: void nmod_poly_atan_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{atan}(h) + O(x^n)`. .. function:: void _nmod_poly_atanh_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `g = \operatorname{atanh}(h) + O(x^n)`. Assumes `n > 0`. Aliasing of `g` and `h` is allowed. .. function:: void nmod_poly_atanh_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{atanh}(h) + O(x^n)`. .. function:: void _nmod_poly_asin_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `g = \operatorname{asin}(h) + O(x^n)`. Assumes `n > 0`. Aliasing of `g` and `h` is allowed. .. function:: void nmod_poly_asin_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{asin}(h) + O(x^n)`. .. function:: void _nmod_poly_asinh_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `g = \operatorname{asinh}(h) + O(x^n)`. Assumes `n > 0`. Aliasing of `g` and `h` is allowed. .. function:: void nmod_poly_asinh_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{asinh}(h) + O(x^n)`. .. function:: void _nmod_poly_sin_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) Set `g = \operatorname{sin}(h) + O(x^n)`. Assumes `n > 0` and that `h` is zero-padded as necessary to length `n`. Aliasing of `g` and `h` is allowed. The value is computed using the identity `\sin(x) = 2 \tan(x/2)) / (1 + \tan^2(x/2)).` .. function:: void nmod_poly_sin_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{sin}(h) + O(x^n)`. .. function:: void _nmod_poly_cos_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) Set `g = \operatorname{cos}(h) + O(x^n)`. Assumes `n > 0` and that `h` is zero-padded as necessary to length `n`. Aliasing of `g` and `h` is allowed. The value is computed using the identity `\cos(x) = (1-\tan^2(x/2)) / (1 + \tan^2(x/2)).` .. function:: void nmod_poly_cos_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{cos}(h) + O(x^n)`. .. function:: void _nmod_poly_tan_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `g = \operatorname{tan}(h) + O(x^n)`. Assumes `n > 0` and that `h` is zero-padded as necessary to length `n`. Aliasing of `g` and `h` is not allowed. Uses Newton iteration to invert the atan function. .. function:: void nmod_poly_tan_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{tan}(h) + O(x^n)`. .. function:: void _nmod_poly_sinh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) Set `g = \operatorname{sinh}(h) + O(x^n)`. Assumes `n > 0` and that `h` is zero-padded as necessary to length `n`. Aliasing of `g` and `h` is not allowed. Uses the identity `\sinh(x) = (e^x - e^{-x})/2`. .. function:: void nmod_poly_sinh_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{sinh}(h) + O(x^n)`. .. function:: void _nmod_poly_cosh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) Set `g = \operatorname{cos}(h) + O(x^n)`. Assumes `n > 0` and that `h` is zero-padded as necessary to length `n`. Aliasing of `g` and `h` is not allowed. Uses the identity `\cosh(x) = (e^x + e^{-x})/2`. .. function:: void nmod_poly_cosh_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{cosh}(h) + O(x^n)`. .. function:: void _nmod_poly_tanh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) Set `g = \operatorname{tanh}(h) + O(x^n)`. Assumes `n > 0` and that `h` is zero-padded as necessary to length `n`. Uses the identity `\tanh(x) = (e^{2x}-1)/(e^{2x}+1)`. .. function:: void nmod_poly_tanh_series(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \operatorname{tanh}(h) + O(x^n)`. Special polynomials -------------------------------------------------------------------------------- .. function:: int _nmod_poly_conway(mp_ptr op, ulong prime, slong deg) Sets ``op`` to the coefficients to the Conway polynomial `C_{p, d}`, where `p` is ``prime`` and `d` is ``deg``. This is done by checking against Frank Lübeck's database [Lüb2004]_, which has been compressed in FLINT. Returns `1` in case of success and returns `0` in case of failure. .. function:: ulong _nmod_poly_conway_rand(slong * degree, flint_rand_t state, int type) Returns a pseudorandom prime and sets ``degree`` that when put into :func:`_nmod_poly_conway` will always succeed. Here, ``type`` can be the following values: * ``0`` for which there is a bijection between the image of this function and the database of Conway polynomials, * ``1`` returns a random prime found in the database and sets ``degree`` to some degree less than `15` along with some prime found in the database, * ``2`` returns a random prime less than `2^{10}` and sets ``degree`` to some random degree found in the database, * ``3`` returns a random prime less than `2^{10}` and sets ``degree`` to some random degree less than `15`. Products -------------------------------------------------------------------------------- .. function:: void _nmod_poly_product_roots_nmod_vec(mp_ptr poly, mp_srcptr xs, slong n, nmod_t mod) Sets ``(poly, n + 1)`` to the monic polynomial which is the product of `(x - x_0)(x - x_1) \cdots (x - x_{n-1})`, the roots `x_i` being given by ``xs``. Aliasing of the input and output is not allowed. .. function:: void nmod_poly_product_roots_nmod_vec(nmod_poly_t poly, mp_srcptr xs, slong n) Sets ``poly`` to the monic polynomial which is the product of `(x - x_0)(x - x_1) \cdots (x - x_{n-1})`, the roots `x_i` being given by ``xs``. .. function:: int nmod_poly_find_distinct_nonzero_roots(mp_limb_t * roots, const nmod_poly_t A) If ``A`` has `\deg(A)` distinct nonzero roots in `\mathbb{F}_p`, write these roots out to ``roots[0]`` to ``roots[deg(A) - 1]`` and return ``1``. Otherwise, return ``0``. It is assumed that ``A`` is nonzero and that the modulus of ``A`` is prime. This function uses Rabin's probabilistic method via gcd's with `(x + \delta)^{\frac{p-1}{2}} - 1`. Subproduct trees -------------------------------------------------------------------------------- .. function:: mp_ptr * _nmod_poly_tree_alloc(slong len) Allocates space for a subproduct tree of the given length, having linear factors at the lowest level. Entry `i` in the tree is a pointer to a single array of limbs, capable of storing `\lfloor n / 2^i \rfloor` subproducts of degree `2^i` adjacently, plus a trailing entry if `n / 2^i` is not an integer. For example, a tree of length 7 built from monic linear factors has the following structure, where spaces have been inserted for illustrative purposes:: X1 X1 X1 X1 X1 X1 X1 XX1 XX1 XX1 X1 XXXX1 XX1 X1 XXXXXXX1 .. function:: void _nmod_poly_tree_free(mp_ptr * tree, slong len) Free the allocated space for the subproduct. .. function:: void _nmod_poly_tree_build(mp_ptr * tree, mp_srcptr roots, slong len, nmod_t mod) Builds a subproduct tree in the preallocated space from the ``len`` monic linear factors `(x-r_i)`. The top level product is not computed. Inflation and deflation -------------------------------------------------------------------------------- .. function:: void nmod_poly_inflate(nmod_poly_t result, const nmod_poly_t input, ulong inflation) Sets ``result`` to the inflated polynomial `p(x^n)` where `p` is given by ``input`` and `n` is given by ``deflation``. .. function:: void nmod_poly_deflate(nmod_poly_t result, const nmod_poly_t input, ulong deflation) Sets ``result`` to the deflated polynomial `p(x^{1/n})` where `p` is given by ``input`` and `n` is given by ``deflation``. Requires `n > 0`. .. function:: ulong nmod_poly_deflation(const nmod_poly_t input) Returns the largest integer by which ``input`` can be deflated. As special cases, returns 0 if ``input`` is the zero polynomial and 1 of ``input`` is a constant polynomial. Chinese Remaindering -------------------------------------------------------------------------------- In all of these functions the moduli (mod.n) of all of the ``nmod_poly``'s involved is assumed to match and be prime. .. function:: void nmod_poly_multi_crt_init(nmod_poly_multi_crt_t CRT) Initialize ``CRT`` for Chinese remaindering. .. function:: int nmod_poly_multi_crt_precompute(nmod_poly_multi_crt_t CRT, const nmod_poly_struct * moduli, slong len) int nmod_poly_multi_crt_precompute_p(nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * moduli, slong len) Configure ``CRT`` for repeated Chinese remaindering of ``moduli``. The number of moduli, ``len``, should be positive. A return of ``0`` indicates that the compilation failed and future calls to :func:`nmod_poly_multi_crt_precomp` will leave the output undefined. A return of ``1`` indicates that the compilation was successful, which occurs if and only if either (1) ``len == 1`` and ``modulus + 0`` is nonzero, or (2) all of the moduli have positive degree and are pairwise relatively prime. .. function:: void nmod_poly_multi_crt_precomp(nmod_poly_t output, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * values) void nmod_poly_multi_crt_precomp_p(nmod_poly_t output, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * values) Set ``output`` to the polynomial of lowest possible degree that is congruent to ``values + i`` modulo the ``moduli + i`` in :func:`nmod_poly_multi_crt_precompute`. The inputs ``values + 0, ..., values + len - 1`` where ``len`` was used in :func:`nmod_poly_multi_crt_precompute` are expected to be valid and have modulus matching the modulus of the moduli used in :func:`nmod_poly_multi_crt_precompute`. .. function:: int nmod_poly_multi_crt(nmod_poly_t output, const nmod_poly_struct * moduli, const nmod_poly_struct * values, slong len) Perform the same operation as :func:`nmod_poly_multi_crt_precomp` while internally constructing and destroying the precomputed data. All of the remarks in :func:`nmod_poly_multi_crt_precompute` apply. .. function:: void nmod_poly_multi_crt_clear(nmod_poly_multi_crt_t CRT) Free all space used by ``CRT``. .. function:: slong _nmod_poly_multi_crt_local_size(const nmod_poly_multi_crt_t CRT) Return the required length of the output for :func:`_nmod_poly_multi_crt_run`. .. function:: void _nmod_poly_multi_crt_run(nmod_poly_struct * outputs, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * inputs) void _nmod_poly_multi_crt_run_p(nmod_poly_struct * outputs, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * inputs) Perform the same operation as :func:`nmod_poly_multi_crt_precomp` using supplied temporary space. The actual output is placed in ``outputs + 0``, and ``outputs`` should contain space for all temporaries and should be at least as long as ``_nmod_poly_multi_crt_local_size(CRT)``. Of course the moduli of these temporaries should match the modulus of the inputs. Berlekamp-Massey Algorithm -------------------------------------------------------------------------------- The nmod_berlekamp_massey_t manages an unlimited stream of points `a_1, a_2, \dots.` At any point in time, after, say, `n` points have been added, a call to :func:`nmod_berlekamp_massey_reduce` will calculate the polynomials `U`, `V` and `R` in the extended euclidean remainder sequence with .. math:: U x^n + V (a_1 x^{n-1} + a_{n-1} x + \cdots + a_n) = R, \quad \deg(U) < \deg(V) \le n/2, \quad \deg(R) < n/2. The polynomials `V` and `R` may be obtained with :func:`nmod_berlekamp_massey_V_poly` and :func:`nmod_berlekamp_massey_R_poly`. This class differs from :func:`fmpz_mod_poly_minpoly` in the following respect. Let `v_i` denote the coefficient of `x^i` in `V`. :func:`fmpz_mod_poly_minpoly` will return a polynomial `V` of lowest degree that annihilates the whole sequence `a_1, \dots, a_n` as .. math:: \sum_{i} v_i a_{j + i} = 0, \quad 1 \le j \le n - \deg(V). The cost is that a polynomial of degree `n-1` might be returned and the return is not generally uniquely determined by the input sequence. For the nmod_berlekamp_massey_t we have .. math:: \sum_{i,j} v_i a_{j+i} x^{-j} = -U + \frac{R}{x^n}\text{,} and it can be seen that `\sum_{i} v_i a_{j + i}` is zero for `1 \le j < n - \deg(R)`. Thus whether or not `V` has annihilated the whole sequence may be checked by comparing the degrees of `V` and `R`. .. function:: void nmod_berlekamp_massey_init(nmod_berlekamp_massey_t B, mp_limb_t p) Initialize ``B`` in characteristic ``p`` with an empty stream. .. function:: void nmod_berlekamp_massey_clear(nmod_berlekamp_massey_t B) Free any space used by ``B``. .. function:: void nmod_berlekamp_massey_start_over(nmod_berlekamp_massey_t B) Empty the stream of points in ``B``. .. function:: void nmod_berlekamp_massey_set_prime(nmod_berlekamp_massey_t B, mp_limb_t p) Set the characteristic of the field and empty the stream of points in ``B``. .. function:: void nmod_berlekamp_massey_add_points(nmod_berlekamp_massey_t B, const mp_limb_t * a, slong count) void nmod_berlekamp_massey_add_zeros(nmod_berlekamp_massey_t B, slong count) void nmod_berlekamp_massey_add_point(nmod_berlekamp_massey_t B, mp_limb_t a) Add point(s) to the stream processed by ``B``. The addition of any number of points will not update the `V` and `R` polynomial. .. function:: int nmod_berlekamp_massey_reduce(nmod_berlekamp_massey_t B) Ensure that the polynomials `V` and `R` are up to date. The return value is ``1`` if this function changed `V` and ``0`` otherwise. For example, if this function is called twice in a row without adding any points in between, the return of the second call should be ``0``. As another example, suppose the object is emptied, the points `1, 1, 2, 3` are added, then reduce is called. This reduce should return ``1`` with `\deg(R) < \deg(V) = 2` because the Fibonacci sequence has been recognized. The further addition of the two points `5, 8` and a reduce will result in a return value of ``0``. .. function:: slong nmod_berlekamp_massey_point_count(const nmod_berlekamp_massey_t B) Return the number of points stored in ``B``. .. function:: const mp_limb_t * nmod_berlekamp_massey_points(const nmod_berlekamp_massey_t B) Return a pointer to the array of points stored in ``B``. This may be ``NULL`` if :func:`nmod_berlekamp_massey_point_count` returns ``0``. .. function:: const nmod_poly_struct * nmod_berlekamp_massey_V_poly(const nmod_berlekamp_massey_t B) Return the polynomial `V` in ``B``. .. function:: const nmod_poly_struct * nmod_berlekamp_massey_R_poly(const nmod_berlekamp_massey_t B) Return the polynomial `R` in ``B``. flint-3.1.3/doc/source/nmod_poly_factor.rst000066400000000000000000000202461461254215100207740ustar00rootroot00000000000000.. _nmod-poly-factor: **nmod_poly_factor.h** -- factorisation of univariate polynomials over integers mod n (word-size n) =================================================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_poly_factor_struct .. type:: nmod_poly_factor_t Factorisation -------------------------------------------------------------------------------- .. function:: void nmod_poly_factor_init(nmod_poly_factor_t fac) Initialises ``fac`` for use. An ``nmod_poly_factor_t`` represents a polynomial in factorised form as a product of polynomials with associated exponents. .. function:: void nmod_poly_factor_clear(nmod_poly_factor_t fac) Frees all memory associated with ``fac``. .. function:: void nmod_poly_factor_realloc(nmod_poly_factor_t fac, slong alloc) Reallocates the factor structure to provide space for precisely ``alloc`` factors. .. function:: void nmod_poly_factor_fit_length(nmod_poly_factor_t fac, slong len) Ensures that the factor structure has space for at least ``len`` factors. This function takes care of the case of repeated calls by always at least doubling the number of factors the structure can hold. .. function:: void nmod_poly_factor_set(nmod_poly_factor_t res, const nmod_poly_factor_t fac) Sets ``res`` to the same factorisation as ``fac``. .. function:: void nmod_poly_factor_print(const nmod_poly_factor_t fac) Prints the entries of ``fac`` to standard output. .. function:: void nmod_poly_factor_insert(nmod_poly_factor_t fac, const nmod_poly_t poly, slong exp) Inserts the factor ``poly`` with multiplicity ``exp`` into the factorisation ``fac``. If ``fac`` already contains ``poly``, then ``exp`` simply gets added to the exponent of the existing entry. .. function:: void nmod_poly_factor_concat(nmod_poly_factor_t res, const nmod_poly_factor_t fac) Concatenates two factorisations. This is equivalent to calling :func:`nmod_poly_factor_insert` repeatedly with the individual factors of ``fac``. Does not support aliasing between ``res`` and ``fac``. .. function:: void nmod_poly_factor_pow(nmod_poly_factor_t fac, slong exp) Raises ``fac`` to the power ``exp``. .. function:: int nmod_poly_is_irreducible(const nmod_poly_t f) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. .. function:: int nmod_poly_is_irreducible_ddf(const nmod_poly_t f) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses fast distinct-degree factorisation. .. function:: int nmod_poly_is_irreducible_rabin(const nmod_poly_t f) Returns 1 if the polynomial ``f`` is irreducible, otherwise returns 0. Uses Rabin irreducibility test. .. function:: int _nmod_poly_is_squarefree(mp_srcptr f, slong len, nmod_t mod) Returns 1 if ``(f, len)`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. There are no restrictions on the length. .. function:: int nmod_poly_is_squarefree(const nmod_poly_t f) Returns 1 if ``f`` is squarefree, and 0 otherwise. As a special case, the zero polynomial is not considered squarefree. .. function:: void nmod_poly_factor_squarefree(nmod_poly_factor_t res, const nmod_poly_t f) Sets ``res`` to a square-free factorization of ``f``. .. function:: int nmod_poly_factor_equal_deg_prob(nmod_poly_t factor, flint_rand_t state, const nmod_poly_t pol, slong d) Probabilistic equal degree factorisation of ``pol`` into irreducible factors of degree ``d``. If it passes, a factor is placed in factor and 1 is returned, otherwise 0 is returned and the value of factor is undetermined. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void nmod_poly_factor_equal_deg(nmod_poly_factor_t factors, const nmod_poly_t pol, slong d) Assuming ``pol`` is a product of irreducible factors all of degree ``d``, finds all those factors and places them in factors. Requires that ``pol`` be monic, non-constant and squarefree. .. function:: void nmod_poly_factor_distinct_deg(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const * degs) Factorises a monic non-constant squarefree polynomial ``poly`` of degree n into factors `f[d]` such that for `1 \leq d \leq n` `f[d]` is the product of the monic irreducible factors of ``poly`` of degree `d`. Factors `f[d]` are stored in ``res``, and the degree `d` of the irreducible factors is stored in ``degs`` in the same order as the factors. Requires that ``degs`` has enough space for ``(n/2)+1 * sizeof(slong)``. .. function:: void nmod_poly_factor_distinct_deg_threaded(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const * degs) Multithreaded version of :func:`nmod_poly_factor_distinct_deg`. .. function:: void nmod_poly_factor_cantor_zassenhaus(nmod_poly_factor_t res, const nmod_poly_t f) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the Cantor-Zassenhaus algorithm. .. function:: void nmod_poly_factor_berlekamp(nmod_poly_factor_t res, const nmod_poly_t f) Factorises a non-constant, squarefree polynomial ``f`` into monic irreducible factors using the Berlekamp algorithm. .. function:: void nmod_poly_factor_kaltofen_shoup(nmod_poly_factor_t res, const nmod_poly_t poly) Factorises a non-constant polynomial ``f`` into monic irreducible factors using the fast version of Cantor-Zassenhaus algorithm proposed by Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby step/giant step” strategy for the distinct-degree factorization step. If :func:`flint_get_num_threads` is greater than one :func:`nmod_poly_factor_distinct_deg_threaded` is used. .. function:: mp_limb_t nmod_poly_factor_with_berlekamp(nmod_poly_factor_t res, const nmod_poly_t f) Factorises a general polynomial ``f`` into monic irreducible factors and returns the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Berlekamp on all the individual square-free factors. .. function:: mp_limb_t nmod_poly_factor_with_cantor_zassenhaus(nmod_poly_factor_t res, const nmod_poly_t f) Factorises a general polynomial ``f`` into monic irreducible factors and returns the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Cantor-Zassenhaus on all the individual square-free factors. .. function:: mp_limb_t nmod_poly_factor_with_kaltofen_shoup(nmod_poly_factor_t res, const nmod_poly_t f) Factorises a general polynomial ``f`` into monic irreducible factors and returns the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs Kaltofen-Shoup on all the individual square-free factors. .. function:: mp_limb_t nmod_poly_factor(nmod_poly_factor_t res, const nmod_poly_t f) Factorises a general polynomial ``f`` into monic irreducible factors and returns the leading coefficient of ``f``, or 0 if ``f`` is the zero polynomial. This function first checks for small special cases, deflates ``f`` if it is of the form `p(x^m)` for some `m > 1`, then performs a square-free factorisation, and finally runs either Cantor-Zassenhaus or Berlekamp on all the individual square-free factors. Currently Cantor-Zassenhaus is used by default unless the modulus is 2, in which case Berlekamp is used. .. function:: void _nmod_poly_interval_poly_worker(void * arg_ptr) Worker function to compute interval polynomials in distinct degree factorisation. Input/output is stored in ``nmod_poly_interval_poly_arg_t``. flint-3.1.3/doc/source/nmod_poly_mat.rst000066400000000000000000000476761461254215100203170ustar00rootroot00000000000000.. _nmod-poly-mat: **nmod_poly_mat.h** -- matrices of univariate polynomials over integers mod n (word-size n) =========================================================================================== The :type:`nmod_poly_mat_t` data type represents matrices whose entries are polynomials having coefficients in `\mathbb{Z}/n\mathbb{Z}`. We generally assume that `n` is a prime number. The :type:`nmod_poly_mat_t` type is defined as an array of :type:`nmod_poly_mat_struct`'s of length one. This permits passing parameters of type :type:`nmod_poly_mat_t` by reference. A matrix internally consists of a single array of :type:`nmod_poly_struct`'s, representing a dense matrix in row-major order. This array is only directly indexed during memory allocation and deallocation. A separate array holds pointers to the start of each row, and is used for all indexing. This allows the rows of a matrix to be permuted quickly by swapping pointers. Matrices having zero rows or columns are allowed. The shape of a matrix is fixed upon initialisation. The user is assumed to provide input and output variables whose dimensions are compatible with the given operation. Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_poly_mat_struct .. type:: nmod_poly_mat_t Memory management -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_init(nmod_poly_mat_t mat, slong rows, slong cols, mp_limb_t n) Initialises a matrix with the given number of rows and columns for use. The modulus is set to `n`. .. function:: void nmod_poly_mat_init_set(nmod_poly_mat_t mat, const nmod_poly_mat_t src) Initialises a matrix ``mat`` of the same dimensions and modulus as ``src``, and sets it to a copy of ``src``. .. function:: void nmod_poly_mat_clear(nmod_poly_mat_t mat) Frees all memory associated with the matrix. The matrix must be reinitialised if it is to be used again. Truncate, shift -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_set_trunc(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, long len) Set ``res`` to the truncation of ``pmat`` to length ``len``. Entries of ``res`` are normalized. .. function:: void nmod_poly_mat_truncate(nmod_poly_mat_t pmat, long len) Truncates ``pmat`` to the given length ``len``, and normalize its entries. If ``len`` is greater than the maximum length of the entries of ``pmat``, then nothing happens. .. function:: void nmod_poly_mat_shift_left(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, slong k) Sets ``res`` to ``pmat`` shifted left by ``k`` coefficients, that is, multiplied by `x^k`. .. function:: void nmod_poly_mat_shift_right(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, slong k) Sets ``res`` to ``pmat`` shifted right by ``k`` coefficients, that is, divide by `x^k` and throw away the remainder. If ``k`` is greater than or equal to the length of ``pmat``, the result is the zero polynomial matrix. Basic properties -------------------------------------------------------------------------------- .. function:: slong nmod_poly_mat_nrows(const nmod_poly_mat_t mat) Returns the number of rows in ``mat``. .. function:: slong nmod_poly_mat_ncols(const nmod_poly_mat_t mat) Returns the number of columns in ``mat``. .. function:: mp_limb_t nmod_poly_mat_modulus(const nmod_poly_mat_t mat) Returns the modulus of ``mat``. Basic assignment and manipulation -------------------------------------------------------------------------------- .. function:: nmod_poly_struct * nmod_poly_mat_entry(const nmod_poly_mat_t mat, slong i, slong j) Gives a reference to the entry at row ``i`` and column ``j``. The reference can be passed as an input or output variable to any ``nmod_poly`` function for direct manipulation of the matrix element. No bounds checking is performed. .. function:: void nmod_poly_mat_set(nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2) Sets ``mat1`` to a copy of ``mat2``. .. function:: void nmod_poly_mat_set_nmod_mat(nmod_poly_mat_t pmat, const nmod_mat_t cmat) Sets the already-initialized polynomial matrix ``pmat`` to a constant matrix with the same entries as ``cmat``. Both input matrices must have the same dimensions and modulus. .. function:: void nmod_poly_mat_swap(nmod_poly_mat_t mat1, nmod_poly_mat_t mat2) Swaps ``mat1`` and ``mat2`` efficiently. .. function:: void nmod_poly_mat_swap_entrywise(nmod_poly_mat_t mat1, nmod_poly_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. Input and output -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_print(const nmod_poly_mat_t mat, const char * x) Prints the matrix ``mat`` to standard output, using the variable ``x``. Random matrix generation -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_randtest(nmod_poly_mat_t mat, flint_rand_t state, slong len) This is equivalent to applying ``nmod_poly_randtest`` to all entries in the matrix. .. function:: void nmod_poly_mat_randtest_sparse(nmod_poly_mat_t A, flint_rand_t state, slong len, float density) Creates a random matrix with the amount of nonzero entries given approximately by the ``density`` variable, which should be a fraction between 0 (most sparse) and 1 (most dense). The nonzero entries will have random lengths between 1 and ``len``. Special matrices -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_zero(nmod_poly_mat_t mat) Sets ``mat`` to the zero matrix. .. function:: void nmod_poly_mat_one(nmod_poly_mat_t mat) Sets ``mat`` to the unit or identity matrix of given shape, having the element 1 on the main diagonal and zeros elsewhere. If ``mat`` is nonsquare, it is set to the truncation of a unit matrix. Basic comparison and properties -------------------------------------------------------------------------------- .. function:: int nmod_poly_mat_equal(const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2) Returns nonzero if ``mat1`` and ``mat2`` have the same shape and all their entries agree, and returns zero otherwise. .. function:: int nmod_poly_mat_equal_nmod_mat(const nmod_poly_mat_t pmat, const nmod_mat_t cmat) Returns nonzero if ``pmat`` is a constant matrix with the same dimensions and entries as ``cmat``; returns zero otherwise. .. function:: int nmod_poly_mat_is_zero(const nmod_poly_mat_t mat) Returns nonzero if all entries in ``mat`` are zero, and returns zero otherwise. .. function:: int nmod_poly_mat_is_one(const nmod_poly_mat_t mat) Returns nonzero if all entry of ``mat`` on the main diagonal are the constant polynomial 1 and all remaining entries are zero, and returns zero otherwise. The matrix need not be square. .. function:: int nmod_poly_mat_is_empty(const nmod_poly_mat_t mat) Returns a non-zero value if the number of rows or the number of columns in ``mat`` is zero, and otherwise returns zero. .. function:: int nmod_poly_mat_is_square(const nmod_poly_mat_t mat) Returns a non-zero value if the number of rows is equal to the number of columns in ``mat``, and otherwise returns zero. .. function:: void nmod_poly_mat_get_coeff_mat(nmod_mat_t coeff, const nmod_poly_mat_t pmat, slong deg) Sets ``coeff`` to be the coefficient of ``pmat`` of degree ``deg``, where ``pmat`` is seen as a polynomial with matrix coefficients and coefficients are numbered from zero. ``coeff`` must be already initialized with the right dimensions and modulus. For entries of ``pmat`` of degree less than ``deg``, the corresponding entry of ``coeff`` is zero. .. function:: void nmod_poly_mat_set_coeff_mat(nmod_poly_mat_t pmat, const nmod_mat_t coeff, slong deg) Sets the coefficient of ``pmat`` of degree ``deg`` to ``coeff``, where ``pmat`` is seen as a polynomial with matrix coefficients and coefficients are numbered from zero. For each entry of ``pmat``, if ``deg`` is larger than its degree, this entry is first resized to the appropriate length, with intervening coefficients being set to zero. Norms -------------------------------------------------------------------------------- .. function:: slong nmod_poly_mat_max_length(const nmod_poly_mat_t A) Returns the maximum polynomial length among all the entries in ``A``. .. function:: slong nmod_poly_mat_degree(const nmod_poly_mat_t pmat) Returns the degree of the polynomial matrix ``pmat``. The zero matrix is deemed to have degree `-1`. Evaluation -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_evaluate_nmod(nmod_mat_t B, const nmod_poly_mat_t A, mp_limb_t x) Sets the ``nmod_mat_t`` ``B`` to ``A`` evaluated entrywise at the point ``x``. Arithmetic -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_scalar_mul_nmod_poly(nmod_poly_mat_t B, const nmod_poly_mat_t A, const nmod_poly_t c) Sets ``B`` to ``A`` multiplied entrywise by the polynomial ``c``. .. function:: void nmod_poly_mat_scalar_mul_nmod(nmod_poly_mat_t B, const nmod_poly_mat_t A, mp_limb_t c) Sets ``B`` to ``A`` multiplied entrywise by the coefficient ``c``, which is assumed to be reduced modulo the modulus. .. function:: void nmod_poly_mat_add(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Sets ``C`` to the sum of ``A`` and ``B``. All matrices must have the same shape. Aliasing is allowed. .. function:: void nmod_poly_mat_sub(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Sets ``C`` to the sum of ``A`` and ``B``. All matrices must have the same shape. Aliasing is allowed. .. function:: void nmod_poly_mat_neg(nmod_poly_mat_t B, const nmod_poly_mat_t A) Sets ``B`` to the negation of ``A``. The matrices must have the same shape. Aliasing is allowed. .. function:: void nmod_poly_mat_mul(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Sets ``C`` to the matrix product of ``A`` and ``B``. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. This function automatically chooses between classical, KS and evaluation-interpolation multiplication. .. function:: void nmod_poly_mat_mul_classical(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Sets ``C`` to the matrix product of ``A`` and ``B``, computed using the classical algorithm. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. .. function:: void nmod_poly_mat_mul_KS(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Sets ``C`` to the matrix product of ``A`` and ``B``, computed using Kronecker segmentation. The matrices must have compatible dimensions for matrix multiplication. Aliasing is allowed. .. function:: void nmod_poly_mat_mul_interpolate(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Sets ``C`` to the matrix product of ``A`` and ``B``, computed through evaluation and interpolation. The matrices must have compatible dimensions for matrix multiplication. For interpolation to be well-defined, we require that the modulus is a prime at least as large as `m + n - 1` where `m` and `n` are the maximum lengths of polynomials in the input matrices. Aliasing is allowed. .. function:: void nmod_poly_mat_sqr(nmod_poly_mat_t B, const nmod_poly_mat_t A) Sets ``B`` to the square of ``A``, which must be a square matrix. Aliasing is allowed. This function automatically chooses between classical and KS squaring. .. function:: void nmod_poly_mat_sqr_classical(nmod_poly_mat_t B, const nmod_poly_mat_t A) Sets ``B`` to the square of ``A``, which must be a square matrix. Aliasing is allowed. This function uses direct formulas for very small matrices, and otherwise classical matrix multiplication. .. function:: void nmod_poly_mat_sqr_KS(nmod_poly_mat_t B, const nmod_poly_mat_t A) Sets ``B`` to the square of ``A``, which must be a square matrix. Aliasing is allowed. This function uses Kronecker segmentation. .. function:: void nmod_poly_mat_sqr_interpolate(nmod_poly_mat_t B, const nmod_poly_mat_t A) Sets ``B`` to the square of ``A``, which must be a square matrix, computed through evaluation and interpolation. For interpolation to be well-defined, we require that the modulus is a prime at least as large as `2n - 1` where `n` is the maximum length of polynomials in the input matrix. Aliasing is allowed. .. function:: void nmod_poly_mat_pow(nmod_poly_mat_t B, const nmod_poly_mat_t A, ulong exp) Sets ``B`` to ``A`` raised to the power ``exp``, where ``A`` is a square matrix. Uses exponentiation by squaring. Aliasing is allowed. Row reduction -------------------------------------------------------------------------------- .. function:: slong nmod_poly_mat_find_pivot_any(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c) Attempts to find a pivot entry for row reduction. Returns a row index `r` between ``start_row`` (inclusive) and ``stop_row`` (exclusive) such that column `c` in ``mat`` has a nonzero entry on row `r`, or returns -1 if no such entry exists. This implementation simply chooses the first nonzero entry from it encounters. This is likely to be a nearly optimal choice if all entries in the matrix have roughly the same size, but can lead to unnecessary coefficient growth if the entries vary in size. .. function:: slong nmod_poly_mat_find_pivot_partial(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c) Attempts to find a pivot entry for row reduction. Returns a row index `r` between ``start_row`` (inclusive) and ``stop_row`` (exclusive) such that column `c` in ``mat`` has a nonzero entry on row `r`, or returns -1 if no such entry exists. This implementation searches all the rows in the column and chooses the nonzero entry of smallest degree. This heuristic typically reduces coefficient growth when the matrix entries vary in size. .. function:: slong nmod_poly_mat_fflu(nmod_poly_mat_t B, nmod_poly_t den, slong * perm, const nmod_poly_mat_t A, int rank_check) Uses fraction-free Gaussian elimination to set (``B``, ``den``) to a fraction-free LU decomposition of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. Pivot elements are chosen with ``nmod_poly_mat_find_pivot_partial``. If ``perm`` is non-``NULL``, the permutation of rows in the matrix will also be applied to ``perm``. If ``rank_check`` is set, the function aborts and returns 0 if the matrix is detected not to have full rank without completing the elimination. The denominator ``den`` is set to `\pm \operatorname{det}(A)`, where the sign is decided by the parity of the permutation. Note that the determinant is not generally the minimal denominator. .. function:: slong nmod_poly_mat_rref(nmod_poly_mat_t B, nmod_poly_t den, const nmod_poly_mat_t A) Sets (``B``, ``den``) to the reduced row echelon form of ``A`` and returns the rank of ``A``. Aliasing of ``A`` and ``B`` is allowed. The denominator ``den`` is set to `\pm \operatorname{det}(A)`. Note that the determinant is not generally the minimal denominator. Trace -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_trace(nmod_poly_t trace, const nmod_poly_mat_t mat) Computes the trace of the matrix, i.e. the sum of the entries on the main diagonal. The matrix is required to be square. Determinant and rank -------------------------------------------------------------------------------- .. function:: void nmod_poly_mat_det(nmod_poly_t det, const nmod_poly_mat_t A) Sets ``det`` to the determinant of the square matrix ``A``. Uses a direct formula, fraction-free LU decomposition, or interpolation, depending on the size of the matrix. .. function:: void nmod_poly_mat_det_fflu(nmod_poly_t det, const nmod_poly_mat_t A) Sets ``det`` to the determinant of the square matrix ``A``. The determinant is computed by performing a fraction-free LU decomposition on a copy of ``A``. .. function:: void nmod_poly_mat_det_interpolate(nmod_poly_t det, const nmod_poly_mat_t A) Sets ``det`` to the determinant of the square matrix ``A``. The determinant is computed by determining a bound `n` for its length, evaluating the matrix at `n` distinct points, computing the determinant of each coefficient matrix, and forming the interpolating polynomial. If the coefficient ring does not contain `n` distinct points (that is, if working over `\mathbf{Z}/p\mathbf{Z}` where `p < n`), this function automatically falls back to ``nmod_poly_mat_det_fflu``. .. function:: slong nmod_poly_mat_rank(const nmod_poly_mat_t A) Returns the rank of ``A``. Performs fraction-free LU decomposition on a copy of ``A``. Inverse -------------------------------------------------------------------------------- .. function:: int nmod_poly_mat_inv(nmod_poly_mat_t Ainv, nmod_poly_t den, const nmod_poly_mat_t A) Sets (``Ainv``, ``den``) to the inverse matrix of ``A``. Returns 1 if ``A`` is nonsingular and 0 if ``A`` is singular. Aliasing of ``Ainv`` and ``A`` is allowed. More precisely, ``det`` will be set to the determinant of ``A`` and ``Ainv`` will be set to the adjugate matrix of ``A``. Note that the determinant is not necessarily the minimal denominator. Uses fraction-free LU decomposition, followed by solving for the identity matrix. Nullspace -------------------------------------------------------------------------------- .. function:: slong nmod_poly_mat_nullspace(nmod_poly_mat_t res, const nmod_poly_mat_t mat) Computes the right rational nullspace of the matrix ``mat`` and returns the nullity. More precisely, assume that ``mat`` has rank `r` and nullity `n`. Then this function sets the first `n` columns of ``res`` to linearly independent vectors spanning the nullspace of ``mat``. As a result, we always have rank(``res``) `= n`, and ``mat`` `\times` ``res`` is the zero matrix. The computed basis vectors will not generally be in a reduced form. In general, the polynomials in each column vector in the result will have a nontrivial common GCD. Solving -------------------------------------------------------------------------------- .. function:: int nmod_poly_mat_solve(nmod_poly_mat_t X, nmod_poly_t den, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. Uses fraction-free LU decomposition followed by fraction-free forward and back substitution. .. function:: int nmod_poly_mat_solve_fflu(nmod_poly_mat_t X, nmod_poly_t den, const nmod_poly_mat_t A, const nmod_poly_mat_t B) Solves the equation `AX = B` for nonsingular `A`. More precisely, computes (``X``, ``den``) such that `AX = B \times \operatorname{den}`. Returns 1 if `A` is nonsingular and 0 if `A` is singular. The computed denominator will not generally be minimal. Uses fraction-free LU decomposition followed by fraction-free forward and back substitution. .. function:: void nmod_poly_mat_solve_fflu_precomp(nmod_poly_mat_t X, const slong * perm, const nmod_poly_mat_t FFLU, const nmod_poly_mat_t B) Performs fraction-free forward and back substitution given a precomputed fraction-free LU decomposition and corresponding permutation. flint-3.1.3/doc/source/nmod_vec.rst000066400000000000000000000137101461254215100172260ustar00rootroot00000000000000.. _nmod-vec: **nmod_vec.h** -- vectors over integers mod n (word-size n) =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: mp_ptr _nmod_vec_init(slong len) Returns a vector of the given length. The entries are not necessarily zero. .. function:: void _nmod_vec_clear(mp_ptr vec) Frees the memory used by the given vector. Random functions -------------------------------------------------------------------------------- .. function:: void _nmod_vec_randtest(mp_ptr vec, flint_rand_t state, slong len, nmod_t mod) Sets ``vec`` to a random vector of the given length with entries reduced modulo ``mod.n``. Basic manipulation and comparison -------------------------------------------------------------------------------- .. function:: void _nmod_vec_set(mp_ptr res, mp_srcptr vec, slong len) Copies ``len`` entries from the vector ``vec`` to ``res``. .. function:: void _nmod_vec_zero(mp_ptr vec, slong len) Zeros the given vector of the given length. .. function:: void _nmod_vec_swap(mp_ptr a, mp_ptr b, slong length) Swaps the vectors ``a`` and ``b`` of length `n` by actually swapping the entries. .. function:: void _nmod_vec_reduce(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod) Reduces the entries of ``(vec, len)`` modulo ``mod.n`` and set ``res`` to the result. .. function:: flint_bitcnt_t _nmod_vec_max_bits(mp_srcptr vec, slong len) Returns the maximum number of bits of any entry in the vector. .. function:: int _nmod_vec_equal(mp_srcptr vec, mp_srcptr vec2, slong len) Returns~`1` if ``(vec, len)`` is equal to ``(vec2, len)``, otherwise returns~`0`. Printing -------------------------------------------------------------------------------- .. function:: void _nmod_vec_print_pretty(mp_srcptr vec, slong len, nmod_t mod) Pretty-prints ``vec`` to ``stdout``. A header is printed followed by the vector enclosed in brackets. Each entry is right-aligned to the width of the modulus written in decimal, and the entries are separated by spaces. For example:: [ 33 181 107 61 32 11 80 138 34 171 86 156] .. function:: int _nmod_vec_fprint_pretty(FILE * file, mp_srcptr vec, slong len, nmod_t mod) Same as ``_nmod_vec_print_pretty`` but printing to ``file``. .. function:: int _nmod_vec_print(mp_srcptr vec, slong len, nmod_t mod) Currently, same as ``_nmod_vec_print_pretty``. .. function:: int _nmod_vec_fprint(FILE * f, mp_srcptr vec, slong len, nmod_t mod) Currently, same as ``_nmod_vec_fprint_pretty``. Arithmetic operations -------------------------------------------------------------------------------- .. function:: void _nmod_vec_add(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod) Sets ``(res, len)`` to the sum of ``(vec1, len)`` and ``(vec2, len)``. .. function:: void _nmod_vec_sub(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod) Sets ``(res, len)`` to the difference of ``(vec1, len)`` and ``(vec2, len)``. .. function:: void _nmod_vec_neg(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod) Sets ``(res, len)`` to the negation of ``(vec, len)``. .. function:: void _nmod_vec_scalar_mul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) Sets ``(res, len)`` to ``(vec, len)`` multiplied by `c`. The element `c` and all elements of `vec` are assumed to be less than `mod.n`. .. function:: void _nmod_vec_scalar_mul_nmod_shoup(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) Sets ``(res, len)`` to ``(vec, len)`` multiplied by `c` using :func:`n_mulmod_shoup`. `mod.n` should be less than `2^{\mathtt{FLINT\_BITS} - 1}`. `c` and all elements of `vec` should be less than `mod.n`. .. function:: void _nmod_vec_scalar_addmul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) Adds ``(vec, len)`` times `c` to the vector ``(res, len)``. The element `c` and all elements of `vec` are assumed to be less than `mod.n`. Dot products -------------------------------------------------------------------------------- .. function:: int _nmod_vec_dot_bound_limbs(slong len, nmod_t mod) Returns the number of limbs (0, 1, 2 or 3) needed to represent the unreduced dot product of two vectors of length ``len`` having entries modulo ``mod.n``, assuming that ``len`` is nonnegative and that ``mod.n`` is nonzero. The computed bound is tight. In other words, this function returns the precise limb size of ``len`` times ``(mod.n - 1) ^ 2``. .. macro:: NMOD_VEC_DOT(res, i, len, expr1, expr2, mod, nlimbs) Effectively performs the computation:: res = 0; for (i = 0; i < len; i++) res += (expr1) * (expr2); but with the arithmetic performed modulo ``mod``. The ``nlimbs`` parameter should be 0, 1, 2 or 3, specifying the number of limbs needed to represent the unreduced result. ``nmod.h`` has to be included in order for this macro to work (order of inclusions does not matter). .. function:: mp_limb_t _nmod_vec_dot(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs) Returns the dot product of (``vec1``, ``len``) and (``vec2``, ``len``). The ``nlimbs`` parameter should be 0, 1, 2 or 3, specifying the number of limbs needed to represent the unreduced result. .. function:: mp_limb_t _nmod_vec_dot_rev(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs) The same as ``_nmod_vec_dot``, but reverses ``vec2``. .. function:: mp_limb_t _nmod_vec_dot_ptr(mp_srcptr vec1, const mp_ptr * vec2, slong offset, slong len, nmod_t mod, int nlimbs) Returns the dot product of (``vec1``, ``len``) and the values at ``vec2[i][offset]``. The ``nlimbs`` parameter should be 0, 1, 2 or 3, specifying the number of limbs needed to represent the unreduced result. flint-3.1.3/doc/source/overview.rst000066400000000000000000000064051461254215100173050ustar00rootroot00000000000000.. _overview: Feature overview =============================================================================== Ball arithmetic, also known as mid-rad interval arithmetic, is an extension of floating-point arithmetic in which an error bound is attached to each variable. This allows computing with real and complex numbers in a mathematically rigorous way. With plain floating-point arithmetic, the user must do an error analysis to guarantee that results are correct. Manual error analysis is time-consuming and bug-prone. Ball arithmetic effectively makes error analysis automatic. In traditional (inf-sup) interval arithmetic, both endpoints of an interval `[a,b]` are full-precision numbers, which makes interval arithmetic twice as expensive as floating-point arithmetic. In ball arithmetic, only the midpoint *m* of an interval `[m \pm r]` is a full-precision number, and a few bits suffice for the radius *r*. At high precision, ball arithmetic is therefore not more expensive than plain floating-point arithmetic. Joris van der Hoeven's paper [Hoe2009]_ is a good introduction to the subject. Other implementations of ball arithmetic include `iRRAM `_ and `Mathemagix `_. Arb differs from earlier implementations in technical aspects of the implementation, which makes certain computations more efficient. It also provides a more comprehensive low-level interface, giving the user full access to the internals. Finally, it implements a wider range of transcendental functions, covering a large portion of the special functions in standard reference works such as [NIST2012]_. The ball arithmetic routines in FLINT (formerly the standalone Arb library) are designed for computer algebra and computational number theory, but may be useful in any area demanding reliable or precise numerical computing. The contents include: * A module (:ref:`arf `) for correctly rounded arbitrary-precision floating-point arithmetic. Arb's floating-point numbers have a few special features, such as arbitrary-size exponents (useful for combinatorics and asymptotics) and dynamic allocation (facilitating implementation of hybrid integer/floating-point and mixed-precision algorithms). * A module (:ref:`mag `) for representing magnitudes (error bounds) more efficiently than with an arbitrary-precision floating-point type. * A module (:ref:`arb `) for real ball arithmetic, where a ball is implemented as an *arf* midpoint and a *mag* radius. * A module (:ref:`acb `) for complex numbers in rectangular form, represented as pairs of real balls. * Modules (:ref:`arb_poly `, :ref:`acb_poly `) for polynomials or power series over the real and complex numbers, implemented using balls as coefficients, with asymptotically fast polynomial multiplication and many other operations. * Modules (:ref:`arb_mat `, :ref:`acb_mat `) for matrices over the real and complex numbers, implemented using balls as coefficients. At the moment, only rudimentary linear algebra operations are provided. * Functions for high-precision evaluation of various mathematical constants and special functions, implemented using ball arithmetic with rigorous error bounds. flint-3.1.3/doc/source/padic.rst000066400000000000000000000527741461254215100165310ustar00rootroot00000000000000.. _padic: **padic.h** -- p-adic numbers =============================================================================== Introduction -------------------------------------------------------------------------------- The ``padic_t`` data type represents elements of `\mathbf{Q}_p` to precision `N`, stored in the form `x = p^v u` with `u, v \in \mathbf{Z}`. Arithmetic operations can be carried out with respect to a context containing the prime number `p` and various pieces of pre-computed data. Independent of the context, we consider a `p`-adic number `x = u p^v` to be in canonical form whenever either `p \nmid u` or `u = v = 0`, and we say it is reduced if, in addition, for non-zero `u`, `u \in (0, p^{N-v})`. We briefly describe the interface: The functions in this module expect arguments of type ``padic_t``, and each variable carries its own precision. The functions have an interface that is similar to the MPFR functions. In particular, they have the same semantics, specified as follows: Compute the requested operation exactly and then reduce the result to the precision of the output variable. Data structures -------------------------------------------------------------------------------- A `p`-adic number of type ``padic_t`` comprises a unit `u`, a valuation `v`, and a precision `N`. We provide the following macros to access these fields, so that code can be developed somewhat independently from the underlying data layout. .. function:: fmpz * padic_unit(const padic_t op) Returns the unit part of the `p`-adic number as a FLINT integer, which can be used as an operand for the ``fmpz`` functions. .. function:: slong padic_val(const padic_t op) Returns the valuation part of the `p`-adic number. Note that this function is implemented as a macro and that the expression ``padic_val(op)`` can be used as both an *lvalue* and an *rvalue*. .. function:: slong padic_get_val(const padic_t op) Returns the valuation part of the `p`-adic number. .. function:: slong padic_prec(const padic_t op) Returns the precision of the `p`-adic number. Note that this function is implemented as a macro and that the expression ``padic_prec(op)`` can be used as both an *lvalue* and an *rvalue*. .. function:: slong padic_get_prec(const padic_t op) Returns the precision of the `p`-adic number. Context -------------------------------------------------------------------------------- A context object for `p`-adic arithmetic contains data pertinent to `p`-adic computations, but which we choose not to store with each element individually. Currently, this includes the prime number `p`, its ``double`` inverse in case of word-sized primes, precomputed powers of `p` in the range given by ``min`` and ``max``, and the printing mode. .. function:: void padic_ctx_init(padic_ctx_t ctx, const fmpz_t p, slong min, slong max, enum padic_print_mode mode) Initialises the context ``ctx`` with the given data. Assumes that `p` is a prime. This is not verified but the subsequent behaviour is undefined if `p` is a composite number. Assumes that ``min`` and ``max`` are non-negative and that ``min`` is at most ``max``, raising an ``abort`` signal otherwise. Assumes that the printing mode is one of ``PADIC_TERSE``, ``PADIC_SERIES``, or ``PADIC_VAL_UNIT``. Using the example `x = 7^{-1} 12` in `\mathbf{Q}_7`, these behave as follows: In ``PADIC_TERSE`` mode, a `p`-adic number is printed in the same way as a rational number, e.g. ``12/7``. In ``PADIC_SERIES`` mode, a `p`-adic number is printed digit by digit, e.g. ``5*7^-1 + 1``. In ``PADIC_VAL_UNIT`` mode, a `p`-adic number is printed showing the valuation and unit parts separately, e.g. ``12*7^-1``. .. function:: void padic_ctx_clear(padic_ctx_t ctx) Clears all memory that has been allocated as part of the context. .. function:: int _padic_ctx_pow_ui(fmpz_t rop, ulong e, const padic_ctx_t ctx) Sets ``rop`` to `p^e` as efficiently as possible, where ``rop`` is expected to be an uninitialised ``fmpz_t``. If the return value is non-zero, it is the responsibility of the caller to clear the returned integer. Memory management -------------------------------------------------------------------------------- .. function:: void padic_init(padic_t rop) Initialises the `p`-adic number with the precision set to ``PADIC_DEFAULT_PREC``, which is defined as `20`. .. function:: void padic_init2(padic_t rop, slong N) Initialises the `p`-adic number ``rop`` with precision `N`. .. function:: void padic_clear(padic_t rop) Clears all memory used by the `p`-adic number ``rop``. .. function:: void _padic_canonicalise(padic_t rop, const padic_ctx_t ctx) Brings the `p`-adic number ``rop`` into canonical form. That is to say, ensures that either `u = v = 0` or `p \nmid u`. There is no reduction modulo a power of `p`. .. function:: void _padic_reduce(padic_t rop, const padic_ctx_t ctx) Given a `p`-adic number ``rop`` in canonical form, reduces it modulo `p^N`. .. function:: void padic_reduce(padic_t rop, const padic_ctx_t ctx) Ensures that the `p`-adic number ``rop`` is reduced. Randomisation -------------------------------------------------------------------------------- .. function:: void padic_randtest(padic_t rop, flint_rand_t state, const padic_ctx_t ctx) Sets ``rop`` to a random `p`-adic number modulo `p^N` with valuation in the range `[- \lceil N/10\rceil, N)`, `[N - \lceil -N/10\rceil, N)`, or `[-10, 0)` as `N` is positive, negative or zero, whenever ``rop`` is non-zero. .. function:: void padic_randtest_not_zero(padic_t rop, flint_rand_t state, const padic_ctx_t ctx) Sets ``rop`` to a random non-zero `p`-adic number modulo `p^N`, where the range of the valuation is as for the function :func:`padic_randtest`. .. function:: void padic_randtest_int(padic_t rop, flint_rand_t state, const padic_ctx_t ctx) Sets ``rop`` to a random `p`-adic integer modulo `p^N`. Note that whenever `N \leq 0`, ``rop`` is set to zero. Assignments and conversions -------------------------------------------------------------------------------- All assignment functions set the value of ``rop`` from ``op``, reduced to the precision of ``rop``. .. function:: void padic_set(padic_t rop, const padic_t op, const padic_ctx_t ctx) Sets ``rop`` to the `p`-adic number ``op``. .. function:: void padic_set_si(padic_t rop, slong op, const padic_ctx_t ctx) Sets the `p`-adic number ``rop`` to the ``slong`` integer ``op``. .. function:: void padic_set_ui(padic_t rop, ulong op, const padic_ctx_t ctx) Sets the `p`-adic number ``rop`` to the ``ulong`` integer ``op``. .. function:: void padic_set_fmpz(padic_t rop, const fmpz_t op, const padic_ctx_t ctx) Sets the `p`-adic number ``rop`` to the integer ``op``. .. function:: void padic_set_fmpq(padic_t rop, const fmpq_t op, const padic_ctx_t ctx) Sets ``rop`` to the rational ``op``. .. function:: void padic_set_mpz(padic_t rop, const mpz_t op, const padic_ctx_t ctx) Sets the `p`-adic number ``rop`` to the GMP integer ``op``. .. function:: void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx) Sets ``rop`` to the GMP rational ``op``. .. function:: void padic_get_fmpz(fmpz_t rop, const padic_t op, const padic_ctx_t ctx) Sets the integer ``rop`` to the exact `p`-adic integer ``op``. If ``op`` is not a `p`-adic integer, raises an ``abort`` signal. .. function:: void padic_get_fmpq(fmpq_t rop, const padic_t op, const padic_ctx_t ctx) Sets the rational ``rop`` to the `p`-adic number ``op``. .. function:: void padic_get_mpz(mpz_t rop, const padic_t op, const padic_ctx_t ctx) Sets the GMP integer ``rop`` to the `p`-adic integer ``op``. If ``op`` is not a `p`-adic integer, raises an ``abort`` signal. .. function:: void padic_get_mpq(mpq_t rop, const padic_t op, const padic_ctx_t ctx) Sets the GMP rational ``rop`` to the value of ``op``. .. function:: void padic_swap(padic_t op1, padic_t op2) Swaps the two `p`-adic numbers ``op1`` and ``op2``. Note that this includes swapping the precisions. In particular, this operation is not equivalent to swapping ``op1`` and ``op2`` using :func:`padic_set` and an auxiliary variable whenever the precisions of the two elements are different. .. function:: void padic_zero(padic_t rop) Sets the `p`-adic number ``rop`` to zero. .. function:: void padic_one(padic_t rop) Sets the `p`-adic number ``rop`` to one, reduced modulo the precision of ``rop``. Comparison -------------------------------------------------------------------------------- .. function:: int padic_is_zero(const padic_t op) Returns whether ``op`` is equal to zero. .. function:: int padic_is_one(const padic_t op) Returns whether ``op`` is equal to one, that is, whether `u = 1` and `v = 0`. .. function:: int padic_equal(const padic_t op1, const padic_t op2) Returns whether ``op1`` and ``op2`` are equal, that is, whether `u_1 = u_2` and `v_1 = v_2`. Arithmetic operations -------------------------------------------------------------------------------- .. function:: slong * _padic_lifts_exps(slong * n, slong N) Given a positive integer `N` define the sequence `a_0 = N, a_1 = \lceil a_0/2\rceil, \dotsc, a_{n-1} = \lceil a_{n-2}/2\rceil = 1`. Then `n = \lceil\log_2 N\rceil + 1`. This function sets `n` and allocates and returns the array `a`. .. function:: void _padic_lifts_pows(fmpz * pow, const slong * a, slong n, const fmpz_t p) Given an array `a` as computed above, this function computes the corresponding powers of `p`, that is, ``pow[i]`` is equal to `p^{a_i}`. .. function:: void padic_add(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) Sets ``rop`` to the sum of ``op1`` and ``op2``. .. function:: void padic_sub(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and ``op2``. .. function:: void padic_neg(padic_t rop, const padic_t op, const padic_ctx_t ctx) Sets ``rop`` to the additive inverse of ``op``. .. function:: void padic_mul(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``. .. function:: void padic_shift(padic_t rop, const padic_t op, slong v, const padic_ctx_t ctx) Sets ``rop`` to the product of ``op`` and `p^v`. .. function:: void padic_div(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) Sets ``rop`` to the quotient of ``op1`` and ``op2``. .. function:: void _padic_inv_precompute(padic_inv_t S, const fmpz_t p, slong N) Pre-computes some data and allocates temporary space for `p`-adic inversion using Hensel lifting. .. function:: void _padic_inv_clear(padic_inv_t S) Frees the memory used by `S`. .. function:: void _padic_inv_precomp(fmpz_t rop, const fmpz_t op, const padic_inv_t S) Sets ``rop`` to the inverse of ``op`` modulo `p^N`, assuming that ``op`` is a unit and `N \geq 1`. In the current implementation, allows aliasing, but this might change in future versions. Uses some data `S` precomputed by calling the function :func:`_padic_inv_precompute`. Note that this object is not declared ``const`` and in fact it carries a field providing temporary work space. This allows repeated calls of this function to avoid repeated memory allocations, as used e.g. by the function :func:`padic_log`. .. function:: void _padic_inv(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) Sets ``rop`` to the inverse of ``op`` modulo `p^N`, assuming that ``op`` is a unit and `N \geq 1`. In the current implementation, allows aliasing, but this might change in future versions. .. function:: void padic_inv(padic_t rop, const padic_t op, const padic_ctx_t ctx) Computes the inverse of ``op`` modulo `p^N`. Suppose that ``op`` is given as `x = u p^v`. Raises an ``abort`` signal if `v < -N`. Otherwise, computes the inverse of `u` modulo `p^{N+v}`. This function employs Hensel lifting of an inverse modulo `p`. .. function:: int padic_sqrt(padic_t rop, const padic_t op, const padic_ctx_t ctx) Returns whether ``op`` is a `p`-adic square. If this is the case, sets ``rop`` to one of the square roots; otherwise, the value of ``rop`` is undefined. We have the following theorem: Let `u \in \mathbf{Z}^{\times}`. Then `u` is a square if and only if `u \bmod p` is a square in `\mathbf{Z} / p \mathbf{Z}`, for `p > 2`, or if `u \bmod 8` is a square in `\mathbf{Z} / 8 \mathbf{Z}`, for `p = 2`. .. function:: void padic_pow_si(padic_t rop, const padic_t op, slong e, const padic_ctx_t ctx) Sets ``rop`` to ``op`` raised to the power `e`, which is defined as one whenever `e = 0`. Assumes that some computations involving `e` and the valuation of ``op`` do not overflow in the ``slong`` range. Note that if the input `x = p^v u` is defined modulo `p^N` then `x^e = p^{ev} u^e` is defined modulo `p^{N + (e - 1) v}`, which is a precision loss in case `v < 0`. Exponential -------------------------------------------------------------------------------- .. function:: slong _padic_exp_bound(slong v, slong N, const fmpz_t p) Returns an integer `i` such that for all `j \geq i` we have `\operatorname{ord}_p(x^j / j!) \geq N`, where `\operatorname{ord}_p(x) = v`. When `p` is a word-sized prime, returns `\left\lceil \frac{(p-1)N - 1}{(p-1)v - 1}\right\rceil`. Otherwise, returns `\lceil N/v\rceil`. Assumes that `v < N`. Moreover, `v` has to be at least `2` or `1`, depending on whether `p` is `2` or odd. .. function:: void _padic_exp_rectangular(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) void _padic_exp_balanced(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) void _padic_exp(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) Sets ``rop`` to the `p`-exponential function evaluated at `x = p^v u`, reduced modulo `p^N`. Assumes that `x \neq 0`, that `\operatorname{ord}_p(x) < N` and that `\exp(x)` converges, that is, that `\operatorname{ord}_p(x)` is at least `2` or `1` depending on whether the prime `p` is `2` or odd. Supports aliasing between ``rop`` and `u`. .. function:: int padic_exp(padic_t y, const padic_t x, const padic_ctx_t ctx) Returns whether the `p`-adic exponential function converges at the `p`-adic number `x`, and if so sets `y` to its value. The `p`-adic exponential function is defined by the usual series .. math:: \exp_p(x) = \sum_{i = 0}^{\infty} \frac{x^i}{i!} but this only converges only when `\operatorname{ord}_p(x) > 1 / (p - 1)`. For elements `x \in \mathbf{Q}_p`, this means that `\operatorname{ord}_p(x) \geq 1` when `p \geq 3` and `\operatorname{ord}_2(x) \geq 2` when `p = 2`. .. function:: int padic_exp_rectangular(padic_t y, const padic_t x, const padic_ctx_t ctx) Returns whether the `p`-adic exponential function converges at the `p`-adic number `x`, and if so sets `y` to its value. Uses a rectangular splitting algorithm to evaluate the series expression of `\exp(x) \bmod{p^N}`. .. function:: int padic_exp_balanced(padic_t y, const padic_t x, const padic_ctx_t ctx) Returns whether the `p`-adic exponential function converges at the `p`-adic number `x`, and if so sets `y` to its value. Uses a balanced approach, balancing the size of chunks of `x` with the valuation and hence the rate of convergence, which results in a quasi-linear algorithm in `N`, for fixed `p`. Logarithm -------------------------------------------------------------------------------- .. function:: slong _padic_log_bound(slong v, slong N, const fmpz_t p) Returns `b` such that for all `i \geq b` we have .. math:: i v - \operatorname{ord}_p(i) \geq N where `v \geq 1`. Assumes that `1 \leq v < N` or `2 \leq v < N` when `p` is odd or `p = 2`, respectively, and also that `N < 2^{f-2}` where `f` is ``FLINT_BITS``. .. function:: void _padic_log(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) void _padic_log_rectangular(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) void _padic_log_satoh(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) void _padic_log_balanced(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) Computes .. math:: z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}, reduced modulo `p^N`. Note that this can be used to compute the `p`-adic logarithm via the equation .. math:: \log(x) & = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} \\ & = - \sum_{i=1}^{\infty} \frac{(1-x)^i}{i}. Assumes that `y = 1 - x` is non-zero and that `v = \operatorname{ord}_p(y)` is at least `1` when `p` is odd and at least `2` when `p = 2` so that the series converges. Assumes that `v < N`, and hence in particular `N \geq 2`. Does not support aliasing between `y` and `z`. .. function:: int padic_log(padic_t rop, const padic_t op, const padic_ctx_t ctx) Returns whether the `p`-adic logarithm function converges at the `p`-adic number ``op``, and if so sets ``rop`` to its value. The `p`-adic logarithm function is defined by the usual series .. math:: \log_p(x) = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} but this only converges when `\operatorname{ord}_p(x - 1)` is at least `2` or `1` when `p = 2` or `p > 2`, respectively. .. function:: int padic_log_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx) Returns whether the `p`-adic logarithm function converges at the `p`-adic number ``op``, and if so sets ``rop`` to its value. Uses a rectangular splitting algorithm to evaluate the series expression of `\log(x) \bmod{p^N}`. .. function:: int padic_log_satoh(padic_t rop, const padic_t op, const padic_ctx_t ctx) Returns whether the `p`-adic logarithm function converges at the `p`-adic number ``op``, and if so sets ``rop`` to its value. Uses an algorithm based on a result of Satoh, Skjernaa and Taguchi that `\operatorname{ord}_p\bigl(a^{p^k} - 1\bigr) > k`, which implies that .. math:: \log(a) \equiv p^{-k} \Bigl( \log\bigl(a^{p^k}\bigr) \pmod{p^{N+k}} \Bigr) \pmod{p^N}. .. function:: int padic_log_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx) Returns whether the `p`-adic logarithm function converges at the `p`-adic number ``op``, and if so sets ``rop`` to its value. Special functions -------------------------------------------------------------------------------- .. function:: void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) Computes the Teichm\"uller lift of the `p`-adic unit ``op``, assuming that `N \geq 1`. Supports aliasing between ``rop`` and ``op``. .. function:: void padic_teichmuller(padic_t rop, const padic_t op, const padic_ctx_t ctx) Computes the Teichm\"uller lift of the `p`-adic unit ``op``. If ``op`` is a `p`-adic integer divisible by `p`, sets ``rop`` to zero, which satisfies `t^p - t = 0`, although it is clearly not a `(p-1)`-st root of unity. If ``op`` has negative valuation, raises an ``abort`` signal. .. function:: ulong padic_val_fac_ui_2(ulong n) Computes the `2`-adic valuation of `n!`. Note that since `n` fits into an ``ulong``, so does `\operatorname{ord}_2(n!)` since `\operatorname{ord}_2(n!) \leq (n - 1) / (p - 1) = n - 1`. .. function:: ulong padic_val_fac_ui(ulong n, const fmpz_t p) Computes the `p`-adic valuation of `n!`. Note that since `n` fits into an ``ulong``, so does `\operatorname{ord}_p(n!)` since `\operatorname{ord}_p(n!) \leq (n - 1) / (p - 1)`. .. function:: void padic_val_fac(fmpz_t rop, const fmpz_t op, const fmpz_t p) Sets ``rop`` to the `p`-adic valuation of the factorial of ``op``, assuming that ``op`` is non-negative. Input and output -------------------------------------------------------------------------------- .. function:: char * padic_get_str(char * str, const padic_t op, const padic_ctx_t ctx) Returns the string representation of the `p`-adic number ``op`` according to the printing mode set in the context. If ``str`` is ``NULL`` then a new block of memory is allocated and a pointer to this is returned. Otherwise, it is assumed that the string ``str`` is large enough to hold the representation and it is also the return value. .. function:: int _padic_fprint(FILE * file, const fmpz_t u, slong v, const padic_ctx_t ctx) int padic_fprint(FILE * file, const padic_t op, const padic_ctx_t ctx) Prints the string representation of the `p`-adic number ``op`` to the stream ``file``. In the current implementation, always returns `1`. .. function:: int _padic_print(const fmpz_t u, slong v, const padic_ctx_t ctx) int padic_print(const padic_t op, const padic_ctx_t ctx) Prints the string representation of the `p`-adic number ``op`` to the stream ``stdout``. In the current implementation, always returns `1`. .. function:: void padic_debug(const padic_t op) Prints debug information about ``op`` to the stream ``stdout``, in the format ``"(u v N)"``. flint-3.1.3/doc/source/padic_mat.rst000066400000000000000000000242131461254215100173550ustar00rootroot00000000000000.. _padic-mat: **padic_mat.h** -- matrices over p-adic numbers =============================================================================== Module documentation -------------------------------------------------------------------------------- We represent a matrix over `\mathbf{Q}_p` as a product `p^v M`, where `p` is a prime number, `v \in \mathbf{Z}` and `M` a matrix over `\mathbf{Z}`. We say this matrix is in *canonical form* if either `M` is zero, in which case we choose `v = 0`, too, or if `M` contains at least one `p`-adic unit. We say this matrix is *reduced* modulo `p^N` if it is canonical form and if all coefficients of `M` lie in the range `[0, p^{N-v})`. Macros -------------------------------------------------------------------------------- .. function:: fmpz_mat_struct * padic_mat(const padic_mat_t A) Returns a pointer to the unit part of the matrix, which is a matrix over `\mathbf{Z}`. The return value can be used as an argument to the functions in the ``fmpz_mat`` module. .. function:: fmpz * padic_mat_entry(const padic_mat_t A, slong i, slong j) Returns a pointer to unit part of the entry in position `(i, j)`. Note that this is not necessarily a unit. The return value can be used as an argument to the functions in the ``fmpz`` module. .. function:: slong padic_mat_val(const padic_mat_t A) Allow access (as L-value or R-value) to ``val`` field of `A`. This function is implemented as a macro. .. function:: slong padic_mat_prec(const padic_mat_t A) Allow access (as L-value or R-value) to ``prec`` field of `A`. This function is implemented as a macro. .. function:: slong padic_mat_get_val(const padic_mat_t A) Returns the valuation of the matrix. .. function:: slong padic_mat_get_prec(const padic_mat_t A) Returns the `p`-adic precision of the matrix. .. function:: slong padic_mat_nrows(const padic_mat_t A) Returns the number of rows of the matrix `A`. .. function:: slong padic_mat_ncols(const padic_mat_t A) Returns the number of columns of the matrix `A`. Memory management -------------------------------------------------------------------------------- .. function:: void padic_mat_init(padic_mat_t A, slong r, slong c) Initialises the matrix `A` as a zero matrix with the specified numbers of rows and columns and precision ``PADIC_DEFAULT_PREC``. .. function:: void padic_mat_init2(padic_mat_t A, slong r, slong c, slong prec) Initialises the matrix `A` as a zero matrix with the specified numbers of rows and columns and the given precision. .. function:: void padic_mat_clear(padic_mat_t A) Clears the matrix `A`. .. function:: void _padic_mat_canonicalise(padic_mat_t A, const padic_ctx_t ctx) Ensures that the matrix `A` is in canonical form. .. function:: void _padic_mat_reduce(padic_mat_t A, const padic_ctx_t ctx) Ensures that the matrix `A` is reduced modulo `p^N`, assuming that it is in canonical form already. .. function:: void padic_mat_reduce(padic_mat_t A, const padic_ctx_t ctx) Ensures that the matrix `A` is reduced modulo `p^N`, without assuming that it is necessarily in canonical form. .. function:: int padic_mat_is_empty(const padic_mat_t A) Returns whether the matrix `A` is empty, that is, whether it has zero rows or zero columns. .. function:: int padic_mat_is_square(const padic_mat_t A) Returns whether the matrix `A` is square. .. function:: int padic_mat_is_canonical(const padic_mat_t A, const padic_ctx_t p) Returns whether the matrix `A` is in canonical form. Basic assignment -------------------------------------------------------------------------------- .. function:: void padic_mat_set(padic_mat_t B, const padic_mat_t A, const padic_ctx_t p) Sets `B` to a copy of `A`, respecting the precision of `B`. .. function:: void padic_mat_swap(padic_mat_t A, padic_mat_t B) Swaps the two matrices `A` and `B`. This is done efficiently by swapping pointers. .. function:: void padic_mat_swap_entrywise(padic_mat_t mat1, padic_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: void padic_mat_zero(padic_mat_t A) Sets the matrix `A` to zero. .. function:: void padic_mat_one(padic_mat_t A) Sets the matrix `A` to the identity matrix. If the precision is negative then the matrix will be the zero matrix. Conversions -------------------------------------------------------------------------------- .. function:: void padic_mat_set_fmpq_mat(padic_mat_t B, const fmpq_mat_t A, const padic_ctx_t ctx) Sets the `p`-adic matrix `B` to the rational matrix `A`, reduced according to the given context. .. function:: void padic_mat_get_fmpq_mat(fmpq_mat_t B, const padic_mat_t A, const padic_ctx_t ctx) Sets the rational matrix `B` to the `p`-adic matrices `A`; no reduction takes place. Entries -------------------------------------------------------------------------------- Because of the choice of the data structure, representing the matrix as `p^v M`, setting an entry of the matrix might lead to changes in all entries in the matrix `M`. Also, a specific entry is not readily available as a `p`-adic number. Thus, there are separate functions available for getting and setting entries. .. function:: void padic_mat_get_entry_padic(padic_t rop, const padic_mat_t op, slong i, slong j, const padic_ctx_t ctx) Sets ``rop`` to the entry in position `(i, j)` in the matrix ``op``. .. function:: void padic_mat_set_entry_padic(padic_mat_t rop, slong i, slong j, const padic_t op, const padic_ctx_t ctx) Sets the entry in position `(i, j)` in the matrix to ``rop``. Comparison -------------------------------------------------------------------------------- .. function:: int padic_mat_equal(const padic_mat_t A, const padic_mat_t B) Returns whether the two matrices `A` and `B` are equal. .. function:: int padic_mat_is_zero(const padic_mat_t A) Returns whether the matrix `A` is zero. Input and output -------------------------------------------------------------------------------- .. function:: int padic_mat_fprint(FILE * file, const padic_mat_t A, const padic_ctx_t ctx) Prints a simple representation of the matrix `A` to the output stream ``file``. The format is the number of rows, a space, the number of columns, two spaces, followed by a list of all the entries, one row after the other. In the current implementation, always returns `1`. .. function:: int padic_mat_fprint_pretty(FILE * file, const padic_mat_t A, const padic_ctx_t ctx) Prints a *pretty* representation of the matrix `A` to the output stream ``file``. In the current implementation, always returns `1`. .. function:: int padic_mat_print(const padic_mat_t A, const padic_ctx_t ctx) int padic_mat_print_pretty(const padic_mat_t A, const padic_ctx_t ctx) Random matrix generation -------------------------------------------------------------------------------- .. function:: void padic_mat_randtest(padic_mat_t A, flint_rand_t state, const padic_ctx_t ctx) Sets `A` to a random matrix. The valuation will be in the range `[- \lceil N/10\rceil, N)`, `[N - \lceil -N/10\rceil, N)`, or `[-10, 0)` as `N` is positive, negative or zero. Transpose -------------------------------------------------------------------------------- .. function:: void padic_mat_transpose(padic_mat_t B, const padic_mat_t A) Sets `B` to `A^t`. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) Sets `C` to the exact sum `A + B`, ensuring that the result is in canonical form. .. function:: void padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) Sets `C` to the sum `A + B` modulo `p^N`. .. function:: void _padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) Sets `C` to the exact difference `A - B`, ensuring that the result is in canonical form. .. function:: void padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) Sets `C` to `A - B`, ensuring that the result is reduced. .. function:: void _padic_mat_neg(padic_mat_t B, const padic_mat_t A) Sets `B` to `-A` in canonical form. .. function:: void padic_mat_neg(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx) Sets `B` to `-A`, ensuring the result is reduced. Scalar operations -------------------------------------------------------------------------------- .. function:: void _padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx) Sets `B` to `c A`, ensuring that the result is in canonical form. .. function:: void padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx) Sets `B` to `c A`, ensuring that the result is reduced. .. function:: void _padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx) Sets `B` to `c A`, ensuring that the result is in canonical form. .. function:: void padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx) Sets `B` to `c A`, ensuring that the result is reduced. .. function:: void padic_mat_scalar_div_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx) Sets `B` to `c^{-1} A`, assuming that `c \neq 0`. Ensures that the result `B` is reduced. Multiplication -------------------------------------------------------------------------------- .. function:: void _padic_mat_mul(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) Sets `C` to the product `A B` of the two matrices `A` and `B`, ensuring that `C` is in canonical form. .. function:: void padic_mat_mul(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) Sets `C` to the product `A B` of the two matrices `A` and `B`, ensuring that `C` is reduced. flint-3.1.3/doc/source/padic_poly.rst000066400000000000000000000517571461254215100175740ustar00rootroot00000000000000.. _padic-poly: **padic_poly.h** -- polynomials over p-adic numbers =============================================================================== Module documentation -------------------------------------------------------------------------------- We represent a polynomial in `\mathbf{Q}_p[x]` as a product `p^v f(x)`, where `p` is a prime number, `v \in \mathbf{Z}` and `f(x) \in \mathbf{Z}[x]`. As a data structure, we call this polynomial *normalised* if the polynomial `f(x)` is *normalised*, that is, if the top coefficient is non-zero. We say this polynomial is in *canonical form* if one of the coefficients of `f(x)` is a `p`-adic unit. If `f(x)` is the zero polynomial, we require that `v = 0`. We say this polynomial is *reduced* modulo `p^N` if it is canonical form and if all coefficients lie in the range `[0, p^N)`. Memory management -------------------------------------------------------------------------------- .. function:: void padic_poly_init(padic_poly_t poly) Initialises ``poly`` for use, setting its length to zero. The precision of the polynomial is set to ``PADIC_DEFAULT_PREC``. A corresponding call to :func:`padic_poly_clear` must be made after finishing with the :type:`padic_poly_t` to free the memory used by the polynomial. .. function:: void padic_poly_init2(padic_poly_t poly, slong alloc, slong prec) Initialises ``poly`` with space for at least ``alloc`` coefficients and sets the length to zero. The allocated coefficients are all set to zero. The precision is set to ``prec``. .. function:: void padic_poly_realloc(padic_poly_t poly, slong alloc, const fmpz_t p) Reallocates the given polynomial to have space for ``alloc`` coefficients. If ``alloc`` is zero the polynomial is cleared and then reinitialised. If the current length is greater than ``alloc`` the polynomial is first truncated to length ``alloc``. .. function:: void padic_poly_fit_length(padic_poly_t poly, slong len) If ``len`` is greater than the number of coefficients currently allocated, then the polynomial is reallocated to have space for at least ``len`` coefficients. No data is lost when calling this function. The function efficiently deals with the case where ``fit_length`` is called many times in small increments by at least doubling the number of allocated coefficients when length is larger than the number of coefficients currently allocated. .. function:: void _padic_poly_set_length(padic_poly_t poly, slong len) Demotes the coefficients of ``poly`` beyond ``len`` and sets the length of ``poly`` to ``len``. Note that if the current length is greater than ``len`` the polynomial may no slonger be in canonical form. .. function:: void padic_poly_clear(padic_poly_t poly) Clears the given polynomial, releasing any memory used. It must be reinitialised in order to be used again. .. function:: void _padic_poly_normalise(padic_poly_t poly) Sets the length of ``poly`` so that the top coefficient is non-zero. If all coefficients are zero, the length is set to zero. This function is mainly used internally, as all functions guarantee normalisation. .. function:: void _padic_poly_canonicalise(fmpz * poly, slong * v, slong len, const fmpz_t p) void padic_poly_canonicalise(padic_poly_t poly, const fmpz_t p) Brings the polynomial ``poly`` into canonical form, assuming that it is normalised already. Does *not* carry out any reduction. .. function:: void padic_poly_reduce(padic_poly_t poly, const padic_ctx_t ctx) Reduces the polynomial ``poly`` modulo `p^N`, assuming that it is in canonical form already. .. function:: void padic_poly_truncate(padic_poly_t poly, slong n, const fmpz_t p) Truncates the polynomial to length at most~`n`. Polynomial parameters -------------------------------------------------------------------------------- .. function:: slong padic_poly_degree(const padic_poly_t poly) Returns the degree of the polynomial ``poly``. .. function:: slong padic_poly_length(const padic_poly_t poly) Returns the length of the polynomial ``poly``. .. function:: slong padic_poly_val(const padic_poly_t poly) Returns the valuation of the polynomial ``poly``, which is defined to be the minimum valuation of all its coefficients. The valuation of the zero polynomial is~`0`. Note that this is implemented as a macro and can be used as either a ``lvalue`` or a ``rvalue``. .. function:: slong padic_poly_prec(padic_poly_t poly) Returns the precision of the polynomial ``poly``. Note that this is implemented as a macro and can be used as either a ``lvalue`` or a ``rvalue``. Note that increasing the precision might require a call to :func:`padic_poly_reduce`. Randomisation -------------------------------------------------------------------------------- .. function:: void padic_poly_randtest(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx) Sets `f` to a random polynomial of length at most ``len`` with entries reduced modulo `p^N`. .. function:: void padic_poly_randtest_not_zero(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx) Sets `f` to a non-zero random polynomial of length at most ``len`` with entries reduced modulo `p^N`. .. function:: void padic_poly_randtest_val(padic_poly_t f, flint_rand_t state, slong val, slong len, const padic_ctx_t ctx) Sets `f` to a random polynomial of length at most ``len`` with at most the prescribed valuation ``val`` and entries reduced modulo `p^N`. Specifically, we aim to set the valuation to be exactly equal to ``val``, but do not check for additional cancellation when creating the coefficients. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void padic_poly_set_padic(padic_poly_t poly, const padic_t x, const padic_ctx_t ctx) Sets the polynomial ``poly`` to the `p`-adic number `x`, reduced to the precision of the polynomial. .. function:: void padic_poly_set(padic_poly_t poly1, const padic_poly_t poly2, const padic_ctx_t ctx) Sets the polynomial ``poly1`` to the polynomial ``poly2``, reduced to the precision of ``poly1``. .. function:: void padic_poly_set_si(padic_poly_t poly, slong x, const padic_ctx_t ctx) Sets the polynomial ``poly`` to the ``signed slong`` integer `x` reduced to the precision of the polynomial. .. function:: void padic_poly_set_ui(padic_poly_t poly, ulong x, const padic_ctx_t ctx) Sets the polynomial ``poly`` to the ``unsigned slong`` integer `x` reduced to the precision of the polynomial. .. function:: void padic_poly_set_fmpz(padic_poly_t poly, const fmpz_t x, const padic_ctx_t ctx) Sets the polynomial ``poly`` to the integer `x` reduced to the precision of the polynomial. .. function:: void padic_poly_set_fmpq(padic_poly_t poly, const fmpq_t x, const padic_ctx_t ctx) Sets the polynomial ``poly`` to the value of the rational `x`, reduced to the precision of the polynomial. .. function:: void padic_poly_set_fmpz_poly(padic_poly_t rop, const fmpz_poly_t op, const padic_ctx_t ctx) Sets the polynomial ``rop`` to the integer polynomial ``op`` reduced to the precision of the polynomial. .. function:: void padic_poly_set_fmpq_poly(padic_poly_t rop, const fmpq_poly_t op, const padic_ctx_t ctx) Sets the polynomial ``rop`` to the value of the rational polynomial ``op``, reduced to the precision of the polynomial. .. function:: int padic_poly_get_fmpz_poly(fmpz_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx) Sets the integer polynomial ``rop`` to the value of the `p`-adic polynomial ``op`` and returns `1` if the polynomial is `p`-adically integral. Otherwise, returns `0`. .. function:: void padic_poly_get_fmpq_poly(fmpq_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx) Sets ``rop`` to the rational polynomial corresponding to the `p`-adic polynomial ``op``. .. function:: void padic_poly_zero(padic_poly_t poly) Sets ``poly`` to the zero polynomial. .. function:: void padic_poly_one(padic_poly_t poly) Sets ``poly`` to the constant polynomial `1`, reduced to the precision of the polynomial. .. function:: void padic_poly_swap(padic_poly_t poly1, padic_poly_t poly2) Swaps the two polynomials ``poly1`` and ``poly2``, including their precisions. This is done efficiently by swapping pointers. Getting and setting coefficients -------------------------------------------------------------------------------- .. function:: void padic_poly_get_coeff_padic(padic_t c, const padic_poly_t poly, slong n, const padic_ctx_t ctx) Sets `c` to the coefficient of `x^n` in the polynomial, reduced modulo the precision of `c`. .. function:: void padic_poly_set_coeff_padic(padic_poly_t f, slong n, const padic_t c, const padic_ctx_t ctx) Sets the coefficient of `x^n` in the polynomial `f` to `c`, reduced to the precision of the polynomial `f`. Note that this operation can take linear time in the length of the polynomial. Comparison -------------------------------------------------------------------------------- .. function:: int padic_poly_equal(const padic_poly_t poly1, const padic_poly_t poly2) Returns whether the two polynomials ``poly1`` and ``poly2`` are equal. .. function:: int padic_poly_is_zero(const padic_poly_t poly) Returns whether the polynomial ``poly`` is the zero polynomial. .. function:: int padic_poly_is_one(const padic_poly_t poly) Returns whether the polynomial ``poly`` is equal to the constant polynomial~`1`, taking the precision of the polynomial into account. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _padic_poly_add(fmpz * rop, slong * rval, slong N, const fmpz * op1, slong val1, slong len1, slong N1, const fmpz * op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx) Sets ``(rop, *val, FLINT_MAX(len1, len2)`` to the sum of ``(op1, val1, len1)`` and ``(op2, val2, len2)``. Assumes that the input is reduced and guarantees that this is also the case for the output. Assumes that `\min\{v_1, v_2\} < N`. Supports aliasing between the output and input arguments. .. function:: void padic_poly_add(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx) Sets `f` to the sum `g + h`. .. function:: void _padic_poly_sub(fmpz * rop, slong * rval, slong N, const fmpz * op1, slong val1, slong len1, slong N1, const fmpz * op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx) Sets ``(rop, *val, FLINT_MAX(len1, len2)`` to the difference of ``(op1, val1, len1)`` and ``(op2, val2, len2)``. Assumes that the input is reduced and guarantees that this is also the case for the output. Assumes that `\min\{v_1, v_2\} < N`. Support aliasing between the output and input arguments. .. function:: void padic_poly_sub(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx) Sets `f` to the difference `g - h`. .. function:: void padic_poly_neg(padic_poly_t f, const padic_poly_t g, const padic_ctx_t ctx) Sets `f` to `-g`. Scalar multiplication -------------------------------------------------------------------------------- .. function:: void _padic_poly_scalar_mul_padic(fmpz * rop, slong * rval, slong N, const fmpz * op, slong val, slong len, const padic_t c, const padic_ctx_t ctx) Sets ``(rop, *rval, len)`` to ``(op, val, len)`` multiplied by the scalar `c`. The result will only be correctly reduced if the polynomial is non-zero. Otherwise, the array ``(rop, len)`` will be set to zero but the valuation ``*rval`` might be wrong. .. function:: void padic_poly_scalar_mul_padic(padic_poly_t rop, const padic_poly_t op, const padic_t c, const padic_ctx_t ctx) Sets the polynomial ``rop`` to the product of the polynomial ``op`` and the `p`-adic number `c`, reducing the result modulo `p^N`. Multiplication -------------------------------------------------------------------------------- .. function:: void _padic_poly_mul(fmpz * rop, slong * rval, slong N, const fmpz * op1, slong val1, slong len1, const fmpz * op2, slong val2, slong len2, const padic_ctx_t ctx) Sets ``(rop, *rval, len1 + len2 - 1)`` to the product of ``(op1, val1, len1)`` and ``(op2, val2, len2)``. Assumes that the resulting valuation ``*rval``, which is the sum of the valuations ``val1`` and ``val2``, is less than the precision~`N` of the context. Assumes that ``len1 >= len2 > 0``. .. function:: void padic_poly_mul(padic_poly_t res, const padic_poly_t poly1, const padic_poly_t poly2, const padic_ctx_t ctx) Sets the polynomial ``res`` to the product of the two polynomials ``poly1`` and ``poly2``, reduced modulo `p^N`. Powering -------------------------------------------------------------------------------- .. function:: void _padic_poly_pow(fmpz * rop, slong * rval, slong N, const fmpz * op, slong val, slong len, ulong e, const padic_ctx_t ctx) Sets the polynomial ``(rop, *rval, e (len - 1) + 1)`` to the polynomial ``(op, val, len)`` raised to the power~`e`. Assumes that `e > 1` and ``len > 0``. Does not support aliasing between the input and output arguments. .. function:: void padic_poly_pow(padic_poly_t rop, const padic_poly_t op, ulong e, const padic_ctx_t ctx) Sets the polynomial ``rop`` to the polynomial ``op`` raised to the power~`e`, reduced to the precision in ``rop``. In the special case `e = 0`, sets ``rop`` to the constant polynomial one reduced to the precision of ``rop``. Also note that when `e = 1`, this operation sets ``rop`` to ``op`` and then reduces ``rop``. When the valuation of the input polynomial is negative, this results in a loss of `p`-adic precision. Suppose that the input polynomial is given to precision~`N` and has valuation~`v < 0`. The result then has valuation `e v < 0` but is only correct to precision `N + (e - 1) v`. Series inversion -------------------------------------------------------------------------------- .. function:: void padic_poly_inv_series(padic_poly_t g, const padic_poly_t f, slong n, const padic_ctx_t ctx) Computes the power series inverse `g` of `f` modulo `X^n`, where `n \geq 1`. Given the polynomial `f \in \mathbf{Q}[X] \subset \mathbf{Q}_p[X]`, there exists a unique polynomial `f^{-1} \in \mathbf{Q}[X]` such that `f f^{-1} = 1` modulo `X^n`. This function sets `g` to `f^{-1}` reduced modulo `p^N`. Assumes that the constant coefficient of `f` is non-zero. Moreover, assumes that the valuation of the constant coefficient of `f` is minimal among the coefficients of `f`. Note that the result `g` is zero if and only if `- \operatorname{ord}_p(f) \geq N`. Derivative -------------------------------------------------------------------------------- .. function:: void _padic_poly_derivative(fmpz * rop, slong * rval, slong N, const fmpz * op, slong val, slong len, const padic_ctx_t ctx) Sets ``(rop, rval)`` to the derivative of ``(op, val)`` reduced modulo `p^N`. Supports aliasing of the input and the output parameters. .. function:: void padic_poly_derivative(padic_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx) Sets ``rop`` to the derivative of ``op``, reducing the result modulo the precision of ``rop``. Shifting -------------------------------------------------------------------------------- .. function:: void padic_poly_shift_left(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx) Notationally, sets the polynomial ``rop`` to the polynomial ``op`` multiplied by `x^n`, where `n \geq 0`, and reduces the result. .. function:: void padic_poly_shift_right(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx) Notationally, sets the polynomial ``rop`` to the polynomial ``op`` after floor division by `x^n`, where `n \geq 0`, ensuring the result is reduced. Evaluation -------------------------------------------------------------------------------- .. function:: void _padic_poly_evaluate_padic(fmpz_t u, slong * v, slong N, const fmpz * poly, slong val, slong len, const fmpz_t a, slong b, const padic_ctx_t ctx) void padic_poly_evaluate_padic(padic_t y, const padic_poly_t poly, const padic_t a, const padic_ctx_t ctx) Sets the `p`-adic number ``y`` to ``poly`` evaluated at `a`, reduced in the given context. Suppose that the polynomial can be written as `F(X) = p^w f(X)` with `\operatorname{ord}_p(f) = 1`, that `\operatorname{ord}_p(a) = b` and that both are defined to precision~`N`. Then `f` is defined to precision `N-w` and so `f(a)` is defined to precision `N-w` when `a` is integral and `N-w+(n-1)b` when `b < 0`, where `n = \deg(f)`. Thus, `y = F(a)` is defined to precision `N` when `a` is integral and `N+(n-1)b` when `b < 0`. Composition -------------------------------------------------------------------------------- .. function:: void _padic_poly_compose(fmpz * rop, slong * rval, slong N, const fmpz * op1, slong val1, slong len1, const fmpz * op2, slong val2, slong len2, const padic_ctx_t ctx) Sets ``(rop, *rval, (len1-1)*(len2-1)+1)`` to the composition of the two input polynomials, reducing the result modulo `p^N`. Assumes that ``len1`` is non-zero. Does not support aliasing. .. function:: void padic_poly_compose(padic_poly_t rop, const padic_poly_t op1, const padic_poly_t op2, const padic_ctx_t ctx) Sets ``rop`` to the composition of ``op1`` and ``op2``, reducing the result in the given context. To be clear about the order of composition, let `f(X)` and `g(X)` denote the polynomials ``op1`` and ``op2``, respectively. Then ``rop`` is set to `f(g(X))`. .. function:: void _padic_poly_compose_pow(fmpz * rop, slong * rval, slong N, const fmpz * op, slong val, slong len, slong k, const padic_ctx_t ctx) Sets ``(rop, *rval, (len - 1)*k + 1)`` to the composition of ``(op, val, len)`` and the monomial `x^k`, where `k \geq 1`. Assumes that ``len`` is positive. Supports aliasing between the input and output polynomials. .. function:: void padic_poly_compose_pow(padic_poly_t rop, const padic_poly_t op, slong k, const padic_ctx_t ctx) Sets ``rop`` to the composition of ``op`` and the monomial `x^k`, where `k \geq 1`. Note that no reduction takes place. Input and output -------------------------------------------------------------------------------- .. function:: int padic_poly_debug(const padic_poly_t poly) Prints the data defining the `p`-adic polynomial ``poly`` in a simple format useful for debugging purposes. In the current implementation, always returns `1`. .. function:: int _padic_poly_fprint(FILE * file, const fmpz * poly, slong val, slong len, const padic_ctx_t ctx) int padic_poly_fprint(FILE * file, const padic_poly_t poly, const padic_ctx_t ctx) Prints a simple representation of the polynomial ``poly`` to the stream ``file``. A non-zero polynomial is represented by the number of coefficients, two spaces, followed by a list of the coefficients, which are printed in a way depending on the print mode, In the ``PADIC_TERSE`` mode, the coefficients are printed as rational numbers. The ``PADIC_SERIES`` mode is currently not supported and will raise an abort signal. In the ``PADIC_VAL_UNIT`` mode, the coefficients are printed in the form `p^v u`. The zero polynomial is represented by ``"0"``. In the current implementation, always returns `1`. .. function:: int _padic_poly_print(const fmpz * poly, slong val, slong len, const padic_ctx_t ctx) int padic_poly_print(const padic_poly_t poly, const padic_ctx_t ctx) Prints a simple representation of the polynomial ``poly`` to ``stdout``. In the current implementation, always returns `1`. .. function:: int _padic_poly_fprint_pretty(FILE * file, const fmpz * poly, slong val, slong len, const char * var, const padic_ctx_t ctx) int padic_poly_fprint_pretty(FILE * file, const padic_poly_t poly, const char * var, const padic_ctx_t ctx) int _padic_poly_print_pretty(const fmpz * poly, slong val, slong len, const char * var, const padic_ctx_t ctx) int padic_poly_print_pretty(const padic_poly_t poly, const char * var, const padic_ctx_t ctx) Testing -------------------------------------------------------------------------------- .. function:: int _padic_poly_is_canonical(const fmpz * op, slong val, slong len, const padic_ctx_t ctx) int padic_poly_is_canonical(const padic_poly_t op, const padic_ctx_t ctx) int _padic_poly_is_reduced(const fmpz * op, slong val, slong len, slong N, const padic_ctx_t ctx) int padic_poly_is_reduced(const padic_poly_t op, const padic_ctx_t ctx) flint-3.1.3/doc/source/partitions.rst000066400000000000000000000071561461254215100176370ustar00rootroot00000000000000.. _partitions: **partitions.h** -- computation of the partition function =============================================================================== This module implements the asymptotically fast algorithm for evaluating the integer partition function `p(n)` described in [Joh2012]_. The idea is to evaluate a truncation of the Hardy-Ramanujan-Rademacher series using tight precision estimates, and symbolically factoring the occurring exponential sums. An implementation based on floating-point arithmetic can also be found in FLINT. That version relies on some numerical subroutines that have not been proved correct. The implementation provided here uses ball arithmetic throughout to guarantee a correct error bound for the numerical approximation of `p(n)`. Optionally, hardware double arithmetic can be used for low-precision terms. This gives a significant speedup for small (e.g. `n < 10^6`). .. function:: void partitions_rademacher_bound(arf_t b, const fmpz_t n, ulong N) Sets `b` to an upper bound for .. math:: M(n,N) = \frac{44 \pi^2}{225 \sqrt 3} N^{-1/2} + \frac{\pi \sqrt{2}}{75} \left( \frac{N}{n-1} \right)^{1/2} \sinh\left(\frac{\pi}{N} \sqrt{\frac{2n}{3}}\right). This formula gives an upper bound for the truncation error in the Hardy-Ramanujan-Rademacher formula when the series is taken up to the term `t(n,N)` inclusive. .. function:: void partitions_hrr_sum_arb(arb_t x, const fmpz_t n, slong N0, slong N, int use_doubles) Evaluates the partial sum `\sum_{k=N_0}^N t(n,k)` of the Hardy-Ramanujan-Rademacher series. If *use_doubles* is nonzero, doubles and the system's standard library math functions are used to evaluate the smallest terms. This significantly speeds up evaluation for small `n` (e.g. `n < 10^6`), and gives a small speed improvement for larger `n`, but the result is not guaranteed to be correct. In practice, the error is estimated very conservatively, and unless the system's standard library is broken, use of doubles can be considered safe. Setting *use_doubles* to zero gives a fully guaranteed bound. .. function:: void partitions_fmpz_fmpz(fmpz_t p, const fmpz_t n, int use_doubles) Computes the partition function `p(n)` using the Hardy-Ramanujan-Rademacher formula. This function computes a numerical ball containing `p(n)` and verifies that the ball contains a unique integer. If *n* is sufficiently large and a number of threads greater than 1 has been selected with :func:`flint_set_num_threads()`, the computation time will be reduced by using two threads. See :func:`partitions_hrr_sum_arb` for an explanation of the *use_doubles* option. .. function:: void partitions_fmpz_ui(fmpz_t p, ulong n) Computes the partition function `p(n)` using the Hardy-Ramanujan-Rademacher formula. This function computes a numerical ball containing `p(n)` and verifies that the ball contains a unique integer. .. function:: void partitions_fmpz_ui_using_doubles(fmpz_t p, ulong n) Computes the partition function `p(n)`, enabling the use of doubles internally. This significantly speeds up evaluation for small `n` (e.g. `n < 10^6`), but the error bounds are not certified (see remarks for :func:`partitions_hrr_sum_arb`). .. function:: void partitions_leading_fmpz(arb_t res, const fmpz_t n, slong prec) Sets *res* to the leading term in the Hardy-Ramanujan series for `p(n)` (without Rademacher's correction of this term, which is vanishingly small when `n` is large), that is, `\sqrt{12} (1-1/t) e^t / (24n-1)` where `t = \pi \sqrt{24n-1} / 6`. flint-3.1.3/doc/source/perm.rst000066400000000000000000000036571461254215100164100ustar00rootroot00000000000000.. _perm: **perm.h** -- permutations =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: slong * _perm_init(slong n) Initialises the permutation for use. .. function:: void _perm_clear(slong * vec) Clears the permutation. Assignment -------------------------------------------------------------------------------- .. function:: void _perm_set(slong * res, const slong * vec, slong n) Sets the permutation ``res`` to the same as the permutation ``vec``. .. function:: void _perm_one(slong * vec, slong n) Sets the permutation to the identity permutation. .. function:: void _perm_inv(slong * res, const slong * vec, slong n) Sets ``res`` to the inverse permutation of ``vec``. Allows aliasing of ``res`` and ``vec``. Composition -------------------------------------------------------------------------------- .. function:: void _perm_compose(slong * res, const slong * vec1, const slong * vec2, slong n) Forms the composition `\pi_1 \circ \pi_2` of two permutations `\pi_1` and `\pi_2`. Here, `\pi_2` is applied first, that is, `(\pi_1 \circ \pi_2)(i) = \pi_1(\pi_2(i))`. Allows aliasing of ``res``, ``vec1`` and ``vec2``. Parity -------------------------------------------------------------------------------- .. function:: int _perm_parity(const slong * vec, slong n) Returns the parity of ``vec``, 0 if the permutation is even and 1 if the permutation is odd. Randomisation -------------------------------------------------------------------------------- .. function:: int _perm_randtest(slong * vec, slong n, flint_rand_t state) Generates a random permutation vector of length `n` and returns its parity, 0 or 1. This function uses the Knuth shuffle algorithm to generate a uniformly random permutation without retries. flint-3.1.3/doc/source/polylogarithms.rst000066400000000000000000000077511461254215100205210ustar00rootroot00000000000000.. _algorithms_polylogarithms: Algorithms for polylogarithms =============================================================================== The polylogarithm is defined for `s, z \in \mathbb{C}` with `|z| < 1` by .. math:: \operatorname{Li}_s(z) = \sum_{k=1}^{\infty} \frac{z^k}{k^s} and for `|z| \ge 1` by analytic continuation, except for the singular point `z = 1`. Computation for small z ------------------------------------------------------------------------------- The power sum converges rapidly when `|z| \ll 1`. To compute the series expansion with respect to `s`, we substitute `s \to s + x \in \mathbb{C}[[x]]` and obtain .. math:: \operatorname{Li}_{s+x}(z) = \sum_{d=0}^{\infty} x^d \frac{(-1)^d}{d!} \sum_{k=1}^{\infty} T(k) where .. math:: T(k) = \frac{z^k \log^d(k)}{k^s}. The remainder term `\left| \sum_{k=N}^{\infty} T(k) \right|` is bounded via the following strategy, implemented in :func:`mag_polylog_tail`. Denote the terms by `T(k)`. We pick a nonincreasing function `U(k)` such that .. math:: \frac{T(k+1)}{T(k)} = z \left(\frac{k}{k+1}\right)^s \left( \frac{\log(k+1)}{\log(k)} \right)^d \le U(k). Then, as soon as `U(N) < 1`, .. math:: \sum_{k=N}^{\infty} T(k) \le T(N) \sum_{k=0}^{\infty} U(N)^k = \frac{T(N)}{1 - U(N)}. In particular, we take .. math:: U(k) = z \; B(k, \max(0, -s)) \; B(k \log(k), d) where `B(m,n) = (1 + 1/m)^n`. This follows from the bounds .. math:: \left(\frac{k}{k+1}\right)^{s} \le \begin{cases} 1 & \text{if } s \ge 0 \\ (1 + 1/k)^{-s} & \text{if } s < 0. \end{cases} and .. math:: \left( \frac{\log(k+1)}{\log(k)} \right)^d \le \left(1 + \frac{1}{k \log(k)}\right)^d. Expansion for general z ------------------------------------------------------------------------------- For general complex `s, z`, we write the polylogarithm as a sum of two Hurwitz zeta functions .. math:: \operatorname{Li}_s(z) = \frac{\Gamma(v)}{(2\pi)^v} \left[ i^v \zeta \left(v, \frac{1}{2} + \frac{\log(-z)}{2\pi i}\right) + i^{-v} \zeta \left(v, \frac{1}{2} - \frac{\log(-z)}{2\pi i}\right) \right] in which `s = 1-v`. With the principal branch of `\log(-z)`, we obtain the conventional analytic continuation of the polylogarithm with a branch cut on `z \in (1,+\infty)`. To compute the series expansion with respect to `v`, we substitute `v \to v + x \in \mathbb{C}[[x]]` in this formula (at the end of the computation, we map `x \to -x` to obtain the power series for `\operatorname{Li}_{s+x}(z)`). The right hand side becomes .. math:: \Gamma(v+x) [E_1 Z_1 + E_2 Z_2] where `E_1 = (i/(2 \pi))^{v+x}`, `Z_1 = \zeta(v+x,\ldots)`, `E_2 = (1/(2 \pi i))^{v+x}`, `Z_2 = \zeta(v+x,\ldots)`. When `v = 1`, the `Z_1` and `Z_2` terms become Laurent series with a leading `1/x` term. In this case, we compute the deflated series `\tilde Z_1, \tilde Z_2 = \zeta(x,\ldots) - 1/x`. Then .. math:: E_1 Z_1 + E_2 Z_2 = (E_1 + E_2)/x + E_1 \tilde Z_1 + E_2 \tilde Z_2. Note that `(E_1 + E_2) / x` is a power series, since the constant term in `E_1 + E_2` is zero when `v = 1`. So we simply compute one extra derivative of both `E_1` and `E_2`, and shift them one step. When `v = 0, -1, -2, \ldots`, the `\Gamma(v+x)` prefactor has a pole. In this case, we proceed analogously and formally multiply `x \, \Gamma(v+x)` with `[E_1 Z_1 + E_2 Z_2] / x`. Note that the formal cancellation only works when the order `s` (or `v`) is an exact integer: it is not currently possible to use this method when `s` is a small ball containing any of `0, 1, 2, \ldots` (then the result becomes indeterminate). The Hurwitz zeta method becomes inefficient when `|z| \to 0` (it gives an indeterminate result when `z = 0`). This is not a problem since we just use the defining series for the polylogarithm in that region. It also becomes inefficient when `|z| \to \infty`, for which an asymptotic expansion would better. flint-3.1.3/doc/source/portability.rst000066400000000000000000000027451461254215100200040ustar00rootroot00000000000000.. _portability: **Portability** =============================================================================== Portable FLINT types ------------------------------------------------------------------------------- For platform independence, FLINT provides two types ``ulong`` and ``slong`` to replace ``unsigned long`` and ``long`` respectively. These are guaranteed to be the same size as GMP's ``mp_limb_t`` and ``mp_limb_signed_t`` types, respectively. A full list of types provided by FLINT is available in ``code_conventions.txt`` in the top-level source tree. As FLINT supports Windows 64 on which the FLINT ``ulong`` and ``slong`` types are 64 bits, whilst ``unsigned long`` and ``long`` are only 32 bits, it is necessary to have a special format specifier which is 64 bits on Windows 64 instead of the usual ``"%lu"`` and ``"%ld"``. For this purpose FLINT provides its own I/O functions, ``flint_printf``, ``flint_fprintf``, ``flint_sprintf``, ``flint_scanf``, ``flint_fscanf`` and ``flint_sscanf``, which work exactly as the usual system versions, but which take the ``"%wu"`` and ``"%wd"`` format specifiers, which support FLINT ``ulong`` and ``slong`` types respectively. Also, instead of using constants ``123UL`` and ``123L``, FLINT provides the macros ``UWORD(123)`` and ``WORD(123)`` respectively for constants of type ``ulong`` and ``slong`` respectively. The maximum and minimum values that can be represented by these types are given by ``UWORD_MAX`` and ``WORD_MAX`` respectively. flint-3.1.3/doc/source/profiler.rst000066400000000000000000000114651461254215100172630ustar00rootroot00000000000000.. _profiler: **profiler.h** -- performance profiling =============================================================================== Timer based on the cycle counter -------------------------------------------------------------------------------- .. function:: void timeit_start(timeit_t t) void timeit_stop(timeit_t t) Gives wall and user time - useful for parallel programming. Example usage:: timeit_t t0; // ... timeit_start(t0); // do stuff, take some time timeit_stop(t0); flint_printf("cpu = %wd ms wall = %wd ms\n", t0->cpu, t0->wall); .. function:: void start_clock(int n) .. function:: void stop_clock(int n) .. function:: double get_clock(int n) Gives time based on cycle counter. First one must ensure the processor speed in cycles per second is set correctly in ``profiler.h``, in the macro definition ``#define FLINT_CLOCKSPEED``. One can access the cycle counter directly by :func:`get_cycle_counter` which returns the current cycle counter as a ``double``. A sample usage of clocks is:: init_all_clocks(); start_clock(n); // do something stop_clock(n); flint_printf("Time in seconds is %f.3\n", get_clock(n)); where ``n`` is a clock number (from 0-19 by default). The number of clocks can be changed by altering ``FLINT_NUM_CLOCKS``. One can also initialise an individual clock with ``init_clock(n)``. Framework for repeatedly sampling a single target -------------------------------------------------------------------------------- .. function:: void prof_repeat(double * min, double * max, profile_target_t target, void * arg) Allows one to automatically time a given function. Here is a sample usage: Suppose one has a function one wishes to profile:: void myfunc(ulong a, ulong b); One creates a struct for passing arguments to our function:: typedef struct { ulong a, b; } myfunc_t; a sample function:: void sample_myfunc(void * arg, ulong count) { myfunc_t * params = (myfunc_t *) arg; ulong a = params->a; ulong b = params->b; for (ulong i = 0; i < count; i++) { prof_start(); myfunc(a, b); prof_stop(); } } Then we do the profile:: double min, max; myfunc_t params; params.a = 3; params.b = 4; prof_repeat(&min, &max, sample_myfunc, ¶ms); flint_printf("Min time is %lf.3s, max time is %lf.3s\n", min, max); If either of the first two parameters to ``prof_repeat`` is ``NULL``, that value is not stored. One may set the minimum time in microseconds for a timing run by adjusting ``DURATION_THRESHOLD`` and one may set a target duration in microseconds by adjusting ``DURATION_TARGET`` in ``profiler.h``. Memory usage -------------------------------------------------------------------------------- .. function:: void get_memory_usage(meminfo_t meminfo) Obtains information about the memory usage of the current process. The meminfo object contains the slots ``size`` (virtual memory size), ``peak`` (peak virtual memory size), ``rss`` (resident set size), ``hwm`` (peak resident set size). The values are stored in kilobytes (1024 bytes). This function currently only works on Linux. Simple profiling macros -------------------------------------------------------------------------------- .. macro:: TIMEIT_REPEAT(timer, reps) .. macro:: TIMEIT_END_REPEAT(timer, reps) Repeatedly runs the code between the ``TIMEIT_REPEAT`` and the ``TIMEIT_END_REPEAT`` markers, automatically increasing the number of repetitions until the elapsed time exceeds the timer resolution. The macro takes as input a predefined ``timeit_t`` object and an integer variable to hold the number of repetitions. .. macro:: TIMEIT_START .. macro:: TIMEIT_STOP Repeatedly runs the code between the ``TIMEIT_START`` and the ``TIMEIT_STOP`` markers, automatically increasing the number of repetitions until the elapsed time exceeds the timer resolution, and then prints the average elapsed cpu and wall time for a single repetition. .. macro:: TIMEIT_ONCE_START .. macro:: TIMEIT_ONCE_STOP Runs the code between the ``TIMEIT_ONCE_START`` and the ``TIMEIT_ONCE_STOP`` markers exactly once and then prints the elapsed cpu and wall time. This does not give a precise measurement if the elapsed time is short compared to the timer resolution. .. macro:: SHOW_MEMORY_USAGE Retrieves memory usage information via ``get_memory_usage`` and prints the results. flint-3.1.3/doc/source/python_flint.rst000066400000000000000000000043161461254215100201530ustar00rootroot00000000000000.. _pyflint: **flint_ctypes** - Python interface =============================================================================== There is a Python wrapper (``flint_ctypes``) included with FLINT available in the ``src/python`` directory. This wrapper is not currently officially supported and should not be used in production, but it can be useful for experimenting with FLINT. .. highlight:: python3 Introduction ------------------------------------------------------------------------------- Examples:: >>> from flint_ctypes import * >>> QQ.bernoulli(50) 495057205241079648212477525/66 >>> sign, primes, exponents = _.factor() >>> sign 1 >>> primes [5, 417202699, 47464429777438199, 2, 3, 11] >>> exponents [2, 1, 1, -1, -1, -1] >>> sign * (primes ** exponents).product() 495057205241079648212477525/66 Types, parents and coercions ............................................................................... >>> ZZ(5) 5 >>> _.parent() Integer ring (fmpz) >>> QQ(5) 5 >>> _.parent() Rational field (fmpq) >>> ZZ(10) / ZZ(6) Traceback (most recent call last): ... FlintDomainError: x / y is not an element of {Integer ring (fmpz)} for {x = 10}, {y = 6} >>> x = QQ(1) / 2; x ** x Traceback (most recent call last): ... FlintDomainError: x ** y is not an element of {Rational field (fmpq)} for {x = 1/2}, {y = 1/2} >>> ZZ(10) / QQ(6) 5/3 >>> x = QQbar(1) / 2; x ** x Root a = 0.707107 of 2*a^2-1 Real and complex numbers ............................................................................... >>> RR.zeta(2) [1.644934066848226 +/- 4.57e-16] >>> RR.prec = 128 >>> RR.zeta(2) [1.64493406684822643647241516664602518922 +/- 2.88e-39] >>> RR.prec = 53 # restore default API documentation ------------------------------------------------------------------------------- .. automodsumm:: flint_ctypes .. autoclass:: flint_ctypes.FlintDomainError .. autoclass:: flint_ctypes.FlintUnableError .. automodule:: flint_ctypes .. :members: .. :undoc-members: .. :special-members: __init__ , __bool__ .. :member-order: bysource .. raw:: latex \newpage flint-3.1.3/doc/source/qadic.rst000066400000000000000000000515131461254215100165200ustar00rootroot00000000000000.. _qadic: **qadic.h** -- unramified extensions over p-adic numbers =============================================================================== Data structures -------------------------------------------------------------------------------- We represent an element of the extension `\mathbf{Q}_q \cong \mathbf{Q}_p[X] / (f(X))` as a polynomial in `\mathbf{Q}_p[X]` of degree less than `\deg(f)`. As such, ``qadic_struct`` and ``qadic_t`` are typedef'ed as ``padic_poly_struct`` and ``padic_poly_t``. Context -------------------------------------------------------------------------------- We represent an unramified extension of `\mathbf{Q}_p` via `\mathbf{Q}_q \cong \mathbf{Q}_p[X] / (f(X))`, where `f \in \mathbf{Q}_p[X]` is a monic, irreducible polynomial which we assume to actually be in `\mathbf{Z}[X]`. The first field in the context structure is a `p`-adic context struct ``pctx``, which contains data about the prime `p`, precomputed powers, the printing mode etc. The polynomial `f` is represented as a sparse polynomial using two arrays `j` and `a` of length ``len``, where `f(X) = \sum_{i} a_{i} X^{j_{i}}`. We also assume that the array `j` is sorted in ascending order. We choose this data structure to improve reduction modulo `f(X)` in `\mathbf{Q}_p[X]`, assuming a sparse polynomial `f(X)` is chosen. The field ``var`` contains the name of a generator of the extension, which is used when printing the elements. .. function:: void qadic_ctx_init(qadic_ctx_t ctx, const fmpz_t p, slong d, slong min, slong max, const char * var, enum padic_print_mode mode) Initialises the context ``ctx`` with prime `p`, extension degree `d`, variable name ``var`` and printing mode ``mode``. The defining polynomial is chosen as a Conway polynomial if possible and otherwise as a random sparse polynomial. Stores powers of `p` with exponents between ``min`` (inclusive) and ``max`` exclusive. Assumes that ``min`` is at most ``max``. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. Assumes that the printing mode is one of ``PADIC_TERSE``, ``PADIC_SERIES``, or ``PADIC_VAL_UNIT``. This function also carries out some relevant precomputation for arithmetic in `\mathbf{Q}_p / (p^N)` such as powers of `p` close to `p^N`. .. function:: void qadic_ctx_init_conway(qadic_ctx_t ctx, const fmpz_t p, slong d, slong min, slong max, const char * var, enum padic_print_mode mode) Initialises the context ``ctx`` with prime `p`, extension degree `d`, variable name ``var`` and printing mode ``mode``. The defining polynomial is chosen as a Conway polynomial, hence has restrictions on the prime and the degree. Stores powers of `p` with exponents between ``min`` (inclusive) and ``max`` exclusive. Assumes that ``min`` is at most ``max``. Assumes that `p` is a prime. Assumes that the string ``var`` is a null-terminated string of length at least one. Assumes that the printing mode is one of ``PADIC_TERSE``, ``PADIC_SERIES``, or ``PADIC_VAL_UNIT``. This function also carries out some relevant precomputation for arithmetic in `\mathbf{Q}_p / (p^N)` such as powers of `p` close to `p^N`. .. function:: void qadic_ctx_clear(qadic_ctx_t ctx) Clears all memory that has been allocated as part of the context. .. function:: slong qadic_ctx_degree(const qadic_ctx_t ctx) Returns the extension degree. .. function:: void qadic_ctx_print(const qadic_ctx_t ctx) Prints the data from the given context. Memory management -------------------------------------------------------------------------------- .. function:: void qadic_init(qadic_t rop) Initialises the element ``rop``, setting its value to `0`. .. function:: void qadic_init2(qadic_t rop, slong prec) Initialises the element ``rop`` with the given output precision, setting the value to `0`. .. function:: void qadic_clear(qadic_t rop) Clears the element ``rop``. .. function:: void _fmpz_poly_reduce(fmpz * R, slong lenR, const fmpz * a, const slong * j, slong len) Reduces a polynomial ``(R, lenR)`` modulo a sparse monic polynomial `f(X) = \sum_{i} a_{i} X^{j_{i}}` of degree at least `2`. Assumes that the array `j` of positive length ``len`` is sorted in ascending order. Allows zero-padding in ``(R, lenR)``. .. function:: void _fmpz_mod_poly_reduce(fmpz * R, slong lenR, const fmpz * a, const slong * j, slong len, const fmpz_t p) Reduces a polynomial ``(R, lenR)`` modulo a sparse monic polynomial `f(X) = \sum_{i} a_{i} X^{j_{i}}` of degree at least `2` in `\mathbf{Z}/(p)`, where `p` is typically a prime power. Assumes that the array `j` of positive length ``len`` is sorted in ascending order. Allows zero-padding in ``(R, lenR)``. .. function:: void qadic_reduce(qadic_t rop, const qadic_ctx_t ctx) Reduces ``rop`` modulo `f(X)` and `p^N`. Properties -------------------------------------------------------------------------------- .. function:: slong qadic_val(const qadic_t op) Returns the valuation of ``op``. .. function:: slong qadic_prec(const qadic_t op) Returns the precision of ``op``. Randomisation -------------------------------------------------------------------------------- .. function:: void qadic_randtest(qadic_t rop, flint_rand_t state, const qadic_ctx_t ctx) Generates a random element of `\mathbf{Q}_q`. .. function:: void qadic_randtest_not_zero(qadic_t rop, flint_rand_t state, const qadic_ctx_t ctx) Generates a random non-zero element of `\mathbf{Q}_q`. .. function:: void qadic_randtest_val(qadic_t rop, flint_rand_t state, slong v, const qadic_ctx_t ctx) Generates a random element of `\mathbf{Q}_q` with prescribed valuation ``val``. Note that if `v \geq N` then the element is necessarily zero. .. function:: void qadic_randtest_int(qadic_t rop, flint_rand_t state, const qadic_ctx_t ctx) Generates a random element of `\mathbf{Q}_q` with non-negative valuation. Assignments and conversions -------------------------------------------------------------------------------- .. function:: void qadic_set(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Sets ``rop`` to ``op``. .. function:: void qadic_zero(qadic_t rop) Sets ``rop`` to zero. .. function:: void qadic_one(qadic_t rop) Sets ``rop`` to one, reduced in the given context. Note that if the precision `N` is non-positive then ``rop`` is actually set to zero. .. function:: void qadic_gen(qadic_t rop, const qadic_ctx_t ctx) Sets ``rop`` to the generator `X` for the extension when `N > 0`, and zero otherwise. If the extension degree is one, raises an abort signal. .. function:: void qadic_set_ui(qadic_t rop, ulong op, const qadic_ctx_t ctx) Sets ``rop`` to the integer ``op``, reduced in the context. .. function:: int qadic_get_padic(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) If the element ``op`` lies in `\mathbf{Q}_p`, sets ``rop`` to its value and returns `1`; otherwise, returns `0`. Comparison -------------------------------------------------------------------------------- .. function:: int qadic_is_zero(const qadic_t op) Returns whether ``op`` is equal to zero. .. function:: int qadic_is_one(const qadic_t op) Returns whether ``op`` is equal to one in the given context. .. function:: int qadic_equal(const qadic_t op1, const qadic_t op2) Returns whether ``op1`` and ``op2`` are equal. Basic arithmetic -------------------------------------------------------------------------------- .. function:: void qadic_add(qadic_t rop, const qadic_t op1, const qadic_t op2, const qadic_ctx_t ctx) Sets ``rop`` to the sum of ``op1`` and ``op2``. Assumes that both ``op1`` and ``op2`` are reduced in the given context and ensures that ``rop`` is, too. .. function:: void qadic_sub(qadic_t rop, const qadic_t op1, const qadic_t op2, const qadic_ctx_t ctx) Sets ``rop`` to the difference of ``op1`` and ``op2``. Assumes that both ``op1`` and ``op2`` are reduced in the given context and ensures that ``rop`` is, too. .. function:: void qadic_neg(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Sets ``rop`` to the negative of ``op``. Assumes that ``op`` is reduced in the given context and ensures that ``rop`` is, too. .. function:: void qadic_mul(qadic_t rop, const qadic_t op1, const qadic_t op2, const qadic_ctx_t ctx) Sets ``rop`` to the product of ``op1`` and ``op2``, reducing the output in the given context. .. function:: void _qadic_inv(fmpz * rop, const fmpz * op, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N) Sets ``(rop, d)`` to the inverse of ``(op, len)`` modulo `f(X)` given by ``(a,j,lena)`` and `p^N`. Assumes that ``(op,len)`` has valuation `0`, that is, that it represents a `p`-adic unit. Assumes that ``len`` is at most `d`. Does not support aliasing. .. function:: void qadic_inv(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Sets ``rop`` to the inverse of ``op``, reduced in the given context. .. function:: void _qadic_pow(fmpz * rop, const fmpz * op, slong len, const fmpz_t e, const fmpz * a, const slong * j, slong lena, const fmpz_t p) Sets ``(rop, 2*d-1)`` to ``(op,len)`` raised to the power `e`, reduced modulo `f(X)` given by ``(a, j, lena)`` and `p`, which is expected to be a prime power. Assumes that `e \geq 0` and that ``len`` is positive and at most `d`. Although we require that ``rop`` provides space for `2d - 1` coefficients, the output will be reduced modulo `f(X)`, which is a polynomial of degree `d`. Does not support aliasing. .. function:: void qadic_pow(qadic_t rop, const qadic_t op, const fmpz_t e, const qadic_ctx_t ctx) Sets ``rop`` the ``op`` raised to the power `e`. Currently assumes that `e \geq 0`. Note that for any input ``op``, ``rop`` is set to one in the given context whenever `e = 0`. Square root -------------------------------------------------------------------------------- .. function:: int qadic_sqrt(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Return ``1`` if the input is a square (to input precision). If so, set ``rop`` to a square root (truncated to output precision). Special functions -------------------------------------------------------------------------------- .. function:: void _qadic_exp_rectangular(fmpz * rop, const fmpz * op, slong v, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) Sets ``(rop, 2*d - 1)`` to the exponential of ``(op, v, len)`` reduced modulo `p^N`, assuming that the series converges. Assumes that ``(op, v, len)`` is non-zero. Does not support aliasing. .. function:: int qadic_exp_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Returns whether the exponential series converges at ``op`` and sets ``rop`` to its value reduced modulo in the given context. .. function:: void _qadic_exp_balanced(fmpz * rop, const fmpz * x, slong v, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) Sets ``(rop, d)`` to the exponential of ``(op, v, len)`` reduced modulo `p^N`, assuming that the series converges. Assumes that ``len`` is in `[1,d)` but supports zero padding, including the special case when ``(op, len)`` is zero. Supports aliasing between ``rop`` and ``op``. .. function:: int qadic_exp_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Returns whether the exponential series converges at ``op`` and sets ``rop`` to its value reduced modulo in the given context. .. function:: void _qadic_exp(fmpz * rop, const fmpz * op, slong v, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) Sets ``(rop, 2*d - 1)`` to the exponential of ``(op, v, len)`` reduced modulo `p^N`, assuming that the series converges. Assumes that ``(op, v, len)`` is non-zero. Does not support aliasing. .. function:: int qadic_exp(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Returns whether the exponential series converges at ``op`` and sets ``rop`` to its value reduced modulo in the given context. The exponential series converges if the valuation of ``op`` is at least `2` or `1` when `p` is even or odd, respectively. .. function:: void _qadic_log_rectangular(fmpz * z, const fmpz * y, slong v, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) Computes .. math:: z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}. Note that this can be used to compute the `p`-adic logarithm via the equation .. math:: \log(x) & = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} \\ & = - \sum_{i=1}^{\infty} \frac{(1-x)^i}{i}. Assumes that `y = 1 - x` is non-zero and that `v = \operatorname{ord}_p(y)` is at least `1` when `p` is odd and at least `2` when `p = 2` so that the series converges. Assumes that `y` is reduced modulo `p^N`. Assumes that `v < N`, and in particular `N \geq 2`. Supports aliasing between `y` and `z`. .. function:: int qadic_log_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Returns whether the `p`-adic logarithm function converges at ``op``, and if so sets ``rop`` to its value. .. function:: void _qadic_log_balanced(fmpz * z, const fmpz * y, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) Computes `(z, d)` as .. math:: z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}. Assumes that `v = \operatorname{ord}_p(y)` is at least `1` when `p` is odd and at least `2` when `p = 2` so that the series converges. Supports aliasing between `z` and `y`. .. function:: int qadic_log_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Returns whether the `p`-adic logarithm function converges at ``op``, and if so sets ``rop`` to its value. .. function:: void _qadic_log(fmpz * z, const fmpz * y, slong v, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) Computes `(z, d)` as .. math:: z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}. Note that this can be used to compute the `p`-adic logarithm via the equation .. math:: \log(x) & = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} \\ & = - \sum_{i=1}^{\infty} \frac{(1-x)^i}{i}. Assumes that `y = 1 - x` is non-zero and that `v = \operatorname{ord}_p(y)` is at least `1` when `p` is odd and at least `2` when `p = 2` so that the series converges. Assumes that `(y, d)` is reduced modulo `p^N`. Assumes that `v < N`, and hence in particular `N \geq 2`. Supports aliasing between `z` and `y`. .. function:: int qadic_log(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Returns whether the `p`-adic logarithm function converges at ``op``, and if so sets ``rop`` to its value. The `p`-adic logarithm function is defined by the usual series .. math:: \log_p(x) = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} but this only converges when `\operatorname{ord}_p(x)` is at least `2` or `1` when `p = 2` or `p > 2`, respectively. .. function:: void _qadic_frobenius_a(fmpz * rop, slong e, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N) Computes `\sigma^e(X) \bmod{p^N}` where `X` is such that `\mathbf{Q}_q \cong \mathbf{Q}_p[X]/(f(X))`. Assumes that the precision `N` is at least `2` and that the extension is non-trivial, i.e. `d \geq 2`. Assumes that `0 < e < d`. Sets ``(rop, 2*d-1)``, although the actual length of the output will be at most `d`. .. function:: void _qadic_frobenius(fmpz * rop, const fmpz * op, slong len, slong e, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N) Sets ``(rop, 2*d-1)`` to `\Sigma` evaluated at ``(op, len)``. Assumes that ``len`` is positive but at most `d`. Assumes that `0 < e < d`. Does not support aliasing. .. function:: void qadic_frobenius(qadic_t rop, const qadic_t op, slong e, const qadic_ctx_t ctx) Evaluates the homomorphism `\Sigma^e` at ``op``. Recall that `\mathbf{Q}_q / \mathbf{Q}_p` is Galois with Galois group `\langle \Sigma \rangle \cong \langle \sigma \rangle`, which is also isomorphic to `\mathbf{Z}/d\mathbf{Z}`, where `\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)` is the Frobenius element `\sigma \colon x \mapsto x^p` and `\Sigma` is its lift to `\operatorname{Gal}(\mathbf{Q}_q/\mathbf{Q}_p)`. This functionality is implemented as ``GaloisImage()`` in Magma. .. function:: void _qadic_teichmuller(fmpz * rop, const fmpz * op, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N) Sets ``(rop, d)`` to the Teichmüller lift of ``(op, len)`` modulo `p^N`. Does not support aliasing. .. function:: void qadic_teichmuller(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) Sets ``rop`` to the Teichmüller lift of ``op`` to the precision given in the context. For a unit ``op``, this is the unique `(q-1)`\th root of unity which is congruent to ``op`` modulo `p`. Sets ``rop`` to zero if ``op`` is zero in the given context. Raises an exception if the valuation of ``op`` is negative. .. function:: void _qadic_trace(fmpz_t rop, const fmpz * op, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t pN) void qadic_trace(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) Sets ``rop`` to the trace of ``op``. For an element `a \in \mathbf{Q}_q`, multiplication by `a` defines a `\mathbf{Q}_p`-linear map on `\mathbf{Q}_q`. We define the trace of `a` as the trace of this map. Equivalently, if `\Sigma` generates `\operatorname{Gal}(\mathbf{Q}_q / \mathbf{Q}_p)` then the trace of `a` is equal to `\sum_{i=0}^{d-1} \Sigma^i (a)`. .. function:: void _qadic_norm(fmpz_t rop, const fmpz * op, slong len, const fmpz * a, const slong * j, slong lena, const fmpz_t p, slong N) Sets ``rop`` to the norm of the element ``(op,len)`` in `\mathbf{Z}_q` to precision `N`, where ``len`` is at least one. The result will be reduced modulo `p^N`. Note that whenever ``(op,len)`` is a unit, so is its norm. Thus, the output ``rop`` of this function will typically not have to be canonicalised or reduced by the caller. .. function:: void qadic_norm(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) Computes the norm of ``op`` to the given precision. Algorithm selection is automatic depending on the input. .. function:: void qadic_norm_analytic(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) Whenever ``op`` has valuation greater than `(p-1)^{-1}`, this routine computes its norm ``rop`` via .. math:: \operatorname{Norm} (x) = \exp \Bigl( \bigl( \operatorname{Trace} \log (x) \bigr) \Bigr). In the special case that ``op`` lies in `\mathbf{Q}_p`, returns its norm as `\operatorname{Norm}(x) = x^d`, where `d` is the extension degree. Otherwise, raises an ``abort`` signal. The complexity of this implementation is quasi-linear in `d` and `N`, and polynomial in `\log p`. .. function:: void qadic_norm_resultant(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) Sets ``rop`` to the norm of ``op``, using the formula .. math:: \operatorname{Norm}(x) = \ell(f)^{-\deg(a)} \operatorname{Res}(f(X), a(X)), where `\mathbf{Q}_q \cong \mathbf{Q}_p[X] / (f(X))`, `\ell(f)` is the leading coefficient of `f(X)`, and `a(X) \in \mathbf{Q}_p[X]` denotes the same polynomial as `x`. The complexity of the current implementation is given by `\mathcal{O}(d^4 M(N \log p))`, where `M(n)` denotes the complexity of multiplying to `n`-bit integers. Output -------------------------------------------------------------------------------- .. function:: int qadic_fprint_pretty(FILE * file, const qadic_t op, const qadic_ctx_t ctx) Prints a pretty representation of ``op`` to ``file``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. .. function:: int qadic_print_pretty(const qadic_t op, const qadic_ctx_t ctx) Prints a pretty representation of ``op`` to ``stdout``. In the current implementation, always returns `1`. The return code is part of the function's signature to allow for a later implementation to return the number of characters printed or a non-positive error code. flint-3.1.3/doc/source/qfb.rst000066400000000000000000000207721461254215100162120ustar00rootroot00000000000000.. _qfb: **qfb.h** -- binary quadratic forms ======================================================================================== Authors: * William Hart * Håvard Damm-Johnsen (updated documentation) Introduction -------------------------------------------------------------------------------- This module contains functionality for creating, listing and reducing binary quadratic forms. A ``qfb`` struct consists of three ``fmpz_t`` s, `a`, `b` and `c`, and basic algorithms for operations such as reduction, composition and enumerating are inplemented and described below. Currently the code only works for definite binary quadratic forms. Memory management ---------------------------------------------------------------------------------------- .. function:: void qfb_init(qfb_t q) Initialise a ``qfb_t`` `q` for use. .. function:: void qfb_clear(qfb_t q) Clear a ``qfb_t`` after use. This releases any memory allocated for `q` back to flint. .. function:: void qfb_array_clear(qfb ** forms, slong num) Clean up an array of ``qfb`` structs allocated by a qfb function. The parameter ``num`` must be set to the length of the array. Hash table ---------------------------------------------------------------------------------------- .. function:: qfb_hash_t * qfb_hash_init(slong depth) Initialises a hash table of size `2^{depth}`. .. function:: void qfb_hash_clear(qfb_hash_t * qhash, slong depth) Frees all memory used by a hash table of size `2^{depth}`. .. function:: void qfb_hash_insert(qfb_hash_t * qhash, qfb_t q, qfb_t q2, slong iter, slong depth) Insert the binary quadratic form ``q`` into the given hash table of size `2^{depth}` in the field ``q`` of the hash structure. Also store the second binary quadratic form ``q2`` (if not ``NULL``) in the similarly named field and ``iter`` in the similarly named field of the hash structure. .. function:: slong qfb_hash_find(qfb_hash_t * qhash, qfb_t q, slong depth) Search for the given binary quadratic form or its inverse in the given hash table of size `2^{depth}`. If it is found, return the index in the table (which is an array of ``qfb_hash_t`` structs), otherwise return ``-1``. Basic manipulation ---------------------------------------------------------------------------------------- .. function:: void qfb_set(qfb_t f, qfb_t g) Set the binary quadratic form `f` to be equal to `g`. Comparison ---------------------------------------------------------------------------------------- .. function:: int qfb_equal(qfb_t f, qfb_t g) Returns `1` if `f` and `g` are identical binary quadratic forms, otherwise returns `0`. Input/output ---------------------------------------------------------------------------------------- .. function:: void qfb_print(qfb_t q) Print a binary quadratic form `q` in the format `(a, b, c)` where `a`, `b`, `c` are the entries of `q`. Computing with forms ---------------------------------------------------------------------------------------- .. function:: void qfb_discriminant(fmpz_t D, qfb_t f) Set `D` to the discriminant of the binary quadratic form `f`, i.e. to `b^2 - 4ac`, where `f = (a, b, c)`. .. function:: void qfb_reduce(qfb_t r, qfb_t f, fmpz_t D) Set `r` to a reduced form equivalent to the binary quadratic form `f` of discriminant `D`. .. function:: int qfb_is_reduced(qfb_t r) Returns `1` if `q` is a reduced binary quadratic form, otherwise returns `0`. Note that this only tests for definite quadratic forms, so a form `r = (a,b,c)` is reduced if and only if `|b| \le a \le c` and if either inequality is an equality, then `b \ge 0`. .. function:: slong qfb_reduced_forms(qfb ** forms, slong d) Given a discriminant `d` (negative for negative definite forms), compute all the reduced binary quadratic forms of that discriminant. The function allocates space for these and returns it in the variable ``forms`` (the user is responsible for cleaning this up by a single call to ``qfb_array_clear`` on ``forms``, after use.) The function returns the number of forms generated (the form class number). The forms are stored in an array of ``qfb`` structs, which contain fields ``a, b, c`` corresponding to forms `(a, b, c)`. .. function:: slong qfb_reduced_forms_large(qfb ** forms, slong d) As for ``qfb_reduced_forms``. However, for small `|d|` it requires fewer primes to be computed at a small cost in speed. It is called automatically by ``qfb_reduced_forms`` for large `|d|` so that ``flint_primes`` is not exhausted. .. function:: void qfb_nucomp(qfb_t r, const qfb_t f, const qfb_t g, fmpz_t D, fmpz_t L) Shanks' NUCOMP as described in [JvdP2002]_. Computes the near reduced composition of forms `f` and `g` given `L = \lfloor |D|^{1/4} \rfloor` where `D` is the common discriminant of `f` and `g`. The result is returned in `r`. We require that `f` is a primitive form. .. function:: void qfb_nudupl(qfb_t r, const qfb_t f, fmpz_t D, fmpz_t L) As for ``nucomp`` except that the form `f` is composed with itself. We require that `f` is a primitive form. .. function:: void qfb_pow_ui(qfb_t r, qfb_t f, fmpz_t D, ulong exp) Compute the near reduced form `r` which is the result of composing the principal form (identity) with `f` ``exp`` times. We require `D` to be set to the discriminant of `f` and that `f` is a primitive form. .. function:: void qfb_pow(qfb_t r, qfb_t f, fmpz_t D, fmpz_t exp) As per ``qfb_pow_ui``. .. function:: void qfb_inverse(qfb_t r, qfb_t f) Set `r` to the inverse of the binary quadratic form `f`. .. function:: int qfb_is_principal_form(qfb_t f, fmpz_t D) Return `1` if `f` is the reduced principal form of discriminant `D`, i.e. the identity in the form class group, else `0`. .. function:: void qfb_principal_form(qfb_t f, fmpz_t D) Set `f` to the principal form of discriminant `D`, i.e. the identity in the form class group. .. function:: int qfb_is_primitive(qfb_t f) Return `1` if `f` is primitive, i.e. the greatest common divisor of its three coefficients is `1`. Otherwise the function returns `0`. .. function:: void qfb_prime_form(qfb_t r, fmpz_t D, fmpz_t p) Sets `r` to the unique prime `(p, b, c)` of discriminant `D`, i.e. with `0 < b \leq p`. We require that `p` is a prime. .. function:: int qfb_exponent_element(fmpz_t exponent, qfb_t f, fmpz_t n, ulong B1, ulong B2_sqrt) Find the exponent of the element `f` in the form class group of forms of discriminant `n`, doing a stage `1` with primes up to at least ``B1`` and a stage `2` for a single large prime up to at least the square of ``B2_sqrt``. If the function fails to find the exponent it returns `0`, otherwise the function returns `1` and ``exponent`` is set to the exponent of `f`, i.e. the minimum power of `f` which gives the identity. It is assumed that the form `f` is reduced. We require that ``iters`` is a power of `2` and that ``iters`` `\ge 1024`. The function performs a stage `2` which stores up to `4\times` ``iters`` binary quadratic forms, and `12\times` ``iters`` additional limbs of data in a hash table, where ``iters`` is the square root of ``B2``. .. function:: int qfb_exponent(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt, slong c) Compute the exponent of the class group of discriminant `n`, doing a stage `1` with primes up to at least ``B1`` and a stage `2` for a single large prime up to at least the square of ``B2_sqrt``, and with probability at least `1 - 2^{-c}`. If the prime limits are exhausted without finding the exponent, the function returns `0`, otherwise it returns `1` and ``exponent`` is set to the computed exponent, i.e. the minimum power to which every element of the class group has to be raised in order to get the identity. The function performs a stage `2` which stores up to `4\times` ``iters`` binary quadratic forms, and `12\times` ``iters`` additional limbs of data in a hash table, where ``iters`` is the square root of ``B2``. We use algorithm 8.1 of [Sut2007]_. .. function:: int qfb_exponent_grh(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt) Similar to ``qfb_exponent`` except that the bound ``c`` is automatically generated such that the exponent is guaranteed to be correct, if found, assuming the GRH, namely that the class group is generated by primes less than `6\log^2(|n|)` as described in [BD1992]_. flint-3.1.3/doc/source/qqbar.rst000066400000000000000000001255431461254215100165520ustar00rootroot00000000000000.. _qqbar: **qqbar.h** -- algebraic numbers represented by minimal polynomials =============================================================================== A :type:`qqbar_t` represents a real or complex algebraic number (an element of `\overline{\mathbb{Q}}`) by its unique reduced minimal polynomial in `\mathbb{Z}[x]` and an isolating complex interval. The precision of isolating intervals is maintained automatically to ensure that all operations on :type:`qqbar_t` instances are exact. This representation is useful for working with individual algebraic numbers of moderate degree (up to 100, say). Arithmetic in this representation is expensive: an arithmetic operation on numbers of degrees *m* and *n* involves computing and then factoring an annihilating polynomial of degree *mn* and potentially also performing numerical root-finding. For doing repeated arithmetic, it is generally more efficient to work with the :type:`ca_t` type in a fixed number field. The :type:`qqbar_t` type is used internally by the :type:`ca_t` type to represent the embedding of number fields in `\mathbb{R}` or `\mathbb{C}` and to decide predicates for algebraic numbers. Types and macros ------------------------------------------------------------------------------- .. type:: qqbar_struct .. type:: qqbar_t A *qqbar_struct* consists of an *fmpz_poly_struct* and an *acb_struct*. A *qqbar_t* is defined as an array of length one of type *qqbar_struct*, permitting a *qqbar_t* to be passed by reference. .. type:: qqbar_ptr Alias for ``qqbar_struct *``, used for *qqbar* vectors. .. type:: qqbar_srcptr Alias for ``const qqbar_struct *``, used for *qqbar* vectors when passed as readonly input to functions. .. macro:: QQBAR_POLY(x) Macro returning a pointer to the minimal polynomial of *x* which can be used as an *fmpz_poly_t*. .. macro:: QQBAR_COEFFS(x) Macro returning a pointer to the array of *fmpz* coefficients of the minimal polynomial of *x*. .. macro:: QQBAR_ENCLOSURE(x) Macro returning a pointer to the enclosure of *x* which can be used as an *acb_t*. Memory management ------------------------------------------------------------------------------- .. function:: void qqbar_init(qqbar_t res) Initializes the variable *res* for use, and sets its value to zero. .. function:: void qqbar_clear(qqbar_t res) Clears the variable *res*, freeing or recycling its allocated memory. .. function:: qqbar_ptr _qqbar_vec_init(slong len) Returns a pointer to an array of *len* initialized *qqbar_struct*:s. .. function:: void _qqbar_vec_clear(qqbar_ptr vec, slong len) Clears all *len* entries in the vector *vec* and frees the vector itself. Assignment ------------------------------------------------------------------------------- .. function:: void qqbar_swap(qqbar_t x, qqbar_t y) Swaps the values of *x* and *y* efficiently. .. function:: void qqbar_set(qqbar_t res, const qqbar_t x) void qqbar_set_si(qqbar_t res, slong x) void qqbar_set_ui(qqbar_t res, ulong x) void qqbar_set_fmpz(qqbar_t res, const fmpz_t x) void qqbar_set_fmpq(qqbar_t res, const fmpq_t x) Sets *res* to the value *x*. .. function:: void qqbar_set_re_im(qqbar_t res, const qqbar_t x, const qqbar_t y) Sets *res* to the value `x + yi`. .. function:: int qqbar_set_d(qqbar_t res, double x) int qqbar_set_re_im_d(qqbar_t res, double x, double y) Sets *res* to the value *x* or `x + yi` respectively. These functions performs error handling: if *x* and *y* are finite, the conversion succeeds and the return flag is 1. If *x* or *y* is non-finite (infinity or NaN), the conversion fails and the return flag is 0. Properties ------------------------------------------------------------------------------- .. function:: slong qqbar_degree(const qqbar_t x) Returns the degree of *x*, i.e. the degree of the minimal polynomial. .. function:: int qqbar_is_rational(const qqbar_t x) Returns whether *x* is a rational number. .. function:: int qqbar_is_integer(const qqbar_t x) Returns whether *x* is an integer (an element of `\mathbb{Z}`). .. function:: int qqbar_is_algebraic_integer(const qqbar_t x) Returns whether *x* is an algebraic integer, i.e. whether its minimal polynomial has leading coefficient 1. .. function:: int qqbar_is_zero(const qqbar_t x) int qqbar_is_one(const qqbar_t x) int qqbar_is_neg_one(const qqbar_t x) Returns whether *x* is the number `0`, `1`, `-1`. .. function:: int qqbar_is_i(const qqbar_t x) int qqbar_is_neg_i(const qqbar_t x) Returns whether *x* is the imaginary unit `i` (respectively `-i`). .. function:: int qqbar_is_real(const qqbar_t x) Returns whether *x* is a real number. .. function:: void qqbar_height(fmpz_t res, const qqbar_t x) Sets *res* to the height of *x* (the largest absolute value of the coefficients of the minimal polynomial of *x*). .. function:: slong qqbar_height_bits(const qqbar_t x) Returns the height of *x* (the largest absolute value of the coefficients of the minimal polynomial of *x*) measured in bits. .. function:: int qqbar_within_limits(const qqbar_t x, slong deg_limit, slong bits_limit) Checks if *x* has degree bounded by *deg_limit* and height bounded by *bits_limit* bits, returning 0 (false) or 1 (true). If *deg_limit* is set to 0, the degree check is skipped, and similarly for *bits_limit*. .. function:: int qqbar_binop_within_limits(const qqbar_t x, const qqbar_t y, slong deg_limit, slong bits_limit) Checks if `x + y`, `x - y`, `x \cdot y` and `x / y` certainly have degree bounded by *deg_limit* (by multiplying the degrees for *x* and *y* to obtain a trivial bound). For *bits_limits*, the sum of the bit heights of *x* and *y* is checked against the bound (this is only a heuristic). If *deg_limit* is set to 0, the degree check is skipped, and similarly for *bits_limit*. Conversions ------------------------------------------------------------------------------- .. function:: void _qqbar_get_fmpq(fmpz_t num, fmpz_t den, const qqbar_t x) Sets *num* and *den* to the numerator and denominator of *x*. Aborts if *x* is not a rational number. .. function:: void qqbar_get_fmpq(fmpq_t res, const qqbar_t x) Sets *res* to *x*. Aborts if *x* is not a rational number. .. function:: void qqbar_get_fmpz(fmpz_t res, const qqbar_t x) Sets *res* to *x*. Aborts if *x* is not an integer. Special values ------------------------------------------------------------------------------- .. function:: void qqbar_zero(qqbar_t res) Sets *res* to the number 0. .. function:: void qqbar_one(qqbar_t res) Sets *res* to the number 1. .. function:: void qqbar_i(qqbar_t res) Sets *res* to the imaginary unit `i`. .. function:: void qqbar_phi(qqbar_t res) Sets *res* to the golden ratio `\varphi = \tfrac{1}{2}(\sqrt{5} + 1)`. Input and output ------------------------------------------------------------------------------- .. function:: void qqbar_print(const qqbar_t x) Prints *res* to standard output. The output shows the degree and the list of coefficients of the minimal polynomial followed by a decimal representation of the enclosing interval. This function is mainly intended for debugging. .. function:: void qqbar_printn(const qqbar_t x, slong n) Prints *res* to standard output. The output shows a decimal approximation to *n* digits. .. function:: void qqbar_printnd(const qqbar_t x, slong n) Prints *res* to standard output. The output shows a decimal approximation to *n* digits, followed by the degree of the number. For example, *print*, *printn* and *printnd* with `n = 6` give the following output for the numbers 0, 1, `i`, `\varphi`, `\sqrt{2}-\sqrt{3} i`: .. code:: deg 1 [0, 1] 0 deg 1 [-1, 1] 1.00000 deg 2 [1, 0, 1] 1.00000*I deg 2 [-1, -1, 1] [1.61803398874989484820458683436563811772 +/- 6.00e-39] deg 4 [25, 0, 2, 0, 1] [1.4142135623730950488016887242096980786 +/- 8.67e-38] + [-1.732050807568877293527446341505872367 +/- 1.10e-37]*I 0 1.00000 1.00000*I 1.61803 1.41421 - 1.73205*I 0 (deg 1) 1.00000 (deg 1) 1.00000*I (deg 2) 1.61803 (deg 2) 1.41421 - 1.73205*I (deg 4) Random generation ------------------------------------------------------------------------------- .. function:: void qqbar_randtest(qqbar_t res, flint_rand_t state, slong deg, slong bits) Sets *res* to a random algebraic number with degree up to *deg* and with height (measured in bits) up to *bits*. .. function:: void qqbar_randtest_real(qqbar_t res, flint_rand_t state, slong deg, slong bits) Sets *res* to a random real algebraic number with degree up to *deg* and with height (measured in bits) up to *bits*. .. function:: void qqbar_randtest_nonreal(qqbar_t res, flint_rand_t state, slong deg, slong bits) Sets *res* to a random nonreal algebraic number with degree up to *deg* and with height (measured in bits) up to *bits*. Since all algebraic numbers of degree 1 are real, *deg* must be at least 2. Comparisons ------------------------------------------------------------------------------- .. function:: int qqbar_equal(const qqbar_t x, const qqbar_t y) Returns whether *x* and *y* are equal. .. function:: int qqbar_equal_fmpq_poly_val(const qqbar_t x, const fmpq_poly_t f, const qqbar_t y) Returns whether *x* is equal to `f(y)`. This function is more efficient than evaluating `f(y)` and comparing the results. .. function:: int qqbar_cmp_re(const qqbar_t x, const qqbar_t y) Compares the real parts of *x* and *y*, returning -1, 0 or +1. .. function:: int qqbar_cmp_im(const qqbar_t x, const qqbar_t y) Compares the imaginary parts of *x* and *y*, returning -1, 0 or +1. .. function:: int qqbar_cmpabs_re(const qqbar_t x, const qqbar_t y) Compares the absolute values of the real parts of *x* and *y*, returning -1, 0 or +1. .. function:: int qqbar_cmpabs_im(const qqbar_t x, const qqbar_t y) Compares the absolute values of the imaginary parts of *x* and *y*, returning -1, 0 or +1. .. function:: int qqbar_cmpabs(const qqbar_t x, const qqbar_t y) Compares the absolute values of *x* and *y*, returning -1, 0 or +1. .. function:: int qqbar_cmp_root_order(const qqbar_t x, const qqbar_t y) Compares *x* and *y* using an arbitrary but convenient ordering defined on the complex numbers. This is useful for sorting the roots of a polynomial in a canonical order. We define the root order as follows: real roots come first, in descending order. Nonreal roots are subsequently ordered first by real part in descending order, then in ascending order by the absolute value of the imaginary part, and then in descending order of the sign. This implies that complex conjugate roots are adjacent, with the root in the upper half plane first. .. function:: ulong qqbar_hash(const qqbar_t x) Returns a hash of *x*. As currently implemented, this function only hashes the minimal polynomial of *x*. The user should mix in some bits based on the numerical value if it is critical to distinguish between conjugates of the same minimal polynomial. This function is also likely to produce serial runs of values for lexicographically close minimal polynomials. This is not necessarily a problem for use in hash tables, but if it is important that all bits in the output are random, the user should apply an integer hash function to the output. Complex parts ------------------------------------------------------------------------------- .. function:: void qqbar_conj(qqbar_t res, const qqbar_t x) Sets *res* to the complex conjugate of *x*. .. function:: void qqbar_re(qqbar_t res, const qqbar_t x) Sets *res* to the real part of *x*. .. function:: void qqbar_im(qqbar_t res, const qqbar_t x) Sets *res* to the imaginary part of *x*. .. function:: void qqbar_re_im(qqbar_t res1, qqbar_t res2, const qqbar_t x) Sets *res1* to the real part of *x* and *res2* to the imaginary part of *x*. .. function:: void qqbar_abs(qqbar_t res, const qqbar_t x) Sets *res* to the absolute value of *x*: .. function:: void qqbar_abs2(qqbar_t res, const qqbar_t x) Sets *res* to the square of the absolute value of *x*. .. function:: void qqbar_sgn(qqbar_t res, const qqbar_t x) Sets *res* to the complex sign of *x*, defined as 0 if *x* is zero and as `x / |x|` otherwise. .. function:: int qqbar_sgn_re(const qqbar_t x) Returns the sign of the real part of *x* (-1, 0 or +1). .. function:: int qqbar_sgn_im(const qqbar_t x) Returns the sign of the imaginary part of *x* (-1, 0 or +1). .. function:: int qqbar_csgn(const qqbar_t x) Returns the extension of the real sign function taking the value 1 for *x* strictly in the right half plane, -1 for *x* strictly in the left half plane, and the sign of the imaginary part when *x* is on the imaginary axis. Equivalently, `\operatorname{csgn}(x) = x / \sqrt{x^2}` except that the value is 0 when *x* is zero. Integer parts ------------------------------------------------------------------------------- .. function:: void qqbar_floor(fmpz_t res, const qqbar_t x) Sets *res* to the floor function of *x*. If *x* is not real, the value is defined as the floor function of the real part of *x*. .. function:: void qqbar_ceil(fmpz_t res, const qqbar_t x) Sets *res* to the ceiling function of *x*. If *x* is not real, the value is defined as the ceiling function of the real part of *x*. Arithmetic ------------------------------------------------------------------------------- .. function:: void qqbar_neg(qqbar_t res, const qqbar_t x) Sets *res* to the negation of *x*. .. function:: void qqbar_add(qqbar_t res, const qqbar_t x, const qqbar_t y) void qqbar_add_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) void qqbar_add_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) void qqbar_add_ui(qqbar_t res, const qqbar_t x, ulong y) void qqbar_add_si(qqbar_t res, const qqbar_t x, slong y) Sets *res* to the sum of *x* and *y*. .. function:: void qqbar_sub(qqbar_t res, const qqbar_t x, const qqbar_t y) void qqbar_sub_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) void qqbar_sub_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) void qqbar_sub_ui(qqbar_t res, const qqbar_t x, ulong y) void qqbar_sub_si(qqbar_t res, const qqbar_t x, slong y) void qqbar_fmpq_sub(qqbar_t res, const fmpq_t x, const qqbar_t y) void qqbar_fmpz_sub(qqbar_t res, const fmpz_t x, const qqbar_t y) void qqbar_ui_sub(qqbar_t res, ulong x, const qqbar_t y) void qqbar_si_sub(qqbar_t res, slong x, const qqbar_t y) Sets *res* to the difference of *x* and *y*. .. function:: void qqbar_mul(qqbar_t res, const qqbar_t x, const qqbar_t y) void qqbar_mul_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) void qqbar_mul_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) void qqbar_mul_ui(qqbar_t res, const qqbar_t x, ulong y) void qqbar_mul_si(qqbar_t res, const qqbar_t x, slong y) Sets *res* to the product of *x* and *y*. .. function:: void qqbar_mul_2exp_si(qqbar_t res, const qqbar_t x, slong e) Sets *res* to *x* multiplied by `2^e`. .. function:: void qqbar_sqr(qqbar_t res, const qqbar_t x) Sets *res* to the square of *x*. .. function:: void qqbar_inv(qqbar_t res, const qqbar_t x) Sets *res* to the multiplicative inverse of *y*. Division by zero calls *flint_abort*. .. function:: void qqbar_div(qqbar_t res, const qqbar_t x, const qqbar_t y) void qqbar_div_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) void qqbar_div_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) void qqbar_div_ui(qqbar_t res, const qqbar_t x, ulong y) void qqbar_div_si(qqbar_t res, const qqbar_t x, slong y) void qqbar_fmpq_div(qqbar_t res, const fmpq_t x, const qqbar_t y) void qqbar_fmpz_div(qqbar_t res, const fmpz_t x, const qqbar_t y) void qqbar_ui_div(qqbar_t res, ulong x, const qqbar_t y) void qqbar_si_div(qqbar_t res, slong x, const qqbar_t y) Sets *res* to the quotient of *x* and *y*. Division by zero calls *flint_abort*. .. function:: void qqbar_scalar_op(qqbar_t res, const qqbar_t x, const fmpz_t a, const fmpz_t b, const fmpz_t c) Sets *res* to the rational affine transformation `(ax+b)/c`, performed as a single operation. There are no restrictions on *a*, *b* and *c* except that *c* must be nonzero. Division by zero calls *flint_abort*. Powers and roots ------------------------------------------------------------------------------- .. function:: void qqbar_sqrt(qqbar_t res, const qqbar_t x) void qqbar_sqrt_ui(qqbar_t res, ulong x) Sets *res* to the principal square root of *x*. .. function:: void qqbar_rsqrt(qqbar_t res, const qqbar_t x) Sets *res* to the reciprocal of the principal square root of *x*. Division by zero calls *flint_abort*. .. function:: void qqbar_pow_ui(qqbar_t res, const qqbar_t x, ulong n) void qqbar_pow_si(qqbar_t res, const qqbar_t x, slong n) void qqbar_pow_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t n) void qqbar_pow_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t n) Sets *res* to *x* raised to the *n*-th power. Raising zero to a negative power aborts. .. function:: void qqbar_root_ui(qqbar_t res, const qqbar_t x, ulong n) void qqbar_fmpq_root_ui(qqbar_t res, const fmpq_t x, ulong n) Sets *res* to the principal *n*-th root of *x*. The order *n* must be positive. .. function:: void qqbar_fmpq_pow_si_ui(qqbar_t res, const fmpq_t x, slong m, ulong n) Sets *res* to the principal branch of `x^{m/n}`. The order *n* must be positive. Division by zero calls *flint_abort*. .. function:: int qqbar_pow(qqbar_t res, const qqbar_t x, const qqbar_t y) General exponentiation: if `x^y` is an algebraic number, sets *res* to this value and returns 1. If `x^y` is transcendental or undefined, returns 0. Note that this function returns 0 instead of aborting on division zero. Numerical enclosures ------------------------------------------------------------------------------- The following functions guarantee a polished output in which both the real and imaginary parts are accurate to *prec* bits and exact when exactly representable (that is, when a real or imaginary part is a sufficiently small dyadic number). In some cases, the computations needed to polish the output may be expensive. When polish is unnecessary, :func:`qqbar_enclosure_raw` may be used instead. Alternatively, :func:`qqbar_cache_enclosure` can be used to avoid recomputations. .. function:: void qqbar_get_acb(acb_t res, const qqbar_t x, slong prec) Sets *res* to an enclosure of *x* rounded to *prec* bits. .. function:: void qqbar_get_arb(arb_t res, const qqbar_t x, slong prec) Sets *res* to an enclosure of *x* rounded to *prec* bits, assuming that *x* is a real number. If *x* is not real, *res* is set to `[\operatorname{NaN} \pm \infty]`. .. function:: void qqbar_get_arb_re(arb_t res, const qqbar_t x, slong prec) Sets *res* to an enclosure of the real part of *x* rounded to *prec* bits. .. function:: void qqbar_get_arb_im(arb_t res, const qqbar_t x, slong prec) Sets *res* to an enclosure of the imaginary part of *x* rounded to *prec* bits. .. function:: void qqbar_cache_enclosure(qqbar_t res, slong prec) Polishes the internal enclosure of *res* to at least *prec* bits of precision in-place. Normally, *qqbar* operations that need high-precision enclosures compute them on the fly without caching the results; if *res* will be used as an invariant operand for many operations, calling this function as a precomputation step can improve performance. Numerator and denominator ------------------------------------------------------------------------------- .. function:: void qqbar_denominator(fmpz_t res, const qqbar_t y) Sets *res* to the denominator of *y*, i.e. the leading coefficient of the minimal polynomial of *y*. .. function:: void qqbar_numerator(qqbar_t res, const qqbar_t y) Sets *res* to the numerator of *y*, i.e. *y* multiplied by its denominator. Conjugates ------------------------------------------------------------------------------- .. function:: void qqbar_conjugates(qqbar_ptr res, const qqbar_t x) Sets the entries of the vector *res* to the *d* algebraic conjugates of *x*, including *x* itself, where *d* is the degree of *x*. The output is sorted in a canonical order (as defined by :func:`qqbar_cmp_root_order`). Polynomial evaluation ------------------------------------------------------------------------------- .. function:: void _qqbar_evaluate_fmpq_poly(qqbar_t res, const fmpz * poly, const fmpz_t den, slong len, const qqbar_t x) void qqbar_evaluate_fmpq_poly(qqbar_t res, const fmpq_poly_t poly, const qqbar_t x) void _qqbar_evaluate_fmpz_poly(qqbar_t res, const fmpz * poly, slong len, const qqbar_t x) void qqbar_evaluate_fmpz_poly(qqbar_t res, const fmpz_poly_t poly, const qqbar_t x) Sets *res* to the value of the given polynomial *poly* evaluated at the algebraic number *x*. These methods detect simple special cases and automatically reduce *poly* if its degree is greater or equal to that of the minimal polynomial of *x*. In the generic case, evaluation is done by computing minimal polynomials of representation matrices. .. function:: int qqbar_evaluate_fmpz_mpoly_iter(qqbar_t res, const fmpz_mpoly_t poly, qqbar_srcptr x, slong deg_limit, slong bits_limit, const fmpz_mpoly_ctx_t ctx) int qqbar_evaluate_fmpz_mpoly_horner(qqbar_t res, const fmpz_mpoly_t poly, qqbar_srcptr x, slong deg_limit, slong bits_limit, const fmpz_mpoly_ctx_t ctx) int qqbar_evaluate_fmpz_mpoly(qqbar_t res, const fmpz_mpoly_t poly, qqbar_srcptr x, slong deg_limit, slong bits_limit, const fmpz_mpoly_ctx_t ctx) Sets *res* to the value of *poly* evaluated at the algebraic numbers given in the vector *x*. The number of variables is defined by the context object *ctx*. The parameters *deg_limit* and *bits_limit* define evaluation limits: if any temporary result exceeds these limits (not necessarily the final value, in case of cancellation), the evaluation is aborted and 0 (failure) is returned. If evaluation succeeds, 1 is returned. The *iter* version iterates over all terms in succession and computes the powers that appear. The *horner* version uses a multivariate implementation of the Horner scheme. The default algorithm currently uses the Horner scheme. Polynomial roots ------------------------------------------------------------------------------- .. function:: void qqbar_roots_fmpz_poly(qqbar_ptr res, const fmpz_poly_t poly, int flags) void qqbar_roots_fmpq_poly(qqbar_ptr res, const fmpq_poly_t poly, int flags) Sets the entries of the vector *res* to the *d* roots of the polynomial *poly*. Roots with multiplicity appear with repetition in the output array. By default, the roots will be sorted in a convenient canonical order (as defined by :func:`qqbar_cmp_root_order`). Instances of a repeated root always appear consecutively. The following *flags* are supported: - QQBAR_ROOTS_IRREDUCIBLE - if set, *poly* is assumed to be irreducible (it may still have constant content), and no polynomial factorization is performed internally. - QQBAR_ROOTS_UNSORTED - if set, the roots will not be guaranteed to be sorted (except for repeated roots being listed consecutively). .. function:: void qqbar_eigenvalues_fmpz_mat(qqbar_ptr res, const fmpz_mat_t mat, int flags) void qqbar_eigenvalues_fmpq_mat(qqbar_ptr res, const fmpq_mat_t mat, int flags) Sets the entries of the vector *res* to the eigenvalues of the square matrix *mat*. These functions compute the characteristic polynomial of *mat* and then call :func:`qqbar_roots_fmpz_poly` with the same flags. Roots of unity and trigonometric functions ------------------------------------------------------------------------------- The following functions use word-size integers *p* and *q* instead of *fmpq_t* instances to express rational numbers. This is to emphasize that the computations are feasible only with small *q* in this representation of algebraic numbers since the associated minimal polynomials have degree `O(q)`. The input *p* and *q* do not need to be reduced *a priori*, but should not be close to the word boundaries (they may be added and subtracted internally). .. function:: void qqbar_root_of_unity(qqbar_t res, slong p, ulong q) Sets *res* to the root of unity `e^{2 \pi i p / q}`. .. function:: int qqbar_is_root_of_unity(slong * p, ulong * q, const qqbar_t x) If *x* is not a root of unity, returns 0. If *x* is a root of unity, returns 1. If *p* and *q* are not *NULL* and *x* is a root of unity, this also sets *p* and *q* to the minimal integers with `0 \le p < q` such that `x = e^{2 \pi i p / q}`. .. function:: void qqbar_exp_pi_i(qqbar_t res, slong p, ulong q) Sets *res* to the root of unity `e^{\pi i p / q}`. .. function:: void qqbar_cos_pi(qqbar_t res, slong p, ulong q) void qqbar_sin_pi(qqbar_t res, slong p, ulong q) int qqbar_tan_pi(qqbar_t res, slong p, ulong q) int qqbar_cot_pi(qqbar_t res, slong p, ulong q) int qqbar_sec_pi(qqbar_t res, slong p, ulong q) int qqbar_csc_pi(qqbar_t res, slong p, ulong q) Sets *res* to the trigonometric function `\cos(\pi x)`, `\sin(\pi x)`, etc., with `x = \tfrac{p}{q}`. The functions tan, cot, sec and csc return the flag 1 if the value exists, and return 0 if the evaluation point is a pole of the function. .. function:: int qqbar_log_pi_i(slong * p, ulong * q, const qqbar_t x) If `y = \operatorname{log}(x) / (\pi i)` is algebraic, and hence necessarily rational, sets `y = p / q` to the reduced such fraction with `-1 < y \le 1` and returns 1. If *y* is not algebraic, returns 0. .. function:: int qqbar_atan_pi(slong * p, ulong * q, const qqbar_t x) If `y = \operatorname{atan}(x) / \pi` is algebraic, and hence necessarily rational, sets `y = p / q` to the reduced such fraction with `|y| < \tfrac{1}{2}` and returns 1. If *y* is not algebraic, returns 0. .. function:: int qqbar_asin_pi(slong * p, ulong * q, const qqbar_t x) If `y = \operatorname{asin}(x) / \pi` is algebraic, and hence necessarily rational, sets `y = p / q` to the reduced such fraction with `|y| \le \tfrac{1}{2}` and returns 1. If *y* is not algebraic, returns 0. .. function:: int qqbar_acos_pi(slong * p, ulong * q, const qqbar_t x) If `y = \operatorname{acos}(x) / \pi` is algebraic, and hence necessarily rational, sets `y = p / q` to the reduced such fraction with `0 \le y \le 1` and returns 1. If *y* is not algebraic, returns 0. .. function:: int qqbar_acot_pi(slong * p, ulong * q, const qqbar_t x) If `y = \operatorname{acot}(x) / \pi` is algebraic, and hence necessarily rational, sets `y = p / q` to the reduced such fraction with `-\tfrac{1}{2} < y \le \tfrac{1}{2}` and returns 1. If *y* is not algebraic, returns 0. .. function:: int qqbar_asec_pi(slong * p, ulong * q, const qqbar_t x) If `y = \operatorname{asec}(x) / \pi` is algebraic, and hence necessarily rational, sets `y = p / q` to the reduced such fraction with `0 \le y \le 1` and returns 1. If *y* is not algebraic, returns 0. .. function:: int qqbar_acsc_pi(slong * p, ulong * q, const qqbar_t x) If `y = \operatorname{acsc}(x) / \pi` is algebraic, and hence necessarily rational, sets `y = p / q` to the reduced such fraction with `-\tfrac{1}{2} \le y \le \tfrac{1}{2}` and returns 1. If *y* is not algebraic, returns 0. Guessing and simplification ------------------------------------------------------------------------------- .. function:: int qqbar_guess(qqbar_t res, const acb_t z, slong max_deg, slong max_bits, int flags, slong prec) Attempts to find an algebraic number *res* of degree at most *max_deg* and height at most *max_bits* bits matching the numerical enclosure *z*. The return flag indicates success. This is only a heuristic method, and the return flag neither implies a rigorous proof that *res* is the correct result, nor a rigorous proof that no suitable algebraic number with the given *max_deg* and *max_bits* exists. (Proof of nonexistence could in principle be computed, but this is not yet implemented.) The working precision *prec* should normally be the same as the precision used to compute *z*. It does not make much sense to run this algorithm with precision smaller than O(*max_deg* · *max_bits*). This function does a single iteration at the target *max_deg*, *max_bits*, and *prec*. For best performance, one should invoke this function repeatedly with successively larger parameters when the size of the intended solution is unknown or may be much smaller than a worst-case bound. .. function:: int qqbar_express_in_field(fmpq_poly_t res, const qqbar_t alpha, const qqbar_t x, slong max_bits, int flags, slong prec) Attempts to express *x* in the number field generated by *alpha*, returning success (0 or 1). On success, *res* is set to a polynomial *f* of degree less than the degree of *alpha* and with height (counting both the numerator and the denominator, when the coefficients of *g* are put on a common denominator) bounded by *max_bits* bits, such that `f(\alpha) = x`. (Exception: the *max_bits* parameter is currently ignored if *x* is rational, in which case *res* is just set to the value of *x*.) This function looks for a linear relation heuristically using a working precision of *prec* bits. If *x* is expressible in terms of *alpha*, then this function is guaranteed to succeed when *prec* is taken large enough. The identity `f(\alpha) = x` is checked rigorously, i.e. a return value of 1 implies a proof of correctness. In principle, choosing a sufficiently large *prec* can be used to prove that *x* does not lie in the field generated by *alpha*, but the present implementation does not support doing so automatically. This function does a single iteration at the target *max_bits* and and *prec*. For best performance, one should invoke this function repeatedly with successively larger parameters when the size of the intended solution is unknown or may be much smaller than a worst-case bound. Symbolic expressions and conversion to radicals ------------------------------------------------------------------------------- .. function:: void qqbar_get_quadratic(fmpz_t a, fmpz_t b, fmpz_t c, fmpz_t q, const qqbar_t x, int factoring) Assuming that *x* has degree 1 or 2, computes integers *a*, *b*, *c* and *q* such that .. math:: x = \frac{a + b \sqrt{c}}{q} and such that *c* is not a perfect square, *q* is positive, and *q* has no content in common with both *a* and *b*. In other words, this determines a quadratic field `\mathbb{Q}(\sqrt{c})` containing *x*, and then finds the canonical reduced coefficients *a*, *b* and *q* expressing *x* in this field. For convenience, this function supports rational *x*, for which *b* and *c* will both be set to zero. The following remarks apply to irrationals. The radicand *c* will not be a perfect square, but will not automatically be squarefree since this would require factoring the discriminant. As a special case, *c* will be set to `-1` if *x* is a Gaussian rational number. Otherwise, behavior is controlled by the *factoring* parameter. * If *factoring* is 0, no factorization is performed apart from removing powers of two. * If *factoring* is 1, a complete factorization is performed (*c* will be minimal). This can be very expensive if the discriminant is large. * If *factoring* is 2, a smooth factorization is performed to remove small factors from *c*. This is a tradeoff that provides pretty output in most cases while avoiding extreme worst-case slowdown. The smooth factorization guarantees finding all small factors (up to some trial division limit determined internally by Flint), but large factors are only found heuristically. .. function:: int qqbar_set_fexpr(qqbar_t res, const fexpr_t expr) Sets *res* to the algebraic number represented by the symbolic expression *expr*, returning 1 on success and 0 on failure. This function performs a "static" evaluation using *qqbar* arithmetic, supporting only closed-form expressions with explicitly algebraic subexpressions. It can be used to recover values generated by :func:`qqbar_get_expr_formula` and variants. For evaluating more complex expressions involving other types of values or requiring symbolic simplifications, the user should preprocess *expr* so that it is in a form which can be parsed by :func:`qqbar_set_fexpr`. The following expressions are supported: * Integer constants * Arithmetic operations with algebraic operands * Square roots of algebraic numbers * Powers with algebraic base and exponent an explicit rational number * NumberI, GoldenRatio, RootOfUnity * Floor, Ceil, Abs, Sign, Csgn, Conjugate, Re, Im, Max, Min * Trigonometric functions with argument an explicit rational number times Pi * Exponentials with argument an explicit rational number times Pi * NumberI * The Decimal() constructor * AlgebraicNumberSerialized() (assuming valid data, which is not checked) * PolynomialRootIndexed() * PolynomialRootNearest() Examples of formulas that are not supported, despite the value being an algebraic number: * ``Pi - Pi`` (general transcendental simplifications are not performed) * ``1 / Infinity`` (only numbers are handled) * ``Sum(n, For(n, 1, 10))`` (only static evaluation is performed) .. function:: void qqbar_get_fexpr_repr(fexpr_t res, const qqbar_t x) Sets *res* to a symbolic expression reflecting the exact internal representation of *x*. The output will have the form ``AlgebraicNumberSerialized(List(coeffs), enclosure)``. The output can be converted back to a ``qqbar_t`` value using :func:`qqbar_set_fexpr`. This is the recommended format for serializing algebraic numbers as it requires minimal computation, but it has the disadvantage of not being human-readable. .. function:: void qqbar_get_fexpr_root_nearest(fexpr_t res, const qqbar_t x) Sets *res* to a symbolic expression unambiguously describing *x* in the form ``PolynomialRootNearest(List(coeffs), point)`` where *point* is an approximation of *x* guaranteed to be closer to *x* than any conjugate root. The output can be converted back to a ``qqbar_t`` value using :func:`qqbar_set_fexpr`. This is a useful format for human-readable presentation, but serialization and deserialization can be expensive. .. function:: void qqbar_get_fexpr_root_indexed(fexpr_t res, const qqbar_t x) Sets *res* to a symbolic expression unambiguously describing *x* in the form ``PolynomialRootIndexed(List(coeffs), index)`` where *index* is the index of *x* among its conjugate roots in the builtin root sort order. The output can be converted back to a ``qqbar_t`` value using :func:`qqbar_set_fexpr`. This is a useful format for human-readable presentation when the numerical value is important, but serialization and deserialization can be expensive. .. function:: int qqbar_get_fexpr_formula(fexpr_t res, const qqbar_t x, ulong flags) Attempts to express the algebraic number *x* as a closed-form expression using arithmetic operations, radicals, and possibly exponentials or trigonometric functions, but without using ``PolynomialRootNearest`` or ``PolynomialRootIndexed``. Returns 0 on failure and 1 on success. The *flags* parameter toggles different methods for generating formulas. It can be set to any combination of the following. If *flags* is 0, only rational numbers will be handled. .. macro:: QQBAR_FORMULA_ALL Toggles all methods (potentially expensive). .. macro:: QQBAR_FORMULA_GAUSSIANS Detect Gaussian rational numbers `a + bi`. .. macro:: QQBAR_FORMULA_QUADRATICS Solve quadratics in the form `a + b \sqrt{d}`. .. macro:: QQBAR_FORMULA_CYCLOTOMICS Detect elements of cyclotomic fields. This works by trying plausible cyclotomic fields (based on the degree of the input), using LLL to find candidate number field elements, and certifying candidates through an exact computation. Detection is heuristic and is not guaranteed to find all cyclotomic numbers. .. macro:: QQBAR_FORMULA_CUBICS QQBAR_FORMULA_QUARTICS QQBAR_FORMULA_QUINTICS Solve polynomials of degree 3, 4 and (where applicable) 5 using cubic, quartic and quintic formulas (not yet implemented). .. macro:: QQBAR_FORMULA_DEPRESSION Use depression to try to generate simpler numbers. .. macro:: QQBAR_FORMULA_DEFLATION Use deflation to try to generate simpler numbers. This allows handling number of the form `a^{1/n}` where *a* can be represented in closed form. .. macro:: QQBAR_FORMULA_SEPARATION Try separating real and imaginary parts or sign and magnitude of complex numbers. This allows handling numbers of the form `a + bi` or `m \cdot s` (with `m > 0, |s| = 1`) where *a* and *b* or *m* and *s* can be represented in closed form. This is only attempted as a fallback after other methods fail: if an explicit Cartesian or magnitude-sign represented is desired, the user should manually separate the number into complex parts before calling :func:`qqbar_get_fexpr_formula`. .. macro:: QQBAR_FORMULA_EXP_FORM QQBAR_FORMULA_TRIG_FORM QQBAR_FORMULA_RADICAL_FORM QQBAR_FORMULA_AUTO_FORM Select output form for cyclotomic numbers. The *auto* form (equivalent to no flags being set) results in radicals for numbers of low degree, trigonometric functions for real numbers, and complex exponentials for nonreal numbers. The other flags (not fully implemented) can be used to force exponential form, trigonometric form, or radical form. Internal functions ------------------------------------------------------------------------------- .. function:: void qqbar_fmpz_poly_composed_op(fmpz_poly_t res, const fmpz_poly_t A, const fmpz_poly_t B, int op) Given nonconstant polynomials *A* and *B*, sets *res* to a polynomial whose roots are `a+b`, `a-b`, `ab` or `a/b` for all roots *a* of *A* and all roots *b* of *B*. The parameter *op* selects the arithmetic operation: 0 for addition, 1 for subtraction, 2 for multiplication and 3 for division. If *op* is 3, *B* must not have zero as a root. .. function:: void qqbar_binary_op(qqbar_t res, const qqbar_t x, const qqbar_t y, int op) Performs a binary operation using a generic algorithm. This does not check for special cases. .. function:: int _qqbar_validate_uniqueness(acb_t res, const fmpz_poly_t poly, const acb_t z, slong max_prec) Given *z* known to be an enclosure of at least one root of *poly*, certifies that the enclosure contains a unique root, and in that case sets *res* to a new (possibly improved) enclosure for the same root, returning 1. Returns 0 if uniqueness cannot be certified. The enclosure is validated by performing a single step with the interval Newton method. The working precision is determined from the accuracy of *z*, but limited by *max_prec* bits. This method slightly inflates the enclosure *z* to improve the chances that the interval Newton step will succeed. Uniqueness on this larger interval implies uniqueness of the original interval, but not existence; when existence has not been ensured a priori, :func:`_qqbar_validate_existence_uniqueness` should be used instead. .. function:: int _qqbar_validate_existence_uniqueness(acb_t res, const fmpz_poly_t poly, const acb_t z, slong max_prec) Given any complex interval *z*, certifies that the enclosure contains a unique root of *poly*, and in that case sets *res* to a new (possibly improved) enclosure for the same root, returning 1. Returns 0 if existence and uniqueness cannot be certified. The enclosure is validated by performing a single step with the interval Newton method. The working precision is determined from the accuracy of *z*, but limited by *max_prec* bits. .. function:: void _qqbar_enclosure_raw(acb_t res, const fmpz_poly_t poly, const acb_t z, slong prec) void qqbar_enclosure_raw(acb_t res, const qqbar_t x, slong prec) Sets *res* to an enclosure of *x* accurate to about *prec* bits (the actual accuracy can be slightly lower, or higher). This function uses repeated interval Newton steps to polish the initial enclosure *z*, doubling the working precision each time. If any step fails to improve the accuracy significantly, the root is recomputed from scratch to higher precision. If the initial enclosure is accurate enough, *res* is set to this value without rounding and without further computation. .. function:: int _qqbar_acb_lindep(fmpz * rel, acb_srcptr vec, slong len, int check, slong prec) Attempts to find an integer vector *rel* giving a linear relation between the elements of the real or complex vector *vec*, using the LLL algorithm. The working precision is set to the minimum of *prec* and the relative accuracy of *vec* (that is, the difference between the largest magnitude and the largest error magnitude within *vec*). 95% of the bits within the working precision are used for the LLL matrix, and the remaining 5% bits are used to validate the linear relation by evaluating the linear combination and checking that the resulting interval contains zero. This validation does not prove the existence or nonexistence of a linear relation, but it provides a quick heuristic way to eliminate spurious relations. If *check* is set, the return value indicates whether the validation was successful; otherwise, the return value simply indicates whether the algorithm was executed normally (failure may occur, for example, if the input vector is non-finite). In principle, this method can be used to produce a proof that no linear relation exists with coefficients up to a specified bit size, but this has not yet been implemented. .. raw:: latex \newpage flint-3.1.3/doc/source/qsieve.rst000066400000000000000000000160771461254215100167410ustar00rootroot00000000000000.. _qsieve: **qsieve.h** -- Quadratic sieve ================================================================================ .. function:: mp_limb_t qsieve_knuth_schroeppel(qs_t qs_inf) Return the Knuth-Schroeppel multiplier for the `n`, integer to be factored based upon the Knuth-Schroeppel function. .. function:: mp_limb_t qsieve_primes_init(qs_t qs_inf) Compute the factor base prime along with there inverse for `kn`, where `k` is Knuth-Schroeppel multiplier and `n` is the integer to be factored. It also computes the square root of `kn` modulo factor base primes. .. function:: mp_limb_t qsieve_primes_increment(qs_t qs_inf, mp_limb_t delta) It increase the number of factor base primes by amount 'delta' and calculate inverse of those primes along with the square root of `kn` modulo those primes. .. function:: void qsieve_init_A0(qs_t qs_inf) First it chooses the possible range of factor of `A _0`, based on the number of bits in optimal value of `A _0`. It tries to select range such that we have plenty of primes to choose from as well as number of factor in `A _0` are sufficient. For input of size less than 130 bit, this selection method doesn't work therefore we randomly generate 2 or 3-subset of all the factor base prime as the factor of `A _0`. Otherwise, if we have to select `s` factor for `A _0`, we generate `s - 1`- subset from odd indices of the possible range of factor and then search last factor using binary search from the even indices of possible range of factor such that value of `A _0` is close to it's optimal value. .. function:: void qsieve_next_A0(qs_t qs_inf) Find next candidate for `A _0` as follows: generate next lexicographic `s - 1`-subset from the odd indices of possible range of factor base and choose the last factor from even indices using binary search so that value `A _0` is close to it's optimal value. .. function:: void qsieve_compute_pre_data(qs_t qs_inf) Precompute all the data associated with factor's of `A _0`, since `A _0` is going to be fixed for several `A`. .. function:: void qsieve_init_poly_first(qs_t qs_inf) Initializes the value of `A = q _0 * A _0`, where `q _0` is non-factor base prime. precompute the data necessary for generating different `B` value using grey code formula. Combine the data calculated for the factor of `A _0` along with the parameter `q _0` to obtain data as for factor of `A`. It also calculates the sieve offset for all the factor base prime, for first polynomial. .. function:: void qsieve_init_poly_next(qs_t qs_inf, slong i) Generate next polynomial or next `B` value for particular `A` and also updates the sieve offsets for all the factor base prime, for this `B` value. .. function:: void qsieve_compute_C(fmpz_t C, qs_t qs_inf, qs_poly_t poly) Given `A` and `B`, calculate `C = (B ^2 - A) / N`. .. function:: void qsieve_do_sieving(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly) First initialize the sieve array to zero, then for each `p \in` ``factor base``, add `\log_2(p)` to the locations `\operatorname{soln1} _p + i * p` and `\operatorname{soln2} _p + i * p` for `i = 0, 1, 2,\dots`, where `\operatorname{soln1} _p` and `\operatorname{soln2} _p` are the sieve offsets calculated for `p`. .. function:: void qsieve_do_sieving2(qs_t qs_inf, unsigned char * seive, qs_poly_t poly) Perform the same task as above but instead of sieving over whole array at once divide the array in blocks and then sieve over each block for all the primes in factor base. .. function:: slong qsieve_evaluate_candidate(qs_t qs_inf, ulong i, unsigned char * sieve, qs_poly_t poly) For location `i` in sieve array value at which, is greater than sieve threshold, check the value of `Q(x)` at position `i` for smoothness. If value is found to be smooth then store it for later processing, else check the residue for the partial if it is found to be partial then store it for late processing. .. function:: slong qsieve_evaluate_sieve(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly) Scan the sieve array for location at, which accumulated value is greater than sieve threshold. .. function:: slong qsieve_collect_relations(qs_t qs_inf, unsigned char * sieve) Call for initialization of polynomial, sieving, and scanning of sieve for all the possible polynomials for particular hypercube i.e. `A`. .. function:: void qsieve_write_to_file(qs_t qs_inf, mp_limb_t prime, const fmpz_t Y, const qs_poly_t poly) Write a relation to the file in a binary format as follows. First, write large prime of size ``sizeof(mp_limb_t)``, in case of full relation it is 1. After this, write the number of small primes with size ``sizeof(slong)``. Then, write the small primes, with a total size of ``number_of_small_primes * sizeof(slong)``. Then, write the number of factors with a size of ``sizeof(slong)``. After that, write the factors and their exponents in the format ``factor_1, exponent_1, factor_2, ...``, all with a total size of ``2 * number_of_factors * sizeof(slong)``. Then write ``Y`` with the size of ``Y`` first (size ``sizeof(slong)``, that may be negative), and then its limbs (size ``Y_size * sizeof(mp_limb_t)``). .. function:: hash_t * qsieve_get_table_entry(qs_t qs_inf, mp_limb_t prime) Return the pointer to the location of 'prime' is hash table if it exist, else create and entry for it in hash table and return pointer to that. .. function:: void qsieve_add_to_hashtable(qs_t qs_inf, mp_limb_t prime) Add 'prime' to the hast table. .. function:: relation_t qsieve_parse_relation(qs_t qs_inf, char * str) Given a string representation of relation from the file, parse it to obtain all the parameters of relation. .. function:: relation_t qsieve_merge_relation(qs_t qs_inf, relation_t a, relation_t b) Given two partial relation having same large prime, merge them to obtain a full relation. .. function:: int qsieve_compare_relation(const void * a, const void * b) Compare two relation based on, first large prime, then number of factor and then offsets of factor in factor base. .. function:: int qsieve_remove_duplicates(relation_t * rel_list, slong num_relations) Remove duplicate from given list of relations by sorting relations in the list. .. function:: void qsieve_insert_relation2(qs_t qs_inf, relation_t * rel_list, slong num_relations) Given a list of relations, insert each relation from the list into the matrix for further processing. .. function:: int qsieve_process_relation(qs_t qs_inf) After we have accumulated required number of relations, first process the file by reading all the relations, removes singleton. Then merge all the possible partial to obtain full relations. .. function:: void qsieve_factor(fmpz_factor_t factors, const fmpz_t n) Factor `n` using the quadratic sieve method. It is required that `n` is not a prime and not a perfect power. There is no guarantee that the factors found will be prime, or distinct. flint-3.1.3/doc/source/references.rst000066400000000000000000000724161461254215100175650ustar00rootroot00000000000000References ------------ (In the PDF edition, this section is empty. See the bibliography listing at the end of the document.) .. [AbbottBronsteinMulders1999] \Fast deterministic computation of determinants of dense matrices, ACM International Symposium on Symbolic and Algebraic Computation (1999) .. [Apostol1997] \Apostol, Tom : Modular functions and Dirichlet series in number theory, Springer (1997) .. [Ari2011] \J. Arias de Reyna, "High precision computation of Riemann’s zeta function by the Riemann-Siegel formula, I", Mathematics of Computation 80 (2011), 995-1009 .. [Ari2012] \J. Arias de Reyna, "Programs for Riemann's zeta function", (J. A. J. van Vonderen, Ed.) *Leven met getallen : liber amicorum ter gelegenheid van de pensionering van Herman te Riele* CWI (2012) 102-112, https://ir.cwi.nl/pub/19724 .. [Arn2010] \J. Arndt, *Matters Computational*, Springer (2010), https://www.jjj.de/fxt/#fxtbook .. [Arn2012] \J. Arndt, "On computing the generalized Lambert series", https://arxiv.org/abs/1202.6525 .. [ArnoldMonagan2011] \Arnold, Andrew and Monagan, Michael : Calculating cyclotomic polynomials, Mathematics of Computation 80:276 (2011) 2359--2379 .. [BBC1997] \D. H. Bailey, J. M. Borwein and R. E. Crandall, "On the Khintchine constant", Mathematics of Computation 66 (1997) 417-431 .. [BBC2000] \J. Borwein, D. M. Bradley and R. E. Crandall, "Computational strategies for the Riemann zeta function", Journal of Computational and Applied Mathematics 121 (2000) 247-296 .. [BBK2014] \D. H. Bailey, J. M. Borwein and A. D. Kaiser. "Automated simplification of large symbolic expressions". Journal of Symbolic Computation Volume 60, January 2014, Pages 120-136. https://doi.org/10.1016/j.jsc.2013.09.001 .. [BD1992] \D. Buchmann and S. Düllmann. "Distributed class group computation." Informatik: Festschrift zum 60. Geburtstag von Günter Hotz (1992): 69-79. .. [BF2020] \F. Beukers and J. Forsgård. "Gamma-evaluations of hypergeometric series". Preprint, 2020. https://arxiv.org/abs/2004.08117 .. [BFSS2006] \A. Bostan, P. Flajolet, B. Salvy and É. Schost. "Fast computation of special resultants". Journal of Symbolic Computation, 41(1):1–29, January 2006. https://doi.org/10.1016/j.jsc.2005.07.001 .. [BJ2013] \R. P. Brent and F. Johansson, "A bound for the error term in the Brent-McMillan algorithm", preprint (2013), https://arxiv.org/abs/1312.0039 .. [BM1980] \R. P. Brent and E. M. McMillan, "Some new algorithms for high-precision computation of Euler's constant", Mathematics of Computation 34 (1980) 305-312. .. [BZ1992] \J. Borwein and I. Zucker, "Fast evaluation of the gamma function for small rational fractions using complete elliptic integrals of the first kind", IMA Journal of Numerical Analysis 12 (1992) 519-526 .. [BZ2011] \R. P. Brent and P. Zimmermann, *Modern Computer Arithmetic*, Cambridge University Press (2011), http://www.loria.fr/~zimmerma/mca/pub226.html .. [BaiWag1980] \Robert Baillie; Samuel S. Wagstaff, Jr. (October 1980). "Lucas Pseudoprimes". Mathematics of Computation. 35 (152): 1391–1417. .. [BerTas2010] \D. Berend and T. Tassa : Improved bounds on Bell numbers and on moments of sums of random variables, Probability and Mathematical Statistics vol. 30 (2010) 185--205 .. [Blo2009] \R. Bloemen, "Even faster zeta(2n) calculation!", https://web.archive.org/web/20141101133659/http://xn--2-umb.com/09/11/even-faster-zeta-calculation .. [Bodrato2010] \Bodrato, Marco : A Strassen-like Matrix Multiplication Suited for Squaring and Higher Power Computation. Proceedings of the ISSAC 2010 München, Germany, 25-28 July, 2010 .. [Boe2020] \H. Boehm. "Towards an API for the real numbers". PLDI 2020: Proceedings of the 41st ACM SIGPLAN Conference on Programming Language Design and Implementation, June 2020, Pages 562-576. https://doi.org/10.1145/3385412.3386037 .. [Bog2012] \I. Bogaert, B. Michiels and J. Fostier, "O(1) computation of Legendre polynomials and Gauss-Legendre nodes and weights for parallel computing", SIAM Journal on Scientific Computing 34:3 (2012), C83-C101 .. [Bol1887] \O. Bolza, "Darstellung der rationalen ganzen Invarianten der Binärform sechsten Grades durch die Nullwerthe der zugehörigen Theta-Functionen", Math. Ann. 30:4 (1887), 478--495. https://doi.org/10.1007/BF01444091 .. [Bor1987] \P. Borwein, "Reduced complexity evaluation of hypergeometric functions", Journal of Approximation Theory 50:3 (1987) .. [Bor2000] \P. Borwein, "An Efficient Algorithm for the Riemann Zeta Function", Constructive experimental and nonlinear analysis, CMS Conference Proc. 27 (2000) 29-34, http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf .. [Bre1978] \R. P. Brent, "A Fortran multiple-precision arithmetic package", ACM Transactions on Mathematical Software, 4(1):57–70, March 1978. .. [Bre1979] \R. P. Brent, "On the Zeros of the Riemann Zeta Function in the Critical Strip", Mathematics of Computation 33 (1979), 1361-1372, https://doi.org/10.1090/S0025-5718-1979-0537983-2 .. [Bre2010] \R. P. Brent, "Ramanujan and Euler's Constant", http://wwwmaths.anu.edu.au/~brent/pd/Euler_CARMA_10.pdf .. [BrentKung1978] \Brent, R. P. and Kung, H. T. : Fast Algorithms for Manipulating Formal Power Series, J. ACM 25:4 (1978) 581--595 .. [BuhlerCrandallSompolski1992] \Buhler, J.P. and Crandall, R.E. and Sompolski, R.W. : Irregular primes to one million : Math. Comp. 59:2000 (1992) 717--722 .. [CFG2017] \F. Cléry, C. Faber, and G. van der Geer. "Covariants of binary sextics and vector-valued Siegel modular forms of genus two", Math. Ann. 369 (2017), 1649--1669. https://doi.org/10.1007/s00208-016-1510-2 .. [CFG2019] \F. Cléry, C. Faber, and G. van der Geer. "Covariants of binary sextics and modular forms of degree 2 with character", Math. Comp. 88 (2019), 2423--2441. https://doi.org/10.1090/mcom/3412 .. [CGHJK1996] \R. M. Corless, G. H. Gonnet, D. E. Hare, D. J. Jeffrey and D. E. Knuth, "On the Lambert W function", Advances in Computational Mathematics, 5(1) (1996), 329-359 .. [CP2005] \R. Crandall and C. Pomerance, *Prime Numbers: A Computational Perspective*, second edition, Springer (2005). .. [Car1995] \B. C. Carlson, "Numerical computation of real or complex elliptic integrals". Numerical Algorithms, 10(1):13-26 (1995). .. [Car2004] \J. Carette. "Understanding expression simplification." ISSAC '04: Proceedings of the 2004 international symposium on Symbolic and algebraic computation, pp. 72-79. 2004. https://doi.org/10.1145/1005285.1005298 .. [Chen2003] \Zhuo Chen and John Greene : Some Comments on Baillie--PSW Pseudoprimes, The Fibonacci Quarterly 41:4 (2003) 334--344 .. [Cho1999] \T. Chow. "What is a closed-form number?". The American Mathematical Monthly Volume 106, 1999 - Issue 5. https://doi.org/10.1080/00029890.1999.12005066 .. [Coh1996] \Cohen, Henri : A course in computational algebraic number theory, Springer, 1996 .. [Coh2000] \H. Cohen. *Advanced topics in computational number theory*. Springer, 2000. https://doi.org/10.1007/978-1-4419-8489-0 .. [Col1971] \Collins, George E. : The Calculation of Multivariate Polynomial Resultants, SYMSAC '71, ACM 1971 212--222 .. [CraPom2005] \Richard Crandall and Carl Pomerance: Prime numbers: a computational perspective. 2005. .. [DHBHS2004] \B. Deconinck, M. Heil, A. Bobenko, M. van Hoeij, and M. Schmies, "Computing Riemann theta functions", Math. Comp. 73:247 (2004), 1417--1442. https://arxiv.org/abs/nlin/0206009 .. [DYF1999] \A. Dzieciol, S. Yngve and P. O. Fröman, "Coulomb wave functions with complex values of the variable and the parameters", J. Math. Phys. 40, 6145 (1999), https://doi.org/10.1063/1.533083 .. [DelegliseNicolasZimmermann2009] \Deleglise, Marc and Niclas, Jean-Louis and Zimmermann, Paul : Landau's function for one million billions, J. Théor. Nombres Bordeaux 20:3 (2009) 625--671 .. [DomKanTro1987] \Domich, P. D. and Kannan, R. and Trotter, L. E. Jr. : Hermite Normal Form Computation Using Modulo Determinant Arithmetic, Math. Operations Res. (12) 1987 50-59 .. [Dup2006] \R. Dupont. "Moyenne arithmético-géométrique, suites de Borchardt et applications." These de doctorat, École polytechnique, Palaiseau (2006). http://www.lix.polytechnique.fr/Labo/Regis.Dupont/these_soutenance.pdf .. [Dus1999] \P. Dusart, "The `k^{th}` prime is greater than `k(\ln k+\ln \ln k-1)` for `k \ge 2`," Math. Comp., 68:225 (January 1999) 411--415. .. [EHJ2016] \A. Enge, W. Hart and F. Johansson, "Short addition sequences for theta functions", preprint (2016), https://arxiv.org/abs/1608.06810 .. [EM2004] \O. Espinosa and V. Moll, "A generalized polygamma function", Integral Transforms and Special Functions (2004), 101-115. .. [EK2023] \N. D. Elkies and J. Kieffer, "A uniform quasi-linear time algorithm for evaluating theta functions in any dimension", in preparation. .. [Fie2007] \C. Fieker, "Sparse representation for cyclotomic fields". Experiment. Math. Volume 16, Issue 4 (2007), 493-500. https://doi.org/10.1080/10586458.2007.10129012 .. [FieHof2014] \Fieker C. and Hofmann T.: "Computing in quotients of rings of integers" LMS Journal of Computation and Mathematics, 17(A), 349-365 .. [Fil1992] \S. Fillebrown, "Faster Computation of Bernoulli Numbers", Journal of Algorithms 13 (1992) 431-445 .. [GCL1992] \K. O. Geddes, S. R. Czapor and G. Labahn. *Algorithms for computer algebra*. Springer, 1992. https://doi.org/10.1007/b102438 .. [GG2003] \J. von zur Gathen and J. Gerhard, *Modern Computer Algebra*, second edition, Cambridge University Press (2003) .. [GS2003] \X. Gourdon and P. Sebah, "Numerical evaluation of the Riemann Zeta-function" (2003), http://numbers.computation.free.fr/Constants/Miscellaneous/zetaevaluations.pdf .. [GVL1996] \G. H. Golub and C. F. Van Loan, *Matrix Computations*, third edition, Johns Hopkins University Press (1996). .. [Gas2018] \D. Gaspard, "Connection formulas between Coulomb wave functions" (2018), https://arxiv.org/abs/1804.10976 .. [Gos1974] \R. W. Gosper, "Acceleration of series", MIT AI Memo no.304, (March-1974). https://dspace.mit.edu/handle/1721.1/6088 .. [Got1959] \E. Gottschling, "Explizite Bestimmung der Randflächen es Fundamentalbereiches der Modulgruppe zweiten Grades'', Math. Annalen 138 (1959), 103--124. https://doi.org/10.1007/BF01342938 .. [GowWag2008] \Jason Gower and Sam Wagstaff : "Square form factoring" Math. Comp. 77, 2008, pp 551-588, https://doi.org/10.1090/S0025-5718-07-02010-8 .. [GraMol2010] \Torbjorn Granlund and Niels Moller : Improved Division by Invariant Integers https://gmplib.org/~tege/division-paper.pdf .. [HM2017] \J. van der Hoeven and B. Mourrain. "Efficient certification of numeric solutions to eigenproblems", MACIS 2017, 81-94, (2017), https://hal.archives-ouvertes.fr/hal-01579079 .. [HS1967] \E. Hansen and R. Smith, "Interval Arithmetic in Matrix Computations, Part II", SIAM Journal of Numerical Analysis, 4(1):1-9 (1967). https://doi.org/10.1137/0704001 .. [HZ2004] \G. Hanrot and P. Zimmermann, "Newton Iteration Revisited" (2004), http://www.loria.fr/~zimmerma/papers/fastnewton.ps.gz .. [HanZim2004] \Guillaume Hanrot and Paul Zimmermann : Newton Iteration Revisited (2004) https://www.loria.fr/~zimmerma/papers/fastnewton.ps.gz .. [Har2010] \D. Harvey, "A multimodular algorithm for computing Bernoulli numbers" (2010), Mathematics of Computation 79.272: 2361-2370 .. [Har2012] \Hart, William B.. (2012) A one line factoring algorithm. Journal of the Australian Mathematical Society, Volume 92 (Number 1). pp. 61-69. .. [Har2015] \W. B. Hart. "ANTIC: Algebraic number theory in C". Computeralgebra-Rundbrief: Vol. 56, 2015 .. [Har2018] \W. B. Hart. "Algebraic number theory". Unpublished manuscript, 2018. .. [Hart2010] \W. B. Hart. "Fast library for number theory: an introduction." International Congress on Mathematical Software. Springer, Berlin, Heidelberg, 2010. https://doi.org/10.1007/978-3-642-15582-6_18 .. [Hen1956] \Peter Henrici : "A Subroutine for Computations with Rational Numbers" J. ACM (1956), https://doi.org/10.1145/320815.320818 .. [Hoe2001] \J. van der Hoeven. "Fast evaluation of holonomic functions near and in regular singularities", Journal of Symbolic Computation, 31(6):717-743 (2001). .. [Hoe2009] \J. van der Hoeven, "Ball arithmetic", Technical Report, HAL 00432152 (2009), http://www.texmacs.org/joris/ball/ball-abs.html .. [Hor1972] \Ellis Horowitz : "Algorithms for Rational Function Arithmetic Operations" Annual ACM Symposium on Theory of Computing: Proceedings of the Fourth Annual ACM Symposium on Theory of Computing (Denver) (1972), https://doi.org/10.1145/800152.804903 .. [Iliopoulos1989] \Iliopoulos, C. S., Worst-Case Complexity Bounds on Algorithms for Computing the Canonical Structure of Finite Abelian Groups and the Hermite and Smith Normal Forms of an Integer Matrix : SIAM J. Computation 18:4 (1989) 658 .. [Igu1972] \J.-I. Igusa. *Theta functions*, Springer, 1972. https://doi.org/10.1007/978-3-642-65315-5 .. [Igu1979] \J.-I. Igusa, "On the ring of modular forms of degree two over Z", Amer. J. Math. 101:1 (1979), 149--183. https://doi.org/10.2307/2373943 .. [JB2018] \F. Johansson and I. Blagouchine. "Computing Stieltjes constants using complex integration", preprint (2018), https://arxiv.org/abs/1804.01679 .. [JM2018] \F. Johansson and M. Mezzarobba, "Fast and rigorous arbitrary-precision computation of Gauss-Legendre quadrature nodes and weights", preprint (2018), https://arxiv.org/abs/1802.03948 .. [JR1999] \D. Jeffrey and A. D. Rich. "Simplifying square roots of square roots by denesting". Computer Algebra Systems: A Practical Guide, M.J. Wester, Ed., Wiley 1999. .. [Joh2012] \F. Johansson, "Efficient implementation of the Hardy-Ramanujan-Rademacher formula", LMS Journal of Computation and Mathematics, Volume 15 (2012), 341-359, http://journals.cambridge.org/action/displayAbstract?fromPage=online&aid=8710297 .. [Joh2013] \F. Johansson, "Rigorous high-precision computation of the Hurwitz zeta function and its derivatives", Numerical Algorithms, http://arxiv.org/abs/1309.2877 https://doi.org/10.1007/s11075-014-9893-1 .. [Joh2014a] \F. Johansson, *Fast and rigorous computation of special functions to high precision*, PhD thesis, RISC, Johannes Kepler University, Linz, 2014. https://fredrikj.net/thesis/ .. [Joh2014b] \F. Johansson, "Evaluating parametric holonomic sequences using rectangular splitting", ISSAC 2014, 256-263. https://doi.org/10.1145/2608628.2608629 .. [Joh2014c] \F. Johansson, "Efficient implementation of elementary functions in the medium-precision range", https://arxiv.org/abs/1410.7176 .. [Joh2015] \F. Johansson, "Computing Bell numbers", https://fredrikj.net/blog/2015/08/computing-bell-numbers/ .. [Joh2015b] \F. Johansson, "A fast algorithm for reversion of power series", Math. Comp. 84 (2015), 475-484, http://doi.org/10.1090/S0025-5718-2014-02857-3 .. [Joh2016] \F. Johansson, "Computing hypergeometric functions rigorously", preprint (2016), https://arxiv.org/abs/1606.06977 .. [Joh2017] \F. Johansson. "Arb: efficient arbitrary-precision midpoint-radius interval arithmetic". IEEE Transactions on Computers, vol 66, issue 8, 2017, pp. 1281-1292. https://doi.org/10.1109/TC.2017.2690633 .. [Joh2017a] \F. Johansson. "Arb: efficient arbitrary-precision midpoint-radius interval arithmetic", IEEE Transactions on Computers, 66(8):1281-1292 (2017). https://doi.org/10.1109/TC.2017.2690633 .. [Joh2017b] \F. Johansson, "Computing the Lambert W function in arbitrary-precision complex interval arithmetic", preprint (2017), https://arxiv.org/abs/1705.03266 .. [Joh2018a] \F. Johansson, "Numerical integration in arbitrary-precision ball arithmetic", preprint (2018), https://arxiv.org/abs/1802.07942 .. [Joh2018b] \F. Johansson and others, "mpmath: a Python library for arbitrary-precision floating-point arithmetic (version 1.1.0)", December 2018. https://mpmath.org/ .. [JvdP2002] \M. J. Jacobson Jr. and A. J. van der Poorten. "Computational aspects of NUCOMP." In International Algorithmic Number Theory Symposium, pp. 120-133. Berlin, Heidelberg: Springer Berlin Heidelberg, 2002. .. [Kahan1991] \Kahan, William: Computing a Real Cube Root. https://csclub.uwaterloo.ca/~pbarfuss/qbrt.pdf .. [KanBac1979] \Kannan, R. and Bachem, A. : Polynomial algorithms for computing and the Smith and Hermite normal forms of an integer matrix, SIAM J. Computation vol. 9 (1979) 499--507 .. [Kar1998] \E. A. Karatsuba, "Fast evaluation of the Hurwitz zeta function and Dirichlet L-series", Problems of Information Transmission 34:4 (1998), 342-353, http://www.mathnet.ru/php/archive.phtml?wshow=paper&jrnid=ppi&paperid=425&option_lang=eng .. [Knu1997] \Knuth, D. E. The Art of Computer Programming, volume 2: Seminumerical algorithms, 1997 .. [Kob2010] \A. Kobel, "Certified Complex Numerical Root Finding", Seminar on Computational Geometry and Geometric Computing (2010), http://www.mpi-inf.mpg.de/departments/d1/teaching/ss10/Seminar_CGGC/Slides/02_Kobel_NRS.pdf .. [Kri2013] \A. Krishnamoorthy and D. Menon, "Matrix Inversion Using Cholesky Decomposition" Proc. of the International Conference on Signal Processing Algorithms, Architectures, Arrangements, and Applications (SPA-2013), pp. 70-72, 2013. .. [LT2016] \H. Labrande and E. Thomé, "Computing theta functions in quasi-linear time in genus 2 and above", ANTS XII, Kaiserslautern, LMS J. Comp. Math 19 (2016), 163--177. https://doi.org/10.1112/S1461157016000309 .. [Leh1970] \R. S. Lehman, "On the Distribution of Zeros of the Riemann Zeta-Function", Proc. of the London Mathematical Society 20(3) (1970), 303-320, https://doi.org/10.1112/plms/s3-20.2.303 .. [LukPatWil1996] \R. F. Lukes and C. D. Patterson and H. C. Williams "Some results on pseudosquares" Math. Comp. 1996, no. 65, 361--372 .. [Lüb2004] \F. Lübeck, "Conway polynomials for finite fields", RTWH Aachen, https://www.math.rwth-aachen.de/~Frank.Luebeck/data/ConwayPol/index.html, (accessed 2024-01-12) .. [MN2019] \P. Molin and C. Neurohr, "Computing period matrices and the Abel--Jacobi map of superelliptic curves", Math. Comp. 88:316 (2019), 847--888. .. [MP2006] \M. Monagan and R. Pearce. "Rational simplification modulo a polynomial ideal". Proceedings of the 2006 international symposium on Symbolic and algebraic computation - ISSAC '06. https://doi.org/10.1145/1145768.1145809 .. [MPFR2012] The MPFR team, "MPFR Algorithms" (2012), https://www.mpfr.org/algo.html .. [MasRob1996] \J. Massias and G. Robin, "Bornes effectives pour certaines fonctions concernant les nombres premiers," J. Theorie Nombres Bordeaux, 8 (1996) 215-242. .. [Mic2007] \N. Michel, "Precise Coulomb wave functions for a wide range of complex l, eta and z", Computer Physics Communications, Volume 176, Issue 3, (2007), 232-249, https://doi.org/10.1016/j.cpc.2006.10.004 .. [Miy2010] \S. Miyajima, "Fast enclosure for all eigenvalues in generalized eigenvalue problems", Journal of Computational and Applied Mathematics, 233 (2010), 2994-3004, https://doi.org/10.1016/j.cam.2009.11.048 .. [Mos1971] \J. Moses. "Algebraic simplification - a guide for the perplexed". Proceedings of the second ACM symposium on Symbolic and algebraic manipulation (1971), 282-304. https://doi.org/10.1145/362637.362648 .. [Mul2000] \Thom Mulders : On Short Multiplications and Divisions, AAECC vol. 11 (2000) 69--88 .. [Mum1983] \D. Mumford, *Tata Lectures on Theta I*, Birkhäuser, 1983. https://doi.org/10.1007/978-1-4899-2843-6 .. [Mum1984] \D. Mumford, *Tata Lectures on Theta II*, Birkhäuser, 1984. https://doi.org/10.1007/978-0-8176-4578-6 .. [NIST2012] National Institute of Standards and Technology, *Digital Library of Mathematical Functions* (2012), https://dlmf.nist.gov/ .. [NakTurWil1997] \Nakos, George and Turner, Peter and Williams, Robert : Fraction-free algorithms for linear and polynomial equations, ACM SIGSAM Bull. 31 (1997) 3 11--19 .. [Olv1997] \F. Olver, *Asymptotics and special functions*, AKP Classics, AK Peters Ltd., Wellesley, MA, 1997. Reprint of the 1974 original. .. [PP2010] \K. H. Pilehrood and T. H. Pilehrood. "Series acceleration formulas for beta values", Discrete Mathematics and Theoretical Computer Science, DMTCS, 12 (2) (2010), 223-236, https://hal.inria.fr/hal-00990465/ .. [PS1973] \M. S. Paterson and L. J. Stockmeyer, "On the number of nonscalar multiplications necessary to evaluate polynomials", SIAM J. Comput (1973) .. [PS1991] \G. Pittaluga and L. Sacripante, "Inequalities for the zeros of the Airy functions", SIAM J. Math. Anal. 22:1 (1991), 260-267. .. [Paterson1973] \Michael S. Paterson and Larry J. Stockmeyer : On the number of nonscalar multiplications necessary to evaluate polynomials, SIAM Journal on Computing (1973) .. [PernetStein2010] \Pernet, C. and Stein, W. : Fast computation of Hermite normal forms of random integer matrices ,J. Number Theory 130:17 (2010) 1675--1683 .. [Pet1999] \K. Petras, "On the computation of the Gauss-Legendre quadrature formula with a given precision", Journal of Computational and Applied Mathematics 112 (1999), 253-267 .. [Pla2011] \D. J. Platt, "Computing degree 1 L-functions rigorously", Ph.D. Thesis, University of Bristol (2011), https://people.maths.bris.ac.uk/~madjp/thesis5.pdf .. [Pla2017] \D. J. Platt, "Isolating some non-trivial zeros of zeta", Mathematics of Computation 86 (2017), 2449-2467, https://doi.org/10.1090/mcom/3198 .. [RF1994] \D. Richardson and J. Fitch. "The identity problem for elementary functions and constants". ISSAC '94: Proceedings of the international symposium on Symbolic and algebraic computation, August 1994, 285-290. https://doi.org/10.1145/190347.190429 .. [Rad1973] \H. Rademacher, *Topics in analytic number theory*, Springer, 1973. .. [Rademacher1937] \Rademacher, Hans : On the partition function `p(n)` Proc. London Math. Soc vol. 43 (1937) 241--254 .. [Ric1992] \D. Richardson. "The elementary constant problem". ISSAC '92: Papers from the international symposium on Symbolic and algebraic computation, August 1992, 108-116. https://doi.org/10.1145/143242.143284 .. [Ric1995] \D. Richardson. "A simplified method of recognizing zero among elementary constants". ISSAC '95: Proceedings of the 1995 international symposium on Symbolic and algebraic computation, April 1995, 104-109. https://doi.org/10.1145/220346.220360 .. [Ric1997] \D. Richardson. "How to recognize zero". Journal of Symbolic Computation 24.6 (1997): 627-645. https://doi.org/10.1006/jsco.1997.0157 .. [Ric2007] \D. Richardson. "Zero tests for constants in simple scientific computation". Mathematics in Computer Science volume 1, pages 21-37 (2007). https://doi.org/10.1007/s11786-007-0002-x .. [Ric2009] \D. Richardson. "Recognising zero among implicitly defined elementary numbers". Preprint, 2009. .. [RosSch1962] \Rosser, J. Barkley; Schoenfeld, Lowell: Approximate formulas for some functions of prime numbers. Illinois J. Math. 6 (1962), no. 1, 64--94. .. [Rum2010] \S. M. Rump, "Verification methods: Rigorous results using floating-point arithmetic", Acta Numerica 19 (2010), 287-449. .. [Smi2001] \D. M. Smith, "Algorithm: Fortran 90 Software for Floating-Point Multiple Precision Arithmetic, Gamma and Related Functions", Transactions on Mathematical Software 27 (2001) 377-387, http://myweb.lmu.edu/dmsmith/toms2001.pdf .. [SorWeb2016] \Sorenson, Jonathan and Webster, Jonathan : Strong pseudoprimes to twelve prime bases. Math. Comp. 86 (2017), 985-1003, https://doi.org/10.1090/mcom/3134 .. [Ste2002] \A. Steel. "A new scheme for computing with algebraically closed fields". In: Fieker C., Kohel D.R. (eds) Algorithmic Number Theory. ANTS 2002. Lecture Notes in Computer Science, vol 2369. Springer, Berlin, Heidelberg. https://doi.org/10.1007/3-540-45455-1_38 .. [Ste2010] \A. Steel. "Computing with algebraically closed fields". Journal of Symbolic Computation 45 (2010) 342-372. https://doi.org/10.1016/j.jsc.2009.09.005 .. [Stehle2010] \Stehlé, Damien : Floating-Point LLL: Theoretical and Practical Aspects, in Nguyen, Phong Q. and Vallée, Brigitte : The LLL Algorithm: Survey and Applications (2010) 179--213 .. [Stein2007] \Stein, William A.: Modular forms, a computational approach. American Mathematical Society. 2007 .. [StoMul1998] \Storjohann, Arne and Mulders, Thom : Fast algorithms for linear algebra modulo :math:`N` : Algorithms---{ESA} '98 (Venice), Lecture Notes in Comput. Sci. 1461 139--150 .. [Str2014] \M. Streng, "Computing Igusa class polynomials", Math. Comp. 83:285 (2014), 275--309. https://doi.org/10.1090/S0025-5718-2013-02712-3 .. [Str1997] \A. Strzebonski. "Computing in the field of complex algebraic numbers". Journal of Symbolic Computation (1997) 24, 647-656. https://doi.org/10.1006/jsco.1997.0158 .. [Str2012] \A. Strzebonski. "Real root isolation for exp-log-arctan functions". Journal of Symbolic Computation 47 (2012) 282–314. https://doi.org/10.1016/j.jsc.2011.11.004 .. [Sut2007] \A. V. Sutherland. "Order computations in generic groups." PhD diss., Massachusetts Institute of Technology, 2007. .. [Tak2000] \D. Takahashi, "A fast algorithm for computing large Fibonacci numbers", Information Processing Letters 75 (2000) 243-246, http://www.ii.uni.wroc.pl/~lorys/IPL/article75-6-1.pdf .. [ThullYap1990] \Thull, K. and Yap, C. : A Unified Approach to HGCD Algorithms for Polynomials and Integers, (1990) .. [Tre2008] \L. N. Trefethen, "Is Gauss Quadrature Better than Clenshaw-Curtis?", SIAM Review, 50:1 (2008), 67-87, https://doi.org/10.1137/060659831 .. [Tru2011] \T. S. Trudgian, "Improvements to Turing's method", Mathematics of Computation 80 (2011), 2259-2279, https://doi.org/10.1090/S0025-5718-2011-02470-1 .. [Tru2014] \T. S. Trudgian, "An improved upper bound for the argument of the Riemann zeta-function on the critical line II", Journal of Number Theory 134 (2014), 280-292, https://doi.org/10.1016/j.jnt.2013.07.017 .. [Tur1953] \A. M. Turing, "Some Calculations of the Riemann Zeta-Function", Proc. of the London Mathematical Society 3(3) (1953), 99-117, https://doi.org/10.1112/plms/s3-3.1.99 .. [Villard2007] \Villard, Gilles : Certification of the QR Factor R and of Lattice Basis Reducedness, In proceedings of ACM International Symposium on Symbolic and Algebraic Computation (2007) 361--368 ACM Press. .. [WaktinsZeitlin1993] \Watkins, W. and Zeitlin, J. : The minimal polynomial of `\cos(2\pi/n)` The American Mathematical Monthly 100:5 (1993) 471--474 .. [Wei2000] \A. Weilert, "(1+i)-ary GCD computation in Z[i] as an analogue to the binary GCD algorithm", Journal of Symbolic Computation 30.5 (2000): 605-617, https://doi.org/10.1006/jsco.2000.0422 .. [Whiteman1956] \Whiteman, A. L. : A sum connected with the series for the partition function, Pacific Journal of Mathematics 6:1 (1956) 159--176 .. [Zip1985] \R. Zippel. "Simplification of expressions involving radicals". Journal of Symbolic Computation (1985) 1, 189-210. https://doi.org/10.1016/S0747-7171(85)80014-6 .. [Zun2023] \J. Zuniga, "Catalan's constant fast convergent series", https://mathoverflow.net/q/424055 .. [Zun2023b] \J. Zuniga, "Are these fast convergent series for log(2) and log(3) already known and proven?", https://math.stackexchange.com/q/4854073 .. [vHP2012] \M. van Hoeij and V. Pal. "Isomorphisms of algebraic number fields". Journal de Théorie des Nombres de Bordeaux, Vol. 24, No. 2 (2012), pp. 293-305. https://doi.org/10.2307/43973105 .. [vdH1995] \J. van der Hoeven, "Automatic numerical expansions". Proc. of the conference Real numbers and computers (1995), 261-274. https://www.texmacs.org/joris/ane/ane-abs.html .. [vdH2006] \J. van der Hoeven, "Computations with effective real numbers". Theoretical Computer Science, Volume 351, Issue 1, 14 February 2006, Pages 52-60. https://doi.org/10.1016/j.tcs.2005.09.060 All referenced works: [AbbottBronsteinMulders1999]_, [Apostol1997]_, [Ari2011]_, [Ari2012]_, [Arn2010]_, [Arn2012]_, [ArnoldMonagan2011]_, [BBC1997]_, [BBC2000]_, [BBK2014]_, [BD1992]_, [BF2020]_, [BFSS2006]_, [BJ2013]_, [BM1980]_, [BZ1992]_, [BZ2011]_, [BaiWag1980]_, [BerTas2010]_, [Blo2009]_, [Bodrato2010]_, [Boe2020]_, [Bog2012]_, [Bol1887]_, [Bor1987]_, [Bor2000]_, [Bre1978]_, [Bre1979]_, [Bre2010]_, [BrentKung1978]_, [BuhlerCrandallSompolski1992]_, [CFG2017]_, [CFG2019]_, [CGHJK1996]_, [CP2005]_, [Car1995]_, [Car2004]_, [Chen2003]_, [Cho1999]_, [Coh1996]_, [Coh2000]_, [Col1971]_, [CraPom2005]_, [DHBHS2004]_, [DYF1999]_, [DelegliseNicolasZimmermann2009]_, [DomKanTro1987]_, [Dup2006]_, [Dus1999]_, [EHJ2016]_, [EM2004]_, [EK2023]_, [Fie2007]_, [FieHof2014]_, [Fil1992]_, [GCL1992]_, [GG2003]_, [GS2003]_, [GVL1996]_, [Gas2018]_, [Gos1974]_, [GowWag2008]_, [GraMol2010]_, [HM2017]_, [HS1967]_, [HZ2004]_, [HanZim2004]_, [Har2010]_, [Har2012]_, [Har2015]_, [Har2018]_, [Hart2010]_, [Hen1956]_, [Hoe2001]_, [Hoe2009]_, [Hor1972]_, [Iliopoulos1989]_, [Igu1972]_, [Igu1979]_, [JB2018]_, [JM2018]_, [JR1999]_, [Joh2012]_, [Joh2013]_, [Joh2014a]_, [Joh2014b]_, [Joh2014c]_, [Joh2015]_, [Joh2015b]_, [Joh2016]_, [Joh2017]_, [Joh2017a]_, [Joh2017b]_, [Joh2018a]_, [Joh2018b]_, [JvdP2002]_, [Kahan1991]_, [KanBac1979]_, [Kar1998]_, [Knu1997]_, [Kob2010]_, [Kri2013]_, [LT2016]_, [Leh1970]_, [LukPatWil1996]_, [MN2019]_, [MP2006]_, [MPFR2012]_, [MasRob1996]_, [Mic2007]_, [Miy2010]_, [Mos1971]_, [Mul2000]_, [Mum1983]_, [Mum1984]_, [NIST2012]_, [NakTurWil1997]_, [Olv1997]_, [PP2010]_, [PS1973]_, [PS1991]_, [Paterson1973]_, [PernetStein2010]_, [Pet1999]_, [Pla2011]_, [Pla2017]_, [RF1994]_, [Rad1973]_, [Rademacher1937]_, [Ric1992]_, [Ric1995]_, [Ric1997]_, [Ric2007]_, [Ric2009]_, [RosSch1962]_, [Rum2010]_, [Smi2001]_, [SorWeb2016]_, [Ste2002]_, [Ste2010]_, [Stehle2010]_, [Stein2007]_, [Sut2007]_, [StoMul1998]_, [Str2014]_, [Str1997]_, [Str2012]_, [Tak2000]_, [ThullYap1990]_, [Tre2008]_, [Tru2011]_, [Tru2014]_, [Tur1953]_, [Villard2007]_, [WaktinsZeitlin1993]_, [Wei2000]_, [Whiteman1956]_, [Zip1985]_, [Zun2023]_, [Zun2023b]_, [vHP2012]_, [vdH1995]_, [vdH2006]_ flint-3.1.3/doc/source/thread_pool.rst000066400000000000000000000041711461254215100177350ustar00rootroot00000000000000.. _thread-pool: **thread_pool.h** -- thread pool =============================================================================== Thread pool -------------------------------------------------------------------------------- .. type:: thread_pool_t This is a thread pool. .. type:: thread_pool_handle This is a handle to a thread in a thread pool. .. function:: void thread_pool_init(thread_pool_t T, slong size) Initialise ``T`` and create ``size`` sleeping threads that are available to work. If `size \le 0` no threads are created and future calls to :func:`thread_pool_request` will return `0` (unless :func:`thread_pool_set_size` has been called). .. function:: slong thread_pool_get_size(thread_pool_t T) Return the number of threads in ``T``. .. function:: int thread_pool_set_size(thread_pool_t T, slong new_size) If all threads in ``T`` are in the available state, resize ``T`` and return 1. Otherwise, return ``0``. .. function:: slong thread_pool_request(thread_pool_t T, thread_pool_handle * out, slong requested) Put at most ``requested`` threads in the unavailable state and return their handles. The handles are written to ``out`` and the number of handles written is returned. These threads must be released by a call to ``thread_pool_give_back``. .. function:: void thread_pool_wake(thread_pool_t T, thread_pool_handle i, int max_workers, void (*f)(void*), void * a) Wake up a sleeping thread ``i`` and have it work on ``f(a)``. The thread being woken will be allowed to start ``max_workers`` additional worker threads. Usually this value should be set to ``0``. .. function:: void thread_pool_wait(thread_pool_t T, thread_pool_handle i) Wait for thread ``i`` to finish working and go back to sleep. .. function:: void thread_pool_give_back(thread_pool_t T, thread_pool_handle i) Put thread ``i`` back in the available state. This thread should be sleeping when this function is called. .. function:: void thread_pool_clear(thread_pool_t T) Release any resources used by ``T``. All threads should be given back before this function is called. flint-3.1.3/doc/source/threading.rst000066400000000000000000000141771461254215100174110ustar00rootroot00000000000000.. _threading: **Threading** =============================================================================== Multithreaded FLINT ------------------------------------------------------------------------------- FLINT provides a number of multithreaded functions, which use multiple threads by default if FLINT was built with at least pthreads. (This functionality works best when thread local storage is also available on the system.) By default, FLINT will just use one thread. To control the maximum number of threads FLINT uses, one can call the function ``flint_set_num_threads(n)``, where `n` is the maximum number of threads to use. One can also query the current thread limit by calling ``flint_get_num_threads()``. Each version of FLINT brings new functions that are threaded by default. Many core algorithms such as the FFT (for large integer and polynomial operations, including some factoring algorithms), integer factoring and multivariate polynomial algorithms are threaded in FLINT. Writing threaded functions in FLINT ----------------------------------- Flint uses a custom thread pool for threading. This involves creating a worker function, requesting threads from the thread pool, starting the threads, waiting for them to finish, then giving the threads back to the pool. Simple examples of this include ``fmpz_mod_mat_mul_classical_threaded`` and ``fmpz_poly_taylor_shift_multi_mod``. The user should not have to run specialised versions of functions to get threading. This means that user facing functions should generally not have ``_threaded`` appended to their name. Either there is a single function that does the job, and it happens to be threaded, or there is a best-of-breed function that calls the appropriate threaded function when this is the best strategy. There are some instances where it may be desirable (e.g. for testing purposes, or because naming proves difficult) where one wants a _threaded in the name. But these cases should be rare. In some cases, one does not want functions to request threads from the pool themselves, but to accept threads from another function which has already obtained them. Such functions will accept an array of thread pool handles and a number of threads. The naming convention for such functions is to append ``_threaded_pool`` to the end of their name. However, the usual distinctions between underscore and non-underscore functions should still apply. Functions should request ``flint_get_num_threads()`` threads from the thread pool. The function should not exceed this number of threads in total. In general a thread that is woken should start zero additional workers. However, if this is not the desired behaviour, an option exists to the function for waking worker threads to alter how many threads it can start. In some cases it is also necessary to temporarily restrict the number of worker threads a given function can start. This is accomplished by calling flint_set_num_workers() and then once the function is called, calling flint_reset_num_workers(). Any threaded function which calls flint_get_num_threads() to determine how many threads to request from the thread pool will be appropriately restricted by such calls. Note that if ``flint_get_num_threads()`` returns ``n`` then the number of workers that can be started is ``n - 1`` (in addition to the thread the function is already running in). For this reason our documentation often distinguishes number of workers and number of threads. Please refer to the thread pool interface and Flint threading interface documentation to see the exact specification. Functional parallel programming helpers --------------------------------------- The following convenience function are defined in ``thread_support.h``. They are currently experimental, and the interfaces might change in a future version. .. function:: slong flint_get_num_available_threads() Returns the number of threads that are not currently in use. .. type:: void (* do_func_t)(slong i, void * args) .. function:: void flint_parallel_do(do_func_t f, void * args, slong n, int thread_limit, int flags) Evaluate ``f(i, args)`` for `0 \le i < n - 1` in parallel using up to ``thread_limits`` threads (including the master thread). If *thread_limit* is nonpositive, the number of threads defaults to ``flint_get_num_threads()``. The following ``flags`` are supported: ``FLINT_PARALLEL_UNIFORM`` - assumes that the cost of function calls is roughly constant, so that scheduling uniformly into blocks is efficient. ``FLINT_PARALLEL_STRIDED`` - assumes that the cost increases or decreases monotonically with ``i``, so that strided scheduling is efficient. ``FLINT_PARALLEL_DYNAMIC`` (not implemented) - use dynamic scheduling. ``FLINT_PARALLEL_VERBOSE`` - print information. .. type:: void (* bsplit_merge_func_t)(void *, void *, void *, void *) .. type:: void (* bsplit_basecase_func_t)(void *, slong, slong, void *) .. type:: void (* bsplit_init_func_t)(void *, void *) .. type:: void (* bsplit_clear_func_t)(void *, void *) .. function:: void flint_parallel_binary_splitting(void * res, bsplit_basecase_func_t basecase, bsplit_merge_func_t merge, size_t sizeof_res, bsplit_init_func_t init, bsplit_clear_func_t clear, void * args, slong a, slong b, slong basecase_cutoff, int thread_limit, int flags) Sets ``res`` to `f(a) \circ f(a+1) \circ \cdots \circ f(b - 1)` computed using parallel binary splitting, using up to ``thread_limits`` threads (including the master thread). If *thread_limit* is nonpositive, the number of threads defaults to ``flint_get_num_threads()``. The function ``basecase(res, a, b, args)`` gets called when `b - a` does not exceed ``basecase_cutoff``, which must be at least 1. The function ``merge(res, x, y, args)`` implements the associative operation (`x \circ y`), writing the result to ``res``. If called with ``FLINT_PARALLEL_BSPLIT_LEFT_INPLACE`` in ``flags``, the same space will be used for ``res`` and ``x``. A result is assumed to fit in a structure of size ``sizeof_res``. The functions ``init(res, args)`` and ``clear(res, args)`` initialize and clear intermediate result objects. flint-3.1.3/doc/source/ulong_extras.rst000066400000000000000000001773341461254215100201630ustar00rootroot00000000000000.. _ulong-extras: **ulong_extras.h** -- arithmetic and number-theoretic functions for single-word integers ======================================================================================== This module implements functions for single limb unsigned integers, including arithmetic with a precomputed inverse and modular arithmetic. The module includes functions for square roots, factorisation and primality testing. Almost all the functions in this module are highly developed and extremely well optimised. The basic type is the ``mp_limb_t`` as defined by GMP. Functions which take a precomputed inverse either have the suffix ``preinv`` and take an ``mp_limb_t`` precomputed inverse as computed by ``n_preinvert_limb`` or have the suffix ``_precomp`` and accept a ``double`` precomputed inverse as computed by ``n_precompute_inverse``. Sometimes three functions with similar names are provided for the same task, e.g. ``n_mod_precomp``, ``n_mod2_precomp`` and ``n_mod2_preinv``. If the part of the name that designates the functionality ends in 2 then the function has few if any limitations on its inputs. Otherwise the function may have limitations such as being limited to 52 or 53 bits. In practice we found that the preinv functions are generally faster anyway, so most times it pays to just use the ``n_blah2_preinv`` variants. Some functions with the ``n_ll_`` or ``n_lll_`` prefix accept parameters of two or three limbs respectively. Simple example -------------- The following example computes `ab \pmod{n}` using a precomputed inverse, where `a = 12345678, b = 87654321` and `n = 111111111`. .. code:: c #include #include "ulong_extras.h" int main() { mp_limb_t r, a, b, n, ninv; a = UWORD(12345678); b = UWORD(87654321); n = UWORD(111111111); ninv = n_preinvert_limb(n); r = n_mulmod2_preinv(a, b, n, ninv); flint_printf("%wu*%wu mod %wu is %wu\n", a, b, n, r); } The output is: .. code:: c 12345678*87654321 mod 111111111 is 23456790 Random functions -------------------------------------------------------------------------------- .. function:: ulong n_randlimb(flint_rand_t state) Returns a uniformly pseudo random limb. The algorithm generates two random half limbs `s_j`, `j = 0, 1`, by iterating respectively `v_{i+1} = (v_i a + b) \bmod{p_j}` for some initial seed `v_0`, randomly chosen values `a` and `b` and ``p_0 = 4294967311 = nextprime(2^32)`` on a 64-bit machine and ``p_0 = nextprime(2^16)`` on a 32-bit machine and ``p_1 = nextprime(p_0)``. .. function:: ulong n_randbits(flint_rand_t state, unsigned int bits) Returns a uniformly pseudo random number with the given number of bits. The most significant bit is always set, unless zero is passed, in which case zero is returned. .. function:: ulong n_randtest_bits(flint_rand_t state, int bits) Returns a uniformly pseudo random number with the given number of bits. The most significant bit is always set, unless zero is passed, in which case zero is returned. The probability of a value with a sparse binary representation being returned is increased. This function is intended for use in test code. .. function:: ulong n_randint(flint_rand_t state, ulong limit) Returns a uniformly pseudo random number up to but not including the given limit. If zero is passed as a parameter, an entire random limb is returned. .. function:: ulong n_urandint(flint_rand_t state, ulong limit) Returns a uniformly pseudo random number up to but not including the given limit. If zero is passed as a parameter, an entire random limb is returned. This function provides somewhat better randomness as compared to :func:`n_randint`, especially for larger values of limit. .. function:: ulong n_randtest(flint_rand_t state) Returns a pseudo random number with a random number of bits, from `0` to ``FLINT_BITS``. The probability of the special values `0`, `1`, ``COEFF_MAX`` and ``WORD_MAX`` is increased as is the probability of a value with sparse binary representation. This random function is mainly used for testing purposes. This function is intended for use in test code. .. function:: ulong n_randtest_not_zero(flint_rand_t state) As for :func:`n_randtest`, but does not return `0`. This function is intended for use in test code. .. function:: ulong n_randprime(flint_rand_t state, ulong bits, int proved) Returns a random prime number ``(proved = 1)`` or probable prime ``(proved = 0)`` with ``bits`` bits, where ``bits`` must be at least 2 and at most ``FLINT_BITS``. .. function:: ulong n_randtest_prime(flint_rand_t state, int proved) Returns a random prime number ``(proved = 1)`` or probable prime ``(proved = 0)`` with size randomly chosen between 2 and ``FLINT_BITS`` bits. This function is intended for use in test code. Basic arithmetic -------------------------------------------------------------------------------- .. function:: ulong n_pow(ulong n, ulong exp) Returns ``n^exp``. No checking is done for overflow. The exponent may be zero. We define `0^0 = 1`. The algorithm simply uses a for loop. Repeated squaring is unlikely to speed up this algorithm. .. function:: ulong n_flog(ulong n, ulong b) Returns `\lfloor\log_b n\rfloor`. Assumes that `n \geq 1` and `b \geq 2`. .. function:: ulong n_clog(ulong n, ulong b) Returns `\lceil\log_b n\rceil`. Assumes that `n \geq 1` and `b \geq 2`. .. function:: ulong n_clog_2exp(ulong n, ulong b) Returns `\lceil\log_b 2^n\rceil`. Assumes that `b \geq 2`. Miscellaneous -------------------------------------------------------------------------------- .. function:: ulong n_revbin(ulong n, ulong b) Returns the binary reverse of `n`, assuming it is `b` bits in length, e.g. ``n_revbin(10110, 6)`` will return ``110100``. .. function:: int n_sizeinbase(ulong n, int base) Returns the exact number of digits needed to represent `n` as a string in base ``base`` assumed to be between 2 and 36. Returns 1 when `n = 0`. Basic arithmetic with precomputed inverses -------------------------------------------------------------------------------- .. function:: ulong n_preinvert_limb_prenorm(ulong n) Computes an approximate inverse ``invxl`` of the limb ``xl``, with an implicit leading~`1`. More formally it computes:: invxl = (B^2 - B*x - 1)/x = (B^2 - 1)/x - B Note that `x` must be normalised, i.e. with msb set. This inverse makes use of the following theorem of Torbjorn Granlund and Peter Montgomery~[Lemma~8.1][GraMon1994]_: Let `d` be normalised, `d < B`, i.e. it fits in a word, and suppose that `m d < B^2 \leq (m+1) d`. Let `0 \leq n \leq B d - 1`. Write `n = n_2 B + n_1 B/2 + n_0` with `n_1 = 0` or `1` and `n_0 < B/2`. Suppose `q_1 B + q_0 = n_2 B + (n_2 + n_1) (m - B) + n_1 (d-B/2) + n_0` and `0 \leq q_0 < B`. Then `0 \leq q_1 < B` and `0 \leq n - q_1 d < 2 d`. In the theorem, `m` is the inverse of `d`. If we let ``m = invxl + B`` and `d = x` we have `m d = B^2 - 1 < B^2` and `(m+1) x = B^2 + d - 1 \geq B^2`. The theorem is often applied as follows: note that `n_0` and `n_1 (d-B/2)` are both less than `B/2`. Also note that `n_1 (m-B) < B`. Thus the sum of all these terms contributes at most `1` to `q_1`. We are left with `n_2 B + n_2 (m-B)`. But note that `(m-B)` is precisely our precomputed inverse ``invxl``. If we write `q_1 B + q_0 = n_2 B + n_2 (m-B)`, then from the theorem, we have `0 \leq n - q_1 d < 3 d`, i.e. the quotient is out by at most `2` and is always either correct or too small. .. function:: ulong n_preinvert_limb(ulong n) Returns a precomputed inverse of `n`, as defined in [GraMol2010]_. This precomputed inverse can be used with all of the functions that take a precomputed inverse whose names are suffixed by ``_preinv``. We require `n > 0`. .. function:: double n_precompute_inverse(ulong n) Returns a precomputed inverse of `n` with double precision value `1/n`. This precomputed inverse can be used with all of the functions that take a precomputed inverse whose names are suffixed by ``_precomp``. We require `n > 0`. .. function:: ulong n_mod_precomp(ulong a, ulong n, double ninv) Returns `a \bmod{n}` given a precomputed inverse of `n` computed by :func:`n_precompute_inverse`. We require ``n < 2^FLINT_D_BITS`` and ``a < 2^(FLINT_BITS-1)`` and `0 \leq a < n^2`. We assume the processor is in the standard round to nearest mode. Thus ``ninv`` is correct to `53` binary bits, the least significant bit of which we shall call a place, and can be at most half a place out. When `a` is multiplied by `ninv`, the binary representation of `a` is exact and the mantissa is less than `2`, thus we see that ``a * ninv`` can be at most one out in the mantissa. We now truncate ``a * ninv`` to the nearest integer, which is always a round down. Either we already have an integer, or we need to make a change down of at least `1` in the last place. In the latter case we either get precisely the exact quotient or below it as when we rounded the product to the nearest place we changed by at most half a place. In the case that truncating to an integer takes us below the exact quotient, we have rounded down by less than `1` plus half a place. But as the product is less than `n` and `n` is less than `2^{53}`, half a place is less than `1`, thus we are out by less than `2` from the exact quotient, i.e. the quotient we have computed is the quotient we are after or one too small. That leaves only the case where we had to round up to the nearest place which happened to be an integer, so that truncating to an integer didn't change anything. But this implies that the exact quotient `a/n` is less than `2^{-54}` from an integer. We deal with this rare case by subtracting 1 from the quotient. Then the quotient we have computed is either exactly what we are after, or one too small. .. function:: ulong n_mod2_precomp(ulong a, ulong n, double ninv) Returns `a \bmod{n}` given a precomputed inverse of `n` computed by :func:`n_precompute_inverse`. There are no restrictions on `a` or on `n`. As for :func:`n_mod_precomp` for `n < 2^{53}` and `a < n^2` the computed quotient is either what we are after or one too large or small. We deal with these cases. Otherwise we can be sure that the top `52` bits of the quotient are computed correctly. We take the remainder and adjust the quotient by multiplying the remainder by ``ninv`` to compute another approximate quotient as per :func:`mod_precomp`. Now the remainder may be either negative or positive, so the quotient we compute may be one out in either direction. .. function:: ulong n_divrem2_preinv(ulong * q, ulong a, ulong n, ulong ninv) Returns `a \bmod{n}` and sets `q` to the quotient of `a` by `n`, given a precomputed inverse of `n` computed by :func:`n_preinvert_limb()`. There are no restrictions on `a` and the only restriction on `n` is that it be nonzero. This uses the algorithm of Granlund and Möller [GraMol2010]_. First `n` is normalised and `a` is shifted into two limbs to compensate. Then their algorithm is applied verbatim and the remainder shifted back. .. function:: ulong n_div2_preinv(ulong a, ulong n, ulong ninv) Returns the Euclidean quotient of `a` by `n` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`. There are no restrictions on `a` and the only restriction on `n` is that it be nonzero. This uses the algorithm of Granlund and Möller [GraMol2010]_. First `n` is normalised and `a` is shifted into two limbs to compensate. Then their algorithm is applied verbatim. .. function:: ulong n_mod2_preinv(ulong a, ulong n, ulong ninv) Returns `a \bmod{n}` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb()`. There are no restrictions on `a` and the only restriction on `n` is that it be nonzero. This uses the algorithm of Granlund and Möller [GraMol2010]_. First `n` is normalised and `a` is shifted into two limbs to compensate. Then their algorithm is applied verbatim and the result shifted back. .. function:: ulong n_divrem2_precomp(ulong * q, ulong a, ulong n, double npre) Returns `a \bmod{n}` given a precomputed inverse of `n` computed by :func:`n_precompute_inverse` and sets `q` to the quotient. There are no restrictions on `a` or on `n`. This is as for :func:`n_mod2_precomp` with some additional care taken to retain the quotient information. There are also special cases to deal with the case where `a` is already reduced modulo `n` and where `n` is `64` bits and `a` is not reduced modulo `n`. .. function:: ulong n_ll_mod_preinv(ulong a_hi, ulong a_lo, ulong n, ulong ninv) Returns `a \bmod{n}` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`. There are no restrictions on `a`, which will be two limbs ``(a_hi, a_lo)``, or on `n`. The old version of this function merely reduced the top limb ``a_hi`` modulo `n` so that :func:`udiv_qrnnd_preinv()` could be used. The new version reduces the top limb modulo `n` as per :func:`n_mod2_preinv` and then the algorithm of Granlund and Möller [GraMol2010]_ is used again to reduce modulo `n`. .. function:: ulong n_lll_mod_preinv(ulong a_hi, ulong a_mi, ulong a_lo, ulong n, ulong ninv) Returns `a \bmod{n}`, where `a` has three limbs ``(a_hi, a_mi, a_lo)``, given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`. It is assumed that ``a_hi`` is reduced modulo `n`. There are no restrictions on `n`. This function uses the algorithm of Granlund and Möller [GraMol2010]_ to first reduce the top two limbs modulo `n`, then does the same on the bottom two limbs. .. function:: ulong n_mulmod_precomp(ulong a, ulong b, ulong n, double ninv) Returns `a b \bmod{n}` given a precomputed inverse of `n` computed by :func:`n_precompute_inverse`. We require ``n < 2^FLINT_D_BITS`` and `0 \leq a, b < n`. We assume the processor is in the standard round to nearest mode. Thus ``ninv`` is correct to `53` binary bits, the least significant bit of which we shall call a place, and can be at most half a place out. The product of `a` and `b` is computed with error at most half a place. When ``a * b`` is multiplied by `ninv` we find that the exact quotient and computed quotient differ by less than two places. As the quotient is less than `n` this means that the exact quotient is at most `1` away from the computed quotient. We truncate this quotient to an integer which reduces the value by less than `1`. We end up with a value which can be no more than two above the quotient we are after and no less than two below. However an argument similar to that for :func:`n_mod_precomp` shows that the truncated computed quotient cannot be two smaller than the truncated exact quotient. In other words the computed integer quotient is at most two above and one below the quotient we are after. .. function:: ulong n_mulmod2_preinv(ulong a, ulong b, ulong n, ulong ninv) Returns `a b \bmod{n}` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`. There are no restrictions on `a`, `b` or on `n`. This is implemented by multiplying using :func:`umul_ppmm` and then reducing using :func:`n_ll_mod_preinv`. .. function:: ulong n_mulmod2(ulong a, ulong b, ulong n) Returns `a b \bmod{n}`. There are no restrictions on `a`, `b` or on `n`. This is implemented by multiplying using :func:`umul_ppmm` and then reducing using :func:`n_ll_mod_preinv` after computing a precomputed inverse. .. function:: ulong n_mulmod_preinv(ulong a, ulong b, ulong n, ulong ninv, ulong norm) Returns `a b \pmod{n}` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`, assuming `a` and `b` are reduced modulo `n` and `n` is normalised, i.e. with most significant bit set. There are no other restrictions on `a`, `b` or `n`. The value ``norm`` is provided for convenience. As `n` is required to be normalised, it may be that `a` and `b` have been shifted to the left by ``norm`` bits before calling the function. Their product then has an extra factor of `2^\text{norm}`. Specifying a nonzero ``norm`` will shift the product right by this many bits before reducing it. The algorithm used is that of Granlund and Möller [GraMol2010]_. Greatest common divisor -------------------------------------------------------------------------------- .. function:: ulong n_gcd(ulong x, ulong y) Returns the greatest common divisor `g` of `x` and `y`. No assumptions are made about the values `x` and `y`. This function wraps GMP's ``mpn_gcd_1``. .. function:: ulong n_gcdinv(ulong * a, ulong x, ulong y) Returns the greatest common divisor `g` of `x` and `y` and computes `a` such that `0 \leq a < y` and `a x = \gcd(x, y) \bmod{y}`, when this is defined. We require `x < y`. When `y = 1` the greatest common divisor is set to `1` and `a` is set to `0`. This is merely an adaption of the extended Euclidean algorithm computing just one cofactor and reducing it modulo `y`. .. function:: ulong n_xgcd(ulong * a, ulong * b, ulong x, ulong y) Returns the greatest common divisor `g` of `x` and `y` and unsigned values `a` and `b` such that `a x - b y = g`. We require `x \geq y`. We claim that computing the extended greatest common divisor via the Euclidean algorithm always results in cofactor `\lvert a \rvert < x/2`, `\lvert b\rvert < x/2`, with perhaps some small degenerate exceptions. We proceed by induction. Suppose we are at some step of the algorithm, with `x_n = q y_n + r` with `r \geq 1`, and suppose `1 = s y_n - t r` with `s < y_n / 2`, `t < y_n / 2` by hypothesis. Write `1 = s y_n - t (x_n - q y_n) = (s + t q) y_n - t x_n`. It suffices to show that `(s + t q) < x_n / 2` as `t < y_n / 2 < x_n / 2`, which will complete the induction step. But at the previous step in the backsubstitution we would have had `1 = s r - c d` with `s < r/2` and `c < r/2`. Then `s + t q < r/2 + y_n / 2 q = (r + q y_n)/2 = x_n / 2`. See the documentation of :func:`n_gcd` for a description of the branching in the algorithm, which is faster than using division. Jacobi and Kronecker symbols -------------------------------------------------------------------------------- .. function:: int n_jacobi(mp_limb_signed_t x, ulong y) Computes the Jacobi symbol `\left(\frac{x}{y}\right)` for any `x` and odd `y`. .. function:: int n_jacobi_unsigned(ulong x, ulong y) Computes the Jacobi symbol, allowing `x` to go up to a full limb. Modular Arithmetic -------------------------------------------------------------------------------- .. function:: ulong n_addmod(ulong a, ulong b, ulong n) Returns `(a + b) \bmod{n}`. .. function:: ulong n_submod(ulong a, ulong b, ulong n) Returns `(a - b) \bmod{n}`. .. function:: ulong n_invmod(ulong x, ulong y) Returns the inverse of `x` modulo `y`, if it exists. Otherwise an exception is thrown. This is merely an adaption of the extended Euclidean algorithm with appropriate normalisation. .. function:: ulong n_powmod_precomp(ulong a, mp_limb_signed_t exp, ulong n, double npre) Returns ``a^exp`` modulo `n` given a precomputed inverse of `n` computed by :func:`n_precompute_inverse`. We require `n < 2^{53}` and `0 \leq a < n`. There are no restrictions on ``exp``, i.e. it can be negative. This is implemented as a standard binary powering algorithm using repeated squaring and reducing modulo `n` at each step. .. function:: ulong n_powmod_ui_precomp(ulong a, ulong exp, ulong n, double npre) Returns ``a^exp`` modulo `n` given a precomputed inverse of `n` computed by :func:`n_precompute_inverse`. We require `n < 2^{53}` and `0 \leq a < n`. The exponent ``exp`` is unsigned and so can be larger than allowed by :func:`n_powmod_precomp`. This is implemented as a standard binary powering algorithm using repeated squaring and reducing modulo `n` at each step. .. function:: ulong n_powmod(ulong a, mp_limb_signed_t exp, ulong n) Returns ``a^exp`` modulo `n`. We require ``n < 2^FLINT_D_BITS`` and `0 \leq a < n`. There are no restrictions on ``exp``, i.e. it can be negative. This is implemented by precomputing an inverse and calling the ``precomp`` version of this function. .. function:: ulong n_powmod2_preinv(ulong a, mp_limb_signed_t exp, ulong n, ulong ninv) Returns ``(a^exp) % n`` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`. We require `0 \leq a < n`, but there are no restrictions on `n` or on ``exp``, i.e. it can be negative. This is implemented as a standard binary powering algorithm using repeated squaring and reducing modulo `n` at each step. If ``exp`` is negative but `a` is not invertible modulo `n`, an exception is raised. .. function:: ulong n_powmod2(ulong a, mp_limb_signed_t exp, ulong n) Returns ``(a^exp) % n``. We require `0 \leq a < n`, but there are no restrictions on `n` or on ``exp``, i.e. it can be negative. This is implemented by precomputing an inverse limb and calling the ``preinv`` version of this function. If ``exp`` is negative but `a` is not invertible modulo `n`, an exception is raised. .. function:: ulong n_powmod2_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv) Returns ``(a^exp) % n`` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`. We require `0 \leq a < n`, but there are no restrictions on `n`. The exponent ``exp`` is unsigned and so can be larger than allowed by :func:`n_powmod2_preinv`. This is implemented as a standard binary powering algorithm using repeated squaring and reducing modulo `n` at each step. .. function:: ulong n_powmod2_fmpz_preinv(ulong a, const fmpz_t exp, ulong n, ulong ninv) Returns ``(a^exp) % n`` given a precomputed inverse of `n` computed by :func:`n_preinvert_limb`. We require `0 \leq a < n`, but there are no restrictions on `n`. The exponent ``exp`` must not be negative. This is implemented as a standard binary powering algorithm using repeated squaring and reducing modulo `n` at each step. .. function:: ulong n_sqrtmod(ulong a, ulong p) If `p` is prime, compute a square root of `a` modulo `p` if `a` is a quadratic residue modulo `p`, otherwise return `0`. If `p` is not prime the result is with high probability `0`, indicating that `p` is not prime, or `a` is not a square modulo `p`. Otherwise the result is meaningless. Assumes that `a` is reduced modulo `p`. .. function:: slong n_sqrtmod_2pow(ulong ** sqrt, ulong a, slong exp) Computes all the square roots of ``a`` modulo ``2^exp``. The roots are stored in an array which is created and whose address is stored in the location pointed to by ``sqrt``. The array of roots is allocated by the function but must be cleaned up by the user by calling ``flint_free``. The number of roots is returned by the function. If ``a`` is not a quadratic residue modulo ``2^exp`` then 0 is returned by the function and the location ``sqrt`` points to is set to NULL. .. function:: slong n_sqrtmod_primepow(ulong ** sqrt, ulong a, ulong p, slong exp) Computes all the square roots of ``a`` modulo ``p^exp``. The roots are stored in an array which is created and whose address is stored in the location pointed to by ``sqrt``. The array of roots is allocated by the function but must be cleaned up by the user by calling ``flint_free``. The number of roots is returned by the function. If ``a`` is not a quadratic residue modulo ``p^exp`` then 0 is returned by the function and the location ``sqrt`` points to is set to NULL. .. function:: slong n_sqrtmodn(ulong ** sqrt, ulong a, n_factor_t * fac) Computes all the square roots of ``a`` modulo ``m`` given the factorisation of ``m`` in ``fac``. The roots are stored in an array which is created and whose address is stored in the location pointed to by ``sqrt``. The array of roots is allocated by the function but must be cleaned up by the user by calling :func:`flint_free`. The number of roots is returned by the function. If ``a`` is not a quadratic residue modulo ``m`` then 0 is returned by the function and the location ``sqrt`` points to is set to NULL. .. function:: mp_limb_t n_mulmod_shoup(mp_limb_t w, mp_limb_t t, mp_limb_t w_precomp, mp_limb_t p) Returns `w t \bmod{p}` given a precomputed scaled approximation of `w / p` computed by :func:`n_mulmod_precomp_shoup`. The value of `p` should be less than `2^{\mathtt{FLINT\_BITS} - 1}`. `w` and `t` should be less than `p`. Works faster than :func:`n_mulmod2_preinv` if `w` fixed and `t` from array (for example, scalar multiplication of vector). .. function:: mp_limb_t n_mulmod_precomp_shoup(mp_limb_t w, mp_limb_t p) Returns `w'`, scaled approximation of `w / p`. `w'` is equal to the integer part of `w \cdot 2^{\mathtt{FLINT\_BITS}} / p`. Divisibility testing -------------------------------------------------------------------------------- .. function:: int n_divides(mp_limb_t * q, mp_limb_t n, mp_limb_t p) Returns ``1`` if ``p`` divides ``n`` and sets ``q`` to the quotient, otherwise returns ``0`` and sets ``q`` to ``0``. Prime number generation and counting -------------------------------------------------------------------------------- .. function:: void n_primes_init(n_primes_t iter) Initialises the prime number iterator ``iter`` for use. .. function:: void n_primes_clear(n_primes_t iter) Clears memory allocated by the prime number iterator ``iter``. .. function:: ulong n_primes_next(n_primes_t iter) Returns the next prime number and advances the state of ``iter``. The first call returns 2. Small primes are looked up from ``flint_small_primes``. When this table is exhausted, primes are generated in blocks by calling :func:`n_primes_sieve_range`. .. function:: void n_primes_jump_after(n_primes_t iter, ulong n) Changes the state of ``iter`` to start generating primes after `n` (excluding `n` itself). .. function:: void n_primes_extend_small(n_primes_t iter, ulong bound) Extends the table of small primes in ``iter`` to contain at least two primes larger than or equal to ``bound``. .. function:: void n_primes_sieve_range(n_primes_t iter, ulong a, ulong b) Sets the block endpoints of ``iter`` to the smallest and largest odd numbers between `a` and `b` inclusive, and sieves to mark all odd primes in this range. The iterator state is changed to point to the first number in the sieved range. .. function:: void n_compute_primes(ulong num_primes) Precomputes at least ``num_primes`` primes and their ``double`` precomputed inverses and stores them in an internal cache. Assuming that FLINT has been built with support for thread-local storage, each thread has its own cache. .. function:: const ulong * n_primes_arr_readonly(ulong num_primes) Returns a pointer to a read-only array of the first ``num_primes`` prime numbers. The computed primes are cached for repeated calls. The pointer is valid until the user calls :func:`n_cleanup_primes` in the same thread. .. function:: const double * n_prime_inverses_arr_readonly(ulong n) Returns a pointer to a read-only array of inverses of the first ``num_primes`` prime numbers. The computed primes are cached for repeated calls. The pointer is valid until the user calls :func:`n_cleanup_primes` in the same thread. .. function:: void n_cleanup_primes() Frees the internal cache of prime numbers used by the current thread. This will invalidate any pointers returned by :func:`n_primes_arr_readonly` or :func:`n_prime_inverses_arr_readonly`. .. function:: ulong n_nextprime(ulong n, int proved) Returns the next prime after `n`. Assumes the result will fit in an ``ulong``. If proved is `0`, i.e. false, the prime is not proven prime, otherwise it is. .. function:: ulong n_prime_pi(ulong n) Returns the value of the prime counting function `\pi(n)`, i.e. the number of primes less than or equal to `n`. The invariant ``n_prime_pi(n_nth_prime(n)) == n``. Currently, this function simply extends the table of cached primes up to an upper limit and then performs a binary search. .. function:: void n_prime_pi_bounds(ulong * lo, ulong * hi, ulong n) Calculates lower and upper bounds for the value of the prime counting function ``lo <= pi(n) <= hi``. If ``lo`` and ``hi`` point to the same location, the high value will be stored. This does a table lookup for small values, then switches over to some proven bounds. The upper approximation is `1.25506 n / \ln n`, and the lower is `n / \ln n`. These bounds are due to Rosser and Schoenfeld [RosSch1962]_ and valid for `n \geq 17`. We use the number of bits in `n` (or one less) to form an approximation to `\ln n`, taking care to use a value too small or too large to maintain the inequality. .. function:: ulong n_nth_prime(ulong n) Returns the `n`\th prime number `p_n`, using the mathematical indexing convention `p_1 = 2, p_2 = 3, \dotsc`. This function simply ensures that the table of cached primes is large enough and then looks up the entry. .. function:: void n_nth_prime_bounds(ulong * lo, ulong * hi, ulong n) Calculates lower and upper bounds for the `n`\th prime number `p_n` , ``lo <= p_n <= hi``. If ``lo`` and ``hi`` point to the same location, the high value will be stored. Note that this function will overflow for sufficiently large `n`. We use the following estimates, valid for `n > 5` : .. math:: p_n & > n (\ln n + \ln \ln n - 1) \\ p_n & < n (\ln n + \ln \ln n) \\ p_n & < n (\ln n + \ln \ln n - 0.9427) \quad (n \geq 15985) The first inequality was proved by Dusart [Dus1999]_, and the last is due to Massias and Robin [MasRob1996]_. For a further overview, see http://primes.utm.edu/howmany.shtml . We bound `\ln n` using the number of bits in `n` as in ``n_prime_pi_bounds()``, and estimate `\ln \ln n` to the nearest integer; this function is nearly constant. Primality testing -------------------------------------------------------------------------------- .. function:: int n_is_oddprime_small(ulong n) Returns `1` if `n` is an odd prime smaller than ``FLINT_ODDPRIME_SMALL_CUTOFF``. Expects `n` to be odd and smaller than the cutoff. This function merely uses a lookup table with one bit allocated for each odd number up to the cutoff. .. function:: int n_is_oddprime_binary(ulong n) This function performs a simple binary search through the table of cached primes for `n`. If it exists in the array it returns `1`, otherwise `0`. For the algorithm to operate correctly `n` should be odd and at least `17`. Lower and upper bounds are computed with :func:`n_prime_pi_bounds`. Once we have bounds on where to look in the table, we refine our search with a simple binary algorithm, taking the top or bottom of the current interval as necessary. .. function:: int n_is_prime_pocklington(ulong n, ulong iterations) Tests if `n` is a prime using the Pocklington--Lehmer primality test. If `1` is returned `n` has been proved prime. If `0` is returned `n` is composite. However `-1` may be returned if nothing was proved either way due to the number of iterations being too small. The most time consuming part of the algorithm is factoring `n - 1`. For this reason :func:`n_factor_partial` is used, which uses a combination of trial factoring and Hart's one line factor algorithm [Har2012]_ to try to quickly factor `n - 1`. Additionally if the cofactor is less than the square root of `n - 1` the algorithm can still proceed. One can also specify a number of iterations if less time should be taken. Simply set this to ``WORD(0)`` if this is irrelevant. In most cases a greater number of iterations will not significantly affect timings as most of the time is spent factoring. See https://mathworld.wolfram.com/PocklingtonsTheorem.html for a description of the algorithm. .. function:: int n_is_prime_pseudosquare(ulong n) Tests if `n` is a prime according to Theorem 2.7 [LukPatWil1996]_. We first factor `N` using trial division up to some limit `B`. In fact, the number of primes used in the trial factoring is at most ``FLINT_PSEUDOSQUARES_CUTOFF``. Next we compute `N/B` and find the next pseudosquare `L_p` above this value, using a static table as per https://oeis.org/A002189/b002189.txt . As noted in the text, if `p` is prime then Step 3 will pass. This test rejects many composites, and so by this time we suspect that `p` is prime. If `N` is `3` or `7` modulo `8`, we are done, and `N` is prime. We now run a probable prime test, for which no known counterexamples are known, to reject any composites. We then proceed to prove `N` prime by executing Step 4. In the case that `N` is `1` modulo `8`, if Step 4 fails, we extend the number of primes `p_i` at Step 3 and hope to find one which passes Step 4. We take the test one past the largest `p` for which we have pseudosquares `L_p` tabulated, as this already corresponds to the next `L_p` which is bigger than `2^{64}` and hence larger than any prime we might be testing. As explained in the text, Condition 4 cannot fail if `N` is prime. The possibility exists that the probable prime test declares a composite prime. However in that case an error is printed, as that would be of independent interest. .. function:: int n_is_prime(ulong n) Tests if `n` is a prime. This first sieves for small prime factors, then simply calls :func:`n_is_probabprime`. This has been checked against the tables of Feitsma and Galway http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html and thus constitutes a check for primality (rather than just pseudoprimality) up to `2^{64}`. In future, this test may produce and check a certificate of primality. This is likely to be significantly slower for prime inputs. .. function:: int n_is_strong_probabprime_precomp(ulong n, double npre, ulong a, ulong d) Tests if `n` is a strong probable prime to the base `a`. We require that `d` is set to the largest odd factor of `n - 1` and ``npre`` is a precomputed inverse of `n` computed with :func:`n_precompute_inverse`. We also require that `n < 2^{53}`, `a` to be reduced modulo `n` and not `0` and `n` to be odd. If we write `n - 1 = 2^s d` where `d` is odd then `n` is a strong probable prime to the base `a`, i.e. an `a`-SPRP, if either `a^d = 1 \pmod n` or `(a^d)^{2^r} = -1 \pmod n` for some `r` less than `s`. A description of strong probable primes is given here: https://mathworld.wolfram.com/StrongPseudoprime.html .. function:: int n_is_strong_probabprime2_preinv(ulong n, ulong ninv, ulong a, ulong d) Tests if `n` is a strong probable prime to the base `a`. We require that `d` is set to the largest odd factor of `n - 1` and ``npre`` is a precomputed inverse of `n` computed with :func:`n_preinvert_limb`. We require `a` to be reduced modulo `n` and non-zero, and `n` to be odd. If we write `n - 1 = 2^s d` where `d` is odd then `n` is a strong probable prime to the base `a` (an `a`-SPRP) if either `a^d = 1 \pmod n` or `(a^d)^{2^r} = -1 \pmod n` for some `r` less than `s`. A description of strong probable primes is given here: https://mathworld.wolfram.com/StrongPseudoprime.html .. function:: int n_is_probabprime_fermat(ulong n, ulong i) Returns `1` if `n` is a base `i` Fermat probable prime. Requires `1 < i < n` and that `i` does not divide `n`. By Fermat's Little Theorem if `i^{n-1}` is not congruent to `1` then `n` is not prime. .. function:: int n_is_probabprime_fibonacci(ulong n) Let `F_j` be the `j`\th element of the Fibonacci sequence `0, 1, 1, 2, 3, 5, \dotsc`, starting at `j = 0`. Then if `n` is prime we have `F_{n - (n/5)} = 0 \pmod n`, where `(n/5)` is the Jacobi symbol. For further details, see pp. 142 [CraPom2005]_. We require that `n` is not divisible by `2` or `5`. .. function:: int n_is_probabprime_BPSW(ulong n) Implements a Baillie--Pomerance--Selfridge--Wagstaff probable primality test. This is a variant of the usual BPSW test (which only uses strong base-2 probable prime and Lucas-Selfridge tests, see Baillie and Wagstaff [BaiWag1980]_). This implementation makes use of a weakening of the usual Baillie-PSW test given in [Chen2003]_, namely replacing the Lucas test with a Fibonacci test when `n \equiv 2, 3 \pmod{5}` (see also the comment on page 143 of [CraPom2005]_), regarding Fibonacci pseudoprimes. There are no known counterexamples to this being a primality test. Up to `2^{64}` the test we use has been checked against tables of pseudoprimes. Thus it is a primality test up to this limit. .. function:: int n_is_probabprime_lucas(ulong n) For details on Lucas pseudoprimes, see [pp. 143] [CraPom2005]_. We implement a variant of the Lucas pseudoprime test similar to that described by Baillie and Wagstaff [BaiWag1980]_. .. function:: int n_is_probabprime(ulong n) Tests if `n` is a probable prime. Up to ``FLINT_ODDPRIME_SMALL_CUTOFF`` this algorithm uses :func:`n_is_oddprime_small` which uses a lookup table. Next it calls :func:`n_compute_primes` with the maximum table size and uses this table to perform a binary search for `n` up to the table limit. Then up to `1050535501` it uses a number of strong probable prime tests, :func:`n_is_strong_probabprime_preinv`, etc., for various bases. The output of the algorithm is guaranteed to be correct up to this bound due to exhaustive tables, described at http://uucode.com/obf/dalbec/alg.html . Beyond that point the BPSW probabilistic primality test is used, by calling the function :func:`n_is_probabprime_BPSW`. There are no known counterexamples, and it has been checked against the tables of Feitsma and Galway and up to the accuracy of those tables, this is an exhaustive check up to `2^{64}`, i.e. there are no counterexamples. Chinese remaindering -------------------------------------------------------------------------------- .. function:: ulong n_CRT(ulong r1, ulong m1, ulong r2, ulong m2) Use the Chinese Remainder Theorem to return the unique value `0 \le x < M` congruent to `r_1` modulo `m_1` and `r_2` modulo `m_2`, where `M = m_1 \times m_2` is assumed to fit a ulong. It is assumed that `m_1` and `m_2` are positive integers greater than `1` and coprime. It is assumed that `0 \le r_1 < m_1` and `0 \le r_2 < m_2`. Square root and perfect power testing -------------------------------------------------------------------------------- .. function:: ulong n_sqrt(ulong a) Computes the integer truncation of the square root of `a`. The implementation uses a call to the IEEE floating point sqrt function. The integer itself is represented by the nearest double and its square root is computed to the nearest place. If `a` is one below a square, the rounding may be up, whereas if it is one above a square, the rounding will be down. Thus the square root may be one too large in some instances which we then adjust by checking if we have the right value. We also have to be careful when the square of this too large value causes an overflow. The same assumptions hold for a single precision float provided the square root itself can be represented in a single float, i.e. for `a < 281474976710656 = 2^{46}`. .. function:: ulong n_sqrtrem(ulong * r, ulong a) Computes the integer truncation of the square root of `a`. The integer itself is represented by the nearest double and its square root is computed to the nearest place. If `a` is one below a square, the rounding may be up, whereas if it is one above a square, the rounding will be down. Thus the square root may be one too large in some instances which we then adjust by checking if we have the right value. We also have to be careful when the square of this too large value causes an overflow. The same assumptions hold for a single precision float provided the square root itself can be represented in a single float, i.e. for \ `a < 281474976710656 = 2^{46}`. The remainder is computed by subtracting the square of the computed square root from `a`. .. function:: int n_is_square(ulong x) Returns `1` if `x` is a square, otherwise `0`. This code first checks if `x` is a square modulo `64`, `63 = 3 \times 3 \times 7` and `65 = 5 \times 13`, using lookup tables, and if so it then takes a square root and checks that the square of this equals the original value. .. function:: int n_is_perfect_power235(ulong n) Returns `1` if `n` is a perfect square, cube or fifth power. This function uses a series of modular tests to reject most non 235-powers. Each modular test returns a value from 0 to 7 whose bits respectively indicate whether the value is a square, cube or fifth power modulo the given modulus. When these are logically ``AND``-ed together, this gives a powerful test which will reject most non-235 powers. If a bit remains set indicating it may be a square, a standard square root test is performed. Similarly a cube root or fifth root can be taken, if indicated, to determine whether the power of that root is exactly equal to `n`. .. function:: int n_is_perfect_power(ulong * root, ulong n) If `n = r^k`, return `k` and set ``root`` to `r`. Note that `0` and `1` are considered squares. No guarantees are made about `r` or `k` being the minimum possible value. .. function:: ulong n_rootrem(ulong * remainder, ulong n, ulong root) This function uses the Newton iteration method to calculate the nth root of a number. First approximation is calculated by an algorithm mentioned in this article: https://en.wikipedia.org/wiki/Fast_inverse_square_root . Instead of the inverse square root, the nth root is calculated. Returns the integer part of ``n ^ 1/root``. Remainder is set as ``n - base^root``. In case `n < 1` or ``root < 1``, `0` is returned. .. function:: ulong n_cbrt(ulong n) This function returns the integer truncation of the cube root of `n`. First approximation is calculated by an algorithm mentioned in this article: https://en.wikipedia.org/wiki/Fast_inverse_square_root . Instead of the inverse square root, the cube root is calculated. This functions uses different algorithms to calculate the cube root, depending upon the size of `n`. For numbers greater than `2^{46}`, it uses :func:`n_cbrt_chebyshev_approx`. Otherwise, it makes use of the iteration, `x \leftarrow x - (x\cdot x\cdot x - a)\cdot x/(2\cdot x\cdot x\cdot x + a)` for getting a good estimate, as mentioned in the paper by W. Kahan [Kahan1991]_ . .. function:: ulong n_cbrt_newton_iteration(ulong n) This function returns the integer truncation of the cube root of `n`. Makes use of Newton iterations to get a close value, and then adjusts the estimate so as to get the correct value. .. function:: ulong n_cbrt_binary_search(ulong n) This function returns the integer truncation of the cube root of `n`. Uses binary search to get the correct value. .. function:: ulong n_cbrt_chebyshev_approx(ulong n) This function returns the integer truncation of the cube root of `n`. The number is first expressed in the form ``x * 2^exp``. This ensures `x` is in the range [0.5, 1]. Cube root of x is calculated using Chebyshev's approximation polynomial for the function `y = x^{1/3}`. The values of the coefficient are calculated from the Python module mpmath, https://mpmath.org, using the function chebyfit. x is multiplied by ``2^exp`` and the cube root of 1, 2 or 4 (according to ``exp%3``). .. function:: ulong n_cbrtrem(ulong * remainder, ulong n) This function returns the integer truncation of the cube root of `n`. Remainder is set as `n` minus the cube of the value returned. Factorisation -------------------------------------------------------------------------------- .. function:: void n_factor_init(n_factor_t * factors) Initializes factors. .. function:: int n_remove(ulong * n, ulong p) Removes the highest possible power of `p` from `n`, replacing `n` with the quotient. The return value is the highest power of `p` that divided `n`. Assumes `n` is not `0`. For `p = 2` trailing zeroes are counted. For other primes `p` is repeatedly squared and stored in a table of powers with the current highest power of `p` removed at each step until no higher power can be removed. The algorithm then proceeds down the power tree again removing powers of `p` until none remain. .. function:: int n_remove2_precomp(ulong * n, ulong p, double ppre) Removes the highest possible power of `p` from `n`, replacing `n` with the quotient. The return value is the highest power of `p` that divided `n`. Assumes `n` is not `0`. We require ``ppre`` to be set to a precomputed inverse of `p` computed with :func:`n_precompute_inverse`. For `p = 2` trailing zeroes are counted. For other primes `p` we make repeated use of :func:`n_divrem2_precomp` until division by `p` is no longer possible. .. function:: void n_factor_insert(n_factor_t * factors, ulong p, ulong exp) Inserts the given prime power factor ``p^exp`` into the ``n_factor_t`` ``factors``. See the documentation for :func:`n_factor_trial` for a description of the ``n_factor_t`` type. The algorithm performs a simple search to see if `p` already exists as a prime factor in the structure. If so the exponent there is increased by the supplied exponent. Otherwise a new factor ``p^exp`` is added to the end of the structure. There is no test code for this function other than its use by the various factoring functions, which have test code. .. function:: ulong n_factor_trial_range(n_factor_t * factors, ulong n, ulong start, ulong num_primes) Trial factor `n` with the first ``num_primes`` primes, but starting at the prime with index start (counting from zero). One requires an initialised ``n_factor_t`` structure, but factors will be added by default to an already used ``n_factor_t``. Use the function :func:`n_factor_init` defined in ``ulong_extras`` if initialisation has not already been completed on factors. Once completed, ``num`` will contain the number of distinct prime factors found. The field `p` is an array of ``ulong``\s containing the distinct prime factors, ``exp`` an array containing the corresponding exponents. The return value is the unfactored cofactor after trial factoring is done. The function calls :func:`n_compute_primes` automatically. See the documentation for that function regarding limits. The algorithm stops when the current prime has a square exceeding `n`, as no prime factor of `n` can exceed this unless `n` is prime. The precomputed inverses of all the primes computed by :func:`n_compute_primes` are utilised with the :func:`n_remove2_precomp` function. .. function:: ulong n_factor_trial(n_factor_t * factors, ulong n, ulong num_primes) This function calls :func:`n_factor_trial_range`, with the value of `0` for ``start``. By default this adds factors to an already existing ``n_factor_t`` or to a newly initialised one. .. function:: ulong n_factor_power235(ulong * exp, ulong n) Returns `0` if `n` is not a perfect square, cube or fifth power. Otherwise it returns the root and sets ``exp`` to either `2`, `3` or `5` appropriately. This function uses a series of modular tests to reject most non 235-powers. Each modular test returns a value from 0 to 7 whose bits respectively indicate whether the value is a square, cube or fifth power modulo the given modulus. When these are logically ``AND``-ed together, this gives a powerful test which will reject most non-235 powers. If a bit remains set indicating it may be a square, a standard square root test is performed. Similarly a cube root or fifth root can be taken, if indicated, to determine whether the power of that root is exactly equal to `n`. .. function:: ulong n_factor_one_line(ulong n, ulong iters) This implements Bill Hart's one line factoring algorithm [Har2012]_. It is a variant of Fermat's algorithm which cycles through a large number of multipliers instead of incrementing the square root. It is faster than SQUFOF for `n` less than about `2^{40}`. .. function:: ulong n_factor_lehman(ulong n) Lehman's factoring algorithm. Currently works up to `10^{16}`, but is not particularly efficient and so is not used in the general factor function. Always returns a factor of `n`. .. function:: ulong n_factor_SQUFOF(ulong n, ulong iters) Attempts to split `n` using the given number of iterations of SQUFOF. Simply set ``iters`` to ``WORD(0)`` for maximum persistence. The version of SQUFOF implemented here is as described by Gower and Wagstaff [GowWag2008]_. We start by trying SQUFOF directly on `n`. If that fails we multiply it by each of the primes in ``flint_primes_small`` in turn. As this multiplication may result in a two limb value we allow this in our implementation of SQUFOF. As SQUFOF works with values about half the size of `n` it only needs single limb arithmetic internally. If SQUFOF fails to factor `n` we return `0`, however with ``iters`` large enough this should never happen. .. function:: void n_factor(n_factor_t * factors, ulong n, int proved) Factors `n` with no restrictions on `n`. If the prime factors are required to be checked with a primality test, one may set ``proved`` to `1`, otherwise set it to `0`, and they will only be probable primes. NB: at the present there is no difference because the probable prime tests have been exhaustively tested up to `2^{64}`. However, in future, this flag may produce and separately check a primality certificate. This may be quite slow (and probably no less reliable in practice). For details on the ``n_factor_t`` structure, see :func:`n_factor_trial`. This function first tries trial factoring with a number of primes specified by the constant ``FLINT_FACTOR_TRIAL_PRIMES``. If the cofactor is `1` or prime the function returns with all the factors. Otherwise, the cofactor is placed in the array ``factor_arr``. Whilst there are factors remaining in there which have not been split, the algorithm continues. At each step each factor is first checked to determine if it is a perfect power. If so it is replaced by the power that has been found. Next if the factor is small enough and composite, in particular, less than ``FLINT_FACTOR_ONE_LINE_MAX`` then :func:`n_factor_one_line` is called with ``FLINT_FACTOR_ONE_LINE_ITERS`` to try and split the factor. If that fails or the factor is too large for :func:`n_factor_one_line` then :func:`n_factor_SQUFOF` is called, with ``FLINT_FACTOR_SQUFOF_ITERS``. If that fails an error results and the program aborts. However this should not happen in practice. .. function:: ulong n_factor_trial_partial(n_factor_t * factors, ulong n, ulong * prod, ulong num_primes, ulong limit) Attempts trial factoring of `n` with the first ``num_primes primes``, but stops when the product of prime factors so far exceeds ``limit``. One requires an initialised ``n_factor_t`` structure, but factors will be added by default to an already used ``n_factor_t``. Use the function :func:`n_factor_init` defined in ``ulong_extras`` if initialisation has not already been completed on ``factors``. Once completed, ``num`` will contain the number of distinct prime factors found. The field `p` is an array of ``ulong``\s containing the distinct prime factors, ``exp`` an array containing the corresponding exponents. The return value is the unfactored cofactor after trial factoring is done. The value ``prod`` will be set to the product of the factors found. The function calls :func:`n_compute_primes` automatically. See the documentation for that function regarding limits. The algorithm stops when the current prime has a square exceeding `n`, as no prime factor of `n` can exceed this unless `n` is prime. The precomputed inverses of all the primes computed by :func:`n_compute_primes` are utilised with the :func:`n_remove2_precomp` function. .. function:: ulong n_factor_partial(n_factor_t * factors, ulong n, ulong limit, int proved) Factors `n`, but stops when the product of prime factors so far exceeds ``limit``. One requires an initialised ``n_factor_t`` structure, but factors will be added by default to an already used ``n_factor_t``. Use the function ``n_factor_init()`` defined in ``ulong_extras`` if initialisation has not already been completed on ``factors``. On exit, ``num`` will contain the number of distinct prime factors found. The field `p` is an array of ``ulong``\s containing the distinct prime factors, ``exp`` an array containing the corresponding exponents. The return value is the unfactored cofactor after factoring is done. The factors are proved prime if ``proved`` is `1`, otherwise they are merely probably prime. .. function:: ulong n_factor_pp1(ulong n, ulong B1, ulong c) Factors `n` using Williams' `p + 1` factoring algorithm, with prime limit set to `B1`. We require `c` to be set to a random value. Each trial of the algorithm with a different value of `c` gives another chance to factor `n`, with roughly exponentially decreasing chance of finding a missing factor. If `p + 1` (or `p - 1`) is not smooth for any factor `p` of `n`, the algorithm will never succeed. The value `c` should be less than `n` and greater than `2`. If the algorithm succeeds, it returns the factor, otherwise it returns `0` or `1` (the trivial factors modulo `n`). .. function:: ulong n_factor_pp1_wrapper(ulong n) A simple wrapper around ``n_factor_pp1`` which works in the range `31`-`64` bits. Below this point, trial factoring will always succeed. This function mainly exists for ``n_factor`` and is tuned to minimise the time for ``n_factor`` on numbers that reach the ``n_factor_pp1`` stage, i.e. after trial factoring and one line factoring. .. function:: int n_factor_pollard_brent_single(mp_limb_t * factor, mp_limb_t n, mp_limb_t ninv, mp_limb_t ai, mp_limb_t xi, mp_limb_t normbits, mp_limb_t max_iters) Pollard Rho algorithm (with Brent modification) for integer factorization. Assumes that the `n` is not prime. `factor` is set as the factor if found. It is not assured that the factor found will be prime. Does not compute the complete factorization, just one factor. Returns 1 if factorization is successful (non trivial factor is found), else returns 0. Assumes `n` is normalized (shifted by normbits bits), and takes as input a precomputed inverse of `n` as computed by :func:`n_preinvert_limb`. `ai` and `xi` should also be shifted left by `normbits`. `ai` is the constant of the polynomial used, `xi` is the initial value. `max\_iters` is the number of iterations tried in process of finding the cycle. The algorithm used is a modification of the original Pollard Rho algorithm, suggested by Richard Brent in the paper, available at https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf .. function:: int n_factor_pollard_brent(mp_limb_t * factor, flint_rand_t state, mp_limb_t n_in, mp_limb_t max_tries, mp_limb_t max_iters) Pollard Rho algorithm, modified as suggested by Richard Brent. Makes a call to :func:`n_factor_pollard_brent_single`. The input parameters ai and xi for :func:`n_factor_pollard_brent_single` are selected at random. If the algorithm fails to find a non trivial factor in one call, it tries again (this time with a different set of random values). This process is repeated a maximum of `max\_tries` times. Assumes `n` is not prime. `factor` is set as the factor found, if factorization is successful. In such a case, 1 is returned. Otherwise, 0 is returned. Factor discovered is not necessarily prime. Arithmetic functions -------------------------------------------------------------------------------- .. function:: int n_moebius_mu(ulong n) Computes the Moebius function `\mu(n)`, which is defined as `\mu(n) = 0` if `n` has a prime factor of multiplicity greater than `1`, `\mu(n) = -1` if `n` has an odd number of distinct prime factors, and `\mu(n) = 1` if `n` has an even number of distinct prime factors. By convention, `\mu(0) = 0`. For even numbers, we use the identities `\mu(4n) = 0` and `\mu(2n) = - \mu(n)`. Odd numbers up to a cutoff are then looked up from a precomputed table storing `\mu(n) + 1` in groups of two bits. For larger `n`, we first check if `n` is divisible by a small odd square and otherwise call ``n_factor()`` and count the factors. .. function:: void n_moebius_mu_vec(int * mu, ulong len) Computes `\mu(n)` for ``n = 0, 1, ..., len - 1``. This is done by sieving over each prime in the range, flipping the sign of `\mu(n)` for every multiple of a prime `p` and setting `\mu(n) = 0` for every multiple of `p^2`. .. function:: int n_is_squarefree(ulong n) Returns `0` if `n` is divisible by some perfect square, and `1` otherwise. This simply amounts to testing whether `\mu(n) \neq 0`. As special cases, `1` is considered squarefree and `0` is not considered squarefree. .. function:: ulong n_euler_phi(ulong n) Computes the Euler totient function `\phi(n)`, counting the number of positive integers less than or equal to `n` that are coprime to `n`. Factorials -------------------------------------------------------------------------------- .. function:: ulong n_factorial_fast_mod2_preinv(ulong n, ulong p, ulong pinv) Returns `n! \bmod p` given a precomputed inverse of `p` as computed by :func:`n_preinvert_limb`. `p` is not required to be a prime, but no special optimisations are made for composite `p`. Uses fast multipoint evaluation, running in about `O(n^{1/2})` time. .. function:: ulong n_factorial_mod2_preinv(ulong n, ulong p, ulong pinv) Returns `n! \bmod p` given a precomputed inverse of `p` as computed by :func:`n_preinvert_limb`. `p` is not required to be a prime, but no special optimisations are made for composite `p`. Uses a lookup table for small `n`, otherwise computes the product if `n` is not too large, and calls the fast algorithm for extremely large `n`. Primitive Roots and Discrete Logarithms -------------------------------------------------------------------------------- .. function:: ulong n_primitive_root_prime_prefactor(ulong p, n_factor_t * factors) Returns a primitive root for the multiplicative subgroup of `\mathbb{Z}/p\mathbb{Z}` where `p` is prime given the factorisation (``factors``) of `p - 1`. .. function:: ulong n_primitive_root_prime(ulong p) Returns a primitive root for the multiplicative subgroup of `\mathbb{Z}/p\mathbb{Z}` where `p` is prime. .. function:: ulong n_discrete_log_bsgs(ulong b, ulong a, ulong n) Returns the discrete logarithm of `b` with respect to `a` in the multiplicative subgroup of `\mathbb{Z}/n\mathbb{Z}` when `\mathbb{Z}/n\mathbb{Z}` is cyclic. That is, it returns a number `x` such that `a^x = b \bmod n`. The multiplicative subgroup is only cyclic when `n` is `2`, `4`, `p^k`, or `2p^k` where `p` is an odd prime and `k` is a positive integer. Elliptic curve method for factorization of ``mp_limb_t`` -------------------------------------------------------------------------------- .. function:: void n_factor_ecm_double(mp_limb_t * x, mp_limb_t * z, mp_limb_t x0, mp_limb_t z0, mp_limb_t n, n_ecm_t n_ecm_inf) Sets the point `(x : z)` to two times `(x_0 : z_0)` modulo `n` according to the formula `x = (x_0 + z_0)^2 \cdot (x_0 - z_0)^2 \mod n,` `z = 4 x_0 z_0 \left((x_0 - z_0)^2 + 4a_{24}x_0z_0\right) \mod n.` This group doubling is valid only for points expressed in Montgomery projective coordinates. .. function:: void n_factor_ecm_add(mp_limb_t * x, mp_limb_t * z, mp_limb_t x1, mp_limb_t z1, mp_limb_t x2, mp_limb_t z2, mp_limb_t x0, mp_limb_t z0, mp_limb_t n, n_ecm_t n_ecm_inf) Sets the point `(x : z)` to the sum of `(x_1 : z_1)` and `(x_2 : z_2)` modulo `n`, given the difference `(x_0 : z_0)` according to the formula This group doubling is valid only for points expressed in Montgomery projective coordinates. .. function:: void n_factor_ecm_mul_montgomery_ladder(mp_limb_t * x, mp_limb_t * z, mp_limb_t x0, mp_limb_t z0, mp_limb_t k, mp_limb_t n, n_ecm_t n_ecm_inf) Montgomery ladder algorithm for scalar multiplication of elliptic points. Sets the point `(x : z)` to `k(x_0 : z_0)` modulo `n`. Valid only for points expressed in Montgomery projective coordinates. .. function:: int n_factor_ecm_select_curve(mp_limb_t * f, mp_limb_t sigma, mp_limb_t n, n_ecm_t n_ecm_inf) Selects a random elliptic curve given a random integer ``sigma``, according to Suyama's parameterization. If the factor is found while selecting the curve, `1` is returned. In case the curve found is not suitable, `0` is returned. Also selects the initial point `x_0`, and the value of `(a + 2)/4`, where `a` is a curve parameter. Sets `z_0` as `1` (shifted left by ``n_ecm_inf->normbits``). All these are stored in the ``n_ecm_t`` struct. The curve selected is of Montgomery form, the points selected satisfy the curve and are projective coordinates. .. function:: int n_factor_ecm_stage_I(mp_limb_t * f, const mp_limb_t * prime_array, mp_limb_t num, mp_limb_t B1, mp_limb_t n, n_ecm_t n_ecm_inf) Stage I implementation of the ECM algorithm. ``f`` is set as the factor if found. ``num`` is number of prime numbers `<=` the bound ``B1``. ``prime_array`` is an array of first ``B1`` primes. `n` is the number being factored. If the factor is found, `1` is returned, otherwise `0`. .. function:: int n_factor_ecm_stage_II(mp_limb_t * f, mp_limb_t B1, mp_limb_t B2, mp_limb_t P, mp_limb_t n, n_ecm_t n_ecm_inf) Stage II implementation of the ECM algorithm. ``f`` is set as the factor if found. ``B1``, ``B2`` are the two bounds. ``P`` is the primorial (approximately equal to `\sqrt{B2}`). `n` is the number being factored. If the factor is found, `1` is returned, otherwise `0`. .. function:: int n_factor_ecm(mp_limb_t * f, mp_limb_t curves, mp_limb_t B1, mp_limb_t B2, flint_rand_t state, mp_limb_t n) Outer wrapper function for the ECM algorithm. It factors `n` which must fit into a ``mp_limb_t``. The function calls stage I and II, and the precomputations (builds ``prime_array`` for stage I, ``GCD_table`` and ``prime_table`` for stage II). ``f`` is set as the factor if found. ``curves`` is the number of random curves being tried. ``B1``, ``B2`` are the two bounds or stage I and stage II. `n` is the number being factored. If a factor is found in stage I, `1` is returned. If a factor is found in stage II, `2` is returned. If a factor is found while selecting the curve, `-1` is returned. Otherwise `0` is returned. flint-3.1.3/doc/source/using.rst000066400000000000000000000551441461254215100165700ustar00rootroot00000000000000.. _using: Using ball arithmetic =============================================================================== This section gives an introduction to working with real numbers in Arb (see :ref:`arb` for the API and technical documentation). The general principles carry over to complex numbers, polynomials and matrices. Ball semantics ------------------------------------------------------------------------------- Let `f : A \to B` be a function. A ball implementation of `f` is a function `F` that maps sets `X \subseteq A` to sets `F(X) \subseteq B` subject to the following rule: For all `x \in X`, we have `f(x) \in F(X)`. In other words, `F(X)` is an *enclosure* for the set `\{f(x) : x \in X\}`. This rule is sometimes called the *inclusion principle*. Throughout the documentation (except where otherwise noted), we will simply write `f(x)` instead of `F(X)` when describing ball implementations of pointwise-defined mathematical functions, understanding that the input is a set of point values and that the output is an enclosure. General subsets of `\mathbb{R}` are not possible to represent on a computer. Instead, we work with subsets of the form `[m \pm r] = [m-r, m+r]` where the midpoint *m* and radius *r* are binary floating-point numbers, i.e. numbers of the form `u 2^v` with `u, v \in \mathbb{Z}` (to make this scheme complete, we also need to adjoin the special floating-point values `-\infty`, `+\infty` and `\operatorname{NaN}`). Given a ball `[m \pm r]` with `m \in \mathbb{R}` (not necessarily a floating-point number), we can always round *m* to a nearby floating-point number that has at most most *prec* bits in the component *u*, and add an upper bound for the rounding error to *r*. In Arb, ball functions that take a *prec* argument as input (e.g. :func:`arb_add`) always round their output to *prec* bits. Some functions are always exact (e.g. :func:`arb_neg`), and thus do not take a *prec* argument. The programming interface resembles that of GMP. Each :type:`arb_t` variable must be initialized with :func:`arb_init` before use (this also sets its value to zero), and deallocated with :func:`arb_clear` after use. Variables have pass-by-reference semantics. In the list of arguments to a function, output variables come first, followed by input variables, and finally the precision: .. code-block:: c #include "arb.h" int main() { arb_t x, y; arb_init(x); arb_init(y); arb_set_ui(x, 3); /* x = 3 */ arb_const_pi(y, 128); /* y = pi, to 128 bits */ arb_sub(y, y, x, 53); /* y = y - x, to 53 bits */ arb_clear(x); arb_clear(y); } Binary and decimal ------------------------------------------------------------------------------- While the internal representation uses binary floating-point numbers, it is usually preferable to print numbers in decimal. The binary-to-decimal conversion generally requires rounding. Three different methods are available for printing a number to standard output: * :func:`arb_print` shows the exact internal representation of a ball, with binary exponents. * :func:`arb_printd` shows an inexact view of the internal representation, approximated by decimal floating-point numbers. * :func:`arb_printn` shows a *decimal ball* that is guaranteed to be an enclosure of the binary floating-point ball. By default, it only prints digits in the midpoint that are certain to be correct, up to an error of at most one unit in the last place. Converting from binary to decimal is generally inexact, and the output of this method takes this rounding into account when printing the radius. This snippet computes a 53-bit enclosure of `\pi` and prints it in three ways: .. code-block:: c arb_const_pi(x, 53); arb_print(x); printf("\n"); arb_printd(x, 20); printf("\n"); arb_printn(x, 20, 0); printf("\n"); The output is: .. code-block:: text (884279719003555 * 2^-48) +/- (536870913 * 2^-80) 3.141592653589793116 +/- 4.4409e-16 [3.141592653589793 +/- 5.61e-16] The :func:`arb_get_str` and :func:`arb_set_str` methods are useful for converting rigorously between decimal strings and binary balls (:func:`arb_get_str` produces the same string as :func:`arb_printn`, and :func:`arb_set_str` can parse such strings back). A potential mistake is to create a ball from a ``double`` constant such as ``2.3``, when this actually represents ``2.29999999999999982236431605997495353221893310546875``. To produce a ball containing the rational number `23/10`, one of the following can be used: .. code-block:: c arb_set_str(x, "2.3", prec) arb_set_ui(x, 23); arb_div_ui(x, x, 10, prec) fmpq_set_si(q, 23, 10); /* q is a FLINT fmpq_t */ arb_set_fmpq(x, q, prec); Quality of enclosures ------------------------------------------------------------------------------- The main problem when working with ball arithmetic (or interval arithmetic) is *overestimation*. In general, the enclosure of a value or set of values as computed with ball arithmetic will be larger than the smallest possible enclosure. Overestimation results naturally from rounding errors and cancellations in the individual steps of a calculation. As a general principle, formula rewriting techniques that make floating-point code more numerically stable also make ball arithmetic code more numerically stable, in the sense of producing tighter enclosures. As a result of the *dependency problem*, ball or interval arithmetic can produce error bounds that are much larger than the actual numerical errors resulting from doing floating-point arithmetic. Consider the expression `(x + 1) - x` as an example. When evaluated in floating-point arithmetic, `x` may have a large initial error. However, that error will cancel itself out in the subtraction, so that the result equals 1 (except perhaps for a small rounding error left from the operation `x + 1`). In ball arithmetic, dependent errors add up instead of cancelling out. If `x = [3 \pm 0.1]`, the result will be `[1 \pm 0.2]`, where the error bound has doubled. In unfavorable circumstances, error bounds can grow exponentially with the number of steps. If all inputs to a calculation are "point values", i.e. exact numbers and known mathematical constants that can be approximated arbitrarily closely (such as `\pi`), then an error of order `2^n` can typically be overcome by working with *n* extra bits of precision, increasing the computation time by an amount that is polynomial in *n*. In certain situations, however, overestimation leads to exponential slowdown or even failure of an algorithm to converge. For example, root-finding algorithms that refine the result iteratively may fail to converge in ball arithmetic, even if they do converge in plain floating-point arithmetic. Therefore, ball arithmetic is not a silver bullet: there will always be situations where some amount of numerical or mathematical analysis is required. Some experimentation may be required to find whether (and how) it can be used effectively for a given problem. Predicates ------------------------------------------------------------------------------- A ball implementation of a predicate `f : \mathbb{R} \to \{\operatorname{True}, \operatorname{False}\}` would need to be able to return a third logical value indicating that the result could be either True or False. In most cases, predicates in Arb are implemented as functions that return the *int* value 1 to indicate that the result certainly is True, and the *int* value 0 to indicate that the result could be either True or False. To test whether a predicate certainly is False, the user must test whether the negated predicate certainly is True. For example, the following code would *not* be correct in general: .. code-block:: c if (arb_is_positive(x)) { ... /* do things assuming that x > 0 */ } else { ... /* do things assuming that x <= 0 */ } Instead, the following can be used: .. code-block:: c if (arb_is_positive(x)) { ... /* do things assuming that x > 0 */ } else if (arb_is_nonpositive(x)) { ... /* do things assuming that x <= 0 */ } else { ... /* do things assuming that the sign of x is unknown */ } Likewise, we will write `x \le y` in mathematical notation with the meaning that `x \le y` holds for all `x \in X, y \in Y` where `X` and `Y` are balls. Note that some predicates such as :func:`arb_overlaps` and :func:`arb_contains` actually are predicates on balls viewed as sets, and not ball implementations of pointwise predicates. Some predicates are also complementary. For example :func:`arb_contains_zero` tests whether the input ball contains the point zero. Negated, it is equivalent to :func:`arb_is_nonzero`, and complementary to :func:`arb_is_zero` as a pointwise predicate: .. code-block:: c if (arb_is_zero(x)) { ... /* do things assuming that x = 0 */ } #if 1 else if (arb_is_nonzero(x)) #else else if (!arb_contains_zero(x)) /* equivalent */ #endif { ... /* do things assuming that x != 0 */ } else { ... /* do things assuming that the sign of x is unknown */ } A worked example: the sine function ------------------------------------------------------------------------------- We implement the function `\sin(x)` naively using the Taylor series `\sum_{k=0}^{\infty} (-1)^k x^{2k+1} / (2k+1)!` and :type:`arb_t` arithmetic. Since there are infinitely many terms, we need to split the series in two parts: a finite sum that can be evaluated directly, and a tail that has to be bounded. We stop as soon as we reach a term `t` bounded by `|t| \le 2^{-prec} < 1`. The terms are alternating and must have decreasing magnitude from that point, so the tail of the series is bounded by `|t|`. We add this magnitude to the radius of the output. Since ball arithmetic automatically bounds the numerical errors resulting from all arithmetic operations, the output *res* is a ball guaranteed to contain `\sin(x)`. .. code-block:: c #include "arb.h" void arb_sin_naive(arb_t res, const arb_t x, slong prec) { arb_t s, t, u, tol; slong k; arb_init(s); arb_init(t); arb_init(u); arb_init(tol); arb_one(tol); arb_mul_2exp_si(tol, tol, -prec); /* tol = 2^-prec */ for (k = 0; ; k++) { arb_pow_ui(t, x, 2 * k + 1, prec); arb_fac_ui(u, 2 * k + 1, prec); arb_div(t, t, u, prec); /* t = x^(2k+1) / (2k+1)! */ arb_abs(u, t); if (arb_le(u, tol)) /* if |t| <= 2^-prec */ { arb_add_error(s, u); /* add |t| to the radius and stop */ break; } if (k % 2 == 0) arb_add(s, s, t, prec); else arb_sub(s, s, t, prec); } arb_set(res, s); arb_clear(s); arb_clear(t); arb_clear(u); arb_clear(tol); } This algorithm is naive, because the Taylor series is slow to converge and suffers from catastrophic cancellation when `|x|` is large (we could also improve the efficiency of the code slightly by computing the terms using recurrence relations instead of computing `x^k` and `k!` from scratch each iteration). As a test, we compute `\sin(2016.1)`. The largest term in the Taylor series for `\sin(x)` reaches a magnitude of about `x^x / x!`, or about `10^{873}` in this case. Therefore, we need over 873 digits (about 3000 bits) of precision to overcome the catastrophic cancellation and determine the result with sufficient accuracy to tell whether it is positive or negative. .. code-block:: c int main() { arb_t x, y; slong prec; arb_init(x); arb_init(y); for (prec = 64; ; prec *= 2) { arb_set_str(x, "2016.1", prec); arb_sin_naive(y, x, prec); printf("Using %5ld bits, sin(x) = ", prec); arb_printn(y, 10, 0); printf("\n"); if (!arb_contains_zero(y)) /* stopping condition */ break; } arb_clear(x); arb_clear(y); } The program produces the following output: .. code-block:: text Using 64 bits, sin(x) = [+/- 2.67e+859] Using 128 bits, sin(x) = [+/- 1.30e+840] Using 256 bits, sin(x) = [+/- 3.60e+801] Using 512 bits, sin(x) = [+/- 3.01e+724] Using 1024 bits, sin(x) = [+/- 2.18e+570] Using 2048 bits, sin(x) = [+/- 1.22e+262] Using 4096 bits, sin(x) = [-0.7190842207 +/- 1.20e-11] As an exercise, the reader may improve the naive algorithm by making it subtract a well-chosen multiple of `2 \pi` from `x` before invoking the Taylor series (hint: use :func:`arb_const_pi`, :func:`arb_div` and :func:`arf_get_fmpz`). If done correctly, 64 bits of precision should be more than enough to compute `\sin(2016.1)`, and with minor adjustments to the code, the user should be able to compute `\sin(\exp(2016.1))` quite easily as well. This example illustrates how ball arithmetic can be used to perform nontrivial calculations. To evaluate an infinite series, the user needs to know how to bound the tail of the series, but everything else is automatic. When evaluating a finite formula that can be expressed completely using built-in functions, all error bounding is automatic from the point of view of the user. In particular, the :func:`arb_sin` method should be used to compute the sine of a real number; it uses a much more efficient algorithm than the naive code above. This example also illustrates the "guess-and-verify" paradigm: instead of determining *a priori* the floating-point precision necessary to get a correct result, we *guess* some initial precision, use ball arithmetic to *verify* that the result is accurate enough, and restart with higher precision (or signal failure) if it is not. If we think of rounding errors as essentially random processes, then a floating-point computation is analogous to a *Monte Carlo algorithm*. Using ball arithmetic to get a verified result effectively turns it into the analog of a *Las Vegas algorithm*, which is a randomized algorithm that always gives a correct result if it terminates, but may fail to terminate (alternatively, instead of actually looping forever, it might signal failure after a certain number of iterations). The loop will fail to terminate if we attempt to determine the sign of `\sin(\pi)`: .. code-block:: text Using 64 bits, sin(x) = [+/- 3.96e-18] Using 128 bits, sin(x) = [+/- 2.17e-37] Using 256 bits, sin(x) = [+/- 6.10e-76] Using 512 bits, sin(x) = [+/- 5.13e-153] Using 1024 bits, sin(x) = [+/- 4.01e-307] Using 2048 bits, sin(x) = [+/- 2.13e-615] Using 4096 bits, sin(x) = [+/- 6.85e-1232] Using 8192 bits, sin(x) = [+/- 6.46e-2465] Using 16384 bits, sin(x) = [+/- 5.09e-4931] Using 32768 bits, sin(x) = [+/- 5.41e-9863] ... The sign of a nonzero real number can be decided by computing it to sufficiently high accuracy, but the sign of an expression that is exactly equal to zero cannot be decided by a numerical computation unless the entire computation happens to be exact (in this example, we could use the :func:`arb_sin_pi` function which computes `\sin(\pi x)` in one step, with the input `x = 1`). It is up to the user to implement a stopping criterion appropriate for the circumstances of a given application. For example, breaking when it is clear that `|\sin(x)| < 10^{-10000}` would allow the program to terminate and convey some meaningful information about the input `x = \pi`, though this would not constitute a mathematical proof that `\sin(\pi) = 0`. More on precision and accuracy ------------------------------------------------------------------------------- The relation between the working precision and the accuracy of the output is not always easy predict. The following remarks might help to choose *prec* optimally. For a ball `[m \pm r]` it is convenient to define the following notions: * Absolute error: `e_{abs} = |r|` * Relative error: `e_{rel} = |r| / \max(0, |m| - |r|)` (or `e_{rel} = 0` if `r = m = 0`) * Absolute accuracy: `a_{abs} = 1 / e_{abs}` * Relative accuracy: `a_{rel} = 1 / e_{rel}` Expressed in bits, one takes the corresponding `\log_2` values. Of course, if `x` is the exact value being approximated, then the "absolute error" so defined is an upper bound for the actual absolute error `|x-m|` and "absolute accuracy" a lower bound for `1/|x-m|`, etc. The *prec* argument in Arb should be thought of as controlling the working precision. Generically, when evaluating a fixed expression (that is, when the sequence of operations does not depend on the precision), the absolute or relative error will be bounded by .. math:: 2^{O(1) - prec} where the `O(1)` term depends on the expression and implementation details of the ball functions used to evaluate it. Accordingly, for an accuracy of *p* bits, we need to use a working precision `O(1) + p`. If the expression is numerically well-behaved, then the `O(1)` term will be small, which leads to the heuristic of "adding a few guard bits" (for most basic calculations, 10 or 20 guard bits is enough). If the `O(1)` term is unknown, then increasing the number of guard bits in exponential steps until the result is accurate enough is generally a good heuristic. Sometimes, a partially accurate result can be used to estimate the `O(1)` term. For example, if the goal is to achieve 100 bits of accuracy and a precision of 120 bits yields 80 bits of accuracy, then it is plausible that a precision of just over 140 bits yields 100 bits of accuracy. Built-in functions in Arb can roughly be characterized as belonging to one of two extremes (though there is actually a spectrum): * Simple operations, including basic arithmetic operations and many elementary functions. In most cases, for an input `x = [m \pm r]`, `f(x)` is evaluated by computing `f(m)` and then separately bounding the *propagated error* `|f(m) - f(m + \varepsilon)|, |\varepsilon| \le r`. The working precision is automatically increased internally so that `f(m)` is computed to *prec* bits of relative accuracy with an error of at most a few units in the last place (perhaps with rare exceptions). The propagated error can generally be bounded quite tightly as well (see :ref:`general_formulas`). As a result, the enclosure will be close to the best possible at the given precision, and the user can estimate the precision to use accordingly. * Complex operations, such as certain higher transcendental functions (for example, the Riemann zeta function). The function is evaluated by performing a sequence of simpler operations, each using ball arithmetic with a working precision of roughly *prec* bits. The sequence of operations might depend on *prec*; for example, an infinite series might be truncated so that the remainder is smaller than `2^{-prec}`. The final result can be far from tight, and it is not guaranteed that the error converges to zero as `prec \to \infty`, though in practice, it should do so in most cases. In short, the *inclusion principle* is the fundamental contract in Arb. Enclosures computed by built-in functions may or may not be tight enough to be useful, but the hope is that they will be sufficient for most purposes. Tightening the error bounds for more complex operations is a long term optimization goal, which in many cases will require a fair amount of research. A tradeoff also has to be made for efficiency: tighter error bounds allow the user to work with a lower precision, but they may also be much more expensive to compute. Polynomial time guarantee ------------------------------------------------------------------------------- Arb provides a soft guarantee that the time used to evaluate a ball function will depend polynomially on *prec* and the bit size of the input, uniformly regardless of the numerical value of the input. The idea behind this soft guarantee is to allow Arb to be used as a black box to evaluate expressions numerically without potentially slowing down, hanging indefinitely or crashing because of "bad" input such as nested exponentials. By controlling the precision, the user can cancel a computation before it uses up an unreasonable amount of resources, without having to rely on other timeout or exception mechanisms. A result that is feasible but very expensive to compute can still be forced by setting the precision high enough. As motivation, consider evaluating `\sin(x)` or `\exp(x)` with the exact floating-point number `x = 2^{2^n}` as input. The time and space required to compute an accurate floating-point approximation of `\sin(x)` or `\exp(x)` increases as `2^n`, in the first case because because of the need to subtract an accurate multiple of `2\pi` and in the second case due to the size of the output exponent and the internal subtraction of an accurate multiple of `\log(2)`. This is despite the fact that the size of `x` as an object in memory only increases linearly with `n`. Already `n = 33` would require at least 1 GB of memory, and `n = 100` would be physically impossible to process. For functions that are computed by direct use of power series expansions, e.g. `f(x) = \sum_{k=0}^{\infty} c_k x^k`, without having fast argument-reduction techniques like those for elementary functions, the time would be exponential in `n` already when `x = 2^n`. Therefore, Arb caps internal work parameters (the internal working precision, the number terms of an infinite series to add, etc.) by polynomial, usually linear, functions of *prec*. When the limit is exceeded, the output is set to a crude bound. For example, if `x` is too large, :func:`arb_sin` will simply return `[\pm 1]`, and :func:`arb_exp` will simply return `[\pm \infty]` if `x` is positive or `[\pm 2^{-m}]` if `x` is negative. This is not just a failsafe, but occasionally a useful optimization. It is not entirely uncommon to have formulas where one term is modest and another term decreases exponentially, such as: .. math:: \log(x) + \sin(x) \exp(-x). For example, the reflection formula of the digamma function has a similar structure. When `x` is large, the right term would be expensive to compute to high relative accuracy. Doing so is unnecessary, however, since a crude bound of `[\pm 1] \cdot [\pm 2^{-m}]` is enough to evaluate the expression as a whole accurately. The polynomial time guarantee is "soft" in that there are a few exceptions. For example, the complexity of computing the Riemann zeta function `\zeta(\sigma+it)` increases linearly with the imaginary height `|t|` in the current implementation, and all known algorithms have a complexity of `|t|^{\alpha}` where the best known value for `\alpha` is about `0.3`. Input with large `|t|` is most likely to be given deliberately by users with the explicit intent of evaluating the zeta function itself, so the evaluation is not cut off automatically. flint-3.1.3/examples/000077500000000000000000000000001461254215100144515ustar00rootroot00000000000000flint-3.1.3/examples/bernoulli.c000066400000000000000000000015501461254215100166110ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "fmpq.h" #include "arb.h" #include "bernoulli.h" #include "profiler.h" int main(int argc, char *argv[]) { fmpq_t x; slong i, num_threads; ulong n; if (argc < 2) { flint_printf("usage: build/examples/bernoulli n [-threads n]\n"); return 1; } n = atol(argv[1]); num_threads = 1; for (i = 2; i < argc; i++) { if (!strcmp(argv[i], "-threads")) num_threads = atol(argv[i+1]); } flint_set_num_threads(num_threads); fmpq_init(x); TIMEIT_ONCE_START bernoulli_fmpq_ui(x, n); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE if (n <= 100) { fmpq_print(x); flint_printf("\n"); } fmpq_clear(x); flint_cleanup_master(); return 0; } flint-3.1.3/examples/binet.c000066400000000000000000000022641461254215100157220ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include "profiler.h" #include "ca.h" int main(int argc, char *argv[]) { ca_ctx_t ctx; ca_t sqrt5, phi, psi, t, u; fmpz_t n; if (argc < 2) { flint_printf("usage: build/examples/binet [-limit B] n\n"); return 1; } fmpz_init(n); fmpz_set_str(n, argv[argc-1], 10); TIMEIT_ONCE_START ca_ctx_init(ctx); if (argc == 4) ctx->options[CA_OPT_PREC_LIMIT] = atol(argv[2]); ca_init(sqrt5, ctx); ca_init(phi, ctx); ca_init(psi, ctx); ca_init(t, ctx); ca_init(u, ctx); ca_sqrt_ui(sqrt5, 5, ctx); ca_add_ui(phi, sqrt5, 1, ctx); ca_div_ui(phi, phi, 2, ctx); ca_ui_sub(psi, 1, phi, ctx); ca_pow_fmpz(t, phi, n, ctx); ca_pow_fmpz(u, psi, n, ctx); ca_sub(t, t, u, ctx); ca_div(t, t, sqrt5, ctx); ca_print(t, ctx); flint_printf("\n"); ca_clear(sqrt5, ctx); ca_clear(phi, ctx); ca_clear(psi, ctx); ca_clear(t, ctx); ca_clear(u, ctx); ca_ctx_clear(ctx); fmpz_clear(n); flint_printf("\n"); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE flint_cleanup(); return 0; } flint-3.1.3/examples/class_poly.c000066400000000000000000000020531461254215100167650ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "arb.h" #include "acb_modular.h" #include "fmpz_poly.h" #include "profiler.h" int main(int argc, char *argv[]) { fmpz_poly_t res; slong i, num_threads; slong D; if (argc < 2) { flint_printf("usage: build/examples/class_poly D [-threads n]\n"); return 1; } D = atol(argv[1]); num_threads = 1; for (i = 2; i < argc; i++) { if (!strcmp(argv[i], "-threads")) num_threads = atol(argv[i+1]); } flint_set_num_threads(num_threads); fmpz_poly_init(res); TIMEIT_ONCE_START acb_modular_hilbert_class_poly(res, D); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE if (FLINT_ABS(D) <= 100) { fmpz_poly_print(res); flint_printf("\n"); } else { flint_printf("degree = %wd, bits = %wd\n", fmpz_poly_degree(res), fmpz_poly_max_bits(res)); } fmpz_poly_clear(res); flint_cleanup_master(); return 0; } flint-3.1.3/examples/complex_plot.c000066400000000000000000000433471461254215100173350ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include #include "acb.h" #include "acb_hypgeom.h" #include "acb_modular.h" #include "acb_elliptic.h" #include "acb_mat.h" #include "acb_theta.h" #include "profiler.h" #include "thread_support.h" /* some useful color operations */ #define CLAMP(y) FLINT_MAX(0.0, FLINT_MIN((y), 1.0)) #define BLEND(x,y) (0.5*(x) + 0.5*(y)) #define DODGE(a,b) ((a) / ((1.0 - (b)) + 1/256.0)) /* HLS algorithm from python's colorsys module */ static double vv(double m1, double m2, double hue) { hue = hue - floor(hue); if (hue < 1/6.) return m1 + (m2-m1)*hue*6.0; if (hue < 0.5) return m2; if (hue < 2/3.) return m1 + (m2-m1)*(2/3.-hue)*6.0; return m1; } static void hls_to_rgb(double *R, double *G, double *B, double h, double l, double s) { double m1, m2; if (s == 0.0) { *R = *G = *B = l; return; } if (l <= 0.5) m2 = l * (1.0+s); else m2 = l+s-(l*s); m1 = 2.0*l - m2; *R = vv(m1, m2, h + 1/3.); *G = vv(m1, m2, h); *B = vv(m1, m2, h - 1/3.); } static void rgb_to_hls(double *H, double *L, double *S, double R, double G, double B) { double h, l, s, hi, lo, d; hi = FLINT_MAX(FLINT_MAX(R, G), B); lo = FLINT_MIN(FLINT_MIN(R, G), B); l = 0.5 * (lo + hi); d = hi - lo; if (hi == lo) { s = 0.0; h = 0.0; } else { if (l <= 0.5) s = d / (hi + lo); else s = d / (2.0 - hi - lo); if (d == 0.0) d = 1.0; if (R == hi) h = (G - B) / d; else if (G == hi) h = (B - R) / d + 2.0; else h = (R - G) / d + 4.0; h = h / 6.0; if (h < 0.0) h += 1.0; } *H = h; *L = l; *S = s; } /* color balance algorithm from gimp */ static double balance_channel(double value, double l, double shadows, double midtones, double highlights) { double a = 0.25, b = 0.333, scale = 0.7; shadows *= CLAMP((l - b) / (-a) + 0.5) * scale; midtones *= CLAMP((l - b) / ( a) + 0.5) * CLAMP((l + b - 1.0) / (-a) + 0.5) * scale; highlights *= CLAMP((l + b - 1.0) / ( a) + 0.5) * scale; value += shadows; value += midtones; value += highlights; return CLAMP(value); } static void balance(double * R, double * G, double * B, double ra, double rb, double rc, /* red shadows, midtones, highlights */ double ga, double gb, double gc, /* green */ double ba, double bb, double bc) /* blue */ { double h, l, s; double h2, l2, s2; rgb_to_hls(&h, &l, &s, *R, *G, *B); *R = balance_channel(*R, *R, ra, rb, rc); *G = balance_channel(*G, *G, ga, gb, gc); *B = balance_channel(*B, *B, ba, bb, bc); /* preserve lightness */ rgb_to_hls(&h2, &l2, &s2, *R, *G, *B); hls_to_rgb(R, G, B, h2, l, s2); } #define PI 3.1415926535898 const double blue_orange_colors[][4] = { {-1.0, 0.0, 0.0, 0.0}, {-0.95, 0.1, 0.2, 0.5}, {-0.5, 0.0, 0.5, 1.0}, {-0.05, 0.4, 0.8, 0.8}, { 0.0, 1.0, 1.0, 1.0}, { 0.05, 1.0, 0.9, 0.3}, { 0.5, 0.9, 0.5, 0.0}, { 0.95, 0.7, 0.1, 0.0}, { 1.0, 0.0, 0.0, 0.0}, { 2.0, 0.0, 0.0, 0.0}, }; void color_function(double * R, double * G, double * B, const acb_t z, int mode) { double H, L, S; slong prec, i; arb_t t, u; if (!acb_is_finite(z) || acb_rel_accuracy_bits(z) < 4) { *R = *G = *B = 0.5; return; } if (mode >= 2) { double R1, G1, B1; double R2, G2, B2; /* combine both color functions */ color_function(&R1, &G1, &B1, z, 0); color_function(&R2, &G2, &B2, z, 1); *R = BLEND(R1, CLAMP(DODGE(R1, R2))); *G = BLEND(G1, CLAMP(DODGE(G1, G2))); *B = BLEND(B1, CLAMP(DODGE(B1, B2))); /* then play with the levels */ if (mode == 3) balance(R, G, B, 0.0, -0.5, 0.2, 0.0, 0.0, -0.1, 0.0, -1.0, -0.2); else if (mode == 4) balance(R, G, B, 0.0, -0.5, 0.2, 0.0, 0.5, -0.1, 0.0, -0.3, -1.0); else if (mode == 5) balance(R, G, B, 0.0, -0.5, -1.0, 0.0, -0.1, -0.67, 0.0, -0.55, -0.12); else if (mode == 6) balance(R, G, B, 0.86, 0.0, 0.13, 0.57, 0.19, -0.52, 0.31, -0.30, -0.94); return; } arb_init(t); arb_init(u); prec = 32; arf_set_round(arb_midref(t), arb_midref(acb_realref(z)), prec, ARF_RND_DOWN); arf_set_round(arb_midref(u), arb_midref(acb_imagref(z)), prec, ARF_RND_DOWN); arb_atan2(t, u, t, prec); H = arf_get_d(arb_midref(t), ARF_RND_DOWN); if (mode == 0) { H = (H + PI) / (2 * PI) + 0.5; H = H - floor(H); acb_abs(t, z, prec); if (arf_cmpabs_2exp_si(arb_midref(t), 200) > 0) { L = 1.0; } else if (arf_cmpabs_2exp_si(arb_midref(t), -200) < 0) { L = 0.0; } else { L = arf_get_d(arb_midref(t), ARF_RND_DOWN); L = 1.0 - 1.0/(1.0 + pow(L, 0.2)); } S = 0.8; hls_to_rgb(R, G, B, H, L, S); } else { H = H / PI; H = FLINT_MAX(FLINT_MIN(H, 1.0), -1.0); for (i = 1; ; i++) { if (blue_orange_colors[i][0] > H) { double a, ra, ga, ba, b, rb, gb, bb, s; a = blue_orange_colors[i-1][0]; ra = blue_orange_colors[i-1][1]; ga = blue_orange_colors[i-1][2]; ba = blue_orange_colors[i-1][3]; b = blue_orange_colors[i][0]; rb = blue_orange_colors[i][1]; gb = blue_orange_colors[i][2]; bb = blue_orange_colors[i][3]; s = (H - a) / (b - a); *R = ra + (rb - ra) * s; *G = ga + (gb - ga) * s; *B = ba + (bb - ba) * s; break; } } } arb_clear(t); arb_clear(u); } typedef void (*func_ptr)(acb_t, const acb_t, slong); void ai(acb_t res, const acb_t z, slong prec) { acb_hypgeom_airy(res, NULL, NULL, NULL, z, prec); } void bi(acb_t res, const acb_t z, slong prec) { acb_hypgeom_airy(NULL, NULL, res, NULL, z, prec); } void besselj(acb_t res, const acb_t z, slong prec) { acb_t nu; acb_init(nu); acb_hypgeom_bessel_j(res, nu, z, prec); acb_clear(nu); } void bessely(acb_t res, const acb_t z, slong prec) { acb_t nu; acb_init(nu); acb_hypgeom_bessel_y(res, nu, z, prec); acb_clear(nu); } void besseli(acb_t res, const acb_t z, slong prec) { acb_t nu; acb_init(nu); acb_hypgeom_bessel_i(res, nu, z, prec); acb_clear(nu); } void besselk(acb_t res, const acb_t z, slong prec) { acb_t nu; acb_init(nu); acb_hypgeom_bessel_k(res, nu, z, prec); acb_clear(nu); } /* this function looks better when scaled */ void modj(acb_t res, const acb_t z, slong prec) { acb_modular_j(res, z, prec); acb_div_ui(res, res, 1728, prec); } void modjq(acb_t res, const acb_t z, slong prec) { acb_t t; acb_init(t); acb_log(res, z, prec); acb_const_pi(t, prec); acb_div(res, res, t, prec); acb_mul_2exp_si(res, res, -1); acb_div_onei(res, res); acb_modular_j(res, res, prec); acb_div_ui(res, res, 1728, prec); acb_clear(t); } void modetaq(acb_t res, const acb_t z, slong prec) { acb_t t; acb_init(t); acb_log(res, z, prec); acb_const_pi(t, prec); acb_div(res, res, t, prec); acb_mul_2exp_si(res, res, -1); acb_div_onei(res, res); acb_modular_eta(res, res, prec); acb_clear(t); } void modlambdaq(acb_t res, const acb_t z, slong prec) { acb_t t; acb_init(t); acb_log(res, z, prec); acb_const_pi(t, prec); acb_div(res, res, t, prec); acb_mul_2exp_si(res, res, -1); acb_div_onei(res, res); acb_modular_lambda(res, res, prec); acb_clear(t); } void ellipp(acb_t res, const acb_t z, slong prec) { acb_onei(res); acb_elliptic_p(res, z, res, prec); } void ellipzeta(acb_t res, const acb_t z, slong prec) { acb_onei(res); acb_elliptic_zeta(res, z, res, prec); } void ellipsigma(acb_t res, const acb_t z, slong prec) { acb_onei(res); acb_elliptic_sigma(res, z, res, prec); } void fresnels(acb_t res, const acb_t z, slong prec) { acb_hypgeom_fresnel(res, NULL, z, 0, prec); } void fresnelc(acb_t res, const acb_t z, slong prec) { acb_hypgeom_fresnel(NULL, res, z, 0, prec); } void riemanntheta(acb_t res, const acb_t z, slong prec) { acb_mat_t tau; acb_ptr th, t; acb_mat_init(tau, 2, 2); acb_set_d_d(acb_mat_entry(tau, 0, 0), 1.0, 2.0); acb_set_d_d(acb_mat_entry(tau, 0, 1), -1.0, -1.0); acb_set_d_d(acb_mat_entry(tau, 1, 0), -1.0, -1.0); acb_set_d_d(acb_mat_entry(tau, 1, 1), 1.0, 2.0); t = _acb_vec_init(2); th = _acb_vec_init(16); acb_set(t, z); acb_div_onei(t + 1, z); acb_mul_2exp_si(t + 1, t + 1, -1); acb_theta_all(th, t, tau, 0, prec); acb_set(res, th + 9); acb_mul_2exp_si(res, res, -2); _acb_vec_clear(th, 16); _acb_vec_clear(t, 2); acb_mat_clear(tau); } typedef struct { arf_ptr xa; arf_ptr xb; arf_ptr ya; arf_ptr yb; slong xnum; slong ynum; slong y; func_ptr func; unsigned char * buf; int color_mode; } work_t; void worker(slong x, work_t * work) { slong prec; acb_t z, w; arf_ptr xa, xb, ya, yb; slong xnum, ynum, y; double R, G, B; acb_init(z); acb_init(w); xa = work->xa; xb = work->xb; ya = work->ya; yb = work->yb; xnum = work->xnum; ynum = work->ynum; y = work->y; for (prec = 30; prec < 500; prec *= 2) { arf_sub(arb_midref(acb_imagref(z)), yb, ya, prec, ARF_RND_DOWN); arf_mul_ui(arb_midref(acb_imagref(z)), arb_midref(acb_imagref(z)), y, prec, ARF_RND_DOWN); arf_div_ui(arb_midref(acb_imagref(z)), arb_midref(acb_imagref(z)), ynum - 1, prec, ARF_RND_DOWN); arf_add(arb_midref(acb_imagref(z)), arb_midref(acb_imagref(z)), ya, prec, ARF_RND_DOWN); arf_sub(arb_midref(acb_realref(z)), xb, xa, prec, ARF_RND_DOWN); arf_mul_ui(arb_midref(acb_realref(z)), arb_midref(acb_realref(z)), x, prec, ARF_RND_DOWN); arf_div_ui(arb_midref(acb_realref(z)), arb_midref(acb_realref(z)), xnum - 1, prec, ARF_RND_DOWN); arf_add(arb_midref(acb_realref(z)), arb_midref(acb_realref(z)), xa, prec, ARF_RND_DOWN); work->func(w, z, prec); if (acb_rel_accuracy_bits(w) > 4) break; } color_function(&R, &G, &B, w, work->color_mode); work->buf[3 * (y * xnum + x) + 0] = FLINT_MIN(255, floor(R * 255)); work->buf[3 * (y * xnum + x) + 1] = FLINT_MIN(255, floor(G * 255)); work->buf[3 * (y * xnum + x) + 2] = FLINT_MIN(255, floor(B * 255)); acb_clear(z); acb_clear(w); } int main(int argc, char *argv[]) { slong x, y, xnum, ynum, i; double dxa, dxb, dya, dyb; FILE * fp; arf_t xa, xb, ya, yb; acb_t z, w; func_ptr func; int color_mode; unsigned char * buf; slong num_threads; if (argc < 2) { printf("complex_plot [-range xa xb ya yb] [-size xn yn] [-color n] [-threads n] \n\n"); printf("Plots one of the predefined functions on [xa,xb] + [ya,yb]i\n"); printf("using domain coloring, at a resolution of xn by yn pixels.\n\n"); printf("Defaults parameters are [-10,10] + [-10,10]i and xn = yn = 512.\n\n"); printf("A color function can be selected with -color. The choices are:\n"); printf("0 phase=hue, magnitude=brightness\n"); printf("1 phase only, white-gold-black-blue-white counterclockwise\n"); printf("2 0+1 (dodge filter)\n"); printf("3 0+1, shiny\n"); printf("4 0+1, warm\n"); printf("5 0+1, cold\n"); printf("6 0+1, tomato\n\n"); printf("The output is written to arbplot.ppm. If you have ImageMagick,\n"); printf("run [convert arbplot.ppm arbplot.png] to get a PNG.\n\n"); printf("Function codes are:\n"); printf(" sin - Sine\n"); printf(" gamma - Gamma function\n"); printf(" digamma - Digamma function\n"); printf(" lgamma - Logarithmic gamma function\n"); printf(" zeta - Riemann zeta function\n"); printf(" erf - Error function\n"); printf(" ai - Airy function Ai\n"); printf(" bi - Airy function Bi\n"); printf(" besselj - Bessel function J_0\n"); printf(" bessely - Bessel function Y_0\n"); printf(" besseli - Bessel function I_0\n"); printf(" besselk - Bessel function K_0\n"); printf(" modj - Modular j-function\n"); printf(" modjq - Modular j-function (as function of q)\n"); printf(" modeta - Dedekind eta function\n"); printf(" modetaq - Dedekind eta function (as function of q)\n"); printf(" modlambda - Modular lambda function\n"); printf(" modlambdaq - Modular lambda function (as function of q)\n"); printf(" ellipp - Weierstrass elliptic function (on square lattice)\n"); printf(" ellipzeta - Weierstrass elliptic function (on square lattice)\n"); printf(" ellipsigma - Weierstrass elliptic function (on square lattice)\n"); printf(" barnesg - Barnes G-function\n"); printf(" agm - Arithmetic geometric mean\n"); printf(" fresnels - Fresnel integral S\n"); printf(" fresnelc - Fresnel integral C\n\n"); return 1; } xnum = 512; ynum = 512; dxa = dya = -10; dxb = dyb = 10; func = acb_gamma; color_mode = 0; num_threads = 1; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-size")) { xnum = atol(argv[i+1]); ynum = atol(argv[i+2]); i += 2; } else if (!strcmp(argv[i], "-range")) { dxa = atof(argv[i+1]); dxb = atof(argv[i+2]); dya = atof(argv[i+3]); dyb = atof(argv[i+4]); i += 4; } else if (!strcmp(argv[i], "-color")) { color_mode = atoi(argv[i+1]); i++; } else if (!strcmp(argv[i], "-threads")) { num_threads = atol(argv[i+1]); i++; } else if (!strcmp(argv[i], "sin")) func = acb_sin; else if (!strcmp(argv[i], "gamma")) func = acb_gamma; else if (!strcmp(argv[i], "digamma")) func = acb_digamma; else if (!strcmp(argv[i], "lgamma")) func = acb_lgamma; else if (!strcmp(argv[i], "zeta")) func = acb_zeta; else if (!strcmp(argv[i], "erf")) func = acb_hypgeom_erf; else if (!strcmp(argv[i], "ai")) func = ai; else if (!strcmp(argv[i], "bi")) func = bi; else if (!strcmp(argv[i], "besselj")) func = besselj; else if (!strcmp(argv[i], "bessely")) func = bessely; else if (!strcmp(argv[i], "besseli")) func = besseli; else if (!strcmp(argv[i], "besselk")) func = besselk; else if (!strcmp(argv[i], "modj")) func = modj; else if (!strcmp(argv[i], "modjq")) func = modjq; else if (!strcmp(argv[i], "modeta")) func = acb_modular_eta; else if (!strcmp(argv[i], "modetaq")) func = modetaq; else if (!strcmp(argv[i], "modlambda")) func = acb_modular_lambda; else if (!strcmp(argv[i], "modlambdaq")) func = modlambdaq; else if (!strcmp(argv[i], "ellipp")) func = ellipp; else if (!strcmp(argv[i], "ellipzeta")) func = ellipzeta; else if (!strcmp(argv[i], "ellipsigma")) func = ellipsigma; else if (!strcmp(argv[i], "barnesg")) func = acb_barnes_g; else if (!strcmp(argv[i], "agm")) func = acb_agm1; else if (!strcmp(argv[i], "fresnels")) func = fresnels; else if (!strcmp(argv[i], "fresnelc")) func = fresnelc; else if (!strcmp(argv[i], "riemanntheta")) func = riemanntheta; else { printf("unknown option: %s\n", argv[i]); return 1; } } acb_init(z); acb_init(w); arf_init(xa); arf_init(xb); arf_init(ya); arf_init(yb); arf_set_d(xa, dxa); arf_set_d(xb, dxb); arf_set_d(ya, dya); arf_set_d(yb, dyb); buf = flint_malloc(3 * xnum * ynum); flint_set_num_threads(num_threads); TIMEIT_ONCE_START for (y = ynum - 1; y >= 0; y--) { work_t work; if (y % (ynum / 16) == 0) printf("row %ld\n", y); work.xa = xa; work.xb = xb; work.ya = ya; work.yb = yb; work.xnum = xnum; work.ynum = ynum; work.y = y; work.func = func; work.buf = buf; work.color_mode = color_mode; flint_parallel_do((do_func_t) worker, &work, xnum, num_threads, FLINT_PARALLEL_STRIDED); } TIMEIT_ONCE_STOP fp = fopen("arbplot.ppm", "w"); fprintf(fp, "P6\n%ld %ld 255\n", xnum, ynum); for (y = ynum - 1; y >= 0; y--) { for (x = 0; x < xnum; x++) { fputc(buf[3 * (y * xnum + x) + 0], fp); fputc(buf[3 * (y * xnum + x) + 1], fp); fputc(buf[3 * (y * xnum + x) + 2], fp); } } flint_free(buf); fclose(fp); arf_clear(xa); arf_clear(xb); arf_clear(ya); arf_clear(yb); acb_clear(z); acb_clear(w); flint_cleanup_master(); return 0; } flint-3.1.3/examples/crt.c000066400000000000000000000026351461254215100154130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program for incremental multimodular reduction and reconstruction using the Chinese Remainder Theorem. */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(int argc, char* argv[]) { slong bit_bound; mp_limb_t prime, res; fmpz_t x, y, prod; if (argc != 2) { flint_printf("Syntax: crt \n"); return EXIT_FAILURE; } fmpz_init(x); fmpz_init(y); fmpz_init(prod); fmpz_set_str(x, argv[1], 10); bit_bound = fmpz_bits(x) + 2; fmpz_zero(y); fmpz_one(prod); prime = 0; while(fmpz_bits(prod) < bit_bound) { prime = n_nextprime(prime, 0); res = fmpz_fdiv_ui(x, prime); fmpz_CRT_ui(y, y, prod, res, prime, 1); flint_printf("residue mod %wu = %wu; reconstruction = ", prime, res); fmpz_print(y); flint_printf("\n"); fmpz_mul_ui(prod, prod, prime); } fmpz_clear(x); fmpz_clear(y); fmpz_clear(prod); return 0; } flint-3.1.3/examples/delta_qexp.c000066400000000000000000000022631461254215100167460ustar00rootroot00000000000000/* Copyright (C) 2007 David Harvey, William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program for computing the q-expansion of the delta function. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "arith.h" int main(int argc, char* argv[]) { fmpz_t c, n; slong N = 0; if (argc == 2) N = atol(argv[1]); if (argc != 2 || N < 1) { flint_printf("Syntax: delta_qexp \n"); flint_printf("where is the (positive) number of terms to compute\n"); return EXIT_FAILURE; } fmpz_init(c); fmpz_init(n); fmpz_set_si(n, N); arith_ramanujan_tau(c, n); flint_printf("Coefficient of q^%wd is ", N); fmpz_print(c); flint_printf("\n"); fmpz_clear(c); fmpz_clear(n); return 0; } flint-3.1.3/examples/dft.c000066400000000000000000000146231461254215100154000ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "profiler.h" #include "ca.h" #include "ca_vec.h" void benchmark_DFT(slong N, int input, int verbose, slong qqbar_limit, slong gb, ca_ctx_t ctx) { ca_ptr x, X, y, w; ca_t t; slong i, k, n; truth_t is_zero; x = _ca_vec_init(N, ctx); X = _ca_vec_init(N, ctx); y = _ca_vec_init(N, ctx); w = _ca_vec_init(2 * N, ctx); ca_init(t, ctx); /* ctx->options[CA_OPT_PRINT_FLAGS] = CA_PRINT_DEBUG; */ /* ctx->options[CA_OPT_VERBOSE] = 1; */ ctx->options[CA_OPT_USE_GROEBNER] = gb; if (qqbar_limit != 0) ctx->options[CA_OPT_QQBAR_DEG_LIMIT] = qqbar_limit; /* Construct input vector */ if (verbose) flint_printf("[x] =\n"); for (i = 0; i < N; i++) { if (input == 0) { ca_set_ui(x + i, i + 2, ctx); } else if (input == 1) { ca_set_ui(x + i, i + 2, ctx); ca_sqrt(x + i, x + i, ctx); } else if (input == 2) { ca_set_ui(x + i, i + 2, ctx); ca_log(x + i, x + i, ctx); } else if (input == 3) { ca_pi_i(x + i, ctx); ca_mul_ui(x + i, x + i, 2, ctx); ca_div_ui(x + i, x + i, i + 2, ctx); ca_exp(x + i, x + i, ctx); } else if (input == 4) { ca_pi(x + i, ctx); ca_mul_ui(x + i, x + i, i + 2, ctx); ca_add_ui(x + i, x + i, 1, ctx); ca_inv(x + i, x + i, ctx); } else if (input == 5) { ca_pi(x + i, ctx); ca_sqrt_ui(w, i + 2, ctx); ca_mul(x + i, x + i, w, ctx); ca_add_ui(x + i, x + i, 1, ctx); ca_inv(x + i, x + i, ctx); } if (verbose) { ca_print(x + i, ctx); printf("\n"); } } /* Construct roots of unity */ for (i = 0; i < 2 * N; i++) { if (i == 0) { ca_one(w + i, ctx); } else if (i == 1) { ca_pi_i(w + i, ctx); ca_mul_ui(w + i, w + i, 2, ctx); ca_div_si(w + i, w + i, N, ctx); ca_exp(w + i, w + i, ctx); } else { ca_mul(w + i, w + i - 1, w + 1, ctx); } } /* Forward DFT */ if (verbose) printf("\nDFT([x]) =\n"); for (k = 0; k < N; k++) { ca_zero(X + k, ctx); for (n = 0; n < N; n++) { ca_mul(t, x + n, w + ((2 * N - k) * n) % (2 * N), ctx); ca_add(X + k, X + k, t, ctx); } if (verbose) { ca_print(X + k, ctx); printf("\n"); } } /* Inverse DFT */ if (verbose) printf("\nIDFT(DFT([x])) =\n"); for (k = 0; k < N; k++) { ca_zero(y + k, ctx); for (n = 0; n < N; n++) { ca_mul(t, X + n, w + (k * n) % (2 * N), ctx); ca_add(y + k, y + k, t, ctx); } ca_div_ui(y + k, y + k, N, ctx); if (verbose) { ca_print(y + k, ctx); flint_printf("\n"); } } if (verbose) printf("\n[x] - IDFT(DFT([x])) =\n"); for (k = 0; k < N; k++) { ca_sub(t, x + k, y + k, ctx); is_zero = ca_check_is_zero(t, ctx); if (verbose) { ca_print(t, ctx); printf(" (= 0 "); truth_print(is_zero); printf(")\n"); } if (is_zero != T_TRUE) { printf("Failed to prove equality!\n"); flint_abort(); } } if (verbose) printf("\n"); _ca_vec_clear(x, N, ctx); _ca_vec_clear(X, N, ctx); _ca_vec_clear(y, N, ctx); _ca_vec_clear(w, 2 * N, ctx); ca_clear(t, ctx); } void usage(void) { printf("usage: dft [-verbose] [-input i] [-limit B] [-timing T] [-nogb] N\n"); } int main(int argc, char *argv[]) { ca_ctx_t ctx; int verbose, input, timing; slong i, Nmin, Nmax, N, qqbar_limit, gb; Nmin = Nmax = 2; verbose = 0; input = 0; timing = 0; qqbar_limit = 0; gb = 1; if (argc < 2) { usage(); return 1; } for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-verbose")) { verbose = 1; } else if (!strcmp(argv[i], "-input")) { input = atol(argv[i+1]); i += 1; } else if (!strcmp(argv[i], "-limit")) { qqbar_limit = atol(argv[i+1]); i += 1; } else if (!strcmp(argv[i], "-nogb")) { gb = 0; } else if (!strcmp(argv[i], "-timing")) { timing = atol(argv[i+1]); i += 1; } else { Nmin = Nmax = atol(argv[i]); if (Nmin < 0) { Nmin = 0; Nmax = -Nmax; } } } for (N = Nmin; N <= Nmax; N++) { flint_printf("DFT benchmark, length N = %wd\n", N); if (input == 0) flint_printf("x_k = k + 2\n"); else if (input == 1) flint_printf("x_k = sqrt(k + 2)\n"); else if (input == 2) flint_printf("x_k = log(k + 2)\n"); else if (input == 3) flint_printf("x_k = exp(2 pi i / (k + 2))\n"); else if (input == 4) flint_printf("x_k = 1 / (1 + (k + 2) pi)\n"); else if (input == 5) flint_printf("x_k = 1 / (1 + sqrt(k + 2) pi)\n"); flint_printf("\n"); if (timing == 0) { TIMEIT_ONCE_START ca_ctx_init(ctx); benchmark_DFT(N, input, verbose, qqbar_limit, gb, ctx); ca_ctx_clear(ctx); TIMEIT_ONCE_STOP } else if (timing == 1) { TIMEIT_START ca_ctx_init(ctx); benchmark_DFT(N, input, verbose, qqbar_limit, gb, ctx); ca_ctx_clear(ctx); TIMEIT_STOP } else { ca_ctx_init(ctx); benchmark_DFT(N, input, verbose, qqbar_limit, gb, ctx); TIMEIT_START benchmark_DFT(N, input, verbose, qqbar_limit, gb, ctx); TIMEIT_STOP ca_ctx_clear(ctx); } } SHOW_MEMORY_USAGE flint_cleanup(); return 0; } flint-3.1.3/examples/elementary.c000066400000000000000000000141141461254215100167630ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include "profiler.h" #include "ca.h" #include "ca_ext.h" #include "ca_field.h" #define START(expr) flint_printf(">>> "); flint_printf(expr) #define OUT \ flint_printf("\n"); \ ca_print(x, ctx); flint_printf("\n\n"); #define OUT2 \ flint_printf("\n"); \ ca_print(x, ctx); flint_printf("\n"); \ flint_printf(">>> Is zero?\n"); truth_print(ca_check_is_zero(x, ctx)); \ flint_printf("\n\n"); void ca_set_qqi_si(ca_t res, slong a, slong b, slong c, slong d, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_set_si(t, a, ctx); ca_div_si(t, t, b, ctx); ca_i(res, ctx); ca_mul_si(res, res, c, ctx); ca_div_si(res, res, d, ctx); ca_add(res, res, t, ctx); ca_clear(t, ctx); } int main(int argc, char *argv[]) { ca_ctx_t ctx; ca_t x, y, z; TIMEIT_ONCE_START ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); START("Exp(Pi*I) + 1"); ca_pi_i(x, ctx); ca_exp(x, x, ctx); ca_add_ui(x, x, 1, ctx); OUT START("Log(-1) / (Pi*I)"); ca_set_si(x, -1, ctx); ca_log(x, x, ctx); ca_pi_i(y, ctx); ca_div(x, x, y, ctx); OUT START("Log(-I) / (Pi*I)"); ca_neg_i(x, ctx); ca_log(x, x, ctx); ca_pi_i(y, ctx); ca_div(x, x, y, ctx); OUT START("Log(1 / 10^123) / Log(100)"); ca_set_ui(x, 10, ctx); ca_pow_ui(x, x, 123, ctx); ca_inv(x, x, ctx); ca_log(x, x, ctx); ca_set_ui(y, 100, ctx); ca_log(y, y, ctx); ca_div(x, x, y, ctx); OUT START("Log(1 + Sqrt(2)) / Log(3 + 2*Sqrt(2))"); ca_sqrt_ui(x, 2, ctx); ca_add_ui(x, x, 1, ctx); ca_log(x, x, ctx); ca_sqrt_ui(y, 2, ctx); ca_mul_ui(y, y, 2, ctx); ca_add_ui(y, y, 3, ctx); ca_log(y, y, ctx); ca_div(x, x, y, ctx); OUT START("Sqrt(2)*Sqrt(3) - Sqrt(6)"); ca_sqrt_ui(x, 2, ctx); ca_sqrt_ui(y, 3, ctx); ca_sqrt_ui(z, 6, ctx); ca_mul(x, x, y, ctx); ca_sub(x, x, z, ctx); OUT START("Exp(1+Sqrt(2)) * Exp(1-Sqrt(2)) / (Exp(1)^2)"); ca_sqrt_ui(x, 2, ctx); ca_add_ui(x, x, 1, ctx); ca_exp(x, x, ctx); ca_sqrt_ui(y, 2, ctx); ca_ui_sub(y, 1, y, ctx); ca_exp(y, y, ctx); ca_one(z, ctx); ca_exp(z, z, ctx); ca_pow_ui(z, z, 2, ctx); ca_mul(x, x, y, ctx); ca_div(x, x, z, ctx); OUT START("I^I - Exp(-Pi/2)"); ca_i(x, ctx); ca_pow(x, x, x, ctx); ca_pi(y, ctx); ca_div_ui(y, y, 2, ctx); ca_neg(y, y, ctx); ca_exp(y, y, ctx); ca_sub(x, x, y, ctx); OUT START("Exp(Sqrt(3))^2 - Exp(Sqrt(12))"); ca_sqrt_ui(x, 3, ctx); ca_exp(x, x, ctx); ca_pow_ui(x, x, 2, ctx); ca_sqrt_ui(y, 12, ctx); ca_exp(y, y, ctx); ca_sub(x, x, y, ctx); OUT START("2*Log(Pi*I) - 4*Log(Sqrt(Pi)) - Pi*I"); ca_pi_i(x, ctx); ca_log(x, x, ctx); ca_mul_ui(x, x, 2, ctx); ca_pi(y, ctx); ca_sqrt(y, y, ctx); ca_log(y, y, ctx); ca_mul_ui(y, y, 4, ctx); ca_sub(x, x, y, ctx); ca_pi_i(y, ctx); ca_sub(x, x, y, ctx); OUT /* Example 1 in [BBK2014] */ START("-I*Pi/8*Log(2/3-2*I/3)^2 + I*Pi/8*Log(2/3+2*I/3)^2 + Pi^2/12*Log(-1-I) + Pi^2/12*Log(-1+I) + Pi^2/12*Log(1/3-I/3) + Pi^2/12*Log(1/3+I/3) - Pi^2/48*Log(18)"); ca_zero(x, ctx); ca_set_qqi_si(y, 2, 3, -2, 3, ctx); ca_log(y, y, ctx); ca_sqr(y, y, ctx); ca_pi_i(z, ctx); ca_mul(y, y, z, ctx); ca_div_si(y, y, -8, ctx); ca_add(x, x, y, ctx); ca_set_qqi_si(y, 2, 3, 2, 3, ctx); ca_log(y, y, ctx); ca_sqr(y, y, ctx); ca_pi_i(z, ctx); ca_mul(y, y, z, ctx); ca_div_si(y, y, 8, ctx); ca_add(x, x, y, ctx); ca_set_qqi_si(y, -1, 1, -1, 1, ctx); ca_log(y, y, ctx); ca_pi(z, ctx); ca_sqr(z, z, ctx); ca_mul(y, y, z, ctx); ca_div_si(y, y, 12, ctx); ca_add(x, x, y, ctx); ca_set_qqi_si(y, -1, 1, 1, 1, ctx); ca_log(y, y, ctx); ca_pi(z, ctx); ca_sqr(z, z, ctx); ca_mul(y, y, z, ctx); ca_div_si(y, y, 12, ctx); ca_add(x, x, y, ctx); ca_set_qqi_si(y, 1, 3, -1, 3, ctx); ca_log(y, y, ctx); ca_pi(z, ctx); ca_sqr(z, z, ctx); ca_mul(y, y, z, ctx); ca_div_si(y, y, 12, ctx); ca_add(x, x, y, ctx); ca_set_qqi_si(y, 1, 3, 1, 3, ctx); ca_log(y, y, ctx); ca_pi(z, ctx); ca_sqr(z, z, ctx); ca_mul(y, y, z, ctx); ca_div_si(y, y, 12, ctx); ca_add(x, x, y, ctx); ca_set_ui(y, 18, ctx); ca_log(y, y, ctx); ca_pi(z, ctx); ca_sqr(z, z, ctx); ca_mul(y, y, z, ctx); ca_div_si(y, y, -48, ctx); ca_sub(x, x, y, ctx); OUT START("Sqrt(5 + 2*Sqrt(6)) - Sqrt(2) - Sqrt(3)"); ca_sqrt_ui(x, 6, ctx); ca_mul_ui(x, x, 2, ctx); ca_add_ui(x, x, 5, ctx); ca_sqrt(x, x, ctx); ca_sqrt_ui(y, 2, ctx); ca_sub(x, x, y, ctx); ca_sqrt_ui(y, 3, ctx); ca_sub(x, x, y, ctx); OUT2 START("Sqrt(I) - (1+I)/Sqrt(2)"); ca_i(x, ctx); ca_sqrt(x, x, ctx); ca_i(y, ctx); ca_add_ui(y, y, 1, ctx); ca_sqrt_ui(z, 2, ctx); ca_div(y, y, z, ctx); ca_sub(x, x, y, ctx); OUT2 START("Exp(Pi*Sqrt(163)) - (640320^3 + 744)"); ca_pi(x, ctx); ca_sqrt_ui(y, 163, ctx); ca_mul(x, x, y, ctx); ca_exp(x, x, ctx); ca_set_ui(y, 640320, ctx); ca_pow_ui(y, y, 3, ctx); ca_add_ui(y, y, 744, ctx); ca_sub(x, x, y, ctx); OUT /* Taken (slightly tweaked) from: https://reference.wolfram.com/language/ref/PossibleZeroQ.html */ START("Erf(2*Log(Sqrt(1/2-Sqrt(2)/4))+Log(4)) - Erf(Log(2-Sqrt(2)))"); ca_sqrt_ui(x, 2, ctx); ca_div_ui(x, x, 4, ctx); ca_one(y, ctx); ca_div_ui(y, y, 2, ctx); ca_sub(x, y, x, ctx); ca_sqrt(x, x, ctx); ca_log(x, x, ctx); ca_mul_ui(x, x, 2, ctx); ca_set_ui(y, 4, ctx); ca_log(y, y, ctx); ca_add(x, y, x, ctx); ca_erf(x, x, ctx); ca_sqrt_ui(y, 2, ctx); ca_ui_sub(y, 2, y, ctx); ca_log(y, y, ctx); ca_erf(y, y, ctx); ca_sub(x, x, y, ctx); OUT flint_printf("\n"); ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_ctx_clear(ctx); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE flint_cleanup(); return 0; } flint-3.1.3/examples/factor_integer.c000066400000000000000000000051761461254215100176210ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_mpoly.h" #include "profiler.h" int main(int argc, char * argv[]) { fmpz_t n; fmpz_factor_t fac; slong i; int num_threads = 1; int timing = 0; if (argc < 2) { flint_printf("usage: factor_integer [-threads t] [-timing] n\n"); flint_printf("n can be given as an expression (no spaces)\n"); return 1; } fmpz_init(n); for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-threads")) { num_threads = atoi(argv[i+1]); flint_set_num_threads(num_threads); i++; } else if (!strcmp(argv[i], "-timing")) { timing = 1; } else { /* allow input like 2^64+1 */ /* we don't have an expression parser for fmpz yet, so use fmpz_mpoly with 0 variables */ { fmpz_mpoly_ctx_t mctx; fmpz_mpoly_t f; fmpz_mpoly_ctx_init(mctx, 0, ORD_LEX); fmpz_mpoly_init(f, mctx); if (fmpz_mpoly_set_str_pretty(f, argv[i], NULL, mctx) != 0) { flint_printf("unable to parse integer\n"); return 1; } fmpz_mpoly_get_fmpz(n, f, mctx); fmpz_mpoly_clear(f, mctx); fmpz_mpoly_ctx_clear(mctx); } } } fmpz_factor_init(fac); if (timing) { TIMEIT_START fmpz_factor(fac, n); TIMEIT_STOP SHOW_MEMORY_USAGE } else { fmpz_factor(fac, n); } fmpz_print(n); flint_printf(" =\n"); if (fac->sign != 1 || fac->num == 0) { flint_printf("%d", fac->sign); if (fac->num > 0) flint_printf(" * "); } for (i = 0; i < fac->num; i++) { fmpz_print(fac->p + i); if (fac->exp[i] >= 2) flint_printf("^%lu", fac->exp[i]); if (i < fac->num - 1) flint_printf(" * "); } flint_printf("\n"); fmpz_factor_clear(fac); fmpz_clear(n); flint_cleanup_master(); return 0; } flint-3.1.3/examples/factor_polynomial.c000066400000000000000000000045501461254215100203420ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" #include "profiler.h" int main(int argc, char * argv[]) { fmpz_mpoly_t f; fmpz_mpoly_ctx_t mctx; fmpz_mpoly_factor_t fac; slong i; int num_threads = 1; int timing = 0; int suppress = 0; const char * vars[] = { "x", "y", "z" }; if (argc < 2) { flint_printf("usage: factor_polynomial [-threads t] [-timing] [-suppress] expr\n"); flint_printf("example: build/examples/factor_polynomial -timing \"(1+x+2*y+3*z)^3+1\"\n"); return 1; } fmpz_mpoly_ctx_init(mctx, 3, ORD_LEX); fmpz_mpoly_init(f, mctx); fmpz_mpoly_factor_init(fac, mctx); for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-threads")) { num_threads = atoi(argv[i+1]); flint_set_num_threads(num_threads); i++; } else if (!strcmp(argv[i], "-timing")) { timing = 1; } else if (!strcmp(argv[i], "-suppress")) { suppress = 1; } else { if (fmpz_mpoly_set_str_pretty(f, argv[i], vars, mctx) != 0) { flint_printf("unable to parse polynomial\n"); return 1; } } } if (timing) { TIMEIT_START fmpz_mpoly_factor(fac, f, mctx); TIMEIT_STOP SHOW_MEMORY_USAGE } else { fmpz_mpoly_factor(fac, f, mctx); } if (!suppress) { fmpz_mpoly_print_pretty(f, vars, mctx); flint_printf(" =\n"); fmpz_mpoly_factor_print_pretty(fac, vars, mctx); flint_printf("\n"); } else { flint_printf("%wd irreducible factors\n", fac->num); } fmpz_mpoly_factor_clear(fac, mctx); fmpz_mpoly_clear(f, mctx); fmpz_mpoly_ctx_clear(mctx); flint_cleanup_master(); return 0; } flint-3.1.3/examples/fmpq_poly.c000066400000000000000000000021051461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Simple example demonstrating the use of the fmpq_poly module. */ #include #include #include "fmpq_poly.h" int main(int argc, char* argv[]) { char *str, *strf, *strg; fmpq_poly_t f, g; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_set_str(f, "2 1/2 3/5"); fmpq_poly_set_str(g, "4 1/3 2 3/2 -1/2"); strf = fmpq_poly_get_str_pretty(f, "t"); strg = fmpq_poly_get_str_pretty(g, "t"); fmpq_poly_mul(f, f, g); str = fmpq_poly_get_str_pretty(f, "t"); flint_printf("(%s) * (%s) = %s\n", strf, strg, str); flint_free(str); flint_free(strf); flint_free(strg); fmpq_poly_clear(f); fmpq_poly_clear(g); return 0; } flint-3.1.3/examples/fmpz_mod_poly.c000066400000000000000000000022231461254215100174720ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Example program for the fmpz_mod_poly module. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" int main(int argc, char* argv[]) { fmpz_t n; fmpz_mod_ctx_t ctx; fmpz_mod_poly_t x, y; fmpz_init_set_ui(n, 7); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(x, ctx); fmpz_mod_poly_init(y, ctx); fmpz_mod_poly_set_coeff_ui(x, 3, 5, ctx); fmpz_mod_poly_set_coeff_ui(x, 0, 6, ctx); fmpz_mod_poly_sqr(y, x, ctx); fmpz_mod_poly_print(x, ctx); flint_printf("\n"); fmpz_mod_poly_print(y, ctx); flint_printf("\n"); fmpz_mod_poly_clear(x, ctx); fmpz_mod_poly_clear(y, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(n); return 0; } flint-3.1.3/examples/fmpz_poly_factor_zassenhaus.c000066400000000000000000000030321461254215100224340ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Example program demonstrating the Zassenhaus factoring algorithm. */ #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { fmpz_poly_t f; fmpz_poly_factor_t facs; fmpz_poly_init(f); fmpz_poly_factor_init(facs); if (0) { FILE *polyfile; polyfile = fopen("examples/fmpz_poly_hensel_P1", "r"); if (!polyfile) { flint_printf("Error. Could not read P1 from file.\n"); flint_abort(); } fmpz_poly_fread(polyfile, f); } fmpz_poly_set_str(f, "63 1 1 1 -4 -7 -2 -6 -3 -7 18 7 25 -11 95 36 21 16 69 56 35 36 32 33 26 -26 -15 -14 -53 -96 67 72 -67 40 -79 -116 -452 -312 -260 -29 -1393 327 69 -28 -241 230 -54 -309 -125 -74 -450 -69 -3 66 -27 73 68 50 -63 -1290 372 31 -16 2"); fmpz_poly_factor_zassenhaus(facs, f); flint_printf("Polynomial:\n"); fmpz_poly_print(f); flint_printf("\nFactorisation:\n"); fmpz_poly_factor_print(facs); fmpz_poly_clear(f); fmpz_poly_factor_clear(facs); return 0; } flint-3.1.3/examples/fmpz_poly_hensel_P1000066400000000000000000000144241461254215100203160ustar00rootroot00000000000000157 2757808487144838302895430769948248417729237108863869417509479459915767341323330697211864790593685466362642868685686280572196434680273380283012145961103760692626213505149801403142032630867205290294889677921852958863296316098679545758264555461523658710938789459422476508285713011640130252486568573874403279248369585169539213650618995126951019719642265868631105857663880266888615740687129117228288314207488263153874611799588864 0 0 0 0 0 -216322796837555313021432683645937044292921028613383407157804069297831574640998740656489092120685008467028608331849579265535298919026656996120638521170849310580349430742714282458612690837924997423939358531519250439003103809474194653867052412730011984853274391208927747745495001768576577005852099658803085546514828589578330785402902514368037827033046816681733696103002335485194130317912396254882191766550071245537280 0 0 0 0 0 -461037645433479417894020721333520318742787637796222824861773705209889273869538158383427629416696554307900636877857163108477972707536277062193762789904663727290361284224373517600871057249998734207159849953758589691456457289461969382313561313225919667846650484354465287838669574263259013740628682955721862333944942797610117714349319340424888849377188433375019685712170554798874566289464703683278915239936 0 0 0 0 0 -3006606488311441089896683017688393310181237526393515483185168180454254753097973363635722407434487318654611062408549655477030250215182281891825672566995224009864674440632939039163270907351880438387976862382953630127475285232095605983810246580601204355061953631934206101782233808526261885763004588113518320634896519093555011110157604966440212309535525594054654293518320014613131809110622208 0 0 0 0 0 -21667646451621122746329554641562526144092633323312599411016990419323105385099476066414168972485002571354506235276444763858199439264635997569307854261698326829531703857487029929169587379456251270438809123403197975344780862412222180332148184540879408846734261457232407592147312924337495632438881306066500258566449544033936294138097409605834038606201765458164323353573757812736 0 0 0 0 0 -36008946342647299345277533676465042992542509358162091707911485884063199188678585181307031154064029716715217548592392000646414311357113983560970141370451913098200635822787067067854257570327208938999696955706264073506673179971102683350614122127866850451153062491787093182867397127538003924258331826086311209206145468869911581822662684689775342390081444166762496 0 0 0 0 0 64738333885402706154009400777843384948514403975131509466836736265603889387062685884838924226241494383359395885853573043385536386037715829201209541872597706855188799653603478660006394706968635342978467902539925660331269747297563569373972862258677268612185384308671129076702627081272278586910256050615727493523124564910427355844022903201664598016 0 0 0 0 0 -26515019326962174180142979909852192000598024025005741295940640978614198820508372895246811842900425977352727727321855043342564236181262669572054649107156675328942799346600624572167621155490882477365676272092450671794375283335841074839674104033802419109510303627230113525211458922561813524476132216574712854465367040031027145736192 0 0 0 0 0 7206103572192660713378206441635342218917489717304647992423853713271386261468915707872924405011212678144586363155710573280556474140830016874081726445858124315662916567493737199217110913142452405975457031642733926038866594546019867393529529573884911052196182095293632879922014565430281245217054716156649445034819584 0 0 0 0 0 -1781067445792627012203411699914789751917558964317719007317246424900608235475797721781459407143458070618250900401160717537304193257391576912113861254338589725654811524225989470856639467420913364918958248936121424237401680876071173527822994467656057208698530802400487646077493116544189557449970155520 0 0 0 0 0 257785868023252499546719038629025522238370895088838886132974669167861057091364847664488796999614147085642953811171182098166013025545859882309438475565596820726130902460185426222014793570631782686609398943162320798462220946658785090792728810983258963716578939056822038673472371032064 0 0 0 0 0 -11784090207202014162295386617819122580975749672866993427537075993392758066192465164322165415699997447946113816444451865902475946080059998736123233932142195687596120620775313704725043713670267057116323795251403918781211539279372041111665200731953898028103168618921984 0 0 0 0 0 -516024270178733628499623062311311909026630748206142586718438261050317424310047984113834321775600080026192071968298564681207899012445940514128285818475704941072871032892579017242172498256146144732370397366971600828731748910067376163611390633039626240 0 0 0 0 0 30082639005203703587384390914836066417375929216836277495255127429645641088564854026651642629932602536304239256338883055950342516352052967456427931536708936701164689433642079716822865825451517411212445927909524063734481575283370491904 0 0 0 0 0 -473470234117762253449114353073575227253051133950080887048220406201777923641087656057923908627860421347898111116275922195546977433176120962969045561381814949718893972897291028710748149921273892963880265171252944044032 0 0 0 0 0 1716231160060069630599685050354626175015068955757203109707649882577572773165548338611188714799775273882912731234014004123562719620912869622981185312386637525543829470533595866145631607760885722906624 0 0 0 0 0 29097610765037817861202663659325678575900946766272112229562997159720733072202069362200879071525561150306287386997432893787696445551277644983772558101666007653602762940659581050683392 0 0 0 0 0 -359926316046483943753279829287876608460021803187136100943332906260813526077725113393005907399350257834664287535635450778981949557310768189387775714926393025942781952 0 0 0 0 0 1585164055408008634764541421847990628448201383564778254157208549989039915612818011950714697494640213070044956331618331201033480861222528629063286784 0 0 0 0 0 -2786147914453983786915822775172002754752542153742435684470657396691295332282129004399822009077517014397168296974400680697863864320 0 0 0 0 0 -38152084257499719867416104314045082135545017120806331924723488759543432766463641099223031913762482060169052160 0 0 0 0 0 6156765507729276548165940166182211314235431893392787456381452344509549569751736679901247307776 0 0 0 0 0 -6689833869884920066141475743520535508680559052015304499397212203049103130624 0 0 0 0 0 2000741892753026115892243757690184900091769801141945106432 0 0 0 0 0 -50111580155260460844584241578962989056 0 0 0 0 0 -28293184124737694080 0 0 0 0 0 1 flint-3.1.3/examples/fmpz_poly_q.c000066400000000000000000000022431461254215100171550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Simple example demonstrating the use of the fmpz_poly_q module. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_q.h" int main(int argc, char* argv[]) { char *str, *strf, *strg; fmpz_poly_q_t f, g; fmpz_poly_q_init(f); fmpz_poly_q_init(g); fmpz_poly_q_set_str(f, "2 1 3/1 2"); fmpz_poly_q_set_str(g, "1 3/2 2 7"); strf = fmpz_poly_q_get_str_pretty(f, "t"); strg = fmpz_poly_q_get_str_pretty(g, "t"); fmpz_poly_q_mul(f, f, g); str = fmpz_poly_q_get_str_pretty(f, "t"); flint_printf("%s * %s = %s\n", strf, strg, str); flint_free(str); flint_free(strf); flint_free(strg); fmpz_poly_q_clear(f); fmpz_poly_q_clear(g); return 0; } flint-3.1.3/examples/fpwrap.c000066400000000000000000000007631461254215100161220ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include "arb_fpwrap.h" int main(void) { double x, y; complex_double cx, cy; int flags = 0; /* default options */ x = 2.0; cx.real = 0.5; cx.imag = 123.0; arb_fpwrap_double_zeta(&y, x, flags); arb_fpwrap_cdouble_zeta(&cy, cx, flags); printf("zeta(%g) = %.16g\n", x, y); printf("zeta(%g + %gi) = %.16g + %.16gi\n", cx.real, cx.imag, cy.real, cy.imag); flint_cleanup(); return 0; } flint-3.1.3/examples/fq_poly.c000066400000000000000000000103661461254215100162740ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program to demonstrate some use of the fq_poly module. */ #include #include #include "fmpz.h" #include "fq.h" #include "fq_poly.h" int main(void) { fmpz_t p; slong d, i; fq_ctx_t ctx; clock_t c0, c1; double c; fq_poly_t f, g, h; FLINT_TEST_INIT(state); printf("Polynomial multiplication over GF(q)\n"); printf("------------------------------------\n"); { printf("1) Two length-10,000 polynomials over GF(3^2)\n"); fmpz_init_set_ui(p, 3); d = 2; fq_ctx_init_conway(ctx, p, d, "X"); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_poly_init(h, ctx); fq_poly_randtest(g, state, 10000, ctx); fq_poly_randtest(h, state, 10000, ctx); c0 = clock(); fq_poly_mul_classical(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("Classical: %fs\n", c); c0 = clock(); for (i = 0; i < 100; i++) fq_poly_mul_reorder(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("Reorder: %fms\n", 10 * c); c0 = clock(); for (i = 0; i < 100; i++) fq_poly_mul_KS(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("KS: %fms\n", 10 * c); fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_poly_clear(h, ctx); fq_ctx_clear(ctx); fmpz_clear(p); } { printf("2) Two length-500 polynomials over GF(3^263)\n"); fmpz_init_set_ui(p, 3); d = 263; fq_ctx_init_conway(ctx, p, d, "X"); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_poly_init(h, ctx); fq_poly_randtest(g, state, 500, ctx); fq_poly_randtest(h, state, 500, ctx); c0 = clock(); fq_poly_mul_classical(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("Classical: %fs\n", c); c0 = clock(); fq_poly_mul_reorder(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("Reorder: %fs\n", c); c0 = clock(); for (i = 0; i < 100; i++) fq_poly_mul_KS(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("KS: %fms\n", 10 * c); fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_poly_clear(h, ctx); fq_ctx_clear(ctx); fmpz_clear(p); } { printf("3) Two length-5 polynomials over GF(109987^4)\n"); fmpz_init_set_ui(p, 109987); d = 4; fq_ctx_init_conway(ctx, p, d, "X"); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_poly_init(h, ctx); fq_poly_randtest(g, state, 4, ctx); fq_poly_randtest(h, state, 4, ctx); c0 = clock(); for (i = 0; i < 1000 * 100; i++) fq_poly_mul_classical(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("Classical: %f\xb5s\n", 10 * c); c0 = clock(); for (i = 0; i < 1000 * 100; i++) fq_poly_mul_reorder(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("Reorder: %f\xb5s\n", 10 * c); c0 = clock(); for (i = 0; i < 1000 * 100; i++) fq_poly_mul_KS(f, g, h, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; printf("KS: %f\xb5s\n", 10 * c); fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_poly_clear(h, ctx); fq_ctx_clear(ctx); fmpz_clear(p); } fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_poly_clear(h, ctx); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/examples/functions_benchmark.c000066400000000000000000000072141461254215100206430ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include "profiler.h" #include "fmpq.h" #include "arb.h" #include "arb_hypgeom.h" #include "acb.h" #include "acb_modular.h" #include "partitions.h" #include "bernoulli.h" #define TIMEIT_ONCE_STOP_VALUES(tcpu, twall) \ } while (0); \ timeit_stop(__timer); \ (tcpu) = __timer->cpu*0.001; \ (twall) = __timer->wall*0.001; \ } while (0); void doit(arb_t res, const arb_t x, slong n, int function, slong prec) { if (function == 0) arb_const_pi(res, prec); else if (function == 1) arb_const_euler(res, prec); else if (function == 2) arb_exp(res, x, prec); else if (function == 3) arb_log(res, x, prec); else if (function == 4) arb_sin(res, x, prec); else if (function == 5) arb_atan(res, x, prec); else if (function == 6) arb_hypgeom_erf(res, x, prec); else if (function == 7) arb_gamma(res, x, prec); else if (function == 8) arb_zeta(res, x, prec); else if (function == 9) { acb_t t; acb_init(t); arb_set(acb_imagref(t), x); acb_modular_eta(t, t, prec); acb_clear(t); } else if (function == 10) { fmpq_t t; fmpq_init(t); bernoulli_fmpq_ui(t, n); fmpq_clear(t); } else if (function == 11) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, n); fmpz_mul(t, t, t); partitions_fmpz_fmpz(t, t, 0); fmpz_clear(t); } } char * description[] = { "const_pi, n digits", "const_euler, n digits", "exp(x), n digits", "log(x), n digits", "sin(x), n digits", "atan(x), n digits", "erf(x), n digits", "gamma(x), n digits", "zeta(x), n digits", "eta(ix), n digits", "bernoulli(n)", "partitions(n^2)", }; slong limit[] = { 1e8, 1e7, 1e7, 1e7, 1e7, 1e7, 1e6, 1e5, 1e4, 1e6, 1e6, 1e7, }; int main(void) { arb_t x, y, res; slong n, prec; int function; double FLINT_SET_BUT_UNUSED(tcpu), twall; arb_init(x); arb_init(y); arb_init(res); for (function = 0; function <= 11; function++) { printf("\n%s\n", description[function]); printf("%12s%24s%24s\n", "", "threads = 1 ", "threads = 8 "); printf("%12s%12s%12s%12s%12s\n", "n", "first", "repeat", "first", "repeat"); for (n = 10; n <= limit[function]; n *= 10) { prec = n * 3.323 + 1; flint_printf("%12wd", n); fflush(stdout); arb_sqrt_ui(x, 2, prec); arb_sub_ui(x, x, 1, prec); flint_set_num_threads(1); flint_cleanup(); TIMEIT_ONCE_START doit(res, x, n, function, prec); TIMEIT_ONCE_STOP_VALUES(tcpu, twall); printf("%12.3g", twall); fflush(stdout); TIMEIT_START doit(res, x, n, function, prec); TIMEIT_STOP_VALUES(tcpu, twall); printf("%12.3g", twall); fflush(stdout); flint_set_num_threads(8); flint_cleanup(); TIMEIT_ONCE_START doit(res, x, n, function, prec); TIMEIT_ONCE_STOP_VALUES(tcpu, twall); printf("%12.3g", twall); fflush(stdout); TIMEIT_START doit(res, x, n, function, prec); TIMEIT_STOP_VALUES(tcpu, twall); printf("%12.3g", twall); fflush(stdout); printf("\n"); } } arb_clear(x); arb_clear(y); arb_clear(res); flint_cleanup_master(); return 0; } flint-3.1.3/examples/hilbert_matrix.c000066400000000000000000000041421461254215100176330ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "arb_mat.h" #include "acb_mat.h" #include "profiler.h" int main(int argc, char *argv[]) { arb_mat_t A; arb_t det; slong i, prec, n; int eig; if (argc < 2 || (argc == 3 && strcmp(argv[1], "-eig"))) { flint_printf("usage: build/examples/hilbert_matrix [-eig] n\n"); return 1; } if (argc == 2) eig = 0; else eig = 1; n = atol(argv[argc-1]); if (eig && (n == 0)) { flint_printf("smallest eigenvalue: undefined for n == 0\n"); return 1; } arb_mat_init(A, n, n); arb_init(det); TIMEIT_ONCE_START for (prec = 20; ; prec *= 2) { arb_mat_hilbert(A, prec); flint_printf("prec=%wd: ", prec); if (eig == 0) { arb_mat_det(det, A, prec); } else { acb_mat_t C, R; acb_ptr E; acb_mat_init(R, n, n); acb_mat_init(C, n, n); E = _acb_vec_init(n); acb_mat_set_arb_mat(C, A); acb_mat_approx_eig_qr(E, NULL, R, C, NULL, 0, prec); if (acb_mat_eig_simple(E, NULL, NULL, C, E, R, prec)) { /* A is symmetric so the eigenvalues are real */ for (i = 0; i < n; i++) arb_zero(acb_imagref(E + i)); /* With isolated eigenvalues, sorting midpoints gives the right result. */ _acb_vec_sort_pretty(E, n); acb_get_real(det, E + 0); } else { arb_indeterminate(det); } acb_mat_clear(R); acb_mat_clear(C); _acb_vec_clear(E, n); } arb_printn(det, 10, 0); flint_printf("\n"); if (!arb_contains_zero(det)) { flint_printf("success!\n"); break; } } TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE arb_mat_clear(A); arb_clear(det); flint_cleanup(); return 0; } flint-3.1.3/examples/hilbert_matrix_ca.c000066400000000000000000000074251461254215100203050ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "profiler.h" #include "fmpq_mat.h" #include "ca.h" #include "ca_vec.h" #include "ca_mat.h" #include "qqbar.h" int main(int argc, char *argv[]) { slong n, i; int qqbar, vieta, novieta; if (argc < 2) { flint_printf("usage: hilbert_matrix [-qqbar] [-vieta | -novieta] n\n"); return 1; } qqbar = 0; vieta = 0; novieta = 0; n = 0; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-qqbar")) { qqbar = 1; } else if (!strcmp(argv[i], "-vieta")) { vieta = 1; } else if (!strcmp(argv[i], "-novieta")) { novieta = 1; } else { n = atol(argv[i]); if (n < 0 || n > 100) flint_abort(); } } TIMEIT_ONCE_START if (qqbar) { fmpq_mat_t mat; qqbar_ptr eig; qqbar_t trace, det; fmpq_mat_init(mat, n, n); qqbar_init(trace); qqbar_init(det); eig = _qqbar_vec_init(n); fmpq_mat_hilbert_matrix(mat); qqbar_eigenvalues_fmpq_mat(eig, mat, 0); flint_printf("Trace:\n"); qqbar_zero(trace); for (i = 0; i < n; i++) { qqbar_add(trace, trace, eig + i); flint_printf("%wd/%wd: degree %wd\n", i, n, qqbar_degree(trace)); } qqbar_print(trace); flint_printf("\n"); flint_printf("Determinant:\n"); qqbar_one(det); for (i = 0; i < n; i++) { qqbar_mul(det, det, eig + i); flint_printf("%wd/%wd: degree %wd\n", i, n, qqbar_degree(det)); } qqbar_print(det); flint_printf("\n"); fmpq_mat_clear(mat); qqbar_clear(trace); qqbar_clear(det); _qqbar_vec_clear(eig, n); } else { ca_ctx_t ctx; ca_mat_t mat; ca_vec_t eig; ca_t trace, det, t; ulong * mul; ca_ctx_init(ctx); /* Verification requires high-degree algebraics. */ ctx->options[CA_OPT_QQBAR_DEG_LIMIT] = 10000; if (vieta) ctx->options[CA_OPT_VIETA_LIMIT] = n; if (novieta) ctx->options[CA_OPT_VIETA_LIMIT] = 0; ca_mat_init(mat, n, n, ctx); ca_vec_init(eig, 0, ctx); mul = flint_malloc(sizeof(ulong) * n); ca_init(trace, ctx); ca_init(det, ctx); ca_init(t, ctx); ca_mat_hilbert(mat, ctx); ca_mat_eigenvalues(eig, mul, mat, ctx); ca_mat_trace(trace, mat, ctx); ca_mat_det(det, mat, ctx); /* note: in general, we should use the multiplicities, but we happen to know that the eigenvalues are simple here */ flint_printf("Trace:\n"); ca_zero(t, ctx); for (i = 0; i < n; i++) ca_add(t, t, ca_vec_entry(eig, i), ctx); ca_print(trace, ctx); flint_printf("\n"); ca_print(t, ctx); flint_printf("\n"); flint_printf("Equal: "); truth_print(ca_check_equal(trace, t, ctx)); flint_printf("\n\n"); flint_printf("Det:\n"); ca_one(t, ctx); for (i = 0; i < n; i++) ca_mul(t, t, ca_vec_entry(eig, i), ctx); ca_print(det, ctx); flint_printf("\n"); ca_print(t, ctx); flint_printf("\n"); flint_printf("Equal: "); truth_print(ca_check_equal(det, t, ctx)); flint_printf("\n\n"); ca_mat_clear(mat, ctx); ca_vec_clear(eig, ctx); flint_free(mul); ca_clear(trace, ctx); ca_clear(det, ctx); ca_clear(t, ctx); ca_ctx_clear(ctx); } flint_printf("\n"); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE flint_cleanup(); return 0; } flint-3.1.3/examples/huge_expr.c000066400000000000000000007111071461254215100166120ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include "profiler.h" #include "ca.h" #include "gr.h" int gr_sqrt_ui(gr_ptr x, ulong y, gr_ctx_t ctx) { int status = gr_set_ui(x, y, ctx); status |= gr_sqrt(x, x, ctx); return status; } void CONST_I(gr_ptr r, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_i(r, ctx)); } void SET_SI(gr_ptr r, slong x, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_set_si(r, x, ctx)); } void NEG(gr_ptr r, gr_srcptr x, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_neg(r, x, ctx)); } void ABS(gr_ptr r, gr_srcptr x, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_abs(r, x, ctx)); } void INV(gr_ptr r, gr_srcptr x, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_inv(r, x, ctx)); } void SQRT(gr_ptr r, gr_srcptr x, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_sqrt(r, x, ctx)); } void ADD(gr_ptr r, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_add(r, x, y, ctx)); } void SUB(gr_ptr r, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_sub(r, x, y, ctx)); } void MUL(gr_ptr r, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_mul(r, x, y, ctx)); } void DIV(gr_ptr r, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_div(r, x, y, ctx)); } void POW(gr_ptr r, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_pow(r, x, y, ctx)); } void ADD_SI(gr_ptr r, gr_srcptr x, slong y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_add_si(r, x, y, ctx)); } void SUB_SI(gr_ptr r, gr_srcptr x, slong y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_sub_si(r, x, y, ctx)); } void MUL_SI(gr_ptr r, gr_srcptr x, slong y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_mul_si(r, x, y, ctx)); } void DIV_SI(gr_ptr r, gr_srcptr x, slong y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_div_si(r, x, y, ctx)); } void SQRT_UI(gr_ptr r, ulong x, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_sqrt_ui(r, x, ctx)); } void POW_UI(gr_ptr r, gr_srcptr x, ulong y, gr_ctx_t ctx) { GR_MUST_SUCCEED(gr_pow_ui(r, x, y, ctx)); } void doit(gr_ctx_t ctx) { gr_ptr N, M, E; gr_ptr tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19, tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27, tmp28, tmp29, tmp30, tmp31, tmp32, tmp33, tmp34; truth_t equal; int status = GR_SUCCESS; gr_ctx_println(ctx); GR_TMP_INIT3(N, M, E, ctx); GR_TMP_INIT5(tmp0, tmp1, tmp2, tmp3, tmp4, ctx); GR_TMP_INIT5(tmp5, tmp6, tmp7, tmp8, tmp9, ctx); GR_TMP_INIT5(tmp10, tmp11, tmp12, tmp13, tmp14, ctx); GR_TMP_INIT5(tmp15, tmp16, tmp17, tmp18, tmp19, ctx); GR_TMP_INIT5(tmp20, tmp21, tmp22, tmp23, tmp24, ctx); GR_TMP_INIT5(tmp25, tmp26, tmp27, tmp28, tmp29, ctx); GR_TMP_INIT5(tmp30, tmp31, tmp32, tmp33, tmp34, ctx); flint_printf("Evaluating N...\n"); TIMEIT_ONCE_START SET_SI(tmp3, 1, ctx); DIV_SI(tmp3, tmp3, 16, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, 7, ctx); SUB_SI(tmp11, tmp11, 10, ctx); MUL_SI(tmp11, tmp11, 44, ctx); SQRT_UI(tmp12, 2, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -17, ctx); ADD_SI(tmp11, tmp11, 26, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 7, ctx); SUB_SI(tmp16, tmp16, 10, ctx); MUL_SI(tmp16, tmp16, 11, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -17, ctx); ADD_SI(tmp16, tmp16, 26, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 63, ctx); SUB_SI(tmp16, tmp16, 89, ctx); MUL_SI(tmp16, tmp16, 10, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SUB(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 3, ctx); SUB_SI(tmp18, tmp18, 4, ctx); MUL_SI(tmp18, tmp18, 3, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 85, ctx); SUB_SI(tmp18, tmp18, 122, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); NEG(tmp16, tmp16, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SUB(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SUB_SI(tmp19, tmp19, 4, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 85, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 122, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 7, ctx); SUB_SI(tmp18, tmp18, 10, ctx); MUL_SI(tmp18, tmp18, 11, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 630, ctx); ADD(tmp14, tmp15, tmp16, ctx); SUB_SI(tmp14, tmp14, 890, ctx); MUL_SI(tmp14, tmp14, 2, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); SUB_SI(tmp15, tmp15, 1, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); ADD(tmp11, tmp12, tmp13, ctx); MUL_SI(tmp11, tmp11, 2, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 3, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, -17, ctx); ADD_SI(tmp14, tmp14, 26, ctx); SQRT(tmp14, tmp14, ctx); ADD(tmp12, tmp13, tmp14, ctx); SUB_SI(tmp12, tmp12, 3, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); ADD(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 63, ctx); SUB_SI(tmp10, tmp10, 89, ctx); MUL_SI(tmp10, tmp10, 40, ctx); SQRT_UI(tmp11, 2, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SUB(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 3, ctx); SUB_SI(tmp12, tmp12, 4, ctx); MUL_SI(tmp12, tmp12, 3, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, -17, ctx); ADD_SI(tmp12, tmp12, 26, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 85, ctx); SUB_SI(tmp12, tmp12, 122, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SUB(tmp9, tmp10, tmp11, ctx); MUL_SI(tmp9, tmp9, 4, ctx); SQRT_UI(tmp10, 2, ctx); NEG(tmp10, tmp10, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SUB(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 5, ctx); SUB_SI(tmp14, tmp14, 7, ctx); MUL_SI(tmp14, tmp14, 22, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, -17, ctx); ADD_SI(tmp14, tmp14, 26, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 5, ctx); SUB_SI(tmp19, tmp19, 7, ctx); MUL_SI(tmp19, tmp19, 11, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 89, ctx); SUB_SI(tmp19, tmp19, 126, ctx); MUL_SI(tmp19, tmp19, 5, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SUB_SI(tmp21, tmp21, 3, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 61, ctx); SUB_SI(tmp21, tmp21, 85, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SUB_SI(tmp22, tmp22, 3, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 61, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 85, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 5, ctx); SUB_SI(tmp21, tmp21, 7, ctx); MUL_SI(tmp21, tmp21, 11, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 445, ctx); ADD(tmp17, tmp18, tmp19, ctx); SUB_SI(tmp17, tmp17, 630, ctx); MUL_SI(tmp17, tmp17, 2, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 1, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 3, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -17, ctx); ADD_SI(tmp17, tmp17, 26, ctx); SQRT(tmp17, tmp17, ctx); ADD(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 3, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); ADD(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 89, ctx); SUB_SI(tmp13, tmp13, 126, ctx); MUL_SI(tmp13, tmp13, 10, ctx); SQRT_UI(tmp14, 2, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 2, ctx); SUB_SI(tmp15, tmp15, 3, ctx); MUL_SI(tmp15, tmp15, 3, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, -17, ctx); ADD_SI(tmp15, tmp15, 26, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 61, ctx); SUB_SI(tmp15, tmp15, 85, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SUB(tmp12, tmp13, tmp14, ctx); MUL_SI(tmp12, tmp12, 2, ctx); SQRT_UI(tmp13, 2, ctx); NEG(tmp13, tmp13, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SUB(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 2, ctx); SUB_SI(tmp16, tmp16, 3, ctx); MUL_SI(tmp16, tmp16, 3, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -17, ctx); ADD_SI(tmp17, tmp17, 26, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 61, ctx); SUB(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 85, ctx); SQRT_UI(tmp15, 2, ctx); NEG(tmp15, tmp15, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 5, ctx); SUB_SI(tmp15, tmp15, 7, ctx); MUL_SI(tmp15, tmp15, 11, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -17, ctx); ADD_SI(tmp16, tmp16, 26, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SUB(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 445, ctx); ADD(tmp11, tmp12, tmp13, ctx); SUB_SI(tmp11, tmp11, 630, ctx); MUL_SI(tmp11, tmp11, 4, ctx); SQRT_UI(tmp12, 2, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); SUB_SI(tmp12, tmp12, 1, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); ADD(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -12, ctx); SQRT_UI(tmp12, 2, ctx); NEG(tmp12, tmp12, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); MUL_SI(tmp12, tmp12, 2, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -17, ctx); ADD_SI(tmp11, tmp11, 26, ctx); SQRT(tmp11, tmp11, ctx); MUL_SI(tmp11, tmp11, 2, ctx); SUB(tmp9, tmp10, tmp11, ctx); ADD_SI(tmp9, tmp9, 24, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); ADD(tmp5, tmp6, tmp7, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 3, ctx); SUB_SI(tmp12, tmp12, 4, ctx); MUL_SI(tmp12, tmp12, 3, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 85, ctx); SUB(tmp10, tmp11, tmp12, ctx); ADD_SI(tmp10, tmp10, 122, ctx); SQRT_UI(tmp11, 2, ctx); NEG(tmp11, tmp11, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, 7, ctx); SUB_SI(tmp11, tmp11, 10, ctx); MUL_SI(tmp11, tmp11, 11, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, -17, ctx); ADD_SI(tmp12, tmp12, 26, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); SUB(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, 630, ctx); ADD(tmp7, tmp8, tmp9, ctx); SUB_SI(tmp7, tmp7, 890, ctx); MUL_SI(tmp7, tmp7, 8, ctx); SQRT_UI(tmp8, 2, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); SUB_SI(tmp8, tmp8, 1, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); ADD(tmp4, tmp5, tmp6, ctx); MUL(tmp2, tmp3, tmp4, ctx); SQRT_UI(tmp11, 2, ctx); SQRT_UI(tmp12, 2, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); SUB(tmp9, tmp10, tmp11, ctx); SUB_SI(tmp9, tmp9, 1, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); SUB_SI(tmp10, tmp10, 1, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); ADD(tmp7, tmp8, tmp9, ctx); SUB_SI(tmp7, tmp7, 1, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 89, ctx); SUB_SI(tmp18, tmp18, 126, ctx); MUL_SI(tmp18, tmp18, 5, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 61, ctx); SUB_SI(tmp22, tmp22, 85, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SUB_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 4, ctx); SUB(tmp23, tmp24, tmp25, ctx); ADD_SI(tmp23, tmp23, 6, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 122, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 170, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 5, ctx); SUB_SI(tmp20, tmp20, 7, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 10, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 14, ctx); MUL_SI(tmp18, tmp18, 11, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 890, ctx); SUB(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 1260, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 3, ctx); SQRT_UI(tmp17, 2, ctx); NEG(tmp17, tmp17, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); ADD(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 5, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -12, ctx); SQRT_UI(tmp17, 2, ctx); NEG(tmp17, tmp17, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL_SI(tmp17, tmp17, 2, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -17, ctx); ADD_SI(tmp16, tmp16, 26, ctx); SQRT(tmp16, tmp16, ctx); MUL_SI(tmp16, tmp16, 2, ctx); SUB(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 24, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 63, ctx); SUB_SI(tmp18, tmp18, 89, ctx); MUL_SI(tmp18, tmp18, 10, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 85, ctx); SUB_SI(tmp22, tmp22, 122, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SUB_SI(tmp25, tmp25, 4, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 6, ctx); SUB(tmp23, tmp24, tmp25, ctx); ADD_SI(tmp23, tmp23, 8, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 170, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 244, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 7, ctx); SUB_SI(tmp20, tmp20, 10, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 14, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 20, ctx); MUL_SI(tmp18, tmp18, 11, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 1260, ctx); SUB(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 1780, ctx); MUL_SI(tmp14, tmp14, 2, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 3, ctx); SQRT_UI(tmp17, 2, ctx); NEG(tmp17, tmp17, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); ADD(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 5, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); ADD(tmp11, tmp12, tmp13, ctx); MUL_SI(tmp11, tmp11, 8, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); ADD_SI(tmp15, tmp15, 1, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); SUB_SI(tmp16, tmp16, 1, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); ADD(tmp13, tmp14, tmp15, ctx); ADD_SI(tmp13, tmp13, 1, ctx); INV(tmp13, tmp13, ctx); SQRT_UI(tmp21, 2, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); SUB_SI(tmp21, tmp21, 1, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 3, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 5, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 8, ctx); SQRT_UI(tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 5, ctx); ADD(tmp18, tmp19, tmp20, ctx); SUB_SI(tmp18, tmp18, 8, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); ADD_SI(tmp17, tmp17, 2, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 1, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); SUB_SI(tmp21, tmp21, 1, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 1, ctx); POW_UI(tmp18, tmp18, 2, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 1, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp28, 2, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); ADD(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); SUB_SI(tmp28, tmp28, 1, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 3, ctx); ADD(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 8, ctx); SQRT_UI(tmp29, 2, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); ADD(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); SUB_SI(tmp29, tmp29, 1, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SUB(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL_SI(tmp27, tmp27, 5, ctx); ADD(tmp25, tmp26, tmp27, ctx); SUB_SI(tmp25, tmp25, 8, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); ADD_SI(tmp24, tmp24, 2, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 1, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); SUB_SI(tmp27, tmp27, 1, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 1, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 2, ctx); POW_UI(tmp25, tmp25, 3, ctx); MUL(tmp23, tmp24, tmp25, ctx); DIV(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 1, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 2, ctx); POW_UI(tmp18, tmp18, 3, ctx); MUL(tmp16, tmp17, tmp18, ctx); DIV(tmp14, tmp15, tmp16, ctx); ADD(tmp12, tmp13, tmp14, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SUB_SI(tmp23, tmp23, 4, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 85, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 122, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 7, ctx); SUB_SI(tmp22, tmp22, 10, ctx); MUL_SI(tmp22, tmp22, 11, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 630, ctx); ADD(tmp18, tmp19, tmp20, ctx); SUB_SI(tmp18, tmp18, 890, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 3, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 3, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 1, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 4896, ctx); SUB_SI(tmp18, tmp18, 6923, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 79, ctx); SUB_SI(tmp20, tmp20, 112, ctx); MUL_SI(tmp20, tmp20, 20, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 27, ctx); SUB_SI(tmp23, tmp23, 38, ctx); MUL_SI(tmp23, tmp23, 7, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 342, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 484, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 2820, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 3992, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SUB_SI(tmp27, tmp27, 3, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 61, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 85, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB_SI(tmp26, tmp26, 7, ctx); MUL_SI(tmp26, tmp26, 11, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 445, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 630, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 3, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 89, ctx); SUB_SI(tmp22, tmp22, 126, ctx); MUL_SI(tmp22, tmp22, 10, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 61, ctx); SUB_SI(tmp24, tmp24, 85, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SUB_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 3, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 61, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 85, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB_SI(tmp22, tmp22, 7, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 7, ctx); MUL_SI(tmp20, tmp20, 22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 890, ctx); ADD(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 1260, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -12, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 24, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 319, ctx); SUB_SI(tmp17, tmp17, 452, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 561, ctx); SUB(tmp15, tmp16, tmp17, ctx); ADD_SI(tmp15, tmp15, 794, ctx); MUL_SI(tmp15, tmp15, 4, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -17, ctx); ADD_SI(tmp16, tmp16, 26, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); ADD(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 17064, ctx); ADD(tmp11, tmp12, tmp13, ctx); SUB_SI(tmp11, tmp11, 24132, ctx); DIV(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 7, ctx); SUB_SI(tmp20, tmp20, 10, ctx); MUL_SI(tmp20, tmp20, 44, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 7, ctx); SUB_SI(tmp25, tmp25, 10, ctx); MUL_SI(tmp25, tmp25, 11, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 63, ctx); SUB_SI(tmp25, tmp25, 89, ctx); MUL_SI(tmp25, tmp25, 10, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SUB_SI(tmp27, tmp27, 4, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 85, ctx); SUB_SI(tmp27, tmp27, 122, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); NEG(tmp25, tmp25, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SUB_SI(tmp28, tmp28, 4, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 85, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 122, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 7, ctx); SUB_SI(tmp27, tmp27, 10, ctx); MUL_SI(tmp27, tmp27, 11, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 630, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 890, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); SUB_SI(tmp24, tmp24, 1, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); ADD(tmp20, tmp21, tmp22, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); ADD(tmp21, tmp22, tmp23, ctx); SUB_SI(tmp21, tmp21, 3, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 63, ctx); SUB_SI(tmp19, tmp19, 89, ctx); MUL_SI(tmp19, tmp19, 40, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SUB_SI(tmp21, tmp21, 4, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 85, ctx); SUB_SI(tmp21, tmp21, 122, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); MUL_SI(tmp18, tmp18, 4, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB_SI(tmp23, tmp23, 7, ctx); MUL_SI(tmp23, tmp23, 22, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 5, ctx); SUB_SI(tmp28, tmp28, 7, ctx); MUL_SI(tmp28, tmp28, 11, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 89, ctx); SUB_SI(tmp28, tmp28, 126, ctx); MUL_SI(tmp28, tmp28, 5, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SUB(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, 2, ctx); SUB_SI(tmp30, tmp30, 3, ctx); MUL_SI(tmp30, tmp30, 3, ctx); SQRT_UI(tmp31, 2, ctx); ADD_SI(tmp31, tmp31, 2, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, 61, ctx); SUB_SI(tmp30, tmp30, 85, ctx); SQRT_UI(tmp31, 2, ctx); ADD_SI(tmp31, tmp31, 2, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); NEG(tmp28, tmp28, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB_SI(tmp31, tmp31, 3, ctx); MUL_SI(tmp31, tmp31, 3, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, -17, ctx); ADD_SI(tmp32, tmp32, 26, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 61, ctx); SUB(tmp29, tmp30, tmp31, ctx); ADD_SI(tmp29, tmp29, 85, ctx); SQRT_UI(tmp30, 2, ctx); NEG(tmp30, tmp30, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, 5, ctx); SUB_SI(tmp30, tmp30, 7, ctx); MUL_SI(tmp30, tmp30, 11, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, -17, ctx); ADD_SI(tmp31, tmp31, 26, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 445, ctx); ADD(tmp26, tmp27, tmp28, ctx); SUB_SI(tmp26, tmp26, 630, ctx); MUL_SI(tmp26, tmp26, 2, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); SUB_SI(tmp27, tmp27, 1, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); ADD(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SUB_SI(tmp24, tmp24, 3, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); ADD(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 89, ctx); SUB_SI(tmp22, tmp22, 126, ctx); MUL_SI(tmp22, tmp22, 10, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SUB_SI(tmp24, tmp24, 3, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 61, ctx); SUB_SI(tmp24, tmp24, 85, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SUB(tmp21, tmp22, tmp23, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SUB_SI(tmp25, tmp25, 3, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 61, ctx); SUB(tmp23, tmp24, tmp25, ctx); ADD_SI(tmp23, tmp23, 85, ctx); SQRT_UI(tmp24, 2, ctx); NEG(tmp24, tmp24, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 5, ctx); SUB_SI(tmp24, tmp24, 7, ctx); MUL_SI(tmp24, tmp24, 11, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 445, ctx); ADD(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 630, ctx); MUL_SI(tmp20, tmp20, 4, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); SUB_SI(tmp21, tmp21, 1, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -12, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 24, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SUB_SI(tmp21, tmp21, 4, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 85, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 122, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 7, ctx); SUB_SI(tmp20, tmp20, 10, ctx); MUL_SI(tmp20, tmp20, 11, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 630, ctx); ADD(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 890, ctx); MUL_SI(tmp16, tmp16, 8, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); SUB_SI(tmp17, tmp17, 1, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp18, 2, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 1, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 3, ctx); ADD(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL_SI(tmp16, tmp16, 5, ctx); SUB(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 8, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SUB_SI(tmp27, tmp27, 4, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 85, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 122, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 7, ctx); SUB_SI(tmp26, tmp26, 10, ctx); MUL_SI(tmp26, tmp26, 11, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 630, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 890, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 3, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 4896, ctx); SUB_SI(tmp22, tmp22, 6923, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 79, ctx); SUB_SI(tmp24, tmp24, 112, ctx); MUL_SI(tmp24, tmp24, 20, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 27, ctx); SUB_SI(tmp27, tmp27, 38, ctx); MUL_SI(tmp27, tmp27, 7, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 342, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 484, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 2820, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 3992, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB_SI(tmp31, tmp31, 3, ctx); MUL_SI(tmp31, tmp31, 3, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, -17, ctx); ADD_SI(tmp32, tmp32, 26, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 61, ctx); SUB(tmp29, tmp30, tmp31, ctx); ADD_SI(tmp29, tmp29, 85, ctx); SQRT_UI(tmp30, 2, ctx); NEG(tmp30, tmp30, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, 5, ctx); SUB_SI(tmp30, tmp30, 7, ctx); MUL_SI(tmp30, tmp30, 11, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, -17, ctx); ADD_SI(tmp31, tmp31, 26, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 445, ctx); ADD(tmp26, tmp27, tmp28, ctx); SUB_SI(tmp26, tmp26, 630, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); ADD(tmp27, tmp28, tmp29, ctx); SUB_SI(tmp27, tmp27, 3, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); SUB_SI(tmp26, tmp26, 1, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 89, ctx); SUB_SI(tmp26, tmp26, 126, ctx); MUL_SI(tmp26, tmp26, 10, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 61, ctx); SUB_SI(tmp28, tmp28, 85, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB_SI(tmp31, tmp31, 3, ctx); SQRT_UI(tmp32, 2, ctx); ADD_SI(tmp32, tmp32, 2, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB(tmp29, tmp30, tmp31, ctx); ADD_SI(tmp29, tmp29, 3, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SUB(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 61, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 85, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB_SI(tmp26, tmp26, 7, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 7, ctx); MUL_SI(tmp24, tmp24, 22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 890, ctx); ADD(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 1260, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -12, ctx); SQRT_UI(tmp24, 2, ctx); NEG(tmp24, tmp24, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 24, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 319, ctx); SUB_SI(tmp21, tmp21, 452, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 561, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 794, ctx); MUL_SI(tmp19, tmp19, 4, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); ADD(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 17064, ctx); ADD(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 24132, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 1, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 1, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 1, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp24, 2, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); ADD(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); SUB_SI(tmp24, tmp24, 1, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 3, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 8, ctx); SQRT_UI(tmp25, 2, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 1, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL_SI(tmp23, tmp23, 5, ctx); ADD(tmp21, tmp22, tmp23, ctx); SUB_SI(tmp21, tmp21, 8, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 1, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 1, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); SUB_SI(tmp21, tmp21, 2, ctx); POW_UI(tmp21, tmp21, 3, ctx); MUL(tmp19, tmp20, tmp21, ctx); DIV(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 1, ctx); MUL(tmp13, tmp14, tmp15, ctx); SET_SI(tmp17, 1, ctx); DIV_SI(tmp17, tmp17, 4, ctx); NEG(tmp17, tmp17, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SET_SI(tmp17, 1, ctx); DIV_SI(tmp17, tmp17, 2, ctx); ADD(tmp15, tmp16, tmp17, ctx); SET_SI(tmp16, 3, ctx); DIV_SI(tmp16, tmp16, 2, ctx); POW(tmp14, tmp15, tmp16, ctx); MUL(tmp12, tmp13, tmp14, ctx); DIV(tmp10, tmp11, tmp12, ctx); ADD(tmp8, tmp9, tmp10, ctx); MUL(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp7, 2, ctx); ADD_SI(tmp7, tmp7, 2, ctx); SQRT(tmp7, tmp7, ctx); ADD_SI(tmp7, tmp7, 2, ctx); SQRT(tmp7, tmp7, ctx); MUL(tmp5, tmp6, tmp7, ctx); SET_SI(tmp8, 1, ctx); DIV_SI(tmp8, tmp8, 4, ctx); NEG(tmp8, tmp8, ctx); SQRT_UI(tmp9, 2, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); SET_SI(tmp8, 1, ctx); DIV_SI(tmp8, tmp8, 2, ctx); ADD(tmp6, tmp7, tmp8, ctx); SQRT(tmp6, tmp6, ctx); DIV(tmp4, tmp5, tmp6, ctx); SQRT_UI(tmp11, 2, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); SQRT_UI(tmp12, 2, ctx); SUB_SI(tmp12, tmp12, 1, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); SUB_SI(tmp11, tmp11, 1, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); SUB(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); ADD(tmp7, tmp8, tmp9, ctx); MUL_SI(tmp7, tmp7, 2, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 7, ctx); SUB_SI(tmp18, tmp18, 10, ctx); MUL_SI(tmp18, tmp18, 44, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 7, ctx); SUB_SI(tmp23, tmp23, 10, ctx); MUL_SI(tmp23, tmp23, 11, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 63, ctx); SUB_SI(tmp23, tmp23, 89, ctx); MUL_SI(tmp23, tmp23, 10, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SUB_SI(tmp25, tmp25, 4, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 85, ctx); SUB_SI(tmp25, tmp25, 122, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SUB_SI(tmp26, tmp26, 4, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 85, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 122, ctx); SQRT_UI(tmp25, 2, ctx); NEG(tmp25, tmp25, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 7, ctx); SUB_SI(tmp25, tmp25, 10, ctx); MUL_SI(tmp25, tmp25, 11, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 630, ctx); ADD(tmp21, tmp22, tmp23, ctx); SUB_SI(tmp21, tmp21, 890, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 3, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 3, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 63, ctx); SUB_SI(tmp17, tmp17, 89, ctx); MUL_SI(tmp17, tmp17, 40, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SUB(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SUB_SI(tmp19, tmp19, 4, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 85, ctx); SUB_SI(tmp19, tmp19, 122, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); MUL_SI(tmp16, tmp16, 4, ctx); SQRT_UI(tmp17, 2, ctx); NEG(tmp17, tmp17, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SUB(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 5, ctx); SUB_SI(tmp21, tmp21, 7, ctx); MUL_SI(tmp21, tmp21, 22, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB_SI(tmp26, tmp26, 7, ctx); MUL_SI(tmp26, tmp26, 11, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 89, ctx); SUB_SI(tmp26, tmp26, 126, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB_SI(tmp28, tmp28, 3, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 61, ctx); SUB_SI(tmp28, tmp28, 85, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SUB(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 2, ctx); SUB_SI(tmp29, tmp29, 3, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 61, ctx); SUB(tmp27, tmp28, tmp29, ctx); ADD_SI(tmp27, tmp27, 85, ctx); SQRT_UI(tmp28, 2, ctx); NEG(tmp28, tmp28, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 5, ctx); SUB_SI(tmp28, tmp28, 7, ctx); MUL_SI(tmp28, tmp28, 11, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SUB(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 445, ctx); ADD(tmp24, tmp25, tmp26, ctx); SUB_SI(tmp24, tmp24, 630, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 1, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 3, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 89, ctx); SUB_SI(tmp20, tmp20, 126, ctx); MUL_SI(tmp20, tmp20, 10, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SUB_SI(tmp22, tmp22, 3, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 61, ctx); SUB_SI(tmp22, tmp22, 85, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SUB_SI(tmp23, tmp23, 3, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 61, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 85, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB_SI(tmp22, tmp22, 7, ctx); MUL_SI(tmp22, tmp22, 11, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 445, ctx); ADD(tmp18, tmp19, tmp20, ctx); SUB_SI(tmp18, tmp18, 630, ctx); MUL_SI(tmp18, tmp18, 4, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -12, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 24, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); ADD(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SUB_SI(tmp19, tmp19, 4, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 85, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 122, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 7, ctx); SUB_SI(tmp18, tmp18, 10, ctx); MUL_SI(tmp18, tmp18, 11, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 630, ctx); ADD(tmp14, tmp15, tmp16, ctx); SUB_SI(tmp14, tmp14, 890, ctx); MUL_SI(tmp14, tmp14, 8, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); SUB_SI(tmp15, tmp15, 1, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SUB(tmp11, tmp12, tmp13, ctx); MUL_SI(tmp11, tmp11, 8, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); ADD_SI(tmp15, tmp15, 1, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); SUB_SI(tmp16, tmp16, 1, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); ADD(tmp13, tmp14, tmp15, ctx); ADD_SI(tmp13, tmp13, 1, ctx); INV(tmp13, tmp13, ctx); SQRT_UI(tmp21, 2, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); SUB_SI(tmp21, tmp21, 1, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 3, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 5, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 8, ctx); SQRT_UI(tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 5, ctx); ADD(tmp18, tmp19, tmp20, ctx); SUB_SI(tmp18, tmp18, 8, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); ADD_SI(tmp17, tmp17, 2, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 1, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); SUB_SI(tmp21, tmp21, 1, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 1, ctx); POW_UI(tmp18, tmp18, 2, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 1, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp28, 2, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); ADD(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); SUB_SI(tmp28, tmp28, 1, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 3, ctx); ADD(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 8, ctx); SQRT_UI(tmp29, 2, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); ADD(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); SUB_SI(tmp29, tmp29, 1, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SUB(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL_SI(tmp27, tmp27, 5, ctx); ADD(tmp25, tmp26, tmp27, ctx); SUB_SI(tmp25, tmp25, 8, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); ADD_SI(tmp24, tmp24, 2, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 1, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); SUB_SI(tmp27, tmp27, 1, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 1, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 2, ctx); POW_UI(tmp25, tmp25, 3, ctx); MUL(tmp23, tmp24, tmp25, ctx); DIV(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 1, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 2, ctx); POW_UI(tmp18, tmp18, 3, ctx); MUL(tmp16, tmp17, tmp18, ctx); DIV(tmp14, tmp15, tmp16, ctx); ADD(tmp12, tmp13, tmp14, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SUB_SI(tmp23, tmp23, 4, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 85, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 122, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 7, ctx); SUB_SI(tmp22, tmp22, 10, ctx); MUL_SI(tmp22, tmp22, 11, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 630, ctx); ADD(tmp18, tmp19, tmp20, ctx); SUB_SI(tmp18, tmp18, 890, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 3, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 3, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 1, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 4896, ctx); SUB_SI(tmp18, tmp18, 6923, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 79, ctx); SUB_SI(tmp20, tmp20, 112, ctx); MUL_SI(tmp20, tmp20, 20, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 27, ctx); SUB_SI(tmp23, tmp23, 38, ctx); MUL_SI(tmp23, tmp23, 7, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 342, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 484, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 2820, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 3992, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SUB_SI(tmp27, tmp27, 3, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 61, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 85, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB_SI(tmp26, tmp26, 7, ctx); MUL_SI(tmp26, tmp26, 11, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 445, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 630, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 3, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 89, ctx); SUB_SI(tmp22, tmp22, 126, ctx); MUL_SI(tmp22, tmp22, 10, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 61, ctx); SUB_SI(tmp24, tmp24, 85, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SUB_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 3, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 61, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 85, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB_SI(tmp22, tmp22, 7, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 7, ctx); MUL_SI(tmp20, tmp20, 22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 890, ctx); ADD(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 1260, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -12, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 24, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 319, ctx); SUB_SI(tmp17, tmp17, 452, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 561, ctx); SUB(tmp15, tmp16, tmp17, ctx); ADD_SI(tmp15, tmp15, 794, ctx); MUL_SI(tmp15, tmp15, 4, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -17, ctx); ADD_SI(tmp16, tmp16, 26, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); ADD(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 17064, ctx); ADD(tmp11, tmp12, tmp13, ctx); SUB_SI(tmp11, tmp11, 24132, ctx); DIV(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 89, ctx); SUB_SI(tmp20, tmp20, 126, ctx); MUL_SI(tmp20, tmp20, 5, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 61, ctx); SUB_SI(tmp24, tmp24, 85, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SUB_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 4, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 6, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 122, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 170, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB_SI(tmp22, tmp22, 7, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 10, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 14, ctx); MUL_SI(tmp20, tmp20, 11, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 890, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 1260, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 3, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD(tmp17, tmp18, tmp19, ctx); SUB_SI(tmp17, tmp17, 5, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -12, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 24, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 63, ctx); SUB_SI(tmp20, tmp20, 89, ctx); MUL_SI(tmp20, tmp20, 10, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 85, ctx); SUB_SI(tmp24, tmp24, 122, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SUB_SI(tmp27, tmp27, 4, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 6, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 8, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 170, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 244, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 7, ctx); SUB_SI(tmp22, tmp22, 10, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 14, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 20, ctx); MUL_SI(tmp20, tmp20, 11, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 1260, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 1780, ctx); MUL_SI(tmp16, tmp16, 2, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 3, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD(tmp17, tmp18, tmp19, ctx); SUB_SI(tmp17, tmp17, 5, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp18, 2, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 1, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 3, ctx); ADD(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL_SI(tmp16, tmp16, 5, ctx); SUB(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 8, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SUB_SI(tmp27, tmp27, 4, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 85, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 122, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 7, ctx); SUB_SI(tmp26, tmp26, 10, ctx); MUL_SI(tmp26, tmp26, 11, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 630, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 890, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 3, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 4896, ctx); SUB_SI(tmp22, tmp22, 6923, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 79, ctx); SUB_SI(tmp24, tmp24, 112, ctx); MUL_SI(tmp24, tmp24, 20, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 27, ctx); SUB_SI(tmp27, tmp27, 38, ctx); MUL_SI(tmp27, tmp27, 7, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 342, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 484, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 2820, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 3992, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB_SI(tmp31, tmp31, 3, ctx); MUL_SI(tmp31, tmp31, 3, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, -17, ctx); ADD_SI(tmp32, tmp32, 26, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 61, ctx); SUB(tmp29, tmp30, tmp31, ctx); ADD_SI(tmp29, tmp29, 85, ctx); SQRT_UI(tmp30, 2, ctx); NEG(tmp30, tmp30, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, 5, ctx); SUB_SI(tmp30, tmp30, 7, ctx); MUL_SI(tmp30, tmp30, 11, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, -17, ctx); ADD_SI(tmp31, tmp31, 26, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 445, ctx); ADD(tmp26, tmp27, tmp28, ctx); SUB_SI(tmp26, tmp26, 630, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); ADD(tmp27, tmp28, tmp29, ctx); SUB_SI(tmp27, tmp27, 3, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); SUB_SI(tmp26, tmp26, 1, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 89, ctx); SUB_SI(tmp26, tmp26, 126, ctx); MUL_SI(tmp26, tmp26, 10, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 61, ctx); SUB_SI(tmp28, tmp28, 85, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB_SI(tmp31, tmp31, 3, ctx); SQRT_UI(tmp32, 2, ctx); ADD_SI(tmp32, tmp32, 2, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB(tmp29, tmp30, tmp31, ctx); ADD_SI(tmp29, tmp29, 3, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SUB(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 61, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 85, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB_SI(tmp26, tmp26, 7, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 5, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 7, ctx); MUL_SI(tmp24, tmp24, 22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 890, ctx); ADD(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 1260, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -12, ctx); SQRT_UI(tmp24, 2, ctx); NEG(tmp24, tmp24, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 24, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 319, ctx); SUB_SI(tmp21, tmp21, 452, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 561, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 794, ctx); MUL_SI(tmp19, tmp19, 4, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); ADD(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 17064, ctx); ADD(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 24132, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 1, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 1, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 1, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp24, 2, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); ADD(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); SUB_SI(tmp24, tmp24, 1, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 3, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 8, ctx); SQRT_UI(tmp25, 2, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 1, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL_SI(tmp23, tmp23, 5, ctx); ADD(tmp21, tmp22, tmp23, ctx); SUB_SI(tmp21, tmp21, 8, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 1, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); ADD(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 1, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); SUB_SI(tmp21, tmp21, 2, ctx); POW_UI(tmp21, tmp21, 3, ctx); MUL(tmp19, tmp20, tmp21, ctx); DIV(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 1, ctx); MUL(tmp13, tmp14, tmp15, ctx); SET_SI(tmp17, 1, ctx); DIV_SI(tmp17, tmp17, 4, ctx); NEG(tmp17, tmp17, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SET_SI(tmp17, 1, ctx); DIV_SI(tmp17, tmp17, 2, ctx); ADD(tmp15, tmp16, tmp17, ctx); SET_SI(tmp16, 3, ctx); DIV_SI(tmp16, tmp16, 2, ctx); POW(tmp14, tmp15, tmp16, ctx); MUL(tmp12, tmp13, tmp14, ctx); DIV(tmp10, tmp11, tmp12, ctx); ADD(tmp8, tmp9, tmp10, ctx); MUL(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp7, 2, ctx); ADD_SI(tmp7, tmp7, 2, ctx); SQRT(tmp7, tmp7, ctx); SUB_SI(tmp7, tmp7, 2, ctx); DIV(tmp5, tmp6, tmp7, ctx); ADD(tmp3, tmp4, tmp5, ctx); MUL(tmp1, tmp2, tmp3, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 3, ctx); SUB_SI(tmp14, tmp14, 4, ctx); MUL_SI(tmp14, tmp14, 3, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, -17, ctx); ADD_SI(tmp15, tmp15, 26, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 85, ctx); SUB(tmp12, tmp13, tmp14, ctx); ADD_SI(tmp12, tmp12, 122, ctx); SQRT_UI(tmp13, 2, ctx); NEG(tmp13, tmp13, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 7, ctx); SUB_SI(tmp13, tmp13, 10, ctx); MUL_SI(tmp13, tmp13, 11, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, -17, ctx); ADD_SI(tmp14, tmp14, 26, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, 630, ctx); ADD(tmp9, tmp10, tmp11, ctx); SUB_SI(tmp9, tmp9, 890, ctx); MUL_SI(tmp9, tmp9, 2, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, 3, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, -17, ctx); ADD_SI(tmp12, tmp12, 26, ctx); SQRT(tmp12, tmp12, ctx); ADD(tmp10, tmp11, tmp12, ctx); SUB_SI(tmp10, tmp10, 3, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); SUB_SI(tmp9, tmp9, 1, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, 4896, ctx); SUB_SI(tmp9, tmp9, 6923, ctx); MUL_SI(tmp9, tmp9, 2, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SUB(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, 79, ctx); SUB_SI(tmp11, tmp11, 112, ctx); MUL_SI(tmp11, tmp11, 20, ctx); SQRT_UI(tmp12, 2, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 27, ctx); SUB_SI(tmp14, tmp14, 38, ctx); MUL_SI(tmp14, tmp14, 7, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 342, ctx); SUB(tmp12, tmp13, tmp14, ctx); ADD_SI(tmp12, tmp12, 484, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SUB(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 2820, ctx); SUB(tmp8, tmp9, tmp10, ctx); ADD_SI(tmp8, tmp8, 3992, ctx); SQRT_UI(tmp9, 2, ctx); NEG(tmp9, tmp9, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); ADD(tmp5, tmp6, tmp7, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SUB_SI(tmp18, tmp18, 3, ctx); MUL_SI(tmp18, tmp18, 3, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 61, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 85, ctx); SQRT_UI(tmp17, 2, ctx); NEG(tmp17, tmp17, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 5, ctx); SUB_SI(tmp17, tmp17, 7, ctx); MUL_SI(tmp17, tmp17, 11, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SUB(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 445, ctx); ADD(tmp13, tmp14, tmp15, ctx); SUB_SI(tmp13, tmp13, 630, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 3, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -17, ctx); ADD_SI(tmp16, tmp16, 26, ctx); SQRT(tmp16, tmp16, ctx); ADD(tmp14, tmp15, tmp16, ctx); SUB_SI(tmp14, tmp14, 3, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); SUB_SI(tmp13, tmp13, 1, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 89, ctx); SUB_SI(tmp13, tmp13, 126, ctx); MUL_SI(tmp13, tmp13, 10, ctx); SQRT_UI(tmp14, 2, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 61, ctx); SUB_SI(tmp15, tmp15, 85, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SUB_SI(tmp18, tmp18, 3, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 3, ctx); MUL_SI(tmp16, tmp16, 3, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -17, ctx); ADD_SI(tmp17, tmp17, 26, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SUB(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 61, ctx); SUB(tmp12, tmp13, tmp14, ctx); ADD_SI(tmp12, tmp12, 85, ctx); MUL_SI(tmp12, tmp12, 2, ctx); SQRT_UI(tmp13, 2, ctx); NEG(tmp13, tmp13, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); ADD(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 5, ctx); SUB_SI(tmp13, tmp13, 7, ctx); SQRT_UI(tmp14, 2, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, 5, ctx); SUB(tmp11, tmp12, tmp13, ctx); ADD_SI(tmp11, tmp11, 7, ctx); MUL_SI(tmp11, tmp11, 22, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, -17, ctx); ADD_SI(tmp12, tmp12, 26, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); ADD(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, 890, ctx); ADD(tmp7, tmp8, tmp9, ctx); SUB_SI(tmp7, tmp7, 1260, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, -12, ctx); SQRT_UI(tmp11, 2, ctx); NEG(tmp11, tmp11, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); MUL_SI(tmp11, tmp11, 2, ctx); SUB(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, -17, ctx); ADD_SI(tmp10, tmp10, 26, ctx); SQRT(tmp10, tmp10, ctx); MUL_SI(tmp10, tmp10, 2, ctx); SUB(tmp8, tmp9, tmp10, ctx); ADD_SI(tmp8, tmp8, 24, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); ADD(tmp4, tmp5, tmp6, ctx); SQRT_UI(tmp8, 2, ctx); MUL_SI(tmp8, tmp8, 319, ctx); SUB_SI(tmp8, tmp8, 452, ctx); SQRT_UI(tmp9, 2, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp8, 2, ctx); MUL_SI(tmp8, tmp8, 561, ctx); SUB(tmp6, tmp7, tmp8, ctx); ADD_SI(tmp6, tmp6, 794, ctx); MUL_SI(tmp6, tmp6, 4, ctx); SQRT_UI(tmp7, 2, ctx); MUL_SI(tmp7, tmp7, -17, ctx); ADD_SI(tmp7, tmp7, 26, ctx); SQRT(tmp7, tmp7, ctx); MUL(tmp5, tmp6, tmp7, ctx); ADD(tmp3, tmp4, tmp5, ctx); SQRT_UI(tmp4, 2, ctx); MUL_SI(tmp4, tmp4, 17064, ctx); ADD(tmp2, tmp3, tmp4, ctx); SUB_SI(tmp2, tmp2, 24132, ctx); DIV(tmp0, tmp1, tmp2, ctx); SET_SI(tmp4, 1, ctx); DIV_SI(tmp4, tmp4, 16, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 89, ctx); SUB_SI(tmp12, tmp12, 126, ctx); MUL_SI(tmp12, tmp12, 5, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 61, ctx); SUB_SI(tmp16, tmp16, 85, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 4, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 6, ctx); MUL_SI(tmp17, tmp17, 3, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SUB(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 122, ctx); SUB(tmp13, tmp14, tmp15, ctx); ADD_SI(tmp13, tmp13, 170, ctx); SQRT_UI(tmp14, 2, ctx); NEG(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 5, ctx); SUB_SI(tmp14, tmp14, 7, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 10, ctx); SUB(tmp12, tmp13, tmp14, ctx); ADD_SI(tmp12, tmp12, 14, ctx); MUL_SI(tmp12, tmp12, 11, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SUB(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 890, ctx); SUB(tmp8, tmp9, tmp10, ctx); ADD_SI(tmp8, tmp8, 1260, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 3, ctx); SQRT_UI(tmp11, 2, ctx); NEG(tmp11, tmp11, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); ADD(tmp9, tmp10, tmp11, ctx); SUB_SI(tmp9, tmp9, 5, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, -12, ctx); SQRT_UI(tmp11, 2, ctx); NEG(tmp11, tmp11, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); MUL_SI(tmp11, tmp11, 2, ctx); SUB(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, -17, ctx); ADD_SI(tmp10, tmp10, 26, ctx); SQRT(tmp10, tmp10, ctx); MUL_SI(tmp10, tmp10, 2, ctx); SUB(tmp8, tmp9, tmp10, ctx); ADD_SI(tmp8, tmp8, 24, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 63, ctx); SUB_SI(tmp12, tmp12, 89, ctx); MUL_SI(tmp12, tmp12, 10, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 85, ctx); SUB_SI(tmp16, tmp16, 122, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SUB_SI(tmp19, tmp19, 4, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 6, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 8, ctx); MUL_SI(tmp17, tmp17, 3, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SUB(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 170, ctx); SUB(tmp13, tmp14, tmp15, ctx); ADD_SI(tmp13, tmp13, 244, ctx); SQRT_UI(tmp14, 2, ctx); NEG(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 7, ctx); SUB_SI(tmp14, tmp14, 10, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 14, ctx); SUB(tmp12, tmp13, tmp14, ctx); ADD_SI(tmp12, tmp12, 20, ctx); MUL_SI(tmp12, tmp12, 11, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SUB(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 1260, ctx); SUB(tmp8, tmp9, tmp10, ctx); ADD_SI(tmp8, tmp8, 1780, ctx); MUL_SI(tmp8, tmp8, 2, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 3, ctx); SQRT_UI(tmp11, 2, ctx); NEG(tmp11, tmp11, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); ADD(tmp9, tmp10, tmp11, ctx); SUB_SI(tmp9, tmp9, 5, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); ADD(tmp5, tmp6, tmp7, ctx); MUL(tmp3, tmp4, tmp5, ctx); SQRT_UI(tmp12, 2, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp12, 2, ctx); SUB(tmp10, tmp11, tmp12, ctx); SUB_SI(tmp10, tmp10, 1, ctx); SQRT_UI(tmp11, 2, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); SUB_SI(tmp11, tmp11, 1, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); SUB(tmp8, tmp9, tmp10, ctx); ADD_SI(tmp8, tmp8, 1, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 7, ctx); SUB_SI(tmp19, tmp19, 10, ctx); MUL_SI(tmp19, tmp19, 44, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 7, ctx); SUB_SI(tmp24, tmp24, 10, ctx); MUL_SI(tmp24, tmp24, 11, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 63, ctx); SUB_SI(tmp24, tmp24, 89, ctx); MUL_SI(tmp24, tmp24, 10, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SUB_SI(tmp26, tmp26, 4, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 85, ctx); SUB_SI(tmp26, tmp26, 122, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); NEG(tmp24, tmp24, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SUB_SI(tmp27, tmp27, 4, ctx); MUL_SI(tmp27, tmp27, 3, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 85, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 122, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 7, ctx); SUB_SI(tmp26, tmp26, 10, ctx); MUL_SI(tmp26, tmp26, 11, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 630, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 890, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); ADD(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 3, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 63, ctx); SUB_SI(tmp18, tmp18, 89, ctx); MUL_SI(tmp18, tmp18, 40, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 3, ctx); SUB_SI(tmp20, tmp20, 4, ctx); MUL_SI(tmp20, tmp20, 3, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 85, ctx); SUB_SI(tmp20, tmp20, 122, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); MUL_SI(tmp17, tmp17, 4, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SUB(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 5, ctx); SUB_SI(tmp22, tmp22, 7, ctx); MUL_SI(tmp22, tmp22, 22, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB_SI(tmp27, tmp27, 7, ctx); MUL_SI(tmp27, tmp27, 11, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 89, ctx); SUB_SI(tmp27, tmp27, 126, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 2, ctx); SUB_SI(tmp29, tmp29, 3, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 61, ctx); SUB_SI(tmp29, tmp29, 85, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SUB(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, 2, ctx); SUB_SI(tmp30, tmp30, 3, ctx); MUL_SI(tmp30, tmp30, 3, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, -17, ctx); ADD_SI(tmp31, tmp31, 26, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, 61, ctx); SUB(tmp28, tmp29, tmp30, ctx); ADD_SI(tmp28, tmp28, 85, ctx); SQRT_UI(tmp29, 2, ctx); NEG(tmp29, tmp29, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 5, ctx); SUB_SI(tmp29, tmp29, 7, ctx); MUL_SI(tmp29, tmp29, 11, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SUB(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 445, ctx); ADD(tmp25, tmp26, tmp27, ctx); SUB_SI(tmp25, tmp25, 630, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); SUB_SI(tmp26, tmp26, 1, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 3, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 89, ctx); SUB_SI(tmp21, tmp21, 126, ctx); MUL_SI(tmp21, tmp21, 10, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SUB_SI(tmp23, tmp23, 3, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 61, ctx); SUB_SI(tmp23, tmp23, 85, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SUB_SI(tmp24, tmp24, 3, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 61, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 85, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB_SI(tmp23, tmp23, 7, ctx); MUL_SI(tmp23, tmp23, 11, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 445, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 630, ctx); MUL_SI(tmp19, tmp19, 4, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); SUB_SI(tmp20, tmp20, 1, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -12, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 24, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 3, ctx); SUB_SI(tmp20, tmp20, 4, ctx); MUL_SI(tmp20, tmp20, 3, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 85, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 122, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 7, ctx); SUB_SI(tmp19, tmp19, 10, ctx); MUL_SI(tmp19, tmp19, 11, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 630, ctx); ADD(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 890, ctx); MUL_SI(tmp15, tmp15, 8, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); SUB_SI(tmp16, tmp16, 1, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SUB(tmp12, tmp13, tmp14, ctx); MUL_SI(tmp12, tmp12, 8, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); ADD_SI(tmp16, tmp16, 1, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); SUB_SI(tmp17, tmp17, 1, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); ADD(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 1, ctx); INV(tmp14, tmp14, ctx); SQRT_UI(tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); ADD(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 5, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 8, ctx); SQRT_UI(tmp23, 2, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL_SI(tmp21, tmp21, 5, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 8, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 1, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); ADD(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 1, ctx); POW_UI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 1, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); SUB_SI(tmp24, tmp24, 1, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp29, 2, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); ADD(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); SUB_SI(tmp29, tmp29, 1, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); ADD(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 8, ctx); SQRT_UI(tmp30, 2, ctx); SQRT_UI(tmp31, 2, ctx); ADD_SI(tmp31, tmp31, 2, ctx); SQRT(tmp31, tmp31, ctx); ADD(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); SUB_SI(tmp30, tmp30, 1, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL_SI(tmp28, tmp28, 5, ctx); ADD(tmp26, tmp27, tmp28, ctx); SUB_SI(tmp26, tmp26, 8, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); ADD_SI(tmp25, tmp25, 2, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 1, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); SUB_SI(tmp28, tmp28, 1, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); ADD(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 1, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); SUB_SI(tmp26, tmp26, 2, ctx); POW_UI(tmp26, tmp26, 3, ctx); MUL(tmp24, tmp25, tmp26, ctx); DIV(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 1, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 2, ctx); POW_UI(tmp19, tmp19, 3, ctx); MUL(tmp17, tmp18, tmp19, ctx); DIV(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SUB_SI(tmp24, tmp24, 4, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 85, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 122, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 7, ctx); SUB_SI(tmp23, tmp23, 10, ctx); MUL_SI(tmp23, tmp23, 11, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 630, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 890, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); ADD(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 3, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 4896, ctx); SUB_SI(tmp19, tmp19, 6923, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 79, ctx); SUB_SI(tmp21, tmp21, 112, ctx); MUL_SI(tmp21, tmp21, 20, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 27, ctx); SUB_SI(tmp24, tmp24, 38, ctx); MUL_SI(tmp24, tmp24, 7, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 342, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 484, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 2820, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 3992, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); ADD(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB_SI(tmp28, tmp28, 3, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 61, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 85, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB_SI(tmp27, tmp27, 7, ctx); MUL_SI(tmp27, tmp27, 11, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 445, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 630, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SUB_SI(tmp24, tmp24, 3, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 89, ctx); SUB_SI(tmp23, tmp23, 126, ctx); MUL_SI(tmp23, tmp23, 10, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 61, ctx); SUB_SI(tmp25, tmp25, 85, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 3, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 61, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 85, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); ADD(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB_SI(tmp23, tmp23, 7, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 7, ctx); MUL_SI(tmp21, tmp21, 22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 890, ctx); ADD(tmp17, tmp18, tmp19, ctx); SUB_SI(tmp17, tmp17, 1260, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -12, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 24, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 319, ctx); SUB_SI(tmp18, tmp18, 452, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 561, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 794, ctx); MUL_SI(tmp16, tmp16, 4, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -17, ctx); ADD_SI(tmp17, tmp17, 26, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 17064, ctx); ADD(tmp12, tmp13, tmp14, ctx); SUB_SI(tmp12, tmp12, 24132, ctx); DIV(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 89, ctx); SUB_SI(tmp21, tmp21, 126, ctx); MUL_SI(tmp21, tmp21, 5, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 61, ctx); SUB_SI(tmp25, tmp25, 85, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 4, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 6, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 122, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 170, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB_SI(tmp23, tmp23, 7, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 10, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 14, ctx); MUL_SI(tmp21, tmp21, 11, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 890, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 1260, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD(tmp18, tmp19, tmp20, ctx); SUB_SI(tmp18, tmp18, 5, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -12, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 24, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 63, ctx); SUB_SI(tmp21, tmp21, 89, ctx); MUL_SI(tmp21, tmp21, 10, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 85, ctx); SUB_SI(tmp25, tmp25, 122, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SUB_SI(tmp28, tmp28, 4, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 6, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 8, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 170, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 244, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 7, ctx); SUB_SI(tmp23, tmp23, 10, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 14, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 20, ctx); MUL_SI(tmp21, tmp21, 11, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 1260, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 1780, ctx); MUL_SI(tmp17, tmp17, 2, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD(tmp18, tmp19, tmp20, ctx); SUB_SI(tmp18, tmp18, 5, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp19, 2, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 3, ctx); ADD(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL_SI(tmp17, tmp17, 5, ctx); SUB(tmp15, tmp16, tmp17, ctx); ADD_SI(tmp15, tmp15, 8, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SUB_SI(tmp28, tmp28, 4, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 85, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 122, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 7, ctx); SUB_SI(tmp27, tmp27, 10, ctx); MUL_SI(tmp27, tmp27, 11, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 630, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 890, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SUB_SI(tmp24, tmp24, 3, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 4896, ctx); SUB_SI(tmp23, tmp23, 6923, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 79, ctx); SUB_SI(tmp25, tmp25, 112, ctx); MUL_SI(tmp25, tmp25, 20, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 27, ctx); SUB_SI(tmp28, tmp28, 38, ctx); MUL_SI(tmp28, tmp28, 7, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 342, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 484, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 2820, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 3992, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); ADD(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 2, ctx); SUB_SI(tmp32, tmp32, 3, ctx); MUL_SI(tmp32, tmp32, 3, ctx); SQRT_UI(tmp33, 2, ctx); MUL_SI(tmp33, tmp33, -17, ctx); ADD_SI(tmp33, tmp33, 26, ctx); SQRT(tmp33, tmp33, ctx); MUL(tmp31, tmp32, tmp33, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 61, ctx); SUB(tmp30, tmp31, tmp32, ctx); ADD_SI(tmp30, tmp30, 85, ctx); SQRT_UI(tmp31, 2, ctx); NEG(tmp31, tmp31, ctx); ADD_SI(tmp31, tmp31, 2, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 5, ctx); SUB_SI(tmp31, tmp31, 7, ctx); MUL_SI(tmp31, tmp31, 11, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, -17, ctx); ADD_SI(tmp32, tmp32, 26, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SUB(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 445, ctx); ADD(tmp27, tmp28, tmp29, ctx); SUB_SI(tmp27, tmp27, 630, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); ADD(tmp28, tmp29, tmp30, ctx); SUB_SI(tmp28, tmp28, 3, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); SUB_SI(tmp27, tmp27, 1, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 89, ctx); SUB_SI(tmp27, tmp27, 126, ctx); MUL_SI(tmp27, tmp27, 10, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 61, ctx); SUB_SI(tmp29, tmp29, 85, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 2, ctx); SUB_SI(tmp32, tmp32, 3, ctx); SQRT_UI(tmp33, 2, ctx); ADD_SI(tmp33, tmp33, 2, ctx); SQRT(tmp33, tmp33, ctx); MUL(tmp31, tmp32, tmp33, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 2, ctx); SUB(tmp30, tmp31, tmp32, ctx); ADD_SI(tmp30, tmp30, 3, ctx); MUL_SI(tmp30, tmp30, 3, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, -17, ctx); ADD_SI(tmp31, tmp31, 26, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 61, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 85, ctx); MUL_SI(tmp26, tmp26, 2, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); ADD(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB_SI(tmp27, tmp27, 7, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 7, ctx); MUL_SI(tmp25, tmp25, 22, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 890, ctx); ADD(tmp21, tmp22, tmp23, ctx); SUB_SI(tmp21, tmp21, 1260, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -12, ctx); SQRT_UI(tmp25, 2, ctx); NEG(tmp25, tmp25, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 24, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 319, ctx); SUB_SI(tmp22, tmp22, 452, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 561, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 794, ctx); MUL_SI(tmp20, tmp20, 4, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 17064, ctx); ADD(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 24132, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 1, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); SUB_SI(tmp20, tmp20, 1, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 1, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 1, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); SUB_SI(tmp20, tmp20, 1, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp25, 2, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 1, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 8, ctx); SQRT_UI(tmp26, 2, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); ADD(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); SUB_SI(tmp26, tmp26, 1, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL_SI(tmp24, tmp24, 5, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 8, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 1, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); SUB_SI(tmp24, tmp24, 1, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 1, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 2, ctx); POW_UI(tmp22, tmp22, 3, ctx); MUL(tmp20, tmp21, tmp22, ctx); DIV(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 1, ctx); MUL(tmp14, tmp15, tmp16, ctx); SET_SI(tmp18, 1, ctx); DIV_SI(tmp18, tmp18, 4, ctx); NEG(tmp18, tmp18, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SET_SI(tmp18, 1, ctx); DIV_SI(tmp18, tmp18, 2, ctx); ADD(tmp16, tmp17, tmp18, ctx); SET_SI(tmp17, 3, ctx); DIV_SI(tmp17, tmp17, 2, ctx); POW(tmp15, tmp16, tmp17, ctx); MUL(tmp13, tmp14, tmp15, ctx); DIV(tmp11, tmp12, tmp13, ctx); ADD(tmp9, tmp10, tmp11, ctx); MUL(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp8, 2, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); SET_SI(tmp9, 1, ctx); DIV_SI(tmp9, tmp9, 4, ctx); NEG(tmp9, tmp9, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SET_SI(tmp9, 1, ctx); DIV_SI(tmp9, tmp9, 2, ctx); ADD(tmp7, tmp8, tmp9, ctx); SQRT(tmp7, tmp7, ctx); DIV(tmp5, tmp6, tmp7, ctx); SQRT_UI(tmp12, 2, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); SQRT_UI(tmp13, 2, ctx); SUB_SI(tmp13, tmp13, 1, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp12, 2, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); SUB_SI(tmp12, tmp12, 1, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); ADD(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); SUB(tmp8, tmp9, tmp10, ctx); MUL_SI(tmp8, tmp8, 2, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 89, ctx); SUB_SI(tmp19, tmp19, 126, ctx); MUL_SI(tmp19, tmp19, 5, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 61, ctx); SUB_SI(tmp23, tmp23, 85, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 2, ctx); SUB_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 4, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 6, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 122, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 170, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 5, ctx); SUB_SI(tmp21, tmp21, 7, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 10, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 14, ctx); MUL_SI(tmp19, tmp19, 11, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 890, ctx); SUB(tmp15, tmp16, tmp17, ctx); ADD_SI(tmp15, tmp15, 1260, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 3, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 5, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -12, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL_SI(tmp18, tmp18, 2, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -17, ctx); ADD_SI(tmp17, tmp17, 26, ctx); SQRT(tmp17, tmp17, ctx); MUL_SI(tmp17, tmp17, 2, ctx); SUB(tmp15, tmp16, tmp17, ctx); ADD_SI(tmp15, tmp15, 24, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 63, ctx); SUB_SI(tmp19, tmp19, 89, ctx); MUL_SI(tmp19, tmp19, 10, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 85, ctx); SUB_SI(tmp23, tmp23, 122, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SUB_SI(tmp26, tmp26, 4, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 6, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 8, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 170, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 244, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 7, ctx); SUB_SI(tmp21, tmp21, 10, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 14, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 20, ctx); MUL_SI(tmp19, tmp19, 11, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 1260, ctx); SUB(tmp15, tmp16, tmp17, ctx); ADD_SI(tmp15, tmp15, 1780, ctx); MUL_SI(tmp15, tmp15, 2, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, 3, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 5, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); ADD(tmp12, tmp13, tmp14, ctx); MUL_SI(tmp12, tmp12, 8, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); ADD_SI(tmp16, tmp16, 1, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); SUB_SI(tmp17, tmp17, 1, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); ADD(tmp14, tmp15, tmp16, ctx); ADD_SI(tmp14, tmp14, 1, ctx); INV(tmp14, tmp14, ctx); SQRT_UI(tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); ADD(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 5, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 8, ctx); SQRT_UI(tmp23, 2, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL_SI(tmp21, tmp21, 5, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 8, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 1, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); ADD(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 1, ctx); POW_UI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 1, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); SUB_SI(tmp24, tmp24, 1, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp29, 2, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); ADD(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); SUB_SI(tmp29, tmp29, 1, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); ADD(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 8, ctx); SQRT_UI(tmp30, 2, ctx); SQRT_UI(tmp31, 2, ctx); ADD_SI(tmp31, tmp31, 2, ctx); SQRT(tmp31, tmp31, ctx); ADD(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); SUB_SI(tmp30, tmp30, 1, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL_SI(tmp28, tmp28, 5, ctx); ADD(tmp26, tmp27, tmp28, ctx); SUB_SI(tmp26, tmp26, 8, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); ADD_SI(tmp25, tmp25, 2, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 1, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); SUB_SI(tmp28, tmp28, 1, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); ADD(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 1, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); SUB_SI(tmp26, tmp26, 2, ctx); POW_UI(tmp26, tmp26, 3, ctx); MUL(tmp24, tmp25, tmp26, ctx); DIV(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 1, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 2, ctx); POW_UI(tmp19, tmp19, 3, ctx); MUL(tmp17, tmp18, tmp19, ctx); DIV(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SUB_SI(tmp24, tmp24, 4, ctx); MUL_SI(tmp24, tmp24, 3, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 85, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 122, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 7, ctx); SUB_SI(tmp23, tmp23, 10, ctx); MUL_SI(tmp23, tmp23, 11, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 630, ctx); ADD(tmp19, tmp20, tmp21, ctx); SUB_SI(tmp19, tmp19, 890, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 3, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); ADD(tmp20, tmp21, tmp22, ctx); SUB_SI(tmp20, tmp20, 3, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 4896, ctx); SUB_SI(tmp19, tmp19, 6923, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 79, ctx); SUB_SI(tmp21, tmp21, 112, ctx); MUL_SI(tmp21, tmp21, 20, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 27, ctx); SUB_SI(tmp24, tmp24, 38, ctx); MUL_SI(tmp24, tmp24, 7, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 342, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 484, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 2820, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 3992, ctx); SQRT_UI(tmp19, 2, ctx); NEG(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); ADD(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB_SI(tmp28, tmp28, 3, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 61, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 85, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB_SI(tmp27, tmp27, 7, ctx); MUL_SI(tmp27, tmp27, 11, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 445, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 630, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SUB_SI(tmp24, tmp24, 3, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 89, ctx); SUB_SI(tmp23, tmp23, 126, ctx); MUL_SI(tmp23, tmp23, 10, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 61, ctx); SUB_SI(tmp25, tmp25, 85, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 2, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 3, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 61, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 85, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); ADD(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB_SI(tmp23, tmp23, 7, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 7, ctx); MUL_SI(tmp21, tmp21, 22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 890, ctx); ADD(tmp17, tmp18, tmp19, ctx); SUB_SI(tmp17, tmp17, 1260, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -12, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL_SI(tmp20, tmp20, 2, ctx); SUB(tmp18, tmp19, tmp20, ctx); ADD_SI(tmp18, tmp18, 24, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 319, ctx); SUB_SI(tmp18, tmp18, 452, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 561, ctx); SUB(tmp16, tmp17, tmp18, ctx); ADD_SI(tmp16, tmp16, 794, ctx); MUL_SI(tmp16, tmp16, 4, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -17, ctx); ADD_SI(tmp17, tmp17, 26, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); ADD(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 17064, ctx); ADD(tmp12, tmp13, tmp14, ctx); SUB_SI(tmp12, tmp12, 24132, ctx); DIV(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 7, ctx); SUB_SI(tmp21, tmp21, 10, ctx); MUL_SI(tmp21, tmp21, 44, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 7, ctx); SUB_SI(tmp26, tmp26, 10, ctx); MUL_SI(tmp26, tmp26, 11, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 63, ctx); SUB_SI(tmp26, tmp26, 89, ctx); MUL_SI(tmp26, tmp26, 10, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SUB_SI(tmp28, tmp28, 4, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 85, ctx); SUB_SI(tmp28, tmp28, 122, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SUB(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); NEG(tmp26, tmp26, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SUB_SI(tmp29, tmp29, 4, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 85, ctx); SUB(tmp27, tmp28, tmp29, ctx); ADD_SI(tmp27, tmp27, 122, ctx); SQRT_UI(tmp28, 2, ctx); NEG(tmp28, tmp28, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 7, ctx); SUB_SI(tmp28, tmp28, 10, ctx); MUL_SI(tmp28, tmp28, 11, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SUB(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 630, ctx); ADD(tmp24, tmp25, tmp26, ctx); SUB_SI(tmp24, tmp24, 890, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 1, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); ADD(tmp21, tmp22, tmp23, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 3, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 3, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, 63, ctx); SUB_SI(tmp20, tmp20, 89, ctx); MUL_SI(tmp20, tmp20, 40, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SUB_SI(tmp22, tmp22, 4, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 85, ctx); SUB_SI(tmp22, tmp22, 122, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); MUL_SI(tmp19, tmp19, 4, ctx); SQRT_UI(tmp20, 2, ctx); NEG(tmp20, tmp20, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 5, ctx); SUB_SI(tmp24, tmp24, 7, ctx); MUL_SI(tmp24, tmp24, 22, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 5, ctx); SUB_SI(tmp29, tmp29, 7, ctx); MUL_SI(tmp29, tmp29, 11, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 89, ctx); SUB_SI(tmp29, tmp29, 126, ctx); MUL_SI(tmp29, tmp29, 5, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SUB(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 2, ctx); SUB_SI(tmp31, tmp31, 3, ctx); MUL_SI(tmp31, tmp31, 3, ctx); SQRT_UI(tmp32, 2, ctx); ADD_SI(tmp32, tmp32, 2, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, -17, ctx); ADD_SI(tmp31, tmp31, 26, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 61, ctx); SUB_SI(tmp31, tmp31, 85, ctx); SQRT_UI(tmp32, 2, ctx); ADD_SI(tmp32, tmp32, 2, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SUB(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); NEG(tmp29, tmp29, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SUB(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 2, ctx); SUB_SI(tmp32, tmp32, 3, ctx); MUL_SI(tmp32, tmp32, 3, ctx); SQRT_UI(tmp33, 2, ctx); MUL_SI(tmp33, tmp33, -17, ctx); ADD_SI(tmp33, tmp33, 26, ctx); SQRT(tmp33, tmp33, ctx); MUL(tmp31, tmp32, tmp33, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 61, ctx); SUB(tmp30, tmp31, tmp32, ctx); ADD_SI(tmp30, tmp30, 85, ctx); SQRT_UI(tmp31, 2, ctx); NEG(tmp31, tmp31, ctx); ADD_SI(tmp31, tmp31, 2, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 5, ctx); SUB_SI(tmp31, tmp31, 7, ctx); MUL_SI(tmp31, tmp31, 11, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, -17, ctx); ADD_SI(tmp32, tmp32, 26, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SUB(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 445, ctx); ADD(tmp27, tmp28, tmp29, ctx); SUB_SI(tmp27, tmp27, 630, ctx); MUL_SI(tmp27, tmp27, 2, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); SUB_SI(tmp28, tmp28, 1, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); ADD(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); ADD(tmp25, tmp26, tmp27, ctx); SUB_SI(tmp25, tmp25, 3, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); ADD(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 89, ctx); SUB_SI(tmp23, tmp23, 126, ctx); MUL_SI(tmp23, tmp23, 10, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SUB_SI(tmp25, tmp25, 3, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, -17, ctx); ADD_SI(tmp25, tmp25, 26, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 61, ctx); SUB_SI(tmp25, tmp25, 85, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SUB(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 2, ctx); SUB_SI(tmp26, tmp26, 3, ctx); MUL_SI(tmp26, tmp26, 3, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, 61, ctx); SUB(tmp24, tmp25, tmp26, ctx); ADD_SI(tmp24, tmp24, 85, ctx); SQRT_UI(tmp25, 2, ctx); NEG(tmp25, tmp25, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 5, ctx); SUB_SI(tmp25, tmp25, 7, ctx); MUL_SI(tmp25, tmp25, 11, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SUB(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 445, ctx); ADD(tmp21, tmp22, tmp23, ctx); SUB_SI(tmp21, tmp21, 630, ctx); MUL_SI(tmp21, tmp21, 4, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 1, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -12, ctx); SQRT_UI(tmp22, 2, ctx); NEG(tmp22, tmp22, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); MUL_SI(tmp22, tmp22, 2, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL_SI(tmp21, tmp21, 2, ctx); SUB(tmp19, tmp20, tmp21, ctx); ADD_SI(tmp19, tmp19, 24, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); ADD(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SUB_SI(tmp22, tmp22, 4, ctx); MUL_SI(tmp22, tmp22, 3, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, -17, ctx); ADD_SI(tmp23, tmp23, 26, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 85, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 122, ctx); SQRT_UI(tmp21, 2, ctx); NEG(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, 7, ctx); SUB_SI(tmp21, tmp21, 10, ctx); MUL_SI(tmp21, tmp21, 11, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, -17, ctx); ADD_SI(tmp22, tmp22, 26, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); SUB(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 630, ctx); ADD(tmp17, tmp18, tmp19, ctx); SUB_SI(tmp17, tmp17, 890, ctx); MUL_SI(tmp17, tmp17, 8, ctx); SQRT_UI(tmp18, 2, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); SUB_SI(tmp18, tmp18, 1, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); ADD(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp19, 2, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB_SI(tmp19, tmp19, 1, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 3, ctx); ADD(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL_SI(tmp17, tmp17, 5, ctx); SUB(tmp15, tmp16, tmp17, ctx); ADD_SI(tmp15, tmp15, 8, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SUB_SI(tmp28, tmp28, 4, ctx); MUL_SI(tmp28, tmp28, 3, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, -17, ctx); ADD_SI(tmp29, tmp29, 26, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 85, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 122, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 7, ctx); SUB_SI(tmp27, tmp27, 10, ctx); MUL_SI(tmp27, tmp27, 11, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, -17, ctx); ADD_SI(tmp28, tmp28, 26, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 630, ctx); ADD(tmp23, tmp24, tmp25, ctx); SUB_SI(tmp23, tmp23, 890, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SUB_SI(tmp24, tmp24, 3, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); SUB_SI(tmp23, tmp23, 1, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 4896, ctx); SUB_SI(tmp23, tmp23, 6923, ctx); MUL_SI(tmp23, tmp23, 2, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SUB(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 79, ctx); SUB_SI(tmp25, tmp25, 112, ctx); MUL_SI(tmp25, tmp25, 20, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 27, ctx); SUB_SI(tmp28, tmp28, 38, ctx); MUL_SI(tmp28, tmp28, 7, ctx); SQRT_UI(tmp29, 2, ctx); ADD_SI(tmp29, tmp29, 2, ctx); SQRT(tmp29, tmp29, ctx); MUL(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 342, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 484, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, -17, ctx); ADD_SI(tmp27, tmp27, 26, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 2820, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 3992, ctx); SQRT_UI(tmp23, 2, ctx); NEG(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); ADD(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 2, ctx); SUB_SI(tmp32, tmp32, 3, ctx); MUL_SI(tmp32, tmp32, 3, ctx); SQRT_UI(tmp33, 2, ctx); MUL_SI(tmp33, tmp33, -17, ctx); ADD_SI(tmp33, tmp33, 26, ctx); SQRT(tmp33, tmp33, ctx); MUL(tmp31, tmp32, tmp33, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 61, ctx); SUB(tmp30, tmp31, tmp32, ctx); ADD_SI(tmp30, tmp30, 85, ctx); SQRT_UI(tmp31, 2, ctx); NEG(tmp31, tmp31, ctx); ADD_SI(tmp31, tmp31, 2, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, 5, ctx); SUB_SI(tmp31, tmp31, 7, ctx); MUL_SI(tmp31, tmp31, 11, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, -17, ctx); ADD_SI(tmp32, tmp32, 26, ctx); SQRT(tmp32, tmp32, ctx); MUL(tmp30, tmp31, tmp32, ctx); SUB(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 445, ctx); ADD(tmp27, tmp28, tmp29, ctx); SUB_SI(tmp27, tmp27, 630, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 3, ctx); SQRT_UI(tmp30, 2, ctx); MUL_SI(tmp30, tmp30, -17, ctx); ADD_SI(tmp30, tmp30, 26, ctx); SQRT(tmp30, tmp30, ctx); ADD(tmp28, tmp29, tmp30, ctx); SUB_SI(tmp28, tmp28, 3, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); SUB_SI(tmp27, tmp27, 1, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 89, ctx); SUB_SI(tmp27, tmp27, 126, ctx); MUL_SI(tmp27, tmp27, 10, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SUB(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp29, 2, ctx); MUL_SI(tmp29, tmp29, 61, ctx); SUB_SI(tmp29, tmp29, 85, ctx); SQRT_UI(tmp30, 2, ctx); ADD_SI(tmp30, tmp30, 2, ctx); SQRT(tmp30, tmp30, ctx); MUL(tmp28, tmp29, tmp30, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 2, ctx); SUB_SI(tmp32, tmp32, 3, ctx); SQRT_UI(tmp33, 2, ctx); ADD_SI(tmp33, tmp33, 2, ctx); SQRT(tmp33, tmp33, ctx); MUL(tmp31, tmp32, tmp33, ctx); SQRT_UI(tmp32, 2, ctx); MUL_SI(tmp32, tmp32, 2, ctx); SUB(tmp30, tmp31, tmp32, ctx); ADD_SI(tmp30, tmp30, 3, ctx); MUL_SI(tmp30, tmp30, 3, ctx); SQRT_UI(tmp31, 2, ctx); MUL_SI(tmp31, tmp31, -17, ctx); ADD_SI(tmp31, tmp31, 26, ctx); SQRT(tmp31, tmp31, ctx); MUL(tmp29, tmp30, tmp31, ctx); SUB(tmp27, tmp28, tmp29, ctx); SQRT_UI(tmp28, 2, ctx); MUL_SI(tmp28, tmp28, 61, ctx); SUB(tmp26, tmp27, tmp28, ctx); ADD_SI(tmp26, tmp26, 85, ctx); MUL_SI(tmp26, tmp26, 2, ctx); SQRT_UI(tmp27, 2, ctx); NEG(tmp27, tmp27, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); MUL(tmp25, tmp26, tmp27, ctx); ADD(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB_SI(tmp27, tmp27, 7, ctx); SQRT_UI(tmp28, 2, ctx); ADD_SI(tmp28, tmp28, 2, ctx); SQRT(tmp28, tmp28, ctx); MUL(tmp26, tmp27, tmp28, ctx); SQRT_UI(tmp27, 2, ctx); MUL_SI(tmp27, tmp27, 5, ctx); SUB(tmp25, tmp26, tmp27, ctx); ADD_SI(tmp25, tmp25, 7, ctx); MUL_SI(tmp25, tmp25, 22, ctx); SQRT_UI(tmp26, 2, ctx); MUL_SI(tmp26, tmp26, -17, ctx); ADD_SI(tmp26, tmp26, 26, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); MUL_SI(tmp23, tmp23, 890, ctx); ADD(tmp21, tmp22, tmp23, ctx); SUB_SI(tmp21, tmp21, 1260, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -12, ctx); SQRT_UI(tmp25, 2, ctx); NEG(tmp25, tmp25, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); MUL_SI(tmp25, tmp25, 2, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, -17, ctx); ADD_SI(tmp24, tmp24, 26, ctx); SQRT(tmp24, tmp24, ctx); MUL_SI(tmp24, tmp24, 2, ctx); SUB(tmp22, tmp23, tmp24, ctx); ADD_SI(tmp22, tmp22, 24, ctx); SQRT(tmp22, tmp22, ctx); MUL(tmp20, tmp21, tmp22, ctx); ADD(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 319, ctx); SUB_SI(tmp22, tmp22, 452, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL(tmp21, tmp22, tmp23, ctx); SQRT_UI(tmp22, 2, ctx); MUL_SI(tmp22, tmp22, 561, ctx); SUB(tmp20, tmp21, tmp22, ctx); ADD_SI(tmp20, tmp20, 794, ctx); MUL_SI(tmp20, tmp20, 4, ctx); SQRT_UI(tmp21, 2, ctx); MUL_SI(tmp21, tmp21, -17, ctx); ADD_SI(tmp21, tmp21, 26, ctx); SQRT(tmp21, tmp21, ctx); MUL(tmp19, tmp20, tmp21, ctx); ADD(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 17064, ctx); ADD(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 24132, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 1, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); SUB_SI(tmp20, tmp20, 1, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 1, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); ADD_SI(tmp19, tmp19, 1, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); SUB_SI(tmp20, tmp20, 1, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); SUB(tmp17, tmp18, tmp19, ctx); SQRT_UI(tmp25, 2, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); ADD(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); ADD_SI(tmp25, tmp25, 2, ctx); SQRT(tmp25, tmp25, ctx); SUB_SI(tmp25, tmp25, 1, ctx); SQRT(tmp25, tmp25, ctx); MUL(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); MUL_SI(tmp24, tmp24, 3, ctx); ADD(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); MUL_SI(tmp23, tmp23, 5, ctx); SUB(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 8, ctx); SQRT_UI(tmp26, 2, ctx); SQRT_UI(tmp27, 2, ctx); ADD_SI(tmp27, tmp27, 2, ctx); SQRT(tmp27, tmp27, ctx); ADD(tmp25, tmp26, tmp27, ctx); SQRT_UI(tmp26, 2, ctx); ADD_SI(tmp26, tmp26, 2, ctx); SQRT(tmp26, tmp26, ctx); SUB_SI(tmp26, tmp26, 1, ctx); SQRT(tmp26, tmp26, ctx); MUL(tmp24, tmp25, tmp26, ctx); SQRT_UI(tmp25, 2, ctx); MUL_SI(tmp25, tmp25, 3, ctx); SUB(tmp23, tmp24, tmp25, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); MUL_SI(tmp24, tmp24, 5, ctx); ADD(tmp22, tmp23, tmp24, ctx); SUB_SI(tmp22, tmp22, 8, ctx); MUL(tmp20, tmp21, tmp22, ctx); SQRT_UI(tmp21, 2, ctx); ADD_SI(tmp21, tmp21, 2, ctx); SQRT(tmp21, tmp21, ctx); ADD_SI(tmp21, tmp21, 2, ctx); MUL(tmp19, tmp20, tmp21, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD_SI(tmp23, tmp23, 1, ctx); SQRT_UI(tmp24, 2, ctx); ADD_SI(tmp24, tmp24, 2, ctx); SQRT(tmp24, tmp24, ctx); SUB_SI(tmp24, tmp24, 1, ctx); SQRT(tmp24, tmp24, ctx); MUL(tmp22, tmp23, tmp24, ctx); SQRT_UI(tmp23, 2, ctx); ADD_SI(tmp23, tmp23, 2, ctx); SQRT(tmp23, tmp23, ctx); ADD(tmp21, tmp22, tmp23, ctx); ADD_SI(tmp21, tmp21, 1, ctx); SQRT_UI(tmp22, 2, ctx); ADD_SI(tmp22, tmp22, 2, ctx); SQRT(tmp22, tmp22, ctx); SUB_SI(tmp22, tmp22, 2, ctx); POW_UI(tmp22, tmp22, 3, ctx); MUL(tmp20, tmp21, tmp22, ctx); DIV(tmp18, tmp19, tmp20, ctx); SUB(tmp16, tmp17, tmp18, ctx); SUB_SI(tmp16, tmp16, 1, ctx); MUL(tmp14, tmp15, tmp16, ctx); SET_SI(tmp18, 1, ctx); DIV_SI(tmp18, tmp18, 4, ctx); NEG(tmp18, tmp18, ctx); SQRT_UI(tmp19, 2, ctx); ADD_SI(tmp19, tmp19, 2, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SET_SI(tmp18, 1, ctx); DIV_SI(tmp18, tmp18, 2, ctx); ADD(tmp16, tmp17, tmp18, ctx); SET_SI(tmp17, 3, ctx); DIV_SI(tmp17, tmp17, 2, ctx); POW(tmp15, tmp16, tmp17, ctx); MUL(tmp13, tmp14, tmp15, ctx); DIV(tmp11, tmp12, tmp13, ctx); ADD(tmp9, tmp10, tmp11, ctx); MUL(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp8, 2, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); SUB_SI(tmp8, tmp8, 2, ctx); DIV(tmp6, tmp7, tmp8, ctx); SUB(tmp4, tmp5, tmp6, ctx); MUL(tmp2, tmp3, tmp4, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 3, ctx); SUB_SI(tmp15, tmp15, 4, ctx); MUL_SI(tmp15, tmp15, 3, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, -17, ctx); ADD_SI(tmp16, tmp16, 26, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 85, ctx); SUB(tmp13, tmp14, tmp15, ctx); ADD_SI(tmp13, tmp13, 122, ctx); SQRT_UI(tmp14, 2, ctx); NEG(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 7, ctx); SUB_SI(tmp14, tmp14, 10, ctx); MUL_SI(tmp14, tmp14, 11, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, -17, ctx); ADD_SI(tmp15, tmp15, 26, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SUB(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 630, ctx); ADD(tmp10, tmp11, tmp12, ctx); SUB_SI(tmp10, tmp10, 890, ctx); MUL_SI(tmp10, tmp10, 2, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 3, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); ADD(tmp11, tmp12, tmp13, ctx); SUB_SI(tmp11, tmp11, 3, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); SUB_SI(tmp10, tmp10, 1, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 4896, ctx); SUB_SI(tmp10, tmp10, 6923, ctx); MUL_SI(tmp10, tmp10, 2, ctx); SQRT_UI(tmp11, 2, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SUB(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 79, ctx); SUB_SI(tmp12, tmp12, 112, ctx); MUL_SI(tmp12, tmp12, 20, ctx); SQRT_UI(tmp13, 2, ctx); ADD_SI(tmp13, tmp13, 2, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 27, ctx); SUB_SI(tmp15, tmp15, 38, ctx); MUL_SI(tmp15, tmp15, 7, ctx); SQRT_UI(tmp16, 2, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 342, ctx); SUB(tmp13, tmp14, tmp15, ctx); ADD_SI(tmp13, tmp13, 484, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, -17, ctx); ADD_SI(tmp14, tmp14, 26, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, 2820, ctx); SUB(tmp9, tmp10, tmp11, ctx); ADD_SI(tmp9, tmp9, 3992, ctx); SQRT_UI(tmp10, 2, ctx); NEG(tmp10, tmp10, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); ADD(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB_SI(tmp19, tmp19, 3, ctx); MUL_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); MUL_SI(tmp20, tmp20, -17, ctx); ADD_SI(tmp20, tmp20, 26, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 61, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 85, ctx); SQRT_UI(tmp18, 2, ctx); NEG(tmp18, tmp18, ctx); ADD_SI(tmp18, tmp18, 2, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, 5, ctx); SUB_SI(tmp18, tmp18, 7, ctx); MUL_SI(tmp18, tmp18, 11, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, -17, ctx); ADD_SI(tmp19, tmp19, 26, ctx); SQRT(tmp19, tmp19, ctx); MUL(tmp17, tmp18, tmp19, ctx); SUB(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 445, ctx); ADD(tmp14, tmp15, tmp16, ctx); SUB_SI(tmp14, tmp14, 630, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 3, ctx); SQRT_UI(tmp17, 2, ctx); MUL_SI(tmp17, tmp17, -17, ctx); ADD_SI(tmp17, tmp17, 26, ctx); SQRT(tmp17, tmp17, ctx); ADD(tmp15, tmp16, tmp17, ctx); SUB_SI(tmp15, tmp15, 3, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); SUB_SI(tmp14, tmp14, 1, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 89, ctx); SUB_SI(tmp14, tmp14, 126, ctx); MUL_SI(tmp14, tmp14, 10, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SUB(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp16, 2, ctx); MUL_SI(tmp16, tmp16, 61, ctx); SUB_SI(tmp16, tmp16, 85, ctx); SQRT_UI(tmp17, 2, ctx); ADD_SI(tmp17, tmp17, 2, ctx); SQRT(tmp17, tmp17, ctx); MUL(tmp15, tmp16, tmp17, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB_SI(tmp19, tmp19, 3, ctx); SQRT_UI(tmp20, 2, ctx); ADD_SI(tmp20, tmp20, 2, ctx); SQRT(tmp20, tmp20, ctx); MUL(tmp18, tmp19, tmp20, ctx); SQRT_UI(tmp19, 2, ctx); MUL_SI(tmp19, tmp19, 2, ctx); SUB(tmp17, tmp18, tmp19, ctx); ADD_SI(tmp17, tmp17, 3, ctx); MUL_SI(tmp17, tmp17, 3, ctx); SQRT_UI(tmp18, 2, ctx); MUL_SI(tmp18, tmp18, -17, ctx); ADD_SI(tmp18, tmp18, 26, ctx); SQRT(tmp18, tmp18, ctx); MUL(tmp16, tmp17, tmp18, ctx); SUB(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, 61, ctx); SUB(tmp13, tmp14, tmp15, ctx); ADD_SI(tmp13, tmp13, 85, ctx); MUL_SI(tmp13, tmp13, 2, ctx); SQRT_UI(tmp14, 2, ctx); NEG(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); ADD(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 5, ctx); SUB_SI(tmp14, tmp14, 7, ctx); SQRT_UI(tmp15, 2, ctx); ADD_SI(tmp15, tmp15, 2, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); MUL_SI(tmp14, tmp14, 5, ctx); SUB(tmp12, tmp13, tmp14, ctx); ADD_SI(tmp12, tmp12, 7, ctx); MUL_SI(tmp12, tmp12, 22, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); ADD(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 890, ctx); ADD(tmp8, tmp9, tmp10, ctx); SUB_SI(tmp8, tmp8, 1260, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -12, ctx); SQRT_UI(tmp12, 2, ctx); NEG(tmp12, tmp12, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); MUL_SI(tmp12, tmp12, 2, ctx); SUB(tmp10, tmp11, tmp12, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -17, ctx); ADD_SI(tmp11, tmp11, 26, ctx); SQRT(tmp11, tmp11, ctx); MUL_SI(tmp11, tmp11, 2, ctx); SUB(tmp9, tmp10, tmp11, ctx); ADD_SI(tmp9, tmp9, 24, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); ADD(tmp5, tmp6, tmp7, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, 319, ctx); SUB_SI(tmp9, tmp9, 452, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, 561, ctx); SUB(tmp7, tmp8, tmp9, ctx); ADD_SI(tmp7, tmp7, 794, ctx); MUL_SI(tmp7, tmp7, 4, ctx); SQRT_UI(tmp8, 2, ctx); MUL_SI(tmp8, tmp8, -17, ctx); ADD_SI(tmp8, tmp8, 26, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); ADD(tmp4, tmp5, tmp6, ctx); SQRT_UI(tmp5, 2, ctx); MUL_SI(tmp5, tmp5, 17064, ctx); ADD(tmp3, tmp4, tmp5, ctx); SUB_SI(tmp3, tmp3, 24132, ctx); DIV(tmp1, tmp2, tmp3, ctx); SUB(N, tmp0, tmp1, ctx); TIMEIT_ONCE_STOP flint_printf("Evaluating M...\n"); TIMEIT_ONCE_START SQRT_UI(tmp6, 2, ctx); MUL_SI(tmp6, tmp6, 6, ctx); SQRT_UI(tmp7, 2, ctx); NEG(tmp7, tmp7, ctx); ADD_SI(tmp7, tmp7, 2, ctx); SQRT(tmp7, tmp7, ctx); ADD(tmp5, tmp6, tmp7, ctx); SQRT_UI(tmp6, 2, ctx); MUL_SI(tmp6, tmp6, -17, ctx); ADD_SI(tmp6, tmp6, 26, ctx); SQRT(tmp6, tmp6, ctx); ADD(tmp4, tmp5, tmp6, ctx); SUB_SI(tmp4, tmp4, 8, ctx); MUL_SI(tmp4, tmp4, 4, ctx); SQRT_UI(tmp6, 2, ctx); MUL_SI(tmp6, tmp6, 3, ctx); SQRT_UI(tmp7, 2, ctx); NEG(tmp7, tmp7, ctx); ADD_SI(tmp7, tmp7, 2, ctx); SQRT(tmp7, tmp7, ctx); ADD(tmp5, tmp6, tmp7, ctx); SUB_SI(tmp5, tmp5, 5, ctx); SQRT(tmp5, tmp5, ctx); MUL(tmp3, tmp4, tmp5, ctx); SQRT_UI(tmp6, 2, ctx); MUL_SI(tmp6, tmp6, 3, ctx); SQRT_UI(tmp7, 2, ctx); MUL_SI(tmp7, tmp7, -17, ctx); ADD_SI(tmp7, tmp7, 26, ctx); SQRT(tmp7, tmp7, ctx); ADD(tmp5, tmp6, tmp7, ctx); SUB_SI(tmp5, tmp5, 3, ctx); SQRT(tmp5, tmp5, ctx); CONST_I(tmp10, ctx); MUL_SI(tmp10, tmp10, -24, ctx); SQRT_UI(tmp11, 2, ctx); MUL(tmp9, tmp10, tmp11, ctx); CONST_I(tmp11, ctx); MUL_SI(tmp11, tmp11, 4, ctx); SQRT_UI(tmp12, 2, ctx); NEG(tmp12, tmp12, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); SUB(tmp8, tmp9, tmp10, ctx); CONST_I(tmp10, ctx); MUL_SI(tmp10, tmp10, 4, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -17, ctx); ADD_SI(tmp11, tmp11, 26, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SUB(tmp7, tmp8, tmp9, ctx); CONST_I(tmp8, ctx); MUL_SI(tmp8, tmp8, 32, ctx); ADD(tmp6, tmp7, tmp8, ctx); MUL(tmp4, tmp5, tmp6, ctx); SUB(tmp2, tmp3, tmp4, ctx); SQRT_UI(tmp9, 2, ctx); SQRT_UI(tmp10, 2, ctx); NEG(tmp10, tmp10, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp10, 2, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -17, ctx); ADD_SI(tmp11, tmp11, 26, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); ADD(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp8, 2, ctx); MUL_SI(tmp8, tmp8, 8, ctx); SUB(tmp6, tmp7, tmp8, ctx); ADD_SI(tmp6, tmp6, 12, ctx); SQRT_UI(tmp8, 2, ctx); MUL_SI(tmp8, tmp8, 3, ctx); SQRT_UI(tmp9, 2, ctx); NEG(tmp9, tmp9, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); ADD(tmp7, tmp8, tmp9, ctx); SUB_SI(tmp7, tmp7, 5, ctx); SQRT(tmp7, tmp7, ctx); MUL(tmp5, tmp6, tmp7, ctx); CONST_I(tmp12, ctx); SQRT_UI(tmp13, 2, ctx); MUL(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp12, 2, ctx); NEG(tmp12, tmp12, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); CONST_I(tmp13, ctx); SQRT_UI(tmp14, 2, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); MUL(tmp11, tmp12, tmp13, ctx); ADD(tmp9, tmp10, tmp11, ctx); CONST_I(tmp11, ctx); MUL_SI(tmp11, tmp11, 8, ctx); SQRT_UI(tmp12, 2, ctx); MUL(tmp10, tmp11, tmp12, ctx); SUB(tmp8, tmp9, tmp10, ctx); CONST_I(tmp9, ctx); MUL_SI(tmp9, tmp9, 12, ctx); ADD(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, 3, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, -17, ctx); ADD_SI(tmp10, tmp10, 26, ctx); SQRT(tmp10, tmp10, ctx); ADD(tmp8, tmp9, tmp10, ctx); SUB_SI(tmp8, tmp8, 3, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); ADD(tmp4, tmp5, tmp6, ctx); SQRT_UI(tmp7, 2, ctx); MUL_SI(tmp7, tmp7, -12, ctx); SQRT_UI(tmp8, 2, ctx); NEG(tmp8, tmp8, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); MUL_SI(tmp8, tmp8, 2, ctx); SUB(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp7, 2, ctx); MUL_SI(tmp7, tmp7, -17, ctx); ADD_SI(tmp7, tmp7, 26, ctx); SQRT(tmp7, tmp7, ctx); MUL_SI(tmp7, tmp7, 2, ctx); SUB(tmp5, tmp6, tmp7, ctx); ADD_SI(tmp5, tmp5, 24, ctx); SQRT(tmp5, tmp5, ctx); MUL(tmp3, tmp4, tmp5, ctx); SUB(tmp1, tmp2, tmp3, ctx); CONST_I(tmp10, ctx); MUL_SI(tmp10, tmp10, 24, ctx); SQRT_UI(tmp11, 2, ctx); MUL(tmp9, tmp10, tmp11, ctx); CONST_I(tmp11, ctx); MUL_SI(tmp11, tmp11, 4, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, -17, ctx); ADD_SI(tmp12, tmp12, 26, ctx); SQRT(tmp12, tmp12, ctx); MUL(tmp10, tmp11, tmp12, ctx); ADD(tmp8, tmp9, tmp10, ctx); CONST_I(tmp9, ctx); MUL_SI(tmp9, tmp9, 32, ctx); SUB(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp8, 2, ctx); NEG(tmp8, tmp8, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); CONST_I(tmp9, ctx); MUL_SI(tmp9, tmp9, 8, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 3, ctx); SUB_SI(tmp10, tmp10, 4, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, -17, ctx); ADD_SI(tmp9, tmp9, 26, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); ADD(tmp5, tmp6, tmp7, ctx); CONST_I(tmp7, ctx); MUL_SI(tmp7, tmp7, 228, ctx); SQRT_UI(tmp8, 2, ctx); MUL(tmp6, tmp7, tmp8, ctx); SUB(tmp4, tmp5, tmp6, ctx); CONST_I(tmp5, ctx); MUL_SI(tmp5, tmp5, 328, ctx); ADD(tmp3, tmp4, tmp5, ctx); SQRT_UI(tmp4, 2, ctx); ADD_SI(tmp4, tmp4, 2, ctx); SQRT(tmp4, tmp4, ctx); SUB_SI(tmp4, tmp4, 1, ctx); SQRT(tmp4, tmp4, ctx); MUL(tmp2, tmp3, tmp4, ctx); SUB(tmp0, tmp1, tmp2, ctx); NEG(tmp0, tmp0, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 6, ctx); SQRT_UI(tmp11, 2, ctx); NEG(tmp11, tmp11, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); ADD(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, -17, ctx); ADD_SI(tmp10, tmp10, 26, ctx); SQRT(tmp10, tmp10, ctx); ADD(tmp8, tmp9, tmp10, ctx); SUB_SI(tmp8, tmp8, 8, ctx); MUL_SI(tmp8, tmp8, 4, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 3, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, -17, ctx); ADD_SI(tmp11, tmp11, 26, ctx); SQRT(tmp11, tmp11, ctx); ADD(tmp9, tmp10, tmp11, ctx); SUB_SI(tmp9, tmp9, 3, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp8, 2, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); SUB_SI(tmp8, tmp8, 1, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp10, 2, ctx); MUL_SI(tmp10, tmp10, 3, ctx); SQRT_UI(tmp11, 2, ctx); NEG(tmp11, tmp11, ctx); ADD_SI(tmp11, tmp11, 2, ctx); SQRT(tmp11, tmp11, ctx); ADD(tmp9, tmp10, tmp11, ctx); SUB_SI(tmp9, tmp9, 5, ctx); SQRT(tmp9, tmp9, ctx); CONST_I(tmp14, ctx); MUL_SI(tmp14, tmp14, -24, ctx); SQRT_UI(tmp15, 2, ctx); MUL(tmp13, tmp14, tmp15, ctx); CONST_I(tmp15, ctx); MUL_SI(tmp15, tmp15, 4, ctx); SQRT_UI(tmp16, 2, ctx); NEG(tmp16, tmp16, ctx); ADD_SI(tmp16, tmp16, 2, ctx); SQRT(tmp16, tmp16, ctx); MUL(tmp14, tmp15, tmp16, ctx); SUB(tmp12, tmp13, tmp14, ctx); CONST_I(tmp14, ctx); MUL_SI(tmp14, tmp14, 4, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, -17, ctx); ADD_SI(tmp15, tmp15, 26, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); SUB(tmp11, tmp12, tmp13, ctx); CONST_I(tmp12, ctx); MUL_SI(tmp12, tmp12, 32, ctx); ADD(tmp10, tmp11, tmp12, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); SUB_SI(tmp9, tmp9, 1, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); ADD(tmp5, tmp6, tmp7, ctx); SQRT_UI(tmp8, 2, ctx); MUL_SI(tmp8, tmp8, 6, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, -17, ctx); ADD_SI(tmp9, tmp9, 26, ctx); SQRT(tmp9, tmp9, ctx); ADD(tmp7, tmp8, tmp9, ctx); SUB_SI(tmp7, tmp7, 8, ctx); MUL_SI(tmp7, tmp7, 4, ctx); SQRT_UI(tmp8, 2, ctx); NEG(tmp8, tmp8, ctx); ADD_SI(tmp8, tmp8, 2, ctx); SQRT(tmp8, tmp8, ctx); MUL(tmp6, tmp7, tmp8, ctx); SUB(tmp4, tmp5, tmp6, ctx); CONST_I(tmp14, ctx); SQRT_UI(tmp15, 2, ctx); MUL(tmp13, tmp14, tmp15, ctx); SQRT_UI(tmp14, 2, ctx); NEG(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); CONST_I(tmp15, ctx); SQRT_UI(tmp16, 2, ctx); MUL(tmp14, tmp15, tmp16, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, -17, ctx); ADD_SI(tmp15, tmp15, 26, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); ADD(tmp11, tmp12, tmp13, ctx); CONST_I(tmp13, ctx); MUL_SI(tmp13, tmp13, 8, ctx); SQRT_UI(tmp14, 2, ctx); MUL(tmp12, tmp13, tmp14, ctx); SUB(tmp10, tmp11, tmp12, ctx); CONST_I(tmp11, ctx); MUL_SI(tmp11, tmp11, 12, ctx); ADD(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp11, 2, ctx); MUL_SI(tmp11, tmp11, 3, ctx); SQRT_UI(tmp12, 2, ctx); NEG(tmp12, tmp12, ctx); ADD_SI(tmp12, tmp12, 2, ctx); SQRT(tmp12, tmp12, ctx); ADD(tmp10, tmp11, tmp12, ctx); SUB_SI(tmp10, tmp10, 5, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); ADD_SI(tmp9, tmp9, 2, ctx); SQRT(tmp9, tmp9, ctx); SUB_SI(tmp9, tmp9, 1, ctx); SQRT(tmp9, tmp9, ctx); MUL(tmp7, tmp8, tmp9, ctx); SQRT_UI(tmp13, 2, ctx); SQRT_UI(tmp14, 2, ctx); NEG(tmp14, tmp14, ctx); ADD_SI(tmp14, tmp14, 2, ctx); SQRT(tmp14, tmp14, ctx); MUL(tmp12, tmp13, tmp14, ctx); SQRT_UI(tmp14, 2, ctx); SQRT_UI(tmp15, 2, ctx); MUL_SI(tmp15, tmp15, -17, ctx); ADD_SI(tmp15, tmp15, 26, ctx); SQRT(tmp15, tmp15, ctx); MUL(tmp13, tmp14, tmp15, ctx); ADD(tmp11, tmp12, tmp13, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 8, ctx); SUB(tmp10, tmp11, tmp12, ctx); ADD_SI(tmp10, tmp10, 12, ctx); SQRT_UI(tmp12, 2, ctx); MUL_SI(tmp12, tmp12, 3, ctx); SQRT_UI(tmp13, 2, ctx); MUL_SI(tmp13, tmp13, -17, ctx); ADD_SI(tmp13, tmp13, 26, ctx); SQRT(tmp13, tmp13, ctx); ADD(tmp11, tmp12, tmp13, ctx); SUB_SI(tmp11, tmp11, 3, ctx); SQRT(tmp11, tmp11, ctx); MUL(tmp9, tmp10, tmp11, ctx); SQRT_UI(tmp10, 2, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); SUB_SI(tmp10, tmp10, 1, ctx); SQRT(tmp10, tmp10, ctx); MUL(tmp8, tmp9, tmp10, ctx); SUB(tmp6, tmp7, tmp8, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, -12, ctx); SQRT_UI(tmp10, 2, ctx); NEG(tmp10, tmp10, ctx); ADD_SI(tmp10, tmp10, 2, ctx); SQRT(tmp10, tmp10, ctx); MUL_SI(tmp10, tmp10, 2, ctx); SUB(tmp8, tmp9, tmp10, ctx); SQRT_UI(tmp9, 2, ctx); MUL_SI(tmp9, tmp9, -17, ctx); ADD_SI(tmp9, tmp9, 26, ctx); SQRT(tmp9, tmp9, ctx); MUL_SI(tmp9, tmp9, 2, ctx); SUB(tmp7, tmp8, tmp9, ctx); ADD_SI(tmp7, tmp7, 24, ctx); SQRT(tmp7, tmp7, ctx); MUL(tmp5, tmp6, tmp7, ctx); ADD(tmp3, tmp4, tmp5, ctx); SQRT_UI(tmp5, 2, ctx); MUL_SI(tmp5, tmp5, 3, ctx); SUB_SI(tmp5, tmp5, 4, ctx); MUL_SI(tmp5, tmp5, 8, ctx); SQRT_UI(tmp6, 2, ctx); MUL_SI(tmp6, tmp6, -17, ctx); ADD_SI(tmp6, tmp6, 26, ctx); SQRT(tmp6, tmp6, ctx); MUL(tmp4, tmp5, tmp6, ctx); SUB(tmp2, tmp3, tmp4, ctx); SQRT_UI(tmp3, 2, ctx); MUL_SI(tmp3, tmp3, 228, ctx); ADD(tmp1, tmp2, tmp3, ctx); SUB_SI(tmp1, tmp1, 328, ctx); DIV(M, tmp0, tmp1, ctx); TIMEIT_ONCE_STOP flint_printf("Evaluating E = -(1-|M|^2)^2...\n"); TIMEIT_ONCE_START ABS(E, M, ctx); POW_UI(E, E, 2, ctx); SUB_SI(E, E, 1, ctx); NEG(E, E, ctx); POW_UI(E, E, 2, ctx); NEG(E, E, ctx); TIMEIT_ONCE_STOP if (status != GR_SUCCESS) { flint_printf("evaluation failed\n"); flint_abort(); } flint_printf("N ~ "); gr_println(N, ctx); flint_printf("E ~ "); gr_println(E, ctx); flint_printf("Testing E = N...\n"); TIMEIT_ONCE_START equal = gr_equal(E, N, ctx); TIMEIT_ONCE_STOP flint_printf("\nEqual = "); truth_print(equal); flint_printf("\n"); GR_TMP_CLEAR3(N, M, E, ctx); GR_TMP_CLEAR5(tmp0, tmp1, tmp2, tmp3, tmp4, ctx); GR_TMP_CLEAR5(tmp5, tmp6, tmp7, tmp8, tmp9, ctx); GR_TMP_CLEAR5(tmp10, tmp11, tmp12, tmp13, tmp14, ctx); GR_TMP_CLEAR5(tmp15, tmp16, tmp17, tmp18, tmp19, ctx); GR_TMP_CLEAR5(tmp20, tmp21, tmp22, tmp23, tmp24, ctx); GR_TMP_CLEAR5(tmp25, tmp26, tmp27, tmp28, tmp29, ctx); GR_TMP_CLEAR5(tmp30, tmp31, tmp32, tmp33, tmp34, ctx); } int main(int argc, char *argv[]) { TIMEIT_ONCE_START if (argc >= 2 && strcmp(argv[1], "-ca") == 0) { gr_ctx_t ctx; gr_ctx_init_complex_algebraic_ca(ctx); gr_ctx_ca_set_option(ctx, CA_OPT_QQBAR_DEG_LIMIT, 10000); doit(ctx); gr_ctx_clear(ctx); } else { gr_ctx_t ctx; gr_ctx_init_complex_qqbar(ctx); doit(ctx); gr_ctx_clear(ctx); } flint_printf("\n"); flint_printf("Total: "); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE flint_cleanup_master(); return 0; } flint-3.1.3/examples/integrals.c000066400000000000000000001044261461254215100166140ustar00rootroot00000000000000/* Rigorous numerical integration (with fast convergence for piecewise holomorphic functions) using Gauss-Legendre quadrature and adaptive subdivision. Author: Fredrik Johansson. This file is in the public domain. */ #include #include #include #include "profiler.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #include "acb_dirichlet.h" #include "acb_modular.h" #include "acb_calc.h" /* ------------------------------------------------------------------------- */ /* Example integrands */ /* ------------------------------------------------------------------------- */ /* f(z) = sin(z) */ int f_sin(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_sin(res, z, prec); return 0; } /* f(z) = floor(z) */ int f_floor(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_real_floor(res, z, order != 0, prec); return 0; } /* f(z) = sqrt(1-z^2) */ int f_circle(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_one(res); acb_submul(res, z, z, prec); acb_real_sqrtpos(res, res, order != 0, prec); return 0; } /* f(z) = 1/(1+z^2) */ int f_atanderiv(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_mul(res, z, z, prec); acb_add_ui(res, res, 1, prec); acb_inv(res, res, prec); return 0; } /* f(z) = sin(z + exp(z)) -- Rump's oscillatory example */ int f_rump(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_exp(res, z, prec); acb_add(res, res, z, prec); acb_sin(res, res, prec); return 0; } /* f(z) = |z^4 + 10z^3 + 19z^2 - 6z - 6| exp(z) (for real z) -- Helfgott's integral on MathOverflow */ int f_helfgott(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_add_si(res, z, 10, prec); acb_mul(res, res, z, prec); acb_add_si(res, res, 19, prec); acb_mul(res, res, z, prec); acb_add_si(res, res, -6, prec); acb_mul(res, res, z, prec); acb_add_si(res, res, -6, prec); acb_real_abs(res, res, order != 0, prec); if (acb_is_finite(res)) { acb_t t; acb_init(t); acb_exp(t, z, prec); acb_mul(res, res, t, prec); acb_clear(t); } return 0; } /* f(z) = zeta(z) */ int f_zeta(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_zeta(res, z, prec); return 0; } /* f(z) = z sin(1/z), assume on real interval */ int f_essing2(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ if ((order == 0) && acb_is_real(z) && arb_contains_zero(acb_realref(z))) { /* todo: arb_zero_pm_one, arb_unit_interval? */ acb_zero(res); mag_one(arb_radref(acb_realref(res))); } else { acb_inv(res, z, prec); acb_sin(res, res, prec); } acb_mul(res, res, z, prec); return 0; } /* f(z) = sin(1/z), assume on real interval */ int f_essing(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ if ((order == 0) && acb_is_real(z) && arb_contains_zero(acb_realref(z))) { /* todo: arb_zero_pm_one, arb_unit_interval? */ acb_zero(res); mag_one(arb_radref(acb_realref(res))); } else { acb_inv(res, z, prec); acb_sin(res, res, prec); } return 0; } /* f(z) = exp(-z) z^1000 */ int f_factorial1000(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_pow_ui(t, z, 1000, prec); acb_neg(res, z); acb_exp(res, res, prec); acb_mul(res, res, t, prec); acb_clear(t); return 0; } /* f(z) = gamma(z) */ int f_gamma(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_gamma(res, z, prec); return 0; } /* f(z) = sin(z) + exp(-200-z^2) */ int f_sin_plus_small(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_mul(t, z, z, prec); acb_add_ui(t, t, 200, prec); acb_neg(t, t); acb_exp(t, t, prec); acb_sin(res, z, prec); acb_add(res, res, t, prec); acb_clear(t); return 0; } /* f(z) = exp(z) */ int f_exp(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_exp(res, z, prec); return 0; } /* f(z) = exp(-z^2) */ int f_gaussian(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_mul(res, z, z, prec); acb_neg(res, res); acb_exp(res, res, prec); return 0; } int f_monster(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_exp(t, z, prec); acb_real_floor(res, t, order != 0, prec); if (acb_is_finite(res)) { acb_sub(res, t, res, prec); acb_add(t, t, z, prec); acb_sin(t, t, prec); acb_mul(res, res, t, prec); } acb_clear(t); return 0; } /* f(z) = sech(10(x-0.2))^2 + sech(100(x-0.4))^4 + sech(1000(x-0.6))^6 */ int f_spike(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t a, b, c; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(a); acb_init(b); acb_init(c); acb_mul_ui(a, z, 10, prec); acb_sub_ui(a, a, 2, prec); acb_sech(a, a, prec); acb_pow_ui(a, a, 2, prec); acb_mul_ui(b, z, 100, prec); acb_sub_ui(b, b, 40, prec); acb_sech(b, b, prec); acb_pow_ui(b, b, 4, prec); acb_mul_ui(c, z, 1000, prec); acb_sub_ui(c, c, 600, prec); acb_sech(c, c, prec); acb_pow_ui(c, c, 6, prec); acb_add(res, a, b, prec); acb_add(res, res, c, prec); acb_clear(a); acb_clear(b); acb_clear(c); return 0; } /* f(z) = sech(z) */ int f_sech(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_sech(res, z, prec); return 0; } /* f(z) = sech^3(z) */ int f_sech3(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_sech(res, z, prec); acb_cube(res, res, prec); return 0; } /* f(z) = -log(z) / (1 + z) */ int f_log_div1p(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_add_ui(t, z, 1, prec); acb_log(res, z, prec); acb_div(res, res, t, prec); acb_neg(res, res); acb_clear(t); return 0; } /* f(z) = z exp(-z) / (1 + exp(-z)) */ int f_log_div1p_transformed(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_neg(t, z); acb_exp(t, t, prec); acb_add_ui(res, t, 1, prec); acb_div(res, t, res, prec); acb_mul(res, res, z, prec); acb_clear(t); return 0; } int f_elliptic_p_laurent_n(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { slong n; acb_t tau; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ n = ((slong *)(param))[0]; acb_init(tau); acb_onei(tau); acb_modular_elliptic_p(res, z, tau, prec); acb_pow_si(tau, z, -n - 1, prec); acb_mul(res, res, tau, prec); acb_clear(tau); return 0; } /* f(z) = zeta'(z) / zeta(z) */ int f_zeta_frac(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_struct t[2]; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_init(t + 1); acb_dirichlet_zeta_jet(t, z, 0, 2, prec); acb_div(res, t + 1, t, prec); acb_clear(t); acb_clear(t + 1); return 0; } int f_lambertw(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); prec = FLINT_MIN(prec, acb_rel_accuracy_bits(z) + 10); if (order != 0) { /* check for branch cut */ arb_const_e(acb_realref(t), prec); acb_inv(t, t, prec); acb_add(t, t, z, prec); if (arb_contains_zero(acb_imagref(t)) && arb_contains_nonpositive(acb_realref(t))) { acb_indeterminate(t); } } if (acb_is_finite(t)) { fmpz_t k; fmpz_init(k); acb_lambertw(res, z, k, 0, prec); fmpz_clear(k); } else { acb_indeterminate(res); } acb_clear(t); return 0; } /* f(z) = max(sin(z), cos(z)) */ int f_max_sin_cos(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, c; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(s); acb_init(c); acb_sin_cos(s, c, z, prec); acb_real_max(res, s, c, order != 0, prec); acb_clear(s); acb_clear(c); return 0; } /* f(z) = erf(z/sqrt(0.0002)*0.5 +1.5)*exp(-z), example provided by Silviu-Ioan Filip */ int f_erf_bent(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_set_ui(t, 1250); acb_sqrt(t, t, prec); acb_mul(t, t, z, prec); acb_set_d(res, 1.5); acb_add(res, res, t, prec); acb_hypgeom_erf(res, res, prec); acb_neg(t, z); acb_exp(t, t, prec); acb_mul(res, res, t, prec); acb_clear(t); return 0; } /* f(z) = Ai(z) */ int f_airy_ai(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_hypgeom_airy(res, NULL, NULL, NULL, z, prec); return 0; } int f_horror(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(s); acb_init(t); acb_real_floor(res, z, order != 0, prec); if (acb_is_finite(res)) { acb_sub(res, z, res, prec); acb_set_d(t, 0.5); acb_sub(res, res, t, prec); acb_sin_cos(s, t, z, prec); acb_real_max(s, s, t, order != 0, prec); acb_mul(res, res, s, prec); } acb_clear(s); acb_clear(t); return 0; } /* f(z) = sqrt(z) */ int f_sqrt(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_sqrt_analytic(res, z, order != 0, prec); return 0; } /* f(z) = 1/sqrt(z) */ int f_rsqrt(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_rsqrt_analytic(res, z, order != 0, prec); return 0; } /* f(z) = rgamma(z) */ int f_rgamma(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_rgamma(res, z, prec); return 0; } /* f(z) = exp(-z^2+iz) */ int f_gaussian_twist(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_mul_onei(res, z); acb_submul(res, z, z, prec); acb_exp(res, res, prec); return 0; } /* f(z) = exp(-z) Ai(-z) */ int f_exp_airy(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_neg(t, z); acb_hypgeom_airy(res, NULL, NULL, NULL, t, prec); acb_exp(t, t, prec); acb_mul(res, res, t, prec); acb_clear(t); return 0; } /* f(z) = z sin(z) / (1 + cos(z)^2) */ int f_sin_cos_frac(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, c; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(s); acb_init(c); acb_sin_cos(s, c, z, prec); acb_mul(c, c, c, prec); acb_add_ui(c, c, 1, prec); acb_mul(s, s, z, prec); acb_div(res, s, c, prec); acb_clear(s); acb_clear(c); return 0; } /* f(z) = sin((1/1000 + (1-z)^2)^(-3/2)), example from Mioara Joldes' thesis (suggested by Nicolas Brisebarre) */ int f_sin_near_essing(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t, u; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_init(u); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_mul(t, t, t, prec); acb_one(u); acb_div_ui(u, u, 1000, prec); acb_add(t, t, u, prec); acb_set_d(u, -1.5); acb_pow_analytic(t, t, u, order != 0, prec); acb_sin(res, t, prec); acb_clear(t); acb_clear(u); return 0; } /* f(z) = exp(-z) (I_0(z/k))^k, from Bruno Salvy */ int f_scaled_bessel(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t nu; ulong k = ((ulong *) param)[0]; acb_init(nu); acb_div_ui(res, z, k, prec); acb_hypgeom_bessel_i_scaled(res, nu, res, prec); acb_pow_ui(res, res, k, prec); acb_clear(nu); return 0; } /* Bound for scaled Bessel function: 2/(2 pi x)^(1/2) Bound for tail of integral: 2 N (k / (pi N))^(k / 2) / (k - 2). */ void scaled_bessel_tail_bound(arb_t b, ulong k, const arb_t N, slong prec) { arb_const_pi(b, prec); arb_mul(b, b, N, prec); arb_ui_div(b, k, b, prec); arb_sqrt(b, b, prec); arb_pow_ui(b, b, k, prec); arb_mul(b, b, N, prec); arb_mul_ui(b, b, 2, prec); arb_div_ui(b, b, k - 2, prec); } void scaled_bessel_select_N(arb_t N, ulong k, slong prec) { slong e; double f = log(k/3.14159265358979)/log(2); e = 1; while ((k / 2.0) * (e - f) - e < prec + 5) e++; arb_one(N); arb_mul_2exp_si(N, N, e); } /* ------------------------------------------------------------------------- */ /* Main test program */ /* ------------------------------------------------------------------------- */ #define NUM_INTEGRALS 37 const char * descr[NUM_INTEGRALS] = { "int_0^100 sin(x) dx", "4 int_0^1 1/(1+x^2) dx", "2 int_0^{inf} 1/(1+x^2) dx (using domain truncation)", "4 int_0^1 sqrt(1-x^2) dx", "int_0^8 sin(x+exp(x)) dx", "int_1^101 floor(x) dx", "int_0^1 |x^4+10x^3+19x^2-6x-6| exp(x) dx", "1/(2 pi i) int zeta(s) ds (closed path around s = 1)", "int_0^1 sin(1/x) dx (slow convergence, use -heap and/or -tol)", "int_0^1 x sin(1/x) dx (slow convergence, use -heap and/or -tol)", "int_0^10000 x^1000 exp(-x) dx", "int_1^{1+1000i} gamma(x) dx", "int_{-10}^{10} sin(x) + exp(-200-x^2) dx", "int_{-1020}^{-1010} exp(x) dx (use -tol 0 for relative error)", "int_0^{inf} exp(-x^2) dx (using domain truncation)", "int_0^1 sech(10(x-0.2))^2 + sech(100(x-0.4))^4 + sech(1000(x-0.6))^6 dx", "int_0^8 (exp(x)-floor(exp(x))) sin(x+exp(x)) dx (use higher -eval)", "int_0^{inf} sech(x) dx (using domain truncation)", "int_0^{inf} sech^3(x) dx (using domain truncation)", "int_0^1 -log(x)/(1+x) dx (using domain truncation)", "int_0^{inf} x exp(-x)/(1+exp(-x)) dx (using domain truncation)", "int_C wp(x)/x^(11) dx (contour for 10th Laurent coefficient of Weierstrass p-function)", "N(1000) = count zeros with 0 < t <= 1000 of zeta(s) using argument principle", "int_0^{1000} W_0(x) dx", "int_0^pi max(sin(x), cos(x)) dx", "int_{-1}^1 erf(x/sqrt(0.0002)*0.5+1.5)*exp(-x) dx", "int_{-10}^10 Ai(x) dx", "int_0^10 (x-floor(x)-1/2) max(sin(x),cos(x)) dx", "int_{-1-i}^{-1+i} sqrt(x) dx", "int_0^{inf} exp(-x^2+ix) dx (using domain truncation)", "int_0^{inf} exp(-x) Ai(-x) dx (using domain truncation)", "int_0^pi x sin(x) / (1 + cos(x)^2) dx", "int_0^3 sin(0.001 + (1-x)^2)^(-3/2)) dx (slow convergence, use higher -eval)", "int_0^{inf} exp(-x) I_0(x/3)^3 dx (using domain truncation)", "int_0^{inf} exp(-x) I_0(x/15)^{15} dx (using domain truncation)", "int_{-1-i}^{-1+i} 1/sqrt(x) dx", "int_0^{inf} 1/gamma(x) dx (using domain truncation)", }; int main(int argc, char *argv[]) { acb_t s, t, a, b; mag_t tol; slong num_threads; slong prec, goal; slong N; ulong k; int integral, ifrom, ito; int i, twice, havegoal, havetol; acb_calc_integrate_opt_t options; ifrom = ito = -1; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-i")) { if (!strcmp(argv[i+1], "all")) { ifrom = 0; ito = NUM_INTEGRALS - 1; } else { ifrom = ito = atol(argv[i+1]); if (ito < 0 || ito >= NUM_INTEGRALS) flint_abort(); } } } if (ifrom == -1) { flint_printf("Compute integrals using acb_calc_integrate.\n"); flint_printf("Usage: integrals -i n [-prec p] [-tol eps] [-twice] [...]\n\n"); flint_printf("-i n - compute integral n (0 <= n <= %d), or \"-i all\"\n", NUM_INTEGRALS - 1); flint_printf("-prec p - precision in bits (default p = 64)\n"); flint_printf("-goal p - approximate relative accuracy goal (default p)\n"); flint_printf("-tol eps - approximate absolute error goal (default 2^-p)\n"); flint_printf("-twice - run twice (to see overhead of computing nodes)\n"); flint_printf("-heap - use heap for subinterval queue\n"); flint_printf("-verbose - show information\n"); flint_printf("-verbose2 - show more information\n"); flint_printf("-deg n - use quadrature degree up to n\n"); flint_printf("-eval n - limit number of function evaluations to n\n"); flint_printf("-depth n - limit subinterval queue size to n\n"); flint_printf("-threads n - use parallel computation with n threads\n\n"); flint_printf("Implemented integrals:\n"); for (integral = 0; integral < NUM_INTEGRALS; integral++) flint_printf("I%d = %s\n", integral, descr[integral]); flint_printf("\n"); return 1; } acb_calc_integrate_opt_init(options); prec = 64; twice = 0; goal = 0; havetol = havegoal = 0; num_threads = 1; acb_init(a); acb_init(b); acb_init(s); acb_init(t); mag_init(tol); for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-prec")) { prec = atol(argv[i+1]); } else if (!strcmp(argv[i], "-twice")) { twice = 1; } else if (!strcmp(argv[i], "-goal")) { goal = atol(argv[i+1]); if (goal < 0) { flint_printf("expected goal >= 0\n"); return 1; } havegoal = 1; } else if (!strcmp(argv[i], "-tol")) { arb_t x; arb_init(x); arb_set_str(x, argv[i+1], 10); arb_get_mag(tol, x); arb_clear(x); havetol = 1; } else if (!strcmp(argv[i], "-deg")) { options->deg_limit = atol(argv[i+1]); } else if (!strcmp(argv[i], "-eval")) { options->eval_limit = atol(argv[i+1]); } else if (!strcmp(argv[i], "-depth")) { options->depth_limit = atol(argv[i+1]); } else if (!strcmp(argv[i], "-verbose")) { options->verbose = 1; } else if (!strcmp(argv[i], "-verbose2")) { options->verbose = 2; } else if (!strcmp(argv[i], "-heap")) { options->use_heap = 1; } else if (!strcmp(argv[i], "-threads")) { num_threads = atol(argv[i+1]); } } if (num_threads >= 2) flint_set_num_threads(num_threads); if (!havegoal) goal = prec; if (!havetol) mag_set_ui_2exp_si(tol, 1, -prec); for (integral = ifrom; integral <= ito; integral++) { flint_printf("I%d = %s ...\n", integral, descr[integral]); for (i = 0; i < 1 + twice; i++) { TIMEIT_ONCE_START switch (integral) { case 0: acb_set_d(a, 0); acb_set_d(b, 100); acb_calc_integrate(s, f_sin, NULL, a, b, goal, tol, options, prec); break; case 1: acb_set_d(a, 0); acb_set_d(b, 1); acb_calc_integrate(s, f_atanderiv, NULL, a, b, goal, tol, options, prec); acb_mul_2exp_si(s, s, 2); break; case 2: acb_set_d(a, 0); acb_one(b); acb_mul_2exp_si(b, b, goal); acb_calc_integrate(s, f_atanderiv, NULL, a, b, goal, tol, options, prec); arb_add_error_2exp_si(acb_realref(s), -goal); acb_mul_2exp_si(s, s, 1); break; case 3: acb_set_d(a, 0); acb_set_d(b, 1); acb_calc_integrate(s, f_circle, NULL, a, b, goal, tol, options, prec); acb_mul_2exp_si(s, s, 2); break; case 4: acb_set_d(a, 0); acb_set_d(b, 8); acb_calc_integrate(s, f_rump, NULL, a, b, goal, tol, options, prec); break; case 5: acb_set_d(a, 1); acb_set_d(b, 101); acb_calc_integrate(s, f_floor, NULL, a, b, goal, tol, options, prec); break; case 6: acb_set_d(a, 0); acb_set_d(b, 1); acb_calc_integrate(s, f_helfgott, NULL, a, b, goal, tol, options, prec); break; case 7: acb_zero(s); acb_set_d_d(a, -1.0, -1.0); acb_set_d_d(b, 2.0, -1.0); acb_calc_integrate(t, f_zeta, NULL, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_set_d_d(a, 2.0, -1.0); acb_set_d_d(b, 2.0, 1.0); acb_calc_integrate(t, f_zeta, NULL, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_set_d_d(a, 2.0, 1.0); acb_set_d_d(b, -1.0, 1.0); acb_calc_integrate(t, f_zeta, NULL, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_set_d_d(a, -1.0, 1.0); acb_set_d_d(b, -1.0, -1.0); acb_calc_integrate(t, f_zeta, NULL, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_const_pi(t, prec); acb_div(s, s, t, prec); acb_mul_2exp_si(s, s, -1); acb_div_onei(s, s); break; case 8: acb_set_d(a, 0); acb_set_d(b, 1); acb_calc_integrate(s, f_essing, NULL, a, b, goal, tol, options, prec); break; case 9: acb_set_d(a, 0); acb_set_d(b, 1); acb_calc_integrate(s, f_essing2, NULL, a, b, goal, tol, options, prec); break; case 10: acb_set_d(a, 0); acb_set_d(b, 10000); acb_calc_integrate(s, f_factorial1000, NULL, a, b, goal, tol, options, prec); break; case 11: acb_set_d_d(a, 1.0, 0.0); acb_set_d_d(b, 1.0, 1000.0); acb_calc_integrate(s, f_gamma, NULL, a, b, goal, tol, options, prec); break; case 12: acb_set_d(a, -10.0); acb_set_d(b, 10.0); acb_calc_integrate(s, f_sin_plus_small, NULL, a, b, goal, tol, options, prec); break; case 13: acb_set_d(a, -1020.0); acb_set_d(b, -1010.0); acb_calc_integrate(s, f_exp, NULL, a, b, goal, tol, options, prec); break; case 14: acb_set_d(a, 0); acb_set_d(b, ceil(sqrt(goal * 0.693147181) + 1.0)); acb_calc_integrate(s, f_gaussian, NULL, a, b, goal, tol, options, prec); acb_mul(b, b, b, prec); acb_neg(b, b); acb_exp(b, b, prec); arb_add_error(acb_realref(s), acb_realref(b)); break; case 15: acb_set_d(a, 0.0); acb_set_d(b, 1.0); acb_calc_integrate(s, f_spike, NULL, a, b, goal, tol, options, prec); break; case 16: acb_set_d(a, 0.0); acb_set_d(b, 8.0); acb_calc_integrate(s, f_monster, NULL, a, b, goal, tol, options, prec); break; case 17: acb_set_d(a, 0); acb_set_d(b, ceil(goal * 0.693147181 + 1.0)); acb_calc_integrate(s, f_sech, NULL, a, b, goal, tol, options, prec); acb_neg(b, b); acb_exp(b, b, prec); acb_mul_2exp_si(b, b, 1); arb_add_error(acb_realref(s), acb_realref(b)); break; case 18: acb_set_d(a, 0); acb_set_d(b, ceil(goal * 0.693147181 / 3.0 + 2.0)); acb_calc_integrate(s, f_sech3, NULL, a, b, goal, tol, options, prec); acb_neg(b, b); acb_mul_ui(b, b, 3, prec); acb_exp(b, b, prec); acb_mul_2exp_si(b, b, 3); acb_div_ui(b, b, 3, prec); arb_add_error(acb_realref(s), acb_realref(b)); break; case 19: if (goal < 0) abort(); /* error bound 2^-N (1+N) when truncated at 2^-N */ N = goal + FLINT_BIT_COUNT(goal); acb_one(a); acb_mul_2exp_si(a, a, -N); acb_one(b); acb_calc_integrate(s, f_log_div1p, NULL, a, b, goal, tol, options, prec); acb_set_ui(b, N + 1); acb_mul_2exp_si(b, b, -N); arb_add_error(acb_realref(s), acb_realref(b)); break; case 20: if (goal < 0) abort(); /* error bound (N+1) exp(-N) when truncated at N */ N = goal + FLINT_BIT_COUNT(goal); acb_zero(a); acb_set_ui(b, N); acb_calc_integrate(s, f_log_div1p_transformed, NULL, a, b, goal, tol, options, prec); acb_neg(b, b); acb_exp(b, b, prec); acb_mul_ui(b, b, N + 1, prec); arb_add_error(acb_realref(s), acb_realref(b)); break; case 21: acb_zero(s); N = 10; acb_set_d_d(a, 0.5, -0.5); acb_set_d_d(b, 0.5, 0.5); acb_calc_integrate(t, f_elliptic_p_laurent_n, &N, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_set_d_d(a, 0.5, 0.5); acb_set_d_d(b, -0.5, 0.5); acb_calc_integrate(t, f_elliptic_p_laurent_n, &N, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_set_d_d(a, -0.5, 0.5); acb_set_d_d(b, -0.5, -0.5); acb_calc_integrate(t, f_elliptic_p_laurent_n, &N, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_set_d_d(a, -0.5, -0.5); acb_set_d_d(b, 0.5, -0.5); acb_calc_integrate(t, f_elliptic_p_laurent_n, &N, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_const_pi(t, prec); acb_div(s, s, t, prec); acb_mul_2exp_si(s, s, -1); acb_div_onei(s, s); break; case 22: acb_zero(s); N = 1000; acb_set_d_d(a, 100.0, 0.0); acb_set_d_d(b, 100.0, N); acb_calc_integrate(t, f_zeta_frac, NULL, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_set_d_d(a, 100, N); acb_set_d_d(b, 0.5, N); acb_calc_integrate(t, f_zeta_frac, NULL, a, b, goal, tol, options, prec); acb_add(s, s, t, prec); acb_div_onei(s, s); arb_zero(acb_imagref(s)); acb_set_ui(t, N); acb_dirichlet_hardy_theta(t, t, NULL, NULL, 1, prec); acb_add(s, s, t, prec); acb_const_pi(t, prec); acb_div(s, s, t, prec); acb_add_ui(s, s, 1, prec); break; case 23: acb_set_d(a, 0.0); acb_set_d(b, 1000.0); acb_calc_integrate(s, f_lambertw, NULL, a, b, goal, tol, options, prec); break; case 24: acb_set_d(a, 0.0); acb_const_pi(b, prec); acb_calc_integrate(s, f_max_sin_cos, NULL, a, b, goal, tol, options, prec); break; case 25: acb_set_si(a, -1); acb_set_si(b, 1); acb_calc_integrate(s, f_erf_bent, NULL, a, b, goal, tol, options, prec); break; case 26: acb_set_si(a, -10); acb_set_si(b, 10); acb_calc_integrate(s, f_airy_ai, NULL, a, b, goal, tol, options, prec); break; case 27: acb_set_si(a, 0); acb_set_si(b, 10); acb_calc_integrate(s, f_horror, NULL, a, b, goal, tol, options, prec); break; case 28: acb_set_d_d(a, -1, -1); acb_set_d_d(b, -1, 1); acb_calc_integrate(s, f_sqrt, NULL, a, b, goal, tol, options, prec); break; case 29: acb_set_d(a, 0); acb_set_d(b, ceil(sqrt(goal * 0.693147181) + 1.0)); acb_calc_integrate(s, f_gaussian_twist, NULL, a, b, goal, tol, options, prec); acb_mul(b, b, b, prec); acb_neg(b, b); acb_exp(b, b, prec); arb_add_error(acb_realref(s), acb_realref(b)); arb_add_error(acb_imagref(s), acb_realref(b)); break; case 30: acb_set_d(a, 0); acb_set_d(b, ceil(goal * 0.693147181 + 1.0)); acb_calc_integrate(s, f_exp_airy, NULL, a, b, goal, tol, options, prec); acb_neg(b, b); acb_exp(b, b, prec); acb_mul_2exp_si(b, b, 1); arb_add_error(acb_realref(s), acb_realref(b)); break; case 31: acb_zero(a); acb_const_pi(b, prec); acb_calc_integrate(s, f_sin_cos_frac, NULL, a, b, goal, tol, options, prec); break; case 32: acb_zero(a); acb_set_ui(b, 3); acb_calc_integrate(s, f_sin_near_essing, NULL, a, b, goal, tol, options, prec); break; case 33: acb_zero(a); acb_zero(b); k = 3; scaled_bessel_select_N(acb_realref(b), k, prec); acb_calc_integrate(s, f_scaled_bessel, &k, a, b, goal, tol, options, prec); scaled_bessel_tail_bound(acb_realref(a), k, acb_realref(b), prec); arb_add_error(acb_realref(s), acb_realref(a)); break; case 34: acb_zero(a); acb_zero(b); k = 15; scaled_bessel_select_N(acb_realref(b), k, prec); acb_calc_integrate(s, f_scaled_bessel, &k, a, b, goal, tol, options, prec); scaled_bessel_tail_bound(acb_realref(a), k, acb_realref(b), prec); arb_add_error(acb_realref(s), acb_realref(a)); break; case 35: acb_set_d_d(a, -1, -1); acb_set_d_d(b, -1, 1); acb_calc_integrate(s, f_rsqrt, NULL, a, b, goal, tol, options, prec); case 36: if (goal < 0) abort(); acb_zero(a); acb_set_ui(b, 4 + (goal + 1) / 2); acb_calc_integrate(s, f_rgamma, NULL, a, b, goal, tol, options, prec); arb_add_error_2exp_si(acb_realref(s), -goal); break; default: abort(); } TIMEIT_ONCE_STOP } flint_printf("I%d = ", integral); acb_printn(s, 3.333 * prec, 0); flint_printf("\n\n"); } acb_clear(a); acb_clear(b); acb_clear(s); acb_clear(t); mag_clear(tol); flint_cleanup_master(); return 0; } flint-3.1.3/examples/keiper_li.c000066400000000000000000000067351461254215100165730ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "arb.h" #include "acb.h" #include "arb_poly.h" #include "profiler.h" void keiper_li_series(arb_ptr z, slong len, slong prec) { arb_ptr t, u, v; t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); TIMEIT_ONCE_START /* -zeta(s) */ flint_printf("zeta: "); TIMEIT_ONCE_START arb_zero(t + 0); arb_one(t + 1); arb_one(u); _arb_poly_zeta_series(v, t, 2, u, 0, len, prec); _arb_vec_neg(v, v, len); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE /* logarithm */ flint_printf("log: "); TIMEIT_ONCE_START _arb_poly_log_series(t, v, len, len, prec); TIMEIT_ONCE_STOP /* add log(gamma(1+s/2)) */ flint_printf("gamma: "); TIMEIT_ONCE_START arb_one(u); arb_one(u + 1); arb_mul_2exp_si(u + 1, u + 1, -1); _arb_poly_lgamma_series(v, u, 2, len, prec); _arb_vec_add(t, t, v, len, prec); TIMEIT_ONCE_STOP /* subtract 0.5 s log(pi) */ arb_const_pi(u, prec); arb_log(u, u, prec); arb_mul_2exp_si(u, u, -1); arb_sub(t + 1, t + 1, u, prec); /* add log(1-s) */ arb_one(u); arb_set_si(u + 1, -1); _arb_poly_log_series(v, u, 2, len, prec); _arb_vec_add(t, t, v, len, prec); /* binomial transform */ flint_printf("binomial transform: "); TIMEIT_ONCE_START arb_set(z, t); _arb_vec_neg(t + 1, t + 1, len - 1); _arb_poly_binomial_transform(z + 1, t + 1, len - 1, len - 1, prec); TIMEIT_ONCE_STOP flint_printf("total: "); TIMEIT_ONCE_STOP _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); } int main(int argc, char *argv[]) { slong i, len, prec, num_threads; char * out_file; arb_ptr z; if (argc < 2) { flint_printf("keiper_li n [-prec prec] [-threads num_threads] [-out out_file]\n"); return 1; } len = atol(argv[1]) + 1; prec = 1.1 * len + 50; num_threads = 1; out_file = NULL; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-prec")) prec = atol(argv[i+1]); else if (!strcmp(argv[i], "-threads")) num_threads = atol(argv[i+1]); else if (!strcmp(argv[i], "-out")) out_file = argv[i+1]; } flint_set_num_threads(num_threads); z = _arb_vec_init(len); keiper_li_series(z, len, prec); for (i = 0; i < len; i++) { if (i <= 10 || len - i <= 10) { flint_printf("%wd: ", i); arb_printd(z + i, 50); flint_printf("\n"); } } SHOW_MEMORY_USAGE if (out_file != NULL) { fmpz_t man, exp; arf_t t; FILE * fp = fopen(out_file, "w"); fmpz_init(man); fmpz_init(exp); arf_init(t); for (i = 0; i < len; i++) { arf_get_fmpz_2exp(man, exp, arb_midref(z + i)); flint_fprintf(fp, "%wd ", i); fmpz_fprint(fp, man); flint_fprintf(fp, " "); fmpz_fprint(fp, exp); flint_fprintf(fp, " "); arf_set_mag(t, arb_radref(z + i)); arf_get_fmpz_2exp(man, exp, t); fmpz_fprint(fp, man); flint_fprintf(fp, " "); fmpz_fprint(fp, exp); flint_fprintf(fp, "\n"); } fclose(fp); fmpz_clear(man); fmpz_clear(exp); arf_clear(t); } _arb_vec_clear(z, len); flint_cleanup(); return 0; } flint-3.1.3/examples/lcentral.c000066400000000000000000000051771461254215100164330ustar00rootroot00000000000000/* This file is public domain. Author: Pascal Molin. */ #include #include #include #include "profiler.h" #include "acb_dirichlet.h" static int usage(char *argv[]) { printf("Computes central values (s = 0.5) of Dirichlet L-functions.\n\n"); printf("usage: %s [--quiet] [--check] [--prec ] qmin qmax\n", argv[0]); return 1; } int main(int argc, char *argv[]) { int i, check = 0, out = 1; slong prec = 100, digits = 30; ulong qmin, qmax, q; acb_t s; acb_dirichlet_hurwitz_precomp_t pre; if (argc < 3) return usage(argv); for (i = 1; i < argc - 2; i++) { if (!strcmp(argv[i], "--quiet")) out = 0; else if (!strcmp(argv[i], "--check")) check = 1; else if (!strcmp(argv[i], "--prec")) { i++; prec = atol(argv[i]); digits = floor(prec * 0.3); } } if (argc < i + 2) return usage(argv); qmin = atol(argv[i]); qmax = atol(argv[i+1]); fflush(stdout); acb_init(s); TIMEIT_ONCE_START acb_one(s); acb_div_si(s, s, 2, prec); acb_dirichlet_hurwitz_precomp_init_num(pre, s, 0, (qmax - qmin + 1) * 0.5 * qmax, prec); for (q = qmin; q <= qmax; q++) { ulong k; dirichlet_group_t G; dirichlet_char_t x; acb_ptr z; if (q % 4 == 2) continue; dirichlet_group_init(G, q); dirichlet_char_init(x, G); z = _acb_vec_init(G->phi_q); acb_dirichlet_l_vec_hurwitz(z, s, pre, G, prec); if (out || check) { k = 0; dirichlet_char_one(x, G); while (dirichlet_char_next(x, G) >= 0) { k++; if (dirichlet_conductor_char(G,x) < q) continue; if (acb_contains_zero(z + k)) { flint_printf("Value could be zero!\n"); flint_printf("%wu,%wu: ", q, x->n); acb_printn(z + k, digits, 0); flint_printf("\n"); flint_abort(); } if (out) { flint_printf("%wu,%wu: ", q, x->n); acb_printn(z + k, digits, 0); flint_printf("\n"); } } } _acb_vec_clear(z, G->phi_q); dirichlet_char_clear(x); dirichlet_group_clear(G); } acb_dirichlet_hurwitz_precomp_clear(pre); acb_clear(s); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE flint_cleanup(); return 0; } flint-3.1.3/examples/logistic.c000066400000000000000000000035311461254215100164340ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include "arb.h" #include "profiler.h" int main(int argc, char *argv[]) { slong prec, goal, digits; const char * xs; const char * rs; arb_t x, r, s, t; slong i, n; if (argc < 2) { flint_printf("nth iterate of the logistic map x_{n+1} = r x_n (1-x_n)\n"); flint_printf("usage: build/examples/logistic n [x_0=0.5] [r=3.75] [digits=10]\n"); return 1; } n = atol(argv[1]); n = FLINT_MAX(n, 0); xs = (argc >= 3) ? argv[2] : "0.5"; rs = (argc >= 4) ? argv[3] : "3.75"; digits = (argc >= 5) ? atol(argv[4]) : 10; if (digits < 1) digits = 1; goal = digits * 3.3219280948873623 + 3; arb_init(x); arb_init(r); arb_init(s); arb_init(t); TIMEIT_ONCE_START for (prec = 64; ; prec *= 2) { flint_printf("Trying prec=%wd bits...", prec); fflush(stdout); arb_set_str(x, xs, prec); arb_set_str(r, rs, prec); if (!arb_is_finite(x) || !arb_is_finite(r)) { flint_printf("unable to parse input string!\n"); flint_abort(); } for (i = 0; i < n; i++) { arb_sub_ui(t, x, 1, prec); arb_neg(t, t); arb_mul(x, x, t, prec); arb_mul(x, x, r, prec); if (arb_rel_accuracy_bits(x) < goal) { flint_printf("ran out of accuracy at step %wd\n", i); break; } } if (i == n) { flint_printf("success!\n"); break; } } TIMEIT_ONCE_STOP flint_printf("x_%wd = ", n); arb_printn(x, digits, 0); flint_printf("\n"); arb_clear(x); arb_clear(r); arb_clear(s); arb_clear(t); flint_cleanup(); return 0; } flint-3.1.3/examples/lvalue.c000066400000000000000000000054061461254215100161120ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "acb_dirichlet.h" #include "profiler.h" int main(int argc, char *argv[]) { dirichlet_group_t G; dirichlet_char_t chi; acb_t s; acb_ptr z; slong prec, i, len; ulong q, n; int zfunction, deflate; if (argc < 2) { flint_printf("lvalue [-character q n] [-re a] [-im b] [-prec p] [-z] [-deflate] [-len l]\n\n"); flint_printf("Print value of Dirichlet L-function at s = a+bi.\n"); flint_printf("Default a = 0.5, b = 0, p = 53, (q, n) = (1, 0) (Riemann zeta)\n"); flint_printf("[-z] - compute Z(s) instead of L(s)\n"); flint_printf("[-deflate] - remove singular term at s = 1\n"); flint_printf("[-len l] - compute l terms in Taylor series at s\n"); return 1; } acb_init(s); zfunction = 0; prec = 53; q = 1; n = 0; len = 1; deflate = 0; acb_set_d(s, 0.5); for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-prec")) { prec = atol(argv[i+1]); } } for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-character")) { q = atol(argv[i+1]); n = atol(argv[i+2]); } else if (!strcmp(argv[i], "-len")) { len = atol(argv[i+1]); } else if (!strcmp(argv[i], "-z")) { zfunction = 1; } else if (!strcmp(argv[i], "-deflate")) { deflate = 1; } else if (!strcmp(argv[i], "-re")) { arb_set_str(acb_realref(s), argv[i+1], prec); } else if (!strcmp(argv[i], "-im")) { arb_set_str(acb_imagref(s), argv[i+1], prec); } } if (n_gcd(q, n) != 1) { flint_printf("need gcd(q,n) = 1 to define a character\n"); flint_abort(); } z = _acb_vec_init(len); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_log(chi, G, n); TIMEIT_ONCE_START if (zfunction) acb_dirichlet_hardy_z(z, s, G, chi, len, prec); else acb_dirichlet_l_jet(z, s, G, chi, deflate, len, prec); for (i = 0; i < len; i++) { if (i == 0) flint_printf("%s(s) = ", zfunction ? "Z" : "L"); else if (i == 1) flint_printf("%s'(s) = ", zfunction ? "Z" : "L"); else flint_printf("[x^%wd] %s(s+x) = ", i, zfunction ? "Z" : "L"); acb_printn(z + i, prec * 0.333 + 1, 0); flint_printf("\n"); } TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE _acb_vec_clear(z, len); acb_clear(s); dirichlet_char_clear(chi); dirichlet_group_clear(G); flint_cleanup(); return 0; } flint-3.1.3/examples/machin.c000066400000000000000000000071121461254215100160550ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include "profiler.h" #include "ca.h" void simple_ca_atan_p_q(ca_t res, ulong p, ulong q, ca_ctx_t ctx) { ca_set_ui(res, p, ctx); ca_div_ui(res, res, q, ctx); ca_atan(res, res, ctx); } /* valid for -1 < x < 1 */ void simple_ca_atanh(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_add_ui(t, x, 1, ctx); ca_sub_ui(u, x, 1, ctx); ca_neg(u, u, ctx); ca_div(res, t, u, ctx); ca_log(res, res, ctx); ca_div_ui(res, res, 2, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } void simple_ca_atanh_p_q(ca_t res, ulong p, ulong q, ca_ctx_t ctx) { ca_set_ui(res, p, ctx); ca_div_ui(res, res, q, ctx); simple_ca_atanh(res, res, ctx); } #define NUM_FORMULAS 8 slong machin_formulas[NUM_FORMULAS][4][2] = { {{1, 1}, {0, 0}, {0, 0}, {0, 0}}, {{1, 2}, {1, 3}, {0, 0}, {0, 0}}, {{2, 2}, {-1, 7}, {0, 0}, {0, 0}}, {{2, 3}, {1, 7}, {0, 0}, {0, 0}}, {{4, 5}, {-1, 239}, {0, 0}, {0, 0}}, {{1, 2}, {1, 5}, {1, 8}, {0, 0}}, {{1, 3}, {1, 4}, {1, 7}, {1, 13}}, {{12, 49}, {32, 57}, {-5, 239}, {12, 110443}}, }; #define NUM_FORMULAS2 7 slong hyperbolic_logs[NUM_FORMULAS2] = {2, 3, 5, 2, 3, 5, 7}; slong hyperbolic_machin_formulas[NUM_FORMULAS2][4][2] = { {{14, 31}, {10, 49}, {6, 161}, {0, 0}}, {{22, 31}, {16, 49}, {10, 161}, {0, 0}}, {{32, 31}, {24, 49}, {14, 161}, {0, 0}}, {{144, 251}, {54, 449}, {-38, 4801}, {62, 8749}}, {{228, 251}, {86, 449}, {-60, 4801}, {98, 8749}}, {{334, 251}, {126, 449}, {-88, 4801}, {144, 8749}}, {{404, 251}, {152, 449}, {-106, 4801}, {174, 8749}}, }; int main(int argc, char *argv[]) { ca_ctx_t ctx; ca_t x, y, pi4; slong i, j, c, q; TIMEIT_ONCE_START ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(pi4, ctx); ca_pi(pi4, ctx); ca_div_ui(pi4, pi4, 4, ctx); for (i = 0; i < NUM_FORMULAS; i++) { flint_printf("["); ca_zero(x, ctx); for (j = 0; j < 4; j++) { c = machin_formulas[i][j][0]; q = machin_formulas[i][j][1]; if (c != 0) { if (j != 0) flint_printf(" + "); flint_printf("(%wd)*atan(1/%wd)", c, q); simple_ca_atan_p_q(y, 1, q, ctx); ca_mul_si(y, y, c, ctx); ca_add(x, x, y, ctx); } } flint_printf(" - pi/4] = "); ca_sub(x, x, pi4, ctx); ca_print(x, ctx); flint_printf("\n"); } flint_printf("\n"); for (i = 0; i < NUM_FORMULAS2; i++) { flint_printf("["); ca_zero(x, ctx); for (j = 0; j < 4; j++) { c = hyperbolic_machin_formulas[i][j][0]; q = hyperbolic_machin_formulas[i][j][1]; if (c != 0) { if (j != 0) flint_printf(" + "); flint_printf("(%wd)*atanh(1/%wd)", c, q); simple_ca_atanh_p_q(y, 1, q, ctx); ca_mul_si(y, y, c, ctx); ca_add(x, x, y, ctx); } } flint_printf(" - log(%wd)] = ", hyperbolic_logs[i]); ca_set_ui(y, hyperbolic_logs[i], ctx); ca_log(y, y, ctx); ca_sub(x, x, y, ctx); ca_print(x, ctx); flint_printf("\n"); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(pi4, ctx); ca_ctx_clear(ctx); flint_printf("\n"); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE flint_cleanup(); return 0; } flint-3.1.3/examples/multi_crt.c000066400000000000000000000037771461254215100166350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program for balanced multimodular reduction and reconstruction using the Chinese Remainder Theorem. */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(int argc, char* argv[]) { slong i; fmpz_t x, y; /* Data needed by multi CRT functions */ fmpz_comb_t comb; fmpz_comb_temp_t comb_temp; mp_limb_t * primes; mp_limb_t * residues; slong num_primes; if (argc != 3) { flint_printf("Syntax: crt \n"); return EXIT_FAILURE; } num_primes = atoi(argv[2]); if (num_primes < 1) { flint_printf("Requires num_primes >= 1\n"); return EXIT_FAILURE; } fmpz_init(x); fmpz_init(y); fmpz_set_str(x, argv[1], 10); primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); primes[0] = 2; for (i = 1; i < num_primes; i++) primes[i] = n_nextprime(primes[i-1], 0); fmpz_comb_init(comb, primes, num_primes); fmpz_comb_temp_init(comb_temp, comb); /* Reduce modulo all primes */ fmpz_multi_mod_ui(residues, x, comb, comb_temp); /* Reconstruct */ fmpz_multi_CRT_ui(y, residues, comb, comb_temp, 1); for (i = 0; i < num_primes; i++) flint_printf("residue mod %wu = %wu\n", primes[i], residues[i]); flint_printf("reconstruction = "); fmpz_print(y); flint_printf("\n"); fmpz_clear(x); fmpz_clear(y); fmpz_comb_temp_clear(comb_temp); fmpz_comb_clear(comb); flint_free(residues); flint_free(primes); return 0; } flint-3.1.3/examples/padic.c000066400000000000000000000071511461254215100157010ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program to demonstrate some use of the padic module. */ #include #include #include #include "flint.h" #include "padic.h" int main(void) { fmpz_t p; padic_ctx_t ctx; char *str; padic_t x, y; flint_printf("Output:\n\n"); /* Case 1 */ flint_printf("Positive integer: x = 127 mod 7^10\n"); fmpz_init(p); fmpz_set_ui(p, 7); padic_ctx_init(ctx, p, 8, 12, PADIC_TERSE); padic_init2(x, 10); padic_set_ui(x, 127, ctx); ctx->mode = PADIC_TERSE; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); ctx->mode = PADIC_SERIES; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); ctx->mode = PADIC_VAL_UNIT; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); padic_clear(x); padic_ctx_clear(ctx); fmpz_clear(p); /* Case 2 */ flint_printf("Positive integer larger than p^N: x = 1057 mod 2^10\n"); fmpz_init(p); fmpz_set_ui(p, 2); padic_ctx_init(ctx, p, 10, 12, PADIC_TERSE); padic_init2(x, 10); padic_set_ui(x, 1057, ctx); ctx->mode = PADIC_TERSE; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); ctx->mode = PADIC_SERIES; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); ctx->mode = PADIC_VAL_UNIT; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); padic_clear(x); padic_ctx_clear(ctx); fmpz_clear(p); /* Case 3 */ flint_printf("Negative integer: x = -127 mod 3^10\n"); fmpz_init(p); fmpz_set_ui(p, 3); padic_ctx_init(ctx, p, 10, 12, PADIC_TERSE); padic_init2(x, 10); padic_set_si(x, -127, ctx); ctx->mode = PADIC_TERSE; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); ctx->mode = PADIC_VAL_UNIT; str = padic_get_str(NULL, x, ctx); flint_printf("print: "), padic_print(x, ctx), flint_printf("\n"); flint_printf("get_str: %s\n", str); flint_free(str); padic_clear(x); padic_ctx_clear(ctx); fmpz_clear(p); /* Log */ flint_printf("Log of 7380996 mod 5^20\n"); fmpz_init(p); fmpz_set_ui(p, 5); padic_ctx_init(ctx, p, 10, 25, PADIC_SERIES); padic_init(x); padic_init(y); padic_set_ui(x, 7380996, ctx); padic_log(y, x, ctx); flint_printf("x = "), padic_print(x, ctx), flint_printf("\n"); flint_printf("y = "), padic_print(y, ctx), flint_printf("\n"); padic_clear(x); padic_clear(y); padic_ctx_clear(ctx); fmpz_clear(p); return 0; } flint-3.1.3/examples/partitions.c000066400000000000000000000025321461254215100170130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* FLINT program for demonstrating the Integer Partition function. */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "arith.h" #include "profiler.h" int main(int argc, char * argv[]) { fmpz_t x; ulong n; slong i; int quiet = 0; slong num_threads = 1; if (argc < 2) { flint_printf("usage: partitions n [-quiet]\n"); return 1; } for (i = 2; i < argc; i++) { if (!strcmp(argv[i], "-quiet")) quiet = 1; else if (!strcmp(argv[i], "-threads")) num_threads = atol(argv[i+1]); } flint_set_num_threads(num_threads); flint_sscanf(argv[1], "%wu", &n); flint_printf("p(%wu) = \n", n); fmpz_init(x); TIMEIT_ONCE_START arith_number_of_partitions(x, n); TIMEIT_ONCE_STOP if (!quiet) { fmpz_print(x); flint_printf("\n"); } fmpz_clear(x); return 0; } flint-3.1.3/examples/pi.c000066400000000000000000000051001461254215100152210ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "arb.h" #include "profiler.h" int main(int argc, char *argv[]) { arb_t x; slong i, prec, digits, condense, num_threads; int constant; if (argc < 2) { flint_printf("usage: build/examples/pi digits [-condense n] [-threads n] [-constant name]\n"); flint_printf("compute digits of pi (or other constants)\n"); flint_printf("supported: pi, e, log2, euler, catalan, khinchin, zeta3, reciprocal_fibonacci\n"); return 1; } digits = atol(argv[1]); num_threads = 1; condense = 20; constant = 0; for (i = 2; i < argc; i++) { if (!strcmp(argv[i], "-condense")) condense = atol(argv[i+1]); else if (!strcmp(argv[i], "-threads")) num_threads = atol(argv[i+1]); else if (!strcmp(argv[i], "-constant")) { if (!strcmp(argv[i+1], "pi")) constant = 0; else if (!strcmp(argv[i+1], "e")) constant = 1; else if (!strcmp(argv[i+1], "log2")) constant = 2; else if (!strcmp(argv[i+1], "euler")) constant = 3; else if (!strcmp(argv[i+1], "catalan")) constant = 4; else if (!strcmp(argv[i+1], "khinchin")) constant = 5; else if (!strcmp(argv[i+1], "zeta3")) constant = 6; else if (!strcmp(argv[i+1], "reciprocal_fibonacci")) constant = 7; else { flint_printf("unknown constant\n"); flint_abort(); } } } flint_set_num_threads(num_threads); arb_init(x); prec = digits * 3.3219280948873623 + 5; flint_printf("precision = %wd bits... ", prec); fflush(stdout); TIMEIT_ONCE_START if (constant == 0) arb_const_pi(x, prec); else if (constant == 1) arb_const_e(x, prec); else if (constant == 2) arb_const_log2(x, prec); else if (constant == 3) arb_const_euler(x, prec); else if (constant == 4) arb_const_catalan(x, prec); else if (constant == 5) arb_const_khinchin(x, prec); else if (constant == 6) arb_zeta_ui(x, 3, prec); else if (constant == 7) arb_const_reciprocal_fibonacci(x, prec); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE arb_printn(x, digits, ARB_STR_CONDENSE * condense); flint_printf("\n"); arb_clear(x); flint_cleanup_master(); return 0; } flint-3.1.3/examples/poly_roots.c000066400000000000000000000150371461254215100170340ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include #include "fmpz_poly_factor.h" #include "fmpq_poly.h" #include "acb.h" #include "arb_fmpz_poly.h" #include "arith.h" #include "profiler.h" int main(int argc, char *argv[]) { fmpz_poly_t f, g; fmpz_poly_factor_t fac; fmpz_t t; acb_ptr roots; slong compd, printd, i, j, deg; int flags; if (argc < 2) { flint_printf("poly_roots [-refine d] [-print d] \n\n"); flint_printf("Isolates all the complex roots of a polynomial with integer coefficients.\n\n"); flint_printf("If -refine d is passed, the roots are refined to a relative tolerance\n"); flint_printf("better than 10^(-d). By default, the roots are only computed to sufficient\n"); flint_printf("accuracy to isolate them. The refinement is not currently done efficiently.\n\n"); flint_printf("If -print d is passed, the computed roots are printed to d decimals.\n"); flint_printf("By default, the roots are not printed.\n\n"); flint_printf("The polynomial can be specified by passing the following as :\n\n"); flint_printf("a Easy polynomial 1 + 2x + ... + (n+1)x^n\n"); flint_printf("t Chebyshev polynomial T_n\n"); flint_printf("u Chebyshev polynomial U_n\n"); flint_printf("p Legendre polynomial P_n\n"); flint_printf("c Cyclotomic polynomial Phi_n\n"); flint_printf("s Swinnerton-Dyer polynomial S_n\n"); flint_printf("b Bernoulli polynomial B_n\n"); flint_printf("w Wilkinson polynomial W_n\n"); flint_printf("e Taylor series of exp(x) truncated to degree n\n"); flint_printf("m The Mignotte-like polynomial x^n + (100x+1)^m, n > m\n"); flint_printf("coeffs c0 + c1 x + ... + cn x^n\n\n"); flint_printf("Concatenate to multiply polynomials, e.g.: p 5 t 6 coeffs 1 2 3\n"); flint_printf("for P_5(x)*T_6(x)*(1+2x+3x^2)\n\n"); return 1; } compd = 0; printd = 0; flags = ARB_FMPZ_POLY_ROOTS_VERBOSE; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(t); fmpz_poly_one(f); for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-refine")) { compd = atol(argv[i+1]); i++; } else if (!strcmp(argv[i], "-print")) { printd = atol(argv[i+1]); i++; } else if (!strcmp(argv[i], "a")) { slong n = atol(argv[i+1]); fmpz_poly_zero(g); for (j = 0; j <= n; j++) fmpz_poly_set_coeff_ui(g, j, j+1); fmpz_poly_mul(f, f, g); i++; } else if (!strcmp(argv[i], "t")) { arith_chebyshev_t_polynomial(g, atol(argv[i+1])); fmpz_poly_mul(f, f, g); i++; } else if (!strcmp(argv[i], "u")) { arith_chebyshev_u_polynomial(g, atol(argv[i+1])); fmpz_poly_mul(f, f, g); i++; } else if (!strcmp(argv[i], "p")) { fmpq_poly_t h; fmpq_poly_init(h); arith_legendre_polynomial(h, atol(argv[i+1])); fmpq_poly_get_numerator(g, h); fmpz_poly_mul(f, f, g); fmpq_poly_clear(h); i++; } else if (!strcmp(argv[i], "c")) { arith_cyclotomic_polynomial(g, atol(argv[i+1])); fmpz_poly_mul(f, f, g); i++; } else if (!strcmp(argv[i], "s")) { arith_swinnerton_dyer_polynomial(g, atol(argv[i+1])); fmpz_poly_mul(f, f, g); i++; } else if (!strcmp(argv[i], "b")) { fmpq_poly_t h; fmpq_poly_init(h); arith_bernoulli_polynomial(h, atol(argv[i+1])); fmpq_poly_get_numerator(g, h); fmpz_poly_mul(f, f, g); fmpq_poly_clear(h); i++; } else if (!strcmp(argv[i], "w")) { slong n = atol(argv[i+1]); fmpz_poly_zero(g); fmpz_poly_fit_length(g, n+2); arith_stirling_number_1_vec(g->coeffs, n+1, n+2); _fmpz_poly_set_length(g, n+2); fmpz_poly_shift_right(g, g, 1); fmpz_poly_mul(f, f, g); i++; } else if (!strcmp(argv[i], "e")) { fmpq_poly_t h; fmpq_poly_init(h); fmpq_poly_set_coeff_si(h, 0, 0); fmpq_poly_set_coeff_si(h, 1, 1); fmpq_poly_exp_series(h, h, atol(argv[i+1]) + 1); fmpq_poly_get_numerator(g, h); fmpz_poly_mul(f, f, g); fmpq_poly_clear(h); i++; } else if (!strcmp(argv[i], "m")) { fmpz_poly_zero(g); fmpz_poly_set_coeff_ui(g, 0, 1); fmpz_poly_set_coeff_ui(g, 1, 100); fmpz_poly_pow(g, g, atol(argv[i+2])); fmpz_poly_set_coeff_ui(g, atol(argv[i+1]), 1); fmpz_poly_mul(f, f, g); i += 2; } else if (!strcmp(argv[i], "coeffs")) { fmpz_poly_zero(g); i++; j = 0; while (i < argc) { if (fmpz_set_str(t, argv[i], 10) != 0) { i--; break; } fmpz_poly_set_coeff_fmpz(g, j, t); i++; j++; } fmpz_poly_mul(f, f, g); } } fmpz_poly_factor_init(fac); flint_printf("computing squarefree factorization...\n"); TIMEIT_ONCE_START fmpz_poly_factor_squarefree(fac, f); TIMEIT_ONCE_STOP TIMEIT_ONCE_START for (i = 0; i < fac->num; i++) { deg = fmpz_poly_degree(fac->p + i); flint_printf("%wd roots with multiplicity %wd\n", deg, fac->exp[i]); roots = _acb_vec_init(deg); arb_fmpz_poly_complex_roots(roots, fac->p + i, flags, compd * 3.32193 + 2); if (printd) { for (j = 0; j < deg; j++) { acb_printn(roots + j, printd, 0); flint_printf("\n"); } } _acb_vec_clear(roots, deg); } TIMEIT_ONCE_STOP fmpz_poly_factor_clear(fac); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(t); flint_cleanup(); return 0; } flint-3.1.3/examples/primegen.c000066400000000000000000000025161461254215100164270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(int argc, char* argv[]) { n_primes_t iter; mp_limb_t p, N; if (argc < 2) { flint_printf("primegen N - print all primes <= N\n"); flint_printf("primegen -c N - generate the primes but just count them\n"); return EXIT_FAILURE; } N = strtoul(argv[argc-1], NULL, 10); if (N == UWORD_MAX) { flint_printf("N must be smaller than %wu\n", UWORD_MAX); return EXIT_FAILURE; } if (argc == 3) { ulong count = 0; n_primes_init(iter); while ((p = n_primes_next(iter)) <= N) count++; n_primes_clear(iter); flint_printf("pi(%wu) = %wu\n", N, count); } else { n_primes_init(iter); while ((p = n_primes_next(iter)) <= N) flint_printf("%wu\n", p); n_primes_clear(iter); } return 0; } flint-3.1.3/examples/qadic.c000066400000000000000000000076171461254215100157110ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program to demonstrate some use of the qadic module. */ #include #include #include "qadic.h" int main(void) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; int ans; /*************************************************************************/ fmpz_t e = {WORD(4)}; fmpz_t nine = {WORD(9)}; fmpz_init_set_ui(p, 3); d = 2; N = 5; qadic_ctx_init_conway(ctx, p, d, 0, N, "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); flint_printf("Compute a power and a sum\n"); padic_poly_fit_length(a, 2); fmpz_one(a->coeffs + 0); fmpz_set_ui(a->coeffs + 1, 2); a->val = 0; _padic_poly_set_length(a, 2); qadic_print_pretty(a, ctx); flint_printf("\n"); qadic_pow(a, a, e, ctx); padic_poly_set_ui(b, 3249, &ctx->pctx); qadic_add(c, a, b, ctx); qadic_print_pretty(a, ctx); flint_printf("\n"); qadic_print_pretty(b, ctx); flint_printf("\n"); qadic_print_pretty(c, ctx); flint_printf("\n"); flint_printf("\n"); flint_printf("Compute a Teichmuller lift\n"); padic_poly_fit_length(a, 2); fmpz_one(a->coeffs + 0); fmpz_set_ui(a->coeffs + 1, 2); a->val = 0; _padic_poly_set_length(a, 2); qadic_teichmuller(b, a, ctx); qadic_pow(c, b, nine, ctx); qadic_print_pretty(a, ctx); flint_printf("\n"); qadic_print_pretty(b, ctx); flint_printf("\n"); qadic_print_pretty(c, ctx); flint_printf("\n"); flint_printf("\n"); flint_printf("Compute an inverse\n"); qadic_set(a, b, ctx); qadic_inv(b, a, ctx); qadic_mul(c, a, b, ctx); qadic_print_pretty(a, ctx); flint_printf("\n"); qadic_print_pretty(b, ctx); flint_printf("\n"); qadic_print_pretty(c, ctx); flint_printf("\n"); flint_printf("\n"); qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_ctx_clear(ctx); fmpz_clear(p); /*************************************************************************/ flint_printf("Compute a Frobenius image\n"); fmpz_init_set_ui(p, 3); d = 2; N = 5; qadic_ctx_init_conway(ctx, p, d, 0, N, "X", PADIC_TERSE); qadic_init2(a, N); qadic_init2(b, N); padic_poly_fit_length(a, 2); a->coeffs[0] = WORD(78); a->coeffs[1] = WORD(45); a->val = 0; _padic_poly_set_length(a, 2); qadic_frobenius(b, a, 1, ctx); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("Context:\n"), qadic_ctx_print(ctx); flint_printf("\n"); qadic_clear(a); qadic_clear(b); qadic_ctx_clear(ctx); fmpz_clear(p); /*************************************************************************/ flint_printf("Compute a square root\n"); fmpz_init_set_ui(p, 2); d = 3; N = 2; qadic_ctx_init_conway(ctx, p, d, 0, N, "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); padic_poly_fit_length(a, d); a->coeffs[0] = WORD(1); a->coeffs[1] = WORD(3); a->coeffs[2] = WORD(1); a->val = 0; _padic_poly_set_length(a, d); ans = qadic_sqrt(b, a, ctx); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("Context:\n"), qadic_ctx_print(ctx); flint_printf("\n"); qadic_clear(a); qadic_clear(b); qadic_ctx_clear(ctx); fmpz_clear(p); return 0; } flint-3.1.3/examples/radix.c000066400000000000000000000065171461254215100157350ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program to demonstrate some use of the function fmpz_mod_poly_radix() for radix conversion over $\mathbf{Z}/n \mathbf{Z}$. */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" int main(void) { const slong n = 12376; const slong N = n / 26; clock_t c0, c1; double c; slong i; fmpz_t a, m; fmpz_mod_ctx_t ctx; fmpz_mod_poly_t A, B, r, t; fmpz_mod_poly_radix_t S; fmpz_mod_poly_struct **b; FLINT_TEST_INIT(state); fmpz_init(a); fmpz_init(m); fmpz_set_ui(m, 17); fmpz_pow_ui(m, m, 26); fmpz_mod_ctx_init(ctx, m); fmpz_mod_poly_init(A, ctx); fmpz_mod_poly_init(B, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_set_coeff_ui(A, 3, 5, ctx); fmpz_mod_poly_set_coeff_ui(A, 4, 4, ctx); fmpz_mod_poly_set_coeff_ui(B, 0, 1, ctx); fmpz_mod_poly_set_coeff_ui(B, 2, 1, ctx); fmpz_mod_poly_set_coeff_ui(B, 3, 5, ctx); fmpz_mod_poly_set_coeff_ui(B, 4, 1, ctx); fmpz_mod_poly_set_coeff_ui(B, 5, 5, ctx); fmpz_mod_poly_set_coeff_ui(B, 8, 8, ctx); fmpz_mod_poly_set_coeff_ui(B, 9, 8, ctx); fmpz_mod_poly_set_coeff_ui(B, 10, 5, ctx); fmpz_mod_poly_set_coeff_ui(B, 12, 6, ctx); fmpz_mod_poly_set_coeff_ui(B, 13, 1, ctx); fmpz_mod_poly_pow(r, A, 3, ctx); fmpz_set_ui(a, 4); fmpz_mod_poly_scalar_mul_fmpz(r, r, a, ctx); fmpz_mod_poly_pow(t, B, 2, ctx); fmpz_set_ui(a, 27); fmpz_mod_poly_scalar_mul_fmpz(t, t, a, ctx); fmpz_mod_poly_add(r, r, t, ctx); b = flint_malloc((N + 1) * sizeof(fmpz_mod_poly_struct *)); for (i = 0; i <= N; i++) { b[i] = flint_malloc(sizeof(fmpz_mod_poly_struct)); fmpz_mod_poly_init(b[i], ctx); } fmpz_mod_poly_randtest(t, state, n + 1, ctx); flint_printf("Radix conversion\n"); flint_printf("----------------\n"); flint_printf(" Degree of the radix: %wd\n", fmpz_mod_poly_degree(r, ctx)); flint_printf(" Bit size of the modulus: %wd\n", (slong) fmpz_bits(m)); flint_printf(" Degree of the input: %wd\n", fmpz_mod_poly_degree(t, ctx)); c0 = clock(); fmpz_mod_poly_radix_init(S, r, n + 1, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; flint_printf(" Precomputation: %fs\n", c); c0 = clock(); fmpz_mod_poly_radix(b, t, S, ctx); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; flint_printf(" Conversion: %fs\n", c); fmpz_clear(a); fmpz_clear(m); fmpz_mod_poly_clear(A, ctx); fmpz_mod_poly_clear(B, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_radix_clear(S); for (i = 0; i <= N; i++) { fmpz_mod_poly_clear(b[i], ctx); flint_free(b[i]); } flint_free(b); fmpz_mod_ctx_clear(ctx); flint_randclear(state); return 0; } flint-3.1.3/examples/real_roots.c000066400000000000000000000236471461254215100170020ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include #include "arb_poly.h" #include "arb_calc.h" #include "acb_hypgeom.h" #include "acb_dirichlet.h" #include "profiler.h" slong eval_count = 0; typedef struct { dirichlet_group_t * G; dirichlet_char_t * chi; } z_param_struct; int z_function(arb_ptr out, const arb_t inp, void * params, slong order, slong prec) { z_param_struct * par = params; if (par->G == NULL) { arb_struct x[2]; arb_init(x); arb_init(x + 1); arb_set(x, inp); arb_one(x + 1); _arb_poly_riemann_siegel_z_series(out, x, FLINT_MIN(2, order), order, prec); arb_clear(x); arb_clear(x + 1); } else { acb_ptr tmp; slong k; tmp = _acb_vec_init(order); acb_set_arb(tmp, inp); acb_dirichlet_hardy_z(tmp, tmp, *(par->G), *(par->chi), order, prec); for (k = 0; k < order; k++) arb_set(out + k, acb_realref(tmp + k)); _acb_vec_clear(tmp, order); } eval_count++; return 0; } int sin_x(arb_ptr out, const arb_t inp, void * params, slong order, slong prec) { int xlen = FLINT_MIN(2, order); arb_set(out, inp); if (xlen > 1) arb_one(out + 1); _arb_poly_sin_series(out, out, xlen, order, prec); eval_count++; return 0; } int sin_x2(arb_ptr out, const arb_t inp, void * params, slong order, slong prec) { arb_ptr x; int xlen = FLINT_MIN(2, order); int ylen = FLINT_MIN(3, order); x = _arb_vec_init(xlen); arb_set(x, inp); if (xlen > 1) arb_one(x + 1); _arb_poly_mullow(out, x, xlen, x, xlen, ylen, prec); _arb_poly_sin_series(out, out, ylen, order, prec); _arb_vec_clear(x, xlen); eval_count++; return 0; } int sin_1x(arb_ptr out, const arb_t inp, void * params, slong order, slong prec) { arb_ptr x; int xlen = FLINT_MIN(2, order); x = _arb_vec_init(xlen); arb_set(x, inp); if (xlen > 1) arb_one(x + 1); _arb_poly_inv_series(out, x, xlen, order, prec); _arb_poly_sin_series(out, out, order, order, prec); _arb_vec_clear(x, xlen); eval_count++; return 0; } int airy(arb_ptr out, const arb_t inp, void * params, slong order, slong prec) { acb_t t, u; int which = ((int *) params)[0]; int xlen = FLINT_MIN(2, order); acb_init(t); acb_init(u); acb_set_arb(t, inp); if (xlen == 1) { if (which == 0) acb_hypgeom_airy(t, NULL, NULL, NULL, t, prec); else if (which == 1) acb_hypgeom_airy(NULL, t, NULL, NULL, t, prec); else if (which == 2) acb_hypgeom_airy(NULL, NULL, t, NULL, t, prec); else acb_hypgeom_airy(NULL, NULL, NULL, t, t, prec); arb_set(out, acb_realref(t)); } else { if (which == 0 || which == 1) acb_hypgeom_airy(t, u, NULL, NULL, t, prec); else acb_hypgeom_airy(NULL, NULL, t, u, t, prec); if (which == 0 || which == 2) { arb_set(out + 0, acb_realref(t)); arb_set(out + 1, acb_realref(u)); /* f''(z) = z f(z) */ if (xlen == 3) arb_mul(out + 2, out + 0, inp, prec); } else { arb_set(out + 0, acb_realref(u)); arb_mul(out + 1, acb_realref(t), inp, prec); /* f'''(z) = f(z) + z f'(z) */ if (xlen == 3) { arb_mul(out + 2, out + 0, inp, prec); arb_add(out + 2, out + 2, acb_realref(t), prec); } } } acb_clear(t); acb_clear(u); eval_count++; return 0; } int main(int argc, char *argv[]) { arf_interval_ptr blocks; arb_calc_func_t function; int * info; void * params; int param1; z_param_struct param2; dirichlet_group_t G; dirichlet_char_t chi; slong digits, low_prec, high_prec, i, num, found_roots, found_unknown; slong maxdepth, maxeval, maxfound; int refine; double a, b; arf_t C; arf_interval_t t, interval; arb_t v, w, z; if (argc < 4) { flint_printf("real_roots function a b [-refine d] [-verbose] " "[-maxdepth n] [-maxeval n] [-maxfound n] [-prec n]\n"); flint_printf("available functions:\n"); flint_printf(" 0 Z(x), Z-function (Riemann zeta or Dirichlet L-function)\n"); flint_printf(" 1 sin(x)\n"); flint_printf(" 2 sin(x^2)\n"); flint_printf(" 3 sin(1/x)\n"); flint_printf(" 4 Ai(x), Airy function\n"); flint_printf(" 5 Ai'(x), Airy function\n"); flint_printf(" 6 Bi(x), Airy function\n"); flint_printf(" 7 Bi'(x), Airy function\n"); flint_printf("With 0, specify optional Dirichlet character with [-character q n]\n"); return 1; } param1 = 0; param2.G = NULL; param2.chi = NULL; params = ¶m1; switch (atoi(argv[1])) { case 0: function = z_function; params = ¶m2; break; case 1: function = sin_x; break; case 2: function = sin_x2; break; case 3: function = sin_1x; break; case 4: function = airy; param1 = 0; break; case 5: function = airy; param1 = 1; break; case 6: function = airy; param1 = 2; break; case 7: function = airy; param1 = 3; break; default: flint_printf("require a function 0-7\n"); return 1; } a = atof(argv[2]); b = atof(argv[3]); if (a >= b) { flint_printf("require a < b!\n"); return 1; } refine = 0; digits = 0; maxdepth = 30; maxeval = 100000; maxfound = 100000; low_prec = 30; for (i = 4; i < argc; i++) { if (!strcmp(argv[i], "-refine")) { refine = 1; digits = atol(argv[i+1]); } else if (!strcmp(argv[i], "-verbose")) { arb_calc_verbose = 1; } else if (!strcmp(argv[i], "-maxdepth")) { maxdepth = atol(argv[i+1]); } else if (!strcmp(argv[i], "-maxeval")) { maxeval = atol(argv[i+1]); } else if (!strcmp(argv[i], "-maxfound")) { maxfound = atol(argv[i+1]); } else if (!strcmp(argv[i], "-prec")) { low_prec = atol(argv[i+1]); } else if (!strcmp(argv[i], "-character")) { dirichlet_group_init(G, atol(argv[i+1])); dirichlet_char_init(chi, G); dirichlet_char_log(chi, G, atol(argv[i+2])); param2.G = &G; param2.chi = χ } } high_prec = digits * 3.32192809488736 + 10; found_roots = 0; found_unknown = 0; arf_init(C); arf_interval_init(t); arf_interval_init(interval); arb_init(v); arb_init(w); arb_init(z); arf_set_d(&interval->a, a); arf_set_d(&interval->b, b); flint_printf("interval: "); arf_interval_printd(interval, 15); flint_printf("\n"); flint_printf("maxdepth = %wd, maxeval = %wd, maxfound = %wd, low_prec = %wd\n", maxdepth, maxeval, maxfound, low_prec); TIMEIT_ONCE_START num = arb_calc_isolate_roots(&blocks, &info, function, params, interval, maxdepth, maxeval, maxfound, low_prec); for (i = 0; i < num; i++) { if (info[i] != 1) { if (arb_calc_verbose) { flint_printf("unable to count roots in "); arf_interval_printd(blocks + i, 15); flint_printf("\n"); } found_unknown++; continue; } found_roots++; if (!refine) continue; if (arb_calc_refine_root_bisect(t, function, params, blocks + i, 5, low_prec) != ARB_CALC_SUCCESS) { flint_printf("warning: some bisection steps failed!\n"); } if (arb_calc_verbose) { flint_printf("after bisection 1: "); arf_interval_printd(t, 15); flint_printf("\n"); } if (arb_calc_refine_root_bisect(blocks + i, function, params, t, 5, low_prec) != ARB_CALC_SUCCESS) { flint_printf("warning: some bisection steps failed!\n"); } if (arb_calc_verbose) { flint_printf("after bisection 2: "); arf_interval_printd(blocks + i, 15); flint_printf("\n"); } arf_interval_get_arb(v, t, high_prec); arb_calc_newton_conv_factor(C, function, params, v, low_prec); arf_interval_get_arb(w, blocks + i, high_prec); if (arb_calc_refine_root_newton(z, function, params, w, v, C, 10, high_prec) != ARB_CALC_SUCCESS) { flint_printf("warning: some newton steps failed!\n"); } flint_printf("refined root (%wd/%wd):\n", i, num); arb_printn(z, digits + 2, 0); flint_printf("\n\n"); } flint_printf("---------------------------------------------------------------\n"); flint_printf("Found roots: %wd\n", found_roots); flint_printf("Subintervals possibly containing undetected roots: %wd\n", found_unknown); flint_printf("Function evaluations: %wd\n", eval_count); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE for (i = 0; i < num; i++) arf_interval_clear(blocks + i); flint_free(blocks); flint_free(info); if (param2.G != NULL) { dirichlet_group_clear(G); dirichlet_char_clear(chi); } arf_interval_clear(t); arf_interval_clear(interval); arf_clear(C); arb_clear(v); arb_clear(w); arb_clear(z); flint_cleanup(); return 0; } flint-3.1.3/examples/stirling_matrix.c000066400000000000000000000026001461254215100200320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Demo FLINT program for generating Stirling number matrices and inverting them. */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "arith.h" int main(int argc, char* argv[]) { slong n; fmpz_mat_t S1, S2, P; if (argc != 2) { flint_printf("Syntax: stirling_matrix \n"); return EXIT_FAILURE; } n = atoi(argv[1]); fmpz_mat_init(S1, n, n); fmpz_mat_init(S2, n, n); fmpz_mat_init(P, n, n); arith_stirling_matrix_1(S1); arith_stirling_matrix_2(S2); fmpz_mat_mul(P, S1, S2); flint_printf("S1 [Stirling numbers of 1st kind]:\n"); fmpz_mat_print_pretty(S1); flint_printf("\n\n"); flint_printf("S2 [Stirling numbers of 2nd kind]:\n"); fmpz_mat_print_pretty(S2); flint_printf("\n\n"); flint_printf("S1 * S2:\n"); fmpz_mat_print_pretty(P); flint_printf("\n\n"); fmpz_mat_clear(S1); fmpz_mat_clear(S2); fmpz_mat_clear(P); return 0; } flint-3.1.3/examples/swinnerton_dyer_poly.c000066400000000000000000000053501461254215100211140ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include "profiler.h" #include "ca.h" #include "ca_vec.h" #include "ca_poly.h" #include "ulong_extras.h" void swinnerton_dyer_poly(ca_ptr T, ulong n, slong trunc, ca_ctx_t ctx) { ca_ptr square_roots, tmp1, tmp2, tmp3; ca_t one; slong i, j, k, N; N = WORD(1) << n; trunc = FLINT_MIN(trunc, N + 1); ca_init(one, ctx); ca_one(one, ctx); square_roots = _ca_vec_init(n, ctx); tmp1 = flint_malloc((N / 4 + 1) * sizeof(ca_struct)); tmp2 = flint_malloc((N / 4 + 1) * sizeof(ca_struct)); tmp3 = _ca_vec_init(N / 2, ctx); for (i = 0; i < n; i++) ca_sqrt_ui(square_roots + i, n_nth_prime(i + 1), ctx); /* Build deflated quadratic factors */ for (i = 0; i < N / 2; i++) { ca_zero(T + i, ctx); for (j = 0; j < n; j++) { if ((i >> j) & 1) ca_add(T + i, T + i, square_roots + j, ctx); else ca_sub(T + i, T + i, square_roots + j, ctx); } ca_sqr(T + i, T + i, ctx); ca_neg(T + i, T + i, ctx); } /* For each level... */ for (i = 0; i < n - 1; i++) { slong stride = UWORD(1) << i; for (j = 0; j < N / 2; j += 2*stride) { for (k = 0; k < stride; k++) { tmp1[k] = T[j + k]; tmp2[k] = T[j + stride + k]; } tmp1[stride] = *one; tmp2[stride] = *one; _ca_poly_mullow(tmp3, tmp1, stride + 1, tmp2, stride + 1, FLINT_MIN(2 * stride, trunc), ctx); _ca_vec_set(T + j, tmp3, FLINT_MIN(2 * stride, trunc), ctx); } } /* Inflate */ for (i = N - 2; i >= 0; i -= 2) { if (i < trunc) ca_swap(T + i, T + i / 2, ctx); if (i + 1 < trunc) ca_zero(T + i + 1, ctx); } ca_one(T + N, ctx); _ca_vec_clear(square_roots, n, ctx); flint_free(tmp1); flint_free(tmp2); _ca_vec_clear(tmp3, N / 2, ctx); ca_clear(one, ctx); } int main(int argc, char *argv[]) { ca_ctx_t ctx; ca_ptr poly; slong i, n, N; if (argc < 2) { flint_printf("usage: build/examples/sdpoly n\n"); return 1; } n = atol(argv[1]); if (n < 0 || n > 20) flint_abort(); N = (1 << n); TIMEIT_ONCE_START ca_ctx_init(ctx); poly = _ca_vec_init(N + 1, ctx); swinnerton_dyer_poly(poly, n, N + 1, ctx); for (i = 0; i <= N; i++) { ca_print(poly + i, ctx); flint_printf("\n"); } _ca_vec_clear(poly, N + 1, ctx); ca_ctx_clear(ctx); flint_printf("\n"); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE flint_cleanup(); return 0; } flint-3.1.3/examples/taylor_integrals.c000066400000000000000000000101351461254215100201770ustar00rootroot00000000000000/* This file is public domain. Author: Fredrik Johansson. */ #include #include "acb_poly.h" #include "arb_calc.h" #include "acb_calc.h" #include "profiler.h" int sinx(acb_ptr out, const acb_t inp, void * params, slong order, slong prec) { int xlen = FLINT_MIN(2, order); acb_set(out, inp); if (xlen > 1) acb_one(out + 1); _acb_poly_sin_series(out, out, xlen, order, prec); return 0; } int elliptic(acb_ptr out, const acb_t inp, void * params, slong order, slong prec) { acb_ptr t; t = _acb_vec_init(order); acb_set(t, inp); if (order > 1) acb_one(t + 1); _acb_poly_sin_series(t, t, FLINT_MIN(2, order), order, prec); _acb_poly_mullow(out, t, order, t, order, order, prec); _acb_vec_scalar_mul_2exp_si(t, out, order, -1); acb_sub_ui(t, t, 1, prec); _acb_vec_neg(t, t, order); _acb_poly_rsqrt_series(out, t, order, order, prec); _acb_vec_clear(t, order); return 0; } int bessel(acb_ptr out, const acb_t inp, void * params, slong order, slong prec) { acb_ptr t; acb_t z; ulong n; t = _acb_vec_init(order); acb_init(z); acb_set(t, inp); if (order > 1) acb_one(t + 1); n = 10; arb_set_si(acb_realref(z), 20); arb_set_si(acb_imagref(z), 10); /* z sin(t) */ _acb_poly_sin_series(out, t, FLINT_MIN(2, order), order, prec); _acb_vec_scalar_mul(out, out, order, z, prec); /* t n */ _acb_vec_scalar_mul_ui(t, t, FLINT_MIN(2, order), n, prec); _acb_poly_sub(out, t, FLINT_MIN(2, order), out, order, prec); _acb_poly_cos_series(out, out, order, order, prec); _acb_vec_clear(t, order); acb_clear(z); return 0; } int main(int argc, char *argv[]) { acb_t r, s, a, b; arf_t inr, outr; slong digits, prec; if (argc < 2) { flint_printf("integrals d\n"); flint_printf("compute integrals using d decimal digits of precision\n"); return 1; } acb_init(r); acb_init(s); acb_init(a); acb_init(b); arf_init(inr); arf_init(outr); arb_calc_verbose = 0; digits = atol(argv[1]); prec = digits * 3.32193; flint_printf("Digits: %wd\n", digits); flint_printf("----------------------------------------------------------------\n"); flint_printf("Integral of sin(t) from 0 to 100.\n"); arf_set_d(inr, 0.125); arf_set_d(outr, 1.0); TIMEIT_ONCE_START acb_set_si(a, 0); acb_set_si(b, 100); acb_calc_integrate_taylor(r, sinx, NULL, a, b, inr, outr, prec, 1.1 * prec); flint_printf("RESULT:\n"); acb_printn(r, digits, 0); flint_printf("\n"); TIMEIT_ONCE_STOP flint_printf("----------------------------------------------------------------\n"); flint_printf("Elliptic integral F(phi, m) = integral of 1/sqrt(1 - m*sin(t)^2)\n"); flint_printf("from 0 to phi, with phi = 6+6i, m = 1/2. Integration path\n"); flint_printf("0 -> 6 -> 6+6i.\n"); arf_set_d(inr, 0.2); arf_set_d(outr, 0.5); TIMEIT_ONCE_START acb_set_si(a, 0); acb_set_si(b, 6); acb_calc_integrate_taylor(r, elliptic, NULL, a, b, inr, outr, prec, 1.1 * prec); acb_set_si(a, 6); arb_set_si(acb_realref(b), 6); arb_set_si(acb_imagref(b), 6); acb_calc_integrate_taylor(s, elliptic, NULL, a, b, inr, outr, prec, 1.1 * prec); acb_add(r, r, s, prec); flint_printf("RESULT:\n"); acb_printn(r, digits, 0); flint_printf("\n"); TIMEIT_ONCE_STOP flint_printf("----------------------------------------------------------------\n"); flint_printf("Bessel function J_n(z) = (1/pi) * integral of cos(t*n - z*sin(t))\n"); flint_printf("from 0 to pi. With n = 10, z = 20 + 10i.\n"); arf_set_d(inr, 0.1); arf_set_d(outr, 0.5); TIMEIT_ONCE_START acb_set_si(a, 0); acb_const_pi(b, 3 * prec); acb_calc_integrate_taylor(r, bessel, NULL, a, b, inr, outr, prec, 3 * prec); acb_div(r, r, b, prec); flint_printf("RESULT:\n"); acb_printn(r, digits, 0); flint_printf("\n"); TIMEIT_ONCE_STOP acb_clear(r); acb_clear(s); acb_clear(a); acb_clear(b); arf_clear(inr); arf_clear(outr); flint_cleanup(); return 0; } flint-3.1.3/examples/zeta_zeros.c000066400000000000000000000177521461254215100170160ustar00rootroot00000000000000/* This file is public domain. Author: D.H.J. Polymath. */ #include #include #include "acb_dirichlet.h" #include "profiler.h" void print_zeros(arb_srcptr p, const fmpz_t n, slong len, slong digits) { slong i; fmpz_t k; fmpz_init_set(k, n); for (i = 0; i < len; i++) { fmpz_print(k); flint_printf("\t"); arb_printn(p+i, digits, ARB_STR_NO_RADIUS); flint_printf("\n"); fmpz_add_ui(k, k, 1); } fmpz_clear(k); } void print_help(void) { flint_printf("zeta_zeros [-n n] [-count n] [-prec n] [-digits n] [-threads n] " "[-platt] [-noplatt] [-v] [-verbose] [-h] [-help]\n\n"); flint_printf("Reports the imaginary parts of consecutive nontrivial zeros " "of the Riemann zeta function.\n"); } void requires_value(int argc, char *argv[], slong i) { if (i == argc-1) { flint_printf("the argument %s requires a value\n", argv[i]); flint_abort(); } } void invalid_value(char *argv[], slong i) { flint_printf("invalid value for the argument %s: %s\n", argv[i], argv[i+1]); flint_abort(); } int main(int argc, char *argv[]) { const slong max_buffersize = 30000; int verbose = 0; int platt = 0; int noplatt = 0; slong i, buffersize, prec, digits; fmpz_t requested, count, nstart, n; arb_ptr p; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")) { print_help(); return 0; } } fmpz_init(requested); fmpz_init(count); fmpz_init(nstart); fmpz_init(n); fmpz_one(nstart); fmpz_set_si(requested, -1); buffersize = max_buffersize; prec = -1; digits = 2; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-noplatt")) { noplatt = 1; } else if (!strcmp(argv[i], "-platt")) { platt = 1; } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "-verbose")) { verbose = 1; } else if (!strcmp(argv[i], "-threads")) { slong threads; requires_value(argc, argv, i); threads = atol(argv[i+1]); if (threads < 1) { invalid_value(argv, i); } flint_set_num_threads(threads); } else if (!strcmp(argv[i], "-n")) { requires_value(argc, argv, i); if (fmpz_set_str(nstart, argv[i+1], 10) || fmpz_sgn(nstart) < 1) { invalid_value(argv, i); } } else if (!strcmp(argv[i], "-count")) { requires_value(argc, argv, i); if (fmpz_set_str(requested, argv[i+1], 10) || fmpz_sgn(requested) < 1) { invalid_value(argv, i); } if (fmpz_cmp_si(requested, buffersize) < 0) { buffersize = fmpz_get_si(requested); } } else if (!strcmp(argv[i], "-prec")) { requires_value(argc, argv, i); prec = atol(argv[i+1]); digits = prec / 3.32192809488736 + 1; if (prec < 2) { invalid_value(argv, i); } } else if (!strcmp(argv[i], "-digits")) { requires_value(argc, argv, i); digits = atol(argv[i+1]); prec = digits * 3.32192809488736 + 3; if (prec < 2) { invalid_value(argv, i); } } } if (platt && noplatt) { flint_printf("conflicting arguments platt and noplatt\n"); flint_abort(); } if (platt && fmpz_cmp_si(nstart, 10000) < 0) { flint_printf("this implementation of the platt algorithm " "is not valid below the 10000th zero\n"); flint_abort(); } /* Above n~1e15 the large height method is better. * Above n~1e11 the large height method is better for more than 100 zeros. * Don't worry about crossing the threshold, just use the method * that is better at the beginning of the run. */ if (!noplatt && !platt) { fmpz_t threshold; fmpz_init(threshold); fmpz_set_si(threshold, 10); fmpz_pow_ui(threshold, threshold, 15); if (fmpz_sgn(requested) < 0 || fmpz_cmp_si(requested, 100) > 0) { fmpz_set_si(threshold, 10); fmpz_pow_ui(threshold, threshold, 11); } if (fmpz_cmp(nstart, threshold) < 0) { noplatt = 1; } else { platt = 1; } fmpz_clear(threshold); } if (prec == -1) { prec = 64 + fmpz_clog_ui(nstart, 2); if (platt) prec *= 2; digits = prec / 3.32192809488736 + 1; } if (verbose) { flint_printf("n: "); fmpz_print(nstart); flint_printf("\n"); flint_printf("count: "); fmpz_print(requested); flint_printf("\n"); flint_printf("threads: %wd\n", flint_get_num_threads()); flint_printf("prec: %wd\n", prec); if (platt) { flint_printf("method: platt (good for large heights, " "many consecutive zeros, and lower precision; " "interprets prec as a working precision)\n"); } else { flint_printf("method: noplatt (good for small heights, " "few consecutive zeros, and greater precision; " "interprets prec as a goal precision)\n"); } } p = _arb_vec_init(buffersize); fmpz_set(n, nstart); fmpz_zero(count); TIMEIT_ONCE_START /* This is the low height method. */ if (noplatt) { fmpz_t iter; fmpz_init(iter); while (fmpz_sgn(requested) < 0 || fmpz_cmp(count, requested) < 0) { slong num = buffersize; if (fmpz_sgn(requested) >= 0) { fmpz_t remaining; fmpz_init(remaining); fmpz_sub(remaining, requested, count); if (fmpz_cmp_si(remaining, num) < 0) { num = fmpz_get_si(remaining); } fmpz_clear(remaining); } if (fmpz_cmp_si(iter, 30) < 0) { num = FLINT_MIN(1 << fmpz_get_si(iter), num); } acb_dirichlet_hardy_z_zeros(p, n, num, prec); print_zeros(p, n, num, digits); fmpz_add_si(n, n, num); fmpz_add_si(count, count, num); fmpz_add_si(iter, iter, 1); } fmpz_clear(iter); } /* This is the large height method. */ if (platt) { while (fmpz_sgn(requested) < 0 || fmpz_cmp(count, requested) < 0) { slong found; slong num = buffersize; if (fmpz_sgn(requested) >= 0) { fmpz_t remaining; fmpz_init(remaining); fmpz_sub(remaining, requested, count); if (fmpz_cmp_si(remaining, num) < 0) { num = fmpz_get_si(remaining); } fmpz_clear(remaining); } found = acb_dirichlet_platt_local_hardy_z_zeros(p, n, num, prec); if (!found) { flint_printf("Failed to find some zeros.\n"); flint_printf("Maybe prec is not high enough or something " "is wrong with the internal tuning parameters."); flint_abort(); } print_zeros(p, n, found, digits); fmpz_add_si(n, n, found); fmpz_add_si(count, count, found); } } TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE _arb_vec_clear(p, buffersize); fmpz_clear(nstart); fmpz_clear(n); fmpz_clear(requested); fmpz_clear(count); flint_cleanup_master(); return 0; } flint-3.1.3/flint.pc.in000066400000000000000000000004411461254215100146770ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ includedir=@includedir@ libdir=@libdir@ Name: @PACKAGE_NAME@ Description: Fast Library for Number Theory Version: @PACKAGE_VERSION@ URL: https://flintlib.org/ Requires: gmp >= 6.2.1 mpfr >= 4.1.0 Cflags: -I${includedir} Libs: -L${libdir} -lflint flint-3.1.3/src/000077500000000000000000000000001461254215100134225ustar00rootroot00000000000000flint-3.1.3/src/NTL-interface.h000066400000000000000000000237251461254215100161770ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FLINT_NTL_INT_H #define FLINT_NTL_INT_H #include #include #include #include #include #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_poly.h" NTL_CLIENT /* Converts an NTL ZZ to an fmpz_t. Assumes the fmpz_t has already been allocated to have sufficient space. */ inline void fmpz_set_ZZ(fmpz_t rop, const ZZ& op) { const _ntl_gbigint x = op.rep; if (!x) fmpz_zero(rop); else { const mp_size_t lw = op.size(); const mp_limb_t *xp = ((mp_limb_t *) (((slong *) (x)) + 2)); if (lw == 0) fmpz_zero(rop); else if (lw == 1) fmpz_set_ui(rop, xp[0]); else { __mpz_struct *mf = _fmpz_promote(rop); mpz_import(mf, lw, -1, sizeof(mp_limb_t), 0, 0, xp); } if (op < WORD(0)) fmpz_neg(rop, rop); } } /* Converts an fmpz_t to an NTL ZZ. Allocation is automatically handled. */ inline void fmpz_get_ZZ(NTL_NNS ZZ& rop, const fmpz_t op) { mp_limb_t *xp; _ntl_gbigint *x = &rop.rep; slong lw = fmpz_size(op); fmpz c = *op; if (lw == 0) { if (*x) ((slong *)(*x))[1] = 0; // size return; } _ntl_gsetlength(x, lw); xp = ((mp_limb_t *) (((slong *) (*x)) + 2)); // data if (COEFF_IS_MPZ(c)) { __mpz_struct * m = COEFF_TO_PTR(c); mpn_copyi(xp, m->_mp_d, lw); } else { if (c < WORD(0)) xp[0] = -c; else xp[0] = c; } if (fmpz_sgn(op) < 0) ((slong *)(*x))[1] = -lw; else ((slong *)(*x))[1] = lw; } /* Converts an NTL ZZ_p to an fmpz_t. Assumes the fmpz_t has already been allocated to have sufficient space. */ inline void fmpz_set_ZZ_p(fmpz_t rop, const NTL_NNS ZZ_p& op) { fmpz_set_ZZ(rop, rep(op)); } /* Converts an fmpz_t to an NTL ZZ_p. Allocation is automatically handled. */ inline void fmpz_get_ZZ_p(NTL_NNS ZZ_p& rop, const fmpz_t op) { ZZ a; fmpz_get_ZZ(a, op); conv(rop, a); } /* Converts an NTL zz_p to an fmpz_t. */ inline void fmpz_set_zz_p(fmpz_t rop, const NTL_NNS zz_p& op) { fmpz_set_si(rop, rep(op)); } /* Converts an fmpz_t to an NTL zz_p. */ void fmpz_get_zz_p(NTL_NNS zz_p& rop, const fmpz_t op) { conv(rop, fmpz_get_si(op)); } /* Converts an fmpz_poly_t to an NTL ZZX. */ inline void fmpz_poly_get_ZZX(NTL_NNS ZZX& rop, const fmpz_poly_t op) { const slong len = op->length; if (len == 0) { rop = 0; } else { slong i; ZZ *ap; rop.rep.SetLength(len); for (i = 0, ap = rop.rep.elts(); i < len; i++, ap++) { fmpz_get_ZZ(*ap, op->coeffs + i); } } } /* Converts an NTL ZZX to an fmpz_poly_t. */ inline void fmpz_poly_set_ZZX(fmpz_poly_t rop, const NTL_NNS ZZX& op) { const slong len = deg(op) + 1; if (len == 0) { fmpz_poly_zero(rop); } else { slong i; const ZZ *ap; fmpz_poly_fit_length(rop, len); _fmpz_poly_set_length(rop, len); for (i = 0, ap = op.rep.elts(); i < len; i++, ap++) { fmpz_set_ZZ(rop->coeffs + i, *ap); } } } /* Converts an fmpz_mod_poly_t to an NTL ZZ_pX. */ inline void fmpz_mod_poly_get_ZZ_pX(NTL_NNS ZZ_pX& rop, const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx) { const slong len = op->length; if (len == 0) { rop = 0; } else { slong i; ZZ_p *ap; rop.rep.SetLength(len); for (i = 0, ap = rop.rep.elts(); i < len; i++, ap++) { fmpz_get_ZZ_p(*ap, op->coeffs + i); } } } /* Converts an NTL ZZ_pX to an fmpz_poly_t. */ inline void fmpz_mod_poly_set_ZZ_pX(fmpz_mod_poly_t rop, const NTL_NNS ZZ_pX& op, const fmpz_mod_ctx_t ctx) { const slong len = deg(op) + 1; if (len == 0) { fmpz_mod_poly_zero(rop, ctx); } else { slong i; const ZZ_p *ap; fmpz_mod_poly_fit_length(rop, len, ctx); _fmpz_mod_poly_set_length(rop, len); for (i = 0, ap = op.rep.elts(); i < len; i++, ap++) { fmpz_set_ZZ_p(rop->coeffs + i, *ap); } } } /* Converts an fq_t to an NTL ZZ_pE. */ inline void fq_get_ZZ_pE(NTL_NNS ZZ_pE& rop, const fq_t op, const fq_ctx_t ctx) { ZZ_pX p; const slong len = op->length; if (len == 0) { rop = 0; } else { slong i; ZZ_p *ap; p.rep.SetLength(len); for (i = 0, ap = p.rep.elts(); i < len; i++, ap++) { fmpz_get_ZZ_p(*ap, op->coeffs + i); } conv(rop, p); } } /* Converts an NTL ZZ_pE to an fq_t. */ inline void fq_set_ZZ_pE(fq_t rop, const NTL_NNS ZZ_pE& op, const fq_ctx_t ctx) { const slong len = deg(rep(op)) + 1; if (len == 0) { fq_zero(rop, ctx); } else { slong i; const ZZ_p *ap; fmpz_poly_fit_length(rop, len); _fmpz_poly_set_length(rop, len); for (i = 0, ap = rep(op).rep.elts(); i < len; i++, ap++) { fmpz_set_ZZ_p(rop->coeffs + i, *ap); } _fmpz_poly_normalise(rop); } } /* Converts an fq_poly_t to an NTL ZZ_pEX. */ inline void fq_poly_get_ZZ_pEX(NTL_NNS ZZ_pEX& rop, const fq_poly_t op, const fq_ctx_t ctx) { const slong len = op->length; if (len == 0) { rop = 0; } else { slong i; ZZ_pE *ap; rop.rep.SetLength(len); for (i = 0, ap = rop.rep.elts(); i < len; i++, ap++) { fq_get_ZZ_pE(*ap, op->coeffs + i, ctx); } } } /* Converts an NTL ZZ_pEX to an fq_poly_t. */ inline void fq_poly_set_ZZ_pEX(fq_poly_t rop, const NTL_NNS ZZ_pEX& op, const fq_ctx_t ctx) { const slong len = deg(op) + 1; if (len == 0) { fq_poly_zero(rop, ctx); } else { slong i; const ZZ_pE *ap; fq_poly_fit_length(rop, len, ctx); _fq_poly_set_length(rop, len, ctx); for (i = 0, ap = op.rep.elts(); i < len; i++, ap++) { fq_set_ZZ_pE(rop->coeffs + i, *ap, ctx); } _fq_poly_normalise(rop, ctx); } } /* Converts an fmpz_mod_poly_t to an NTL zz_pX. */ inline void fmpz_mod_poly_get_zz_pX(NTL_NNS zz_pX& rop, const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx) { const slong len = op->length; if (len == 0) { rop = 0; } else { slong i; zz_p *ap; rop.rep.SetLength(len); for (i = 0, ap = rop.rep.elts(); i < len; i++, ap++) { fmpz_get_zz_p(*ap, op->coeffs + i); } } } /* Converts an NTL zz_pX to an fmpz_poly_t. */ inline void fmpz_mod_poly_set_zz_pX(fmpz_mod_poly_t rop, const NTL_NNS zz_pX& op, const fmpz_mod_ctx_t ctx) { const slong len = deg(op) + 1; if (len == 0) { fmpz_mod_poly_zero(rop, ctx); } else { slong i; const zz_p *ap; fmpz_mod_poly_fit_length(rop, len, ctx); _fmpz_mod_poly_set_length(rop, len); for (i = 0, ap = op.rep.elts(); i < len; i++, ap++) { fmpz_set_zz_p(rop->coeffs + i, *ap); } } } /* Converts an fq_t to an NTL zz_pE. */ inline void fq_get_zz_pE(NTL_NNS zz_pE& rop, const fq_t op, const fq_ctx_t ctx) { zz_pX p; const slong len = op->length; if (len == 0) { rop = 0; } else { slong i; zz_p *ap; p.rep.SetLength(len); for (i = 0, ap = p.rep.elts(); i < len; i++, ap++) { fmpz_get_zz_p(*ap, op->coeffs + i); } conv(rop, p); } } /* Converts an NTL zz_pE to an fq_t. */ inline void fq_set_zz_pE(fq_t rop, const NTL_NNS zz_pE& op, const fq_ctx_t ctx) { const slong len = deg(rep(op)) + 1; if (len == 0) { fq_zero(rop, ctx); } else { slong i; const zz_p *ap; fmpz_poly_fit_length(rop, len); _fmpz_poly_set_length(rop, len); for (i = 0, ap = rep(op).rep.elts(); i < len; i++, ap++) { fmpz_set_zz_p(rop->coeffs + i, *ap); } _fmpz_poly_normalise(rop); } } /* Converts an fq_poly_t to an NTL zz_pEX. */ inline void fq_poly_get_zz_pEX(NTL_NNS zz_pEX& rop, const fq_poly_t op, const fq_ctx_t ctx) { const slong len = op->length; if (len == 0) { rop = 0; } else { slong i; zz_pE *ap; rop.rep.SetLength(len); for (i = 0, ap = rop.rep.elts(); i < len; i++, ap++) { fq_get_zz_pE(*ap, op->coeffs + i, ctx); } } } /* Converts an NTL zz_pEX to an fq_poly_t. */ inline void fq_poly_set_zz_pEX(fq_poly_t rop, const NTL_NNS zz_pEX& op, const fq_ctx_t ctx) { const slong len = deg(op) + 1; if (len == 0) { fq_poly_zero(rop, ctx); } else { slong i; const zz_pE *ap; fq_poly_fit_length(rop, len, ctx); _fq_poly_set_length(rop, len, ctx); for (i = 0, ap = op.rep.elts(); i < len; i++, ap++) { fq_set_zz_pE(rop->coeffs + i, *ap, ctx); } _fq_poly_normalise(rop, ctx); } } #endif flint-3.1.3/src/acb.h000066400000000000000000000752341461254215100143330ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_H #define ACB_H #ifdef ACB_INLINES_C #define ACB_INLINE #else #define ACB_INLINE static inline #endif #include "arb.h" #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif #define acb_realref(x) (&(x)->real) #define acb_imagref(x) (&(x)->imag) ACB_INLINE void acb_init(acb_t x) { arb_init(acb_realref(x)); arb_init(acb_imagref(x)); } void acb_clear(acb_t x); acb_ptr _acb_vec_init(slong n); void _acb_vec_clear(acb_ptr v, slong n); ACB_INLINE arb_ptr acb_real_ptr(acb_t z) { return acb_realref(z); } ACB_INLINE arb_ptr acb_imag_ptr(acb_t z) { return acb_imagref(z); } ACB_INLINE void acb_get_real(arb_t re, const acb_t z) { arb_set(re, acb_realref(z)); } ACB_INLINE void acb_get_imag(arb_t im, const acb_t z) { arb_set(im, acb_imagref(z)); } ACB_INLINE void acb_get_mid(acb_t res, const acb_t x) { arb_get_mid_arb(acb_realref(res), acb_realref(x)); arb_get_mid_arb(acb_imagref(res), acb_imagref(x)); } ACB_INLINE int acb_is_zero(const acb_t z) { return arb_is_zero(acb_realref(z)) && arb_is_zero(acb_imagref(z)); } ACB_INLINE int acb_is_one(const acb_t z) { return arb_is_one(acb_realref(z)) && arb_is_zero(acb_imagref(z)); } ACB_INLINE int acb_is_exact(const acb_t z) { return arb_is_exact(acb_realref(z)) && arb_is_exact(acb_imagref(z)); } ACB_INLINE int acb_is_int(const acb_t z) { return arb_is_zero(acb_imagref(z)) && arb_is_int(acb_realref(z)); } ACB_INLINE int acb_is_int_2exp_si(const acb_t z, slong e) { return arb_is_zero(acb_imagref(z)) && arb_is_int_2exp_si(acb_realref(z), e); } ACB_INLINE void acb_zero(acb_t z) { arb_zero(acb_realref(z)); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_one(acb_t z) { arb_one(acb_realref(z)); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_onei(acb_t z) { arb_zero(acb_realref(z)); arb_one(acb_imagref(z)); } ACB_INLINE void acb_set(acb_t z, const acb_t x) { arb_set(acb_realref(z), acb_realref(x)); arb_set(acb_imagref(z), acb_imagref(x)); } ACB_INLINE void acb_set_round(acb_t z, const acb_t x, slong prec) { arb_set_round(acb_realref(z), acb_realref(x), prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_neg_round(acb_t z, const acb_t x, slong prec) { arb_neg_round(acb_realref(z), acb_realref(x), prec); arb_neg_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_swap(acb_t z, acb_t x) { arb_swap(acb_realref(z), acb_realref(x)); arb_swap(acb_imagref(z), acb_imagref(x)); } ACB_INLINE int acb_equal(const acb_t x, const acb_t y) { return arb_equal(acb_realref(x), acb_realref(y)) && arb_equal(acb_imagref(x), acb_imagref(y)); } ACB_INLINE int acb_equal_si(const acb_t x, slong y) { return arb_equal_si(acb_realref(x), y) && arb_is_zero(acb_imagref(x)); } ACB_INLINE int acb_eq(const acb_t x, const acb_t y) { return arb_eq(acb_realref(x), acb_realref(y)) && arb_eq(acb_imagref(x), acb_imagref(y)); } ACB_INLINE int acb_ne(const acb_t x, const acb_t y) { return arb_ne(acb_realref(x), acb_realref(y)) || arb_ne(acb_imagref(x), acb_imagref(y)); } ACB_INLINE int acb_overlaps(const acb_t x, const acb_t y) { return arb_overlaps(acb_realref(x), acb_realref(y)) && arb_overlaps(acb_imagref(x), acb_imagref(y)); } ACB_INLINE int acb_contains_zero(const acb_t x) { return arb_contains_zero(acb_realref(x)) && arb_contains_zero(acb_imagref(x)); } ACB_INLINE int acb_contains_fmpq(const acb_t x, const fmpq_t y) { return arb_contains_fmpq(acb_realref(x), y) && arb_contains_zero(acb_imagref(x)); } ACB_INLINE int acb_contains_fmpz(const acb_t x, const fmpz_t y) { return arb_contains_fmpz(acb_realref(x), y) && arb_contains_zero(acb_imagref(x)); } ACB_INLINE int acb_contains(const acb_t x, const acb_t y) { return arb_contains(acb_realref(x), acb_realref(y)) && arb_contains(acb_imagref(x), acb_imagref(y)); } ACB_INLINE int acb_contains_interior(const acb_t x, const acb_t y) { return arb_contains_interior(acb_realref(x), acb_realref(y)) && arb_contains_interior(acb_imagref(x), acb_imagref(y)); } ACB_INLINE void acb_set_ui(acb_t z, ulong c) { arb_set_ui(acb_realref(z), c); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_set_d(acb_t z, double c) { arb_set_d(acb_realref(z), c); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_set_si(acb_t z, slong c) { arb_set_si(acb_realref(z), c); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_set_si_si(acb_t z, slong x, slong y) { arb_set_si(acb_realref(z), x); arb_set_si(acb_imagref(z), y); } ACB_INLINE void acb_set_d_d(acb_t z, double x, double y) { arb_set_d(acb_realref(z), x); arb_set_d(acb_imagref(z), y); } ACB_INLINE void acb_set_fmpz(acb_t z, const fmpz_t c) { arb_set_fmpz(acb_realref(z), c); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_set_fmpz_fmpz(acb_t z, const fmpz_t x, const fmpz_t y) { arb_set_fmpz(acb_realref(z), x); arb_set_fmpz(acb_imagref(z), y); } ACB_INLINE void acb_set_round_fmpz(acb_t z, const fmpz_t y, slong prec) { arb_set_round_fmpz(acb_realref(z), y, prec); arb_zero(acb_imagref(z)); } int acb_contains_int(const acb_t x); int acb_get_unique_fmpz(fmpz_t z, const acb_t x); ACB_INLINE void acb_set_fmpq(acb_t z, const fmpq_t c, slong prec) { arb_set_fmpq(acb_realref(z), c, prec); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_set_arb(acb_t z, const arb_t c) { arb_set(acb_realref(z), c); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_set_arb_arb(acb_t z, const arb_t x, const arb_t y) { arb_set(acb_realref(z), x); arb_set(acb_imagref(z), y); } ACB_INLINE void acb_set_round_arb(acb_t z, const arb_t x, slong prec) { arb_set_round(acb_realref(z), x, prec); arb_zero(acb_imagref(z)); } ACB_INLINE void acb_trim(acb_t z, const acb_t x) { arb_trim(acb_realref(z), acb_realref(x)); arb_trim(acb_imagref(z), acb_imagref(x)); } ACB_INLINE void acb_add_error_arf(acb_t x, const arf_t err) { arb_add_error_arf(acb_realref(x), err); arb_add_error_arf(acb_imagref(x), err); } ACB_INLINE void acb_add_error_mag(acb_t x, const mag_t err) { arb_add_error_mag(acb_realref(x), err); arb_add_error_mag(acb_imagref(x), err); } ACB_INLINE void acb_add_error_arb(acb_t x, const arb_t err) { arb_add_error(acb_realref(x), err); arb_add_error(acb_imagref(x), err); } void acb_get_mag(mag_t z, const acb_t x); void acb_get_mag_lower(mag_t z, const acb_t x); void acb_get_abs_ubound_arf(arf_t u, const acb_t z, slong prec); void acb_get_abs_lbound_arf(arf_t u, const acb_t z, slong prec); void acb_get_rad_ubound_arf(arf_t u, const acb_t z, slong prec); ACB_INLINE void acb_union(acb_t res, const acb_t x, const acb_t y, slong prec) { arb_union(acb_realref(res), acb_realref(x), acb_realref(y), prec); arb_union(acb_imagref(res), acb_imagref(x), acb_imagref(y), prec); } void acb_arg(arb_t r, const acb_t z, slong prec); void acb_sgn(acb_t res, const acb_t z, slong prec); void acb_csgn(arb_t res, const acb_t z); void acb_real_abs(acb_t res, const acb_t z, int analytic, slong prec); void acb_real_sgn(acb_t res, const acb_t z, int analytic, slong prec); void acb_real_heaviside(acb_t res, const acb_t z, int analytic, slong prec); void acb_real_floor(acb_t res, const acb_t z, int analytic, slong prec); void acb_real_ceil(acb_t res, const acb_t z, int analytic, slong prec); void acb_real_max(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec); void acb_real_min(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec); void acb_real_sqrtpos(acb_t res, const acb_t z, int analytic, slong prec); void acb_sqrt_analytic(acb_t res, const acb_t z, int analytic, slong prec); void acb_rsqrt_analytic(acb_t res, const acb_t z, int analytic, slong prec); void acb_log_analytic(acb_t res, const acb_t z, int analytic, slong prec); void acb_pow_analytic(acb_t res, const acb_t z, const acb_t w, int analytic, slong prec); ACB_INLINE void acb_add(acb_t z, const acb_t x, const acb_t y, slong prec) { arb_add(acb_realref(z), acb_realref(x), acb_realref(y), prec); arb_add(acb_imagref(z), acb_imagref(x), acb_imagref(y), prec); } ACB_INLINE void acb_sub(acb_t z, const acb_t x, const acb_t y, slong prec) { arb_sub(acb_realref(z), acb_realref(x), acb_realref(y), prec); arb_sub(acb_imagref(z), acb_imagref(x), acb_imagref(y), prec); } ACB_INLINE void acb_add_si(acb_t z, const acb_t x, slong c, slong prec) { arb_add_si(acb_realref(z), acb_realref(x), c, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_add_ui(acb_t z, const acb_t x, ulong c, slong prec) { arb_add_ui(acb_realref(z), acb_realref(x), c, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_sub_si(acb_t z, const acb_t x, slong c, slong prec) { arb_sub_si(acb_realref(z), acb_realref(x), c, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_sub_ui(acb_t z, const acb_t x, ulong c, slong prec) { arb_sub_ui(acb_realref(z), acb_realref(x), c, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_add_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) { arb_add_fmpz(acb_realref(z), acb_realref(x), y, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_add_arb(acb_t z, const acb_t x, const arb_t y, slong prec) { arb_add(acb_realref(z), acb_realref(x), y, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_sub_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) { arb_sub_fmpz(acb_realref(z), acb_realref(x), y, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_sub_arb(acb_t z, const acb_t x, const arb_t y, slong prec) { arb_sub(acb_realref(z), acb_realref(x), y, prec); arb_set_round(acb_imagref(z), acb_imagref(x), prec); } ACB_INLINE void acb_neg(acb_t z, const acb_t x) { arb_neg(acb_realref(z), acb_realref(x)); arb_neg(acb_imagref(z), acb_imagref(x)); } ACB_INLINE void acb_conj(acb_t z, const acb_t x) { arb_set(acb_realref(z), acb_realref(x)); arb_neg(acb_imagref(z), acb_imagref(x)); } ACB_INLINE void acb_abs(arb_t u, const acb_t z, slong prec) { arb_hypot(u, acb_realref(z), acb_imagref(z), prec); } ACB_INLINE void acb_mul_ui(acb_t z, const acb_t x, ulong y, slong prec) { arb_mul_ui(acb_realref(z), acb_realref(x), y, prec); arb_mul_ui(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_mul_si(acb_t z, const acb_t x, slong y, slong prec) { arb_mul_si(acb_realref(z), acb_realref(x), y, prec); arb_mul_si(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_mul_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) { arb_mul_fmpz(acb_realref(z), acb_realref(x), y, prec); arb_mul_fmpz(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_mul_arb(acb_t z, const acb_t x, const arb_t y, slong prec) { arb_mul(acb_realref(z), acb_realref(x), y, prec); arb_mul(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_mul_onei(acb_t z, const acb_t x) { if (z == x) { arb_swap(acb_realref(z), acb_imagref(z)); arb_neg(acb_realref(z), acb_realref(z)); } else { arb_neg(acb_realref(z), acb_imagref(x)); arb_set(acb_imagref(z), acb_realref(x)); } } ACB_INLINE void acb_div_onei(acb_t z, const acb_t x) { if (z == x) { arb_swap(acb_realref(z), acb_imagref(z)); arb_neg(acb_imagref(z), acb_imagref(z)); } else { arb_set(acb_realref(z), acb_imagref(x)); arb_neg(acb_imagref(z), acb_realref(x)); } } ACB_INLINE void acb_mul_i_pow_si(acb_t z, const acb_t x, slong k) { k &= 3; if (k == 0) acb_set(z, x); else if (k == 1) acb_mul_onei(z, x); else if (k == 2) acb_neg(z, x); else acb_div_onei(z, x); } void acb_mul(acb_t z, const acb_t x, const acb_t y, slong prec); void acb_mul_naive(acb_t z, const acb_t x, const acb_t y, slong prec); ACB_INLINE void acb_mul_2exp_si(acb_t z, const acb_t x, slong e) { arb_mul_2exp_si(acb_realref(z), acb_realref(x), e); arb_mul_2exp_si(acb_imagref(z), acb_imagref(x), e); } ACB_INLINE void acb_mul_2exp_fmpz(acb_t z, const acb_t x, const fmpz_t c) { arb_mul_2exp_fmpz(acb_realref(z), acb_realref(x), c); arb_mul_2exp_fmpz(acb_imagref(z), acb_imagref(x), c); } void acb_addmul(acb_t z, const acb_t x, const acb_t y, slong prec); void acb_submul(acb_t z, const acb_t x, const acb_t y, slong prec); ACB_INLINE void acb_addmul_ui(acb_t z, const acb_t x, ulong y, slong prec) { arb_addmul_ui(acb_realref(z), acb_realref(x), y, prec); arb_addmul_ui(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_addmul_si(acb_t z, const acb_t x, slong y, slong prec) { arb_addmul_si(acb_realref(z), acb_realref(x), y, prec); arb_addmul_si(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_submul_ui(acb_t z, const acb_t x, ulong y, slong prec) { arb_submul_ui(acb_realref(z), acb_realref(x), y, prec); arb_submul_ui(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_submul_si(acb_t z, const acb_t x, slong y, slong prec) { arb_submul_si(acb_realref(z), acb_realref(x), y, prec); arb_submul_si(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_addmul_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) { arb_addmul_fmpz(acb_realref(z), acb_realref(x), y, prec); arb_addmul_fmpz(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_submul_fmpz(acb_t z, const acb_t x, const fmpz_t y, slong prec) { arb_submul_fmpz(acb_realref(z), acb_realref(x), y, prec); arb_submul_fmpz(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_addmul_arb(acb_t z, const acb_t x, const arb_t y, slong prec) { arb_addmul(acb_realref(z), acb_realref(x), y, prec); arb_addmul(acb_imagref(z), acb_imagref(x), y, prec); } ACB_INLINE void acb_submul_arb(acb_t z, const acb_t x, const arb_t y, slong prec) { arb_submul(acb_realref(z), acb_realref(x), y, prec); arb_submul(acb_imagref(z), acb_imagref(x), y, prec); } void acb_dot_simple(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec); void acb_dot_precise(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec); void acb_dot(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec); void acb_approx_dot(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec); void acb_dot_ui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec); void acb_dot_si(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const slong * y, slong ystep, slong len, slong prec); void acb_dot_uiui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec); void acb_dot_siui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec); void acb_dot_fmpz(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const fmpz * y, slong ystep, slong len, slong prec); void acb_inv(acb_t z, const acb_t x, slong prec); void acb_div(acb_t z, const acb_t x, const acb_t y, slong prec); ACB_INLINE void acb_div_ui(acb_t z, const acb_t x, ulong c, slong prec) { arb_div_ui(acb_realref(z), acb_realref(x), c, prec); arb_div_ui(acb_imagref(z), acb_imagref(x), c, prec); } ACB_INLINE void acb_div_si(acb_t z, const acb_t x, slong c, slong prec) { arb_div_si(acb_realref(z), acb_realref(x), c, prec); arb_div_si(acb_imagref(z), acb_imagref(x), c, prec); } ACB_INLINE void acb_div_arb(acb_t z, const acb_t x, const arb_t c, slong prec) { arb_div(acb_realref(z), acb_realref(x), c, prec); arb_div(acb_imagref(z), acb_imagref(x), c, prec); } ACB_INLINE void acb_div_fmpz(acb_t z, const acb_t x, const fmpz_t c, slong prec) { arb_div_fmpz(acb_realref(z), acb_realref(x), c, prec); arb_div_fmpz(acb_imagref(z), acb_imagref(x), c, prec); } void acb_cube(acb_t y, const acb_t x, slong prec); void acb_pow_fmpz(acb_t y, const acb_t b, const fmpz_t e, slong prec); void acb_pow_ui(acb_t y, const acb_t b, ulong e, slong prec); void acb_pow_si(acb_t y, const acb_t b, slong e, slong prec); ACB_INLINE void acb_const_pi(acb_t x, slong prec) { arb_const_pi(acb_realref(x), prec); arb_zero(acb_imagref(x)); } void acb_log(acb_t r, const acb_t z, slong prec); void acb_log1p(acb_t r, const acb_t z, slong prec); void acb_exp(acb_t r, const acb_t z, slong prec); void acb_exp_pi_i(acb_t r, const acb_t z, slong prec); void acb_exp_invexp(acb_t r, acb_t s, const acb_t z, slong prec); void acb_expm1(acb_t r, const acb_t z, slong prec); void acb_sin(acb_t r, const acb_t z, slong prec); void acb_cos(acb_t r, const acb_t z, slong prec); void acb_sin_cos(acb_t s, acb_t c, const acb_t z, slong prec); void acb_tan(acb_t r, const acb_t z, slong prec); void acb_cot(acb_t r, const acb_t z, slong prec); void acb_asin(acb_t r, const acb_t z, slong prec); void acb_acos(acb_t r, const acb_t z, slong prec); void acb_atan(acb_t r, const acb_t z, slong prec); void acb_asinh(acb_t r, const acb_t z, slong prec); void acb_acosh(acb_t r, const acb_t z, slong prec); void acb_atanh(acb_t r, const acb_t z, slong prec); ACB_INLINE void acb_sinh(acb_t y, const acb_t x, slong prec) { acb_mul_onei(y, x); acb_sin(y, y, prec); acb_div_onei(y, y); } ACB_INLINE void acb_cosh(acb_t y, const acb_t x, slong prec) { acb_mul_onei(y, x); acb_cos(y, y, prec); } ACB_INLINE void acb_sinh_cosh(acb_t y, acb_t z, const acb_t x, slong prec) { acb_mul_onei(y, x); acb_sin_cos(y, z, y, prec); acb_div_onei(y, y); } ACB_INLINE void acb_tanh(acb_t y, const acb_t x, slong prec) { acb_mul_onei(y, x); acb_tan(y, y, prec); acb_div_onei(y, y); } ACB_INLINE void acb_coth(acb_t y, const acb_t x, slong prec) { acb_mul_onei(y, x); acb_cot(y, y, prec); acb_mul_onei(y, y); } void acb_sech(acb_t r, const acb_t z, slong prec); void acb_csch(acb_t r, const acb_t z, slong prec); ACB_INLINE void acb_sec(acb_t y, const acb_t x, slong prec) { acb_mul_onei(y, x); acb_sech(y, y, prec); } ACB_INLINE void acb_csc(acb_t y, const acb_t x, slong prec) { acb_mul_onei(y, x); acb_csch(y, y, prec); acb_mul_onei(y, y); } void acb_sin_pi(acb_t r, const acb_t z, slong prec); void acb_cos_pi(acb_t r, const acb_t z, slong prec); void acb_sin_cos_pi(acb_t s, acb_t c, const acb_t z, slong prec); void acb_tan_pi(acb_t r, const acb_t z, slong prec); void acb_cot_pi(acb_t r, const acb_t z, slong prec); void acb_csc_pi(acb_t y, const acb_t x, slong prec); void acb_sinc(acb_t res, const acb_t z, slong prec); void acb_sinc_pi(acb_t res, const acb_t z, slong prec); void acb_pow_arb(acb_t z, const acb_t x, const arb_t y, slong prec); void acb_pow(acb_t r, const acb_t x, const acb_t y, slong prec); void acb_sqrt(acb_t y, const acb_t x, slong prec); void acb_rsqrt(acb_t y, const acb_t x, slong prec); void acb_sqrts(acb_t y1, acb_t y2, const acb_t x, slong prec); void acb_root_ui(acb_t y, const acb_t x, ulong k, slong prec); void acb_quadratic_roots_fmpz(acb_t r1, acb_t r2, const fmpz_t a, const fmpz_t b, const fmpz_t c, slong prec); void acb_chebyshev_t_ui(acb_t a, ulong n, const acb_t x, slong prec); void acb_chebyshev_t2_ui(acb_t a, acb_t b, ulong n, const acb_t x, slong prec); void acb_chebyshev_u_ui(acb_t a, ulong n, const acb_t x, slong prec); void acb_chebyshev_u2_ui(acb_t a, acb_t b, ulong n, const acb_t x, slong prec); void acb_rising_ui(acb_t z, const acb_t x, ulong n, slong prec); void acb_rising(acb_t z, const acb_t x, const acb_t n, slong prec); void acb_rising2_ui(acb_t u, acb_t v, const acb_t x, ulong n, slong prec); void acb_rising_ui_get_mag(mag_t bound, const acb_t s, ulong n); void acb_gamma(acb_t y, const acb_t x, slong prec); void acb_rgamma(acb_t y, const acb_t x, slong prec); void acb_lgamma(acb_t y, const acb_t x, slong prec); void acb_log_sin_pi(acb_t res, const acb_t z, slong prec); void acb_digamma(acb_t y, const acb_t x, slong prec); void acb_zeta(acb_t z, const acb_t s, slong prec); void acb_hurwitz_zeta(acb_t z, const acb_t s, const acb_t a, slong prec); void acb_polygamma(acb_t res, const acb_t s, const acb_t z, slong prec); void acb_bernoulli_poly_ui(acb_t res, ulong n, const acb_t x, slong prec); void acb_log_barnes_g(acb_t res, const acb_t z, slong prec); void acb_barnes_g(acb_t res, const acb_t z, slong prec); void acb_polylog(acb_t w, const acb_t s, const acb_t z, slong prec); void acb_polylog_si(acb_t w, slong s, const acb_t z, slong prec); void acb_agm1(acb_t m, const acb_t z, slong prec); void acb_agm1_cpx(acb_ptr m, const acb_t z, slong len, slong prec); void acb_agm(acb_t res, const acb_t a, const acb_t b, slong prec); #define ACB_LAMBERTW_LEFT 2 #define ACB_LAMBERTW_MIDDLE 4 void acb_lambertw_asymp(acb_t res, const acb_t z, const fmpz_t k, slong L, slong M, slong prec); int acb_lambertw_check_branch(const acb_t w, const fmpz_t k, slong prec); void acb_lambertw_bound_deriv(mag_t res, const acb_t z, const acb_t ez1, const fmpz_t k); void acb_lambertw(acb_t res, const acb_t z, const fmpz_t k, int flags, slong prec); ACB_INLINE void acb_sqr(acb_t res, const acb_t val, slong prec) { acb_mul(res, val, val, prec); } ACB_INLINE int acb_is_finite(const acb_t x) { return arb_is_finite(acb_realref(x)) && arb_is_finite(acb_imagref(x)); } ACB_INLINE void acb_indeterminate(acb_t x) { arb_indeterminate(acb_realref(x)); arb_indeterminate(acb_imagref(x)); } ACB_INLINE acb_ptr _acb_vec_entry_ptr(acb_ptr vec, slong i) { return vec + i; } ACB_INLINE void _acb_vec_zero(acb_ptr A, slong n) { slong i; for (i = 0; i < n; i++) acb_zero(A + i); } ACB_INLINE int _acb_vec_is_zero(acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) if (!acb_is_zero(vec + i)) return 0; return 1; } ACB_INLINE void _acb_vec_set(acb_ptr res, acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) acb_set(res + i, vec + i); } ACB_INLINE void _acb_vec_set_round(acb_ptr res, acb_srcptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) acb_set_round(res + i, vec + i, prec); } ACB_INLINE void _acb_vec_swap(acb_ptr res, acb_ptr vec, slong len) { slong i; for (i = 0; i < len; i++) acb_swap(res + i, vec + i); } ACB_INLINE void _acb_vec_neg(acb_ptr res, acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) acb_neg(res + i, vec + i); } ACB_INLINE void _acb_vec_add(acb_ptr res, acb_srcptr vec1, acb_srcptr vec2, slong len, slong prec) { slong i; for (i = 0; i < len; i++) acb_add(res + i, vec1 + i, vec2 + i, prec); } ACB_INLINE void _acb_vec_sub(acb_ptr res, acb_srcptr vec1, acb_srcptr vec2, slong len, slong prec) { slong i; for (i = 0; i < len; i++) acb_sub(res + i, vec1 + i, vec2 + i, prec); } ACB_INLINE void _acb_vec_scalar_submul(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) { slong i; for (i = 0; i < len; i++) acb_submul(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_addmul(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) { slong i; for (i = 0; i < len; i++) acb_addmul(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_mul(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) { slong i; for (i = 0; i < len; i++) acb_mul(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_mul_ui(acb_ptr res, acb_srcptr vec, slong len, ulong c, slong prec) { slong i; for (i = 0; i < len; i++) acb_mul_ui(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_mul_2exp_si(acb_ptr res, acb_srcptr vec, slong len, slong c) { slong i; for (i = 0; i < len; i++) acb_mul_2exp_si(res + i, vec + i, c); } ACB_INLINE void _acb_vec_scalar_mul_onei(acb_ptr res, acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) acb_mul_onei(res + i, vec + i); } ACB_INLINE void _acb_vec_scalar_div_ui(acb_ptr res, acb_srcptr vec, slong len, ulong c, slong prec) { slong i; for (i = 0; i < len; i++) acb_div_ui(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_div(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) { slong i; for (i = 0; i < len; i++) acb_div(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_mul_arb(acb_ptr res, acb_srcptr vec, slong len, const arb_t c, slong prec) { slong i; for (i = 0; i < len; i++) acb_mul_arb(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_div_arb(acb_ptr res, acb_srcptr vec, slong len, const arb_t c, slong prec) { slong i; for (i = 0; i < len; i++) { arb_div(acb_realref(res + i), acb_realref(vec + i), c, prec); arb_div(acb_imagref(res + i), acb_imagref(vec + i), c, prec); } } ACB_INLINE void _acb_vec_scalar_mul_fmpz(acb_ptr res, acb_srcptr vec, slong len, const fmpz_t c, slong prec) { slong i; for (i = 0; i < len; i++) acb_mul_fmpz(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_scalar_div_fmpz(acb_ptr res, acb_srcptr vec, slong len, const fmpz_t c, slong prec) { slong i; for (i = 0; i < len; i++) acb_div_fmpz(res + i, vec + i, c, prec); } ACB_INLINE void _acb_vec_sqr(acb_ptr res, acb_srcptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) acb_sqr(res + i, vec + i, prec); } #ifdef FLINT_HAVE_FILE void acb_fprint(FILE * file, const acb_t x); void acb_fprintd(FILE * file, const acb_t z, slong digits); void acb_fprintn(FILE * fp, const acb_t z, slong digits, ulong flags); #endif void acb_print(const acb_t x); void acb_printd(const acb_t z, slong digits); void acb_printn(const acb_t x, slong digits, ulong flags); void _acb_vec_printd(acb_srcptr vec, slong len, slong ndigits); void _acb_vec_printn(acb_srcptr vec, slong len, slong ndigits, ulong flags); void acb_randtest(acb_t z, flint_rand_t state, slong prec, slong mag_bits); void acb_randtest_special(acb_t z, flint_rand_t state, slong prec, slong mag_bits); void acb_randtest_precise(acb_t z, flint_rand_t state, slong prec, slong mag_bits); void acb_randtest_param(acb_t z, flint_rand_t state, slong prec, slong mag_bits); void acb_urandom(acb_t z, flint_rand_t state, slong prec); slong acb_rel_error_bits(const acb_t x); ACB_INLINE slong acb_rel_accuracy_bits(const acb_t x) { return -acb_rel_error_bits(x); } slong acb_rel_one_accuracy_bits(const acb_t x); ACB_INLINE slong acb_bits(const acb_t x) { slong b1, b2; b1 = arb_bits(acb_realref(x)); b2 = arb_bits(acb_imagref(x)); return FLINT_MAX(b1, b2); } ACB_INLINE int acb_is_real(const acb_t x) { return arb_is_zero(acb_imagref(x)); } ACB_INLINE int _acb_vec_is_real(acb_srcptr v, slong len) { slong i; for (i = 0; i < len; i++) { if (!acb_is_real(v + i)) return 0; } return 1; } ACB_INLINE int _acb_vec_is_finite(acb_srcptr vec, slong len) { return _arb_vec_is_finite((arb_srcptr) vec, 2 * len); } ACB_INLINE int _acb_vec_equal(acb_srcptr vec1, acb_srcptr vec2, slong len) { slong i; for (i = 0; i < len; i++) { if (!acb_equal(vec1 + i, vec2 + i)) return 0; } return 1; } ACB_INLINE int _acb_vec_overlaps(acb_srcptr vec1, acb_srcptr vec2, slong len) { slong i; for (i = 0; i < len; i++) { if (!acb_overlaps(vec1 + i, vec2 + i)) return 0; } return 1; } ACB_INLINE int _acb_vec_contains(acb_srcptr vec1, acb_srcptr vec2, slong len) { slong i; for (i = 0; i < len; i++) { if (!acb_contains(vec1 + i, vec2 + i)) return 0; } return 1; } ACB_INLINE void _acb_vec_get_real(arb_ptr re, acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) { arb_set(re + i, acb_realref(vec + i)); } } ACB_INLINE void _acb_vec_get_imag(arb_ptr im, acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) { arb_set(im + i, acb_imagref(vec + i)); } } ACB_INLINE void _acb_vec_set_real_imag(acb_ptr vec, arb_srcptr re, arb_srcptr im, slong len) { slong i; for (i = 0; i < len; i++) { acb_set_arb_arb(vec + i, re + i, im + i); } } ACB_INLINE slong _acb_vec_bits(acb_srcptr vec, slong len) { return _arb_vec_bits((arb_srcptr) vec, 2 * len); } void _acb_vec_set_powers(acb_ptr xs, const acb_t x, slong len, slong prec); ACB_INLINE void _acb_vec_add_error_arf_vec(acb_ptr res, arf_srcptr err, slong len) { slong i; for (i = 0; i < len; i++) acb_add_error_arf(res + i, err + i); } ACB_INLINE void _acb_vec_add_error_mag_vec(acb_ptr res, mag_srcptr err, slong len) { slong i; for (i = 0; i < len; i++) { mag_add(arb_radref(acb_realref(res + i)), arb_radref(acb_realref(res + i)), err + i); mag_add(arb_radref(acb_imagref(res + i)), arb_radref(acb_imagref(res + i)), err + i); } } ACB_INLINE void _acb_vec_indeterminate(acb_ptr vec, slong len) { _arb_vec_indeterminate((arb_ptr) vec, 2 * len); } ACB_INLINE void _acb_vec_trim(acb_ptr res, acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) acb_trim(res + i, vec + i); } ACB_INLINE int _acb_vec_get_unique_fmpz_vec(fmpz * res, acb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) if (!acb_get_unique_fmpz(res + i, vec + i)) return 0; return 1; } /* sort complex numbers in a nice-to-display order */ void _acb_vec_sort_pretty(acb_ptr vec, slong len); /* roots of unity */ void acb_unit_root(acb_t res, ulong order, slong prec); void _acb_vec_unit_roots(acb_ptr z, slong order, slong len, slong prec); ACB_INLINE slong acb_allocated_bytes(const acb_t x) { return arb_allocated_bytes(acb_realref(x)) + arb_allocated_bytes(acb_imagref(x)); } ACB_INLINE slong _acb_vec_allocated_bytes(acb_srcptr vec, slong len) { return _arb_vec_allocated_bytes((arb_srcptr) vec, 2 * len); } ACB_INLINE double _acb_vec_estimate_allocated_bytes(slong len, slong prec) { return 2 * _arb_vec_estimate_allocated_bytes(len, prec); } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb/000077500000000000000000000000001461254215100141475ustar00rootroot00000000000000flint-3.1.3/src/acb/acos.c000066400000000000000000000020551461254215100152420ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_acos(acb_t res, const acb_t z, slong prec) { if (acb_is_one(z)) { acb_zero(res); } else { acb_t t; acb_init(t); acb_one(t); if (arb_is_zero(acb_imagref(z)) && arb_gt(acb_realref(z), acb_realref(t))) { /* pure imaginary on (1,inf) */ acb_asin(res, z, prec); acb_neg(res, res); arb_zero(acb_realref(res)); } else { acb_asin(res, z, prec); acb_const_pi(t, prec); acb_mul_2exp_si(t, t, -1); acb_sub(res, t, res, prec); } acb_clear(t); } } flint-3.1.3/src/acb/acosh.c000066400000000000000000000023261461254215100154130ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_acosh(acb_t res, const acb_t z, slong prec) { if (acb_is_one(z)) { acb_zero(res); } else { acb_t t, u; acb_init(t); acb_init(u); acb_add_ui(t, z, 1, prec); acb_sub_ui(u, z, 1, prec); acb_sqrt(t, t, prec); acb_sqrt(u, u, prec); acb_mul(t, t, u, prec); acb_add(t, t, z, prec); if (!arb_is_zero(acb_imagref(z))) { acb_log(res, t, prec); } else { /* pure imaginary on (-1,1) */ arb_abs(acb_realref(u), acb_realref(z)); arb_one(acb_imagref(u)); acb_log(res, t, prec); if (arb_lt(acb_realref(u), acb_imagref(u))) arb_zero(acb_realref(res)); } acb_clear(t); acb_clear(u); } } flint-3.1.3/src/acb/addmul.c000066400000000000000000000017701461254215100155660ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_addmul(acb_t z, const acb_t x, const acb_t y, slong prec) { if (arb_is_zero(acb_imagref(y))) { arb_addmul(acb_imagref(z), acb_imagref(x), acb_realref(y), prec); arb_addmul(acb_realref(z), acb_realref(x), acb_realref(y), prec); } else if (arb_is_zero(acb_imagref(x))) { arb_addmul(acb_imagref(z), acb_imagref(y), acb_realref(x), prec); arb_addmul(acb_realref(z), acb_realref(y), acb_realref(x), prec); } else { acb_t t; acb_init(t); acb_mul(t, x, y, prec); acb_add(z, z, t, prec); acb_clear(t); } } flint-3.1.3/src/acb/agm.c000066400000000000000000000061751461254215100150700ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void mag_agm(mag_t res, const mag_t x, const mag_t y); static void agm_helper(acb_t res, const acb_t a, const acb_t b, slong prec) { if (acb_rel_accuracy_bits(b) >= acb_rel_accuracy_bits(a)) { acb_div(res, a, b, prec); acb_agm1(res, res, prec); acb_mul(res, res, b, prec); } else { acb_div(res, b, a, prec); acb_agm1(res, res, prec); acb_mul(res, res, a, prec); } } void acb_agm(acb_t res, const acb_t a, const acb_t b, slong prec) { acb_t t, u, v; if (!acb_is_finite(a) || !acb_is_finite(b)) { acb_indeterminate(res); return; } if (acb_is_zero(a) || acb_is_zero(b)) { acb_zero(res); return; } if (arb_is_zero(acb_imagref(a)) && arb_is_zero(acb_imagref(b))) { if (arb_is_nonnegative(acb_realref(a)) && arb_is_nonnegative(acb_realref(b))) { arb_agm(acb_realref(res), acb_realref(a), acb_realref(b), prec); arb_zero(acb_imagref(res)); return; } } if (acb_contains_zero(a) || acb_contains_zero(b)) { mag_t ra, rb; mag_init(ra); mag_init(rb); acb_get_mag(ra, a); acb_get_mag(rb, b); mag_agm(ra, ra, rb); acb_zero(res); acb_add_error_mag(res, ra); mag_clear(ra); mag_clear(rb); return; } acb_init(t); acb_add(t, a, b, prec); acb_mul_2exp_si(t, t, -1); /* a ~= -b; bound magnitude */ if (acb_contains_zero(t)) { mag_t ra, rb; mag_init(ra); mag_init(rb); acb_get_mag(ra, a); acb_get_mag(rb, b); mag_mul(rb, ra, rb); mag_sqrt(rb, rb); acb_get_mag(ra, t); mag_agm(ra, ra, rb); acb_zero(res); acb_add_error_mag(res, ra); mag_clear(ra); mag_clear(rb); acb_clear(t); return; } /* Do the initial step with the optimal square root, reducing to agm1 */ acb_init(u); acb_init(v); acb_mul(u, a, b, prec); /* we can compute either square root here; avoid the branch cut */ if (arf_sgn(arb_midref(acb_realref(u))) >= 0) { acb_sqrt(u, u, prec); } else { acb_neg(u, u); acb_sqrt(u, u, prec); acb_mul_onei(u, u); } acb_div(v, t, u, prec); if (arb_is_nonnegative(acb_realref(v))) { agm_helper(res, t, u, prec); } else if (arb_is_negative(acb_realref(v))) { acb_neg(u, u); agm_helper(res, t, u, prec); } else { agm_helper(v, t, u, prec); acb_neg(u, u); agm_helper(res, t, u, prec); acb_union(res, res, v, prec); } acb_clear(t); acb_clear(u); acb_clear(v); } flint-3.1.3/src/acb/agm1.c000066400000000000000000000344371461254215100151530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_poly.h" void mag_agm(mag_t res, const mag_t x, const mag_t y); /* Checks that |arg(z)| <= 3 pi / 4 */ static int acb_check_arg(const acb_t z) { mag_t re, im; int res; if (!arb_contains_negative(acb_realref(z))) return 1; mag_init(re); mag_init(im); arb_get_mag(re, acb_realref(z)); arb_get_mag_lower(im, acb_imagref(z)); res = mag_cmp(re, im) < 0; mag_clear(re); mag_clear(im); return res; } static void sqrtmul(acb_t c, const acb_t a, const acb_t b, slong prec) { if (arb_is_positive(acb_realref(a)) && arb_is_positive(acb_realref(b))) { acb_mul(c, a, b, prec); acb_sqrt(c, c, prec); } else if (arb_is_nonnegative(acb_imagref(a)) && arb_is_nonnegative(acb_imagref(b))) { acb_mul(c, a, b, prec); acb_neg(c, c); acb_sqrt(c, c, prec); acb_mul_onei(c, c); } else if (arb_is_nonpositive(acb_imagref(a)) && arb_is_nonpositive(acb_imagref(b))) { acb_mul(c, a, b, prec); acb_neg(c, c); acb_sqrt(c, c, prec); acb_mul_onei(c, c); acb_neg(c, c); } else { acb_t d; acb_init(d); acb_sqrt(c, a, prec); acb_sqrt(d, b, prec); acb_mul(c, c, d, prec); acb_clear(d); } } static void acb_agm_close_taylor(acb_t res, acb_t z, acb_t z2, const acb_t aplusb, const acb_t aminusb, const mag_t err, slong prec) { acb_div(z, aminusb, aplusb, prec); acb_sqr(z, z, prec); acb_sqr(z2, z, prec); acb_mul_si(res, z2, -469, prec); acb_addmul_si(res, z, -704, prec); acb_mul(res, res, z2, prec); acb_addmul_si(res, z2, -1280, prec); acb_mul_2exp_si(z, z, 12); acb_sub(res, res, z, prec); acb_add_ui(res, res, 16384, prec); acb_mul_2exp_si(res, res, -15); acb_add_error_mag(res, err); acb_mul(res, res, aplusb, prec); } static void acb_agm1_around_zero(acb_t res, const acb_t z, slong prec) { mag_t a, b; mag_init(a); mag_init(b); mag_one(a); acb_get_mag(b, z); mag_agm(a, a, b); acb_zero(res); acb_add_error_mag(res, a); mag_clear(a); mag_clear(b); } void acb_agm1_basecase(acb_t res, const acb_t z, slong prec) { acb_t a, b, t, u; mag_t err, err2; int isreal; isreal = acb_is_real(z) && arb_is_nonnegative(acb_realref(z)); if (isreal) { acb_init(a); acb_one(a); arb_agm(acb_realref(res), acb_realref(a), acb_realref(z), prec); arb_zero(acb_imagref(res)); acb_clear(a); return; } if (acb_is_zero(z)) { acb_zero(res); return; } if (acb_is_one(z)) { acb_one(res); return; } if (!acb_check_arg(z)) { acb_agm1_around_zero(res, z, prec); return; } acb_init(a); acb_init(b); acb_init(t); acb_init(u); mag_init(err); mag_init(err2); acb_one(a); acb_set_round(b, z, prec); while (1) { acb_sub(u, a, b, prec); if (acb_contains_zero(u)) { /* Dupont's thesis, p. 87: |M(z) - a_n| <= |a_n - b_n| */ acb_set(res, a); acb_get_mag(err, u); acb_add_error_mag(res, err); break; } acb_add(t, a, b, prec); acb_get_mag(err, u); acb_get_mag_lower(err2, t); mag_div(err, err, err2); mag_geom_series(err, err, 10); mag_mul_2exp_si(err, err, -6); if (mag_cmp_2exp_si(err, -prec) < 0) { acb_agm_close_taylor(res, a, b, t, u, err, prec); break; } acb_mul_2exp_si(t, t, -1); sqrtmul(u, a, b, prec); acb_swap(t, a); acb_swap(u, b); } acb_clear(a); acb_clear(b); acb_clear(t); acb_clear(u); mag_clear(err); mag_clear(err2); } /* Computes (M(z), M'(z)) using a finite difference. Assumes z exact, |arg(z)| <= 3 pi / 4. */ void acb_agm1_deriv_diff(acb_t Mz, acb_t Mzp, const acb_t z, slong prec) { mag_t err, t, C; fmpz_t rexp, hexp; acb_t u, v; slong wp, qexp; int isreal; if (!acb_is_exact(z) || !acb_is_finite(z) || acb_is_zero(z) || !acb_check_arg(z)) { acb_indeterminate(Mz); acb_indeterminate(Mzp); return; } isreal = acb_is_real(z) && arb_is_nonnegative(acb_realref(z)); /* |M^(k)(z) / k!| <= C * D^k where C = max(1, |z| + r), D = 1/r, and 0 < r < |z| M(z+h) - M(z-h) |--------------- - M'(z)| <= D^3 h^2 / (1 - D h) 2h M(z+h) + M(z-h) |--------------- - M(z)| <= D^2 h^2 / (1 - D h) 2 h D < 1. */ fmpz_init(hexp); fmpz_init(rexp); mag_init(err); mag_init(t); mag_init(C); acb_init(u); acb_init(v); /* choose r = 2^rexp such that r < |z| */ acb_get_mag_lower(t, z); fmpz_sub_ui(rexp, MAG_EXPREF(t), 2); /* Choose h = r/q = 2^hexp = 2^(rexp-qexp) with qexp = floor(prec/2) + 5 D = 1/r = 2^-rexp f(z) error <= C D^2 h^2 / (1-Dh) f'(z) error <= C D^3 h^2 / (1-Dh) 1/(1-Dh) < 2, hence: f(z) error < 2 C D^2 h^2 = C 2^(1-2*qexp) f'(z) error < 2 C D^3 h^2 = C 2^(1-rexp-2*qexp) */ /* C = max(1, |z| + r) */ acb_get_mag(C, z); mag_one(t); mag_mul_2exp_fmpz(t, t, rexp); mag_add(C, C, t); mag_one(t); mag_max(C, C, t); qexp = prec / 2 + 5; /* if (fmpz_sgn(rexp) < 0) qexp += fmpz_bits(rexp); */ /* compute h = 2^hexp */ fmpz_sub_ui(hexp, rexp, qexp); /* compute finite differences */ wp = prec + qexp + 5; acb_one(u); acb_mul_2exp_fmpz(u, u, hexp); acb_add(u, z, u, wp); acb_agm1_basecase(u, u, wp); acb_one(v); acb_mul_2exp_fmpz(v, v, hexp); acb_sub(v, z, v, wp); acb_agm1_basecase(v, v, wp); acb_add(Mz, u, v, prec); acb_sub(Mzp, u, v, prec); acb_mul_2exp_si(Mz, Mz, -1); acb_mul_2exp_si(Mzp, Mzp, -1); fmpz_neg(hexp, hexp); acb_mul_2exp_fmpz(Mzp, Mzp, hexp); /* add error */ mag_mul_2exp_si(err, C, 1 - 2 * qexp); if (isreal) arb_add_error_mag(acb_realref(Mz), err); else acb_add_error_mag(Mz, err); fmpz_neg(rexp, rexp); mag_mul_2exp_fmpz(err, err, rexp); if (isreal) arb_add_error_mag(acb_realref(Mzp), err); else acb_add_error_mag(Mzp, err); fmpz_clear(hexp); fmpz_clear(rexp); mag_clear(err); mag_clear(t); mag_clear(C); acb_clear(u); acb_clear(v); } /* For input z + eps First derivative bound: max(1, |z|+|eps|+r) / r Second derivative bound: 2 max(1, |z|+|eps|+r) / r^2 This is assuming that the circle at z with radius |eps| + r does not cross the negative half axis, which we check. */ void acb_agm1_deriv_right(acb_t Mz, acb_t Mzp, const acb_t z, slong prec) { if (acb_is_exact(z)) { acb_agm1_deriv_diff(Mz, Mzp, z, prec); } else { if (!acb_is_finite(z) || !acb_check_arg(z)) { acb_indeterminate(Mz); acb_indeterminate(Mzp); } else { acb_t t; mag_t r, eps, err, one; int isreal; acb_init(t); mag_init(r); mag_init(err); mag_init(one); mag_init(eps); isreal = acb_is_real(z) && arb_is_nonnegative(acb_realref(z)); mag_hypot(eps, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); /* choose r avoiding overlap with negative half axis */ if (arf_sgn(arb_midref(acb_realref(z))) < 0) arb_get_mag_lower(r, acb_imagref(z)); else acb_get_mag_lower(r, z); mag_mul_2exp_si(r, r, -1); if (mag_is_zero(r)) { acb_indeterminate(Mz); acb_indeterminate(Mzp); } else { acb_set(t, z); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_get_mag(err, z); mag_add(err, err, r); mag_add(err, err, eps); mag_one(one); mag_max(err, err, one); mag_mul(err, err, eps); acb_agm1_deriv_diff(Mz, Mzp, t, prec); mag_div(err, err, r); if (isreal) arb_add_error_mag(acb_realref(Mz), err); else acb_add_error_mag(Mz, err); mag_div(err, err, r); mag_mul_2exp_si(err, err, 1); if (isreal) arb_add_error_mag(acb_realref(Mzp), err); else acb_add_error_mag(Mzp, err); } acb_clear(t); mag_clear(r); mag_clear(err); mag_clear(one); mag_clear(eps); } } } void acb_agm1(acb_t res, const acb_t z, slong prec) { if (acb_is_zero(z)) { acb_zero(res); } else if (!acb_is_finite(z)) { acb_indeterminate(res); } else if (acb_contains_zero(z)) { acb_agm1_around_zero(res, z, prec); } else if (arf_sgn(arb_midref(acb_realref(z))) >= 0) { acb_agm1_basecase(res, z, prec); } else if (acb_equal_si(z, -1)) { acb_zero(res); } else { /* use M(1,z) = M((z+1)/2, sqrt(z)) = (z+1)/2 * M(1, 2 sqrt(z) / (z+1)) = sqrt(z) * M(1, (z+1) / (2 sqrt(z)) */ acb_t t; acb_init(t); acb_add_ui(t, z, 1, prec); acb_mul_2exp_si(t, t, -1); if (acb_contains_zero(t)) { mag_t ra, rb; mag_init(ra); mag_init(rb); acb_get_mag(ra, t); acb_get_mag(rb, z); mag_sqrt(rb, rb); mag_agm(ra, ra, rb); acb_zero(res); acb_add_error_mag(res, ra); mag_clear(ra); mag_clear(rb); } else if (acb_rel_accuracy_bits(t) > acb_rel_accuracy_bits(z)) { acb_sqrt(res, z, prec); acb_div(res, res, t, prec); acb_agm1_basecase(res, res, prec); acb_mul(res, res, t, prec); } else { acb_sqrt(res, z, prec); acb_div(t, t, res, prec); acb_agm1_basecase(t, t, prec); acb_mul(res, res, t, prec); } acb_clear(t); } } void acb_agm1_deriv(acb_t Mz, acb_t Mzp, const acb_t z, slong prec) { /* u = 2 sqrt(z) / (1+z) Mz = (1+z) M(u) / 2 Mzp = [M(u) - (z-1) M'(u) / ((1+z) sqrt(z))] / 2 */ if (arf_sgn(arb_midref(acb_realref(z))) >= 0) { if (acb_is_one(z)) { acb_one(Mz); acb_mul_2exp_si(Mzp, Mz, -1); } else acb_agm1_deriv_right(Mz, Mzp, z, prec); } else { acb_t t, u, zp1, zm1; acb_init(t); acb_init(u); acb_init(zp1); acb_init(zm1); acb_sqrt(t, z, prec); acb_add_ui(zp1, z, 1, prec); acb_sub_ui(zm1, z, 1, prec); acb_div(u, t, zp1, prec); acb_mul_2exp_si(u, u, 1); acb_agm1_deriv_right(Mz, Mzp, u, prec); acb_mul(Mzp, Mzp, zm1, prec); acb_mul(t, t, zp1, prec); acb_div(Mzp, Mzp, t, prec); acb_sub(Mzp, Mz, Mzp, prec); acb_mul_2exp_si(Mzp, Mzp, -1); acb_mul(Mz, Mz, zp1, prec); acb_mul_2exp_si(Mz, Mz, -1); acb_clear(t); acb_clear(u); acb_clear(zp1); acb_clear(zm1); } } void acb_agm1_cpx(acb_ptr m, const acb_t z, slong len, slong prec) { if (len < 1) return; if (len == 1) { acb_agm1(m, z, prec); return; } if (len == 2) { acb_agm1_deriv(m, m + 1, z, prec); return; } if (len >= 3) { acb_t t, u, v; acb_ptr w; slong k, n; acb_init(t); acb_init(u); acb_init(v); w = _acb_vec_init(len); acb_agm1_deriv(w, w + 1, z, prec); /* invert series */ acb_inv(w, w, prec); acb_mul(t, w, w, prec); acb_mul(w + 1, w + 1, t, prec); acb_neg(w + 1, w + 1); if (acb_is_one(z)) { for (k = 2; k < len; k++) { n = k - 2; acb_mul_ui(w + k, w + n + 0, (n+1)*(n+1), prec); acb_addmul_ui(w + k, w + n + 1, 7+3*n*(3+n), prec); acb_div_ui(w + k, w + k, 2*(n+2)*(n+2), prec); acb_neg(w + k, w + k); } } else { /* t = 3z^2 - 1 */ /* u = -1 / (z^3 - z) */ acb_mul(t, z, z, prec); acb_mul(u, t, z, prec); acb_mul_ui(t, t, 3, prec); acb_sub_ui(t, t, 1, prec); acb_sub(u, u, z, prec); acb_inv(u, u, prec); acb_neg(u, u); /* use differential equation for second derivative */ acb_mul(w + 2, z, w + 0, prec); acb_addmul(w + 2, t, w + 1, prec); acb_mul(w + 2, w + 2, u, prec); acb_mul_2exp_si(w + 2, w + 2, -1); /* recurrence */ for (k = 3; k < len; k++) { n = k - 3; acb_mul_ui(w + k, w + n + 0, (n+1)*(n+1), prec); acb_mul(v, w + n + 1, z, prec); acb_addmul_ui(w + k, v, 7+3*n*(3+n), prec); acb_mul(v, w + n + 2, t, prec); acb_addmul_ui(w + k, v, (n+2)*(n+2), prec); acb_mul(w + k, w + k, u, prec); acb_div_ui(w + k, w + k, (n+2)*(n+3), prec); } } /* invert series */ _acb_poly_inv_series(m, w, len, len, prec); acb_clear(t); acb_clear(u); acb_clear(v); _acb_vec_clear(w, len); } } flint-3.1.3/src/acb/approx_dot.c000066400000000000000000000536561461254215100165110ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "mpn_extras.h" /* We need uint64_t instead of mp_limb_t on 32-bit systems for safe summation of 30-bit error bounds. */ #include void _arb_dot_addmul_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, mp_srcptr yptr, mp_size_t yn, int negative, flint_bitcnt_t shift); void _arb_dot_add_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, int negative, flint_bitcnt_t shift); static void _arb_dot_output(arb_t res, mp_ptr sum, mp_size_t sn, int negative, slong sum_exp, slong prec) { slong exp_fix; if (sum[sn - 1] >= LIMB_TOP) { mpn_neg(sum, sum, sn); negative ^= 1; } exp_fix = 0; if (sum[sn - 1] == 0) { slong sum_exp2; mp_size_t sn2; sn2 = sn; sum_exp2 = sum_exp; while (sn2 > 0 && sum[sn2 - 1] == 0) { sum_exp2 -= FLINT_BITS; sn2--; } if (sn2 == 0) { arf_zero(arb_midref(res)); } else { _arf_set_round_mpn(arb_midref(res), &exp_fix, sum, sn2, negative, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp_fix + sum_exp2); } } else { if (sn == 2) /* unnecessary? */ _arf_set_round_uiui(arb_midref(res), &exp_fix, sum[1], sum[0], negative, prec, ARF_RND_DOWN); else _arf_set_round_mpn(arb_midref(res), &exp_fix, sum, sn, negative, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp_fix + sum_exp); } } /* xxx: don't use surrounding variables */ #define ARB_DOT_ADD(s_sum, s_serr, s_sn, s_sum_exp, s_subtract, xm) \ if (!arf_is_special(xm)) \ { \ mp_srcptr xptr; \ xexp = ARF_EXP(xm); \ xn = ARF_SIZE(xm); \ xnegative = ARF_SGNBIT(xm); \ shift = s_sum_exp - xexp; \ if (shift >= s_sn * FLINT_BITS) \ { \ } \ else \ { \ xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); \ _arb_dot_add_generic(s_sum, &s_serr, tmp, s_sn, xptr, xn, xnegative ^ s_subtract, shift); \ } \ } \ static void _arf_complex_mul_gauss(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d) { mp_srcptr ap, bp, cp, dp; int asgn, bsgn, csgn, dsgn; mp_size_t an, bn, cn, dn; slong aexp, bexp, cexp, dexp; fmpz texp, uexp; fmpz_t za, zb, zc, zd, t, u, v; slong abot, bbot, cbot, dbot; ARF_GET_MPN_READONLY(ap, an, a); asgn = ARF_SGNBIT(a); aexp = ARF_EXP(a); ARF_GET_MPN_READONLY(bp, bn, b); bsgn = ARF_SGNBIT(b); bexp = ARF_EXP(b); ARF_GET_MPN_READONLY(cp, cn, c); csgn = ARF_SGNBIT(c); cexp = ARF_EXP(c); ARF_GET_MPN_READONLY(dp, dn, d); dsgn = ARF_SGNBIT(d); dexp = ARF_EXP(d); /* Gauss multiplication e = ac - bd f = (a+b)(c+d) - ac - bd */ abot = aexp - an * FLINT_BITS; bbot = bexp - bn * FLINT_BITS; cbot = cexp - cn * FLINT_BITS; dbot = dexp - dn * FLINT_BITS; texp = FLINT_MIN(abot, bbot); uexp = FLINT_MIN(cbot, dbot); fmpz_init(za); fmpz_init(zb); fmpz_init(zc); fmpz_init(zd); fmpz_init(t); fmpz_init(u); fmpz_init(v); fmpz_lshift_mpn(za, ap, an, asgn, abot - texp); fmpz_lshift_mpn(zb, bp, bn, bsgn, bbot - texp); fmpz_lshift_mpn(zc, cp, cn, csgn, cbot - uexp); fmpz_lshift_mpn(zd, dp, dn, dsgn, dbot - uexp); fmpz_add(t, za, zb); fmpz_add(v, zc, zd); fmpz_mul(u, t, v); fmpz_mul(t, za, zc); fmpz_mul(v, zb, zd); fmpz_sub(u, u, t); fmpz_sub(u, u, v); fmpz_sub(t, t, v); texp += uexp; arf_set_fmpz_2exp(e, t, &texp); arf_set_fmpz_2exp(f, u, &texp); fmpz_clear(za); fmpz_clear(zb); fmpz_clear(zc); fmpz_clear(zd); fmpz_clear(t); fmpz_clear(u); fmpz_clear(v); } FLINT_DLL extern slong acb_dot_gauss_dot_cutoff; #define GAUSS_CUTOFF acb_dot_gauss_dot_cutoff void acb_approx_dot_simple(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) { slong i; if (len <= 0) { if (initial == NULL) { arf_zero(arb_midref(acb_realref(res))); arf_zero(arb_midref(acb_imagref(res))); } else { arf_set_round(arb_midref(acb_realref(res)), arb_midref(acb_realref(initial)), prec, ARB_RND); arf_set_round(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(initial)), prec, ARB_RND); } return; } if (initial == NULL && len == 1) { arf_complex_mul(arb_midref(acb_realref(res)), arb_midref(acb_imagref(res)), arb_midref(acb_realref(x)), arb_midref(acb_imagref(x)), arb_midref(acb_realref(y)), arb_midref(acb_imagref(y)), prec, ARB_RND); } else { arf_t e, f; arf_init(e); arf_init(f); if (initial != NULL) { if (subtract) { arf_neg(arb_midref(acb_realref(res)), arb_midref(acb_realref(initial))); arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(initial))); } else { arf_set(arb_midref(acb_realref(res)), arb_midref(acb_realref(initial))); arf_set(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(initial))); } } for (i = 0; i < len; i++) { arf_complex_mul(e, f, arb_midref(acb_realref(x + i * xstep)), arb_midref(acb_imagref(x + i * xstep)), arb_midref(acb_realref(y + i * ystep)), arb_midref(acb_imagref(y + i * ystep)), prec, ARB_RND); if (i == 0 && initial == NULL) { arf_set(arb_midref(acb_realref(res)), e); arf_set(arb_midref(acb_imagref(res)), f); } else { arf_add(arb_midref(acb_realref(res)), arb_midref(acb_realref(res)), e, prec, ARB_RND); arf_add(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(res)), f, prec, ARB_RND); } } arf_clear(e); arf_clear(f); } if (subtract) { arf_neg(arb_midref(acb_realref(res)), arb_midref(acb_realref(res))); arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(res))); } } void acb_approx_dot(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) { slong i, j, padding, extend; slong xexp, yexp, exp; slong re_nonzero, im_nonzero; slong re_max_exp, re_min_exp, re_sum_exp; slong im_max_exp, im_min_exp, im_sum_exp; slong re_prec, im_prec; int xnegative, ynegative; mp_size_t xn, yn, re_sn, im_sn, alloc; flint_bitcnt_t shift; arb_srcptr xi, yi; arf_srcptr xm, ym; mp_limb_t re_serr, im_serr; /* Sum over arithmetic errors */ mp_ptr tmp, re_sum, im_sum; /* Workspace */ slong xoff, yoff; char * use_gauss; ARF_ADD_TMP_DECL; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { acb_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } /* Number of nonzero midpoint terms in sum. */ re_nonzero = 0; im_nonzero = 0; /* Terms are bounded by 2^max_exp (with WORD_MIN = -infty) */ re_max_exp = WORD_MIN; im_max_exp = WORD_MIN; /* Used to reduce the precision. */ re_min_exp = WORD_MAX; im_min_exp = WORD_MAX; /* Account for the initial term. */ if (initial != NULL) { if (!ARF_IS_LAGOM(arb_midref(acb_realref(initial))) || !ARF_IS_LAGOM(arb_midref(acb_imagref(initial)))) { acb_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(acb_realref(initial)); if (!arf_is_special(xm)) { re_max_exp = ARF_EXP(xm); re_nonzero++; if (prec > 2 * FLINT_BITS) re_min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } xm = arb_midref(acb_imagref(initial)); if (!arf_is_special(xm)) { im_max_exp = ARF_EXP(xm); im_nonzero++; if (prec > 2 * FLINT_BITS) im_min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } } for (xoff = 0; xoff < 2; xoff++) { for (yoff = 0; yoff < 2; yoff++) { slong nonzero, max_exp, min_exp; if (xoff == yoff) { nonzero = re_nonzero; max_exp = re_max_exp; min_exp = re_min_exp; } else { nonzero = im_nonzero; max_exp = im_max_exp; min_exp = im_min_exp; } /* Determine maximum exponents for the main sum and the radius sum. */ for (i = 0; i < len; i++) { xi = ((arb_srcptr) x) + 2 * i * xstep + xoff; yi = ((arb_srcptr) y) + 2 * i * ystep + yoff; /* Fallback for huge exponents or non-finite values. */ if (!ARF_IS_LAGOM(arb_midref(xi)) || !ARF_IS_LAGOM(arb_midref(yi))) { acb_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(xi); ym = arb_midref(yi); /* (xm+xr)(ym+yr) = xm ym + [xr ym + xm yr + xr yr] */ if (!arf_is_special(xm)) { xexp = ARF_EXP(xm); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_exp = FLINT_MAX(max_exp, xexp + yexp); nonzero++; if (prec > 2 * FLINT_BITS) { slong bot; bot = (xexp + yexp) - (ARF_SIZE(xm) + ARF_SIZE(ym)) * FLINT_BITS; min_exp = FLINT_MIN(min_exp, bot); } } } } if (xoff == yoff) { re_nonzero = nonzero; re_max_exp = max_exp; re_min_exp = min_exp; } else { im_nonzero = nonzero; im_max_exp = max_exp; im_min_exp = min_exp; } } } re_prec = prec; im_prec = prec; if (re_max_exp == WORD_MIN && im_max_exp == WORD_MIN) { arf_zero(arb_midref(acb_realref(res))); arf_zero(arb_midref(acb_imagref(res))); return; } /* The midpoint sum is zero. */ if (re_max_exp == WORD_MIN) { re_prec = 2; } else { if (re_min_exp != WORD_MAX) re_prec = FLINT_MIN(re_prec, re_max_exp - re_min_exp + MAG_BITS); re_prec = FLINT_MAX(re_prec, 2); } if (im_max_exp == WORD_MIN) { im_prec = 2; } else { if (re_min_exp != WORD_MAX) im_prec = FLINT_MIN(im_prec, im_max_exp - im_min_exp + MAG_BITS); im_prec = FLINT_MAX(im_prec, 2); } extend = FLINT_BIT_COUNT(re_nonzero) + 1; padding = 4 + FLINT_BIT_COUNT(len); re_sn = (re_prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; re_sn = FLINT_MAX(re_sn, 2); re_sum_exp = re_max_exp + extend; extend = FLINT_BIT_COUNT(im_nonzero) + 1; padding = 4 + FLINT_BIT_COUNT(len); im_sn = (im_prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; im_sn = FLINT_MAX(im_sn, 2); im_sum_exp = im_max_exp + extend; /* We need sn + 1 limb for the sum (sn limbs + 1 dummy limb for carry or borrow that avoids an extra branch). We need 2 * (sn + 2) limbs to store the product of two numbers with up to (sn + 2) limbs, plus 1 extra limb for shifting the product. */ alloc = (re_sn + 1) + (im_sn + 1) + 2 * (FLINT_MAX(re_sn, im_sn) + 2) + 1; ARF_ADD_TMP_ALLOC(re_sum, alloc) im_sum = re_sum + (re_sn + 1); tmp = im_sum + (im_sn + 1); /* Set sum to 0 */ re_serr = 0; for (j = 0; j < re_sn + 1; j++) re_sum[j] = 0; im_serr = 0; for (j = 0; j < im_sn + 1; j++) im_sum[j] = 0; if (initial != NULL) { xm = arb_midref(acb_realref(initial)); ARB_DOT_ADD(re_sum, re_serr, re_sn, re_sum_exp, subtract, xm); xm = arb_midref(acb_imagref(initial)); ARB_DOT_ADD(im_sum, im_serr, im_sn, im_sum_exp, subtract, xm); } use_gauss = NULL; if (re_prec >= GAUSS_CUTOFF * FLINT_BITS && im_prec >= GAUSS_CUTOFF * FLINT_BITS) { arf_t e, f; for (i = 0; i < len; i++) { arb_srcptr ai, bi, ci, di; mp_size_t an, bn, cn, dn; slong aexp, bexp, cexp, dexp; ai = ((arb_srcptr) x) + 2 * i * xstep; bi = ((arb_srcptr) x) + 2 * i * xstep + 1; ci = ((arb_srcptr) y) + 2 * i * ystep; di = ((arb_srcptr) y) + 2 * i * ystep + 1; an = ARF_SIZE(arb_midref(ai)); bn = ARF_SIZE(arb_midref(bi)); cn = ARF_SIZE(arb_midref(ci)); dn = ARF_SIZE(arb_midref(di)); aexp = ARF_EXP(arb_midref(ai)); bexp = ARF_EXP(arb_midref(bi)); cexp = ARF_EXP(arb_midref(ci)); dexp = ARF_EXP(arb_midref(di)); if (an >= GAUSS_CUTOFF && bn >= GAUSS_CUTOFF && bn >= GAUSS_CUTOFF && cn >= GAUSS_CUTOFF && FLINT_ABS(an - bn) <= 2 && FLINT_ABS(cn - dn) <= 2 && FLINT_ABS(aexp - bexp) <= 64 && FLINT_ABS(cexp - dexp) <= 64 && re_sum_exp - (aexp + cexp) < 0.1 * re_prec && im_sum_exp - (aexp + dexp) < 0.1 * im_prec && an + cn < 2.2 * re_sn && an + dn < 2.2 * im_sn) { if (use_gauss == NULL) { use_gauss = flint_calloc(len, sizeof(char)); arf_init(e); arf_init(f); } use_gauss[i] = 1; _arf_complex_mul_gauss(e, f, arb_midref(ai), arb_midref(bi), arb_midref(ci), arb_midref(di)); ARB_DOT_ADD(re_sum, re_serr, re_sn, re_sum_exp, 0, e); ARB_DOT_ADD(im_sum, im_serr, im_sn, im_sum_exp, 0, f); } } if (use_gauss != NULL) { arf_clear(e); arf_clear(f); } } for (xoff = 0; xoff < 2; xoff++) { for (yoff = 0; yoff < 2; yoff++) { slong sum_exp; mp_ptr sum; mp_size_t sn; mp_limb_t serr; int flipsign; if (xoff == yoff) { sum_exp = re_sum_exp; sum = re_sum; sn = re_sn; if (re_max_exp == WORD_MIN) continue; } else { sum_exp = im_sum_exp; sum = im_sum; sn = im_sn; if (im_max_exp == WORD_MIN) continue; } serr = 0; flipsign = (xoff + yoff == 2); for (i = 0; i < len; i++) { xi = ((arb_srcptr) x) + 2 * i * xstep + xoff; yi = ((arb_srcptr) y) + 2 * i * ystep + yoff; xm = arb_midref(xi); ym = arb_midref(yi); /* The midpoints of x[i] and y[i] are both nonzero. */ if (!arf_is_special(xm) && !arf_is_special(ym)) { xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); yexp = ARF_EXP(ym); yn = ARF_SIZE(ym); ynegative = ARF_SGNBIT(ym); exp = xexp + yexp; shift = sum_exp - exp; if (shift >= sn * FLINT_BITS) { } else if (xn <= 2 && yn <= 2 && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; if (xn == 1 && yn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; umul_ppmm(u3, u2, x0, y0); u1 = u0 = 0; } else if (xn == 2 && yn == 2) { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); } else if (xn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X1(u3, u2, u1, y1, y0, x0); u0 = 0; } else { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; FLINT_MPN_MUL_2X1(u3, u2, u1, x1, x0, y0); u0 = 0; } if (sn == 2) { if (shift < FLINT_BITS) { u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u2 = u3; u3 = 0; } else /* FLINT_BITS < shift < 2 * FLINT_BITS */ { u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } if (xnegative ^ ynegative ^ flipsign) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else if (sn == 3) { if (shift < FLINT_BITS) { u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u1 = u2; u2 = u3; u3 = 0; } else if (shift < 2 * FLINT_BITS) { u1 = (u3 << (2 * FLINT_BITS - shift)) | (u2 >> (shift - FLINT_BITS)); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } else if (shift == 2 * FLINT_BITS) { u1 = u3; u2 = 0; u3 = 0; } else /* 2 * FLINT_BITS < shift < 3 * FLINT_BITS */ { u1 = (u3 >> (shift - 2 * FLINT_BITS)); u2 = 0; u3 = 0; } if (xnegative ^ ynegative ^ flipsign) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } else { mp_srcptr xptr, yptr; xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); yptr = (yn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(ym) : ARF_PTR_D(ym); if (use_gauss == NULL || use_gauss[i] == 0) _arb_dot_addmul_generic(sum, &serr, tmp, sn, xptr, xn, yptr, yn, xnegative ^ ynegative ^ flipsign, shift); } } } } } _arb_dot_output(acb_realref(res), re_sum, re_sn, subtract, re_sum_exp, re_prec); _arb_dot_output(acb_imagref(res), im_sum, im_sn, subtract, im_sum_exp, im_prec); ARF_ADD_TMP_FREE(re_sum, alloc); if (use_gauss != NULL) flint_free(use_gauss); } flint-3.1.3/src/acb/arg.c000066400000000000000000000007761461254215100150760ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_arg(arb_t r, const acb_t z, slong prec) { arb_atan2(r, acb_imagref(z), acb_realref(z), prec); } flint-3.1.3/src/acb/asin.c000066400000000000000000000022221461254215100152430ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_asin(acb_t res, const acb_t z, slong prec) { if (arb_is_zero(acb_realref(z))) { arb_asinh(acb_imagref(res), acb_imagref(z), prec); arb_zero(acb_realref(res)); } else { acb_t t; acb_init(t); acb_mul(t, z, z, prec); acb_sub_ui(t, t, 1, prec); acb_neg(t, t); acb_sqrt(t, t, prec); if (acb_is_real(z) && acb_is_real(t)) { arb_atan2(acb_realref(res), acb_realref(z), acb_realref(t), prec); arb_zero(acb_imagref(res)); } else { acb_mul_onei(res, z); acb_add(res, res, t, prec); acb_log(res, res, prec); acb_div_onei(res, res); } acb_clear(t); } } flint-3.1.3/src/acb/asinh.c000066400000000000000000000010361461254215100154150ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_asinh(acb_t res, const acb_t z, slong prec) { acb_mul_onei(res, z); acb_asin(res, res, prec); acb_div_onei(res, res); } flint-3.1.3/src/acb/atan.c000066400000000000000000000053421461254215100152420ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" /* branch cuts are on (+/-i)*[1,inf] */ int acb_atan_on_branch_cut(const acb_t z) { arb_t unit; int result; if (!acb_is_finite(z)) return 1; if (arb_is_nonzero(acb_realref(z))) return 0; if (arb_contains_si(acb_imagref(z), 1) || arb_contains_si(acb_imagref(z), -1)) return 1; arb_init(unit); mag_one(arb_radref(unit)); result = !arb_contains(unit, acb_imagref(z)); arb_clear(unit); return result; } void acb_atan(acb_t r, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_atan(acb_realref(r), acb_realref(z), prec); arb_zero(acb_imagref(r)); } else if (!acb_is_finite(z)) { acb_indeterminate(r); } else { acb_t t, u; acb_init(t); acb_init(u); if (acb_atan_on_branch_cut(z)) { acb_mul_onei(u, z); acb_neg(t, u); acb_log1p(t, t, prec); acb_log1p(u, u, prec); acb_sub(t, t, u, prec); acb_mul_onei(t, t); acb_mul_2exp_si(r, t, -1); } else if (acb_is_exact(z)) { acb_onei(t); acb_sub(t, t, z, prec); acb_div(t, z, t, prec); acb_mul_2exp_si(t, t, 1); acb_log1p(t, t, prec); acb_mul_onei(t, t); acb_mul_2exp_si(r, t, -1); } else { mag_t err, err2; mag_init(err); mag_init(err2); /* atan'(z) = 1/(1+z^2) = 1/((z+i)(z-i)) */ acb_onei(t); acb_add(t, z, t, prec); acb_get_mag_lower(err, t); acb_onei(t); acb_sub(t, z, t, prec); acb_get_mag_lower(err2, t); mag_mul_lower(err, err, err2); mag_hypot(err2, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_div(err, err2, err); arf_set(arb_midref(acb_realref(t)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(t)), arb_midref(acb_imagref(z))); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_atan(r, t, prec); acb_add_error_mag(r, err); mag_clear(err); mag_clear(err2); } acb_clear(t); acb_clear(u); } } flint-3.1.3/src/acb/atanh.c000066400000000000000000000010361461254215100154060ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_atanh(acb_t res, const acb_t z, slong prec) { acb_mul_onei(res, z); acb_atan(res, res, prec); acb_div_onei(res, res); } flint-3.1.3/src/acb/barnes_g.c000066400000000000000000000056241461254215100161020ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_poly.h" void _arb_const_zeta_minus_one_eval(arb_t y, slong prec) { acb_struct z[2]; acb_t s, a; acb_init(z + 0); acb_init(z + 1); acb_init(s); acb_init(a); acb_set_si(s, -1); acb_one(a); _acb_poly_zeta_cpx_series(z, s, a, 0, 2, prec + 20); arb_set(y, acb_realref(z + 1)); acb_clear(z + 0); acb_clear(z + 1); acb_clear(s); acb_clear(a); } ARB_DEF_CACHED_CONSTANT(_arb_const_zeta_minus_one, _arb_const_zeta_minus_one_eval) /* LogG(z) = (z-1) LogGamma(z) - zeta'(-1,z) + zeta'(-1) LogG'(z) = (1/2)(-2z + 1 + log(2pi)) + (z-1) digamma(z) */ void _acb_log_barnes_g_zeta(acb_t res, const acb_t z, slong prec) { acb_struct t[3]; acb_init(t + 0); acb_init(t + 1); acb_init(t + 2); acb_set_si(t + 2, -1); _acb_poly_zeta_cpx_series(t, t + 2, z, 0, 2, prec); _arb_const_zeta_minus_one(acb_realref(t), prec); arb_zero(acb_imagref(t)); acb_sub(t, t, t + 1, prec); acb_lgamma(t + 1, z, prec); acb_sub_ui(t + 2, z, 1, prec); acb_addmul(t, t + 1, t + 2, prec); acb_set(res, t); acb_clear(t + 0); acb_clear(t + 1); acb_clear(t + 2); } void _acb_barnes_g_ui_rec(acb_t res, ulong n, slong prec) { acb_t t; ulong k; acb_init(t); acb_one(res); acb_one(t); for (k = 3; k < n; k++) { acb_mul_ui(t, t, k - 1, prec); acb_mul(res, res, t, prec); } acb_clear(t); } void acb_log_barnes_g(acb_t res, const acb_t z, slong prec) { if (acb_is_int(z)) { if (arb_is_nonpositive(acb_realref(z))) { acb_indeterminate(res); return; } if (arf_cmpabs_ui(arb_midref(acb_realref(z)), prec) < 0) { _acb_barnes_g_ui_rec(res, arf_get_si(arb_midref(acb_realref(z)), ARF_RND_DOWN), prec); acb_log(res, res, prec); return; } } _acb_log_barnes_g_zeta(res, z, prec); } void acb_barnes_g(acb_t res, const acb_t z, slong prec) { int real; real = acb_is_real(z); if (acb_is_int(z)) { if (arb_is_nonpositive(acb_realref(z))) { acb_zero(res); return; } if (arf_cmpabs_ui(arb_midref(acb_realref(z)), prec) < 0) { _acb_barnes_g_ui_rec(res, arf_get_si(arb_midref(acb_realref(z)), ARF_RND_DOWN), prec); return; } } _acb_log_barnes_g_zeta(res, z, prec); acb_exp(res, res, prec); if (real) arb_zero(acb_imagref(res)); } flint-3.1.3/src/acb/bernoulli_poly_ui.c000066400000000000000000000037001461254215100200460ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_bernoulli_poly_ui(acb_t res, ulong n, const acb_t x, slong prec) { acb_t s, x2; arb_t t, c; ulong k; if (n == 0) { acb_one(res); return; } if (n == 1) { acb_mul_2exp_si(res, x, 1); acb_sub_ui(res, res, 1, prec); acb_mul_2exp_si(res, res, -1); return; } if (acb_is_real(x)) { arb_bernoulli_poly_ui(acb_realref(res), n, acb_realref(x), prec); arb_zero(acb_imagref(res)); return; } /* assuming small n simplifies the code that follows */ if (n >> (FLINT_BITS / 2) || !acb_is_finite(x)) { acb_indeterminate(res); return; } acb_init(s); acb_init(x2); arb_init(t); arb_init(c); acb_mul(x2, x, x, prec); /* s = x^2 - x n / 2 */ acb_mul_ui(s, x, n, prec); acb_mul_2exp_si(s, s, -1); acb_sub(s, x2, s, prec); /* c = n (n-1) / 2; s = s + c / 6 */ arb_set_ui(c, n * (n - 1)); arb_mul_2exp_si(c, c, -1); arb_div_ui(t, c, 6, prec); acb_add_arb(s, s, t, prec); for (k = 4; k <= n; k += 2) { /* c = binomial(n,k) */ arb_mul_ui(c, c, (n + 1 - k) * (n + 2 - k), prec); arb_div_ui(c, c, k * (k - 1), prec); /* s = s x^2 + b_k c */ acb_mul(s, s, x2, prec); arb_bernoulli_ui(t, k, prec); arb_mul(t, t, c, prec); acb_add_arb(s, s, t, prec); } if (n >= 3 && n % 2) acb_mul(s, s, x, prec); acb_swap(res, s); acb_clear(s); acb_clear(x2); arb_clear(t); arb_clear(c); } flint-3.1.3/src/acb/chebyshev_t2_ui.c000066400000000000000000000023221461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_chebyshev_t2_ui(acb_t a, acb_t b, ulong n, const acb_t x, slong prec) { int i; acb_set_round(a, x, prec); acb_one(b); if (n <= 1) { if (n == 0) acb_swap(a, b); return; } for (i = FLINT_BIT_COUNT(n - 1) - 1; i >= 0; i--) { if (((n - 1) >> i) & 1) { acb_mul(b, b, a, prec); acb_mul_2exp_si(b, b, 1); acb_sub(b, b, x, prec); acb_mul(a, a, a, prec); acb_mul_2exp_si(a, a, 1); acb_sub_ui(a, a, 1, prec); } else { acb_mul(a, a, b, prec); acb_mul_2exp_si(a, a, 1); acb_sub(a, a, x, prec); acb_mul(b, b, b, prec); acb_mul_2exp_si(b, b, 1); acb_sub_ui(b, b, 1, prec); } } } flint-3.1.3/src/acb/chebyshev_t_ui.c000066400000000000000000000024271461254215100173200ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_chebyshev_t_ui(acb_t y, ulong n, const acb_t x, slong prec) { int i, r; if (n <= 1) { if (n == 0) acb_one(y); else acb_set_round(y, x, prec); return; } r = flint_ctz(n); if ((n >> r) == 1) { acb_mul(y, x, x, prec); acb_mul_2exp_si(y, y, 1); acb_sub_ui(y, y, 1, prec); r -= 1; } else { /* we only need one value, so break out final iteration */ acb_t t, u; acb_init(t); acb_init(u); acb_chebyshev_t2_ui(t, u, (n >> (r + 1)) + 1, x, prec); acb_mul(t, t, u, prec); acb_mul_2exp_si(t, t, 1); acb_sub(y, t, x, prec); acb_clear(t); acb_clear(u); } for (i = 0; i < r; i++) { acb_mul(y, y, y, prec); acb_mul_2exp_si(y, y, 1); acb_sub_ui(y, y, 1, prec); } } flint-3.1.3/src/acb/chebyshev_u2_ui.c000066400000000000000000000024401461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_chebyshev_u2_ui(acb_t a, acb_t b, ulong n, const acb_t x, slong prec) { int i; acb_t t, u; if (n == 0) { acb_one(a); acb_zero(b); return; } acb_set_round(a, x, prec); acb_mul_2exp_si(a, a, 1); acb_one(b); if (n == 1) return; acb_init(t); acb_init(u); for (i = FLINT_BIT_COUNT(n) - 2; i >= 0; i--) { acb_add(t, a, b, prec); acb_sub(u, a, b, prec); if ((n >> i) & 1) { acb_submul(b, x, a, prec); acb_mul(a, a, b, prec); acb_neg(a, a); acb_mul_2exp_si(a, a, 1); acb_mul(b, t, u, prec); } else { acb_submul(a, x, b, prec); acb_mul(b, a, b, prec); acb_mul_2exp_si(b, b, 1); acb_mul(a, t, u, prec); } } acb_clear(t); acb_clear(u); } flint-3.1.3/src/acb/chebyshev_u_ui.c000066400000000000000000000021171461254215100173150ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_chebyshev_u_ui(acb_t y, ulong n, const acb_t x, slong prec) { acb_t a, b; if (n <= 1) { if (n == 0) { acb_one(y); } else { acb_set_round(y, x, prec); acb_mul_2exp_si(y, y, 1); } return; } acb_init(a); acb_init(b); acb_chebyshev_u2_ui(a, b, n / 2, x, prec); if (n % 2 == 0) { acb_add(y, a, b, prec); acb_sub(b, a, b, prec); acb_mul(y, y, b, prec); } else { acb_submul(b, a, x, prec); acb_mul(y, a, b, prec); acb_mul_2exp_si(y, y, 1); acb_neg(y, y); } acb_clear(a); acb_clear(b); } flint-3.1.3/src/acb/clear.c000066400000000000000000000023731461254215100154060ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" /* The clear methods are not defined as inlines since this inflates the code size. We inline the content manually here to avoid function call overhead. Question: would calling arb_clear twice here be worth the call overhead, by improving branch prediction? */ void acb_clear(acb_t x) { ARF_DEMOTE(arb_midref(acb_realref(x))); if (COEFF_IS_MPZ(ARF_EXP(arb_midref(acb_realref(x))))) _fmpz_clear_mpz(ARF_EXP(arb_midref(acb_realref(x)))); if (COEFF_IS_MPZ(MAG_EXP(arb_radref(acb_realref(x))))) _fmpz_clear_mpz(MAG_EXP(arb_radref(acb_realref(x)))); ARF_DEMOTE(arb_midref(acb_imagref(x))); if (COEFF_IS_MPZ(ARF_EXP(arb_midref(acb_imagref(x))))) _fmpz_clear_mpz(ARF_EXP(arb_midref(acb_imagref(x)))); if (COEFF_IS_MPZ(MAG_EXP(arb_radref(acb_imagref(x))))) _fmpz_clear_mpz(MAG_EXP(arb_radref(acb_imagref(x)))); } flint-3.1.3/src/acb/contains_int.c000066400000000000000000000010451461254215100170030ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" int acb_contains_int(const acb_t x) { if (!arb_contains_zero(acb_imagref(x))) return 0; return arb_contains_int(acb_realref(x)); } flint-3.1.3/src/acb/cos.c000066400000000000000000000022701461254215100151000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_cos(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_cos(acb_realref(r), a, prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(a)) { arb_cosh(acb_realref(r), b, prec); arb_zero(acb_imagref(r)); } else { arb_t sa, ca, sb, cb; arb_init(sa); arb_init(ca); arb_init(sb); arb_init(cb); arb_sin_cos(sa, ca, a, prec); arb_sinh_cosh(sb, cb, b, prec); arb_mul(acb_realref(r), ca, cb, prec); arb_mul(acb_imagref(r), sa, sb, prec); arb_neg(acb_imagref(r), acb_imagref(r)); arb_clear(sa); arb_clear(ca); arb_clear(sb); arb_clear(cb); } #undef a #undef b } flint-3.1.3/src/acb/cos_pi.c000066400000000000000000000025771461254215100156020ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_cos_pi(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_cos_pi(acb_realref(r), a, prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(a)) { arb_t t; arb_init(t); arb_const_pi(t, prec); arb_mul(t, t, b, prec); arb_cosh(acb_realref(r), t, prec); arb_zero(acb_imagref(r)); arb_clear(t); } else { arb_t sa, ca, sb, cb; arb_init(sa); arb_init(ca); arb_init(sb); arb_init(cb); arb_sin_cos_pi(sa, ca, a, prec); arb_const_pi(cb, prec); arb_mul(cb, cb, b, prec); arb_sinh_cosh(sb, cb, cb, prec); arb_mul(acb_realref(r), ca, cb, prec); arb_mul(acb_imagref(r), sa, sb, prec); arb_neg(acb_imagref(r), acb_imagref(r)); arb_clear(sa); arb_clear(ca); arb_clear(sb); arb_clear(cb); } #undef a #undef b } flint-3.1.3/src/acb/cot.c000066400000000000000000000034271461254215100151060ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_cot(acb_t r, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_cot(acb_realref(r), acb_realref(z), prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(acb_realref(z))) { arb_coth(acb_imagref(r), acb_imagref(z), prec); arb_neg(acb_imagref(r), acb_imagref(r)); arb_zero(acb_realref(r)); } else { acb_t t; acb_init(t); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0) { acb_sin_cos(r, t, z, prec + 4); acb_div(r, t, r, prec); } else { acb_mul_2exp_si(t, z, 1); if (arf_sgn(arb_midref(acb_imagref(z))) > 0) { acb_mul_onei(t, t); acb_exp(t, t, prec + 4); acb_sub_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_mul_onei(r, r); } else { acb_div_onei(t, t); acb_exp(t, t, prec + 4); acb_sub_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_div_onei(r, r); } } acb_clear(t); } } flint-3.1.3/src/acb/cot_pi.c000066400000000000000000000036041461254215100155730ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_cot_pi(acb_t r, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_cot_pi(acb_realref(r), acb_realref(z), prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(acb_realref(z))) { arb_t t; arb_init(t); arb_const_pi(t, prec + 4); arb_mul(t, acb_imagref(z), t, prec + 4); arb_coth(acb_imagref(r), t, prec); arb_neg(acb_imagref(r), acb_imagref(r)); arb_zero(acb_realref(r)); arb_clear(t); } else { acb_t t; acb_init(t); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0) { acb_sin_cos_pi(r, t, z, prec + 4); acb_div(r, t, r, prec); } else { acb_mul_2exp_si(t, z, 1); if (arf_sgn(arb_midref(acb_imagref(z))) > 0) { acb_exp_pi_i(t, t, prec + 4); acb_sub_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_mul_onei(r, r); } else { acb_neg(t, t); acb_exp_pi_i(t, t, prec + 4); acb_sub_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_div_onei(r, r); } } acb_clear(t); } } flint-3.1.3/src/acb/csc_pi.c000066400000000000000000000037311461254215100155570ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_csc_pi(acb_t res, const acb_t z, slong prec) { if (acb_contains_zero(z) || !acb_is_finite(z)) { acb_indeterminate(res); } else if (arb_is_zero(acb_imagref(z))) { arb_csc_pi(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } else if (arb_is_zero(acb_realref(z))) { arb_const_pi(acb_realref(res), prec); arb_mul(acb_imagref(res), acb_imagref(z), acb_realref(res), prec); arb_csch(acb_imagref(res), acb_imagref(res), prec); arb_neg(acb_imagref(res), acb_imagref(res)); arb_zero(acb_realref(res)); } else { if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) > 0) { acb_t t; acb_init(t); if (arf_sgn(arb_midref(acb_imagref(z))) < 0) { acb_neg(t, z); acb_exp_pi_i(t, t, prec + 4); acb_mul(res, t, t, prec + 4); acb_sub_ui(res, res, 1, prec + 4); acb_div(res, t, res, prec); acb_neg(res, res); } else { acb_exp_pi_i(t, z, prec + 4); acb_mul(res, t, t, prec + 4); acb_sub_ui(res, res, 1, prec + 4); acb_div(res, t, res, prec); } acb_mul_2exp_si(res, res, 1); acb_mul_onei(res, res); acb_clear(t); } else { acb_sin_pi(res, z, prec + 4); acb_inv(res, res, prec); } } } flint-3.1.3/src/acb/csch.c000066400000000000000000000034021461254215100152320ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_csch(acb_t res, const acb_t z, slong prec) { if (acb_contains_zero(z) || !acb_is_finite(z)) { acb_indeterminate(res); } else if (arb_is_zero(acb_imagref(z))) { arb_csch(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } else if (arb_is_zero(acb_realref(z))) { arb_csc(acb_imagref(res), acb_imagref(z), prec); arb_neg(acb_imagref(res), acb_imagref(res)); arb_zero(acb_realref(res)); } else { if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 0) > 0) { acb_t t; acb_init(t); if (arf_sgn(arb_midref(acb_realref(z))) > 0) { acb_neg(t, z); acb_exp(t, t, prec + 4); acb_mul(res, t, t, prec + 4); acb_sub_ui(res, res, 1, prec + 4); acb_div(res, t, res, prec); acb_neg(res, res); } else { acb_exp(t, z, prec + 4); acb_mul(res, t, t, prec + 4); acb_sub_ui(res, res, 1, prec + 4); acb_div(res, t, res, prec); } acb_mul_2exp_si(res, res, 1); acb_clear(t); } else { acb_sinh(res, z, prec + 4); acb_inv(res, res, prec); } } } flint-3.1.3/src/acb/csgn.c000066400000000000000000000011171461254215100152450ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_csgn(arb_t res, const acb_t z) { if (arb_is_zero(acb_realref(z))) { arb_sgn(res, acb_imagref(z)); } else { arb_sgn(res, acb_realref(z)); } } flint-3.1.3/src/acb/cube.c000066400000000000000000000024611461254215100152340ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_cube(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_pow_ui(acb_realref(r), a, 3, prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(a)) { arb_pow_ui(acb_imagref(r), b, 3, prec); arb_neg(acb_imagref(r), acb_imagref(r)); arb_zero(acb_realref(r)); } else { arb_t t, u, v; arb_init(t); arb_init(u); arb_init(v); arb_mul(t, a, a, prec); arb_mul(u, b, b, prec); arb_set(v, t); /* t = a^2 - 3b^2 */ arb_submul_ui(t, u, 3, prec); /* u = -(b^2 - 3a^2) */ arb_submul_ui(u, v, 3, prec); arb_neg(u, u); arb_mul(acb_realref(r), t, a, prec); arb_mul(acb_imagref(r), u, b, prec); arb_clear(t); arb_clear(u); arb_clear(v); } #undef a #undef b } flint-3.1.3/src/acb/digamma.c000066400000000000000000000034131461254215100157130ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t x, int use_reflect, int digamma, slong prec); void acb_gamma_stirling_eval(acb_t s, const acb_t z, slong nterms, int digamma, slong prec); void acb_digamma(acb_t y, const acb_t x, slong prec) { int reflect; slong r, n, wp; acb_t t, u, v; if (acb_is_real(x)) { arb_digamma(acb_realref(y), acb_realref(x), prec); arb_zero(acb_imagref(y)); return; } wp = prec + FLINT_BIT_COUNT(prec); acb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 1, wp); acb_init(t); acb_init(u); acb_init(v); /* psi(x) = psi((1-x)+r) - h(1-x,r) - pi*cot(pi*x) */ if (reflect) { acb_sub_ui(t, x, 1, wp); acb_neg(t, t); acb_cot_pi(v, x, wp); arb_const_pi(acb_realref(u), wp); acb_mul_arb(v, v, acb_realref(u), wp); acb_rising2_ui(y, u, t, r, wp); acb_div(u, u, y, wp); acb_add(v, v, u, wp); acb_add_ui(t, t, r, wp); acb_gamma_stirling_eval(u, t, n, 1, wp); acb_sub(y, u, v, wp); } else { acb_add_ui(t, x, r, wp); acb_gamma_stirling_eval(u, t, n, 1, wp); acb_rising2_ui(y, t, x, r, wp); acb_div(t, t, y, wp); acb_sub(y, u, t, prec); } acb_clear(t); acb_clear(u); acb_clear(v); } flint-3.1.3/src/acb/div.c000066400000000000000000000057371461254215100151110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_div(acb_t z, const acb_t x, const acb_t y, slong prec) { #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(y) #define d acb_imagref(y) if (arb_is_zero(d)) { if (arb_is_zero(b)) { arb_div(acb_realref(z), a, c, prec); arb_zero(acb_imagref(z)); } else if (arb_is_zero(a)) { arb_div(acb_imagref(z), b, c, prec); arb_zero(acb_realref(z)); } else if (z != y) { arb_div(acb_realref(z), a, c, prec); arb_div(acb_imagref(z), b, c, prec); } else { arb_t t; arb_init(t); arb_set(t, c); arb_div(acb_realref(z), a, t, prec); arb_div(acb_imagref(z), b, t, prec); arb_clear(t); } } else if (arb_is_zero(c)) { if (arb_is_zero(b)) { arb_div(acb_imagref(z), a, d, prec); arb_neg(acb_imagref(z), acb_imagref(z)); arb_zero(acb_realref(z)); } else if (arb_is_zero(a)) { arb_div(acb_realref(z), b, d, prec); arb_zero(acb_imagref(z)); } else if (z != y) { arb_div(acb_realref(z), a, d, prec); arb_div(acb_imagref(z), b, d, prec); arb_swap(acb_realref(z), acb_imagref(z)); arb_neg(acb_imagref(z), acb_imagref(z)); } else { arb_t t; arb_init(t); arb_set(t, d); arb_div(acb_realref(z), a, t, prec); arb_div(acb_imagref(z), b, t, prec); arb_swap(acb_realref(z), acb_imagref(z)); arb_neg(acb_imagref(z), acb_imagref(z)); arb_clear(t); } } else { if (prec > 256 && acb_bits(y) <= prec / 2 && acb_is_exact(y)) { arb_t t, u, v; arb_init(t); arb_init(u); arb_init(v); arb_mul(t, c, c, prec); arb_addmul(t, d, d, prec); arb_mul(u, a, c, prec); arb_addmul(u, b, d, prec); arb_mul(v, b, c, prec); arb_submul(v, a, d, prec); arb_div(acb_realref(z), u, t, prec); arb_div(acb_imagref(z), v, t, prec); arb_clear(t); arb_clear(u); arb_clear(v); } else { acb_t t; acb_init(t); acb_inv(t, y, prec); acb_mul(z, x, t, prec); acb_clear(t); } } #undef a #undef b #undef c #undef d } flint-3.1.3/src/acb/dot.c000066400000000000000000000744421461254215100151140ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "mpn_extras.h" /* We need uint64_t instead of mp_limb_t on 32-bit systems for safe summation of 30-bit error bounds. */ #include /* Add ((a * b) / 2^MAG_BITS) * 2^exp into srad*2^srad_exp. Assumes that srad_exp >= exp and that overflow cannot occur. */ #define RAD_ADDMUL(srad, srad_exp, a, b, exp) \ do { \ uint64_t __a, __b; \ slong __shift; \ __a = (a); \ __b = (b); \ __shift = (srad_exp) - (exp); \ if (__shift < MAG_BITS) \ (srad) += (((__a) * (__b)) >> (MAG_BITS + __shift)) + 1; \ else \ (srad) += 1; \ } while (0) void mag_set_ui_2exp_small(mag_t z, ulong x, slong e); static void add_errors(mag_t rad, uint64_t Aerr, slong Aexp, uint64_t Berr, slong Bexp, uint64_t Cerr, slong Cexp) { slong shift; if (Aerr && Berr) { if (Aexp >= Bexp) { shift = Aexp - Bexp; if (shift < 64) Aerr = Aerr + (Berr >> shift) + 1; else Aerr = Aerr + 1; } else { shift = Bexp - Aexp; if (shift < 64) Aerr = Berr + (Aerr >> shift) + 1; else Aerr = Berr + 1; Aexp = Bexp; } } else if (Berr) { Aerr = Berr; Aexp = Bexp; } if (Aerr && Cerr) { if (Aexp >= Cexp) { shift = Aexp - Cexp; if (shift < 64) Aerr = Aerr + (Cerr >> shift) + 1; else Aerr = Aerr + 1; } else { shift = Cexp - Aexp; if (shift < 64) Aerr = Cerr + (Aerr >> shift) + 1; else Aerr = Cerr + 1; Aexp = Cexp; } } else if (Cerr) { Aerr = Cerr; Aexp = Cexp; } #if FLINT_BITS == 64 mag_set_ui_2exp_small(rad, Aerr, Aexp - MAG_BITS); #else mag_set_d(rad, Aerr * (1.0 + 1e-14)); mag_mul_2exp_si(rad, rad, Aexp - MAG_BITS); #endif } void _arb_dot_addmul_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, mp_srcptr yptr, mp_size_t yn, int negative, flint_bitcnt_t shift); void _arb_dot_add_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, int negative, flint_bitcnt_t shift); static void _arb_dot_output(arb_t res, mp_ptr sum, mp_size_t sn, int negative, uint64_t serr, slong sum_exp, uint64_t srad, slong srad_exp, slong prec) { slong exp_fix; int inexact; if (sum[sn - 1] >= LIMB_TOP) { mpn_neg(sum, sum, sn); negative ^= 1; } exp_fix = 0; if (sum[sn - 1] == 0) { slong sum_exp2; mp_size_t sn2; sn2 = sn; sum_exp2 = sum_exp; while (sn2 > 0 && sum[sn2 - 1] == 0) { sum_exp2 -= FLINT_BITS; sn2--; } if (sn2 == 0) { arf_zero(arb_midref(res)); inexact = 0; } else { inexact = _arf_set_round_mpn(arb_midref(res), &exp_fix, sum, sn2, negative, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp_fix + sum_exp2); } } else { if (sn == 2) /* unnecessary? */ inexact = _arf_set_round_uiui(arb_midref(res), &exp_fix, sum[1], sum[0], negative, prec, ARF_RND_DOWN); else inexact = _arf_set_round_mpn(arb_midref(res), &exp_fix, sum, sn, negative, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp_fix + sum_exp); } add_errors(arb_radref(res), inexact << MAG_BITS, exp_fix + sum_exp - prec, ((uint64_t) serr) << MAG_BITS, sum_exp - sn * FLINT_BITS, srad, srad_exp); } /* xxx: don't use surrounding variables */ #define ARB_DOT_ADD(s_sum, s_serr, s_sn, s_sum_exp, s_subtract, xm) \ if (!arf_is_special(xm)) \ { \ mp_srcptr xptr; \ xexp = ARF_EXP(xm); \ xn = ARF_SIZE(xm); \ xnegative = ARF_SGNBIT(xm); \ shift = s_sum_exp - xexp; \ if (shift >= s_sn * FLINT_BITS) \ { \ s_serr++; \ } \ else \ { \ xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); \ _arb_dot_add_generic(s_sum, &s_serr, tmp, s_sn, xptr, xn, xnegative ^ s_subtract, shift); \ } \ } \ /* xxx: don't use surrounding variables */ #define ARB_DOT_ADD_RAD(s_srad, s_srad_exp, xr) \ if (!mag_is_special(xr)) \ { \ xrad = MAG_MAN(xr); \ xrexp = MAG_EXP(xr); \ shift = s_srad_exp - xrexp; \ if (shift < 64) \ s_srad += (xrad >> shift) + 1; \ else \ s_srad++; \ } static void _arf_complex_mul_gauss(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d) { mp_srcptr ap, bp, cp, dp; int asgn, bsgn, csgn, dsgn; mp_size_t an, bn, cn, dn; slong aexp, bexp, cexp, dexp; fmpz texp, uexp; fmpz_t za, zb, zc, zd, t, u, v; slong abot, bbot, cbot, dbot; ARF_GET_MPN_READONLY(ap, an, a); asgn = ARF_SGNBIT(a); aexp = ARF_EXP(a); ARF_GET_MPN_READONLY(bp, bn, b); bsgn = ARF_SGNBIT(b); bexp = ARF_EXP(b); ARF_GET_MPN_READONLY(cp, cn, c); csgn = ARF_SGNBIT(c); cexp = ARF_EXP(c); ARF_GET_MPN_READONLY(dp, dn, d); dsgn = ARF_SGNBIT(d); dexp = ARF_EXP(d); /* Gauss multiplication e = ac - bd f = (a+b)(c+d) - ac - bd */ abot = aexp - an * FLINT_BITS; bbot = bexp - bn * FLINT_BITS; cbot = cexp - cn * FLINT_BITS; dbot = dexp - dn * FLINT_BITS; texp = FLINT_MIN(abot, bbot); uexp = FLINT_MIN(cbot, dbot); fmpz_init(za); fmpz_init(zb); fmpz_init(zc); fmpz_init(zd); fmpz_init(t); fmpz_init(u); fmpz_init(v); fmpz_lshift_mpn(za, ap, an, asgn, abot - texp); fmpz_lshift_mpn(zb, bp, bn, bsgn, bbot - texp); fmpz_lshift_mpn(zc, cp, cn, csgn, cbot - uexp); fmpz_lshift_mpn(zd, dp, dn, dsgn, dbot - uexp); fmpz_add(t, za, zb); fmpz_add(v, zc, zd); fmpz_mul(u, t, v); fmpz_mul(t, za, zc); fmpz_mul(v, zb, zd); fmpz_sub(u, u, t); fmpz_sub(u, u, v); fmpz_sub(t, t, v); texp += uexp; arf_set_fmpz_2exp(e, t, &texp); arf_set_fmpz_2exp(f, u, &texp); fmpz_clear(za); fmpz_clear(zb); fmpz_clear(zc); fmpz_clear(zd); fmpz_clear(t); fmpz_clear(u); fmpz_clear(v); } /* TODO: this could be much lower, but it's currently competing against mulhigh in the Karatsuba range. */ FLINT_DLL slong acb_dot_gauss_dot_cutoff = 128; #define GAUSS_CUTOFF acb_dot_gauss_dot_cutoff void acb_dot(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) { slong i, j, padding, extend; slong xexp, yexp, exp; slong re_nonzero, im_nonzero; slong re_max_exp, re_min_exp, re_sum_exp; slong im_max_exp, im_min_exp, im_sum_exp; slong re_srad_exp, re_max_rad_exp; slong im_srad_exp, im_max_rad_exp; slong re_prec, im_prec; slong xrexp, yrexp; int xnegative, ynegative; mp_size_t xn, yn, re_sn, im_sn, alloc; flint_bitcnt_t shift; arb_srcptr xi, yi; arf_srcptr xm, ym; mag_srcptr xr, yr; mp_limb_t xtop, ytop; mp_limb_t xrad, yrad; mp_limb_t re_serr, im_serr; /* Sum over arithmetic errors */ uint64_t re_srad, im_srad; /* Sum over propagated errors */ mp_ptr tmp, re_sum, im_sum; /* Workspace */ slong xoff, yoff; char * use_gauss; ARF_ADD_TMP_DECL; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) acb_zero(res); else { acb_mul(res, x, y, prec); if (subtract) acb_neg(res, res); } return; } else if (len <= 0) { acb_set_round(res, initial, prec); return; } } /* Number of nonzero midpoint terms in sum. */ re_nonzero = 0; im_nonzero = 0; /* Terms are bounded by 2^max_exp (with WORD_MIN = -infty) */ re_max_exp = WORD_MIN; im_max_exp = WORD_MIN; /* Propagated error terms are bounded by 2^max_rad_exp */ re_max_rad_exp = WORD_MIN; im_max_rad_exp = WORD_MIN; /* Used to reduce the precision. */ re_min_exp = WORD_MAX; im_min_exp = WORD_MAX; /* Account for the initial term. */ if (initial != NULL) { if (!ARB_IS_LAGOM(acb_realref(initial)) || !ARB_IS_LAGOM(acb_imagref(initial))) { acb_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(acb_realref(initial)); xr = arb_radref(acb_realref(initial)); if (!arf_is_special(xm)) { re_max_exp = ARF_EXP(xm); re_nonzero++; if (prec > 2 * FLINT_BITS) re_min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } if (!mag_is_special(xr)) re_max_rad_exp = MAG_EXP(xr); xm = arb_midref(acb_imagref(initial)); xr = arb_radref(acb_imagref(initial)); if (!arf_is_special(xm)) { im_max_exp = ARF_EXP(xm); im_nonzero++; if (prec > 2 * FLINT_BITS) im_min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } if (!mag_is_special(xr)) im_max_rad_exp = MAG_EXP(xr); } for (xoff = 0; xoff < 2; xoff++) { for (yoff = 0; yoff < 2; yoff++) { slong nonzero, max_exp, min_exp, max_rad_exp; if (xoff == yoff) { nonzero = re_nonzero; max_exp = re_max_exp; min_exp = re_min_exp; max_rad_exp = re_max_rad_exp; } else { nonzero = im_nonzero; max_exp = im_max_exp; min_exp = im_min_exp; max_rad_exp = im_max_rad_exp; } /* Determine maximum exponents for the main sum and the radius sum. */ for (i = 0; i < len; i++) { xi = ((arb_srcptr) x) + 2 * i * xstep + xoff; yi = ((arb_srcptr) y) + 2 * i * ystep + yoff; /* Fallback for huge exponents or non-finite values. */ if (!ARB_IS_LAGOM(xi) || !ARB_IS_LAGOM(yi)) { acb_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(xi); ym = arb_midref(yi); xr = arb_radref(xi); yr = arb_radref(yi); /* (xm+xr)(ym+yr) = xm ym + [xr ym + xm yr + xr yr] */ if (!arf_is_special(xm)) { xexp = ARF_EXP(xm); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_exp = FLINT_MAX(max_exp, xexp + yexp); nonzero++; if (prec > 2 * FLINT_BITS) { slong bot; bot = (xexp + yexp) - (ARF_SIZE(xm) + ARF_SIZE(ym)) * FLINT_BITS; min_exp = FLINT_MIN(min_exp, bot); } if (!mag_is_special(xr)) { xrexp = MAG_EXP(xr); max_rad_exp = FLINT_MAX(max_rad_exp, yexp + xrexp); if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xexp + yrexp); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yrexp); } } else { if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xexp + yrexp); } } } else /* if y = 0, something can happen only if yr != 0 */ { if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xexp + yrexp); if (!mag_is_special(xr)) { xrexp = MAG_EXP(xr); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yrexp); } } } } else /* if x = 0, something can happen only if xr != 0 */ { if (!mag_is_special(xr)) { xrexp = MAG_EXP(xr); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yexp); } if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yrexp); } } } } if (xoff == yoff) { re_nonzero = nonzero; re_max_exp = max_exp; re_min_exp = min_exp; re_max_rad_exp = max_rad_exp; } else { im_nonzero = nonzero; im_max_exp = max_exp; im_min_exp = min_exp; im_max_rad_exp = max_rad_exp; } } } re_prec = prec; im_prec = prec; if (re_max_exp == WORD_MIN && re_max_rad_exp == WORD_MIN && im_max_exp == WORD_MIN && im_max_rad_exp == WORD_MIN) { acb_zero(res); return; } /* The midpoint sum is zero. */ if (re_max_exp == WORD_MIN) { re_prec = 2; } else { if (re_max_rad_exp != WORD_MIN) re_prec = FLINT_MIN(re_prec, re_max_exp - re_max_rad_exp + MAG_BITS); if (re_min_exp != WORD_MAX) re_prec = FLINT_MIN(re_prec, re_max_exp - re_min_exp + MAG_BITS); re_prec = FLINT_MAX(re_prec, 2); } if (im_max_exp == WORD_MIN) { im_prec = 2; } else { if (im_max_rad_exp != WORD_MIN) im_prec = FLINT_MIN(im_prec, im_max_exp - im_max_rad_exp + MAG_BITS); if (re_min_exp != WORD_MAX) im_prec = FLINT_MIN(im_prec, im_max_exp - im_min_exp + MAG_BITS); im_prec = FLINT_MAX(im_prec, 2); } extend = FLINT_BIT_COUNT(re_nonzero) + 1; padding = 4 + FLINT_BIT_COUNT(len); re_sn = (re_prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; re_sn = FLINT_MAX(re_sn, 2); re_sum_exp = re_max_exp + extend; extend = FLINT_BIT_COUNT(im_nonzero) + 1; padding = 4 + FLINT_BIT_COUNT(len); im_sn = (im_prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; im_sn = FLINT_MAX(im_sn, 2); im_sum_exp = im_max_exp + extend; /* We need sn + 1 limb for the sum (sn limbs + 1 dummy limb for carry or borrow that avoids an extra branch). We need 2 * (sn + 2) limbs to store the product of two numbers with up to (sn + 2) limbs, plus 1 extra limb for shifting the product. */ alloc = (re_sn + 1) + (im_sn + 1) + 2 * (FLINT_MAX(re_sn, im_sn) + 2) + 1; ARF_ADD_TMP_ALLOC(re_sum, alloc) im_sum = re_sum + (re_sn + 1); tmp = im_sum + (im_sn + 1); /* Sum of propagated errors. */ re_srad_exp = re_max_rad_exp; re_srad = 0; im_srad_exp = im_max_rad_exp; im_srad = 0; /* Set sum to 0 */ re_serr = 0; for (j = 0; j < re_sn + 1; j++) re_sum[j] = 0; im_serr = 0; for (j = 0; j < im_sn + 1; j++) im_sum[j] = 0; if (initial != NULL) { xm = arb_midref(acb_realref(initial)); xr = arb_radref(acb_realref(initial)); ARB_DOT_ADD(re_sum, re_serr, re_sn, re_sum_exp, subtract, xm); ARB_DOT_ADD_RAD(re_srad, re_srad_exp, xr); xm = arb_midref(acb_imagref(initial)); xr = arb_radref(acb_imagref(initial)); ARB_DOT_ADD(im_sum, im_serr, im_sn, im_sum_exp, subtract, xm); ARB_DOT_ADD_RAD(im_srad, im_srad_exp, xr); } /* Look for terms to process using the Gauss multiplication formula. If any such terms are found, we mask the ith entry in use_gauss so that they will be skipped in the main loop. Important: the cutoffs must be such that the fast case (xn <= 2, yn <= 2, sn <= 3) is not hit below and the mask check is done. The cutoffs below are not optimal in the generic case; also, it would be nicer to have both mulhigh and Gauss here. A more elegant solution would be to write a fallback version of acb_dot_simple where acb_addmul does the right thing. */ use_gauss = NULL; if (re_prec >= GAUSS_CUTOFF * FLINT_BITS && im_prec >= GAUSS_CUTOFF * FLINT_BITS) { arf_t e, f; for (i = 0; i < len; i++) { arb_srcptr ai, bi, ci, di; mp_size_t an, bn, cn, dn; slong aexp, bexp, cexp, dexp; ai = ((arb_srcptr) x) + 2 * i * xstep; bi = ((arb_srcptr) x) + 2 * i * xstep + 1; ci = ((arb_srcptr) y) + 2 * i * ystep; di = ((arb_srcptr) y) + 2 * i * ystep + 1; an = ARF_SIZE(arb_midref(ai)); bn = ARF_SIZE(arb_midref(bi)); cn = ARF_SIZE(arb_midref(ci)); dn = ARF_SIZE(arb_midref(di)); aexp = ARF_EXP(arb_midref(ai)); bexp = ARF_EXP(arb_midref(bi)); cexp = ARF_EXP(arb_midref(ci)); dexp = ARF_EXP(arb_midref(di)); if (an >= GAUSS_CUTOFF && bn >= GAUSS_CUTOFF && bn >= GAUSS_CUTOFF && cn >= GAUSS_CUTOFF && FLINT_ABS(an - bn) <= 2 && FLINT_ABS(cn - dn) <= 2 && FLINT_ABS(aexp - bexp) <= 64 && FLINT_ABS(cexp - dexp) <= 64 && re_sum_exp - (aexp + cexp) < 0.1 * re_prec && im_sum_exp - (aexp + dexp) < 0.1 * im_prec && an + cn < 2.2 * re_sn && an + dn < 2.2 * im_sn) { if (use_gauss == NULL) { use_gauss = flint_calloc(len, sizeof(char)); arf_init(e); arf_init(f); } use_gauss[i] = 1; _arf_complex_mul_gauss(e, f, arb_midref(ai), arb_midref(bi), arb_midref(ci), arb_midref(di)); ARB_DOT_ADD(re_sum, re_serr, re_sn, re_sum_exp, 0, e); ARB_DOT_ADD(im_sum, im_serr, im_sn, im_sum_exp, 0, f); } } if (use_gauss != NULL) { arf_clear(e); arf_clear(f); } } for (xoff = 0; xoff < 2; xoff++) { for (yoff = 0; yoff < 2; yoff++) { slong sum_exp, srad_exp; mp_ptr sum; mp_size_t sn; mp_limb_t serr; uint64_t srad; int flipsign; if (xoff == yoff) { sum_exp = re_sum_exp; srad_exp = re_srad_exp; sum = re_sum; sn = re_sn; if (re_max_exp == WORD_MIN && re_max_rad_exp == WORD_MIN) continue; } else { sum_exp = im_sum_exp; srad_exp = im_srad_exp; sum = im_sum; sn = im_sn; if (im_max_exp == WORD_MIN && im_max_rad_exp == WORD_MIN) continue; } serr = 0; srad = 0; flipsign = (xoff + yoff == 2); for (i = 0; i < len; i++) { xi = ((arb_srcptr) x) + 2 * i * xstep + xoff; yi = ((arb_srcptr) y) + 2 * i * ystep + yoff; xm = arb_midref(xi); ym = arb_midref(yi); xr = arb_radref(xi); yr = arb_radref(yi); /* The midpoints of x[i] and y[i] are both nonzero. */ if (!arf_is_special(xm) && !arf_is_special(ym)) { xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); yexp = ARF_EXP(ym); yn = ARF_SIZE(ym); ynegative = ARF_SGNBIT(ym); exp = xexp + yexp; shift = sum_exp - exp; if (shift >= sn * FLINT_BITS) { /* We may yet need the top limbs for bounds. */ ARF_GET_TOP_LIMB(xtop, xm); ARF_GET_TOP_LIMB(ytop, ym); serr++; } else if (xn <= 2 && yn <= 2 && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; if (xn == 1 && yn == 1) { xtop = ARF_NOPTR_D(xm)[0]; ytop = ARF_NOPTR_D(ym)[0]; umul_ppmm(u3, u2, xtop, ytop); u1 = u0 = 0; } else if (xn == 2 && yn == 2) { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; xtop = x1; ytop = y1; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); } else if (xn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; xtop = x0; ytop = y1; FLINT_MPN_MUL_2X1(u3, u2, u1, y1, y0, x0); u0 = 0; } else { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; xtop = x1; ytop = y0; FLINT_MPN_MUL_2X1(u3, u2, u1, x1, x0, y0); u0 = 0; } if (sn == 2) { if (shift < FLINT_BITS) { serr += ((u2 << (FLINT_BITS - shift)) != 0) || (u1 != 0) || (u0 != 0); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { serr += (u2 != 0) || (u1 != 0) || (u0 != 0); u2 = u3; u3 = 0; } else /* FLINT_BITS < shift < 2 * FLINT_BITS */ { serr += ((u3 << (2 * FLINT_BITS - shift)) != 0) || (u2 != 0) || (u1 != 0) || (u0 != 0); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } if (xnegative ^ ynegative ^ flipsign) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else if (sn == 3) { if (shift < FLINT_BITS) { serr += ((u1 << (FLINT_BITS - shift)) != 0) || (u0 != 0); u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { serr += (u1 != 0) || (u0 != 0); u1 = u2; u2 = u3; u3 = 0; } else if (shift < 2 * FLINT_BITS) { serr += ((u2 << (2 * FLINT_BITS - shift)) != 0) || (u1 != 0) || (u0 != 0); u1 = (u3 << (2 * FLINT_BITS - shift)) | (u2 >> (shift - FLINT_BITS)); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } else if (shift == 2 * FLINT_BITS) { serr += (u2 != 0) || (u1 != 0) || (u0 != 0); u1 = u3; u2 = 0; u3 = 0; } else /* 2 * FLINT_BITS < shift < 3 * FLINT_BITS */ { serr += ((u3 << (3 * FLINT_BITS - shift)) != 0) || (u2 != 0) || (u1 != 0) || (u0 != 0); u1 = (u3 >> (shift - 2 * FLINT_BITS)); u2 = 0; u3 = 0; } if (xnegative ^ ynegative ^ flipsign) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } else { mp_srcptr xptr, yptr; xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); yptr = (yn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(ym) : ARF_PTR_D(ym); xtop = xptr[xn - 1]; ytop = yptr[yn - 1]; if (use_gauss == NULL || use_gauss[i] == 0) _arb_dot_addmul_generic(sum, &serr, tmp, sn, xptr, xn, yptr, yn, xnegative ^ ynegative ^ flipsign, shift); } xrad = MAG_MAN(xr); yrad = MAG_MAN(yr); if (xrad != 0 && yrad != 0) { xrexp = MAG_EXP(xr); yrexp = MAG_EXP(yr); RAD_ADDMUL(srad, srad_exp, (xtop >> (FLINT_BITS - MAG_BITS)) + 1, yrad, xexp + yrexp); RAD_ADDMUL(srad, srad_exp, (ytop >> (FLINT_BITS - MAG_BITS)) + 1, xrad, yexp + xrexp); RAD_ADDMUL(srad, srad_exp, xrad, yrad, xrexp + yrexp); } else if (xrad != 0) { xrexp = MAG_EXP(xr); RAD_ADDMUL(srad, srad_exp, (ytop >> (FLINT_BITS - MAG_BITS)) + 1, xrad, yexp + xrexp); } else if (yrad != 0) { yrexp = MAG_EXP(yr); RAD_ADDMUL(srad, srad_exp, (xtop >> (FLINT_BITS - MAG_BITS)) + 1, yrad, xexp + yrexp); } } else { xrad = MAG_MAN(xr); yrad = MAG_MAN(yr); xexp = ARF_EXP(xm); yexp = ARF_EXP(ym); xrexp = MAG_EXP(xr); yrexp = MAG_EXP(yr); /* (xm+xr)(ym+yr) = xm ym + [xm yr + ym xr + xr yr] */ if (yrad && !arf_is_special(xm)) { ARF_GET_TOP_LIMB(xtop, xm); RAD_ADDMUL(srad, srad_exp, (xtop >> (FLINT_BITS - MAG_BITS)) + 1, yrad, xexp + yrexp); } if (xrad && !arf_is_special(ym)) { ARF_GET_TOP_LIMB(ytop, ym); RAD_ADDMUL(srad, srad_exp, (ytop >> (FLINT_BITS - MAG_BITS)) + 1, xrad, yexp + xrexp); } if (xrad && yrad) { RAD_ADDMUL(srad, srad_exp, xrad, yrad, xrexp + yrexp); } } } if (xoff == yoff) { re_serr += serr; re_srad += srad; } else { im_serr += serr; im_srad += srad; } } } _arb_dot_output(acb_realref(res), re_sum, re_sn, subtract, re_serr, re_sum_exp, re_srad, re_srad_exp, re_prec); _arb_dot_output(acb_imagref(res), im_sum, im_sn, subtract, im_serr, im_sum_exp, im_srad, im_srad_exp, im_prec); ARF_ADD_TMP_FREE(re_sum, alloc); if (use_gauss != NULL) flint_free(use_gauss); } flint-3.1.3/src/acb/dot_fmpz.c000066400000000000000000000100311461254215100161300ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_dot_fmpz(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const fmpz * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i, ssize, size, tmp_size; mp_ptr ztmp; fmpz v; ulong av, al; unsigned int bc; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) acb_zero(res); else { acb_mul_fmpz(res, x, y, prec); if (subtract) acb_neg(res, res); } return; } else if (len <= 0) { acb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); tmp_size = 0; for (i = 0; i < len; i++) { v = y[i * ystep]; MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; if (v == 0) { ARF_XSIZE(arb_midref(t + i)) = 0; ARF_EXP(arb_midref(t + i)) = ARF_EXP_ZERO; } else if (!COEFF_IS_MPZ(v)) { av = FLINT_ABS(v); bc = flint_clz(av); ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = av << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, v < 0); } else { __mpz_struct * z = COEFF_TO_PTR(v); ssize = z->_mp_size; size = FLINT_ABS(ssize); av = z->_mp_d[size - 1]; bc = flint_clz(av); if (size == 1) { ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = av << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, ssize < 0); } else if (size == 2) { al = z->_mp_d[0]; ARF_EXP(arb_midref(t + i)) = 2 * FLINT_BITS - bc; if (bc != 0) { av = (av << bc) | (al >> (FLINT_BITS - bc)); al = al << bc; } ARF_NOPTR_D(arb_midref(t + i))[0] = al; ARF_NOPTR_D(arb_midref(t + i))[1] = av; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(2, ssize < 0); } else { if (bc != 0) { tmp_size += size; /* use to flag tmp where we need tmp storage */ MAG_MAN(arb_radref(t + i)) = bc; } ARF_EXP(arb_midref(t + i)) = size * FLINT_BITS - bc; ARF_PTR_D(arb_midref(t + i)) = z->_mp_d; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(size, ssize < 0); } } } if (tmp_size != 0) { ztmp = TMP_ALLOC(sizeof(mp_limb_t) * tmp_size); for (i = 0; i < len; i++) { bc = MAG_MAN(arb_radref(t + i)); if (bc != 0) { size = ARF_SIZE(arb_midref(t + i)); mpn_lshift(ztmp, ARF_PTR_D(arb_midref(t + i)), size, bc); ARF_PTR_D(arb_midref(t + i)) = ztmp; ztmp += size; } MAG_MAN(arb_radref(t + i)) = 0; } } arb_dot(((arb_ptr) res) + 0, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 0, subtract, ((arb_srcptr) x) + 0, 2 * xstep, t, 1, len, prec); arb_dot(((arb_ptr) res) + 1, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 1, subtract, ((arb_srcptr) x) + 1, 2 * xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/acb/dot_precise.c000066400000000000000000000031021461254215100166070ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_dot_precise(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) { arb_ptr tmp; slong i; tmp = flint_malloc(sizeof(arb_struct) * (4 * len)); for (i = 0; i < len; i++) { tmp[0 * len + i] = *acb_realref(x + i * xstep); tmp[1 * len + i] = *acb_imagref(x + i * xstep); tmp[2 * len + i] = *acb_realref(y + i * ystep); arb_init(tmp + 3 * len + i); arb_neg(tmp + 3 * len + i, acb_imagref(y + i * ystep)); } arb_dot_precise(acb_realref(res), initial == NULL ? NULL : acb_realref(initial), subtract, tmp, 1, tmp + 2 * len, 1, 2 * len, prec); for (i = 0; i < len; i++) arb_clear(tmp + 3 * len + i); for (i = 0; i < len; i++) { tmp[0 * len + i] = *acb_realref(x + i * xstep); tmp[1 * len + i] = *acb_imagref(x + i * xstep); tmp[2 * len + i] = *acb_imagref(y + i * ystep); tmp[3 * len + i] = *acb_realref(y + i * ystep); } arb_dot_precise(acb_imagref(res), initial == NULL ? NULL : acb_imagref(initial), subtract, tmp, 1, tmp + 2 * len, 1, 2 * len, prec); flint_free(tmp); } flint-3.1.3/src/acb/dot_si.c000066400000000000000000000040211461254215100155710ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_dot_si(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const slong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; slong v; ulong av; unsigned int bc; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) acb_zero(res); else { acb_mul_si(res, x, y[0], prec); if (subtract) acb_neg(res, res); } return; } else if (len <= 0) { acb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { v = y[i * ystep]; if (v == 0) { ARF_XSIZE(arb_midref(t + i)) = 0; ARF_EXP(arb_midref(t + i)) = ARF_EXP_ZERO; } else { av = FLINT_ABS(v); bc = flint_clz(av); ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = av << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, v < 0); } MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(((arb_ptr) res) + 0, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 0, subtract, ((arb_srcptr) x) + 0, 2 * xstep, t, 1, len, prec); arb_dot(((arb_ptr) res) + 1, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 1, subtract, ((arb_srcptr) x) + 1, 2 * xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/acb/dot_simple.c000066400000000000000000000021151461254215100164510ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_dot_simple(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) { slong i; if (len <= 0) { if (initial == NULL) acb_zero(res); else acb_set_round(res, initial, prec); return; } if (initial == NULL) { acb_mul(res, x, y, prec); } else { if (subtract) acb_neg(res, initial); else acb_set(res, initial); acb_addmul(res, x, y, prec); } for (i = 1; i < len; i++) acb_addmul(res, x + i * xstep, y + i * ystep, prec); if (subtract) acb_neg(res, res); } flint-3.1.3/src/acb/dot_siui.c000066400000000000000000000057141461254215100161410ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" static void arf_shallow_set_siui(arf_t res, ulong vhi, ulong vlo) { int negative; unsigned int bc; negative = ((slong) vhi) < 0; if (negative) { vhi = -vhi - (vlo != 0); vlo = -vlo; } if (vhi == 0) { if (vlo == 0) { ARF_XSIZE(res) = 0; ARF_EXP(res) = ARF_EXP_ZERO; } else { bc = flint_clz(vlo); ARF_EXP(res) = FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, negative); } } else if (vlo == 0) { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vhi << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, negative); } else { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; if (bc == 0) ARF_NOPTR_D(res)[1] = vhi; else ARF_NOPTR_D(res)[1] = (vhi << bc) | (vlo >> (FLINT_BITS - bc)); ARF_XSIZE(res) = ARF_MAKE_XSIZE(2, negative); } } void acb_dot_siui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; ulong vhi, vlo; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) acb_zero(res); else { arf_t t; arf_shallow_set_siui(t, y[1], y[0]); arb_mul_arf(acb_realref(res), acb_realref(x), t, prec); arb_mul_arf(acb_imagref(res), acb_imagref(x), t, prec); if (subtract) acb_neg(res, res); } return; } else if (len <= 0) { acb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { vlo = y[2 * i * ystep]; vhi = y[2 * i * ystep + 1]; arf_shallow_set_siui(arb_midref(t + i), vhi, vlo); MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(((arb_ptr) res) + 0, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 0, subtract, ((arb_srcptr) x) + 0, 2 * xstep, t, 1, len, prec); arb_dot(((arb_ptr) res) + 1, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 1, subtract, ((arb_srcptr) x) + 1, 2 * xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/acb/dot_ui.c000066400000000000000000000037361461254215100156070ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_dot_ui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; ulong v; unsigned int bc; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) acb_zero(res); else { acb_mul_ui(res, x, y[0], prec); if (subtract) acb_neg(res, res); } return; } else if (len <= 0) { acb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { v = y[i * ystep]; if (v == 0) { ARF_XSIZE(arb_midref(t + i)) = 0; ARF_EXP(arb_midref(t + i)) = ARF_EXP_ZERO; } else { bc = flint_clz(v); ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = v << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, 0); } MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(((arb_ptr) res) + 0, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 0, subtract, ((arb_srcptr) x) + 0, 2 * xstep, t, 1, len, prec); arb_dot(((arb_ptr) res) + 1, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 1, subtract, ((arb_srcptr) x) + 1, 2 * xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/acb/dot_uiui.c000066400000000000000000000054561461254215100161460ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" static void arf_shallow_set_uiui(arf_t res, ulong vhi, ulong vlo) { unsigned int bc; if (vhi == 0) { if (vlo == 0) { ARF_XSIZE(res) = 0; ARF_EXP(res) = ARF_EXP_ZERO; } else { bc = flint_clz(vlo); ARF_EXP(res) = FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, 0); } } else if (vlo == 0) { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vhi << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, 0); } else { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; if (bc == 0) ARF_NOPTR_D(res)[1] = vhi; else ARF_NOPTR_D(res)[1] = (vhi << bc) | (vlo >> (FLINT_BITS - bc)); ARF_XSIZE(res) = ARF_MAKE_XSIZE(2, 0); } } void acb_dot_uiui(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; ulong vhi, vlo; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) acb_zero(res); else { arf_t t; arf_shallow_set_uiui(t, y[1], y[0]); arb_mul_arf(acb_realref(res), acb_realref(x), t, prec); arb_mul_arf(acb_imagref(res), acb_imagref(x), t, prec); if (subtract) acb_neg(res, res); } return; } else if (len <= 0) { acb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { vlo = y[2 * i * ystep]; vhi = y[2 * i * ystep + 1]; arf_shallow_set_uiui(arb_midref(t + i), vhi, vlo); MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(((arb_ptr) res) + 0, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 0, subtract, ((arb_srcptr) x) + 0, 2 * xstep, t, 1, len, prec); arb_dot(((arb_ptr) res) + 1, (initial == NULL) ? NULL : ((arb_srcptr) initial) + 1, subtract, ((arb_srcptr) x) + 1, 2 * xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/acb/exp.c000066400000000000000000000020551461254215100151110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_exp(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_exp(acb_realref(r), a, prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(a)) { arb_sin_cos(acb_imagref(r), acb_realref(r), b, prec); } else { arb_t t, u, v; arb_init(t); arb_init(u); arb_init(v); arb_exp(t, a, prec); arb_sin_cos(u, v, b, prec); arb_mul(acb_realref(r), t, v, prec); arb_mul(acb_imagref(r), t, u, prec); arb_clear(t); arb_clear(u); arb_clear(v); } #undef a #undef b } flint-3.1.3/src/acb/exp_invexp.c000066400000000000000000000025221461254215100165010ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_exp_invexp(acb_t r, acb_t s, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_exp_invexp(acb_realref(r), acb_realref(s), a, prec); arb_zero(acb_imagref(r)); arb_zero(acb_imagref(s)); } else if (arb_is_zero(a)) { arb_sin_cos(acb_imagref(r), acb_realref(r), b, prec); acb_conj(s, r); } else { arb_t t, u, v, w; arb_init(t); arb_init(u); arb_init(v); arb_init(w); arb_exp_invexp(t, u, a, prec); arb_sin_cos(v, w, b, prec); arb_mul(acb_realref(r), t, w, prec); arb_mul(acb_imagref(r), t, v, prec); arb_mul(acb_realref(s), u, w, prec); arb_mul(acb_imagref(s), u, v, prec); arb_neg(acb_imagref(s), acb_imagref(s)); arb_clear(t); arb_clear(u); arb_clear(v); arb_clear(w); } #undef a #undef b } flint-3.1.3/src/acb/exp_pi_i.c000066400000000000000000000024631461254215100161140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_exp_pi_i(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_sin_cos_pi(acb_imagref(r), acb_realref(r), a, prec); } else if (arb_is_zero(a)) { arb_const_pi(acb_realref(r), prec); arb_mul(acb_realref(r), acb_realref(r), b, prec); arb_neg(acb_realref(r), acb_realref(r)); arb_exp(acb_realref(r), acb_realref(r), prec); arb_zero(acb_imagref(r)); } else { arb_t t, u, v; arb_init(t); arb_init(u); arb_init(v); arb_const_pi(t, prec); arb_mul(t, t, b, prec); arb_neg(t, t); arb_exp(t, t, prec); arb_sin_cos_pi(u, v, a, prec); arb_mul(acb_realref(r), t, v, prec); arb_mul(acb_imagref(r), t, u, prec); arb_clear(t); arb_clear(u); arb_clear(v); } #undef a #undef b } flint-3.1.3/src/acb/expm1.c000066400000000000000000000040451461254215100153500ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_expm1(acb_t res, const acb_t z, slong prec) { if (acb_is_real(z)) { arb_expm1(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } else if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -3) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -3) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -3) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -3) <= 0) { arf_srcptr midmax; slong extra; if (arf_cmpabs(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z))) >= 0) midmax = arb_midref(acb_realref(z)); else midmax = arb_midref(acb_imagref(z)); if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -prec - 100) > 0) { extra = -ARF_EXP(midmax); extra = FLINT_MIN(extra, prec + 100); extra = FLINT_MAX(extra, 0); acb_exp(res, z, prec + extra + 4); acb_sub_ui(res, res, 1, prec); } else { /* lazy solution: e^z-1 = 4 (sinh(z/4)+cosh(z/4))^2 sinh(z/4) cosh(z/4) */ acb_t t, u; acb_init(t); acb_init(u); acb_mul_2exp_si(t, z, -2); acb_sinh_cosh(t, u, t, prec + 4); acb_add(res, t, u, prec + 4); acb_mul(res, res, res, prec + 4); acb_mul(t, t, u, prec + 4); acb_mul(res, res, t, prec); acb_mul_2exp_si(res, res, 2); acb_clear(t); acb_clear(u); } } else { acb_exp(res, z, prec + 4); acb_sub_ui(res, res, 1, prec); } } flint-3.1.3/src/acb/gamma.c000066400000000000000000000064341461254215100154040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bernoulli.h" #include "acb.h" #include "acb_hypgeom.h" void acb_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t z, int use_reflect, int digamma, slong prec); void acb_gamma_stirling_bound(mag_ptr err, const acb_t z, slong k0, slong knum, slong n); void arb_gamma_stirling_coeff(arb_t b, ulong k, int digamma, slong prec); void acb_gamma_stirling_eval(acb_t s, const acb_t z, slong nterms, int digamma, slong prec) { acb_t t, logz, zinv, zinv2; arb_t b; mag_t err; slong k, term_prec; double z_mag, term_mag; acb_init(t); acb_init(logz); acb_init(zinv); acb_init(zinv2); arb_init(b); acb_log(logz, z, prec); acb_inv(zinv, z, prec); nterms = FLINT_MAX(nterms, 1); acb_zero(s); if (nterms > 1) { acb_mul(zinv2, zinv, zinv, prec); z_mag = arf_get_d(arb_midref(acb_realref(logz)), ARF_RND_UP) * 1.44269504088896; for (k = nterms - 1; k >= 1; k--) { term_mag = bernoulli_bound_2exp_si(2 * k); term_mag -= (2 * k - 1) * z_mag; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); arb_gamma_stirling_coeff(b, k, digamma, term_prec); if (prec > 2000) { acb_set_round(t, zinv2, term_prec); acb_mul(s, s, t, term_prec); } else acb_mul(s, s, zinv2, term_prec); arb_add(acb_realref(s), acb_realref(s), b, term_prec); } if (digamma) acb_mul(s, s, zinv2, prec); else acb_mul(s, s, zinv, prec); } /* remainder bound */ mag_init(err); acb_gamma_stirling_bound(err, z, digamma ? 1 : 0, 1, nterms); mag_add(arb_radref(acb_realref(s)), arb_radref(acb_realref(s)), err); mag_add(arb_radref(acb_imagref(s)), arb_radref(acb_imagref(s)), err); mag_clear(err); if (digamma) { acb_neg(s, s); acb_mul_2exp_si(zinv, zinv, -1); acb_sub(s, s, zinv, prec); acb_add(s, s, logz, prec); } else { /* (z-0.5)*log(z) - z + log(2*pi)/2 */ arb_one(b); arb_mul_2exp_si(b, b, -1); arb_set(acb_imagref(t), acb_imagref(z)); arb_sub(acb_realref(t), acb_realref(z), b, prec); acb_mul(t, logz, t, prec); acb_add(s, s, t, prec); acb_sub(s, s, z, prec); arb_const_log_sqrt2pi(b, prec); arb_add(acb_realref(s), acb_realref(s), b, prec); } acb_clear(t); acb_clear(logz); acb_clear(zinv); acb_clear(zinv2); arb_clear(b); } void acb_gamma(acb_t y, const acb_t x, slong prec) { acb_hypgeom_gamma(y, x, prec); } void acb_rgamma(acb_t y, const acb_t x, slong prec) { acb_hypgeom_rgamma(y, x, prec); } void acb_lgamma(acb_t y, const acb_t x, slong prec) { acb_hypgeom_lgamma(y, x, prec); } flint-3.1.3/src/acb/get_abs_lbound_arf.c000066400000000000000000000020521461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_get_abs_lbound_arf(arf_t u, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_get_abs_lbound_arf(u, acb_realref(z), prec); } else if (arb_is_zero(acb_realref(z))) { arb_get_abs_lbound_arf(u, acb_imagref(z), prec); } else { arf_t v; arf_init(v); arb_get_abs_lbound_arf(u, acb_realref(z), prec); arb_get_abs_lbound_arf(v, acb_imagref(z), prec); arf_mul(u, u, u, prec, ARF_RND_DOWN); arf_mul(v, v, v, prec, ARF_RND_DOWN); arf_add(u, u, v, prec, ARF_RND_DOWN); arf_sqrt(u, u, prec, ARF_RND_DOWN); arf_clear(v); } } flint-3.1.3/src/acb/get_abs_ubound_arf.c000066400000000000000000000020421461254215100201210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_get_abs_ubound_arf(arf_t u, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_get_abs_ubound_arf(u, acb_realref(z), prec); } else if (arb_is_zero(acb_realref(z))) { arb_get_abs_ubound_arf(u, acb_imagref(z), prec); } else { arf_t v; arf_init(v); arb_get_abs_ubound_arf(u, acb_realref(z), prec); arb_get_abs_ubound_arf(v, acb_imagref(z), prec); arf_mul(u, u, u, prec, ARF_RND_UP); arf_mul(v, v, v, prec, ARF_RND_UP); arf_add(u, u, v, prec, ARF_RND_UP); arf_sqrt(u, u, prec, ARF_RND_UP); arf_clear(v); } } flint-3.1.3/src/acb/get_mag.c000066400000000000000000000015501461254215100157170ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_get_mag(mag_t u, const acb_t z) { if (arb_is_zero(acb_imagref(z))) { arb_get_mag(u, acb_realref(z)); } else if (arb_is_zero(acb_realref(z))) { arb_get_mag(u, acb_imagref(z)); } else { mag_t v; mag_init(v); arb_get_mag(u, acb_realref(z)); arb_get_mag(v, acb_imagref(z)); mag_mul(u, u, u); mag_addmul(u, v, v); mag_sqrt(u, u); mag_clear(v); } } flint-3.1.3/src/acb/get_mag_lower.c000066400000000000000000000016651461254215100171360ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_get_mag_lower(mag_t z, const acb_t x) { if (arb_is_zero(acb_imagref(x))) { arb_get_mag_lower(z, acb_realref(x)); } else if (arb_is_zero(acb_realref(x))) { arb_get_mag_lower(z, acb_imagref(x)); } else { mag_t t; mag_init(t); arb_get_mag_lower(t, acb_realref(x)); arb_get_mag_lower(z, acb_imagref(x)); mag_mul_lower(t, t, t); mag_mul_lower(z, z, z); mag_add_lower(z, z, t); mag_sqrt_lower(z, z); mag_clear(t); } } flint-3.1.3/src/acb/get_rad_ubound_arf.c000066400000000000000000000013371461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_get_rad_ubound_arf(arf_t u, const acb_t z, slong prec) { /* fixme: this bound is very sloppy */ if (mag_cmp(arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))) >= 0) arf_set_mag(u, arb_radref(acb_realref(z))); else arf_set_mag(u, arb_radref(acb_imagref(z))); arf_mul_2exp_si(u, u, 1); } flint-3.1.3/src/acb/get_unique_fmpz.c000066400000000000000000000010701461254215100175120ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" int acb_get_unique_fmpz(fmpz_t z, const acb_t x) { if (!arb_contains_zero(acb_imagref(x))) return 0; return arb_get_unique_fmpz(z, acb_realref(x)); } flint-3.1.3/src/acb/inlines.c000066400000000000000000000006461461254215100157620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ACB_INLINES_C #include "acb.h" flint-3.1.3/src/acb/inv.c000066400000000000000000000125041461254215100151110ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" static void _arb_arf_div_rounded_den(arb_t res, const arf_t x, const arf_t y, int yinexact, slong prec) { int inexact = arf_div(arb_midref(res), x, y, prec, ARB_RND); if (yinexact && !arf_is_special(arb_midref(res))) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec - 1); else if (inexact) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec); else mag_zero(arb_radref(res)); } static void _arb_arf_div_rounded_den_add_err(arb_t res, const arf_t x, const arf_t y, int yinexact, slong prec) { int inexact = arf_div(arb_midref(res), x, y, prec, ARB_RND); if (yinexact && !arf_is_special(arb_midref(res))) arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec - 1); else if (inexact) arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec); } void acb_inv(acb_t res, const acb_t z, slong prec) { mag_t am, bm; slong hprec; #define a arb_midref(acb_realref(z)) #define b arb_midref(acb_imagref(z)) #define x arb_radref(acb_realref(z)) #define y arb_radref(acb_imagref(z)) /* choose precision for the floating-point approximation of a^2+b^2 so that the double rounding result in less than 2 ulp error; also use at least MAG_BITS bits since the value will be recycled for error bounds */ hprec = FLINT_MAX(prec + 3, MAG_BITS); if (arb_is_zero(acb_imagref(z))) { arb_inv(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); return; } if (arb_is_zero(acb_realref(z))) { arb_inv(acb_imagref(res), acb_imagref(z), prec); arb_neg(acb_imagref(res), acb_imagref(res)); arb_zero(acb_realref(res)); return; } if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (mag_is_zero(x) && mag_is_zero(y)) { int inexact; arf_t a2b2; arf_init(a2b2); inexact = arf_sosq(a2b2, a, b, hprec, ARF_RND_DOWN); if (arf_is_special(a2b2)) { acb_indeterminate(res); } else { _arb_arf_div_rounded_den(acb_realref(res), a, a2b2, inexact, prec); _arb_arf_div_rounded_den(acb_imagref(res), b, a2b2, inexact, prec); arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(res))); } arf_clear(a2b2); return; } mag_init(am); mag_init(bm); /* first bound |a|-x, |b|-y */ arb_get_mag_lower(am, acb_realref(z)); arb_get_mag_lower(bm, acb_imagref(z)); if ((mag_is_zero(am) && mag_is_zero(bm))) { acb_indeterminate(res); } else { /* The propagated error in the real part is given exactly by (a+x')/((a+x')^2+(b+y'))^2 - a/(a^2+b^2) = P / Q, P = [(b^2-a^2) x' - a (x'^2+y'^2 + 2y'b)] Q = [(a^2+b^2)((a+x')^2+(b+y')^2)] where |x'| <= x and |y'| <= y, and analogously for the imaginary part. */ mag_t t, u, v, w; arf_t a2b2; int inexact; mag_init(t); mag_init(u); mag_init(v); mag_init(w); arf_init(a2b2); inexact = arf_sosq(a2b2, a, b, hprec, ARF_RND_DOWN); /* compute denominator */ /* t = (|a|-x)^2 + (|b|-x)^2 (lower bound) */ mag_mul_lower(t, am, am); mag_mul_lower(u, bm, bm); mag_add_lower(t, t, u); /* u = a^2 + b^2 (lower bound) */ arf_get_mag_lower(u, a2b2); /* t = ((|a|-x)^2 + (|b|-x)^2)(a^2 + b^2) (lower bound) */ mag_mul_lower(t, t, u); /* compute numerator */ /* real: |a^2-b^2| x + |a| ((x^2 + y^2) + 2 |b| y)) */ /* imag: |a^2-b^2| y + |b| ((x^2 + y^2) + 2 |a| x)) */ /* am, bm = upper bounds for a, b */ arf_get_mag(am, a); arf_get_mag(bm, b); /* v = x^2 + y^2 */ mag_mul(v, x, x); mag_addmul(v, y, y); /* u = |a| ((x^2 + y^2) + 2 |b| y) */ mag_mul_2exp_si(u, bm, 1); mag_mul(u, u, y); mag_add(u, u, v); mag_mul(u, u, am); /* v = |b| ((x^2 + y^2) + 2 |a| x) */ mag_mul_2exp_si(w, am, 1); mag_addmul(v, w, x); mag_mul(v, v, bm); /* w = |b^2 - a^2| (upper bound) */ if (arf_cmpabs(a, b) >= 0) mag_mul(w, am, am); else mag_mul(w, bm, bm); mag_addmul(u, w, x); mag_addmul(v, w, y); mag_div(arb_radref(acb_realref(res)), u, t); mag_div(arb_radref(acb_imagref(res)), v, t); _arb_arf_div_rounded_den_add_err(acb_realref(res), a, a2b2, inexact, prec); _arb_arf_div_rounded_den_add_err(acb_imagref(res), b, a2b2, inexact, prec); arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(res))); mag_clear(t); mag_clear(u); mag_clear(v); mag_clear(w); arf_clear(a2b2); } mag_clear(am); mag_clear(bm); #undef a #undef b #undef x #undef y } flint-3.1.3/src/acb/io.c000066400000000000000000000061671461254215100147340ustar00rootroot00000000000000/* Copyright (C) 2012, 2015 Fredrik Johansson Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb.h" /* printing *******************************************************************/ void acb_fprint(FILE * file, const acb_t x) { flint_fprintf(file, "("); arb_fprint(file, acb_realref(x)); flint_fprintf(file, ", "); arb_fprint(file, acb_imagref(x)); flint_fprintf(file, ")"); } void acb_fprintd(FILE * file, const acb_t z, slong digits) { flint_fprintf(file, "("); arf_fprintd(file, arb_midref(acb_realref(z)), digits); if (arf_sgn(arb_midref(acb_imagref(z))) < 0) { arf_t t; arf_init_neg_shallow(t, arb_midref(acb_imagref(z))); flint_fprintf(file, " - "); arf_fprintd(file, t, digits); } else { flint_fprintf(file, " + "); arf_fprintd(file, arb_midref(acb_imagref(z)), digits); } flint_fprintf(file, "j)"); flint_fprintf(file, " +/- "); flint_fprintf(file, "("); mag_fprintd(file, arb_radref(acb_realref(z)), 3); flint_fprintf(file, ", "); mag_fprintd(file, arb_radref(acb_imagref(z)), 3); flint_fprintf(file, "j)"); } void acb_fprintn(FILE * file, const acb_t z, slong digits, ulong flags) { if (arb_is_zero(acb_imagref(z))) { arb_fprintn(file, acb_realref(z), digits, flags); } else if (arb_is_zero(acb_realref(z))) { arb_fprintn(file, acb_imagref(z), digits, flags); flint_fprintf(file, "*I"); } else { arb_fprintn(file, acb_realref(z), digits, flags); if ((arb_is_exact(acb_imagref(z)) || (flags & ARB_STR_NO_RADIUS)) && arf_sgn(arb_midref(acb_imagref(z))) < 0) { arb_t t; arb_init(t); arb_neg(t, acb_imagref(z)); flint_fprintf(file, " - "); arb_fprintn(file, t, digits, flags); arb_clear(t); } else { flint_fprintf(file, " + "); arb_fprintn(file, acb_imagref(z), digits, flags); } flint_fprintf(file, "*I"); } } void acb_print(const acb_t x) { acb_fprint(stdout, x); } void acb_printd(const acb_t z, slong digits) { acb_fprintd(stdout, z, digits); } void acb_printn(const acb_t x, slong digits, ulong flags) { acb_fprintn(stdout, x, digits, flags); } void _acb_vec_printn(acb_srcptr vec, slong len, slong ndigits, ulong flags) { slong i; for (i = 0; i < len; i++) { acb_printn(vec + i, ndigits, flags); if (i < len - 1) flint_printf(", "); } } void _acb_vec_printd(acb_srcptr vec, slong len, slong ndigits) { slong i; for (i = 0; i < len; i++) { acb_printd(vec + i, ndigits); if (i < len - 1) { flint_printf(", "); } } flint_printf("\n"); } flint-3.1.3/src/acb/lambertw.c000066400000000000000000000536171461254215100161440ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #ifdef __GNUC__ # define atan2 __builtin_atan2 # define cos __builtin_cos # define fabs __builtin_fabs # define log __builtin_log # define pow __builtin_pow # define sin __builtin_sin #else # include #endif /* Check if z crosses a branch cut. */ int acb_lambertw_branch_crossing(const acb_t z, const acb_t ez1, const fmpz_t k) { if (arb_contains_zero(acb_imagref(z)) && !arb_is_nonnegative(acb_imagref(z))) { if (fmpz_is_zero(k)) { if (!arb_is_positive(acb_realref(ez1))) { return 1; } } else if (!arb_is_positive(acb_realref(z))) { return 1; } } return 0; } /* todo: remove radii */ void acb_lambertw_halley_step(acb_t res, acb_t ew, const acb_t z, const acb_t w, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_exp(ew, w, prec); acb_add_ui(u, w, 2, prec); acb_add_ui(v, w, 1, prec); acb_mul_2exp_si(v, v, 1); acb_div(v, u, v, prec); acb_mul(t, ew, w, prec); acb_sub(u, t, z, prec); acb_mul(v, v, u, prec); acb_neg(v, v); acb_add(v, v, t, prec); acb_add(v, v, ew, prec); acb_div(t, u, v, prec); acb_sub(t, w, t, prec); acb_swap(res, t); acb_clear(t); acb_clear(u); acb_clear(v); } /* assumes no aliasing of w and p */ void acb_lambertw_branchpoint_series(acb_t w, const acb_t t, int bound, slong prec) { slong i; static const int coeffs[] = {-130636800,130636800,-43545600,19958400, -10402560,5813640,-3394560,2042589,-1256320}; acb_zero(w); for (i = 8; i >= 0; i--) { acb_mul(w, w, t, prec); acb_add_si(w, w, coeffs[i], prec); } acb_div_si(w, w, -coeffs[0], prec); if (bound) { mag_t err; mag_init(err); acb_get_mag(err, t); mag_geom_series(err, err, 9); if (acb_is_real(t)) arb_add_error_mag(acb_realref(w), err); else acb_add_error_mag(w, err); mag_clear(err); } } void acb_lambertw_principal_d(acb_t res, const acb_t z) { double za, zb, wa, wb, ewa, ewb, t, u, q, r; int k, maxk = 15; za = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); zb = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); /* make sure we end up on the right branch */ if (za < -0.367 && zb > -1e-20 && zb <= 0.0 && arf_sgn(arb_midref(acb_imagref(z))) < 0) zb = -1e-20; wa = za; wb = zb; if (fabs(wa) > 2.0 || fabs(wb) > 2.0) { t = atan2(wb, wa); wa = 0.5 * log(wa * wa + wb * wb); wb = t; } else if (fabs(wa) > 0.25 || fabs(wb) > 0.25) { /* We have W(z) ~= -1 + (2(ez+1))^(1/2) near the branch point. Changing the exponent to 1/4 gives a much worse local guess which however does the job on a larger domain. */ wa *= 5.43656365691809; wb *= 5.43656365691809; wa += 2.0; t = atan2(wb, wa); r = pow(wa * wa + wb * wb, 0.125); wa = r * cos(0.25 * t); wb = r * sin(0.25 * t); wa -= 1.0; } for (k = 0; k < maxk; k++) { #if __GNUC__ t = __builtin_exp(wa); #else t = exp(wa); #endif ewa = t * cos(wb); ewb = t * sin(wb); t = (ewa * wa - ewb * wb); q = t + ewa; t -= za; u = (ewb * wa + ewa * wb); r = u + ewb; u -= zb; ewa = q * t + r * u; ewb = q * u - r * t; r = 1.0 / (q * q + r * r); ewa *= r; ewb *= r; if ((ewa*ewa + ewb*ewb) < (wa*wa + wb*wb) * 1e-12) maxk = FLINT_MIN(maxk, k + 2); wa -= ewa; wb -= ewb; } acb_set_d_d(res, wa, wb); } void acb_lambertw_initial_asymp(acb_t w, const acb_t z, const fmpz_t k, slong prec) { acb_t L1, L2, t; acb_init(L1); acb_init(L2); acb_init(t); acb_const_pi(L2, prec); acb_mul_2exp_si(L2, L2, 1); acb_mul_fmpz(L2, L2, k, prec); acb_mul_onei(L2, L2); acb_log(L1, z, prec); acb_add(L1, L1, L2, prec); acb_log(L2, L1, prec); /* L1 - L2 + L2/L1 + L2(L2-2)/(2 L1^2) */ acb_inv(t, L1, prec); acb_mul_2exp_si(w, L2, 1); acb_submul(w, L2, L2, prec); acb_neg(w, w); acb_mul(w, w, t, prec); acb_mul_2exp_si(w, w, -1); acb_add(w, w, L2, prec); acb_mul(w, w, t, prec); acb_sub(w, w, L2, prec); acb_add(w, w, L1, prec); acb_clear(L1); acb_clear(L2); acb_clear(t); } /* assumes no aliasing */ slong acb_lambertw_initial(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, slong prec) { /* Handle z very close to 0 on the principal branch. */ if (fmpz_is_zero(k) && (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -20) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -20) <= 0)) { acb_set(res, z); acb_submul(res, res, res, prec); return 40; /* could be tightened... */ } /* For moderate input not close to the branch point, compute a double approximation as the initial value. */ if (fmpz_is_zero(k) && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 400) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 400) < 0 && (arf_cmp_d(arb_midref(acb_realref(z)), -0.37) < 0 || arf_cmp_d(arb_midref(acb_realref(z)), -0.36) > 0 || arf_cmpabs_d(arb_midref(acb_imagref(z)), 0.01) > 0)) { acb_lambertw_principal_d(res, z); return 48; } /* Check if we are close to the branch point at -1/e. */ if ((fmpz_is_zero(k) || (fmpz_is_one(k) && arb_is_negative(acb_imagref(z))) || (fmpz_equal_si(k, -1) && arb_is_nonnegative(acb_imagref(z)))) && ((arf_cmpabs_2exp_si(arb_midref(acb_realref(ez1)), -2) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(ez1)), -2) <= 0))) { acb_t t; acb_init(t); acb_mul_2exp_si(t, ez1, 1); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_mul_ui(t, t, 3, prec); acb_sqrt(t, t, prec); if (!fmpz_is_zero(k)) acb_neg(t, t); acb_lambertw_branchpoint_series(res, t, 0, prec); acb_clear(t); return 1; /* todo: estimate */ } acb_lambertw_initial_asymp(res, z, k, prec); return 1; /* todo: estimate */ } /* note: z should be exact here */ void acb_lambertw_main(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec) { acb_t w, t, oldw, ew; mag_t err; slong i, wp, accuracy, ebits, kbits, mbits, wp_initial, extraprec; int have_ew; acb_init(t); acb_init(w); acb_init(oldw); acb_init(ew); mag_init(err); /* We need higher precision for large k, large exponents, or very close to the branch point at -1/e. todo: we should be recomputing ez1 to higher precision when close... */ acb_get_mag(err, z); if (fmpz_is_zero(k) && mag_cmp_2exp_si(err, 0) < 0) ebits = 0; else ebits = fmpz_bits(MAG_EXPREF(err)); if (fmpz_is_zero(k) || (fmpz_is_one(k) && arb_is_negative(acb_imagref(z))) || (fmpz_equal_si(k, -1) && arb_is_nonnegative(acb_imagref(z)))) { acb_get_mag(err, ez1); mbits = -MAG_EXP(err); mbits = FLINT_MAX(mbits, 0); mbits = FLINT_MIN(mbits, prec); } else { mbits = 0; } kbits = fmpz_bits(k); extraprec = FLINT_MAX(ebits, kbits); extraprec = FLINT_MAX(extraprec, mbits); wp = wp_initial = 40 + extraprec; accuracy = acb_lambertw_initial(w, z, ez1, k, wp_initial); mag_zero(arb_radref(acb_realref(w))); mag_zero(arb_radref(acb_imagref(w))); /* We should be able to compute e^w for the final certification during the Halley iteration. */ have_ew = 0; for (i = 0; i < 5 + FLINT_BIT_COUNT(prec + extraprec); i++) { /* todo: should we restart? */ if (!acb_is_finite(w)) break; wp = FLINT_MIN(3 * accuracy, 1.1 * prec + 10); wp = FLINT_MAX(wp, 40); wp += extraprec; acb_set(oldw, w); acb_lambertw_halley_step(t, ew, z, w, wp); /* estimate the error (conservatively) */ acb_sub(w, w, t, wp); acb_get_mag(err, w); acb_set(w, t); acb_add_error_mag(t, err); accuracy = acb_rel_accuracy_bits(t); if (accuracy > 2 * extraprec) accuracy *= 2.9; /* less conservatively */ accuracy = FLINT_MIN(accuracy, wp); accuracy = FLINT_MAX(accuracy, 0); if (accuracy > prec + extraprec) { /* e^w = e^oldw * e^(w-oldw) */ acb_sub(t, w, oldw, wp); acb_exp(t, t, wp); acb_mul(ew, ew, t, wp); have_ew = 1; break; } mag_zero(arb_radref(acb_realref(w))); mag_zero(arb_radref(acb_imagref(w))); } wp = FLINT_MIN(3 * accuracy, 1.1 * prec + 10); wp = FLINT_MAX(wp, 40); wp += extraprec; if (acb_lambertw_check_branch(w, k, wp)) { acb_t u, r, eu1; mag_t err, rad; acb_init(u); acb_init(r); acb_init(eu1); mag_init(err); mag_init(rad); if (have_ew) acb_set(t, ew); else acb_exp(t, w, wp); /* t = w e^w */ acb_mul(t, t, w, wp); acb_sub(r, t, z, wp); /* Bound W' on the straight line path between t and z */ acb_union(u, t, z, wp); arb_const_e(acb_realref(eu1), wp); arb_zero(acb_imagref(eu1)); acb_mul(eu1, eu1, u, wp); acb_add_ui(eu1, eu1, 1, wp); if (acb_lambertw_branch_crossing(u, eu1, k)) { mag_inf(err); } else { acb_lambertw_bound_deriv(err, u, eu1, k); acb_get_mag(rad, r); mag_mul(err, err, rad); } acb_add_error_mag(w, err); acb_set(res, w); acb_clear(u); acb_clear(r); acb_clear(eu1); mag_clear(err); mag_clear(rad); } else { acb_indeterminate(res); } acb_clear(t); acb_clear(w); acb_clear(oldw); acb_clear(ew); mag_clear(err); } void acb_lambertw_cleared_cut(acb_t res, const acb_t z, const fmpz_t k, int flags, slong prec) { acb_t ez1; acb_init(ez1); /* compute e*z + 1 */ arb_const_e(acb_realref(ez1), prec); acb_mul(ez1, ez1, z, prec); acb_add_ui(ez1, ez1, 1, prec); if (acb_is_exact(z)) { acb_lambertw_main(res, z, ez1, k, flags, prec); } else { acb_t zz; mag_t err, rad; mag_init(err); mag_init(rad); acb_init(zz); acb_lambertw_bound_deriv(err, z, ez1, k); mag_hypot(rad, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul(err, err, rad); acb_set(zz, z); mag_zero(arb_radref(acb_realref(zz))); mag_zero(arb_radref(acb_imagref(zz))); /* todo: recompute ez1? */ acb_lambertw_main(res, zz, ez1, k, flags, prec); acb_add_error_mag(res, err); mag_clear(err); mag_clear(rad); acb_clear(zz); } acb_clear(ez1); } /* Extremely close to the branch point at -1/e, use the series expansion directly. */ int acb_lambertw_try_near_branch_point(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec) { if (fmpz_is_zero(k) || (fmpz_is_one(k) && arb_is_negative(acb_imagref(z))) || (fmpz_equal_si(k, -1) && arb_is_nonnegative(acb_imagref(z)))) { if (acb_contains_zero(ez1) || (arf_cmpabs_2exp_si(arb_midref(acb_realref(ez1)), -prec / 4.5 - 6) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(ez1)), -prec / 4.5 - 6) < 0)) { acb_t t; acb_init(t); acb_mul_2exp_si(t, ez1, 1); acb_sqrt(t, t, prec); if (!fmpz_is_zero(k)) acb_neg(t, t); acb_lambertw_branchpoint_series(res, t, 1, prec); acb_clear(t); return 1; } } return 0; } void acb_lambertw_cleared_cut_fix_small(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec) { acb_t zz, zmid, zmide1; arf_t eps; acb_init(zz); acb_init(zmid); acb_init(zmide1); arf_init(eps); arf_mul_2exp_si(eps, arb_midref(acb_realref(z)), -prec); acb_set(zz, z); if (arf_sgn(arb_midref(acb_realref(zz))) < 0 && (!fmpz_is_zero(k) || arf_sgn(arb_midref(acb_realref(ez1))) < 0) && arf_cmpabs(arb_midref(acb_imagref(zz)), eps) < 0) { /* now the value must be in [0,2eps] */ arf_get_mag(arb_radref(acb_imagref(zz)), eps); arf_set_mag(arb_midref(acb_imagref(zz)), arb_radref(acb_imagref(zz))); if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) { acb_lambertw_cleared_cut(res, zz, k, flags, prec); } else { fmpz_t kk; fmpz_init(kk); fmpz_neg(kk, k); acb_lambertw_cleared_cut(res, zz, kk, flags, prec); acb_conj(res, res); fmpz_clear(kk); } } else { acb_lambertw_cleared_cut(res, zz, k, flags, prec); } acb_clear(zz); acb_clear(zmid); acb_clear(zmide1); arf_clear(eps); } void _acb_lambertw(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec) { slong goal, ebits, ebits2, ls, lt; const fmpz * expo; /* Estimated accuracy goal. */ /* todo: account for exponent bits and bits in k. */ goal = acb_rel_accuracy_bits(z); goal = FLINT_MAX(goal, 10); goal = FLINT_MIN(goal, prec); /* Handle tiny z directly. For k >= 2, |c_k| <= 4^k / 16. */ if (fmpz_is_zero(k) && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -goal / 2) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -goal / 2) < 0) { mag_t err; mag_init(err); acb_get_mag(err, z); mag_mul_2exp_si(err, err, 2); acb_set(res, z); acb_submul(res, res, res, prec); mag_geom_series(err, err, 3); mag_mul_2exp_si(err, err, -4); acb_add_error_mag(res, err); mag_clear(err); return; } if (arf_cmpabs(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z))) >= 0) expo = ARF_EXPREF(arb_midref(acb_realref(z))); else expo = ARF_EXPREF(arb_midref(acb_imagref(z))); ebits = fmpz_bits(expo); /* ebits ~= log2(|log(z) + 2 pi i k|) */ /* ebits2 ~= log2(log(log(z))) */ ebits = FLINT_MAX(ebits, fmpz_bits(k)); ebits = FLINT_MAX(ebits, 1) - 1; ebits2 = FLINT_BIT_COUNT(ebits); ebits2 = FLINT_MAX(ebits2, 1) - 1; /* We gain accuracy from the exponent when W ~ log - log log */ if (fmpz_sgn(expo) > 0 || (fmpz_sgn(expo) < 0 && !fmpz_is_zero(k))) { goal += ebits - ebits2; goal = FLINT_MAX(goal, 10); goal = FLINT_MIN(goal, prec); /* The asymptotic series with truncation L, M gives us about t - max(2+lt+L*(2+ls), M*(2+lt)) bits of accuracy where ls = -ebits, lt = ebits2 - ebits. */ ls = 2 - ebits; lt = 2 + ebits2 - ebits; if (ebits - FLINT_MAX(lt + 1*ls, 1*lt) > goal) { acb_lambertw_asymp(res, z, k, 1, 1, goal); acb_set_round(res, res, prec); return; } else if (ebits - FLINT_MAX(lt + 3*ls, 5*lt) > goal) { acb_lambertw_asymp(res, z, k, 3, 5, goal); acb_set_round(res, res, prec); return; } } /* Extremely close to the branch point at -1/e, use the series expansion directly. */ if (acb_lambertw_try_near_branch_point(res, z, ez1, k, flags, goal)) { acb_set_round(res, res, prec); return; } /* compute union of both sides */ if (acb_lambertw_branch_crossing(z, ez1, k)) { acb_t za, zb, eza1, ezb1; fmpz_t kk; acb_init(za); acb_init(zb); acb_init(eza1); acb_init(ezb1); fmpz_init(kk); fmpz_neg(kk, k); acb_set(za, z); acb_conj(zb, z); arb_nonnegative_part(acb_imagref(za), acb_imagref(za)); arb_nonnegative_part(acb_imagref(zb), acb_imagref(zb)); acb_set(eza1, ez1); acb_conj(ezb1, ez1); arb_nonnegative_part(acb_imagref(eza1), acb_imagref(eza1)); arb_nonnegative_part(acb_imagref(ezb1), acb_imagref(ezb1)); /* Check series expansion again, because now there is no crossing. */ if (!acb_lambertw_try_near_branch_point(res, za, eza1, k, flags, goal)) acb_lambertw_cleared_cut_fix_small(za, za, eza1, k, flags, goal); if (!acb_lambertw_try_near_branch_point(res, zb, ezb1, kk, flags, goal)) acb_lambertw_cleared_cut_fix_small(zb, zb, ezb1, kk, flags, goal); acb_conj(zb, zb); acb_union(res, za, zb, prec); acb_clear(za); acb_clear(zb); acb_clear(eza1); acb_clear(ezb1); fmpz_clear(kk); } else { acb_lambertw_cleared_cut_fix_small(res, z, ez1, k, flags, goal); acb_set_round(res, res, prec); } } void acb_lambertw_middle(acb_t res, const acb_t z, slong prec) { fmpz_t k; if (acb_contains_zero(z)) { acb_indeterminate(res); return; } fmpz_init(k); fmpz_set_si(k, -1); if (arb_is_positive(acb_imagref(z))) { acb_lambertw(res, z, k, 0, prec); } else if (arb_is_negative(acb_imagref(z))) { acb_conj(res, z); acb_lambertw(res, res, k, 0, prec); acb_conj(res, res); } else if (arb_is_negative(acb_realref(z))) { if (arb_is_nonnegative(acb_imagref(z))) { acb_lambertw(res, z, k, 0, prec); } else if (arb_is_negative(acb_imagref(z))) { acb_conj(res, z); acb_lambertw(res, res, k, 0, prec); acb_conj(res, res); } else { acb_t za, zb; acb_init(za); acb_init(zb); acb_set(za, z); acb_conj(zb, z); arb_nonnegative_part(acb_imagref(za), acb_imagref(za)); arb_nonnegative_part(acb_imagref(zb), acb_imagref(zb)); acb_lambertw(za, za, k, 0, prec); acb_lambertw(zb, zb, k, 0, prec); acb_conj(zb, zb); acb_union(res, za, zb, prec); acb_clear(za); acb_clear(zb); } } else /* re is positive */ { if (arb_is_positive(acb_imagref(z))) { acb_lambertw(res, z, k, 0, prec); } else if (arb_is_nonpositive(acb_imagref(z))) { acb_conj(res, z); acb_lambertw(res, res, k, 0, prec); acb_conj(res, res); } else { acb_t za, zb; acb_init(za); acb_init(zb); acb_set(za, z); acb_conj(zb, z); arb_nonnegative_part(acb_imagref(za), acb_imagref(za)); arb_nonnegative_part(acb_imagref(zb), acb_imagref(zb)); acb_lambertw(za, za, k, 0, prec); acb_lambertw(zb, zb, k, 0, prec); acb_conj(zb, zb); acb_union(res, za, zb, prec); acb_clear(za); acb_clear(zb); } } fmpz_clear(k); } void acb_lambertw_left(acb_t res, const acb_t z, const fmpz_t k, slong prec) { if (acb_contains_zero(z) && !(fmpz_equal_si(k, -1) && acb_is_real(z))) { acb_indeterminate(res); return; } if (arb_is_positive(acb_imagref(z))) { acb_lambertw(res, z, k, 0, prec); } else if (arb_is_nonpositive(acb_imagref(z))) { fmpz_t kk; fmpz_init(kk); fmpz_add_ui(kk, k, 1); fmpz_neg(kk, kk); acb_conj(res, z); acb_lambertw(res, res, kk, 0, prec); acb_conj(res, res); fmpz_clear(kk); } else { acb_t za, zb; fmpz_t kk; acb_init(za); acb_init(zb); fmpz_init(kk); acb_set(za, z); acb_conj(zb, z); arb_nonnegative_part(acb_imagref(za), acb_imagref(za)); arb_nonnegative_part(acb_imagref(zb), acb_imagref(zb)); fmpz_add_ui(kk, k, 1); fmpz_neg(kk, kk); acb_lambertw(za, za, k, 0, prec); acb_lambertw(zb, zb, kk, 0, prec); acb_conj(zb, zb); acb_union(res, za, zb, prec); acb_clear(za); acb_clear(zb); fmpz_clear(kk); } } void acb_lambertw(acb_t res, const acb_t z, const fmpz_t k, int flags, slong prec) { acb_t ez1; if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (flags == ACB_LAMBERTW_LEFT) { acb_lambertw_left(res, z, k, prec); return; } if (flags == ACB_LAMBERTW_MIDDLE) { acb_lambertw_middle(res, z, prec); return; } if (acb_contains_zero(z) && !fmpz_is_zero(k)) { acb_indeterminate(res); return; } acb_init(ez1); /* precompute z*e + 1 */ arb_const_e(acb_realref(ez1), prec); acb_mul(ez1, ez1, z, prec); acb_add_ui(ez1, ez1, 1, prec); /* Compute standard branches */ /* use real code when possible */ if (acb_is_real(z) && arb_is_positive(acb_realref(ez1)) && (fmpz_is_zero(k) || (fmpz_equal_si(k, -1) && arb_is_negative(acb_realref(z))))) { arb_lambertw(acb_realref(res), acb_realref(z), !fmpz_is_zero(k), prec); arb_zero(acb_imagref(res)); } else { _acb_lambertw(res, z, ez1, k, flags, prec); } acb_clear(ez1); } flint-3.1.3/src/acb/lambertw_asymp.c000066400000000000000000000063101461254215100173410ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "acb.h" void acb_lambertw_asymp(acb_t res, const acb_t z, const fmpz_t k, slong L, slong M, slong prec) { acb_t L1, L2, sigma, tau, s, c, u; slong l, m; fmpz_t t; fmpz * sc; /* For k = 0, the asymptotic expansion is not valid near 0. */ /* (It is sufficient to look at the midpoint as a test here.) */ if (fmpz_is_zero(k) && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 0) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0) { acb_indeterminate(res); return; } acb_init(L1); acb_init(L2); acb_init(sigma); acb_init(tau); acb_init(s); acb_init(c); acb_init(u); fmpz_init(t); acb_const_pi(L2, prec); acb_mul_2exp_si(L2, L2, 1); acb_mul_fmpz(L2, L2, k, prec); acb_mul_onei(L2, L2); acb_log(L1, z, prec); acb_add(L1, L1, L2, prec); acb_log(L2, L1, prec); acb_inv(sigma, L1, prec); acb_mul(tau, L2, sigma, prec); acb_zero(s); /* Stirling numbers */ sc = _fmpz_vec_init(L); acb_one(u); for (m = 1; m < M; m++) { if (m == 1) { for (l = 0; l < L; l++) fmpz_one(sc + l); } else { for (l = 0; l < L; l++) { fmpz_mul_ui(sc + l, sc + l, m + l - 1); if (l > 0) fmpz_add(sc + l, sc + l, sc + l - 1); } } acb_zero(c); /* todo: precompute powers instead of horner */ for (l = L - 1; l >= 0; l--) { acb_mul(c, c, sigma, prec); if (l % 2) acb_sub_fmpz(c, c, sc + l, prec); else acb_add_fmpz(c, c, sc + l, prec); } acb_mul(u, u, tau, prec); acb_div_ui(u, u, m, prec); acb_addmul(s, c, u, prec); } _fmpz_vec_clear(sc, L); acb_sub(s, s, L2, prec); acb_add(s, s, L1, prec); { mag_t m4s, m4t, one, q, r; mag_init(m4s); mag_init(m4t); mag_init(one); mag_init(q); mag_init(r); acb_get_mag(m4s, sigma); mag_mul_2exp_si(m4s, m4s, 2); acb_get_mag(m4t, tau); mag_mul_2exp_si(m4t, m4t, 2); mag_one(one); mag_sub_lower(q, one, m4s); mag_sub_lower(r, one, m4t); mag_mul(q, q, r); mag_pow_ui(r, m4s, L); mag_mul(r, r, m4t); mag_pow_ui(m4t, m4t, M); mag_add(r, r, m4t); mag_div(q, r, q); acb_add_error_mag(s, q); mag_clear(m4s); mag_clear(m4t); mag_clear(one); mag_clear(q); mag_clear(r); } acb_set(res, s); acb_clear(sigma); acb_clear(tau); acb_clear(s); acb_clear(c); acb_clear(L1); acb_clear(L2); acb_clear(u); fmpz_clear(t); } flint-3.1.3/src/acb/lambertw_bound_deriv.c000066400000000000000000000057531461254215100205220ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_lambertw_bound_deriv(mag_t res, const acb_t z, const acb_t ez1, const fmpz_t k) { mag_t t, u, v; mag_init(t); mag_init(u); mag_init(v); if (fmpz_is_zero(k)) { acb_get_mag(t, z); /* |z| <= 64 */ if (mag_cmp_2exp_si(t, 6) < 0) { /* 2.25 / sqrt(|t|) / sqrt(1+|t|), t = |ez+1| */ acb_get_mag_lower(t, ez1); mag_one(u); mag_add_lower(u, u, t); mag_mul_lower(t, t, u); mag_rsqrt(t, t); if (arb_is_positive(acb_realref(ez1))) { mag_mul_ui(t, t, 135); /* x0.9375 for small improvement */ mag_mul_2exp_si(t, t, -6); } else { mag_mul_ui(t, t, 9); mag_mul_2exp_si(t, t, -2); } mag_set(res, t); } else { acb_get_mag_lower(t, z); if (mag_cmp_2exp_si(t, 2) >= 0) { mag_one(u); mag_div(res, u, t); } else /* unlikely */ { acb_get_mag_lower(u, ez1); mag_rsqrt(u, u); mag_mul_2exp_si(u, u, -1); mag_add_ui(u, u, 1); mag_mul_ui(u, u, 3); mag_div(res, u, t); } } } else if (fmpz_is_pm1(k)) { if (arb_is_nonnegative(acb_realref(z)) || (fmpz_is_one(k) && arb_is_nonnegative(acb_imagref(z))) || (fmpz_equal_si(k, -1) && arb_is_negative(acb_imagref(z)))) { /* (1 + 1/(4+|z|^2))/|z| */ acb_get_mag_lower(t, z); mag_mul_lower(u, t, t); mag_set_ui_lower(v, 4); mag_add_lower(u, u, v); mag_one(v); mag_div(u, v, u); mag_add(u, u, v); mag_div(res, u, t); } else { /* (1 + 0.71875/sqrt(|e*z+1|)) / |z| */ acb_get_mag_lower(t, ez1); mag_rsqrt(t, t); mag_mul_ui(t, t, 23); mag_mul_2exp_si(t, t, -5); mag_one(u); mag_add(t, t, u); acb_get_mag_lower(u, z); mag_div(res, t, u); } mag_clear(t); mag_clear(u); mag_clear(v); return; } else { /* |W'(z)| = |1/z| |W(z)/(1+W(z))| <= |1/z| (2pi) / (2pi-1) */ mag_set_ui_2exp_si(t, 77, -6); acb_get_mag_lower(res, z); mag_div(res, t, res); } mag_clear(t); mag_clear(u); mag_clear(v); } flint-3.1.3/src/acb/lambertw_check_branch.c000066400000000000000000000050241461254215100206030ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" int _acb_lambertw_check_branch(const acb_t w, const fmpz_t k, slong prec) { arb_t t, u, v, a, b; int res = 0; arb_init(t); arb_init(u); arb_init(v); arb_init(a); arb_init(b); /* t = x sinc(y), v = -cos(y) */ if (arb_is_exact(acb_imagref(w))) { if (arb_is_zero(acb_imagref(w))) { arb_one(t); arb_one(v); } else { arb_sin_cos(t, v, acb_imagref(w), prec); arb_div(t, t, acb_imagref(w), prec); } } else { arb_sinc(t, acb_imagref(w), prec); arb_cos(v, acb_imagref(w), prec); } arb_mul(t, t, acb_realref(w), prec); arb_neg(v, v); /* u = y / pi, with conjugate relation for k */ arb_const_pi(u, prec); arb_div(u, acb_imagref(w), u, prec); if (fmpz_sgn(k) < 0) arb_neg(u, u); if (fmpz_is_zero(k)) { /* -1 < u < 1 and t > v */ arb_set_si(a, -1); arb_set_si(b, 1); if (arb_gt(u, a) && arb_lt(u, b) && arb_gt(t, v)) { res = 1; } } else { arb_set_fmpz(a, k); arb_abs(a, a); arb_mul_2exp_si(a, a, 1); arb_add_ui(b, a, 1, prec); arb_sub_ui(a, a, 2, prec); /* if u > 2|k|-2 and u < 2|k|+1 */ if (arb_gt(u, a) && arb_lt(u, b)) { arb_add_ui(a, a, 1, prec); arb_sub_ui(b, b, 1, prec); /* if u > 2|k|-1 and u < 2|k| */ if (arb_gt(u, a) && arb_lt(u, b)) { res = 1; } else if (arb_lt(u, b) && arb_lt(t, v)) /* u < 2|k| and t < v */ { res = 1; } else if (arb_gt(u, a) && arb_gt(t, v)) /* u > 2|k|-1 and t > v */ { res = 1; } } } arb_clear(t); arb_clear(u); arb_clear(v); arb_clear(a); arb_clear(b); return res; } int acb_lambertw_check_branch(const acb_t w, const fmpz_t k, slong prec) { if (prec > 64 && _acb_lambertw_check_branch(w, k, 32)) return 1; return _acb_lambertw_check_branch(w, k, prec); } flint-3.1.3/src/acb/log.c000066400000000000000000000047201461254215100150770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_log(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { if (arb_is_positive(a)) { arb_log(acb_realref(r), a, prec); arb_zero(acb_imagref(r)); } else if (arb_is_negative(a)) { arb_neg(acb_realref(r), a); arb_log(acb_realref(r), acb_realref(r), prec); arb_const_pi(acb_imagref(r), prec); } else { acb_indeterminate(r); } } else if (arb_is_zero(a)) { if (arb_is_positive(b)) { arb_log(acb_realref(r), b, prec); arb_const_pi(acb_imagref(r), prec); arb_mul_2exp_si(acb_imagref(r), acb_imagref(r), -1); } else if (arb_is_negative(b)) { arb_neg(acb_realref(r), b); arb_log(acb_realref(r), acb_realref(r), prec); arb_const_pi(acb_imagref(r), prec); arb_mul_2exp_si(acb_imagref(r), acb_imagref(r), -1); arb_neg(acb_imagref(r), acb_imagref(r)); } else { acb_indeterminate(r); } } else { if (r != z) { arb_log_hypot(acb_realref(r), a, b, prec); if (arb_is_finite(acb_realref(r))) arb_atan2(acb_imagref(r), b, a, prec); else arb_indeterminate(acb_imagref(r)); } else { arb_t t; arb_init(t); arb_log_hypot(t, a, b, prec); if (arb_is_finite(t)) arb_atan2(acb_imagref(r), b, a, prec); else arb_indeterminate(acb_imagref(r)); arb_swap(acb_realref(r), t); arb_clear(t); } } #undef a #undef b } void acb_log_analytic(acb_t res, const acb_t z, int analytic, slong prec) { if (analytic && arb_contains_zero(acb_imagref(z)) && !arb_is_positive(acb_realref(z))) { acb_indeterminate(res); } else { acb_log(res, z, prec); } } flint-3.1.3/src/acb/log1p.c000066400000000000000000000031211461254215100153320ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" static void acb_log1p_tiny(acb_t r, const acb_t z, slong prec) { mag_t b, c; acb_t t; int real; mag_init(b); mag_init(c); acb_init(t); real = acb_is_real(z); /* if |z| < 1, then |log(1+z) - [z - z^2/2]| <= |z|^3/(1-|z|) */ acb_get_mag(b, z); mag_one(c); mag_sub_lower(c, c, b); mag_pow_ui(b, b, 3); mag_div(b, b, c); acb_mul(t, z, z, prec); acb_mul_2exp_si(t, t, -1); acb_sub(r, z, t, prec); if (real && mag_is_finite(b)) arb_add_error_mag(acb_realref(r), b); else acb_add_error_mag(r, b); mag_clear(b); mag_clear(c); acb_clear(t); } void acb_log1p(acb_t r, const acb_t z, slong prec) { slong magz, magx, magy; if (acb_is_zero(z)) { acb_zero(r); return; } magx = arf_abs_bound_lt_2exp_si(arb_midref(acb_realref(z))); magy = arf_abs_bound_lt_2exp_si(arb_midref(acb_imagref(z))); magz = FLINT_MAX(magx, magy); if (magz < -prec) { acb_log1p_tiny(r, z, prec); } else { if (magz < 0) acb_add_ui(r, z, 1, prec + (-magz) + 4); else acb_add_ui(r, z, 1, prec + 4); acb_log(r, r, prec); } } flint-3.1.3/src/acb/log_sin_pi.c000066400000000000000000000061571461254215100164460ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" static void acb_log_sin_pi_half(acb_t res, const acb_t z, slong prec, int upper) { acb_t t, u, zmid; arf_t n; arb_t pi; acb_init(t); acb_init(u); acb_init(zmid); arf_init(n); arb_init(pi); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); arf_floor(n, arb_midref(acb_realref(zmid))); arb_sub_arf(acb_realref(zmid), acb_realref(zmid), n, prec); arb_const_pi(pi, prec); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(zmid)), 2) < 1) { acb_sin_pi(t, zmid, prec); acb_log(t, t, prec); } else /* i*pi*(z-0.5) + log((1-exp(-2i*pi*z))/2) */ { acb_mul_2exp_si(t, zmid, 1); acb_neg(t, t); if (upper) acb_conj(t, t); acb_exp_pi_i(t, t, prec); acb_sub_ui(t, t, 1, prec); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_log(t, t, prec); acb_one(u); acb_mul_2exp_si(u, u, -1); acb_sub(u, zmid, u, prec); if (upper) acb_conj(u, u); acb_mul_onei(u, u); acb_addmul_arb(t, u, pi, prec); if (upper) acb_conj(t, t); } if (upper) arb_submul_arf(acb_imagref(t), pi, n, prec); else arb_addmul_arf(acb_imagref(t), pi, n, prec); /* propagated error bound from the derivative pi cot(pi z) */ if (!acb_is_exact(z)) { mag_t zm, um; mag_init(zm); mag_init(um); acb_cot_pi(u, z, prec); acb_mul_arb(u, u, pi, prec); mag_hypot(zm, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); acb_get_mag(um, u); mag_mul(um, um, zm); acb_add_error_mag(t, um); mag_clear(zm); mag_clear(um); } acb_set(res, t); acb_clear(t); acb_clear(u); acb_clear(zmid); arf_clear(n); arb_clear(pi); } void acb_log_sin_pi(acb_t res, const acb_t z, slong prec) { if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (arb_is_positive(acb_imagref(z)) || (arb_is_zero(acb_imagref(z)) && arb_is_negative(acb_realref(z)))) { acb_log_sin_pi_half(res, z, prec, 1); } else if (arb_is_negative(acb_imagref(z)) || (arb_is_zero(acb_imagref(z)) && arb_is_positive(acb_realref(z)))) { acb_log_sin_pi_half(res, z, prec, 0); } else { acb_t t; acb_init(t); acb_log_sin_pi_half(t, z, prec, 1); acb_log_sin_pi_half(res, z, prec, 0); arb_union(acb_realref(res), acb_realref(res), acb_realref(t), prec); arb_union(acb_imagref(res), acb_imagref(res), acb_imagref(t), prec); acb_clear(t); } } flint-3.1.3/src/acb/mul.c000066400000000000000000000136271461254215100151210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(y) #define d acb_imagref(y) #define e acb_realref(z) #define f acb_imagref(z) #define ar arb_radref(a) #define br arb_radref(b) #define cr arb_radref(c) #define dr arb_radref(d) static void _acb_sqr_fast(acb_t z, const acb_t x, slong prec) { int inexact; mag_t am, bm, er, fr; mag_fast_init_set_arf(am, arb_midref(a)); mag_fast_init_set_arf(bm, arb_midref(b)); mag_init(er); mag_init(fr); mag_fast_addmul(er, am, ar); mag_fast_addmul(er, bm, br); mag_fast_mul_2exp_si(er, er, 1); mag_fast_addmul(er, ar, ar); mag_fast_addmul(er, br, br); mag_fast_addmul(fr, bm, ar); mag_fast_addmul(fr, am, br); mag_fast_addmul(fr, ar, br); mag_fast_mul_2exp_si(fr, fr, 1); inexact = arf_complex_sqr(arb_midref(e), arb_midref(f), arb_midref(a), arb_midref(b), prec, ARB_RND); if (inexact & 1) arf_mag_add_ulp(arb_radref(e), er, arb_midref(e), prec); else mag_set(arb_radref(e), er); if (inexact & 2) arf_mag_add_ulp(arb_radref(f), fr, arb_midref(f), prec); else mag_set(arb_radref(f), fr); } static void _acb_sqr_slow(acb_t z, const acb_t x, slong prec) { int inexact; mag_t am, bm, er, fr; mag_init_set_arf(am, arb_midref(a)); mag_init_set_arf(bm, arb_midref(b)); mag_init(er); mag_init(fr); mag_addmul(er, am, ar); mag_addmul(er, bm, br); mag_mul_2exp_si(er, er, 1); mag_addmul(er, ar, ar); mag_addmul(er, br, br); mag_addmul(fr, bm, ar); mag_addmul(fr, am, br); mag_addmul(fr, ar, br); mag_mul_2exp_si(fr, fr, 1); inexact = arf_complex_sqr(arb_midref(e), arb_midref(f), arb_midref(a), arb_midref(b), prec, ARB_RND); if (inexact & 1) arf_mag_add_ulp(arb_radref(e), er, arb_midref(e), prec); else mag_swap(arb_radref(e), er); if (inexact & 2) arf_mag_add_ulp(arb_radref(f), fr, arb_midref(f), prec); else mag_swap(arb_radref(f), fr); mag_clear(am); mag_clear(bm); mag_clear(er); mag_clear(fr); } static void _acb_mul_fast(acb_t z, const acb_t x, const acb_t y, slong prec) { int inexact; mag_t am, bm, cm, dm, er, fr; mag_fast_init_set_arf(am, arb_midref(a)); mag_fast_init_set_arf(bm, arb_midref(b)); mag_fast_init_set_arf(cm, arb_midref(c)); mag_fast_init_set_arf(dm, arb_midref(d)); mag_init(er); mag_init(fr); mag_fast_addmul(er, am, cr); mag_fast_addmul(er, bm, dr); mag_fast_addmul(er, cm, ar); mag_fast_addmul(er, dm, br); mag_fast_addmul(er, ar, cr); mag_fast_addmul(er, br, dr); mag_fast_addmul(fr, am, dr); mag_fast_addmul(fr, bm, cr); mag_fast_addmul(fr, cm, br); mag_fast_addmul(fr, dm, ar); mag_fast_addmul(fr, br, cr); mag_fast_addmul(fr, ar, dr); inexact = arf_complex_mul(arb_midref(e), arb_midref(f), arb_midref(a), arb_midref(b), arb_midref(c), arb_midref(d), prec, ARB_RND); if (inexact & 1) arf_mag_add_ulp(arb_radref(e), er, arb_midref(e), prec); else mag_set(arb_radref(e), er); if (inexact & 2) arf_mag_add_ulp(arb_radref(f), fr, arb_midref(f), prec); else mag_set(arb_radref(f), fr); } static void _acb_mul_slow(acb_t z, const acb_t x, const acb_t y, slong prec) { int inexact; mag_t am, bm, cm, dm, er, fr; mag_init_set_arf(am, arb_midref(a)); mag_init_set_arf(bm, arb_midref(b)); mag_init_set_arf(cm, arb_midref(c)); mag_init_set_arf(dm, arb_midref(d)); mag_init(er); mag_init(fr); mag_addmul(er, am, cr); mag_addmul(er, bm, dr); mag_addmul(er, cm, ar); mag_addmul(er, dm, br); mag_addmul(er, ar, cr); mag_addmul(er, br, dr); mag_addmul(fr, am, dr); mag_addmul(fr, bm, cr); mag_addmul(fr, cm, br); mag_addmul(fr, dm, ar); mag_addmul(fr, br, cr); mag_addmul(fr, ar, dr); inexact = arf_complex_mul(arb_midref(e), arb_midref(f), arb_midref(a), arb_midref(b), arb_midref(c), arb_midref(d), prec, ARB_RND); if (inexact & 1) arf_mag_add_ulp(arb_radref(e), er, arb_midref(e), prec); else mag_swap(arb_radref(e), er); if (inexact & 2) arf_mag_add_ulp(arb_radref(f), fr, arb_midref(f), prec); else mag_swap(arb_radref(f), fr); mag_clear(am); mag_clear(bm); mag_clear(cm); mag_clear(dm); mag_clear(er); mag_clear(fr); } void acb_mul(acb_t z, const acb_t x, const acb_t y, slong prec) { if (arb_is_zero(b)) { arb_mul(f, d, a, prec); arb_mul(e, c, a, prec); } else if (arb_is_zero(d)) { arb_mul(f, b, c, prec); arb_mul(e, a, c, prec); } else if (arb_is_zero(a)) { arb_mul(e, c, b, prec); arb_mul(f, d, b, prec); acb_mul_onei(z, z); } else if (arb_is_zero(c)) { arb_mul(e, a, d, prec); arb_mul(f, b, d, prec); acb_mul_onei(z, z); } /* squaring = a^2-b^2, 2ab */ else if (x == y) { if (ARB_IS_LAGOM(a) && ARB_IS_LAGOM(b)) _acb_sqr_fast(z, x, prec); else _acb_sqr_slow(z, x, prec); } else { if (ARB_IS_LAGOM(a) && ARB_IS_LAGOM(b) && ARB_IS_LAGOM(c) && ARB_IS_LAGOM(d)) _acb_mul_fast(z, x, y, prec); else _acb_mul_slow(z, x, y, prec); } } #undef a #undef b #undef c #undef d #undef e #undef f #undef ar #undef br #undef cr #undef dr flint-3.1.3/src/acb/mul_naive.c000066400000000000000000000055601461254215100163000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_mul_naive(acb_t z, const acb_t x, const acb_t y, slong prec) { #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(y) #define d acb_imagref(y) #define e acb_realref(z) #define f acb_imagref(z) if (arb_is_zero(b)) { arb_mul(f, d, a, prec); arb_mul(e, c, a, prec); } else if (arb_is_zero(d)) { arb_mul(f, b, c, prec); arb_mul(e, a, c, prec); } else if (arb_is_zero(a)) { arb_mul(e, c, b, prec); arb_mul(f, d, b, prec); acb_mul_onei(z, z); } else if (arb_is_zero(c)) { arb_mul(e, a, d, prec); arb_mul(f, b, d, prec); acb_mul_onei(z, z); } /* squaring = a^2-b^2, 2ab */ else if (x == y) { /* aliasing */ if (z == x) { arb_t t; arb_init(t); arb_mul(t, a, b, prec); arb_mul_2exp_si(t, t, 1); arb_mul(e, a, a, prec); arb_mul(f, b, b, prec); arb_sub(e, e, f, prec); arb_swap(f, t); arb_clear(t); } else { arb_mul(e, a, a, prec); arb_mul(f, b, b, prec); arb_sub(e, e, f, prec); arb_mul(f, a, b, prec); arb_mul_2exp_si(f, f, 1); } } else { /* aliasing */ if (z == x) { arb_t t, u; arb_init(t); arb_init(u); arb_mul(t, a, c, prec); arb_mul(u, a, d, prec); arb_mul(e, b, d, prec); arb_sub(e, t, e, prec); arb_mul(f, b, c, prec); arb_add(f, u, f, prec); arb_clear(t); arb_clear(u); } else if (z == y) { arb_t t, u; arb_init(t); arb_init(u); arb_mul(t, a, c, prec); arb_mul(u, b, c, prec); arb_mul(e, b, d, prec); arb_sub(e, t, e, prec); arb_mul(f, a, d, prec); arb_add(f, u, f, prec); arb_clear(t); arb_clear(u); } else { arb_t t; arb_init(t); arb_mul(e, a, c, prec); arb_mul(t, b, d, prec); arb_sub(e, e, t, prec); arb_mul(f, a, d, prec); arb_mul(t, b, c, prec); arb_add(f, f, t, prec); arb_clear(t); } } #undef a #undef b #undef c #undef d #undef e #undef f } flint-3.1.3/src/acb/polygamma.c000066400000000000000000000031571461254215100163070ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_poly.h" void acb_polygamma(acb_t res, const acb_t s, const acb_t z, slong prec) { if (acb_is_zero(s)) { acb_digamma(res, z, prec); } else if (acb_is_int(s) && arb_is_positive(acb_realref(s))) { acb_t t, u; acb_init(t); acb_init(u); acb_add_ui(t, s, 1, prec); acb_gamma(u, t, prec); acb_hurwitz_zeta(t, t, z, prec); if (acb_is_int_2exp_si(s, 1)) acb_neg(t, t); acb_mul(res, t, u, prec); acb_clear(t); acb_clear(u); } else { acb_t t, u; acb_struct v[2]; acb_init(t); acb_init(u); acb_init(v); acb_init(v + 1); /* u = psi(-s) + gamma */ acb_neg(t, s); acb_digamma(u, t, prec); arb_const_euler(acb_realref(v), prec); arb_add(acb_realref(u), acb_realref(u), acb_realref(v), prec); acb_add_ui(t, s, 1, prec); _acb_poly_zeta_cpx_series(v, t, z, 0, 2, prec); acb_addmul(v + 1, v, u, prec); acb_neg(t, s); acb_rgamma(u, t, prec); acb_mul(res, v + 1, u, prec); acb_clear(v); acb_clear(v + 1); acb_clear(t); acb_clear(u); } } flint-3.1.3/src/acb/polylog.c000066400000000000000000000014141461254215100160000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_poly.h" void acb_polylog(acb_t w, const acb_t s, const acb_t z, slong prec) { acb_t t; acb_init(t); _acb_poly_polylog_cpx(t, s, z, 1, prec); acb_swap(w, t); acb_clear(t); } void acb_polylog_si(acb_t w, slong s, const acb_t z, slong prec) { acb_t t; acb_init(t); acb_set_si(t, s); acb_polylog(w, t, z, prec); acb_clear(t); } flint-3.1.3/src/acb/pow.c000066400000000000000000000121371461254215100151240ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_pow_fmpz_binexp(acb_t y, const acb_t b, const fmpz_t e, slong prec) { slong i, wp, bits; if (-WORD(2) <= *e && *e <= WORD(4)) { if (*e == WORD(0)) { acb_one(y); } else if (*e == WORD(1)) { acb_set_round(y, b, prec); } else if (*e == -WORD(1)) { acb_inv(y, b, prec); } else if (*e == WORD(2)) { acb_mul(y, b, b, prec); } else if (*e == WORD(3)) { acb_cube(y, b, prec); } else if (*e == WORD(4)) { acb_mul(y, b, b, prec); acb_mul(y, y, y, prec); } else { acb_inv(y, b, prec); acb_mul(y, y, y, prec); } return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); if (acb_is_exact(b)) { acb_pow_fmpz_binexp(y, b, f, prec + 2); acb_inv(y, y, prec); } else { acb_inv(y, b, prec + fmpz_bits(e) + 2); acb_pow_fmpz_binexp(y, y, f, prec); } fmpz_clear(f); return; } if (!COEFF_IS_MPZ(*e) && ((*e) % 3 == 0)) { fmpz e3 = (*e) / 3; acb_pow_fmpz_binexp(y, b, &e3, prec); acb_cube(y, y, prec); return; } if (y == b) { acb_t t; acb_init(t); acb_set(t, b); acb_pow_fmpz_binexp(y, t, e, prec); acb_clear(t); return; } acb_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { acb_mul(y, y, y, wp); if (fmpz_tstbit(e, i)) acb_mul(y, y, b, wp); } } void acb_pow_fmpz(acb_t y, const acb_t b, const fmpz_t e, slong prec) { acb_pow_fmpz_binexp(y, b, e, prec); } void acb_pow_ui(acb_t y, const acb_t b, ulong e, slong prec) { fmpz_t f; fmpz_init_set_ui(f, e); acb_pow_fmpz(y, b, f, prec); fmpz_clear(f); } void acb_pow_si(acb_t y, const acb_t b, slong e, slong prec) { fmpz_t f; fmpz_init(f); fmpz_set_si(f, e); acb_pow_fmpz(y, b, f, prec); fmpz_clear(f); } void _acb_pow_exp(acb_t z, const acb_t x, const acb_t y, slong prec) { acb_t t; acb_init(t); acb_log(t, x, prec); acb_mul(t, t, y, prec); acb_exp(z, t, prec); acb_clear(t); } void _acb_pow_arb_exp(acb_t z, const acb_t x, const arb_t y, slong prec) { acb_t t; acb_init(t); acb_log(t, x, prec); acb_mul_arb(t, t, y, prec); acb_exp(z, t, prec); acb_clear(t); } #define BINEXP_LIMIT 64 void acb_pow_arb(acb_t z, const acb_t x, const arb_t y, slong prec) { const arf_struct * ymid = arb_midref(y); const mag_struct * yrad = arb_radref(y); if (arb_is_zero(y)) { acb_one(z); return; } if (acb_is_zero(x)) { if (arb_is_positive(y)) acb_zero(z); else acb_indeterminate(z); return; } if (mag_is_zero(yrad)) { /* small half-integer or integer */ if (arf_cmpabs_2exp_si(ymid, BINEXP_LIMIT) < 0 && arf_is_int_2exp_si(ymid, -1)) { fmpz_t e; fmpz_init(e); if (arf_is_int(ymid)) { arf_get_fmpz_fixed_si(e, ymid, 0); acb_pow_fmpz_binexp(z, x, e, prec); } else { arf_get_fmpz_fixed_si(e, ymid, -1); if (fmpz_sgn(e) >= 0) { acb_sqrt(z, x, prec + fmpz_bits(e)); acb_pow_fmpz_binexp(z, z, e, prec); } else { fmpz_neg(e, e); acb_rsqrt(z, x, prec + fmpz_bits(e)); acb_pow_fmpz_binexp(z, z, e, prec); } } fmpz_clear(e); return; } } _acb_pow_arb_exp(z, x, y, prec); } void acb_pow(acb_t z, const acb_t x, const acb_t y, slong prec) { if (arb_is_zero(acb_imagref(y))) { acb_pow_arb(z, x, acb_realref(y), prec); } else { if (acb_is_zero(x)) { if (arb_is_positive(acb_realref(y))) acb_zero(z); else acb_indeterminate(z); return; } _acb_pow_exp(z, x, y, prec); } } void acb_pow_analytic(acb_t res, const acb_t z, const acb_t w, int analytic, slong prec) { if (analytic && !acb_is_int(w) && arb_contains_zero(acb_imagref(z)) && !arb_is_positive(acb_realref(z))) { acb_indeterminate(res); } else { acb_pow(res, z, w, prec); } } flint-3.1.3/src/acb/quadratic_roots_fmpz.c000066400000000000000000000022601461254215100205520ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_quadratic_roots_fmpz(acb_t r1, acb_t r2, const fmpz_t a, const fmpz_t b, const fmpz_t c, slong prec) { fmpz_t d; fmpz_init(d); /* d = b^2 - 4ac */ fmpz_mul(d, a, c); fmpz_mul_2exp(d, d, 2); fmpz_submul(d, b, b); fmpz_neg(d, d); /* +/- sqrt(d) */ acb_zero(r1); if (fmpz_sgn(d) >= 0) { arb_sqrt_fmpz(acb_realref(r1), d, prec + fmpz_bits(d) + 4); } else { fmpz_neg(d, d); arb_sqrt_fmpz(acb_imagref(r1), d, prec + fmpz_bits(d) + 4); } acb_neg(r2, r1); /* -b */ acb_sub_fmpz(r1, r1, b, prec + 4); acb_sub_fmpz(r2, r2, b, prec + 4); /* divide by 2a */ fmpz_mul_2exp(d, a, 1); acb_div_fmpz(r1, r1, d, prec); acb_div_fmpz(r2, r2, d, prec); fmpz_clear(d); return; } flint-3.1.3/src/acb/randtest.c000066400000000000000000000026611461254215100161440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_randtest(acb_t z, flint_rand_t state, slong prec, slong mag_bits) { arb_randtest(acb_realref(z), state, prec, mag_bits); arb_randtest(acb_imagref(z), state, prec, mag_bits); } void acb_randtest_special(acb_t z, flint_rand_t state, slong prec, slong mag_bits) { arb_randtest_special(acb_realref(z), state, prec, mag_bits); arb_randtest_special(acb_imagref(z), state, prec, mag_bits); } void acb_randtest_precise(acb_t z, flint_rand_t state, slong prec, slong mag_bits) { arb_randtest_precise(acb_realref(z), state, prec, mag_bits); arb_randtest_precise(acb_imagref(z), state, prec, mag_bits); } void acb_randtest_param(acb_t x, flint_rand_t state, slong prec, slong size) { if (n_randint(state, 8) == 0) { fmpz_t t; fmpz_init(t); fmpz_randtest(t, state, 1 + n_randint(state, prec)); arb_set_fmpz(acb_realref(x), t); arb_zero(acb_imagref(x)); acb_mul_2exp_si(x, x, -1); fmpz_clear(t); } else { acb_randtest(x, state, prec, size); } } flint-3.1.3/src/acb/real_abs.c000066400000000000000000000017621461254215100160710ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_abs(acb_t res, const acb_t z, int analytic, slong prec) { if (!acb_is_finite(z) || (analytic && arb_contains_zero(acb_realref(z)))) { acb_indeterminate(res); } else { if (arb_is_nonnegative(acb_realref(z))) { acb_set_round(res, z, prec); } else if (arb_is_negative(acb_realref(z))) { acb_neg_round(res, z, prec); } else { acb_t t; acb_init(t); acb_neg(t, z); acb_union(res, z, t, prec); acb_clear(t); } } } flint-3.1.3/src/acb/real_ceil.c000066400000000000000000000013101461254215100162250ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_ceil(acb_t res, const acb_t z, int analytic, slong prec) { if (!acb_is_finite(z) || (analytic && arb_contains_int(acb_realref(z)))) { acb_indeterminate(res); } else { arb_ceil(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } } flint-3.1.3/src/acb/real_floor.c000066400000000000000000000013121461254215100164340ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_floor(acb_t res, const acb_t z, int analytic, slong prec) { if (!acb_is_finite(z) || (analytic && arb_contains_int(acb_realref(z)))) { acb_indeterminate(res); } else { arb_floor(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } } flint-3.1.3/src/acb/real_heaviside.c000066400000000000000000000012021461254215100172520ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_heaviside(acb_t res, const acb_t z, int analytic, slong prec) { acb_real_sgn(res, z, analytic, prec); if (acb_is_finite(res)) { acb_add_ui(res, res, 1, prec); acb_mul_2exp_si(res, res, -1); } } flint-3.1.3/src/acb/real_max.c000066400000000000000000000016541461254215100161110ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_max(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec) { arb_t t; if (!acb_is_finite(x) || !acb_is_finite(y)) { acb_indeterminate(res); return; } arb_init(t); arb_sub(t, acb_realref(x), acb_realref(y), prec); if (arb_is_positive(t)) acb_set_round(res, x, prec); else if (arb_is_negative(t)) acb_set_round(res, y, prec); else if (!analytic) acb_union(res, x, y, prec); else acb_indeterminate(res); arb_clear(t); } flint-3.1.3/src/acb/real_min.c000066400000000000000000000016541461254215100161070ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_min(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec) { arb_t t; if (!acb_is_finite(x) || !acb_is_finite(y)) { acb_indeterminate(res); return; } arb_init(t); arb_sub(t, acb_realref(x), acb_realref(y), prec); if (arb_is_positive(t)) acb_set_round(res, y, prec); else if (arb_is_negative(t)) acb_set_round(res, x, prec); else if (!analytic) acb_union(res, x, y, prec); else acb_indeterminate(res); arb_clear(t); } flint-3.1.3/src/acb/real_sgn.c000066400000000000000000000012651461254215100161110ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_sgn(acb_t res, const acb_t z, int analytic, slong prec) { if (!acb_is_finite(z) || (analytic && arb_contains_zero(acb_realref(z)))) { acb_indeterminate(res); } else { acb_csgn(acb_realref(res), z); arb_zero(acb_imagref(res)); } } flint-3.1.3/src/acb/real_sqrtpos.c000066400000000000000000000014631461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_real_sqrtpos(acb_t res, const acb_t z, int analytic, slong prec) { if (arb_is_zero(acb_imagref(z)) && !analytic) { arb_sqrtpos(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } else if (arb_is_positive(acb_realref(z)) || !arb_contains_zero(acb_imagref(z))) { acb_sqrt(res, z, prec); } else { acb_indeterminate(res); } } flint-3.1.3/src/acb/rel_error_bits.c000066400000000000000000000042351461254215100173330ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" slong acb_rel_error_bits(const acb_t x) { int am, ar, bm, br; slong result; const fmpz * radmag; const fmpz * midmag; fmpz_t t; am = !arf_is_zero(arb_midref(acb_realref(x))); ar = !mag_is_zero(arb_radref(acb_realref(x))); bm = !arf_is_zero(arb_midref(acb_imagref(x))); br = !mag_is_zero(arb_radref(acb_imagref(x))); /* no radius -- exact */ if (!ar && !br) return -ARF_PREC_EXACT; /* no midpoint -- infinite relative error */ if (!am && !bm) return ARF_PREC_EXACT; if (!acb_is_finite(x)) return ARF_PREC_EXACT; #define ame ARF_EXPREF(arb_midref(acb_realref(x))) #define are MAG_EXPREF(arb_radref(acb_realref(x))) #define bme ARF_EXPREF(arb_midref(acb_imagref(x))) #define bre MAG_EXPREF(arb_radref(acb_imagref(x))) if (am && bm) midmag = fmpz_cmp(ame, bme) >= 0 ? ame : bme; else if (am) midmag = ame; else midmag = bme; if (ar && br) radmag = fmpz_cmp(are, bre) >= 0 ? are : bre; else if (ar) radmag = are; else radmag = bre; fmpz_init(t); fmpz_add_ui(t, radmag, 1); result = _fmpz_sub_small(t, midmag); fmpz_clear(t); return result; } slong acb_rel_one_accuracy_bits(const acb_t z) { if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -1) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -1) < 0) { acb_t t; arf_init(arb_midref(acb_realref(t))); arf_one(arb_midref(acb_realref(t))); arf_init(arb_midref(acb_imagref(t))); *arb_radref(acb_realref(t)) = *arb_radref(acb_realref(z)); *arb_radref(acb_imagref(t)) = *arb_radref(acb_imagref(z)); return acb_rel_accuracy_bits(t); } else { return acb_rel_accuracy_bits(z); } } flint-3.1.3/src/acb/rising2_ui.c000066400000000000000000000015311461254215100163650ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_rising2_ui(acb_t u, acb_t v, const acb_t x, ulong n, slong prec) { if (x == u || x == v) { acb_t t; acb_init(t); acb_set(t, x); acb_rising2_ui(u, v, t, n, prec); acb_clear(t); } else { acb_struct tmp[2]; tmp[0] = *u; tmp[1] = *v; acb_hypgeom_rising_ui_jet(tmp, x, n, 2, prec); *u = tmp[0]; *v = tmp[1]; } } flint-3.1.3/src/acb/rising_ui.c000066400000000000000000000012071461254215100163030ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_rising_ui(acb_t y, const acb_t x, ulong n, slong prec) { acb_hypgeom_rising_ui(y, x, n, prec); } void acb_rising(acb_t y, const acb_t x, const acb_t n, slong prec) { acb_hypgeom_rising(y, x, n, prec); } flint-3.1.3/src/acb/rising_ui_get_mag.c000066400000000000000000000042661461254215100177760ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" static void acb_rising_get_mag2_right(mag_t bound, const arb_t a, const arb_t b, ulong n) { mag_t t, u; ulong k; mag_init(t); mag_init(u); arb_get_mag(t, a); arb_get_mag(u, b); mag_mul(bound, t, t); mag_addmul(bound, u, u); mag_set(u, bound); mag_mul_2exp_si(t, t, 1); for (k = 1; k < n; k++) { mag_add_ui(u, u, 2 * k - 1); mag_add(u, u, t); mag_mul(bound, bound, u); } mag_clear(t); mag_clear(u); } void acb_rising_ui_get_mag(mag_t bound, const acb_t s, ulong n) { if (n == 0) { mag_one(bound); return; } if (n == 1) { acb_get_mag(bound, s); return; } if (!acb_is_finite(s)) { mag_inf(bound); return; } if (arf_sgn(arb_midref(acb_realref(s))) >= 0) { acb_rising_get_mag2_right(bound, acb_realref(s), acb_imagref(s), n); } else { arb_t a; slong k; mag_t bound2, t, u; arb_init(a); mag_init(bound2); mag_init(t); mag_init(u); arb_get_mag(u, acb_imagref(s)); mag_mul(u, u, u); mag_one(bound); for (k = 0; k < n; k++) { arb_add_ui(a, acb_realref(s), k, MAG_BITS); if (arf_sgn(arb_midref(a)) >= 0) { acb_rising_get_mag2_right(bound2, a, acb_imagref(s), n - k); mag_mul(bound, bound, bound2); break; } else { arb_get_mag(t, a); mag_mul(t, t, t); mag_add(t, t, u); mag_mul(bound, bound, t); } } arb_clear(a); mag_clear(bound2); mag_clear(t); mag_clear(u); } mag_sqrt(bound, bound); } flint-3.1.3/src/acb/root_ui.c000066400000000000000000000020631461254215100157740ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_root_ui(acb_t res, const acb_t z, ulong n, slong prec) { if (n == 0) { acb_indeterminate(res); } else if (n == 1) { acb_set_round(res, z, prec); } else if (n == 2) { acb_sqrt(res, z, prec); } else if (n == 4) { acb_sqrt(res, z, prec + 4); acb_sqrt(res, res, prec); } else if (acb_is_real(z) && arb_is_nonnegative(acb_realref(z))) { arb_root(acb_realref(res), acb_realref(z), n, prec); arb_zero(acb_imagref(res)); } else { acb_log(res, z, prec + 4); acb_div_ui(res, res, n, prec + 4); acb_exp(res, res, prec); } } flint-3.1.3/src/acb/rsqrt.c000066400000000000000000000275211461254215100154750ustar00rootroot00000000000000/* Copyright (C) 2013, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" /* r - |m| */ void arb_get_mag_reverse(mag_t res, const arb_t x) { mag_t t; mag_init(t); arf_get_mag_lower(t, arb_midref(x)); mag_sub(res, arb_radref(x), t); mag_clear(t); } /* upper bound for re(rsqrt(x+yi)) / |rsqrt(x+yi)|, given upper bound for x, lower bound for y */ void mag_rsqrt_re_quadrant1_upper(mag_t res, const mag_t x, const mag_t y) { if (mag_is_zero(x)) { mag_one(res); mag_mul_2exp_si(res, res, -1); } else { mag_t t, u; mag_init(t); mag_init(u); /* t = (y/x)^2 -- the result is a decreasing function of t */ mag_div_lower(t, y, x); mag_mul_lower(t, t, t); /* (rsqrt(t^2+1)+1)/2 */ mag_add_ui_lower(u, t, 1); mag_rsqrt(u, u); mag_add_ui(u, u, 1); mag_mul_2exp_si(res, u, -1); mag_clear(t); mag_clear(u); } mag_sqrt(res, res); } /* lower bound for re(rsqrt(x+yi)) / |rsqrt(x+yi)|, given lower bound for x, upper bound for y */ void mag_rsqrt_re_quadrant1_lower(mag_t res, const mag_t x, const mag_t y) { if (mag_is_zero(x)) { mag_one(res); mag_mul_2exp_si(res, res, -1); } else { mag_t t, u; mag_init(t); mag_init(u); /* t = (y/x)^2 -- the result is a decreasing function of t */ mag_div(t, y, x); mag_mul(t, t, t); /* (rsqrt(t^2+1)+1)/2 */ mag_add_ui(u, t, 1); mag_rsqrt_lower(u, u); mag_add_ui_lower(u, u, 1); mag_mul_2exp_si(res, u, -1); mag_clear(t); mag_clear(u); } mag_sqrt_lower(res, res); } /* upper bound for re(rsqrt(-x+yi)) / |rsqrt(x+yi)|, given lower bound for -x, upper bound for y */ void mag_rsqrt_re_quadrant2_upper(mag_t res, const mag_t x, const mag_t y) { if (mag_is_zero(x)) { mag_one(res); mag_mul_2exp_si(res, res, -1); } else { mag_t t, u, v; mag_init(t); mag_init(u); mag_init(v); /* t = (y/x)^2 -- the result is an increasing function of t */ mag_div(t, y, x); mag_mul(t, t, t); /* t / (2*(t+1)*(rsqrt(t+1)+1)) */ mag_add_ui(u, t, 1); mag_rsqrt_lower(v, u); mag_add_ui_lower(v, v, 1); mag_add_ui_lower(u, t, 1); mag_mul_lower(v, v, u); mag_mul_2exp_si(v, v, 1); mag_div(res, t, v); mag_clear(t); mag_clear(u); mag_clear(v); } mag_sqrt(res, res); } /* lower bound for re(rsqrt(-x+yi)) / |rsqrt(x+yi)|, given upper bound for -x, lower bound for y */ void mag_rsqrt_re_quadrant2_lower(mag_t res, const mag_t x, const mag_t y) { if (mag_is_zero(x)) { mag_one(res); mag_mul_2exp_si(res, res, -1); } else { mag_t t, u, v; mag_init(t); mag_init(u); mag_init(v); /* t = (y/x)^2 -- the result is an increasing function of t */ mag_div_lower(t, y, x); mag_mul_lower(t, t, t); /* t / (2*(t+1)*(rsqrt(t+1)+1)) */ mag_add_ui_lower(u, t, 1); mag_rsqrt(v, u); mag_add_ui(v, v, 1); mag_add_ui(u, t, 1); mag_mul(v, v, u); mag_mul_2exp_si(v, v, 1); mag_div_lower(res, t, v); mag_clear(t); mag_clear(u); mag_clear(v); } mag_sqrt_lower(res, res); } void acb_rsqrt_wide(acb_t res, const acb_t z, slong prec) { mag_t ax, ay, bx, by, cx, cy, dx, dy, am, bm; mag_t one; mag_init(ax); mag_init(ay); mag_init(bx); mag_init(by); mag_init(cx); mag_init(cy); mag_init(dx); mag_init(dy); mag_init(am); mag_init(bm); mag_init(one); mag_one(one); /* magnitude */ acb_get_mag(am, z); mag_rsqrt_lower(am, am); acb_get_mag_lower(bm, z); mag_rsqrt(bm, bm); /* upper or lower half plane */ if (arb_is_nonnegative(acb_imagref(z)) || arb_is_negative(acb_imagref(z))) { if (arb_is_nonnegative(acb_realref(z))) { arb_get_mag_lower(ax, acb_realref(z)); arb_get_mag(ay, acb_imagref(z)); arb_get_mag(bx, acb_realref(z)); arb_get_mag_lower(by, acb_imagref(z)); mag_rsqrt_re_quadrant2_lower(cx, bx, by); mag_rsqrt_re_quadrant2_upper(dx, ax, ay); /* equivalent but more expensive than pythagoras mag_rsqrt_re_quadrant1_lower(ax, ax, ay); mag_rsqrt_re_quadrant1_upper(bx, bx, by); */ mag_mul(ax, dx, dx); mag_sub_lower(ax, one, ax); mag_sqrt_lower(ax, ax); mag_mul_lower(bx, cx, cx); mag_sub(bx, one, bx); mag_sqrt(bx, bx); } else { if (arb_is_nonpositive(acb_realref(z))) { arb_get_mag(ax, acb_realref(z)); arb_get_mag_lower(ay, acb_imagref(z)); arb_get_mag_lower(bx, acb_realref(z)); arb_get_mag(by, acb_imagref(z)); /* equivalent but more expensive than pythagoras mag_rsqrt_re_quadrant1_lower(cx, bx, by); mag_rsqrt_re_quadrant1_upper(dx, ax, ay); */ mag_rsqrt_re_quadrant2_lower(ax, ax, ay); mag_rsqrt_re_quadrant2_upper(bx, bx, by); } else if (arf_sgn(arb_midref(acb_realref(z))) >= 0) { arb_get_mag_reverse(ax, acb_realref(z)); arb_get_mag_lower(ay, acb_imagref(z)); arb_get_mag(bx, acb_realref(z)); arb_get_mag_lower(by, acb_imagref(z)); mag_rsqrt_re_quadrant2_lower(ax, ax, ay); mag_rsqrt_re_quadrant1_upper(bx, bx, by); } else { arb_get_mag(ax, acb_realref(z)); arb_get_mag_lower(ay, acb_imagref(z)); arb_get_mag_reverse(bx, acb_realref(z)); arb_get_mag_lower(by, acb_imagref(z)); mag_rsqrt_re_quadrant2_lower(ax, ax, ay); mag_rsqrt_re_quadrant1_upper(bx, bx, by); } /* pythagoras */ mag_mul(cx, bx, bx); mag_sub_lower(cx, one, bx); mag_sqrt_lower(cx, cx); mag_mul_lower(dx, ax, ax); mag_sub(dx, one, dx); mag_sqrt(dx, dx); } mag_mul_lower(ax, ax, am); mag_mul_lower(cx, cx, am); mag_mul(bx, bx, bm); mag_mul(dx, dx, bm); if (arf_sgn(arb_midref(acb_imagref(z))) > 0) { arb_set_interval_mag(acb_realref(res), ax, bx, prec); arb_set_interval_mag(acb_imagref(res), cx, dx, prec); arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(res))); } else { arb_set_interval_mag(acb_realref(res), ax, bx, prec); arb_set_interval_mag(acb_imagref(res), cx, dx, prec); } } else if (arb_is_positive(acb_realref(z))) { /* right half plane, straddling real line */ int symmetric; symmetric = arf_is_zero(arb_midref(acb_imagref(z))); arb_get_mag_lower(ax, acb_realref(z)); arb_get_mag(dy, acb_imagref(z)); arb_get_mag_reverse(cy, acb_imagref(z)); if (!symmetric) mag_rsqrt_re_quadrant2_lower(cx, ax, cy); mag_rsqrt_re_quadrant2_upper(dx, ax, dy); mag_one(bx); /* mag_rsqrt_re_quadrant1_lower(ax, ax, dy); */ mag_mul(ax, dx, dx); mag_sub_lower(ax, one, ax); mag_sqrt_lower(ax, ax); mag_mul_lower(ax, ax, am); mag_mul(bx, bx, bm); mag_mul(cx, cx, bm); mag_mul(dx, dx, bm); if (symmetric) arb_set_interval_neg_pos_mag(acb_imagref(res), dx, dx, prec); else if (arf_sgn(arb_midref(acb_imagref(z))) > 0) arb_set_interval_neg_pos_mag(acb_imagref(res), dx, cx, prec); else arb_set_interval_neg_pos_mag(acb_imagref(res), cx, dx, prec); arb_set_interval_mag(acb_realref(res), ax, bx, prec); } else /* left half plane, straddling branch cut */ { mag_zero(ax); arb_get_mag_lower(bx, acb_realref(z)); arb_get_mag(by, acb_imagref(z)); mag_rsqrt_re_quadrant2_upper(bx, bx, by); mag_mul_lower(ax, ax, am); mag_mul(bx, bx, bm); arb_set_interval_mag(acb_realref(res), ax, bx, prec); /* cx, dx = 1,1 */ arb_set_interval_neg_pos_mag(acb_imagref(res), bm, bm, prec); } mag_clear(ax); mag_clear(ay); mag_clear(bx); mag_clear(by); mag_clear(cx); mag_clear(cy); mag_clear(dx); mag_clear(dy); mag_clear(am); mag_clear(bm); mag_clear(one); } void acb_rsqrt_precise(acb_t y, const acb_t x, slong prec) { #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(y) #define d acb_imagref(y) arb_t r, t, u, v; slong wp; /* based on the identity sqrt(z) = sqrt(r) (z+r) / |z+r|: */ /* 1/sqrt(a+bi) = (1/v)((a+r) - b*i), r = |a+bi|, v = sqrt(r*(b^2+(a+r)^2)) */ wp = prec + 6; arb_init(r); arb_init(t); arb_init(u); arb_init(v); /* u = b^2, r = |a+bi| */ arb_mul(t, a, a, wp); arb_mul(u, b, b, wp); arb_add(r, t, u, wp); arb_sqrtpos(r, r, wp); /* t = a+r, v = r*(b^2+(a+r)^2) */ arb_add(t, r, a, wp); arb_mul(v, t, t, wp); arb_add(v, v, u, wp); arb_mul(v, v, r, wp); /* v = 1/sqrt(v) */ arb_rsqrt(v, v, wp); arb_mul(c, t, v, prec); arb_mul(d, b, v, prec); arb_neg(d, d); arb_clear(r); arb_clear(t); arb_clear(u); arb_clear(v); #undef a #undef b #undef c #undef d } void acb_rsqrt(acb_t y, const acb_t x, slong prec) { slong acc; #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(y) #define d acb_imagref(y) if (acb_contains_zero(x)) { acb_indeterminate(y); return; } if (arb_is_zero(b)) { if (arb_is_nonnegative(a)) { arb_rsqrt(c, a, prec); arb_zero(d); return; } else if (arb_is_nonpositive(a)) { arb_neg(d, a); arb_rsqrt(d, d, prec); arb_neg(d, d); arb_zero(c); return; } } if (arb_is_zero(a)) { if (arb_is_nonnegative(b)) { arb_mul_2exp_si(c, b, 1); arb_rsqrt(c, c, prec); arb_neg(d, c); return; } else if (arb_is_nonpositive(b)) { arb_mul_2exp_si(c, b, 1); arb_neg(c, c); arb_rsqrt(c, c, prec); arb_set(d, c); return; } } acc = acb_rel_accuracy_bits(x); if (acc < 25) { acb_rsqrt_wide(y, x, prec); } else { if (arb_is_positive(a)) { acb_rsqrt_precise(y, x, prec); } else if (arb_is_nonnegative(b)) { acb_neg(y, x); acb_rsqrt_precise(y, y, prec); acb_div_onei(y, y); } else if (arb_is_negative(b)) { acb_neg(y, x); acb_rsqrt_precise(y, y, prec); acb_mul_onei(y, y); } else { acb_rsqrt_wide(y, x, prec); } } #undef a #undef b #undef c #undef d } void acb_rsqrt_analytic(acb_t res, const acb_t z, int analytic, slong prec) { if (analytic && arb_contains_zero(acb_imagref(z)) && !arb_is_positive(acb_realref(z))) { acb_indeterminate(res); } else { acb_rsqrt(res, z, prec); } } flint-3.1.3/src/acb/sech.c000066400000000000000000000026551461254215100152450ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sech(acb_t res, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_sech(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } else if (arb_is_zero(acb_realref(z))) { arb_sec(acb_realref(res), acb_imagref(z), prec); arb_zero(acb_imagref(res)); } else { if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 0) > 0) { acb_t t; acb_init(t); if (arf_sgn(arb_midref(acb_realref(z))) > 0) { acb_neg(t, z); acb_exp(t, t, prec + 4); } else { acb_exp(t, z, prec + 4); } acb_mul(res, t, t, prec + 4); acb_add_ui(res, res, 1, prec + 4); acb_div(res, t, res, prec); acb_mul_2exp_si(res, res, 1); acb_clear(t); } else { acb_cosh(res, z, prec + 4); acb_inv(res, res, prec); } } } flint-3.1.3/src/acb/sgn.c000066400000000000000000000022071461254215100151030ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sgn(acb_t res, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_sgn(acb_realref(res), acb_realref(z)); arb_zero(acb_imagref(res)); } else if (arb_is_zero(acb_realref(z))) { arb_sgn(acb_imagref(res), acb_imagref(z)); arb_zero(acb_realref(res)); } else { arb_t t; arb_init(t); acb_abs(t, z, prec); arb_inv(t, t, prec); if (arb_is_finite(t)) { acb_mul_arb(res, z, t, prec); } else { arf_zero(arb_midref(acb_realref(res))); mag_one(arb_radref(acb_realref(res))); arb_set(acb_imagref(res), acb_realref(res)); } arb_clear(t); } } flint-3.1.3/src/acb/sin.c000066400000000000000000000022071461254215100151050ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sin(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_sin(acb_realref(r), a, prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(a)) { arb_sinh(acb_imagref(r), b, prec); arb_zero(acb_realref(r)); } else { arb_t sa, ca, sb, cb; arb_init(sa); arb_init(ca); arb_init(sb); arb_init(cb); arb_sin_cos(sa, ca, a, prec); arb_sinh_cosh(sb, cb, b, prec); arb_mul(acb_realref(r), sa, cb, prec); arb_mul(acb_imagref(r), sb, ca, prec); arb_clear(sa); arb_clear(ca); arb_clear(sb); arb_clear(cb); } #undef a #undef b } flint-3.1.3/src/acb/sin_cos.c000066400000000000000000000026211461254215100157510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sin_cos(acb_t s, acb_t c, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_sin_cos(acb_realref(s), acb_realref(c), a, prec); arb_zero(acb_imagref(s)); arb_zero(acb_imagref(c)); } else if (arb_is_zero(a)) { arb_sinh_cosh(acb_imagref(s), acb_realref(c), b, prec); arb_zero(acb_realref(s)); arb_zero(acb_imagref(c)); } else { arb_t sa, ca, sb, cb; arb_init(sa); arb_init(ca); arb_init(sb); arb_init(cb); arb_sin_cos(sa, ca, a, prec); arb_sinh_cosh(sb, cb, b, prec); arb_mul(acb_realref(s), sa, cb, prec); arb_mul(acb_imagref(s), sb, ca, prec); arb_mul(acb_realref(c), ca, cb, prec); arb_mul(acb_imagref(c), sa, sb, prec); arb_neg(acb_imagref(c), acb_imagref(c)); arb_clear(sa); arb_clear(ca); arb_clear(sb); arb_clear(cb); } #undef a #undef b } flint-3.1.3/src/acb/sin_cos_pi.c000066400000000000000000000031311461254215100164360ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sin_cos_pi(acb_t s, acb_t c, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_sin_cos_pi(acb_realref(s), acb_realref(c), a, prec); arb_zero(acb_imagref(s)); arb_zero(acb_imagref(c)); } else if (arb_is_zero(a)) { arb_t t; arb_init(t); arb_const_pi(t, prec); arb_mul(t, t, b, prec); arb_sinh_cosh(acb_imagref(s), acb_realref(c), t, prec); arb_zero(acb_realref(s)); arb_zero(acb_imagref(c)); arb_clear(t); } else { arb_t sa, ca, sb, cb; arb_init(sa); arb_init(ca); arb_init(sb); arb_init(cb); arb_const_pi(sb, prec); arb_mul(sb, sb, b, prec); arb_sin_cos_pi(sa, ca, a, prec); arb_sinh_cosh(sb, cb, sb, prec); arb_mul(acb_realref(s), sa, cb, prec); arb_mul(acb_imagref(s), sb, ca, prec); arb_mul(acb_realref(c), ca, cb, prec); arb_mul(acb_imagref(c), sa, sb, prec); arb_neg(acb_imagref(c), acb_imagref(c)); arb_clear(sa); arb_clear(ca); arb_clear(sb); arb_clear(cb); } #undef a #undef b } flint-3.1.3/src/acb/sin_pi.c000066400000000000000000000025161461254215100156000ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sin_pi(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { arb_sin_pi(acb_realref(r), a, prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(a)) { arb_t t; arb_init(t); arb_const_pi(t, prec); arb_mul(t, t, b, prec); arb_sinh(acb_imagref(r), t, prec); arb_zero(acb_realref(r)); arb_clear(t); } else { arb_t sa, ca, sb, cb; arb_init(sa); arb_init(ca); arb_init(sb); arb_init(cb); arb_sin_cos_pi(sa, ca, a, prec); arb_const_pi(cb, prec); arb_mul(cb, cb, b, prec); arb_sinh_cosh(sb, cb, cb, prec); arb_mul(acb_realref(r), sa, cb, prec); arb_mul(acb_imagref(r), sb, ca, prec); arb_clear(sa); arb_clear(ca); arb_clear(sb); arb_clear(cb); } #undef a #undef b } flint-3.1.3/src/acb/sinc.c000066400000000000000000000040701461254215100152500ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" static int _acb_is_large(const acb_t z) { int res; mag_t t; mag_init(t); acb_get_mag_lower(t, z); res = mag_cmp_2exp_si(t, 0) >= 0; mag_clear(t); return res; } static void _acb_sinc_direct(acb_t res, const acb_t z, slong prec) { if (acb_is_zero(z)) { acb_one(res); } else { acb_t t; acb_init(t); acb_sin(t, z, prec + 2); acb_div(res, t, z, prec); acb_clear(t); } } static void _acb_sinc_diffbound(acb_t res, const acb_t z, slong prec) { mag_t u, v; int isreal; mag_init(u); mag_init(v); isreal = arb_is_zero(acb_realref(z)); /* exp(|im(z)|) is a crude bound for |sinc'(z)| */ arb_get_mag(u, acb_imagref(z)); mag_hypot(v, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_exp(u, u); mag_mul(u, u, v); arf_set(arb_midref(acb_realref(res)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(z))); mag_zero(arb_radref(acb_realref(res))); mag_zero(arb_radref(acb_imagref(res))); _acb_sinc_direct(res, res, prec); if (isreal) arb_add_error_mag(acb_realref(res), u); else acb_add_error_mag(res, u); mag_clear(u); mag_clear(v); } void acb_sinc(acb_t res, const acb_t z, slong prec) { if (!acb_is_finite(z)) { acb_indeterminate(res); } else if (acb_is_real(z)) { arb_sinc(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } else if (acb_is_exact(z) || _acb_is_large(z)) { _acb_sinc_direct(res, z, prec); } else { _acb_sinc_diffbound(res, z, prec); } } flint-3.1.3/src/acb/sinc_pi.c000066400000000000000000000017251461254215100157440ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sinc_pi(acb_t res, const acb_t x, slong prec) { mag_t m; acb_t t; if (acb_is_zero(x)) { acb_one(res); return; } mag_init(m); acb_init(t); acb_get_mag_lower(m, x); if (mag_cmp_2exp_si(m, -1) > 0) { acb_const_pi(t, prec + 4); acb_mul(t, t, x, prec + 4); acb_sin_pi(res, x, prec + 4); acb_div(res, res, t, prec); } else { acb_const_pi(t, prec + 4); acb_mul(t, t, x, prec + 4); acb_sinc(res, t, prec); } mag_clear(m); acb_clear(t); } flint-3.1.3/src/acb/sqrt.c000066400000000000000000000071451461254215100153130ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sqrt(acb_t y, const acb_t x, slong prec) { arb_t r, t, u; slong wp; int done; #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(y) #define d acb_imagref(y) if (arb_is_zero(b)) { if (arb_is_nonnegative(a)) { arb_sqrt(c, a, prec); arb_zero(d); return; } else if (arb_is_nonpositive(a)) { arb_neg(d, a); arb_sqrt(d, d, prec); arb_zero(c); return; } } if (arb_is_zero(a)) { if (arb_is_nonnegative(b)) { arb_mul_2exp_si(c, b, -1); arb_sqrt(c, c, prec); arb_set(d, c); return; } else if (arb_is_nonpositive(b)) { arb_mul_2exp_si(c, b, -1); arb_neg(c, c); arb_sqrt(c, c, prec); arb_neg(d, c); return; } } wp = prec + 4; arb_init(r); arb_init(t); arb_init(u); /* r = |a+bi| */ acb_abs(r, x, wp); done = 0; if (arf_sgn(arb_midref(a)) >= 0) { arb_add(t, r, a, wp); if (arb_rel_accuracy_bits(t) > 8) { /* sqrt(a+bi) = sqrt((r+a)/2) + b/sqrt(2*(r+a))*i */ arb_mul_2exp_si(u, t, 1); arb_sqrt(u, u, wp); arb_div(d, b, u, prec); arb_set_round(c, u, prec); arb_mul_2exp_si(c, c, -1); done = 1; } else { arb_sub(u, r, a, wp); } } else if (!arb_contains_zero(b)) { arb_sub(u, r, a, wp); if (arb_rel_accuracy_bits(u) > 8) { /* sqrt(a+bi) = |b|/sqrt(2*(r-a)) + sgn(b)*sqrt((r-a)/2)*i */ int sgn = arf_sgn(arb_midref(b)); arb_mul_2exp_si(t, u, 1); arb_sqrt(t, t, wp); arb_div(c, b, t, prec); arb_abs(c, c); arb_set_round(d, t, prec); arb_mul_2exp_si(d, d, -1); if (sgn < 0) arb_neg(d, d); done = 1; } else { arb_add(t, r, a, wp); } } else { arb_add(t, r, a, wp); arb_sub(u, r, a, wp); } /* t = r+a, u = r-a */ if (!done) { /* sqrt(a+bi) = sqrt((r+a)/2) + (b/|b|)*sqrt((r-a)/2)*i (sign) */ arb_mul_2exp_si(t, t, -1); arb_mul_2exp_si(u, u, -1); arb_sqrtpos(c, t, prec); if (arb_is_nonnegative(b)) { arb_sqrtpos(d, u, prec); } else if (arb_is_nonpositive(b)) { arb_sqrtpos(d, u, prec); arb_neg(d, d); } else { arb_sqrtpos(t, u, wp); arb_neg(u, t); arb_union(d, t, u, prec); } } arb_clear(r); arb_clear(t); arb_clear(u); #undef a #undef b #undef c #undef d } void acb_sqrt_analytic(acb_t res, const acb_t z, int analytic, slong prec) { if (analytic && arb_contains_zero(acb_imagref(z)) && !arb_is_positive(acb_realref(z))) { acb_indeterminate(res); } else { acb_sqrt(res, z, prec); } } flint-3.1.3/src/acb/sqrts.c000066400000000000000000000016111461254215100154660ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_sqrts(acb_t y1, acb_t y2, const acb_t x, slong prec) { if (acb_contains_zero(x)) { acb_sqrt(y1, x, prec); acb_neg(y2, y1); acb_union(y1, y1, y2, prec); acb_set(y2, y1); } else if (arb_contains_zero(acb_imagref(x)) && arb_is_negative(acb_realref(x))) { acb_neg(y1, x); acb_sqrt(y1, y1, prec); acb_mul_onei(y1, y1); acb_neg(y2, y1); } else { acb_sqrt(y1, x, prec); acb_neg(y2, y1); } } flint-3.1.3/src/acb/submul.c000066400000000000000000000017701461254215100156270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_submul(acb_t z, const acb_t x, const acb_t y, slong prec) { if (arb_is_zero(acb_imagref(y))) { arb_submul(acb_imagref(z), acb_imagref(x), acb_realref(y), prec); arb_submul(acb_realref(z), acb_realref(x), acb_realref(y), prec); } else if (arb_is_zero(acb_imagref(x))) { arb_submul(acb_imagref(z), acb_imagref(y), acb_realref(x), prec); arb_submul(acb_realref(z), acb_realref(y), acb_realref(x), prec); } else { acb_t t; acb_init(t); acb_mul(t, x, y, prec); acb_sub(z, z, t, prec); acb_clear(t); } } flint-3.1.3/src/acb/tan.c000066400000000000000000000033461461254215100151030ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_tan(acb_t r, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_tan(acb_realref(r), acb_realref(z), prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(acb_realref(z))) { arb_tanh(acb_imagref(r), acb_imagref(z), prec); arb_zero(acb_realref(r)); } else { acb_t t; acb_init(t); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0) { acb_sin_cos(r, t, z, prec + 4); acb_div(r, r, t, prec); } else { acb_mul_2exp_si(t, z, 1); if (arf_sgn(arb_midref(acb_imagref(z))) > 0) { acb_mul_onei(t, t); acb_exp(t, t, prec + 4); acb_add_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_div_onei(r, r); } else { acb_div_onei(t, t); acb_exp(t, t, prec + 4); acb_add_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_mul_onei(r, r); } } acb_clear(t); } } flint-3.1.3/src/acb/tan_pi.c000066400000000000000000000035231461254215100155700ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_tan_pi(acb_t r, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_tan_pi(acb_realref(r), acb_realref(z), prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(acb_realref(z))) { arb_t t; arb_init(t); arb_const_pi(t, prec + 4); arb_mul(t, acb_imagref(z), t, prec + 4); arb_tanh(acb_imagref(r), t, prec); arb_zero(acb_realref(r)); arb_clear(t); } else { acb_t t; acb_init(t); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0) { acb_sin_cos_pi(r, t, z, prec + 4); acb_div(r, r, t, prec); } else { acb_mul_2exp_si(t, z, 1); if (arf_sgn(arb_midref(acb_imagref(z))) > 0) { acb_exp_pi_i(t, t, prec + 4); acb_add_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_div_onei(r, r); } else { acb_neg(t, t); acb_exp_pi_i(t, t, prec + 4); acb_add_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_mul_onei(r, r); } } acb_clear(t); } } flint-3.1.3/src/acb/test/000077500000000000000000000000001461254215100151265ustar00rootroot00000000000000flint-3.1.3/src/acb/test/main.c000066400000000000000000000113131461254215100162150ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-acos.c" #include "t-acosh.c" #include "t-agm1.c" #include "t-agm.c" #include "t-approx_dot.c" #include "t-asin.c" #include "t-asinh.c" #include "t-atan.c" #include "t-atanh.c" #include "t-barnes_g.c" #include "t-bernoulli_poly_ui.c" #include "t-chebyshev_t_ui.c" #include "t-chebyshev_u_ui.c" #include "t-cos_pi.c" #include "t-cot.c" #include "t-coth.c" #include "t-cot_pi.c" #include "t-csc.c" #include "t-csch.c" #include "t-csc_pi.c" #include "t-csgn.c" #include "t-digamma.c" #include "t-div.c" #include "t-dot.c" #include "t-dot_fmpz.c" #include "t-dot_si.c" #include "t-dot_siui.c" #include "t-dot_ui.c" #include "t-dot_uiui.c" #include "t-exp.c" #include "t-exp_invexp.c" #include "t-expm1.c" #include "t-exp_pi_i.c" #include "t-gamma.c" #include "t-get_abs_lbound_arf.c" #include "t-get_abs_ubound_arf.c" #include "t-get_mag.c" #include "t-get_mag_lower.c" #include "t-inv.c" #include "t-lambertw.c" #include "t-lgamma.c" #include "t-log1p.c" #include "t-log.c" #include "t-log_sin_pi.c" #include "t-mul.c" #include "t-mul_naive.c" #include "t-polygamma.c" #include "t-pow.c" #include "t-pow_fmpz.c" #include "t-quadratic_roots_fmpz.c" #include "t-rel_accuracy_bits.c" #include "t-rgamma.c" #include "t-rising2_ui.c" #include "t-rising_ui.c" #include "t-rising_ui_get_mag.c" #include "t-root_ui.c" #include "t-rsqrt.c" #include "t-sec.c" #include "t-sech.c" #include "t-sgn.c" #include "t-sinc.c" #include "t-sin_cos.c" #include "t-sinc_pi.c" #include "t-sinh_cosh.c" #include "t-sin_pi.c" #include "t-sqrt.c" #include "t-sqrts.c" #include "t-tan.c" #include "t-tanh.c" #include "t-tan_pi.c" #include "t-urandom.c" #include "t-vec_set_real_imag.c" #include "t-vec_unit_roots.c" #include "t-zeta.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_acos), TEST_FUNCTION(acb_acosh), TEST_FUNCTION(acb_agm1), TEST_FUNCTION(acb_agm), TEST_FUNCTION(acb_approx_dot), TEST_FUNCTION(acb_asin), TEST_FUNCTION(acb_asinh), TEST_FUNCTION(acb_atan), TEST_FUNCTION(acb_atanh), TEST_FUNCTION(acb_barnes_g), TEST_FUNCTION(acb_bernoulli_poly_ui), TEST_FUNCTION(acb_chebyshev_t_ui), TEST_FUNCTION(acb_chebyshev_u_ui), TEST_FUNCTION(acb_cos_pi), TEST_FUNCTION(acb_cot), TEST_FUNCTION(acb_coth), TEST_FUNCTION(acb_cot_pi), TEST_FUNCTION(acb_csc), TEST_FUNCTION(acb_csch), TEST_FUNCTION(acb_csc_pi), TEST_FUNCTION(acb_csgn), TEST_FUNCTION(acb_digamma), TEST_FUNCTION(acb_div), TEST_FUNCTION(acb_dot), TEST_FUNCTION(acb_dot_fmpz), TEST_FUNCTION(acb_dot_si), TEST_FUNCTION(acb_dot_siui), TEST_FUNCTION(acb_dot_ui), TEST_FUNCTION(acb_dot_uiui), TEST_FUNCTION(acb_exp), TEST_FUNCTION(acb_exp_invexp), TEST_FUNCTION(acb_expm1), TEST_FUNCTION(acb_exp_pi_i), TEST_FUNCTION(acb_gamma), TEST_FUNCTION(acb_get_abs_lbound_arf), TEST_FUNCTION(acb_get_abs_ubound_arf), TEST_FUNCTION(acb_get_mag), TEST_FUNCTION(acb_get_mag_lower), TEST_FUNCTION(acb_inv), TEST_FUNCTION(acb_lambertw), TEST_FUNCTION(acb_lgamma), TEST_FUNCTION(acb_log1p), TEST_FUNCTION(acb_log), TEST_FUNCTION(acb_log_sin_pi), TEST_FUNCTION(acb_mul), TEST_FUNCTION(acb_mul_naive), TEST_FUNCTION(acb_polygamma), TEST_FUNCTION(acb_pow), TEST_FUNCTION(acb_pow_fmpz), TEST_FUNCTION(acb_quadratic_roots_fmpz), TEST_FUNCTION(acb_rel_accuracy_bits), TEST_FUNCTION(acb_rgamma), TEST_FUNCTION(acb_rising2_ui), TEST_FUNCTION(acb_rising_ui), TEST_FUNCTION(acb_rising_ui_get_mag), TEST_FUNCTION(acb_root_ui), TEST_FUNCTION(acb_rsqrt), TEST_FUNCTION(acb_sec), TEST_FUNCTION(acb_sech), TEST_FUNCTION(acb_sgn), TEST_FUNCTION(acb_sinc), TEST_FUNCTION(acb_sin_cos), TEST_FUNCTION(acb_sinc_pi), TEST_FUNCTION(acb_sinh_cosh), TEST_FUNCTION(acb_sin_pi), TEST_FUNCTION(acb_sqrt), TEST_FUNCTION(acb_sqrts), TEST_FUNCTION(acb_tan), TEST_FUNCTION(acb_tanh), TEST_FUNCTION(acb_tan_pi), TEST_FUNCTION(acb_urandom), TEST_FUNCTION(acb_vec_set_real_imag), TEST_FUNCTION(acb_vec_unit_roots), TEST_FUNCTION(acb_zeta) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb/test/t-acos.c000066400000000000000000000043221461254215100164610ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_acos, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_acos(a, x, prec1); acb_acos(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check cos(acos(x)) = x */ acb_cos(b, b, prec1); if (!acb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_acos(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-acosh.c000066400000000000000000000043311461254215100166310ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_acosh, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_acosh(a, x, prec1); acb_acosh(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check cosh(acosh(x)) = x */ acb_cosh(b, b, prec1); if (!acb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_acosh(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-agm.c000066400000000000000000000464041461254215100163070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #define NUM_TESTS 256 const double agm_testdata[NUM_TESTS][6] = { {-1, -1, -1, -1, -1.00000000000000, -1.00000000000000}, {-1, -1, -1, 0, -1.04916052873278, -0.478155746088161}, {-1, -1, -1, 1, -1.19814023473559, 0.000000000000000}, {-1, -1, -1, 2, -1.35980258211696, 0.412918513270561}, {-1, -1, 0, -1, -0.478155746088161, -1.04916052873278}, {-1, -1, 0, 0, 0.000000000000000, 0.000000000000000}, {-1, -1, 0, 1, -0.778004078788958, 0.188411067988680}, {-1, -1, 0, 2, -0.966415146777638, 0.589593010800278}, {-1, -1, 1, -1, 0.000000000000000, -1.19814023473559}, {-1, -1, 1, 0, 0.188411067988680, -0.778004078788958}, {-1, -1, 1, 1, 0.000000000000000, 0.000000000000000}, {-1, -1, 1, 2, -0.574659643809835, 0.810208383866421}, {-1, -1, 2, -1, 0.412918513270561, -1.35980258211696}, {-1, -1, 2, 0, 0.589593010800278, -0.966415146777638}, {-1, -1, 2, 1, 0.810208383866421, -0.574659643809835}, {-1, -1, 2, 2, 1.08423239187061, -0.238299975053003}, {-1, 0, -1, -1, -1.04916052873278, -0.478155746088161}, {-1, 0, -1, 0, -1.00000000000000, 0.000000000000000}, {-1, 0, -1, 1, -1.04916052873278, 0.478155746088161}, {-1, 0, -1, 2, -1.13815978557677, 0.897764105638205}, {-1, 0, 0, -1, -0.599070117367796, -0.599070117367796}, {-1, 0, 0, 0, 0.000000000000000, 0.000000000000000}, {-1, 0, 0, 1, -0.599070117367796, 0.599070117367796}, {-1, 0, 0, 2, -0.742646422399778, 1.01005159361958}, {-1, 0, 1, -1, -0.188411067988680, -0.778004078788958}, {-1, 0, 1, 0, 0.000000000000000, 0.000000000000000}, {-1, 0, 1, 1, -0.188411067988680, 0.778004078788958}, {-1, 0, 1, 2, -0.363823969691055, 1.15631976909117}, {-1, 0, 2, -1, 0.178866979357132, -0.985872907297986}, {-1, 0, 2, 0, 0.422966208408802, 0.661266183461805}, {-1, 0, 2, 1, 0.178866979357132, 0.985872907297986}, {-1, 0, 2, 2, -0.0126420344317752, 1.32391495927282}, {-1, 1, -1, -1, -1.19814023473559, 0.000000000000000}, {-1, 1, -1, 0, -1.04916052873278, 0.478155746088161}, {-1, 1, -1, 1, -1.00000000000000, 1.00000000000000}, {-1, 1, -1, 2, -1.02005412633766, 1.47134936286465}, {-1, 1, 0, -1, -0.778004078788958, -0.188411067988680}, {-1, 1, 0, 0, 0.000000000000000, 0.000000000000000}, {-1, 1, 0, 1, -0.478155746088161, 1.04916052873278}, {-1, 1, 0, 2, -0.571004782644619, 1.52731627482094}, {-1, 1, 1, -1, 0.000000000000000, 0.000000000000000}, {-1, 1, 1, 0, 0.188411067988680, 0.778004078788958}, {-1, 1, 1, 1, 0.000000000000000, 1.19814023473559}, {-1, 1, 1, 2, -0.136827548397369, 1.62780548487271}, {-1, 1, 2, -1, 0.810208383866421, 0.574659643809835}, {-1, 1, 2, 0, 0.589593010800278, 0.966415146777638}, {-1, 1, 2, 1, 0.412918513270561, 1.35980258211696}, {-1, 1, 2, 2, 0.267405171219803, 1.75269801601936}, {-1, 2, -1, -1, -1.35980258211696, 0.412918513270561}, {-1, 2, -1, 0, -1.13815978557677, 0.897764105638205}, {-1, 2, -1, 1, -1.02005412633766, 1.47134936286465}, {-1, 2, -1, 2, -1.00000000000000, 2.00000000000000}, {-1, 2, 0, -1, -0.985872907297986, 0.178866979357132}, {-1, 2, 0, 0, 0.000000000000000, 0.000000000000000}, {-1, 2, 0, 1, -0.420983902077155, 1.47839688785392}, {-1, 2, 0, 2, -0.493004461502931, 2.02900451838781}, {-1, 2, 1, -1, 0.574659643809835, 0.810208383866421}, {-1, 2, 1, 0, 0.363823969691055, 1.15631976909117}, {-1, 2, 1, 1, 0.136827548397369, 1.62780548487271}, {-1, 2, 1, 2, 0.000000000000000, 2.11638793788003}, {-1, 2, 2, -1, 0.963366302386887, 0.963366302386887}, {-1, 2, 2, 0, 0.777111977967075, 1.37110999239961}, {-1, 2, 2, 1, 0.599070117367796, 1.79721035210339}, {-1, 2, 2, 2, 0.455159607692816, 2.23571522629432}, {0, -1, -1, -1, -0.478155746088161, -1.04916052873278}, {0, -1, -1, 0, -0.599070117367796, -0.599070117367796}, {0, -1, -1, 1, -0.778004078788958, -0.188411067988680}, {0, -1, -1, 2, -0.985872907297986, 0.178866979357132}, {0, -1, 0, -1, 0.000000000000000, -1.00000000000000}, {0, -1, 0, 0, 0.000000000000000, 0.000000000000000}, {0, -1, 0, 1, 0.000000000000000, 0.000000000000000}, {0, -1, 0, 2, 0.661266183461805, 0.422966208408802}, {0, -1, 1, -1, 0.478155746088161, -1.04916052873278}, {0, -1, 1, 0, 0.599070117367796, -0.599070117367796}, {0, -1, 1, 1, 0.778004078788958, -0.188411067988680}, {0, -1, 1, 2, 0.985872907297986, 0.178866979357132}, {0, -1, 2, -1, 0.897764105638205, -1.13815978557677}, {0, -1, 2, 0, 1.01005159361958, -0.742646422399778}, {0, -1, 2, 1, 1.15631976909117, -0.363823969691055}, {0, -1, 2, 2, 1.32391495927282, -0.0126420344317752}, {0, 0, -1, -1, 0.000000000000000, 0.000000000000000}, {0, 0, -1, 0, 0.000000000000000, 0.000000000000000}, {0, 0, -1, 1, 0.000000000000000, 0.000000000000000}, {0, 0, -1, 2, 0.000000000000000, 0.000000000000000}, {0, 0, 0, -1, 0.000000000000000, 0.000000000000000}, {0, 0, 0, 0, 0.000000000000000, 0.000000000000000}, {0, 0, 0, 1, 0.000000000000000, 0.000000000000000}, {0, 0, 0, 2, 0.000000000000000, 0.000000000000000}, {0, 0, 1, -1, 0.000000000000000, 0.000000000000000}, {0, 0, 1, 0, 0.000000000000000, 0.000000000000000}, {0, 0, 1, 1, 0.000000000000000, 0.000000000000000}, {0, 0, 1, 2, 0.000000000000000, 0.000000000000000}, {0, 0, 2, -1, 0.000000000000000, 0.000000000000000}, {0, 0, 2, 0, 0.000000000000000, 0.000000000000000}, {0, 0, 2, 1, 0.000000000000000, 0.000000000000000}, {0, 0, 2, 2, 0.000000000000000, 0.000000000000000}, {0, 1, -1, -1, -0.778004078788958, 0.188411067988680}, {0, 1, -1, 0, -0.599070117367796, 0.599070117367796}, {0, 1, -1, 1, -0.478155746088161, 1.04916052873278}, {0, 1, -1, 2, -0.420983902077155, 1.47839688785392}, {0, 1, 0, -1, 0.000000000000000, 0.000000000000000}, {0, 1, 0, 0, 0.000000000000000, 0.000000000000000}, {0, 1, 0, 1, 0.000000000000000, 1.00000000000000}, {0, 1, 0, 2, 0.000000000000000, 1.45679103104691}, {0, 1, 1, -1, 0.778004078788958, 0.188411067988680}, {0, 1, 1, 0, 0.599070117367796, 0.599070117367796}, {0, 1, 1, 1, 0.478155746088161, 1.04916052873278}, {0, 1, 1, 2, 0.420983902077155, 1.47839688785392}, {0, 1, 2, -1, 1.15631976909117, 0.363823969691055}, {0, 1, 2, 0, 1.01005159361958, 0.742646422399778}, {0, 1, 2, 1, 0.897764105638205, 1.13815978557677}, {0, 1, 2, 2, 0.820905313474926, 1.53147158277780}, {0, 2, -1, -1, -0.966415146777638, 0.589593010800278}, {0, 2, -1, 0, -0.742646422399778, 1.01005159361958}, {0, 2, -1, 1, -0.571004782644619, 1.52731627482094}, {0, 2, -1, 2, -0.493004461502931, 2.02900451838781}, {0, 2, 0, -1, 0.661266183461805, 0.422966208408802}, {0, 2, 0, 0, 0.000000000000000, 0.000000000000000}, {0, 2, 0, 1, 0.000000000000000, 1.45679103104691}, {0, 2, 0, 2, 0.000000000000000, 2.00000000000000}, {0, 2, 1, -1, 0.966415146777638, 0.589593010800278}, {0, 2, 1, 0, 0.742646422399778, 1.01005159361958}, {0, 2, 1, 1, 0.571004782644619, 1.52731627482094}, {0, 2, 1, 2, 0.493004461502931, 2.02900451838781}, {0, 2, 2, -1, 1.37110999239961, 0.777111977967075}, {0, 2, 2, 0, 1.19814023473559, 1.19814023473559}, {0, 2, 2, 1, 1.05542091981433, 1.64623191253177}, {0, 2, 2, 2, 0.956311492176322, 2.09832105746556}, {1, -1, -1, -1, 0.000000000000000, -1.19814023473559}, {1, -1, -1, 0, -0.188411067988680, -0.778004078788958}, {1, -1, -1, 1, 0.000000000000000, 0.000000000000000}, {1, -1, -1, 2, 0.574659643809835, 0.810208383866421}, {1, -1, 0, -1, 0.478155746088161, -1.04916052873278}, {1, -1, 0, 0, 0.000000000000000, 0.000000000000000}, {1, -1, 0, 1, 0.778004078788958, 0.188411067988680}, {1, -1, 0, 2, 0.966415146777638, 0.589593010800278}, {1, -1, 1, -1, 1.00000000000000, -1.00000000000000}, {1, -1, 1, 0, 1.04916052873278, -0.478155746088161}, {1, -1, 1, 1, 1.19814023473559, 0.000000000000000}, {1, -1, 1, 2, 1.35980258211696, 0.412918513270561}, {1, -1, 2, -1, 1.47134936286465, -1.02005412633766}, {1, -1, 2, 0, 1.52731627482094, -0.571004782644619}, {1, -1, 2, 1, 1.62780548487271, -0.136827548397369}, {1, -1, 2, 2, 1.75269801601936, 0.267405171219803}, {1, 0, -1, -1, 0.188411067988680, -0.778004078788958}, {1, 0, -1, 0, 0.000000000000000, 0.000000000000000}, {1, 0, -1, 1, 0.188411067988680, 0.778004078788958}, {1, 0, -1, 2, 0.363823969691055, 1.15631976909117}, {1, 0, 0, -1, 0.599070117367796, -0.599070117367796}, {1, 0, 0, 0, 0.000000000000000, 0.000000000000000}, {1, 0, 0, 1, 0.599070117367796, 0.599070117367796}, {1, 0, 0, 2, 0.742646422399778, 1.01005159361958}, {1, 0, 1, -1, 1.04916052873278, -0.478155746088161}, {1, 0, 1, 0, 1.00000000000000, 0.000000000000000}, {1, 0, 1, 1, 1.04916052873278, 0.478155746088161}, {1, 0, 1, 2, 1.13815978557677, 0.897764105638205}, {1, 0, 2, -1, 1.47839688785392, -0.420983902077155}, {1, 0, 2, 0, 1.45679103104691, 0.000000000000000}, {1, 0, 2, 1, 1.47839688785392, 0.420983902077155}, {1, 0, 2, 2, 1.53147158277780, 0.820905313474926}, {1, 1, -1, -1, 0.000000000000000, 0.000000000000000}, {1, 1, -1, 0, -0.188411067988680, 0.778004078788958}, {1, 1, -1, 1, 0.000000000000000, 1.19814023473559}, {1, 1, -1, 2, 0.136827548397369, 1.62780548487271}, {1, 1, 0, -1, 0.778004078788958, -0.188411067988680}, {1, 1, 0, 0, 0.000000000000000, 0.000000000000000}, {1, 1, 0, 1, 0.478155746088161, 1.04916052873278}, {1, 1, 0, 2, 0.571004782644619, 1.52731627482094}, {1, 1, 1, -1, 1.19814023473559, 0.000000000000000}, {1, 1, 1, 0, 1.04916052873278, 0.478155746088161}, {1, 1, 1, 1, 1.00000000000000, 1.00000000000000}, {1, 1, 1, 2, 1.02005412633766, 1.47134936286465}, {1, 1, 2, -1, 1.62780548487271, 0.136827548397369}, {1, 1, 2, 0, 1.52731627482094, 0.571004782644619}, {1, 1, 2, 1, 1.47134936286465, 1.02005412633766}, {1, 1, 2, 2, 1.45679103104691, 1.45679103104691}, {1, 2, -1, -1, -0.574659643809835, 0.810208383866421}, {1, 2, -1, 0, -0.363823969691055, 1.15631976909117}, {1, 2, -1, 1, -0.136827548397369, 1.62780548487271}, {1, 2, -1, 2, 0.000000000000000, 2.11638793788003}, {1, 2, 0, -1, 0.985872907297986, 0.178866979357132}, {1, 2, 0, 0, 0.000000000000000, 0.000000000000000}, {1, 2, 0, 1, 0.420983902077155, 1.47839688785392}, {1, 2, 0, 2, 0.493004461502931, 2.02900451838781}, {1, 2, 1, -1, 1.35980258211696, 0.412918513270561}, {1, 2, 1, 0, 1.13815978557677, 0.897764105638205}, {1, 2, 1, 1, 1.02005412633766, 1.47134936286465}, {1, 2, 1, 2, 1.00000000000000, 2.00000000000000}, {1, 2, 2, -1, 1.79721035210339, 0.599070117367796}, {1, 2, 2, 0, 1.64623191253177, 1.05542091981433}, {1, 2, 2, 1, 1.54030226799894, 1.54030226799894}, {1, 2, 2, 2, 1.48529284479956, 2.02010318723916}, {2, -1, -1, -1, 0.412918513270561, -1.35980258211696}, {2, -1, -1, 0, 0.178866979357132, -0.985872907297986}, {2, -1, -1, 1, 0.810208383866421, 0.574659643809835}, {2, -1, -1, 2, 0.963366302386887, 0.963366302386887}, {2, -1, 0, -1, 0.897764105638205, -1.13815978557677}, {2, -1, 0, 0, 0.000000000000000, 0.000000000000000}, {2, -1, 0, 1, 1.15631976909117, 0.363823969691055}, {2, -1, 0, 2, 1.37110999239961, 0.777111977967075}, {2, -1, 1, -1, 1.47134936286465, -1.02005412633766}, {2, -1, 1, 0, 1.47839688785392, -0.420983902077155}, {2, -1, 1, 1, 1.62780548487271, 0.136827548397369}, {2, -1, 1, 2, 1.79721035210339, 0.599070117367796}, {2, -1, 2, -1, 2.00000000000000, -1.00000000000000}, {2, -1, 2, 0, 2.02900451838781, -0.493004461502931}, {2, -1, 2, 1, 2.11638793788003, 0.000000000000000}, {2, -1, 2, 2, 2.23571522629432, 0.455159607692816}, {2, 0, -1, -1, 0.589593010800278, -0.966415146777638}, {2, 0, -1, 0, 0.422966208408802, 0.661266183461805}, {2, 0, -1, 1, 0.589593010800278, 0.966415146777638}, {2, 0, -1, 2, 0.777111977967075, 1.37110999239961}, {2, 0, 0, -1, 1.01005159361958, -0.742646422399778}, {2, 0, 0, 0, 0.000000000000000, 0.000000000000000}, {2, 0, 0, 1, 1.01005159361958, 0.742646422399778}, {2, 0, 0, 2, 1.19814023473559, 1.19814023473559}, {2, 0, 1, -1, 1.52731627482094, -0.571004782644619}, {2, 0, 1, 0, 1.45679103104691, 0.000000000000000}, {2, 0, 1, 1, 1.52731627482094, 0.571004782644619}, {2, 0, 1, 2, 1.64623191253177, 1.05542091981433}, {2, 0, 2, -1, 2.02900451838781, -0.493004461502931}, {2, 0, 2, 0, 2.00000000000000, 0.000000000000000}, {2, 0, 2, 1, 2.02900451838781, 0.493004461502931}, {2, 0, 2, 2, 2.09832105746556, 0.956311492176322}, {2, 1, -1, -1, 0.810208383866421, -0.574659643809835}, {2, 1, -1, 0, 0.178866979357132, 0.985872907297986}, {2, 1, -1, 1, 0.412918513270561, 1.35980258211696}, {2, 1, -1, 2, 0.599070117367796, 1.79721035210339}, {2, 1, 0, -1, 1.15631976909117, -0.363823969691055}, {2, 1, 0, 0, 0.000000000000000, 0.000000000000000}, {2, 1, 0, 1, 0.897764105638205, 1.13815978557677}, {2, 1, 0, 2, 1.05542091981433, 1.64623191253177}, {2, 1, 1, -1, 1.62780548487271, -0.136827548397369}, {2, 1, 1, 0, 1.47839688785392, 0.420983902077155}, {2, 1, 1, 1, 1.47134936286465, 1.02005412633766}, {2, 1, 1, 2, 1.54030226799894, 1.54030226799894}, {2, 1, 2, -1, 2.11638793788003, 0.000000000000000}, {2, 1, 2, 0, 2.02900451838781, 0.493004461502931}, {2, 1, 2, 1, 2.00000000000000, 1.00000000000000}, {2, 1, 2, 2, 2.02010318723916, 1.48529284479956}, {2, 2, -1, -1, 1.08423239187061, -0.238299975053003}, {2, 2, -1, 0, -0.0126420344317752, 1.32391495927282}, {2, 2, -1, 1, 0.267405171219803, 1.75269801601936}, {2, 2, -1, 2, 0.455159607692816, 2.23571522629432}, {2, 2, 0, -1, 1.32391495927282, -0.0126420344317752}, {2, 2, 0, 0, 0.000000000000000, 0.000000000000000}, {2, 2, 0, 1, 0.820905313474926, 1.53147158277780}, {2, 2, 0, 2, 0.956311492176322, 2.09832105746556}, {2, 2, 1, -1, 1.75269801601936, 0.267405171219803}, {2, 2, 1, 0, 1.53147158277780, 0.820905313474926}, {2, 2, 1, 1, 1.45679103104691, 1.45679103104691}, {2, 2, 1, 2, 1.48529284479956, 2.02010318723916}, {2, 2, 2, -1, 2.23571522629432, 0.455159607692816}, {2, 2, 2, 0, 2.09832105746556, 0.956311492176322}, {2, 2, 2, 1, 2.02010318723916, 1.48529284479956}, {2, 2, 2, 2, 2.00000000000000, 2.00000000000000}, }; TEST_FUNCTION_START(acb_agm, state) { slong iter; /* test particular values against table */ { acb_t x, y, r, s; acb_init(x); acb_init(y); acb_init(r); acb_init(s); for (iter = 0; iter < NUM_TESTS; iter++) { acb_set_d_d(x, agm_testdata[iter][0], agm_testdata[iter][1]); acb_set_d_d(y, agm_testdata[iter][2], agm_testdata[iter][3]); acb_set_d_d(s, agm_testdata[iter][4], agm_testdata[iter][5]); mag_set_d(arb_radref(acb_realref(s)), 1e-13); mag_set_d(arb_radref(acb_imagref(s)), 1e-13); acb_agm(r, x, y, 64); if (!acb_overlaps(r, s)) { flint_printf("FAIL\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 15); flint_printf("\n\n"); flint_printf("r = "); acb_printd(r, 15); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(x); acb_clear(y); acb_clear(r); acb_clear(s); } /* self-consistency test */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t m1, m2; acb_t x1, x2, y1, y2, t; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); acb_init(x1); acb_init(x2); acb_init(y1); acb_init(y2); acb_init(m1); acb_init(m2); acb_init(t); acb_randtest(x1, state, prec1, 1 + n_randint(state, 100)); acb_randtest(y1, state, prec1, 1 + n_randint(state, 100)); acb_randtest(m1, state, prec1, 1 + n_randint(state, 100)); acb_randtest(m2, state, prec1, 1 + n_randint(state, 100)); if (n_randint(state, 2)) { acb_randtest(t, state, prec2, 1 + n_randint(state, 200)); acb_mul(y1, x1, t, prec1); } if (n_randint(state, 2)) acb_swap(x1, y1); if (n_randint(state, 2)) { acb_set(x2, x1); } else { acb_randtest(t, state, prec2, 1 + n_randint(state, 200)); acb_add(x2, x1, t, prec2); acb_sub(x2, x2, t, prec2); } if (n_randint(state, 2)) { acb_set(y2, y1); } else { acb_randtest(t, state, prec2, 1 + n_randint(state, 200)); acb_add(y2, y1, t, prec2); acb_sub(y2, y2, t, prec2); } acb_agm(m1, x1, y1, prec1); acb_agm(m2, x2, y2, prec2); if (!acb_overlaps(m1, m2)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("x1 = "); acb_printd(x1, 30); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 30); flint_printf("\n\n"); flint_printf("x2 = "); acb_printd(x2, 30); flint_printf("\n\n"); flint_printf("y2 = "); acb_printd(y2, 30); flint_printf("\n\n"); flint_printf("m1 = "); acb_printd(m1, 30); flint_printf("\n\n"); flint_printf("m2 = "); acb_printd(m2, 30); flint_printf("\n\n"); flint_abort(); } acb_div(t, x1, y1, prec1); if (acb_is_finite(t) && (!acb_is_real(t) || !arb_is_negative(acb_realref(t)))) { if (n_randint(state, 2)) { acb_div(t, x1, y1, prec1); acb_agm1(t, t, prec1); acb_mul(t, t, y1, prec1); } else { acb_div(t, y1, x1, prec1); acb_agm1(t, t, prec1); acb_mul(t, t, x1, prec1); } if (!acb_overlaps(t, m1)) { flint_printf("FAIL (overlap 2)\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("x1 = "); acb_printd(x1, 30); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 30); flint_printf("\n\n"); flint_printf("m1 = "); acb_printd(m1, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } } acb_clear(x1); acb_clear(x2); acb_clear(y1); acb_clear(y2); acb_clear(m1); acb_clear(m2); acb_clear(t); } TEST_FUNCTION_END(state); } #undef NUM_TESTS flint-3.1.3/src/acb/test/t-agm1.c000066400000000000000000000154541461254215100163710ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define EPS 1e-13 #define NUM_DERIVS 4 #define NUM_TESTS 11 const double agm1_testdata[NUM_TESTS][10] = { {1.0, 0.0, 1.0, 0.0, 0.5, 0.0, -0.0625, 0.0, 0.03125, 0.0}, {0.25, 0.0, 0.56075714507190064253, 0.0, 0.76633907325304843764, 0.0, -0.58010113691169132987, 0.0, 1.2991960360521313649, 0.0}, {1.0, 1.0, 1.0491605287327802205, 0.47815574608816122933, 0.44643105633549979073, -0.08043578677710866283, -0.015455284495904882924, 0.031976374729700173479, -0.005073437378084728324, -0.010673958729796444985}, {0.0, 1.0, 0.59907011736779610372, 0.59907011736779610372, 0.43640657965245804105, -0.16266353771533806267, 0.031271486774469549792, 0.031271486774469549792, -0.0084910439043492636266, 0.022780442870120286166}, {-1.0, 1.0, 0.18841106798868002055, 0.77800407878895828015, 0.39320630832295102335, -0.19287323123455182026, 0.016808115488846724979, 0.020163502567351546742, -0.011189063384352573532, -0.0045629824424054816356}, {-0.25, 0.0, 0.24392673474953340413, 0.27799893427725564501, 0.079794586546549867566, -0.32574453868033984617, -0.27530931370867131683, -0.60287933825809104112, -0.54714813521966247214, -0.97291617788393560861}, {-2.0, 0.0, -0.42296620840880168736, 0.66126618346180476447, 0.29655367830470777795, -0.27314834694816402295, 0.018331225229748304014, -0.043277191398267359935, 0.0094104572902577354423, -0.021071819981331905571}, {-0.99999994039535522461, 0.0, 0.0069953999943208591971, 0.08334545077423930704, 12454.444757282471906, 73670.447089584396744, -87884330303.90316493, -553342797575.05204396, 909784741818095264.43, 5883796037072491540.4}, {-1.0000000596046447754, 0.0, -0.0069954003670321135601, 0.083345455480285282001, 12454.451634795395449, -73670.529975671147878, 87884324285.574775284, -553342761339.97964199, 909784713383817144.98, -5883795855289758433.3}, {-1.0, 5.9604644775390625e-8, 2.3677293150757997928e-9, 0.083932595219022127005, 75242.17179390509748, -0.041726661532440829443, -18488.306894081923308, 563725525035.34898339, -5988414396610684162.5, -92537341636.835656296}, {-1.0, -5.9604644775390625e-8, 2.3677293150757997928e-9, -0.083932595219022127005, 75242.17179390509748, 0.041726661532440829443, -18488.306894081923308, -563725525035.34898339, -5988414396610684162.5, 92537341636.835656296}, }; TEST_FUNCTION_START(acb_agm1, state) { slong iter; /* check particular values against table */ { acb_t z, t; acb_ptr w1; slong i, j, prec, cnj; acb_init(z); acb_init(t); w1 = _acb_vec_init(NUM_DERIVS); for (prec = 32; prec <= 512; prec *= 4) { for (i = 0; i < NUM_TESTS; i++) { for (cnj = 0; cnj < 2; cnj++) { if (cnj == 1 && agm1_testdata[i][0] < 0 && agm1_testdata[i][1] == 0) continue; acb_zero(z); arf_set_d(arb_midref(acb_realref(z)), agm1_testdata[i][0]); arf_set_d(arb_midref(acb_imagref(z)), cnj ? -agm1_testdata[i][1] : agm1_testdata[i][1]); acb_agm1_cpx(w1, z, NUM_DERIVS, prec); for (j = 0; j < NUM_DERIVS; j++) { arf_set_d(arb_midref(acb_realref(t)), agm1_testdata[i][2+2*j]); mag_set_d(arb_radref(acb_realref(t)), fabs(agm1_testdata[i][2+2*j]) * EPS); arf_set_d(arb_midref(acb_imagref(t)), cnj ? -agm1_testdata[i][2+2*j+1] : agm1_testdata[i][2+2*j+1]); mag_set_d(arb_radref(acb_imagref(t)), fabs(agm1_testdata[i][2+2*j+1]) * EPS); if (!acb_overlaps(w1 + j, t)) { flint_printf("FAIL\n\n"); flint_printf("j = %wd\n\n", j); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 15); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1 + j, 15); flint_printf("\n\n"); flint_abort(); } } } } } _acb_vec_clear(w1, NUM_DERIVS); acb_clear(z); acb_clear(t); } /* self-consistency test */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr m1, m2; acb_t z1, z2, t; slong i, len1, len2, prec1, prec2; len1 = n_randint(state, 10); len2 = n_randint(state, 10); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); m1 = _acb_vec_init(len1); m2 = _acb_vec_init(len2); acb_init(z1); acb_init(z2); acb_init(t); acb_randtest(z1, state, prec1, 1 + n_randint(state, 100)); if (n_randint(state, 2)) { acb_set(z2, z1); } else { acb_randtest(t, state, prec2, 1 + n_randint(state, 100)); acb_add(z2, z1, t, prec2); acb_sub(z2, z2, t, prec2); } acb_agm1_cpx(m1, z1, len1, prec1); acb_agm1_cpx(m2, z2, len2, prec2); for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(m1 + i, m2 + i)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("iter = %wd, i = %wd, len1 = %wd, len2 = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, i, len1, len2, prec1, prec2); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_printf("m1 = "); acb_printd(m1, 30); flint_printf("\n\n"); flint_printf("m2 = "); acb_printd(m2, 30); flint_printf("\n\n"); flint_abort(); } } _acb_vec_clear(m1, len1); _acb_vec_clear(m2, len2); acb_clear(z1); acb_clear(z2); acb_clear(t); } TEST_FUNCTION_END(state); } #undef EPS #undef NUM_DERIVS #undef NUM_TESTS flint-3.1.3/src/acb/test/t-approx_dot.c000066400000000000000000000213341461254215100177150ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" FLINT_DLL extern slong acb_dot_gauss_dot_cutoff; TEST_FUNCTION_START(acb_approx_dot, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr x, y; acb_t s1, s2, z; slong i, len, prec, xbits, ybits, ebits; int initial, subtract, revx, revy; if (n_randint(state, 100) == 0) len = n_randint(state, 100); else if (n_randint(state, 10) == 0) len = n_randint(state, 10); else len = n_randint(state, 3); acb_dot_gauss_dot_cutoff = 3 + n_randint(state, 30); if (n_randint(state, 10) != 0 || len > 10) { prec = 2 + n_randint(state, 500); xbits = 2 + n_randint(state, 500); ybits = 2 + n_randint(state, 500); } else { prec = 2 + n_randint(state, 4000); xbits = 2 + n_randint(state, 4000); ybits = 2 + n_randint(state, 4000); } if (n_randint(state, 100) == 0) ebits = 2 + n_randint(state, 100); else ebits = 2 + n_randint(state, 10); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acb_vec_init(len); y = _acb_vec_init(len); acb_init(s1); acb_init(s2); acb_init(z); switch (n_randint(state, 3)) { case 0: for (i = 0; i < len; i++) { acb_randtest(x + i, state, xbits, ebits); acb_randtest(y + i, state, ybits, ebits); } break; /* Test with cancellation */ case 1: for (i = 0; i < len; i++) { if (i <= len / 2) { acb_randtest(x + i, state, xbits, ebits); acb_randtest(y + i, state, ybits, ebits); } else { acb_neg(x + i, x + len - i - 1); acb_set(y + i, y + len - i - 1); } } break; default: for (i = 0; i < len; i++) { if (i <= len / 2) { acb_randtest(x + i, state, xbits, ebits); acb_randtest(y + i, state, ybits, ebits); } else { acb_neg_round(x + i, x + len - i - 1, 2 + n_randint(state, 500)); acb_set_round(y + i, y + len - i - 1, 2 + n_randint(state, 500)); } } break; } acb_randtest(s1, state, 200, 100); acb_randtest(s2, state, 200, 100); acb_randtest(z, state, xbits, ebits); acb_approx_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); mag_zero(arb_radref(acb_realref(s1))); mag_zero(arb_radref(acb_imagref(s1))); /* With the fast algorithm, we expect identical results when reversing the vectors. */ if (ebits <= 12) { acb_approx_dot(s2, initial ? z : NULL, subtract, !revx ? (x + len - 1) : x, !revx ? -1 : 1, !revy ? (y + len - 1) : y, !revy ? -1 : 1, len, prec); mag_zero(arb_radref(acb_realref(s2))); mag_zero(arb_radref(acb_imagref(s2))); if (!acb_equal(s1, s2)) { flint_printf("FAIL (reversal)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } } /* Verify that radii are ignored */ for (i = 0; i < len; i++) { arb_get_mid_arb(acb_realref(x + i), acb_realref(x + i)); arb_get_mid_arb(acb_imagref(x + i), acb_imagref(x + i)); arb_get_mid_arb(acb_realref(y + i), acb_realref(y + i)); arb_get_mid_arb(acb_imagref(y + i), acb_imagref(y + i)); } arb_get_mid_arb(acb_realref(z), acb_realref(z)); arb_get_mid_arb(acb_imagref(z), acb_imagref(z)); acb_approx_dot(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); mag_zero(arb_radref(acb_realref(s2))); mag_zero(arb_radref(acb_imagref(s2))); if (!acb_equal(s1, s2)) { flint_printf("FAIL (radii)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } /* Compare with acb_dot */ acb_approx_dot(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); { mag_t err, xx, yy; mag_init(err); mag_init(xx); mag_init(yy); if (initial) acb_get_mag(err, z); for (i = 0; i < len; i++) { acb_get_mag(xx, revx ? x + len - 1 - i : x + i); acb_get_mag(yy, revx ? y + len - 1 - i : y + i); mag_addmul(err, xx, yy); } mag_mul_2exp_si(err, err, -prec + 2); acb_add_error_mag(s2, err); if (!acb_contains(s2, s1)) { flint_printf("FAIL (inclusion)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } mag_clear(err); mag_clear(xx); mag_clear(yy); } acb_clear(s1); acb_clear(s2); acb_clear(z); _acb_vec_clear(x, len); _acb_vec_clear(y, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-asin.c000066400000000000000000000043231461254215100164670ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_asin, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_asin(a, x, prec1); acb_asin(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check sin(asin(x)) = x */ acb_sin(b, b, prec1); if (!acb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_asin(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-asinh.c000066400000000000000000000043311461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_asinh, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_asinh(a, x, prec1); acb_asinh(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check sinh(asinh(x)) = x */ acb_sinh(b, b, prec1); if (!acb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_asinh(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-atan.c000066400000000000000000000043231461254215100164600ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_atan, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_atan(a, x, prec1); acb_atan(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check tan(atan(x)) = x */ acb_tan(b, b, prec1); if (!acb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_atan(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-atanh.c000066400000000000000000000043311461254215100166270ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_atanh, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_atanh(a, x, prec1); acb_atanh(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check tanh(atanh(x)) = x */ acb_tanh(b, b, prec1); if (!acb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_atanh(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-barnes_g.c000066400000000000000000000053331461254215100173170ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_barnes_g, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); acb_init(d); arb_randtest_precise(acb_realref(a), state, 1 + n_randint(state, 300), 1 + n_randint(state, 8)); arb_randtest_precise(acb_imagref(a), state, 1 + n_randint(state, 300), 1 + n_randint(state, 8)); acb_log_barnes_g(b, a, prec1); if (n_randint(state, 4) == 0) { acb_randtest(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_add(a, a, c, prec1); acb_sub(a, a, c, prec1); } acb_log_barnes_g(c, a, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_barnes_g(d, a, prec1); acb_exp(c, b, prec1); if (!acb_overlaps(c, d)) { flint_printf("FAIL: overlap 2\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } /* check lG(z+1) = lG(z) + lgamma(z) */ acb_lgamma(c, a, prec1); acb_add(b, b, c, prec1); acb_add_ui(c, a, 1, prec1); acb_log_barnes_g(c, c, prec1); if (!acb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-bernoulli_poly_ui.c000066400000000000000000000042021461254215100212640ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_bernoulli_poly_ui, state) { slong iter; /* test multiplication theorem */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, t, res1, res2; ulong n, m, k; slong prec; n = n_randint(state, 50); m = 1 + n_randint(state, 5); prec = 2 + n_randint(state, 200); acb_init(x); acb_init(t); acb_init(res1); acb_init(res2); acb_randtest(x, state, 2 + n_randint(state, 200), 20); acb_randtest(res1, state, 2 + n_randint(state, 200), 20); acb_mul_ui(t, x, m, prec); acb_bernoulli_poly_ui(res1, n, t, prec); acb_zero(res2); for (k = 0; k < m; k++) { acb_set_ui(t, k); acb_div_ui(t, t, m, prec); acb_add(t, t, x, prec); acb_bernoulli_poly_ui(t, n, t, prec); acb_add(res2, res2, t, prec); } if (n > 0) { arb_ui_pow_ui(acb_realref(t), m, n - 1, prec); acb_mul_arb(res2, res2, acb_realref(t), prec); } else { acb_div_ui(res2, res2, m, prec); } if (!acb_overlaps(res1, res2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu, m = %wu\n\n", n, m); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 15); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(t); acb_clear(res1); acb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-chebyshev_t_ui.c000066400000000000000000000062411461254215100205360ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_chebyshev_t_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; ulong n; slong prec; n = n_randtest(state); prec = 2 + n_randint(state, 300); acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(a, state, 1 + n_randint(state, 300), 5); acb_randtest(c, state, 1 + n_randint(state, 300), 5); acb_cos(b, a, prec); acb_chebyshev_t_ui(c, n, b, prec); acb_mul_ui(d, a, n, prec); acb_cos(d, d, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: c = T_n(cos(a)) = d = cos(n*a)\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("d = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_chebyshev_t_ui(b, n, b, prec); if (!acb_equal(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_randtest(a, state, 1 + n_randint(state, 300), 5); acb_randtest(b, state, 1 + n_randint(state, 300), 5); acb_randtest(c, state, 1 + n_randint(state, 300), 5); acb_chebyshev_t2_ui(b, c, n, a, prec); acb_chebyshev_t_ui(d, n, a, prec); if (!acb_overlaps(b, d)) { flint_printf("FAIL: T_n\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } if (n == 0) acb_set(d, a); else acb_chebyshev_t_ui(d, n - 1, a, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: T_{n-1}\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-chebyshev_u_ui.c000066400000000000000000000071411461254215100205370ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_chebyshev_u_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e; ulong n; slong prec; n = n_randtest(state); prec = 2 + n_randint(state, 300); acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_randtest_precise(a, state, 1 + n_randint(state, 300), 5); acb_randtest_precise(c, state, 1 + n_randint(state, 300), 5); acb_sin_cos(d, b, a, prec); acb_chebyshev_u_ui(c, n, b, prec); acb_mul(d, c, d, prec); if (n == LIMB_ONES) acb_mul_2exp_si(e, a, FLINT_BITS); else acb_mul_ui(e, a, n + 1, prec); acb_sin(e, e, prec); if (!acb_overlaps(d, e)) { flint_printf("FAIL: sin(a)*U_n(cos(a)) = sin((n+1)a)\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 15); flint_printf("\n\n"); flint_printf("e = "); acb_printd(e, 15); flint_printf("\n\n"); flint_abort(); } acb_chebyshev_u_ui(b, n, b, prec); if (!acb_equal(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_randtest(a, state, 1 + n_randint(state, 300), 5); acb_randtest(b, state, 1 + n_randint(state, 300), 5); acb_randtest(c, state, 1 + n_randint(state, 300), 5); acb_chebyshev_u2_ui(b, c, n, a, prec); acb_chebyshev_u_ui(d, n, a, prec); if (!acb_overlaps(b, d)) { flint_printf("FAIL: U_n\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } if (n == 0) acb_zero(d); else acb_chebyshev_u_ui(d, n - 1, a, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: U_{n-1}\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-cos_pi.c000066400000000000000000000044621461254215100170150ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_cos_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_cos_pi(a, x, prec1); acb_cos_pi(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* compare with cos */ arb_const_pi(acb_realref(c), prec1); acb_mul_arb(y, x, acb_realref(c), prec1); acb_cos(c, y, prec1); if (!acb_overlaps(a, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_cos_pi(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-cot.c000066400000000000000000000050741461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_cot, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest(y, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_cot(a, x, prec1); acb_cot(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* check cot(x+y) = (cot(x) cot(y) - 1) / (cot(x) + cot(y)) */ acb_add(b, x, y, prec1); acb_cot(b, b, prec1); acb_cot(c, y, prec1); acb_add(d, a, c, prec1); acb_mul(c, a, c, prec1); acb_sub_ui(c, c, 1, prec1); acb_div(d, c, d, prec1); if (!acb_overlaps(b, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_cot(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-cot_pi.c000066400000000000000000000044631461254215100170170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_cot_pi, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_cot_pi(a, x, prec1); acb_cot_pi(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* compare with cot */ arb_const_pi(acb_realref(c), prec1); acb_mul_arb(y, x, acb_realref(c), prec1); acb_cot(c, y, prec1); if (!acb_overlaps(a, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_cot_pi(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-coth.c000066400000000000000000000051031461254215100164670ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_coth, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(x, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); acb_randtest(y, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); acb_coth(a, x, prec1); acb_coth(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* check coth(x+y) = (1 + coth(x) coth(y)) / (coth(x) + coth(y)) */ acb_add(b, x, y, prec1); acb_coth(b, b, prec1); acb_coth(c, y, prec1); acb_add(d, a, c, prec1); acb_mul(c, a, c, prec1); acb_add_ui(c, c, 1, prec1); acb_div(d, c, d, prec1); if (!acb_overlaps(b, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_coth(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-csc.c000066400000000000000000000032531461254215100163060ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_csc, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 300), 100); acb_randtest_special(a, state, 1 + n_randint(state, 300), 100); acb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { acb_csc(a, x, prec1); } else { acb_set(a, x); acb_csc(a, a, prec1); } acb_sin(b, x, prec2); acb_inv(b, b, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-csc_pi.c000066400000000000000000000033361461254215100170000ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_csc_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 300), 100); acb_randtest_special(a, state, 1 + n_randint(state, 300), 100); acb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { acb_csc_pi(a, x, prec1); } else { acb_set(a, x); acb_csc_pi(a, a, prec1); } acb_sin_pi(b, x, prec2); acb_inv(b, b, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-csch.c000066400000000000000000000032571461254215100164620ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_csch, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 300), 100); acb_randtest_special(a, state, 1 + n_randint(state, 300), 100); acb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { acb_csch(a, x, prec1); } else { acb_set(a, x); acb_csch(a, a, prec1); } acb_sinh(b, x, prec2); acb_inv(b, b, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-csgn.c000066400000000000000000000031301461254215100164620ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_csgn, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y; arb_t a; slong prec; acb_init(x); acb_init(y); arb_init(a); acb_randtest_special(x, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); arb_randtest_special(a, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); prec = 2 + n_randint(state, 200); acb_csgn(a, x); if (acb_is_zero(x)) { acb_zero(y); } else { acb_mul(y, x, x, prec); acb_sqrt(y, y, prec); acb_div(y, y, x, prec); } if (!arb_contains(acb_realref(y), a)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); arb_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-digamma.c000066400000000000000000000045041461254215100171350ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_digamma, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); arb_randtest_precise(acb_realref(a), state, 1 + n_randint(state, 1000), 3); arb_randtest_precise(acb_imagref(a), state, 1 + n_randint(state, 1000), 3); acb_digamma(b, a, prec1); acb_digamma(c, a, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_set(c, a); acb_digamma(c, c, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } /* check digamma(z+1) = digamma(z) + 1/z */ acb_inv(c, a, prec1); acb_add(b, b, c, prec1); acb_add_ui(c, a, 1, prec1); acb_digamma(c, c, prec1); if (!acb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-div.c000066400000000000000000000132211461254215100163140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_div, state) { slong iter; /* test aliasing of c and a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_div(c, a, b, prec); acb_div(a, a, b, prec); if (!acb_equal(a, c)) { flint_printf("FAIL: aliasing c, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test aliasing of c and b */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_div(c, a, b, prec); acb_div(b, a, b, prec); if (!acb_equal(b, c)) { flint_printf("FAIL: aliasing c, b\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test aliasing a, a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_set(b, a); acb_div(c, a, a, prec); acb_div(d, a, b, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: aliasing a, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } /* test aliasing a, a, a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_set(b, a); acb_div(c, a, b, prec); acb_div(a, a, a, prec); if (!acb_overlaps(a, c)) { flint_printf("FAIL: aliasing a, a, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test (a+b)/c = a/c + b/c */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e, f; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_init(f); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); acb_add(d, a, b, 2 + n_randint(state, 200)); acb_div(e, d, c, 2 + n_randint(state, 200)); acb_div(d, a, c, 2 + n_randint(state, 200)); acb_div(f, b, c, 2 + n_randint(state, 200)); acb_add(f, d, f, 2 + n_randint(state, 200)); if (!acb_overlaps(e, f)) { flint_printf("FAIL: (a+b)/c = a/c + b/c\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("e = "); acb_print(e); flint_printf("\n\n"); flint_printf("f = "); acb_print(f); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); acb_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-dot.c000066400000000000000000000145231461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" FLINT_DLL extern slong acb_dot_gauss_dot_cutoff; TEST_FUNCTION_START(acb_dot, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr x, y; acb_t s1, s2, z; slong i, len, prec, xbits, ybits, ebits; int ok, initial, subtract, revx, revy; if (n_randint(state, 100) == 0) len = n_randint(state, 50); else if (n_randint(state, 10) == 0) len = n_randint(state, 5); else len = n_randint(state, 3); acb_dot_gauss_dot_cutoff = 3 + n_randint(state, 30); if (n_randint(state, 10) != 0 || len > 10) { prec = 2 + n_randint(state, 500); xbits = 2 + n_randint(state, 500); ybits = 2 + n_randint(state, 500); } else { prec = 2 + n_randint(state, 5000); xbits = 2 + n_randint(state, 5000); ybits = 2 + n_randint(state, 5000); } if (n_randint(state, 100) == 0) ebits = 2 + n_randint(state, 100); else ebits = 2 + n_randint(state, 10); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acb_vec_init(len); y = _acb_vec_init(len); acb_init(s1); acb_init(s2); acb_init(z); switch (n_randint(state, 3)) { case 0: for (i = 0; i < len; i++) { acb_randtest(x + i, state, xbits, ebits); acb_randtest(y + i, state, ybits, ebits); } break; /* Test with cancellation */ case 1: for (i = 0; i < len; i++) { if (i <= len / 2) { acb_randtest(x + i, state, xbits, ebits); acb_randtest(y + i, state, ybits, ebits); } else { acb_neg(x + i, x + len - i - 1); acb_set(y + i, y + len - i - 1); } } break; default: for (i = 0; i < len; i++) { if (i <= len / 2) { acb_randtest(x + i, state, xbits, ebits); acb_randtest(y + i, state, ybits, ebits); } else { acb_neg_round(x + i, x + len - i - 1, 2 + n_randint(state, 500)); acb_set_round(y + i, y + len - i - 1, 2 + n_randint(state, 500)); } } break; } acb_randtest(s1, state, 200, 100); acb_randtest(s2, state, 200, 100); acb_randtest(z, state, xbits, ebits); acb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); acb_dot_precise(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, ebits <= 12 ? ARF_PREC_EXACT : 2 * prec + 100); if (ebits <= 12) ok = acb_contains(s1, s2); else ok = acb_overlaps(s1, s2); if (!ok) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd, subtract = %d\n\n", iter, len, prec, ebits, subtract); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } /* With the fast algorithm, we expect identical results when reversing the vectors. */ if (ebits <= 12) { revx ^= 1; revy ^= 1; acb_dot(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); if (!acb_equal(s1, s2)) { flint_printf("FAIL (reversal)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } } acb_clear(s1); acb_clear(s2); acb_clear(z); _acb_vec_clear(x, len); _acb_vec_clear(y, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-dot_fmpz.c000066400000000000000000000056241461254215100173640ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "acb.h" TEST_FUNCTION_START(acb_dot_fmpz, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr x, y; fmpz * w; acb_t s1, s2, z; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acb_vec_init(len); y = _acb_vec_init(len); w = _fmpz_vec_init(len); acb_init(s1); acb_init(s2); acb_init(z); for (i = 0; i < len; i++) { acb_randtest(x + i, state, 2 + n_randint(state, 200), 10); fmpz_randtest(w + i, state, 1 + n_randint(state, 200)); acb_set_fmpz(y + i, w + i); } acb_randtest(s1, state, 200, 10); acb_randtest(s2, state, 200, 10); acb_randtest(z, state, 200, 10); acb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); acb_dot_fmpz(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + len - 1) : w, revy ? -1 : 1, len, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z); _acb_vec_clear(x, len); _acb_vec_clear(y, len); _fmpz_vec_clear(w, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-dot_si.c000066400000000000000000000055331461254215100170220ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_dot_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr x, y; slong * w; acb_t s1, s2, z; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acb_vec_init(len); y = _acb_vec_init(len); w = flint_malloc(sizeof(ulong) * len); acb_init(s1); acb_init(s2); acb_init(z); for (i = 0; i < len; i++) { acb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[i] = n_randtest(state); acb_set_si(y + i, w[i]); } acb_randtest(s1, state, 200, 10); acb_randtest(s2, state, 200, 10); acb_randtest(z, state, 200, 10); acb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); acb_dot_si(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + len - 1) : w, revy ? -1 : 1, len, prec); if (!acb_equal(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z); _acb_vec_clear(x, len); _acb_vec_clear(y, len); flint_free(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-dot_siui.c000066400000000000000000000060271461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_dot_siui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr x, y; ulong * w; acb_t s1, s2, z; fmpz_t c; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acb_vec_init(len); y = _acb_vec_init(len); w = flint_malloc(2 * sizeof(ulong) * len); acb_init(s1); acb_init(s2); acb_init(z); fmpz_init(c); for (i = 0; i < len; i++) { acb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[2 * i] = n_randtest(state); w[2 * i + 1] = n_randtest(state); fmpz_set_signed_uiui(c, w[2 * i + 1], w[2 * i]); acb_set_fmpz(y + i, c); } acb_randtest(s1, state, 200, 10); acb_randtest(s2, state, 200, 10); acb_randtest(z, state, 200, 10); acb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); acb_dot_siui(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + 2 * len - 2) : w, revy ? -1 : 1, len, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z); _acb_vec_clear(x, len); _acb_vec_clear(y, len); flint_free(w); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-dot_ui.c000066400000000000000000000055331461254215100170240ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_dot_ui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr x, y; ulong * w; acb_t s1, s2, z; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acb_vec_init(len); y = _acb_vec_init(len); w = flint_malloc(sizeof(ulong) * len); acb_init(s1); acb_init(s2); acb_init(z); for (i = 0; i < len; i++) { acb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[i] = n_randtest(state); acb_set_ui(y + i, w[i]); } acb_randtest(s1, state, 200, 10); acb_randtest(s2, state, 200, 10); acb_randtest(z, state, 200, 10); acb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); acb_dot_ui(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + len - 1) : w, revy ? -1 : 1, len, prec); if (!acb_equal(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z); _acb_vec_clear(x, len); _acb_vec_clear(y, len); flint_free(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-dot_uiui.c000066400000000000000000000060201461254215100173520ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_dot_uiui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr x, y; ulong * w; acb_t s1, s2, z; fmpz_t c; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acb_vec_init(len); y = _acb_vec_init(len); w = flint_malloc(2 * sizeof(ulong) * len); acb_init(s1); acb_init(s2); acb_init(z); fmpz_init(c); for (i = 0; i < len; i++) { acb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[2 * i] = n_randtest(state); w[2 * i + 1] = n_randtest(state); fmpz_set_uiui(c, w[2 * i + 1], w[2 * i]); acb_set_fmpz(y + i, c); } acb_randtest(s1, state, 200, 10); acb_randtest(s2, state, 200, 10); acb_randtest(z, state, 200, 10); acb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); acb_dot_uiui(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + 2 * len - 2) : w, revy ? -1 : 1, len, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); acb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", acb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(x + i)); flint_printf("y[%wd] = ", i); acb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", acb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z); _acb_vec_clear(x, len); _acb_vec_clear(y, len); flint_free(w); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-exp.c000066400000000000000000000032421461254215100163300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_exp, state) { slong iter; /* check exp(a+b) = exp(a)*exp(b) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); acb_randtest(c, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_add(c, a, b, prec); acb_exp(c, c, prec); acb_exp(d, a, prec); acb_exp(e, b, prec); acb_mul(d, d, e, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-exp_invexp.c000066400000000000000000000026701461254215100177250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_exp_invexp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); acb_randtest(c, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_exp_invexp(b, c, a, prec); acb_mul(b, b, c, prec); acb_one(c); if (!acb_contains(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-exp_pi_i.c000066400000000000000000000041701461254215100173310ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_exp_pi_i, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); acb_randtest(c, state, 1 + n_randint(state, 200), 3); acb_randtest(d, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_exp_pi_i(b, a, prec); acb_const_pi(c, prec); acb_mul(c, c, a, prec); acb_mul_onei(c, c); acb_exp(d, c, prec); if (!acb_overlaps(d, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 30); flint_printf("\n\n"); flint_abort(); } acb_set(c, a); acb_exp_pi_i(c, c, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-expm1.c000066400000000000000000000041101461254215100165610ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_expm1, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_expm1(a, x, prec1); acb_set(b, x); /* also test aliasing */ acb_expm1(b, b, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check expm1(x) = exp(x)-1 */ acb_exp(b, x, prec2); acb_sub_ui(b, b, 1, prec2); if (!acb_overlaps(a, b)) { flint_printf("FAIL: expm1 vs exp\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-gamma.c000066400000000000000000000036121461254215100166170ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_gamma, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); arb_randtest_precise(acb_realref(a), state, 1 + n_randint(state, 1000), 3); arb_randtest_precise(acb_imagref(a), state, 1 + n_randint(state, 1000), 3); acb_gamma(b, a, prec1); acb_gamma(c, a, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } /* check gamma(z+1) = z gamma(z) */ acb_mul(b, b, a, prec1); acb_add_ui(c, a, 1, prec1); acb_gamma(c, c, prec1); if (!acb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-get_abs_lbound_arf.c000066400000000000000000000030611461254215100213320ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_get_abs_lbound_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a; arf_t m, m2, x, y, s; acb_init(a); arf_init(m); arf_init(m2); arf_init(x); arf_init(y); arf_init(s); acb_randtest_special(a, state, 200, 10); acb_get_abs_lbound_arf(m, a, 2 + n_randint(state, 100)); /* check m^2 <= x^2 + y^2 */ arf_mul(m2, m, m, ARF_PREC_EXACT, ARF_RND_DOWN); arb_get_abs_lbound_arf(x, acb_realref(a), ARF_PREC_EXACT); arb_get_abs_lbound_arf(y, acb_imagref(a), ARF_PREC_EXACT); arf_sosq(s, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_cmp(m2, s) > 0) { flint_printf("FAIL:\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("m = "); arf_print(m); flint_printf("\n\n"); flint_abort(); } acb_clear(a); arf_clear(m); arf_clear(m2); arf_clear(x); arf_clear(y); arf_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-get_abs_ubound_arf.c000066400000000000000000000030611461254215100213430ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_get_abs_ubound_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a; arf_t m, m2, x, y, s; acb_init(a); arf_init(m); arf_init(m2); arf_init(x); arf_init(y); arf_init(s); acb_randtest_special(a, state, 200, 10); acb_get_abs_ubound_arf(m, a, 2 + n_randint(state, 100)); /* check m^2 >= x^2 + y^2 */ arf_mul(m2, m, m, ARF_PREC_EXACT, ARF_RND_DOWN); arb_get_abs_ubound_arf(x, acb_realref(a), ARF_PREC_EXACT); arb_get_abs_ubound_arf(y, acb_imagref(a), ARF_PREC_EXACT); arf_sosq(s, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_cmp(m2, s) < 0) { flint_printf("FAIL:\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("m = "); arf_print(m); flint_printf("\n\n"); flint_abort(); } acb_clear(a); arf_clear(m); arf_clear(m2); arf_clear(x); arf_clear(y); arf_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-get_mag.c000066400000000000000000000031061461254215100171360ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_get_mag, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a; arf_t m2, x, y, s; mag_t m; acb_init(a); mag_init(m); arf_init(m2); arf_init(x); arf_init(y); arf_init(s); acb_randtest_special(a, state, 200, 10); acb_get_mag(m, a); MAG_CHECK_BITS(m) /* check m^2 >= x^2 + y^2 */ arf_set_mag(m2, m); arf_mul(m2, m2, m2, ARF_PREC_EXACT, ARF_RND_DOWN); arb_get_abs_ubound_arf(x, acb_realref(a), ARF_PREC_EXACT); arb_get_abs_ubound_arf(y, acb_imagref(a), ARF_PREC_EXACT); arf_sosq(s, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_cmp(m2, s) < 0) { flint_printf("FAIL:\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("m = "); mag_print(m); flint_printf("\n\n"); flint_abort(); } acb_clear(a); mag_clear(m); arf_clear(m2); arf_clear(x); arf_clear(y); arf_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-get_mag_lower.c000066400000000000000000000031221461254215100203440ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_get_mag_lower, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a; arf_t m2, x, y, s; mag_t m; acb_init(a); mag_init(m); arf_init(m2); arf_init(x); arf_init(y); arf_init(s); acb_randtest_special(a, state, 200, 10); acb_get_mag_lower(m, a); MAG_CHECK_BITS(m) /* check m^2 <= x^2 + y^2 */ arf_set_mag(m2, m); arf_mul(m2, m2, m2, ARF_PREC_EXACT, ARF_RND_DOWN); arb_get_abs_lbound_arf(x, acb_realref(a), ARF_PREC_EXACT); arb_get_abs_lbound_arf(y, acb_imagref(a), ARF_PREC_EXACT); arf_sosq(s, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_cmp(m2, s) > 0) { flint_printf("FAIL:\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("m = "); mag_print(m); flint_printf("\n\n"); flint_abort(); } acb_clear(a); mag_clear(m); arf_clear(m2); arf_clear(x); arf_clear(y); arf_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-inv.c000066400000000000000000000071661461254215100163410ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" static void acb_inv_naive(acb_t z, const acb_t x, slong prec) { #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(z) #define d acb_imagref(z) if (arb_is_zero(b)) { arb_inv(c, a, prec); arb_zero(d); } else if (arb_is_zero(a)) { arb_inv(d, b, prec); arb_neg(d, d); arb_zero(c); } else { arb_t t; arb_init(t); arb_mul(t, a, a, prec); arb_addmul(t, b, b, prec); arb_div(c, a, t, prec); arb_div(d, b, t, prec); arb_neg(d, d); arb_clear(t); } #undef a #undef b #undef c #undef d } TEST_FUNCTION_START(acb_inv, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e, f; arf_t t; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_init(f); arf_init(t); prec = 2 + n_randint(state, 1000); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 100); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 100); acb_inv(b, a, prec); acb_inv_naive(c, a, prec); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_abort(); } acb_set(c, a); acb_inv(c, c, prec); if (!acb_equal(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_abort(); } acb_randtest(a, state, 1 + n_randint(state, 1000), 10); acb_randtest(b, state, 1 + n_randint(state, 1000), 10); acb_zero(d); arf_set_mag(t, arb_radref(acb_realref(a))); if (n_randint(state, 2)) arf_neg(t, t); arf_add(arb_midref(acb_realref(d)), arb_midref(acb_realref(a)), t, ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_mag(t, arb_radref(acb_imagref(a))); if (n_randint(state, 2)) arf_neg(t, t); arf_add(arb_midref(acb_imagref(d)), arb_midref(acb_imagref(a)), t, ARF_PREC_EXACT, ARF_RND_DOWN); acb_inv(b, a, 2 + n_randint(state, 1000)); acb_inv(d, d, 2 + n_randint(state, 1000)); if (!acb_overlaps(b, d)) { flint_printf("FAIL: corner test\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); acb_clear(f); arf_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-lambertw.c000066400000000000000000000123471461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_lambertw, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x1, x2, t, w1, w2; slong prec1, prec2, ebits; int flags; fmpz_t k; acb_init(x1); acb_init(x2); acb_init(t); acb_init(w1); acb_init(w2); fmpz_init(k); if (n_randint(state, 4) == 0) { prec1 = 2 + n_randint(state, 3000); prec2 = 2 + n_randint(state, 3000); ebits = 1 + n_randint(state, 1000); } else { prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 50); } acb_randtest(x1, state, 1 + n_randint(state, 1000), ebits); acb_randtest(x2, state, 1 + n_randint(state, 1000), ebits); acb_randtest(t, state, 1 + n_randint(state, 1000), ebits); acb_randtest(w1, state, 1 + n_randint(state, 1000), ebits); acb_randtest(w2, state, 1 + n_randint(state, 1000), ebits); fmpz_randtest(k, state, ebits); flags = 0; switch (n_randint(state, 10)) { case 0: flags = ACB_LAMBERTW_LEFT; break; case 1: flags = ACB_LAMBERTW_MIDDLE; fmpz_set_si(k, -1); break; default: break; } if (n_randint(state, 4) == 0) { arb_const_e(acb_realref(t), 2 * prec1); arb_inv(acb_realref(t), acb_realref(t), 2 * prec1); arb_sub(acb_realref(x1), acb_realref(x1), acb_realref(t), 2 * prec1); } if (n_randint(state, 2)) { acb_set(x2, x1); } else { acb_add(x2, x1, t, 2 * prec1); acb_sub(x2, x2, t, 2 * prec1); } if (n_randint(state, 4) == 0 && flags == 0) acb_lambertw_asymp(w1, x1, k, 1 + n_randint(state, 10), 1 + n_randint(state, 10), prec1); else acb_lambertw(w1, x1, k, flags, prec1); if (n_randint(state, 2)) { acb_set(w2, x2); acb_lambertw(w2, w2, k, flags, prec1); } else { acb_lambertw(w2, x2, k, flags, prec1); } if (!acb_overlaps(w1, w2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter %wd, flags = %d, branch = ", flags, iter); fmpz_print(k); flint_printf(" prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); acb_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); acb_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n"); flint_abort(); } acb_exp(t, w1, prec1); acb_mul(t, t, w1, prec1); if (!acb_contains(t, x1)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("iter %wd, flags = %d, branch = ", flags, iter); fmpz_print(k); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); acb_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); acb_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 50); flint_printf("\n\n"); flint_abort(); } if (!arb_contains_zero(acb_imagref(x1))) { acb_conj(x2, x1); fmpz_neg(k, k); if (flags == 2) fmpz_sub_ui(k, k, 1); acb_lambertw(w2, x2, k, flags, prec2); if (flags == 2) fmpz_add_ui(k, k, 1); fmpz_neg(k, k); acb_conj(w2, w2); if (!acb_overlaps(w1, w2)) { flint_printf("FAIL: conjugation\n\n"); flint_printf("iter %wd, flags = %d, branch = ", flags, iter); fmpz_print(k); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); acb_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); acb_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n"); flint_abort(); } } acb_clear(x1); acb_clear(x2); acb_clear(t); acb_clear(w1); acb_clear(w2); fmpz_clear(k); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-lgamma.c000066400000000000000000000043041461254215100167720ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_lgamma, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 500); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); arb_randtest_precise(acb_realref(a), state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); arb_randtest_precise(acb_imagref(a), state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_lgamma(b, a, prec1); if (n_randint(state, 4) == 0) { acb_randtest(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_add(a, a, c, prec1); acb_sub(a, a, c, prec1); } acb_lgamma(c, a, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } /* check lgamma(z+1) = lgamma(z) + log(z) */ acb_log(c, a, prec1); acb_add(b, b, c, prec1); acb_add_ui(c, a, 1, prec1); acb_lgamma(c, c, prec1); if (!acb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-log.c000066400000000000000000000157611461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" /* old acb_log code for comparison */ static int close_to_one(const acb_t z) { mp_limb_t top; if (arf_abs_bound_lt_2exp_si(arb_midref(acb_imagref(z))) > -3) return 0; if (ARF_EXP(arb_midref(acb_realref(z))) == 0) { ARF_GET_TOP_LIMB(top, arb_midref(acb_realref(z))); return (top >> (FLINT_BITS - 4)) == 15; } else if (ARF_EXP(arb_midref(acb_realref(z))) == 1) { ARF_GET_TOP_LIMB(top, arb_midref(acb_realref(z))); return (top >> (FLINT_BITS - 4)) == 8; } return 0; } void acb_log_old(acb_t r, const acb_t z, slong prec) { #define a acb_realref(z) #define b acb_imagref(z) if (arb_is_zero(b)) { if (arb_is_positive(a)) { arb_log(acb_realref(r), a, prec); arb_zero(acb_imagref(r)); } else if (arb_is_negative(a)) { arb_neg(acb_realref(r), a); arb_log(acb_realref(r), acb_realref(r), prec); arb_const_pi(acb_imagref(r), prec); } else { acb_indeterminate(r); } } else if (arb_is_zero(a)) { if (arb_is_positive(b)) { arb_log(acb_realref(r), b, prec); arb_const_pi(acb_imagref(r), prec); arb_mul_2exp_si(acb_imagref(r), acb_imagref(r), -1); } else if (arb_is_negative(b)) { arb_neg(acb_realref(r), b); arb_log(acb_realref(r), acb_realref(r), prec); arb_const_pi(acb_imagref(r), prec); arb_mul_2exp_si(acb_imagref(r), acb_imagref(r), -1); arb_neg(acb_imagref(r), acb_imagref(r)); } else { acb_indeterminate(r); } } else { arb_t t, u; arb_init(t); arb_init(u); if (close_to_one(z)) { arb_sub_ui(u, a, 1, prec + 8); arb_mul(t, u, u, prec + 8); arb_addmul(t, b, b, prec + 8); arb_mul_2exp_si(u, u, 1); arb_add(t, t, u, prec + 8); arb_log1p(t, t, prec); arb_mul_2exp_si(t, t, -1); } else { arb_mul(t, a, a, prec + 8); arb_addmul(t, b, b, prec + 8); if (arb_contains_zero(t) || arf_sgn(arb_midref(t)) < 0) arb_zero_pm_inf(t); else arb_log(t, t, prec); arb_mul_2exp_si(t, t, -1); } acb_arg(u, z, prec); arb_swap(acb_realref(r), t); arb_swap(acb_imagref(r), u); arb_clear(t); arb_clear(u); } if (!acb_is_finite(r)) acb_indeterminate(r); #undef a #undef b } TEST_FUNCTION_START(acb_log, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b, d; slong prec1, prec2, acc1, acc2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_init(d); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); if (n_randint(state, 2)) { acb_log(a, x, prec1); } else { acb_set(a, x); /* test aliasing */ acb_log(a, a, prec1); } if (n_randint(state, 2)) { acb_log(b, x, prec2); } else { acb_set(b, x); /* test aliasing */ acb_log(b, b, prec2); } /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } if (!acb_contains_zero(x) && acb_is_finite(x) && !acb_is_finite(a)) { flint_printf("FAIL: not finite\n\n"); flint_printf("prec1 = %wd\n\n", prec1); flint_printf("x = "); acb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_abort(); } /* check exp(log(x)) = x */ acb_exp(b, b, prec1); if (!acb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_log_old(d, x, prec1); /* check consistency */ if (!acb_overlaps(a, d)) { flint_printf("FAIL: overlap 2\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* compare accuracy with log_old */ acc1 = arb_rel_accuracy_bits(acb_realref(a)); acc2 = arb_rel_accuracy_bits(acb_realref(d)); if (acc2 > 0 && acc1 < acc2 - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd, acc2 = %wd\n\n", prec1, acc1, acc2); flint_printf("x = "); acb_printd(x, 50); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 50); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(acb_imagref(a)); acc2 = arb_rel_accuracy_bits(acb_imagref(d)); if (acc2 > 0 && acc1 < acc2 - 2) { flint_printf("FAIL: accuracy 2\n\n"); flint_printf("prec1 = %wd, acc1 = %wd, acc2 = %wd\n\n", prec1, acc1, acc2); flint_printf("x = "); acb_printd(x, 50); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 50); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-log1p.c000066400000000000000000000045221461254215100165600ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_log1p, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_log1p(a, x, prec1); acb_log1p(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check log1p(x) = log(1+x) */ acb_add_ui(b, x, 1, prec2); acb_log(b, b, prec2); if (!acb_overlaps(a, b)) { flint_printf("FAIL: log1p vs log\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_log1p(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-log_sin_pi.c000066400000000000000000000041661461254215100176640ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_log_sin_pi, state) { slong iter; /* check functional equation S(s+1) = S(s) + log(-s) - log(s) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, s1, r, r1, t; slong prec; acb_init(s); acb_init(s1); acb_init(r); acb_init(r1); acb_init(t); prec = 2 + n_randint(state, 500); acb_randtest(s, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); acb_randtest(r, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); acb_randtest(r1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); acb_log_sin_pi(r, s, prec); acb_add_ui(s1, s, 1, prec); if (n_randint(state, 4) == 0) { acb_randtest(t, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_add(s1, s1, t, prec); acb_sub(s1, s1, t, prec); } acb_log_sin_pi(r1, s1, prec); acb_log(t, s, prec); acb_sub(r, r, t, prec); acb_neg(t, s); acb_log(t, t, prec); acb_add(r, r, t, prec); if (!acb_overlaps(r, r1)) { flint_printf("FAIL: overlap\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_printf("s1 = "); acb_printd(s1, 30); flint_printf("\n\n"); flint_printf("r = "); acb_printd(r, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(s); acb_clear(s1); acb_clear(r); acb_clear(r1); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-mul.c000066400000000000000000000220211461254215100163250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_mul, state) { slong iter, iter2; /* test aliasing of c and a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_mul(c, a, b, prec); acb_mul(a, a, b, prec); if (!acb_equal(a, c)) { flint_printf("FAIL: aliasing c, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test aliasing of c and b */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_mul(c, a, b, prec); acb_mul(b, a, b, prec); if (!acb_equal(b, c)) { flint_printf("FAIL: aliasing b, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test aliasing a, a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_set(b, a); acb_mul(c, a, a, prec); acb_mul(d, a, b, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: aliasing a, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } /* test aliasing a, a, a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_set(b, a); acb_mul(c, a, b, prec); acb_mul(a, a, a, prec); if (!acb_overlaps(a, c)) { flint_printf("FAIL: aliasing a, a, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test a*(b+c) = a*b + a*c */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e, f; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_init(f); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); acb_add(d, b, c, 2 + n_randint(state, 200)); acb_mul(e, a, d, 2 + n_randint(state, 200)); acb_mul(d, a, b, 2 + n_randint(state, 200)); acb_mul(f, a, c, 2 + n_randint(state, 200)); acb_add(f, d, f, 2 + n_randint(state, 200)); if (!acb_overlaps(e, f)) { flint_printf("FAIL: a*(b+c) = a*b + a*c\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("e = "); acb_print(e); flint_printf("\n\n"); flint_printf("f = "); acb_print(f); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); acb_clear(f); } /* compare with mul_naive */ /* main test */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, z, v; slong prec; acb_init(x); acb_init(y); acb_init(z); acb_init(v); for (iter2 = 0; iter2 < 100; iter2++) { acb_randtest_special(x, state, n_randint(state,2) ? 2000 : 200, 200); acb_randtest_special(y, state, n_randint(state,2) ? 2000 : 200, 200); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 5)) { case 0: acb_mul(z, x, y, prec); acb_mul_naive(v, x, y, prec); if (!acb_overlaps(z, v)) { flint_printf("FAIL!\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_printf("v = "); acb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 1: acb_set(y, x); acb_mul(z, x, y, prec); acb_mul(v, x, x, prec); if (!acb_overlaps(z, v)) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_printf("v = "); acb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 2: acb_mul(v, x, x, prec); acb_mul(x, x, x, prec); if (!acb_equal(v, x)) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_printf("v = "); acb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 3: acb_mul(v, x, y, prec); acb_mul(x, x, y, prec); if (!acb_equal(v, x)) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("v = "); acb_print(v); flint_printf("\n\n"); flint_abort(); } break; default: acb_mul(v, x, y, prec); acb_mul(x, y, x, prec); if (!acb_overlaps(v, x)) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("v = "); acb_print(v); flint_printf("\n\n"); flint_abort(); } break; } } acb_clear(x); acb_clear(y); acb_clear(z); acb_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-mul_naive.c000066400000000000000000000133311461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_mul_naive, state) { slong iter; /* test aliasing of c and a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_mul_naive(c, a, b, prec); acb_mul_naive(a, a, b, prec); if (!acb_equal(a, c)) { flint_printf("FAIL: aliasing c, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test aliasing of c and b */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_mul_naive(c, a, b, prec); acb_mul_naive(b, a, b, prec); if (!acb_equal(b, c)) { flint_printf("FAIL: aliasing b, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test aliasing a, a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_set(b, a); acb_mul_naive(c, a, a, prec); acb_mul_naive(d, a, b, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: aliasing a, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } /* test aliasing a, a, a */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); acb_set(b, a); acb_mul_naive(c, a, b, prec); acb_mul_naive(a, a, a, prec); if (!acb_overlaps(a, c)) { flint_printf("FAIL: aliasing a, a, a\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } /* test a*(b+c) = a*b + a*c */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e, f; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_init(f); acb_randtest(a, state, 1 + n_randint(state, 200), 10); acb_randtest(b, state, 1 + n_randint(state, 200), 10); acb_randtest(c, state, 1 + n_randint(state, 200), 10); acb_add(d, b, c, 2 + n_randint(state, 200)); acb_mul_naive(e, a, d, 2 + n_randint(state, 200)); acb_mul_naive(d, a, b, 2 + n_randint(state, 200)); acb_mul_naive(f, a, c, 2 + n_randint(state, 200)); acb_add(f, d, f, 2 + n_randint(state, 200)); if (!acb_overlaps(e, f)) { flint_printf("FAIL: a*(b+c) = a*b + a*c\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("e = "); acb_print(e); flint_printf("\n\n"); flint_printf("f = "); acb_print(f); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); acb_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-polygamma.c000066400000000000000000000053251461254215100175260ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" static const char *testdata[5] = { "-0.2487544770337842625472529935761139760973697136685351169998556396906930329999105060928584336658420889 +/- 1e-90", "-0.9189385332046727417803297364056176398613974736377834128171515404827656959272603976947432986359541976 +/- 1e-90", "-0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 +/- 1e-90", "1.644934066848226436472415166646025189218949901206798437735558229370007470403200873833628900619758705 +/- 1e-90", "-2.404113806319188570799476323022899981529972584680997763584543110683676411572626180372911747218670516 +/- 1e-90", }; TEST_FUNCTION_START(acb_polygamma, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, s, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 500); prec2 = prec1 + 30; acb_init(a); acb_init(s); acb_init(b); acb_init(c); if (iter < 200) { slong i = n_randint(state, 5); acb_set_si(s, -2 + i); acb_one(a); acb_randtest(c, state, 1 + n_randint(state, 500), 3); acb_add(s, s, c, prec2); acb_sub(s, s, c, prec2); acb_polygamma(b, s, a, prec1); acb_zero(c); arb_set_str(acb_realref(c), testdata[i], prec2); } else { acb_randtest(a, state, 1 + n_randint(state, 500), 3); acb_randtest(s, state, 1 + n_randint(state, 500), 3); acb_polygamma(b, s, a, prec1); acb_randtest(c, state, 1 + n_randint(state, 500), 3); acb_add(s, s, c, prec2); acb_sub(s, s, c, prec2); acb_polygamma(c, s, a, prec2); } if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("s = "); acb_print(s); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(s); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-pow.c000066400000000000000000000067541461254215100163540ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_pow, state) { slong iter; /* check large arguments */ for (iter = 0; iter < 20000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, e, f; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_init(f); acb_randtest(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 200)); if (n_randint(state, 4) == 0) arb_zero(acb_imagref(a)); acb_randtest(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 200)); if (n_randint(state, 4) == 0) arb_zero(acb_imagref(b)); acb_pow(c, a, b, prec1); acb_pow(d, a, b, prec2); if (!acb_overlaps(c, d)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_randtest(c, state, 1 + n_randint(state, 1000), 200); /* check a^(b+c) = a^b*a^c */ acb_add(e, b, c, prec1); acb_pow(d, a, e, prec1); acb_pow(e, a, b, prec1); acb_pow(f, a, c, prec1); acb_mul(e, e, f, prec1); if (!acb_overlaps(d, e)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_printf("e = "); acb_print(e); flint_printf("\n\n"); flint_abort(); } acb_pow(c, a, b, prec1); acb_set(d, a); acb_pow(d, d, b, prec2); if (!acb_overlaps(c, d)) { flint_printf("FAIL: aliasing 1\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_set(d, b); acb_pow(d, a, d, prec2); if (!acb_overlaps(c, d)) { flint_printf("FAIL: aliasing 2\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); acb_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-pow_fmpz.c000066400000000000000000000047401461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_pow_fmpz, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; fmpz_t e1, e2, e3; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); acb_init(d); fmpz_init(e1); fmpz_init(e2); fmpz_init(e3); acb_randtest(a, state, 1 + n_randint(state, 1000), 200); acb_randtest(b, state, 1 + n_randint(state, 1000), 200); fmpz_randtest(e1, state, 200); fmpz_randtest(e2, state, 200); acb_pow_fmpz(b, a, e1, prec1); acb_pow_fmpz(c, a, e1, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("e1 = "); fmpz_print(e1); flint_printf("\n\n"); flint_abort(); } /* check a^(e1+e2) = a^e1*a^e2 */ acb_pow_fmpz(c, a, e2, prec1); acb_mul(d, b, c, prec1); fmpz_add(e3, e1, e2); acb_pow_fmpz(c, a, e3, prec1); if (!acb_overlaps(c, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_printf("e1 = "); fmpz_print(e1); flint_printf("\n\n"); flint_printf("e2 = "); fmpz_print(e2); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); fmpz_clear(e1); fmpz_clear(e2); fmpz_clear(e3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-quadratic_roots_fmpz.c000066400000000000000000000046411461254215100217770ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_quadratic_roots_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t r1, r2, x, y; fmpz_t a, b, c; slong prec; fmpz_init(a); fmpz_init(b); fmpz_init(c); acb_init(r1); acb_init(r2); acb_init(x); acb_init(y); prec = 2 + n_randint(state, 1000); fmpz_randtest_not_zero(a, state, 1 + n_randint(state, 1000)); fmpz_randtest(b, state, 1 + n_randint(state, 1000)); fmpz_randtest(c, state, 1 + n_randint(state, 1000)); acb_randtest(r1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(r2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_quadratic_roots_fmpz(r1, r2, a, b, c, prec); acb_mul(x, r1, r1, prec); acb_mul_fmpz(x, x, a, prec); acb_addmul_fmpz(x, r1, b, prec); acb_add_fmpz(x, x, c, prec); acb_mul(y, r2, r2, prec); acb_mul_fmpz(y, y, a, prec); acb_addmul_fmpz(y, r2, b, prec); acb_add_fmpz(y, y, c, prec); if (!acb_contains_zero(x) || !acb_contains_zero(y) || acb_rel_accuracy_bits(r1) < prec - 4 || acb_rel_accuracy_bits(r2) < prec - 4) { flint_printf("FAIL: containment / accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); acb_clear(r1); acb_clear(r2); acb_clear(x); acb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-rel_accuracy_bits.c000066400000000000000000000055361461254215100212210ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_rel_accuracy_bits, state) { slong iter; /* test aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; acb_t z; slong a1, a2; arb_init(x); acb_init(z); arb_randtest_special(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 200)); acb_set_arb(z, x); a1 = arb_rel_accuracy_bits(x); a2 = acb_rel_accuracy_bits(z); if (a1 != a2) { flint_printf("FAIL: acb != arb\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_printf("a1 = %wd, a2 = %wd\n\n", a1, a2); flint_abort(); } acb_randtest_special(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 200)); a1 = acb_rel_accuracy_bits(z); if (n_randint(state, 2)) arf_swap(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z))); if (n_randint(state, 2)) mag_swap(arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); a2 = acb_rel_accuracy_bits(z); if (a1 != a2) { flint_printf("FAIL: swapping\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_printf("a1 = %wd, a2 = %wd\n\n", a1, a2); flint_abort(); } acb_randtest_special(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 200)); if (arf_cmpabs(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z))) >= 0) arf_set(arb_midref(x), arb_midref(acb_realref(z))); else arf_set(arb_midref(x), arb_midref(acb_imagref(z))); if (mag_cmp(arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))) >= 0) mag_set(arb_radref(x), arb_radref(acb_realref(z))); else mag_set(arb_radref(x), arb_radref(acb_imagref(z))); a1 = acb_rel_accuracy_bits(z); a2 = arb_rel_accuracy_bits(x); if (a1 != a2) { flint_printf("FAIL: acb != arb (2)\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_printf("a1 = %wd, a2 = %wd\n\n", a1, a2); flint_abort(); } arb_clear(x); acb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-rgamma.c000066400000000000000000000036141461254215100170030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_rgamma, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); arb_randtest_precise(acb_realref(a), state, 1 + n_randint(state, 1000), 3); arb_randtest_precise(acb_imagref(a), state, 1 + n_randint(state, 1000), 3); acb_rgamma(b, a, prec1); acb_rgamma(c, a, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } /* check 1/gamma(z+1) = 1/gamma(z)/z */ acb_div(b, b, a, prec1); acb_add_ui(c, a, 1, prec1); acb_rgamma(c, c, prec1); if (!acb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-rising2_ui.c000066400000000000000000000062161461254215100176120ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "arith.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_rising2_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, u, v, u2, v2; fmpz *f; acb_ptr g; ulong n; slong i, prec; acb_init(a); acb_init(u); acb_init(v); acb_init(u2); acb_init(v2); acb_randtest(a, state, 1 + n_randint(state, 4000), 10); acb_randtest(u, state, 1 + n_randint(state, 4000), 10); acb_randtest(v, state, 1 + n_randint(state, 4000), 10); n = n_randint(state, 120); f = _fmpz_vec_init(n + 1); g = _acb_vec_init(n + 1); prec = 2 + n_randint(state, 4000); acb_rising2_ui(u, v, a, n, prec); arith_stirling_number_1u_vec(f, n, n + 1); for (i = 0; i <= n; i++) acb_set_fmpz(g + i, f + i); _acb_poly_evaluate(u2, g, n + 1, a, prec); _acb_poly_derivative(g, g, n + 1, prec); _acb_poly_evaluate(v2, g, n, a, prec); if (!acb_overlaps(u, u2) || !acb_overlaps(v, v2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n", n); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("u = "); acb_printd(u, 15); flint_printf("\n\n"); flint_printf("u2 = "); acb_printd(u2, 15); flint_printf("\n\n"); flint_printf("v = "); acb_printd(v, 15); flint_printf("\n\n"); flint_printf("v2 = "); acb_printd(v2, 15); flint_printf("\n\n"); flint_abort(); } acb_set(u2, a); acb_rising2_ui(u2, v, u2, n, prec); if (!acb_equal(u2, u)) { flint_printf("FAIL: aliasing 1\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("u = "); acb_printd(u, 15); flint_printf("\n\n"); flint_printf("u2 = "); acb_printd(u2, 15); flint_printf("\n\n"); flint_printf("n = %wu\n", n); flint_abort(); } acb_set(v2, a); acb_rising2_ui(u, v2, v2, n, prec); if (!acb_equal(v2, v)) { flint_printf("FAIL: aliasing 2\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("v = "); acb_printd(v, 15); flint_printf("\n\n"); flint_printf("v2 = "); acb_printd(v2, 15); flint_printf("\n\n"); flint_printf("n = %wu\n", n); flint_abort(); } acb_clear(a); acb_clear(u); acb_clear(v); acb_clear(u2); acb_clear(v2); _fmpz_vec_clear(f, n + 1); _acb_vec_clear(g, n + 1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-rising_ui.c000066400000000000000000000051201461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_rising_ui, state) { slong iter; /* check functional equation */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, xn, y, z; ulong n, m; acb_init(x); acb_init(xn); acb_init(y); acb_init(z); acb_randtest(x, state, 1 + n_randint(state, 4000), 10); n = n_randint(state, 80); m = n_randint(state, 40); acb_add_ui(xn, x, n, 1 + n_randint(state, 4000)); acb_rising_ui(y, x, n, 2 + n_randint(state, 4000)); acb_rising_ui(z, xn, m, 2 + n_randint(state, 4000)); acb_mul(y, y, z, 2 + n_randint(state, 4000)); acb_rising_ui(z, x, n + m, 2 + n_randint(state, 4000)); if (!acb_overlaps(y, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n", n); flint_printf("m = %wu\n", m); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("xn = "); acb_print(xn); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(xn); acb_clear(y); acb_clear(z); } /* aliasing of y and x */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y; ulong n; slong prec; acb_init(x); acb_init(y); acb_randtest(x, state, 1 + n_randint(state, 200), 10); acb_randtest(y, state, 1 + n_randint(state, 200), 10); n = n_randint(state, 100); prec = 2 + n_randint(state, 4000); acb_rising_ui(y, x, n, prec); acb_rising_ui(x, x, n, prec); if (!acb_equal(x, y)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("n = %wu\n", n); flint_abort(); } acb_clear(x); acb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-rising_ui_get_mag.c000066400000000000000000000027531461254215100212150ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_rising_ui_get_mag, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, z; mag_t b; ulong n; acb_init(x); acb_init(y); acb_init(z); mag_init(b); acb_randtest(x, state, 1 + n_randint(state, 400), 1 + n_randint(state, 100)); n = n_randint(state, 80); acb_rising_ui(y, x, n, 2 + n_randint(state, 400)); acb_rising_ui_get_mag(b, x, n); acb_zero(z); acb_add_error_mag(z, b); if (!acb_overlaps(y, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n", n); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(z); mag_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-root_ui.c000066400000000000000000000032101461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_root_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; ulong k; slong prec; prec = 2 + n_randint(state, 1000); k = n_randtest_not_zero(state); acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_root_ui(b, a, k, prec); acb_pow_ui(c, b, k, prec); if (!acb_contains(c, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("k = %wu\n", k); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_root_ui(a, a, k, prec); if (!acb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-rsqrt.c000066400000000000000000000126031461254215100167100ustar00rootroot00000000000000/* Copyright (C) 2013, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_rsqrt, state) { slong iter; /* check union */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, x, ra, rb, rc, rx; acb_init(a); acb_init(b); acb_init(c); acb_init(x); acb_init(ra); acb_init(rb); acb_init(rc); acb_init(rx); acb_randtest_precise(a, state, 1 + n_randint(state, 500), 1 + n_randint(state, 80)); acb_randtest_precise(b, state, 1 + n_randint(state, 500), 1 + n_randint(state, 80)); acb_randtest_precise(c, state, 1 + n_randint(state, 500), 1 + n_randint(state, 80)); acb_randtest(ra, state, 1 + n_randint(state, 500), 1 + n_randint(state, 80)); acb_randtest(rb, state, 1 + n_randint(state, 500), 1 + n_randint(state, 80)); acb_randtest(rc, state, 1 + n_randint(state, 500), 1 + n_randint(state, 80)); acb_randtest(rx, state, 1 + n_randint(state, 500), 1 + n_randint(state, 80)); acb_union(x, a, b, 2 + n_randint(state, 500)); acb_union(x, x, c, 2 + n_randint(state, 500)); acb_rsqrt(rx, x, 2 + n_randint(state, 500)); acb_rsqrt(ra, a, 2 + n_randint(state, 500)); acb_rsqrt(rb, b, 2 + n_randint(state, 500)); acb_rsqrt(rc, c, 2 + n_randint(state, 500)); if (!acb_overlaps(rx, ra)) { flint_printf("FAIL: overlap a\n\n"); flint_printf("a = "); acb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); acb_printn(c, 50, 0); flint_printf("\n\n"); flint_printf("x = "); acb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("ra = "); acb_printn(ra, 50, 0); flint_printf("\n\n"); flint_printf("rx = "); acb_printn(rx, 50, 0); flint_printf("\n\n"); flint_abort(); } if (!acb_overlaps(rx, rb)) { flint_printf("FAIL: overlap b\n\n"); flint_printf("a = "); acb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); acb_printn(c, 50, 0); flint_printf("\n\n"); flint_printf("x = "); acb_printn(x, 50, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("rb = "); acb_printn(rb, 50, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("rx = "); acb_printn(rx, 50, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } if (!acb_overlaps(rx, rc)) { flint_printf("FAIL: overlap c\n\n"); flint_printf("a = "); acb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); acb_printn(c, 50, 0); flint_printf("\n\n"); flint_printf("x = "); acb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("rc = "); acb_printn(rc, 50, 0); flint_printf("\n\n"); flint_printf("rx = "); acb_printn(rx, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(x); acb_clear(ra); acb_clear(rb); acb_clear(rc); acb_clear(rx); } /* check (a^(-1/2))^(-2) = a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 2000), 10); acb_randtest(b, state, 1 + n_randint(state, 2000), 10); prec = 2 + n_randint(state, 2000); acb_rsqrt(b, a, prec); acb_inv(c, b, prec); acb_mul(c, c, c, prec); if (!acb_contains(c, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_log(c, a, FLINT_MIN(prec, 200)); acb_mul_2exp_si(c, c, -1); acb_neg(c, c); acb_exp(c, c, FLINT_MIN(prec, 200)); if (!acb_overlaps(c, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_rsqrt(a, a, prec); if (!acb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sec.c000066400000000000000000000032531461254215100163100ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sec, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 300), 100); acb_randtest_special(a, state, 1 + n_randint(state, 300), 100); acb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { acb_sec(a, x, prec1); } else { acb_set(a, x); acb_sec(a, a, prec1); } acb_cos(b, x, prec2); acb_inv(b, b, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sech.c000066400000000000000000000032571461254215100164640ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sech, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 300), 100); acb_randtest_special(a, state, 1 + n_randint(state, 300), 100); acb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { acb_sech(a, x, prec1); } else { acb_set(a, x); acb_sech(a, a, prec1); } acb_cosh(b, x, prec2); acb_inv(b, b, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); acb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sgn.c000066400000000000000000000037141461254215100163270ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sgn, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, a, b; slong prec; acb_init(x); acb_init(a); acb_init(b); acb_randtest_special(x, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); acb_randtest_special(a, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); prec = 2 + n_randint(state, 200); acb_sgn(a, x, prec); if (acb_is_zero(x)) { acb_zero(b); } else { arb_zero(acb_realref(b)); acb_arg(acb_imagref(b), x, prec); acb_exp(b, b, prec); } if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_sgn(x, x, prec); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sin_cos.c000066400000000000000000000065541461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sin_cos, state) { slong iter; /* check sin(a+b) = cos(b)*sin(a) + cos(a)*sin(b) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, cosa, sina, cosb, sinb; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(cosa); acb_init(sina); acb_init(cosb); acb_init(sinb); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_add(c, a, b, prec); acb_sin(c, c, prec); acb_sin_cos(sina, cosa, a, prec); acb_sin_cos(sinb, cosb, b, prec); acb_mul(cosb, cosb, sina, prec); acb_mul(cosa, cosa, sinb, prec); acb_add(d, cosa, cosb, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: sin(a+b) = cos(b)*sin(a) + cos(a)*sin(b)\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(cosa); acb_clear(sina); acb_clear(cosb); acb_clear(sinb); } /* check cos(a+b) = cos(b)*cos(a) - sin(a)*sin(b) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, cosa, sina, cosb, sinb; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(cosa); acb_init(sina); acb_init(cosb); acb_init(sinb); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_add(c, a, b, prec); acb_cos(c, c, prec); acb_sin_cos(sina, cosa, a, prec); acb_sin_cos(sinb, cosb, b, prec); acb_mul(cosa, cosa, cosb, prec); acb_mul(sina, sina, sinb, prec); acb_sub(d, cosa, sina, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: cos(a+b) = cos(b)*cos(a) - sin(a)*sin(b)\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(cosa); acb_clear(sina); acb_clear(cosb); acb_clear(sinb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sin_pi.c000066400000000000000000000044621461254215100170220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sin_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_sin_pi(a, x, prec1); acb_sin_pi(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* compare with cos */ arb_const_pi(acb_realref(c), prec1); acb_mul_arb(y, x, acb_realref(c), prec1); acb_sin(c, y, prec1); if (!acb_overlaps(a, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_sin_pi(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sinc.c000066400000000000000000000040701461254215100164700ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sinc, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(a, state, 1 + n_randint(state, 400), 2 + n_randint(state, 100)); acb_randtest(b, state, 1 + n_randint(state, 400), 2 + n_randint(state, 100)); acb_randtest(c, state, 1 + n_randint(state, 400), 2 + n_randint(state, 100)); acb_sinc(b, a, 2 + n_randint(state, 400)); acb_sin(c, a, 2 + n_randint(state, 400)); acb_mul(d, b, a, 2 + n_randint(state, 400)); /* check consistency */ if (!acb_overlaps(c, d)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 30); flint_printf("\n\n"); flint_abort(); } acb_set(c, a); acb_sinc(c, c, 2 + n_randint(state, 400)); if (!acb_overlaps(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sinc_pi.c000066400000000000000000000031101461254215100171520ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sinc_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, z; slong prec; acb_init(x); acb_init(y); acb_init(z); prec = 2 + n_randint(state, 200); acb_randtest(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); acb_randtest(y, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); if (n_randint(state, 2)) { acb_set(y, x); acb_sinc_pi(y, y, prec); } else acb_sinc_pi(y, x, prec); acb_const_pi(z, prec); acb_mul(z, z, x, prec); acb_sinc(z, z, prec); if (!acb_overlaps(y, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sinh_cosh.c000066400000000000000000000066141461254215100175170ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sinh_cosh, state) { slong iter; /* check sinh(a+b) = cosh(b)*sinh(a) + cosh(a)*sinh(b) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, cosa, sina, cosb, sinb; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(cosa); acb_init(sina); acb_init(cosb); acb_init(sinb); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_add(c, a, b, prec); acb_sinh(c, c, prec); acb_sinh_cosh(sina, cosa, a, prec); acb_sinh_cosh(sinb, cosb, b, prec); acb_mul(cosb, cosb, sina, prec); acb_mul(cosa, cosa, sinb, prec); acb_add(d, cosa, cosb, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: sinh(a+b) = cosh(b)*sinh(a) + cosh(a)*sinh(b)\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(cosa); acb_clear(sina); acb_clear(cosb); acb_clear(sinb); } /* check cosh(a+b) = cosh(b)*cosh(a) + sinh(a)*sinh(b) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, d, cosa, sina, cosb, sinb; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(cosa); acb_init(sina); acb_init(cosb); acb_init(sinb); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_add(c, a, b, prec); acb_cosh(c, c, prec); acb_sinh_cosh(sina, cosa, a, prec); acb_sinh_cosh(sinb, cosb, b, prec); acb_mul(cosa, cosa, cosb, prec); acb_mul(sina, sina, sinb, prec); acb_add(d, cosa, sina, prec); if (!acb_overlaps(c, d)) { flint_printf("FAIL: cosh(a+b) = cosh(b)*cosh(a) + sinh(a)*sinh(b)\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(cosa); acb_clear(sina); acb_clear(cosb); acb_clear(sinb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sqrt.c000066400000000000000000000032211461254215100165220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sqrt, state) { slong iter; /* check (a^(1/2))^2 = a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec; acb_init(a); acb_init(b); acb_init(c); acb_randtest(a, state, 1 + n_randint(state, 2000), 10); acb_randtest(b, state, 1 + n_randint(state, 2000), 10); prec = 2 + n_randint(state, 2000); acb_sqrt(b, a, prec); acb_mul(c, b, b, prec); if (!acb_contains(c, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_sqrt(a, a, prec); if (!acb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-sqrts.c000066400000000000000000000041331461254215100167100ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_sqrts, state) { slong iter; /* Test: - acb_sqrts on y = x^2 gives both x and -x - acb_sqrts on a precise number does not lose precision */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { acb_t x, y1, y2, t; arf_t e; slong prec = 20 + n_randint(state, 1000); slong mag_bits = n_randint(state, 10); acb_init(x); acb_init(y1); acb_init(y2); acb_init(t); arf_init(e); acb_randtest(x, state, prec, mag_bits); acb_sqr(y1, x, prec); acb_sqrts(y1, y2, y1, prec); acb_neg(t, x); if (!(acb_contains(y1, x) && acb_contains(y2, t)) && !(acb_contains(y1, t) && acb_contains(y2, x))) { flint_printf("FAIL (containment)\n"); acb_printd(x, 10); flint_printf("\n"); acb_printd(y1, 10); flint_printf("\n"); acb_printd(y2, 10); flint_printf("\n"); flint_abort(); } acb_urandom(x, state, prec); acb_sqrts(y1, y2, x, prec); arf_one(e); arf_mul_2exp_si(e, e, -prec / 2 + 10); acb_get_mid(t, y1); acb_add_error_arf(t, e); if (!acb_contains(t, y1)) { flint_printf("FAIL (precision)\n"); flint_printf("prec = %wd, y1, x:\n", prec); acb_printd(y1, 10); flint_printf("\n"); acb_printd(x, 10); flint_printf("\n"); flint_abort(); } acb_clear(x); acb_clear(y1); acb_clear(y2); acb_clear(t); arf_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-tan.c000066400000000000000000000051231461254215100163160ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_tan, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_randtest(y, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_tan(a, x, prec1); acb_tan(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* check tan(x+y) = (tan(x) + tan(y)) / (1 - tan(x) tan(y)) */ acb_add(b, x, y, prec1); acb_tan(b, b, prec1); acb_tan(c, y, prec1); acb_add(d, a, c, prec1); acb_mul(c, a, c, prec1); acb_sub_ui(c, c, 1, prec1); acb_neg(c, c); acb_div(d, d, c, prec1); if (!acb_overlaps(b, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_tan(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-tan_pi.c000066400000000000000000000044631461254215100170140ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_tan_pi, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_tan_pi(a, x, prec1); acb_tan_pi(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* compare with tan */ arb_const_pi(acb_realref(c), prec1); acb_mul_arb(y, x, acb_realref(c), prec1); acb_tan(c, y, prec1); if (!acb_overlaps(a, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_tan_pi(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-tanh.c000066400000000000000000000051031461254215100164640ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_tanh, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_randtest(x, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); acb_randtest(y, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); acb_tanh(a, x, prec1); acb_tanh(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } /* check tanh(x+y) = (tanh(x) + tanh(y)) / (1 + tanh(x) tanh(y)) */ acb_add(b, x, y, prec1); acb_tanh(b, b, prec1); acb_tanh(c, y, prec1); acb_add(d, a, c, prec1); acb_mul(c, a, c, prec1); acb_add_ui(c, c, 1, prec1); acb_div(d, d, c, prec1); if (!acb_overlaps(b, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("d = "); acb_print(d); flint_printf("\n\n"); flint_abort(); } acb_tanh(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-urandom.c000066400000000000000000000024541461254215100172050ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #define N 10000 /* same as t-urandom in arb/, but ignore variance */ TEST_FUNCTION_START(acb_urandom, state) { slong iter; slong prec; acb_ptr rand; acb_t m; /* mean */ acb_t mp; arb_t tol; acb_init(m); acb_init(mp); arb_init(tol); rand = _acb_vec_init(N); prec = 299; for (iter = 0; iter < N; iter++) { acb_urandom(rand + iter, state, prec); acb_add(m, m, rand + iter, prec); } acb_div_si(m, m, N, prec); /* one percent deviation */ arb_set_str(tol, "0 +/- 0.01", prec); acb_set_arb_arb(mp, tol, tol); if (!acb_contains(mp, m)) { flint_printf("FAIL: mean\n\n"); flint_printf("m = "); acb_printd(m, 15); flint_printf("\n\n"); flint_abort(); } _acb_vec_clear(rand, N); acb_clear(m); acb_clear(mp); arb_clear(tol); TEST_FUNCTION_END(state); } #undef N flint-3.1.3/src/acb/test/t-vec_set_real_imag.c000066400000000000000000000027461461254215100211740ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_vec_set_real_imag, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong len = n_randint(state, 100); slong prec = 10 + n_randint(state, 100); slong mag_bits = n_randint(state, 10); arb_ptr re, im; acb_ptr z, t; slong k; re = _arb_vec_init(len); im = _arb_vec_init(len); z = _acb_vec_init(len); t = _acb_vec_init(len); for (k = 0; k < len; k++) { acb_randtest_precise(&z[k], state, prec, mag_bits); } _acb_vec_get_real(re, z, len); _acb_vec_get_imag(im, z, len); _acb_vec_set_real_imag(t, re, im, len); for (k = 0; k < len; k++) { if (!acb_equal(&z[k], &t[k])) { flint_printf("FAIL\n\n"); flint_abort(); } } _arb_vec_clear(re, len); _arb_vec_clear(im, len); _acb_vec_clear(z, len); _acb_vec_clear(t, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-vec_unit_roots.c000066400000000000000000000040751461254215100206030ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "acb.h" TEST_FUNCTION_START(acb_vec_unit_roots, state) { slong iter; for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { slong len, prec, order, k; acb_ptr vec; fmpq_t q; acb_t t; len = n_randint(state, 100); prec = 10 + n_randint(state, 200); switch (n_randint(state, 5)) { case 0: order = 1 + len * n_randint(state, 6); break; case 1: order = 1 + n_randint(state, 4 * len); break; default: order = 1 + n_randint(state, len); break; } if (n_randint(state, 2)) order = -order; vec = _acb_vec_init(len); acb_init(t); fmpq_init(q); _acb_vec_unit_roots(vec, order, len, prec); for (k = 0; k < len; k++) { if (order < 0) fmpq_set_si(q, -2 * k, -order); else fmpq_set_si(q, 2 * k, order); arb_sin_cos_pi_fmpq(acb_imagref(t), acb_realref(t), q, prec); if (!acb_overlaps(vec + k, t)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu, order = %wd, k = %wd, prec = %wd\n\n", len, order, k, prec); flint_printf("vec = "); acb_printn(vec + k, 30, 0); flint_printf("\n\n"); flint_printf("t = "); acb_printn(t, 30, 0); flint_printf("\n\n"); flint_abort(); } } _acb_vec_clear(vec, len); acb_clear(t); fmpq_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/test/t-zeta.c000066400000000000000000000026241461254215100165020ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" TEST_FUNCTION_START(acb_zeta, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 500); prec2 = prec1 + 30; acb_init(a); acb_init(b); acb_init(c); arb_randtest_precise(acb_realref(a), state, 1 + n_randint(state, 500), 5); arb_randtest_precise(acb_imagref(a), state, 1 + n_randint(state, 500), 3); acb_zeta(b, a, prec1); acb_zeta(c, a, prec2); if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb/unit_root.c000066400000000000000000000017301461254215100163360ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb.h" static void _acb_unit_root(acb_t res, ulong order, slong prec) { fmpq_t t; fmpq_init(t); fmpq_set_si(t, 2, order); arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); fmpq_clear(t); } void acb_unit_root(acb_t res, ulong order, slong prec) { switch (order) { case 1: acb_one(res); break; case 2: acb_set_si(res, -1); break; case 4: acb_onei(res); break; default: _acb_unit_root(res, order, prec); break; } } flint-3.1.3/src/acb/urandom.c000066400000000000000000000016071461254215100157640ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void acb_urandom(acb_t z, flint_rand_t state, slong prec) { arb_t abs; slong k; int done = 0; arb_init(abs); while (!done) { arb_urandom(acb_realref(z), state, prec); arb_urandom(acb_imagref(z), state, prec); /* Re-sample if z is outside the unit circle */ acb_abs(abs, z, prec); arb_sub_si(abs, abs, 1, prec); done = arb_is_nonpositive(abs); } k = n_randint(state, 4); acb_mul_i_pow_si(z, z, k); arb_clear(abs); } flint-3.1.3/src/acb/vec_clear.c000066400000000000000000000010231461254215100162320ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void _acb_vec_clear(acb_ptr v, slong n) { slong i; for (i = 0; i < n; i++) acb_clear(v + i); flint_free(v); } flint-3.1.3/src/acb/vec_init.c000066400000000000000000000011061461254215100161110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" acb_ptr _acb_vec_init(slong n) { slong i; acb_ptr v = (acb_ptr) flint_malloc(sizeof(acb_struct) * n); for (i = 0; i < n; i++) acb_init(v + i); return v; } flint-3.1.3/src/acb/vec_set_powers.c000066400000000000000000000014451461254215100173460ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void _acb_vec_set_powers(acb_ptr xs, const acb_t x, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { if (i == 0) acb_one(xs + i); else if (i == 1) acb_set_round(xs + i, x, prec); else if (i % 2 == 0) acb_mul(xs + i, xs + i / 2, xs + i / 2, prec); else acb_mul(xs + i, xs + i - 1, x, prec); } } flint-3.1.3/src/acb/vec_sort_pretty.c000066400000000000000000000023541461254215100175520ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb.h" #ifndef __compar_fn_t #if defined(_MSC_VER) typedef int(*__compar_fn_t) (const void *, const void *); #else typedef int(*__compar_fn_t) (__const void *, __const void *); #endif #endif int acb_cmp_pretty(const acb_t a, const acb_t b) { arb_t t, u, v; int res; arb_init(t); arb_init(u); arb_init(v); arb_abs(u, acb_imagref(a)); arb_abs(v, acb_imagref(b)); arb_sub(t, u, v, MAG_BITS); res = 0; if (arb_contains_zero(t)) { arb_sub(t, acb_realref(a), acb_realref(b), MAG_BITS); res = arb_is_positive(t) ? 1 : -1; } else { res = arb_is_positive(t) ? 1 : -1; } arb_clear(t); arb_clear(u); arb_clear(v); return res; } void _acb_vec_sort_pretty(acb_ptr vec, slong len) { qsort(vec, len, sizeof(acb_struct), (__compar_fn_t) acb_cmp_pretty); } flint-3.1.3/src/acb/vec_unit_roots.c000066400000000000000000000037221461254215100173610ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" void _acb_vec_unit_roots(acb_ptr res, slong n, slong len, slong prec) { int conj = 0; slong k, len1, wp; acb_t t; if (len <= 0) return; if (n == 0) { flint_throw(FLINT_ERROR, "\n_acb_vec_unit_roots: need order != 0\n"); } if (n < 0) { n = -n; conj = 1; } if (n % 4 == 0) len1 = FLINT_MIN(len, n / 8 + 1); else if (n % 2 == 0) len1 = FLINT_MIN(len, n / 4 + 1); else len1 = FLINT_MIN(len, n / 2 + 1); wp = prec + 6 + 2 * FLINT_BIT_COUNT(len1); acb_init(t); acb_unit_root(t, n, prec); _acb_vec_set_powers(res, t, len1, wp); acb_clear(t); _acb_vec_set_round(res, res, len1, prec); if (n % 4 == 0) { for (k = n / 8 + 1; k <= n / 4 && k < len; k++) { arb_set(acb_realref(res + k), acb_imagref(res + n / 4 - k)); arb_set(acb_imagref(res + k), acb_realref(res + n / 4 - k)); } for (k = n / 4 + 1; k <= n / 2 && k < len; k++) acb_mul_onei(res + k, res + k - n / 4); } else if (n % 2 == 0) { for (k = n / 4 + 1; k <= n / 2 && k < len; k++) { acb_set(res + k, res + n / 2 - k); arb_neg(acb_realref(res + k), acb_realref(res + k)); } } for (k = n / 2 + 1; k < len && k < n; k++) acb_conj(res + k, res + n - k); for (k = n; k < len; k++) acb_set(res + k, res - n + k); if (conj) { for (k = 1; k < len; k++) acb_conj(res + k, res + k); } } flint-3.1.3/src/acb/zeta.c000066400000000000000000000017671461254215100152710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_poly.h" #include "acb_dirichlet.h" void acb_zeta_si(acb_t z, slong s, slong prec) { if (s >= 0) { arb_zeta_ui(acb_realref(z), s, prec); } else { arb_bernoulli_ui(acb_realref(z), 1-s, prec); arb_div_ui(acb_realref(z), acb_realref(z), 1-s, prec); arb_neg(acb_realref(z), acb_realref(z)); } arb_zero(acb_imagref(z)); return; } void acb_hurwitz_zeta(acb_t z, const acb_t s, const acb_t a, slong prec) { acb_dirichlet_hurwitz(z, s, a, prec); } void acb_zeta(acb_t z, const acb_t s, slong prec) { acb_dirichlet_zeta(z, s, prec); } flint-3.1.3/src/acb_calc.h000066400000000000000000000032721461254215100153060ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_CALC_H #define ACB_CALC_H #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif typedef int (*acb_calc_func_t)(acb_ptr out, const acb_t inp, void * param, slong order, slong prec); /* Integration (old) */ void acb_calc_cauchy_bound(arb_t bound, acb_calc_func_t func, void * param, const acb_t x, const arb_t radius, slong maxdepth, slong prec); int acb_calc_integrate_taylor(acb_t res, acb_calc_func_t func, void * param, const acb_t a, const acb_t b, const arf_t inner_radius, const arf_t outer_radius, slong accuracy_goal, slong prec); /* Integration */ typedef struct { slong deg_limit; slong eval_limit; slong depth_limit; int use_heap; int verbose; } acb_calc_integrate_opt_struct; typedef acb_calc_integrate_opt_struct acb_calc_integrate_opt_t[1]; void acb_calc_integrate_opt_init(acb_calc_integrate_opt_t options); int acb_calc_integrate(acb_t res, acb_calc_func_t f, void * param, const acb_t a, const acb_t b, slong goal, const mag_t tol, const acb_calc_integrate_opt_t options, slong prec); int acb_calc_integrate_gl_auto_deg(acb_t res, slong * eval_count, acb_calc_func_t f, void * param, const acb_t a, const acb_t b, const mag_t tol, slong deg_limit, int verbose, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_calc/000077500000000000000000000000001461254215100151315ustar00rootroot00000000000000flint-3.1.3/src/acb_calc/cauchy_bound.c000066400000000000000000000047621461254215100177510ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_calc.h" void acb_calc_cauchy_bound(arb_t bound, acb_calc_func_t func, void * param, const acb_t x, const arb_t radius, slong maxdepth, slong prec) { slong i, n, depth, wp; arb_t pi, theta, v, s1, c1, s2, c2, st, ct; acb_t t, u; arb_t b; arb_init(pi); arb_init(theta); arb_init(v); arb_init(s1); arb_init(c1); arb_init(s2); arb_init(c2); arb_init(st); arb_init(ct); acb_init(t); acb_init(u); arb_init(b); wp = prec + 20; arb_const_pi(pi, wp); arb_zero_pm_inf(b); for (depth = 0, n = 16; depth < maxdepth; n *= 2, depth++) { arb_zero(b); /* theta = 2 pi / n */ arb_div_ui(theta, pi, n, wp); arb_mul_2exp_si(theta, theta, 1); /* sine and cosine of i*theta and (i+1)*theta */ arb_zero(s1); arb_one(c1); arb_sin_cos(st, ct, theta, wp); arb_set(s2, st); arb_set(c2, ct); for (i = 0; i < n; i++) { /* sine and cosine of 2 pi ([i,i+1]/n) */ /* since we use power of two subdivision points, the sine and cosine are monotone on each subinterval */ arb_union(acb_realref(t), c1, c2, wp); arb_union(acb_imagref(t), s1, s2, wp); acb_mul_arb(t, t, radius, wp); acb_add(t, t, x, prec); /* next angle */ arb_mul(v, c2, ct, wp); arb_mul(c1, s2, st, wp); arb_sub(c1, v, c1, wp); arb_mul(v, c2, st, wp); arb_mul(s1, s2, ct, wp); arb_add(s1, v, s1, wp); arb_swap(c1, c2); arb_swap(s1, s2); func(u, t, param, 1, prec); acb_abs(v, u, prec); arb_add(b, b, v, prec); } arb_div_ui(b, b, n, prec); if (arb_is_positive(b)) break; } arb_set(bound, b); arb_clear(pi); arb_clear(theta); arb_clear(v); acb_clear(t); acb_clear(u); arb_clear(b); arb_clear(s1); arb_clear(c1); arb_clear(s2); arb_clear(c2); arb_clear(st); arb_clear(ct); } flint-3.1.3/src/acb_calc/integrate.c000066400000000000000000000230421461254215100172600ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_calc.h" #include "acb_calc.h" static void quad_simple(acb_t res, acb_calc_func_t f, void * param, const acb_t a, const acb_t b, slong prec) { acb_t mid, delta, wide; mag_t tmpm; acb_init(mid); acb_init(delta); acb_init(wide); mag_init(tmpm); /* delta = (b-a)/2 */ acb_sub(delta, b, a, prec); acb_mul_2exp_si(delta, delta, -1); /* mid = (a+b)/2 */ acb_add(mid, a, b, prec); acb_mul_2exp_si(mid, mid, -1); /* wide = mid +- [delta] */ acb_set(wide, mid); arb_get_mag(tmpm, acb_realref(delta)); arb_add_error_mag(acb_realref(wide), tmpm); arb_get_mag(tmpm, acb_imagref(delta)); arb_add_error_mag(acb_imagref(wide), tmpm); /* Direct evaluation: integral = (b-a) * f([a,b]). */ f(res, wide, param, 0, prec); acb_mul(res, res, delta, prec); acb_mul_2exp_si(res, res, 1); acb_clear(mid); acb_clear(delta); acb_clear(wide); mag_clear(tmpm); } static void heap_up(acb_ptr as, acb_ptr bs, acb_ptr vs, mag_ptr ms, slong n) { slong i, max, l, r; i = 0; for (;;) { max = i; l = 2 * i + 1; r = 2 * i + 2; if (l < n && mag_cmp(ms + l, ms + max) > 0) max = l; if (r < n && mag_cmp(ms + r, ms + max) > 0) max = r; if (max != i) { acb_swap(as + i, as + max); acb_swap(bs + i, bs + max); acb_swap(vs + i, vs + max); mag_swap(ms + i, ms + max); i = max; } else { break; } } } static void heap_down(acb_ptr as, acb_ptr bs, acb_ptr vs, mag_ptr ms, slong n) { slong j, k; k = n - 1; j = (k - 1) / 2; while (k > 0 && mag_cmp(ms + j, ms + k) < 0) { acb_swap(as + j, as + k); acb_swap(bs + j, bs + k); acb_swap(vs + j, vs + k); mag_swap(ms + j, ms + k); k = j; j = (j - 1) / 2; } } static int _acb_overlaps(acb_t tmp, const acb_t a, const acb_t b, slong prec) { acb_sub(tmp, a, b, prec); return acb_contains_zero(tmp); } int acb_calc_integrate(acb_t res, acb_calc_func_t f, void * param, const acb_t a, const acb_t b, slong goal, const mag_t tol, const acb_calc_integrate_opt_t options, slong prec) { acb_ptr as, bs, vs; mag_ptr ms; acb_t s, t, u; mag_t tmpm, tmpn, new_tol; slong depth_limit, eval_limit, deg_limit; slong depth, depth_max, eval, feval, top; slong leaf_interval_count; slong alloc; int stopping, real_error, use_heap, status, gl_status, verbose; if (options == NULL) { acb_calc_integrate_opt_t opt; acb_calc_integrate_opt_init(opt); return acb_calc_integrate(res, f, param, a, b, goal, tol, opt, prec); } status = ARB_CALC_SUCCESS; acb_init(s); acb_init(t); acb_init(u); mag_init(tmpm); mag_init(tmpn); mag_init(new_tol); depth_limit = options->depth_limit; if (depth_limit <= 0) depth_limit = 2 * prec; depth_limit = FLINT_MAX(depth_limit, 1); eval_limit = options->eval_limit; if (eval_limit <= 0) eval_limit = 1000 * prec + prec * prec; eval_limit = FLINT_MAX(eval_limit, 1); goal = FLINT_MAX(goal, 0); deg_limit = options->deg_limit; if (deg_limit <= 0) deg_limit = 0.5 * FLINT_MIN(goal, prec) + 60; verbose = options->verbose; use_heap = options->use_heap; alloc = 4; as = _acb_vec_init(alloc); bs = _acb_vec_init(alloc); vs = _acb_vec_init(alloc); ms = _mag_vec_init(alloc); /* Compute initial crude estimate for the whole interval. */ acb_set(as, a); acb_set(bs, b); quad_simple(vs, f, param, as, bs, prec); mag_hypot(ms, arb_radref(acb_realref(vs)), arb_radref(acb_imagref(vs))); depth = depth_max = 1; eval = 1; stopping = 0; leaf_interval_count = 0; /* Adjust absolute tolerance based on new information. */ acb_get_mag_lower(tmpm, vs); mag_mul_2exp_si(tmpm, tmpm, -goal); mag_max(new_tol, tol, tmpm); acb_zero(s); while (depth >= 1) { if (stopping == 0 && eval >= eval_limit - 1) { if (verbose > 0) flint_printf("stopping at eval_limit %wd\n", eval_limit); status = ARB_CALC_NO_CONVERGENCE; stopping = 1; continue; } if (use_heap) top = 0; else top = depth - 1; /* We are done with this subinterval. */ if (mag_cmp(ms + top, new_tol) < 0 || _acb_overlaps(u, as + top, bs + top, prec) || stopping) { acb_add(s, s, vs + top, prec); leaf_interval_count++; depth--; if (use_heap && depth > 0) { acb_swap(as, as + depth); acb_swap(bs, bs + depth); acb_swap(vs, vs + depth); mag_swap(ms, ms + depth); heap_up(as, bs, vs, ms, depth); } continue; } /* Attempt using Gauss-Legendre rule. */ if (acb_is_finite(vs + top)) { gl_status = acb_calc_integrate_gl_auto_deg(u, &feval, f, param, as + top, bs + top, new_tol, deg_limit, verbose > 1, prec); eval += feval; /* We are done with this subinterval. */ if (gl_status == ARB_CALC_SUCCESS) { /* We know that the result is real. */ real_error = acb_is_finite(vs + top) && acb_is_real(vs + top); if (real_error) arb_zero(acb_imagref(u)); acb_add(s, s, u, prec); leaf_interval_count++; /* Adjust absolute tolerance based on new information. */ acb_get_mag_lower(tmpm, u); mag_mul_2exp_si(tmpm, tmpm, -goal); mag_max(new_tol, new_tol, tmpm); depth--; if (use_heap && depth > 0) { acb_swap(as, as + depth); acb_swap(bs, bs + depth); acb_swap(vs, vs + depth); mag_swap(ms, ms + depth); heap_up(as, bs, vs, ms, depth); } continue; } } if (depth >= depth_limit - 1) { if (verbose > 0) flint_printf("stopping at depth_limit %wd\n", depth_limit); status = ARB_CALC_NO_CONVERGENCE; stopping = 1; continue; } if (depth >= alloc - 1) { slong k; as = flint_realloc(as, 2 * alloc * sizeof(acb_struct)); bs = flint_realloc(bs, 2 * alloc * sizeof(acb_struct)); vs = flint_realloc(vs, 2 * alloc * sizeof(acb_struct)); ms = flint_realloc(ms, 2 * alloc * sizeof(mag_struct)); for (k = alloc; k < 2 * alloc; k++) { acb_init(as + k); acb_init(bs + k); acb_init(vs + k); mag_init(ms + k); } alloc *= 2; } /* Bisection. */ /* Interval [depth] becomes [mid, b]. */ acb_set(bs + depth, bs + top); acb_add(as + depth, as + top, bs + top, prec); acb_mul_2exp_si(as + depth, as + depth, -1); /* Interval [top] becomes [a, mid]. */ acb_set(bs + top, as + depth); /* Evaluate on [a, mid] */ quad_simple(vs + top, f, param, as + top, bs + top, prec); mag_hypot(ms + top, arb_radref(acb_realref(vs + top)), arb_radref(acb_imagref(vs + top))); eval++; /* Adjust absolute tolerance based on new information. */ acb_get_mag_lower(tmpm, vs + top); mag_mul_2exp_si(tmpm, tmpm, -goal); mag_max(new_tol, new_tol, tmpm); /* Evaluate on [mid, b] */ quad_simple(vs + depth, f, param, as + depth, bs + depth, prec); mag_hypot(ms + depth, arb_radref(acb_realref(vs + depth)), arb_radref(acb_imagref(vs + depth))); eval++; /* Adjust absolute tolerance based on new information. */ acb_get_mag_lower(tmpm, vs + depth); mag_mul_2exp_si(tmpm, tmpm, -goal); mag_max(new_tol, new_tol, tmpm); /* Make the interval with the larger error the priority. */ if (mag_cmp(ms + top, ms + depth) < 0) { acb_swap(as + top, as + depth); acb_swap(bs + top, bs + depth); acb_swap(vs + top, vs + depth); mag_swap(ms + top, ms + depth); } if (use_heap) { heap_up(as, bs, vs, ms, depth); heap_down(as, bs, vs, ms, depth + 1); } depth++; depth_max = FLINT_MAX(depth, depth_max); } if (verbose > 0) { flint_printf("depth %wd/%wd, eval %wd/%wd, %wd leaf intervals\n", depth_max, depth_limit, eval, eval_limit, leaf_interval_count); } acb_set(res, s); _acb_vec_clear(as, alloc); _acb_vec_clear(bs, alloc); _acb_vec_clear(vs, alloc); _mag_vec_clear(ms, alloc); acb_clear(s); acb_clear(t); acb_clear(u); mag_clear(tmpm); mag_clear(tmpn); mag_clear(new_tol); return status; } flint-3.1.3/src/acb_calc/integrate_gl_auto_deg.c000066400000000000000000000237671461254215100216270ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "acb.h" #include "arb_hypgeom.h" #include "arb_calc.h" #include "acb_calc.h" /* Gauss-Legendre quadrature nodes are cached to speed up multiple integrations and adaptive subdivision. The steps of 2^(n/2) used here give slightly better performance than steps of 2^n (we use at most 1.4x more points than needed and not 2x more points) but may require more precomputation. */ #define GL_STEPS 38 const slong gl_steps[GL_STEPS] = {1, 2, 4, 6, 8, 12, 16, 22, 32, 46, 64, 90, 128, 182, 256, 362, 512, 724, 1024, 1448, 2048, 2896, 4096, 5792, 8192, 11586, 16384, 23170, 32768, 46340, 65536, 92682, 131072, 185364, 262144, 370728, 524288, 741456}; typedef struct { slong gl_prec[GL_STEPS]; arb_ptr gl_nodes[GL_STEPS]; arb_ptr gl_weights[GL_STEPS]; } gl_cache_struct; FLINT_TLS_PREFIX gl_cache_struct * gl_cache = NULL; void gl_cleanup(void) { slong i; if (gl_cache == NULL) return; for (i = 0; i < GL_STEPS; i++) { if (gl_cache->gl_prec[i] != 0) { _arb_vec_clear(gl_cache->gl_nodes[i], (gl_steps[i] + 1) / 2); _arb_vec_clear(gl_cache->gl_weights[i], (gl_steps[i] + 1) / 2); } } flint_free(gl_cache); gl_cache = NULL; } void gl_init(void) { gl_cache = flint_calloc(1, sizeof(gl_cache_struct)); flint_register_cleanup_function(gl_cleanup); } /* Compute GL node and weight of index k for n = gl_steps[i]. Cached. */ typedef struct { arb_ptr nodes; arb_ptr weights; slong n; slong wp; } nodes_work_t; static void nodes_worker(slong jj, nodes_work_t * work) { arb_hypgeom_legendre_p_ui_root(work->nodes + jj, work->weights + jj, work->n, jj, work->wp); } /* if k >= 0, compute the node and weight of index k */ /* if k < 0, compute the first (n+1)/2 nodes and weights (the others are given by symmetry) */ void acb_calc_gl_node(arb_ptr x, arb_ptr w, slong i, slong k, slong prec) { slong n, kk, wp; int all; if (i < 0 || i >= GL_STEPS || prec < 2) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (gl_cache == NULL) gl_init(); n = gl_steps[i]; if (k >= n) flint_throw(FLINT_ERROR, "(%s)\n", __func__); all = (k < 0); if (gl_cache->gl_prec[i] < prec) { nodes_work_t work; if (gl_cache->gl_prec[i] == 0) { gl_cache->gl_nodes[i] = _arb_vec_init((n + 1) / 2); gl_cache->gl_weights[i] = _arb_vec_init((n + 1) / 2); } wp = FLINT_MAX(prec, gl_cache->gl_prec[i] * 2 + 30); work.nodes = gl_cache->gl_nodes[i]; work.weights = gl_cache->gl_weights[i]; work.n = n; work.wp = wp; flint_parallel_do((do_func_t) nodes_worker, &work, (n + 1) / 2, -1, FLINT_PARALLEL_STRIDED); gl_cache->gl_prec[i] = wp; } if (all) { for (k = 0; k < (n + 1) / 2; k++) { arb_set_round(x + k, gl_cache->gl_nodes[i] + k, prec); arb_set_round(w + k, gl_cache->gl_weights[i] + k, prec); } } else { if (2 * k < n) kk = k; else kk = n - 1 - k; if (2 * k < n) arb_set_round(x, gl_cache->gl_nodes[i] + kk, prec); else arb_neg_round(x, gl_cache->gl_nodes[i] + kk, prec); arb_set_round(w, gl_cache->gl_weights[i] + kk, prec); } } typedef struct { slong n; slong prec; arb_srcptr x; arb_srcptr w; acb_srcptr delta; acb_srcptr mid; acb_ptr v; acb_calc_func_t f; void * param; } gl_work_t; static void gl_worker(slong k, gl_work_t * args) { arb_t x, w; acb_t t; slong k2; slong prec = args->prec; slong n = args->n; acb_ptr v = args->v; arb_init(x); arb_init(w); acb_init(t); if (2 * k < n) k2 = k; else k2 = n - 1 - k; acb_mul_arb(t, args->delta, args->x + k2, prec); if (k2 != k) acb_neg(t, t); acb_add(t, t, args->mid, prec); args->f(v + k, t, args->param, 0, prec); acb_mul_arb(v + k, v + k, args->w + k2, prec); arb_clear(x); arb_clear(w); acb_clear(t); } int acb_calc_integrate_gl_auto_deg(acb_t res, slong * eval_count, acb_calc_func_t f, void * param, const acb_t a, const acb_t b, const mag_t tol, slong deg_limit, int verbose, slong prec) { acb_t mid, delta, wide; mag_t tmpm; slong status; acb_t s, v; mag_t M, X, Y, rho, err, t, best_rho; slong k, Xexp; slong i, n, best_n; status = ARB_CALC_NO_CONVERGENCE; if (deg_limit <= 0) { acb_indeterminate(res); eval_count[0] = 0; return status; } acb_init(mid); acb_init(delta); acb_init(wide); mag_init(tmpm); /* delta = (b-a)/2 */ acb_sub(delta, b, a, prec); acb_mul_2exp_si(delta, delta, -1); /* mid = (a+b)/2 */ acb_add(mid, a, b, prec); acb_mul_2exp_si(mid, mid, -1); acb_init(s); acb_init(v); mag_init(M); mag_init(X); mag_init(Y); mag_init(rho); mag_init(t); mag_init(err); mag_init(best_rho); best_n = -1; eval_count[0] = 0; mag_inf(err); for (Xexp = 0; Xexp < prec /* && Xexp == 0 */; Xexp += FLINT_MAX(1, Xexp)) { mag_one(X); mag_mul_2exp_si(X, X, Xexp + 1); /* rho = X + sqrt(X^2 - 1) (lower bound) */ mag_mul_lower(rho, X, X); mag_one(t); mag_sub_lower(rho, rho, t); mag_sqrt_lower(rho, rho); mag_add_lower(rho, rho, X); /* Y = sqrt(X^2 - 1) (upper bound) */ mag_mul(Y, X, X); mag_one(t); mag_sub(Y, Y, t); mag_sqrt(Y, Y); acb_zero(wide); mag_set(arb_radref(acb_realref(wide)), X); mag_set(arb_radref(acb_imagref(wide)), Y); /* transform to [a,b] */ acb_mul(wide, wide, delta, prec); acb_add(wide, wide, mid, prec); f(v, wide, param, 1, prec); eval_count[0]++; /* no chance */ if (!acb_is_finite(v)) break; /* M = (b-a)/2 |f| */ acb_get_mag(M, v); acb_get_mag(tmpm, delta); mag_mul(M, M, tmpm); /* Search for the smallest n that gives err < tol (if possible) */ for (i = 0; i < GL_STEPS && gl_steps[i] <= deg_limit; i++) { n = gl_steps[i]; /* (64/15) M / ((rho-1) rho^(2n-1)) */ mag_pow_ui_lower(t, rho, 2 * n - 1); mag_one(tmpm); mag_sub_lower(tmpm, rho, tmpm); mag_mul_lower(t, t, tmpm); mag_mul_ui_lower(t, t, 15); mag_div(t, M, t); mag_mul_2exp_si(t, t, 6); if (mag_cmp(t, tol) < 0) { status = ARB_CALC_SUCCESS; /* The best so far. */ if (best_n == -1 || n < best_n) { mag_set(err, t); mag_set(best_rho, rho); best_n = n; } /* Best possible n. */ if (n == 1) break; } } } /* Evaluate best found Gauss-Legendre quadrature rule. */ if (status == ARB_CALC_SUCCESS) { slong nt; arb_t x, w; arb_init(x); arb_init(w); if (verbose) { acb_get_mag(tmpm, delta); flint_printf(" {GL deg %wd on [", best_n); acb_printn(a, 10, ARB_STR_NO_RADIUS); flint_printf(", "); acb_printn(b, 10, ARB_STR_NO_RADIUS); flint_printf("], delta "); mag_printd(tmpm, 5); flint_printf(", rho "); mag_printd(best_rho, 5); flint_printf(", tol "); mag_printd(tol, 3); flint_printf("}\n"); } if (best_n == -1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); for (i = 0; i < GL_STEPS; i++) if (gl_steps[i] == best_n) break; nt = flint_get_num_threads(); if (nt >= 2 && best_n >= 2) { gl_work_t work; acb_ptr v; arb_ptr x, w; v = _acb_vec_init(best_n); w = _arb_vec_init((best_n + 1) / 2); x = _arb_vec_init((best_n + 1) / 2); acb_calc_gl_node(x, w, i, -1, prec); work.n = best_n; work.x = x; work.w = w; work.prec = prec; work.delta = delta; work.mid = mid; work.v = v; work.f = f; work.param = param; flint_parallel_do((do_func_t) gl_worker, &work, best_n, -1, FLINT_PARALLEL_STRIDED); acb_add(s, v, v + 1, prec); for (k = 2; k < best_n; k++) acb_add(s, s, v + k, prec); _acb_vec_clear(v, best_n); _arb_vec_clear(x, (best_n + 1) / 2); _arb_vec_clear(w, (best_n + 1) / 2); } else { acb_zero(s); for (k = 0; k < best_n; k++) { acb_calc_gl_node(x, w, i, k, prec); acb_mul_arb(wide, delta, x, prec); acb_add(wide, wide, mid, prec); f(v, wide, param, 0, prec); acb_addmul_arb(s, v, w, prec); } } eval_count[0] += best_n; acb_mul(res, s, delta, prec); acb_add_error_mag(res, err); arb_clear(x); arb_clear(w); } else { acb_indeterminate(res); } acb_clear(s); acb_clear(v); mag_clear(M); mag_clear(X); mag_clear(Y); mag_clear(rho); mag_clear(t); mag_clear(err); mag_clear(best_rho); acb_clear(mid); acb_clear(delta); acb_clear(wide); mag_clear(tmpm); return status; } flint-3.1.3/src/acb_calc/integrate_opt_init.c000066400000000000000000000011511461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_calc.h" void acb_calc_integrate_opt_init(acb_calc_integrate_opt_t options) { options->deg_limit = 0; options->eval_limit = 0; options->depth_limit = 0; options->use_heap = 0; options->verbose = 0; } flint-3.1.3/src/acb_calc/integrate_taylor.c000066400000000000000000000150701461254215100206540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "arb_calc.h" #include "acb_calc.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif int acb_calc_integrate_taylor(acb_t res, acb_calc_func_t func, void * param, const acb_t a, const acb_t b, const arf_t inner_radius, const arf_t outer_radius, slong accuracy_goal, slong prec) { slong num_steps, step, N, bp; int result; acb_t delta, m, x, y1, y2, sum; acb_ptr taylor_poly; arf_t err; acb_init(delta); acb_init(m); acb_init(x); acb_init(y1); acb_init(y2); acb_init(sum); arf_init(err); acb_sub(delta, b, a, prec); /* precision used for bounds calculations */ bp = MAG_BITS; /* compute the number of steps */ { arf_t t; arf_init(t); acb_get_abs_ubound_arf(t, delta, bp); arf_div(t, t, inner_radius, bp, ARF_RND_UP); arf_mul_2exp_si(t, t, -1); num_steps = (slong) (arf_get_d(t, ARF_RND_UP) + 1.0); /* make sure it's not something absurd */ num_steps = FLINT_MIN(num_steps, 10 * prec); num_steps = FLINT_MAX(num_steps, 1); arf_clear(t); } result = ARB_CALC_SUCCESS; acb_zero(sum); for (step = 0; step < num_steps; step++) { /* midpoint of subinterval */ acb_mul_ui(m, delta, 2 * step + 1, prec); acb_div_ui(m, m, 2 * num_steps, prec); acb_add(m, m, a, prec); if (arb_calc_verbose) { flint_printf("integration point %wd/%wd: ", 2 * step + 1, 2 * num_steps); acb_printd(m, 15); flint_printf("\n"); } /* evaluate at +/- x */ /* TODO: exactify m, and include error in x? */ acb_div_ui(x, delta, 2 * num_steps, prec); /* compute bounds and number of terms to use */ { arb_t cbound, xbound, rbound; arf_t C, D, R, X, T; double DD, TT, NN; arb_init(cbound); arb_init(xbound); arb_init(rbound); arf_init(C); arf_init(D); arf_init(R); arf_init(X); arf_init(T); /* R is the outer radius */ arf_set(R, outer_radius); /* X = upper bound for |x| */ acb_get_abs_ubound_arf(X, x, bp); arb_set_arf(xbound, X); /* Compute C(m,R). Important subtlety: due to rounding when computing m, we will in general be farther than R away from the integration path. But since acb_calc_cauchy_bound actually integrates over the area traced by a complex interval, it will catch any extra singularities (giving an infinite bound). */ arb_set_arf(rbound, outer_radius); acb_calc_cauchy_bound(cbound, func, param, m, rbound, 8, bp); arf_set_mag(C, arb_radref(cbound)); arf_add(C, arb_midref(cbound), C, bp, ARF_RND_UP); /* Sanity check: we need C < inf and R > X */ if (arf_is_finite(C) && arf_cmp(R, X) > 0) { /* Compute upper bound for D = C * R * X / (R - X) */ arf_mul(D, C, R, bp, ARF_RND_UP); arf_mul(D, D, X, bp, ARF_RND_UP); arf_sub(T, R, X, bp, ARF_RND_DOWN); arf_div(D, D, T, bp, ARF_RND_UP); /* Compute upper bound for T = (X / R) */ arf_div(T, X, R, bp, ARF_RND_UP); /* Choose N */ /* TODO: use arf arithmetic to avoid overflow */ /* TODO: use relative accuracy (look at |f(m)|?) */ DD = arf_get_d(D, ARF_RND_UP); TT = arf_get_d(T, ARF_RND_UP); NN = -(accuracy_goal * 0.69314718055994530942 + log(DD)) / log(TT); N = NN + 0.5; N = FLINT_MIN(N, 100 * prec); N = FLINT_MAX(N, 1); /* Tail bound: D / (N + 1) * T^N */ { mag_t TT; mag_init(TT); arf_get_mag(TT, T); mag_pow_ui(TT, TT, N); arf_set_mag(T, TT); mag_clear(TT); } arf_mul(D, D, T, bp, ARF_RND_UP); arf_div_ui(err, D, N + 1, bp, ARF_RND_UP); } else { N = 1; arf_pos_inf(err); result = ARB_CALC_NO_CONVERGENCE; } if (arb_calc_verbose) { flint_printf("N = %wd; bound: ", N); arf_printd(err, 15); flint_printf("\n"); flint_printf("R: "); arf_printd(R, 15); flint_printf("\n"); flint_printf("C: "); arf_printd(C, 15); flint_printf("\n"); flint_printf("X: "); arf_printd(X, 15); flint_printf("\n"); } arb_clear(cbound); arb_clear(xbound); arb_clear(rbound); arf_clear(C); arf_clear(D); arf_clear(R); arf_clear(X); arf_clear(T); } /* evaluate Taylor polynomial */ taylor_poly = _acb_vec_init(N + 1); func(taylor_poly, m, param, N, prec); _acb_poly_integral(taylor_poly, taylor_poly, N + 1, prec); _acb_poly_evaluate(y2, taylor_poly, N + 1, x, prec); acb_neg(x, x); _acb_poly_evaluate(y1, taylor_poly, N + 1, x, prec); acb_neg(x, x); /* add truncation error */ arb_add_error_arf(acb_realref(y1), err); arb_add_error_arf(acb_imagref(y1), err); arb_add_error_arf(acb_realref(y2), err); arb_add_error_arf(acb_imagref(y2), err); acb_add(sum, sum, y2, prec); acb_sub(sum, sum, y1, prec); if (arb_calc_verbose) { flint_printf("values: "); acb_printd(y1, 15); flint_printf(" "); acb_printd(y2, 15); flint_printf("\n"); } _acb_vec_clear(taylor_poly, N + 1); if (result == ARB_CALC_NO_CONVERGENCE) break; } acb_set(res, sum); acb_clear(delta); acb_clear(m); acb_clear(x); acb_clear(y1); acb_clear(y2); acb_clear(sum); arf_clear(err); return result; } flint-3.1.3/src/acb_calc/test/000077500000000000000000000000001461254215100161105ustar00rootroot00000000000000flint-3.1.3/src/acb_calc/test/main.c000066400000000000000000000016311461254215100172010ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-cauchy_bound.c" #include "t-integrate.c" #include "t-integrate_taylor.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_calc_cauchy_bound), TEST_FUNCTION(acb_calc_integrate), TEST_FUNCTION(acb_calc_integrate_taylor) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_calc/test/t-cauchy_bound.c000066400000000000000000000042211461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_calc.h" /* sin(x), defined in t-cauchy_bound.c and t-integrate_taylor.c */ #ifndef sin_x #define sin_x sin_x int sin_x(acb_ptr out, const acb_t inp, void * params, slong order, slong prec) { int xlen = FLINT_MIN(2, order); acb_set(out, inp); if (xlen > 1) acb_one(out + 1); _acb_poly_sin_series(out, out, xlen, order, prec); return 0; } #endif static const double answers[10] = { 1.04570093561423094, 2.0358667496686487, 4.82706400405656566, 11.2347033850581819, 27.1331828778516522, 67.210305990439042, 168.564351176369878, 427.496180295369909, 1093.56959348921777, 2815.70144392142227 }; TEST_FUNCTION_START(acb_calc_cauchy_bound, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_t b, radius, ans; acb_t x; slong r, prec, maxdepth; arb_init(b); arb_init(radius); arb_init(ans); acb_init(x); acb_set_ui(x, 5); r = 1 + n_randint(state, 10); arb_set_ui(radius, r); prec = 2 + n_randint(state, 100); maxdepth = n_randint(state, 10); acb_calc_cauchy_bound(b, sin_x, NULL, x, radius, maxdepth, prec); arf_set_d(arb_midref(ans), answers[r-1]); mag_set_d(arb_radref(ans), 1e-8); if (!arb_overlaps(b, ans)) { flint_printf("FAIL\n"); flint_printf("r = %wd, prec = %wd, maxdepth = %wd\n\n", r, prec, maxdepth); arb_printd(b, 15); flint_printf("\n\n"); arb_printd(ans, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(b); arb_clear(radius); arb_clear(ans); acb_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_calc/test/t-integrate.c000066400000000000000000000517741461254215100205150ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_calc.h" int f_zero(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_zero(res); return 0; } int f_indet(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_indeterminate(res); return 0; } int f_cube(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_cube(res, z, prec); return 0; } int f_sin(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_sin(res, z, prec); return 0; } int f_sqrt(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_sqrt_analytic(res, z, order != 0, prec); return 0; } int f_rsqrt(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_rsqrt_analytic(res, z, order != 0, prec); return 0; } int f_log(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_log_analytic(res, z, order != 0, prec); return 0; } int f_pow_pi(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_const_pi(res, prec); acb_pow_analytic(res, z, res, order != 0, prec); return 0; } int f_circle(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_one(res); acb_submul(res, z, z, prec); acb_real_sqrtpos(res, res, order != 0, prec); return 0; } /* f(z) = sin(z + exp(z)) -- Rump's oscillatory example */ int f_rump(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_exp(res, z, prec); acb_add(res, res, z, prec); acb_sin(res, res, prec); return 0; } /* f(z) = |z^4 + 10z^3 + 19z^2 - 6z - 6| exp(z) (for real z) -- Helfgott's integral on MathOverflow */ int f_helfgott(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_add_si(res, z, 10, prec); acb_mul(res, res, z, prec); acb_add_si(res, res, 19, prec); acb_mul(res, res, z, prec); acb_add_si(res, res, -6, prec); acb_mul(res, res, z, prec); acb_add_si(res, res, -6, prec); acb_real_abs(res, res, order != 0, prec); if (acb_is_finite(res)) { acb_t t; acb_init(t); acb_exp(t, z, prec); acb_mul(res, res, t, prec); acb_clear(t); } return 0; } /* f(z) = z sin(1/z), assume on real interval */ int f_essing2(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ if ((order == 0) && acb_is_real(z) && arb_contains_zero(acb_realref(z))) { /* todo: arb_zero_pm_one, arb_unit_interval? */ acb_zero(res); mag_one(arb_radref(acb_realref(res))); } else { acb_inv(res, z, prec); acb_sin(res, res, prec); } acb_mul(res, res, z, prec); return 0; } /* f(z) = sech(10(x-0.2))^2 + sech(100(x-0.4))^4 + sech(1000(x-0.6))^6 */ int f_spike(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t a, b, c; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(a); acb_init(b); acb_init(c); acb_mul_ui(a, z, 10, prec); acb_sub_ui(a, a, 2, prec); acb_sech(a, a, prec); acb_pow_ui(a, a, 2, prec); acb_mul_ui(b, z, 100, prec); acb_sub_ui(b, b, 40, prec); acb_sech(b, b, prec); acb_pow_ui(b, b, 4, prec); acb_mul_ui(c, z, 1000, prec); acb_sub_ui(c, c, 600, prec); acb_sech(c, c, prec); acb_pow_ui(c, c, 6, prec); acb_add(res, a, b, prec); acb_add(res, res, c, prec); acb_clear(a); acb_clear(b); acb_clear(c); return 0; } /* more tests for the individual acb_real_* functions */ /* abs(sin(x))*cos(1+x) */ int f_abs(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, c; acb_init(s); acb_init(c); acb_sin(s, z, prec); acb_add_ui(c, z, 1, prec); acb_cos(c, c, prec); acb_real_abs(s, s, order != 0, prec); acb_mul(res, s, c, prec); acb_clear(s); acb_clear(c); return 0; } /* sign(sin(x))*cos(1+x) */ int f_sgn(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, c; acb_init(s); acb_init(c); acb_sin(s, z, prec); acb_add_ui(c, z, 1, prec); acb_cos(c, c, prec); acb_real_sgn(s, s, order != 0, prec); acb_mul(res, s, c, prec); acb_clear(s); acb_clear(c); return 0; } /* heaviside(sin(x))*cos(1+x) */ int f_heaviside(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, c; acb_init(s); acb_init(c); acb_sin(s, z, prec); acb_add_ui(c, z, 1, prec); acb_cos(c, c, prec); acb_real_heaviside(s, s, order != 0, prec); acb_mul(res, s, c, prec); acb_clear(s); acb_clear(c); return 0; } /* floor(x-5) cos(1+x) */ int f_floor(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t c; acb_init(c); acb_add_ui(c, z, 1, prec); acb_cos(c, c, prec); acb_sub_ui(res, z, 5, prec); acb_real_floor(res, res, order != 0, prec); acb_mul(res, res, c, prec); acb_clear(c); return 0; } /* ceil(x-5) cos(1+x) */ int f_ceil(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t c; acb_init(c); acb_add_ui(c, z, 1, prec); acb_cos(c, c, prec); acb_sub_ui(res, z, 5, prec); acb_real_ceil(res, res, order != 0, prec); acb_mul(res, res, c, prec); acb_clear(c); return 0; } /* max(sin(x),cos(x)) */ int f_max(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, c; acb_init(s); acb_init(c); acb_sin_cos(s, c, z, prec); acb_real_max(res, s, c, order != 0, prec); acb_clear(s); acb_clear(c); return 0; } /* min(sin(x),cos(x)) */ int f_min(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t s, c; acb_init(s); acb_init(c); acb_sin_cos(s, c, z, prec); acb_real_min(res, s, c, order != 0, prec); acb_clear(s); acb_clear(c); return 0; } TEST_FUNCTION_START(acb_calc_integrate, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t ans, res, a, b, t; slong goal, prec, abs_goal; mag_t tol; acb_calc_integrate_opt_t opt; int integral; flint_set_num_threads(1 + n_randint(state, 3)); acb_init(ans); acb_init(res); acb_init(a); acb_init(b); acb_init(t); mag_init(tol); acb_calc_integrate_opt_init(opt); goal = 2 + n_randint(state, 300); prec = 2 + n_randint(state, 300); abs_goal = n_randint(state, 300); mag_set_ui_2exp_si(tol, n_randint(state, 2), -abs_goal); opt->eval_limit = n_randint(state, 10000); if (n_randint(state, 2)) opt->depth_limit = n_randint(state, 100); if (n_randint(state, 2)) opt->deg_limit = n_randint(state, 100); opt->use_heap = n_randint(state, 2); integral = n_randint(state, 9); if (integral == 0) { acb_randtest(a, state, 1 + n_randint(state, 200), 2); acb_randtest(b, state, 1 + n_randint(state, 200), 2); acb_cos(ans, a, prec); acb_cos(res, b, prec); acb_sub(ans, ans, res, prec); acb_calc_integrate(res, f_sin, NULL, a, b, goal, tol, opt, prec); } else if (integral == 1) { acb_randtest(a, state, 1 + n_randint(state, 200), 2); acb_randtest(b, state, 1 + n_randint(state, 200), 2); acb_pow_ui(ans, a, 4, prec); acb_pow_ui(res, b, 4, prec); acb_sub(ans, res, ans, prec); acb_mul_2exp_si(ans, ans, -2); acb_calc_integrate(res, f_cube, NULL, a, b, goal, tol, opt, prec); } else if (integral == 2) { acb_zero(a); acb_one(b); acb_const_pi(ans, prec); acb_mul_2exp_si(ans, ans, -2); if (n_randint(state, 2)) { acb_swap(a, b); acb_neg(ans, ans); } acb_calc_integrate(res, f_circle, NULL, a, b, goal, tol, opt, prec); } else if (integral == 3) { acb_zero(a); acb_one(b); acb_zero(ans); arb_set_str(acb_realref(ans), "0.3785300171241613098817352756283519095343133 +/- 1e-40", prec); if (n_randint(state, 2)) { acb_swap(a, b); acb_neg(ans, ans); } acb_calc_integrate(res, f_essing2, NULL, a, b, goal, tol, opt, prec); } else if (integral == 4) { acb_zero(a); acb_one(b); acb_zero(ans); arb_set_str(acb_realref(ans), "11.147310550057139733915902084255301415775813549800589418261584268232061665808482234384871404010464 +/- 2.28e-97", prec); if (n_randint(state, 2)) { acb_swap(a, b); acb_neg(ans, ans); } acb_calc_integrate(res, f_helfgott, NULL, a, b, goal, tol, opt, prec); } else if (integral == 5) { acb_zero(a); acb_set_ui(b, 8); acb_zero(ans); arb_set_str(acb_realref(ans), "0.34740017265724780787951215911989312465745625486618018388549271361674821398878532052968510434660 +/- 5.97e-96", prec); if (n_randint(state, 2)) { acb_swap(a, b); acb_neg(ans, ans); } acb_calc_integrate(res, f_rump, NULL, a, b, goal, tol, opt, prec); } else if (integral == 6) { acb_zero(a); acb_one(b); acb_zero(ans); arb_set_str(acb_realref(ans), "0.21080273550054927737564325570572915436090918643678119034785050587872061312814550020505868926155764 +/- 3.72e-99", prec); if (n_randint(state, 2)) { acb_swap(a, b); acb_neg(ans, ans); } acb_calc_integrate(res, f_spike, NULL, a, b, goal, tol, opt, prec); } else if (integral == 7) { acb_randtest_special(a, state, 1 + n_randint(state, 200), 2); acb_randtest_special(b, state, 1 + n_randint(state, 200), 2); acb_zero(ans); acb_calc_integrate(res, f_zero, NULL, a, b, goal, tol, opt, prec); } else if (integral == 8) { acb_randtest_special(a, state, 1 + n_randint(state, 200), 2); acb_randtest_special(b, state, 1 + n_randint(state, 200), 2); acb_indeterminate(ans); acb_calc_integrate(res, f_indet, NULL, a, b, goal, tol, opt, prec); } if (!acb_overlaps(res, ans)) { flint_printf("FAIL! (iter = %wd)\n", iter); flint_printf("integral = %d, prec = %wd, goal = %wd\n", integral, prec, goal); flint_printf("a = "); acb_printn(a, 150, 0); flint_printf("\n"); flint_printf("b = "); acb_printn(b, 150, 0); flint_printf("\n"); flint_printf("res = "); acb_printn(res, 150, 0); flint_printf("\n\n"); flint_printf("ans = "); acb_printn(ans, 150, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(ans); acb_clear(res); acb_clear(a); acb_clear(b); acb_clear(t); mag_clear(tol); } /* more tests for the individual real extensions and branched functions */ { acb_t a, b, z, w; slong prec; mag_t tol; acb_init(a); acb_init(b); acb_init(z); acb_init(w); mag_init(tol); acb_zero(a); acb_set_ui(b, 10); prec = 53; mag_set_ui_2exp_si(tol, 1, -prec); acb_calc_integrate(z, f_abs, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "-1.3517710956465318592 +/- 1e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (abs)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_sgn, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "-4.8903066871045720895 +/- 1e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (sgn)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_heaviside, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "-3.3658839392315860266 +/- 1e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (heaviside)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_floor, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "-0.36232328857344524392 +/- 1e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 16) { flint_printf("FAIL (floor)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_ceil, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "-2.2037844799320452076 +/- 1e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 16) { flint_printf("FAIL (ceil)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_max, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "5.0817122161957375987 +/- 1e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (max)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_min, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "-3.7866617980086549598 +/- 1e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (min)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } prec = 64; mag_set_ui_2exp_si(tol, 1, -prec); acb_set_ui(a, 10); acb_set_ui(b, 11); acb_calc_integrate(z, f_sqrt, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "3.2400640614837366802 +/- 1.65e-20", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (sqrt)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_rsqrt, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "0.30869426037404103423 +/- 2.08e-21", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (rsqrt)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_log, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "2.3509970708416191445 +/- 1.47e-21", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (log)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_pow_pi, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "1619.0628341842463436 +/- 2.79e-17", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 10) { flint_printf("FAIL (pow_pi)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_set_d_d(a, -10, -1); acb_set_d_d(b, -10, +1); acb_zero(w); acb_calc_integrate(z, f_sqrt, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_imagref(w), "0.15801534879296271761 +/- 4.91e-21", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 25) { flint_printf("FAIL (sqrt 2)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_rsqrt, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_imagref(w), "0.015762235473606564294 +/- 2.80e-22", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 25) { flint_printf("FAIL (rsqrt 2)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_log, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_imagref(w), "4.6084935666644999985 +/- 4.69e-20", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 25) { flint_printf("FAIL (log 2)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_calc_integrate(z, f_pow_pi, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_imagref(w), "-2660.1245860252382407 +/- 8.64e-18", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 25) { flint_printf("FAIL (pow_pi 2)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } prec = 100; mag_set_ui_2exp_si(tol, 1, -prec); acb_set_d_d(a, -100, -1); acb_set_d_d(b, -100, +2); acb_zero(w); acb_calc_integrate(z, f_log, NULL, a, b, prec, tol, NULL, prec); arb_set_str(acb_realref(w), "-3.12659390337983876281336380373 +/- 3.97e-30", prec); arb_set_str(acb_imagref(w), "13.8156605414673448203655975232 +/- 2.39e-29", prec); if (!acb_overlaps(z, w) || acb_rel_accuracy_bits(z) < prec - 25) { flint_printf("FAIL (log 3)\n"); flint_printf("z = "); acb_printn(z, 20, 0); flint_printf("\n"); flint_printf("w = "); acb_printn(w, 20, 0); flint_printf("\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(z); acb_clear(w); mag_clear(tol); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_calc/test/t-integrate_taylor.c000066400000000000000000000050461461254215100220760ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_calc.h" /* sin(x), defined in t-cauchy_bound.c and t-integrate_taylor.c */ #ifndef sin_x #define sin_x sin_x int sin_x(acb_ptr out, const acb_t inp, void * params, slong order, slong prec) { int xlen = FLINT_MIN(2, order); acb_set(out, inp); if (xlen > 1) acb_one(out + 1); _acb_poly_sin_series(out, out, xlen, order, prec); return 0; } #endif TEST_FUNCTION_START(acb_calc_integrate_taylor, state) { slong iter; for (iter = 0; iter < 150 * 0.1 * flint_test_multiplier(); iter++) { acb_t ans, res, a, b; arf_t inr, outr; double t; slong goal, prec; acb_init(ans); acb_init(res); acb_init(a); acb_init(b); arf_init(inr); arf_init(outr); goal = 2 + n_randint(state, 300); prec = 2 + n_randint(state, 300); acb_randtest(a, state, 1 + n_randint(state, 200), 2); acb_randtest(b, state, 1 + n_randint(state, 200), 2); acb_cos(ans, a, prec); acb_cos(res, b, prec); acb_sub(ans, ans, res, prec); t = (1 + n_randint(state, 20)) / 10.0; arf_set_d(inr, t); arf_set_d(outr, t + (1 + n_randint(state, 20)) / 5.0); acb_calc_integrate_taylor(res, sin_x, NULL, a, b, inr, outr, goal, prec); if (!acb_overlaps(res, ans)) { flint_printf("FAIL! (iter = %wd)\n", iter); flint_printf("prec = %wd, goal = %wd\n", prec, goal); flint_printf("inr = "); arf_printd(inr, 15); flint_printf("\n"); flint_printf("outr = "); arf_printd(outr, 15); flint_printf("\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n"); flint_printf("res = "); acb_printd(res, 15); flint_printf("\n\n"); flint_printf("ans = "); acb_printd(ans, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(ans); acb_clear(res); acb_clear(a); acb_clear(b); arf_clear(inr); arf_clear(outr); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dft.h000066400000000000000000000206101461254215100151540ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_DFT_H #define ACB_DFT_H #include "ulong_extras.h" #include "acb.h" #ifdef __cplusplus extern "C" { #endif void _acb_dft_naive(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec); void acb_dft_naive(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dft_rad2_inplace(acb_ptr v, int e, slong prec); void acb_dft_rad2(acb_ptr w, acb_srcptr v, int e, slong prec); void acb_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); void acb_dft_rad2_inplace_threaded(acb_ptr v, int e, slong prec); void acb_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); void acb_dft_convol_dft(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); void acb_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); void acb_dft_convol_mullow(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); void acb_dft_convol(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); #define CRT_MAX 15 typedef struct { int num; nmod_t n; slong m[CRT_MAX]; ulong M[CRT_MAX]; ulong vM[CRT_MAX]; } crt_struct; typedef crt_struct crt_t[1]; void crt_init(crt_t c, ulong n); void crt_decomp(acb_ptr y, acb_srcptr x, slong dx, const crt_t c, ulong len); void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); typedef struct acb_dft_step_struct acb_dft_step_struct; typedef acb_dft_step_struct * acb_dft_step_ptr; typedef struct { slong n; acb_ptr z; int zclear; slong num; acb_dft_step_ptr cyc; } acb_dft_cyc_struct; typedef acb_dft_cyc_struct acb_dft_cyc_t[1]; typedef struct { int e; slong n; /* = 1 << e */ slong dv; slong nz; /* = n but could be bigger */ acb_ptr z; } acb_dft_rad2_struct; typedef acb_dft_rad2_struct acb_dft_rad2_t[1]; typedef struct { slong n; slong dv; acb_ptr z; /* z[k] = e(k^2/2n) */ acb_ptr g; /* g[k] = dft( z ) */ acb_dft_rad2_t rad2; } acb_dft_bluestein_struct; typedef acb_dft_bluestein_struct acb_dft_bluestein_t[1]; typedef struct { slong n; slong num; acb_dft_step_ptr cyc; } acb_dft_prod_struct; typedef acb_dft_prod_struct acb_dft_prod_t[1]; typedef struct { slong n; crt_t c; slong dv; /* then a product */ acb_dft_step_ptr cyc; } acb_dft_crt_struct; typedef acb_dft_crt_struct acb_dft_crt_t[1]; typedef struct { slong n; slong dv; int zclear; acb_ptr z; slong dz; } acb_dft_naive_struct; typedef acb_dft_naive_struct acb_dft_naive_t[1]; typedef struct { slong n; int type; union { acb_dft_rad2_t rad2; acb_dft_cyc_t cyc; acb_dft_prod_t prod; acb_dft_crt_t crt; acb_dft_naive_t naive; acb_dft_bluestein_t bluestein; } t; } acb_dft_pre_struct; typedef acb_dft_pre_struct acb_dft_pre_t[1]; /* covers both product and cyclic case */ struct acb_dft_step_struct { /* [G:H] */ slong m; /* card H */ slong M; slong dv; /* = M for prod, also = M if cyc is reordered */ /* pointer on some roots of unity, if needed */ acb_srcptr z; /* index of mM in z */ slong dz; /* dft to call on H */ acb_dft_pre_t pre; /* dft to call on G/H ? */ }; /*typedef acb_dft_pre_struct acb_dft_pre_t[1];*/ #define DFT_VERB 0 enum { DFT_NAIVE, DFT_CYC, DFT_PROD, DFT_CRT , DFT_RAD2 , DFT_CONV }; void acb_dft_step(acb_ptr w, acb_srcptr v, acb_dft_step_ptr cyc, slong num, slong prec); void acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec); void acb_dft_inverse_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec); void acb_dft_naive_precomp(acb_ptr w, acb_srcptr v, const acb_dft_naive_t pol, slong prec); void acb_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dft_cyc_t cyc, slong prec); void acb_dft_rad2_precomp_inplace(acb_ptr v, const acb_dft_rad2_t rad2, slong prec); void acb_dft_rad2_precomp(acb_ptr w, acb_srcptr v, const acb_dft_rad2_t rad2, slong prec); void acb_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dft_crt_t crt, slong prec); void acb_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dft_prod_t prod, slong prec); void acb_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dft_bluestein_t t, slong prec); void acb_dft_rad2_precomp_inplace_threaded(acb_ptr v, const acb_dft_rad2_t rad2, slong prec); void acb_dft_inverse_rad2_precomp_inplace(acb_ptr v, const acb_dft_rad2_t rad2, slong prec); void acb_dft_inverse_rad2_precomp(acb_ptr w, acb_srcptr v, const acb_dft_rad2_t rad2, slong prec); void acb_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dft_rad2_t, slong prec); void _acb_dft_precomp_init(acb_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec); void acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec); void acb_dft_precomp_clear(acb_dft_pre_t pre); void acb_dft(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dft_inverse(acb_ptr w, acb_srcptr v, slong len, slong prec); acb_dft_step_ptr _acb_dft_steps_prod(slong * m, slong num, slong prec); FLINT_FORCE_INLINE void acb_dft_prod_init(acb_dft_prod_t t, slong * cyc, slong num, slong prec) { t->num = num; t->cyc = _acb_dft_steps_prod(cyc, num, prec); } void acb_dft_prod_clear(acb_dft_prod_t t); void _acb_dft_cyc_init_z_fac(acb_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec); void _acb_dft_cyc_init(acb_dft_cyc_t t, slong dv, slong len, slong prec); FLINT_FORCE_INLINE void acb_dft_cyc_init(acb_dft_cyc_t t, slong len, slong prec) { _acb_dft_cyc_init(t, 1, len, prec); } void acb_dft_cyc_clear(acb_dft_cyc_t t); void _acb_dft_naive_init(acb_dft_naive_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec); FLINT_FORCE_INLINE void acb_dft_naive_init(acb_dft_naive_t pol, slong len, slong prec) { _acb_dft_naive_init(pol, 1, NULL, 0, len, prec); } FLINT_FORCE_INLINE void acb_dft_naive_clear(acb_dft_naive_t pol) { if (pol->zclear) _acb_vec_clear(pol->z, pol->n); } void _acb_dft_rad2_init(acb_dft_rad2_t t, slong dv, int e, slong prec); FLINT_FORCE_INLINE void acb_dft_rad2_init(acb_dft_rad2_t t, int e, slong prec) { _acb_dft_rad2_init(t, 1, e, prec); } FLINT_FORCE_INLINE void acb_dft_rad2_clear(acb_dft_rad2_t t) { _acb_vec_clear(t->z, t->nz); } void _acb_dft_bluestein_init(acb_dft_bluestein_t t, slong dv, slong n, slong prec); FLINT_FORCE_INLINE void acb_dft_bluestein_init(acb_dft_bluestein_t t, slong n, slong prec) { _acb_dft_bluestein_init(t, 1, n, prec); } FLINT_FORCE_INLINE void acb_dft_bluestein_clear(acb_dft_bluestein_t t) { if (t->n != 0) { _acb_vec_clear(t->z, t->n); _acb_vec_clear(t->g, t->rad2->n); acb_dft_rad2_clear(t->rad2); } } void _acb_dft_crt_init(acb_dft_crt_t crt, slong dv, slong len, slong prec); void acb_dft_crt_init(acb_dft_crt_t crt, slong len, slong prec); void acb_dft_crt_clear(acb_dft_crt_t crt); /* utils, could be moved elsewhere */ FLINT_FORCE_INLINE void acb_swap_ri(acb_t x) { arb_swap(acb_realref(x), acb_imagref(x)); } FLINT_FORCE_INLINE void acb_vec_swap_ri(acb_ptr v, slong len) { slong k; for (k = 0; k < len; k++) acb_swap_ri(v + k); } FLINT_FORCE_INLINE void _acb_vec_kronecker_mul(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) { slong k; for (k = 0; k < len; k++) acb_mul(z + k, x + k, y + k, prec); } FLINT_FORCE_INLINE void _acb_vec_kronecker_mul_step(acb_ptr z, acb_srcptr x, acb_srcptr y, slong step, slong len, slong prec) { slong k; for (k = 0; k < len; k++) { acb_mul(z + k, x + k, y + k * step, prec); } } FLINT_FORCE_INLINE void acb_vec_printd_index(acb_srcptr vec, slong len, slong digits) { slong i; for (i = 0; i < len; i++) { flint_printf("[%wd] ", i); acb_printd(vec + i, digits); flint_printf("\n"); } } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_dft/000077500000000000000000000000001461254215100150045ustar00rootroot00000000000000flint-3.1.3/src/acb_dft/bluestein.c000066400000000000000000000072171461254215100171510ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "acb_dft.h" #include "acb_modular.h" /* z[k] = z^(k^2), z a 2n-th root of unity */ static void _acb_vec_bluestein_factors(acb_ptr z, slong n, slong prec) { /* this function is used mostly with prime-power n * so the set of squares has index 2 only. * computing an addition sequence does not considerably improve things */ if (n < 30) { slong k, k2; acb_ptr z2n; nmod_t n2; z2n = _acb_vec_init(2 * n); _acb_vec_unit_roots(z2n, -2 * n, 2 * n, prec); nmod_init(&n2, FLINT_MAX(2 * n, 1)); for (k = 0, k2 = 0; k < n; k++) { acb_set(z + k, z2n + k2); k2 = nmod_add(k2, 2 * k + 1, n2); } _acb_vec_clear(z2n, 2 * n); } else { nmod_t n2; slong k, k2, dk; slong * v, * s; acb_ptr t; s = flint_malloc(n * sizeof(slong)); v = flint_malloc((n + 1)* sizeof(slong)); t = _acb_vec_init(n + 1); nmod_init(&n2, 2 * n); for (k = 0; k < n; k++) v[k] = 0; for (k = 0, k2 = 0, dk = 1; k < n; k++) { s[k] = k2; if (k2 < n) v[k2] = -1; else v[2 * n - k2] = -1; k2 = nmod_add(k2, dk, n2); dk = nmod_add(dk, 2, n2); } acb_modular_fill_addseq(v, n); acb_one(t + 0); acb_unit_root(t + 1, 2 * n, prec); acb_conj(t + 1, t + 1); acb_set_si(t + n, -1); for (k = 2; k < n; k++) if (v[k]) acb_mul(t + k, t + v[k], t + k - v[k], prec); for (k = 0; k < n; k++) { if (s[k] <= n) acb_set(z + k, t + s[k]); else acb_conj(z + k, t + 2 * n - s[k]); } _acb_vec_clear(t, n + 1); flint_free(s); flint_free(v); } } void _acb_dft_bluestein_init(acb_dft_bluestein_t t, slong dv, slong n, slong prec) { acb_ptr z, g; slong k, n2; int e; t->n = n; t->dv = dv; if (n == 0) return; e = n_clog(2 * n - 1, 2); if (DFT_VERB) flint_printf("dft_bluestein: init z[2^%i]\n", e); acb_dft_rad2_init(t->rad2, e, prec); t->z = z = _acb_vec_init(n); _acb_vec_bluestein_factors(t->z, n, prec); n2 = t->rad2->n; t->g = g = _acb_vec_init(n2); acb_one(g + 0); for (k = 1; k < n; k++) { acb_conj(g + k, z + k); acb_set(g + n2 - k, g + k); } acb_dft_rad2_precomp_inplace(g, t->rad2, prec); } void acb_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dft_bluestein_t t, slong prec) { slong n = t->n, np = t->rad2->n, dv = t->dv; acb_ptr fp; if (n == 0) return; fp = _acb_vec_init(np); _acb_vec_kronecker_mul_step(fp, t->z, v, dv, n, prec); acb_dft_rad2_precomp_inplace(fp, t->rad2, prec); _acb_vec_kronecker_mul(fp, t->g, fp, np, prec); acb_dft_inverse_rad2_precomp_inplace(fp, t->rad2, prec); _acb_vec_kronecker_mul(w, t->z, fp, n, prec); _acb_vec_clear(fp, n); } void acb_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec) { acb_dft_bluestein_t t; acb_dft_bluestein_init(t, len, prec); acb_dft_bluestein_precomp(w, v, t, prec); acb_dft_bluestein_clear(t); } flint-3.1.3/src/acb_dft/convol.c000066400000000000000000000016571461254215100164610ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" static int use_dft(slong len, slong prec) { slong l2 = len; while (l2 >= 16) l2 >>= 1; if (l2 < 11) { while (!(len & 1)) len >>= 1; while (len % 3 == 0) len /= 3; while (len % 5 == 0) len /= 5; while (len % 7 == 0) len /= 7; return (len == 1); } return 0; } void acb_dft_convol(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) { if (use_dft(len, prec)) acb_dft_convol_dft(w, f, g, len, prec); else acb_dft_convol_rad2(w, f, g, len, prec); } flint-3.1.3/src/acb_dft/convol_dft.c000066400000000000000000000020741461254215100173100ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" void acb_dft_convol_dft_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, const acb_dft_pre_t pre, slong prec) { acb_ptr fp, gp; fp = _acb_vec_init(pre->n); gp = _acb_vec_init(pre->n); acb_dft_precomp(fp, f, pre, prec); acb_dft_precomp(gp, g, pre, prec); _acb_vec_kronecker_mul(gp, gp, fp, pre->n, prec); acb_dft_inverse_precomp(w, gp, pre, prec); _acb_vec_clear(fp, pre->n); _acb_vec_clear(gp, pre->n); } void acb_dft_convol_dft(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) { acb_dft_pre_t pre; acb_dft_precomp_init(pre, len, prec); acb_dft_convol_dft_precomp(w, f, g, pre, prec); acb_dft_precomp_clear(pre); } flint-3.1.3/src/acb_dft/convol_mullow.c000066400000000000000000000017431461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" #include "acb_poly.h" void acb_dft_convol_mullow(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) { /* TODO: should probably use (acb_struct *) arrays */ acb_ptr gg, ww; if (len == 0) return; gg = _acb_vec_init(2 * len - 1); ww = _acb_vec_init(2 * len - 1); _acb_vec_set(gg, g, len); _acb_vec_set(gg + len, g, len - 1); _acb_poly_mullow(ww, f, len, gg, 2 * len - 1, 2 * len - 1, prec); _acb_vec_set(w, ww + len, len - 1); acb_set(w + len - 1, ww + len - 1); _acb_vec_clear(gg, 2 * len - 1); _acb_vec_clear(ww, 2 * len - 1); } flint-3.1.3/src/acb_dft/convol_naive.c000066400000000000000000000014701461254215100176340ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" void acb_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) { slong x, y; for (x = 0; x < len; x ++) { acb_ptr wx; acb_srcptr fx; wx = w + x; fx = f + x; acb_zero(wx); for (y = 0; y <= x; y++) acb_addmul(wx, fx - y, g + y, prec); for (; y < len; y++) acb_addmul(wx, fx + (len - y), g + y, prec); } } flint-3.1.3/src/acb_dft/convol_rad2.c000066400000000000000000000041171461254215100173630ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" /* assume np >= 2 * n - 1 */ void acb_dft_convol_pad(acb_ptr fp, acb_ptr gp, acb_srcptr f, acb_srcptr g, slong n, slong np) { slong k; if (np < 2 * n - 1) { flint_throw(FLINT_ERROR, "dft_convol_pad: overlapping padding %wd < 2*%wd-1\n", np, n); } for (k = 0; k < n; k++) acb_set(gp + k, g + k); for (; k < np; k++) acb_zero(gp + k); for (k = 0; k < n; k++) acb_set(fp + k, f + k); for (k = 1; k < n; k++) acb_set(fp + np - k, f + n - k); for (k = n; k <= np - n; k++) acb_zero(fp + k); } void acb_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dft_rad2_t rad2, slong prec) { slong np; acb_ptr fp, gp; np = rad2->n; if (len <= 0) return; fp = _acb_vec_init(np); gp = _acb_vec_init(np); if (len == np) { _acb_vec_set(fp, f, len); _acb_vec_set(gp, g, len); } else acb_dft_convol_pad(fp, gp, f, g, len, np); acb_dft_rad2_precomp_inplace(fp, rad2, prec); acb_dft_rad2_precomp_inplace(gp, rad2, prec); _acb_vec_kronecker_mul(gp, gp, fp, np, prec); acb_dft_inverse_rad2_precomp_inplace(gp, rad2, prec); _acb_vec_set(w, gp, len); _acb_vec_clear(fp, np); _acb_vec_clear(gp, np); } void acb_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) { int e; acb_dft_rad2_t dft; /* catch power of 2 */ if (len <= 0) return; else if ((len & (len - 1)) == 0) e = n_clog(len, 2); else e = n_clog(2 * len - 1, 2); acb_dft_rad2_init(dft, e, prec); acb_dft_convol_rad2_precomp(w, f, g, len, dft, prec); acb_dft_rad2_clear(dft); } flint-3.1.3/src/acb_dft/crt.c000066400000000000000000000112111461254215100157340ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "acb_dft.h" void crt_init(crt_t c, ulong n) { int k; n_factor_t fac; n_factor_init(&fac); if (n) n_factor(&fac, n, 1); else fac.num = 0; nmod_init(&c->n, FLINT_MAX(n, 1)); c->num = fac.num; for (k = 0; k < fac.num; k++) { c->m[k] = n_pow(fac.p[k], fac.exp[k]); c->M[k] = n / c->m[k]; c->vM[k] = c->M[k] * n_invmod(c->M[k] % c->m[k], c->m[k]); /* flint_printf("m[%ld]=%ld, M[%ld]=%wu, vM[%ld]=%wu\n", k, c->m[k], k, c->M[k], k, c->vM[k]); */ } } void crt_print(const crt_t c) { slong k; if (c->num == 0) { flint_throw(FLINT_ERROR, "trivial group\n"); } for (k = 0; k < c->num; k++) flint_printf("Z/%wuZ ", c->m[k]); flint_printf("\n"); } #if 0 /* lexicographic index of crt elt j */ static ulong index_crt(crt_t c, ulong j) { int k; ulong res = 0; for (k = 0; k < c->num; k ++) res = res * c->m[k] + (j % c->m[k]); return res; } /* crt elt of lexicographic index i */ static ulong crt_index(crt_t c, ulong i) { int k; ulong j, res = 0; for (k = 0; k < c->num; k ++) { j = i % c->m[k]; i = i / c->m[k]; res = nmod_add(res, j * c->vM[k], c->n); } return res; } /* for all elements can do fast conrey-like loop just adding vM[k] */ static acb_ptr reorder_to_crt(acb_srcptr v, crt_t c, ulong len) { ulong k; acb_ptr res; res = flint_malloc(len * sizeof(acb_struct)); for (k = 0; k < len; k++) res[index_crt(c, k)] = v[k]; return res; } static acb_ptr reorder_from_crt(acb_srcptr v, crt_t c, ulong len) { ulong k; acb_ptr res; res = flint_malloc(len * sizeof(acb_struct)); for (k = 0; k < len; k++) res[k] = v[index_crt(c, k)]; return res; } #endif void crt_decomp(acb_ptr y, acb_srcptr x, slong dv, const crt_t c, ulong len) { int j, e[CRT_MAX]; ulong k, l; for (j = 0; j < c->num; j++) e[j] = 0; l = 0; for(k = 0; k < len; k++) { acb_set(y + k, x + l * dv); for (j = c->num - 1; j >= 0; e[j] = 0, j--) { e[j]++; l = nmod_add(l, c->vM[j], c->n); if (e[j] < c->m[j]) break; } } } void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) { int j, e[CRT_MAX]; ulong k, l; for (j = 0; j < c->num; j++) e[j] = 0; l = 0; for(k = 0; k < len; k++) { acb_set(y + l, x + k); for (j = c->num - 1; j >= 0; e[j] = 0, j--) { e[j]++; l = nmod_add(l, c->M[j], c->n); if (e[j] < c->m[j]) break; } } } void _acb_dft_crt_init(acb_dft_crt_t crt, slong dv, slong len, slong prec) { crt->n = len; crt_init(crt->c, len); crt->dv = dv; crt->cyc = _acb_dft_steps_prod(crt->c->m, crt->c->num, prec); } void acb_dft_crt_init(acb_dft_crt_t crt, slong len, slong prec) { crt->n = len; crt_init(crt->c, len); crt->dv = 1; crt->cyc = _acb_dft_steps_prod(crt->c->m, crt->c->num, prec); } void acb_dft_crt_clear(acb_dft_crt_t crt) { slong i; for (i = 0; i < crt->c->num; i++) acb_dft_precomp_clear(crt->cyc[i].pre); flint_free(crt->cyc); } void acb_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dft_crt_t crt, slong prec) { if (crt->n <= 1) { if (crt->n == 1) acb_set(w, v); } else { acb_ptr t; t = _acb_vec_init(crt->n); if (w == v) { _acb_vec_set(t, v, crt->n); v = t; } crt_decomp(w, v, crt->dv, crt->c, crt->n); acb_dft_step(t, w, crt->cyc, crt->c->num, prec); crt_recomp(w, t, crt->c, crt->n); _acb_vec_clear(t, crt->n); } } void acb_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) { if (len <= 1) { if (len == 1) acb_set(w, v); } else { crt_t c; acb_ptr t; t = _acb_vec_init(len); if (w == v) { _acb_vec_set(t, v, len); v = t; } crt_init(c, len); crt_decomp(w, v, 1, c, len); acb_dft_prod(t, w, c->m, c->num, prec); crt_recomp(w, t, c, len); _acb_vec_clear(t, len); } } flint-3.1.3/src/acb_dft/cyc.c000066400000000000000000000056311461254215100157330ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" void _acb_dft_cyc_init_z_fac(acb_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec) { slong i, j, num; t->n = len; num = 0; for (i = 0; i < fac.num; i++) num += fac.exp[i]; t->num = num; t->cyc = flint_malloc(num * sizeof(acb_dft_step_struct)); if (z == NULL) { if (DFT_VERB) flint_printf("dft_cyc: init z[%wu]\n", t->n); z = _acb_vec_init(t->n); _acb_vec_unit_roots(z, -t->n, t->n, prec); dz = 1; t->zclear = 1; } else { if (DFT_VERB) flint_printf("dft_cyc: roots of order %wu already computed\n", t->n); t->zclear = 0; } t->z = z; num = 0; for (i = 0; i < fac.num; i++) { for (j = 0; j < fac.exp[i]; j++) { slong m, M; m = fac.p[i]; M = (len /= m); t->cyc[num].m = m; t->cyc[num].M = M; t->cyc[num].dv = dv; t->cyc[num].z = z; t->cyc[num].dz = dz; /* TODO: ugly, reorder should solve this */ if (num == t->num - 1) _acb_dft_precomp_init(t->cyc[num].pre, dv, z, dz, m, prec); else _acb_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec); dv *= m; dz *= m; num++; } } } void _acb_dft_cyc_init(acb_dft_cyc_t t, slong dv, slong len, slong prec) { n_factor_t fac; n_factor_init(&fac); if (len) n_factor(&fac, len, 1); else fac.num = 0; _acb_dft_cyc_init_z_fac(t, fac, dv, NULL, 0, len, prec); } void acb_dft_cyc_clear(acb_dft_cyc_t t) { slong i; for (i = 0; i < t->num; i++) acb_dft_precomp_clear(t->cyc[i].pre); if (t->zclear) _acb_vec_clear(t->z, t->n); flint_free(t->cyc); } void acb_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dft_cyc_t cyc, slong prec) { if (cyc->num == 0) { if (cyc->n == 1) acb_set(w, v); } else acb_dft_step(w, v, cyc->cyc, cyc->num, prec); } void acb_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) { acb_dft_cyc_t cyc; acb_dft_cyc_init(cyc, len, prec); acb_dft_cyc_precomp(w, v, cyc, prec); acb_dft_cyc_clear(cyc); } void acb_dft_inverse_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) { /* divide before to keep v const */ _acb_vec_scalar_div_ui(w, v, len, len, prec); acb_vec_swap_ri(w, len); acb_dft_cyc(w, w, len, prec); acb_vec_swap_ri(w, len); } flint-3.1.3/src/acb_dft/naive.c000066400000000000000000000042761461254215100162630ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" /* all roots are already computed, w != v */ void _acb_dft_naive(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec) { slong i, j; acb_ptr wi, v1 = NULL; acb_srcptr vj; if (w == v) { flint_throw(FLINT_ERROR, "\n_acb_dft_naive: does not accept aliasing\n"); } for (i = 0, wi = w; i < len; i++, wi++) { acb_zero(wi); for (j = 0, vj = v; j < len; j++, vj += dv) acb_addmul(wi, vj, z + dz * (i * j % len), prec); } if (v1) _acb_vec_clear(v1, len); } void acb_dft_naive_precomp(acb_ptr w, acb_srcptr v, const acb_dft_naive_t pol, slong prec) { if (v == w) { acb_ptr v1 = _acb_vec_init(pol->n); _acb_vec_set(v1, v, pol->n); _acb_dft_naive(w, v1, pol->dv, pol->z, pol->dz, pol->n, prec); _acb_vec_clear(v1, pol->n); } else _acb_dft_naive(w, v, pol->dv, pol->z, pol->dz, pol->n, prec); } void acb_dft_naive(acb_ptr w, acb_srcptr v, slong len, slong prec) { acb_ptr z, v1 = NULL; z = _acb_vec_init(len); _acb_vec_unit_roots(z, -len, len, prec); if (w == v) { v1 = _acb_vec_init(len); _acb_vec_set(v1, v, len); v = v1; } _acb_dft_naive(w, v, 1, z, 1, len, prec); if (v1) _acb_vec_clear(v1, len); _acb_vec_clear(z, len); } void _acb_dft_naive_init(acb_dft_naive_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec) { pol->n = len; pol->dv = dv; if (z == NULL) { if (DFT_VERB) flint_printf("dft_naive: init z[%wd]\n",len); pol->z = _acb_vec_init(len); _acb_vec_unit_roots(pol->z, -len, len, prec); pol->dz = 1; pol->zclear = 1; } else { pol->z = z; pol->dz = dz; pol->zclear = 0; } } flint-3.1.3/src/acb_dft/precomp.c000066400000000000000000000101101461254215100166060ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" void _acb_dft_precomp_init(acb_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec) { pre->n = len; if (len <= 1) { pre->type = DFT_NAIVE; _acb_dft_naive_init(pre->t.naive, dv, z, dz, len, prec); } else if (n_is_prime(len)) { if (len < 100) { pre->type = DFT_NAIVE; _acb_dft_naive_init(pre->t.naive, dv, z, dz, len, prec); } else { pre->type = DFT_CONV; /* FIXME: do not recompute the same bluestein * scheme if needed several times */ _acb_dft_bluestein_init(pre->t.bluestein, dv, len, prec); } } else { n_factor_t fac; n_factor_init(&fac); n_factor(&fac, len, 1); if (fac.num == 1) { /* TODO: could be p^e, or 2^e, but with dv shift */ if (fac.p[0] == 2) { pre->type = DFT_RAD2; _acb_dft_rad2_init(pre->t.rad2, dv, fac.exp[0], prec); } else { pre->type = DFT_CYC; _acb_dft_cyc_init_z_fac(pre->t.cyc, fac, dv, z, dz, len, prec); } } else { pre->type = DFT_CRT; _acb_dft_crt_init(pre->t.crt, dv, len, prec); } } } void acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec) { _acb_dft_precomp_init(pre, 1, NULL, 0, len, prec); } void acb_dft_precomp_clear(acb_dft_pre_t pre) { switch (pre->type) { case DFT_NAIVE: acb_dft_naive_clear(pre->t.naive); break; case DFT_CYC: acb_dft_cyc_clear(pre->t.cyc); break; case DFT_PROD: acb_dft_prod_clear(pre->t.prod); break; case DFT_CRT: acb_dft_crt_clear(pre->t.crt); break; case DFT_RAD2: acb_dft_rad2_clear(pre->t.rad2); break; case DFT_CONV: acb_dft_bluestein_clear(pre->t.bluestein); break; default: flint_throw(FLINT_ERROR, "acb_dft_clear: unknown strategy code %i\n", pre->type); } } void acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec) { switch (pre->type) { case DFT_NAIVE: acb_dft_naive_precomp(w, v, pre->t.naive, prec); break; case DFT_CYC: acb_dft_cyc_precomp(w, v, pre->t.cyc, prec); break; case DFT_PROD: acb_dft_prod_precomp(w, v, pre->t.prod, prec); break; case DFT_CRT: acb_dft_crt_precomp(w, v, pre->t.crt, prec); break; case DFT_RAD2: acb_dft_rad2_precomp(w, v, pre->t.rad2, prec); break; case DFT_CONV: acb_dft_bluestein_precomp(w, v, pre->t.bluestein, prec); break; default: flint_throw(FLINT_ERROR, "acb_dft_precomp: unknown strategy code %i\n", pre->type); } } void acb_dft(acb_ptr w, acb_srcptr v, slong len, slong prec) { acb_dft_pre_t t; acb_dft_precomp_init(t, len, prec); acb_dft_precomp(w, v, t, prec); acb_dft_precomp_clear(t); } void acb_dft_inverse_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec) { slong k; acb_dft_precomp(w, v, pre, prec); for (k = 1; 2 * k < pre->n; k++) acb_swap(w + k, w + pre->n - k); _acb_vec_scalar_div_ui(w, w, pre->n, pre->n, prec); } void acb_dft_inverse(acb_ptr w, acb_srcptr v, slong len, slong prec) { slong k; acb_dft(w, v, len, prec); for (k = 1; 2 * k < len; k++) acb_swap(w + k, w + len - k); _acb_vec_scalar_div_ui(w, w, len, len, prec); } flint-3.1.3/src/acb_dft/prod.c000066400000000000000000000027171461254215100161230ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" acb_dft_step_ptr _acb_dft_steps_prod(slong * cyc, slong num, slong prec) { slong i, len; acb_dft_step_ptr s; s = flint_malloc(num * sizeof(acb_dft_step_struct)); len = 1; for (i = 0; i < num; i++) len *= cyc[i]; for (i = 0; i < num; i++) { slong m, M; m = cyc[i]; M = (len /= m); s[i].m = m; s[i].M = M; s[i].dv = M; s[i].dz = 0; s[i].z = NULL; _acb_dft_precomp_init(s[i].pre, M, NULL, 0, m, prec); } return s; } void acb_dft_prod_clear(acb_dft_prod_t t) { slong i; for (i = 0; i < t->num; i++) acb_dft_precomp_clear(t->cyc[i].pre); flint_free(t->cyc); } void acb_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dft_prod_t prod, slong prec) { if (prod->num >= 1) acb_dft_step(w, v, prod->cyc, prod->num, prec); } void acb_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) { acb_dft_prod_t t; acb_dft_prod_init(t, cyc, num, prec); acb_dft_prod_precomp(w, v, t, prec); acb_dft_prod_clear(t); } flint-3.1.3/src/acb_dft/profile/000077500000000000000000000000001461254215100164445ustar00rootroot00000000000000flint-3.1.3/src/acb_dft/profile/p-convol.c000066400000000000000000000070631461254215100203530ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_dft.h" #include "profiler.h" #define LOG 0 #define CSV 1 #define JSON 2 typedef void (*do_f) (acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec); int main(int argc, char *argv[]) { int out; flint_rand_t state; int l, nf = 5; do_f func[5] = { acb_dft_convol_naive, acb_dft_convol_dft, acb_dft_convol_rad2, acb_dft_convol_mullow, acb_dft_convol, }; char * name[5] = { "naive", "dft", "rad2", "mullow", "default" }; int i, ni = 14; ulong len[14] = { 60, 5*5*5, 131, 2*3*5*7, 256, 3*3*3*3*3, 2*2*2*43, 503, 2*2*2*101, 3001, 8192, 13*11*61, 10000, 101*103 }; char * factor[14] = { "2^2*3*5", "5^3", "131", "2*3*5*7", "2^8", "3^5", "2^3*43", "503", "2^3*101", "3001", "2^13", "11*13*61", "2^4*5^4", "101*103" }; slong ml[14] = { 20, 10, 10, 5, 5, 5, 3, 3, 2, 2, 1, 1, 1, 1}; int j, nj = 4; slong prec[4] = { 64, 128, 512, 1024 }; slong mp[4] = { 40, 20, 5, 2 }; if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } if (out == CSV) flint_printf("# %-12s, %7s, %7s, %7s\n","name", "prec", "len", "factor", "time"); flint_randinit(state); for (j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { slong k, nm; acb_ptr u, v, w; nm = mp[j] * ml[i]; u = _acb_vec_init(len[i]); v = _acb_vec_init(len[i]); w = _acb_vec_init(len[i]); for (k = 0; k < len[i]; k++) { acb_randtest_precise(u + k, state, prec[j], 4); acb_randtest_precise(v + k, state, prec[j], 4); } if (out == LOG) flint_printf("%wu * CONV(%wu = %s), prec %wu....\n", nm, len[i], factor[i], prec[j]); for (l = 0; l < nf; l++) { slong m; if (len[i] > 1000 && l == 0) continue; if (out == LOG) flint_printf("%-14s ... ", name[l]); else if (out == CSV) flint_printf("%-12s, %7d, %8s, %7d, ", name[l], prec[j], len[i], factor[i]); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"len\": %d, \"factor\": %s, \"time\": ", name[l], prec[j], len[i], factor[i]); TIMEIT_ONCE_START for (m = 0; m < nm; m++) func[l](w, u, v, len[i], prec[j]); TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } _acb_vec_clear(u, len[i]); _acb_vec_clear(v, len[i]); _acb_vec_clear(w, len[i]); } } flint_cleanup(); return 0; } flint-3.1.3/src/acb_dft/profile/p-dft.c000066400000000000000000000073271461254215100176330ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_dft.h" #include "profiler.h" #define LOG 0 #define CSV 1 #define JSON 2 typedef void (*do_f) (acb_ptr y, acb_srcptr x, slong len, slong prec); int main(int argc, char *argv[]) { int out; flint_rand_t state; int l, nf = 5; do_f func[5] = { acb_dft_naive, acb_dft_crt, acb_dft_cyc, acb_dft_bluestein, acb_dft }; char * name[6] = { "naive", "crt", "cyc", "bluestein", "default", "precomp" }; int i, ni = 14; ulong len[14] = { 60, 5*5*5, 131, 2*3*5*7, 256, 3*3*3*3*3, 2*2*2*43, 503, 2*2*2*101, 3001, 8192, 13*11*61, 10000, 101*103 }; char * factor[14] = { "2^2*3*5", "5^3", "131", "2*3*5*7", "2^8", "3^5", "2^3*43", "503", "2^3*101", "3001", "2^13", "11*13*61", "2^4*5^4", "101*103" }; slong ml[14] = { 20, 10, 20, 20, 10, 10, 10, 5, 5, 5, 3, 3, 3, 3}; int j, nj = 4; slong prec[4] = { 64, 128, 512, 1024 }; slong mp[4] = { 40, 20, 5, 2 }; if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } if (out == CSV) flint_printf("# %-12s, %7s, %7s, %7s\n","name", "prec", "len", "factor", "time"); flint_randinit(state); for (j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { slong k, nm; acb_ptr u, v; nm = mp[j] * ml[i]; u = _acb_vec_init(len[i]); v = _acb_vec_init(len[i]); for (k = 0; k < len[i]; k++) acb_randtest_precise(u + k, state, prec[j], 4); if (out == LOG) flint_printf("%wu * DFT(%wu = %s), prec %wu....\n", nm, len[i], factor[i], prec[j]); for (l = 0; l <= nf; l++) { slong m; if (len[i] > 300 && l == 0) continue; if (out == LOG) flint_printf("%-14s ... ", name[l]); else if (out == CSV) flint_printf("%-12s, %7d, %8s, %7d, ", name[l], prec[j], len[i], factor[i]); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"len\": %d, \"factor\": %s, \"time\": ", name[l], prec[j], len[i], factor[i]); TIMEIT_ONCE_START if (l < nf) { for (m = 0; m < nm; m++) func[l](v, u, len[i], prec[j]); } else { acb_dft_pre_t t; acb_dft_precomp_init(t, len[i], prec[j]); for (m = 0; m < nm; m++) acb_dft_precomp(v, u, t, prec[j]); acb_dft_precomp_clear(t); } TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } _acb_vec_clear(u, len[i]); _acb_vec_clear(v, len[i]); } } flint_cleanup(); return 0; } flint-3.1.3/src/acb_dft/rad2.c000066400000000000000000000060201461254215100157760ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" /* swap each element with one with bit-reversed index */ void acb_dft_rad2_reorder(acb_ptr v, slong n) { slong i, j, k, l; for (i = 0, l = n>>1; i < l; i++) { /* j = bit reversal of i */ for (k = 1, j = 0; k < n; k <<= 1) { j <<= 1; if (i & k) j |= 1; } if (i < j) acb_swap(v + i, v + j); else if (i > j) acb_swap(v + n - 1 - i, v + n - 1 - j); i++, j |= l; acb_swap(v + i, v + j); } } void _acb_dft_rad2_init(acb_dft_rad2_t t, slong dv, int e, slong prec) { if (e < 0) { flint_throw(FLINT_ERROR, "acb_dft_rad2_init: need e >= 0"); } t->e = e; t->n = WORD(1) << e; t->dv = dv; t->nz = t->n >> 1; t->z = _acb_vec_init(t->nz); /* set n/2 roots of order n */ _acb_vec_unit_roots(t->z, -t->n, t->nz, prec); } /* remark: can use same rad2 with smaller power of 2 */ void acb_dft_rad2_precomp_inplace(acb_ptr v, const acb_dft_rad2_t rad2, slong prec) { if (flint_get_num_threads() > 1 && rad2-> e > 9) { acb_dft_rad2_precomp_inplace_threaded(v, rad2, prec); } else { slong j, k, l; slong n = rad2->n, nz = rad2->nz; acb_ptr p, vend = v + n, w = rad2->z; acb_t tmp; acb_init(tmp); acb_dft_rad2_reorder(v, n); for (k = 1, l = nz; k < n; k <<= 1, l >>= 1) for (p = v; p < vend; p += k) for (j = 0; j < nz; j += l, p++) { acb_mul(tmp, p + k, w + j, prec); acb_sub(p + k, p + 0, tmp, prec); acb_add(p + 0, p + 0, tmp, prec); } acb_clear(tmp); } } void acb_dft_inverse_rad2_precomp_inplace(acb_ptr v, const acb_dft_rad2_t rad2, slong prec) { slong k, n = rad2->n; acb_dft_rad2_precomp_inplace(v, rad2, prec); _acb_vec_scalar_mul_2exp_si(v, v, n, - rad2->e); for (k = 1; k < n / 2; k++) acb_swap(v + k, v + n - k); } void acb_dft_rad2_inplace(acb_ptr v, int e, slong prec) { acb_dft_rad2_t rad2; acb_dft_rad2_init(rad2, e, prec); acb_dft_rad2_precomp_inplace(v, rad2, prec); acb_dft_rad2_clear(rad2); } void acb_dft_rad2_precomp(acb_ptr w, acb_srcptr v, const acb_dft_rad2_t rad2, slong prec) { slong k; for (k = 0; k < rad2->n; k++, v += rad2->dv) acb_set(w + k, v + 0); acb_dft_rad2_precomp_inplace(w, rad2, prec); } void acb_dft_rad2(acb_ptr w, acb_srcptr v, int e, slong prec) { acb_dft_rad2_t rad2; acb_dft_rad2_init(rad2, e, prec); acb_dft_rad2_precomp(w, v, rad2, prec); acb_dft_rad2_clear(rad2); } flint-3.1.3/src/acb_dft/rad2_threaded.c000066400000000000000000000066041461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin Copyright (C) 2020 D.H.J. Polymath Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "acb_dft.h" void acb_dft_rad2_reorder(acb_ptr v, slong n); typedef struct { acb_ptr v; acb_ptr vend; slong k; slong l; slong jstart; slong jend; acb_srcptr w; slong prec; } _worker_arg; void _acb_dft_rad2_thread(void * arg_ptr) { _worker_arg arg = *((_worker_arg *) arg_ptr); slong j, rstart, pstep; acb_ptr p, r; acb_t tmp; acb_init(tmp); rstart = arg.jstart / arg.l; pstep = 2 * arg.k; for (p = arg.v; p < arg.vend; p += pstep) { for (r = p + rstart, j = arg.jstart; j < arg.jend; j += arg.l, r++) { acb_mul(tmp, r + arg.k, arg.w + j, arg.prec); acb_sub(r + arg.k, r + 0, tmp, arg.prec); acb_add(r + 0, r + 0, tmp, arg.prec); } } acb_clear(tmp); flint_cleanup(); return; } void acb_dft_rad2_precomp_inplace_threaded(acb_ptr v, const acb_dft_rad2_t rad2, slong prec) { slong num_threads, num_workers; thread_pool_handle * handles; _worker_arg * args; slong t, logt, logk, logl; slong n = rad2->n; slong nz = rad2->nz; /* always n/2 ? */ slong logn = rad2->e; num_workers = flint_request_threads(&handles, nz); num_threads = num_workers + 1; for (logt = 0; WORD(1) << (logt + 1) <= num_threads; logt++); t = WORD(1) << logt; args = FLINT_ARRAY_ALLOC(t, _worker_arg); acb_dft_rad2_reorder(v, n); for (logk = 0, logl = logn - 1; logk < logn; logk += 1, logl -= 1) { slong i, j, p; slong logpstep = logk + 1 + FLINT_MAX(0, logl - logt); slong logjstep = logl + FLINT_MIN(logk, logn - 1 - logt); slong pstep = WORD(1) << logpstep; slong jstep = WORD(1) << logjstep; i = 0; for (p = 0; p < n; p += pstep) { for (j = 0; j < nz ; j += jstep) { args[i].v = v + p; args[i].vend = v + p + pstep; args[i].jstart = j; args[i].jend = j + jstep; args[i].k = WORD(1) << logk; args[i].l = WORD(1) << logl; args[i].w = rad2->z; args[i].prec = prec; if (i != num_workers) thread_pool_wake(global_thread_pool, handles[i], 0, _acb_dft_rad2_thread, &args[i]); else _acb_dft_rad2_thread(&args[i]); i++; } } if (i != t) flint_throw(FLINT_ERROR, "unequal i=%wd, t=%wd in %s\n", i, t, __func__); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); } flint_give_back_threads(handles, num_workers); flint_free(args); } void acb_dft_rad2_inplace_threaded(acb_ptr v, int e, slong prec) { acb_dft_rad2_t rad2; acb_dft_rad2_init(rad2, e, prec); acb_dft_rad2_precomp_inplace_threaded(v, rad2, prec); acb_dft_rad2_clear(rad2); } flint-3.1.3/src/acb_dft/step.c000066400000000000000000000042201461254215100161210ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" #define REORDER 0 void acb_dft_step(acb_ptr w, acb_srcptr v, acb_dft_step_ptr cyc, slong num, slong prec) { acb_dft_step_struct c; if (num == 0) return; c = cyc[0]; if (num == 1) { acb_dft_precomp(w, v, c.pre, prec); /*_acb_dft_base(w, v, c.dv, c.z, c.dz, c.m, prec);*/ } else { slong i, j; slong m = c.m, M = c.M, dv = c.dv, dz = c.dz; acb_srcptr z = c.z; acb_ptr t; #if REORDER acb_ptr w2; #endif t = _acb_vec_init(m * M); if (w == v) { _acb_vec_set(t, v, m * M); v = t; } /* m DFT of size M */ for (i = 0; i < m; i++) acb_dft_step(w + i * M, v + i * dv, cyc + 1, num - 1, prec); /* twiddle if non trivial product */ if (c.z != NULL) { acb_ptr wi; for (wi = w + M, i = 1; i < m; i++, wi += M) for (j = 1; j < M; j++) { if (DFT_VERB) flint_printf("z[%wu*%wu]",dz,i*j); acb_mul(wi + j, wi + j, z + dz * i * j, prec); } if (DFT_VERB) flint_printf("\n"); } #if REORDER /* reorder w to avoid dv shifts in next DFT */ w2 = flint_malloc(m * M * sizeof(acb_struct)); for (j = 0; j < M; j++) for (i = 0; i < m; i++) w2[j + M * i] = w[i + m * j]; #endif /* M DFT of size m */ for (j = 0; j < M; j++) acb_dft_precomp(t + m * j, w + j, c.pre, prec); /* reorder */ for (i = 0; i < m; i++) for (j = 0; j < M; j++) acb_set(w + j + M * i, t + i + m * j); _acb_vec_clear(t, m * M); } } flint-3.1.3/src/acb_dft/test/000077500000000000000000000000001461254215100157635ustar00rootroot00000000000000flint-3.1.3/src/acb_dft/test/main.c000066400000000000000000000014551461254215100170600ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-convol.c" #include "t-dft.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_dft_convol), TEST_FUNCTION(acb_dft) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_dft/test/t-convol.c000066400000000000000000000070411461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dft.h" /* Both of these are defined in t-convol.c and t-dft.c. However, do_f is not the * same. */ #define do_f hogusbogusname typedef void (*do_f) (acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec); #ifndef check_vec_eq_prec #define check_vec_eq_prec check_vec_eq_prec void check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char d[], char f1[], char f2[]) { slong i; for (i = 0; i < len; i++) { if (!acb_overlaps(w1 + i, w2 + i)) { flint_printf("FAIL\n\n"); flint_printf("q = %wu, size = %wd\n", q, len); flint_printf("\nDFT %sdiffer from index %wd / %wd \n", d, i, len); flint_printf("\n%s =\n", f1); acb_vec_printd_index(w1, len, digits); flint_printf("\n%s =\n", f2); acb_vec_printd_index(w2, len, digits); flint_printf("\n\n"); flint_abort(); } else if (!acb_is_zero(w1+i) && (acb_rel_accuracy_bits(w1 + i) < 30 || acb_rel_accuracy_bits(w2 + i) < 30)) { flint_printf("FAIL\n\n"); flint_printf("q = %wu\n", q); flint_printf("\nDFT inaccurate from index %wd / %wd \n", i, len); flint_printf("\n%s =\n", f1); acb_printd(w1 + i, digits); flint_printf("\n%s =\n", f2); acb_printd(w2 + i, digits); flint_printf("\nerrors %wd & %wd [prec = %wd]\n", acb_rel_accuracy_bits(w1 + i), acb_rel_accuracy_bits(w2 + i), prec); flint_abort(); } } } #endif TEST_FUNCTION_START(acb_dft_convol, state) { slong k; slong prec = 100, digits = 30; slong nq = 17; ulong q[17] = { 0, 1, 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 256, 308, 335, 344, 961}; ulong nr = 5; slong f, nf = 4; do_f func[4] = { acb_dft_convol_naive, acb_dft_convol_rad2, acb_dft_convol_dft, acb_dft_convol_mullow }; char * name[4] = { "naive", "rad2", "dft", "mullow" }; for (k = 0; k < nq + nr; k++) { slong i, len; acb_ptr z1, z2, x, y; if (k < nq) len = q[k]; else len = n_randint(state, 2000); z1 = _acb_vec_init(len); z2 = _acb_vec_init(len); x = _acb_vec_init(len); y = _acb_vec_init(len); for (i = 0; i < len; i++) { #if 1 acb_set_si(x + i, n_randint(state, 4 * len)); acb_set_si(y + i, n_randint(state, 4 * len)); #else acb_set_si_si(x + i, n_randint(state, 4 * len), n_randint(state, 4 * len)); acb_set_si_si(y + i, n_randint(state, 4 * len), n_randint(state, 4 * len)); #endif } for (f = 0; f < nf; f++) { acb_ptr z = (f == 0) ? z1 : z2; func[f](z, x, y, len, prec); if (f == 0) continue; check_vec_eq_prec(z1, z2, len, prec, digits, len, "", name[0], name[f]); } _acb_vec_clear(x, len); _acb_vec_clear(y, len); _acb_vec_clear(z1, len); _acb_vec_clear(z2, len); } TEST_FUNCTION_END(state); } #undef do_f flint-3.1.3/src/acb_dft/test/t-dft.c000066400000000000000000000120101461254215100171370ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dft.h" /* Both of these are defined in t-convol.c and t-dft.c. However, do_f is not the * same. */ #define do_f rajtantajtan typedef void (*do_f) (acb_ptr w, acb_srcptr v, slong len, slong prec); #ifndef check_vec_eq_prec #define check_vec_eq_prec check_vec_eq_prec void check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char d[], char f1[], char f2[]) { slong i; for (i = 0; i < len; i++) { if (!acb_overlaps(w1 + i, w2 + i)) { flint_printf("FAIL\n\n"); flint_printf("q = %wu, size = %wd\n", q, len); flint_printf("\nDFT %sdiffer from index %wd / %wd \n", d, i, len); flint_printf("\n%s =\n", f1); acb_vec_printd_index(w1, len, digits); flint_printf("\n%s =\n", f2); acb_vec_printd_index(w2, len, digits); flint_printf("\n\n"); flint_abort(); } else if (!acb_is_zero(w1+i) && (acb_rel_accuracy_bits(w1 + i) < 30 || acb_rel_accuracy_bits(w2 + i) < 30)) { flint_printf("FAIL\n\n"); flint_printf("q = %wu\n", q); flint_printf("\nDFT inaccurate from index %wd / %wd \n", i, len); flint_printf("\n%s =\n", f1); acb_printd(w1 + i, digits); flint_printf("\n%s =\n", f2); acb_printd(w2 + i, digits); flint_printf("\nerrors %wd & %wd [prec = %wd]\n", acb_rel_accuracy_bits(w1 + i), acb_rel_accuracy_bits(w2 + i), prec); flint_abort(); } } } #endif TEST_FUNCTION_START(acb_dft, state) { slong k; slong prec = 100, digits = 30; slong nq = 19; ulong q[19] = { 0, 1, 2, 3, 4, 5, 6, 23, 10, 15, 16, 30, 59, 125, 308, 335, 525, 961, 1225}; slong nr = 5; slong f, nf = 5; do_f func[5] = { acb_dft_naive, acb_dft_cyc, acb_dft_crt, acb_dft_bluestein, acb_dft }; char * name[5] = { "naive", "cyc", "crt", "bluestein", "default" }; /* cyclic dft */ for (k = 0; k < nq + nr; k++) { slong i, len, f0; acb_ptr v, w1, w2, w3; if (k < nq) len = q[k]; else len = n_randint(state, 1000); v = _acb_vec_init(len); w1 = _acb_vec_init(len); w2 = _acb_vec_init(len); w3 = _acb_vec_init(len); for (i = 0; i < len; i++) acb_set_si_si(v + i, i, 3 - i); /* avoid naive for long transforms */ f0 = (len > 50); for (f = f0; f < nf; f++) { acb_ptr w = (f == f0) ? w1 : w2; if (DFT_VERB) flint_printf("\n%s %wu\n", name[f], len); /* compute DFT */ func[f](w, v, len, prec); if (len < 500) { /* check aliasing */ _acb_vec_set(w3, v, len); func[f](w3, w3, len, prec); check_vec_eq_prec(w1, w3, len, prec, digits, len, "alias ", name[0], name[f]); } if (f > f0) { /* check non aliased */ check_vec_eq_prec(w1, w2, len, prec, digits, len, "no alias ", name[0], name[f]); } else { /* check inverse */ acb_dft_inverse(w2, w1, len, prec); check_vec_eq_prec(v, w2, len, prec, digits, len, "inverse ", "original", "inverse"); } } _acb_vec_clear(v, len); _acb_vec_clear(w1, len); _acb_vec_clear(w2, len); _acb_vec_clear(w3, len); } /* radix2 dft */ for (k = 0; k < 11; k++) { slong n = 1 << k, j; acb_ptr v, w1, w2; v = w2 = _acb_vec_init(n); w1 = _acb_vec_init(n); for (j = 0; j < n; j++) acb_set_si_si(v + j, j, j + 2); acb_dft_cyc(w1, v, n, prec); acb_dft_rad2_inplace(w2, k, prec); check_vec_eq_prec(w1, w2, n, prec, digits, n, "rad2 ", "cyc", "rad2"); _acb_vec_clear(v, n); _acb_vec_clear(w1, n); } /* multi-threaded radix2 dft */ for (k = 0; k < 11; k++) { slong n = 1 << k, j; acb_ptr v, w1, w2; v = w2 = _acb_vec_init(n); w1 = _acb_vec_init(n); flint_set_num_threads(k % 5 + 1); for (j = 0; j < n; j++) acb_set_si_si(v + j, j, j + 2); acb_dft_cyc(w1, v, n, prec); acb_dft_rad2_inplace_threaded(w2, k, prec); check_vec_eq_prec(w1, w2, n, prec, digits, n, "rad2 ", "cyc", "rad2"); _acb_vec_clear(v, n); _acb_vec_clear(w1, n); } TEST_FUNCTION_END(state); } #undef do_f flint-3.1.3/src/acb_dirichlet.h000066400000000000000000000363451461254215100163620ustar00rootroot00000000000000/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_DIRICHLET_H #define ACB_DIRICHLET_H #include "acb.h" #include "dirichlet.h" #ifdef __cplusplus extern "C" { #endif void acb_dirichlet_powsum_term(acb_ptr res, arb_t log_prev, ulong * prev, const acb_t s, ulong k, int integer, int critical_line, slong len, slong prec); void acb_dirichlet_powsum_sieved(acb_ptr z, const acb_t s, ulong n, slong len, slong prec); void acb_dirichlet_powsum_smooth(acb_ptr z, const acb_t s, ulong n, slong len, slong prec); void acb_dirichlet_zeta_bound(mag_t res, const acb_t s); void acb_dirichlet_zeta_deriv_bound(mag_t der1, mag_t der2, const acb_t s); void acb_dirichlet_zeta_rs_f_coeffs(acb_ptr c, const arb_t p, slong N, slong prec); void acb_dirichlet_zeta_rs_d_coeffs(arb_ptr d, const arb_t sigma, slong k, slong prec); void acb_dirichlet_zeta_rs_bound(mag_t err, const acb_t s, slong K); void acb_dirichlet_zeta_rs_r(acb_t res, const acb_t s, slong K, slong prec); void acb_dirichlet_zeta_rs(acb_t res, const acb_t s, slong K, slong prec); void acb_dirichlet_zeta(acb_t res, const acb_t s, slong prec); void acb_dirichlet_zeta_jet_rs(acb_ptr res, const acb_t s, slong len, slong prec); void acb_dirichlet_zeta_jet(acb_t res, const acb_t s, int deflate, slong len, slong prec); void acb_dirichlet_hurwitz(acb_t res, const acb_t s, const acb_t a, slong prec); void acb_dirichlet_lerch_phi_integral(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec); void acb_dirichlet_lerch_phi_direct(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec); void acb_dirichlet_lerch_phi(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec); void acb_dirichlet_stieltjes(acb_t res, const fmpz_t n, const acb_t a, slong prec); typedef struct { acb_struct s; mag_struct err; acb_ptr coeffs; int deflate; slong A; slong N; slong K; } acb_dirichlet_hurwitz_precomp_struct; typedef acb_dirichlet_hurwitz_precomp_struct acb_dirichlet_hurwitz_precomp_t[1]; void acb_dirichlet_hurwitz_precomp_init(acb_dirichlet_hurwitz_precomp_t pre, const acb_t s, int deflate, slong A, slong K, slong N, slong prec); void acb_dirichlet_hurwitz_precomp_init_num(acb_dirichlet_hurwitz_precomp_t pre, const acb_t s, int deflate, double num_eval, slong prec); void acb_dirichlet_hurwitz_precomp_clear(acb_dirichlet_hurwitz_precomp_t pre); void acb_dirichlet_hurwitz_precomp_bound(mag_t res, const acb_t s, slong A, slong K, slong N); void acb_dirichlet_hurwitz_precomp_eval(acb_t res, const acb_dirichlet_hurwitz_precomp_t pre, ulong p, ulong q, slong prec); void acb_dirichlet_hurwitz_precomp_choose_param(ulong * A, ulong * K, ulong * N, const acb_t s, double num_eval, slong prec); void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, const signed char * chi, int mod, int reciprocal, slong prec); void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); void acb_dirichlet_xi(acb_t res, const acb_t s, slong prec); void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec); void acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec); /* precompute roots of unity */ typedef struct { ulong order; ulong reduced_order; acb_t z; slong size; slong depth; acb_ptr * Z; int use_pow; } acb_dirichlet_roots_struct; typedef acb_dirichlet_roots_struct acb_dirichlet_roots_t[1]; void acb_dirichlet_roots_init(acb_dirichlet_roots_t t, ulong order, slong num, slong prec); void acb_dirichlet_roots_clear(acb_dirichlet_roots_t t); void acb_dirichlet_root(acb_t z, const acb_dirichlet_roots_t t, ulong n, slong prec); void acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec); void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec); void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); void acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec); void acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_roots_t z, slong len, slong prec); void acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_roots_t z, slong len, slong prec); ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec); ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec); void mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n); void _acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slong prec); void acb_dirichlet_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec); void acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec); void acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); void acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); ulong jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond); void acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); void acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); void acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); void acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec); void acb_dirichlet_l_euler_product(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_hurwitz_precomp_t precomp, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_l(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_hurwitz_precomp_t precomp, const dirichlet_group_t G, slong prec); void acb_dirichlet_l_jet(acb_ptr res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec); void acb_dirichlet_l_fmpq_afe(acb_t res, const fmpq_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_l_fmpq(acb_t res, const fmpq_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void _acb_dirichlet_l_series(acb_ptr res, acb_srcptr s, slong slen, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec); void acb_dirichlet_l_series(acb_poly_t res, const acb_poly_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec); void acb_dirichlet_hardy_theta(acb_ptr res, const acb_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec); void acb_dirichlet_hardy_z(acb_ptr res, const acb_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec); void _acb_dirichlet_hardy_theta_series(acb_ptr res, acb_srcptr s, slong slen, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec); void acb_dirichlet_hardy_theta_series(acb_poly_t res, const acb_poly_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec); void _acb_dirichlet_hardy_z_series(acb_ptr res, acb_srcptr s, slong slen, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec); void acb_dirichlet_hardy_z_series(acb_poly_t res, const acb_poly_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec); void acb_dirichlet_gram_point(arb_t res, const fmpz_t n, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); ulong acb_dirichlet_turing_method_bound(const fmpz_t p); int _acb_dirichlet_definite_hardy_z(arb_t res, const arf_t t, slong *pprec); void _acb_dirichlet_isolate_gram_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n); void _acb_dirichlet_isolate_rosser_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n); void _acb_dirichlet_isolate_turing_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n); void acb_dirichlet_isolate_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n); void _acb_dirichlet_refine_hardy_z_zero(arb_t res, const arf_t a, const arf_t b, slong prec); void acb_dirichlet_hardy_z_zeros(arb_ptr res, const fmpz_t n, slong len, slong prec); void acb_dirichlet_zeta_zeros(acb_ptr res, const fmpz_t n, slong len, slong prec); slong acb_dirichlet_platt_zeta_zeros(acb_ptr res, const fmpz_t n, slong len, slong prec); void _acb_dirichlet_exact_zeta_nzeros(fmpz_t res, const arf_t t); void acb_dirichlet_zeta_nzeros(arb_t res, const arb_t t, slong prec); void acb_dirichlet_backlund_s(arb_t res, const arb_t t, slong prec); void acb_dirichlet_backlund_s_bound(mag_t res, const arb_t t); void acb_dirichlet_zeta_nzeros_gram(fmpz_t res, const fmpz_t n); slong acb_dirichlet_backlund_s_gram(const fmpz_t n); FLINT_FORCE_INLINE void acb_dirichlet_hardy_z_zero(arb_t res, const fmpz_t n, slong prec) { acb_dirichlet_hardy_z_zeros(res, n, 1, prec); } FLINT_FORCE_INLINE void acb_dirichlet_zeta_zero(acb_t res, const fmpz_t n, slong prec) { acb_dirichlet_zeta_zeros(res, n, 1, prec); } /* Platt zeta zeros */ typedef struct { slong len; arb_ptr p; arb_struct Xa; arb_struct Xb; } acb_dirichlet_platt_c_precomp_struct; typedef acb_dirichlet_platt_c_precomp_struct acb_dirichlet_platt_c_precomp_t[1]; typedef struct { arb_struct c1; arb_struct c2; } acb_dirichlet_platt_i_precomp_struct; typedef acb_dirichlet_platt_i_precomp_struct acb_dirichlet_platt_i_precomp_t[1]; typedef struct { acb_dirichlet_platt_c_precomp_struct pre_c; acb_dirichlet_platt_i_precomp_struct pre_i; } acb_dirichlet_platt_ws_precomp_struct; typedef acb_dirichlet_platt_ws_precomp_struct acb_dirichlet_platt_ws_precomp_t[1]; /* Platt C bound */ void acb_dirichlet_platt_c_precomp_init(acb_dirichlet_platt_c_precomp_t pre, slong sigma, const arb_t h, ulong k, slong prec); void acb_dirichlet_platt_c_precomp_clear(acb_dirichlet_platt_c_precomp_t pre); void acb_dirichlet_platt_c_bound_precomp(arb_t res, const acb_dirichlet_platt_c_precomp_t pre, slong sigma, const arb_t t0, const arb_t h, slong k, slong prec); void acb_dirichlet_platt_c_bound(arb_t res, slong sigma, const arb_t t0, const arb_t h, slong k, slong prec); /* Platt I bound */ void acb_dirichlet_platt_i_precomp_init(acb_dirichlet_platt_i_precomp_t pre, slong A, const arb_t H, slong sigma, slong prec); void acb_dirichlet_platt_i_precomp_clear(acb_dirichlet_platt_i_precomp_t pre); void acb_dirichlet_platt_i_bound_precomp(arb_t res, const acb_dirichlet_platt_i_precomp_t pre_i, const acb_dirichlet_platt_c_precomp_t pre_c, const arb_t t0, slong A, const arb_t H, slong sigma, slong prec); void acb_dirichlet_platt_i_bound(arb_t res, const arb_t t0, slong A, const arb_t H, slong sigma, slong prec); /* Platt Gaussian-windowed Whittaker-Shannon interpolation */ void acb_dirichlet_platt_ws_precomp_init(acb_dirichlet_platt_ws_precomp_t pre, slong A, const arb_t H, slong sigma, slong prec); void acb_dirichlet_platt_ws_precomp_clear(acb_dirichlet_platt_ws_precomp_t pre); void acb_dirichlet_platt_ws_interpolation_precomp(arb_t res, arf_t deriv, const acb_dirichlet_platt_ws_precomp_t pre, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong Ns_max, const arb_t H, slong sigma, slong prec); void acb_dirichlet_platt_ws_interpolation(arb_t res, arf_t deriv, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong Ns_max, const arb_t H, slong sigma, slong prec); void acb_dirichlet_platt_bound_C3(arb_t res, const arb_t t0, slong A, const arb_t H, slong Ns, slong prec); void acb_dirichlet_platt_scaled_lambda(arb_t res, const arb_t t, slong prec); void acb_dirichlet_platt_scaled_lambda_vec(arb_ptr res, const fmpz_t T, slong A, slong B, slong prec); /* Platt lemma bounds of errors in the DFT grid evaluation of scaled Lambda */ void acb_dirichlet_platt_beta(arb_t res, const arb_t t, slong prec); void acb_dirichlet_platt_lemma_32(arb_t out, const arb_t h, const arb_t t0, const arb_t x, slong prec); void acb_dirichlet_platt_lemma_A5(arb_t out, slong B, const arb_t h, slong k, slong prec); void acb_dirichlet_platt_lemma_A7(arb_t out, slong sigma, const arb_t t0, const arb_t h, slong k, slong A, slong prec); void acb_dirichlet_platt_lemma_A9(arb_t out, slong sigma, const arb_t t0, const arb_t h, slong A, slong prec); void acb_dirichlet_platt_lemma_A11(arb_t out, const arb_t t0, const arb_t h, slong B, slong prec); void acb_dirichlet_platt_lemma_B1(arb_t out, slong sigma, const arb_t t0, const arb_t h, const fmpz_t J, slong prec); void acb_dirichlet_platt_lemma_B2(arb_t out, slong K, const arb_t h, const arb_t xi, slong prec); /* Platt DFT grid evaluation of scaled Lambda */ void acb_dirichlet_platt_multieval(arb_ptr out, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec); void acb_dirichlet_platt_multieval_threaded(arb_ptr out, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec); /* Platt Hardy Z zeros */ slong _acb_dirichlet_platt_local_hardy_z_zeros( arb_ptr res, const fmpz_t n, slong len, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma_grid, slong Ns_max, const arb_t H, slong sigma_interp, slong prec); slong acb_dirichlet_platt_local_hardy_z_zeros( arb_ptr res, const fmpz_t n, slong len, slong prec); slong acb_dirichlet_platt_hardy_z_zeros( arb_ptr res, const fmpz_t n, slong len, slong prec); /* Discrete Fourier Transform */ void acb_dirichlet_dft_index(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec); void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_dirichlet/000077500000000000000000000000001461254215100161765ustar00rootroot00000000000000flint-3.1.3/src/acb_dirichlet/arb_quadratic_powers.c000066400000000000000000000017101461254215100225410ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* TODO: BSGS can reduce to nv mul */ void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec) { slong i; arb_t dx, x2; arb_init(dx); arb_init(x2); arb_set(dx, x); arb_mul(x2, x, x, prec); for (i = 0; i < nv; i++) { if (i == 0) arb_one(v + i); else if (i == 1) arb_set_round(v + i, x, prec); else { arb_mul(dx, dx, x2, prec); arb_mul(v + i, v + i - 1, dx, prec); } } arb_clear(dx); arb_clear(x2); } flint-3.1.3/src/acb_dirichlet/backlund_s.c000066400000000000000000000044321461254215100204520ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* S(t) = N(t) - theta(t)/pi - 1 */ static void _backlund_s(arb_t res, const arb_t t, slong prec) { arb_t N; acb_t z; arb_init(N); acb_init(z); acb_dirichlet_zeta_nzeros(N, t, prec); acb_set_arb(z, t); acb_dirichlet_hardy_theta(z, z, NULL, NULL, 1, prec); arb_const_pi(acb_imagref(z), prec); arb_div(acb_realref(z), acb_realref(z), acb_imagref(z), prec); arb_sub(res, N, acb_realref(z), prec); arb_sub_ui(res, res, 1, prec); arb_clear(N); acb_clear(z); } void acb_dirichlet_backlund_s(arb_t res, const arb_t t, slong prec) { mag_t m, b; mag_init(m); mag_init(b); arb_get_mag(m, t); if (!arb_is_nonnegative(t)) { arb_indeterminate(res); } else if (mag_cmp_2exp_si(m, 6) < 0) /* If t is small then N(t) is fast. */ { _backlund_s(res, t, prec); } else { /* * If the error radius of t is greater than 8/log(t) then use a fast * bound. The threshold doesn't matter for correctness, but note that * the average spacing of zeros is 2*pi/log(t) asymptotically. * Otherwise if the radius is smaller use S(t) = N(t) - theta(t)/pi - 1. */ mag_log(b, m); mag_mul_2exp_si(b, b, -3); mag_inv(b, b); if (mag_cmp(arb_radref(t), b) > 0) { arb_zero(res); acb_dirichlet_backlund_s_bound(arb_radref(res), t); } else { acb_t z; acb_init(z); /* * The difference (N(t) - theta(t)/pi) loses precision from * cancellation. Add extra bits to mitigate the loss. */ acb_set_arb(z, t); acb_dirichlet_hardy_theta(z, z, NULL, NULL, 1, prec); _backlund_s(res, t, prec + mag_get_d_log2_approx(m)); acb_clear(z); } } mag_clear(m); mag_clear(b); } flint-3.1.3/src/acb_dirichlet/backlund_s_bound.c000066400000000000000000000031601461254215100216360ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void _mag_div_ui_ui(mag_t res, ulong a, ulong b) { mag_set_ui(res, a); mag_div_ui(res, res, b); } void acb_dirichlet_backlund_s_bound(mag_t res, const arb_t t) { if (!arb_is_nonnegative(t)) { mag_inf(res); } else { mag_t m; mag_init(m); arb_get_mag(m, t); if (mag_cmp_2exp_si(m, 8) < 0) /* 2^8 < 280 */ { mag_one(res); } else if (mag_cmp_2exp_si(m, 22) < 0) /* 2^22 < 6.8*10^6 */ { mag_set_ui(res, 2); } else if (mag_cmp_2exp_si(m, 29) < 0) /* 2^29 < 5.45*10^8 */ { _mag_div_ui_ui(res, 231366, 100000); } else { /* |S(t)| <= 0.112*log(t) + 0.278*log(log(t)) + 2.51 */ mag_t c, logm; mag_init(c); mag_init(logm); mag_log(logm, m); _mag_div_ui_ui(c, 278, 1000); mag_log(res, logm); mag_mul(res, res, c); _mag_div_ui_ui(c, 112, 1000); mag_addmul(res, c, logm); _mag_div_ui_ui(c, 251, 100); mag_add(res, res, c); mag_clear(c); mag_clear(logm); } mag_clear(m); } } flint-3.1.3/src/acb_dirichlet/backlund_s_gram.c000066400000000000000000000014261461254215100214600ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" slong acb_dirichlet_backlund_s_gram(const fmpz_t n) { slong res = 0; if (fmpz_cmp_si(n, -1) < 0) { flint_throw(FLINT_ERROR, "n must be >= -1\n"); } else { fmpz_t k; fmpz_init(k); acb_dirichlet_zeta_nzeros_gram(k, n); fmpz_sub(k, k, n); res = fmpz_get_si(k) - 1; fmpz_clear(k); } return res; } flint-3.1.3/src/acb_dirichlet/chi.c000066400000000000000000000016431461254215100171110ustar00rootroot00000000000000/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb_dirichlet.h" void acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec) { ulong expo; expo = dirichlet_chi(G, chi, n); if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else { fmpq_t t; fmpq_init(t); fmpq_set_si(t, 2 * expo , G->expo); arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); fmpq_clear(t); } } flint-3.1.3/src/acb_dirichlet/chi_vec.c000066400000000000000000000020051461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec) { slong k; ulong * a, order; acb_dirichlet_roots_t t; a = flint_malloc(nv * sizeof(ulong)); order = dirichlet_order_char(G, chi); dirichlet_chi_vec_order(a, G, chi, order, nv); acb_dirichlet_roots_init(t, order, nv, prec); acb_zero(v + 0); for (k = 0; k < nv; k++) { if (a[k] != DIRICHLET_CHI_NULL) acb_dirichlet_root(v + k, t, a[k], prec); else acb_zero(v + k); } acb_dirichlet_roots_clear(t); flint_free(a); } flint-3.1.3/src/acb_dirichlet/dft.c000066400000000000000000000031511461254215100171170ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" #include "acb_dirichlet.h" /* dft, lexicographic conrey indexing, array size G->phi_q */ void acb_dirichlet_dft_index(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) { if (G->phi_q == 1) { acb_set(w, v); } else { slong k, l, * cyc; cyc = flint_malloc(G->num * sizeof(slong)); for (k = 0, l = G->num - 1; l >= 0; k++, l--) cyc[k] = G->P[k].phi.n; acb_dft_prod(w, v, cyc, G->num, prec); flint_free(cyc); } } /* dft, number indexing, array size G->q */ void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) { ulong i, len; acb_ptr t1, t2; dirichlet_char_t x; len = G->phi_q; t1 = flint_malloc(len * sizeof(acb_struct)); dirichlet_char_init(x, G); dirichlet_char_one(x, G); for (i = 0; i < len; i++) { t1[i] = v[x->n]; dirichlet_char_next(x, G); }; t2 = _acb_vec_init(len); acb_dirichlet_dft_index(t2, t1, G, prec); dirichlet_char_one(x, G); for (i = 0; i < len; i++) { acb_set(w + x->n, t2 + i); dirichlet_char_next(x, G); }; _acb_vec_clear(t2, len); dirichlet_char_clear(x); flint_free(t1); } flint-3.1.3/src/acb_dirichlet/eta.c000066400000000000000000000032741461254215100171210ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec) { if (!acb_is_finite(s)) { acb_indeterminate(res); } else if (arb_contains_si(acb_realref(s), 1) && arb_contains_zero(acb_imagref(s))) { if (acb_is_one(s)) { arb_const_log2(acb_realref(res), prec); arb_zero(acb_imagref(res)); } else { mag_t m; int is_real = acb_is_real(s); mag_init(m); /* Taylor coefficients at s = 1 are bounded by |c_k| < 1/4^k. */ acb_sub_ui(res, s, 1, prec); acb_get_mag(m, res); mag_mul_2exp_si(m, m, -2); mag_geom_series(m, m, 1); arb_const_log2(acb_realref(res), prec); arb_zero(acb_imagref(res)); if (is_real) arb_add_error_mag(acb_realref(res), m); else acb_add_error_mag(res, m); mag_clear(m); } } else { acb_t t; acb_init(t); acb_one(t); acb_mul_2exp_si(t, t, -1); acb_pow(t, t, s, prec); acb_mul_2exp_si(t, t, 1); acb_sub_ui(t, t, 1, prec); acb_neg(t, t); acb_zeta(res, s, prec); acb_mul(res, res, t, prec); acb_clear(t); } } flint-3.1.3/src/acb_dirichlet/euler_product_real_ui.c000066400000000000000000000170521461254215100227230ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log # define sqrt __builtin_sqrt #else # include #endif #define ONE_OVER_LOG2 1.4426950408889634 typedef struct { ulong s; int mod; const signed char * chi; mp_ptr primes; double * powmags; slong num_primes; slong wp; slong index; slong num_threads; arb_struct res; } euler_work_chunk_t; static void euler_worker(void * _work) { euler_work_chunk_t * work = ((euler_work_chunk_t *) _work); slong i; slong powprec; double powmag; arb_t t, u; ulong p; arb_init(t); arb_init(u); for (i = work->index; i < work->num_primes; i += work->num_threads) { p = work->primes[i]; powmag = work->powmags[i]; powprec = FLINT_MAX(work->wp - powmag, 8); arb_ui_pow_ui(t, p, work->s, powprec); arb_set_round(u, &work->res, powprec); arb_div(t, u, t, powprec); if (work->mod == 1 || (work->chi[p % work->mod] == 1)) arb_sub(&work->res, &work->res, t, work->wp); else arb_add(&work->res, &work->res, t, work->wp); } arb_clear(t); arb_clear(u); } void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, const signed char * chi, int mod, int reciprocal, slong prec) { slong wp, powprec; double logp, powmag, errmag, limit; arb_t t, u; ulong p; mag_t err; slong num_threads; if (s <= 1) { arb_indeterminate(res); return; } if (prec < 2) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* L(s), 1/L(s) = 1 + ... For s >= 3, zeta(s,2) < 2^(1-s). */ if (s > (ulong) prec) { arf_one(arb_midref(res)); mag_set_ui_2exp_si(arb_radref(res), 1, -prec); return; } /* L(s), 1/L(s) = 1 +/- chi(2) 2^(-s) + ... For s >= 2, zeta(s,3) < 2^(2-floor(3s/2)). */ if (s > 0.7 * prec) { arb_one(res); if (chi[2 % mod] != 0) { arf_t t; arf_init(t); arf_set_si_2exp_si(t, chi[2 % mod], -s); if (reciprocal) arf_neg(t, t); arb_add_arf(res, res, t, prec); arf_clear(t); } arb_add_error_2exp_si(res, 2 - (3 * s) / 2); return; } /* Heuristic. */ wp = prec + FLINT_BIT_COUNT(prec) + (prec / s) + 4; arb_init(t); arb_init(u); /* 1 - chi(2) 2^(-s) */ arb_one(res); arf_set_ui_2exp_si(arb_midref(t), 1, -s); /* -s cannot overflow */ if (chi[2 % mod] == 1) arb_sub(res, res, t, wp); else if (chi[2 % mod] == -1) arb_add(res, res, t, wp); /* Cut at some point if this algorithm just isn't a good fit... */ /* The C * prec / log(prec) cutoff in arb_zeta_ui implies that the limit should be at least prec ^ (log(2) / C) for the Riemann zeta function, which gives prec ^ 1.2956 here. */ limit = 100 + prec * sqrt(prec); num_threads = flint_get_num_available_threads(); if (num_threads > 1 && prec > 5000 && s > 5000) { n_primes_t iter; slong i; mp_ptr primes; double * powmags; slong num_primes = 0; slong alloc = 16; slong thread_limit, num_threads, num_workers; thread_pool_handle * handles; euler_work_chunk_t * work; ulong first_omitted_p = 3; n_primes_init(iter); n_primes_jump_after(iter, 3); primes = flint_malloc(alloc * sizeof(mp_limb_t)); powmags = flint_malloc(alloc * sizeof(double)); for (p = 3; p < limit; p = n_primes_next(iter)) { first_omitted_p = p; if (mod == 1 || chi[p % mod] != 0) { /* p^s */ logp = log(p); powmag = s * logp * ONE_OVER_LOG2; /* zeta(s,p) ~= 1/p^s + 1/((s-1) p^(s-1)) */ errmag = (log(s - 1.0) + (s - 1.0) * logp) * ONE_OVER_LOG2; errmag = FLINT_MIN(powmag, errmag); if (errmag > prec + 2) break; if (num_primes >= alloc) { alloc *= 2; primes = flint_realloc(primes, alloc * sizeof(mp_limb_t)); powmags = flint_realloc(powmags, alloc * sizeof(double)); } primes[num_primes] = p; powmags[num_primes] = powmag; num_primes++; } } n_primes_clear(iter); thread_limit = flint_get_num_threads(); thread_limit = FLINT_MIN(thread_limit, num_primes / 4); thread_limit = FLINT_MAX(thread_limit, 1); num_workers = flint_request_threads(&handles, thread_limit); num_threads = num_workers + 1; work = flint_malloc(num_threads * sizeof(euler_work_chunk_t)); for (i = 0; i < num_threads; i++) { work[i].s = s; work[i].mod = mod; work[i].chi = chi; work[i].primes = primes; work[i].powmags = powmags; work[i].num_primes = num_primes; work[i].wp = wp; work[i].index = i; work[i].num_threads = num_threads; arb_init(&work[i].res); arb_one(&work[i].res); } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, euler_worker, &work[i]); euler_worker(&work[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); for (i = 0; i < num_threads; i++) { arb_mul(res, res, &work[i].res, wp); arb_clear(&work[i].res); } flint_free(work); flint_free(primes); flint_free(powmags); mag_init(err); mag_hurwitz_zeta_uiui(err, s, first_omitted_p); arb_add_error_mag(res, err); mag_clear(err); } else { /* todo: prime iterator here too? */ for (p = 3; p < limit; p = n_nextprime(p, 1)) { if (mod == 1 || chi[p % mod] != 0) { /* p^s */ logp = log(p); powmag = s * logp * ONE_OVER_LOG2; /* zeta(s,p) ~= 1/p^s + 1/((s-1) p^(s-1)) */ errmag = (log(s - 1.0) + (s - 1.0) * logp) * ONE_OVER_LOG2; errmag = FLINT_MIN(powmag, errmag); if (errmag > prec + 2) break; powprec = FLINT_MAX(wp - powmag, 8); arb_ui_pow_ui(t, p, s, powprec); arb_set_round(u, res, powprec); arb_div(t, u, t, powprec); if (mod == 1 || (chi[p % mod] == 1)) arb_sub(res, res, t, wp); else arb_add(res, res, t, wp); } } mag_init(err); mag_hurwitz_zeta_uiui(err, s, p); arb_add_error_mag(res, err); mag_clear(err); } if (reciprocal) arb_set_round(res, res, prec); else arb_inv(res, res, prec); arb_clear(t); arb_clear(u); } flint-3.1.3/src/acb_dirichlet/gauss_sum.c000066400000000000000000000052671461254215100203620ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong cond, slong prec) { slong k, mu = 1; ulong NN0 = G->q / cond; /* G(chi) = mu(N/N0)chi0(N/N0)G(chi0) */ if (NN0 % 2 == 0) { if (G->q % 4) mu = -1; else { acb_zero(res); return; } } for (k = G->neven; k < G->num; k++) { ulong p = G->P[k].p; if (G->P[k].e > 1 && NN0 % (p*p) == 0) { acb_zero(res); return; } if (NN0 % p == 0) mu *= -1; } if (chi->n == 1) { acb_set_si(res, mu); } else { dirichlet_group_t G0; dirichlet_char_t chi0; acb_t z; /* primitive char associated to chi */ dirichlet_subgroup_init(G0, G, cond); dirichlet_char_init(chi0, G0); dirichlet_char_lower(chi0, G0, chi, G); acb_init(z); acb_dirichlet_gauss_sum(z, G0, chi0, prec); acb_dirichlet_chi(res, G0, chi0, NN0, prec); acb_mul(res, res, z, prec); acb_mul_si(res, res, mu, prec); dirichlet_group_clear(G0); dirichlet_char_clear(chi0); acb_clear(z); } } void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { ulong cond = dirichlet_conductor_char(G, chi); /* TODO: no need, factor also does it... */ if (cond != G->q) { gauss_sum_non_primitive(res, G, chi, cond, prec); } else if (dirichlet_char_is_real(G, chi)) { acb_dirichlet_gauss_sum_order2(res, G, chi, prec); } else if (G->num > 1 && G->num > G->neven) { acb_dirichlet_gauss_sum_factor(res, G, chi, prec); } else { /* must be non primitive */ if (acb_dirichlet_theta_length_d(G->q, 1, prec) > G->q) acb_dirichlet_gauss_sum_naive(res, G, chi, prec); else acb_dirichlet_gauss_sum_theta(res, G, chi, prec); } } void acb_dirichlet_gauss_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, slong prec) { dirichlet_char_t chi; dirichlet_char_init(chi, G); dirichlet_char_log(chi, G, a); acb_dirichlet_gauss_sum(res, G, chi, prec); dirichlet_char_clear(chi); } flint-3.1.3/src/acb_dirichlet/gauss_sum_factor.c000066400000000000000000000032501461254215100217060ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { slong k; acb_t tmp; /* early check */ for (k = (G->neven == 2); k < G->num; k++) { /* if e > 1 and not primitive, 0 */ if (chi->log[k] % G->P[k].p == 0 && G->P[k].e > 1) { acb_zero(res); return; } } /* factor */ acb_one(res); acb_init(tmp); for (k = (G->neven == 2); k < G->num; k++) { ulong pe = G->P[k].pe.n; dirichlet_group_t Gp; dirichlet_char_t chip; dirichlet_subgroup_init(Gp, G, pe); dirichlet_char_init(chip, Gp); chip->n = chi->n % pe; if (k == 1 && G->neven == 2) { chip->log[0] = chi->log[0]; chip->log[1] = chi->log[1]; } else chip->log[0] = chi->log[k]; /* chi_pe(a, q/pe) * G_pe(a) */ acb_dirichlet_gauss_sum(tmp, Gp, chip, prec); acb_mul(res, res, tmp, prec); acb_dirichlet_chi(tmp, Gp, chip, (G->q / pe) % pe, prec); acb_mul(res, res, tmp, prec); dirichlet_char_clear(chip); dirichlet_group_clear(Gp); } if (G->q_even == 2) acb_neg(res, res); acb_clear(tmp); } flint-3.1.3/src/acb_dirichlet/gauss_sum_naive.c000066400000000000000000000014411461254215100215320ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { acb_t z; acb_ptr v; v = _acb_vec_init(G->q); acb_dirichlet_chi_vec(v, G, chi, G->q, prec); acb_init(z); acb_unit_root(z, G->q, prec); _acb_poly_evaluate(res, v, G->q, z, prec); acb_clear(z); _acb_vec_clear(v, G->q); } flint-3.1.3/src/acb_dirichlet/gauss_sum_order2.c000066400000000000000000000014021461254215100216220ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { if (dirichlet_parity_char(G, chi)) { arb_zero(acb_realref(res)); arb_sqrt_ui(acb_imagref(res), G->q, prec); } else { arb_zero(acb_imagref(res)); arb_sqrt_ui(acb_realref(res), G->q, prec); } } flint-3.1.3/src/acb_dirichlet/gauss_sum_theta.c000066400000000000000000000022451461254215100215400ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { ulong cond = dirichlet_conductor_char(G, chi); if (cond < G->q || (G->q == 300 && (chi->n == 71 || chi->n == 131)) || (G->q == 600 && (chi->n == 11 || chi->n == 491))) { flint_throw(FLINT_ERROR, "(gauss_sum_theta): non available for non primitive character" "or exceptional characters chi_300(71,.), chi_300(131,.), " "chi_600(11,.) and chi_600(491,.)\n"); } else { acb_t iq; acb_init(iq); acb_dirichlet_gauss_sum_order2(iq, G, chi, prec); acb_dirichlet_root_number_theta(res, G, chi, prec); acb_mul(res, res, iq, prec); acb_clear(iq); } } flint-3.1.3/src/acb_dirichlet/gram_point.c000066400000000000000000000110121461254215100204740ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* Claim: the error is bounded by 1/64 if n <= 1 and (1/64) (log(n)/n) if n >= 2. A crude lower bound for g_n is 2 pi exp(W(n)), or 8*n/log(n) for n >= 8. We want to solve pi n = -t/2 log(2 pi/t) - t/2 - pi/8 + epsilon for t (= g_n). Using (47) in Brent [https://arxiv.org/abs/1609.03682], |epsilon| <= 1/(8 t) for for t >= 2. Also, for x >= 3, |f'(x)| < 0.5 where f(x) = exp(W(x)). Assume n >= 9, so that (n+1/8)/e >= 3.35. Then inverting gives t = 2 pi exp[W( [pi n - epsilon + pi/8] / (pi e) ) + 1] = 2 pi e exp[W((n+1/8)/e - epsilon / (pi e))] = 2 pi e exp[W((n+1/8)/e)] + epsilon2, |epsilon2| <= 1/(8 t) <= (1/64) (log(n)/n) One can check 0 <= n <= 8 separately. */ static void gram_point_initial(arb_t x, const fmpz_t n, slong prec) { arb_t pi, e; mag_t b; arb_init(pi); arb_init(e); mag_init(b); arb_const_pi(pi, prec); arb_const_e(e, prec); /* x = 2*pi*exp(1 + W((n+1/8)/e)) */ arb_one(x); arb_mul_2exp_si(x, x, -3); arb_add_fmpz(x, x, n, prec); arb_div(x, x, e, prec); arb_lambertw(x, x, 0, prec); arb_add_ui(x, x, 1, prec); arb_exp(x, x, prec); arb_mul(x, x, pi, prec); arb_mul_2exp_si(x, x, 1); if (fmpz_cmp_ui(n, 1) <= 0) { mag_set_ui_2exp_si(b, 1, -6); } else { mag_set_fmpz(b, n); mag_log(b, b); mag_div_fmpz(b, b, n); mag_mul_2exp_si(b, b, -6); } arb_add_error_mag(x, b); arb_clear(pi); arb_clear(e); mag_clear(b); } void acb_dirichlet_gram_point(arb_t res, const fmpz_t n, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { slong asymp_accuracy; /* Only implemented for n >= -1 and Riemann zeta. */ if (fmpz_cmp_si(n, -1) < 0 || G != NULL || chi != NULL) { arb_indeterminate(res); return; } asymp_accuracy = 2 * fmpz_bits(n); asymp_accuracy = FLINT_MIN(asymp_accuracy, prec); gram_point_initial(res, n, asymp_accuracy + 20); asymp_accuracy = arb_rel_accuracy_bits(res); if (asymp_accuracy < prec) { acb_struct tmp[2]; arb_t f, fprime, root; mag_t C, r; slong * steps; slong wp, step; acb_init(tmp); acb_init(tmp + 1); arb_init(f); arb_init(fprime); arb_init(root); mag_init(C); mag_init(r); steps = flint_malloc(sizeof(slong) * FLINT_BITS); step = 0; steps[step] = prec * 1.05 + 10; while (steps[step] / 2 > asymp_accuracy) { steps[step + 1] = steps[step] / 2; step++; } arb_set(root, res); /* theta''(x) <= C = 1/x, x >= 1 */ arb_get_mag_lower(C, root); if (mag_cmp_2exp_si(C, 0) >= 0) mag_inv(C, C); else mag_inf(C); arb_set(root, res); for ( ; step >= 0; step--) { wp = steps[step] + 10; wp = FLINT_MAX(wp, arb_rel_accuracy_bits(root) + 10); /* store radius, set root to the midpoint */ mag_set(r, arb_radref(root)); mag_zero(arb_radref(root)); acb_set_arb(tmp, root); acb_dirichlet_hardy_theta(tmp, tmp, NULL, NULL, 2, wp); arb_set(f, acb_realref(tmp)); arb_const_pi(acb_imagref(tmp), wp); arb_submul_fmpz(f, acb_imagref(tmp), n, wp); arb_set(fprime, acb_realref(tmp + 1)); /* f'([m+/-r]) = f'(m) +/- f''([m +/- r]) * r */ mag_mul(r, C, r); arb_add_error_mag(fprime, r); arb_div(f, f, fprime, wp); arb_sub(root, root, f, wp); /* Verify inclusion so that C is still valid. */ if (!arb_contains(res, root)) { flint_printf("unexpected: no containment computing Gram point\n"); arb_set(root, res); break; } } arb_set(res, root); acb_clear(tmp); acb_clear(tmp + 1); arb_clear(f); arb_clear(fprime); arb_clear(root); mag_clear(C); mag_clear(r); flint_free(steps); } arb_set_round(res, res, prec); } flint-3.1.3/src/acb_dirichlet/hardy_theta.c000066400000000000000000000057061461254215100206460ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_hardy_theta(acb_ptr res, const acb_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) { acb_struct y[2]; arb_t c; slong k; int parity; ulong q; if (len <= 0) return; if (t == res) { acb_init(y); acb_set(y, t); acb_dirichlet_hardy_theta(res, y, G, chi, len, prec); acb_clear(y); return; } if (G == NULL) { parity = 0; q = 1; } else { parity = dirichlet_parity_char(G, chi); q = G->q; if (q != dirichlet_conductor_char(G, chi)) { flint_throw(FLINT_ERROR, "hardy theta: need primitive character\n"); } } if (!acb_is_finite(t)) { _acb_vec_indeterminate(res, len); return; } acb_init(y + 0); acb_init(y + 1); arb_init(c); /* res = log gamma((s+parity)/2), s = 0.5+i(t+x) */ acb_mul_onei(y, t); arb_set_d(c, 0.5 + parity); arb_add(acb_realref(y), acb_realref(y), c, prec); acb_mul_2exp_si(y, y, -1); acb_onei(y + 1); acb_mul_2exp_si(y + 1, y + 1, -1); _acb_poly_lgamma_series(res, y, FLINT_MIN(len, 2), len, prec); if (acb_is_real(t)) { for (k = 0; k < len; k++) { arb_set(acb_realref(res + k), acb_imagref(res + k)); arb_zero(acb_imagref(res + k)); } } else { acb_ptr v = _acb_vec_init(len); /* v = log gamma(((1-s)+parity)/2), s = 0.5+i(t+x) */ acb_div_onei(y, t); arb_set_d(c, 0.5 + parity); arb_add(acb_realref(y), acb_realref(y), c, prec); acb_mul_2exp_si(y, y, -1); acb_neg(y + 1, y + 1); _acb_poly_lgamma_series(v, y, FLINT_MIN(len, 2), len, prec); _acb_vec_sub(res, res, v, len, prec); for (k = 0; k < len; k++) { acb_div_onei(res + k, res + k); acb_mul_2exp_si(res + k, res + k, -1); } _acb_vec_clear(v, len); } /* (t+x) [-(1/2) log(pi/q)] */ arb_const_pi(c, prec); arb_div_ui(c, c, q, prec); arb_log(c, c, prec); arb_mul_2exp_si(c, c, -1); acb_submul_arb(res, t, c, prec); if (len > 1) acb_sub_arb(res + 1, res + 1, c, prec); /* i log(eps) / 2 */ if (q > 1) { acb_dirichlet_root_number(y, G, chi, prec); acb_arg(c, y, prec); arb_mul_2exp_si(c, c, -1); arb_sub(acb_realref(res), acb_realref(res), c, prec); } acb_clear(y + 0); acb_clear(y + 1); arb_clear(c); } flint-3.1.3/src/acb_dirichlet/hardy_theta_series.c000066400000000000000000000034761461254215100222220ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" void _acb_dirichlet_hardy_theta_series(acb_ptr res, acb_srcptr s, slong slen, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) { slen = FLINT_MIN(slen, len); if (len == 0) return; if (slen == 1) { acb_dirichlet_hardy_theta(res, s, G, chi, 1, prec); _acb_vec_zero(res + 1, len - 1); } else { acb_ptr t, u; t = _acb_vec_init(len); u = _acb_vec_init(slen); acb_dirichlet_hardy_theta(t, s, G, chi, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, s + 1, slen - 1); _acb_poly_compose_series(res, t, len, u, slen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, slen); } } void acb_dirichlet_hardy_theta_series(acb_poly_t res, const acb_poly_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) { if (len == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, len); if (s->length == 0) { acb_t t; acb_init(t); _acb_dirichlet_hardy_theta_series(res->coeffs, t, 1, G, chi, len, prec); acb_clear(t); } else { _acb_dirichlet_hardy_theta_series(res->coeffs, s->coeffs, s->length, G, chi, len, prec); } _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_dirichlet/hardy_z.c000066400000000000000000000036331461254215100200070ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_hardy_z(acb_ptr res, const acb_t t, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) { acb_ptr v, w; slong k; int is_real; if (len <= 0) return; /* use reflection formula -- todo for other characters */ if ((G == NULL || G->q == 1) && arf_sgn(arb_midref(acb_imagref(t))) > 0) { acb_neg(res, t); acb_dirichlet_hardy_z(res, res, G, chi, len, prec); for (k = 1; k < len; k += 2) acb_neg(res + k, res + k); return; } v = _acb_vec_init(len); w = _acb_vec_init(len); is_real = acb_is_real(t); /* v = exp(i theta(t+x)) */ acb_dirichlet_hardy_theta(v, t, G, chi, len, prec); _acb_vec_scalar_mul_onei(v, v, len); _acb_poly_exp_series(v, v, len, len, prec); /* w = L(1/2 + i (t+x)) */ acb_one(w); acb_mul_2exp_si(w, w, -1); arb_sub(acb_realref(w), acb_realref(w), acb_imagref(t), prec); arb_set(acb_imagref(w), acb_realref(t)); acb_dirichlet_l_jet(w, w, G, chi, 0, len, prec); for (k = 0; k < len; k++) { if (k % 4 == 1) acb_mul_onei(w + k, w + k); else if (k % 4 == 2) acb_neg(w + k, w + k); else if (k % 4 == 3) acb_div_onei(w + k, w + k); } _acb_poly_mullow(res, v, len, w, len, len, prec); if (is_real) for (k = 0; k < len; k++) arb_zero(acb_imagref(res + k)); _acb_vec_clear(v, len); _acb_vec_clear(w, len); } flint-3.1.3/src/acb_dirichlet/hardy_z_series.c000066400000000000000000000034461461254215100213630ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" void _acb_dirichlet_hardy_z_series(acb_ptr res, acb_srcptr s, slong slen, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) { slen = FLINT_MIN(slen, len); if (len == 0) return; if (slen == 1) { acb_dirichlet_hardy_z(res, s, G, chi, 1, prec); _acb_vec_zero(res + 1, len - 1); } else { acb_ptr t, u; t = _acb_vec_init(len); u = _acb_vec_init(slen); acb_dirichlet_hardy_z(t, s, G, chi, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, s + 1, slen - 1); _acb_poly_compose_series(res, t, len, u, slen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, slen); } } void acb_dirichlet_hardy_z_series(acb_poly_t res, const acb_poly_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, slong prec) { if (len == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, len); if (s->length == 0) { acb_t t; acb_init(t); _acb_dirichlet_hardy_z_series(res->coeffs, t, 1, G, chi, len, prec); acb_clear(t); } else { _acb_dirichlet_hardy_z_series(res->coeffs, s->coeffs, s->length, G, chi, len, prec); } _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_dirichlet/hardy_z_zero.c000066400000000000000000000134621461254215100210470ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "arb_calc.h" static void _acb_set_arf(acb_t res, const arf_t t) { acb_zero(res); arb_set_arf(acb_realref(res), t); } int _acb_dirichlet_definite_hardy_z(arb_t res, const arf_t t, slong *pprec) { int msign; acb_t z; acb_init(z); while (1) { _acb_set_arf(z, t); acb_dirichlet_hardy_z(z, z, NULL, NULL, 1, *pprec); msign = arb_sgn_nonzero(acb_realref(z)); if (msign) { break; } *pprec *= 2; } acb_get_real(res, z); acb_clear(z); return msign; } void _refine_hardy_z_zero_illinois(arb_t res, const arf_t ra, const arf_t rb, slong prec) { arf_t a, b, fa, fb, c, fc, t; arb_t z; slong k, nmag, abs_tol, wp; int asign, bsign, csign; arf_init(a); arf_init(b); arf_init(c); arf_init(fa); arf_init(fb); arf_init(fc); arf_init(t); arb_init(z); arf_set(a, ra); arf_set(b, rb); nmag = arf_abs_bound_lt_2exp_si(b); abs_tol = nmag - prec - 4; wp = prec + nmag + 8; asign = _acb_dirichlet_definite_hardy_z(z, a, &wp); arf_set(fa, arb_midref(z)); bsign = _acb_dirichlet_definite_hardy_z(z, b, &wp); arf_set(fb, arb_midref(z)); if (asign == bsign) { flint_throw(FLINT_ERROR, "isolate a zero before bisecting the interval\n"); } for (k = 0; k < 40; k++) { /* c = a - fa * (b - a) / (fb - fa) */ arf_sub(c, b, a, wp, ARF_RND_NEAR); arf_sub(t, fb, fa, wp, ARF_RND_NEAR); arf_div(c, c, t, wp, ARF_RND_NEAR); arf_mul(c, c, fa, wp, ARF_RND_NEAR); arf_sub(c, a, c, wp, ARF_RND_NEAR); /* if c is not sandwiched between a and b, improve precision and fall back to one bisection step */ if (!arf_is_finite(c) || !((arf_cmp(a, c) < 0 && arf_cmp(c, b) < 0) || (arf_cmp(b, c) < 0 && arf_cmp(c, a) < 0))) { /* flint_printf("no sandwich (k = %wd)\n", k); */ wp += 32; arf_add(c, a, b, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_2exp_si(c, c, -1); } csign = _acb_dirichlet_definite_hardy_z(z, c, &wp); arf_set(fc, arb_midref(z)); if (csign != bsign) { arf_set(a, b); arf_set(fa, fb); asign = bsign; arf_set(b, c); arf_set(fb, fc); bsign = csign; } else { arf_set(b, c); arf_set(fb, fc); bsign = csign; arf_mul_2exp_si(fa, fa, -1); } arf_sub(t, a, b, wp, ARF_RND_DOWN); arf_abs(t, t); if (arf_cmpabs_2exp_si(t, abs_tol) < 0) break; } /* a and b may have changed places */ if (arf_cmp(a, b) > 0) arf_swap(a, b); arb_set_interval_arf(res, a, b, prec); arf_clear(a); arf_clear(b); arf_clear(c); arf_clear(fa); arf_clear(fb); arf_clear(fc); arf_clear(t); arb_clear(z); } void _refine_hardy_z_zero_newton(arb_t res, const arf_t ra, const arf_t rb, slong prec) { acb_t z, zstart; acb_ptr v; mag_t der1, der2, err; slong nbits, initial_prec, extraprec, wp, step; slong * steps; acb_init(z); acb_init(zstart); v = _acb_vec_init(2); mag_init(der1); mag_init(der2); mag_init(err); nbits = arf_abs_bound_lt_2exp_si(rb); extraprec = nbits + 10; initial_prec = 3 * nbits + 30; _refine_hardy_z_zero_illinois(acb_imagref(zstart), ra, rb, initial_prec); arb_set_d(acb_realref(zstart), 0.5); /* Real part is exactly 1/2, but need an epsilon-enclosure (for bounds) since we work with the complex function. */ mag_set_ui_2exp_si(arb_radref(acb_realref(zstart)), 1, nbits - initial_prec - 4); /* Bound |zeta''(zstart)| for Newton error bound. */ acb_dirichlet_zeta_deriv_bound(der1, der2, zstart); steps = flint_malloc(sizeof(slong) * FLINT_BITS); step = 0; steps[step] = prec; while (steps[step] / 2 + extraprec > initial_prec) { steps[step + 1] = steps[step] / 2 + extraprec; step++; } acb_set(z, zstart); for ( ; step >= 0; step--) { wp = steps[step] + extraprec; mag_set(err, arb_radref(acb_imagref(z))); acb_get_mid(z, z); acb_dirichlet_zeta_jet(v, z, 0, 2, wp); mag_mul(err, err, der2); acb_add_error_mag(v + 1, err); acb_div(v, v, v + 1, wp); acb_sub(v, z, v, wp); if (acb_contains(zstart, v)) { acb_set(z, v); arb_set_d(acb_realref(z), 0.5); } else { /* can this happen? should we fallback to illinois? */ flint_throw(FLINT_ERROR, "no inclusion for interval newton!\n"); } } arb_set(res, acb_imagref(z)); flint_free(steps); acb_clear(z); acb_clear(zstart); _acb_vec_clear(v, 2); mag_clear(der1); mag_clear(der2); mag_clear(err); } void _acb_dirichlet_refine_hardy_z_zero(arb_t res, const arf_t a, const arf_t b, slong prec) { slong bits; arb_set_interval_arf(res, a, b, prec + 8); bits = arb_rel_accuracy_bits(res); if (bits < prec) { if (prec < 4 * arf_abs_bound_lt_2exp_si(b) + 40) _refine_hardy_z_zero_illinois(res, a, b, prec); else _refine_hardy_z_zero_newton(res, a, b, prec); } arb_set_round(res, res, prec); } flint-3.1.3/src/acb_dirichlet/hurwitz.c000066400000000000000000000027271461254215100200660ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" void acb_dirichlet_hurwitz(acb_t res, const acb_t s, const acb_t a, slong prec) { if (acb_is_one(a)) { acb_dirichlet_zeta(res, s, prec); return; } if (acb_is_zero(s)) { acb_mul_2exp_si(res, a, 1); acb_sub_ui(res, res, 1, prec); acb_neg(res, res); acb_mul_2exp_si(res, res, -1); return; } if (acb_is_zero(a) && acb_is_int(s) && arf_sgn(arb_midref(acb_realref(s))) < 0) { acb_dirichlet_zeta(res, s, prec); return; } if (acb_is_int(s) && arf_sgn(arb_midref(acb_realref(s))) < 0 && arf_cmpabs_ui(arb_midref(acb_realref(s)), prec / 2) < 0) { slong n = arf_get_si(arb_midref(acb_realref(s)), ARF_RND_FLOOR); acb_bernoulli_poly_ui(res, 1 - n, a, prec); acb_div_si(res, res, n - 1, prec); return; } if (arb_contains_zero(acb_imagref(s)) && arb_contains_si(acb_realref(s), 1)) { acb_indeterminate(res); return; } _acb_poly_zeta_cpx_series(res, s, a, 0, 1, prec); } flint-3.1.3/src/acb_dirichlet/hurwitz_precomp_bound.c000066400000000000000000000041711461254215100227750ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_hurwitz_precomp_bound(mag_t res, const acb_t s, slong A, slong K, slong N) { acb_t s1; mag_t x, t, TK, C; slong sigmaK; arf_t u; if (A < 1 || K < 1 || N < 1) { mag_inf(res); return; } /* sigmaK = re(s) + K, floor bound */ arf_init(u); arf_set_mag(u, arb_radref(acb_realref(s))); arf_sub(u, arb_midref(acb_realref(s)), u, MAG_BITS, ARF_RND_FLOOR); arf_add_ui(u, u, K, MAG_BITS, ARF_RND_FLOOR); if (arf_cmp_ui(u, 2) < 0 || arf_cmp_2exp_si(u, FLINT_BITS - 2) > 0) { mag_inf(res); arf_clear(u); return; } sigmaK = arf_get_si(u, ARF_RND_FLOOR); arf_clear(u); acb_init(s1); mag_init(x); mag_init(t); mag_init(TK); mag_init(C); /* With N grid points, we will have |x| <= 1 / (2N). */ mag_one(x); mag_div_ui(x, x, 2 * N); /* T(K) = |x|^K |(s)_K| / K! * [1/A^(sigma+K) + ...] */ mag_pow_ui(TK, x, K); acb_rising_ui_get_mag(t, s, K); mag_mul(TK, TK, t); mag_rfac_ui(t, K); mag_mul(TK, TK, t); /* Note: here we assume that mag_hurwitz_zeta_uiui uses an error bound that is at least as large as the one used in the proof. */ mag_hurwitz_zeta_uiui(t, sigmaK, A); mag_mul(TK, TK, t); /* C = |x|/A (1 + 1/(K+sigma+A-1)) (1 + |s-1|/(K+1)) */ mag_div_ui(C, x, A); mag_one(t); mag_div_ui(t, t, sigmaK + A - 1); mag_add_ui(t, t, 1); mag_mul(C, C, t); acb_sub_ui(s1, s, 1, MAG_BITS); acb_get_mag(t, s1); mag_div_ui(t, t, K + 1); mag_add_ui(t, t, 1); mag_mul(C, C, t); mag_geom_series(t, C, 0); mag_mul(res, TK, t); acb_clear(s1); mag_clear(x); mag_clear(t); mag_clear(TK); mag_clear(C); } flint-3.1.3/src/acb_dirichlet/hurwitz_precomp_choose_param.c000066400000000000000000000062701461254215100243300ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define log __builtin_log # define sqrt __builtin_sqrt #else # include #endif void acb_dirichlet_hurwitz_precomp_choose_param(ulong * _A, ulong *_K, ulong *_N, const acb_t s, double num_eval, slong prec) { double MUL_COST, POW_COST, ZETA_COST, height, abss, cost, best_cost; ulong A, K, N, best_A, best_K, best_N; mag_t err; /* Default algorithm: separate evaluations with no precomputation. */ best_A = best_K = best_N = 0; *_A = *_K = *_N = 0; /* This is pointless. */ if (num_eval < 10) return; /* Precomputation fails at nonpositive integers. */ if (acb_contains_int(s) && !arb_is_positive(acb_realref(s))) return; prec = FLINT_MAX(prec, 8); height = arf_get_d(arb_midref(acb_imagref(s)), ARF_RND_DOWN); height = fabs(height); abss = arf_get_d(arb_midref(acb_realref(s)), ARF_RND_DOWN); abss = sqrt(abss*abss + height*height); /* Relative evaluation time, estimated empirically. */ MUL_COST = 1.0; POW_COST = 10.0 + FLINT_MIN(0.005 * prec, 200.0); ZETA_COST = 200.0 + 2.0*height + (3.0*prec + 0.0002*height*prec)*prec; /* Cost for the default algorithm. */ best_cost = num_eval * ZETA_COST; /* Give the default algorithm some more leeway. */ best_cost *= 0.5; if (acb_is_int(s)) best_cost *= 0.5; mag_init(err); for (N = 1; N <= FLINT_MIN(num_eval, 2048); N = FLINT_MAX(N+1, N*1.2)) { /* AN should be at least as large as |s| */ A = FLINT_MAX(abss / N + 1.0, 1); /* Estimate K based on asymptotics for the error term. We will have to adjust up by actually computing the error bound. */ K = FLINT_MAX(prec * log(2) / (log(2*A*N) + 1.0) + 1.0, 1); for ( ; K < num_eval; K = FLINT_MAX(K+1, K*1.2)) { /* Too much space. */ if (_acb_vec_estimate_allocated_bytes(N * K, prec) > 1e9) break; acb_dirichlet_hurwitz_precomp_bound(err, s, A, K, N); cost = (K * num_eval) * MUL_COST + /* polynomial evaluation */ (A * num_eval) * POW_COST + /* power sum */ (N * K) * ZETA_COST; /* precomputation cost */ /* The accuracy is good enough. */ if (mag_cmp_2exp_si(err, -prec) <= 0) { if (cost < best_cost) { best_cost = cost; best_A = A; best_K = K; best_N = N; } break; } /* It will only get worse from here. */ if (cost > best_cost) break; } } *_A = best_A; *_K = best_K; *_N = best_N; mag_clear(err); } flint-3.1.3/src/acb_dirichlet/hurwitz_precomp_clear.c000066400000000000000000000011731461254215100227530ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_hurwitz_precomp_clear(acb_dirichlet_hurwitz_precomp_t pre) { acb_clear(&pre->s); if (pre->A != 0) { mag_clear(&pre->err); _acb_vec_clear(pre->coeffs, pre->N * pre->K); } } flint-3.1.3/src/acb_dirichlet/hurwitz_precomp_eval.c000066400000000000000000000035371461254215100226220ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_hurwitz_precomp_eval(acb_t res, const acb_dirichlet_hurwitz_precomp_t pre, ulong p, ulong q, slong prec) { slong i; acb_t a, t; if (p > q) { flint_throw(FLINT_ERROR, "hurwitz_precomp_eval: require p <= n\n"); } if (pre->A == 0) { acb_init(a); acb_set_ui(a, p); acb_div_ui(a, a, q, prec); if (pre->deflate == 0) acb_hurwitz_zeta(res, &pre->s, a, prec); else _acb_poly_zeta_cpx_series(res, &pre->s, a, 1, 1, prec); acb_clear(a); return; } acb_init(a); acb_init(t); /* todo: avoid integer overflows below */ if (p == q) i = pre->N - 1; else i = (pre->N * p) / q; acb_set_si(a, 2 * pre->N * p - q * (2 * i + 1)); acb_div_ui(a, a, 2 * q * pre->N, prec); /* compute zeta(s,A+p/q) */ _acb_poly_evaluate(res, pre->coeffs + i * pre->K, pre->K, a, prec); /* error bound */ if (acb_is_real(&pre->s)) arb_add_error_mag(acb_realref(res), &pre->err); else acb_add_error_mag(res, &pre->err); /* zeta(s,p/q) = (p/q)^-s + ... + (p/q+A-1)^-s zeta(s,A+p/q) */ for (i = 0; i < pre->A; i++) { acb_set_ui(a, p); acb_div_ui(a, a, q, prec); acb_add_ui(a, a, i, prec); acb_neg(t, &pre->s); acb_pow(a, a, t, prec); acb_add(res, res, a, prec); } acb_clear(a); acb_clear(t); } flint-3.1.3/src/acb_dirichlet/hurwitz_precomp_init.c000066400000000000000000000050721461254215100226320ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_hurwitz_precomp_init(acb_dirichlet_hurwitz_precomp_t pre, const acb_t s, int deflate, slong A, slong K, slong N, slong prec) { slong i, k; pre->deflate = deflate; pre->A = A; pre->K = K; pre->N = N; acb_init(&pre->s); acb_set(&pre->s, s); if (A == 0) return; if (A < 1 || K < 1 || N < 1) { flint_throw(FLINT_ERROR, "hurwitz_precomp_init: require A, K, N >= 1 (unless A == 0)\n"); } pre->coeffs = _acb_vec_init(N * K); mag_init(&pre->err); acb_dirichlet_hurwitz_precomp_bound(&pre->err, s, A, K, N); if (mag_is_finite(&pre->err)) { acb_t t, a; acb_init(t); acb_init(a); /* (-1)^k (s)_k / k! */ acb_one(pre->coeffs + 0); for (k = 1; k < K; k++) { acb_add_ui(pre->coeffs + k, s, k - 1, prec); acb_mul(pre->coeffs + k, pre->coeffs + k, pre->coeffs + k - 1, prec); acb_div_ui(pre->coeffs + k, pre->coeffs + k, k, prec); acb_neg(pre->coeffs + k, pre->coeffs + k); } for (i = 1; i < N; i++) _acb_vec_set(pre->coeffs + i * K, pre->coeffs, K); /* zeta(s+k,a) where a = A + (2*i+1)/(2*N) */ for (i = 0; i < N; i++) { acb_set_ui(a, 2 * i + 1); acb_div_ui(a, a, 2 * N, prec); acb_add_ui(a, a, A, prec); for (k = 0; k < K; k++) { acb_add_ui(t, s, k, prec); if (deflate && k == 0) _acb_poly_zeta_cpx_series(t, t, a, 1, 1, prec); else acb_hurwitz_zeta(t, t, a, prec); acb_mul(pre->coeffs + i * K + k, pre->coeffs + i * K + k, t, prec); } } acb_clear(t); acb_clear(a); } } void acb_dirichlet_hurwitz_precomp_init_num(acb_dirichlet_hurwitz_precomp_t pre, const acb_t s, int deflate, double num_eval, slong prec) { ulong A, K, N; acb_dirichlet_hurwitz_precomp_choose_param(&A, &K, &N, s, num_eval, prec); acb_dirichlet_hurwitz_precomp_init(pre, s, deflate, A, K, N, prec); } flint-3.1.3/src/acb_dirichlet/isolate_hardy_z_zero.c000066400000000000000000001116641461254215100225720ustar00rootroot00000000000000/* Copyright (C) 2010 Juan Arias de Reyna Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "acb_dirichlet.h" #include "arb_calc.h" /* * For a detailed explanation of the algorithm implemented in this file, see: * * J. Arias de Reyna, "Programs for Riemann's zeta function", (J. A. J. van * Vonderen, Ed.) Leven met getallen : liber amicorum ter gelegenheid van de * pensionering van Herman te Riele, CWI (2012) 102-112, * https://ir.cwi.nl/pub/19724 */ /* * These constants define the largest n such that for every k <= n * the kth zero of the Hardy Z function is governed by Gram's law * or by Rosser's rule respectively. */ static const slong GRAMS_LAW_MAX = 126; static const slong ROSSERS_RULE_MAX = 13999526; /* * This structure describes a node of a doubly linked list. * Each node represents a height t at which the Hardy Z-function * Z(t) has been evaluated. * * As it relates to this data structure, the big picture of the algorithm * to isolate the nth zero is roughly: * * 1) Initialize a two-node list consisting of the two points * predicted by Gram's law to surround the nth zero. * 2) Append and prepend as many additional Gram points as are indicated * by the theory behind Turing's method, and occasionally insert points * between existing points for the purpose of certifying blocks of intervals * as 'good'. * 3) Repeatedly insert new points into the list, interleaving existing points, * until the number of sign changes indicated by theory is observed. * This is where the algorithm would enter an infinite loop if it encountered * a counterexample to the Riemann hypothesis. * 4) Traverse the list until we find the pair of adjacent nodes with opposite * signs of Z(t) that corresponds to the nth zero; the t heights of the * two nodes define the endpoints of an isolating interval. * 5) Delete the list. */ typedef struct _zz_node_struct { arf_struct t; /* height t where v = Z(t) is evaluated */ arb_struct v; /* Z(t) */ fmpz *gram; /* Gram point index or NULL if not a Gram point */ slong prec; /* precision of evaluation of v */ struct _zz_node_struct *prev; struct _zz_node_struct *next; } zz_node_struct; typedef zz_node_struct zz_node_t[1]; typedef zz_node_struct * zz_node_ptr; typedef const zz_node_struct * zz_node_srcptr; static int zz_node_is_gram_node(const zz_node_t p) { return p->gram != NULL; } static int zz_node_sgn(const zz_node_t p) { int s = arb_sgn_nonzero(&p->v); if (!s) { flint_throw(FLINT_ERROR, "unexpectedly imprecise evaluation of Z(t)\n"); } return s; } /* Good Gram points are Gram points where sgn(Z(g(n)))*(-1)^n > 0. */ static int zz_node_is_good_gram_node(const zz_node_t p) { if (zz_node_is_gram_node(p)) { int s = zz_node_sgn(p); if ((s > 0 && fmpz_is_even(p->gram)) || (s < 0 && fmpz_is_odd(p->gram))) { return 1; } } return 0; } static void zz_node_init(zz_node_t p) { arf_init(&p->t); arb_init(&p->v); arb_indeterminate(&p->v); p->prec = 0; p->gram = NULL; p->prev = NULL; p->next = NULL; } static void zz_node_clear(zz_node_t p) { arf_clear(&p->t); arb_clear(&p->v); if (p->gram) { fmpz_clear(p->gram); flint_free(p->gram); } p->prec = 0; p->gram = NULL; p->prev = NULL; p->next = NULL; } /* * The node p represents the evaluation of the Hardy Z-function * at a point t with some precision. This function re-evaluates * the Hardy Z-function at t with greater precision, and it also * guarantees that the precision is high enough to determine the * sign of Z(t). */ static int zz_node_refine(zz_node_t p) { slong default_prec = arf_bits(&p->t) + 8; if (p->prec < default_prec) { p->prec = default_prec; } else { p->prec *= 2; } return _acb_dirichlet_definite_hardy_z(&p->v, &p->t, &p->prec); } /* * Create a node representing an evaluation of the Hardy Z-function * at arbitrary point t. Upon creation the sign of Z(t) will * be known with certainty. */ static zz_node_ptr create_non_gram_node(const arf_t t) { zz_node_ptr p = flint_malloc(sizeof(zz_node_struct)); zz_node_init(p); arf_set(&p->t, t); zz_node_refine(p); return p; } /* * Create a node representing an evaluation of the Hardy Z-function * at the nth Gram point g(n). Upon creation a floating point number t will be * assigned to this node, with the property that there are no zeros of the * Hardy Z-function between t and the actual value of g(n). * The sign of Z(t) will also be known with certainty. */ static zz_node_ptr create_gram_node(const fmpz_t n) { zz_node_ptr p; arb_t t, v; acb_t z; slong prec = fmpz_bits(n) + 8; arb_init(t); arb_init(v); acb_init(z); while (1) { /* Computing the Gram point to higher precision improves performance significantly. The likely explanation (not verified) is that when evaluating the Z-function at an inexact ball using the Riemann-Siegel formula, error propagation uses a bound for Z' that is far from tight. The extra precision compensates for this lack of tightness. */ acb_dirichlet_gram_point(t, n, NULL, NULL, prec + fmpz_bits(n)); acb_set_arb(z, t); acb_dirichlet_hardy_z(z, z, NULL, NULL, 1, prec); acb_get_real(v, z); if (!arb_contains_zero(v)) { break; } prec *= 2; } p = flint_malloc(sizeof(zz_node_struct)); zz_node_init(p); p->gram = flint_malloc(sizeof(fmpz)); fmpz_init(p->gram); /* t contains g(n) and does not contain a zero of the Z function */ fmpz_set(p->gram, n); arf_set(&p->t, arb_midref(t)); arb_set(&p->v, v); p->prec = prec; arb_clear(t); arb_clear(v); acb_clear(z); return p; } /* * Count the number of Gram intervals between the Gram point * represented by node a and the Gram point represented by node b. * Traversing the linked list is not necessary because the Gram indices * of nodes a and b can be accessed directly. */ static slong count_gram_intervals(zz_node_srcptr a, zz_node_srcptr b) { slong out = 0; if (!a || !b) { flint_throw(FLINT_ERROR, "a and b must be non-NULL\n"); } if (!zz_node_is_good_gram_node(a) || !zz_node_is_good_gram_node(b)) { flint_throw(FLINT_ERROR, "both nodes must be good Gram points\n"); } else { fmpz_t m; fmpz_init(m); fmpz_sub(m, b->gram, a->gram); out = fmpz_get_si(m); fmpz_clear(m); } return out; } /* * Count the observed number of sign changes of Z(t) by traversing * a linked list of evaluated points from node a to node b. */ static slong count_sign_changes(zz_node_srcptr a, zz_node_srcptr b) { zz_node_srcptr p, q; slong n = 0; if (!a || !b) { flint_throw(FLINT_ERROR, "a and b must be non-NULL\n"); } p = a; q = a->next; while (p != b) { if (!q) { flint_throw(FLINT_ERROR, "prematurely reached end of list\n"); } if (zz_node_sgn(p) != zz_node_sgn(q)) { n++; } p = q; q = q->next; } return n; } /* * Modify a linked list that ends with node p, * by appending nodes representing Gram points. * Continue until a 'good' Gram point is found. */ static zz_node_ptr extend_to_next_good_gram_node(zz_node_t p) { fmpz_t n; zz_node_ptr q, r; fmpz_init(n); if (!zz_node_is_gram_node(p)) { flint_throw(FLINT_ERROR, "expected to begin at a gram point\n"); } if (p->next) { flint_throw(FLINT_ERROR, "expected to extend from the end of a list\n"); } fmpz_set(n, p->gram); q = p; while (1) { fmpz_add_ui(n, n, 1); r = create_gram_node(n); q->next = r; r->prev = q; q = r; r = NULL; if (zz_node_is_good_gram_node(q)) { break; } } fmpz_clear(n); return q; } /* * Modify a linked list that begins with node p, * by prepending nodes representing Gram points. * Continue until a 'good' Gram point is found. */ static zz_node_ptr extend_to_prev_good_gram_node(zz_node_t p) { fmpz_t n; zz_node_ptr q, r; fmpz_init(n); if (!zz_node_is_gram_node(p)) { flint_throw(FLINT_ERROR, "expected to begin at a gram point\n"); } if (p->prev) { flint_throw(FLINT_ERROR, "expected to extend from the start of a list\n"); } fmpz_set(n, p->gram); q = p; while (1) { fmpz_sub_ui(n, n, 1); r = create_gram_node(n); q->prev = r; r->next = q; q = r; r = NULL; if (zz_node_is_good_gram_node(q)) { break; } } fmpz_clear(n); return q; } /* * TODO: This is probably redundant. * Can arb_get_lbound_arf ever give a negative arf given a nonnegative arb? * If the answer is no, and it's probably no, then this function * can be deleted. */ static void _arb_get_lbound_arf_nonnegative(arf_t res, const arb_t x, slong prec) { arb_get_lbound_arf(res, x, prec); if (arf_cmp_si(res, 0) < 0) { arf_zero(res); } } /* * res = (x1*w1 + x2*w2) / (w1 + w2) * Undefined if weights are not nonnegative. * If w1 and w2 are zero, the resulting interval contains x1 and x2. */ static void _weighted_arithmetic_mean(arb_t res, const arf_t x1, const arf_t x2, const arb_t w1, const arb_t w2, slong prec) { if (!arb_is_nonnegative(w1) || !arb_is_nonnegative(w2)) { arb_indeterminate(res); } else if (arb_is_zero(w1) && arb_is_zero(w2)) { arb_set_interval_arf(res, x1, x2, prec); } else if (arb_is_zero(w1)) { arb_set_arf(res, x2); } else if (arb_is_zero(w2)) { arb_set_arf(res, x1); } else if (arb_is_exact(w1) && arb_is_exact(w2)) { arb_t a, b; arb_init(a); arb_init(b); arb_mul_arf(a, w1, x1, prec); arb_addmul_arf(a, w2, x2, prec); arb_add(b, w1, w2, prec); arb_div(res, a, b, prec); arb_clear(a); arb_clear(b); } else { arb_t a, b, r1, r2; arb_init(a); arb_init(b); arb_init(r1); arb_init(r2); arb_zero(a); arb_zero(b); _arb_get_lbound_arf_nonnegative(arb_midref(a), w1, prec); arb_get_ubound_arf(arb_midref(b), w2, prec); _weighted_arithmetic_mean(r1, x1, x2, a, b, prec); arb_zero(a); arb_zero(b); arb_get_ubound_arf(arb_midref(a), w1, prec); _arb_get_lbound_arf_nonnegative(arb_midref(b), w2, prec); _weighted_arithmetic_mean(r2, x1, x2, a, b, prec); arb_union(res, r1, r2, prec); arb_clear(a); arb_clear(b); arb_clear(r1); arb_clear(r2); } } /* * Split the interval (t1, t2) into the intervals (t1, out) and (out, t2) * in an attempt to increase the number of observed sign changes of Z(t) * between endpoints. * v1 and v2 are the Hardy Z-function values at t1 and t2 respectively. * sign1 and sign2 are the signs of v1 and v2 respectively. */ static void split_interval(arb_t out, const arf_t t1, const arb_t v1, slong sign1, const arf_t t2, const arb_t v2, slong sign2, slong prec) { if (sign1 == sign2) { /* * out = (sqrt(v2/v1)*t1 + t2) / (sqrt(v2/v1) + 1) * We have f(t1)=v1, f(t2)=v2 where v1 and v2 have the same sign, * and we want to guess t between t1 and t2 so that f(t) * has the opposite sign. Try the vertex of a parabola that would touch * f(t)=0 between t1 and t2 and would pass through (t1,v1) and (t2,v2). */ arb_t w1, w2; arb_init(w1); arb_init(w2); arb_abs(w1, v2); /* w1, v2 is deliberate */ arb_sqrt(w1, w1, prec); arb_abs(w2, v1); /* w2, v1 is deliberate */ arb_sqrt(w2, w2, prec); _weighted_arithmetic_mean(out, t1, t2, w1, w2, prec); arb_clear(w1); arb_clear(w2); } else { /* * out = (t1 + t2) / 2 * There is already one sign change in this interval. * To find additional sign changes we would need to evaluate * at least two more points in the interval, * so begin by just splitting the interval in half at the midpoint. */ arb_set_arf(out, t1); arb_add_arf(out, out, t2, prec); arb_mul_2exp_si(out, out, -1); } } /* * Add a new node between each pair of existing nodes in the linked list * of evaluated values of t, within the sublist demarcated by nodes a and b. */ static void intercalate(zz_node_t a, zz_node_t b) { arb_t t; zz_node_ptr q, r, mid_node; if (a == NULL || b == NULL) { flint_throw(FLINT_ERROR, "a and b must be non-NULL\n"); } if (!zz_node_is_good_gram_node(a) || !zz_node_is_good_gram_node(b)) { flint_throw(FLINT_ERROR, "a and b must represent good Gram points\n"); } if (a == b) return; arb_init(t); q = a; r = a->next; while (q != b) { if (!r) { flint_throw(FLINT_ERROR, "prematurely reached end of list\n"); } while (1) { split_interval(t, &q->t, &q->v, zz_node_sgn(q), &r->t, &r->v, zz_node_sgn(r), FLINT_MIN(q->prec, r->prec)); if (!arb_contains_arf(t, &q->t) && !arb_contains_arf(t, &r->t)) { break; } zz_node_refine((q->prec < r->prec) ? q : r); } mid_node = create_non_gram_node(arb_midref(t)); q->next = mid_node; mid_node->prev = q; mid_node->next = r; r->prev = mid_node; q = r; r = r->next; } arb_clear(t); } /* * Virtually trim k Gram/Rosser blocks from the head and from the tail * of the sublist (a, b). The resulting sublist is (*A, *B). * No nodes or connections between nodes are modified, added, or deleted. */ static void trim(zz_node_ptr *A, zz_node_ptr *B, zz_node_ptr a, zz_node_ptr b, slong k) { slong n; for (n = 0; n < k; n++) { a = a->next; while (!zz_node_is_good_gram_node(a)) { a = a->next; } b = b->prev; while (!zz_node_is_good_gram_node(b)) { b = b->prev; } } *A = a; *B = b; } /* * Given a linked sublist beginning at U and ending at V defining function * evaluations at points that fully separate zeros of Z(t) in the vicinity * of the nth zero, traverse the list until the nth zero is found. * Continue traversing the list until len consecutive isolating intervals * have been found, or until the end of the sublist is reached. * Return the number of isolated zeros found, starting at the nth zero. */ static slong count_up_separated_zeros(arf_interval_ptr res, zz_node_srcptr U, zz_node_srcptr V, const fmpz_t n, slong len) { if (len <= 0) { return 0; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "nonpositive indices of zeros are not supported\n"); } else if (U == NULL || V == NULL) { flint_throw(FLINT_ERROR, "U and V must not be NULL\n"); } if (!zz_node_is_good_gram_node(U) || !zz_node_is_good_gram_node(V)) { flint_throw(FLINT_ERROR, "U and V must be good Gram points\n"); } else { slong i = 0; zz_node_srcptr p = U; fmpz_t N, k; fmpz_init(N); fmpz_init(k); fmpz_add_ui(N, p->gram, 1); fmpz_set(k, n); while (p != V) { if (!p->next) { flint_throw(FLINT_ERROR, "prematurely reached end of list\n"); } if (zz_node_sgn(p) != zz_node_sgn(p->next)) { fmpz_add_ui(N, N, 1); if (fmpz_equal(N, k)) { arf_set(&res[i].a, &p->t); arf_set(&res[i].b, &p->next->t); fmpz_add_ui(k, k, 1); i++; if (i == len) break; } } p = p->next; } fmpz_clear(k); return i; } return 0; } /* * Find one 'superblock' below n and one 'superblock' above n. * The term 'superblock' in this context means a stretch of * enough consecutive 'good' Rosser/Gram blocks to meet the Turing method bound. * The output *psb is the number of blocks in the superblock. * The output nodes *pu and *pv are the first node of the first superblock * and the last node of the second superblock respectively. */ static void turing_search_near(zz_node_ptr *pu, zz_node_ptr *pv, slong *psb, const fmpz_t n) { zz_node_ptr u, v; slong i; slong zn; /* target number of sign changes */ slong sb; /* the number of padding blocks required by Turing's method */ slong cgb; /* the number of consecutive good blocks */ const slong loopcount = 4; fmpz_t k; fmpz_init(k); fmpz_sub_ui(k, n, 2); u = create_gram_node(k); fmpz_sub_ui(k, n, 1); v = create_gram_node(k); u->next = v; v->prev = u; if (!zz_node_is_good_gram_node(u)) u = extend_to_prev_good_gram_node(u); if (!zz_node_is_good_gram_node(v)) v = extend_to_next_good_gram_node(v); /* * Extend the search to greater heights t. * * Continue adding Gram points until the number of consecutive * 'good' Gram/Rosser blocks reaches the Turing method bound. */ sb = 0; cgb = 0; while (1) { zz_node_ptr nv; nv = extend_to_next_good_gram_node(v); zn = count_gram_intervals(v, nv); for (i = 0; i < loopcount && count_sign_changes(v, nv) < zn; i++) { intercalate(v, nv); } if (count_sign_changes(v, nv) >= zn) { cgb++; if (cgb > sb) { sb = cgb; if (acb_dirichlet_turing_method_bound(nv->gram) <= sb) { v = nv; break; } } } else { cgb = 0; } v = nv; } /* Extend the search to smaller heights t. */ cgb = 0; while (1) { zz_node_ptr pu; pu = extend_to_prev_good_gram_node(u); zn = count_gram_intervals(pu, u); for (i = 0; i < loopcount && count_sign_changes(pu, u) < zn; i++) { intercalate(pu, u); } if (count_sign_changes(pu, u) >= zn) { cgb++; if (cgb == sb) { u = pu; break; } } else { cgb = 0; } u = pu; } *pu = u; *pv = v; *psb = sb; fmpz_clear(k); } /* * Find one 'double superblock' beginning below the point represented * by node u, and find one 'double superblock' ending above the point * represented by node v. The term 'double superblock' in this context * means a stretch of twice as many consecutive 'good' Rosser/Gram blocks * as would meet the Turing method bound. * The output nodes *pu and *pv are the first node of the first double * superblock and the last node of the second double superblock respectively. * The output integer *psb reports one half of the number * of blocks in the double superblock. * The parameter initial_cgb is the number of consecutive good blocks * above and below the points represented by nodes u and v respectively. */ static void turing_search_far(zz_node_ptr *pu, zz_node_ptr *pv, slong *psb, zz_node_ptr u, zz_node_ptr v, slong initial_cgb) { slong i; slong zn; /* target number of sign changes */ slong sb; /* the number of padding blocks required by Turing's method */ slong cgb; /* the number of consecutive good blocks */ const slong loopcount = 4; /* * Extend the search to greater heights t. * * Continue adding Gram points until the number of consecutive * 'good' Gram/Rosser blocks is twice the number required by * the Turing method bound. */ sb = 0; cgb = initial_cgb; while (1) { zz_node_ptr nv; nv = extend_to_next_good_gram_node(v); zn = count_gram_intervals(v, nv); for (i = 0; i < loopcount && count_sign_changes(v, nv) < zn; i++) { intercalate(v, nv); } if (count_sign_changes(v, nv) >= zn) { cgb++; if (cgb % 2 == 0 && sb < cgb / 2) { sb = cgb / 2; if (acb_dirichlet_turing_method_bound(nv->gram) <= sb) { v = nv; break; } } } else { cgb = 0; } v = nv; } /* Extend the search to smaller heights t. */ cgb = initial_cgb; while (1) { zz_node_ptr pu; pu = extend_to_prev_good_gram_node(u); zn = count_gram_intervals(pu, u); for (i = 0; i < loopcount && count_sign_changes(pu, u) < zn; i++) { intercalate(pu, u); } if (count_sign_changes(pu, u) >= zn) { cgb++; if (cgb == sb*2) { u = pu; break; } } else { cgb = 0; } u = pu; } *pu = u; *pv = v; *psb = sb; } /* * Used for both zero isolation and for N(t). * n is the index of a Hardy Z-function zero of interest. * *pu and *pv are the first and last node of an output list. * *pU and *pV are the first and last nodes of a sublist with * fully separated zeros, within the *pu -- *pv list. */ static void _separated_turing_list(zz_node_ptr *pU, zz_node_ptr *pV, zz_node_ptr *pu, zz_node_ptr *pv, const fmpz_t n) { zz_node_ptr U, V, u, v; slong i; slong sb_near; /* Turing method bound for near search */ slong sb_far; /* Turing method bound for far search */ slong zn; /* target number of sign changes */ slong variations; /* observed number of sign changes */ const slong loopcount = 4; /* * The loopcount controls how hard we try to find zeros in Gram/Rosser * blocks. If the loopcount is too high then when Rosser's rule is violated * we will spend too much time searching for zeros that don't exist. * If the loopcount is too low then we will miss some 'good' blocks, * causing the search to be extended unnecessarily far from the initial * guess before eventually making another pass in which loopcount * is effectively infinite. */ if (fmpz_cmp_si(n, 2) < 0) { flint_throw(FLINT_ERROR, "invalid n: %s\n", fmpz_get_str(NULL, 10, n)); } turing_search_near(&u, &v, &sb_near, n); trim(&U, &V, u, v, sb_near); zn = count_gram_intervals(U, V); for (i = 0; i < loopcount && count_sign_changes(U, V) < zn; i++) { intercalate(U, V); } variations = count_sign_changes(U, V); if (variations > zn) { flint_throw(FLINT_ERROR, "unexpected number of sign changes\n"); } else if (variations < zn) { zz_node_ptr r = U; zz_node_ptr s = V; turing_search_far(&u, &v, &sb_far, u, v, sb_near); trim(&U, &V, u, v, 2*sb_far); zn = count_gram_intervals(U, V); for (i = 0; i < loopcount && count_sign_changes(U, V) < zn; i++) { intercalate(U, r); intercalate(s, V); } variations = count_sign_changes(U, V); if (variations > zn) { flint_throw(FLINT_ERROR, "unexpected number of sign changes\n"); } else if (variations < zn) { trim(&U, &V, u, v, sb_far); zn = count_gram_intervals(U, V); while (count_sign_changes(U, V) < zn) { intercalate(U, V); } if (count_sign_changes(U, V) != zn) { flint_throw(FLINT_ERROR, "unexpected number of sign changes\n"); } } } *pu = u; *pv = v; *pU = U; *pV = V; } /* * Used for both zero isolation and for N(t). * n is the index of a Hardy Z-function zero of interest. * *pu and *pv are the first and last node of an output list * with fully separated zeros. */ static void _separated_rosser_list(zz_node_ptr *pu, zz_node_ptr *pv, const fmpz_t n) { fmpz_t k; zz_node_ptr u, v; if (fmpz_cmp_si(n, 1) < 0 || fmpz_cmp_si(n, ROSSERS_RULE_MAX) > 0) { flint_throw(FLINT_ERROR, "invalid n: %s\n", fmpz_get_str(NULL, 10, n)); } fmpz_init(k); fmpz_sub_ui(k, n, 2); u = create_gram_node(k); fmpz_sub_ui(k, n, 1); v = create_gram_node(k); u->next = v; v->prev = u; if (!zz_node_is_good_gram_node(u)) u = extend_to_prev_good_gram_node(u); if (!zz_node_is_good_gram_node(v)) v = extend_to_next_good_gram_node(v); while (count_sign_changes(u, v) != count_gram_intervals(u, v)) { intercalate(u, v); } *pu = u; *pv = v; fmpz_clear(k); } /* * Used for both zero isolation and for N(t). * n is the index of a Hardy Z-function zero of interest. * *pu and *pv are the first and last node of an output list * with fully separated zeros. */ static void _separated_gram_list(zz_node_ptr *pu, zz_node_ptr *pv, const fmpz_t n) { fmpz_t k; zz_node_ptr u, v; if (fmpz_cmp_si(n, 1) < 0 || fmpz_cmp_si(n, GRAMS_LAW_MAX) > 0) { flint_throw(FLINT_ERROR, "invalid n: %s\n", fmpz_get_str(NULL, 10, n)); } fmpz_init(k); fmpz_sub_ui(k, n, 2); u = create_gram_node(k); fmpz_sub_ui(k, n, 1); v = create_gram_node(k); u->next = v; v->prev = u; *pu = u; *pv = v; fmpz_clear(k); } /* * Get a list of points that fully separate zeros of Z. * Used for both zero isolation and for N(t). * n is the index of a Hardy Z-function zero of interest. * *pu and *pv are the first and last node of an output list. * *pU and *pV are the first and last nodes of a sublist with * fully separated zeros, within the *pu -- *pv list. */ static void _separated_list(zz_node_ptr *pU, zz_node_ptr *pV, zz_node_ptr *pu, zz_node_ptr *pv, const fmpz_t n) { zz_node_ptr U, V, u, v; if (fmpz_cmp_si(n, GRAMS_LAW_MAX) <= 0) { _separated_gram_list(&u, &v, n); U = u; V = v; } else if (fmpz_cmp_si(n, ROSSERS_RULE_MAX) <= 0) { _separated_rosser_list(&u, &v, n); U = u; V = v; } else { _separated_turing_list(&U, &V, &u, &v, n); } if (U == NULL || V == NULL) { flint_throw(FLINT_ERROR, "U and V must not be NULL\n"); } if (!zz_node_is_good_gram_node(U) || !zz_node_is_good_gram_node(V)) { flint_throw(FLINT_ERROR, "U and V must be good Gram points\n"); } if (U == V) { flint_throw(FLINT_ERROR, "the list must include at least one interval\n"); } *pU = U; *pV = V; *pu = u; *pv = v; } /* * Isolate up to len zeros, starting from the nth zero. * Return the number of isolated zeros. */ static slong _isolate_hardy_z_zeros(arf_interval_ptr res, const fmpz_t n, slong len) { zz_node_ptr U, V, u, v; slong count; _separated_list(&U, &V, &u, &v, n); count = count_up_separated_zeros(res, U, V, n, len); while (u) { v = u; u = u->next; zz_node_clear(v); flint_free(v); } return count; } /* Isolate len zeros, starting from the nth zero. */ void acb_dirichlet_isolate_hardy_z_zeros(arf_interval_ptr res, const fmpz_t n, slong len) { if (len <= 0) { return; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "nonpositive indices of zeros are not supported\n"); } else { slong c = 0; fmpz_t k; fmpz_init(k); while (c < len) { fmpz_add_si(k, n, c); c += _isolate_hardy_z_zeros(res + c, k, len - c); } fmpz_clear(k); } } void acb_dirichlet_isolate_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) { if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "nonpositive indices of zeros are not supported\n"); } else { arf_interval_t r; arf_interval_init(r); _isolate_hardy_z_zeros(r, n, 1); arf_set(a, &r->a); arf_set(b, &r->b); arf_interval_clear(r); } } static void count_up(arf_t a, arf_t b, zz_node_srcptr U, zz_node_srcptr V, const fmpz_t n) { arf_interval_t r; arf_interval_init(r); count_up_separated_zeros(r, U, V, n, 1); arf_set(a, &r->a); arf_set(b, &r->b); arf_interval_clear(r); } void _acb_dirichlet_isolate_turing_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) { zz_node_ptr U, V, u, v; _separated_turing_list(&U, &V, &u, &v, n); count_up(a, b, U, V, n); while (u) { v = u; u = u->next; zz_node_clear(v); flint_free(v); } } void _acb_dirichlet_isolate_rosser_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) { zz_node_ptr u, v; _separated_rosser_list(&u, &v, n); count_up(a, b, u, v, n); while (u) { v = u; u = u->next; zz_node_clear(v); flint_free(v); } } void _acb_dirichlet_isolate_gram_hardy_z_zero(arf_t a, arf_t b, const fmpz_t n) { zz_node_ptr u, v; _separated_gram_list(&u, &v, n); count_up(a, b, u, v, n); while (u) { v = u; u = u->next; zz_node_clear(v); flint_free(v); } } static void _acb_set_arf(acb_t res, const arf_t t) { acb_zero(res); arb_set_arf(acb_realref(res), t); } /* * Find the index of the largest Gram point less than t. * Requires t > 10. */ static void gram_index(fmpz_t res, const arf_t t) { if (arf_cmp_si(t, 10) < 0) { flint_throw(FLINT_ERROR, "gram_index requires t > 10\n"); } else { acb_t z; slong prec = arf_abs_bound_lt_2exp_si(t) + 8; acb_init(z); while (1) { _acb_set_arf(z, t); acb_dirichlet_hardy_theta(z, z, NULL, NULL, 1, prec); arb_const_pi(acb_imagref(z), prec); arb_div(acb_realref(z), acb_realref(z), acb_imagref(z), prec); arb_floor(acb_realref(z), acb_realref(z), prec); if (arb_get_unique_fmpz(res, acb_realref(z))) { break; } prec *= 2; } acb_clear(z); } } /* * Compute nzeros(t) for up to len values of t * and return the number computed. p must be in increasing order, * and all entries must be greater than 10. */ static slong _exact_zeta_multi_nzeros(fmpz *res, arf_srcptr points, slong len) { zz_node_ptr U, V, u, v, p; arb_t x; fmpz_t n, N; slong i; arf_srcptr t; int s; slong prec; arb_init(x); fmpz_init(n); fmpz_init(N); /* * The first point is located between two Gram points. Find the unique n * such that the nth zero is also predicted to be located between these * Gram points. */ gram_index(n, points); fmpz_add_ui(n, n, 2); /* Get a list of points that fully separate zeros of Z. */ _separated_list(&U, &V, &u, &v, n); p = U; fmpz_add_ui(N, U->gram, 1); /* * It's possible that one or more points are located between * the first Gram point and the arf_t representative of that Gram point. */ for (i = 0, t = points; i < len && arf_cmp(t, &p->t) <= 0; i++, t++) { fmpz_set(res + i, N); } while (i < len && p != V) { if (!p->next) { flint_throw(FLINT_ERROR, "prematurely reached the end of the list\n"); } if (zz_node_sgn(p) != zz_node_sgn(p->next)) { while (i < len && arf_cmp(t, &p->next->t) <= 0) { prec = arf_abs_bound_lt_2exp_si(t) + 8; s = _acb_dirichlet_definite_hardy_z(x, t, &prec); if (zz_node_sgn(p->next) == s) { fmpz_add_ui(res + i, N, 1); } else { fmpz_set(res + i, N); } t++; i++; } fmpz_add_ui(N, N, 1); } p = p->next; } /* * It's possible that the first point in the array is located between * the last Gram point and the arf_t representative of that Gram point. */ if (i == 0) { fmpz_set(res, N); i++; } while (u) { v = u; u = u->next; zz_node_clear(v); flint_free(v); } arb_clear(x); fmpz_clear(n); fmpz_clear(N); return i; } /* * Compute nzeros for len values of t. The array p must be in increasing order. */ static void exact_zeta_multi_nzeros(fmpz *res, arf_srcptr p, slong len) { slong i, c; arf_srcptr q; if (len <= 0) { return; } for (i = 0, q = p; i < len - 1; i++, q++) { if (arf_cmp(q, p) > 0) { flint_throw(FLINT_ERROR, "p must be in increasing order\n"); } } c = 0; while (c < len) { if (arf_cmp_si(p + c, 14) < 0) { fmpz_zero(res + c); c++; } else { c += _exact_zeta_multi_nzeros(res + c, p + c, len - c); } } } void _acb_dirichlet_exact_zeta_nzeros(fmpz_t res, const arf_t t) { exact_zeta_multi_nzeros(res, t, 1); } typedef struct { arb_ptr res; arf_interval_ptr p; slong prec; } work_t; static void refinement_worker(slong i, work_t * work) { _acb_dirichlet_refine_hardy_z_zero(work->res + i, &(work->p[i].a), &(work->p[i].b), work->prec); } void acb_dirichlet_hardy_z_zeros(arb_ptr res, const fmpz_t n, slong len, slong prec) { if (len <= 0) { return; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "nonpositive indices of zeros are not supported\n"); } else { work_t work; arf_interval_ptr p = _arf_interval_vec_init(len); acb_dirichlet_isolate_hardy_z_zeros(p, n, len); work.res = res; work.p = p; work.prec = prec; flint_parallel_do((do_func_t) refinement_worker, &work, len, -1, FLINT_PARALLEL_STRIDED); _arf_interval_vec_clear(p, len); } } static void _arb_set_interval_fmpz(arb_t res, const fmpz_t a, const fmpz_t b) { fmpz_t n; fmpz_init(n); fmpz_add(n, a, b); arf_set_fmpz(arb_midref(res), n); fmpz_sub(n, b, a); mag_set_fmpz(arb_radref(res), n); arb_mul_2exp_si(res, res, -1); fmpz_clear(n); } void acb_dirichlet_zeta_nzeros(arb_t res, const arb_t t, slong prec) { if (arb_is_exact(t)) { fmpz_t n; fmpz_init(n); _acb_dirichlet_exact_zeta_nzeros(n, arb_midref(t)); arb_set_fmpz(res, n); fmpz_clear(n); } else { arf_struct b[2]; fmpz n[2]; arf_init(b); arf_init(b + 1); fmpz_init(n); fmpz_init(n + 1); arb_get_lbound_arf(b, t, prec); arb_get_ubound_arf(b + 1, t, prec); exact_zeta_multi_nzeros(n, b, 2); _arb_set_interval_fmpz(res, n, n + 1); arf_clear(b); arf_clear(b + 1); fmpz_clear(n); fmpz_clear(n + 1); } arb_set_round(res, res, prec); } void acb_dirichlet_zeta_nzeros_gram(fmpz_t res, const fmpz_t n) { zz_node_ptr U, V, u, v, p; fmpz_t k, N; if (fmpz_cmp_si(n, -1) < 0) { flint_throw(FLINT_ERROR, "n must be >= -1\n"); } fmpz_init(k); fmpz_init(N); /* * Get a list of points that fully separate zeros of Z. * The kth zero is expected to be between the k-2 and the k-1 gram points. */ fmpz_add_ui(k, n, 2); _separated_list(&U, &V, &u, &v, k); p = U; fmpz_add_ui(N, U->gram, 1); fmpz_set_si(res, -1); while (1) { if (p == NULL) { flint_throw(FLINT_ERROR, "prematurely reached the end of the list\n"); } if (zz_node_is_gram_node(p) && fmpz_equal(n, p->gram)) { fmpz_set(res, N); break; } if (zz_node_sgn(p) != zz_node_sgn(p->next)) { fmpz_add_ui(N, N, 1); } if (p == V) { break; } p = p->next; } if (fmpz_sgn(res) < 0) { flint_throw(FLINT_ERROR, "failed to find the gram point\n"); } while (u) { v = u; u = u->next; zz_node_clear(v); flint_free(v); } fmpz_clear(k); fmpz_clear(N); } flint-3.1.3/src/acb_dirichlet/jacobi_sum.c000066400000000000000000000056401461254215100204620ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* J_N(1,a) = sum on x = 1 mod some p | q */ ulong jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond) { if (e > 1 && cond % (p*p) == 0) { return 0; } else { slong r = (e > 1) ? pe / p : 1; if (cond % p) return r * (p - 2); else return -r; } } static ulong jacobi_one(const dirichlet_group_t G, ulong cond) { slong k, r = 1; for (k = 0; k < G->num; k++) r *= jacobi_one_prime(G->P[k].p, G->P[k].e, G->P[k].pe.n, cond); return r; } void acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { if (G->q_even > 1) { acb_zero(res); } else if (chi1->n == 1 || chi2->n == 1) { ulong cond = (chi1->n == 1) ? dirichlet_conductor_char(G, chi2) : dirichlet_conductor_char(G, chi1); acb_set_si(res, jacobi_one(G, cond)); } else if (nmod_mul(chi1->n, chi2->n, G->mod) == 1) { ulong n; n = jacobi_one(G, dirichlet_conductor_char(G, chi1)); if (dirichlet_parity_char(G, chi1)) acb_set_si(res, -n); else acb_set_si(res, n); } else { if (G->q <= 150) acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); else if (G->num > 1) acb_dirichlet_jacobi_sum_factor(res, G, chi1, chi2, prec); else if (G->P[0].e > 1) acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); else acb_dirichlet_jacobi_sum_gauss(res, G, chi1, chi2, prec); } } void acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec) { if (G->q_even > 1) { acb_zero(res); } else if (a == 1 || b == 1) { ulong cond = (a == 1) ? dirichlet_conductor_ui(G, b) : dirichlet_conductor_ui(G, a); acb_set_si(res, jacobi_one(G, cond)); } else if (nmod_mul(a, b, G->mod) == 1) { ulong n; n = jacobi_one(G, dirichlet_conductor_ui(G, a)); if (dirichlet_parity_ui(G, a)) acb_set_si(res, -n); else acb_set_si(res, n); } else { dirichlet_char_t chi1, chi2; dirichlet_char_init(chi1, G); dirichlet_char_init(chi2, G); dirichlet_char_log(chi1, G, a); dirichlet_char_log(chi2, G, b); acb_dirichlet_jacobi_sum(res, G, chi1, chi2, prec); dirichlet_char_clear(chi1); dirichlet_char_clear(chi2); } } flint-3.1.3/src/acb_dirichlet/jacobi_sum_factor.c000066400000000000000000000041651461254215100220210ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { slong k; acb_t tmp; acb_init(tmp); acb_one(res); /* TODO: efficient subgroup */ for (k = 0; k < G->num; k++) { nmod_t pe; ulong p, e, ap, bp; p = G->P[k].p; e = G->P[k].e; pe = G->P[k].pe; ap = chi1->n % pe.n; bp = chi2->n % pe.n; if (ap == 1 || bp == 1 || nmod_mul(ap, bp, pe) == 1) { slong r; ulong cond; cond = (ap == 1) ? dirichlet_conductor_char(G, chi2) : dirichlet_conductor_char(G, chi1); r = jacobi_one_prime(p, e, pe.n, cond); /* chi(a,-1) if ap * bp = 1 */ if (ap != 1 && bp != 1) r *= n_jacobi_unsigned(ap, p); acb_mul_si(res, res, r, prec); } else { dirichlet_group_t Gp; dirichlet_char_t chi1p, chi2p; dirichlet_group_init(Gp, pe.n); dirichlet_char_init(chi1p, Gp); dirichlet_char_init(chi2p, Gp); chi1p->n = ap; chi1p->log[0] = chi1->log[k]; chi2p->n = ap; chi2p->log[0] = chi2->log[k]; /* TODO: work out gauss relations for e > 1 */ if (p <= 100 || e > 1) acb_dirichlet_jacobi_sum_naive(tmp, Gp, chi1p, chi2p, prec); else acb_dirichlet_jacobi_sum_gauss(tmp, Gp, chi1p, chi2p, prec); acb_mul(res, res, tmp, prec); dirichlet_char_clear(chi1p); dirichlet_char_clear(chi2p); dirichlet_group_clear(Gp); } } acb_clear(tmp); } flint-3.1.3/src/acb_dirichlet/jacobi_sum_gauss.c000066400000000000000000000021451461254215100216610ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* should use only for prime power modulus */ void acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ acb_t tmp; dirichlet_char_t chi12; dirichlet_char_init(chi12, G); dirichlet_char_mul(chi12, G, chi1, chi2); acb_init(tmp); acb_dirichlet_gauss_sum(res, G, chi1, prec); if (chi2->n == chi1->n) acb_set(tmp, res); else acb_dirichlet_gauss_sum(tmp, G, chi2, prec); acb_mul(res, res, tmp, prec); acb_dirichlet_gauss_sum(tmp, G, chi12, prec); acb_div(res, res, tmp, prec); dirichlet_char_clear(chi12); acb_clear(tmp); } flint-3.1.3/src/acb_dirichlet/jacobi_sum_naive.c000066400000000000000000000031001461254215100216310ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { ulong k1, k2, m1, m2, g, e, m; ulong * v1, * v2; slong *v; nmod_t expo; acb_t z; v1 = flint_malloc(G->q * sizeof(ulong)); v2 = flint_malloc(G->q * sizeof(ulong)); dirichlet_vec_set_null(v1, G, G->q); dirichlet_chi_vec_loop(v1, G, chi1, G->q); dirichlet_vec_set_null(v2, G, G->q); dirichlet_chi_vec_loop(v2, G, chi2, G->q); nmod_init(&expo, G->expo); m1 = dirichlet_order_char(G, chi1); m2 = dirichlet_order_char(G, chi2); g = m1 * m2 / n_gcd(m1, m2); m = G->expo / g; v = flint_malloc(g * sizeof(slong)); for (e = 0; e < g; e++) v[e] = 0; for (k1 = 2, k2 = G->q - 1; k2 > 1; k1++, k2--) { if (v1[k1] == DIRICHLET_CHI_NULL || v2[k2] == DIRICHLET_CHI_NULL) continue; e = nmod_add(v1[k1], v2[k2], expo) / m; v[e]++; } acb_init(z); acb_unit_root(z, g, prec); acb_dirichlet_si_poly_evaluate(res, v, g, z, prec); acb_clear(z); flint_free(v); flint_free(v2); flint_free(v1); } flint-3.1.3/src/acb_dirichlet/l.c000066400000000000000000000063531461254215100166040ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif void acb_dirichlet_l_general(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { /* this cutoff is probably too conservative when q is large */ if (arf_cmp_d(arb_midref(acb_realref(s)), 8 + 0.5 * prec / log(prec)) >= 0) { acb_dirichlet_l_euler_product(res, s, G, chi, prec); } else { slong wp = prec + n_clog(G->phi_q, 2); acb_dirichlet_hurwitz_precomp_t pre; acb_dirichlet_hurwitz_precomp_init_num(pre, s, acb_is_one(s), G->phi_q, wp); acb_dirichlet_l_hurwitz(res, s, pre, G, chi, prec); acb_dirichlet_hurwitz_precomp_clear(pre); } } void acb_dirichlet_l(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { if (!acb_is_finite(s)) { acb_indeterminate(res); } else if (G == NULL || G->q == 1) { acb_dirichlet_zeta(res, s, prec); } else if (dirichlet_char_is_primitive(G, chi) && (arf_cmp_d(arb_midref(acb_realref(s)), -0.5) < 0 || (G->q != 1 && dirichlet_parity_char(G, chi) == 0 && arf_cmpabs_d(arb_midref(acb_imagref(s)), 0.125) < 0 && arf_cmp_d(arb_midref(acb_realref(s)), 0.125) < 0))) { /* use functional equation */ acb_t t, u, v; int parity; ulong q; parity = dirichlet_parity_char(G, chi); q = G->q; acb_init(t); acb_init(u); acb_init(v); /* gamma((1-s+p)/2) / gamma((s+p)/2) */ acb_add_ui(t, s, parity, prec); acb_mul_2exp_si(t, t, -1); acb_rgamma(t, t, prec); if (!acb_is_zero(t)) /* assumes q != 1 when s = 0 */ { acb_neg(u, s); acb_add_ui(u, u, 1 + parity, prec); acb_mul_2exp_si(u, u, -1); acb_gamma(u, u, prec); acb_mul(t, t, u, prec); /* epsilon */ acb_dirichlet_root_number(u, G, chi, prec); acb_mul(t, t, u, prec); /* (pi/q)^(s-1/2) */ acb_const_pi(u, prec); acb_div_ui(u, u, q, prec); acb_set_d(v, -0.5); acb_add(v, v, s, prec); acb_pow(u, u, v, prec); acb_mul(t, t, u, prec); acb_sub_ui(u, s, 1, prec); acb_neg(u, u); acb_conj(u, u); acb_dirichlet_l_general(u, u, G, chi, prec); acb_conj(u, u); acb_mul(t, t, u, prec); if (dirichlet_char_is_real(G, chi) && acb_is_real(s)) arb_zero(acb_imagref(t)); } acb_set(res, t); acb_clear(t); acb_clear(u); acb_clear(v); } else { acb_dirichlet_l_general(res, s, G, chi, prec); } } flint-3.1.3/src/acb_dirichlet/l_euler_product.c000066400000000000000000000101631461254215100215320ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow # define sqrt __builtin_sqrt #else # include #endif #define ONE_OVER_LOG2 1.4426950408889634 void acb_dirichlet_l_euler_product(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { arf_t left; slong wp, powprec, left_s, acc; ulong val, p, p_limit; double p_needed_approx, powmag, logp, errmag; int is_real, is_int; acb_t t, u, v, c, negs; acb_dirichlet_roots_t roots; mag_t err; if (!acb_is_finite(s)) { acb_indeterminate(res); return; } arf_init(left); arf_set_mag(left, arb_radref(acb_realref(s))); arf_sub(left, arb_midref(acb_realref(s)), left, 2 * MAG_BITS, ARF_RND_FLOOR); /* Require re(s) >= 2. */ if (arf_cmp_si(left, 2) < 0) { acb_indeterminate(res); arf_clear(left); return; } is_real = acb_is_real(s) && dirichlet_char_is_real(G, chi); /* L(s) ~= 1. */ if (arf_cmp_si(left, prec) > 0) { acb_one(res); mag_hurwitz_zeta_uiui(arb_radref(acb_realref(res)), prec, 2); if (!is_real) mag_set(arb_radref(acb_imagref(res)), arb_radref(acb_realref(res))); acb_inv(res, res, prec); arf_clear(left); return; } left_s = arf_get_si(left, ARF_RND_FLOOR); /* Adjust precision based on possible accuracy. */ acc = acb_rel_accuracy_bits(s); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); acc += left_s; prec = FLINT_MIN(prec, acc + 10); /* Heuristic. */ wp = prec + FLINT_BIT_COUNT(prec) + (prec / left_s) + 4; /* Don't work too hard if a small s was passed as input. */ p_limit = 100 + prec * sqrt(prec); /* Truncating at p ~= 2^(prec/s) gives an error of 2^-prec */ if (((double) prec) / left_s > 50.0) p_needed_approx = pow(2.0, 50.0); else p_needed_approx = pow(2.0, ((double) prec) / left_s); p_needed_approx = FLINT_MIN(p_limit, p_needed_approx); /* todo: use exponent of chi instead of G? */ acb_dirichlet_roots_init(roots, G->expo, p_needed_approx / (1.0 + log(p_needed_approx)), wp); acb_init(t); acb_init(u); acb_init(v); acb_init(c); acb_init(negs); is_int = acb_is_int(s); acb_neg(negs, s); acb_one(v); for (p = 2; p < p_limit; p = n_nextprime(p, 1)) { /* p^s */ logp = log(p); powmag = left_s * logp * ONE_OVER_LOG2; /* zeta(s,p) ~= 1/p^s + 1/((s-1) p^(s-1)) */ errmag = (log(left_s - 1.0) + (left_s - 1.0) * logp) * ONE_OVER_LOG2; errmag = FLINT_MIN(powmag, errmag); if (errmag > prec + 2) break; powprec = FLINT_MAX(wp - powmag, 8); val = dirichlet_chi(G, chi, p); if (val != DIRICHLET_CHI_NULL) { acb_dirichlet_root(c, roots, val, powprec); acb_set_ui(t, p); if (is_int) { acb_pow(t, t, s, powprec); acb_set_round(u, v, powprec); acb_div(t, u, t, powprec); } else { acb_pow(t, t, negs, powprec); acb_set_round(u, v, powprec); acb_mul(t, u, t, powprec); } acb_mul(t, t, c, powprec); acb_sub(v, v, t, wp); } } mag_init(err); mag_hurwitz_zeta_uiui(err, left_s, p); if (is_real) arb_add_error_mag(acb_realref(v), err); else acb_add_error_mag(v, err); mag_clear(err); acb_inv(res, v, prec); acb_dirichlet_roots_clear(roots); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(c); acb_clear(negs); arf_clear(left); } flint-3.1.3/src/acb_dirichlet/l_fmpq.c000066400000000000000000000033401461254215100176200ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb_mat.h" #include "arb_hypgeom.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif int acb_dirichlet_l_fmpq_use_afe(ulong q, const fmpq_t s, slong prec) { double cutoff; if ((slong) fmpz_bits(fmpq_numref(s)) - (slong) fmpz_bits(fmpq_denref(s)) > 20) return 0; if (fabs(fmpq_get_d(s)) > 10 + prec * 0.01) return 0; if (q == 1) { if (fmpz_is_one(fmpq_denref(s))) return 0; if (fmpz_is_one(fmpq_numref(s)) && fmpz_equal_si(fmpq_denref(s), 2)) return prec > 32000; return prec > 70000; } if (fmpq_is_zero(s)) return 0; if (fmpz_cmp_ui(fmpq_denref(s), 2) <= 0) { if (prec > 30000) return 1; if (fmpq_is_one(s)) return q > 1000; return q > 50; } cutoff = 15000.0 / q; return prec > cutoff; } void acb_dirichlet_l_fmpq(acb_t res, const fmpq_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { ulong q; q = (G == NULL) ? 1 : G->q; if (acb_dirichlet_l_fmpq_use_afe(q, s, prec)) { acb_dirichlet_l_fmpq_afe(res, s, G, chi, prec); if (acb_is_finite(res)) return; } acb_set_fmpq(res, s, prec + 10); acb_dirichlet_l(res, res, G, chi, prec); } flint-3.1.3/src/acb_dirichlet/l_fmpq_afe.c000066400000000000000000000410671461254215100204430ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb_mat.h" #include "arb_hypgeom.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif #define VERBOSE 0 static double log_gamma_upper_approx(double a, double z) { if (a < z) return (a - 1) * log(z) - z; else return a * (log(a) - 1); } void acb_dirichlet_root_number2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { acb_dirichlet_root_number(res, G, chi, prec); if (dirichlet_char_is_real(G, chi)) arb_zero(acb_imagref(res)); } static void _arf_trunc(arf_t x) { if (arf_sgn(x) < 0) arf_ceil(x, x); else arf_floor(x, x); } static void arb_extract_bits(arb_t t, const arb_t z, slong b) { arb_mul_2exp_si(t, z, b); _arf_trunc(arb_midref(t)); mag_zero(arb_radref(t)); arb_mul_2exp_si(t, t, -b); } static void acb_dirichlet_afe_tail_bound(mag_t res, const fmpq_t sd2, slong N, ulong q, int parity) { mag_t pi_n2_q, t, u; fmpz_t sprime; mag_init(pi_n2_q); mag_init(t); mag_init(u); fmpz_init(sprime); /* pi_n2_q = pi * N^2 / q (lower bound) */ mag_const_pi_lower(pi_n2_q); mag_mul_ui_lower(pi_n2_q, pi_n2_q, N); mag_mul_ui_lower(pi_n2_q, pi_n2_q, N); mag_set_ui(t, q); mag_div_lower(pi_n2_q, pi_n2_q, t); /* upper bound for sd2 */ fmpz_cdiv_q(sprime, fmpq_numref(sd2), fmpq_denref(sd2)); /* require pi_n2_q > s' */ mag_set_fmpz(t, sprime); if (fmpz_sgn(sprime) > 0 && mag_cmp(pi_n2_q, t) <= 0) { mag_inf(res); } else { mag_expinv(res, pi_n2_q); mag_div_ui(res, res, N); if (!parity) mag_div_ui(res, res, N); /* (1 + q/pi) */ mag_set_ui(t, q); mag_const_pi_lower(u); mag_div(t, t, u); mag_add_ui(t, t, 1); mag_mul(res, res, t); /* max(1, 2^s') */ if (fmpz_sgn(sprime) > 0) mag_mul_2exp_fmpz(res, res, sprime); /* (pi/q)^(s'-1) */ fmpz_sub_ui(sprime, sprime, 1); if (fmpz_sgn(sprime) >= 0) { mag_const_pi(t); mag_set_ui_lower(u, q); mag_div(t, t, u); mag_pow_fmpz(t, t, sprime); } else { mag_const_pi_lower(t); mag_set_ui(u, q); mag_div_lower(t, t, u); fmpz_neg(sprime, sprime); mag_pow_fmpz_lower(t, t, sprime); mag_inv(t, t); } mag_mul(res, res, t); } mag_clear(pi_n2_q); mag_clear(t); mag_clear(u); fmpz_clear(sprime); } void acb_dirichlet_fmpq_sum_afe(acb_t res, const fmpq_t s, const dirichlet_group_t G, const dirichlet_char_t chi, const mag_t abs_tol, slong prec) { slong NN, n, start_bits, bits, wp, wp2, gamma_cached_prec; mag_t AE, err, abs_tol_gamma; arb_t ns, t, u, v, z, z0, z1, x, x2, Ga, Gz1, Gz0, expmz0, z0_prevn, Gz0_prevn, expmz0_prevn; acb_t c; fmpq_t s2; int parity, gamma_singular; ulong q; double abs_tol_mag; double gammainc_mag, gamma_mag, ns_mag; double aa, zz; #if VERBOSE double t1, t2, t3; #endif mag_init(AE); mag_init(err); mag_init(abs_tol_gamma); arb_init(ns); arb_init(t); arb_init(u); arb_init(v); arb_init(z); arb_init(z0); arb_init(z1); arb_init(x); arb_init(x2); arb_init(Ga); arb_init(Gz0); arb_init(Gz1); arb_init(expmz0); arb_init(z0_prevn); arb_init(Gz0_prevn); arb_init(expmz0_prevn); acb_init(c); fmpq_init(s2); if (G == NULL) { parity = 0; q = 1; } else { parity = dirichlet_parity_char(G, chi); q = G->q; } acb_zero(res); /* Initial precision for gamma; may have to be increased later. */ gamma_cached_prec = prec * 1.05 + 30; /* s2 = (s+parity)/2 */ fmpq_add_ui(s2, s, parity); fmpq_div_2exp(s2, s2, 1); gamma_singular = (fmpz_is_one(fmpq_denref(s2)) && fmpz_sgn(fmpq_numref(s2)) <= 0); if (!gamma_singular) arb_gamma_fmpq(Ga, s2, gamma_cached_prec); for (n = 1; ; n += 1) { #if VERBOSE printf("-----------------------------------------------------------\n"); flint_printf("n = %wd (s+parity)/2 = %f z = %f q = %wu\n", n, fmpq_get_d(s2), 3.1415926535897932 * n * n / q, q); #endif acb_dirichlet_afe_tail_bound(err, s2, n, q, parity); #if VERBOSE printf(" abs_tol = "); mag_printd(abs_tol, 5); printf("\n"); printf(" truncation error = "); mag_printd(err, 5); printf("\n"); #endif if (mag_cmp(err, abs_tol) < 0) { if (G == NULL || dirichlet_char_is_real(G, chi)) arb_add_error_mag(acb_realref(res), err); else acb_add_error_mag(res, err); break; } /* Compute local precision and tolerances. */ abs_tol_mag = mag_get_d_log2_approx(abs_tol); aa = fmpq_get_d(s2); zz = 3.1415926535897932385 * n * n / q; /* Gamma((s+parity)/2, z) (want lower bound, to estimate cancellation) */ gammainc_mag = log_gamma_upper_approx(aa, zz) / log(2); /* n^-s */ ns_mag = -fmpq_get_d(s) * log(n) / log(2); /* Want Gamma(a,z) n^-s with abs_tol --> want Gamma(a,z) with abs_tol * n^s */ mag_set_ui_2exp_si(abs_tol_gamma, 1, abs_tol_mag - ns_mag); /* wp = Precision needed sans cancellation. */ wp = gammainc_mag + ns_mag - abs_tol_mag + 5; wp = FLINT_MAX(wp, 30); /* wp2 = Precision needed with cancellation. */ if (gamma_singular) { /* Max term is roughly n^(-s) * z^((s+parity)/2) * exp(z) */ wp2 = -abs_tol_mag + ns_mag + aa * log(zz) + zz / log(2) + 5; wp2 = FLINT_MAX(wp2, 30); } else { /* Estimate of Gamma((s+parity)/2) */ gamma_mag = ARF_EXP(arb_midref(Ga)); wp2 = FLINT_MAX(gamma_mag, gammainc_mag) + ns_mag - abs_tol_mag + 5; wp2 = FLINT_MAX(wp2, 30); } #if VERBOSE printf(" abs_tol_gamma = "); mag_printd(abs_tol_gamma, 5); printf("\n"); printf(" gamma(a) = "); arb_printd(Ga, 10); printf("\n"); printf(" wp = %ld wp2 = %ld\n", wp, wp2); #endif if (G == NULL) acb_one(c); else acb_dirichlet_chi(c, G, chi, n, wp); if (acb_is_zero(c)) continue; arb_const_pi(z, wp2); arb_mul_ui(z, z, n, wp2); arb_mul_ui(z, z, n, wp2); arb_div_ui(z, z, q, wp2); start_bits = 32; arb_extract_bits(z0, z, start_bits); /* Can we use the asymptotic series? */ NN = _arb_hypgeom_gamma_upper_fmpq_inf_choose_N(AE, s2, z0, abs_tol_gamma); #if VERBOSE t1 = clock(); #endif /* For each new point, evaluate from scratch or use continuation? The former seems to be faster. */ if (1) { if (NN != -1) { /* OK to use the asymptotic series. */ _arb_hypgeom_gamma_upper_fmpq_inf_bsplit(Gz0, s2, z0, NN, wp); arb_add_error_mag(Gz0, AE); #if VERBOSE flint_printf(" asymptotic series with N = %wd: ", NN); arb_printd(Gz0, 10); printf("\n"); #endif } else { /* Otherwise fallback to the series at 0. */ if (gamma_singular) { slong nn; nn = *fmpq_numref(s2); if (COEFF_IS_MPZ(nn)) { arb_indeterminate(Gz0); } else { nn = -nn; NN = _arb_hypgeom_gamma_upper_singular_si_choose_N(AE, nn, z0, abs_tol_gamma); _arb_hypgeom_gamma_upper_singular_si_bsplit(Gz0, nn, z0, NN, wp2); arb_add_error_mag(Gz0, AE); #if VERBOSE flint_printf(" singular series with N = %wd, z0 = ", NN); arb_printd(z0, 10); printf(" "); mag_printd(AE, 10); printf("\n"); #endif } } else { NN = _arb_hypgeom_gamma_lower_fmpq_0_choose_N(AE, s2, z0, abs_tol_gamma); _arb_hypgeom_gamma_lower_fmpq_0_bsplit(Gz0, s2, z0, NN, wp2); arb_add_error_mag(Gz0, AE); #if VERBOSE flint_printf(" lower series with N = %wd, z0 = ", NN); arb_printd(z0, 10); printf(" "); mag_printd(AE, 10); printf("\n"); #endif while (mag_cmp(arb_radref(Ga), abs_tol_gamma) > 0) { gamma_cached_prec *= 2; arb_gamma_fmpq(Ga, s2, gamma_cached_prec); } #if VERBOSE flint_printf(" lower series with N = %wd: ", NN); arb_printd(Gz0, 10); printf("\n"); #endif arb_sub(Gz0, Ga, Gz0, wp); #if VERBOSE flint_printf(" G(a) - lower series: "); arb_printd(Gz0, 10); printf("\n"); #endif } } } else { _arb_gamma_upper_fmpq_step_bsplit(Gz0, s2, z0_prevn, z0, Gz0_prevn, expmz0_prevn, abs_tol_gamma, wp); } #if VERBOSE printf(" Gz0 = "); arb_printd(Gz0, 10); printf("\n"); #endif if (n == 1) { arb_neg(expmz0, z0); arb_exp(expmz0, expmz0, wp); } else { arb_sub(t, z0_prevn, z0, wp); arb_exp(t, t, wp); arb_mul(expmz0, expmz0_prevn, t, wp); } arb_set(z0_prevn, z0); arb_set(expmz0_prevn, expmz0); arb_set(Gz0_prevn, Gz0); #if VERBOSE t2 = clock(); #endif /* Bit-burst steps */ for (bits = start_bits * 2; bits < wp / 8; bits *= 2) { arb_extract_bits(z1, z, bits); _arb_gamma_upper_fmpq_step_bsplit(Gz1, s2, z0, z1, Gz0, expmz0, abs_tol_gamma, wp); arb_sub(t, z0, z1, wp); arb_exp(t, t, wp); arb_mul(expmz0, expmz0, t, wp); arb_set(Gz0, Gz1); arb_set(z0, z1); } /* Final step, including error bound */ _arb_gamma_upper_fmpq_step_bsplit(Gz1, s2, z0, z, Gz0, expmz0, abs_tol_gamma, wp); arb_set(Gz0, Gz1); #if VERBOSE printf(" Gz0 = "); arb_printd(Gz0, 10); printf(" tol "); mag_printd(abs_tol_gamma, 5); printf("\n"); #endif /* Multiply by prefactor n^-s */ arb_set_ui(ns, n); arb_pow_fmpq(ns, ns, s, wp); arb_div(Gz0, Gz0, ns, wp); #if VERBOSE printf(" 1/n^s = "); arb_printn(ns, 5, ARB_STR_NO_RADIUS); printf("\n"); printf(" Gz0 * pre = "); arb_printd(Gz0, 10); printf(" tol "); mag_printd(abs_tol, 5); printf("\n"); #endif acb_addmul_arb(res, c, Gz0, prec); #if VERBOSE printf(" sum = "); acb_printd(res, 10); printf("\n"); t3 = clock(); printf(" time: %f, %f\n", (t2 - t1) / CLOCKS_PER_SEC, (t3 - t2) / CLOCKS_PER_SEC); #endif } mag_clear(AE); mag_clear(err); mag_clear(abs_tol_gamma); arb_clear(ns); arb_clear(t); arb_clear(u); arb_clear(v); arb_clear(z); arb_clear(z0); arb_clear(z1); arb_clear(x); arb_clear(x2); arb_clear(Ga); arb_clear(Gz0); arb_clear(Gz1); arb_clear(expmz0); arb_clear(z0_prevn); arb_clear(Gz0_prevn); arb_clear(expmz0_prevn); acb_clear(c); fmpq_clear(s2); } #define PI 3.1415926535897932385 #define INV_LOG2 1.4426950408889634074; /* max(pi/q,s/2)**(s/2-1) * exp(-max(pi/q,s/2)) static double estimate_sum1_mag(double s, double q) { return ((0.5 * s - 1) * log(FLINT_MAX(PI / q, 0.5 * s)) - FLINT_MAX(PI / q, 0.5 * s)) * INV_LOG2; } */ void acb_dirichlet_l_fmpq_afe(acb_t res, const fmpq_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { arb_t t; acb_t S1, S2, w; fmpq_t s2; mag_t tol1, tol2; double ds, m1, m2, m2pre; slong origprec, prec1, prec2; ulong q; int parity; /* Todo: implement decomposition for imprimitive characters. */ if (G != NULL && !dirichlet_char_is_primitive(G, chi)) { acb_indeterminate(res); return; } q = (G == NULL) ? 1 : G->q; parity = (G == NULL) ? 0 : dirichlet_parity_char(G, chi); /* Division by gamma((s+parity)/2) at a pole. */ if (fmpz_is_one(fmpq_denref(s))) { const fmpz * n = fmpq_numref(s); if ((parity == 0 && fmpz_sgn(n) <= 0 && fmpz_is_even(n)) || (parity == 1 && fmpz_sgn(n) < 0 && fmpz_is_odd(n))) { /* Special case for zeta */ if (q == 1 && fmpz_is_zero(n)) acb_set_d(res, -0.5); else acb_zero(res); return; } } origprec = prec; prec = prec * 1.001 + 2 * FLINT_BIT_COUNT(q); acb_init(S1); acb_init(S2); acb_init(w); arb_init(t); fmpq_init(s2); mag_init(tol1); mag_init(tol2); ds = fmpq_get_d(s); m1 = log_gamma_upper_approx(0.5 * (ds + parity), PI / q) * INV_LOG2; m2 = log_gamma_upper_approx(0.5 * (1.0 - ds + parity), PI / q) * INV_LOG2; m2pre = (ds - 0.5) * log(PI / q) * INV_LOG2; mag_one(tol1); mag_mul_2exp_si(tol1, tol1, FLINT_MAX(m1, m2 + m2pre) - prec); mag_mul_2exp_si(tol2, tol1, -m2pre); prec1 = prec - (FLINT_MAX(m1, m2 + m2pre) - m1); prec1 = FLINT_MAX(prec1, 32); prec2 = prec - (FLINT_MAX(m1, m2 + m2pre) - (m2 + m2pre)); prec2 = FLINT_MAX(prec2, 32); #if VERBOSE printf("mag1 = %ld mag2 = %ld mag2 + pre = %ld prec, prec1, prec2 = %ld, %ld, %ld\n", (slong) m1, (slong) m2, (slong) (m2 + m2pre), prec, prec1, prec2); printf("tol1 = %ld tol2 = %ld\n", MAG_EXP(tol1), MAG_EXP(tol2)); #endif acb_dirichlet_fmpq_sum_afe(S1, s, G, chi, tol1, prec1); #if VERBOSE printf("=====================================================\n"); printf("S1 = "); acb_printd(S1, 20); printf(" estimate = "); printf(" %g\n", ldexp(1.0, m1)); printf("=====================================================\n"); #endif if (q == 1 && fmpz_is_one(fmpq_numref(s)) && fmpz_equal_ui(fmpq_denref(s), 2)) { acb_mul_2exp_si(res, S1, 1); } else { /* rootnum (pi/q)^(s-1/2) sum(1-s) */ if (fmpz_is_one(fmpq_numref(s)) && fmpz_equal_ui(fmpq_denref(s), 2)) { acb_conj(S2, S1); } else { fmpq_sub_ui(s2, s, 1); fmpq_neg(s2, s2); acb_dirichlet_fmpq_sum_afe(S2, s2, G, chi, tol2, prec2); acb_conj(S2, S2); } #if VERBOSE printf("=====================================================\n"); printf("S1 = "); acb_printd(S1, 20); printf(" estimate = "); printf(" %g\n", ldexp(1.0, m1)); printf("S2 = "); acb_printd(S2, 20); printf(" estimate = "); printf(" %g\n", ldexp(1.0, m2)); printf("=====================================================\n"); #endif arb_const_pi(t, prec); arb_div_ui(t, t, q, prec); fmpq_set_si(s2, 1, 2); fmpq_sub(s2, s, s2); arb_pow_fmpq(t, t, s2, prec); acb_mul_arb(S2, S2, t, prec); if (q != 1) { acb_dirichlet_root_number2(w, G, chi, prec); acb_mul(S2, S2, w, prec); } #if VERBOSE printf("S2 * prefactor = "); acb_printd(S2, 20); printf(" estimate = "); printf(" %g\n", ldexp(1.0, m2 + m2pre)); #endif acb_add(res, S1, S2, prec); } /* add pi^(s/2) / (s (s-1)) */ if (q == 1) { arb_const_pi(t, prec); fmpq_div_2exp(s2, s, 1); arb_pow_fmpq(t, t, s2, prec); fmpq_sub_ui(s2, s, 1); fmpq_mul(s2, s2, s); arb_div_fmpz(t, t, fmpq_numref(s2), prec); arb_mul_fmpz(t, t, fmpq_denref(s2), prec); acb_add_arb(res, res, t, prec); } /* divide by gamma((s+parity)/2) */ fmpq_add_ui(s2, s, parity); fmpq_div_2exp(s2, s2, 1); arb_gamma_fmpq(t, s2, prec); acb_div_arb(res, res, t, prec); acb_set_round(res, res, origprec); acb_clear(S1); acb_clear(S2); acb_clear(w); arb_clear(t); fmpq_clear(s2); mag_clear(tol1); mag_clear(tol2); } flint-3.1.3/src/acb_dirichlet/l_hurwitz.c000066400000000000000000000042261461254215100203750ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_hurwitz_precomp_t precomp, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { ulong order, chin, mult; acb_t t, u, a, w; dirichlet_char_t cn; acb_dirichlet_roots_t roots; int deflate; /* remove pole in Hurwitz zeta at s = 1 */ deflate = 0; if (acb_is_one(s)) { if (dirichlet_char_is_principal(G, chi)) { acb_indeterminate(res); return; } deflate = 1; } dirichlet_char_init(cn, G); acb_init(t); acb_init(u); acb_init(a); acb_init(w); dirichlet_char_one(cn, G); acb_zero(t); prec += n_clog(G->phi_q, 2); order = dirichlet_order_char(G, chi); mult = G->expo / order; acb_dirichlet_roots_init(roots, order, dirichlet_group_size(G), prec); do { chin = dirichlet_pairing_char(G, chi, cn) / mult; if (precomp == NULL) { acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); if (deflate == 0) acb_hurwitz_zeta(u, s, a, prec); else _acb_poly_zeta_cpx_series(u, s, a, 1, 1, prec); } else { acb_dirichlet_hurwitz_precomp_eval(u, precomp, cn->n, G->q, prec); } acb_dirichlet_root(w, roots, chin, prec); acb_addmul(t, u, w, prec); } while (dirichlet_char_next(cn, G) >= 0); acb_set_ui(u, G->q); acb_neg(a, s); acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); dirichlet_char_clear(cn); acb_dirichlet_roots_clear(roots); acb_clear(t); acb_clear(u); acb_clear(a); acb_clear(w); } flint-3.1.3/src/acb_dirichlet/l_jet.c000066400000000000000000000067441461254215100174520ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" /* todo: move implemetation to the acb_dirichlet module */ void _acb_poly_zeta_cpx_reflect(acb_ptr t, const acb_t h, const acb_t a, int deflate, slong len, slong prec); void acb_dirichlet_l_jet(acb_ptr res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec) { ulong order, chin, mult, phi; acb_t a, w; acb_ptr t, u; dirichlet_char_t cn; acb_dirichlet_roots_t roots; int deflate_hurwitz; if (len <= 0) return; /* special-case Riemann zeta */ if (G == NULL || G->q == 1) { if (len == 1 && !deflate) acb_dirichlet_zeta(res, s, prec); else acb_dirichlet_zeta_jet(res, s, deflate, len, prec); return; } if (len == 1 && !(deflate && dirichlet_char_is_principal(G, chi))) { acb_dirichlet_l(res, s, G, chi, prec); return; } if (dirichlet_char_is_principal(G, chi)) deflate_hurwitz = deflate; else deflate_hurwitz = acb_is_one(s); dirichlet_char_init(cn, G); t = _acb_vec_init(len); u = _acb_vec_init(len + 2); acb_init(a); acb_init(w); dirichlet_char_one(cn, G); prec += n_clog(G->phi_q, 2); order = dirichlet_order_char(G, chi); mult = G->expo / order; acb_dirichlet_roots_init(roots, order, dirichlet_group_size(G), prec); phi = 0; do { chin = dirichlet_pairing_char(G, chi, cn) / mult; acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); _acb_poly_zeta_cpx_series(u, s, a, deflate_hurwitz, len, prec); acb_dirichlet_root(w, roots, chin, prec); _acb_vec_scalar_addmul(t, u, len, w, prec); phi++; } while (dirichlet_char_next(cn, G) >= 0); if (dirichlet_char_is_principal(G, chi) && deflate) { /* res = t * q^(-(s+x)) + [phi(q) * (q^(-(s+x)) - q^-1) / ((s+x)-1)] */ if (acb_is_one(s)) { acb_set_ui(a, G->q); _acb_poly_acb_invpow_cpx(u, a, s, len + 1, prec); _acb_poly_mullow(res, t, len, u, len, len, prec); acb_set_ui(u, phi); _acb_vec_scalar_addmul(res, u + 1, len, u, prec); } else { acb_sub_ui(u, s, 1, prec); acb_one(u + 1); acb_set_ui(a, G->q); _acb_poly_acb_invpow_cpx(u + 2, a, s, len, prec); _acb_poly_mullow(res, t, len, u + 2, len, len, prec); acb_inv(a, a, prec); acb_sub(u + 2, u + 2, a, prec); _acb_poly_div_series(t, u + 2, len, u, 2, len, prec); acb_set_ui(u, phi); _acb_vec_scalar_addmul(res, t, len, u, prec); } } else { /* res = t * q^(-(s+x)) */ acb_set_ui(a, G->q); _acb_poly_acb_invpow_cpx(u, a, s, len, prec); _acb_poly_mullow(res, t, len, u, len, len, prec); } dirichlet_char_clear(cn); acb_dirichlet_roots_clear(roots); _acb_vec_clear(t, len); _acb_vec_clear(u, len + 2); acb_clear(a); acb_clear(w); } flint-3.1.3/src/acb_dirichlet/l_series.c000066400000000000000000000035041461254215100201510ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" void _acb_dirichlet_l_series(acb_ptr res, acb_srcptr s, slong slen, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec) { slen = FLINT_MIN(slen, len); if (len == 0) return; if (slen == 1 && !deflate) { acb_dirichlet_l(res, s, G, chi, prec); _acb_vec_zero(res + 1, len - 1); } else { acb_ptr t, u; t = _acb_vec_init(len); u = _acb_vec_init(slen); acb_dirichlet_l_jet(t, s, G, chi, deflate, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, s + 1, slen - 1); _acb_poly_compose_series(res, t, len, u, slen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, slen); } } void acb_dirichlet_l_series(acb_poly_t res, const acb_poly_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec) { if (len == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, len); if (s->length == 0) { acb_t t; acb_init(t); _acb_dirichlet_l_series(res->coeffs, t, 1, G, chi, deflate, len, prec); acb_clear(t); } else { _acb_dirichlet_l_series(res->coeffs, s->coeffs, s->length, G, chi, deflate, len, prec); } _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_dirichlet/l_vec_hurwitz.c000066400000000000000000000035341461254215100212330ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_hurwitz_precomp_t precomp, const dirichlet_group_t G, slong prec) { acb_t a, qs; acb_ptr zeta, z; dirichlet_char_t cn; int deflate; /* remove pole in Hurwitz zeta at s = 1 */ deflate = acb_is_one(s); dirichlet_char_init(cn, G); acb_init(qs); acb_init(a); prec += n_clog(G->phi_q, 2); acb_set_ui(qs, G->q); acb_neg(a, s); acb_pow(qs, qs, a, prec); zeta = z = _acb_vec_init(G->phi_q); dirichlet_char_one(cn, G); do { if (precomp == NULL) { acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); if (deflate == 0) acb_hurwitz_zeta(z, s, a, prec); else _acb_poly_zeta_cpx_series(z, s, a, 1, 1, prec); } else { acb_dirichlet_hurwitz_precomp_eval(z, precomp, cn->n, G->q, prec); } acb_mul(z, z, qs, prec); acb_conj(z, z); z++; } while (dirichlet_char_next(cn, G) >= 0); acb_dirichlet_dft_index(res, zeta, G, prec); { slong k; for (k = 0; k < G->phi_q; k++) acb_conj(res + k, res + k); } /* restore pole for the principal character */ if (deflate) acb_indeterminate(res); dirichlet_char_clear(cn); _acb_vec_clear(zeta, G->phi_q); acb_clear(qs); acb_clear(a); } flint-3.1.3/src/acb_dirichlet/lerch_phi.c000066400000000000000000000072111461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_hypgeom.h" #include "acb_dirichlet.h" void acb_dirichlet_lerch_phi(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec) { if (!acb_is_finite(z) || !acb_is_finite(s) || !acb_is_finite(a)) { acb_indeterminate(res); return; } if (acb_contains_int(a) && !arb_is_positive(acb_realref(a))) { if (!(acb_is_int(s) && arb_is_nonpositive(acb_realref(s)))) { acb_indeterminate(res); return; } } if (acb_is_zero(z)) { acb_t t; acb_init(t); acb_neg(t, s); acb_pow(res, a, t, prec); acb_clear(t); return; } if (acb_is_one(z)) { arb_t one; arb_init(one); if (arb_gt(acb_realref(s), one)) acb_dirichlet_hurwitz(res, s, a, prec); else acb_indeterminate(res); arb_clear(one); return; } if (acb_equal_si(z, -1)) { if (acb_is_one(a)) { acb_dirichlet_eta(res, s, prec); } else if (acb_is_one(s)) { /* (psi((a+1)/2) - psi(a/2))/2 */ acb_t t, u; acb_init(t); acb_init(u); acb_mul_2exp_si(t, a, -1); acb_digamma(t, t, prec); acb_add_ui(u, a, 1, prec); acb_mul_2exp_si(u, u, -1); acb_digamma(u, u, prec); acb_sub(res, u, t, prec); acb_mul_2exp_si(res, res, -1); acb_clear(t); acb_clear(u); } else { /* 2^(-s) (zeta(s,a/2) - zeta(s,(a+1)/2)) */ acb_t t, u; acb_init(t); acb_init(u); acb_mul_2exp_si(t, a, -1); acb_hurwitz_zeta(t, s, t, prec); acb_add_ui(u, a, 1, prec); acb_mul_2exp_si(u, u, -1); acb_hurwitz_zeta(u, s, u, prec); acb_sub(t, t, u, prec); acb_neg(u, s); acb_set_ui(res, 2); acb_pow(res, res, u, prec); acb_mul(res, res, t, prec); acb_clear(t); acb_clear(u); } return; } if (acb_is_zero(s)) { acb_sub_ui(res, z, 1, prec + 5); acb_neg(res, res); acb_inv(res, res, prec); return; } if (acb_is_one(s)) { acb_t t, u; acb_init(t); acb_init(u); acb_one(t); acb_add_ui(u, a, 1, prec + 5); acb_hypgeom_2f1(t, t, a, u, z, ACB_HYPGEOM_2F1_BC, prec + 5); acb_div(res, t, a, prec); if (!acb_is_finite(res)) acb_indeterminate(res); acb_clear(t); acb_clear(u); return; } if (acb_is_one(a) && !acb_contains_zero(z)) { acb_t t; acb_init(t); acb_polylog(t, s, z, prec); acb_div(res, t, z, prec); acb_clear(t); return; } { mag_t zm, lim; mag_init(zm); mag_init(lim); acb_get_mag(zm, z); mag_set_d(lim, 0.875); if (mag_cmp(zm, lim) <= 0) { acb_dirichlet_lerch_phi_direct(res, z, s, a, prec); } else { acb_dirichlet_lerch_phi_integral(res, z, s, a, prec); } mag_clear(zm); mag_clear(lim); } } flint-3.1.3/src/acb_dirichlet/lerch_phi_direct.c000066400000000000000000000070001461254215100216260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_lerch_phi_direct(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec) { slong N, Nmax, wp, n; int a_real; acb_t negs, t, u, sum; mag_t C, S, zmag, tail_bound, tm, tol; if (!acb_is_finite(z) || !acb_is_finite(s) || !acb_is_finite(a)) { acb_indeterminate(res); return; } if (acb_contains_int(a) && !arb_is_positive(acb_realref(a))) { if (!(acb_is_int(s) && arb_is_nonpositive(acb_realref(s)))) { acb_indeterminate(res); return; } } acb_init(negs); acb_init(t); acb_init(u); acb_init(sum); acb_neg(negs, s); mag_init(C); mag_init(S); mag_init(zmag); mag_init(tail_bound); mag_init(tm); mag_init(tol); a_real = acb_is_real(a); wp = prec + 10; acb_get_mag(zmag, z); /* first term: 1/a^s */ acb_pow(sum, a, negs, wp); acb_get_mag(tol, sum); mag_mul_2exp_si(tol, tol, -wp); if (a_real) { /* Tail bound |z|^N / |(a+N)^s| * sum C^k, C = |z| * exp(max(0, -re(s)) / (a+N)) */ arb_nonnegative_part(acb_realref(t), acb_realref(negs)); arb_get_mag(S, acb_realref(t)); } else { /* Tail bound |z|^N / |(a+N)^s| * sum C^k, C = |z| * exp(|s / (a+N)|) */ acb_get_mag(S, s); } Nmax = 100 * prec + 0.1 * prec * n_sqrt(prec); Nmax = FLINT_MAX(Nmax, 1); Nmax = FLINT_MIN(Nmax, WORD_MAX / 2); mag_inf(tail_bound); for (N = 1; N <= Nmax; N = FLINT_MAX(N+4, N*1.1)) { acb_add_ui(t, a, N, 53); if (arb_is_positive(acb_realref(t))) { acb_get_mag_lower(C, t); mag_div(C, S, C); mag_exp(C, C); mag_mul(C, C, zmag); mag_geom_series(C, C, 0); if (mag_is_finite(C)) { mag_pow_ui(tail_bound, zmag, N); mag_mul(tail_bound, tail_bound, C); acb_pow(t, t, negs, 53); acb_get_mag(C, t); mag_mul(tail_bound, tail_bound, C); if (mag_cmp(tail_bound, tol) <= 0) break; } else { mag_inf(tail_bound); } } } if (mag_is_finite(tail_bound)) { acb_one(t); for (n = 1; n < N; n++) { if (n % 8 == 0 && !acb_is_real(z)) acb_pow_ui(t, z, n, wp); else acb_mul(t, t, z, wp); acb_add_ui(u, a, n, wp); acb_pow(u, u, negs, wp); acb_mul(u, t, u, wp); acb_add(sum, sum, u, wp); } if (acb_is_real(z) && acb_is_real(s) && acb_is_real(a)) arb_add_error_mag(acb_realref(sum), tail_bound); else acb_add_error_mag(sum, tail_bound); acb_set_round(res, sum, prec); } else { acb_indeterminate(res); } mag_clear(C); mag_clear(S); mag_clear(zmag); mag_clear(tail_bound); mag_clear(tm); mag_clear(tol); acb_clear(negs); acb_clear(t); acb_clear(u); acb_clear(sum); } flint-3.1.3/src/acb_dirichlet/lerch_phi_integral.c000066400000000000000000000414721461254215100221740ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_calc.h" #include "acb_dirichlet.h" static void integral_tail(mag_t bound, const acb_t z, const acb_t log_z, const acb_t s, const acb_t a, const arb_t R, slong prec) { arb_t C, s1; mag_t t; arb_init(C); arb_init(s1); mag_init(t); /* re(s) - 1 */ arb_sub_ui(s1, acb_realref(s), 1, prec); /* C = re(a) - max(0, re(s) - 1) / R */ arb_nonnegative_part(C, s1); arb_div(C, C, R, prec); arb_sub(C, acb_realref(a), C, prec); /* C > 0 */ if (arb_is_positive(C)) { /* |log(z)| + 1 */ acb_get_mag(bound, log_z); mag_add_ui(bound, bound, 1); /* R */ arb_get_mag_lower(t, R); /* R > |log(z)| + 1 */ if (mag_cmp(t, bound) > 0) { /* 2 * R^(re(s)-1) * C^(-1) * exp(-re(a)*R) */ arb_pow(s1, R, s1, prec); arb_div(C, s1, C, prec); arb_mul_2exp_si(C, C, 1); arb_mul(s1, acb_realref(a), R, prec); arb_neg(s1, s1); arb_exp(s1, s1, prec); arb_mul(C, C, s1, prec); arb_get_mag(bound, C); } else { mag_inf(bound); } } else { mag_inf(bound); } arb_clear(C); arb_clear(s1); mag_clear(t); } static int _integrand(acb_ptr res, const acb_t t, void * param, slong order, int negate_power, slong prec) { acb_srcptr z, s, a; acb_t u, v; if (order > 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* Would be needed for Taylor method. */ z = ((acb_srcptr)(param)) + 0; s = ((acb_srcptr)(param)) + 1; a = ((acb_srcptr)(param)) + 2; acb_init(u); acb_init(v); acb_neg(u, t); acb_exp(u, u, prec); acb_mul(u, u, z, prec); acb_sub_ui(u, u, 1, prec); acb_neg(u, u); if (acb_contains_zero(u)) { acb_indeterminate(res); } else { /* t^(s-1) * exp(-a*t) = exp((s-1)*log(t) - a*t) */ /* (-t)^(s-1) * exp(-a*t) = exp((s-1)*log(t) - a*t) */ acb_sub_ui(v, s, 1, prec); if (acb_is_int(s)) { if (negate_power) { acb_neg(res, t); acb_pow(v, res, v, prec); } else { acb_pow(v, t, v, prec); } acb_div(u, v, u, prec); acb_mul(v, a, t, prec); acb_neg(v, v); acb_exp(v, v, prec); acb_mul(res, u, v, prec); } else { if (negate_power) { acb_neg(res, t); acb_log_analytic(res, res, order != 0, prec); } else { acb_log_analytic(res, t, order != 0, prec); } acb_mul(res, res, v, prec); acb_submul(res, a, t, prec); acb_exp(res, res, prec); acb_div(res, res, u, prec); } } acb_clear(u); acb_clear(v); return 0; } static int integrand(acb_ptr res, const acb_t t, void * param, slong order, slong prec) { return _integrand(res, t, param, order, 0, prec); } static int integrand2(acb_ptr res, const acb_t t, void * param, slong order, slong prec) { return _integrand(res, t, param, order, 1, prec); } void _acb_dirichlet_lerch_phi_integral(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec) { acb_t log_z, t, u, v, w, zero, N; acb_ptr param; mag_t abs_tol, tail_bound; slong i, rel_goal; acb_calc_integrate_opt_t options; int is_real; mag_t log_z_im_lower; acb_t xa, xb; acb_init(log_z); acb_init(t); acb_init(u); acb_init(v); acb_init(w); acb_init(zero); acb_init(N); mag_init(abs_tol); mag_init(tail_bound); mag_init(log_z_im_lower); acb_init(xa); acb_init(xb); param = _acb_vec_init(3); /* compute either the principal log or +/ 2 pi i (does not matter as long as the imaginary part is not too far off) */ if (arb_is_positive(acb_realref(z)) || !arb_contains_zero(acb_imagref(z))) { acb_log(log_z, z, prec); } else { acb_neg(log_z, z); acb_log(log_z, log_z, prec); acb_const_pi(t, prec); acb_mul_2exp_si(t, t, 1); acb_mul_onei(t, t); if (arf_sgn(arb_midref(acb_realref(z))) >= 0) acb_add(log_z, log_z, t, prec); else acb_sub(log_z, log_z, t, prec); } arb_one(acb_realref(t)); is_real = acb_is_real(z) && acb_is_real(s) && acb_is_real(a) && arb_is_positive(acb_realref(a)) && arb_lt(acb_realref(z), acb_realref(t)); acb_set(param + 0, z); acb_set(param + 1, s); acb_set(param + 2, a); acb_one(N); mag_inf(tail_bound); /* todo: good relative magnitude */ acb_one(t); acb_get_mag(abs_tol, t); mag_mul_2exp_si(abs_tol, abs_tol, -prec); acb_zero(t); for (i = 1; i < prec; i++) { acb_one(N); acb_mul_2exp_si(N, N, i); integral_tail(tail_bound, z, log_z, s, a, acb_realref(N), 53); if (mag_cmp(tail_bound, abs_tol) < 0) break; } rel_goal = prec; acb_calc_integrate_opt_init(options); arb_get_mag_lower(log_z_im_lower, acb_imagref(log_z)); /* todo: with several integrals, add the errors to tolerances */ if (acb_is_int(s) && arb_is_positive(acb_realref(s))) { /* integer s > 0: use direct integral */ /* no need to avoid pole near path */ if (arb_is_negative(acb_realref(log_z)) || mag_cmp_2exp_si(log_z_im_lower, -2) > 0) { acb_zero(xa); acb_set(xb, N); acb_calc_integrate(t, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); } /* take detour through upper plane */ else if (arb_is_nonpositive(acb_imagref(log_z))) { acb_zero(xa); acb_onei(xb); acb_calc_integrate(t, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_swap(xa, xb); acb_add(xb, xa, N, prec); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_add(t, t, u, prec); acb_swap(xa, xb); acb_set(xb, N); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_add(t, t, u, prec); } /* take detour through lower plane */ else if (arb_is_positive(acb_imagref(log_z))) { acb_zero(xa); acb_onei(xb); acb_conj(xb, xb); acb_calc_integrate(t, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_swap(xa, xb); acb_add(xb, xa, N, prec); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_add(t, t, u, prec); acb_swap(xa, xb); acb_set(xb, N); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_add(t, t, u, prec); } else { /* todo: compute union of both branches? */ acb_indeterminate(t); } acb_add_error_mag(t, tail_bound); if (is_real && acb_is_finite(t)) arb_zero(acb_imagref(t)); acb_rgamma(u, s, prec); acb_mul(res, t, u, prec); } else { arb_t left, right, bottom, top; acb_t residue; mag_t rm, im; arb_init(left); arb_init(right); arb_init(bottom); arb_init(top); acb_init(residue); mag_init(rm); mag_init(im); arb_get_mag_lower(rm, acb_realref(log_z)); arb_get_mag_lower(im, acb_imagref(log_z)); if (arb_is_negative(acb_realref(log_z)) && mag_cmp_2exp_si(rm, -1) > 0) { /* re(log(z)) < -0.5 - pole certainly excluded */ /* left = min(|re(log(z))| / 2, 1) */ arf_set_mag(arb_midref(left), rm); arf_mul_2exp_si(arb_midref(left), arb_midref(left), -1); if (arf_cmpabs_2exp_si(arb_midref(left), 0) > 0) arb_one(left); arb_set(right, left); arb_set(top, left); arb_set(bottom, left); } else if (mag_cmp_2exp_si(im, -1) > 0) { /* im(log(z)) > 0.5 - pole certainly excluded */ arf_set_mag(arb_midref(left), im); arf_mul_2exp_si(arb_midref(left), arb_midref(left), -1); if (arf_cmpabs_2exp_si(arb_midref(left), 0) > 0) arb_one(left); arb_set(right, left); arb_set(top, left); arb_set(bottom, left); } else { /* residue = (-log(z))^s / log(z) / z^a */ acb_neg(residue, log_z); acb_pow(residue, residue, s, prec); acb_div(residue, residue, log_z, prec); acb_pow(t, z, a, prec); acb_div(residue, residue, t, prec); /* |im(log(z)) + 1 */ arb_get_mag(im, acb_imagref(log_z)); /* containing a unique pole is uncertain -- error out */ if (mag_cmp_2exp_si(im, 1) > 0) { acb_indeterminate(res); goto cleanup1; } else { arf_set_mag(arb_midref(top), im); arb_add_ui(top, top, 1, prec); arb_set(bottom, top); /* max(0, -re(log(z))) + 1 */ arb_get_lbound_arf(arb_midref(left), acb_realref(log_z), prec); arb_neg(left, left); if (arf_sgn(arb_midref(left)) < 0) arb_one(left); else arb_add_ui(left, left, 1, prec); /* max(0, re(log(z))) + 1 */ arb_get_ubound_arf(arb_midref(right), acb_realref(log_z), prec); if (arf_sgn(arb_midref(right)) < 0) arb_one(right); else arb_add_ui(right, right, 1, prec); } } arb_neg(left, left); arb_neg(bottom, bottom); acb_zero(t); /* w = (-1)^(s-1) */ acb_sub_ui(w, s, 1, prec); acb_exp_pi_i(w, w, prec); if (is_real) { /* right -> top right */ arb_set(acb_realref(xa), right); arb_zero(acb_imagref(xa)); arb_set(acb_realref(xb), right); arb_set(acb_imagref(xb), top); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_div(u, u, w, prec); acb_add(t, t, u, prec); /* top right -> top left */ arb_set(acb_realref(xa), right); arb_set(acb_imagref(xa), top); arb_set(acb_realref(xb), left); arb_set(acb_imagref(xb), top); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_div(u, u, w, prec); acb_add(t, t, u, prec); /* top left -> left */ arb_set(acb_realref(xa), left); arb_set(acb_imagref(xa), top); arb_set(acb_realref(xb), left); arb_zero(acb_imagref(xb)); acb_calc_integrate(u, integrand2, param, xa, xb, rel_goal, abs_tol, options, prec); acb_add(t, t, u, prec); /* 2 * imaginary part */ arb_zero(acb_realref(t)); acb_mul_2exp_si(t, t, 1); } else { /* right -> top right */ arb_set(acb_realref(xa), right); arb_zero(acb_imagref(xa)); arb_set(acb_realref(xb), right); arb_set(acb_imagref(xb), top); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_div(u, u, w, prec); acb_add(t, t, u, prec); /* top right -> top left */ arb_set(acb_realref(xa), right); arb_set(acb_imagref(xa), top); arb_set(acb_realref(xb), left); arb_set(acb_imagref(xb), top); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_div(u, u, w, prec); acb_add(t, t, u, prec); /* top left -> bottom left */ arb_set(acb_realref(xa), left); arb_set(acb_imagref(xa), top); arb_set(acb_realref(xb), left); arb_set(acb_imagref(xb), bottom); acb_calc_integrate(u, integrand2, param, xa, xb, rel_goal, abs_tol, options, prec); acb_add(t, t, u, prec); /* bottom left -> bottom right */ arb_set(acb_realref(xa), left); arb_set(acb_imagref(xa), bottom); arb_set(acb_realref(xb), right); arb_set(acb_imagref(xb), bottom); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_mul(u, u, w, prec); acb_add(t, t, u, prec); /* bottom right -> right */ arb_set(acb_realref(xa), right); arb_set(acb_imagref(xa), bottom); arb_set(acb_realref(xb), right); arb_zero(acb_imagref(xb)); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_mul(u, u, w, prec); acb_add(t, t, u, prec); } /* right -> infinity */ arb_set(acb_realref(xa), right); arb_zero(acb_imagref(xa)); arb_set(acb_realref(xb), acb_realref(N)); arb_zero(acb_imagref(xb)); acb_calc_integrate(u, integrand, param, xa, xb, rel_goal, abs_tol, options, prec); acb_add_error_mag(u, tail_bound); /* (w - 1/w) */ acb_inv(v, w, prec); acb_sub(v, w, v, prec); acb_addmul(t, u, v, prec); /* -gamma(1-s) * (t / (2 pi i) + residue) */ acb_const_pi(u, prec); acb_mul_onei(u, u); acb_mul_2exp_si(u, u, 1); acb_div(t, t, u, prec); acb_add(t, t, residue, prec); acb_sub_ui(u, s, 1, prec); acb_neg(u, u); acb_gamma(u, u, prec); acb_neg(u, u); acb_mul(res, t, u, prec); if (is_real) arb_zero(acb_imagref(res)); cleanup1: arb_clear(left); arb_clear(right); arb_clear(bottom); arb_clear(top); acb_clear(residue); mag_clear(rm); mag_clear(im); } mag_clear(log_z_im_lower); acb_clear(xa); acb_clear(xb); acb_clear(log_z); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); acb_clear(zero); acb_clear(N); mag_clear(abs_tol); mag_clear(tail_bound); _acb_vec_clear(param, 3); } void acb_dirichlet_lerch_phi_integral(acb_t res, const acb_t z, const acb_t s, const acb_t a, slong prec) { if (!acb_is_finite(z) || !acb_is_finite(s) || !acb_is_finite(a) || acb_contains_zero(z) || (arb_contains_si(acb_realref(z), 1) && arb_contains_zero(acb_imagref(z)))) { acb_indeterminate(res); return; } if (acb_contains_int(a) && !arb_is_positive(acb_realref(a))) { if (!(acb_is_int(s) && arb_is_nonpositive(acb_realref(s)))) { acb_indeterminate(res); return; } } /* wide intervals will just cause numerical integration to converge slowly, clogging unit tests */ if (acb_rel_accuracy_bits(z) < 1 || acb_rel_accuracy_bits(s) < 1 || acb_rel_accuracy_bits(a) < 1) { acb_indeterminate(res); return; } if (arf_cmp_si(arb_midref(acb_realref(a)), -2 * prec) < 0) { acb_indeterminate(res); return; } if (arf_cmp_si(arb_midref(acb_realref(a)), 2) < 0) { slong n, N, wp; acb_t t, u, sum, negs; N = 2 - arf_get_si(arb_midref(acb_realref(a)), ARF_RND_FLOOR); wp = prec + 10; acb_init(t); acb_init(u); acb_init(sum); acb_init(negs); acb_one(t); acb_neg(negs, s); for (n = 0; n < N; n++) { if (n >= 1) { if (n % 8 == 0 && !acb_is_real(z)) acb_pow_ui(t, z, n, wp); else acb_mul(t, t, z, wp); } acb_add_ui(u, a, n, wp); acb_pow(u, u, negs, wp); acb_mul(u, t, u, wp); acb_add(sum, sum, u, wp); } acb_add_ui(t, a, n, wp); _acb_dirichlet_lerch_phi_integral(u, z, s, t, prec); acb_pow_ui(t, z, n, prec); acb_mul(u, u, t, prec); acb_add(res, u, sum, prec); acb_clear(t); acb_clear(u); acb_clear(sum); acb_clear(negs); } else { _acb_dirichlet_lerch_phi_integral(res, z, s, a, prec); } } flint-3.1.3/src/acb_dirichlet/pairing.c000066400000000000000000000015061461254215100177750ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb_dirichlet.h" void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec) { ulong expo; expo = dirichlet_pairing(G, m, n); if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else { fmpq_t t; fmpq_init(t); fmpq_set_si(t, 2 * expo, G->expo); arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); fmpq_clear(t); } } flint-3.1.3/src/acb_dirichlet/pairing_conrey.c000066400000000000000000000015621461254215100213560ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb_dirichlet.h" void acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec) { ulong expo; expo = dirichlet_pairing_char(G, a, b); if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else { fmpq_t t; fmpq_init(t); fmpq_set_si(t, 2 * expo, G->expo); arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); fmpq_clear(t); } } flint-3.1.3/src/acb_dirichlet/platt_beta.c000066400000000000000000000014651461254215100204670ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void _arb_inv_ui(arb_t res, ulong n, slong prec) { arb_set_ui(res, n); arb_inv(res, res, prec); } void acb_dirichlet_platt_beta(arb_t res, const arb_t t, slong prec) { arb_t u, v; arb_init(u); arb_init(v); arb_log(u, t, prec); arb_log(v, u, prec); arb_div(u, v, u, prec); _arb_inv_ui(res, 6, prec); arb_add(res, res, u, prec); arb_clear(u); arb_clear(v); } flint-3.1.3/src/acb_dirichlet/platt_c_bound.c000066400000000000000000000136541461254215100211700ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_dirichlet.h" #include "arb_hypgeom.h" static void _arb_pow_si(arb_t res, const arb_t x, slong y, slong prec) { arb_t a; arb_init(a); arb_set_si(a, y); arb_pow(res, x, a, prec); arb_clear(a); } static void _arb_add_d(arb_t res, const arb_t x, double y, slong prec) { arb_t a; arb_init(a); arb_set_d(a, y); arb_add(res, x, a, prec); arb_clear(a); } static void _arb_sub_d(arb_t res, const arb_t x, double y, slong prec) { _arb_add_d(res, x, -y, prec); } /* res = 2^((6*k+5-sigma)/4) * pi^k * (sigma + 1/2)^k * h */ static void _pre_c_Xa(arb_t res, slong sigma, const arb_t h, ulong k, slong prec) { arb_t pi, two, x1, x2; arb_init(pi); arb_init(two); arb_init(x1); arb_init(x2); arb_const_pi(pi, prec); arb_set_si(two, 2); arb_set_si(x1, (6*k + 5 - sigma)); arb_mul_2exp_si(x1, x1, -2); arb_pow(x1, two, x1, prec); arb_set_si(x2, sigma); _arb_add_d(x2, x2, 0.5, prec); arb_mul(x2, x2, pi, prec); arb_pow_ui(x2, x2, k, prec); arb_mul(res, x1, x2, prec); arb_mul(res, res, h, prec); arb_clear(pi); arb_clear(two); arb_clear(x1); arb_clear(x2); } /* res = 2^((6*k+7-sigma)/4) * pi^(k - 1/2) */ static void _pre_c_Xb(arb_t res, slong sigma, ulong k, slong prec) { arb_t pi, two, x1, x2; arb_init(pi); arb_init(two); arb_init(x1); arb_init(x2); arb_const_pi(pi, prec); arb_set_si(two, 2); arb_set_si(x1, (6*k + 7 - sigma)); arb_mul_2exp_si(x1, x1, -2); arb_pow(x1, two, x1, prec); arb_set_ui(x2, k); _arb_sub_d(x2, x2, 0.5, prec); arb_pow(x2, pi, x2, prec); arb_mul(res, x1, x2, prec); arb_clear(pi); arb_clear(two); arb_clear(x1); arb_clear(x2); } /* * res[(sigma-1)/2 - l] = binom((sigma-1)/2, l) * 2^((k+l-1)/2) * * h^(k+l+1) * gamma((k+l+1)/2, (sigma+1/2)^2 / 2*h^2) */ static void _pre_c_p(arb_ptr res, slong sigma, const arb_t h, ulong k, slong prec) { slong l; slong len = (sigma - 1)/2 + 1; arb_t two, f, f1, f2, u, base, x; arb_init(two); arb_init(f); arb_init(f1); arb_init(f2); arb_init(u); arb_init(base); arb_init(x); /* precompute 2^((k-1)/2) * h^(k+1) */ arb_set_ui(two, 2); arb_set_si(f1, k-1); arb_mul_2exp_si(f1, f1, -1); arb_pow(f1, two, f1, prec); _arb_pow_si(f2, h, k+1, prec); arb_mul(f, f1, f2, prec); /* precompute (sigma + 1/2)^2 / 2*h^2 */ arb_set_si(u, sigma); _arb_add_d(u, u, 0.5, prec); arb_div(u, u, h, prec); arb_sqr(u, u, prec); arb_mul_2exp_si(u, u, -1); /* precompute powers of sqrt(2)*h */ arb_sqrt_ui(base, 2, prec); arb_mul(base, base, h, prec); _arb_vec_set_powers(res, base, len, prec); for (l = 0; l < len; l++) { arb_mul(res + l, res + l, f, prec); arb_bin_uiui(x, (sigma - 1)/2, l, prec); arb_mul(res + l, res + l, x, prec); arb_set_si(x, k + l + 1); arb_mul_2exp_si(x, x, -1); arb_hypgeom_gamma_upper(x, x, u, 0, prec); arb_mul(res + l, res + l, x, prec); } _arb_poly_reverse(res, res, len, len); arb_clear(two); arb_clear(f); arb_clear(f1); arb_clear(f2); arb_clear(u); arb_clear(base); arb_clear(x); } void acb_dirichlet_platt_c_precomp_init(acb_dirichlet_platt_c_precomp_t pre, slong sigma, const arb_t h, ulong k, slong prec) { if (!arb_is_positive(h)) { flint_throw(FLINT_ERROR, "requires positive h\n"); } else if (sigma % 2 == 0 || sigma < 3) { flint_throw(FLINT_ERROR, "requires odd integer sigma >= 3 (sigma=%wd)\n", sigma); } else { pre->len = (sigma - 1) / 2 + 1; arb_init(&pre->Xa); arb_init(&pre->Xb); pre->p = _arb_vec_init(pre->len); _pre_c_Xa(&pre->Xa, sigma, h, k, prec); _pre_c_Xb(&pre->Xb, sigma, k, prec); _pre_c_p(pre->p, sigma, h, k, prec); } } void acb_dirichlet_platt_c_precomp_clear(acb_dirichlet_platt_c_precomp_t pre) { arb_clear(&pre->Xa); arb_clear(&pre->Xb); _arb_vec_clear(pre->p, pre->len); } void acb_dirichlet_platt_c_bound_precomp(arb_t res, const acb_dirichlet_platt_c_precomp_t pre, slong sigma, const arb_t t0, const arb_t h, slong k, slong prec) { /* requires sigma + 1/2 <= t0 */ arb_t lhs; arb_init(lhs); arb_set_si(lhs, sigma); _arb_add_d(lhs, lhs, 0.5, prec); if (!arb_le(lhs, t0)) { arb_zero_pm_inf(res); } else { arb_t u, v; arb_init(u); arb_init(v); /* u = exp((1 + sqrt(8))/(6*t0)) */ arb_sqrt_ui(u, 8, prec); arb_add_ui(u, u, 1, prec); arb_div_ui(u, u, 6, prec); arb_div(u, u, t0, prec); arb_exp(u, u, prec); /* v = (sigma + 1/2 + t0)^((sigma - 1)/2) */ arb_add_si(v, t0, sigma, prec); _arb_add_d(v, v, 0.5, prec); _arb_pow_si(v, v, (sigma - 1)/2, prec); /* res = u*(v*Xa + Xb*X(t0)) */ _arb_poly_evaluate(res, pre->p, pre->len, t0, prec); arb_mul(res, res, &pre->Xb, prec); arb_addmul(res, v, &pre->Xa, prec); arb_mul(res, res, u, prec); arb_clear(u); arb_clear(v); } arb_clear(lhs); } void acb_dirichlet_platt_c_bound(arb_t res, slong sigma, const arb_t t0, const arb_t h, slong k, slong prec) { acb_dirichlet_platt_c_precomp_t pre; acb_dirichlet_platt_c_precomp_init(pre, sigma, h, k, prec); acb_dirichlet_platt_c_bound_precomp(res, pre, sigma, t0, h, k, prec); acb_dirichlet_platt_c_precomp_clear(pre); } flint-3.1.3/src/acb_dirichlet/platt_hardy_z_zeros.c000066400000000000000000000020741461254215100224330ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" slong acb_dirichlet_platt_hardy_z_zeros( arb_ptr res, const fmpz_t n, slong len, slong prec) { if (len <= 0 || fmpz_sizeinbase(n, 10) < 5) { return 0; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "Nonpositive indices of Hardy Z zeros are not supported.\n"); } else { slong r, s; fmpz_t k; fmpz_init(k); fmpz_set(k, n); for (s = 0; s < len; s += r) { r = acb_dirichlet_platt_local_hardy_z_zeros(res + s, k, len - s, prec); if (!r) break; fmpz_add_si(k, k, r); } return s; } return 0; } flint-3.1.3/src/acb_dirichlet/platt_i_bound.c000066400000000000000000000076211461254215100211730ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "arb_hypgeom.h" /* c1 = 4*zeta(sigma)/(2*sigma-1) * pi^((-3-2*sigma)/4) * exp(...) */ static void _pre_i_c1(arb_t res, slong A, const arb_t H, slong sigma, slong prec) { arb_t pi, x1, x2, x3, x4; arb_init(pi); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_const_pi(pi, prec); /* x1 = 4*zeta(sigma) / (2*sigma - 1) */ arb_set_si(x1, sigma); arb_zeta(x1, x1, prec); arb_mul_2exp_si(x1, x1, 2); arb_div_si(x1, x1, 2*sigma - 1, prec); /* x2 = pi^((-3-2*sigma)/4) */ arb_inv(x2, pi, prec); arb_root_ui(x2, x2, 4, prec); arb_pow_ui(x2, x2, 3 + 2*sigma, prec); /* x3 = (2*sigma-1)^2 / (8*H^2) */ arb_set_si(x3, 2*sigma - 1); arb_div(x3, x3, H, prec); arb_sqr(x3, x3, prec); arb_mul_2exp_si(x3, x3, -3); /* x4 = pi*A*(2*sigma-1)/2 */ arb_mul_si(x4, pi, A*(2*sigma-1), prec); arb_mul_2exp_si(x4, x4, -1); /* res = x1*x2*exp(x3 - x4) */ arb_sub(res, x3, x4, prec); arb_exp(res, res, prec); arb_mul(res, res, x1, prec); arb_mul(res, res, x2, prec); arb_clear(pi); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); } /* c2 = 8*pi^(1/4) */ static void _pre_i_c2(arb_t res, slong prec) { arb_t pi; arb_init(pi); arb_const_pi(pi, prec); arb_root_ui(res, pi, 4, prec); arb_mul_2exp_si(res, res, 3); arb_clear(pi); } void acb_dirichlet_platt_i_precomp_init(acb_dirichlet_platt_i_precomp_t pre, slong A, const arb_t H, slong sigma, slong prec) { arb_init(&pre->c1); arb_init(&pre->c2); _pre_i_c1(&pre->c1, A, H, sigma, prec); _pre_i_c2(&pre->c2, prec); } void acb_dirichlet_platt_i_precomp_clear(acb_dirichlet_platt_i_precomp_t pre) { arb_clear(&pre->c1); arb_clear(&pre->c2); } void acb_dirichlet_platt_i_bound_precomp(arb_t res, const acb_dirichlet_platt_i_precomp_t pre_i, const acb_dirichlet_platt_c_precomp_t pre_c, const arb_t t0, slong A, const arb_t H, slong sigma, slong prec) { arb_t pi, cbound, x1, x2, x3, x4, x5; arb_init(pi); arb_init(cbound); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_init(x5); arb_const_pi(pi, prec); /* x1 = (1 - 4*t0^2)/(8*H^2) */ arb_sqr(x1, t0, prec); arb_mul_2exp_si(x1, x1, 2); arb_sub_ui(x1, x1, 1, prec); arb_neg(x1, x1); arb_div(x1, x1, H, prec); arb_div(x1, x1, H, prec); arb_mul_2exp_si(x1, x1, -3); /* x2 = pi*A/2 */ arb_mul_si(x2, pi, A, prec); arb_mul_2exp_si(x2, x2, -1); /* x3 = exp(x1 - x2) */ arb_sub(x3, x1, x2, prec); arb_exp(x3, x3, prec); acb_dirichlet_platt_c_bound_precomp( cbound, pre_c, sigma, t0, H, 0, prec); /* res = c1*cbound + c2*x3 */ arb_mul(x4, &pre_i->c1, cbound, prec); arb_mul(x5, &pre_i->c2, x3, prec); arb_add(res, x4, x5, prec); arb_clear(pi); arb_clear(cbound); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); arb_clear(x5); } void acb_dirichlet_platt_i_bound(arb_t res, const arb_t t0, slong A, const arb_t H, slong sigma, slong prec) { acb_dirichlet_platt_c_precomp_t pre_c; acb_dirichlet_platt_i_precomp_t pre_i; acb_dirichlet_platt_c_precomp_init(pre_c, sigma, H, 0, prec); acb_dirichlet_platt_i_precomp_init(pre_i, A, H, sigma, prec); acb_dirichlet_platt_i_bound_precomp( res, pre_i, pre_c, t0, A, H, sigma, prec); acb_dirichlet_platt_c_precomp_clear(pre_c); acb_dirichlet_platt_i_precomp_clear(pre_i); } flint-3.1.3/src/acb_dirichlet/platt_lemma_32.c000066400000000000000000000023501461254215100211450ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* out = 2*pi^(5/4)*exp(1/(8*h^2) - (t0^2)/(2*h^2) - pi*x) */ void acb_dirichlet_platt_lemma_32(arb_t out, const arb_t h, const arb_t t0, const arb_t x, slong prec) { arb_t pi, one_fourth; arb_t x1, x2; arb_init(pi); arb_init(one_fourth); arb_init(x1); arb_init(x2); arb_const_pi(pi, prec); arb_set_d(one_fourth, 0.25); arb_set_d(x1, 1.25); arb_pow(x1, pi, x1, prec); arb_mul_2exp_si(x1, x1, 1); arb_sqr(x2, t0, prec); arb_sub(x2, x2, one_fourth, prec); arb_div(x2, x2, h, prec); arb_div(x2, x2, h, prec); arb_mul_2exp_si(x2, x2, -1); arb_mul(out, pi, x, prec); arb_add(out, out, x2, prec); arb_neg(out, out); arb_exp(out, out, prec); arb_mul(out, out, x1, prec); arb_clear(pi); arb_clear(one_fourth); arb_clear(x1); arb_clear(x2); } flint-3.1.3/src/acb_dirichlet/platt_lemma_A11.c000066400000000000000000000101151461254215100212410ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "arb_hypgeom.h" static void _platt_lemma_A11_X(arb_t out, const arb_t t0, const arb_t h, slong B, const arb_t beta, slong prec) { arb_t x1, x2; arb_init(x1); arb_init(x2); arb_set_si(x1, B); arb_mul_2exp_si(x1, x1, -1); arb_add(x1, x1, t0, prec); arb_pow(x1, x1, beta, prec); arb_set_si(x2, B); arb_div(x2, x2, h, prec); arb_sqr(x2, x2, prec); arb_mul_2exp_si(x2, x2, -3); arb_neg(x2, x2); arb_exp(x2, x2, prec); arb_mul(out, x1, x2, prec); arb_clear(x1); arb_clear(x2); } static void _platt_lemma_A11_Y(arb_t out, const arb_t t0, const arb_t h, slong B, const arb_t beta, slong prec) { arb_t x1, x2, x3, x4, x5; arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_init(x5); arb_rsqrt_ui(x1, 2, prec); arb_pow(x2, t0, beta, prec); arb_one(x3); arb_mul_2exp_si(x3, x3, -1); arb_set_si(x4, B); arb_div(x4, x4, h, prec); arb_sqr(x4, x4, prec); arb_mul_2exp_si(x4, x4, -3); arb_hypgeom_gamma_upper(x5, x3, x4, 0, prec); arb_mul(out, x1, x2, prec); arb_mul(out, out, x5, prec); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); arb_clear(x5); } static void _platt_lemma_A11_Z(arb_t out, const arb_t t0, const arb_t h, const arb_t beta, slong prec) { arb_t two; arb_t x1, x2, x3, x4, x5; arb_init(two); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_init(x5); arb_set_ui(two, 2); arb_sub_ui(x1, beta, 1, prec); arb_mul_2exp_si(x1, x1, -1); arb_pow(x1, two, x1, prec); arb_pow(x2, h, beta, prec); arb_add_ui(x3, beta, 1, prec); arb_mul_2exp_si(x3, x3, -1); arb_div(x4, t0, h, prec); arb_sqr(x4, x4, prec); arb_mul_2exp_si(x4, x4, -1); arb_hypgeom_gamma_upper(x5, x3, x4, 0, prec); arb_mul(out, x1, x2, prec); arb_mul(out, out, x5, prec); arb_clear(two); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); arb_clear(x5); } static int _platt_lemma_A11_constraint(const arb_t t0, const arb_t h, slong B, const arb_t beta, slong prec) { int result; arb_t a, b, expe; arb_init(a); arb_init(b); arb_init(expe); /* expe = exp(e) */ arb_const_e(expe, prec); arb_exp(expe, expe, prec); /* a = beta*h^2 / t0 */ arb_sqr(a, h, prec); arb_mul(a, a, beta, prec); arb_div(a, a, t0, prec); /* b = B/2 */ arb_set_si(b, B); arb_mul_2exp_si(b, b, -1); result = arb_le(a, b) && arb_le(b, t0) && arb_gt(t0, expe); arb_clear(a); arb_clear(b); arb_clear(expe); return result; } void acb_dirichlet_platt_lemma_A11(arb_t out, const arb_t t0, const arb_t h, slong B, slong prec) { arb_t beta; arb_init(beta); acb_dirichlet_platt_beta(beta, t0, prec); if (_platt_lemma_A11_constraint(t0, h, B, beta, prec)) { arb_t X, Y, Z; arb_t x1, x2; arb_init(X); arb_init(Y); arb_init(Z); arb_init(x1); arb_init(x2); _platt_lemma_A11_X(X, t0, h, B, beta, prec); _platt_lemma_A11_Y(Y, t0, h, B, beta, prec); _platt_lemma_A11_Z(Z, t0, h, beta, prec); arb_set_ui(x1, 2); arb_pow(x1, x1, beta, prec); arb_mul(x1, x1, h, prec); arb_div_si(x1, x1, B, prec); arb_add(x2, Y, Z, prec); arb_mul(x2, x2, x1, prec); arb_add(x2, x2, X, prec); arb_mul_ui(x2, x2, 6, prec); arb_set(out, x2); arb_clear(X); arb_clear(Y); arb_clear(Z); arb_clear(x1); arb_clear(x2); } else { arb_zero_pm_inf(out); } arb_clear(beta); } flint-3.1.3/src/acb_dirichlet/platt_lemma_A5.c000066400000000000000000000040661461254215100211740ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "arb_hypgeom.h" /* Lemma A5 requires B > h*sqrt(k) */ static int _platt_lemma_A5_constraint(slong B, const arb_t h, slong k, slong prec) { int result; arb_t lhs, rhs; arb_init(rhs); arb_init(lhs); arb_set_si(lhs, B); arb_sqrt_ui(rhs, (ulong) k, prec); arb_mul(rhs, rhs, h, prec); result = arb_gt(lhs, rhs); arb_clear(rhs); arb_clear(lhs); return result; } void acb_dirichlet_platt_lemma_A5(arb_t out, slong B, const arb_t h, slong k, slong prec) { arb_t a, b; arb_t x1, x2, x3, x4, x5, x6; if (!_platt_lemma_A5_constraint(B, h, k, prec)) { arb_zero_pm_inf(out); return; } arb_init(a); arb_init(b); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_init(x5); arb_init(x6); arb_const_pi(x1, prec); arb_mul_si(x1, x1, B, prec); arb_pow_ui(x1, x1, (ulong) k, prec); arb_mul_2exp_si(x1, x1, 3); arb_set_si(a, B); arb_div(a, a, h, prec); arb_sqr(a, a, prec); arb_mul_2exp_si(a, a, -3); arb_neg(x2, a); arb_exp(x2, x2, prec); arb_set_si(x3, 3*k - 1); arb_mul_2exp_si(x3, x3, -1); arb_set_ui(x4, 2); arb_pow(x4, x4, x3, prec); arb_set_si(b, k+1); arb_div_si(x5, h, B, prec); arb_pow_ui(x5, x5, (ulong) (k+1), prec); arb_mul_2exp_si(x6, b, -1); arb_hypgeom_gamma_upper(x6, x6, a, 0, prec); arb_mul(out, x4, x5, prec); arb_mul(out, out, x6, prec); arb_add(out, out, x2, prec); arb_mul(out, out, x1, prec); arb_clear(a); arb_clear(b); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); arb_clear(x5); arb_clear(x6); } flint-3.1.3/src/acb_dirichlet/platt_lemma_A7.c000066400000000000000000000075321461254215100211770ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void _platt_lemma_A7_S(arb_t out, slong sigma, const arb_t t0, const arb_t h, slong k, slong A, slong prec) { slong l; arb_t total, summand; arb_t pi, half; arb_t a; arb_t l_factorial, kd2, t02; arb_t x1, x2, x3, x4, x5; arb_init(total); arb_init(summand); arb_init(pi); arb_init(half); arb_init(a); arb_init(l_factorial); arb_init(kd2); arb_init(t02); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_init(x5); arb_one(half); arb_mul_2exp_si(half, half, -1); arb_const_pi(pi, prec); arb_one(l_factorial); arb_set_si(kd2, k); arb_mul_2exp_si(kd2, kd2, -1); arb_sqr(t02, t0, prec); for (l=0; l<=(sigma-1)/2; l++) { if (l > 1) { arb_mul_si(l_factorial, l_factorial, l, prec); } arb_mul_si(a, pi, 4*l+1, prec); arb_mul_si(a, a, A, prec); arb_inv(x1, a, prec); arb_add_ui(x1, x1, 1, prec); arb_add_si(x2, half, 2*l, prec); arb_sqr(x2, x2, prec); arb_add(x2, x2, t02, prec); arb_pow(x2, x2, kd2, prec); arb_div(x2, x2, l_factorial, prec); arb_set_si(x3, 4*l + 1); arb_div(x3, x3, h, prec); arb_sqr(x3, x3, prec); arb_mul_2exp_si(x3, x3, -3); arb_mul_2exp_si(x4, a, -1); arb_sub(x5, x3, x4, prec); arb_exp(x5, x5, prec); arb_mul(summand, x1, x2, prec); arb_mul(summand, summand, x5, prec); arb_add(total, total, summand, prec); } arb_set(out, total); arb_clear(total); arb_clear(summand); arb_clear(pi); arb_clear(half); arb_clear(a); arb_clear(l_factorial); arb_clear(kd2); arb_clear(t02); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); arb_clear(x5); } void acb_dirichlet_platt_lemma_A7(arb_t out, slong sigma, const arb_t t0, const arb_t h, slong k, slong A, slong prec) { arb_t S, C; arb_t pi, a; arb_t x1, x2; arb_t y1, y2, y3, y4; arb_t z1, z2; if (sigma % 2 == 0 || sigma < 3) { arb_zero_pm_inf(out); return; } arb_init(S); arb_init(C); arb_init(pi); arb_init(a); arb_init(x1); arb_init(x2); arb_init(y1); arb_init(y2); arb_init(y3); arb_init(y4); arb_init(z1); arb_init(z2); arb_const_pi(pi, prec); arb_pow_ui(x1, pi, (ulong) (k+1), prec); arb_mul_2exp_si(x1, x1, k+3); arb_div(x2, t0, h, prec); arb_sqr(x2, x2, prec); arb_mul_2exp_si(x2, x2, -1); arb_neg(x2, x2); arb_exp(x2, x2, prec); _platt_lemma_A7_S(S, sigma, t0, h, k, A, prec); arb_mul(z1, x1, x2, prec); arb_mul(z1, z1, S, prec); arb_mul_si(a, pi, 2*sigma-1, prec); arb_mul_si(a, a, A, prec); arb_inv(y1, a, prec); arb_add_ui(y1, y1, 1, prec); arb_set_si(y2, 2*sigma + 1); arb_div(y2, y2, h, prec); arb_sqr(y2, y2, prec); arb_mul_2exp_si(y2, y2, -3); arb_mul_2exp_si(y3, a, -1); arb_sub(y4, y2, y3, prec); arb_exp(y4, y4, prec); acb_dirichlet_platt_c_bound(C, sigma, t0, h, k, prec); arb_mul(z2, y1, y4, prec); arb_mul(z2, z2, C, prec); arb_mul_2exp_si(z2, z2, 1); arb_add(out, z1, z2, prec); arb_clear(S); arb_clear(C); arb_clear(pi); arb_clear(a); arb_clear(x1); arb_clear(x2); arb_clear(y1); arb_clear(y2); arb_clear(y3); arb_clear(y4); arb_clear(z1); arb_clear(z2); } flint-3.1.3/src/acb_dirichlet/platt_lemma_A9.c000066400000000000000000000064001461254215100211720ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void _arb_pow_d(arb_t z, const arb_t x, double d, slong prec) { arb_t u; arb_init(u); arb_set_d(u, d); arb_pow(z, x, u, prec); arb_clear(u); } static void _platt_lemma_A9_a(arb_t out, slong sigma, const arb_t t0, const arb_t h, slong A, slong prec) { arb_t a, pi, C; arb_t y1, y2, y3, y4; arb_t z1, z2, z3; arb_init(a); arb_init(pi); arb_init(C); arb_init(y1); arb_init(y2); arb_init(y3); arb_init(y4); arb_init(z1); arb_init(z2); arb_init(z3); arb_const_pi(pi, prec); arb_mul_si(a, pi, 2*sigma-1, prec); arb_mul_si(a, a, A, prec); arb_inv(y1, a, prec); arb_add_ui(y1, y1, 1, prec); arb_set_si(y2, 2*sigma - 1); arb_div(y2, y2, h, prec); arb_sqr(y2, y2, prec); arb_mul_2exp_si(y2, y2, -3); arb_mul_2exp_si(y3, a, -1); arb_sub(y4, y2, y3, prec); arb_exp(y4, y4, prec); acb_dirichlet_platt_c_bound(C, sigma, t0, h, 0, prec); arb_zeta_ui(z1, (ulong) sigma, prec); arb_mul_2exp_si(z1, z1, 1); arb_set_si(z2, 1-2*sigma); arb_mul_2exp_si(z2, z2, -2); arb_pow(z2, pi, z2, prec); arb_sub(z3, y2, y3, prec); arb_exp(z3, z3, prec); arb_mul(out, z1, z2, prec); arb_mul(out, out, z3, prec); arb_mul(out, out, C, prec); arb_mul(out, out, y1, prec); arb_clear(a); arb_clear(pi); arb_clear(C); arb_clear(y1); arb_clear(y2); arb_clear(y3); arb_clear(y4); arb_clear(z1); arb_clear(z2); arb_clear(z3); } static void _platt_lemma_A9_b(arb_t out, const arb_t t0, const arb_t h, slong A, slong prec) { arb_t pi; arb_t x1, x2, x3, x4, x5; arb_init(pi); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_init(x5); arb_const_pi(pi, prec); _arb_pow_d(x1, pi, 1.25, prec); arb_mul_2exp_si(x1, x1, 2); arb_sqr(x2, t0, prec); arb_mul_2exp_si(x2, x2, 2); arb_sub_ui(x2, x2, 1, prec); arb_neg(x2, x2); arb_div(x2, x2, h, prec); arb_div(x2, x2, h, prec); arb_mul_2exp_si(x2, x2, -3); arb_mul_si(x3, pi, A, prec); arb_mul_2exp_si(x3, x3, -1); arb_mul_si(x4, pi, A, prec); arb_inv(x4, x4, prec); arb_add_ui(x4, x4, 1, prec); arb_sub(x5, x2, x3, prec); arb_exp(x5, x5, prec); arb_mul(out, x1, x4, prec); arb_mul(out, out, x5, prec); arb_clear(pi); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); arb_clear(x5); } void acb_dirichlet_platt_lemma_A9(arb_t out, slong sigma, const arb_t t0, const arb_t h, slong A, slong prec) { arb_t a, b; if (sigma % 2 == 0 || sigma < 3) { arb_zero_pm_inf(out); return; } arb_init(a); arb_init(b); _platt_lemma_A9_a(a, sigma, t0, h, A, prec); _platt_lemma_A9_b(b, t0, h, A, prec); arb_add(out, a, b, prec); arb_clear(a); arb_clear(b); } flint-3.1.3/src/acb_dirichlet/platt_lemma_B1.c000066400000000000000000000026541461254215100211720ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_platt_lemma_B1(arb_t out, slong sigma, const arb_t t0, const arb_t h, const fmpz_t J, slong prec) { arb_t pi, C, x1, x2, x3, Ja; if (sigma % 2 == 0 || sigma < 3) { arb_zero_pm_inf(out); return; } arb_init(pi); arb_init(C); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(Ja); arb_const_pi(pi, prec); acb_dirichlet_platt_c_bound(C, sigma, t0, h, 0, prec); arb_set_fmpz(Ja, J); arb_set_si(x1, 2*sigma - 1); arb_div(x1, x1, h, prec); arb_sqr(x1, x1, prec); arb_mul_2exp_si(x1, x1, -3); arb_exp(x1, x1, prec); arb_set_si(x2, 1 - 2*sigma); arb_mul_2exp_si(x2, x2, -2); arb_pow(x2, pi, x2, prec); arb_set_si(x3, 1 - sigma); arb_pow(x3, Ja, x3, prec); arb_div_si(x3, x3, sigma - 1, prec); arb_mul(out, x1, x2, prec); arb_mul(out, out, x3, prec); arb_mul(out, out, C, prec); arb_clear(pi); arb_clear(C); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(Ja); } flint-3.1.3/src/acb_dirichlet/platt_lemma_B2.c000066400000000000000000000026351461254215100211720ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_platt_lemma_B2(arb_t out, slong K, const arb_t h, const arb_t xi, slong prec) { arb_t two, half, pi; arb_t x1, x2, x3, x4, x5; arb_init(two); arb_init(half); arb_init(pi); arb_init(x1); arb_init(x2); arb_init(x3); arb_init(x4); arb_init(x5); arb_set_ui(two, 2); arb_mul_2exp_si(half, two, -2); arb_const_pi(pi, prec); arb_set_si(x1, K + 5); arb_mul_2exp_si(x1, x1, -1); arb_pow(x1, two, x1, prec); arb_add_si(x2, half, K, prec); arb_pow(x2, pi, x2, prec); arb_pow_ui(x3, h, (ulong) (K + 1), prec); arb_pow_ui(x4, xi, (ulong) K, prec); arb_set_si(x5, K + 2); arb_mul_2exp_si(x5, x5, -1); arb_rgamma(x5, x5, prec); arb_mul(out, x1, x2, prec); arb_mul(out, out, x3, prec); arb_mul(out, out, x4, prec); arb_mul(out, out, x5, prec); arb_clear(two); arb_clear(half); arb_clear(pi); arb_clear(x1); arb_clear(x2); arb_clear(x3); arb_clear(x4); arb_clear(x5); } flint-3.1.3/src/acb_dirichlet/platt_local_hardy_z_zeros.c000066400000000000000000001152761461254215100236160ustar00rootroot00000000000000/* Copyright (C) 2010 Juan Arias de Reyna Copyright (C) 2019 D.H.J. Polymath Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "arb_calc.h" #ifdef __GNUC__ # define exp __builtin_exp #else # include #endif static const slong LOOPCOUNT = 4; /* * For a detailed explanation of the variant of Turing's method * implemented in this file, see: * * J. Arias de Reyna, "Programs for Riemann's zeta function", (J. A. J. van * Vonderen, Ed.) Leven met getallen : liber amicorum ter gelegenheid van de * pensionering van Herman te Riele, CWI (2012) 102-112, * https://ir.cwi.nl/pub/19724 */ /* * This structure describes the local context in which Platt's scaled Lambda * function f may be estimated by Gaussian-windowed Whittaker-Shannon * interpolation. */ typedef struct { /* grid location and shape */ fmpz T; /* midpoint */ slong A; /* resolution */ slong B; /* width */ /* interpolation tuning parameters */ slong Ns_max; /* max number of support points per side */ arb_struct H; /* standard deviation of Gaussian window */ slong sigma; arb_ptr p; /* f evaluated at N = A*B points on the grid */ acb_dirichlet_platt_ws_precomp_struct pre; /* precomp interpolation stuff */ } platt_ctx_struct; typedef platt_ctx_struct platt_ctx_t[1]; typedef platt_ctx_struct * platt_ctx_ptr; typedef const platt_ctx_struct * platt_ctx_srcptr; static void platt_ctx_init(platt_ctx_t ctx, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma_grid, slong Ns_max, const arb_t H, slong sigma_interp, slong prec) { fmpz_init(&ctx->T); arb_init(&ctx->H); ctx->p = _arb_vec_init(A*B); ctx->A = A; ctx->B = B; ctx->Ns_max = Ns_max; ctx->sigma = sigma_interp; fmpz_set(&ctx->T, T); arb_set(&ctx->H, H); acb_dirichlet_platt_ws_precomp_init(&ctx->pre, A, H, sigma_interp, prec); acb_dirichlet_platt_multieval(ctx->p, T, A, B, h, J, K, sigma_grid, prec); } static void platt_ctx_clear(platt_ctx_t ctx) { slong N = ctx->A * ctx->B; fmpz_clear(&ctx->T); arb_clear(&ctx->H); _arb_vec_clear(ctx->p, N); acb_dirichlet_platt_ws_precomp_clear(&ctx->pre); } static void platt_ctx_interpolate(arb_t res, arf_t deriv, const platt_ctx_t ctx, const arb_t t0, slong prec) { acb_dirichlet_platt_ws_interpolation_precomp(res, deriv, &ctx->pre, t0, ctx->p, &ctx->T, ctx->A, ctx->B, ctx->Ns_max, &ctx->H, ctx->sigma, prec); } static void platt_ctx_interpolate_arf(arb_t res, arf_t deriv, const platt_ctx_t ctx, const arf_t t0, slong prec) { arb_t t; arb_init(t); arb_set_arf(t, t0); platt_ctx_interpolate(res, deriv, ctx, t, prec); arb_clear(t); } /* * This structure describes a node of a doubly linked list. * Each node represents a height t at which Platt's scaled Lambda function * f(t) has been evaluated by interpolation on a grid. */ typedef struct _zz_node_struct { arf_struct t; /* height t where v = f(t) is evaluated */ arb_struct v; /* f(t) */ fmpz *gram; /* Gram point index or NULL if not a Gram point */ struct _zz_node_struct *prev; struct _zz_node_struct *next; } zz_node_struct; typedef zz_node_struct zz_node_t[1]; typedef zz_node_struct * zz_node_ptr; typedef const zz_node_struct * zz_node_srcptr; static int zz_node_is_gram_node(const zz_node_t p) { return p->gram != NULL; } static int zz_node_sgn(const zz_node_t p) { int s = arb_sgn_nonzero(&p->v); if (!s) { flint_throw(FLINT_ERROR, "unexpectedly imprecise evaluation of f(t)\n"); } return s; } /* Good Gram points are Gram points where sgn(f(g(n)))*(-1)^n > 0. */ static int zz_node_is_good_gram_node(const zz_node_t p) { if (zz_node_is_gram_node(p)) { int s = zz_node_sgn(p); if ((s > 0 && fmpz_is_even(p->gram)) || (s < 0 && fmpz_is_odd(p->gram))) { return 1; } } return 0; } static void zz_node_init(zz_node_t p) { arf_init(&p->t); arb_init(&p->v); arb_indeterminate(&p->v); p->gram = NULL; p->prev = NULL; p->next = NULL; } static void zz_node_clear(zz_node_t p) { arf_clear(&p->t); arb_clear(&p->v); if (p->gram) { fmpz_clear(p->gram); flint_free(p->gram); } p->gram = NULL; p->prev = NULL; p->next = NULL; } static void delete_list_to(zz_node_ptr head, zz_node_srcptr target) { zz_node_ptr u, v; if (head) { if (head->prev) { flint_throw(FLINT_ERROR, "expected the first node in the list\n"); } } u = head; while (u != target) { if (u == NULL) { flint_throw(FLINT_ERROR, "failed to find target within list\n"); } v = u; u = u->next; zz_node_clear(v); flint_free(v); } if (u != NULL) { u->prev = NULL; } } static void delete_list(zz_node_ptr head) { delete_list_to(head, NULL); } /* * Create a node representing an evaluation of the scaled Lambda function * at arbitrary point t. Upon creation the sign of f(t) will * be known with certainty. If this is not possible then NULL is returned. */ static zz_node_ptr create_non_gram_node(const arf_t t, const platt_ctx_t ctx, slong prec) { zz_node_ptr p = flint_malloc(sizeof(zz_node_struct)); zz_node_init(p); arf_set(&p->t, t); platt_ctx_interpolate_arf(&p->v, NULL, ctx, t, prec); if (arb_contains_zero(&p->v)) { zz_node_clear(p); p = NULL; } return p; } /* * Create a node representing an evaluation of the scaled Lambda function * at the nth Gram point g(n). Upon creation a floating point number t will be * assigned to this node, with the property that there are no zeros of the * scaled Lambda function between t and the actual value of g(n). * The sign of f(t) will also be known with certainty, otherwise NULL * is returned. */ static zz_node_ptr create_gram_node(const fmpz_t n, const platt_ctx_t ctx, slong prec) { zz_node_ptr p = NULL; arb_t t, v; acb_t z; arb_init(t); arb_init(v); acb_init(z); acb_dirichlet_gram_point(t, n, NULL, NULL, prec + fmpz_sizeinbase(n, 2)); acb_set_arb(z, t); platt_ctx_interpolate(v, NULL, ctx, t, prec); if (!arb_contains_zero(v)) { /* t contains g(n) and does not contain a zero of the f function */ p = flint_malloc(sizeof(zz_node_struct)); zz_node_init(p); p->gram = flint_malloc(sizeof(fmpz)); fmpz_init(p->gram); fmpz_set(p->gram, n); arf_set(&p->t, arb_midref(t)); arb_set(&p->v, v); } arb_clear(t); arb_clear(v); acb_clear(z); return p; } /* * Count the number of Gram intervals between the Gram point * represented by node a and the Gram point represented by node b. * Traversing the linked list is not necessary because the Gram indices * of nodes a and b can be accessed directly. */ static slong count_gram_intervals(zz_node_srcptr a, zz_node_srcptr b) { slong out = 0; if (!a || !b) { flint_throw(FLINT_ERROR, "a and b must be non-NULL\n"); } if (!zz_node_is_good_gram_node(a) || !zz_node_is_good_gram_node(b)) { flint_throw(FLINT_ERROR, "both nodes must be good Gram points\n"); } else { fmpz_t m; fmpz_init(m); fmpz_sub(m, b->gram, a->gram); out = fmpz_get_si(m); fmpz_clear(m); } return out; } /* * Count the observed number of sign changes of f(t) by traversing * a linked list of evaluated points from node a to node b. */ static slong count_sign_changes(zz_node_srcptr a, zz_node_srcptr b) { zz_node_srcptr p, q; slong n = 0; if (!a || !b) { flint_throw(FLINT_ERROR, "a and b must be non-NULL\n"); } p = a; q = a->next; while (p != b) { if (!q) { flint_throw(FLINT_ERROR, "prematurely reached end of list\n"); } if (zz_node_sgn(p) != zz_node_sgn(q)) { n++; } p = q; q = q->next; } return n; } /* * Modify a linked list that ends with node p, * by appending nodes representing Gram points. * Continue until a 'good' Gram point is found. * Returns nonzero on success. * Sets *out to the last point in the list. */ static int extend_to_next_good_gram_node( zz_node_ptr *out, zz_node_t p, const platt_ctx_t ctx, slong prec) { fmpz_t n; zz_node_ptr q, r; int result = 1; fmpz_init(n); if (!zz_node_is_gram_node(p)) { flint_throw(FLINT_ERROR, "expected to begin at a gram point\n"); } if (p->next) { flint_throw(FLINT_ERROR, "expected to extend from the end of a list\n"); } fmpz_set(n, p->gram); q = p; while (1) { fmpz_add_ui(n, n, 1); r = create_gram_node(n, ctx, prec); if (r) { q->next = r; r->prev = q; q = r; r = NULL; if (zz_node_is_good_gram_node(q)) { break; } } else { result = 0; break; } } fmpz_clear(n); *out = q; return result; } /* * Modify a linked list that begins with node p, * by prepending nodes representing Gram points. * Continue until a 'good' Gram point is found. * Returns nonzero on success. * Sets *out to the first point in the list. */ static int extend_to_prev_good_gram_node(zz_node_ptr *out, zz_node_t p, const platt_ctx_t ctx, slong prec) { fmpz_t n; zz_node_ptr q, r; int result = 1; fmpz_init(n); if (!zz_node_is_gram_node(p)) { flint_throw(FLINT_ERROR, "expected to begin at a gram point\n"); } if (p->prev) { flint_throw(FLINT_ERROR, "expected to extend from the start of a list\n"); } fmpz_set(n, p->gram); q = p; while (1) { fmpz_sub_ui(n, n, 1); r = create_gram_node(n, ctx, prec); if (r) { q->prev = r; r->next = q; q = r; r = NULL; if (zz_node_is_good_gram_node(q)) { break; } } else { result = 0; break; } } fmpz_clear(n); *out = q; return result; } static zz_node_ptr _scan_to_prev_good_gram_node(zz_node_ptr p) { zz_node_ptr u = p->prev; while (u) { if (zz_node_is_good_gram_node(u)) { return u; } u = u->prev; } return NULL; } static zz_node_ptr scan_to_prev_good_gram_node(zz_node_ptr p, slong count) { slong i; zz_node_ptr u = p; for (i = 0; i < count; i++) { if ((u = _scan_to_prev_good_gram_node(u)) == NULL) { return NULL; } } return u; } static zz_node_ptr _scan_to_next_good_gram_node(zz_node_ptr p) { zz_node_ptr u = p->next; while (u) { if (zz_node_is_good_gram_node(u)) { return u; } u = u->next; } return NULL; } static zz_node_ptr scan_to_next_good_gram_node(zz_node_ptr p, slong count) { slong i; zz_node_ptr u = p; for (i = 0; i < count; i++) { if ((u = _scan_to_next_good_gram_node(u)) == NULL) { return NULL; } } return u; } /* * res = (x1*w1 + x2*w2) / (w1 + w2) * Undefined if weights are not nonnegative. * If w1 and w2 are zero, the resulting interval contains x1 and x2. */ static void _weighted_arithmetic_mean(arb_t res, const arf_t x1, const arf_t x2, const arb_t w1, const arb_t w2, slong prec) { if (!arb_is_nonnegative(w1) || !arb_is_nonnegative(w2)) { arb_indeterminate(res); } else if (arb_is_zero(w1) && arb_is_zero(w2)) { arb_set_interval_arf(res, x1, x2, prec); } else if (arb_is_zero(w1)) { arb_set_arf(res, x2); } else if (arb_is_zero(w2)) { arb_set_arf(res, x1); } else if (arb_is_exact(w1) && arb_is_exact(w2)) { arb_t a, b; arb_init(a); arb_init(b); arb_mul_arf(a, w1, x1, prec); arb_addmul_arf(a, w2, x2, prec); arb_add(b, w1, w2, prec); arb_div(res, a, b, prec); arb_clear(a); arb_clear(b); } else { arb_t a, b, r1, r2; arb_init(a); arb_init(b); arb_init(r1); arb_init(r2); arb_zero(a); arb_zero(b); arb_get_lbound_arf(arb_midref(a), w1, prec); arb_get_ubound_arf(arb_midref(b), w2, prec); _weighted_arithmetic_mean(r1, x1, x2, a, b, prec); arb_zero(a); arb_zero(b); arb_get_ubound_arf(arb_midref(a), w1, prec); arb_get_lbound_arf(arb_midref(b), w2, prec); _weighted_arithmetic_mean(r2, x1, x2, a, b, prec); arb_union(res, r1, r2, prec); arb_clear(a); arb_clear(b); arb_clear(r1); arb_clear(r2); } } /* * Split the interval (t1, t2) into the intervals (t1, out) and (out, t2) * in an attempt to increase the number of observed sign changes of f(t) * between endpoints. * v1 and v2 are the scaled Lambda function values at t1 and t2 respectively. * sign1 and sign2 are the signs of v1 and v2 respectively. */ static void split_interval(arb_t out, const arf_t t1, const arb_t v1, slong sign1, const arf_t t2, const arb_t v2, slong sign2, slong prec) { if (sign1 == sign2) { /* * out = (sqrt(v2/v1)*t1 + t2) / (sqrt(v2/v1) + 1) * We have f(t1)=v1, f(t2)=v2 where v1 and v2 have the same sign, * and we want to guess t between t1 and t2 so that f(t) * has the opposite sign. Try the vertex of a parabola that would touch * f(t)=0 between t1 and t2 and would pass through (t1,v1) and (t2,v2). */ arb_t w1, w2; arb_init(w1); arb_init(w2); arb_abs(w1, v2); /* w1, v2 is deliberate */ arb_sqrt(w1, w1, prec); arb_abs(w2, v1); /* w2, v1 is deliberate */ arb_sqrt(w2, w2, prec); _weighted_arithmetic_mean(out, t1, t2, w1, w2, prec); arb_clear(w1); arb_clear(w2); } else { /* * out = (t1 + t2) / 2 * There is already one sign change in this interval. * To find additional sign changes we would need to evaluate * at least two more points in the interval, * so begin by just splitting the interval in half at the midpoint. */ arb_set_arf(out, t1); arb_add_arf(out, out, t2, prec); arb_mul_2exp_si(out, out, -1); } } /* * Add a new node between each pair of existing nodes in the linked list * of evaluated values of t, within the sublist demarcated by nodes a and b. * Returns nonzero on success. */ static int intercalate(const platt_ctx_t ctx, zz_node_t a, zz_node_t b, slong prec) { arb_t t; zz_node_ptr q, r, mid_node; int result = 1; if (a == NULL || b == NULL) { flint_throw(FLINT_ERROR, "a and b must be non-NULL\n"); } if (!zz_node_is_good_gram_node(a) || !zz_node_is_good_gram_node(b)) { flint_throw(FLINT_ERROR, "a and b must represent good Gram points\n"); } if (a == b) return result; arb_init(t); q = a; r = a->next; while (q != b) { if (!r) { flint_throw(FLINT_ERROR, "prematurely reached end of list\n"); } split_interval(t, &q->t, &q->v, zz_node_sgn(q), &r->t, &r->v, zz_node_sgn(r), prec); if (arb_contains_arf(t, &q->t) || arb_contains_arf(t, &r->t)) { result = 0; break; } mid_node = create_non_gram_node(arb_midref(t), ctx, prec); if (!mid_node) { result = 0; break; } q->next = mid_node; mid_node->prev = q; mid_node->next = r; r->prev = mid_node; q = r; r = r->next; } arb_clear(t); return result; } /* * Given a linked sublist beginning at U and ending at V defining function * evaluations at points that fully separate zeros of f(t) in the vicinity * of the nth zero, traverse the list until the nth zero is found. * Continue traversing the list until len consecutive isolating intervals * have been found, or until the end of the sublist is reached. * Return the number of isolated zeros found, starting at the nth zero. */ static slong count_up_separated_zeros(arf_interval_ptr res, zz_node_srcptr U, zz_node_srcptr V, const fmpz_t n, slong len) { if (len <= 0) { return 0; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "nonpositive indices of zeros are not supported\n"); } else if (U == NULL || V == NULL) { flint_throw(FLINT_ERROR, "U and V must not be NULL\n"); } if (!zz_node_is_good_gram_node(U) || !zz_node_is_good_gram_node(V)) { flint_throw(FLINT_ERROR, "U and V must be good Gram points\n"); } else { slong i = 0; zz_node_srcptr p = U; fmpz_t N, k; fmpz_init(N); fmpz_init(k); fmpz_add_ui(N, p->gram, 1); fmpz_set(k, n); while (p != V) { if (!p->next) { flint_throw(FLINT_ERROR, "prematurely reached end of list\n"); } if (zz_node_sgn(p) != zz_node_sgn(p->next)) { fmpz_add_ui(N, N, 1); if (fmpz_equal(N, k)) { arf_set(&res[i].a, &p->t); arf_set(&res[i].b, &p->next->t); fmpz_add_ui(k, k, 1); i++; if (i == len) break; } } p = p->next; } fmpz_clear(k); return i; } return 0; } /* * Create a small linked list defining the Gram block that is expected * to contain the nth zero according to the Gram heuristic. * Returns 0 if unable to create the Gram block. * The output node *p is the first node in the Gram block on success * or NULL on failure. * The output node *q is the last node in the Gram block on success * or NULL on failure. * Success does not necessarily mean that the Gram block contains the nth zero. */ static int create_initial_gram_block(zz_node_ptr *p, zz_node_ptr *q, const platt_ctx_t ctx, const fmpz_t n, slong prec) { zz_node_ptr u, v; fmpz_t k; slong result = 1; fmpz_init(k); *p = NULL; *q = NULL; fmpz_sub_ui(k, n, 2); u = create_gram_node(k, ctx, prec); if (!u) { result = 0; goto finish; } fmpz_sub_ui(k, n, 1); v = create_gram_node(k, ctx, prec); if (!v) { result = 0; goto finish; } u->next = v; v->prev = u; if (!zz_node_is_good_gram_node(u)) { if (!extend_to_prev_good_gram_node(&u, u, ctx, prec)) { result = 0; goto finish; } } if (!zz_node_is_good_gram_node(v)) { if (!extend_to_next_good_gram_node(&v, v, ctx, prec)) { result = 0; goto finish; } } finish: if (result) { *p = u; *q = v; } else { delete_list(u); } return result; } /* * On failure returns 0 and output variables are NULL or zero. * The output variable *pu is the head of the output list. * The output variable *pv is the tail of the output list. * The first *pbound Gram blocks in the output list are certified as 'good', * and the list probably contains a few more trailing Gram blocks (not * necessarily certified as 'good'). */ static int create_initial_double_superblock(zz_node_ptr *pu, zz_node_ptr *pv, slong *pbound, const platt_ctx_t ctx, const fmpz_t n, slong prec) { zz_node_ptr p, q, u, v; slong i, k, bound, zn; slong good_block_count; slong result = 1; *pu = NULL; *pv = NULL; *pbound = 0; if (!create_initial_gram_block(&p, &q, ctx, n, prec)) { result = 0; goto finish; } /* * Add blocks in the forward direction until we have at least k Gram blocks, * where k is the turing method bound. * Note that these blocks are not necessarily good Gram blocks * and will not necessarily belong to the initial double superblock. * The bound may increase as the list is extended. */ for (k = 1; k < acb_dirichlet_turing_method_bound(q->gram); k++) { if (!extend_to_next_good_gram_node(&q, q, ctx, prec)) { result = 0; goto finish; } } bound = k; /* * Scan the list backwards, attempting to certify blocks as 'good' * and tracking the current number of consecutive good Gram blocks. */ good_block_count = 0; v = q; while ((u = _scan_to_prev_good_gram_node(v)) != NULL) { zn = count_gram_intervals(u, v); for (i = 0; i < LOOPCOUNT && count_sign_changes(u, v) < zn; i++) { if (!intercalate(ctx, u, v, prec)) { result = 0; goto finish; } } if (count_sign_changes(u, v) >= zn) { good_block_count++; } else { good_block_count = 0; } v = u; } if (v != p) { flint_throw(FLINT_ERROR, "unexpected endpoint of backwards scan\n"); } /* * Add blocks in the backwards direction until the number * of consecutive good Gram blocks is twice the computed bound. */ while (good_block_count < 2*bound) { if (!extend_to_prev_good_gram_node(&p, v, ctx, prec)) { result = 0; goto finish; } zn = count_gram_intervals(p, v); for (i = 0; i < LOOPCOUNT && count_sign_changes(p, v) < zn; i++) { if (!intercalate(ctx, p, v, prec)) { result = 0; goto finish; } } if (count_sign_changes(p, v) >= zn) { good_block_count++; } else { good_block_count = 0; } v = p; } finish: if (result) { *pu = p; *pv = q; *pbound = bound; } else { delete_list(p); } return result; } static slong _isolate_zeros(arf_interval_ptr res, const platt_ctx_t ctx, const fmpz_t n, slong len, slong prec) { zz_node_ptr x, y; /* Anchor nodes where N(t) is known */ zz_node_ptr u, v; /* For certifying Gram nodes as 'good' */ zz_node_ptr p, q; fmpz_t nnext; slong i, k, bound, zn, zc, zeros_count; fmpz_init(nnext); fmpz_set(nnext, n); p = NULL; zeros_count = 0; if (!create_initial_double_superblock(&p, &q, &bound, ctx, n, prec)) { goto finish; } /* * Set the anchor to the central good Gram node of the * initial double superblock. * Delete the nodes in the list before the anchor. */ x = scan_to_next_good_gram_node(p, bound); if (x == NULL) { flint_throw(FLINT_ERROR, "missing or incomplete initial block\n"); } delete_list_to(p, x); p = x; /* * Set v to the forward-most node in the list, * and track the number of consecutive good Gram blocks at that point. */ v = scan_to_next_good_gram_node(p, bound); if (v == NULL) { flint_throw(FLINT_ERROR, "missing or incomplete initial block\n"); } k = 2*bound; u = v; while ((v = _scan_to_next_good_gram_node(v)) != NULL) { zn = count_gram_intervals(u, v); if (count_sign_changes(u, v) >= zn) { k++; } else { k = 0; } u = v; } if (u != q) { flint_throw(FLINT_ERROR, "failed to scan the initial list\n"); } v = u; /* * Iterate through Gram blocks. The central good Gram point in each * stretch of 2*bound consecutive good Gram blocks is an 'anchor' point * where the number of zeros less than that point is known. * Therefore the number of zeros between each pair of anchor points * is known. As anchor points are certified, isolate the zeros falling * between each pair. */ while (1) { u = v; if (!extend_to_next_good_gram_node(&v, v, ctx, prec)) { goto finish; } zn = count_gram_intervals(u, v); for (i = 0; i < LOOPCOUNT && count_sign_changes(u, v) < zn; i++) { if (!intercalate(ctx, u, v, prec)) { goto finish; } } if (count_sign_changes(u, v) >= zn) { k++; } else { k = 0; } bound = acb_dirichlet_turing_method_bound(v->gram); if (k >= 2*bound && fmpz_cmp(x->gram, v->gram) < 0) { /* There are exactly zn zeros between the anchor points x and y. */ y = scan_to_prev_good_gram_node(v, bound); if (!y) { flint_throw(FLINT_ERROR, "failed to scan backwards to anchor point\n"); } zn = count_gram_intervals(x, y); while (count_sign_changes(x, y) < zn) { if (!intercalate(ctx, x, y, prec)) { goto finish; } } zc = count_up_separated_zeros(res + zeros_count, x, y, nnext, len - zeros_count); if (zc < 0 || zc > len - zeros_count) { flint_throw(FLINT_ERROR, "unexpected number of isolated zeros\n"); } zeros_count += zc; if (zeros_count == len) { goto finish; } fmpz_add_ui(nnext, nnext, zc); x = y; delete_list_to(p, x); p = x; } } finish: fmpz_clear(nnext); delete_list(p); return zeros_count; } slong _acb_dirichlet_platt_isolate_local_hardy_z_zeros( arf_interval_ptr res, const fmpz_t n, slong len, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma_grid, slong Ns_max, const arb_t H, slong sigma_interp, slong prec) { slong zeros_count; platt_ctx_t ctx; platt_ctx_init(ctx, T, A, B, h, J, K, sigma_grid, Ns_max, H, sigma_interp, prec); zeros_count = _isolate_zeros(res, ctx, n, len, prec); platt_ctx_clear(ctx); return zeros_count; } static void _refine_local_hardy_z_zero_illinois(arb_t res, const platt_ctx_t ctx, const arf_t ra, const arf_t rb, slong prec) { arf_t a, b, fa, fb, c, fc, t; arb_t z; slong k, nmag, abs_tol, wp; int asign, bsign, csign; arf_init(a); arf_init(b); arf_init(c); arf_init(fa); arf_init(fb); arf_init(fc); arf_init(t); arb_init(z); arf_set(a, ra); arf_set(b, rb); nmag = arf_abs_bound_lt_2exp_si(b); abs_tol = nmag - prec - 4; wp = prec + nmag + 8; platt_ctx_interpolate_arf(z, NULL, ctx, a, wp); asign = arb_sgn_nonzero(z); arf_set(fa, arb_midref(z)); platt_ctx_interpolate_arf(z, NULL, ctx, b, wp); bsign = arb_sgn_nonzero(z); arf_set(fb, arb_midref(z)); if (!asign || !bsign) { flint_throw(FLINT_ERROR, "the function evaluations at the endpoints of the initial " "interval must not contain zero\n"); } if (asign == bsign) { flint_throw(FLINT_ERROR, "isolate a zero before bisecting the interval\n"); } for (k = 0; k < 40; k++) { /* c = a - fa * (b - a) / (fb - fa) */ arf_sub(c, b, a, wp, ARF_RND_NEAR); arf_sub(t, fb, fa, wp, ARF_RND_NEAR); arf_div(c, c, t, wp, ARF_RND_NEAR); arf_mul(c, c, fa, wp, ARF_RND_NEAR); arf_sub(c, a, c, wp, ARF_RND_NEAR); /* if c is not sandwiched between a and b, fall back to one bisection step */ if (!arf_is_finite(c) || !((arf_cmp(a, c) < 0 && arf_cmp(c, b) < 0) || (arf_cmp(b, c) < 0 && arf_cmp(c, a) < 0))) { /* flint_printf("no sandwich (k = %wd)\n", k); */ arf_add(c, a, b, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_2exp_si(c, c, -1); } platt_ctx_interpolate_arf(z, NULL, ctx, c, wp); csign = arb_sgn_nonzero(z); /* If the guess is close enough to a zero that the sign * cannot be determined, then use the derivative to * make an appropriately small interval around the guess. */ if (!csign) { arf_t deriv, aprime, bprime, faprime, fbprime, err, delta; slong i, aprimesign, bprimesign; arf_init(deriv); arf_init(aprime); arf_init(bprime); arf_init(faprime); arf_init(fbprime); arf_init(err); arf_init(delta); arf_set_mag(err, arb_radref(z)); platt_ctx_interpolate_arf(NULL, deriv, ctx, c, wp); arf_div(delta, err, deriv, wp, ARF_RND_NEAR); arf_mul_si(delta, delta, 3, wp, ARF_RND_NEAR); arf_mul_2exp_si(delta, delta, -1); arf_set(aprime, c); arf_set(bprime, c); /* When the context allows the interval endpoints to * be evaluated to relatively high precision, * this should not require more than one or two iterations. */ for (i = 0; i < 5; i++) { arf_sub(aprime, aprime, delta, wp, ARF_RND_DOWN); arf_add(bprime, bprime, delta, wp, ARF_RND_UP); if (arf_cmp(a, b) < 0) { if (arf_cmp(aprime, a) < 0) arf_set(aprime, a); if (arf_cmp(b, bprime) < 0) arf_set(bprime, b); } else { if (arf_cmp(aprime, b) < 0) arf_set(aprime, b); if (arf_cmp(a, bprime) < 0) arf_set(bprime, a); } platt_ctx_interpolate_arf(z, NULL, ctx, aprime, wp); arf_set(faprime, arb_midref(z)); aprimesign = arb_sgn_nonzero(z); platt_ctx_interpolate_arf(z, NULL, ctx, bprime, wp); arf_set(fbprime, arb_midref(z)); bprimesign = arb_sgn_nonzero(z); if (aprimesign && bprimesign && aprimesign != bprimesign) { arf_set(a, aprime); arf_set(b, bprime); arf_set(fa, faprime); arf_set(fb, fbprime); break; } } arf_clear(deriv); arf_clear(aprime); arf_clear(bprime); arf_clear(faprime); arf_clear(fbprime); arf_clear(err); arf_clear(delta); break; } arf_set(fc, arb_midref(z)); if (csign != bsign) { arf_set(a, b); arf_set(fa, fb); asign = bsign; arf_set(b, c); arf_set(fb, fc); bsign = csign; } else { arf_set(b, c); arf_set(fb, fc); bsign = csign; arf_mul_2exp_si(fa, fa, -1); } arf_sub(t, a, b, wp, ARF_RND_DOWN); arf_abs(t, t); if (arf_cmpabs_2exp_si(t, abs_tol) < 0) break; } /* a and b may have changed places */ if (arf_cmp(a, b) > 0) arf_swap(a, b); arb_set_interval_arf(res, a, b, prec); arf_clear(a); arf_clear(b); arf_clear(c); arf_clear(fa); arf_clear(fb); arf_clear(fc); arf_clear(t); arb_clear(z); } slong _acb_dirichlet_platt_local_hardy_z_zeros( arb_ptr res, const fmpz_t n, slong len, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma_grid, slong Ns_max, const arb_t H, slong sigma_interp, slong prec) { slong zeros_count, i; arf_interval_ptr p; platt_ctx_t ctx; platt_ctx_init( ctx, T, A, B, h, J, K, sigma_grid, Ns_max, H, sigma_interp, prec); p = _arf_interval_vec_init(len); zeros_count = _isolate_zeros(p, ctx, n, len, prec); for (i = 0; i < zeros_count; i++) { _refine_local_hardy_z_zero_illinois(res+i, ctx, &p[i].a, &p[i].b, prec); } platt_ctx_clear(ctx); _arf_interval_vec_clear(p, len); return zeros_count; } static void _arb_get_lbound_fmpz(fmpz_t z, const arb_t x, slong prec) { arf_t u; arf_init(u); arb_get_lbound_arf(u, x, prec); arf_get_fmpz(z, u, ARF_RND_DOWN); arf_clear(u); } /* Compares f to g=a*10^b. * Returns a negative value if f < g, positive value if g < f, otherwise 0. */ static int _fmpz_cmp_a_10exp_b(const fmpz_t f, slong a, slong b) { int result; fmpz_t g; fmpz_init(g); fmpz_set_ui(g, 10); fmpz_pow_ui(g, g, b); fmpz_mul_si(g, g, a); result = fmpz_cmp(f, g); fmpz_clear(g); return result; } static platt_ctx_ptr _create_heuristic_context(const fmpz_t n, slong prec) { platt_ctx_ptr p = NULL; slong K, A, B, Ns_max, sigma_grid, sigma_interp; slong kbits; fmpz_t J, T, k; arb_t g, h, H, logT; double dlogJ, dK, dgrid, dh, dH, dinterp; double x, x2, x3, x4; fmpz_init(J); fmpz_init(T); fmpz_init(k); arb_init(g); arb_init(h); arb_init(H); arb_init(logT); /* Estimate the height of the nth zero using gram points -- * it's predicted to fall between g(n-2) and g(n-1). */ fmpz_sub_ui(k, n, 2); kbits = fmpz_sizeinbase(k, 2); acb_dirichlet_gram_point(g, k, NULL, NULL, prec + kbits); /* Let T be the integer at the center of the evaluation grid. */ _arb_get_lbound_fmpz(T, g, prec + kbits); arb_log_fmpz(logT, T, prec); x = arf_get_d(arb_midref(logT), ARF_RND_NEAR); x2 = x*x; x3 = x2*x; x4 = x2*x2; if (_fmpz_cmp_a_10exp_b(n, 1, 4) < 0) { goto finish; } else if (_fmpz_cmp_a_10exp_b(n, 1, 5) < 0) { /* interpolated for n in [1e4, 1e5] */ A = 4; B = 64; Ns_max = 100; dinterp = 25; dK = 28; dgrid = 31; dlogJ = 8.4398 + -0.40306*x + 0.029866*x2 + -2.2858e-05*x3; dh = 1.0844 + 0.25524*x + -0.0046997*x2 + -6.3447e-05*x3; dH = -11.882 + 3.9521*x + -0.38654*x2 + 0.012728*x3; } else if (_fmpz_cmp_a_10exp_b(n, 1, 7) < 0) { /* interpolated for n in [1e4, 1e7] */ A = 8; B = 4096; Ns_max = 200; dinterp = 25; dlogJ = 0.88323 + 0.21392*x + 0.020846*x2 + -0.00053151*x3; dK = 137.27 + -15.609*x + 1.0778*x2 + -0.025927*x3; dgrid = -1711.1 + 701.03*x + -48.424*x2 + 1.2075*x3; dh = 448.2 + -84.087*x + 6.2089*x2 + -0.14565*x3; dH = 0.94123 + 0.021136*x + -0.00093042*x2 + 3.1007e-05*x3; } else if (_fmpz_cmp_a_10exp_b(n, 2, 17) < 0) { /* interpolated for n in [1e7, 5e22] */ A = 8; B = 4096; Ns_max = 200; dlogJ = -0.4035 + 0.49086*x + 0.00016299*x2 + -3.6139e-06*x3 + 2.9323e-08*x4; dK = 79.032 + -1.781*x + 0.039243*x2 + -0.00094859*x3 + 7.3149e-06*x4; dgrid = 1186.9 + 130.17*x + -7.4059*x2 + 0.17895*x3 + -0.001602*x4; dinterp = -24.252 + 7.3231*x + -0.38971*x2 + 0.0088745*x3 + -7.4331e-05*x4; dh = 178.66 + -15.127*x + 0.93132*x2 + -0.02311*x3 + 0.00022146*x4; dH = 2.5499 + -0.24402*x + 0.014953*x2 + -0.00037347*x3 + 3.5596e-06*x4; } else if (_fmpz_cmp_a_10exp_b(n, 1, 37) < 0) { /* interpolated for n in [1e7, 1e37] */ A = 16; B = 8192; Ns_max = 300; dlogJ = -0.50566 + 0.49723*x + 1.7964e-05*x2 + -2.3664e-07*x3 + 1.1234e-09*x4; dK = 100.97 + -0.709*x + -0.0020664*x2 + 3.1633e-05*x3 + -2.2912e-07*x4; dgrid = 3998.1 + 6.68*x + -0.3202*x2 + 0.0051782*x3 + -3.3829e-05*x4; dinterp = 21.203 + -0.2797*x + 0.01191*x2 + -0.00019769*x3 + 1.0395e-06*x4; dh = 137.6 + -0.16471*x + 0.039086*x2 + -0.00063299*x3 + 4.9674e-06*x4; dH = 0.64172 + -0.0017413*x + 0.0002195*x2 + -3.5247e-06*x3 + 2.6633e-08*x4; } else { goto finish; } arb_set_d(h, dh); arb_set_d(H, dH); fmpz_set_si(J, (slong) exp(dlogJ)); K = (slong) dK; sigma_grid = ((slong) (dgrid/2))*2 + 1; sigma_interp = ((slong) (dinterp/2))*2 + 1; p = flint_malloc(sizeof(platt_ctx_struct)); platt_ctx_init(p, T, A, B, h, J, K, sigma_grid, Ns_max, H, sigma_interp, prec); finish: fmpz_clear(J); fmpz_clear(T); fmpz_clear(k); arb_clear(g); arb_clear(h); arb_clear(H); arb_clear(logT); return p; } /* Returns the number of zeros found. */ slong acb_dirichlet_platt_isolate_local_hardy_z_zeros( arf_interval_ptr res, const fmpz_t n, slong len, slong prec) { if (len <= 0 || fmpz_sizeinbase(n, 10) < 5) { return 0; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "Nonpositive indices of Hardy Z zeros are not supported.\n"); } else { slong zeros_count = 0; platt_ctx_ptr ctx = _create_heuristic_context(n, prec); if (ctx) { zeros_count = _isolate_zeros(res, ctx, n, len, prec); platt_ctx_clear(ctx); flint_free(ctx); } return zeros_count; } return 0; } /* Returns the number of zeros found. */ slong acb_dirichlet_platt_local_hardy_z_zeros( arb_ptr res, const fmpz_t n, slong len, slong prec) { if (len <= 0 || fmpz_sizeinbase(n, 10) < 5) { return 0; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "Nonpositive indices of Hardy Z zeros are not supported.\n"); } else { slong zeros_count = 0; platt_ctx_ptr ctx; ctx = _create_heuristic_context(n, prec); if (ctx) { slong i; arf_interval_ptr p = _arf_interval_vec_init(len); zeros_count = _isolate_zeros(p, ctx, n, len, prec); for (i = 0; i < zeros_count; i++) { _refine_local_hardy_z_zero_illinois( res+i, ctx, &p[i].a, &p[i].b, prec); } _arf_interval_vec_clear(p, len); platt_ctx_clear(ctx); flint_free(ctx); } return zeros_count; } return 0; } flint-3.1.3/src/acb_dirichlet/platt_multieval.c000066400000000000000000000411501461254215100215510ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "acb_dirichlet.h" #include "arb_hypgeom.h" #include "acb_dft.h" static void _acb_dot_arb(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) { arb_ptr a; arb_srcptr b, c; if (sizeof(acb_struct) != 2*sizeof(arb_struct)) { flint_throw(FLINT_ERROR, "expected sizeof(acb_struct)=%zu " "to be twice sizeof(arb_struct)=%zu\n", sizeof(acb_struct), sizeof(arb_struct)); } if (initial == NULL) { flint_throw(FLINT_ERROR, "not implemented for NULL initial value\n"); } a = acb_realref(res); b = acb_realref(initial); c = acb_realref(x); arb_dot(a, b, subtract, c, xstep*2, y, ystep, len, prec); a = acb_imagref(res); b = acb_imagref(initial); c = acb_imagref(x); arb_dot(a, b, subtract, c, xstep*2, y, ystep, len, prec); } static void _arb_add_d(arb_t z, const arb_t x, double d, slong prec) { arb_t u; arb_init(u); arb_set_d(u, d); arb_add(z, x, u, prec); arb_clear(u); } static void _arb_div_si_si(arb_t z, slong a, slong b, slong prec) { arb_set_si(z, a); arb_div_si(z, z, b, prec); } static void _arb_inv_si(arb_t z, slong n, slong prec) { arb_set_si(z, n); arb_inv(z, z, prec); } static void platt_g_gamma_term(acb_t out, const arb_t t0, const acb_t t, slong prec) { acb_t z; acb_init(z); acb_add_arb(z, t, t0, prec); acb_mul_onei(z, z); acb_mul_2exp_si(z, z, 1); acb_add_ui(z, z, 1, prec); acb_mul_2exp_si(z, z, -2); acb_gamma(out, z, prec); acb_clear(z); } static void platt_g_exp_term(acb_t out, const arb_t t0, const arb_t h, const acb_t t, slong prec) { arb_t pi; acb_t z1, z2; arb_init(pi); acb_init(z1); acb_init(z2); arb_const_pi(pi, prec); acb_add_arb(z1, t, t0, prec); acb_mul_arb(z1, z1, pi, prec); acb_mul_2exp_si(z1, z1, -2); acb_div_arb(z2, t, h, prec); acb_sqr(z2, z2, prec); acb_mul_2exp_si(z2, z2, -1); acb_sub(out, z1, z2, prec); acb_exp(out, out, prec); arb_clear(pi); acb_clear(z1); acb_clear(z2); } static void platt_g_base(acb_t out, const acb_t t, slong prec) { arb_t pi; arb_init(pi); arb_const_pi(pi, prec); acb_mul_arb(out, t, pi, prec); acb_mul_onei(out, out); acb_mul_2exp_si(out, out, 1); acb_neg(out, out); arb_clear(pi); } static void platt_g_table(acb_ptr table, slong A, slong B, const arb_t t0, const arb_t h, slong K, slong prec) { slong N = A*B; slong i, n, k; acb_t t, base; acb_t gamma_term, exp_term, coeff; acb_ptr precomputed_powers; acb_init(t); acb_init(base); acb_init(gamma_term); acb_init(exp_term); acb_init(coeff); precomputed_powers = _acb_vec_init(K); for (i=0; i= m/B - 1/(2*B) */ void get_smk_points(fmpz * res, slong A, slong B) { slong m, N, prec; arb_t x, u, v; fmpz_t z; arb_init(x); arb_init(u); /* pi / B */ arb_init(v); /* 1 / sqrt(pi) */ fmpz_init(z); N = A*B; prec = 4; arb_indeterminate(u); arb_indeterminate(v); for (m = 0; m < N; m++) { while (1) { arb_set_si(x, 2*m - 1); arb_mul(x, x, u, prec); arb_exp(x, x, prec); arb_mul(x, x, v, prec); arb_ceil(x, x, prec); if (arb_get_unique_fmpz(z, x)) { fmpz_set(res + m, z); break; } else { prec *= 2; arb_const_pi(u, prec); arb_div_si(u, u, B, prec); arb_const_sqrt_pi(v, prec); arb_inv(v, v, prec); } } } arb_clear(x); arb_clear(u); arb_clear(v); fmpz_clear(z); } slong platt_get_smk_index(slong B, const fmpz_t j, slong prec) { slong m; arb_t pi, x; fmpz_t z; arb_init(pi); arb_init(x); fmpz_init(z); m = -1; while (1) { arb_const_pi(pi, prec); logjsqrtpi(x, j, prec); arb_div(x, x, pi, prec); arb_mul_2exp_si(x, x, -1); arb_mul_si(x, x, B, prec); _arb_add_d(x, x, 0.5, prec); arb_floor(x, x, prec); if (arb_get_unique_fmpz(z, x)) { m = fmpz_get_si(z); break; } else { prec *= 2; } } arb_clear(pi); arb_clear(x); fmpz_clear(z); return m; } typedef struct { slong bmax; slong b; slong K; arb_ptr M; /* (b, K) */ acb_ptr v; /* (b, ) */ } smk_block_struct; typedef smk_block_struct smk_block_t[1]; static void smk_block_init(smk_block_t p, slong K, slong bmax) { p->bmax = bmax; p->b = 0; p->K = K; p->M = _arb_vec_init(K*bmax); p->v = _acb_vec_init(bmax); } static void smk_block_clear(smk_block_t p) { _arb_vec_clear(p->M, p->K * p->bmax); _acb_vec_clear(p->v, p->bmax); } static int smk_block_is_full(smk_block_t p) { return p->b == p->bmax; } static void smk_block_reset(smk_block_t p) { p->b = 0; } static void smk_block_increment(smk_block_t p, const acb_t z, arb_srcptr v) { if (smk_block_is_full(p)) { flint_throw(FLINT_ERROR, "trying to increment a full block\n"); } acb_set(p->v + p->b, z); _arb_vec_set(p->M + p->K * p->b, v, p->K); p->b += 1; } static void smk_block_accumulate(smk_block_t p, acb_ptr res, slong prec) { slong i; for (i = 0; i < p->K; i++) _acb_dot_arb(res + i, res + i, 0, p->v, 1, p->M + i, p->K, p->b, prec); } void _platt_smk(acb_ptr table, acb_ptr startvec, acb_ptr stopvec, const fmpz * smk_points, const arb_t t0, slong A, slong B, const fmpz_t jstart, const fmpz_t jstop, slong mstart, slong mstop, slong K, slong prec) { fmpz_t j, j_plus_one; slong k, m; slong N = A * B; smk_block_t block; acb_ptr accum; arb_ptr diff_powers; arb_t rpi, logsqrtpi, rsqrtj, um, a, base; acb_t z; fmpz_init(j); fmpz_init(j_plus_one); arb_init(rpi); arb_init(logsqrtpi); arb_init(rsqrtj); arb_init(um); arb_init(a); arb_init(base); acb_init(z); smk_block_init(block, K, 32); diff_powers = _arb_vec_init(K); accum = _acb_vec_init(K); arb_const_pi(rpi, prec); arb_inv(rpi, rpi, prec); arb_const_sqrt_pi(logsqrtpi, prec); arb_log(logsqrtpi, logsqrtpi, prec); m = platt_get_smk_index(B, jstart, prec); _arb_div_si_si(um, m, B, prec); for (fmpz_set(j, jstart); fmpz_cmp(j, jstop) <= 0; fmpz_add_ui(j, j, 1)) { arb_log_fmpz(a, j, prec); arb_add(a, a, logsqrtpi, prec); arb_mul(a, a, rpi, prec); /* todo arb_rsqrt_fmpz */ arb_sqrt_fmpz(rsqrtj, j, prec); arb_inv(rsqrtj, rsqrtj, prec); acb_set_arb(z, t0); acb_mul_arb(z, z, a, prec); acb_neg(z, z); acb_exp_pi_i(z, z, prec); acb_mul_arb(z, z, rsqrtj, prec); while (m < N - 1 && fmpz_cmp(smk_points + m + 1, j) <= 0) { m += 1; _arb_div_si_si(um, m, B, prec); } if (m < mstart || m > mstop) { flint_throw(FLINT_ERROR, "out of bounds error: m = %wd not in [%wd, %wd]\n", m, mstart, mstop); } arb_mul_2exp_si(base, a, -1); arb_sub(base, base, um, prec); _arb_vec_set_powers(diff_powers, base, K, prec); smk_block_increment(block, z, diff_powers); { int j_stops, m_increases; fmpz_add_ui(j_plus_one, j, 1); j_stops = fmpz_equal(j, jstop); m_increases = (m < N - 1 && fmpz_cmp(smk_points + m + 1, j_plus_one) <= 0); if (j_stops || m_increases || smk_block_is_full(block)) { smk_block_accumulate(block, accum, prec); smk_block_reset(block); } if (j_stops || m_increases) { if (startvec && m == mstart) { _acb_vec_set(startvec, accum, K); } else if (stopvec && m == mstop) { _acb_vec_set(stopvec, accum, K); } else { for (k = 0; k < K; k++) acb_set(table + N*k + m, accum + k); } _acb_vec_zero(accum, K); } } } fmpz_clear(j); fmpz_clear(j_plus_one); arb_clear(rpi); arb_clear(logsqrtpi); arb_clear(rsqrtj); arb_clear(um); arb_clear(a); arb_clear(base); acb_clear(z); smk_block_clear(block); _arb_vec_clear(diff_powers, K); _acb_vec_clear(accum, K); } static void do_convolutions(acb_ptr out_table, acb_srcptr table, acb_srcptr S_table, slong N, slong K, slong prec) { slong i, k; acb_ptr padded_table_row, padded_S_table_row, padded_out_table; acb_ptr fp, gp; acb_dft_pre_t pre; padded_table_row = _acb_vec_init(N*2); padded_S_table_row = _acb_vec_init(N*2); padded_out_table = _acb_vec_init(N*2); fp = _acb_vec_init(N*2); gp = _acb_vec_init(N*2); acb_dft_precomp_init(pre, N*2, prec); for (k = 0; k < K; k++) { _acb_vec_zero(padded_table_row, N*2); _acb_vec_zero(padded_S_table_row, N*2); _acb_vec_zero(padded_out_table, N*2); _acb_vec_set(padded_table_row, table + k*N, N); _acb_vec_set(padded_S_table_row, S_table + k*N, N); for (i = 1; i < N; i++) { acb_swap(padded_S_table_row + i, padded_S_table_row + N*2 - i); } acb_dft_precomp(fp, padded_S_table_row, pre, prec); acb_dft_precomp(gp, padded_table_row, pre, prec); _acb_vec_kronecker_mul(gp, gp, fp, N*2, prec); acb_dft_inverse_precomp(padded_out_table, gp, pre, prec); for (i = 0; i <= N/2; i++) { acb_add(out_table + i, out_table + i, padded_out_table + i, prec); } } _acb_vec_clear(padded_table_row, N*2); _acb_vec_clear(padded_S_table_row, N*2); _acb_vec_clear(padded_out_table, N*2); _acb_vec_clear(fp, N*2); _acb_vec_clear(gp, N*2); acb_dft_precomp_clear(pre); } static void remove_gaussian_window(arb_ptr out, slong A, slong B, const arb_t h, slong prec) { slong i, n; slong N = A*B; arb_t t, x; arb_init(t); arb_init(x); for (i = 0; i < N; i++) { n = i - N/2; arb_set_si(t, n); arb_div_si(t, t, A, prec); arb_div(x, t, h, prec); arb_sqr(x, x, prec); arb_mul_2exp_si(x, x, -1); arb_exp(x, x, prec); arb_mul(out + i, out + i, x, prec); } arb_clear(t); arb_clear(x); } void _acb_dirichlet_platt_multieval(arb_ptr out, acb_srcptr S_table, const arb_t t0, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec) { slong N = A*B; slong i, k; acb_ptr table, out_a, out_b; acb_ptr row; arb_t t, x, k_factorial, err, ratio, c, xi; acb_t z; acb_dft_pre_t pre_N; arb_init(t); arb_init(x); arb_init(k_factorial); arb_init(err); arb_init(ratio); arb_init(c); arb_init(xi); acb_init(z); table = _acb_vec_init(K*N); out_a = _acb_vec_init(N); out_b = _acb_vec_init(N); acb_dft_precomp_init(pre_N, N, prec); _arb_inv_si(xi, B, prec); arb_mul_2exp_si(xi, xi, -1); platt_g_table(table, A, B, t0, h, K, prec); for (k = 0; k < K; k++) { acb_dirichlet_platt_lemma_A5(err, B, h, k, prec); _acb_vec_scalar_add_error_arb_mag(table + N*k, N, err); } for (k = 0; k < K; k++) { row = table + N*k; for (i = 0; i < N/2; i++) { acb_swap(row + i, row + i + N/2); } acb_dft_precomp(row, row, pre_N, prec); } _acb_vec_scalar_div_ui(table, table, N*K, (ulong) A, prec); for (k = 0; k < K; k++) { acb_dirichlet_platt_lemma_A7(err, sigma, t0, h, k, A, prec); _acb_vec_scalar_add_error_arb_mag(table + N*k, N, err); } arb_one(k_factorial); for (k = 2; k < K; k++) { row = table + N*k; arb_mul_ui(k_factorial, k_factorial, (ulong) k, prec); _acb_vec_scalar_div_arb(row, row, N, k_factorial, prec); } do_convolutions(out_a, table, S_table, N, K, prec); for (i = 0; i < N/2 + 1; i++) { arb_set_si(x, i); arb_div_si(x, x, B, prec); acb_dirichlet_platt_lemma_32(err, h, t0, x, prec); _acb_add_error_arb_mag(out_a + i, err); } acb_dirichlet_platt_lemma_B1(err, sigma, t0, h, J, prec); _acb_vec_scalar_add_error_arb_mag(out_a, N/2 + 1, err); arb_sqrt_fmpz(c, J, prec); arb_mul_2exp_si(c, c, 1); arb_sub_ui(c, c, 1, prec); acb_dirichlet_platt_lemma_B2(err, K, h, xi, prec); arb_mul(err, err, c, prec); _acb_vec_scalar_add_error_arb_mag(out_a, N/2 + 1, err); for (i = 1; i < N/2; i++) { acb_conj(out_a + N - i, out_a + i); } acb_dirichlet_platt_lemma_A9(err, sigma, t0, h, A, prec); _acb_vec_scalar_add_error_arb_mag(out_a, N, err); acb_dft_inverse_precomp(out_b, out_a, pre_N, prec); _acb_vec_scalar_mul_ui(out_b, out_b, N, (ulong) A, prec); for (i = 0; i < N/2; i++) { acb_swap(out_b + i, out_b + i + N/2); } acb_dirichlet_platt_lemma_A11(err, t0, h, B, prec); _acb_vec_scalar_add_error_arb_mag(out_b, N, err); for (i = 0; i < N; i++) { arb_swap(out + i, acb_realref(out_b + i)); } remove_gaussian_window(out, A, B, h, prec); arb_clear(t); arb_clear(x); arb_clear(k_factorial); arb_clear(err); arb_clear(ratio); arb_clear(c); arb_clear(xi); acb_clear(z); _acb_vec_clear(table, K*N); _acb_vec_clear(out_a, N); _acb_vec_clear(out_b, N); acb_dft_precomp_clear(pre_N); } void acb_dirichlet_platt_multieval(arb_ptr out, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec) { if (flint_get_num_threads() > 1) { acb_dirichlet_platt_multieval_threaded( out, T, A, B, h, J, K, sigma, prec); } else { slong N = A*B; acb_ptr S; arb_t t0; fmpz_t one; fmpz * smk_points; smk_points = _fmpz_vec_init(N); get_smk_points(smk_points, A, B); fmpz_init(one); fmpz_one(one); arb_init(t0); S = _acb_vec_init(K*N); arb_set_fmpz(t0, T); _platt_smk(S, NULL, NULL, smk_points, t0, A, B, one, J, 0, N-1, K, prec); _acb_dirichlet_platt_multieval(out, S, t0, A, B, h, J, K, sigma, prec); arb_clear(t0); fmpz_clear(one); _acb_vec_clear(S, K*N); _fmpz_vec_clear(smk_points, N); } } flint-3.1.3/src/acb_dirichlet/platt_multieval_threaded.c000066400000000000000000000103111461254215100234040ustar00rootroot00000000000000/* Copyright (C) 2020 Rudolph Copyright (C) 2020 D.H.J. Polymath Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz_vec.h" #include "acb_dirichlet.h" slong platt_get_smk_index(slong B, const fmpz_t j, slong prec); void get_smk_points(slong * res, slong A, slong B); void _platt_smk(acb_ptr table, acb_ptr startvec, acb_ptr stopvec, const slong * smk_points, const arb_t t0, slong A, slong B, const fmpz_t jstart, const fmpz_t jstop, slong mstart, slong mstop, slong K, slong prec); void _acb_dirichlet_platt_multieval(arb_ptr out, acb_srcptr S_table, const arb_t t0, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec); typedef struct { acb_ptr S; acb_ptr startvec; acb_ptr stopvec; const slong * smk_points; arb_srcptr t0; slong A; slong B; slong K; fmpz_t jstart; fmpz_t jstop; slong mstart; slong mstop; slong prec; } _worker_arg; static void _platt_smk_thread(void * arg_ptr) { _worker_arg *p = (_worker_arg *) arg_ptr; _platt_smk(p->S, p->startvec, p->stopvec, p->smk_points, p->t0, p->A, p->B, p->jstart, p->jstop, p->mstart, p->mstop, p->K, p->prec); flint_cleanup(); return; } void acb_dirichlet_platt_multieval_threaded(arb_ptr out, const fmpz_t T, slong A, slong B, const arb_t h, const fmpz_t J, slong K, slong sigma, slong prec) { slong i, num_workers, num_threads, N; fmpz * smk_points; thread_pool_handle * handles; _worker_arg * args; acb_ptr S; arb_t t0; fmpz_t threadtasks; num_workers = flint_request_threads(&handles, WORD_MAX); num_threads = num_workers + 1; N = A*B; fmpz_init(threadtasks); args = FLINT_ARRAY_ALLOC(num_threads, _worker_arg); fmpz_add_si(threadtasks, J, num_workers); fmpz_tdiv_q_ui(threadtasks, threadtasks, num_threads); smk_points = _fmpz_vec_init(N); arb_init(t0); get_smk_points(smk_points, A, B); arb_set_fmpz(t0, T); S = _acb_vec_init(K * N); for (i = 0; i < num_threads; i++) { args[i].S = S; args[i].startvec = _acb_vec_init(K); args[i].stopvec = _acb_vec_init(K); args[i].smk_points = smk_points; args[i].t0 = t0; args[i].A = A; args[i].B = B; args[i].K = K; args[i].prec = prec; fmpz_init(args[i].jstart); fmpz_init(args[i].jstop); fmpz_mul_si(args[i].jstart, threadtasks, i); fmpz_add_ui(args[i].jstart, args[i].jstart, 1); fmpz_mul_si(args[i].jstop, threadtasks, i + 1); args[i].mstart = platt_get_smk_index(B, args[i].jstart, prec); args[i].mstop = platt_get_smk_index(B, args[i].jstop, prec); } fmpz_set(args[num_threads - 1].jstop, J); args[num_threads - 1].mstop = platt_get_smk_index(B, J, prec); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _platt_smk_thread, &args[i]); /* Work on master thread */ _platt_smk_thread(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); for (i = 0; i < num_threads; i++) { slong k; for (k = 0; k < K; k++) { acb_ptr z; z = S + N*k + args[i].mstart; acb_add(z, z, args[i].startvec + k, prec); z = S + N*k + args[i].mstop; acb_add(z, z, args[i].stopvec + k, prec); } _acb_vec_clear(args[i].startvec, K); _acb_vec_clear(args[i].stopvec, K); fmpz_clear(args[i].jstart); fmpz_clear(args[i].jstop); } _acb_dirichlet_platt_multieval(out, S, t0, A, B, h, J, K, sigma, prec); arb_clear(t0); _acb_vec_clear(S, K * N); _fmpz_vec_clear(smk_points, N); flint_give_back_threads(handles, num_workers); flint_free(args); } flint-3.1.3/src/acb_dirichlet/platt_ws_interpolation.c000066400000000000000000000374601461254215100231600ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "arb_hypgeom.h" #include "arb_poly.h" static void _arb_div_si_si(arb_t res, slong x, slong y, slong prec) { arb_set_si(res, x); arb_div_si(res, res, y, prec); } static void _arb_ui_pow_arb(arb_t res, ulong n, const arb_t x, slong prec) { arb_t a; arb_init(a); arb_set_ui(a, n); arb_pow(res, a, x, prec); arb_clear(a); } /* * Follows the notation in https://en.wikipedia.org/wiki/Gaussian_function * res = a*exp(-(x-b)^2 / (2*c^2)) * If 'a' is NULL a default coefficient of 1 is used. * If 'b' is NULL a default mean of 0 is used. */ static void _arb_gaussian(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t x, slong prec) { arb_t z; arb_init(z); if (b == NULL) arb_set(z, x); else arb_sub(z, x, b, prec); arb_div(z, z, c, prec); arb_sqr(z, z, prec); arb_mul_2exp_si(z, z, -1); arb_neg(z, z); arb_exp(z, z, prec); if (a == NULL) arb_set(res, z); else arb_mul(res, z, a, prec); arb_clear(z); } static void _platt_lambda(arb_t res, const arb_t t, slong prec) { acb_t pi, s, z, s1, s2; acb_init(pi); acb_init(s); acb_init(z); acb_init(s1); acb_init(s2); arb_set_d(acb_realref(s), 0.5); arb_set(acb_imagref(s), t); acb_const_pi(pi, prec); arb_mul_2exp_si(acb_imagref(s1), t, -1); acb_neg(s1, s1); acb_pow(s1, pi, s1, prec); acb_mul_2exp_si(s2, s, -1); acb_gamma(s2, s2, prec); acb_zeta(z, s, prec); acb_mul(z, z, s1, prec); acb_mul(z, z, s2, prec); if (!arb_contains_zero(acb_imagref(z))) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } arb_set(res, acb_realref(z)); acb_clear(pi); acb_clear(s); acb_clear(z); acb_clear(s1); acb_clear(s2); } void acb_dirichlet_platt_scaled_lambda(arb_t res, const arb_t t, slong prec) { arb_t pi, lam; arb_init(pi); arb_init(lam); arb_const_pi(pi, prec); _platt_lambda(lam, t, prec); arb_mul(res, pi, t, prec); arb_mul_2exp_si(res, res, -2); arb_exp(res, res, prec); arb_mul(res, res, lam, prec); arb_clear(pi); arb_clear(lam); } void acb_dirichlet_platt_scaled_lambda_vec(arb_ptr res, const fmpz_t T, slong A, slong B, slong prec) { slong N = A*B; if (A < 1 || B < 1 || N % 2) { flint_throw(FLINT_ERROR, "requires an even number of grid points\n"); } else { slong i; arb_t t; arb_init(t); for (i = 0; i < N; i++) { slong n = i - N/2; _arb_div_si_si(t, n, A, prec); arb_add_fmpz(t, t, T, prec); acb_dirichlet_platt_scaled_lambda(res + i, t, prec); } arb_clear(t); } } static void _platt_bound_C3_X(arb_t res, const arb_t t0, slong A, const arb_t H, slong Ns, const arb_t beta, slong prec) { arb_t a, c, x; arb_init(a); arb_init(c); arb_init(x); /* res = gaussian(a=(t0+Ns/A)^beta, b=NULL, c=A*H, x=Ns) */ _arb_div_si_si(a, Ns, A, prec); arb_add(a, a, t0, prec); arb_pow(a, a, beta, prec); arb_mul_si(c, H, A, prec); arb_set_si(x, Ns); _arb_gaussian(res, a, NULL, c, x, prec); arb_clear(a); arb_clear(c); arb_clear(x); } static void _platt_bound_C3_Y(arb_t res, const arb_t t0, slong A, const arb_t H, slong Ns, const arb_t beta, slong prec) { arb_t a, b, g, g1, g2; arb_init(a); arb_init(b); arb_init(g); arb_init(g1); arb_init(g2); /* a = 2^((2*beta - 1)/2) */ arb_mul_2exp_si(a, beta, 1); arb_sub_ui(a, a, 1, prec); arb_mul_2exp_si(a, a, -1); _arb_ui_pow_arb(a, 2, a, prec); /* b = t0^beta */ arb_pow(b, t0, beta, prec); /* g = incomplete_gamma(1/2, Ns^2 / (2*A^2*H^2)) */ arb_set_d(g1, 0.5); _arb_div_si_si(g2, Ns, A, prec); arb_div(g2, g2, H, prec); arb_sqr(g2, g2, prec); arb_mul_2exp_si(g2, g2, -1); arb_hypgeom_gamma_upper(g, g1, g2, 0, prec); /* res = a*b*A*H*g */ arb_mul_si(res, H, A, prec); arb_mul(res, res, a, prec); arb_mul(res, res, b, prec); arb_mul(res, res, g, prec); arb_clear(a); arb_clear(b); arb_clear(g); arb_clear(g1); arb_clear(g2); } static void _platt_bound_C3_Z(arb_t res, const arb_t t0, slong A, const arb_t H, const arb_t beta, slong prec) { arb_t a, b, g, g1, g2; arb_init(a); arb_init(b); arb_init(g); arb_init(g1); arb_init(g2); /* a = 2^((3*beta - 1)/2) */ arb_mul_ui(a, beta, 3, prec); arb_sub_ui(a, a, 1, prec); arb_mul_2exp_si(a, a, -1); _arb_ui_pow_arb(a, 2, a, prec); /* b = H^(beta + 1) */ arb_add_ui(b, beta, 1, prec); arb_pow(b, H, b, prec); /* g = incomplete_gamma((beta+1)/2, t0^2 / (2*H^2)) */ arb_add_ui(g1, beta, 1, prec); arb_mul_2exp_si(g1, g1, -1); arb_div(g2, t0, H, prec); arb_sqr(g2, g2, prec); arb_mul_2exp_si(g2, g2, -1); arb_hypgeom_gamma_upper(g, g1, g2, 0, prec); /* res = a*b*A*g */ arb_mul_si(res, g, A, prec); arb_mul(res, res, a, prec); arb_mul(res, res, b, prec); arb_clear(a); arb_clear(b); arb_clear(g); arb_clear(g1); arb_clear(g2); } /* * An improvement of Lemma C.3 is used, which is tighter by a factor of A. * https://github.com/fredrik-johansson/arb/pull/269#issuecomment-468488347 */ void acb_dirichlet_platt_bound_C3(arb_t res, const arb_t t0, slong A, const arb_t H, slong Ns, slong prec) { arb_t pi, ee, beta, X, Y, Z, lhs, rhs; arb_init(pi); arb_init(ee); arb_init(beta); arb_init(X); arb_init(Y); arb_init(Z); arb_init(lhs); arb_init(rhs); /* t0 > exp(exp(1) is required for valid error bounds. */ arb_const_e(ee, prec); arb_exp(ee, ee, prec); if (!arb_gt(t0, ee)) { arb_zero_pm_inf(res); goto finish; } /* 0 < Ns <= t0*A is required for valid error bounds. */ arb_set_si(lhs, Ns); arb_mul_si(rhs, t0, A, prec); if (!arb_is_positive(lhs) || !arb_le(lhs, rhs)) { arb_zero_pm_inf(res); goto finish; } /* res = (X + Y + Z) * 6 / (pi * Ns) */ arb_const_pi(pi, prec); acb_dirichlet_platt_beta(beta, t0, prec); _platt_bound_C3_X(X, t0, A, H, Ns, beta, prec); _platt_bound_C3_Y(Y, t0, A, H, Ns, beta, prec); _platt_bound_C3_Z(Z, t0, A, H, beta, prec); arb_add(res, X, Y, prec); arb_add(res, res, Z, prec); arb_mul_ui(res, res, 6, prec); arb_div(res, res, pi, prec); arb_div_si(res, res, Ns, prec); finish: arb_clear(pi); arb_clear(ee); arb_clear(beta); arb_clear(X); arb_clear(Y); arb_clear(Z); arb_clear(lhs); arb_clear(rhs); } /* Does not account for limited resolution and supporting points. */ static void _interpolation_helper_raw(arb_t res, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong i0, slong Ns, const arb_t H, slong prec) { mag_t m; arb_t accum1; /* sum of terms where the argument of sinc is small */ arb_t accum2; /* sum of terms where the argument of sinc is large */ arb_t dt0, dt, a, b, s, pi, g, x, c; slong i; slong N = A*B; mag_init(m); arb_init(accum1); arb_init(accum2); arb_init(dt0); arb_init(dt); arb_init(a); arb_init(b); arb_init(s); arb_init(pi); arb_init(g); arb_init(x); arb_init(c); arb_const_pi(pi, prec); arb_sub_fmpz(dt0, t0, T, prec + fmpz_clog_ui(T, 2)); /* x = -N/2 - A*dt0 */ arb_mul_si(x, dt0, A, prec); arb_add_si(x, x, N/2, prec); arb_neg(x, x); /* c = sin(pi*x) / pi */ arb_sin_pi(c, x, prec); arb_div(c, c, pi, prec); for (i = i0; i < i0 + 2*Ns; i++) { slong n = i - N/2; _arb_div_si_si(dt, n, A, prec); _arb_gaussian(g, NULL, dt0, H, dt, prec); arb_mul(s, g, p + i, prec); arb_add_si(a, x, i, prec); arb_get_mag(m, a); if (mag_cmp_2exp_si(m, -1) < 0) { arb_sinc_pi(b, a, prec); arb_addmul(accum1, s, b, prec); } else { arb_div(b, s, a, prec); if (i % 2) { arb_neg(b, b); } arb_add(accum2, accum2, b, prec); } } arb_set(res, accum1); arb_addmul(res, accum2, c, prec); mag_clear(m); arb_clear(accum1); arb_clear(accum2); arb_clear(dt0); arb_clear(dt); arb_clear(a); arb_clear(b); arb_clear(s); arb_clear(pi); arb_clear(g); arb_clear(x); arb_clear(c); } /* Sets res to the function (a * exp(-(b-h)^2 / c)) * sinc_pi(d*(b-h))) * of the power series h, for the purpose of computing derivatives * of the Gaussian-windowed Whittaker-Shannon interpolation. * Supports aliasing. */ static void _arb_poly_gwws_series(arb_ptr res, arb_srcptr h, slong hlen, const arb_t a, const arb_t b, const arb_t c, const arb_t d, slong len, slong prec) { arb_ptr u, u2, v, w; hlen = FLINT_MIN(hlen, len); u = _arb_vec_init(hlen); u2 = _arb_vec_init(len); v = _arb_vec_init(len); w = _arb_vec_init(len); /* u = b-h; u2 = (b-h)^2 */ _arb_vec_neg(u, h, hlen); arb_add(u, u, b, prec); _arb_poly_mullow(u2, u, hlen, u, hlen, len, prec); /* v = exp(-(b-h)^2 / c) */ _arb_vec_scalar_div(v, u2, len, c, prec); _arb_vec_neg(v, v, len); _arb_poly_exp_series(v, v, len, len, prec); /* w = sinc_pi(d*(b-h)) */ _arb_vec_scalar_mul(w, u, hlen, d, prec); _arb_poly_sinc_pi_series(w, w, hlen, len, prec); /* res = a * exp(-(b-h)^2 / c)) * sinc_pi(d*(b-h)) */ _arb_poly_mullow(res, v, len, w, len, len, prec); _arb_vec_scalar_mul(res, res, len, a, prec); _arb_vec_clear(u, hlen); _arb_vec_clear(u2, len); _arb_vec_clear(v, len); _arb_vec_clear(w, len); } /* Does not account for limited resolution and supporting points. */ static void _interpolation_helper_raw_series(arb_ptr res, arb_srcptr t0, slong t0len, arb_srcptr p, const fmpz_t T, slong A, slong B, slong i0, slong Ns, const arb_t H, slong trunc, slong prec) { t0len = FLINT_MIN(t0len, trunc); if (t0len == 1) { _interpolation_helper_raw(res, t0, p, T, A, B, i0, Ns, H, prec); _arb_vec_zero(res + 1, trunc - 1); } else { arb_ptr h, g, accum; arb_t b, c, d; slong N = A*B; slong i; arb_init(b); arb_init(c); arb_init(d); h = _arb_vec_init(t0len); g = _arb_vec_init(trunc); accum = _arb_vec_init(trunc); arb_sqr(c, H, prec); arb_mul_2exp_si(c, c, 1); arb_set_si(d, A); _arb_vec_set(h, t0, t0len); arb_sub_fmpz(h, t0, T, prec + fmpz_clog_ui(T, 2)); for (i = i0; i < i0 + 2*Ns; i++) { slong n = i - N/2; _arb_div_si_si(b, n, A, prec); _arb_poly_gwws_series(g, h, t0len, p + i, b, c, d, trunc, prec); _arb_vec_add(accum, accum, g, trunc, prec); } _arb_vec_set(res, accum, trunc); arb_clear(b); arb_clear(c); arb_clear(d); _arb_vec_clear(h, t0len); _arb_vec_clear(g, trunc); _arb_vec_clear(accum, trunc); } } static void _interpolation_deriv_helper(arf_t res, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong i0, slong Ns, const arb_t H, slong prec) { arb_ptr t, h; t = _arb_vec_init(2); h = _arb_vec_init(2); arb_set(t+0, t0); arb_one(t+1); _interpolation_helper_raw_series( h, t, 2, p, T, A, B, i0, Ns, H, 2, prec); arf_set(res, arb_midref(h+1)); _arb_vec_clear(t, 2); _arb_vec_clear(h, 2); } /* Accounts for limited resolution and supporting points. */ static void _interpolation_helper(arb_t res, const acb_dirichlet_platt_ws_precomp_t pre, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong i0, slong Ns, const arb_t H, slong sigma, slong prec) { arb_t total, err; arb_init(total); arb_init(err); _interpolation_helper_raw( total, t0, p, T, A, B, i0, Ns, H, prec); acb_dirichlet_platt_bound_C3(err, t0, A, H, Ns, prec); arb_add_error(total, err); acb_dirichlet_platt_i_bound_precomp( err, &pre->pre_i, &pre->pre_c, t0, A, H, sigma, prec); arb_add_error(total, err); arb_set(res, total); arb_clear(total); arb_clear(err); } void acb_dirichlet_platt_ws_precomp_init(acb_dirichlet_platt_ws_precomp_t pre, slong A, const arb_t H, slong sigma, slong prec) { acb_dirichlet_platt_c_precomp_init(&pre->pre_c, sigma, H, 0, prec); acb_dirichlet_platt_i_precomp_init(&pre->pre_i, A, H, sigma, prec); } void acb_dirichlet_platt_ws_precomp_clear(acb_dirichlet_platt_ws_precomp_t pre) { acb_dirichlet_platt_c_precomp_clear(&pre->pre_c); acb_dirichlet_platt_i_precomp_clear(&pre->pre_i); } void acb_dirichlet_platt_ws_interpolation_precomp(arb_t res, arf_t deriv, const acb_dirichlet_platt_ws_precomp_t pre, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong Ns_max, const arb_t H, slong sigma, slong prec) { slong N = A*B; if (A < 1 || B < 1 || N % 2) { flint_throw(FLINT_ERROR, "requires an even number of grid points\n"); } else { arb_t x, dt0, dt0A, total; arf_t lower_f; slong n, lower_n; arb_init(x); arb_init(dt0); arb_init(dt0A); arb_init(total); arf_init(lower_f); arb_sub_fmpz(dt0, t0, T, prec + fmpz_clog_ui(T, 2)); arb_mul_si(dt0A, dt0, A, prec); arb_get_lbound_arf(lower_f, dt0A, prec); lower_n = arf_get_si(lower_f, ARF_RND_FLOOR); if (deriv) { arf_zero(deriv); } /* * More than one iteration is needed only when the set of * supporting points for interpolation is uncertain. */ for (n = lower_n; n == lower_n || arb_contains_si(dt0A, n); n++) { slong nlow = N/2 + n + 1; slong nhigh = N/2 - n - 1; slong Ns = FLINT_MIN(Ns_max, FLINT_MIN(nlow, nhigh)); if (Ns < 1) { arb_zero_pm_inf(total); } else { slong i0 = N/2 + n - (Ns - 1); if (res) { _interpolation_helper( x, pre, t0, p, T, A, B, i0, Ns, H, sigma, prec); if (n == lower_n) { arb_set(total, x); } else { arb_union(total, total, x, prec); } } if (deriv) { _interpolation_deriv_helper( deriv, t0, p, T, A, B, i0, Ns, H, prec); } } } if (res) { arb_set(res, total); } arb_clear(x); arb_clear(dt0); arb_clear(dt0A); arb_clear(total); arf_clear(lower_f); } } void acb_dirichlet_platt_ws_interpolation(arb_t res, arf_t deriv, const arb_t t0, arb_srcptr p, const fmpz_t T, slong A, slong B, slong Ns_max, const arb_t H, slong sigma, slong prec) { acb_dirichlet_platt_ws_precomp_t pre; acb_dirichlet_platt_ws_precomp_init(pre, A, H, sigma, prec); acb_dirichlet_platt_ws_interpolation_precomp( res, deriv, pre, t0, p, T, A, B, Ns_max, H, sigma, prec); acb_dirichlet_platt_ws_precomp_clear(pre); } flint-3.1.3/src/acb_dirichlet/platt_zeta_zeros.c000066400000000000000000000021001461254215100217240ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" slong acb_dirichlet_platt_zeta_zeros(acb_ptr res, const fmpz_t n, slong len, slong prec) { if (len <= 0 || fmpz_sizeinbase(n, 10) < 5) { return 0; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "nonpositive indices of zeta zeros are not supported\n"); } else { slong i, found; arb_ptr p; p = _arb_vec_init(len); found = acb_dirichlet_platt_hardy_z_zeros(p, n, len, prec); for (i = 0; i < found; i++) { acb_set_d(res + i, 0.5); arb_set(acb_imagref(res + i), p + i); } _arb_vec_clear(p, len); return found; } return 0; } flint-3.1.3/src/acb_dirichlet/powsum_sieved.c000066400000000000000000000060131461254215100212330ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" #define POWER(_k) (powers + (((_k)-1)/2) * (len)) #define DIVISOR(_k) (divisors[((_k)-1)/2]) void acb_dirichlet_powsum_sieved(acb_ptr z, const acb_t s, ulong n, slong len, slong prec) { slong * divisors; slong powers_alloc; slong i, j, k, ibound, power_of_two, horner_point; ulong kprev; int critical_line, integer; acb_ptr powers; acb_ptr t, u, x; acb_ptr p1, p2; arb_t logk, v, w; if (n <= 1) { acb_set_ui(z, n); _acb_vec_zero(z + 1, len - 1); return; } critical_line = arb_is_exact(acb_realref(s)) && (arf_cmp_2exp_si(arb_midref(acb_realref(s)), -1) == 0); integer = arb_is_zero(acb_imagref(s)) && arb_is_int(acb_realref(s)); divisors = flint_calloc(n / 2 + 1, sizeof(slong)); powers_alloc = (n / 6 + 1) * len; powers = _acb_vec_init(powers_alloc); ibound = n_sqrt(n); for (i = 3; i <= ibound; i += 2) if (DIVISOR(i) == 0) for (j = i * i; j <= n; j += 2 * i) DIVISOR(j) = i; t = _acb_vec_init(len); u = _acb_vec_init(len); x = _acb_vec_init(len); arb_init(logk); arb_init(v); arb_init(w); power_of_two = 1; while (power_of_two * 2 <= n) power_of_two *= 2; horner_point = n / power_of_two; _acb_vec_zero(z, len); kprev = 1; acb_dirichlet_powsum_term(x, logk, &kprev, s, 2, integer, critical_line, len, prec); for (k = 1; k <= n; k += 2) { /* t = k^(-s) */ if (DIVISOR(k) == 0) { acb_dirichlet_powsum_term(t, logk, &kprev, s, k, integer, critical_line, len, prec); } else { p1 = POWER(DIVISOR(k)); p2 = POWER(k / DIVISOR(k)); if (len == 1) acb_mul(t, p1, p2, prec); else _acb_poly_mullow(t, p1, len, p2, len, len, prec); } if (k * 3 <= n) _acb_vec_set(POWER(k), t, len); _acb_vec_add(u, u, t, len, prec); while (k == horner_point && power_of_two != 1) { _acb_poly_mullow(t, z, len, x, len, len, prec); _acb_vec_add(z, t, u, len, prec); power_of_two /= 2; horner_point = n / power_of_two; horner_point -= (horner_point % 2 == 0); } } _acb_poly_mullow(t, z, len, x, len, len, prec); _acb_vec_add(z, t, u, len, prec); flint_free(divisors); _acb_vec_clear(powers, powers_alloc); _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(x, len); arb_clear(logk); arb_clear(v); arb_clear(w); } flint-3.1.3/src/acb_dirichlet/powsum_smooth.c000066400000000000000000000124011461254215100212630ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" /* bound number of 5-smooth numbers up to n; see http://oeis.org/A188425 */ /* this does not need to be tight */ static slong smooth_bound(ulong n) { if (n <= 256) return 52; if (n <= 65536) return 284; if (n <= 16777216) return 836; return 13283; /* ok up to 2^64 */ } static ulong smul(ulong x, ulong y) { ulong hi, lo; umul_ppmm(hi, lo, x, y); if (hi) return UWORD_MAX; else return lo; } static slong _index(const ulong * v, ulong c) { slong i; for (i = 0; ; i++) if (v[i] == c) return i; } void acb_dirichlet_powsum_smooth(acb_ptr res, const acb_t s, ulong N, slong d, slong prec) { ulong * smooth; /* numbers 2^i 3^j 5^k <= N */ slong num_smooth; /* the number of such numbers */ acb_ptr sums; /* partial sum for each smooth prefactor */ acb_ptr powers; /* (3^j 5^k)^(-s) */ acb_ptr t; /* temporary */ arb_t log_n; ulong x2, x3, x5, m, n, nprev; slong i2, i3, i5, i, j, iu; int critical_line, integer; if (N <= 1) { acb_set_ui(res, N); _acb_vec_zero(res + 1, d - 1); return; } if (N >= UWORD_MAX - 2) flint_throw(FLINT_ERROR, "(%s)\n", __func__); critical_line = arb_is_exact(acb_realref(s)) && (arf_cmp_2exp_si(arb_midref(acb_realref(s)), -1) == 0); integer = arb_is_zero(acb_imagref(s)) && arb_is_int(acb_realref(s)); /* generate the smooth numbers */ smooth = flint_malloc(smooth_bound(N) * sizeof(ulong)); smooth[0] = 1; num_smooth = 1; x2 = 2; x3 = 3; x5 = 5; i2 = i3 = i5 = 0; while ((m = FLINT_MIN(FLINT_MIN(x2, x3), x5)) <= N) { smooth[num_smooth++] = m; if (m == x2) x2 = smul(2, smooth[++i2]); if (m == x3) x3 = smul(3, smooth[++i3]); if (m == x5) x5 = smul(5, smooth[++i5]); } sums = _acb_vec_init(num_smooth * d); powers = _acb_vec_init(num_smooth * d); t = _acb_vec_init(d); arb_init(log_n); arb_zero(log_n); nprev = 1; /* add 1^-s */ for (i = 0; i < num_smooth; i++) acb_one(sums + i * d); /* compute all the non-smooth index terms (bulk of the work) */ for (n = 7; n <= N; n += 2) { if ((n % 3 != 0) && (n % 5 != 0)) { acb_dirichlet_powsum_term(t, log_n, &nprev, s, n, integer, critical_line, d, prec); _acb_vec_add(sums, sums, t, d, prec); for (i = 1; i < num_smooth && (smooth[i] <= (N / n)); i++) _acb_vec_add(sums + i * d, sums + i * d, t, d, prec); } } /* compute 2^(-s) and powers (3^j 3^k)^(-s) */ arb_zero(log_n); nprev = 1; for (i = 1; i < num_smooth; i++) { n = smooth[i]; if (n == 2) { acb_dirichlet_powsum_term(powers + i * d, log_n, &nprev, s, n, integer, critical_line, d, prec); } else if (n % 2 != 0) { if (n <= 5) { acb_dirichlet_powsum_term(powers + i * d, log_n, &nprev, s, n, integer, critical_line, d, prec); } else if (n % 3 == 0) { i3 = _index(smooth, 3); iu = _index(smooth, n / 3); _acb_poly_mullow(powers + i * d, powers + i3 * d, d, powers + iu * d, d, d, prec); } else { i5 = _index(smooth, 5); iu = _index(smooth, n / 5); _acb_poly_mullow(powers + i * d, powers + i5 * d, d, powers + iu * d, d, d, prec); } } } /* merge the sums into the power-of-two sums */ for (i = 0; i < num_smooth; i++) { ulong u, v; m = smooth[i]; u = m; v = 0; while ((u & 1) == 0) { u >>= 1; v++; } if ((UWORD(1) << v) != m) { j = _index(smooth, UWORD(1) << v); iu = _index(smooth, u); if (u == 1) { _acb_vec_add(sums + j * d, sums + j * d, sums + i * d, d, prec); } else { _acb_poly_mullow(t, sums + i * d, d, powers + iu * d, d, d, prec); _acb_vec_add(sums + j * d, sums + j * d, t, d, prec); } } } /* finally evaluate with respect to powers of 2 using horner */ _acb_vec_zero(res, d); i2 = _index(smooth, 2); for (i = num_smooth - 1; i >= 0; i--) { n = smooth[i]; if ((n & (n - 1)) == 0) { _acb_poly_mullow(t, powers + i2 * d, d, res, d, d, prec); _acb_vec_add(res, sums + i * d, t, d, prec); } } _acb_vec_clear(sums, num_smooth * d); _acb_vec_clear(powers, num_smooth * d); _acb_vec_clear(t, d); arb_clear(log_n); flint_free(smooth); } flint-3.1.3/src/acb_dirichlet/powsum_term.c000066400000000000000000000035441461254215100207310ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_powsum_term(acb_ptr res, arb_t log_prev, ulong * prev, const acb_t s, ulong k, int integer, int critical_line, slong len, slong prec) { slong i; if (integer) { arb_neg(acb_realref(res), acb_realref(s)); arb_set_ui(acb_imagref(res), k); arb_pow(acb_realref(res), acb_imagref(res), acb_realref(res), prec); arb_zero(acb_imagref(res)); if (len != 1) { arb_log_ui_from_prev(log_prev, k, log_prev, *prev, prec); *prev = k; } } else { arb_t w; arb_init(w); arb_log_ui_from_prev(log_prev, k, log_prev, *prev, prec); *prev = k; arb_mul(w, log_prev, acb_imagref(s), prec); arb_sin_cos(acb_imagref(res), acb_realref(res), w, prec); arb_neg(acb_imagref(res), acb_imagref(res)); if (critical_line) { arb_rsqrt_ui(w, k, prec); acb_mul_arb(res, res, w, prec); } else { arb_mul(w, acb_realref(s), log_prev, prec); arb_neg(w, w); arb_exp(w, w, prec); acb_mul_arb(res, res, w, prec); } arb_clear(w); } if (len > 1) { arb_neg(log_prev, log_prev); for (i = 1; i < len; i++) { acb_mul_arb(res + i, res + i - 1, log_prev, prec); acb_div_ui(res + i, res + i, i, prec); } arb_neg(log_prev, log_prev); } } flint-3.1.3/src/acb_dirichlet/profile/000077500000000000000000000000001461254215100176365ustar00rootroot00000000000000flint-3.1.3/src/acb_dirichlet/profile/p-gauss.c000066400000000000000000000066501461254215100213700ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_dirichlet.h" #include "profiler.h" #define LOG 0 #define CSV 1 #define JSON 2 typedef void (*do_f) (acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); int main(int argc, char *argv[]) { int out; int l, nf = 5; do_f func[5] = { acb_dirichlet_gauss_sum_naive, acb_dirichlet_gauss_sum_factor, acb_dirichlet_gauss_sum_theta, acb_dirichlet_gauss_sum, acb_dirichlet_gauss_sum }; char * name[5] = { "naive", "factor", "theta", "default", "precomp" }; int i, ni = 5; ulong qmin[5] = { 3, 50, 500, 1000, 10000 }; ulong qmax[5] = { 50, 100, 599, 1050, 10030 }; int j, nj = 3; slong prec[3] = { 64, 128, 1024 }; if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } if (out == CSV) flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "prec", "qmin", "qmax", "time"); for (j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { if (out == LOG) flint_printf("G_q(a) at prec %wu for all %wu <= q <= %wu....\n", prec[j], qmin[i], qmax[i]); for (l = 0; l < nf; l++) { ulong q; if (qmin[i] > 2000 && l == 0) continue; if (out == LOG) flint_printf("%-14s ... ", name[l]); else if (out == CSV) flint_printf("%-12s, %7d, %7d, %7d, ", name[l], prec[j], qmin[i], qmax[i]); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ", name[l], prec[j], qmin[i], qmax[i]); TIMEIT_ONCE_START for (q = qmin[i]; q <= qmax[i]; q++) { dirichlet_group_t G; dirichlet_char_t chi; acb_t res; if (q % 4 == 2) continue; dirichlet_group_init(G, q); if (l == 4) dirichlet_group_dlog_precompute(G, 1); dirichlet_char_init(chi, G); dirichlet_char_first_primitive(chi, G); acb_init(res); do { func[l](res, G, chi, prec[j]); } while (dirichlet_char_next_primitive(chi, G) >= 0); acb_clear(res); dirichlet_char_clear(chi); if (l == 4) dirichlet_group_dlog_clear(G); dirichlet_group_clear(G); } TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } } } flint_cleanup(); return 0; } flint-3.1.3/src/acb_dirichlet/profile/p-jacobi.c000066400000000000000000000065101461254215100214700ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_dirichlet.h" #include "profiler.h" #define LOG 0 #define CSV 1 #define JSON 2 typedef void (*do_f) (acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); int main(int argc, char *argv[]) { int out; int l, nf = 4; do_f func[4] = { acb_dirichlet_jacobi_sum_naive, acb_dirichlet_jacobi_sum_factor, acb_dirichlet_jacobi_sum_gauss, acb_dirichlet_jacobi_sum }; char * name[4] = { "naive", "factor", "gauss", "default" }; int i, ni = 4; ulong qmin[4] = { 3, 51, 501, 10001 }; ulong qmax[4] = { 30, 100, 550, 10050 }; int j, nj = 3; slong prec[3] = { 64, 128, 1024 }; if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } if (out == CSV) flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "prec", "qmin", "qmax", "time"); for (j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { if (out == LOG) flint_printf("J_q(a,b) at prec %wu for all %wu <= q <= %wu....\n", prec[j], qmin[i], qmax[i]); for (l = 0; l < nf; l++) { ulong q; if (out == LOG) flint_printf("%-14s ... ", name[l]); else if (out == CSV) flint_printf("%-12s, %7d, %7d, %7d, ", name[l], prec[j], qmin[i], qmax[i]); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ", name[l], prec[j], qmin[i], qmax[i]); TIMEIT_ONCE_START for (q = qmin[i]; q <= qmax[i]; q+=2) { dirichlet_group_t G; dirichlet_char_t chi1, chi2; acb_t res; dirichlet_group_init(G, q); dirichlet_char_init(chi1, G); dirichlet_char_init(chi2, G); acb_init(res); do { slong c = 0; dirichlet_char_set(chi2, G, chi1); do { func[l](res, G, chi1, chi2, prec[j]); } while (dirichlet_char_next(chi2, G) >= 0 && c++ < 30); } while (dirichlet_char_next(chi1, G) >= 0); acb_clear(res); dirichlet_char_clear(chi1); dirichlet_char_clear(chi2); dirichlet_group_clear(G); } TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } } } flint_cleanup(); return 0; } flint-3.1.3/src/acb_dirichlet/profile/p-thetanull.c000066400000000000000000000115571461254215100222500ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "acb_dirichlet.h" static int usage(char *argv[]) { printf("usage: %s [--progress ] [--all] [--odd] [--prec ] [--onlymod] {qmin qmax | --value q a}\n", argv[0]); return 1; } static void value(ulong q, ulong a, slong prec, slong digits) { dirichlet_group_t G; dirichlet_char_t chi; acb_t res; arb_t one; dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_log(chi, G, a); acb_init(res); arb_init(one); arb_one(one); acb_dirichlet_theta_arb(res, G, chi, one, prec); acb_printd(res, digits); flint_printf("\n"); arb_clear(one); acb_clear(res); dirichlet_group_clear(G); dirichlet_char_clear(chi); } static void check_q(ulong q, int odd, slong prec, slong digits, int onlymod) { slong s; ulong k; dirichlet_group_t G; dirichlet_char_t x; acb_ptr theta, z; arb_t z1; arb_ptr t; dirichlet_group_init(G, q); dirichlet_char_init(x, G); theta = _acb_vec_init(G->phi_q); z = _acb_vec_init(G->phi_q); arb_init(z1); arb_const_pi(z1, prec); arb_div_ui(z1, z1, q, prec); arb_neg(z1, z1); arb_exp(z1, z1, prec); /* len = acb_dirichlet_theta_length_d(q, 1., prec); */ t = _arb_vec_init(q); acb_dirichlet_arb_quadratic_powers(t, q, z1, prec); for (s = 0; s <= odd; s++) { k = 0; dirichlet_char_one(x, G); do { acb_set_arb(z + k, t + x->n); k++; } while (dirichlet_char_next(x, G) >= 0); acb_dirichlet_dft_index(theta, z, G, prec); /* check zeros */ dirichlet_char_one(x, G); for (k = 0; k < G->phi_q; k++) { if (acb_contains_zero(theta + k) && dirichlet_conductor_char(G, x) == q && dirichlet_parity_char(G, x) == s) { if (onlymod) { flint_printf("%wu,%wu\n",q,x->n); } else { flint_printf("\ntheta null q = %wu, n = %wu\n",q, x->n); acb_printd(theta + k, digits); flint_printf("\n"); } } dirichlet_char_next(x, G); } if (odd) { /* change t for odd characters */ for (k = 0; k < q; k++) arb_mul_ui(t + k, t + k, k, prec); } } _arb_vec_clear(t, q); _acb_vec_clear(theta, G->phi_q); _acb_vec_clear(z, G->phi_q); arb_clear(z1); dirichlet_char_clear(x); dirichlet_group_clear(G); } int main(int argc, char *argv[]) { int i, all = 0, odd = 0, onlymod = 0, eval = 0; slong prec = 50, digits = 10; slong step = 0; ulong q, qmin, qmax; n_primes_t iter; if (argc < 3) return usage(argv); for (i = 1; i < argc - 2; i++) { if (!strcmp(argv[i],"--eval")) eval = 1; if (!strcmp(argv[i],"--all")) all = 1; if (!strcmp(argv[i],"--onlymod")) onlymod = 1; else if (!strcmp(argv[i],"--odd")) odd = 1; else if (!strcmp(argv[i],"--progress")) { i++; step = atol(argv[i]); } else if (!strcmp(argv[i],"--prec")) { i++; prec = atol(argv[i]); digits = floor(prec * 0.3); } } if (argc < i + 2) return usage(argv); qmin = atol(argv[i]); qmax = atol(argv[i+1]); if (eval) { value(qmin, qmax, prec, digits); } else { if (all) { for (q = qmin; q <= qmax; q++) { if (q % 4 == 2) continue; check_q(q, odd, prec, digits, onlymod); if (step && q % step == 0) flint_printf("[%wu]",q); } } else { ulong p; slong it = 0; /* look for vanishing theta values for prime power moduli */ n_primes_init(iter); while ((p = n_primes_next(iter)) < qmax) { for (q = p; q < qmin; q*= p); for (; q < qmax; q *= p) check_q(q, odd, prec, digits, onlymod); if (step && (it++ % step == 0)) flint_printf("[%wu]",p); } n_primes_clear(iter); } } flint_cleanup(); return 0; } flint-3.1.3/src/acb_dirichlet/profile/p-vec.c000066400000000000000000000121341461254215100210150ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_dirichlet.h" #include "profiler.h" #define LOG 0 #define CSV 1 #define JSON 2 typedef void (*do_f) (ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); static void do_empty(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { return; } static void do_dlog_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { slong k, l; nmod_t order; nmod_init(&order, dirichlet_order_char(G, chi)); for (k = 0; k < nv; k++) v[k] = 0; for (l = G->neven; l < G->num; l++) { dirichlet_prime_group_struct P = G->P[l]; dlog_vec_loop_add(v, nv, P.g, chi->log[l], P.pe, P.phi.n, order); } dirichlet_vec_set_null(v, G, nv); } static void do_eratos(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { slong k, p, pmax; nmod_t order; n_primes_t iter; n_primes_init(iter); nmod_init(&order, dirichlet_order_char(G, chi)); pmax = (nv < G->q) ? nv : G->q; v[1] = 0; while ((p = n_primes_next(iter)) < pmax) { if (G->q % p == 0) { for (k = p; k < nv; k += p) v[k] = DIRICHLET_CHI_NULL; } else { long chip; chip = dirichlet_chi(G, chi, p); for (k = p; k < nv; k += p) if (v[k] != -1) v[k] = nmod_add(v[k], chip, order); } } n_primes_clear(iter); } int main(int argc, char *argv[]) { int out; ulong * rand; flint_rand_t state; slong r, nr; int l, nf = 9; do_f func[9] = { do_empty, dirichlet_chi_vec_loop, do_dlog_primeloop, dirichlet_chi_vec_primeloop, do_eratos, dirichlet_chi_vec, dirichlet_chi_vec, dirichlet_chi_vec, dirichlet_chi_vec }; char * name[9] = { "char only", "big loop", "prime loops", "prime dlog_vec", "manual eratos", "default", "precomp 1", "precomp 20", "precomp 100" }; int i, ni = 5; ulong qmin[5] = { 2, 1000, 3000, 10000, 100000 }; ulong qmax[5] = { 500, 2000, 5000, 12000, 100500 }; int j, nj = 3; slong nv[3] = { 50, 300, 2000 }; nr = 20; flint_randinit(state); rand = flint_malloc(nr * sizeof(ulong)); for (r = 0; r < nr; r++) rand[r] = n_randprime(state, 42, 0); if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } if (out == CSV) flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "num", "qmin", "qmax", "time"); for (j = 0; j < nj; j++) { ulong * v; v = flint_malloc(nv[j] * sizeof(ulong)); for (i = 0; i < ni; i++) { if (out == LOG) flint_printf("%wu * ui_chi(rand, 1..%wu) for all %wu <= q <= %wu....\n", nr, nv[j], qmin[i], qmax[i]); for (l = 0; l < nf; l++) { ulong q; /* eratos too slow */ if (l == 4 && i > 2) continue; if (out == LOG) flint_printf("%-14s ... ", name[l]); else if (out == CSV) flint_printf("%-12s, %7d, %7d, %7d, ", name[l], nv[j], qmin[i], qmax[i]); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"num\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ", name[l], nv[j], qmin[i], qmax[i]); TIMEIT_ONCE_START for (q = qmin[i]; q <= qmax[i]; q++) { dirichlet_group_t G; dirichlet_char_t chi; dirichlet_group_init(G, q); dirichlet_char_init(chi, G); if (l >= 6) dirichlet_group_dlog_precompute(G, (l == 6) ? 1 : (l==7) ? 20 : 100); for (r = 0; r < nr; r++) { dirichlet_char_log(chi, G, rand[r] % q); func[l](v, G, chi, nv[j]); } if (l >= 6) dirichlet_group_dlog_clear(G); dirichlet_char_clear(chi); dirichlet_group_clear(G); } TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } } flint_free(v); } flint_free(rand); flint_randclear(state); flint_cleanup(); return 0; } flint-3.1.3/src/acb_dirichlet/qseries_arb.c000066400000000000000000000017471461254215100206520ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* sum a_k x^(k^2), assume a[0] = 0 */ void acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec) { slong k; arb_t xk2, dx, x2; arb_init(xk2); arb_init(dx); arb_init(x2); arb_set(dx, x); arb_set(xk2, dx); arb_mul(x2, dx, dx, prec); acb_mul_arb(res, a + 1, xk2, prec); /* TODO: reduce prec */ for (k = 2; k < len; k++) { arb_mul(dx, dx, x2, prec); arb_mul(xk2, xk2, dx, prec); acb_addmul_arb(res, a + k, xk2, prec); } arb_clear(xk2); arb_clear(x2); arb_clear(dx); } flint-3.1.3/src/acb_dirichlet/qseries_arb_powers.c000066400000000000000000000050011461254215100222340ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_roots_t roots, slong len, slong prec) { slong k; arb_t xk2, dx, x2; acb_t zk; arb_init(xk2); arb_init(dx); arb_init(x2); acb_init(zk); arb_set(dx, x); arb_set(xk2, dx); arb_mul(x2, dx, dx, prec); acb_set_arb(res, xk2); /* TODO: reduce prec */ for (k = 2; k < len; k++) { arb_mul(dx, dx, x2, prec); arb_mul(xk2, xk2, dx, prec); if (a[k] != DIRICHLET_CHI_NULL) { acb_dirichlet_root(zk, roots, a[k], prec); if (parity) acb_mul_si(zk, zk, k, prec); acb_addmul_arb(res, zk, xk2, prec); } } arb_clear(xk2); arb_clear(x2); arb_clear(dx); acb_clear(zk); } /* small order, multiply by chi at the end */ void acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_roots_t roots, slong len, slong prec) { slong k; ulong order = roots->order; arb_t xk2, kxk2, dx, x2; acb_ptr t; arb_init(xk2); arb_init(dx); arb_init(x2); arb_init(kxk2); arb_set(dx, x); arb_set(xk2, x); arb_mul(x2, x, x, prec); t = _acb_vec_init(order); _acb_vec_zero(t, order); arb_set(acb_realref(t + 0), xk2); /* TODO: reduce precision at each step */ for (k = 2; k < len; k++) { arb_mul(dx, dx, x2, prec); arb_mul(xk2, xk2, dx, prec); if (a[k] != DIRICHLET_CHI_NULL) { if (parity) { arb_mul_si(kxk2, xk2, k, prec); arb_add(acb_realref(t + a[k]), acb_realref(t + a[k]), kxk2, prec); } else { arb_add(acb_realref(t + a[k]), acb_realref(t + a[k]), xk2, prec); } } } /* now Horner */ acb_dirichlet_root(res, roots, 1, prec); _acb_poly_evaluate(res, t, order, res, prec); _acb_vec_clear(t, order); arb_clear(xk2); arb_clear(x2); arb_clear(dx); arb_clear(kxk2); } flint-3.1.3/src/acb_dirichlet/root.c000066400000000000000000000043671461254215100173370ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb_dirichlet.h" void acb_dirichlet_root(acb_t z, const acb_dirichlet_roots_t t, ulong k, slong prec) { ulong n = t->order; int swap, flip, conjugate; slong wp; if (k > n) k %= n; swap = flip = conjugate = 0; if (k > n / 2) { conjugate = 1; k = n - k; } if (n % 2 == 0 && k > n / 4) { flip = 1; k = n / 2 - k; } if (n % 4 == 0 && k > n / 8) { swap = 1; k = n / 4 - k; } wp = prec + 6 + 2 * FLINT_BIT_COUNT(t->reduced_order); if (k == 0) { acb_one(z); } else if (t->depth == 0) { if (t->use_pow) { acb_pow_ui(z, t->z, k, wp); acb_set_round(z, z, prec); } else { ulong r; fmpq_t t; fmpq_init(t); r = n_gcd(n, 2 * k); /* no overflow since since k <= n / 2 */ fmpz_set_ui(fmpq_numref(t), (2 * k) / r); fmpz_set_ui(fmpq_denref(t), n / r); arb_sin_cos_pi_fmpq(acb_imagref(z), acb_realref(z), t, prec); fmpq_clear(t); } } else if (t->depth == 1) { acb_set_round(z, t->Z[0] + k, prec); } else { slong j; ulong r; r = k % t->size; k = k / t->size; acb_set(z, t->Z[0] + r); for (j = 1; j < t->depth && k != 0; j++) { r = k % t->size; k = k / t->size; acb_mul(z, z, t->Z[j] + r, wp); } if (k != 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); acb_set_round(z, z, prec); } if (swap) arb_swap(acb_realref(z), acb_imagref(z)); if (flip) arb_neg(acb_realref(z), acb_realref(z)); if (conjugate) arb_neg(acb_imagref(z), acb_imagref(z)); } flint-3.1.3/src/acb_dirichlet/root_number.c000066400000000000000000000027201461254215100206760ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { arb_t x; acb_t eps; arb_init(x); arb_one(x); acb_dirichlet_theta_arb(res, G, chi, x, prec); acb_init(eps); acb_conj(eps, res); acb_div(res, res, eps, prec); if (dirichlet_char_is_real(G, chi)) arb_zero(acb_imagref(res)); arb_clear(x); acb_clear(eps); } void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { if (dirichlet_conductor_char(G, chi) < G->q) { flint_throw(FLINT_ERROR, "root number: need primitive character\n"); } else if (G->num > 1) { acb_t iq; acb_init(iq); acb_dirichlet_gauss_sum_order2(iq, G, chi, prec); acb_dirichlet_gauss_sum(res, G, chi, prec); acb_div(res, res, iq, prec); acb_clear(iq); } else { acb_dirichlet_root_number_theta(res, G, chi, prec); } if (dirichlet_char_is_real(G, chi)) arb_zero(acb_imagref(res)); } flint-3.1.3/src/acb_dirichlet/roots_clear.c000066400000000000000000000011351461254215100206560ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_roots_clear(acb_dirichlet_roots_t t) { slong k; for (k = 0; k < t->depth; k++) _acb_vec_clear(t->Z[k], t->size + 1); flint_free(t->Z); acb_clear(t->z); } flint-3.1.3/src/acb_dirichlet/roots_init.c000066400000000000000000000055221461254215100205370ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_roots_init(acb_dirichlet_roots_t t, ulong order, slong num, slong prec) { slong k, size, depth, best_depth, wp; ulong reduced_order; double cost, best_cost; /* exploit 90 deg symmetries */ if (order % 4 == 0) reduced_order = order / 8 + 1; else if (order % 2 == 0) reduced_order = order / 4 + 1; else reduced_order = order / 2 + 1; wp = prec + 6 + 2 * FLINT_BIT_COUNT(reduced_order); t->order = order; t->reduced_order = reduced_order; t->use_pow = 0; if (reduced_order <= 2 || num <= 2) { depth = 0; size = 0; } else { /* At depth = d and reduced_order = n, for k evaluations we need about log_2(n) * k muls if d == 0 d * n^(1/d) + (d-1) * k muls if d > 0 */ best_cost = FLINT_BIT_COUNT(reduced_order) * (double) num; best_depth = 0; for (depth = 1; depth <= 4; depth++) { size = n_root(reduced_order, depth) + 1; /* limit memory usage */ if (depth * _acb_vec_estimate_allocated_bytes(size, wp) > 1e9) continue; cost = depth * (double) size + (depth - 1) * (double) num; if (cost < best_cost) { best_depth = depth; best_cost = cost; } } depth = best_depth; size = n_root(reduced_order, depth) + 1; } t->size = size; t->depth = depth; acb_init(t->z); if (depth != 0) { acb_struct * z; acb_unit_root(t->z, order, wp); z = t->z; t->Z = flint_malloc(depth * sizeof(acb_ptr)); /* todo: at the last level, we could avoid computing entries that will never be reached */ for (k = 0; k < depth; k++) { t->Z[k] = _acb_vec_init(size + 1); _acb_vec_set_powers(t->Z[k], z, size + 1, wp); z = t->Z[k] + size; } } else { /* this tuning could be improved */ if (reduced_order < 30) t->use_pow = 1; else if (reduced_order < 100) t->use_pow = (prec >= 512); else if (reduced_order < 10000) t->use_pow = (prec >= 4096); else t->use_pow = (prec >= 16384); if (t->use_pow) acb_unit_root(t->z, order, wp); t->Z = NULL; } } flint-3.1.3/src/acb_dirichlet/si_poly_evaluate.c000066400000000000000000000025541461254215100217140ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* bsgs evaluation */ void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec) { slong k, r, m; acb_t sq; acb_ptr zk; if (len < 3) { if (len == 0) { acb_zero(res); } else if (len == 1) { acb_set_si(res, v[0]); } else if (len == 2) { acb_mul_si(res, z, v[1], prec); acb_add_si(res, res, v[0], prec); } return; } m = n_sqrt(len) + 1; zk = _acb_vec_init(m + 1); _acb_vec_set_powers(zk, z, m + 1, prec); acb_init(sq); acb_zero(res); k = len - 1; r = k % m; for (; k >= 0; r = m - 1) { acb_dot_si(sq, NULL, 0, zk + r, -1, v + k, -1, r + 1, prec); k -= (r + 1); acb_mul(res, res, zk + m, prec); acb_add(res, res, sq, prec); } _acb_vec_clear(zk, m + 1); acb_clear(sq); } flint-3.1.3/src/acb_dirichlet/stieltjes.c000066400000000000000000000422661461254215100203620ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" #include "acb_calc.h" #ifdef __GNUC__ # define atan2 __builtin_atan2 # define cos __builtin_cos # define exp __builtin_exp # define log __builtin_log # define pow __builtin_pow # define sqrt __builtin_sqrt # define tan __builtin_tan #else # include #endif /* Bound the quadratic Taylor error term. */ static void stieltjes_bound_quadratic_term(arb_t B, const acb_t z, const fmpz_t n1, const acb_t alpha, slong prec) { acb_t t, log_t; mag_t b, c, d; acb_init(t); acb_init(log_t); mag_init(b); mag_init(c); mag_init(d); /* g''(z) = (n+1)(1+1/log(t)) / (t^2 log(t)) */ /* t = alpha + iz, log_t = log(t) */ acb_mul_onei(t, z); acb_add(t, t, alpha, prec); acb_log(log_t, t, prec); acb_get_mag_lower(b, t); acb_get_mag_lower(c, log_t); /* d = 1+1/log(t) */ mag_inv(d, c); mag_add_ui(d, d, 1); /* divide by t^2 log(t) */ mag_div(d, d, b); mag_div(d, d, b); mag_div(d, d, c); mag_mul_fmpz(d, d, n1); /* For Taylor remainder: 1/2 rad(z)^2 */ mag_hypot(b, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul(b, b, b); mag_mul_2exp_si(b, b, -1); mag_mul(d, d, b); arf_set_mag(arb_midref(B), d); mag_zero(arb_radref(B)); acb_clear(t); acb_clear(log_t); mag_clear(b); mag_clear(c); mag_clear(d); } static void stieltjes_bound_large3(arb_t B, const acb_t x, const fmpz_t n1, const acb_t alpha, slong prec) { acb_t m, t, log_t, u, v; acb_t g0, g1, g2; mag_t C, D; acb_init(m); acb_init(t); acb_init(log_t); acb_init(u); acb_init(v); acb_init(g0); acb_init(g1); acb_init(g2); mag_init(C); mag_init(D); /* m = mid(x) */ acb_set(m, x); mag_zero(arb_radref(acb_realref(m))); mag_zero(arb_radref(acb_imagref(m))); /* t = alpha + im */ acb_mul_onei(t, m); acb_add(t, t, alpha, prec); /* log_t = log(alpha+im) */ acb_log(log_t, t, prec); /* u = x - m */ acb_sub(u, x, m, prec); acb_get_mag(D, u); /* g0 = g(m) = (n+1) log(log(alpha+im)) - 2 pi m */ acb_log(g0, log_t, prec); acb_mul_fmpz(g0, g0, n1, prec); acb_const_pi(v, prec); acb_mul(v, v, m, prec); acb_mul_2exp_si(v, v, 1); acb_sub(g0, g0, v, prec); /* g1 = g'(m) (x-m); g'(m) = i(n+1)/((alpha+im) log(alpha+im)) - 2 pi */ acb_mul(g1, t, log_t, prec); acb_inv(g1, g1, prec); acb_mul_fmpz(g1, g1, n1, prec); acb_mul_onei(g1, g1); acb_const_pi(t, prec); /* recycle t */ acb_mul_2exp_si(t, t, 1); acb_sub(g1, g1, t, prec); acb_mul(g1, g1, u, prec); /* absolute value -- optional (does not seem to affect speed much) */ acb_abs(acb_realref(g1), g1, prec); arb_zero(acb_imagref(g1)); stieltjes_bound_quadratic_term(acb_realref(g2), x, n1, alpha, prec); acb_exp(g0, g0, prec); acb_exp(g1, g1, prec); acb_exp(g2, g2, prec); acb_get_mag(C, g0); acb_get_mag(D, g1); mag_mul(C, C, D); acb_get_mag(D, g2); mag_mul(C, C, D); mag_mul_ui(C, C, 5); arb_zero(B); arf_set_mag(arb_midref(B), C); acb_clear(m); acb_clear(t); acb_clear(log_t); acb_clear(u); acb_clear(v); mag_clear(C); mag_clear(D); acb_clear(g0); acb_clear(g1); acb_clear(g2); } static void stieltjes_bound_large(acb_t res, const acb_t x, const fmpz_t n1, const acb_t alpha, slong prec) { arb_t B; mag_t t; arb_init(B); mag_init(t); prec = FLINT_MIN(prec, 30 + fmpz_bits(n1)); stieltjes_bound_large3(B, x, n1, alpha, prec); arb_get_mag(t, B); acb_zero(res); arb_add_error_mag(acb_realref(res), t); arb_add_error_mag(acb_imagref(res), t); arb_clear(B); mag_clear(t); } static void stieltjes_integrand(acb_t res, const acb_t x, const fmpz_t n1, const acb_t alpha, int analytic, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_mul_onei(t, x); acb_add(t, t, alpha, prec); acb_set_ui(u, 5); /* check branch cut of logarithm */ if (arb_contains_zero(acb_imagref(t)) && !arb_is_positive(acb_realref(t))) { acb_indeterminate(res); } else if ((analytic || acb_rel_accuracy_bits(t) < prec - 10) && arb_gt(acb_realref(x), acb_realref(u))) { /* note: requires re(x) > 1 */ stieltjes_bound_large(res, x, n1, alpha, prec); } else { acb_const_pi(u, prec); acb_mul(u, u, x, prec); acb_sech(u, u, prec); if (acb_is_finite(u)) { acb_mul(u, u, u, prec); acb_log(t, t, prec); acb_pow_fmpz(t, t, n1, prec); acb_mul(res, t, u, prec); } else { acb_indeterminate(res); } } acb_clear(t); acb_clear(u); } typedef struct { const fmpz * n1; const acb_struct * alpha; } _stieltjes_param; /* Compute the approximate saddle point. */ static void stieltjes_omega(acb_t omega, const fmpz_t n1, const acb_t alpha, slong prec) { acb_t t, u; fmpz_t k; acb_init(t); acb_init(u); fmpz_init(k); /* u = (n+1)i / (2pi) */ arb_set_fmpz(acb_imagref(t), n1); acb_const_pi(u, prec); acb_mul_2exp_si(u, u, 1); acb_div(u, t, u, prec); /* u / W(u) */ acb_lambertw(t, u, k, 0, prec); acb_div(t, u, t, prec); acb_sub(t, alpha, t, prec); acb_mul_onei(t, t); acb_set(omega, t); acb_clear(t); acb_clear(u); fmpz_clear(k); } /* Compute an approximation of the magnitude of gamma_n. */ static void stieltjes_mag_approx(arb_t C, mag_t tol, const fmpz_t n1, const acb_t alpha) { slong prec; acb_t w, v, q; prec = 32 + 2 * fmpz_bits(n1); acb_init(w); acb_init(v); acb_init(q); stieltjes_omega(w, n1, alpha, prec); stieltjes_integrand(v, w, n1, alpha, 0, prec); acb_set_fmpz(q, n1); acb_sqrt(q, q, prec); acb_mul(v, v, q, prec); acb_get_mag(tol, v); arb_set(C, acb_imagref(w)); mag_zero(arb_radref(C)); acb_clear(w); acb_clear(v); acb_clear(q); } int _f_stieltjes(acb_ptr res, const acb_t x, void * param, slong order, slong prec) { const fmpz * n1; const acb_struct * alpha; if (order > 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* Would be needed for Taylor method. */ n1 = ((const _stieltjes_param *) param)->n1; alpha = ((const _stieltjes_param *) param)->alpha; stieltjes_integrand(res, x, n1, alpha, order != 0, prec); return 0; } /* Estimate log2(|gamma_n|), for fast cancellation estimate when n is small. */ static double stieltjes_mag(double n) { double u, v, A, B; double va, vb, t; double pi = 3.141592653589793; int i; if (n <= 1.0) return 0.0; va = 1e-6; vb = 0.5 * pi - 1e-6; for (i = 0; i < 53; i++) /* bisection */ { v = (va + vb) * 0.5; t = 2 * pi * exp(v * tan(v)) - n * cos(v) / v; if (t < 0.0) va = v; else vb = v; } v = va; u = v * tan(v); A = 0.5 * log(u * u + v * v) - u / (u * u + v * v); B = 2 * sqrt(2 * pi) * sqrt(u * u + v * v) * pow((u + 1) * (u + 1) + v * v, -0.25); t = (log(B) + n * A - 0.5 * log(n)) / log(2); return t; } static double _d_approx_hypot(double x, double y) { return sqrt(x * x + y * y); } /* log2 magnitude of integrand at z = x+yi; alpha = a+bi */ static double integrand_mag(double n, double x, double y, double a, double b) { double t, u; t = log(_d_approx_hypot(a - y, b + x)); u = atan2(b + x, a - y); t = log(_d_approx_hypot(t,u)) * (n+1) - 2.0 * 3.1415926535897932 * x; return t * 1.44269504088896341; } static double find_x_maximizing_mag(double n, double y) { double xa, xb, xma, xmb, ma, mb; int i; xa = 1.0; xb = n; for (i = 0; i < 80; i++) { xma = xa + (xb - xa) / 3; xmb = xb - (xb - xa) / 3; ma = integrand_mag(n, xma, y, 0.5, 0.0); mb = integrand_mag(n, xmb, y, 0.5, 0.0); if (ma < mb) xa = xma; else xb = xmb; } return xa; } static void stieltjes_choose_N(arb_t N, const fmpz_t n1, const acb_t alpha, slong prec) { if (fmpz_bits(n1) < 30) { double nn, NN, aa, bb; nn = fmpz_get_d(n1) - 1.0; NN = FLINT_MAX(nn, 4); aa = arf_get_d(arb_midref(acb_realref(alpha)), ARF_RND_DOWN); bb = arf_get_d(arb_midref(acb_imagref(alpha)), ARF_RND_DOWN); while (integrand_mag(nn, NN, 0.0, aa, bb) > -prec - 20) { NN *= 2.0; if (NN > 1e30) break; } arb_set_d(N, NN); } else { /* todo: account for huge alpha? */ arb_set_fmpz(N, n1); } } static void stieltjes_tail_bound(mag_t bound, const arb_t N, const fmpz_t n1, const acb_t alpha) { slong prec; arb_t x, y, D; acb_t aNi, logaNi; mag_t t, u; prec = MAG_BITS + fmpz_bits(n1); arb_init(x); arb_init(y); arb_init(D); acb_init(aNi); acb_init(logaNi); mag_init(t); mag_init(u); /* alpha + Ni */ acb_set(aNi, alpha); arb_add(acb_imagref(aNi), acb_imagref(aNi), N, prec); /* log(alpha + Ni) */ acb_log(logaNi, aNi, prec); /* check (n+1)/(|alpha+Ni| log(alpha + Ni)|) < 2 */ acb_get_mag_lower(t, aNi); acb_get_mag_lower(u, logaNi); mag_mul_lower(t, t, u); mag_inv(t, t); mag_mul_fmpz(t, t, n1); /* also check N >= |im(alpha)| + 2 */ arb_abs(x, acb_imagref(alpha)); arb_add_ui(x, x, 2, prec); if (mag_cmp_2exp_si(t, 1) >= 0 || !arb_ge(N, x)) { mag_inf(bound); } else { /* exp(-2 pi N) */ arb_set(x, N); arb_mul_2exp_si(x, x, 1); arb_const_pi(y, prec); arb_mul(y, y, x, prec); arb_neg(y, y); arb_exp(y, y, prec); /* |log|^(n+1) */ acb_get_mag(t, logaNi); arf_set_mag(arb_midref(x), t); mag_zero(arb_radref(x)); arb_pow_fmpz(x, x, n1, prec); arb_mul(x, x, y, prec); arb_get_mag(bound, x); } arb_clear(x); arb_clear(y); arb_clear(D); acb_clear(aNi); acb_clear(logaNi); mag_clear(t); mag_clear(u); } void _acb_dirichlet_stieltjes_integral2(acb_t res, const fmpz_t n, const acb_t alpha, slong prec) { double gamma_mag, max_mag, cancellation, xa; fmpz_t n1; acb_t a, b, v, w; slong wp; mag_t tol, bound; acb_calc_integrate_opt_t opt; _stieltjes_param param; /* integration points */ arb_t M, N, C; /* required for the integral representation to be valid */ if (!arb_is_positive(acb_realref(alpha))) { acb_indeterminate(res); return; } fmpz_init(n1); arb_init(M); arb_init(N); arb_init(C); acb_init(a); acb_init(b); acb_init(v); acb_init(w); mag_init(tol); mag_init(bound); fmpz_add_ui(n1, n, 1); param.n1 = n1; param.alpha = alpha; arb_set_ui(M, 10); stieltjes_choose_N(N, n1, alpha, prec); stieltjes_tail_bound(bound, N, n1, alpha); if (acb_is_real(alpha) && arf_cmpabs_2exp_si(arb_midref(acb_realref(alpha)), 2) < 0 && fmpz_cmp_ui(n1, 5000) < 0) { double nn = fmpz_get_ui(n1) - 1; gamma_mag = stieltjes_mag(nn); xa = find_x_maximizing_mag(nn, 0.0); max_mag = integrand_mag(nn, xa, 0.0, 0.5, 0.0); cancellation = FLINT_MAX(0, max_mag - gamma_mag); if (cancellation < 10 + 0.1 * prec) { arb_zero(C); mag_one(tol); mag_mul_2exp_si(tol, tol, gamma_mag); } else { stieltjes_mag_approx(C, tol, n1, alpha); cancellation = 0; } } else { stieltjes_mag_approx(C, tol, n1, alpha); cancellation = 0; } mag_mul_2exp_si(tol, tol, -prec - 5); /* todo: 1 * fmpz_bits(n1) should be enough, but acb powering is inaccurate */ wp = prec + 2 * fmpz_bits(n1) + cancellation + 10; acb_calc_integrate_opt_init(opt); /* opt->verbose = 1; */ opt->deg_limit = 100 + 1.2 * prec; /* Small speedup. */ if (arb_is_zero(C)) { acb_zero(a); acb_set_arb(b, N); acb_calc_integrate(w, _f_stieltjes, ¶m, a, b, wp, tol, opt, wp); acb_add(v, v, w, wp); } else { acb_zero(a); /* a = 0 */ acb_set_arb(b, M); /* b = M */ acb_calc_integrate(w, _f_stieltjes, ¶m, a, b, wp, tol, opt, wp); acb_add(v, v, w, wp); acb_set(a, b); acb_set_arb(b, M); arb_set(acb_imagref(b), C); /* b = M + i C */ acb_calc_integrate(w, _f_stieltjes, ¶m, a, b, wp, tol, opt, wp); acb_add(v, v, w, wp); acb_set(a, b); arb_set(acb_realref(b), N); /* b = N + i C */ acb_calc_integrate(w, _f_stieltjes, ¶m, a, b, wp, tol, opt, wp); acb_add(v, v, w, wp); acb_set(a, b); arb_zero(acb_imagref(b)); /* b = N */ acb_calc_integrate(w, _f_stieltjes, ¶m, a, b, wp, tol, opt, wp); acb_add(v, v, w, wp); } acb_add_error_mag(v, bound); acb_const_pi(b, wp); acb_mul(v, v, b, wp); acb_div_fmpz(v, v, n1, wp); acb_neg(v, v); if (acb_is_real(alpha)) arb_zero(acb_imagref(v)); acb_set_round(res, v, prec); fmpz_clear(n1); acb_clear(a); acb_clear(b); acb_clear(v); acb_clear(w); mag_clear(tol); mag_clear(bound); arb_clear(M); arb_clear(N); arb_clear(C); } void _acb_dirichlet_stieltjes_integral(acb_t res, const fmpz_t n, const acb_t a, slong prec) { acb_t alpha; acb_init(alpha); /* alpha = a-1/2 */ acb_set_d(alpha, 0.5); acb_sub(alpha, a, alpha, prec); if (acb_is_real(a)) { acb_conj(alpha, alpha); _acb_dirichlet_stieltjes_integral2(res, n, alpha, prec); } else { acb_t r1, r2; acb_init(r1); acb_init(r2); _acb_dirichlet_stieltjes_integral2(r1, n, alpha, prec); acb_conj(alpha, alpha); _acb_dirichlet_stieltjes_integral2(r2, n, alpha, prec); acb_conj(r2, r2); acb_add(res, r1, r2, prec); acb_mul_2exp_si(res, res, -1); acb_clear(r1); acb_clear(r2); } acb_clear(alpha); } void acb_dirichlet_stieltjes_integral(acb_t res, const fmpz_t n, const acb_t a, slong prec) { /* the algorithm only works for re(a) > 1/2 */ if (arf_cmp_si(arb_midref(acb_realref(a)), 1) < 0) { slong k, m, wp; acb_t ak, t, s; if (arf_cmp_si(arb_midref(acb_realref(a)), -prec) < 0) { acb_indeterminate(res); return; } m = 1 - arf_get_si(arb_midref(acb_realref(a)), ARF_RND_FLOOR); acb_init(ak); acb_init(t); acb_init(s); wp = prec + 2 * fmpz_bits(n); for (k = 0; k < m; k++) { acb_add_si(ak, a, k, wp); acb_log(t, ak, wp); acb_pow_fmpz(t, t, n, wp); acb_div(t, t, ak, wp); acb_add(s, s, t, wp); } acb_add_si(ak, a, m, wp); _acb_dirichlet_stieltjes_integral(t, n, ak, prec); acb_add(res, s, t, prec); acb_clear(s); acb_clear(t); acb_clear(ak); } else { _acb_dirichlet_stieltjes_integral(res, n, a, prec); } } void acb_dirichlet_stieltjes_em(acb_t res, const fmpz_t n, const acb_t a, slong prec) { if (fmpz_cmp_ui(n, 10000) > 0) { acb_indeterminate(res); } else { slong nn, wp; acb_ptr z; acb_t s; nn = fmpz_get_ui(n); acb_init(s); z = _acb_vec_init(nn + 1); wp = prec * 1.05 + 2.2*nn + 10; /* todo: bogus */ /* todo: we don't want to compute all the coefficients */ acb_one(s); _acb_poly_zeta_cpx_series(z, s, a, 1, nn + 1, wp); arb_fac_ui(acb_realref(s), nn, prec + 10); acb_mul_arb(res, z + nn, acb_realref(s), prec); if (fmpz_is_odd(n)) acb_neg(res, res); acb_clear(s); _acb_vec_clear(z, nn + 1); } } void acb_dirichlet_stieltjes(acb_t res, const fmpz_t n, const acb_t a, slong prec) { slong cutoff; if (acb_is_one(a) && fmpz_is_zero(n)) { arb_const_euler(acb_realref(res), prec); arb_zero(acb_imagref(res)); return; } if (fmpz_sgn(n) < 0) { flint_throw(FLINT_ERROR, "stieltjes constants only defined for n >= 0"); } /* undefined at a = 0, -1, -2, ... */ if (acb_contains_int(a) && !arb_is_positive(acb_realref(a))) { acb_indeterminate(res); return; } cutoff = FLINT_MAX(100, prec / 2); cutoff = FLINT_MIN(cutoff, 10000); if (fmpz_cmp_ui(n, cutoff) >= 0) { acb_dirichlet_stieltjes_integral(res, n, a, prec); } else { acb_dirichlet_stieltjes_em(res, n, a, prec); } } flint-3.1.3/src/acb_dirichlet/test/000077500000000000000000000000001461254215100171555ustar00rootroot00000000000000flint-3.1.3/src/acb_dirichlet/test/main.c000066400000000000000000000102271461254215100202470ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-backlund_s_bound.c" #include "t-backlund_s.c" #include "t-backlund_s_gram.c" #include "t-chi.c" #include "t-dft.c" #include "t-eta.c" #include "t-euler_product_real_ui.c" #include "t-gauss.c" #include "t-gram_point.c" #include "t-hardy_theta_series.c" #include "t-hardy_z.c" #include "t-hardy_z_series.c" #include "t-hardy_z_zero.c" #include "t-hardy_z_zeros.c" #include "t-hurwitz.c" #include "t-hurwitz_precomp.c" #include "t-isolate_hardy_z_zero.c" #include "t-jacobi.c" #include "t-l.c" #include "t-lerch_phi.c" #include "t-l_euler_product.c" #include "t-l_fmpq_afe.c" #include "t-l_fmpq.c" #include "t-l_hurwitz.c" #include "t-l_jet.c" #include "t-l_series.c" #include "t-l_vec_hurwitz.c" #include "t-platt_beta.c" #include "t-platt_hardy_z_zeros.c" #include "t-platt_local_hardy_z_zeros.c" #include "t-platt_multieval.c" #include "t-platt_multieval_threaded.c" #include "t-platt_ws_interpolation.c" #include "t-platt_zeta_zeros.c" #include "t-powsum_smooth.c" #include "t-roots.c" #include "t-stieltjes.c" #include "t-thetanull.c" #include "t-turing_method_bound.c" #include "t-xi.c" #include "t-zeta_bound.c" #include "t-zeta_jet_rs.c" #include "t-zeta_nzeros.c" #include "t-zeta_nzeros_gram.c" #include "t-zeta_rs.c" #include "t-zeta_rs_r.c" #include "t-zeta_zero.c" #include "t-zeta_zeros.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_dirichlet_backlund_s_bound), TEST_FUNCTION(acb_dirichlet_backlund_s), TEST_FUNCTION(acb_dirichlet_backlund_s_gram), TEST_FUNCTION(acb_dirichlet_chi), TEST_FUNCTION(acb_dirichlet_dft), TEST_FUNCTION(acb_dirichlet_eta), TEST_FUNCTION(acb_dirichlet_euler_product_real_ui), TEST_FUNCTION(acb_dirichlet_gauss), TEST_FUNCTION(acb_dirichlet_gram_point), TEST_FUNCTION(acb_dirichlet_hardy_theta_series), TEST_FUNCTION(acb_dirichlet_hardy_z), TEST_FUNCTION(acb_dirichlet_hardy_z_series), TEST_FUNCTION(acb_dirichlet_hardy_z_zero), TEST_FUNCTION(acb_dirichlet_hardy_z_zeros), TEST_FUNCTION(acb_dirichlet_hurwitz), TEST_FUNCTION(acb_dirichlet_hurwitz_precomp), TEST_FUNCTION(acb_dirichlet_isolate_hardy_z_zero), TEST_FUNCTION(acb_dirichlet_jacobi), TEST_FUNCTION(acb_dirichlet_l), TEST_FUNCTION(acb_dirichlet_lerch_phi), TEST_FUNCTION(acb_dirichlet_l_euler_product), TEST_FUNCTION(acb_dirichlet_l_fmpq_afe), TEST_FUNCTION(acb_dirichlet_l_fmpq), TEST_FUNCTION(acb_dirichlet_l_hurwitz), TEST_FUNCTION(acb_dirichlet_l_jet), TEST_FUNCTION(acb_dirichlet_l_series), TEST_FUNCTION(acb_dirichlet_l_vec_hurwitz), TEST_FUNCTION(acb_dirichlet_platt_beta), TEST_FUNCTION(acb_dirichlet_platt_hardy_z_zeros), TEST_FUNCTION(acb_dirichlet_platt_local_hardy_z_zeros), TEST_FUNCTION(acb_dirichlet_platt_multieval), TEST_FUNCTION(acb_dirichlet_platt_multieval_threaded), TEST_FUNCTION(acb_dirichlet_platt_ws_interpolation), TEST_FUNCTION(acb_dirichlet_platt_zeta_zeros), TEST_FUNCTION(acb_dirichlet_powsum_smooth), TEST_FUNCTION(acb_dirichlet_roots), TEST_FUNCTION(acb_dirichlet_stieltjes), TEST_FUNCTION(acb_dirichlet_thetanull), TEST_FUNCTION(acb_dirichlet_turing_method_bound), TEST_FUNCTION(acb_dirichlet_xi), TEST_FUNCTION(acb_dirichlet_zeta_bound), TEST_FUNCTION(acb_dirichlet_zeta_jet_rs), TEST_FUNCTION(acb_dirichlet_zeta_nzeros), TEST_FUNCTION(acb_dirichlet_zeta_nzeros_gram), TEST_FUNCTION(acb_dirichlet_zeta_rs), TEST_FUNCTION(acb_dirichlet_zeta_rs_r), TEST_FUNCTION(acb_dirichlet_zeta_zero), TEST_FUNCTION(acb_dirichlet_zeta_zeros) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_dirichlet/test/t-backlund_s.c000066400000000000000000000030521461254215100216670ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_backlund_s, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); arb_init(a); arb_init(b); arb_init(c); arb_randtest(a, state, 1 + n_randint(state, 1000), 4); acb_dirichlet_backlund_s(b, a, prec1); if (n_randint(state, 2)) { acb_dirichlet_backlund_s(c, a, prec2); } else /* test aliasing */ { arb_set(c, a); acb_dirichlet_backlund_s(c, c, prec2); } if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-backlund_s_bound.c000066400000000000000000000035231461254215100230610ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_backlund_s_bound, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; mag_t u, v; slong aprec, bprec; slong abits, bbits; aprec = 2 + n_randint(state, 1000); bprec = 2 + n_randint(state, 1000); abits = 2 + n_randint(state, 100); bbits = 2 + n_randint(state, 100); arb_init(a); arb_init(b); mag_init(u); mag_init(v); arb_randtest(a, state, aprec, abits); arb_randtest(b, state, bprec, bbits); if (arb_is_nonnegative(a) && arb_is_nonnegative(b)) { acb_dirichlet_backlund_s_bound(u, a); acb_dirichlet_backlund_s_bound(v, b); if ((arb_lt(a, b) && mag_cmp(u, v) > 0) || (arb_gt(a, b) && mag_cmp(u, v) < 0)) { flint_printf("FAIL: increasing on t >= 0\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("u = "); mag_print(u); flint_printf("\n\n"); flint_printf("v = "); mag_print(v); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); mag_clear(u); mag_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-backlund_s_gram.c000066400000000000000000000033171461254215100227010ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_backlund_s_gram, state) { slong iter; for (iter = 0; iter < 130 + 20 * 0.1 * flint_test_multiplier(); iter++) { arb_t t, x; fmpz_t n; slong S, prec1, prec2; arb_init(t); arb_init(x); fmpz_init(n); if (iter < 130) { fmpz_set_si(n, iter - 1); } else { fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 129); } prec1 = 2 + n_randtest(state) % 100; prec2 = 2 + n_randtest(state) % 100; S = acb_dirichlet_backlund_s_gram(n); acb_dirichlet_gram_point(t, n, NULL, NULL, prec1); acb_dirichlet_backlund_s(x, t, prec2); if (!arb_contains_si(x, S)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("S = %wd\n\n", S); flint_printf("t = "); arb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(t); arb_clear(x); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-chi.c000066400000000000000000000102051461254215100203230ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_chi, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t zn1, zn2, zn1n2, zn1zn2; dirichlet_group_t G; dirichlet_char_t chi; ulong q, m, n1, n2, iter2; int res; q = 1 + n_randint(state, 1000); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); acb_init(zn1); acb_init(zn2); acb_init(zn1n2); acb_init(zn1zn2); /* check chi(n1) chi(n2) = chi(n1 n2) */ for (iter2 = 0; iter2 < 10; iter2++) { do { m = 1 + n_randint(state, q); } while (n_gcd(q, m) != 1); dirichlet_char_log(chi, G, m); n1 = n_randint(state, 1000); n2 = n_randint(state, 1000); acb_dirichlet_chi(zn1, G, chi, n1, 53); acb_dirichlet_pairing(zn2, G, m, n1, 53); if (!acb_overlaps(zn1, zn2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("n = %wu\n\n", n1); flint_printf("char = "); acb_printd(zn1, 15); flint_printf("\n\n"); flint_printf("pairing = "); acb_printd(zn2, 15); flint_printf("\n\n"); dirichlet_char_print(G, chi); dirichlet_char_log(chi, G, m); flint_printf("log(m) = "); dirichlet_char_print(G, chi); dirichlet_char_log(chi, G, n1); flint_printf("log(n1) = "); dirichlet_char_print(G, chi); flint_abort(); } acb_dirichlet_pairing(zn2, G, m, n2, 53); acb_dirichlet_pairing(zn1n2, G, m, n1 * n2, 53); acb_mul(zn1zn2, zn1, zn2, 53); if (!acb_overlaps(zn1n2, zn1zn2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("n1 = %wu\n\n", n1); flint_printf("n2 = %wu\n\n", n2); flint_printf("zn1 = "); acb_printd(zn1, 15); flint_printf("\n\n"); flint_printf("zn2 = "); acb_printd(zn2, 15); flint_printf("\n\n"); flint_printf("zn1n2 = "); acb_printd(zn1n2, 15); flint_printf("\n\n"); flint_printf("zn1zn2 = "); acb_printd(zn1zn2, 15); flint_printf("\n\n"); flint_abort(); } } if (iter % 10 == 0) { /* check orthogonality */ acb_zero(zn1); n1 = n_randint(state, 1000); for (m = 1; m <= q; m++) { if (n_gcd(q, m) == 1) { acb_dirichlet_pairing(zn2, G, m, n1, 53); acb_add(zn1, zn1, zn2, 53); } } if (n1 % q == 1 % q) res = arb_contains_si(acb_realref(zn1), n_euler_phi(q)) && arb_contains_zero(acb_imagref(zn1)); else res = acb_contains_zero(zn1); if (!res) { flint_printf("FAIL: orthogonality\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("phi = %wu\n\n", n_euler_phi(q)); flint_printf("n1 = %wu\n\n", n1); flint_printf("zn1 = "); acb_printd(zn1, 15); flint_printf("\n\n"); flint_abort(); } } dirichlet_group_clear(G); dirichlet_char_clear(chi); acb_clear(zn1); acb_clear(zn2); acb_clear(zn1n2); acb_clear(zn1zn2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-dft.c000066400000000000000000000070111461254215100203360ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" typedef void (*do_f) (acb_ptr w, acb_srcptr v, slong len, slong prec); void check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char f1[], char f2[]) { slong i; for (i = 0; i < len; i++) { if (!acb_overlaps(w1 + i, w2 + i)) { flint_printf("FAIL\n\n"); flint_printf("q = %wu, size = %wd\n", q, len); flint_printf("\nDFT differ from index %wd / %wd \n", i, len); flint_printf("\n%s =\n", f1); _acb_vec_printd(w1, len, digits); flint_printf("\n%s =\n", f2); _acb_vec_printd(w2, len, digits); flint_printf("\n\n"); flint_abort(); } else if (acb_rel_accuracy_bits(w1 + i) < 30 || acb_rel_accuracy_bits(w2 + i) < 30) { flint_printf("FAIL\n\n"); flint_printf("q = %wu\n", q); flint_printf("\nDFT inaccurate from index %wd / %wd \n", i, len); flint_printf("\nnaive =\n"); acb_printd(w1 + i, digits); flint_printf("\nfast =\n"); acb_printd(w2 + i, digits); flint_printf("\nerrors %wd & %wd [prec = %wd]\n", acb_rel_accuracy_bits(w1 + i), acb_rel_accuracy_bits(w2 + i), prec); flint_abort(); } } } TEST_FUNCTION_START(acb_dirichlet_dft, state) { slong k; slong prec = 100, digits = 30; slong nq = 13; ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; /* Dirichlet group DFT */ for (k = 0; k < nq; k++) { slong i, j, len; dirichlet_group_t G; dirichlet_char_t x, y; acb_dirichlet_roots_t roots; acb_t chiy; acb_ptr v, w1, w2; dirichlet_group_init(G, q[k]); len = G->phi_q; v = _acb_vec_init(len); w1 = _acb_vec_init(len); w2 = _acb_vec_init(len); acb_init(chiy); acb_dirichlet_roots_init(roots, G->expo, len, prec); dirichlet_char_init(x, G); dirichlet_char_init(y, G); for (i = 0; i < len; i++) acb_randtest_precise(v + i, state, prec, 0); /* naive */ dirichlet_char_one(x, G); for (i = 0; i < len; i++) { acb_zero(w1 + i); dirichlet_char_one(y, G); for (j = 0; j < len; j++) { acb_dirichlet_root(chiy, roots, dirichlet_pairing_char(G, x, y), prec); acb_conj(chiy, chiy); acb_addmul(w1 + i, chiy, v + j, prec); dirichlet_char_next(y, G); } dirichlet_char_next(x, G); } /* dft */ acb_dirichlet_dft_index(w2, v, G, prec); check_vec_eq_prec(w1, w2, len, prec, digits, q[k], "naive", "group"); _acb_vec_clear(v, len); _acb_vec_clear(w1, len); _acb_vec_clear(w2, len); acb_dirichlet_roots_clear(roots); dirichlet_char_clear(x); dirichlet_char_clear(y); dirichlet_group_clear(G); acb_clear(chiy); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-eta.c000066400000000000000000000033171461254215100203370ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_eta, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { acb_t z1, z2, s1, s2; slong prec1, prec2; acb_init(z1); acb_init(z2); acb_init(s1); acb_init(s2); acb_randtest(s1, state, 2 + n_randint(state, 100), 3); acb_randtest(z1, state, 2 + n_randint(state, 100), 3); acb_randtest(z2, state, 2 + n_randint(state, 100), 3); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); acb_add(s2, s1, z1, prec2); acb_sub(s2, s2, z1, prec2); acb_dirichlet_eta(z1, s1, prec1); acb_dirichlet_eta(z2, s2, prec2); if (!acb_overlaps(z1, z2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("s1 = "); acb_printn(s1, 50, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 50, 0); flint_printf("\n\n"); flint_printf("z1 = "); acb_printn(z1, 50, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z1); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-euler_product_real_ui.c000066400000000000000000000074101461254215100241400ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif const signed char chi[8][6] = { {1, 1}, {2, 0, 1}, {3, 0, 1, 1}, {3, 0, 1, -1}, {4, 0, 1, 0, 1}, {4, 0, 1, 0, -1}, {5, 0, 1, 1, 1, 1}, {5, 0, 1, -1, -1, 1}, }; const double L10[8] = { 1.0009945751278180853371459589, 1.0000170413630448254881839023, 1.00097762319679253337038382667, 0.999024291448866695201196896346, 1.0000170413630448254881839023, 0.999983164026196877405540729958, 1.00099447262597359224857402038, 0.999007468458940084215357132419 }; TEST_FUNCTION_START(acb_dirichlet_euler_product_real_ui, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { arb_t res1, res2; ulong s; slong prec1, prec2, accuracy; int choice, reciprocal1, reciprocal2; if (iter % 10 == 0) { s = n_randtest(state); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); } else { s = 6 + n_randint(state, 1 << n_randint(state, 12)); prec1 = 2 + n_randint(state, 12 * s); prec2 = 2 + n_randint(state, 12 * s); } if (n_randint(state, 30) == 0) prec1 = 2 + n_randint(state, 4000); choice = n_randint(state, 7); reciprocal1 = n_randint(state, 2); reciprocal2 = n_randint(state, 2); arb_init(res1); arb_init(res2); arb_randtest(res1, state, 200, 100); _acb_dirichlet_euler_product_real_ui(res1, s, chi[choice] + 1, chi[choice][0], reciprocal1, prec1); _acb_dirichlet_euler_product_real_ui(res2, s, chi[choice] + 1, chi[choice][0], reciprocal2, prec2); if (reciprocal1 != reciprocal2) arb_inv(res2, res2, prec2); if (!arb_overlaps(res1, res2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("s = %wu\n\n", s); flint_printf("chi: %d\n", choice); flint_printf("res1 = "); arb_printd(res1, prec1 / 3.33); flint_printf("\n\n"); flint_printf("res2 = "); arb_printd(res2, prec2 / 3.33); flint_printf("\n\n"); flint_abort(); } if (s >= 6 && prec1 < 2 * s * log(s)) { accuracy = arb_rel_accuracy_bits(res1); if (accuracy < prec1 - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec1); flint_printf("res1 = "); arb_printd(res1, prec1 / 3.33); flint_printf("\n\n"); flint_abort(); } } if (s == 10) { arf_set_d(arb_midref(res2), L10[choice]); mag_set_d(arb_radref(res2), 1e-15); if (reciprocal1) arb_inv(res2, res2, 53); if (!arb_overlaps(res1, res2)) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("s = %wu\n\n", s); flint_printf("chi: %d\n", choice); flint_printf("res1 = "); arb_printd(res1, prec1 / 3.33); flint_printf("\n\n"); flint_printf("res2 = "); arb_printd(res2, prec2 / 3.33); flint_printf("\n\n"); flint_abort(); } } arb_clear(res1); arb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-gauss.c000066400000000000000000000040661461254215100207120ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_gauss, state) { slong prec = 128; ulong q; /* check Gauss sums */ for (q = 3; q < 250; q ++) { dirichlet_group_t G; dirichlet_char_t chi; acb_t s1, s2, s3, s4; dirichlet_group_init(G, q); dirichlet_char_init(chi, G); acb_init(s1); acb_init(s2); acb_init(s3); acb_init(s4); dirichlet_char_one(chi, G); while (1) { acb_dirichlet_gauss_sum_naive(s1, G, chi, prec); acb_dirichlet_gauss_sum(s2, G, chi, prec); acb_dirichlet_gauss_sum_factor(s3, G, chi, prec); if (dirichlet_conductor_char(G, chi) == G->q) acb_dirichlet_gauss_sum_theta(s4, G, chi, prec); else acb_set(s4, s1); if (!acb_overlaps(s1, s2) || !acb_overlaps(s1, s3) || !acb_overlaps(s1, s4)) { flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->n); flint_printf("\nnaive "); acb_printd(s1, 25); flint_printf("\ndefault "); acb_printd(s2, 25); flint_printf("\nfactor "); acb_printd(s3, 25); flint_printf("\ntheta "); acb_printd(s4, 25); flint_abort(); } if (dirichlet_char_next(chi, G) < 0) break; } acb_clear(s1); acb_clear(s2); acb_clear(s3); acb_clear(s4); dirichlet_group_clear(G); dirichlet_char_clear(chi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-gram_point.c000066400000000000000000000055761461254215100217360ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_gram_point, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x1, x2, v1, v2, pin; acb_t t; fmpz_t n; slong prec1, prec2; arb_init(x1); arb_init(x2); arb_init(v1); arb_init(v2); arb_init(pin); acb_init(t); fmpz_init(n); fmpz_randtest_unsigned(n, state, 500); fmpz_sub_ui(n, n, 1); prec1 = 2 + n_randtest(state) % 500; prec2 = 2 + n_randtest(state) % 2000; acb_dirichlet_gram_point(x1, n, NULL, NULL, prec1); acb_dirichlet_gram_point(x2, n, NULL, NULL, prec2); arb_const_pi(pin, FLINT_MAX(prec1, prec2) + 20); arb_mul_fmpz(pin, pin, n, FLINT_MAX(prec1, prec2) + 20); acb_set_arb(t, x1); acb_dirichlet_hardy_theta(t, t, NULL, NULL, 1, prec1 + 20); arb_set(v1, acb_realref(t)); acb_set_arb(t, x2); acb_dirichlet_hardy_theta(t, t, NULL, NULL, 1, prec2 + 20); arb_set(v2, acb_realref(t)); if (!arb_overlaps(x1, x2) || !arb_contains(v1, pin) || !arb_contains(v2, pin)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_printf("v1 = "); arb_printn(v1, 100, 0); flint_printf("\n\n"); flint_printf("v2 = "); arb_printn(v2, 100, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(x1) < prec1 - 3 || arb_rel_accuracy_bits(x2) < prec2 - 3) { flint_printf("FAIL: accuracy\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("acc(x1) = %wd, acc(x2) = %wd\n\n", arb_rel_accuracy_bits(x1), arb_rel_accuracy_bits(x2)); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x1); arb_clear(x2); arb_clear(v1); arb_clear(v2); arb_clear(pin); acb_clear(t); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-hardy_theta_series.c000066400000000000000000000044641461254215100234400ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_hardy_theta_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; dirichlet_group_t G; dirichlet_char_t chi; ulong q; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 8); n1 = 1 + n_randint(state, 8); n2 = 1 + n_randint(state, 8); do { q = 1 + n_randint(state, 15); } while (q % 4 == 2); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); do { dirichlet_char_index(chi, G, n_randint(state, G->phi_q)); } while (!dirichlet_char_is_primitive(G, chi)); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_randtest(S, state, m, bits1, 3); acb_dirichlet_hardy_theta_series(A, S, G, chi, n1, bits2); acb_poly_set(B, S); /* aliasing */ acb_dirichlet_hardy_theta_series(B, B, G, chi, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); dirichlet_char_clear(chi); dirichlet_group_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-hardy_z.c000066400000000000000000000072341461254215100212300ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_hardy_z, state) { slong iter; /* test self-consistency */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, s2; dirichlet_group_t G; dirichlet_char_t chi; acb_ptr vec1, vec2; slong len1, len2; slong prec1, prec2; ulong q, k; slong i; len1 = n_randint(state, 6); len2 = n_randint(state, 6); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); do { q = 1 + n_randint(state, 30); } while (q % 4 == 2); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); do { k = n_randint(state, n_euler_phi(q)); dirichlet_char_index(chi, G, k); } while (dirichlet_conductor_char(G, chi) != q); acb_init(s); acb_init(s2); vec1 = _acb_vec_init(len1); vec2 = _acb_vec_init(len2); acb_randtest(s, state, 2 + n_randint(state, 200), 2); acb_randtest(s2, state, 2 + n_randint(state, 200), 2); acb_sub(s2, s2, s2, 200); acb_add(s2, s, s2, 200); acb_dirichlet_hardy_z(vec1, s, G, chi, len1, prec1); acb_dirichlet_hardy_z(vec2, s2, G, chi, len2, prec2); for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(vec1 + i, vec2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd q = %wu k = %wu i = %wd\n\n", iter, q, k, i); flint_printf("s = "); acb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); acb_printn(vec1 + i, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); acb_printn(vec2 + i, 50, 0); flint_printf("\n\n"); flint_abort(); } } if (arb_contains_zero(acb_imagref(s))) { for (i = 0; i < len1; i++) { if (!arb_contains_zero(acb_imagref(vec1 + i))) { flint_printf("FAIL: real 1\n\n"); flint_printf("iter = %wd q = %wu k = %wu i = %wd\n\n", iter, q, k, i); flint_printf("s = "); acb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); acb_printn(vec1 + i, 50, 0); flint_printf("\n\n"); flint_abort(); } } } if (arb_contains_zero(acb_imagref(s2))) { for (i = 0; i < len2; i++) { if (!arb_contains_zero(acb_imagref(vec2 + i))) { flint_printf("FAIL: real 1\n\n"); flint_printf("iter = %wd q = %wu k = %wu i = %wd\n\n", iter, q, k, i); flint_printf("s = "); acb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); acb_printn(vec2 + i, 50, 0); flint_printf("\n\n"); flint_abort(); } } } dirichlet_char_clear(chi); dirichlet_group_clear(G); acb_clear(s); acb_clear(s2); _acb_vec_clear(vec1, len1); _acb_vec_clear(vec2, len2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-hardy_z_series.c000066400000000000000000000045631461254215100226040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_hardy_z_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; dirichlet_group_t G; dirichlet_char_t chi; ulong q; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 8); n1 = 1 + n_randint(state, 8); n2 = 1 + n_randint(state, 8); do { q = 1 + n_randint(state, 15); } while (q % 4 == 2); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); do { dirichlet_char_index(chi, G, n_randint(state, G->phi_q)); } while (!dirichlet_char_is_primitive(G, chi)); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_randtest(S, state, m, bits1, 3); acb_dirichlet_hardy_z_series(A, S, G, chi, n1, bits2); acb_poly_set(B, S); /* aliasing */ if (q == 1 && n_randint(state, 2)) acb_poly_neg(B, B); acb_dirichlet_hardy_z_series(B, B, G, chi, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); dirichlet_char_clear(chi); dirichlet_group_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-hardy_z_zero.c000066400000000000000000000052561461254215100222710ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_hardy_z_zero, state) { slong iter; for (iter = 0; iter < 20 * 0.1 * flint_test_multiplier(); iter++) { arb_t x1, x2, v1, v2; acb_t t; fmpz_t n; slong prec1, prec2; arb_init(x1); arb_init(x2); arb_init(v1); arb_init(v2); acb_init(t); fmpz_init(n); fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 1); prec1 = 2 + n_randtest(state) % 50; prec2 = 2 + n_randtest(state) % 200; acb_dirichlet_hardy_z_zero(x1, n, prec1); acb_dirichlet_hardy_z_zero(x2, n, prec2); acb_set_arb(t, x1); acb_dirichlet_hardy_z(t, t, NULL, NULL, 1, prec1 + 20); arb_set(v1, acb_realref(t)); acb_set_arb(t, x2); acb_dirichlet_hardy_z(t, t, NULL, NULL, 1, prec2 + 20); arb_set(v2, acb_realref(t)); if (!arb_overlaps(x1, x2) || !arb_contains_zero(v1) || !arb_contains_zero(v2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_printf("v1 = "); arb_printn(v1, 100, 0); flint_printf("\n\n"); flint_printf("v2 = "); arb_printn(v2, 100, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(x1) < prec1 - 3 || arb_rel_accuracy_bits(x2) < prec2 - 3) { flint_printf("FAIL: accuracy\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("acc(x1) = %wd, acc(x2) = %wd\n\n", arb_rel_accuracy_bits(x1), arb_rel_accuracy_bits(x2)); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x1); arb_clear(x2); arb_clear(v1); arb_clear(v2); acb_clear(t); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-hardy_z_zeros.c000066400000000000000000000057751461254215100224620ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_hardy_z_zeros, state) { slong iter; for (iter = 0; iter < 20 * 0.1 * flint_test_multiplier(); iter++) { arb_t x1, x2, v1, v2; acb_t t; fmpz_t n, k; slong prec1, prec2; slong len, i; const slong maxlen = 5; arb_ptr p; arb_init(x1); arb_init(x2); arb_init(v1); arb_init(v2); acb_init(t); fmpz_init(n); fmpz_init(k); p = _arb_vec_init(maxlen); fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 1); prec1 = 2 + n_randtest(state) % 50; prec2 = 2 + n_randtest(state) % 200; len = 1 + n_randint(state, maxlen); i = n_randint(state, len); acb_dirichlet_hardy_z_zeros(p, n, len, prec1); arb_set(x1, p + i); fmpz_add_si(k, n, i); acb_dirichlet_hardy_z_zero(x2, k, prec2); acb_set_arb(t, x1); acb_dirichlet_hardy_z(t, t, NULL, NULL, 1, prec1 + 20); arb_set(v1, acb_realref(t)); acb_set_arb(t, x2); acb_dirichlet_hardy_z(t, t, NULL, NULL, 1, prec2 + 20); arb_set(v2, acb_realref(t)); if (!arb_overlaps(x1, x2) || !arb_contains_zero(v1) || !arb_contains_zero(v2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_printf("v1 = "); arb_printn(v1, 100, 0); flint_printf("\n\n"); flint_printf("v2 = "); arb_printn(v2, 100, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(x1) < prec1 - 3 || arb_rel_accuracy_bits(x2) < prec2 - 3) { flint_printf("FAIL: accuracy\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("acc(x1) = %wd, acc(x2) = %wd\n\n", arb_rel_accuracy_bits(x1), arb_rel_accuracy_bits(x2)); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x1); arb_clear(x2); arb_clear(v1); arb_clear(v2); acb_clear(t); fmpz_clear(n); fmpz_clear(k); _arb_vec_clear(p, maxlen); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-hurwitz.c000066400000000000000000000045301461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_hurwitz, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, a, b, z1, z2; slong prec1, prec2; acb_init(s); acb_init(a); acb_init(b); acb_init(z1); acb_init(z2); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); acb_randtest(s, state, 1 + n_randint(state, 500), 3); acb_randtest(a, state, 1 + n_randint(state, 500), 3); acb_randtest(b, state, 1 + n_randint(state, 500), 10); acb_randtest(z1, state, 1 + n_randint(state, 500), 10); acb_randtest(z2, state, 1 + n_randint(state, 500), 10); if (n_randint(state, 2)) acb_set_si(a, n_randint(state, 100) - 50); if (n_randint(state, 2)) acb_set_si(s, n_randint(state, 100) - 50); /* test zeta(s,a) = 2^(-s) (zeta(s,a/2) + zeta(s,(a+1)/2)) */ acb_mul_2exp_si(b, a, -1); acb_dirichlet_hurwitz(z2, s, b, prec2); acb_add_ui(b, a, 1, prec2); acb_mul_2exp_si(b, b, -1); acb_dirichlet_hurwitz(b, s, b, prec2); acb_add(z2, z2, b, prec2); acb_neg(b, s); acb_set_ui(z1, 2); acb_pow(b, z1, b, prec2); acb_mul(z2, z2, b, prec2); acb_dirichlet_hurwitz(z1, s, a, prec1); if (!acb_overlaps(z1, z2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(s); acb_clear(a); acb_clear(b); acb_clear(z1); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-hurwitz_precomp.c000066400000000000000000000045311461254215100230260ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_dirichlet_hurwitz_precomp, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, a, z1, z2; ulong p, q; slong prec1, prec2, A, K, N, i; acb_dirichlet_hurwitz_precomp_t pre; int deflate; prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); A = 1 + n_randint(state, 10); K = 1 + n_randint(state, 10); N = 1 + n_randint(state, 10); deflate = (n_randint(state, 3) == 0); acb_init(s); acb_init(a); acb_init(z1); acb_init(z2); acb_randtest(s, state, 1 + n_randint(state, 200), 2); acb_dirichlet_hurwitz_precomp_init(pre, s, deflate, A, K, N, prec1); for (i = 0; i < 10; i++) { q = 1 + n_randint(state, 1000); p = 1 + n_randint(state, q); acb_dirichlet_hurwitz_precomp_eval(z1, pre, p, q, prec1); acb_set_ui(a, p); acb_div_ui(a, a, q, prec2); if (deflate) _acb_poly_zeta_cpx_series(z2, s, a, 1, 1, prec2); else acb_hurwitz_zeta(z2, s, a, prec2); if (!acb_overlaps(z1, z2)) { flint_printf("FAIL! (overlap)"); flint_printf("s = "); acb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("A = %wd K = %wd N = %wd\n\n", A, K, N); flint_printf("p = %wu q = %wu\n\n", p, q); flint_printf("z1 = "); acb_printn(z1, 50, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 50, 0); flint_printf("\n\n"); flint_abort(); } } acb_dirichlet_hurwitz_precomp_clear(pre); acb_clear(s); acb_clear(a); acb_clear(z1); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-isolate_hardy_z_zero.c000066400000000000000000000050511461254215100240020ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" static void _check_interval(const arf_t a, const arf_t b, const fmpz_t n) { arb_t v; int sa, sb; slong prec = arf_bits(b) + 8; arb_init(v); if (arf_cmp(a, b) >= 0) { flint_printf("FAIL: interval endpoint ordering\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_abort(); } sa = _acb_dirichlet_definite_hardy_z(v, a, &prec); sb = _acb_dirichlet_definite_hardy_z(v, b, &prec); if (sa == sb) { flint_printf("FAIL: interval endpoint function signs\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("sa = %d\n\n", sa); flint_printf("sb = %d\n\n", sb); flint_abort(); } arb_clear(v); } TEST_FUNCTION_START(acb_dirichlet_isolate_hardy_z_zero, state) { slong iter; for (iter = 0; iter < 126 + 20 * 0.1 * flint_test_multiplier(); iter++) { arf_t a, b; fmpz_t n; arf_init(a); arf_init(b); fmpz_init(n); if (iter < 126) { fmpz_set_si(n, iter + 1); } else { fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 127); } acb_dirichlet_isolate_hardy_z_zero(a, b, n); _check_interval(a, b, n); if (fmpz_cmp_si(n, 126) <= 0) { _acb_dirichlet_isolate_gram_hardy_z_zero(a, b, n); _check_interval(a, b, n); } if (fmpz_cmp_si(n, 13999526) <= 0) { _acb_dirichlet_isolate_rosser_hardy_z_zero(a, b, n); _check_interval(a, b, n); } if (fmpz_cmp_si(n, 2) >= 0) { _acb_dirichlet_isolate_turing_hardy_z_zero(a, b, n); _check_interval(a, b, n); } arf_clear(a); arf_clear(b); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-jacobi.c000066400000000000000000000044101461254215100210100ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_jacobi, state) { slong prec = 128; ulong q; /* check Jacobi sums */ for (q = 29 * 29; q > 1; q = q%2 ? 3*q+1 : q/2) { slong m1, m2; dirichlet_group_t G; dirichlet_char_t chi1, chi2; acb_t s1, s2; dirichlet_group_init(G, q); dirichlet_char_init(chi1, G); dirichlet_char_init(chi2, G); acb_init(s1); acb_init(s2); dirichlet_char_one(chi1, G); for (m1 = 0; m1 < 50; m1++) { dirichlet_char_one(chi2, G); for (m2 = 0; m2 < 50; m2++) { acb_dirichlet_jacobi_sum_naive(s1, G, chi1, chi2, prec); acb_dirichlet_jacobi_sum(s2, G, chi1, chi2, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL: J_%wu(%wu,%wu)", q, chi1->n, chi2->n); flint_printf("\nnaive "); acb_printd(s1, 25); flint_printf("\ndefault "); acb_printd(s2, 25); flint_printf("\n"); flint_printf("cond = %wu, %wu, %wu\n", dirichlet_conductor_char(G, chi1), dirichlet_conductor_char(G, chi2), dirichlet_conductor_ui(G, nmod_mul(chi1->n, chi2->n, G->mod)) ); flint_abort(); } if (dirichlet_char_next(chi2, G) < 0) break; } if (dirichlet_char_next(chi1, G) < 0) break; } acb_clear(s1); acb_clear(s2); dirichlet_group_clear(G); dirichlet_char_clear(chi1); dirichlet_char_clear(chi2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l.c000066400000000000000000000035671461254215100200300ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_l, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, t, u; dirichlet_group_t G; dirichlet_char_t chi; ulong q, k; slong prec; acb_init(s); acb_init(t); acb_init(u); q = 1 + n_randint(state, 50); prec = 2 + n_randint(state, 100); k = n_randint(state, n_euler_phi(q)); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_index(chi, G, k); if (n_randint(state, 2)) acb_set_si(s, n_randint(state, 50) - 25); else acb_randtest(s, state, 2 + n_randint(state, 200), 2); acb_dirichlet_l_hurwitz(t, s, NULL, G, chi, prec); acb_dirichlet_l(u, s, G, chi, prec); if (!acb_overlaps(t, u)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd q = %wu k = %wu prec = %wd\n\n", iter, q, k, prec); flint_printf("s = "); acb_printn(s, 100, 0); flint_printf("\n\n"); flint_printf("t = "); acb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("u = "); acb_printn(u, 100, 0); flint_printf("\n\n"); flint_abort(); } dirichlet_char_clear(chi); dirichlet_group_clear(G); acb_clear(s); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l_euler_product.c000066400000000000000000000043141461254215100227530ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_l_euler_product, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, t, u; dirichlet_group_t G; dirichlet_char_t chi; ulong q, k; slong prec; acb_init(s); acb_init(t); acb_init(u); q = 1 + n_randint(state, 50); prec = 2 + n_randint(state, 500); k = n_randint(state, n_euler_phi(q)); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_index(chi, G, k); if (n_randint(state, 2)) { acb_set_ui(s, 2 + n_randint(state, prec + 50)); } else { acb_randtest(s, state, 2 + n_randint(state, 200), 2); arb_abs(acb_realref(s), acb_realref(s)); if (n_randint(state, 2)) acb_add_ui(s, s, n_randtest(state), prec); } if (n_randint(state, 2)) acb_dirichlet_l_hurwitz(t, s, NULL, G, chi, prec); else acb_dirichlet_l_euler_product(t, s, G, chi, prec * 1.5); acb_dirichlet_l_euler_product(u, s, G, chi, prec); if (!acb_overlaps(t, u)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd q = %wu k = %wu prec = %wd\n\n", iter, q, k, prec); flint_printf("s = "); acb_printn(s, 100, 0); flint_printf("\n\n"); flint_printf("t = "); acb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("u = "); acb_printn(u, 100, 0); flint_printf("\n\n"); flint_abort(); } dirichlet_char_clear(chi); dirichlet_group_clear(G); acb_clear(s); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l_fmpq.c000066400000000000000000000043461461254215100210470ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_l_fmpq, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { fmpq_t x; acb_t s, t, u; dirichlet_group_t G; dirichlet_char_t chi; ulong q, k; slong prec; fmpq_init(x); acb_init(s); acb_init(t); acb_init(u); q = 1 + n_randint(state, 50); prec = 2 + n_randint(state, 300); k = n_randint(state, n_euler_phi(q)); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_index(chi, G, k); fmpq_randtest(x, state, 2 + n_randint(state, 100)); if (fmpq_get_d(x) < -100.0) fmpq_neg(x, x); acb_set_fmpq(s, x, prec); if (n_randint(state, 2)) acb_dirichlet_l_hurwitz(t, s, NULL, G, chi, prec); else acb_dirichlet_l(t, s, G, chi, prec); acb_dirichlet_l_fmpq(u, x, G, chi, prec); if (!acb_overlaps(t, u)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd q = %wu k = %wu prec = %wd\n\n", iter, q, k, prec); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("s = "); acb_printn(s, 100, 0); flint_printf("\n\n"); flint_printf("t = "); acb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("u = "); acb_printn(u, 100, 0); flint_printf("\n\n"); acb_sub(t, t, u, prec); flint_printf("t - u = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } dirichlet_char_clear(chi); dirichlet_group_clear(G); fmpq_clear(x); acb_clear(s); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l_fmpq_afe.c000066400000000000000000000046761461254215100216700ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_l_fmpq_afe, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_t x; acb_t s, t, u; dirichlet_group_t G; dirichlet_char_t chi; ulong q, k; slong prec; fmpq_init(x); acb_init(s); acb_init(t); acb_init(u); q = 1 + n_randint(state, 50); prec = 2 + n_randint(state, 400); k = n_randint(state, n_euler_phi(q)); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_index(chi, G, k); if (dirichlet_char_is_primitive(G, chi)) { if (n_randint(state, 2)) fmpq_set_si(x, -8 + (slong) n_randint(state, 8), 1); else fmpq_randtest(x, state, 2 + n_randint(state, 8)); acb_set_fmpq(s, x, prec); if (n_randint(state, 2)) acb_dirichlet_l_hurwitz(t, s, NULL, G, chi, prec); else acb_dirichlet_l(t, s, G, chi, prec); acb_dirichlet_l_fmpq_afe(u, x, G, chi, prec); if (!acb_overlaps(t, u)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd q = %wu k = %wu prec = %wd\n\n", iter, q, k, prec); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("s = "); acb_printn(s, 100, 0); flint_printf("\n\n"); flint_printf("t = "); acb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("u = "); acb_printn(u, 100, 0); flint_printf("\n\n"); acb_sub(t, t, u, prec); flint_printf("t - u = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } } dirichlet_char_clear(chi); dirichlet_group_clear(G); fmpq_clear(x); acb_clear(s); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l_hurwitz.c000066400000000000000000000114621461254215100216150ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" #define nq 5 #define nx 3 TEST_FUNCTION_START(acb_dirichlet_l_hurwitz, state) { slong i, j; ulong q[nq] = {3, 5, 61, 91, 800}; ulong m[nq] = {2, 4, 11, 2, 3}; slong prec = 150; acb_ptr x; /* cannot test at s = 1 with hurwitz */ const char * x_r[nx] = { "1", "0.5", "0.5" }; const char * x_i[nx] = { "1", "0", "6" }; acb_t ref, res; /* default(realprecision, 54) X = [ 1 + I, 1/2, 1/2 + 6 * I ] C = [Mod(2,3),Mod(4,5),Mod(11,61),Mod(2,91),Mod(3,800)] v = concat([ [lfun(c,x) | x<-X] | c<-C]) apply(z->printf("\"%s\",\n",real(z)),v) apply(z->printf("\"%s\",\n",imag(z)),v) */ const char * ref_r[nq * nx] = { "0.655527984002548033786648216345221087939439503905627469", "0.480867557696828626181220063235589877776829730832371863", "1.56831301727577320813799211138797101541772722814204757", "0.521271244517346991221550773660594765406476858135844321", "0.231750947504015755883383661760877226427886696409005898", "0.275543455389521803395512886745330595086898302178508437", "0.598221809458540554839300433683735304093606595684903281", "0.489264190003695740292779374874163221990017067040417393", "0.573331076412428980263984182365365715292560207445592018", "0.510279695870740409778738767334484809708615155539404548", "0.635626509594367380604827545000418331455019188562281349", "0.129304857274642475564179442785425797926079767522671163", "1.18088858810025653590356481638012816019876881487868657", "2.17175778983760437737667738885959799183430688287297767", "3.41568550810774629867945639900431994221065497147578087" }; const char * ref_i[nq * nx] = { "0.220206044893215842652155131408935133596486560067476474", "0", "-0.969458654385732175077973304161399773236957587792986099", "0.354614573267731219242838516784605303288232150760467423", "0", "-0.995392028773643947872231871832838543767598301887892796", "1.04370497561090171487193145841005574472705644411957863", "-0.108902811943905225853677097712717212629591264759957602", "-0.232114369998608907337769019848201890558327186146689311", "-0.133300066189980774635445078240315148544665020358019145", "0.0119464572932630291870372694406253796888930803905106876", "-0.567660589679294457801153713636532209809112025502518666", "-0.654079942571300523223917775358845549990877148918886474", "0.970337207245832214408380510793679653538607483205616894", "-1.43652482351673593824956935036654893593947145947637807" }; x = _acb_vec_init(nx); for (j = 0; j < nx; j++) { if (arb_set_str(acb_realref(x + j), x_r[j], prec) || arb_set_str(acb_imagref(x + j), x_i[j], prec) ) { flint_printf("error while setting x[%wd] <- %s+I*%s\n", j, x_r[j], x_i[j]); flint_abort(); } } acb_init(ref); acb_init(res); for (i = 0; i < nq; i++) { dirichlet_group_t G; dirichlet_char_t chi; dirichlet_group_init(G, q[i]); dirichlet_char_init(chi, G); dirichlet_char_log(chi, G, m[i]); for (j = 0; j < nx; j++) { if (arb_set_str(acb_realref(ref), ref_r[i * nx + j], prec - 10) || arb_set_str(acb_imagref(ref), ref_i[i * nx + j], prec - 10) ) { flint_printf("error while setting ref <- %s+I*%s\n", ref_r[i * nx + j], ref_i[i * nx + j]); flint_abort(); } acb_dirichlet_l_hurwitz(res, x + j, NULL, G, chi, prec + 10); if (!acb_contains(ref, res)) { flint_printf("FAIL:\n\n"); flint_printf("q = %wu\n", q[i]); flint_printf("m = %wu\n", m[i]); flint_printf("x = "); acb_printd(x, 54); flint_printf("\nref = "); acb_printd(ref, 54); flint_printf("\nl(chi,x) = "); acb_printd(res, 54); flint_printf("\n\n"); flint_abort(); } } dirichlet_char_clear(chi); dirichlet_group_clear(G); } acb_clear(ref); acb_clear(res); _acb_vec_clear(x, nx); TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l_jet.c000066400000000000000000000152521461254215100206640ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif /* Laurent expansions at s = 1 of first 10 principal L-functions */ /* with mpmath: chis = [[1],[0,1],[0,1,1],[0,1,0,1],[0,1,1,1,1],[0,1,0,0,0,1],[0,1,1,1,1,1,1], [0,1,0,1,0,1,0,1],[0,1,1,0,1,1,0,1,1],[0,1,0,1,0,0,0,1,0,1]] mp.dps = 40 for chi in chis: phi = chi.count(1); q = len(chi) L = lambda s: dirichlet(s, chi) - phi/((s-1)*q) c0 = taylor(L, 1, 0, method="quad") c1 = taylor(L, 1, 5, singular=True)[1:] for c in c0 + c1: print nstr(c, 20) + ",", print */ #define TESTQ 10 #define TESTLEN 6 static const double laurent_data[TESTQ][TESTLEN] = { {0.57721566490153286061, 0.072815845483676724861, -0.0048451815964361592423, -0.00034230573671722431103, 0.000096890419394470835728, -6.6110318108421891813e-6}, {0.63518142273073908501, 0.11634237461305384831, -0.018765738937942729408, 0.00061334298434914532242, 0.00042338142025747308027, -0.00010545096447379519004}, {0.7510145394903918042, 0.058764477744540050414, -0.019011359100973296683, 0.0056382252365739175151, -0.0009550480622176659462, 0.000021808301216554848718}, {0.63518142273073908501, 0.11634237461305384831, -0.018765738937942729408, 0.00061334298434914532242, 0.00042338142025747308027, -0.00010545096447379519004}, {0.78366011440804636341, -0.014977808062405260803, 0.0090104707969118845102, 0.003603799084856807634, -0.0029351216034181476022, 0.00093077685173004747355}, {0.60655632993184433857, 0.2095885418562151802, -0.060844893711330538429, 0.0068080382961291386117, 0.0022236616427578346453, -0.0013581825996235430782}, {0.77274344835207292411, -0.047596894381510269689, 0.035406039531261788462, -0.0054159870134630085898, -0.0019749752308692423114, 0.0014492998471928196325}, {0.63518142273073908501, 0.11634237461305384831, -0.018765738937942729408, 0.00061334298434914532242, 0.00042338142025747308027, -0.00010545096447379519004}, {0.7510145394903918042, 0.058764477744540050414, -0.019011359100973296683, 0.0056382252365739175151, -0.0009550480622176659462, 0.000021808301216554848718}, {0.66908892942800130547, 0.16801639259476784034, -0.072611999814034642781, 0.024624650443138705595, -0.004951850872731033514, -0.00020178815459414925709} }; TEST_FUNCTION_START(acb_dirichlet_l_jet, state) { slong iter; /* test Laurent series at s = 1 */ { acb_t s, t; dirichlet_group_t G; dirichlet_char_t chi; acb_ptr vec; ulong q; slong i; acb_init(s); acb_init(t); vec = _acb_vec_init(TESTLEN); acb_one(s); for (q = 1; q <= TESTQ; q++) { dirichlet_group_init(G, q); dirichlet_char_init(chi, G); acb_dirichlet_l_jet(vec, s, G, chi, 1, TESTLEN, 100); for (i = 0; i < TESTLEN; i++) { acb_set_d(t, laurent_data[q - 1][i]); mag_set_d(arb_radref(acb_realref(t)), fabs(laurent_data[q - 1][i]) * 1e-14); if (!acb_overlaps(vec + i, t)) { flint_printf("FAIL: Laurent series\n\n"); flint_printf("q = %wu i = %wd\n\n", q, i); flint_printf("r1 = "); acb_printn(vec + i, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); acb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } } dirichlet_char_clear(chi); dirichlet_group_clear(G); } acb_clear(s); acb_clear(t); _acb_vec_clear(vec, TESTLEN); } /* test self-consistency */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s; dirichlet_group_t G; dirichlet_char_t chi; acb_ptr vec1, vec2; slong len1, len2; slong prec1, prec2; int deflate1, deflate2; ulong q, k; slong i; len1 = n_randint(state, 5); len2 = n_randint(state, 5); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); deflate1 = n_randint(state, 2); deflate2 = n_randint(state, 2); q = 1 + n_randint(state, 20); k = n_randint(state, n_euler_phi(q)); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_index(chi, G, k); acb_init(s); vec1 = _acb_vec_init(len1); vec2 = _acb_vec_init(len2); if (n_randint(state, 4) == 0) acb_one(s); else acb_randtest(s, state, 2 + n_randint(state, 200), 2); acb_dirichlet_l_jet(vec1, s, G, chi, deflate1, len1, prec1); acb_dirichlet_l_jet(vec2, s, G, chi, deflate2, len2, prec2); if (deflate1 != deflate2 && dirichlet_char_is_principal(G, chi)) { /* add or subtract phi(q)/((s+x-1)q) */ acb_t t, u; acb_init(t); acb_init(u); acb_set_ui(t, n_euler_phi(q)); acb_div_ui(t, t, q, prec1); acb_sub_ui(u, s, 1, prec1); for (i = 0; i < len1; i++) { acb_div(t, t, u, prec1); if (deflate1) acb_add(vec1 + i, vec1 + i, t, prec1); else acb_sub(vec1 + i, vec1 + i, t, prec1); acb_neg(t, t); } acb_clear(t); acb_clear(u); } for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(vec1 + i, vec2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd q = %wu k = %wu i = %wd\n\n", iter, q, k, i); flint_printf("s = "); acb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); acb_printn(vec1 + i, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); acb_printn(vec2 + i, 50, 0); flint_printf("\n\n"); flint_abort(); } } dirichlet_char_clear(chi); dirichlet_group_clear(G); acb_clear(s); _acb_vec_clear(vec1, len1); _acb_vec_clear(vec2, len2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l_series.c000066400000000000000000000043131461254215100213700ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_l_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; int deflate; acb_poly_t S, A, B, C; dirichlet_group_t G; dirichlet_char_t chi; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 8); n1 = 1 + n_randint(state, 8); n2 = 1 + n_randint(state, 8); dirichlet_group_init(G, 1 + n_randint(state, 12)); dirichlet_char_init(chi, G); dirichlet_char_index(chi, G, n_randint(state, G->phi_q)); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); deflate = n_randint(state, 2); acb_poly_randtest(S, state, m, bits1, 3); acb_dirichlet_l_series(A, S, G, chi, deflate, n1, bits2); acb_poly_set(B, S); /* aliasing */ acb_dirichlet_l_series(B, B, G, chi, deflate, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); dirichlet_char_clear(chi); dirichlet_group_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-l_vec_hurwitz.c000066400000000000000000000066071461254215100224570ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_l_vec_hurwitz, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { ulong i, q; slong prec; dirichlet_group_t G; dirichlet_char_t chi; acb_t s, z; acb_ptr v; acb_dirichlet_hurwitz_precomp_t pre; prec = 50 + n_randint(state, 50); q = 1 + n_randint(state, 50); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); acb_init(s); acb_one(s); acb_div_si(s, s, 2, prec); v = _acb_vec_init(G->phi_q); if (n_randint(state, 2)) { ulong A, K, N; acb_dirichlet_hurwitz_precomp_choose_param(&A, &K, &N, s, G->phi_q, prec); acb_dirichlet_hurwitz_precomp_init(pre, s, acb_is_one(s), A, K, N, prec); } else { acb_dirichlet_hurwitz_precomp_init_num(pre, s, acb_is_one(s), G->phi_q, prec); } /* all at once */ if (n_randint(state, 2)) acb_dirichlet_l_vec_hurwitz(v, s, pre, G, prec); else acb_dirichlet_l_vec_hurwitz(v, s, NULL, G, prec); /* check with complete loop */ i = 0; acb_init(z); dirichlet_char_one(chi, G); do { if (n_randint(state, 2)) acb_dirichlet_l_hurwitz(z, s, pre, G, chi, prec); else acb_dirichlet_l_hurwitz(z, s, NULL, G, chi, prec); if (!acb_overlaps(z, v + i)) { flint_printf("\n L value differ"); flint_printf("\nL(1/2, %wu) single = ", chi->n); acb_printd(z, 20); flint_printf("\nL(1/2, %wu) multi = ", chi->n); acb_printd(v + i, 20); flint_printf("\n\n"); _acb_vec_printd(v, G->phi_q, 10); flint_printf("\n\n"); flint_abort(); } else if (acb_rel_accuracy_bits(z) < prec - 8 || acb_rel_accuracy_bits(v + i) < prec - 8) { flint_printf("FAIL\n\n"); flint_printf("q = %wu\n", q); flint_printf("\nL(1/2,chi_%wu(%wu,)) inaccurate\n", q, chi->n); flint_printf("\nsingle =\n"); acb_printd(z, 30); flint_printf("\ndft =\n"); acb_printd(v + i, 30); flint_printf("\nerrors %wd & %wd [prec = %wd]\n", acb_rel_accuracy_bits(z), acb_rel_accuracy_bits(v + i), prec); flint_abort(); } i++; } while (dirichlet_char_next(chi, G) >= 0); acb_clear(s); _acb_vec_clear(v, G->phi_q); dirichlet_char_clear(chi); dirichlet_group_clear(G); acb_dirichlet_hurwitz_precomp_clear(pre); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-lerch_phi.c000066400000000000000000000156231461254215100215260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" void acb_dirichlet_lerch_phi_test(acb_t res, const acb_t z, const acb_t s, const acb_t a, int algorithm, slong prec) { switch (algorithm % 3) { case 0: acb_dirichlet_lerch_phi_direct(res, z, s, a, prec); if (!acb_is_finite(res)) acb_dirichlet_lerch_phi(res, z, s, a, prec); break; case 1: acb_dirichlet_lerch_phi_integral(res, z, s, a, prec); break; default: acb_dirichlet_lerch_phi(res, z, s, a, prec); break; } } static void acb_set_dddd(acb_t z, double a, double ar, double b, double br) { arf_set_d(arb_midref(acb_realref(z)), a); mag_set_d(arb_radref(acb_realref(z)), ar); arf_set_d(arb_midref(acb_imagref(z)), b); mag_set_d(arb_radref(acb_imagref(z)), br); } #define NUM_TESTS 15 /* z, s, a, phi(z, s, a) */ const double testdata[NUM_TESTS][8] = { { 1.0, 0.00390625, 1.5, 0.0, 2.25, 0.0, 1.3422063426254739626, 0.13465412214420029791 }, { 1.0, 0.0, 1.5, 0.0, 2.25, 0.0, 1.4975136076666680360, 0.0 }, { 1.0, -0.00390625, 1.5, 0.0, 2.25, 0.0, 1.3422063426254739626, -0.13465412214420029791 }, { 2.0, 0.00390625, 1.5, 0.0, 2.25, 0.0, -0.16955701974487404975, 0.61946301461898363407 }, { 2.0, 0.0, 1.5, 0.0, 2.25, 0.0, -0.17140382129993246416, -0.62044054732729604008 }, { 2.0, -0.00390625, 1.5, 0.0, 2.25, 0.0, -0.16955701974487404975, -0.61946301461898363407 }, { 0.6875, 0.0, 0.0, 0.0, -1.0, 2.0, 3.2, 0.0 }, { 0.0, 8.0, 1.0, 0.0, 1.0, -1.0, -0.21201062033942531891, 0.15142847985530888328 }, { 0.0, 8.0, 1.0, 1.0, 1.0, -1.0, -0.18714764709994647918, -0.031327583631588241802 }, { 1.875, 2.625, -1.0, 0.0, 1.0, 0.0, -0.10448979591836734694, -0.078367346938775510204 }, { -2.5, -1.0, -3.75, 0.0, -3.75, 7.5, 195.9465378716877103, 889.34175804326870925 }, { 0.0, -1.5, 1.0, 0.5, -1.0, 6.0, -0.20452787205323008395, 0.14062505401787546806 }, { -3.0, 3.0, 9.5, 0.0, 0.0, -5.5, 5.5775511785583065106e-7, -4.488380385476415194e-7 }, { -1.0, 0.0, -1.0, 0.0, -1.0, 0.0, -0.75, 0.0 }, { -3.0, 0.0, -2.0, 0.0, -2.0, 0.0, 1.84375, 0.0 }, }; TEST_FUNCTION_START(acb_dirichlet_lerch_phi, state) { slong iter; /* check test values */ for (iter = 0; iter < 5 * 0.1 * flint_test_multiplier(); iter++) { slong i; acb_t z, s, a, p1, p2; int alg; acb_init(z); acb_init(s); acb_init(a); acb_init(p1); acb_init(p2); for (i = 0; i < NUM_TESTS; i++) { alg = n_randlimb(state); acb_set_dddd(z, testdata[i][0], 0.0, testdata[i][1], 0.0); acb_set_dddd(s, testdata[i][2], 0.0, testdata[i][3], 0.0); acb_set_dddd(a, testdata[i][4], 1e-14, testdata[i][5], 1e-14); acb_set_dddd(p2, testdata[i][6], 1e-14, testdata[i][7], 1e-14); acb_dirichlet_lerch_phi_test(p1, z, s, a, alg, 2 + n_randint(state, 100)); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (test value)\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(z); acb_clear(s); acb_clear(a); acb_clear(p1); acb_clear(p2); } for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_t z, s, a, b, r1, r2, r3; slong prec1, prec2; int alg1, alg2, alg3; /* flint_printf("iter %wd\n", iter); */ acb_init(z); acb_init(s); acb_init(a); acb_init(b); acb_init(r1); acb_init(r2); acb_init(r3); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); alg1 = n_randlimb(state); alg2 = n_randlimb(state); alg3 = n_randlimb(state); acb_randtest(z, state, 1 + n_randint(state, 500), 3); acb_randtest(s, state, 1 + n_randint(state, 500), 3); acb_randtest(a, state, 1 + n_randint(state, 500), 3); acb_randtest(b, state, 1 + n_randint(state, 500), 10); acb_randtest(r1, state, 1 + n_randint(state, 500), 10); acb_randtest(r2, state, 1 + n_randint(state, 500), 10); if (n_randint(state, 2)) acb_set_si(z, n_randint(state, 5) - 2); if (n_randint(state, 2)) acb_set_si(a, n_randint(state, 5) - 2); if (n_randint(state, 2)) acb_set_si(s, n_randint(state, 5) - 2); acb_dirichlet_lerch_phi_test(r1, z, s, a, alg1, prec1); acb_dirichlet_lerch_phi_test(r2, z, s, a, alg2, prec2); if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } /* test phi(z,s,a) = z*phi(z,s,a+1) + a^-s */ acb_add_ui(b, a, 1, prec2); acb_dirichlet_lerch_phi_test(r2, z, s, b, alg3, prec2); acb_neg(r3, s); acb_pow(r3, a, r3, prec2); acb_addmul(r3, r2, z, prec2); if (!acb_overlaps(r1, r3)) { flint_printf("FAIL (2): overlap\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_printf("r3 = "); acb_printd(r3, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z); acb_clear(s); acb_clear(a); acb_clear(b); acb_clear(r1); acb_clear(r2); acb_clear(r3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-platt_beta.c000066400000000000000000000062301461254215100217020ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" static void _arb_div_ui_ui(arb_t res, ulong a, ulong b, slong prec) { arb_set_ui(res, a); arb_div_ui(res, res, b, prec); } static int _arb_lt_d(const arb_t a, double d) { int result; arb_t x; arb_init(x); arb_set_d(x, d); result = arb_lt(a, x); arb_clear(x); return result; } TEST_FUNCTION_START(acb_dirichlet_platt_beta, state) { slong iter; arb_t x, t, t0, expe; arb_init(x); arb_init(t); arb_init(t0); arb_init(expe); for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t beta, a, b, c; acb_t z; slong prec, mbits; prec = 2 + n_randint(state, 300); mbits = 2 + n_randint(state, 20); arb_randtest(t, state, prec, mbits); arb_randtest(t0, state, prec, mbits); arb_abs(t, t); arb_abs(t0, t0); arb_add(x, t, t0, prec); arb_const_e(expe, prec); arb_exp(expe, expe, prec); if (!arb_is_nonnegative(t) || !arb_gt(t0, expe) || !_arb_lt_d(x, 1e8)) { continue; } arb_init(beta); arb_init(a); arb_init(b); arb_init(c); acb_init(z); acb_dirichlet_platt_beta(beta, t0, prec); /* Lemma A.10 in "Isolating some non-trivial zeros of zeta" */ arb_pow(a, x, beta, prec); arb_mul_ui(a, a, 3, prec); acb_dirichlet_platt_scaled_lambda(c, t, prec); arb_abs(c, c); if (arb_gt(c, a)) { flint_printf("FAIL: Lemma A.10 |f(t)|\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("prec = %wd\n\n", prec); flint_printf("t = "); arb_printd(t, 15); flint_printf("\n\n"); flint_printf("t0 = "); arb_printd(t0, 15); flint_printf("\n\n"); flint_abort(); } /* In Lemma A.10 proof in "Isolating some non-trivial zeros of zeta" */ arb_pow(a, x, beta, prec); _arb_div_ui_ui(b, 732, 1000, prec); arb_mul(a, a, b, prec); acb_set_d(z, 0.5); arb_set(acb_imagref(z), x); acb_zeta(z, z, prec); acb_abs(c, z, prec); if (arb_gt(c, a)) { flint_printf("FAIL: Lemma A.10 |zeta(1/2 + i(t + t0))|\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("prec = %wd\n\n", prec); flint_printf("t = "); arb_printd(t, 15); flint_printf("\n\n"); flint_printf("t0 = "); arb_printd(t0, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(beta); arb_clear(a); arb_clear(b); arb_clear(c); acb_clear(z); } arb_clear(x); arb_clear(t); arb_clear(t0); arb_clear(expe); TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-platt_hardy_z_zeros.c000066400000000000000000000030151461254215100236470ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_platt_hardy_z_zeros, state) { fmpz_t n; arb_ptr pa, pb; slong count, i; slong maxcount = 50; slong prec = 64; fmpz_init(n); pa = _arb_vec_init(maxcount); pb = _arb_vec_init(maxcount); fmpz_set_si(n, 10000); count = acb_dirichlet_platt_hardy_z_zeros(pa, n, maxcount, prec); acb_dirichlet_hardy_z_zeros(pb, n, count, prec); if (count != maxcount) { flint_printf("FAIL: not enough zeros were isolated\n\n"); flint_printf("count = %wd maxcount = %wd\n\n", count, maxcount); flint_abort(); } for (i = 0; i < count; i++) { if (!arb_overlaps(pa+i, pb+i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("observed[%wd] = ", i); arb_printd(pa+i, 20); flint_printf("\n\n"); flint_printf("expected[%wd] = ", i); arb_printd(pb+i, 20); flint_printf("\n\n"); flint_abort(); } } fmpz_clear(n); _arb_vec_clear(pa, maxcount); _arb_vec_clear(pb, maxcount); TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-platt_local_hardy_z_zeros.c000066400000000000000000000045101461254215100250220ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_platt_local_hardy_z_zeros, state) { /* Check a specific combination of parameter values that is relatively fast * to evaluate and that has relatively tight bounds. */ slong A, B, K, sigma_grid, Ns_max, sigma_interp; arb_t h, H; fmpz_t J, T, n; arb_ptr pa, pb; slong count, i; slong maxcount = 50; slong prec = 128; arb_init(h); arb_init(H); fmpz_init(J); fmpz_init(T); fmpz_init(n); pa = _arb_vec_init(maxcount); pb = _arb_vec_init(maxcount); fmpz_set_si(n, 10142); /* parameters related to the location/resolution/width of the grid */ fmpz_set_si(T, 10000); A = 8; B = 128; /* tuning parameters for the evaluation of grid points */ fmpz_set_si(J, 1000); K = 30; sigma_grid = 63; arb_set_d(h, 4.5); /* tuning parameters for interpolation on the grid */ Ns_max = 200; sigma_interp = 21; arb_one(H); count = _acb_dirichlet_platt_local_hardy_z_zeros(pa, n, maxcount, T, A, B, h, J, K, sigma_grid, Ns_max, H, sigma_interp, prec); acb_dirichlet_hardy_z_zeros(pb, n, count, prec); if (count != maxcount) { flint_printf("FAIL: not enough zeros were isolated\n\n"); flint_printf("count = %wd maxcount = %wd\n\n", count, maxcount); flint_abort(); } for (i = 0; i < count; i++) { if (!arb_overlaps(pa+i, pb+i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("observed[%wd] = ", i); arb_printd(pa+i, 20); flint_printf("\n\n"); flint_printf("expected[%wd] = ", i); arb_printd(pb+i, 20); flint_printf("\n\n"); flint_abort(); } } arb_clear(h); arb_clear(H); fmpz_clear(J); fmpz_clear(T); fmpz_clear(n); _arb_vec_clear(pa, maxcount); _arb_vec_clear(pb, maxcount); TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-platt_multieval.c000066400000000000000000000155101461254215100227720ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" static void _arb_inv_si(arb_t res, slong a, slong prec) { arb_set_si(res, a); arb_inv(res, res, prec); } /* Defined in t-platt_multieval.c and t-platt_multieval_threaded.c */ #ifndef _arb_div_si_si #define _arb_div_si_si _arb_div_si_si static void _arb_div_si_si(arb_t res, slong a, slong b, slong prec) { arb_set_si(res, a); arb_div_si(res, res, b, prec); } #endif static void _check_containment(const char *name, const arb_t x, const char *s) { arb_t u; slong prec = 300; arb_init(u); arb_set_str(u, s, prec); if (!arb_contains(u, x)) { flint_printf("FAIL: %s\n\n", name); flint_printf("observed = "); arb_printn(x, 30, 0); flint_printf("\n\n"); flint_printf("expected = "); arb_printn(u, 30, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(u); } TEST_FUNCTION_START(acb_dirichlet_platt_multieval, state) { slong iter; /* Check a specific combination of parameter values that is relatively fast * to evaluate and that has relatively tight bounds. */ { slong A = 8; slong B = 128; slong N = A*B; slong K = 30; slong sigma = 63; slong prec = 128; fmpz_t J, T; arb_t h; arb_ptr vec; arb_init(h); fmpz_init(J); fmpz_init(T); fmpz_set_si(J, 1000); fmpz_set_si(T, 10000); arb_set_d(h, 4.5); /* Spot-check lemma bound containment * in intervals calculated with PARI/GP. */ { arb_t lem, xi, x, beta, t0; slong i = 201; slong k = 5; slong wp = 300; arb_init(lem); arb_init(xi); arb_init(x); arb_init(t0); arb_init(beta); _arb_inv_si(xi, B, wp); arb_mul_2exp_si(xi, xi, -1); _arb_div_si_si(x, i, B, wp); arb_set_fmpz(t0, T); acb_dirichlet_platt_beta(beta, t0, wp); acb_dirichlet_platt_lemma_32(lem, h, t0, x, wp); _check_containment("Lemma 3.2", lem, "[5.3526496753240991744e-1072334 +/- 2.55e-1072354]"); acb_dirichlet_platt_c_bound(lem, sigma, t0, h, k, wp); _check_containment("Lemma A.3", lem, "[1.3516642396389823078e+134 +/- 2.65e+114]"); acb_dirichlet_platt_lemma_A5(lem, B, h, k, wp); _check_containment("Lemma A.5", lem, "[1.0075390047893384632e-30 +/- 5.57e-51]"); acb_dirichlet_platt_lemma_A7(lem, sigma, t0, h, k, A, wp); _check_containment("Lemma A.7", lem, "[3.0406705491484062400e-505 +/- 1.57e-525]"); acb_dirichlet_platt_lemma_A9(lem, sigma, t0, h, A, wp); _check_containment("Lemma A.9", lem, "[6.8953211848420326275e-536 +/- 3.52e-556]"); acb_dirichlet_platt_lemma_A11(lem, t0, h, B, wp); _check_containment("Lemma A.11", lem, "[3.0825745863006335768e-42 +/- 3.68e-62]"); acb_dirichlet_platt_lemma_B1(lem, sigma, t0, h, J, wp); _check_containment("Lemma B.1", lem, "[8.5737638613320328274e-42 +/- 7.50e-63]"); acb_dirichlet_platt_lemma_B2(lem, K, h, xi, wp); _check_containment("Lemma B.2", lem, "[2.0748437544358592615e-44 +/- 4.76e-64]"); arb_clear(lem); arb_clear(xi); arb_clear(x); arb_clear(t0); arb_clear(beta); } /* Check a few random entries in the multieval vector. */ vec = _arb_vec_init(N); acb_dirichlet_platt_multieval(vec, T, A, B, h, J, K, sigma, prec); for (iter = 0; iter < 20; iter++) { arb_t t, r; slong i = n_randint(state, N); slong n = i - N/2; arb_init(t); arb_init(r); _arb_div_si_si(t, n, A, prec); arb_add_fmpz(t, t, T, prec); acb_dirichlet_platt_scaled_lambda(r, t, prec); if (!arb_overlaps(vec + i, r)) { flint_printf("FAIL: overlap for hardcoded example\n\n"); flint_printf("i = %wd n = %wd\n\n", i, n); flint_printf("vec[%wd] = ", i); arb_printn(vec + i, 30, 0); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, 30, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(t); arb_clear(r); } fmpz_clear(J); fmpz_clear(T); arb_clear(h); _arb_vec_clear(vec, N); } for (iter = 0; iter < 10 * 0.1 * flint_test_multiplier(); iter++) { slong prec; ulong A, B, N, K; slong sigma, Tbits; fmpz_t J, T; arb_t h; arb_ptr v1, v2; /* better but slower limits are in parentheses below */ prec = 2 + n_randint(state, 300); sigma = 1 + 2*(1 + n_randint(state, 100)); /* (200) */ K = 1 + n_randint(state, 20); /* (50) */ A = 1 + n_randint(state, 10); B = 1 + n_randint(state, 10); /* (500) */ if (n_randint(state, 2)) A *= 2; else B *= 2; N = A*B; fmpz_init(J); fmpz_init(T); fmpz_set_si(J, 1 + n_randint(state, 100)); /* (10000) */ Tbits = 5 + n_randint(state, 15); fmpz_set_ui(T, n_randtest_bits(state, Tbits)); arb_init(h); arb_set_si(h, 1 + n_randint(state, 20000)); arb_div_si(h, h, 1000, prec); v1 = _arb_vec_init(N); v2 = _arb_vec_init(N); acb_dirichlet_platt_scaled_lambda_vec(v1, T, A, B, prec); acb_dirichlet_platt_multieval(v2, T, A, B, h, J, K, sigma, prec); if (!_arb_vec_overlaps(v1, v2, N)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd prec = %wd\n\n", iter, prec); flint_printf("sigma = %wd\n\n", sigma); flint_printf("A = %wu B = %wu K = %wu\n\n", A, B, K); flint_printf("J = "); fmpz_print(J); flint_printf("\n\n"); flint_printf("T = "); fmpz_print(T); flint_printf("\n\n"); flint_printf("h = "); arb_printn(h, 30, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(h); fmpz_clear(J); fmpz_clear(T); _arb_vec_clear(v1, N); _arb_vec_clear(v2, N); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-platt_multieval_threaded.c000066400000000000000000000104331461254215100246310ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" /* Defined in t-platt_multieval.c and t-platt_multieval_threaded.c */ #ifndef _arb_div_si_si #define _arb_div_si_si _arb_div_si_si static void _arb_div_si_si(arb_t res, slong a, slong b, slong prec) { arb_set_si(res, a); arb_div_si(res, res, b, prec); } #endif TEST_FUNCTION_START(acb_dirichlet_platt_multieval_threaded, state) { slong iter; /* Check a specific combination of parameter values that is relatively fast * to evaluate and that has relatively tight bounds. */ { slong A = 8; slong B = 128; slong N = A*B; slong K = 30; slong sigma = 63; slong prec = 128; fmpz_t J; fmpz_t T; arb_t h; arb_ptr vec; arb_init(h); fmpz_init(J); fmpz_init(T); fmpz_set_si(J, 1000); fmpz_set_si(T, 10000); arb_set_d(h, 4.5); flint_set_num_threads(5); /* Check a few random entries in the multieval vector. */ vec = _arb_vec_init(N); acb_dirichlet_platt_multieval_threaded(vec, T, A, B, h, J, K, sigma, prec); for (iter = 0; iter < 20; iter++) { arb_t t, r; slong i = n_randint(state, N); slong n = i - N/2; arb_init(t); arb_init(r); _arb_div_si_si(t, n, A, prec); arb_add_fmpz(t, t, T, prec); acb_dirichlet_platt_scaled_lambda(r, t, prec); if (!arb_overlaps(vec + i, r)) { flint_printf("FAIL: overlap for hardcoded example\n\n"); flint_printf("i = %wd n = %wd\n\n", i, n); flint_printf("vec[%wd] = ", i); arb_printn(vec + i, 30, 0); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, 30, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(t); arb_clear(r); } fmpz_clear(J); fmpz_clear(T); arb_clear(h); _arb_vec_clear(vec, N); } for (iter = 0; iter < 10 * 0.1 * flint_test_multiplier(); iter++) { slong prec; ulong A, B, N, K; slong sigma, Tbits; fmpz_t J, T; arb_t h; arb_ptr v1, v2; /* better but slower limits are in parentheses below */ prec = 2 + n_randint(state, 300); sigma = 1 + 2*(1 + n_randint(state, 100)); /* (200) */ K = 1 + n_randint(state, 20); /* (50) */ A = 1 + n_randint(state, 10); B = 1 + n_randint(state, 10); /* (500) */ if (n_randint(state, 2)) A *= 2; else B *= 2; N = A*B; fmpz_init(J); fmpz_init(T); fmpz_set_si(J, 1 + n_randint(state, 100)); /* (10000) */ Tbits = 5 + n_randint(state, 15); fmpz_set_ui(T, n_randtest_bits(state, Tbits)); arb_init(h); arb_set_si(h, 1 + n_randint(state, 20000)); arb_div_si(h, h, 1000, prec); flint_set_num_threads(1 + n_randint(state, 5)); v1 = _arb_vec_init(N); v2 = _arb_vec_init(N); acb_dirichlet_platt_scaled_lambda_vec(v1, T, A, B, prec); acb_dirichlet_platt_multieval_threaded(v2, T, A, B, h, J, K, sigma, prec); if (!_arb_vec_overlaps(v1, v2, N)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd prec = %wd\n\n", iter, prec); flint_printf("sigma = %wd\n\n", sigma); flint_printf("A = %wu B = %wu K = %wu\n\n", A, B, K); flint_printf("J = "); fmpz_print(J); flint_printf("\n\n"); flint_printf("T = "); fmpz_print(T); flint_printf("\n\n"); flint_printf("h = "); arb_printn(h, 30, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(h); fmpz_clear(J); fmpz_clear(T); _arb_vec_clear(v1, N); _arb_vec_clear(v2, N); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-platt_ws_interpolation.c000066400000000000000000000060011461254215100243630ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_platt_ws_interpolation, state) { slong iter; for (iter = 0; iter < 5 * 0.1 * flint_test_multiplier(); iter++) { ulong A, B, iter2; int Tbits; fmpz_t T; arb_ptr vec; slong vprec; A = 1 + n_randint(state, 10); B = 1 + n_randint(state, 10); if (n_randint(state, 2)) A *= 2; else B *= 2; fmpz_init(T); Tbits = 5 + n_randint(state, 20); fmpz_set_ui(T, n_randtest_bits(state, Tbits)); vprec = 2 + n_randint(state, 300); vec = _arb_vec_init(A*B); acb_dirichlet_platt_scaled_lambda_vec(vec, T, A, B, vprec); for (iter2 = 0; iter2 < 50; iter2++) { ulong Ns_max, sigma; arb_t expected, observed; arb_t t0, H; slong prec; arb_init(t0); arb_init(H); arb_init(expected); arb_init(observed); prec = 2 + n_randint(state, 300); Ns_max = 1 + n_randint(state, 100); sigma = 1 + 2*(1 + n_randint(state, 100)); arb_set_si(t0, A*B*500 - n_randint(state, A*B*1000) - 1); arb_div_ui(t0, t0, A*1000, prec); arb_add_fmpz(t0, t0, T, prec); arb_set_ui(H, 1 + n_randint(state, 10000)); arb_div_ui(H, H, 1000, prec); arb_abs(H, H); acb_dirichlet_platt_scaled_lambda(expected, t0, prec); acb_dirichlet_platt_ws_interpolation(observed, NULL, t0, vec, T, A, B, Ns_max, H, sigma, prec); if (!arb_overlaps(expected, observed)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("iter2 = %wd\n\n", iter2); flint_printf("A = %wu\n\n", A); flint_printf("B = %wu\n\n", B); flint_printf("T = "); fmpz_print(T); flint_printf("\n\n"); flint_printf("vprec = %wd\n\n", vprec); flint_printf("Ns_max = %wu\n\n", Ns_max); flint_printf("sigma = %wu\n\n", sigma); flint_printf("prec = %wd\n\n", prec); flint_printf("t0 = "); arb_printd(t0, 15); flint_printf("\n\n"); flint_printf("H = "); arb_printd(H, 15); flint_printf("\n\n"); } arb_clear(t0); arb_clear(H); arb_clear(expected); arb_clear(observed); } fmpz_clear(T); _arb_vec_clear(vec, A*B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-platt_zeta_zeros.c000066400000000000000000000030041461254215100231500ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_platt_zeta_zeros, state) { fmpz_t n; acb_ptr pa, pb; slong count, i; slong maxcount = 50; slong prec = 64; fmpz_init(n); pa = _acb_vec_init(maxcount); pb = _acb_vec_init(maxcount); fmpz_set_si(n, 10000); count = acb_dirichlet_platt_zeta_zeros(pa, n, maxcount, prec); acb_dirichlet_zeta_zeros(pb, n, count, prec); if (count != maxcount) { flint_printf("FAIL: not enough zeros were isolated\n\n"); flint_printf("count = %wd maxcount = %wd\n\n", count, maxcount); flint_abort(); } for (i = 0; i < count; i++) { if (!acb_overlaps(pa+i, pb+i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("observed[%wd] = ", i); acb_printd(pa+i, 20); flint_printf("\n\n"); flint_printf("expected[%wd] = ", i); acb_printd(pb+i, 20); flint_printf("\n\n"); flint_abort(); } } fmpz_clear(n); _acb_vec_clear(pa, maxcount); _acb_vec_clear(pb, maxcount); TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-powsum_smooth.c000066400000000000000000000040771461254215100225150ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_dirichlet_powsum_smooth, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s; acb_ptr z1, z2; slong i, n, len, prec; acb_init(s); if (n_randint(state, 2)) { acb_randtest(s, state, 1 + n_randint(state, 200), 3); } else { arb_set_ui(acb_realref(s), 1); arb_mul_2exp_si(acb_realref(s), acb_realref(s), -1); arb_randtest(acb_imagref(s), state, 1 + n_randint(state, 200), 4); } prec = 2 + n_randint(state, 200); n = n_randtest(state) % 500; len = 1 + n_randint(state, 4); z1 = _acb_vec_init(len); z2 = _acb_vec_init(len); acb_dirichlet_powsum_sieved(z1, s, n, len, prec); acb_dirichlet_powsum_smooth(z2, s, n, len, prec); for (i = 0; i < len; i++) { if (!acb_overlaps(z1 + i, z2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("n = %wd, prec = %wd, len = %wd, i = %wd\n\n", n, prec, len, i); flint_printf("s = "); acb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1 + i, prec / 3.33); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2 + i, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } acb_clear(s); _acb_vec_clear(z1, len); _acb_vec_clear(z2, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-roots.c000066400000000000000000000032741461254215100207360ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_roots, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, z; acb_dirichlet_roots_t roots; ulong n, k; slong prec; slong iter2; n = 1 + n_randint(state, 1000); prec = 2 + n_randint(state, 200); acb_init(x); acb_init(y); acb_init(z); acb_dirichlet_roots_init(roots, n, n_randtest(state), prec); acb_unit_root(y, n, prec); for (iter2 = 0; iter2 <= FLINT_MIN(n, 20); iter2++) { k = n_randint(state, 2 * n); acb_dirichlet_root(x, roots, k, prec); acb_pow_ui(z, y, k, prec); if (!acb_overlaps(x, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd n = %wu k = %wu prec = %wd\n\n", iter, n, k, prec); flint_printf("x = "); acb_printn(x, 30, 0); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 30, 0); flint_printf("\n\n"); flint_abort(); } } acb_dirichlet_roots_clear(roots); acb_clear(x); acb_clear(y); acb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-stieltjes.c000066400000000000000000000074051461254215100215760ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" void acb_dirichlet_stieltjes_integral(acb_t res, const fmpz_t n, const acb_t a, slong prec); void acb_dirichlet_stieltjes_em(acb_t res, const fmpz_t n, const acb_t a, slong prec); TEST_FUNCTION_START(acb_dirichlet_stieltjes, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { acb_t b1, b2, a; fmpz_t n; slong prec1, prec2, acc1, acc2; int alg1, alg2; fmpz_init(n); acb_init(b1); acb_init(b2); acb_init(a); if (n_randint(state, 10) == 0) { acb_one(a); fmpz_randtest(n, state, 1 + n_randint(state, 100)); fmpz_abs(n, n); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); } else if (n_randint(state, 7) != 0) { acb_one(a); fmpz_randtest(n, state, 2 + n_randint(state, 12)); fmpz_abs(n, n); prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); } else { acb_randtest_precise(a, state, 400, 3); fmpz_randtest(n, state, 7); fmpz_abs(n, n); prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); } alg1 = n_randint(state, 3); alg2 = n_randint(state, 3); if (fmpz_cmp_ui(n, 40) >= 0) { alg1 = 1 + n_randint(state, 2); alg2 = 1 + n_randint(state, 2); } else { alg1 = n_randint(state, 3); alg2 = n_randint(state, 3); } if (alg1 == 0) acb_dirichlet_stieltjes_em(b1, n, a, prec1); else if (alg1 == 1) acb_dirichlet_stieltjes_integral(b1, n, a, prec1); else acb_dirichlet_stieltjes(b1, n, a, prec1); if (alg2 == 0) acb_dirichlet_stieltjes_em(b2, n, a, prec2); else if (alg2 == 1) acb_dirichlet_stieltjes_integral(b2, n, a, prec2); else acb_dirichlet_stieltjes(b2, n, a, prec2); if (!acb_overlaps(b1, b2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd, alg1 = %d, alg2 = %d\n\n", iter, alg1, alg2); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 100, 0); flint_printf("\n\n"); flint_printf("b1 = "); acb_printn(b1, 1000, 0); flint_printf("\n\n"); flint_printf("b2 = "); acb_printn(b2, 1000, 0); flint_printf("\n\n"); flint_abort(); } acc1 = acb_rel_accuracy_bits(b1); acc2 = acb_rel_accuracy_bits(b2); if (acb_is_one(a) && (acc1 < prec1 - 10 || acc2 < prec2 - 10)) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd\n", prec1, acc1); flint_printf("prec2 = %wd, acc2 = %wd\n", prec2, acc2); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("b1 = "); acb_printn(b1, 500, 0); flint_printf("\n\n"); flint_printf("b2 = "); acb_printn(b2, 500, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(b1); acb_clear(b2); acb_clear(a); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-thetanull.c000066400000000000000000000062611461254215100215670ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_thetanull, state) { slong prec = 64; ulong q; /* check the only theta functions * theta(chi) = sum chi(k)* k^odd * exp(-Pi * k^2 / q) * vanishing at 1 correspond to two specific * characters of moduli 300 and 600 + conjugates */ for (q = 3; q < 1000; q ++) { dirichlet_group_t G; dirichlet_char_t chi; ulong * v, nv, k; acb_t sum; acb_ptr z; arb_t eq; arb_ptr t, kt, tt; if (q % 4 == 2) /* no primitive character mod q */ continue; dirichlet_group_init(G, q); dirichlet_char_init(chi, G); z = _acb_vec_init(G->expo); _acb_vec_unit_roots(z, G->expo, G->expo, prec); nv = acb_dirichlet_theta_length_d(q, 1, prec); v = flint_malloc(nv * sizeof(ulong)); arb_init(eq); arb_const_pi(eq, prec); arb_div_ui(eq, eq, q, prec); arb_neg(eq, eq); arb_exp(eq, eq, prec); t = _arb_vec_init(nv); acb_dirichlet_arb_quadratic_powers(t, nv, eq, prec); kt = _arb_vec_init(nv); for (k = 1; k < nv; k++) arb_mul_ui(kt + k, t + k, k, prec); /* theta function on primitive characters */ acb_init(sum); dirichlet_char_first_primitive(chi, G); do { acb_zero(sum); dirichlet_chi_vec(v, G, chi, nv); tt = dirichlet_parity_char(G, chi) ? kt : t; for (k = 1; k < nv; k++) if (v[k] != DIRICHLET_CHI_NULL) acb_addmul_arb(sum, z + v[k], tt + k, prec); if ((q == 300 && (chi->n == 71 || chi->n == 131)) || (q == 600 && (chi->n == 11 || chi->n == 491))) { if (!acb_contains_zero(sum)) { flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); acb_printd(sum, 10); flint_printf("\n"); dirichlet_char_print(G, chi); flint_printf("\n"); flint_abort(); } } else if (acb_contains_zero(sum)) { flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); acb_printd(sum, 10); flint_printf("\n"); dirichlet_char_print(G, chi); flint_printf("\n"); flint_abort(); } } while (dirichlet_char_next_primitive(chi, G) >= 0); _acb_vec_clear(z, G->expo); _arb_vec_clear(kt, nv); _arb_vec_clear(t, nv); acb_clear(sum); arb_clear(eq); flint_free(v); dirichlet_group_clear(G); dirichlet_char_clear(chi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-turing_method_bound.c000066400000000000000000000026431461254215100236260ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_turing_method_bound, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { ulong u, v; fmpz_t a, b; fmpz_init(a); fmpz_init(b); fmpz_randtest_unsigned(a, state, 500); fmpz_randtest_unsigned(b, state, 500); fmpz_sub_ui(a, a, 1); fmpz_sub_ui(b, b, 1); u = acb_dirichlet_turing_method_bound(a); v = acb_dirichlet_turing_method_bound(b); if ((fmpz_cmp(a, b) < 0 && u > v) || (fmpz_cmp(a, b) > 0 && u < v)) { flint_printf("FAIL: increasing on p >= -1\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("u = %wu\n", u); flint_printf("v = %wu\n", v); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-xi.c000066400000000000000000000037671461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2018 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_xi, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); acb_init(a); acb_init(b); acb_init(c); acb_randtest_precise(a, state, 1 + n_randint(state, 1000), 3); acb_dirichlet_xi(b, a, prec1); if (n_randint(state, 2)) { acb_dirichlet_xi(c, a, prec2); } else /* test aliasing */ { acb_set(c, a); acb_dirichlet_xi(c, c, prec2); } if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } /* check xi(s) = xi(1-s) */ acb_sub_ui(c, a, 1, prec1); acb_neg(c, c); acb_dirichlet_xi(c, c, prec1); if (!acb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_bound.c000066400000000000000000000105241461254215100217160ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_bound, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, sb, z; arb_t x, y; slong prec, i; mag_t zbound; acb_init(s); acb_init(sb); acb_init(z); arb_init(x); arb_init(y); mag_init(zbound); acb_randtest(s, state, 2 + n_randint(state, 100), 4); if (n_randint(state, 2)) arb_set_d(acb_realref(s), -0.5 + n_randint(state, 32) / 16.0); mag_zero(arb_radref(acb_realref(s))); mag_zero(arb_radref(acb_imagref(s))); /* create a larger interval containing s */ acb_set(sb, s); for (i = 0; i < 2; i++) { arb_randtest(x, state, 2 + n_randint(state, 100), 2); arb_add(x, x, acb_realref(s), 2 * MAG_BITS); arb_intersection(acb_realref(sb), acb_realref(sb), x, 2 * MAG_BITS); arb_randtest(x, state, 2 + n_randint(state, 100), 2); arb_add(x, x, acb_imagref(s), 2 * MAG_BITS); arb_intersection(acb_imagref(sb), acb_imagref(sb), x, 2 * MAG_BITS); } acb_dirichlet_zeta_bound(zbound, sb); if (!mag_is_inf(zbound)) { for (prec = 64; ; prec *= 2) { acb_zeta(z, s, prec); if (acb_rel_accuracy_bits(z) > MAG_BITS) break; } acb_abs(x, z, 2 * MAG_BITS); arb_zero(y); arf_set_mag(arb_midref(y), zbound); if (!arb_le(x, y)) { flint_printf("FAIL: bound\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("s = "); acb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("sb = "); acb_printn(sb, 50, 0); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 50, 0); flint_printf("\n\n"); flint_printf("zbound = "); mag_printd(zbound, 10); flint_printf("\n\n"); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 50, 0); flint_printf("\n\n"); flint_abort(); } } acb_clear(s); acb_clear(sb); acb_clear(z); arb_clear(x); arb_clear(y); mag_clear(zbound); } /* test deriv_bound */ for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { acb_t s; acb_ptr v; mag_t b, b1, b2, m, m1, m2; acb_init(s); v = _acb_vec_init(3); mag_init(b); mag_init(b1); mag_init(b2); mag_init(m); mag_init(m1); mag_init(m2); acb_randtest(s, state, 2 + n_randint(state, 100), 2); arb_mul_ui(acb_realref(s), acb_realref(s), n_randtest(state) % 100, 100); arb_mul_ui(acb_imagref(s), acb_imagref(s), n_randtest(state) % 10000, 100); acb_dirichlet_zeta_bound(b, s); acb_dirichlet_zeta_deriv_bound(b1, b2, s); acb_get_mid(s, s); acb_dirichlet_zeta_jet(v, s, 0, 3, 53); acb_get_mag(m, v); acb_get_mag(m1, v + 1); acb_get_mag(m2, v + 2); if (mag_cmp(m, b) > 0 || mag_cmp(m1, b1) > 0 || mag_cmp(m2, b2) > 0) { flint_printf("FAIL\n\n"); acb_printn(s, 30, 0); flint_printf("\n\n"); mag_printd(m, 10); flint_printf(" "); mag_printd(b, 10); flint_printf("\n\n"); mag_printd(m1, 10); flint_printf(" "); mag_printd(b1, 10); flint_printf("\n\n"); mag_printd(m2, 10); flint_printf(" "); mag_printd(b2, 10); flint_printf("\n\n"); flint_abort(); } acb_clear(s); _acb_vec_clear(v, 3); mag_clear(b); mag_clear(b1); mag_clear(b2); mag_clear(m); mag_clear(m1); mag_clear(m2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_jet_rs.c000066400000000000000000000067141461254215100221030ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_jet_rs, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { acb_t s1, s2, a; acb_ptr r1, r2; slong prec1, prec2, len; acb_init(a); acb_init(s1); acb_init(s2); r1 = _acb_vec_init(2); r2 = _acb_vec_init(2); len = 1 + n_randint(state, 2); if (n_randint(state, 2)) arb_set_d(acb_realref(s1), 0.5); else arb_randtest(acb_realref(s1), state, 2 + n_randint(state, 100), 2); arb_randtest(acb_imagref(s1), state, 2 + n_randint(state, 100), 2); arb_add_ui(acb_imagref(s1), acb_imagref(s1), n_randtest(state) % 1000, 100); acb_set(s2, s1); acb_randtest(r1, state, 2 + n_randint(state, 100), 3); acb_randtest(r2, state, 2 + n_randint(state, 100), 3); if (len > 1) { acb_randtest(r1 + 1, state, 2 + n_randint(state, 100), 3); acb_randtest(r2 + 1, state, 2 + n_randint(state, 100), 3); } prec1 = 2 + n_randint(state, 150); prec2 = 2 + n_randint(state, 150); if (n_randint(state, 4) == 0) { mag_zero(arb_radref(acb_realref(s2))); mag_zero(arb_radref(acb_imagref(s2))); } if (n_randint(state, 4) == 0) { if (n_randint(state, 2)) arb_get_ubound_arf(arb_midref(acb_realref(s2)), acb_realref(s2), ARF_PREC_EXACT); else arb_get_lbound_arf(arb_midref(acb_realref(s2)), acb_realref(s2), ARF_PREC_EXACT); mag_zero(arb_radref(acb_realref(s2))); } if (n_randint(state, 4) == 0) { if (n_randint(state, 2)) arb_get_ubound_arf(arb_midref(acb_imagref(s2)), acb_imagref(s2), ARF_PREC_EXACT); else arb_get_lbound_arf(arb_midref(acb_imagref(s2)), acb_imagref(s2), ARF_PREC_EXACT); mag_zero(arb_radref(acb_imagref(s2))); } acb_dirichlet_zeta_jet_rs(r1, s1, len, prec1); acb_one(a); _acb_poly_zeta_cpx_series(r2, s2, a, 0, len, prec2); if (!acb_overlaps(r1, r2) || !acb_overlaps(r1 + 1, r2 + 1)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd, len = %wd\n", iter, len); flint_printf("s1 = "); acb_printn(s1, 50, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 50, 0); flint_printf("\n\n"); flint_printf("r1[0] = "); acb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2[0] = "); acb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("r1[1] = "); acb_printn(r1 + 1, 50, 0); flint_printf("\n\n"); flint_printf("r2[1] = "); acb_printn(r2 + 1, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(s1); acb_clear(s2); _acb_vec_clear(r1, 2); _acb_vec_clear(r2, 2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_nzeros.c000066400000000000000000000075521461254215100221360ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_nzeros, state) { slong iter; for (iter = 0; iter < 130 + 20 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, t; arf_t f1, f2; fmpz_t n, m, k1, k2; acb_t z; slong prec1, prec2; arb_init(x); arb_init(y); arb_init(t); acb_init(z); arf_init(f1); arf_init(f2); fmpz_init(n); fmpz_init(m); fmpz_init(k1); fmpz_init(k2); if (iter < 130) { fmpz_set_si(n, iter + 1); } else { fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 131); } prec1 = 2 + n_randtest(state) % 50; prec2 = 2 + n_randtest(state) % 200; acb_dirichlet_hardy_z_zero(t, n, prec1); acb_dirichlet_zeta_nzeros(x, t, prec2); fmpz_sub_ui(m, n, 1); if (!arb_contains_fmpz(x, n) || !arb_contains_fmpz(x, m)) { flint_printf("FAIL: zero containment\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("t = "); arb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_get_lbound_arf(f1, t, prec1); arb_get_ubound_arf(f2, t, prec1); _acb_dirichlet_exact_zeta_nzeros(k1, f1); _acb_dirichlet_exact_zeta_nzeros(k2, f2); if (!(fmpz_cmp(k1, n) < 0 && fmpz_cmp(k2, n) >= 0)) { flint_printf("FAIL: near a zero\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("f2 = "); arf_print(f2); flint_printf("\n\n"); flint_printf("k1 = "); fmpz_print(k1); flint_printf("\n\n"); flint_printf("k2 = "); fmpz_print(k2); flint_printf("\n\n"); flint_abort(); } fmpz_sub_ui(m, n, 2); acb_dirichlet_gram_point(t, m, NULL, NULL, prec1); arb_get_lbound_arf(f1, t, prec1); arb_get_ubound_arf(f2, t, prec1); arb_set_interval_arf(t, f1, f2, prec1); acb_set_arb(z, t); acb_dirichlet_hardy_z(z, z, NULL, NULL, 1, prec1); if (!acb_contains_zero(z)) { _acb_dirichlet_exact_zeta_nzeros(k1, f1); _acb_dirichlet_exact_zeta_nzeros(k2, f2); if (!fmpz_equal(k1, k2)) { flint_printf("FAIL: near a gram point\n\n"); flint_printf("m = "); fmpz_print(m); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("f2 = "); arf_print(f2); flint_printf("\n\n"); flint_printf("k1 = "); fmpz_print(k1); flint_printf("\n\n"); flint_printf("k2 = "); fmpz_print(k2); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(y); arb_clear(t); acb_clear(z); arf_clear(f1); arf_clear(f2); fmpz_clear(n); fmpz_clear(m); fmpz_clear(k1); fmpz_clear(k2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_nzeros_gram.c000066400000000000000000000034331461254215100231360ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_nzeros_gram, state) { slong iter; for (iter = 0; iter < 130 + 20 * 0.1 * flint_test_multiplier(); iter++) { arb_t t, x; fmpz_t N, n; slong prec1, prec2; arb_init(t); arb_init(x); fmpz_init(n); fmpz_init(N); if (iter < 130) { fmpz_set_si(n, iter - 1); } else { fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 129); } prec1 = 2 + n_randtest(state) % 100; prec2 = 2 + n_randtest(state) % 100; acb_dirichlet_zeta_nzeros_gram(N, n); acb_dirichlet_gram_point(t, n, NULL, NULL, prec1); acb_dirichlet_zeta_nzeros(x, t, prec2); if (!arb_contains_fmpz(x, N)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("N = "); fmpz_print(N); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 100, 0); flint_printf("\n\n"); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(t); arb_clear(x); fmpz_clear(n); fmpz_clear(N); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_rs.c000066400000000000000000000043661461254215100212420ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_rs, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z1, z2, s1, s2; slong prec1, prec2, K1; acb_init(z1); acb_init(z2); acb_init(s1); acb_init(s2); if (n_randint(state, 2)) arb_set_d(acb_realref(s1), 0.5); else arb_randtest(acb_realref(s1), state, 2 + n_randint(state, 100), 2); arb_randtest(acb_imagref(s1), state, 2 + n_randint(state, 100), 2); arb_add_ui(acb_imagref(s1), acb_imagref(s1), n_randtest(state) % 1000, 100); acb_randtest(z1, state, 2 + n_randint(state, 100), 3); acb_randtest(z2, state, 2 + n_randint(state, 100), 3); prec1 = 2 + n_randint(state, 150); prec2 = 2 + n_randint(state, 150); K1 = n_randint(state, 10); if (n_randint(state, 2)) { mag_zero(arb_radref(acb_realref(s1))); mag_zero(arb_radref(acb_imagref(s1))); } acb_set(s2, s1); acb_dirichlet_zeta_rs(z1, s1, K1, prec1); acb_zeta(z2, s2, prec2); /* should be Euler-Maclaurin */ if (!acb_overlaps(z1, z2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("K1 = %wd\n\n", K1); flint_printf("s1 = "); acb_printn(s1, 50, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 50, 0); flint_printf("\n\n"); flint_printf("z1 = "); acb_printn(z1, 50, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z1); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_rs_r.c000066400000000000000000000050011461254215100215460ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_rs_r, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z1, z2, s1, s2; slong prec1, prec2, K1, K2; acb_init(z1); acb_init(z2); acb_init(s1); acb_init(s2); if (n_randint(state, 2)) arb_set_d(acb_realref(s1), 0.5); else arb_randtest(acb_realref(s1), state, 2 + n_randint(state, 100), 2); arb_randtest(acb_imagref(s1), state, 2 + n_randint(state, 100), 2); arb_abs(acb_imagref(s1), acb_imagref(s1)); arb_add_ui(acb_imagref(s1), acb_imagref(s1), n_randtest(state) % 1000000, 100); acb_randtest(z1, state, 2 + n_randint(state, 100), 3); acb_randtest(z2, state, 2 + n_randint(state, 100), 3); prec1 = 2 + n_randint(state, 150); prec2 = 2 + n_randint(state, 150); K1 = n_randint(state, 10); K2 = n_randint(state, 10); if (n_randint(state, 2)) { mag_zero(arb_radref(acb_realref(s1))); mag_zero(arb_radref(acb_imagref(s1))); } if (n_randint(state, 2)) { acb_set(s2, s1); } else { acb_add(s2, s1, z1, prec2); acb_sub(s2, s2, z1, prec2); } acb_dirichlet_zeta_rs_r(z1, s1, K1, prec1); acb_dirichlet_zeta_rs_r(z2, s2, K2, prec2); if (!acb_overlaps(z1, z2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("K1 = %wd, K2 = %wd\n\n", K1, K2); flint_printf("s1 = "); acb_printn(s1, 50, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 50, 0); flint_printf("\n\n"); flint_printf("z1 = "); acb_printn(z1, 50, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(s1); acb_clear(s2); acb_clear(z1); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_zero.c000066400000000000000000000052751461254215100215750ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_zero, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { acb_t v1, v2, z1, z2; fmpz_t n, m; slong prec1, prec2; acb_init(v1); acb_init(v2); acb_init(z1); acb_init(z2); fmpz_init(n); fmpz_init(m); fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 1); if (n_randint(state, 10) != 0) { prec1 = 2 + n_randtest(state) % 50; prec2 = 2 + n_randtest(state) % 200; } else { prec1 = 2 + n_randtest(state) % 200; prec2 = 2 + n_randtest(state) % 600; } acb_dirichlet_zeta_zero(z1, n, prec1); acb_dirichlet_zeta_zero(z2, n, prec2); acb_dirichlet_zeta(v1, z1, prec1 + 20); acb_dirichlet_zeta(v2, z2, prec2 + 20); if (!acb_overlaps(z1, z2) || !acb_contains_zero(v1) || !acb_contains_zero(v2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("z1 = "); acb_printn(z1, 100, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 100, 0); flint_printf("\n\n"); flint_printf("v1 = "); acb_printn(v1, 100, 0); flint_printf("\n\n"); flint_printf("v2 = "); acb_printn(v2, 100, 0); flint_printf("\n\n"); flint_abort(); } if (acb_rel_accuracy_bits(z1) < prec1 - 3 || acb_rel_accuracy_bits(z2) < prec2 - 3) { flint_printf("FAIL: accuracy\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("acc(z1) = %wd, acc(z2) = %wd\n\n", acb_rel_accuracy_bits(z1), acb_rel_accuracy_bits(z2)); flint_printf("z1 = "); acb_printn(z1, 100, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 100, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(z1); acb_clear(z2); acb_clear(v1); acb_clear(v2); fmpz_clear(n); fmpz_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/test/t-zeta_zeros.c000066400000000000000000000055061461254215100217550ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(acb_dirichlet_zeta_zeros, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { acb_t v1, v2, z1, z2; fmpz_t n, m, k; acb_ptr p; slong prec1, prec2; slong i, len; const slong maxlen = 5; acb_init(v1); acb_init(v2); acb_init(z1); acb_init(z2); fmpz_init(n); fmpz_init(m); fmpz_init(k); p = _acb_vec_init(maxlen); fmpz_randtest_unsigned(n, state, 20); fmpz_add_ui(n, n, 1); prec1 = 2 + n_randtest(state) % 50; prec2 = 2 + n_randtest(state) % 200; len = 1 + n_randint(state, maxlen); i = n_randint(state, len); acb_dirichlet_zeta_zeros(p, n, len, prec1); acb_set(z1, p + i); fmpz_add_si(k, n, i); acb_dirichlet_zeta_zero(z2, k, prec2); acb_dirichlet_zeta(v1, z1, prec1 + 20); acb_dirichlet_zeta(v2, z2, prec2 + 20); if (!acb_overlaps(z1, z2) || !acb_contains_zero(v1) || !acb_contains_zero(v2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("z1 = "); acb_printn(z1, 100, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 100, 0); flint_printf("\n\n"); flint_printf("v1 = "); acb_printn(v1, 100, 0); flint_printf("\n\n"); flint_printf("v2 = "); acb_printn(v2, 100, 0); flint_printf("\n\n"); flint_abort(); } if (acb_rel_accuracy_bits(z1) < prec1 - 3 || acb_rel_accuracy_bits(z2) < prec2 - 3) { flint_printf("FAIL: accuracy\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("acc(z1) = %wd, acc(z2) = %wd\n\n", acb_rel_accuracy_bits(z1), acb_rel_accuracy_bits(z2)); flint_printf("z1 = "); acb_printn(z1, 100, 0); flint_printf("\n\n"); flint_printf("z2 = "); acb_printn(z2, 100, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(z1); acb_clear(z2); acb_clear(v1); acb_clear(v2); fmpz_clear(n); fmpz_clear(m); fmpz_clear(k); _acb_vec_clear(p, maxlen); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_dirichlet/theta_arb.c000066400000000000000000000055311461254215100202770ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "acb_poly.h" void _acb_dirichlet_theta_arb_smallorder(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec) { ulong order; ulong * a; int parity; acb_dirichlet_roots_t z; parity = dirichlet_parity_char(G, chi); order = dirichlet_order_char(G, chi); a = flint_malloc(len * sizeof(ulong)); dirichlet_chi_vec_order(a, G, chi, order, len); acb_dirichlet_roots_init(z, order, 0, prec); acb_dirichlet_qseries_arb_powers_smallorder(res, xt, parity, a, z, len, prec); acb_dirichlet_roots_clear(z); flint_free(a); } void _acb_dirichlet_theta_arb_series(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec) { acb_ptr a; a = _acb_vec_init(len); acb_dirichlet_chi_vec(a, G, chi, len, prec); if (dirichlet_parity_char(G, chi)) { slong k; for (k = 2; k < len; k++) acb_mul_si(a + k, a + k, k, prec); } acb_dirichlet_qseries_arb(res, a, xt, len, prec); _acb_vec_clear(a, len); } void _acb_dirichlet_theta_arb_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec) { ulong order, * a; acb_dirichlet_roots_t z; int parity; parity = dirichlet_parity_char(G, chi); order = dirichlet_order_char(G, chi); a = flint_malloc(len * sizeof(ulong)); dirichlet_chi_vec_order(a, G, chi, order, len); acb_dirichlet_roots_init(z, order, len, prec); acb_dirichlet_qseries_arb_powers_naive(res, xt, parity, a, z, len, prec); acb_dirichlet_roots_clear(z); flint_free(a); } void acb_dirichlet_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec) { slong len; ulong order; arb_t xt; mag_t e; len = acb_dirichlet_theta_length(G->q, t, prec); arb_init(xt); _acb_dirichlet_theta_argument_at_arb(xt, G->q, t, prec); mag_init(e); mag_tail_kexpk2_arb(e, xt, len); arb_neg(xt, xt); arb_exp(xt, xt, prec); /* TODO: tune this limit */ order = dirichlet_order_char(G, chi); if (order < 30) _acb_dirichlet_theta_arb_smallorder(res, G, chi, xt, len, prec); else _acb_dirichlet_theta_arb_naive(res, G, chi, xt, len, prec); arb_add_error_mag(acb_realref(res), e); arb_add_error_mag(acb_imagref(res), e); mag_clear(e); acb_mul_2exp_si(res, res, 1); arb_clear(xt); } flint-3.1.3/src/acb_dirichlet/theta_length.c000066400000000000000000000037121461254215100210130ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include #define PI 3.14159265358 #define LOG2 0.69314718055 ulong acb_dirichlet_theta_length_d(ulong q, double t, slong prec) { double a, la; a = PI / (double)q * t * t; la = (a < .3) ? -log(2*a*(1-a)) : .8; la = ((double)prec * LOG2 + la) / a; return ceil(sqrt(la)+.5); } ulong acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec) { double dt; ulong len; arf_t at; arf_init(at); arb_get_lbound_arf(at, t, 53); dt = arf_get_d(at, ARF_RND_DOWN); len = acb_dirichlet_theta_length_d(q, dt, prec); arf_clear(at); return len; } /* bound for sum_{k>n} k*exp(-a k^2) */ void mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n) { mag_t m; mag_init(m); arb_get_mag_lower(m, a); /* a < 1/4 */ if (mag_cmp_2exp_si(m, -2) <= 0) { mag_t c; mag_init(c); mag_mul_ui_lower(res, m, n*n-n+1); /* todo: possible overflow */ mag_expinv(res, res); /* c = 2a(1+2a) */ mag_mul_2exp_si(m, m, 1); mag_one(c); mag_add_lower(c, m, c); mag_mul_lower(c, m, c); mag_div(res, res, c); mag_clear(c); } else { mag_mul_ui_lower(res, m, n*n-n-1); /* todo: possible overflow */ mag_expinv(res, res); mag_mul_ui(res, res, 2); } mag_clear(m); } /* a(t) = Pi / q * t^2 */ void _acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slong prec) { arb_const_pi(xt, prec); arb_div_ui(xt, xt, q, prec); arb_mul(xt, xt, t, prec); arb_mul(xt, xt, t, prec); } flint-3.1.3/src/acb_dirichlet/turing_method_bound.c000066400000000000000000000027501461254215100224050ustar00rootroot00000000000000/* Copyright (C) 2019 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void _mag_div_ui_ui(mag_t res, ulong a, ulong b) { mag_set_ui(res, a); mag_div_ui(res, res, b); } ulong acb_dirichlet_turing_method_bound(const fmpz_t p) { ulong result; arb_t t; fmpz_t k; mag_t m, b1, b2, c; arb_init(t); fmpz_init(k); mag_init(m); mag_init(b1); mag_init(b2); mag_init(c); acb_dirichlet_gram_point(t, p, NULL, NULL, FLINT_MAX(8, fmpz_bits(p))); arb_get_mag(m, t); mag_log(m, m); /* b1 = 0.0061*log(gram(p))^2 + 0.08*log(gram(p)) */ _mag_div_ui_ui(c, 61, 10000); mag_mul(b1, c, m); _mag_div_ui_ui(c, 8, 100); mag_add(b1, b1, c); mag_mul(b1, b1, m); /* b2 = 0.0031*log(gram(p))^2 + 0.11*log(gram(p)) */ _mag_div_ui_ui(c, 31, 10000); mag_mul(b2, c, m); _mag_div_ui_ui(c, 11, 100); mag_add(b2, b2, c); mag_mul(b2, b2, m); /* result = ceil(min(b1, b2)) */ mag_min(m, b1, b2); mag_get_fmpz(k, m); result = fmpz_get_ui(k); arb_clear(t); fmpz_clear(k); mag_clear(m); mag_clear(b1); mag_clear(b2); mag_clear(c); return result; } flint-3.1.3/src/acb_dirichlet/ui_theta_arb.c000066400000000000000000000012671461254215100207760ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec) { dirichlet_char_t chi; dirichlet_char_init(chi, G); dirichlet_char_log(chi, G, a); acb_dirichlet_theta_arb(res, G, chi, t, prec); dirichlet_char_clear(chi); } flint-3.1.3/src/acb_dirichlet/vec_mellin_arb.c000066400000000000000000000030401461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_vec_mellin_arb(acb_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, const arb_t t, slong n, slong prec) { slong k; arb_t tk, xt, stk, st; acb_ptr a; mag_t e; a = _acb_vec_init(len); acb_dirichlet_chi_vec(a, G, chi, len, prec); if (dirichlet_parity_char(G, chi)) { for (k = 2; k < len; k++) acb_mul_si(a + k, a + k, k, prec); } arb_init(tk); arb_init(xt); arb_init(st); arb_init(stk); mag_init(e); arb_sqrt(st, t, prec); arb_one(tk); arb_one(stk); for (k = 0; k < n; k++) { _acb_dirichlet_theta_argument_at_arb(xt, G->q, tk, prec); mag_tail_kexpk2_arb(e, xt, len); arb_neg(xt, xt); arb_exp(xt, xt, prec); /* TODO: reduce len */ acb_dirichlet_qseries_arb(res + k, a, xt, len, prec); acb_add_error_mag(res + k, e); acb_mul_arb(res + k, res + k, stk, prec); arb_mul(tk, tk, t, prec); arb_mul(stk, stk, st, prec); } mag_clear(e); arb_clear(xt); arb_clear(tk); arb_clear(stk); arb_clear(st); _acb_vec_clear(a, len); } flint-3.1.3/src/acb_dirichlet/xi.c000066400000000000000000000032571461254215100167710ustar00rootroot00000000000000/* Copyright (C) 2018 D.H.J Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void _acb_dirichlet_xi(acb_t res, const acb_t s, slong prec) { acb_t pi, z1, z2, z3; acb_init(pi); acb_init(z1); acb_init(z2); acb_init(z3); /* (s-1) * pi^(-s/2) * gamma(1 + s/2) * zeta(s) */ acb_const_pi(pi, prec); acb_mul_2exp_si(z1, s, -1); acb_neg(z1, z1); acb_pow(z1, pi, z1, prec); acb_mul_2exp_si(z2, s, -1); acb_add_ui(z2, z2, 1, prec); acb_gamma(z2, z2, prec); acb_zeta(z3, s, prec); acb_sub_ui(res, s, 1, prec); acb_mul(res, res, z1, prec); acb_mul(res, res, z2, prec); acb_mul(res, res, z3, prec); acb_clear(pi); acb_clear(z1); acb_clear(z2); acb_clear(z3); } void acb_dirichlet_xi(acb_t res, const acb_t s, slong prec) { if (!acb_is_finite(s)) { acb_indeterminate(res); } else if (acb_is_one(s)) { acb_one(res); acb_mul_2exp_si(res, res, -1); } else if ((arf_sgn(arb_midref(acb_realref(s))) < 0 && !acb_contains_zero(s)) || (arb_contains_si(acb_realref(s), 1) && /* also intervals around s = 1 */ arb_contains_zero(acb_imagref(s)))) { acb_sub_ui(res, s, 1, prec); acb_neg(res, res); _acb_dirichlet_xi(res, res, prec); } else { _acb_dirichlet_xi(res, s, prec); } } flint-3.1.3/src/acb_dirichlet/zeta.c000066400000000000000000000045531461254215100173140ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif void acb_zeta_si(acb_t z, slong s, slong prec); static void _acb_dirichlet_zeta(acb_t res, const acb_t s, slong prec) { acb_t a; acb_init(a); acb_one(a); _acb_poly_zeta_cpx_series(res, s, a, 0, 1, prec); acb_clear(a); } /* todo: use euler product for complex s, and check efficiency for large negative integers */ void acb_dirichlet_zeta(acb_t res, const acb_t s, slong prec) { double cutoff; if (acb_is_int(s) && arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), FLINT_BITS - 1) < 0) { acb_zeta_si(res, arf_get_si(arb_midref(acb_realref(s)), ARF_RND_DOWN), prec); return; } if (arb_contains_zero(acb_imagref(s)) && arb_contains_si(acb_realref(s), 1)) { acb_indeterminate(res); return; } cutoff = 24.0 * prec * sqrt(prec); if (arf_cmpabs_d(arb_midref(acb_imagref(s)), cutoff) >= 0 && arf_cmpabs_d(arb_midref(acb_realref(s)), 10 + prec * 0.1) <= 0) { acb_dirichlet_zeta_rs(res, s, 0, prec); return; } if ((arf_sgn(arb_midref(acb_realref(s))) < 0) && !acb_contains_zero(s)) { acb_t t, u, v; slong wp = prec + 6; acb_init(t); acb_init(u); acb_init(v); acb_sub_ui(t, s, 1, wp); /* 2 * (2pi)^(s-1) */ arb_const_pi(acb_realref(u), wp); acb_mul_2exp_si(u, u, 1); acb_pow(u, u, t, wp); acb_mul_2exp_si(u, u, 1); /* sin(pi*s/2) */ acb_mul_2exp_si(v, s, -1); acb_sin_pi(v, v, wp); acb_mul(u, u, v, wp); /* gamma(1-s) zeta(1-s) */ acb_neg(t, t); acb_gamma(v, t, wp); acb_mul(u, u, v, wp); _acb_dirichlet_zeta(v, t, prec); acb_mul(res, u, v, prec); acb_clear(t); acb_clear(u); acb_clear(v); } else { _acb_dirichlet_zeta(res, s, prec); } } flint-3.1.3/src/acb_dirichlet/zeta_bound.c000066400000000000000000000166551461254215100205110ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" static void _mag_pow(mag_t res, const mag_t x, const mag_t y) { arb_t t, u; arb_init(t); arb_init(u); arf_set_mag(arb_midref(t), x); arf_set_mag(arb_midref(u), y); arb_pow(t, t, u, 2 * MAG_BITS); arb_get_mag(res, t); arb_clear(t); arb_clear(u); } /* zeta(1+s) < 1+1/s */ static void mag_zeta1p(mag_t res, const mag_t s) { mag_t t; mag_init(t); mag_one(t); mag_div(t, t, s); mag_add_ui(res, t, 1); mag_clear(t); } /* |zeta(s)| <= (2pi)^sigma |gamma(1-s)| exp(pi|t|/2) zeta(1-sigma) / pi */ void acb_dirichlet_zeta_bound_functional_equation(mag_t res, const acb_t s) { slong prec, p; acb_t z; arb_t x; mag_t t; if (!arb_is_negative(acb_realref(s))) { mag_inf(res); return; } acb_init(z); arb_init(x); mag_init(t); prec = 0; p = arf_abs_bound_lt_2exp_si(arb_midref(acb_imagref(s))); prec = FLINT_MAX(p, prec); p = arf_abs_bound_lt_2exp_si(arb_midref(acb_realref(s))); prec = FLINT_MAX(p, prec); /* we *could* increase the precision even further to return finite results for huge input... but there's not much practical reason to... */ prec = FLINT_MIN(prec, 1000); prec += MAG_BITS; /* gamma(1-s) */ acb_sub_ui(z, s, 1, prec); acb_neg(z, z); acb_gamma(z, z, prec); acb_get_mag(res, z); /* (2pi)^sigma */ arb_const_pi(x, prec); arb_mul_2exp_si(x, x, 1); arb_pow(x, x, acb_realref(s), prec); arb_get_mag(t, x); mag_mul(res, res, t); /* 1/pi */ mag_div_ui(res, res, 3); /* exp(pi|t|/2) */ arb_const_pi(x, prec); arb_mul(x, x, acb_imagref(s), prec); arb_abs(x, x); arb_mul_2exp_si(x, x, -1); arb_exp(x, x, prec); arb_get_mag(t, x); mag_mul(res, res, t); /* zeta(1-s) */ arb_neg(x, acb_realref(s)); arb_get_mag_lower(t, x); mag_zeta1p(t, t); mag_mul(res, res, t); acb_clear(z); arb_clear(x); mag_clear(t); } /* Rademacher 43.3: Assume -eta <= sigma <= 1 + eta where 0 < eta <= 1/2. Then: |zeta(s)| < 3 |(1+s)/(1-s)| |(1+s)/(2pi)|^e zeta(1+eta) where e = (1+eta-sigma)/2. Inside the strip, we use this formula with eta = 0.1 (this could be improved). */ void acb_dirichlet_zeta_bound_strip(mag_t res, const acb_t s) { arf_t eta, a; acb_t s1; mag_t t, u, v; acb_init(s1); arf_init(eta); arf_init(a); mag_init(t); mag_init(u); mag_init(v); /* We need -eta <= sigma <= 1 + eta where sigma = m +/- r, i.e. eta >= max(-m, m-1) + r. */ arf_neg(eta, arb_midref(acb_realref(s))); arf_sub_ui(a, arb_midref(acb_realref(s)), 1, MAG_BITS, ARF_RND_CEIL); arf_max(eta, eta, a); arf_set_mag(a, arb_radref(acb_realref(s))); arf_add(eta, eta, a, MAG_BITS, ARF_RND_CEIL); /* eta = max(eta, 0.1), to avoid the pole */ arf_set_d(a, 0.1); arf_max(eta, eta, a); /* Requires 0 <= eta <= 1/2. */ if (arf_cmpabs_2exp_si(eta, -1) <= 0) { /* t = |1+s|/(2pi) */ acb_add_ui(s1, s, 1, MAG_BITS); acb_get_mag(t, s1); mag_set_ui_2exp_si(u, 163, -10); /* 1/(2pi) < 163/1024 */ mag_mul(t, t, u); /* a = (1+eta-sigma)/2 */ arf_set_mag(a, arb_radref(acb_realref(s))); arf_add(a, eta, a, MAG_BITS, ARF_RND_CEIL); arf_sub(a, a, arb_midref(acb_realref(s)), MAG_BITS, ARF_RND_CEIL); arf_add_ui(a, a, 1, MAG_BITS, ARF_RND_CEIL); arf_mul_2exp_si(a, a, -1); if (arf_sgn(a) < 0) arf_zero(a); arf_get_mag(u, a); /* t = (|1+s|/(2pi))^((1+eta-sigma)/2) */ _mag_pow(t, t, u); /* 3|1+s|/|1-s| */ acb_get_mag(u, s1); mag_mul(t, t, u); acb_sub_ui(s1, s, 1, MAG_BITS); acb_get_mag_lower(u, s1); mag_div(t, t, u); mag_mul_ui(t, t, 3); /* zeta(1+eta) */ arf_get_mag_lower(u, eta); mag_zeta1p(u, u); mag_mul(t, t, u); mag_set(res, t); } else { mag_inf(res); } acb_clear(s1); arf_clear(eta); arf_clear(a); mag_clear(t); mag_clear(u); mag_clear(v); } /* We have three cases: Rademacher's bound valid on -0.5 <= sigma <= 1.5, the trivial bound on sigma > 1, and the functional equation valid on sigma < 0. We intersect s with three separate domains for evaluation: right, inside, and left of the extended strip [-0.25,1.25]. Sharper bounds could be used precisely when sigma = 1/2, or very close to the line sigma = 1. */ void acb_dirichlet_zeta_bound(mag_t res, const acb_t s) { arb_t strip; mag_t t; if (!acb_is_finite(s)) { mag_inf(res); return; } arb_init(strip); mag_init(t); arf_set_ui_2exp_si(arb_midref(strip), 1, -1); mag_set_ui_2exp_si(arb_radref(strip), 3, -2); if (arb_le(strip, acb_realref(s))) { arb_get_mag_lower(res, acb_realref(s)); mag_one(t); mag_sub_lower(res, res, t); mag_zeta1p(res, res); } else if (arb_contains(strip, acb_realref(s))) { acb_dirichlet_zeta_bound_strip(res, s); } else if (arb_le(acb_realref(s), strip)) { acb_dirichlet_zeta_bound_functional_equation(res, s); } else { acb_t ss; arf_t x1, x2; acb_init(ss); arf_init(x1); arf_init(x2); /* Since s overlaps at least two regions, it must certainly overlap with the extended strip. */ arb_set(acb_imagref(ss), acb_imagref(s)); arb_intersection(acb_realref(ss), acb_realref(s), strip, MAG_BITS); acb_dirichlet_zeta_bound_strip(res, ss); /* We may have real parts > 1.25. */ /* The bound computed for the extended strip *should* already be larger than zeta(1.25) < 5, but just to be sure... */ mag_set_ui(t, 5); mag_max(res, res, t); /* Finally, we may have have real parts < -0.25. */ arf_set_mag(x1, arb_radref(acb_realref(s))); arf_sub(x1, arb_midref(acb_realref(s)), x1, MAG_BITS, ARF_RND_FLOOR); arf_set_d(x2, -0.25); if (arf_cmp(x1, x2) < 0) { arb_set_interval_arf(acb_realref(ss), x1, x2, MAG_BITS); acb_dirichlet_zeta_bound_functional_equation(t, ss); mag_max(res, res, t); } acb_clear(ss); arf_clear(x1); arf_clear(x2); } arb_clear(strip); mag_clear(t); } /* |f'(s)| <= |f(s +/- R)| / R |f''(s)| <= 2 |f(s +/- R)| / R^2 */ void acb_dirichlet_zeta_deriv_bound(mag_t der1, mag_t der2, const acb_t s) { mag_t R, M; acb_t t; mag_init(R); mag_init(M); acb_init(t); /* R = 1/8 */ mag_set_ui_2exp_si(R, 1, -3); /* t = s +/- R */ acb_set(t, s); mag_add(arb_radref(acb_realref(t)), arb_radref(acb_realref(t)), R); mag_add(arb_radref(acb_imagref(t)), arb_radref(acb_imagref(t)), R); /* M = |f(s +/- R)| */ acb_dirichlet_zeta_bound(M, t); /* der1 = |f'(s)| */ mag_div(der1, M, R); /* der2 = |f''(s)| */ mag_div(der2, der1, R); mag_mul_2exp_si(der2, der2, 1); acb_clear(t); mag_clear(R); mag_clear(M); } flint-3.1.3/src/acb_dirichlet/zeta_jet.c000066400000000000000000000076551461254215100201640ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif void _acb_dirichlet_zeta_jet(acb_t t, const acb_t h, int deflate, slong len, slong prec) { acb_t a; acb_init(a); acb_one(a); /* use reflection formula */ if (arf_sgn(arb_midref(acb_realref(h))) < 0) { /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */ acb_t pi, hcopy; acb_ptr f, s1, s2, s3, s4, u; slong i; acb_init(pi); acb_init(hcopy); f = _acb_vec_init(2); s1 = _acb_vec_init(len); s2 = _acb_vec_init(len); s3 = _acb_vec_init(len); s4 = _acb_vec_init(len); u = _acb_vec_init(len); acb_set(hcopy, h); acb_const_pi(pi, prec); /* s1 = (2*pi)**s */ acb_mul_2exp_si(pi, pi, 1); _acb_poly_pow_cpx(s1, pi, h, len, prec); acb_mul_2exp_si(pi, pi, -1); /* s2 = sin(pi*s/2) / pi */ acb_set(f, h); acb_one(f + 1); acb_mul_2exp_si(f, f, -1); acb_mul_2exp_si(f + 1, f + 1, -1); _acb_poly_sin_pi_series(s2, f, 2, len, prec); _acb_vec_scalar_div(s2, s2, len, pi, prec); /* s3 = gamma(1-s) */ acb_sub_ui(f, hcopy, 1, prec); acb_neg(f, f); acb_set_si(f + 1, -1); _acb_poly_gamma_series(s3, f, 2, len, prec); /* s4 = zeta(1-s) */ acb_sub_ui(f, hcopy, 1, prec); acb_neg(f, f); _acb_poly_zeta_cpx_series(s4, f, a, 0, len, prec); for (i = 1; i < len; i += 2) acb_neg(s4 + i, s4 + i); _acb_poly_mullow(u, s1, len, s2, len, len, prec); _acb_poly_mullow(s1, s3, len, s4, len, len, prec); _acb_poly_mullow(t, u, len, s1, len, len, prec); /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */ if (deflate) { acb_sub_ui(u, hcopy, 1, prec); acb_neg(u, u); acb_inv(u, u, prec); for (i = 1; i < len; i++) acb_mul(u + i, u + i - 1, u, prec); _acb_vec_add(t, t, u, len, prec); } acb_clear(pi); acb_clear(hcopy); _acb_vec_clear(f, 2); _acb_vec_clear(s1, len); _acb_vec_clear(s2, len); _acb_vec_clear(s3, len); _acb_vec_clear(s4, len); _acb_vec_clear(u, len); } else { _acb_poly_zeta_cpx_series(t, h, a, deflate, len, prec); } acb_clear(a); } /* todo: should adjust precision to input accuracy */ void acb_dirichlet_zeta_jet(acb_t res, const acb_t s, int deflate, slong len, slong prec) { double cutoff; if (len == 1 && deflate == 0) { acb_zeta(res, s, prec); return; } if (deflate == 0 && (arb_contains_zero(acb_imagref(s)) && arb_contains_si(acb_realref(s), 1))) { _acb_vec_indeterminate(res, len); return; } if (len > 2 || deflate != 0) { _acb_dirichlet_zeta_jet(res, s, deflate, len, prec); } else { cutoff = 24.0 * prec * sqrt(prec); if (arb_is_exact(acb_realref(s)) && arf_cmp_2exp_si(arb_midref(acb_realref(s)), -1) == 0) cutoff *= 2.5; else cutoff *= 4.0; if (arf_cmpabs_d(arb_midref(acb_imagref(s)), cutoff) >= 0 && arf_cmpabs_d(arb_midref(acb_realref(s)), 10 + prec * 0.1) <= 0) { acb_dirichlet_zeta_jet_rs(res, s, len, prec); } else { _acb_dirichlet_zeta_jet(res, s, deflate, len, prec); } } } flint-3.1.3/src/acb_dirichlet/zeta_jet_rs.c000066400000000000000000000104341461254215100206550ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* f(s) = (f(s+hi) + f(s-hi))/2 + err0 f'(s) = (f(s+hi) - f(s-hi))/(2hi) + err1 |err0| <= |f(s +/- R)| (1/R)^2 h^2 / (1 - h/R) |err1| <= |f(s +/- R)| (1/R)^3 h^2 / (1 - h/R) assuming h/R < 1 */ static void acb_dirichlet_zeta_jet_rs_mid(acb_ptr res, const acb_t s, slong prec) { acb_t t, u; arb_t hh; mag_t h, R, err0, err1, tmp; slong hexp; acb_init(t); acb_init(u); arb_init(hh); mag_init(h); mag_init(R); mag_init(err0); mag_init(err1); mag_init(tmp); hexp = -(prec / 2) - 10; mag_set_ui_2exp_si(h, 1, hexp); mag_set_ui_2exp_si(R, 1, -5); acb_set(t, s); mag_add(arb_radref(acb_realref(t)), arb_radref(acb_realref(t)), R); mag_add(arb_radref(acb_imagref(t)), arb_radref(acb_imagref(t)), R); /* tmp = |f(s +/- R)| */ acb_dirichlet_zeta_bound(tmp, t); /* err0 = (1/R)^2 h^2 / (1 - h/R) */ mag_div(err0, h, R); mag_geom_series(err0, err0, 2); /* err0 *= tmp */ mag_mul(err0, err0, tmp); /* err1 = err0 / R */ mag_div(err1, err0, R); /* hh = h as an arb_t */ arb_one(hh); arb_mul_2exp_si(hh, hh, hexp); acb_set(t, s); acb_set(u, s); arb_add(acb_imagref(t), acb_imagref(t), hh, 10 * prec); arb_sub(acb_imagref(u), acb_imagref(u), hh, 10 * prec); /* zeta(mid(s)+ih) */ acb_dirichlet_zeta_rs(res, t, 0, 1.5 * prec + 10); /* zeta(mid(s)-ih) */ acb_dirichlet_zeta_rs(res + 1, u, 0, 1.5 * prec + 10); acb_sub(t, res, res + 1, prec); acb_add(res, res, res + 1, prec); acb_swap(res + 1, t); acb_mul_2exp_si(res, res, -1); acb_mul_2exp_si(res + 1, res + 1, -1); acb_mul_2exp_si(res + 1, res + 1, -hexp); acb_div_onei(res + 1, res + 1); acb_add_error_mag(res, err0); acb_add_error_mag(res + 1, err1); acb_clear(t); acb_clear(u); arb_clear(hh); mag_clear(h); mag_clear(R); mag_clear(err0); mag_clear(err1); mag_clear(tmp); } void acb_dirichlet_zeta_jet_rs(acb_ptr res, const acb_t s, slong len, slong prec) { if (len > 2) { flint_throw(FLINT_ERROR, "acb_dirichlet_zeta_jet_rs: len > 2 not implemented\n"); } if (len <= 0) return; if (len == 1) { acb_dirichlet_zeta_rs(res, s, 0, prec); } else if (acb_is_exact(s)) { acb_dirichlet_zeta_jet_rs_mid(res, s, prec); } else { acb_t t; mag_t r, err0, err1, der1, der2, M; /* slong acc; acc = acb_rel_accuracy_bits(s); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + 20); */ /* assume s = m +/- r f(s) = f(m) + err0 f'(s) = f'(m) + err1 |err1| <= |f''(s)| r |err0| <= min(|f'(s)| r, |f'(m)| r + 0.5 |f''(s)| r^2) = r min(|f'(s)|, |f'(m)| + 0.5 |f''(s)| r) */ acb_init(t); mag_init(r); mag_init(err0); mag_init(err1); mag_init(der1); mag_init(der2); mag_init(M); /* r = rad(s) */ mag_hypot(r, arb_radref(acb_realref(s)), arb_radref(acb_imagref(s))); /* Bound zeta'(s), zeta''(s) */ acb_dirichlet_zeta_deriv_bound(der1, der2, s); /* f(m), f'(m) */ acb_get_mid(t, s); acb_dirichlet_zeta_jet_rs_mid(res, t, prec); /* err1 = |f''(s)| r */ mag_mul(err1, der2, r); /* err0 = |f'(m)| + 0.5 |f''(s)| r */ acb_get_mag(M, res + 1); mag_mul_2exp_si(err0, err1, -1); mag_add(err0, err0, M); /* err0 = min(err0, |f'(s)| */ mag_min(err0, err0, der1); /* err0 = err0 * r */ mag_mul(err0, err0, r); acb_add_error_mag(res, err0); acb_add_error_mag(res + 1, err1); acb_clear(t); mag_clear(r); mag_clear(err0); mag_clear(err1); mag_clear(der1); mag_clear(der2); mag_clear(M); } } flint-3.1.3/src/acb_dirichlet/zeta_rs.c000066400000000000000000000060411461254215100200120ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_zeta_rs_mid(acb_t res, const acb_t s, slong K, slong prec) { acb_t R1, R2, X, t; slong wp; if (arf_sgn(arb_midref(acb_imagref(s))) < 0) { acb_init(t); acb_conj(t, s); acb_dirichlet_zeta_rs(res, t, K, prec); acb_conj(res, res); acb_clear(t); return; } acb_init(R1); acb_init(R2); acb_init(X); acb_init(t); /* rs_r increases the precision internally */ wp = prec; acb_dirichlet_zeta_rs_r(R1, s, K, wp); if (arb_is_exact(acb_realref(s)) && (arf_cmp_2exp_si(arb_midref(acb_realref(s)), -1) == 0)) { acb_conj(R2, R1); } else { /* conj(R(conj(1-s))) */ arb_sub_ui(acb_realref(t), acb_realref(s), 1, 10 * wp); arb_neg(acb_realref(t), acb_realref(t)); arb_set(acb_imagref(t), acb_imagref(s)); acb_dirichlet_zeta_rs_r(R2, t, K, wp); acb_conj(R2, R2); } if (acb_is_finite(R1) && acb_is_finite(R2)) { wp += 10 + arf_abs_bound_lt_2exp_si(arb_midref(acb_imagref(s))); wp = FLINT_MAX(wp, 10); /* X = pi^(s-1/2) gamma((1-s)/2) rgamma(s/2) = (2 pi)^s rgamma(s) / (2 cos(pi s / 2)) */ acb_rgamma(X, s, wp); acb_const_pi(t, wp); acb_mul_2exp_si(t, t, 1); acb_pow(t, t, s, wp); acb_mul(X, X, t, wp); acb_mul_2exp_si(t, s, -1); acb_cos_pi(t, t, wp); acb_mul_2exp_si(t, t, 1); acb_div(X, X, t, wp); acb_mul(R2, R2, X, wp); } /* R1 + X * R2 */ acb_add(res, R1, R2, prec); acb_clear(R1); acb_clear(R2); acb_clear(X); acb_clear(t); } void acb_dirichlet_zeta_rs(acb_t res, const acb_t s, slong K, slong prec) { if (acb_is_exact(s)) { acb_dirichlet_zeta_rs_mid(res, s, K, prec); } else { acb_t t; mag_t rad, err, err2; slong acc; acc = acb_rel_accuracy_bits(s); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + 20); acb_init(t); mag_init(rad); mag_init(err); mag_init(err2); /* rad = rad(s) */ mag_hypot(rad, arb_radref(acb_realref(s)), arb_radref(acb_imagref(s))); /* bound |zeta'(s)| */ acb_dirichlet_zeta_deriv_bound(err, err2, s); /* error <= |zeta'(s)| * rad(s) */ mag_mul(err, err, rad); /* evaluate at midpoint */ acb_get_mid(t, s); acb_dirichlet_zeta_rs_mid(res, t, K, prec); acb_add_error_mag(res, err); acb_clear(t); mag_clear(rad); mag_clear(err); mag_clear(err2); } } flint-3.1.3/src/acb_dirichlet/zeta_rs_bound.c000066400000000000000000000042361461254215100212050ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" /* Arias de Reyna, Theorem 4.2 */ void acb_dirichlet_zeta_rs_bound(mag_t err, const acb_t s, slong K) { arb_t a; mag_t c1, c2, c3; slong e; if (!arb_is_positive(acb_imagref(s)) || K < 1 || !acb_is_finite(s)) { mag_inf(err); return; } arb_init(a); arb_add_ui(a, acb_realref(s), K, MAG_BITS); arb_sub_ui(a, a, 2, MAG_BITS); if (!arb_is_nonnegative(acb_realref(s)) && !arb_is_nonnegative(a)) { mag_inf(err); arb_clear(a); return; } mag_init(c1); mag_init(c2); mag_init(c3); /* c1 = 1/7 2^(3 sigma / 2) re(sigma) >= 0 */ /* c1 < 1/2 re(sigma) < 0 */ arf_set_mag(arb_midref(a), arb_radref(acb_realref(s))); arf_add(arb_midref(a), arb_midref(a), arb_midref(acb_realref(s)), MAG_BITS, ARF_RND_CEIL); if (arf_sgn(arb_midref(a)) <= 0) { mag_set_ui_2exp_si(c1, 1, -1); } else if (arf_cmp_2exp_si(arb_midref(a), FLINT_BITS - 4) < 0) { mag_one(c1); mag_div_ui(c1, c1, 7); e = arf_get_si(arb_midref(a), ARF_RND_CEIL); mag_mul_2exp_si(c1, c1, (3 * e + 1) / 2); if (mag_cmp_2exp_si(c1, -1) < 0) mag_set_ui_2exp_si(c1, 1, -1); } else { mag_inf(c1); } /* c2 = 1 / ((10/11) sqrt(t/(2pi))) = (11/10) sqrt((2pi)/t) */ arb_get_mag_lower(c3, acb_imagref(s)); mag_const_pi(c2); mag_mul_2exp_si(c2, c2, 1); mag_div(c2, c2, c3); mag_sqrt(c2, c2); mag_mul_ui(c2, c2, 11); mag_div_ui(c2, c2, 10); /* c2 = c2^(K+1) */ mag_pow_ui(c2, c2, K + 1); /* c3 = gamma((K+1)/2) */ mag_fac_ui(c3, K / 2); mag_mul(err, c1, c2); mag_mul(err, err, c3); mag_clear(c1); mag_clear(c2); mag_clear(c3); arb_clear(a); } flint-3.1.3/src/acb_dirichlet/zeta_rs_d_coeffs.c000066400000000000000000000027521461254215100216470ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_zeta_rs_d_coeffs(arb_ptr d, const arb_t sigma, slong k, slong prec) { slong j, r, m; arb_t u; arb_init(u); arb_one(u); arb_submul_ui(u, sigma, 2, prec); if (k == 0) { arb_one(d); arb_zero(d + 1); return; } for (j = (3 * k) / 2; j >= 0; j--) { m = 3 * k - 2 * j; if (m != 0) { arb_mul_2exp_si(d + j, d + j, -1); if (j >= 1) arb_addmul(d + j, d + j - 1, u, prec); arb_div_ui(d + j, d + j, 2 * m, prec); if (j >= 2) arb_submul_ui(d + j, d + j - 2, m + 1, prec); } } if (k % 2 == 0) { j = (3 * k) / 2; arb_zero(d + j); arb_set_ui(u, 2); for (r = j - 1; r >= 0; r--) { if ((j - r) % 2 == 0) arb_submul(d + j, d + r, u, prec); else arb_addmul(d + j, d + r, u, prec); arb_mul_ui(u, u, 4 * j - 4 * r + 2, prec); } } arb_zero(d + (3 * k) / 2 + 1); arb_clear(u); } flint-3.1.3/src/acb_dirichlet/zeta_rs_f_coeffs.c000066400000000000000000000037461461254215100216550ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" #include "acb_dirichlet.h" void acb_dirichlet_zeta_rs_f_coeffs(acb_ptr c, const arb_t p, slong N, slong prec) { arb_ptr R, I, T, X; slong i, len; R = _arb_vec_init(N); I = _arb_vec_init(N); T = _arb_vec_init(N); X = _arb_vec_init(2); arb_set(X, p); arb_one(X + 1); /* I, R = sin,cos(pi*(X^2/2 + 3/8)) */ len = FLINT_MIN(N, 3); _arb_poly_mullow(T, X, 2, X, 2, len, prec); _arb_vec_scalar_mul_2exp_si(T, T, len, -1); arb_set_d(R, 0.375); arb_add(T, T, R, prec); _arb_poly_sin_cos_pi_series(I, R, T, len, N, prec); /* I -= cos(pi*x/2) * sqrt(2) */ _arb_vec_scalar_mul_2exp_si(X, X, 2, -1); _arb_poly_cos_pi_series(T, X, 2, N, prec); arb_sqrt_ui((arb_ptr) c, 2, prec); _arb_vec_scalar_mul(T, T, N, (arb_ptr) c, prec); _arb_vec_sub(I, I, T, N, prec); _arb_vec_scalar_mul_2exp_si(X, X, 2, 1); /* T = 1 / (2 cos(pi*x)) */ _arb_poly_cos_pi_series(T, X, 2, N, prec); _arb_vec_scalar_mul_2exp_si(T, T, N, 1); _arb_poly_inv_series((arb_ptr) c, T, N, N, prec); _arb_vec_swap(T, (arb_ptr) c, N); /* R, I *= T */ _arb_poly_mullow((arb_ptr) c, R, N, T, N, N, prec); _arb_vec_swap(R, (arb_ptr) c, N); _arb_poly_mullow((arb_ptr) c, I, N, T, N, N, prec); _arb_vec_swap(I, (arb_ptr) c, N); for (i = 0; i < N; i++) { arb_swap(acb_realref(c + i), R + i); arb_swap(acb_imagref(c + i), I + i); } _acb_poly_inv_borel_transform(c, c, N, prec); _arb_vec_clear(R, N); _arb_vec_clear(I, N); _arb_vec_clear(T, N); _arb_vec_clear(X, 2); } flint-3.1.3/src/acb_dirichlet/zeta_rs_r.c000066400000000000000000000141331461254215100203340ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif void acb_dirichlet_zeta_rs_r(acb_t res, const acb_t s, slong K, slong prec) { arb_ptr dk, pipow; acb_ptr Fp; arb_t a, p, api2, api2pow; acb_t U, S, u, v; fmpz_t N; mag_t err; slong j, k, wp, K_limit; /* determinate K automatically */ if (K <= 0) { double sigma, t, log2err, best_log2err; slong best_K; sigma = arf_get_d(arb_midref(acb_realref(s)), ARF_RND_DOWN); t = arf_get_d(arb_midref(acb_imagref(s)), ARF_RND_DOWN); if (!(sigma > -1e6 && sigma < 1e6) || !(t > 1 && t < 1e40)) { acb_indeterminate(res); return; } best_K = 1; best_log2err = 1e300; /* todo: also break if too slow rate of decay? */ K_limit = 10 + prec * 0.25; K_limit += pow(t, 0.2); /* possibly useful for off-strip evaluation */ for (K = 1; K < K_limit; K++) { if (sigma < 0 && K + sigma < 3) continue; /* Asymptotic approximation of the error term */ log2err = 2.7889996532222537064 - 0.12022458674074695061 / K + 0.2419040680416126037 * K + 0.7213475204444817037 * K * log(K) + (-0.7213475204444817037 - 0.7213475204444817037 * K) * log(t); if (sigma >= 0.0) log2err += -2.8073549220576041074 + 1.5 * sigma; if (log2err < best_log2err) { best_log2err = log2err; best_K = K; } if (log2err < -prec) break; } K = best_K; } mag_init(err); acb_dirichlet_zeta_rs_bound(err, s, K); if (!mag_is_finite(err)) { acb_indeterminate(res); mag_clear(err); return; } arb_init(a); arb_init(p); arb_init(api2); arb_init(api2pow); acb_init(U); acb_init(S); acb_init(u); acb_init(v); fmpz_init(N); dk = _arb_vec_init((3 * K) / 2 + 2); Fp = _acb_vec_init(3 * K + 1); pipow = _arb_vec_init((3 * K) / 2 + 2); for (wp = 2 * prec; ; wp *= 2) { /* a = sqrt(t / (2pi)) */ arb_const_pi(a, wp); arb_mul_2exp_si(a, a, 1); arb_div(a, acb_imagref(s), a, wp); arb_sqrt(a, a, wp); /* N = floor(a) */ arb_floor(p, a, wp); if (!arb_get_unique_fmpz(N, p)) { if (wp > 4 * prec && wp > arb_rel_accuracy_bits(acb_imagref(s))) { acb_indeterminate(res); goto cleanup; } continue; } /* p = 1 + 2(N-a) */ arb_sub_fmpz(p, a, N, wp); arb_neg(p, p); arb_mul_2exp_si(p, p, 1); arb_add_ui(p, p, 1, wp); acb_dirichlet_zeta_rs_f_coeffs(Fp, p, 3 * K + 1, wp); if (acb_rel_accuracy_bits(Fp + 3 * K) >= prec) break; if (wp > 4 * prec && wp > arb_rel_accuracy_bits(acb_imagref(s))) break; } if (!fmpz_fits_si(N)) { acb_indeterminate(res); goto cleanup; } wp = prec + 10 + 3 * fmpz_bits(N); /* xxx */ wp = FLINT_MAX(wp, prec + 10); wp = wp + FLINT_BIT_COUNT(K); acb_zero(S); arb_const_pi(api2, wp); _arb_vec_set_powers(pipow, api2, (3 * K) / 2 + 2, wp); arb_mul(api2, api2, api2, wp); arb_mul(api2, api2, a, wp); arb_inv(api2, api2, wp); arb_one(api2pow); for (k = 0; k <= K; k++) { acb_dirichlet_zeta_rs_d_coeffs(dk, acb_realref(s), k, wp); acb_zero(u); for (j = 0; j <= (3 * k) / 2; j++) { /* (pi/(2i))^j d^(k)_j F^(3k-2j)(p) */ arb_mul(acb_realref(v), pipow + j, dk + j, wp); arb_mul_2exp_si(acb_realref(v), acb_realref(v), -j); arb_zero(acb_imagref(v)); if (j % 4 == 1) acb_div_onei(v, v); else if (j % 4 == 2) acb_neg(v, v); else if (j % 4 == 3) acb_mul_onei(v, v); acb_addmul(u, v, Fp + 3 * k - 2 * j, wp); } acb_addmul_arb(S, u, api2pow, wp); arb_mul(api2pow, api2pow, api2, wp); } acb_add_error_mag(S, err); /* U = exp(-i[(t/2) log(t/(2pi)) - t/2 - pi/8]) */ arb_log(acb_realref(u), a, wp); arb_mul_2exp_si(acb_realref(u), acb_realref(u), 1); arb_sub_ui(acb_realref(u), acb_realref(u), 1, wp); arb_mul(acb_realref(u), acb_realref(u), acb_imagref(s), wp); arb_mul_2exp_si(acb_realref(u), acb_realref(u), -1); arb_const_pi(acb_imagref(u), wp); arb_mul_2exp_si(acb_imagref(u), acb_imagref(u), -3); arb_sub(acb_realref(u), acb_realref(u), acb_imagref(u), wp); arb_neg(acb_realref(u), acb_realref(u)); arb_sin_cos(acb_imagref(U), acb_realref(U), acb_realref(u), wp); /* S = (-1)^(N-1) * U * a^(-sigma) * S */ acb_mul(S, S, U, wp); arb_neg(acb_realref(u), acb_realref(s)); arb_pow(acb_realref(u), a, acb_realref(u), wp); acb_mul_arb(S, S, acb_realref(u), wp); if (fmpz_is_even(N)) acb_neg(S, S); if (_acb_vec_estimate_allocated_bytes(fmpz_get_ui(N) / 6, wp) < 4e9) acb_dirichlet_powsum_sieved(u, s, fmpz_get_ui(N), 1, wp); else acb_dirichlet_powsum_smooth(u, s, fmpz_get_ui(N), 1, wp); acb_add(S, S, u, wp); acb_set(res, S); /* don't set_round here; the extra precision is useful */ cleanup: _arb_vec_clear(dk, (3 * K) / 2 + 2); _acb_vec_clear(Fp, 3 * K + 1); _arb_vec_clear(pipow, (3 * K) / 2 + 2); arb_clear(a); arb_clear(p); arb_clear(api2); arb_clear(api2pow); acb_clear(U); acb_clear(S); acb_clear(u); acb_clear(v); fmpz_clear(N); mag_clear(err); } flint-3.1.3/src/acb_dirichlet/zeta_zeros.c000066400000000000000000000020111461254215100205210ustar00rootroot00000000000000/* Copyright (C) 2010 Juan Arias de Reyna Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" void acb_dirichlet_zeta_zeros(acb_ptr res, const fmpz_t n, slong len, slong prec) { if (len <= 0) { return; } else if (fmpz_sgn(n) < 1) { flint_throw(FLINT_ERROR, "nonpositive indices of zeta zeros are not supported\n"); } else { slong i; arb_ptr p; p = _arb_vec_init(len); acb_dirichlet_hardy_z_zeros(p, n, len, prec); for (i = 0; i < len; i++) { acb_set_d(res + i, 0.5); arb_set(acb_imagref(res + i), p + i); } _arb_vec_clear(p, len); } } flint-3.1.3/src/acb_elliptic.h000066400000000000000000000053321461254215100162100ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_ELLIPTIC_H #define ACB_ELLIPTIC_H #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif void acb_elliptic_k(acb_t k, const acb_t m, slong prec); void acb_elliptic_k_jet(acb_ptr w, const acb_t m, slong len, slong prec); void _acb_elliptic_k_series(acb_ptr res, acb_srcptr m, slong zlen, slong len, slong prec); void acb_elliptic_k_series(acb_poly_t res, const acb_poly_t m, slong len, slong prec); void acb_elliptic_e(acb_t res, const acb_t m, slong prec); void acb_elliptic_rf(acb_t res, const acb_t x, const acb_t y, const acb_t z, int flags, slong prec); void acb_elliptic_rj(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec); void acb_elliptic_rj_carlson(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec); void acb_elliptic_rj_integration(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec); void acb_elliptic_rg(acb_t res, const acb_t x, const acb_t y, const acb_t z, int flags, slong prec); void acb_elliptic_rc1(acb_t res, const acb_t x, slong prec); void acb_elliptic_f(acb_t res, const acb_t phi, const acb_t m, int times_pi, slong prec); void acb_elliptic_e_inc(acb_t res, const acb_t phi, const acb_t m, int times_pi, slong prec); void acb_elliptic_pi(acb_t r, const acb_t n, const acb_t m, slong prec); void acb_elliptic_pi_inc(acb_t res, const acb_t n, const acb_t phi, const acb_t m, int times_pi, slong prec); void acb_elliptic_p(acb_t r, const acb_t z, const acb_t tau, slong prec); void acb_elliptic_p_prime(acb_t r, const acb_t z, const acb_t tau, slong prec); void acb_elliptic_p_jet(acb_ptr r, const acb_t z, const acb_t tau, slong len, slong prec); void _acb_elliptic_p_series(acb_ptr res, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec); void acb_elliptic_p_series(acb_poly_t res, const acb_poly_t z, const acb_t tau, slong len, slong prec); void acb_elliptic_zeta(acb_t res, const acb_t z, const acb_t tau, slong prec); void acb_elliptic_sigma(acb_t res, const acb_t z, const acb_t tau, slong prec); void acb_elliptic_roots(acb_t e1, acb_t e2, acb_t e3, const acb_t tau, slong prec); void acb_elliptic_invariants(acb_t g2, acb_t g3, const acb_t tau, slong prec); void acb_elliptic_inv_p(acb_t res, const acb_t z, const acb_t tau, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_elliptic/000077500000000000000000000000001461254215100160345ustar00rootroot00000000000000flint-3.1.3/src/acb_elliptic/e.c000066400000000000000000000020631461254215100164250ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" void acb_elliptic_e(acb_t res, const acb_t m, slong prec) { if (acb_is_zero(m)) { acb_const_pi(res, prec); acb_mul_2exp_si(res, res, -1); } else if (acb_is_one(m)) { acb_one(res); } else { acb_struct t[2]; acb_init(t + 0); acb_init(t + 1); acb_elliptic_k_jet(t, m, 2, prec); acb_mul(t + 1, t + 1, m, prec); acb_mul_2exp_si(t + 1, t + 1, 1); acb_add(t, t, t + 1, prec); acb_sub_ui(t + 1, m, 1, prec); acb_mul(res, t, t + 1, prec); acb_neg(res, res); acb_clear(t + 0); acb_clear(t + 1); } } flint-3.1.3/src/acb_elliptic/e_inc.c000066400000000000000000000125261461254215100172630ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" /* Evaluation on -pi/2 <= re(z) <= pi/2, no aliasing. */ /* s*(RF(x,y,1) - m*s^2*RD(x,y,1)/3), x = c^2, y=1-m*s^2 */ void acb_elliptic_e_reduced(acb_t r, const acb_t z, const acb_t m, int times_pi, slong prec) { acb_t s, c, x, y, rf, rd; acb_init(s); acb_init(c); acb_init(x); acb_init(y); acb_init(rf); acb_init(rd); if (times_pi) acb_sin_cos_pi(s, c, z, prec); else acb_sin_cos(s, c, z, prec); acb_mul(x, c, c, prec); acb_mul(y, s, s, prec); acb_mul(y, y, m, prec); acb_sub_ui(y, y, 1, prec); acb_neg(y, y); acb_one(rf); acb_one(rd); acb_elliptic_rf(rf, x, y, rf, 0, prec); acb_elliptic_rj(rd, x, y, rd, rd, 0, prec); acb_mul(y, s, s, prec); acb_mul(y, y, m, prec); acb_mul(rd, rd, y, prec); acb_div_ui(rd, rd, 3, prec); acb_sub(r, rf, rd, prec); acb_mul(r, r, s, prec); acb_clear(s); acb_clear(c); acb_clear(x); acb_clear(y); acb_clear(rf); acb_clear(rd); } void acb_elliptic_e_inc(acb_t res, const acb_t phi, const acb_t m, int times_pi, slong prec) { arb_t x, d, pi; acb_t z, w, r; if (!acb_is_finite(phi) || !acb_is_finite(m)) { acb_indeterminate(res); return; } if (acb_is_zero(m)) { if (times_pi) { arb_init(pi); arb_const_pi(pi, prec); acb_mul_arb(res, phi, pi, prec); arb_clear(pi); } else { acb_set_round(res, phi, prec); } return; } if (acb_is_zero(phi)) { acb_zero(res); return; } if (times_pi && acb_is_int_2exp_si(phi, -1)) { acb_t t; acb_init(t); acb_mul_2exp_si(t, phi, 1); acb_elliptic_e(res, m, prec); acb_mul(res, res, t, prec); acb_clear(t); return; } arb_init(x); arb_init(d); arb_init(pi); acb_init(z); acb_init(w); acb_init(r); arb_set(x, acb_realref(phi)); arb_const_pi(pi, prec); if (times_pi) arb_set(d, x); else arb_div(d, x, pi, prec); arb_mul_2exp_si(d, d, 1); arb_add_ui(d, d, 1, prec); arb_mul_2exp_si(d, d, -1); if (mag_cmp_2exp_si(arb_radref(d), -1) >= 0) { /* may span multiple periods... don't bother */ acb_indeterminate(res); } else if (arb_contains_int(d) && !arb_is_exact(d)) /* two adjacent d */ { acb_t r2, w2; int is_real; acb_init(r2); acb_init(w2); arb_sub_ui(x, acb_realref(m), 1, prec); is_real = acb_is_real(phi) && acb_is_real(m) && arb_is_negative(x); /* left d */ acb_zero(z); arf_set_mag(arb_midref(acb_realref(z)), arb_radref(d)); mag_zero(arb_radref(d)); arb_sub(d, d, acb_realref(z), 2 * prec + 100); /* meant to be exact */ arb_floor(d, d, prec); /* w = 2 E(m) */ acb_elliptic_e(w, m, prec); acb_mul_2exp_si(w, w, 1); /* z = phi - d * pi */ if (times_pi) { acb_sub_arb(z, phi, d, prec); } else { arb_mul(acb_realref(z), pi, d, prec); arb_sub(acb_realref(z), acb_realref(phi), acb_realref(z), prec); arb_set(acb_imagref(z), acb_imagref(phi)); } acb_elliptic_e_reduced(r, z, m, times_pi, prec); acb_addmul_arb(r, w, d, prec); /* z = phi - (d + 1) * pi */ if (times_pi) acb_sub_ui(z, z, 1, prec); else acb_sub_arb(z, z, pi, prec); acb_elliptic_e_reduced(r2, z, m, times_pi, prec); arb_add_ui(d, d, 1, prec); acb_addmul_arb(r2, w, d, prec); arb_union(acb_realref(res), acb_realref(r), acb_realref(r2), prec); arb_union(acb_imagref(res), acb_imagref(r), acb_imagref(r2), prec); if (is_real) arb_zero(acb_imagref(res)); acb_clear(r2); acb_clear(w2); } else { /* this could still be inexact if d is large (which is fine) */ arb_floor(d, d, prec); if (arb_is_zero(d)) { acb_set(z, phi); acb_zero(w); } else { /* z = phi - d*pi */ if (times_pi) { acb_sub_arb(z, phi, d, prec); } else { arb_mul(acb_realref(z), pi, d, prec); arb_sub(acb_realref(z), acb_realref(phi), acb_realref(z), prec); arb_set(acb_imagref(z), acb_imagref(phi)); } /* w = 2 d E(m) */ acb_elliptic_e(w, m, prec); acb_mul_arb(w, w, d, prec); acb_mul_2exp_si(w, w, 1); } acb_elliptic_e_reduced(r, z, m, times_pi, prec); acb_add(r, r, w, prec); acb_set(res, r); } arb_clear(x); arb_clear(d); arb_clear(pi); acb_clear(z); acb_clear(w); acb_clear(r); } flint-3.1.3/src/acb_elliptic/f.c000066400000000000000000000117371461254215100164360ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" /* Evaluation on -pi/2 <= re(z) <= pi/2, no aliasing. */ /* s*RF(c^2, 1-m*s^2, 1) */ void acb_elliptic_f_reduced(acb_t r, const acb_t z, const acb_t m, int times_pi, slong prec) { acb_t s, c, a; acb_init(s); acb_init(c); acb_init(a); if (times_pi) acb_sin_cos_pi(s, c, z, prec); else acb_sin_cos(s, c, z, prec); acb_mul(c, c, c, prec); acb_mul(r, s, s, prec); acb_mul(r, r, m, prec); acb_sub_ui(r, r, 1, prec); acb_neg(r, r); acb_one(a); acb_elliptic_rf(r, c, r, a, 0, prec); acb_mul(r, r, s, prec); acb_clear(s); acb_clear(c); acb_clear(a); } void acb_elliptic_f(acb_t res, const acb_t phi, const acb_t m, int times_pi, slong prec) { arb_t x, d, pi; acb_t z, w, r; if (!acb_is_finite(phi) || !acb_is_finite(m)) { acb_indeterminate(res); return; } if (acb_is_zero(m)) { if (times_pi) { arb_init(pi); arb_const_pi(pi, prec); acb_mul_arb(res, phi, pi, prec); arb_clear(pi); } else { acb_set_round(res, phi, prec); } return; } if (acb_is_zero(phi)) { acb_zero(res); return; } if (times_pi && acb_is_int_2exp_si(phi, -1)) { acb_t t; acb_init(t); acb_mul_2exp_si(t, phi, 1); acb_elliptic_k(res, m, prec); acb_mul(res, res, t, prec); acb_clear(t); return; } arb_init(x); arb_init(d); arb_init(pi); acb_init(z); acb_init(w); acb_init(r); arb_set(x, acb_realref(phi)); arb_const_pi(pi, prec); if (times_pi) arb_set(d, x); else arb_div(d, x, pi, prec); arb_mul_2exp_si(d, d, 1); arb_add_ui(d, d, 1, prec); arb_mul_2exp_si(d, d, -1); if (mag_cmp_2exp_si(arb_radref(d), -1) >= 0) { /* may span multiple periods... don't bother */ acb_indeterminate(res); } else if (arb_contains_int(d) && !arb_is_exact(d)) /* two adjacent d */ { acb_t r2, w2; int is_real; acb_init(r2); acb_init(w2); arb_sub_ui(x, acb_realref(m), 1, prec); is_real = acb_is_real(phi) && acb_is_real(m) && arb_is_negative(x); /* left d */ acb_zero(z); arf_set_mag(arb_midref(acb_realref(z)), arb_radref(d)); mag_zero(arb_radref(d)); arb_sub(d, d, acb_realref(z), 2 * prec + 100); /* meant to be exact */ arb_floor(d, d, prec); /* w = 2 K(m) */ acb_elliptic_k(w, m, prec); acb_mul_2exp_si(w, w, 1); /* z = phi - d * pi */ if (times_pi) { acb_sub_arb(z, phi, d, prec); } else { arb_mul(acb_realref(z), pi, d, prec); arb_sub(acb_realref(z), acb_realref(phi), acb_realref(z), prec); arb_set(acb_imagref(z), acb_imagref(phi)); } acb_elliptic_f_reduced(r, z, m, times_pi, prec); acb_addmul_arb(r, w, d, prec); /* z = phi - (d + 1) * pi */ if (times_pi) acb_sub_ui(z, z, 1, prec); else acb_sub_arb(z, z, pi, prec); acb_elliptic_f_reduced(r2, z, m, times_pi, prec); arb_add_ui(d, d, 1, prec); acb_addmul_arb(r2, w, d, prec); arb_union(acb_realref(res), acb_realref(r), acb_realref(r2), prec); arb_union(acb_imagref(res), acb_imagref(r), acb_imagref(r2), prec); if (is_real) arb_zero(acb_imagref(res)); acb_clear(r2); acb_clear(w2); } else { /* this could still be inexact if d is large (which is fine) */ arb_floor(d, d, prec); if (arb_is_zero(d)) { acb_set(z, phi); acb_zero(w); } else { /* z = phi - d*pi */ if (times_pi) { acb_sub_arb(z, phi, d, prec); } else { arb_mul(acb_realref(z), pi, d, prec); arb_sub(acb_realref(z), acb_realref(phi), acb_realref(z), prec); arb_set(acb_imagref(z), acb_imagref(phi)); } /* w = 2 d K(m) */ acb_elliptic_k(w, m, prec); acb_mul_arb(w, w, d, prec); acb_mul_2exp_si(w, w, 1); } acb_elliptic_f_reduced(r, z, m, times_pi, prec); acb_add(r, r, w, prec); acb_set(res, r); } arb_clear(x); arb_clear(d); arb_clear(pi); acb_clear(z); acb_clear(w); acb_clear(r); } flint-3.1.3/src/acb_elliptic/inv_p.c000066400000000000000000000015001461254215100173070ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" void acb_elliptic_inv_p(acb_t res, const acb_t z, const acb_t tau, slong prec) { acb_t e1, e2, e3; acb_init(e1); acb_init(e2); acb_init(e3); acb_elliptic_roots(e1, e2, e3, tau, prec); acb_sub(e1, z, e1, prec); acb_sub(e2, z, e2, prec); acb_sub(e3, z, e3, prec); acb_elliptic_rf(res, e1, e2, e3, 0, prec); acb_clear(e1); acb_clear(e2); acb_clear(e3); } flint-3.1.3/src/acb_elliptic/invariants.c000066400000000000000000000013611461254215100203570ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" void acb_elliptic_invariants(acb_t g2, acb_t g3, const acb_t tau, slong prec) { acb_struct t[2]; acb_init(t); acb_init(t + 1); acb_modular_eisenstein(t, tau, 2, prec); acb_mul_ui(g2, t, 60, prec); acb_mul_ui(g3, t + 1, 140, prec); acb_clear(t); acb_clear(t + 1); } flint-3.1.3/src/acb_elliptic/k.c000066400000000000000000000013231461254215100164310ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" void acb_elliptic_k(acb_t k, const acb_t m, slong prec) { acb_t t; acb_init(t); acb_sub_ui(t, m, 1, prec); acb_neg(t, t); acb_sqrt(t, t, prec); acb_agm1(k, t, prec); acb_const_pi(t, prec); acb_div(k, t, k, prec); acb_mul_2exp_si(k, k, -1); acb_clear(t); } flint-3.1.3/src/acb_elliptic/k_jet.c000066400000000000000000000041051461254215100172740ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" void acb_elliptic_k_jet(acb_ptr w, const acb_t m, slong len, slong prec) { acb_t t, u, msub1m, m2sub1; slong k, n; if (len < 1) return; if (len == 1) { acb_elliptic_k(w, m, prec); return; } if (acb_is_zero(m)) { acb_const_pi(w, prec); acb_mul_2exp_si(w, w, -1); for (k = 1; k < len; k++) { acb_mul_ui(w + k, w + k - 1, (2 * k - 1) * (2 * k - 1), prec); acb_div_ui(w + k, w + k, 4 * k * k, prec); } return; } acb_init(t); acb_init(u); acb_init(msub1m); acb_init(m2sub1); acb_sub_ui(msub1m, m, 1, prec); acb_neg(t, msub1m); acb_sqrt(t, t, prec); acb_mul(msub1m, msub1m, m, prec); acb_mul_2exp_si(m2sub1, m, 1); acb_sub_ui(m2sub1, m2sub1, 1, prec); acb_agm1_cpx(w, t, 2, prec); /* pi M'(t) / (4 t M(t)^2) */ acb_mul(u, w, w, prec); acb_mul(t, t, u, prec); acb_div(w + 1, w + 1, t, prec); acb_const_pi(u, prec); acb_mul(w + 1, w + 1, u, prec); acb_mul_2exp_si(w + 1, w + 1, -2); /* pi / (2 M(t)) */ acb_const_pi(u, prec); acb_div(w, u, w, prec); acb_mul_2exp_si(w, w, -1); acb_inv(t, msub1m, prec); for (k = 2; k < len; k++) { n = k - 2; acb_mul_ui(w + k, w + n, (2 * n + 1) * (2 * n + 1), prec); acb_mul(u, w + n + 1, m2sub1, prec); acb_addmul_ui(w + k, u, (n + 1) * (n + 1) * 4, prec); acb_mul(w + k, w + k, t, prec); acb_div_ui(w + k, w + k, 4 * (n + 1) * (n + 2), prec); acb_neg(w + k, w + k); } acb_clear(t); acb_clear(u); acb_clear(msub1m); acb_clear(m2sub1); } flint-3.1.3/src/acb_elliptic/k_series.c000066400000000000000000000026031461254215100200050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_elliptic.h" void _acb_elliptic_k_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) { acb_ptr t, u; zlen = FLINT_MIN(zlen, len); t = _acb_vec_init(len); u = _acb_vec_init(len); acb_elliptic_k_jet(t, z, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, z + 1, zlen - 1); _acb_poly_compose_series(res, t, len, u, zlen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void acb_elliptic_k_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec) { if (n == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, n); if (z->length == 0) { acb_t t; acb_init(t); _acb_elliptic_k_series(res->coeffs, t, 1, n, prec); acb_clear(t); } else { _acb_elliptic_k_series(res->coeffs, z->coeffs, z->length, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_elliptic/p.c000066400000000000000000000030051461254215100164350ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" void acb_elliptic_p(acb_t r, const acb_t z, const acb_t tau, slong prec) { acb_struct t0[4], tz[4]; acb_t t; int i, real; real = acb_is_real(z) && arb_is_int_2exp_si(acb_realref(tau), -1) && arb_is_positive(acb_imagref(tau)); acb_init(t); for (i = 0; i < 4; i++) { acb_init(t0 + i); acb_init(tz + i); } acb_modular_theta(tz + 0, tz + 1, tz + 2, tz + 3, z, tau, prec); acb_zero(t); acb_modular_theta(t0 + 0, t0 + 1, t0 + 2, t0 + 3, t, tau, prec); acb_mul(t, t0 + 1, t0 + 2, prec); acb_mul(t, t, tz + 3, prec); acb_div(t, t, tz + 0, prec); acb_mul(t, t, t, prec); acb_pow_ui(t0 + 1, t0 + 1, 4, prec); acb_pow_ui(t0 + 2, t0 + 2, 4, prec); acb_add(r, t0 + 1, t0 + 2, prec); acb_div_ui(r, r, 3, prec); acb_sub(r, t, r, prec); acb_const_pi(t, prec); acb_mul(t, t, t, prec); acb_mul(r, r, t, prec); if (real) arb_zero(acb_imagref(r)); acb_clear(t); for (i = 0; i < 4; i++) { acb_clear(t0 + i); acb_clear(tz + i); } } flint-3.1.3/src/acb_elliptic/p_jet.c000066400000000000000000000042621461254215100173050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_elliptic.h" #include "acb_modular.h" #include "acb_poly.h" void acb_elliptic_p_jet(acb_ptr r, const acb_t z, const acb_t tau, slong len, slong prec) { acb_t t01, t02, t03, t04; acb_ptr tz1, tz2, tz3, tz4; acb_t t; int real; slong k; if (len < 1) return; if (len == 1) { acb_elliptic_p(r, z, tau, prec); return; } real = acb_is_real(z) && arb_is_int_2exp_si(acb_realref(tau), -1) && arb_is_positive(acb_imagref(tau)); acb_init(t); acb_init(t01); acb_init(t02); acb_init(t03); acb_init(t04); tz1 = _acb_vec_init(len); tz2 = _acb_vec_init(len); tz3 = _acb_vec_init(len); tz4 = _acb_vec_init(len); acb_modular_theta_jet(tz1, tz2, tz3, tz4, z, tau, len, prec); /* [theta_4(z) / theta_1(z)]^2 */ _acb_poly_div_series(tz2, tz4, len, tz1, len, len, prec); _acb_poly_mullow(tz1, tz2, len, tz2, len, len, prec); acb_zero(t); acb_modular_theta(t01, t02, t03, t04, t, tau, prec); /* [theta_2(0) * theta_3(0)] ^2 */ acb_mul(t, t02, t03, prec); acb_mul(t, t, t, prec); _acb_vec_scalar_mul(tz1, tz1, len, t, prec); /* - [theta_2(0)^4 + theta_3(0)^4] / 3 */ acb_pow_ui(t02, t02, 4, prec); acb_pow_ui(t03, t03, 4, prec); acb_add(t, t02, t03, prec); acb_div_ui(t, t, 3, prec); acb_sub(tz1, tz1, t, prec); /* times pi^2 */ acb_const_pi(t, prec); acb_mul(t, t, t, prec); _acb_vec_scalar_mul(r, tz1, len, t, prec); if (real) { for (k = 0; k < len; k++) arb_zero(acb_imagref(r + k)); } acb_clear(t); acb_clear(t01); acb_clear(t02); acb_clear(t03); acb_clear(t04); _acb_vec_clear(tz1, len); _acb_vec_clear(tz2, len); _acb_vec_clear(tz3, len); _acb_vec_clear(tz4, len); } flint-3.1.3/src/acb_elliptic/p_prime.c000066400000000000000000000027301461254215100176350ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" void acb_elliptic_p_prime(acb_t r, const acb_t z, const acb_t tau, slong prec) { acb_struct tz[4]; acb_t t1, t2, t3; int i, real; real = acb_is_real(z) && arb_is_int_2exp_si(acb_realref(tau), -1) && arb_is_positive(acb_imagref(tau)); acb_init(t1); acb_init(t2); acb_init(t3); for (i = 0; i < 4; i++) acb_init(tz + i); acb_modular_theta(tz + 0, tz + 1, tz + 2, tz + 3, z, tau, prec); /* (-2*pi*eta^2/theta1)^3*theta2*theta3*theta4 */ acb_const_pi(t2, prec); acb_mul_2exp_si(t2, t2, 1); acb_neg(t2, t2); acb_modular_eta(t3, tau, prec); acb_mul(t1, t3, t3, prec); acb_mul(t3, t1, t2, prec); acb_div(t1, t3, tz + 0, prec); acb_mul(t2, t1, t1, prec); acb_mul(t3, t1, t2, prec); acb_mul(t1, tz + 1, tz + 2, prec); acb_mul(t2, t1, tz + 3, prec); acb_mul(r, t3, t2, prec); if (real) arb_zero(acb_imagref(r)); acb_clear(t1); acb_clear(t2); acb_clear(t3); for (i = 0; i < 4; i++) acb_clear(tz + i); } flint-3.1.3/src/acb_elliptic/p_series.c000066400000000000000000000026641461254215100200210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_elliptic.h" void _acb_elliptic_p_series(acb_ptr res, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec) { acb_ptr t, u; zlen = FLINT_MIN(zlen, len); t = _acb_vec_init(len); u = _acb_vec_init(len); acb_elliptic_p_jet(t, z, tau, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, z + 1, zlen - 1); _acb_poly_compose_series(res, t, len, u, zlen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void acb_elliptic_p_series(acb_poly_t res, const acb_poly_t z, const acb_t tau, slong n, slong prec) { if (n == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, n); if (z->length == 0) { acb_t t; acb_init(t); _acb_elliptic_p_series(res->coeffs, t, 1, tau, n, prec); acb_clear(t); } else { _acb_elliptic_p_series(res->coeffs, z->coeffs, z->length, tau, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_elliptic/pi.c000066400000000000000000000151441461254215100166150ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" /* Evaluation on -pi/2 <= re(z) <= pi/2, no aliasing. */ /* s*(RF(x,y,1) + n*s^2*RJ(x,y,1,p)/3), x = c^2, y=1-m*s^2, p=1-n*s^2 */ /* complete: c = 0, s = 1 */ void acb_elliptic_pi_reduced(acb_t r, const acb_t n, const acb_t z, const acb_t m, int times_pi, slong prec) { acb_t s, c, x, y, p, rf, rj; acb_init(s); acb_init(c); acb_init(x); acb_init(y); acb_init(p); acb_init(rf); acb_init(rj); if (times_pi) acb_sin_cos_pi(s, c, z, prec); else acb_sin_cos(s, c, z, prec); acb_mul(x, c, c, prec); acb_mul(y, s, s, prec); acb_mul(p, y, n, prec); acb_mul(y, y, m, prec); acb_sub_ui(y, y, 1, prec); acb_neg(y, y); acb_sub_ui(p, p, 1, prec); acb_neg(p, p); acb_one(rf); acb_one(rj); acb_elliptic_rf(rf, x, y, rf, 0, prec); acb_elliptic_rj(rj, x, y, rj, p, 0, prec); acb_mul(y, s, s, prec); acb_mul(y, y, n, prec); acb_mul(rj, rj, y, prec); acb_div_ui(rj, rj, 3, prec); acb_add(r, rf, rj, prec); acb_mul(r, r, s, prec); acb_clear(s); acb_clear(c); acb_clear(x); acb_clear(y); acb_clear(p); acb_clear(rf); acb_clear(rj); } void acb_elliptic_pi(acb_t r, const acb_t n, const acb_t m, slong prec) { if (acb_is_zero(n)) { acb_elliptic_k(r, m, prec); } else if (acb_is_zero(m)) { arb_t pi; arb_init(pi); arb_const_pi(pi, prec); acb_sub_ui(r, n, 1, prec); acb_neg(r, r); acb_rsqrt(r, r, prec); acb_mul_arb(r, r, pi, prec); acb_mul_2exp_si(r, r, -1); arb_clear(pi); } else { acb_t z; acb_init(z); acb_one(z); acb_mul_2exp_si(z, z, -1); acb_elliptic_pi_reduced(r, n, z, m, 1, prec); acb_clear(z); } } void acb_elliptic_pi_inc(acb_t res, const acb_t n, const acb_t phi, const acb_t m, int times_pi, slong prec) { arb_t x, d, pi; acb_t z, w, r; if (!acb_is_finite(n) || !acb_is_finite(phi) || !acb_is_finite(m)) { acb_indeterminate(res); return; } if (acb_is_zero(n)) { acb_elliptic_f(res, phi, m, times_pi, prec); return; } if (acb_is_zero(phi) || (times_pi && acb_is_int_2exp_si(phi, -1))) { acb_t t; acb_init(t); acb_mul_2exp_si(t, phi, 1); acb_elliptic_pi(res, n, m, prec); acb_mul(res, res, t, prec); acb_clear(t); return; } /* Fixme: the exact argument reduction sometimes does not work when re(phi) = k/2 and we end up exactly on a branch cut, presumably due to getting the wrong sign in R_J? Should investigate and find a better solution. */ if (times_pi && !acb_is_real(phi)) { acb_init(z); arb_init(pi); arb_const_pi(pi, prec); acb_mul_arb(z, phi, pi, prec); acb_elliptic_pi_inc(res, n, z, m, 0, prec); acb_clear(z); arb_clear(pi); return; } arb_init(x); arb_init(d); arb_init(pi); acb_init(z); acb_init(w); acb_init(r); arb_set(x, acb_realref(phi)); arb_const_pi(pi, prec); if (times_pi) arb_set(d, x); else arb_div(d, x, pi, prec); arb_mul_2exp_si(d, d, 1); arb_add_ui(d, d, 1, prec); arb_mul_2exp_si(d, d, -1); if (mag_cmp_2exp_si(arb_radref(d), -1) >= 0) { /* may span multiple periods... don't bother */ acb_indeterminate(res); } else if (arb_contains_int(d) && !arb_is_exact(d)) /* two adjacent d */ { acb_t r2, w2; int is_real; acb_init(r2); acb_init(w2); is_real = acb_is_real(phi) && acb_is_real(m) && acb_is_real(n); arb_sub_ui(x, acb_realref(m), 1, prec); is_real = is_real && arb_is_negative(x); arb_sub_ui(x, acb_realref(n), 1, prec); is_real = is_real && arb_is_negative(x); /* left d */ acb_zero(z); arf_set_mag(arb_midref(acb_realref(z)), arb_radref(d)); mag_zero(arb_radref(d)); arb_sub(d, d, acb_realref(z), 2 * prec + 100); /* meant to be exact */ arb_floor(d, d, prec); /* w = 2 Pi(n, m) */ acb_elliptic_pi(w, n, m, prec); acb_mul_2exp_si(w, w, 1); /* z = phi - d * pi */ if (times_pi) { acb_sub_arb(z, phi, d, prec); } else { arb_mul(acb_realref(z), pi, d, prec); arb_sub(acb_realref(z), acb_realref(phi), acb_realref(z), prec); arb_set(acb_imagref(z), acb_imagref(phi)); } acb_elliptic_pi_reduced(r, n, z, m, times_pi, prec); acb_addmul_arb(r, w, d, prec); /* z = phi - (d + 1) * pi */ if (times_pi) acb_sub_ui(z, z, 1, prec); else acb_sub_arb(z, z, pi, prec); acb_elliptic_pi_reduced(r2, n, z, m, times_pi, prec); arb_add_ui(d, d, 1, prec); acb_addmul_arb(r2, w, d, prec); arb_union(acb_realref(res), acb_realref(r), acb_realref(r2), prec); arb_union(acb_imagref(res), acb_imagref(r), acb_imagref(r2), prec); if (is_real) arb_zero(acb_imagref(res)); acb_clear(r2); acb_clear(w2); } else { /* this could still be inexact if d is large (which is fine) */ arb_floor(d, d, prec); if (arb_is_zero(d)) { acb_set(z, phi); acb_zero(w); } else { /* z = phi - d*pi */ if (times_pi) { acb_sub_arb(z, phi, d, prec); } else { arb_mul(acb_realref(z), pi, d, prec); arb_sub(acb_realref(z), acb_realref(phi), acb_realref(z), prec); arb_set(acb_imagref(z), acb_imagref(phi)); } /* w = 2 d Pi(n, m) */ acb_elliptic_pi(w, n, m, prec); acb_mul_arb(w, w, d, prec); acb_mul_2exp_si(w, w, 1); } acb_elliptic_pi_reduced(r, n, z, m, times_pi, prec); acb_add(r, r, w, prec); acb_set(res, r); } arb_clear(x); arb_clear(d); arb_clear(pi); acb_clear(z); acb_clear(w); acb_clear(r); } flint-3.1.3/src/acb_elliptic/rc1.c000066400000000000000000000054471461254215100166770ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" /* Compute R_C(1,1+x) = atan(sqrt(x))/sqrt(x) = 2F1(1,1/2,3/2,-x) */ static void _acb_elliptic_rc1(acb_t res, const acb_t x, slong prec) { acb_t t; acb_init(t); acb_sqrt(t, x, prec + 2); acb_atan(res, t, prec + 2); acb_div(res, res, t, prec); acb_clear(t); } void acb_elliptic_rc1(acb_t res, const acb_t x, slong prec) { mag_t xm; mag_init(xm); acb_get_mag(xm, x); if (mag_cmp_2exp_si(xm, 0) < 0) { slong k, n; for (n = 1; n <= 6; n++) { if (mag_cmp_2exp_si(xm, -prec / n) < 0) break; } /* Use Taylor series: 1 - x/3 + x^2/5 - x^3/7 + x^4/9 + ... */ if (n <= 6) { const short coeffs[] = {3465, -1155, 693, -495, 385, -315}; acb_t s; acb_init(s); for (k = n - 1; k >= 0; k--) { acb_mul(s, s, x, prec); acb_add_si(s, s, coeffs[k], prec); } acb_div_si(s, s, coeffs[0], prec); mag_geom_series(xm, xm, n); if (acb_is_real(x)) arb_add_error_mag(acb_realref(s), xm); else acb_add_error_mag(s, xm); acb_set(res, s); acb_clear(s); } else if (acb_is_exact(x)) { _acb_elliptic_rc1(res, x, prec); } else { acb_t w; mag_t err, rad; acb_init(w); mag_init(err); mag_init(rad); /* On the unit disc, |f'(x)| <= 0.5 / |1+x| */ acb_add_ui(w, x, 1, MAG_BITS); acb_get_mag_lower(err, w); mag_one(rad); mag_mul_2exp_si(rad, rad, -1); mag_div(err, rad, err); mag_hypot(rad, arb_radref(acb_realref(x)), arb_radref(acb_imagref(x))); mag_mul(err, err, rad); acb_set(w, x); mag_zero(arb_radref(acb_realref(w))); mag_zero(arb_radref(acb_imagref(w))); _acb_elliptic_rc1(w, w, prec); if (acb_is_real(x)) arb_add_error_mag(acb_realref(w), err); else acb_add_error_mag(w, err); acb_set(res, w); acb_clear(w); mag_clear(err); mag_clear(rad); } } else { _acb_elliptic_rc1(res, x, prec); } mag_clear(xm); } flint-3.1.3/src/acb_elliptic/rf.c000066400000000000000000000214651461254215100166170ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif static const unsigned short den_ratio_tab[512] = { 1,1,10,7,12,11,26,1,136,19,2,23,20,1,58,31, 16,1,74,1,164,43,2,47,56,1,106,1,4,59,122,1, 32,67,2,71,292,1,2,79,24,83,2,1,356,1,2,1, 1552,1,202,103,4,107,218,1,904,1,2,1,44,1,10,127, 64,131,2,1,548,139,2,1,8,1,298,151,4,1,314,1, 16,163,2,167,52,1,346,1,8,179,362,1,4,1,2,191, 6176,1,394,199,4,1,2,1,8,211,2,1,4,1,2,223, 16,227,458,1,932,1,2,239,1928,1,2,1,4,251,2,1, 32896,1,2,263,4,1,538,271,8,1,554,1,1124,283,2,1, 272,1,586,1,4,1,2,1,8,307,2,311,1252,1,634,1, 32,1,2,1,4,331,2,1,2696,1,2,7,4,347,698,1, 5648,1,2,359,76,1,2,367,8,1,746,1,4,379,2,383, 64,1,778,1,4,1,794,1,3208,1,2,1,1636,1,2,1, 16,419,842,1,4,1,2,431,3464,1,2,439,4,443,2,1, 14368,1,2,1,1828,1,922,463,8,467,2,1,4,1,2,479, 16,1,2,487,4,491,2,1,8,499,2,503,4,1,1018,1, 256,1,2,1,2084,523,2,1,184,1,2,1,4,1,1082,1, 16,547,2,1,4,1,1114,1,8,563,2,1,2276,571,2,1, 18464,1,2,1,4,587,2,1,4744,1,2,599,2404,1,2,607, 16,1,1226,1,2468,619,2,1,40,1,2,631,4,1,2,1, 41024,643,2,647,4,1,1306,1,8,659,1322,1,4,1,2,1, 10768,1,1354,1,4,683,2,1,8,691,2,1,4,1,1402,1, 32,1,1418,1,4,1,2,719,8,1,2,727,12,1,1466,1, 16,739,2,743,4,1,2,751,8,1,1514,1,3044,1,2,2, 49216,1,1546,1,4,1,2,1,8,787,2,1,4,1,1594,1, 16,1,2,1,3236,811,2,1,8,1,1642,823,4,827,1658,1, 32,1,2,839,116,1,2,1,8,1,1706,1,3428,859,2,863, 16,1,2,1,4,1,1754,1,7048,883,2,887,4,1,2,1, 64,1,2,1,4,907,2,911,8,1,2,919,4,1,2,1, 14864,1,2,1,3748,1,1882,1,8,947,2,1,3812,1,2,1, 992,1,2,967,4,971,2,1,7816,1,2,983,4,1,2,991, 16,1,1994,1,4,1,2,1,8072,1,2026,1,4,1019,2042,1, }; void acb_elliptic_rf_taylor_sum(acb_t res, const acb_t E2, const acb_t E3, slong nterms, slong prec) { fmpz_t den, c, d, e; acb_ptr E2pow; arb_ptr E2powr; acb_t s; slong x, y, XMAX, YMAX, NMAX, N; int real; NMAX = nterms - 1; YMAX = NMAX / 3; XMAX = NMAX / 2; real = acb_is_real(E2) && acb_is_real(E3); fmpz_init(den); fmpz_init(c); fmpz_init(d); fmpz_init(e); acb_init(s); if (real) { E2powr = _arb_vec_init(XMAX + 1); E2pow = NULL; _arb_vec_set_powers(E2powr, acb_realref(E2), XMAX + 1, prec); } else { E2pow = _acb_vec_init(XMAX + 1); E2powr = NULL; _acb_vec_set_powers(E2pow, E2, XMAX + 1, prec); } /* Compute universal denominator. */ fmpz_one(den); for (N = 1; N <= NMAX; N++) fmpz_mul_ui(den, den, den_ratio_tab[N]); /* Compute initial coefficient rf(1/2,y) / y! */ fmpz_set(c, den); for (y = 0; y < YMAX; y++) { fmpz_mul_ui(c, c, 2 * y + 1); fmpz_divexact_ui(c, c, 2 * y + 2); } acb_zero(res); for (y = YMAX; y >= 0; y--) { acb_zero(s); if (y != YMAX) { fmpz_mul_ui(c, c, 2 * y + 2); fmpz_divexact_ui(c, c, 2 * y + 1); } fmpz_set(d, c); /* Use powers with respect to E2 */ for (x = 0; x <= XMAX; x++) { N = 2 * x + 3 * y; if (N <= NMAX) { fmpz_divexact_ui(e, d, 2 * N + 1); if (x % 2 == 1) fmpz_neg(e, e); if (x != 0 || y != 0) { if (real) arb_addmul_fmpz(acb_realref(s), E2powr + x, e, prec); else acb_addmul_fmpz(s, E2pow + x, e, prec); } fmpz_mul_ui(d, d, 2 * x + 2 * y + 1); fmpz_divexact_ui(d, d, 2 * x + 2); } } /* Horner with respect to E3 */ acb_mul(res, res, E3, prec); acb_add(res, res, s, prec); } acb_div_fmpz(res, res, den, prec); acb_add_ui(res, res, 1, prec); fmpz_clear(den); fmpz_clear(c); fmpz_clear(d); fmpz_clear(e); acb_clear(s); if (real) _arb_vec_clear(E2powr, XMAX + 1); else _acb_vec_clear(E2pow, XMAX + 1); } void acb_elliptic_rf(acb_t res, const acb_t x, const acb_t y, const acb_t z, int flags, slong prec) { acb_t xx, yy, zz, sx, sy, sz, t; acb_t X, Y, Z, E2, E3; mag_t err, err2, prev_err; slong k, wp, accx, accy, accz, order; if (!acb_is_finite(x) || !acb_is_finite(y) || !acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_contains_zero(x) + acb_contains_zero(y) + acb_contains_zero(z) > 1) { acb_indeterminate(res); return; } acb_init(xx); acb_init(yy); acb_init(zz); acb_init(sx); acb_init(sy); acb_init(sz); acb_init(X); acb_init(Y); acb_init(Z); acb_init(E2); acb_init(E3); acb_init(t); mag_init(err); mag_init(err2); mag_init(prev_err); order = 5; /* will be set later */ acb_set(xx, x); acb_set(yy, y); acb_set(zz, z); /* First guess precision based on the inputs. */ /* This does not account for mixing. */ accx = acb_rel_accuracy_bits(xx); accy = acb_rel_accuracy_bits(yy); accz = acb_rel_accuracy_bits(zz); accx = FLINT_MAX(accx, accy); accx = FLINT_MAX(accx, accz); if (accx < prec - 20) prec = FLINT_MAX(2, accx + 20); wp = prec + 10 + FLINT_BIT_COUNT(prec); /* Must do at least one iteration. */ for (k = 0; k < prec; k++) { acb_sqrt(sx, xx, wp); acb_sqrt(sy, yy, wp); acb_sqrt(sz, zz, wp); acb_add(t, sy, sz, wp); acb_mul(t, t, sx, wp); acb_addmul(t, sy, sz, wp); acb_add(xx, xx, t, wp); acb_add(yy, yy, t, wp); acb_add(zz, zz, t, wp); acb_mul_2exp_si(xx, xx, -2); acb_mul_2exp_si(yy, yy, -2); acb_mul_2exp_si(zz, zz, -2); /* Improve precision estimate and set expansion order. */ /* Should this done for other k also? */ if (k == 0) { accx = acb_rel_accuracy_bits(xx); accy = acb_rel_accuracy_bits(yy); accz = acb_rel_accuracy_bits(zz); accx = FLINT_MAX(accx, accy); accx = FLINT_MAX(accx, accz); if (accx < prec - 20) prec = FLINT_MAX(2, accx + 20); wp = prec + 10 + FLINT_BIT_COUNT(prec); if (acb_is_real(xx) && acb_is_real(yy) && acb_is_real(zz)) order = 2.1 * pow(prec, 0.4); else order = 2.5 * pow(prec, 0.4); order = FLINT_MIN(order, 500); order = FLINT_MAX(order, 2); } /* Close enough? Quick estimate based on |x-y|/|x| and |x-z|/|x| */ /* We also terminate if there is no improvement. */ acb_sub(t, xx, yy, wp); acb_get_mag(err, t); acb_sub(t, xx, zz, wp); acb_get_mag(err2, t); mag_max(err, err, err2); acb_get_mag_lower(err2, xx); mag_div(err, err, err2); mag_pow_ui(err, err, order); if (mag_cmp_2exp_si(err, -prec) < 0 || (k > 2 && mag_cmp(err, prev_err) > 0)) break; mag_set(prev_err, err); } /* X = 1-x/t, Y = 1-y/t, Z = -X-Y, t = (x+y+z)/3 */ acb_add(t, xx, yy, wp); acb_add(t, t, zz, wp); acb_div_ui(t, t, 3, wp); acb_div(X, xx, t, wp); acb_sub_ui(X, X, 1, wp); acb_neg(X, X); acb_div(Y, yy, t, wp); acb_sub_ui(Y, Y, 1, wp); acb_neg(Y, Y); acb_add(Z, X, Y, wp); acb_neg(Z, Z); /* E2 = XY-Z^2, E3 = XYZ */ acb_mul(E2, X, Y, wp); acb_mul(E3, E2, Z, wp); acb_submul(E2, Z, Z, wp); /* Crude bound for the coefficient of X^n1 Y^n2 Z^n3 with n1+n2+n3=n: 2*(9/8)^n. */ /* Error bound. */ acb_get_mag(err, X); acb_get_mag(err2, Y); mag_max(err, err, err2); acb_get_mag(err2, Z); mag_max(err, err, err2); mag_mul_ui(err, err, 9); mag_mul_2exp_si(err, err, -3); mag_geom_series(err, err, order); mag_mul_2exp_si(err, err, 1); acb_elliptic_rf_taylor_sum(sx, E2, E3, order, wp); if (acb_is_real(X) && acb_is_real(Y)) arb_add_error_mag(acb_realref(sx), err); else acb_add_error_mag(sx, err); acb_rsqrt(t, t, wp); acb_mul(res, sx, t, prec); acb_clear(xx); acb_clear(yy); acb_clear(zz); acb_clear(sx); acb_clear(sy); acb_clear(sz); acb_clear(X); acb_clear(Y); acb_clear(Z); acb_clear(E2); acb_clear(E3); acb_clear(t); mag_clear(err); mag_clear(err2); mag_clear(prev_err); } flint-3.1.3/src/acb_elliptic/rg.c000066400000000000000000000037311461254215100166140ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" void _acb_elliptic_rg(acb_t res, const acb_t x, const acb_t y, const acb_t z, int flags, slong prec) { acb_t a, b, c, t; slong wp; wp = prec + 10; acb_init(a); acb_init(b); acb_init(c); acb_init(t); acb_elliptic_rf(a, x, y, z, 0, wp); acb_mul(a, a, z, wp); acb_elliptic_rj(b, x, y, z, z, 0, wp); acb_sub(c, x, z, wp); acb_mul(b, b, c, wp); acb_sub(c, z, y, wp); acb_mul(b, b, c, wp); acb_div_ui(b, b, 3, wp); acb_sqrt(c, x, wp); acb_sqrt(t, y, wp); acb_mul(c, c, t, wp); acb_rsqrt(t, z, wp); acb_mul(c, c, t, wp); acb_add(res, a, b, wp); acb_add(res, res, c, prec); acb_mul_2exp_si(res, res, -1); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(t); } void acb_elliptic_rg(acb_t res, const acb_t x, const acb_t y, const acb_t z, int flags, slong prec) { if (acb_is_zero(x) && acb_is_zero(y)) { acb_sqrt(res, z, prec); acb_mul_2exp_si(res, res, -1); } else if (acb_is_zero(x) && acb_is_zero(z)) { acb_sqrt(res, y, prec); acb_mul_2exp_si(res, res, -1); } else if (acb_is_zero(y) && acb_is_zero(z)) { acb_sqrt(res, x, prec); acb_mul_2exp_si(res, res, -1); } else if (acb_contains_zero(z)) { if (acb_contains_zero(y)) _acb_elliptic_rg(res, y, z, x, flags, prec); else _acb_elliptic_rg(res, x, z, y, flags, prec); } else { _acb_elliptic_rg(res, x, y, z, flags, prec); } } flint-3.1.3/src/acb_elliptic/rj.c000066400000000000000000000576331461254215100166310ustar00rootroot00000000000000/* Copyright (C) 2017, 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_calc.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif static const unsigned short den_ratio_tab[512] = { 1,1,14,3,44,13,10,17,152,1,46,1,12,29,62,1, 16,37,2,41,172,1,94,7,8,53,2,1,236,61,2,1, 2144,1,142,73,20,1,158,3,664,1,2,89,4,1,2,97, 16,101,206,1,428,109,2,113,8,1,2,11,4,1,254,1, 8384,1,2,137,556,1,2,1,8,149,302,1,4,157,2,1, 2608,1,334,13,4,173,2,1,1432,181,2,1,4,1,382,193, 32,197,398,1,4,1,2,1,1688,1,2,1,4,1,446,1, 3632,229,2,233,4,1,478,241,24,1,2,1,1004,1,2,257, 128,1,526,1,4,269,542,1,8,277,2,281,1132,1,2,17, 16,293,2,1,4,1,2,1,2456,1,622,313,4,317,2,1, 32,1,2,1,1324,1,2,337,8,1,14,1,1388,349,2,353, 16,1,718,19,4,1,734,1,8,373,10,1,1516,1,766,1, 64,389,2,1,4,397,2,401,8,1,2,409,4,1,2,1, 6704,421,2,1,4,1,862,433,8,1,878,1,1772,1,2,449, 32,1,2,457,4,461,926,1,3736,1,2,1,4,1,958,1, 16,1,974,1,1964,1,2,1,3992,1,1006,1,4,509,2,1, 256,1,2,521,2092,1,2,23,8,1,2,1,4,541,2,1, 8752,1,2,1,4,557,2,1,4504,1,2,569,2284,1,2,577, 32,1,2,1,2348,1,2,593,8,1,1198,601,4,1,1214,1, 16,613,2,617,2476,1,2,1,8,1,1262,1,4,1,2,641, 41152,1,1294,1,4,653,2,1,5272,661,2,1,4,1,2,673, 16,677,2,1,2732,1,2,1,5528,1,2,1,4,701,2,1, 32,709,2,1,4,1,1438,1,8,1,1454,3,4,733,2,1, 11824,1,1486,1,4,1,1502,1,8,757,2,761,4,1,2,769, 128,773,2,1,4,1,2,1,6296,1,2,1,4,797,2,1, 16,1,2,809,3244,1,2,1,8,821,1646,1,3308,829,2,1, 32,1,1678,29,4,1,2,1,8,853,2,857,3436,1,1726,1, 16,1,2,1,4,877,2,881,7064,1,1774,1,4,1,2,1, 64,1,2,1,3628,1,1822,1,8,1,1838,1,4,1,2,929, 16,1,2,937,4,941,2,1,7576,1,2,953,4,1,2,31, 32,1,1934,1,3884,1,2,977,8,1,1966,1,4,1,1982,1, 16,997,2,1,4,1,2,1009,8,1013,2,1,4076,1021,2,1 }; static inline slong rj_fdiv(slong x, slong y) { if (x < 0) return -1; else return x / y; } void acb_elliptic_rj_taylor_sum(acb_t res, const acb_t E2, const acb_t E3, const acb_t E4, const acb_t E5, slong nterms, slong prec) { slong m2, m3, m4, m5, m2start, m3start, m4start, m5start, NMAX, N, M; slong m2dim, m3dim; acb_t s2, s3, s4, s5; acb_ptr powtab; fmpz_t c2, c3, c4, c5, den, t; acb_init(s2); acb_init(s3); acb_init(s4); acb_init(s5); fmpz_init(c2); fmpz_init(c3); fmpz_init(c4); fmpz_init(c5); fmpz_init(den); fmpz_init(t); NMAX = nterms - 1; m2dim = NMAX / 2 + 1; m3dim = NMAX / 3 + 1; powtab = _acb_vec_init(m2dim * m3dim); /* Compute universal denominator */ fmpz_one(den); for (N = 1; N <= NMAX; N++) fmpz_mul_ui(den, den, den_ratio_tab[N]); /* Precompute powers of E2 and E3 */ for (m2 = 0; m2 <= NMAX / 2; m2++) { for (m3 = 0; m3 <= rj_fdiv(NMAX - 2 * m2, 3); m3++) { slong i, j, k; i = m3 * m2dim + m2; if (m2 <= 1 && m3 <= 1) { if (m2 == 0 && m3 == 0) acb_one(powtab + i); else if (m2 == 0 && m3 == 1) acb_set(powtab + i, E3); else if (m2 == 1 && m3 == 0) acb_set(powtab + i, E2); else acb_mul(powtab + i, E2, E3, prec); } else { j = (m3 / 2) * m2dim + (m2 / 2); k = (m3 - (m3 / 2)) * m2dim + (m2 - (m2 / 2)); acb_mul(powtab + i, powtab + j, powtab + k, prec); } } } acb_zero(s5); m5start = NMAX / 5; fmpz_mul_ui(c5, den, 3); for (m5 = 0; m5 < m5start; m5++) { fmpz_mul_ui(c5, c5, 2 * m5 + 1); fmpz_divexact_ui(c5, c5, 2 * m5 + 2); } for (m5 = m5start; m5 >= 0; m5--) { acb_zero(s4); m4start = rj_fdiv(NMAX - 5 * m5, 4); if (m5 != m5start) { fmpz_mul_ui(c5, c5, 2 * m5 + 2); fmpz_divexact_ui(c5, c5, 2 * m5 + 1); } fmpz_set(c4, c5); for (m4 = 0; m4 < m4start; m4++) { fmpz_mul_ui(c4, c4, 2 * m5 + 2 * m4 + 1); fmpz_divexact_ui(c4, c4, 2 * m4 + 2); } for (m4 = m4start; m4 >= 0; m4--) { acb_zero(s3); m3start = rj_fdiv(NMAX - 5 * m5 - 4 * m4, 3); if (m4 != m4start) { fmpz_mul_ui(c4, c4, 2 * m4 + 2); fmpz_divexact_ui(c4, c4, 2 * m5 + 2 * m4 + 1); } fmpz_set(c3, c4); for (m3 = 0; m3 <= m3start; m3++) { m2start = rj_fdiv(NMAX - 5 * m5 - 4 * m4 - 3 * m3, 2); fmpz_set(c2, c3); for (m2 = 0; m2 <= m2start; m2++) { M = m5 + m4 + m3 + m2; N = 5 * m5 + 4 * m4 + 3 * m3 + 2 * m2; if (N > NMAX) flint_throw(FLINT_ERROR, "(%s)\n", __func__); fmpz_divexact_ui(t, c2, 2 * N + 3); if ((M + N) % 2) fmpz_neg(t, t); acb_addmul_fmpz(s3, powtab + m3 * m2dim + m2, t, prec); if (m2 < m2start) { fmpz_mul_ui(c2, c2, 2 * m5 + 2 * m4 + 2 * m3 + 2 * m2 + 1); fmpz_divexact_ui(c2, c2, 2 * m2 + 2); } } if (m3 < m3start) { fmpz_mul_ui(c3, c3, 2 * m5 + 2 * m4 + 2 * m3 + 1); fmpz_divexact_ui(c3, c3, 2 * m3 + 2); } } /* Horner with respect to E4. */ acb_mul(s4, s4, E4, prec); acb_add(s4, s4, s3, prec); } /* Horner with respect to E5. */ acb_mul(s5, s5, E5, prec); acb_add(s5, s5, s4, prec); } acb_div_fmpz(res, s5, den, prec); _acb_vec_clear(powtab, m2dim * m3dim); acb_clear(s2); acb_clear(s3); acb_clear(s4); acb_clear(s5); fmpz_clear(c2); fmpz_clear(c3); fmpz_clear(c4); fmpz_clear(c5); fmpz_clear(den); fmpz_clear(t); } void acb_elliptic_rj_carlson(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec) { acb_t xx, yy, zz, pp, sx, sy, sz, sp, t, d, delta, S; acb_t A, AA, X, Y, Z, P, E2, E3, E4, E5; mag_t err, err2, prev_err; slong k, wp, accx, accy, accz, accp, order; int rd, real; /* printf("RJ carlson "); acb_printn(x, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(y, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(z, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(p, 6, ARB_STR_NO_RADIUS); printf(" "); printf("\n"); */ if (!acb_is_finite(x) || !acb_is_finite(y) || !acb_is_finite(z) || !acb_is_finite(p)) { acb_indeterminate(res); return; } if ((acb_contains_zero(x) + acb_contains_zero(y) + acb_contains_zero(z) > 1) || acb_contains_zero(p)) { acb_indeterminate(res); return; } /* Special case computing R_D(x,y,z) */ rd = (z == p) || acb_eq(z, p); acb_init(xx); acb_init(yy); acb_init(zz); acb_init(pp); acb_init(sx); acb_init(sy); acb_init(sz); acb_init(sp); acb_init(S); acb_init(A); acb_init(AA); acb_init(X); acb_init(Y); acb_init(Z); acb_init(P); acb_init(E2); acb_init(E3); acb_init(E4); acb_init(E5); acb_init(t); acb_init(d); acb_init(delta); mag_init(err); mag_init(err2); mag_init(prev_err); acb_set(xx, x); acb_set(yy, y); acb_set(zz, z); acb_set(pp, p); acb_zero(S); real = acb_is_real(x) && acb_is_real(y) && acb_is_real(z) && acb_is_real(p) && arb_is_nonnegative(acb_realref(x)) && arb_is_nonnegative(acb_realref(y)) && arb_is_nonnegative(acb_realref(z)) && arb_is_nonnegative(acb_realref(p)); order = 5; /* will be set later */ /* First guess precision based on the inputs. */ /* This does not account for mixing. */ accx = acb_rel_accuracy_bits(xx); accy = acb_rel_accuracy_bits(yy); accz = acb_rel_accuracy_bits(zz); accp = acb_rel_accuracy_bits(pp); accx = FLINT_MAX(accx, accy); accx = FLINT_MAX(accx, accz); accx = FLINT_MAX(accx, accp); if (accx < prec - 20) prec = FLINT_MAX(2, accx + 20); wp = prec + 4 + FLINT_BIT_COUNT(prec); if (!rd) { acb_mul_2exp_si(A, p, 1); acb_add(A, A, z, wp); } else { acb_mul_ui(A, z, 3, wp); } acb_add(A, A, x, wp); acb_add(A, A, y, wp); acb_div_ui(A, A, 5, wp); acb_set(AA, A); if (!rd) { acb_sub(delta, p, x, wp); acb_sub(t, p, y, wp); acb_mul(delta, delta, t, wp); acb_sub(t, p, z, wp); acb_mul(delta, delta, t, wp); } /* must do at least one iteration */ for (k = 0; k < prec; k++) { acb_sqrt(sx, xx, wp); acb_sqrt(sy, yy, wp); acb_sqrt(sz, zz, wp); if (!rd) acb_sqrt(sp, pp, wp); acb_add(t, sy, sz, wp); acb_mul(t, t, sx, wp); acb_addmul(t, sy, sz, wp); acb_add(xx, xx, t, wp); acb_add(yy, yy, t, wp); acb_add(zz, zz, t, wp); if (!rd) acb_add(pp, pp, t, wp); acb_add(AA, AA, t, wp); acb_mul_2exp_si(xx, xx, -2); acb_mul_2exp_si(yy, yy, -2); acb_mul_2exp_si(zz, zz, -2); if (!rd) acb_mul_2exp_si(pp, pp, -2); acb_mul_2exp_si(AA, AA, -2); if (!rd) { /* d = (sp+sx)(sp+sy)(sp+sz) */ /* e = 4^(-3k) delta / d^2 */ /* S += 4^(-k) RC(1, 1+e) / d */ acb_add(d, sp, sx, wp); acb_add(t, sp, sy, wp); acb_mul(d, d, t, wp); acb_add(t, sp, sz, wp); acb_mul(d, d, t, wp); /* E2 = e */ acb_mul(E2, d, d, wp); acb_div(E2, delta, E2, wp); acb_mul_2exp_si(E2, E2, -6 * k); acb_elliptic_rc1(E4, E2, wp); acb_div(E4, E4, d, wp); acb_mul_2exp_si(E4, E4, -2 * k); acb_add(S, S, E4, wp); } else { acb_mul(t, sz, zz, wp); acb_mul_2exp_si(t, t, 2); acb_inv(t, t, wp); acb_mul_2exp_si(t, t, -2 * k); acb_mul_2exp_si(t, t, -1); acb_add(S, S, t, wp); } /* Improve precision estimate and set expansion order. */ /* Should this done for other k also? */ if (k == 0) { accx = acb_rel_accuracy_bits(xx); accy = acb_rel_accuracy_bits(yy); accz = acb_rel_accuracy_bits(zz); accp = acb_rel_accuracy_bits(pp); accx = FLINT_MAX(accx, accy); accx = FLINT_MAX(accx, accz); accx = FLINT_MAX(accx, accp); if (accx < prec - 20) prec = FLINT_MAX(2, accx + 20); wp = prec + 4 + FLINT_BIT_COUNT(prec); if (!rd) if (real) order = 2.3 * pow(prec, 0.34); else order = 2.5 * pow(prec, 0.35); else if (real) order = 2.0 * pow(prec, 0.33); else order = 2.2 * pow(prec, 0.33); order = FLINT_MIN(order, 500); order = FLINT_MAX(order, 5); } /* Close enough? */ acb_sub(t, xx, yy, wp); acb_get_mag(err, t); acb_sub(t, xx, zz, wp); acb_get_mag(err2, t); mag_max(err, err, err2); if (!rd) { acb_sub(t, xx, pp, wp); acb_get_mag(err2, t); mag_max(err, err, err2); } acb_get_mag_lower(err2, xx); mag_div(err, err, err2); mag_pow_ui(err, err, order); if (mag_cmp_2exp_si(err, -prec) < 0 || (k > 2 && mag_cmp(err, prev_err) > 0)) { k++; break; } mag_set(prev_err, err); } /* X = (A-x)/(4^k AA) */ /* Y = (A-y)/(4^k AA) */ /* Z = (A-z)/(4^k AA) */ /* P = (-X-Y-Z)/2 */ acb_mul_2exp_si(t, AA, 2 * k); acb_inv(t, t, prec); acb_sub(X, A, x, prec); acb_mul(X, X, t, prec); acb_sub(Y, A, y, prec); acb_mul(Y, Y, t, prec); acb_sub(Z, A, z, prec); acb_mul(Z, Z, t, prec); acb_add(P, X, Y, prec); acb_add(P, P, Z, prec); acb_neg(P, P); acb_mul_2exp_si(P, P, -1); /* todo: improve for R_D */ /* E2 = XY + XZ + YZ - 3 P^2 */ /* E3 = XYZ + 2 E2 P + 4 P^3 */ /* E4 = (2 XYZ + E2 P + 3 P^3) P */ /* E5 = XYZP^2 */ acb_mul(t, P, P, prec); /* t = P^2 */ acb_mul(E2, X, Y, prec); acb_mul(E3, E2, Z, prec); acb_mul_2exp_si(E4, E3, 1); acb_mul(E5, E3, t, prec); acb_add(sx, X, Y, prec); acb_addmul(E2, sx, Z, prec); acb_submul_ui(E2, t, 3, prec); acb_mul(sx, E2, P, prec); acb_add(E4, E4, sx, prec); acb_mul_2exp_si(sx, sx, 1); acb_add(E3, E3, sx, prec); acb_mul(t, t, P, prec); /* t = P^3 */ acb_addmul_ui(E3, t, 4, prec); acb_addmul_ui(E4, t, 3, prec); acb_mul(E4, E4, P, prec); /* Error bound. */ acb_get_mag(err, X); acb_get_mag(err2, Y); mag_max(err, err, err2); acb_get_mag(err2, Z); mag_max(err, err, err2); acb_get_mag(err2, P); mag_max(err, err, err2); mag_mul_ui(err, err, 9); mag_mul_2exp_si(err, err, -3); mag_geom_series(err, err, order); mag_mul_2exp_si(err, err, 1); acb_elliptic_rj_taylor_sum(sx, E2, E3, E4, E5, order, wp); if (acb_is_real(X) && acb_is_real(Y) && acb_is_real(Z)) arb_add_error_mag(acb_realref(sx), err); else acb_add_error_mag(sx, err); acb_rsqrt(t, AA, wp); acb_div(t, t, AA, wp); acb_mul_2exp_si(t, t, -2 * k); acb_mul(t, t, sx, wp); acb_addmul_ui(t, S, 6, prec); acb_set(res, t); acb_clear(xx); acb_clear(yy); acb_clear(zz); acb_clear(pp); acb_clear(sx); acb_clear(sy); acb_clear(sz); acb_clear(sp); acb_clear(S); acb_clear(A); acb_clear(AA); acb_clear(X); acb_clear(Y); acb_clear(Z); acb_clear(P); acb_clear(E2); acb_clear(E3); acb_clear(E4); acb_clear(E5); acb_clear(t); acb_clear(d); acb_clear(delta); mag_clear(err); mag_clear(err2); mag_clear(prev_err); } static int acb_eq_conj(const acb_t x, const acb_t y) { int res; acb_t t; acb_init(t); acb_conj(t, y); res = acb_eq(x, t); acb_clear(t); return res; } /* todo: speed up this function -- early abort -- only compute single rsqrt or sqrt when evaluating precisely (but need to make sure branch is correct!) */ static int RJ_integrand(acb_ptr res, const acb_t t, void * param, slong order, slong prec) { acb_ptr x, y, z, p; acb_t xt, yt, zt, pt; int analytic, deflated; if (order > 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* Would be needed for Taylor method. */ x = ((acb_ptr) param); y = ((acb_ptr) param) + 1; z = ((acb_ptr) param) + 2; p = ((acb_ptr) param) + 3; deflated = acb_is_zero(x); analytic = (order != 0); acb_init(xt); acb_init(yt); acb_init(zt); acb_init(pt); /* if x = 0, change of variables t -> t^2 to remove singularity at 0 */ if (deflated) { acb_sqr(xt, t, prec); acb_add(yt, y, xt, prec); acb_add(zt, z, xt, prec); acb_add(pt, p, xt, prec); if (acb_contains_zero(yt) || acb_contains_zero(zt) || acb_contains_zero(pt)) { acb_indeterminate(res); } else { acb_rsqrt_analytic(yt, yt, analytic, prec); acb_rsqrt_analytic(zt, zt, analytic, prec); acb_mul(xt, yt, zt, prec); acb_div(xt, xt, pt, prec); acb_mul_2exp_si(xt, xt, 1); acb_set(res, xt); } } else { acb_add(xt, x, t, prec); acb_add(yt, y, t, prec); acb_add(zt, z, t, prec); acb_add(pt, p, t, prec); if (acb_contains_zero(xt) || acb_contains_zero(yt) || acb_contains_zero(zt) || acb_contains_zero(pt)) { acb_indeterminate(res); } else { acb_rsqrt_analytic(xt, xt, analytic, prec); acb_rsqrt_analytic(yt, yt, analytic, prec); acb_rsqrt_analytic(zt, zt, analytic, prec); acb_mul(xt, xt, yt, prec); acb_mul(xt, xt, zt, prec); acb_div(xt, xt, pt, prec); acb_set(res, xt); } } acb_clear(xt); acb_clear(yt); acb_clear(zt); acb_clear(pt); return 0; } void acb_elliptic_rj_integration(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec) { acb_t a, b, N, I, J; arb_t A; acb_ptr xyzp; mag_t tol; int deflated; /* printf("RJ integration: "); acb_printn(x, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(y, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(z, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(p, 6, ARB_STR_NO_RADIUS); printf(" "); printf("\n"); */ acb_init(N); acb_init(a); acb_init(b); acb_init(I); acb_init(J); arb_init(A); xyzp = _acb_vec_init(4); mag_init(tol); /* compute shift that puts parameters in right half-plane */ arb_min(A, acb_realref(x), acb_realref(y), prec); arb_min(A, A, acb_realref(z), prec); arb_min(A, A, acb_realref(p), prec); arb_neg(A, A); arb_one(acb_realref(a)); arb_max(A, A, acb_realref(a), prec); arb_add_ui(A, A, 2, prec); arb_get_ubound_arf(arb_midref(A), A, prec); mag_zero(arb_radref(A)); acb_set(xyzp, x); acb_set(xyzp + 1, y); acb_set(xyzp + 2, z); acb_set(xyzp + 3, p); /* If there is a zero among x, y, z, put it first. */ if (acb_is_zero(y)) acb_swap(xyzp, xyzp + 1); if (acb_is_zero(z)) acb_swap(xyzp, xyzp + 2); deflated = acb_is_zero(xyzp); acb_set_arb(N, A); /* Path deformation to avoid 0 */ if ((arb_is_nonnegative(acb_imagref(x)) || arb_is_positive(acb_realref(x))) && (arb_is_nonnegative(acb_imagref(y)) || arb_is_positive(acb_realref(y))) && (arb_is_nonnegative(acb_imagref(z)) || arb_is_positive(acb_realref(z))) && (arb_is_nonnegative(acb_imagref(p)) || arb_is_positive(acb_realref(p)))) { arb_set_si(acb_imagref(N), 1); } else if ((arb_is_negative(acb_imagref(x)) || arb_is_positive(acb_realref(x))) && (arb_is_negative(acb_imagref(y)) || arb_is_positive(acb_realref(y))) && (arb_is_negative(acb_imagref(z)) || arb_is_positive(acb_realref(z))) && (arb_is_negative(acb_imagref(p)) || arb_is_positive(acb_realref(p)))) { arb_set_si(acb_imagref(N), -1); } else { int i; arb_set_si(acb_imagref(N), 2); /* Go through the upper half-plane, but low enough that any parameter starting in the lower plane doesn't cross the branch cut */ for (i = 0; i < 4; i++) { if (deflated && (i == 0)) continue; if (arb_is_nonnegative(acb_imagref(xyzp + i)) || arb_is_positive(acb_realref(xyzp + i))) continue; arb_zero(acb_realref(a)); /* use as tmp var */ arb_get_abs_lbound_arf(arb_midref(acb_realref(a)), acb_imagref(xyzp + i), prec); arb_min(acb_imagref(N), acb_imagref(N), acb_realref(a), prec); } arb_mul_2exp_si(acb_imagref(N), acb_imagref(N), -1); } mag_one(tol); mag_mul_2exp_si(tol, tol, -prec); acb_zero(a); if (deflated) acb_sqrt(b, N, prec); else acb_set(b, N); /* flint_printf("integrate "); flint_printf("%d\n", deflated); flint_printf("x = "); acb_printd(xyzp, 10); flint_printf("\n"); flint_printf("y = "); acb_printd(xyzp + 1, 10); flint_printf("\n"); flint_printf("z = "); acb_printd(xyzp + 2, 10); flint_printf("\n"); flint_printf("p = "); acb_printd(xyzp + 3, 10); flint_printf("\n"); flint_printf("a = "); acb_printd(a, 10); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 10); flint_printf("\n"); flint_printf("N = "); acb_printd(N, 10); flint_printf("\n"); */ acb_calc_integrate(I, RJ_integrand, xyzp, a, b, prec, tol, NULL, prec); acb_mul_ui(I, I, 3, prec); acb_mul_2exp_si(I, I, -1); /* flint_printf("I = "); acb_printd(I, 10); flint_printf("\n"); */ acb_add(xyzp, x, N, prec); acb_add(xyzp + 1, y, N, prec); acb_add(xyzp + 2, z, N, prec); acb_add(xyzp + 3, p, N, prec); acb_elliptic_rj_carlson(J, xyzp, xyzp + 1, xyzp + 2, xyzp + 3, 0, prec); acb_add(res, I, J, prec); acb_clear(N); acb_clear(a); acb_clear(b); acb_clear(I); acb_clear(J); arb_clear(A); _acb_vec_clear(xyzp, 4); mag_clear(tol); } void acb_elliptic_rj(acb_t res, const acb_t x, const acb_t y, const acb_t z, const acb_t p, int flags, slong prec) { /* printf("RJ: "); acb_printn(x, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(y, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(z, 6, ARB_STR_NO_RADIUS); printf(" "); acb_printn(p, 6, ARB_STR_NO_RADIUS); printf(" "); printf("\n"); */ if (!acb_is_finite(x) || !acb_is_finite(y) || !acb_is_finite(z) || !acb_is_finite(p)) { acb_indeterminate(res); return; } if ((acb_contains_zero(x) + acb_contains_zero(y) + acb_contains_zero(z) > 1) || acb_contains_zero(p)) { acb_indeterminate(res); return; } /* Carlson's algorithm is correct in the degenerate case computing R_D */ if (x == p || acb_eq(x, p)) { acb_elliptic_rj_carlson(res, y, z, x, p, flags, prec); return; } if (y == p || acb_eq(y, p)) { acb_elliptic_rj_carlson(res, x, z, y, p, flags, prec); return; } if (z == p || acb_eq(z, p)) { acb_elliptic_rj_carlson(res, x, y, z, p, flags, prec); return; } /* Sufficient condition for correctness */ if (arb_is_nonnegative(acb_realref(x)) && arb_is_nonnegative(acb_realref(y)) && arb_is_nonnegative(acb_realref(z)) && arb_is_positive(acb_realref(p))) { acb_elliptic_rj_carlson(res, x, y, z, p, flags, prec); return; } /* Sufficient condition for correctness */ if (acb_is_real(x) && acb_is_real(y) && acb_is_real(z) && acb_is_real(p)) { acb_elliptic_rj_carlson(res, x, y, z, p, flags, prec); return; } /* Also a sufficient condition */ if (arb_is_nonnegative(acb_realref(p)) || arb_is_nonzero(acb_imagref(p))) { if ((arb_is_zero(acb_imagref(x)) && arb_is_nonnegative(acb_realref(x)) && acb_eq_conj(y, z)) || (arb_is_zero(acb_imagref(y)) && arb_is_nonnegative(acb_realref(y)) && acb_eq_conj(x, z)) || (arb_is_zero(acb_imagref(z)) && arb_is_nonnegative(acb_realref(z)) && acb_eq_conj(x, y))) { acb_elliptic_rj_carlson(res, x, y, z, p, flags, prec); return; } } /* Fast abort for input straddling branch cuts */ if ((arb_contains_zero(acb_imagref(x)) && !(arb_is_nonnegative(acb_imagref(x)) || arb_is_nonnegative(acb_realref(x)))) || (arb_contains_zero(acb_imagref(y)) && !(arb_is_nonnegative(acb_imagref(y)) || arb_is_nonnegative(acb_realref(y)))) || (arb_contains_zero(acb_imagref(z)) && !(arb_is_nonnegative(acb_imagref(z)) || arb_is_nonnegative(acb_realref(z)))) || (arb_contains_zero(acb_imagref(p)) && !(arb_is_nonnegative(acb_imagref(p)) || arb_is_nonnegative(acb_realref(p))))) { acb_indeterminate(res); return; } /* Use integration as fallback */ acb_elliptic_rj_integration(res, x, y, z, p, flags, prec); } flint-3.1.3/src/acb_elliptic/roots.c000066400000000000000000000032761461254215100173560ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" void acb_elliptic_roots(acb_t e1, acb_t e2, acb_t e3, const acb_t tau, slong prec) { acb_t t1, t2, t3, t4; int e1r, e23r; if (!arb_is_positive(acb_imagref(tau)) || !arb_is_finite(acb_realref(tau))) { acb_indeterminate(e1); acb_indeterminate(e2); acb_indeterminate(e3); return; } acb_init(t1); acb_init(t2); acb_init(t3); acb_init(t4); e1r = e23r = 0; if (arb_is_int(acb_realref(tau))) e1r = e23r = 1; else if (arb_is_int_2exp_si(acb_realref(tau), -1)) e1r = 1; acb_modular_theta(t1, t2, t3, t4, t1, tau, prec); acb_pow_ui(t2, t2, 4, prec); acb_pow_ui(t4, t4, 4, prec); acb_sub(e2, t2, t4, prec); acb_mul_2exp_si(t3, t4, 1); acb_add(e1, t2, t3, prec); acb_mul_2exp_si(t3, t2, 1); acb_add(e3, t3, t4, prec); acb_const_pi(t3, prec); acb_mul(t3, t3, t3, prec); acb_div_ui(t3, t3, 3, prec); acb_mul(e1, e1, t3, prec); acb_mul(e2, e2, t3, prec); acb_mul(e3, e3, t3, prec); acb_neg(e3, e3); if (e1r) arb_zero(acb_imagref(e1)); if (e23r) { arb_zero(acb_imagref(e2)); arb_zero(acb_imagref(e3)); } acb_clear(t1); acb_clear(t2); acb_clear(t3); acb_clear(t4); } flint-3.1.3/src/acb_elliptic/test/000077500000000000000000000000001461254215100170135ustar00rootroot00000000000000flint-3.1.3/src/acb_elliptic/test/main.c000066400000000000000000000026771461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-e_inc.c" #include "t-f.c" #include "t-invariants.c" #include "t-inv_p.c" #include "t-pi.c" #include "t-pi_inc.c" #include "t-p_p_prime.c" #include "t-rc1.c" #include "t-rf.c" #include "t-rg.c" #include "t-rj.c" #include "t-sigma.c" #include "t-zeta.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_elliptic_e_inc), TEST_FUNCTION(acb_elliptic_f), TEST_FUNCTION(acb_elliptic_invariants), TEST_FUNCTION(acb_elliptic_inv_p), TEST_FUNCTION(acb_elliptic_pi), TEST_FUNCTION(acb_elliptic_pi_inc), TEST_FUNCTION(acb_elliptic_p_p_prime), TEST_FUNCTION(acb_elliptic_rc1), TEST_FUNCTION(acb_elliptic_rf), TEST_FUNCTION(acb_elliptic_rg), TEST_FUNCTION(acb_elliptic_rj), TEST_FUNCTION(acb_elliptic_sigma), TEST_FUNCTION(acb_elliptic_zeta) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_elliptic/test/t-e_inc.c000066400000000000000000000067271461254215100205110ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_elliptic_e_inc, state) { slong iter; /* test E(z,m) = E(z+pi k, m) - 2 k E(m) */ for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z1, z2, m, r1, r2, r3, t; arb_t pi; fmpz_t k; slong prec1, prec2; int times_pi; acb_init(z1); acb_init(z2); acb_init(m); acb_init(r1); acb_init(r2); acb_init(r3); acb_init(t); arb_init(pi); fmpz_init(k); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); times_pi = n_randint(state, 2); acb_randtest(z1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); acb_randtest(m, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); fmpz_randtest(k, state, 1 + n_randint(state, 100)); arb_const_pi(pi, FLINT_MAX(prec1, prec2)); if (n_randint(state, 2)) arb_set_d(acb_realref(z1), -4.5 + n_randint(state, 10)); if (times_pi) { if (n_randint(state, 2)) { acb_mul_arb(t, z1, pi, prec2); acb_elliptic_e_inc(r1, t, m, 0, prec1); } else { acb_elliptic_e_inc(r1, z1, m, 1, prec1); } if (n_randint(state, 2)) { acb_add_fmpz(z2, z1, k, prec2); acb_elliptic_e_inc(r2, z2, m, 1, prec2); } else { acb_mul_arb(z2, z1, pi, prec2); arb_addmul_fmpz(acb_realref(z2), pi, k, prec2); acb_elliptic_e_inc(r2, z2, m, 0, prec2); } } else { acb_elliptic_e_inc(r1, z1, m, 0, prec1); acb_set(z2, z1); arb_addmul_fmpz(acb_realref(z2), pi, k, prec2); acb_elliptic_e_inc(r2, z2, m, 0, prec2); } acb_set(r3, r2); acb_modular_elliptic_e(t, m, prec2); acb_mul_2exp_si(t, t, 1); acb_submul_fmpz(r3, t, k, prec2); if (!acb_overlaps(r1, r3)) { flint_printf("FAIL: overlap\n\n"); flint_printf("times_pi = %d\n\n", times_pi); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("k = "); fmpz_print(k); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_printf("r3 = "); acb_printd(r3, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z1); acb_clear(z2); acb_clear(m); acb_clear(r1); acb_clear(r2); acb_clear(r3); acb_clear(t); arb_clear(pi); fmpz_clear(k); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-f.c000066400000000000000000000066751461254215100176630ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_elliptic_f, state) { slong iter; /* test F(z,m) = F(z+pi k, m) - 2 k K(m) */ for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z1, z2, m, r1, r2, r3, t; arb_t pi; fmpz_t k; slong prec1, prec2; int times_pi; acb_init(z1); acb_init(z2); acb_init(m); acb_init(r1); acb_init(r2); acb_init(r3); acb_init(t); arb_init(pi); fmpz_init(k); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); times_pi = n_randint(state, 2); acb_randtest(z1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest(m, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); fmpz_randtest(k, state, 1 + n_randint(state, 100)); arb_const_pi(pi, FLINT_MAX(prec1, prec2)); if (n_randint(state, 2)) arb_set_d(acb_realref(z1), -4.5 + n_randint(state, 10)); if (times_pi) { if (n_randint(state, 2)) { acb_mul_arb(t, z1, pi, prec2); acb_elliptic_f(r1, t, m, 0, prec1); } else { acb_elliptic_f(r1, z1, m, 1, prec1); } if (n_randint(state, 2)) { acb_add_fmpz(z2, z1, k, prec2); acb_elliptic_f(r2, z2, m, 1, prec2); } else { acb_mul_arb(z2, z1, pi, prec2); arb_addmul_fmpz(acb_realref(z2), pi, k, prec2); acb_elliptic_f(r2, z2, m, 0, prec2); } } else { acb_elliptic_f(r1, z1, m, 0, prec1); acb_set(z2, z1); arb_addmul_fmpz(acb_realref(z2), pi, k, prec2); acb_elliptic_f(r2, z2, m, 0, prec2); } acb_set(r3, r2); acb_modular_elliptic_k(t, m, prec2); acb_mul_2exp_si(t, t, 1); acb_submul_fmpz(r3, t, k, prec2); if (!acb_overlaps(r1, r3)) { flint_printf("FAIL: overlap\n\n"); flint_printf("times_pi = %d\n\n", times_pi); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("k = "); fmpz_print(k); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_printf("r3 = "); acb_printd(r3, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z1); acb_clear(z2); acb_clear(m); acb_clear(r1); acb_clear(r2); acb_clear(r3); acb_clear(t); arb_clear(pi); fmpz_clear(k); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-inv_p.c000066400000000000000000000033621461254215100205370ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" TEST_FUNCTION_START(acb_elliptic_inv_p, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z, w, pw; slong prec; acb_init(tau); acb_init(z); acb_init(w); acb_init(pw); prec = 2 + n_randint(state, 400); acb_randtest(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); acb_randtest(w, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); acb_randtest(tau, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); if (arf_sgn(arb_midref(acb_imagref(tau))) < 0) acb_neg(tau, tau); acb_elliptic_inv_p(w, z, tau, prec); acb_elliptic_p(pw, w, tau, prec); if (!acb_contains(pw, z)) { flint_printf("FAIL (containment)\n"); flint_printf("tau = "); acb_printd(tau, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 30); flint_printf("\n\n"); flint_printf("pw = "); acb_printd(pw, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z); acb_clear(w); acb_clear(pw); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-invariants.c000066400000000000000000000042151461254215100216000ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" TEST_FUNCTION_START(acb_elliptic_invariants, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, e1, e2, e3, g2, g3, h2, h3; slong prec; acb_init(tau); acb_init(e1); acb_init(e2); acb_init(e3); acb_init(g2); acb_init(g3); acb_init(h2); acb_init(h3); prec = 2 + n_randint(state, 400); acb_randtest(tau, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); if (arf_sgn(arb_midref(acb_imagref(tau))) < 0) acb_neg(tau, tau); acb_elliptic_roots(e1, e2, e3, tau, prec); acb_elliptic_invariants(g2, g3, tau, prec); acb_mul(h2, e1, e1, prec); acb_addmul(h2, e2, e2, prec); acb_addmul(h2, e3, e3, prec); acb_mul_2exp_si(h2, h2, 1); acb_mul(h3, e1, e2, prec); acb_mul(h3, h3, e3, prec); acb_mul_2exp_si(h3, h3, 2); if (!acb_overlaps(g2, h2) || !acb_overlaps(g3, h3)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau = "); acb_printd(tau, 30); flint_printf("\n\n"); flint_printf("g2 = "); acb_printd(g2, 30); flint_printf("\n\n"); flint_printf("g3 = "); acb_printd(g3, 30); flint_printf("\n\n"); flint_printf("h2 = "); acb_printd(h2, 30); flint_printf("\n\n"); flint_printf("h3 = "); acb_printd(h3, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(e1); acb_clear(e2); acb_clear(e3); acb_clear(g2); acb_clear(g3); acb_clear(h2); acb_clear(h3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-p_p_prime.c000066400000000000000000000056231461254215100214000ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" TEST_FUNCTION_START(acb_elliptic_p_p_prime, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_struct pj[2]; acb_t tau, z, p, pp, g2, g3, t; slong prec; acb_init(tau); acb_init(z); acb_init(p); acb_init(pp); acb_init(pj + 0); acb_init(pj + 1); acb_init(g2); acb_init(g3); acb_init(t); prec = 2 + n_randint(state, 400); acb_randtest(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); acb_randtest(tau, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); if (arf_sgn(arb_midref(acb_imagref(tau))) < 0) acb_neg(tau, tau); acb_elliptic_p(p, z, tau, prec); acb_elliptic_p_prime(pp, z, tau, prec); acb_elliptic_p_jet(pj, z, tau, 2, prec); if (!acb_overlaps(p, pj + 0) || !acb_overlaps(pp, pj + 1)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau = "); acb_printd(tau, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("p = "); acb_printd(p, 30); flint_printf("\n\n"); flint_printf("pp = "); acb_printd(pp, 30); flint_printf("\n\n"); flint_printf("pj0 = "); acb_printd(pj + 0, 30); flint_printf("\n\n"); flint_printf("pj1 = "); acb_printd(pj + 1, 30); flint_printf("\n\n"); flint_abort(); } acb_elliptic_invariants(g2, g3, tau, prec); acb_pow_ui(pj + 0, pp, 2, prec); acb_mul(t, p, g2, prec); acb_add(t, t, g3, prec); acb_pow_ui(pj + 1, p, 3, prec); acb_mul_ui(pj + 1, pj + 1, 4, prec); acb_sub(pj + 1, pj + 1, t, prec); if (!acb_overlaps(pj + 0, pj + 1)) { flint_printf("FAIL (check pp^2 = 4p^3-g2*p-g3)\n"); flint_printf("tau = "); acb_printd(tau, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("p = "); acb_printd(p, 30); flint_printf("\n\n"); flint_printf("pp = "); acb_printd(pp, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z); acb_clear(p); acb_clear(pp); acb_clear(pj + 0); acb_clear(pj + 1); acb_clear(g2); acb_clear(g3); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-pi.c000066400000000000000000000130461461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif static const double testdata_pi[17][6] = { {-2.0, 0.0, 0.0, 0.0, 0.9068996821171089253, 0.0}, {-2.0, 0.0, 2.0, 0.0, 0.90023699434287315449, -0.5446596026314193538}, {-2.0, 0.0, 0.0, 1.0, 0.84791174714919877248, 0.12945491185218067805}, {0.0, 0.0, -2.0, 0.0, 1.1714200841467698589, 0.0}, {0.0, 0.0, 2.0, 0.0, 1.3110287771460599052, -1.3110287771460599052}, {0.0, 0.0, 0.0, 1.0, 1.4212722810450360172, 0.29538028421477684284}, {2.0, 0.0, -2.0, 0.0, 0.30328372333566606144, -1.1107207345395915618}, {2.0, 0.0, 0.0, 0.0, 0.0, -1.5707963267948966192}, {2.0, 0.0, 0.0, 1.0, 0.53486323549280133642, -1.7002121907485779385}, {0.0, 1.0, -2.0, 0.0, 0.95136015191114896677, 0.33513918759114703301}, {0.0, 1.0, 0.0, 0.0, 1.2203312255379458475, 0.50547774420519745381}, {0.0, 1.0, 2.0, 0.0, 1.7987619218751253398, -0.55552744414075242238}, {2.0, -1.0, 2.0, 1.0, 1.8578723151271115, -1.18642180609983531}, {2.0, -0.5, 0.5, 1.0, 0.936761970766645807, -1.61876787838890786}, {2.0, 0.0, 1.0, 1.0, 0.999881420735506708, -2.4139272867045391}, {2.0, 1.0, 2.0, -1.0, 1.8578723151271115, 1.18642180609983531}, {2.0, 1.0, 2.0, 0.0, 2.78474654927885845, 2.02204728966993314}, }; TEST_FUNCTION_START(acb_elliptic_pi, state) { slong iter; /* Test self-consistency, and Pi(n,n) = E(n) / (1-n) */ for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, m, r1, r2, t; slong prec1, prec2; prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); acb_init(n); acb_init(m); acb_init(r1); acb_init(r2); acb_init(t); if (iter == 0) { slong k; for (k = 0; k < 17; k++) { acb_set_d_d(n, testdata_pi[k][0], testdata_pi[k][1]); acb_set_d_d(m, testdata_pi[k][2], testdata_pi[k][3]); acb_set_d_d(r2, testdata_pi[k][4], testdata_pi[k][5]); mag_set_d(arb_radref(acb_realref(r2)), 1e-14 * fabs(testdata_pi[k][4])); mag_set_d(arb_radref(acb_imagref(r2)), 1e-14 * fabs(testdata_pi[k][5])); for (prec1 = 32; prec1 <= (0.1 * flint_test_multiplier() < 1.0 ? 64 : 256); prec1 *= 2) { acb_elliptic_pi(r1, n, m, prec1 + 30); if (!acb_overlaps(r1, r2) || acb_rel_accuracy_bits(r1) < prec1) { flint_printf("FAIL: overlap (testdata)\n\n"); flint_printf("prec = %wd, accuracy = %wd\n\n", prec1, acb_rel_accuracy_bits(r1)); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } } } acb_randtest(n, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_randtest(m, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_one(t); if ((acb_is_real(n) && acb_is_real(m) && arb_le(acb_realref(n), acb_realref(t)) && arb_le(acb_realref(m), acb_realref(t))) || n_randint(state, 10) == 0) { acb_elliptic_pi(r1, n, n, prec1); acb_modular_elliptic_e(r2, n, prec1); acb_sub_ui(t, n, 1, prec1); acb_neg(t, t); acb_div(r2, r2, t, prec1); if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap (m=n)\n\n"); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } acb_elliptic_pi(r1, n, m, prec1); acb_randtest(t, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_add(n, n, t, prec2); acb_sub(n, n, t, prec2); acb_randtest(t, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_add(m, m, t, prec2); acb_sub(m, m, t, prec2); acb_elliptic_pi(r2, n, m, prec2); if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap (consistency)\n\n"); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } acb_clear(n); acb_clear(m); acb_clear(r1); acb_clear(r2); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-pi_inc.c000066400000000000000000000132521461254215100206640ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_elliptic_pi_inc, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_t z1, z2, n, m, r1, r2, r3, t; arb_t pi; fmpz_t k; slong prec1, prec2; int times_pi; acb_init(z1); acb_init(z2); acb_init(n); acb_init(m); acb_init(r1); acb_init(r2); acb_init(r3); acb_init(t); arb_init(pi); fmpz_init(k); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); times_pi = n_randint(state, 2); acb_randtest(n, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); acb_randtest(z1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); acb_randtest(m, state, 1 + n_randint(state, 500), 1 + n_randint(state, 10)); fmpz_randtest(k, state, 1 + n_randint(state, 100)); arb_const_pi(pi, FLINT_MAX(prec1, prec2)); acb_one(t); if ((acb_is_real(n) && acb_is_real(z1) && acb_is_real(m) && arb_le(acb_realref(n), acb_realref(t)) && arb_le(acb_realref(m), acb_realref(t))) || n_randint(state, 10) == 0) { if (n_randint(state, 2)) arb_set_d(acb_realref(z1), -4.5 + n_randint(state, 10)); /* test Pi(n,z,m) = Pi(n, z+pi k, m) - 2 k Pi(n, m) */ if (times_pi) { if (n_randint(state, 2)) { acb_mul_arb(t, z1, pi, prec2); acb_elliptic_pi_inc(r1, n, t, m, 0, prec1); } else { acb_elliptic_pi_inc(r1, n, z1, m, 1, prec1); } if (n_randint(state, 2)) { acb_add_fmpz(z2, z1, k, prec2); acb_elliptic_pi_inc(r2, n, z2, m, 1, prec2); } else { acb_mul_arb(z2, z1, pi, prec2); arb_addmul_fmpz(acb_realref(z2), pi, k, prec2); acb_elliptic_pi_inc(r2, n, z2, m, 0, prec2); } } else { acb_elliptic_pi_inc(r1, n, z1, m, 0, prec1); acb_set(z2, z1); arb_addmul_fmpz(acb_realref(z2), pi, k, prec2); acb_elliptic_pi_inc(r2, n, z2, m, 0, prec2); } acb_set(r3, r2); acb_elliptic_pi(t, n, m, prec2); acb_mul_2exp_si(t, t, 1); acb_submul_fmpz(r3, t, k, prec2); if (!acb_overlaps(r1, r3)) { flint_printf("FAIL: overlap\n\n"); flint_printf("times_pi = %d\n\n", times_pi); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("k = "); fmpz_print(k); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_printf("r3 = "); acb_printd(r3, 30); flint_printf("\n\n"); flint_abort(); } /* test http://functions.wolfram.com/EllipticIntegrals/EllipticPi3/03/01/01/0006/ */ /* Pi(n,z,n) = (n sin(2z) / (2 sqrt(1-n sin(z)^2)) - E(z,n))/(n-1) */ acb_elliptic_pi_inc(r1, n, z1, n, times_pi, prec1); if (times_pi) acb_sin_pi(z2, z1, prec1); else acb_sin(z2, z1, prec1); acb_mul(z2, z2, z2, prec1); acb_mul(z2, z2, n, prec1); acb_sub_ui(z2, z2, 1, prec1); acb_neg(z2, z2); acb_rsqrt(z2, z2, prec1); acb_mul_2exp_si(z2, z2, -1); acb_mul_2exp_si(r3, z1, 1); if (times_pi) acb_sin_pi(r3, r3, prec1); else acb_sin(r3, r3, prec1); acb_mul(z2, z2, r3, prec1); acb_mul(z2, z2, n, prec1); acb_elliptic_e_inc(r3, z1, n, times_pi, prec1); acb_sub(z2, z2, r3, prec1); acb_sub_ui(r3, n, 1, prec1); acb_div(r2, z2, r3, prec1); if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap Pi(n,z,n)\n\n"); flint_printf("times_pi = %d\n\n", times_pi); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } acb_clear(z1); acb_clear(z2); acb_clear(n); acb_clear(m); acb_clear(r1); acb_clear(r2); acb_clear(r3); acb_clear(t); arb_clear(pi); fmpz_clear(k); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-rc1.c000066400000000000000000000034141461254215100201070ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_elliptic_rc1, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, r1, r2, a, b, c; acb_init(x); acb_init(r1); acb_init(r2); acb_init(a); acb_init(b); acb_init(c); acb_randtest(x, state, 1 + n_randint(state, 300), 10); acb_randtest(a, state, 1 + n_randint(state, 300), 10); acb_add(r2, x, a, 200); acb_sub(r2, r2, a, 200); acb_neg(r2, r2); if (n_randint(state, 2)) acb_swap(x, r2); acb_elliptic_rc1(r1, x, 2 + n_randint(state, 200)); acb_one(a); acb_set_d(b, 0.5); acb_set_d(c, 1.5); acb_hypgeom_2f1(r2, a, b, c, r2, 0, 20 + n_randint(state, 200)); if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(r1); acb_clear(r2); acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-rf.c000066400000000000000000000046771461254215100200450ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" TEST_FUNCTION_START(acb_elliptic_rf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, z, r1, r2; slong prec1, prec2; prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); acb_init(x); acb_init(y); acb_init(z); acb_init(r1); acb_init(r2); acb_randtest_special(x, state, 1 + n_randint(state, 300), 1 + n_randint(state, 100)); acb_randtest_special(y, state, 1 + n_randint(state, 300), 1 + n_randint(state, 100)); acb_randtest_special(z, state, 1 + n_randint(state, 300), 1 + n_randint(state, 100)); acb_elliptic_rf(r1, x, y, z, 0, prec1); switch (n_randint(state, 6)) { case 0: acb_elliptic_rf(r2, x, y, z, 0, prec2); break; case 1: acb_elliptic_rf(r2, x, z, y, 0, prec2); break; case 2: acb_elliptic_rf(r2, y, x, z, 0, prec2); break; case 3: acb_elliptic_rf(r2, y, z, x, 0, prec2); break; case 4: acb_elliptic_rf(r2, z, x, y, 0, prec2); break; default: acb_elliptic_rf(r2, z, y, x, 0, prec2); break; } if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(z); acb_clear(r1); acb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-rg.c000066400000000000000000000111311461254215100200250ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif /* Test input from Carlson's paper and checked with mpmath. */ static const double testdata_rg[7][8] = { {0.0, 0.0, 16.0, 0.0, 16.0, 0.0, 3.1415926535897932385, 0.0}, {2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 1.7255030280692277601, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.4236065423969895433, 0.0}, {-1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.44660591677018372657, 0.70768352357515390073}, {0.0, -1.0, -1.0, 1.0, 0.0, 1.0, 0.36023392184473309034, 0.40348623401722113741}, {0.0, 0.0, 0.0796, 0.0, 4.0, 0.0, 1.0284758090288040022, 0.0}, /* more tests */ {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, }; TEST_FUNCTION_START(acb_elliptic_rg, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, z, r1, r2; slong prec1, prec2; prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); acb_init(x); acb_init(y); acb_init(z); acb_init(r1); acb_init(r2); if (iter == 0) { slong k; for (k = 0; k < 7; k++) { acb_set_d_d(x, testdata_rg[k][0], testdata_rg[k][1]); acb_set_d_d(y, testdata_rg[k][2], testdata_rg[k][3]); acb_set_d_d(z, testdata_rg[k][4], testdata_rg[k][5]); acb_set_d_d(r2, testdata_rg[k][6], testdata_rg[k][7]); mag_set_d(arb_radref(acb_realref(r2)), 1e-14 * fabs(testdata_rg[k][6])); mag_set_d(arb_radref(acb_imagref(r2)), 1e-14 * fabs(testdata_rg[k][7])); for (prec1 = 16; prec1 <= 256; prec1 *= 2) { acb_elliptic_rg(r1, x, y, z, 0, prec1); if (!acb_overlaps(r1, r2) || acb_rel_accuracy_bits(r1) < prec1 * 0.9 - 10) { flint_printf("FAIL: overlap (testdata rg)\n\n"); flint_printf("prec = %wd, accuracy = %wd\n\n", prec1, acb_rel_accuracy_bits(r1)); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } } } acb_randtest(x, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_randtest(y, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_randtest(z, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_elliptic_rg(r1, x, y, z, 0, prec1); switch (n_randint(state, 6)) { case 0: acb_elliptic_rg(r2, x, y, z, 0, prec2); break; case 1: acb_elliptic_rg(r2, x, z, y, 0, prec2); break; case 2: acb_elliptic_rg(r2, y, x, z, 0, prec2); break; case 3: acb_elliptic_rg(r2, y, z, x, 0, prec2); break; case 4: acb_elliptic_rg(r2, z, x, y, 0, prec2); break; default: acb_elliptic_rg(r2, z, y, x, 0, prec2); break; } if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(y); acb_clear(z); acb_clear(r1); acb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-rj.c000066400000000000000000000227511461254215100200420ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_elliptic.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif /* Test input from Carlson's paper and checked with mpmath. */ static const double testdata_rj[16][10] = { {0.0, 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.77688623778582332014, 0.0}, {2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 5.0, 0.0, 0.14297579667156753833, 0.0}, {2.0, 0.0, 3.0, 0.0, 4.0, 0.0, -1.0, 1.0, 0.13613945827770535204, -0.3820756162442716425}, {0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 2.0, 0.0, 1.6490011662710884518, 0.0}, {-1.0, 1.0, -1.0, -1.0, 1.0, 0.0, 2.0, 0.0, 0.94148358841220238083, 0.0}, {0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0, -1.0, 1.8260115229009316249, 1.22906619086434715}, {-1.0, 1.0, -1.0, -1.0, 1.0, 0.0, -3.0, 1.0, -0.61127970812028172124, -1.068403839000680788}, {-1.0, 1.0, -2.0, -1.0, 0.0, -1.0, -1.0, 1.0, 1.8249027393703805305, -1.2218475784827035855}, /* additional tests where Carlson's algorithm may not be valid */ {-1.0, -0.5, -10.0, -6.0, -10.0, -3.0, -5.0, 10.0, 0.128470516743927699, 0.102175950778504625}, {1.987, 0.0, 4.463, -1.614, 0.0, 0.0, -3.965, 0.0, -0.341575118513811305, -0.394703757004268486}, {0.3068, 0.0, -4.037, 0.632, 1.654, 0.0, -0.9609, 0.0, -1.14735199581485639, -0.134450158867472264}, {0.3068, 0.0, -4.037, -0.632, 1.654, 0.0, -0.9609, 0.0, 1.758765901861727, -0.161002343366626892}, {0.3068, 0.0, -4.037, 0.0632, 1.654, 0.0, -0.9609, 0.0, -1.17157627949475577, -0.069182614173988811}, {0.3068, 0.0, -4.037, -0.0632, 1.654, 0.0, -0.9609, 0.0, 1.77940452391261626, 0.0388711305592447234}, {0.3068, 0.0, -4.037, 0.00632, 1.654, 0.0, -0.9609, 0.0, -1.17337595670549633, -0.0623069224526925}, {0.3068, 0.0, -4.037, -0.00632, 1.654, 0.0, -0.9609, 0.0, 1.77806722756403055, 0.0592749824572262329}, }; static const double testdata_rd[6][8] = { {0.0, 0.0, 2.0, 0.0, 1.0, 0.0, 1.7972103521033883112, 0.0}, {2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 0.16510527294261053349, 0.0}, {0.0, 1.0, 0.0, -1.0, 2.0, 0.0, 0.65933854154219768919, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 1.2708196271909686299, 2.7811120159520578776}, {0.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.8577235439239060056, -0.96193450888838559989}, {-2.0, -1.0, 0.0, -1.0, -1.0, 1.0, 1.8249027393703805305, -1.2218475784827035855}, }; TEST_FUNCTION_START(acb_elliptic_rj, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, y, z, p, r1, r2; slong prec1, prec2; prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); acb_init(x); acb_init(y); acb_init(z); acb_init(p); acb_init(r1); acb_init(r2); if (iter == 0) { slong k; for (k = 0; k < 16; k++) { acb_set_d_d(x, testdata_rj[k][0], testdata_rj[k][1]); acb_set_d_d(y, testdata_rj[k][2], testdata_rj[k][3]); acb_set_d_d(z, testdata_rj[k][4], testdata_rj[k][5]); acb_set_d_d(p, testdata_rj[k][6], testdata_rj[k][7]); acb_set_d_d(r2, testdata_rj[k][8], testdata_rj[k][9]); mag_set_d(arb_radref(acb_realref(r2)), 1e-14 * fabs(testdata_rj[k][8])); mag_set_d(arb_radref(acb_imagref(r2)), 1e-14 * fabs(testdata_rj[k][9])); for (prec1 = 16; prec1 <= 256; prec1 *= 2) { acb_elliptic_rj(r1, x, y, z, p, 0, prec1); if (!acb_overlaps(r1, r2) || (k < 8 && acb_rel_accuracy_bits(r1) < prec1 - 12)) { flint_printf("FAIL: overlap (testdata rj)\n\n"); flint_printf("prec = %wd, accuracy = %wd\n\n", prec1, acb_rel_accuracy_bits(r1)); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("p = "); acb_printd(p, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } } for (k = 0; k < 6; k++) { acb_set_d_d(x, testdata_rd[k][0], testdata_rd[k][1]); acb_set_d_d(y, testdata_rd[k][2], testdata_rd[k][3]); acb_set_d_d(z, testdata_rd[k][4], testdata_rd[k][5]); acb_set_d_d(r2, testdata_rd[k][6], testdata_rd[k][7]); mag_set_d(arb_radref(acb_realref(r2)), 1e-14 * fabs(testdata_rd[k][6])); mag_set_d(arb_radref(acb_imagref(r2)), 1e-14 * fabs(testdata_rd[k][7])); for (prec1 = 16; prec1 <= 256; prec1 *= 2) { acb_elliptic_rj(r1, x, y, z, z, 0, prec1); if (!acb_overlaps(r1, r2) || acb_rel_accuracy_bits(r1) < prec1 - 12) { flint_printf("FAIL: overlap (testdata rd)\n\n"); flint_printf("prec = %wd, accuracy = %wd\n\n", prec1, acb_rel_accuracy_bits(r1)); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } } } acb_randtest(x, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_randtest(y, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_randtest(z, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); acb_set(p, z); /* Potentially slow general tests */ if ((arb_is_nonnegative(acb_realref(x)) && arb_is_nonnegative(acb_realref(y)) && arb_is_nonnegative(acb_realref(z)) && arb_is_positive(acb_realref(p))) || (n_randint(state, 10) == 0 && prec1 < 100 && prec2 < 100)) { acb_elliptic_rj(r1, x, y, z, z, 0, prec1); acb_elliptic_rj(r2, x, y, z, p, 0, prec2); if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap R_D\n\n"); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("p = "); acb_printd(p, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } acb_randtest(p, state, 1 + n_randint(state, 300), 1 + n_randint(state, 30)); /* Specialize */ if (n_randint(state, 2)) { if (arb_is_zero(acb_imagref(y))) arb_one(acb_imagref(y)); acb_conj(z, y); arb_zero(acb_imagref(x)); arb_abs(acb_realref(x), acb_realref(x)); } acb_elliptic_rj(r1, x, y, z, p, 0, prec1); switch (n_randint(state, 6)) { case 0: acb_elliptic_rj(r2, x, y, z, p, 0, prec2); break; case 1: acb_elliptic_rj(r2, x, z, y, p, 0, prec2); break; case 2: acb_elliptic_rj(r2, y, x, z, p, 0, prec2); break; case 3: acb_elliptic_rj(r2, y, z, x, p, 0, prec2); break; case 4: acb_elliptic_rj(r2, z, x, y, p, 0, prec2); break; default: acb_elliptic_rj(r2, z, y, x, p, 0, prec2); break; } if (!acb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("p = "); acb_printd(p, 30); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } acb_clear(x); acb_clear(y); acb_clear(z); acb_clear(p); acb_clear(r1); acb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_elliptic/test/t-sigma.c000066400000000000000000000126121461254215100205220ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" #include "acb_elliptic.h" #define NUM_TESTS 6 #define EPS 1e-13 /* z, tau, sigma(z, tau) checked with Mathematica: N[{z, tau, WeierstrassSigma[z, WeierstrassInvariants[{1, tau}/2]]}, 20] */ /* testdata is defined in t-sigma.c and t-zeta.c */ #define testdata testdata0 const double testdata[NUM_TESTS][6] = { { 1.4142135623730950488, 1.7320508075688772935, 2.2360679774997896964, 2.6457513110645905905, 3.2497809387982239642, -6.2896427497987532326 }, { -1.0, -2.0, -1.0, 3.0, -0.17877885105742438172, 0.58508579024326876042 }, { 0.1, 0.0, 0.6, 0.2, 0.100055263033144515447, -0.000188998253739903104 }, { 0.0, 0.2, 0.2, 0.1, -0.05083547794781899013, 0.19409530512485630787 }, { 0.5, 0.0, 0.333333333333333333, 20.0, 0.48022700051193809297, 0.0 }, { 0.6666666666666667, 1.0, -3.1415926535897932385, 1.0, 1.3092907491438550394, 0.9063920053572463817 } }; /* acb_set_dddd is defined in t-sigma.c and t-zeta.c */ #ifndef acb_set_dddd #define acb_set_dddd acb_set_dddd static void acb_set_dddd(acb_t z, double a, double ar, double b, double br) { arf_set_d(arb_midref(acb_realref(z)), a); mag_set_d(arb_radref(acb_realref(z)), ar); arf_set_d(arb_midref(acb_imagref(z)), b); mag_set_d(arb_radref(acb_imagref(z)), br); } #endif TEST_FUNCTION_START(acb_elliptic_sigma, state) { slong iter; /* check test values */ for (iter = 0; iter < 20 * 0.1 * flint_test_multiplier(); iter++) { slong i; acb_t z, tau, p1, p2; acb_init(z); acb_init(tau); acb_init(p1); acb_init(p2); for (i = 0; i < NUM_TESTS; i++) { acb_set_dddd(z, testdata[i][0], 0.0, testdata[i][1], 0.0); acb_set_dddd(tau, testdata[i][2], 0.0, testdata[i][3], 0.0); acb_set_dddd(p2, testdata[i][4], EPS, testdata[i][5], EPS); acb_elliptic_sigma(p1, z, tau, 2 + n_randint(state, 400)); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (test value)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(z); acb_clear(tau); acb_clear(p1); acb_clear(p2); } /* Test periods */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z1, z2, e1, e2, p1, p2, t, u; slong m, n, e0, prec0, prec1, prec2; acb_init(tau); acb_init(z1); acb_init(z2); acb_init(e1); acb_init(e2); acb_init(p1); acb_init(p2); acb_init(t); acb_init(u); e0 = 1 + n_randint(state, 10); prec0 = 2 + n_randint(state, 400); prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); acb_randtest(tau, state, prec0, e0); if (arf_sgn(arb_midref(acb_imagref(tau))) < 0) acb_neg(tau, tau); acb_one(e1); acb_mul_2exp_si(e1, e1, -1); acb_elliptic_zeta(e1, e1, tau, prec0); acb_mul_2exp_si(e2, tau, -1); acb_elliptic_zeta(e2, e2, tau, prec0); acb_randtest(z1, state, prec0, e0); acb_randtest(p1, state, prec0, e0); acb_randtest(p2, state, prec0, e0); /* z2 = z1 + m + n*tau */ m = n_randint(state, 10); n = n_randint(state, 10); acb_add_ui(z2, z1, m, prec0); acb_addmul_ui(z2, tau, n, prec0); /* sigma(z + m + n*tau) = (-1)^(m+n+mn) exp((m e1 + n e2)(m + n tau + 2z) sigma(z) */ acb_elliptic_sigma(p1, z1, tau, prec1); acb_elliptic_sigma(p2, z2, tau, prec2); acb_mul_ui(t, e1, m, prec2); acb_addmul_ui(t, e2, n, prec2); acb_mul_2exp_si(u, z1, 1); acb_addmul_ui(u, tau, n, prec2); acb_add_ui(u, u, m, prec2); acb_mul(t, t, u, prec2); acb_neg(t, t); acb_exp(t, t, prec2); if ((m + n + m*n) % 2 == 1) acb_neg(t, t); acb_mul(p2, p2, t, prec2); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z1); acb_clear(z2); acb_clear(e1); acb_clear(e2); acb_clear(p1); acb_clear(p2); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } #undef testdata flint-3.1.3/src/acb_elliptic/test/t-zeta.c000066400000000000000000000134551461254215100203730ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" #include "acb_elliptic.h" #define NUM_TESTS 6 #define EPS 1e-13 /* z, tau, zeta(z, tau) checked with Mathematica: N[{z, tau, WeierstrassZeta[z, WeierstrassInvariants[{1, tau}/2]]}, 20] */ /* testdata is defined in t-sigma.c and t-zeta.c */ #define testdata testdata1 const double testdata[NUM_TESTS][6] = { { 1.4142135623730950488, 1.7320508075688772935, 2.2360679774997896964, 2.6457513110645905905, 4.6708530542187465956, 2.5654839019069906619 }, { -3.0, -2.0, -7.0, 3.0, -9.8696028584909729616, -3.4498761151331612449 }, { 0.1, 0.0, 0.6, 0.2, 10.0222822996630537305, -0.0754856899565257555 }, { 0.0, 0.1, 0.6, 0.2, -0.0754856899565257555, -10.0222822996630537305 }, { 0.5, 0.0, 0.333333333333333333, 20.0, 1.6449340668482264365, 0.0 }, { 3.6666666666666667, 2014.0, -3.1415926535897932385, 0.1, -147965.49261828128352, -10426.83705290890375 } }; /* acb_set_dddd is defined in t-sigma.c and t-zeta.c */ #ifndef acb_set_dddd #define acb_set_dddd acb_set_dddd static void acb_set_dddd(acb_t z, double a, double ar, double b, double br) { arf_set_d(arb_midref(acb_realref(z)), a); mag_set_d(arb_radref(acb_realref(z)), ar); arf_set_d(arb_midref(acb_imagref(z)), b); mag_set_d(arb_radref(acb_imagref(z)), br); } #endif TEST_FUNCTION_START(acb_elliptic_zeta, state) { slong iter; /* check test values */ for (iter = 0; iter < 20 * 0.1 * flint_test_multiplier(); iter++) { slong i; acb_t z, tau, p1, p2; acb_init(z); acb_init(tau); acb_init(p1); acb_init(p2); for (i = 0; i < NUM_TESTS; i++) { acb_set_dddd(z, testdata[i][0], 0.0, testdata[i][1], 0.0); acb_set_dddd(tau, testdata[i][2], 0.0, testdata[i][3], 0.0); if (i == NUM_TESTS - 1) /* sensitive to rounding errors in doubles */ acb_set_dddd(p2, testdata[i][4], 1e-6, testdata[i][5], 1e-6); else acb_set_dddd(p2, testdata[i][4], EPS, testdata[i][5], EPS); acb_elliptic_zeta(p1, z, tau, 2 + n_randint(state, 400)); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (test value)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } acb_elliptic_zeta(p2, z, tau, 2 + n_randint(state, 800)); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (test value 2)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(z); acb_clear(tau); acb_clear(p1); acb_clear(p2); } /* Test periods */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z1, z2, e1, e2, p1, p2; slong m, n, e0, prec0, prec1, prec2; acb_init(tau); acb_init(z1); acb_init(z2); acb_init(e1); acb_init(e2); acb_init(p1); acb_init(p2); e0 = 1 + n_randint(state, 10); prec0 = 2 + n_randint(state, 400); prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); acb_randtest(tau, state, prec0, e0); if (arf_sgn(arb_midref(acb_imagref(tau))) < 0) acb_neg(tau, tau); acb_one(e1); acb_mul_2exp_si(e1, e1, -1); acb_elliptic_zeta(e1, e1, tau, prec0); acb_mul_2exp_si(e2, tau, -1); acb_elliptic_zeta(e2, e2, tau, prec0); acb_mul_2exp_si(e1, e1, 1); acb_mul_2exp_si(e2, e2, 1); acb_randtest(z1, state, prec0, e0); acb_randtest(p1, state, prec0, e0); acb_randtest(p2, state, prec0, e0); /* z2 = z1 + m + n*tau */ m = n_randint(state, 10); n = n_randint(state, 10); acb_add_ui(z2, z1, m, prec0); acb_addmul_ui(z2, tau, n, prec0); /* zeta(z + 1) = zeta(z) + 2 zeta(1) */ /* zeta(z + tau) = zeta(z) + 2 zeta(tau) */ acb_elliptic_zeta(p1, z1, tau, prec1); acb_elliptic_zeta(p2, z2, tau, prec2); acb_submul_ui(p2, e1, m, prec2); acb_submul_ui(p2, e2, n, prec2); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z1); acb_clear(z2); acb_clear(e1); acb_clear(e2); acb_clear(p1); acb_clear(p2); } TEST_FUNCTION_END(state); } #undef testdata1 flint-3.1.3/src/acb_elliptic/zeta.c000066400000000000000000000042711461254215100171470ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_elliptic.h" #include "acb_modular.h" /* eta1 = (-1/6) theta1'''(0) / theta1'(0) */ static void eta1(acb_t res, acb_t theta1, const acb_t tau, slong prec) { acb_ptr theta; acb_t z; acb_init(z); theta = _acb_vec_init(16); acb_modular_theta_jet(theta, theta + 4, theta + 8, theta + 12, z, tau, 4, prec); if (theta1 != NULL) acb_set(theta1, theta + 1); acb_div(res, theta + 3, theta + 1, prec); acb_neg(res, res); _acb_vec_clear(theta, 16); acb_clear(z); } /* zeta(z) = 2 eta1 z + theta1'(z,q) / theta1(z,q) */ void acb_elliptic_zeta(acb_t res, const acb_t z, const acb_t tau, slong prec) { acb_ptr t; int real; real = acb_is_real(z) && arb_is_int_2exp_si(acb_realref(tau), -1) && arb_is_positive(acb_imagref(tau)); t = _acb_vec_init(8); acb_modular_theta_jet(t, t + 2, t + 4, t + 6, z, tau, 2, prec); eta1(t + 2, NULL, tau, prec); acb_mul_2exp_si(t + 2, t + 2, 1); acb_mul(t + 2, t + 2, z, prec); acb_div(t, t + 1, t, prec); acb_add(res, t, t + 2, prec); if (real) arb_zero(acb_imagref(res)); _acb_vec_clear(t, 8); } /* sigma(z) = exp(eta1 z^2) theta1(z) / theta1'(0) */ void acb_elliptic_sigma(acb_t res, const acb_t z, const acb_t tau, slong prec) { acb_ptr t; int real; real = acb_is_real(z) && arb_is_int_2exp_si(acb_realref(tau), -1) && arb_is_positive(acb_imagref(tau)); t = _acb_vec_init(8); acb_modular_theta_jet(t, t + 2, t + 4, t + 6, z, tau, 2, prec); eta1(t + 2, t + 3, tau, prec); acb_mul(t + 4, z, z, prec); acb_mul(t + 2, t + 2, t + 4, prec); acb_exp(t + 2, t + 2, prec); acb_div(t, t, t + 3, prec); acb_mul(res, t, t + 2, prec); if (real) arb_zero(acb_imagref(res)); _acb_vec_clear(t, 8); } flint-3.1.3/src/acb_hypgeom.h000066400000000000000000000402211461254215100160470ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_HYPGEOM_H #define ACB_HYPGEOM_H #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif void acb_hypgeom_rising_ui_forward(acb_t res, const acb_t x, ulong n, slong prec); void acb_hypgeom_rising_ui_rs(acb_t res, const acb_t x, ulong n, ulong m, slong prec); void acb_hypgeom_rising_ui_bs(acb_t res, const acb_t x, ulong n, slong prec); void acb_hypgeom_rising_ui_rec(acb_t res, const acb_t x, ulong n, slong prec); void acb_hypgeom_rising_ui(acb_t y, const acb_t x, ulong n, slong prec); void acb_hypgeom_rising(acb_t y, const acb_t x, const acb_t n, slong prec); void acb_hypgeom_rising_ui_jet_powsum(acb_ptr res, const acb_t x, ulong n, slong len, slong prec); void acb_hypgeom_rising_ui_jet_rs(acb_ptr res, const acb_t x, ulong n, ulong m, slong len, slong prec); void acb_hypgeom_rising_ui_jet_bs(acb_ptr res, const acb_t x, ulong n, slong len, slong prec); void acb_hypgeom_rising_ui_jet(acb_ptr res, const acb_t x, ulong n, slong len, slong prec); void acb_hypgeom_log_rising_ui_jet(acb_ptr res, const acb_t z, ulong r, slong len, slong prec); void acb_hypgeom_log_rising_ui(acb_ptr res, const acb_t z, ulong r, slong prec); void acb_hypgeom_gamma_stirling_sum_horner(acb_t s, const acb_t z, slong N, slong prec); void acb_hypgeom_gamma_stirling_sum_improved(acb_t s, const acb_t z, slong N, slong K, slong prec); void acb_hypgeom_gamma_stirling(acb_t res, const acb_t x, int reciprocal, slong prec); int acb_hypgeom_gamma_taylor(acb_t res, const acb_t x, int reciprocal, slong prec); void acb_hypgeom_gamma(acb_t y, const acb_t x, slong prec); void acb_hypgeom_rgamma(acb_t y, const acb_t x, slong prec); void acb_hypgeom_lgamma(acb_t y, const acb_t x, slong prec); void acb_hypgeom_pfq_bound_factor(mag_t C, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, ulong n); slong acb_hypgeom_pfq_choose_n(acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong prec); void acb_hypgeom_pfq_sum_forward(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec); void acb_hypgeom_pfq_sum_rs(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec); void acb_hypgeom_pfq_sum_bs(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec); void acb_hypgeom_pfq_sum_fme(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec); void acb_hypgeom_pfq_sum(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec); void acb_hypgeom_pfq_sum_bs_invz(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec); void acb_hypgeom_pfq_sum_invz(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, const acb_t zinv, slong n, slong prec); void acb_hypgeom_pfq_direct(acb_t res, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec); slong acb_hypgeom_pfq_series_choose_n(const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, slong len, slong prec); void acb_hypgeom_pfq_series_sum_forward(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec); void acb_hypgeom_pfq_series_sum_bs(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec); void acb_hypgeom_pfq_series_sum_rs(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec); void acb_hypgeom_pfq_series_sum(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec); void acb_hypgeom_pfq_series_direct(acb_poly_t res, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec); void acb_hypgeom_pfq(acb_t res, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, int regularized, slong prec); void acb_hypgeom_u_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong n, slong prec); void acb_hypgeom_u_1f1_series(acb_poly_t res, const acb_poly_t a, const acb_poly_t b, const acb_poly_t z, slong len, slong prec); void acb_hypgeom_u_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec); void acb_hypgeom_u(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec); int acb_hypgeom_u_use_asymp(const acb_t z, slong prec); void acb_hypgeom_m_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void acb_hypgeom_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_j_asymp(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_j(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_i_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec); void acb_hypgeom_bessel_i_asymp(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec); void acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_i_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_k_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec); void acb_hypgeom_bessel_k_0f1_series(acb_poly_t res, const acb_poly_t n, const acb_poly_t z, int scaled, slong len, slong prec); void acb_hypgeom_bessel_k_asymp(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec); void acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_k_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_y(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_jy(acb_t res1, acb_t res2, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_0f1_asymp(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec); void acb_hypgeom_0f1_direct(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec); void acb_hypgeom_0f1(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec); void acb_hypgeom_airy_bound(mag_t ai, mag_t aip, mag_t bi, mag_t bip, const acb_t z); void acb_hypgeom_airy_asymp(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong n, slong prec); void acb_hypgeom_airy_direct(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong n, slong prec); void acb_hypgeom_airy(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong prec); void acb_hypgeom_airy_jet(acb_ptr ai, acb_ptr bi, const acb_t z, slong len, slong prec); void _acb_hypgeom_airy_series(acb_ptr ai, acb_ptr ai_prime, acb_ptr bi, acb_ptr bi_prime, acb_srcptr z, slong zlen, slong len, slong prec); void acb_hypgeom_airy_series(acb_poly_t ai, acb_poly_t ai_prime, acb_poly_t bi, acb_poly_t bi_prime, const acb_poly_t z, slong len, slong prec); void acb_hypgeom_coulomb(acb_t F, acb_t G, acb_t Hpos, acb_t Hneg, const acb_t l, const acb_t eta, const acb_t z, slong prec); void acb_hypgeom_coulomb_jet(acb_ptr F, acb_ptr G, acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta, const acb_t z, slong len, slong prec); void _acb_hypgeom_coulomb_series(acb_ptr F, acb_ptr G, acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta, acb_srcptr z, slong zlen, slong len, slong prec); void acb_hypgeom_coulomb_series(acb_poly_t F, acb_poly_t G, acb_poly_t Hpos, acb_poly_t Hneg, const acb_t l, const acb_t eta, const acb_poly_t z, slong len, slong prec); void acb_hypgeom_gamma_upper_asymp(acb_t res, const acb_t s, const acb_t z, int modified, slong prec); void acb_hypgeom_gamma_upper_1f1a(acb_t res, const acb_t s, const acb_t z, int modified, slong prec); void acb_hypgeom_gamma_upper_1f1b(acb_t res, const acb_t s, const acb_t z, int modified, slong prec); void acb_hypgeom_gamma_upper_singular(acb_t res, slong s, const acb_t z, int modified, slong prec); void acb_hypgeom_gamma_upper(acb_t res, const acb_t s, const acb_t z, int modified, slong prec); void _acb_hypgeom_gamma_upper_series(acb_ptr g, const acb_t s, acb_srcptr h, slong hlen, int regularized, slong n, slong prec); void acb_hypgeom_gamma_upper_series(acb_poly_t g, const acb_t s, const acb_poly_t h, int regularized, slong n, slong prec); void acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int modified, slong prec); void _acb_hypgeom_gamma_lower_series(acb_ptr g, const acb_t s, acb_srcptr h, slong hlen, int regularized, slong n, slong prec); void acb_hypgeom_gamma_lower_series(acb_poly_t g, const acb_t s, const acb_poly_t h, int regularized, slong n, slong prec); void acb_hypgeom_beta_lower(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void _acb_hypgeom_beta_lower_series(acb_ptr res, const acb_t a, const acb_t b, acb_srcptr z, slong zlen, int regularized, slong len, slong prec); void acb_hypgeom_beta_lower_series(acb_poly_t res, const acb_t a, const acb_t b, const acb_poly_t z, int regularized, slong len, slong prec); void acb_hypgeom_expint(acb_t res, const acb_t s, const acb_t z, slong prec); void acb_hypgeom_erf_propagated_error(mag_t re, mag_t im, const acb_t z); void acb_hypgeom_erf_1f1a(acb_t res, const acb_t z, slong prec); void acb_hypgeom_erf_1f1b(acb_t res, const acb_t z, slong prec); void acb_hypgeom_erf_asymp(acb_t res, const acb_t z, int complementary, slong prec, slong prec2); void acb_hypgeom_erf(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_erf_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_erf_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_erfc(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_erfc_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_erfc_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_erfi(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_erfi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_erfi_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_fresnel(acb_t res1, acb_t res2, const acb_t z, int normalized, slong prec); void _acb_hypgeom_fresnel_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, int normalized, slong len, slong prec); void acb_hypgeom_fresnel_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, int normalized, slong len, slong prec); void acb_hypgeom_ei_asymp(acb_t res, const acb_t z, slong prec); void acb_hypgeom_ei_2f2(acb_t res, const acb_t z, slong prec); void acb_hypgeom_ei(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_ei_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_ei_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_si_asymp(acb_t res, const acb_t z, slong prec); void acb_hypgeom_si_1f2(acb_t res, const acb_t z, slong prec); void acb_hypgeom_si(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_si_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_si_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_ci_asymp(acb_t res, const acb_t z, slong prec); void acb_hypgeom_ci_2f3(acb_t res, const acb_t z, slong prec); void acb_hypgeom_ci(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_ci_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_ci_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_shi(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_shi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_shi_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_chi_asymp(acb_t res, const acb_t z, slong prec); void acb_hypgeom_chi_2f3(acb_t res, const acb_t z, slong prec); void acb_hypgeom_chi(acb_t res, const acb_t z, slong prec); void _acb_hypgeom_chi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_hypgeom_chi_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec); void acb_hypgeom_li(acb_t res, const acb_t z, int offset, slong prec); void _acb_hypgeom_li_series(acb_ptr g, acb_srcptr h, slong hlen, int offset, slong len, slong prec); void acb_hypgeom_li_series(acb_poly_t g, const acb_poly_t h, int offset, slong len, slong prec); void acb_hypgeom_2f1_continuation(acb_t res0, acb_t res1, const acb_t a, const acb_t b, const acb_t c, const acb_t z0, const acb_t z1, const acb_t f0, const acb_t f1, slong prec); void acb_hypgeom_2f1_series_direct(acb_poly_t res, const acb_poly_t a, const acb_poly_t b, const acb_poly_t c, const acb_poly_t z, int regularized, slong len, slong prec); void acb_hypgeom_2f1_direct(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, slong prec); void acb_hypgeom_2f1_transform(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, int which, slong prec); void acb_hypgeom_2f1_transform_limit(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, int which, slong prec); void acb_hypgeom_2f1_corner(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, slong prec); int acb_hypgeom_2f1_choose(const acb_t z); void acb_hypgeom_2f1(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, slong prec); #define ACB_HYPGEOM_2F1_REGULARIZED 1 #define ACB_HYPGEOM_2F1_AB 2 /* a-b integer */ #define ACB_HYPGEOM_2F1_AC 4 /* a-c integer */ #define ACB_HYPGEOM_2F1_BC 8 /* b-c integer */ #define ACB_HYPGEOM_2F1_ABC 16 /* a+b-c integer */ void acb_hypgeom_legendre_p_uiui_rec(acb_t res, ulong n, ulong m, const acb_t z, slong prec); void acb_hypgeom_legendre_p(acb_t res, const acb_t n, const acb_t m, const acb_t z, int type, slong prec); void acb_hypgeom_legendre_q(acb_t res, const acb_t n, const acb_t m, const acb_t z, int type, slong prec); void acb_hypgeom_jacobi_p(acb_t res, const acb_t n, const acb_t a, const acb_t b, const acb_t z, slong prec); void acb_hypgeom_gegenbauer_c(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec); void acb_hypgeom_laguerre_l(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec); void acb_hypgeom_hermite_h(acb_t res, const acb_t n, const acb_t z, slong prec); void acb_hypgeom_chebyshev_t(acb_t res, const acb_t n, const acb_t z, slong prec); void acb_hypgeom_chebyshev_u(acb_t res, const acb_t n, const acb_t z, slong prec); void acb_hypgeom_spherical_y(acb_t res, slong n, slong m, const acb_t theta, const acb_t phi, slong prec); void acb_hypgeom_dilog_bernoulli(acb_t res, const acb_t z, slong prec); void acb_hypgeom_dilog_continuation(acb_t res, const acb_t a, const acb_t z, slong prec); void acb_hypgeom_dilog_bitburst(acb_t res, acb_t z0, const acb_t z, slong prec); void acb_hypgeom_dilog_transform(acb_t res, const acb_t z, int algorithm, slong prec); void acb_hypgeom_dilog_zero_taylor(acb_t res, const acb_t z, slong prec); void acb_hypgeom_dilog_zero(acb_t res, const acb_t z, slong prec); void acb_hypgeom_dilog(acb_t res, const acb_t z, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_hypgeom/000077500000000000000000000000001461254215100156775ustar00rootroot00000000000000flint-3.1.3/src/acb_hypgeom/0f1.c000066400000000000000000000065711461254215100164420ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_0f1_asymp(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec) { acb_t t, u, v; int neg; acb_init(t); acb_init(u); acb_init(v); /* both expansions are correct, but we want the one that works better on the real line */ neg = arf_sgn(arb_midref(acb_realref(z))) < 0; if (neg) acb_neg(t, z); else acb_set(t, z); acb_sqrt(t, t, prec); acb_mul_2exp_si(v, t, 1); acb_sub_ui(u, a, 1, prec); if (neg) acb_hypgeom_bessel_j_asymp(v, u, v, prec); else acb_hypgeom_bessel_i_asymp(v, u, v, 0, prec); acb_neg(u, u); acb_pow(t, t, u, prec); acb_mul(v, v, t, prec); if (!regularized) { acb_gamma(t, a, prec); acb_mul(v, v, t, prec); } acb_set(res, v); acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_0f1_direct(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec) { if (regularized) { if (acb_is_int(a) && arf_sgn(arb_midref(acb_realref(a))) <= 0) { acb_t t, u; acb_init(t); acb_init(u); acb_sub_ui(t, a, 2, prec); acb_neg(t, t); acb_sub_ui(u, a, 1, prec); acb_neg(u, u); acb_pow(u, z, u, prec); /* this cannot recurse infinitely, because t will either be an exact positive integer, or inexact */ acb_hypgeom_0f1_direct(res, t, z, regularized, prec); acb_mul(res, res, u, prec); acb_clear(t); acb_clear(u); } else /* todo: could skip when a=1 or a=2 */ { acb_t t; acb_init(t); acb_rgamma(t, a, prec); acb_hypgeom_0f1_direct(res, a, z, 0, prec); acb_mul(res, res, t, prec); acb_clear(t); } } else { acb_struct bb[2]; bb[0] = *a; acb_init(bb + 1); acb_one(bb + 1); acb_hypgeom_pfq_direct(res, NULL, 0, bb, 2, z, -1, prec); acb_clear(bb + 1); } } int acb_hypgeom_0f1_use_asymp(const acb_t z, slong prec) { double x, y, c; if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 0) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0)) { return 0; } if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 0) > 128 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) > 128)) { return 1; } x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); c = prec * 0.69314718055994530942; c = c * c; c = c * c; return x * x + y * y > c; } void acb_hypgeom_0f1(acb_t res, const acb_t a, const acb_t z, int regularized, slong prec) { if (acb_hypgeom_0f1_use_asymp(z, prec)) acb_hypgeom_0f1_asymp(res, a, z, regularized, prec); else acb_hypgeom_0f1_direct(res, a, z, regularized, prec); } flint-3.1.3/src/acb_hypgeom/2f1.c000066400000000000000000000144531461254215100164420ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #include "arb_hypgeom.h" static void _acb_hypgeom_2f1r_reduced(acb_t res, const acb_t b, const acb_t c, const acb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_neg(u, b); acb_pow(t, t, u, prec); acb_rgamma(u, c, prec); acb_mul(t, t, u, prec); acb_set(res, t); acb_clear(t); acb_clear(u); return; } void acb_hypgeom_2f1_nointegration(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int flags, slong prec) { int algorithm, regularized; regularized = flags & ACB_HYPGEOM_2F1_REGULARIZED; if (!acb_is_finite(a) || !acb_is_finite(b) || !acb_is_finite(c) || !acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_is_zero(z)) { if (regularized) acb_rgamma(res, c, prec); else acb_one(res); return; } if (regularized && acb_is_int(c) && arb_is_nonpositive(acb_realref(c))) { if ((acb_is_int(a) && arb_is_nonpositive(acb_realref(a)) && arf_cmp(arb_midref(acb_realref(a)), arb_midref(acb_realref(c))) >= 0) || (acb_is_int(b) && arb_is_nonpositive(acb_realref(b)) && arf_cmp(arb_midref(acb_realref(b)), arb_midref(acb_realref(c))) >= 0)) { acb_zero(res); return; } } if (regularized && acb_eq(a, c)) { _acb_hypgeom_2f1r_reduced(res, b, c, z, prec); return; } if (regularized && acb_eq(b, c)) { _acb_hypgeom_2f1r_reduced(res, a, c, z, prec); return; } /* polynomial */ if (acb_is_int(a) && arf_sgn(arb_midref(acb_realref(a))) <= 0 && arf_cmpabs_ui(arb_midref(acb_realref(a)), prec) < 0) { acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec); return; } /* polynomial */ if (acb_is_int(b) && arf_sgn(arb_midref(acb_realref(b))) <= 0 && arf_cmpabs_ui(arb_midref(acb_realref(b)), prec) < 0) { acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec); return; } /* Try to reduce to a polynomial case using the Pfaff transformation */ /* TODO: look at flags for integer c-b, c-a here, even when c is nonexact */ if (acb_is_exact(c)) { acb_t t; acb_init(t); acb_sub(t, c, b, prec); if (acb_is_int(t) && arb_is_nonpositive(acb_realref(t))) { acb_hypgeom_2f1_transform(res, a, b, c, z, flags, 1, prec); acb_clear(t); return; } acb_sub(t, c, a, prec); if (acb_is_int(t) && arb_is_nonpositive(acb_realref(t))) { int f1, f2; /* When swapping a, b, also swap the flags. */ f1 = flags & ACB_HYPGEOM_2F1_AC; f2 = flags & ACB_HYPGEOM_2F1_BC; flags &= ~ACB_HYPGEOM_2F1_AC; flags &= ~ACB_HYPGEOM_2F1_BC; if (f1) flags |= ACB_HYPGEOM_2F1_BC; if (f2) flags |= ACB_HYPGEOM_2F1_AC; acb_hypgeom_2f1_transform(res, b, a, c, z, flags, 1, prec); acb_clear(t); return; } acb_clear(t); } /* special value at z = 1 */ if (acb_is_one(z)) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_sub(t, c, a, prec); acb_sub(u, c, b, prec); acb_sub(v, t, b, prec); if (arb_is_positive(acb_realref(v))) { acb_rgamma(t, t, prec); acb_rgamma(u, u, prec); acb_mul(t, t, u, prec); acb_gamma(v, v, prec); acb_mul(t, t, v, prec); if (!regularized) { acb_gamma(v, c, prec); acb_mul(t, t, v, prec); } acb_set(res, t); } else { acb_indeterminate(res); } acb_clear(t); acb_clear(u); acb_clear(v); return; } algorithm = acb_hypgeom_2f1_choose(z); if (algorithm == 0) { acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec); } else if (algorithm >= 1 && algorithm <= 5) { acb_hypgeom_2f1_transform(res, a, b, c, z, flags, algorithm, prec); } else { acb_hypgeom_2f1_corner(res, a, b, c, z, regularized, prec); } } void acb_hypgeom_2f1(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int flags, slong prec) { acb_t res2; slong acc, max, t; acb_init(res2); acb_hypgeom_2f1_nointegration(res2, a, b, c, z, flags, prec); acc = acb_rel_accuracy_bits(res2); if (acc < 0.5 * prec) { max = prec; t = acb_rel_accuracy_bits(z); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(a); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(b); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(c); max = FLINT_MIN(max, t); if (max > 2 && acc < 0.5 * max) { if (acb_is_real(a) && acb_is_real(b) && acb_is_real(c) && acb_is_real(z) && arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(c)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0) { arb_hypgeom_2f1_integration(acb_realref(res), acb_realref(a), acb_realref(b), acb_realref(c), acb_realref(z), flags, prec); arb_zero(acb_imagref(res)); if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) || (acb_is_finite(res) && !acb_is_finite(res2))) { acb_swap(res, res2); } } } } acb_swap(res, res2); acb_clear(res2); } flint-3.1.3/src/acb_hypgeom/2f1_choose.c000066400000000000000000000030061461254215100177720ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #define ALWAYS1 (0.25 * 0.25) #define ALWAYS2 (0.75 * 0.75) #define LIMIT (0.75 * 0.75) int acb_hypgeom_2f1_choose(const acb_t z) { double x, y; double mag[7]; int i, pick; x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); x = FLINT_MAX(FLINT_MIN(x, 1e10), -1e10); y = FLINT_MAX(FLINT_MIN(y, 1e10), -1e10); mag[0] = x*x + y*y; /* |z|^2 */ mag[4] = (1.0-x)*(1.0-x) + y*y; /* |1-z|^2 */ if (mag[0] <= ALWAYS1) return 0; mag[1] = mag[0] / FLINT_MAX(mag[4], 1e-10); /* |z/(z-1)|^2 */ if (mag[1] <= ALWAYS1) return 1; if (mag[0] <= ALWAYS2 || mag[1] <= ALWAYS2) return mag[0] <= mag[1] ? 0 : 1; mag[2] = 1.0 / mag[0]; /* |1/z|^2 */ mag[3] = 1.0 / FLINT_MAX(mag[4], 1e-10); /* 1/|1-z|^2 */ mag[5] = mag[4] / mag[0]; /* |1-1/z|^2 = |(1-z)/z|^2 */ pick = 0; for (i = 1; i < 6; i++) { if (mag[i] < mag[pick]) pick = i; } if (mag[pick] <= LIMIT) return pick; return 6; } flint-3.1.3/src/acb_hypgeom/2f1_continuation.c000066400000000000000000000134731461254215100212350ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* Differential equation for F(a,b,c,y+z): (y+z)(y-1+z) F''(z) + ((y+z)(a+b+1) - c) F'(z) + a b F(z) = 0 Coefficients in the Taylor series are bounded by A * binomial(N+k, k) * nu^k using the Cauchy-Kovalevskaya majorant method. See J. van der Hoeven, "Fast evaluation of holonomic functions near and in regular singularities" */ static void bound(mag_t A, mag_t nu, mag_t N, const acb_t a, const acb_t b, const acb_t c, const acb_t y, const acb_t f0, const acb_t f1) { mag_t M0, M1, t, u; acb_t d; acb_init(d); mag_init(M0); mag_init(M1); mag_init(t); mag_init(u); /* nu = max(1/|y-1|, 1/|y|) = 1/min(|y-1|, |y|) */ acb_get_mag_lower(t, y); acb_sub_ui(d, y, 1, MAG_BITS); acb_get_mag_lower(u, d); mag_min(t, t, u); mag_one(u); mag_div(nu, u, t); /* M0 = 2 nu |ab| */ acb_get_mag(t, a); acb_get_mag(u, b); mag_mul(M0, t, u); mag_mul(M0, M0, nu); mag_mul_2exp_si(M0, M0, 1); /* M1 = nu |a+b+1| + 2|c| */ acb_add(d, a, b, MAG_BITS); acb_add_ui(d, d, 1, MAG_BITS); acb_get_mag(t, d); mag_mul(t, t, nu); acb_get_mag(u, c); mag_mul_2exp_si(u, u, 1); mag_add(M1, t, u); /* N = max(sqrt(2 M0), 2 M1) / nu */ mag_mul_2exp_si(M0, M0, 1); mag_sqrt(M0, M0); mag_mul_2exp_si(M1, M1, 1); mag_max(N, M0, M1); mag_div(N, N, nu); /* A = max(|f0|, |f1| / (nu (N+1)) */ acb_get_mag(t, f0); acb_get_mag(u, f1); mag_div(u, u, nu); mag_div(u, u, N); /* upper bound for dividing by N+1 */ mag_max(A, t, u); acb_clear(d); mag_clear(M0); mag_clear(M1); mag_clear(t); mag_clear(u); } /* F(x) = c0 + c1 x + c2 x^2 + c3 x^3 + [...] F'(x) = c1 + 2 c2 x + 3 c3 x^2 + 4 c4 x^3 + [...] */ static void evaluate_sum(acb_t res, acb_t res1, const acb_t a, const acb_t b, const acb_t c, const acb_t y, const acb_t x, const acb_t f0, const acb_t f1, slong num, slong prec) { acb_t s, s2, w, d, e, xpow, ck, cknext; slong k; acb_init(s); acb_init(s2); acb_init(w); acb_init(d); acb_init(e); acb_init(xpow); acb_init(ck); acb_init(cknext); /* d = (y-1)*y */ acb_sub_ui(d, y, 1, prec); acb_mul(d, d, y, prec); acb_one(xpow); for (k = 0; k < num; k++) { if (k == 0) { acb_set(ck, f0); acb_set(cknext, f1); } else { acb_add_ui(w, b, k-1, prec); acb_mul(w, w, ck, prec); acb_add_ui(e, a, k-1, prec); acb_mul(w, w, e, prec); acb_add(e, a, b, prec); acb_add_ui(e, e, 2*(k+1)-3, prec); acb_mul(e, e, y, prec); acb_sub(e, e, c, prec); acb_sub_ui(e, e, k-1, prec); acb_mul_ui(e, e, k, prec); acb_addmul(w, e, cknext, prec); acb_mul_ui(e, d, k+1, prec); acb_mul_ui(e, e, k, prec); acb_div(w, w, e, prec); acb_neg(w, w); acb_set(ck, cknext); acb_set(cknext, w); } acb_addmul(s, ck, xpow, prec); acb_mul_ui(w, cknext, k+1, prec); acb_addmul(s2, w, xpow, prec); acb_mul(xpow, xpow, x, prec); } acb_set(res, s); acb_set(res1, s2); acb_clear(s); acb_clear(s2); acb_clear(w); acb_clear(d); acb_clear(e); acb_clear(xpow); acb_clear(ck); acb_clear(cknext); } void acb_hypgeom_2f1_continuation(acb_t res, acb_t res1, const acb_t a, const acb_t b, const acb_t c, const acb_t y, const acb_t z, const acb_t f0, const acb_t f1, slong prec) { mag_t A, nu, N, w, err, err1, R, T, goal; acb_t x; slong j, k; mag_init(A); mag_init(nu); mag_init(N); mag_init(err); mag_init(err1); mag_init(w); mag_init(R); mag_init(T); mag_init(goal); acb_init(x); bound(A, nu, N, a, b, c, y, f0, f1); acb_sub(x, z, y, prec); /* |T(k)| <= A * binomial(N+k, k) * nu^k * |x|^k */ acb_get_mag(w, x); mag_mul(w, w, nu); /* w = nu |x| */ mag_mul_2exp_si(goal, A, -prec-2); /* bound for T(0) */ mag_set(T, A); mag_inf(R); for (k = 1; k < 100 * prec; k++) { /* T(k) = T(k) * R(k), R(k) = (N+k)/k * w = (1 + N/k) w */ mag_div_ui(R, N, k); mag_add_ui(R, R, 1); mag_mul(R, R, w); /* T(k) */ mag_mul(T, T, R); if (mag_cmp(T, goal) <= 0 && mag_cmp_2exp_si(R, 0) < 0) break; } /* T(k) [1 + R + R^2 + R^3 + ...] */ mag_geom_series(err, R, 0); mag_mul(err, T, err); /* Now compute T, R for the derivative */ /* Coefficients are A * (k+1) * binomial(N+k+1, k+1) */ mag_add_ui(T, N, 1); mag_mul(T, T, A); mag_inf(R); for (j = 1; j <= k; j++) { mag_add_ui(R, N, k + 1); mag_div_ui(R, R, k); mag_mul(R, R, w); mag_mul(T, T, R); } mag_geom_series(err1, R, 0); mag_mul(err1, T, err1); if (mag_is_inf(err)) { acb_indeterminate(res); acb_indeterminate(res1); } else { evaluate_sum(res, res1, a, b, c, y, x, f0, f1, k, prec); acb_add_error_mag(res, err); acb_add_error_mag(res1, err1); } mag_clear(A); mag_clear(nu); mag_clear(N); mag_clear(err); mag_clear(err1); mag_clear(w); mag_clear(R); mag_clear(T); mag_clear(goal); acb_clear(x); } flint-3.1.3/src/acb_hypgeom/2f1_corner.c000066400000000000000000000032551461254215100200100ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_2f1_corner(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, slong prec) { acb_t aa, bb, cc, z1, z2, f1, f2; int upper; acb_init(aa); acb_init(bb); acb_init(cc); acb_init(z1); acb_init(z2); acb_init(f1); acb_init(f2); acb_add_ui(aa, a, 1, prec); acb_add_ui(bb, b, 1, prec); acb_add_ui(cc, c, 1, prec); upper = arb_is_positive(acb_imagref(z)); /* 0 -> 0.5 +/- 0.5i -> 0.5 +/- 0.75i -> z */ #if 0 acb_set_d_d(z1, 0.5, upper ? 0.5 : -0.5); acb_set_d_d(z2, 0.5, upper ? 0.75 : -0.75); #else acb_set_d_d(z1, 0.375, upper ? 0.625 : -0.625); acb_set_d_d(z2, 0.5, upper ? 0.8125 : -0.8125); #endif acb_hypgeom_2f1_direct(f1, a, b, c, z1, regularized, prec); acb_hypgeom_2f1_direct(f2, aa, bb, cc, z1, regularized, prec); acb_mul(f2, f2, a, prec); acb_mul(f2, f2, b, prec); if (!regularized) acb_div(f2, f2, c, prec); acb_hypgeom_2f1_continuation(f1, f2, a, b, c, z1, z2, f1, f2, prec); acb_set(z1, z2); acb_set(z2, z); acb_hypgeom_2f1_continuation(f1, f2, a, b, c, z1, z2, f1, f2, prec); acb_set(res, f1); acb_clear(aa); acb_clear(bb); acb_clear(cc); acb_clear(z1); acb_clear(z2); acb_clear(f1); acb_clear(f2); } flint-3.1.3/src/acb_hypgeom/2f1_direct.c000066400000000000000000000064041461254215100177710ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_2f1_direct(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, slong prec) { /* 2F1R(a,b,-n,z) = (a)_(n+1) * (b)_(n+1) * z^(n+1) / (n+1)! * 2F1(a+n+1, b+n+1, n+2, z) */ if (regularized && acb_is_int(c) && arf_sgn(arb_midref(acb_realref(c))) <= 0) { if ((acb_is_int(a) && arb_is_nonpositive(acb_realref(a)) && arf_cmp(arb_midref(acb_realref(a)), arb_midref(acb_realref(c))) >= 0) || (acb_is_int(b) && arb_is_nonpositive(acb_realref(b)) && arf_cmp(arb_midref(acb_realref(b)), arb_midref(acb_realref(c))) >= 0)) { acb_zero(res); } else { acb_t n, n1, t, u, v; acb_ptr aa; int p, q; acb_init(n); acb_init(n1); acb_init(t); acb_init(u); acb_init(v); aa = _acb_vec_init(4); acb_neg(n, c); acb_add_ui(n1, n, 1, prec); acb_add(aa, a, n1, prec); acb_add(aa + 1, b, n1, prec); acb_add_ui(aa + 2, n1, 1, prec); if (acb_is_one(aa)) { p = q = 1; acb_swap(aa, aa + 1); } else if (acb_is_one(aa + 1)) { p = q = 1; } else { p = q = 2; acb_one(aa + 3); } acb_hypgeom_pfq_direct(t, aa, p, aa + 2, q, z, -1, prec); /* z^(n+1) */ acb_pow(u, z, n1, prec); acb_mul(t, t, u, prec); acb_rising(u, a, n1, prec); acb_mul(t, t, u, prec); acb_rising(u, b, n1, prec); acb_mul(t, t, u, prec); /* 1/(n+1)! */ acb_rgamma(u, aa + 2, prec); acb_mul(t, t, u, prec); acb_set(res, t); acb_clear(n); acb_clear(n1); acb_clear(t); acb_clear(u); acb_clear(v); _acb_vec_clear(aa, 4); } } else { acb_ptr aa; int p, q; aa = _acb_vec_init(4); acb_set(aa + 2, c); if (acb_is_one(a)) { p = q = 1; acb_set(aa, b); } else if (acb_is_one(b)) { p = q = 1; acb_set(aa, a); } else { p = q = 2; acb_set(aa, a); acb_set(aa + 1, b); acb_one(aa + 3); } acb_hypgeom_pfq_direct(res, aa, p, aa + 2, q, z, -1, prec); if (regularized) { acb_rgamma(aa + 2, aa + 2, prec); acb_mul(res, res, aa + 2, prec); } _acb_vec_clear(aa, 4); } if (!acb_is_finite(res)) acb_indeterminate(res); } flint-3.1.3/src/acb_hypgeom/2f1_series_direct.c000066400000000000000000000015461461254215100213450ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void acb_hypgeom_2f1_series_direct(acb_poly_t res, const acb_poly_t a, const acb_poly_t b, const acb_poly_t c, const acb_poly_t z, int regularized, slong len, slong prec) { acb_poly_struct aa[4]; aa[0] = *a; aa[1] = *b; aa[2] = *c; acb_poly_init(&aa[3]); acb_poly_one(&aa[3]); acb_hypgeom_pfq_series_direct(res, aa, 2, aa + 2, 2, z, regularized, -1, len, prec); acb_poly_clear(&aa[3]); } flint-3.1.3/src/acb_hypgeom/2f1_transform.c000066400000000000000000000315771461254215100205430ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" /* which == 0 -- z which == 1 -- z/(z-1) which == 2 -- 1/z which == 3 -- 1/(1-z) which == 4 -- 1-z which == 5 -- 1-1/z */ void _acb_hypgeom_2f1_transform_limit(acb_t res, const acb_poly_t a, const acb_poly_t b, const acb_poly_t c, const acb_poly_t z, int which, slong prec) { acb_poly_t ba, ca, cb, cab, ac1, bc1, ab1, ba1, w, t, u, v, s; acb_t tt; acb_poly_init(ba); acb_poly_init(ca); acb_poly_init(cb); acb_poly_init(cab); acb_poly_init(ac1); acb_poly_init(bc1); acb_poly_init(ab1); acb_poly_init(ba1); acb_poly_init(w); acb_poly_init(t); acb_poly_init(u); acb_poly_init(v); acb_poly_init(s); acb_init(tt); acb_poly_add_si(s, z, -1, prec); /* s = 1 - z */ acb_poly_neg(s, s); acb_poly_sub(ba, b, a, prec); /* ba = b - a */ acb_poly_sub(ca, c, a, prec); /* ca = c - a */ acb_poly_sub(cb, c, b, prec); /* cb = c - b */ acb_poly_sub(cab, ca, b, prec); /* cab = c - a - b */ acb_poly_add_si(ac1, ca, -1, prec); acb_poly_neg(ac1, ac1); /* ac1 = a - c + 1 */ acb_poly_add_si(bc1, cb, -1, prec); acb_poly_neg(bc1, bc1); /* bc1 = b - c + 1 */ acb_poly_add_si(ab1, ba, -1, prec); acb_poly_neg(ab1, ab1); /* ab1 = a - b + 1 */ acb_poly_add_si(ba1, ba, 1, prec); /* ba1 = b - a + 1 */ /* t = left term, u = right term (DLMF 15.8.1 - 15.8.5) */ if (which == 2) { acb_poly_inv_series(w, z, 2, prec); /* w = 1/z */ acb_hypgeom_2f1_series_direct(t, a, ac1, ab1, w, 1, 2, prec); acb_hypgeom_2f1_series_direct(u, b, bc1, ba1, w, 1, 2, prec); } else if (which == 3) { acb_poly_inv_series(w, s, 2, prec); /* w = 1/(1-z) */ acb_hypgeom_2f1_series_direct(t, a, cb, ab1, w, 1, 2, prec); acb_hypgeom_2f1_series_direct(u, b, ca, ba1, w, 1, 2, prec); } else if (which == 4) { acb_poly_set(w, s); /* w = 1-z */ acb_poly_add(v, ac1, b, prec); /* v = a+b-c+1 */ acb_hypgeom_2f1_series_direct(t, a, b, v, w, 1, 2, prec); acb_poly_add_si(v, cab, 1, prec); /* v = c-a-b+1 */ acb_hypgeom_2f1_series_direct(u, ca, cb, v, w, 1, 2, prec); } else if (which == 5) { acb_poly_inv_series(w, z, 2, prec); /* w = 1-1/z */ acb_poly_neg(w, w); acb_poly_add_si(w, w, 1, prec); acb_poly_add(v, ac1, b, prec); /* v = a+b-c+1 */ acb_hypgeom_2f1_series_direct(t, a, ac1, v, w, 1, 2, prec); acb_poly_add_si(v, cab, 1, prec); /* v = c-a-b+1 */ acb_poly_add_si(u, a, -1, prec); /* u = 1-a */ acb_poly_neg(u, u); acb_hypgeom_2f1_series_direct(u, ca, u, v, w, 1, 2, prec); } else { flint_throw(FLINT_ERROR, "invalid transformation!\n"); } /* gamma factors */ acb_poly_rgamma_series(v, a, 2, prec); acb_poly_mullow(u, u, v, 2, prec); acb_poly_rgamma_series(v, ca, 2, prec); acb_poly_mullow(t, t, v, 2, prec); acb_poly_rgamma_series(v, b, 2, prec); if (which == 2 || which == 3) acb_poly_mullow(t, t, v, 2, prec); else acb_poly_mullow(u, u, v, 2, prec); acb_poly_rgamma_series(v, cb, 2, prec); if (which == 2 || which == 3) acb_poly_mullow(u, u, v, 2, prec); else acb_poly_mullow(t, t, v, 2, prec); if (which == 2 || which == 3) { if (which == 2) acb_poly_neg(s, z); /* -z, otherwise 1-z since before */ acb_poly_neg(v, a); acb_poly_pow_series(v, s, v, 2, prec); acb_poly_mullow(t, t, v, 2, prec); acb_poly_neg(v, b); acb_poly_pow_series(v, s, v, 2, prec); acb_poly_mullow(u, u, v, 2, prec); } else { acb_poly_pow_series(v, s, cab, 2, prec); acb_poly_mullow(u, u, v, 2, prec); if (which == 5) { acb_poly_neg(v, a); acb_poly_pow_series(v, z, v, 2, prec); acb_poly_mullow(t, t, v, 2, prec); acb_poly_neg(v, ca); acb_poly_pow_series(v, z, v, 2, prec); acb_poly_mullow(u, u, v, 2, prec); } } acb_poly_sub(t, t, u, prec); if (which == 2 || which == 3) acb_poly_sin_pi_series(v, ba, 2, prec); else acb_poly_sin_pi_series(v, cab, 2, prec); acb_poly_get_coeff_acb(tt, t, 1); acb_poly_get_coeff_acb(res, v, 1); acb_div(res, tt, res, prec); acb_const_pi(tt, prec); acb_mul(res, res, tt, prec); acb_poly_clear(ba); acb_poly_clear(ca); acb_poly_clear(cb); acb_poly_clear(cab); acb_poly_clear(ac1); acb_poly_clear(bc1); acb_poly_clear(ab1); acb_poly_clear(ba1); acb_poly_clear(w); acb_poly_clear(t); acb_poly_clear(u); acb_poly_clear(v); acb_poly_clear(s); acb_clear(tt); } void acb_hypgeom_2f1_transform_limit(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, int which, slong prec) { acb_poly_t aa, bb, cc, zz; acb_t t; if (acb_contains_zero(z) || !acb_is_finite(z)) { acb_indeterminate(res); return; } if (arb_contains_si(acb_realref(z), 1) && arb_contains_zero(acb_imagref(z))) { acb_indeterminate(res); return; } if (!regularized) { acb_init(t); acb_gamma(t, c, prec); acb_hypgeom_2f1_transform_limit(res, a, b, c, z, 1, which, prec); acb_mul(res, res, t, prec); acb_clear(t); return; } acb_poly_init(aa); acb_poly_init(bb); acb_poly_init(cc); acb_poly_init(zz); acb_init(t); acb_poly_set_acb(aa, a); acb_poly_set_acb(bb, b); acb_poly_set_acb(cc, c); acb_poly_set_acb(zz, z); if (which == 2 || which == 3) { acb_sub(t, b, a, prec); acb_poly_set_coeff_si(aa, 1, 1); /* prefer b-a nonnegative (either is correct) to avoid expensive operations in the hypergeometric series */ if (arb_is_nonnegative(acb_realref(t))) _acb_hypgeom_2f1_transform_limit(res, aa, bb, cc, zz, which, prec); else _acb_hypgeom_2f1_transform_limit(res, bb, aa, cc, zz, which, prec); } else { acb_poly_set_coeff_si(aa, 1, 1); _acb_hypgeom_2f1_transform_limit(res, aa, bb, cc, zz, which, prec); } acb_poly_clear(aa); acb_poly_clear(bb); acb_poly_clear(cc); acb_poly_clear(zz); acb_clear(t); } void acb_hypgeom_2f1_transform_nolimit(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, int which, slong prec) { acb_t ba, ca, cb, cab, ac1, bc1, ab1, ba1, w, t, u, v, s; if (acb_contains_zero(z) || !acb_is_finite(z)) { acb_indeterminate(res); return; } if (arb_contains_si(acb_realref(z), 1) && arb_contains_zero(acb_imagref(z))) { acb_indeterminate(res); return; } if (!regularized) { acb_init(t); acb_gamma(t, c, prec); acb_hypgeom_2f1_transform_nolimit(res, a, b, c, z, 1, which, prec); acb_mul(res, res, t, prec); acb_clear(t); return; } acb_init(ba); acb_init(ca); acb_init(cb); acb_init(cab); acb_init(ac1); acb_init(bc1); acb_init(ab1); acb_init(ba1); acb_init(w); acb_init(t); acb_init(u); acb_init(v); acb_init(s); acb_add_si(s, z, -1, prec); /* s = 1 - z */ acb_neg(s, s); acb_sub(ba, b, a, prec); /* ba = b - a */ acb_sub(ca, c, a, prec); /* ca = c - a */ acb_sub(cb, c, b, prec); /* cb = c - b */ acb_sub(cab, ca, b, prec); /* cab = c - a - b */ acb_add_si(ac1, ca, -1, prec); acb_neg(ac1, ac1); /* ac1 = a - c + 1 */ acb_add_si(bc1, cb, -1, prec); acb_neg(bc1, bc1); /* bc1 = b - c + 1 */ acb_add_si(ab1, ba, -1, prec); acb_neg(ab1, ab1); /* ab1 = a - b + 1 */ acb_add_si(ba1, ba, 1, prec); /* ba1 = b - a + 1 */ /* t = left term, u = right term (DLMF 15.8.1 - 15.8.5) */ if (which == 2) { acb_inv(w, z, prec); /* w = 1/z */ acb_hypgeom_2f1_direct(t, a, ac1, ab1, w, 1, prec); acb_hypgeom_2f1_direct(u, b, bc1, ba1, w, 1, prec); } else if (which == 3) { acb_inv(w, s, prec); /* w = 1/(1-z) */ acb_hypgeom_2f1_direct(t, a, cb, ab1, w, 1, prec); acb_hypgeom_2f1_direct(u, b, ca, ba1, w, 1, prec); } else if (which == 4) { acb_set(w, s); /* w = 1-z */ acb_add(v, ac1, b, prec); /* v = a+b-c+1 */ acb_hypgeom_2f1_direct(t, a, b, v, w, 1, prec); acb_add_si(v, cab, 1, prec); /* v = c-a-b+1 */ acb_hypgeom_2f1_direct(u, ca, cb, v, w, 1, prec); } else if (which == 5) { acb_inv(w, z, prec); /* w = 1-1/z */ acb_neg(w, w); acb_add_si(w, w, 1, prec); acb_add(v, ac1, b, prec); /* v = a+b-c+1 */ acb_hypgeom_2f1_direct(t, a, ac1, v, w, 1, prec); acb_add_si(v, cab, 1, prec); /* v = c-a-b+1 */ acb_add_si(u, a, -1, prec); /* u = 1-a */ acb_neg(u, u); acb_hypgeom_2f1_direct(u, ca, u, v, w, 1, prec); } else { flint_throw(FLINT_ERROR, "invalid transformation!\n"); } /* gamma factors */ acb_rgamma(v, a, prec); acb_mul(u, u, v, prec); acb_rgamma(v, ca, prec); acb_mul(t, t, v, prec); acb_rgamma(v, b, prec); if (which == 2 || which == 3) acb_mul(t, t, v, prec); else acb_mul(u, u, v, prec); acb_rgamma(v, cb, prec); if (which == 2 || which == 3) acb_mul(u, u, v, prec); else acb_mul(t, t, v, prec); if (which == 2 || which == 3) { if (which == 2) acb_neg(s, z); /* -z, otherwise 1-z since before */ acb_neg(v, a); acb_pow(v, s, v, prec); acb_mul(t, t, v, prec); acb_neg(v, b); acb_pow(v, s, v, prec); acb_mul(u, u, v, prec); } else { acb_pow(v, s, cab, prec); acb_mul(u, u, v, prec); if (which == 5) { acb_neg(v, a); acb_pow(v, z, v, prec); acb_mul(t, t, v, prec); acb_neg(v, ca); acb_pow(v, z, v, prec); acb_mul(u, u, v, prec); } } acb_sub(t, t, u, prec); if (which == 2 || which == 3) acb_sin_pi(v, ba, prec); else acb_sin_pi(v, cab, prec); acb_div(t, t, v, prec); acb_const_pi(v, prec); acb_mul(t, t, v, prec); acb_set(res, t); acb_clear(ba); acb_clear(ca); acb_clear(cb); acb_clear(cab); acb_clear(ac1); acb_clear(bc1); acb_clear(ab1); acb_clear(ba1); acb_clear(w); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(s); } void acb_hypgeom_2f1_transform(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int flags, int which, slong prec) { int regularized; regularized = flags & ACB_HYPGEOM_2F1_REGULARIZED; if (which == 1) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_sub_ui(t, z, 1, prec); /* t = z-1 */ acb_div(u, z, t, prec); /* u = z/(z-1) */ acb_neg(t, t); acb_neg(v, a); acb_pow(t, t, v, prec); /* t = (1-z)^-a */ acb_sub(v, c, b, prec); /* v = c-b */ /* We cannot use regularized=1 directly, since if c is a nonnegative integer, the transformation formula reads (lhs) * 0 = (rhs) * 0. */ acb_hypgeom_2f1_direct(u, a, v, c, u, 1, prec); if (!regularized) { acb_gamma(v, c, prec); acb_mul(u, u, v, prec); } acb_mul(res, u, t, prec); acb_clear(t); acb_clear(u); acb_clear(v); } else { acb_t d; int limit; acb_init(d); if (which == 2 || which == 3) { if (flags & ACB_HYPGEOM_2F1_AB) { limit = 1; } else { acb_sub(d, b, a, prec); limit = acb_is_int(d); } } else { if (flags & ACB_HYPGEOM_2F1_ABC) { limit = 1; } else { acb_sub(d, c, a, prec); acb_sub(d, d, b, prec); limit = acb_is_int(d); } } if (limit) acb_hypgeom_2f1_transform_limit(res, a, b, c, z, regularized, which, prec); else acb_hypgeom_2f1_transform_nolimit(res, a, b, c, z, regularized, which, prec); acb_clear(d); } if (!acb_is_finite(res)) acb_indeterminate(res); } flint-3.1.3/src/acb_hypgeom/airy.c000066400000000000000000000220311461254215100170050ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "double_extras.h" #include "acb_hypgeom.h" #define LOG2 0.69314718055994530942 #define EXP1 2.7182818284590452354 static const double small_log_tab[] = { 0.0, 0.0, 0.693147180559945309, 1.09861228866810969, 1.38629436111989062, 1.60943791243410037, 1.791759469228055, 1.94591014905531331, 2.07944154167983593, 2.19722457733621938, 2.30258509299404568, 2.39789527279837054, 2.48490664978800031, 2.56494935746153674, 2.63905732961525861, 2.70805020110221007, 2.77258872223978124, 2.83321334405621608, 2.89037175789616469, 2.94443897916644046, 2.99573227355399099, 3.044522437723423, 3.09104245335831585, 3.13549421592914969, 3.17805383034794562, 3.21887582486820075, 3.25809653802148205, 3.29583686600432907, 3.33220451017520392, 3.36729582998647403, 3.40119738166215538, 3.43398720448514625, 3.46573590279972655, 3.49650756146648024, 3.52636052461616139, 3.55534806148941368, 3.58351893845611, 3.61091791264422444, 3.63758615972638577, 3.66356164612964643, 3.6888794541139363, 3.7135720667043078, 3.73766961828336831, 3.76120011569356242, 3.78418963391826116, 3.80666248977031976, 3.828641396489095, 3.85014760171005859, 3.87120101090789093, 3.89182029811062661, 3.91202300542814606, 3.93182563272432577, 3.95124371858142735, 3.97029191355212183, 3.98898404656427438, 4.00733318523247092, 4.02535169073514923, 4.04305126783455015, 4.06044301054641934, 4.07753744390571945, 4.09434456222210068, 4.11087386417331125, 4.12713438504509156, 4.14313472639153269, }; static slong asymp_pick_terms(double prec, double logz) { double logk, log2term, log2term_prev; slong k; log2term_prev = 0.0; for (k = 1; ; k++) { logk = k < 64 ? small_log_tab[k] : log(k); log2term = -1.3257480647361593990 - 0.72134752044448170368*logk + k * (-1.8577325401678072259 + 1.4426950408889634074*logk - 2.1640425613334451110*logz); if (log2term > log2term_prev - 0.5) return -1; if (log2term < -prec) return k; } } /* Accurate estimate of log2(|Ai(z)|) or log2(|Bi(z)|), given z = x + yi. Should subtract 0.25*log2(|z| + log2(2*sqrt(pi)) from the output. */ static double estimate_airy(double x, double y, int ai) { double r, t, sgn; r = x; t = x * ((x * x) - 3.0 * (y * y)); y = y * (3.0 * (x * x) - (y * y)); x = t * (1.0 / 9.0); y = y * (1.0 / 9.0); sgn = 1.0; if (r > 0.0 && x > 0.0) { t = sqrt(x * x + y * y) + x; if (ai) sgn = -1.0; } else { x = -x; if (x > 0.0 && x > 1e6 * fabs(y)) t = y * y / (2.0 * x); else t = sqrt(x * x + y * y) - x; } return sgn * sqrt(0.5 * t) * 2.8853900817779268147; } /* error propagation based on derivatives */ void acb_hypgeom_airy_prop(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong n, int algo, slong prec) { mag_t aib, aipb, bib, bipb, zb, rad; acb_t zz; int real; mag_init(aib); mag_init(aipb); mag_init(bib); mag_init(bipb); mag_init(zb); mag_init(rad); acb_init(zz); real = acb_is_real(z); arf_set(arb_midref(acb_realref(zz)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zz)), arb_midref(acb_imagref(z))); mag_hypot(rad, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); acb_get_mag(zb, z); acb_hypgeom_airy_bound(aib, aipb, bib, bipb, z); if (algo == 0) acb_hypgeom_airy_direct(ai, aip, bi, bip, zz, n, prec); else acb_hypgeom_airy_asymp(ai, aip, bi, bip, zz, n, prec); if (ai != NULL) { mag_mul(aipb, aipb, rad); if (real) arb_add_error_mag(acb_realref(ai), aipb); else acb_add_error_mag(ai, aipb); } if (aip != NULL) { mag_mul(aib, aib, rad); mag_mul(aib, aib, zb); /* |Ai''(z)| = |z Ai(z)| */ if (real) arb_add_error_mag(acb_realref(aip), aib); else acb_add_error_mag(aip, aib); } if (bi != NULL) { mag_mul(bipb, bipb, rad); if (real) arb_add_error_mag(acb_realref(bi), bipb); else acb_add_error_mag(bi, bipb); } if (bip != NULL) { mag_mul(bib, bib, rad); mag_mul(bib, bib, zb); /* |Bi''(z)| = |z Bi(z)| */ if (real) arb_add_error_mag(acb_realref(bip), bib); else acb_add_error_mag(bip, bib); } mag_clear(aib); mag_clear(aipb); mag_clear(bib); mag_clear(bipb); mag_clear(zb); mag_clear(rad); acb_clear(zz); } void acb_hypgeom_airy_direct_prop(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong n, slong prec) { acb_hypgeom_airy_prop(ai, aip, bi, bip, z, n, 0, prec); } void acb_hypgeom_airy_asymp2(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong n, slong prec) { /* avoid singularity in asymptotic expansion near 0 */ if (acb_rel_accuracy_bits(z) > 3) acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, prec); else acb_hypgeom_airy_prop(ai, aip, bi, bip, z, n, 1, prec); } void acb_hypgeom_airy(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong prec) { arf_srcptr re, im; double x, y, t, zmag, z15, term_est, airy_est, abstol; slong n, wp; if (!acb_is_finite(z)) { if (ai != NULL) acb_indeterminate(ai); if (aip != NULL) acb_indeterminate(aip); if (bi != NULL) acb_indeterminate(bi); if (bip != NULL) acb_indeterminate(bip); return; } re = arb_midref(acb_realref(z)); im = arb_midref(acb_imagref(z)); wp = prec * 1.03 + 15; /* tiny input -- use direct method and pick n without underflowing */ if (arf_cmpabs_2exp_si(re, -64) < 0 && arf_cmpabs_2exp_si(im, -64) < 0) { if (arf_cmpabs_2exp_si(re, -wp) < 0 && arf_cmpabs_2exp_si(im, -wp) < 0) { n = 1; /* very tiny input */ } else { if (arf_cmpabs(re, im) > 0) zmag = fmpz_get_d(ARF_EXPREF(re)); else zmag = fmpz_get_d(ARF_EXPREF(im)); zmag = 3.0 * zmag + 1; n = wp / (-zmag) + 1; } if (acb_is_exact(z)) acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); else acb_hypgeom_airy_direct_prop(ai, aip, bi, bip, z, n, wp); } /* huge input -- use asymptotics and pick n without overflowing */ else if ((arf_cmpabs_2exp_si(re, 64) > 0 || arf_cmpabs_2exp_si(im, 64) > 0)) { if (arf_cmpabs_2exp_si(re, prec) > 0 || arf_cmpabs_2exp_si(im, prec) > 0) { n = 1; /* very huge input */ } else { x = fmpz_get_d(ARF_EXPREF(re)); y = fmpz_get_d(ARF_EXPREF(im)); zmag = (FLINT_MAX(x, y) - 2) * LOG2; n = asymp_pick_terms(wp, zmag); n = FLINT_MAX(n, 1); } acb_hypgeom_airy_asymp2(ai, aip, bi, bip, z, n, wp); } else /* moderate input */ { x = arf_get_d(re, ARF_RND_DOWN); y = arf_get_d(im, ARF_RND_DOWN); zmag = sqrt(x * x + y * y); z15 = zmag * sqrt(zmag); if (zmag >= 4.0 && (n = asymp_pick_terms(wp, log(zmag))) != -1) { acb_hypgeom_airy_asymp2(ai, aip, bi, bip, z, n, wp); } else if (zmag <= 1.5) { t = 3 * (wp * LOG2) / (2 * z15 * EXP1); t = (wp * LOG2) / (2 * d_lambertw(t)); n = FLINT_MAX(t + 1, 2); if (acb_is_exact(z)) acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); else acb_hypgeom_airy_direct_prop(ai, aip, bi, bip, z, n, wp); } else { /* estimate largest term: log2(exp(2(z^3/9)^(1/2))) */ term_est = 0.96179669392597560491 * z15; /* estimate the smaller of Ai and Bi */ airy_est = estimate_airy(x, y, (ai != NULL || aip != NULL)); /* estimate absolute tolerance and necessary working precision */ abstol = airy_est - wp; wp = wp + term_est - airy_est; wp = FLINT_MAX(wp, 10); t = 3 * (-abstol * LOG2) / (2 * z15 * EXP1); t = (-abstol * LOG2) / (2 * d_lambertw(t)); n = FLINT_MAX(t + 1, 2); if (acb_is_exact(z)) acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); else acb_hypgeom_airy_direct_prop(ai, aip, bi, bip, z, n, wp); } } if (ai != NULL) acb_set_round(ai, ai, prec); if (aip != NULL) acb_set_round(aip, aip, prec); if (bi != NULL) acb_set_round(bi, bi, prec); if (bip != NULL) acb_set_round(bip, bip, prec); } flint-3.1.3/src/acb_hypgeom/airy_asymp.c000066400000000000000000000374641461254215100202360ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_mag_chi(mag_t chi, ulong n); static int arg_lt_2pi3(const acb_t z, const acb_t zeta) { if (arb_is_nonnegative(acb_realref(z))) return 1; if (arb_is_positive(acb_imagref(z)) && arb_is_positive(acb_imagref(zeta))) return 1; if (arb_is_negative(acb_imagref(z)) && arb_is_negative(acb_imagref(zeta))) return 1; return 0; } /* assuming a >= b >= c >= d, e >= f */ void _acb_mul4div2_ui(acb_t x, ulong a, ulong b, ulong c, ulong d, ulong e, ulong f, slong prec) { if (a < (UWORD(1) << (FLINT_BITS / 4))) { acb_mul_ui(x, x, a * b * c * d, prec); } else if (a < (UWORD(1) << (FLINT_BITS / 2))) { acb_mul_ui(x, x, a * b, prec); acb_mul_ui(x, x, c * d, prec); } else { acb_mul_ui(x, x, a, prec); acb_mul_ui(x, x, b, prec); acb_mul_ui(x, x, c, prec); acb_mul_ui(x, x, d, prec); } if (e < (UWORD(1) << (FLINT_BITS / 2))) { acb_div_ui(x, x, e * f, prec); } else { acb_div_ui(x, x, e, prec); acb_div_ui(x, x, f, prec); } } void acb_hypgeom_airy_asymp_sum(acb_t s0even, acb_t s0odd, acb_t s1even, acb_t s1odd, mag_t t0n, mag_t t1n, const acb_t z, const acb_t z2, slong n, slong prec) { slong m, k, j; acb_ptr z2pow; acb_get_mag(t0n, z); mag_mul_ui(t0n, t0n, 72); mag_pow_ui(t0n, t0n, n); mag_one(t1n); for (k = 1; k <= n; k++) { mag_mul_ui(t0n, t0n, 6 * k - 1); mag_mul_ui(t0n, t0n, 6 * k - 5); mag_mul_ui_lower(t1n, t1n, 72 * k); } mag_div(t0n, t0n, t1n); mag_mul_ui(t1n, t0n, 6 * n + 1); mag_div_ui(t1n, t1n, 6 * n - 1); m = n_sqrt(n / 2); m = FLINT_MAX(m, 1); z2pow = _acb_vec_init(m + 1); _acb_vec_set_powers(z2pow, z2, m + 1, prec); if (s0even != NULL) { acb_zero(s0even); for (k = n + (n % 2); k >= 0; k -= 2) { j = (k / 2) % m; if (k < n) acb_add(s0even, s0even, z2pow + j, prec); if (k > 0) { _acb_mul4div2_ui(s0even, 6*k-1, 6*k-5, 6*k-7, 6*k-11, k, k-1, prec); if (j == 0 && k < n) acb_mul(s0even, s0even, z2pow + m, prec); } } } if (s0odd != NULL) { acb_zero(s0odd); for (k = n + 1 + (n % 2); k >= 1; k -= 2) { j = ((k - 1) / 2) % m; if (k < n) acb_add(s0odd, s0odd, z2pow + j, prec); if (k > 1) { _acb_mul4div2_ui(s0odd, 6*k-1, 6*k-5, 6*k-7, 6*k-11, k, k-1, prec); if (j == 0 && k < n) acb_mul(s0odd, s0odd, z2pow + m, prec); } else { acb_mul(s0odd, s0odd, z, prec); acb_mul_ui(s0odd, s0odd, 5, prec); } } } if (s1even != NULL) { acb_zero(s1even); for (k = n + (n % 2); k >= 0; k -= 2) { j = (k / 2) % m; if (k < n) acb_add(s1even, s1even, z2pow + j, prec); if (k > 0) { _acb_mul4div2_ui(s1even, 6*k+1, 6*k-5, 6*k-7, FLINT_ABS(6*k-13), k, k-1, prec); if (k == 2) acb_neg(s1even, s1even); if (j == 0 && k < n) acb_mul(s1even, s1even, z2pow + m, prec); } } } if (s1odd != NULL) { acb_zero(s1odd); for (k = n + 1 + (n % 2); k >= 1; k -= 2) { j = ((k - 1) / 2) % m; if (k < n) acb_add(s1odd, s1odd, z2pow + j, prec); if (k > 1) { _acb_mul4div2_ui(s1odd, 6*k+1, 6*k-5, 6*k-7, 6*k-13, k, k-1, prec); if (j == 0 && k < n) acb_mul(s1odd, s1odd, z2pow + m, prec); } else { acb_mul(s1odd, s1odd, z, prec); acb_mul_si(s1odd, s1odd, -7, prec); } } } _acb_vec_clear(z2pow, m + 1); } void acb_hypgeom_airy_asymp_bound_factor(mag_t bound, const acb_t z, const acb_t zeta, ulong n) { mag_t t, u, v; mag_init(t); mag_init(u); mag_init(v); if (arb_is_nonnegative(acb_realref(z)) && arb_is_nonnegative(acb_realref(zeta))) { /* 2 exp(7 / (36 |zeta|)) */ mag_set_ui_2exp_si(t, 50, -8); /* bound for 7/36 */ acb_get_mag_lower(u, zeta); mag_div(t, t, u); mag_exp(t, t); mag_mul_2exp_si(bound, t, 1); } else { /* 2 exp(7 pi / (72 |zeta|)) */ mag_set_ui_2exp_si(t, 79, -8); /* bound for 7 pi/72 */ acb_get_mag_lower(u, zeta); mag_div(t, t, u); mag_exp(t, t); mag_mul_2exp_si(bound, t, 1); /* 4 exp(7 pi / (36 |re(zeta)|)) / |cos(arg(zeta))|^n */ if (!arg_lt_2pi3(z, zeta)) { arb_get_mag_lower(u, acb_realref(zeta)); arb_get_mag(v, acb_imagref(zeta)); /* 4 exp(7 pi / (36 u)) < exp(157/(256 u)) */ mag_set_ui_2exp_si(t, 157, -8); mag_div(t, t, u); mag_exp(t, t); mag_mul_2exp_si(t, t, 2); /* |1/cos(arg(zeta))| = sqrt(1+(v/u)^2) */ mag_div(v, v, u); mag_mul(v, v, v); mag_one(u); mag_add(v, v, u); mag_sqrt(v, v); mag_pow_ui(v, v, n); mag_mul(t, t, v); mag_max(bound, bound, t); } /* chi(n) */ acb_hypgeom_mag_chi(t, n); mag_mul(bound, bound, t); } mag_clear(t); mag_clear(u); mag_clear(v); } void acb_hypgeom_airy_asymp(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong n, slong prec) { acb_t t, u, w, z_root, zeta; acb_t s0even, s0odd, s1even, s1odd, E1, E2; mag_t err1, err2, erru, errv, errtmp; int want_d0, want_d1, is_real, upper; acb_init(t); acb_init(u); acb_init(w); acb_init(z_root); acb_init(zeta); acb_init(s0even); acb_init(s0odd); acb_init(s1even); acb_init(s1odd); acb_init(E1); acb_init(E2); mag_init(err1); mag_init(err2); mag_init(errtmp); mag_init(erru); mag_init(errv); is_real = acb_is_real(z); want_d0 = (ai != NULL) || (bi != NULL); want_d1 = (aip != NULL) || (bip != NULL); /* required for some of the error bounds to be valid */ n = FLINT_MAX(n, 1); /* this is just a heuristic; the sectors are validated later */ if (arf_sgn(arb_midref(acb_realref(z))) >= 0) { /* z_root = z^(1/4), zeta = 2 z^(3/2) / 3 */ acb_sqrt(z_root, z, prec); acb_cube(zeta, z_root, prec); acb_sqrt(z_root, z_root, prec); acb_mul_2exp_si(zeta, zeta, 1); acb_div_ui(zeta, zeta, 3, prec); /* compute bound factor for z = t = z1, zeta = u = zeta1 */ acb_hypgeom_airy_asymp_bound_factor(err1, z, zeta, n); /* this is just a heuristic; the sectors are validated later */ upper = arf_sgn(arb_midref(acb_imagref(z))) >= 0; if (upper) { /* check -pi/3 < arg(z) < pi */ if (arb_is_positive(acb_imagref(z)) || (arb_is_positive(acb_realref(z)) && arb_is_positive(acb_realref(zeta)))) { arb_one(acb_realref(w)); arb_sqrt_ui(acb_imagref(w), 3, prec); acb_mul_2exp_si(w, w, -1); acb_neg(w, w); acb_mul(t, w, z, prec); acb_neg(u, zeta); acb_hypgeom_airy_asymp_bound_factor(err2, t, u, n); } else { mag_inf(err2); } } else { /* check -pi < arg(z) < pi/3 */ if (arb_is_negative(acb_imagref(z)) || (arb_is_positive(acb_realref(z)) && arb_is_positive(acb_realref(zeta)))) { arb_set_si(acb_realref(w), -1); arb_sqrt_ui(acb_imagref(w), 3, prec); acb_mul_2exp_si(w, w, -1); acb_mul(t, w, z, prec); acb_neg(u, zeta); acb_hypgeom_airy_asymp_bound_factor(err2, t, u, n); } else { mag_inf(err2); } } acb_mul_ui(t, zeta, 72, prec); acb_inv(t, t, prec); acb_mul(u, t, t, prec); acb_hypgeom_airy_asymp_sum(want_d0 ? s0even : NULL, want_d0 ? s0odd : NULL, want_d1 ? s1even : NULL, want_d1 ? s1odd : NULL, erru, errv, t, u, n, prec); /* exponentials */ acb_exp_invexp(E2, E1, zeta, prec); /* common prefactor */ acb_const_pi(w, prec); acb_sqrt(w, w, prec); acb_mul_2exp_si(w, w, 1); if (ai != NULL || bi != NULL) { /* t = sum (-1)^k u(k) / (zeta)^k + error */ acb_sub(t, s0even, s0odd, prec); mag_mul(errtmp, err1, erru); acb_add_error_mag(t, errtmp); /* u = sum (-1)^k u(k) / (-zeta)^k = sum u(k) / (zeta)^k + error */ acb_add(u, s0even, s0odd, prec); mag_mul(errtmp, err2, erru); acb_add_error_mag(u, errtmp); if (ai != NULL) { acb_mul(ai, t, E1, prec); } if (bi != NULL) { acb_mul(t, t, E1, prec); acb_mul(u, u, E2, prec); acb_mul_2exp_si(u, u, 1); if (upper) acb_mul_onei(t, t); else acb_div_onei(t, t); acb_add(bi, t, u, prec); } acb_mul(t, w, z_root, prec); acb_inv(t, t, prec); if (ai != NULL) acb_mul(ai, ai, t, prec); if (bi != NULL) acb_mul(bi, bi, t, prec); } if (aip != NULL || bip != NULL) { /* t = sum (-1)^k v(k) / (zeta)^k + error */ acb_sub(t, s1even, s1odd, prec); mag_mul(errtmp, err1, errv); acb_add_error_mag(t, errtmp); /* u = sum (-1)^k v(k) / (-zeta)^k = sum v(k) / (zeta)^k + error */ acb_add(u, s1even, s1odd, prec); mag_mul(errtmp, err2, errv); acb_add_error_mag(u, errtmp); if (aip != NULL) { acb_mul(aip, t, E1, prec); acb_neg(aip, aip); } if (bip != NULL) { acb_mul(t, t, E1, prec); acb_mul(u, u, E2, prec); acb_mul_2exp_si(u, u, 1); if (upper) acb_div_onei(t, t); else acb_mul_onei(t, t); acb_add(bip, t, u, prec); } acb_inv(t, w, prec); acb_mul(t, t, z_root, prec); if (aip != NULL) acb_mul(aip, aip, t, prec); if (bip != NULL) acb_mul(bip, bip, t, prec); } } else { /* z_root = (-z)^(1/4), zeta = 2 (-z)^(3/2) / 3 */ acb_neg(t, z); acb_sqrt(z_root, t, prec); acb_cube(zeta, z_root, prec); acb_sqrt(z_root, z_root, prec); acb_mul_2exp_si(zeta, zeta, 1); acb_div_ui(zeta, zeta, 3, prec); if (arg_lt_2pi3(t, zeta)) { /* compute bound factor for i zeta */ arb_one(acb_realref(w)); arb_sqrt_ui(acb_imagref(w), 3, prec); acb_mul_2exp_si(w, w, -1); acb_mul(t, z, w, prec); acb_neg(t, t); acb_mul_onei(u, zeta); acb_hypgeom_airy_asymp_bound_factor(err1, t, u, n); /* compute bound factor for -i zeta */ acb_conj(w, w); acb_mul(t, z, w, prec); acb_neg(t, t); acb_div_onei(u, zeta); acb_hypgeom_airy_asymp_bound_factor(err2, t, u, n); } else { mag_inf(err1); mag_inf(err2); } /* t = 1/(72 i zeta), u = (1/(72 i zeta))^2 */ acb_mul_onei(t, zeta); acb_mul_ui(t, t, 72, prec); acb_inv(t, t, prec); acb_mul(u, t, t, prec); acb_hypgeom_airy_asymp_sum(want_d0 ? s0even : NULL, want_d0 ? s0odd : NULL, want_d1 ? s1even : NULL, want_d1 ? s1odd : NULL, erru, errv, t, u, n, prec); /* exponentials */ acb_const_pi(t, prec); acb_mul_2exp_si(t, t, -2); acb_sub(t, zeta, t, prec); acb_mul_onei(t, t); acb_exp_invexp(E2, E1, t, prec); /* common prefactor */ acb_const_pi(w, prec); acb_sqrt(w, w, prec); acb_mul_2exp_si(w, w, 1); if (ai != NULL || bi != NULL) { /* t = sum (-1)^k u(k) / (i zeta)^k + error */ acb_sub(t, s0even, s0odd, prec); mag_mul(errtmp, err1, erru); acb_add_error_mag(t, errtmp); /* w = sum (-1)^k u(k) / (-i zeta)^k = sum u(k) / (i zeta)^k + error */ acb_add(u, s0even, s0odd, prec); mag_mul(errtmp, err2, erru); acb_add_error_mag(u, errtmp); if (ai != NULL) { acb_mul(ai, t, E1, prec); acb_addmul(ai, u, E2, prec); } if (bi != NULL) { /* (-i E1) t + (+i E2) u */ acb_mul(bi, u, E2, prec); acb_submul(bi, t, E1, prec); acb_mul_onei(bi, bi); } acb_mul(t, w, z_root, prec); acb_inv(t, t, prec); if (ai != NULL) acb_mul(ai, ai, t, prec); if (bi != NULL) acb_mul(bi, bi, t, prec); } if (aip != NULL || bip != NULL) { /* t = sum (-1)^k v(k) / (i zeta)^k + error */ acb_sub(t, s1even, s1odd, prec); mag_mul(errtmp, err1, errv); acb_add_error_mag(t, errtmp); /* u = sum (-1)^k v(k) / (-i zeta)^k = sum v(k) / (i zeta)^k + error */ acb_add(u, s1even, s1odd, prec); mag_mul(errtmp, err2, errv); acb_add_error_mag(u, errtmp); if (bip != NULL) { acb_mul(bip, t, E1, prec); acb_addmul(bip, u, E2, prec); } if (aip != NULL) { /* i E1 t - i E2 u */ acb_mul(aip, t, E1, prec); acb_submul(aip, u, E2, prec); acb_mul_onei(aip, aip); } acb_inv(t, w, prec); acb_mul(t, t, z_root, prec); if (aip != NULL) acb_mul(aip, aip, t, prec); if (bip != NULL) acb_mul(bip, bip, t, prec); } } if (is_real) { if (ai != NULL) arb_zero(acb_imagref(ai)); if (aip != NULL) arb_zero(acb_imagref(aip)); if (bi != NULL) arb_zero(acb_imagref(bi)); if (bip != NULL) arb_zero(acb_imagref(bip)); } acb_clear(t); acb_clear(u); acb_clear(w); acb_clear(z_root); acb_clear(zeta); acb_clear(s0even); acb_clear(s0odd); acb_clear(s1even); acb_clear(s1odd); acb_clear(E1); acb_clear(E2); mag_clear(err1); mag_clear(err2); mag_clear(errtmp); mag_clear(erru); mag_clear(errv); } flint-3.1.3/src/acb_hypgeom/airy_bound.c000066400000000000000000000232551461254215100202050ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void arb_bound_exp_neg(mag_t b, const arb_t x) { arb_t t; arb_init(t); arf_set_mag(arb_midref(t), arb_radref(x)); arf_sub(arb_midref(t), arb_midref(x), arb_midref(t), MAG_BITS, ARF_RND_FLOOR); arf_neg(arb_midref(t), arb_midref(t)); arb_exp(t, t, MAG_BITS); arb_get_mag(b, t); arb_clear(t); } /* Implements DLMF 9.7.17. We assume |zeta| >= 1/2 and |arg(z)| <= 2 pi/3 here, ignoring the smaller points which must be dealt with separately. */ void acb_hypgeom_airy_bound_9_7_17(mag_t bound, const acb_t z, const acb_t zeta) { mag_t D, t, u, v, zeta_lower, half; mag_init(D); mag_init(t); mag_init(u); mag_init(v); mag_init(zeta_lower); mag_init(half); mag_one(half); mag_mul_2exp_si(half, half, -1); acb_get_mag_lower(zeta_lower, zeta); mag_max(zeta_lower, zeta_lower, half); /* by assumption */ /* 2 chi(1) exp(7 pi / (72 |zeta|)) * c_1 */ /* simplified bound assuming |zeta| >= 1/2 */ mag_one(D); /* exp(-zeta) / (2 sqrt(pi)) * (1 + D / |zeta|) */ /* t = exp(-zeta) / (2 sqrt(pi)) < exp(-zeta) * (73/256) */ arb_bound_exp_neg(t, acb_realref(zeta)); mag_mul_ui(t, t, 73); mag_mul_2exp_si(t, t, -8); /* u = 1 + D / |zeta| */ mag_div(u, D, zeta_lower); mag_one(v); mag_add(u, u, v); mag_mul(bound, t, u); mag_clear(D); mag_clear(t); mag_clear(u); mag_clear(v); mag_clear(zeta_lower); } void acb_hypgeom_airy_bound_arg_le_2pi3(mag_t A, mag_t B, const acb_t z, slong wp) { acb_t zeta, z1; acb_init(zeta); acb_init(z1); acb_set_round(zeta, z, wp); acb_sqrt(zeta, zeta, wp); acb_cube(zeta, zeta, wp); acb_mul_2exp_si(zeta, zeta, 1); acb_div_ui(zeta, zeta, 3, wp); acb_hypgeom_airy_bound_9_7_17(A, z, zeta); /* Use Bi(z) = w_1 Ai(z) + 2 w_2 Ai(z exp(+/- 2pi i / 3)), where w_1, w_2 are roots of unity */ if (B != NULL) { arb_sqrt_ui(acb_imagref(z1), 3, wp); arb_set_si(acb_realref(z1), -1); acb_mul_2exp_si(z1, z1, -1); /* multiply by exp(-2 pi i / 3) in upper half plane and by exp(2 pi i / 3) in lower half plane, to stay close to positive reals */ /* in principle, we should be computing the union of both cases, but since Bi is conjugate symmetric with the maximum value attained on the positive real line, it's sufficient to consider the case centered on the midpoint */ if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) acb_conj(z1, z1); acb_mul(z1, z1, z, wp); acb_neg(zeta, zeta); /* same effect regardless of exp(+/-2 pi i/3) */ acb_hypgeom_airy_bound_9_7_17(B, z1, zeta); mag_mul_2exp_si(B, B, 1); mag_add(B, B, A); } acb_clear(zeta); acb_clear(z1); } /* near the negative half line, use |Ai(-z)|, |Bi(-z)| <= |Ai(z exp(pi i/3))| + |Ai(z exp(-pi i/3))| */ void acb_hypgeom_airy_bound_arg_ge_2pi3(mag_t A, mag_t B, const acb_t z, slong wp) { acb_t zeta, z1, z2; acb_init(zeta); acb_init(z1); acb_init(z2); arb_sqrt_ui(acb_imagref(z1), 3, wp); arb_one(acb_realref(z1)); acb_mul_2exp_si(z1, z1, -1); acb_conj(z2, z1); acb_neg_round(zeta, z, wp); acb_mul(z1, z1, zeta, wp); acb_sqrt(zeta, zeta, wp); acb_cube(zeta, zeta, wp); acb_mul_2exp_si(zeta, zeta, 1); acb_div_ui(zeta, zeta, 3, wp); acb_mul_onei(zeta, zeta); acb_hypgeom_airy_bound_9_7_17(A, z1, zeta); /* conjugate symmetry */ if (arb_is_zero(acb_imagref(z))) { mag_mul_2exp_si(A, A, 1); } else { mag_t D; mag_init(D); acb_mul(z2, z2, zeta, wp); acb_neg(zeta, zeta); acb_hypgeom_airy_bound_9_7_17(D, z2, zeta); mag_add(A, A, D); mag_clear(D); } if (B != NULL) mag_set(B, A); acb_clear(zeta); acb_clear(z1); acb_clear(z2); } static int arg_lt_2pi3_fast(const acb_t z) { arf_t t; mag_t x, y, s; int res; if (arb_is_zero(acb_imagref(z)) && arb_is_nonnegative(acb_realref(z))) return 1; arf_init(t); mag_init(x); mag_init(y); mag_init(s); arf_set_mag(t, arb_radref(acb_realref(z))); arf_sub(t, arb_midref(acb_realref(z)), t, MAG_BITS, ARF_RND_FLOOR); if (arf_sgn(t) >= 0) { res = 1; } else { arf_get_mag(x, t); arb_get_mag_lower(y, acb_imagref(z)); mag_set_ui(s, 3); mag_sqrt(s, s); mag_mul(s, s, x); res = mag_cmp(s, y) <= 0; } arf_clear(t); mag_clear(x); mag_clear(y); mag_clear(s); return res; } static int arg_gt_2pi3_fast(const acb_t z) { arf_t t; mag_t x, y, s; int res; if (arb_is_zero(acb_imagref(z)) && arb_is_negative(acb_realref(z))) return 1; arf_init(t); mag_init(x); mag_init(y); mag_init(s); arf_set_mag(t, arb_radref(acb_realref(z))); arf_add(t, arb_midref(acb_realref(z)), t, MAG_BITS, ARF_RND_CEIL); if (arf_sgn(t) >= 0) { res = 0; } else { arf_get_mag_lower(x, t); arb_get_mag(y, acb_imagref(z)); mag_set_ui_lower(s, 3); mag_sqrt_lower(s, s); mag_mul_lower(s, s, x); res = mag_cmp(s, y) >= 0; } arf_clear(t); mag_clear(x); mag_clear(y); mag_clear(s); return res; } void acb_hypgeom_airy_bound(mag_t ai, mag_t aip, mag_t bi, mag_t bip, const acb_t z) { acb_t zeta; mag_t A, B, D, zlo, zhi; slong wp; int near_zero; /* Fast and slightly tighter bounds for real z <= 0 */ /* Todo: could implement bounds for z >= 0 too */ if (acb_is_real(z) && arb_is_nonpositive(acb_realref(z))) { mag_init(zlo); mag_init(zhi); mag_init(A); mag_init(B); mag_init(D); if (ai != NULL || bi != NULL) { acb_get_mag_lower(zlo, z); mag_rsqrt(A, zlo); mag_sqrt(A, A); mag_mul_ui(A, A, 150); mag_set_ui(D, 160); mag_min(A, A, D); mag_mul_2exp_si(A, A, -8); if (ai != NULL) mag_set(ai, A); if (bi != NULL) mag_set(bi, A); } if (aip != NULL || bip != NULL) { acb_get_mag(zhi, z); mag_sqrt(A, zhi); mag_sqrt(A, A); mag_mul_ui(A, A, 150); mag_set_ui(D, 160); mag_max(B, A, D); mag_mul_2exp_si(B, B, -8); mag_set_ui(D, 67); mag_max(A, A, D); mag_mul_2exp_si(A, A, -8); if (aip != NULL) mag_set(aip, A); if (bip != NULL) mag_set(bip, B); } mag_clear(zlo); mag_clear(zhi); mag_clear(A); mag_clear(B); mag_clear(D); return; } acb_init(zeta); mag_init(A); mag_init(B); mag_init(D); mag_init(zlo); mag_init(zhi); wp = MAG_BITS * 2; acb_get_mag_lower(zlo, z); acb_get_mag(zhi, z); if (mag_cmp_2exp_si(zhi, 0) <= 0) { /* inside unit circle -- don't look at asymptotics */ if (ai != NULL) mag_set_ui_2exp_si(ai, 159, -8); if (aip != NULL) mag_set_ui_2exp_si(aip, 125, -8); if (bi != NULL) mag_set_ui_2exp_si(bi, 310, -8); if (bip != NULL) mag_set_ui_2exp_si(bip, 239, -8); } else { /* look at asymptotics outside unit circle */ near_zero = mag_cmp_2exp_si(zlo, 0) <= 0; if (near_zero) mag_one(zlo); if (arg_lt_2pi3_fast(z)) { acb_hypgeom_airy_bound_arg_le_2pi3(A, (bi != NULL || bip != NULL) ? B : NULL, z, wp); } else if (arg_gt_2pi3_fast(z)) { acb_hypgeom_airy_bound_arg_ge_2pi3(A, (bi != NULL || bip != NULL) ? B : NULL, z, wp); } else { mag_t A2, B2; mag_init(A2); mag_init(B2); acb_hypgeom_airy_bound_arg_le_2pi3(A, (bi != NULL || bip != NULL) ? B : NULL, z, wp); acb_hypgeom_airy_bound_arg_ge_2pi3(A2, (bi != NULL || bip != NULL) ? B2 : NULL, z, wp); mag_max(A, A, A2); mag_max(B, B, A2); mag_clear(A2); mag_clear(B2); } /* bound |z|^(1/4) */ mag_sqrt(zhi, zhi); mag_sqrt(zhi, zhi); /* bound |z|^(-1/4) */ mag_rsqrt(zlo, zlo); mag_sqrt(zlo, zlo); if (ai != NULL) mag_mul(ai, A, zlo); if (aip != NULL) mag_mul(aip, A, zhi); if (bi != NULL) mag_mul(bi, B, zlo); if (bip != NULL) mag_mul(bip, B, zhi); if (near_zero) { /* max by bounds on the unit circle */ if (ai != NULL) { mag_set_ui_2exp_si(D, 159, -8); mag_max(ai, ai, D); } if (aip != NULL) { mag_set_ui_2exp_si(D, 125, -8); mag_max(aip, aip, D); } if (bi != NULL) { mag_set_ui_2exp_si(D, 310, -8); mag_max(bi, bi, D); } if (bip != NULL) { mag_set_ui_2exp_si(D, 239, -8); mag_max(bip, bip, D); } } } acb_clear(zeta); mag_clear(A); mag_clear(B); mag_clear(D); mag_clear(zlo); mag_clear(zhi); } flint-3.1.3/src/acb_hypgeom/airy_direct.c000066400000000000000000000155011461254215100203430ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" #include "acb.h" #include "acb_hypgeom.h" void arb_const_airy_ai0_eval(arb_t y, slong prec) { arb_t t; fmpq_t v; arb_init(t); fmpq_init(v); arb_set_ui(y, 3); arb_root_ui(y, y, 3, prec + 5); arb_mul(y, y, y, prec + 5); fmpq_set_si(v, 2, 3); arb_gamma_fmpq(t, v, prec + 5); arb_mul(y, y, t, prec + 5); arb_inv(y, y, prec); arb_clear(t); fmpq_clear(v); } void arb_const_airy_ai1_eval(arb_t y, slong prec) { arb_t t; fmpq_t v; arb_init(t); fmpq_init(v); arb_set_ui(y, 3); arb_root_ui(y, y, 3, prec + 5); fmpq_set_si(v, 1, 3); arb_gamma_fmpq(t, v, prec + 5); arb_mul(y, y, t, prec + 5); arb_inv(y, y, prec); arb_neg(y, y); arb_clear(t); fmpq_clear(v); } void arb_const_airy_bi0_eval(arb_t y, slong prec) { arb_t t; fmpq_t v; arb_init(t); fmpq_init(v); arb_set_ui(y, 3); arb_root_ui(y, y, 6, prec + 5); fmpq_set_si(v, 2, 3); arb_gamma_fmpq(t, v, prec + 5); arb_mul(y, y, t, prec + 5); arb_inv(y, y, prec); arb_clear(t); fmpq_clear(v); } void arb_const_airy_bi1_eval(arb_t y, slong prec) { arb_t t; fmpq_t v; arb_init(t); fmpq_init(v); arb_set_ui(y, 3); arb_root_ui(y, y, 6, prec + 5); fmpq_set_si(v, 1, 3); arb_gamma_fmpq(t, v, prec + 5); arb_div(y, y, t, prec); arb_clear(t); fmpq_clear(v); } ARB_DEF_CACHED_CONSTANT(arb_const_airy_ai0, arb_const_airy_ai0_eval) ARB_DEF_CACHED_CONSTANT(arb_const_airy_ai1, arb_const_airy_ai1_eval) ARB_DEF_CACHED_CONSTANT(arb_const_airy_bi0, arb_const_airy_bi0_eval) ARB_DEF_CACHED_CONSTANT(arb_const_airy_bi1, arb_const_airy_bi1_eval) static void acb_hypgeom_airy_0f1_sum_inner(acb_t s, acb_srcptr t, slong m, slong n, slong alpha, int real, slong prec) { slong j, k; mp_limb_t c, chi, clo; acb_zero(s); /* not implemented (coefficient overflow) */ if (FLINT_BITS == 32 && n > 37000) { acb_indeterminate(s); return; } c = 1; j = (n - 1) % m; for (k = n - 1; k >= 0; k--) { if (k != 0) { umul_ppmm(chi, clo, c, 3 * k + alpha); if (chi == 0) umul_ppmm(chi, clo, clo, k); if (chi != 0) { acb_div_ui(s, s, c, prec); c = 1; } } if (real) arb_addmul_ui(acb_realref(s), acb_realref(t + j), c, prec); else acb_addmul_ui(s, t + j, c, prec); if (k != 0) { c = c * k * (3 * k + alpha); if (j == 0) { acb_mul(s, s, t + m, prec); j = m - 1; } else { j--; } } } acb_div_ui(s, s, c, prec); } /* s1 = 0F1(1/3, z/3) s2 = 0F1(2/3, z/3) s4 = 0F1(4/3, z/3) s5 = 0F1(5/3, z/3) */ static void acb_hypgeom_airy_0f1_sum(acb_t s1, acb_t s2, acb_t s4, acb_t s5, const acb_t z, slong n, int real, slong prec) { acb_ptr t; slong m; m = 2 * n_sqrt(n); m = FLINT_MAX(m, 1); t = _acb_vec_init(m + 1); _acb_vec_set_powers(t, z, m + 1, prec); if (s1 != NULL) acb_hypgeom_airy_0f1_sum_inner(s1, t, m, n, -2, real, prec); if (s2 != NULL) acb_hypgeom_airy_0f1_sum_inner(s2, t, m, n, -1, real, prec); if (s4 != NULL) acb_hypgeom_airy_0f1_sum_inner(s4, t, m, n, +1, real, prec); if (s5 != NULL) acb_hypgeom_airy_0f1_sum_inner(s5, t, m, n, +2, real, prec); _acb_vec_clear(t, m + 1); } void acb_hypgeom_airy_direct(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong n, slong prec) { mag_t err, wmag, tm; int is_real; acb_t s1, s2, s4, s5, t, u; arb_t ai0, ai1, bi0, bi1; mag_init(err); mag_init(wmag); mag_init(tm); acb_init(s1); acb_init(s2); acb_init(s4); acb_init(s5); acb_init(t); acb_init(u); arb_init(ai0); arb_init(ai1); arb_init(bi0); arb_init(bi1); n = FLINT_MAX(n, 2); is_real = acb_is_real(z); acb_get_mag(wmag, z); /* With w = z^3/9, the terms are bounded by 3 w^n / [(n-1)!]^2. 3 w^n w w^2 ---------- [ 1 + --- + ------- + ....] ((n-1)!)^2 n^2 (n+1)^2 */ mag_pow_ui(wmag, wmag, 3); mag_div_ui(wmag, wmag, 9); mag_pow_ui(err, wmag, n); mag_div_ui(tm, wmag, n); mag_div_ui(tm, tm, n); mag_geom_series(tm, tm, 0); mag_mul(err, err, tm); mag_rfac_ui(tm, n - 1); mag_mul(tm, tm, tm); mag_mul(err, err, tm); mag_mul_ui(err, err, 3); acb_cube(t, z, prec); acb_div_ui(t, t, 3, prec); acb_hypgeom_airy_0f1_sum( (aip != NULL || bip != NULL) ? s1 : NULL, (ai != NULL || bi != NULL) ? s2 : NULL, (ai != NULL || bi != NULL) ? s4 : NULL, (aip != NULL || bip != NULL) ? s5 : NULL, t, n, is_real, prec); if (is_real) { arb_add_error_mag(acb_realref(s1), err); arb_add_error_mag(acb_realref(s2), err); arb_add_error_mag(acb_realref(s4), err); arb_add_error_mag(acb_realref(s5), err); } else { acb_add_error_mag(s1, err); acb_add_error_mag(s2, err); acb_add_error_mag(s4, err); acb_add_error_mag(s5, err); } if (ai != NULL || aip != NULL) { arb_const_airy_ai0(ai0, prec); arb_const_airy_ai1(ai1, prec); } if (bi != NULL || bip != NULL) { arb_const_airy_bi0(bi0, prec); arb_const_airy_bi1(bi1, prec); } /* support aliasing with z */ acb_set(t, z); if (ai != NULL || bi != NULL) { acb_mul(u, s4, t, prec); if (ai != NULL) { acb_mul_arb(ai, s2, ai0, prec); acb_addmul_arb(ai, u, ai1, prec); } if (bi != NULL) { acb_mul_arb(bi, s2, bi0, prec); acb_addmul_arb(bi, u, bi1, prec); } } if (aip != NULL || bip != NULL) { acb_mul(u, t, t, prec); acb_mul_2exp_si(u, u, -1); acb_mul(u, u, s5, prec); if (aip != NULL) { acb_mul_arb(aip, s1, ai1, prec); acb_addmul_arb(aip, u, ai0, prec); } if (bip != NULL) { acb_mul_arb(bip, s1, bi1, prec); acb_addmul_arb(bip, u, bi0, prec); } } mag_clear(err); mag_clear(wmag); mag_clear(tm); acb_clear(s1); acb_clear(s2); acb_clear(s4); acb_clear(s5); acb_clear(t); acb_clear(u); arb_clear(ai0); arb_clear(ai1); arb_clear(bi0); arb_clear(bi1); } flint-3.1.3/src/acb_hypgeom/airy_jet.c000066400000000000000000000023461461254215100176560ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" static void airy_recurrence(acb_ptr ai, const acb_t z, slong len, slong prec) { slong k; if (len >= 3) { acb_mul(ai + 2, ai, z, prec); acb_mul_2exp_si(ai + 2, ai + 2, -1); } for (k = 3; k < len; k++) { acb_mul(ai + k, ai + k - 2, z, prec); acb_add(ai + k, ai + k, ai + k - 3, prec); acb_div_ui(ai + k, ai + k, k * (k - 1), prec); } } void acb_hypgeom_airy_jet(acb_ptr ai, acb_ptr bi, const acb_t z, slong len, slong prec) { if (len <= 0) return; if (len == 1) { acb_hypgeom_airy(ai, NULL, bi, NULL, z, prec); return; } acb_hypgeom_airy(ai, ai ? (ai + 1) : NULL, bi, bi ? (bi + 1) : NULL, z, prec); if (ai != NULL) airy_recurrence(ai, z, len, prec); if (bi != NULL) airy_recurrence(bi, z, len, prec); } flint-3.1.3/src/acb_hypgeom/airy_series.c000066400000000000000000000066111461254215100203650ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_airy_series(acb_ptr ai, acb_ptr ai_prime, acb_ptr bi, acb_ptr bi_prime, acb_srcptr z, slong zlen, slong len, slong prec) { acb_ptr t, u, v; slong tlen = len + ((ai_prime != NULL) || (bi_prime != NULL)); zlen = FLINT_MIN(zlen, len); if (zlen <= 0) return; if (zlen == 1) { acb_hypgeom_airy(ai, ai_prime, bi, bi_prime, z, prec); return; } t = _acb_vec_init(tlen); u = _acb_vec_init(tlen); v = _acb_vec_init(len); acb_hypgeom_airy_jet((ai || ai_prime) ? t : NULL, (bi || bi_prime) ? u : NULL, z, tlen, prec); /* compose with nonconstant part */ acb_zero(v); _acb_vec_set(v + 1, z + 1, zlen - 1); if (ai != NULL) _acb_poly_compose_series(ai, t, len, v, zlen, len, prec); if (bi != NULL) _acb_poly_compose_series(bi, u, len, v, zlen, len, prec); /* todo: use chain rule to avoid compositions for derivatives? */ if (ai_prime != NULL) { _acb_poly_derivative(t, t, len + 1, prec); _acb_poly_compose_series(ai_prime, t, len, v, zlen, len, prec); } if (bi_prime != NULL) { _acb_poly_derivative(u, u, len + 1, prec); _acb_poly_compose_series(bi_prime, u, len, v, zlen, len, prec); } _acb_vec_clear(t, tlen); _acb_vec_clear(u, tlen); _acb_vec_clear(v, len); } void acb_hypgeom_airy_series(acb_poly_t ai, acb_poly_t ai_prime, acb_poly_t bi, acb_poly_t bi_prime, const acb_poly_t z, slong len, slong prec) { if (len == 0) { if (ai != NULL) acb_poly_zero(ai); if (ai_prime != NULL) acb_poly_zero(ai_prime); if (bi != NULL) acb_poly_zero(bi); if (bi_prime != NULL) acb_poly_zero(bi_prime); return; } if (z->length <= 1) len = 1; if (ai != NULL) acb_poly_fit_length(ai, len); if (ai_prime != NULL) acb_poly_fit_length(ai_prime, len); if (bi != NULL) acb_poly_fit_length(bi, len); if (bi_prime != NULL) acb_poly_fit_length(bi_prime, len); if (z->length == 0) { acb_t t; acb_init(t); _acb_hypgeom_airy_series( ai ? ai->coeffs : NULL, ai_prime ? ai_prime->coeffs : NULL, bi ? bi->coeffs : NULL, bi_prime ? bi_prime->coeffs : NULL, t, 1, len, prec); acb_clear(t); } else { _acb_hypgeom_airy_series( ai ? ai->coeffs : NULL, ai_prime ? ai_prime->coeffs : NULL, bi ? bi->coeffs : NULL, bi_prime ? bi_prime->coeffs : NULL, z->coeffs, z->length, len, prec); } if (ai != NULL) { _acb_poly_set_length(ai, len); _acb_poly_normalise(ai); } if (ai_prime != NULL) { _acb_poly_set_length(ai_prime, len); _acb_poly_normalise(ai_prime); } if (bi != NULL) { _acb_poly_set_length(bi, len); _acb_poly_normalise(bi); } if (bi_prime != NULL) { _acb_poly_set_length(bi_prime, len); _acb_poly_normalise(bi_prime); } } flint-3.1.3/src/acb_hypgeom/bessel_i.c000066400000000000000000000147401461254215100176360ustar00rootroot00000000000000/* Copyright (C) 2014-2015, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void acb_hypgeom_bessel_i_asymp_prefactors(acb_t A, acb_t B, acb_t C, const acb_t nu, const acb_t z, int scaled, slong prec) { acb_t t, u; acb_init(t); acb_init(u); /* C = (2 pi z)^(-1/2) */ acb_const_pi(C, prec); acb_mul_2exp_si(C, C, 1); acb_mul(C, C, z, prec); acb_rsqrt(C, C, prec); if (arb_is_positive(acb_imagref(z)) || (arb_is_zero(acb_imagref(z)) && arb_is_negative(acb_realref(z)))) { acb_exp_pi_i(t, nu, prec); acb_mul_onei(t, t); } else if (arb_is_negative(acb_imagref(z)) || (arb_is_zero(acb_imagref(z)) && arb_is_positive(acb_realref(z)))) { acb_neg(t, nu); acb_exp_pi_i(t, t, prec); acb_mul_onei(t, t); acb_neg(t, t); } else { acb_exp_pi_i(t, nu, prec); acb_mul_onei(t, t); acb_neg(u, nu); acb_exp_pi_i(u, u, prec); acb_mul_onei(u, u); acb_neg(u, u); arb_union(acb_realref(t), acb_realref(t), acb_realref(u), prec); arb_union(acb_imagref(t), acb_imagref(t), acb_imagref(u), prec); } if (scaled) { acb_neg(u, z); acb_mul_2exp_si(u, u, 1); acb_exp(u, u, prec); acb_mul(A, t, u, prec); acb_one(B); } else { acb_exp_invexp(B, A, z, prec); acb_mul(A, A, t, prec); } acb_clear(t); acb_clear(u); } void acb_hypgeom_bessel_i_asymp(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { acb_t A1, A2, C, U1, U2, s, t, u; int is_real, is_imag; acb_init(A1); acb_init(A2); acb_init(C); acb_init(U1); acb_init(U2); acb_init(s); acb_init(t); acb_init(u); is_imag = 0; is_real = acb_is_real(nu) && acb_is_real(z) && (acb_is_int(nu) || arb_is_positive(acb_realref(z))); if (!is_real && !scaled && arb_is_zero(acb_realref(z)) && acb_is_int(nu)) { acb_mul_2exp_si(t, nu, -1); if (acb_is_int(t)) is_real = 1; else is_imag = 1; } if (scaled) is_imag = 0; acb_hypgeom_bessel_i_asymp_prefactors(A1, A2, C, nu, z, scaled, prec); /* todo: if Ap ~ 2^a and Am = 2^b and U1 ~ U2 ~ 1, change precision? */ if (!acb_is_finite(A1) || !acb_is_finite(A2) || !acb_is_finite(C)) { acb_indeterminate(res); } else { /* s = 1/2 + nu */ acb_one(s); acb_mul_2exp_si(s, s, -1); acb_add(s, s, nu, prec); /* t = 1 + 2 nu */ acb_mul_2exp_si(t, nu, 1); acb_add_ui(t, t, 1, prec); acb_mul_2exp_si(u, z, 1); acb_hypgeom_u_asymp(U1, s, t, u, -1, prec); acb_neg(u, u); acb_hypgeom_u_asymp(U2, s, t, u, -1, prec); acb_mul(res, A1, U1, prec); acb_addmul(res, A2, U2, prec); acb_mul(res, res, C, prec); if (is_real) arb_zero(acb_imagref(res)); if (is_imag) arb_zero(acb_realref(res)); } acb_clear(A1); acb_clear(A2); acb_clear(C); acb_clear(U1); acb_clear(U2); acb_clear(s); acb_clear(t); acb_clear(u); } void acb_hypgeom_bessel_i_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { acb_struct b[2]; acb_t w, c, t; if (acb_is_int(nu) && arb_is_negative(acb_realref(nu))) { acb_init(t); acb_neg(t, nu); acb_hypgeom_bessel_i_0f1(res, t, z, scaled, prec); acb_clear(t); return; } acb_init(b + 0); acb_init(b + 1); acb_init(w); acb_init(c); acb_init(t); acb_add_ui(b + 0, nu, 1, prec); acb_one(b + 1); /* (z/2)^nu / gamma(nu+1) */ acb_mul_2exp_si(c, z, -1); acb_pow(c, c, nu, prec); acb_rgamma(t, b + 0, prec); acb_mul(c, t, c, prec); /* z^2/4 */ acb_mul(w, z, z, prec); acb_mul_2exp_si(w, w, -2); acb_hypgeom_pfq_direct(t, NULL, 0, b, 2, w, -1, prec); if (scaled) { acb_neg(w, z); acb_exp(w, w, prec); acb_mul(t, t, w, prec); } acb_mul(res, t, c, prec); acb_clear(b + 0); acb_clear(b + 1); acb_clear(w); acb_clear(c); acb_clear(t); } void acb_hypgeom_bessel_i_nointegration(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { mag_t zmag; mag_init(zmag); acb_get_mag(zmag, z); if (mag_cmp_2exp_si(zmag, 4) < 0 || (mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec)) acb_hypgeom_bessel_i_0f1(res, nu, z, scaled, prec); else acb_hypgeom_bessel_i_asymp(res, nu, z, scaled, prec); mag_clear(zmag); } void _acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { acb_t res2; slong acc, max, t; acb_init(res2); acb_hypgeom_bessel_i_nointegration(res2, nu, z, scaled, prec); acc = acb_rel_accuracy_bits(res2); if (acc < 0.5 * prec) { max = prec; t = acb_rel_accuracy_bits(z); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(nu); max = FLINT_MIN(max, t); if (max > 2 && acc < 0.5 * max) { if (acb_is_real(nu) && acb_is_real(z) && arf_cmp_2exp_si(arb_midref(acb_realref(nu)), -1) > 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(nu)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0) { arb_hypgeom_bessel_i_integration(acb_realref(res), acb_realref(nu), acb_realref(z), scaled, prec); arb_zero(acb_imagref(res)); if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) || (acb_is_finite(res) && !acb_is_finite(res2))) { acb_swap(res, res2); } } } } acb_swap(res, res2); acb_clear(res2); } void acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, slong prec) { _acb_hypgeom_bessel_i(res, nu, z, 0, prec); } void acb_hypgeom_bessel_i_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec) { _acb_hypgeom_bessel_i(res, nu, z, 1, prec); } flint-3.1.3/src/acb_hypgeom/bessel_j.c000066400000000000000000000131531461254215100176340ustar00rootroot00000000000000/* Copyright (C) 2014-2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* assumes no aliasing */ /* (+/- iz)^(-1/2-v) * z^v * exp(+/- iz) */ void acb_hypgeom_bessel_j_asymp_prefactors_fallback(acb_t Ap, acb_t Am, acb_t C, const acb_t nu, const acb_t z, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); /* v = -1/2-nu */ acb_one(v); acb_mul_2exp_si(v, v, -1); acb_add(v, v, nu, prec); acb_neg(v, v); acb_mul_onei(t, z); /* t = iz */ acb_neg(u, t); /* u = -iz */ /* Ap, Am = (+/- iz)^(-1/2-nu) */ acb_pow(Ap, t, v, prec); acb_pow(Am, u, v, prec); /* Ap, Am *= exp(+/- iz) */ acb_exp_invexp(u, v, t, prec); acb_mul(Ap, Ap, u, prec); acb_mul(Am, Am, v, prec); /* z^nu */ acb_pow(t, z, nu, prec); acb_mul(Ap, Ap, t, prec); acb_mul(Am, Am, t, prec); /* (2 pi)^(-1/2) */ acb_const_pi(C, prec); acb_mul_2exp_si(C, C, 1); acb_rsqrt(C, C, prec); acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_bessel_j_asymp_prefactors(acb_t Ap, acb_t Am, acb_t C, const acb_t nu, const acb_t z, slong prec) { if (arb_is_positive(acb_realref(z))) { acb_t t, u; acb_init(t); acb_init(u); /* -(2nu+1)/4 * pi + z */ acb_mul_2exp_si(t, nu, 1); acb_add_ui(t, t, 1, prec); acb_mul_2exp_si(t, t, -2); acb_neg(t, t); acb_const_pi(u, prec); acb_mul(t, t, u, prec); acb_add(t, t, z, prec); acb_mul_onei(t, t); acb_exp_invexp(Ap, Am, t, prec); /* (2 pi z)^(-1/2) */ acb_const_pi(C, prec); acb_mul_2exp_si(C, C, 1); acb_mul(C, C, z, prec); acb_rsqrt(C, C, prec); acb_clear(t); acb_clear(u); return; } acb_hypgeom_bessel_j_asymp_prefactors_fallback(Ap, Am, C, nu, z, prec); } void acb_hypgeom_bessel_j_asymp(acb_t res, const acb_t nu, const acb_t z, slong prec) { acb_t A1, A2, C, U1, U2, s, t, u; int is_real, is_imag; /* zero at -inf and +inf when nu is finite */ if (acb_is_finite(nu) && !acb_is_finite(z) && acb_is_real(z) && !acb_contains_zero(z)) { acb_zero(res); return; } acb_init(A1); acb_init(A2); acb_init(C); acb_init(U1); acb_init(U2); acb_init(s); acb_init(t); acb_init(u); is_imag = 0; is_real = acb_is_real(nu) && acb_is_real(z) && (acb_is_int(nu) || arb_is_positive(acb_realref(z))); if (!is_real && arb_is_zero(acb_realref(z)) && acb_is_int(nu)) { acb_mul_2exp_si(t, nu, -1); if (acb_is_int(t)) is_real = 1; else is_imag = 1; } acb_hypgeom_bessel_j_asymp_prefactors(A1, A2, C, nu, z, prec); /* todo: if Ap ~ 2^a and Am = 2^b and U1 ~ U2 ~ 1, change precision? */ if (!acb_is_finite(A1) || !acb_is_finite(A2) || !acb_is_finite(C)) { acb_indeterminate(res); } else { /* s = 1/2 + nu */ acb_one(s); acb_mul_2exp_si(s, s, -1); acb_add(s, s, nu, prec); /* t = 1 + 2 nu */ acb_mul_2exp_si(t, nu, 1); acb_add_ui(t, t, 1, prec); acb_mul_onei(u, z); acb_mul_2exp_si(u, u, 1); acb_hypgeom_u_asymp(U2, s, t, u, -1, prec); acb_neg(u, u); acb_hypgeom_u_asymp(U1, s, t, u, -1, prec); acb_mul(res, A1, U1, prec); acb_addmul(res, A2, U2, prec); acb_mul(res, res, C, prec); if (is_real) arb_zero(acb_imagref(res)); if (is_imag) arb_zero(acb_realref(res)); } acb_clear(A1); acb_clear(A2); acb_clear(C); acb_clear(U1); acb_clear(U2); acb_clear(s); acb_clear(t); acb_clear(u); } void acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, slong prec) { acb_struct b[2]; acb_t w, c, t; if (acb_is_int(nu) && arb_is_negative(acb_realref(nu))) { acb_init(t); acb_neg(t, nu); acb_hypgeom_bessel_j_0f1(res, t, z, prec); acb_mul_2exp_si(t, t, -1); if (!acb_is_int(t)) acb_neg(res, res); acb_clear(t); return; } acb_init(b + 0); acb_init(b + 1); acb_init(w); acb_init(c); acb_init(t); acb_add_ui(b + 0, nu, 1, prec); acb_one(b + 1); /* (z/2)^nu / gamma(nu+1) */ acb_mul_2exp_si(c, z, -1); acb_pow(c, c, nu, prec); acb_rgamma(t, b + 0, prec); acb_mul(c, t, c, prec); /* -z^2/4 */ acb_mul(w, z, z, prec); acb_mul_2exp_si(w, w, -2); acb_neg(w, w); acb_hypgeom_pfq_direct(t, NULL, 0, b, 2, w, -1, prec); acb_mul(res, t, c, prec); acb_clear(b + 0); acb_clear(b + 1); acb_clear(w); acb_clear(c); acb_clear(t); } /* The asymptotic series can be used roughly when [(1+log(2))/log(2) = 2.44269504088896] * z > p We are a bit more conservative and use the factor 2. */ void acb_hypgeom_bessel_j(acb_t res, const acb_t nu, const acb_t z, slong prec) { mag_t zmag; mag_init(zmag); acb_get_mag(zmag, z); if (mag_cmp_2exp_si(zmag, 4) < 0 || (mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec)) acb_hypgeom_bessel_j_0f1(res, nu, z, prec); else acb_hypgeom_bessel_j_asymp(res, nu, z, prec); mag_clear(zmag); } flint-3.1.3/src/acb_hypgeom/bessel_k.c000066400000000000000000000156661461254215100176500ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void acb_hypgeom_bessel_k_asymp(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { acb_t t, a, b, w; acb_init(t); acb_init(a); acb_init(b); acb_init(w); acb_one(a); acb_mul_2exp_si(a, a, -1); acb_add(a, a, nu, prec); acb_mul_2exp_si(b, nu, 1); acb_add_ui(b, b, 1, prec); acb_mul_2exp_si(w, z, 1); acb_hypgeom_u_asymp(t, a, b, w, -1, prec); if (!scaled) { acb_neg(a, z); acb_exp(a, a, prec); acb_mul(t, t, a, prec); } acb_mul_2exp_si(w, z, 1); acb_rsqrt(w, w, prec); acb_mul(res, t, w, prec); arb_const_sqrt_pi(acb_realref(w), prec); acb_mul_arb(res, res, acb_realref(w), prec); acb_clear(t); acb_clear(a); acb_clear(b); acb_clear(w); } void acb_hypgeom_bessel_k_0f1_series(acb_poly_t res, const acb_poly_t nu, const acb_poly_t z, int scaled, slong len, slong prec) { acb_poly_t s, u, A, B; acb_poly_struct b[2]; arb_t c; slong wlen; int singular; acb_poly_init(s); acb_poly_init(u); acb_poly_init(A); acb_poly_init(B); acb_poly_init(b + 0); acb_poly_init(b + 1); arb_init(c); singular = (nu->length == 0) || acb_is_int(nu->coeffs); wlen = len + (singular != 0); /* A = (z/2)^nu, B = 1/A */ acb_poly_scalar_mul_2exp_si(A, z, -1); acb_poly_pow_series(A, A, nu, wlen, prec); acb_poly_inv_series(B, A, wlen, prec); acb_poly_mullow(u, z, z, wlen, prec); acb_poly_scalar_mul_2exp_si(u, u, -2); acb_poly_one(b + 1); acb_poly_add_si(b + 0, nu, 1, prec); acb_hypgeom_pfq_series_direct(s, NULL, 0, b, 2, u, 1, -1, wlen, prec); acb_poly_mullow(A, A, s, wlen, prec); acb_poly_add_si(b + 0, nu, -1, prec); acb_poly_neg(b + 0, b + 0); acb_hypgeom_pfq_series_direct(s, NULL, 0, b, 2, u, 1, -1, wlen, prec); acb_poly_mullow(B, B, s, wlen, prec); acb_poly_sub(A, B, A, prec); acb_poly_scalar_mul_2exp_si(A, A, -1); /* multiply by pi csc(pi nu) */ acb_poly_sin_pi_series(B, nu, wlen, prec); if (singular) { acb_poly_shift_right(A, A, 1); acb_poly_shift_right(B, B, 1); } if (scaled) { acb_poly_exp_series(u, z, len, prec); acb_poly_mullow(A, A, u, len, prec); } acb_poly_div_series(res, A, B, len, prec); arb_const_pi(c, prec); _acb_vec_scalar_mul_arb(res->coeffs, res->coeffs, res->length, c, prec); acb_poly_clear(s); acb_poly_clear(u); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(b + 0); acb_poly_clear(b + 1); arb_clear(c); } void acb_hypgeom_bessel_k_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { if (acb_is_int(nu)) { acb_poly_t nux, zx, rx; acb_poly_init(nux); acb_poly_init(zx); acb_poly_init(rx); acb_poly_set_coeff_acb(nux, 0, nu); acb_poly_set_coeff_si(nux, 1, 1); acb_poly_set_acb(zx, z); acb_hypgeom_bessel_k_0f1_series(rx, nux, zx, scaled, 1, prec); acb_poly_get_coeff_acb(res, rx, 0); acb_poly_clear(nux); acb_poly_clear(zx); acb_poly_clear(rx); } else { acb_t t, u, v, w; acb_struct b[2]; acb_init(t); acb_init(u); acb_init(v); acb_init(w); acb_init(b + 0); acb_init(b + 1); /* u = 0F1(1+nu), v = 0F1(1-nu) */ acb_mul(t, z, z, prec); acb_mul_2exp_si(t, t, -2); acb_add_ui(b, nu, 1, prec); acb_one(b + 1); acb_hypgeom_pfq_direct(u, NULL, 0, b, 2, t, -1, prec); acb_sub_ui(b, nu, 1, prec); acb_neg(b, b); acb_hypgeom_pfq_direct(v, NULL, 0, b, 2, t, -1, prec); /* v = v * gamma(nu) / (z/2)^nu */ acb_mul_2exp_si(t, z, -1); acb_pow(t, t, nu, prec); acb_gamma(w, nu, prec); acb_mul(v, v, w, prec); acb_div(v, v, t, prec); /* u = u * t * pi / (gamma(nu) * nu * sin(pi nu)) */ acb_mul(u, u, t, prec); acb_const_pi(t, prec); acb_mul(u, u, t, prec); acb_sin_pi(t, nu, prec); acb_mul(t, t, w, prec); acb_mul(t, t, nu, prec); acb_div(u, u, t, prec); acb_sub(v, v, u, prec); acb_mul_2exp_si(v, v, -1); if (scaled) { acb_exp(t, z, prec); acb_mul(v, v, t, prec); } acb_set(res, v); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); acb_clear(b + 0); acb_clear(b + 1); } } void acb_hypgeom_bessel_k_nointegration(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { mag_t zmag; mag_init(zmag); acb_get_mag(zmag, z); if (mag_cmp_2exp_si(zmag, 4) < 0 || (mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec)) acb_hypgeom_bessel_k_0f1(res, nu, z, scaled, prec); else acb_hypgeom_bessel_k_asymp(res, nu, z, scaled, prec); mag_clear(zmag); } void _acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec) { acb_t res2; slong acc, max, t; acb_init(res2); acb_hypgeom_bessel_k_nointegration(res2, nu, z, scaled, prec); acc = acb_rel_accuracy_bits(res2); if (acc < 0.5 * prec) { max = prec; t = acb_rel_accuracy_bits(z); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(nu); max = FLINT_MIN(max, t); if (max > 2 && acc < 0.5 * max) { if (acb_is_real(nu) && acb_is_real(z) && arf_cmp_d(arb_midref(acb_realref(nu)), -0.5) > 0 && arf_cmp_2exp_si(arb_midref(acb_realref(z)), -16) > 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(nu)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0) { arb_hypgeom_bessel_k_integration(acb_realref(res), acb_realref(nu), acb_realref(z), scaled, prec); arb_zero(acb_imagref(res)); if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) || (acb_is_finite(res) && !acb_is_finite(res2))) { acb_swap(res, res2); } } } } acb_swap(res, res2); acb_clear(res2); } void acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, slong prec) { _acb_hypgeom_bessel_k(res, nu, z, 0, prec); } void acb_hypgeom_bessel_k_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec) { _acb_hypgeom_bessel_k(res, nu, z, 1, prec); } flint-3.1.3/src/acb_hypgeom/bessel_y.c000066400000000000000000000050211461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" static void phase(acb_t res, const arb_t re, const arb_t im) { if (arb_is_nonnegative(re) || arb_is_negative(im)) { acb_one(res); } else if (arb_is_negative(re) && arb_is_nonnegative(im)) { acb_set_si(res, -3); } else { arb_zero(acb_imagref(res)); /* -1 +/- 2 */ arf_set_si(arb_midref(acb_realref(res)), -1); mag_one(arb_radref(acb_realref(res))); mag_mul_2exp_si(arb_radref(acb_realref(res)), arb_radref(acb_realref(res)), 1); } } void acb_hypgeom_bessel_jy(acb_t res1, acb_t res2, const acb_t nu, const acb_t z, slong prec) { acb_t jnu, t, u, v; /* both j and y are zero at -inf and +inf when nu is finite */ if (acb_is_finite(nu) && !acb_is_finite(z) && acb_is_real(z) && !acb_contains_zero(z)) { if (res1 != NULL) acb_zero(res1); acb_zero(res2); return; } acb_init(jnu); acb_init(t); acb_init(u); acb_init(v); acb_hypgeom_bessel_j(jnu, nu, z, prec); if (acb_is_int(nu)) { int is_real = acb_is_real(nu) && acb_is_real(z) && arb_is_positive(acb_realref(z)); acb_mul_onei(t, z); acb_hypgeom_bessel_k(t, nu, t, prec); acb_onei(u); acb_pow(u, u, nu, prec); acb_mul(t, t, u, prec); acb_const_pi(u, prec); acb_div(t, t, u, prec); acb_mul_2exp_si(t, t, 1); acb_neg(t, t); phase(v, acb_realref(z), acb_imagref(z)); acb_mul(u, jnu, v, prec); acb_mul_onei(u, u); acb_sub(res2, t, u, prec); if (is_real) arb_zero(acb_imagref(res2)); } else { acb_sin_cos_pi(t, u, nu, prec); acb_mul(v, jnu, u, prec); acb_neg(u, nu); acb_hypgeom_bessel_j(u, u, z, prec); acb_sub(v, v, u, prec); acb_div(res2, v, t, prec); } if (res1 != NULL) acb_set(res1, jnu); acb_clear(jnu); acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_bessel_y(acb_t res, const acb_t nu, const acb_t z, slong prec) { acb_hypgeom_bessel_jy(NULL, res, nu, z, prec); } flint-3.1.3/src/acb_hypgeom/beta_lower.c000066400000000000000000000034501461254215100201700ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* todo: move this to the acb module? */ static void acb_beta(acb_t res, const acb_t a, const acb_t b, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_gamma(t, a, prec); acb_gamma(u, b, prec); acb_add(res, a, b, prec); acb_rgamma(res, res, prec); acb_mul(res, res, t, prec); acb_mul(res, res, u, prec); acb_clear(t); acb_clear(u); } void acb_hypgeom_beta_lower(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { acb_t t, u; if (acb_is_zero(z) && arb_is_positive(acb_realref(a))) { acb_zero(res); return; } if (acb_is_one(z) && arb_is_positive(acb_realref(b))) { if (regularized) acb_one(res); else acb_beta(res, a, b, prec); return; } acb_init(t); acb_init(u); acb_sub_ui(t, b, 1, prec); acb_neg(t, t); acb_add_ui(u, a, 1, prec); if (regularized) { acb_hypgeom_2f1(t, a, t, u, z, 1, prec); acb_add(u, a, b, prec); acb_gamma(u, u, prec); acb_mul(t, t, u, prec); acb_rgamma(u, b, prec); acb_mul(t, t, u, prec); } else { acb_hypgeom_2f1(t, a, t, u, z, 0, prec); acb_div(t, t, a, prec); } acb_pow(u, z, a, prec); acb_mul(t, t, u, prec); acb_set(res, t); acb_clear(t); acb_clear(u); } flint-3.1.3/src/acb_hypgeom/beta_lower_series.c000066400000000000000000000055071461254215100215470ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_beta_lower_series(acb_ptr res, const acb_t a, const acb_t b, acb_srcptr z, slong zlen, int regularized, slong len, slong prec) { acb_ptr t, u, v; acb_t c, d, e; zlen = FLINT_MIN(zlen, len); if (zlen == 1) { acb_hypgeom_beta_lower(res, a, b, z, regularized, prec); _acb_vec_zero(res + 1, len - 1); return; } t = _acb_vec_init(len); u = _acb_vec_init(len); v = _acb_vec_init(zlen - 1); acb_init(c); acb_init(d); acb_init(e); acb_hypgeom_beta_lower(d, a, b, z, regularized, prec); if (regularized) { /* todo: except in special cases, we already compute a bunch of gamma functions in beta_lower, so we could avoid recomputing them */ acb_add(e, a, b, prec); acb_gamma(e, e, prec); acb_rgamma(c, a, prec); acb_mul(e, e, c, prec); acb_rgamma(c, b, prec); acb_mul(e, e, c, prec); } /* u = (1-z)^(b-1) */ _acb_vec_neg(t, z, zlen); acb_add_ui(t, t, 1, prec); acb_sub_ui(c, b, 1, prec); _acb_poly_pow_acb_series(u, t, FLINT_MIN(zlen, len - 1), c, len - 1, prec); /* t = z^(a-1) */ acb_sub_ui(c, a, 1, prec); _acb_poly_pow_acb_series(t, z, FLINT_MIN(zlen, len - 1), c, len - 1, prec); /* v = z' */ _acb_poly_derivative(v, z, zlen, prec); _acb_poly_mullow(res, t, len - 1, u, len - 1, len - 1, prec); _acb_poly_mullow(t, res, len - 1, v, zlen - 1, len - 1, prec); _acb_poly_integral(res, t, len, prec); if (regularized) { _acb_vec_scalar_mul(res, res, len, e, prec); } acb_set(res, d); _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(v, zlen - 1); acb_clear(c); acb_clear(d); acb_clear(e); } void acb_hypgeom_beta_lower_series(acb_poly_t res, const acb_t a, const acb_t b, const acb_poly_t z, int regularized, slong len, slong prec) { if (len == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, len); if (z->length == 0) { acb_t t; acb_init(t); _acb_hypgeom_beta_lower_series(res->coeffs, a, b, t, 1, regularized, len, prec); acb_clear(t); } else { _acb_hypgeom_beta_lower_series(res->coeffs, a, b, z->coeffs, z->length, regularized, len, prec); } _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_hypgeom/chebyshev_t.c000066400000000000000000000037341461254215100203550ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_chebyshev_t(acb_t res, const acb_t n, const acb_t z, slong prec) { acb_t t; if (acb_is_int(n) && arf_cmpabs_2exp_si(arb_midref(acb_realref(n)), FLINT_BITS - 1) < 0) { slong k = arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN); acb_chebyshev_t_ui(res, FLINT_ABS(k), z, prec); return; } if (acb_is_zero(z)) { acb_mul_2exp_si(res, n, -1); acb_cos_pi(res, res, prec); return; } if (acb_is_one(z)) { acb_one(res); return; } acb_init(t); acb_set_si(t, -1); if (acb_equal(t, z)) { acb_cos_pi(res, n, prec); } else { acb_sub_ui(t, z, 1, prec); if (arf_cmpabs_2exp_si(arb_midref(acb_realref(t)), -2 - prec / 10) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(t)), -2 - prec / 10) < 0) { acb_t a, c; acb_init(a); acb_init(c); acb_neg(a, n); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_hypgeom_2f1(res, a, n, c, t, 0, prec); acb_clear(a); acb_clear(c); } else if (arb_is_nonnegative(acb_realref(t))) { acb_acosh(t, z, prec); acb_mul(t, t, n, prec); acb_cosh(res, t, prec); } else { acb_acos(t, z, prec); acb_mul(t, t, n, prec); acb_cos(res, t, prec); } } acb_clear(t); } flint-3.1.3/src/acb_hypgeom/chebyshev_u.c000066400000000000000000000053051461254215100203520ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_chebyshev_u(acb_t res, const acb_t n, const acb_t z, slong prec) { acb_t t, u; if (acb_is_int(n) && arf_cmpabs_2exp_si(arb_midref(acb_realref(n)), FLINT_BITS - 1) < 0) { slong k = arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN); if (k >= 0) { acb_chebyshev_u_ui(res, k, z, prec); } else if (k == -1) { acb_zero(res); } else { acb_chebyshev_u_ui(res, -2-k, z, prec); acb_neg(res, res); } return; } if (acb_is_zero(z)) { acb_mul_2exp_si(res, n, -1); acb_cos_pi(res, res, prec); return; } if (acb_is_one(z)) { acb_add_ui(res, n, 1, prec); return; } acb_init(t); acb_init(u); acb_add_ui(u, n, 1, prec); acb_sub_ui(t, z, 1, prec); if (arf_cmpabs_2exp_si(arb_midref(acb_realref(t)), -2 - prec / 10) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(t)), -2 - prec / 10) < 0) { acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c); acb_neg(a, n); acb_add_ui(b, n, 2, prec); acb_set_ui(c, 3); acb_mul_2exp_si(c, c, -1); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_hypgeom_2f1(t, a, b, c, t, 0, prec); acb_mul(res, t, u, prec); acb_clear(a); acb_clear(b); acb_clear(c); } else { if (arb_is_positive(acb_realref(t))) { /* sinh((n+1) acosh(z)) / (sqrt(z-1) sqrt(z+1)); can use one square root when strictly in the right half plane */ acb_mul(t, z, z, prec); acb_sub_ui(t, t, 1, prec); acb_acosh(res, z, prec); acb_mul(res, res, u, prec); acb_sinh(res, res, prec); acb_rsqrt(t, t, prec); acb_mul(res, res, t, prec); } else { acb_mul(t, z, z, prec); acb_sub_ui(t, t, 1, prec); acb_acos(res, z, prec); acb_mul(res, res, u, prec); acb_sin(res, res, prec); acb_neg(t, t); acb_rsqrt(t, t, prec); acb_mul(res, res, t, prec); } } acb_clear(t); acb_clear(u); } flint-3.1.3/src/acb_hypgeom/chi.c000066400000000000000000000067521461254215100166200ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_chi_asymp(acb_t res, const acb_t z, slong prec) { acb_t t, u, v, one; acb_init(t); acb_init(u); acb_init(v); acb_init(one); acb_one(one); /* u = U(1,1,z) */ acb_hypgeom_u_asymp(u, one, one, z, -1, prec); /* v = e^(-z) */ acb_neg(v, z); acb_exp(v, v, prec); acb_mul(t, u, v, prec); if (arb_is_zero(acb_realref(z))) { arb_div(acb_realref(t), acb_imagref(t), acb_imagref(z), prec); arb_zero(acb_imagref(t)); acb_neg(t, t); } else { /* u = U(1,1,-z) */ acb_neg(u, z); acb_hypgeom_u_asymp(u, one, one, u, -1, prec); acb_inv(v, v, prec); acb_submul(t, u, v, prec); acb_div(t, t, z, prec); acb_mul_2exp_si(t, t, -1); acb_neg(t, t); } if (acb_is_real(z)) { if (arb_is_positive(acb_realref(z))) { arb_zero(acb_imagref(t)); } else if (arb_is_negative(acb_realref(z))) { arb_const_pi(acb_imagref(t), prec); } else { /* add [-pi,pi]/2 i */ acb_const_pi(u, prec); arb_zero(acb_imagref(t)); arb_add_error(acb_imagref(t), acb_realref(u)); } } else { /* -pi/2 if positive real or in lower half plane pi/2 if negative real or in upper half plane */ if (arb_is_negative(acb_imagref(z))) { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else if (arb_is_positive(acb_imagref(z))) { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else { /* add [-pi,pi]/2 i */ acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_add_error(acb_imagref(t), acb_realref(u)); } } acb_swap(res, t); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(one); } void acb_hypgeom_chi_2f3(acb_t res, const acb_t z, slong prec) { acb_t a, t, u; acb_struct b[3]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(b + 2); acb_init(t); acb_init(u); acb_one(a); acb_set_ui(b, 2); acb_set(b + 1, b); acb_set_ui(b + 2, 3); acb_mul_2exp_si(b + 2, b + 2, -1); acb_mul(t, z, z, prec); acb_mul_2exp_si(t, t, -2); acb_hypgeom_pfq_direct(u, a, 1, b, 3, t, -1, prec); acb_mul(u, u, t, prec); acb_log(t, z, prec); acb_add(u, u, t, prec); arb_const_euler(acb_realref(t), prec); arb_add(acb_realref(u), acb_realref(u), acb_realref(t), prec); acb_swap(res, u); acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(b + 2); acb_clear(t); acb_clear(u); } void acb_hypgeom_chi(acb_t res, const acb_t z, slong prec) { if (acb_hypgeom_u_use_asymp(z, prec)) acb_hypgeom_chi_asymp(res, z, prec); else acb_hypgeom_chi_2f3(res, z, prec); } flint-3.1.3/src/acb_hypgeom/chi_series.c000066400000000000000000000035161461254215100201650ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_chi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { acb_t c; if (acb_contains_zero(h)) { _acb_vec_indeterminate(g, len); return; } acb_init(c); acb_hypgeom_chi(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else { acb_ptr t, u, v; t = _acb_vec_init(len); u = _acb_vec_init(len); v = _acb_vec_init(len); /* Chi(h(x)) = integral([h'(x) / h(x)] cosh(h(x)) */ _acb_poly_cosh_series(t, h, hlen, len - 1, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec); _acb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec); _acb_poly_integral(g, u, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(v, len); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_chi_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_inv_series(g, h, len, prec); return; } acb_poly_fit_length(g, len); _acb_hypgeom_chi_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/ci.c000066400000000000000000000106771461254215100164510ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void acb_hypgeom_ci_asymp(acb_t res, const acb_t z, slong prec) { acb_t t, u, w, v, one; acb_init(t); acb_init(u); acb_init(w); acb_init(v); acb_init(one); acb_one(one); acb_mul_onei(w, z); /* u = U(1,1,iz) */ acb_hypgeom_u_asymp(u, one, one, w, -1, prec); /* v = e^(-iz) */ acb_neg(v, w); acb_exp(v, v, prec); acb_mul(t, u, v, prec); if (acb_is_real(z)) { arb_div(acb_realref(t), acb_imagref(t), acb_realref(z), prec); arb_zero(acb_imagref(t)); acb_neg(t, t); } else { /* u = U(1,1,-iz) */ acb_neg(w, w); acb_hypgeom_u_asymp(u, one, one, w, -1, prec); acb_inv(v, v, prec); acb_submul(t, u, v, prec); acb_div(t, t, w, prec); acb_mul_2exp_si(t, t, -1); } if (arb_is_zero(acb_realref(z))) { if (arb_is_positive(acb_imagref(z))) { arb_const_pi(acb_imagref(t), prec); arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1); } else if (arb_is_negative(acb_imagref(z))) { arb_const_pi(acb_imagref(t), prec); arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1); arb_neg(acb_imagref(t), acb_imagref(t)); } else { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_zero(acb_imagref(t)); arb_add_error(acb_imagref(t), acb_realref(u)); } } else { /* 0 if positive or positive imaginary pi if upper left quadrant (including negative real axis) -pi if lower left quadrant (including negative imaginary axis) */ if (arb_is_positive(acb_realref(z))) { /* do nothing */ } else if (arb_is_negative(acb_realref(z)) && arb_is_nonnegative(acb_imagref(z))) { acb_const_pi(u, prec); arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else if (arb_is_nonpositive(acb_realref(z)) && arb_is_negative(acb_imagref(z))) { acb_const_pi(u, prec); arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else { /* add [-pi,pi] */ acb_const_pi(u, prec); arb_add_error(acb_imagref(t), acb_realref(u)); } } acb_swap(res, t); acb_clear(t); acb_clear(u); acb_clear(w); acb_clear(v); acb_clear(one); } void acb_hypgeom_ci_2f3(acb_t res, const acb_t z, slong prec) { acb_t a, t, u; acb_struct b[3]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(b + 2); acb_init(t); acb_init(u); acb_one(a); acb_set_ui(b, 2); acb_set(b + 1, b); acb_set_ui(b + 2, 3); acb_mul_2exp_si(b + 2, b + 2, -1); acb_mul(t, z, z, prec); acb_mul_2exp_si(t, t, -2); acb_neg(t, t); acb_hypgeom_pfq_direct(u, a, 1, b, 3, t, -1, prec); acb_mul(u, u, t, prec); acb_log(t, z, prec); acb_add(u, u, t, prec); arb_const_euler(acb_realref(t), prec); arb_add(acb_realref(u), acb_realref(u), acb_realref(t), prec); acb_swap(res, u); acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(b + 2); acb_clear(t); acb_clear(u); } void acb_hypgeom_ci(acb_t res, const acb_t z, slong prec) { if (acb_is_real(z) && arb_is_finite(acb_realref(z))) { if (arb_is_positive(acb_realref(z))) { arb_hypgeom_ci(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); } else if (arb_is_negative(acb_realref(z))) { arb_neg(acb_realref(res), acb_realref(z)); arb_hypgeom_ci(acb_realref(res), acb_realref(res), prec); arb_const_pi(acb_imagref(res), prec); } else { acb_indeterminate(res); } return; } if (acb_hypgeom_u_use_asymp(z, prec)) acb_hypgeom_ci_asymp(res, z, prec); else acb_hypgeom_ci_2f3(res, z, prec); } flint-3.1.3/src/acb_hypgeom/ci_series.c000066400000000000000000000035071461254215100200150ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_ci_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { acb_t c; if (acb_contains_zero(h)) { _acb_vec_indeterminate(g, len); return; } acb_init(c); acb_hypgeom_ci(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else { acb_ptr t, u, v; t = _acb_vec_init(len); u = _acb_vec_init(len); v = _acb_vec_init(len); /* Ci(h(x)) = integral([h'(x) / h(x)] cos(h(x)) */ _acb_poly_cos_series(t, h, hlen, len - 1, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec); _acb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec); _acb_poly_integral(g, u, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(v, len); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_ci_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_inv_series(g, h, len, prec); return; } acb_poly_fit_length(g, len); _acb_hypgeom_ci_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/coulomb.c000066400000000000000000000230651461254215100175110ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" static void acb_hypgeom_coulomb_is_real(int * C, int * F, int * G, const acb_t l1, const acb_t eta, const acb_t z) { *C = *F = *G = 0; if (acb_is_real(l1) && acb_is_real(eta)) { if (arb_is_positive(acb_realref(l1)) || arb_is_nonzero(acb_realref(eta))) { *C = 1; } if (acb_is_real(z)) { if (arb_is_positive(acb_realref(z))) { *F = *G = 1; } if (acb_is_int(l1)) *F = 1; } } } void _acb_hypgeom_coulomb(acb_t F, acb_t G, acb_t Hpos, acb_t Hneg, const acb_t l, const acb_t eta, const acb_t z, int asymp, slong prec) { acb_t u, v, lu, lv, z1, z2, m, h, T1, T2, U1, U2, H1, H2, C, theta; int C_real, F_real, G_real; int want_U1, want_U2, cut; acb_init(u); acb_init(v); acb_init(lu); acb_init(lv); acb_init(z1); acb_init(z2); acb_init(m); acb_init(h); acb_init(T1); acb_init(T2); acb_init(U1); acb_init(U2); acb_init(H1); acb_init(H2); acb_init(C); acb_init(theta); acb_indeterminate(U1); acb_indeterminate(U2); /* z1 = 2iz, z2 = -2iz, */ acb_mul_onei(z1, z); acb_mul_2exp_si(z1, z1, 1); acb_neg(z2, z1); if (asymp == -1) asymp = acb_hypgeom_u_use_asymp(z1, prec); /* Need the union of both sides of the branch cut for G, H+, H-. */ if (arb_is_nonnegative(acb_imagref(z)) || arb_is_negative(acb_imagref(z)) || arb_is_positive(acb_realref(z))) cut = 0; else cut = 1; want_U1 = want_U2 = 0; if (asymp) { want_U1 = want_U2 = 1; } else { if (G != NULL || Hpos != NULL || Hneg != NULL) { if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) want_U1 = 1; else want_U2 = 1; if (cut) want_U1 = want_U2 = 1; } } /* m = l+1 */ acb_add_ui(m, l, 1, prec); acb_hypgeom_coulomb_is_real(&C_real, &F_real, &G_real, m, eta, z); /* u = 1+l+i eta, v = 1+l-i eta */ acb_mul_onei(u, eta); acb_add(u, u, m, prec); acb_div_onei(v, eta); acb_add(v, v, m, prec); /* lu = lgamma(u), v = lgamma(v) */ acb_lgamma(lu, u, prec); if (C_real) acb_conj(lv, lu); else acb_lgamma(lv, v, prec); /* m = 2l+2 */ acb_mul_2exp_si(m, m, 1); if (asymp) { if (want_U1 && want_U2 && G_real) { acb_hypgeom_u_asymp(U1, u, m, z2, -1, prec); acb_conj(U2, U1); } else { if (want_U1) acb_hypgeom_u_asymp(U1, u, m, z2, -1, prec); if (want_U2) acb_hypgeom_u_asymp(U2, v, m, z1, -1, prec); } } else { if (want_U1 && want_U2 && G_real) { acb_hypgeom_u(U1, u, m, z2, prec); acb_pow(h, z2, u, prec); acb_mul(U1, U1, h, prec); acb_conj(U2, U1); } else { if (want_U1) { acb_hypgeom_u(U1, u, m, z2, prec); acb_pow(h, z2, u, prec); acb_mul(U1, U1, h, prec); } if (want_U2) { acb_hypgeom_u(U2, v, m, z1, prec); acb_pow(h, z1, v, prec); acb_mul(U2, U2, h, prec); } } } /* C = exp((-pi eta + lu + lv)/2) */ acb_const_pi(C, prec); acb_mul(C, C, eta, prec); acb_neg(C, C); if (C_real) { acb_mul_2exp_si(T1, lu, 1); arb_zero(acb_imagref(T1)); acb_add(C, C, T1, prec); } else { acb_add(C, C, lu, prec); acb_add(C, C, lv, prec); } acb_mul_2exp_si(C, C, -1); /* https://fungrim.org/entry/1976e1/ */ if (asymp) { /* T1 = exp(-(-iz + lv + u log(z1)) U1 */ /* T2 = exp(-(+iz + lu + v log(z2)) U2 */ acb_log(T1, z1, prec); acb_mul(T1, T1, u, prec); acb_add(T1, T1, lv, prec); acb_mul_2exp_si(z1, z1, -1); acb_sub(T1, T1, z1, prec); acb_mul_2exp_si(z1, z1, 1); acb_neg(T1, T1); acb_exp(T1, T1, prec); acb_mul(T1, T1, U1, prec); if (F_real) { acb_mul_2exp_si(F, T1, 1); arb_zero(acb_imagref(F)); } else { acb_log(T2, z2, prec); acb_mul(T2, T2, v, prec); acb_add(T2, T2, lu, prec); acb_mul_2exp_si(z2, z2, -1); acb_sub(T2, T2, z2, prec); acb_mul_2exp_si(z2, z2, 1); acb_neg(T2, T2); acb_exp(T2, T2, prec); acb_mul(T2, T2, U2, prec); /* F = (T1 + T2) z C */ acb_add(F, T1, T2, prec); } } else { /* C *= exp(-iz) */ acb_div_onei(F, z); acb_add(C, C, F, prec); /* https://fungrim.org/entry/2a2f18/ */ acb_hypgeom_m(F, v, m, z1, 1, prec); } if (acb_contains_zero(z)) { acb_exp(C, C, prec); /* (2z)^l without logarithm */ acb_mul_2exp_si(h, z, 1); acb_pow(h, h, l, prec); acb_mul(C, C, h, prec); /* h = log(2z) */ acb_indeterminate(h); } else { /* h = log(2z) */ acb_mul_2exp_si(h, z, 1); acb_log(h, h, prec); acb_addmul(C, h, l, prec); acb_exp(C, C, prec); } acb_mul(F, F, C, prec); if (F_real) arb_zero(acb_imagref(F)); acb_mul(F, F, z, prec); if (G != NULL || Hpos != NULL || Hneg != NULL) { /* theta = z - eta h - 0.5 l pi + (lu - lv) / (2i) */ acb_sub(theta, lu, lv, prec); acb_div_onei(theta, theta); acb_mul_2exp_si(theta, theta, -1); acb_const_pi(H1, prec); acb_mul_2exp_si(H1, H1, -1); acb_submul(theta, H1, l, prec); acb_submul(theta, eta, h, prec); acb_add(theta, theta, z, prec); /* H1 = exp(+i theta) U1, H2 = exp(-i theta) U2 */ acb_mul_onei(H1, theta); acb_exp_invexp(H1, H2, H1, prec); acb_mul(H1, H1, U1, prec); acb_mul(H2, H2, U2, prec); if (G != NULL) { /* https://fungrim.org/entry/e2efbf/ */ if (asymp && arb_is_positive(acb_realref(z))) { if (G_real) { if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) acb_set(G, H1); else acb_set(G, H2); arb_zero(acb_imagref(G)); } else { acb_add(G, H1, H2, prec); acb_mul_2exp_si(G, G, -1); } } else { /* https://fungrim.org/entry/8027e8/ */ acb_div_onei(u, F); acb_add(u, H1, u, prec); /* https://fungrim.org/entry/69e5fb/ */ acb_mul_onei(v, F); acb_add(v, H2, v, prec); if (cut) acb_union(G, u, v, prec); else if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) acb_set(G, u); else acb_set(G, v); if (G_real) arb_zero(acb_imagref(G)); } } if (Hpos != NULL) { /* https://fungrim.org/entry/bcdfc6/ */ acb_set(u, H1); /* https://fungrim.org/entry/f0414a/ */ acb_mul_onei(v, F); acb_mul_2exp_si(v, v, 1); acb_add(v, H2, v, prec); if (cut) acb_union(Hpos, u, v, prec); else if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) acb_set(Hpos, u); else acb_set(Hpos, v); if (G_real) arb_set(acb_imagref(Hpos), acb_realref(F)); } if (Hneg != NULL) { /* https://fungrim.org/entry/0cc301/ */ acb_div_onei(u, F); acb_mul_2exp_si(u, u, 1); acb_add(u, H1, u, prec); /* https://fungrim.org/entry/781eae/ */ acb_set(v, H2); if (cut) acb_union(Hneg, u, v, prec); else if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) acb_set(Hneg, u); else acb_set(Hneg, v); if (G_real) arb_neg(acb_imagref(Hneg), acb_realref(F)); } } acb_clear(u); acb_clear(v); acb_clear(lu); acb_clear(lv); acb_clear(z1); acb_clear(z2); acb_clear(m); acb_clear(h); acb_clear(T1); acb_clear(T2); acb_clear(U1); acb_clear(U2); acb_clear(H1); acb_clear(H2); acb_clear(C); acb_clear(theta); } void acb_hypgeom_coulomb(acb_t F, acb_t G, acb_t Hpos, acb_t Hneg, const acb_t l, const acb_t eta, const acb_t z, slong prec) { /* We always compute F. Also handle aliasing. */ acb_t F2, l2, eta2, z2; acb_init(F2); acb_init(l2); acb_init(eta2); acb_init(z2); acb_set(l2, l); acb_set(eta2, eta); acb_set(z2, z); _acb_hypgeom_coulomb(F2, G, Hpos, Hneg, l2, eta2, z2, -1, prec); if (F != NULL) acb_set(F, F2); acb_clear(F2); acb_clear(l2); acb_clear(eta2); acb_clear(z2); } flint-3.1.3/src/acb_hypgeom/coulomb_jet.c000066400000000000000000000243201461254215100203460ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" /* need special case for integer l and z = 0 since the recurrence relations break down */ static void _acb_hypgeom_coulomb_f_int_jet(acb_ptr F, const acb_t l, const acb_t eta, const acb_t z, slong len, slong prec) { acb_poly_struct a[1]; acb_poly_struct b[2]; acb_poly_t zx, M, zxi; acb_t t; slong k; int real; if (arf_cmp_si(arb_midref(acb_realref(l)), -1) < 0) { _acb_vec_indeterminate(F, len); return; } /* https://fungrim.org/entry/2a2f18/ */ /* F = C * (z+x)^(l+1) e^(-+ i (z+x)) M(l + 1 -+ i eta, 2l+2, +- 2 i (z+x)) */ acb_poly_init(a); acb_poly_init(b); acb_poly_init(b + 1); acb_poly_init(zx); acb_poly_init(M); acb_poly_init(zxi); acb_init(t); acb_poly_set_coeff_acb(zx, 0, z); acb_poly_set_coeff_si(zx, 1, 1); acb_div_onei(t, eta); acb_add(t, t, l, prec); acb_add_ui(t, t, 1, prec); acb_poly_set_acb(a, t); acb_add_ui(t, l, 1, prec); acb_mul_2exp_si(t, t, 1); acb_poly_set_acb(b, t); acb_poly_one(b + 1); acb_onei(t); acb_mul_2exp_si(t, t, 1); acb_poly_scalar_mul(zxi, zx, t, prec); acb_hypgeom_pfq_series_direct(M, a, 1, b, 2, zxi, 1, -1, len, prec); acb_poly_scalar_mul_2exp_si(zxi, zxi, -1); acb_poly_neg(zxi, zxi); acb_poly_exp_series(zxi, zxi, len, prec); acb_poly_mullow(M, M, zxi, len, prec); acb_add_ui(t, l, 1, prec); acb_poly_pow_acb_series(zxi, zx, t, len, prec); acb_poly_mullow(M, M, zxi, len, prec); { /* C = 2^l exp((-pi eta + lu + lv)/2) */ acb_t C, lu, lv; acb_init(C); acb_init(lu); acb_init(lv); acb_add_ui(lu, l, 1, prec); acb_mul_onei(t, eta); acb_add(lu, lu, t, prec); acb_add_ui(lv, l, 1, prec); acb_div_onei(t, eta); acb_add(lv, lv, t, prec); acb_lgamma(lu, lu, prec); acb_lgamma(lv, lv, prec); acb_const_pi(t, prec); acb_add(C, lu, lv, prec); acb_submul(C, t, eta, prec); acb_mul_2exp_si(C, C, -1); acb_exp(C, C, prec); acb_set_ui(t, 2); acb_pow(t, t, l, prec); acb_mul(C, C, t, prec); acb_poly_scalar_mul(M, M, C, prec); acb_clear(C); acb_clear(lu); acb_clear(lv); } real = acb_is_real(z) && acb_is_real(eta); for (k = 0; k < len; k++) { acb_poly_get_coeff_acb(F + k, M, k); if (real) arb_zero(acb_imagref(F + k)); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(b + 1); acb_poly_clear(zx); acb_poly_clear(M); acb_poly_clear(zxi); acb_clear(t); } static void _acb_hypgeom_coulomb_jet(acb_ptr F, acb_ptr G, acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta, const acb_t z, slong len, slong prec) { acb_t l1, t, R, S; if (len <= 0) return; if (len == 1) { acb_hypgeom_coulomb(F, G, Hpos, Hneg, l, eta, z, prec); return; } if (acb_contains_zero(z)) { if (F != NULL) { if (acb_is_int(l)) _acb_hypgeom_coulomb_f_int_jet(F, l, eta, z, len, prec); else _acb_vec_indeterminate(F, len); } if (G != NULL) _acb_vec_indeterminate(G, len); if (Hpos != NULL) _acb_vec_indeterminate(Hpos, len); if (Hneg != NULL) _acb_vec_indeterminate(Hneg, len); return; } acb_init(l1); acb_init(t); acb_init(R); acb_init(S); acb_add_ui(l1, l, 1, prec); acb_hypgeom_coulomb(F, G, Hpos, Hneg, l, eta, z, prec); /* todo: somehow recycle the gamma function values for the two evaluations? */ acb_hypgeom_coulomb((F == NULL) ? NULL : (F + 1), (G == NULL) ? NULL : (G + 1), (Hpos == NULL) ? NULL : (Hpos + 1), (Hneg == NULL) ? NULL : (Hneg + 1), l1, eta, z, prec); /* First derivatives: https://fungrim.org/entry/a51a4b/, https://fungrim.org/entry/2fec14/ */ /* R_l = (2l+1) C_l / C_{l+1} = sqrt(l+i eta) sqrt(l-i eta) / l */ if (acb_is_real(l) && acb_is_real(eta) && arb_is_nonzero(acb_realref(eta))) { acb_mul(R, l1, l1, prec); acb_addmul(R, eta, eta, prec); acb_sqrt(R, R, prec); } else { acb_mul_onei(t, eta); acb_add(t, t, l1, prec); acb_sqrt(t, t, prec); acb_div_onei(R, eta); acb_add(R, R, l1, prec); acb_sqrt(R, R, prec); acb_mul(R, R, t, prec); } acb_div(R, R, l1, prec); acb_div(S, l1, z, prec); acb_div(t, eta, l1, prec); acb_add(S, S, t, prec); /* todo: fix regular F at origin */ if (F != NULL) { acb_mul(F + 1, F + 1, R, prec); acb_neg(F + 1, F + 1); acb_addmul(F + 1, F, S, prec); } if (G != NULL) { acb_mul(G + 1, G + 1, R, prec); acb_neg(G + 1, G + 1); acb_addmul(G + 1, G, S, prec); } if (Hpos != NULL) { acb_mul(Hpos + 1, Hpos + 1, R, prec); acb_neg(Hpos + 1, Hpos + 1); acb_addmul(Hpos + 1, Hpos, S, prec); } if (Hneg != NULL) { acb_mul(Hneg + 1, Hneg + 1, R, prec); acb_neg(Hneg + 1, Hneg + 1); acb_addmul(Hneg + 1, Hneg, S, prec); } if (len >= 3) { acb_t q, q2, w, w2; acb_init(q); acb_init(q2); acb_init(w); acb_init(w2); acb_inv(w, z, prec); acb_mul(w2, w, w, prec); /* https://fungrim.org/entry/07a654/ */ /* F''/2 = q F, q = (2eta/z + l(l+1)/z^2 - 1)/2 */ acb_mul(q, l, l1, prec); acb_mul(q, q, w2, prec); acb_mul_2exp_si(q2, eta, 1); acb_addmul(q, q2, w, prec); acb_sub_ui(q, q, 1, prec); acb_mul_2exp_si(q, q, -1); if (F != NULL) acb_mul(F + 2, F, q, prec); if (G != NULL) acb_mul(G + 2, G, q, prec); if (Hpos != NULL) acb_mul(Hpos + 2, Hpos, q, prec); if (Hneg != NULL) acb_mul(Hneg + 2, Hneg, q, prec); /* https://fungrim.org/entry/faa118/ */ /* F'''/6 = (2qF' - q2 F)/6, q2 = 2(eta + l(l+1)/z)/z^2 */ if (len >= 4) { acb_mul_2exp_si(q, q, 1); acb_mul(q2, l, l1, prec); acb_mul(q2, q2, w, prec); acb_add(q2, q2, eta, prec); acb_mul_2exp_si(q2, q2, 1); acb_mul(q2, q2, w2, prec); if (F != NULL) { acb_mul(F + 3, F + 1, q, prec); acb_submul(F + 3, F + 0, q2, prec); acb_div_ui(F + 3, F + 3, 6, prec); } if (G != NULL) { acb_mul(G + 3, G + 1, q, prec); acb_submul(G + 3, G, q2, prec); acb_div_ui(G + 3, G + 3, 6, prec); } if (Hpos != NULL) { acb_mul(Hpos + 3, Hpos + 1, q, prec); acb_submul(Hpos + 3, Hpos, q2, prec); acb_div_ui(Hpos + 3, Hpos + 3, 6, prec); } if (Hneg != NULL) { acb_mul(Hneg + 3, Hneg + 1, q, prec); acb_submul(Hneg + 3, Hneg, q2, prec); acb_div_ui(Hneg + 3, Hneg + 3, 6, prec); } } /* https://fungrim.org/entry/eca10b/ */ if (len >= 5) { slong k; acb_ptr s; s = _acb_vec_init(4); /* s4 = -(k(k+7) + 12) s3 = 2 (k(k+5) + 6) z s2 = (k(k+3) + z^2 - 2z*eta - l(l+1) + 2) s1 = 2(z-eta) s0 = 1 F[k+4] = (s0*F[k] + s1*F[k+1] + s2*F[k+2] + s3*F[k+3]) / s4 / z^2 */ acb_sub(s + 1, z, eta, prec); acb_mul_2exp_si(s + 1, s + 1, 1); acb_mul(q, z, z, prec); acb_mul(q2, eta, z, prec); acb_mul_2exp_si(q2, q2, 1); acb_sub(q, q, q2, prec); acb_submul(q, l, l1, prec); for (k = 0; k + 4 < len; k++) { acb_mul_si(s + 3, z, 2 * (k * (k + 5) + 6), prec); acb_add_si(s + 2, q, k * (k + 3) + 2, prec); if (F != NULL) { acb_dot(F + k + 4, F + k, 0, F + k + 1, 1, s + 1, 1, 3, prec); acb_div_si(F + k + 4, F + k + 4, -(k * (k + 7) + 12), prec); acb_mul(F + k + 4, F + k + 4, w2, prec); } if (G != NULL) { acb_dot(G + k + 4, G + k, 0, G + k + 1, 1, s + 1, 1, 3, prec); acb_div_si(G + k + 4, G + k + 4, -(k * (k + 7) + 12), prec); acb_mul(G + k + 4, G + k + 4, w2, prec); } if (Hpos != NULL) { acb_dot(Hpos + k + 4, Hpos + k, 0, Hpos + k + 1, 1, s + 1, 1, 3, prec); acb_div_si(Hpos + k + 4, Hpos + k + 4, -(k * (k + 7) + 12), prec); acb_mul(Hpos + k + 4, Hpos + k + 4, w2, prec); } if (Hneg != NULL) { acb_dot(Hneg + k + 4, Hneg + k, 0, Hneg + k + 1, 1, s + 1, 1, 3, prec); acb_div_si(Hneg + k + 4, Hneg + k + 4, -(k * (k + 7) + 12), prec); acb_mul(Hneg + k + 4, Hneg + k + 4, w2, prec); } } _acb_vec_clear(s, 4); } acb_clear(q); acb_clear(q2); acb_clear(w); acb_clear(w2); } acb_clear(l1); acb_clear(t); acb_clear(R); acb_clear(S); } void acb_hypgeom_coulomb_jet(acb_ptr F, acb_ptr G, acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta, const acb_t z, slong len, slong prec) { acb_t t; /* to allow aliasing with z */ acb_init(t); acb_set(t, z); _acb_hypgeom_coulomb_jet(F, G, Hpos, Hneg, l, eta, t, len, prec); acb_clear(t); } flint-3.1.3/src/acb_hypgeom/coulomb_series.c000066400000000000000000000064151461254215100210630ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_coulomb_series(acb_ptr F, acb_ptr G, acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta, acb_srcptr z, slong zlen, slong len, slong prec) { acb_ptr t, v; if (len == 0) return; zlen = FLINT_MIN(zlen, len); if (zlen == 1) { acb_hypgeom_coulomb(F, G, Hpos, Hneg, l, eta, z, prec); if (F != NULL) _acb_vec_zero(F + 1, len - 1); if (G != NULL) _acb_vec_zero(G + 1, len - 1); if (Hpos != NULL) _acb_vec_zero(Hpos + 1, len - 1); if (Hneg != NULL) _acb_vec_zero(Hneg + 1, len - 1); return; } t = _acb_vec_init(len); v = _acb_vec_init(zlen); /* copy nonconstant part first to allow aliasing */ acb_zero(v); _acb_vec_set(v + 1, z + 1, zlen - 1); acb_hypgeom_coulomb_jet(F, G, Hpos, Hneg, l, eta, z, len, prec); if (F != NULL) { _acb_vec_set(t, F, len); _acb_poly_compose_series(F, t, len, v, zlen, len, prec); } if (G != NULL) { _acb_vec_set(t, G, len); _acb_poly_compose_series(G, t, len, v, zlen, len, prec); } if (Hpos != NULL) { _acb_vec_set(t, Hpos, len); _acb_poly_compose_series(Hpos, t, len, v, zlen, len, prec); } if (Hneg != NULL) { _acb_vec_set(t, Hneg, len); _acb_poly_compose_series(Hneg, t, len, v, zlen, len, prec); } _acb_vec_clear(t, len); _acb_vec_clear(v, zlen); } void acb_hypgeom_coulomb_series(acb_poly_t F, acb_poly_t G, acb_poly_t Hpos, acb_poly_t Hneg, const acb_t l, const acb_t eta, const acb_poly_t z, slong len, slong prec) { acb_srcptr zptr; slong zlen; acb_t t; if (len == 0) { if (F != NULL) acb_poly_zero(F); if (G != NULL) acb_poly_zero(G); if (Hpos != NULL) acb_poly_zero(Hpos); if (Hneg != NULL) acb_poly_zero(Hneg); return; } zlen = z->length; if (zlen <= 1) len = 1; if (F != NULL) acb_poly_fit_length(F, len); if (G != NULL) acb_poly_fit_length(G, len); if (Hpos != NULL) acb_poly_fit_length(Hpos, len); if (Hneg != NULL) acb_poly_fit_length(Hneg, len); if (zlen == 0) { acb_init(t); zptr = t; zlen = 1; } else { zptr = z->coeffs; } _acb_hypgeom_coulomb_series( F ? F->coeffs : NULL, G ? G->coeffs : NULL, Hpos ? Hpos->coeffs : NULL, Hneg ? Hneg->coeffs : NULL, l, eta, zptr, zlen, len, prec); if (F != NULL) _acb_poly_set_length(F, len); if (G != NULL) _acb_poly_set_length(G, len); if (Hpos != NULL) _acb_poly_set_length(Hpos, len); if (Hneg != NULL) _acb_poly_set_length(Hneg, len); if (F != NULL) _acb_poly_normalise(F); if (G != NULL) _acb_poly_normalise(G); if (Hpos != NULL) _acb_poly_normalise(Hpos); if (Hneg != NULL) _acb_poly_normalise(Hneg); } flint-3.1.3/src/acb_hypgeom/dilog.c000066400000000000000000000104701461254215100171430ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define atan2 __builtin_atan2 # define fabs __builtin_fabs # define log __builtin_log #else # include #endif void acb_hypgeom_dilog(acb_t res, const acb_t z, slong prec) { double a, b, best, mz, mz1, t, u; int algorithm; slong acc, inprec; if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_is_zero(z)) { acb_zero(res); return; } acc = acb_rel_accuracy_bits(z); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + 30); inprec = prec; /* first take care of exponents that may overflow doubles */ if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -20) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -20) <= 0) { acb_hypgeom_dilog_zero(res, z, prec); return; } if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 20) >= 0 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 20) >= 0) { acb_hypgeom_dilog_transform(res, z, 1, prec); return; } prec = 1.005 * prec + 5; a = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); b = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); best = mz = a * a + b * b; algorithm = 0; /* if |z| > 0.25, consider expanding somewhere other than the origin */ if (best > 0.25 * 0.25) { if (1.0 / mz < best) /* use 1/z */ { best = 1.0 / mz; algorithm = 1; } mz1 = (a - 1.0) * (a - 1.0) + b * b; if (mz1 < best) /* use 1-z */ { best = mz1; algorithm = 2; } if (mz1 > 0.001 && mz / mz1 < best) /* use z/(z-1) */ { best = mz / mz1; algorithm = 3; } if (mz1 > 0.001 && 1.0 / mz1 < best) /* use 1/(1-z) */ { best = 1.0 / mz1; algorithm = 4; } } /* do we still have |z| > 0.25 after transforming? */ if (best > 0.25 * 0.25) { /* use series with bernoulli numbers (if not too many!) */ if (prec < 10000) { /* t = |log(a+bi)|^2 / (2 pi)^2 */ t = log(a * a + b * b); u = atan2(b, a); t = (t * t + u * u) * 0.02533029591; if (prec > 1000) t *= 4.0; /* penalty at high precision */ else t *= 1.1; /* small penalty... also helps avoid this method at negative reals where the log branch cut enters (todo: combine with 1-z formula?) */ if (t < best) { algorithm = 8; best = t; } } } /* fall back on expanding at another special point (this should only happen at high precision, where we will use the bit-burst algorithm) */ if (best > 0.75 * 0.75) { b = fabs(b); /* reduce to upper half plane */ /* expanding at z0 = i: effective radius |z-i|/sqrt(2) */ t = ((b - 1.0) * (b - 1.0) + a * a) * 0.5; if (t < best) { best = t; algorithm = 5; } /* expanding at z0 = (1+i)/2: effective radius |z-(1+i)/2|*sqrt(2) */ t = 1.0 + 2.0 * (a * (a - 1.0) + b * (b - 1.0)); if (t < best) { best = t; algorithm = 6; } /* expanding at z0 = 1+i: effective radius |z-(1+i)| */ t = 2.0 + (a - 2.0) * a + (b - 2.0) * b; if (t < best) { best = t; algorithm = 7; } } if (algorithm == 0) acb_hypgeom_dilog_zero(res, z, prec); else if (algorithm >= 1 && algorithm <= 7) acb_hypgeom_dilog_transform(res, z, algorithm, prec); else /* (algorithm == 8) */ acb_hypgeom_dilog_bernoulli(res, z, prec); acb_set_round(res, res, inprec); } flint-3.1.3/src/acb_hypgeom/dilog_bernoulli.c000066400000000000000000000050341461254215100212160ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #include "bernoulli.h" /* todo: use log(1-z) when this is better? would also need to adjust strategy in the main function */ void acb_hypgeom_dilog_bernoulli(acb_t res, const acb_t z, slong prec) { acb_t s, w, w2; slong n, k; fmpz_t c, d; mag_t m, err; double lm; int real; acb_init(s); acb_init(w); acb_init(w2); fmpz_init(c); fmpz_init(d); mag_init(m); mag_init(err); real = 0; if (acb_is_real(z)) { arb_sub_ui(acb_realref(w), acb_realref(z), 1, 30); real = arb_is_nonpositive(acb_realref(w)); } acb_log(w, z, prec); acb_get_mag(m, w); /* for k >= 4, the terms are bounded by (|w| / (2 pi))^k */ mag_set_ui_2exp_si(err, 2670177, -24); /* upper bound for 1/(2pi) */ mag_mul(err, err, m); lm = mag_get_d_log2_approx(err); if (lm < -0.25) { n = prec / (-lm) + 1; n = FLINT_MAX(n, 4); mag_geom_series(err, err, n); BERNOULLI_ENSURE_CACHED(n) acb_mul(w2, w, w, prec); for (k = n - (n % 2 == 0); k >= 3; k -= 2) { fmpz_mul_ui(c, fmpq_denref(bernoulli_cache + k - 1), k - 1); fmpz_mul_ui(d, c, (k + 1) * (k + 2)); acb_mul(s, s, w2, prec); acb_mul_fmpz(s, s, c, prec); fmpz_mul_ui(c, fmpq_numref(bernoulli_cache + k - 1), (k + 1) * (k + 2)); acb_sub_fmpz(s, s, c, prec); acb_div_fmpz(s, s, d, prec); } acb_mul(s, s, w, prec); acb_mul_2exp_si(s, s, 1); acb_sub_ui(s, s, 3, prec); acb_mul(s, s, w2, prec); acb_mul_2exp_si(s, s, -1); acb_const_pi(w2, prec); acb_addmul(s, w2, w2, prec); acb_div_ui(s, s, 6, prec); acb_neg(w2, w); acb_log(w2, w2, prec); acb_submul(s, w2, w, prec); acb_add(res, s, w, prec); acb_add_error_mag(res, err); if (real) arb_zero(acb_imagref(res)); } else { acb_indeterminate(res); } acb_clear(s); acb_clear(w); acb_clear(w2); fmpz_clear(c); fmpz_clear(d); mag_clear(m); mag_clear(err); } flint-3.1.3/src/acb_hypgeom/dilog_bitburst.c000066400000000000000000000041271461254215100210630ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #include "bernoulli.h" static void _arf_trunc(arf_t x) { if (arf_sgn(x) < 0) arf_ceil(x, x); else arf_floor(x, x); } static void acb_extract_bits(acb_t t, const acb_t z, slong b) { acb_mul_2exp_si(t, z, b); _arf_trunc(arb_midref(acb_realref(t))); _arf_trunc(arb_midref(acb_imagref(t))); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_mul_2exp_si(t, t, -b); } void acb_hypgeom_dilog_bitburst(acb_t res, acb_t z0, const acb_t z, slong prec) { acb_t s, t, tprev, u; slong w; slong start = 16; acb_init(s); acb_init(t); acb_init(tprev); acb_init(u); acb_sub_ui(t, z, 1, 30); arb_abs(acb_imagref(t), acb_imagref(t)); /* we don't want to end up on the branch cut */ if (arb_contains_nonnegative(acb_realref(t)) && !arb_gt(acb_imagref(t), acb_realref(t))) { acb_set(z0, z); acb_zero(res); } else { acb_extract_bits(t, z, start); acb_set(z0, t); acb_set(tprev, t); for (w = 2 * start; w < prec; w *= 2) { acb_extract_bits(t, z, w); acb_sub(u, t, z, 30); if (arf_cmpabs_2exp_si(arb_midref(acb_realref(u)), -prec / 8) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(u)), -prec / 8) < 0) break; acb_hypgeom_dilog_continuation(u, tprev, t, prec); acb_add(s, s, u, prec); acb_set(tprev, t); } acb_hypgeom_dilog_continuation(u, tprev, z, prec); acb_add(s, s, u, prec); acb_set(res, s); } acb_clear(s); acb_clear(t); acb_clear(tprev); acb_clear(u); } flint-3.1.3/src/acb_hypgeom/dilog_continuation.c000066400000000000000000000156701461254215100217440ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" static void bsplit(acb_ptr VA, const acb_t z, const acb_t z2, const acb_t a, const acb_t a1a, slong k, slong h, slong prec) { if (h - k == 1) { acb_zero(VA + 0); acb_mul_ui(VA + 1, a1a, (k+1)*(k+2), prec); acb_mul_si(VA + 2, z2, -k*k, prec); acb_mul_ui(VA + 3, a, (k+1)*(2*k+1), prec); acb_sub_ui(VA + 3, VA + 3, (k+1)*(k+1), prec); acb_mul(VA + 3, VA + 3, z, prec); acb_neg(VA + 3, VA + 3); acb_set(VA + 4, VA + 1); acb_zero(VA + 5); acb_set(VA + 6, VA + 1); } else { slong m; acb_ptr VB; if (h <= k) flint_throw(FLINT_ERROR, "(%s)\n", __func__); m = k + (h - k) / 2; VB = _acb_vec_init(7); bsplit(VA, z, z2, a, a1a, k, m, prec); bsplit(VB, z, z2, a, a1a, m, h, prec); acb_mul(VA + 6, VA + 6, VB + 6, prec); acb_mul(VA + 4, VA + 4, VB + 6, prec); acb_addmul(VA + 4, VA + 0, VB + 4, prec); acb_addmul(VA + 4, VA + 2, VB + 5, prec); acb_mul(VA + 5, VA + 5, VB + 6, prec); acb_addmul(VA + 5, VA + 1, VB + 4, prec); acb_addmul(VA + 5, VA + 3, VB + 5, prec); acb_set(VB + 6, VA + 3); acb_mul(VA + 3, VA + 3, VB + 3, prec); acb_addmul(VA + 3, VA + 1, VB + 2, prec); acb_set(VB + 5, VA + 2); acb_mul(VA + 2, VA + 2, VB + 3, prec); acb_addmul(VA + 2, VA + 0, VB + 2, prec); acb_mul(VA + 1, VA + 1, VB + 0, prec); acb_addmul(VA + 1, VB + 6, VB + 1, prec); acb_mul(VA + 0, VA + 0, VB + 0, prec); acb_addmul(VA + 0, VB + 5, VB + 1, prec); _acb_vec_clear(VB, 7); } } /* Some possible approaches to bounding the Taylor coefficients c_k at the expansion point a: 1. Inspection of the symbolic derivatives gives the trivial bound |c_k| <= (1+|log(1-a)|) / min(|a|,|a-1|)^k which is good enough when not close to 0. 2. Using Cauchy's integral formula, some explicit computation gives |c_k| <= 4/|1-a|^k when |a| <= 1/2 or a = +/- i. The constant could certainly be improved. 3. For k >= 1, c_k = 2F1(k,k,k+1,a) / k^2. Can we use monotonicity to get good estimates here when a is complex? Note that 2F1(k,k,k,a) = (1-a)^-k. */ void acb_hypgeom_dilog_continuation(acb_t res, const acb_t a, const acb_t z, slong prec) { acb_t za, a1, a1a, za2, log1a; acb_ptr V; slong n; double tr; mag_t tm, err, am; int real; if (acb_is_zero(a)) { acb_hypgeom_dilog_zero_taylor(res, z, prec); return; } if (acb_eq(a, z)) { acb_zero(res); return; } acb_init(za); acb_init(a1); acb_init(a1a); acb_init(za2); acb_init(log1a); mag_init(tm); mag_init(err); mag_init(am); acb_sub(za, z, a, prec); /* z-a */ acb_sub_ui(a1, a, 1, prec); /* a-1 */ acb_mul(a1a, a1, a, prec); /* (a-1)a */ acb_mul(za2, za, za, prec); /* (z-a)^2 */ acb_neg(log1a, a1); acb_log(log1a, log1a, prec); /* log(1-a) */ acb_get_mag(am, a); if (mag_cmp_2exp_si(am, -1) <= 0 || (acb_is_exact(a) && arb_is_zero(acb_realref(a)) && arf_cmpabs_ui(arb_midref(acb_imagref(a)), 1) == 0)) { acb_get_mag_lower(am, a1); acb_get_mag(tm, za); mag_div(tm, tm, am); /* tm = ratio */ mag_set_ui(am, 4); /* am = prefactor */ } else { acb_get_mag_lower(am, a); acb_get_mag_lower(tm, a1); mag_min(am, am, tm); acb_get_mag(tm, za); mag_div(tm, tm, am); /* tm = ratio */ acb_get_mag(am, log1a); mag_add_ui(am, am, 1); /* am = prefactor */ } tr = mag_get_d_log2_approx(tm); if (tr < -0.1) { arf_srcptr rr, ii; rr = arb_midref(acb_realref(z)); ii = arb_midref(acb_imagref(z)); if (arf_cmpabs(ii, rr) > 0) rr = ii; /* target relative accuracy near 0 */ if (arf_cmpabs_2exp_si(rr, -2) < 0 && arf_cmpabs_2exp_si(rr, -prec) > 0) n = (prec - arf_abs_bound_lt_2exp_si(rr)) / (-tr) + 1; else n = prec / (-tr) + 1; n = FLINT_MAX(n, 2); } else { n = 2; } mag_geom_series(err, tm, n); mag_mul(err, err, am); real = acb_is_real(a) && acb_is_real(z) && arb_is_negative(acb_realref(a1)) && mag_is_finite(err); if (n < 10) { /* forward recurrence - faster for small n and/or low precision, but must be avoided for large n since complex intervals blow up */ acb_t s, t, u, v; slong k; acb_init(s); acb_init(t); acb_init(u); acb_init(v); acb_div(u, log1a, a, prec); acb_neg(u, u); if (n >= 3) { acb_inv(v, a1, prec); acb_add(v, v, u, prec); acb_div(v, v, a, prec); acb_mul_2exp_si(v, v, -1); acb_neg(v, v); acb_mul(v, v, za2, prec); } acb_mul(u, u, za, prec); acb_add(s, u, v, prec); for (k = 3; k < n; k++) { acb_mul_ui(u, u, (k - 2) * (k - 2), prec); acb_mul(u, u, za2, prec); acb_mul_ui(t, a, (k - 1) * (2 * k - 3), prec); acb_sub_ui(t, t, (k - 1) * (k - 1), prec); acb_mul(t, t, v, prec); acb_addmul(u, t, za, prec); acb_mul_ui(t, a1a, (k - 1) * k, prec); acb_neg(t, t); acb_div(u, u, t, prec); acb_add(s, s, u, prec); acb_swap(v, u); } acb_set(res, s); acb_clear(s); acb_clear(t); acb_clear(u); acb_clear(v); } else { /* binary splitting */ V = _acb_vec_init(7); bsplit(V, za, za2, a, a1a, 1, 1 + n, prec); acb_mul(V + 1, V + 4, log1a, prec); acb_neg(V + 1, V + 1); acb_mul(V + 2, V + 5, za2, prec); acb_mul_2exp_si(V + 2, V + 2, -1); acb_mul(V + 1, V + 1, za, prec); acb_div(V + 3, V + 2, a1, prec); acb_sub(V + 1, V + 1, V + 3, prec); acb_div(V + 0, log1a, a, prec); acb_addmul(V + 1, V + 2, V + 0, prec); acb_mul(V + 6, V + 6, a, prec); acb_div(V + 0, V + 1, V + 6, prec); acb_set(res, V + 0); _acb_vec_clear(V, 7); } if (real) arb_add_error_mag(acb_realref(res), err); else acb_add_error_mag(res, err); acb_clear(za); acb_clear(a1); acb_clear(a1a); acb_clear(za2); acb_clear(log1a); mag_clear(tm); mag_clear(err); mag_clear(am); } flint-3.1.3/src/acb_hypgeom/dilog_transform.c000066400000000000000000000132451461254215100212410ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_dilog_transform(acb_t res, const acb_t z, int algorithm, slong prec) { acb_t t, u; acb_init(t); acb_init(u); if (algorithm == 1) { /* Li_2(z) = -Li_2(1/z) - log(-z)^2/2 - pi^2/6, z not in (0,1) */ arf_set_ui_2exp_si(arb_midref(acb_realref(t)), 1, -1); mag_set_ui_2exp_si(arb_radref(acb_realref(t)), 1, -1); if (acb_overlaps(z, t)) { acb_indeterminate(res); } else { acb_inv(t, z, prec); acb_hypgeom_dilog_zero(t, t, prec); acb_neg(u, z); acb_log(u, u, prec); acb_mul(u, u, u, prec); acb_mul_2exp_si(u, u, -1); acb_add(t, t, u, prec); acb_const_pi(u, prec); acb_mul(u, u, u, prec); acb_div_ui(u, u, 6, prec); acb_add(t, t, u, prec); acb_neg(res, t); } } else if (algorithm == 2) { /* Li_2(z) = -Li_2(1-z) - log(1-z) log(z) + pi^2/6 */ if (acb_is_one(z)) { acb_zero(res); } else { acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_hypgeom_dilog_zero(u, t, prec); acb_log(t, t, prec); acb_log(res, z, prec); acb_mul(res, res, t, prec); acb_add(res, res, u, prec); } acb_const_pi(t, prec); acb_mul(t, t, t, prec); acb_div_ui(t, t, 6, prec); acb_sub(res, t, res, prec); } else if (algorithm == 3) { /* Li_2(z) = -Li_2(z/(z-1)) - log(1-z)^2/2, z not in (1,inf) */ acb_sub_ui(t, z, 1, prec); if (!arb_is_negative(acb_realref(t))) { acb_indeterminate(res); } else { acb_div(u, z, t, prec); acb_hypgeom_dilog_zero(u, u, prec); acb_neg(t, t); acb_log(t, t, prec); acb_mul(t, t, t, prec); acb_mul_2exp_si(t, t, -1); acb_add(t, t, u, prec); acb_neg(res, t); } } else if (algorithm == 4) { /* Li_2(z) = Li_2(1/(1-z)) + log(1-z) [log(1-z)/2 - log(-z)] - pi^2/6 */ acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_inv(u, t, prec); acb_hypgeom_dilog_zero(u, u, prec); acb_log(t, t, prec); acb_neg(res, z); acb_log(res, res, prec); acb_mul_2exp_si(res, res, 1); acb_sub(res, t, res, prec); acb_mul_2exp_si(res, res, -1); acb_addmul(u, res, t, prec); acb_const_pi(t, prec); acb_mul(t, t, t, prec); acb_div_ui(t, t, 6, prec); acb_sub(res, u, t, prec); } else if (algorithm >= 5 && algorithm <= 7) { if (arb_contains_zero(acb_imagref(z))) { acb_indeterminate(res); } else { acb_t a; acb_init(a); if (algorithm == 5) { acb_onei(a); /* Li_2(i) = -pi^2/48 + C i */ arb_const_catalan(acb_imagref(u), prec); arb_const_pi(acb_realref(u), prec); arb_mul(acb_realref(u), acb_realref(u), acb_realref(u), prec); arb_div_si(acb_realref(u), acb_realref(u), -48, prec); } else if (algorithm == 6) { /* Li_2((1+i)/2) = (5 pi^2 / 96 - log(2)^2/8) + (C - pi log(2) / 8) i */ arb_t t; arb_init(t); acb_set_d_d(a, 0.5, 0.5); arb_const_pi(t, prec); arb_const_log2(acb_imagref(u), prec); arb_mul(acb_realref(u), acb_imagref(u), acb_imagref(u), prec); arb_mul(acb_imagref(u), acb_imagref(u), t, prec); acb_mul_2exp_si(u, u, -3); arb_mul(t, t, t, prec); arb_mul_ui(t, t, 5, prec); arb_div_ui(t, t, 96, prec); arb_sub(acb_realref(u), t, acb_realref(u), prec); arb_const_catalan(t, prec); arb_sub(acb_imagref(u), t, acb_imagref(u), prec); arb_clear(t); } else { /* Li_2(1+i) = pi^2/16 + (C + pi log(2)/4) i */ arb_t t; arb_init(t); acb_set_d_d(a, 1.0, 1.0); arb_const_pi(acb_realref(u), prec); arb_mul_2exp_si(acb_realref(u), acb_realref(u), -2); arb_const_log2(t, prec); arb_mul(acb_imagref(u), acb_realref(u), t, prec); arb_const_catalan(t, prec); arb_add(acb_imagref(u), acb_imagref(u), t, prec); arb_mul(acb_realref(u), acb_realref(u), acb_realref(u), prec); arb_clear(t); } if (arf_sgn(arb_midref(acb_imagref(z))) < 0) { acb_conj(a, a); acb_conj(u, u); } acb_hypgeom_dilog_bitburst(res, t, z, prec); acb_add(res, res, u, prec); acb_hypgeom_dilog_continuation(t, a, t, prec); acb_add(res, res, t, prec); acb_clear(a); } } else { flint_throw(FLINT_ERROR, "unknown algorithm\n"); } acb_clear(t); acb_clear(u); } flint-3.1.3/src/acb_hypgeom/dilog_zero.c000066400000000000000000000017031461254215100202010ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_dilog_zero(acb_t res, const acb_t z, slong prec) { if (prec < 40000 || (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -prec / 1000) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -prec / 1000) < 0)) { acb_hypgeom_dilog_zero_taylor(res, z, prec); } else { acb_t z0; acb_init(z0); acb_hypgeom_dilog_bitburst(res, z0, z, prec); acb_hypgeom_dilog_zero_taylor(z0, z0, prec); acb_add(res, res, z0, prec); acb_clear(z0); } } flint-3.1.3/src/acb_hypgeom/dilog_zero_taylor.c000066400000000000000000000116171461254215100216000ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "acb_hypgeom.h" static void bsplit_zero(acb_t P, acb_t R, acb_t Q, const acb_t z, slong a, slong b, slong prec) { if (b - a == 1) { acb_mul_ui(P, z, a * a, prec); acb_set_ui(R, (a + 1) * (a + 1)); acb_set(Q, R); } else { acb_t P2, R2, Q2; slong m; acb_init(P2); acb_init(R2); acb_init(Q2); m = a + (b - a) / 2; bsplit_zero(P, R, Q, z, a, m, prec); bsplit_zero(P2, R2, Q2, z, m, b, prec); acb_mul(R, R, Q2, prec); acb_addmul(R, P, R2, prec); acb_mul(P, P, P2, prec); acb_mul(Q, Q, Q2, prec); acb_clear(P2); acb_clear(R2); acb_clear(Q2); } } #if FLINT_BITS == 64 #define DIVLIM 1625 /* just a tuning value */ #define DIVLIM2 1000000000 /* avoid overflow */ #else #define DIVLIM 40 #define DIVLIM2 30000 #endif void acb_hypgeom_dilog_taylor_sum(acb_t res, const acb_t z, slong n, slong prec) { slong k, qk, m, power; ulong q; acb_t s, t, u; acb_ptr zpow; int real; if (n <= 3) { if (n <= 1) acb_zero(res); else if (n == 2) acb_set_round(res, z, prec); else { acb_init(t); acb_mul(t, z, z, prec); acb_mul_2exp_si(t, t, -2); acb_add(res, z, t, prec); acb_clear(t); } return; } /* use binary splitting */ if (prec > 4000 && acb_bits(z) < prec * 0.02) { acb_init(s); acb_init(t); acb_init(u); bsplit_zero(s, t, u, z, 1, n, prec); acb_add(s, s, t, prec); acb_mul(s, s, z, prec); acb_div(res, s, u, prec); acb_clear(s); acb_clear(t); acb_clear(u); return; } real = acb_is_real(z); k = n - 1; m = n_sqrt(n); acb_init(s); acb_init(t); zpow = _acb_vec_init(m + 1); _acb_vec_set_powers(zpow, z, m + 1, prec); power = (n - 1) % m; while (k >= DIVLIM) { if (k < DIVLIM2) /* todo: write a div_uiui function? */ { acb_div_ui(t, zpow + power, k * k, prec); } else { acb_div_ui(t, zpow + power, k, prec); acb_div_ui(t, t, k, prec); } acb_add(s, s, t, prec); if (power == 0) { acb_mul(s, s, zpow + m, prec); power = m - 1; } else { power--; } k--; } qk = k; /* k at which to change denominator */ q = 1; while (k >= 2) { /* find next qk such that the consecutive denominators can be collected in a single word */ if (k == qk) { if (q != 1) acb_div_ui(s, s, q, prec); q = qk * qk; qk--; while (qk > 1) { ulong hi, lo; umul_ppmm(hi, lo, q, qk * qk); if (hi != 0) break; q *= qk * qk; qk--; } acb_mul_ui(s, s, q, prec); } if (power == 0) { acb_add_ui(s, s, q / (k * k), prec); acb_mul(s, s, zpow + m, prec); power = m - 1; } else { if (real) /* minor optimization */ arb_addmul_ui(acb_realref(s), acb_realref(zpow + power), q / (k * k), prec); else acb_addmul_ui(s, zpow + power, q / (k * k), prec); power--; } k--; } if (q != 1) acb_div_ui(s, s, q, prec); acb_add(s, s, z, prec); acb_swap(res, s); _acb_vec_clear(zpow, m + 1); acb_clear(s); acb_clear(t); } void acb_hypgeom_dilog_zero_taylor(acb_t res, const acb_t z, slong prec) { mag_t m; slong n; double x; int real; mag_init(m); acb_get_mag(m, z); real = acb_is_real(z); x = -mag_get_d_log2_approx(m); n = 2; if (x > 0.01) { n = prec / x + 1; n += (x > 2.0); /* relative error for very small |z| */ } n = FLINT_MAX(n, 2); mag_geom_series(m, m, n); mag_div_ui(m, m, n); mag_div_ui(m, m, n); if (mag_is_finite(m)) { acb_hypgeom_dilog_taylor_sum(res, z, n, prec); if (real) arb_add_error_mag(acb_realref(res), m); else acb_add_error_mag(res, m); } else { acb_indeterminate(res); } mag_clear(m); } flint-3.1.3/src/acb_hypgeom/ei.c000066400000000000000000000055221461254215100164440ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_ei_asymp(acb_t res, const acb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_one(t); acb_neg(u, z); acb_hypgeom_u_asymp(u, t, t, u, -1, prec); acb_div(u, u, z, prec); acb_exp(t, z, prec); acb_mul(u, u, t, prec); if (arb_is_zero(acb_imagref(z))) { arb_zero(acb_imagref(u)); } else if (arb_is_positive(acb_imagref(z))) { acb_const_pi(t, prec); arb_add(acb_imagref(u), acb_imagref(u), acb_realref(t), prec); } else if (arb_is_negative(acb_imagref(z))) { acb_const_pi(t, prec); arb_sub(acb_imagref(u), acb_imagref(u), acb_realref(t), prec); } else { /* add [-pi,pi] i */ acb_const_pi(t, prec); arb_add_error(acb_imagref(u), acb_realref(t)); } acb_swap(res, u); acb_clear(t); acb_clear(u); } /* Ei(z) = z 2F2(1,1,2,2,z) + 0.5[log(z)-log(1/z)] + gamma */ void acb_hypgeom_ei_2f2(acb_t res, const acb_t z, slong prec) { acb_t a, t; acb_struct b[2]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(t); acb_one(a); acb_set_ui(b, 2); acb_set_ui(b + 1, 2); acb_hypgeom_pfq_direct(t, a, 1, b, 2, z, -1, prec); acb_mul(t, t, z, prec); arb_const_euler(acb_realref(a), prec); arb_add(acb_realref(t), acb_realref(t), acb_realref(a), prec); if (arb_is_zero(acb_imagref(z))) { if (arb_is_positive(acb_realref(z))) { acb_log(a, z, prec); } else { /* ok if overlapping zero -- will be indeterminate either way */ acb_neg(a, z); acb_log(a, a, prec); arb_zero(acb_imagref(a)); } acb_add(t, t, a, prec); } else if (arb_is_nonzero(acb_imagref(z)) || arb_is_nonnegative(acb_realref(z))) /* not overlapping (-inf,0] */ { acb_log(a, z, prec); acb_add(t, t, a, prec); } else { acb_log(a, z, prec); arb_zero(acb_imagref(a)); acb_const_pi(b, prec); arb_add_error(acb_imagref(a), acb_realref(b)); acb_add(t, t, a, prec); } acb_swap(res, t); acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(t); } void acb_hypgeom_ei(acb_t res, const acb_t z, slong prec) { if (acb_hypgeom_u_use_asymp(z, prec)) acb_hypgeom_ei_asymp(res, z, prec); else acb_hypgeom_ei_2f2(res, z, prec); } flint-3.1.3/src/acb_hypgeom/ei_series.c000066400000000000000000000035071461254215100200170ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_ei_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { acb_t c; if (acb_contains_zero(h)) { _acb_vec_indeterminate(g, len); return; } acb_init(c); acb_hypgeom_ei(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else { acb_ptr t, u, v; t = _acb_vec_init(len); u = _acb_vec_init(len); v = _acb_vec_init(len); /* Ei(h(x)) = integral([h'(x) / h(x)] exp(h(x)) */ _acb_poly_exp_series(t, h, hlen, len - 1, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec); _acb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec); _acb_poly_integral(g, u, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(v, len); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_ei_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_inv_series(g, h, len, prec); return; } acb_poly_fit_length(g, len); _acb_hypgeom_ei_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/erf.c000066400000000000000000000175771461254215100166400ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif /* IMAG: erf(z) = 2z/sqrt(pi) * 1F1(1/2, 3/2, -z^2) */ void acb_hypgeom_erf_1f1a(acb_t res, const acb_t z, slong prec) { acb_t a, t, w; acb_struct b[2]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(t); acb_init(w); acb_one(a); acb_mul_2exp_si(a, a, -1); acb_set_ui(b, 3); acb_mul_2exp_si(b, b, -1); acb_one(b + 1); acb_mul(w, z, z, prec); acb_neg(w, w); acb_hypgeom_pfq_direct(t, a, 1, b, 2, w, -1, prec); acb_mul(t, t, z, prec); arb_const_sqrt_pi(acb_realref(w), prec); acb_div_arb(t, t, acb_realref(w), prec); acb_mul_2exp_si(res, t, 1); acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(t); acb_clear(w); } /* REAL: erf(x) = 2x/sqrt(pi) * exp(-x^2) 1F1(1, 3/2, x^2) */ void acb_hypgeom_erf_1f1b(acb_t res, const acb_t z, slong prec) { acb_t a, b, t, w; acb_init(a); acb_init(b); acb_init(t); acb_init(w); acb_set_ui(b, 3); acb_mul_2exp_si(b, b, -1); acb_mul(w, z, z, prec); acb_hypgeom_pfq_direct(t, a, 0, b, 1, w, -1, prec); acb_neg(w, w); acb_exp(w, w, prec); acb_mul(t, t, w, prec); acb_mul(t, t, z, prec); arb_const_sqrt_pi(acb_realref(w), prec); acb_div_arb(t, t, acb_realref(w), prec); acb_mul_2exp_si(res, t, 1); acb_clear(a); acb_clear(b); acb_clear(t); acb_clear(w); } void acb_hypgeom_erf_asymp(acb_t res, const acb_t z, int complementary, slong prec, slong prec2) { acb_t a, t, u; acb_init(a); acb_init(t); acb_init(u); if (!acb_is_exact(z) && (arf_cmpabs_ui(arb_midref(acb_realref(z)), prec) < 0) && (arf_cmpabs_ui(arb_midref(acb_imagref(z)), prec) < 0)) { acb_t zmid; mag_t re_err, im_err; acb_init(zmid); mag_init(re_err); mag_init(im_err); acb_hypgeom_erf_propagated_error(re_err, im_err, z); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); acb_hypgeom_erf_asymp(res, zmid, complementary, prec, prec2); arb_add_error_mag(acb_realref(res), re_err); arb_add_error_mag(acb_imagref(res), im_err); acb_clear(zmid); mag_clear(re_err); mag_clear(im_err); return; } acb_one(a); acb_mul_2exp_si(a, a, -1); acb_mul(t, z, z, prec2); acb_hypgeom_u_asymp(u, a, a, t, -1, prec2); acb_neg(t, t); acb_exp(t, t, prec2); acb_mul(u, u, t, prec2); arb_const_sqrt_pi(acb_realref(t), prec2); arb_zero(acb_imagref(t)); acb_mul(t, t, z, prec2); acb_div(u, u, t, prec2); /* branch cut term: -1 or 1 */ acb_csgn(acb_realref(t), z); arb_zero(acb_imagref(t)); if (complementary) { /* erfc(z) = 1 - erf(z) = u - (sgn - 1) */ acb_sub_ui(t, t, 1, prec); acb_sub(t, u, t, prec); } else { /* erf(z) = sgn - u */ acb_sub(t, t, u, prec); } if (arb_is_zero(acb_imagref(z))) { arb_zero(acb_imagref(t)); } else if (arb_is_zero(acb_realref(z))) { if (complementary) arb_one(acb_realref(t)); else arb_zero(acb_realref(t)); } acb_set(res, t); acb_clear(a); acb_clear(t); acb_clear(u); } void acb_hypgeom_erf_propagated_error(mag_t re, mag_t im, const acb_t z) { mag_t x, y; mag_init(x); mag_init(y); /* |exp(-(x+y)^2)| = exp(y^2-x^2) */ arb_get_mag(y, acb_imagref(z)); mag_mul(y, y, y); arb_get_mag_lower(x, acb_realref(z)); mag_mul_lower(x, x, x); if (mag_cmp(y, x) >= 0) { mag_sub(re, y, x); mag_exp(re, re); } else { mag_sub_lower(re, x, y); mag_expinv(re, re); } /* Radius. */ mag_hypot(x, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul(re, re, x); /* 2/sqrt(pi) < 289/256 */ mag_mul_ui(re, re, 289); mag_mul_2exp_si(re, re, -8); if (arb_is_zero(acb_imagref(z))) { /* todo: could bound magnitude even for complex numbers */ mag_set_ui(y, 2); mag_min(re, re, y); mag_zero(im); } else if (arb_is_zero(acb_realref(z))) { mag_swap(im, re); mag_zero(re); } else { mag_set(im, re); } mag_clear(x); mag_clear(y); } void acb_hypgeom_erf_1f1(acb_t res, const acb_t z, slong prec, slong wp, int more_imaginary) { if (acb_rel_accuracy_bits(z) >= wp) { if (more_imaginary) acb_hypgeom_erf_1f1a(res, z, wp); else acb_hypgeom_erf_1f1b(res, z, wp); } else { acb_t zmid; mag_t re_err, im_err; acb_init(zmid); mag_init(re_err); mag_init(im_err); acb_hypgeom_erf_propagated_error(re_err, im_err, z); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); if (more_imaginary) acb_hypgeom_erf_1f1a(res, zmid, wp); else acb_hypgeom_erf_1f1b(res, zmid, wp); arb_add_error_mag(acb_realref(res), re_err); arb_add_error_mag(acb_imagref(res), im_err); acb_clear(zmid); mag_clear(re_err); mag_clear(im_err); } acb_set_round(res, res, prec); } void acb_hypgeom_erf(acb_t res, const acb_t z, slong prec) { double x, y, abs_z2, log_z, log_erf_z_asymp; slong prec2, wp; int more_imaginary; if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_is_real(z)) { arb_hypgeom_erf(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); return; } if (acb_is_zero(z)) { acb_zero(res); return; } if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -64) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -64) < 0)) { acb_hypgeom_erf_1f1(res, z, prec, prec, 1); return; } if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0)) { acb_hypgeom_erf_asymp(res, z, 0, prec, prec); return; } x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); abs_z2 = x * x + y * y; log_z = 0.5 * log(abs_z2); /* estimate of log(erf(z)), disregarding csgn term */ log_erf_z_asymp = y*y - x*x - log_z; if (log_z - abs_z2 < -(prec + 8) * 0.69314718055994530942) { /* If the asymptotic term is small, we can compute with reduced precision. */ prec2 = FLINT_MIN(prec + 4 + log_erf_z_asymp * 1.4426950408889634074, (double) prec); prec2 = FLINT_MAX(8, prec2); prec2 = FLINT_MIN(prec2, prec); acb_hypgeom_erf_asymp(res, z, 0, prec, prec2); } else { more_imaginary = arf_cmpabs(arb_midref(acb_imagref(z)), arb_midref(acb_realref(z))) > 0; /* Worst case: exp(|x|^2), computed: exp(x^2). (x^2+y^2) - (x^2-y^2) = 2y^2, etc. */ if (more_imaginary) wp = prec + FLINT_MAX(2 * x * x, 0.0) * 1.4426950408889634074 + 5; else wp = prec + FLINT_MAX(2 * y * y, 0.0) * 1.4426950408889634074 + 5; acb_hypgeom_erf_1f1(res, z, prec, wp, more_imaginary); } } flint-3.1.3/src/acb_hypgeom/erf_series.c000066400000000000000000000036251461254215100201770ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_erf_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { acb_t c; acb_init(c); acb_hypgeom_erf(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else { acb_ptr t, u; slong ulen; t = _acb_vec_init(len); u = _acb_vec_init(len); /* erf(h(x)) = integral(h'(x) exp(-h(x)^2)) * (2/sqrt(pi)) */ ulen = FLINT_MIN(len, 2 * hlen - 1); _acb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); _acb_vec_neg(u, u, ulen); _acb_poly_exp_series(u, u, ulen, len, prec); _acb_poly_derivative(t, h, hlen, prec); _acb_poly_mullow(g, u, len, t, hlen - 1, len, prec); _acb_poly_integral(g, g, len, prec); arb_const_sqrt_pi(acb_realref(t), prec); arb_inv(acb_realref(t), acb_realref(t), prec); arb_mul_2exp_si(acb_realref(t), acb_realref(t), 1); _acb_vec_scalar_mul_arb(g, g, len, acb_realref(t), prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_erf_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, len); _acb_hypgeom_erf_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/erfc.c000066400000000000000000000054371461254215100167730ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif void acb_hypgeom_erfc(acb_t res, const acb_t z, slong prec) { double x, y, abs_z2, log_z, log_erfc_z_asymp; if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_is_real(z)) { arb_hypgeom_erfc(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); return; } if (acb_is_zero(z)) { acb_one(res); return; } if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -64) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -64) < 0) || arf_sgn(arb_midref(acb_realref(z))) < 0) { acb_hypgeom_erf(res, z, prec); acb_sub_ui(res, res, 1, prec); acb_neg(res, res); return; } if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0)) { acb_hypgeom_erf_asymp(res, z, 1, prec, prec); return; } x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); abs_z2 = x * x + y * y; if (abs_z2 > (prec + 8) * 0.69314718055994530942) { acb_hypgeom_erf_asymp(res, z, 1, prec, prec); } else { slong wp; log_z = 0.5 * log(abs_z2); log_erfc_z_asymp = y * y - x * x - log_z; wp = prec + 2; if (log_erfc_z_asymp < 0.0) wp += (-log_erfc_z_asymp) * 1.4426950408889634074; if (acb_rel_accuracy_bits(z) >= wp) { acb_hypgeom_erf(res, z, wp); } else { acb_t zmid; mag_t re_err, im_err; acb_init(zmid); mag_init(re_err); mag_init(im_err); acb_hypgeom_erf_propagated_error(re_err, im_err, z); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); acb_hypgeom_erf(res, zmid, wp); arb_add_error_mag(acb_realref(res), re_err); arb_add_error_mag(acb_imagref(res), im_err); acb_clear(zmid); mag_clear(re_err); mag_clear(im_err); } acb_sub_ui(res, res, 1, prec); acb_neg(res, res); } } flint-3.1.3/src/acb_hypgeom/erfc_series.c000066400000000000000000000037701461254215100203430ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_erfc_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { acb_t c; acb_init(c); acb_hypgeom_erfc(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else { acb_ptr t, u; slong ulen; t = _acb_vec_init(len); u = _acb_vec_init(len); /* erfc(h(x)) = integral(-h'(x) exp(-h(x)^2)) * (2/sqrt(pi)) */ ulen = FLINT_MIN(len, 2 * hlen - 1); _acb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); _acb_vec_neg(u, u, ulen); _acb_poly_exp_series(u, u, ulen, len, prec); _acb_poly_derivative(t, h, hlen, prec); _acb_poly_mullow(g, u, len, t, hlen - 1, len, prec); _acb_poly_integral(g, g, len, prec); arb_const_sqrt_pi(acb_realref(t), prec); arb_inv(acb_realref(t), acb_realref(t), prec); arb_mul_2exp_si(acb_realref(t), acb_realref(t), 1); _acb_vec_scalar_mul_arb(g, g, len, acb_realref(t), prec); _acb_vec_neg(g, g, len); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_erfc_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_one(g); return; } acb_poly_fit_length(g, len); _acb_hypgeom_erfc_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/erfi.c000066400000000000000000000011341461254215100167670ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_erfi(acb_t res, const acb_t z, slong prec) { acb_mul_onei(res, z); acb_hypgeom_erf(res, res, prec); acb_mul_onei(res, res); acb_neg(res, res); } flint-3.1.3/src/acb_hypgeom/erfi_series.c000066400000000000000000000025121461254215100203420ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_erfi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_hypgeom_erfi(g, h, prec); _acb_vec_zero(g + 1, len - 1); } else { slong k; acb_ptr t = _acb_vec_init(hlen); for (k = 0; k < hlen; k++) acb_mul_onei(t + k, h + k); _acb_hypgeom_erf_series(g, t, hlen, len, prec); for (k = 0; k < len; k++) acb_div_onei(g + k, g + k); _acb_vec_clear(t, hlen); } } void acb_hypgeom_erfi_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, len); _acb_hypgeom_erfi_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/expint.c000066400000000000000000000012161461254215100173520ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_expint(acb_t res, const acb_t s, const acb_t z, slong prec) { acb_t t; acb_init(t); acb_sub_ui(t, s, 1, prec); acb_neg(t, t); acb_hypgeom_gamma_upper(res, t, z, 2, prec); acb_clear(t); } flint-3.1.3/src/acb_hypgeom/fresnel.c000066400000000000000000000134151461254215100175050ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* We compute the following normalized versions internally: S(z) = (8/sqrt(pi)) int_0^z sin(2t^2) dt C(z) = (8/sqrt(pi)) int_0^z cos(2t^2) dt The benefit is that z^2 can be computed exactly inside erf when we have multiplied by 1+i instead of (1+i)/sqrt(2), so we get faster evaluation and better error bounds for Fresnel integrals on the real line (this is a bit of a hack, and it would be better to somehow pass z^2 directly to the erf evaluation code). */ void acb_hypgeom_fresnel_erf(acb_t res1, acb_t res2, const acb_t z, slong prec) { acb_t t, u, v, w1, w2; acb_init(t); acb_init(v); acb_init(w1); if (arb_is_zero(acb_imagref(z))) { acb_mul_onei(t, z); acb_add(w1, z, t, 2 * prec); acb_hypgeom_erf(t, w1, prec + 4); acb_mul_2exp_si(t, t, 1); acb_mul_onei(v, t); acb_add(t, t, v, prec); if (res1 != NULL) acb_set_arb(res1, acb_realref(t)); if (res2 != NULL) acb_set_arb(res2, acb_imagref(t)); } else if (arb_is_zero(acb_realref(z))) { acb_mul_onei(t, z); acb_sub(w1, t, z, 2 * prec); acb_hypgeom_erf(t, w1, prec + 4); acb_mul_2exp_si(t, t, 1); acb_mul_onei(v, t); acb_add(t, t, v, prec); if (res1 != NULL) acb_set_arb(res1, acb_realref(t)); if (res1 != NULL) acb_mul_onei(res1, res1); if (res2 != NULL) acb_set_arb(res2, acb_imagref(t)); if (res2 != NULL) acb_div_onei(res2, res2); } else { acb_init(u); acb_init(w2); /* w1 = (1+i)z, w2 = (1-i)z */ acb_mul_onei(t, z); acb_add(w1, z, t, 2 * prec); acb_sub(w2, z, t, 2 * prec); acb_hypgeom_erf(t, w1, prec + 4); acb_hypgeom_erf(u, w2, prec + 4); /* S = (1+i) (t - ui) = (1+i) t + (1-i) u */ /* C = (1-i) (t + ui) = (1-i) t + (1+i) u */ acb_mul_onei(v, t); if (res1 != NULL) acb_add(res1, t, v, prec); if (res2 != NULL) acb_sub(res2, t, v, prec); acb_mul_onei(v, u); if (res1 != NULL) acb_add(res1, res1, u, prec); if (res1 != NULL) acb_sub(res1, res1, v, prec); if (res2 != NULL) acb_add(res2, res2, u, prec); if (res2 != NULL) acb_add(res2, res2, v, prec); acb_clear(u); acb_clear(w2); } acb_clear(t); acb_clear(v); acb_clear(w1); } /* derivatives: |8/sqrt(pi) sin(2z^2)|, |8/sqrt(pi) cos(2z^2)| <= 5 exp(4|xy|) */ void acb_hypgeom_fresnel_erf_error(acb_t res1, acb_t res2, const acb_t z, slong prec) { mag_t re; mag_t im; acb_t zmid; mag_init(re); mag_init(im); acb_init(zmid); if (arf_cmpabs_ui(arb_midref(acb_realref(z)), 1000) < 0 && arf_cmpabs_ui(arb_midref(acb_imagref(z)), 1000) < 0) { arb_get_mag(re, acb_realref(z)); arb_get_mag(im, acb_imagref(z)); mag_mul(re, re, im); mag_mul_2exp_si(re, re, 2); mag_exp(re, re); mag_mul_ui(re, re, 5); } else { arb_t t; arb_init(t); arb_mul(t, acb_realref(z), acb_imagref(z), prec); arb_abs(t, t); arb_mul_2exp_si(t, t, 2); arb_exp(t, t, prec); arb_get_mag(re, t); mag_mul_ui(re, re, 5); arb_clear(t); } mag_hypot(im, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul(re, re, im); if (arb_is_zero(acb_imagref(z))) { mag_set_ui(im, 8); /* For real x, |S(x)| < 4, |C(x)| < 4. */ mag_min(re, re, im); mag_zero(im); } else if (arb_is_zero(acb_realref(z))) { mag_set_ui(im, 8); mag_min(im, re, im); mag_zero(re); } else { mag_set(im, re); } arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); acb_hypgeom_fresnel_erf(res1, res2, zmid, prec); if (res1 != NULL) { arb_add_error_mag(acb_realref(res1), re); arb_add_error_mag(acb_imagref(res1), im); } if (res2 != NULL) { arb_add_error_mag(acb_realref(res2), re); arb_add_error_mag(acb_imagref(res2), im); } mag_clear(re); mag_clear(im); acb_clear(zmid); } void acb_hypgeom_fresnel(acb_t res1, acb_t res2, const acb_t z, int normalized, slong prec) { slong wp; acb_t w; arb_t c; if (!acb_is_finite(z)) { if (res1 != NULL) acb_indeterminate(res1); if (res2 != NULL) acb_indeterminate(res2); return; } acb_init(w); arb_init(c); wp = prec + 8; if (normalized) { arb_const_pi(c, wp); arb_sqrt(c, c, wp); arb_mul_2exp_si(c, c, -1); acb_mul_arb(w, z, c, wp); acb_hypgeom_fresnel_erf_error(res1, res2, w, wp); } else { arb_sqrt_ui(c, 2, wp); arb_mul_2exp_si(c, c, -1); acb_mul_arb(w, z, c, wp); acb_hypgeom_fresnel_erf_error(res1, res2, w, wp); arb_const_pi(c, wp); arb_mul_2exp_si(c, c, -1); arb_sqrt(c, c, wp); if (res1 != NULL) acb_mul_arb(res1, res1, c, wp); if (res2 != NULL) acb_mul_arb(res2, res2, c, wp); } if (res1 != NULL) { acb_mul_2exp_si(res1, res1, -2); acb_set_round(res1, res1, prec); } if (res2 != NULL) { acb_mul_2exp_si(res2, res2, -2); acb_set_round(res2, res2, prec); } acb_clear(w); arb_clear(c); } flint-3.1.3/src/acb_hypgeom/fresnel_series.c000066400000000000000000000060071461254215100210560ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_fresnel_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, int normalized, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_hypgeom_fresnel(s, c, h, normalized, prec); if (s != NULL) _acb_vec_zero(s + 1, len - 1); if (c != NULL) _acb_vec_zero(c + 1, len - 1); } else { acb_t s0, c0; acb_ptr t, u, v; slong ulen; acb_init(s0); acb_init(c0); acb_hypgeom_fresnel((s != NULL) ? s0 : NULL, (c != NULL) ? c0 : NULL, h, normalized, prec); t = _acb_vec_init(len); u = _acb_vec_init(len); v = _acb_vec_init(len); /* normalized: */ /* C(h(x)) = integral(h'(x) cos(-(pi/2) h(x)^2)) */ /* S(h(x)) = -integral(h'(x) sin(-(pi/2) h(x)^2)) */ ulen = FLINT_MIN(len, 2 * hlen - 1); _acb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); _acb_vec_neg(u, u, ulen); if (normalized) { _acb_vec_scalar_mul_2exp_si(u, u, ulen, -1); _acb_poly_sin_cos_pi_series(u, v, u, ulen, len, prec); } else { _acb_poly_sin_cos_series(u, v, u, ulen, len, prec); } _acb_poly_derivative(t, h, hlen, prec); if (s != NULL) { _acb_poly_mullow(s, u, len, t, hlen - 1, len, prec); _acb_poly_integral(s, s, len, prec); _acb_vec_neg(s, s, len); acb_swap(s, s0); } if (c != NULL) { _acb_poly_mullow(c, v, len, t, hlen - 1, len, prec); _acb_poly_integral(c, c, len, prec); acb_swap(c, c0); } _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(v, len); acb_clear(s0); acb_clear(c0); } } void acb_hypgeom_fresnel_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, int normalized, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { if (s != NULL) acb_poly_zero(s); if (c != NULL) acb_poly_zero(c); return; } if (s != NULL) acb_poly_fit_length(s, len); if (c != NULL) acb_poly_fit_length(c, len); _acb_hypgeom_fresnel_series((s != NULL) ? s->coeffs : NULL, (c != NULL) ? c->coeffs : NULL, h->coeffs, hlen, normalized, len, prec); if (s != NULL) _acb_poly_set_length(s, len); if (c != NULL) _acb_poly_set_length(c, len); if (s != NULL) _acb_poly_normalise(s); if (c != NULL) _acb_poly_normalise(c); } flint-3.1.3/src/acb_hypgeom/gamma.c000066400000000000000000000131311461254215100171240ustar00rootroot00000000000000/* Copyright (C) 2014, 2015, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #include "arb_hypgeom.h" void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t z, int use_reflect, int digamma, slong prec); void acb_gamma_stirling_bound(mag_ptr err, const acb_t x, slong k0, slong knum, slong n); void acb_hypgeom_gamma_stirling_inner(acb_t s, const acb_t z, slong N, slong prec) { acb_t logz, t; mag_t err; mag_init(err); acb_init(t); acb_init(logz); acb_gamma_stirling_bound(err, z, 0, 1, N); /* t = (z-0.5)*log(z) - z + log(2*pi)/2 */ acb_log(logz, z, prec); arb_one(acb_realref(t)); arb_mul_2exp_si(acb_realref(t), acb_realref(t), -1); acb_sub(t, z, t, prec); acb_mul(t, logz, t, prec); acb_sub(t, t, z, prec); arb_const_log_sqrt2pi(acb_realref(logz), prec); arb_add(acb_realref(t), acb_realref(t), acb_realref(logz), prec); /* sum part */ if (prec <= 128 || (prec <= 1024 && N <= 40) || (prec <= 2048 && N <= 16)) acb_hypgeom_gamma_stirling_sum_horner(s, z, N, prec); else acb_hypgeom_gamma_stirling_sum_improved(s, z, N, 0, prec); acb_add(s, s, t, prec); acb_add_error_mag(s, err); acb_clear(t); acb_clear(logz); mag_clear(err); } void acb_hypgeom_gamma_stirling(acb_t y, const acb_t x, int reciprocal, slong prec) { int reflect; slong r, n, wp; acb_t t, u, v; double acc; wp = prec + FLINT_BIT_COUNT(prec); /* todo: for large x (if exact or accurate enough), increase precision */ acc = acb_rel_accuracy_bits(x); acc = FLINT_MAX(acc, 0); wp = FLINT_MIN(prec, acc + 20); wp = FLINT_MAX(wp, 2); wp = wp + FLINT_BIT_COUNT(wp); if (acc < 3) /* try to avoid divisions blowing up */ { if (arf_cmp_d(arb_midref(acb_realref(x)), -0.5) < 0) { reflect = 1; r = 0; } else if (arf_cmp_si(arb_midref(acb_realref(x)), 1) < 0) { reflect = 0; r = 1; } else { reflect = 0; r = 0; } n = 1; } else { acb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 0, wp); } acb_init(t); acb_init(u); acb_init(v); if (reflect) { acb_sub_ui(t, x, 1, wp); acb_neg(t, t); acb_hypgeom_rising_ui_rec(u, t, r, wp); arb_const_pi(acb_realref(v), wp); acb_mul_arb(u, u, acb_realref(v), wp); acb_add_ui(t, t, r, wp); acb_hypgeom_gamma_stirling_inner(v, t, n, wp); if (reciprocal) { /* rgamma(x) = gamma(1-x+r) sin(pi x) / ((rf(1-x, r) * pi) */ acb_exp(v, v, wp); acb_sin_pi(t, x, wp); acb_mul(v, v, t, wp); acb_mul(y, u, v, wp); acb_div(y, v, u, prec); } else { /* gamma(x) = (rf(1-x, r) * pi) rgamma(1-x+r) csc(pi x) */ acb_neg(v, v); acb_exp(v, v, wp); acb_csc_pi(t, x, wp); acb_mul(v, v, t, wp); acb_mul(y, v, u, prec); } } else { acb_add_ui(t, x, r, wp); acb_hypgeom_gamma_stirling_inner(u, t, n, wp); if (reciprocal) { /* rgamma(x) = rf(x,r) rgamma(x+r) */ acb_neg(u, u); acb_exp(u, u, prec); acb_hypgeom_rising_ui_rec(v, x, r, wp); acb_mul(y, v, u, prec); } else { /* gamma(x) = gamma(x+r) / rf(x,r) */ acb_exp(u, u, prec); acb_hypgeom_rising_ui_rec(v, x, r, wp); acb_div(y, u, v, prec); } } acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_gamma(acb_t y, const acb_t x, slong prec) { if (acb_is_real(x)) { arb_hypgeom_gamma(acb_realref(y), acb_realref(x), prec); arb_zero(acb_imagref(y)); return; } if (acb_hypgeom_gamma_taylor(y, x, 0, prec)) return; acb_hypgeom_gamma_stirling(y, x, 0, prec); } void acb_hypgeom_rgamma(acb_t y, const acb_t x, slong prec) { mag_t magz; if (acb_is_real(x)) { arb_hypgeom_rgamma(acb_realref(y), acb_realref(x), prec); arb_zero(acb_imagref(y)); return; } if (acb_hypgeom_gamma_taylor(y, x, 1, prec)) return; mag_init(magz); acb_get_mag(magz, x); if (mag_is_inf(magz)) { acb_indeterminate(y); } else { acb_hypgeom_gamma_stirling(y, x, 1, prec); /* Todo: improved bounds computation */ if (!acb_is_finite(y)) { arb_t t, u, R; arb_init(R); arb_init(t); arb_init(u); arf_set_mag(arb_midref(R), magz); arb_set_d(u, 0.5); arb_add(u, u, R, MAG_BITS); arb_pow(u, R, u, MAG_BITS); arb_const_pi(t, MAG_BITS); arb_mul(t, t, R, MAG_BITS); arb_mul_2exp_si(t, t, -1); arb_exp(t, t, MAG_BITS); arb_mul(t, t, u, MAG_BITS); arb_get_mag(magz, t); acb_zero(y); acb_add_error_mag(y, magz); arb_clear(R); arb_clear(t); arb_clear(u); } } mag_clear(magz); } flint-3.1.3/src/acb_hypgeom/gamma_lower.c000066400000000000000000000026061461254215100203410ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) { acb_t s1, nz, t, u; if (!acb_is_finite(s) || !acb_is_finite(z)) { acb_indeterminate(res); return; } acb_init(s1); acb_init(nz); acb_init(t); acb_init(u); acb_add_ui(s1, s, 1, prec); acb_neg(nz, z); if (regularized == 0) { /* \gamma(s, z) = s^-1 z^s 1F1(s, 1+s, -z) */ acb_hypgeom_m(u, s, s1, nz, 0, prec); acb_pow(t, z, s, prec); acb_mul(u, u, t, prec); acb_div(res, u, s, prec); } else if (regularized == 1) { /* P(s, z) = z^s \gamma^{*}(s, z) */ acb_hypgeom_m(u, s, s1, nz, 1, prec); acb_pow(t, z, s, prec); acb_mul(res, u, t, prec); } else if (regularized == 2) { /* \gamma^{*}(s, z) */ acb_hypgeom_m(res, s, s1, nz, 1, prec); } acb_clear(s1); acb_clear(nz); acb_clear(t); acb_clear(u); } flint-3.1.3/src/acb_hypgeom/gamma_lower_series.c000066400000000000000000000062141461254215100217120ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_gamma_lower_series(acb_ptr g, const acb_t s, acb_srcptr h, slong hlen, int regularized, slong n, slong prec) { acb_t c; hlen = FLINT_MIN(hlen, n); if (regularized == 2 && acb_is_int(s) && arb_is_nonpositive(acb_realref(s))) { acb_t ns; acb_init(ns); acb_neg(ns, s); if (g == h) { acb_ptr t = _acb_vec_init(hlen); _acb_vec_set(t, h, hlen); _acb_poly_pow_acb_series(g, t, hlen, ns, n, prec); _acb_vec_clear(t, hlen); } else { _acb_poly_pow_acb_series(g, h, hlen, ns, n, prec); } acb_clear(ns); return; } acb_init(c); acb_hypgeom_gamma_lower(c, s, h, regularized, prec); if (hlen == 1) { _acb_vec_zero(g + 1, n - 1); } else { acb_ptr t, u, v; acb_ptr w = NULL; t = _acb_vec_init(n); u = _acb_vec_init(n); v = _acb_vec_init(n); if (regularized == 2) { w = _acb_vec_init(n); acb_neg(t, s); _acb_poly_pow_acb_series(w, h, hlen, t, n, prec); } /* gamma(s, h(x)) = integral(h'(x) h(x)^(s-1) exp(-h(x)) */ acb_sub_ui(u, s, 1, prec); _acb_poly_pow_acb_series(t, h, hlen, u, n, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_mullow(v, t, n, u, hlen - 1, n, prec); _acb_vec_neg(t, h, hlen); _acb_poly_exp_series(t, t, hlen, n, prec); _acb_poly_mullow(g, v, n, t, n, n, prec); _acb_poly_integral(g, g, n, prec); if (regularized == 1) { acb_rgamma(t, s, prec); _acb_vec_scalar_mul(g, g, n, t, prec); } else if (regularized == 2) { acb_rgamma(t, s, prec); _acb_vec_scalar_mul(g, g, n, t, prec); _acb_vec_set(u, g, n); _acb_poly_mullow(g, u, n, w, n, n, prec); _acb_vec_clear(w, n); } _acb_vec_clear(t, n); _acb_vec_clear(u, n); _acb_vec_clear(v, n); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_gamma_lower_series(acb_poly_t g, const acb_t s, const acb_poly_t h, int regularized, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, n); if (hlen == 0) { acb_t t; acb_init(t); _acb_hypgeom_gamma_lower_series(g->coeffs, s, t, 1, regularized, n, prec); acb_clear(t); } else { _acb_hypgeom_gamma_lower_series( g->coeffs, s, h->coeffs, hlen, regularized, n, prec); } _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/gamma_stirling_sum_horner.c000066400000000000000000000034151461254215100233040ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void arb_gamma_stirling_coeff(arb_t b, ulong k, int digamma, slong prec); void acb_hypgeom_gamma_stirling_sum_horner(acb_t s, const acb_t z, slong N, slong prec) { acb_t b, t, zinv, w; mag_t zinv_mag; slong n, term_mag, term_prec; slong * term_mags; if (N <= 1) { acb_zero(s); return; } acb_init(b); acb_init(t); acb_init(zinv); acb_init(w); mag_init(zinv_mag); acb_inv(zinv, z, prec); acb_mul(w, zinv, zinv, prec); acb_get_mag(zinv_mag, zinv); term_mags = flint_malloc(sizeof(ulong) * N); _arb_hypgeom_gamma_stirling_term_bounds(term_mags, zinv_mag, N); acb_zero(s); for (n = N - 1; n >= 1; n--) { term_mag = term_mags[n]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); if (prec - term_prec > 200) { acb_set_round(t, w, term_prec); acb_mul(s, s, t, term_prec); } else acb_mul(s, s, w, term_prec); arb_gamma_stirling_coeff(acb_realref(b), n, 0, term_prec); acb_add_arb(s, s, acb_realref(b), term_prec); } acb_mul(s, s, zinv, prec); flint_free(term_mags); acb_clear(t); acb_clear(b); acb_clear(zinv); acb_clear(w); mag_clear(zinv_mag); } flint-3.1.3/src/acb_hypgeom/gamma_stirling_sum_improved.c000066400000000000000000000311701461254215100236330ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #include "bernoulli.h" /* todo: move to acb module */ static void acb_fma_ui(acb_t res, const acb_t x, ulong y, const acb_t z, slong prec) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ arb_fma_arf(acb_realref(res), acb_realref(x), t, acb_realref(z), prec); arb_fma_arf(acb_imagref(res), acb_imagref(x), t, acb_imagref(z), prec); } void acb_hypgeom_gamma_stirling_sum_improved(acb_t s, const acb_t z, slong N, slong K, slong prec) { acb_t b, t, zinv, w, u, S2, S3, S4; mag_t zinv_mag, err; slong n, term_mag, term_prec; slong * term_mags; slong i, j, k, M; slong * Mk; acb_ptr upow, ukpow; slong kodd, kpow_exp, wp; fmpz_t kpow; slong m; if (N <= 1) { acb_zero(s); return; } if (N == 2) { acb_mul_ui(s, z, 12, prec); acb_inv(s, s, prec); return; } if (K == 0) { if (prec <= 128) K = 1; else if (prec <= 1024) K = 2; else { K = 4 + 0.1 * sqrt(FLINT_MAX(prec - 4096, 0)); K = FLINT_MIN(K, 100); } } acb_init(b); acb_init(t); acb_init(zinv); acb_init(w); acb_init(u); acb_init(S2); acb_init(S3); acb_init(S4); mag_init(zinv_mag); mag_init(err); acb_inv(zinv, z, prec); acb_mul(w, zinv, zinv, prec); acb_get_mag(zinv_mag, zinv); term_mags = flint_malloc(sizeof(ulong) * (N + 1)); /* Avoid possible overflow. (This case is not interesting to handle well, but we need to handle it.) */ if (mag_cmp_2exp_si(zinv_mag, 10) > 0) K = 1; /* Avoid possible underflow. */ if (mag_cmp_2exp_si(zinv_mag, -100000) < 0) mag_set_ui_2exp_si(zinv_mag, 1, -100000); _arb_hypgeom_gamma_stirling_term_bounds(term_mags, zinv_mag, N + 1); /* We will assume below that term_mags is nonincreasing */ for (n = N - 2; n >= 1; n--) { if (term_mags[n] < term_mags[n + 1]) term_mags[n] = term_mags[n + 1]; } Mk = NULL; if (K > 1) { Mk = flint_malloc(sizeof(slong) * (K + 1)); Mk[0] = Mk[1] = N; for (k = 2; k <= K; k++) { double log2_k; Mk[k] = N; log2_k = log(k) * (1.0 / 0.693147180559945309); while (Mk[k] > 2) { slong err, Mnew; Mnew = Mk[k] - 1; err = term_mags[Mnew] - log2_k * (2 * Mnew) + FLINT_BIT_COUNT(N - Mnew); if (err < -prec) Mk[k] = Mnew; else break; } } /* We will assume that Mk is nonincreasing. */ for (k = 2; k <= K; k++) { if (Mk[k] > Mk[k - 1]) Mk[k] = Mk[k - 1]; } while (K >= 2 && Mk[K] == Mk[K - 1]) K--; M = Mk[K]; mag_hurwitz_zeta_uiui(err, 2 * M, K); mag_mul_ui(err, err, N - M); mag_mul_2exp_si(err, err, term_mags[M]); for (k = 1; k < K; k++) { mag_t t; mag_init(t); mag_set_ui_lower(t, k); mag_inv(t, t); mag_pow_ui(t, t, 2 * Mk[k]); mag_mul_ui(t, t, N - Mk[k]); mag_mul_2exp_si(t, t, term_mags[Mk[k]]); mag_add(err, err, t); mag_clear(t); } } else { M = N; } m = sqrt(N - M); m = FLINT_MAX(m, 1); /* S3 precision */ wp = prec + term_mags[M]; wp = FLINT_MIN(wp, prec); wp = FLINT_MAX(wp, 10); acb_zero(S3); /* todo: could avoid one mul + div with precomputation here */ /* u = -1 / (2 pi z)^2 */ acb_const_pi(u, wp); acb_mul(u, u, z, wp); acb_mul_2exp_si(u, u, 1); acb_mul(u, u, u, wp); acb_inv(u, u, wp); acb_neg(u, u); fmpz_init(kpow); upow = _acb_vec_init(m + 1); ukpow = _acb_vec_init(m + 1); _acb_vec_set_powers(upow, u, m + 1, wp); for (kodd = 1; kodd < K; kodd += 2) { for (k = kodd; k < K; k *= 2) { if (k == 1) { _acb_vec_set(ukpow, upow, m + 1); fmpz_one(kpow); kpow_exp = 0; } else if (k == kodd) { acb_set(ukpow + 0, upow + 0); for (j = 1; j <= FLINT_MIN(Mk[k] - M - 1, m); j++) { if (j == 1) fmpz_set_ui(kpow, k * k); else fmpz_mul_ui(kpow, kpow, k * k); acb_div_fmpz(ukpow + j, upow + j, kpow, wp); } /* set kpow = k^(2M) */ fmpz_ui_pow_ui(kpow, k * k, M); kpow_exp = 0; } else { /* compute x / k^(2j) given x / (k/2)^(2j) */ for (j = 1; j <= FLINT_MIN(Mk[k] - M - 1, m); j++) acb_mul_2exp_si(ukpow + j, ukpow + j, -2 * j); kpow_exp += 2 * M; } acb_zero(S4); for (n = Mk[k] - 1; n >= M; n--) { i = n - M; term_prec = prec + term_mags[n]; term_prec = FLINT_MIN(wp, prec); term_prec = FLINT_MAX(term_prec, 10); /* note: set_round makes small difference here */ acb_fma_ui(S4, S4, (2 * n) * (2 * n - 1), ukpow + i % m, term_prec); if (i != 0 && i % m == 0) { /* note: set_round makes small difference here */ acb_mul(S4, S4, ukpow + m, term_prec); } } /* divide by k^(2M) */ if (k != 1) { if (!fmpz_is_one(kpow)) acb_div_fmpz(S4, S4, kpow, wp); acb_mul_2exp_si(S4, S4, -kpow_exp); } acb_add(S3, S3, S4, wp); } } /* multiply by -2 (2M-2)! u^M z */ fmpz_fac_ui(kpow, 2 * M - 2); acb_mul_fmpz(S3, S3, kpow, wp); acb_pow_ui(u, u, M, wp); acb_mul(S3, S3, u, wp); acb_set_round(t, z, wp); acb_mul(S3, S3, t, wp); acb_mul_2exp_si(S3, S3, 1); acb_neg(S3, S3); acb_add_error_mag(S3, err); _acb_vec_clear(upow, m + 1); _acb_vec_clear(ukpow, m + 1); fmpz_clear(kpow); acb_zero(S2); m = sqrt(M); upow = _acb_vec_init(m + 1); _acb_vec_set_powers(upow, w, m + 1, prec); BERNOULLI_ENSURE_CACHED(2 * M - 2); { fmpz_t d, e, f, g, h; fmpz q[4]; fmpz_init(d); fmpz_init(e); fmpz_init(f); fmpz_init(g); fmpz_init(h); fmpz_init(q); fmpz_init(q + 1); fmpz_init(q + 2); fmpz_init(q + 3); for (n = M - 1; n >= 1; n--) { i = n - 1; if (i >= 4 && i % m >= 3 && prec >= 512 && prec <= 4096) { term_mag = term_mags[n - 3]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * (n - 0)), 2 * (n - 0) * (2 * (n - 0) - 1)); fmpz_mul_ui(e, fmpq_denref(bernoulli_cache + 2 * (n - 1)), 2 * (n - 1) * (2 * (n - 1) - 1)); fmpz_mul_ui(g, fmpq_denref(bernoulli_cache + 2 * (n - 2)), 2 * (n - 2) * (2 * (n - 2) - 1)); fmpz_mul_ui(h, fmpq_denref(bernoulli_cache + 2 * (n - 3)), 2 * (n - 3) * (2 * (n - 3) - 1)); /* q3 = egh q2 = dgh q1 = deh q0 = deg d = degh */ fmpz_mul(q + 3, e, g); fmpz_mul(q + 0, q + 3, d); fmpz_mul(q + 3, q + 3, h); fmpz_mul(q + 2, d, h); fmpz_mul(q + 1, q + 2, e); fmpz_mul(q + 2, q + 2, g); fmpz_mul(d, q + 3, d); fmpz_mul(q + 3, q + 3, fmpq_numref(bernoulli_cache + 2 * (n - 0))); fmpz_mul(q + 2, q + 2, fmpq_numref(bernoulli_cache + 2 * (n - 1))); fmpz_mul(q + 1, q + 1, fmpq_numref(bernoulli_cache + 2 * (n - 2))); fmpz_mul(q + 0, q + 0, fmpq_numref(bernoulli_cache + 2 * (n - 3))); acb_dot_fmpz(t, NULL, 0, upow + i % m - 3, 1, q, 1, 4, term_prec); acb_div_fmpz(t, t, d, term_prec); acb_add(S2, S2, t, term_prec); n -= 3; i -= 3; } else if (i >= 3 && i % m >= 2) { term_mag = term_mags[n - 2]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * (n - 0)), 2 * (n - 0) * (2 * (n - 0) - 1)); fmpz_mul_ui(e, fmpq_denref(bernoulli_cache + 2 * (n - 1)), 2 * (n - 1) * (2 * (n - 1) - 1)); fmpz_mul_ui(g, fmpq_denref(bernoulli_cache + 2 * (n - 2)), 2 * (n - 2) * (2 * (n - 2) - 1)); fmpz_mul(q + 2, e, g); fmpz_mul(q + 2, q + 2, fmpq_numref(bernoulli_cache + 2 * (n - 0))); fmpz_mul(q + 1, d, g); fmpz_mul(q + 1, q + 1, fmpq_numref(bernoulli_cache + 2 * (n - 1))); fmpz_mul(q + 0, d, e); fmpz_mul(d, q + 0, g); fmpz_mul(q + 0, q + 0, fmpq_numref(bernoulli_cache + 2 * (n - 2))); acb_dot_fmpz(t, NULL, 0, upow + i % m - 2, 1, q, 1, 3, term_prec); acb_div_fmpz(t, t, d, term_prec); acb_add(S2, S2, t, term_prec); n -= 2; i -= 2; } else if (i >= 1 && i % m >= 1) { term_mag = term_mags[n - 1]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * (n - 0)), 2 * (n - 0) * (2 * (n - 0) - 1)); fmpz_mul_ui(e, fmpq_denref(bernoulli_cache + 2 * (n - 1)), 2 * (n - 1) * (2 * (n - 1) - 1)); fmpz_mul(f, fmpq_numref(bernoulli_cache + 2 * (n - 0)), e); acb_set_round(u, upow + i % m, term_prec); acb_mul_fmpz(t, u, f, term_prec); /* todo: output-sensitive mul */ fmpz_mul(f, fmpq_numref(bernoulli_cache + 2 * (n - 1)), d); acb_set_round(u, upow + i % m - 1, term_prec); acb_mul_fmpz(u, u, f, term_prec); /* todo: output-sensitive mul */ acb_add(t, t, u, term_prec); fmpz_mul(d, d, e); acb_div_fmpz(t, t, d, term_prec); acb_add(S2, S2, t, term_prec); n--; i--; } else { term_mag = term_mags[n]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); acb_set_round(u, upow + i % m, term_prec); acb_mul_fmpz(t, u, fmpq_numref(bernoulli_cache + 2 * n), term_prec); /* todo: output-sensitive mul */ fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * n), 2 * n * (2 * n - 1)); acb_div_fmpz(t, t, d, term_prec); acb_add(S2, S2, t, term_prec); } if (i != 0 && i % m == 0) { acb_set_round(u, upow + m, term_prec); /* todo: output-sensitive mul */ acb_mul(S2, S2, u, term_prec); } } fmpz_clear(q); fmpz_clear(q + 1); fmpz_clear(q + 2); fmpz_clear(q + 3); fmpz_clear(d); fmpz_clear(e); fmpz_clear(f); fmpz_clear(g); fmpz_clear(h); } _acb_vec_clear(upow, m + 1); acb_mul(S2, S2, zinv, prec); acb_add(s, S2, S3, prec); flint_free(term_mags); if (Mk != NULL) flint_free(Mk); acb_clear(b); acb_clear(t); acb_clear(zinv); acb_clear(w); acb_clear(u); acb_clear(S2); acb_clear(S3); acb_clear(S4); mag_clear(zinv_mag); mag_clear(err); } flint-3.1.3/src/acb_hypgeom/gamma_taylor.c000066400000000000000000000150751461254215100205270ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif static void evaluate_rect(acb_t res, const short * term_prec, slong len, const acb_t x, slong prec) { slong i, j, m, r, n1, n2; acb_ptr xs; acb_t s, t; arb_struct c[17]; m = n_sqrt(len) + 1; m = FLINT_MIN(m, 16); r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); _acb_vec_set_powers(xs, x, m + 1, prec); acb_zero(res); for (i = r - 1; i >= 0; i--) { n1 = m * i; n2 = FLINT_MIN(len, n1 + m); for (j = n1; j < n2; j++) { if (j == 0) { arb_init(c); arb_one(c); } else { if (!_arb_hypgeom_gamma_coeff_shallow(arb_midref(c + j - n1), arb_radref(c + j - n1), j, term_prec[j])) flint_throw(FLINT_ERROR, "(%s)\n", __func__); } } arb_dot(acb_realref(s), NULL, 0, acb_realref(xs), 2, c, 1, n2 - n1, prec); arb_dot(acb_imagref(s), NULL, 0, acb_imagref(xs), 2, c, 1, n2 - n1, prec); #if 0 acb_set_round(t, xs + m, term_prec[n1]); acb_mul(res, res, t, term_prec[n1]); acb_add(res, res, s, term_prec[n1]); #else acb_mul(res, res, xs + m, term_prec[n1]); acb_add(res, res, s, term_prec[n1]); #endif } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); } /* Bound requires: |u| <= 20, N <= 10000, N != (1443, 2005, 9891). */ static void error_bound(mag_t err, const acb_t u, slong N) { mag_t t; mag_init(t); acb_get_mag(t, u); if (N >= 1443 || mag_cmp_2exp_si(t, 4) > 0) { mag_inf(err); } else { mag_pow_ui(err, t, N); mag_mul_2exp_si(err, err, arb_hypgeom_gamma_coeffs[N].exp); if (mag_cmp_2exp_si(t, -1) > 0) mag_mul(err, err, t); else mag_mul_2exp_si(err, err, -1); mag_mul_2exp_si(err, err, 3); if (mag_cmp_2exp_si(err, -8) > 0) mag_inf(err); } mag_clear(t); } static double want_taylor(double x, double y, slong prec) { if (y < 0.0) y = -y; if (x < 0.0) x = -x; if ((prec < 128 && y > 4.0) || (prec < 256 && y > 5.0) || (prec < 512 && y > 8.0) || (prec < 1024 && y > 9.0) || y > 10.0) { return 0; } if (x * (1.0 + 0.75 * y) > 8 + 0.15 * prec) { return 0; } return 1; } int acb_hypgeom_gamma_taylor(acb_t res, const acb_t z, int reciprocal, slong prec) { acb_t s, u; int success; double dua, dub, du2, log2u; slong i, r, n, wp, tail_bound, goal; short term_prec[ARB_HYPGEOM_GAMMA_TAB_NUM]; mag_t err; if (!acb_is_finite(z) || arf_cmp_2exp_si(arb_midref(acb_imagref(z)), 4) >= 0 || arf_cmp_2exp_si(arb_midref(acb_realref(z)), 10) >= 0) { return 0; } dua = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_UP); dub = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_UP); dub = fabs(dub); if (!want_taylor(dua, dub, prec)) return 0; if (dua >= 0.0) r = (slong) (dua + 0.5); else r = -(slong) (-dua + 0.5); acb_init(s); acb_init(u); mag_init(err); success = 0; /* Argument reduction: u = z - r */ acb_sub_si(u, z, r, 2 * prec + 10); dua -= r; goal = acb_rel_accuracy_bits(u); /* not designed for wide intervals (yet) */ if (goal < 8) { success = 0; goto cleanup; } goal = FLINT_MIN(goal, prec - MAG_BITS) + MAG_BITS; goal = FLINT_MAX(goal, 5); goal = goal + 5; wp = goal + 4 + FLINT_BIT_COUNT(FLINT_ABS(r)); if (wp > ARB_HYPGEOM_GAMMA_TAB_PREC) { success = 0; goto cleanup; } if (!want_taylor(r, dub, goal)) { success = 0; goto cleanup; } du2 = dua * dua + dub * dub; if (du2 > 1e-8) { log2u = 0.5 * mag_d_log_upper_bound(du2) * 1.4426950408889634074 * (1 + 1e-14); } else { slong aexp, bexp; aexp = arf_cmpabs_2exp_si(arb_midref(acb_realref(u)), -wp) >= 0 ? ARF_EXP(arb_midref(acb_realref(u))) : -wp; bexp = arf_cmpabs_2exp_si(arb_midref(acb_imagref(u)), -wp) >= 0 ? ARF_EXP(arb_midref(acb_imagref(u))) : -wp; log2u = FLINT_MAX(aexp, bexp) + 1; } term_prec[0] = wp; n = 0; for (i = 1; i < ARB_HYPGEOM_GAMMA_TAB_NUM; i++) { tail_bound = arb_hypgeom_gamma_coeffs[i].exp + i * log2u + 5; if (tail_bound <= -goal) { n = i; break; } term_prec[i] = FLINT_MIN(FLINT_MAX(wp + tail_bound, 2), wp); if (term_prec[i] > arb_hypgeom_gamma_coeffs[i].nlimbs * FLINT_BITS) { success = 0; goto cleanup; } } if (n != 0) error_bound(err, u, n); if (n == 0 || mag_is_inf(err)) { success = 0; goto cleanup; } evaluate_rect(s, term_prec, n, u, wp); acb_add_error_mag(s, err); if (r == 0 || r == 1) { if (r == 0) acb_mul(s, s, u, wp); if (reciprocal) { acb_set_round(res, s, prec); } else { acb_one(u); acb_div(res, u, s, prec); } } else if (r >= 2) { acb_add_ui(u, u, 1, wp); acb_hypgeom_rising_ui_rec(u, u, r - 1, wp); if (reciprocal) acb_div(res, s, u, prec); else acb_div(res, u, s, prec); } else { /* gamma(x) = (-1)^r / (rgamma(1+x-r)*rf(1+r-x,-r)*(x-r)) */ /* 1/gamma(x) = (-1)^r * rgamma(1+x-r) * rf(1+r-x,-r) * (x-r) */ acb_neg(res, z); acb_add_si(res, res, 1 + r, wp); acb_hypgeom_rising_ui_rec(res, res, -r, wp); acb_mul(u, res, u, wp); if (reciprocal) { acb_mul(res, s, u, prec); } else { acb_mul(u, s, u, wp); acb_inv(res, u, prec); } if (r % 2) acb_neg(res, res); } success = 1; cleanup: acb_clear(s); acb_clear(u); mag_clear(err); return success; } flint-3.1.3/src/acb_hypgeom/gamma_upper.c000066400000000000000000000314701461254215100203450ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" int acb_hypgeom_u_asymp_determine_region(const mag_t r, const mag_t zlo, const acb_t z); void acb_hypgeom_gamma_upper_asymp(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_sub_ui(t, s, 1, prec); acb_neg(t, t); acb_hypgeom_u_asymp(u, t, t, z, -1, prec); if (regularized == 2) { acb_div(u, u, z, prec); } else { acb_neg(t, t); acb_pow(t, z, t, prec); acb_mul(u, u, t, prec); if (regularized == 1) { acb_rgamma(t, s, prec); acb_mul(u, u, t, prec); } } acb_neg(t, z); acb_exp(t, t, prec); acb_mul(res, t, u, prec); acb_clear(t); acb_clear(u); } void acb_hypgeom_gamma_upper_1f1a(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) { acb_t a, t, w; acb_struct b[2]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(t); acb_init(w); acb_set(a, s); acb_add_ui(b, s, 1, prec); acb_one(b + 1); acb_neg(w, z); /* t = 1F1(s, s+1, -z) / s */ acb_hypgeom_pfq_direct(t, a, 1, b, 2, w, -1, prec); acb_div(t, t, s, prec); if (regularized == 2) { acb_neg(a, s); acb_pow(a, z, a, prec); acb_gamma(b, s, prec); acb_mul(b, b, a, prec); acb_sub(res, b, t, prec); } else { acb_pow(a, z, s, prec); acb_mul(t, t, a, prec); if (regularized == 1) { acb_rgamma(a, s, prec); acb_mul(t, t, a, prec); acb_sub_ui(res, t, 1, prec); acb_neg(res, res); } else { acb_gamma(a, s, prec); acb_sub(res, a, t, prec); } } acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(t); acb_clear(w); } void acb_hypgeom_gamma_upper_1f1b(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) { acb_t a, b, t; acb_init(a); acb_init(b); acb_init(t); acb_add_ui(b, s, 1, prec); acb_hypgeom_pfq_direct(t, NULL, 0, b, 1, z, -1, prec); acb_div(t, t, s, prec); acb_neg(a, z); acb_exp(a, a, prec); acb_mul(t, t, a, prec); if (regularized == 2) { acb_neg(a, s); acb_pow(a, z, a, prec); acb_gamma(b, s, prec); acb_mul(b, b, a, prec); acb_sub(res, b, t, prec); } else { acb_pow(a, z, s, prec); acb_mul(t, t, a, prec); if (regularized == 1) { acb_rgamma(a, s, prec); acb_mul(t, t, a, prec); acb_sub_ui(res, t, 1, prec); acb_neg(res, res); } else { acb_gamma(a, s, prec); acb_sub(res, a, t, prec); } } acb_clear(a); acb_clear(b); acb_clear(t); } /* requires n <= 0 */ void acb_hypgeom_gamma_upper_singular(acb_t res, slong s, const acb_t z, int regularized, slong prec) { acb_t A, B, C, t, u; acb_struct a[2]; acb_struct b[2]; arb_t f; slong n; if (regularized == 1) { acb_zero(res); return; } n = -s; acb_init(A); acb_init(B); acb_init(C); acb_init(t); acb_init(u); arb_init(f); acb_init(a + 0); acb_init(a + 1); acb_init(b + 0); acb_init(b + 1); arb_fac_ui(f, n, prec); /* (-1)^n (psi(n+1) - log(z)) / n! */ acb_set_ui(A, n + 1); acb_digamma(A, A, prec); acb_log(t, z, prec); acb_sub(A, A, t, prec); acb_div_arb(A, A, f, prec); if (n % 2) acb_neg(A, A); /* (-1)^n z 2F2(1,1;2,2+n;-z) / (n+1)! */ acb_set_si(a, 1); acb_set_si(b, 2); acb_set_si(b + 1, 2 + n); acb_neg(t, z); acb_hypgeom_pfq_direct(B, a, 1, b, 2, t, -1, prec); acb_mul(B, B, z, prec); arb_mul_ui(f, f, n + 1, prec); acb_div_arb(B, B, f, prec); if (n % 2) acb_neg(B, B); /* -sum((-z)^k / ((k-n) k!), k=0...n-1) */ acb_set_si(a, -n); acb_set_si(b, 1 - n); acb_set_si(b + 1, 1); acb_neg(t, z); if (n == 0) { acb_zero(C); } else { acb_hypgeom_pfq_sum(C, u, a, 1, b, 2, t, n, prec); acb_div_ui(C, C, n, prec); } if (regularized == 2) { acb_pow_si(t, z, n, prec); acb_mul(A, A, t, prec); acb_mul(B, B, t, prec); } else { acb_pow_si(t, z, -n, prec); acb_mul(C, C, t, prec); } acb_add(res, A, B, prec); acb_add(res, res, C, prec); acb_clear(A); acb_clear(B); acb_clear(C); acb_clear(t); acb_clear(u); arb_clear(f); acb_clear(a + 0); acb_clear(a + 1); acb_clear(b + 0); acb_clear(b + 1); } static int _determine_region(const acb_t s, const acb_t z) { int R; mag_t r, zlo; acb_t t; mag_init(r); mag_init(zlo); acb_init(t); /* lower bound for |z| */ acb_get_mag_lower(zlo, z); /* upper bound for r = |s - 1| */ acb_sub_ui(t, s, 1, MAG_BITS); acb_get_mag(r, t); R = acb_hypgeom_u_asymp_determine_region(r, zlo, z); mag_clear(r); mag_clear(zlo); acb_clear(t); return R; } /* Returns 1 if it can be determined that a^n > b^n + c^n. * Requires 1 <= n <= WORD_MAX. * If n == WORD_MAX, the infinity norm a > max(b, c) is compared instead. */ int _mag_gt_norm_ui(const mag_t a, const mag_t b, const mag_t c, ulong n) { int result; result = 0; if (n < 1) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } else if (mag_is_zero(a)) { result = 0; } else if (mag_is_zero(b)) { result = mag_cmp(a, c) > 0; } else if (mag_is_zero(c)) { result = mag_cmp(a, b) > 0; } else if (n == WORD_MAX) { result = mag_cmp(a, b) > 0 && mag_cmp(a, c) > 0; } else if (n == 1) { mag_t sum; mag_init(sum); mag_add(sum, b, c); result = mag_cmp(a, sum) > 0; mag_clear(sum); } else if (_mag_gt_norm_ui(a, b, c, 1)) { result = 1; } else if (!_mag_gt_norm_ui(a, b, c, WORD_MAX)) { result = 0; } else { mag_t u, v, w, sum; mag_init(u); mag_init(v); mag_init(w); mag_init(sum); mag_pow_ui_lower(u, a, n); mag_pow_ui(v, b, n); mag_pow_ui(w, c, n); mag_add(sum, v, w); result = mag_cmp(u, sum) > 0; mag_clear(u); mag_clear(v); mag_clear(w); mag_clear(sum); } return result; } /* Given nonnegative real s, x, and prec, * returns 1 if the asymptotic expansion of the * hypergeometric U function should be used for upper incomplete gamma. * It returns 1 if x > 4 and (x-c)^8 > (a*s)^8 + (b*prec)^8. * Careful mag rounding is not used because this is just a heuristic. */ static int _nonnegative_real_use_asymp(const mag_t s, const mag_t x, slong prec) { int result; result = 0; if (mag_cmp_2exp_si(x, 2) > 0) { mag_t a, b, c, u, v, w; mag_init(a); mag_init(b); mag_init(c); mag_init(u); mag_init(v); mag_init(w); mag_set_d(a, 1.029287542); mag_set_d(b, 0.3319411658); mag_set_d(c, 2.391097143); mag_sub(u, x, c); mag_mul(v, a, s); mag_mul_ui(w, b, FLINT_MAX(0, prec)); result = _mag_gt_norm_ui(u, v, w, 8); mag_clear(a); mag_clear(b); mag_clear(c); mag_clear(u); mag_clear(v); mag_clear(w); } return result; } static int _acb_is_nonnegative_real(const acb_t z) { return arb_is_zero(acb_imagref(z)) && arb_is_nonnegative(acb_realref(z)); } void acb_hypgeom_gamma_upper_nointegration(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) { if (!acb_is_finite(s) || !acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_is_zero(z)) { if (regularized == 2) { if (arb_is_negative(acb_realref(s))) { acb_inv(res, s, prec); acb_neg(res, res); } else { acb_indeterminate(res); } } else { if (arb_is_positive(acb_realref(s))) { if (regularized == 1) acb_one(res); else acb_gamma(res, s, prec); } else { acb_indeterminate(res); } } } else { slong n = WORD_MAX; if (acb_is_int(s)) { if (regularized == 1 && arf_sgn(arb_midref(acb_realref(s))) <= 0) { acb_zero(res); return; } if (arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), 30) < 0) { n = arf_get_si(arb_midref(acb_realref(s)), ARF_RND_DOWN); } } if (n >= 1 && n <= 3) { acb_t t, u; acb_init(t); acb_init(u); if (regularized == 2) acb_pow_si(u, z, n, prec); if (n == 1) { acb_neg(res, z); acb_exp(res, res, prec); } else if (n == 2) { acb_add_ui(t, z, 1, prec); acb_neg(res, z); acb_exp(res, res, prec); acb_mul(res, res, t, prec); } else if (n == 3) { acb_add_ui(t, z, 2, prec); acb_mul(t, t, z, prec); acb_add_ui(t, t, 2, prec); acb_neg(res, z); acb_exp(res, res, prec); acb_mul(res, res, t, prec); } if (regularized == 2) acb_div(res, res, u, prec); else if (regularized == 1 && n == 3) acb_mul_2exp_si(res, res, -1); acb_clear(t); acb_clear(u); return; } if (_acb_is_nonnegative_real(s) && _acb_is_nonnegative_real(z)) { int result; mag_t ms, mx; mag_init(ms); mag_init(mx); arb_get_mag(ms, acb_realref(s)); arb_get_mag(mx, acb_realref(z)); result = _nonnegative_real_use_asymp(ms, mx, prec); mag_clear(ms); mag_clear(mx); if (result) { acb_hypgeom_gamma_upper_asymp(res, s, z, regularized, prec); return; } } else if (acb_hypgeom_u_use_asymp(z, prec) && ((0 < n && n < WORD_MAX) || _determine_region(s, z))) { acb_hypgeom_gamma_upper_asymp(res, s, z, regularized, prec); return; } if (n <= 0 && n > -10 * prec) { acb_hypgeom_gamma_upper_singular(res, n, z, regularized, prec); return; } if (arf_sgn(arb_midref(acb_realref(z))) > 0) acb_hypgeom_gamma_upper_1f1b(res, s, z, regularized, prec); else acb_hypgeom_gamma_upper_1f1a(res, s, z, regularized, prec); } } void acb_hypgeom_gamma_upper(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) { acb_t res2; slong acc, max, t; acb_init(res2); acb_hypgeom_gamma_upper_nointegration(res2, s, z, regularized, prec); acc = acb_rel_accuracy_bits(res2); if (acc < 0.5 * prec) { max = prec; t = acb_rel_accuracy_bits(z); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(s); max = FLINT_MIN(max, t); if (max > 2 && acc < 0.5 * max) { if (acb_is_real(s) && acb_is_real(z) && arf_cmp_2exp_si(arb_midref(acb_realref(z)), -16) > 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0) { arb_hypgeom_gamma_upper_integration(acb_realref(res), acb_realref(s), acb_realref(z), regularized, prec); arb_zero(acb_imagref(res)); if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) || (acb_is_finite(res) && !acb_is_finite(res2))) { acb_swap(res, res2); } } } } acb_swap(res, res2); acb_clear(res2); } flint-3.1.3/src/acb_hypgeom/gamma_upper_series.c000066400000000000000000000051261461254215100217160ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_gamma_upper_series(acb_ptr g, const acb_t s, acb_srcptr h, slong hlen, int regularized, slong n, slong prec) { acb_t c; acb_init(c); acb_hypgeom_gamma_upper(c, s, h, regularized, prec); hlen = FLINT_MIN(hlen, n); if (hlen == 1) { _acb_vec_zero(g + 1, n - 1); } else { acb_ptr t, u, v; acb_ptr w = NULL; t = _acb_vec_init(n); u = _acb_vec_init(n); v = _acb_vec_init(n); if (regularized == 2) { w = _acb_vec_init(n); acb_neg(t, s); _acb_poly_pow_acb_series(w, h, hlen, t, n, prec); } /* Gamma(s, h(x)) = -integral(h'(x) h(x)^(s-1) exp(-h(x)) */ acb_sub_ui(u, s, 1, prec); _acb_poly_pow_acb_series(t, h, hlen, u, n, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_mullow(v, t, n, u, hlen - 1, n, prec); _acb_vec_neg(t, h, hlen); _acb_poly_exp_series(t, t, hlen, n, prec); _acb_poly_mullow(g, v, n, t, n, n, prec); _acb_poly_integral(g, g, n, prec); _acb_vec_neg(g, g, n); if (regularized == 1) { acb_rgamma(t, s, prec); _acb_vec_scalar_mul(g, g, n, t, prec); } else if (regularized == 2) { _acb_vec_set(u, g, n); _acb_poly_mullow(g, u, n, w, n, n, prec); _acb_vec_clear(w, n); } _acb_vec_clear(t, n); _acb_vec_clear(u, n); _acb_vec_clear(v, n); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_gamma_upper_series(acb_poly_t g, const acb_t s, const acb_poly_t h, int regularized, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, n); if (hlen == 0) { acb_t t; acb_init(t); _acb_hypgeom_gamma_upper_series(g->coeffs, s, t, 1, regularized, n, prec); acb_clear(t); } else { _acb_hypgeom_gamma_upper_series( g->coeffs, s, h->coeffs, hlen, regularized, n, prec); } _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/gegenbauer_c.c000066400000000000000000000051001461254215100204450ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* this can be improved */ static int use_recurrence(const acb_t n, const acb_t m, slong prec) { if (!acb_is_int(n) || !arb_is_nonnegative(acb_realref(n))) return 0; if (arf_cmpabs_ui(arb_midref(acb_realref(n)), prec) > 0) return 0; if (arb_is_nonnegative(acb_realref(m))) return 0; return 1; } void acb_hypgeom_gegenbauer_c_ui_recurrence(acb_t res, ulong n, const acb_t m, const acb_t z, slong prec) { acb_t t, u, v; ulong k; if (n == 0) { acb_one(res); return; } if (n == 1) { acb_mul(res, m, z, prec); acb_mul_2exp_si(res, res, 1); return; } acb_init(t); acb_init(u); acb_init(v); acb_one(t); acb_mul(u, m, z, prec); acb_mul_2exp_si(u, u, 1); for (k = 2; k <= n; k++) { acb_mul_2exp_si(v, m, 1); acb_add_ui(v, v, k - 2, prec); acb_mul(t, t, v, prec); acb_add_ui(v, m, k - 1, prec); acb_mul(v, v, z, prec); acb_mul_2exp_si(v, v, 1); acb_mul(v, v, u, prec); acb_sub(t, v, t, prec); acb_div_ui(t, t, k, prec); acb_swap(t, u); } acb_set(res, u); acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_gegenbauer_c(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) { acb_t a, b, c, t; if (use_recurrence(n, m, prec)) { acb_hypgeom_gegenbauer_c_ui_recurrence(res, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), m, z, prec); return; } acb_init(a); acb_init(b); acb_init(c); acb_init(t); acb_neg(a, n); acb_mul_2exp_si(b, m, 1); acb_add(b, b, n, prec); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_add(c, c, m, prec); acb_sub_ui(t, z, 1, prec); acb_mul_2exp_si(t, t, -1); acb_neg(t, t); acb_hypgeom_2f1(t, a, b, c, t, 0, prec); acb_mul_2exp_si(b, m, 1); acb_rising(b, b, n, prec); acb_mul(t, t, b, prec); acb_add_ui(b, n, 1, prec); acb_rgamma(b, b, prec); acb_mul(t, t, b, prec); acb_set(res, t); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(t); } flint-3.1.3/src/acb_hypgeom/hermite_h.c000066400000000000000000000061221461254215100200100ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_hermite_h_ui_recurrence(acb_t res, ulong n, const acb_t z, slong prec) { acb_t t, u, v; ulong k; if (n == 0) { acb_one(res); return; } if (n == 1) { acb_set_round(res, z, prec); acb_mul_2exp_si(res, res, 1); return; } acb_init(t); acb_init(u); acb_init(v); acb_one(t); acb_mul_2exp_si(u, z, 1); for (k = 2; k <= n; k++) { acb_mul(v, u, z, prec); acb_submul_ui(v, t, k - 1, prec); acb_mul_2exp_si(v, v, 1); acb_swap(t, u); acb_swap(u, v); } acb_set(res, u); acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_hermite_h(acb_t res, const acb_t n, const acb_t z, slong prec) { acb_t a, b, c, t, u, v; int use_asymp; if (acb_is_int(n) && arb_is_nonnegative(acb_realref(n)) && (arf_cmpabs_ui(arb_midref(acb_realref(n)), 30) < 0)) { acb_hypgeom_hermite_h_ui_recurrence(res, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), z, prec); return; } acb_init(a); acb_init(b); acb_init(c); acb_init(t); acb_init(u); acb_init(v); acb_mul(t, z, z, prec); use_asymp = arb_is_positive(acb_realref(z)) && acb_hypgeom_u_use_asymp(t, prec); if (use_asymp) { acb_mul_2exp_si(a, n, -1); acb_neg(a, a); acb_one(b); acb_mul_2exp_si(b, b, -1); acb_hypgeom_u_asymp(u, a, b, t, -1, prec); acb_mul_2exp_si(t, z, 1); acb_pow(t, t, n, prec); acb_mul(u, u, t, prec); acb_set(res, u); } else { /* a = (1-n)/2 */ acb_sub_ui(a, n, 1, prec); acb_neg(a, a); acb_mul_2exp_si(a, a, -1); /* c = -n/2 */ acb_mul_2exp_si(c, n, -1); acb_neg(c, c); acb_rgamma(u, a, prec); if (!acb_is_zero(u)) { acb_one(b); acb_mul_2exp_si(b, b, -1); acb_hypgeom_m(v, c, b, t, 0, prec); acb_mul(u, u, v, prec); } acb_rgamma(v, c, prec); if (!acb_is_zero(v)) { acb_set_ui(b, 3); acb_mul_2exp_si(b, b, -1); acb_hypgeom_m(t, a, b, t, 0, prec); acb_mul_2exp_si(t, t, 1); acb_mul(t, t, z, prec); acb_submul(u, v, t, prec); } acb_set_ui(t, 2); acb_pow(t, t, n, prec); acb_mul(u, u, t, prec); arb_const_sqrt_pi(acb_realref(t), prec); acb_mul_arb(u, u, acb_realref(t), prec); acb_set(res, u); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(t); acb_clear(u); acb_clear(v); } flint-3.1.3/src/acb_hypgeom/jacobi_p.c000066400000000000000000000052501461254215100176130ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* this can be improved */ static int use_recurrence(const acb_t n, const acb_t a, const acb_t b, slong prec) { if (!acb_is_int(n) || !arb_is_nonnegative(acb_realref(n))) return 0; if (arf_cmpabs_ui(arb_midref(acb_realref(n)), prec) > 0) return 0; if (arb_is_nonnegative(acb_realref(a)) || arf_get_d(arb_midref(acb_realref(a)), ARF_RND_DOWN) > -0.9) return 0; return 1; } void acb_hypgeom_jacobi_p_ui_direct(acb_t res, ulong n, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_ptr terms; acb_t t, u, v; slong k; terms = _acb_vec_init(n + 1); acb_init(t); acb_init(u); acb_init(v); acb_one(terms); acb_add_ui(u, z, 1, prec); for (k = 1; k <= n; k++) { acb_add_ui(t, a, n + 1 - k, prec); acb_mul(t, t, u, prec); acb_div_ui(t, t, 2 * k, prec); acb_mul(terms + k, terms + k - 1, t, prec); } acb_sub_ui(u, z, 1, prec); acb_one(v); for (k = 1; k <= n; k++) { acb_add_ui(t, b, n + 1 - k, prec); acb_mul(t, t, u, prec); acb_div_ui(t, t, 2 * k, prec); acb_mul(v, v, t, prec); acb_mul(terms + n - k, terms + n - k, v, prec); } acb_set(res, terms); for (k = 1; k <= n; k++) acb_add(res, res, terms + k, prec); _acb_vec_clear(terms, n + 1); acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_jacobi_p(acb_t res, const acb_t n, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_t t, u, v, w; if (use_recurrence(n, a, b, prec)) { acb_hypgeom_jacobi_p_ui_direct(res, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), a, b, z, prec); return; } acb_init(t); acb_init(u); acb_init(v); acb_init(w); acb_neg(t, n); acb_add_ui(v, a, 1, prec); acb_add(u, n, v, prec); acb_add(u, u, b, prec); acb_sub_ui(w, z, 1, prec); acb_mul_2exp_si(w, w, -1); acb_neg(w, w); acb_hypgeom_2f1(w, t, u, v, w, 0, prec); acb_rising(t, v, n, prec); acb_mul(w, w, t, prec); acb_add_ui(t, n, 1, prec); acb_rgamma(t, t, prec); acb_mul(w, w, t, prec); acb_set(res, w); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); } flint-3.1.3/src/acb_hypgeom/laguerre_l.c000066400000000000000000000046331461254215100201720ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* this can be improved */ static int use_recurrence(const acb_t n, const acb_t m, slong prec) { if (!acb_is_int(n) || !arb_is_nonnegative(acb_realref(n))) return 0; if (arf_cmpabs_ui(arb_midref(acb_realref(n)), prec) > 0) return 0; if (arf_cmpabs(arb_midref(acb_realref(n)), arb_midref(acb_realref(m))) >= 0) return 0; return 1; } void acb_hypgeom_laguerre_l_ui_recurrence(acb_t res, ulong n, const acb_t m, const acb_t z, slong prec) { acb_t t, u, v; ulong k; if (n == 0) { acb_one(res); return; } if (n == 1) { acb_sub(res, m, z, prec); acb_add_ui(res, res, 1, prec); return; } acb_init(t); acb_init(u); acb_init(v); acb_one(t); acb_sub(u, m, z, prec); acb_add_ui(u, u, 1, prec); for (k = 2; k <= n; k++) { acb_add_ui(v, m, k - 1, prec); acb_mul(t, t, v, prec); acb_add_ui(v, m, 2 * k - 1, prec); acb_sub(v, v, z, prec); acb_mul(v, v, u, prec); acb_sub(t, v, t, prec); acb_div_ui(t, t, k, prec); acb_swap(t, u); } acb_set(res, u); acb_clear(t); acb_clear(u); acb_clear(v); } void acb_hypgeom_laguerre_l(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) { acb_t t, u, v; if (use_recurrence(n, m, prec)) { acb_hypgeom_laguerre_l_ui_recurrence(res, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), m, z, prec); return; } /* todo: should be a test of whether n contains any negative integer */ if (acb_contains_int(n) && !arb_is_nonnegative(acb_realref(n))) { acb_indeterminate(res); return; } acb_init(t); acb_init(u); acb_init(v); acb_neg(t, n); acb_add_ui(u, m, 1, prec); acb_hypgeom_m(t, t, u, z, 1, prec); acb_add_ui(u, n, 1, prec); acb_rising(u, u, m, prec); acb_mul(res, t, u, prec); acb_clear(t); acb_clear(u); acb_clear(v); } flint-3.1.3/src/acb_hypgeom/legendre_p.c000066400000000000000000000075011461254215100201520ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #include "arb_hypgeom.h" void acb_hypgeom_legendre_p(acb_t res, const acb_t n, const acb_t m, const acb_t z, int type, slong prec) { acb_t a, b, c, w; int flag; if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_is_real(z) && acb_is_zero(m) && acb_is_int(n) && arf_sgn(arb_midref(acb_realref(n))) >= 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(n)), FLINT_BITS - 1) < 0) { arb_hypgeom_legendre_p_ui(acb_realref(res), NULL, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), acb_realref(z), prec); arb_zero(acb_imagref(res)); return; } if (acb_is_int(n) && acb_is_int(m) && arb_is_nonnegative(acb_realref(n)) && arb_is_nonnegative(acb_realref(m)) && type == 0) { arf_srcptr nn = arb_midref(acb_realref(n)); arf_srcptr mm = arb_midref(acb_realref(m)); if (arf_cmpabs(mm, nn) > 0) { acb_zero(res); return; } if (arf_cmpabs_2exp_si(nn, FLINT_BITS - 1) < 0 && arf_cmpabs_2exp_si(mm, FLINT_BITS - 1) < 0) { slong nnn, mmm; nnn = arf_get_si(nn, ARF_RND_DOWN); mmm = arf_get_si(mm, ARF_RND_DOWN); /* we will probably lose all accuracy... */ if (nnn - mmm > 2 * prec) { acb_indeterminate(res); } /* hypergeometric series is faster at high precision, but avoid at 1 */ else if (prec < 500 + nnn * 10.0 || (nnn - mmm) < 10 || (arb_contains_si(acb_realref(z), 1) && arb_contains_zero(acb_imagref(z)))) { if (mmm == 0) { acb_hypgeom_legendre_p_uiui_rec(res, nnn, mmm, z, prec); } else { acb_init(a); acb_init(b); acb_mul(a, z, z, prec); acb_sub_ui(a, a, 1, prec); acb_neg(a, a); acb_mul_2exp_si(b, m, -1); acb_pow(a, a, b, prec); acb_hypgeom_legendre_p_uiui_rec(res, nnn, mmm, z, prec); acb_mul(res, res, a, prec); acb_clear(a); acb_clear(b); } return; } } } acb_init(a); acb_init(b); acb_init(c); acb_init(w); acb_neg(a, n); acb_add_ui(b, n, 1, prec); acb_sub_ui(c, m, 1, prec); acb_neg(c, c); acb_sub_ui(w, z, 1, prec); acb_neg(w, w); acb_mul_2exp_si(w, w, -1); /* a + b - c (which could be inexact) is integer iff c is integer */ flag = 1; if (acb_is_int(c)) { flag |= ACB_HYPGEOM_2F1_ABC; } acb_hypgeom_2f1(w, a, b, c, w, flag, prec); if (!acb_is_zero(m)) { acb_add_ui(a, z, 1, prec); acb_sub_ui(b, z, 1, prec); if (type == 0) { acb_neg(b, b); } else if (type != 1) { flint_throw(FLINT_ERROR, "unsupported 'type' %d for legendre p\n", type); } acb_mul_2exp_si(c, m, -1); acb_pow(a, a, c, prec); acb_neg(c, c); acb_pow(b, b, c, prec); acb_mul(w, w, a, prec); acb_mul(w, w, b, prec); } acb_set(res, w); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(w); } flint-3.1.3/src/acb_hypgeom/legendre_p_uiui_rec.c000066400000000000000000000031701461254215100220340ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_legendre_p_uiui_rec(acb_t res, ulong n, ulong m, const acb_t z, slong prec) { acb_t t, u, v; slong k; if (!acb_is_finite(z)) { acb_indeterminate(res); return; } if (m > n) { acb_zero(res); return; } if ((n - m) / 4 > prec) { acb_indeterminate(res); return; } acb_init(t); acb_init(u); acb_init(v); /* t = p(m,m) = (-1)^m (2m-1)!! */ if (m == 0) arb_one(acb_realref(t)); else arb_doublefac_ui(acb_realref(t), 2 * m - 1, prec); if (m % 2) arb_neg(acb_realref(t), acb_realref(t)); if (n > m) { /* t = p(m+1,m) = z(2m+1)p(m,m), u = p(m,m) */ acb_mul_ui(u, t, 2 * m + 1, prec); acb_mul(u, u, z, prec); acb_swap(t, u); for (k = m + 2; k <= n; k++) { /* t, u = ((2*k-1)*z*t - (k+m-1)*u) / (k-m), t */ acb_mul(v, t, z, prec); acb_mul_ui(v, v, 2 * k - 1, prec); acb_submul_ui(v, u, k + m - 1, prec); acb_div_ui(u, v, k - m, prec); acb_swap(t, u); } } acb_set(res, t); acb_clear(t); acb_clear(u); acb_clear(v); } flint-3.1.3/src/acb_hypgeom/legendre_q.c000066400000000000000000000170511461254215100201540ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* invalid in (-1,0) */ int _acb_hypgeom_legendre_q_single_valid(const acb_t z) { arb_t t; int ok; if (!arb_contains_zero(acb_imagref(z))) return 1; if (arb_is_positive(acb_imagref(z))) return 1; arb_init(t); arb_one(t); arb_neg(t, t); ok = arb_lt(acb_realref(z), t); arb_clear(t); return ok; } void _acb_hypgeom_legendre_q_double(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); if (acb_is_int(m)) { acb_sub_ui(t, z, 1, prec); acb_mul_2exp_si(u, m, -1); acb_pow(v, t, u, prec); acb_neg(t, t); acb_neg(u, u); acb_pow(t, t, u, prec); acb_mul(t, t, v, prec); acb_hypgeom_legendre_q(u, n, m, z, 0, prec); acb_mul(t, t, u, prec); acb_mul_2exp_si(u, m, -1); if (!acb_is_int(u)) acb_neg(t, t); acb_sub_ui(u, z, 1, prec); acb_sqrt(u, u, prec); acb_sub_ui(v, z, 1, prec); acb_neg(v, v); acb_rsqrt(v, v, prec); acb_mul(u, u, v, prec); acb_hypgeom_legendre_p(v, n, m, z, 1, prec); acb_mul(u, u, v, prec); acb_const_pi(v, prec); acb_mul(u, u, v, prec); acb_mul_2exp_si(u, u, -1); acb_sub(res, t, u, prec); } else { acb_sub(t, n, m, prec); acb_add_ui(t, t, 1, prec); acb_mul_2exp_si(u, m, 1); acb_rising(t, t, u, prec); acb_neg(u, m); acb_hypgeom_legendre_p(u, n, u, z, 1, prec); acb_mul(t, t, u, prec); acb_hypgeom_legendre_p(u, n, m, z, 1, prec); acb_sub(t, u, t, prec); acb_exp_pi_i(u, m, prec); acb_mul(t, t, u, prec); acb_sin_pi(u, m, prec); acb_div(t, t, u, prec); acb_const_pi(u, prec); acb_mul(t, t, u, prec); acb_mul_2exp_si(t, t, -1); acb_set(res, t); } acb_clear(t); acb_clear(u); acb_clear(v); } void _acb_hypgeom_legendre_q_single(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) { acb_t a, b, c, z2, t, u; acb_init(a); acb_init(b); acb_init(c); acb_init(z2); acb_init(t); acb_init(u); /* invalid in (-1,0) */ if (!_acb_hypgeom_legendre_q_single_valid(z)) { acb_indeterminate(res); return; } acb_pow_si(z2, z, -2, prec); /* z2 = 1/z^2 */ /* t = 2F1r((m+n+1)/2, (m+n)/2+1, n+3/2, 1/z^2) */ acb_add(b, m, n, prec); acb_add_ui(a, b, 1, prec); acb_mul_2exp_si(a, a, -1); acb_mul_2exp_si(b, b, -1); acb_add_ui(b, b, 1, prec); acb_set_ui(c, 3); acb_mul_2exp_si(c, c, -1); acb_add(c, c, n, prec); acb_hypgeom_2f1(t, a, b, c, z2, 1, prec); /* prefactor sqrt(pi) 2^-n (z+1)^(m/2) (z-1)^(m/2) exp(i pi m) */ /* (1/2) gamma(m+n+1) z^(-m-n-1) */ if (!acb_is_zero(m)) { acb_add_ui(z2, z, 1, prec); acb_mul_2exp_si(c, m, -1); acb_pow(z2, z2, c, prec); acb_mul(t, t, z2, prec); acb_sub_ui(z2, z, 1, prec); acb_mul_2exp_si(c, m, -1); acb_pow(z2, z2, c, prec); acb_mul(t, t, z2, prec); acb_exp_pi_i(z2, m, prec); acb_mul(t, t, z2, prec); } acb_set_ui(z2, 2); acb_neg(c, n); acb_pow(z2, z2, c, prec); acb_mul(t, t, z2, prec); acb_add(c, m, n, prec); acb_add_ui(c, c, 1, prec); acb_gamma(z2, c, prec); acb_mul(t, t, z2, prec); acb_neg(c, c); acb_pow(z2, z, c, prec); acb_mul(t, t, z2, prec); acb_mul_2exp_si(t, t, -1); arb_const_sqrt_pi(acb_realref(u), prec); acb_mul_arb(t, t, acb_realref(u), prec); acb_set(res, t); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z2); acb_clear(t); acb_clear(u); } void acb_hypgeom_legendre_q(acb_t res, const acb_t n, const acb_t m, const acb_t z, int type, slong prec) { if (type == 0) { /* http://functions.wolfram.com/07.11.26.0033.01 */ /* todo: simplify the gamma quotients and the sqrt pi factor... */ acb_t a, b, c, z2, mn, nm, t, u; acb_init(a); acb_init(b); acb_init(c); acb_init(z2); acb_init(mn); acb_init(nm); acb_init(t); acb_init(u); acb_add(mn, m, n, prec); /* mn = m + n */ acb_sub(nm, n, m, prec); /* nm = n - m */ acb_mul(z2, z, z, prec); /* z2 = z^2 */ /* t = 2F1((1-m-n)/2, (n-m)/2+1, 3/2, z^2) */ acb_sub_ui(a, mn, 1, prec); acb_neg(a, a); acb_mul_2exp_si(a, a, -1); acb_mul_2exp_si(b, nm, -1); acb_add_ui(b, b, 1, prec); acb_set_ui(c, 3); acb_mul_2exp_si(c, c, -1); acb_hypgeom_2f1(t, a, b, c, z2, 0, prec); /* u = 2F1(-(m+n)/2, (n-m+1)/2, 1/2, z^2) */ acb_neg(a, mn); acb_mul_2exp_si(a, a, -1); acb_add_ui(b, nm, 1, prec); acb_mul_2exp_si(b, b, -1); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_hypgeom_2f1(u, a, b, c, z2, 0, prec); /* a = cospi((m+n)/2) gamma((m+n)/2+1) rgamma((n-m+1)/2) z */ /* b = sinpi((m+n)/2) gamma((m+n+1)/2) rgamma((n-m)/2+1) / 2 */ acb_mul_2exp_si(a, mn, -1); acb_sin_cos_pi(b, a, a, prec); acb_mul_2exp_si(c, mn, -1); acb_add_ui(c, c, 1, prec); acb_gamma(c, c, prec); acb_mul(a, a, c, prec); acb_add_ui(c, nm, 1, prec); acb_mul_2exp_si(c, c, -1); acb_rgamma(c, c, prec); acb_mul(a, a, c, prec); acb_mul(a, a, z, prec); acb_add_ui(c, mn, 1, prec); acb_mul_2exp_si(c, c, -1); acb_gamma(c, c, prec); acb_mul(b, b, c, prec); acb_mul_2exp_si(c, nm, -1); acb_add_ui(c, c, 1, prec); acb_rgamma(c, c, prec); acb_mul(b, b, c, prec); acb_mul_2exp_si(b, b, -1); /* at - bu */ acb_mul(t, t, a, prec); acb_mul(u, u, b, prec); acb_sub(t, t, u, prec); /* prefactor sqrt(pi) 2^m (1-z^2)^(-m/2) */ if (!acb_is_zero(m)) { acb_sub_ui(u, z2, 1, prec); acb_neg(u, u); acb_neg(c, m); acb_mul_2exp_si(c, c, -1); acb_pow(u, u, c, prec); acb_set_ui(c, 2); acb_pow(c, c, m, prec); acb_mul(u, u, c, prec); acb_mul(t, t, u, prec); } arb_const_sqrt_pi(acb_realref(u), prec); acb_mul_arb(t, t, acb_realref(u), prec); acb_set(res, t); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z2); acb_clear(mn); acb_clear(nm); acb_clear(t); acb_clear(u); } else if (type == 1) { if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -2) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -2) < 0) || !_acb_hypgeom_legendre_q_single_valid(z)) { _acb_hypgeom_legendre_q_double(res, n, m, z, prec); } else { _acb_hypgeom_legendre_q_single(res, n, m, z, prec); } } else { flint_throw(FLINT_ERROR, "unsupported 'type' %d for legendre q\n", type); } } flint-3.1.3/src/acb_hypgeom/lgamma.c000066400000000000000000000144771461254215100173160ustar00rootroot00000000000000/* Copyright (C) 2014, 2015, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define floor __builtin_floor #else # include #endif void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t z, int use_reflect, int digamma, slong prec); void acb_hypgeom_gamma_stirling_inner(acb_t s, const acb_t z, slong N, slong prec); static double want_taylor(double x, double y, slong prec) { if (y < 0.0) y = -y; if (x < 0.0) x = -2.0 * x; if ((prec < 128 && y > 4.0) || (prec < 256 && y > 5.0) || (prec < 512 && y > 8.0) || (prec < 1024 && y > 9.0) || y > 10.0) { return 0; } if (x * (1.0 + 0.75 * y) > 8 + 0.15 * prec) { return 0; } return 1; } /* Linear fit on [0.5, 1.5] for lambda x: findroot(lambda y: im(loggamma(x+1j*y)) - (n+0.5)*pi */ static const double Atab[] = { 4.5835631239879990091, 6.4037921417161376741, 7.9938623618272375768, 9.4449131928216797873, 10.802608819487725856, 12.0918817314347272, }; static const double Btab[] = { -1.1432582881376479127, -0.86248117216701645437, -0.75778990135448922722, -0.69734688055939976228, -0.65626499937495627271, -0.62578331900739100617, }; void _arb_const_log_pi(arb_t t, slong prec) { arb_const_pi(t, prec + 2); arb_log(t, t, prec); } ARB_DEF_CACHED_CONSTANT(arb_const_log_pi, _arb_const_log_pi) int acb_hypgeom_lgamma_taylor(acb_t res, const acb_t z, slong prec) { double x, y, acc; slong k, r, wp; acb_t t, u; int reflect; /* Assume xerr, yerr <= 1/16 */ if (mag_cmp_2exp_si(arb_radref(acb_realref(z)), -4) > 0) return 0; if (mag_cmp_2exp_si(arb_radref(acb_imagref(z)), -4) > 0) return 0; acc = acb_rel_accuracy_bits(z); acc = FLINT_MAX(acc, 0); wp = FLINT_MIN(prec, acc + 20); wp = FLINT_MAX(wp, 2); /* x, y plus eventual rounding error */ x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_NEAR); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_NEAR); if (!want_taylor(x, y, wp)) return 0; acb_init(t); acb_init(u); /* Reduce real part to (approximately) [0.5, 1.5]. */ r = floor(x - 0.5); /* Reflection formula is slower but improves accuracy. */ reflect = (x < -3.0); if (reflect) { acb_neg(u, z); acb_add_si(u, u, 2 + r, 2 * prec + 10); x = 2.0 + r - x; y = -y; } else { acb_sub_si(u, z, r, 2 * prec + 10); x = x - r; } for (k = 0; k < 6; k++) { if (fabs(y) <= Atab[k] + Btab[k] * x) { if (!acb_hypgeom_gamma_taylor(t, u, 1, wp)) { acb_clear(t); acb_clear(u); return 0; } if (k % 2 == 0) { acb_log(t, t, wp); acb_neg(t, t); } else { acb_neg(t, t); acb_log(t, t, wp); acb_neg(t, t); } if (k != 0) { arb_t pi; arb_init(pi); arb_const_pi(pi, wp); arb_addmul_si(acb_imagref(t), pi, (y > 0) ? k : -k, wp); arb_clear(pi); } if (reflect) { acb_t v; acb_init(v); /* loggamma(x) = log(pi) - lsin(x) - loggamma(2+r-x) - logrf(2+r-x, -r-1) */ acb_hypgeom_log_rising_ui(v, u, -r-1, wp); acb_log_sin_pi(res, z, wp); acb_add(res, res, v, wp); acb_add(res, res, t, wp); acb_neg(res, res); arb_const_log_pi(acb_realref(t), wp); arb_zero(acb_imagref(t)); acb_add(res, res, t, prec); acb_clear(v); } else if (r == 0) { acb_set_round(res, t, prec); } else if (r > 0) { acb_hypgeom_log_rising_ui(res, u, r, wp); acb_add(res, res, t, prec); } else { acb_hypgeom_log_rising_ui(res, z, -r, wp); acb_sub(res, t, res, prec); } acb_clear(t); acb_clear(u); return 1; } } acb_clear(t); acb_clear(u); return 0; } void acb_hypgeom_lgamma(acb_t y, const acb_t x, slong prec) { int reflect; slong r, n, wp; acb_t t, u, v; double acc; if (acb_is_real(x) && arb_is_positive(acb_realref(x))) { arb_hypgeom_lgamma(acb_realref(y), acb_realref(x), prec); arb_zero(acb_imagref(y)); return; } if (acb_hypgeom_lgamma_taylor(y, x, prec)) return; acc = acb_rel_accuracy_bits(x); acc = FLINT_MAX(acc, 0); wp = FLINT_MIN(prec, acc + 20); wp = FLINT_MAX(wp, 2); wp = wp + FLINT_BIT_COUNT(wp); acb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 0, wp); acb_init(t); acb_init(u); acb_init(v); if (reflect) { /* log gamma(x) = log rf(1-x, r) - log gamma(1-x+r) - log sin(pi x) + log(pi) */ acb_sub_ui(u, x, 1, wp); acb_neg(u, u); acb_hypgeom_log_rising_ui(t, u, r, wp); acb_add_ui(u, u, r, wp); acb_hypgeom_gamma_stirling_inner(v, u, n, wp); acb_sub(t, t, v, wp); acb_log_sin_pi(u, x, wp); acb_sub(t, t, u, wp); arb_const_log_pi(acb_realref(u), wp); arb_zero(acb_imagref(u)); acb_add(y, t, u, wp); } else { /* log gamma(x) = log gamma(x+r) - log rf(x,r) */ acb_add_ui(t, x, r, wp); acb_hypgeom_gamma_stirling_inner(u, t, n, wp); acb_hypgeom_log_rising_ui(t, x, r, wp); acb_sub(y, u, t, prec); } if (!acb_is_finite(y)) acb_indeterminate(y); acb_clear(t); acb_clear(u); acb_clear(v); } flint-3.1.3/src/acb_hypgeom/li.c000066400000000000000000000027561461254215100164610ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" static void _acb_hypgeom_li(acb_t res, const acb_t z, slong prec) { if (acb_is_zero(z)) { acb_zero(res); } else { acb_log(res, z, prec); acb_hypgeom_ei(res, res, prec); } } void _acb_hypgeom_const_li2_eval(arb_t s, slong prec) { acb_t t; acb_init(t); acb_set_ui(t, 2); _acb_hypgeom_li(t, t, prec); arb_set(s, acb_realref(t)); acb_clear(t); } ARB_DEF_CACHED_CONSTANT(_acb_hypgeom_const_li2, _acb_hypgeom_const_li2_eval) static void _acb_hypgeom_li_offset(acb_t res, const acb_t z, slong prec) { if (acb_is_int(z) && arf_cmp_2exp_si(arb_midref(acb_realref(z)), 1) == 0) { acb_zero(res); } else { arb_t t; arb_init(t); _acb_hypgeom_const_li2(t, prec); _acb_hypgeom_li(res, z, prec); arb_sub(acb_realref(res), acb_realref(res), t, prec); arb_clear(t); } } void acb_hypgeom_li(acb_t res, const acb_t z, int offset, slong prec) { if (offset) _acb_hypgeom_li_offset(res, z, prec); else _acb_hypgeom_li(res, z, prec); } flint-3.1.3/src/acb_hypgeom/li_series.c000066400000000000000000000035201461254215100200210ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_li_series(acb_ptr g, acb_srcptr h, slong hlen, int offset, slong len, slong prec) { acb_t c; if (acb_contains_zero(h)) { _acb_vec_indeterminate(g, len); return; } acb_init(c); acb_hypgeom_li(c, h, offset, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else if (len == 2) { acb_log(g, h, prec); acb_div(g + 1, h + 1, g, prec); } else { acb_ptr t, u; t = _acb_vec_init(len); u = _acb_vec_init(hlen); /* li(h(x)) = integral(h'(x) / log(h(x))) */ _acb_poly_log_series(t, h, hlen, len - 1, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_div_series(g, u, hlen - 1, t, len - 1, len - 1, prec); _acb_poly_integral(g, g, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, hlen); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_li_series(acb_poly_t g, const acb_poly_t h, int offset, slong len, slong prec) { slong hlen = h->length; if (len == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_inv_series(g, h, len, prec); return; } acb_poly_fit_length(g, len); _acb_hypgeom_li_series(g->coeffs, h->coeffs, hlen, offset, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/log_rising_ui_jet.c000066400000000000000000000146551461254215100215510ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif static void _acb_log_rising_correct_branch(acb_t res, const acb_t t_wrong, const acb_t z, ulong r, slong prec) { acb_t f; arb_t pi, u, v; fmpz_t pi_mult; slong i, argprec; acb_init(f); arb_init(u); arb_init(pi); arb_init(v); fmpz_init(pi_mult); argprec = FLINT_MIN(prec, 40); arb_zero(u); for (i = 0; i < r; i++) { acb_add_ui(f, z, i, argprec); acb_arg(v, f, argprec); arb_add(u, u, v, argprec); } if (argprec == prec) { arb_set(acb_imagref(res), u); } else { arb_sub(v, u, acb_imagref(t_wrong), argprec); arb_const_pi(pi, argprec); arb_div(v, v, pi, argprec); if (arb_get_unique_fmpz(pi_mult, v)) { arb_const_pi(v, prec); arb_mul_fmpz(v, v, pi_mult, prec); arb_add(acb_imagref(res), acb_imagref(t_wrong), v, prec); } else { arb_zero(u); for (i = 0; i < r; i++) { acb_add_ui(f, z, i, prec); acb_arg(v, f, prec); arb_add(u, u, v, prec); } arb_set(acb_imagref(res), u); } } arb_set(acb_realref(res), acb_realref(t_wrong)); acb_clear(f); arb_clear(u); arb_clear(v); arb_clear(pi); fmpz_clear(pi_mult); } void acb_hypgeom_log_rising_ui_jet_fallback(acb_ptr res, const acb_t z, slong r, slong len, slong prec) { acb_t t; acb_init(t); acb_set(t, z); if (len == 1) { acb_hypgeom_rising_ui_rec(res, t, r, prec); acb_log(res, res, prec); } else { acb_hypgeom_rising_ui_jet(res, t, r, len, prec); _acb_poly_log_series(res, res, FLINT_MIN(len, r + 1), len, prec); } _acb_log_rising_correct_branch(res, res, t, r, prec); acb_clear(t); } void acb_hypgeom_log_rising_ui_jet(acb_ptr res, const acb_t z, ulong r, slong len, slong prec) { double za, zb, sa, sb, ta, tb, ma, mb, zak; slong k, correction; int neg; if (r == 0 || len == 0) { _acb_vec_zero(res, len); return; } if (r == 1) { if (len == 1) { acb_log(res, z, prec); } else { acb_set(res, z); acb_one(res + 1); _acb_poly_log_series(res, res, 2, len, prec); } return; } if (arb_is_zero(acb_imagref(z))) { if (arb_is_positive(acb_realref(z))) { acb_hypgeom_rising_ui_jet(res, z, r, len, prec); _acb_poly_log_series(res, res, FLINT_MIN(len, r + 1), len, prec); } else if (arb_contains_int(acb_realref(z))) { _acb_vec_indeterminate(res, len); } else { arb_t t, u; arb_init(t); arb_init(u); arb_floor(u, acb_realref(z), prec); arb_neg(u, u); arb_set_ui(t, r); arb_min(u, u, t, prec); arb_const_pi(t, prec); arb_mul(t, u, t, prec); acb_hypgeom_rising_ui_jet(res, z, r, len, prec); _acb_vec_neg(res, res, FLINT_MIN(len, r + 1)); _acb_poly_log_series(res, res, FLINT_MIN(len, r + 1), len, prec); arb_swap(acb_imagref(res), t); arb_clear(t); arb_clear(u); } return; } /* We use doubles if it is safe. - No overflow/underflow possible. - Input is accurate enough (and not too close to the real line). Note: the relative error for a complex floating-point multiplication is bounded by sqrt(5) * eps, and we basically only need to determine the result to within one quadrant. */ /* todo: wide */ if (prec <= 20 || acb_rel_accuracy_bits(z) < 30 || arb_rel_accuracy_bits(acb_imagref(z)) < 30) { acb_hypgeom_log_rising_ui_jet_fallback(res, z, r, len, prec); return; } za = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_NEAR); zb = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_NEAR); if (!(r <= 1e6 && za <= 1e6 && za >= -1e6 && zb <= 1e6 && zb >= -1e6 && (zb > 1e-6 || zb < -1e-6))) { acb_hypgeom_log_rising_ui_jet_fallback(res, z, r, len, prec); return; } sa = za; sb = zb; correction = 0; neg = 0; for (k = 1; k < r; k++) { zak = za + k; ta = sa * zak - sb * zb; tb = sb * zak + sa * zb; if (zb > 0.0) { if (sb >= 0.0 && tb < 0.0) correction += 2; } else { if (sb < 0.0 && tb >= 0.0) correction += 2; } sa = ta; sb = tb; if (k % 4 == 0) { ma = fabs(sa); mb = fabs(sb); /* Rescale to protect against overflow. */ if (ma > mb) ma = 1.0 / ma; else ma = 1.0 / mb; sa *= ma; sb *= ma; } } if (sa < 0.0) { neg = 1; if ((zb > 0.0 && sb >= 0.0) || (zb < 0.0 && sb < 0.0)) correction += 1; else correction -= 1; } if (len == 1) { acb_hypgeom_rising_ui_rec(res, z, r, prec); if (neg) acb_neg(res, res); acb_log(res, res, prec); } else { acb_hypgeom_rising_ui_jet(res, z, r, len, prec); if (neg) _acb_vec_neg(res, res, FLINT_MIN(len, r + 1)); _acb_poly_log_series(res, res, FLINT_MIN(len, r + 1), len, prec); } if (zb < 0.0) correction = -correction; if (correction != 0) { arb_t t; arb_init(t); arb_const_pi(t, prec); arb_addmul_si(acb_imagref(res), t, correction, prec); arb_clear(t); } } void acb_hypgeom_log_rising_ui(acb_ptr res, const acb_t z, ulong r, slong prec) { acb_hypgeom_log_rising_ui_jet(res, z, r, 1, prec); } flint-3.1.3/src/acb_hypgeom/m.c000066400000000000000000000224121461254215100163000ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define sqrt __builtin_sqrt #else # include #endif void acb_hypgeom_m_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { acb_t t, u, v, c; acb_init(t); acb_init(u); acb_init(v); acb_init(c); acb_sub(c, b, a, prec); acb_neg(v, z); acb_hypgeom_u_asymp(t, a, b, z, -1, prec); acb_hypgeom_u_asymp(u, c, b, v, -1, prec); /* gamma(b-a) */ acb_rgamma(v, c, prec); acb_mul(t, t, v, prec); /* z^(a-b) */ acb_neg(c, c); acb_pow(v, z, c, prec); acb_mul(u, u, v, prec); /* gamma(a) */ acb_rgamma(v, a, prec); acb_mul(u, u, v, prec); /* exp(z) */ acb_exp(v, z, prec); acb_mul(u, u, v, prec); /* (-z)^(-a) */ acb_neg(c, a); acb_neg(v, z); acb_pow(v, v, c, prec); acb_mul(t, t, v, prec); acb_add(t, t, u, prec); if (!regularized) { acb_gamma(v, b, prec); if (acb_is_finite(v)) acb_mul(t, t, v, prec); else acb_indeterminate(t); } if (acb_is_real(a) && acb_is_real(b) && acb_is_real(z)) { arb_zero(acb_imagref(t)); } acb_swap(res, t); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(c); } void _acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec, slong gamma_prec, int kummer) { if (regularized) { /* Remove singularity */ if (acb_is_int(b) && arb_is_nonpositive(acb_realref(b)) && arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0) { acb_t c, d, t, u; slong n; n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN); acb_init(c); acb_init(d); acb_init(t); acb_init(u); acb_sub(c, a, b, prec); acb_add_ui(c, c, 1, prec); acb_neg(d, b); acb_add_ui(d, d, 2, prec); _acb_hypgeom_m_1f1(t, c, d, z, 0, prec, gamma_prec, kummer); acb_pow_ui(u, z, 1 - n, prec); acb_mul(t, t, u, prec); acb_rising_ui(u, a, 1 - n, prec); acb_mul(t, t, u, prec); arb_fac_ui(acb_realref(u), 1 - n, prec); acb_div_arb(res, t, acb_realref(u), prec); acb_clear(c); acb_clear(d); acb_clear(t); acb_clear(u); } else { acb_t t; acb_init(t); acb_rgamma(t, b, gamma_prec); _acb_hypgeom_m_1f1(res, a, b, z, 0, prec, gamma_prec, kummer); acb_mul(res, res, t, prec); acb_clear(t); } return; } /* Kummer's transformation */ if (kummer) { acb_t u, v; acb_init(u); acb_init(v); acb_sub(u, b, a, prec); acb_neg(v, z); _acb_hypgeom_m_1f1(u, u, b, v, regularized, prec, gamma_prec, 0); acb_exp(v, z, prec); acb_mul(res, u, v, prec); acb_clear(u); acb_clear(v); return; } if (acb_is_one(a)) { acb_hypgeom_pfq_direct(res, NULL, 0, b, 1, z, -1, prec); } else { acb_struct c[3]; c[0] = *a; c[1] = *b; acb_init(c + 2); acb_one(c + 2); acb_hypgeom_pfq_direct(res, c, 1, c + 1, 2, z, -1, prec); acb_clear(c + 2); } } void acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { if (arf_sgn(arb_midref(acb_realref(z))) >= 0 || (acb_is_int(a) && arb_is_nonpositive(acb_realref(a)))) { _acb_hypgeom_m_1f1(res, a, b, z, regularized, prec, prec, 0); } else { _acb_hypgeom_m_1f1(res, a, b, z, regularized, prec, prec, 1); } } static double hypotmx(double x, double y) { if (x > 0.0 && x > 1e6 * fabs(y)) return y * y / (2.0 * x); else return sqrt(x * x + y * y) - x; } void acb_hypgeom_m_choose(int * asymp, int * kummer, slong * wp, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { double x, y, t, cancellation; double input_accuracy, direct_accuracy, asymp_accuracy; slong m = WORD_MAX; slong n = WORD_MAX; if (acb_is_int(a) && arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 30) < 0) { m = arf_get_si(arb_midref(acb_realref(a)), ARF_RND_DOWN); } if (acb_is_int(b) && arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0) { n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN); } *asymp = 0; *kummer = 0; *wp = prec; /* The 1F1 series terminates. */ /* TODO: for large m, estimate extra precision here. */ if (m <= 0 && m < n && m > -10 * prec && (n > 0 || !regularized)) { *asymp = 0; return; } /* The 1F1 series terminates with the Kummer transform. */ /* TODO: for large m, estimate extra precision here. */ if (m >= 1 && n >= 1 && m < 0.1 * prec && n < 0.1 * prec && n <= m) { *asymp = 0; *kummer = 1; return; } input_accuracy = acb_rel_one_accuracy_bits(z); t = acb_rel_one_accuracy_bits(a); input_accuracy = FLINT_MIN(input_accuracy, t); t = acb_rel_one_accuracy_bits(b); input_accuracy = FLINT_MIN(input_accuracy, t); input_accuracy = FLINT_MAX(input_accuracy, 0.0); /* From here we ignore the values of a, b. Taking them into account is a possible future improvement... */ /* Tiny |z|. */ if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 2) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 2) < 0)) { *asymp = 0; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); return; } /* Huge |z|. */ if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0)) { *asymp = 1; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); return; } x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); asymp_accuracy = sqrt(x * x + y * y) * 1.44269504088896 - 5.0; /* The Kummer transformation gives less cancellation with the 1F1 series. */ if (x < 0.0) { *kummer = 1; x = -x; } if (asymp_accuracy >= prec) { *asymp = 1; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); return; } cancellation = hypotmx(x, y) * 1.44269504088896; direct_accuracy = input_accuracy - cancellation; if (direct_accuracy > asymp_accuracy) { *asymp = 0; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec + cancellation)); } else { *asymp = 1; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); } } void acb_hypgeom_m_nointegration(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { int asymp, kummer; slong wp; acb_hypgeom_m_choose(&asymp, &kummer, &wp, a, b, z, regularized, prec); if (asymp) { acb_hypgeom_m_asymp(res, a, b, z, regularized, wp); } else { _acb_hypgeom_m_1f1(res, a, b, z, regularized, wp, FLINT_MIN(wp, prec), kummer); } acb_set_round(res, res, prec); } void acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { acb_t res2; slong acc, max, t; acb_init(res2); acb_hypgeom_m_nointegration(res2, a, b, z, regularized, prec); acc = acb_rel_accuracy_bits(res2); if (acc < 0.5 * prec) { max = prec; t = acb_rel_accuracy_bits(z); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(a); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(b); max = FLINT_MIN(max, t); if (max > 2 && acc < 0.5 * max) { if (acb_is_real(a) && acb_is_real(b) && acb_is_real(z) && arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0) { arb_hypgeom_1f1_integration(acb_realref(res), acb_realref(a), acb_realref(b), acb_realref(z), regularized, prec); arb_zero(acb_imagref(res)); if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) || (acb_is_finite(res) && !acb_is_finite(res2))) { acb_swap(res, res2); } } } } acb_swap(res, res2); acb_clear(res2); } void acb_hypgeom_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { acb_hypgeom_m(res, a, b, z, regularized, prec); } flint-3.1.3/src/acb_hypgeom/pfq.c000066400000000000000000000070711461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" static int _acb_vec_maybe_nonpositive_int(acb_srcptr b, slong q) { slong i; for (i = 0; i < q; i++) if (!arb_is_positive(acb_realref(b + i)) && acb_contains_int(b + i)) return 1; return 0; } void acb_hypgeom_pfq(acb_t res, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, int regularized, slong prec) { if (p == 0 && q == 0) { acb_exp(res, z, prec); } else if (p == 1 && q == 0) { acb_t t; acb_init(t); acb_neg(t, a); acb_sub_ui(res, z, 1, prec); acb_neg(res, res); acb_pow(res, res, t, prec); acb_clear(t); } else if (p == 0 && q == 1) { acb_hypgeom_0f1(res, b, z, regularized, prec); } else if (p == 1 && q == 1) { acb_hypgeom_m(res, a, b, z, regularized, prec); } else if (p == 2 && q == 1) { acb_hypgeom_2f1(res, a, a + 1, b, z, regularized, prec); } else if (regularized && _acb_vec_maybe_nonpositive_int(b, q)) { /* todo: implement regularized sum without using polynomials */ acb_poly_struct * tmp; slong i; tmp = flint_malloc(sizeof(acb_poly_struct) * (p + q + 2)); for (i = 0; i < p + q + 2; i++) acb_poly_init(tmp + i); for (i = 0; i < p; i++) acb_poly_set_acb(tmp + i, a + i); for (i = 0; i < q; i++) acb_poly_set_acb(tmp + p + i, b + i); acb_poly_one(tmp + p + q); acb_poly_set_acb(tmp + p + q + 1, z); acb_hypgeom_pfq_series_direct(tmp, tmp, p, tmp + p, q + 1, tmp + p + q + 1, regularized, -1, 1, prec); acb_poly_get_coeff_acb(res, tmp, 0); for (i = 0; i < p + q + 2; i++) acb_poly_clear(tmp + i); flint_free(tmp); } else { acb_ptr tmp; slong i, j, alloc = 0; /* check if we can remove a '1' from the upper parameters */ for (i = 0; i < p; i++) { if (acb_is_one(a + i)) { alloc = p; tmp = _acb_vec_init(alloc); for (j = 0; j < p - 1; j++) acb_set(tmp + 1 + j, a + j + (j >= i)); acb_hypgeom_pfq_direct(tmp, tmp + 1, p - 1, b, q, z, -1, prec); break; } } if (alloc == 0) { alloc = q + 2; tmp = _acb_vec_init(alloc); for (j = 0; j < q; j++) acb_set(tmp + 1 + j, b + j); acb_one(tmp + 1 + q); acb_hypgeom_pfq_direct(tmp, a, p, tmp + 1, q + 1, z, -1, prec); } if (regularized && q > 0) { acb_t c, t; acb_init(c); acb_init(t); acb_rgamma(c, b, prec); for (i = 1; i < q; i++) { acb_rgamma(t, b + i, prec); acb_mul(c, c, t, prec); } acb_mul(tmp, tmp, c, prec); acb_clear(c); acb_clear(t); } acb_set(res, tmp); _acb_vec_clear(tmp, alloc); } if (!acb_is_finite(res)) acb_indeterminate(res); } flint-3.1.3/src/acb_hypgeom/pfq_bound_factor.c000066400000000000000000000027351461254215100213650ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_pfq_bound_factor(mag_t C, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, ulong n) { mag_t t, u; acb_t w; slong i; if (p > q) { mag_inf(C); return; } mag_init(t); mag_init(u); acb_init(w); acb_get_mag(C, z); for (i = 0; i < q; i++) { acb_add_ui(w, b + i, n, MAG_BITS); if (arb_is_positive(acb_realref(w))) { acb_get_mag_lower(u, w); if (i < p) { acb_sub(w, a + i, b + i, MAG_BITS); acb_get_mag(t, w); mag_div(t, t, u); mag_one(u); mag_add(t, t, u); mag_mul(C, C, t); } else { mag_div(C, C, u); } } else { mag_inf(C); } } mag_one(t); mag_sub_lower(u, t, C); if (mag_is_zero(u)) mag_inf(C); else mag_div(C, t, u); mag_clear(t); mag_clear(u); acb_clear(w); } flint-3.1.3/src/acb_hypgeom/pfq_choose_n.c000066400000000000000000000202331461254215100205060ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define floor __builtin_floor # define log __builtin_log #else # include #endif #define D_ABS(x) ((x) < 0.0 ? (-(x)) : (x)) int acb_hypgeom_pfq_choose_n_double(slong * nn, const double * are, const double * aim, slong p, const double * bre, const double * bim, slong q, double log2_z, slong n_skip, slong n_min, slong n_max, slong prec) { double increase, term, term_max, accuracy, accuracy_best, t, u; double required_decrease; slong k, n, n_best; int success; if (p < q) required_decrease = 0.01; else if (p == q) required_decrease = 0.0001; else required_decrease = 0.01; term = term_max = accuracy = accuracy_best = 0.0; success = 0; for (n = n_best = n_skip; n < n_max; n++) { t = 1.0; for (k = 0; k < FLINT_MAX(p, q); k++) { if (k < p) { u = (are[k]+n-1)*(are[k]+n-1) + (aim[k]*aim[k]); t *= D_ABS(u); } if (k < q) { u = (bre[k]+n-1)*(bre[k]+n-1) + (bim[k]*bim[k]); u = D_ABS(u); if (u > 1e-100) t /= u; } } increase = 0.5 * log(t) * 1.4426950408889634074 + log2_z; term += increase; term_max = FLINT_MAX(term_max, term); accuracy = term_max - term; if (accuracy > accuracy_best && n >= n_min && increase < -required_decrease) { n_best = n; accuracy_best = accuracy; } if (accuracy_best > prec + 4) { success = 1; break; } } *nn = n_best; return success; } slong acb_hypgeom_pfq_choose_n_max(acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong prec, slong n_max) { slong n_skip, n_min, n_terminating, nint; slong k, n; double log2_z; double * are; double * aim; double * bre; double * bim; mag_t zmag; int success; if (acb_is_zero(z) || !acb_is_finite(z)) return 1; mag_init(zmag); are = flint_malloc(sizeof(double) * 2 * (p + q)); aim = are + p; bre = aim + p; bim = bre + q; acb_get_mag(zmag, z); log2_z = mag_get_d_log2_approx(zmag); n_skip = 1; n_min = 1; n_terminating = WORD_MAX; for (k = 0; k < p; k++) { are[k] = arf_get_d(arb_midref(acb_realref(a + k)), ARF_RND_DOWN); aim[k] = arf_get_d(arb_midref(acb_imagref(a + k)), ARF_RND_DOWN); /* If the series is terminating, stop at this n. */ if (acb_is_int(a + k) && are[k] <= 0.0) { n_terminating = FLINT_MIN(n_terminating, (slong) (-are[k] + 1)); n_terminating = FLINT_MAX(n_terminating, 1); } else if (are[k] <= 0.01 && D_ABS(aim[k]) < 0.01) { /* If very close to an integer, we don't want to deal with it using doubles, so fast forward (todo: could work with the log2 of the difference instead when this happens). */ nint = floor(are[k] + 0.5); if (D_ABS(nint - are[k]) < 0.01) n_skip = FLINT_MAX(n_skip, 2 - nint); } } n_max = FLINT_MIN(n_max, n_terminating); for (k = 0; k < q; k++) { bre[k] = arf_get_d(arb_midref(acb_realref(b + k)), ARF_RND_DOWN); bim[k] = arf_get_d(arb_midref(acb_imagref(b + k)), ARF_RND_DOWN); if (bre[k] <= 0.25) { n_min = FLINT_MAX(n_min, 2 - bre[k]); /* Also avoid near-integers here (can even allow exact integers when computing regularized hypergeometric functions). */ if (bre[k] <= 0.01 && D_ABS(bim[k]) < 0.01) { nint = floor(bre[k] + 0.5); if (D_ABS(nint - bre[k]) < 0.01) n_skip = FLINT_MAX(n_skip, 2 - nint); } } } success = acb_hypgeom_pfq_choose_n_double(&n, are, aim, p, bre, bim, q, log2_z, n_skip, n_min, n_max, prec); if (!success) { if (n_terminating <= n_max) { n = n_terminating; } else { n = FLINT_MAX(n_min, n); n = FLINT_MIN(n_max, n); } } flint_free(are); mag_clear(zmag); return n; } slong acb_hypgeom_pfq_choose_n(acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong prec) { return acb_hypgeom_pfq_choose_n_max(a, p, b, q, z, prec, FLINT_MIN(WORD_MAX / 2, 50 + 10 * prec)); } slong acb_hypgeom_pfq_series_choose_n(const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, slong len, slong prec) { slong n_skip, n_min, n_max, n_terminating, nint; slong k, n; double log2_z; double * are; double * aim; double * bre; double * bim; acb_t t; mag_t zmag; int success; if (z->length == 0) /* todo: check finite */ return 1; mag_init(zmag); acb_init(t); are = flint_malloc(sizeof(double) * 2 * (p + q)); aim = are + p; bre = aim + p; bim = bre + q; acb_get_mag(zmag, z->coeffs); log2_z = mag_get_d_log2_approx(zmag); n_skip = 1; n_min = 1; n_max = FLINT_MIN(WORD_MAX / 2, 50 + 10 * prec); n_terminating = WORD_MAX; /* e.g. for exp(x + O(x^100)), make sure that we actually run the recurrence up to order 100. todo: compute correctly based on degrees of inputs */ n_min = FLINT_MAX(n_min, len); n_max = FLINT_MAX(n_max, n_min); for (k = 0; k < p; k++) { acb_poly_get_coeff_acb(t, a + k, 0); are[k] = arf_get_d(arb_midref(acb_realref(t)), ARF_RND_DOWN); aim[k] = arf_get_d(arb_midref(acb_imagref(t)), ARF_RND_DOWN); /* If the series is terminating, stop at this n. */ if (acb_is_int(t) && are[k] <= 0.0 && acb_poly_length(a + k) <= 1) { n_terminating = FLINT_MIN(n_terminating, (slong) (-are[k] + 1)); n_terminating = FLINT_MAX(n_terminating, 1); } else if (are[k] <= 0.01 && D_ABS(aim[k]) < 0.01) { /* If very close to an integer, we don't want to deal with it using doubles, so fast forward (todo: could work with the log2 of the difference instead when this happens). */ nint = floor(are[k] + 0.5); if (D_ABS(nint - are[k]) < 0.01) n_skip = FLINT_MAX(n_skip, 2 - nint); } } n_max = FLINT_MIN(n_max, n_terminating); for (k = 0; k < q; k++) { acb_poly_get_coeff_acb(t, b + k, 0); bre[k] = arf_get_d(arb_midref(acb_realref(t)), ARF_RND_DOWN); bim[k] = arf_get_d(arb_midref(acb_imagref(t)), ARF_RND_DOWN); if (bre[k] <= 0.25) { n_min = FLINT_MAX(n_min, 2 - bre[k]); /* Also avoid near-integers here (can even allow exact integers when computing regularized hypergeometric functions). */ if (bre[k] <= 0.01 && D_ABS(bim[k]) < 0.01) { nint = floor(bre[k] + 0.5); if (D_ABS(nint - bre[k]) < 0.01) n_skip = FLINT_MAX(n_skip, 2 - nint); } } } success = acb_hypgeom_pfq_choose_n_double(&n, are, aim, p, bre, bim, q, log2_z, n_skip, n_min, n_max, prec); if (!success) { if (n_terminating <= n_max) { n = n_terminating; } else { n = FLINT_MAX(n_min, n); n = FLINT_MIN(n_max, n); } } flint_free(are); acb_clear(t); mag_clear(zmag); return n; } flint-3.1.3/src/acb_hypgeom/pfq_direct.c000066400000000000000000000023151461254215100201640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_pfq_direct(acb_t res, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { acb_t s, t; mag_t err, C; acb_init(s); acb_init(t); mag_init(err); mag_init(C); if (n < 0) n = acb_hypgeom_pfq_choose_n(a, p, b, q, z, prec); acb_hypgeom_pfq_sum(s, t, a, p, b, q, z, n, prec); if (!acb_is_zero(t)) { acb_hypgeom_pfq_bound_factor(C, a, p, b, q, z, n); acb_get_mag(err, t); mag_mul(err, err, C); if (_acb_vec_is_real(a, p) && _acb_vec_is_real(b, q) && acb_is_real(z)) arb_add_error_mag(acb_realref(s), err); else acb_add_error_mag(s, err); } acb_set(res, s); acb_clear(s); acb_clear(t); mag_clear(err); mag_clear(C); } flint-3.1.3/src/acb_hypgeom/pfq_series_direct.c000066400000000000000000000154311461254215100215410ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_poly_reciprocal_majorant(arb_ptr res, acb_srcptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { if (i == 0) { acb_get_abs_lbound_arf(arb_midref(res + i), vec + i, prec); mag_zero(arb_radref(res + i)); } else { acb_get_abs_ubound_arf(arb_midref(res + i), vec + i, prec); arf_neg(arb_midref(res + i), arb_midref(res + i)); mag_zero(arb_radref(res + i)); } } } void acb_poly_reciprocal_majorant(arb_poly_t res, const acb_poly_t poly, slong prec) { arb_poly_fit_length(res, poly->length); _acb_poly_reciprocal_majorant(res->coeffs, poly->coeffs, poly->length, prec); _arb_poly_set_length(res, poly->length); } /* F = 1 + U + U^2 + ... = 1/(1-U) assuming that U[0] is positive; indeterminate if not convergent */ static void arb_poly_geometric_sum(arb_poly_t F, const arb_poly_t U, slong len, slong prec) { if (U->length == 0) { arb_poly_one(F); return; } arb_poly_add_si(F, U, -1, prec); arb_poly_neg(F, F); if (F->length > 0 && arb_is_positive(F->coeffs)) { arb_poly_inv_series(F, F, len, prec); } else { arb_poly_fit_length(F, len); _arb_vec_indeterminate(F->coeffs, len); _arb_poly_set_length(F, len); } } /* F = 1 + U + U^2 + U^3 + ... = 1/(1-U) U = product of (1 + |A-B|/(|B[0] - |B[1:]|) product of (1 / (|B[0] - |B[1:]|)) * |Z| */ void acb_hypgeom_pfq_series_bound_factor(arb_poly_t F, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, slong n, slong len, slong prec) { slong i; arb_poly_t T, U, V; acb_poly_t BN, AB; /* not convergent */ if (p > q) { arb_poly_fit_length(F, len); _arb_vec_indeterminate(F->coeffs, len); _arb_poly_set_length(F, len); return; } arb_poly_init(T); arb_poly_init(U); arb_poly_init(V); acb_poly_init(BN); acb_poly_init(AB); acb_poly_majorant(U, z, prec); for (i = 0; i < q; i++) { acb_poly_add_si(BN, b + i, n, prec); if (acb_poly_length(BN) != 0 && arb_is_positive(acb_realref(BN->coeffs))) { if (i < p) { /* 1 + |a-b|/reciprocal_majorant(b + n) */ acb_poly_sub(AB, a + i, b + i, prec); acb_poly_majorant(T, AB, prec); acb_poly_reciprocal_majorant(V, BN, prec); arb_poly_div_series(T, T, V, len, prec); arb_poly_add_si(T, T, 1, prec); arb_poly_mullow(U, U, T, len, prec); } else { acb_poly_reciprocal_majorant(T, BN, prec); arb_poly_div_series(U, U, T, len, prec); } } else { arb_poly_fit_length(U, len); _arb_vec_indeterminate(U->coeffs, len); _arb_poly_set_length(U, len); break; } } /* F = 1/(1-U) */ arb_poly_geometric_sum(F, U, len, prec); arb_poly_clear(T); arb_poly_clear(U); arb_poly_clear(V); acb_poly_clear(BN); acb_poly_clear(AB); } void acb_hypgeom_pfq_series_direct(acb_poly_t res, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) { acb_poly_t s, t, err; arb_poly_t C, T; slong i; int is_real; int terminating; /* default algorithm to choose number of terms */ if (n < 0) { n = acb_hypgeom_pfq_series_choose_n(a, p, b, q, z, len, prec); } terminating = 0; /* check if it terminates due to a root of the numerator */ for (i = 0; i < p; i++) { if (acb_poly_length(a + i) == 0 && n > 0) { terminating = 1; } else if (acb_poly_length(a + i) == 1) { acb_srcptr c = acb_poly_get_coeff_ptr(a + i, 0); if (acb_is_int(c) && arb_is_negative(acb_realref(c)) && arf_cmpabs_ui(arb_midref(acb_realref(c)), n) < 0) { terminating = 1; } } } /* check if it terminates (to order n) due to z */ /* the following tests could be made stronger... */ if (z->length == 0 && n >= 1) { terminating = 1; } else if (!terminating && z->length > 0 && acb_is_zero(z->coeffs) && n >= len) { if (regularized) { terminating = 1; } else { terminating = 1; for (i = 0; i < q; i++) { acb_srcptr c = acb_poly_get_coeff_ptr(b + i, 0); if (!arb_is_positive(acb_realref(c)) && acb_contains_int(c)) terminating = 0; } } } acb_poly_init(s); acb_poly_init(t); acb_poly_init(err); arb_poly_init(C); arb_poly_init(T); acb_hypgeom_pfq_series_sum(s, t, a, p, b, q, z, regularized, n, len, prec); if (!terminating) { is_real = acb_poly_is_real(z); for (i = 0; i < p; i++) is_real = is_real && acb_poly_is_real(a + i); for (i = 0; i < q; i++) is_real = is_real && acb_poly_is_real(b + i); acb_poly_majorant(T, t, MAG_BITS); acb_hypgeom_pfq_series_bound_factor(C, a, p, b, q, z, n, len, MAG_BITS); if (!_arb_vec_is_finite(T->coeffs, T->length) || !_arb_vec_is_finite(C->coeffs, C->length)) { arb_poly_fit_length(T, len); _arb_vec_indeterminate(T->coeffs, len); _arb_poly_set_length(T, len); } else { arb_poly_mullow(T, T, C, len, MAG_BITS); } /* create polynomial of errors */ acb_poly_fit_length(err, len); for (i = 0; i < FLINT_MIN(len, T->length); i++) { arb_add_error(acb_realref(err->coeffs + i), T->coeffs + i); if (!is_real) arb_add_error(acb_imagref(err->coeffs + i), T->coeffs + i); } _acb_poly_set_length(err, len); _acb_poly_normalise(err); acb_poly_add(s, s, err, prec); } acb_poly_set(res, s); acb_poly_clear(s); acb_poly_clear(t); acb_poly_clear(err); arb_poly_clear(C); arb_poly_clear(T); } flint-3.1.3/src/acb_hypgeom/pfq_series_sum.c000066400000000000000000000043571461254215100211000ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void acb_hypgeom_pfq_series_sum(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) { slong abits, zbits, i, j, cb; if (n < 4) { acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, n, len, prec); return; } abits = 0; zbits = 0; for (i = 0; i < p; i++) { for (j = 0; j < FLINT_MIN(acb_poly_length(a + i), n); j++) { cb = acb_bits((a + i)->coeffs + j); abits = FLINT_MAX(abits, cb); } } for (i = 0; i < q; i++) { for (j = 0; j < FLINT_MIN(acb_poly_length(b + i), n); j++) { cb = acb_bits((b + i)->coeffs + j); abits = FLINT_MAX(abits, cb); } } for (j = 0; j < FLINT_MIN(acb_poly_length(z), n); j++) { cb = acb_bits(z->coeffs + j); zbits = FLINT_MAX(zbits, cb); } /* Prefer RS with small coefficients in parameters, large coefficients in z. TODO: tune for larger len? */ if (len <= 5 && prec > 900 && abits < prec * 0.1 && zbits > prec * 0.1) { acb_hypgeom_pfq_series_sum_rs(s, t, a, p, b, q, z, regularized, n, len, prec); return; } /* Prefer BS with small coefficients and high precision, or when computing derivatives of high order. */ if ((abits < prec * 0.1 && zbits < prec * 0.1 && prec > 600) || len > 20) { acb_hypgeom_pfq_series_sum_bs(s, t, a, p, b, q, z, regularized, n, len, prec); return; } /* TODO: also use bs here when n is large enough, for better numerical stability? */ acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, n, len, prec); } flint-3.1.3/src/acb_hypgeom/pfq_series_sum_bs.c000066400000000000000000000122201461254215100215500ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" static void factor(acb_poly_t A, acb_poly_t tmp, const acb_poly_struct * a, slong p, const acb_poly_t z, slong k, slong len, slong prec) { slong i; if (p == 0) { if (z == NULL) acb_poly_one(A); else acb_poly_set(A, z); } else { acb_poly_add_si(A, a, k, prec); for (i = 1; i < p; i++) { acb_poly_add_si(tmp, a + i, k, prec); acb_poly_mullow(A, A, tmp, len, prec); } if (z != NULL) { acb_poly_mullow(A, A, z, len, prec); } } } static void bsplit(acb_poly_t A1, acb_poly_t B1, acb_poly_t C1, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, slong aa, slong bb, slong len, slong prec) { if (bb - aa == 1) { factor(A1, B1, a, p, z, aa, len, prec); factor(C1, B1, b, q, NULL, aa, len, prec); /* acb_poly_set(B1, C1); but we skip this */ } else { slong m; acb_poly_t A2, B2, C2, tmp; acb_poly_init(A2); acb_poly_init(B2); acb_poly_init(C2); acb_poly_init(tmp); m = aa + (bb - aa) / 2; bsplit(A1, B1, C1, a, p, b, q, z, aa, m, len, prec); bsplit(A2, B2, C2, a, p, b, q, z, m, bb, len, prec); if (bb - m == 1) /* B2 = C2 */ { if (m - aa == 1) acb_poly_add(B2, A1, C1, prec); else acb_poly_add(B2, A1, B1, prec); acb_poly_mullow(B1, B2, C2, len, prec); } else { if (m - aa == 1) { acb_poly_mullow(B1, C1, C2, len, prec); } else { acb_poly_mullow(tmp, B1, C2, len, prec); acb_poly_swap(B1, tmp); } acb_poly_mullow(tmp, A1, B2, len, prec); acb_poly_add(B1, B1, tmp, prec); } acb_poly_mullow(tmp, A1, A2, len, prec); acb_poly_swap(A1, tmp); acb_poly_mullow(tmp, C1, C2, len, prec); acb_poly_swap(C1, tmp); acb_poly_clear(A2); acb_poly_clear(B2); acb_poly_clear(C2); acb_poly_clear(tmp); } } void acb_hypgeom_pfq_series_sum_bs(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) { acb_poly_t u, v, w; slong i, start; if (n == 0) { acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, n, len, prec); return; } start = 0; if (regularized) { /* Use basecase algorithm to get past any poles. G(x) = 1/Gamma(x) n = 1: s = 0; t = G(b); b = 0 requires skipping n = 2: s = G(b); t = G(b) G(b+1); b = 0, -1 require skipping... TODO: when pole is near the end, do the *start* (or middle segment) using fast algorithm; use basecase algorithm for the end. */ for (i = 0; i < q; i++) { if (acb_poly_is_zero(b + i)) { start = FLINT_MAX(start, 1); } else { /* todo: use a fuzzier test? */ if (acb_contains_int((b + i)->coeffs) && !arb_is_positive(acb_realref((b + i)->coeffs)) && arf_cmpabs_2exp_si(arb_midref(acb_realref((b + i)->coeffs)), FLINT_BITS - 2) < 0) { slong c = -arf_get_si(arb_midref(acb_realref((b + i)->coeffs)), ARF_RND_NEAR); /* if c >= n, terminates earlier, so no problem */ if (c < n) { start = FLINT_MAX(start, c + 1); } } } } /* We should now have start <= n. */ if (start > n) flint_throw(FLINT_ERROR, "(%s)\n", __func__); acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, start, len, prec); } else { acb_poly_zero(s); acb_poly_one(t); } if (start == n) return; acb_poly_init(u); acb_poly_init(v); acb_poly_init(w); bsplit(u, v, w, a, p, b, q, z, start, n, len, prec); if (n - start == 1) acb_poly_set(v, w); /* B1 not set */ acb_poly_mullow(v, v, t, len, prec); acb_poly_div_series(v, v, w, len, prec); acb_poly_add(s, s, v, prec); acb_poly_mullow(t, t, u, len, prec); acb_poly_div_series(t, t, w, len, prec); acb_poly_clear(u); acb_poly_clear(v); acb_poly_clear(w); } flint-3.1.3/src/acb_hypgeom/pfq_series_sum_forward.c000066400000000000000000000103021461254215100226070ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void acb_hypgeom_pfq_series_sum_forward(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) { acb_poly_t u, v; acb_poly_t tmp; slong k, i; acb_poly_init(u); acb_poly_init(v); acb_poly_init(tmp); if (!regularized) { acb_poly_zero(s); acb_poly_one(t); for (k = 0; k < n && acb_poly_length(t) != 0; k++) { acb_poly_add(s, s, t, prec); if (p > 0) { acb_poly_add_si(u, a, k, prec); for (i = 1; i < p; i++) { acb_poly_add_si(v, a + i, k, prec); acb_poly_mullow(u, u, v, len, prec); } acb_poly_mullow(t, t, u, len, prec); } if (q > 0) { acb_poly_add_si(u, b, k, prec); for (i = 1; i < q; i++) { acb_poly_add_si(v, b + i, k, prec); acb_poly_mullow(u, u, v, len, prec); } acb_poly_div_series(t, t, u, len, prec); } acb_poly_mullow(t, t, z, len, prec); } } else { acb_poly_zero(s); if (q == 0) acb_poly_one(t); for (i = 0; i < q; i++) { if (i == 0) { acb_poly_rgamma_series(t, b + i, len, prec); } else { acb_poly_rgamma_series(u, b + i, len, prec); acb_poly_mullow(tmp, t, u, len, prec); acb_poly_swap(tmp, t); } } for (k = 0; k < n; k++) { acb_poly_add(s, s, t, prec); if (p > 0) { acb_poly_add_si(u, a, k, prec); for (i = 1; i < p; i++) { acb_poly_add_si(v, a + i, k, prec); acb_poly_mullow(tmp, u, v, len, prec); acb_poly_swap(tmp, u); } acb_poly_mullow(tmp, t, u, len, prec); acb_poly_swap(tmp, t); } if (q > 0) { acb_poly_add_si(u, b, k, prec); for (i = 1; i < q; i++) { acb_poly_add_si(v, b + i, k, prec); acb_poly_mullow(tmp, u, v, len, prec); acb_poly_swap(tmp, u); } if (acb_poly_length(u) > 0 && !acb_contains_zero(u->coeffs)) { acb_poly_div_series(tmp, t, u, len, prec); acb_poly_mullow(t, tmp, z, len, prec); } else { /* compute term from scratch */ acb_poly_one(t); for (i = 0; i < p; i++) { acb_poly_rising_ui_series(v, a + i, k + 1, len, prec); acb_poly_mullow(t, t, v, len, prec); } for (i = 0; i < q; i++) { acb_poly_add_si(v, b + i, k + 1, prec); acb_poly_rgamma_series(v, v, len, prec); acb_poly_mullow(t, t, v, len, prec); } acb_poly_pow_ui_trunc_binexp(v, z, k + 1, len, prec); acb_poly_mullow(t, t, v, len, prec); } } else { acb_poly_mullow(tmp, t, z, len, prec); acb_poly_swap(tmp, t); } } } acb_poly_clear(u); acb_poly_clear(v); acb_poly_clear(tmp); } flint-3.1.3/src/acb_hypgeom/pfq_series_sum_rs.c000066400000000000000000000161531461254215100216010ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb_poly.h" #include "acb_hypgeom.h" #define FAST_T 0 void acb_poly_reciprocal_majorant(arb_poly_t res, const acb_poly_t poly, slong prec); static void rsplit(acb_poly_t res, acb_poly_t term, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, slong offset, slong n, slong len, slong prec) { acb_poly_struct * zpow; acb_poly_t s, t, u; slong i, j, k, m, tprec; int is_real; #if FAST_T arb_poly_t B, C, D; #else acb_poly_t B, C, D; #endif if (n == 0) { acb_poly_zero(res); acb_poly_one(term); return; } if (n < 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); m = n_sqrt(n); m = FLINT_MIN(m, 150); acb_poly_init(s); acb_poly_init(t); acb_poly_init(u); #if FAST_T tprec = MAG_BITS; arb_poly_init(B); arb_poly_init(C); arb_poly_init(D); arb_poly_one(B); arb_poly_one(D); is_real = 1; for (i = 0; i < p; i++) for (j = 0; j < FLINT_MIN(acb_poly_length(a + i), len); j++) is_real = is_real && acb_is_real((a + i)->coeffs + j); for (i = 0; i < q; i++) for (j = 0; j < FLINT_MIN(acb_poly_length(b + i), len); j++) is_real = is_real && acb_is_real((b + i)->coeffs + j); for (j = 0; j < FLINT_MIN(acb_poly_length(z), len); j++) is_real = is_real && acb_is_real(z->coeffs + j); #else tprec = 2 * MAG_BITS; is_real = 0; (void) is_real; acb_poly_init(B); acb_poly_init(C); acb_poly_init(D); acb_poly_one(B); acb_poly_one(D); #endif zpow = flint_malloc(sizeof(acb_poly_struct) * (m + 1)); for (i = 0; i <= m; i++) acb_poly_init(zpow + i); for (i = 0; i <= m; i++) { if (i == 0) acb_poly_one(zpow + i); else if (i == 1) acb_poly_set_round(zpow + i, z, prec); else if (i % 2 == 0) acb_poly_mullow(zpow + i, zpow + i / 2, zpow + i / 2, len, prec); else acb_poly_mullow(zpow + i, zpow + i - 1, zpow + 1, len, prec); } for (k = n; k >= 0; k--) { j = k % m; if (k < n) acb_poly_add(s, s, zpow + j, prec); if (k > 0) { if (p > 0) { acb_poly_add_si(u, a, offset + k - 1, prec); for (i = 1; i < p; i++) { acb_poly_add_si(t, a + i, offset + k - 1, prec); acb_poly_mullow(u, u, t, len, prec); } if (k < n) acb_poly_mullow(s, s, u, len, prec); #if FAST_T acb_poly_majorant(C, u, tprec); arb_poly_mullow(B, B, C, len, tprec); #else acb_poly_set_round(C, u, tprec); acb_poly_mullow(B, B, C, len, tprec); #endif } if (q > 0) { acb_poly_add_si(u, b, offset + k - 1, prec); for (i = 1; i < q; i++) { acb_poly_add_si(t, b + i, offset + k - 1, prec); acb_poly_mullow(u, u, t, len, prec); } if (k < n) acb_poly_div_series(s, s, u, len, prec); #if FAST_T acb_poly_reciprocal_majorant(C, u, tprec); arb_poly_mullow(D, D, C, len, tprec); #else acb_poly_set_round(C, u, tprec); acb_poly_mullow(D, D, C, len, tprec); #endif } if (j == 0 && k < n) { acb_poly_mullow(s, s, zpow + m, len, prec); } } } #if FAST_T arb_poly_div_series(B, B, D, len, tprec); acb_poly_majorant(C, z, tprec); arb_poly_pow_ui_trunc_binexp(C, C, n, len, tprec); arb_poly_mullow(C, B, C, len, tprec); acb_poly_fit_length(term, arb_poly_length(C)); for (i = 0; i < arb_poly_length(C); i++) { arb_get_mag(arb_radref(acb_realref(term->coeffs + i)), C->coeffs + i); arf_zero(arb_midref(acb_realref(term->coeffs + i))); if (is_real) arb_zero(acb_imagref(term->coeffs + i)); else arb_set(acb_imagref(term->coeffs + i), acb_realref(term->coeffs + i)); } _acb_poly_set_length(term, arb_poly_length(C)); _acb_poly_normalise(term); #else acb_poly_div_series(B, B, D, len, tprec); acb_poly_set_round(C, z, tprec); acb_poly_pow_ui_trunc_binexp(C, C, n, len, tprec); acb_poly_mullow(term, B, C, len, tprec); #endif acb_poly_set(res, s); #if FAST_T arb_poly_clear(B); arb_poly_clear(C); arb_poly_clear(D); #else acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(D); #endif acb_poly_clear(s); acb_poly_clear(t); acb_poly_clear(u); for (i = 0; i <= m; i++) acb_poly_clear(zpow + i); flint_free(zpow); } void acb_hypgeom_pfq_series_sum_rs(acb_poly_t s, acb_poly_t t, const acb_poly_struct * a, slong p, const acb_poly_struct * b, slong q, const acb_poly_t z, int regularized, slong n, slong len, slong prec) { acb_poly_t u, v; slong i, start; if (n == 0) { acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, n, len, prec); return; } start = 0; if (regularized) { for (i = 0; i < q; i++) { if (acb_poly_is_zero(b + i)) { start = FLINT_MAX(start, 1); } else { /* todo: use a fuzzier test? */ if (acb_contains_int((b + i)->coeffs) && !arb_is_positive(acb_realref((b + i)->coeffs)) && arf_cmpabs_2exp_si(arb_midref(acb_realref((b + i)->coeffs)), FLINT_BITS - 2) < 0) { slong c = -arf_get_si(arb_midref(acb_realref((b + i)->coeffs)), ARF_RND_NEAR); /* if c >= n, terminates earlier, so no problem */ if (c < n) { start = FLINT_MAX(start, c + 1); } } } } /* We should now have start <= n. */ if (start > n) flint_throw(FLINT_ERROR, "(%s)\n", __func__); acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, start, len, prec); } else { acb_poly_zero(s); acb_poly_one(t); } if (start == n) return; acb_poly_init(u); acb_poly_init(v); rsplit(u, v, a, p, b, q, z, start, n - start, len, prec); acb_poly_mullow(u, u, t, len, prec); acb_poly_add(s, s, u, prec); acb_poly_mullow(t, t, v, len, prec); acb_poly_clear(u); acb_poly_clear(v); } flint-3.1.3/src/acb_hypgeom/pfq_sum.c000066400000000000000000000043101461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_pfq_sum(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { if (n > 4 && prec >= 128 && _acb_vec_bits(a, p) * p + _acb_vec_bits(b, q) * q + 10 < prec / 2) { if (prec >= 256 && acb_bits(z) < prec * 0.01) acb_hypgeom_pfq_sum_bs(s, t, a, p, b, q, z, n, prec); else acb_hypgeom_pfq_sum_rs(s, t, a, p, b, q, z, n, prec); } else if (prec >= 1500 && n >= 30 + 100000 / (prec - 1000)) { acb_hypgeom_pfq_sum_fme(s, t, a, p, b, q, z, n, prec); } else { /* With inexact complex numbers, prefer binary splitting as it reduces the wrapping effect. */ if (n > 8) acb_hypgeom_pfq_sum_bs(s, t, a, p, b, q, z, n, prec); else acb_hypgeom_pfq_sum_forward(s, t, a, p, b, q, z, n, prec); } } void acb_hypgeom_pfq_sum_invz(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, const acb_t zinv, slong n, slong prec) { if (n > 4 && prec >= 128 && _acb_vec_bits(a, p) * p + _acb_vec_bits(b, q) * q + 10 < prec / 2) { if (prec >= 256 && acb_bits(zinv) < prec * 0.01) acb_hypgeom_pfq_sum_bs_invz(s, t, a, p, b, q, zinv, n, prec); else acb_hypgeom_pfq_sum_rs(s, t, a, p, b, q, z, n, prec); } else if (prec >= 1500 && n >= 30 + 100000 / (prec - 1000)) { acb_hypgeom_pfq_sum_fme(s, t, a, p, b, q, z, n, prec); } else { /* With inexact complex numbers, binary splitting as it reduces the wrapping effect. */ if (n > 8) acb_hypgeom_pfq_sum_bs_invz(s, t, a, p, b, q, zinv, n, prec); else acb_hypgeom_pfq_sum_forward(s, t, a, p, b, q, z, n, prec); } } flint-3.1.3/src/acb_hypgeom/pfq_sum_bs.c000066400000000000000000000105641461254215100202070ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" /* [S(k+1)] = [ R(k) 0 ] [S(k)] [T(k+1)] [ 1 1 ] [T(k)] [S(k+1)] = [ P(k) / Q(k) 0 ] [S(k)] [T(k+1)] [ 1 1 ] [T(k)] 1 [ P(k) ] ---- [ ] Q(k) [ Q(k) Q(k) ] [[A2 0] [B2 C2]] . [[A1 0] [B1 C1]] = [[A1 A2 0] [A1 B2 + B1 C2 C1 C2] A1 B2 + B1 B2 = B2 (A1 + B1) -- use to save time? */ static void factor(acb_t A, acb_t tmp, acb_srcptr a, slong p, const acb_t z, slong k, slong prec) { slong i; if (p == 0) { if (z == NULL) acb_one(A); else acb_set(A, z); } else { acb_add_ui(A, a, k, prec); for (i = 1; i < p; i++) { acb_add_ui(tmp, a + i, k, prec); acb_mul(A, A, tmp, prec); } if (z != NULL) acb_mul(A, A, z, prec); } } static void bsplit(acb_t A1, acb_t B1, acb_t C1, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong aa, slong bb, slong prec, int invz) { if (bb - aa == 1) { factor(A1, B1, a, p, invz ? NULL : z, aa, prec); factor(C1, B1, b, q, invz ? z : NULL, aa, prec); /* acb_set(B1, C1); but we skip this */ } else { slong m; acb_t A2, B2, C2; acb_init(A2); acb_init(B2); acb_init(C2); m = aa + (bb - aa) / 2; bsplit(A1, B1, C1, a, p, b, q, z, aa, m, prec, invz); bsplit(A2, B2, C2, a, p, b, q, z, m, bb, prec, invz); if (bb - m == 1) /* B2 = C2 */ { if (m - aa == 1) acb_add(B2, A1, C1, prec); else acb_add(B2, A1, B1, prec); acb_mul(B1, B2, C2, prec); } else { if (m - aa == 1) acb_mul(B1, C1, C2, prec); else acb_mul(B1, B1, C2, prec); acb_addmul(B1, A1, B2, prec); } acb_mul(A1, A1, A2, prec); acb_mul(C1, C1, C2, prec); acb_clear(A2); acb_clear(B2); acb_clear(C2); } } void acb_hypgeom_pfq_sum_bs(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { acb_t u, v, w, tmp; if (n < 4) { acb_hypgeom_pfq_sum_forward(s, t, a, p, b, q, z, n, prec); return; } acb_init(u); acb_init(v); acb_init(w); acb_init(tmp); /* we compute to n-1 instead of n to avoid dividing by 0 in the denominator when computing a hypergeometric polynomial that terminates right before a pole */ bsplit(u, v, w, a, p, b, q, z, 0, n - 1, prec, 0); acb_add(s, u, v, prec); /* s = s + t */ acb_div(s, s, w, prec); /* split off last factor */ factor(t, tmp, a, p, z, n - 1, prec); acb_mul(u, u, t, prec); factor(t, tmp, b, q, NULL, n - 1, prec); acb_mul(w, w, t, prec); acb_div(t, u, w, prec); acb_clear(u); acb_clear(v); acb_clear(w); acb_clear(tmp); } void acb_hypgeom_pfq_sum_bs_invz(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { acb_t u, v, w, tmp; if (n < 4) { acb_init(u); acb_inv(u, z, prec); acb_hypgeom_pfq_sum_forward(s, t, a, p, b, q, u, n, prec); acb_clear(u); return; } acb_init(u); acb_init(v); acb_init(w); acb_init(tmp); /* we compute to n-1 instead of n to avoid dividing by 0 in the denominator when computing a hypergeometric polynomial that terminates right before a pole */ bsplit(u, v, w, a, p, b, q, z, 0, n - 1, prec, 1); acb_add(s, u, v, prec); /* s = s + t */ acb_div(s, s, w, prec); /* split off last factor */ factor(t, tmp, a, p, NULL, n - 1, prec); acb_mul(u, u, t, prec); factor(t, tmp, b, q, z, n - 1, prec); acb_mul(w, w, t, prec); acb_div(t, u, w, prec); acb_clear(u); acb_clear(v); acb_clear(w); acb_clear(tmp); } flint-3.1.3/src/acb_hypgeom/pfq_sum_fme.c000066400000000000000000000153351461254215100203530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb_poly.h" #include "acb_hypgeom.h" static void evaluate(acb_poly_t A, acb_srcptr a, slong p, const acb_t z, slong n, slong prec) { acb_poly_fit_length(A, p + 1); if (p == 1) { acb_add_ui(A->coeffs, a, n, prec); if (z != NULL) acb_mul(A->coeffs, A->coeffs, z, prec); } else if (p == 2) { acb_add(A->coeffs, a + 0, a + 1, prec); acb_add_ui(A->coeffs + 1, A->coeffs, 2 * n, prec); acb_add_ui(A->coeffs, A->coeffs, n, prec); acb_mul_ui(A->coeffs, A->coeffs, n, prec); acb_addmul(A->coeffs, a + 0, a + 1, prec); if (z != NULL) { acb_mul(A->coeffs, A->coeffs, z, prec); acb_mul(A->coeffs + 1, A->coeffs + 1, z, prec); } } else if (p == 3) { acb_t t, u; acb_init(t); acb_init(u); acb_add(t, a + 0, a + 1, prec); acb_add(t, t, a + 2, prec); acb_mul(u, a + 0, a + 1, prec); acb_mul(A->coeffs, u, a + 2, prec); acb_addmul(u, a + 0, a + 2, prec); acb_addmul(u, a + 1, a + 2, prec); /* (a0 + n)(a1 + n)(a2 + n) = a0 a1 a2 + (a0 a1 + a0 a2 + a1 a2) n + (a0 + a1 + a2) n^2 + n^3 (a0 a1 + a0 a2 + a1 a2) + 2 (a0 + a1 + a2) n + 3 n^2 (a0 + a1 + a2) + 3n 1 */ acb_addmul_ui(A->coeffs, u, n, prec); acb_addmul_ui(A->coeffs, t, n * n, prec); acb_add_ui(A->coeffs, A->coeffs, n * n * n, prec); acb_set(A->coeffs + 1, u); acb_addmul_ui(A->coeffs + 1, t, 2 * n, prec); acb_add_ui(A->coeffs + 1, A->coeffs + 1, 3 * n * n, prec); acb_add_ui(A->coeffs + 2, t, 3 * n, prec); if (z != NULL) { acb_mul(A->coeffs + 0, A->coeffs + 0, z, prec); acb_mul(A->coeffs + 1, A->coeffs + 1, z, prec); acb_mul(A->coeffs + 2, A->coeffs + 2, z, prec); } acb_clear(t); acb_clear(u); } else if (p != 0) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } if (z != NULL) acb_set(A->coeffs + p, z); else acb_one(A->coeffs + p); _acb_poly_set_length(A, p + 1); _acb_poly_normalise(A); } /* todo: do this using underscore methods */ static void bsplit(acb_poly_t A, acb_poly_t B, acb_poly_t C, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong an, slong bn, slong prec) { if (bn - an == 1) { evaluate(A, a, p, z, an, prec); evaluate(B, b, q, NULL, an, prec); acb_poly_set(C, B); } else if (bn - an == 2) /* inlined */ { acb_poly_t A2, B2; acb_poly_init(A2); acb_poly_init(B2); evaluate(A, a, p, z, an, prec); evaluate(A2, a, p, z, an + 1, prec); evaluate(B, b, q, NULL, an, prec); evaluate(B2, b, q, NULL, an + 1, prec); acb_poly_mul(C, B, B2, prec); acb_poly_set(B, C); acb_poly_mul(C, A, B2, prec); acb_poly_add(C, C, B, prec); acb_poly_mul(A2, A, A2, prec); acb_poly_swap(A, A2); acb_poly_clear(A2); acb_poly_clear(B2); } else { slong m = an + (bn - an) / 2; acb_poly_t A2, B2, C2, T; acb_poly_init(A2); acb_poly_init(B2); acb_poly_init(C2); acb_poly_init(T); bsplit(A, B, C, a, p, b, q, z, an, m, prec); bsplit(A2, B2, C2, a, p, b, q, z, m, bn, prec); acb_poly_mul(T, B2, C, prec); acb_poly_mul(C, A, C2, prec); acb_poly_add(C, C, T, prec); acb_poly_mul(C2, B, B2, prec); acb_poly_swap(B, C2); acb_poly_mul(B2, A, A2, prec); acb_poly_swap(A, B2); acb_poly_clear(A2); acb_poly_clear(B2); acb_poly_clear(C2); acb_poly_clear(T); } } void acb_hypgeom_pfq_sum_fme(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { acb_poly_t A, B, C; acb_ptr ks, As, Bs, Cs; acb_t u, v; acb_ptr * tree; slong i, k, m, w; /* we compute to n-1 instead of n to avoid dividing by 0 in the denominator when computing a hypergeometric polynomial that terminates right before a pole */ if (n > 4) { m = n_sqrt(n - 1) / 4; /* tuning parameter */ w = (n - 1) / FLINT_MAX(m, 1); } else { m = w = 0; } if (m < 1 || w < 1 || p > 3 || q > 3) { acb_hypgeom_pfq_sum_forward(s, t, a, p, b, q, z, n, prec); return; } acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(u); acb_init(v); ks = _acb_vec_init(w); As = _acb_vec_init(w); Bs = _acb_vec_init(w); Cs = _acb_vec_init(w); bsplit(A, B, C, a, p, b, q, z, 0, m, prec); for (i = 0; i < w; i++) acb_set_ui(ks + i, i * m); tree = _acb_poly_tree_alloc(w); _acb_poly_tree_build(tree, ks, w, prec); _acb_poly_evaluate_vec_fast_precomp(As, A->coeffs, A->length, tree, w, prec); _acb_poly_evaluate_vec_fast_precomp(Bs, B->coeffs, B->length, tree, w, prec); _acb_poly_evaluate_vec_fast_precomp(Cs, C->coeffs, C->length, tree, w, prec); _acb_poly_tree_free(tree, w); /* todo: use binary splitting here for improved numerical stability */ for (i = 1; i < w; i++) { acb_mul(Cs, Cs, Bs + i, prec); acb_addmul(Cs, As, Cs + i, prec); acb_mul(As, As, As + i, prec); acb_mul(Bs, Bs, Bs + i, prec); } acb_div(s, Cs, Bs, prec); acb_div(t, As, Bs, prec); for (k = w * m; k < n && !acb_is_zero(t); k++) { acb_add(s, s, t, prec); if (p > 0) { acb_add_ui(u, a, k, prec); for (i = 1; i < p; i++) { acb_add_ui(v, a + i, k, prec); acb_mul(u, u, v, prec); } acb_mul(t, t, u, prec); } if (q > 0) { acb_add_ui(u, b, k, prec); for (i = 1; i < q; i++) { acb_add_ui(v, b + i, k, prec); acb_mul(u, u, v, prec); } acb_div(t, t, u, prec); } acb_mul(t, t, z, prec); } acb_clear(u); acb_clear(v); _acb_vec_clear(ks, w); _acb_vec_clear(As, w); _acb_vec_clear(Bs, w); _acb_vec_clear(Cs, w); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); } flint-3.1.3/src/acb_hypgeom/pfq_sum_forward.c000066400000000000000000000025261461254215100212460ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_pfq_sum_forward(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { acb_t u, v; slong k, i; acb_init(u); acb_init(v); acb_zero(s); acb_one(t); for (k = 0; k < n && !acb_is_zero(t); k++) { acb_add(s, s, t, prec); if (p > 0) { acb_add_ui(u, a, k, prec); for (i = 1; i < p; i++) { acb_add_ui(v, a + i, k, prec); acb_mul(u, u, v, prec); } acb_mul(t, t, u, prec); } if (q > 0) { acb_add_ui(u, b, k, prec); for (i = 1; i < q; i++) { acb_add_ui(v, b + i, k, prec); acb_mul(u, u, v, prec); } acb_div(t, t, u, prec); } acb_mul(t, t, z, prec); } acb_clear(u); acb_clear(v); } flint-3.1.3/src/acb_hypgeom/pfq_sum_rs.c000066400000000000000000000050761461254215100202310ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_pfq_sum_rs(acb_t res, acb_t term, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { acb_ptr zpow; acb_t s, t, u; slong i, j, k, m; mag_t B, C; if (n == 0) { acb_zero(res); acb_one(term); return; } if (n < 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); m = n_sqrt(n); m = FLINT_MIN(m, 150); mag_init(B); mag_init(C); acb_init(s); acb_init(t); acb_init(u); zpow = _acb_vec_init(m + 1); _acb_vec_set_powers(zpow, z, m + 1, prec); mag_one(B); for (k = n; k >= 0; k--) { j = k % m; if (k < n) acb_add(s, s, zpow + j, prec); if (k > 0) { if (p > 0) { acb_add_ui(u, a, k - 1, prec); for (i = 1; i < p; i++) { acb_add_ui(t, a + i, k - 1, prec); acb_mul(u, u, t, prec); } if (k < n) acb_mul(s, s, u, prec); acb_get_mag(C, u); mag_mul(B, B, C); } if (q > 0) { acb_add_ui(u, b, k - 1, prec); for (i = 1; i < q; i++) { acb_add_ui(t, b + i, k - 1, prec); acb_mul(u, u, t, prec); } if (k < n) acb_div(s, s, u, prec); acb_get_mag_lower(C, u); mag_div(B, B, C); } if (j == 0 && k < n) { acb_mul(s, s, zpow + m, prec); } } } acb_get_mag(C, z); mag_pow_ui(C, C, n); mag_mul(B, B, C); acb_zero(term); if (_acb_vec_is_real(a, p) && _acb_vec_is_real(b, q) && acb_is_real(z)) arb_add_error_mag(acb_realref(term), B); else acb_add_error_mag(term, B); acb_set(res, s); mag_clear(B); mag_clear(C); acb_clear(s); acb_clear(t); acb_clear(u); _acb_vec_clear(zpow, m + 1); } flint-3.1.3/src/acb_hypgeom/rising_ui.c000066400000000000000000000025301461254215100200330ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_rising_ui(acb_t y, const acb_t x, ulong n, slong prec) { if (n < FLINT_MAX(prec, 100)) { acb_hypgeom_rising_ui_rec(y, x, n, prec); } else { acb_t t; acb_init(t); acb_add_ui(t, x, n, prec); acb_gamma(t, t, prec); acb_rgamma(y, x, prec); acb_mul(y, y, t, prec); acb_clear(t); } } void acb_hypgeom_rising(acb_t y, const acb_t x, const acb_t n, slong prec) { if (acb_is_int(n) && arf_sgn(arb_midref(acb_realref(n))) >= 0 && arf_cmpabs_ui(arb_midref(acb_realref(n)), FLINT_MAX(prec, 100)) < 0) { acb_hypgeom_rising_ui_rec(y, x, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), prec); } else { acb_t t; acb_init(t); acb_add(t, x, n, prec); acb_gamma(t, t, prec); acb_rgamma(y, x, prec); acb_mul(y, y, t, prec); acb_clear(t); } } flint-3.1.3/src/acb_hypgeom/rising_ui_bs.c000066400000000000000000000026651461254215100205300ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" static void bsplit(acb_t y, const acb_t x, ulong a, ulong b, slong prec) { if (b - a <= 4) { if (a == 0) { acb_hypgeom_rising_ui_forward(y, x, b, prec); } else { acb_add_ui(y, x, a, prec); acb_hypgeom_rising_ui_forward(y, y, b - a, prec); } } else { acb_t t, u; ulong m = a + (b - a) / 2; acb_init(t); acb_init(u); bsplit(t, x, a, m, prec); bsplit(u, x, m, b, prec); acb_mul(y, t, u, prec); acb_clear(t); acb_clear(u); } } void acb_hypgeom_rising_ui_bs(acb_t res, const acb_t x, ulong n, slong prec) { if (n <= 1) { if (n == 0) acb_one(res); else acb_set_round(res, x, prec); return; } { acb_t t; slong wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); acb_init(t); bsplit(t, x, 0, n, wp); acb_set_round(res, t, prec); acb_clear(t); } } flint-3.1.3/src/acb_hypgeom/rising_ui_forward.c000066400000000000000000000020211461254215100215520ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void _arb_increment_fast(arb_t x, slong prec); void acb_hypgeom_rising_ui_forward(acb_t res, const acb_t x, ulong n, slong prec) { acb_t t; ulong k; slong wp; if (n <= 1) { if (n == 0) acb_one(res); else acb_set_round(res, x, prec); return; } wp = prec + FLINT_BIT_COUNT(n); acb_init(t); acb_add_ui(t, x, 1, wp); acb_mul(res, x, t, (n == 2) ? prec : wp); for (k = 2; k < n; k++) { _arb_increment_fast(acb_realref(t), wp); acb_mul(res, res, t, k == (n - 1) ? prec : wp); } acb_clear(t); } flint-3.1.3/src/acb_hypgeom/rising_ui_jet.c000066400000000000000000000025401461254215100206760ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_rising_ui_jet(acb_ptr res, const acb_t x, ulong n, slong len, slong prec) { if (len == 1) { acb_hypgeom_rising_ui_rec(res, x, n, prec); } else if (n <= 7) { acb_hypgeom_rising_ui_jet_powsum(res, x, n, len, prec); } else if (len == 2) { if (n <= 30 || acb_bits(x) >= prec / 128) acb_hypgeom_rising_ui_jet_rs(res, x, n, 0, len, prec); else acb_hypgeom_rising_ui_jet_bs(res, x, n, len, prec); } else { if (n <= 20 || (n <= 200 && prec > 400 * n && acb_bits(x) >= prec / 4)) { acb_hypgeom_rising_ui_jet_powsum(res, x, n, len, prec); } else if (len >= 64 || (acb_bits(x) + 1 < prec / 1024 && n >= 32)) { acb_hypgeom_rising_ui_jet_bs(res, x, n, len, prec); } else { acb_hypgeom_rising_ui_jet_rs(res, x, n, 0, len, prec); } } } flint-3.1.3/src/acb_hypgeom/rising_ui_jet_bs.c000066400000000000000000000036371461254215100213720ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" #include "acb_hypgeom.h" static void bsplit(acb_ptr res, const acb_t x, ulong a, ulong b, slong trunc, slong prec) { trunc = FLINT_MIN(trunc, b - a + 1); if (b - a <= 12) { if (a == 0) { acb_hypgeom_rising_ui_jet_powsum(res, x, b - a, FLINT_MIN(trunc, b - a + 1), prec); } else { acb_t t; acb_init(t); acb_add_ui(t, x, a, prec); acb_hypgeom_rising_ui_jet_powsum(res, t, b - a, FLINT_MIN(trunc, b - a + 1), prec); acb_clear(t); } } else { acb_ptr L, R; slong len1, len2; slong m = a + (b - a) / 2; len1 = poly_pow_length(2, m - a, trunc); len2 = poly_pow_length(2, b - m, trunc); L = _acb_vec_init(len1 + len2); R = L + len1; bsplit(L, x, a, m, trunc, prec); bsplit(R, x, m, b, trunc, prec); _acb_poly_mullow(res, L, len1, R, len2, FLINT_MIN(trunc, len1 + len2 - 1), prec); _acb_vec_clear(L, len1 + len2); } } void acb_hypgeom_rising_ui_jet_bs(acb_ptr res, const acb_t x, ulong n, slong len, slong prec) { if (len == 0) return; if (len > n + 1) { _acb_vec_zero(res + n + 1, len - n - 1); len = n + 1; } if (len == n + 1) { acb_one(res + n); len = n; } if (n <= 1) { if (n == 1) acb_set_round(res, x, prec); return; } bsplit(res, x, 0, n, len, prec); } flint-3.1.3/src/acb_hypgeom/rising_ui_jet_powsum.c000066400000000000000000000101221461254215100223030ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fmpz_vec.h" #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_rising_ui_jet_powsum(acb_ptr res, const acb_t x, ulong n, slong len, slong prec) { slong i, j, k, wp; acb_ptr xpow; TMP_INIT; if (len == 0) return; if (len > n + 1) { _acb_vec_zero(res + n + 1, len - n - 1); len = n + 1; } if (len == n + 1) { acb_one(res + n); len = n; } if (n <= 1) { if (n == 1) acb_set_round(res, x, prec); return; } if (len == 1) { acb_hypgeom_rising_ui_rs(res, x, n, 0, prec); return; } if (n == 2) { acb_mul_2exp_si(res + 1, x, 1); acb_add_ui(res + 1, res + 1, 1, prec); acb_mul(res, x, x, prec + 4); acb_add(res, res, x, prec); return; } if (n <= 12 || (FLINT_BITS == 64 && n <= 20)) { mp_ptr c; TMP_START; wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); c = TMP_ALLOC(sizeof(mp_limb_t) * (n + 1) * len); _nmod_vec_zero(c, (n + 1) * len); c[0] = 0; c[1] = 1; c[(n + 1) + 0] = 1; for (i = 2; i <= n; i++) { for (j = FLINT_MIN(len - 1, i); j >= 0; j--) { slong ln, pos; ln = i + 1 - j; pos = (n + 1) * j; if (i == j) { c[pos] = 1; } else { c[pos + ln - 1] = c[pos + ln - 2]; for (k = ln - 2; k >= 1; k--) c[pos + k] = c[pos + k] * (i - 1) + c[pos + k - 1]; c[pos + 0] *= (i - 1); if (j != 0) for (k = ln - 1; k >= 0; k--) c[pos + k] += c[pos - (n + 1) + k]; } } } xpow = _acb_vec_init(n + 1); _acb_vec_set_powers(xpow, x, n + 1, wp); acb_dot_ui(res, NULL, 0, xpow + 1, 1, c + 1, 1, n, prec); for (i = 1; i < len; i++) acb_dot_ui(res + i, NULL, 0, xpow, 1, c + (n + 1) * i, 1, n + 1 - i, prec); _acb_vec_clear(xpow, n + 1); TMP_END; } else { fmpz * c; wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); c = _fmpz_vec_init((n + 1) * len); fmpz_one(c + 1); fmpz_one(c + (n + 1) + 0); for (i = 2; i <= n; i++) { for (j = FLINT_MIN(len - 1, i); j >= 0; j--) { slong ln, pos; ln = i + 1 - j; pos = (n + 1) * j; if (i == j) { fmpz_one(c + pos); } else { fmpz_set(c + pos + ln - 1, c + pos + ln - 2); for (k = ln - 2; k >= 1; k--) { fmpz_mul_ui(c + pos + k, c + pos + k, i - 1); fmpz_add(c + pos + k, c + pos + k, c + pos + k - 1); } fmpz_mul_ui(c + pos + 0, c + pos + 0, i - 1); if (j != 0) for (k = ln - 1; k >= 0; k--) fmpz_add(c + pos + k, c + pos + k, c + pos - (n + 1) + k); } } } xpow = _acb_vec_init(n + 1); _acb_vec_set_powers(xpow, x, n + 1, wp); acb_dot_fmpz(res, NULL, 0, xpow + 1, 1, c + 1, 1, n, prec); for (i = 1; i < len; i++) acb_dot_fmpz(res + i, NULL, 0, xpow, 1, c + (n + 1) * i, 1, n + 1 - i, prec); _acb_vec_clear(xpow, n + 1); _fmpz_vec_clear(c, (n + 1) * len); } } flint-3.1.3/src/acb_hypgeom/rising_ui_jet_rs.c000066400000000000000000000105161461254215100214040ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "acb_poly.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif void acb_hypgeom_rising_ui_jet_rs(acb_ptr res, const acb_t x, ulong n, ulong m, slong len, slong prec) { slong i, j, k, l, m0, xmlen, tlen, ulen, climbs, climbs_max, wp; acb_ptr tmp, xpow; acb_ptr t, u; mp_ptr c; TMP_INIT; if (len == 0) return; if (len > n + 1) { _acb_vec_zero(res + n + 1, len - n - 1); len = n + 1; } if (len == n + 1) { acb_one(res + n); len = n; } if (n <= 1) { if (n == 1) acb_set_round(res, x, prec); return; } if (len == 1) { acb_hypgeom_rising_ui_rs(res, x, n, m, prec); return; } TMP_START; if (m == 0) { if (n <= 7) m = n; else if (n <= 12) m = (n + 1) / 2; else if (n <= 32) m = (n + 2) / 3; else { m0 = n_sqrt(n); m = 8 + 0.5 * pow(prec, 0.4); m = FLINT_MIN(m, m0); m = FLINT_MIN(m, 64); } } wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); climbs_max = FLINT_BIT_COUNT(n - 1) * m; c = TMP_ALLOC(sizeof(mp_limb_t) * climbs_max * m); /* length of (x+t)^m */ xmlen = FLINT_MIN(len, m + 1); tmp = _acb_vec_init(2 * len + (m + 1) * xmlen); t = tmp; u = tmp + len; xpow = tmp + 2 * len; _acb_vec_set_powers(xpow, x, m + 1, wp); tlen = 1; /* First derivatives */ for (i = 1; i <= m; i++) acb_mul_ui(xpow + (m + 1) + i, xpow + i - 1, i, wp); /* Higher derivatives if we need them */ if (len >= 3) { fmpz * f = _fmpz_vec_init(len); fmpz_one(f + 0); fmpz_one(f + 1); for (i = 2; i <= m; i++) { for (j = FLINT_MIN(xmlen - 1, i + 1); j >= 1; j--) fmpz_add(f + j, f + j, f + j - 1); for (j = 2; j < FLINT_MIN(xmlen, i + 1); j++) acb_mul_fmpz(xpow + (m + 1) * j + i, xpow + i - j, f + j, wp); } _fmpz_vec_clear(f, len); } for (k = 0; k < n; k += m) { l = FLINT_MIN(m, n - k); climbs = FLINT_BIT_COUNT(k + l - 1) * l; climbs = (climbs + FLINT_BITS - 1) / FLINT_BITS; ulen = FLINT_MIN(len, l + 1); if (l == 1) { acb_add_ui(u, x, k, wp); acb_one(u + 1); } else { if (climbs == 1) { _arb_hypgeom_rising_coeffs_1(c, k, l); for (j = 0; j < ulen; j++) acb_dot_ui(u + j, xpow + (m + 1) * j + l, 0, xpow + (m + 1) * j + j, 1, c + j, 1, l - j, wp); } else if (climbs == 2) { _arb_hypgeom_rising_coeffs_2(c, k, l); for (j = 0; j < ulen; j++) acb_dot_uiui(u + j, xpow + (m + 1) * j + l, 0, xpow + (m + 1) * j + j, 1, c + 2 * j, 1, l - j, wp); } else { fmpz * f = (fmpz *) c; for (i = 0; i < l; i++) fmpz_init(f + i); _arb_hypgeom_rising_coeffs_fmpz(f, k, l); for (j = 0; j < ulen; j++) acb_dot_fmpz(u + j, xpow + (m + 1) * j + l, 0, xpow + (m + 1) * j + j, 1, f + j, 1, l - j, wp); for (i = 0; i < l; i++) fmpz_clear(f + i); } } if (k == 0) { tlen = ulen; _acb_vec_swap(t, u, ulen); } else { _acb_poly_mullow(res, t, tlen, u, ulen, FLINT_MIN(len, tlen + ulen - 1), wp); tlen = FLINT_MIN(len, tlen + ulen - 1); _acb_vec_swap(t, res, tlen); } } _acb_vec_set_round(res, t, len, prec); _acb_vec_clear(tmp, 2 * len + (m + 1) * xmlen); TMP_END; } flint-3.1.3/src/acb_hypgeom/rising_ui_rec.c000066400000000000000000000024241461254215100206660ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void acb_hypgeom_rising_ui_rec(acb_t res, const acb_t x, ulong n, slong prec) { if (n <= 1) { if (n == 0) acb_one(res); else acb_set_round(res, x, prec); return; } if (arb_is_zero(acb_imagref(x))) { arb_hypgeom_rising_ui_rec(acb_realref(res), acb_realref(x), n, prec); arb_zero(acb_imagref(res)); return; } if (n == 2 && prec <= 1024) { if (res != x) acb_set(res, x); acb_addmul(res, x, x, prec); return; } if (n <= 5 && prec <= 512) { acb_hypgeom_rising_ui_forward(res, x, n, prec); } else { if (n >= 20 && acb_bits(x) < prec / 8) acb_hypgeom_rising_ui_bs(res, x, n, prec); else acb_hypgeom_rising_ui_rs(res, x, n, 0, prec); } } flint-3.1.3/src/acb_hypgeom/rising_ui_rs.c000066400000000000000000000053771461254215100205530ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif void acb_hypgeom_rising_ui_rs(acb_t res, const acb_t x, ulong n, ulong m, slong prec) { slong i, k, l, m0, climbs, climbs_max, wp; acb_ptr xpow; acb_t t, u; mp_ptr c; TMP_INIT; if (n <= 1) { if (n == 0) acb_one(res); else acb_set_round(res, x, prec); return; } TMP_START; if (m == 0 || m == -1) { if (n <= 6) m = 2; else if (n <= 16) m = 4; else if (n <= 40) m = 6; else { m0 = n_sqrt(n); m = 8 + 0.27 * pow(1.5 * FLINT_MAX(0, prec - 1024), 0.4); m = FLINT_MIN(m, m0); m = FLINT_MIN(m, 64); } } wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); climbs_max = FLINT_BIT_COUNT(n - 1) * m; c = TMP_ALLOC(sizeof(mp_limb_t) * climbs_max * m); xpow = _acb_vec_init(m + 1); _acb_vec_set_powers(xpow, x, m + 1, wp); acb_init(t); acb_init(u); for (k = 0; k < n; k += m) { l = FLINT_MIN(m, n - k); climbs = FLINT_BIT_COUNT(k + l - 1) * l; climbs = (climbs + FLINT_BITS - 1) / FLINT_BITS; /* assumes l >= 2 */ if (l == 1) { acb_add_ui(u, x, k, wp); } else { if (climbs == 1) { _arb_hypgeom_rising_coeffs_1(c, k, l); acb_dot_ui(u, xpow + l, 0, xpow, 1, c, 1, l, wp); } else if (climbs == 2) { _arb_hypgeom_rising_coeffs_2(c, k, l); acb_dot_uiui(u, xpow + l, 0, xpow, 1, c, 1, l, wp); } else { fmpz * f = (fmpz *) c; for (i = 0; i < l; i++) fmpz_init(f + i); _arb_hypgeom_rising_coeffs_fmpz(f, k, l); acb_dot_fmpz(u, xpow + l, 0, xpow, 1, f, 1, l, wp); for (i = 0; i < l; i++) fmpz_clear(f + i); } } if (k == 0) acb_swap(t, u); else acb_mul(t, t, u, wp); } acb_set_round(res, t, prec); acb_clear(t); acb_clear(u); _acb_vec_clear(xpow, m + 1); TMP_END; } flint-3.1.3/src/acb_hypgeom/shi.c000066400000000000000000000011321461254215100166230ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_shi(acb_t res, const acb_t z, slong prec) { acb_mul_onei(res, z); acb_hypgeom_si(res, res, prec); acb_mul_onei(res, res); acb_neg(res, res); } flint-3.1.3/src/acb_hypgeom/shi_series.c000066400000000000000000000033701461254215100202030ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_shi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { acb_t c; acb_init(c); acb_hypgeom_shi(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else if (len == 2) { acb_mul_onei(g, h); acb_sinc(g, g, prec); acb_mul(g + 1, g, h + 1, prec); } else { acb_ptr t, u; slong i; t = _acb_vec_init(len - 1); u = _acb_vec_init(hlen); /* Shi(h(x)) = integral(h'(x) sinc(i h(x))) */ for (i = 0; i < hlen; i++) acb_mul_onei(u + i, h + i); _acb_poly_sinc_series(t, u, hlen, len - 1, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_mullow(g, t, len - 1, u, hlen - 1, len - 1, prec); _acb_poly_integral(g, g, len, prec); _acb_vec_clear(t, len - 1); _acb_vec_clear(u, hlen); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_shi_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, len); _acb_hypgeom_shi_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/si.c000066400000000000000000000060451461254215100164630ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void acb_hypgeom_si_asymp(acb_t res, const acb_t z, slong prec) { acb_t t, u, w, v, one; acb_init(t); acb_init(u); acb_init(w); acb_init(v); acb_init(one); acb_one(one); acb_mul_onei(w, z); /* u = U(1,1,iz) */ acb_hypgeom_u_asymp(u, one, one, w, -1, prec); /* v = e^(-iz) */ acb_neg(v, w); acb_exp(v, v, prec); acb_mul(t, u, v, prec); if (acb_is_real(z)) { arb_div(acb_realref(t), acb_realref(t), acb_realref(z), prec); arb_zero(acb_imagref(t)); acb_neg(t, t); } else { /* u = U(1,1,-iz) */ acb_neg(w, w); acb_hypgeom_u_asymp(u, one, one, w, -1, prec); acb_inv(v, v, prec); acb_addmul(t, u, v, prec); acb_div(t, t, z, prec); acb_mul_2exp_si(t, t, -1); acb_neg(t, t); } if (arb_is_zero(acb_realref(z))) { /* the function is imaginary */ arb_zero(acb_realref(t)); } else if (arb_is_positive(acb_realref(z))) { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_add(acb_realref(t), acb_realref(t), acb_realref(u), prec); } else if (arb_is_negative(acb_realref(z))) { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_sub(acb_realref(t), acb_realref(t), acb_realref(u), prec); } else { /* add [-pi,pi]/2 */ acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_add_error(acb_imagref(t), acb_realref(u)); } acb_swap(res, t); acb_clear(t); acb_clear(u); acb_clear(w); acb_clear(v); acb_clear(one); } void acb_hypgeom_si_1f2(acb_t res, const acb_t z, slong prec) { acb_t a, t; acb_struct b[3]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(b + 2); acb_init(t); acb_one(a); acb_mul_2exp_si(a, a, -1); acb_set_ui(b, 3); acb_mul_2exp_si(b, b, -1); acb_set(b + 1, b); acb_one(b + 2); acb_mul(t, z, z, prec); acb_mul_2exp_si(t, t, -2); acb_neg(t, t); acb_hypgeom_pfq_direct(t, a, 1, b, 3, t, -1, prec); acb_mul(t, t, z, prec); acb_swap(res, t); acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(b + 2); acb_clear(t); } void acb_hypgeom_si(acb_t res, const acb_t z, slong prec) { if (acb_is_real(z) && arb_is_finite(acb_realref(z))) { arb_hypgeom_si(acb_realref(res), acb_realref(z), prec); arb_zero(acb_imagref(res)); return; } if (acb_hypgeom_u_use_asymp(z, prec)) acb_hypgeom_si_asymp(res, z, prec); else acb_hypgeom_si_1f2(res, z, prec); } flint-3.1.3/src/acb_hypgeom/si_series.c000066400000000000000000000032011461254215100200240ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_hypgeom_si_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { acb_t c; acb_init(c); acb_hypgeom_si(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _acb_vec_zero(g + 1, len - 1); } else if (len == 2) { acb_sinc(g, h, prec); acb_mul(g + 1, g, h + 1, prec); } else { acb_ptr t, u; t = _acb_vec_init(len - 1); u = _acb_vec_init(hlen - 1); /* Si(h(x)) = integral(h'(x) sinc(h(x))) */ _acb_poly_sinc_series(t, h, hlen, len - 1, prec); _acb_poly_derivative(u, h, hlen, prec); _acb_poly_mullow(g, t, len - 1, u, hlen - 1, len - 1, prec); _acb_poly_integral(g, g, len, prec); _acb_vec_clear(t, len - 1); _acb_vec_clear(u, hlen - 1); } acb_swap(g, c); acb_clear(c); } void acb_hypgeom_si_series(acb_poly_t g, const acb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, len); _acb_hypgeom_si_series(g->coeffs, h->coeffs, hlen, len, prec); _acb_poly_set_length(g, len); _acb_poly_normalise(g); } flint-3.1.3/src/acb_hypgeom/spherical_y.c000066400000000000000000000035321461254215100203500ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_spherical_y(acb_t res, slong n, slong m, const acb_t theta, const acb_t phi, slong prec) { acb_t t, u; if (n < 0) { if (m <= n) { acb_zero(res); return; } n = -1-n; } if (m > n || m < -n) { acb_zero(res); return; } if (n > WORD_MAX / 4) { acb_indeterminate(res); return; } acb_init(t); acb_init(u); acb_sin_cos(t, u, theta, prec); /* P_n^m(cos(theta)) */ acb_hypgeom_legendre_p_uiui_rec(u, n, FLINT_ABS(m), u, prec); acb_pow_ui(t, t, FLINT_ABS(m), prec); acb_mul(t, t, u, prec); /* exp(i m phi) */ acb_mul_onei(u, phi); acb_mul_si(u, u, m, prec); acb_exp(u, u, prec); if (m < 0 && m % 2) acb_neg(u, u); acb_mul(t, t, u, prec); /* sqrt((2n+1)/(4pi) (n-m)!/(n+m)!) */ arb_fac_ui(acb_realref(u), n - FLINT_ABS(m), prec); arb_fac_ui(acb_imagref(u), n + FLINT_ABS(m), prec); arb_mul_ui(acb_realref(u), acb_realref(u), 2 * n + 1, prec); arb_div(acb_realref(u), acb_realref(u), acb_imagref(u), prec); arb_const_pi(acb_imagref(u), prec); arb_div(acb_realref(u), acb_realref(u), acb_imagref(u), prec); arb_mul_2exp_si(acb_realref(u), acb_realref(u), -2); arb_sqrt(acb_realref(u), acb_realref(u), prec); acb_mul_arb(t, t, acb_realref(u), prec); acb_set(res, t); acb_clear(t); acb_clear(u); } flint-3.1.3/src/acb_hypgeom/test/000077500000000000000000000000001461254215100166565ustar00rootroot00000000000000flint-3.1.3/src/acb_hypgeom/test/main.c000066400000000000000000000116061461254215100177520ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-0f1.c" #include "t-2f1.c" #include "t-2f1_continuation.c" #include "t-airy_bound.c" #include "t-airy.c" #include "t-airy_series.c" #include "t-bessel_i.c" #include "t-bessel_j.c" #include "t-bessel_k.c" #include "t-bessel_y.c" #include "t-beta_lower.c" #include "t-beta_lower_series.c" #include "t-chebyshev_t.c" #include "t-chebyshev_u.c" #include "t-chi.c" #include "t-chi_series.c" #include "t-ci.c" #include "t-ci_series.c" #include "t-coulomb.c" #include "t-coulomb_series.c" #include "t-dilog.c" #include "t-ei.c" #include "t-ei_series.c" #include "t-erf.c" #include "t-erfc.c" #include "t-erfc_series.c" #include "t-erfi_series.c" #include "t-erf_series.c" #include "t-fresnel.c" #include "t-fresnel_series.c" #include "t-gamma_lower.c" #include "t-gamma_lower_series.c" #include "t-gamma_stirling_sum.c" #include "t-gamma_taylor.c" #include "t-gamma_upper.c" #include "t-gamma_upper_series.c" #include "t-gegenbauer_c.c" #include "t-hermite_h.c" #include "t-jacobi_p.c" #include "t-laguerre_l.c" #include "t-legendre_p.c" #include "t-legendre_q.c" #include "t-lgamma.c" #include "t-li_series.c" #include "t-log_rising_ui.c" #include "t-log_rising_ui_jet.c" #include "t-m.c" #include "t-pfq.c" #include "t-pfq_series_direct.c" #include "t-pfq_series_sum_bs.c" #include "t-pfq_series_sum_rs.c" #include "t-pfq_sum_bs.c" #include "t-pfq_sum_fme.c" #include "t-pfq_sum_invz.c" #include "t-pfq_sum_rs.c" #include "t-rising_ui.c" #include "t-rising_ui_jet.c" #include "t-shi_series.c" #include "t-si.c" #include "t-si_series.c" #include "t-spherical_y.c" #include "t-u_asymp.c" #include "t-u.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_hypgeom_0f1), TEST_FUNCTION(acb_hypgeom_2f1), TEST_FUNCTION(acb_hypgeom_2f1_continuation), TEST_FUNCTION(acb_hypgeom_airy_bound), TEST_FUNCTION(acb_hypgeom_airy), TEST_FUNCTION(acb_hypgeom_airy_series), TEST_FUNCTION(acb_hypgeom_bessel_i), TEST_FUNCTION(acb_hypgeom_bessel_j), TEST_FUNCTION(acb_hypgeom_bessel_k), TEST_FUNCTION(acb_hypgeom_bessel_y), TEST_FUNCTION(acb_hypgeom_beta_lower), TEST_FUNCTION(acb_hypgeom_beta_lower_series), TEST_FUNCTION(acb_hypgeom_chebyshev_t), TEST_FUNCTION(acb_hypgeom_chebyshev_u), TEST_FUNCTION(acb_hypgeom_chi), TEST_FUNCTION(acb_hypgeom_chi_series), TEST_FUNCTION(acb_hypgeom_ci), TEST_FUNCTION(acb_hypgeom_ci_series), TEST_FUNCTION(acb_hypgeom_coulomb), TEST_FUNCTION(acb_hypgeom_coulomb_series), TEST_FUNCTION(acb_hypgeom_dilog), TEST_FUNCTION(acb_hypgeom_ei), TEST_FUNCTION(acb_hypgeom_ei_series), TEST_FUNCTION(acb_hypgeom_erf), TEST_FUNCTION(acb_hypgeom_erfc), TEST_FUNCTION(acb_hypgeom_erfc_series), TEST_FUNCTION(acb_hypgeom_erfi_series), TEST_FUNCTION(acb_hypgeom_erf_series), TEST_FUNCTION(acb_hypgeom_fresnel), TEST_FUNCTION(acb_hypgeom_fresnel_series), TEST_FUNCTION(acb_hypgeom_gamma_lower), TEST_FUNCTION(acb_hypgeom_gamma_lower_series), TEST_FUNCTION(acb_hypgeom_gamma_stirling_sum), TEST_FUNCTION(acb_hypgeom_gamma_taylor), TEST_FUNCTION(acb_hypgeom_gamma_upper), TEST_FUNCTION(acb_hypgeom_gamma_upper_series), TEST_FUNCTION(acb_hypgeom_gegenbauer_c), TEST_FUNCTION(acb_hypgeom_hermite_h), TEST_FUNCTION(acb_hypgeom_jacobi_p), TEST_FUNCTION(acb_hypgeom_laguerre_l), TEST_FUNCTION(acb_hypgeom_legendre_p), TEST_FUNCTION(acb_hypgeom_legendre_q), TEST_FUNCTION(acb_hypgeom_lgamma), TEST_FUNCTION(acb_hypgeom_li_series), TEST_FUNCTION(acb_hypgeom_log_rising_ui), TEST_FUNCTION(acb_hypgeom_log_rising_ui_jet), TEST_FUNCTION(acb_hypgeom_m), TEST_FUNCTION(acb_hypgeom_pfq), TEST_FUNCTION(acb_hypgeom_pfq_series_direct), TEST_FUNCTION(acb_hypgeom_pfq_series_sum_bs), TEST_FUNCTION(acb_hypgeom_pfq_series_sum_rs), TEST_FUNCTION(acb_hypgeom_pfq_sum_bs), TEST_FUNCTION(acb_hypgeom_pfq_sum_fme), TEST_FUNCTION(acb_hypgeom_pfq_sum_invz), TEST_FUNCTION(acb_hypgeom_pfq_sum_rs), TEST_FUNCTION(acb_hypgeom_rising_ui), TEST_FUNCTION(acb_hypgeom_rising_ui_jet), TEST_FUNCTION(acb_hypgeom_shi_series), TEST_FUNCTION(acb_hypgeom_si), TEST_FUNCTION(acb_hypgeom_si_series), TEST_FUNCTION(acb_hypgeom_spherical_y), TEST_FUNCTION(acb_hypgeom_u_asymp), TEST_FUNCTION(acb_hypgeom_u) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_hypgeom/test/t-0f1.c000066400000000000000000000052571461254215100176620ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_0f1, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, z, w1, w2; slong prec1, prec2; int regularized, ebits; acb_init(a); acb_init(z); acb_init(w1); acb_init(w2); prec1 = 2 + n_randint(state, 700); prec2 = 2 + n_randint(state, 700); if (n_randint(state, 5) == 0) ebits = 100; else ebits = 10; acb_randtest_param(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest_param(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); regularized = n_randint(state, 2); switch (n_randint(state, 3)) { case 0: acb_hypgeom_0f1_asymp(w1, a, z, regularized, prec1); break; case 1: acb_hypgeom_0f1_direct(w1, a, z, regularized, prec1); break; default: acb_hypgeom_0f1(w1, a, z, regularized, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_0f1_asymp(w2, a, z, regularized, prec2); break; case 1: acb_hypgeom_0f1_direct(w2, a, z, regularized, prec2); break; default: acb_hypgeom_0f1(w2, a, z, regularized, prec2); } if (!acb_overlaps(w1, w2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(z); acb_clear(w1); acb_clear(w2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-2f1.c000066400000000000000000000126341461254215100176610ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_2f1, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, z, w1, w2, t; slong prec1, prec2; int reg1, reg2, ebits; int alg1, alg2; int flags1, flags2; acb_init(a); acb_init(b); acb_init(c); acb_init(z); acb_init(w1); acb_init(w2); acb_init(t); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); if (n_randint(state, 20) == 0) ebits = 30; else ebits = 5; flags1 = flags2 = 0; switch (n_randint(state, 3)) { case 0: acb_set_si(a, n_randint(state, 500)); acb_set_si(b, n_randint(state, 500)); acb_set_si(c, n_randint(state, 10)); break; case 1: acb_set_si(a, n_randint(state, 200) - 100); acb_set_si(b, n_randint(state, 200) - 100); acb_set_si(c, n_randint(state, 200) - 100); break; default: acb_randtest_param(a, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest_param(b, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest_param(c, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); } /* TODO: test other cases (a-c, b-c), once implemented. */ if (n_randint(state, 10) == 0) { acb_add_si(a, b, n_randint(state, 20) - 10, prec1); flags1 |= ACB_HYPGEOM_2F1_AB; if (n_randint(state, 2)) flags2 |= ACB_HYPGEOM_2F1_AB; } if (n_randint(state, 10) == 0) { acb_add(c, a, b, prec1); acb_add_si(c, c, n_randint(state, 20) - 10, prec1); flags1 |= ACB_HYPGEOM_2F1_ABC; if (n_randint(state, 2)) flags2 |= ACB_HYPGEOM_2F1_ABC; } acb_randtest_param(z, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest(w1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest(w2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); if (n_randint(state, 2)) arb_zero(acb_imagref(z)); reg1 = n_randint(state, 2); reg2 = n_randint(state, 2); alg1 = n_randint(state, 10); alg2 = n_randint(state, 10); if (reg1) flags1 |= ACB_HYPGEOM_2F1_REGULARIZED; if (reg2) flags2 |= ACB_HYPGEOM_2F1_REGULARIZED; switch (alg1) { case 0: acb_hypgeom_2f1_direct(w1, a, b, c, z, reg1, prec1); break; case 1: case 2: case 3: case 4: case 5: acb_hypgeom_2f1_transform(w1, a, b, c, z, flags1, alg1, prec1); break; case 6: acb_hypgeom_2f1_corner(w1, a, b, c, z, reg1, prec1); break; default: acb_hypgeom_2f1(w1, a, b, c, z, flags1, prec1); } switch (alg2) { case 0: acb_hypgeom_2f1_direct(w2, a, b, c, z, reg2, prec2); break; case 1: case 2: case 3: case 4: case 5: acb_hypgeom_2f1_transform(w2, a, b, c, z, flags2, alg2, prec2); break; case 6: acb_hypgeom_2f1_corner(w2, a, b, c, z, reg2, prec2); break; default: acb_hypgeom_2f1(w2, a, b, c, z, flags2, prec2); } if (reg1 != reg2) { acb_rgamma(t, c, prec2); if (reg1) acb_mul(w2, w2, t, prec2); else acb_mul(w1, w1, t, prec2); } if (!acb_overlaps(w1, w2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("alg1 = %d, alg2 = %d\n\n", alg1, alg2); flint_printf("reg1 = %d, reg2 = %d\n\n", reg1, reg2); flint_printf("flags1 = %d, flags2 = %d\n\n", flags1, flags2); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z); acb_clear(w1); acb_clear(w2); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-2f1_continuation.c000066400000000000000000000123621461254215100224510ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_2f1_continuation, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c, z1, z2, f1, f2, g1, g2, h1, h2, aa, bb, cc; mag_t d0, d1, dt; slong prec; int regularized, ebits; acb_init(a); acb_init(b); acb_init(c); acb_init(aa); acb_init(bb); acb_init(cc); acb_init(z1); acb_init(z2); acb_init(f1); acb_init(f2); acb_init(g1); acb_init(g2); acb_init(h1); acb_init(h2); mag_init(d0); mag_init(d1); mag_init(dt); prec = 2 + n_randint(state, 300); ebits = 10; regularized = n_randint(state, 2); acb_randtest_param(a, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2)); acb_randtest_param(b, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2)); acb_randtest_param(c, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2)); acb_randtest(h1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest(h2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); do { int left, upper, lower; acb_randtest_param(z1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest_param(z2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); /* we test both convergent and non-convergent cases, but try to be more efficient by generating more convergent cases */ if (n_randint(state, 2)) { acb_sub_ui(aa, z1, 1, prec); acb_get_mag(d0, z1); acb_get_mag(d1, aa); acb_get_mag(dt, z2); if (mag_cmp(dt, d0) >= 0 || mag_cmp(dt, d1) >= 0) continue; } acb_add(z2, z1, z2, prec); /* for the test, don't cross the branch cut */ acb_sub_ui(aa, z1, 1, prec); acb_sub_ui(bb, z2, 1, prec); left = arb_is_negative(acb_realref(aa)) && arb_is_negative(acb_realref(bb)); upper = arb_is_positive(acb_imagref(aa)) && arb_is_positive(acb_imagref(bb)); lower = arb_is_nonpositive(acb_imagref(aa)) && arb_is_nonpositive(acb_imagref(bb)); if (left || upper || lower) break; } while (1); acb_add_ui(aa, a, 1, prec); acb_add_ui(bb, b, 1, prec); acb_add_ui(cc, c, 1, prec); acb_hypgeom_2f1(f1, a, b, c, z1, regularized, prec); acb_hypgeom_2f1(f2, aa, bb, cc, z1, regularized, prec); acb_mul(f2, f2, a, prec); acb_mul(f2, f2, b, prec); if (!regularized) acb_div(f2, f2, c, prec); acb_hypgeom_2f1_continuation(h1, h2, a, b, c, z1, z2, f1, f2, prec); if (acb_is_finite(h1) || acb_is_finite(h2)) { acb_hypgeom_2f1(g1, a, b, c, z2, regularized, prec); acb_hypgeom_2f1(g2, aa, bb, cc, z2, regularized, prec); acb_mul(g2, g2, a, prec); acb_mul(g2, g2, b, prec); if (!regularized) acb_div(g2, g2, c, prec); if (!acb_overlaps(g1, h1) || !acb_overlaps(g2, h2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("regularized = %d, prec = %wd\n\n", regularized, prec); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_printf("F(a,b,c,z1) and F'(a,b,c,z1):\n"); flint_printf("f1 = "); acb_printd(f1, 30); flint_printf("\n\n"); flint_printf("f2 = "); acb_printd(f2, 30); flint_printf("\n\n"); flint_printf("F(a,b,c,z2) and F'(a,b,c,z2):\n"); flint_printf("g1 = "); acb_printd(g1, 30); flint_printf("\n\n"); flint_printf("g2 = "); acb_printd(g2, 30); flint_printf("\n\n"); flint_printf("Computed F and F':\n"); flint_printf("h1 = "); acb_printd(h1, 30); flint_printf("\n\n"); flint_printf("h2 = "); acb_printd(h2, 30); flint_printf("\n\n"); flint_abort(); } } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(aa); acb_clear(bb); acb_clear(cc); acb_clear(z1); acb_clear(z2); acb_clear(f1); acb_clear(f2); acb_clear(g1); acb_clear(g2); acb_clear(h1); acb_clear(h2); mag_clear(d0); mag_clear(d1); mag_clear(dt); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-airy.c000066400000000000000000000134651461254215100202400ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_airy, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z, t, w; acb_t ai1, aip1, bi1, bip1; acb_t ai2, aip2, bi2, bip2; slong n1, n2, prec1, prec2; unsigned int mask; acb_init(z); acb_init(t); acb_init(w); acb_init(ai1); acb_init(aip1); acb_init(bi1); acb_init(bip1); acb_init(ai2); acb_init(aip2); acb_init(bi2); acb_init(bip2); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); n1 = n_randint(state, 300); n2 = n_randint(state, 300); acb_randtest_param(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_param(t, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_add(z, z, t, 1000); acb_sub(z, z, t, 1000); switch (n_randint(state, 3)) { case 0: acb_hypgeom_airy_direct(ai1, aip1, bi1, bip1, z, n1, prec1); break; case 1: acb_hypgeom_airy_asymp(ai1, aip1, bi1, bip1, z, n1, prec1); break; default: acb_hypgeom_airy(ai1, aip1, bi1, bip1, z, prec1); break; } switch (n_randint(state, 3)) { case 0: acb_hypgeom_airy_direct(ai2, aip2, bi2, bip2, z, n2, prec2); break; case 1: acb_hypgeom_airy_asymp(ai2, aip2, bi2, bip2, z, n2, prec2); break; default: acb_hypgeom_airy(ai2, aip2, bi2, bip2, z, prec2); break; } if (!acb_overlaps(ai1, ai2)) { flint_printf("FAIL: consistency (Ai)\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("ai1 = "); acb_printd(ai1, 30); flint_printf("\n\n"); flint_printf("ai2 = "); acb_printd(ai2, 30); flint_printf("\n\n"); flint_abort(); } if (!acb_overlaps(aip1, aip2)) { flint_printf("FAIL: consistency (Ai')\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("aip1 = "); acb_printd(aip1, 30); flint_printf("\n\n"); flint_printf("aip2 = "); acb_printd(aip2, 30); flint_printf("\n\n"); flint_abort(); } if (!acb_overlaps(bi1, bi2)) { flint_printf("FAIL: consistency (Bi)\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("bi1 = "); acb_printd(bi1, 30); flint_printf("\n\n"); flint_printf("bi2 = "); acb_printd(bi2, 30); flint_printf("\n\n"); flint_abort(); } if (!acb_overlaps(bip1, bip2)) { flint_printf("FAIL: consistency (Bi')\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("bip1 = "); acb_printd(bip1, 30); flint_printf("\n\n"); flint_printf("bip2 = "); acb_printd(bip2, 30); flint_printf("\n\n"); flint_abort(); } acb_mul(w, ai1, bip1, prec1); acb_submul(w, bi1, aip1, prec1); acb_const_pi(t, prec1); acb_inv(t, t, prec1); if (!acb_overlaps(w, t)) { flint_printf("FAIL: wronskian\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("ai1 = "); acb_printd(ai1, 30); flint_printf("\n\n"); flint_printf("aip1 = "); acb_printd(aip1, 30); flint_printf("\n\n"); flint_printf("bi1 = "); acb_printd(bi1, 30); flint_printf("\n\n"); flint_printf("bip1 = "); acb_printd(bip1, 30); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 30); flint_printf("\n\n"); flint_abort(); } mask = n_randlimb(state); acb_hypgeom_airy((mask & 1) ? ai2 : NULL, (mask & 2) ? aip2 : NULL, (mask & 4) ? bi2 : NULL, (mask & 8) ? bip2 : NULL, z, prec2); if (!acb_overlaps(ai1, ai2) || !acb_overlaps(aip1, aip2) || !acb_overlaps(bi1, bi2) || !acb_overlaps(bip1, bip2)) { flint_printf("FAIL: consistency (mask)\n\n"); flint_printf("mask = %u\n\n", mask); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("ai1 = "); acb_printd(ai1, 30); flint_printf("\n\n"); flint_printf("ai2 = "); acb_printd(ai2, 30); flint_printf("\n\n"); flint_printf("aip1 = "); acb_printd(aip1, 30); flint_printf("\n\n"); flint_printf("aip2 = "); acb_printd(aip2, 30); flint_printf("\n\n"); flint_printf("bi1 = "); acb_printd(bi1, 30); flint_printf("\n\n"); flint_printf("bi2 = "); acb_printd(bi2, 30); flint_printf("\n\n"); flint_printf("bip1 = "); acb_printd(bip1, 30); flint_printf("\n\n"); flint_printf("bip2 = "); acb_printd(bip2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z); acb_clear(t); acb_clear(w); acb_clear(ai1); acb_clear(aip1); acb_clear(bi1); acb_clear(bip1); acb_clear(ai2); acb_clear(aip2); acb_clear(bi2); acb_clear(bip2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-airy_bound.c000066400000000000000000000122401461254215100214150ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_airy_bound, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t ai, aip, bi, bip, z1, z2; slong prec; mag_t aib, aipb, bib, bipb, aim, aipm, bim, bipm; acb_init(ai); acb_init(aip); acb_init(bi); acb_init(bip); acb_init(z1); acb_init(z2); mag_init(aib); mag_init(aipb); mag_init(bib); mag_init(bipb); mag_init(aim); mag_init(aipm); mag_init(bim); mag_init(bipm); acb_randtest(z1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); arb_mul_ui(acb_realref(z1), acb_realref(z1), n_randint(state, 300), 1 + n_randint(state, 200)); arb_mul_ui(acb_imagref(z1), acb_imagref(z1), n_randint(state, 300), 1 + n_randint(state, 200)); acb_zero(z2); arf_set_mag(arb_midref(acb_realref(z2)), arb_radref(acb_realref(z1))); arf_set_mag(arb_midref(acb_imagref(z2)), arb_radref(acb_imagref(z1))); switch (n_randint(state, 5)) { case 0: arf_add(arb_midref(acb_realref(z2)), arb_midref(acb_realref(z1)), arb_midref(acb_realref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); arf_add(arb_midref(acb_imagref(z2)), arb_midref(acb_imagref(z1)), arb_midref(acb_imagref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); break; case 1: arf_add(arb_midref(acb_realref(z2)), arb_midref(acb_realref(z1)), arb_midref(acb_realref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); arf_sub(arb_midref(acb_imagref(z2)), arb_midref(acb_imagref(z1)), arb_midref(acb_imagref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); break; case 2: arf_sub(arb_midref(acb_realref(z2)), arb_midref(acb_realref(z1)), arb_midref(acb_realref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); arf_add(arb_midref(acb_imagref(z2)), arb_midref(acb_imagref(z1)), arb_midref(acb_imagref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); break; case 3: arf_sub(arb_midref(acb_realref(z2)), arb_midref(acb_realref(z1)), arb_midref(acb_realref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); arf_sub(arb_midref(acb_imagref(z2)), arb_midref(acb_imagref(z1)), arb_midref(acb_imagref(z2)), ARF_PREC_EXACT, ARF_RND_DOWN); break; default: arf_set(arb_midref(acb_realref(z2)), arb_midref(acb_realref(z1))); arf_set(arb_midref(acb_imagref(z2)), arb_midref(acb_imagref(z1))); } acb_hypgeom_airy_bound(aib, aipb, bib, bipb, z1); prec = MAG_BITS + 10; do { acb_hypgeom_airy(ai, aip, bi, bip, z2, prec); if (acb_rel_accuracy_bits(ai) >= MAG_BITS && acb_rel_accuracy_bits(aip) >= MAG_BITS && acb_rel_accuracy_bits(bi) >= MAG_BITS && acb_rel_accuracy_bits(bip) >= MAG_BITS) break; prec *= 2; } while (1); acb_get_mag(aim, ai); acb_get_mag(aipm, aip); acb_get_mag(bim, bi); acb_get_mag(bipm, bip); if (mag_cmp(aim, aib) > 0 || mag_cmp(aipm, aipb) > 0 || mag_cmp(bim, bib) > 0 || mag_cmp(aipm, bipb) > 0) { printf("FAIL\n"); flint_printf("z1 = "); acb_printd(z1, 20); flint_printf("\n"); flint_printf("z2 = "); acb_printd(z2, 20); flint_printf("\n\n"); flint_printf("ai = "); acb_printd(ai, 20); flint_printf("\n"); flint_printf("aim = "); mag_printd(aim, 10); printf("\n"); flint_printf("aib = "); mag_printd(aib, 10); printf("\n\n"); flint_printf("api = "); acb_printd(aip, 20); flint_printf("\n"); flint_printf("aipm = "); mag_printd(aipm, 10); printf("\n"); flint_printf("aipb = "); mag_printd(aipb, 10); printf("\n\n"); flint_printf("bi = "); acb_printd(bi, 20); flint_printf("\n"); flint_printf("bim = "); mag_printd(bim, 10); printf("\n"); flint_printf("bib = "); mag_printd(bib, 10); printf("\n\n"); flint_printf("bpi = "); acb_printd(bip, 20); flint_printf("\n"); flint_printf("bipm = "); mag_printd(bipm, 10); printf("\n"); flint_printf("bipb = "); mag_printd(bipb, 10); printf("\n\n"); flint_abort(); } acb_clear(ai); acb_clear(aip); acb_clear(bi); acb_clear(bip); acb_clear(z1); acb_clear(z2); mag_clear(aib); mag_clear(aipb); mag_clear(bib); mag_clear(bipb); mag_clear(aim); mag_clear(aipm); mag_clear(bim); mag_clear(bipm); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-airy_series.c000066400000000000000000000111241461254215100216000ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_airy_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t ai, aip, bi, bip, ai2, aip2, bi2, bip2, z, w, t; acb_t c; slong n1, n2, prec1, prec2; unsigned int mask; acb_poly_init(ai); acb_poly_init(aip); acb_poly_init(bi); acb_poly_init(bip); acb_poly_init(ai2); acb_poly_init(aip2); acb_poly_init(bi2); acb_poly_init(bip2); acb_poly_init(z); acb_poly_init(w); acb_poly_init(t); acb_init(c); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); n1 = n_randint(state, 6); n2 = n_randint(state, 6); acb_poly_randtest(ai, state, 10, prec1, 10); acb_poly_randtest(aip, state, 10, prec1, 10); acb_poly_randtest(bi, state, 10, prec1, 10); acb_poly_randtest(bip, state, 10, prec1, 10); acb_poly_randtest(z, state, 1 + n_randint(state, 10), prec1, 10); acb_hypgeom_airy_series(ai, aip, bi, bip, z, n1, prec1); acb_poly_mullow(w, ai, bip, n1, prec1); acb_poly_mullow(t, bi, aip, n1, prec1); acb_poly_sub(w, w, t, prec1); acb_const_pi(c, prec1); acb_inv(c, c, prec1); acb_poly_set_acb(t, c); acb_poly_truncate(t, n1); if (!acb_poly_overlaps(w, t)) { flint_printf("FAIL: wronskian\n\n"); flint_printf("z = "); acb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("ai = "); acb_poly_printd(ai, 30); flint_printf("\n\n"); flint_printf("aip = "); acb_poly_printd(aip, 30); flint_printf("\n\n"); flint_printf("bi = "); acb_poly_printd(bi, 30); flint_printf("\n\n"); flint_printf("bip = "); acb_poly_printd(bip, 30); flint_printf("\n\n"); flint_printf("w = "); acb_poly_printd(w, 30); flint_printf("\n\n"); flint_abort(); } mask = n_randlimb(state); acb_hypgeom_airy_series((mask & 1) ? ai2 : NULL, (mask & 2) ? aip2 : NULL, (mask & 4) ? bi2 : NULL, (mask & 8) ? bip2 : NULL, z, n2, prec2); acb_poly_truncate(ai, FLINT_MIN(n1, n2)); acb_poly_truncate(aip, FLINT_MIN(n1, n2)); acb_poly_truncate(bi, FLINT_MIN(n1, n2)); acb_poly_truncate(bip, FLINT_MIN(n1, n2)); acb_poly_truncate(ai2, FLINT_MIN(n1, n2)); acb_poly_truncate(aip2, FLINT_MIN(n1, n2)); acb_poly_truncate(bi2, FLINT_MIN(n1, n2)); acb_poly_truncate(bip2, FLINT_MIN(n1, n2)); if (((mask & 1) && (!acb_poly_overlaps(ai, ai2))) || ((mask & 2) && (!acb_poly_overlaps(aip, aip2))) || ((mask & 4) && (!acb_poly_overlaps(bi, bi2))) || ((mask & 8) && (!acb_poly_overlaps(bip, bip2)))) { flint_printf("FAIL: consistency (mask)\n\n"); flint_printf("mask = %u\n\n", mask); flint_printf("len1 = %wd, len2 = %wd\n\n", n1, n2); flint_printf("z = "); acb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("ai = "); acb_poly_printd(ai, 30); flint_printf("\n\n"); flint_printf("ai2 = "); acb_poly_printd(ai2, 30); flint_printf("\n\n"); flint_printf("aip = "); acb_poly_printd(aip, 30); flint_printf("\n\n"); flint_printf("aip2 = "); acb_poly_printd(aip2, 30); flint_printf("\n\n"); flint_printf("bi = "); acb_poly_printd(bi, 30); flint_printf("\n\n"); flint_printf("bi2 = "); acb_poly_printd(bi2, 30); flint_printf("\n\n"); flint_printf("bip = "); acb_poly_printd(bip, 30); flint_printf("\n\n"); flint_printf("bip2 = "); acb_poly_printd(bip2, 30); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(ai); acb_poly_clear(aip); acb_poly_clear(bi); acb_poly_clear(bip); acb_poly_clear(ai2); acb_poly_clear(aip2); acb_poly_clear(bi2); acb_poly_clear(bip2); acb_poly_clear(z); acb_poly_clear(w); acb_poly_clear(t); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-bessel_i.c000066400000000000000000000202251461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_bessel_i, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t nu, z, jv, iv, t; slong prec; int scaled; acb_init(nu); acb_init(z); acb_init(jv); acb_init(iv); acb_init(t); prec = 2 + n_randint(state, 500); scaled = n_randint(state, 2); acb_randtest_param(nu, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 20)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); if (n_randint(state, 2) && prec <= 200) { arb_zero(acb_imagref(nu)); arb_zero(acb_imagref(z)); arb_abs(acb_realref(nu), acb_realref(nu)); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(iv, nu, z, scaled, prec); break; case 1: acb_hypgeom_bessel_i_0f1(iv, nu, z, scaled, prec); break; default: if (scaled) acb_hypgeom_bessel_i_scaled(iv, nu, z, prec); else acb_hypgeom_bessel_i(iv, nu, z, prec); } acb_mul_onei(t, z); acb_hypgeom_bessel_j(jv, nu, t, prec); acb_pow(t, z, nu, prec); acb_mul(jv, jv, t, prec); acb_mul_onei(t, z); acb_pow(t, t, nu, prec); acb_div(jv, jv, t, prec); if (scaled) { acb_neg(t, z); acb_exp(t, t, prec); acb_mul(jv, jv, t, prec); } if (!acb_overlaps(iv, jv)) { flint_printf("FAIL: consistency with bessel_j\n\n"); flint_printf("scaled = %d\n\n", scaled); flint_printf("nu = "); acb_printd(nu, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("iv = "); acb_printd(iv, 30); flint_printf("\n\n"); flint_printf("jv = "); acb_printd(jv, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(nu); acb_clear(z); acb_clear(jv); acb_clear(iv); acb_clear(t); } for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t nu0, nu1, nu2, z, w0, w1, w2, t, u; slong prec0, prec1, prec2; acb_init(nu0); acb_init(nu1); acb_init(nu2); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_randtest_param(nu0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_sub_ui(nu1, nu0, 1, prec0); acb_sub_ui(nu2, nu0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w0, nu0, z, 0, prec0); break; case 1: acb_hypgeom_bessel_i_0f1(w0, nu0, z, 0, prec0); break; default: acb_hypgeom_bessel_i(w0, nu0, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w1, nu0, z, 0, prec1); break; case 1: acb_hypgeom_bessel_i_0f1(w1, nu0, z, 0, prec1); break; default: acb_hypgeom_bessel_i(w1, nu0, z, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w1, nu1, z, 0, prec1); break; case 1: acb_hypgeom_bessel_i_0f1(w1, nu1, z, 0, prec1); break; default: acb_hypgeom_bessel_i(w1, nu1, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w2, nu2, z, 0, prec2); break; case 1: acb_hypgeom_bessel_i_0f1(w2, nu2, z, 0, prec2); break; default: if (n_randint(state, 2)) { acb_hypgeom_bessel_i(w2, nu2, z, prec2); } else { acb_hypgeom_bessel_i_scaled(w2, nu2, z, prec2); acb_exp(t, z, prec2); acb_mul(w2, w2, t, prec2); } } acb_mul(t, w1, nu1, prec0); acb_mul_2exp_si(t, t, 1); acb_submul(t, w2, z, prec0); acb_addmul(t, w0, z, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_neg(t, nu0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w2, t, z, 0, prec2); break; case 1: acb_hypgeom_bessel_i_0f1(w2, t, z, 0, prec2); break; default: acb_hypgeom_bessel_i(w2, t, z, prec2); } acb_mul(w1, w1, w2, prec2); acb_neg(t, nu1); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w2, t, z, 0, prec2); break; case 1: acb_hypgeom_bessel_i_0f1(w2, t, z, 0, prec2); break; default: acb_hypgeom_bessel_i(w2, t, z, prec2); } acb_mul(w0, w0, w2, prec2); acb_sub(w0, w1, w0, prec2); acb_sin_pi(t, nu0, prec2); acb_const_pi(u, prec2); acb_mul(u, u, z, prec2); acb_div(t, t, u, prec2); acb_mul_2exp_si(t, t, 1); if (!acb_overlaps(w0, t)) { flint_printf("FAIL: wronskian\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(nu0); acb_clear(nu1); acb_clear(nu2); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-bessel_j.c000066400000000000000000000132601461254215100210530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_bessel_j, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t nu0, nu1, nu2, z, w0, w1, w2, t, u; slong prec0, prec1, prec2; acb_init(nu0); acb_init(nu1); acb_init(nu2); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_randtest_param(nu0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_sub_ui(nu1, nu0, 1, prec0); acb_sub_ui(nu2, nu0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w0, nu0, z, prec0); break; case 1: acb_hypgeom_bessel_j_0f1(w0, nu0, z, prec0); break; default: acb_hypgeom_bessel_j(w0, nu0, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w1, nu0, z, prec1); break; case 1: acb_hypgeom_bessel_j_0f1(w1, nu0, z, prec1); break; default: acb_hypgeom_bessel_j(w1, nu0, z, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w1, nu1, z, prec1); break; case 1: acb_hypgeom_bessel_j_0f1(w1, nu1, z, prec1); break; default: acb_hypgeom_bessel_j(w1, nu1, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w2, nu2, z, prec2); break; case 1: acb_hypgeom_bessel_j_0f1(w2, nu2, z, prec2); break; default: acb_hypgeom_bessel_j(w2, nu2, z, prec2); } acb_mul(t, w1, nu1, prec0); acb_mul_2exp_si(t, t, 1); acb_submul(t, w2, z, prec0); acb_submul(t, w0, z, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_neg(t, nu0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w2, t, z, prec2); break; case 1: acb_hypgeom_bessel_j_0f1(w2, t, z, prec2); break; default: acb_hypgeom_bessel_j(w2, t, z, prec2); } acb_mul(w1, w1, w2, prec2); acb_neg(t, nu1); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w2, t, z, prec2); break; case 1: acb_hypgeom_bessel_j_0f1(w2, t, z, prec2); break; default: acb_hypgeom_bessel_j(w2, t, z, prec2); } acb_mul(w0, w0, w2, prec2); acb_add(w0, w0, w1, prec2); acb_sin_pi(t, nu0, prec2); acb_const_pi(u, prec2); acb_mul(u, u, z, prec2); acb_div(t, t, u, prec2); acb_mul_2exp_si(t, t, 1); if (!acb_overlaps(w0, t)) { flint_printf("FAIL: wronskian\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(nu0); acb_clear(nu1); acb_clear(nu2); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-bessel_k.c000066400000000000000000000127611461254215100210610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_bessel_k, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t nu0, nu1, nu2, z, w0, w1, w2, t, u; slong prec0, prec1, prec2; int scaled; acb_init(nu0); acb_init(nu1); acb_init(nu2); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 700); prec1 = 2 + n_randint(state, 700); prec2 = 2 + n_randint(state, 700); scaled = n_randint(state, 2); acb_randtest_param(nu0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); if (n_randint(state, 4) == 0) arb_zero(acb_imagref(z)); if (n_randint(state, 2) && prec0 <= 200 && prec1 <= 200 && prec2 <= 200) { arb_zero(acb_imagref(nu0)); arb_zero(acb_imagref(z)); arb_abs(acb_realref(nu0), acb_realref(nu0)); } acb_sub_ui(nu1, nu0, 1, prec0); acb_sub_ui(nu2, nu0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w0, nu0, z, scaled, prec0); break; case 1: acb_hypgeom_bessel_k_0f1(w0, nu0, z, scaled, prec0); break; default: if (scaled) acb_hypgeom_bessel_k_scaled(w0, nu0, z, prec0); else acb_hypgeom_bessel_k(w0, nu0, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w1, nu0, z, scaled, prec1); break; case 1: acb_hypgeom_bessel_k_0f1(w1, nu0, z, scaled, prec1); break; default: if (scaled) acb_hypgeom_bessel_k_scaled(w1, nu0, z, prec1); else acb_hypgeom_bessel_k(w1, nu0, z, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("scaled = %d\n\n", scaled); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w1, nu1, z, scaled, prec1); break; case 1: acb_hypgeom_bessel_k_0f1(w1, nu1, z, scaled, prec1); break; default: if (scaled) acb_hypgeom_bessel_k_scaled(w1, nu1, z, prec1); else acb_hypgeom_bessel_k(w1, nu1, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w2, nu2, z, scaled, prec2); break; case 1: acb_hypgeom_bessel_k_0f1(w2, nu2, z, scaled, prec2); break; default: if (scaled) { acb_hypgeom_bessel_k(w2, nu2, z, prec2); acb_exp(t, z, prec2); acb_mul(w2, w2, t, prec2); } else { acb_hypgeom_bessel_k_scaled(w2, nu2, z, prec2); acb_neg(t, z); acb_exp(t, t, prec2); acb_mul(w2, w2, t, prec2); } } acb_mul(t, w1, nu1, prec0); acb_mul_2exp_si(t, t, 1); acb_addmul(t, w2, z, prec0); acb_submul(t, w0, z, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(nu0); acb_clear(nu1); acb_clear(nu2); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-bessel_y.c000066400000000000000000000077501461254215100211010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_bessel_y, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t nu, nu1, z, jv, jv1, yv, yv1, r, s; slong prec, n; acb_init(nu); acb_init(nu1); acb_init(z); acb_init(jv); acb_init(jv1); acb_init(yv); acb_init(yv1); acb_init(r); acb_init(s); prec = 2 + n_randint(state, 500); acb_randtest_param(nu, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); if (n_randint(state, 4) == 0) arb_zero(acb_imagref(z)); acb_add_ui(nu1, nu, 1, prec); if (n_randint(state, 2)) { acb_hypgeom_bessel_j(jv, nu, z, prec); acb_hypgeom_bessel_y(yv, nu, z, prec); } else { acb_hypgeom_bessel_jy(jv, yv, nu, z, prec); } if (n_randint(state, 2)) { acb_hypgeom_bessel_j(jv1, nu1, z, prec); acb_hypgeom_bessel_y(yv1, nu1, z, prec); } else { acb_hypgeom_bessel_jy(jv1, yv1, nu1, z, prec); } acb_mul(r, jv1, yv, prec); acb_submul(r, jv, yv1, prec); acb_mul(r, r, z, prec); acb_const_pi(s, prec); acb_mul(r, r, s, prec); acb_sub_ui(r, r, 2, prec); if (!acb_contains_zero(r)) { flint_printf("FAIL: wronskian\n\n"); flint_printf("nu = "); acb_printd(nu, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("yv = "); acb_printd(yv, 30); flint_printf("\n\n"); flint_printf("yv1 = "); acb_printd(yv1, 30); flint_printf("\n\n"); flint_printf("jv = "); acb_printd(jv, 30); flint_printf("\n\n"); flint_printf("jv1 = "); acb_printd(jv1, 30); flint_printf("\n\n"); flint_printf("r = "); acb_printd(r, 30); flint_printf("\n\n"); flint_abort(); } /* Y_n(-z) = (-1)^n [Y_n(z) - (2/pi) [log(z) - log(-z)] J_v(z)] */ n = n_randint(state, 20) - 10; acb_set_si(nu, n); acb_hypgeom_bessel_y(yv, nu, z, prec); acb_hypgeom_bessel_j(jv, nu, z, prec); acb_log(r, z, prec); acb_neg(s, z); acb_log(s, s, prec); acb_sub(r, r, s, prec); acb_mul(jv, jv, r, prec); acb_const_pi(r, prec); acb_div(jv, jv, r, prec); acb_mul_2exp_si(jv, jv, 1); acb_sub(r, yv, jv, prec); if (n % 2) acb_neg(r, r); acb_neg(yv1, z); acb_hypgeom_bessel_y(yv1, nu, yv1, prec); if (!acb_overlaps(r, yv1)) { flint_printf("FAIL: reflection formula\n\n"); flint_printf("nu = "); acb_printd(nu, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("yv = "); acb_printd(yv, 30); flint_printf("\n\n"); flint_printf("yv1 = "); acb_printd(yv1, 30); flint_printf("\n\n"); flint_printf("jv = "); acb_printd(jv, 30); flint_printf("\n\n"); flint_printf("r = "); acb_printd(r, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(nu); acb_clear(nu1); acb_clear(z); acb_clear(jv); acb_clear(jv1); acb_clear(yv); acb_clear(yv1); acb_clear(r); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-beta_lower.c000066400000000000000000000140511461254215100214070ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_beta_lower, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, a1, b, b1, z, w, wa1, wb1, t, u; slong prec; int regularized; acb_init(a); acb_init(a1); acb_init(b); acb_init(b1); acb_init(z); acb_init(w); acb_init(wa1); acb_init(wb1); acb_init(t); acb_init(u); regularized = n_randint(state, 2); prec = 2 + n_randint(state, 100); acb_randtest_param(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_randtest_param(b, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_randtest_param(z, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_add_ui(a1, a, 1, prec); acb_add_ui(b1, b, 1, prec); acb_hypgeom_beta_lower(w, a, b, z, regularized, prec); acb_hypgeom_beta_lower(wa1, a1, b, z, regularized, prec); acb_hypgeom_beta_lower(wb1, a, b1, z, regularized, prec); if (regularized) { acb_mul(t, wa1, a, prec); acb_addmul(t, wb1, b, prec); acb_add(u, a, b, prec); acb_div(t, t, u, prec); } else { acb_add(t, wa1, wb1, prec); } if (!acb_overlaps(w, t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 30); flint_printf("\n\n"); flint_printf("wa1 = "); acb_printd(wa1, 30); flint_printf("\n\n"); flint_printf("wb1 = "); acb_printd(wb1, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } /* test I(a,b;z) = 1-I(b,a,1-z) */ if (!regularized) { acb_add(t, a, b, prec); acb_gamma(t, t, prec); acb_mul(w, w, t, prec); acb_rgamma(t, a, prec); acb_mul(w, w, t, prec); acb_rgamma(t, b, prec); acb_mul(w, w, t, prec); } acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_hypgeom_beta_lower(t, b, a, t, 1, prec); acb_sub_ui(t, t, 1, prec); acb_neg(t, t); if (!acb_overlaps(w, t)) { flint_printf("FAIL: symmetry\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(a1); acb_clear(b); acb_clear(b1); acb_clear(z); acb_clear(w); acb_clear(wa1); acb_clear(wb1); acb_clear(t); acb_clear(u); } /* see issue 359 */ { slong prec; acb_t z, a, b, res, res2; acb_init(z); acb_init(a); acb_init(b); acb_init(res); acb_init(res2); prec = 64; acb_set_d(a, 1e5); acb_set_d(b, 1e5); acb_set_ui(z, 4999); acb_div_ui(z, z, 10000, prec); acb_hypgeom_beta_lower(res, a, b, z, 1, prec); arb_set_str(acb_realref(res2), "0.4643650813520 +/- 5.17e-14", prec); if (!acb_overlaps(res, res2) || acb_rel_accuracy_bits(res) < acb_rel_accuracy_bits(res2) - 10) { flint_printf("FAIL: test case (1)\n\n"); flint_printf("res = "); acb_printd(res, 100); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 100); flint_printf("\n\n"); flint_abort(); } prec = 128; acb_set_d(a, 1e10); acb_set_d(b, 1e10); acb_set_ui(z, 4999); acb_div_ui(z, z, 10000, prec); acb_hypgeom_beta_lower(res, a, b, z, 1, prec); arb_set_str(acb_realref(res2), "2.69791122252793228610950163e-176 +/- 2.47e-203", prec); if (!acb_overlaps(res, res2) || acb_rel_accuracy_bits(res) < acb_rel_accuracy_bits(res2) - 10) { flint_printf("FAIL: test case (2)\n\n"); flint_printf("res = "); acb_printd(res, 100); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 100); flint_printf("\n\n"); flint_abort(); } prec = 128; acb_set_d(a, 1e15); acb_set_d(b, 1e15); acb_set_ui(z, 4999); acb_div_ui(z, z, 10000, prec); acb_hypgeom_beta_lower(res, a, b, z, 1, prec); arb_set_str(acb_realref(res2), "1.0612052723416047758478e-17371784 +/- 7.21e-17371807", prec); if (!acb_overlaps(res, res2) || acb_rel_accuracy_bits(res) < acb_rel_accuracy_bits(res2) - 10) { flint_printf("FAIL: test case (3\n\n"); flint_printf("res = "); acb_printd(res, 100); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 100); flint_printf("\n\n"); flint_abort(); } acb_clear(z); acb_clear(a); acb_clear(b); acb_clear(res); acb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-beta_lower_series.c000066400000000000000000000121711461254215100227620ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_beta_lower_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, a1, b, b1, t, u; acb_poly_t z, w, wa1, wb1, pt, pu; slong prec, len, lena1, lenb1; int regularized; acb_init(a); acb_init(a1); acb_init(b); acb_init(b1); acb_init(t); acb_init(u); acb_poly_init(z); acb_poly_init(w); acb_poly_init(wa1); acb_poly_init(wb1); acb_poly_init(pt); acb_poly_init(pu); regularized = n_randint(state, 2); prec = 2 + n_randint(state, 100); acb_randtest_param(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_randtest_param(b, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_poly_randtest(z, state, 10, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_poly_randtest(w, state, 10, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_poly_randtest(wa1, state, 10, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_poly_randtest(wb1, state, 10, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); len = n_randint(state, 10); lena1 = n_randint(state, 10); lenb1 = n_randint(state, 10); acb_add_ui(a1, a, 1, prec); acb_add_ui(b1, b, 1, prec); acb_hypgeom_beta_lower_series(w, a, b, z, regularized, len, prec); acb_hypgeom_beta_lower_series(wa1, a1, b, z, regularized, lena1, prec); acb_hypgeom_beta_lower_series(wb1, a, b1, z, regularized, lenb1, prec); if (regularized) { acb_poly_scalar_mul(pt, wa1, a, prec); acb_poly_scalar_mul(pu, wb1, b, prec); acb_poly_add(pt, pt, pu, prec); acb_add(u, a, b, prec); acb_poly_scalar_div(pt, pt, u, prec); } else { acb_poly_add(pt, wa1, wb1, prec); } acb_poly_set(pu, w); acb_poly_truncate(pu, FLINT_MIN(FLINT_MIN(len, lena1), lenb1)); acb_poly_truncate(pt, FLINT_MIN(FLINT_MIN(len, lena1), lenb1)); if (!acb_poly_overlaps(pu, pt)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("len = %wd, lena1 = %wd, lenb1 = %wd\n\n", len, lena1, lenb1); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("w = "); acb_poly_printd(w, 30); flint_printf("\n\n"); flint_printf("wa1 = "); acb_poly_printd(wa1, 30); flint_printf("\n\n"); flint_printf("wb1 = "); acb_poly_printd(wb1, 30); flint_printf("\n\n"); flint_printf("pt = "); acb_poly_printd(pt, 30); flint_printf("\n\n"); flint_abort(); } /* test I(a,b;z) = 1-I(b,a,1-z) */ if (!regularized) { acb_add(t, a, b, prec); acb_gamma(t, t, prec); acb_poly_scalar_mul(w, w, t, prec); acb_rgamma(t, a, prec); acb_poly_scalar_mul(w, w, t, prec); acb_rgamma(t, b, prec); acb_poly_scalar_mul(w, w, t, prec); } acb_poly_add_si(pt, z, -1, prec); acb_poly_neg(pt, pt); acb_hypgeom_beta_lower_series(pt, b, a, pt, 1, lena1, prec); acb_poly_add_si(pt, pt, -1, prec); acb_poly_neg(pt, pt); acb_poly_set(pu, w); acb_poly_truncate(pu, FLINT_MIN(len, lena1)); acb_poly_truncate(pt, FLINT_MIN(len, lena1)); if (!acb_poly_overlaps(pu, pt)) { flint_printf("FAIL: symmetry\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("len = %wd, lena1 = %wd\n\n", len, lena1); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("w = "); acb_poly_printd(w, 30); flint_printf("\n\n"); flint_printf("pt = "); acb_poly_printd(pt, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(a1); acb_clear(b); acb_clear(b1); acb_clear(t); acb_clear(u); acb_poly_clear(z); acb_poly_clear(w); acb_poly_clear(wa1); acb_poly_clear(wb1); acb_poly_clear(pt); acb_poly_clear(pu); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-chebyshev_t.c000066400000000000000000000043701461254215100215720ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_chebyshev_t, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, z, a, b, c, t, res1, res2; slong prec; acb_init(n); acb_init(z); acb_init(a); acb_init(b); acb_init(c); acb_init(t); acb_init(res1); acb_init(res2); prec = 2 + n_randint(state, 300); acb_randtest_param(n, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(z, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(res1, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(res2, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_hypgeom_chebyshev_t(res1, n, z, prec); acb_neg(a, n); acb_set(b, n); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_hypgeom_2f1(res2, a, b, c, t, 0, 2 + n_randint(state, 300)); if (!acb_overlaps(res1, res2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(z); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(t); acb_clear(res1); acb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-chebyshev_u.c000066400000000000000000000045231461254215100215730ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_chebyshev_u, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, z, a, b, c, t, res1, res2; slong prec; acb_init(n); acb_init(z); acb_init(a); acb_init(b); acb_init(c); acb_init(t); acb_init(res1); acb_init(res2); prec = 2 + n_randint(state, 300); acb_randtest_param(n, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(z, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(res1, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(res2, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_hypgeom_chebyshev_u(res1, n, z, prec); acb_neg(a, n); acb_add_ui(b, n, 2, prec); acb_set_ui(c, 3); acb_mul_2exp_si(c, c, -1); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_hypgeom_2f1(res2, a, b, c, t, 0, 2 + n_randint(state, 300)); acb_add_ui(t, n, 1, prec); acb_mul(res2, res2, t, prec); if (!acb_overlaps(res1, res2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(z); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(t); acb_clear(res1); acb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-chi.c000066400000000000000000000046371461254215100200400ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_chi, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z0, z1, w0, w1; slong prec0, prec1; acb_init(z0); acb_init(z1); acb_init(w0); acb_init(w1); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); acb_randtest(z0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_set(z1, z0); if (n_randint(state, 2)) { acb_add(z1, z1, w0, prec0); acb_sub(z1, z1, w0, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_chi_2f3(w0, z0, prec0); break; case 1: acb_hypgeom_chi_asymp(w0, z0, prec0); break; default: acb_hypgeom_chi(w0, z0, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_chi_2f3(w1, z1, prec1); break; case 1: acb_hypgeom_chi_asymp(w1, z1, prec1); break; default: acb_hypgeom_chi(w1, z1, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("z0 = "); acb_printd(z0, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z0); acb_clear(z1); acb_clear(w0); acb_clear(w1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-chi_series.c000066400000000000000000000052431461254215100214040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_chi_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, n3, bits1, bits2, bits3; acb_poly_t S, A, B, C, T, U; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); n3 = FLINT_MIN(n1, n2); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_init(T); acb_poly_init(U); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_chi_series(A, S, n1, bits2); acb_hypgeom_chi_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, n3); acb_poly_truncate(B, n3); /* [Chi(h(x))]' h(x) = cosh(h(x)) h'(x) */ acb_poly_cosh_series(U, S, n3, bits2); acb_poly_derivative(T, S, bits2); acb_poly_mullow(U, U, T, FLINT_MAX(0, n3 - 1), bits2); acb_poly_derivative(T, A, bits2); acb_poly_mullow(T, T, S, FLINT_MAX(0, n3 - 1), bits2); if (!acb_poly_overlaps(B, C) || !acb_poly_overlaps(T, U)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("T = "); acb_poly_printd(T, 15); flint_printf("\n\n"); flint_printf("U = "); acb_poly_printd(U, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_chi_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(T); acb_poly_clear(U); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-ci.c000066400000000000000000000046331461254215100176640ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_ci, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z0, z1, w0, w1; slong prec0, prec1; acb_init(z0); acb_init(z1); acb_init(w0); acb_init(w1); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); acb_randtest(z0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_set(z1, z0); if (n_randint(state, 2)) { acb_add(z1, z1, w0, prec0); acb_sub(z1, z1, w0, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_ci_2f3(w0, z0, prec0); break; case 1: acb_hypgeom_ci_asymp(w0, z0, prec0); break; default: acb_hypgeom_ci(w0, z0, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_ci_2f3(w1, z1, prec1); break; case 1: acb_hypgeom_ci_asymp(w1, z1, prec1); break; default: acb_hypgeom_ci(w1, z1, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("z0 = "); acb_printd(z0, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z0); acb_clear(z1); acb_clear(w0); acb_clear(w1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-ci_series.c000066400000000000000000000052341461254215100212340ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_ci_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, n3, bits1, bits2, bits3; acb_poly_t S, A, B, C, T, U; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); n3 = FLINT_MIN(n1, n2); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_init(T); acb_poly_init(U); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_ci_series(A, S, n1, bits2); acb_hypgeom_ci_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, n3); acb_poly_truncate(B, n3); /* [Ci(h(x))]' h(x) = cos(h(x)) h'(x) */ acb_poly_cos_series(U, S, n3, bits2); acb_poly_derivative(T, S, bits2); acb_poly_mullow(U, U, T, FLINT_MAX(0, n3 - 1), bits2); acb_poly_derivative(T, A, bits2); acb_poly_mullow(T, T, S, FLINT_MAX(0, n3 - 1), bits2); if (!acb_poly_overlaps(B, C) || !acb_poly_overlaps(T, U)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("T = "); acb_poly_printd(T, 15); flint_printf("\n\n"); flint_printf("U = "); acb_poly_printd(U, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_ci_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(T); acb_poly_clear(U); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-coulomb.c000066400000000000000000000162241461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_coulomb, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z, t, u, eta, l; acb_t F1, G1, Hpos1, Hneg1; acb_t F2, G2, Hpos2, Hneg2; slong prec1, prec2; unsigned int mask; acb_init(z); acb_init(t); acb_init(u); acb_init(eta); acb_init(l); acb_init(F1); acb_init(G1); acb_init(Hpos1); acb_init(Hneg1); acb_init(F2); acb_init(G2); acb_init(Hpos2); acb_init(Hneg2); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); acb_randtest_param(eta, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); acb_randtest_param(l, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); acb_randtest_param(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); acb_randtest_param(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); acb_randtest_param(t, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); acb_add(z, z, t, 1000); acb_sub(z, z, t, 1000); acb_hypgeom_coulomb(F1, G1, Hpos1, Hneg1, l, eta, z, prec1); acb_hypgeom_coulomb(F2, G2, Hpos2, Hneg2, l, eta, z, prec2); if (!acb_overlaps(F1, F2) || !acb_overlaps(G1, G2) || !acb_overlaps(Hpos1, Hpos2) || !acb_overlaps(Hneg1, Hneg2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("l = "); acb_printn(l, 30, 0); flint_printf("\n\n"); flint_printf("eta = "); acb_printn(eta, 30, 0); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 30, 0); flint_printf("\n\n"); flint_printf("F1 = "); acb_printn(F1, 30, 0); flint_printf("\n"); flint_printf("F2 = "); acb_printn(F2, 30, 0); flint_printf("\n\n"); flint_printf("G1 = "); acb_printn(G1, 30, 0); flint_printf("\n"); flint_printf("G2 = "); acb_printn(G2, 30, 0); flint_printf("\n\n"); flint_printf("Hpos1 = "); acb_printn(Hpos1, 30, 0); flint_printf("\n"); flint_printf("Hpos2 = "); acb_printn(Hpos2, 30, 0); flint_printf("\n\n"); flint_printf("Hneg1 = "); acb_printn(Hneg1, 30, 0); flint_printf("\n"); flint_printf("Hneg2 = "); acb_printn(Hneg2, 30, 0); flint_printf("\n\n"); flint_abort(); } acb_mul_onei(t, F1); acb_add(t, t, G1, prec1); acb_div_onei(u, F1); acb_add(u, u, G1, prec1); if (!acb_overlaps(t, Hpos1) || !acb_overlaps(u, Hneg1)) { flint_printf("FAIL: complex\n\n"); flint_printf("l = "); acb_printn(l, 30, 0); flint_printf("\n\n"); flint_printf("eta = "); acb_printn(eta, 30, 0); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 30, 0); flint_printf("\n\n"); flint_printf("F1 = "); acb_printn(F1, 30, 0); flint_printf("\n"); flint_printf("G1 = "); acb_printn(G1, 30, 0); flint_printf("\n"); flint_printf("Hpos1 = "); acb_printn(Hpos1, 30, 0); flint_printf("\n"); flint_printf("Hneg1 = "); acb_printn(Hneg1, 30, 0); flint_printf("\n"); flint_printf("t = "); acb_printn(t, 30, 0); flint_printf("\n"); flint_printf("u = "); acb_printn(u, 30, 0); flint_printf("\n"); flint_abort(); } mask = n_randlimb(state); if (n_randint(state, 2) == 0) { acb_randtest_param(t, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); acb_add(z, z, t, prec2); acb_sub(z, z, t, prec2); } /* also test aliasing */ acb_set(G2, z); acb_hypgeom_coulomb((mask & 1) ? F2 : NULL, (mask & 2) ? G2 : NULL, (mask & 4) ? Hpos2 : NULL, (mask & 8) ? Hneg2 : NULL, l, eta, G2, prec2); if (((mask & 1) && !acb_overlaps(F1, F2)) || ((mask & 2) && !acb_overlaps(G1, G2)) || ((mask & 4) && !acb_overlaps(Hpos1, Hpos2)) || ((mask & 8) && !acb_overlaps(Hneg1, Hneg2))) { flint_printf("FAIL: consistency (mask)\n\n"); flint_printf("mask = %u\n\n", mask); flint_printf("l = "); acb_printn(l, 30, 0); flint_printf("\n\n"); flint_printf("eta = "); acb_printn(eta, 30, 0); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 30, 0); flint_printf("\n\n"); flint_printf("F1 = "); acb_printn(F1, 30, 0); flint_printf("\n"); flint_printf("F2 = "); acb_printn(F2, 30, 0); flint_printf("\n\n"); flint_printf("G1 = "); acb_printn(G1, 30, 0); flint_printf("\n"); flint_printf("G2 = "); acb_printn(G2, 30, 0); flint_printf("\n\n"); flint_printf("Hpos1 = "); acb_printn(Hpos1, 30, 0); flint_printf("\n"); flint_printf("Hpos2 = "); acb_printn(Hpos2, 30, 0); flint_printf("\n\n"); flint_printf("Hneg1 = "); acb_printn(Hneg1, 30, 0); flint_printf("\n"); flint_printf("Hneg2 = "); acb_printn(Hneg2, 30, 0); flint_printf("\n\n"); flint_abort(); } /* Check F_{l-1} G_{l} - F_{l} G_{l-1} = l (l^2 + eta^2)^(1/2) */ acb_sub_ui(t, l, 1, prec2); acb_hypgeom_coulomb(F2, G2, NULL, NULL, t, eta, z, prec2); acb_mul_onei(t, eta); acb_add(t, t, l, prec2); acb_rsqrt(t, t, prec2); acb_div_onei(u, eta); acb_add(u, u, l, prec2); acb_rsqrt(u, u, prec2); acb_mul(u, t, u, prec2); acb_mul(u, u, l, prec2); acb_mul(t, F2, G1, prec2); acb_submul(t, F1, G2, prec2); if (!acb_overlaps(t, u)) { flint_printf("FAIL: cross-product\n\n"); flint_printf("l = "); acb_printn(l, 30, 0); flint_printf("\n\n"); flint_printf("eta = "); acb_printn(eta, 30, 0); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 30, 0); flint_printf("\n\n"); flint_printf("F1 = "); acb_printn(F1, 30, 0); flint_printf("\n"); flint_printf("G1 = "); acb_printn(G1, 30, 0); flint_printf("\n"); flint_printf("F2 = "); acb_printn(F2, 30, 0); flint_printf("\n"); flint_printf("G2 = "); acb_printn(G2, 30, 0); flint_printf("\n"); flint_printf("t = "); acb_printn(t, 30, 0); flint_printf("\n"); flint_printf("u = "); acb_printn(u, 30, 0); flint_printf("\n"); flint_abort(); } acb_clear(z); acb_clear(t); acb_clear(u); acb_clear(eta); acb_clear(l); acb_clear(F1); acb_clear(G1); acb_clear(Hpos1); acb_clear(Hneg1); acb_clear(F2); acb_clear(G2); acb_clear(Hpos2); acb_clear(Hneg2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-coulomb_series.c000066400000000000000000000141041461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_coulomb_series, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t F, G, Hpos, Hneg, F2, G2, Hpos2, Hneg2, z, w, t, u; acb_t c, l, eta, z0; slong n1, n2, prec1, prec2; unsigned int mask; acb_poly_init(F); acb_poly_init(G); acb_poly_init(Hpos); acb_poly_init(Hneg); acb_poly_init(F2); acb_poly_init(G2); acb_poly_init(Hpos2); acb_poly_init(Hneg2); acb_poly_init(z); acb_poly_init(w); acb_poly_init(t); acb_poly_init(u); acb_init(c); acb_init(l); acb_init(eta); acb_init(z0); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); n1 = n_randint(state, 8); n2 = n_randint(state, 8); acb_poly_randtest(F, state, 10, prec1, 10); acb_poly_randtest(G, state, 10, prec1, 10); acb_poly_randtest(Hpos, state, 10, prec1, 10); acb_poly_randtest(Hneg, state, 10, prec1, 10); acb_randtest_param(l, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); acb_randtest_param(eta, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); acb_poly_randtest(z, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); acb_hypgeom_coulomb_series(F, G, Hpos, Hneg, l, eta, z, n1, prec1); acb_poly_derivative(t, F, prec1); if (n_randint(state, 2)) acb_poly_set(u, G); else if (n_randint(state, 2)) acb_poly_set(u, Hpos); else acb_poly_set(u, Hneg); /* F' G - F G' = 1 */ acb_poly_mullow(w, t, u, FLINT_MAX(n1 - 1, 0), prec1); acb_poly_derivative(u, u, prec1); acb_poly_mullow(t, F, u, FLINT_MAX(n1 - 1, 0), prec1); acb_poly_sub(w, w, t, prec1); acb_poly_derivative(t, z, prec1); acb_poly_truncate(t, FLINT_MAX(n1 - 1, 0)); /* hack: work around mullow(nan, 0) = 0 */ acb_poly_get_coeff_acb(z0, z, 0); if (!acb_contains_zero(z0) && !acb_poly_overlaps(w, t)) { flint_printf("FAIL: wronskian, n1 = %wd\n\n", n1); flint_printf("l = "); acb_printd(l, 30); flint_printf("\n\n"); flint_printf("eta = "); acb_printd(eta, 30); flint_printf("\n\n"); flint_printf("z = "); acb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("F = "); acb_poly_printd(F, 30); flint_printf("\n\n"); flint_printf("G = "); acb_poly_printd(G, 30); flint_printf("\n\n"); flint_printf("Hpos = "); acb_poly_printd(Hpos, 30); flint_printf("\n\n"); flint_printf("Hneg = "); acb_poly_printd(Hneg, 30); flint_printf("\n\n"); flint_printf("w = "); acb_poly_printd(w, 30); flint_printf("\n\n"); flint_printf("t = "); acb_poly_printd(t, 30); flint_printf("\n\n"); flint_abort(); } mask = n_randlimb(state); acb_poly_set(G2, z); /* for aliasing */ if (n_randint(state, 2)) { acb_poly_randtest(u, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); acb_poly_add(G2, G2, u, prec2); acb_poly_sub(G2, G2, u, prec2); } acb_hypgeom_coulomb_series((mask & 1) ? F2 : NULL, (mask & 2) ? G2 : NULL, (mask & 4) ? Hpos2 : NULL, (mask & 8) ? Hneg2 : NULL, l, eta, G2, n2, prec2); acb_poly_truncate(F, FLINT_MIN(n1, n2)); acb_poly_truncate(G, FLINT_MIN(n1, n2)); acb_poly_truncate(Hpos, FLINT_MIN(n1, n2)); acb_poly_truncate(Hneg, FLINT_MIN(n1, n2)); acb_poly_truncate(F2, FLINT_MIN(n1, n2)); acb_poly_truncate(G2, FLINT_MIN(n1, n2)); acb_poly_truncate(Hpos2, FLINT_MIN(n1, n2)); acb_poly_truncate(Hneg2, FLINT_MIN(n1, n2)); if (((mask & 1) && (!acb_poly_overlaps(F, F2))) || ((mask & 2) && (!acb_poly_overlaps(G, G2))) || ((mask & 4) && (!acb_poly_overlaps(Hpos, Hpos2))) || ((mask & 8) && (!acb_poly_overlaps(Hneg, Hneg2)))) { flint_printf("FAIL: consistency (mask)\n\n"); flint_printf("mask = %u\n\n", mask); flint_printf("len1 = %wd, len2 = %wd\n\n", n1, n2); flint_printf("l = "); acb_printd(l, 30); flint_printf("\n\n"); flint_printf("eta = "); acb_printd(eta, 30); flint_printf("\n\n"); flint_printf("z = "); acb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("F = "); acb_poly_printd(F, 30); flint_printf("\n\n"); flint_printf("F2 = "); acb_poly_printd(F2, 30); flint_printf("\n\n"); flint_printf("G = "); acb_poly_printd(G, 30); flint_printf("\n\n"); flint_printf("G2 = "); acb_poly_printd(G2, 30); flint_printf("\n\n"); flint_printf("Hpos = "); acb_poly_printd(Hpos, 30); flint_printf("\n\n"); flint_printf("Hpos2 = "); acb_poly_printd(Hpos2, 30); flint_printf("\n\n"); flint_printf("Hneg = "); acb_poly_printd(Hneg, 30); flint_printf("\n\n"); flint_printf("Hneg2 = "); acb_poly_printd(Hneg2, 30); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(F); acb_poly_clear(G); acb_poly_clear(Hpos); acb_poly_clear(Hneg); acb_poly_clear(F2); acb_poly_clear(G2); acb_poly_clear(Hpos2); acb_poly_clear(Hneg2); acb_poly_clear(z); acb_poly_clear(w); acb_poly_clear(t); acb_poly_clear(u); acb_clear(c); acb_clear(l); acb_clear(eta); acb_clear(z0); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-dilog.c000066400000000000000000000070401461254215100203620ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_dilog, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z0, z1, w0, w1, a; slong prec0, prec1; int alg0, alg1; acb_init(z0); acb_init(z1); acb_init(w0); acb_init(w1); acb_init(a); prec0 = 2 + n_randint(state, 500); prec1 = 2 + n_randint(state, 500); acb_randtest(z0, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_set(z1, z0); if (n_randint(state, 2)) { acb_add(z1, z1, w0, prec0); acb_sub(z1, z1, w0, prec0); } switch ((alg0 = n_randint(state, 15))) { case 0: acb_hypgeom_dilog_zero(w0, z0, prec0); break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: acb_hypgeom_dilog_transform(w0, z0, alg0, prec0); break; case 8: acb_hypgeom_dilog_bernoulli(w0, z0, prec0); break; case 9: acb_hypgeom_dilog_bitburst(w0, a, z0, prec0); acb_hypgeom_dilog(a, a, prec0); acb_add(w0, w0, a, prec0); break; default: acb_hypgeom_dilog(w0, z0, prec0); } acb_set(w1, z1); /* also test aliasing */ switch ((alg1 = n_randint(state, 15))) { case 0: acb_hypgeom_dilog_zero(w1, w1, prec1); break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: acb_hypgeom_dilog_transform(w1, w1, alg1, prec1); break; case 8: acb_hypgeom_dilog_bernoulli(w1, z1, prec1); break; case 9: acb_hypgeom_dilog_bitburst(w1, a, z1, prec1); acb_hypgeom_dilog(a, a, prec1); acb_add(w1, w1, a, prec1); break; default: acb_hypgeom_dilog(w1, z1, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("alg0 = %d, alg1 = %d\n\n", alg0, alg1); flint_printf("prec0 = %wd, prec1 = %wd\n\n", prec0, prec1); flint_printf("z0 = "); acb_printd(z0, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z0); acb_clear(z1); acb_clear(w0); acb_clear(w1); acb_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-ei.c000066400000000000000000000062121461254215100176610ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_ei_fallback(acb_t res, const acb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_zero(t); acb_neg(u, z); acb_hypgeom_gamma_upper(u, t, u, 0, prec); acb_neg(u, u); acb_log(t, z, prec); acb_mul_2exp_si(t, t, -1); acb_add(u, u, t, prec); acb_inv(t, z, prec); acb_log(t, t, prec); acb_mul_2exp_si(t, t, -1); acb_sub(u, u, t, prec); acb_neg(t, z); acb_log(t, t, prec); acb_sub(u, u, t, prec); acb_swap(res, u); acb_clear(t); acb_clear(u); } TEST_FUNCTION_START(acb_hypgeom_ei, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z0, z1, w0, w1; slong prec0, prec1; acb_init(z0); acb_init(z1); acb_init(w0); acb_init(w1); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); acb_randtest(z0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_set(z1, z0); if (n_randint(state, 2)) { acb_add(z1, z1, w0, prec0); acb_sub(z1, z1, w0, prec0); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_ei_2f2(w0, z0, prec0); break; case 1: acb_hypgeom_ei_asymp(w0, z0, prec0); break; case 2: acb_hypgeom_ei(w0, z0, prec0); break; default: acb_hypgeom_ei_fallback(w0, z0, prec0); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_ei_2f2(w1, z1, prec1); break; case 1: acb_hypgeom_ei_asymp(w1, z1, prec1); break; case 2: acb_hypgeom_ei(w1, z1, prec1); break; default: acb_hypgeom_ei_fallback(w1, z1, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("z0 = "); acb_printd(z0, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z0); acb_clear(z1); acb_clear(w0); acb_clear(w1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-ei_series.c000066400000000000000000000051341461254215100212350ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_ei_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, n3, bits1, bits2, bits3; acb_poly_t S, A, B, C, T, U; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); n3 = FLINT_MIN(n1, n2); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_init(T); acb_poly_init(U); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_ei_series(A, S, n1, bits2); acb_hypgeom_ei_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, n3); acb_poly_truncate(B, n3); /* [Ei(h(x))]' h(x) = exp(h(x)) h'(x) */ acb_poly_derivative(T, A, bits2); acb_poly_mullow(T, T, S, FLINT_MAX(0, n3 - 1), bits2); acb_poly_exp_series(U, S, n3, bits2); acb_poly_derivative(U, U, bits2); if (!acb_poly_overlaps(B, C) || !acb_poly_overlaps(T, U)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("T = "); acb_poly_printd(T, 15); flint_printf("\n\n"); flint_printf("U = "); acb_poly_printd(U, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_ei_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(T); acb_poly_clear(U); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-erf.c000066400000000000000000000046421461254215100200450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_erf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2, prec3, prec4; prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); prec3 = 2 + n_randint(state, 1000); prec4 = 2 + n_randint(state, 1000); acb_init(a); acb_init(b); acb_init(c); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_special(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); switch (n_randint(state, 4)) { case 0: acb_hypgeom_erf_asymp(b, a, 0, prec1, prec3); break; case 1: acb_hypgeom_erf_1f1a(b, a, prec1); break; case 2: acb_hypgeom_erf_1f1b(b, a, prec1); break; default: acb_hypgeom_erf(b, a, prec1); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_erf_asymp(c, a, 0, prec2, prec4); break; case 1: acb_hypgeom_erf_1f1a(c, a, prec2); break; case 2: acb_hypgeom_erf_1f1b(c, a, prec2); break; default: acb_hypgeom_erf(c, a, prec2); } if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-erf_series.c000066400000000000000000000040731461254215100214150ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_erf_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_erf_series(A, S, n1, bits2); acb_hypgeom_erf_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_erf_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-erfc.c000066400000000000000000000046041461254215100202060ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_erfc, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2, prec3, prec4; prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); prec3 = 2 + n_randint(state, 1000); prec4 = 2 + n_randint(state, 1000); acb_init(a); acb_init(b); acb_init(c); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_special(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); switch (n_randint(state, 4)) { case 0: acb_hypgeom_erf_asymp(b, a, 1, prec1, prec3); break; case 1: acb_hypgeom_erf(b, a, prec1); acb_sub_ui(b, b, 1, prec1); acb_neg(b, b); break; default: acb_hypgeom_erfc(b, a, prec1); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_erf_asymp(c, a, 1, prec2, prec4); break; case 1: acb_hypgeom_erf(c, a, prec2); acb_sub_ui(c, c, 1, prec2); acb_neg(c, c); break; default: acb_hypgeom_erfc(c, a, prec2); } if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-erfc_series.c000066400000000000000000000042041461254215100215540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_erfc_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_erfc_series(A, S, n1, bits2); acb_hypgeom_erf_series(B, S, n2, bits3); acb_poly_add_si(B, B, -1, bits3); acb_poly_neg(B, B); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_erfc_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-erfi_series.c000066400000000000000000000044271461254215100215710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_erfi_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; acb_t I; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(I); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_erfi_series(A, S, n1, bits2); acb_onei(I); acb_poly_set_acb(C, I); acb_poly_mul(B, S, C, bits3); acb_hypgeom_erf_series(B, B, n2, bits3); acb_poly_neg(C, C); acb_poly_mul(B, B, C, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_erfi_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_clear(I); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-fresnel.c000066400000000000000000000066531461254215100207330ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_fresnel, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z, z2, s, c, u, v; slong prec1, prec2; int normalized; prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); acb_init(z); acb_init(z2); acb_init(s); acb_init(c); acb_init(u); acb_init(v); acb_randtest_special(z, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(c, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); normalized = n_randint(state, 2); /* test S(z) + i C(z) = sqrt(pi/2) (1+i)/2 erf((1+i)/sqrt(2) z) */ /* u = rhs */ acb_onei(u); acb_sqrt(u, u, prec1); acb_mul(u, u, z, prec1); acb_hypgeom_erf(u, u, prec1); acb_mul_onei(v, u); acb_add(u, u, v, prec1); acb_mul_2exp_si(u, u, -1); acb_const_pi(v, prec1); acb_mul_2exp_si(v, v, -1); acb_sqrt(v, v, prec1); acb_mul(u, u, v, prec1); if (normalized) { acb_const_pi(v, prec2); acb_mul_2exp_si(v, v, -1); acb_sqrt(v, v, prec2); acb_div(z2, z, v, prec2); } else { acb_set(z2, z); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_fresnel(s, c, z2, normalized, prec2); break; case 1: acb_hypgeom_fresnel(s, NULL, z2, normalized, prec2); acb_hypgeom_fresnel(NULL, c, z2, normalized, prec2); break; case 2: acb_set(s, z2); acb_hypgeom_fresnel(s, c, s, normalized, prec2); break; case 3: acb_set(c, z2); acb_hypgeom_fresnel(s, c, c, normalized, prec2); break; default: acb_hypgeom_fresnel(s, c, z2, normalized, prec2); } if (normalized) { acb_mul(s, s, v, prec2); acb_mul(c, c, v, prec2); } acb_mul_onei(v, c); acb_add(v, v, s, prec2); if (!acb_overlaps(u, v)) { flint_printf("FAIL: overlap\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("u = "); acb_printd(u, 30); flint_printf("\n\n"); flint_printf("v = "); acb_printd(v, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z); acb_clear(z2); acb_clear(s); acb_clear(c); acb_clear(u); acb_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-fresnel_series.c000066400000000000000000000103531461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_fresnel_series, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t X, S1, S2, C1, C2, T; acb_t c; int normalized; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); normalized = n_randint(state, 2); acb_poly_init(X); acb_poly_init(S1); acb_poly_init(S2); acb_poly_init(C1); acb_poly_init(C2); acb_poly_init(T); acb_init(c); acb_poly_randtest(X, state, m, bits1, 3); acb_poly_randtest(S1, state, 10, bits1, 3); acb_poly_randtest(S2, state, 10, bits1, 3); acb_poly_randtest(C1, state, 10, bits1, 3); acb_poly_randtest(C2, state, 10, bits1, 3); acb_hypgeom_fresnel_series(S1, C1, X, normalized, n1, bits2); switch (n_randint(state, 8)) { case 0: acb_hypgeom_fresnel_series(S2, C2, X, normalized, n2, bits3); break; case 1: acb_hypgeom_fresnel_series(S2, NULL, X, normalized, n2, bits3); acb_hypgeom_fresnel_series(NULL, C2, X, normalized, n2, bits3); break; case 2: acb_poly_set(S2, X); acb_hypgeom_fresnel_series(NULL, C2, S2, normalized, n2, bits3); acb_hypgeom_fresnel_series(S2, NULL, S2, normalized, n2, bits3); break; case 3: acb_poly_set(C2, X); acb_hypgeom_fresnel_series(S2, NULL, C2, normalized, n2, bits3); acb_hypgeom_fresnel_series(NULL, C2, C2, normalized, n2, bits3); break; case 4: acb_poly_set(S2, X); acb_hypgeom_fresnel_series(S2, C2, S2, normalized, n2, bits3); break; case 5: acb_poly_set(C2, X); acb_hypgeom_fresnel_series(S2, C2, C2, normalized, n2, bits3); break; default: acb_const_pi(c, bits3); acb_mul_2exp_si(c, c, -1); acb_sqrt(c, c, bits3); if (normalized == 0) acb_inv(c, c, bits3); acb_poly_set_acb(T, c); acb_poly_mul(T, T, X, bits3); acb_hypgeom_fresnel_series(S2, C2, T, !normalized, n2, bits3); acb_inv(c, c, bits3); acb_poly_set_acb(T, c); acb_poly_mul(S2, S2, T, bits3); acb_poly_mul(C2, C2, T, bits3); } acb_poly_truncate(S1, FLINT_MIN(n1, n2)); acb_poly_truncate(C1, FLINT_MIN(n1, n2)); acb_poly_truncate(S2, FLINT_MIN(n1, n2)); acb_poly_truncate(C2, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(S1, S2) || !acb_poly_overlaps(C1, C2)) { flint_printf("FAIL (n1 = %wd, n2 = %wd, norm = %d)\n\n", n1, n2, normalized); flint_printf("X = "); acb_poly_printd(X, 15); flint_printf("\n\n"); flint_printf("S1 = "); acb_poly_printd(S1, 15); flint_printf("\n\n"); flint_printf("S2 = "); acb_poly_printd(S2, 15); flint_printf("\n\n"); flint_printf("C1 = "); acb_poly_printd(C1, 15); flint_printf("\n\n"); flint_printf("C2 = "); acb_poly_printd(C2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(X); acb_poly_clear(S1); acb_poly_clear(S2); acb_poly_clear(C1); acb_poly_clear(C2); acb_poly_clear(T); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-gamma_lower.c000066400000000000000000000120011461254215100215470ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_gamma_lower, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a0, a1, b, z, w0, w1, t, u, enz; slong prec0, prec1; int regularized; acb_init(a0); acb_init(a1); acb_init(b); acb_init(z); acb_init(w0); acb_init(w1); acb_init(t); acb_init(u); acb_init(enz); regularized = n_randint(state, 3); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); acb_randtest_param(a0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_add_ui(a1, a0, 1, prec0); acb_hypgeom_gamma_lower(w0, a0, z, regularized, prec0); acb_hypgeom_gamma_lower(w1, a1, z, regularized, prec1); acb_neg(enz, z); acb_exp(enz, enz, prec0); /* recurrence relations */ if (regularized == 2) { /* gamma^{*}(a,z) - exp(-z)/Gamma(a+1) - z gamma^{*}(a+1,z) = 0 */ /* http://dlmf.nist.gov/8.8.E4 */ acb_set(t, w0); acb_rgamma(u, a1, prec0); acb_submul(t, enz, u, prec0); acb_submul(t, z, w1, prec0); } else if (regularized == 1) { /* P(a,z) - exp(-z) z^a / Gamma(a+1) - P(a+1,z) = 0 */ /* http://dlmf.nist.gov/8.8.E5 */ acb_pow(u, z, a0, prec0); acb_rgamma(b, a1, prec0); acb_mul(u, u, b, prec0); acb_sub(t, w0, w1, prec0); acb_submul(t, enz, u, prec0); } else { /* a gamma(a,z) - exp(-z) z^a - gamma(a+1,z) = 0 */ /* http://dlmf.nist.gov/8.8.E1 */ acb_pow(u, z, a0, prec0); acb_mul(t, a0, w0, prec0); acb_submul(t, enz, u, prec0); acb_sub(t, t, w1, prec0); } if (!acb_contains_zero(t)) { flint_printf("FAIL: recurrence relation\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a0 = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } /* identities relating lower and upper incomplete gamma functions */ if (regularized == 0 || regularized == 1) { acb_t u0; acb_init(u0); acb_hypgeom_gamma_upper(u0, a0, z, regularized, prec0); acb_zero(t); if (regularized == 1) { /* P(s,z) + Q(s,z) - 1 = 0 */ /* http://dlmf.nist.gov/8.2.E5 */ acb_add(t, w0, u0, prec0); acb_sub_ui(t, t, 1, prec0); } else { /* gamma(s,z) + Gamma(s,z) - Gamma(s) = 0 */ /* excludes non-positive integer values of s */ /* http://dlmf.nist.gov/8.2.E3 */ if (!acb_is_int(a0) || arb_is_positive(acb_realref(a0))) { acb_gamma(b, a0, prec0); acb_add(t, w0, u0, prec0); acb_sub(t, t, b, prec0); } } if (!acb_contains_zero(t)) { flint_printf("FAIL: lower plus upper\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a0 = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(u0); } acb_clear(a0); acb_clear(a1); acb_clear(b); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(t); acb_clear(u); acb_clear(enz); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-gamma_lower_series.c000066400000000000000000000140641461254215100231340ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_gamma_lower_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; acb_t s, t, c; int regularized; regularized = n_randint(state, 3); bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(s); acb_init(t); acb_init(c); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); if (n_randint(state, 10)) { acb_randtest(s, state, bits1, 3); } else { fmpz_t k; fmpz_init(k); fmpz_randtest(k, state, 100); acb_set_fmpz(s, k); fmpz_clear(k); } acb_hypgeom_gamma_lower_series(A, s, S, regularized, n1, bits2); acb_hypgeom_gamma_lower_series(B, s, S, regularized, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL (consistency)\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("C = "); acb_poly_printd(C, 15); flint_printf("\n\n"); flint_abort(); } /* f(h(x)) = exp(-h(x)) h(x)^(s-1) */ acb_poly_neg(C, S); acb_poly_exp_series(C, C, n1, bits2); acb_sub_ui(t, s, 1, bits2); acb_poly_pow_acb_series(B, S, t, n1, bits2); acb_poly_mullow(C, C, B, n1, bits2); if (regularized == 0) { /* integral(f(h(x)) h'(x))' = f(h(x)) h'(x) */ acb_poly_derivative(B, S, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_poly_truncate(C, n1 - 1); } else if (regularized == 1) { /* (integral(f(h(x)) h'(x)) / c)' = (f(h(x)) h'(x)) / c */ acb_poly_derivative(B, S, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_gamma(c, s, bits2); acb_poly_scalar_div(C, C, c, bits2); acb_poly_truncate(C, n1 - 1); } else if (regularized == 2) { if (acb_is_int(s) && arf_sgn(arb_midref(acb_realref(s))) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), 30) < 0) { /* (h(x)^-s)' = -s h(x)^-(s+1) h'(x) */ acb_poly_derivative(C, S, bits2); acb_add_ui(t, s, 1, bits2); acb_neg(t, t); acb_poly_pow_acb_series(B, S, t, n1, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_poly_scalar_mul(C, C, s, bits2); acb_poly_neg(C, C); acb_poly_truncate(C, n1 - 1); } else { /* (h(x)^-s integral(f(h(x)) h'(x)) / c)' = * h(x)^-(s+1) (h(x) f(h(x)) - s integral(f(h(x)) h'(x))) h'(x) / c */ acb_poly_t D; acb_poly_init(D); acb_poly_derivative(B, S, bits2); acb_poly_mullow(D, C, B, n1, bits2); acb_poly_integral(D, D, bits2); acb_poly_scalar_mul(D, D, s, bits2); acb_poly_mullow(C, C, S, n1, bits2); acb_poly_sub(D, C, D, bits2); acb_add_ui(t, s, 1, bits2); acb_neg(t, t); acb_poly_pow_acb_series(B, S, t, n1, bits2); acb_poly_mullow(C, D, B, n1, bits2); acb_poly_derivative(B, S, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_gamma(c, s, bits2); acb_poly_scalar_div(C, C, c, bits2); acb_poly_truncate(C, n1 - 1); acb_poly_clear(D); } } acb_poly_derivative(B, A, bits2); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL (derivative)\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("C = "); acb_poly_printd(C, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_gamma_lower_series(S, s, S, regularized, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_clear(s); acb_clear(t); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-gamma_stirling_sum.c000066400000000000000000000030601461254215100231430ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_gamma_stirling_sum, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z, s1, s2; slong prec, N, K; prec = 2 + n_randint(state, 800); N = n_randint(state, 200); K = n_randint(state, 20); acb_init(z); acb_init(s1); acb_init(s2); acb_randtest(z, state, prec, 10 + n_randint(state, 200)); acb_hypgeom_gamma_stirling_sum_horner(s1, z, N, prec); acb_hypgeom_gamma_stirling_sum_improved(s2, z, N, K, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("N = %wd, K = %wd, prec = %wd\n\n", N, K, prec); flint_printf("z = "); acb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(z); acb_clear(s1); acb_clear(s2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-gamma_taylor.c000066400000000000000000000104661461254215100217460ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_gamma_taylor, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, s1, s2, a, b; slong prec, ebits, prec2; int success, success2, alias, reciprocal; if (n_randint(state, 10) == 0) prec = 2 + n_randint(state, 4000); else prec = 2 + n_randint(state, 300); if (n_randint(state, 10) == 0) ebits = 100; else ebits = 10; prec2 = prec + 1 + n_randint(state, 30); acb_init(x); acb_init(s1); acb_init(s2); acb_init(a); acb_init(b); acb_randtest(x, state, prec, ebits); acb_randtest(s1, state, prec, 10); acb_randtest(s2, state, prec, 10); alias = n_randint(state, 2); reciprocal = n_randint(state, 2); if (alias) { success = acb_hypgeom_gamma_taylor(s1, x, reciprocal, prec); } else { acb_set(s1, x); success = acb_hypgeom_gamma_taylor(s1, s1, reciprocal, prec); } if (success) { /* printf("%ld\n", iter); */ /* Compare with Stirling series algorithm. */ acb_hypgeom_gamma_stirling(s2, x, reciprocal, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); acb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); acb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); acb_printd(s1, 1000); flint_printf("\n\n"); flint_abort(); } /* Compare with different level of precision. */ success2 = acb_hypgeom_gamma_taylor(s2, x, reciprocal, prec2); if (success2 && !acb_overlaps(s1, s2)) { flint_printf("FAIL (2)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); acb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); acb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_abort(); } acb_get_mid(a, x); if (n_randint(state, 2)) { arf_set_mag(arb_midref(acb_realref(b)), arb_radref(acb_realref(x))); arf_set_mag(arb_midref(acb_imagref(b)), arb_radref(acb_imagref(x))); if (n_randint(state, 2)) acb_neg(b, b); if (n_randint(state, 2)) acb_conj(b, b); acb_add(a, a, b, prec2); } success2 = acb_hypgeom_gamma_taylor(s2, a, reciprocal, prec2); if (success2 && !acb_overlaps(s1, s2)) { flint_printf("FAIL (3)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); acb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); acb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_abort(); } } acb_clear(x); acb_clear(s1); acb_clear(s2); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-gamma_upper.c000066400000000000000000000255001461254215100215620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" int _mag_gt_norm_ui(const mag_t a, const mag_t b, const mag_t c, ulong n); static void _accuracy_regression_test(const acb_t s, const acb_t z, int regularized, slong prec, slong issue, slong accuracy) { acb_t g; acb_init(g); acb_hypgeom_gamma_upper(g, s, z, regularized, prec); if (acb_rel_accuracy_bits(g) < accuracy) { flint_printf("FAIL: accuracy regression in issue #%wd\n\n", issue); flint_printf("prec = %wd\n\n", prec); flint_printf("regularized = %d\n\n", regularized); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("g = "); acb_printd(g, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(g); } TEST_FUNCTION_START(acb_hypgeom_gamma_upper, state) { slong iter; /* special accuracy test -- see nemo #38 */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, z, res; slong prec, goal; int regularized; acb_init(a); acb_init(z); acb_init(res); acb_set_si(a, n_randint(state, 100) - 50); do { acb_set_si(z, n_randint(state, 100) - 50); } while (acb_is_zero(z)); regularized = n_randint(state, 3); goal = 2 + n_randint(state, 4000); for (prec = 2 + n_randint(state, 1000); ; prec *= 2) { acb_hypgeom_gamma_upper(res, a, z, regularized, prec); if (acb_rel_accuracy_bits(res) > goal) break; if (prec > 10000) { printf("FAIL (convergence)\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res = "); acb_printd(res, 30); flint_printf("\n\n"); flint_abort(); } } acb_clear(a); acb_clear(z); acb_clear(res); } for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a0, a1, b, z, w0, w1, t, u; slong prec0, prec1; int regularized; acb_init(a0); acb_init(a1); acb_init(b); acb_init(z); acb_init(w0); acb_init(w1); acb_init(t); acb_init(u); regularized = n_randint(state, 3); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); acb_randtest_param(a0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_add_ui(a1, a0, 1, prec0); switch (n_randint(state, 4)) { case 0: acb_hypgeom_gamma_upper_asymp(w0, a0, z, regularized, prec0); break; case 1: acb_hypgeom_gamma_upper_1f1a(w0, a0, z, regularized, prec0); break; case 2: acb_hypgeom_gamma_upper_1f1b(w0, a0, z, regularized, prec0); break; default: acb_hypgeom_gamma_upper(w0, a0, z, regularized, prec0); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_gamma_upper_asymp(w1, a0, z, regularized, prec1); break; case 1: acb_hypgeom_gamma_upper_1f1a(w1, a0, z, regularized, prec1); break; case 2: acb_hypgeom_gamma_upper_1f1b(w1, a0, z, regularized, prec1); break; default: acb_hypgeom_gamma_upper(w1, a0, z, regularized, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("a0 = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_gamma_upper_asymp(w1, a1, z, regularized, prec1); break; case 1: acb_hypgeom_gamma_upper_1f1a(w1, a1, z, regularized, prec1); break; case 2: acb_hypgeom_gamma_upper_1f1b(w1, a1, z, regularized, prec1); break; default: acb_hypgeom_gamma_upper(w1, a1, z, regularized, prec1); } if (regularized == 2) { /* a R(a,z) + exp(-z) - z R(a+1,z) = 0 */ acb_one(t); acb_neg(u, z); acb_exp(u, u, prec0); acb_mul(t, t, u, prec0); acb_mul(b, w1, z, prec0); acb_addmul(t, a0, w0, prec0); acb_sub(t, t, b, prec0); } else if (regularized == 1) { /* Q(a,z) + exp(-z) z^a / Gamma(a+1) - Q(a+1,z) = 0 */ /* http://dlmf.nist.gov/8.8.E6 */ acb_pow(t, z, a0, prec0); acb_rgamma(u, a1, prec0); acb_mul(t, t, u, prec0); acb_neg(u, z); acb_exp(u, u, prec0); acb_mul(t, t, u, prec0); acb_add(t, t, w0, prec0); acb_sub(t, t, w1, prec0); } else { /* a Gamma(a,z) + exp(-z) z^a - Gamma(a+1,z) = 0 */ /* http://dlmf.nist.gov/8.8.E2 */ acb_pow(t, z, a0, prec0); acb_neg(u, z); acb_exp(u, u, prec0); acb_mul(t, t, u, prec0); acb_addmul(t, a0, w0, prec0); acb_sub(t, t, w1, prec0); } if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a0 = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a0); acb_clear(a1); acb_clear(b); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(t); acb_clear(u); } /* Accuracy regression tests. */ { acb_t s, z; slong prec, issue, accuracy; acb_init(s); acb_init(z); issue = 166; prec = 165; accuracy = 100; acb_zero(s); acb_set_si(z, 110); _accuracy_regression_test(s, z, 2, prec, issue, accuracy); issue = 276; prec = 300; accuracy = 100; acb_set_ui(s, 357); acb_set_ui(z, 356); _accuracy_regression_test(s, z, 0, prec, issue, accuracy); arb_set_str(acb_realref(s), "356.123", prec); arb_set_str(acb_realref(z), "356.456", prec); _accuracy_regression_test(s, z, 0, prec, issue, accuracy); arb_set_str(acb_realref(s), "357.123", prec); arb_set_str(acb_realref(z), "356.456", prec); _accuracy_regression_test(s, z, 0, prec, issue, accuracy); arb_set_str(acb_realref(s), "357.456", prec); arb_set_str(acb_realref(z), "356.123", prec); _accuracy_regression_test(s, z, 0, prec, issue, accuracy); acb_clear(s); acb_clear(z); } /* Norm comparison tests (compare a^n to b^n + c^n). */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong prec; ulong n; arb_t a, b, c, u, v, w, rhs; arb_init(a); arb_init(b); arb_init(c); arb_init(u); arb_init(v); arb_init(w); arb_init(rhs); prec = n_randint(state, 1000) + 1; while (!arb_is_positive(a)) { arb_randtest(a, state, n_randint(state, 1000)+1, n_randint(state, 100)+1); } while (!arb_is_positive(b)) { arb_randtest(b, state, n_randint(state, 1000)+1, n_randint(state, 100)+1); } while (!arb_is_positive(c)) { arb_randtest(c, state, n_randint(state, 1000)+1, n_randint(state, 100)+1); } if (n_randint(state, 20)) arb_zero(a); if (n_randint(state, 20)) arb_zero(b); if (n_randint(state, 20)) arb_zero(c); if (n_randint(state, 20)) arb_set(b, a); if (n_randint(state, 20)) arb_set(c, b); if (n_randint(state, 20)) arb_set(c, a); n = n_randint(state, 10); if (!n) n = WORD_MAX; if (n == WORD_MAX) { arb_set(u, a); arb_max(rhs, b, c, prec); } else { arb_pow_ui(u, a, n, prec); arb_pow_ui(v, b, n, prec); arb_pow_ui(w, c, n, prec); arb_add(rhs, v, w, prec); } if (arb_lt(u, rhs) || (arb_is_exact(u) && arb_equal(u, rhs))) { mag_t ma, mb, mc; mag_init(ma); mag_init(mb); mag_init(mc); arb_get_mag_lower(ma, a); arb_get_mag(mb, b); arb_get_mag(mc, c); if (_mag_gt_norm_ui(ma, mb, mc, n)) { flint_printf("FAIL: _mag_gt_norm_ui\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 30); flint_printf("\n\n"); flint_printf("n = %ld\n\n", n); flint_abort(); } mag_clear(ma); mag_clear(mb); mag_clear(mc); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(u); arb_clear(v); arb_clear(w); arb_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-gamma_upper_series.c000066400000000000000000000120301461254215100231260ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_gamma_upper_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; acb_t s, t, c; int regularized; regularized = n_randint(state, 3); bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(s); acb_init(t); acb_init(c); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_randtest(s, state, bits1, 3); acb_hypgeom_gamma_upper_series(A, s, S, regularized, n1, bits2); acb_hypgeom_gamma_upper_series(B, s, S, regularized, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL (consistency)\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("C = "); acb_poly_printd(C, 15); flint_printf("\n\n"); flint_abort(); } /* f(h(x)) = -exp(-h(x)) h(x)^(s-1) */ acb_poly_neg(C, S); acb_poly_exp_series(C, C, n1, bits2); acb_sub_ui(t, s, 1, bits2); acb_poly_pow_acb_series(B, S, t, n1, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_poly_neg(C, C); if (regularized == 0) { /* integral(f(h(x)) h'(x))' = f(h(x)) h'(x) */ acb_poly_derivative(B, S, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_poly_truncate(C, n1 - 1); } else if (regularized == 1) { /* (integral(f(h(x)) h'(x)) / c)' = (f(h(x)) h'(x)) / c */ acb_poly_derivative(B, S, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_gamma(c, s, bits2); acb_poly_scalar_div(C, C, c, bits2); acb_poly_truncate(C, n1 - 1); } else if (regularized == 2) { /* (h(x)^-s integral(f(h(x)) h'(x)))' = * h(x)^-(s+1) (h(x) f(h(x)) - s integral(f(h(x)) h'(x))) h'(x) */ acb_poly_t D; acb_poly_init(D); acb_poly_derivative(B, S, bits2); acb_poly_mullow(D, C, B, n1, bits2); acb_poly_integral(D, D, bits2); acb_poly_scalar_mul(D, D, s, bits2); acb_poly_mullow(C, C, S, n1, bits2); acb_poly_sub(D, C, D, bits2); acb_add_ui(t, s, 1, bits2); acb_neg(t, t); acb_poly_pow_acb_series(B, S, t, n1, bits2); acb_poly_mullow(C, D, B, n1, bits2); acb_poly_derivative(B, S, bits2); acb_poly_mullow(C, C, B, n1, bits2); acb_poly_truncate(C, n1 - 1); acb_poly_clear(D); } acb_poly_derivative(B, A, bits2); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL (derivative)\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("C = "); acb_poly_printd(C, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_gamma_upper_series(S, s, S, regularized, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_clear(s); acb_clear(t); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-gegenbauer_c.c000066400000000000000000000050011461254215100216650ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_gegenbauer_c, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, m, z, t, u, res1, res2; slong prec1, prec2; acb_init(n); acb_init(m); acb_init(z); acb_init(t); acb_init(u); acb_init(res1); acb_init(res2); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); if (n_randint(state, 2)) { acb_set_si(m, n_randint(state, 20) - 10); acb_set_si(n, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), 10); acb_randtest_param(m, state, 1 + n_randint(state, 400), 10); } acb_randtest_param(z, state, 1 + n_randint(state, 400), 10); acb_hypgeom_gegenbauer_c(res1, n, m, z, prec1); acb_one(t); acb_mul_2exp_si(t, t, -1); acb_sub(t, m, t, prec2); acb_hypgeom_jacobi_p(res2, n, t, t, z, prec2); acb_add_ui(t, t, 1, prec2); acb_rising(t, t, n, prec2); acb_div(res2, res2, t, prec2); acb_mul_2exp_si(t, m, 1); acb_rising(t, t, n, prec2); acb_mul(res2, res2, t, prec2); if (!acb_overlaps(res1, res2)) { flint_printf("FAIL: consistency 1\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(m); acb_clear(z); acb_clear(t); acb_clear(u); acb_clear(res1); acb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-hermite_h.c000066400000000000000000000045661461254215100212420ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_hermite_h, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, n1, n2, z, res1, res2, res3, s; slong prec1, prec2, prec3; acb_init(n); acb_init(n1); acb_init(n2); acb_init(z); acb_init(res1); acb_init(res2); acb_init(res3); acb_init(s); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); prec3 = 2 + n_randint(state, 300); acb_randtest_param(n, state, 1 + n_randint(state, 400), 10); acb_sub_ui(n1, n, 1, prec1); acb_sub_ui(n2, n, 2, prec1); acb_randtest_param(z, state, 1 + n_randint(state, 400), 10); acb_randtest_param(res1, state, 1 + n_randint(state, 400), 10); acb_hypgeom_hermite_h(res1, n, z, prec1); acb_hypgeom_hermite_h(res2, n1, z, prec2); acb_hypgeom_hermite_h(res3, n2, z, prec3); acb_mul(s, res2, z, prec1); acb_submul(s, res3, n1, prec1); acb_mul_2exp_si(s, s, 1); if (!acb_overlaps(res1, s)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_printf("res3 = "); acb_printd(res3, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(n1); acb_clear(n2); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(res3); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-jacobi_p.c000066400000000000000000000056131461254215100210360ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_jacobi_p, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, a, b, n1, a1, b1, z, res1, res2, res3, s; slong prec; acb_init(n); acb_init(a); acb_init(b); acb_init(n1); acb_init(a1); acb_init(b1); acb_init(z); acb_init(res1); acb_init(res2); acb_init(res3); acb_init(s); prec = 2 + n_randint(state, 300); if (n_randint(state, 2)) { acb_set_si(n, n_randint(state, 20) - 10); acb_set_si(a, n_randint(state, 20) - 10); acb_set_si(b, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), 10); acb_randtest_param(a, state, 1 + n_randint(state, 400), 10); acb_randtest_param(b, state, 1 + n_randint(state, 400), 10); } acb_randtest_param(z, state, 1 + n_randint(state, 400), 10); acb_sub_ui(n1, n, 1, prec); acb_sub_ui(a1, a, 1, prec); acb_sub_ui(b1, b, 1, prec); acb_hypgeom_jacobi_p(res1, n, a, b1, z, prec); acb_hypgeom_jacobi_p(res2, n, a1, b, z, 2 + n_randint(state, 300)); acb_hypgeom_jacobi_p(res3, n1, a, b, z, 2 + n_randint(state, 300)); acb_sub(s, res1, res2, prec); if (!acb_overlaps(s, res3)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_printf("res3 = "); acb_printd(res3, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(a); acb_clear(b); acb_clear(n1); acb_clear(a1); acb_clear(b1); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(res3); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-laguerre_l.c000066400000000000000000000051471461254215100214130ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_laguerre_l, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, m, n1, m1, z, res1, res2, res3, s; slong prec; acb_init(n); acb_init(m); acb_init(n1); acb_init(m1); acb_init(z); acb_init(res1); acb_init(res2); acb_init(res3); acb_init(s); prec = 2 + n_randint(state, 200); if (n_randint(state, 2)) { acb_set_si(n, n_randint(state, 20) - 10); acb_set_si(m, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), 10); acb_randtest_param(m, state, 1 + n_randint(state, 400), 10); } acb_randtest_param(z, state, 1 + n_randint(state, 400), 10); acb_sub_ui(n1, n, 1, prec); acb_sub_ui(m1, m, 1, prec); acb_hypgeom_laguerre_l(res1, n, m, z, prec); acb_hypgeom_laguerre_l(res2, n1, m, z, 2 + n_randint(state, 200)); acb_hypgeom_laguerre_l(res3, n, m1, z, 2 + n_randint(state, 200)); acb_add(s, res2, res3, prec); if (acb_is_finite(res1) && acb_is_finite(s) && !acb_overlaps(res1, s)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_printf("res3 = "); acb_printd(res3, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(m); acb_clear(n1); acb_clear(m1); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(res3); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-legendre_p.c000066400000000000000000000063221461254215100213720ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_legendre_p, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, na, nb, m, z, res1, res2, res3, t, u; slong prec1, prec2, ebits; int type; acb_init(n); acb_init(na); acb_init(nb); acb_init(m); acb_init(z); acb_init(res1); acb_init(res2); acb_init(res3); acb_init(t); acb_init(u); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 10); if (n_randint(state, 2)) { acb_set_si(m, n_randint(state, 20) - 10); acb_set_si(n, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), ebits); acb_randtest_param(m, state, 1 + n_randint(state, 400), ebits); } acb_randtest_param(z, state, 1 + n_randint(state, 400), ebits); acb_sub_ui(na, n, 1, prec2); acb_add_ui(nb, n, 1, prec2); type = n_randint(state, 2); acb_hypgeom_legendre_p(res1, n, m, z, type, prec1); acb_hypgeom_legendre_p(res2, na, m, z, type, prec2); acb_hypgeom_legendre_p(res3, nb, m, z, type, prec2); acb_add(t, n, m, prec2); acb_mul(t, t, res2, prec2); acb_sub(u, n, m, prec2); acb_add_ui(u, u, 1, prec2); acb_mul(u, u, res3, prec2); acb_add(t, t, u, prec2); acb_mul_2exp_si(u, n, 1); acb_add_ui(u, u, 1, prec2); acb_mul(u, u, z, prec2); acb_mul(u, u, res1, prec2); if (!acb_overlaps(t, u)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("type = %d\n\n", type); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_printf("res3 = "); acb_printd(res3, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_printf("u = "); acb_printd(u, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(na); acb_clear(nb); acb_clear(m); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(res3); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-legendre_q.c000066400000000000000000000122411461254215100213700ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" /* these functions are not public for now */ void _acb_hypgeom_legendre_q_single(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec); void _acb_hypgeom_legendre_q_double(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec); TEST_FUNCTION_START(acb_hypgeom_legendre_q, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, m, z, res1, res2; slong prec1, prec2, ebits; acb_init(n); acb_init(m); acb_init(z); acb_init(res1); acb_init(res2); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 10); if (n_randint(state, 2)) { acb_set_si(m, n_randint(state, 20) - 10); acb_set_si(n, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), ebits); acb_randtest_param(m, state, 1 + n_randint(state, 400), ebits); } acb_randtest_param(z, state, 1 + n_randint(state, 400), ebits); _acb_hypgeom_legendre_q_single(res1, n, m, z, prec1); _acb_hypgeom_legendre_q_double(res2, n, m, z, prec2); if (!acb_overlaps(res1, res2)) { flint_printf("FAIL: consistency 1\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(m); acb_clear(z); acb_clear(res1); acb_clear(res2); } for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t n, m, z, res1, res2, t, u; slong prec1, prec2, ebits; int type; acb_init(n); acb_init(m); acb_init(z); acb_init(res1); acb_init(res2); acb_init(t); acb_init(u); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 10); if (n_randint(state, 2)) { acb_set_si(m, n_randint(state, 20) - 10); acb_set_si(n, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), ebits); acb_randtest_param(m, state, 1 + n_randint(state, 400), ebits); } acb_randtest_param(z, state, 1 + n_randint(state, 400), ebits); type = n_randint(state, 2); acb_hypgeom_legendre_q(res1, n, m, z, type, prec1); acb_neg(t, m); acb_hypgeom_legendre_p(res2, n, t, z, type, prec2); acb_add(u, m, n, prec2); acb_add_ui(u, u, 1, prec2); acb_gamma(u, u, prec2); acb_mul(res2, res2, u, prec2); acb_sub(u, n, m, prec2); acb_add_ui(u, u, 1, prec2); acb_rgamma(u, u, prec2); acb_mul(res2, res2, u, prec2); acb_hypgeom_legendre_p(t, n, m, z, type, prec2); if (type == 0) { acb_cos_pi(u, m, prec2); acb_mul(t, t, u, prec2); } acb_sub(res2, t, res2, prec2); if (type == 1) { acb_exp_pi_i(t, m, prec2); acb_mul(res2, res2, t, prec2); } acb_sin_pi(t, m, prec2); if (acb_contains_zero(t)) acb_indeterminate(res2); else acb_div(res2, res2, t, prec2); acb_const_pi(t, prec2); acb_mul(res2, res2, t, prec2); acb_mul_2exp_si(res2, res2, -1); if (!acb_overlaps(res1, res2)) { flint_printf("FAIL: consistency 2\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("type = %d\n\n", type); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(n); acb_clear(m); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-lgamma.c000066400000000000000000000063741461254215100205330ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_lgamma, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z, s1, s2, a, b; slong prec, ebits, prec2; prec = 2 + n_randint(state, 200); if (n_randint(state, 10) == 0) prec = 2 + n_randint(state, 1000); if (n_randint(state, 10) == 0) ebits = 100; else ebits = 10; ebits = 2; prec2 = 2 + n_randint(state, 200); acb_init(z); acb_init(s1); acb_init(s2); acb_init(a); acb_init(b); acb_randtest(z, state, prec, ebits); acb_randtest(s1, state, prec, 10); acb_randtest(s2, state, prec, 10); if (n_randint(state, 2)) { acb_hypgeom_lgamma(s1, z, prec); } else { acb_set(s1, z); acb_hypgeom_lgamma(s1, s1, prec); } acb_add_ui(s2, z, 1, prec2); acb_hypgeom_lgamma(s2, s2, prec2); acb_log(a, z, prec2); acb_sub(s2, s2, a, prec2); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("z = "); acb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); acb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); acb_printd(s1, 1000); flint_printf("\n\n"); flint_abort(); } acb_get_mid(a, z); if (n_randint(state, 2)) { arf_set_mag(arb_midref(acb_realref(b)), arb_radref(acb_realref(z))); arf_set_mag(arb_midref(acb_imagref(b)), arb_radref(acb_imagref(z))); if (n_randint(state, 2)) acb_neg(b, b); if (n_randint(state, 2)) acb_conj(b, b); acb_add(a, a, b, prec); } acb_hypgeom_lgamma(s2, a, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL (2)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("z = "); acb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); acb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); acb_printd(s1, 1000); flint_printf("\n\n"); flint_abort(); } acb_clear(z); acb_clear(s1); acb_clear(s2); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-li_series.c000066400000000000000000000053351461254215100212470ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_li_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, n3, bits1, bits2, bits3; acb_poly_t S, A, B, C, T, U; int offset; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); n3 = FLINT_MIN(n1, n2); offset = n_randint(state, 2); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_init(T); acb_poly_init(U); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_li_series(A, S, offset, n1, bits2); acb_hypgeom_li_series(B, S, offset, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, n3); acb_poly_truncate(B, n3); /* [li(h(x))]' log(h(x)) = h'(x) */ acb_poly_derivative(T, A, bits2); acb_poly_log_series(U, S, n3, bits2); acb_poly_mullow(T, T, U, FLINT_MAX(0, n3 - 1), bits2); acb_poly_derivative(U, S, bits2); acb_poly_truncate(U, FLINT_MAX(0, n3 - 1)); if (!acb_poly_overlaps(B, C) || !acb_poly_overlaps(T, U)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("T = "); acb_poly_printd(T, 15); flint_printf("\n\n"); flint_printf("U = "); acb_poly_printd(U, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_li_series(S, S, offset, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(T); acb_poly_clear(U); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-log_rising_ui.c000066400000000000000000000072601461254215100221210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_log_rising_ui_naive(acb_t res, const acb_t z, ulong r, slong prec) { acb_t t, u; slong k; acb_init(t); acb_init(u); for (k = 0; k < r; k++) { acb_add_ui(t, z, k, prec); acb_log(t, t, prec); acb_add(u, u, t, prec); } acb_swap(res, u); acb_clear(t); acb_clear(u); } TEST_FUNCTION_START(acb_hypgeom_log_rising_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z, s1, s2, a, b; slong prec, ebits, prec2; ulong n; prec = 2 + n_randint(state, 100); if (n_randint(state, 10) == 0) ebits = 100; else ebits = 10; ebits = 2; prec2 = prec + 1 + n_randint(state, 30); acb_init(z); acb_init(s1); acb_init(s2); acb_init(a); acb_init(b); acb_randtest(z, state, prec, ebits); acb_randtest(s1, state, prec, 10); acb_randtest(s2, state, prec, 10); n = n_randint(state, 20); if (n_randint(state, 20) == 0) n = n_randint(state, 200); if (n_randint(state, 2)) { acb_hypgeom_log_rising_ui(s1, z, n, prec); } else { acb_set(s1, z); acb_hypgeom_log_rising_ui(s1, s1, n, prec); } acb_hypgeom_log_rising_ui_naive(s2, z, n, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("n = %wu\n\n", n); flint_printf("z = "); acb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); acb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); acb_printd(s1, 1000); flint_printf("\n\n"); flint_abort(); } acb_get_mid(a, z); if (n_randint(state, 2)) { arf_set_mag(arb_midref(acb_realref(b)), arb_radref(acb_realref(z))); arf_set_mag(arb_midref(acb_imagref(b)), arb_radref(acb_imagref(z))); if (n_randint(state, 2)) acb_neg(b, b); if (n_randint(state, 2)) acb_conj(b, b); acb_add(a, a, b, prec); } acb_hypgeom_log_rising_ui(s2, a, n, prec); if (!acb_overlaps(s1, s2)) { flint_printf("FAIL (2)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("n = %wu\n\n", n); flint_printf("z = "); acb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("a = "); acb_printn(a, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); acb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); acb_printn(s2, 1000, 0); flint_printf("\n\n"); acb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); acb_printd(s1, 1000); flint_printf("\n\n"); flint_abort(); } acb_clear(z); acb_clear(s1); acb_clear(s2); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-log_rising_ui_jet.c000066400000000000000000000052441461254215100227630ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_log_rising_ui_jet, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z; acb_ptr s1, s2, s3, s4; slong prec, ebits, len, len1, len2, len3, len4; ulong n, m; prec = 2 + n_randint(state, 100); len = n_randint(state, 5); len1 = len + n_randint(state, 2); len2 = len + n_randint(state, 2); len3 = len + n_randint(state, 2); len4 = len + n_randint(state, 2); if (n_randint(state, 10) == 0) ebits = 100; else ebits = 10; ebits = 2; acb_init(z); s1 = _acb_vec_init(FLINT_MAX(1, len1)); s2 = _acb_vec_init(FLINT_MAX(1, len2)); s3 = _acb_vec_init(FLINT_MAX(1, len3)); s4 = _acb_vec_init(FLINT_MAX(1, len4)); acb_randtest(z, state, prec, ebits); acb_randtest(s1, state, prec, 10); acb_randtest(s2, state, prec, 10); n = n_randint(state, 8); m = n_randint(state, 8); acb_hypgeom_log_rising_ui_jet(s1, z, n + m, len1, prec); acb_hypgeom_log_rising_ui_jet(s2, z, n, len2, prec); acb_add_ui(s4, z, n, prec); acb_hypgeom_log_rising_ui_jet(s3, s4, m, len3, prec); _acb_vec_add(s4, s2, s3, len, prec); if (!_acb_poly_overlaps(s1, len, s4, len)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("n = %wu, m = %lu\n\n", n, m); flint_printf("z = "); acb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); _acb_vec_printn(s1, len, 30, 0); flint_printf("\n\n"); flint_printf("s2 = "); _acb_vec_printn(s2, len, 30, 0); flint_printf("\n\n"); flint_printf("s3 = "); _acb_vec_printn(s3, len, 30, 0); flint_printf("\n\n"); flint_printf("s4 = "); _acb_vec_printn(s4, len, 30, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(z); _acb_vec_clear(s1, FLINT_MAX(1, len1)); _acb_vec_clear(s2, FLINT_MAX(1, len2)); _acb_vec_clear(s3, FLINT_MAX(1, len3)); _acb_vec_clear(s4, FLINT_MAX(1, len4)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-m.c000066400000000000000000000205041461254215100175200ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_m, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a0, a1, a2, b, z, w0, w1, w2, t, u; slong prec0, prec1, prec2; int regularized, ebits; acb_init(a0); acb_init(a1); acb_init(a2); acb_init(b); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 700); prec1 = 2 + n_randint(state, 700); prec2 = 2 + n_randint(state, 700); if (n_randint(state, 5) == 0) ebits = 100; else ebits = 10; acb_randtest_param(a0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest_param(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, ebits)); regularized = n_randint(state, 2); if (prec0 <= 300 && prec1 <= 300 && prec2 <= 300 && n_randint(state, 2)) { arb_zero(acb_imagref(a0)); arb_zero(acb_imagref(b)); arb_zero(acb_imagref(z)); } acb_add_ui(a1, a0, 1, prec0); acb_add_ui(a2, a0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_m_asymp(w0, a0, b, z, regularized, prec0); break; case 1: acb_hypgeom_m_1f1(w0, a0, b, z, regularized, prec0); break; default: acb_hypgeom_m(w0, a0, b, z, regularized, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_m_asymp(w1, a0, b, z, regularized, prec1); break; case 1: acb_hypgeom_m_1f1(w1, a0, b, z, regularized, prec1); break; default: acb_hypgeom_m(w1, a0, b, z, regularized, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("regularized = %d\n\n", regularized); flint_printf("a = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_m_asymp(w1, a1, b, z, regularized, prec1); break; case 1: acb_hypgeom_m_1f1(w1, a1, b, z, regularized, prec1); break; default: acb_hypgeom_m(w1, a1, b, z, regularized, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_m_asymp(w2, a2, b, z, regularized, prec2); break; case 1: acb_hypgeom_m_1f1(w2, a2, b, z, regularized, prec2); break; default: acb_hypgeom_m(w2, a2, b, z, regularized, prec2); } /* 1F1(a,b,z) * (a-b+1) */ acb_sub(u, a1, b, prec0); acb_mul(t, w0, u, prec0); /* 1F1(a+1,b,z) * (2a - b + z + 2) */ acb_mul_2exp_si(u, a0, 1); acb_sub(u, u, b, prec0); acb_add(u, u, z, prec0); acb_add_ui(u, u, 2, prec0); acb_submul(t, w1, u, prec0); /* 1F1(a+2,b,z) * -(a+1) */ acb_addmul(t, w2, a1, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("a = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_add_ui(a1, b, 1, prec0); acb_add_ui(a2, b, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_m_asymp(w1, a0, a1, z, regularized, prec1); break; case 1: acb_hypgeom_m_1f1(w1, a0, a1, z, regularized, prec1); break; default: acb_hypgeom_m(w1, a0, a1, z, regularized, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_m_asymp(w2, a0, a2, z, regularized, prec2); break; case 1: acb_hypgeom_m_1f1(w2, a0, a2, z, regularized, prec2); break; default: acb_hypgeom_m(w2, a0, a2, z, regularized, prec2); } if (regularized) { acb_set(t, w0); acb_add(u, b, z, prec0); acb_submul(t, w1, u, prec0); acb_sub(u, a0, a1, prec0); acb_mul(u, u, z, prec0); acb_submul(t, w2, u, prec0); } else { acb_mul(t, w0, b, prec0); acb_mul(t, t, a1, prec0); acb_add(u, b, z, prec0); acb_mul(u, u, a1, prec0); acb_submul(t, w1, u, prec0); acb_sub(u, a0, a1, prec0); acb_mul(u, u, z, prec0); acb_submul(t, w2, u, prec0); } if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation 2\n\n"); flint_printf("a = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_m(a0, a0, b, z, regularized, prec0); acb_set(t, a0); break; case 1: acb_hypgeom_m(b, a0, b, z, regularized, prec0); acb_set(t, b); break; default: acb_hypgeom_m(z, a0, b, z, regularized, prec2); acb_set(t, z); } if (!acb_overlaps(t, w0)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a0); acb_clear(a1); acb_clear(a2); acb_clear(b); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq.c000066400000000000000000000071641461254215100200610ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr a, b; acb_t z, t, res1, res2; slong i, p, q, extend, prec1, prec2; int regularized1, regularized2; p = n_randint(state, 3); q = n_randint(state, 3); extend = n_randint(state, 3); a = _acb_vec_init(p + extend); b = _acb_vec_init(q + extend); acb_init(z); acb_init(t); acb_init(res1); acb_init(res2); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); regularized1 = n_randint(state, 2); regularized2 = n_randint(state, 2); for (i = 0; i < p; i++) { if (n_randint(state, 2)) acb_one(a + i); else acb_randtest_param(a + i, state, 1 + n_randint(state, 200), 3); } for (i = 0; i < q; i++) acb_randtest_param(b + i, state, 1 + n_randint(state, 200), 3); for (i = 0; i < extend; i++) { acb_randtest_param(a + p + i, state, 1 + n_randint(state, 200), 3); acb_set(b + q + i, a + p + i); } acb_randtest_param(z, state, 1 + n_randint(state, 200), 3); acb_hypgeom_pfq(res1, a, p, b, q, z, regularized1, prec1); acb_hypgeom_pfq(res2, a, p + extend, b, q + extend, z, regularized2, prec2); if (regularized1 && !regularized2) { for (i = 0; i < q; i++) { acb_rgamma(t, b + i, prec2); acb_mul(res2, res2, t, prec2); } } else if (regularized2) { if (!regularized1) { for (i = 0; i < q; i++) { acb_rgamma(t, b + i, prec2); acb_mul(res1, res1, t, prec2); } } for (i = 0; i < extend; i++) { acb_rgamma(t, b + q + i, prec2); acb_mul(res1, res1, t, prec2); } } if (!acb_overlaps(res1, res2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("p = %wd, q = %wd, regularized1 = %d, regularized2 = %d\n\n", p, q, regularized1, regularized2); for (i = 0; i < p + extend; i++) { flint_printf("a[%wd] = ", i); acb_printd(a + i, 30); flint_printf("\n\n"); } for (i = 0; i < q + extend; i++) { flint_printf("b[%wd] = ", i); acb_printd(b + i, 30); flint_printf("\n\n"); } flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_abort(); } _acb_vec_clear(a, p + extend); _acb_vec_clear(b, q + extend); acb_clear(z); acb_clear(t); acb_clear(res1); acb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq_series_direct.c000066400000000000000000000065101461254215100227570ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq_series_direct, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_struct a[4], b[4]; acb_poly_t z, s1, s2; slong i, p, q, len1, len2, n1, n2, prec1, prec2; int regularized; p = n_randint(state, 3); q = n_randint(state, 3); len1 = n_randint(state, 8); len2 = n_randint(state, 8); prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); if (n_randint(state, 2)) n1 = -1; else n1 = n_randint(state, 50); if (n_randint(state, 2)) n2 = -1; else n2 = n_randint(state, 50); regularized = n_randint(state, 2); acb_poly_init(z); acb_poly_init(s1); acb_poly_init(s2); for (i = 0; i < p; i++) acb_poly_init(a + i); for (i = 0; i < q; i++) acb_poly_init(b + i); acb_poly_randtest(z, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 10); for (i = 0; i < p; i++) acb_poly_randtest(a + i, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 3); for (i = 0; i < q; i++) acb_poly_randtest(b + i, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 3); acb_hypgeom_pfq_series_direct(s1, a, p, b, q, z, regularized, n1, len1, prec1); acb_hypgeom_pfq_series_direct(s2, a, p, b, q, z, regularized, n2, len2, prec2); acb_poly_truncate(s1, FLINT_MIN(len1, len2)); acb_poly_truncate(s2, FLINT_MIN(len1, len2)); if (!acb_poly_overlaps(s1, s2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("n1 = %wd, n2 = %wd prec1 = %wd, prec2 = %wd\n\n", n1, n2, prec1, prec2); flint_printf("p = %wd, q = %wd\n\n", p, q); flint_printf("z = "); acb_poly_printd(z, 15); flint_printf("\n\n"); for (i = 0; i < p; i++) { flint_printf("a[%wd] = ", i); acb_poly_printd(a + i, 15); flint_printf("\n\n"); } for (i = 0; i < q; i++) { flint_printf("b[%wd] = ", i); acb_poly_printd(b + i, 15); flint_printf("\n\n"); } flint_printf("s1 = "); acb_poly_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); acb_poly_printd(s2, 15); flint_printf("\n\n"); acb_poly_sub(s1, s1, s2, prec1); flint_printf("diff = "); acb_poly_printd(s1, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(z); acb_poly_clear(s1); acb_poly_clear(s2); for (i = 0; i < p; i++) acb_poly_clear(a + i); for (i = 0; i < q; i++) acb_poly_clear(b + i); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq_series_sum_bs.c000066400000000000000000000073241461254215100230010ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq_series_sum_bs, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_struct a[4], b[4]; acb_poly_t z, s1, s2, t1, t2; slong i, p, q, len1, len2, n, prec1, prec2; int regularized; p = n_randint(state, 3); q = n_randint(state, 3); len1 = n_randint(state, 8); len2 = n_randint(state, 8); prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); n = n_randint(state, 50); regularized = n_randint(state, 2); acb_poly_init(z); acb_poly_init(s1); acb_poly_init(s2); acb_poly_init(t1); acb_poly_init(t2); for (i = 0; i < p; i++) acb_poly_init(a + i); for (i = 0; i < q; i++) acb_poly_init(b + i); acb_poly_randtest(z, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 10); for (i = 0; i < p; i++) acb_poly_randtest(a + i, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 3); for (i = 0; i < q; i++) acb_poly_randtest(b + i, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 3); acb_hypgeom_pfq_series_sum_forward(s1, t1, a, p, b, q, z, regularized, n, len1, prec1); acb_hypgeom_pfq_series_sum_bs(s2, t2, a, p, b, q, z, regularized, n, len2, prec2); acb_poly_truncate(s1, FLINT_MIN(len1, len2)); acb_poly_truncate(s2, FLINT_MIN(len1, len2)); acb_poly_truncate(t1, FLINT_MIN(len1, len2)); acb_poly_truncate(t2, FLINT_MIN(len1, len2)); if (!acb_poly_overlaps(s1, s2) || !acb_poly_overlaps(t1, t2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("n = %wd, len1 = %wd, len2 = %wd, prec1 = %wd, prec2 = %wd\n\n", n, len1, len2, prec1, prec2); flint_printf("p = %wd, q = %wd\n\n", p, q); flint_printf("z = "); acb_poly_printd(z, 15); flint_printf("\n\n"); for (i = 0; i < p; i++) { flint_printf("a[%wd] = ", i); acb_poly_printd(a + i, 15); flint_printf("\n\n"); } for (i = 0; i < q; i++) { flint_printf("b[%wd] = ", i); acb_poly_printd(b + i, 15); flint_printf("\n\n"); } flint_printf("s1 = "); acb_poly_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); acb_poly_printd(s2, 15); flint_printf("\n\n"); acb_poly_sub(s1, s1, s2, prec1); flint_printf("diff = "); acb_poly_printd(s1, 15); flint_printf("\n\n"); flint_printf("t1 = "); acb_poly_printd(t1, 15); flint_printf("\n\n"); flint_printf("t2 = "); acb_poly_printd(t2, 15); flint_printf("\n\n"); acb_poly_sub(t1, t1, t2, prec1); flint_printf("diff = "); acb_poly_printd(t1, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(z); acb_poly_clear(s1); acb_poly_clear(s2); for (i = 0; i < p; i++) acb_poly_clear(a + i); for (i = 0; i < q; i++) acb_poly_clear(b + i); acb_poly_clear(t1); acb_poly_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq_series_sum_rs.c000066400000000000000000000073241461254215100230210ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq_series_sum_rs, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_struct a[4], b[4]; acb_poly_t z, s1, s2, t1, t2; slong i, p, q, len1, len2, n, prec1, prec2; int regularized; p = n_randint(state, 3); q = n_randint(state, 3); len1 = n_randint(state, 8); len2 = n_randint(state, 8); prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); n = n_randint(state, 50); regularized = n_randint(state, 2); acb_poly_init(z); acb_poly_init(s1); acb_poly_init(s2); acb_poly_init(t1); acb_poly_init(t2); for (i = 0; i < p; i++) acb_poly_init(a + i); for (i = 0; i < q; i++) acb_poly_init(b + i); acb_poly_randtest(z, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 10); for (i = 0; i < p; i++) acb_poly_randtest(a + i, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 3); for (i = 0; i < q; i++) acb_poly_randtest(b + i, state, 1 + n_randint(state, 10), 1 + n_randint(state, 500), 3); acb_hypgeom_pfq_series_sum_forward(s1, t1, a, p, b, q, z, regularized, n, len1, prec1); acb_hypgeom_pfq_series_sum_rs(s2, t2, a, p, b, q, z, regularized, n, len2, prec2); acb_poly_truncate(s1, FLINT_MIN(len1, len2)); acb_poly_truncate(s2, FLINT_MIN(len1, len2)); acb_poly_truncate(t1, FLINT_MIN(len1, len2)); acb_poly_truncate(t2, FLINT_MIN(len1, len2)); if (!acb_poly_overlaps(s1, s2) || !acb_poly_overlaps(t1, t2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("n = %wd, len1 = %wd, len2 = %wd, prec1 = %wd, prec2 = %wd\n\n", n, len1, len2, prec1, prec2); flint_printf("p = %wd, q = %wd\n\n", p, q); flint_printf("z = "); acb_poly_printd(z, 15); flint_printf("\n\n"); for (i = 0; i < p; i++) { flint_printf("a[%wd] = ", i); acb_poly_printd(a + i, 15); flint_printf("\n\n"); } for (i = 0; i < q; i++) { flint_printf("b[%wd] = ", i); acb_poly_printd(b + i, 15); flint_printf("\n\n"); } flint_printf("s1 = "); acb_poly_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); acb_poly_printd(s2, 15); flint_printf("\n\n"); acb_poly_sub(s1, s1, s2, prec1); flint_printf("diff = "); acb_poly_printd(s1, 15); flint_printf("\n\n"); flint_printf("t1 = "); acb_poly_printd(t1, 15); flint_printf("\n\n"); flint_printf("t2 = "); acb_poly_printd(t2, 15); flint_printf("\n\n"); acb_poly_sub(t1, t1, t2, prec1); flint_printf("diff = "); acb_poly_printd(t1, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(z); acb_poly_clear(s1); acb_poly_clear(s2); for (i = 0; i < p; i++) acb_poly_clear(a + i); for (i = 0; i < q; i++) acb_poly_clear(b + i); acb_poly_clear(t1); acb_poly_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq_sum_bs.c000066400000000000000000000051251461254215100214240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq_sum_bs, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr a, b; acb_t z, s1, s2, t1, t2; slong i, p, q, n, prec1, prec2; p = n_randint(state, 5); q = n_randint(state, 5); n = n_randint(state, 300); prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); acb_init(z); acb_init(s1); acb_init(s2); acb_init(t1); acb_init(t2); acb_randtest_special(z, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(t1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(t2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); a = _acb_vec_init(p); b = _acb_vec_init(q); for (i = 0; i < p; i++) acb_randtest(a + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); for (i = 0; i < q; i++) acb_randtest(b + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_hypgeom_pfq_sum_forward(s1, t1, a, p, b, q, z, n, prec1); acb_hypgeom_pfq_sum_bs(s2, t2, a, p, b, q, z, n, prec2); if (!acb_overlaps(s1, s2) || !acb_overlaps(t1, t2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("z = "); acb_print(a); flint_printf("\n\n"); flint_printf("s1 = "); acb_print(s1); flint_printf("\n\n"); flint_printf("s2 = "); acb_print(s2); flint_printf("\n\n"); flint_printf("t1 = "); acb_print(t1); flint_printf("\n\n"); flint_printf("t2 = "); acb_print(t2); flint_printf("\n\n"); flint_abort(); } _acb_vec_clear(a, p); _acb_vec_clear(b, q); acb_clear(z); acb_clear(s1); acb_clear(s2); acb_clear(t1); acb_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq_sum_fme.c000066400000000000000000000050421461254215100215650ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq_sum_fme, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr a, b; acb_t z, s1, s2, t1, t2; slong i, p, q, n, prec1, prec2; p = n_randint(state, 4); q = n_randint(state, 4); n = n_randint(state, 100); prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); acb_init(z); acb_init(s1); acb_init(s2); acb_init(t1); acb_init(t2); acb_randtest(z, state, 1 + n_randint(state, 500), 1 + n_randint(state, 5)); acb_randtest(s1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 5)); acb_randtest(t1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 5)); acb_randtest(s2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 5)); acb_randtest(t2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 5)); a = _acb_vec_init(p); b = _acb_vec_init(q); for (i = 0; i < p; i++) acb_randtest(a + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 5)); for (i = 0; i < q; i++) acb_randtest(b + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 5)); acb_hypgeom_pfq_sum_forward(s1, t1, a, p, b, q, z, n, prec1); acb_hypgeom_pfq_sum_fme(s2, t2, a, p, b, q, z, n, prec2); if (!acb_overlaps(s1, s2) || !acb_overlaps(t1, t2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("z = "); acb_print(a); flint_printf("\n\n"); flint_printf("s1 = "); acb_print(s1); flint_printf("\n\n"); flint_printf("s2 = "); acb_print(s2); flint_printf("\n\n"); flint_printf("t1 = "); acb_print(t1); flint_printf("\n\n"); flint_printf("t2 = "); acb_print(t2); flint_printf("\n\n"); flint_abort(); } _acb_vec_clear(a, p); _acb_vec_clear(b, q); acb_clear(z); acb_clear(s1); acb_clear(s2); acb_clear(t1); acb_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq_sum_invz.c000066400000000000000000000056101461254215100220050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq_sum_invz, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr a, b; acb_t z, zinv, s1, s2, t1, t2; slong i, p, q, n, prec1, prec2; p = n_randint(state, 5); q = n_randint(state, 5); n = n_randint(state, 300); prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); acb_init(z); acb_init(zinv); acb_init(s1); acb_init(s2); acb_init(t1); acb_init(t2); acb_randtest_special(z, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(t1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(t2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_inv(zinv, z, 1 + n_randint(state, 500)); a = _acb_vec_init(p); b = _acb_vec_init(q); for (i = 0; i < p; i++) acb_randtest(a + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); for (i = 0; i < q; i++) acb_randtest(b + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); if (n_randint(state, 2)) acb_hypgeom_pfq_sum_invz(s1, t1, a, p, b, q, zinv, z, n, prec1); else acb_hypgeom_pfq_sum_bs_invz(s1, t1, a, p, b, q, z, n, prec1); acb_hypgeom_pfq_sum(s2, t2, a, p, b, q, zinv, n, prec2); if (!acb_overlaps(s1, s2) || !acb_overlaps(t1, t2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wd\n\n", n); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("s1 = "); acb_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); acb_printd(s2, 15); flint_printf("\n\n"); flint_printf("t1 = "); acb_printd(t1, 15); flint_printf("\n\n"); flint_printf("t2 = "); acb_printd(t2, 15); flint_printf("\n\n"); flint_abort(); } _acb_vec_clear(a, p); _acb_vec_clear(b, q); acb_clear(z); acb_clear(zinv); acb_clear(s1); acb_clear(s2); acb_clear(t1); acb_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-pfq_sum_rs.c000066400000000000000000000051251461254215100214440ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_pfq_sum_rs, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr a, b; acb_t z, s1, s2, t1, t2; slong i, p, q, n, prec1, prec2; p = n_randint(state, 5); q = n_randint(state, 5); n = n_randint(state, 300); prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); acb_init(z); acb_init(s1); acb_init(s2); acb_init(t1); acb_init(t2); acb_randtest_special(z, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(t1, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(t2, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); a = _acb_vec_init(p); b = _acb_vec_init(q); for (i = 0; i < p; i++) acb_randtest(a + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); for (i = 0; i < q; i++) acb_randtest(b + i, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10)); acb_hypgeom_pfq_sum_forward(s1, t1, a, p, b, q, z, n, prec1); acb_hypgeom_pfq_sum_rs(s2, t2, a, p, b, q, z, n, prec2); if (!acb_overlaps(s1, s2) || !acb_overlaps(t1, t2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("z = "); acb_print(a); flint_printf("\n\n"); flint_printf("s1 = "); acb_print(s1); flint_printf("\n\n"); flint_printf("s2 = "); acb_print(s2); flint_printf("\n\n"); flint_printf("t1 = "); acb_print(t1); flint_printf("\n\n"); flint_printf("t2 = "); acb_print(t2); flint_printf("\n\n"); flint_abort(); } _acb_vec_clear(a, p); _acb_vec_clear(b, q); acb_clear(z); acb_clear(s1); acb_clear(s2); acb_clear(t1); acb_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-rising_ui.c000066400000000000000000000064321461254215100212600ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" /* Conflicting types in t-rising_ui.c and t-rising_ui_jet.c */ #define rising_algorithm rising_algorithm0 void rising_algorithm(acb_t res, const acb_t x, ulong n, ulong m, slong prec, int alg, int alias) { if (alias) { acb_set(res, x); rising_algorithm(res, res, n, m, prec, alg, 0); return; } if (alg == 0) acb_hypgeom_rising_ui_rs(res, x, n, m, prec); else if (alg == 1) acb_hypgeom_rising_ui_forward(res, x, n, prec); else if (alg == 2) acb_hypgeom_rising_ui_bs(res, x, n, prec); else if (alg == 3) acb_hypgeom_rising_ui_rec(res, x, n, prec); else acb_hypgeom_rising_ui(res, x, n, prec); } TEST_FUNCTION_START(acb_hypgeom_rising_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, xk, y, ya, yb, yayb; ulong k, n, m1, m2, m3; slong prec; int alg1, alg2, alg3, alias1, alias2, alias3; prec = 2 + n_randint(state, 200); k = n_randint(state, 10); n = n_randint(state, 50); m1 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n + k, 1)); m2 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(k, 1)); m3 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n, 1)); alg1 = n_randint(state, 5); alg2 = n_randint(state, 5); alg3 = n_randint(state, 5); alias1 = n_randint(state, 2); alias2 = n_randint(state, 2); alias3 = n_randint(state, 2); if (n_randint(state, 100) == 0) n += 100; acb_init(x); acb_init(xk); acb_init(y); acb_init(ya); acb_init(yb); acb_init(yayb); acb_randtest(x, state, prec, 10 + n_randint(state, 200)); acb_add_ui(xk, x, k, prec); rising_algorithm(y, x, n + k, m1, prec, alg1, alias1); rising_algorithm(ya, x, k, m2, prec, alg2, alias2); rising_algorithm(yb, xk, n, m3, prec, alg3, alias3); acb_mul(yayb, ya, yb, prec); if (!acb_overlaps(y, yayb)) { flint_printf("FAIL\n\n"); flint_printf("k = %wu, n = %wu, m1 = %wu, m2 = %wu, m3 = %wu\n\n", k, n, m1, m2, m3); flint_printf("x = "); acb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); acb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("ya = "); acb_printn(ya, 100, 0); flint_printf("\n\n"); flint_printf("yb = "); acb_printn(yb, 100, 0); flint_printf("\n\n"); flint_printf("yayb = "); acb_printn(yayb, 100, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(xk); acb_clear(y); acb_clear(ya); acb_clear(yb); acb_clear(yayb); } TEST_FUNCTION_END(state); } #undef rising_algorithm flint-3.1.3/src/acb_hypgeom/test/t-rising_ui_jet.c000066400000000000000000000062061461254215100221210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" /* Conflicting types in t-rising_ui.c and t-rising_ui_jet.c */ #define rising_algorithm rising_algorithm1 void rising_algorithm(acb_ptr res, const acb_t x, ulong n, ulong m, slong len, slong prec, int alg) { if (alg == 0) acb_hypgeom_rising_ui_jet_powsum(res, x, n, len, prec); else if (alg == 1) acb_hypgeom_rising_ui_jet_rs(res, x, n, m, len, prec); else if (alg == 2) acb_hypgeom_rising_ui_jet_bs(res, x, n, len, prec); else acb_hypgeom_rising_ui_jet(res, x, n, len, prec); } TEST_FUNCTION_START(acb_hypgeom_rising_ui_jet, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t x, xk; acb_ptr y, ya, yb, yayb; ulong k, n, m1, m2, m3, len; slong prec; int alg1, alg2, alg3; prec = 2 + n_randint(state, 200); len = 1 + n_randint(state, 6); k = n_randint(state, 10); n = n_randint(state, 50); m1 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n + k, 1)); m2 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(k, 1)); m3 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n, 1)); alg1 = n_randint(state, 4); alg2 = n_randint(state, 4); alg3 = n_randint(state, 4); acb_init(x); acb_init(xk); y = _acb_vec_init(len); ya = _acb_vec_init(len); yb = _acb_vec_init(len); yayb = _acb_vec_init(len); acb_randtest(x, state, prec, 10); acb_add_ui(xk, x, k, prec); rising_algorithm(y, x, n + k, m1, len, prec, alg1); rising_algorithm(ya, x, k, m2, len, prec, alg2); rising_algorithm(yb, xk, n, m3, len, prec, alg3); _acb_poly_mullow(yayb, ya, len, yb, len, len, prec); if (!_acb_poly_overlaps(y, len, yayb, len)) { flint_printf("FAIL\n\n"); flint_printf("len = %wd, k = %wu, n = %wu, m1 = %wu, m2 = %wu, m3 = %wu\n\n", len, k, n, m1, m2, m3); flint_printf("x = "); acb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); _acb_vec_printn(y, len, 100, 0); flint_printf("\n\n"); flint_printf("ya = "); _acb_vec_printn(ya, len, 100, 0); flint_printf("\n\n"); flint_printf("yb = "); _acb_vec_printn(yb, len, 100, 0); flint_printf("\n\n"); flint_printf("yayb = "); _acb_vec_printn(yayb, len, 100, 0); flint_printf("\n\n"); flint_abort(); } acb_clear(x); acb_clear(xk); _acb_vec_clear(y, len); _acb_vec_clear(ya, len); _acb_vec_clear(yb, len); _acb_vec_clear(yayb, len); } TEST_FUNCTION_END(state); } #undef rising_algorithm flint-3.1.3/src/acb_hypgeom/test/t-shi_series.c000066400000000000000000000052431461254215100214240ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_shi_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, n3, bits1, bits2, bits3; acb_poly_t S, A, B, C, T, U; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); n3 = FLINT_MIN(n1, n2); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_init(T); acb_poly_init(U); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_shi_series(A, S, n1, bits2); acb_hypgeom_shi_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, n3); acb_poly_truncate(B, n3); /* [Shi(h(x))]' h(x) = sinh(h(x)) h'(x) */ acb_poly_sinh_series(U, S, n3, bits2); acb_poly_derivative(T, S, bits2); acb_poly_mullow(U, U, T, FLINT_MAX(0, n3 - 1), bits2); acb_poly_derivative(T, A, bits2); acb_poly_mullow(T, T, S, FLINT_MAX(0, n3 - 1), bits2); if (!acb_poly_overlaps(B, C) || !acb_poly_overlaps(T, U)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("T = "); acb_poly_printd(T, 15); flint_printf("\n\n"); flint_printf("U = "); acb_poly_printd(U, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_shi_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(T); acb_poly_clear(U); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-si.c000066400000000000000000000046331461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t z0, z1, w0, w1; slong prec0, prec1; acb_init(z0); acb_init(z1); acb_init(w0); acb_init(w1); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); acb_randtest(z0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_set(z1, z0); if (n_randint(state, 2)) { acb_add(z1, z1, w0, prec0); acb_sub(z1, z1, w0, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_si_1f2(w0, z0, prec0); break; case 1: acb_hypgeom_si_asymp(w0, z0, prec0); break; default: acb_hypgeom_si(w0, z0, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_si_1f2(w1, z1, prec1); break; case 1: acb_hypgeom_si_asymp(w1, z1, prec1); break; default: acb_hypgeom_si(w1, z1, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("z0 = "); acb_printd(z0, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(z0); acb_clear(z1); acb_clear(w0); acb_clear(w1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-si_series.c000066400000000000000000000052341461254215100212540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_si_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, n3, bits1, bits2, bits3; acb_poly_t S, A, B, C, T, U; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); n3 = FLINT_MIN(n1, n2); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_init(T); acb_poly_init(U); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_hypgeom_si_series(A, S, n1, bits2); acb_hypgeom_si_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, n3); acb_poly_truncate(B, n3); /* [Si(h(x))]' h(x) = sin(h(x)) h'(x) */ acb_poly_sin_series(U, S, n3, bits2); acb_poly_derivative(T, S, bits2); acb_poly_mullow(U, U, T, FLINT_MAX(0, n3 - 1), bits2); acb_poly_derivative(T, A, bits2); acb_poly_mullow(T, T, S, FLINT_MAX(0, n3 - 1), bits2); if (!acb_poly_overlaps(B, C) || !acb_poly_overlaps(T, U)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_printf("T = "); acb_poly_printd(T, 15); flint_printf("\n\n"); flint_printf("U = "); acb_poly_printd(U, 15); flint_printf("\n\n"); flint_abort(); } acb_hypgeom_si_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(T); acb_poly_clear(U); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-spherical_y.c000066400000000000000000000107221461254215100215670ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" /* generated with mpmath */ static const double testdata[] = { 0.0, 0.0, -0.02701626593453869896, 0.06085851132589568114, 0.092391418427377575111, 0.29443833672801130076, 0.65131374739365937388, 0.37063665572827331764, 0.83847032733386007862, -0.28730577566514336534, -0.14750357092078405673, -0.30269451746476217073, -0.048646822931479694311, 0.038926542608778397121, 0.0048197328091099892156, 0.003641138129582944611, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.027574808444335508972, 0.11025410152651193448, 0.35400136349600893569, 0.24420566191536183849, 0.67425312681608106523, -0.11728998324910652574, -0.069322941709900597259, -0.18037674817459565026, -0.018729775699827662658, 0.013254956213452933465, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.14771800806690767222, 0.11532328561497280466, 0.50057392828327004059, -0.029559886614345590592, -0.02552211332726607337, -0.080244885187214384683, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.28209479177387814347, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.28209479177387814347, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.14771800806690767222, 0.11532328561497280466, 0.50057392828327004059, -0.029559886614345590592, -0.02552211332726607337, -0.080244885187214384683, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.027574808444335508972, 0.11025410152651193448, 0.35400136349600893569, 0.24420566191536183849, 0.67425312681608106523, -0.11728998324910652574, -0.069322941709900597259, -0.18037674817459565026, -0.018729775699827662658, 0.013254956213452933465, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.02701626593453869896, 0.06085851132589568114, 0.092391418427377575111, 0.29443833672801130076, 0.65131374739365937388, 0.37063665572827331764, 0.83847032733386007862, -0.28730577566514336534, -0.14750357092078405673, -0.30269451746476217073, -0.048646822931479694311, 0.038926542608778397121, 0.0048197328091099892156, 0.003641138129582944611, 0.0, 0.0, -0.033798002071615353821, 0.018033964330683617275, -0.071988993423855434033, 0.19195223773954952294, 0.23381678888295549361, 0.58288246446413288682, 1.0666048448920927459, 0.45816450098677839043, 0.99160821344691798668, -0.56670953266315770842, -0.27930640165163989333, -0.44051756827083040505, -0.092578419347396006256, 0.086641542063743427664, 0.015474322098595795308, 0.010316287906840124695, 0.00051935757617903067671, -0.0014726339944978705874, }; TEST_FUNCTION_START(acb_hypgeom_spherical_y, state) { { slong i, n, m; acb_t z, w, x, y; acb_init(z); acb_init(w); acb_init(x); acb_init(y); i = 0; arb_set_str(acb_realref(x), "0.2", 64); arb_set_str(acb_imagref(x), "0.3", 64); arb_set_str(acb_realref(y), "0.3", 64); arb_set_str(acb_imagref(y), "0.4", 64); for (n = -4; n <= 4; n++) { for (m = -4; m <= 4; m++) { acb_hypgeom_spherical_y(z, n, m, x, y, 64); acb_set_d_d(w, testdata[2 * i], testdata[2 * i + 1]); mag_set_d(arb_radref(acb_realref(w)), 1e-13); mag_set_d(arb_radref(acb_imagref(w)), 1e-13); if (!acb_overlaps(z, w)) { flint_printf("FAIL: value\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); flint_printf("z = "); acb_printd(z, 20); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 20); flint_printf("\n\n"); flint_abort(); } i++; } } acb_clear(z); acb_clear(w); acb_clear(x); acb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-u.c000066400000000000000000000121601461254215100175270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" void acb_hypgeom_u_asymp_proper(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_t t; acb_init(t); acb_pow(t, z, a, prec); acb_hypgeom_u_asymp(res, a, b, z, -1, prec); acb_div(res, res, t, prec); acb_clear(t); } TEST_FUNCTION_START(acb_hypgeom_u, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a0, a1, a2, b, z, w0, w1, w2, t, u; slong prec0, prec1, prec2; acb_init(a0); acb_init(a1); acb_init(a2); acb_init(b); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 700); prec1 = 2 + n_randint(state, 700); prec2 = 2 + n_randint(state, 700); acb_randtest_param(a0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_param(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); if (prec0 <= 300 && prec1 <= 300 && prec2 <= 300 && n_randint(state, 2)) { arb_zero(acb_imagref(a0)); arb_zero(acb_imagref(b)); arb_zero(acb_imagref(z)); } acb_add_ui(a1, a0, 1, prec0); acb_add_ui(a2, a0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w0, a0, b, z, prec0); break; case 1: acb_hypgeom_u_1f1(w0, a0, b, z, prec0); break; default: acb_hypgeom_u(w0, a0, b, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w1, a0, b, z, prec1); break; case 1: acb_hypgeom_u_1f1(w1, a0, b, z, prec1); break; default: acb_hypgeom_u(w1, a0, b, z, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("a = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w1, a1, b, z, prec1); break; case 1: acb_hypgeom_u_1f1(w1, a1, b, z, prec1); break; default: acb_hypgeom_u(w1, a1, b, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w2, a2, b, z, prec2); break; case 1: acb_hypgeom_u_1f1(w2, a2, b, z, prec2); break; default: acb_hypgeom_u(w2, a2, b, z, prec2); } acb_set(t, w0); acb_mul_2exp_si(u, a0, 1); acb_sub(u, u, b, prec0); acb_add(u, u, z, prec0); acb_add_ui(u, u, 2, prec0); acb_submul(t, w1, u, prec0); acb_sub(u, a2, b, prec0); acb_mul(u, u, a1, prec0); acb_addmul(t, w2, u, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("a = "); acb_printd(a0, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(a0); acb_clear(a1); acb_clear(a2); acb_clear(b); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/test/t-u_asymp.c000066400000000000000000000157011461254215100207440ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_hypgeom.h" TEST_FUNCTION_START(acb_hypgeom_u_asymp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t a, b, a2, b2, z, U1, U2, t, u, M1, M2, am; acb_struct bm[2]; ulong n1, n2; slong prec0, prec1, prec2; acb_init(a); acb_init(b); acb_init(a2); acb_init(b2); acb_init(z); acb_init(U1); acb_init(U2); acb_init(t); acb_init(u); acb_init(M1); acb_init(M2); acb_init(am); acb_init(bm); acb_init(bm + 1); if (n_randint(state, 4) == 0) { n1 = n_randint(state, 200); n2 = n_randint(state, 200); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); } else { n1 = n_randint(state, 40); n2 = n_randint(state, 40); prec0 = 2 + n_randint(state, 300); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); } acb_randtest_param(a, state, prec0, 1 + n_randint(state, 20)); if (n_randint(state, 4) == 0) acb_add_ui(b, a, n_randint(state, 10), prec0); else acb_randtest_param(b, state, prec0, 1 + n_randint(state, 20)); acb_randtest(z, state, prec0, 1 + n_randint(state, 20)); /* Test Kummer's transformation */ acb_sub(a2, a, b, prec0); acb_add_ui(a2, a2, 1, prec0); acb_sub_ui(b2, b, 2, prec0); acb_neg(b2, b2); acb_hypgeom_u_asymp(U1, a, b, z, n1, prec1); acb_hypgeom_u_asymp(U2, a2, b2, z, n2, prec2); if (!acb_overlaps(U1, U2)) { flint_printf("FAIL (Kummer transformation)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("U2 = "); acb_printd(U2, 100); flint_printf("\n"); flint_abort(); } /* Check contiguous relation (b-a-1)U(a,b-1,z) + z U(a,b+1,z) + (1-b-z) U(a,b,z) = 0 */ acb_one(t); acb_sub(t, t, b, prec0); acb_sub(t, t, z, prec0); acb_mul(u, U1, t, prec1); acb_add_ui(b2, b, 1, prec0); acb_hypgeom_u_asymp(U2, a, b2, z, n2, prec2); acb_addmul(u, U2, z, prec1); acb_sub_ui(b2, b, 1, prec0); acb_hypgeom_u_asymp(U2, a, b2, z, n2, prec2); acb_sub(t, b, a, prec0); acb_sub_ui(t, t, 1, prec0); acb_mul(t, t, U2, prec0); acb_add(t, t, u, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL (contiguous relation)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("t = "); acb_printd(t, 100); flint_printf("\n"); flint_abort(); } /* Test U(a,b,z) = gamma(1-b)/gamma(a-b+1) M(a,b,z) + gamma(b-1)/gamma(a) z^(1-b) M(a-b+1,2-b,z) */ acb_set(am, a); acb_set(bm, b); acb_one(bm + 1); acb_hypgeom_pfq_direct(M1, am, 1, bm, 2, z, n2, prec2); acb_sub(am, a, b, prec2); acb_add_ui(am, am, 1, prec2); acb_sub_ui(bm, b, 2, prec2); acb_neg(bm, bm); acb_one(bm + 1); acb_hypgeom_pfq_direct(M2, am, 1, bm, 2, z, n2, prec2); acb_sub(am, a, b, prec2); acb_add_ui(am, am, 1, prec2); acb_rgamma(am, am, prec2); acb_mul(M1, M1, am, prec2); acb_sub_ui(am, b, 1, prec2); acb_neg(am, am); acb_gamma(am, am, prec2); acb_mul(M1, M1, am, prec2); acb_rgamma(am, a, prec2); acb_mul(M2, M2, am, prec2); acb_sub_ui(am, b, 1, prec2); acb_gamma(am, am, prec2); acb_mul(M2, M2, am, prec2); acb_sub_ui(am, b, 1, prec2); acb_neg(am, am); acb_pow(am, z, am, prec2); acb_mul(M2, M2, am, prec2); acb_add(U2, M1, M2, prec2); acb_pow(am, z, a, prec2); acb_mul(U2, U2, am, prec2); if (!acb_overlaps(U1, U2)) { flint_printf("FAIL (U in terms of M)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("U2 = "); acb_printd(U2, 100); flint_printf("\n"); flint_abort(); } /* Test special value: b = a+1 */ acb_add_ui(b, a, 1, prec0); acb_hypgeom_u_asymp(U1, a, b, z, n1, prec1); acb_one(U2); if (!acb_overlaps(U1, U2)) { flint_printf("FAIL (special value)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("U2 = "); acb_printd(U2, 100); flint_printf("\n"); flint_abort(); } acb_clear(a); acb_clear(b); acb_clear(a2); acb_clear(b2); acb_clear(z); acb_clear(U1); acb_clear(U2); acb_clear(t); acb_clear(u); acb_clear(M1); acb_clear(M2); acb_clear(am); acb_clear(bm); acb_clear(bm + 1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_hypgeom/u.c000066400000000000000000000276021461254215100163160ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif static void bsplit(acb_t A, acb_t B, acb_t C, acb_t D, const acb_t b, const acb_t z, slong n0, slong n1, slong prec) { if (n1 - n0 == 1) { acb_zero(A); acb_one(B); acb_neg(C, b); acb_add_si(C, C, 2 - n0, prec); acb_mul_si(C, C, n0 - 1, prec); acb_sub(D, z, b, prec); acb_add_si(D, D, 2 - 2 * n0, prec); } else { slong m; acb_t T, A2, B2, C2, D2; acb_init(T); acb_init(A2); acb_init(B2); acb_init(C2); acb_init(D2); m = n0 + (n1 - n0) / 2; bsplit(A, B, C, D, b, z, n0, m, prec); bsplit(A2, B2, C2, D2, b, z, m, n1, prec); acb_set(T, A); acb_mul(A, A, A2, prec); acb_addmul(A, B2, C, prec); acb_mul(C, C, D2, prec); acb_addmul(C, C2, T, prec); acb_set(T, B); acb_mul(B, B, A2, prec); acb_addmul(B, B2, D, prec); acb_mul(D, D, D2, prec); acb_addmul(D, C2, T, prec); acb_clear(T); acb_clear(A2); acb_clear(B2); acb_clear(C2); acb_clear(D2); } } void acb_hypgeom_u_si_rec(acb_t res, slong a, const acb_t b, const acb_t z, slong prec) { slong k; acb_t u0, u1, t; if (a > 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (a == 0) { acb_one(res); return; } else if (a == -1) { acb_sub(res, z, b, prec); return; } /* special-case U(-n, -n+1, z) = z^n */ if (acb_equal_si(b, a + 1)) { acb_pow_si(res, z, -a, prec); return; } acb_init(u0); acb_init(u1); acb_init(t); acb_one(u0); acb_sub(u1, z, b, prec); if (-a < 20) { for (k = 2; k <= -a; k++) { acb_neg(t, b); acb_add_si(t, t, 2 - k, prec); acb_mul_si(t, t, k - 1, prec); acb_mul(u0, u0, t, prec); acb_sub(t, z, b, prec); acb_add_si(t, t, 2 - 2 * k, prec); acb_addmul(u0, u1, t, prec); acb_swap(u0, u1); } acb_set(res, u1); } else { acb_t A, B, C, D; acb_init(A); acb_init(B); acb_init(C); acb_init(D); bsplit(A, B, C, D, b, z, 2, -a + 1, prec); acb_sub(A, z, b, prec); acb_mul(D, D, A, prec); acb_add(res, C, D, prec); acb_clear(A); acb_clear(B); acb_clear(C); acb_clear(D); } acb_clear(u0); acb_clear(u1); acb_clear(t); } void acb_hypgeom_u_1f1_series(acb_poly_t res, const acb_poly_t a, const acb_poly_t b, const acb_poly_t z, slong len, slong prec) { acb_poly_t s, u, A, B; acb_poly_struct aa[3]; arb_t c; slong wlen; int singular; acb_poly_init(s); acb_poly_init(u); acb_poly_init(A); acb_poly_init(B); acb_poly_init(aa + 0); acb_poly_init(aa + 1); acb_poly_init(aa + 2); arb_init(c); singular = (b->length == 0) || acb_is_int(b->coeffs); wlen = len + (singular != 0); /* A = rgamma(a-b+1) * 1F~1(a,b,z) */ acb_poly_sub(u, a, b, prec); acb_poly_add_si(u, u, 1, prec); acb_poly_rgamma_series(A, u, wlen, prec); /* todo: handle a = 1 efficiently */ acb_poly_set(aa, a); acb_poly_set(aa + 1, b); acb_poly_one(aa + 2); acb_hypgeom_pfq_series_direct(s, aa, 1, aa + 1, 2, z, 1, -1, wlen, prec); acb_poly_mullow(A, A, s, wlen, prec); /* B = rgamma(a) * 1F~1(a-b+1,2-b,z) * z^(1-b) */ acb_poly_set(aa, u); acb_poly_add_si(aa + 1, b, -2, prec); acb_poly_neg(aa + 1, aa + 1); acb_hypgeom_pfq_series_direct(s, aa, 1, aa + 1, 2, z, 1, -1, wlen, prec); acb_poly_rgamma_series(B, a, wlen, prec); acb_poly_mullow(B, B, s, wlen, prec); acb_poly_add_si(u, b, -1, prec); acb_poly_neg(u, u); acb_poly_pow_series(s, z, u, wlen, prec); acb_poly_mullow(B, B, s, wlen, prec); acb_poly_sub(A, A, B, prec); /* multiply by pi csc(pi b) */ acb_poly_sin_pi_series(B, b, wlen, prec); if (singular) { acb_poly_shift_right(A, A, 1); acb_poly_shift_right(B, B, 1); } acb_poly_div_series(res, A, B, len, prec); arb_const_pi(c, prec); _acb_vec_scalar_mul_arb(res->coeffs, res->coeffs, res->length, c, prec); acb_poly_clear(s); acb_poly_clear(u); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(aa + 0); acb_poly_clear(aa + 1); acb_poly_clear(aa + 2); arb_clear(c); } void acb_hypgeom_u_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec) { if (acb_is_int(b)) { acb_poly_t aa, bb, zz; acb_poly_init(aa); acb_poly_init(bb); acb_poly_init(zz); acb_poly_set_acb(aa, a); acb_poly_set_coeff_acb(bb, 0, b); acb_poly_set_coeff_si(bb, 1, 1); acb_poly_set_acb(zz, z); acb_hypgeom_u_1f1_series(zz, aa, bb, zz, 1, prec); acb_poly_get_coeff_acb(res, zz, 0); acb_poly_clear(aa); acb_poly_clear(bb); acb_poly_clear(zz); } else { acb_t t, u, v; acb_struct aa[3]; acb_init(t); acb_init(u); acb_init(v); acb_init(aa + 0); acb_init(aa + 1); acb_init(aa + 2); acb_set(aa, a); acb_set(aa + 1, b); acb_one(aa + 2); acb_hypgeom_pfq_direct(u, aa, 1, aa + 1, 2, z, -1, prec); acb_sub(aa, a, b, prec); acb_add_ui(aa, aa, 1, prec); acb_sub_ui(aa + 1, b, 2, prec); acb_neg(aa + 1, aa + 1); acb_hypgeom_pfq_direct(v, aa, 1, aa + 1, 2, z, -1, prec); acb_sub_ui(aa + 1, b, 1, prec); /* rgamma(a-b+1) * gamma(1-b) * u */ acb_rgamma(t, aa, prec); acb_mul(u, u, t, prec); acb_neg(t, aa + 1); acb_gamma(t, t, prec); acb_mul(u, u, t, prec); /* rgamma(a) * gamma(b-1) * z^(1-b) * v */ acb_rgamma(t, a, prec); acb_mul(v, v, t, prec); acb_gamma(t, aa + 1, prec); acb_mul(v, v, t, prec); acb_neg(t, aa + 1); acb_pow(t, z, t, prec); acb_mul(v, v, t, prec); acb_add(res, u, v, prec); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(aa + 0); acb_clear(aa + 1); acb_clear(aa + 2); } } void acb_hypgeom_u_choose(int * asymp, slong * wp, const acb_t a, const acb_t b, const acb_t z, slong prec) { double x, y, t, cancellation; double input_accuracy, direct_accuracy, asymp_accuracy; *asymp = 0; *wp = prec; input_accuracy = acb_rel_one_accuracy_bits(z); t = acb_rel_one_accuracy_bits(a); input_accuracy = FLINT_MIN(input_accuracy, t); t = acb_rel_one_accuracy_bits(b); input_accuracy = FLINT_MIN(input_accuracy, t); input_accuracy = FLINT_MAX(input_accuracy, 0.0); /* From here we ignore the values of a, b. Taking them into account is a possible future improvement... */ /* Tiny |z|. */ if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 2) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 2) < 0)) { *asymp = 0; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); return; } /* Huge |z|. */ if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0)) { *asymp = 1; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); return; } x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); asymp_accuracy = sqrt(x * x + y * y) * 1.44269504088896; /* The Kummer transformation gives less cancellation with the 1F1 series. if (x < 0.0) { *kummer = 1; x = -x; } */ if (asymp_accuracy >= prec) { *asymp = 1; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); return; } /* Assume U ~ 1, M ~ exp(|z|) (there is cancellation both in the evaluation of M and in the linear combination) -- a better estimate would account for a, b. */ cancellation = sqrt(x * x + y * y) * 1.44269504088896 + 5; direct_accuracy = input_accuracy - cancellation; if (direct_accuracy > asymp_accuracy) { *asymp = 0; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec + cancellation)); } else { *asymp = 1; *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec)); } } void acb_hypgeom_u_nointegration(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_t t; arf_srcptr av, tv; av = arb_midref(acb_realref(a)); /* Handle small polynomial cases without divisions. */ /* todo: should incorporate a -> 1+a-b transformation, also... */ if (acb_is_int(a) && arf_sgn(av) <= 0) { if (arf_cmpabs_ui(av, 30) < 0 || (arf_cmpabs_ui(av, prec) < 0 && ((acb_bits(b) < 0.1 * prec && acb_bits(z) < 0.1 * prec) || acb_contains_zero(z)))) { acb_hypgeom_u_si_rec(res, arf_get_si(av, ARF_RND_DOWN), b, z, prec); return; } } acb_init(t); acb_sub(t, a, b, prec); acb_add_ui(t, t, 1, prec); tv = arb_midref(acb_realref(t)); /* todo: combine these conditions with the code below */ if ((acb_is_int(a) && arf_sgn(av) <= 0) || (acb_is_int(t) && arf_sgn(tv) <= 0) || acb_hypgeom_u_use_asymp(z, prec)) { acb_neg(t, a); acb_pow(t, z, t, prec); acb_hypgeom_u_asymp(res, a, b, z, -1, prec); acb_mul(res, res, t, prec); } else { slong wp; int asymp; acb_hypgeom_u_choose(&asymp, &wp, a, b, z, prec); if (asymp) { acb_neg(t, a); acb_pow(t, z, t, prec); acb_hypgeom_u_asymp(res, a, b, z, -1, wp); acb_mul(res, res, t, prec); } else { acb_hypgeom_u_1f1(res, a, b, z, wp); acb_set_round(res, res, prec); } } acb_clear(t); } void acb_hypgeom_u(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_t res2; slong acc, max, t; acb_init(res2); acb_hypgeom_u_nointegration(res2, a, b, z, prec); acc = acb_rel_accuracy_bits(res2); if (acc < 0.5 * prec) { max = prec; t = acb_rel_accuracy_bits(z); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(a); max = FLINT_MIN(max, t); t = acb_rel_accuracy_bits(b); max = FLINT_MIN(max, t); if (max > 2 && acc < 0.5 * max) { if (acb_is_real(a) && acb_is_real(b) && acb_is_real(z) && arb_is_positive(acb_realref(z)) && arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 60) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0) { arb_hypgeom_u_integration(acb_realref(res), acb_realref(a), acb_realref(b), acb_realref(z), prec); arb_zero(acb_imagref(res)); if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) || (acb_is_finite(res) && !acb_is_finite(res2))) { acb_swap(res, res2); } } } } acb_swap(res, res2); acb_clear(res2); } flint-3.1.3/src/acb_hypgeom/u_asymp.c000066400000000000000000000227351461254215100175310ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" slong acb_hypgeom_pfq_choose_n_max(acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong prec, slong n_max); int acb_hypgeom_u_asymp_determine_region(const mag_t r, const mag_t zlo, const acb_t z) { int R; mag_t u, zre, zim; mag_init(u); mag_init(zre); mag_init(zim); /* lower bounds for |re(z)|, |im(z)|, |z| */ arb_get_mag_lower(zre, acb_realref(z)); arb_get_mag_lower(zim, acb_imagref(z)); R = 0; if (mag_cmp(zlo, r) >= 0) { int znonneg = arb_is_nonnegative(acb_realref(z)); if (znonneg && mag_cmp(zre, r) >= 0) { R = 1; } else if (mag_cmp(zim, r) >= 0 || znonneg) { R = 2; } else { mag_mul_2exp_si(u, r, 1); if (mag_cmp(zlo, u) >= 0) R = 3; } } mag_clear(u); mag_clear(zre); mag_clear(zim); return R; } /* computes the factors that are independent of n (all are upper bounds) */ void acb_hypgeom_u_asymp_bound_factors(int * R, mag_t alpha, mag_t nu, mag_t sigma, mag_t rho, mag_t zinv, const acb_t a, const acb_t b, const acb_t z) { mag_t r, u, zlo, sigma_prime; acb_t t; mag_init(r); mag_init(u); mag_init(zlo); mag_init(sigma_prime); acb_init(t); /* upper bound for 1/|z| */ acb_get_mag_lower(zlo, z); mag_inv(zinv, zlo); /* upper bound for r = |b - 2a| */ acb_mul_2exp_si(t, a, 1); acb_sub(t, b, t, MAG_BITS); acb_get_mag(r, t); /* determine region */ *R = acb_hypgeom_u_asymp_determine_region(r, zlo, z); if (*R == 0) { mag_inf(alpha); mag_inf(nu); mag_inf(sigma); mag_inf(rho); } else { /* sigma = |(b-2a)/z| */ mag_mul(sigma, r, zinv); /* nu = (1/2 + 1/2 sqrt(1-4 sigma^2))^(-1/2) <= 1 + 2 sigma^2 */ if (mag_cmp_2exp_si(sigma, -1) <= 0) { mag_mul(nu, sigma, sigma); mag_mul_2exp_si(nu, nu, 1); mag_one(u); mag_add(nu, nu, u); } else { mag_inf(nu); } /* modified sigma for alpha, beta, rho when in R3 */ if (*R == 3) mag_mul(sigma_prime, sigma, nu); else mag_set(sigma_prime, sigma); /* alpha = 1/(1-sigma') */ mag_one(alpha); mag_sub_lower(alpha, alpha, sigma_prime); mag_one(u); mag_div(alpha, u, alpha); /* rho = |2a^2-2ab+b|/2 + sigma'*(1+sigma'/4)/(1-sigma')^2 */ mag_mul_2exp_si(rho, sigma_prime, -2); mag_one(u); mag_add(rho, rho, u); mag_mul(rho, rho, sigma_prime); mag_mul(rho, rho, alpha); mag_mul(rho, rho, alpha); acb_sub(t, a, b, MAG_BITS); acb_mul(t, t, a, MAG_BITS); acb_mul_2exp_si(t, t, 1); acb_add(t, t, b, MAG_BITS); acb_get_mag(u, t); mag_mul_2exp_si(u, u, -1); mag_add(rho, rho, u); } mag_clear(r); mag_clear(u); mag_clear(zlo); mag_clear(sigma_prime); acb_clear(t); } void acb_hypgeom_mag_chi(mag_t chi, ulong n) { mag_t p, q; ulong k; mag_init(p); mag_init(q); if (n % 2 == 0) { mag_one(p); mag_one(q); } else { /* upper bound for pi/2 */ mag_set_ui_2exp_si(p, 843314857, -28); mag_one(q); } for (k = n; k >= 2; k -= 2) { mag_mul_ui(p, p, k); mag_mul_ui_lower(q, q, k - 1); } mag_div(chi, p, q); mag_clear(p); mag_clear(q); } static void acb_hypgeom_mag_Cn(mag_t Cn, int R, const mag_t nu, const mag_t sigma, ulong n) { if (R == 1) { mag_one(Cn); } else { acb_hypgeom_mag_chi(Cn, n); if (R == 3) { mag_t tmp; mag_init(tmp); mag_mul(tmp, nu, nu); mag_mul(tmp, tmp, sigma); if (n != 1) mag_mul_ui(tmp, tmp, n); mag_add(Cn, Cn, tmp); mag_pow_ui(tmp, nu, n); mag_mul(Cn, Cn, tmp); mag_clear(tmp); } } } static int acb_is_nonpositive_int(const acb_t x) { return acb_is_int(x) && arf_sgn(arb_midref(acb_realref(x))) <= 0; } void acb_hypgeom_u_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, slong n, slong prec) { acb_struct aa[3]; acb_t s, t, w, winv; int R, p, q, is_real, is_terminating; slong n_terminating; if (!acb_is_finite(a) || !acb_is_finite(b) || !acb_is_finite(z)) { acb_indeterminate(res); return; } acb_init(aa); acb_init(aa + 1); acb_init(aa + 2); acb_init(s); acb_init(t); acb_init(w); acb_init(winv); is_terminating = 0; n_terminating = WORD_MAX; /* special case, for incomplete gamma [todo: also when they happen to be exact and with difference 1...] */ if (a == b) { acb_set(aa, a); p = 1; q = 0; } else { acb_set(aa, a); acb_sub(aa + 1, a, b, prec); acb_add_ui(aa + 1, aa + 1, 1, prec); acb_one(aa + 2); p = 2; q = 1; } if (acb_is_nonpositive_int(aa)) { is_terminating = 1; if (arf_cmpabs_ui(arb_midref(acb_realref(aa)), prec) < 0) n_terminating = 1 - arf_get_si(arb_midref(acb_realref(aa)), ARF_RND_DOWN); } if (p == 2 && acb_is_nonpositive_int(aa + 1)) { is_terminating = 1; if (arf_cmpabs_ui(arb_midref(acb_realref(aa + 1)), n_terminating) < 0) n_terminating = 1 - arf_get_si(arb_midref(acb_realref(aa + 1)), ARF_RND_DOWN); } acb_neg(w, z); acb_inv(w, w, prec); acb_neg(winv, z); /* low degree polynomial -- no need to try to terminate sooner */ if (is_terminating && n_terminating < 8) { acb_hypgeom_pfq_sum_invz(s, t, aa, p, aa + p, q, w, winv, n_terminating, prec); acb_set(res, s); } else { mag_t C1, Cn, alpha, nu, sigma, rho, zinv, tmp, err; mag_init(C1); mag_init(Cn); mag_init(alpha); mag_init(nu); mag_init(sigma); mag_init(rho); mag_init(zinv); mag_init(tmp); mag_init(err); acb_hypgeom_u_asymp_bound_factors(&R, alpha, nu, sigma, rho, zinv, a, b, z); is_real = acb_is_real(a) && acb_is_real(b) && acb_is_real(z) && (is_terminating || arb_is_positive(acb_realref(z))); if (R == 0) { /* if R == 0, the error bound is infinite unless terminating */ if (is_terminating && n_terminating < prec) { acb_hypgeom_pfq_sum_invz(s, t, aa, p, aa + p, q, w, winv, n_terminating, prec); acb_set(res, s); } else { acb_indeterminate(res); } } else { /* C1 */ acb_hypgeom_mag_Cn(C1, R, nu, sigma, 1); /* err = 2 * alpha * exp(...) */ mag_mul(tmp, C1, rho); mag_mul(tmp, tmp, alpha); mag_mul(tmp, tmp, zinv); mag_mul_2exp_si(tmp, tmp, 1); mag_exp(err, tmp); mag_mul(err, err, alpha); mag_mul_2exp_si(err, err, 1); /* choose n automatically */ if (n < 0) { slong moreprec; /* take err into account when finding truncation point */ /* we should take Cn into account as well, but this depends on n which is to be determined; it's easier to look only at exp(...) which should be larger anyway */ if (mag_cmp_2exp_si(err, 10 * prec) > 0) moreprec = 10 * prec; else if (mag_cmp_2exp_si(err, 0) < 0) moreprec = 0; else moreprec = MAG_EXP(err); n = acb_hypgeom_pfq_choose_n_max(aa, p, aa + p, q, w, prec + moreprec, FLINT_MIN(WORD_MAX / 2, 50 + 10 * prec)); } acb_hypgeom_pfq_sum_invz(s, t, aa, p, aa + p, q, w, winv, n, prec); /* add error bound, if not terminating */ if (!(is_terminating && n == n_terminating)) { acb_hypgeom_mag_Cn(Cn, R, nu, sigma, n); mag_mul(err, err, Cn); /* nth term * factor */ acb_get_mag(tmp, t); mag_mul(err, err, tmp); if (is_real) arb_add_error_mag(acb_realref(s), err); else acb_add_error_mag(s, err); } acb_set(res, s); } mag_clear(C1); mag_clear(Cn); mag_clear(alpha); mag_clear(nu); mag_clear(sigma); mag_clear(rho); mag_clear(zinv); mag_clear(tmp); mag_clear(err); } acb_clear(aa); acb_clear(aa + 1); acb_clear(aa + 2); acb_clear(s); acb_clear(t); acb_clear(w); acb_clear(winv); } flint-3.1.3/src/acb_hypgeom/u_use_asymp.c000066400000000000000000000021061461254215100203730ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_hypgeom.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif int acb_hypgeom_u_use_asymp(const acb_t z, slong prec) { double x, y; if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 0) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0)) { return 0; } if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0)) { return 1; } x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); return sqrt(x * x + y * y) > prec * 0.69314718055994530942; } flint-3.1.3/src/acb_mat.h000066400000000000000000000350451461254215100151700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_MAT_H #define ACB_MAT_H #ifdef ACB_MAT_INLINES_C #define ACB_MAT_INLINE #else #define ACB_MAT_INLINE static inline #endif #include "fmpq_types.h" #include "arb_mat.h" #include "acb.h" #ifdef __cplusplus extern "C" { #endif #define acb_mat_entry(mat,i,j) ((mat)->rows[i] + (j)) #define acb_mat_nrows(mat) ((mat)->r) #define acb_mat_ncols(mat) ((mat)->c) ACB_MAT_INLINE acb_ptr acb_mat_entry_ptr(acb_mat_t mat, slong i, slong j) { return acb_mat_entry(mat, i, j); } /* Memory management */ void acb_mat_init(acb_mat_t mat, slong r, slong c); void acb_mat_clear(acb_mat_t mat); ACB_MAT_INLINE void acb_mat_swap(acb_mat_t mat1, acb_mat_t mat2) { FLINT_SWAP(acb_mat_struct, *mat1, *mat2); } ACB_MAT_INLINE void acb_mat_swap_entrywise(acb_mat_t mat1, acb_mat_t mat2) { slong i, j; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) acb_swap(acb_mat_entry(mat2, i, j), acb_mat_entry(mat1, i, j)); } /* Window matrices */ void acb_mat_window_init(acb_mat_t window, const acb_mat_t mat, slong r1, slong c1, slong r2, slong c2); ARB_MAT_INLINE void acb_mat_window_clear(acb_mat_t window) { flint_free(window->rows); } /* Conversions */ void acb_mat_set(acb_mat_t dest, const acb_mat_t src); void acb_mat_set_fmpz_mat(acb_mat_t dest, const fmpz_mat_t src); void acb_mat_set_round_fmpz_mat(acb_mat_t dest, const fmpz_mat_t src, slong prec); void acb_mat_set_fmpq_mat(acb_mat_t dest, const fmpq_mat_t src, slong prec); void acb_mat_set_arb_mat(acb_mat_t dest, const arb_mat_t src); void acb_mat_set_round_arb_mat(acb_mat_t dest, const arb_mat_t src, slong prec); void acb_mat_get_real(arb_mat_t re, const acb_mat_t mat); void acb_mat_get_imag(arb_mat_t im, const acb_mat_t mat); void acb_mat_set_real_imag(acb_mat_t mat, const arb_mat_t re, const arb_mat_t im); /* Random generation */ void acb_mat_randtest(acb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits); void acb_mat_randtest_eig(acb_mat_t A, flint_rand_t state, acb_srcptr E, slong prec); /* I/O */ #ifdef FLINT_HAVE_FILE void acb_mat_fprintd(FILE * file, const acb_mat_t mat, slong digits); #endif void acb_mat_printd(const acb_mat_t mat, slong digits); /* Comparisons */ int acb_mat_eq(const acb_mat_t mat1, const acb_mat_t mat2); int acb_mat_ne(const acb_mat_t mat1, const acb_mat_t mat2); int acb_mat_equal(const acb_mat_t mat1, const acb_mat_t mat2); int acb_mat_overlaps(const acb_mat_t mat1, const acb_mat_t mat2); int acb_mat_contains(const acb_mat_t mat1, const acb_mat_t mat2); int acb_mat_contains_fmpq_mat(const acb_mat_t mat1, const fmpq_mat_t mat2); int acb_mat_contains_fmpz_mat(const acb_mat_t mat1, const fmpz_mat_t mat2); int acb_mat_is_real(const acb_mat_t mat); ACB_MAT_INLINE int acb_mat_is_empty(const acb_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } ACB_MAT_INLINE int acb_mat_is_square(const acb_mat_t mat) { return (mat->r == mat->c); } int acb_mat_is_exact(const acb_mat_t mat); int acb_mat_is_zero(const acb_mat_t mat); int acb_mat_is_finite(const acb_mat_t mat); int acb_mat_is_triu(const acb_mat_t mat); int acb_mat_is_tril(const acb_mat_t mat); ACB_MAT_INLINE int acb_mat_is_diag(const acb_mat_t mat) { return acb_mat_is_tril(mat) && acb_mat_is_triu(mat); } /* Radius and interval operations */ ACB_MAT_INLINE void acb_mat_get_mid(acb_mat_t B, const acb_mat_t A) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) { for (j = 0; j < acb_mat_ncols(A); j++) { arb_get_mid_arb(acb_realref(acb_mat_entry(B, i, j)), acb_realref(acb_mat_entry(A, i, j))); arb_get_mid_arb(acb_imagref(acb_mat_entry(B, i, j)), acb_imagref(acb_mat_entry(A, i, j))); } } } ACB_MAT_INLINE void acb_mat_add_error_mag(acb_mat_t mat, const mag_t err) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) for (j = 0; j < acb_mat_ncols(mat); j++) acb_add_error_mag(acb_mat_entry(mat, i, j), err); } /* Special matrices */ void acb_mat_zero(acb_mat_t mat); void acb_mat_one(acb_mat_t mat); void acb_mat_ones(acb_mat_t mat); void acb_mat_onei(acb_mat_t mat); void acb_mat_indeterminate(acb_mat_t mat); void acb_mat_dft(acb_mat_t res, int kind, slong prec); void acb_mat_transpose(acb_mat_t mat1, const acb_mat_t mat2); void acb_mat_conjugate(acb_mat_t mat1, const acb_mat_t mat2); ACB_MAT_INLINE void acb_mat_conjugate_transpose(acb_mat_t mat1, const acb_mat_t mat2) { acb_mat_transpose(mat1, mat2); acb_mat_conjugate(mat1, mat1); } /* Norms */ void acb_mat_bound_inf_norm(mag_t b, const acb_mat_t A); void acb_mat_frobenius_norm(arb_t res, const acb_mat_t A, slong prec); void acb_mat_bound_frobenius_norm(mag_t b, const acb_mat_t A); /* Arithmetic */ void acb_mat_neg(acb_mat_t dest, const acb_mat_t src); void acb_mat_add(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec); void acb_mat_sub(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec); void acb_mat_mul_classical(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec); void acb_mat_mul_threaded(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec); void acb_mat_mul_reorder(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec); void acb_mat_mul(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec); void acb_mat_mul_entrywise(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec); void acb_mat_sqr_classical(acb_mat_t res, const acb_mat_t mat, slong prec); void acb_mat_sqr(acb_mat_t res, const acb_mat_t mat, slong prec); void acb_mat_pow_ui(acb_mat_t B, const acb_mat_t A, ulong exp, slong prec); /* Scalar arithmetic */ ACB_MAT_INLINE void acb_mat_scalar_mul_2exp_si(acb_mat_t B, const acb_mat_t A, slong c) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_mul_2exp_si(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c); } ACB_MAT_INLINE void acb_mat_scalar_addmul_si(acb_mat_t B, const acb_mat_t A, slong c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_addmul_si(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_mul_si(acb_mat_t B, const acb_mat_t A, slong c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_mul_si(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_div_si(acb_mat_t B, const acb_mat_t A, slong c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_div_si(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_addmul_fmpz(acb_mat_t B, const acb_mat_t A, const fmpz_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_addmul_fmpz(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_mul_fmpz(acb_mat_t B, const acb_mat_t A, const fmpz_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_mul_fmpz(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_div_fmpz(acb_mat_t B, const acb_mat_t A, const fmpz_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_div_fmpz(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_addmul_acb(acb_mat_t B, const acb_mat_t A, const acb_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_addmul(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_mul_acb(acb_mat_t B, const acb_mat_t A, const acb_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_mul(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_div_acb(acb_mat_t B, const acb_mat_t A, const acb_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_div(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_addmul_arb(acb_mat_t B, const acb_mat_t A, const arb_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_addmul_arb(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_mul_arb(acb_mat_t B, const acb_mat_t A, const arb_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_mul_arb(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } ACB_MAT_INLINE void acb_mat_scalar_div_arb(acb_mat_t B, const acb_mat_t A, const arb_t c, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_div_arb(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), c, prec); } /* Vector arithmetic */ void _acb_mat_vector_mul_row(acb_ptr res, acb_srcptr v, const acb_mat_t A, slong prec); void _acb_mat_vector_mul_col(acb_ptr res, const acb_mat_t A, acb_srcptr v, slong prec); void acb_mat_vector_mul_row(acb_ptr res, acb_srcptr v, const acb_mat_t A, slong prec); void acb_mat_vector_mul_col(acb_ptr res, const acb_mat_t A, acb_srcptr v, slong prec); /* Solving */ ACB_MAT_INLINE void acb_mat_swap_rows(acb_mat_t mat, slong * perm, slong r, slong s) { if (r != s) { if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(acb_ptr, mat->rows[r], mat->rows[s]); } } slong acb_mat_find_pivot_partial(const acb_mat_t mat, slong start_row, slong end_row, slong c); void acb_mat_solve_tril_classical(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec); void acb_mat_solve_tril_recursive(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec); void acb_mat_solve_tril(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec); void acb_mat_solve_triu_classical(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec); void acb_mat_solve_triu_recursive(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec); void acb_mat_solve_triu(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec); int acb_mat_lu_classical(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec); int acb_mat_lu_recursive(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec); int acb_mat_lu(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec); void acb_mat_solve_lu_precomp(acb_mat_t X, const slong * perm, const acb_mat_t A, const acb_mat_t B, slong prec); int acb_mat_solve_lu(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec); int acb_mat_solve(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec); int acb_mat_solve_precond(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec); void acb_mat_approx_mul(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec); void acb_mat_approx_solve_triu(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec); void acb_mat_approx_solve_tril(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec); int acb_mat_approx_lu(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec); void acb_mat_approx_solve_lu_precomp(acb_mat_t X, const slong * perm, const acb_mat_t A, const acb_mat_t B, slong prec); int acb_mat_approx_solve(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec); int acb_mat_approx_inv(acb_mat_t X, const acb_mat_t A, slong prec); int acb_mat_inv(acb_mat_t X, const acb_mat_t A, slong prec); void acb_mat_det_lu(acb_t det, const acb_mat_t A, slong prec); void acb_mat_det_precond(acb_t det, const acb_mat_t A, slong prec); void acb_mat_det(acb_t det, const acb_mat_t A, slong prec); /* Eigenvalues and eigenvectors */ int acb_mat_approx_eig_qr(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, const mag_t tol, slong maxiter, slong prec); void acb_mat_eig_global_enclosure(mag_t eps, const acb_mat_t A, acb_srcptr E, const acb_mat_t R, slong prec); void acb_mat_eig_enclosure_rump(acb_t lambda, acb_mat_t J, acb_mat_t X, const acb_mat_t A, const acb_t lambda_approx, const acb_mat_t X_approx, slong prec); int acb_mat_eig_simple_rump(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec); int acb_mat_eig_simple_vdhoeven_mourrain(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec); int acb_mat_eig_simple(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec); int acb_mat_eig_multiple_rump(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec); int acb_mat_eig_multiple(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec); /* Special functions */ void acb_mat_exp_taylor_sum(acb_mat_t S, const acb_mat_t A, slong N, slong prec); void acb_mat_exp(acb_mat_t B, const acb_mat_t A, slong prec); void _acb_mat_charpoly(acb_ptr poly, const acb_mat_t mat, slong prec); void acb_mat_charpoly(acb_poly_t poly, const acb_mat_t mat, slong prec); void _acb_mat_companion(acb_mat_t mat, acb_srcptr poly, slong prec); void acb_mat_companion(acb_mat_t mat, const acb_poly_t poly, slong prec); void acb_mat_trace(acb_t trace, const acb_mat_t mat, slong prec); void _acb_mat_diag_prod(acb_t res, const acb_mat_t A, slong a, slong b, slong prec); void acb_mat_diag_prod(acb_t res, const acb_mat_t A, slong prec); ACB_MAT_INLINE slong acb_mat_allocated_bytes(const acb_mat_t x) { return _acb_vec_allocated_bytes(x->entries, x->r * x->c) + x->r * sizeof(acb_ptr); } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_mat/000077500000000000000000000000001461254215100150105ustar00rootroot00000000000000flint-3.1.3/src/acb_mat/add.c000066400000000000000000000013651461254215100157110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_add(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) acb_add(acb_mat_entry(res, i, j), acb_mat_entry(mat1, i, j), acb_mat_entry(mat2, i, j), prec); } flint-3.1.3/src/acb_mat/approx_eig_qr.c000066400000000000000000000715231461254215100200230ustar00rootroot00000000000000/* Copyright 2013 Timo Hartmann Copyright 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Adapted from eigen.py in mpmath (written by Timo Hartmann) Todo items present in the original code: - Implement balancing - Aggressive early deflation */ #include "acb_mat.h" static void acb_approx_mag(mag_t res, const acb_t x) { mag_t t; mag_init(t); arf_get_mag(res, arb_midref(acb_realref(x))); arf_get_mag(t, arb_midref(acb_imagref(x))); mag_hypot(res, res, t); mag_clear(t); } static void acb_approx_mul(acb_t res, const acb_t x, const acb_t y, slong prec) { arf_complex_mul(arb_midref(acb_realref(res)), arb_midref(acb_imagref(res)), arb_midref(acb_realref(x)), arb_midref(acb_imagref(x)), arb_midref(acb_realref(y)), arb_midref(acb_imagref(y)), prec, ARF_RND_DOWN); } static void acb_approx_add(acb_t res, const acb_t x, const acb_t y, slong prec) { arf_add(arb_midref(acb_realref(res)), arb_midref(acb_realref(x)), arb_midref(acb_realref(y)), prec, ARF_RND_DOWN); arf_add(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(x)), arb_midref(acb_imagref(y)), prec, ARF_RND_DOWN); } static void acb_approx_sub(acb_t res, const acb_t x, const acb_t y, slong prec) { arf_sub(arb_midref(acb_realref(res)), arb_midref(acb_realref(x)), arb_midref(acb_realref(y)), prec, ARF_RND_DOWN); arf_sub(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(x)), arb_midref(acb_imagref(y)), prec, ARF_RND_DOWN); } static void acb_approx_set(acb_t res, const acb_t x) { arf_set(arb_midref(acb_realref(res)), arb_midref(acb_realref(x))); arf_set(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(x))); } static void acb_approx_div_arb(acb_t res, const acb_t x, const arb_t y, slong prec) { arf_div(arb_midref(acb_realref(res)), arb_midref(acb_realref(x)), arb_midref(y), prec, ARF_RND_DOWN); arf_div(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(x)), arb_midref(y), prec, ARF_RND_DOWN); } static void acb_approx_inv(acb_t z, const acb_t x, slong prec) { arf_set(arb_midref(acb_realref(z)), arb_midref(acb_realref(x))); arf_set(arb_midref(acb_imagref(z)), arb_midref(acb_imagref(x))); mag_zero(arb_radref(acb_realref(z))); mag_zero(arb_radref(acb_imagref(z))); acb_inv(z, z, prec); mag_zero(arb_radref(acb_realref(z))); mag_zero(arb_radref(acb_imagref(z))); } static void acb_approx_div(acb_t z, const acb_t x, const acb_t y, slong prec) { acb_t t; acb_init(t); acb_approx_inv(t, y, prec); acb_approx_mul(z, x, t, prec); acb_clear(t); } void acb_mat_approx_qr_step(acb_mat_t A, acb_mat_t Q, slong n0, slong n1, const acb_t shift, slong prec) { slong j, k, n; acb_t c, s, negs, cc, cs, negcs, t; acb_struct v1[2]; acb_struct v1neg[2]; acb_struct v2[2]; acb_struct v2neg[2]; acb_struct v3[2]; arb_t v, u; n = acb_mat_nrows(A); acb_init(c); acb_init(s); acb_init(negs); acb_init(cc); acb_init(cs); acb_init(negcs); acb_init(t); arb_init(v); arb_init(u); /* Calculate Givens rotation */ acb_approx_sub(c, acb_mat_entry(A, n0, n0), shift, prec); acb_approx_set(s, acb_mat_entry(A, n0 + 1, n0)); arf_sosq(arb_midref(v), arb_midref(acb_realref(c)), arb_midref(acb_imagref(c)), prec, ARF_RND_DOWN); arf_sosq(arb_midref(u), arb_midref(acb_realref(s)), arb_midref(acb_imagref(s)), prec, ARF_RND_DOWN); arf_add(arb_midref(v), arb_midref(v), arb_midref(u), prec, ARF_RND_DOWN); arf_sqrt(arb_midref(v), arb_midref(v), prec, ARF_RND_DOWN); if (arb_is_zero(v)) { arb_one(v); acb_one(c); acb_zero(s); } else { acb_approx_div_arb(c, c, v, prec); acb_approx_div_arb(s, s, v, prec); } acb_conj(cc, c); acb_conj(cs, s); acb_neg(negs, s); acb_neg(negcs, cs); v1[0] = *c; v1[1] = *s; v1neg[0] = *c; v1neg[1] = *negs; v2[0] = *cc; v2[1] = *cs; v2neg[0] = *cc; v2neg[1] = *negcs; /* Apply Givens rotation from the left */ for (k = n0; k < n; k++) { v3[0] = *acb_mat_entry(A, n0, k); v3[1] = *acb_mat_entry(A, n0 + 1, k); /* x = A[n0 ,k] */ /* y = A[n0+1,k] */ /* A[n0, k] = cc * x + cs * y */ /* A[n0 + 1, k] = c * y - s * x */ acb_approx_dot(t, NULL, 0, v2, 1, v3, 1, 2, prec); acb_approx_dot(acb_mat_entry(A, n0 + 1, k), NULL, 0, v1neg, 1, v3 + 1, -1, 2, prec); acb_swap(t, acb_mat_entry(A, n0, k)); } /* Apply Givens rotation from the right */ for (k = 0; k < FLINT_MIN(n1, n0 + 3); k++) { /* x = A[k,n0 ] */ /* y = A[k,n0+1] */ /* A[k,n0 ] = c * x + s * y */ /* A[k,n0+1] = cc * y - cs * x */ v3[0] = *acb_mat_entry(A, k, n0); v3[1] = *acb_mat_entry(A, k, n0 + 1); acb_approx_dot(t, NULL, 0, v1, 1, v3, 1, 2, prec); acb_approx_dot(acb_mat_entry(A, k, n0 + 1), NULL, 0, v2neg, 1, v3 + 1, -1, 2, prec); acb_swap(t, acb_mat_entry(A, k, n0)); } if (Q != NULL) { for (k = 0; k < n; k++) { /* x = Q[k,n0 ] */ /* y = Q[k,n0+1] */ /* Q[k,n0 ] = c * x + s * y */ /* Q[k,n0+1] = cc * y - cs * x */ v3[0] = *acb_mat_entry(Q, k, n0); v3[1] = *acb_mat_entry(Q, k, n0 + 1); acb_approx_dot(t, NULL, 0, v1, 1, v3, 1, 2, prec); acb_approx_dot(acb_mat_entry(Q, k, n0 + 1), NULL, 0, v2neg, 1, v3 + 1, -1, 2, prec); acb_swap(t, acb_mat_entry(Q, k, n0)); } } for (j = n0; j < n1 - 2; j++) { /* Calculate Givens rotation */ acb_set(c, acb_mat_entry(A, j + 1, j)); acb_set(s, acb_mat_entry(A, j + 2, j)); arf_sosq(arb_midref(v), arb_midref(acb_realref(c)), arb_midref(acb_imagref(c)), prec, ARF_RND_DOWN); arf_sosq(arb_midref(u), arb_midref(acb_realref(s)), arb_midref(acb_imagref(s)), prec, ARF_RND_DOWN); arf_add(arb_midref(v), arb_midref(v), arb_midref(u), prec, ARF_RND_DOWN); arf_sqrt(arb_midref(v), arb_midref(v), prec, ARF_RND_DOWN); if (arb_is_zero(v)) { acb_zero(acb_mat_entry(A, j + 1, j)); arb_one(v); acb_one(c); acb_zero(s); } else { acb_set_arb(acb_mat_entry(A, j + 1, j), v); acb_approx_div_arb(c, c, v, prec); acb_approx_div_arb(s, s, v, prec); } acb_zero(acb_mat_entry(A, j + 2, j)); acb_conj(cc, c); acb_conj(cs, s); acb_neg(negs, s); acb_neg(negcs, cs); v1[0] = *c; v1[1] = *s; v1neg[0] = *c; v1neg[1] = *negs; v2[0] = *cc; v2[1] = *cs; v2neg[0] = *cc; v2neg[1] = *negcs; /* Apply Givens rotation from the left */ for (k = j + 1; k < n; k++) { v3[0] = *acb_mat_entry(A, j + 1, k); v3[1] = *acb_mat_entry(A, j + 2, k); /* x = A[j+1, k] */ /* y = A[j+2, k] */ /* A[j + 1, k] = cc * x + cs * y */ /* A[j + 2, k] = c * y - s * x */ acb_approx_dot(t, NULL, 0, v2, 1, v3, 1, 2, prec); acb_approx_dot(acb_mat_entry(A, j + 2, k), NULL, 0, v1neg, 1, v3 + 1, -1, 2, prec); acb_swap(t, acb_mat_entry(A, j + 1, k)); } /* Apply Givens rotation from the right */ for (k = 0; k < FLINT_MIN(n1, j + 4); k++) { /* x = A[k,j+1] */ /* y = A[k,j+2] */ /* A[k,j+1] = c * x + s * y */ /* A[k,j+2] = cc * y - cs * x */ v3[0] = *acb_mat_entry(A, k, j + 1); v3[1] = *acb_mat_entry(A, k, j + 2); acb_approx_dot(t, NULL, 0, v1, 1, v3, 1, 2, prec); acb_approx_dot(acb_mat_entry(A, k, j + 2), NULL, 0, v2neg, 1, v3 + 1, -1, 2, prec); acb_swap(t, acb_mat_entry(A, k, j + 1)); } if (Q != NULL) { for (k = 0; k < n; k++) { /* x = Q[k,j+1] */ /* y = Q[k,j+2] */ /* Q[k,j+1] = c * x + s * y */ /* Q[k,j+2] = cc * y - cs * x */ v3[0] = *acb_mat_entry(Q, k, j + 1); v3[1] = *acb_mat_entry(Q, k, j + 2); acb_approx_dot(t, NULL, 0, v1, 1, v3, 1, 2, prec); acb_approx_dot(acb_mat_entry(Q, k, j + 2), NULL, 0, v2neg, 1, v3 + 1, -1, 2, prec); acb_swap(t, acb_mat_entry(Q, k, j + 1)); } } } acb_clear(c); acb_clear(s); acb_clear(negs); acb_clear(cc); acb_clear(cs); acb_clear(negcs); acb_clear(t); arb_clear(v); arb_clear(u); } void acb_mat_approx_hessenberg_reduce_0(acb_mat_t A, acb_ptr T, slong prec) { slong i, j, k, n; arf_t scale, scale_inv, tt, H, G, f; acb_ptr V1, V2; acb_t ff, GG, TT; acb_t F; n = acb_mat_nrows(A); if (n <= 2) return; arf_init(scale); arf_init(scale_inv); arf_init(tt); arf_init(H); arf_init(G); arf_init(f); acb_init(F); V1 = _acb_vec_init(n + 1); V2 = _acb_vec_init(n + 1); acb_init(ff); acb_init(GG); acb_init(TT); for (i = n - 1; i >= 2; i--) { /* Scale the vector (todo: is this needed?) */ arf_zero(scale); for (k = 0; k < i; k++) { arf_abs(tt, arb_midref(acb_realref(acb_mat_entry(A, i, k)))); arf_add(scale, scale, tt, prec, ARF_RND_DOWN); arf_abs(tt, arb_midref(acb_imagref(acb_mat_entry(A, i, k)))); arf_add(scale, scale, tt, prec, ARF_RND_DOWN); } arf_ui_div(scale_inv, 1, scale, prec, ARF_RND_DOWN); if (arf_is_zero(scale)) { acb_zero(T + i); acb_zero(acb_mat_entry(A, i, i - 1)); continue; } /* Calculate parameters for Householder transformation. */ arf_zero(H); for (k = 0; k < i; k++) { arf_ptr Aikr, Aiki; Aikr = arb_midref(acb_realref(acb_mat_entry(A, i, k))); Aiki = arb_midref(acb_imagref(acb_mat_entry(A, i, k))); arf_mul(Aikr, Aikr, scale_inv, prec, ARF_RND_DOWN); arf_mul(Aiki, Aiki, scale_inv, prec, ARF_RND_DOWN); arf_addmul(H, Aikr, Aikr, prec, ARF_RND_DOWN); arf_addmul(H, Aiki, Aiki, prec, ARF_RND_DOWN); } acb_set(F, acb_mat_entry(A, i, i - 1)); /* f = abs(F) */ arf_mul(f, arb_midref(acb_realref(F)), arb_midref(acb_realref(F)), prec, ARF_RND_DOWN); arf_addmul(f, arb_midref(acb_imagref(F)), arb_midref(acb_imagref(F)), prec, ARF_RND_DOWN); arf_sqrt(f, f, prec, ARF_RND_DOWN); arf_sqrt(G, H, prec, ARF_RND_DOWN); /* A[i,i-1] = -G scale */ arf_mul(arb_midref(acb_realref(acb_mat_entry(A, i, i - 1))), G, scale, prec, ARF_RND_DOWN); arf_neg(arb_midref(acb_realref(acb_mat_entry(A, i, i - 1))), arb_midref(acb_realref(acb_mat_entry(A, i, i - 1)))); arf_zero(arb_midref(acb_imagref(acb_mat_entry(A, i, i - 1)))); if (arf_is_zero(f)) { arb_set_arf(acb_realref(T + i), G); arb_zero(acb_imagref(T + i)); } else { /* ff = F / f */ arf_div(arb_midref(acb_realref(ff)), arb_midref(acb_realref(F)), f, prec, ARF_RND_DOWN); arf_div(arb_midref(acb_imagref(ff)), arb_midref(acb_imagref(F)), f, prec, ARF_RND_DOWN); /* T[i] = F + G ff */ acb_set(T + i, F); arf_addmul(arb_midref(acb_realref(T + i)), arb_midref(acb_realref(ff)), G, prec, ARF_RND_DOWN); arf_addmul(arb_midref(acb_imagref(T + i)), arb_midref(acb_imagref(ff)), G, prec, ARF_RND_DOWN); /* A[i,i-1] *= ff */ acb_approx_mul(acb_mat_entry(A, i, i - 1), acb_mat_entry(A, i, i - 1), ff, prec); } arf_addmul(H, G, f, prec, ARF_RND_DOWN); arf_rsqrt(H, H, prec, ARF_RND_DOWN); arf_mul(arb_midref(acb_realref(T + i)), arb_midref(acb_realref(T + i)), H, prec, ARF_RND_DOWN); arf_mul(arb_midref(acb_imagref(T + i)), arb_midref(acb_imagref(T + i)), H, prec, ARF_RND_DOWN); for (k = 0; k < i - 1; k++) { arf_mul(arb_midref(acb_realref(acb_mat_entry(A, i, k))), arb_midref(acb_realref(acb_mat_entry(A, i, k))), H, prec, ARF_RND_DOWN); arf_mul(arb_midref(acb_imagref(acb_mat_entry(A, i, k))), arb_midref(acb_imagref(acb_mat_entry(A, i, k))), H, prec, ARF_RND_DOWN); } /* todo: optimize copies below */ /* todo: conj mid etc... */ /* Apply Householder transformation (from the right). */ for (j = 0; j < i; j++) { acb_conj(V1, T + i); acb_set(V2, acb_mat_entry(A, j, i - 1)); for (k = 0; k < i - 1; k++) { acb_conj(V1 + k + 1, acb_mat_entry(A, i, k)); acb_set(V2 + k + 1, acb_mat_entry(A, j, k)); } acb_approx_dot(GG, NULL, 0, V1, 1, V2, 1, i, prec); acb_approx_mul(TT, GG, T + i, prec); acb_approx_sub(acb_mat_entry(A, j, i - 1), acb_mat_entry(A, j, i - 1), TT, prec); for (k = 0; k < i - 1; k++) { acb_approx_mul(TT, GG, acb_mat_entry(A, i, k), prec); acb_approx_sub(acb_mat_entry(A, j, k), acb_mat_entry(A, j, k), TT, prec); } } for (j = 0; j < n; j++) { acb_set(V1, T + i); acb_set(V2, acb_mat_entry(A, i - 1, j)); for (k = 0; k < i - 1; k++) { acb_set(V1 + k + 1, acb_mat_entry(A, i, k)); acb_set(V2 + k + 1, acb_mat_entry(A, k, j)); } acb_approx_dot(GG, NULL, 0, V1, 1, V2, 1, i, prec); acb_conj(TT, T + i); acb_approx_mul(TT, GG, TT, prec); acb_approx_sub(acb_mat_entry(A, i - 1, j), acb_mat_entry(A, i - 1, j), TT, prec); for (k = 0; k < i - 1; k++) { acb_conj(TT, acb_mat_entry(A, i, k)); acb_approx_mul(TT, GG, TT, prec); acb_approx_sub(acb_mat_entry(A, k, j), acb_mat_entry(A, k, j), TT, prec); } } } arf_clear(scale); arf_clear(scale_inv); arf_clear(tt); arf_clear(H); arf_clear(G); arf_clear(f); acb_clear(F); _acb_vec_clear(V1, n + 1); _acb_vec_clear(V2, n + 1); acb_clear(ff); acb_clear(GG); acb_clear(TT); } void acb_mat_approx_hessenberg_reduce_1(acb_mat_t A, acb_srcptr T, slong prec) { slong i, j, k, n; acb_t G, t; n = acb_mat_nrows(A); if (n <= 1) { if (n == 1) acb_one(acb_mat_entry(A, 0, 0)); return; } acb_one(acb_mat_entry(A, 0, 0)); acb_one(acb_mat_entry(A, 1, 1)); acb_zero(acb_mat_entry(A, 0, 1)); acb_zero(acb_mat_entry(A, 1, 0)); acb_init(G); acb_init(t); for (i = 2; i < n; i++) { if (!acb_is_zero(T + i)) { /* todo: rewrite using approx_dot */ for (j = 0; j < i; j++) { acb_approx_mul(G, T + i, acb_mat_entry(A, i - 1, j), prec); for (k = 0; k < i - 1; k++) { acb_approx_mul(t, acb_mat_entry(A, i, k), acb_mat_entry(A, k, j), prec); acb_approx_add(G, G, t, prec); } acb_conj(t, T + i); acb_approx_mul(t, G, t, prec); acb_approx_sub(acb_mat_entry(A, i - 1, j), acb_mat_entry(A, i - 1, j), t, prec); for (k = 0; k < i - 1; k++) { acb_conj(t, acb_mat_entry(A, i, k)); acb_approx_mul(t, G, t, prec); acb_approx_sub(acb_mat_entry(A, k, j), acb_mat_entry(A, k, j), t, prec); } } } acb_one(acb_mat_entry(A, i, i)); for (j = 0; j < i; j++) { acb_zero(acb_mat_entry(A, j, i)); acb_zero(acb_mat_entry(A, i, j)); } } acb_clear(G); acb_clear(t); } /* Right eigenvectors of a triu matrix. No aliasing. */ void acb_mat_approx_eig_triu_r(acb_mat_t ER, const acb_mat_t A, slong prec) { slong i, j, k, n; mag_t tm, smin, unfl, simin, smlnum, rmax; acb_t r, s, t; n = acb_mat_nrows(A); acb_mat_one(ER); acb_init(r); acb_init(s); acb_init(t); mag_init(tm); mag_init(smin); mag_init(smlnum); mag_init(unfl); mag_init(simin); mag_init(rmax); mag_set_ui_2exp_si(unfl, 1, -30 * prec); mag_mul_ui(smlnum, unfl, n); mag_mul_2exp_si(smlnum, smlnum, prec); mag_set_ui_2exp_si(simin, 1, prec / 2); mag_one(rmax); for (i = 1; i < n; i++) { acb_set(s, acb_mat_entry(A, i, i)); /* smin = max(eps * abs(s), smlnum) */ acb_approx_mag(smin, s); mag_mul_2exp_si(smin, smin, -prec); mag_max(smin, smin, smlnum); for (j = i - 1; j >= 0; j--) { acb_approx_dot(r, NULL, 0, A->rows[j] + j + 1, 1, ER->rows[i] + j + 1, 1, i - j, prec); acb_approx_sub(t, acb_mat_entry(A, j, j), s, prec); /* if abs(t) < smin: t = smin */ acb_approx_mag(tm, t); if (mag_cmp(tm, smin) < 0) { acb_zero(t); arf_set_mag(arb_midref(acb_realref(t)), smin); } acb_approx_div(acb_mat_entry(ER, i, j), r, t, prec); acb_neg(acb_mat_entry(ER, i, j), acb_mat_entry(ER, i, j)); acb_approx_mag(tm, r); mag_max(rmax, rmax, tm); if (mag_cmp(rmax, simin) > 0) { arb_t b; arb_init(b); arf_set_mag(arb_midref(b), rmax); for (k = j; k < i + 1; k++) { acb_approx_div_arb(acb_mat_entry(ER, i, k), acb_mat_entry(ER, i, k), b, prec); } mag_one(rmax); arb_clear(b); } } if (mag_cmp_2exp_si(rmax, 0) != 0) { arb_t b; arb_init(b); arf_set_mag(arb_midref(b), rmax); for (k = 0; k < i + 1; k++) { acb_approx_div_arb(acb_mat_entry(ER, i, k), acb_mat_entry(ER, i, k), b, prec); } arb_clear(b); } } acb_mat_transpose(ER, ER); acb_clear(r); acb_clear(s); acb_clear(t); mag_clear(tm); mag_clear(smin); mag_clear(smlnum); mag_clear(unfl); mag_clear(simin); mag_clear(rmax); } /* Left eigenvectors of a triu matrix. No aliasing. */ void acb_mat_approx_eig_triu_l(acb_mat_t EL, const acb_mat_t A, slong prec) { slong i, j, k, n; mag_t tm, smin, unfl, simin, smlnum, rmax; acb_t r, s, t; acb_mat_t AT; n = acb_mat_nrows(A); acb_mat_init(AT, n, n); acb_mat_one(EL); acb_mat_transpose(AT, A); acb_init(r); acb_init(s); acb_init(t); mag_init(tm); mag_init(smin); mag_init(smlnum); mag_init(unfl); mag_init(simin); mag_init(rmax); mag_set_ui_2exp_si(unfl, 1, -30 * prec); mag_mul_ui(smlnum, unfl, n); mag_mul_2exp_si(smlnum, smlnum, prec); mag_set_ui_2exp_si(simin, 1, prec / 2); mag_one(rmax); for (i = 0; i < n - 1; i++) { acb_set(s, acb_mat_entry(AT, i, i)); /* smin = max(eps * abs(s), smlnum) */ acb_approx_mag(smin, s); mag_mul_2exp_si(smin, smin, -prec); mag_max(smin, smin, smlnum); for (j = i + 1; j < n; j++) { acb_approx_dot(r, NULL, 0, EL->rows[i] + i, 1, AT->rows[j] + i, 1, j - i, prec); acb_approx_sub(t, acb_mat_entry(AT, j, j), s, prec); /* if abs(t) < smin: t = smin */ acb_approx_mag(tm, t); if (mag_cmp(tm, smin) < 0) { acb_zero(t); arf_set_mag(arb_midref(acb_realref(t)), smin); } acb_approx_div(acb_mat_entry(EL, i, j), r, t, prec); acb_neg(acb_mat_entry(EL, i, j), acb_mat_entry(EL, i, j)); acb_approx_mag(tm, r); mag_max(rmax, rmax, tm); if (mag_cmp(rmax, simin) > 0) { arb_t b; arb_init(b); arf_set_mag(arb_midref(b), rmax); for (k = i; k < j + 1; k++) { acb_approx_div_arb(acb_mat_entry(EL, i, k), acb_mat_entry(EL, i, k), b, prec); } mag_one(rmax); arb_clear(b); } } if (mag_cmp_2exp_si(rmax, 0) != 0) { arb_t b; arb_init(b); arf_set_mag(arb_midref(b), rmax); for (k = i; k < n; k++) { acb_approx_div_arb(acb_mat_entry(EL, i, k), acb_mat_entry(EL, i, k), b, prec); } arb_clear(b); } } acb_mat_clear(AT); acb_clear(r); acb_clear(s); acb_clear(t); mag_clear(tm); mag_clear(smin); mag_clear(smlnum); mag_clear(unfl); mag_clear(simin); mag_clear(rmax); } int acb_mat_approx_hessenberg_qr(acb_mat_t A, acb_mat_t Q, const mag_t tol, slong maxiter, slong prec) { slong n, i, j, k, n0, n1, iter, total_iter; mag_t norm, tm, um, eps, ts; acb_t shift, s, t, a, b; int result; n = acb_mat_nrows(A); if (n <= 1) return 1; mag_init(norm); mag_init(tm); mag_init(um); mag_init(eps); mag_init(ts); acb_init(shift); acb_init(s); acb_init(t); acb_init(a); acb_init(b); for (i = 0; i < n; i++) { for (j = 0; j < FLINT_MIN(i + 2, n); j++) { arf_get_mag(tm, arb_midref(acb_realref(acb_mat_entry(A, j, i)))); arf_get_mag(um, arb_midref(acb_imagref(acb_mat_entry(A, j, i)))); mag_addmul(norm, tm, tm); mag_addmul(norm, um, um); } } mag_sqrt(norm, norm); mag_div_ui(norm, norm, n); if (mag_is_zero(norm)) return 1; if (mag_is_inf(norm)) return 0; if (tol == NULL) { mag_one(eps); mag_mul_2exp_si(eps, eps, -prec); mag_div_ui(eps, eps, 100 * n); } else { mag_set(eps, tol); } if (maxiter <= 0) { maxiter = 14 * n; maxiter += prec / 10; } /* The active submatrix is A[n0:n1,n0:n1]. */ n0 = 0; n1 = n; iter = total_iter = 0; result = 0; while (1) { k = n0; /* flint_printf("total_iter %wd active %wd\n", total_iter, n1 - n0); */ while (k + 1 < n1) { mag_zero(ts); arf_get_mag(tm, arb_midref(acb_realref(acb_mat_entry(A, k, k)))); mag_add(ts, ts, tm); arf_get_mag(tm, arb_midref(acb_imagref(acb_mat_entry(A, k, k)))); mag_add(ts, ts, tm); arf_get_mag(tm, arb_midref(acb_realref(acb_mat_entry(A, k + 1, k + 1)))); mag_add(ts, ts, tm); arf_get_mag(tm, arb_midref(acb_imagref(acb_mat_entry(A, k + 1, k + 1)))); mag_add(ts, ts, tm); /* if s < eps * norm, s = norm */ mag_mul(tm, eps, norm); if (mag_cmp(ts, tm) < 0) mag_set(ts, norm); /* if abs(A[k+1,k]) < eps * s, break */ arf_get_mag(tm, arb_midref(acb_realref(acb_mat_entry(A, k + 1, k)))); arf_get_mag(um, arb_midref(acb_imagref(acb_mat_entry(A, k + 1, k)))); mag_hypot(tm, tm, um); mag_mul(um, eps, ts); if (mag_cmp(tm, um) < 0) break; k++; } /* Deflation found at position (k+1, k). */ if (k + 1 < n1) { acb_zero(acb_mat_entry(A, k + 1, k)); n0 = k + 1; iter = 0; if (n0 + 1 >= n1) { /* Block of size at most two has converged. */ n0 = 0; n1 = k + 1; if (n1 < 2) { /* QR algorithm has converged. */ result = 1; goto cleanup; } } } else { if (iter % 30 == 10) { /* Exceptional shift */ acb_set(shift, acb_mat_entry(A, n1 - 1, n1 - 2)); } else if (iter % 30 == 20) { /* Exceptional shift */ acb_abs(acb_realref(shift), acb_mat_entry(A, n1 - 1, n1 - 2), prec); arb_zero(acb_imagref(shift)); } else if (iter % 30 == 29) { /* Exceptional shift */ acb_zero(shift); arf_set_mag(arb_midref(acb_realref(shift)), norm); } else { acb_approx_add(t, acb_mat_entry(A, n1 - 2, n1 - 2), acb_mat_entry(A, n1 - 1, n1 - 1), prec); acb_approx_sub(a, acb_mat_entry(A, n1 - 1, n1 - 1), acb_mat_entry(A, n1 - 2, n1 - 2), prec); acb_approx_mul(a, a, a, prec); acb_approx_mul(b, acb_mat_entry(A, n1 - 1, n1 - 2), acb_mat_entry(A, n1 - 2, n1 - 1), prec); acb_mul_2exp_si(b, b, 2); acb_approx_add(s, a, b, prec); if (arb_is_positive(acb_realref(s))) { acb_sqrt(s, s, prec); acb_get_mid(s, s); } else { acb_neg(s, s); acb_sqrt(s, s, prec); acb_get_mid(s, s); acb_mul_onei(s, s); } acb_approx_add(a, t, s, prec); acb_approx_sub(b, t, s, prec); acb_mul_2exp_si(a, a, -1); acb_mul_2exp_si(b, b, -1); acb_approx_sub(s, acb_mat_entry(A, n1 - 1, n1 - 1), a, prec); acb_approx_sub(t, acb_mat_entry(A, n1 - 1, n1 - 1), b, prec); acb_get_mag(tm, s); acb_get_mag(um, t); if (mag_cmp(tm, um) > 0) acb_set(shift, b); else acb_set(shift, a); } mag_zero(arb_radref(acb_realref(shift))); mag_zero(arb_radref(acb_imagref(shift))); iter++; total_iter++; acb_mat_approx_qr_step(A, Q, n0, n1, shift, prec); if (iter > maxiter) { result = 0; goto cleanup; } } } cleanup: mag_clear(norm); mag_clear(tm); mag_clear(um); mag_clear(ts); mag_clear(eps); acb_clear(shift); acb_clear(s); acb_clear(t); acb_clear(a); acb_clear(b); return result; } int acb_mat_approx_eig_qr(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, const mag_t tol, slong maxiter, slong prec) { slong n, i, j; acb_ptr T; acb_mat_t Acopy, Q; int result; n = acb_mat_nrows(A); T = _acb_vec_init(n); acb_mat_init(Acopy, n, n); acb_mat_get_mid(Acopy, A); acb_mat_approx_hessenberg_reduce_0(Acopy, T, prec); if (L != NULL || R != NULL) { acb_mat_init(Q, n, n); acb_mat_set(Q, Acopy); acb_mat_approx_hessenberg_reduce_1(Q, T, prec); } for (i = 0; i < n; i++) for (j = i + 2; j < n; j++) acb_zero(acb_mat_entry(Acopy, j, i)); result = acb_mat_approx_hessenberg_qr(Acopy, (L != NULL || R != NULL) ? Q : NULL, tol, maxiter, prec); for (i = 0; i < n; i++) acb_get_mid(E + i, acb_mat_entry(Acopy, i, i)); if (R != NULL) { acb_mat_t ER; acb_mat_init(ER, n, n); acb_mat_approx_eig_triu_r(ER, Acopy, prec); acb_mat_approx_mul(R, Q, ER, prec); acb_mat_get_mid(R, R); /* zero radii */ acb_mat_clear(ER); } if (L != NULL) { acb_mat_t EL; acb_mat_init(EL, n, n); acb_mat_approx_eig_triu_l(EL, Acopy, prec); acb_mat_conjugate_transpose(Q, Q); acb_mat_approx_mul(L, EL, Q, prec); acb_mat_get_mid(L, L); /* zero radii */ acb_mat_clear(EL); } if (L != NULL || R != NULL) acb_mat_clear(Q); _acb_vec_clear(T, n); acb_mat_clear(Acopy); return result; } flint-3.1.3/src/acb_mat/approx_inv.c000066400000000000000000000014221461254215100173400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_approx_inv(acb_mat_t X, const acb_mat_t A, slong prec) { if (X == A) { int r; acb_mat_t T; acb_mat_init(T, acb_mat_nrows(A), acb_mat_ncols(A)); r = acb_mat_approx_inv(T, A, prec); acb_mat_swap(T, X); acb_mat_clear(T); return r; } acb_mat_one(X); return acb_mat_approx_solve(X, A, X, prec); } flint-3.1.3/src/acb_mat/approx_lu.c000066400000000000000000000124451461254215100171730ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" static void _apply_permutation(slong * AP, acb_mat_t A, slong * P, slong n, slong offset) { if (n != 0) { acb_ptr * Atmp; slong * APtmp; slong i; Atmp = flint_malloc(sizeof(acb_ptr) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } static void _acb_approx_mul(acb_t res, const acb_t x, const acb_t y, slong prec) { arf_complex_mul(arb_midref(acb_realref(res)), arb_midref(acb_imagref(res)), arb_midref(acb_realref(x)), arb_midref(acb_imagref(x)), arb_midref(acb_realref(y)), arb_midref(acb_imagref(y)), prec, ARB_RND); } static void _acb_approx_inv(acb_t z, const acb_t x, slong prec) { arf_set(arb_midref(acb_realref(z)), arb_midref(acb_realref(x))); arf_set(arb_midref(acb_imagref(z)), arb_midref(acb_imagref(x))); mag_zero(arb_radref(acb_realref(z))); mag_zero(arb_radref(acb_imagref(z))); acb_inv(z, z, prec); mag_zero(arb_radref(acb_realref(z))); mag_zero(arb_radref(acb_imagref(z))); } static void _acb_vec_approx_scalar_addmul(acb_ptr res, acb_srcptr vec, slong len, const acb_t c, slong prec) { acb_t t; slong i; acb_init(t); for (i = 0; i < len; i++) { _acb_approx_mul(t, vec + i, c, prec); arf_add(arb_midref(acb_realref(res + i)), arb_midref(acb_realref(res + i)), arb_midref(acb_realref(t)), prec, ARB_RND); arf_add(arb_midref(acb_imagref(res + i)), arb_midref(acb_imagref(res + i)), arb_midref(acb_imagref(t)), prec, ARB_RND); } acb_clear(t); } int acb_mat_approx_lu_classical(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec) { acb_t d, e; acb_ptr * a; slong i, j, m, n, r, row, col; int result; if (acb_mat_is_empty(A)) return 1; m = acb_mat_nrows(A); n = acb_mat_ncols(A); acb_mat_get_mid(LU, A); a = LU->rows; row = col = 0; for (i = 0; i < m; i++) P[i] = i; acb_init(d); acb_init(e); result = 1; while (row < m && col < n) { r = acb_mat_find_pivot_partial(LU, row, m, col); if (r == -1) { result = 0; break; } else if (r != row) acb_mat_swap_rows(LU, P, row, r); _acb_approx_inv(d, a[row] + col, prec); for (j = row + 1; j < m; j++) { _acb_approx_mul(e, a[j] + col, d, prec); acb_neg(e, e); _acb_vec_approx_scalar_addmul(a[j] + col, a[row] + col, n - col, e, prec); acb_zero(a[j] + col); acb_neg(a[j] + row, e); } row++; col++; } acb_clear(d); acb_clear(e); return result; } int acb_mat_approx_lu_recursive(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec) { slong i, m, n, r1, r2, n1; acb_mat_t A0, A1, A00, A01, A10, A11; slong * P1; m = A->r; n = A->c; if (m <= 1 || n <= 1) { return acb_mat_approx_lu_classical(P, LU, A, prec); } acb_mat_get_mid(LU, A); n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; P1 = flint_malloc(sizeof(slong) * m); acb_mat_window_init(A0, LU, 0, 0, m, n1); acb_mat_window_init(A1, LU, 0, n1, m, n); r1 = acb_mat_approx_lu(P1, A0, A0, prec); if (!r1) { flint_free(P1); acb_mat_window_clear(A0); acb_mat_window_clear(A1); return 0; } /* r1 = rank of A0 */ r1 = FLINT_MIN(m, n1); _apply_permutation(P, LU, P1, m, 0); acb_mat_window_init(A00, LU, 0, 0, r1, r1); acb_mat_window_init(A10, LU, r1, 0, m, r1); acb_mat_window_init(A01, LU, 0, n1, r1, n); acb_mat_window_init(A11, LU, r1, n1, m, n); acb_mat_approx_solve_tril(A01, A00, A01, 1, prec); { /* acb_mat_submul(A11, A11, A10, A01, prec); */ acb_mat_t T; acb_mat_init(T, A10->r, A01->c); acb_mat_approx_mul(T, A10, A01, prec); acb_mat_sub(A11, A11, T, prec); acb_mat_get_mid(A11, A11); acb_mat_clear(T); } r2 = acb_mat_approx_lu(P1, A11, A11, prec); if (!r2) r1 = r2 = 0; else _apply_permutation(P, LU, P1, m - r1, r1); flint_free(P1); acb_mat_window_clear(A00); acb_mat_window_clear(A01); acb_mat_window_clear(A10); acb_mat_window_clear(A11); acb_mat_window_clear(A0); acb_mat_window_clear(A1); return r1 && r2; } int acb_mat_approx_lu(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec) { if (acb_mat_nrows(A) < 8 || acb_mat_ncols(A) < 8) return acb_mat_approx_lu_classical(P, LU, A, prec); else return acb_mat_approx_lu_recursive(P, LU, A, prec); } flint-3.1.3/src/acb_mat/approx_mul.c000066400000000000000000000074671461254215100173600ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_approx_mul_classical(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { slong ar, br, bc, i, j; ar = acb_mat_nrows(A); br = acb_mat_nrows(B); bc = acb_mat_ncols(B); if (br == 0) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { arf_zero(arb_midref(acb_realref(acb_mat_entry(C, i, j)))); arf_zero(arb_midref(acb_imagref(acb_mat_entry(C, i, j)))); } } return; } if (A == C || B == C) { acb_mat_t T; acb_mat_init(T, ar, bc); acb_mat_approx_mul_classical(T, A, B, prec); acb_mat_swap_entrywise(T, C); acb_mat_clear(T); return; } if (br == 1) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { arf_complex_mul( arb_midref(acb_realref(acb_mat_entry(C, i, j))), arb_midref(acb_imagref(acb_mat_entry(C, i, j))), arb_midref(acb_realref(acb_mat_entry(A, i, 0))), arb_midref(acb_imagref(acb_mat_entry(A, i, 0))), arb_midref(acb_realref(acb_mat_entry(B, 0, j))), arb_midref(acb_imagref(acb_mat_entry(B, 0, j))), prec, ARB_RND); } } } else { acb_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(sizeof(acb_struct) * br * bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) tmp[j * br + i] = *acb_mat_entry(B, i, j); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { acb_approx_dot(acb_mat_entry(C, i, j), NULL, 0, A->rows[i], 1, tmp + j * br, 1, br, prec); } } TMP_END; } } void acb_mat_approx_mul(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { slong cutoff; /* todo: detect small-integer matrices */ if (prec <= 2 * FLINT_BITS) cutoff = 120; else if (prec <= 16 * FLINT_BITS) cutoff = 60; else cutoff = 40; if (acb_mat_nrows(A) <= cutoff || acb_mat_ncols(A) <= cutoff || acb_mat_ncols(B) <= cutoff) { acb_mat_approx_mul_classical(C, A, B, prec); } else { if (acb_mat_is_exact(A) && acb_mat_is_exact(B)) { acb_mat_mul(C, A, B, prec); } else { acb_mat_t AM, BM; if (acb_mat_is_exact(A)) { acb_mat_init(BM, acb_mat_nrows(B), acb_mat_ncols(B)); acb_mat_get_mid(BM, B); acb_mat_mul(C, A, BM, prec); acb_mat_clear(BM); } else if (acb_mat_is_exact(B)) { acb_mat_init(AM, acb_mat_nrows(A), acb_mat_ncols(A)); acb_mat_get_mid(AM, A); acb_mat_mul(C, AM, B, prec); acb_mat_clear(AM); } else { acb_mat_init(BM, acb_mat_nrows(B), acb_mat_ncols(B)); acb_mat_get_mid(BM, B); acb_mat_init(AM, acb_mat_nrows(A), acb_mat_ncols(A)); acb_mat_get_mid(AM, A); acb_mat_mul(C, AM, BM, prec); acb_mat_clear(AM); acb_mat_clear(BM); } } acb_mat_get_mid(C, C); } } flint-3.1.3/src/acb_mat/approx_solve.c000066400000000000000000000016231461254215100176770ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "acb_mat.h" int acb_mat_approx_solve(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) { int result; slong n, m, *perm; acb_mat_t LU; n = acb_mat_nrows(A); m = acb_mat_ncols(X); if (n == 0 || m == 0) return 1; perm = _perm_init(n); acb_mat_init(LU, n, n); result = acb_mat_approx_lu(perm, LU, A, prec); if (result) acb_mat_approx_solve_lu_precomp(X, perm, LU, B, prec); acb_mat_clear(LU); _perm_clear(perm); return result; } flint-3.1.3/src/acb_mat/approx_solve_lu_precomp.c000066400000000000000000000024071461254215100221250ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_approx_solve_lu_precomp(acb_mat_t X, const slong * perm, const acb_mat_t A, const acb_mat_t B, slong prec) { slong i, c, n, m; n = acb_mat_nrows(X); m = acb_mat_ncols(X); if (X == B) { acb_ptr tmp = flint_malloc(sizeof(acb_struct) * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) tmp[i] = B->rows[perm[i]][c]; for (i = 0; i < n; i++) X->rows[i][c] = tmp[i]; } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { acb_set(acb_mat_entry(X, i, c), acb_mat_entry(B, perm[i], c)); } } } acb_mat_get_mid(X, X); acb_mat_approx_solve_tril(X, A, X, 1, prec); acb_mat_approx_solve_triu(X, A, X, 0, prec); } flint-3.1.3/src/acb_mat/approx_solve_tril.c000066400000000000000000000070121461254215100207270ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" static void acb_approx_mul(acb_t res, const acb_t x, const acb_t y, slong prec) { arf_complex_mul(arb_midref(acb_realref(res)), arb_midref(acb_imagref(res)), arb_midref(acb_realref(x)), arb_midref(acb_imagref(x)), arb_midref(acb_realref(y)), arb_midref(acb_imagref(y)), prec, ARB_RND); } /* note: the tmp variable t should have zero radius */ static void acb_approx_div(acb_t z, const acb_t x, const acb_t y, acb_t t, slong prec) { arf_set(arb_midref(acb_realref(t)), arb_midref(acb_realref(y))); arf_set(arb_midref(acb_imagref(t)), arb_midref(acb_imagref(y))); acb_inv(t, t, prec); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_approx_mul(z, x, t, prec); } void acb_mat_approx_solve_tril_classical(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) { slong i, j, n, m; acb_ptr tmp; acb_t s, t; n = L->r; m = B->c; acb_init(s); acb_init(t); tmp = flint_malloc(sizeof(acb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *acb_mat_entry(X, j, i); for (j = 0; j < n; j++) { acb_approx_dot(s, acb_mat_entry(B, j, i), 1, L->rows[j], 1, tmp, 1, j, prec); if (!unit) acb_approx_div(tmp + j, s, acb_mat_entry(L, j, j), t, prec); else acb_swap(tmp + j, s); } for (j = 0; j < n; j++) *acb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); acb_clear(s); acb_clear(t); } void acb_mat_approx_solve_tril_recursive(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) { acb_mat_t LA, LC, LD, XX, XY, BX, BY, T; slong r, n, m; n = L->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A 0]^ [X] == [A^ 0 ] [X] == [A^ X] [C D] [Y] == [-D^ C A^ D^] [Y] == [D^ (Y - C A^ X)] */ acb_mat_window_init(LA, L, 0, 0, r, r); acb_mat_window_init(LC, L, r, 0, n, r); acb_mat_window_init(LD, L, r, r, n, n); acb_mat_window_init(BX, B, 0, 0, r, m); acb_mat_window_init(BY, B, r, 0, n, m); acb_mat_window_init(XX, X, 0, 0, r, m); acb_mat_window_init(XY, X, r, 0, n, m); acb_mat_approx_solve_tril(XX, LA, BX, unit, prec); /* acb_mat_submul(XY, BY, LC, XX); */ acb_mat_init(T, LC->r, BX->c); acb_mat_approx_mul(T, LC, XX, prec); acb_mat_sub(XY, BY, T, prec); acb_mat_get_mid(XY, XY); acb_mat_clear(T); acb_mat_approx_solve_tril(XY, LD, XY, unit, prec); acb_mat_window_clear(LA); acb_mat_window_clear(LC); acb_mat_window_clear(LD); acb_mat_window_clear(BX); acb_mat_window_clear(BY); acb_mat_window_clear(XX); acb_mat_window_clear(XY); } void acb_mat_approx_solve_tril(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) acb_mat_approx_solve_tril_classical(X, L, B, unit, prec); else acb_mat_approx_solve_tril_recursive(X, L, B, unit, prec); } flint-3.1.3/src/acb_mat/approx_solve_triu.c000066400000000000000000000067201461254215100207450ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" static void acb_approx_mul(acb_t res, const acb_t x, const acb_t y, slong prec) { arf_complex_mul(arb_midref(acb_realref(res)), arb_midref(acb_imagref(res)), arb_midref(acb_realref(x)), arb_midref(acb_imagref(x)), arb_midref(acb_realref(y)), arb_midref(acb_imagref(y)), prec, ARB_RND); } /* note: the tmp variable t should have zero radius */ static void acb_approx_div(acb_t z, const acb_t x, const acb_t y, acb_t t, slong prec) { arf_set(arb_midref(acb_realref(t)), arb_midref(acb_realref(y))); arf_set(arb_midref(acb_imagref(t)), arb_midref(acb_imagref(y))); acb_inv(t, t, prec); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_approx_mul(z, x, t, prec); } void acb_mat_approx_solve_triu_classical(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) { slong i, j, n, m; acb_ptr tmp; acb_t s, t; n = U->r; m = B->c; acb_init(s); acb_init(t); tmp = flint_malloc(sizeof(acb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *acb_mat_entry(X, j, i); for (j = n - 1; j >= 0; j--) { acb_approx_dot(s, acb_mat_entry(B, j, i), 1, U->rows[j] + j + 1, 1, tmp + j + 1, 1, n - j - 1, prec); if (!unit) acb_approx_div(tmp + j, s, arb_mat_entry(U, j, j), t, prec); else acb_swap(tmp + j, s); } for (j = 0; j < n; j++) *acb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); acb_clear(s); acb_clear(t); } void acb_mat_approx_solve_triu_recursive(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) { acb_mat_t UA, UB, UD, XX, XY, BX, BY, T; slong r, n, m; n = U->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A B]^ [X] == [A^ (X - B D^ Y)] [0 D] [Y] == [ D^ Y ] */ acb_mat_window_init(UA, U, 0, 0, r, r); acb_mat_window_init(UB, U, 0, r, r, n); acb_mat_window_init(UD, U, r, r, n, n); acb_mat_window_init(BX, B, 0, 0, r, m); acb_mat_window_init(BY, B, r, 0, n, m); acb_mat_window_init(XX, X, 0, 0, r, m); acb_mat_window_init(XY, X, r, 0, n, m); acb_mat_approx_solve_triu(XY, UD, BY, unit, prec); acb_mat_init(T, UB->r, XY->c); acb_mat_approx_mul(T, UB, XY, prec); acb_mat_sub(XX, BX, T, prec); acb_mat_get_mid(XX, XX); acb_mat_clear(T); acb_mat_approx_solve_triu(XX, UA, XX, unit, prec); acb_mat_window_clear(UA); acb_mat_window_clear(UB); acb_mat_window_clear(UD); acb_mat_window_clear(BX); acb_mat_window_clear(BY); acb_mat_window_clear(XX); acb_mat_window_clear(XY); } void acb_mat_approx_solve_triu(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) acb_mat_approx_solve_triu_classical(X, U, B, unit, prec); else acb_mat_approx_solve_triu_recursive(X, U, B, unit, prec); } flint-3.1.3/src/acb_mat/bound_frobenius_norm.c000066400000000000000000000017121461254215100213730ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_bound_frobenius_norm(mag_t b, const acb_mat_t A) { slong i, j, r, c; mag_t t; r = acb_mat_nrows(A); c = acb_mat_ncols(A); mag_zero(b); if (r == 0 || c == 0) return; mag_init(t); for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { acb_srcptr z = acb_mat_entry(A, i, j); arb_get_mag(t, acb_realref(z)); mag_addmul(b, t, t); arb_get_mag(t, acb_imagref(z)); mag_addmul(b, t, t); } } mag_sqrt(b, b); mag_clear(t); } flint-3.1.3/src/acb_mat/bound_inf_norm.c000066400000000000000000000016221461254215100201530ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_bound_inf_norm(mag_t b, const acb_mat_t A) { slong i, j, r, c; mag_t s, t; r = acb_mat_nrows(A); c = acb_mat_ncols(A); mag_zero(b); if (r == 0 || c == 0) return; mag_init(s); mag_init(t); for (i = 0; i < r; i++) { mag_zero(s); for (j = 0; j < c; j++) { acb_get_mag(t, acb_mat_entry(A, i, j)); mag_add(s, s, t); } mag_max(b, b, s); } mag_clear(s); mag_clear(t); } flint-3.1.3/src/acb_mat/charpoly.c000066400000000000000000000044111461254215100167750ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_mat.h" void _acb_mat_charpoly(acb_ptr cp, const acb_mat_t mat, slong prec) { const slong n = mat->r; if (n == 0) { acb_one(cp); } else if (n == 1) { acb_neg(cp + 0, acb_mat_entry(mat, 0, 0)); acb_one(cp + 1); } else { slong i, k, t; acb_ptr a, A, s; a = _acb_vec_init(n * n); A = a + (n - 1) * n; _acb_vec_zero(cp, n + 1); acb_neg(cp + 0, acb_mat_entry(mat, 0, 0)); for (t = 1; t < n; t++) { for (i = 0; i <= t; i++) { acb_set(a + 0 * n + i, acb_mat_entry(mat, i, t)); } acb_set(A + 0, acb_mat_entry(mat, t, t)); for (k = 1; k < t; k++) { for (i = 0; i <= t; i++) { s = a + k * n + i; acb_dot(s, NULL, 0, mat->rows[i], 1, a + (k - 1) * n, 1, t + 1, prec); } acb_set(A + k, a + k * n + t); } acb_dot(A + t, NULL, 0, mat->rows[t], 1, a + (t - 1) * n, 1, t + 1, prec); for (k = 0; k <= t; k++) { acb_dot(cp + k, cp + k, 1, A, 1, cp + k - 1, -1, k, prec); acb_sub(cp + k, cp + k, A + k, prec); } } /* Shift all coefficients up by one */ for (i = n; i > 0; i--) acb_swap(cp + i, cp + (i - 1)); acb_one(cp + 0); _acb_poly_reverse(cp, cp, n + 1, n + 1); _acb_vec_clear(a, n * n); } } void acb_mat_charpoly(acb_poly_t cp, const acb_mat_t mat, slong prec) { if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (acb_mat_charpoly). Non-square matrix.\n"); } acb_poly_fit_length(cp, mat->r + 1); _acb_poly_set_length(cp, mat->r + 1); _acb_mat_charpoly(cp->coeffs, mat, prec); } flint-3.1.3/src/acb_mat/clear.c000066400000000000000000000010731461254215100162430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_clear(acb_mat_t mat) { if (mat->entries != NULL) { _acb_vec_clear(mat->entries, mat->r * mat->c); flint_free(mat->rows); } } flint-3.1.3/src/acb_mat/companion.c000066400000000000000000000022701461254215100171400ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_mat.h" void _acb_mat_companion(acb_mat_t A, acb_srcptr poly, slong prec) { slong i, j, n; acb_t c; n = acb_mat_nrows(A); if (n == 0) return; for (i = 0; i < n - 1; i++) for (j = 0; j < n; j++) acb_set_ui(acb_mat_entry(A, i, j), (i + 1) == j); acb_init(c); acb_inv(c, poly + n, prec); acb_neg(c, c); for (j = 0; j < n; j++) acb_mul(acb_mat_entry(A, n - 1, j), poly + j, c, prec); acb_clear(c); } void acb_mat_companion(acb_mat_t A, const acb_poly_t poly, slong prec) { slong n = acb_mat_nrows(A); if (n != acb_poly_degree(poly) || n != acb_mat_ncols(A)) { flint_throw(FLINT_ERROR, "acb_mat_companion: incompatible dimensions!\n"); } _acb_mat_companion(A, poly->coeffs, prec); } flint-3.1.3/src/acb_mat/conjugate.c000066400000000000000000000015031461254215100171320ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_conjugate(acb_mat_t B, const acb_mat_t A) { slong i, j; if ((acb_mat_nrows(B) != acb_mat_nrows(A)) || (acb_mat_ncols(B) != acb_mat_ncols(A))) { flint_throw(FLINT_ERROR, "acb_mat_conjugate: incompatible dimensions.\n"); } for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_conj(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j)); } flint-3.1.3/src/acb_mat/contains.c000066400000000000000000000015121461254215100167710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_contains(const acb_mat_t mat1, const acb_mat_t mat2) { slong i, j; if ((acb_mat_nrows(mat1) != acb_mat_nrows(mat2)) || (acb_mat_ncols(mat1) != acb_mat_ncols(mat2))) return 0; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) if (!acb_contains(acb_mat_entry(mat1, i, j), acb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/contains_fmpq_mat.c000066400000000000000000000016001461254215100206530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" #include "acb_mat.h" int acb_mat_contains_fmpq_mat(const acb_mat_t mat1, const fmpq_mat_t mat2) { slong i, j; if ((acb_mat_nrows(mat1) != acb_mat_nrows(mat2)) || (acb_mat_ncols(mat1) != acb_mat_ncols(mat2))) return 0; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) if (!acb_contains_fmpq(acb_mat_entry(mat1, i, j), fmpq_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/contains_fmpz_mat.c000066400000000000000000000016001461254215100206640ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "acb_mat.h" int acb_mat_contains_fmpz_mat(const acb_mat_t mat1, const fmpz_mat_t mat2) { slong i, j; if ((acb_mat_nrows(mat1) != acb_mat_nrows(mat2)) || (acb_mat_ncols(mat1) != acb_mat_ncols(mat2))) return 0; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) if (!acb_contains_fmpz(acb_mat_entry(mat1, i, j), fmpz_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/det.c000066400000000000000000000043671461254215100157420ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" static void _acb_mat_det_cofactor_2x2(acb_t t, const acb_mat_t A, slong prec) { acb_mul (t, acb_mat_entry(A, 0, 0), acb_mat_entry(A, 1, 1), prec); acb_submul(t, acb_mat_entry(A, 0, 1), acb_mat_entry(A, 1, 0), prec); } static void _acb_mat_det_cofactor_3x3(acb_t t, const acb_mat_t A, slong prec) { acb_t a; acb_init(a); acb_mul (a, acb_mat_entry(A, 1, 0), acb_mat_entry(A, 2, 1), prec); acb_submul(a, acb_mat_entry(A, 1, 1), acb_mat_entry(A, 2, 0), prec); acb_mul (t, a, acb_mat_entry(A, 0, 2), prec); acb_mul (a, acb_mat_entry(A, 1, 2), acb_mat_entry(A, 2, 0), prec); acb_submul(a, acb_mat_entry(A, 1, 0), acb_mat_entry(A, 2, 2), prec); acb_addmul(t, a, acb_mat_entry(A, 0, 1), prec); acb_mul (a, acb_mat_entry(A, 1, 1), acb_mat_entry(A, 2, 2), prec); acb_submul(a, acb_mat_entry(A, 1, 2), acb_mat_entry(A, 2, 1), prec); acb_addmul(t, a, acb_mat_entry(A, 0, 0), prec); acb_clear(a); } void acb_mat_det(acb_t det, const acb_mat_t A, slong prec) { slong n; if (!acb_mat_is_square(A)) { flint_throw(FLINT_ERROR, "acb_mat_det: a square matrix is required!\n"); } n = acb_mat_nrows(A); if (n == 0) { acb_one(det); } else if (n == 1) { acb_set_round(det, acb_mat_entry(A, 0, 0), prec); } else if (n == 2) { _acb_mat_det_cofactor_2x2(det, A, prec); } else if (!acb_mat_is_finite(A)) { acb_indeterminate(det); } else if (acb_mat_is_tril(A) || acb_mat_is_triu(A)) { acb_mat_diag_prod(det, A, prec); } else if (n == 3) { _acb_mat_det_cofactor_3x3(det, A, prec); /* note: 4x4 performs worse than LU */ } else { if (n <= 14 || prec > 10.0 * n) acb_mat_det_lu(det, A, prec); else acb_mat_det_precond(det, A, prec); } } flint-3.1.3/src/acb_mat/det_lu.c000066400000000000000000000063761461254215100164440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" slong acb_mat_gauss_partial(acb_mat_t A, slong prec) { acb_t e; acb_ptr * a; slong j, m, n, r, rank, row, col, sign; m = A->r; n = A->c; a = A->rows; rank = row = col = 0; sign = 1; acb_init(e); while (row < m && col < n) { r = acb_mat_find_pivot_partial(A, row, m, col); if (r == -1) { break; } else if (r != row) { acb_mat_swap_rows(A, NULL, row, r); sign *= -1; } rank++; for (j = row + 1; j < m; j++) { acb_div(e, a[j] + col, a[row] + col, prec); acb_neg(e, e); _acb_vec_scalar_addmul(a[j] + col + 1, a[row] + col + 1, n - col - 1, e, prec); } row++; col++; } acb_clear(e); return rank * sign; } void acb_vec_get_arf_2norm_squared_bound(arf_t s, acb_srcptr vec, slong len, slong prec) { slong i; arf_t t; arf_init(t); arf_zero(s); for (i = 0; i < len; i++) { arb_get_abs_ubound_arf(t, acb_realref(vec + i), prec); arf_addmul(s, t, t, prec, ARF_RND_UP); arb_get_abs_ubound_arf(t, acb_imagref(vec + i), prec); arf_addmul(s, t, t, prec, ARF_RND_UP); } arf_clear(t); } void acb_mat_det_lu_inplace(acb_t det, acb_mat_t A, slong prec) { slong i, n, sign, rank; int is_real; n = acb_mat_nrows(A); rank = acb_mat_gauss_partial(A, prec); sign = (rank < 0) ? -1 : 1; rank = FLINT_ABS(rank); _acb_mat_diag_prod(det, A, 0, rank, prec); acb_mul_si(det, det, sign, prec); /* bound unreduced part using Hadamard's inequality */ if (rank < n) { arf_t t; arf_t d; acb_t e; arf_init(t); arf_init(d); acb_init(e); arf_one(d); is_real = acb_mat_is_real(A); for (i = rank; i < n; i++) { acb_vec_get_arf_2norm_squared_bound(t, A->rows[i] + rank, n - rank, MAG_BITS); arf_mul(d, d, t, MAG_BITS, ARF_RND_UP); } /* now d contains the absolute value of the determinant */ arf_sqrt(d, d, MAG_BITS, ARF_RND_UP); /* multiply by disc with radius d */ if (is_real) { arb_add_error_arf(acb_realref(e), d); } else { arb_add_error_arf(acb_realref(e), d); arb_add_error_arf(acb_imagref(e), d); } acb_mul(det, det, e, prec); acb_clear(e); arf_clear(d); arf_clear(t); } } void acb_mat_det_lu(acb_t det, const acb_mat_t A, slong prec) { slong n; n = acb_mat_nrows(A); if (n == 0) { acb_one(det); } else { acb_mat_t T; acb_mat_init(T, acb_mat_nrows(A), acb_mat_ncols(A)); acb_mat_set(T, A); acb_mat_det_lu_inplace(det, T, prec); acb_mat_clear(T); } } flint-3.1.3/src/acb_mat/det_precond.c000066400000000000000000000070471461254215100174520ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "acb_mat.h" static void _apply_permutation(acb_mat_t A, slong * P, slong n) { acb_ptr * Atmp; slong i; Atmp = flint_malloc(sizeof(acb_ptr) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i]]; for (i = 0; i < n; i++) A->rows[i] = Atmp[i]; flint_free(Atmp); } /* Enclosure of det(I + eps) using Gershgorin circles. Can be improved. */ void acb_mat_det_one_gershgorin(acb_t det, const acb_mat_t A) { slong n, i, j; acb_t t; mag_t r, e, f; n = acb_mat_nrows(A); acb_init(t); mag_init(r); mag_init(e); mag_init(f); for (i = 0; i < n; i++) { mag_zero(e); for (j = 0; j < n; j++) { if (i == j) { acb_sub_ui(t, acb_mat_entry(A, i, j), 1, MAG_BITS); acb_get_mag(f, t); } else { acb_get_mag(f, acb_mat_entry(A, i, j)); } mag_add(e, e, f); } mag_max(r, r, e); } /* (1 + eps)^n - 1 <= expm1(n*eps) */ mag_mul_ui(r, r, n); mag_expm1(r, r); acb_one(det); mag_set(arb_radref(acb_realref(det)), r); mag_set(arb_radref(acb_imagref(det)), r); acb_clear(t); mag_clear(r); mag_clear(e); mag_clear(f); } void acb_mat_det_precond(acb_t det, const acb_mat_t A, slong prec) { acb_mat_t LU, Linv, Uinv; acb_t detU; slong n; slong *P; n = acb_mat_nrows(A); if (n == 0) { acb_one(det); return; } P = _perm_init(n); acb_mat_init(LU, n, n); if (!acb_mat_approx_lu(P, LU, A, prec)) { /* Fallback. */ acb_mat_det_lu(det, A, prec); } else { acb_mat_init(Linv, n, n); acb_mat_init(Uinv, n, n); acb_init(detU); acb_mat_one(Linv); acb_mat_approx_solve_tril(Linv, LU, Linv, 1, prec); acb_mat_one(Uinv); acb_mat_approx_solve_triu(Uinv, LU, Uinv, 0, prec); acb_mat_diag_prod(detU, Uinv, prec); acb_mat_mul(LU, A, Uinv, prec); _apply_permutation(LU, P, n); acb_mat_mul(Uinv, Linv, LU, prec); acb_mat_det_one_gershgorin(det, Uinv); if (acb_mat_is_real(A)) arb_zero(acb_imagref(det)); if (_perm_parity(P, n)) acb_neg(det, det); acb_div(det, det, detU, prec); if (acb_contains_zero(det)) { mag_t rad1, rad2; /* Run the interval LU algorithm. This can give a much better bound if the Gaussian elimination manages to work through several rows, and it is not that expensive. */ acb_mat_det_lu(detU, A, prec); mag_init(rad1); mag_init(rad2); mag_hypot(rad1, arb_radref(acb_realref(detU)), arb_radref(acb_imagref(detU))); mag_hypot(rad2, arb_radref(acb_realref(det)), arb_radref(acb_imagref(det))); if (mag_cmp(rad1, rad2) < 0) acb_set(det, detU); mag_clear(rad1); mag_clear(rad2); } acb_mat_clear(Linv); acb_mat_clear(Uinv); acb_clear(detU); } _perm_clear(P); acb_mat_clear(LU); } flint-3.1.3/src/acb_mat/dft.c000066400000000000000000000021671461254215100157370ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_dirichlet.h" void acb_mat_dft(acb_mat_t res, int kind, slong prec) { acb_dirichlet_roots_t roots; acb_t t; acb_t v; slong n, r, c, i, j; r = arb_mat_nrows(res); c = arb_mat_ncols(res); n = FLINT_MIN(r, c); if (n == 0) return; acb_dirichlet_roots_init(roots, n, (r - 1) * c, prec); acb_init(t); acb_init(v); acb_set_ui(v, n); acb_rsqrt(v, v, prec); for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { acb_dirichlet_root(t, roots, i * j, prec); acb_conj(t, t); acb_mul(acb_mat_entry(res, i, j), t, v, prec); } } acb_dirichlet_roots_clear(roots); acb_clear(t); acb_clear(v); } flint-3.1.3/src/acb_mat/diag_prod.c000066400000000000000000000025061461254215100171070ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void _acb_mat_diag_prod(acb_t res, const acb_mat_t A, slong a, slong b, slong prec) { if (b - a == 0) acb_one(res); else if (b - a == 1) acb_set_round(res, acb_mat_entry(A, a, a), prec); else if (b - a == 2) acb_mul(res, acb_mat_entry(A, a, a), acb_mat_entry(A, a + 1, a + 1), prec); else if (b - a == 3) { acb_mul(res, acb_mat_entry(A, a, a), acb_mat_entry(A, a + 1, a + 1), prec); acb_mul(res, res, acb_mat_entry(A, a + 2, a + 2), prec); } else { acb_t t; acb_init(t); _acb_mat_diag_prod(t, A, a, a + (b - a) / 2, prec); _acb_mat_diag_prod(res, A, a + (b - a) / 2, b, prec); acb_mul(res, res, t, prec); acb_clear(t); } } void acb_mat_diag_prod(acb_t res, const acb_mat_t A, slong prec) { slong m, n; m = acb_mat_nrows(A); n = acb_mat_nrows(A); _acb_mat_diag_prod(res, A, 0, FLINT_MIN(m, n), prec); } flint-3.1.3/src/acb_mat/eig_enclosure_rump.c000066400000000000000000000271311461254215100210460ustar00rootroot00000000000000/* Copyright 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" /* Follows section 13.4 of Siegfried M. Rump, "Verication methods: Rigorous results using floating-point arithmetic", Acta Numerica 19 (2010), pp. 287 - 449, implemented as verifyeig() in INTLAB. Cheat sheet for the formulas in Rump's paper. Assuming U = first n-k indices, V = last k indices. U U^T M = selects first n-k rows from M, zeroing rest V V^T M = selects last k rows from M, zeroing rest M U U^T = selects first n-k columns from M, zeroing rest M V V^T = selects last k columns from M, zeroing rest U^T M = selects first n-k rows from M, truncating matrix V^T M = selects last k rows from M, truncating matrix M U = selects first n-k columns from M, truncating matrix M V = selects last k columns from M, truncating matrix X V^T = extends X to n x n matrix (placing X on right) */ static void acb_approx_neg(acb_t res, const acb_t x) { arf_neg(arb_midref(acb_realref(res)), arb_midref(acb_realref(x))); arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(x))); } static void acb_approx_sub(acb_t res, const acb_t x, const acb_t y, slong prec) { arf_sub(arb_midref(acb_realref(res)), arb_midref(acb_realref(x)), arb_midref(acb_realref(y)), prec, ARF_RND_DOWN); arf_sub(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(x)), arb_midref(acb_imagref(y)), prec, ARF_RND_DOWN); } /* todo: separate out */ void acb_mat_bound_max_norm(mag_t res, const acb_mat_t A) { mag_t t; slong i, j; mag_init(t); mag_zero(res); for (i = 0; i < acb_mat_nrows(A); i++) { for (j = 0; j < acb_mat_ncols(A); j++) { acb_get_mag(t, acb_mat_entry(A, i, j)); mag_max(res, res, t); } } mag_clear(t); } static void arb_mat_nonnegative_eig_bound(mag_t eps, const arb_mat_t M, slong prec) { /* Cheap, but poor for defective eigenvalues */ arb_mat_bound_frobenius_norm(eps, M); /* Use Perron root bound. TODO: do something direct for k = 2. */ if (1) { acb_mat_t A, R, E; arb_mat_t V, MV; mag_t tm, um, vbound; slong i, j, k; k = arb_mat_nrows(M); acb_mat_init(A, k, k); acb_mat_init(R, k, k); acb_mat_init(E, 1, k); arb_mat_init(V, k, k); arb_mat_init(MV, k, k); mag_init(tm); mag_init(um); mag_init(vbound); acb_mat_set_arb_mat(A, M); /* TODO: could probably lower precision if precision is very high? */ acb_mat_approx_eig_qr(acb_mat_entry(E, 0, 0), NULL, R, A, NULL, 0, prec); for (i = 0; i < k; i++) { for (j = 0; j < k; j++) { acb_get_mag(tm, acb_mat_entry(R, i, j)); arf_set_mag(arb_midref(arb_mat_entry(V, i, j)), tm); } } arb_mat_mul(MV, M, V, MAG_BITS); for (j = 0; j < k; j++) { mag_zero(vbound); for (i = 0; i < k; i++) { arb_get_mag(tm, arb_mat_entry(MV, i, j)); arb_get_mag_lower(um, arb_mat_entry(V, i, j)); mag_div(tm, tm, um); mag_max(vbound, vbound, tm); } mag_min(eps, eps, vbound); } acb_mat_clear(A); acb_mat_clear(R); acb_mat_clear(E); arb_mat_clear(V); arb_mat_clear(MV); mag_clear(tm); mag_clear(um); mag_clear(vbound); } } static void acb_approx_mag(mag_t res, const acb_t x) { mag_t t; mag_init(t); arf_get_mag(res, arb_midref(acb_realref(x))); arf_get_mag(t, arb_midref(acb_imagref(x))); mag_hypot(res, res, t); mag_clear(t); } /* Extract k largest rows to freeze */ static void partition_X_sorted(slong * u, slong * v, const acb_mat_t X, slong prec) { slong i, j, n, k, c; slong * row_idx; mag_ptr row_mag; mag_t t; n = acb_mat_nrows(X); k = acb_mat_ncols(X); row_mag = _mag_vec_init(n); row_idx = flint_malloc(sizeof(slong) * n); mag_init(t); for (i = 0; i < n; i++) { row_idx[i] = i; for (j = 0; j < k; j++) { acb_approx_mag(t, acb_mat_entry(X, i, j)); mag_add(row_mag + i, row_mag + i, t); } } /* Bubble sort... */ for (i = 0; i < n - 1; i++) { for (j = 0; j < n - i - 1; j++) { if (mag_cmp(row_mag + j, row_mag + j + 1) > 0) { mag_swap(row_mag + j, row_mag + j + 1); c = row_idx[j]; row_idx[j] = row_idx[j + 1]; row_idx[j + 1] = c; } } } /* Not frozen rows of the approximation. */ for (i = 0; i < n - k; i++) u[i] = row_idx[i]; /* Frozen rows of the approximation. */ for (i = 0; i < k; i++) v[i] = row_idx[n - k + i]; _mag_vec_clear(row_mag, n); flint_free(row_idx); mag_clear(t); } static void partition_X_trivial(slong * u, slong * v, const acb_mat_t X, slong prec) { slong n, k, i; n = acb_mat_nrows(X); k = acb_mat_ncols(X); /* Not frozen rows of the approximation. */ for (i = 0; i < n - k; i++) u[i] = i; /* Frozen rows of the approximation. */ for (i = 0; i < k; i++) v[i] = n - k + i; } void acb_mat_eig_enclosure_rump(acb_t lambda, acb_mat_t J, acb_mat_t X, const acb_mat_t A, const acb_t lambda_approx, const acb_mat_t X_approx, slong prec) { slong n, k, i, j, iter, maxiter; slong *u, *v; acb_mat_t R, I, T, Y, Y0, UY, VY, Yeps; mag_t eps; n = acb_mat_nrows(A); k = acb_mat_ncols(X_approx); if (k < 1 || k > n || n != acb_mat_nrows(X_approx) || n != acb_mat_ncols(A)) { flint_throw(FLINT_ERROR, "bad matrix dimensions in acb_mat_eig_enclosure_rump\n"); } /* Not frozen rows of the approximation. */ u = flint_malloc(sizeof(slong) * (n - k)); /* Frozen rows of the approximation. */ v = flint_malloc(sizeof(slong) * k); if (k == 1) partition_X_sorted(u, v, X_approx, prec); else partition_X_trivial(u, v, X_approx, prec); mag_init(eps); acb_mat_init(R, n, n); acb_mat_init(UY, n, k); acb_mat_init(VY, k, k); acb_mat_init(T, n, n); acb_mat_init(Y, n, k); acb_mat_init(Y0, n, k); acb_mat_init(Yeps, n, k); /* Preconditioner: R ~= ((A - lambda_approx I) U U^T - X_approx V^T)^(-1) */ acb_mat_get_mid(R, A); for (i = 0; i < n; i++) acb_approx_sub(acb_mat_entry(R, i, i), acb_mat_entry(R, i, i), lambda_approx, prec); for (i = 0; i < n; i++) for (j = 0; j < k; j++) acb_approx_neg(acb_mat_entry(R, i, v[j]), acb_mat_entry(X_approx, i, j)); acb_mat_init(I, n, n); acb_mat_one(I); acb_mat_approx_solve(R, R, I, prec); acb_mat_clear(I); /* T = I - R * ((A - lambda_approx I) U U^T - X_approx V^T) */ /* Y = Y_0 = -R * ((A - lambda_approx I) X_approx) */ acb_mat_set(T, A); for (i = 0; i < n; i++) acb_sub(acb_mat_entry(T, i, i), acb_mat_entry(T, i, i), lambda_approx, prec); acb_mat_mul(Y0, T, X_approx, prec); acb_mat_mul(Y0, R, Y0, prec); acb_mat_neg(Y0, Y0); acb_mat_set(Y, Y0); for (i = 0; i < n; i++) for (j = 0; j < k; j++) acb_neg(acb_mat_entry(T, i, v[j]), acb_mat_entry(X_approx, i, j)); acb_mat_mul(T, R, T, prec); acb_mat_neg(T, T); for (i = 0; i < n; i++) acb_add_ui(acb_mat_entry(T, i, i), acb_mat_entry(T, i, i), 1, prec); /* Iteration with epsilon-inflation */ /* Y represents the error with respect to lambda_approx and X_approx */ /* TODO: what number of iterations is actually reasonable? */ /* TODO: what size of epsilon is actually reasonable? */ maxiter = 5 + FLINT_BIT_COUNT(prec); for (iter = 0; iter < maxiter; iter++) { /* Inflate Y. TODO: make it elementwise? */ acb_mat_bound_max_norm(eps, Y); if (mag_is_zero(eps)) mag_set_ui_2exp_si(eps, 1, -20 * prec); mag_mul_2exp_si(eps, eps, -3 + 2 * iter); /* if (iter > 3) mag_mul_2exp_si(eps, eps, (prec / 2) * (iter - 3) / (maxiter - 3)); */ acb_mat_add_error_mag(Y, eps); acb_mat_set(Yeps, Y); /* Y = Y0 + T Y + R ((U U^T Y) V^T Y) */ acb_mat_zero(UY); acb_mat_zero(VY); /* U U^T Y -- zero the rows at indices v. */ acb_mat_set(UY, Y); for (i = 0; i < k; i++) for (j = 0; j < k; j++) acb_zero(acb_mat_entry(UY, v[i], j)); /* V^T Y -- extract rows at indices v */ for (i = 0; i < k; i++) for (j = 0; j < k; j++) acb_set(acb_mat_entry(VY, i, j), acb_mat_entry(Y, v[i], j)); acb_mat_mul(UY, UY, VY, prec); acb_mat_mul(UY, R, UY, prec); acb_mat_mul(Y, T, Y, prec); acb_mat_add(Y, Y, UY, prec); acb_mat_add(Y, Y, Y0, prec); if (acb_mat_contains(Yeps, Y)) { acb_get_mid(lambda, lambda_approx); if (J != NULL) { /* J = lambda_approx I_k + V^T Y */ for (i = 0; i < k; i++) for (j = 0; j < k; j++) acb_set(acb_mat_entry(J, i, j), acb_mat_entry(Y, v[i], j)); for (i = 0; i < k; i++) acb_add(acb_mat_entry(J, i, i), acb_mat_entry(J, i, i), lambda, prec); } /* The correction for the frozen rows corresponds to the eigenvalue. */ if (k == 1) { /* Just one eigenvalue. */ acb_get_mag(eps, acb_mat_entry(Y, v[0], 0)); } else { /* Inclusion of eigenvalues of lambda_approx I_k + V^T Y. */ arb_mat_t M; arb_mat_init(M, k, k); /* Extract rows of Y corresponding to the eigenvalue correction. */ for (i = 0; i < k; i++) { for (j = 0; j < k; j++) { acb_get_mag(eps, acb_mat_entry(Y, v[i], j)); arf_set_mag(arb_midref(arb_mat_entry(M, i, j)), eps); } } arb_mat_nonnegative_eig_bound(eps, M, prec); arb_mat_clear(M); } /* Error bound for eigenvalues. */ acb_add_error_mag(lambda, eps); acb_mat_get_mid(X, X_approx); /* Error bounds for eigenvectors. */ /* Update the not frozen rows of the eigenvectors. */ for (i = 0; i < n - k; i++) { for (j = 0; j < k; j++) acb_add(acb_mat_entry(X, u[i], j), acb_mat_entry(X, u[i], j), acb_mat_entry(Y, u[i], j), prec); } goto cleanup; } } /* We failed to find an enclosure. */ acb_indeterminate(lambda); acb_mat_indeterminate(X); if (J != NULL) acb_mat_indeterminate(J); cleanup: acb_mat_clear(R); acb_mat_clear(T); acb_mat_clear(Y); acb_mat_clear(Y0); acb_mat_clear(Yeps); acb_mat_clear(UY); acb_mat_clear(VY); mag_clear(eps); flint_free(u); flint_free(v); } flint-3.1.3/src/acb_mat/eig_global_enclosure.c000066400000000000000000000030541461254215100213210ustar00rootroot00000000000000/* Copyright 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_eig_global_enclosure(mag_t eps, const acb_mat_t A, acb_srcptr E, const acb_mat_t R, slong prec) { acb_mat_t Y, R1, R2; slong i, j, n; mag_t r1, r2; n = acb_mat_nrows(A); acb_mat_init(Y, n, n); acb_mat_init(R1, n, n); acb_mat_init(R2, n, n); mag_init(r1); mag_init(r2); /* Y ~= inv(R) */ acb_mat_one(R1); acb_mat_approx_solve(Y, R, R1, prec); /* R2 = Y*R - I */ acb_mat_mul(R2, Y, R, prec); for (i = 0; i < n; i++) acb_sub_ui(acb_mat_entry(R2, i, i), acb_mat_entry(R2, i, i), 1, prec); acb_mat_bound_inf_norm(r2, R2); if (mag_cmp_2exp_si(r2, 0) < 0) { /* R1 = Y*(AR - RD) */ acb_mat_mul(R2, A, R, prec); for (i = 0; i < n; i++) for (j = 0; j < n; j++) acb_submul(acb_mat_entry(R2, i, j), acb_mat_entry(R, i, j), E + j, prec); acb_mat_mul(R1, Y, R2, prec); acb_mat_bound_inf_norm(r1, R1); mag_geom_series(r2, r2, 0); mag_mul(eps, r1, r2); } else { mag_inf(eps); } acb_mat_clear(R1); acb_mat_clear(R2); acb_mat_clear(Y); mag_clear(r1); mag_clear(r2); } flint-3.1.3/src/acb_mat/eig_multiple.c000066400000000000000000000015711461254215100176370ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_eig_multiple(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) { slong n; acb_ptr F; int success; n = arb_mat_nrows(A); F = _acb_vec_init(n); success = acb_mat_eig_simple_vdhoeven_mourrain(F, NULL, NULL, A, E_approx, R_approx, prec); if (!success) success = acb_mat_eig_multiple_rump(F, A, E_approx, R_approx, prec); _acb_vec_set(E, F, n); _acb_vec_clear(F, n); return success; } flint-3.1.3/src/acb_mat/eig_multiple_rump.c000066400000000000000000000104421461254215100206770ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" static void acb_approx_mag(mag_t res, const acb_t x) { mag_t t; mag_init(t); arf_get_mag(res, arb_midref(acb_realref(x))); arf_get_mag(t, arb_midref(acb_imagref(x))); mag_hypot(res, res, t); mag_clear(t); } static int close(const acb_t x, const acb_t y, const mag_t eps) { arf_t t; mag_t a, b; int result; mag_init(a); mag_init(b); arf_init(t); arf_sub(t, arb_midref(acb_realref(x)), arb_midref(acb_realref(y)), MAG_BITS, ARF_RND_UP); arf_get_mag(a, t); arf_sub(t, arb_midref(acb_imagref(x)), arb_midref(acb_imagref(y)), MAG_BITS, ARF_RND_UP); arf_get_mag(b, t); mag_hypot(a, a, b); result = (mag_cmp(a, eps) <= 0); mag_clear(a); mag_clear(b); arf_clear(t); return result; } int acb_mat_eig_multiple_rump(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) { slong c, i, j, k, n; acb_mat_t X; acb_ptr F; int result; slong iter; mag_t escale, eps, tm, um; slong ** cluster; slong * cluster_size; slong num_clusters; n = acb_mat_nrows(A); if (n == 0) return 1; cluster = flint_malloc(sizeof(slong *) * n); for (i = 0; i < n; i++) cluster[i] = flint_malloc(sizeof(slong) * n); cluster_size = flint_malloc(sizeof(slong) * n); mag_init(eps); mag_init(escale); mag_init(tm); mag_init(um); mag_zero(escale); for (i = 0; i < n; i++) { acb_approx_mag(tm, E_approx + i); mag_max(escale, escale, tm); } /* todo: when num_clusters = 1, could use fallback global enclosure */ /* todo: initial clustering could be allowed to be zero */ /* M 2^(-0.75p), M 2^(-0.5p), M 2^(-0.25p), ... */ for (iter = 0; iter < 2; iter++) { mag_mul_2exp_si(eps, escale, -prec + (iter + 1) * prec/4); /* Group the eigenvalue approximations. */ num_clusters = 0; for (i = 0; i < n; i++) { int new_cluster = 1; for (j = 0; j < num_clusters && new_cluster; j++) { if (close(E_approx + i, E_approx + cluster[j][0], eps)) { cluster[j][cluster_size[j]] = i; cluster_size[j]++; new_cluster = 0; } } if (new_cluster) { cluster[num_clusters][0] = i; cluster_size[num_clusters] = 1; num_clusters++; } } result = 1; F = _acb_vec_init(num_clusters); for (c = 0; c < num_clusters && result; c++) { k = cluster_size[c]; acb_mat_init(X, n, k); for (i = 0; i < n; i++) for (j = 0; j < k; j++) acb_set(acb_mat_entry(X, i, j), acb_mat_entry(R_approx, i, cluster[c][j])); acb_mat_eig_enclosure_rump(F + c, NULL, X, A, E_approx + cluster[c][0], X, prec); if (!acb_is_finite(F + c)) result = 0; acb_mat_clear(X); } for (i = 0; i < num_clusters; i++) { for (j = i + 1; j < num_clusters; j++) { if (acb_overlaps(F + i, F + j)) result = 0; } } if (result) { i = 0; for (c = 0; c < num_clusters; c++) { for (j = 0; j < cluster_size[c]; j++) { acb_set(E + i, F + c); i++; } } } _acb_vec_clear(F, num_clusters); if (result) break; } if (!result) _acb_vec_indeterminate(E, n); for (i = 0; i < n; i++) flint_free(cluster[i]); flint_free(cluster); flint_free(cluster_size); mag_clear(eps); mag_clear(escale); mag_clear(tm); mag_clear(um); return result; } flint-3.1.3/src/acb_mat/eig_simple.c000066400000000000000000000011761461254215100172760ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_eig_simple(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) { return acb_mat_eig_simple_vdhoeven_mourrain(E, L, R, A, E_approx, R_approx, prec); } flint-3.1.3/src/acb_mat/eig_simple_rump.c000066400000000000000000000035151461254215100203400ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_eig_simple_rump(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) { slong i, j, n; acb_mat_t X, R2; int result; n = acb_mat_nrows(A); if (n == 0) return 1; if (n == 1) { acb_set_round(E, acb_mat_entry(A, 0, 0), prec); if (L != NULL) acb_one(acb_mat_entry(L, 0, 0)); if (R != NULL) acb_one(acb_mat_entry(R, 0, 0)); return 1; } acb_mat_init(X, n, 1); acb_mat_init(R2, n, n); result = 1; for (i = 0; i < n && result; i++) { for (j = 0; j < n; j++) acb_set(acb_mat_entry(X, j, 0), acb_mat_entry(R_approx, j, i)); acb_mat_eig_enclosure_rump(E + i, NULL, X, A, E_approx + i, X, prec); if (!acb_is_finite(E + i)) result = 0; for (j = 0; j < i; j++) if (acb_overlaps(E + i, E + j)) result = 0; for (j = 0; j < n; j++) acb_set(acb_mat_entry(R2, j, i), acb_mat_entry(X, j, 0)); } if (R != NULL) { if (result) acb_mat_set(R, R2); else acb_mat_indeterminate(R); } if (L != NULL) { if (!result || !acb_mat_inv(L, R2, prec)) acb_mat_indeterminate(L); } if (!result) _acb_vec_indeterminate(E, n); acb_mat_clear(X); acb_mat_clear(R2); return result; } flint-3.1.3/src/acb_mat/eig_simple_vdhoeven_mourrain.c000066400000000000000000000135041461254215100231060ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" /* todo: move out */ void acb_mat_inf_norm(arb_t res, const acb_mat_t A, slong prec) { slong i, j, m, n; arb_t s, t; m = acb_mat_nrows(A); n = acb_mat_nrows(A); if (m == 0 || n == 0) { arb_zero(res); return; } arb_init(s); arb_init(t); arb_zero(res); for (i = 0; i < m; i++) { acb_abs(s, acb_mat_entry(A, i, 0), prec); for (j = 1; j < n; j++) { acb_abs(t, acb_mat_entry(A, i, j), prec); arb_add(s, s, t, prec); } arb_max(res, res, s, prec); } arb_clear(s); arb_clear(t); } static void diagonal_certify(arb_t epsilon, arb_t eta1, arb_t eta2, const acb_mat_t D, const acb_mat_t H, slong prec) { arb_t mu, sigma, alpha, t, u, v; acb_t d; slong i, j, n; arb_init(mu); arb_init(sigma); arb_init(alpha); arb_init(t); arb_init(u); arb_init(v); acb_init(d); n = acb_mat_nrows(D); /* D = diagonal matrix; H = off diagonal matrix */ /* mu = ||D|| */ acb_mat_inf_norm(mu, D, prec); /* sigma = sigma(D) = separation number */ arb_pos_inf(sigma); for (i = 0; i < n; i++) { for (j = i + 1; j < n; j++) { acb_sub(d, acb_mat_entry(D, i, i), acb_mat_entry(D, j, j), prec); acb_abs(t, d, prec); arb_min(sigma, sigma, t, prec); } } /* eta1 = ||Delta(H)|| Delta = diagonal projection */ arb_zero(eta1); /* eta2 = ||Omega(H)|| Omega = off-diagonal projection */ acb_mat_inf_norm(eta2, H, prec); /* alpha = min(sigma / (6 mu), 1/4) */ arb_div(t, sigma, mu, prec); arb_div_ui(t, t, 6, prec); arb_set_d(u, 0.25); arb_min(alpha, t, u, prec); arb_add(t, eta1, eta2, prec); arb_mul(u, alpha, mu, prec); arb_mul_2exp_si(u, u, -3); arb_mul(v, alpha, sigma, prec); arb_mul_2exp_si(v, v, -3); if (arb_le(t, u) && arb_le(eta2, v)) { arb_div(epsilon, eta2, sigma, prec); arb_mul_ui(epsilon, epsilon, 3, prec); } else { arb_indeterminate(epsilon); } arb_clear(mu); arb_clear(sigma); arb_clear(alpha); arb_clear(t); arb_clear(u); arb_clear(v); acb_clear(d); } int acb_mat_eig_simple_vdhoeven_mourrain(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec) { acb_mat_t D, T, AT; int result; slong i, j, n; result = 0; n = acb_mat_nrows(A); if (n == 0) return 1; if (n == 1) { acb_set_round(E, acb_mat_entry(A, 0, 0), prec); if (L != NULL) acb_one(acb_mat_entry(L, 0, 0)); if (R != NULL) acb_one(acb_mat_entry(R, 0, 0)); return 1; } acb_mat_init(D, n, n); acb_mat_init(T, n, n); acb_mat_init(AT, n, n); /* T D = A T */ acb_mat_get_mid(T, R_approx); acb_mat_mul(AT, A, T, prec); if (acb_mat_solve(D, T, AT, prec)) { acb_mat_t DD, DH; arb_t epsilon, eta1, eta2; arb_init(epsilon); arb_init(eta1); arb_init(eta2); acb_mat_init(DD, n, n); acb_mat_init(DH, n, n); for (i = 0; i < n; i++) acb_set(acb_mat_entry(DD, i, i), acb_mat_entry(D, i, i)); for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (i != j) acb_set(acb_mat_entry(DH, i, j), acb_mat_entry(D, i, j)); diagonal_certify(epsilon, eta1, eta2, DD, DH, 2 * MAG_BITS); if (arb_is_finite(epsilon)) { for (i = 0; i < n; i++) { /* note: paper actually uses D_c which would be better? */ acb_set(E + i, acb_mat_entry(D, i, i)); arb_add_error(acb_realref(E + i), eta2); arb_add_error(acb_imagref(E + i), eta2); } result = 1; /* unlikely */ for (i = 0; i < n; i++) for (j = i + 1; j < n; j++) if (acb_overlaps(E + i, E + j)) result = 0; if (result && (R != NULL || L != NULL)) { mag_t ep, em; mag_init(ep); mag_init(em); arb_get_mag(ep, epsilon); acb_mat_zero(D); acb_mat_add_error_mag(D, ep); acb_mat_mul(D, T, D, MAG_BITS); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { acb_get_mag(ep, acb_mat_entry(D, i, j)); acb_add_error_mag(acb_mat_entry(T, i, j), ep); } } if (R != NULL) acb_mat_set(R, T); if (L != NULL) { if (!acb_mat_inv(L, T, prec)) acb_mat_indeterminate(L); } mag_clear(ep); mag_clear(em); } } acb_mat_clear(DD); acb_mat_clear(DH); arb_clear(epsilon); arb_clear(eta1); arb_clear(eta2); } if (!result) { for (i = 0; i < n; i++) acb_indeterminate(E + i); if (L != NULL) acb_mat_indeterminate(L); if (R != NULL) acb_mat_indeterminate(R); } acb_mat_clear(D); acb_mat_clear(T); acb_mat_clear(AT); return result; } flint-3.1.3/src/acb_mat/eq.c000066400000000000000000000015121461254215100155600ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_eq(const acb_mat_t mat1, const acb_mat_t mat2) { slong i, j; if ((acb_mat_nrows(mat1) != acb_mat_nrows(mat2)) || (acb_mat_ncols(mat1) != acb_mat_ncols(mat2))) return 0; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) if (!acb_eq(acb_mat_entry(mat1, i, j), acb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/equal.c000066400000000000000000000015241461254215100162650ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_equal(const acb_mat_t mat1, const acb_mat_t mat2) { slong i, j; if ((acb_mat_nrows(mat1) != acb_mat_nrows(mat2)) || (acb_mat_ncols(mat1) != acb_mat_ncols(mat2))) return 0; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) if (!acb_equal(acb_mat_entry(mat1, i, j), acb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/exp.c000066400000000000000000000115431461254215100157540ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz_mat.h" #include "acb_mat.h" #include "bool_mat.h" slong _arb_mat_exp_choose_N(const mag_t norm, slong prec); static slong _acb_mat_count_is_zero(const acb_mat_t A) { slong nz, i, j; for (nz = 0, i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) nz += acb_is_zero(acb_mat_entry(A, i, j)); return nz; } static void _acb_mat_exp_diagonal(acb_mat_t B, const acb_mat_t A, slong prec) { slong n, i; n = acb_mat_nrows(A); if (B != A) { acb_mat_zero(B); } for (i = 0; i < n; i++) { acb_exp(acb_mat_entry(B, i, i), acb_mat_entry(A, i, i), prec); } } void acb_mat_exp(acb_mat_t B, const acb_mat_t A, slong prec) { slong i, j, dim, nz; bool_mat_t S; slong nildegree; if (!acb_mat_is_square(A)) { flint_throw(FLINT_ERROR, "acb_mat_exp: a square matrix is required!\n"); } if (acb_mat_is_empty(A)) return; dim = acb_mat_nrows(A); if (dim == 1) { acb_exp(acb_mat_entry(B, 0, 0), acb_mat_entry(A, 0, 0), prec); return; } if (acb_mat_is_real(A)) { arb_mat_t R; arb_mat_init(R, dim, dim); for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) arb_set(arb_mat_entry(R, i, j), acb_realref(acb_mat_entry(A, i, j))); arb_mat_exp(R, R, prec); acb_mat_set_arb_mat(B, R); arb_mat_clear(R); return; } nz = _acb_mat_count_is_zero(A); if (nz == dim * dim) { acb_mat_one(B); return; } bool_mat_init(S, dim, dim); if (nz == 0) { nildegree = -1; bool_mat_complement(S, S); } else { for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) bool_mat_set_entry(S, i, j, !acb_is_zero(acb_mat_entry(A, i, j))); if (bool_mat_is_diagonal(S)) { _acb_mat_exp_diagonal(B, A, prec); bool_mat_clear(S); return; } else { nildegree = bool_mat_nilpotency_degree(S); } } /* evaluate using scaling and squaring of truncated taylor series */ { slong wp, N, q, r; mag_t norm, err; acb_mat_t T; wp = prec + 3 * FLINT_BIT_COUNT(prec); mag_init(norm); mag_init(err); acb_mat_init(T, dim, dim); acb_mat_bound_inf_norm(norm, A); q = pow(wp, 0.25); /* wanted magnitude */ if (mag_cmp_2exp_si(norm, 2 * wp) > 0) /* too big */ r = 2 * wp; else if (mag_cmp_2exp_si(norm, -q) < 0) /* tiny, no need to reduce */ r = 0; else r = FLINT_MAX(0, q + MAG_EXP(norm)); /* reduce to magnitude 2^(-r) */ acb_mat_scalar_mul_2exp_si(T, A, -r); mag_mul_2exp_si(norm, norm, -r); N = _arb_mat_exp_choose_N(norm, wp); /* if positive, nildegree is an upper bound on nilpotency degree */ if (nildegree > 0) N = FLINT_MIN(N, nildegree); mag_exp_tail(err, norm, N); acb_mat_exp_taylor_sum(B, T, N, wp); /* add truncation error to entries for which it is not ruled out */ if (nz == 0) { for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) acb_add_error_mag(acb_mat_entry(B, i, j), err); } else if (nildegree < 0 || N < nildegree) { slong w; fmpz_mat_t W; fmpz_mat_init(W, dim, dim); w = bool_mat_all_pairs_longest_walk(W, S); if (w + 1 != nildegree) flint_throw(FLINT_ERROR, "(%s)\n", __func__); for (i = 0; i < dim; i++) { for (j = 0; j < dim; j++) { slong d = fmpz_get_si(fmpz_mat_entry(W, i, j)) + 1; if (d < 0 || N < d) { acb_add_error_mag(acb_mat_entry(B, i, j), err); } } } fmpz_mat_clear(W); } for (i = 0; i < r; i++) { acb_mat_sqr(T, B, wp); acb_mat_swap(T, B); } for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) acb_set_round(acb_mat_entry(B, i, j), acb_mat_entry(B, i, j), prec); mag_clear(norm); mag_clear(err); acb_mat_clear(T); } bool_mat_clear(S); } flint-3.1.3/src/acb_mat/exp_taylor_sum.c000066400000000000000000000054101461254215100202260ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb_mat.h" void acb_mat_exp_taylor_sum(acb_mat_t S, const acb_mat_t A, slong N, slong prec) { if (A == S) { acb_mat_t t; acb_mat_init(t, acb_mat_nrows(A), acb_mat_nrows(A)); acb_mat_set(t, A); acb_mat_exp_taylor_sum(S, t, N, prec); acb_mat_clear(t); } else if (N <= 0) { acb_mat_zero(S); } else if (N == 1) { acb_mat_one(S); } else if (N == 2) { acb_mat_one(S); acb_mat_add(S, S, A, prec); } else if (N == 3) { acb_mat_t T; acb_mat_init(T, acb_mat_nrows(A), acb_mat_nrows(A)); acb_mat_sqr(T, A, prec); acb_mat_scalar_mul_2exp_si(T, T, -1); acb_mat_add(S, A, T, prec); acb_mat_one(T); acb_mat_add(S, S, T, prec); acb_mat_clear(T); } else { slong i, lo, hi, m, w, dim; acb_mat_struct * pows; acb_mat_t T, U; fmpz_t c, f; dim = acb_mat_nrows(A); m = n_sqrt(N); w = (N + m - 1) / m; fmpz_init(c); fmpz_init(f); pows = flint_malloc(sizeof(acb_mat_t) * (m + 1)); acb_mat_init(T, dim, dim); acb_mat_init(U, dim, dim); for (i = 0; i <= m; i++) { acb_mat_init(pows + i, dim, dim); if (i == 0) acb_mat_one(pows + i); else if (i == 1) acb_mat_set(pows + i, A); else acb_mat_mul(pows + i, pows + i - 1, A, prec); } acb_mat_zero(S); fmpz_one(f); for (i = w - 1; i >= 0; i--) { lo = i * m; hi = FLINT_MIN(N - 1, lo + m - 1); acb_mat_zero(T); fmpz_one(c); while (hi >= lo) { acb_mat_scalar_addmul_fmpz(T, pows + hi - lo, c, prec); if (hi != 0) fmpz_mul_ui(c, c, hi); hi--; } acb_mat_mul(U, pows + m, S, prec); acb_mat_scalar_mul_fmpz(S, T, f, prec); acb_mat_add(S, S, U, prec); fmpz_mul(f, f, c); } acb_mat_scalar_div_fmpz(S, S, f, prec); fmpz_clear(c); fmpz_clear(f); for (i = 0; i <= m; i++) acb_mat_clear(pows + i); flint_free(pows); acb_mat_clear(T); acb_mat_clear(U); } } flint-3.1.3/src/acb_mat/find_pivot_partial.c000066400000000000000000000027521461254215100210370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_cmpabs_approx(const acb_t x, const acb_t y) { const arf_struct *xm, *ym; if (arf_cmpabs(arb_midref(acb_realref(x)), arb_midref(acb_imagref(x))) >= 0) xm = arb_midref(acb_realref(x)); else xm = arb_midref(acb_imagref(x)); if (arf_cmpabs(arb_midref(acb_realref(y)), arb_midref(acb_imagref(y))) >= 0) ym = arb_midref(acb_realref(y)); else ym = arb_midref(acb_imagref(y)); return arf_cmpabs(xm, ym); } slong acb_mat_find_pivot_partial(const acb_mat_t mat, slong start_row, slong end_row, slong c) { slong best_row, i; best_row = -1; for (i = start_row; i < end_row; i++) { if (!acb_contains_zero(acb_mat_entry(mat, i, c))) { if (best_row == -1) { best_row = i; } /* todo: should take the radius into account */ else if (acb_cmpabs_approx(acb_mat_entry(mat, i, c), acb_mat_entry(mat, best_row, c)) > 0) { best_row = i; } } } return best_row; } flint-3.1.3/src/acb_mat/frobenius_norm.c000066400000000000000000000016331461254215100202060ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_frobenius_norm(arb_t res, const acb_mat_t A, slong prec) { slong i, j, r, c; r = acb_mat_nrows(A); c = acb_mat_ncols(A); arb_zero(res); if (r == 0 || c == 0) return; for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { acb_srcptr z = acb_mat_entry(A, i, j); arb_addmul(res, acb_realref(z), acb_realref(z), prec); arb_addmul(res, acb_imagref(z), acb_imagref(z), prec); } } arb_sqrtpos(res, res, prec); } flint-3.1.3/src/acb_mat/get_imag.c000066400000000000000000000012511461254215100167270ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_get_imag(arb_mat_t im, const acb_mat_t mat) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) { for (j = 0; j < acb_mat_ncols(mat); j++) { acb_get_imag(arb_mat_entry(im, i, j), acb_mat_entry(mat, i, j)); } } } flint-3.1.3/src/acb_mat/get_real.c000066400000000000000000000012511461254215100167350ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_get_real(arb_mat_t re, const acb_mat_t mat) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) { for (j = 0; j < acb_mat_ncols(mat); j++) { acb_get_real(arb_mat_entry(re, i, j), acb_mat_entry(mat, i, j)); } } } flint-3.1.3/src/acb_mat/indeterminate.c000066400000000000000000000011431461254215100200030ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_indeterminate(acb_mat_t A) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) acb_indeterminate(acb_mat_entry(A, i, j)); } flint-3.1.3/src/acb_mat/init.c000066400000000000000000000014151461254215100161200ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_init(acb_mat_t mat, slong r, slong c) { if (r != 0 && c != 0) { slong i; mat->entries = _acb_vec_init(r * c); mat->rows = (acb_ptr *) flint_malloc(r * sizeof(acb_ptr)); for (i = 0; i < r; i++) mat->rows[i] = mat->entries + i * c; } else mat->entries = NULL; mat->r = r; mat->c = c; } flint-3.1.3/src/acb_mat/inlines.c000066400000000000000000000006561461254215100166240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ACB_MAT_INLINES_C #include "acb_mat.h" flint-3.1.3/src/acb_mat/inv.c000066400000000000000000000013751461254215100157560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_inv(acb_mat_t X, const acb_mat_t A, slong prec) { if (X == A) { int r; acb_mat_t T; acb_mat_init(T, acb_mat_nrows(A), acb_mat_ncols(A)); r = acb_mat_inv(T, A, prec); acb_mat_swap(T, X); acb_mat_clear(T); return r; } acb_mat_one(X); return acb_mat_solve(X, A, X, prec); } flint-3.1.3/src/acb_mat/io.c000066400000000000000000000020701461254215100155620ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_mat.h" /* printing *******************************************************************/ void acb_mat_fprintd(FILE * file, const acb_mat_t mat, slong digits) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) { flint_fprintf(file, "["); for (j = 0; j < acb_mat_ncols(mat); j++) { acb_fprintd(file, acb_mat_entry(mat, i, j), digits); if (j < acb_mat_ncols(mat) - 1) flint_fprintf(file, ", "); } flint_fprintf(file, "]\n"); } } void acb_mat_printd(const acb_mat_t mat, slong digits) { acb_mat_fprintd(stdout, mat, digits); } flint-3.1.3/src/acb_mat/is_exact.c000066400000000000000000000013651461254215100167600ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_is_exact(const acb_mat_t A) { slong i, j; for (i = 0; i < acb_mat_nrows(A); i++) for (j = 0; j < acb_mat_ncols(A); j++) if (!mag_is_zero(arb_radref(acb_realref(acb_mat_entry(A, i, j)))) || !mag_is_zero(arb_radref(acb_imagref(acb_mat_entry(A, i, j))))) return 0; return 1; } flint-3.1.3/src/acb_mat/is_finite.c000066400000000000000000000012531461254215100171260ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_is_finite(const acb_mat_t A) { slong i, j, n, m; n = acb_mat_nrows(A); m = acb_mat_ncols(A); for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (!acb_is_finite(acb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/is_real.c000066400000000000000000000012221461254215100165670ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_is_real(const acb_mat_t mat) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) for (j = 0; j < acb_mat_ncols(mat); j++) if (!acb_is_real(acb_mat_entry(mat, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/is_tril.c000066400000000000000000000012531461254215100166220ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_is_tril(const acb_mat_t A) { slong i, j, n, m; n = acb_mat_nrows(A); m = acb_mat_ncols(A); for (i = 0; i < n; i++) for (j = i + 1; j < m; j++) if (!acb_is_zero(acb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/is_triu.c000066400000000000000000000012651461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_is_triu(const acb_mat_t A) { slong i, j, n, m; n = acb_mat_nrows(A); m = acb_mat_ncols(A); for (i = 1; i < n; i++) for (j = 0; j < FLINT_MIN(i, m); j++) if (!acb_is_zero(acb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/is_zero.c000066400000000000000000000012471461254215100166320ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_is_zero(const acb_mat_t A) { slong i, j, n, m; n = acb_mat_nrows(A); m = acb_mat_ncols(A); for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (!acb_is_zero(acb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/lu.c000066400000000000000000000012111461254215100155670ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_lu(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec) { if (acb_mat_nrows(A) < 8 || acb_mat_ncols(A) < 8) return acb_mat_lu_classical(P, LU, A, prec); else return acb_mat_lu_recursive(P, LU, A, prec); } flint-3.1.3/src/acb_mat/lu_classical.c000066400000000000000000000027541461254215100176220ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_lu_classical(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec) { acb_t d, e; acb_ptr * a; slong i, j, m, n, r, row, col; int result; if (acb_mat_is_empty(A)) return 1; m = acb_mat_nrows(A); n = acb_mat_ncols(A); acb_mat_set(LU, A); a = LU->rows; row = col = 0; for (i = 0; i < m; i++) P[i] = i; acb_init(d); acb_init(e); result = 1; while (row < m && col < n) { r = acb_mat_find_pivot_partial(LU, row, m, col); if (r == -1) { result = 0; break; } else if (r != row) acb_mat_swap_rows(LU, P, row, r); acb_set(d, a[row] + col); for (j = row + 1; j < m; j++) { acb_div(e, a[j] + col, d, prec); acb_neg(e, e); _acb_vec_scalar_addmul(a[j] + col, a[row] + col, n - col, e, prec); acb_zero(a[j] + col); acb_neg(a[j] + row, e); } row++; col++; } acb_clear(d); acb_clear(e); return result; } flint-3.1.3/src/acb_mat/lu_recursive.c000066400000000000000000000051411461254215100176640ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" static void _apply_permutation(slong * AP, acb_mat_t A, slong * P, slong n, slong offset) { if (n != 0) { acb_ptr * Atmp; slong * APtmp; slong i; Atmp = flint_malloc(sizeof(acb_ptr) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } int acb_mat_lu_recursive(slong * P, acb_mat_t LU, const acb_mat_t A, slong prec) { slong i, m, n, r1, r2, n1; acb_mat_t A0, A1, A00, A01, A10, A11; slong * P1; m = A->r; n = A->c; if (m <= 1 || n <= 1) { return acb_mat_lu_classical(P, LU, A, prec); } if (LU != A) acb_mat_set(LU, A); n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; P1 = flint_malloc(sizeof(slong) * m); acb_mat_window_init(A0, LU, 0, 0, m, n1); acb_mat_window_init(A1, LU, 0, n1, m, n); r1 = acb_mat_lu(P1, A0, A0, prec); if (!r1) { flint_free(P1); acb_mat_window_clear(A0); acb_mat_window_clear(A1); return 0; } /* r1 = rank of A0 */ r1 = FLINT_MIN(m, n1); _apply_permutation(P, LU, P1, m, 0); acb_mat_window_init(A00, LU, 0, 0, r1, r1); acb_mat_window_init(A10, LU, r1, 0, m, r1); acb_mat_window_init(A01, LU, 0, n1, r1, n); acb_mat_window_init(A11, LU, r1, n1, m, n); acb_mat_solve_tril(A01, A00, A01, 1, prec); { /* acb_mat_submul(A11, A11, A10, A01, prec); */ acb_mat_t T; acb_mat_init(T, A10->r, A01->c); acb_mat_mul(T, A10, A01, prec); acb_mat_sub(A11, A11, T, prec); acb_mat_clear(T); } r2 = acb_mat_lu(P1, A11, A11, prec); if (!r2) r1 = r2 = 0; else _apply_permutation(P, LU, P1, m - r1, r1); flint_free(P1); acb_mat_window_clear(A00); acb_mat_window_clear(A01); acb_mat_window_clear(A10); acb_mat_window_clear(A11); acb_mat_window_clear(A0); acb_mat_window_clear(A1); return r1 && r2; } flint-3.1.3/src/acb_mat/mul.c000066400000000000000000000040301461254215100157460ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" static slong acb_mat_bits(const acb_mat_t A) { slong b, t, i, ar, ac; ar = acb_mat_nrows(A); ac = acb_mat_ncols(A); b = 0; for (i = 0; i < ar; i++) { t = _arb_vec_bits((arb_srcptr) A->rows[i], 2 * ac); b = FLINT_MAX(b, t); } return b; } int acb_mat_is_lagom(const acb_mat_t A) { slong i, j, M, N; M = acb_mat_nrows(A); N = acb_mat_ncols(A); for (i = 0; i < M; i++) { for (j = 0; j < N; j++) { if (!ARB_IS_LAGOM(acb_realref(acb_mat_entry(A, i, j))) || !ARB_IS_LAGOM(acb_imagref(acb_mat_entry(A, i, j)))) return 0; } } return 1; } void acb_mat_mul(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { slong ar, ac, br, bc, n, abits, bbits, bits; ar = acb_mat_nrows(A); ac = acb_mat_ncols(A); br = acb_mat_nrows(B); bc = acb_mat_ncols(B); if (ac != br || ar != acb_mat_nrows(C) || bc != acb_mat_ncols(C)) { flint_throw(FLINT_ERROR, "acb_mat_mul: incompatible dimensions\n"); } n = FLINT_MIN(ar, ac); n = FLINT_MIN(ac, bc); if (n >= 20) { abits = acb_mat_bits(A); bbits = acb_mat_bits(B); bits = FLINT_MIN(prec, FLINT_MAX(abits, bbits)); if (bits < 8000 && n >= 5 + bits / 64) { acb_mat_mul_reorder(C, A, B, prec); return; } } if (flint_get_num_threads() > 1 && ((double) ar * (double) ac * (double) bc * (double) prec > 100000)) { acb_mat_mul_threaded(C, A, B, prec); } else { acb_mat_mul_classical(C, A, B, prec); } } flint-3.1.3/src/acb_mat/mul_classical.c000066400000000000000000000045261461254215100177760ustar00rootroot00000000000000/* Copyright (C) 2012, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_mul_classical(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { slong ar, ac, br, bc, i, j, k; if (A == B && (acb_mat_nrows(A) <= 2 || (prec >= 1024 && acb_mat_nrows(A) < 8))) { acb_mat_sqr_classical(C, A, prec); return; } ar = acb_mat_nrows(A); ac = acb_mat_ncols(A); br = acb_mat_nrows(B); bc = acb_mat_ncols(B); if (ac != br || ar != acb_mat_nrows(C) || bc != acb_mat_ncols(C)) { flint_throw(FLINT_ERROR, "acb_mat_mul: incompatible dimensions\n"); } if (br == 0) { acb_mat_zero(C); return; } if (A == C || B == C) { acb_mat_t T; acb_mat_init(T, ar, bc); acb_mat_mul_classical(T, A, B, prec); acb_mat_swap_entrywise(T, C); acb_mat_clear(T); return; } if (br <= 2) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { /* todo: efficient fmma code */ acb_mul(acb_mat_entry(C, i, j), acb_mat_entry(A, i, 0), acb_mat_entry(B, 0, j), prec); for (k = 1; k < br; k++) { acb_addmul(acb_mat_entry(C, i, j), acb_mat_entry(A, i, k), acb_mat_entry(B, k, j), prec); } } } } else { acb_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(sizeof(acb_struct) * br * bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) tmp[j * br + i] = *acb_mat_entry(B, i, j); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { acb_dot(acb_mat_entry(C, i, j), NULL, 0, A->rows[i], 1, tmp + j * br, 1, br, prec); } } TMP_END; } } flint-3.1.3/src/acb_mat/mul_entrywise.c000066400000000000000000000017041461254215100200640ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_mul_entrywise(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { slong i, j; if (acb_mat_nrows(A) != acb_mat_nrows(B) || acb_mat_ncols(A) != acb_mat_ncols(B)) { flint_throw(FLINT_ERROR, "acb_mat_mul_entrywise: incompatible dimensions\n"); } for (i = 0; i < acb_mat_nrows(A); i++) { for (j = 0; j < acb_mat_ncols(A); j++) { acb_mul(acb_mat_entry(C, i, j), acb_mat_entry(A, i, j), acb_mat_entry(B, i, j), prec); } } } flint-3.1.3/src/acb_mat/mul_reorder.c000066400000000000000000000172411461254215100175000ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" FLINT_STATIC_NOINLINE void copy_re_shallow(arb_mat_t X, const acb_mat_t A) { slong M, N, i, j; M = arb_mat_nrows(X); N = arb_mat_ncols(X); for (i = 0; i < M; i++) for (j = 0; j < N; j++) *arb_mat_entry(X, i, j) = *acb_realref(acb_mat_entry(A, i, j)); } FLINT_STATIC_NOINLINE void copy_im_shallow(arb_mat_t X, const acb_mat_t A) { slong M, N, i, j; M = arb_mat_nrows(X); N = arb_mat_ncols(X); for (i = 0; i < M; i++) for (j = 0; j < N; j++) *arb_mat_entry(X, i, j) = *acb_imagref(acb_mat_entry(A, i, j)); } FLINT_STATIC_NOINLINE void clear_shallow(arb_mat_t X) { slong M, N, i, j; M = arb_mat_nrows(X); N = arb_mat_ncols(X); for (i = 0; i < M; i++) for (j = 0; j < N; j++) arb_init(arb_mat_entry(X, i, j)); } /* todo: squaring optimizations */ void acb_mat_mul_reorder(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { arb_mat_t X, Y, Z, W; slong M, N, P; slong i, j; M = acb_mat_nrows(A); N = acb_mat_ncols(A); P = acb_mat_ncols(B); if (acb_mat_is_real(A)) { if (acb_mat_is_real(B)) { arb_mat_init(X, M, N); arb_mat_init(Y, N, P); arb_mat_init(Z, M, P); copy_re_shallow(X, A); copy_re_shallow(Y, B); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_zero(acb_imagref(acb_mat_entry(C, i, j))); if (A == C || B == C) { arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_swap(acb_realref(acb_mat_entry(C, i, j)), acb_mat_entry(Z, i, j)); } else { copy_re_shallow(Z, C); arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) *acb_realref(acb_mat_entry(C, i, j)) = *arb_mat_entry(Z, i, j); clear_shallow(Z); } clear_shallow(X); clear_shallow(Y); arb_mat_clear(X); arb_mat_clear(Y); arb_mat_clear(Z); } else { arb_mat_init(X, M, N); arb_mat_init(Y, N, P); arb_mat_init(Z, M, P); /* (reA*reB, reA*imB) */ copy_re_shallow(X, A); copy_re_shallow(Y, B); if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, M, P); arb_mat_mul(T, X, Y, prec); copy_im_shallow(Y, B); arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_swap(acb_realref(acb_mat_entry(C, i, j)), acb_mat_entry(T, i, j)); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_swap(acb_imagref(acb_mat_entry(C, i, j)), acb_mat_entry(Z, i, j)); arb_mat_clear(T); } else { copy_re_shallow(Z, C); arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) *acb_realref(acb_mat_entry(C, i, j)) = *arb_mat_entry(Z, i, j); copy_im_shallow(Z, C); copy_im_shallow(Y, B); arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) *acb_imagref(acb_mat_entry(C, i, j)) = *arb_mat_entry(Z, i, j); clear_shallow(Z); } clear_shallow(X); clear_shallow(Y); arb_mat_clear(X); arb_mat_clear(Y); arb_mat_clear(Z); } } else if (acb_mat_is_real(B)) { arb_mat_init(X, M, N); arb_mat_init(Y, N, P); arb_mat_init(Z, M, P); /* (reA*reB, imA*reB) */ copy_re_shallow(X, A); copy_re_shallow(Y, B); if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, M, P); arb_mat_mul(T, X, Y, prec); copy_im_shallow(X, A); arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_swap(acb_realref(acb_mat_entry(C, i, j)), acb_mat_entry(T, i, j)); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_swap(acb_imagref(acb_mat_entry(C, i, j)), acb_mat_entry(Z, i, j)); arb_mat_clear(T); } else { copy_re_shallow(Z, C); arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) *acb_realref(acb_mat_entry(C, i, j)) = *arb_mat_entry(Z, i, j); copy_im_shallow(Z, C); copy_im_shallow(X, A); arb_mat_mul(Z, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) *acb_imagref(acb_mat_entry(C, i, j)) = *arb_mat_entry(Z, i, j); clear_shallow(Z); } clear_shallow(X); clear_shallow(Y); arb_mat_clear(X); arb_mat_clear(Y); arb_mat_clear(Z); } else { arb_mat_init(X, M, N); arb_mat_init(Y, N, P); arb_mat_init(Z, M, P); arb_mat_init(W, M, P); copy_re_shallow(X, A); copy_re_shallow(Y, B); arb_mat_mul(Z, X, Y, prec); copy_im_shallow(X, A); copy_im_shallow(Y, B); arb_mat_mul(W, X, Y, prec); if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, M, P); arb_mat_sub(T, Z, W, prec); copy_re_shallow(X, A); arb_mat_mul(Z, X, Y, prec); copy_im_shallow(X, A); copy_re_shallow(Y, B); arb_mat_mul(W, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_swap(acb_realref(acb_mat_entry(C, i, j)), arb_mat_entry(T, i, j)); arb_mat_clear(T); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_add(acb_imagref(acb_mat_entry(C, i, j)), arb_mat_entry(Z, i, j), arb_mat_entry(W, i, j), prec); } else { for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_sub(acb_realref(acb_mat_entry(C, i, j)), arb_mat_entry(Z, i, j), arb_mat_entry(W, i, j), prec); copy_re_shallow(X, A); arb_mat_mul(Z, X, Y, prec); copy_im_shallow(X, A); copy_re_shallow(Y, B); arb_mat_mul(W, X, Y, prec); for (i = 0; i < M; i++) for (j = 0; j < P; j++) arb_add(acb_imagref(acb_mat_entry(C, i, j)), arb_mat_entry(Z, i, j), arb_mat_entry(W, i, j), prec); } clear_shallow(X); clear_shallow(Y); arb_mat_clear(X); arb_mat_clear(Y); arb_mat_clear(Z); arb_mat_clear(W); } } flint-3.1.3/src/acb_mat/mul_threaded.c000066400000000000000000000062141461254215100176140ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "acb_mat.h" typedef struct { acb_ptr * C; const acb_ptr * A; const acb_ptr * B; slong ar0; slong ar1; slong bc0; slong bc1; slong br; slong prec; } _worker_arg; void _acb_mat_mul_thread(void * arg_ptr) { _worker_arg arg = *((_worker_arg *) arg_ptr); slong i, j, br, bc; acb_ptr tmp; TMP_INIT; br = arg.br; bc = arg.bc1 - arg.bc0; TMP_START; tmp = TMP_ALLOC(sizeof(acb_struct) * br * bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) tmp[j * br + i] = arg.B[i][arg.bc0 + j]; for (i = arg.ar0; i < arg.ar1; i++) { for (j = arg.bc0; j < arg.bc1; j++) { acb_dot(arg.C[i] + j, NULL, 0, arg.A[i], 1, tmp + (j - arg.bc0) * br, 1, br, arg.prec); } } TMP_END; flint_cleanup(); return; } void acb_mat_mul_threaded(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { slong ar, ac, br, bc, i, num_threads, num_workers; thread_pool_handle * handles; _worker_arg * args; ar = acb_mat_nrows(A); ac = acb_mat_ncols(A); br = acb_mat_nrows(B); bc = acb_mat_ncols(B); if (ac != br || ar != acb_mat_nrows(C) || bc != acb_mat_ncols(C)) flint_throw(FLINT_DOMERR, "incompatible dimensions in %s\n", __func__); if (br == 0) { acb_mat_zero(C); return; } if (A == C || B == C) { acb_mat_t T; acb_mat_init(T, ar, bc); acb_mat_mul_threaded(T, A, B, prec); acb_mat_swap_entrywise(T, C); acb_mat_clear(T); return; } num_workers = flint_request_threads(&handles, FLINT_MAX(ar, bc)); num_threads = num_workers + 1; args = FLINT_ARRAY_ALLOC(num_threads, _worker_arg); for (i = 0; i < num_threads; i++) { args[i].C = C->rows; args[i].A = A->rows; args[i].B = B->rows; if (ar >= bc) { args[i].ar0 = (ar * i) / num_threads; args[i].ar1 = (ar * (i + 1)) / num_threads; args[i].bc0 = 0; args[i].bc1 = bc; } else { args[i].ar0 = 0; args[i].ar1 = ar; args[i].bc0 = (bc * i) / num_threads; args[i].bc1 = (bc * (i + 1)) / num_threads; } args[i].br = br; args[i].prec = prec; if (i < num_workers) thread_pool_wake(global_thread_pool, handles[i], 0, _acb_mat_mul_thread, &args[i]); else _acb_mat_mul_thread(&args[i]); } for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); flint_free(args); } flint-3.1.3/src/acb_mat/ne.c000066400000000000000000000015111461254215100155540ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_ne(const acb_mat_t mat1, const acb_mat_t mat2) { slong i, j; if ((acb_mat_nrows(mat1) != acb_mat_nrows(mat2)) || (acb_mat_ncols(mat1) != acb_mat_ncols(mat2))) return 1; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) if (acb_ne(acb_mat_entry(mat1, i, j), acb_mat_entry(mat2, i, j))) return 1; return 0; } flint-3.1.3/src/acb_mat/neg.c000066400000000000000000000012301461254215100157210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_neg(acb_mat_t dest, const acb_mat_t src) { slong i, j; for (i = 0; i < acb_mat_nrows(src); i++) for (j = 0; j < acb_mat_ncols(src); j++) acb_neg(acb_mat_entry(dest, i, j), acb_mat_entry(src, i, j)); } flint-3.1.3/src/acb_mat/one.c000066400000000000000000000012701461254215100157350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_one(acb_mat_t mat) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) for (j = 0; j < acb_mat_ncols(mat); j++) if (i == j) acb_one(acb_mat_entry(mat, i, j)); else acb_zero(acb_mat_entry(mat, i, j)); } flint-3.1.3/src/acb_mat/onei.c000066400000000000000000000014151461254215100161070ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_onei(acb_mat_t mat) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) { for (j = 0; j < acb_mat_ncols(mat); j++) { if (i == j) { acb_onei(acb_mat_entry(mat, i, j)); } else { acb_zero(acb_mat_entry(mat, i, j)); } } } } flint-3.1.3/src/acb_mat/ones.c000066400000000000000000000011651461254215100161230ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_ones(acb_mat_t mat) { slong R, C, i, j; R = acb_mat_nrows(mat); C = acb_mat_ncols(mat); for (i = 0; i < R; i++) for (j = 0; j < C; j++) acb_one(acb_mat_entry(mat, i, j)); } flint-3.1.3/src/acb_mat/overlaps.c000066400000000000000000000015121461254215100170060ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_overlaps(const acb_mat_t mat1, const acb_mat_t mat2) { slong i, j; if ((acb_mat_nrows(mat1) != acb_mat_nrows(mat2)) || (acb_mat_ncols(mat1) != acb_mat_ncols(mat2))) return 0; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) if (!acb_overlaps(acb_mat_entry(mat1, i, j), acb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/acb_mat/pow_ui.c000066400000000000000000000026351461254215100164640ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_pow_ui(acb_mat_t B, const acb_mat_t A, ulong exp, slong prec) { slong d = acb_mat_nrows(A); if (exp <= 2 || d <= 1) { if (exp == 0 || d == 0) { acb_mat_one(B); } else if (d == 1) { acb_pow_ui(acb_mat_entry(B, 0, 0), acb_mat_entry(A, 0, 0), exp, prec); } else if (exp == 1) { acb_mat_set(B, A); } else if (exp == 2) { acb_mat_sqr(B, A, prec); } } else { acb_mat_t T, U; slong i; acb_mat_init(T, d, d); acb_mat_set(T, A); acb_mat_init(U, d, d); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { acb_mat_sqr(U, T, prec); if (exp & (WORD(1) << i)) acb_mat_mul(T, U, A, prec); else acb_mat_swap(T, U); } acb_mat_swap(B, T); acb_mat_clear(T); acb_mat_clear(U); } } flint-3.1.3/src/acb_mat/randtest.c000066400000000000000000000023221461254215100167770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_randtest(acb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) { slong i, j, density; density = n_randint(state, 100); if (n_randint(state, 2)) for (i = 0; i < acb_mat_nrows(mat); i++) for (j = 0; j < acb_mat_ncols(mat); j++) if (n_randint(state, 100) < density) acb_randtest(acb_mat_entry(mat, i, j), state, prec, mag_bits); else acb_zero(acb_mat_entry(mat, i, j)); else for (i = 0; i < acb_mat_nrows(mat); i++) for (j = 0; j < acb_mat_ncols(mat); j++) if (n_randint(state, 100) < density) acb_randtest_precise(acb_mat_entry(mat, i, j), state, prec, mag_bits); else acb_zero(acb_mat_entry(mat, i, j)); } flint-3.1.3/src/acb_mat/randtest_eig.c000066400000000000000000000030171461254215100176250ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_randtest_eig(acb_mat_t A, flint_rand_t state, acb_srcptr E, slong prec) { slong n, i, j, ebits; acb_mat_t U, Q; n = acb_mat_nrows(A); ebits = 1 + n_randint(state, 5); acb_mat_init(U, n, n); acb_mat_init(Q, n, n); /* Skew-Hermitian matrix */ acb_mat_randtest(Q, state, prec, 1); if (n_randint(state, 2)) acb_mat_get_mid(Q, Q); for (i = 0; i < n; i++) { for (j = i + 1; j < n; j++) { acb_neg(acb_mat_entry(Q, i, j), acb_mat_entry(Q, j, i)); acb_conj(acb_mat_entry(Q, i, j), acb_mat_entry(Q, i, j)); } arb_zero(acb_realref(acb_mat_entry(Q, i, i))); } acb_mat_exp(Q, Q, prec); acb_mat_randtest(U, state, prec, ebits); if (n_randint(state, 2)) acb_mat_get_mid(U, U); for (i = 0; i < n; i++) for (j = 0; j < i; j++) acb_zero(acb_mat_entry(U, i, j)); for (i = 0; i < n; i++) acb_set(acb_mat_entry(U, i, i), E + i); acb_mat_mul(U, Q, U, prec); acb_mat_conjugate_transpose(Q, Q); acb_mat_mul(A, U, Q, prec); acb_mat_clear(U); acb_mat_clear(Q); } flint-3.1.3/src/acb_mat/set.c000066400000000000000000000013441461254215100157510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_set(acb_mat_t dest, const acb_mat_t src) { slong i, j; if (dest != src && acb_mat_ncols(src) != 0) { for (i = 0; i < acb_mat_nrows(src); i++) for (j = 0; j < acb_mat_ncols(src); j++) acb_set(acb_mat_entry(dest, i, j), acb_mat_entry(src, i, j)); } } flint-3.1.3/src/acb_mat/set_arb_mat.c000066400000000000000000000013401461254215100174320ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_set_arb_mat(acb_mat_t dest, const arb_mat_t src) { slong i, j; if (acb_mat_ncols(dest) != 0) { for (i = 0; i < acb_mat_nrows(dest); i++) for (j = 0; j < acb_mat_ncols(dest); j++) acb_set_arb(acb_mat_entry(dest, i, j), arb_mat_entry(src, i, j)); } } flint-3.1.3/src/acb_mat/set_fmpq_mat.c000066400000000000000000000014201461254215100176300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" #include "acb_mat.h" void acb_mat_set_fmpq_mat(acb_mat_t dest, const fmpq_mat_t src, slong prec) { slong i, j; if (acb_mat_ncols(dest) != 0) { for (i = 0; i < acb_mat_nrows(dest); i++) for (j = 0; j < acb_mat_ncols(dest); j++) acb_set_fmpq(acb_mat_entry(dest, i, j), fmpq_mat_entry(src, i, j), prec); } } flint-3.1.3/src/acb_mat/set_fmpz_mat.c000066400000000000000000000013761461254215100176530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "acb_mat.h" void acb_mat_set_fmpz_mat(acb_mat_t dest, const fmpz_mat_t src) { slong i, j; if (acb_mat_ncols(dest) != 0) { for (i = 0; i < acb_mat_nrows(dest); i++) for (j = 0; j < acb_mat_ncols(dest); j++) acb_set_fmpz(acb_mat_entry(dest, i, j), fmpz_mat_entry(src, i, j)); } } flint-3.1.3/src/acb_mat/set_real_imag.c000066400000000000000000000013701461254215100177500ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_set_real_imag(acb_mat_t mat, const arb_mat_t re, const arb_mat_t im) { slong i, j; for (i = 0; i < acb_mat_nrows(re); i++) { for (j = 0; j < acb_mat_ncols(re); j++) { acb_set_arb_arb(acb_mat_entry(mat, i, j), arb_mat_entry(re, i, j), arb_mat_entry(im, i, j)); } } } flint-3.1.3/src/acb_mat/set_round_arb_mat.c000066400000000000000000000013761461254215100206520ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_set_round_arb_mat(acb_mat_t dest, const arb_mat_t src, slong prec) { slong i, j; if (acb_mat_ncols(dest) != 0) { for (i = 0; i < acb_mat_nrows(dest); i++) for (j = 0; j < acb_mat_ncols(dest); j++) acb_set_round_arb(acb_mat_entry(dest, i, j), arb_mat_entry(src, i, j), prec); } } flint-3.1.3/src/acb_mat/set_round_fmpz_mat.c000066400000000000000000000014301461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "acb_mat.h" void acb_mat_set_round_fmpz_mat(acb_mat_t dest, const fmpz_mat_t src, slong prec) { slong i, j; if (acb_mat_ncols(dest) != 0) { for (i = 0; i < acb_mat_nrows(dest); i++) for (j = 0; j < acb_mat_ncols(dest); j++) acb_set_round_fmpz(acb_mat_entry(dest, i, j), fmpz_mat_entry(src, i, j), prec); } } flint-3.1.3/src/acb_mat/solve.c000066400000000000000000000012341461254215100163040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int acb_mat_solve(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) { slong n = acb_mat_nrows(A); if (n <= 4 || prec > 10.0 * n) return acb_mat_solve_lu(X, A, B, prec); else return acb_mat_solve_precond(X, A, B, prec); } flint-3.1.3/src/acb_mat/solve_lu.c000066400000000000000000000016121461254215100170040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "acb_mat.h" int acb_mat_solve_lu(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) { int result; slong n, m, *perm; acb_mat_t LU; n = acb_mat_nrows(A); m = acb_mat_ncols(X); if (n == 0 || m == 0) return 1; perm = _perm_init(n); acb_mat_init(LU, n, n); result = acb_mat_lu(perm, LU, A, prec); if (result) acb_mat_solve_lu_precomp(X, perm, LU, B, prec); acb_mat_clear(LU); _perm_clear(perm); return result; } flint-3.1.3/src/acb_mat/solve_lu_precomp.c000066400000000000000000000040241461254215100205310ustar00rootroot00000000000000/* Copyright (C) 2012,2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_solve_lu_precomp(acb_mat_t X, const slong * perm, const acb_mat_t A, const acb_mat_t B, slong prec) { slong i, j, c, n, m; n = acb_mat_nrows(X); m = acb_mat_ncols(X); if (X == B) { acb_ptr tmp = flint_malloc(sizeof(acb_struct) * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) tmp[i] = B->rows[perm[i]][c]; for (i = 0; i < n; i++) X->rows[i][c] = tmp[i]; } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { acb_set(acb_mat_entry(X, i, c), acb_mat_entry(B, perm[i], c)); } } } /* solve_tril and solve_triu have some overhead */ if (n >= 4) { acb_mat_solve_tril(X, A, X, 1, prec); acb_mat_solve_triu(X, A, X, 0, prec); return; } for (c = 0; c < m; c++) { /* solve Ly = b */ for (i = 1; i < n; i++) { for (j = 0; j < i; j++) { acb_submul(acb_mat_entry(X, i, c), acb_mat_entry(A, i, j), acb_mat_entry(X, j, c), prec); } } /* solve Ux = y */ for (i = n - 1; i >= 0; i--) { for (j = i + 1; j < n; j++) { acb_submul(acb_mat_entry(X, i, c), acb_mat_entry(A, i, j), acb_mat_entry(X, j, c), prec); } acb_div(acb_mat_entry(X, i, c), acb_mat_entry(X, i, c), acb_mat_entry(A, i, i), prec); } } } flint-3.1.3/src/acb_mat/solve_precond.c000066400000000000000000000064021461254215100200200ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" int _acb_mat_solve_c(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) { int result; slong m, n; acb_mat_t I, R; n = acb_mat_nrows(A); m = acb_mat_ncols(X); if (n == 0 || m == 0) return 1; acb_mat_init(I, n, n); acb_mat_init(R, n, n); acb_mat_one(I); result = acb_mat_approx_solve(R, A, I, prec); if (result) { acb_mat_t RA, RB; acb_mat_init(RA, n, n); acb_mat_init(RB, n, m); acb_mat_mul(RA, R, A, prec); acb_mat_mul(RB, R, B, prec); result = acb_mat_solve_lu(X, RA, RB, prec); acb_mat_clear(RA); acb_mat_clear(RB); } acb_mat_clear(I); acb_mat_clear(R); return result; } int _acb_mat_solve_d(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) { int result, real; slong m, n; acb_mat_t I, R; n = acb_mat_nrows(A); m = acb_mat_ncols(X); if (n == 0 || m == 0) return 1; real = acb_mat_is_real(A) && acb_mat_is_real(B); acb_mat_init(I, n, n); acb_mat_init(R, n, n); acb_mat_one(I); result = acb_mat_approx_solve(R, A, I, prec); if (result) { acb_mat_t RA, RB, E; mag_t d; acb_mat_init(RA, n, n); acb_mat_init(RB, n, m); acb_mat_init(E, n, n); mag_init(d); acb_mat_mul(RA, R, A, prec); acb_mat_mul(RB, R, B, prec); acb_mat_sub(E, I, RA, prec); acb_mat_bound_inf_norm(d, E); if (mag_cmp_2exp_si(d, 0) < 0) { slong i, j; mag_t e, err; mag_init(e); mag_init(err); mag_geom_series(d, d, 1); acb_mat_set(X, RB); for (j = 0; j < m; j++) { mag_zero(err); for (i = 0; i < n; i++) { acb_get_mag(e, acb_mat_entry(RB, i, j)); mag_max(err, err, e); } mag_mul(err, err, d); for (i = 0; i < n; i++) { if (real) arb_add_error_mag(acb_realref(acb_mat_entry(X, i, j)), err); else acb_add_error_mag(acb_mat_entry(X, i, j), err); } } mag_clear(e); mag_clear(err); } else { result = acb_mat_solve_lu(X, RA, RB, prec); } acb_mat_clear(RA); acb_mat_clear(RB); acb_mat_clear(E); mag_clear(d); } acb_mat_clear(I); acb_mat_clear(R); return result; } int acb_mat_solve_precond(acb_mat_t X, const acb_mat_t A, const acb_mat_t B, slong prec) { slong n = acb_mat_nrows(A); slong m = acb_mat_ncols(B); if (m < 0.1 * n + 1) return _acb_mat_solve_c(X, A, B, prec); else return _acb_mat_solve_d(X, A, B, prec); } flint-3.1.3/src/acb_mat/solve_tril.c000066400000000000000000000052311461254215100173370ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_solve_tril_classical(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) { slong i, j, n, m; acb_ptr tmp; acb_t s; n = L->r; m = B->c; acb_init(s); tmp = flint_malloc(sizeof(acb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *acb_mat_entry(X, j, i); for (j = 0; j < n; j++) { acb_dot(s, acb_mat_entry(B, j, i), 1, L->rows[j], 1, tmp, 1, j, prec); if (!unit) acb_div(tmp + j, s, acb_mat_entry(L, j, j), prec); else acb_swap(tmp + j, s); } for (j = 0; j < n; j++) *acb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); acb_clear(s); } void acb_mat_solve_tril_recursive(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) { acb_mat_t LA, LC, LD, XX, XY, BX, BY, T; slong r, n, m; n = L->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A 0]^ [X] == [A^ 0 ] [X] == [A^ X] [C D] [Y] == [-D^ C A^ D^] [Y] == [D^ (Y - C A^ X)] */ acb_mat_window_init(LA, L, 0, 0, r, r); acb_mat_window_init(LC, L, r, 0, n, r); acb_mat_window_init(LD, L, r, r, n, n); acb_mat_window_init(BX, B, 0, 0, r, m); acb_mat_window_init(BY, B, r, 0, n, m); acb_mat_window_init(XX, X, 0, 0, r, m); acb_mat_window_init(XY, X, r, 0, n, m); acb_mat_solve_tril(XX, LA, BX, unit, prec); /* acb_mat_submul(XY, BY, LC, XX); */ acb_mat_init(T, LC->r, BX->c); acb_mat_mul(T, LC, XX, prec); acb_mat_sub(XY, BY, T, prec); acb_mat_clear(T); acb_mat_solve_tril(XY, LD, XY, unit, prec); acb_mat_window_clear(LA); acb_mat_window_clear(LC); acb_mat_window_clear(LD); acb_mat_window_clear(BX); acb_mat_window_clear(BY); acb_mat_window_clear(XX); acb_mat_window_clear(XY); } void acb_mat_solve_tril(acb_mat_t X, const acb_mat_t L, const acb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) acb_mat_solve_tril_classical(X, L, B, unit, prec); else acb_mat_solve_tril_recursive(X, L, B, unit, prec); } flint-3.1.3/src/acb_mat/solve_triu.c000066400000000000000000000052111461254215100173460ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_solve_triu_classical(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) { slong i, j, n, m; acb_ptr tmp; acb_t s; n = U->r; m = B->c; acb_init(s); tmp = flint_malloc(sizeof(acb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *acb_mat_entry(X, j, i); for (j = n - 1; j >= 0; j--) { acb_dot(s, acb_mat_entry(B, j, i), 1, U->rows[j] + j + 1, 1, tmp + j + 1, 1, n - j - 1, prec); if (!unit) acb_div(tmp + j, s, acb_mat_entry(U, j, j), prec); else acb_swap(tmp + j, s); } for (j = 0; j < n; j++) *acb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); acb_clear(s); } void acb_mat_solve_triu_recursive(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) { acb_mat_t UA, UB, UD, XX, XY, BX, BY, T; slong r, n, m; n = U->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A B]^ [X] == [A^ (X - B D^ Y)] [0 D] [Y] == [ D^ Y ] */ acb_mat_window_init(UA, U, 0, 0, r, r); acb_mat_window_init(UB, U, 0, r, r, n); acb_mat_window_init(UD, U, r, r, n, n); acb_mat_window_init(BX, B, 0, 0, r, m); acb_mat_window_init(BY, B, r, 0, n, m); acb_mat_window_init(XX, X, 0, 0, r, m); acb_mat_window_init(XY, X, r, 0, n, m); acb_mat_solve_triu(XY, UD, BY, unit, prec); /* acb_mat_submul(XX, BX, UB, XY); */ acb_mat_init(T, UB->r, XY->c); acb_mat_mul(T, UB, XY, prec); acb_mat_sub(XX, BX, T, prec); acb_mat_clear(T); acb_mat_solve_triu(XX, UA, XX, unit, prec); acb_mat_window_clear(UA); acb_mat_window_clear(UB); acb_mat_window_clear(UD); acb_mat_window_clear(BX); acb_mat_window_clear(BY); acb_mat_window_clear(XX); acb_mat_window_clear(XY); } void acb_mat_solve_triu(acb_mat_t X, const acb_mat_t U, const acb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) acb_mat_solve_triu_classical(X, U, B, unit, prec); else acb_mat_solve_triu_recursive(X, U, B, unit, prec); } flint-3.1.3/src/acb_mat/sqr.c000066400000000000000000000007601461254215100157640ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_sqr(acb_mat_t B, const acb_mat_t A, slong prec) { acb_mat_mul(B, A, A, prec); } flint-3.1.3/src/acb_mat/sqr_classical.c000066400000000000000000000051721461254215100200040ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_sqr_classical(acb_mat_t B, const acb_mat_t A, slong prec) { slong n, i, j, k; acb_t p, s; n = acb_mat_nrows(A); if (acb_mat_ncols(A) != n || acb_mat_nrows(B) != n || acb_mat_ncols(B) != n) { flint_throw(FLINT_ERROR, "acb_mat_sqr: incompatible dimensions\n"); } if (n == 0) return; if (n == 1) { acb_mul(acb_mat_entry(B, 0, 0), acb_mat_entry(A, 0, 0), acb_mat_entry(A, 0, 0), prec); return; } if (A == B) { acb_mat_t T; acb_mat_init(T, n, n); acb_mat_sqr_classical(T, A, prec); acb_mat_swap(T, B); acb_mat_clear(T); return; } acb_init(p); acb_init(s); /* contribution of diagonal of A to diagonal of B */ for (i = 0; i < n; i++) { acb_mul(acb_mat_entry(B, i, i), acb_mat_entry(A, i, i), acb_mat_entry(A, i, i), prec); } for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { /* contribution of off-diagonal of A to diagonal of B */ acb_mul(p, acb_mat_entry(A, i, j), acb_mat_entry(A, j, i), prec); acb_add(acb_mat_entry(B, i, i), acb_mat_entry(B, i, i), p, prec); acb_add(acb_mat_entry(B, j, j), acb_mat_entry(B, j, j), p, prec); /* contribution of diagonal of A to off-diagonal of B */ acb_add(s, acb_mat_entry(A, i, i), acb_mat_entry(A, j, j), prec); acb_mul(acb_mat_entry(B, i, j), acb_mat_entry(A, i, j), s, prec); acb_mul(acb_mat_entry(B, j, i), acb_mat_entry(A, j, i), s, prec); } } /* contribution of off-diagonal of A to off-diagonal of B */ if (n > 2) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { for (k = 0; k < n; k++) { if (i != j && j != k && k != i) { acb_addmul(acb_mat_entry(B, i, j), acb_mat_entry(A, i, k), acb_mat_entry(A, k, j), prec); } } } } } acb_clear(p); acb_clear(s); } flint-3.1.3/src/acb_mat/sub.c000066400000000000000000000013651461254215100157520ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_sub(acb_mat_t res, const acb_mat_t mat1, const acb_mat_t mat2, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(mat1); i++) for (j = 0; j < acb_mat_ncols(mat1); j++) acb_sub(acb_mat_entry(res, i, j), acb_mat_entry(mat1, i, j), acb_mat_entry(mat2, i, j), prec); } flint-3.1.3/src/acb_mat/test/000077500000000000000000000000001461254215100157675ustar00rootroot00000000000000flint-3.1.3/src/acb_mat/test/main.c000066400000000000000000000050731461254215100170640ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-approx_eig_qr.c" #include "t-charpoly.c" #include "t-companion.c" #include "t-det.c" #include "t-det_precond.c" #include "t-dft.c" #include "t-eig_enclosure_rump.c" #include "t-eig_global_enclosure.c" #include "t-eig_multiple.c" #include "t-eig_simple.c" #include "t-exp.c" #include "t-exp_taylor_sum.c" #include "t-frobenius_norm.c" #include "t-inv.c" #include "t-lu.c" #include "t-lu_recursive.c" #include "t-mul.c" #include "t-mul_entrywise.c" #include "t-mul_reorder.c" #include "t-mul_threaded.c" #include "t-set_real_imag.c" #include "t-solve.c" #include "t-solve_lu.c" #include "t-solve_precond.c" #include "t-solve_tril.c" #include "t-solve_triu.c" #include "t-sqr.c" #include "t-trace.c" #include "t-transpose.c" #include "t-vector_mul.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_mat_approx_eig_qr), TEST_FUNCTION(acb_mat_charpoly), TEST_FUNCTION(acb_mat_companion), TEST_FUNCTION(acb_mat_det), TEST_FUNCTION(acb_mat_det_precond), TEST_FUNCTION(acb_mat_dft), TEST_FUNCTION(acb_mat_eig_enclosure_rump), TEST_FUNCTION(acb_mat_eig_global_enclosure), TEST_FUNCTION(acb_mat_eig_multiple), TEST_FUNCTION(acb_mat_eig_simple), TEST_FUNCTION(acb_mat_exp), TEST_FUNCTION(acb_mat_exp_taylor_sum), TEST_FUNCTION(acb_mat_frobenius_norm), TEST_FUNCTION(acb_mat_inv), TEST_FUNCTION(acb_mat_lu), TEST_FUNCTION(acb_mat_lu_recursive), TEST_FUNCTION(acb_mat_mul), TEST_FUNCTION(acb_mat_mul_entrywise), TEST_FUNCTION(acb_mat_mul_reorder), TEST_FUNCTION(acb_mat_mul_threaded), TEST_FUNCTION(acb_mat_set_real_imag), TEST_FUNCTION(acb_mat_solve), TEST_FUNCTION(acb_mat_solve_lu), TEST_FUNCTION(acb_mat_solve_precond), TEST_FUNCTION(acb_mat_solve_tril), TEST_FUNCTION(acb_mat_solve_triu), TEST_FUNCTION(acb_mat_sqr), TEST_FUNCTION(acb_mat_trace), TEST_FUNCTION(acb_mat_transpose), TEST_FUNCTION(acb_mat_vector_mul) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_mat/test/t-approx_eig_qr.c000066400000000000000000000127301461254215100212360ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_approx_eig_qr, state) { slong iter; /* Test random & DFT matrices */ for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, L, R; acb_ptr E; acb_t t; mag_t b; slong i, j, n, prec, goal, c0, c1, c2, c3; int wantL, wantR, result, dft; dft = n_randint(state, 2); if (dft) n = n_randint(state, 30); else n = n_randint(state, 15); goal = 2 + n_randint(state, 100); wantL = n_randint(state, 2); wantR = n_randint(state, 2); acb_mat_init(A, n, n); acb_mat_init(L, n, n); acb_mat_init(R, n, n); acb_init(t); mag_init(b); E = _acb_vec_init(n); for (prec = 32; ; prec *= 2) { if (dft) { acb_mat_dft(A, 0, prec); } else { acb_mat_randtest(A, state, 2 + n_randint(state, 200), 5); acb_mat_get_mid(A, A); } acb_mat_approx_eig_qr(E, wantL ? L : NULL, wantR ? R : NULL, A, NULL, 0, prec); if (dft) { /* Verify the known eigenvalues + multiplicities */ c0 = c1 = c2 = c3 = 0; for (i = 0; i < n; i++) { acb_set_d_d(t, 1.0, 0.0); acb_sub(t, t, E + i, prec); acb_get_mag(b, t); c0 += (mag_cmp_2exp_si(b, -goal) < 0); acb_set_d_d(t, -1.0, 0.0); acb_sub(t, t, E + i, prec); acb_get_mag(b, t); c1 += (mag_cmp_2exp_si(b, -goal) < 0); acb_set_d_d(t, 0.0, 1.0); acb_sub(t, t, E + i, prec); acb_get_mag(b, t); c2 += (mag_cmp_2exp_si(b, -goal) < 0); acb_set_d_d(t, 0.0, -1.0); acb_sub(t, t, E + i, prec); acb_get_mag(b, t); c3 += (mag_cmp_2exp_si(b, -goal) < 0); } result = (n == 0 || (c0 == (n+4)/4 && c1 == (n+2)/4 && c2 == (n-1)/4 && c3 == (n+1)/4)); } else { result = 1; } if (result && wantL) { acb_mat_t LA, D; acb_mat_init(LA, n, n); acb_mat_init(D, n, n); /* Check LA - lambda L = 0 */ acb_mat_approx_mul(LA, L, A, prec); for (i = 0; i < n; i++) acb_set(acb_mat_entry(D, i, i), E + i); acb_mat_approx_mul(D, D, L, prec); acb_mat_sub(LA, LA, D, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { acb_get_mag(b, acb_mat_entry(LA, i, j)); result = result && (mag_cmp_2exp_si(b, -goal) < 0); } } acb_mat_clear(LA); acb_mat_clear(D); } if (result && wantR) { acb_mat_t AR, D; acb_mat_init(AR, n, n); acb_mat_init(D, n, n); /* Check AR - R lambda = 0 */ acb_mat_approx_mul(AR, A, R, prec); for (i = 0; i < n; i++) acb_set(acb_mat_entry(D, i, i), E + i); acb_mat_approx_mul(D, R, D, prec); acb_mat_sub(AR, AR, D, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { acb_get_mag(b, acb_mat_entry(AR, i, j)); result = result && (mag_cmp_2exp_si(b, -goal) < 0); } } acb_mat_clear(AR); acb_mat_clear(D); } if (result) break; if (prec > 2000) { flint_printf("FAIL (convergence, dft = %d)\n\n", dft); flint_printf("n = %wd\n\n", n); acb_mat_printd(A, 10); flint_printf("\n\n"); for (i = 0; i < n; i++) { acb_printn(E + i, 50, 0); flint_printf("\n"); } flint_printf("\n"); if (wantL) { flint_printf("L = \n"); acb_mat_printd(L, 10); flint_printf("\n\n"); } if (wantR) { flint_printf("R = \n"); acb_mat_printd(R, 10); flint_printf("\n\n"); } flint_abort(); } } acb_mat_clear(A); acb_mat_clear(L); acb_mat_clear(R); _acb_vec_clear(E, n); acb_clear(t); mag_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-charpoly.c000066400000000000000000000036441461254215100202240ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_charpoly, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, B, C, D; acb_poly_t f, g; slong m, n; m = n_randint(state, 8); n = m; acb_mat_init(A, m, n); acb_mat_init(B, m, n); acb_mat_init(C, m, m); acb_mat_init(D, n, n); acb_poly_init(f); acb_poly_init(g); acb_mat_randtest(A, state, 1 + n_randint(state, 1000), 10); acb_mat_randtest(B, state, 1 + n_randint(state, 1000), 10); acb_mat_mul(C, A, B, 2 + n_randint(state, 1000)); acb_mat_mul(D, B, A, 2 + n_randint(state, 1000)); acb_mat_charpoly(f, C, 2 + n_randint(state, 1000)); acb_mat_charpoly(g, D, 2 + n_randint(state, 1000)); if (!acb_poly_overlaps(f, g)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), acb_mat_printd(A, 15), flint_printf("\n"); flint_printf("Matrix B:\n"), acb_mat_printd(B, 15), flint_printf("\n"); flint_printf("cp(AB) = "), acb_poly_printd(f, 15), flint_printf("\n"); flint_printf("cp(BA) = "), acb_poly_printd(g, 15), flint_printf("\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(C); acb_mat_clear(D); acb_poly_clear(f); acb_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-companion.c000066400000000000000000000032051461254215100203570ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_companion, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A; acb_poly_t f, g; slong n, prec; acb_poly_init(f); acb_poly_init(g); do { acb_poly_randtest(f, state, 1 + n_randint(state, 8), 1 + n_randint(state, 1000), 10); } while (acb_poly_degree(f) < 0); n = acb_poly_degree(f); prec = 2 + n_randint(state, 200); acb_mat_init(A, n, n); acb_mat_randtest(A, state, 1 + n_randint(state, 1000), 10); acb_mat_companion(A, f, prec); acb_mat_charpoly(g, A, prec); acb_poly_scalar_mul(g, g, acb_poly_get_coeff_ptr(f, n), prec); if (!acb_poly_contains(g, f)) { flint_printf("FAIL\n"); flint_printf("A:\n"), acb_mat_printd(A, 15), flint_printf("\n"); flint_printf("f:\n"), acb_poly_printd(f, 15), flint_printf("\n"); flint_printf("g:\n"), acb_poly_printd(g, 15), flint_printf("\n"); flint_abort(); } acb_mat_clear(A); acb_poly_clear(f); acb_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-det.c000066400000000000000000000074541461254215100171620ustar00rootroot00000000000000/* Copyright (C) 2012, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_det, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; fmpq_t Qdet; acb_mat_t A; acb_t Adet; slong n, qbits, prec; n = n_randint(state, 12); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_init(Qdet); acb_mat_init(A, n, n); acb_init(Adet); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_det(Qdet, Q); acb_mat_set_fmpq_mat(A, Q, prec); acb_mat_det(Adet, A, prec); if (!acb_contains_fmpq(Adet, Qdet)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qdet = \n"); fmpq_print(Qdet); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Adet = \n"); acb_printd(Adet, 15); flint_printf("\n\n"); flint_printf("Adet = \n"); acb_print(Adet); flint_printf("\n\n"); flint_abort(); } fmpq_mat_clear(Q); fmpq_clear(Qdet); acb_mat_clear(A); acb_clear(Adet); } for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, B, AB; acb_t detA, detB, detAB, t; slong n, prec1, prec2, prec3; n = n_randint(state, 12); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); prec3 = 2 + n_randint(state, 200); acb_mat_init(A, n, n); acb_mat_init(B, n, n); acb_mat_init(AB, n, n); acb_init(detA); acb_init(detB); acb_init(detAB); acb_init(t); acb_mat_randtest(A, state, 2 + n_randint(state, 200), 2 + n_randint(state, 100)); acb_mat_randtest(B, state, 2 + n_randint(state, 200), 2 + n_randint(state, 100)); acb_mat_mul(AB, A, B, prec3); acb_mat_det(detA, A, prec1); acb_mat_det(detB, B, prec2); acb_mat_det(detAB, AB, prec3); acb_mul(t, detA, detB, 1000); if (!acb_overlaps(t, detAB)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("n = %wd, prec1 = %wd, prec2 = %wd, prec3 = %wd\n", n, prec1, prec2, prec3); flint_printf("\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("detA = \n"); acb_printn(detA, 50, 0); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("detB = \n"); acb_printn(detB, 50, 0); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(AB, 15); flint_printf("\n\n"); flint_printf("detAB = \n"); acb_printn(detAB, 50, 0); flint_printf("\n\n"); flint_printf("detA*detB = \n"); acb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(AB); acb_clear(detA); acb_clear(detB); acb_clear(detAB); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-det_precond.c000066400000000000000000000123351461254215100206660ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_det_precond, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; fmpq_t Qdet; acb_mat_t A; acb_t Adet; slong n, qbits, prec; n = n_randint(state, 12); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_init(Qdet); acb_mat_init(A, n, n); acb_init(Adet); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_det(Qdet, Q); acb_mat_set_fmpq_mat(A, Q, prec); acb_mat_det_precond(Adet, A, prec); if (!acb_contains_fmpq(Adet, Qdet)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qdet = \n"); fmpq_print(Qdet); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Adet = \n"); acb_printd(Adet, 15); flint_printf("\n\n"); flint_printf("Adet = \n"); acb_print(Adet); flint_printf("\n\n"); flint_abort(); } fmpq_mat_clear(Q); fmpq_clear(Qdet); acb_mat_clear(A); acb_clear(Adet); } for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, B, AB; acb_t detA, detB, detAB, detAb, detBb, detABb, t; slong n, prec1, prec2, prec3; n = n_randint(state, 12); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); prec3 = 2 + n_randint(state, 200); acb_mat_init(A, n, n); acb_mat_init(B, n, n); acb_mat_init(AB, n, n); acb_init(detA); acb_init(detB); acb_init(detAB); acb_init(t); acb_init(detAb); acb_init(detBb); acb_init(detABb); acb_mat_randtest(A, state, 2 + n_randint(state, 200), 2 + n_randint(state, 20)); acb_mat_randtest(B, state, 2 + n_randint(state, 200), 2 + n_randint(state, 20)); acb_mat_mul(AB, A, B, prec3); acb_mat_det_precond(detA, A, prec1); acb_mat_det_precond(detB, B, prec2); acb_mat_det_precond(detAB, AB, prec3); acb_mul(t, detA, detB, 1000); if (!acb_overlaps(t, detAB)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("n = %wd, prec1 = %wd, prec2 = %wd, prec3 = %wd\n", n, prec1, prec2, prec3); flint_printf("\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("detA = \n"); acb_printn(detA, 50, 0); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("detB = \n"); acb_printn(detB, 50, 0); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(AB, 15); flint_printf("\n\n"); flint_printf("detAB = \n"); acb_printn(detAB, 50, 0); flint_printf("\n\n"); flint_printf("detA*detB = \n"); acb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_mat_det_lu(detAb, A, prec1); acb_mat_det_lu(detBb, B, prec2); acb_mat_det_lu(detABb, AB, prec3); if (!acb_overlaps(detA, detAb) || !acb_overlaps(detB, detBb) || !acb_overlaps(detAB, detABb)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("n = %wd, prec1 = %wd, prec2 = %wd, prec3 = %wd\n", n, prec1, prec2, prec3); flint_printf("\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("detA = \n"); acb_printn(detA, 50, 0); flint_printf("\n\n"); flint_printf("detAb = \n"); acb_printn(detAb, 50, 0); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("detB = \n"); acb_printn(detB, 50, 0); flint_printf("\n\n"); flint_printf("detBb = \n"); acb_printn(detBb, 50, 0); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(AB, 15); flint_printf("\n\n"); flint_printf("detAB = \n"); acb_printn(detAB, 50, 0); flint_printf("\n\n"); flint_printf("detABb = \n"); acb_printn(detABb, 50, 0); flint_printf("\n\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(AB); acb_clear(detA); acb_clear(detB); acb_clear(detAB); acb_clear(t); acb_clear(detAb); acb_clear(detBb); acb_clear(detABb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-dft.c000066400000000000000000000031131461254215100171470ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_dft, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, Ainv, AT; slong n, prec; n = n_randint(state, 10); prec = 53 + n_randint(state, 30); acb_mat_init(A, n, n); acb_mat_init(Ainv, n, n); acb_mat_init(AT, n, n); acb_mat_randtest(A, state, 100, 10); acb_mat_dft(A, 0, prec); if (!acb_mat_inv(Ainv, A, prec)) { flint_printf("FAIL: small DFT matrix (n = %wd) not invertible\n", n); flint_abort(); } acb_mat_conjugate_transpose(AT, A); if (!acb_mat_overlaps(AT, Ainv)) { flint_printf("FAIL: overlap (n = %wd)\n", n); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); acb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_printf("AT = \n"); acb_mat_printd(AT, 15); flint_printf("\n\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(Ainv); acb_mat_clear(AT); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-eig_enclosure_rump.c000066400000000000000000000176221461254215100222720ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_eig_enclosure_rump, state) { slong iter; /* Test random matrices */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, X, R, AR, J, RJ, Z, Z0; acb_ptr E, F; acb_t b, lambda; slong i, j, h, k, n, iter2, prec, found_eigenvalue; n = 1 + n_randint(state, 7); prec = 2 + n_randint(state, 200); acb_mat_init(A, n, n); acb_mat_init(X, n, n); acb_init(lambda); acb_init(b); E = _acb_vec_init(n); F = _acb_vec_init(n); if (n_randint(state, 2)) { for (i = 0; i < n; i++) acb_randtest(E + i, state, prec, 3); } else { /* Randomly repeat eigenvalues. */ for (i = 0; i < n; i++) { if (i == 0 || n_randint(state, 2)) acb_randtest(E + i, state, prec, 3); else acb_set(E + i, E + n_randint(state, i)); } } if (n_randint(state, 2)) { for (i = 0; i < n; i++) acb_get_mid(E + i, E + i); } acb_mat_randtest_eig(A, state, E, prec); acb_mat_approx_eig_qr(F, NULL, X, A, NULL, 0, prec); /* Perturb F further. */ if (n_randint(state, 4) == 0) { for (i = 0; i < n; i++) { acb_randtest(b, state, prec, 1); acb_mul_2exp_si(b, b, -n_randint(state, prec)); acb_add(F + i, F + i, b, prec); } } /* Perturb X further. */ if (n_randint(state, 10) == 0) { j = n_randint(state, n); for (i = 0; i < n; i++) { acb_randtest(b, state, prec, 1); acb_mul_2exp_si(b, b, -10 - n_randint(state, prec)); acb_add(acb_mat_entry(X, i, j), acb_mat_entry(X, i, j), b, prec); } } /* Test k = 1 */ if (1) { acb_mat_init(R, n, 1); acb_mat_init(AR, n, 1); acb_mat_init(Z, n, 1); acb_mat_init(Z0, n, 1); for (j = 0; j < n; j++) { acb_set(lambda, F + j); for (i = 0; i < n; i++) acb_set(acb_mat_entry(R, i, 0), acb_mat_entry(X, i, j)); acb_mat_eig_enclosure_rump(lambda, NULL, R, A, lambda, R, prec); acb_mat_mul(AR, A, R, prec); acb_mat_neg(Z, AR); acb_mat_scalar_addmul_acb(Z, R, lambda, prec); if (!acb_mat_contains(Z, Z0)) { flint_printf("FAIL: not containing zero!\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("lambda = \n"); acb_printd(lambda, 20); flint_printf("\n\n"); flint_printf("Z = \n"); acb_mat_printd(Z, 20); flint_printf("\n\n"); flint_printf("E = \n"); for (j = 0; j < n; j++) { acb_printd(E + j, 20); flint_printf("\n"); } flint_abort(); } found_eigenvalue = 0; for (j = 0; j < n; j++) { if (acb_contains(lambda, E + j)) found_eigenvalue++; } if (found_eigenvalue == 0) { flint_printf("FAIL: eigenvalue not found\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("lambda = \n"); acb_printd(lambda, 20); flint_printf("\n\n"); flint_printf("Z = \n"); acb_mat_printd(Z, 20); flint_printf("\n\n"); flint_printf("E = \n"); for (j = 0; j < n; j++) { acb_printd(E + j, 20); flint_printf("\n"); } flint_abort(); } } acb_mat_clear(R); acb_mat_clear(AR); acb_mat_clear(Z); acb_mat_clear(Z0); } /* Test k > 1 */ for (iter2 = 1; iter2 < n; iter2++) { k = n_randint(state, n + 1); k = FLINT_MAX(k, 2); acb_mat_init(R, n, k); acb_mat_init(AR, n, k); acb_mat_init(Z, n, k); acb_mat_init(Z0, n, k); acb_mat_init(J, k, k); acb_mat_init(RJ, n, k); /* Random selection */ for (h = 0; h < k; h++) { j = n_randint(state, n); if (h == 0 || n_randint(state, 2)) acb_set(lambda, F + j); for (i = 0; i < n; i++) acb_set(acb_mat_entry(R, i, h), acb_mat_entry(X, i, j)); } acb_mat_eig_enclosure_rump(lambda, J, R, A, lambda, R, prec); /* AY = YJ */ acb_mat_mul(AR, A, R, prec); acb_mat_mul(RJ, R, J, prec); acb_mat_sub(Z, AR, RJ, prec); if (!acb_mat_contains(Z, Z0)) { flint_printf("FAIL: not containing zero! (k = %wd, prec = %wd)\n\n", k, prec); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("lambda = \n"); acb_printd(lambda, 20); flint_printf("\n\n"); flint_printf("J = \n"); acb_mat_printd(J, 20); flint_printf("\n\n"); flint_printf("Z = \n"); acb_mat_printd(Z, 20); flint_printf("\n\n"); flint_printf("E = \n"); for (j = 0; j < n; j++) { acb_printd(E + j, 20); flint_printf("\n"); } flint_abort(); } found_eigenvalue = 0; for (j = 0; j < n; j++) { if (acb_contains(lambda, E + j)) found_eigenvalue++; } if (found_eigenvalue < k) { flint_printf("FAIL: eigenvalue not found (k = %wd, found = %wd)\n\n", k, found_eigenvalue); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("lambda = \n"); acb_printd(lambda, 20); flint_printf("\n\n"); flint_printf("Z = \n"); acb_mat_printd(Z, 20); flint_printf("\n\n"); flint_printf("E = \n"); for (j = 0; j < n; j++) { acb_printd(E + j, 20); flint_printf("\n"); } flint_abort(); } acb_mat_clear(R); acb_mat_clear(AR); acb_mat_clear(Z); acb_mat_clear(Z0); acb_mat_clear(J); acb_mat_clear(RJ); } acb_mat_clear(A); acb_mat_clear(X); acb_clear(lambda); acb_clear(b); _acb_vec_clear(E, n); _acb_vec_clear(F, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-eig_global_enclosure.c000066400000000000000000000052651461254215100225470ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_eig_global_enclosure, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, X; acb_ptr E, F, B; mag_t eps; slong i, j, n, prec; int success; n = n_randint(state, 8); prec = 2 + n_randint(state, 100); acb_mat_init(A, n, n); acb_mat_init(X, n, n); E = _acb_vec_init(n); F = _acb_vec_init(n); B = _acb_vec_init(n); mag_init(eps); for (i = 0; i < n; i++) acb_randtest(E + i, state, prec, 3); acb_mat_randtest_eig(A, state, E, prec); acb_mat_approx_eig_qr(F, NULL, X, A, NULL, 0, prec); /* perturb F further */ if (n_randint(state, 2)) { for (i = 0; i < n; i++) { acb_randtest(B, state, prec, 1); acb_mul_2exp_si(B, B, -n_randint(state, prec)); acb_add(F + i, F + i, B, prec); } } acb_mat_eig_global_enclosure(eps, A, F, X, prec); _acb_vec_set(B, F, n); for (i = 0; i < n; i++) acb_add_error_mag(B + i, eps); for (i = 0; i < n; i++) { success = 0; for (j = 0; j < n; j++) { if (acb_contains(B + j, E + i)) { success = 1; break; } } if (!success) { flint_printf("FAIL\n\n"); flint_printf("A =\n"); acb_mat_printd(A, 20); flint_printf("\n\ni = %wd\n\n", i); flint_printf("\nE =\n"); for (j = 0; j < n; j++) { acb_printn(E + j, 20, 0); flint_printf("\n"); } flint_printf("\nB =\n"); for (j = 0; j < n; j++) { acb_printn(B + j, 20, 0); flint_printf("\n"); } flint_abort(); } } acb_mat_clear(A); acb_mat_clear(X); _acb_vec_clear(E, n); _acb_vec_clear(F, n); _acb_vec_clear(B, n); mag_clear(eps); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-eig_multiple.c000066400000000000000000000150241461254215100210550ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_eig_multiple, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, R; acb_ptr E, F; acb_t b; slong i, j, n, prec, count, count2; int result; n = n_randint(state, 8); prec = 2 + n_randint(state, 200); acb_init(b); acb_mat_init(A, n, n); acb_mat_init(R, n, n); E = _acb_vec_init(n); F = _acb_vec_init(n); if (n_randint(state, 10) != 0) { for (i = 0; i < n; i++) acb_randtest(E + i, state, prec, 2); } else { /* Randomly repeat eigenvalues. */ for (i = 0; i < n; i++) { if (i == 0 || n_randint(state, 2)) acb_randtest(E + i, state, prec, 2); else acb_set(E + i, E + n_randint(state, i)); } } if (n_randint(state, 2)) { for (i = 0; i < n; i++) acb_get_mid(E + i, E + i); } acb_mat_randtest_eig(A, state, E, prec); acb_mat_approx_eig_qr(F, NULL, R, A, NULL, 0, prec); /* Perturb F further. */ if (n_randint(state, 10) == 0) { for (i = 0; i < n; i++) { acb_randtest(b, state, prec, 1); acb_mul_2exp_si(b, b, -n_randint(state, prec)); acb_add(F + i, F + i, b, prec); } } /* Perturb R further. */ if (n_randint(state, 10) == 0) { j = n_randint(state, n); for (i = 0; i < n; i++) { acb_randtest(b, state, prec, 1); acb_mul_2exp_si(b, b, -10 - n_randint(state, prec)); acb_add(acb_mat_entry(R, i, j), acb_mat_entry(R, i, j), b, prec); } } if (n_randint(state, 2)) result = acb_mat_eig_multiple_rump(F, A, E, R, prec); else result = acb_mat_eig_multiple(F, A, E, R, prec); if (result) { count = 0; count2 = 0; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j == 0 || !acb_equal(F + j, F + j - 1)) count += acb_contains(F + j, E + i); } for (j = 0; j < n; j++) { if (j == 0 || !acb_equal(F + j, F + j - 1)) count2 += acb_overlaps(F + j, E + i); } } if (count != n || count2 != n) { flint_printf("FAIL: count\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("count = %wd, count2 = %wd\n\n", count, count2); flint_printf("E = \n"); for (j = 0; j < n; j++) { acb_printd(E + j, 20); flint_printf("\n"); } flint_printf("F = \n"); for (j = 0; j < n; j++) { acb_printd(F + j, 20); flint_printf("\n"); } flint_abort(); } } acb_mat_clear(A); acb_mat_clear(R); _acb_vec_clear(E, n); _acb_vec_clear(F, n); acb_clear(b); } /* Test convergence for DFT matrices */ for (iter = 0; iter < 50 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, R, QC; acb_ptr E; acb_t t; fmpq_mat_t Q, Qinv; slong i, n, c0, c1, c2, c3; slong prec; int algorithm, result; n = n_randint(state, 30); algorithm = n_randint(state, 2); acb_mat_init(A, n, n); acb_mat_init(R, n, n); E = _acb_vec_init(n); acb_init(t); acb_mat_init(QC, n, n); fmpq_mat_init(Q, n, n); fmpq_mat_init(Qinv, n, n); /* The current algorithm is not robust enough. */ #if 0 do { fmpq_mat_randtest(Q, state, 2 + n_randint(state, 10)); } while (!fmpq_mat_inv(Qinv, Q)); #else fmpq_mat_one(Q); fmpq_mat_one(Qinv); #endif for (prec = 32; ; prec *= 2) { if (prec > 10000) { flint_printf("FAIL: unsuccessful, prec > 10000\n\n"); flint_printf("algorithm = %d, iter %wd\n\n", algorithm, iter); flint_abort(); } acb_mat_dft(A, 0, prec); #if 0 acb_mat_set_fmpq_mat(QC, Q, prec); acb_mat_mul(A, A, QC, prec); acb_mat_set_fmpq_mat(QC, Qinv, prec); acb_mat_mul(A, QC, A, prec); #endif acb_mat_approx_eig_qr(E, NULL, R, A, NULL, 0, prec); if (algorithm == 0) result = acb_mat_eig_multiple_rump(E, A, E, R, prec); else result = acb_mat_eig_multiple(E, A, E, R, prec); /* Verify the known eigenvalues + multiplicities */ if (result) { c0 = c1 = c2 = c3 = 0; for (i = 0; i < n; i++) { acb_set_d_d(t, 1.0, 0.0); c0 += acb_contains(E + i, t); acb_set_d_d(t, -1.0, 0.0); c1 += acb_contains(E + i, t); acb_set_d_d(t, 0.0, 1.0); c2 += acb_contains(E + i, t); acb_set_d_d(t, 0.0, -1.0); c3 += acb_contains(E + i, t); } result = (n == 0 || (c0 == (n+4)/4 && c1 == (n+2)/4 && c2 == (n-1)/4 && c3 == (n+1)/4)); } if (result) break; } acb_mat_clear(A); acb_mat_clear(R); acb_mat_clear(QC); _acb_vec_clear(E, n); acb_clear(t); fmpq_mat_clear(Q); fmpq_mat_clear(Qinv); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-eig_simple.c000066400000000000000000000234261461254215100205200ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_poly.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_eig_simple, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, L, R, LAR, D; acb_ptr E, F; acb_t b; slong i, j, n, prec, count, count2; int result, algorithm; n = n_randint(state, 8); prec = 2 + n_randint(state, 200); algorithm = n_randint(state, 3); acb_mat_init(A, n, n); acb_mat_init(L, n, n); acb_mat_init(R, n, n); acb_mat_init(LAR, n, n); acb_mat_init(D, n, n); acb_init(b); E = _acb_vec_init(n); F = _acb_vec_init(n); if (n_randint(state, 10) != 0) { for (i = 0; i < n; i++) acb_randtest(E + i, state, prec, 2); } else { /* Randomly repeat eigenvalues. */ for (i = 0; i < n; i++) { if (i == 0 || n_randint(state, 2)) acb_randtest(E + i, state, prec, 2); else acb_set(E + i, E + n_randint(state, i)); } } if (n_randint(state, 2)) { for (i = 0; i < n; i++) acb_get_mid(E + i, E + i); } acb_mat_randtest_eig(A, state, E, prec); acb_mat_approx_eig_qr(F, NULL, R, A, NULL, 0, prec); /* Perturb F further. */ if (n_randint(state, 10) == 0) { for (i = 0; i < n; i++) { acb_randtest(b, state, prec, 1); acb_mul_2exp_si(b, b, -n_randint(state, prec)); acb_add(F + i, F + i, b, prec); } } /* Perturb R further. */ if (n_randint(state, 10) == 0) { j = n_randint(state, n); for (i = 0; i < n; i++) { acb_randtest(b, state, prec, 1); acb_mul_2exp_si(b, b, -10 - n_randint(state, prec)); acb_add(acb_mat_entry(R, i, j), acb_mat_entry(R, i, j), b, prec); } } if (n_randint(state, 2)) { if (algorithm == 0) result = acb_mat_eig_simple(F, L, R, A, E, R, prec); else if (algorithm == 1) result = acb_mat_eig_simple_rump(F, L, R, A, E, R, prec); else result = acb_mat_eig_simple_vdhoeven_mourrain(F, L, R, A, E, R, prec); } else { int r1, r2; if (algorithm == 0) { r1 = acb_mat_eig_simple(F, L, NULL, A, E, R, prec); r2 = acb_mat_eig_simple(F, NULL, R, A, E, R, prec); } else if (algorithm == 1) { r1 = acb_mat_eig_simple_rump(F, L, NULL, A, E, R, prec); r2 = acb_mat_eig_simple_rump(F, NULL, R, A, E, R, prec); } else { r1 = acb_mat_eig_simple_vdhoeven_mourrain(F, L, NULL, A, E, R, prec); r2 = acb_mat_eig_simple_vdhoeven_mourrain(F, NULL, R, A, E, R, prec); } result = n_randint(state, 2) ? r1 : r2; } acb_mat_mul(LAR, L, A, prec); acb_mat_mul(LAR, LAR, R, prec); for (i = 0; i < n; i++) acb_set(acb_mat_entry(D, i, i), F + i); if (!acb_mat_overlaps(LAR, D)) { flint_printf("FAIL: overlap\n\n"); flint_printf("algorithm = %d\n\n", algorithm); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("L = \n"); acb_mat_printd(L, 20); flint_printf("\n\n"); flint_printf("D = \n"); acb_mat_printd(D, 20); flint_printf("\n\n"); flint_printf("LAR = \n"); acb_mat_printd(LAR, 20); flint_printf("\n\n"); flint_abort(); } if (result) { for (i = 0; i < n; i++) { count = 0; for (j = 0; j < n; j++) count += acb_contains(F + i, E + j); count2 = 0; for (j = 0; j < n; j++) count2 += acb_overlaps(F + i, E + j); if (count != 1 || count2 != 1) { flint_printf("FAIL: count\n\n"); flint_printf("algorithm = %d\n\n", algorithm); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("L = \n"); acb_mat_printd(L, 20); flint_printf("\n\n"); flint_printf("D = \n"); acb_mat_printd(D, 20); flint_printf("\n\n"); flint_printf("LAR = \n"); acb_mat_printd(LAR, 20); flint_printf("\n\n"); flint_printf("i = %wd, count = %wd, count2 = %wd\n\n", i, count, count2); flint_abort(); } } } acb_mat_clear(A); acb_mat_clear(L); acb_mat_clear(R); acb_mat_clear(LAR); acb_mat_clear(D); acb_clear(b); _acb_vec_clear(E, n); _acb_vec_clear(F, n); } /* Test convergence, given companion matrices */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, R, QC; acb_ptr E; acb_ptr roots; fmpq_mat_t Q, Qinv; acb_poly_t f; slong i, j, n, prec, count, count2; int algorithm, success; algorithm = n_randint(state, 3); n = n_randint(state, 10); roots = _acb_vec_init(n); E = _acb_vec_init(n); acb_poly_init(f); acb_mat_init(A, n, n); acb_mat_init(R, n, n); fmpq_mat_init(Q, n, n); fmpq_mat_init(Qinv, n, n); acb_mat_init(QC, n, n); for (i = 0; i < n; i++) { new_root: acb_randtest(roots + i, state, 2 + n_randint(state, 100), 4); acb_get_mid(roots + i, roots + i); for (j = 0; j < i; j++) if (acb_equal(roots + i, roots + j)) goto new_root; } do { fmpq_mat_randtest(Q, state, 2 + n_randint(state, 100)); } while (!fmpq_mat_inv(Qinv, Q)); success = 0; for (prec = 32; !success; prec *= 2) { if (prec > 10000) { flint_printf("FAIL: unsuccessful, prec > 10000\n\n"); flint_printf("algorithm = %d, iter %wd\n\n", algorithm, iter); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("roots = \n"); for (j = 0; j < n; j++) { acb_printd(roots + j, 20); flint_printf("\n"); } flint_abort(); } acb_poly_product_roots(f, roots, n, prec); acb_mat_companion(A, f, prec); acb_mat_set_fmpq_mat(QC, Q, prec); acb_mat_mul(A, A, QC, prec); acb_mat_set_fmpq_mat(QC, Qinv, prec); acb_mat_mul(A, QC, A, prec); acb_mat_approx_eig_qr(E, NULL, R, A, NULL, 0, prec); if (algorithm == 0) success = acb_mat_eig_simple(E, NULL, NULL, A, E, R, prec); else if (algorithm == 1) success = acb_mat_eig_simple_rump(E, NULL, NULL, A, E, R, prec); else success = acb_mat_eig_simple_vdhoeven_mourrain(E, NULL, NULL, A, E, R, prec); if (success) { for (i = 0; i < n; i++) { count = 0; for (j = 0; j < n; j++) count += acb_contains(E + i, roots + j); count2 = 0; for (j = 0; j < n; j++) count2 += acb_overlaps(E + i, roots + j); if (count != 1 || count2 != 1) { flint_printf("FAIL: count\n\n"); flint_printf("algorithm = %d\n\n", algorithm); flint_printf("A = \n"); acb_mat_printd(A, 20); flint_printf("\n\n"); flint_printf("R = \n"); acb_mat_printd(R, 20); flint_printf("\n\n"); flint_printf("i = %wd, count = %wd, count2 = %wd\n\n", i, count, count2); flint_printf("roots = \n"); for (j = 0; j < n; j++) { acb_printd(roots + j, 20); flint_printf("\n"); } flint_printf("E = \n"); for (j = 0; j < n; j++) { acb_printd(E + j, 20); flint_printf("\n"); } flint_abort(); } } } } fmpq_mat_clear(Q); fmpq_mat_clear(Qinv); acb_mat_clear(QC); acb_mat_clear(A); acb_mat_clear(R); acb_poly_clear(f); _acb_vec_clear(roots, n); _acb_vec_clear(E, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-exp.c000066400000000000000000000056271461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" void _fmpq_mat_randtest_for_exp(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong i, j; slong d, l, u; d = n_randint(state, 5); l = n_randint(state, 5); u = n_randint(state, 5); fmpq_mat_zero(mat); for (i = 0; i < fmpq_mat_nrows(mat); i++) { for (j = 0; j < fmpq_mat_ncols(mat); j++) { if ((i == j && d) || (i < j && u) || (i > j && l)) { fmpq_randtest(fmpq_mat_entry(mat, i, j), state, bits); } } } } TEST_FUNCTION_START(acb_mat_exp, state) { slong iter; /* check exp(A)*exp(c*A) = exp((1+c)*A) */ for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, E, F, EF, G; fmpq_mat_t Q; acb_t c, d; slong n, qbits, prec; n = n_randint(state, 5); qbits = 2 + n_randint(state, 300); prec = 2 + n_randint(state, 300); acb_init(c); acb_init(d); fmpq_mat_init(Q, n, n); acb_mat_init(A, n, n); acb_mat_init(E, n, n); acb_mat_init(F, n, n); acb_mat_init(EF, n, n); acb_mat_init(G, n, n); _fmpq_mat_randtest_for_exp(Q, state, qbits); acb_mat_set_fmpq_mat(A, Q, prec); acb_mat_exp(E, A, prec); acb_randtest(c, state, prec, 10); acb_mat_scalar_mul_acb(F, A, c, prec); acb_mat_exp(F, F, prec); acb_add_ui(d, c, 1, prec); acb_mat_scalar_mul_acb(G, A, d, prec); acb_mat_exp(G, G, prec); acb_mat_mul(EF, E, F, prec); if (!acb_mat_overlaps(EF, G)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("c = \n"); acb_printd(c, 15); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("E = \n"); acb_mat_printd(E, 15); flint_printf("\n\n"); flint_printf("F = \n"); acb_mat_printd(F, 15); flint_printf("\n\n"); flint_printf("E*F = \n"); acb_mat_printd(EF, 15); flint_printf("\n\n"); flint_printf("G = \n"); acb_mat_printd(G, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(c); acb_clear(d); fmpq_mat_clear(Q); acb_mat_clear(A); acb_mat_clear(E); acb_mat_clear(F); acb_mat_clear(EF); acb_mat_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-exp_taylor_sum.c000066400000000000000000000042761461254215100214570ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_exp_taylor_sum, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, S1, S2, S3; fmpz_t f; slong n, N, prec1, prec2; n = n_randint(state, 5); N = n_randint(state, 40); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); acb_mat_init(A, n, n); acb_mat_init(S1, n, n); acb_mat_init(S2, n, n); acb_mat_init(S3, n, n); fmpz_init(f); acb_mat_randtest(A, state, prec1, 10); acb_mat_randtest(S1, state, prec1, 10); acb_mat_randtest(S2, state, prec1, 10); acb_mat_exp_taylor_sum(S1, A, N, prec1); acb_mat_exp_taylor_sum(S2, A, N + 1, prec2); acb_mat_pow_ui(S3, A, N, prec2); fmpz_fac_ui(f, N); acb_mat_scalar_div_fmpz(S3, S3, f, prec2); acb_mat_add(S3, S3, S1, prec2); if (!acb_mat_overlaps(S2, S3)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, N = %wd\n", n, N); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("S1 = \n"); acb_mat_printd(S1, 15); flint_printf("\n\n"); flint_printf("S2 = \n"); acb_mat_printd(S2, 15); flint_printf("\n\n"); flint_printf("S3 = \n"); acb_mat_printd(S3, 15); flint_printf("\n\n"); flint_abort(); } acb_mat_exp_taylor_sum(A, A, N, prec1); if (!acb_mat_overlaps(A, S1)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(S1); acb_mat_clear(S2); acb_mat_clear(S3); fmpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-frobenius_norm.c000066400000000000000000000166511461254215100214340ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" static void _acb_mat_set_fmpq_mat_fmpq_mat(acb_mat_t C, const fmpq_mat_t rsrc, const fmpq_mat_t isrc, slong prec) { slong i, j; for (i = 0; i < acb_mat_nrows(C); i++) { for (j = 0; j < acb_mat_ncols(C); j++) { arb_set_fmpq(acb_realref(acb_mat_entry(C, i, j)), fmpq_mat_entry(rsrc, i, j), prec); arb_set_fmpq(acb_imagref(acb_mat_entry(C, i, j)), fmpq_mat_entry(isrc, i, j), prec); } } } static void _acb_mat_conjugate_transpose(acb_mat_t B, const acb_mat_t A) { slong i, j; acb_mat_transpose(B, A); for (i = 0; i < acb_mat_nrows(B); i++) for (j = 0; j < acb_mat_ncols(B); j++) acb_conj(acb_mat_entry(B, i, j), acb_mat_entry(B, i, j)); } static void _fmpq_mat_sum_of_squares(fmpq_t res, const fmpq_mat_t Q) { slong i, j; fmpq_zero(res); for (i = 0; i < fmpq_mat_nrows(Q); i++) { for (j = 0; j < fmpq_mat_ncols(Q); j++) { fmpq_addmul(res, fmpq_mat_entry(Q, i, j), fmpq_mat_entry(Q, i, j)); } } } TEST_FUNCTION_START(acb_mat_frobenius_norm, state) { slong iter; /* compare to the exact rational norm */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Qr, Qi; fmpq_t q; acb_mat_t A; slong n, qbits, prec; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 200); fmpq_mat_init(Qr, n, n); fmpq_mat_init(Qi, n, n); fmpq_init(q); acb_mat_init(A, n, n); fmpq_mat_randtest(Qr, state, qbits); fmpq_mat_randtest(Qi, state, qbits); /* compute the square of the exact rational norm */ { fmpq_t qr, qi; fmpq_init(qr); fmpq_init(qi); _fmpq_mat_sum_of_squares(qr, Qr); _fmpq_mat_sum_of_squares(qi, Qi); fmpq_add(q, qr, qi); fmpq_clear(qr); fmpq_clear(qi); } _acb_mat_set_fmpq_mat_fmpq_mat(A, Qr, Qi, prec); /* check that the arb interval contains the exact value */ { arb_t a; arb_init(a); acb_mat_frobenius_norm(a, A, prec); arb_mul(a, a, a, prec); if (!arb_contains_fmpq(a, q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Qr = \n"); fmpq_mat_print(Qr); flint_printf("\n\n"); flint_printf("Qi = \n"); fmpq_mat_print(Qi); flint_printf("\n\n"); flint_printf("frobenius_norm(Q)^2 = \n"); fmpq_print(q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("frobenius_norm(A)^2 = \n"); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("frobenius_norm(A)^2 = \n"); arb_print(a); flint_printf("\n\n"); flint_abort(); } arb_clear(a); } /* check that the upper bound is not less than the exact value */ { mag_t b; fmpq_t y; mag_init(b); fmpq_init(y); acb_mat_bound_frobenius_norm(b, A); mag_mul(b, b, b); mag_get_fmpq(y, b); if (fmpq_cmp(q, y) > 0) { flint_printf("FAIL (bound, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Qr = \n"); fmpq_mat_print(Qr); flint_printf("\n\n"); flint_printf("Qi = \n"); fmpq_mat_print(Qi); flint_printf("\n\n"); flint_printf("frobenius_norm(Q)^2 = \n"); fmpq_print(q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("bound_frobenius_norm(A)^2 = \n"); mag_printd(b, 15); flint_printf("\n\n"); flint_printf("bound_frobenius_norm(A)^2 = \n"); mag_print(b); flint_printf("\n\n"); flint_abort(); } mag_clear(b); fmpq_clear(y); } fmpq_mat_clear(Qr); fmpq_mat_clear(Qi); fmpq_clear(q); acb_mat_clear(A); } /* check trace(A^H A) = frobenius_norm(A)^2 */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, prec; acb_mat_t A, AH, AHA; acb_t t; prec = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); acb_mat_init(A, m, n); acb_mat_init(AH, n, m); acb_mat_init(AHA, n, n); acb_init(t); acb_mat_randtest(A, state, 2 + n_randint(state, 100), 10); _acb_mat_conjugate_transpose(AH, A); acb_mat_mul(AHA, AH, A, prec); acb_mat_trace(t, AHA, prec); acb_sqrt(t, t, prec); /* check the norm bound */ { mag_t low, frobenius; mag_init(low); acb_get_mag_lower(low, t); mag_init(frobenius); acb_mat_bound_frobenius_norm(frobenius, A); if (mag_cmp(low, frobenius) > 0) { flint_printf("FAIL (frobenius norm bound)\n", iter); flint_printf("m = %wd, n = %wd, prec = %wd\n", m, n, prec); flint_printf("\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("lower(sqrt(trace(A^H A))) = \n"); mag_printd(low, 15); flint_printf("\n\n"); flint_printf("bound_frobenius_norm(A) = \n"); mag_printd(frobenius, 15); flint_printf("\n\n"); flint_abort(); } mag_clear(low); mag_clear(frobenius); } /* check the norm interval */ { arb_t frobenius; arb_init(frobenius); acb_mat_frobenius_norm(frobenius, A, prec); if (!arb_overlaps(acb_realref(t), frobenius)) { flint_printf("FAIL (frobenius norm overlap)\n", iter); flint_printf("m = %wd, n = %wd, prec = %wd\n", m, n, prec); flint_printf("\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("sqrt(trace(A^H A)) = \n"); acb_printd(t, 15); flint_printf("\n\n"); flint_printf("frobenius_norm(A) = \n"); arb_printd(frobenius, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(frobenius); } acb_mat_clear(A); acb_mat_clear(AH); acb_mat_clear(AHA); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-inv.c000066400000000000000000000073151461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_inv, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, Qinv; acb_mat_t A, Ainv; slong n, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(Qinv, n, n); acb_mat_init(A, n, n); acb_mat_init(Ainv, n, n); fmpq_mat_randtest(Q, state, qbits); q_invertible = fmpq_mat_inv(Qinv, Q); if (!q_invertible) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_inv(Ainv, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); acb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_inv(Ainv, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!acb_mat_contains_fmpq_mat(Ainv, Qinv)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qinv = \n"); fmpq_mat_print(Qinv); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); acb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = acb_mat_inv(A, A, prec); if (!acb_mat_equal(A, Ainv) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); acb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(Qinv); acb_mat_clear(A); acb_mat_clear(Ainv); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-lu.c000066400000000000000000000105101461254215100170110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" /* Defined in t-lu.c and t-lu_recursive.c */ #ifndef fmpq_mat_is_invertible #define fmpq_mat_is_invertible fmpq_mat_is_invertible int fmpq_mat_is_invertible(const fmpq_mat_t A) { int r; fmpq_t t; fmpq_init(t); fmpq_mat_det(t, A); r = !fmpq_is_zero(t); fmpq_clear(t); return r; } #endif TEST_FUNCTION_START(acb_mat_lu, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; acb_mat_t A, LU, P, L, U, T; slong i, j, n, qbits, prec, *perm; int q_invertible, r_invertible; n = n_randint(state, 10); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); acb_mat_init(A, n, n); acb_mat_init(LU, n, n); acb_mat_init(P, n, n); acb_mat_init(L, n, n); acb_mat_init(U, n, n); acb_mat_init(T, n, n); perm = _perm_init(n); fmpq_mat_randtest(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_lu(perm, LU, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); acb_mat_printd(LU, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_lu(perm, LU, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_abort(); } prec *= 2; } } acb_mat_one(L); for (i = 0; i < n; i++) for (j = 0; j < i; j++) acb_set(acb_mat_entry(L, i, j), acb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) for (j = i; j < n; j++) acb_set(acb_mat_entry(U, i, j), acb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) acb_one(acb_mat_entry(P, perm[i], i)); acb_mat_mul(T, P, L, prec); acb_mat_mul(T, T, U, prec); if (!acb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); acb_mat_printd(LU, 15); flint_printf("\n\n"); flint_printf("L = \n"); acb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); acb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("P*L*U = \n"); acb_mat_printd(T, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); acb_mat_clear(A); acb_mat_clear(LU); acb_mat_clear(P); acb_mat_clear(L); acb_mat_clear(U); acb_mat_clear(T); _perm_clear(perm); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-lu_recursive.c000066400000000000000000000123471461254215100211120ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" /* Defined in t-lu.c and t-lu_recursive.c */ #ifndef fmpq_mat_is_invertible #define fmpq_mat_is_invertible fmpq_mat_is_invertible int fmpq_mat_is_invertible(const fmpq_mat_t A) { int r; fmpq_t t; fmpq_init(t); fmpq_mat_det(t, A); r = !fmpq_is_zero(t); fmpq_clear(t); return r; } #endif TEST_FUNCTION_START(acb_mat_lu_recursive, state) { slong iter; /* Dummy test with rectangular matrices. Rectangular matrices are not actually supported (the output may be bogus), but the algorithm should at least not crash. */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, prec; slong *perm; acb_mat_t A, LU; n = n_randint(state, 20); m = n_randint(state, 20); prec = 2 + n_randint(state, 200); acb_mat_init(A, n, m); acb_mat_init(LU, n, m); perm = _perm_init(n); acb_mat_randtest(A, state, prec, 10); if (n_randint(state, 2)) { acb_mat_lu_recursive(perm, LU, A, prec); } else { acb_mat_set(LU, A); acb_mat_lu_recursive(perm, LU, LU, prec); } acb_mat_clear(A); acb_mat_clear(LU); _perm_clear(perm); } for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; acb_mat_t A, LU, P, L, U, T; slong i, j, n, qbits, prec, *perm; int q_invertible, r_invertible; n = n_randint(state, 20); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); acb_mat_init(A, n, n); acb_mat_init(LU, n, n); acb_mat_init(P, n, n); acb_mat_init(L, n, n); acb_mat_init(U, n, n); acb_mat_init(T, n, n); perm = _perm_init(n); fmpq_mat_randtest(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_lu_recursive(perm, LU, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); acb_mat_printd(LU, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_lu_recursive(perm, LU, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_abort(); } prec *= 2; } } acb_mat_one(L); for (i = 0; i < n; i++) for (j = 0; j < i; j++) acb_set(acb_mat_entry(L, i, j), acb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) for (j = i; j < n; j++) acb_set(acb_mat_entry(U, i, j), acb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) acb_one(acb_mat_entry(P, perm[i], i)); acb_mat_mul(T, P, L, prec); acb_mat_mul(T, T, U, prec); if (!acb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); acb_mat_printd(LU, 15); flint_printf("\n\n"); flint_printf("L = \n"); acb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); acb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("P*L*U = \n"); acb_mat_printd(T, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); acb_mat_clear(A); acb_mat_clear(LU); acb_mat_clear(P); acb_mat_clear(L); acb_mat_clear(U); acb_mat_clear(T); _perm_clear(perm); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-mul.c000066400000000000000000000215071461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" /* Defined in t-mul.c and t-mul_reorder.c */ #ifndef _acb_mat_init_randtest #define _acb_mat_init_randtest _acb_mat_init_randtest void _acb_mat_init_randtest(acb_mat_t mat, slong r, slong c, flint_rand_t state) { acb_mat_init(mat, r, c); acb_mat_randtest(mat, state, 2 + n_randint(state, 200), 10); } #endif /* Defined in t-mul.c and t-mul_reorder.c */ #ifndef _acb_mat_nprintd #define _acb_mat_nprintd _acb_mat_nprintd void _acb_mat_nprintd(const char * name, acb_mat_t mat) { flint_printf("%s = ", name); acb_mat_printd(mat, 15); flint_printf("\n\n"); } #endif TEST_FUNCTION_START(acb_mat_mul, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; acb_mat_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, k); fmpq_mat_init(C, m, k); acb_mat_init(a, m, n); acb_mat_init(b, n, k); acb_mat_init(c, m, k); acb_mat_init(d, m, k); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); fmpq_mat_mul(C, A, B); acb_mat_set_fmpq_mat(a, A, rbits1); acb_mat_set_fmpq_mat(b, B, rbits2); acb_mat_mul(c, a, b, rbits3); if (!acb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd, k = %wd, bits3 = %wd\n", m, n, k, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (acb_mat_nrows(a) == acb_mat_nrows(c) && acb_mat_ncols(a) == acb_mat_ncols(c)) { acb_mat_set(d, a); acb_mat_mul(d, d, b, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (acb_mat_nrows(b) == acb_mat_nrows(c) && acb_mat_ncols(b) == acb_mat_ncols(c)) { acb_mat_set(d, b); acb_mat_mul(d, a, d, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); } /* check algebraic properties like associativity and distributivity */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, l; slong rbits; acb_mat_t a, b, c, d, ab, ac, bd, cd, s; rbits = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); l = n_randint(state, 10); _acb_mat_init_randtest(a, m, n, state); _acb_mat_init_randtest(b, n, k, state); _acb_mat_init_randtest(c, n, k, state); _acb_mat_init_randtest(d, k, l, state); acb_mat_init(ab, m, k); acb_mat_init(ac, m, k); acb_mat_init(bd, n, l); acb_mat_init(cd, n, l); acb_mat_init(s, n, k); acb_mat_mul(ab, a, b, rbits); acb_mat_mul(ac, a, c, rbits); acb_mat_mul(bd, b, d, rbits); acb_mat_mul(cd, c, d, rbits); acb_mat_add(s, b, c, rbits); /* check associativity of multiplication */ /* (A*B)*D = A*(B*D) */ { acb_mat_t lhs, rhs; acb_mat_init(lhs, m, l); acb_mat_init(rhs, m, l); acb_mat_mul(lhs, ab, d, rbits); acb_mat_mul(rhs, a, bd, rbits); if (!acb_mat_overlaps(lhs, rhs)) { flint_printf("FAIL\n\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("a", a); _acb_mat_nprintd("b", b); _acb_mat_nprintd("d", d); _acb_mat_nprintd("(a*b)*d", lhs); _acb_mat_nprintd("a*(b*d)", rhs); flint_abort(); } acb_mat_clear(lhs); acb_mat_clear(rhs); } /* check left distributivity of multiplication over addition */ /* A*(B + C) = A*B + A*C */ { acb_mat_t lhs, rhs; acb_mat_init(lhs, m, k); acb_mat_init(rhs, m, k); acb_mat_mul(lhs, a, s, rbits); acb_mat_add(rhs, ab, ac, rbits); if (!acb_mat_overlaps(lhs, rhs)) { flint_printf("FAIL\n\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("a", a); _acb_mat_nprintd("b", b); _acb_mat_nprintd("c", c); _acb_mat_nprintd("a*(b + c)", lhs); _acb_mat_nprintd("a*b + b*c", rhs); flint_abort(); } acb_mat_clear(lhs); acb_mat_clear(rhs); } /* check right distributivity of multiplication over addition */ /* (B + C)*D = B*D + C*D */ { acb_mat_t lhs, rhs; acb_mat_init(lhs, n, l); acb_mat_init(rhs, n, l); acb_mat_mul(lhs, s, d, rbits); acb_mat_add(rhs, bd, cd, rbits); if (!acb_mat_overlaps(lhs, rhs)) { flint_printf("FAIL\n\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("b", b); _acb_mat_nprintd("c", c); _acb_mat_nprintd("d", d); _acb_mat_nprintd("(b + c)*d", lhs); _acb_mat_nprintd("b*d + c*d", rhs); flint_abort(); } acb_mat_clear(lhs); acb_mat_clear(rhs); } /* check left multiplicative identity I*D = D */ { acb_mat_t one, lhs; acb_mat_init(one, k, k); acb_mat_init(lhs, k, l); acb_mat_one(one); acb_mat_mul(lhs, one, d, rbits); if (!acb_mat_contains(lhs, d)) { flint_printf("FAIL\n\n"); flint_printf("k = %wd, l = %wd\n", k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("identity * d", lhs); _acb_mat_nprintd("d", d); flint_abort(); } acb_mat_clear(one); acb_mat_clear(lhs); } /* check right multiplicative identity A*I = A */ { acb_mat_t one, lhs; acb_mat_init(one, n, n); acb_mat_init(lhs, m, n); acb_mat_one(one); acb_mat_mul(lhs, a, one, rbits); if (!acb_mat_contains(lhs, a)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd\n", m, n); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("a * identity", lhs); _acb_mat_nprintd("a", a); flint_abort(); } acb_mat_clear(one); acb_mat_clear(lhs); } acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); acb_mat_clear(ab); acb_mat_clear(ac); acb_mat_clear(bd); acb_mat_clear(cd); acb_mat_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-mul_entrywise.c000066400000000000000000000067541461254215100213160ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" void _fmpq_mat_mul_entrywise(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) { slong i, j; for (i = 0; i < fmpq_mat_nrows(A); i++) { for (j = 0; j < fmpq_mat_ncols(A); j++) { fmpq_mul(fmpq_mat_entry(C, i, j), fmpq_mat_entry(A, i, j), fmpq_mat_entry(B, i, j)); } } } TEST_FUNCTION_START(acb_mat_mul_entrywise, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; acb_mat_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); acb_mat_init(a, m, n); acb_mat_init(b, m, n); acb_mat_init(c, m, n); acb_mat_init(d, m, n); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); _fmpq_mat_mul_entrywise(C, A, B); acb_mat_set_fmpq_mat(a, A, rbits1); acb_mat_set_fmpq_mat(b, B, rbits2); acb_mat_mul_entrywise(c, a, b, rbits3); if (!acb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd, bits3 = %wd\n", m, n, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (acb_mat_nrows(a) == acb_mat_nrows(c) && acb_mat_ncols(a) == acb_mat_ncols(c)) { acb_mat_set(d, a); acb_mat_mul_entrywise(d, d, b, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (acb_mat_nrows(b) == acb_mat_nrows(c) && acb_mat_ncols(b) == acb_mat_ncols(c)) { acb_mat_set(d, b); acb_mat_mul_entrywise(d, a, d, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-mul_reorder.c000066400000000000000000000255741461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2012, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" /* Defined in t-mul.c and t-mul_reorder.c */ #ifndef _acb_mat_init_randtest #define _acb_mat_init_randtest _acb_mat_init_randtest void _acb_mat_init_randtest(acb_mat_t mat, slong r, slong c, flint_rand_t state) { acb_mat_init(mat, r, c); acb_mat_randtest(mat, state, 2 + n_randint(state, 200), 10); } #endif /* Defined in t-mul.c and t-mul_reorder.c */ #ifndef _acb_mat_nprintd #define _acb_mat_nprintd _acb_mat_nprintd void _acb_mat_nprintd(const char * name, acb_mat_t mat) { flint_printf("%s = ", name); acb_mat_printd(mat, 15); flint_printf("\n\n"); } #endif TEST_FUNCTION_START(acb_mat_mul_reorder, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; acb_mat_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 8); n = n_randint(state, 8); k = n_randint(state, 8); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, k); fmpq_mat_init(C, m, k); acb_mat_init(a, m, n); acb_mat_init(b, n, k); _acb_mat_init_randtest(c, m, k, state); _acb_mat_init_randtest(d, m, k, state); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); fmpq_mat_mul(C, A, B); acb_mat_set_fmpq_mat(a, A, rbits1); acb_mat_set_fmpq_mat(b, B, rbits2); acb_mat_mul_reorder(c, a, b, rbits3); if (!acb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd, k = %wd, bits3 = %wd\n", m, n, k, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (acb_mat_nrows(a) == acb_mat_nrows(c) && acb_mat_ncols(a) == acb_mat_ncols(c)) { acb_mat_set(d, a); acb_mat_mul_reorder(d, d, b, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (acb_mat_nrows(b) == acb_mat_nrows(c) && acb_mat_ncols(b) == acb_mat_ncols(c)) { acb_mat_set(d, b); acb_mat_mul_reorder(d, a, d, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); } /* general aliasing test */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n; slong rbits; acb_mat_t a, b, c, d; rbits = 2 + n_randint(state, 200); m = n_randint(state, 8); n = n_randint(state, 8); _acb_mat_init_randtest(a, m, n, state); _acb_mat_init_randtest(b, n, n, state); _acb_mat_init_randtest(c, m, n, state); _acb_mat_init_randtest(d, m, n, state); acb_mat_mul_reorder(c, a, b, rbits); acb_mat_set(d, a); acb_mat_mul_reorder(d, d, b, rbits); if (!acb_mat_equal(c, d)) { flint_printf("FAIL (aliasing 3)\n\n"); _acb_mat_nprintd("a", a); _acb_mat_nprintd("b", b); _acb_mat_nprintd("c", d); _acb_mat_nprintd("d", d); flint_abort(); } acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); _acb_mat_init_randtest(a, m, m, state); _acb_mat_init_randtest(b, m, n, state); _acb_mat_init_randtest(c, m, n, state); _acb_mat_init_randtest(d, m, n, state); acb_mat_mul_reorder(c, a, b, rbits); acb_mat_set(d, b); acb_mat_mul_reorder(d, a, d, rbits); if (!acb_mat_equal(c, d)) { flint_printf("FAIL (aliasing 4)\n\n"); _acb_mat_nprintd("a", a); _acb_mat_nprintd("b", b); _acb_mat_nprintd("c", d); _acb_mat_nprintd("d", d); flint_abort(); } acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); } /* check algebraic properties like associativity and distributivity */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, l; slong rbits; acb_mat_t a, b, c, d, ab, ac, bd, cd, s; rbits = 2 + n_randint(state, 200); m = n_randint(state, 8); n = n_randint(state, 8); k = n_randint(state, 8); l = n_randint(state, 8); _acb_mat_init_randtest(a, m, n, state); _acb_mat_init_randtest(b, n, k, state); _acb_mat_init_randtest(c, n, k, state); _acb_mat_init_randtest(d, k, l, state); _acb_mat_init_randtest(ab, m, k, state); _acb_mat_init_randtest(ac, m, k, state); _acb_mat_init_randtest(bd, n, l, state); _acb_mat_init_randtest(cd, n, l, state); _acb_mat_init_randtest(s, n, k, state); acb_mat_mul_reorder(ab, a, b, rbits); acb_mat_mul_reorder(ac, a, c, rbits); acb_mat_mul_reorder(bd, b, d, rbits); acb_mat_mul_reorder(cd, c, d, rbits); acb_mat_add(s, b, c, rbits); /* check associativity of multiplication */ /* (A*B)*D = A*(B*D) */ { acb_mat_t lhs, rhs; _acb_mat_init_randtest(lhs, m, l, state); _acb_mat_init_randtest(rhs, m, l, state); acb_mat_mul_reorder(lhs, ab, d, rbits); acb_mat_mul_reorder(rhs, a, bd, rbits); if (!acb_mat_overlaps(lhs, rhs)) { flint_printf("FAIL\n\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("a", a); _acb_mat_nprintd("b", b); _acb_mat_nprintd("d", d); _acb_mat_nprintd("(a*b)*d", lhs); _acb_mat_nprintd("a*(b*d)", rhs); flint_abort(); } acb_mat_clear(lhs); acb_mat_clear(rhs); } /* check left distributivity of multiplication over addition */ /* A*(B + C) = A*B + A*C */ { acb_mat_t lhs, rhs; _acb_mat_init_randtest(lhs, m, k, state); _acb_mat_init_randtest(rhs, m, k, state); acb_mat_mul_reorder(lhs, a, s, rbits); acb_mat_add(rhs, ab, ac, rbits); if (!acb_mat_overlaps(lhs, rhs)) { flint_printf("FAIL\n\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("a", a); _acb_mat_nprintd("b", b); _acb_mat_nprintd("c", c); _acb_mat_nprintd("a*(b + c)", lhs); _acb_mat_nprintd("a*b + b*c", rhs); flint_abort(); } acb_mat_clear(lhs); acb_mat_clear(rhs); } /* check right distributivity of multiplication over addition */ /* (B + C)*D = B*D + C*D */ { acb_mat_t lhs, rhs; _acb_mat_init_randtest(lhs, n, l, state); _acb_mat_init_randtest(rhs, n, l, state); acb_mat_mul_reorder(lhs, s, d, rbits); acb_mat_add(rhs, bd, cd, rbits); if (!acb_mat_overlaps(lhs, rhs)) { flint_printf("FAIL\n\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("b", b); _acb_mat_nprintd("c", c); _acb_mat_nprintd("d", d); _acb_mat_nprintd("(b + c)*d", lhs); _acb_mat_nprintd("b*d + c*d", rhs); flint_abort(); } acb_mat_clear(lhs); acb_mat_clear(rhs); } /* check left multiplicative identity I*D = D */ { acb_mat_t one, lhs; _acb_mat_init_randtest(one, k, k, state); _acb_mat_init_randtest(lhs, k, l, state); acb_mat_one(one); acb_mat_mul_reorder(lhs, one, d, rbits); if (!acb_mat_contains(lhs, d)) { flint_printf("FAIL\n\n"); flint_printf("k = %wd, l = %wd\n", k, l); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("identity * d", lhs); _acb_mat_nprintd("d", d); flint_abort(); } acb_mat_clear(one); acb_mat_clear(lhs); } /* check right multiplicative identity A*I = A */ { acb_mat_t one, lhs; _acb_mat_init_randtest(one, n, n, state); _acb_mat_init_randtest(lhs, m, n, state); acb_mat_one(one); acb_mat_mul_reorder(lhs, a, one, rbits); if (!acb_mat_contains(lhs, a)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd\n", m, n); flint_printf("rbits = %wd\n", rbits); _acb_mat_nprintd("a * identity", lhs); _acb_mat_nprintd("a", a); flint_abort(); } acb_mat_clear(one); acb_mat_clear(lhs); } acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); acb_mat_clear(ab); acb_mat_clear(ac); acb_mat_clear(bd); acb_mat_clear(cd); acb_mat_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-mul_threaded.c000066400000000000000000000064021461254215100210330ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_mul_threaded, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; acb_mat_t a, b, c, d; flint_set_num_threads(1 + n_randint(state, 5)); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, k); fmpq_mat_init(C, m, k); acb_mat_init(a, m, n); acb_mat_init(b, n, k); acb_mat_init(c, m, k); acb_mat_init(d, m, k); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); fmpq_mat_mul(C, A, B); acb_mat_set_fmpq_mat(a, A, rbits1); acb_mat_set_fmpq_mat(b, B, rbits2); acb_mat_mul_threaded(c, a, b, rbits3); if (!acb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("threads = %d, m = %wd, n = %wd, k = %wd, bits3 = %wd\n", flint_get_num_threads(), m, n, k, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (acb_mat_nrows(a) == acb_mat_nrows(c) && acb_mat_ncols(a) == acb_mat_ncols(c)) { acb_mat_set(d, a); acb_mat_mul_threaded(d, d, b, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (acb_mat_nrows(b) == acb_mat_nrows(c) && acb_mat_ncols(b) == acb_mat_ncols(c)) { acb_mat_set(d, b); acb_mat_mul_threaded(d, a, d, rbits3); if (!acb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); acb_mat_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-set_real_imag.c000066400000000000000000000027131461254215100211720ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_set_real_imag, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong m, n; arb_mat_t re, im, x, y; acb_mat_t z; m = n_randint(state, 10); n = n_randint(state, 10); arb_mat_init(re, m, n); arb_mat_init(im, m, n); arb_mat_init(x, m, n); arb_mat_init(y, m, n); acb_mat_init(z, m, n); arb_mat_randtest(re, state, 2 + n_randint(state, 100), 10); arb_mat_randtest(im, state, 2 + n_randint(state, 100), 10); acb_mat_set_real_imag(z, re, im); acb_mat_get_real(x, z); acb_mat_get_imag(y, z); if (!arb_mat_equal(x, re) || !arb_mat_equal(y, im)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd\n", m, n); flint_abort(); } arb_mat_clear(re); arb_mat_clear(im); arb_mat_clear(x); arb_mat_clear(y); acb_mat_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-solve.c000066400000000000000000000107051461254215100175270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_solve, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; acb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 10); m = n_randint(state, 10); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); acb_mat_init(A, n, n); acb_mat_init(X, n, m); acb_mat_init(B, n, m); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_solve(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { acb_mat_set_fmpq_mat(A, Q, prec); acb_mat_set_fmpq_mat(B, QB, prec); r_invertible = acb_mat_solve(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!acb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = acb_mat_solve(B, A, B, prec); if (!acb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-solve_lu.c000066400000000000000000000107211461254215100202250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_solve_lu, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; acb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 10); m = n_randint(state, 10); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); acb_mat_init(A, n, n); acb_mat_init(X, n, m); acb_mat_init(B, n, m); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_solve_lu(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { acb_mat_set_fmpq_mat(A, Q, prec); acb_mat_set_fmpq_mat(B, QB, prec); r_invertible = acb_mat_solve_lu(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!acb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = acb_mat_solve_lu(B, A, B, prec); if (!acb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-solve_precond.c000066400000000000000000000134301461254215100212370ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_solve_precond, state) { slong iter; /* test random matrices, to test complex solving */ for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, X, B, Y; slong n, m, prec; n = n_randint(state, 10); m = n_randint(state, 10); acb_mat_init(A, n, n); acb_mat_init(X, n, m); acb_mat_init(B, n, m); acb_mat_init(Y, n, m); prec = 2 + n_randint(state, 200); acb_mat_randtest(A, state, 200, 1 + n_randint(state, 10)); acb_mat_randtest(X, state, 200, 1 + n_randint(state, 10)); acb_mat_randtest(Y, state, 200, 1 + n_randint(state, 10)); acb_mat_mul(B, A, X, prec); if (acb_mat_solve_precond(Y, A, B, prec)) { if (!acb_mat_contains(Y, X)) { flint_printf("FAIL: containment\n"); flint_printf("A = \n"); acb_mat_printd(A, 30); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(A, 30); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(A, 30); flint_printf("\n\n"); flint_printf("Y = \n"); acb_mat_printd(A, 30); flint_printf("\n\n"); flint_abort(); } } acb_mat_clear(A); acb_mat_clear(X); acb_mat_clear(B); acb_mat_clear(Y); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; acb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); m = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); acb_mat_init(A, n, n); acb_mat_init(X, n, m); acb_mat_init(B, n, m); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { acb_mat_set_fmpq_mat(A, Q, prec); r_invertible = acb_mat_solve_precond(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over C\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { acb_mat_set_fmpq_mat(A, Q, prec); acb_mat_set_fmpq_mat(B, QB, prec); r_invertible = acb_mat_solve_precond(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!acb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = acb_mat_solve_precond(B, A, B, prec); if (!acb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-solve_tril.c000066400000000000000000000057611461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_solve_tril, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, X, B, Y; slong rows, cols, prec, i, j; int unit; prec = 2 + n_randint(state, 200); if (n_randint(state, 10) == 0) { rows = n_randint(state, 60); cols = n_randint(state, 60); } else { rows = n_randint(state, 10); cols = n_randint(state, 10); } unit = n_randint(state, 2); acb_mat_init(A, rows, rows); acb_mat_init(B, rows, cols); acb_mat_init(X, rows, cols); acb_mat_init(Y, rows, cols); acb_mat_randtest(A, state, prec, 10); acb_mat_randtest(X, state, prec, 10); acb_mat_randtest(Y, state, prec, 10); for (i = 0; i < rows; i++) { if (unit) acb_one(acb_mat_entry(A, i, i)); else acb_set_ui(acb_mat_entry(A, i, i), 1 + n_randint(state, 100)); for (j = i + 1; j < rows; j++) acb_zero(acb_mat_entry(A, i, j)); } acb_mat_mul(B, A, X, prec); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) acb_set_ui(acb_mat_entry(A, i, i), 1 + n_randint(state, 100)); } /* Check Y = A^(-1) * (A * X) = X */ acb_mat_solve_tril(Y, A, B, unit, prec); if (!acb_mat_overlaps(Y, X)) { flint_printf("FAIL\n"); flint_printf("A = \n"); acb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); acb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } /* Check aliasing */ acb_mat_solve_tril(B, A, B, unit, prec); if (!acb_mat_equal(B, Y)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); acb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); acb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(X); acb_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-solve_triu.c000066400000000000000000000057521461254215100206000ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_solve_triu, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_mat_t A, X, B, Y; slong rows, cols, prec, i, j; int unit; prec = 2 + n_randint(state, 200); if (n_randint(state, 10) == 0) { rows = n_randint(state, 60); cols = n_randint(state, 60); } else { rows = n_randint(state, 10); cols = n_randint(state, 10); } unit = n_randint(state, 2); acb_mat_init(A, rows, rows); acb_mat_init(B, rows, cols); acb_mat_init(X, rows, cols); acb_mat_init(Y, rows, cols); acb_mat_randtest(A, state, prec, 10); acb_mat_randtest(X, state, prec, 10); acb_mat_randtest(Y, state, prec, 10); for (i = 0; i < rows; i++) { if (unit) acb_one(acb_mat_entry(A, i, i)); else acb_set_ui(acb_mat_entry(A, i, i), 1 + n_randint(state, 100)); for (j = 0; j < i; j++) acb_zero(acb_mat_entry(A, i, j)); } acb_mat_mul(B, A, X, prec); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) acb_set_ui(acb_mat_entry(A, i, i), 1 + n_randint(state, 100)); } /* Check Y = A^(-1) * (A * X) = X */ acb_mat_solve_triu(Y, A, B, unit, prec); if (!acb_mat_overlaps(Y, X)) { flint_printf("FAIL\n"); flint_printf("A = \n"); acb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); acb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } /* Check aliasing */ acb_mat_solve_triu(B, A, B, unit, prec); if (!acb_mat_equal(B, Y)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); acb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); acb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); acb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); acb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(X); acb_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-sqr.c000066400000000000000000000040161461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_sqr, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong n, qbits1, rbits1, rbits2; fmpq_mat_t A, B; acb_mat_t a, b, c; qbits1 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); n = n_randint(state, 10); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); acb_mat_init(a, n, n); acb_mat_init(b, n, n); acb_mat_init(c, n, n); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_mul(B, A, A); acb_mat_set_fmpq_mat(a, A, rbits1); acb_mat_sqr(b, a, rbits2); if (!acb_mat_contains_fmpq_mat(b, B)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, bits2 = %wd\n", n, rbits2); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("a = "); acb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_mat_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ acb_mat_set(c, a); acb_mat_sqr(c, c, rbits2); if (!acb_mat_equal(c, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-trace.c000066400000000000000000000071711461254215100175000ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_trace, state) { slong iter; /* check that the acb trace contains the fmpq trace */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; fmpq_t Qtrace; acb_mat_t A; acb_t Atrace; slong n, qbits, prec; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_init(Qtrace); acb_mat_init(A, n, n); acb_init(Atrace); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_trace(Qtrace, Q); acb_mat_set_fmpq_mat(A, Q, prec); acb_mat_trace(Atrace, A, prec); if (!acb_contains_fmpq(Atrace, Qtrace)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qtrace = \n"); fmpq_print(Qtrace); flint_printf("\n\n"); flint_printf("A = \n"); acb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Atrace = \n"); acb_printd(Atrace, 15); flint_printf("\n\n"); flint_printf("Atrace = \n"); acb_print(Atrace); flint_printf("\n\n"); flint_abort(); } fmpq_mat_clear(Q); fmpq_clear(Qtrace); acb_mat_clear(A); acb_clear(Atrace); } /* check trace(A*B) = trace(B*A) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, prec; acb_mat_t a, b, ab, ba; acb_t trab, trba; prec = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); acb_mat_init(a, m, n); acb_mat_init(b, n, m); acb_mat_init(ab, m, m); acb_mat_init(ba, n, n); acb_init(trab); acb_init(trba); acb_mat_randtest(a, state, 2 + n_randint(state, 100), 10); acb_mat_randtest(b, state, 2 + n_randint(state, 100), 10); acb_mat_mul(ab, a, b, prec); acb_mat_mul(ba, b, a, prec); acb_mat_trace(trab, ab, prec); acb_mat_trace(trba, ba, prec); if (!acb_overlaps(trab, trba)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("m = %wd, n = %wd, prec = %wd\n", m, n, prec); flint_printf("\n"); flint_printf("a = \n"); acb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = \n"); acb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("ab = \n"); acb_mat_printd(ab, 15); flint_printf("\n\n"); flint_printf("ba = \n"); acb_mat_printd(ba, 15); flint_printf("\n\n"); flint_printf("trace(ab) = \n"); acb_printd(trab, 15); flint_printf("\n\n"); flint_printf("trace(ba) = \n"); acb_printd(trba, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(trab); acb_clear(trba); acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(ab); acb_mat_clear(ba); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-transpose.c000066400000000000000000000031521461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_transpose, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n; acb_mat_t a, b, c; m = n_randint(state, 10); n = n_randint(state, 10); acb_mat_init(a, m, n); acb_mat_init(b, n, m); acb_mat_init(c, m, n); acb_mat_randtest(a, state, 2 + n_randint(state, 100), 10); acb_mat_randtest(b, state, 2 + n_randint(state, 100), 10); acb_mat_randtest(c, state, 2 + n_randint(state, 100), 10); acb_mat_transpose(b, a); acb_mat_transpose(c, b); if (!acb_mat_equal(c, a)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd\n", m, n); flint_abort(); } if (acb_mat_nrows(a) == acb_mat_ncols(a)) { acb_mat_transpose(c, a); acb_mat_transpose(a, a); if (!acb_mat_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } } acb_mat_clear(a); acb_mat_clear(b); acb_mat_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/test/t-vector_mul.c000066400000000000000000000031661461254215100205610ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" TEST_FUNCTION_START(acb_mat_vector_mul, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong nrow = n_randint(state, 10); slong ncol = n_randint(state, 10); slong bits = n_randint(state, 10); slong prec = 100 + n_randint(state, 200); acb_mat_t A, B; acb_ptr v, res, t; slong k; acb_mat_init(A, nrow, ncol); acb_mat_init(B, ncol, nrow); v = _acb_vec_init(ncol); res = _acb_vec_init(nrow); t = _acb_vec_init(nrow); acb_mat_randtest(A, state, prec, bits); for (k = 0; k < ncol; k++) { acb_randtest_precise(&v[k], state, prec, bits); } /* Test: should be equal for transpose */ acb_mat_vector_mul_col(res, A, v, prec); acb_mat_transpose(B, A); acb_mat_vector_mul_row(t, v, B, prec); if (!_acb_vec_overlaps(res, t, nrow)) { flint_printf("FAIL\n"); flint_abort(); } acb_mat_clear(A); acb_mat_clear(B); _acb_vec_clear(v, ncol); _acb_vec_clear(res, nrow); _acb_vec_clear(t, nrow); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_mat/trace.c000066400000000000000000000015361461254215100162570ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_trace(acb_t trace, const acb_mat_t mat, slong prec) { slong i; if (!acb_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "acb_mat_trace: a square matrix is required!\n"); } if (acb_mat_is_empty(mat)) { acb_zero(trace); return; } acb_set(trace, acb_mat_entry(mat, 0, 0)); for (i = 1; i < acb_mat_nrows(mat); i++) { acb_add(trace, trace, acb_mat_entry(mat, i, i), prec); } } flint-3.1.3/src/acb_mat/transpose.c000066400000000000000000000023271461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_transpose(acb_mat_t B, const acb_mat_t A) { slong i, j; if (acb_mat_nrows(B) != acb_mat_ncols(A) || acb_mat_ncols(B) != acb_mat_nrows(A)) { flint_throw(FLINT_ERROR, "Exception (acb_mat_transpose). Incompatible dimensions.\n"); } if (acb_mat_is_empty(A)) return; if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < acb_mat_nrows(A) - 1; i++) { for (j = i + 1; j < acb_mat_ncols(A); j++) { acb_swap(acb_mat_entry(A, i, j), acb_mat_entry(A, j, i)); } } } else /* Not aliased; general case */ { for (i = 0; i < acb_mat_nrows(B); i++) for (j = 0; j < acb_mat_ncols(B); j++) acb_set(acb_mat_entry(B, i, j), acb_mat_entry(A, j, i)); } } flint-3.1.3/src/acb_mat/vector_mul.c000066400000000000000000000036061461254215100173400ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void _acb_mat_vector_mul_row(acb_ptr res, acb_srcptr v, const acb_mat_t A, slong prec) { slong r = acb_mat_nrows(A); slong c = acb_mat_ncols(A); acb_ptr tmp; slong k, j; if (acb_mat_is_empty(A)) { _acb_vec_zero(res, c); } else { tmp = flint_malloc(r * sizeof(acb_struct)); for (k = 0; k < c; k++) { for (j = 0; j < r; j++) { tmp[j] = *acb_mat_entry(A, j, k); } acb_dot(&res[k], NULL, 0, tmp, 1, v, 1, r, prec); } flint_free(tmp); } } void acb_mat_vector_mul_row(acb_ptr res, acb_srcptr v, const acb_mat_t A, slong prec) { slong c = acb_mat_ncols(A); acb_ptr aux; aux = _acb_vec_init(c); _acb_mat_vector_mul_row(aux, v, A, prec); _acb_vec_set(res, aux, c); _acb_vec_clear(aux, c); } void _acb_mat_vector_mul_col(acb_ptr res, const acb_mat_t A, acb_srcptr v, slong prec) { slong r = acb_mat_nrows(A); slong c = acb_mat_ncols(A); slong k; if (acb_mat_is_empty(A)) { _acb_vec_zero(res, r); } else { for (k = 0; k < r; k++) { acb_dot(&res[k], NULL, 0, A->rows[k], 1, v, 1, c, prec); } } } void acb_mat_vector_mul_col(acb_ptr res, const acb_mat_t A, acb_srcptr v, slong prec) { slong r = acb_mat_nrows(A); acb_ptr aux; aux = _acb_vec_init(r); _acb_mat_vector_mul_col(aux, A, v, prec); _acb_vec_set(res, aux, r); _acb_vec_clear(aux, r); } flint-3.1.3/src/acb_mat/window_init.c000066400000000000000000000013651461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_window_init(acb_mat_t window, const acb_mat_t mat, slong r1, slong c1, slong r2, slong c2) { slong i; window->entries = NULL; window->rows = flint_malloc((r2 - r1) * sizeof(acb_ptr)); for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; window->r = r2 - r1; window->c = c2 - c1; } flint-3.1.3/src/acb_mat/zero.c000066400000000000000000000011311461254215100161270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" void acb_mat_zero(acb_mat_t mat) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) for (j = 0; j < acb_mat_ncols(mat); j++) acb_zero(acb_mat_entry(mat, i, j)); } flint-3.1.3/src/acb_modular.h000066400000000000000000000126151461254215100160500ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_MODULAR_H #define ACB_MODULAR_H #ifdef ACB_MODULAR_INLINES_C #define ACB_MODULAR_INLINE #else #define ACB_MODULAR_INLINE static inline #endif #include "fmpz.h" #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz a; fmpz b; fmpz c; fmpz d; } psl2z_struct; typedef psl2z_struct psl2z_t[1]; ACB_MODULAR_INLINE void psl2z_init(psl2z_t g) { fmpz_init(&g->a); fmpz_init(&g->b); fmpz_init(&g->c); fmpz_init(&g->d); fmpz_one(&g->a); fmpz_one(&g->d); } ACB_MODULAR_INLINE void psl2z_clear(psl2z_t g) { fmpz_clear(&g->a); fmpz_clear(&g->b); fmpz_clear(&g->c); fmpz_clear(&g->d); } ACB_MODULAR_INLINE void psl2z_swap(psl2z_t f, psl2z_t g) { FLINT_SWAP(psl2z_struct, *f, *g); } ACB_MODULAR_INLINE void psl2z_set(psl2z_t h, const psl2z_t g) { fmpz_set(&h->a, &g->a); fmpz_set(&h->b, &g->b); fmpz_set(&h->c, &g->c); fmpz_set(&h->d, &g->d); } ACB_MODULAR_INLINE void psl2z_one(psl2z_t g) { fmpz_one(&g->a); fmpz_zero(&g->b); fmpz_zero(&g->c); fmpz_one(&g->d); } #ifdef FLINT_HAVE_FILE void psl2z_fprint(FILE * file, const psl2z_t g); #endif void psl2z_print(const psl2z_t g); ACB_MODULAR_INLINE int psl2z_equal(const psl2z_t f, const psl2z_t g) { return fmpz_equal(&f->a, &g->a) && fmpz_equal(&f->b, &g->b) && fmpz_equal(&f->c, &g->c) && fmpz_equal(&f->d, &g->d); } void psl2z_mul(psl2z_t h, const psl2z_t f, const psl2z_t g); void psl2z_inv(psl2z_t h, const psl2z_t g); int psl2z_is_one(const psl2z_t g); int psl2z_is_correct(const psl2z_t g); void psl2z_randtest(psl2z_t g, flint_rand_t state, slong bits); void acb_modular_transform(acb_t w, const psl2z_t g, const acb_t z, slong prec); void acb_modular_fundamental_domain_approx_d(psl2z_t g, double x, double y, double one_minus_eps); void acb_modular_fundamental_domain_approx_arf(psl2z_t g, const arf_t xx, const arf_t yy, const arf_t one_minus_eps, slong prec); void acb_modular_fundamental_domain_approx(acb_t w, psl2z_t g, const acb_t z, const arf_t one_minus_eps, slong prec); int acb_modular_is_in_fundamental_domain(const acb_t z, const arf_t tol, slong prec); void acb_modular_addseq_theta(slong * exponents, slong * aindex, slong * bindex, slong num); void acb_modular_addseq_eta(slong * exponents, slong * aindex, slong * bindex, slong num); void acb_modular_fill_addseq(slong * tab, slong len); void acb_modular_theta_transform(int * R, int * S, int * C, const psl2z_t g); void acb_modular_theta_const_sum(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong prec); void acb_modular_theta_const_sum_basecase(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong N, slong prec); void acb_modular_theta_const_sum_rs(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong N, slong prec); void acb_modular_theta_sum(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t w, int w_is_unit, const acb_t q, slong len, slong prec); void acb_modular_theta_notransform(acb_t theta1, acb_t theta2, acb_t theta3, acb_t theta4, const acb_t z, const acb_t tau, slong prec); void acb_modular_theta(acb_t theta1, acb_t theta2, acb_t theta3, acb_t theta4, const acb_t z, const acb_t tau, slong prec); void acb_modular_theta_jet_notransform(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t z, const acb_t tau, slong len, slong prec); void acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t z, const acb_t tau, slong len, slong prec); void _acb_modular_theta_series(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec); void acb_modular_theta_series(acb_poly_t theta1, acb_poly_t theta2, acb_poly_t theta3, acb_poly_t theta4, const acb_poly_t z, const acb_t tau, slong len, slong prec); void acb_modular_j(acb_t z, const acb_t tau, slong prec); int acb_modular_epsilon_arg(const psl2z_t g); void acb_modular_eta_sum(acb_t eta, const acb_t q, slong prec); void acb_modular_eta(acb_t z, const acb_t tau, slong prec); void acb_modular_lambda(acb_t r, const acb_t tau, slong prec); void acb_modular_delta(acb_t r, const acb_t tau, slong prec); void acb_modular_eisenstein(acb_ptr r, const acb_t tau, slong len, slong prec); void acb_modular_elliptic_p(acb_t r, const acb_t z, const acb_t tau, slong prec); void acb_modular_elliptic_p_zpx(acb_ptr r, const acb_t z, const acb_t tau, slong len, slong prec); void acb_modular_elliptic_k(acb_t k, const acb_t m, slong prec); void acb_modular_elliptic_k_cpx(acb_ptr w, const acb_t m, slong len, slong prec); void acb_modular_elliptic_e(acb_t res, const acb_t m, slong prec); void acb_modular_hilbert_class_poly(fmpz_poly_t res, slong D); /* this is a performance hack until the main arb/acb functions improve */ void _acb_modular_mul(acb_t z, acb_t tmp1, acb_t tmp2, const acb_t x, const acb_t y, slong wprec, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_modular/000077500000000000000000000000001461254215100156725ustar00rootroot00000000000000flint-3.1.3/src/acb_modular/addseq.c000066400000000000000000000066271461254215100173120ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" static slong bisect(slong needle, const slong * haystack, slong len) { slong a, b, mid; a = 0; b = len - 1; while (a < b) { mid = (a + b) / 2; if (haystack[mid] < needle) a = mid + 1; else b = mid; } if (a == b && haystack[a] == needle) { return a; } return -1; } /* write p = 2a with a in P */ static int write_as_2a(slong * i1, slong * i2, slong p, const slong * P, slong Plen) { if (p % 2 == 0) { slong i = bisect(p / 2, P, Plen); if (i != -1) { *i1 = *i2 = i; return 1; } } return 0; } /* write p = a + b with a, b in P */ static int write_as_a_b(slong * i1, slong * i2, slong p, const slong * P, slong Plen) { slong i, j, pi; for (i = 0; i < Plen; i++) { pi = P[i]; j = bisect(p - pi, P, Plen); if (j != -1) { *i1 = i; *i2 = j; return 1; } } return 0; } /* write p = 2a + b with a, b in P */ static int write_as_2a_b(slong * i1, slong * i2, slong p, const slong * P, slong Plen) { slong i, j, pi; for (i = 0; i < Plen; i++) { pi = P[i]; if (2 * pi > p) break; j = bisect(p - 2*pi, P, Plen); if (j != -1) { *i1 = i; *i2 = j; return 1; } } return 0; } void acb_modular_addseq_theta(slong * exponents, slong * aindex, slong * bindex, slong num) { slong i; slong c; for (i = 0; i < num; i++) { if (i == 0) { exponents[i] = 1; aindex[i] = 0; bindex[i] = 0; continue; } else { c = ((i + 2) * (i + 2)) / 4; exponents[i] = c; if (write_as_2a(aindex + i, bindex + i, c, exponents, i)) continue; if (write_as_a_b(aindex + i, bindex + i, c, exponents, i)) continue; if (write_as_2a_b(aindex + i, bindex + i, c, exponents, i)) continue; flint_throw(FLINT_ERROR, "i = %wd, c = %wu: bad addition sequence!\n", i, c); } } } void acb_modular_addseq_eta(slong * exponents, slong * aindex, slong * bindex, slong num) { slong i; slong c; for (i = 0; i < num; i++) { if (i == 0) { exponents[i] = 1; aindex[i] = 0; bindex[i] = 0; continue; } else { c = ((i + 2) / 2) * ((3 * i + 5) / 2) / 2; exponents[i] = c; if (write_as_2a(aindex + i, bindex + i, c, exponents, i)) continue; if (write_as_a_b(aindex + i, bindex + i, c, exponents, i)) continue; if (write_as_2a_b(aindex + i, bindex + i, c, exponents, i)) continue; flint_throw(FLINT_ERROR, "i = %wd, c = %wu: bad addition sequence!\n", i, c); } } } flint-3.1.3/src/acb_modular/delta.c000066400000000000000000000035121461254215100171300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_delta(acb_t z, const acb_t tau, slong prec) { psl2z_t g; arf_t one_minus_eps; acb_t tau_prime, t1, t2, t3, t4, q; int real; if (!arb_is_positive(acb_imagref(tau)) || !arb_is_finite(acb_realref(tau))) { acb_indeterminate(z); return; } real = arb_is_int_2exp_si(acb_realref(tau), -1); psl2z_init(g); arf_init(one_minus_eps); acb_init(tau_prime); acb_init(t1); acb_init(t2); acb_init(t3); acb_init(t4); acb_init(q); arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); acb_exp_pi_i(q, tau_prime, prec); acb_modular_theta_const_sum(t2, t3, t4, q, prec); /* (t2 t3 t4) ^ 8 * q^2 */ acb_mul(t1, t2, t3, prec); acb_mul(t1, t1, t4, prec); acb_mul(t1, t1, t1, prec); acb_mul(t1, t1, t1, prec); acb_mul(t1, t1, q, prec); acb_mul(t1, t1, t1, prec); acb_mul_2exp_si(t1, t1, -8); if (!fmpz_is_zero(&g->c)) { acb_mul_fmpz(t2, tau, &g->c, prec); acb_add_fmpz(t2, t2, &g->d, prec); acb_pow_ui(t2, t2, 12, prec); acb_div(t1, t1, t2, prec); } acb_set(z, t1); if (real) arb_zero(acb_imagref(z)); psl2z_clear(g); arf_clear(one_minus_eps); acb_clear(tau_prime); acb_clear(t1); acb_clear(t2); acb_clear(t3); acb_clear(t4); acb_clear(q); } flint-3.1.3/src/acb_modular/eisenstein.c000066400000000000000000000073701461254215100202130ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_eisenstein(acb_ptr r, const acb_t tau, slong len, slong prec) { psl2z_t g; arf_t one_minus_eps; acb_t tau_prime, t1, t2, t3, t4, q; slong m, n; int real; if (len < 1) return; if (!arb_is_positive(acb_imagref(tau)) || !arb_is_finite(acb_realref(tau))) { _acb_vec_indeterminate(r, len); return; } real = arb_is_int_2exp_si(acb_realref(tau), -1); psl2z_init(g); arf_init(one_minus_eps); acb_init(tau_prime); acb_init(t1); acb_init(t2); acb_init(t3); acb_init(t4); acb_init(q); arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); acb_exp_pi_i(q, tau_prime, prec); acb_modular_theta_const_sum(t2, t3, t4, q, prec); /* fourth powers of the theta functions (a, b, c) */ acb_mul(t2, t2, t2, prec); acb_mul(t2, t2, t2, prec); acb_mul(t2, t2, q, prec); acb_mul(t3, t3, t3, prec); acb_mul(t3, t3, t3, prec); acb_mul(t4, t4, t4, prec); acb_mul(t4, t4, t4, prec); /* c2 = pi^4 * (a^8 + b^8 + c^8) / 30 */ /* c3 = pi^6 * (b^12 + c^12 - 3a^8 * (b^4+c^4)) / 189 */ /* r = a^8 */ acb_mul(r, t2, t2, prec); if (len > 1) { /* r[1] = -3 a^8 * (b^4 + c^4) */ acb_add(r + 1, t3, t4, prec); acb_mul(r + 1, r + 1, r, prec); acb_mul_si(r + 1, r + 1, -3, prec); } /* b^8 */ acb_mul(t1, t3, t3, prec); acb_add(r, r, t1, prec); /* b^12 */ if (len > 1) acb_addmul(r + 1, t1, t3, prec); /* c^8 */ acb_mul(t1, t4, t4, prec); acb_add(r, r, t1, prec); /* c^12 */ if (len > 1) acb_addmul(r + 1, t1, t4, prec); acb_const_pi(t1, prec); acb_mul(t1, t1, t1, prec); acb_mul(t2, t1, t1, prec); acb_mul(r, r, t2, prec); acb_div_ui(r, r, 30, prec); if (len > 1) { acb_mul(t2, t2, t1, prec); acb_mul(r + 1, r + 1, t2, prec); acb_div_ui(r + 1, r + 1, 189, prec); } /* apply modular transformation */ if (!fmpz_is_zero(&g->c)) { acb_mul_fmpz(t1, tau, &g->c, prec); acb_add_fmpz(t1, t1, &g->d, prec); acb_inv(t1, t1, prec); acb_mul(t1, t1, t1, prec); acb_mul(t2, t1, t1, prec); acb_mul(r, r, t2, prec); if (len > 1) { acb_mul(t2, t1, t2, prec); acb_mul(r + 1, r + 1, t2, prec); } } if (real) { arb_zero(acb_imagref(r)); if (len > 1) arb_zero(acb_imagref(r + 1)); } /* compute more coefficients using recurrence */ for (n = 4; n < len + 2; n++) { acb_zero(r + n - 2); m = 2; for (m = 2; m * 2 < n; m++) acb_addmul(r + n - 2, r + m - 2, r + n - m - 2, prec); acb_mul_2exp_si(r + n - 2, r + n - 2, 1); if (n % 2 == 0) acb_addmul(r + n - 2, r + n / 2 - 2, r + n / 2 - 2, prec); acb_mul_ui(r + n - 2, r + n - 2, 3, prec); acb_div_ui(r + n - 2, r + n - 2, (2 * n + 1) * (n - 3), prec); } /* convert c's to G's */ for (n = 0; n < len; n++) acb_div_ui(r + n, r + n, 2 * n + 3, prec); psl2z_clear(g); arf_clear(one_minus_eps); acb_clear(tau_prime); acb_clear(t1); acb_clear(t2); acb_clear(t3); acb_clear(t4); acb_clear(q); } flint-3.1.3/src/acb_modular/elliptic_e.c000066400000000000000000000010331461254215100201440ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" #include "acb_elliptic.h" void acb_modular_elliptic_e(acb_t res, const acb_t m, slong prec) { acb_elliptic_e(res, m, prec); } flint-3.1.3/src/acb_modular/elliptic_k.c000066400000000000000000000010271461254215100201550ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" #include "acb_elliptic.h" void acb_modular_elliptic_k(acb_t k, const acb_t m, slong prec) { acb_elliptic_k(k, m, prec); } flint-3.1.3/src/acb_modular/elliptic_k_cpx.c000066400000000000000000000010611461254215100210250ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" #include "acb_elliptic.h" void acb_modular_elliptic_k_cpx(acb_ptr w, const acb_t m, slong len, slong prec) { acb_elliptic_k_jet(w, m, len, prec); } flint-3.1.3/src/acb_modular/elliptic_p.c000066400000000000000000000010551461254215100201630ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" #include "acb_elliptic.h" void acb_modular_elliptic_p(acb_t r, const acb_t z, const acb_t tau, slong prec) { acb_elliptic_p(r, z, tau, prec); } flint-3.1.3/src/acb_modular/elliptic_p_zpx.c000066400000000000000000000011071461254215100210620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" #include "acb_elliptic.h" void acb_modular_elliptic_p_zpx(acb_ptr r, const acb_t z, const acb_t tau, slong len, slong prec) { acb_elliptic_p_jet(r, z, tau, len, prec); } flint-3.1.3/src/acb_modular/epsilon_arg.c000066400000000000000000000035141461254215100203430ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" static int fmpz_kronecker1(const fmpz_t a, const fmpz_t b) { if (fmpz_sgn(b) < 0) { int r; fmpz_t t; fmpz_init(t); fmpz_neg(t, b); r = fmpz_kronecker1(a, t); fmpz_clear(t); return r; } else if (fmpz_is_one(b)) { return 1; } else { return fmpz_jacobi(a, b); } } int acb_modular_epsilon_arg(const psl2z_t g) { #define a (&g->a) #define b (&g->b) #define c (&g->c) #define d (&g->d) if (fmpz_is_zero(c)) { return fmpz_fdiv_ui(b, 24); } else { int aa, bb, cc, dd; int u; aa = fmpz_fdiv_ui(a, 24); bb = fmpz_fdiv_ui(b, 24); cc = fmpz_fdiv_ui(c, 24); dd = fmpz_fdiv_ui(d, 24); if (cc % 2 == 1) { u = fmpz_kronecker1(a, c); aa = aa*bb + 2*aa*cc - 3*cc + cc*dd*(1-aa*aa); } else { u = fmpz_kronecker1(c, a); aa = aa*bb - aa*cc + 3*aa - 3 + cc*dd*(1-aa*aa); } if (u == -1) { aa += 12; } else if (u != 1) { flint_throw(FLINT_ERROR, "bad kronecker input\n"); } /* mod 24 */ if (aa < 0) { aa = 24 - ((-aa) % 24); if (aa == 24) aa = 0; } else aa = aa % 24; return aa; } #undef a #undef b #undef c #undef d } flint-3.1.3/src/acb_modular/eta.c000066400000000000000000000031451461254215100166120ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb.h" #include "acb_modular.h" void acb_modular_eta(acb_t z, const acb_t tau, slong prec) { psl2z_t g; fmpq_t t; arf_t one_minus_eps; acb_t tau_prime, eta, q, q24; psl2z_init(g); fmpq_init(t); arf_init(one_minus_eps); acb_init(tau_prime); acb_init(eta); acb_init(q); acb_init(q24); arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); acb_div_ui(q24, tau_prime, 12, prec); acb_exp_pi_i(q24, q24, prec); acb_pow_ui(q, q24, 24, prec); acb_modular_eta_sum(eta, q, prec); acb_mul(eta, eta, q24, prec); /* epsilon^-1 */ fmpq_set_si(t, -acb_modular_epsilon_arg(g), 12); arb_sin_cos_pi_fmpq(acb_imagref(q), acb_realref(q), t, prec); acb_mul(eta, eta, q, prec); /* (c*tau+d)^(-1/2) */ if (!fmpz_is_zero(&g->c)) { acb_mul_fmpz(q, tau, &g->c, prec); acb_add_fmpz(q, q, &g->d, prec); acb_rsqrt(q, q, prec); acb_mul(eta, eta, q, prec); } acb_set(z, eta); psl2z_clear(g); fmpq_clear(t); arf_clear(one_minus_eps); acb_clear(tau_prime); acb_clear(eta); acb_clear(q); acb_clear(q24); } flint-3.1.3/src/acb_modular/eta_sum.c000066400000000000000000000164411461254215100175010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" static const int pentagonal_best_m[] = { 2, 5, 7, 11, 13, 17, 19, 23, 25, 35, 55, 65, 77, 91, 119, 133, 143, 175, 275, 325, 385, 455, 595, 665, 715, 935, 1001, 1309, 1463, 1547, 1729, 1925, 2275, 2975, 3325, 3575, 4675, 5005, 6545, 7315, 7735, 8645, 10465, 11305, 12155, 13585, 16445, 17017, 19019, 23023, 24871, 25025, 32725, 36575, 38675, 43225, 52325, 56525, 60775, 67925, 82225, 85085, 95095, 115115, 124355, 145145, 146965, 168245, 177905, 198835, 224315, 230945, 279565, 312455, 323323, 391391, 425425, 475475, 575575, 621775, 725725, 734825, 841225, 889525, 994175, 0 }; static const int pentagonal_best_m_residues[] = { 2, 3, 4, 6, 7, 9, 10, 12, 11, 12, 18, 21, 24, 28, 36, 40, 42, 44, 66, 77, 72, 84, 108, 120, 126, 162, 168, 216, 240, 252, 280, 264, 308, 396, 440, 462, 594, 504, 648, 720, 756, 840, 1008, 1080, 1134, 1260, 1512, 1512, 1680, 2016, 2160, 1848, 2376, 2640, 2772, 3080, 3696, 3960, 4158, 4620, 5544, 4536, 5040, 6048, 6480, 7560, 7560, 8640, 9072, 10080, 11340, 11340, 13608, 15120, 15120, 18144, 16632, 18480, 22176, 23760, 27720, 27720, 31680, 33264, 36960, 0 }; slong acb_modular_rs_optimal_m(const int * best_ms, const int * num_residues, slong N); #define PENTAGONAL(N) ((((N)+2)/2) * ((3*(N)+5)/2)/2) void _acb_modular_mul(acb_t z, acb_t tmp1, acb_t tmp2, const acb_t x, const acb_t y, slong wprec, slong prec) { if (prec <= 1024) { acb_mul(z, x, y, wprec); } else if (x == y) { acb_set_round(tmp1, x, wprec); acb_mul(z, tmp1, tmp1, wprec); } else { acb_set_round(tmp1, x, wprec); acb_set_round(tmp2, y, wprec); acb_mul(z, tmp1, tmp2, wprec); } } void _acb_modular_eta_sum_basecase(acb_t eta, const acb_t q, double log2q_approx, slong N, slong prec) { slong e, e1, e2, k, k1, k2, num, term_prec; slong *exponents, *aindex, *bindex; acb_ptr qpow; acb_t tmp1, tmp2; double log2term_approx; if (N <= 5) { if (N <= 1) { acb_set_ui(eta, N != 0); } else if (N == 2) { acb_sub_ui(eta, q, 1, prec); acb_neg(eta, eta); } else { acb_mul(eta, q, q, prec); acb_add(eta, eta, q, prec); acb_neg(eta, eta); acb_add_ui(eta, eta, 1, prec); } return; } num = 1; while (PENTAGONAL(num) < N) num++; acb_init(tmp1); acb_init(tmp2); exponents = flint_malloc(sizeof(slong) * 3 * num); aindex = exponents + num; bindex = aindex + num; qpow = _acb_vec_init(num); acb_modular_addseq_eta(exponents, aindex, bindex, num); acb_set_round(qpow + 0, q, prec); acb_zero(eta); for (k = 0; k < num; k++) { e = exponents[k]; log2term_approx = e * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); if (k > 0) { k1 = aindex[k]; k2 = bindex[k]; e1 = exponents[k1]; e2 = exponents[k2]; if (e == e1 + e2) { _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + k1, qpow + k2, term_prec, prec); } else if (e == 2 * e1 + e2) { _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + k1, qpow + k1, term_prec, prec); _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + k, qpow + k2, term_prec, prec); } else { flint_throw(FLINT_ERROR, "exponent not in addition sequence!\n"); } } if (k % 4 <= 1) acb_sub(eta, eta, qpow + k, prec); else acb_add(eta, eta, qpow + k, prec); } acb_add_ui(eta, eta, 1, prec); flint_free(exponents); _acb_vec_clear(qpow, num); acb_clear(tmp1); acb_clear(tmp2); } void _acb_modular_eta_sum_rs(acb_t eta, const acb_t q, double log2q_approx, slong N, slong prec) { slong * tab; slong k, term_prec, i, e, eprev; slong m, num_pentagonal; double log2term_approx; acb_ptr qpow; acb_t tmp1, tmp2; acb_init(tmp1); acb_init(tmp2); /* choose rectangular splitting parameters */ m = acb_modular_rs_optimal_m(pentagonal_best_m, pentagonal_best_m_residues, N); /* build addition sequence */ tab = flint_calloc(m + 1, sizeof(slong)); for (k = 0; PENTAGONAL(k) < N; k++) tab[PENTAGONAL(k) % m] = -1; num_pentagonal = k; tab[m] = -1; /* compute powers in addition sequence */ qpow = _acb_vec_init(m + 1); acb_modular_fill_addseq(tab, m + 1); for (k = 0; k < m + 1; k++) { if (k == 0) { acb_one(qpow + k); } else if (k == 1) { acb_set_round(qpow + k, q, prec); } else if (tab[k] != 0) { log2term_approx = k * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + tab[k], qpow + k - tab[k], term_prec, prec); } } /* compute eta */ acb_zero(eta); term_prec = prec; for (k = num_pentagonal - 1; k >= 0; k--) { e = PENTAGONAL(k); /* exponent */ eprev = PENTAGONAL(k+1); log2term_approx = e * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); /* giant steps */ for (i = e / m; i < eprev / m; i++) { if (!acb_is_zero(eta)) _acb_modular_mul(eta, tmp1, tmp2, eta, qpow + m, term_prec, prec); } if (k % 4 <= 1) acb_sub(eta, eta, qpow + (e % m), prec); else acb_add(eta, eta, qpow + (e % m), prec); } acb_add_ui(eta, eta, 1, prec); acb_clear(tmp1); acb_clear(tmp2); _acb_vec_clear(qpow, m + 1); flint_free(tab); } void acb_modular_eta_sum(acb_t eta, const acb_t q, slong prec) { mag_t err, qmag; double log2q_approx; int q_is_real; slong N; mag_init(err); mag_init(qmag); q_is_real = arb_is_zero(acb_imagref(q)); acb_get_mag(qmag, q); log2q_approx = mag_get_d_log2_approx(qmag); if (log2q_approx >= 0.0) { N = 1; mag_inf(err); } else /* Pick N and compute error bound */ { N = 0; while (0.05 * N * N < prec) { if (log2q_approx * PENTAGONAL(N) < -prec - 2) break; N++; } N = PENTAGONAL(N); mag_geom_series(err, qmag, N); if (mag_is_inf(err)) N = 1; } if (N < 400) _acb_modular_eta_sum_basecase(eta, q, log2q_approx, N, prec); else _acb_modular_eta_sum_rs(eta, q, log2q_approx, N, prec); if (q_is_real) arb_add_error_mag(acb_realref(eta), err); else acb_add_error_mag(eta, err); mag_clear(err); mag_clear(qmag); } flint-3.1.3/src/acb_modular/fill_addseq.c000066400000000000000000000034261461254215100203120ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" void acb_modular_fill_addseq(slong * tab, slong len) { slong i, j; for (i = 2; i < len; i++) { if (tab[i] == -1) { /* prefer doubling (squaring) */ if ((i % 2) == 0 && tab[i / 2] != 0) { tab[i] = i / 2; } else { /* check if it can be written as a sum */ /* prefer unbalanced, because one power will have low precision */ #if 1 for (j = 1; 2 * j <= i; j++) #else for (j = i / 2; j >= 1; j--) #endif { if (tab[j] != 0 && tab[i-j] != 0) { tab[i] = j; break; } } /* extend and start over */ if (tab[i] == -1) { tab[i] = i / 2; if (tab[i / 2] == 0) tab[i / 2] = -1; if (tab[i - i / 2] == 0) tab[i - i / 2] = -1; i = 1; } } } } /* prefer squaring (extra entries may have been inserted) */ for (i = 2; i < len; i += 2) { if (tab[i] != 0 && tab[i] != i / 2) { if (tab[i / 2] != 0) tab[i] = i / 2; } } } flint-3.1.3/src/acb_modular/fundamental_domain_approx.c000066400000000000000000000051371461254215100232620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" static int good_enough(const acb_t z, const arf_t one_minus_eps, slong prec) { arf_t m; int res; if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -1) > 0) return 0; if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) >= 0) return 1; arf_init(m); arf_mul(m, arb_midref(acb_realref(z)), arb_midref(acb_realref(z)), prec, ARF_RND_DOWN); arf_addmul(m, arb_midref(acb_imagref(z)), arb_midref(acb_imagref(z)), prec, ARF_RND_DOWN); res = (arf_cmp(m, one_minus_eps) >= 0); arf_clear(m); return res; } void acb_modular_fundamental_domain_approx(acb_t w, psl2z_t g, const acb_t z, const arf_t one_minus_eps, slong prec) { acb_t t; psl2z_one(g); /* we must be in the upper half-plane */ if (!acb_is_finite(z) || arf_sgn(arb_midref(acb_imagref(z))) <= 0) { acb_set(w, z); return; } /* too large real-value shift */ if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), prec) > 0) { acb_set(w, z); return; } /* y >= 1: just shift x */ if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) >= 0) { arf_get_fmpz(&g->b, arb_midref(acb_realref(z)), ARF_RND_NEAR); acb_sub_fmpz(w, z, &g->b, prec); fmpz_neg(&g->b, &g->b); return; } acb_init(t); /* try using doubles */ if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -40) > 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 40) < 0) { double zred, zimd; zred = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN); zimd = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN); acb_modular_fundamental_domain_approx_d(g, zred, zimd, arf_get_d(one_minus_eps, ARF_RND_UP)); acb_modular_transform(t, g, z, prec); if (good_enough(t, one_minus_eps, prec)) { acb_swap(w, t); acb_clear(t); return; } } /* try with full precision */ acb_modular_fundamental_domain_approx_arf(g, arb_midref(acb_realref(z)), arb_midref(acb_imagref(z)), one_minus_eps, prec); acb_modular_transform(t, g, z, prec); acb_swap(w, t); acb_clear(t); } flint-3.1.3/src/acb_modular/fundamental_domain_approx_arf.c000066400000000000000000000045611461254215100241120ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_fundamental_domain_approx_arf(psl2z_t g, const arf_t xx, const arf_t yy, const arf_t one_minus_eps, slong prec) { slong i; arf_t x, y, t; fmpz_t n; psl2z_one(g); /* we must be in the upper half-plane */ if (!arf_is_finite(xx) || !arf_is_finite(yy) || arf_sgn(yy) <= 0) return; arf_init(x); arf_init(y); arf_init(t); fmpz_init(n); arf_set_round(x, xx, prec, ARF_RND_DOWN); arf_set_round(y, yy, prec, ARF_RND_DOWN); for (i = 0; i < 10 + prec / 4; i++) { /* too large shift */ if (arf_cmpabs_2exp_si(x, prec) > 0) { psl2z_one(g); break; } if (fmpz_bits(&g->a) > prec || fmpz_bits(&g->b) > prec || fmpz_bits(&g->c) > prec || fmpz_bits(&g->d) > prec) { psl2z_one(g); break; } /* shift */ if (arf_cmpabs_2exp_si(x, -1) > 0) { arf_get_fmpz(n, x, ARF_RND_NEAR); arf_sub_fmpz(x, x, n, prec, ARF_RND_DOWN); fmpz_submul(&g->a, &g->c, n); fmpz_submul(&g->b, &g->d, n); continue; } arf_mul(t, x, x, prec, ARF_RND_DOWN); arf_addmul(t, y, y, prec, ARF_RND_DOWN); /* inversion */ if (arf_cmp(t, one_minus_eps) < 0) { arf_div(x, x, t, prec, ARF_RND_DOWN); arf_neg(x, x); arf_div(y, y, t, prec, ARF_RND_DOWN); fmpz_swap(&g->a, &g->c); fmpz_swap(&g->b, &g->d); fmpz_neg(&g->a, &g->a); fmpz_neg(&g->b, &g->b); continue; } /* we're good */ break; } if (fmpz_sgn(&g->c) < 0 || (fmpz_is_zero(&g->c) && fmpz_sgn(&g->d) < 0)) { fmpz_neg(&g->a, &g->a); fmpz_neg(&g->b, &g->b); fmpz_neg(&g->c, &g->c); fmpz_neg(&g->d, &g->d); } arf_clear(x); arf_clear(y); arf_clear(t); fmpz_clear(n); } flint-3.1.3/src/acb_modular/fundamental_domain_approx_d.c000066400000000000000000000037101461254215100235600ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" #ifdef __GNUC__ # define floor __builtin_floor #else # include #endif static inline int d_is_ok(double x) { return (x > -1e15) && (x < 1e15); } void acb_modular_fundamental_domain_approx_d(psl2z_t g, double x, double y, double one_minus_eps) { double a, b, c, d, aa, bb, t; int i; a = d = 1; b = c = 0; for (i = 0; i < 20; i++) { if (!d_is_ok(x) || !d_is_ok(y) || !(y > 0.0)) { psl2z_one(g); return; } /* shift */ if (x < -0.5 || x > 0.5) { t = floor(x + 0.5); x -= t; a -= t * c; b -= t * d; /* too large to guarantee exactness */ if (!d_is_ok(a) || !d_is_ok(b)) { psl2z_one(g); return; } continue; } t = x*x + y*y; /* can't divide by a too small number */ if (t < 1e-30) { psl2z_one(g); break; } /* inversion */ if (t < one_minus_eps) { t = 1.0 / t; x *= -t; y *= t; aa = a; bb = b; a = -c; b = -d; c = aa; d = bb; continue; } /* we're good */ break; } if (c < 0 || (c == 0 && d < 0)) { a = -a; b = -b; c = -c; d = -d; } fmpz_set_d(&g->a, a); fmpz_set_d(&g->b, b); fmpz_set_d(&g->c, c); fmpz_set_d(&g->d, d); } flint-3.1.3/src/acb_modular/hilbert_class_poly.c000066400000000000000000000124011461254215100217150ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "ulong_extras.h" #include "fmpz_poly.h" #include "acb.h" #include "arb_poly.h" #include "acb_modular.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif static void bsplit(arb_poly_t pol, const arb_t sqrtD, const slong * qbf, slong a, slong b, slong prec) { if (b - a == 0) { arb_poly_one(pol); } else if (b - a == 1) { acb_t z; acb_init(z); /* j((-b+sqrt(-D))/(2a)) */ arb_set_si(acb_realref(z), -FLINT_ABS(qbf[3 * a + 1])); arb_set(acb_imagref(z), sqrtD); acb_div_si(z, z, 2 * qbf[3 * a], prec); acb_modular_j(z, z, prec); if (qbf[3 * a + 1] < 0) { /* (x^2 - 2re(j) x + |j|^2) */ arb_poly_fit_length(pol, 3); arb_mul(pol->coeffs, acb_realref(z), acb_realref(z), prec); arb_addmul(pol->coeffs, acb_imagref(z), acb_imagref(z), prec); arb_mul_2exp_si(pol->coeffs + 1, acb_realref(z), 1); arb_neg(pol->coeffs + 1, pol->coeffs + 1); arb_one(pol->coeffs + 2); _arb_poly_set_length(pol, 3); } else { /* (x-j) */ arb_poly_fit_length(pol, 2); arb_neg(pol->coeffs, acb_realref(z)); arb_one(pol->coeffs + 1); _arb_poly_set_length(pol, 2); } acb_clear(z); } else { arb_poly_t tmp; arb_poly_init(tmp); bsplit(pol, sqrtD, qbf, a, a + (b - a) / 2, prec); bsplit(tmp, sqrtD, qbf, a + (b - a) / 2, b, prec); arb_poly_mul(pol, pol, tmp, prec); arb_poly_clear(tmp); } } typedef struct { const slong * qbf; arb_srcptr sqrtD; slong prec; } work_t; static void basecase(arb_poly_t res, slong a, slong b, work_t * work) { bsplit(res, work->sqrtD, work->qbf, a, b, work->prec); } static void merge(arb_poly_t res, const arb_poly_t a, const arb_poly_t b, work_t * work) { arb_poly_mul(res, a, b, work->prec); } int _acb_modular_hilbert_class_poly(fmpz_poly_t res, slong D, const slong * qbf, slong qbf_len, slong prec) { arb_t sqrtD; arb_poly_t pol; int success; work_t work; arb_init(sqrtD); arb_poly_init(pol); arb_set_si(sqrtD, -D); arb_sqrt(sqrtD, sqrtD, prec); work.qbf = qbf; work.sqrtD = sqrtD; work.prec = prec; flint_parallel_binary_splitting(pol, (bsplit_basecase_func_t) basecase, (bsplit_merge_func_t) merge, sizeof(arb_poly_struct), (bsplit_init_func_t) arb_poly_init, (bsplit_clear_func_t) arb_poly_clear, &work, 0, qbf_len, 1, -1, 0); /* bsplit(pol, sqrtD, qbf, 0, qbf_len, prec); */ success = arb_poly_get_unique_fmpz_poly(res, pol); arb_clear(sqrtD); arb_poly_clear(pol); return success; } void acb_modular_hilbert_class_poly(fmpz_poly_t res, slong D) { slong i, a, b, c, ac, qbf_alloc, qbf_len, prec; slong * qbf; double lgh; if (D >= 0 || ((D & 3) > 1)) { fmpz_poly_zero(res); return; } qbf_alloc = qbf_len = 0; qbf = NULL; b = D & 1; /* Cohen algorithm 5.3.5 */ do { ac = (b*b - D) / 4; a = FLINT_MAX(b, 1); do { if (ac % a == 0 && n_gcd(n_gcd(a, b), ac/a) == 1) { c = ac / a; if (qbf_len >= qbf_alloc) { qbf_alloc = FLINT_MAX(4, FLINT_MAX(qbf_len + 1, qbf_alloc * 2)); qbf = flint_realloc(qbf, qbf_alloc * 3 * sizeof(slong)); } if (a == b || a*a == ac || b == 0) { qbf[3 * qbf_len + 0] = a; qbf[3 * qbf_len + 1] = b; qbf[3 * qbf_len + 2] = c; } else { /* -b indicates that we have both b and -b */ qbf[3 * qbf_len + 0] = a; qbf[3 * qbf_len + 1] = -b; qbf[3 * qbf_len + 2] = c; } qbf_len++; } a++; } while (a*a <= ac); b += 2; } while (3*b*b <= -D); /* Estimate precision - see p.7 in http://hal.inria.fr/inria-00001040 */ lgh = 0.0; for (i = 0; i < qbf_len; i++) { if (qbf[3 * i + 1] < 0) lgh += 2.0 / qbf[3 * i]; else lgh += 1.0 / qbf[3 * i]; } lgh = 3.141593 * sqrt(-D) * lgh; #if 0 lgh += 3.012 * h; prec = lgh * 1.442696; prec = prec + 10; #else prec = lgh * 1.442696; /* heuristic, but more accurate */ prec = prec * 1.005 + 20; #endif while (!_acb_modular_hilbert_class_poly(res, D, qbf, qbf_len, prec)) { flint_printf("hilbert_class_poly failed at %wd bits of precision\n", prec); prec = prec * 1.2 + 10; } flint_free(qbf); } flint-3.1.3/src/acb_modular/inlines.c000066400000000000000000000006661461254215100175070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ACB_MODULAR_INLINES_C #include "acb_modular.h" flint-3.1.3/src/acb_modular/io.c000066400000000000000000000015561461254215100164540ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_modular.h" /* printing *******************************************************************/ void psl2z_fprint(FILE * file, const psl2z_t g) { flint_fprintf(file, "["); fmpz_fprint(file, &g->a); flint_fprintf(file, " "); fmpz_fprint(file, &g->b); flint_fprintf(file, "; "); fmpz_fprint(file, &g->c); flint_fprintf(file, " "); fmpz_fprint(file, &g->d); flint_fprintf(file, "]"); } void psl2z_print(const psl2z_t g) { psl2z_fprint(stdout, g); } flint-3.1.3/src/acb_modular/is_in_fundamental_domain.c000066400000000000000000000024331461254215100230460ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" int acb_modular_is_in_fundamental_domain(const acb_t z, const arf_t tol, slong prec) { arb_t t; arb_init(t); /* require re(w) + 1/2 >= 0 */ arb_set_ui(t, 1); arb_mul_2exp_si(t, t, -1); arb_add(t, t, acb_realref(z), prec); arb_add_arf(t, t, tol, prec); if (!arb_is_nonnegative(t)) { arb_clear(t); return 0; } /* require re(w) - 1/2 <= 0 */ arb_set_ui(t, 1); arb_mul_2exp_si(t, t, -1); arb_sub(t, acb_realref(z), t, prec); arb_sub_arf(t, t, tol, prec); if (!arb_is_nonpositive(t)) { arb_clear(t); return 0; } /* require |w| >= 1 - tol, i.e. |w| - 1 + tol >= 0 */ acb_abs(t, z, prec); arb_sub_ui(t, t, 1, prec); arb_add_arf(t, t, tol, prec); if (!arb_is_nonnegative(t)) { arb_clear(t); return 0; } arb_clear(t); return 1; } flint-3.1.3/src/acb_modular/j.c000066400000000000000000000036161461254215100162750ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_j(acb_t z, const acb_t tau, slong prec) { psl2z_t g; arf_t one_minus_eps; acb_t tau_prime, t2, t3, t4, q; int real; if (!arb_is_positive(acb_imagref(tau)) || !arb_is_finite(acb_realref(tau))) { acb_indeterminate(z); return; } real = arb_is_int_2exp_si(acb_realref(tau), -1); psl2z_init(g); arf_init(one_minus_eps); acb_init(tau_prime); acb_init(t2); acb_init(t3); acb_init(t4); acb_init(q); arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); acb_exp_pi_i(q, tau_prime, prec); acb_modular_theta_const_sum(t2, t3, t4, q, prec); /* theta2 ^ 8 */ acb_mul(t2, t2, t2, prec); acb_mul(t2, t2, t2, prec); acb_mul(t2, t2, q, prec); acb_mul(t2, t2, t2, prec); /* theta3 ^ 8 */ acb_mul(t3, t3, t3, prec); acb_mul(t3, t3, t3, prec); acb_mul(t3, t3, t3, prec); /* theta4 ^ 8 */ acb_mul(t4, t4, t4, prec); acb_mul(t4, t4, t4, prec); acb_mul(t4, t4, t4, prec); acb_mul(z, t2, t3, prec); acb_mul(z, z, t4, prec); acb_add(t2, t2, t3, prec); acb_add(t2, t2, t4, prec); acb_cube(t2, t2, prec); acb_div(z, t2, z, prec); acb_mul_2exp_si(z, z, 5); if (real) arb_zero(acb_imagref(z)); psl2z_clear(g); arf_clear(one_minus_eps); acb_clear(tau_prime); acb_clear(t2); acb_clear(t3); acb_clear(t4); acb_clear(q); } flint-3.1.3/src/acb_modular/lambda.c000066400000000000000000000034621461254215100172630ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_lambda(acb_t r, const acb_t tau, slong prec) { psl2z_t g; arf_t one_minus_eps; acb_t tau_prime, q; acb_struct thetas[4]; int R[4], S[4], C; int Rsum, qpower; psl2z_init(g); arf_init(one_minus_eps); acb_init(tau_prime); acb_init(q); acb_init(thetas + 0); acb_init(thetas + 1); acb_init(thetas + 2); acb_init(thetas + 3); arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); acb_modular_theta_transform(R, S, &C, g); acb_exp_pi_i(q, tau_prime, prec); acb_modular_theta_const_sum(thetas + 1, thetas + 2, thetas + 3, q, prec); acb_zero(thetas + 0); /* divide the transformation factors */ Rsum = 4 * (R[1] - R[2]); /* possible factor [q^(+/- 1/4)]^4 needed for theta_1^4 or theta_2^4 */ qpower = (S[1] == 0 || S[1] == 1) - (S[2] == 0 || S[2] == 1); acb_div(r, thetas + S[1], thetas + S[2], prec); acb_mul(r, r, r, prec); acb_mul(r, r, r, prec); if ((Rsum & 7) == 4) acb_neg(r, r); if (qpower == 1) acb_mul(r, r, q, prec); else if (qpower == -1) acb_div(r, r, q, prec); psl2z_clear(g); arf_clear(one_minus_eps); acb_clear(tau_prime); acb_clear(q); acb_clear(thetas + 0); acb_clear(thetas + 1); acb_clear(thetas + 2); acb_clear(thetas + 3); } flint-3.1.3/src/acb_modular/psl2z.c000066400000000000000000000053631461254215100171170ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" void psl2z_inv(psl2z_t h, const psl2z_t g) { if (h != g) psl2z_set(h, g); if (fmpz_is_zero(&h->c) && fmpz_sgn(&h->a) > 0) { fmpz_neg(&h->b, &h->b); fmpz_swap(&h->d, &h->a); } else { fmpz_swap(&h->a, &h->d); fmpz_neg(&h->a, &h->a); fmpz_neg(&h->d, &h->d); } } int psl2z_is_correct(const psl2z_t g) { int res; fmpz_t t; if (fmpz_sgn(&g->c) < 0) return 0; if (fmpz_is_zero(&g->c) && fmpz_sgn(&g->d) <= 0) return 0; fmpz_init(t); fmpz_mul(t, &g->a, &g->d); fmpz_submul(t, &g->b, &g->c); res = fmpz_is_one(t); fmpz_clear(t); return res; } int psl2z_is_one(const psl2z_t g) { return fmpz_is_one(&g->a) && fmpz_is_zero(&g->b) && fmpz_is_zero(&g->c) && fmpz_is_one(&g->d); } void psl2z_mul(psl2z_t h, const psl2z_t f, const psl2z_t g) { if (h == f || h == g) { psl2z_t t; psl2z_init(t); psl2z_mul(t, f, g); psl2z_swap(t, h); psl2z_clear(t); return; } fmpz_mul(&h->a, &f->a, &g->a); fmpz_addmul(&h->a, &f->b, &g->c); fmpz_mul(&h->b, &f->a, &g->b); fmpz_addmul(&h->b, &f->b, &g->d); fmpz_mul(&h->c, &f->c, &g->a); fmpz_addmul(&h->c, &f->d, &g->c); fmpz_mul(&h->d, &f->c, &g->b); fmpz_addmul(&h->d, &f->d, &g->d); if (fmpz_sgn(&h->c) < 0 || (fmpz_is_zero(&h->c) && fmpz_sgn(&h->d) < 0)) { fmpz_neg(&h->a, &h->a); fmpz_neg(&h->b, &h->b); fmpz_neg(&h->c, &h->c); fmpz_neg(&h->d, &h->d); } } void psl2z_randtest(psl2z_t g, flint_rand_t state, slong bits) { bits = FLINT_MAX(bits, 1); fmpz_randtest(&g->a, state, bits); fmpz_randtest(&g->b, state, bits); if (fmpz_is_zero(&g->a) && fmpz_is_zero(&g->b)) { psl2z_one(g); } else { fmpz_t t; fmpz_init(t); fmpz_xgcd(t, &g->d, &g->c, &g->a, &g->b); fmpz_divexact(&g->a, &g->a, t); fmpz_divexact(&g->b, &g->b, t); if (fmpz_sgn(&g->c) < 0) fmpz_neg(&g->c, &g->c); else fmpz_neg(&g->b, &g->b); if (fmpz_is_zero(&g->c) && fmpz_sgn(&g->d) < 0) { fmpz_neg(&g->a, &g->a); fmpz_neg(&g->b, &g->b); fmpz_neg(&g->c, &g->c); fmpz_neg(&g->d, &g->d); } fmpz_clear(t); } } flint-3.1.3/src/acb_modular/test/000077500000000000000000000000001461254215100166515ustar00rootroot00000000000000flint-3.1.3/src/acb_modular/test/main.c000066400000000000000000000040571461254215100177470ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-delta.c" #include "t-eisenstein.c" #include "t-elliptic_e.c" #include "t-elliptic_k.c" #include "t-elliptic_p.c" #include "t-elliptic_p_zpx.c" #include "t-epsilon_arg.c" #include "t-eta.c" #include "t-fundamental_domain_approx.c" #include "t-hilbert_class_poly.c" #include "t-j.c" #include "t-lambda.c" #include "t-psl2z_inv.c" #include "t-psl2z_mul.c" #include "t-theta.c" #include "t-theta_const_sum_rs.c" #include "t-theta_jet.c" #include "t-theta_series.c" #include "t-theta_sum.c" #include "t-transform.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_modular_delta), TEST_FUNCTION(acb_modular_eisenstein), TEST_FUNCTION(acb_modular_elliptic_e), TEST_FUNCTION(acb_modular_elliptic_k), TEST_FUNCTION(acb_modular_elliptic_p), TEST_FUNCTION(acb_modular_elliptic_p_zpx), TEST_FUNCTION(acb_modular_epsilon_arg), TEST_FUNCTION(acb_modular_eta), TEST_FUNCTION(acb_modular_fundamental_domain_approx), TEST_FUNCTION(acb_modular_hilbert_class_poly), TEST_FUNCTION(acb_modular_j), TEST_FUNCTION(acb_modular_lambda), TEST_FUNCTION(acb_modular_psl2z_inv), TEST_FUNCTION(acb_modular_psl2z_mul), TEST_FUNCTION(acb_modular_theta), TEST_FUNCTION(acb_modular_theta_const_sum_rs), TEST_FUNCTION(acb_modular_theta_jet), TEST_FUNCTION(acb_modular_theta_series), TEST_FUNCTION(acb_modular_theta_sum), TEST_FUNCTION(acb_modular_transform) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_modular/test/t-delta.c000066400000000000000000000040311461254215100203450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_delta, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z1, z2; slong e0, prec0, prec1, prec2; acb_init(tau); acb_init(z1); acb_init(z2); e0 = 1 + n_randint(state, 10); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_randtest(tau, state, prec0, e0); acb_randtest(z1, state, prec0, e0); acb_randtest(z2, state, prec0, e0); /* compare with eta */ acb_modular_delta(z1, tau, prec1); acb_modular_eta(z2, tau, prec2); acb_pow_ui(z2, z2, 24, prec2); if (!acb_overlaps(z1, z2)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } acb_modular_delta(tau, tau, prec1); if (!acb_overlaps(z1, tau)) { flint_printf("FAIL (aliasing)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z1); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-eisenstein.c000066400000000000000000000050471461254215100214320ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_eisenstein, state) { slong iter; /* Test functional equation */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau1, tau2, t; acb_ptr r1, r2; slong e0, prec0, prec1, prec2, len1, len2, i; psl2z_t g; psl2z_init(g); acb_init(tau1); acb_init(tau2); acb_init(t); e0 = 1 + n_randint(state, 200); prec0 = 2 + n_randint(state, 2000); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); len1 = n_randint(state, 20); len2 = n_randint(state, 20); r1 = _acb_vec_init(len1); r2 = _acb_vec_init(len2); acb_randtest(tau1, state, prec0, e0); acb_randtest(tau2, state, prec0, e0); psl2z_randtest(g, state, 1 + n_randint(state, 200)); acb_modular_transform(tau2, g, tau1, prec0); acb_modular_eisenstein(r1, tau1, len1, prec1); acb_modular_eisenstein(r2, tau2, len2, prec2); for (i = 0; i < FLINT_MIN(len1, len2); i++) { acb_mul_fmpz(t, tau1, &g->c, prec1); acb_add_fmpz(t, t, &g->d, prec1); acb_pow_ui(t, t, 2 * i + 4, prec1); acb_mul(t, t, r1 + i, prec1); if (!acb_overlaps(t, r2 + i)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau1 = "); acb_printd(tau1, 15); flint_printf("\n\n"); flint_printf("tau2 = "); acb_printd(tau2, 15); flint_printf("\n\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n\n"); flint_printf("r1 = "); acb_printd(r1 + i, 15); flint_printf("\n\n"); flint_printf("r2 = "); acb_printd(r2 + i, 15); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(tau1); acb_clear(tau2); acb_clear(t); _acb_vec_clear(r1, len1); _acb_vec_clear(r2, len2); psl2z_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-elliptic_e.c000066400000000000000000000043001461254215100213640ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_elliptic_e, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_t m, w, K, Kp, E, Ep, r, pi2; slong prec; acb_init(m); acb_init(w); acb_init(K); acb_init(Kp); acb_init(E); acb_init(Ep); acb_init(r); acb_init(pi2); prec = 2 + n_randint(state, 1000); acb_randtest(m, state, prec, 1 + n_randint(state, 100)); acb_sub_ui(w, m, 1, prec); acb_neg(w, w); acb_const_pi(pi2, prec); acb_mul_2exp_si(pi2, pi2, -1); acb_modular_elliptic_k(K, m, prec); acb_modular_elliptic_k(Kp, w, prec); acb_modular_elliptic_e(E, m, prec); acb_modular_elliptic_e(Ep, w, prec); acb_mul(r, K, Ep, prec); acb_addmul(r, E, Kp, prec); acb_submul(r, K, Kp, prec); if (!acb_overlaps(r, pi2)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 30); flint_printf("\n\n"); flint_printf("K = "); acb_printd(K, 30); flint_printf("\n\n"); flint_printf("Kp = "); acb_printd(Kp, 30); flint_printf("\n\n"); flint_printf("E = "); acb_printd(E, 30); flint_printf("\n\n"); flint_printf("Ep = "); acb_printd(Ep, 30); flint_printf("\n\n"); flint_printf("r = "); acb_printd(r, 30); flint_printf("\n\n"); flint_abort(); } acb_clear(m); acb_clear(w); acb_clear(K); acb_clear(Kp); acb_clear(E); acb_clear(Ep); acb_clear(r); acb_clear(pi2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-elliptic_k.c000066400000000000000000000133001461254215100213720ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define EPS 1e-13 #define NUM_DERIVS 4 #define NUM_TESTS 7 const double k_testdata[NUM_TESTS][10] = { {0.0, 0.0, 1.5707963267948966192, 0.0, 0.39269908169872415481, 0.0, 0.22089323345553233708, 0.0, 0.15339807878856412297, 0.0}, {0.5, 0.0, 1.8540746773013719184, 0.0, 0.84721308479397908661, 0.0, 0.92703733865068595922, 0.0, 1.2708196271909686299, 0.0}, {-1.0, 0.0, 1.3110287771460599052, 0.0, 0.17798966494456595038, 0.0, 0.051552950136795718707, 0.0, 0.018179887959689603011, 0.0}, {2.0, 0.0, 1.3110287771460599052, -1.3110287771460599052, -0.47752472362846400224, 0.17798966494456595038, 0.2762042441497192576, -0.051552950136795718707, -0.18666835846938225718, 0.018179887959689603011}, {-3.0, 0.0, 1.0782578237498216177, 0.0, 0.078788301660931975886, 0.0, 0.011748068987044517782, 0.0, 0.0021065590680576326689, 0.0}, {1.0, 1.0, 1.5092369540512728293, 0.62514641520269688427, -0.079689518666051625811, 0.40903679001382547524, -0.23159955416582020342, -0.028627375924621981072, 0.014191044435751759097, -0.16030448214657194629}, {-2.0, -3.0, 1.0408718798817036, -0.24497111630480680352, 0.04401149835588265436, -0.060184042863324675054, -0.0012755513109907959184, -0.01044301570409968822, -0.0013811810360989366762, -0.0011248246747562196271} }; TEST_FUNCTION_START(acb_modular_elliptic_k, state) { slong iter; /* check particular values against table */ { acb_t z, t; acb_ptr w1; slong i, j, prec, cnj; acb_init(z); acb_init(t); w1 = _acb_vec_init(NUM_DERIVS); for (prec = 32; prec <= 512; prec *= 4) { for (i = 0; i < NUM_TESTS; i++) { for (cnj = 0; cnj < 2; cnj++) { if (cnj == 1 && k_testdata[i][0] > 1 && k_testdata[i][1] == 0) continue; acb_zero(z); arf_set_d(arb_midref(acb_realref(z)), k_testdata[i][0]); arf_set_d(arb_midref(acb_imagref(z)), cnj ? -k_testdata[i][1] : k_testdata[i][1]); acb_modular_elliptic_k_cpx(w1, z, NUM_DERIVS, prec); for (j = 0; j < NUM_DERIVS; j++) { arf_set_d(arb_midref(acb_realref(t)), k_testdata[i][2+2*j]); mag_set_d(arb_radref(acb_realref(t)), fabs(k_testdata[i][2+2*j]) * EPS); arf_set_d(arb_midref(acb_imagref(t)), cnj ? -k_testdata[i][2+2*j+1] : k_testdata[i][2+2*j+1]); mag_set_d(arb_radref(acb_imagref(t)), fabs(k_testdata[i][2+2*j+1]) * EPS); if (!acb_overlaps(w1 + j, t)) { flint_printf("FAIL\n\n"); flint_printf("j = %wd\n\n", j); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 15); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1 + j, 15); flint_printf("\n\n"); flint_abort(); } } } } } _acb_vec_clear(w1, NUM_DERIVS); acb_clear(z); acb_clear(t); } /* self-consistency test */ for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr m1, m2; acb_t z1, z2, t; slong i, len1, len2, prec1, prec2; len1 = n_randint(state, 10); len2 = n_randint(state, 10); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); m1 = _acb_vec_init(len1); m2 = _acb_vec_init(len2); acb_init(z1); acb_init(z2); acb_init(t); acb_randtest(z1, state, prec1, 1 + n_randint(state, 100)); if (n_randint(state, 2)) { acb_set(z2, z1); } else { acb_randtest(t, state, prec2, 1 + n_randint(state, 100)); acb_add(z2, z1, t, prec2); acb_sub(z2, z2, t, prec2); } acb_modular_elliptic_k_cpx(m1, z1, len1, prec1); acb_modular_elliptic_k_cpx(m2, z2, len2, prec2); for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(m1 + i, m2 + i)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("iter = %wd, i = %wd, len1 = %wd, len2 = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, i, len1, len2, prec1, prec2); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_printf("m1 = "); acb_printd(m1, 30); flint_printf("\n\n"); flint_printf("m2 = "); acb_printd(m2, 30); flint_printf("\n\n"); flint_abort(); } } _acb_vec_clear(m1, len1); _acb_vec_clear(m2, len2); acb_clear(z1); acb_clear(z2); acb_clear(t); } TEST_FUNCTION_END(state); } #undef NUM_TESTS #undef EPS flint-3.1.3/src/acb_modular/test/t-elliptic_p.c000066400000000000000000000127331461254215100214100ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" #define NUM_TESTS 6 #define EPS 1e-13 /* z, tau, p(z, tau) checked with Mathematica: N[{z, tau, WeierstrassP[z, WeierstrassInvariants[{1, tau}/2]]}, 20] */ const double testdata[NUM_TESTS][6] = { { 1.4142135623730950488, 1.7320508075688772935, 2.2360679774997896964, 2.6457513110645905905, -3.3440423818409419071, 0.1143522489547216990 }, { -3.0, -2.0, -7.0, 3.0, -3.3640051024505898616, 0.0 }, { 0.1, 0.0, 0.6, 0.2, 99.322596953997138519, 2.258818666973309701 }, { 0.0, 0.1, 0.6, 0.2, -99.322596953997138519, -2.258818666973309701 }, { 0.5, 0.0, 0.333333333333333333, 20.0, 6.5797362673929057459, 0.0 }, { 3.6666666666666667, 2014.0, -3.1415926535897932385, 0.1, -36.988356711748296440, -102.242185767588750178 } }; static void acb_set_dddd(acb_t z, double a, double ar, double b, double br) { arf_set_d(arb_midref(acb_realref(z)), a); mag_set_d(arb_radref(acb_realref(z)), ar); arf_set_d(arb_midref(acb_imagref(z)), b); mag_set_d(arb_radref(acb_imagref(z)), br); } TEST_FUNCTION_START(acb_modular_elliptic_p, state) { slong iter; /* check test values */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong i; acb_t z, tau, p1, p2; acb_init(z); acb_init(tau); acb_init(p1); acb_init(p2); for (i = 0; i < NUM_TESTS; i++) { acb_set_dddd(z, testdata[i][0], 0.0, testdata[i][1], 0.0); acb_set_dddd(tau, testdata[i][2], 0.0, testdata[i][3], 0.0); if (i == NUM_TESTS - 1) /* sensitive to rounding errors in doubles */ acb_set_dddd(p2, testdata[i][4], 1e-6, testdata[i][5], 1e-6); else acb_set_dddd(p2, testdata[i][4], EPS, testdata[i][5], EPS); acb_modular_elliptic_p(p1, z, tau, 2 + n_randint(state, 1000)); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (test value)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } acb_modular_elliptic_p(p2, z, tau, 2 + n_randint(state, 1000)); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (test value 2)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(z); acb_clear(tau); acb_clear(p1); acb_clear(p2); } /* Test periods */ for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z1, z2, p1, p2; slong m, n, e0, prec0, prec1, prec2; acb_init(tau); acb_init(z1); acb_init(z2); acb_init(p1); acb_init(p2); e0 = 1 + n_randint(state, 10); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_randtest(tau, state, prec0, e0); if (arf_sgn(arb_midref(acb_imagref(tau))) < 0) acb_neg(tau, tau); acb_randtest(z1, state, prec0, e0); acb_randtest(p1, state, prec0, e0); acb_randtest(p2, state, prec0, e0); /* z2 = z1 + m + n*tau */ m = n_randint(state, 10); n = n_randint(state, 10); acb_add_ui(z2, z1, m, prec0); acb_addmul_ui(z2, tau, n, prec0); acb_modular_elliptic_p(p1, z1, tau, prec1); acb_modular_elliptic_p(p2, z2, tau, prec2); if (!acb_overlaps(p1, p2)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n"); flint_abort(); } acb_modular_elliptic_p(z1, z1, tau, prec1); if (!acb_overlaps(z1, p1)) { flint_printf("FAIL (aliasing)\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z1); acb_clear(z2); acb_clear(p1); acb_clear(p2); } TEST_FUNCTION_END(state); } #undef NUM_TESTS #undef EPS flint-3.1.3/src/acb_modular/test/t-elliptic_p_zpx.c000066400000000000000000000077651461254215100223220ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_elliptic_p_zpx, state) { slong iter; /* Test differential equation */ for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z; acb_ptr g, wp, wp3, wpd, wpd2; slong prec, len, i; len = 1 + n_randint(state, 15); prec = 2 + n_randint(state, 1000); acb_init(tau); acb_init(z); g = _acb_vec_init(2); wp = _acb_vec_init(len + 1); wp3 = _acb_vec_init(len); wpd = _acb_vec_init(len); wpd2 = _acb_vec_init(len); acb_randtest(tau, state, prec, 10); acb_randtest(z, state, prec, 10); acb_modular_elliptic_p_zpx(wp, z, tau, len + 1, prec); acb_modular_eisenstein(g, tau, 2, prec); acb_mul_ui(g, g, 60, prec); acb_mul_ui(g + 1, g + 1, 140, prec); _acb_poly_derivative(wpd, wp, len + 1, prec); _acb_poly_mullow(wpd2, wpd, len, wpd, len, len, prec); _acb_poly_pow_ui_trunc_binexp(wp3, wp, len, 3, len, prec); _acb_vec_scalar_mul_ui(wp3, wp3, len, 4, prec); _acb_vec_scalar_submul(wp3, wp, len, g, prec); acb_sub(wp3, wp3, g + 1, prec); for (i = 0; i < len; i++) { if (!acb_overlaps(wpd2 + i, wp3 + i)) { flint_printf("FAIL (overlap)\n"); flint_printf("i = %wd len = %wd prec = %wd\n\n", i, len, prec); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("wp = "); acb_printd(wp + i, 15); flint_printf("\n\n"); flint_printf("wpd = "); acb_printd(wpd + i, 15); flint_printf("\n\n"); flint_printf("wp3 = "); acb_printd(wp3 + i, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(tau); acb_clear(z); _acb_vec_clear(g, 2); _acb_vec_clear(wp, len + 1); _acb_vec_clear(wp3, len); _acb_vec_clear(wpd, len); _acb_vec_clear(wpd2, len); } /* Consistency test */ for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z; acb_ptr wp1, wp2; slong prec1, prec2, len1, len2, i; len1 = n_randint(state, 15); len2 = n_randint(state, 15); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_init(tau); acb_init(z); wp1 = _acb_vec_init(len1); wp2 = _acb_vec_init(len2); acb_randtest(tau, state, prec1, 10); acb_randtest(z, state, prec1, 10); acb_modular_elliptic_p_zpx(wp1, z, tau, len1, prec1); acb_modular_elliptic_p_zpx(wp2, z, tau, len2, prec2); for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(wp1 + i, wp2 + i)) { flint_printf("FAIL (overlap)\n"); flint_printf("i = %wd len1 = %wd len2 = %wd\n\n", i, len1, len2); flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("wp1 = "); acb_printd(wp1 + i, 15); flint_printf("\n\n"); flint_printf("wp2 = "); acb_printd(wp2 + i, 15); flint_printf("\n\n"); flint_abort(); } } acb_clear(tau); acb_clear(z); _acb_vec_clear(wp1, len1); _acb_vec_clear(wp2, len2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-epsilon_arg.c000066400000000000000000000044221461254215100215620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "acb.h" #include "acb_modular.h" #include "arith.h" static void acb_modular_epsilon_arg_naive(fmpq_t arg, const psl2z_t g) { #define a (&g->a) #define b (&g->b) #define c (&g->c) #define d (&g->d) if (fmpz_is_zero(c)) { fmpz_set(fmpq_numref(arg), b); fmpz_set_ui(fmpq_denref(arg), 12); fmpq_canonicalise(arg); } else { fmpq_t t; fmpq_init(t); fmpz_add(fmpq_numref(arg), a, d); fmpz_submul_ui(fmpq_numref(arg), c, 3); fmpz_mul_ui(fmpq_denref(arg), c, 12); fmpq_canonicalise(arg); arith_dedekind_sum(t, d, c); fmpq_sub(arg, arg, t); fmpq_clear(t); } #undef a #undef b #undef c #undef d } TEST_FUNCTION_START(acb_modular_epsilon_arg, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { psl2z_t g; fmpq_t x, y; acb_t a, b; psl2z_init(g); fmpq_init(x); fmpq_init(y); acb_init(a); acb_init(b); psl2z_randtest(g, state, n_randint(state, 200)); fmpq_randtest(x, state, 100); fmpq_randtest(y, state, 100); fmpq_set_si(x, acb_modular_epsilon_arg(g), 12); acb_modular_epsilon_arg_naive(y, g); arb_sin_cos_pi_fmpq(acb_imagref(a), acb_realref(a), x, 200); arb_sin_cos_pi_fmpq(acb_imagref(b), acb_realref(b), x, 200); if (!acb_overlaps(a, b)) { flint_printf("FAIL\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n"); flint_abort(); } psl2z_clear(g); fmpq_clear(x); fmpq_clear(y); acb_clear(a); acb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-eta.c000066400000000000000000000102331461254215100200260ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_eta, state) { slong iter; /* Test functional equation */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau1, tau2, z1, z2, z3, t; fmpq_t arg; slong e0, prec0, prec1, prec2; psl2z_t g; psl2z_init(g); fmpq_init(arg); acb_init(tau1); acb_init(tau2); acb_init(z1); acb_init(z2); acb_init(z3); acb_init(t); e0 = 1 + n_randint(state, 200); prec0 = 2 + n_randint(state, 2000); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); acb_randtest(tau1, state, prec0, e0); acb_randtest(tau2, state, prec0, e0); acb_randtest(z1, state, prec0, e0); acb_randtest(z2, state, prec0, e0); psl2z_randtest(g, state, 1 + n_randint(state, 200)); acb_modular_transform(tau2, g, tau1, prec0); acb_modular_eta(z1, tau1, prec1); acb_modular_eta(z2, tau2, prec2); /* apply transformation */ fmpq_set_si(arg, acb_modular_epsilon_arg(g), 12); arb_sin_cos_pi_fmpq(acb_imagref(t), acb_realref(t), arg, prec1); acb_mul(z3, z1, t, prec1); acb_mul_fmpz(t, tau1, &g->c, prec1); acb_add_fmpz(t, t, &g->d, prec1); acb_sqrt(t, t, prec1); acb_mul(z3, z3, t, prec1); if (!acb_overlaps(z3, z2)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau1 = "); acb_printd(tau1, 15); flint_printf("\n\n"); flint_printf("tau2 = "); acb_printd(tau2, 15); flint_printf("\n\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_printf("z3 = "); acb_printd(z3, 15); flint_printf("\n\n"); flint_abort(); } acb_modular_eta(tau1, tau1, prec2); if (!acb_overlaps(z1, tau1)) { flint_printf("FAIL (aliasing)\n"); flint_printf("tau1 = "); acb_print(tau1); flint_printf("\n\n"); flint_printf("tau2 = "); acb_print(tau2); flint_printf("\n\n"); flint_printf("z1 = "); acb_print(z1); flint_printf("\n\n"); flint_printf("z2 = "); acb_print(z2); flint_printf("\n\n"); flint_abort(); } acb_clear(tau1); acb_clear(tau2); acb_clear(z1); acb_clear(z2); acb_clear(z3); acb_clear(t); psl2z_clear(g); fmpq_clear(arg); } /* Test special values */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z; arb_t t, u; slong prec; acb_init(tau); acb_init(z); arb_init(t); arb_init(u); prec = 2 + n_randint(state, 10000); acb_randtest(z, state, prec, 10); acb_onei(tau); acb_modular_eta(z, tau, prec); arb_one(t); arb_mul_2exp_si(t, t, -2); arb_gamma(t, t, prec); arb_const_pi(u, prec); arb_root_ui(u, u, 4, prec); arb_pow_ui(u, u, 3, prec); arb_div(t, t, u, prec); arb_mul_2exp_si(t, t, -1); if (!arb_overlaps(acb_realref(z), t) || !arb_contains_zero(acb_imagref(z))) { flint_printf("FAIL (value 1)\n"); flint_printf("tau = "); acb_print(tau); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z); arb_clear(t); arb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-fundamental_domain_approx.c000066400000000000000000000103211461254215100244710ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_fundamental_domain_approx, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_t x, y; psl2z_t g; arf_t one_minus_eps, tol; acb_t z, w, w2; arb_t t; slong prec; fmpq_init(x); fmpq_init(y); psl2z_init(g); acb_init(z); acb_init(w); acb_init(w2); arf_init(one_minus_eps); arf_init(tol); arb_init(t); /* pick an exact point in the upper half plane */ fmpq_randtest(x, state, 1 + n_randint(state, 500)); do { fmpq_randtest(y, state, 1 + n_randint(state, 500)); } while (fmpz_sgn(fmpq_numref(y)) <= 0); /* pick a tolerance */ arf_set_ui_2exp_si(tol, 1, -(slong) n_randint(state, 500)); /* now increase the precision until convergence */ for (prec = 32; ; prec *= 2) { if (prec > 16384) { flint_printf("FAIL (no convergence)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n\n"); flint_abort(); } arb_set_fmpq(acb_realref(z), x, prec); arb_set_fmpq(acb_imagref(z), y, prec); arf_set_ui_2exp_si(one_minus_eps, 1, -prec / 4); arf_sub_ui(one_minus_eps, one_minus_eps, 1, prec, ARF_RND_DOWN); arf_neg(one_minus_eps, one_minus_eps); acb_modular_fundamental_domain_approx(w, g, z, one_minus_eps, prec); acb_modular_transform(w2, g, z, prec); if (!psl2z_is_correct(g) || !acb_overlaps(w, w2)) { flint_printf("FAIL (incorrect transformation)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n\n"); flint_abort(); } /* success */ if (acb_modular_is_in_fundamental_domain(w, tol, prec)) break; } /* check that g^(-1) * w contains x+yi */ psl2z_inv(g, g); acb_modular_transform(w2, g, w, 2 + n_randint(state, 1000)); if (!arb_contains_fmpq(acb_realref(w2), x) || !arb_contains_fmpq(acb_imagref(w2), y)) { flint_printf("FAIL (inverse containment)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n\n"); flint_abort(); } fmpq_clear(x); fmpq_clear(y); psl2z_clear(g); acb_clear(z); acb_clear(w); acb_clear(w2); arf_clear(one_minus_eps); arf_clear(tol); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-hilbert_class_poly.c000066400000000000000000000166421461254215100231500ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "fmpz_poly.h" #include "acb.h" #include "acb_modular.h" /* reference values h_(-d)(2015) mod 31337 computed using sage */ static const short hilbert_poly_values[1000] = { 0, 0, 0, 2015, 287, 0, 0, 5390, 25352, 0, 0, 3446, 10689, 0, 0, 7571, 27889, 0, 0, 9315, 17503, 0, 0, 20694, 1734, 0, 0, 5911, 29250, 0, 0, 6194, 3783, 0, 0, 6982, 30449, 0, 0, 10645, 11069, 0, 0, 494, 29262, 0, 0, 10595, 22835, 0, 0, 18309, 24632, 0, 0, 6433, 5042, 0, 0, 9174, 24082, 0, 0, 3463, 30027, 0, 0, 11406, 22491, 0, 0, 16831, 8457, 0, 0, 21721, 19275, 0, 0, 23777, 28295, 0, 0, 13585, 26717, 0, 0, 632, 20965, 0, 0, 9886, 852, 0, 0, 18674, 12461, 0, 0, 17204, 23887, 0, 0, 132, 11124, 0, 0, 29609, 2760, 0, 0, 29227, 28978, 0, 0, 29543, 20831, 0, 0, 12260, 15153, 0, 0, 18215, 29267, 0, 0, 13864, 4648, 0, 0, 9591, 3948, 0, 0, 29683, 20283, 0, 0, 30212, 23760, 0, 0, 10290, 17465, 0, 0, 31207, 21341, 0, 0, 19076, 29310, 0, 0, 740, 11697, 0, 0, 20446, 7258, 0, 0, 16515, 29406, 0, 0, 19948, 20065, 0, 0, 8576, 19014, 0, 0, 1647, 1354, 0, 0, 19468, 6933, 0, 0, 2065, 17883, 0, 0, 19430, 5539, 0, 0, 5738, 25233, 0, 0, 21651, 6815, 0, 0, 23927, 28399, 0, 0, 3108, 23302, 0, 0, 17409, 7911, 0, 0, 26800, 31051, 0, 0, 14360, 11091, 0, 0, 10984, 11954, 0, 0, 26389, 3557, 0, 0, 3298, 18516, 0, 0, 22211, 2972, 0, 0, 22613, 5274, 0, 0, 27799, 13362, 0, 0, 8002, 23366, 0, 0, 31122, 20593, 0, 0, 356, 19130, 0, 0, 10024, 2373, 0, 0, 19390, 28768, 0, 0, 25504, 4440, 0, 0, 14798, 8726, 0, 0, 6180, 7623, 0, 0, 12941, 31038, 0, 0, 14370, 29147, 0, 0, 166, 10994, 0, 0, 8397, 354, 0, 0, 26973, 17435, 0, 0, 21128, 5064, 0, 0, 20453, 30343, 0, 0, 25679, 6503, 0, 0, 28364, 4924, 0, 0, 6341, 11339, 0, 0, 10624, 17028, 0, 0, 28001, 192, 0, 0, 27052, 28470, 0, 0, 10034, 12162, 0, 0, 25236, 6842, 0, 0, 19334, 7593, 0, 0, 29159, 26694, 0, 0, 14719, 26199, 0, 0, 9382, 25741, 0, 0, 31174, 8440, 0, 0, 4218, 17722, 0, 0, 11574, 8090, 0, 0, 9938, 4982, 0, 0, 22701, 6931, 0, 0, 29372, 29088, 0, 0, 28, 24186, 0, 0, 23852, 7521, 0, 0, 18508, 9883, 0, 0, 2392, 30611, 0, 0, 26103, 11926, 0, 0, 27676, 24118, 0, 0, 7495, 15441, 0, 0, 12681, 20030, 0, 0, 8106, 3260, 0, 0, 25626, 24143, 0, 0, 17471, 9620, 0, 0, 24315, 24991, 0, 0, 25966, 12488, 0, 0, 9839, 25896, 0, 0, 14932, 27863, 0, 0, 20652, 11663, 0, 0, 1779, 5540, 0, 0, 2066, 24758, 0, 0, 23522, 20408, 0, 0, 26357, 2423, 0, 0, 14671, 18184, 0, 0, 16904, 264, 0, 0, 27879, 30997, 0, 0, 1506, 23000, 0, 0, 1236, 13243, 0, 0, 24917, 2346, 0, 0, 2397, 14849, 0, 0, 21298, 15702, 0, 0, 9627, 8103, 0, 0, 26185, 6738, 0, 0, 2476, 21350, 0, 0, 7578, 9859, 0, 0, 19157, 5329, 0, 0, 401, 3223, 0, 0, 30337, 21258, 0, 0, 25707, 14593, 0, 0, 8611, 15496, 0, 0, 12225, 1505, 0, 0, 23534, 16704, 0, 0, 13230, 19926, 0, 0, 12220, 19104, 0, 0, 6130, 12697, 0, 0, 19881, 6864, 0, 0, 25044, 7436, 0, 0, 29137, 14435, 0, 0, 20628, 26292, 0, 0, 30933, 8606, 0, 0, 28752, 23603, 0, 0, 11633, 21739, 0, 0, 22592, 18621, 0, 0, 20125, 1595, 0, 0, 25306, 15723, 0, 0, 1643, 16444, 0, 0, 11825, 27858, 0, 0, 13835, 4948, 0, 0, 29003, 12298, 0, 0, 16479, 12920, 0, 0, 25238, 15558, 0, 0, 4102, 16578, 0, 0, 10456, 546, 0, 0, 3738, 28968, 0, 0, 20266, 8035, 0, 0, 9779, 25941, 0, 0, 5911, 20127, 0, 0, 18291, 28982, 0, 0, 18831, 29846, 0, 0, 21272, 11493, 0, 0, 24427, 28574, 0, 0, 22664, 14849, 0, 0, 30445, 20996, 0, 0, 13612, 18604, 0, 0, 19880, 19227, 0, 0, 6230, 17398, 0, 0, 29192, 29933, 0, 0, 25046, 14031, 0, 0, 24100, 463, 0, 0, 19254, 17038, 0, 0, 19912, 10339, 0, 0, 12475, 24909, 0, 0, 3292, 18482, 0, 0, 1542, 24603, 0, 0, 24850, 2332, 0, 0, 22262, 14510, 0, 0, 16526, 18396, 0, 0, 30544, 14396, 0, 0, 2788, 18461, 0, 0, 17619, 14749, 0, 0, 29832, 24740, 0, 0, 19298, 20355, 0, 0, 538, 18003, 0, 0, 4225, 4401, 0, 0, 28095, 1371, 0, 0, 2724, 353, 0, 0, 8917, 943, 0, 0, 4998, 2384, 0, 0, 14677, 9528, 0, 0, 7351, 13960, 0, 0, 4467, 8153, 0, 0, 16711, 8606, 0, 0, 24590, 1061, 0, 0, 7678, 5647, 0, 0, 27940, 3563, 0, 0, 11137, 29574, 0, 0, 15623, 29261, 0, 0, 15422, 3266, 0, 0, 26284, 9039, 0, 0, 9616, 21817, 0, 0, 2661, 8479, 0, 0, 19882, 5965, 0, 0, 13459, 2231, 0, 0, 10839, 22085, 0, 0, 23581, 14883, 0, 0, 7516, 20147, 0, 0, 7072, 16192, 0, 0, 26870, 29168, 0, 0, 5724, 19808, 0, 0, 25458, 21905, 0, 0, 28942, 29586, 0, 0, 13256, 6359, 0, 0, 15267, 8726, 0, 0, 29008, 24734, 0, 0, 2786, 716, 0, 0, 29798, 3021, 0, 0, 1388, 28017, 0, 0, 26001, 11541, 0, 0, 19326, 2630, 0, 0, 5326, 1153, 0, 0, 12367, 12089, 0, 0, 15701, 7816, 0, 0, 28096, 13980, 0, 0, 15683, 16412, 0, 0, 29609, 21907, 0, 0, 2266, 30126, 0, 0, 26922, 29563, 0, 0, 27024, 11031, 0, 0, 28714, 4013, 0, 0, 20446, 30395, 0, 0, 1980, 26546, 0, 0, 26413, 13346, 0, 0, 4083, 837, 0, 0, 7134, 251, 0, 0, 29540, 6521, 0, 0, 18515, 2436, 0, 0, 21198, 24291, 0, 0, 26451, 28377, 0, 0, 18689, 15300, 0, 0, 8527, 27153, 0, 0, 18586, 30431, 0, 0, 28981, 13795, 0, 0, 11286, 26207, 0, 0, 11870, 2833, 0, 0, 6996, 19018, 0, 0, 22638, 18958, 0, 0, 10333, 12804, 0, 0, 13618, 8212, 0, 0, 30926, 11947, 0, 0, 6681 }; static const int hilbert_poly_values_2[] = { -2000, 13490, -1999, 10172, -4000, 2042, -3999, 16478, -8000, 14919, -7999, 15365, -16000, 8190, -15999, 30928, -32000, 10486, -31999, 2808, -64000, 26310, -63999, 23551, /* slow -128000, 30815, -127999, 2144, -256000, 5257, -255999, 18151, -512000, 31288, -511999, 30227, -1024000, 14241, -1023999, 16711, */ 0, 0, }; TEST_FUNCTION_START(acb_modular_hilbert_class_poly, state) { { slong i; mp_limb_t c; fmpz_poly_t hd; nmod_poly_t hdp; fmpz_poly_init(hd); nmod_poly_init(hdp, 31337); for (i = 0; i < 1000; i++) { acb_modular_hilbert_class_poly(hd, -i); fmpz_poly_get_nmod_poly(hdp, hd); c = nmod_poly_evaluate_nmod(hdp, 2015); if (c != hilbert_poly_values[i]) { flint_printf("FAIL!\n"); flint_printf("D = %wd\n", -i); flint_printf("c = %wu\n", c); flint_printf("expected = %d\n", (int) hilbert_poly_values[i]); flint_abort(); } } for (i = 0; hilbert_poly_values_2[2 * i] != 0; i++) { acb_modular_hilbert_class_poly(hd, hilbert_poly_values_2[2 * i]); fmpz_poly_get_nmod_poly(hdp, hd); c = nmod_poly_evaluate_nmod(hdp, 2015); if (c != hilbert_poly_values_2[2 * i + 1]) { flint_printf("FAIL!\n"); flint_printf("D = %wd\n", -i); flint_printf("c = %wu\n", c); flint_printf("expected = %d\n", (int) hilbert_poly_values_2[2*i+1]); flint_abort(); } } fmpz_poly_clear(hd); nmod_poly_clear(hdp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-j.c000066400000000000000000000067521461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_j, state) { slong iter; /* Test SL2Z invariance */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau1, tau2, z1, z2; slong e0, prec0, prec1, prec2; psl2z_t g; psl2z_init(g); acb_init(tau1); acb_init(tau2); acb_init(z1); acb_init(z2); e0 = 1 + n_randint(state, 100); prec0 = 2 + n_randint(state, 2000); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); acb_randtest(tau1, state, prec0, e0); acb_randtest(tau2, state, prec0, e0); acb_randtest(z1, state, prec0, e0); acb_randtest(z2, state, prec0, e0); psl2z_randtest(g, state, 1 + n_randint(state, 200)); acb_modular_transform(tau2, g, tau1, prec0); acb_modular_j(z1, tau1, prec1); acb_modular_j(z2, tau2, prec2); if (!acb_overlaps(z1, z2)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau1 = "); acb_print(tau1); flint_printf("\n\n"); flint_printf("tau2 = "); acb_print(tau2); flint_printf("\n\n"); flint_printf("z1 = "); acb_print(z1); flint_printf("\n\n"); flint_printf("z2 = "); acb_print(z2); flint_printf("\n\n"); flint_abort(); } acb_modular_j(tau1, tau1, prec2); if (!acb_overlaps(z1, tau1)) { flint_printf("FAIL (aliasing)\n"); flint_printf("tau1 = "); acb_print(tau1); flint_printf("\n\n"); flint_printf("tau2 = "); acb_print(tau2); flint_printf("\n\n"); flint_printf("z1 = "); acb_print(z1); flint_printf("\n\n"); flint_printf("z2 = "); acb_print(z2); flint_printf("\n\n"); flint_abort(); } acb_clear(tau1); acb_clear(tau2); acb_clear(z1); acb_clear(z2); psl2z_clear(g); } /* Test special values */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau, z; slong prec; acb_init(tau); acb_init(z); prec = 2 + n_randint(state, 2000); acb_randtest(z, state, prec, 10); acb_onei(tau); acb_modular_j(z, tau, prec); acb_sub_ui(z, z, 1728, prec); if (!acb_contains_zero(z)) { flint_printf("FAIL (value 1)\n"); flint_printf("tau = "); acb_print(tau); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_abort(); } acb_set_ui(tau, 2); acb_div_ui(tau, tau, 3, prec); acb_exp_pi_i(tau, tau, prec); acb_modular_j(z, tau, prec); if (!acb_contains_zero(z)) { flint_printf("FAIL (value 2)\n"); flint_printf("tau = "); acb_print(tau); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); flint_abort(); } acb_clear(tau); acb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-lambda.c000066400000000000000000000065441461254215100205070ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_lambda, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t tau1, tau2, z1, z2, z3, t; slong e0, prec0, prec1, prec2, step; acb_init(tau1); acb_init(tau2); acb_init(z1); acb_init(z2); acb_init(z3); acb_init(t); e0 = 1 + n_randint(state, 100); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_randtest(tau1, state, prec0, e0); acb_randtest(tau2, state, prec0, e0); acb_randtest(z1, state, prec0, e0); acb_randtest(z2, state, prec0, e0); acb_set(tau2, tau1); step = n_randint(state, 10); /* Test invariance */ while (step --> 0) { if (n_randint(state, 2)) { acb_add_ui(tau2, tau2, 2, prec0); } else { acb_mul_si(z1, tau2, -2, prec0); acb_add_ui(z1, z1, 1, prec0); acb_div(tau2, tau2, z1, prec0); } } acb_modular_lambda(z1, tau1, prec1); acb_modular_lambda(z2, tau2, prec2); /* Compare with eta */ acb_mul_2exp_si(tau1, tau1, -1); acb_modular_eta(z3, tau1, prec2); acb_mul_2exp_si(tau1, tau1, 2); acb_modular_eta(t, tau1, prec2); acb_mul(t, t, t, prec2); acb_mul(z3, z3, t, prec2); acb_mul_2exp_si(tau1, tau1, -1); acb_modular_eta(t, tau1, prec2); acb_pow_ui(t, t, 3, prec2); acb_div(z3, z3, t, prec2); acb_pow_ui(z3, z3, 8, prec2); acb_mul_2exp_si(z3, z3, 4); if (!acb_overlaps(z1, z2) || !acb_overlaps(z1, z3)) { flint_printf("FAIL (overlap)\n"); flint_printf("tau1 = "); acb_printd(tau1, 15); flint_printf("\n\n"); flint_printf("tau2 = "); acb_printd(tau2, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_printf("z3 = "); acb_printd(z3, 15); flint_printf("\n\n"); flint_abort(); } acb_modular_lambda(tau1, tau1, prec2); if (!acb_overlaps(z1, tau1)) { flint_printf("FAIL (aliasing)\n"); flint_printf("tau1 = "); acb_printd(tau1, 15); flint_printf("\n\n"); flint_printf("tau2 = "); acb_printd(tau2, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(tau1); acb_clear(tau2); acb_clear(z1); acb_clear(z2); acb_clear(z3); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-psl2z_inv.c000066400000000000000000000034621461254215100212110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_psl2z_inv, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { psl2z_t f, g, h, i; psl2z_init(f); psl2z_init(g); psl2z_init(h); psl2z_init(i); psl2z_randtest(f, state, n_randint(state, 100)); psl2z_randtest(g, state, n_randint(state, 100)); psl2z_randtest(h, state, n_randint(state, 100)); psl2z_inv(g, f); psl2z_mul(h, f, g); psl2z_one(i); if (!psl2z_equal(h, i) || !psl2z_is_correct(g)) { flint_printf("FAIL\n"); flint_printf("f = "); psl2z_print(f); flint_printf("\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n"); flint_printf("h = "); psl2z_print(h); flint_printf("\n"); flint_printf("i = "); psl2z_print(i); flint_printf("\n"); flint_abort(); } psl2z_inv(f, f); if (!psl2z_equal(f, g) || !psl2z_is_correct(f)) { flint_printf("FAIL (aliasing)\n"); flint_printf("f = "); psl2z_print(f); flint_printf("\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n"); flint_abort(); } psl2z_clear(f); psl2z_clear(g); psl2z_clear(h); psl2z_clear(i); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-psl2z_mul.c000066400000000000000000000035031461254215100212060ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_psl2z_mul, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { psl2z_t f, g, h, u, v; psl2z_init(f); psl2z_init(g); psl2z_init(h); psl2z_init(u); psl2z_init(v); psl2z_randtest(f, state, n_randint(state, 100)); psl2z_randtest(g, state, n_randint(state, 100)); psl2z_randtest(h, state, n_randint(state, 100)); psl2z_randtest(u, state, n_randint(state, 100)); psl2z_randtest(v, state, n_randint(state, 100)); /* test (f*g)*h = f*(g*h) */ psl2z_mul(u, f, g); psl2z_mul(u, u, h); psl2z_mul(v, g, h); psl2z_mul(v, f, v); if (!psl2z_equal(u, v) || !psl2z_is_correct(u) || !psl2z_is_correct(v)) { flint_printf("FAIL\n"); flint_printf("f = "); psl2z_print(f); flint_printf("\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n"); flint_printf("h = "); psl2z_print(h); flint_printf("\n"); flint_printf("u = "); psl2z_print(u); flint_printf("\n"); flint_printf("v = "); psl2z_print(v); flint_printf("\n"); flint_abort(); } psl2z_clear(f); psl2z_clear(g); psl2z_clear(h); psl2z_clear(u); psl2z_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-theta.c000066400000000000000000000054561461254215100203750ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_theta, state) { slong iter; /* Test consistency with/without transform */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_t t1, t2, t3, t4, t1b, t2b, t3b, t4b, z, tau; slong prec0, prec1, prec2, e0; acb_init(t1); acb_init(t2); acb_init(t3); acb_init(t4); acb_init(t1b); acb_init(t2b); acb_init(t3b); acb_init(t4b); acb_init(z); acb_init(tau); prec0 = 2 + n_randint(state, 2000); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); e0 = 1 + n_randint(state, 100); acb_randtest(tau, state, prec0, e0); acb_randtest(z, state, prec0, e0); arb_abs(acb_imagref(tau), acb_imagref(tau)); if (n_randint(state, 3) == 0) arb_set_si(acb_realref(tau), -10 + n_randint(state, 20)); if (n_randint(state, 3) == 0) arb_zero(acb_imagref(z)); if (n_randint(state, 3) == 0) arb_zero(acb_realref(z)); acb_modular_theta(t1, t2, t3, t4, z, tau, prec1); acb_modular_theta_notransform(t1b, t2b, t3b, t4b, z, tau, prec2); if (!acb_overlaps(t1, t1b) || !acb_overlaps(t2, t2b) || !acb_overlaps(t3, t3b) || !acb_overlaps(t4, t4b)) { flint_printf("FAIL (overlap)\n"); flint_printf("z = "); acb_printd(z, 25); flint_printf("\n\n"); flint_printf("tau = "); acb_printd(tau, 25); flint_printf("\n\n"); flint_printf("t1 = "); acb_printd(t1, 15); flint_printf("\n\n"); flint_printf("t1b = "); acb_printd(t1b, 15); flint_printf("\n\n"); flint_printf("t2 = "); acb_printd(t2, 15); flint_printf("\n\n"); flint_printf("t2b = "); acb_printd(t2b, 15); flint_printf("\n\n"); flint_printf("t3 = "); acb_printd(t3, 15); flint_printf("\n\n"); flint_printf("t3b = "); acb_printd(t3b, 15); flint_printf("\n\n"); flint_printf("t4 = "); acb_printd(t4, 15); flint_printf("\n\n"); flint_printf("t4b = "); acb_printd(t4b, 15); flint_printf("\n\n"); flint_abort(); } acb_clear(t1); acb_clear(t2); acb_clear(t3); acb_clear(t4); acb_clear(t1b); acb_clear(t2b); acb_clear(t3b); acb_clear(t4b); acb_clear(z); acb_clear(tau); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-theta_const_sum_rs.c000066400000000000000000000045651461254215100231730ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_theta_const_sum_rs, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_t q, t2a, t2b, t3a, t3b, t4a, t4b; slong prec1, prec2, N; acb_init(q); acb_init(t2a); acb_init(t2b); acb_init(t3a); acb_init(t3b); acb_init(t4a); acb_init(t4b); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); N = n_randint(state, 300); acb_randtest(q, state, prec1, 3); acb_randtest(t2a, state, prec1, 3); acb_randtest(t2b, state, prec1, 3); acb_randtest(t3a, state, prec1, 3); acb_randtest(t3b, state, prec1, 3); acb_randtest(t4a, state, prec1, 3); acb_randtest(t4b, state, prec1, 3); acb_modular_theta_const_sum_basecase(t2a, t3a, t4a, q, N, prec1); acb_modular_theta_const_sum_rs(t2b, t3b, t4b, q, N, prec2); if (!acb_overlaps(t2a, t2b) || !acb_overlaps(t3a, t3b) || !acb_overlaps(t4a, t4b)) { flint_printf("FAIL (overlap) iter = %wd\n", iter); flint_printf("N = %wd\n", N); flint_printf("q = "); acb_printd(q, 50); flint_printf("\n\n"); flint_printf("t2a = "); acb_printd(t2a, 50); flint_printf("\n\n"); flint_printf("t2b = "); acb_printd(t2b, 50); flint_printf("\n\n"); flint_printf("t3a = "); acb_printd(t3a, 50); flint_printf("\n\n"); flint_printf("t3b = "); acb_printd(t3b, 50); flint_printf("\n\n"); flint_printf("t4a = "); acb_printd(t4a, 50); flint_printf("\n\n"); flint_printf("t4b = "); acb_printd(t4b, 50); flint_printf("\n\n"); flint_abort(); } acb_clear(q); acb_clear(t2a); acb_clear(t2b); acb_clear(t3a); acb_clear(t3b); acb_clear(t4a); acb_clear(t4b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-theta_jet.c000066400000000000000000000075631461254215100212400ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_theta_jet, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr t1a, t1b, t2a, t2b, t3a, t3b, t4a, t4b; acb_t z, tau; slong prec0, e0, prec1, prec2, len1, len2, i; acb_init(z); acb_init(tau); e0 = 1 + n_randint(state, 10); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); len1 = 1 + n_randint(state, 10); len2 = 1 + n_randint(state, 10); t1a = _acb_vec_init(len1); t2a = _acb_vec_init(len1); t3a = _acb_vec_init(len1); t4a = _acb_vec_init(len1); t1b = _acb_vec_init(len2); t2b = _acb_vec_init(len2); t3b = _acb_vec_init(len2); t4b = _acb_vec_init(len2); acb_randtest(z, state, prec0, e0); acb_randtest(tau, state, prec0, e0); arb_abs(acb_imagref(tau), acb_imagref(tau)); for (i = 0; i < len1; i++) { acb_randtest(t1a + i, state, prec0, e0); acb_randtest(t2a + i, state, prec0, e0); acb_randtest(t3a + i, state, prec0, e0); acb_randtest(t4a + i, state, prec0, e0); } for (i = 0; i < len2; i++) { acb_randtest(t1b + i, state, prec0, e0); acb_randtest(t2b + i, state, prec0, e0); acb_randtest(t3b + i, state, prec0, e0); acb_randtest(t4b + i, state, prec0, e0); } acb_modular_theta_jet_notransform(t1a, t2a, t3a, t4a, z, tau, len1, prec1); acb_modular_theta_jet(t1b, t2b, t3b, t4b, z, tau, len2, prec2); for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(t1a + i, t1b + i) || !acb_overlaps(t2a + i, t2b + i) || !acb_overlaps(t3a + i, t3b + i) || !acb_overlaps(t4a + i, t4b + i)) { flint_printf("FAIL (overlap) iter = %wd\n", iter); flint_printf("len1 = %wd, len2 = %wd, prec1 = %wd, prec2 = %wd\n\n", len1, len2, prec1, prec2); flint_printf("i = %wd\n\n", i); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n\n"); flint_printf("tau = "); acb_printd(tau, 50); flint_printf("\n\n"); flint_printf("t1a = "); acb_printd(t1a + i, 50); flint_printf("\n\n"); flint_printf("t1b = "); acb_printd(t1b + i, 50); flint_printf("\n\n"); flint_printf("t2a = "); acb_printd(t2a + i, 50); flint_printf("\n\n"); flint_printf("t2b = "); acb_printd(t2b + i, 50); flint_printf("\n\n"); flint_printf("t3a = "); acb_printd(t3a + i, 50); flint_printf("\n\n"); flint_printf("t3b = "); acb_printd(t3b + i, 50); flint_printf("\n\n"); flint_printf("t4a = "); acb_printd(t4a + i, 50); flint_printf("\n\n"); flint_printf("t4b = "); acb_printd(t4b + i, 50); flint_printf("\n\n"); flint_abort(); } } _acb_vec_clear(t1a, len1); _acb_vec_clear(t2a, len1); _acb_vec_clear(t3a, len1); _acb_vec_clear(t4a, len1); _acb_vec_clear(t1b, len2); _acb_vec_clear(t2b, len2); _acb_vec_clear(t3b, len2); _acb_vec_clear(t4b, len2); acb_clear(z); acb_clear(tau); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-theta_series.c000066400000000000000000000074361461254215100217470ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "acb_poly.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_theta_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t t1, t2, t3, t4, t1b, t2b, t3b, t4b, z; acb_t tau; slong len1, len2, prec1, prec2; unsigned int mask; acb_poly_init(t1); acb_poly_init(t1b); acb_poly_init(t2); acb_poly_init(t2b); acb_poly_init(t3); acb_poly_init(t3b); acb_poly_init(t4); acb_poly_init(t4b); acb_poly_init(z); acb_init(tau); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); len1 = n_randint(state, 6); len2 = n_randint(state, 6); acb_poly_randtest(t1, state, 10, prec1, 10); acb_poly_randtest(t2, state, 10, prec1, 10); acb_poly_randtest(t3, state, 10, prec1, 10); acb_poly_randtest(t4, state, 10, prec1, 10); acb_poly_randtest(z, state, 1 + n_randint(state, 10), prec1, 10); acb_randtest(tau, state, prec1, 10); acb_modular_theta_series(t1, t2, t3, t4, z, tau, len1, prec1); mask = n_randlimb(state); acb_modular_theta_series((mask & 1) ? t1b : NULL, (mask & 2) ? t2b : NULL, (mask & 4) ? t3b : NULL, (mask & 8) ? t4b : NULL, z, tau, len2, prec2); acb_poly_truncate(t1, FLINT_MIN(len1, len2)); acb_poly_truncate(t1b, FLINT_MIN(len1, len2)); acb_poly_truncate(t2, FLINT_MIN(len1, len2)); acb_poly_truncate(t2b, FLINT_MIN(len1, len2)); acb_poly_truncate(t3, FLINT_MIN(len1, len2)); acb_poly_truncate(t3b, FLINT_MIN(len1, len2)); acb_poly_truncate(t4, FLINT_MIN(len1, len2)); acb_poly_truncate(t4b, FLINT_MIN(len1, len2)); if (((mask & 1) && (!acb_poly_overlaps(t1, t1b))) || ((mask & 2) && (!acb_poly_overlaps(t2, t2b))) || ((mask & 4) && (!acb_poly_overlaps(t3, t3b))) || ((mask & 8) && (!acb_poly_overlaps(t4, t4b)))) { flint_printf("FAIL: consistency (mask)\n\n"); flint_printf("mask = %u\n\n", mask); flint_printf("len1 = %wd, len2 = %wd\n\n", len1, len2); flint_printf("z = "); acb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("tau = "); acb_printd(tau, 30); flint_printf("\n\n"); flint_printf("t1 = "); acb_poly_printd(t1, 30); flint_printf("\n\n"); flint_printf("t1b = "); acb_poly_printd(t1b, 30); flint_printf("\n\n"); flint_printf("t2 = "); acb_poly_printd(t2, 30); flint_printf("\n\n"); flint_printf("t2b = "); acb_poly_printd(t2b, 30); flint_printf("\n\n"); flint_printf("t3 = "); acb_poly_printd(t3, 30); flint_printf("\n\n"); flint_printf("t3b = "); acb_poly_printd(t3b, 30); flint_printf("\n\n"); flint_printf("t4 = "); acb_poly_printd(t4, 30); flint_printf("\n\n"); flint_printf("t4b = "); acb_poly_printd(t4b, 30); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(t1); acb_poly_clear(t1b); acb_poly_clear(t2); acb_poly_clear(t2b); acb_poly_clear(t3); acb_poly_clear(t3b); acb_poly_clear(t4); acb_poly_clear(t4b); acb_poly_clear(z); acb_clear(tau); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-theta_sum.c000066400000000000000000000104261461254215100212520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_theta_sum, state) { slong iter; /* Very weak test, just testing the error bounds and not that we compute the right functions */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_ptr t1a, t1b, t2a, t2b, t3a, t3b, t4a, t4b; acb_t w, q; int w_is_unit; slong prec0, e0, prec1, prec2, len1, len2, i; acb_init(w); acb_init(q); e0 = 1 + n_randint(state, 100); prec0 = 2 + n_randint(state, 3000); prec1 = 2 + n_randint(state, 3000); prec2 = 2 + n_randint(state, 3000); len1 = 1 + n_randint(state, 30); len2 = 1 + n_randint(state, 30); t1a = _acb_vec_init(len1); t2a = _acb_vec_init(len1); t3a = _acb_vec_init(len1); t4a = _acb_vec_init(len1); t1b = _acb_vec_init(len2); t2b = _acb_vec_init(len2); t3b = _acb_vec_init(len2); t4b = _acb_vec_init(len2); if (n_randint(state, 2)) { arb_randtest(acb_realref(q), state, prec0, e0); arb_zero(acb_imagref(q)); acb_exp_pi_i(w, q, prec0); w_is_unit = n_randint(state, 2); } else { acb_randtest(w, state, prec0, e0); w_is_unit = 0; } acb_randtest(q, state, prec0, e0); for (i = 0; i < len1; i++) { acb_randtest(t1a + i, state, prec0, e0); acb_randtest(t2a + i, state, prec0, e0); acb_randtest(t3a + i, state, prec0, e0); acb_randtest(t4a + i, state, prec0, e0); } for (i = 0; i < len2; i++) { acb_randtest(t1b + i, state, prec0, e0); acb_randtest(t2b + i, state, prec0, e0); acb_randtest(t3b + i, state, prec0, e0); acb_randtest(t4b + i, state, prec0, e0); } acb_modular_theta_sum(t1a, t2a, t3a, t4a, w, w_is_unit, q, len1, prec1); acb_modular_theta_sum(t1b, t2b, t3b, t4b, w, w_is_unit & n_randint(state, 2), q, len2, prec2); for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(t1a + i, t1b + i) || !acb_overlaps(t2a + i, t2b + i) || !acb_overlaps(t3a + i, t3b + i) || !acb_overlaps(t4a + i, t4b + i)) { flint_printf("FAIL (overlap) iter = %wd\n", iter); flint_printf("len1 = %wd, len2 = %wd, prec1 = %wd, prec2 = %wd\n\n", len1, len2, prec1, prec2); flint_printf("i = %wd\n\n", i); flint_printf("q = "); acb_printd(q, 50); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 50); flint_printf("\n\n"); flint_printf("t1a = "); acb_printd(t1a + i, 50); flint_printf("\n\n"); flint_printf("t1b = "); acb_printd(t1b + i, 50); flint_printf("\n\n"); flint_printf("t2a = "); acb_printd(t2a + i, 50); flint_printf("\n\n"); flint_printf("t2b = "); acb_printd(t2b + i, 50); flint_printf("\n\n"); flint_printf("t3a = "); acb_printd(t3a + i, 50); flint_printf("\n\n"); flint_printf("t3b = "); acb_printd(t3b + i, 50); flint_printf("\n\n"); flint_printf("t4a = "); acb_printd(t4a + i, 50); flint_printf("\n\n"); flint_printf("t4b = "); acb_printd(t4b + i, 50); flint_printf("\n\n"); flint_abort(); } } _acb_vec_clear(t1a, len1); _acb_vec_clear(t2a, len1); _acb_vec_clear(t3a, len1); _acb_vec_clear(t4a, len1); _acb_vec_clear(t1b, len2); _acb_vec_clear(t2b, len2); _acb_vec_clear(t3b, len2); _acb_vec_clear(t4b, len2); acb_clear(w); acb_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/test/t-transform.c000066400000000000000000000036751461254215100213040ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_modular.h" TEST_FUNCTION_START(acb_modular_transform, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { psl2z_t g; acb_t z, w1, w2, t; slong prec; psl2z_init(g); acb_init(z); acb_init(w1); acb_init(w2); acb_init(t); psl2z_randtest(g, state, n_randint(state, 20)); acb_randtest(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 20)); acb_randtest(w1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 20)); acb_randtest(w2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 20)); acb_modular_transform(w1, g, z, 2 + n_randint(state, 200)); prec = 2 + n_randint(state, 200); acb_mul_fmpz(t, z, &g->a, prec); acb_add_fmpz(t, t, &g->b, prec); acb_mul_fmpz(w2, z, &g->c, prec); acb_add_fmpz(w2, w2, &g->d, prec); acb_div(w2, t, w2, prec); if (!acb_overlaps(w1, w2)) { flint_printf("FAIL\n"); flint_printf("g = "); psl2z_print(g); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_abort(); } psl2z_clear(g); acb_clear(z); acb_clear(w1); acb_clear(w2); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_modular/theta.c000066400000000000000000000170771461254215100171570ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb.h" #include "acb_modular.h" static void acb_mul_4th_root(acb_t y, const acb_t x, int r, slong prec) { r &= 7; if (r == 0) { acb_set(y, x); } else if (r == 4) { acb_neg(y, x); } else if (r == 2) { acb_mul_onei(y, x); } else if (r == 6) { acb_mul_onei(y, x); acb_neg(y, y); } else { fmpq_t t; fmpq_init(t); fmpq_set_si(t, r, 4); arb_sin_cos_pi_fmpq(acb_imagref(y), acb_realref(y), t, prec); acb_mul(y, y, x, prec); fmpq_clear(t); } } void acb_modular_theta(acb_t theta1, acb_t theta2, acb_t theta3, acb_t theta4, const acb_t z, const acb_t tau, slong prec) { fmpq_t t; psl2z_t g; arf_t one_minus_eps; acb_t z_prime, tau_prime, q, q4, w, A, B; acb_struct thetas[4]; int w_is_unit, R[4], S[4], C; int t1r, t1i, t2r, t2i, t3r, t4r; if (!acb_is_finite(z) || !acb_is_finite(tau) || !arb_is_positive(acb_imagref(tau))) { acb_indeterminate(theta1); acb_indeterminate(theta2); acb_indeterminate(theta3); acb_indeterminate(theta4); return; } /* special cases when real(tau) is an integer n: z is real: theta1 real if n mod 4 = 0 theta1 imaginary if n mod 4 = 2 theta2 real if n mod 4 = 0 theta2 imaginary if n mod 4 = 2 theta3 real always theta4 real always z is imaginary: theta1 real if n mod 4 = 2 theta1 imaginary if n mod 4 = 0 theta2 real if n mod 4 = 0 theta2 imaginary if n mod 4 = 2 theta3 real always theta4 real always */ t1r = t1i = t2r = t2i = t3r = t4r = 0; if (arb_is_int(acb_realref(tau))) { int val; if (arb_is_int_2exp_si(acb_realref(tau), 2)) val = 2; else if (arb_is_int_2exp_si(acb_realref(tau), 1)) val = 1; else val = 0; if (arb_is_zero(acb_imagref(z))) { t3r = t4r = 1; if (val == 2) t1r = t2r = 1; if (val == 1) t1i = t2i = 1; } if (arb_is_zero(acb_realref(z))) { t3r = t4r = 1; if (val == 2) t1i = t2r = 1; if (val == 1) t1r = t2i = 1; } } psl2z_init(g); fmpq_init(t); arf_init(one_minus_eps); acb_init(z_prime); acb_init(tau_prime); acb_init(q); acb_init(q4); acb_init(w); acb_init(thetas + 0); acb_init(thetas + 1); acb_init(thetas + 2); acb_init(thetas + 3); acb_init(A); acb_init(B); /* move tau to the fundamental domain */ arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); /* compute transformation parameters */ acb_modular_theta_transform(R, S, &C, g); if (C == 0) { acb_set(z_prime, z); acb_one(A); } else { /* B = 1/(c*tau+d) (temporarily) */ acb_mul_fmpz(B, tau, &g->c, prec); acb_add_fmpz(B, B, &g->d, prec); acb_inv(B, B, prec); /* -z/(c*tau+d) */ acb_mul(z_prime, z, B, prec); acb_neg(z_prime, z_prime); /* A = sqrt(i/(c*tau+d)) */ acb_mul_onei(A, B); acb_sqrt(A, A, prec); /* B = exp(-pi i c z^2/(c*tau+d)) */ /* we first compute the argument here */ if (acb_is_zero(z)) { acb_zero(B); } else { acb_mul(B, z_prime, z, prec); acb_mul_fmpz(B, B, &g->c, prec); } } /* reduce z_prime modulo tau_prime if the imaginary part is large */ if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z_prime)), 4) > 0) { arb_t nn; arb_init(nn); arf_div(arb_midref(nn), arb_midref(acb_imagref(z_prime)), arb_midref(acb_imagref(tau_prime)), prec, ARF_RND_DOWN); arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), 1); arf_add_ui(arb_midref(nn), arb_midref(nn), 1, prec, ARF_RND_DOWN); arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), -1); arf_floor(arb_midref(nn), arb_midref(nn)); /* transform z_prime further */ acb_submul_arb(z_prime, tau_prime, nn, prec); /* add -tau n^2 - 2nz to B */ arb_mul_2exp_si(nn, nn, 1); acb_submul_arb(B, z_prime, nn, prec); arb_mul_2exp_si(nn, nn, -1); arb_sqr(nn, nn, prec); acb_submul_arb(B, tau_prime, nn, prec); /* theta1, theta4 pick up factors (-1)^n */ if (!arf_is_int_2exp_si(arb_midref(nn), 1)) { int i; for (i = 0; i < 4; i++) { if (S[i] == 0 || S[i] == 3) R[i] += 4; } } C = 1; arb_clear(nn); } if (C != 0) acb_exp_pi_i(B, B, prec); /* compute q_{1/4}, q */ acb_mul_2exp_si(q4, tau_prime, -2); acb_exp_pi_i(q4, q4, prec); acb_pow_ui(q, q4, 4, prec); /* compute w */ acb_exp_pi_i(w, z_prime, prec); w_is_unit = arb_is_zero(acb_imagref(z_prime)); /* evaluate theta functions of transformed variables */ acb_modular_theta_sum(thetas + 0, thetas + 1, thetas + 2, thetas + 3, w, w_is_unit, q, 1, prec); acb_mul(thetas + 0, thetas + 0, q4, prec); acb_mul(thetas + 1, thetas + 1, q4, prec); /* multiply by roots of unity */ acb_mul_4th_root(theta1, thetas + S[0], R[0], prec); acb_mul_4th_root(theta2, thetas + S[1], R[1], prec); acb_mul_4th_root(theta3, thetas + S[2], R[2], prec); acb_mul_4th_root(theta4, thetas + S[3], R[3], prec); if (C != 0) { acb_mul(A, A, B, prec); acb_mul(theta1, theta1, A, prec); acb_mul(theta2, theta2, A, prec); acb_mul(theta3, theta3, A, prec); acb_mul(theta4, theta4, A, prec); } if (t1r) arb_zero(acb_imagref(theta1)); if (t1i) arb_zero(acb_realref(theta1)); if (t2r) arb_zero(acb_imagref(theta2)); if (t2i) arb_zero(acb_realref(theta2)); if (t3r) arb_zero(acb_imagref(theta3)); if (t4r) arb_zero(acb_imagref(theta4)); psl2z_clear(g); fmpq_clear(t); arf_clear(one_minus_eps); acb_clear(z_prime); acb_clear(tau_prime); acb_clear(q); acb_clear(q4); acb_clear(w); acb_clear(thetas + 0); acb_clear(thetas + 1); acb_clear(thetas + 2); acb_clear(thetas + 3); acb_clear(A); acb_clear(B); } void acb_modular_theta_notransform(acb_t theta1, acb_t theta2, acb_t theta3, acb_t theta4, const acb_t z, const acb_t tau, slong prec) { acb_t q, q4, w; int w_is_unit; acb_init(q); acb_init(q4); acb_init(w); /* compute q_{1/4}, q */ acb_mul_2exp_si(q4, tau, -2); acb_exp_pi_i(q4, q4, prec); acb_pow_ui(q, q4, 4, prec); /* compute w */ acb_exp_pi_i(w, z, prec); w_is_unit = arb_is_zero(acb_imagref(z)); /* evaluate theta functions */ acb_modular_theta_sum(theta1, theta2, theta3, theta4, w, w_is_unit, q, 1, prec); acb_mul(theta1, theta1, q4, prec); acb_mul(theta2, theta2, q4, prec); acb_clear(q); acb_clear(q4); acb_clear(w); } flint-3.1.3/src/acb_modular/theta_const_sum.c000066400000000000000000000035541461254215100212440ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_theta_const_sum(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong prec) { mag_t qmag, err; double log2q_approx; int is_real, is_real_or_imag; slong N; mag_init(qmag); mag_init(err); acb_get_mag(qmag, q); log2q_approx = mag_get_d_log2_approx(qmag); is_real = arb_is_zero(acb_imagref(q)); is_real_or_imag = is_real || arb_is_zero(acb_realref(q)); if (log2q_approx >= 0.0) { N = 1; mag_inf(err); } else { N = 0; while (0.05 * N * N < prec) { if (log2q_approx * ((N+2)*(N+2)/4) < -prec - 2) break; N++; } N = (N+2)*(N+2)/4; mag_geom_series(err, qmag, N); mag_mul_2exp_si(err, err, 1); /* each term is taken twice */ if (mag_is_inf(err)) N = 1; } if (N < 1800) acb_modular_theta_const_sum_basecase(theta2, theta3, theta4, q, N, prec); else acb_modular_theta_const_sum_rs(theta2, theta3, theta4, q, N, prec); if (is_real_or_imag) arb_add_error_mag(acb_realref(theta2), err); else acb_add_error_mag(theta2, err); if (is_real) { arb_add_error_mag(acb_realref(theta3), err); arb_add_error_mag(acb_realref(theta4), err); } else { acb_add_error_mag(theta3, err); acb_add_error_mag(theta4, err); } mag_clear(qmag); mag_clear(err); } flint-3.1.3/src/acb_modular/theta_const_sum_basecase.c000066400000000000000000000110501461254215100230600ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_theta_const_sum_basecase(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong N, slong prec) { slong * tab; slong k, term_prec; double log2q_approx, log2term_approx; mag_t qmag; acb_ptr qpow; acb_t s1, s2, s3, t1, t2; if (N < 2) { acb_set_ui(theta2, 2 * (N > 0)); acb_set_ui(theta3, N > 0); acb_set(theta4, theta3); return; } if (N < 25) { acb_t q1, q2, q4, q8, q16; acb_init(q1); acb_init(q2); acb_init(q4); acb_init(q8); acb_init(q16); acb_set_round(q1, q, prec); if (N > 2) acb_mul(q2, q1, q1, prec); if (N > 4) acb_mul(q4, q2, q2, prec); if (N > 9) acb_mul(q8, q4, q4, prec); if (N > 16) acb_mul(q16, q8, q8, prec); /* theta2 = 2 + 2q^2 + 2q^4 [2q^2 + 2q^8 + 2q^16] */ if (N > 6) { if (N > 12) { acb_add(theta2, q2, q8, prec); if (N > 20) acb_add(theta2, theta2, q16, prec); acb_mul(theta2, theta2, q4, prec); } else { acb_mul(theta2, q2, q4, prec); } acb_add(theta2, theta2, q2, prec); acb_add_ui(theta2, theta2, 1, prec); } else if (N > 2) acb_add_ui(theta2, q2, 1, prec); else acb_one(theta2); acb_mul_2exp_si(theta2, theta2, 1); /* theta3 = [1 + 2q^4 + 2q^16] + [2q + 2q^9] */ /* theta4 = [1 + 2q^4 + 2q^16] - [2q + 2q^9] */ if (N > 4) { if (N > 16) acb_add(q4, q4, q16, prec); acb_mul_2exp_si(q4, q4, 1); acb_add_ui(q4, q4, 1, prec); if (N > 9) acb_addmul(q1, q1, q8, prec); acb_mul_2exp_si(q1, q1, 1); acb_add(theta3, q4, q1, prec); acb_sub(theta4, q4, q1, prec); } else { acb_mul_2exp_si(q1, q1, 1); acb_add_ui(theta3, q1, 1, prec); acb_sub_ui(theta4, q1, 1, prec); acb_neg(theta4, theta4); } acb_clear(q1); acb_clear(q2); acb_clear(q4); acb_clear(q8); acb_clear(q16); return; } mag_init(qmag); acb_init(s1); acb_init(s2); acb_init(s3); acb_init(t1); acb_init(t2); tab = flint_calloc(N, sizeof(slong)); qpow = _acb_vec_init(N); for (k = 0; k*(k+1) < N; k++) tab[k*(k+1)] = -1; for (k = 0; 4*k*k < N; k++) tab[4*k*k] = -1; for (k = 0; 4*k*(k+1) + 1 < N; k++) tab[4*k*(k+1)] = -1; if (N > 0) tab[0] = 0; if (N > 1) tab[1] = 1; acb_modular_fill_addseq(tab, N); acb_get_mag(qmag, q); log2q_approx = mag_get_d_log2_approx(qmag); for (k = 0; k < N; k++) { if (k == 0) { acb_one(qpow + k); } else if (k == 1) { acb_set_round(qpow + k, q, prec); } else if (tab[k] != 0) { log2term_approx = k * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); _acb_modular_mul(qpow + k, t1, t2, qpow + tab[k], qpow + k - tab[k], term_prec, prec); } } for (k = 0; k*(k+1) < N; k++) acb_add(s1, s1, qpow + k*(k+1), prec); for (k = 1; 4*k*k < N; k++) acb_add(s2, s2, qpow + 4*k*k, prec); for (k = 0; 4*k*(k+1) + 1 < N; k++) acb_add(s3, s3, qpow + 4*k*(k+1), prec); /* theta2 = 2 + 2q^2 + 2q^6 + 2q^12 + 2q^20 + 2q^30 + ... theta3 = 1 + 2 (q^4 + q^16 + ...) + 2q (1 + q^8 + q^24 + ...) theta4 = 1 + 2 (q^4 + q^16 + ...) - 2q (1 + q^8 + q^24 + ...) */ acb_mul(s3, s3, q, prec); acb_mul_2exp_si(s3, s3, 1); acb_mul_2exp_si(s2, s2, 1); acb_add(theta3, s2, s3, prec); acb_sub(theta4, s2, s3, prec); acb_add_ui(theta3, theta3, 1, prec); acb_add_ui(theta4, theta4, 1, prec); acb_mul_2exp_si(theta2, s1, 1); _acb_vec_clear(qpow, N); flint_free(tab); acb_clear(s1); acb_clear(s2); acb_clear(s3); acb_clear(t1); acb_clear(t2); mag_clear(qmag); } flint-3.1.3/src/acb_modular/theta_const_sum_rs.c000066400000000000000000000137641461254215100217540ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" static const int square_best_m[] = { 2, 3, 4, 8, 12, 16, 32, 48, 80, 96, 112, 144, 240, 288, 336, 480, 560, 576, 720, 1008, 1440, 1680, 2016, 2640, 2880, 3600, 4032, 5040, 7920, 9360, 10080, 15840, 18480, 20160, 25200, 31680, 37440, 39600, 44352, 50400, 55440, 65520, 85680, 95760, 102960, 110880, 131040, 171360, 191520, 205920, 221760, 262080, 277200, 327600, 383040, 411840, 514800, 554400, 655200, 720720, 942480, 0 }; static const int square_best_m_residues[] = { 2, 2, 2, 3, 4, 4, 7, 8, 12, 14, 16, 16, 24, 28, 32, 42, 48, 48, 48, 64, 84, 96, 112, 144, 144, 176, 192, 192, 288, 336, 336, 504, 576, 576, 704, 864, 1008, 1056, 1152, 1232, 1152, 1344, 1728, 1920, 2016, 2016, 2352, 3024, 3360, 3528, 3456, 4032, 4224, 4928, 5760, 6048, 7392, 7392, 8624, 8064, 10368, 0 }; static const int trigonal_best_m[] = { 2, 6, 10, 14, 18, 30, 42, 66, 70, 90, 126, 198, 210, 330, 390, 450, 630, 990, 1170, 1386, 1638, 2142, 2310, 2730, 3150, 4950, 5850, 6930, 8190, 10710, 11970, 12870, 16830, 18018, 23562, 26334, 27846, 30030, 34650, 40950, 53550, 59850, 64350, 84150, 90090, 117810, 131670, 139230, 155610, 188370, 203490, 218790, 244530, 270270, 296010, 306306, 342342, 414414, 447678, 450450, 589050, 658350, 696150, 778050, 941850, 0 }; static const int trigonal_best_m_residues[] = { 1, 2, 3, 4, 4, 6, 8, 12, 12, 12, 16, 24, 24, 36, 42, 44, 48, 72, 84, 96, 112, 144, 144, 168, 176, 264, 308, 288, 336, 432, 480, 504, 648, 672, 864, 960, 1008, 1008, 1056, 1232, 1584, 1760, 1848, 2376, 2016, 2592, 2880, 3024, 3360, 4032, 4320, 4536, 5040, 5544, 6048, 6048, 6720, 8064, 8640, 7392, 9504, 10560, 11088, 12320, 14784, 0, }; slong acb_modular_rs_optimal_m(const int * best_ms, const int * num_residues, slong N) { slong i, m, cost, best_i, best_m, best_cost; best_i = 0; best_m = best_ms[0]; best_cost = WORD_MAX; for (i = 0; (m = best_ms[i]) != 0; i++) { cost = N / m + num_residues[i]; if (i == 0 || cost < best_cost) { best_i = i; best_cost = cost; best_m = m; } } /* flint_printf("N = %wd, best_m = %wd, best_cost = %wd, s(m) = %d\n", N, best_m, best_cost, num_residues[best_i]); */ i = best_i; return best_m; } void acb_modular_theta_const_sum_rs(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong N, slong prec) { slong * tab; slong k, term_prec, i, e, eprev; slong M, m2, m3, num_square, num_trigonal; double log2q_approx, log2term_approx; acb_ptr qpow; acb_t tmp1, tmp2; mag_t qmag; mag_init(qmag); acb_get_mag(qmag, q); log2q_approx = mag_get_d_log2_approx(qmag); mag_clear(qmag); acb_init(tmp1); acb_init(tmp2); /* choose rectangular splitting parameters */ m2 = acb_modular_rs_optimal_m(trigonal_best_m, trigonal_best_m_residues, N); m3 = acb_modular_rs_optimal_m(square_best_m, square_best_m_residues, N); M = FLINT_MAX(m2, m3) + 1; /* build addition sequence */ tab = flint_calloc(M, sizeof(slong)); for (k = 0; k*(k+1) < N; k++) tab[(k*(k+1)) % m2] = -1; num_trigonal = k; for (k = 0; k*k < N; k++) tab[(k*k) % m3] = -1; num_square = k; tab[m2] = -1; tab[m3] = -1; /* compute powers in addition sequence */ qpow = _acb_vec_init(M); acb_modular_fill_addseq(tab, M); for (k = 0; k < M; k++) { if (k == 0) { acb_one(qpow + k); } else if (k == 1) { acb_set_round(qpow + k, q, prec); } else if (tab[k] != 0) { log2term_approx = k * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + tab[k], qpow + k - tab[k], term_prec, prec); } } /* compute theta2 */ acb_zero(theta2); term_prec = prec; for (k = num_trigonal - 1; k >= 0; k--) { e = k * (k + 1); /* exponent */ eprev = (k + 1) * (k + 2); log2term_approx = e * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); /* giant steps */ for (i = e / m2; i < eprev / m2; i++) { if (!acb_is_zero(theta2)) _acb_modular_mul(theta2, tmp1, tmp2, theta2, qpow + m2, term_prec, prec); } acb_add(theta2, theta2, qpow + (e % m2), prec); } acb_mul_2exp_si(theta2, theta2, 1); /* compute theta3, theta4 */ acb_zero(theta3); acb_zero(theta4); term_prec = prec; for (k = num_square - 1; k >= 0; k--) { e = k * k; /* exponent */ eprev = (k + 1) * (k + 1); log2term_approx = e * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); /* giant steps */ for (i = e / m3; i < eprev / m3; i++) { if (!acb_is_zero(theta3)) _acb_modular_mul(theta3, tmp1, tmp2, theta3, qpow + m3, term_prec, prec); if (!acb_is_zero(theta4)) _acb_modular_mul(theta4, tmp1, tmp2, theta4, qpow + m3, term_prec, prec); } if (k == 0) { acb_mul_2exp_si(theta3, theta3, 1); acb_mul_2exp_si(theta4, theta4, 1); } acb_add(theta3, theta3, qpow + (e % m3), prec); if (k % 2 == 0) acb_add(theta4, theta4, qpow + (e % m3), prec); else acb_sub(theta4, theta4, qpow + (e % m3), prec); } acb_clear(tmp1); acb_clear(tmp2); _acb_vec_clear(qpow, M); flint_free(tab); } flint-3.1.3/src/acb_modular/theta_jet.c000066400000000000000000000210631461254215100200070ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb_modular.h" #include "acb_poly.h" static void _acb_vec_mul_4th_root(acb_ptr y, acb_srcptr x, slong len, int r, slong prec) { slong k; r &= 7; if (r == 0) { _acb_vec_set(y, x, len); } else if (r == 4) { _acb_vec_neg(y, x, len); } else if (r == 2) { for (k = 0; k < len; k++) acb_mul_onei(y + k, x + k); } else if (r == 6) { for (k = 0; k < len; k++) { acb_mul_onei(y + k, x + k); acb_neg(y + k, y + k); } } else { fmpq_t t; acb_t w; fmpq_init(t); acb_init(w); fmpq_set_si(t, r, 4); arb_sin_cos_pi_fmpq(acb_imagref(w), acb_realref(w), t, prec); _acb_vec_scalar_mul(y, x, len, w, prec); fmpq_clear(t); acb_clear(w); } } void acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t z, const acb_t tau, slong len, slong prec) { fmpq_t t; psl2z_t g; arf_t one_minus_eps; acb_t z_prime, tau_prime, q, q4, w, A; acb_ptr B; acb_ptr thetas[4]; int w_is_unit, R[4], S[4], C, rescale; slong k; if (len == 0) return; if (len == 1) { acb_modular_theta(theta1, theta2, theta3, theta4, z, tau, prec); return; } psl2z_init(g); arf_init(one_minus_eps); acb_init(tau_prime); /* move tau to the fundamental domain */ arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); if (psl2z_is_one(g) && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 4) <= 0) { acb_modular_theta_jet_notransform(theta1, theta2, theta3, theta4, z, tau, len, prec); } else { fmpq_init(t); acb_init(z_prime); acb_init(q); acb_init(q4); acb_init(w); acb_init(A); B = _acb_vec_init(len); thetas[0] = _acb_vec_init(len); thetas[1] = _acb_vec_init(len); thetas[2] = _acb_vec_init(len); thetas[3] = _acb_vec_init(len); /* compute transformation parameters */ acb_modular_theta_transform(R, S, &C, g); if (C == 0) { acb_set(z_prime, z); acb_one(A); rescale = 0; } else { rescale = 1; /* B = 1/(c*tau+d) (temporarily) */ acb_mul_fmpz(B, tau, &g->c, prec); acb_add_fmpz(B, B, &g->d, prec); acb_inv(B, B, prec); /* z' = -z/(c*tau+d) */ acb_mul(z_prime, z, B, prec); acb_neg(z_prime, z_prime); /* A = sqrt(i/(c*tau+d)) */ acb_mul_onei(A, B); acb_sqrt(A, A, prec); /* B = c/(c*tau+d) */ acb_mul_fmpz(B, B, &g->c, prec); /* B[2] = -c/(c*tau+d) */ if (len >= 3) acb_neg(B + 2, B); if (len >= 2) { /* B[1] = -2*z*c/(c*tau+d) */ acb_mul(B + 1, B, z, prec); acb_mul_2exp_si(B + 1, B + 1, 1); acb_neg(B + 1, B + 1); } acb_mul(B, z_prime, z, prec); acb_mul_fmpz(B, B, &g->c, prec); /* we will have B = exp(-pi i c (z+x)^2/(c*tau+d)) after computing the exponential later */ } /* reduce z_prime modulo tau_prime if the imaginary part is large */ if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z_prime)), 4) > 0) { arb_t nn; arb_init(nn); arf_div(arb_midref(nn), arb_midref(acb_imagref(z_prime)), arb_midref(acb_imagref(tau_prime)), prec, ARF_RND_DOWN); arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), 1); arf_add_ui(arb_midref(nn), arb_midref(nn), 1, prec, ARF_RND_DOWN); arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), -1); arf_floor(arb_midref(nn), arb_midref(nn)); /* transform z_prime further */ acb_submul_arb(z_prime, tau_prime, nn, prec); /* add -tau n^2 - 2n(z+x)' to B */ arb_mul_2exp_si(nn, nn, 1); acb_submul_arb(B, z_prime, nn, prec); if (len >= 2) { acb_t u; acb_init(u); /* the x picks up a factor -1/(tau*c+d) */ if (rescale) { acb_mul_fmpz(u, tau, &g->c, prec); acb_add_fmpz(u, u, &g->d, prec); acb_inv(u, u, prec); acb_neg(u, u); acb_mul_arb(u, u, nn, prec); acb_sub(B + 1, B + 1, u, prec); } else { acb_sub_arb(B + 1, B + 1, nn, prec); } acb_clear(u); } arb_mul_2exp_si(nn, nn, -1); arb_sqr(nn, nn, prec); acb_submul_arb(B, tau_prime, nn, prec); /* theta1, theta4 pick up factors (-1)^n */ if (!arf_is_int_2exp_si(arb_midref(nn), 1)) { int i; for (i = 0; i < 4; i++) { if (S[i] == 0 || S[i] == 3) R[i] += 4; } } C = 1; arb_clear(nn); } if (C != 0) _acb_poly_exp_pi_i_series(B, B, FLINT_MIN(len, 3), len, prec); /* compute q_{1/4}, q */ acb_mul_2exp_si(q4, tau_prime, -2); acb_exp_pi_i(q4, q4, prec); acb_pow_ui(q, q4, 4, prec); /* compute w */ acb_exp_pi_i(w, z_prime, prec); w_is_unit = arb_is_zero(acb_imagref(z_prime)); /* evaluate theta functions of transformed variables */ acb_modular_theta_sum(thetas[0], thetas[1], thetas[2], thetas[3], w, w_is_unit, q, len, prec); /* correct for change of variables */ if (rescale) { /* [-1/(tau*c+d)]]^k */ acb_mul_fmpz(z_prime, tau, &g->c, prec); acb_add_fmpz(z_prime, z_prime, &g->d, prec); acb_inv(z_prime, z_prime, prec); acb_neg(z_prime, z_prime); acb_set(w, z_prime); for (k = 1; k < len; k++) { acb_mul(thetas[0] + k, thetas[0] + k, w, prec); acb_mul(thetas[1] + k, thetas[1] + k, w, prec); acb_mul(thetas[2] + k, thetas[2] + k, w, prec); acb_mul(thetas[3] + k, thetas[3] + k, w, prec); acb_mul(w, w, z_prime, prec); } } /* todo: fuse */ _acb_vec_scalar_mul(thetas[0], thetas[0], len, q4, prec); _acb_vec_scalar_mul(thetas[1], thetas[1], len, q4, prec); /* multiply by roots of unity */ _acb_vec_mul_4th_root(theta1, thetas[S[0]], len, R[0], prec); _acb_vec_mul_4th_root(theta2, thetas[S[1]], len, R[1], prec); _acb_vec_mul_4th_root(theta3, thetas[S[2]], len, R[2], prec); _acb_vec_mul_4th_root(theta4, thetas[S[3]], len, R[3], prec); if (C != 0) { _acb_vec_scalar_mul(B, B, len, A, prec); _acb_poly_mullow(thetas[0], theta1, len, B, len, len, prec); _acb_poly_mullow(thetas[1], theta2, len, B, len, len, prec); _acb_poly_mullow(thetas[2], theta3, len, B, len, len, prec); _acb_poly_mullow(thetas[3], theta4, len, B, len, len, prec); for (k = 0; k < len; k++) acb_swap(theta1 + k, thetas[0] + k); for (k = 0; k < len; k++) acb_swap(theta2 + k, thetas[1] + k); for (k = 0; k < len; k++) acb_swap(theta3 + k, thetas[2] + k); for (k = 0; k < len; k++) acb_swap(theta4 + k, thetas[3] + k); } fmpq_clear(t); acb_clear(z_prime); acb_clear(q); acb_clear(q4); acb_clear(w); acb_clear(A); _acb_vec_clear(B, len); _acb_vec_clear(thetas[0], len); _acb_vec_clear(thetas[1], len); _acb_vec_clear(thetas[2], len); _acb_vec_clear(thetas[3], len); } psl2z_clear(g); arf_clear(one_minus_eps); acb_clear(tau_prime); } flint-3.1.3/src/acb_modular/theta_jet_notransform.c000066400000000000000000000022731461254215100224410ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_theta_jet_notransform(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t z, const acb_t tau, slong len, slong prec) { acb_t q, q4, w; int w_is_unit; acb_init(q); acb_init(q4); acb_init(w); /* compute q_{1/4}, q */ acb_mul_2exp_si(q4, tau, -2); acb_exp_pi_i(q4, q4, prec); acb_pow_ui(q, q4, 4, prec); /* compute w */ acb_exp_pi_i(w, z, prec); w_is_unit = arb_is_zero(acb_imagref(z)); /* evaluate theta functions */ acb_modular_theta_sum(theta1, theta2, theta3, theta4, w, w_is_unit, q, len, prec); _acb_vec_scalar_mul(theta1, theta1, len, q4, prec); _acb_vec_scalar_mul(theta2, theta2, len, q4, prec); acb_clear(q); acb_clear(q4); acb_clear(w); } flint-3.1.3/src/acb_modular/theta_series.c000066400000000000000000000065241461254215100205240ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_modular.h" void _acb_modular_theta_series(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec) { acb_ptr t1, t2, t3, t4, t, v; zlen = FLINT_MIN(zlen, len); if (zlen <= 0) return; t = _acb_vec_init(4 * len); t1 = t; t2 = t1 + len; t3 = t2 + len; t4 = t3 + len; acb_modular_theta_jet(t1, t2, t3, t4, z, tau, len, prec); if (len == 1) { if (theta1 != NULL) acb_set(theta1, t1); if (theta2 != NULL) acb_set(theta2, t2); if (theta3 != NULL) acb_set(theta3, t3); if (theta4 != NULL) acb_set(theta4, t4); } else { v = _acb_vec_init(zlen); /* compose with nonconstant part */ acb_zero(v); _acb_vec_set(v + 1, z + 1, zlen - 1); if (theta1 != NULL) _acb_poly_compose_series(theta1, t1, len, v, zlen, len, prec); if (theta2 != NULL) _acb_poly_compose_series(theta2, t2, len, v, zlen, len, prec); if (theta3 != NULL) _acb_poly_compose_series(theta3, t3, len, v, zlen, len, prec); if (theta4 != NULL) _acb_poly_compose_series(theta4, t4, len, v, zlen, len, prec); _acb_vec_clear(v, zlen); } _acb_vec_clear(t, 4 * len); } void acb_modular_theta_series(acb_poly_t theta1, acb_poly_t theta2, acb_poly_t theta3, acb_poly_t theta4, const acb_poly_t z, const acb_t tau, slong len, slong prec) { if (len == 0) { if (theta1 != NULL) acb_poly_zero(theta1); if (theta2 != NULL) acb_poly_zero(theta2); if (theta3 != NULL) acb_poly_zero(theta3); if (theta4 != NULL) acb_poly_zero(theta4); return; } if (z->length <= 1) len = 1; if (theta1 != NULL) acb_poly_fit_length(theta1, len); if (theta2 != NULL) acb_poly_fit_length(theta2, len); if (theta3 != NULL) acb_poly_fit_length(theta3, len); if (theta4 != NULL) acb_poly_fit_length(theta4, len); if (z->length == 0) { acb_t t; acb_init(t); _acb_modular_theta_series(theta1 ? theta1->coeffs : NULL, theta2 ? theta2->coeffs : NULL, theta3 ? theta3->coeffs : NULL, theta4 ? theta4->coeffs : NULL, t, 1, tau, len, prec); acb_clear(t); } else { _acb_modular_theta_series(theta1 ? theta1->coeffs : NULL, theta2 ? theta2->coeffs : NULL, theta3 ? theta3->coeffs : NULL, theta4 ? theta4->coeffs : NULL, z->coeffs, z->length, tau, len, prec); } if (theta1 != NULL) _acb_poly_set_length(theta1, len); if (theta2 != NULL) _acb_poly_set_length(theta2, len); if (theta3 != NULL) _acb_poly_set_length(theta3, len); if (theta4 != NULL) _acb_poly_set_length(theta4, len); if (theta1 != NULL) _acb_poly_normalise(theta1); if (theta2 != NULL) _acb_poly_normalise(theta2); if (theta3 != NULL) _acb_poly_normalise(theta3); if (theta4 != NULL) _acb_poly_normalise(theta4); } flint-3.1.3/src/acb_modular/theta_sum.c000066400000000000000000000325541461254215100200400ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_theta_sum(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t w, int w_is_unit, const acb_t q, slong len, slong prec) { mag_t qmag, wmag, vmag; mag_ptr err; double log2q_approx, log2w_approx, log2term_approx; slong e, e1, e2, k, k1, k2, r, n, N, WN, term_prec; slong *exponents, *aindex, *bindex; acb_ptr qpow, wpow, vpow; acb_t tmp1, tmp2, v; int q_is_real, w_is_one; q_is_real = arb_is_zero(acb_imagref(q)); w_is_one = acb_is_one(w); if (w_is_one && len == 1) { acb_modular_theta_const_sum(theta2, theta3, theta4, q, prec); acb_zero(theta1); return; } mag_init(qmag); mag_init(wmag); mag_init(vmag); acb_init(tmp1); acb_init(tmp2); acb_init(v); err = _mag_vec_init(len); if (w_is_one) acb_one(v); else if (w_is_unit) acb_conj(v, w); else acb_inv(v, w, prec); acb_get_mag(qmag, q); log2q_approx = mag_get_d_log2_approx(qmag); if (w_is_unit) { mag_one(wmag); mag_one(vmag); log2w_approx = 0.0; } else { acb_get_mag(wmag, w); acb_get_mag(vmag, v); mag_max(wmag, wmag, vmag); log2w_approx = mag_get_d_log2_approx(wmag); } if (log2q_approx >= 0.0) { N = 1; for (r = 0; r < len; r++) mag_inf(err + r); } else /* Pick N and compute error bound */ { mag_t den, cmag, dmag; mag_init(den); mag_init(cmag); mag_init(dmag); N = 1; while (0.05 * N * N < prec) { log2term_approx = log2q_approx * ((N+2)*(N+2)/4) + (N+2)*log2w_approx; if (log2term_approx < -prec - 2) break; N++; } if (len == 1) { if (w_is_unit) { mag_one(den); mag_sub_lower(den, den, qmag); /* 1 - |q| is good enough */ } else /* denominator: 1 - |q|^(floor((N+1)/2)+1) * max(|w|,1/|w|) */ { mag_pow_ui(err, qmag, (N + 1) / 2 + 1); mag_mul(err, err, wmag); mag_one(den); mag_sub_lower(den, den, err); } /* no convergence */ if (mag_is_zero(den)) { N = 1; mag_inf(err); } else if (w_is_unit) { mag_pow_ui(err, qmag, ((N + 2) * (N + 2)) / 4); mag_div(err, err, den); mag_mul_2exp_si(err, err, 1); } else { mag_pow_ui(err, qmag, ((N + 2) * (N + 2)) / 4); mag_pow_ui(vmag, wmag, N + 2); mag_mul(err, err, vmag); mag_div(err, err, den); mag_mul_2exp_si(err, err, 1); } } else { /* numerator: 2 |q|^E * max(|w|,|v|)^(N+2) * (N+2)^r */ mag_pow_ui(err, qmag, ((N + 2) * (N + 2)) / 4); if (!w_is_one) { mag_pow_ui(vmag, wmag, N + 2); mag_mul(err, err, vmag); } mag_mul_2exp_si(err, err, 1); for (r = 1; r < len; r++) mag_mul_ui(err + r, err + r - 1, N + 2); /* den: 1 - |q|^floor((N+1)/2+1) * max(|w|,|v|) * exp(r/(N+2)) */ mag_pow_ui(cmag, qmag, (N + 1) / 2 + 1); mag_mul(cmag, cmag, wmag); for (r = 0; r < len; r++) { mag_set_ui(dmag, r); mag_div_ui(dmag, dmag, N + 2); mag_exp(dmag, dmag); mag_mul(dmag, cmag, dmag); mag_one(den); mag_sub_lower(den, den, dmag); if (mag_is_zero(den)) mag_inf(err + r); else mag_div(err + r, err + r, den); } } /* don't do work if we can't determine the zeroth derivative */ if (mag_is_inf(err)) N = 1; mag_clear(den); mag_clear(cmag); mag_clear(dmag); } exponents = flint_malloc(sizeof(slong) * 3 * N); aindex = exponents + N; bindex = aindex + N; qpow = _acb_vec_init(N); acb_modular_addseq_theta(exponents, aindex, bindex, N); acb_set_round(qpow + 0, q, prec); _acb_vec_zero(theta1, len); _acb_vec_zero(theta2, len); _acb_vec_zero(theta3, len); _acb_vec_zero(theta4, len); WN = (N + 3) / 2; /* compute powers of w^2 and 1/w^2 */ /* todo: conjugates... */ if (!w_is_one) { wpow = _acb_vec_init(WN); vpow = _acb_vec_init(WN + 1); acb_mul(tmp1, w, w, prec); acb_mul(tmp2, v, v, prec); _acb_vec_set_powers(wpow, tmp1, WN, prec); _acb_vec_set_powers(vpow, tmp2, WN + 1, prec); } else { wpow = vpow = NULL; } for (k = 0; k < N; k++) { e = exponents[k]; log2term_approx = e * log2q_approx + (k+2) * log2w_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); if (k > 0) { k1 = aindex[k]; k2 = bindex[k]; e1 = exponents[k1]; e2 = exponents[k2]; if (e == e1 + e2) { _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + k1, qpow + k2, term_prec, prec); } else if (e == 2 * e1 + e2) { _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + k1, qpow + k1, term_prec, prec); _acb_modular_mul(qpow + k, tmp1, tmp2, qpow + k, qpow + k2, term_prec, prec); } else { flint_throw(FLINT_ERROR, "exponent not in addition sequence!\n"); } } if (w_is_one && len == 1) { if (k % 2 == 0) { acb_add(theta3, theta3, qpow + k, prec); if (k % 4 == 0) acb_sub(theta4, theta4, qpow + k, prec); else acb_add(theta4, theta4, qpow + k, prec); } else { acb_add(theta2, theta2, qpow + k, prec); } } else { n = k / 2 + 1; if (k % 2 == 0) { acb_ptr term; if (w_is_one) { acb_mul_2exp_si(tmp1, qpow + k, 1); acb_zero(tmp2); } else { /* tmp1 = w^(2n) + v^(2n) ~= 2 cos(2n) */ acb_add(tmp1, wpow + n, vpow + n, term_prec); acb_mul(tmp1, qpow + k, tmp1, term_prec); /* tmp2 = w^(2n) - v^(2n) ~= 2 sin(2n) */ if (len > 1) { acb_sub(tmp2, wpow + n, vpow + n, term_prec); acb_mul(tmp2, qpow + k, tmp2, term_prec); } } /* compute all the derivatives */ for (r = 0; r < len; r++) { term = (r % 2 == 0) ? tmp1 : tmp2; if (r == 1) acb_mul_ui(term, term, 2 * n, term_prec); else if (r > 1) acb_mul_ui(term, term, 4 * n * n, term_prec); acb_add(theta3 + r, theta3 + r, term, prec); if (k % 4 == 0) acb_sub(theta4 + r, theta4 + r, term, prec); else acb_add(theta4 + r, theta4 + r, term, prec); } } else { acb_ptr term; if (w_is_one) { acb_mul_2exp_si(tmp1, qpow + k, 1); acb_zero(tmp2); } else { /* tmp1 = w^(2n) + v^(2n+2) ~= 2 cos(2n+1) / w */ acb_add(tmp1, wpow + n, vpow + n + 1, term_prec); acb_mul(tmp1, qpow + k, tmp1, term_prec); /* tmp2 = w^(2n) - v^(2n+2) ~= 2 sin(2n+1) / w */ acb_sub(tmp2, wpow + n, vpow + n + 1, term_prec); acb_mul(tmp2, qpow + k, tmp2, term_prec); } /* compute all the derivatives */ for (r = 0; r < len; r++) { if (r > 0) { acb_mul_ui(tmp1, tmp1, 2 * n + 1, term_prec); acb_mul_ui(tmp2, tmp2, 2 * n + 1, term_prec); } term = (r % 2 == 0) ? tmp2 : tmp1; if (k % 4 == 1) acb_sub(theta1 + r, theta1 + r, term, prec); else acb_add(theta1 + r, theta1 + r, term, prec); term = (r % 2 == 0) ? tmp1 : tmp2; acb_add(theta2 + r, theta2 + r, term, prec); } } } } if (w_is_one && len == 1) { acb_mul_2exp_si(theta2, theta2, 1); acb_mul_2exp_si(theta3, theta3, 1); acb_mul_2exp_si(theta4, theta4, 1); } /* theta1: w * sum + 2 sin */ /* theta2: w * sum + 2 cos */ if (!w_is_one) { _acb_vec_scalar_mul(theta1, theta1, len, w, prec); _acb_vec_scalar_mul(theta2, theta2, len, w, prec); acb_add(tmp1, w, v, prec); acb_sub(tmp2, w, v, prec); } else { acb_set_ui(tmp1, 2); acb_zero(tmp2); } for (r = 0; r < len; r++) { acb_add(theta1 + r, theta1 + r, (r % 2 == 0) ? tmp2 : tmp1, prec); acb_add(theta2 + r, theta2 + r, (r % 2 == 0) ? tmp1 : tmp2, prec); } /* Coefficient r in the z-expansion gains a factor: pi^r / r! times a sign: + 2 cos = +1 * (exp + 1/exp) - 2 sin = +i * (exp - 1/exp) - 2 cos = -1 * (exp + 1/exp) + 2 sin = -i * (exp - 1/exp) ... */ acb_mul_onei(theta1, theta1); acb_neg(theta1, theta1); for (r = 1; r < len; r++) { if (r % 4 == 0) { acb_mul_onei(theta1 + r, theta1 + r); acb_neg(theta1 + r, theta1 + r); } else if (r % 4 == 1) { acb_mul_onei(theta2 + r, theta2 + r); acb_mul_onei(theta3 + r, theta3 + r); acb_mul_onei(theta4 + r, theta4 + r); } else if (r % 4 == 2) { acb_mul_onei(theta1 + r, theta1 + r); acb_neg(theta2 + r, theta2 + r); acb_neg(theta3 + r, theta3 + r); acb_neg(theta4 + r, theta4 + r); } else { acb_neg(theta1 + r, theta1 + r); acb_mul_onei(theta2 + r, theta2 + r); acb_mul_onei(theta3 + r, theta3 + r); acb_mul_onei(theta4 + r, theta4 + r); acb_neg(theta2 + r, theta2 + r); acb_neg(theta3 + r, theta3 + r); acb_neg(theta4 + r, theta4 + r); } } /* Add error bound. Note that this must be done after the rearrangements above, and before scaling by pi^r / r! below. */ for (r = 0; r < len; r++) { if (q_is_real && w_is_unit) /* result must be real */ { arb_add_error_mag(acb_realref(theta1 + r), err + r); arb_add_error_mag(acb_realref(theta2 + r), err + r); arb_add_error_mag(acb_realref(theta3 + r), err + r); arb_add_error_mag(acb_realref(theta4 + r), err + r); } else { acb_add_error_mag(theta1 + r, err + r); acb_add_error_mag(theta2 + r, err + r); acb_add_error_mag(theta3 + r, err + r); acb_add_error_mag(theta4 + r, err + r); } } if (len > 1) { arb_t c, d; arb_init(c); arb_init(d); arb_const_pi(c, prec); arb_set(d, c); for (r = 1; r < len; r++) { acb_mul_arb(theta1 + r, theta1 + r, d, prec); acb_mul_arb(theta2 + r, theta2 + r, d, prec); acb_mul_arb(theta3 + r, theta3 + r, d, prec); acb_mul_arb(theta4 + r, theta4 + r, d, prec); if (r + 1 < len) { arb_mul(d, d, c, prec); arb_div_ui(d, d, r + 1, prec); } } arb_clear(c); arb_clear(d); } acb_add_ui(theta3, theta3, 1, prec); acb_add_ui(theta4, theta4, 1, prec); if (!w_is_one) { _acb_vec_clear(wpow, WN); _acb_vec_clear(vpow, WN + 1); } flint_free(exponents); _acb_vec_clear(qpow, N); acb_clear(tmp1); acb_clear(tmp2); acb_clear(v); mag_clear(qmag); mag_clear(wmag); mag_clear(vmag); _mag_vec_clear(err, len); } flint-3.1.3/src/acb_modular/theta_transform.c000066400000000000000000000045161461254215100212440ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" /* convert theta_{m,n} to theta_i */ static int swappy1(int m, int n) { m = m & 1; n = n & 1; if (m == 0 && n == 0) return 2; if (m == 0 && n == 1) return 3; if (m == 1 && n == 0) return 1; return 0; } /* extra phase shift picked up: a factor (-1)^n when m is congruent to 2,3 (mod 4), and possibly a factor i = sqrt(-1) when converting from theta_1 to theta_{1,1} */ static int swappy2(int m, int n) { m = m & 3; n = n & 1; if (m == 1 && n == 1) return 2; /* i */ if (m == 2 && n == 1) return 4; /* (-1)^n */ if (m == 3 && n == 1) return 6; /* (-1)^n * i */ return 0; } void acb_modular_theta_transform(int * R, int * S, int * C, const psl2z_t g) { R[0] = 0; R[1] = 0; R[2] = 0; R[3] = 0; S[0] = 0; S[1] = 1; S[2] = 2; S[3] = 3; if (fmpz_is_zero(&g->c)) { C[0] = 0; if (fmpz_is_odd(&g->b)) { S[2] = 3; S[3] = 2; } /* -b mod 8 */ R[0] = (- (int) fmpz_fdiv_ui(&g->b, 8)) & 7; R[1] = R[0]; } else { int a, b, c, d, e1, e2; psl2z_t h; psl2z_init(h); psl2z_inv(h, g); e1 = acb_modular_epsilon_arg(h); e2 = acb_modular_epsilon_arg(g); psl2z_clear(h); C[0] = 1; a = fmpz_fdiv_ui(&g->a, 8); b = fmpz_fdiv_ui(&g->b, 8); c = fmpz_fdiv_ui(&g->c, 8); d = fmpz_fdiv_ui(&g->d, 8); R[0] = e1 + 1; R[1] = -e2 + 5 + (2 - c) * a; R[2] = -e2 + 4 + (c - d - 2) * (b - a); R[3] = -e2 + 3 - (2 + d) * b; S[1] = swappy1(1 - c, 1 + a); R[1] += swappy2(1 - c, 1 + a); S[2] = swappy1(1 + d - c, 1 - b + a); R[2] += swappy2(1 + d - c, 1 - b + a); S[3] = swappy1(1 + d, 1 - b); R[3] += swappy2(1 + d, 1 - b); /* floor mod by 8 */ R[0] &= 7; R[1] &= 7; R[2] &= 7; R[3] &= 7; } } flint-3.1.3/src/acb_modular/transform.c000066400000000000000000000046231461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_modular.h" void acb_modular_transform(acb_t w, const psl2z_t g, const acb_t z, slong prec) { #define a (&g->a) #define b (&g->b) #define c (&g->c) #define d (&g->d) #define x acb_realref(z) #define y acb_imagref(z) if (fmpz_is_zero(c)) { /* (az+b)/d, where we must have a = d = 1 */ acb_add_fmpz(w, z, b, prec); } else if (fmpz_is_zero(a)) { /* b/(cz+d), where -bc = 1, c = 1 => -1/(z+d) */ acb_add_fmpz(w, z, d, prec); acb_inv(w, w, prec); acb_neg(w, w); } else if (0) { acb_t t, u; acb_init(t); acb_init(u); acb_set_fmpz(t, b); acb_addmul_fmpz(t, z, a, prec); acb_set_fmpz(u, d); acb_addmul_fmpz(u, z, c, prec); acb_div(w, t, u, prec); acb_clear(t); acb_clear(u); } else { /* (az+b)/(cz+d) = (re+im*i)/den where re = bd + (bc+ad)x + ac(x^2+y^2) im = (ad-bc)y den = c^2(x^2+y^2) + 2cdx + d^2 */ fmpz_t t; arb_t re, im, den; arb_init(re); arb_init(im); arb_init(den); fmpz_init(t); arb_mul(im, x, x, prec); arb_addmul(im, y, y, prec); fmpz_mul(t, b, d); arb_set_fmpz(re, t); fmpz_mul(t, b, c); fmpz_addmul(t, a, d); arb_addmul_fmpz(re, x, t, prec); fmpz_mul(t, a, c); arb_addmul_fmpz(re, im, t, prec); fmpz_mul(t, d, d); arb_set_fmpz(den, t); fmpz_mul(t, c, d); fmpz_mul_2exp(t, t, 1); arb_addmul_fmpz(den, x, t, prec); fmpz_mul(t, c, c); arb_addmul_fmpz(den, im, t, prec); fmpz_mul(t, a, d); fmpz_submul(t, b, c); arb_mul_fmpz(im, y, t, prec); arb_div(acb_realref(w), re, den, prec); arb_div(acb_imagref(w), im, den, prec); arb_clear(re); arb_clear(im); arb_clear(den); fmpz_clear(t); } #undef a #undef b #undef c #undef d #undef x #undef y } flint-3.1.3/src/acb_poly.h000066400000000000000000000626121461254215100153720ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_POLY_H #define ACB_POLY_H #ifdef ACB_POLY_INLINES_C #define ACB_POLY_INLINE #else #define ACB_POLY_INLINE static inline #endif #include "fmpq_types.h" #include "acb.h" #ifdef __cplusplus extern "C" { #endif /* Memory management */ void acb_poly_init(acb_poly_t poly); void acb_poly_init2(acb_poly_t poly, slong len); void acb_poly_clear(acb_poly_t poly); void acb_poly_fit_length(acb_poly_t poly, slong len); void _acb_poly_set_length(acb_poly_t poly, slong len); void _acb_poly_normalise(acb_poly_t poly); ACB_POLY_INLINE void acb_poly_swap(acb_poly_t poly1, acb_poly_t poly2) { FLINT_SWAP(acb_poly_struct, *poly1, *poly2); } ACB_POLY_INLINE slong acb_poly_length(const acb_poly_t poly) { return poly->length; } ACB_POLY_INLINE slong acb_poly_degree(const acb_poly_t poly) { return poly->length - 1; } slong acb_poly_valuation(const acb_poly_t poly); ACB_POLY_INLINE int acb_poly_is_zero(const acb_poly_t z) { return acb_poly_length(z) == 0; } ACB_POLY_INLINE int acb_poly_is_one(const acb_poly_t z) { return (acb_poly_length(z) == 1) && acb_is_one(z->coeffs); } ACB_POLY_INLINE int acb_poly_is_x(const acb_poly_t z) { return (acb_poly_length(z) == 2) && acb_is_zero(z->coeffs) && acb_is_one(z->coeffs + 1); } ACB_POLY_INLINE void acb_poly_zero(acb_poly_t poly) { poly->length = 0; } ACB_POLY_INLINE void acb_poly_one(acb_poly_t poly) { acb_poly_fit_length(poly, 1); acb_one(poly->coeffs); _acb_poly_set_length(poly, 1); } void acb_poly_set_coeff_si(acb_poly_t poly, slong n, slong x); void acb_poly_set_coeff_acb(acb_poly_t poly, slong n, const acb_t x); void acb_poly_get_coeff_acb(acb_t x, const acb_poly_t poly, slong n); #define acb_poly_get_coeff_ptr(poly, n) \ ((n) < (poly)->length ? (poly)->coeffs + (n) : NULL) void _acb_poly_shift_right(acb_ptr res, acb_srcptr poly, slong len, slong n); void acb_poly_shift_right(acb_poly_t res, const acb_poly_t poly, slong n); void _acb_poly_shift_left(acb_ptr res, acb_srcptr poly, slong len, slong n); void acb_poly_shift_left(acb_poly_t res, const acb_poly_t poly, slong n); ACB_POLY_INLINE void acb_poly_truncate(acb_poly_t poly, slong newlen) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) acb_zero(poly->coeffs + i); poly->length = newlen; _acb_poly_normalise(poly); } } void _acb_poly_majorant(arb_ptr res, acb_srcptr vec, slong len, slong prec); void acb_poly_majorant(arb_poly_t res, const acb_poly_t poly, slong prec); #ifdef FLINT_HAVE_FILE void acb_poly_fprintd(FILE * file, const acb_poly_t poly, slong digits); #endif void acb_poly_printd(const acb_poly_t poly, slong digits); void _acb_poly_evaluate_horner(acb_t res, acb_srcptr f, slong len, const acb_t a, slong prec); void acb_poly_evaluate_horner(acb_t res, const acb_poly_t f, const acb_t a, slong prec); void _acb_poly_evaluate_rectangular(acb_t y, acb_srcptr poly, slong len, const acb_t x, slong prec); void acb_poly_evaluate_rectangular(acb_t res, const acb_poly_t f, const acb_t a, slong prec); void _acb_poly_evaluate(acb_t res, acb_srcptr f, slong len, const acb_t a, slong prec); void acb_poly_evaluate(acb_t res, const acb_poly_t f, const acb_t a, slong prec); void _acb_poly_evaluate2_horner(acb_t y, acb_t z, acb_srcptr f, slong len, const acb_t x, slong prec); void acb_poly_evaluate2_horner(acb_t y, acb_t z, const acb_poly_t f, const acb_t x, slong prec); void _acb_poly_evaluate2_rectangular(acb_t y, acb_t z, acb_srcptr f, slong len, const acb_t x, slong prec); void acb_poly_evaluate2_rectangular(acb_t y, acb_t z, const acb_poly_t f, const acb_t x, slong prec); void _acb_poly_evaluate2(acb_t y, acb_t z, acb_srcptr f, slong len, const acb_t x, slong prec); void acb_poly_evaluate2(acb_t y, acb_t z, const acb_poly_t f, const acb_t x, slong prec); void _acb_poly_derivative(acb_ptr res, acb_srcptr poly, slong len, slong prec); void acb_poly_derivative(acb_poly_t res, const acb_poly_t poly, slong prec); void _acb_poly_nth_derivative(acb_ptr res, acb_srcptr poly, ulong n, slong len, slong prec); void acb_poly_nth_derivative(acb_poly_t res, const acb_poly_t poly, ulong n, slong prec); void _acb_poly_integral(acb_ptr res, acb_srcptr poly, slong len, slong prec); void acb_poly_integral(acb_poly_t res, const acb_poly_t poly, slong prec); /* Transforms */ void acb_poly_borel_transform(acb_poly_t res, const acb_poly_t poly, slong prec); void _acb_poly_borel_transform(acb_ptr res, acb_srcptr poly, slong len, slong prec); void acb_poly_inv_borel_transform(acb_poly_t res, const acb_poly_t poly, slong prec); void _acb_poly_inv_borel_transform(acb_ptr res, acb_srcptr poly, slong len, slong prec); void _acb_poly_binomial_transform_basecase(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec); void acb_poly_binomial_transform_basecase(acb_poly_t b, const acb_poly_t a, slong len, slong prec); void _acb_poly_binomial_transform_convolution(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec); void acb_poly_binomial_transform_convolution(acb_poly_t b, const acb_poly_t a, slong len, slong prec); void _acb_poly_binomial_transform(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec); void acb_poly_binomial_transform(acb_poly_t b, const acb_poly_t a, slong len, slong prec); void _acb_poly_graeffe_transform(acb_ptr b, acb_srcptr a, slong len, slong prec); void acb_poly_graeffe_transform(acb_poly_t b, const acb_poly_t a, slong prec); void acb_poly_set(acb_poly_t dest, const acb_poly_t src); void acb_poly_set_round(acb_poly_t dest, const acb_poly_t src, slong prec); void acb_poly_set_trunc(acb_poly_t res, const acb_poly_t poly, slong n); void acb_poly_set_trunc_round(acb_poly_t res, const acb_poly_t poly, slong n, slong prec); void acb_poly_set_arb_poly(acb_poly_t poly, const arb_poly_t re); void acb_poly_set2_arb_poly(acb_poly_t poly, const arb_poly_t re, const arb_poly_t im); void acb_poly_set_fmpq_poly(acb_poly_t poly, const fmpq_poly_t re, slong prec); void acb_poly_set2_fmpq_poly(acb_poly_t poly, const fmpq_poly_t re, const fmpq_poly_t im, slong prec); void acb_poly_set_fmpz_poly(acb_poly_t poly, const fmpz_poly_t src, slong prec); void acb_poly_set2_fmpz_poly(acb_poly_t poly, const fmpz_poly_t re, const fmpz_poly_t im, slong prec); int acb_poly_get_unique_fmpz_poly(fmpz_poly_t res, const acb_poly_t src); ACB_POLY_INLINE void acb_poly_set_acb(acb_poly_t poly, const acb_t c) { acb_poly_fit_length(poly, 1); acb_set(poly->coeffs, c); _acb_poly_set_length(poly, !acb_is_zero(poly->coeffs)); } void acb_poly_set_si(acb_poly_t poly, slong c); void acb_poly_randtest(acb_poly_t poly, flint_rand_t state, slong len, slong prec, slong mag_bits); int acb_poly_equal(const acb_poly_t A, const acb_poly_t B); int acb_poly_contains_fmpz_poly(const acb_poly_t poly1, const fmpz_poly_t poly2); int acb_poly_contains_fmpq_poly(const acb_poly_t poly1, const fmpq_poly_t poly2); int _acb_poly_overlaps(acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2); int acb_poly_overlaps(const acb_poly_t poly1, const acb_poly_t poly2); int acb_poly_contains(const acb_poly_t poly1, const acb_poly_t poly2); ACB_POLY_INLINE int acb_poly_is_real(const acb_poly_t poly) { return _acb_vec_is_real(poly->coeffs, poly->length); } void _acb_poly_add(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec); void acb_poly_add(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec); void acb_poly_add_si(acb_poly_t res, const acb_poly_t poly, slong c, slong prec); void _acb_poly_sub(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec); void acb_poly_sub(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec); void acb_poly_add_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong len, slong prec); void acb_poly_sub_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong len, slong prec); ACB_POLY_INLINE void acb_poly_neg(acb_poly_t res, const acb_poly_t poly) { acb_poly_fit_length(res, poly->length); _acb_vec_neg(res->coeffs, poly->coeffs, poly->length); _acb_poly_set_length(res, poly->length); } ACB_POLY_INLINE void acb_poly_scalar_mul_2exp_si(acb_poly_t res, const acb_poly_t poly, slong c) { acb_poly_fit_length(res, poly->length); _acb_vec_scalar_mul_2exp_si(res->coeffs, poly->coeffs, poly->length, c); _acb_poly_set_length(res, poly->length); } ACB_POLY_INLINE void acb_poly_scalar_mul(acb_poly_t res, const acb_poly_t poly, const acb_t c, slong prec) { acb_poly_fit_length(res, poly->length); _acb_vec_scalar_mul(res->coeffs, poly->coeffs, poly->length, c, prec); _acb_poly_set_length(res, poly->length); _acb_poly_normalise(res); } ACB_POLY_INLINE void acb_poly_scalar_div(acb_poly_t res, const acb_poly_t poly, const acb_t c, slong prec) { acb_poly_fit_length(res, poly->length); _acb_vec_scalar_div(res->coeffs, poly->coeffs, poly->length, c, prec); _acb_poly_set_length(res, poly->length); _acb_poly_normalise(res); } void acb_poly_mullow_classical(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec); void _acb_poly_mullow_classical(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec); void _acb_poly_mullow_transpose(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec); void acb_poly_mullow_transpose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec); void _acb_poly_mullow_transpose_gauss(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec); void acb_poly_mullow_transpose_gauss(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec); void _acb_poly_mullow(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec); void acb_poly_mullow(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec); void _acb_poly_mul(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec); void acb_poly_mul(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec); ACB_POLY_INLINE void _acb_poly_mul_monic(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec) { if (len1 + len2 - 2 > 0) _acb_poly_mullow(res, poly1, len1, poly2, len2, len1 + len2 - 2, prec); acb_one(res + len1 + len2 - 2); } void _acb_poly_inv_series(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong len, slong prec); void acb_poly_inv_series(acb_poly_t Qinv, const acb_poly_t Q, slong n, slong prec); void _acb_poly_div_series(acb_ptr Q, acb_srcptr A, slong Alen, acb_srcptr B, slong Blen, slong n, slong prec); void acb_poly_div_series(acb_poly_t Q, const acb_poly_t A, const acb_poly_t B, slong n, slong prec); void _acb_poly_reverse(acb_ptr res, acb_srcptr poly, slong len, slong n); void _acb_poly_div(acb_ptr Q, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec); void _acb_poly_divrem(acb_ptr Q, acb_ptr R, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec); void _acb_poly_rem(acb_ptr R, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec); int acb_poly_divrem(acb_poly_t Q, acb_poly_t R, const acb_poly_t A, const acb_poly_t B, slong prec); void _acb_poly_div_root(acb_ptr Q, acb_t R, acb_srcptr A, slong len, const acb_t c, slong prec); /* Composition */ void _acb_poly_taylor_shift(acb_ptr poly, const acb_t c, slong n, slong prec); void acb_poly_taylor_shift(acb_poly_t g, const acb_poly_t f, const acb_t c, slong prec); void _acb_poly_compose(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec); void acb_poly_compose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec); void _acb_poly_compose_series(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec); void acb_poly_compose_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec); /* Reversion */ void _acb_poly_revert_series(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong n, slong prec); void acb_poly_revert_series(acb_poly_t Qinv, const acb_poly_t Q, slong n, slong prec); void _acb_poly_evaluate_vec_fast_precomp(acb_ptr vs, acb_srcptr poly, slong plen, acb_ptr * tree, slong len, slong prec); void _acb_poly_evaluate_vec_fast(acb_ptr ys, acb_srcptr poly, slong plen, acb_srcptr xs, slong n, slong prec); void acb_poly_evaluate_vec_fast(acb_ptr ys, const acb_poly_t poly, acb_srcptr xs, slong n, slong prec); void _acb_poly_evaluate_vec_iter(acb_ptr ys, acb_srcptr poly, slong plen, acb_srcptr xs, slong n, slong prec); void acb_poly_evaluate_vec_iter(acb_ptr ys, const acb_poly_t poly, acb_srcptr xs, slong n, slong prec); void _acb_poly_interpolate_barycentric(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec); void acb_poly_interpolate_barycentric(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec); void _acb_poly_interpolation_weights(acb_ptr w, acb_ptr * tree, slong len, slong prec); void _acb_poly_interpolate_fast_precomp(acb_ptr poly, acb_srcptr ys, acb_ptr * tree, acb_srcptr weights, slong len, slong prec); void _acb_poly_interpolate_fast(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong len, slong prec); void acb_poly_interpolate_fast(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec); void _acb_poly_interpolate_newton(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec); void acb_poly_interpolate_newton(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec); void _acb_poly_product_roots(acb_ptr poly, acb_srcptr xs, slong n, slong prec); void acb_poly_product_roots(acb_poly_t poly, acb_srcptr xs, slong n, slong prec); acb_ptr * _acb_poly_tree_alloc(slong len); void _acb_poly_tree_free(acb_ptr * tree, slong len); void _acb_poly_tree_build(acb_ptr * tree, acb_srcptr roots, slong len, slong prec); void _acb_poly_root_inclusion(acb_t r, const acb_t m, acb_srcptr poly, acb_srcptr polyder, slong len, slong prec); slong _acb_poly_validate_roots(acb_ptr roots, acb_srcptr poly, slong len, slong prec); void _acb_poly_refine_roots_durand_kerner(acb_ptr roots, acb_srcptr poly, slong len, slong prec); slong _acb_poly_find_roots(acb_ptr roots, acb_srcptr poly, acb_srcptr initial, slong len, slong maxiter, slong prec); slong acb_poly_find_roots(acb_ptr roots, const acb_poly_t poly, acb_srcptr initial, slong maxiter, slong prec); void _acb_poly_root_bound_fujiwara(mag_t bound, acb_srcptr poly, slong len); void acb_poly_root_bound_fujiwara(mag_t bound, acb_poly_t poly); int _acb_poly_validate_real_roots(acb_srcptr roots, acb_srcptr poly, slong len, slong prec); int acb_poly_validate_real_roots(acb_srcptr roots, const acb_poly_t poly, slong prec); /* Special functions */ void _acb_poly_pow_ui_trunc_binexp(acb_ptr res, acb_srcptr f, slong flen, ulong exp, slong len, slong prec); void acb_poly_pow_ui_trunc_binexp(acb_poly_t res, const acb_poly_t poly, ulong exp, slong len, slong prec); void _acb_poly_pow_ui(acb_ptr res, acb_srcptr f, slong flen, ulong exp, slong prec); void acb_poly_pow_ui(acb_poly_t res, const acb_poly_t poly, ulong exp, slong prec); void _acb_poly_rsqrt_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_rsqrt_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_sqrt_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_sqrt_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_log_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec); void acb_poly_log_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec); void _acb_poly_log1p_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec); void acb_poly_log1p_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec); void _acb_poly_atan_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec); void acb_poly_atan_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec); void _acb_poly_exp_series_basecase(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_exp_series_basecase(acb_poly_t f, const acb_poly_t h, slong n, slong prec); void _acb_poly_exp_series(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_exp_series(acb_poly_t f, const acb_poly_t h, slong n, slong prec); void _acb_poly_exp_pi_i_series(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_exp_pi_i_series(acb_poly_t f, const acb_poly_t h, slong n, slong prec); void _acb_poly_sinh_cosh_series_basecase(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_sinh_cosh_series_basecase(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec); void _acb_poly_sinh_cosh_series_exponential(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_sinh_cosh_series_exponential(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec); void _acb_poly_sinh_cosh_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_sinh_cosh_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec); void _acb_poly_sinh_series(acb_ptr s, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_sinh_series(acb_poly_t s, const acb_poly_t h, slong n, slong prec); void _acb_poly_cosh_series(acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_cosh_series(acb_poly_t c, const acb_poly_t h, slong n, slong prec); void _acb_poly_sin_cos_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_sin_cos_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec); void _acb_poly_sin_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_sin_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_cos_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_cos_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_sin_cos_pi_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_sin_cos_pi_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec); void _acb_poly_sin_pi_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_sin_pi_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_cos_pi_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_cos_pi_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_cot_pi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_cot_pi_series(acb_poly_t res, const acb_poly_t f, slong len, slong prec); void _acb_poly_tan_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_tan_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_sinc_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_sinc_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); void _acb_poly_lambertw_series(acb_ptr res, acb_srcptr z, slong zlen, const fmpz_t k, int flags, slong len, slong prec); void acb_poly_lambertw_series(acb_poly_t res, const acb_poly_t z, const fmpz_t k, int flags, slong len, slong prec); void _acb_poly_gamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_gamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec); void _acb_poly_rgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_rgamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec); void _acb_poly_lgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_lgamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec); void _acb_poly_digamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec); void acb_poly_digamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec); void _acb_poly_rising_ui_series(acb_ptr res, acb_srcptr f, slong flen, ulong r, slong trunc, slong prec); void acb_poly_rising_ui_series(acb_poly_t res, const acb_poly_t f, ulong r, slong trunc, slong prec); void _acb_poly_pow_acb_series(acb_ptr h, acb_srcptr f, slong flen, const acb_t g, slong len, slong prec); void acb_poly_pow_acb_series(acb_poly_t h, const acb_poly_t f, const acb_t g, slong len, slong prec); void _acb_poly_pow_series(acb_ptr h, acb_srcptr f, slong flen, acb_srcptr g, slong glen, slong len, slong prec); void acb_poly_pow_series(acb_poly_t h, const acb_poly_t f, const acb_poly_t g, slong len, slong prec); void _acb_poly_binomial_pow_acb_series(acb_ptr h, acb_srcptr f, slong flen, const acb_t g, slong len, slong prec); /* TODO: document */ ACB_POLY_INLINE void _acb_poly_acb_pow_cpx(acb_ptr w, const acb_t a, const acb_t b, slong len, slong prec) { if (len == 1) { acb_pow(w, a, b, prec); } else { acb_t log_a; slong k; acb_init(log_a); acb_log(log_a, a, prec); acb_mul(w, log_a, b, prec); acb_exp(w, w, prec); for (k = 1; k < len; k++) { acb_mul(w + k, w + k - 1, log_a, prec); acb_div_ui(w + k, w + k, k, prec); } acb_clear(log_a); } } #define _acb_poly_pow_cpx _acb_poly_acb_pow_cpx /* TODO: document */ void _acb_poly_acb_invpow_cpx(acb_ptr res, const acb_t N, const acb_t c, slong trunc, slong prec); /* TODO: document */ void _acb_poly_mullow_cpx(acb_ptr res, acb_srcptr src, slong len, const acb_t c, slong trunc, slong prec); void _acb_poly_powsum_series_naive(acb_ptr z, const acb_t s, const acb_t a, const acb_t q, slong n, slong len, slong prec); void _acb_poly_powsum_series_naive_threaded(acb_ptr z, const acb_t s, const acb_t a, const acb_t q, slong n, slong len, slong prec); void _acb_poly_powsum_one_series_sieved(acb_ptr z, const acb_t s, slong n, slong len, slong prec); void _acb_poly_zeta_em_sum(acb_ptr z, const acb_t s, const acb_t a, int deflate, ulong N, ulong M, slong d, slong prec); void _acb_poly_zeta_em_choose_param(mag_t bound, ulong * N, ulong * M, const acb_t s, const acb_t a, slong d, slong target, slong prec); void _acb_poly_zeta_em_bound1(mag_t bound, const acb_t s, const acb_t a, slong N, slong M, slong d, slong wp); void _acb_poly_zeta_em_bound(arb_ptr vec, const acb_t s, const acb_t a, ulong N, ulong M, slong d, slong wp); void _acb_poly_zeta_em_tail_naive(acb_ptr sum, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong len, slong prec); void _acb_poly_zeta_em_tail_bsplit(acb_ptr z, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong len, slong prec); void _acb_poly_zeta_cpx_series(acb_ptr z, const acb_t s, const acb_t a, int deflate, slong d, slong prec); void _acb_poly_zeta_series(acb_ptr res, acb_srcptr h, slong hlen, const acb_t a, int deflate, slong len, slong prec); void acb_poly_zeta_series(acb_poly_t res, const acb_poly_t f, const acb_t a, int deflate, slong n, slong prec); void _acb_poly_polylog_cpx_zeta(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec); void _acb_poly_polylog_cpx_small(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec); void _acb_poly_polylog_cpx(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec); void _acb_poly_polylog_series(acb_ptr res, acb_srcptr s, slong slen, const acb_t z, slong len, slong prec); void acb_poly_polylog_series(acb_poly_t res, const acb_poly_t s, const acb_t z, slong n, slong prec); void _acb_poly_agm1_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec); void acb_poly_agm1_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec); void _acb_poly_elliptic_k_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec); void acb_poly_elliptic_k_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec); void _acb_poly_elliptic_p_series(acb_ptr res, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec); void acb_poly_elliptic_p_series(acb_poly_t res, const acb_poly_t z, const acb_t tau, slong n, slong prec); void _acb_poly_erf_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec); void acb_poly_erf_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec); ACB_POLY_INLINE slong acb_poly_allocated_bytes(const acb_poly_t x) { return _acb_vec_allocated_bytes(x->coeffs, x->alloc); } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_poly/000077500000000000000000000000001461254215100152125ustar00rootroot00000000000000flint-3.1.3/src/acb_poly/add.c000066400000000000000000000022621461254215100161100ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_add(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) acb_add(res + i, poly1 + i, poly2 + i, prec); for (i = min; i < len1; i++) acb_set_round(res + i, poly1 + i, prec); for (i = min; i < len2; i++) acb_set_round(res + i, poly2 + i, prec); } void acb_poly_add(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec) { slong max = FLINT_MAX(poly1->length, poly2->length); acb_poly_fit_length(res, max); _acb_poly_add(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); _acb_poly_set_length(res, max); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/add_series.c000066400000000000000000000015751461254215100174700ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_add_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong len, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; len1 = FLINT_MIN(len1, len); len2 = FLINT_MIN(len2, len); len = FLINT_MAX(len1, len2); acb_poly_fit_length(res, len); _acb_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/add_si.c000066400000000000000000000016711461254215100166060ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_add_si(acb_poly_t res, const acb_poly_t x, slong y, slong prec) { slong len = x->length; if (len == 0) { acb_poly_set_si(res, y); } else { acb_poly_fit_length(res, len); if (y >= 0) acb_add_ui(res->coeffs, x->coeffs, y, prec); else acb_sub_ui(res->coeffs, x->coeffs, -y, prec); if (res != x) _acb_vec_set(res->coeffs + 1, x->coeffs + 1, len - 1); _acb_poly_set_length(res, len); _acb_poly_normalise(res); } } flint-3.1.3/src/acb_poly/agm1_series.c000066400000000000000000000025371461254215100175640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_agm1_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) { acb_ptr t, u; zlen = FLINT_MIN(zlen, len); t = _acb_vec_init(len); u = _acb_vec_init(len); acb_agm1_cpx(t, z, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, z + 1, zlen - 1); _acb_poly_compose_series(res, t, len, u, zlen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void acb_poly_agm1_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec) { if (n == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, n); if (z->length == 0) { acb_t t; acb_init(t); _acb_poly_agm1_series(res->coeffs, t, 1, n, prec); acb_clear(t); } else { _acb_poly_agm1_series(res->coeffs, z->coeffs, z->length, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/atan_series.c000066400000000000000000000020061461254215100176510ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" void _acb_poly_atan_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); if (_gr_poly_atan_series(g, h, hlen, n, ctx) != GR_SUCCESS) _acb_vec_indeterminate(g, n); } void acb_poly_atan_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, n); _acb_poly_atan_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/binomial_transform.c000066400000000000000000000024201461254215100212410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_binomial_transform(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec) { if (alen < 10 || len < 10) _acb_poly_binomial_transform_basecase(b, a, alen, len, prec); else _acb_poly_binomial_transform_convolution(b, a, alen, len, prec); } void acb_poly_binomial_transform(acb_poly_t b, const acb_poly_t a, slong len, slong prec) { if (len == 0 || a->length == 0) { acb_poly_zero(b); return; } if (b == a) { acb_poly_t c; acb_poly_init2(c, len); _acb_poly_binomial_transform(c->coeffs, a->coeffs, a->length, len, prec); acb_poly_swap(b, c); acb_poly_clear(c); } else { acb_poly_fit_length(b, len); _acb_poly_binomial_transform(b->coeffs, a->coeffs, a->length, len, prec); } _acb_poly_set_length(b, len); _acb_poly_normalise(b); } flint-3.1.3/src/acb_poly/binomial_transform_basecase.c000066400000000000000000000031371461254215100230750ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_binomial_transform_basecase(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec) { slong n, k; fmpz_t t; fmpz_init(t); for (n = 0; n < len; n++) { acb_zero(b + n); for (k = 0; k < FLINT_MIN(n + 1, alen); k++) { if (k == 0) { fmpz_one(t); } else { fmpz_mul_si(t, t, -(n - k + 1)); fmpz_divexact_ui(t, t, k); } acb_addmul_fmpz(b + n, a + k, t, prec); } } fmpz_clear(t); } void acb_poly_binomial_transform_basecase(acb_poly_t b, const acb_poly_t a, slong len, slong prec) { if (len == 0 || a->length == 0) { acb_poly_zero(b); return; } if (b == a) { acb_poly_t c; acb_poly_init2(c, len); _acb_poly_binomial_transform_basecase(c->coeffs, a->coeffs, a->length, len, prec); acb_poly_swap(b, c); acb_poly_clear(c); } else { acb_poly_fit_length(b, len); _acb_poly_binomial_transform_basecase(b->coeffs, a->coeffs, a->length, len, prec); } _acb_poly_set_length(b, len); _acb_poly_normalise(b); } flint-3.1.3/src/acb_poly/binomial_transform_convolution.c000066400000000000000000000032141461254215100237020ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_poly.h" void _acb_poly_binomial_transform_convolution(acb_ptr b, acb_srcptr a, slong alen, slong len, slong prec) { slong i; acb_ptr c, d; alen = FLINT_MIN(alen, len); c = _acb_vec_init(alen); d = _acb_vec_init(len); _acb_poly_borel_transform(c, a, alen, prec); for (i = 1; i < alen; i += 2) acb_neg(c + i, c + i); acb_one(d); for (i = 1; i < len; i++) acb_div_ui(d + i, d + i - 1, i, prec); _acb_poly_mullow(b, d, len, c, alen, len, prec); _acb_poly_inv_borel_transform(b, b, len, prec); _acb_vec_clear(c, alen); _acb_vec_clear(d, len); } void acb_poly_binomial_transform_convolution(acb_poly_t b, const acb_poly_t a, slong len, slong prec) { if (len == 0 || a->length == 0) { acb_poly_zero(b); return; } if (b == a) { acb_poly_t c; acb_poly_init2(c, len); _acb_poly_binomial_transform_convolution(c->coeffs, a->coeffs, a->length, len, prec); acb_poly_swap(b, c); acb_poly_clear(c); } else { acb_poly_fit_length(b, len); _acb_poly_binomial_transform_convolution(b->coeffs, a->coeffs, a->length, len, prec); } _acb_poly_set_length(b, len); _acb_poly_normalise(b); } flint-3.1.3/src/acb_poly/borel_transform.c000066400000000000000000000017601461254215100205600ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_borel_transform(acb_ptr res, acb_srcptr poly, slong len, slong prec) { slong i; arb_t t; arb_init(t); arb_one(t); for (i = 0; i < len; i++) { if (i > 1) arb_mul_ui(t, t, i, prec); acb_div_arb(res + i, poly + i, t, prec); } arb_clear(t); } void acb_poly_borel_transform(acb_poly_t res, const acb_poly_t poly, slong prec) { acb_poly_fit_length(res, poly->length); _acb_poly_borel_transform(res->coeffs, poly->coeffs, poly->length, prec); _acb_poly_set_length(res, poly->length); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/clear.c000066400000000000000000000010671461254215100164500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_clear(acb_poly_t poly) { slong i; for (i = 0; i < poly->alloc; i++) acb_clear(poly->coeffs + i); flint_free(poly->coeffs); } flint-3.1.3/src/acb_poly/compose.c000066400000000000000000000035461461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" void _acb_poly_compose(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); if (_gr_poly_compose_divconquer(res, poly1, len1, poly2, len2, ctx) != GR_SUCCESS) _acb_vec_indeterminate(res, (len1 - 1) * (len2 - 1) + 1); } void acb_poly_compose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { acb_poly_zero(res); } else if (len1 == 1 || len2 == 0) { acb_poly_set_acb(res, poly1->coeffs); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { acb_poly_fit_length(res, lenr); _acb_poly_compose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); } else { acb_poly_t t; acb_poly_init2(t, lenr); _acb_poly_compose(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); acb_poly_swap(res, t); acb_poly_clear(t); } _acb_poly_set_length(res, lenr); _acb_poly_normalise(res); } } flint-3.1.3/src/acb_poly/compose_series.c000066400000000000000000000056471461254215100204110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" void _acb_poly_compose_series(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { if (len2 == 1) { acb_set_round(res, poly1, prec); _acb_vec_zero(res + 1, n - 1); } else if (!_acb_vec_is_finite(poly1, len1) || !_acb_vec_is_finite(poly2, len2)) { /* find k such that the first k coefficients of both poly1 and * poly2 are finite */ slong k = 0; while (((k >= len1) || acb_is_finite(poly1 + k)) && ((k >= len2) || acb_is_finite(poly2 + k))) k += 1; if (k > 0) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); GR_MUST_SUCCEED(_gr_poly_compose_series(res, poly1, FLINT_MIN(len1, k), poly2, FLINT_MIN(len2, k), FLINT_MIN(n, k), ctx)); _acb_vec_indeterminate(res + k, n - k); } else { _acb_vec_indeterminate(res, n); } } else { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); GR_MUST_SUCCEED(_gr_poly_compose_series(res, poly1, len1, poly2, len2, n, ctx)); } } void acb_poly_compose_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !acb_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "compose_series: inner " "polynomial must have zero constant term\n"); } if (len1 == 0 || n == 0) { acb_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { acb_poly_set_acb(res, poly1->coeffs); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { acb_poly_fit_length(res, lenr); _acb_poly_compose_series(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, prec); _acb_poly_set_length(res, lenr); _acb_poly_normalise(res); } else { acb_poly_t t; acb_poly_init2(t, lenr); _acb_poly_compose_series(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, prec); _acb_poly_set_length(t, lenr); _acb_poly_normalise(t); acb_poly_swap(res, t); acb_poly_clear(t); } } flint-3.1.3/src/acb_poly/contains.c000066400000000000000000000015001461254215100171700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" int acb_poly_contains(const acb_poly_t poly1, const acb_poly_t poly2) { slong i; if (poly2->length > poly1->length) return 0; for (i = 0; i < poly2->length; i++) { if (!acb_contains(poly1->coeffs + i, poly2->coeffs + i)) return 0; } for (i = poly2->length; i < poly1->length; i++) if (!acb_contains_zero(poly1->coeffs + i)) return 0; return 1; } flint-3.1.3/src/acb_poly/contains_fmpq_poly.c000066400000000000000000000017741461254215100212730ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_poly.h" #include "acb_poly.h" int acb_poly_contains_fmpq_poly(const acb_poly_t poly1, const fmpq_poly_t poly2) { slong i; fmpq_t t; if (poly2->length > poly1->length) return 0; fmpq_init(t); for (i = 0; i < poly2->length; i++) { fmpq_poly_get_coeff_fmpq(t, poly2, i); if (!acb_contains_fmpq(poly1->coeffs + i, t)) { fmpq_clear(t); return 0; } } fmpq_clear(t); for (i = poly2->length; i < poly1->length; i++) if (!acb_contains_zero(poly1->coeffs + i)) return 0; return 1; } flint-3.1.3/src/acb_poly/contains_fmpz_poly.c000066400000000000000000000015331461254215100212750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "acb_poly.h" int acb_poly_contains_fmpz_poly(const acb_poly_t poly1, const fmpz_poly_t poly2) { slong i; if (poly2->length > poly1->length) return 0; for (i = 0; i < poly2->length; i++) if (!acb_contains_fmpz(poly1->coeffs + i, poly2->coeffs + i)) return 0; for (i = poly2->length; i < poly1->length; i++) if (!acb_contains_zero(poly1->coeffs + i)) return 0; return 1; } flint-3.1.3/src/acb_poly/cos_pi_series.c000066400000000000000000000027661461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_cos_pi_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_cos_pi(g, h, prec); _acb_vec_zero(g + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); acb_sin_cos_pi(t, g, h, prec); acb_neg(t, t); acb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ acb_const_pi(t, prec); acb_mul(g + 1, g + 1, t, prec); acb_clear(t); } else { acb_ptr t = _acb_vec_init(n); _acb_poly_sin_cos_pi_series(t, g, h, hlen, n, prec); _acb_vec_clear(t, n); } } void acb_poly_cos_pi_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_one(g); return; } if (hlen == 1) n = 1; acb_poly_fit_length(g, n); _acb_poly_cos_pi_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/cos_series.c000066400000000000000000000026351461254215100175220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_cos_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_cos(g, h, prec); _acb_vec_zero(g + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); acb_sin_cos(t, g, h, prec); acb_neg(t, t); acb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ acb_clear(t); } else { acb_ptr t = _acb_vec_init(n); _acb_poly_sin_cos_series(t, g, h, hlen, n, prec); _acb_vec_clear(t, n); } } void acb_poly_cos_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_one(g); return; } if (hlen == 1) n = 1; acb_poly_fit_length(g, n); _acb_poly_cos_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/cosh_series.c000066400000000000000000000026161461254215100176710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_cosh_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_cosh(g, h, prec); _acb_vec_zero(g + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); acb_sinh_cosh(t, g, h, prec); acb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ acb_clear(t); } else { acb_ptr t = _acb_vec_init(n); _acb_poly_sinh_cosh_series(t, g, h, hlen, n, prec); _acb_vec_clear(t, n); } } void acb_poly_cosh_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_one(g); return; } if (hlen == 1) n = 1; acb_poly_fit_length(g, n); _acb_poly_cosh_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/cot_pi_series.c000066400000000000000000000051731461254215100202130ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_cot_pi_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_cot_pi(g, h, prec); _acb_vec_zero(g + 1, len - 1); } else { acb_ptr t, u; t = _acb_vec_init(len); u = _acb_vec_init(len); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(h)), 0) < 0) { _acb_poly_sin_cos_pi_series(t, u, h, hlen, len, prec); _acb_poly_div_series(g, u, len, t, len, len, prec); } else { _acb_vec_scalar_mul_2exp_si(t, h, hlen, 1); if (arf_sgn(arb_midref(acb_imagref(h))) > 0) { acb_const_pi(u, prec); acb_mul_onei(u, u); _acb_vec_scalar_mul(t, t, hlen, u, prec); _acb_poly_exp_series(t, t, hlen, len, prec); acb_sub_ui(u, t, 1, prec); _acb_vec_set(u + 1, t + 1, len - 1); _acb_poly_div_series(g, t, len, u, len, len, prec); _acb_vec_scalar_mul_2exp_si(g, g, len, 1); acb_sub_ui(g, g, 1, prec); _acb_vec_scalar_mul_onei(g, g, len); } else { acb_const_pi(u, prec); acb_div_onei(u, u); _acb_vec_scalar_mul(t, t, hlen, u, prec); _acb_poly_exp_series(t, t, hlen, len, prec); acb_sub_ui(u, t, 1, prec); _acb_vec_set(u + 1, t + 1, len - 1); _acb_poly_div_series(g, t, len, u, len, len, prec); _acb_vec_scalar_mul_2exp_si(g, g, len, 1); acb_sub_ui(g, g, 1, prec); _acb_vec_scalar_mul_onei(g, g, len); _acb_vec_neg(g, g, len); } } _acb_vec_clear(t, len); _acb_vec_clear(u, len); } } void acb_poly_cot_pi_series(acb_poly_t res, const acb_poly_t f, slong len, slong prec) { acb_poly_fit_length(res, len); if (f->length == 0 || len == 0) _acb_vec_indeterminate(res->coeffs, len); else _acb_poly_cot_pi_series(res->coeffs, f->coeffs, f->length, len, prec); _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/derivative.c000066400000000000000000000016421461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_derivative(acb_ptr res, acb_srcptr poly, slong len, slong prec) { slong i; for (i = 1; i < len; i++) acb_mul_ui(res + i - 1, poly + i, i, prec); } void acb_poly_derivative(acb_poly_t res, const acb_poly_t poly, slong prec) { slong len = poly->length; if (len < 2) { acb_poly_zero(res); } else { acb_poly_fit_length(res, len - 1); _acb_poly_derivative(res->coeffs, poly->coeffs, len, prec); _acb_poly_set_length(res, len - 1); } } flint-3.1.3/src/acb_poly/digamma_series.c000066400000000000000000000101151461254215100203250ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t x, int use_reflect, int digamma, slong prec); void _acb_poly_gamma_stirling_eval(acb_ptr res, const acb_t z, slong n, slong num, slong prec); void _acb_poly_gamma_stirling_eval2(acb_ptr res, const acb_t z, slong n, slong num, int diff, slong prec); void _acb_poly_digamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong i, r, n, rflen, wp; acb_t zr; acb_ptr t, u, v; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_digamma(res, h, prec); if (acb_is_finite(res)) _acb_vec_zero(res + 1, len - 1); else _acb_vec_indeterminate(res + 1, len - 1); return; } /* use real code for real input */ if (_acb_vec_is_real(h, hlen)) { arb_ptr tmp = _arb_vec_init(len); for (i = 0; i < hlen; i++) arb_set(tmp + i, acb_realref(h + i)); _arb_poly_digamma_series(tmp, tmp, hlen, len, prec); for (i = 0; i < len; i++) acb_set_arb(res + i, tmp + i); _arb_vec_clear(tmp, len); return; } wp = prec + FLINT_BIT_COUNT(prec); t = _acb_vec_init(len + 1); u = _acb_vec_init(len + 1); v = _acb_vec_init(len + 1); acb_init(zr); /* use Stirling series */ acb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 1, wp); /* psi(x) = psi((1-x)+r) - h(1-x,r) - pi*cot(pi*x) */ if (reflect) { if (r != 0) /* otherwise t = 0 */ { acb_sub_ui(v, h, 1, wp); acb_neg(v, v); acb_one(v + 1); rflen = FLINT_MIN(len + 1, r + 1); _acb_poly_rising_ui_series(u, v, 2, r, rflen, wp); _acb_poly_derivative(v, u, rflen, wp); _acb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp); for (i = 1; i < len; i += 2) acb_neg(t + i, t + i); } acb_sub_ui(zr, h, r + 1, wp); acb_neg(zr, zr); _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp); for (i = 1; i < len; i += 2) acb_neg(u + i, u + i); _acb_vec_sub(u, u, t, len, wp); acb_set(t, h); acb_one(t + 1); _acb_poly_cot_pi_series(t, t, 2, len, wp); acb_const_pi(v, wp); _acb_vec_scalar_mul(t, t, len, v, wp); _acb_vec_sub(u, u, t, len, wp); } else { if (r == 0) { acb_add_ui(zr, h, r, wp); _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp); } else { acb_set(v, h); acb_one(v + 1); rflen = FLINT_MIN(len + 1, r + 1); _acb_poly_rising_ui_series(u, v, 2, r, rflen, wp); _acb_poly_derivative(v, u, rflen, wp); _acb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp); acb_add_ui(zr, h, r, wp); _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp); _acb_vec_sub(u, u, t, len, wp); } } /* compose with nonconstant part */ acb_zero(t); _acb_vec_set(t + 1, h + 1, hlen - 1); _acb_poly_compose_series(res, u, len, t, hlen, len, prec); acb_clear(zr); _acb_vec_clear(t, len + 1); _acb_vec_clear(u, len + 1); _acb_vec_clear(v, len + 1); } void acb_poly_digamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) { acb_poly_fit_length(res, n); if (f->length == 0 || n == 0) _acb_vec_indeterminate(res->coeffs, n); else _acb_poly_digamma_series(res->coeffs, f->coeffs, f->length, n, prec); _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/div_root.c000066400000000000000000000021341461254215100172030ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_div_root(acb_ptr Q, acb_t R, acb_srcptr A, slong len, const acb_t c, slong prec) { acb_t r, t; slong i; if (len < 2) { acb_zero(R); return; } acb_init(r); acb_init(t); acb_set(t, A + len - 2); acb_set(Q + len - 2, A + len - 1); acb_set(r, Q + len - 2); /* TODO: avoid the extra assignments (but still support aliasing) */ for (i = len - 2; i > 0; i--) { acb_mul(r, r, c, prec); acb_add(r, r, t, prec); acb_set(t, A + i - 1); acb_set(Q + i - 1, r); } acb_mul(r, r, c, prec); acb_add(R, r, t, prec); acb_clear(r); acb_clear(t); } flint-3.1.3/src/acb_poly/div_series.c000066400000000000000000000053371461254215100175220ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_div_series(acb_ptr Q, acb_srcptr A, slong Alen, acb_srcptr B, slong Blen, slong n, slong prec) { Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (Blen == 1) { _acb_vec_scalar_div(Q, A, Alen, B, prec); _acb_vec_zero(Q + Alen, n - Alen); } else if (n == 2) { if (Alen == 1) { acb_div(Q, A, B, prec); acb_div(Q + 1, Q, B, prec); acb_mul(Q + 1, Q + 1, B + 1, prec); acb_neg(Q + 1, Q + 1); } else { acb_div(Q, A, B, prec); acb_mul(Q + 1, Q, B + 1, prec); acb_sub(Q + 1, A + 1, Q + 1, prec); acb_div(Q + 1, Q + 1, B, prec); } } else if (Blen == 2 || n <= 10) { /* The basecase algorithm is faster for much larger Blen and n than this, but unfortunately has worse numerical stability. */ slong i; acb_t q; acb_init(q); acb_inv(q, B, prec); acb_div(Q, A, B, prec); for (i = 1; i < n; i++) { acb_dot(Q + i, (i < Alen) ? A + i : NULL, 1, B + 1, 1, Q + i - 1, -1, FLINT_MIN(i, Blen - 1), prec); if (!acb_is_one(q)) acb_mul(Q + i, Q + i, q, prec); } acb_clear(q); } else { acb_ptr Binv; Binv = _acb_vec_init(n); _acb_poly_inv_series(Binv, B, Blen, n, prec); _acb_poly_mullow(Q, Binv, n, A, Alen, n, prec); _acb_vec_clear(Binv, n); } } void acb_poly_div_series(acb_poly_t Q, const acb_poly_t A, const acb_poly_t B, slong n, slong prec) { if (n == 0) { acb_poly_zero(Q); return; } if (B->length == 0) { acb_poly_fit_length(Q, n); _acb_vec_indeterminate(Q->coeffs, n); _acb_poly_set_length(Q, n); return; } if (A->length == 0) { acb_poly_zero(Q); return; } if (Q == A || Q == B) { acb_poly_t t; acb_poly_init(t); acb_poly_div_series(t, A, B, n, prec); acb_poly_swap(Q, t); acb_poly_clear(t); return; } acb_poly_fit_length(Q, n); _acb_poly_div_series(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, n, prec); _acb_poly_set_length(Q, n); _acb_poly_normalise(Q); } flint-3.1.3/src/acb_poly/divrem.c000066400000000000000000000056631461254215100166560ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" /* TODO: tighten this code */ void _acb_poly_div(acb_ptr Q, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) { slong lenQ, lenB2; acb_ptr Arev, Brev; lenQ = lenA - lenB + 1; Arev = _acb_vec_init(2 * lenQ); Brev = Arev + lenQ; _acb_poly_reverse(Arev, A + (lenA - lenQ), lenQ, lenQ); if (lenB >= lenQ) { _acb_poly_reverse(Brev, B + (lenB - lenQ), lenQ, lenQ); lenB2 = lenQ; } else { _acb_poly_reverse(Brev, B, lenB, lenB); lenB2 = lenB; } _acb_poly_div_series(Q, Arev, lenQ, Brev, lenB2, lenQ, prec); _acb_poly_reverse(Q, Q, lenQ, lenQ); _acb_vec_clear(Arev, 2 * lenQ); } void _acb_poly_divrem(acb_ptr Q, acb_ptr R, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) { const slong lenQ = lenA - lenB + 1; _acb_poly_div(Q, A, lenA, B, lenB, prec); if (lenB > 1) { if (lenQ >= lenB - 1) _acb_poly_mullow(R, Q, lenQ, B, lenB - 1, lenB - 1, prec); else _acb_poly_mullow(R, B, lenB - 1, Q, lenQ, lenB - 1, prec); _acb_vec_sub(R, A, R, lenB - 1, prec); } } void _acb_poly_rem(acb_ptr R, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) { const slong lenQ = lenA - lenB + 1; acb_ptr Q = _acb_vec_init(lenQ); _acb_poly_divrem(Q, R, A, lenA, B, lenB, prec); _acb_vec_clear(Q, lenQ); } int acb_poly_divrem(acb_poly_t Q, acb_poly_t R, const acb_poly_t A, const acb_poly_t B, slong prec) { const slong lenA = A->length, lenB = B->length; if (lenB == 0 || acb_contains_zero(B->coeffs + lenB - 1)) { return 0; } if (lenA < lenB) { acb_poly_set(R, A); acb_poly_zero(Q); return 1; } if (Q == A || Q == B) { acb_poly_t T; acb_poly_init(T); acb_poly_divrem(T, R, A, B, prec); acb_poly_swap(Q, T); acb_poly_clear(T); return 1; } if (R == A || R == B) { acb_poly_t U; acb_poly_init(U); acb_poly_divrem(Q, U, A, B, prec); acb_poly_swap(R, U); acb_poly_clear(U); return 1; } acb_poly_fit_length(Q, lenA - lenB + 1); acb_poly_fit_length(R, lenB - 1); _acb_poly_divrem(Q->coeffs, R->coeffs, A->coeffs, lenA, B->coeffs, lenB, prec); _acb_poly_set_length(Q, lenA - lenB + 1); _acb_poly_set_length(R, lenB - 1); _acb_poly_normalise(R); return 1; } flint-3.1.3/src/acb_poly/elliptic_k_series.c000066400000000000000000000013531461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_modular.h" #include "acb_elliptic.h" void _acb_poly_elliptic_k_series(acb_ptr res, acb_srcptr z, slong zlen, slong len, slong prec) { _acb_elliptic_k_series(res, z, zlen, len, prec); } void acb_poly_elliptic_k_series(acb_poly_t res, const acb_poly_t z, slong n, slong prec) { acb_elliptic_k_series(res, z, n, prec); } flint-3.1.3/src/acb_poly/elliptic_p_series.c000066400000000000000000000014271461254215100210600ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_modular.h" #include "acb_elliptic.h" void _acb_poly_elliptic_p_series(acb_ptr res, acb_srcptr z, slong zlen, const acb_t tau, slong len, slong prec) { _acb_elliptic_p_series(res, z, zlen, tau, len, prec); } void acb_poly_elliptic_p_series(acb_poly_t res, const acb_poly_t z, const acb_t tau, slong n, slong prec) { acb_elliptic_p_series(res, z, tau, n, prec); } flint-3.1.3/src/acb_poly/equal.c000066400000000000000000000012251461254215100164650ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" int acb_poly_equal(const acb_poly_t A, const acb_poly_t B) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) if (!acb_equal(A->coeffs + i, B->coeffs + i)) return 0; return 1; } flint-3.1.3/src/acb_poly/erf_series.c000066400000000000000000000012711461254215100175050ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_poly_erf_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { _acb_hypgeom_erf_series(g, h, hlen, n, prec); } void acb_poly_erf_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { acb_hypgeom_erf_series(g, h, n, prec); } flint-3.1.3/src/acb_poly/evaluate.c000066400000000000000000000017341461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_evaluate(acb_t res, acb_srcptr f, slong len, const acb_t x, slong prec) { if ((prec >= 1024) && (len >= 5 + 20000 / prec)) { slong fbits; fbits = _acb_vec_bits(f, len); if (fbits <= prec / 2) { _acb_poly_evaluate_rectangular(res, f, len, x, prec); return; } } _acb_poly_evaluate_horner(res, f, len, x, prec); } void acb_poly_evaluate(acb_t res, const acb_poly_t f, const acb_t a, slong prec) { _acb_poly_evaluate(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/acb_poly/evaluate2.c000066400000000000000000000017271461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_evaluate2(acb_t y, acb_t z, acb_srcptr f, slong len, const acb_t x, slong prec) { if ((prec >= 1024) && (len >= 5 + 20000 / prec)) { slong fbits; fbits = _acb_vec_bits(f, len); if (fbits <= prec / 2) { _acb_poly_evaluate2_rectangular(y, z, f, len, x, prec); return; } } _acb_poly_evaluate2_horner(y, z, f, len, x, prec); } void acb_poly_evaluate2(acb_t r, acb_t s, const acb_poly_t f, const acb_t a, slong prec) { _acb_poly_evaluate2(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/acb_poly/evaluate2_horner.c000066400000000000000000000032011461254215100206170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_evaluate2_horner(acb_t y, acb_t z, acb_srcptr poly, slong len, const acb_t x, slong prec) { if (len == 0) { acb_zero(y); acb_zero(z); } else if (len == 1) { acb_set_round(y, poly + 0, prec); acb_zero(z); } else if (acb_is_zero(x)) { acb_set_round(y, poly + 0, prec); acb_set_round(z, poly + 1, prec); } else if (len == 2) { acb_mul(y, x, poly + 1, prec); acb_add(y, y, poly + 0, prec); acb_set_round(z, poly + 1, prec); } else { acb_t t, u, v; slong i; acb_init(t); acb_init(u); acb_init(v); acb_set_round(u, poly + len - 1, prec); acb_zero(v); for (i = len - 2; i >= 0; i--) { acb_mul(t, v, x, prec); acb_add(v, u, t, prec); acb_mul(t, u, x, prec); acb_add(u, t, poly + i, prec); } acb_swap(y, u); acb_swap(z, v); acb_clear(t); acb_clear(u); acb_clear(v); } } void acb_poly_evaluate2_horner(acb_t r, acb_t s, const acb_poly_t f, const acb_t a, slong prec) { _acb_poly_evaluate2_horner(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/acb_poly/evaluate2_rectangular.c000066400000000000000000000047371461254215100216500ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb_poly.h" void _acb_poly_evaluate2_rectangular(acb_t y, acb_t z, acb_srcptr poly, slong len, const acb_t x, slong prec) { slong i, j, m, r; acb_ptr xs; acb_t s, t, c; if (len < 3) { if (len == 0) { acb_zero(y); acb_zero(z); } else if (len == 1) { acb_set_round(y, poly + 0, prec); acb_zero(z); } else if (len == 2) { acb_mul(y, x, poly + 1, prec); acb_add(y, y, poly + 0, prec); acb_set_round(z, poly + 1, prec); } return; } m = n_sqrt(len) + 1; m *= 1; r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); acb_init(c); _acb_vec_set_powers(xs, x, m + 1, prec); acb_dot(y, poly + (r - 1) * m, 0, xs + 1, 1, poly + (r - 1) * m + 1, 1, len - (r - 1) * m - 1, prec); for (i = r - 2; i >= 0; i--) { acb_dot(s, poly + i * m, 0, xs + 1, 1, poly + i * m + 1, 1, m - 1, prec); acb_mul(y, y, xs + m, prec); acb_add(y, y, s, prec); } /* todo: rewrite using acb_dot */ len -= 1; r = (len + m - 1) / m; acb_mul_ui(z, poly + (r - 1) * m + 1, (r - 1) * m + 1, ARF_PREC_EXACT); for (j = 1; (r - 1) * m + j < len; j++) { acb_mul_ui(c, poly + (r - 1) * m + j + 1, (r - 1) * m + j + 1, ARF_PREC_EXACT); acb_addmul(z, xs + j, c, prec); } for (i = r - 2; i >= 0; i--) { acb_mul_ui(s, poly + i * m + 1, i * m + 1, ARF_PREC_EXACT); for (j = 1; j < m; j++) { acb_mul_ui(c, poly + i * m + j + 1, i * m + j + 1, ARF_PREC_EXACT); acb_addmul(s, xs + j, c, prec); } acb_mul(z, z, xs + m, prec); acb_add(z, z, s, prec); } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); acb_clear(c); } void acb_poly_evaluate2_rectangular(acb_t r, acb_t s, const acb_poly_t f, const acb_t a, slong prec) { _acb_poly_evaluate2_rectangular(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/acb_poly/evaluate_horner.c000066400000000000000000000024511461254215100205430ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_evaluate_horner(acb_t y, acb_srcptr f, slong len, const acb_t x, slong prec) { if (len == 0) { acb_zero(y); } else if (len == 1 || acb_is_zero(x)) { acb_set_round(y, f, prec); } else if (len == 2) { acb_mul(y, x, f + 1, prec); acb_add(y, y, f + 0, prec); } else { slong i = len - 1; acb_t t, u; acb_init(t); acb_init(u); acb_set(u, f + i); for (i = len - 2; i >= 0; i--) { acb_mul(t, u, x, prec); acb_add(u, f + i, t, prec); } acb_swap(y, u); acb_clear(t); acb_clear(u); } } void acb_poly_evaluate_horner(acb_t res, const acb_poly_t f, const acb_t a, slong prec) { _acb_poly_evaluate_horner(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/acb_poly/evaluate_rectangular.c000066400000000000000000000032361461254215100215570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb_poly.h" void _acb_poly_evaluate_rectangular(acb_t y, acb_srcptr poly, slong len, const acb_t x, slong prec) { slong i, m, r; acb_ptr xs; acb_t s, t, c; if (len < 3) { if (len == 0) { acb_zero(y); } else if (len == 1) { acb_set_round(y, poly + 0, prec); } else if (len == 2) { acb_mul(y, x, poly + 1, prec); acb_add(y, y, poly + 0, prec); } return; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); acb_init(c); _acb_vec_set_powers(xs, x, m + 1, prec); acb_dot(y, poly + (r - 1) * m, 0, xs + 1, 1, poly + (r - 1) * m + 1, 1, len - (r - 1) * m - 1, prec); for (i = r - 2; i >= 0; i--) { acb_dot(s, poly + i * m, 0, xs + 1, 1, poly + i * m + 1, 1, m - 1, prec); acb_mul(y, y, xs + m, prec); acb_add(y, y, s, prec); } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); acb_clear(c); } void acb_poly_evaluate_rectangular(acb_t res, const acb_poly_t f, const acb_t a, slong prec) { _acb_poly_evaluate_rectangular(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/acb_poly/evaluate_vec_fast.c000066400000000000000000000067121461254215100210440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" /* This gives some speedup for small lengths. */ static inline void _acb_poly_rem_2(acb_ptr r, acb_srcptr a, slong al, acb_srcptr b, slong bl, slong prec) { if (al == 2) { acb_mul(r + 0, a + 1, b + 0, prec); acb_sub(r + 0, a + 0, r + 0, prec); } else { _acb_poly_rem(r, a, al, b, bl, prec); } } void _acb_poly_evaluate_vec_fast_precomp(acb_ptr vs, acb_srcptr poly, slong plen, acb_ptr * tree, slong len, slong prec) { slong height, i, j, pow, left; slong tree_height; slong tlen; acb_ptr t, u, swap, pa, pb, pc; /* avoid worrying about some degenerate cases */ if (len < 2 || plen < 2) { if (len == 1) { acb_t tmp; acb_init(tmp); acb_neg(tmp, tree[0] + 0); _acb_poly_evaluate(vs + 0, poly, plen, tmp, prec); acb_clear(tmp); } else if (len != 0 && plen == 0) { _acb_vec_zero(vs, len); } else if (len != 0 && plen == 1) { for (i = 0; i < len; i++) acb_set(vs + i, poly + 0); } return; } t = _acb_vec_init(len); u = _acb_vec_init(len); left = len; /* Initial reduction. We allow the polynomial to be larger or smaller than the number of points. */ height = FLINT_BIT_COUNT(plen - 1) - 1; tree_height = FLINT_CLOG2(len); while (height >= tree_height) height--; pow = WORD(1) << height; for (i = j = 0; i < len; i += pow, j += (pow + 1)) { tlen = ((i + pow) <= len) ? pow : len % pow; _acb_poly_rem(t + i, poly, plen, tree[height] + j, tlen + 1, prec); } for (i = height - 1; i >= 0; i--) { pow = WORD(1) << i; left = len; pa = tree[i]; pb = t; pc = u; while (left >= 2 * pow) { _acb_poly_rem_2(pc, pb, 2 * pow, pa, pow + 1, prec); _acb_poly_rem_2(pc + pow, pb, 2 * pow, pa + pow + 1, pow + 1, prec); pa += 2 * pow + 2; pb += 2 * pow; pc += 2 * pow; left -= 2 * pow; } if (left > pow) { _acb_poly_rem(pc, pb, left, pa, pow + 1, prec); _acb_poly_rem(pc + pow, pb, left, pa + pow + 1, left - pow + 1, prec); } else if (left > 0) _acb_vec_set(pc, pb, left); swap = t; t = u; u = swap; } _acb_vec_set(vs, t, len); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void _acb_poly_evaluate_vec_fast(acb_ptr ys, acb_srcptr poly, slong plen, acb_srcptr xs, slong n, slong prec) { acb_ptr * tree; tree = _acb_poly_tree_alloc(n); _acb_poly_tree_build(tree, xs, n, prec); _acb_poly_evaluate_vec_fast_precomp(ys, poly, plen, tree, n, prec); _acb_poly_tree_free(tree, n); } void acb_poly_evaluate_vec_fast(acb_ptr ys, const acb_poly_t poly, acb_srcptr xs, slong n, slong prec) { _acb_poly_evaluate_vec_fast(ys, poly->coeffs, poly->length, xs, n, prec); } flint-3.1.3/src/acb_poly/evaluate_vec_iter.c000066400000000000000000000015361461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_evaluate_vec_iter(acb_ptr ys, acb_srcptr poly, slong plen, acb_srcptr xs, slong n, slong prec) { slong i; for (i = 0; i < n; i++) _acb_poly_evaluate(ys + i, poly, plen, xs + i, prec); } void acb_poly_evaluate_vec_iter(acb_ptr ys, const acb_poly_t poly, acb_srcptr xs, slong n, slong prec) { _acb_poly_evaluate_vec_iter(ys, poly->coeffs, poly->length, xs, n, prec); } flint-3.1.3/src/acb_poly/exp_pi_i_series.c000066400000000000000000000033721461254215100205310ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_exp_pi_i_series(acb_ptr f, acb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_exp_pi_i(f, h, prec); _acb_vec_zero(f + 1, len - 1); } else if (len == 2) { arb_t t; arb_init(t); arb_const_pi(t, prec); acb_exp_pi_i(f, h, prec); acb_mul_arb(f + 1, h + 1, t, prec); acb_mul_onei(f + 1, f + 1); acb_mul(f + 1, f + 1, f + 0, prec); arb_clear(t); } else { acb_ptr t; t = _acb_vec_init(hlen + 1); acb_const_pi(t, prec); acb_mul_onei(t, t); _acb_vec_scalar_mul(t + 1, h + 1, hlen - 1, t, prec); acb_zero(t); acb_exp_pi_i(t + hlen, h, prec); _acb_poly_exp_series(f, t, hlen, len, prec); _acb_vec_scalar_mul(f, f, len, t + hlen, prec); _acb_vec_clear(t, hlen + 1); } } void acb_poly_exp_pi_i_series(acb_poly_t f, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(f); return; } if (hlen == 0) { acb_poly_one(f); return; } if (hlen == 1) n = 1; acb_poly_fit_length(f, n); _acb_poly_exp_pi_i_series(f->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(f, n); _acb_poly_normalise(f); } flint-3.1.3/src/acb_poly/exp_series.c000066400000000000000000000120731461254215100175270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif /* allow changing this from the test code */ FLINT_DLL slong acb_poly_newton_exp_cutoff = 0; /* with inverse=1 simultaneously computes g = exp(-x) to length n with inverse=0 uses g as scratch space, computing g = exp(-x) only to length (n+1)/2 */ static void _acb_poly_exp_series_newton(acb_ptr f, acb_ptr g, acb_srcptr h, slong len, slong prec, int inverse, slong cutoff) { slong alloc; acb_ptr T, U, hprime; alloc = 3 * len; T = _acb_vec_init(alloc); U = T + len; hprime = U + len; _acb_poly_derivative(hprime, h, len, prec); acb_zero(hprime + len - 1); NEWTON_INIT(cutoff, len) /* f := exp(h) + O(x^m), g := exp(-h) + O(x^m2) */ NEWTON_BASECASE(n) _acb_poly_exp_series_basecase(f, h, n, n, prec); _acb_poly_inv_series(g, f, (n + 1) / 2, (n + 1) / 2, prec); NEWTON_END_BASECASE /* extend from length m to length n */ NEWTON_LOOP(m, n) slong m2 = (m + 1) / 2; slong l = m - 1; /* shifted for derivative */ /* g := exp(-h) + O(x^m) */ _acb_poly_mullow(T, f, m, g, m2, m, prec); _acb_poly_mullow(g + m2, g, m2, T + m2, m - m2, m - m2, prec); _acb_vec_neg(g + m2, g + m2, m - m2); /* U := h' + g (f' - f h') + O(x^(n-1)) Note: should replace h' by h' mod x^(m-1) */ _acb_vec_zero(f + m, n - m); _acb_poly_mullow(T, f, n, hprime, n, n, prec); /* should be mulmid */ _acb_poly_derivative(U, f, n, prec); acb_zero(U + n - 1); /* should skip low terms */ _acb_vec_sub(U + l, U + l, T + l, n - l, prec); _acb_poly_mullow(T + l, g, n - m, U + l, n - m, n - m, prec); _acb_vec_add(U + l, hprime + l, T + l, n - m, prec); /* f := f + f * (h - int U) + O(x^n) = exp(h) + O(x^n) */ _acb_poly_integral(U, U, n, prec); /* should skip low terms */ _acb_vec_sub(U + m, h + m, U + m, n - m, prec); _acb_poly_mullow(f + m, f, n - m, U + m, n - m, n - m, prec); /* g := exp(-h) + O(x^n) */ /* not needed if we only want exp(x) */ if (n == len && inverse) { _acb_poly_mullow(T, f, n, g, m, n, prec); _acb_poly_mullow(g + m, g, m, T + m, n - m, n - m, prec); _acb_vec_neg(g + m, g + m, n - m); } NEWTON_END_LOOP NEWTON_END _acb_vec_clear(T, alloc); } void _acb_poly_exp_series(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_exp(f, h, prec); _acb_vec_zero(f + 1, n - 1); } else if (n == 2) { acb_exp(f, h, prec); acb_mul(f + 1, f, h + 1, prec); /* safe since hlen >= 2 */ } else if (_acb_vec_is_zero(h + 1, hlen - 2)) /* h = a + bx^d */ { slong i, j, d = hlen - 1; acb_t t; acb_init(t); acb_set(t, h + d); acb_exp(f, h, prec); for (i = 1, j = d; j < n; j += d, i++) { acb_mul(f + j, f + j - d, t, prec); acb_div_ui(f + j, f + j, i, prec); _acb_vec_zero(f + j - d + 1, hlen - 2); } _acb_vec_zero(f + j - d + 1, n - (j - d + 1)); acb_clear(t); } else { slong cutoff; if (acb_poly_newton_exp_cutoff != 0) cutoff = acb_poly_newton_exp_cutoff; else if (prec <= 256) cutoff = 750; else cutoff = 1e5 / pow(log(prec), 3); if (hlen <= cutoff) { _acb_poly_exp_series_basecase(f, h, hlen, n, prec); } else { acb_ptr g, t; acb_t u; int fix; g = _acb_vec_init((n + 1) / 2); fix = (hlen < n || h == f || !acb_is_zero(h)); if (fix) { t = _acb_vec_init(n); _acb_vec_set(t + 1, h + 1, hlen - 1); } else t = (acb_ptr) h; acb_init(u); acb_exp(u, h, prec); _acb_poly_exp_series_newton(f, g, t, n, prec, 0, cutoff); if (!acb_is_one(u)) _acb_vec_scalar_mul(f, f, n, u, prec); _acb_vec_clear(g, (n + 1) / 2); if (fix) _acb_vec_clear(t, n); acb_clear(u); } } } void acb_poly_exp_series(acb_poly_t f, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(f); return; } if (hlen == 0) { acb_poly_one(f); return; } if (hlen == 1) n = 1; acb_poly_fit_length(f, n); _acb_poly_exp_series(f->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(f, n); _acb_poly_normalise(f); } flint-3.1.3/src/acb_poly/exp_series_basecase.c000066400000000000000000000045541461254215100213620ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif static void _acb_poly_exp_series_basecase_rec(acb_ptr f, acb_ptr a, acb_srcptr h, slong hlen, slong n, slong prec) { slong k; acb_t s; acb_init(s); acb_exp(f, h, prec); for (k = 1; k < hlen; k++) acb_mul_ui(a + k, h + k, k, prec); for (k = 1; k < n; k++) { acb_dot(s, NULL, 0, a + 1, 1, f + k - 1, -1, FLINT_MIN(k, hlen - 1), prec); acb_div_ui(f + k, s, k, prec); } acb_clear(s); } void _acb_poly_exp_series_basecase(acb_ptr f, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(n, hlen); if (n < 20 || hlen < 0.9 * n || prec <= 2 * FLINT_BITS || n < 1000.0 / log(prec + 10) - 70) { acb_ptr t = _acb_vec_init(hlen); _acb_poly_exp_series_basecase_rec(f, t, h, hlen, n, prec); _acb_vec_clear(t, hlen); } else { slong m, v; acb_ptr t, u; m = (n + 2) / 3; v = m * 2; t = _acb_vec_init(n); u = _acb_vec_init(n - m); _acb_poly_mullow(t, h + m, hlen - m, h + m, hlen - m, n - v, prec); _acb_vec_scalar_mul_2exp_si(t, t, n - v, -1); _acb_vec_set(u, h + m, v - m); _acb_poly_add(u + v - m, t, n - v, h + v, hlen - v, prec); _acb_poly_exp_series_basecase_rec(f, t, h, m, n, prec); _acb_poly_mullow(t, f, n, u, n - m, n - m, prec); _acb_poly_add(f + m, f + m, n - m, t, n - m, prec); _acb_vec_clear(t, n); _acb_vec_clear(u, n - m); } } void acb_poly_exp_series_basecase(acb_poly_t f, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(f); return; } if (hlen == 0) { acb_poly_one(f); return; } acb_poly_fit_length(f, n); _acb_poly_exp_series_basecase(f->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(f, n); _acb_poly_normalise(f); } flint-3.1.3/src/acb_poly/find_roots.c000066400000000000000000000077641461254215100175420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" #include "acb_poly.h" slong _acb_get_mid_mag(const acb_t z) { slong rm, im; rm = arf_abs_bound_lt_2exp_si(arb_midref(acb_realref(z))); im = arf_abs_bound_lt_2exp_si(arb_midref(acb_imagref(z))); return FLINT_MAX(rm, im); } slong _acb_get_rad_mag(const acb_t z) { slong rm, im; /* TODO: write mag function */ arf_t t; arf_init(t); arf_set_mag(t, arb_radref(acb_realref(z))); rm = arf_abs_bound_lt_2exp_si(t); arf_set_mag(t, arb_radref(acb_imagref(z))); im = arf_abs_bound_lt_2exp_si(t); arf_clear(t); return FLINT_MAX(rm, im); } void _acb_poly_roots_initial_values(acb_ptr roots, slong deg, slong prec) { slong i; fmpq_t q; fmpq_init(q); fmpq_set_si(q, 4, 10); arb_set_fmpq(acb_realref(roots + 0), q, prec); mag_zero(arb_radref(acb_realref(roots + 0))); fmpq_set_si(q, 9, 10); arb_set_fmpq(acb_imagref(roots + 0), q, prec); mag_zero(arb_radref(acb_imagref(roots + 0))); fmpq_clear(q); for (i = 1; i < deg; i++) { acb_mul(roots + i, roots + i - 1, roots + 0, prec); mag_zero(arb_radref(acb_realref(roots + i))); mag_zero(arb_radref(acb_imagref(roots + i))); } } slong _acb_poly_find_roots(acb_ptr roots, acb_srcptr poly, acb_srcptr initial, slong len, slong maxiter, slong prec) { slong iter, i, deg; slong rootmag, max_rootmag, correction, max_correction; deg = len - 1; if (deg == 0) { return 0; } else if (acb_contains_zero(poly + len - 1)) { /* if the leading coefficient contains zero, roots can be anywhere */ for (i = 0; i < deg; i++) { arb_zero_pm_inf(acb_realref(roots + i)); arb_zero_pm_inf(acb_imagref(roots + i)); } return 0; } else if (deg == 1) { acb_inv(roots + 0, poly + 1, prec); acb_mul(roots + 0, roots + 0, poly + 0, prec); acb_neg(roots + 0, roots + 0); return 1; } if (initial == NULL) _acb_poly_roots_initial_values(roots, deg, prec); else _acb_vec_set(roots, initial, deg); if (maxiter == 0) maxiter = 2 * deg + n_sqrt(prec); for (iter = 0; iter < maxiter; iter++) { max_rootmag = -ARF_PREC_EXACT; for (i = 0; i < deg; i++) { rootmag = _acb_get_mid_mag(roots + i); max_rootmag = FLINT_MAX(rootmag, max_rootmag); } _acb_poly_refine_roots_durand_kerner(roots, poly, len, prec); max_correction = -ARF_PREC_EXACT; for (i = 0; i < deg; i++) { correction = _acb_get_rad_mag(roots + i); max_correction = FLINT_MAX(correction, max_correction); } /* estimate the correction relative to the whole set of roots */ max_correction -= max_rootmag; /* flint_printf("ITER %wd MAX CORRECTION: %wd\n", iter, max_correction); */ if (max_correction < -prec / 2) maxiter = FLINT_MIN(maxiter, iter + 2); else if (max_correction < -prec / 3) maxiter = FLINT_MIN(maxiter, iter + 3); else if (max_correction < -prec / 4) maxiter = FLINT_MIN(maxiter, iter + 4); } return _acb_poly_validate_roots(roots, poly, len, prec); } slong acb_poly_find_roots(acb_ptr roots, const acb_poly_t poly, acb_srcptr initial, slong maxiter, slong prec) { slong len = poly->length; if (len == 0) { flint_throw(FLINT_ERROR, "find_roots: expected a nonzero polynomial"); } return _acb_poly_find_roots(roots, poly->coeffs, initial, len, maxiter, prec); } flint-3.1.3/src/acb_poly/fit_length.c000066400000000000000000000014261461254215100175040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_fit_length(acb_poly_t poly, slong len) { slong i; if (len > poly->alloc) { if (len < 2 * poly->alloc) len = 2 * poly->alloc; poly->coeffs = flint_realloc(poly->coeffs, len * sizeof(acb_struct)); for (i = poly->alloc; i < len; i++) acb_init(poly->coeffs + i); poly->alloc = len; } } flint-3.1.3/src/acb_poly/gamma_series.c000066400000000000000000000214421461254215100200150ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void acb_gamma_stirling_bound(mag_ptr err, const acb_t x, slong k0, slong knum, slong n); void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t x, int use_reflect, int digamma, slong prec); void arb_gamma_stirling_coeff(arb_t b, ulong k, int digamma, slong prec); static void bsplit(acb_ptr Q, acb_ptr T, const acb_t z, slong a, slong b, slong num, slong prec) { if (b - a == 1) { arb_gamma_stirling_coeff(acb_realref(T), a, 0, prec); arb_zero(acb_imagref(T)); if (a == 1) { /* (z + t) */ acb_set(Q, z); if (num > 1) acb_one(Q + 1); if (num > 2) acb_zero(Q + 2); } else { /* (z + t)^2 */ acb_mul(Q, z, z, prec); /* TODO: precompute */ if (num > 1) acb_mul_2exp_si(Q + 1, z, 1); if (num > 2) acb_one(Q + 2); } } else { slong m, n1, n2, q1len, q2len, t1len, t2len, qlen, tlen, alloc; acb_ptr Q1, T1, Q2, T2; m = a + (b - a) / 2; n1 = m - a; n2 = b - m; q1len = FLINT_MIN(2 * n1 + 1, num); t1len = FLINT_MIN(2 * n1 - 1, num); q2len = FLINT_MIN(2 * n2 + 1, num); t2len = FLINT_MIN(2 * n2 - 1, num); qlen = FLINT_MIN(q1len + q2len - 1, num); tlen = FLINT_MIN(t1len + q2len - 1, num); alloc = q1len + q2len + t1len + t2len; Q1 = _acb_vec_init(alloc); Q2 = Q1 + q1len; T1 = Q2 + q2len; T2 = T1 + t1len; bsplit(Q1, T1, z, a, m, num, prec); bsplit(Q2, T2, z, m, b, num, prec); _acb_poly_mullow(Q, Q2, q2len, Q1, q1len, qlen, prec); _acb_poly_mullow(T, Q2, q2len, T1, t1len, tlen, prec); _acb_poly_add(T, T, tlen, T2, t2len, prec); _acb_vec_clear(Q1, alloc); } } void _acb_poly_log_cpx_series(acb_ptr res, const acb_t c, slong num, slong prec) { slong i; for (i = 0; i < num; i++) { if (i == 0) acb_log(res + i, c, prec); else if (i == 1) acb_inv(res + i, c, prec); else acb_mul(res + i, res + i - 1, res + 1, prec); } for (i = 2; i < num; i++) { acb_div_ui(res + i, res + i, i, prec); if (i % 2 == 0) acb_neg(res + i, res + i); } } void _acb_poly_gamma_stirling_eval2(acb_ptr res, const acb_t z, slong n, slong num, int diff, slong prec) { slong k, tlen, qlen; acb_ptr T, Q; mag_ptr err; acb_t c; T = _acb_vec_init(num); Q = _acb_vec_init(num); err = _mag_vec_init(num); acb_init(c); acb_gamma_stirling_bound(err, z, 0, num, n); if (n <= 1) { _acb_vec_zero(res, num); } else { qlen = FLINT_MIN(2 * (n - 1) + 1, num); tlen = FLINT_MIN(2 * (n - 1) - 1, num); bsplit(Q, T, z, 1, n, num, prec); _acb_poly_div_series(res, T, tlen, Q, qlen, num, prec); } if (diff) { _acb_vec_add_error_mag_vec(res, err, num); _acb_poly_derivative(res, res, num, prec); if (num > 1) { /* add log(z+x) - 1/(2(z+x)) */ acb_inv(c, z, prec); _acb_vec_set_powers(T, c, num, prec); for (k = 1; k < num - 1; k++) { acb_mul_2exp_si(T, z, 1); acb_div_ui(T, T, k, prec); acb_add_ui(T, T, 1, prec); acb_mul_2exp_si(T, T, -1); if (k % 2 == 0) acb_submul(res + k, T, T + k + 1, prec); else acb_addmul(res + k, T, T + k + 1, prec); } acb_mul_2exp_si(c, c, -1); acb_sub(res, res, c, prec); acb_log(c, z, prec); acb_add(res, res, c, prec); } } else { /* ((z-1/2) + t) * log(z+t) */ _acb_poly_log_cpx_series(T, z, num, prec); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_sub(c, z, c, prec); _acb_poly_mullow_cpx(T, T, num, c, num, prec); /* constant term */ arb_const_log_sqrt2pi(acb_realref(c), prec); arb_zero(acb_imagref(c)); acb_add(T, T, c, prec); /* subtract (z+t) */ acb_sub(T, T, z, prec); if (num > 1) acb_sub_ui(T + 1, T + 1, 1, prec); _acb_vec_add(res, res, T, num, prec); _acb_vec_add_error_mag_vec(res, err, num); } _acb_vec_clear(T, num); _acb_vec_clear(Q, num); _mag_vec_clear(err, num); acb_clear(c); } void _acb_poly_gamma_stirling_eval(acb_ptr res, const acb_t z, slong n, slong num, slong prec) { _acb_poly_gamma_stirling_eval2(res, z, n, num, 0, prec); } void _acb_poly_gamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong i, rflen, r, n, wp; acb_ptr t, u, v; acb_struct f[2]; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_gamma(res, h, prec); if (acb_is_finite(res)) _acb_vec_zero(res + 1, len - 1); else _acb_vec_indeterminate(res + 1, len - 1); return; } /* use real code for real input */ if (_acb_vec_is_real(h, hlen)) { arb_ptr tmp = _arb_vec_init(len); for (i = 0; i < hlen; i++) arb_set(tmp + i, acb_realref(h + i)); _arb_poly_gamma_series(tmp, tmp, hlen, len, prec); for (i = 0; i < len; i++) acb_set_arb(res + i, tmp + i); _arb_vec_clear(tmp, len); return; } wp = prec + FLINT_BIT_COUNT(prec); t = _acb_vec_init(len); u = _acb_vec_init(len); v = _acb_vec_init(len); acb_init(f); acb_init(f + 1); /* use Stirling series */ acb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp); /* gamma(h) = (rf(1-h, r) * pi) / (gamma(1-h+r) sin(pi h)), h = h0 + t*/ if (reflect) { /* u = 1/gamma(r+1-h) */ acb_sub_ui(f, h, r + 1, wp); acb_neg(f, f); _acb_poly_gamma_stirling_eval(t, f, n, len, wp); _acb_vec_neg(t, t, len); _acb_poly_exp_series(u, t, len, len, wp); for (i = 1; i < len; i += 2) acb_neg(u + i, u + i); /* v = 1/sin(pi x) */ acb_set(f, h); acb_one(f + 1); _acb_poly_sin_pi_series(t, f, 2, len, wp); _acb_poly_inv_series(v, t, len, len, wp); _acb_poly_mullow(t, u, len, v, len, len, wp); /* rf(1-h,r) * pi */ if (r == 0) { rflen = 1; acb_const_pi(u, wp); } else { acb_sub_ui(f, h, 1, wp); acb_neg(f, f); acb_set_si(f + 1, -1); rflen = FLINT_MIN(len, r + 1); _acb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), r, rflen, wp); acb_const_pi(v, wp); _acb_vec_scalar_mul(u, u, rflen, v, wp); } /* multiply by rising factorial */ _acb_poly_mullow(v, t, len, u, rflen, len, wp); } else { /* gamma(h) = gamma(h+r) / rf(h,r) */ if (r == 0) { acb_add_ui(f, h, r, wp); _acb_poly_gamma_stirling_eval(t, f, n, len, wp); _acb_poly_exp_series(v, t, len, len, wp); } else { /* TODO: div_series may be better (once it has a good basecase), if the rising factorial is short */ acb_set(f, h); acb_one(f + 1); rflen = FLINT_MIN(len, r + 1); _acb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), r, rflen, wp); _acb_poly_inv_series(t, u, rflen, len, wp); acb_add_ui(f, h, r, wp); _acb_poly_gamma_stirling_eval(v, f, n, len, wp); _acb_poly_exp_series(u, v, len, len, wp); _acb_poly_mullow(v, u, len, t, len, len, wp); } } /* compose with nonconstant part */ acb_zero(t); _acb_vec_set(t + 1, h + 1, hlen - 1); _acb_poly_compose_series(res, v, len, t, hlen, len, prec); acb_clear(f); acb_clear(f + 1); _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(v, len); } void acb_poly_gamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) { acb_poly_fit_length(res, n); if (f->length == 0 || n == 0) _acb_vec_indeterminate(res->coeffs, n); else _acb_poly_gamma_series(res->coeffs, f->coeffs, f->length, n, prec); _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/get_coeff_acb.c000066400000000000000000000010751461254215100201070ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_get_coeff_acb(acb_t x, const acb_poly_t poly, slong n) { if (n < poly->length) acb_set(x, poly->coeffs + n); else acb_zero(x); } flint-3.1.3/src/acb_poly/get_unique_fmpz_poly.c000066400000000000000000000013531461254215100216240ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "acb_poly.h" int acb_poly_get_unique_fmpz_poly(fmpz_poly_t res, const acb_poly_t src) { int success; fmpz_poly_fit_length(res, src->length); success = _acb_vec_get_unique_fmpz_vec(res->coeffs, src->coeffs, src->length); _fmpz_poly_set_length(res, src->length); _fmpz_poly_normalise(res); return success; } flint-3.1.3/src/acb_poly/graeffe_transform.c000066400000000000000000000027451461254215100210600ustar00rootroot00000000000000/* Copyright (C) 2021 Matthias Gessinger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_graeffe_transform(acb_ptr b, acb_srcptr a, slong len, slong prec) { slong lo, le, ls, deg, i; acb_ptr pe, po; if (len <= 1) { if (len) acb_sqr(b, a, prec); return; } deg = len - 1; lo = len / 2; ls = 2 * lo - 1; le = deg / 2 + 1; po = _acb_vec_init(lo); pe = _acb_vec_init(FLINT_MAX(le, ls)); for (i = deg; i >= 0; i--) { if (i % 2 == 0) acb_set(pe + i / 2, a + i); else acb_set(po + i / 2, a + i); } _acb_poly_mul(b, pe, le, pe, le, prec); _acb_poly_mul(pe, po, lo, po, lo, prec); _acb_poly_sub(b + 1, b + 1, ls, pe, ls, prec); if (len % 2 == 0) { _acb_vec_neg(b, b, deg); acb_set(b + deg, pe + (deg - 1)); } _acb_vec_clear(pe, FLINT_MAX(le, ls)); _acb_vec_clear(po, lo); } void acb_poly_graeffe_transform(acb_poly_t b, const acb_poly_t a, slong prec) { acb_poly_fit_length(b, a->length); _acb_poly_graeffe_transform(b->coeffs, a->coeffs, a->length, prec); _acb_poly_set_length(b, a->length); } flint-3.1.3/src/acb_poly/init.c000066400000000000000000000011641461254215100163230ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_init(acb_poly_t poly) { poly->coeffs = NULL; poly->length = 0; poly->alloc = 0; } void acb_poly_init2(acb_poly_t poly, slong len) { acb_poly_init(poly); acb_poly_fit_length(poly, len); } flint-3.1.3/src/acb_poly/inlines.c000066400000000000000000000006601461254215100170210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ACB_POLY_INLINES_C #include "acb_poly.h" flint-3.1.3/src/acb_poly/integral.c000066400000000000000000000016021461254215100171620ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_integral(acb_ptr res, acb_srcptr poly, slong len, slong prec) { slong k = len - 1; for (k = len - 1; k > 0; k--) acb_div_ui(res + k, poly + k - 1, k, prec); acb_zero(res); } void acb_poly_integral(acb_poly_t res, const acb_poly_t poly, slong prec) { acb_poly_fit_length(res, poly->length + 1); _acb_poly_integral(res->coeffs, poly->coeffs, poly->length + 1, prec); _acb_poly_set_length(res, poly->length + 1); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/interpolate_barycentric.c000066400000000000000000000034161461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_interpolate_barycentric(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) { acb_ptr P, Q, w; acb_t t; slong i, j; if (n == 1) { acb_set(poly, ys); return; } P = _acb_vec_init(n + 1); Q = _acb_vec_init(n); w = _acb_vec_init(n); acb_init(t); _acb_poly_product_roots(P, xs, n, prec); for (i = 0; i < n; i++) { acb_one(w + i); for (j = 0; j < n; j++) { if (i != j) { acb_sub(t, xs + i, xs + j, prec); acb_mul(w + i, w + i, t, prec); } } acb_inv(w + i, w + i, prec); } _acb_vec_zero(poly, n); for (i = 0; i < n; i++) { _acb_poly_div_root(Q, t, P, n + 1, xs + i, prec); acb_mul(t, w + i, ys + i, prec); _acb_vec_scalar_addmul(poly, Q, n, t, prec); } _acb_vec_clear(P, n + 1); _acb_vec_clear(Q, n); _acb_vec_clear(w, n); acb_clear(t); } void acb_poly_interpolate_barycentric(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) { if (n == 0) { acb_poly_zero(poly); } else { acb_poly_fit_length(poly, n); _acb_poly_set_length(poly, n); _acb_poly_interpolate_barycentric(poly->coeffs, xs, ys, n, prec); _acb_poly_normalise(poly); } } flint-3.1.3/src/acb_poly/interpolate_fast.c000066400000000000000000000057511461254215100207310ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_interpolation_weights(acb_ptr w, acb_ptr * tree, slong len, slong prec) { acb_ptr tmp; slong i, n, height; if (len == 0) return; if (len == 1) { acb_one(w); return; } tmp = _acb_vec_init(len + 1); height = FLINT_CLOG2(len); n = WORD(1) << (height - 1); _acb_poly_mul_monic(tmp, tree[height-1], n + 1, tree[height-1] + (n + 1), (len - n + 1), prec); _acb_poly_derivative(tmp, tmp, len + 1, prec); _acb_poly_evaluate_vec_fast_precomp(w, tmp, len, tree, len, prec); for (i = 0; i < len; i++) acb_inv(w + i, w + i, prec); _acb_vec_clear(tmp, len + 1); } void _acb_poly_interpolate_fast_precomp(acb_ptr poly, acb_srcptr ys, acb_ptr * tree, acb_srcptr weights, slong len, slong prec) { acb_ptr t, u, pa, pb; slong i, pow, left; if (len == 0) return; t = _acb_vec_init(len); u = _acb_vec_init(len); for (i = 0; i < len; i++) acb_mul(poly + i, weights + i, ys + i, prec); for (i = 0; i < FLINT_CLOG2(len); i++) { pow = (WORD(1) << i); pa = tree[i]; pb = poly; left = len; while (left >= 2 * pow) { _acb_poly_mul(t, pa, pow + 1, pb + pow, pow, prec); _acb_poly_mul(u, pa + pow + 1, pow + 1, pb, pow, prec); _acb_vec_add(pb, t, u, 2 * pow, prec); left -= 2 * pow; pa += 2 * pow + 2; pb += 2 * pow; } if (left > pow) { _acb_poly_mul(t, pa, pow + 1, pb + pow, left - pow, prec); _acb_poly_mul(u, pb, pow, pa + pow + 1, left - pow + 1, prec); _acb_vec_add(pb, t, u, left, prec); } } _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void _acb_poly_interpolate_fast(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong len, slong prec) { acb_ptr * tree; acb_ptr w; tree = _acb_poly_tree_alloc(len); _acb_poly_tree_build(tree, xs, len, prec); w = _acb_vec_init(len); _acb_poly_interpolation_weights(w, tree, len, prec); _acb_poly_interpolate_fast_precomp(poly, ys, tree, w, len, prec); _acb_vec_clear(w, len); _acb_poly_tree_free(tree, len); } void acb_poly_interpolate_fast(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) { if (n == 0) { acb_poly_zero(poly); } else { acb_poly_fit_length(poly, n); _acb_poly_set_length(poly, n); _acb_poly_interpolate_fast(poly->coeffs, xs, ys, n, prec); _acb_poly_normalise(poly); } } flint-3.1.3/src/acb_poly/interpolate_newton.c000066400000000000000000000043211461254215100212760ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" static void _interpolate_newton(acb_ptr ys, acb_srcptr xs, slong n, slong prec) { acb_t p, q, t; slong i, j; acb_init(p); acb_init(q); acb_init(t); for (i = 1; i < n; i++) { acb_set(t, ys + i - 1); for (j = i; j < n; j++) { acb_sub(p, ys + j, t, prec); acb_sub(q, xs + j, xs + j - i, prec); acb_set(t, ys + j); acb_div(ys + j, p, q, prec); } } acb_clear(p); acb_clear(q); acb_clear(t); } static void _newton_to_monomial(acb_ptr ys, acb_srcptr xs, slong n, slong prec) { acb_t t, u; slong i, j; acb_init(t); acb_init(u); for (i = n - 2; i >= 0; i--) { acb_set(t, ys + i); acb_set(ys + i, ys + i + 1); for (j = i + 1; j < n - 1; j++) { acb_mul(u, ys + j, xs + i, prec); acb_sub(ys + j, ys + j + 1, u, prec); } acb_mul(u, ys + n - 1, xs + i, prec); acb_sub(ys + n - 1, t, u, prec); } _acb_poly_reverse(ys, ys, n, n); acb_clear(t); acb_clear(u); } void _acb_poly_interpolate_newton(acb_ptr poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) { if (n == 1) { acb_set(poly, ys); } else { _acb_vec_set(poly, ys, n); _interpolate_newton(poly, xs, n, prec); while (n > 0 && acb_is_zero(poly + n - 1)) n--; _newton_to_monomial(poly, xs, n, prec); } } void acb_poly_interpolate_newton(acb_poly_t poly, acb_srcptr xs, acb_srcptr ys, slong n, slong prec) { if (n == 0) { acb_poly_zero(poly); } else { acb_poly_fit_length(poly, n); _acb_poly_set_length(poly, n); _acb_poly_interpolate_newton(poly->coeffs, xs, ys, n, prec); _acb_poly_normalise(poly); } } flint-3.1.3/src/acb_poly/inv_borel_transform.c000066400000000000000000000017741461254215100214410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_inv_borel_transform(acb_ptr res, acb_srcptr poly, slong len, slong prec) { slong i; arb_t t; arb_init(t); arb_one(t); for (i = 0; i < len; i++) { if (i > 1) arb_mul_ui(t, t, i, prec); acb_mul_arb(res + i, poly + i, t, prec); } arb_clear(t); } void acb_poly_inv_borel_transform(acb_poly_t res, const acb_poly_t poly, slong prec) { acb_poly_fit_length(res, poly->length); _acb_poly_inv_borel_transform(res->coeffs, poly->coeffs, poly->length, prec); _acb_poly_set_length(res, poly->length); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/inv_series.c000066400000000000000000000055141461254215100175310ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" #define MULLOW(z, x, xn, y, yn, nn, prec) \ if ((xn) >= (yn)) \ _acb_poly_mullow(z, x, xn, y, yn, nn, prec); \ else \ _acb_poly_mullow(z, y, yn, x, xn, nn, prec); \ void _acb_poly_inv_series(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong len, slong prec) { Qlen = FLINT_MIN(Qlen, len); acb_inv(Qinv, Q, prec); if (Qlen == 1) { _acb_vec_zero(Qinv + 1, len - 1); } else if (len == 2) { acb_mul(Qinv + 1, Qinv, Qinv, prec); acb_mul(Qinv + 1, Qinv + 1, Q + 1, prec); acb_neg(Qinv + 1, Qinv + 1); } else { slong i, blen; /* The basecase algorithm is faster for much larger Qlen or len than this, but unfortunately also much less numerically stable. */ if (Qlen == 2 || len <= 8) blen = len; else blen = FLINT_MIN(len, 4); for (i = 1; i < blen; i++) { acb_dot(Qinv + i, NULL, 1, Q + 1, 1, Qinv + i - 1, -1, FLINT_MIN(i, Qlen - 1), prec); if (!acb_is_one(Qinv)) acb_mul(Qinv + i, Qinv + i, Qinv, prec); } if (len > blen) { slong Qnlen, Wlen, W2len; acb_ptr W; W = _acb_vec_init(len); NEWTON_INIT(blen, len) NEWTON_LOOP(m, n) Qnlen = FLINT_MIN(Qlen, n); Wlen = FLINT_MIN(Qnlen + m - 1, n); W2len = Wlen - m; MULLOW(W, Q, Qnlen, Qinv, m, Wlen, prec); MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m, prec); _acb_vec_neg(Qinv + m, Qinv + m, n - m); NEWTON_END_LOOP NEWTON_END _acb_vec_clear(W, len); } } } void acb_poly_inv_series(acb_poly_t Qinv, const acb_poly_t Q, slong n, slong prec) { if (n == 0) { acb_poly_zero(Qinv); return; } if (Q->length == 0) { acb_poly_fit_length(Qinv, n); _acb_vec_indeterminate(Qinv->coeffs, n); _acb_poly_set_length(Qinv, n); return; } if (Qinv == Q) { acb_poly_t t; acb_poly_init(t); acb_poly_inv_series(t, Q, n, prec); acb_poly_swap(Qinv, t); acb_poly_clear(t); return; } acb_poly_fit_length(Qinv, n); _acb_poly_inv_series(Qinv->coeffs, Q->coeffs, Q->length, n, prec); _acb_poly_set_length(Qinv, n); _acb_poly_normalise(Qinv); } flint-3.1.3/src/acb_poly/io.c000066400000000000000000000017161461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_poly.h" /* printing *******************************************************************/ void acb_poly_fprintd(FILE * file, const acb_poly_t poly, slong digits) { slong i; flint_fprintf(file, "["); for (i = 0; i < poly->length; i++) { acb_fprintd(file, poly->coeffs + i, digits); if (i + 1 < poly->length) flint_fprintf(file, "\n"); } flint_fprintf(file, "]"); } void acb_poly_printd(const acb_poly_t poly, slong digits) { acb_poly_fprintd(stdout, poly, digits); } flint-3.1.3/src/acb_poly/lambertw_series.c000066400000000000000000000045421461254215100205520ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void _acb_poly_lambertw_series(acb_ptr res, acb_srcptr z, slong zlen, const fmpz_t k, int flags, slong len, slong prec) { acb_ptr w, ew, t, u; acb_t ew0; zlen = FLINT_MIN(zlen, len); if (zlen == 1) { acb_lambertw(res, z, k, flags, prec); _acb_vec_zero(res + 1, len - 1); return; } w = _acb_vec_init(len); ew = _acb_vec_init(len); t = _acb_vec_init(len); u = _acb_vec_init(len); acb_init(ew0); acb_lambertw(w, z, k, flags, prec); if (acb_contains_zero(w)) acb_exp(ew0, w, prec); else acb_div(ew0, z, w, prec); acb_add(t, ew0, z, prec); acb_div(w + 1, z + 1, t, prec); NEWTON_INIT(2, len) NEWTON_LOOP(m, n) /* _acb_poly_exp_series(ew, w, m, n, prec); */ acb_zero(t); _acb_vec_set(t + 1, w + 1, m - 1); _acb_poly_exp_series(ew, t, m, n, prec); _acb_vec_scalar_mul(ew, ew, n, ew0, prec); _acb_poly_mullow(t, ew, n, w, m, n, prec); _acb_poly_sub(u, t, n, z, FLINT_MIN(zlen, n), prec); _acb_vec_add(t, t, ew, n, prec); _acb_poly_div_series(ew, u, n, t, n, n, prec); _acb_vec_neg(w + m, ew + m, n - m); NEWTON_END_LOOP NEWTON_END _acb_vec_set(res, w, len); _acb_vec_clear(w, len); _acb_vec_clear(ew, len); _acb_vec_clear(t, len); _acb_vec_clear(u, len); acb_clear(ew0); } void acb_poly_lambertw_series(acb_poly_t res, const acb_poly_t z, const fmpz_t k, int flags, slong len, slong prec) { if (len == 0 || (fmpz_is_zero(k) && z->length == 0)) { acb_poly_zero(res); return; } if (z->length == 0) { acb_poly_fit_length(res, len); _acb_vec_indeterminate(res->coeffs, len); _acb_poly_set_length(res, len); return; } acb_poly_fit_length(res, len); _acb_poly_lambertw_series(res->coeffs, z->coeffs, z->length, k, flags, len, prec); _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/lgamma_series.c000066400000000000000000000102721461254215100201700ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" #include "acb_hypgeom.h" void _acb_log_rising_correct_branch(acb_t t, const acb_t t_wrong, const acb_t z, ulong r, slong prec); void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t x, int use_reflect, int digamma, slong prec); void _acb_poly_gamma_stirling_eval(acb_ptr res, const acb_t z, slong n, slong num, slong prec); void _acb_poly_lgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong i, r, n, wp; acb_t zr; acb_ptr t, u; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_lgamma(res, h, prec); if (acb_is_finite(res)) _acb_vec_zero(res + 1, len - 1); else _acb_vec_indeterminate(res + 1, len - 1); return; } if (len == 2) { acb_t v; acb_init(v); acb_set(v, h + 1); acb_digamma(res + 1, h, prec); acb_lgamma(res, h, prec); acb_mul(res + 1, res + 1, v, prec); acb_clear(v); return; } /* use real code for real input and output */ if (_acb_vec_is_real(h, hlen) && arb_is_positive(acb_realref(h))) { arb_ptr tmp = _arb_vec_init(len); for (i = 0; i < hlen; i++) arb_set(tmp + i, acb_realref(h + i)); _arb_poly_lgamma_series(tmp, tmp, hlen, len, prec); for (i = 0; i < len; i++) acb_set_arb(res + i, tmp + i); _arb_vec_clear(tmp, len); return; } wp = prec + FLINT_BIT_COUNT(prec); t = _acb_vec_init(len); u = _acb_vec_init(len); acb_init(zr); /* use Stirling series */ acb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp); if (reflect) { /* log gamma(h+x) = log rf(1-(h+x), r) - log gamma(1-(h+x)+r) - log sin(pi (h+x)) + log(pi) */ if (r != 0) /* otherwise t = 0 */ { acb_sub_ui(u, h, 1, wp); acb_neg(u, u); acb_hypgeom_log_rising_ui_jet(t, u, r, len, wp); for (i = 1; i < len; i += 2) acb_neg(t + i, t + i); } acb_sub_ui(u, h, 1, wp); acb_neg(u, u); acb_add_ui(zr, u, r, wp); _acb_poly_gamma_stirling_eval(u, zr, n, len, wp); for (i = 1; i < len; i += 2) acb_neg(u + i, u + i); _acb_vec_sub(t, t, u, len, wp); /* log(sin) is unstable with large imaginary parts; cot_pi is implemented in a numerically stable way */ acb_set(u, h); acb_one(u + 1); _acb_poly_cot_pi_series(u, u, 2, len - 1, wp); _acb_poly_integral(u, u, len, wp); acb_const_pi(u, wp); _acb_vec_scalar_mul(u + 1, u + 1, len - 1, u, wp); acb_log_sin_pi(u, h, wp); _acb_vec_sub(u, t, u, len, wp); acb_const_pi(t, wp); /* todo: constant for log pi */ acb_log(t, t, wp); acb_add(u, u, t, wp); } else { /* log gamma(x) = log gamma(x+r) - log rf(x,r) */ acb_add_ui(zr, h, r, wp); _acb_poly_gamma_stirling_eval(u, zr, n, len, wp); if (r != 0) { acb_hypgeom_log_rising_ui_jet(t, h, r, len, wp); _acb_vec_sub(u, u, t, len, wp); } } /* compose with nonconstant part */ acb_zero(t); _acb_vec_set(t + 1, h + 1, hlen - 1); _acb_poly_compose_series(res, u, len, t, hlen, len, prec); acb_clear(zr); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void acb_poly_lgamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) { acb_poly_fit_length(res, n); if (f->length == 0 || n == 0) _acb_vec_indeterminate(res->coeffs, n); else _acb_poly_lgamma_series(res->coeffs, f->coeffs, f->length, n, prec); _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/log1p_series.c000066400000000000000000000021461461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" void _acb_poly_log1p_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); if (_gr_poly_log1p_series(res, f, flen, n, ctx) != GR_SUCCESS) _acb_vec_indeterminate(res, n); } void acb_poly_log1p_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) { slong flen = f->length; if (flen == 0 || n == 0) { acb_poly_zero(res); return; } if (flen == 1 /*&& !acb_contains_si(f->coeffs, -1)*/) n = 1; acb_poly_fit_length(res, n); _acb_poly_log1p_series(res->coeffs, f->coeffs, flen, n, prec); _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/log_series.c000066400000000000000000000021121461254215100175050ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" void _acb_poly_log_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); if (_gr_poly_log_series(res, f, flen, n, ctx) != GR_SUCCESS) _acb_vec_indeterminate(res, n); } void acb_poly_log_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) { if (n == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, n); if (f->length == 0) _acb_vec_indeterminate(res->coeffs, n); else _acb_poly_log_series(res->coeffs, f->coeffs, f->length, n, prec); _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/majorant.c000066400000000000000000000016161461254215100171750ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void _acb_poly_majorant(arb_ptr res, acb_srcptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { acb_get_abs_ubound_arf(arb_midref(res + i), vec + i, prec); mag_zero(arb_radref(res + i)); } } void acb_poly_majorant(arb_poly_t res, const acb_poly_t poly, slong prec) { arb_poly_fit_length(res, poly->length); _acb_poly_majorant(res->coeffs, poly->coeffs, poly->length, prec); _arb_poly_set_length(res, poly->length); } flint-3.1.3/src/acb_poly/mul.c000066400000000000000000000026601461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_mul(acb_ptr C, acb_srcptr A, slong lenA, acb_srcptr B, slong lenB, slong prec) { _acb_poly_mullow(C, A, lenA, B, lenB, lenA + lenB - 1, prec); } void acb_poly_mul(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { acb_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { acb_poly_t temp; acb_poly_init2(temp, len_out); _acb_poly_mul(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); acb_poly_swap(res, temp); acb_poly_clear(temp); } else { acb_poly_fit_length(res, len_out); _acb_poly_mul(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); } _acb_poly_set_length(res, len_out); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/mullow.c000066400000000000000000000076101461254215100167010ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif void _acb_poly_mullow(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { if (n == 1) { acb_mul(res, poly1, poly2, prec); } else if (n <= 7 || len1 <= 7 || len2 <= 7) { _acb_poly_mullow_classical(res, poly1, len1, poly2, len2, n, prec); } else { slong cutoff; double p; if (prec <= 2 * FLINT_BITS) { cutoff = 110; } else { p = log(prec); cutoff = 10000.0 / (p * p * p); cutoff = FLINT_MIN(cutoff, 60); if (poly1 == poly2 && prec >= 256) cutoff *= 1.25; if (poly1 == poly2 && prec >= 4096) cutoff *= 1.25; cutoff = FLINT_MAX(cutoff, 8); } if (2 * FLINT_MIN(len1, len2) <= cutoff || n <= cutoff) _acb_poly_mullow_classical(res, poly1, len1, poly2, len2, n, prec); else _acb_poly_mullow_transpose(res, poly1, len1, poly2, len2, n, prec); } } void acb_poly_mullow(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; if (len1 == 0 || len2 == 0 || n == 0) { acb_poly_zero(res); return; } n = FLINT_MIN((len1 + len2 - 1), n); len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); /* Hack to avoid temporary allocations with first derivatives. */ if (n <= 2 && !(len1 == 2 && len2 == 2)) { acb_poly_fit_length(res, n); if (n == 1) { acb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); } else if (len2 == 1) { acb_mul(res->coeffs + 1, poly1->coeffs + 1, poly2->coeffs, prec); acb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); } else if (len1 == 1) { acb_mul(res->coeffs + 1, poly2->coeffs + 1, poly1->coeffs, prec); acb_mul(res->coeffs, poly2->coeffs, poly1->coeffs, prec); } else { if (res == poly1 || res == poly2) { acb_t t; acb_init(t); acb_mul(t, poly1->coeffs, poly2->coeffs + 1, prec); acb_addmul(t, poly2->coeffs, poly1->coeffs + 1, prec); acb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); acb_swap(t, res->coeffs + 1); acb_clear(t); } else { acb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); acb_mul(res->coeffs + 1, poly1->coeffs, poly2->coeffs + 1, prec); acb_addmul(res->coeffs + 1, poly2->coeffs, poly1->coeffs + 1, prec); } } _acb_poly_set_length(res, n); _acb_poly_normalise(res); return; } if (res == poly1 || res == poly2) { acb_poly_t t; acb_poly_init2(t, n); _acb_poly_mullow(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); acb_poly_swap(res, t); acb_poly_clear(t); } else { acb_poly_fit_length(res, n); _acb_poly_mullow(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/mullow_classical.c000066400000000000000000000063401461254215100207160ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_mullow_classical(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) { acb_mul(res, poly1, poly2, prec); } else if (poly1 == poly2 && len1 == len2) { slong i, start, stop; acb_sqr(res, poly1, prec); acb_mul(res + 1, poly1, poly1 + 1, prec); acb_mul_2exp_si(res + 1, res + 1, 1); for (i = 2; i < FLINT_MIN(n, 2 * len1 - 3); i++) { start = FLINT_MAX(0, i - len1 + 1); stop = FLINT_MIN(len1 - 1, (i + 1) / 2 - 1); acb_dot(res + i, NULL, 0, poly1 + start, 1, poly1 + i - start, -1, stop - start + 1, prec); acb_mul_2exp_si(res + i, res + i, 1); if (i % 2 == 0 && i / 2 < len1) acb_addmul(res + i, poly1 + i / 2, poly1 + i / 2, prec); } if (len1 > 2 && n >= 2 * len1 - 2) { acb_mul(res + 2 * len1 - 3, poly1 + len1 - 1, poly1 + len1 - 2, prec); acb_mul_2exp_si(res + 2 * len1 - 3, res + 2 * len1 - 3, 1); } if (n >= 2 * len1 - 1) acb_sqr(res + 2 * len1 - 2, poly1 + len1 - 1, prec); } else if (len1 == 1) { _acb_vec_scalar_mul(res, poly2, n, poly1, prec); } else if (len2 == 1) { _acb_vec_scalar_mul(res, poly1, n, poly2, prec); } else { slong i, top1, top2; acb_mul(res, poly1, poly2, prec); for (i = 1; i < n; i++) { top1 = FLINT_MIN(len1 - 1, i); top2 = FLINT_MIN(len2 - 1, i); acb_dot(res + i, NULL, 0, poly1 + i - top2, 1, poly2 + top2, -1, top1 + top2 - i + 1, prec); } } } void acb_poly_mullow_classical(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec) { slong len_out; if (poly1->length == 0 || poly2->length == 0 || n == 0) { acb_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (n > len_out) n = len_out; if (res == poly1 || res == poly2) { acb_poly_t t; acb_poly_init2(t, n); _acb_poly_mullow_classical(t->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, prec); acb_poly_swap(res, t); acb_poly_clear(t); } else { acb_poly_fit_length(res, n); _acb_poly_mullow_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/mullow_transpose.c000066400000000000000000000055711461254215100210030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void _acb_poly_mullow_transpose(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { arb_ptr a, b, c, d, e, f, w; arb_ptr t; slong i; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + n))); a = w; b = a + len1; c = b + len1; d = c + len2; e = d + len2; f = e + n; /* (e+fi) = (a+bi)(c+di) = (ac - bd) + (ad + bc)i */ t = _arb_vec_init(n); for (i = 0; i < len1; i++) { a[i] = *acb_realref(poly1 + i); b[i] = *acb_imagref(poly1 + i); } for (i = 0; i < len2; i++) { c[i] = *acb_realref(poly2 + i); d[i] = *acb_imagref(poly2 + i); } for (i = 0; i < n; i++) { e[i] = *acb_realref(res + i); f[i] = *acb_imagref(res + i); } _arb_poly_mullow(e, a, len1, c, len2, n, prec); _arb_poly_mullow(t, b, len1, d, len2, n, prec); _arb_vec_sub(e, e, t, n, prec); _arb_poly_mullow(f, a, len1, d, len2, n, prec); /* squaring */ if (poly1 == poly2 && len1 == len2) { _arb_vec_scalar_mul_2exp_si(f, f, n, 1); } else { _arb_poly_mullow(t, b, len1, c, len2, n, prec); _arb_vec_add(f, f, t, n, prec); } for (i = 0; i < n; i++) { *acb_realref(res + i) = e[i]; *acb_imagref(res + i) = f[i]; } _arb_vec_clear(t, n); flint_free(w); } void acb_poly_mullow_transpose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; if (len1 == 0 || len2 == 0 || n == 0) { acb_poly_zero(res); return; } n = FLINT_MIN((len1 + len2 - 1), n); len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (res == poly1 || res == poly2) { acb_poly_t t; acb_poly_init2(t, n); _acb_poly_mullow_transpose(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); acb_poly_swap(res, t); acb_poly_clear(t); } else { acb_poly_fit_length(res, n); _acb_poly_mullow_transpose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/mullow_transpose_gauss.c000066400000000000000000000055611461254215100222040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void _acb_poly_mullow_transpose_gauss(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { arb_ptr a, b, c, d, e, f, w; arb_ptr t, u, v; slong i; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + n))); a = w; b = a + len1; c = b + len1; d = c + len2; e = d + len2; f = e + n; t = _arb_vec_init(n); u = _arb_vec_init(n); v = _arb_vec_init(n); for (i = 0; i < len1; i++) { a[i] = *acb_realref(poly1 + i); b[i] = *acb_imagref(poly1 + i); } for (i = 0; i < len2; i++) { c[i] = *acb_realref(poly2 + i); d[i] = *acb_imagref(poly2 + i); } for (i = 0; i < n; i++) { e[i] = *acb_realref(res + i); f[i] = *acb_imagref(res + i); } _arb_vec_add(t, a, b, len1, prec); _arb_vec_add(u, c, d, len2, prec); _arb_poly_mullow(v, t, len1, u, len2, n, prec); _arb_poly_mullow(t, a, len1, c, len2, n, prec); _arb_poly_mullow(u, b, len1, d, len2, n, prec); _arb_vec_sub(e, t, u, n, prec); _arb_vec_sub(f, v, t, n, prec); _arb_vec_sub(f, f, u, n, prec); for (i = 0; i < n; i++) { *acb_realref(res + i) = e[i]; *acb_imagref(res + i) = f[i]; } _arb_vec_clear(t, n); _arb_vec_clear(u, n); _arb_vec_clear(v, n); flint_free(w); } void acb_poly_mullow_transpose_gauss(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong n, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; if (len1 == 0 || len2 == 0 || n == 0) { acb_poly_zero(res); return; } n = FLINT_MIN((len1 + len2 - 1), n); len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (res == poly1 || res == poly2) { acb_poly_t t; acb_poly_init2(t, n); _acb_poly_mullow_transpose_gauss(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); acb_poly_swap(res, t); acb_poly_clear(t); } else { acb_poly_fit_length(res, n); _acb_poly_mullow_transpose_gauss(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/normalise.c000066400000000000000000000011051461254215100173440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_normalise(acb_poly_t poly) { slong i; for (i = poly->length - 1; (i >= 0) && acb_is_zero(poly->coeffs + i); i--); poly->length = i + 1; } flint-3.1.3/src/acb_poly/nth_derivative.c000066400000000000000000000024371461254215100203770ustar00rootroot00000000000000/* Copyright (C) 2023 Joel Dahne This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" void _acb_poly_nth_derivative(acb_ptr res, acb_srcptr poly, ulong n, slong len, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); if (_gr_poly_nth_derivative(res, poly, n, len, ctx) != GR_SUCCESS) _acb_vec_indeterminate(res, n); } void acb_poly_nth_derivative(acb_poly_t res, const acb_poly_t poly, ulong n, slong prec) { const slong len = poly->length; if (len <= n) { acb_poly_zero(res); } else if (n == 0) { acb_poly_set(res, poly); } else if (n == 1) { acb_poly_fit_length(res, len - 1); _acb_poly_derivative(res->coeffs, poly->coeffs, len, prec); _acb_poly_set_length(res, len - 1); } else { acb_poly_fit_length(res, len - n); _acb_poly_nth_derivative(res->coeffs, poly->coeffs, n, len, prec); _acb_poly_set_length(res, len - n); } } flint-3.1.3/src/acb_poly/overlaps.c000066400000000000000000000020411461254215100172060ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" int _acb_poly_overlaps(acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2) { slong i; for (i = 0; i < len2; i++) if (!acb_overlaps(poly1 + i, poly2 + i)) return 0; for (i = len2; i < len1; i++) if (!acb_contains_zero(poly1 + i)) return 0; return 1; } int acb_poly_overlaps(const acb_poly_t poly1, const acb_poly_t poly2) { slong len1 = poly1->length; slong len2 = poly2->length; if (len1 >= len2) return _acb_poly_overlaps(poly1->coeffs, len1, poly2->coeffs, len2); else return _acb_poly_overlaps(poly2->coeffs, len2, poly1->coeffs, len1); } flint-3.1.3/src/acb_poly/polylog_series.c000066400000000000000000000200131461254215100204110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_hypgeom.h" /* note: will not return a wrong value, as arf_get_si aborts on overflow */ slong arb_get_si_lower(const arb_t x) { arf_t t; slong v; arf_init(t); arf_set_mag(t, arb_radref(x)); arf_sub(t, arb_midref(x), t, 2 * FLINT_BITS, ARF_RND_FLOOR); v = arf_get_si(t, ARF_RND_FLOOR); arf_clear(t); return v; } slong polylog_choose_terms(mag_t err, slong sigma, const mag_t z, slong d, slong prec) { slong N; for (N = 3; ; N = FLINT_MAX(N+3, N*1.1)) { mag_polylog_tail(err, z, sigma, d, N); /* TODO: do something else when |Li_s(z)| is very small/very large? */ if (mag_cmp_2exp_si(err, -prec) < 0) break; if (N > 100 * prec) { N = 3; mag_inf(err); break; } } return N; } int polylog_is_real(const acb_t s, const acb_t z) { if (!arb_is_zero(acb_imagref(s))) return 0; else if (!arb_is_zero(acb_imagref(z))) return 0; else if (arb_contains_si(acb_realref(z), 1)) return 0; else if (acb_is_int(s) && arb_is_nonpositive(acb_realref(s))) return 1; else return (arf_cmp_2exp_si(arb_midref(acb_realref(z)), 0) < 0); } void _acb_poly_polylog_cpx_zeta(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec) { acb_ptr e1, e2, z1, z2, e1z1, e2z2; acb_t t, u, v; slong k, len2; int deflate_zeta, deflate_gamma, is_real; if (!acb_is_finite(s) || !acb_is_finite(z)) { _acb_vec_indeterminate(w, len); return; } if (acb_is_one(z)) { if (arb_gt(acb_realref(s), acb_realref(z))) /* Re(s) > 1 */ { acb_zeta(w, s, prec); _acb_vec_indeterminate(w + 1, len - 1); } else { _acb_vec_indeterminate(w, len); } return; } is_real = polylog_is_real(s, z); acb_init(t); acb_init(u); acb_init(v); /* v = 1-s */ acb_one(v); acb_sub(v, v, s, prec); /* pole of zeta */ deflate_zeta = acb_is_one(v); /* poles of gamma at nonpositive integer v */ deflate_gamma = (arb_is_zero(acb_imagref(v)) && arb_is_int(acb_realref(v)) && arf_sgn(arb_midref(acb_realref(v))) <= 0); len2 = len + deflate_gamma; e1 = _acb_vec_init(len + 1); e2 = _acb_vec_init(len + 1); z1 = _acb_vec_init(len + 1); z2 = _acb_vec_init(len + 1); e1z1 = _acb_vec_init(len + 1); e2z2 = _acb_vec_init(len + 1); /* u = log(-z)/(pi*i) */ acb_neg(t, z); acb_log(t, t, prec); acb_const_pi(u, prec); acb_mul_onei(u, u); acb_div(u, t, u, prec); /* z1 = zeta(v+x, 1/2 + log(-z)/(2*pi*i)) */ acb_one(t); acb_add(t, t, u, prec); acb_mul_2exp_si(t, t, -1); _acb_poly_zeta_cpx_series(z1, v, t, deflate_zeta, len2, prec); /* z2 = zeta(v+x, 1/2 - log(-z)/(2*pi*i)) */ acb_one(t); acb_sub(t, t, u, prec); acb_mul_2exp_si(t, t, -1); _acb_poly_zeta_cpx_series(z2, v, t, deflate_zeta, len2, prec); /* e1 = (i/(2pi))^(v+x) */ acb_onei(t); acb_const_pi(u, prec); acb_div(t, t, u, prec); acb_mul_2exp_si(t, t, -1); _acb_poly_acb_pow_cpx(e1, t, v, len + (deflate_zeta || deflate_gamma), prec); /* e2 = (1/(2 pi i))^(v+x) */ acb_conj(t, t); _acb_poly_acb_pow_cpx(e2, t, v, len + (deflate_zeta || deflate_gamma), prec); _acb_poly_mullow(e1z1, e1, len2, z1, len2, len2, prec); _acb_poly_mullow(e2z2, e2, len2, z2, len2, len2, prec); _acb_vec_add(z1, e1z1, e2z2, len2, prec); if (deflate_gamma) { /* gamma(v+x) = pi/sin(pi(v+x)) * 1/gamma(1-v-x) */ /* TODO: write a csc function? */ acb_zero(e1); acb_const_pi(e1 + 1, prec); acb_mul_2exp_si(e2, v, -1); if (!arb_is_int(acb_realref(e2))) acb_neg(e1 + 1, e1 + 1); _acb_poly_sin_series(e2, e1, 2, len2, prec); _acb_poly_inv_series(e1, e2 + 1, len, len, prec); acb_const_pi(e2, prec); _acb_vec_scalar_mul(e1, e1, len, e2, prec); acb_set(z2, s); acb_set_si(z2 + 1, -1); _acb_poly_rgamma_series(e2, z2, 2, len, prec); _acb_poly_mullow(z2, e1, len, e2, len, len, prec); _acb_poly_mullow(w, z1 + 1, len, z2, len, len, prec); } else { if (deflate_zeta) { for (k = 0; k < len; k++) { arb_mul_2exp_si(acb_realref(e1 + k + 1), acb_realref(e1 + k + 1), 1); arb_add(acb_realref(z1 + k), acb_realref(z1 + k), acb_realref(e1 + k + 1), prec); } } /* gamma(v+x) */ acb_set(e1, v); if (len > 1) acb_one(e1 + 1); _acb_poly_gamma_series(z2, e1, FLINT_MIN(len, 2), len, prec); _acb_poly_mullow(w, z2, len, z1, len, len, prec); } /* correct signs (from s -> 1-s) */ for (k = 1; k < len; k += 2) acb_neg(w + k, w + k); if (is_real) if (acb_is_finite(w)) arb_zero(acb_imagref(w)); _acb_vec_clear(e1, len + 1); _acb_vec_clear(e2, len + 1); _acb_vec_clear(z1, len + 1); _acb_vec_clear(z2, len + 1); _acb_vec_clear(e1z1, len + 1); _acb_vec_clear(e2z2, len + 1); acb_clear(t); acb_clear(u); acb_clear(v); } void _acb_poly_polylog_cpx_small(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec) { slong k, N, sigma; int is_real; mag_t zmag, err, errf; acb_t a; acb_init(a); mag_init(zmag); mag_init(err); mag_init(errf); is_real = polylog_is_real(s, z); acb_get_mag(zmag, z); sigma = arb_get_si_lower(acb_realref(s)); N = polylog_choose_terms(err, sigma, zmag, len - 1, prec); /* TODO: allow threading */ acb_one(a); _acb_poly_powsum_series_naive(w, s, a, z, N - 1, len, prec); _acb_vec_scalar_mul(w, w, len, z, prec); for (k = 0; k < len; k++) { mag_polylog_tail(err, zmag, sigma, k, N); mag_rfac_ui(errf, k); mag_mul(err, err, errf); if (is_real && mag_is_finite(err)) arb_add_error_mag(acb_realref(w + k), err); else acb_add_error_mag(w + k, err); } acb_clear(a); mag_clear(zmag); mag_clear(err); mag_clear(errf); } void _acb_poly_polylog_cpx(acb_ptr w, const acb_t s, const acb_t z, slong len, slong prec) { mag_t zmag; if (len == 1 && acb_equal_si(s, 2)) { acb_hypgeom_dilog(w, z, prec); return; } mag_init(zmag); acb_get_mag(zmag, z); if (mag_cmp_2exp_si(zmag, -1) < 0) _acb_poly_polylog_cpx_small(w, s, z, len, prec); else _acb_poly_polylog_cpx_zeta(w, s, z, len, prec); mag_clear(zmag); } void _acb_poly_polylog_series(acb_ptr res, acb_srcptr s, slong slen, const acb_t z, slong len, slong prec) { acb_ptr t, u; slen = FLINT_MIN(slen, len); t = _acb_vec_init(len); u = _acb_vec_init(len); _acb_poly_polylog_cpx(t, s, z, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, s + 1, slen - 1); _acb_poly_compose_series(res, t, len, u, slen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void acb_poly_polylog_series(acb_poly_t res, const acb_poly_t s, const acb_t z, slong n, slong prec) { if (n == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, n); if (s->length == 0) { acb_t t; acb_init(t); _acb_poly_polylog_series(res->coeffs, t, 1, z, n, prec); acb_clear(t); } else { _acb_poly_polylog_series(res->coeffs, s->coeffs, s->length, z, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/pow_acb_series.c000066400000000000000000000074751461254215100203570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" /* (a + bx^c)^g where a = f[0] and b = f[flen-1] */ void _acb_poly_binomial_pow_acb_series(acb_ptr h, acb_srcptr f, slong flen, const acb_t g, slong len, slong prec) { slong i, j, d; acb_t t; acb_init(t); d = flen - 1; acb_pow(h, f, g, prec); acb_div(t, f + d, f, prec); for (i = 1, j = d; j < len; i++, j += d) { acb_sub_ui(h + j, g, i - 1, prec); acb_mul(h + j, h + j, h + j - d, prec); acb_mul(h + j, h + j, t, prec); acb_div_ui(h + j, h + j, i, prec); } if (d > 1) { for (i = 1; i < len; i++) if (i % d != 0) acb_zero(h + i); } acb_clear(t); return; } void _acb_poly_pow_acb_series(acb_ptr h, acb_srcptr f, slong flen, const acb_t g, slong len, slong prec) { int f_binomial, g_exact, g_int; while (flen > 0 && acb_is_zero(f + flen - 1)) flen--; if (flen <= 1) { acb_pow(h, f, g, prec); _acb_vec_zero(h + 1, len - 1); return; } g_exact = acb_is_exact(g); g_int = acb_is_real(g) && arb_is_int(acb_realref(g)); f_binomial = _acb_vec_is_zero(f + 1, flen - 2); /* g = small integer */ if (g_exact && g_int && arf_cmpabs_2exp_si(arb_midref(acb_realref(g)), FLINT_BITS - 1) < 0) { slong e, hlen; e = arf_get_si(arb_midref(acb_realref(g)), ARF_RND_DOWN); hlen = poly_pow_length(flen, FLINT_ABS(e), len); if (e >= 0) { _acb_poly_pow_ui_trunc_binexp(h, f, flen, e, hlen, prec); _acb_vec_zero(h + hlen, len - hlen); return; } else if (!f_binomial) { acb_ptr t; t = _acb_vec_init(hlen); _acb_poly_pow_ui_trunc_binexp(t, f, flen, -e, hlen, prec); _acb_poly_inv_series(h, t, hlen, len, prec); _acb_vec_clear(t, hlen); return; } } /* (a + bx^c)^g */ if (f_binomial) { _acb_poly_binomial_pow_acb_series(h, f, flen, g, len, prec); return; } /* g = +/- 1/2 */ if (g_exact && acb_is_real(g) && arf_cmpabs_2exp_si(arb_midref(acb_realref(g)), -1) == 0) { if (arf_sgn(arb_midref(acb_realref(g))) > 0) _acb_poly_sqrt_series(h, f, flen, len, prec); else _acb_poly_rsqrt_series(h, f, flen, len, prec); return; } /* f^g = exp(g*log(f)) */ _acb_poly_log_series(h, f, flen, len, prec); _acb_vec_scalar_mul(h, h, len, g, prec); _acb_poly_exp_series(h, h, len, len, prec); } void acb_poly_pow_acb_series(acb_poly_t h, const acb_poly_t f, const acb_t g, slong len, slong prec) { slong flen; flen = f->length; flen = FLINT_MIN(flen, len); if (len == 0) { acb_poly_zero(h); return; } if (acb_is_zero(g)) { acb_poly_one(h); return; } if (flen == 0) { acb_poly_zero(h); return; } if (f == h) { acb_poly_t t; acb_poly_init2(t, len); _acb_poly_pow_acb_series(t->coeffs, f->coeffs, flen, g, len, prec); _acb_poly_set_length(t, len); _acb_poly_normalise(t); acb_poly_swap(t, h); acb_poly_clear(t); } else { acb_poly_fit_length(h, len); _acb_poly_pow_acb_series(h->coeffs, f->coeffs, flen, g, len, prec); _acb_poly_set_length(h, len); _acb_poly_normalise(h); } } flint-3.1.3/src/acb_poly/pow_series.c000066400000000000000000000045241461254215100175420ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_pow_series(acb_ptr h, acb_srcptr f, slong flen, acb_srcptr g, slong glen, slong len, slong prec) { if (glen == 1) { _acb_poly_pow_acb_series(h, f, flen, g, len, prec); return; } /* f^g = exp(g * log(f)) */ if (flen == 1) { acb_t t; acb_init(t); acb_log(t, f, prec); _acb_vec_scalar_mul(h, g, glen, t, prec); _acb_poly_exp_series(h, h, glen, len, prec); acb_clear(t); } else { acb_ptr t; t = _acb_vec_init(len); _acb_poly_log_series(t, f, flen, len, prec); _acb_poly_mullow(h, t, len, g, glen, len, prec); _acb_poly_exp_series(h, h, len, len, prec); _acb_vec_clear(t, len); } } void acb_poly_pow_series(acb_poly_t h, const acb_poly_t f, const acb_poly_t g, slong len, slong prec) { slong flen, glen; flen = f->length; glen = g->length; flen = FLINT_MIN(flen, len); glen = FLINT_MIN(glen, len); if (len == 0) { acb_poly_zero(h); return; } if (glen == 0) { acb_poly_one(h); return; } if (flen == 0) { acb_poly_zero(h); return; } if (flen == 1 && glen == 1) { acb_poly_fit_length(h, 1); acb_pow(h->coeffs, f->coeffs, g->coeffs, prec); _acb_poly_set_length(h, 1); _acb_poly_normalise(h); return; } if (f == h || g == h) { acb_poly_t t; acb_poly_init2(t, len); _acb_poly_pow_series(t->coeffs, f->coeffs, flen, g->coeffs, glen, len, prec); _acb_poly_set_length(t, len); _acb_poly_normalise(t); acb_poly_swap(t, h); acb_poly_clear(t); } else { acb_poly_fit_length(h, len); _acb_poly_pow_series(h->coeffs, f->coeffs, flen, g->coeffs, glen, len, prec); _acb_poly_set_length(h, len); _acb_poly_normalise(h); } } flint-3.1.3/src/acb_poly/pow_ui.c000066400000000000000000000027201461254215100166610ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_pow_ui(acb_ptr res, acb_srcptr f, slong flen, ulong exp, slong prec) { _acb_poly_pow_ui_trunc_binexp(res, f, flen, exp, exp * (flen - 1) + 1, prec); } void acb_poly_pow_ui(acb_poly_t res, const acb_poly_t poly, ulong exp, slong prec) { slong flen, rlen; flen = poly->length; if (exp == 0) { acb_poly_one(res); } else if (flen == 0) { acb_poly_zero(res); } else { rlen = exp * (flen - 1) + 1; if (res != poly) { acb_poly_fit_length(res, rlen); _acb_poly_pow_ui(res->coeffs, poly->coeffs, flen, exp, prec); _acb_poly_set_length(res, rlen); _acb_poly_normalise(res); } else { acb_poly_t t; acb_poly_init2(t, rlen); _acb_poly_pow_ui(t->coeffs, poly->coeffs, flen, exp, prec); _acb_poly_set_length(t, rlen); _acb_poly_normalise(t); acb_poly_swap(res, t); acb_poly_clear(t); } } } flint-3.1.3/src/acb_poly/pow_ui_trunc_binexp.c000066400000000000000000000040341461254215100214410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" #include "gr_poly.h" void _acb_poly_pow_ui_trunc_binexp(acb_ptr res, acb_srcptr f, slong flen, ulong exp, slong len, slong prec) { if (exp <= 2) { if (exp == 0) acb_one(res); else if (exp == 1) _acb_vec_set_round(res, f, len, prec); else _acb_poly_mullow(res, f, flen, f, flen, len, prec); } else if (!_acb_vec_is_finite(f, flen)) { _acb_vec_indeterminate(res, len); } else { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); GR_MUST_SUCCEED(_gr_poly_pow_series_ui_binexp(res, f, flen, exp, len, ctx)); } } void acb_poly_pow_ui_trunc_binexp(acb_poly_t res, const acb_poly_t poly, ulong exp, slong len, slong prec) { slong flen, rlen; flen = poly->length; if (exp == 0 && len != 0) { acb_poly_one(res); } else if (flen == 0 || len == 0) { acb_poly_zero(res); } else { rlen = poly_pow_length(flen, exp, len); if (res != poly) { acb_poly_fit_length(res, rlen); _acb_poly_pow_ui_trunc_binexp(res->coeffs, poly->coeffs, flen, exp, rlen, prec); _acb_poly_set_length(res, rlen); _acb_poly_normalise(res); } else { acb_poly_t t; acb_poly_init2(t, rlen); _acb_poly_pow_ui_trunc_binexp(t->coeffs, poly->coeffs, flen, exp, rlen, prec); _acb_poly_set_length(t, rlen); _acb_poly_normalise(t); acb_poly_swap(res, t); acb_poly_clear(t); } } } flint-3.1.3/src/acb_poly/powsum_one_series_sieved.c000066400000000000000000000011211461254215100224550ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" void _acb_poly_powsum_one_series_sieved(acb_ptr z, const acb_t s, slong n, slong len, slong prec) { acb_dirichlet_powsum_sieved(z, s, n, len, prec); } flint-3.1.3/src/acb_poly/powsum_series_naive.c000066400000000000000000000043131461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_acb_invpow_cpx(acb_ptr res, const acb_t N, const acb_t c, slong trunc, slong prec) { slong i; acb_t logN; acb_init(logN); acb_log(logN, N, prec); acb_mul(res + 0, logN, c, prec); acb_neg(res + 0, res + 0); acb_exp(res + 0, res + 0, prec); for (i = 1; i < trunc; i++) { acb_mul(res + i, res + i - 1, logN, prec); acb_div_si(res + i, res + i, -i, prec); } acb_clear(logN); } void _acb_poly_powsum_series_naive(acb_ptr z, const acb_t s, const acb_t a, const acb_t q, slong n, slong len, slong prec) { slong k, i; int q_one, s_int; acb_t ak, logak, t, qpow, negs; acb_init(ak); acb_init(logak); acb_init(t); acb_init(qpow); acb_init(negs); _acb_vec_zero(z, len); acb_one(qpow); acb_neg(negs, s); q_one = acb_is_one(q); s_int = arb_is_int(acb_realref(s)) && arb_is_zero(acb_imagref(s)); for (k = 0; k < n; k++) { acb_add_ui(ak, a, k, prec); if (len == 1) { acb_pow(t, ak, negs, prec); } else { acb_log(logak, ak, prec); if (s_int) { acb_pow(t, ak, negs, prec); } else { acb_mul(t, logak, negs, prec); acb_exp(t, t, prec); } } if (!q_one) { acb_mul(t, t, qpow, prec); if (k < n - 1) acb_mul(qpow, qpow, q, prec); } acb_add(z, z, t, prec); for (i = 1; i < len; i++) { acb_mul(t, t, logak, prec); acb_div_si(t, t, -i, prec); acb_add(z + i, z + i, t, prec); } } acb_clear(ak); acb_clear(logak); acb_clear(t); acb_clear(qpow); acb_clear(negs); } flint-3.1.3/src/acb_poly/powsum_series_naive_threaded.c000066400000000000000000000110461461254215100233060ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "acb_poly.h" typedef struct { acb_ptr z; acb_srcptr s; acb_srcptr a; acb_srcptr q; slong n0; slong n1; slong d0; slong len; slong prec; } _worker_arg; void _acb_zeta_powsum_evaluator(void * arg_ptr) { _worker_arg arg = *((_worker_arg *) arg_ptr); slong i, k; int q_one, s_int; acb_t t, u, v, ak, qpow, negs; arb_t f; acb_init(t); acb_init(u); acb_init(v); acb_init(ak); acb_init(qpow); acb_init(negs); arb_init(f); _acb_vec_zero(arg.z, arg.len); q_one = acb_is_one(arg.q); s_int = arb_is_int(acb_realref(arg.s)) && arb_is_zero(acb_imagref(arg.s)); if (!q_one) acb_pow_ui(qpow, arg.q, arg.n0, arg.prec); acb_neg(negs, arg.s); arb_fac_ui(f, arg.d0, arg.prec); for (k = arg.n0; k < arg.n1; k++) { acb_add_ui(ak, arg.a, k, arg.prec); if (arg.d0 == 0 && arg.len == 1) { /* u = (a+k)^(-s) */ acb_pow(u, ak, negs, arg.prec); } else { /* t = log(a+k) */ acb_log(t, ak, arg.prec); /* u = (a+k)^(-s) */ if (s_int) { acb_pow(u, ak, negs, arg.prec); } else { acb_mul(u, t, negs, arg.prec); acb_exp(u, u, arg.prec); } } /* u = u * q^k */ if (!q_one) { acb_mul(u, u, qpow, arg.prec); if (k < arg.n1 - 1) acb_mul(qpow, qpow, arg.q, arg.prec); } /* forward: u *= (-1)^d * log(a+k)^d / d! */ if (arg.d0 != 0) { acb_pow_ui(v, t, arg.d0, arg.prec); acb_mul(u, u, v, arg.prec); arb_div(acb_realref(u), acb_realref(u), f, arg.prec); arb_div(acb_imagref(u), acb_imagref(u), f, arg.prec); if (arg.d0 % 2) acb_neg(u, u); } acb_add(arg.z, arg.z, u, arg.prec); for (i = 1; i < arg.len; i++) { acb_mul(u, u, t, arg.prec); acb_div_si(u, u, -(arg.d0 + i), arg.prec); acb_add(arg.z + i, arg.z + i, u, arg.prec); } } acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(ak); acb_clear(qpow); acb_clear(negs); arb_clear(f); flint_cleanup(); return; } void _acb_poly_powsum_series_naive_threaded(acb_ptr z, const acb_t s, const acb_t a, const acb_t q, slong n, slong len, slong prec) { thread_pool_handle * handles; _worker_arg * args; slong i, num_threads, num_workers; int split_each_term; split_each_term = (len > 1000); num_workers = flint_request_threads(&handles, split_each_term ? len : n); num_threads = num_workers + 1; args = FLINT_ARRAY_ALLOC(num_threads, _worker_arg); for (i = 0; i < num_threads; i++) { args[i].s = s; args[i].a = a; args[i].q = q; if (split_each_term) { slong n0, n1; n0 = (len * i) / num_threads; n1 = (len * (i + 1)) / num_threads; args[i].z = z + n0; args[i].n0 = 0; args[i].n1 = n; args[i].d0 = n0; args[i].len = n1 - n0; } else { args[i].z = _acb_vec_init(len); args[i].n0 = (n * i) / num_threads; args[i].n1 = (n * (i + 1)) / num_threads; args[i].d0 = 0; args[i].len = len; } args[i].prec = prec; if (i < num_workers) thread_pool_wake(global_thread_pool, handles[i], 0, _acb_zeta_powsum_evaluator, &args[i]); else _acb_zeta_powsum_evaluator(&args[i]); } for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); if (!split_each_term) { _acb_vec_zero(z, len); for (i = 0; i < num_threads; i++) { _acb_vec_add(z, z, args[i].z, len, prec); _acb_vec_clear(args[i].z, len); } } flint_give_back_threads(handles, num_workers); flint_free(args); } flint-3.1.3/src/acb_poly/product_roots.c000066400000000000000000000033761461254215100202750ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_product_roots(acb_ptr poly, acb_srcptr xs, slong n, slong prec) { if (n == 0) { acb_one(poly); } else if (n == 1) { acb_neg(poly, xs); acb_one(poly + 1); } else if (n == 2) { acb_mul(poly, xs + 0, xs + 1, prec); acb_add(poly + 1, xs + 0, xs + 1, prec); acb_neg(poly + 1, poly + 1); acb_one(poly + 2); } else if (n == 3) { acb_mul(poly + 1, xs, xs + 1, prec); acb_mul(poly, poly + 1, xs + 2, prec); acb_neg(poly, poly); acb_add(poly + 2, xs, xs + 1, prec); acb_addmul(poly + 1, poly + 2, xs + 2, prec); acb_add(poly + 2, poly + 2, xs + 2, prec); acb_neg(poly + 2, poly + 2); acb_one(poly + 3); } else { const slong m = (n + 1) / 2; acb_ptr tmp; tmp = _acb_vec_init(n + 2); _acb_poly_product_roots(tmp, xs, m, prec); _acb_poly_product_roots(tmp + m + 1, xs + m, n - m, prec); _acb_poly_mul_monic(poly, tmp, m + 1, tmp + m + 1, n - m + 1, prec); _acb_vec_clear(tmp, n + 2); } } void acb_poly_product_roots(acb_poly_t poly, acb_srcptr xs, slong n, slong prec) { acb_poly_fit_length(poly, n + 1); _acb_poly_product_roots(poly->coeffs, xs, n, prec); _acb_poly_set_length(poly, n + 1); } flint-3.1.3/src/acb_poly/randtest.c000066400000000000000000000021571461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_randtest(acb_poly_t poly, flint_rand_t state, slong len, slong prec, slong mag_bits) { slong i; acb_poly_fit_length(poly, len); if (n_randint(state, 2)) { for (i = 0; i < len; i++) { arb_randtest(acb_realref(poly->coeffs + i), state, prec, mag_bits); arb_randtest(acb_imagref(poly->coeffs + i), state, prec, mag_bits); } } else { for (i = 0; i < len; i++) { arb_randtest_precise(acb_realref(poly->coeffs + i), state, prec, mag_bits); arb_randtest_precise(acb_imagref(poly->coeffs + i), state, prec, mag_bits); } } _acb_poly_set_length(poly, len); _acb_poly_normalise(poly); } flint-3.1.3/src/acb_poly/refine_roots_durand_kerner.c000066400000000000000000000073551461254215100227710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" /* we don't need any error bounding, so we define a few helper functions that ignore the radii */ static inline void acb_sub_mid(acb_t z, const acb_t x, const acb_t y, slong prec) { arf_sub(arb_midref(acb_realref(z)), arb_midref(acb_realref(x)), arb_midref(acb_realref(y)), prec, ARF_RND_DOWN); arf_sub(arb_midref(acb_imagref(z)), arb_midref(acb_imagref(x)), arb_midref(acb_imagref(y)), prec, ARF_RND_DOWN); } static inline void acb_add_mid(acb_t z, const acb_t x, const acb_t y, slong prec) { arf_add(arb_midref(acb_realref(z)), arb_midref(acb_realref(x)), arb_midref(acb_realref(y)), prec, ARF_RND_DOWN); arf_add(arb_midref(acb_imagref(z)), arb_midref(acb_imagref(x)), arb_midref(acb_imagref(y)), prec, ARF_RND_DOWN); } static inline void acb_mul_mid(acb_t z, const acb_t x, const acb_t y, slong prec) { #define a arb_midref(acb_realref(x)) #define b arb_midref(acb_imagref(x)) #define c arb_midref(acb_realref(y)) #define d arb_midref(acb_imagref(y)) #define e arb_midref(acb_realref(z)) #define f arb_midref(acb_imagref(z)) arf_complex_mul(e, f, a, b, c, d, prec, ARF_RND_DOWN); #undef a #undef b #undef c #undef d #undef e #undef f } static inline void acb_inv_mid(acb_t z, const acb_t x, slong prec) { arf_t t; arf_init(t); #define a arb_midref(acb_realref(x)) #define b arb_midref(acb_imagref(x)) #define e arb_midref(acb_realref(z)) #define f arb_midref(acb_imagref(z)) arf_mul(t, a, a, prec, ARF_RND_DOWN); arf_addmul(t, b, b, prec, ARF_RND_DOWN); arf_div(e, a, t, prec, ARF_RND_DOWN); arf_div(f, b, t, prec, ARF_RND_DOWN); arf_neg(f, f); #undef a #undef b #undef e #undef f arf_clear(t); } void _acb_poly_evaluate_mid(acb_t res, acb_srcptr f, slong len, const acb_t a, slong prec) { slong i = len - 1; acb_t t; acb_init(t); acb_set(res, f + i); for (i = len - 2; i >= 0; i--) { acb_mul_mid(t, res, a, prec); acb_add_mid(res, f + i, t, prec); } acb_clear(t); } void _acb_poly_refine_roots_durand_kerner(acb_ptr roots, acb_srcptr poly, slong len, slong prec) { slong i, j; acb_t x, y, t; acb_init(x); acb_init(y); acb_init(t); for (i = 0; i < len - 1; i++) { _acb_poly_evaluate_mid(x, poly, len, roots + i, prec); acb_set(y, poly + len - 1); for (j = 0; j < len - 1; j++) { if (i != j) { acb_sub_mid(t, roots + i, roots + j, prec); acb_mul_mid(y, y, t, prec); } } mag_zero(arb_radref(acb_realref(y))); mag_zero(arb_radref(acb_imagref(y))); /* In the extremely unlikely event that y = 0, don't divide by 0. */ if (arf_is_zero(arb_midref(acb_realref(y))) && arf_is_zero(arb_midref(acb_imagref(y)))) { arf_set_ui_2exp_si(arb_midref(acb_realref(y)), 1, -prec); arf_set_ui_2exp_si(arb_midref(acb_imagref(y)), 1, -prec); } acb_inv_mid(t, y, prec); acb_mul_mid(t, t, x, prec); acb_sub_mid(roots + i, roots + i, t, prec); arf_get_mag(arb_radref(acb_realref(roots + i)), arb_midref(acb_realref(t))); arf_get_mag(arb_radref(acb_imagref(roots + i)), arb_midref(acb_imagref(t))); } acb_clear(x); acb_clear(y); acb_clear(t); } flint-3.1.3/src/acb_poly/reverse.c000066400000000000000000000017131461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_reverse(acb_ptr res, acb_srcptr poly, slong len, slong n) { if (res == poly) { slong i; for (i = 0; i < n / 2; i++) { acb_struct t = res[i]; res[i] = res[n - 1 - i]; res[n - 1 - i] = t; } for (i = 0; i < n - len; i++) acb_zero(res + i); } else { slong i; for (i = 0; i < n - len; i++) acb_zero(res + i); for (i = 0; i < len; i++) acb_set(res + (n - len) + i, poly + (len - 1) - i); } } flint-3.1.3/src/acb_poly/revert_series.c000066400000000000000000000027631461254215100202470ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" #include "acb_poly.h" void _acb_poly_revert_series(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); if (_gr_poly_revert_series(Qinv, Q, Qlen, n, ctx) != GR_SUCCESS) _acb_vec_indeterminate(Qinv, n); } void acb_poly_revert_series(acb_poly_t Qinv, const acb_poly_t Q, slong n, slong prec) { slong Qlen = Q->length; if (Qlen < 2 || !acb_is_zero(Q->coeffs) || acb_contains_zero(Q->coeffs + 1)) { flint_throw(FLINT_ERROR, "(acb_poly_revert_series): Input must \n" "have zero constant term and nonzero coefficient of x^1.\n"); } if (Qinv != Q) { acb_poly_fit_length(Qinv, n); _acb_poly_revert_series(Qinv->coeffs, Q->coeffs, Qlen, n, prec); } else { acb_poly_t t; acb_poly_init2(t, n); _acb_poly_revert_series(t->coeffs, Q->coeffs, Qlen, n, prec); acb_poly_swap(Qinv, t); acb_poly_clear(t); } _acb_poly_set_length(Qinv, n); _acb_poly_normalise(Qinv); } flint-3.1.3/src/acb_poly/rgamma_series.c000066400000000000000000000104661461254215100202030ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t x, int use_reflect, int digamma, slong prec); void _acb_poly_gamma_stirling_eval(acb_ptr res, const acb_t z, slong n, slong num, slong prec); void _acb_poly_rgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong i, rflen, r, n, wp; acb_ptr t, u, v; acb_struct f[2]; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_rgamma(res, h, prec); _acb_vec_zero(res + 1, len - 1); return; } /* use real code for real input */ if (_acb_vec_is_real(h, hlen)) { arb_ptr tmp = _arb_vec_init(len); for (i = 0; i < hlen; i++) arb_set(tmp + i, acb_realref(h + i)); _arb_poly_rgamma_series(tmp, tmp, hlen, len, prec); for (i = 0; i < len; i++) acb_set_arb(res + i, tmp + i); _arb_vec_clear(tmp, len); return; } wp = prec + FLINT_BIT_COUNT(prec); t = _acb_vec_init(len); u = _acb_vec_init(len); v = _acb_vec_init(len); acb_init(f); acb_init(f + 1); /* otherwise use Stirling series */ acb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp); /* rgamma(h) = (gamma(1-h+r) sin(pi h)) / (rf(1-h, r) * pi), h = h0 + t*/ if (reflect) { /* u = gamma(r+1-h) */ acb_sub_ui(f, h, r + 1, wp); acb_neg(f, f); _acb_poly_gamma_stirling_eval(t, f, n, len, wp); _acb_poly_exp_series(u, t, len, len, wp); for (i = 1; i < len; i += 2) acb_neg(u + i, u + i); /* v = sin(pi x) */ acb_set(f, h); acb_one(f + 1); _acb_poly_sin_pi_series(v, f, 2, len, wp); _acb_poly_mullow(t, u, len, v, len, len, wp); /* rf(1-h,r) * pi */ if (r == 0) { acb_const_pi(u, wp); _acb_vec_scalar_div(v, t, len, u, wp); } else { acb_sub_ui(f, h, 1, wp); acb_neg(f, f); acb_set_si(f + 1, -1); rflen = FLINT_MIN(len, r + 1); _acb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r, rflen, wp); acb_const_pi(u, wp); _acb_vec_scalar_mul(v, v, rflen, u, wp); /* divide by rising factorial */ /* TODO: might better to use div_series, when it has a good basecase */ _acb_poly_inv_series(u, v, rflen, len, wp); _acb_poly_mullow(v, t, len, u, len, len, wp); } } else { /* rgamma(h) = rgamma(h+r) rf(h,r) */ if (r == 0) { acb_add_ui(f, h, r, wp); _acb_poly_gamma_stirling_eval(t, f, n, len, wp); _acb_vec_neg(t, t, len); _acb_poly_exp_series(v, t, len, len, wp); } else { acb_set(f, h); acb_one(f + 1); rflen = FLINT_MIN(len, r + 1); _acb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, wp); acb_add_ui(f, h, r, wp); _acb_poly_gamma_stirling_eval(v, f, n, len, wp); _acb_vec_neg(v, v, len); _acb_poly_exp_series(u, v, len, len, wp); _acb_poly_mullow(v, u, len, t, rflen, len, wp); } } /* compose with nonconstant part */ acb_zero(t); _acb_vec_set(t + 1, h + 1, hlen - 1); _acb_poly_compose_series(res, v, len, t, hlen, len, prec); acb_clear(f); acb_clear(f + 1); _acb_vec_clear(t, len); _acb_vec_clear(u, len); _acb_vec_clear(v, len); } void acb_poly_rgamma_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec) { if (f->length == 0 || n == 0) { acb_poly_zero(res); } else { acb_poly_fit_length(res, n); _acb_poly_rgamma_series(res->coeffs, f->coeffs, f->length, n, prec); _acb_poly_set_length(res, n); _acb_poly_normalise(res); } } flint-3.1.3/src/acb_poly/rising_ui_series.c000066400000000000000000000047651461254215100207340ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" static void _acb_poly_rising_ui_series_bsplit(acb_ptr res, acb_srcptr f, slong flen, ulong a, ulong b, slong trunc, slong prec) { flen = FLINT_MIN(flen, trunc); if (b - a == 1) { acb_add_ui(res, f, a, prec); _acb_vec_set(res + 1, f + 1, flen - 1); } else { acb_ptr L, R; slong len1, len2; slong m = a + (b - a) / 2; len1 = poly_pow_length(flen, m - a, trunc); len2 = poly_pow_length(flen, b - m, trunc); L = _acb_vec_init(len1 + len2); R = L + len1; _acb_poly_rising_ui_series_bsplit(L, f, flen, a, m, trunc, prec); _acb_poly_rising_ui_series_bsplit(R, f, flen, m, b, trunc, prec); _acb_poly_mullow(res, L, len1, R, len2, FLINT_MIN(trunc, len1 + len2 - 1), prec); _acb_vec_clear(L, len1 + len2); } } void _acb_poly_rising_ui_series(acb_ptr res, acb_srcptr f, slong flen, ulong r, slong trunc, slong prec) { if (trunc == 1 || flen == 1) { acb_rising_ui(res, f, r, prec); _acb_vec_zero(res + 1, trunc - 1); } else if (trunc == 2) { acb_rising2_ui(res, res + 1, f, r, prec); acb_mul(res + 1, res + 1, f + 1, prec); } else { _acb_poly_rising_ui_series_bsplit(res, f, flen, 0, r, trunc, prec); } } void acb_poly_rising_ui_series(acb_poly_t res, const acb_poly_t f, ulong r, slong trunc, slong prec) { slong len; if ((f->length == 0 && r != 0) || trunc == 0) { acb_poly_zero(res); return; } if (r == 0) { acb_poly_one(res); return; } len = poly_pow_length(f->length, r, trunc); if (f == res) { acb_poly_t tmp; acb_poly_init(tmp); acb_poly_rising_ui_series(tmp, f, r, len, prec); acb_poly_swap(tmp, res); acb_poly_clear(tmp); } else { acb_poly_fit_length(res, len); _acb_poly_rising_ui_series(res->coeffs, f->coeffs, f->length, r, len, prec); _acb_poly_set_length(res, len); _acb_poly_normalise(res); } } flint-3.1.3/src/acb_poly/root_bound_fujiwara.c000066400000000000000000000023221461254215100214170ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_root_bound_fujiwara(mag_t bound, acb_srcptr poly, slong len) { mag_t t, u, v; slong i; if (len <= 1) { mag_inf(bound); return; } mag_init(t); mag_init(u); mag_init(v); /* u = 1/leading */ acb_get_mag_lower(t, poly + len - 1); mag_one(u); mag_div(u, u, t); mag_zero(v); for (i = 0; i < len - 1; i++) { acb_get_mag(t, poly + len - 2 - i); mag_mul(t, t, u); if (i == len - 2) mag_mul_2exp_si(t, t, -1); mag_root(t, t, i + 1); mag_max(v, v, t); } mag_mul_2exp_si(bound, v, 1); mag_clear(t); mag_clear(u); mag_clear(v); } void acb_poly_root_bound_fujiwara(mag_t bound, acb_poly_t poly) { _acb_poly_root_bound_fujiwara(bound, poly->coeffs, poly->length); } flint-3.1.3/src/acb_poly/root_inclusion.c000066400000000000000000000025221461254215100204250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_root_inclusion(acb_t r, const acb_t m, acb_srcptr poly, acb_srcptr polyder, slong len, slong prec) { acb_t t; arf_t u, v; acb_init(t); arf_init(u); arf_init(v); acb_set(r, m); mag_zero(arb_radref(acb_realref(r))); mag_zero(arb_radref(acb_imagref(r))); _acb_poly_evaluate(t, poly, len, r, prec); acb_get_abs_ubound_arf(u, t, MAG_BITS); /* it could happen that we have an exact root, in which case we should avoid dividing by the derivative */ if (!arf_is_zero(u)) { _acb_poly_evaluate(t, polyder, len - 1, r, prec); acb_inv(t, t, MAG_BITS); acb_get_abs_ubound_arf(v, t, MAG_BITS); arf_mul(u, u, v, MAG_BITS, ARF_RND_UP); arf_mul_ui(u, u, len - 1, MAG_BITS, ARF_RND_UP); } arf_get_mag(arb_radref(acb_realref(r)), u); arf_get_mag(arb_radref(acb_imagref(r)), u); arf_clear(u); arf_clear(v); acb_clear(t); } flint-3.1.3/src/acb_poly/rsqrt_series.c000066400000000000000000000045251461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void _acb_poly_rsqrt_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); while (hlen > 0 && acb_is_zero(h + hlen - 1)) hlen--; if (hlen <= 1) { acb_rsqrt(g, h, prec); _acb_vec_zero(g + 1, len - 1); } else if (len == 2) { acb_rsqrt(g, h, prec); acb_div(g + 1, h + 1, h, prec); acb_mul(g + 1, g + 1, g, prec); acb_mul_2exp_si(g + 1, g + 1, -1); acb_neg(g + 1, g + 1); } else if (_acb_vec_is_zero(h + 1, hlen - 2)) { acb_t t; acb_init(t); arf_set_si_2exp_si(arb_midref(acb_realref(t)), -1, -1); _acb_poly_binomial_pow_acb_series(g, h, hlen, t, len, prec); acb_clear(t); } else { acb_ptr t, u; slong tlen; t = _acb_vec_init(2 * len); u = t + len; acb_rsqrt(g, h, prec); NEWTON_INIT(1, len) NEWTON_LOOP(m, n) tlen = FLINT_MIN(2 * m - 1, n); _acb_poly_mullow(t, g, m, g, m, tlen, prec); _acb_poly_mullow(u, g, m, t, tlen, n, prec); _acb_poly_mullow(t, u, n, h, hlen, n, prec); _acb_vec_scalar_mul_2exp_si(g + m, t + m, n - m, -1); _acb_vec_neg(g + m, g + m, n - m); NEWTON_END_LOOP NEWTON_END _acb_vec_clear(t, 2 * len); } } void acb_poly_rsqrt_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { if (n == 0) { acb_poly_zero(g); return; } if (g == h) { acb_poly_t t; acb_poly_init(t); acb_poly_rsqrt_series(t, h, n, prec); acb_poly_swap(g, t); acb_poly_clear(t); return; } acb_poly_fit_length(g, n); if (h->length == 0) _acb_vec_indeterminate(g->coeffs, n); else _acb_poly_rsqrt_series(g->coeffs, h->coeffs, h->length, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/set.c000066400000000000000000000011651461254215100161540ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_set(acb_poly_t dest, const acb_poly_t src) { slong len = acb_poly_length(src); acb_poly_fit_length(dest, len); _acb_vec_set(dest->coeffs, src->coeffs, len); _acb_poly_set_length(dest, len); } flint-3.1.3/src/acb_poly/set2_arb_poly.c000066400000000000000000000026251461254215100201270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void acb_poly_set_arb_poly(acb_poly_t poly, const arb_poly_t re) { slong i, len; len = arb_poly_length(re); acb_poly_fit_length(poly, len); for (i = 0; i < len; i++) { arb_set(acb_realref(poly->coeffs + i), re->coeffs + i); arb_zero(acb_imagref(poly->coeffs + i)); } _acb_poly_set_length(poly, len); } void acb_poly_set2_arb_poly(acb_poly_t poly, const arb_poly_t re, const arb_poly_t im) { slong i, rlen, ilen, len; rlen = arb_poly_length(re); ilen = arb_poly_length(im); len = FLINT_MAX(rlen, ilen); acb_poly_fit_length(poly, len); for (i = 0; i < rlen; i++) arb_set(acb_realref(poly->coeffs + i), re->coeffs + i); for (i = rlen; i < len; i++) arb_zero(acb_realref(poly->coeffs + i)); for (i = 0; i < ilen; i++) arb_set(acb_imagref(poly->coeffs + i), im->coeffs + i); for (i = ilen; i < len; i++) arb_zero(acb_imagref(poly->coeffs + i)); _acb_poly_set_length(poly, len); } flint-3.1.3/src/acb_poly/set2_fmpq_poly.c000066400000000000000000000017711461254215100203270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "arb_poly.h" #include "acb_poly.h" void acb_poly_set_fmpq_poly(acb_poly_t poly, const fmpq_poly_t re, slong prec) { arb_poly_t t; arb_poly_init(t); arb_poly_set_fmpq_poly(t, re, prec); acb_poly_set_arb_poly(poly, t); arb_poly_clear(t); } void acb_poly_set2_fmpq_poly(acb_poly_t poly, const fmpq_poly_t re, const fmpq_poly_t im, slong prec) { arb_poly_t t, u; arb_poly_init(t); arb_poly_init(u); arb_poly_set_fmpq_poly(t, re, prec); arb_poly_set_fmpq_poly(u, im, prec); acb_poly_set2_arb_poly(poly, t, u); arb_poly_clear(t); arb_poly_clear(u); } flint-3.1.3/src/acb_poly/set2_fmpz_poly.c000066400000000000000000000014311461254215100203310ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb_poly.h" #include "acb_poly.h" void acb_poly_set2_fmpz_poly(acb_poly_t poly, const fmpz_poly_t re, const fmpz_poly_t im, slong prec) { arb_poly_t t, u; arb_poly_init(t); arb_poly_init(u); arb_poly_set_fmpz_poly(t, re, prec); arb_poly_set_fmpz_poly(u, im, prec); acb_poly_set2_arb_poly(poly, t, u); arb_poly_clear(t); arb_poly_clear(u); } flint-3.1.3/src/acb_poly/set_coeff_acb.c000066400000000000000000000013261461254215100201220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_set_coeff_acb(acb_poly_t poly, slong n, const acb_t x) { acb_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { _acb_vec_zero(poly->coeffs + poly->length, n - poly->length); poly->length = n + 1; } acb_set(poly->coeffs + n, x); _acb_poly_normalise(poly); } flint-3.1.3/src/acb_poly/set_coeff_si.c000066400000000000000000000013221461254215100200040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_set_coeff_si(acb_poly_t poly, slong n, slong x) { acb_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { _acb_vec_zero(poly->coeffs + poly->length, n - poly->length); poly->length = n + 1; } acb_set_si(poly->coeffs + n, x); _acb_poly_normalise(poly); } flint-3.1.3/src/acb_poly/set_fmpz_poly.c000066400000000000000000000013311461254215100202460ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "acb_poly.h" void acb_poly_set_fmpz_poly(acb_poly_t poly, const fmpz_poly_t src, slong prec) { slong i, len = fmpz_poly_length(src); acb_poly_fit_length(poly, len); _acb_poly_set_length(poly, len); for (i = 0; i < len; i++) acb_set_round_fmpz(poly->coeffs + i, src->coeffs + i, prec); } flint-3.1.3/src/acb_poly/set_length.c000066400000000000000000000011641461254215100175140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_set_length(acb_poly_t poly, slong len) { slong i; if (poly->length > len) { for (i = len; i < poly->length; i++) acb_zero(poly->coeffs + i); } poly->length = len; } flint-3.1.3/src/acb_poly/set_round.c000066400000000000000000000012231461254215100173560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_set_round(acb_poly_t dest, const acb_poly_t src, slong prec) { slong len = acb_poly_length(src); acb_poly_fit_length(dest, len); _acb_vec_set_round(dest->coeffs, src->coeffs, len, prec); _acb_poly_set_length(dest, len); } flint-3.1.3/src/acb_poly/set_si.c000066400000000000000000000012111461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_set_si(acb_poly_t poly, slong c) { if (c == 0) { acb_poly_zero(poly); } else { acb_poly_fit_length(poly, 1); acb_set_si(poly->coeffs, c); _acb_poly_set_length(poly, 1); } } flint-3.1.3/src/acb_poly/set_trunc.c000066400000000000000000000015321461254215100173650ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_set_trunc(acb_poly_t res, const acb_poly_t poly, slong n) { if (poly == res) { acb_poly_truncate(res, n); } else { slong rlen; rlen = FLINT_MIN(n, poly->length); while (rlen > 0 && acb_is_zero(poly->coeffs + rlen - 1)) rlen--; acb_poly_fit_length(res, rlen); _acb_vec_set(res->coeffs, poly->coeffs, rlen); _acb_poly_set_length(res, rlen); } } flint-3.1.3/src/acb_poly/set_trunc_round.c000066400000000000000000000017011461254215100205720ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_set_trunc_round(acb_poly_t res, const acb_poly_t poly, slong n, slong prec) { if (poly == res) { acb_poly_truncate(res, n); _acb_vec_set_round(res->coeffs, res->coeffs, res->length, prec); } else { slong rlen; rlen = FLINT_MIN(n, poly->length); while (rlen > 0 && acb_is_zero(poly->coeffs + rlen - 1)) rlen--; acb_poly_fit_length(res, rlen); _acb_vec_set_round(res->coeffs, poly->coeffs, rlen, prec); _acb_poly_set_length(res, rlen); } } flint-3.1.3/src/acb_poly/shift_left.c000066400000000000000000000024461461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_shift_left(acb_ptr res, acb_srcptr poly, slong len, slong n) { slong i; /* Copy in reverse to avoid writing over unshifted coefficients */ if (res != poly) { for (i = len; i--; ) acb_set(res + n + i, poly + i); } else { for (i = len; i--; ) acb_swap(res + n + i, res + i); } for (i = 0; i < n; i++) acb_zero(res + i); } void acb_poly_shift_left(acb_poly_t res, const acb_poly_t poly, slong n) { if (n == 0) { acb_poly_set(res, poly); return; } if (poly->length == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, poly->length + n); _acb_poly_shift_left(res->coeffs, poly->coeffs, poly->length, n); _acb_poly_set_length(res, poly->length + n); } flint-3.1.3/src/acb_poly/shift_right.c000066400000000000000000000024121461254215100176670ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_shift_right(acb_ptr res, acb_srcptr poly, slong len, slong n) { slong i; /* Copy in forward order to avoid writing over unshifted coefficients */ if (res != poly) { for (i = 0; i < len - n; i++) acb_set(res + i, poly + n + i); } else { for (i = 0; i < len - n; i++) acb_swap(res + i, res + n + i); } } void acb_poly_shift_right(acb_poly_t res, const acb_poly_t poly, slong n) { if (n == 0) { acb_poly_set(res, poly); return; } if (poly->length <= n) { acb_poly_zero(res); return; } acb_poly_fit_length(res, poly->length - n); _acb_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n); _acb_poly_set_length(res, poly->length - n); } flint-3.1.3/src/acb_poly/sin_cos_series.c000066400000000000000000000071601461254215100203710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif static void __acb_poly_sin_cos_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, int times_pi, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { if (times_pi) acb_sin_cos_pi(s, c, h, prec); else acb_sin_cos(s, c, h, prec); _acb_vec_zero(s + 1, n - 1); _acb_vec_zero(c + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); if (times_pi) { acb_const_pi(t, prec); acb_mul(t, t, h + 1, prec); acb_sin_cos_pi(s, c, h, prec); } else { acb_set(t, h + 1); acb_sin_cos(s, c, h, prec); } acb_mul(s + 1, c, t, prec); acb_neg(t, t); acb_mul(c + 1, s, t, prec); acb_clear(t); } else { slong cutoff; gr_ctx_t ctx; int status; if (prec <= 128) { cutoff = 1400; } else { cutoff = 100000 / pow(log(prec), 3); cutoff = FLINT_MIN(cutoff, 700); } gr_ctx_init_complex_acb(ctx, 53); if (hlen < cutoff) status = _gr_poly_sin_cos_series_basecase(s, c, h, hlen, n, times_pi, ctx); else status = _gr_poly_sin_cos_series_tangent(s, c, h, hlen, n, times_pi, ctx); if (status != GR_SUCCESS) { _acb_vec_indeterminate(s, n); _acb_vec_indeterminate(c, n); } } } void _acb_poly_sin_cos_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) { __acb_poly_sin_cos_series(s, c, h, hlen, n, 0, prec); } void _acb_poly_sin_cos_pi_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) { __acb_poly_sin_cos_series(s, c, h, hlen, n, 1, prec); } void acb_poly_sin_cos_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(s); acb_poly_zero(c); return; } if (hlen == 0) { acb_poly_zero(s); acb_poly_one(c); return; } if (hlen == 1) n = 1; acb_poly_fit_length(s, n); acb_poly_fit_length(c, n); _acb_poly_sin_cos_series(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(s, n); _acb_poly_normalise(s); _acb_poly_set_length(c, n); _acb_poly_normalise(c); } void acb_poly_sin_cos_pi_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(s); acb_poly_zero(c); return; } if (hlen == 0) { acb_poly_zero(s); acb_poly_one(c); return; } if (hlen == 1) n = 1; acb_poly_fit_length(s, n); acb_poly_fit_length(c, n); _acb_poly_sin_cos_pi_series(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(s, n); _acb_poly_normalise(s); _acb_poly_set_length(c, n); _acb_poly_normalise(c); } flint-3.1.3/src/acb_poly/sin_pi_series.c000066400000000000000000000026431461254215100202160ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sin_pi_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_sin_pi(g, h, prec); _acb_vec_zero(g + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); acb_sin_cos_pi(g, t, h, prec); acb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ acb_const_pi(t, prec); acb_mul(g + 1, g + 1, t, prec); acb_clear(t); } else { acb_ptr t = _acb_vec_init(n); _acb_poly_sin_cos_pi_series(g, t, h, hlen, n, prec); _acb_vec_clear(t, n); } } void acb_poly_sin_pi_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { acb_poly_zero(g); return; } if (hlen == 1) n = 1; acb_poly_fit_length(g, n); _acb_poly_sin_pi_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/sin_series.c000066400000000000000000000025121461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sin_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_sin(g, h, prec); _acb_vec_zero(g + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); acb_sin_cos(g, t, h, prec); acb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ acb_clear(t); } else { acb_ptr t = _acb_vec_init(n); _acb_poly_sin_cos_series(g, t, h, hlen, n, prec); _acb_vec_clear(t, n); } } void acb_poly_sin_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { acb_poly_zero(g); return; } if (hlen == 1) n = 1; acb_poly_fit_length(g, n); _acb_poly_sin_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/sinc_series.c000066400000000000000000000031221461254215100176620ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sinc_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_sinc(g, h, prec); _acb_vec_zero(g + 1, n - 1); } else { acb_ptr t, u; t = _acb_vec_init(n + 1); u = _acb_vec_init(hlen); _acb_vec_set(u, h, hlen); if (acb_is_zero(h)) { _acb_poly_sin_series(t, u, hlen, n + 1, prec); _acb_poly_div_series(g, t + 1, n, u + 1, hlen - 1, n, prec); } else { _acb_poly_sin_series(t, u, hlen, n, prec); _acb_poly_div_series(g, t, n, u, hlen, n, prec); } _acb_vec_clear(t, n + 1); _acb_vec_clear(u, hlen); } } void acb_poly_sinc_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(g); return; } if (hlen == 0) { acb_poly_one(g); return; } if (hlen == 1) n = 1; acb_poly_fit_length(g, n); _acb_poly_sinc_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/sinh_cosh_series.c000066400000000000000000000037541461254215100207160ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif void _acb_poly_sinh_cosh_series(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_sinh_cosh(s, c, h, prec); _acb_vec_zero(s + 1, n - 1); _acb_vec_zero(c + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); acb_set(t, h + 1); acb_sinh_cosh(s, c, h, prec); acb_mul(s + 1, c, t, prec); acb_mul(c + 1, s, t, prec); acb_clear(t); } else { slong cutoff; if (prec <= 128) cutoff = 400; else cutoff = 30000 / pow(log(prec), 3); if (hlen < cutoff) _acb_poly_sinh_cosh_series_basecase(s, c, h, hlen, n, prec); else _acb_poly_sinh_cosh_series_exponential(s, c, h, hlen, n, prec); } } void acb_poly_sinh_cosh_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(s); acb_poly_zero(c); return; } if (hlen == 0) { acb_poly_zero(s); acb_poly_one(c); return; } if (hlen == 1) n = 1; acb_poly_fit_length(s, n); acb_poly_fit_length(c, n); _acb_poly_sinh_cosh_series(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(s, n); _acb_poly_normalise(s); _acb_poly_set_length(c, n); _acb_poly_normalise(c); } flint-3.1.3/src/acb_poly/sinh_cosh_series_basecase.c000066400000000000000000000035121461254215100225340ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sinh_cosh_series_basecase(acb_ptr s, acb_ptr c, acb_srcptr h, slong hlen, slong n, slong prec) { slong k, alen = FLINT_MIN(n, hlen); acb_ptr a; acb_t t, u; acb_sinh_cosh(s, c, h, prec); if (hlen == 1) { _acb_vec_zero(s + 1, n - 1); _acb_vec_zero(c + 1, n - 1); return; } acb_init(t); acb_init(u); a = _acb_vec_init(alen); for (k = 1; k < alen; k++) acb_mul_ui(a + k, h + k, k, prec); for (k = 1; k < n; k++) { acb_dot(t, NULL, 0, a + 1, 1, s + k - 1, -1, FLINT_MIN(k, hlen - 1), prec); acb_dot(u, NULL, 0, a + 1, 1, c + k - 1, -1, FLINT_MIN(k, hlen - 1), prec); acb_div_ui(c + k, t, k, prec); acb_div_ui(s + k, u, k, prec); } acb_clear(t); acb_clear(u); _acb_vec_clear(a, alen); } void acb_poly_sinh_cosh_series_basecase(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(s); acb_poly_zero(c); return; } if (hlen == 0) { acb_poly_zero(s); acb_poly_one(c); return; } acb_poly_fit_length(s, n); acb_poly_fit_length(c, n); _acb_poly_sinh_cosh_series_basecase(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(s, n); _acb_poly_normalise(s); _acb_poly_set_length(c, n); _acb_poly_normalise(c); } flint-3.1.3/src/acb_poly/sinh_cosh_series_exponential.c000066400000000000000000000050051461254215100233130ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sinh_cosh_series_exponential(acb_ptr s, acb_ptr c, const acb_srcptr h, slong hlen, slong len, slong prec) { acb_ptr t, u, v; acb_t s0, c0; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { acb_sinh_cosh(s, c, h, prec); _acb_vec_zero(s + 1, len - 1); _acb_vec_zero(c + 1, len - 1); return; } acb_init(s0); acb_init(c0); t = _acb_vec_init(3 * len); u = t + len; v = u + len; acb_sinh_cosh(s0, c0, h, prec); _acb_vec_set(t + 1, h + 1, hlen - 1); _acb_poly_exp_series(t, t, len, len, prec); /* todo: part of the inverse could be avoided since exp computes it internally to half the length */ _acb_poly_inv_series(u, t, len, len, prec); /* hyperbolic sine */ _acb_vec_sub(s, t, u, len, prec); _acb_vec_scalar_mul_2exp_si(s, s, len, -1); /* hyperbolic cosine */ _acb_vec_add(c, t, u, len, prec); _acb_vec_scalar_mul_2exp_si(c, c, len, -1); /* sinh(h0 + h1) = cosh(h0) sinh(h1) + sinh(h0) cosh(h1) cosh(h0 + h1) = cosh(h0) cosh(h1) + sinh(h0) sinh(h1) */ if (!acb_is_zero(s0)) { _acb_vec_scalar_mul(t, s, len, c0, prec); _acb_vec_scalar_mul(u, c, len, s0, prec); _acb_vec_scalar_mul(v, s, len, s0, prec); _acb_vec_add(s, t, u, len, prec); _acb_vec_scalar_mul(t, c, len, c0, prec); _acb_vec_add(c, t, v, len, prec); } _acb_vec_clear(t, 3 * len); acb_clear(s0); acb_clear(c0); } void acb_poly_sinh_cosh_series_exponential(acb_poly_t s, acb_poly_t c, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { acb_poly_zero(s); acb_poly_zero(c); return; } if (hlen == 0) { acb_poly_zero(s); acb_poly_one(c); return; } acb_poly_fit_length(s, n); acb_poly_fit_length(c, n); _acb_poly_sinh_cosh_series_exponential(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(s, n); _acb_poly_normalise(s); _acb_poly_set_length(c, n); _acb_poly_normalise(c); } flint-3.1.3/src/acb_poly/sinh_series.c000066400000000000000000000025221461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sinh_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { acb_sinh(g, h, prec); _acb_vec_zero(g + 1, n - 1); } else if (n == 2) { acb_t t; acb_init(t); acb_sinh_cosh(g, t, h, prec); acb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ acb_clear(t); } else { acb_ptr t = _acb_vec_init(n); _acb_poly_sinh_cosh_series(g, t, h, hlen, n, prec); _acb_vec_clear(t, n); } } void acb_poly_sinh_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { acb_poly_zero(g); return; } if (hlen == 1) n = 1; acb_poly_fit_length(g, n); _acb_poly_sinh_series(g->coeffs, h->coeffs, hlen, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/sqrt_series.c000066400000000000000000000036401461254215100177240ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sqrt_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); while (hlen > 0 && acb_is_zero(h + hlen - 1)) hlen--; if (hlen <= 1) { acb_sqrt(g, h, prec); _acb_vec_zero(g + 1, len - 1); } else if (len == 2) { acb_sqrt(g, h, prec); acb_div(g + 1, h + 1, h, prec); acb_mul(g + 1, g + 1, g, prec); acb_mul_2exp_si(g + 1, g + 1, -1); } else if (_acb_vec_is_zero(h + 1, hlen - 2)) { acb_t t; acb_init(t); arf_set_si_2exp_si(arb_midref(acb_realref(t)), 1, -1); _acb_poly_binomial_pow_acb_series(g, h, hlen, t, len, prec); acb_clear(t); } else { acb_ptr t; t = _acb_vec_init(len); _acb_poly_rsqrt_series(t, h, hlen, len, prec); _acb_poly_mullow(g, t, len, h, hlen, len, prec); _acb_vec_clear(t, len); } } void acb_poly_sqrt_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { if (n == 0) { acb_poly_zero(g); return; } if (g == h) { acb_poly_t t; acb_poly_init(t); acb_poly_sqrt_series(t, h, n, prec); acb_poly_swap(g, t); acb_poly_clear(t); return; } acb_poly_fit_length(g, n); if (h->length == 0) _acb_vec_indeterminate(g->coeffs, n); else _acb_poly_sqrt_series(g->coeffs, h->coeffs, h->length, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/sub.c000066400000000000000000000022621461254215100161510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void _acb_poly_sub(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong prec) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) acb_sub(res + i, poly1 + i, poly2 + i, prec); for (i = min; i < len1; i++) acb_set_round(res + i, poly1 + i, prec); for (i = min; i < len2; i++) acb_neg_round(res + i, poly2 + i, prec); } void acb_poly_sub(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong prec) { slong max = FLINT_MAX(poly1->length, poly2->length); acb_poly_fit_length(res, max); _acb_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); _acb_poly_set_length(res, max); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/sub_series.c000066400000000000000000000015751461254215100175310ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" void acb_poly_sub_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong len, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; len1 = FLINT_MIN(len1, len); len2 = FLINT_MIN(len2, len); len = FLINT_MAX(len1, len2); acb_poly_fit_length(res, len); _acb_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); _acb_poly_set_length(res, len); _acb_poly_normalise(res); } flint-3.1.3/src/acb_poly/tan_series.c000066400000000000000000000021261461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" #define TAN_NEWTON_CUTOFF 20 void _acb_poly_tan_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); hlen = FLINT_MIN(hlen, len); if (_gr_poly_tan_series_newton(res, h, hlen, len, TAN_NEWTON_CUTOFF, ctx) != GR_SUCCESS) _acb_vec_indeterminate(res, len); } void acb_poly_tan_series(acb_poly_t g, const acb_poly_t h, slong n, slong prec) { if (h->length == 0 || n == 0) { acb_poly_zero(g); return; } acb_poly_fit_length(g, n); _acb_poly_tan_series(g->coeffs, h->coeffs, h->length, n, prec); _acb_poly_set_length(g, n); _acb_poly_normalise(g); } flint-3.1.3/src/acb_poly/taylor_shift.c000066400000000000000000000031371461254215100200710ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "gr_poly.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif int _gr_acb_poly_taylor_shift(acb_ptr res, acb_srcptr poly, slong n, const acb_t c, gr_ctx_t ctx) { slong prec; if (n <= 30) return _gr_poly_taylor_shift_horner(res, poly, n, c, ctx); prec = _gr_ctx_get_real_prec(ctx); if (n <= 30 || (n <= 500 && acb_bits(c) == 1 && n < 30 + 3 * sqrt(prec)) || (n <= 100 && acb_bits(c) < 0.01 * prec)) { return _gr_poly_taylor_shift_horner(res, poly, n, c, ctx); } else if (prec > 2 * n) { return _gr_poly_taylor_shift_convolution(res, poly, n, c, ctx); } else { return _gr_poly_taylor_shift_divconquer(res, poly, n, c, ctx); } } void _acb_poly_taylor_shift(acb_ptr poly, const acb_t c, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_complex_acb(ctx, prec); if (_gr_poly_taylor_shift(poly, poly, n, c, ctx) != GR_SUCCESS) _acb_vec_indeterminate(poly, n); } void acb_poly_taylor_shift(acb_poly_t g, const acb_poly_t f, const acb_t c, slong prec) { if (f != g) acb_poly_set_round(g, f, prec); _acb_poly_taylor_shift(g->coeffs, c, g->length, prec); } flint-3.1.3/src/acb_poly/test/000077500000000000000000000000001461254215100161715ustar00rootroot00000000000000flint-3.1.3/src/acb_poly/test/main.c000066400000000000000000000144651461254215100172730ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_series.c" #include "t-add_si.c" #include "t-agm1_series.c" #include "t-atan_series.c" #include "t-binomial_transform_basecase.c" #include "t-binomial_transform.c" #include "t-binomial_transform_convolution.c" #include "t-borel_transform.c" #include "t-compose.c" #include "t-compose_series.c" #include "t-cos_pi_series.c" #include "t-cot_pi_series.c" #include "t-digamma_series.c" #include "t-divrem.c" #include "t-div_series.c" #include "t-elliptic_k_series.c" #include "t-elliptic_p_series.c" #include "t-evaluate2.c" #include "t-evaluate2_horner.c" #include "t-evaluate2_rectangular.c" #include "t-evaluate.c" #include "t-evaluate_horner.c" #include "t-evaluate_rectangular.c" #include "t-evaluate_vec_fast.c" #include "t-evaluate_vec_iter.c" #include "t-exp_pi_i_series.c" #include "t-exp_series_basecase.c" #include "t-exp_series.c" #include "t-find_roots.c" #include "t-gamma_series.c" #include "t-get_coeff_ptr.c" #include "t-get_set_coeff_acb.c" #include "t-get_unique_fmpz_poly.c" #include "t-graeffe_transform.c" #include "t-interpolate_barycentric.c" #include "t-interpolate_fast.c" #include "t-interpolate_newton.c" #include "t-inv_series.c" #include "t-lambertw_series.c" #include "t-lgamma_series.c" #include "t-log1p_series.c" #include "t-log_series.c" #include "t-mullow.c" #include "t-mullow_classical.c" #include "t-mullow_transpose.c" #include "t-mullow_transpose_gauss.c" #include "t-polylog_cpx.c" #include "t-polylog_series.c" #include "t-pow_acb_series.c" #include "t-pow_series.c" #include "t-powsum_one_series_sieved.c" #include "t-powsum_series_naive_threaded.c" #include "t-pow_ui.c" #include "t-pow_ui_trunc_binexp.c" #include "t-product_roots.c" #include "t-revert_series.c" #include "t-rgamma_series.c" #include "t-rising_ui_series.c" #include "t-root_bound_fujiwara.c" #include "t-rsqrt_series.c" #include "t-set_trunc_round.c" #include "t-shift_left_right.c" #include "t-sin_cos_pi_series.c" #include "t-sin_cos_series.c" #include "t-sinc_series.c" #include "t-sinh_cosh_series.c" #include "t-sin_pi_series.c" #include "t-sin_series_cos_series.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-tan_series.c" #include "t-taylor_shift.c" #include "t-zeta_cpx_series.c" #include "t-zeta_em_tail_bsplit.c" #include "t-zeta_series.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_poly_add), TEST_FUNCTION(acb_poly_add_series), TEST_FUNCTION(acb_poly_add_si), TEST_FUNCTION(acb_poly_agm1_series), TEST_FUNCTION(acb_poly_atan_series), TEST_FUNCTION(acb_poly_binomial_transform_basecase), TEST_FUNCTION(acb_poly_binomial_transform), TEST_FUNCTION(acb_poly_binomial_transform_convolution), TEST_FUNCTION(acb_poly_borel_transform), TEST_FUNCTION(acb_poly_compose), TEST_FUNCTION(acb_poly_compose_series), TEST_FUNCTION(acb_poly_cos_pi_series), TEST_FUNCTION(acb_poly_cot_pi_series), TEST_FUNCTION(acb_poly_digamma_series), TEST_FUNCTION(acb_poly_divrem), TEST_FUNCTION(acb_poly_div_series), TEST_FUNCTION(acb_poly_elliptic_k_series), TEST_FUNCTION(acb_poly_elliptic_p_series), TEST_FUNCTION(acb_poly_evaluate2), TEST_FUNCTION(acb_poly_evaluate2_horner), TEST_FUNCTION(acb_poly_evaluate2_rectangular), TEST_FUNCTION(acb_poly_evaluate), TEST_FUNCTION(acb_poly_evaluate_horner), TEST_FUNCTION(acb_poly_evaluate_rectangular), TEST_FUNCTION(acb_poly_evaluate_vec_fast), TEST_FUNCTION(acb_poly_evaluate_vec_iter), TEST_FUNCTION(acb_poly_exp_pi_i_series), TEST_FUNCTION(acb_poly_exp_series_basecase), TEST_FUNCTION(acb_poly_exp_series), TEST_FUNCTION(acb_poly_find_roots), TEST_FUNCTION(acb_poly_gamma_series), TEST_FUNCTION(acb_poly_get_coeff_ptr), TEST_FUNCTION(acb_poly_get_set_coeff_acb), TEST_FUNCTION(acb_poly_get_unique_fmpz_poly), TEST_FUNCTION(acb_poly_graeffe_transform), TEST_FUNCTION(acb_poly_interpolate_barycentric), TEST_FUNCTION(acb_poly_interpolate_fast), TEST_FUNCTION(acb_poly_interpolate_newton), TEST_FUNCTION(acb_poly_inv_series), TEST_FUNCTION(acb_poly_lambertw_series), TEST_FUNCTION(acb_poly_lgamma_series), TEST_FUNCTION(acb_poly_log1p_series), TEST_FUNCTION(acb_poly_log_series), TEST_FUNCTION(acb_poly_mullow), TEST_FUNCTION(acb_poly_mullow_classical), TEST_FUNCTION(acb_poly_mullow_transpose), TEST_FUNCTION(acb_poly_mullow_transpose_gauss), TEST_FUNCTION(acb_poly_polylog_cpx), TEST_FUNCTION(acb_poly_polylog_series), TEST_FUNCTION(acb_poly_pow_acb_series), TEST_FUNCTION(acb_poly_pow_series), TEST_FUNCTION(acb_poly_powsum_one_series_sieved), TEST_FUNCTION(acb_poly_powsum_series_naive_threaded), TEST_FUNCTION(acb_poly_pow_ui), TEST_FUNCTION(acb_poly_pow_ui_trunc_binexp), TEST_FUNCTION(acb_poly_product_roots), TEST_FUNCTION(acb_poly_revert_series), TEST_FUNCTION(acb_poly_rgamma_series), TEST_FUNCTION(acb_poly_rising_ui_series), TEST_FUNCTION(acb_poly_root_bound_fujiwara), TEST_FUNCTION(acb_poly_rsqrt_series), TEST_FUNCTION(acb_poly_set_trunc_round), TEST_FUNCTION(acb_poly_shift_left_right), TEST_FUNCTION(acb_poly_sin_cos_pi_series), TEST_FUNCTION(acb_poly_sin_cos_series), TEST_FUNCTION(acb_poly_sinc_series), TEST_FUNCTION(acb_poly_sinh_cosh_series), TEST_FUNCTION(acb_poly_sin_pi_series), TEST_FUNCTION(acb_poly_sin_series_cos_series), TEST_FUNCTION(acb_poly_sqrt_series), TEST_FUNCTION(acb_poly_sub), TEST_FUNCTION(acb_poly_sub_series), TEST_FUNCTION(acb_poly_tan_series), TEST_FUNCTION(acb_poly_taylor_shift), TEST_FUNCTION(acb_poly_zeta_cpx_series), TEST_FUNCTION(acb_poly_zeta_em_tail_bsplit), TEST_FUNCTION(acb_poly_zeta_series) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_poly/test/t-add.c000066400000000000000000000054361461254215100173360ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_add, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_add(C, A, B); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_add(c, a, b, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_add(d, d, b, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_add(d, a, d, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-add_series.c000066400000000000000000000042761461254215100207110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_add_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d; slong len, prec; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10); acb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10); acb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10); acb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10); prec = 2 + n_randint(state, 100); len = n_randint(state, 10); acb_poly_add_series(c, a, b, len, prec); acb_poly_add(d, a, b, prec); acb_poly_truncate(d, len); if (!acb_poly_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_add_series(d, d, b, len, prec); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_add_series(d, a, d, len, prec); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-add_si.c000066400000000000000000000033351461254215100200250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_add_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d; slong v; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); acb_poly_randtest(b, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); acb_poly_randtest(c, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); acb_poly_randtest(d, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); v = n_randtest(state); acb_poly_set_si(b, v); acb_poly_add(c, a, b, 2 + n_randint(state, 200)); acb_poly_add_si(d, a, v, 2 + n_randint(state, 200)); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_abort(); } acb_poly_add_si(a, a, v, 2 + n_randint(state, 200)); if (!acb_poly_overlaps(a, d)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-agm1_series.c000066400000000000000000000040321461254215100207740ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_agm1_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_poly_agm1_series(A, S, n1, bits2); acb_poly_agm1_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_agm1_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-atan_series.c000066400000000000000000000053011461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_atan_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; acb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, m, qbits); fmpq_poly_set_coeff_si(A, 0, 0); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_atan_series(b, a, n, rbits2); /* Check 2 atan(x) = atan(2x/(1-x^2)) + C */ acb_poly_mullow(c, a, a, n, rbits2); acb_poly_one(d); acb_poly_sub(c, d, c, rbits2); acb_poly_add(d, a, a, rbits2); if (acb_poly_length(c) != 0) { acb_poly_div_series(c, d, c, n, rbits2); acb_poly_atan_series(c, c, n, rbits2); acb_poly_add(d, b, b, rbits2); /* TODO: also check the first coefficient */ acb_poly_set_coeff_si(c, 0, 0); acb_poly_set_coeff_si(d, 0, 0); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } } acb_poly_atan_series(a, a, n, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-binomial_transform.c000066400000000000000000000056751461254215100225000ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_binomial_transform, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d; slong j, n, prec; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); n = n_randint(state, 20); prec = 2 + n_randint(state, 200); acb_poly_randtest(a, state, n, prec, 10); acb_poly_randtest(b, state, n, prec, 10); acb_poly_randtest(c, state, n, prec, 10); /* check self-inversion property */ acb_poly_binomial_transform(b, a, n, prec); acb_poly_binomial_transform(c, b, n, prec); acb_poly_set(d, a); acb_poly_truncate(d, n); if (!acb_poly_contains(c, d)) { flint_printf("FAIL (containment)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d: "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_binomial_transform(d, d, n, prec); if (!acb_poly_equal(d, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d: "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* compare with power series operations */ acb_poly_zero(d); for (j = 1; j < n; j++) acb_poly_set_coeff_si(d, j, -1); acb_poly_compose_series(c, a, d, n, prec); for (j = 0; j < n; j++) acb_poly_set_coeff_si(d, j, 1); acb_poly_mullow(c, c, d, n, prec); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL (power series)\n\n"); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-binomial_transform_basecase.c000066400000000000000000000057411461254215100243200ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_binomial_transform_basecase, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d; slong j, n, prec; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); n = n_randint(state, 20); prec = 2 + n_randint(state, 200); acb_poly_randtest(a, state, n, prec, 10); acb_poly_randtest(b, state, n, prec, 10); acb_poly_randtest(c, state, n, prec, 10); /* check self-inversion property */ acb_poly_binomial_transform_basecase(b, a, n, prec); acb_poly_binomial_transform_basecase(c, b, n, prec); acb_poly_set(d, a); acb_poly_truncate(d, n); if (!acb_poly_contains(c, d)) { flint_printf("FAIL (containment)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d: "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_binomial_transform_basecase(d, d, n, prec); if (!acb_poly_equal(d, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d: "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* compare with power series operations */ acb_poly_zero(d); for (j = 1; j < n; j++) acb_poly_set_coeff_si(d, j, -1); acb_poly_compose_series(c, a, d, n, prec); for (j = 0; j < n; j++) acb_poly_set_coeff_si(d, j, 1); acb_poly_mullow(c, c, d, n, prec); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL (power series)\n\n"); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-binomial_transform_convolution.c000066400000000000000000000057551461254215100251360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_binomial_transform_convolution, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d; slong j, n, prec; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); n = n_randint(state, 20); prec = 2 + n_randint(state, 200); acb_poly_randtest(a, state, n, prec, 10); acb_poly_randtest(b, state, n, prec, 10); acb_poly_randtest(c, state, n, prec, 10); /* check self-inversion property */ acb_poly_binomial_transform_convolution(b, a, n, prec); acb_poly_binomial_transform_convolution(c, b, n, prec); acb_poly_set(d, a); acb_poly_truncate(d, n); if (!acb_poly_contains(c, d)) { flint_printf("FAIL (containment)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d: "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_binomial_transform_convolution(d, d, n, prec); if (!acb_poly_equal(d, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d: "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* compare with power series operations */ acb_poly_zero(d); for (j = 1; j < n; j++) acb_poly_set_coeff_si(d, j, -1); acb_poly_compose_series(c, a, d, n, prec); for (j = 0; j < n; j++) acb_poly_set_coeff_si(d, j, 1); acb_poly_mullow(c, c, d, n, prec); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL (power series)\n\n"); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-borel_transform.c000066400000000000000000000033471461254215100220030ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_borel_transform, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d; slong n, prec; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); n = n_randint(state, 30); prec = n_randint(state, 200); acb_poly_randtest(a, state, n, prec, 10); acb_poly_randtest(b, state, n, prec, 10); acb_poly_randtest(c, state, n, prec, 10); acb_poly_borel_transform(b, a, prec); acb_poly_inv_borel_transform(c, b, prec); if (!acb_poly_contains(c, a)) { flint_printf("FAIL (containment)\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_borel_transform(d, d, prec); if (!acb_poly_equal(d, b)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_inv_borel_transform(d, d, prec); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-compose.c000066400000000000000000000053721461254215100202520ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_compose, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 20), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_compose(C, A, B); acb_poly_randtest(c, state, 1 + n_randint(state, 20), rbits1, 4); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_compose(c, a, b, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_compose(d, d, b, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_compose(d, a, d, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-compose_series.c000066400000000000000000000111571461254215100216220ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_compose_series, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, n; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); n = 2 + n_randint(state, 25); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 25), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 25), qbits2); fmpq_poly_set_coeff_ui(B, 0, 0); fmpq_poly_compose_series(C, A, B, n); acb_poly_randtest(c, state, 1 + n_randint(state, 20), rbits1, 4); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_compose_series(c, a, b, n, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, bits3 = %wd\n", n, rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_compose_series(d, d, b, n, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_compose_series(d, a, d, n, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } if (a->length > 0 && b->length > 0) { int any_finite; slong i, k, l, m; /* randomize coefficients to set to indeterminate value */ /* if the value is equal to the length we don't set an indeterminate value */ k = n_randint(state, a->length + 1); l = 1 + n_randint(state, b->length); if (k < a->length) acb_indeterminate(a->coeffs + k); else k = n; // k doesn't affect number of finite coefficients if (l < b->length) acb_indeterminate(b->coeffs + l); else l = n; // l doesn't affect number of finite coefficients acb_poly_compose_series(d, a, b, n, rbits3); /* up to this all coefficients should be finite */ m = FLINT_MIN(FLINT_MIN(k, l), d->length); /* check that coefficients after m are all non-finite */ any_finite = 0; for (i = m; i < d->length; i++) any_finite |= acb_is_finite(d->coeffs + i); if (any_finite) { flint_printf("FAIL (non-finite 1)\n\n"); flint_abort(); } /* check that coefficients up to m are all finite and contain the expected result */ if (!_acb_vec_is_finite(d->coeffs, m)) { flint_printf("FAIL (non-finite 2)\n\n"); flint_abort(); } fmpq_poly_truncate(C, m); acb_poly_truncate(d, m); if (!acb_poly_contains_fmpq_poly(d, C)) { flint_printf("FAIL (non-finite 3)\n\n"); flint_abort(); } } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-cos_pi_series.c000066400000000000000000000043101461254215100214220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_cos_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; acb_t pi; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(pi); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_poly_cos_pi_series(A, S, n1, bits2); acb_const_pi(pi, bits3); acb_poly_set_acb(B, pi); acb_poly_mul(B, S, B, bits3); acb_poly_cos_series(B, B, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_cos_pi_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_clear(pi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-cot_pi_series.c000066400000000000000000000036651461254215100214370ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_cot_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, bits1, bits2, bits3; acb_poly_t S, A, B, C; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_randtest(S, state, m, bits1, 10); acb_poly_randtest(A, state, m, bits1, 10); acb_poly_randtest(B, state, m, bits1, 10); acb_poly_cot_pi_series(A, S, n1, bits2); acb_poly_sin_cos_pi_series(B, C, S, n1, bits3); acb_poly_div_series(B, C, B, n1, bits3); if (!acb_poly_overlaps(A, B)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_cot_pi_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-digamma_series.c000066400000000000000000000053421461254215100215530ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_digamma_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; acb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 300); rbits2 = 2 + n_randint(state, 300); rbits3 = 2 + n_randint(state, 300); m = n_randint(state, 25); n1 = n_randint(state, 25); n2 = n_randint(state, 25); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, m, rbits1, 10); acb_poly_digamma_series(b, a, n1, rbits2); acb_poly_digamma_series(c, a, n2, rbits3); acb_poly_set(d, b); acb_poly_truncate(d, FLINT_MIN(n1, n2)); acb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); acb_poly_printd(a, 50); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 50); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 50); flint_printf("\n\n"); flint_abort(); } /* check psi(a) + 1/a = psi(a+1) */ acb_poly_inv_series(c, a, n1, rbits2); acb_poly_add(c, b, c, rbits2); acb_poly_add_si(d, a, 1, rbits2); acb_poly_digamma_series(d, d, n1, rbits2); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_digamma_series(a, a, n1, rbits2); if (!acb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-div_series.c000066400000000000000000000057611461254215100207430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_div_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, p, qbits, rbits1, rbits2; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); p = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, m, qbits); do { fmpq_poly_randtest_not_zero(B, state, n, qbits); } while (B->coeffs[0] == 0); fmpq_poly_div_series(C, A, B, p); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits1); acb_poly_div_series(c, a, b, p, rbits2); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_div_series(d, d, b, p, rbits2); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_div_series(d, a, d, p, rbits2); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_div_series(c, d, d, p, rbits2); acb_poly_div_series(d, d, d, p, rbits2); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 3)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-divrem.c000066400000000000000000000065471461254215100201000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_divrem, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t A, B, Q, R; acb_poly_t a, b, q, r; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(Q); fmpq_poly_init(R); acb_poly_init(a); acb_poly_init(b); acb_poly_init(q); acb_poly_init(r); fmpq_poly_randtest(A, state, m, qbits1); fmpq_poly_randtest_not_zero(B, state, n, qbits2); fmpq_poly_divrem(Q, R, A, B); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_divrem(q, r, a, b, rbits3); if (!acb_poly_contains_fmpq_poly(q, Q) || !acb_poly_contains_fmpq_poly(r, R)) { flint_printf("FAIL\n\n"); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("Q = "); fmpq_poly_print(Q); flint_printf("\n\n"); flint_printf("R = "); fmpq_poly_print(R); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("q = "); acb_poly_printd(q, 15); flint_printf("\n\n"); flint_printf("r = "); acb_poly_printd(r, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_divrem(a, r, a, b, rbits3); if (!acb_poly_equal(a, q)) { flint_printf("FAIL (aliasing q, a)\n\n"); } acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_divrem(b, r, a, b, rbits3); if (!acb_poly_equal(b, q)) { flint_printf("FAIL (aliasing q, b)\n\n"); flint_abort(); } acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_divrem(q, a, a, b, rbits3); if (!acb_poly_equal(a, r)) { flint_printf("FAIL (aliasing r, a)\n\n"); flint_abort(); } acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_divrem(q, b, a, b, rbits3); if (!acb_poly_equal(b, r)) { flint_printf("FAIL (aliasing r, b)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(Q); fmpq_poly_clear(R); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(q); acb_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-elliptic_k_series.c000066400000000000000000000040621461254215100222710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_elliptic_k_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_poly_elliptic_k_series(A, S, n1, bits2); acb_poly_elliptic_k_series(B, S, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_elliptic_k_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-elliptic_p_series.c000066400000000000000000000043541461254215100223020ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_elliptic_p_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; acb_t z; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(z); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_randtest(z, state, bits1, 3); acb_poly_elliptic_p_series(A, S, z, n1, bits2); acb_poly_elliptic_p_series(B, S, z, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_elliptic_p_series(S, S, z, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate.c000066400000000000000000000044751461254215100204160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq_t X, Y; acb_poly_t f; acb_t x, y; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(F); fmpq_init(X); fmpq_init(Y); acb_poly_init(f); acb_init(x); acb_init(y); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); fmpq_randtest(X, state, qbits2); fmpq_poly_evaluate_fmpq(Y, F, X); acb_poly_set_fmpq_poly(f, F, rbits1); acb_set_fmpq(x, X, rbits2); acb_poly_evaluate(y, f, x, rbits3); if (!acb_contains_fmpq(y, Y)) { flint_printf("FAIL\n\n"); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y); flint_printf("\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 15); flint_printf("\n\n"); flint_abort(); } /* aliasing */ acb_poly_evaluate(x, f, x, rbits3); if (!acb_contains_fmpq(x, Y)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(F); fmpq_clear(X); fmpq_clear(Y); acb_poly_clear(f); acb_clear(x); acb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate2.c000066400000000000000000000041321461254215100204660ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate2, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t f, g; acb_t x, y1, z1, y2, z2; acb_init(x); acb_init(y1); acb_init(z1); acb_init(y2); acb_init(z2); acb_poly_init(f); acb_poly_init(g); acb_randtest(x, state, 2 + n_randint(state, 1000), 5); acb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); acb_poly_derivative(g, f, 2 + n_randint(state, 1000)); acb_poly_evaluate2(y1, z1, f, x, 2 + n_randint(state, 1000)); acb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); acb_poly_evaluate_horner(z2, g, x, 2 + n_randint(state, 1000)); if (!acb_overlaps(y1, y2) || !acb_overlaps(z1, z2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); acb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("y2 = "); acb_printd(y2, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_clear(x); acb_clear(y1); acb_clear(z1); acb_clear(y2); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate2_horner.c000066400000000000000000000041501461254215100220430ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate2_horner, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t f, g; acb_t x, y1, z1, y2, z2; acb_init(x); acb_init(y1); acb_init(z1); acb_init(y2); acb_init(z2); acb_poly_init(f); acb_poly_init(g); acb_randtest(x, state, 2 + n_randint(state, 1000), 5); acb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); acb_poly_derivative(g, f, 2 + n_randint(state, 1000)); acb_poly_evaluate2_horner(y1, z1, f, x, 2 + n_randint(state, 1000)); acb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); acb_poly_evaluate_horner(z2, g, x, 2 + n_randint(state, 1000)); if (!acb_overlaps(y1, y2) || !acb_overlaps(z1, z2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); acb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("y2 = "); acb_printd(y2, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_clear(x); acb_clear(y1); acb_clear(z1); acb_clear(y2); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate2_rectangular.c000066400000000000000000000041621461254215100230600ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate2_rectangular, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t f, g; acb_t x, y1, z1, y2, z2; acb_init(x); acb_init(y1); acb_init(z1); acb_init(y2); acb_init(z2); acb_poly_init(f); acb_poly_init(g); acb_randtest(x, state, 2 + n_randint(state, 1000), 5); acb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); acb_poly_derivative(g, f, 2 + n_randint(state, 1000)); acb_poly_evaluate2_rectangular(y1, z1, f, x, 2 + n_randint(state, 1000)); acb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); acb_poly_evaluate_horner(z2, g, x, 2 + n_randint(state, 1000)); if (!acb_overlaps(y1, y2) || !acb_overlaps(z1, z2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); acb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("y2 = "); acb_printd(y2, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_clear(x); acb_clear(y1); acb_clear(z1); acb_clear(y2); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate_horner.c000066400000000000000000000045221461254215100217640ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate_horner, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq_t X, Y; acb_poly_t f; acb_t x, y; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(F); fmpq_init(X); fmpq_init(Y); acb_poly_init(f); acb_init(x); acb_init(y); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); fmpq_randtest(X, state, qbits2); fmpq_poly_evaluate_fmpq(Y, F, X); acb_poly_set_fmpq_poly(f, F, rbits1); acb_set_fmpq(x, X, rbits2); acb_poly_evaluate_horner(y, f, x, rbits3); if (!acb_contains_fmpq(y, Y)) { flint_printf("FAIL\n\n"); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y); flint_printf("\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 15); flint_printf("\n\n"); flint_abort(); } /* aliasing */ acb_poly_evaluate_horner(x, f, x, rbits3); if (!acb_contains_fmpq(x, Y)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(F); fmpq_clear(X); fmpq_clear(Y); acb_poly_clear(f); acb_clear(x); acb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate_rectangular.c000066400000000000000000000031071461254215100227740ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate_rectangular, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t f; acb_t x, y1, y2; acb_init(x); acb_init(y1); acb_init(y2); acb_poly_init(f); acb_randtest(x, state, 2 + n_randint(state, 1000), 5); acb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); acb_poly_evaluate_rectangular(y1, f, x, 2 + n_randint(state, 1000)); acb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); if (!acb_overlaps(y1, y2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 15); flint_printf("\n\n"); flint_printf("y2 = "); acb_printd(y2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(f); acb_clear(x); acb_clear(y1); acb_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate_vec_fast.c000066400000000000000000000050321461254215100222560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate_vec_fast, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq * X, * Y; acb_poly_t f; acb_ptr x, y; qbits1 = 2 + n_randint(state, 100); qbits2 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); n = n_randint(state, 10); fmpq_poly_init(F); X = _fmpq_vec_init(n); Y = _fmpq_vec_init(n); acb_poly_init(f); x = _acb_vec_init(n); y = _acb_vec_init(n); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); for (i = 0; i < n; i++) fmpq_randtest(X + i, state, qbits2); for (i = 0; i < n; i++) fmpq_poly_evaluate_fmpq(Y + i, F, X + i); acb_poly_set_fmpq_poly(f, F, rbits1); for (i = 0; i < n; i++) acb_set_fmpq(x + i, X + i, rbits2); acb_poly_evaluate_vec_fast(y, f, x, n, rbits3); for (i = 0; i < n; i++) { if (!acb_contains_fmpq(y + i, Y + i)) { flint_printf("FAIL (%wd of %wd)\n\n", i, n); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X + i); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y + i); flint_printf("\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x + i, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y + i, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_poly_clear(F); _fmpq_vec_clear(X, n); _fmpq_vec_clear(Y, n); acb_poly_clear(f); _acb_vec_clear(x, n); _acb_vec_clear(y, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-evaluate_vec_iter.c000066400000000000000000000050321461254215100222640ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_evaluate_vec_iter, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq * X, * Y; acb_poly_t f; acb_ptr x, y; qbits1 = 2 + n_randint(state, 100); qbits2 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); n = n_randint(state, 10); fmpq_poly_init(F); X = _fmpq_vec_init(n); Y = _fmpq_vec_init(n); acb_poly_init(f); x = _acb_vec_init(n); y = _acb_vec_init(n); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); for (i = 0; i < n; i++) fmpq_randtest(X + i, state, qbits2); for (i = 0; i < n; i++) fmpq_poly_evaluate_fmpq(Y + i, F, X + i); acb_poly_set_fmpq_poly(f, F, rbits1); for (i = 0; i < n; i++) acb_set_fmpq(x + i, X + i, rbits2); acb_poly_evaluate_vec_iter(y, f, x, n, rbits3); for (i = 0; i < n; i++) { if (!acb_contains_fmpq(y + i, Y + i)) { flint_printf("FAIL (%wd of %wd)\n\n", i, n); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X + i); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y + i); flint_printf("\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x + i, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y + i, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_poly_clear(F); _fmpq_vec_clear(X, n); _fmpq_vec_clear(Y, n); acb_poly_clear(f); _acb_vec_clear(x, n); _acb_vec_clear(y, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-exp_pi_i_series.c000066400000000000000000000037721461254215100217550ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_exp_pi_i_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, prec; acb_poly_t a, b, c; acb_t t; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_init(t); prec = 2 + n_randint(state, 100); acb_poly_randtest(a, state, 1 + n_randint(state, 20), prec, 5); acb_poly_randtest(b, state, 1 + n_randint(state, 20), prec, 5); acb_poly_randtest(c, state, 1 + n_randint(state, 20), prec, 5); m = n_randint(state, 20); n = n_randint(state, 20); if (n_randint(state, 2) == 0) acb_poly_exp_pi_i_series(b, a, m, prec); else { acb_poly_set(b, a); acb_poly_exp_pi_i_series(b, b, m, prec); } acb_const_pi(t, prec); acb_mul_onei(t, t); acb_poly_scalar_mul(c, a, t, prec); acb_poly_exp_series(c, c, n, prec); acb_poly_truncate(b, FLINT_MIN(m, n)); acb_poly_truncate(c, FLINT_MIN(m, n)); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-exp_series.c000066400000000000000000000046221461254215100207500ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" FLINT_DLL extern slong acb_poly_newton_exp_cutoff; TEST_FUNCTION_START(acb_poly_exp_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, bits1, bits2, bits3; acb_poly_t a, b, c, d; bits1 = 2 + n_randint(state, 100); bits2 = 2 + n_randint(state, 100); bits3 = 2 + n_randint(state, 100); if (iter > 1000) { acb_poly_newton_exp_cutoff = 5 + n_randint(state, 50); } if (n_randint(state, 100) == 0) { m = 1 + n_randint(state, 100); n = 1 + n_randint(state, 100); } else { m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); } acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, m, bits1, 5); acb_poly_randtest(b, state, m, bits1, 5); acb_poly_randtest(c, state, 1 + n_randint(state, 300), bits1, 10); acb_poly_randtest(d, state, 1 + n_randint(state, 300), bits1, 10); /* check exp(a+b) = exp(a) exp(b) */ acb_poly_exp_series(c, a, n, bits2); acb_poly_exp_series(d, b, n, bits2); acb_poly_mullow(c, c, d, n, bits2); acb_poly_add(d, a, b, bits3); acb_poly_exp_series(d, d, n, bits3); /* also aliasing test */ if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-exp_series_basecase.c000066400000000000000000000036771461254215100226070ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_exp_series_basecase, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, bits1, bits2, bits3; acb_poly_t a, b, c, d; bits1 = 2 + n_randint(state, 100); bits2 = 2 + n_randint(state, 100); bits3 = 2 + n_randint(state, 100); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, m, bits1, 5); acb_poly_randtest(b, state, m, bits1, 5); /* check exp(a+b) = exp(a) exp(b) */ acb_poly_exp_series_basecase(c, a, n, bits2); acb_poly_exp_series_basecase(d, b, n, bits2); acb_poly_mullow(c, c, d, n, bits2); acb_poly_add(d, a, b, bits3); acb_poly_exp_series_basecase(d, d, n, bits3); /* also aliasing test */ if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-find_roots.c000066400000000000000000000047531461254215100207550ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_find_roots, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t A; acb_poly_t B; acb_poly_t C; acb_t t; acb_ptr roots; slong i, deg, isolated; slong prec = 10 + n_randint(state, 400); acb_init(t); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); do { acb_poly_randtest(A, state, 2 + n_randint(state, 15), prec, 5); } while (A->length == 0); deg = A->length - 1; roots = _acb_vec_init(deg); isolated = acb_poly_find_roots(roots, A, NULL, 0, prec); if (isolated == deg) { acb_poly_fit_length(B, 1); acb_set(B->coeffs, A->coeffs + deg); _acb_poly_set_length(B, 1); for (i = 0; i < deg; i++) { acb_poly_fit_length(C, 2); acb_one(C->coeffs + 1); acb_neg(C->coeffs + 0, roots + i); _acb_poly_set_length(C, 2); acb_poly_mul(B, B, C, prec); } if (!acb_poly_contains(B, A)) { flint_printf("FAIL: product does not equal polynomial\n"); acb_poly_printd(A, 15); flint_printf("\n\n"); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } } for (i = 0; i < isolated; i++) { acb_poly_evaluate(t, A, roots + i, prec); if (!acb_contains_zero(t)) { flint_printf("FAIL: poly(root) does not contain zero\n"); acb_poly_printd(A, 15); flint_printf("\n\n"); acb_printd(roots + i, 15); flint_printf("\n\n"); acb_printd(t, 15); flint_printf("\n\n"); flint_abort(); } } _acb_vec_clear(roots, deg); acb_clear(t); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-gamma_series.c000066400000000000000000000055301461254215100212350ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_gamma_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; acb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 25); n1 = 1 + n_randint(state, 25); n2 = 1 + n_randint(state, 25); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, m, rbits1, 3); acb_poly_randtest(b, state, m, rbits1, 3); acb_poly_randtest(c, state, m, rbits1, 3); acb_poly_gamma_series(b, a, n1, rbits2); acb_poly_gamma_series(c, a, n2, rbits3); acb_poly_set(d, b); acb_poly_truncate(d, FLINT_MIN(n1, n2)); acb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check gamma(a) * a = gamma(a+1) */ acb_poly_mullow(c, b, a, n1, rbits2); acb_poly_set(d, a); acb_add_ui(d->coeffs, d->coeffs, 1, rbits2); acb_poly_gamma_series(d, d, n1, rbits2); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation, n1 = %wd)\n\n", n1); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_gamma_series(a, a, n1, rbits2); if (!acb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-get_coeff_ptr.c000066400000000000000000000025431461254215100214100ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_get_coeff_ptr, state) { int i, result; for (i = 0; i < 1000; i++) { acb_poly_t A; acb_t a; slong n = n_randint(state, 100); acb_poly_init(A); acb_poly_randtest(A, state, n_randint(state, 100), 100, 10); acb_init(a); acb_poly_get_coeff_acb(a, A, n); result = n < acb_poly_length(A) ? acb_equal(a, acb_poly_get_coeff_ptr(A, n)) : acb_poly_get_coeff_ptr(A, n) == NULL; if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), acb_poly_printd(A, 10), flint_printf("\n\n"); flint_printf("a = "), acb_print(a), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_abort(); } acb_poly_clear(A); acb_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-get_set_coeff_acb.c000066400000000000000000000027761461254215100222130ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_get_set_coeff_acb, state) { int i, j, result; for (i = 0; i < 100; i++) { acb_poly_t a; acb_t x1, x2; slong coeff, len; acb_poly_init(a); acb_init(x1); acb_init(x2); len = n_randint(state, 100) + 1; for (j = 0; j < 100; j++) { acb_randtest(x1, state, 2 + n_randint(state, 200), 10); coeff = n_randint(state, len); acb_poly_set_coeff_acb(a, coeff, x1); acb_poly_get_coeff_acb(x2, a, coeff); result = (acb_equal(x1, x2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x1 = "), acb_print(x1), flint_printf("\n"); flint_printf("x2 = "), acb_print(x2), flint_printf("\n"); flint_printf("coeff = %wd, length = %wd\n", coeff, len); flint_abort(); } } acb_clear(x1); acb_clear(x2); acb_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-get_unique_fmpz_poly.c000066400000000000000000000042651461254215100230510ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_get_unique_fmpz_poly, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong prec, c; fmpz_poly_t A, B, C; acb_poly_t a, b; fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_init(C); acb_poly_init(a); acb_poly_init(b); fmpz_poly_randtest(A, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000)); fmpz_poly_randtest(B, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000)); fmpz_poly_randtest(C, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000)); c = 1 + n_randint(state, 1000); prec = 2 + n_randint(state, 100); for ( ; ; ) { acb_poly_set_fmpz_poly(a, A, prec); acb_poly_set2_fmpz_poly(b, B, C, prec); acb_poly_scalar_mul_2exp_si(b, b, -c); acb_poly_add(a, a, b, prec); acb_poly_sub(a, a, b, prec); if (acb_poly_get_unique_fmpz_poly(B, a)) { if (!fmpz_poly_equal(A, B)) { flint_printf("FAIL\n\n"); flint_printf("A = "); fmpz_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpz_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_abort(); } break; } else { prec *= 2; } } fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-graeffe_transform.c000066400000000000000000000047101461254215100222720ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_graeffe_transform, state) { slong iter; acb_poly_t a, b, c; acb_ptr roots; acb_t leading; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_init(leading); for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong n, prec, i; n = n_randint(state, 20); prec = 2 + n_randint(state, 256); roots = _acb_vec_init(n); acb_randtest(leading, state, prec, n_randint(state, 16)); for (i = 0; i < n; i++) acb_randtest(roots + i, state, prec, n_randint(state, 16)); acb_poly_product_roots(a, roots, n, prec); acb_poly_scalar_mul(a, a, leading, prec); for (i = 0; i < n; i++) acb_sqr(roots + i, roots + i, prec); acb_sqr(leading, leading, prec); acb_poly_product_roots(c, roots, n, prec); acb_poly_scalar_mul(c, c, leading, prec); acb_poly_graeffe_transform(b, a, prec); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_graeffe_transform(a, a, prec); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } _acb_vec_clear(roots, n); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_clear(leading); TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-interpolate_barycentric.c000066400000000000000000000046261461254215100235210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_interpolate_barycentric, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t P; acb_poly_t R, S; fmpq_t t, u; acb_ptr xs, ys; fmpq_poly_init(P); acb_poly_init(R); acb_poly_init(S); fmpq_init(t); fmpq_init(u); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 5); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_randtest(P, state, 1 + n_randint(state, 20), qbits1); n = P->length; xs = _acb_vec_init(n); ys = _acb_vec_init(n); acb_poly_set_fmpq_poly(R, P, rbits1); if (n > 0) { fmpq_randtest(t, state, qbits2); acb_set_fmpq(xs, t, rbits2); for (i = 1; i < n; i++) { fmpq_randtest_not_zero(u, state, qbits2); fmpq_abs(u, u); fmpq_add(t, t, u); acb_set_fmpq(xs + i, t, rbits2); } } for (i = 0; i < n; i++) acb_poly_evaluate(ys + i, R, xs + i, rbits2); acb_poly_interpolate_barycentric(S, xs, ys, n, rbits3); if (!acb_poly_contains_fmpq_poly(S, P)) { flint_printf("FAIL:\n"); flint_printf("P = "); fmpq_poly_print(P); flint_printf("\n\n"); flint_printf("R = "); acb_poly_printd(R, 15); flint_printf("\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(P); acb_poly_clear(R); acb_poly_clear(S); fmpq_clear(t); fmpq_clear(u); _acb_vec_clear(xs, n); _acb_vec_clear(ys, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-interpolate_fast.c000066400000000000000000000046101461254215100221420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_interpolate_fast, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t P; acb_poly_t R, S; fmpq_t t, u; acb_ptr xs, ys; fmpq_poly_init(P); acb_poly_init(R); acb_poly_init(S); fmpq_init(t); fmpq_init(u); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 5); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_randtest(P, state, 1 + n_randint(state, 20), qbits1); n = P->length; xs = _acb_vec_init(n); ys = _acb_vec_init(n); acb_poly_set_fmpq_poly(R, P, rbits1); if (n > 0) { fmpq_randtest(t, state, qbits2); acb_set_fmpq(xs, t, rbits2); for (i = 1; i < n; i++) { fmpq_randtest_not_zero(u, state, qbits2); fmpq_abs(u, u); fmpq_add(t, t, u); acb_set_fmpq(xs + i, t, rbits2); } } for (i = 0; i < n; i++) acb_poly_evaluate(ys + i, R, xs + i, rbits2); acb_poly_interpolate_fast(S, xs, ys, n, rbits3); if (!acb_poly_contains_fmpq_poly(S, P)) { flint_printf("FAIL:\n"); flint_printf("P = "); fmpq_poly_print(P); flint_printf("\n\n"); flint_printf("R = "); acb_poly_printd(R, 15); flint_printf("\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(P); acb_poly_clear(R); acb_poly_clear(S); fmpq_clear(t); fmpq_clear(u); _acb_vec_clear(xs, n); _acb_vec_clear(ys, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-interpolate_newton.c000066400000000000000000000046141461254215100225230ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_interpolate_newton, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t P; acb_poly_t R, S; fmpq_t t, u; acb_ptr xs, ys; fmpq_poly_init(P); acb_poly_init(R); acb_poly_init(S); fmpq_init(t); fmpq_init(u); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 5); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_randtest(P, state, 1 + n_randint(state, 20), qbits1); n = P->length; xs = _acb_vec_init(n); ys = _acb_vec_init(n); acb_poly_set_fmpq_poly(R, P, rbits1); if (n > 0) { fmpq_randtest(t, state, qbits2); acb_set_fmpq(xs, t, rbits2); for (i = 1; i < n; i++) { fmpq_randtest_not_zero(u, state, qbits2); fmpq_abs(u, u); fmpq_add(t, t, u); acb_set_fmpq(xs + i, t, rbits2); } } for (i = 0; i < n; i++) acb_poly_evaluate(ys + i, R, xs + i, rbits2); acb_poly_interpolate_newton(S, xs, ys, n, rbits3); if (!acb_poly_contains_fmpq_poly(S, P)) { flint_printf("FAIL:\n"); flint_printf("P = "); fmpq_poly_print(P); flint_printf("\n\n"); flint_printf("R = "); acb_poly_printd(R, 15); flint_printf("\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(P); acb_poly_clear(R); acb_poly_clear(S); fmpq_clear(t); fmpq_clear(u); _acb_vec_clear(xs, n); _acb_vec_clear(ys, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-inv_series.c000066400000000000000000000064321461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_inv_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; acb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); acb_poly_init(a); acb_poly_init(b); do { fmpq_poly_randtest_not_zero(A, state, m, qbits); } while (A->coeffs[0] == 0); fmpq_poly_inv_series(B, A, n); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_inv_series(b, a, n, rbits2); if (!acb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_inv_series(a, a, n, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); } /* check f * f^-1 = 1 */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, trunc; acb_poly_t a, b, ab; fmpq_poly_t id; bits = 2 + n_randint(state, 200); trunc = 1 + n_randint(state, 10); acb_poly_init(a); acb_poly_init(b); acb_poly_init(ab); fmpq_poly_init(id); do { acb_poly_randtest(a, state, 1 + n_randint(state, 10), bits, 5); } while (a->length == 0 || acb_contains_zero(a->coeffs + 0)); acb_poly_inv_series(b, a, trunc, bits); acb_poly_mullow(ab, a, b, trunc, bits); fmpq_poly_set_ui(id, 1); if (!acb_poly_contains_fmpq_poly(ab, id)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("ab = "); acb_poly_printd(ab, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(ab); fmpq_poly_clear(id); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-lambertw_series.c000066400000000000000000000105141461254215100217660ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_lambertw_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t x1, x2, t, w1, w2; slong prec1, prec2, n1, n2, ebits; fmpz_t k; acb_poly_init(x1); acb_poly_init(x2); acb_poly_init(t); acb_poly_init(w1); acb_poly_init(w2); fmpz_init(k); n1 = n_randint(state, 15); n2 = n_randint(state, 15); if (n_randint(state, 4) == 0) { prec1 = 2 + n_randint(state, 3000); prec2 = 2 + n_randint(state, 3000); ebits = 1 + n_randint(state, 1000); } else { prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 50); } fmpz_randtest(k, state, ebits); acb_poly_randtest(x1, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); acb_poly_randtest(x2, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); acb_poly_randtest(t, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); acb_poly_randtest(w1, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); acb_poly_randtest(w2, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); if (n_randint(state, 4) == 0) { acb_t u; acb_init(u); arb_const_e(acb_realref(u), 2 * prec1); acb_inv(u, u, 2 * prec1); acb_poly_set_acb(t, u); acb_poly_sub(x1, x1, t, 2 * prec1); acb_clear(u); } if (n_randint(state, 2)) { acb_poly_set(x2, x1); } else { acb_poly_add(x2, x1, t, 2 * prec1); acb_poly_sub(x2, x2, t, 2 * prec1); } acb_poly_lambertw_series(w1, x1, k, 0, n1, prec1); if (n_randint(state, 2)) { acb_poly_set(w2, x2); acb_poly_lambertw_series(w2, w2, k, 0, n2, prec1); } else { acb_poly_lambertw_series(w2, x2, k, 0, n2, prec1); } acb_poly_truncate(w1, FLINT_MIN(n1, n2)); acb_poly_truncate(w2, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(w1, w2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter %wd, branch = ", iter); fmpz_print(k); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); acb_poly_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); acb_poly_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); acb_poly_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_poly_printd(w2, 50); flint_printf("\n\n"); flint_abort(); } acb_poly_exp_series(t, w1, FLINT_MIN(n1, n2), prec1); acb_poly_mullow(t, t, w1, FLINT_MIN(n1, n2), prec1); acb_poly_truncate(x1, FLINT_MIN(n1, n2)); if (!acb_poly_contains(t, x1)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("iter %wd, branch = ", iter); fmpz_print(k); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); acb_poly_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); acb_poly_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); acb_poly_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); acb_poly_printd(w2, 50); flint_printf("\n\n"); flint_printf("t = "); acb_poly_printd(t, 50); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(x1); acb_poly_clear(x2); acb_poly_clear(t); acb_poly_clear(w1); acb_poly_clear(w2); fmpz_clear(k); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-lgamma_series.c000066400000000000000000000071721461254215100214150ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_lgamma_series, state) { slong iter; /* special accuracy test case */ { acb_poly_t a; acb_t c; acb_init(c); acb_poly_init(a); arb_set_str(acb_realref(c), "-20.25", 53); arb_set_str(acb_imagref(c), "1e1000", 53); acb_poly_set_coeff_acb(a, 0, c); acb_poly_set_coeff_si(a, 1, 1); acb_poly_lgamma_series(a, a, 3, 53); if (acb_rel_accuracy_bits(a->coeffs) < 40 || acb_rel_accuracy_bits(a->coeffs + 1) < 40 || acb_rel_accuracy_bits(a->coeffs + 2) < 40) { flint_printf("FAIL: accuracy (reflection formula)\n\n"); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_clear(c); } for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; acb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, m, rbits1, 10); acb_poly_randtest(b, state, m, rbits1, 10); acb_poly_randtest(c, state, m, rbits1, 10); acb_poly_lgamma_series(b, a, n1, rbits2); acb_poly_lgamma_series(c, a, n2, rbits3); acb_poly_set(d, b); acb_poly_truncate(d, FLINT_MIN(n1, n2)); acb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check loggamma(a) + log(a) = loggamma(a+1) */ acb_poly_log_series(c, a, n1, rbits2); acb_poly_add(c, b, c, rbits2); acb_poly_set(d, a); acb_add_ui(d->coeffs, d->coeffs, 1, rbits2); acb_poly_lgamma_series(d, d, n1, rbits2); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_lgamma_series(a, a, n1, rbits2); if (!acb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-log1p_series.c000066400000000000000000000037121461254215100211750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_log1p_series, state) { slong iter; /* compare with log_series */ for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c; slong m, n, prec; prec = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_randtest(a, state, 1 + n_randint(state, 10), prec, 5); acb_poly_randtest(b, state, 1 + n_randint(state, 10), prec, 5); acb_poly_randtest(c, state, 1 + n_randint(state, 10), prec, 5); if (n_randint(state, 2)) acb_poly_log1p_series(b, a, n, prec); else { acb_poly_set(b, a); acb_poly_log1p_series(b, b, n, prec); } acb_poly_add_si(c, a, 1, prec); acb_poly_log_series(c, c, m, prec); acb_poly_truncate(b, FLINT_MIN(m, n)); acb_poly_truncate(c, FLINT_MIN(m, n)); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd\n\n", m, n); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-log_series.c000066400000000000000000000114331461254215100207330ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_log_series, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; acb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); acb_poly_init(a); acb_poly_init(b); fmpq_poly_randtest_not_zero(A, state, m, qbits); fmpq_poly_set_coeff_ui(A, 0, UWORD(1)); fmpq_poly_log_series(B, A, n); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); acb_poly_log_series(b, a, n, rbits2); if (!acb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); } /* test aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; acb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); acb_poly_init(a); acb_poly_init(b); do { fmpq_poly_randtest_not_zero(A, state, m, qbits); } while (fmpz_sgn(A->coeffs + 0) <= 0); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_log_series(b, a, n, rbits2); acb_poly_log_series(a, a, n, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); acb_poly_clear(a); acb_poly_clear(b); } /* test that exp(log(f)) contains f */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2, rbits3; fmpq_poly_t A; acb_poly_t a, b, c; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); do { fmpq_poly_randtest_not_zero(A, state, m, qbits); } while (fmpz_sgn(A->coeffs + 0) <= 0); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); acb_poly_log_series(b, a, n, rbits2); acb_poly_exp_series_basecase(c, b, n, rbits3); fmpq_poly_truncate(A, n); if (!acb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-mullow.c000066400000000000000000000120721461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_mullow, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_mullow(C, A, B, trunc); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_mullow(c, a, b, trunc, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_mullow(d, d, b, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_mullow(d, a, d, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ acb_poly_set(b, a); acb_poly_mullow(c, a, b, trunc, rbits3); acb_poly_mullow(d, a, a, trunc, rbits3); if (!acb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_mullow(a, a, a, trunc, rbits3); if (!acb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } /* compare with classical */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, trunc; acb_poly_t a, b, ab, ab2; bits = 2 + n_randint(state, 200); trunc = n_randint(state, 10); acb_poly_init(a); acb_poly_init(b); acb_poly_init(ab); acb_poly_init(ab2); acb_poly_randtest(a, state, 1 + n_randint(state, 10), bits, 5); acb_poly_randtest(b, state, 1 + n_randint(state, 10), bits, 5); acb_poly_mullow_classical(ab, a, b, trunc, bits); acb_poly_mullow(ab2, a, b, trunc, bits); if (!acb_poly_overlaps(ab, ab2)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("ab = "); acb_poly_printd(ab, 15); flint_printf("\n\n"); flint_printf("ab2 = "); acb_poly_printd(ab2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(ab); acb_poly_clear(ab2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-mullow_classical.c000066400000000000000000000132421461254215100221350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_mullow_classical, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_mullow(C, A, B, trunc); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_mullow_classical(c, a, b, trunc, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_mullow_classical(d, d, b, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_mullow_classical(d, a, d, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ acb_poly_set(b, a); acb_poly_mullow_classical(c, a, b, trunc, rbits3); acb_poly_mullow_classical(d, a, a, trunc, rbits3); if (!acb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_mullow_classical(a, a, a, trunc, rbits3); if (!acb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } /* check a*(b+c) = a*b+a*c */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, trunc; acb_poly_t a, b, c, bc, abc, ab, ac, abac; bits = 2 + n_randint(state, 200); trunc = n_randint(state, 10); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(bc); acb_poly_init(abc); acb_poly_init(ab); acb_poly_init(ac); acb_poly_init(abac); acb_poly_randtest(a, state, 1 + n_randint(state, 10), bits, 5); acb_poly_randtest(b, state, 1 + n_randint(state, 10), bits, 5); acb_poly_randtest(c, state, 1 + n_randint(state, 10), bits, 5); acb_poly_add(bc, b, c, bits); acb_poly_mullow_classical(abc, a, bc, trunc, bits); acb_poly_mullow_classical(ab, a, b, trunc, bits); acb_poly_mullow_classical(ac, a, c, trunc, bits); acb_poly_add(abac, ab, ac, bits); if (!acb_poly_overlaps(abc, abac)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("abc = "); acb_poly_printd(abc, 15); flint_printf("\n\n"); flint_printf("abac = "); acb_poly_printd(abac, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(bc); acb_poly_clear(abc); acb_poly_clear(ab); acb_poly_clear(ac); acb_poly_clear(abac); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-mullow_transpose.c000066400000000000000000000122121461254215100222110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_mullow_transpose, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_mullow(C, A, B, trunc); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_mullow_transpose(c, a, b, trunc, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_mullow_transpose(d, d, b, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_mullow_transpose(d, a, d, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ acb_poly_set(b, a); acb_poly_mullow_transpose(c, a, b, trunc, rbits3); acb_poly_mullow_transpose(d, a, a, trunc, rbits3); if (!acb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_mullow_transpose(a, a, a, trunc, rbits3); if (!acb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } /* compare with classical */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, trunc; acb_poly_t a, b, ab, ab2; bits = 2 + n_randint(state, 200); trunc = n_randint(state, 10); acb_poly_init(a); acb_poly_init(b); acb_poly_init(ab); acb_poly_init(ab2); acb_poly_randtest(a, state, 1 + n_randint(state, 10), bits, 5); acb_poly_randtest(b, state, 1 + n_randint(state, 10), bits, 5); acb_poly_mullow_classical(ab, a, b, trunc, bits); acb_poly_mullow_transpose(ab2, a, b, trunc, bits); if (!acb_poly_overlaps(ab, ab2)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("ab = "); acb_poly_printd(ab, 15); flint_printf("\n\n"); flint_printf("ab2 = "); acb_poly_printd(ab2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(ab); acb_poly_clear(ab2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-mullow_transpose_gauss.c000066400000000000000000000122721461254215100234210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_mullow_transpose_gauss, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_mullow(C, A, B, trunc); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_mullow_transpose_gauss(c, a, b, trunc, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_mullow_transpose_gauss(d, d, b, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_mullow_transpose_gauss(d, a, d, trunc, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ acb_poly_set(b, a); acb_poly_mullow_transpose_gauss(c, a, b, trunc, rbits3); acb_poly_mullow_transpose_gauss(d, a, a, trunc, rbits3); if (!acb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_mullow_transpose_gauss(a, a, a, trunc, rbits3); if (!acb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } /* compare with classical */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, trunc; acb_poly_t a, b, ab, ab2; bits = 2 + n_randint(state, 200); trunc = n_randint(state, 10); acb_poly_init(a); acb_poly_init(b); acb_poly_init(ab); acb_poly_init(ab2); acb_poly_randtest(a, state, 1 + n_randint(state, 10), bits, 5); acb_poly_randtest(b, state, 1 + n_randint(state, 10), bits, 5); acb_poly_mullow_classical(ab, a, b, trunc, bits); acb_poly_mullow_transpose_gauss(ab2, a, b, trunc, bits); if (!acb_poly_overlaps(ab, ab2)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("ab = "); acb_poly_printd(ab, 15); flint_printf("\n\n"); flint_printf("ab2 = "); acb_poly_printd(ab2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(ab); acb_poly_clear(ab2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-polylog_cpx.c000066400000000000000000000316611461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define EPS 1e-13 #define NUM_DERIVS 3 #define NUM_TESTS 56 const double polylog_testdata[NUM_TESTS][10] = { {-2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {-2.0, 0.0, -0.5, 0.0, -0.0740740740740740741, 0.0, -0.158799035455864473, 0.0, 0.00278425812292977954, 0.0}, {-2.0, 0.0, 0.99609375, 0.0, 33358080.0, 0.0, -215693527.719090182, 0.0, 703924885.809675425, 0.0}, {-2.0, 0.0, 1.00390625, 0.0, -33751296.0, 0.0, 218367905.967311029, -106032823.56283664, -546519337.1290267, 686023009.262281684}, {-2.0, 0.0, -4.25, 0.0, 0.0954540546377281071, 0.0, -0.0297817299750221174, 0.0, -0.196648773789941696, 0.0}, {-2.0, 0.0, 3.5, 0.0, -1.008, 0.0, 0.691243661008350802, -3.19575256895409845, 4.53340070033764442, 2.22882281653983385}, {-2.0, 0.0, 0.0, -1.0, 0.0, 0.5, -0.852556797635011582, -0.25189536315108886, 0.345626503121598963, -0.46292146649778986}, {-2.0, 0.0, 0.125, 0.125, 0.071424, 0.280832, 0.0646851488459364134, -0.118051747326526959, -0.0396751348737248634, 0.0452067417426917285}, {-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {-1.0, 0.0, -0.5, 0.0, -0.222222222222222222, 0.0, -0.131883201632587537, 0.0, 0.0199225628389378777, 0.0}, {-1.0, 0.0, 0.99609375, 0.0, 65280.0, 0.0, -389461.499432291984, 0.0, 1182814.77437627002, 0.0}, {-1.0, 0.0, 1.00390625, 0.0, 65792.0, 0.0, -392773.095775796478, 206691.925664168516, 868954.597422132011, -1233932.55215831045}, {-1.0, 0.0, -4.25, 0.0, -0.154195011337868481, 0.0, -0.474824989764482489, 0.0, -0.21428706813151403, 0.0}, {-1.0, 0.0, 3.5, 0.0, 0.56, 0.0, -0.322735710701998933, 2.00176023742981729, -3.09698193717149541, -0.395213225234415973}, {-1.0, 0.0, 0.0, -1.0, -0.5, 0.0, -0.183855151549436048, -0.58312180806163756, 0.254077251327014729, 0.0351429519611278982}, {-1.0, 0.0, 0.125, 0.125, 0.1088, 0.1984, 0.0192018441183911, -0.0548368329876085499, -0.0115465156713130216, 0.020954643261003461}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, -0.5, 0.0, -0.333333333333333333, 0.0, -0.0904116649848191551, 0.0, 0.0199028637728058217, 0.0}, {0.0, 0.0, 0.99609375, 0.0, 255.0, 0.0, -1269.73106874463507, 0.0, 3359.60296533314103, 0.0}, {0.0, 0.0, 1.00390625, 0.0, -257.0, 0.0, 1273.86116119868176, -805.817494984366455, -2113.9649224353639, 4004.84182305521042}, {0.0, 0.0, -4.25, 0.0, -0.809523809523809524, 0.0, -0.795769271870623909, 0.0, -0.0965372637237445457, 0.0}, {0.0, 0.0, 3.5, 0.0, -1.4, 0.0, -1.78816683065098841, -2.50773109725857055, 1.83790031889197745, -2.01262260402527512}, {0.0, 0.0, 0.0, -1.0, -0.5, -0.5, 0.120782237635245222, -0.391594392706836776, 0.0669079578849868665, 0.116416441749488305}, {0.0, 0.0, 0.125, 0.125, 0.12, 0.16, 0.00583206536388767829, -0.0256940749384562616, -0.00344424777009813297, 0.00965046958017889366}, {-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {-0.5, 0.0, -0.5, 0.0, -0.283012810746506023, 0.0, -0.111080563146094489, 0.0, 0.0211430885590715694, 0.0}, {-0.5, 0.0, 0.99609375, 0.0, 3619.14124113924805, 0.0, -20195.2825251289493, 0.0, 58032.3050555790807, 0.0}, {-0.5, 0.0, 1.00390625, 0.0, -0.207985517845521836, 3640.61848390552728, -11437.7014354502895, -20327.8206114649109, 63861.4335397379033, 40487.2831296029499}, {-0.5, 0.0, -4.25, 0.0, -0.441427843410865187, 0.0, -0.665497904840929966, 0.0, -0.162969337925229287, 0.0}, {-0.5, 0.0, 3.5, 0.0, -0.232043460812781422, 0.63203565652521718, -2.44367789279529917, 0.119367210264842707, -0.763914228371074801, -2.81228485141461073}, {-0.5, 0.0, 0.0, -1.0, -0.537549381115898973, -0.27517974122882025, 0.0158915835170861709, -0.505981074388456133, 0.147999289996985447, 0.105632732120539676}, {-0.5, 0.0, 0.125, 0.125, 0.116021225799463628, 0.175602658223910358, 0.0105539353881710306, -0.0374742285737420805, -0.0062875342272019156, 0.0142081398192247589}, {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {1.0, 0.0, -0.5, 0.0, -0.405465108108164382, 0.0, -0.0556552111040376179, 0.0, 0.0145754167941056437, 0.0}, {1.0, 0.0, 0.99609375, 0.0, 5.54517744447956248, 0.0, -13.0766609768056118, 0.0, 24.0940545588450487, 0.0}, {1.0, 0.0, 1.00390625, 0.0, 5.54517744447956248, -3.14159265358979324, -8.16844417312495553, 15.6134381896777968, -0.38789687903338657, -36.2148484363837508}, {1.0, 0.0, -4.25, 0.0, -1.65822807660353238, 0.0, -0.861140718490863904, 0.0, 0.0240108114276114004, 0.0}, {1.0, 0.0, 3.5, 0.0, -0.916290731874155065, -3.14159265358979324, 2.57284574234941582, -2.52133906787958123, 1.44241441233798233, 1.57208443290129947}, {1.0, 0.0, 0.0, -1.0, -0.346573590279972655, -0.78539816339744831, 0.160292055087885226, -0.192901316796912429, -0.0115066749133700615, 0.0770708622146679417}, {1.0, 0.0, 0.125, 0.125, 0.123430038965762899, 0.141897054604163923, 0.00180689203856968544, -0.0122114794810442984, -0.00105066979284378462, 0.00449853805632375062}, {2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.0, 0.0, -0.5, 0.0, -0.448414206923646202, 0.0, -0.0320237060779612787, 0.0, 0.0092536571135294828, 0.0}, {2.0, 0.0, 0.99609375, 0.0, 1.61932072927810507, 0.0, -0.863010139919679163, 0.0, 0.825515949454683347, 0.0}, {2.0, 0.0, 1.00390625, 0.0, 1.6704551616562229, -0.0122479400888173039, -0.992661633138610541, 0.0731191212424626706, 1.04852574935488925, -0.214307793003452771}, {2.0, 0.0, -4.25, 0.0, -2.46898738747224279, 0.0, -0.739287387997829118, 0.0, 0.0874470644522297429, 0.0}, {2.0, 0.0, 3.5, 0.0, 2.1959348115757808, -3.93567093851438969, 2.87640729249480637, 0.777030723254221356, -0.81939570865486996, 1.19241843763256774}, {2.0, 0.0, 0.0, -1.0, -0.205616758356028305, -0.915965594177219015, 0.117193531789480469, -0.0815807361165927951, -0.0255408233794369879, 0.0372076062178391175}, {2.0, 0.0, 0.125, 0.125, 0.124500148439393858, 0.133240721203487057, 0.000569113907620539642, -0.00588251562210034232, -0.000326714635669985778, 0.00213086661076891839}, {-2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {-2.0, 2.0, -0.5, 0.0, -0.132203419506655614, -0.390689361106274866, -0.256343261725123592, 0.106175177622871437, 0.0749290443999118563, 0.0319207027895210173}, {-2.0, 2.0, 0.99609375, 0.0, 13841369.6929212372, -8339597.62269406988, -87251051.2148652244, 65225350.0315463319, 273254167.909661771, -247710863.316563213}, {-2.0, 2.0, 1.00390625, 0.0, -26028.6661639721745, 15961.1559569935978, 113847.512122984734, -206358.723605581203, 6578.40068463757013, 908971.828153761815}, {-2.0, 2.0, -4.25, 0.0, 1.26205464628714387, 0.274313692011971484, 0.442242006131113713, -1.61799252235272836, -0.927785295033312282, -0.172205994085466244}, {-2.0, 2.0, 3.5, 0.0, 0.0870998538268457367, 0.0980699787750225838, 0.152937181587789832, -0.0211963252018165386, 0.0431921445114569281, -0.0695183434413184998}, {-2.0, 2.0, 0.0, -1.0, 0.199312975007554535, -0.0775592701795263651, -0.0210851901426345675, -0.167326332453265841, -0.0632997708310078762, -0.0392019115527122943}, {-2.0, 2.0, 0.125, 0.125, 0.315234332693229892, 0.165559827416958489, -0.16530664867351669, -0.0392852937947218337, 0.0780220225006149953, 0.0215283250955342792}, }; TEST_FUNCTION_START(acb_poly_polylog_cpx, state) { slong iter; /* check particular values against table */ { acb_t s, z, t; acb_ptr w1, w2; slong i, j, prec; acb_init(s); acb_init(z); acb_init(t); w1 = _acb_vec_init(NUM_DERIVS); w2 = _acb_vec_init(NUM_DERIVS); for (prec = 32; prec <= 512; prec *= 4) { for (i = 0; i < NUM_TESTS; i++) { acb_zero(s); arf_set_d(arb_midref(acb_realref(s)), polylog_testdata[i][0]); arf_set_d(arb_midref(acb_imagref(s)), polylog_testdata[i][1]); acb_zero(z); arf_set_d(arb_midref(acb_realref(z)), polylog_testdata[i][2]); arf_set_d(arb_midref(acb_imagref(z)), polylog_testdata[i][3]); _acb_poly_polylog_cpx_small(w1, s, z, NUM_DERIVS, prec); _acb_poly_polylog_cpx_zeta(w2, s, z, NUM_DERIVS, prec); for (j = 0; j < NUM_DERIVS; j++) { arf_set_d(arb_midref(acb_realref(t)), polylog_testdata[i][4+2*j]); mag_set_d(arb_radref(acb_realref(t)), fabs(polylog_testdata[i][4+2*j]) * EPS); arf_set_d(arb_midref(acb_imagref(t)), polylog_testdata[i][4+2*j+1]); mag_set_d(arb_radref(acb_imagref(t)), fabs(polylog_testdata[i][4+2*j+1]) * EPS); if (!acb_overlaps(w1 + j, t) || !acb_overlaps(w2 + j, t) || !acb_overlaps(w1 + j, w2 + j)) { flint_printf("FAIL\n\n"); flint_printf("s = "); acb_printd(s, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 15); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1 + j, 15); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2 + j, 15); flint_printf("\n\n"); flint_abort(); } } } } _acb_vec_clear(w1, NUM_DERIVS); _acb_vec_clear(w2, NUM_DERIVS); acb_clear(s); acb_clear(z); acb_clear(t); } for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, z; acb_ptr w1, w2; slong i, len1, len2, prec1, prec2; acb_init(s); acb_init(z); if (n_randint(state, 2)) acb_randtest(s, state, 1 + n_randint(state, 300), 3); else acb_set_si(s, n_randint(state, 20) - 10); switch (n_randint(state, 3)) { case 0: acb_randtest(z, state, 1 + n_randint(state, 300), 10); break; case 1: arb_randtest(acb_realref(z), state, 1 + n_randint(state, 300), 10); break; case 2: acb_one(z); break; } prec1 = 2 + n_randint(state, 300); prec2 = prec1 + 30; len1 = 1 + n_randint(state, 20); len2 = 1 + n_randint(state, 20); w1 = _acb_vec_init(len1); w2 = _acb_vec_init(len2); switch (n_randint(state, 5)) { case 0: _acb_poly_polylog_cpx_small(w1, s, z, len1, prec1); break; case 1: _acb_poly_polylog_cpx_zeta(w1, s, z, len1, prec1); break; default: _acb_poly_polylog_cpx(w1, s, z, len1, prec1); break; } switch (n_randint(state, 5)) { case 0: _acb_poly_polylog_cpx_small(w2, s, z, len2, prec2); break; case 1: _acb_poly_polylog_cpx_zeta(w2, s, z, len2, prec2); break; default: _acb_poly_polylog_cpx(w2, s, z, len2, prec2); break; } for (i = 0; i < FLINT_MIN(len1, len2); i++) { if (!acb_overlaps(w1 + i, w2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("len1 = %wd, len2 = %wd, i = %wd\n\n", len1, len2, i); flint_printf("s = "); acb_printd(s, prec1 / 3.33); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, prec1 / 3.33); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1 + i, prec1 / 3.33); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2 + i, prec2 / 3.33); flint_printf("\n\n"); flint_abort(); } } acb_clear(s); acb_clear(z); _acb_vec_clear(w1, len1); _acb_vec_clear(w2, len2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-polylog_series.c000066400000000000000000000043401461254215100216360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_polylog_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; acb_t z; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 10); n1 = 1 + n_randint(state, 10); n2 = 1 + n_randint(state, 10); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(z); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_randtest(z, state, bits1, 3); acb_poly_polylog_series(A, S, z, n1, bits2); acb_poly_polylog_series(B, S, z, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_polylog_series(S, S, z, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-pow_acb_series.c000066400000000000000000000051011461254215100215570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_pow_acb_series, state) { slong iter; /* compare with exp/log */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong prec, trunc; acb_poly_t f, g, h1, h2; acb_t c; prec = 2 + n_randint(state, 200); trunc = n_randint(state, 20); acb_poly_init(f); acb_poly_init(g); acb_poly_init(h1); acb_poly_init(h2); acb_init(c); /* generate binomials */ if (n_randint(state, 20) == 0) { acb_randtest(c, state, prec, 10); acb_poly_set_coeff_acb(f, 0, c); acb_randtest(c, state, prec, 10); acb_poly_set_coeff_acb(f, 1 + n_randint(state, 20), c); } else { acb_poly_randtest(f, state, 1 + n_randint(state, 20), prec, 10); } acb_poly_randtest(h1, state, 1 + n_randint(state, 20), prec, 10); acb_randtest(c, state, prec, 10); acb_poly_set_acb(g, c); /* f^c */ acb_poly_pow_acb_series(h1, f, c, trunc, prec); /* f^c = exp(c*log(f)) */ acb_poly_log_series(h2, f, trunc, prec); acb_poly_mullow(h2, h2, g, trunc, prec); acb_poly_exp_series(h2, h2, trunc, prec); if (!acb_poly_overlaps(h1, h2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("trunc = %wd\n", trunc); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 15); flint_printf("\n\n"); flint_printf("h1 = "); acb_poly_printd(h1, 15); flint_printf("\n\n"); flint_printf("h2 = "); acb_poly_printd(h2, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_pow_acb_series(f, f, c, trunc, prec); if (!acb_poly_overlaps(f, h1)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_poly_clear(h1); acb_poly_clear(h2); acb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-pow_series.c000066400000000000000000000054021461254215100207560ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_pow_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong rbits1, rbits2, len; acb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); len = n_randint(state, 25); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); if (n_randint(state, 4) == 0) acb_poly_randtest(a, state, 1, rbits1, 25); else acb_poly_randtest(a, state, 1 + n_randint(state, 20), rbits1, 5); if (n_randint(state, 4) == 0) acb_poly_randtest(b, state, 1, rbits1, 25); else acb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); acb_poly_randtest(c, state, 1 + n_randint(state, 20), rbits1, 5); acb_poly_pow_series(c, a, b, len, rbits2); /* a^b = exp(b log a) */ acb_poly_log_series(d, a, len, rbits2); acb_poly_mullow(d, d, b, len, rbits2); acb_poly_exp_series(d, d, len, rbits2); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL (iter %wd)\n\n", iter); flint_printf("bits2 = %wd\n", rbits2); flint_printf("len = %wd\n", len); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* check aliasing */ if (iter < 5000) { acb_poly_set(d, a); acb_poly_pow_series(d, d, b, len, rbits2); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL (aliasing 1)\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_pow_series(d, a, d, len, rbits2); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL (aliasing 2)\n"); flint_abort(); } } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-pow_ui.c000066400000000000000000000040271461254215100201030ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_pow_ui, state) { slong iter; /* compare with fmpz_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong zbits1, rbits1, rbits2; ulong e; fmpz_poly_t A, B; acb_poly_t a, b; zbits1 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); e = n_randint(state, 30); fmpz_poly_init(A); fmpz_poly_init(B); acb_poly_init(a); acb_poly_init(b); fmpz_poly_randtest(A, state, 1 + n_randint(state, 8), zbits1); fmpz_poly_pow(B, A, e); acb_poly_set_fmpz_poly(a, A, rbits1); acb_poly_pow_ui(b, a, e, rbits2); if (!acb_poly_contains_fmpz_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("e = %wu\n", e); flint_printf("A = "); fmpz_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpz_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_pow_ui(a, a, e, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpz_poly_clear(A); fmpz_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-pow_ui_trunc_binexp.c000066400000000000000000000042711461254215100226640ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_pow_ui_trunc_binexp, state) { slong iter; /* compare with fmpz_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong zbits1, rbits1, rbits2, trunc; ulong e; fmpz_poly_t A, B; acb_poly_t a, b; zbits1 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); e = n_randint(state, 50); trunc = n_randint(state, 40); fmpz_poly_init(A); fmpz_poly_init(B); acb_poly_init(a); acb_poly_init(b); fmpz_poly_randtest(A, state, 1 + n_randint(state, 10), zbits1); fmpz_poly_pow_trunc(B, A, e, trunc); acb_poly_set_fmpz_poly(a, A, rbits1); acb_poly_pow_ui_trunc_binexp(b, a, e, trunc, rbits2); if (!acb_poly_contains_fmpz_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("e = %wu\n", e); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpz_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpz_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_pow_ui_trunc_binexp(a, a, e, trunc, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpz_poly_clear(A); fmpz_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-powsum_one_series_sieved.c000066400000000000000000000044251461254215100237070ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_powsum_one_series_sieved, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, a, q; acb_ptr z1, z2; slong i, n, len, prec; acb_init(s); acb_init(a); acb_init(q); if (n_randint(state, 2)) { acb_randtest(s, state, 1 + n_randint(state, 200), 3); } else { arb_set_ui(acb_realref(s), 1); arb_mul_2exp_si(acb_realref(s), acb_realref(s), -1); arb_randtest(acb_imagref(s), state, 1 + n_randint(state, 200), 4); } acb_one(a); acb_one(q); prec = 2 + n_randint(state, 200); n = n_randint(state, 100); len = 1 + n_randint(state, 10); z1 = _acb_vec_init(len); z2 = _acb_vec_init(len); _acb_poly_powsum_series_naive(z1, s, a, q, n, len, prec); _acb_poly_powsum_one_series_sieved(z2, s, n, len, prec); for (i = 0; i < len; i++) { if (!acb_overlaps(z1 + i, z2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("n = %wd, prec = %wd, len = %wd, i = %wd\n\n", n, prec, len, i); flint_printf("s = "); acb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, prec / 3.33); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1 + i, prec / 3.33); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2 + i, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } acb_clear(a); acb_clear(s); acb_clear(q); _acb_vec_clear(z1, len); _acb_vec_clear(z2, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-powsum_series_naive_threaded.c000066400000000000000000000052341461254215100245300ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_powsum_series_naive_threaded, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, a, q; acb_ptr z1, z2; slong i, n, len, prec; acb_init(s); acb_init(a); acb_init(q); if (n_randint(state, 2)) { acb_randtest(s, state, 1 + n_randint(state, 200), 3); } else { arb_set_ui(acb_realref(s), 1); arb_mul_2exp_si(acb_realref(s), acb_realref(s), -1); arb_randtest(acb_imagref(s), state, 1 + n_randint(state, 200), 4); } if (n_randint(state, 2)) acb_one(a); else acb_randtest(a, state, 1 + n_randint(state, 200), 3); if (n_randint(state, 2)) acb_one(q); else acb_randtest(q, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); n = n_randint(state, 100); len = 1 + n_randint(state, 10); z1 = _acb_vec_init(len); z2 = _acb_vec_init(len); _acb_poly_powsum_series_naive(z1, s, a, q, n, len, prec); flint_set_num_threads(1 + n_randint(state, 3)); _acb_poly_powsum_series_naive_threaded(z2, s, a, q, n, len, prec); for (i = 0; i < len; i++) { if (!acb_overlaps(z1 + i, z2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("n = %wd, prec = %wd, len = %wd, i = %wd\n\n", n, prec, len, i); flint_printf("s = "); acb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, prec / 3.33); flint_printf("\n\n"); flint_printf("q = "); acb_printd(q, prec / 3.33); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1 + i, prec / 3.33); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2 + i, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } acb_clear(a); acb_clear(s); acb_clear(q); _acb_vec_clear(z1, len); _acb_vec_clear(z2, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-product_roots.c000066400000000000000000000040571461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_product_roots, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong prec, len, m, i; acb_poly_t a, b, c, d; acb_ptr r; prec = 2 + n_randint(state, 200); len = n_randint(state, 12); if (len > 0) m = n_randint(state, len); else m = 0; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); r = _acb_vec_init(len); for (i = 0; i < len; i++) acb_randtest(r + i, state, 1 + n_randint(state, 200), 10); acb_poly_product_roots(a, r, len, prec); acb_poly_product_roots(b, r, m, prec); acb_poly_product_roots(c, r + m, len - m, prec); acb_poly_mul(d, b, c, prec); if (!acb_poly_overlaps(a, d)) { flint_printf("FAIL\n\n"); flint_printf("len = %wd, m = %wd\n\n", len, m); for (i = 0; i < len; i++) { acb_printd(r + i, 15); flint_printf("\n"); } flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); _acb_vec_clear(r, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-revert_series.c000066400000000000000000000043001461254215100214540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_revert_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, rbits1, rbits2, n; fmpq_poly_t A, B; acb_poly_t a, b, c; qbits1 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); n = 2 + n_randint(state, 25); fmpq_poly_init(A); fmpq_poly_init(B); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); do { fmpq_poly_randtest(A, state, 1 + n_randint(state, 25), qbits1); fmpq_poly_set_coeff_ui(A, 0, 0); } while (A->length < 2 || fmpz_is_zero(A->coeffs + 1)); fmpq_poly_revert_series(B, A, n); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_revert_series(b, a, n, rbits2); if (!acb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, bits2 = %wd\n", n, rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(c, a); acb_poly_revert_series(c, c, n, rbits2); if (!acb_poly_equal(c, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-rgamma_series.c000066400000000000000000000054641461254215100214250ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_rgamma_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; acb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, m, rbits1, 3); acb_poly_randtest(b, state, m, rbits1, 3); acb_poly_randtest(c, state, m, rbits1, 3); acb_poly_rgamma_series(b, a, n1, rbits2); acb_poly_rgamma_series(c, a, n2, rbits3); acb_poly_set(d, b); acb_poly_truncate(d, FLINT_MIN(n1, n2)); acb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check rgamma(a) = a gamma(a+1) */ acb_poly_add_si(d, a, 1, rbits2); acb_poly_rgamma_series(d, d, n1, rbits2); acb_poly_mullow(c, d, a, n1, rbits2); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL (functional equation, n1 = %wd)\n\n", n1); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_rgamma_series(a, a, n1, rbits2); if (!acb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-rising_ui_series.c000066400000000000000000000063151461254215100221450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_rising_ui_series, state) { slong iter; /* check rf(f, a) * rf(f + a, b) = rf(f, a + b) */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, trunc; ulong a, b; acb_poly_t f, g, h1, h2, h1h2, h3; bits = 2 + n_randint(state, 200); trunc = 1 + n_randint(state, 20); a = n_randint(state, 10); b = n_randint(state, 10); acb_poly_init(f); acb_poly_init(g); acb_poly_init(h1); acb_poly_init(h2); acb_poly_init(h1h2); acb_poly_init(h3); acb_poly_randtest(f, state, 1 + n_randint(state, 20), bits, 4); acb_poly_set(g, f); /* g = f + 1 */ if (g->length == 0) { acb_poly_fit_length(g, 1); acb_set_ui(g->coeffs, a); _acb_poly_set_length(g, 1); _acb_poly_normalise(g); } else { acb_add_ui(g->coeffs, g->coeffs, a, bits); _acb_poly_normalise(g); } acb_poly_rising_ui_series(h1, f, a, trunc, bits); acb_poly_rising_ui_series(h2, g, b, trunc, bits); acb_poly_rising_ui_series(h3, f, a + b, trunc, bits); acb_poly_mullow(h1h2, h1, h2, trunc, bits); if (!acb_poly_overlaps(h1h2, h3)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", a); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); acb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("h1 = "); acb_poly_printd(h1, 15); flint_printf("\n\n"); flint_printf("h2 = "); acb_poly_printd(h2, 15); flint_printf("\n\n"); flint_printf("h1h2 = "); acb_poly_printd(h1h2, 15); flint_printf("\n\n"); flint_printf("h3 = "); acb_poly_printd(h3, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_rising_ui_series(f, f, a, trunc, bits); if (!acb_poly_equal(f, h1)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", a); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("h1 = "); acb_poly_printd(h1, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_poly_clear(h1); acb_poly_clear(h2); acb_poly_clear(h1h2); acb_poly_clear(h3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-root_bound_fujiwara.c000066400000000000000000000043071461254215100226440ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_root_bound_fujiwara, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a; acb_ptr roots; acb_t t; mag_t mag1, mag2; slong i, deg, prec; prec = 10 + n_randint(state, 400); deg = n_randint(state, 10); acb_init(t); acb_poly_init(a); mag_init(mag1); mag_init(mag2); roots = _acb_vec_init(deg); for (i = 0; i < deg; i++) acb_randtest(roots + i, state, prec, 1 + n_randint(state, 20)); acb_poly_product_roots(a, roots, deg, prec); acb_randtest(t, state, prec, 1 + n_randint(state, 20)); acb_poly_scalar_mul(a, a, t, prec); acb_poly_root_bound_fujiwara(mag1, a); for (i = 0; i < deg; i++) { acb_get_mag(mag2, roots + i); /* acb_get_mag gives an upper bound which due to rounding could be larger than mag1, so we pick a slightly smaller number */ mag_mul_ui(mag2, mag2, 10000); mag_div_ui(mag2, mag2, 10001); if (mag_cmp(mag2, mag1) > 0) { flint_printf("FAIL\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("root = "); acb_printd(roots + i, 15); flint_printf("\n\n"); flint_printf("mag1 = "); mag_printd(mag1, 10); flint_printf("\n\n"); flint_printf("mag2 = "); mag_printd(mag2, 10); flint_printf("\n\n"); flint_abort(); } } _acb_vec_clear(roots, deg); acb_clear(t); acb_poly_clear(a); mag_clear(mag1); mag_clear(mag2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-rsqrt_series.c000066400000000000000000000043051461254215100213250ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_rsqrt_series, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; acb_poly_t a, b, c; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); fmpq_poly_randtest_not_zero(A, state, m, qbits); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_randtest(b, state, 1 + n_randint(state, 30), rbits1, 5); acb_poly_rsqrt_series(b, a, n, rbits2); /* Check 1/((1/sqrt(a))^2) = a */ acb_poly_mullow(c, b, b, n, rbits2); acb_poly_inv_series(c, c, n, rbits2); fmpq_poly_truncate(A, n); if (!acb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_rsqrt_series(a, a, n, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-set_trunc_round.c000066400000000000000000000042501461254215100220140ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_set_trunc_round, state) { int iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d, e; slong n, prec; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_init(e); acb_poly_randtest(a, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); acb_poly_randtest(b, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); acb_poly_randtest(c, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); acb_poly_randtest(d, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); acb_poly_randtest(e, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); n = n_randint(state, 10); prec = 2 + n_randint(state, 200); acb_poly_set_trunc(b, a, n); acb_poly_set_round(b, b, prec); acb_poly_set_round(c, a, prec); acb_poly_set_trunc(c, c, n); acb_poly_set_trunc_round(d, a, n, prec); acb_poly_set(e, a); acb_poly_set_trunc_round(e, e, n, prec); if (!acb_poly_equal(b, c) || !acb_poly_equal(c, d) || !acb_poly_equal(d, e)) { flint_printf("FAIL\n\n"); acb_poly_printd(a, 50), flint_printf("\n\n"); acb_poly_printd(b, 50), flint_printf("\n\n"); acb_poly_printd(c, 50), flint_printf("\n\n"); acb_poly_printd(d, 50), flint_printf("\n\n"); acb_poly_printd(e, 50), flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); acb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-shift_left_right.c000066400000000000000000000054161461254215100221300ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_shift_left_right, state) { int i, result; /* Check aliasing of a and b for left shift */ for (i = 0; i < 1000; i++) { acb_poly_t a, b; slong shift = n_randint(state, 100); acb_poly_init(a); acb_poly_init(b); acb_poly_randtest(a, state, n_randint(state, 100), 2 + n_randint(state, 200), 10); acb_poly_shift_left(b, a, shift); acb_poly_shift_left(a, a, shift); result = (acb_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); acb_poly_printd(a, 10), flint_printf("\n\n"); acb_poly_printd(b, 10), flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); } /* Check aliasing of a and b for right shift */ for (i = 0; i < 1000; i++) { acb_poly_t a, b; slong shift = n_randint(state, 100); acb_poly_init(a); acb_poly_init(b); acb_poly_randtest(a, state, n_randint(state, 100), 2 + n_randint(state, 200), 10); acb_poly_shift_right(b, a, shift); acb_poly_shift_right(a, a, shift); result = (acb_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); acb_poly_printd(a, 10), flint_printf("\n\n"); acb_poly_printd(b, 10), flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); } /* Check shift left then right does nothing */ for (i = 0; i < 1000; i++) { acb_poly_t a, b, c; slong shift = n_randint(state, 100); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_randtest(a, state, n_randint(state, 100), 2 + n_randint(state, 200), 10); acb_poly_shift_left(b, a, shift); acb_poly_shift_right(c, b, shift); result = (acb_poly_equal(c, a)); if (!result) { flint_printf("FAIL:\n"); acb_poly_printd(a, 10), flint_printf("\n\n"); acb_poly_printd(b, 10), flint_printf("\n\n"); acb_poly_printd(c, 10), flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sin_cos_pi_series.c000066400000000000000000000052301461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sin_cos_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; acb_poly_t a, b, c, d, e; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); fmpq_poly_init(B); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_init(e); fmpq_poly_randtest(A, state, m, qbits); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_sin_cos_pi_series(b, c, a, n, rbits2); /* Check sin(x)^2 + cos(x)^2 = 1 */ acb_poly_mullow(d, b, b, n, rbits2); acb_poly_mullow(e, c, c, n, rbits2); acb_poly_add(d, d, e, rbits2); fmpq_poly_one(B); if (!acb_poly_contains_fmpq_poly(d, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_sin_cos_pi_series(d, c, d, n, rbits2); if (!acb_poly_equal(b, d)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_sin_cos_pi_series(b, d, d, n, rbits2); if (!acb_poly_equal(c, d)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); acb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sin_cos_series.c000066400000000000000000000046521461254215100216140ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sin_cos_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, rbits1, rbits2; fmpq_poly_t B; acb_poly_t a, b, c, d, e; rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(B); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_init(e); acb_poly_randtest(a, state, m, rbits1, 10); acb_poly_sin_cos_series(b, c, a, n, rbits2); /* Check sin(x)^2 + cos(x)^2 = 1 */ acb_poly_mullow(d, b, b, n, rbits2); acb_poly_mullow(e, c, c, n, rbits2); acb_poly_add(d, d, e, rbits2); fmpq_poly_one(B); if (!acb_poly_contains_fmpq_poly(d, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_sin_cos_series(d, c, d, n, rbits2); if (!acb_poly_equal(b, d)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_sin_cos_series(b, d, d, n, rbits2); if (!acb_poly_equal(c, d)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); acb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sin_pi_series.c000066400000000000000000000043101461254215100214270ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sin_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; acb_poly_t S, A, B, C; acb_t pi; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(pi); acb_poly_randtest(S, state, m, bits1, 3); acb_poly_randtest(A, state, m, bits1, 3); acb_poly_randtest(B, state, m, bits1, 3); acb_poly_sin_pi_series(A, S, n1, bits2); acb_const_pi(pi, bits3); acb_poly_set_acb(B, pi); acb_poly_mul(B, S, B, bits3); acb_poly_sin_series(B, B, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_sin_pi_series(S, S, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_clear(pi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sin_series_cos_series.c000066400000000000000000000047121461254215100231630ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sin_series_cos_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, rbits1, rbits2; fmpq_poly_t B; acb_poly_t a, b, c, d, e; rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(B); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_init(e); acb_poly_randtest(a, state, m, rbits1, 10); acb_poly_sin_series(b, a, n, rbits2); acb_poly_cos_series(c, a, n, rbits2); /* Check sin(x)^2 + cos(x)^2 = 1 */ acb_poly_mullow(d, b, b, n, rbits2); acb_poly_mullow(e, c, c, n, rbits2); acb_poly_add(d, d, e, rbits2); fmpq_poly_one(B); if (!acb_poly_contains_fmpq_poly(d, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_sin_series(d, d, n, rbits2); if (!acb_poly_equal(b, d)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_cos_series(d, d, n, rbits2); if (!acb_poly_equal(c, d)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(B); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); acb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sinc_series.c000066400000000000000000000053401461254215100211060ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sinc_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; acb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 300); rbits2 = 2 + n_randint(state, 300); rbits3 = 2 + n_randint(state, 300); m = n_randint(state, 15); n1 = n_randint(state, 15); n2 = n_randint(state, 15); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, m, rbits1, 10); acb_poly_randtest(b, state, 10, rbits1, 10); acb_poly_randtest(c, state, 10, rbits1, 10); acb_poly_sinc_series(b, a, n1, rbits2); acb_poly_sinc_series(c, a, n2, rbits3); acb_poly_set(d, b); acb_poly_truncate(d, FLINT_MIN(n1, n2)); acb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); acb_poly_printd(a, 50); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 50); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 50); flint_printf("\n\n"); flint_abort(); } /* check x sinc(x) = sin(x) */ acb_poly_mullow(c, b, a, n1, rbits2); acb_poly_sin_series(d, a, n1, rbits2); if (!acb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_sinc_series(a, a, n1, rbits2); if (!acb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sinh_cosh_series.c000066400000000000000000000076511461254215100221360ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sinh_cosh_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d, e; slong n1, n2, prec; int alg1, alg2; prec = 2 + n_randint(state, 200); if (n_randint(state, 40) == 0) { n1 = n_randint(state, 300); n2 = n_randint(state, 300); } else { n1 = n_randint(state, 30); n2 = n_randint(state, 30); } acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_init(e); acb_poly_randtest(a, state, 20, prec, 3); acb_poly_randtest(b, state, 20, prec, 10); acb_poly_randtest(c, state, 20, prec, 10); acb_poly_randtest(d, state, 20, prec, 10); acb_poly_randtest(e, state, 20, prec, 10); alg1 = n_randint(state, 4); alg2 = n_randint(state, 7); switch (alg1) { case 0: acb_poly_sinh_cosh_series(b, c, a, n1, prec); break; case 1: acb_poly_sinh_cosh_series_basecase(b, c, a, n1, prec); break; case 2: acb_poly_sinh_cosh_series_exponential(b, c, a, n1, prec); break; default: acb_poly_sinh_series(b, a, n1, prec); acb_poly_cosh_series(c, a, n1, prec); break; } switch (alg2) { case 0: acb_poly_sinh_cosh_series(d, e, a, n2, prec); break; case 1: acb_poly_sinh_cosh_series_basecase(d, e, a, n2, prec); break; case 2: acb_poly_sinh_cosh_series_exponential(d, e, a, n2, prec); break; case 3: acb_poly_sinh_series(d, a, n2, prec); acb_poly_cosh_series(e, a, n2, prec); break; case 4: acb_poly_set(d, a); acb_poly_sinh_cosh_series(d, e, d, n2, prec); break; case 5: acb_poly_set(e, a); acb_poly_sinh_cosh_series(d, e, e, n2, prec); break; default: acb_poly_set(d, a); acb_poly_sinh_series(d, d, n2, prec); acb_poly_set(e, a); acb_poly_cosh_series(e, e, n2, prec); break; } acb_poly_truncate(b, FLINT_MIN(n1, n2)); acb_poly_truncate(c, FLINT_MIN(n1, n2)); acb_poly_truncate(d, FLINT_MIN(n1, n2)); acb_poly_truncate(e, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(b, d) || !acb_poly_overlaps(c, e)) { flint_printf("FAIL\n\n"); flint_printf("alg1 = %d, alg2 = %d, n1 = %wd, n2 = %wd\n\n", alg1, alg2, n1, n2); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n"); flint_printf("d = "); acb_poly_printd(e, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); acb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sqrt_series.c000066400000000000000000000041011461254215100211350ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sqrt_series, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; acb_poly_t a, b, c; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); fmpq_poly_randtest_not_zero(A, state, m, qbits); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_sqrt_series(b, a, n, rbits2); /* Check sqrt(a)^2 = a */ acb_poly_mullow(c, b, b, n, rbits2); fmpq_poly_truncate(A, n); if (!acb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_sqrt_series(a, a, n, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sub.c000066400000000000000000000054361461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sub, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; acb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_sub(C, A, B); acb_poly_set_fmpq_poly(a, A, rbits1); acb_poly_set_fmpq_poly(b, B, rbits2); acb_poly_sub(c, a, b, rbits3); if (!acb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_sub(d, d, b, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_sub(d, a, d, rbits3); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-sub_series.c000066400000000000000000000042761461254215100207520ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_sub_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_poly_t a, b, c, d; slong len, prec; acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10); acb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10); acb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10); acb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10); prec = 2 + n_randint(state, 100); len = n_randint(state, 10); acb_poly_sub_series(c, a, b, len, prec); acb_poly_sub(d, a, b, prec); acb_poly_truncate(d, len); if (!acb_poly_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_set(d, a); acb_poly_sub_series(d, d, b, len, prec); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } acb_poly_set(d, b); acb_poly_sub_series(d, a, d, len, prec); if (!acb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-tan_series.c000066400000000000000000000044641461254215100207420ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_tan_series, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, rbits1, rbits2; acb_poly_t a, b, c, d, e; rbits1 = 2 + n_randint(state, 100); rbits2 = 2 + n_randint(state, 100); if (n_randint(state, 10) == 0) { m = 1 + n_randint(state, 50); n = 1 + n_randint(state, 50); } else { m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); } acb_poly_init(a); acb_poly_init(b); acb_poly_init(c); acb_poly_init(d); acb_poly_init(e); acb_poly_randtest(a, state, m, rbits1, 10); acb_poly_tan_series(b, a, n, rbits2); /* check tan(x) = 2*tan(x/2)/(1-tan(x/2)^2) */ acb_poly_scalar_mul_2exp_si(c, a, -1); acb_poly_tan_series(c, c, n, rbits2); acb_poly_mullow(d, c, c, n, rbits2); acb_poly_one(e); acb_poly_sub(e, e, d, rbits2); acb_poly_div_series(c, c, e, n, rbits2); acb_poly_scalar_mul_2exp_si(c, c, 1); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_tan_series(a, a, n, rbits2); if (!acb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); acb_poly_clear(d); acb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-taylor_shift.c000066400000000000000000000043031461254215100213050ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_taylor_shift, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong prec1, prec2; acb_poly_t f, g; acb_t c, d, e; prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); acb_poly_init(f); acb_poly_init(g); acb_init(c); acb_init(d); acb_init(e); acb_poly_randtest(f, state, 1 + n_randint(state, 40), 1 + n_randint(state, 500), 10); acb_poly_randtest(g, state, 1 + n_randint(state, 20), 1 + n_randint(state, 500), 10); if (n_randint(state, 2)) acb_set_si(c, n_randint(state, 5) - 2); else acb_randtest(c, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); if (n_randint(state, 2)) acb_set_si(d, n_randint(state, 5) - 2); else acb_randtest(d, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_add(e, c, d, prec1); /* check f(x+c)(x+d) = f(x+c+d) */ acb_poly_taylor_shift(g, f, e, prec2); acb_poly_taylor_shift(f, f, c, prec1); acb_poly_taylor_shift(f, f, d, prec1); if (!acb_poly_overlaps(f, g)) { flint_printf("FAIL\n\n"); flint_printf("c = "); acb_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 15); flint_printf("\n\n"); flint_printf("f = "); acb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); acb_poly_printd(g, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_clear(c); acb_clear(d); acb_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-zeta_cpx_series.c000066400000000000000000000051371461254215100217730ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_zeta_cpx_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t s, a; acb_ptr z1, z2; slong i, len, prec1, prec2; int deflate; acb_init(s); acb_init(a); if (n_randint(state, 2)) { acb_randtest(s, state, 1 + n_randint(state, 300), 3); } else { arb_set_ui(acb_realref(s), 1); arb_mul_2exp_si(acb_realref(s), acb_realref(s), -1); arb_randtest(acb_imagref(s), state, 1 + n_randint(state, 300), 4); } switch (n_randint(state, 3)) { case 0: acb_randtest(a, state, 1 + n_randint(state, 300), 3); break; case 1: arb_randtest(acb_realref(a), state, 1 + n_randint(state, 300), 3); break; case 2: acb_one(a); break; } prec1 = 2 + n_randint(state, 300); prec2 = prec1 + 30; len = 1 + n_randint(state, 20); deflate = n_randint(state, 2); z1 = _acb_vec_init(len); z2 = _acb_vec_init(len); _acb_poly_zeta_cpx_series(z1, s, a, deflate, len, prec1); _acb_poly_zeta_cpx_series(z2, s, a, deflate, len, prec2); for (i = 0; i < len; i++) { if (!acb_overlaps(z1 + i, z2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("deflate = %d, len = %wd, i = %wd\n\n", deflate, len, i); flint_printf("s = "); acb_printd(s, prec1 / 3.33); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, prec1 / 3.33); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1 + i, prec1 / 3.33); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2 + i, prec2 / 3.33); flint_printf("\n\n"); flint_abort(); } } acb_clear(a); acb_clear(s); _acb_vec_clear(z1, len); _acb_vec_clear(z2, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-zeta_em_tail_bsplit.c000066400000000000000000000040761461254215100226170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_zeta_em_tail_bsplit, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acb_t Na, s; acb_ptr z1, z2, Nasx; slong i, M, len, prec; prec = 2 + n_randint(state, 400); len = 1 + n_randint(state, 30); M = n_randint(state, 40); acb_init(Na); acb_init(s); Nasx = _acb_vec_init(len); z1 = _acb_vec_init(len); z2 = _acb_vec_init(len); acb_randtest(Na, state, prec, 4); acb_randtest(s, state, prec, 4); _acb_poly_acb_invpow_cpx(Nasx, Na, s, len, prec); _acb_poly_zeta_em_tail_naive(z1, s, Na, Nasx, M, len, prec); _acb_poly_zeta_em_tail_bsplit(z2, s, Na, Nasx, M, len, prec); for (i = 0; i < len; i++) { if (!acb_overlaps(z1 + i, z2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("prec = %wd, len = %wd, M = %wd\n", prec, len, M); flint_printf("s = "); acb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_printf("Na = "); acb_printd(Na, prec / 3.33); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1 + i, prec / 3.33); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2 + i, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } acb_clear(Na); acb_clear(s); _acb_vec_clear(Nasx, len); _acb_vec_clear(z1, len); _acb_vec_clear(z2, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/test/t-zeta_series.c000066400000000000000000000067421461254215100211240ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" TEST_FUNCTION_START(acb_poly_zeta_series, state) { slong iter; for (iter = 0; iter < 400 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; int deflate; acb_poly_t S, A, B, C, D, E, F; acb_t a, a1; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 25); n1 = 1 + n_randint(state, 25); n2 = 1 + n_randint(state, 25); acb_poly_init(S); acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_poly_init(D); acb_poly_init(E); acb_poly_init(F); acb_init(a); acb_init(a1); deflate = n_randint(state, 2); acb_poly_randtest(S, state, m, bits1, 3); arb_randtest_precise(acb_realref(a), state, bits1, 3); arb_randtest_precise(acb_imagref(a), state, bits1, 3); acb_poly_set_coeff_acb(S, 0, a); if (n_randint(state, 2)) acb_randtest(a, state, bits1, 3); else acb_one(a); acb_poly_zeta_series(A, S, a, deflate, n1, bits2); acb_poly_zeta_series(B, S, a, deflate, n2, bits3); acb_poly_set(C, A); acb_poly_truncate(C, FLINT_MIN(n1, n2)); acb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!acb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); acb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } /* check zeta(s,a) = zeta(s,a+1) + a^(-s) */ acb_poly_set_acb(D, a); acb_poly_log_series(D, D, n1, bits2); acb_poly_mullow(D, D, S, n1, bits2); acb_poly_neg(D, D); acb_poly_exp_series(D, D, n1, bits2); acb_add_ui(a1, a, 1, bits2); acb_poly_zeta_series(E, S, a1, deflate, n1, bits2); acb_poly_add(E, E, D, bits2); if (!acb_poly_overlaps(A, E)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("S = "); acb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n\n"); flint_printf("A = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("E = "); acb_poly_printd(A, 15); flint_printf("\n\n"); flint_abort(); } acb_poly_zeta_series(S, S, a, deflate, n1, bits2); if (!acb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } acb_poly_clear(S); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); acb_poly_clear(D); acb_poly_clear(E); acb_poly_clear(F); acb_clear(a); acb_clear(a1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_poly/tree.c000066400000000000000000000047671461254215100163330ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" acb_ptr * _acb_poly_tree_alloc(slong len) { acb_ptr * tree = NULL; if (len) { slong i, height = FLINT_CLOG2(len); tree = flint_malloc(sizeof(acb_ptr) * (height + 1)); for (i = 0; i <= height; i++) tree[i] = _acb_vec_init(len + (len >> i) + 1); } return tree; } void _acb_poly_tree_free(acb_ptr * tree, slong len) { if (len) { slong i, height = FLINT_CLOG2(len); for (i = 0; i <= height; i++) _acb_vec_clear(tree[i], len + (len >> i) + 1); flint_free(tree); } } void _acb_poly_tree_build(acb_ptr * tree, acb_srcptr roots, slong len, slong prec) { slong height, pow, left, i; acb_ptr pa, pb; acb_srcptr a, b; if (len == 0) return; height = FLINT_CLOG2(len); /* zeroth level, (x-a) */ for (i = 0; i < len; i++) { acb_one(tree[0] + (2 * i + 1)); acb_neg(tree[0] + (2 * i), roots + i); } /* first level, (x-a)(x-b) = x^2 + (-a-b)*x + a*b */ if (height > 1) { pa = tree[1]; for (i = 0; i < len / 2; i++) { a = (acb_srcptr) (roots + (2 * i)); b = (acb_srcptr) (roots + (2 * i + 1)); acb_mul(pa + (3 * i), a, b, prec); acb_add(pa + (3 * i + 1), a, b, prec); acb_neg(pa + (3 * i + 1), pa + (3 * i + 1)); acb_one(pa + (3 * i + 2)); } if (len & 1) { acb_neg(pa + (3 * (len / 2)), roots + len - 1); acb_one(pa + (3 * (len / 2) + 1)); } } for (i = 1; i < height - 1; i++) { left = len; pow = WORD(1) << i; pa = tree[i]; pb = tree[i + 1]; while (left >= 2 * pow) { _acb_poly_mul_monic(pb, pa, pow + 1, pa + pow + 1, pow + 1, prec); left -= 2 * pow; pa += 2 * pow + 2; pb += 2 * pow + 1; } if (left > pow) { _acb_poly_mul_monic(pb, pa, pow + 1, pa + pow + 1, left - pow + 1, prec); } else if (left > 0) _acb_vec_set(pb, pa, left + 1); } } flint-3.1.3/src/acb_poly/validate_real_roots.c000066400000000000000000000070341461254215100214040ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "acb_poly.h" #ifndef __compar_fn_t #if defined(_MSC_VER) typedef int(*__compar_fn_t) (const void *, const void *); #else typedef int(*__compar_fn_t) (__const void *, __const void *); #endif #endif int arb_cmp_mid(const arb_t a, const arb_t b) { return arf_cmp(arb_midref(a), arb_midref(b)); } void _arb_vec_sort_mid(arb_ptr vec, slong len) { qsort(vec, len, sizeof(arb_struct), (__compar_fn_t) arb_cmp_mid); } int _acb_poly_validate_real_roots(acb_srcptr roots, acb_srcptr poly, slong len, slong prec) { slong i, deg, num_real; arb_ptr real; int result; deg = len - 1; num_real = 0; result = 1; if (deg <= 1) return 1; real = _arb_vec_init(deg); /* pick out the candidate real roots */ for (i = 0; i < deg; i++) { if (arb_contains_zero(acb_imagref(roots + i))) { arb_set(real + num_real, acb_realref(roots + i)); num_real++; } } /* number of real roots must be even if the polynomial is even, and odd if the polynomial is odd (unless there are repeated roots... in which case the input is invalid) */ if ((num_real % 2) != (deg % 2)) { result = 0; } else if (num_real > 0) { int sign_neg_inf, sign_pos_inf, prev_sign; acb_t t; acb_init(t); /* by assumption that the roots are real and isolated, the lead coefficient really must be known to be either positive or negative */ sign_pos_inf = arb_is_positive(acb_realref(poly + deg)) ? 1 : -1; sign_neg_inf = (deg % 2) ? -sign_pos_inf : sign_pos_inf; /* now we check that there's a sign change between each root */ _arb_vec_sort_mid(real, num_real); prev_sign = sign_neg_inf; for (i = 0; i < num_real - 1; i++) { /* set t to the midpoint between the midpoints */ arb_zero(acb_imagref(t)); arf_add(arb_midref(acb_realref(t)), arb_midref(real + i), arb_midref(real + i + 1), prec, ARF_RND_DOWN); arf_mul_2exp_si(arb_midref(acb_realref(t)), arb_midref(acb_realref(t)), -1); mag_zero(arb_radref(acb_realref(t))); /* check that this point really is between both intervals (one interval could be much wider than the other */ if (arb_lt(real + i, acb_realref(t)) && arb_lt(acb_realref(t), real + i + 1)) { /* check sign change */ _acb_poly_evaluate(t, poly, len, t, prec); if (prev_sign == 1) result = arb_is_negative(acb_realref(t)); else result = arb_is_positive(acb_realref(t)); if (!result) break; prev_sign = -prev_sign; } else { result = 0; break; } } acb_clear(t); } _arb_vec_clear(real, deg); return result; } int acb_poly_validate_real_roots(acb_srcptr roots, const acb_poly_t poly, slong prec) { return _acb_poly_validate_real_roots(roots, poly->coeffs, poly->length, prec); } flint-3.1.3/src/acb_poly/validate_roots.c000066400000000000000000000036351461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" slong _acb_poly_validate_roots(acb_ptr roots, acb_srcptr poly, slong len, slong prec) { slong i, j, deg; slong isolated, nonisolated, total_isolated; acb_ptr deriv; acb_ptr tmp; int *overlap; deg = len - 1; deriv = _acb_vec_init(deg); overlap = flint_calloc(deg, sizeof(int)); tmp = flint_malloc(sizeof(acb_struct) * deg); _acb_poly_derivative(deriv, poly, len, prec); /* compute an inclusion interval for each point */ for (i = 0; i < deg; i++) { _acb_poly_root_inclusion(roots + i, roots + i, poly, deriv, len, prec); } /* find which points do not overlap with any other points */ for (i = 0; i < deg; i++) { for (j = i + 1; j < deg; j++) { if (acb_overlaps(roots + i, roots + j)) { overlap[i] = overlap[j] = 1; } } } /* count and move all isolated roots to the front of the array */ total_isolated = 0; for (i = 0; i < deg; i++) total_isolated += (overlap[i] == 0); for (i = 0; i < deg; i++) tmp[i] = roots[i]; isolated = 0; nonisolated = 0; for (i = 0; i < deg; i++) { if (overlap[i] == 0) { roots[isolated] = tmp[i]; isolated++; } else { roots[total_isolated + nonisolated] = tmp[i]; nonisolated++; } } _acb_vec_clear(deriv, deg); flint_free(tmp); flint_free(overlap); return isolated; } flint-3.1.3/src/acb_poly/valuation.c000066400000000000000000000011341461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" slong acb_poly_valuation(const acb_poly_t poly) { slong i, len = poly->length; for (i = 0; i < len; i++) if (!acb_is_zero(poly->coeffs + i)) return i; return -1; } flint-3.1.3/src/acb_poly/zeta_em_bound.c000066400000000000000000000110641461254215100201730ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" static void bound_I(arb_ptr I, const arb_t A, const arb_t B, const arb_t C, slong len, slong wp) { slong k; arb_t D, Dk, L, T, Bm1; arb_init(D); arb_init(Dk); arb_init(Bm1); arb_init(T); arb_init(L); arb_sub_ui(Bm1, B, 1, wp); arb_one(L); /* T = 1 / (A^Bm1 * Bm1) */ arb_pow(T, A, Bm1, wp); arb_mul(T, T, Bm1, wp); arb_inv(T, T, wp); if (len > 1) { arb_log(D, A, wp); arb_add(D, D, C, wp); arb_mul(D, D, Bm1, wp); arb_set(Dk, D); } for (k = 0; k < len; k++) { if (k > 0) { arb_mul_ui(L, L, k, wp); arb_add(L, L, Dk, wp); if (k < len - 1) arb_mul(Dk, Dk, D, wp); } arb_mul(I + k, L, T, wp); if (k < len - 1) arb_div(T, T, Bm1, wp); } arb_clear(D); arb_clear(Dk); arb_clear(Bm1); arb_clear(T); arb_clear(L); } /* 0.5*(B/AN)^2 + |B|/AN */ static void bound_C(arb_t C, const arb_t AN, const arb_t B, slong wp) { arb_t t; arb_init(t); arb_abs(t, B); arb_div(t, t, AN, wp); arb_mul_2exp_si(C, t, -1); arb_add_ui(C, C, 1, wp); arb_mul(C, C, t, wp); arb_clear(t); } static void bound_K(arb_t C, const arb_t AN, const arb_t B, const arb_t T, slong wp) { if (arb_is_zero(B) || arb_is_zero(T)) { arb_one(C); } else { arb_div(C, B, AN, wp); /* TODO: atan is dumb, should also bound by pi/2 */ arb_atan(C, C, wp); arb_mul(C, C, T, wp); if (arb_is_nonpositive(C)) arb_one(C); else arb_exp(C, C, wp); } } static void bound_rfac(arb_ptr F, const acb_t s, ulong n, slong len, slong wp) { if (len == 1) { acb_rising_ui_get_mag(arb_radref(F), s, n); arf_set_mag(arb_midref(F), arb_radref(F)); mag_zero(arb_radref(F + 0)); } else { arb_struct sx[2]; arb_init(sx + 0); arb_init(sx + 1); acb_abs(sx + 0, s, wp); arb_one(sx + 1); _arb_vec_zero(F, len); _arb_poly_rising_ui_series(F, sx, 2, n, len, wp); arb_clear(sx + 0); arb_clear(sx + 1); } } void _acb_poly_zeta_em_bound(arb_ptr bound, const acb_t s, const acb_t a, ulong N, ulong M, slong len, slong wp) { arb_t K, C, AN, S2M; arb_ptr F, R; slong k; arb_srcptr alpha = acb_realref(a); arb_srcptr beta = acb_imagref(a); arb_srcptr sigma = acb_realref(s); arb_srcptr tau = acb_imagref(s); arb_init(AN); arb_init(S2M); /* require alpha + N > 1, sigma + 2M > 1 */ arb_add_ui(AN, alpha, N - 1, wp); arb_add_ui(S2M, sigma, 2*M - 1, wp); if (!arb_is_positive(AN) || !arb_is_positive(S2M) || N < 1 || M < 1) { arb_clear(AN); arb_clear(S2M); for (k = 0; k < len; k++) arb_pos_inf(bound + k); return; } /* alpha + N, sigma + 2M */ arb_add_ui(AN, AN, 1, wp); arb_add_ui(S2M, S2M, 1, wp); R = _arb_vec_init(len); F = _arb_vec_init(len); arb_init(K); arb_init(C); /* bound for power integral */ bound_C(C, AN, beta, wp); bound_K(K, AN, beta, tau, wp); bound_I(R, AN, S2M, C, len, wp); for (k = 0; k < len; k++) { arb_mul(R + k, R + k, K, wp); arb_div_ui(K, K, k + 1, wp); } /* bound for rising factorial */ bound_rfac(F, s, 2*M, len, wp); /* product (TODO: only need upper bound; write a function for this) */ _arb_poly_mullow(bound, F, len, R, len, len, wp); /* bound for bernoulli polynomials, 4 / (2pi)^(2M) */ arb_const_pi(C, wp); arb_mul_2exp_si(C, C, 1); arb_pow_ui(C, C, 2 * M, wp); arb_ui_div(C, 4, C, wp); _arb_vec_scalar_mul(bound, bound, len, C, wp); arb_clear(K); arb_clear(C); arb_clear(AN); arb_clear(S2M); _arb_vec_clear(R, len); _arb_vec_clear(F, len); } void _acb_poly_zeta_em_bound1(mag_t bound, const acb_t s, const acb_t a, slong N, slong M, slong len, slong wp) { arb_ptr vec = _arb_vec_init(len); _acb_poly_zeta_em_bound(vec, s, a, N, M, len, wp); _arb_vec_get_mag(bound, vec, len); _arb_vec_clear(vec, len); } flint-3.1.3/src/acb_poly/zeta_em_choose_param.c000066400000000000000000000055211461254215100215250ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" static ulong choose_M(ulong N, slong target) { return FLINT_MIN(N, target + FLINT_MIN(N / 100, 2000)); } static void estimate_mag(mag_t m, const acb_t s, const acb_t a, slong prec) { acb_t t; acb_init(t); if (acb_contains_zero(a)) { mag_one(m); } else { acb_neg(t, s); acb_pow(t, a, t, prec); if (acb_is_finite(t)) acb_get_mag(m, t); else mag_one(m); } acb_clear(t); } void _acb_poly_zeta_em_choose_param(mag_t bound, ulong * N, ulong * M, const acb_t s, const acb_t a, slong d, slong target, slong prec) { ulong A, B, C, limit; mag_t Abound, Bbound, Cbound, tol; mag_init(Abound); mag_init(Bbound); mag_init(Cbound); mag_init(tol); if (!acb_is_one(a)) { /* estimate zeta(s,a) ~= a^-s -- todo: this can be very inaccurate */ estimate_mag(tol, s, a, prec); mag_mul_2exp_si(tol, tol, -target); } else { mag_set_ui_2exp_si(tol, 1, -target); } A = 1; B = 2; /* Hack: allow evaluation very high up in the critical strip... */ if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(s)), 10) > 0 && acb_is_real(a) /* && arb_is_positive(acb_realref(a)) */) { limit = UWORD_MAX / 4; mag_set_ui_2exp_si(tol, 1, -target); } else limit = 100 * target; /* but normally, fail more quickly */ _acb_poly_zeta_em_bound1(Bbound, s, a, B, choose_M(B, target), d, prec); if (mag_cmp(Bbound, tol) > 0) { while (mag_cmp(Bbound, tol) > 0 && B <= limit) { mag_set(Abound, Bbound); A *= 2; B *= 2; if (B == 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); _acb_poly_zeta_em_bound1(Bbound, s, a, B, choose_M(B, target), d, prec); } /* bisect (-A, B] */ while (B > A + 4) { C = A + (B - A) / 2; _acb_poly_zeta_em_bound1(Cbound, s, a, C, choose_M(C, target), d, prec); if (mag_cmp(Cbound, tol) < 0) { B = C; mag_set(Bbound, Cbound); } else { A = C; mag_set(Abound, Cbound); } } } mag_set(bound, Bbound); *N = B; *M = choose_M(B, target); mag_clear(Abound); mag_clear(Bbound); mag_clear(Cbound); mag_clear(tol); } flint-3.1.3/src/acb_poly/zeta_em_sum.c000066400000000000000000000102351461254215100176670ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" /* res = src * (c + x) */ void _acb_poly_mullow_cpx(acb_ptr res, acb_srcptr src, slong len, const acb_t c, slong trunc, slong prec) { slong i; if (len < trunc) acb_set(res + len, src + len - 1); for (i = len - 1; i > 0; i--) { acb_mul(res + i, src + i, c, prec); acb_add(res + i, res + i, src + i - 1, prec); } acb_mul(res, src, c, prec); } /* todo: don't hardcode this */ #define SIEVE_ALLOC_LIMIT 4e9 /* 4 GB */ void _acb_poly_zeta_em_sum(acb_ptr z, const acb_t s, const acb_t a, int deflate, ulong N, ulong M, slong d, slong prec) { acb_ptr t, u, v, sum; acb_t Na, one; slong i; t = _acb_vec_init(d + 1); u = _acb_vec_init(d); v = _acb_vec_init(d); sum = _acb_vec_init(d); acb_init(Na); acb_init(one); prec += 2 * (FLINT_BIT_COUNT(N) + FLINT_BIT_COUNT(d)); acb_one(one); /* sum 1/(k+a)^(s+x) */ if (acb_is_one(a) && d <= 2 && _acb_vec_estimate_allocated_bytes(d * N / 6, prec) < SIEVE_ALLOC_LIMIT) acb_dirichlet_powsum_sieved(sum, s, N, d, prec); else if (acb_is_one(a) && d <= 4) /* todo: also better for slightly larger d, if N and prec large enough */ acb_dirichlet_powsum_smooth(sum, s, N, d, prec); else if (N > 50 && flint_get_num_threads() > 1) _acb_poly_powsum_series_naive_threaded(sum, s, a, one, N, d, prec); else _acb_poly_powsum_series_naive(sum, s, a, one, N, d, prec); /* t = 1/(N+a)^(s+x); we might need one extra term for deflation */ acb_add_ui(Na, a, N, prec); _acb_poly_acb_invpow_cpx(t, Na, s, d + 1, prec); /* sum += (N+a) * 1/((s+x)-1) * t */ if (!deflate) { /* u = (N+a)^(1-(s+x)) */ acb_sub_ui(v, s, 1, prec); _acb_poly_acb_invpow_cpx(u, Na, v, d, prec); /* divide by 1/((s-1) + x) */ acb_sub_ui(v, s, 1, prec); acb_div(u, u, v, prec); for (i = 1; i < d; i++) { acb_sub(u + i, u + i, u + i - 1, prec); acb_div(u + i, u + i, v, prec); } _acb_vec_add(sum, sum, u, d, prec); } /* sum += ((N+a)^(1-(s+x)) - 1) / ((s+x) - 1) */ else { /* at s = 1, this becomes (N*t - 1)/x, i.e. just remove one coeff */ if (acb_is_one(s)) { for (i = 0; i < d; i++) acb_mul(u + i, t + i + 1, Na, prec); _acb_vec_add(sum, sum, u, d, prec); } else { /* TODO: this is numerically unstable for large derivatives, and divides by zero if s contains 1. We want a good way to evaluate the power series ((N+a)^y - 1) / y where y has nonzero constant term, without doing a division. How is this best done? */ _acb_vec_scalar_mul(t, t, d, Na, prec); acb_sub_ui(t + 0, t + 0, 1, prec); acb_sub_ui(u + 0, s, 1, prec); acb_inv(u + 0, u + 0, prec); for (i = 1; i < d; i++) acb_mul(u + i, u + i - 1, u + 0, prec); for (i = 1; i < d; i += 2) acb_neg(u + i, u + i); _acb_poly_mullow(v, u, d, t, d, d, prec); _acb_vec_add(sum, sum, v, d, prec); _acb_poly_acb_invpow_cpx(t, Na, s, d, prec); } } /* sum += u = 1/2 * t */ _acb_vec_scalar_mul_2exp_si(u, t, d, -WORD(1)); _acb_vec_add(sum, sum, u, d, prec); /* Euler-Maclaurin formula tail */ if (d < 5 || d < M / 10) _acb_poly_zeta_em_tail_naive(u, s, Na, t, M, d, prec); else _acb_poly_zeta_em_tail_bsplit(u, s, Na, t, M, d, prec); _acb_vec_add(z, sum, u, d, prec); _acb_vec_clear(t, d + 1); _acb_vec_clear(u, d); _acb_vec_clear(v, d); _acb_vec_clear(sum, d); acb_clear(Na); acb_clear(one); } flint-3.1.3/src/acb_poly/zeta_em_tail_bsplit.c000066400000000000000000000063271461254215100214000ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "bernoulli.h" static void bsplit(acb_ptr P, acb_ptr T, const acb_t s, const acb_t Na, slong a, slong b, int cont, slong len, slong prec) { slong plen = FLINT_MIN(2 * (b - a) + 1, len); if (b - a == 1) { slong j = a; fmpz_t t; fmpz_init(t); if (j == 0) { acb_set(P, s); if (len > 1) acb_one(P + 1); if (len > 2) acb_zero(P + 2); } else { /* P = ((s+x)+2j-1)(s+x)+2j) */ /* constant term = s^2 + (4j-1)s + (4j^2-2j)*/ acb_mul(P, s, s, prec); acb_addmul_ui(P, s, 4*j-1, prec); fmpz_set_ui(t, 2*j); fmpz_mul_ui(t, t, 2*j-1); acb_add_fmpz(P, P, t, prec); /* x term = (2s+4j-1) */ if (len > 1) { acb_mul_ui(P + 1, s, 2, prec); acb_add_ui(P + 1, P + 1, 4*j-1, prec); } /* x^2 term = 1 */ if (len > 2) acb_one(P + 2); } /* P = P / ((2j+1)*(2j+2)) */ fmpz_set_ui(t, 2*j+1); fmpz_mul_ui(t, t, 2*j+2); _acb_vec_scalar_div_fmpz(P, P, plen, t, prec); /* P = P / Na or P / Na^2 */ if (j == 0) acb_set(T, Na); else acb_mul(T, Na, Na, prec); _acb_vec_scalar_div(P, P, plen, T, prec); /* T = P * B_{2j+2} */ _acb_vec_scalar_mul_fmpz(T, P, plen, fmpq_numref(bernoulli_cache + 2 * j + 2), prec); _acb_vec_scalar_div_fmpz(T, T, plen, fmpq_denref(bernoulli_cache + 2 * j + 2), prec); fmpz_clear(t); } else { slong m, len1, len2, alloc; acb_ptr P1, T1, P2, T2; m = a + (b - a) / 2; len1 = FLINT_MIN(2 * (m - a) + 1, len); len2 = FLINT_MIN(2 * (b - m) + 1, len); alloc = 2 * len1 + 2 * len2; P1 = _acb_vec_init(alloc); T1 = P1 + len1; P2 = T1 + len1; T2 = P2 + len2; bsplit(P1, T1, s, Na, a, m, 1, len, prec); bsplit(P2, T2, s, Na, m, b, 1, len, prec); /* P = P1 * P2 */ if (cont) _acb_poly_mullow(P, P2, len2, P1, len1, plen, prec); /* T = T1 + P1 * T2 */ _acb_poly_mullow(T, T2, len2, P1, len1, plen, prec); _acb_vec_add(T, T, T1, len1, prec); _acb_vec_clear(P1, alloc); } } void _acb_poly_zeta_em_tail_bsplit(acb_ptr z, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong len, slong prec) { acb_ptr P, T; if (M < 1) { _acb_vec_zero(z, len); return; } BERNOULLI_ENSURE_CACHED(2 * M); P = _acb_vec_init(len); T = _acb_vec_init(len); bsplit(P, T, s, Na, 0, M, 0, len, prec); _acb_poly_mullow(z, T, len, Nasx, len, len, prec); _acb_vec_clear(P, len); _acb_vec_clear(T, len); } flint-3.1.3/src/acb_poly/zeta_em_tail_naive.c000066400000000000000000000052431461254215100212010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "bernoulli.h" void _acb_poly_mullow_cpx(acb_ptr res, acb_srcptr src, slong len, const acb_t c, slong trunc, slong prec); void _acb_poly_zeta_em_tail_naive(acb_ptr sum, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong d, slong prec) { acb_ptr u, term; acb_t Na2, splus, rec; arb_t x; fmpz_t c; int aint; slong r; BERNOULLI_ENSURE_CACHED(2 * M); u = _acb_vec_init(d); term = _acb_vec_init(d); acb_init(splus); acb_init(rec); acb_init(Na2); arb_init(x); fmpz_init(c); _acb_vec_zero(sum, d); /* u = 1/2 * Nasx */ _acb_vec_scalar_mul_2exp_si(u, Nasx, d, -WORD(1)); /* term = u * (s+x) / (N+a) */ _acb_poly_mullow_cpx(u, u, d, s, d, prec); _acb_vec_scalar_div(term, u, d, Na, prec); /* (N+a)^2 or 1/(N+a)^2 */ acb_mul(Na2, Na, Na, prec); aint = acb_is_int(Na2); if (!aint) acb_inv(Na2, Na2, prec); for (r = 1; r <= M; r++) { /* flint_printf("sum 2: %wd %wd\n", r, M); */ /* sum += bernoulli number * term */ arb_set_round_fmpz(x, fmpq_numref(bernoulli_cache + 2 * r), prec); arb_div_fmpz(x, x, fmpq_denref(bernoulli_cache + 2 * r), prec); _acb_vec_scalar_mul_arb(u, term, d, x, prec); _acb_vec_add(sum, sum, u, d, prec); /* multiply term by ((s+x)+2r-1)((s+x)+2r) / ((N+a)^2 * (2*r+1)*(2*r+2)) */ acb_set(splus, s); arb_add_ui(acb_realref(splus), acb_realref(splus), 2*r-1, prec); _acb_poly_mullow_cpx(term, term, d, splus, d, prec); arb_add_ui(acb_realref(splus), acb_realref(splus), 1, prec); _acb_poly_mullow_cpx(term, term, d, splus, d, prec); /* TODO: combine with previous multiplication? */ if (aint) { arb_mul_ui(x, acb_realref(Na2), 2*r+1, prec); arb_mul_ui(x, x, 2*r+2, prec); _acb_vec_scalar_div_arb(term, term, d, x, prec); } else { fmpz_set_ui(c, 2*r+1); fmpz_mul_ui(c, c, 2*r+2); acb_div_fmpz(rec, Na2, c, prec); _acb_vec_scalar_mul(term, term, d, rec, prec); } } _acb_vec_clear(u, d); _acb_vec_clear(term, d); acb_clear(splus); acb_clear(rec); acb_clear(Na2); arb_clear(x); fmpz_clear(c); } flint-3.1.3/src/acb_poly/zeta_series.c000066400000000000000000000061241461254215100176760ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_dirichlet.h" void _acb_poly_zeta_cpx_series(acb_ptr z, const acb_t s, const acb_t a, int deflate, slong d, slong prec) { ulong M, N; slong i, bound_prec; mag_t bound; arb_ptr vb; int is_real, const_is_real; if (d < 1) return; if (!acb_is_finite(s) || !acb_is_finite(a)) { _acb_vec_indeterminate(z, d); return; } if (acb_is_one(s) && deflate && d == 1) { acb_digamma(z, a, prec); acb_neg(z, z); if (!acb_is_finite(z)) /* todo: in digamma */ acb_indeterminate(z); return; } is_real = const_is_real = 0; if (acb_is_real(s) && acb_is_real(a)) { if (arb_is_positive(acb_realref(a))) { is_real = const_is_real = 1; } else if (arb_is_int(acb_realref(a)) && arb_is_int(acb_realref(s)) && arb_is_nonpositive(acb_realref(s))) { const_is_real = 1; } } mag_init(bound); vb = _arb_vec_init(d); bound_prec = 40 + prec / 20; _acb_poly_zeta_em_choose_param(bound, &N, &M, s, a, FLINT_MIN(d, 2), prec, bound_prec); _acb_poly_zeta_em_bound(vb, s, a, N, M, d, bound_prec); _acb_poly_zeta_em_sum(z, s, a, deflate, N, M, d, prec); for (i = 0; i < d; i++) { arb_get_mag(bound, vb + i); arb_add_error_mag(acb_realref(z + i), bound); if (!is_real && !(i == 0 && const_is_real)) arb_add_error_mag(acb_imagref(z + i), bound); } mag_clear(bound); _arb_vec_clear(vb, d); } void _acb_poly_zeta_series(acb_ptr res, acb_srcptr h, slong hlen, const acb_t a, int deflate, slong len, slong prec) { acb_ptr t, u; hlen = FLINT_MIN(hlen, len); t = _acb_vec_init(len); u = _acb_vec_init(len); if (acb_is_one(a)) acb_dirichlet_zeta_jet(t, h, deflate, len, prec); else _acb_poly_zeta_cpx_series(t, h, a, deflate, len, prec); /* compose with nonconstant part */ acb_zero(u); _acb_vec_set(u + 1, h + 1, hlen - 1); _acb_poly_compose_series(res, t, len, u, hlen, len, prec); _acb_vec_clear(t, len); _acb_vec_clear(u, len); } void acb_poly_zeta_series(acb_poly_t res, const acb_poly_t f, const acb_t a, int deflate, slong n, slong prec) { if (n == 0) { acb_poly_zero(res); return; } acb_poly_fit_length(res, n); if (f->length == 0) { acb_t t; acb_init(t); _acb_poly_zeta_series(res->coeffs, t, 1, a, deflate, n, prec); acb_clear(t); } else { _acb_poly_zeta_series(res->coeffs, f->coeffs, f->length, a, deflate, n, prec); } _acb_poly_set_length(res, n); _acb_poly_normalise(res); } flint-3.1.3/src/acb_theta.h000066400000000000000000000263031461254215100155110ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_THETA_H #define ACB_THETA_H #include "fmpz_mat.h" #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif #define ACB_THETA_LOW_PREC 32 /* The Siegel modular group */ FLINT_FORCE_INLINE slong sp2gz_dim(const fmpz_mat_t mat) { return fmpz_mat_nrows(mat) / 2; } void sp2gz_set_blocks(fmpz_mat_t mat, const fmpz_mat_t alpha, const fmpz_mat_t beta, const fmpz_mat_t gamma, const fmpz_mat_t delta); void sp2gz_j(fmpz_mat_t mat); void sp2gz_block_diag(fmpz_mat_t mat, const fmpz_mat_t U); void sp2gz_trig(fmpz_mat_t mat, const fmpz_mat_t S); void sp2gz_embed(fmpz_mat_t res, const fmpz_mat_t mat); void sp2gz_restrict(fmpz_mat_t res, const fmpz_mat_t mat); slong sp2gz_nb_fundamental(slong g); void sp2gz_fundamental(fmpz_mat_t mat, slong j); int sp2gz_is_correct(const fmpz_mat_t mat); int sp2gz_is_j(const fmpz_mat_t mat); int sp2gz_is_block_diag(const fmpz_mat_t mat); int sp2gz_is_trig(const fmpz_mat_t mat); int sp2gz_is_embedded(fmpz_mat_t res, const fmpz_mat_t mat); void sp2gz_inv(fmpz_mat_t inv, const fmpz_mat_t mat); fmpz_mat_struct * sp2gz_decompose(slong * nb, const fmpz_mat_t mat); void sp2gz_randtest(fmpz_mat_t mat, flint_rand_t state, slong bits); /* The Siegel half space */ void acb_siegel_cocycle(acb_mat_t c, const fmpz_mat_t mat, const acb_mat_t tau, slong prec); void acb_siegel_transform_cocycle_inv(acb_mat_t w, acb_mat_t c, acb_mat_t cinv, const fmpz_mat_t mat, const acb_mat_t tau, slong prec); void acb_siegel_transform(acb_mat_t w, const fmpz_mat_t mat, const acb_mat_t tau, slong prec); void acb_siegel_transform_z(acb_ptr r, acb_mat_t w, const fmpz_mat_t mat, acb_srcptr z, const acb_mat_t tau, slong prec); void acb_siegel_cho(arb_mat_t C, const acb_mat_t tau, slong prec); void acb_siegel_yinv(arb_mat_t Yinv, const acb_mat_t tau, slong prec); void acb_siegel_reduce(fmpz_mat_t mat, const acb_mat_t tau, slong prec); int acb_siegel_is_reduced(const acb_mat_t tau, slong tol_exp, slong prec); void acb_siegel_randtest(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits); void acb_siegel_randtest_reduced(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits); void acb_siegel_randtest_vec(acb_ptr z, flint_rand_t state, slong g, slong prec); /* Theta characteristics */ void acb_theta_char_get_slong(slong * n, ulong a, slong g); ulong acb_theta_char_get_a(const slong * n, slong g); void acb_theta_char_get_arb(arb_ptr v, ulong a, slong g); void acb_theta_char_get_acb(acb_ptr v, ulong a, slong g); slong acb_theta_char_dot(ulong a, ulong b, slong g); slong acb_theta_char_dot_slong(ulong a, const slong * n, slong g); void acb_theta_char_dot_acb(acb_t x, ulong a, acb_srcptr z, slong g, slong prec); int acb_theta_char_is_even(ulong ab, slong g); int acb_theta_char_is_goepel(ulong ch1, ulong ch2, ulong ch3, ulong ch4, slong g); int acb_theta_char_is_syzygous(ulong ch1, ulong ch2, ulong ch3, slong g); /* Ellipsoids in naive algorithms */ struct acb_theta_eld_struct { slong dim, ambient_dim; slong * last_coords; slong min, mid, max, nr, nl; struct acb_theta_eld_struct * rchildren; struct acb_theta_eld_struct * lchildren; slong nb_pts, nb_border; slong * box; }; typedef struct acb_theta_eld_struct acb_theta_eld_t[1]; #define acb_theta_eld_dim(E) ((E)->dim) #define acb_theta_eld_ambient_dim(E) ((E)->ambient_dim) #define acb_theta_eld_coord(E, k) ((E)->last_coords[(k) - acb_theta_eld_dim(E)]) #define acb_theta_eld_min(E) ((E)->min) #define acb_theta_eld_mid(E) ((E)->mid) #define acb_theta_eld_max(E) ((E)->max) #define acb_theta_eld_nr(E) ((E)->nr) #define acb_theta_eld_nl(E) ((E)->nl) #define acb_theta_eld_rchild(E, k) (&(E)->rchildren[(k)]) #define acb_theta_eld_lchild(E, k) (&(E)->lchildren[(k)]) #define acb_theta_eld_nb_pts(E) ((E)->nb_pts) #define acb_theta_eld_nb_border(E) ((E)->nb_border) #define acb_theta_eld_box(E, k) ((E)->box[(k)]) void acb_theta_eld_init(acb_theta_eld_t E, slong d, slong g); void acb_theta_eld_clear(acb_theta_eld_t E); int acb_theta_eld_set(acb_theta_eld_t E, const arb_mat_t C, const arf_t R2, arb_srcptr v); void acb_theta_eld_points(slong * pts, const acb_theta_eld_t E); void acb_theta_eld_border(slong * pts, const acb_theta_eld_t E); int acb_theta_eld_contains(const acb_theta_eld_t E, const slong * pt); void acb_theta_eld_print(const acb_theta_eld_t E); /* Naive algorithms */ void acb_theta_naive_radius(arf_t R2, arf_t eps, const arb_mat_t C, slong ord, slong prec); void acb_theta_naive_reduce(arb_ptr v, acb_ptr new_zs, arb_ptr as, acb_ptr cs, arb_ptr us, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec); void acb_theta_naive_term(acb_t res, acb_srcptr z, const acb_mat_t tau, const slong * tup, const slong * n, slong prec); typedef void (*acb_theta_naive_worker_t)(acb_ptr, acb_srcptr, acb_srcptr, const slong *, slong, const acb_t, const slong *, slong, slong, slong, slong); void acb_theta_naive_worker(acb_ptr th, slong len, acb_srcptr zs, slong nb, const acb_mat_t tau, const acb_theta_eld_t E, slong ord, slong prec, acb_theta_naive_worker_t worker); void acb_theta_naive_00(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec); void acb_theta_naive_0b(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec); void acb_theta_naive_fixed_ab(acb_ptr th, ulong ab, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec); void acb_theta_naive_fixed_a(acb_ptr th, ulong a, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec); void acb_theta_naive_all(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec); /* Naive algorithms for derivatives */ slong acb_theta_jet_nb(slong ord, slong g); slong acb_theta_jet_total_order(const slong * tup, slong g); void acb_theta_jet_tuples(slong * tups, slong ord, slong g); slong acb_theta_jet_index(const slong * tup, slong g); void acb_theta_jet_mul(acb_ptr res, acb_srcptr v1, acb_srcptr v2, slong ord, slong g, slong prec); void acb_theta_jet_compose(acb_ptr res, acb_srcptr v, const acb_mat_t N, slong ord, slong prec); void acb_theta_jet_exp_pi_i(acb_ptr res, arb_srcptr a, slong ord, slong g, slong prec); void acb_theta_jet_naive_radius(arf_t R2, arf_t eps, const arb_mat_t C, arb_srcptr v, slong ord, slong prec); void acb_theta_jet_naive_00(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec); void acb_theta_jet_naive_fixed_ab(acb_ptr dth, ulong ab, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec); void acb_theta_jet_naive_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec); void acb_theta_jet_error_bounds(arb_ptr err, acb_srcptr z, const acb_mat_t tau, acb_srcptr dth, slong ord, slong prec); /* Quasi-linear algorithms on the reduced domain */ void acb_theta_dist_pt(arb_t d, arb_srcptr v, const arb_mat_t C, const slong * n, slong prec); void acb_theta_dist_lat(arb_t d, arb_srcptr v, const arb_mat_t C, slong prec); void acb_theta_dist_a0(arb_ptr d, acb_srcptr z, const acb_mat_t tau, slong prec); slong acb_theta_dist_addprec(const arb_t d); void acb_theta_agm_hadamard(acb_ptr res, acb_srcptr a, slong g, slong prec); void acb_theta_agm_sqrt(acb_ptr res, acb_srcptr a, acb_srcptr roots, slong nb, slong prec); void acb_theta_agm_mul(acb_ptr res, acb_srcptr a1, acb_srcptr a2, slong g, slong prec); void acb_theta_agm_mul_tight(acb_ptr res, acb_srcptr a0, acb_srcptr a, arb_srcptr d0, arb_srcptr d, slong g, slong prec); typedef int (*acb_theta_ql_worker_t)(acb_ptr, acb_srcptr, acb_srcptr, arb_srcptr, arb_srcptr, const acb_mat_t, slong, slong); int acb_theta_ql_a0_naive(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec); int acb_theta_ql_a0_split(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d, const acb_mat_t tau, slong s, slong guard, slong prec, acb_theta_ql_worker_t worker); int acb_theta_ql_a0_steps(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong nb_steps, slong s, slong guard, slong prec, acb_theta_ql_worker_t worker); slong acb_theta_ql_a0_nb_steps(const arb_mat_t C, slong s, slong prec); int acb_theta_ql_a0(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec); slong acb_theta_ql_reduce(acb_ptr x, acb_t c, arb_t u, slong * n1, acb_srcptr z, const acb_mat_t tau, slong prec); void acb_theta_ql_all(acb_ptr th, acb_srcptr z, const acb_mat_t tau, int sqr, slong prec); /* Quasi-linear algorithms for derivatives */ void acb_theta_jet_ql_bounds(arb_t c, arb_t rho, acb_srcptr z, const acb_mat_t tau, slong ord); void acb_theta_jet_ql_radius(arf_t eps, arf_t err, const arb_t c, const arb_t rho, slong ord, slong g, slong prec); void acb_theta_jet_ql_finite_diff(acb_ptr dth, const arf_t eps, const arf_t err, const arb_t rho, acb_srcptr val, slong ord, slong g, slong prec); void acb_theta_jet_ql_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec); /* Transformation formulas */ ulong acb_theta_transform_char(slong * e, const fmpz_mat_t mat, ulong ab); void acb_theta_transform_sqrtdet(acb_t res, const acb_mat_t tau, slong prec); slong acb_theta_transform_kappa(acb_t sqrtdet, const fmpz_mat_t mat, const acb_mat_t tau, slong prec); slong acb_theta_transform_kappa2(const fmpz_mat_t mat); void acb_theta_transform_proj(acb_ptr res, const fmpz_mat_t mat, acb_srcptr th, int sqr, slong prec); void acb_theta_all(acb_ptr th, acb_srcptr z, const acb_mat_t tau, int sqr, slong prec); void acb_theta_jet_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec); /* Genus 2 specifics */ #define ACB_THETA_G2_COV_NB 26 void acb_theta_g2_jet_naive_1(acb_ptr dth, const acb_mat_t tau, slong prec); void acb_theta_g2_detk_symj(acb_poly_t res, const acb_mat_t m, const acb_poly_t f, slong k, slong j, slong prec); void acb_theta_g2_transvectant(acb_poly_t res, const acb_poly_t g, const acb_poly_t h, slong m, slong n, slong k, slong prec); void acb_theta_g2_transvectant_lead(acb_t r, const acb_poly_t g, const acb_poly_t h, slong m, slong n, slong k, slong prec); slong acb_theta_g2_character(const fmpz_mat_t mat); void acb_theta_g2_psi4(acb_t res, acb_srcptr th2, slong prec); void acb_theta_g2_psi6(acb_t res, acb_srcptr th2, slong prec); void acb_theta_g2_chi10(acb_t res, acb_srcptr th2, slong prec); void acb_theta_g2_chi12(acb_t res, acb_srcptr th2, slong prec); void acb_theta_g2_chi5(acb_t res, acb_srcptr th, slong prec); void acb_theta_g2_chi35(acb_t res, acb_srcptr th, slong prec); void acb_theta_g2_chi3_6(acb_poly_t res, acb_srcptr dth, slong prec); void acb_theta_g2_sextic(acb_poly_t res, const acb_mat_t tau, slong prec); void acb_theta_g2_sextic_chi5(acb_poly_t res, acb_t chi5, const acb_mat_t tau, slong prec); void acb_theta_g2_covariants(acb_poly_struct * res, const acb_poly_t f, slong prec); void acb_theta_g2_covariants_lead(acb_ptr res, const acb_poly_t f, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acb_theta/000077500000000000000000000000001461254215100153345ustar00rootroot00000000000000flint-3.1.3/src/acb_theta/agm_hadamard.c000066400000000000000000000016551461254215100200740ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_agm_hadamard(acb_ptr res, acb_srcptr a, slong g, slong prec) { acb_ptr v; slong half; if (g == 0) { acb_set(&res[0], &a[0]); } else { half = 1 << (g - 1); v = _acb_vec_init(1 << g); acb_theta_agm_hadamard(v, a, g - 1, prec); acb_theta_agm_hadamard(v + half, a + half, g - 1, prec); _acb_vec_add(res, v, v + half, half, prec); _acb_vec_sub(res + half, v, v + half, half, prec); _acb_vec_clear(v, 1 << g); } } flint-3.1.3/src/acb_theta/agm_mul.c000066400000000000000000000020541461254215100171220ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_agm_mul(acb_ptr res, acb_srcptr a1, acb_srcptr a2, slong g, slong prec) { acb_ptr v; slong n = 1 << g; slong k; v = _acb_vec_init(2 * n); acb_theta_agm_hadamard(v, a1, g, prec); if (a1 == a2) { for (k = 0; k < n; k++) { acb_sqr(&v[k], &v[k], prec); } } else { acb_theta_agm_hadamard(v + n, a2, g, prec); for (k = 0; k < n; k++) { acb_mul(&v[k], &v[k], &v[k + n], prec); } } acb_theta_agm_hadamard(res, v, g, prec); _acb_vec_scalar_mul_2exp_si(res, res, n, -2 * g); _acb_vec_clear(v, 2 * n); } flint-3.1.3/src/acb_theta/agm_mul_tight.c000066400000000000000000000104671461254215100203300ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" static void acb_theta_agm_rel_mag_err(arf_t m, arf_t eps, acb_srcptr a, arb_srcptr d, slong nb, slong prec) { acb_t x, err; arb_t y; arf_t abs; slong k; acb_init(x); acb_init(err); arb_init(y); arf_init(abs); arf_zero(m); arf_zero(eps); for (k = 0; k < nb; k++) { arb_zero(y); arb_get_ubound_arf(arb_midref(y), &d[k], prec); arb_exp(y, y, prec); acb_mul_arb(x, &a[k], y, prec); acb_abs(y, x, prec); arb_get_ubound_arf(abs, y, prec); arf_max(m, m, abs); acb_zero(err); arf_set_mag(arb_midref(acb_realref(err)), arb_radref(acb_realref(x))); arf_set_mag(arb_midref(acb_imagref(err)), arb_radref(acb_imagref(x))); acb_abs(y, err, prec); arb_get_ubound_arf(abs, y, prec); arf_max(eps, eps, abs); } acb_clear(x); acb_clear(err); arb_clear(y); arf_clear(abs); } /* This is assuming a0 corresponds to theta constants */ static void acb_theta_agm_mul_tight_gen(acb_ptr res, acb_srcptr a0, acb_srcptr a, arb_srcptr d0, arb_srcptr d, slong g, slong prec) { slong n = 1 << g; slong lp = ACB_THETA_LOW_PREC; slong hprec = prec; acb_ptr v0, v; arf_t m0, m, eps0, eps, e, t; arb_t err; slong k; v0 = _acb_vec_init(n); v = _acb_vec_init(n); arf_init(m0); arf_init(m); arf_init(eps0); arf_init(eps); arf_init(e); arf_init(t); arb_init(err); acb_theta_agm_rel_mag_err(m0, eps0, a0, d0, n, prec); acb_theta_agm_rel_mag_err(m, eps, a, d, n, prec); for (k = 0; k < n; k++) { hprec = FLINT_MAX(hprec, prec + acb_theta_dist_addprec(&d[k])); acb_get_mid(&v0[k], &a0[k]); acb_get_mid(&v[k], &a[k]); } /* Perform agm_mul or agm_sqr at high precision */ if (a0 == a) { acb_theta_agm_mul(res, v0, v0, g, hprec); } else { acb_theta_agm_mul(res, v0, v, g, hprec); } /* New relative error wrt distances is m0 eps + m eps0 + eps0 eps */ arf_mul(e, m0, eps, lp, ARF_RND_CEIL); arf_mul(t, m, eps0, lp, ARF_RND_CEIL); arf_add(e, e, t, lp, ARF_RND_CEIL); arf_mul(t, eps, eps0, lp, ARF_RND_CEIL); arf_add(e, e, t, lp, ARF_RND_CEIL); for (k = 0; k < n; k++) { arb_neg(err, &d[k]); arb_exp(err, err, prec); arb_mul_arf(err, err, e, lp); acb_add_error_arb(&res[k], err); } _acb_vec_clear(v0, n); _acb_vec_clear(v, n); arf_clear(m0); arf_clear(m); arf_clear(eps0); arf_clear(eps); arf_clear(e); arf_clear(t); arb_clear(err); } /* there might be a way of saving some multiplications here by writing in terms of real & imaginary parts */ static void acb_theta_agm_mul_tight_g1(acb_ptr res, acb_srcptr a0, acb_srcptr a, arb_srcptr d0, arb_srcptr d, slong g, slong prec) { acb_t t; acb_ptr aux; acb_init(t); aux = _acb_vec_init(2); if (a == a0) { acb_sqr(t, &a[0], prec); acb_sqr(&aux[0], &a[1], prec); acb_add(&aux[0], &aux[0], t, prec + acb_theta_dist_addprec(&d[0])); acb_mul(&aux[1], &a[0], &a[1], prec); acb_mul_2exp_si(&aux[1], &aux[1], 1); } else { acb_mul(t, &a0[0], &a[0], prec); acb_mul(&aux[0], &a0[1], &a[1], prec); acb_add(&aux[0], &aux[0], t, prec + acb_theta_dist_addprec(&d[0])); acb_mul(t, &a0[0], &a[1], prec); acb_mul(&aux[1], &a0[1], &a[0], prec); acb_add(&aux[1], &aux[1], t, prec + acb_theta_dist_addprec(&d[1])); } _acb_vec_scalar_mul_2exp_si(res, aux, 2, -1); acb_clear(t); _acb_vec_clear(aux, 2); } void acb_theta_agm_mul_tight(acb_ptr res, acb_srcptr a0, acb_srcptr a, arb_srcptr d0, arb_srcptr d, slong g, slong prec) { if (g == 1) { acb_theta_agm_mul_tight_g1(res, a0, a, d0, d, g, prec); } else { acb_theta_agm_mul_tight_gen(res, a0, a, d0, d, g, prec); } } flint-3.1.3/src/acb_theta/agm_sqrt.c000066400000000000000000000022151461254215100173150ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" static void acb_theta_agm_sqrt_entry(acb_t res, const acb_t a, const acb_t rt, slong prec) { acb_t y1, y2; int t1, t2; acb_init(y1); acb_init(y2); acb_sqrts(y1, y2, a, prec); t1 = acb_overlaps(rt, y1); t2 = acb_overlaps(rt, y2); if (t1 && t2) { acb_union(res, y1, y2, prec); } else if (t1) { acb_set(res, y1); } else if (t2) { acb_set(res, y2); } else { acb_indeterminate(res); } acb_clear(y1); acb_clear(y2); } void acb_theta_agm_sqrt(acb_ptr res, acb_srcptr a, acb_srcptr rts, slong nb, slong prec) { slong k; for (k = 0; k < nb; k++) { acb_theta_agm_sqrt_entry(&res[k], &a[k], &rts[k], prec); } } flint-3.1.3/src/acb_theta/all.c000066400000000000000000000047231461254215100162560ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_mat.h" #include "acb_theta.h" void acb_theta_all(acb_ptr th, acb_srcptr z, const acb_mat_t tau, int sqr, slong prec) { slong g = acb_mat_nrows(tau); slong n2 = 1 << (2 * g); fmpz_mat_t mat, gamma; acb_mat_t w, c, N; acb_ptr x, y, aux, units; acb_t s, t; ulong ab, image_ab; slong kappa, e; fmpz_mat_init(mat, 2 * g, 2 * g); acb_mat_init(w, g, g); acb_mat_init(c, g, g); acb_mat_init(N, g, g); x = _acb_vec_init(g); y = _acb_vec_init(g); aux = _acb_vec_init(n2); units = _acb_vec_init(8); acb_init(s); acb_init(t); acb_siegel_reduce(mat, tau, prec); acb_siegel_transform_z(x, w, mat, z, tau, prec); acb_siegel_cocycle(c, mat, tau, prec); _acb_vec_unit_roots(units, 8, 8, prec); if (acb_siegel_is_reduced(w, -10, prec)) { sp2gz_inv(mat, mat); fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); acb_mat_set_fmpz_mat(N, gamma); fmpz_mat_window_clear(gamma); acb_mat_mul(N, c, N, prec); acb_mat_vector_mul_col(y, N, x, prec); acb_dot(t, NULL, 0, x, 1, y, 1, g, prec); acb_theta_ql_all(aux, x, w, sqr, prec); if (sqr) { kappa = acb_theta_transform_kappa2(mat); acb_siegel_cocycle(c, mat, w, prec); acb_mat_det(s, c, prec); acb_mul_2exp_si(t, t, 1); } else { kappa = acb_theta_transform_kappa(s, mat, w, prec); } acb_exp_pi_i(t, t, prec); acb_mul(s, s, t, prec); for (ab = 0; ab < n2; ab++) { image_ab = acb_theta_transform_char(&e, mat, ab); acb_mul(t, s, &units[((sqr ? 2 : 1) * (kappa + e)) % 8], prec); acb_mul(&th[ab], &aux[image_ab], t, prec); } } else { _acb_vec_indeterminate(th, n2); } fmpz_mat_clear(mat); acb_mat_clear(w); acb_mat_clear(c); acb_mat_clear(N); _acb_vec_clear(x, g); _acb_vec_clear(y, g); _acb_vec_clear(aux, n2); _acb_vec_clear(units, 8); acb_clear(s); acb_clear(t); } flint-3.1.3/src/acb_theta/char_dot.c000066400000000000000000000012201461254215100172560ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" slong acb_theta_char_dot(ulong a, ulong b, slong g) { int sgn = 0; slong k; ulong and = a & b; for (k = 0; k < g; k++) { if (and & 1) { sgn++; } and = and >> 1; } return sgn % 4; } flint-3.1.3/src/acb_theta/char_dot_acb.c000066400000000000000000000012751461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_char_dot_acb(acb_t x, ulong a, acb_srcptr z, slong g, slong prec) { slong * v; v = flint_malloc(g * sizeof(slong)); acb_theta_char_get_slong(v, a, g); acb_dot_si(x, NULL, 0, z, 1, v, 1, g, prec); acb_mul_2exp_si(x, x, -1); flint_free(v); } flint-3.1.3/src/acb_theta/char_dot_slong.c000066400000000000000000000012771461254215100204740ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" slong acb_theta_char_dot_slong(ulong a, const slong * n, slong g) { ulong a_shift = a; slong sgn = 0; slong k; for (k = 0; k < g; k++) { if (a_shift & 1) { sgn += n[g - 1 - k] & 3; } a_shift = a_shift >> 1; } return sgn % 4; } flint-3.1.3/src/acb_theta/char_get_a.c000066400000000000000000000011241461254215100175520ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" ulong acb_theta_char_get_a(const slong * n, slong g) { slong k; ulong a = 0; for (k = 0; k < g; k++) { a *= 2; a += ((n[k] % 2) + 2) % 2; } return a; } flint-3.1.3/src/acb_theta/char_get_acb.c000066400000000000000000000011771461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_char_get_acb(acb_ptr v, ulong a, slong g) { slong k; for (k = g - 1; k >= 0; k--) { acb_set_si(&v[k], a & 1); a = a >> 1; } _acb_vec_scalar_mul_2exp_si(v, v, g, -1); } flint-3.1.3/src/acb_theta/char_get_arb.c000066400000000000000000000011771461254215100201060ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb_theta.h" void acb_theta_char_get_arb(arb_ptr v, ulong a, slong g) { slong k; for (k = g - 1; k >= 0; k--) { arb_set_si(&v[k], a & 1); a = a >> 1; } _arb_vec_scalar_mul_2exp_si(v, v, g, -1); } flint-3.1.3/src/acb_theta/char_get_slong.c000066400000000000000000000010661461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void acb_theta_char_get_slong(slong * n, ulong a, slong g) { slong k; for (k = g - 1; k >= 0; k--) { n[k] = a & 1; a = a >> 1; } } flint-3.1.3/src/acb_theta/char_is_even.c000066400000000000000000000010171461254215100201240ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int acb_theta_char_is_even(ulong ab, slong g) { ulong a = ab >> g; return (acb_theta_char_dot(a, ab, g) % 2 == 0); } flint-3.1.3/src/acb_theta/char_is_goepel.c000066400000000000000000000014741461254215100204510ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int acb_theta_char_is_goepel(ulong ch1, ulong ch2, ulong ch3, ulong ch4, slong g) { if (ch1 == ch2 || ch1 == ch3 || ch1 == ch4 || ch2 == ch3 || ch2 == ch4 || ch3 == ch4) { return 0; } return acb_theta_char_is_even(ch1, g) && acb_theta_char_is_even(ch2, g) && acb_theta_char_is_even(ch3, g) && acb_theta_char_is_even(ch4, g) && ((ch1 ^ ch2 ^ ch3 ^ ch4) == 0); } flint-3.1.3/src/acb_theta/char_is_syzygous.c000066400000000000000000000010471461254215100211060ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int acb_theta_char_is_syzygous(ulong ch1, ulong ch2, ulong ch3, slong g) { return acb_theta_char_is_goepel(ch1, ch2, ch3, ch1 ^ ch2 ^ ch3, g); } flint-3.1.3/src/acb_theta/dist_a0.c000066400000000000000000000022541461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_theta_dist_a0(arb_ptr d, acb_srcptr z, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; arb_mat_t Yinv, C; arb_ptr v, w; ulong a; arb_mat_init(Yinv, g, g); arb_mat_init(C, g, g); v = _arb_vec_init(g); w = _arb_vec_init(g); acb_siegel_yinv(Yinv, tau, prec); acb_siegel_cho(C, tau, prec); _acb_vec_get_imag(v, z, g); arb_mat_vector_mul_col(v, Yinv, v, prec); for (a = 0; a < n; a++) { acb_theta_char_get_arb(w, a, g); _arb_vec_add(w, v, w, g, prec); arb_mat_vector_mul_col(w, C, w, prec); acb_theta_dist_lat(&d[a], w, C, prec); } arb_mat_clear(Yinv); arb_mat_clear(C); _arb_vec_clear(v, g); _arb_vec_clear(w, g); } flint-3.1.3/src/acb_theta/dist_addprec.c000066400000000000000000000015121461254215100201240ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb_theta.h" slong acb_theta_dist_addprec(const arb_t d2) { arb_t x; slong prec = ACB_THETA_LOW_PREC; slong res; arb_init(x); arb_const_log2(x, prec); arb_div(x, d2, x, prec); if (arb_is_finite(x) && (arf_cmpabs_2exp_si(arb_midref(x), 30) <= 0)) { res = arf_get_si(arb_midref(x), prec); } else /* should never happen */ { res = 0; } arb_clear(x); return res; } flint-3.1.3/src/acb_theta/dist_lat.c000066400000000000000000000060221461254215100173030ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" static void acb_theta_dist_unif(arb_t d, const arb_mat_t C, slong prec) { slong g = arb_mat_nrows(C); arb_ptr v; slong k; v = _arb_vec_init(g); for (k = 0; k < g; k++) { arb_zero_pm_one(&v[k]); arb_mul_2exp_si(&v[k], &v[k], -1); } arb_mat_vector_mul_col(v, C, v, prec); arb_dot(d, NULL, 0, v, 1, v, 1, g, prec); _arb_vec_clear(v, g); } static void acb_theta_dist_ubound(arf_t u, arb_srcptr v, const arb_mat_t C, slong prec) { slong g = acb_mat_nrows(C); slong nb = 1 << g; arb_mat_t Cinv; arb_ptr x; slong * approx; slong * pt; arb_t d; arf_t b; slong j, k; int r = 1; arb_mat_init(Cinv, g, g); x = _arb_vec_init(g); approx = flint_malloc(2 * g * sizeof(slong)); pt = flint_malloc(g * sizeof(slong)); arb_init(d); arf_init(b); arb_mat_one(Cinv); arb_mat_solve_triu(Cinv, C, Cinv, 0, prec); arb_mat_vector_mul_col(x, Cinv, v, prec); r = _arb_vec_is_finite(x, g); for (k = 0; (k < g) && r; k++) { r = (arf_cmpabs_2exp_si(arb_midref(&x[k]), 30) <= 0); if (r) { approx[2 * k] = - arf_get_si(arb_midref(&x[k]), ARF_RND_FLOOR); approx[2 * k + 1] = - arf_get_si(arb_midref(&x[k]), ARF_RND_CEIL); } } arf_pos_inf(u); if (r) { for (k = 0; k < nb; k++) { for (j = 0; j < g; j++) { pt[j] = approx[2 * j + (k & (1 << j) ? 0 : 1)]; } acb_theta_dist_pt(d, v, C, pt, prec); arb_get_ubound_arf(b, d, prec); arf_min(u, u, b); } } arb_mat_clear(Cinv); _arb_vec_clear(x, g); flint_free(approx); flint_free(pt); arb_clear(d); arf_clear(b); } void acb_theta_dist_lat(arb_t d, arb_srcptr v, const arb_mat_t C, slong prec) { slong g = arb_mat_nrows(C); acb_theta_eld_t E; slong nb; slong * pts; arf_t u; arb_t x; slong k; int b; acb_theta_eld_init(E, g, g); arf_init(u); arb_init(x); acb_theta_dist_ubound(u, v, C, prec); b = acb_theta_eld_set(E, C, u, v); if (b) { nb = acb_theta_eld_nb_pts(E); pts = flint_malloc(nb * g * sizeof(slong)); acb_theta_eld_points(pts, E); arb_pos_inf(d); for (k = 0; k < nb; k++) { acb_theta_dist_pt(x, v, C, pts + k * g, prec); arb_min(d, d, x, prec); } flint_free(pts); } else { acb_theta_dist_unif(d, C, prec); } arb_nonnegative_part(d, d); acb_theta_eld_clear(E); arf_clear(u); arb_clear(x); } flint-3.1.3/src/acb_theta/dist_pt.c000066400000000000000000000015021461254215100171440ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_theta.h" void acb_theta_dist_pt(arb_t d, arb_srcptr v, const arb_mat_t C, const slong * n, slong prec) { slong g = arb_mat_nrows(C); arb_ptr w; slong k; w = _arb_vec_init(g); for (k = 0; k < g; k++) { arb_set_si(&w[k], n[k]); } arb_mat_vector_mul_col(w, C, w, prec); _arb_vec_add(w, w, v, g, prec); arb_dot(d, NULL, 0, w, 1, w, 1, g, prec); _arb_vec_clear(w, g); } flint-3.1.3/src/acb_theta/eld_border.c000066400000000000000000000025571461254215100176120ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void acb_theta_eld_border(slong * pts, const acb_theta_eld_t E) { slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); slong nr = acb_theta_eld_nr(E); slong nl = acb_theta_eld_nl(E); slong max = acb_theta_eld_max(E); slong min = acb_theta_eld_min(E); slong k, i; if (d == 1) { pts[0] = min - 1; pts[g] = max + 1; for (k = 1; k < g; k++) { pts[k] = acb_theta_eld_coord(E, k); pts[k + g] = acb_theta_eld_coord(E, k); } } else /* d > 1 */ { i = 0; for (k = 0; k < nr; k++) { acb_theta_eld_border(&pts[i], acb_theta_eld_rchild(E, k)); i += g * acb_theta_eld_nb_border(acb_theta_eld_rchild(E, k)); } for (k = 0; k < nl; k++) { acb_theta_eld_border(&pts[i], acb_theta_eld_lchild(E, k)); i += g * acb_theta_eld_nb_border(acb_theta_eld_lchild(E, k)); } } } flint-3.1.3/src/acb_theta/eld_clear.c000066400000000000000000000016611461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void acb_theta_eld_clear(acb_theta_eld_t E) { slong k; slong nr = acb_theta_eld_nr(E); slong nl = acb_theta_eld_nl(E); if (nr > 0) { for (k = 0; k < nr; k++) { acb_theta_eld_clear(acb_theta_eld_rchild(E, k)); } flint_free(E->rchildren); } if (nl > 0) { for (k = 0; k < nl; k++) { acb_theta_eld_clear(acb_theta_eld_lchild(E, k)); } flint_free(E->lchildren); } flint_free(E->last_coords); flint_free(E->box); } flint-3.1.3/src/acb_theta/eld_contains.c000066400000000000000000000026271461254215100201510ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" static int acb_theta_eld_contains_rec(const acb_theta_eld_t E, const slong * pt) { slong d = acb_theta_eld_dim(E); slong c = pt[d - 1]; slong k; if (c < acb_theta_eld_min(E) || c > acb_theta_eld_max(E)) { return 0; } else if (d == 1) { return 1; } else if (c >= acb_theta_eld_mid(E)) { k = c - acb_theta_eld_mid(E); return acb_theta_eld_contains_rec(acb_theta_eld_rchild(E, k), pt); } else { k = acb_theta_eld_mid(E) - 1 - c; return acb_theta_eld_contains_rec(acb_theta_eld_lchild(E, k), pt); } } int acb_theta_eld_contains(const acb_theta_eld_t E, const slong * pt) { slong g = acb_theta_eld_ambient_dim(E); slong d = acb_theta_eld_dim(E); slong k; if (acb_theta_eld_nb_pts(E) == 0) { return 0; } for (k = d; k < g; k++) { if (pt[k] != acb_theta_eld_coord(E, k)) { return 0; } } return acb_theta_eld_contains_rec(E, pt); } flint-3.1.3/src/acb_theta/eld_init.c000066400000000000000000000014221461254215100172660ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void acb_theta_eld_init(acb_theta_eld_t E, slong d, slong g) { FLINT_ASSERT(d >= 1 && d <= g); acb_theta_eld_dim(E) = d; acb_theta_eld_ambient_dim(E) = g; E->last_coords = flint_malloc((g - d) * sizeof(slong)); E->rchildren = NULL; acb_theta_eld_nr(E) = 0; E->lchildren = NULL; acb_theta_eld_nl(E) = 0; E->box = flint_malloc(d * sizeof(slong)); } flint-3.1.3/src/acb_theta/eld_points.c000066400000000000000000000025421461254215100176430ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void acb_theta_eld_points(slong * pts, const acb_theta_eld_t E) { slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); slong nr = acb_theta_eld_nr(E); slong nl = acb_theta_eld_nl(E); slong k, j, i; if (d == 1) { i = 0; for (k = acb_theta_eld_min(E); k <= acb_theta_eld_max(E); k++) { pts[i] = k; for (j = 1; j < g; j++) { pts[i + j] = acb_theta_eld_coord(E, j); } i += g; } } else /* d > 1 */ { i = 0; for (k = 0; k < nr; k++) { acb_theta_eld_points(&pts[i], acb_theta_eld_rchild(E, k)); i += g * acb_theta_eld_nb_pts(acb_theta_eld_rchild(E, k)); } for (k = 0; k < nl; k++) { acb_theta_eld_points(&pts[i], acb_theta_eld_lchild(E, k)); i += g * acb_theta_eld_nb_pts(acb_theta_eld_lchild(E, k)); } } } flint-3.1.3/src/acb_theta/eld_print.c000066400000000000000000000022301461254215100174550ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void acb_theta_eld_print(const acb_theta_eld_t E) { slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); slong k; for (k = 0; k < g - d; k++) { flint_printf(" "); } flint_printf("Slice (..."); for (k = 0; k < g - d; k++) { flint_printf(", %wd", acb_theta_eld_coord(E, k + d)); } flint_printf("): from %wd to %wd (mid: %wd)\n", acb_theta_eld_min(E), acb_theta_eld_max(E), acb_theta_eld_mid(E)); if (d > 1) { for (k = 0; k < acb_theta_eld_nr(E); k++) { acb_theta_eld_print(acb_theta_eld_rchild(E, k)); } for (k = 0; k < acb_theta_eld_nl(E); k++) { acb_theta_eld_print(acb_theta_eld_lchild(E, k)); } } } flint-3.1.3/src/acb_theta/eld_set.c000066400000000000000000000202751461254215100171250ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_theta.h" #define ACB_THETA_ELD_MAX_PTS 1000000 #define ACB_THETA_ELD_MAX_ERR 100 static void slong_vec_max(slong * r, slong * v1, slong * v2, slong d) { slong k; for (k = 0; k < d; k++) { r[k] = FLINT_MAX(v1[k], v2[k]); } } static int arf_get_si_safe(slong * m, const arf_t x, arf_rnd_t rnd) { if (!arf_is_finite(x)) { return 0; } else if (arf_cmpabs_2exp_si(x, FLINT_BITS - 4) > 0) { return 0; } else { *m = arf_get_si(x, rnd); return 1; } } static int acb_theta_eld_interval(slong * min, slong * mid, slong * max, const arb_t ctr, const arf_t rad) { slong lp = ACB_THETA_LOW_PREC; slong e; arb_t y; arf_t b; int res; arb_init(y); arf_init(b); arf_set_mag(b, arb_radref(ctr)); res = arf_get_si_safe(&e, b, ARF_RND_NEAR); if (res) { res = (e <= ACB_THETA_ELD_MAX_ERR); } res = res && arf_get_si_safe(mid, arb_midref(ctr), ARF_RND_NEAR); arb_set_arf(y, rad); arb_add(y, ctr, y, lp); arb_get_ubound_arf(b, y, lp); res = res && arf_get_si_safe(max, b, ARF_RND_FLOOR); arb_set_arf(y, rad); arb_sub(y, ctr, y, lp); arb_get_lbound_arf(b, y, lp); res = res && arf_get_si_safe(min, b, ARF_RND_CEIL); arb_clear(y); arf_clear(b); return res; } static void acb_theta_eld_next_R2(arf_t next_R2, const arf_t R2, const arb_t gamma, const arb_t v, slong k) { slong lp = ACB_THETA_LOW_PREC; arb_t x; arf_t sub; arb_init(x); arf_init(sub); /* Set next_R2 to R2 - (v + gamma*k)^2 */ arb_mul_si(x, gamma, k, lp); arb_add(x, x, v, lp); arb_sqr(x, x, lp); arb_get_lbound_arf(sub, x, lp); arf_sub(next_R2, R2, sub, lp, ARF_RND_CEIL); arb_clear(x); arf_clear(sub); } static void acb_theta_eld_init_children(acb_theta_eld_t E, slong nr, slong nl) { slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); slong k; if (nr > 0) /* should always be the case */ { E->rchildren = flint_malloc(nr * sizeof(struct acb_theta_eld_struct)); acb_theta_eld_nr(E) = nr; for (k = 0; k < nr; k++) { acb_theta_eld_init(acb_theta_eld_rchild(E, k), d - 1, g); } } if (nl > 0) { E->lchildren = flint_malloc(nl * sizeof(struct acb_theta_eld_struct)); acb_theta_eld_nl(E) = nl; for (k = 0; k < nl; k++) { acb_theta_eld_init(acb_theta_eld_lchild(E, k), d - 1, g); } } } static int acb_theta_eld_init_interval(acb_theta_eld_t E, const arb_mat_t C, const arf_t R2, arb_srcptr v, slong * last_coords) { slong min, mid, max; slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); slong lp = ACB_THETA_LOW_PREC; slong k; arb_t x, ctr; arf_t rad; int res; arb_init(x); arb_init(ctr); arf_init(rad); for (k = 0; k < g - d; k++) { E->last_coords[k] = last_coords[k]; } if (arf_cmp_si(R2, 0) < 0) { arf_zero(rad); } else { arb_set_arf(x, R2); arb_sqrt(x, x, lp); arb_div(x, x, arb_mat_entry(C, d - 1, d - 1), lp); arb_get_ubound_arf(rad, x, lp); } arb_div(ctr, &v[d - 1], arb_mat_entry(C, d - 1, d - 1), lp); arb_neg(ctr, ctr); res = acb_theta_eld_interval(&min, &mid, &max, ctr, rad); if (res) { acb_theta_eld_min(E) = min; acb_theta_eld_mid(E) = mid; acb_theta_eld_max(E) = max; } arb_clear(x); arb_clear(ctr); arf_clear(rad); return res; } /* Main recursive function in dimension d>1 */ static int acb_theta_eld_set_rec(acb_theta_eld_t E, const arb_mat_t C, const arf_t R2, arb_srcptr v, slong * last_coords) { slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); slong lp = ACB_THETA_LOW_PREC; slong min, mid, max, k; arf_t next_R2; slong *next_coords; arb_ptr v_diff; arb_ptr v_mid; arb_ptr next_v; slong c; slong nr, nl; int res; res = acb_theta_eld_init_interval(E, C, R2, v, last_coords); if (!res) { return 0; } min = acb_theta_eld_min(E); mid = acb_theta_eld_mid(E); max = acb_theta_eld_max(E); /* Induction only if d > 1 and min <= max */ if (min > max) { acb_theta_eld_nb_pts(E) = 0; if (d == 1) { acb_theta_eld_nb_border(E) = 2; } else { acb_theta_eld_nb_border(E) = 0; } for (k = 0; k < d; k++) { acb_theta_eld_box(E, k) = 0; } return 1; } else if (d == 1) { acb_theta_eld_nb_pts(E) = max - min + 1; acb_theta_eld_nb_border(E) = 2; acb_theta_eld_box(E, 0) = FLINT_MAX(max, -min); return (acb_theta_eld_nb_pts(E) <= ACB_THETA_ELD_MAX_PTS); } /* Begin main function */ arf_init(next_R2); next_coords = flint_malloc((g - d + 1) * sizeof(slong)); v_diff = _arb_vec_init(d - 1); v_mid = _arb_vec_init(d - 1); next_v = _arb_vec_init(d - 1); /* Initialize children */ nr = max - mid + 1; nl = mid - min; acb_theta_eld_init_children(E, nr, nl); /* Set v_mid, v_diff */ for (k = 0; k < d - 1; k++) { arb_set(&v_diff[k], arb_mat_entry(C, k, d - 1)); arb_mul_si(&v_mid[k], &v_diff[k], mid, lp); } _arb_vec_add(v_mid, v_mid, v, d - 1, lp); for (k = 0; k < g - d; k++) { next_coords[k + 1] = last_coords[k]; } /* Set children recursively */ acb_theta_eld_nb_pts(E) = 0; acb_theta_eld_nb_border(E) = 0; acb_theta_eld_box(E, d - 1) = FLINT_MAX(max, -min); for (k = 0; k < d - 1; k++) { acb_theta_eld_box(E, k) = 0; } /* Right loop */ _arb_vec_set(next_v, v_mid, d - 1); for (k = 0; (k < nr) && res; k++) { if (k > 0) { _arb_vec_add(next_v, next_v, v_diff, d - 1, lp); } c = mid + k; acb_theta_eld_next_R2(next_R2, R2, arb_mat_entry(C, d - 1, d - 1), &v[d - 1], c); next_coords[0] = c; res = acb_theta_eld_set_rec(acb_theta_eld_rchild(E, k), C, next_R2, next_v, next_coords); if (res) { acb_theta_eld_nb_pts(E) += acb_theta_eld_nb_pts(acb_theta_eld_rchild(E, k)); acb_theta_eld_nb_border(E) += acb_theta_eld_nb_border(acb_theta_eld_rchild(E, k)); slong_vec_max(E->box, E->box, acb_theta_eld_rchild(E, k)->box, d - 1); res = (acb_theta_eld_nb_pts(E) <= ACB_THETA_ELD_MAX_PTS); } } /* Left loop */ _arb_vec_set(next_v, v_mid, d - 1); for (k = 0; (k < nl) && res; k++) { _arb_vec_sub(next_v, next_v, v_diff, d - 1, lp); c = mid - (k + 1); acb_theta_eld_next_R2(next_R2, R2, arb_mat_entry(C, d - 1, d - 1), &v[d - 1], c); next_coords[0] = c; res = acb_theta_eld_set_rec(acb_theta_eld_lchild(E, k), C, next_R2, next_v, next_coords); if (res) /* we expect this always holds */ { acb_theta_eld_nb_pts(E) += acb_theta_eld_nb_pts(acb_theta_eld_lchild(E, k)); acb_theta_eld_nb_border(E) += acb_theta_eld_nb_border(acb_theta_eld_lchild(E, k)); slong_vec_max(E->box, E->box, acb_theta_eld_lchild(E, k)->box, d - 1); res = (acb_theta_eld_nb_pts(E) <= ACB_THETA_ELD_MAX_PTS); } } arf_clear(next_R2); flint_free(next_coords); _arb_vec_clear(v_diff, d - 1); _arb_vec_clear(v_mid, d - 1); _arb_vec_clear(next_v, d - 1); return res; } int acb_theta_eld_set(acb_theta_eld_t E, const arb_mat_t C, const arf_t R2, arb_srcptr v) { slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); acb_theta_eld_clear(E); acb_theta_eld_init(E, d, g); return acb_theta_eld_set_rec(E, C, R2, v, NULL); } flint-3.1.3/src/acb_theta/g2_character.c000066400000000000000000000052161461254215100200300ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" /* See Cléry, Faber, van der Geer, "Covariants of binary sextics and modular forms of degree 2 with character", §12 */ static void g2_block_coeffs_mod_2(slong * coeffs, const fmpz_mat_t w) { fmpz_t x; fmpz_init(x); coeffs[0] = fmpz_mod_ui(x, fmpz_mat_entry(w, 0, 0), 2); coeffs[1] = fmpz_mod_ui(x, fmpz_mat_entry(w, 0, 1), 2); coeffs[2] = fmpz_mod_ui(x, fmpz_mat_entry(w, 1, 0), 2); coeffs[3] = fmpz_mod_ui(x, fmpz_mat_entry(w, 1, 1), 2); fmpz_clear(x); } static slong g2_block_det_mod_2(slong * coeffs) { return (coeffs[0] * coeffs[3] + coeffs[1] * coeffs[2]) % 2; } static slong g2_character_formula(slong * a, slong * b, slong * c, slong * d) { return (a[0] * c[0] + a[1] * c[0] + a[1] * c[1] + a[2] * c[2] + a[3] * c[2] + a[3] * c[3] + c[0] * c[1] + c[1] * c[2] + c[2] * c[3] + c[0] * d[3] + c[1] * d[2] + c[1] * d[3] + c[2] * d[1] + c[3] * d[0] + c[3] * d[1]) % 2; } static slong g2_character_switch(slong * a, slong * b, slong * c, slong * d, int twice) { slong row[4]; if (g2_block_det_mod_2(c) == 1) { return g2_character_formula(a, b, c, d); } if (g2_block_det_mod_2(a) == 1) { return g2_character_formula(c, d, a, b); } if (g2_block_det_mod_2(d) == 1) { return g2_character_formula(b, a, d, c); } if (g2_block_det_mod_2(b) == 1) { return g2_character_formula(d, c, b, a); } if (twice) { flint_throw(FLINT_ERROR, "error: went through g2_character_switch twice\n"); } row[0] = a[0]; row[1] = a[1]; row[2] = b[0]; row[3] = b[1]; a[0] = c[0]; a[1] = c[1]; b[0] = d[0]; b[1] = d[1]; c[0] = row[0]; c[1] = row[1]; d[0] = row[2]; d[1] = row[3]; return 1 - g2_character_switch(a, b, c, d, 1); } slong acb_theta_g2_character(const fmpz_mat_t mat) { fmpz_mat_t w; slong coeffs[16]; slong j, k; for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { fmpz_mat_window_init(w, mat, 2 * j, 2 * k, 2 * j + 2, 2 * k + 2); g2_block_coeffs_mod_2(coeffs + 4 * (2 * j + k), w); fmpz_mat_window_clear(w); } } return g2_character_switch(coeffs, coeffs + 4, coeffs + 8, coeffs + 12, 0); } flint-3.1.3/src/acb_theta/g2_chi10.c000066400000000000000000000014331461254215100167750ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_g2_chi10(acb_t res, acb_srcptr th2, slong prec) { slong g = 2; slong n = 1 << (2 * g); ulong ab; acb_t t; acb_init(t); acb_one(t); for (ab = 0; ab < n; ab++) { if (acb_theta_char_is_even(ab, g)) { acb_mul(t, t, &th2[ab], prec); } } acb_mul_2exp_si(res, t, -12); acb_clear(t); } flint-3.1.3/src/acb_theta/g2_chi12.c000066400000000000000000000030401461254215100167730ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_g2_chi12(acb_t res, acb_srcptr th2, slong prec) { slong g = 2; ulong ch1, ch2, ch3, ch4, ab; ulong n = 1 << (2 * g); acb_t s, t; acb_init(s); acb_init(t); for (ch1 = 0; ch1 < n; ch1++) { for (ch2 = ch1 + 1; ch2 < n; ch2++) { for (ch3 = ch2 + 1; ch3 < n; ch3++) { ch4 = ch1 ^ ch2 ^ ch3; if (acb_theta_char_is_goepel(ch1, ch2, ch3, ch4, g)) { acb_one(t); for (ab = 0; ab < n; ab++) { if (acb_theta_char_is_even(ab, g) && (ab != ch1) && (ab != ch2) && (ab != ch3) && (ab != ch4)) { acb_mul(t, t, &th2[ab], prec); } } acb_sqr(t, t, prec); acb_add(s, s, t, prec); } } } } acb_mul_2exp_si(res, s, -15); acb_clear(s); acb_clear(t); } flint-3.1.3/src/acb_theta/g2_chi35.c000066400000000000000000000057411461254215100170120ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" /* Bolza to Mumford: 0 -> {0,5} 2 -> {2,5} 4 -> {4,5} 5 -> empty set Then: {i,j} -> S = {i+1,j+1} */ /* Mumford to characteristics: emptyset -> 0 {1,2} -> 2 {1,4} -> 9 {1,6} -> 12 {2,3} -> 8 {2,5} -> 15 {3,4} -> 3 {3,6} -> 6 {4,5} -> 4 {5,6} -> 1 */ /* See Bolza, "Darstellung von Invarianten durch \theta-Functionen, p.493 */ static void bolza_E(acb_t E, acb_srcptr th, slong prec) { acb_ptr R; acb_ptr v; acb_ptr cmp; acb_t P; slong k; R = _acb_vec_init(15); v = _acb_vec_init(16); cmp = _acb_vec_init(15); acb_init(P); for (k = 0; k < 16; k++) { acb_pow_ui(&v[k], &th[k], 4, prec); } acb_sub(&R[0], &v[2], &v[6], prec); acb_sub(&cmp[0], &v[1], &v[9], prec); acb_sub(&R[1], &v[8], &v[12], prec); acb_sub(&cmp[1], &v[1], &v[3], prec); acb_sub(&R[2], &v[0], &v[4], prec); acb_add(&cmp[2], &v[9], &v[3], prec); acb_sub(&R[3], &v[4], &v[12], prec); acb_sub(&cmp[3], &v[2], &v[3], prec); acb_sub(&R[4], &v[0], &v[8], prec); acb_add(&cmp[4], &v[6], &v[3], prec); acb_sub(&R[5], &v[4], &v[6], prec); acb_sub(&cmp[5], &v[8], &v[9], prec); acb_sub(&R[6], &v[0], &v[2], prec); acb_add(&cmp[6], &v[12], &v[9], prec); acb_add(&R[7], &v[12], &v[6], prec); acb_sub(&cmp[7], &v[0], &v[1], prec); acb_sub(&R[8], &v[4], &v[2], prec); acb_sub(&cmp[8], &v[8], &v[1], prec); acb_add(&R[9], &v[8], &v[2], prec); acb_add(&cmp[9], &v[4], &v[1], prec); acb_sub(&R[10], &v[0], &v[6], prec); acb_add(&cmp[10], &v[12], &v[1], prec); acb_add(&R[11], &v[12], &v[2], prec); acb_sub(&cmp[11], &v[0], &v[9], prec); acb_sub(&R[12], &v[4], &v[8], prec); acb_sub(&cmp[12], &v[2], &v[1], prec); acb_add(&R[13], &v[6], &v[8], prec); acb_sub(&cmp[13], &v[0], &v[3], prec); acb_sub(&R[14], &v[0], &v[12], prec); acb_add(&cmp[14], &v[2], &v[9], prec); acb_one(P); for (k = 0; k < 16; k++) { if (acb_theta_char_is_even(k, 2)) { acb_mul(P, P, &th[k], prec); } } acb_one(E); for (k = 0; k < 15; k++) { acb_mul(E, E, &R[k], prec); } acb_mul(E, E, P, prec); /* prod (theta) * prod(Ri) */ _acb_vec_clear(R, 15); _acb_vec_clear(v, 16); _acb_vec_clear(cmp, 15); acb_clear(P); } /* See Igusa, "Modular forms and projective invariants" p. 848 */ void acb_theta_g2_chi35(acb_t res, acb_srcptr th, slong prec) { acb_t t; acb_init(t); bolza_E(t, th, prec); acb_neg(res, t); acb_mul_2exp_si(res, res, -37); acb_clear(t); } flint-3.1.3/src/acb_theta/g2_chi3_6.c000066400000000000000000000032721461254215100171470ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_theta.h" void acb_theta_g2_chi3_6(acb_poly_t res, acb_srcptr dth, slong prec) { slong g = 2; slong n = 1 << (2 * g); slong orders[2] = {1, 0}; slong i1 = acb_theta_jet_index(orders, g) - 1; /* 0 or 1 */ slong nb = acb_theta_jet_nb(1, g); acb_poly_struct * aux; acb_poly_t s; acb_t den; ulong ab; slong k; aux = flint_malloc(6 * sizeof(acb_poly_struct)); acb_poly_init(s); acb_init(den); for (k = 0; k < 6; k++) { acb_poly_init(&aux[k]); } k = 0; for (ab = 0; ab < n; ab++) { if (!acb_theta_char_is_even(ab, g)) { acb_poly_set_coeff_acb(&aux[k], 1, &dth[nb * ab + 1 + i1]); acb_poly_set_coeff_acb(&aux[k], 0, &dth[nb * ab + 1 + (1 - i1)]); k++; } } acb_poly_mul(res, &aux[0], &aux[1], prec); acb_poly_mul(res, res, &aux[2], prec); acb_poly_mul(s, &aux[3], &aux[4], prec); acb_poly_mul(s, s, &aux[5], prec); acb_poly_mul(res, res, s, prec); acb_const_pi(den, prec); acb_pow_ui(den, den, 6, prec); acb_poly_scalar_div(res, res, den, prec); acb_poly_scalar_mul_2exp_si(res, res, -6); acb_poly_clear(s); acb_clear(den); for (k = 0; k < 6; k++) { acb_poly_clear(&aux[k]); } flint_free(aux); } flint-3.1.3/src/acb_theta/g2_chi5.c000066400000000000000000000014561461254215100167260ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_g2_chi5(acb_t res, acb_srcptr th, slong prec) { slong g = 2; slong n = 1 << (2 * g); ulong ab; acb_t t; acb_init(t); acb_one(t); for (ab = 0; ab < n; ab++) { if (acb_theta_char_is_even(ab, g)) { acb_mul(t, t, &th[ab], prec); } } acb_neg(res, t); acb_mul_2exp_si(res, res, -6); acb_clear(t); } flint-3.1.3/src/acb_theta/g2_covariants.c000066400000000000000000000062031461254215100202420ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_theta.h" static void acb_theta_g2_transvectants(acb_poly_struct * res, const acb_poly_t f, slong prec) { acb_poly_t s; acb_poly_init(s); acb_poly_set(&res[0], f); acb_theta_g2_transvectant(&res[1], f, f, 6, 6, 6, prec); acb_theta_g2_transvectant(&res[2], f, f, 6, 6, 4, prec); acb_theta_g2_transvectant(&res[3], f, f, 6, 6, 2, prec); acb_theta_g2_transvectant(&res[4], f, &res[2], 6, 4, 4, prec); acb_theta_g2_transvectant(&res[5], f, &res[2], 6, 4, 2, prec); acb_theta_g2_transvectant(&res[6], f, &res[2], 6, 4, 1, prec); acb_theta_g2_transvectant(&res[7], f, &res[3], 6, 8, 1, prec); acb_theta_g2_transvectant(&res[8], &res[2], &res[2], 4, 4, 4, prec); acb_theta_g2_transvectant(&res[9], f, &res[4], 6, 2, 2, prec); acb_theta_g2_transvectant(&res[10], f, &res[4], 6, 2, 1, prec); acb_theta_g2_transvectant(&res[11], &res[3], &res[2], 8, 4, 1, prec); acb_theta_g2_transvectant(&res[12], &res[2], &res[4], 4, 2, 2, prec); acb_theta_g2_transvectant(&res[13], &res[2], &res[4], 4, 2, 1, prec); acb_theta_g2_transvectant(&res[14], &res[3], &res[4], 8, 2, 1, prec); acb_theta_g2_transvectant(&res[15], &res[4], &res[4], 2, 2, 2, prec); acb_theta_g2_transvectant(&res[16], &res[5], &res[4], 6, 2, 1, prec); acb_theta_g2_transvectant(&res[17], &res[6], &res[4], 8, 2, 2, prec); acb_poly_mul(s, &res[4], &res[4], prec); /* now C_32^2 */ acb_theta_g2_transvectant(&res[18], f, s, 6, 4, 4, prec); acb_theta_g2_transvectant(&res[19], f, s, 6, 4, 3, prec); acb_theta_g2_transvectant(&res[20], &res[2], s, 4, 4, 3, prec); acb_theta_g2_transvectant(&res[21], &res[6], s, 8, 4, 4, prec); acb_poly_mul(s, s, &res[4], prec); /* now C_32^3 */ acb_theta_g2_transvectant(&res[22], f, s, 6, 6, 6, prec); acb_theta_g2_transvectant(&res[23], f, s, 6, 6, 5, prec); acb_theta_g2_transvectant(&res[24], &res[6], s, 8, 6, 6, prec); acb_poly_mul(s, s, &res[4], prec); /* now C_32^4 */ acb_theta_g2_transvectant(&res[25], &res[6], s, 8, 8, 8, prec); acb_poly_clear(s); } void acb_theta_g2_covariants(acb_poly_struct * res, const acb_poly_t f, slong prec) { double cofactors[ACB_THETA_G2_COV_NB] = {1, 60, 75, 90, 2250, 2250, 450, 540, 11250, 67500, 13500, 13500, 168750, 67500, 405000, 10125000, 2025000, 2700000, 151875000, 60750000, 15187500, 9112500000, 227812500000, 13668750000, 8201250000000, 384433593750}; acb_t c; fmpz_t m; slong k; acb_init(c); fmpz_init(m); acb_theta_g2_transvectants(res, f, prec); for (k = 0; k < ACB_THETA_G2_COV_NB; k++) { fmpz_set_d(m, cofactors[k]); acb_set_fmpz(c, m); acb_poly_scalar_mul(&res[k], &res[k], c, prec); } acb_clear(c); fmpz_clear(m); } flint-3.1.3/src/acb_theta/g2_covariants_lead.c000066400000000000000000000070541461254215100212340ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_theta.h" static void acb_theta_g2_transvectants(acb_ptr res, const acb_poly_t f, slong prec) { acb_poly_t s, r2, r3, r4, r5, r6; acb_poly_init(s); acb_poly_init(r2); acb_poly_init(r3); acb_poly_init(r4); acb_poly_init(r5); acb_poly_init(r6); /* Get polynomials */ acb_theta_g2_transvectant(r2, f, f, 6, 6, 4, prec); acb_theta_g2_transvectant(r3, f, f, 6, 6, 2, prec); acb_theta_g2_transvectant(r4, f, r2, 6, 4, 4, prec); acb_theta_g2_transvectant(r5, f, r2, 6, 4, 2, prec); acb_theta_g2_transvectant(r6, f, r2, 6, 4, 1, prec); /* Get leading coefficients of f, r2, ..., r6 */ acb_poly_get_coeff_acb(&res[0], f, 6); acb_poly_get_coeff_acb(&res[2], r2, 4); acb_poly_get_coeff_acb(&res[3], r3, 8); acb_poly_get_coeff_acb(&res[4], r4, 2); acb_poly_get_coeff_acb(&res[5], r5, 6); acb_poly_get_coeff_acb(&res[6], r6, 8); /* Get other coefficients */ acb_theta_g2_transvectant_lead(&res[1], f, f, 6, 6, 6, prec); acb_theta_g2_transvectant_lead(&res[7], f, r3, 6, 8, 1, prec); acb_theta_g2_transvectant_lead(&res[8], r2, r2, 4, 4, 4, prec); acb_theta_g2_transvectant_lead(&res[9], f, r4, 6, 2, 2, prec); acb_theta_g2_transvectant_lead(&res[10], f, r4, 6, 2, 1, prec); acb_theta_g2_transvectant_lead(&res[11], r3, r2, 8, 4, 1, prec); acb_theta_g2_transvectant_lead(&res[12], r2, r4, 4, 2, 2, prec); acb_theta_g2_transvectant_lead(&res[13], r2, r4, 4, 2, 1, prec); acb_theta_g2_transvectant_lead(&res[14], r3, r4, 8, 2, 1, prec); acb_theta_g2_transvectant_lead(&res[15], r4, r4, 2, 2, 2, prec); acb_theta_g2_transvectant_lead(&res[16], r5, r4, 6, 2, 1, prec); acb_theta_g2_transvectant_lead(&res[17], r6, r4, 8, 2, 2, prec); acb_poly_mul(s, r4, r4, prec); /* C_32^2 */ acb_theta_g2_transvectant_lead(&res[18], f, s, 6, 4, 4, prec); acb_theta_g2_transvectant_lead(&res[19], f, s, 6, 4, 3, prec); acb_theta_g2_transvectant_lead(&res[20], r2, s, 4, 4, 3, prec); acb_theta_g2_transvectant_lead(&res[21], r6, s, 8, 4, 4, prec); acb_poly_mul(s, s, r4, prec); /* now C_32^3 */ acb_theta_g2_transvectant_lead(&res[22], f, s, 6, 6, 6, prec); acb_theta_g2_transvectant_lead(&res[23], f, s, 6, 6, 5, prec); acb_theta_g2_transvectant_lead(&res[24], r6, s, 8, 6, 6, prec); acb_poly_mul(s, s, r4, prec); /* now C_32^4 */ acb_theta_g2_transvectant_lead(&res[25], r6, s, 8, 8, 8, prec); acb_poly_clear(s); acb_poly_clear(r2); acb_poly_clear(r3); acb_poly_clear(r4); acb_poly_clear(r5); acb_poly_clear(r6); } void acb_theta_g2_covariants_lead(acb_ptr res, const acb_poly_t f, slong prec) { double cofactors[ACB_THETA_G2_COV_NB] = {1, 60, 75, 90, 2250, 2250, 450, 540, 11250, 67500, 13500, 13500, 168750, 67500, 405000, 10125000, 2025000, 2700000, 151875000, 60750000, 15187500, 9112500000, 227812500000, 13668750000, 8201250000000, 384433593750}; fmpz_t m; slong k; fmpz_init(m); acb_theta_g2_transvectants(res, f, prec); for (k = 0; k < ACB_THETA_G2_COV_NB; k++) { fmpz_set_d(m, cofactors[k]); acb_mul_fmpz(&res[k], &res[k], m, prec); } fmpz_clear(m); } flint-3.1.3/src/acb_theta/g2_detk_symj.c000066400000000000000000000027541461254215100200710ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" void acb_theta_g2_detk_symj(acb_poly_t res, const acb_mat_t m, const acb_poly_t f, slong k, slong j, slong prec) { acb_poly_t x, y, t, u, aux; acb_t a; slong i; acb_poly_init(x); acb_poly_init(y); acb_poly_init(t); acb_poly_init(u); acb_poly_init(aux); acb_init(a); acb_poly_set_coeff_acb(x, 0, acb_mat_entry(m, 1, 0)); acb_poly_set_coeff_acb(x, 1, acb_mat_entry(m, 0, 0)); acb_poly_set_coeff_acb(y, 0, acb_mat_entry(m, 1, 1)); acb_poly_set_coeff_acb(y, 1, acb_mat_entry(m, 0, 1)); for (i = 0; i <= j; i++) { acb_poly_get_coeff_acb(a, f, i); acb_poly_pow_ui(t, x, i, prec); acb_poly_pow_ui(u, y, j - i, prec); acb_poly_mul(t, t, u, prec); acb_poly_scalar_mul(t, t, a, prec); acb_poly_add(aux, aux, t, prec); } acb_mat_det(a, m, prec); acb_pow_si(a, a, k, prec); acb_poly_scalar_mul(res, aux, a, prec); acb_poly_clear(x); acb_poly_clear(y); acb_poly_clear(aux); acb_poly_clear(t); acb_poly_clear(u); acb_clear(a); } flint-3.1.3/src/acb_theta/g2_jet_naive_1.c000066400000000000000000000174621461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" #define ACB_THETA_G2_JET_NAIVE_1_THRESHOLD 100 static void worker(acb_ptr dth, acb_srcptr v1, acb_srcptr v2, const slong * precs, slong len, const acb_t cofactor, const slong * coords, slong ord, slong g, slong prec, slong fullprec) { slong n = 1 << g; acb_ptr v3, aux, sums_1, sums_2, diffs; acb_t x; slong a0, a1, b; slong * dots; slong i, ind0, ind1; v3 = _acb_vec_init(len); aux = _acb_vec_init(2 * 3 * n); sums_1 = _acb_vec_init(4); sums_2 = _acb_vec_init(4); diffs = _acb_vec_init(8); dots = flint_malloc(n * sizeof(slong)); acb_init(x); /* Precompute a0, a1, dots and multiplications */ a0 = acb_theta_char_get_a(coords, g); a1 = a0 ^ (1 << (g - 1)); for (b = 0; b < n; b++) { dots[b] = acb_theta_char_dot_slong(b, coords, g); } if (len > ACB_THETA_G2_JET_NAIVE_1_THRESHOLD) { /* Store multiplications in v3 */ for (i = 0; i < len; i++) { acb_mul(&v3[i], &v1[i], &v2[i], precs[i]); } /* Main loop */ for (i = 0; i < len; i++) { for (b = 0; b < n; b++) { acb_mul_i_pow_si(x, &v3[i], (dots[b] + i * (b >> (g - 1))) % 4); ind0 = 3 * n * (i % 2) + 3 * b; if ((dots[b] + i * (b >> (g - 1))) % 2 == 0) { acb_add(&aux[ind0], &aux[ind0], x, prec); } else { acb_addmul_si(&aux[ind0 + 1], x, coords[0] + i, prec); acb_addmul_si(&aux[ind0 + 2], x, coords[1], prec); } } } } else { /* Compute dot products and sum them appropriately */ for (i = 0; i < len; i++) { acb_mul_si(&v3[i], &v2[i], coords[0] + i, precs[i]); } for (i = 0; i < 4; i++) { acb_dot(&sums_1[i], NULL, 0, v1 + i, 4, v2 + i, 4, (len + 3 - i) / 4, prec); acb_dot(&sums_2[i], NULL, 0, v1 + i, 4, v3 + i, 4, (len + 3 - i) / 4, prec); } acb_add(&diffs[0], &sums_1[0], &sums_1[2], prec); acb_add(&diffs[1], &sums_1[1], &sums_1[3], prec); acb_sub(&diffs[2], &sums_1[0], &sums_1[2], prec); acb_sub(&diffs[3], &sums_1[1], &sums_1[3], prec); acb_add(&diffs[4], &sums_2[0], &sums_2[2], prec); acb_add(&diffs[5], &sums_2[1], &sums_2[3], prec); acb_sub(&diffs[6], &sums_2[0], &sums_2[2], prec); acb_sub(&diffs[7], &sums_2[1], &sums_2[3], prec); /* Loop over b */ for (b = 0; b < n; b++) { ind0 = 3 * b; ind1 = 3 * (n + b); if ((b >> (g - 1)) == 0) { if (dots[b] % 2 == 0) { /* All even */ acb_mul_i_pow_si(x, &diffs[0], dots[b]); acb_add(&aux[ind0], &aux[ind0], x, prec); acb_mul_i_pow_si(x, &diffs[1], dots[b]); acb_add(&aux[ind1], &aux[ind1], x, prec); } else { /* All odd; use v3 for derivative wrt z1 */ acb_mul_i_pow_si(x, &diffs[4], dots[b]); acb_add(&aux[ind0 + 1], &aux[ind0 + 1], x, prec); acb_mul_i_pow_si(x, &diffs[0], dots[b]); acb_add(&aux[ind0 + 2], &aux[ind0 + 2], x, prec); acb_mul_i_pow_si(x, &diffs[5], dots[b]); acb_add(&aux[ind1 + 1], &aux[ind1 + 1], x, prec); acb_mul_i_pow_si(x, &diffs[1], dots[b]); acb_add(&aux[ind1 + 2], &aux[ind1 + 2], x, prec); } } else { /* Alternating, with different signs for a0 and a1 */ if (dots[b] % 2 == 0) { /* a0 even, a1 odd */ acb_mul_i_pow_si(x, &diffs[2], dots[b]); acb_add(&aux[ind0], &aux[ind0], x, prec); acb_mul_i_pow_si(x, &diffs[7], dots[b] + 1); acb_add(&aux[ind1 + 1], &aux[ind1 + 1], x, prec); acb_mul_i_pow_si(x, &diffs[3], dots[b] + 1); acb_add(&aux[ind1 + 2], &aux[ind1 + 2], x, prec); } else { /* a0 odd, a1 even */ acb_mul_i_pow_si(x, &diffs[3], dots[b] + 1); acb_add(&aux[ind1], &aux[ind1], x, prec); acb_mul_i_pow_si(x, &diffs[6], dots[b]); acb_add(&aux[ind0 + 1], &aux[ind0 + 1], x, prec); acb_mul_i_pow_si(x, &diffs[2], dots[b]); acb_add(&aux[ind0 + 2], &aux[ind0 + 2], x, prec); } } } /* Multiply d/dz2 entries by coords[1] */ for (i = 0; i < 2 * n; i++) { acb_mul_si(&aux[3 * i + 2], &aux[3 * i + 2], coords[1], prec); } } /* Multiply vector by cofactor and add to dth */ _acb_vec_scalar_mul(aux, aux, 2 * 3 * n, cofactor, prec); for (b = 0; b < n; b++) { _acb_vec_add(&dth[3 * (n * a0 + b)], &dth[3 * (n * a0 + b)], &aux[3 * b], 3, fullprec); _acb_vec_add(&dth[3 * (n * a1 + b)], &dth[3 * (n * a1 + b)], &aux[3 * (n + b)], 3, fullprec); } _acb_vec_clear(v3, len); _acb_vec_clear(aux, 2 * 3 * n); _acb_vec_clear(sums_1, 4); _acb_vec_clear(sums_2, 4); _acb_vec_clear(diffs, 8); flint_free(dots); acb_clear(x); } void acb_theta_g2_jet_naive_1(acb_ptr dth, const acb_mat_t tau, slong prec) { slong g = 2; slong n2 = 1 << (2 * g); slong ord = 1; acb_theta_eld_t E; acb_mat_t new_tau; arb_mat_t C; arf_t R2, eps; acb_ptr z; arb_ptr v, a; acb_t c; arb_t u; slong k; int b; acb_theta_eld_init(E, g, g); acb_mat_init(new_tau, g, g); arb_mat_init(C, g, g); arf_init(R2); arf_init(eps); z = _acb_vec_init(g); v = _arb_vec_init(g); a = _arb_vec_init(g); acb_init(c); arb_init(u); acb_mat_scalar_mul_2exp_si(new_tau, tau, -2); acb_siegel_cho(C, new_tau, prec); acb_theta_naive_reduce(v, z, a, c, u, z, 1, new_tau, prec); acb_theta_jet_naive_radius(R2, eps, C, v, ord, prec); b = acb_theta_eld_set(E, C, R2, v); if (b) { acb_theta_naive_worker(dth, 3 * n2, z, 1, new_tau, E, ord, prec, worker); arb_mul_arf(u, u, eps, prec); for (k = 0; k < 3 * n2; k++) { acb_add_error_arb(&dth[k], u); } _arb_vec_scalar_mul_2exp_si(a, a, 2, 1); _arb_vec_neg(a, a, 2); for (k = 0; k < n2; k++) { acb_addmul_arb(&dth[3 * k + 1], &dth[3 * k], &a[0], prec); acb_addmul_arb(&dth[3 * k + 2], &dth[3 * k], &a[1], prec); } acb_const_pi(c, prec); acb_mul_onei(c, c); for (k = 0; k < n2; k++) { acb_mul(&dth[3 * k + 1], &dth[3 * k + 1], c, prec); acb_mul(&dth[3 * k + 2], &dth[3 * k + 2], c, prec); } } else { for (k = 0; k < 3 * n2; k++) { acb_indeterminate(&dth[k]); } } acb_theta_eld_clear(E); acb_mat_clear(new_tau); arb_mat_clear(C); arf_clear(R2); arf_clear(eps); _acb_vec_clear(z, g); _arb_vec_clear(v, g); _arb_vec_clear(a, g); acb_clear(c); arb_clear(u); } flint-3.1.3/src/acb_theta/g2_psi4.c000066400000000000000000000015071461254215100167520ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_g2_psi4(acb_t res, acb_srcptr th2, slong prec) { slong g = 2; ulong ab; acb_t s, t; acb_init(s); acb_init(t); for (ab = 0; ab < (1 << (2 * g)); ab++) { if (acb_theta_char_is_even(ab, g)) { acb_pow_ui(t, &th2[ab], 4, prec); acb_add(s, s, t, prec); } } acb_mul_2exp_si(res, s, -2); acb_clear(s); acb_clear(t); } flint-3.1.3/src/acb_theta/g2_psi6.c000066400000000000000000000041501461254215100167510ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" static void g2_psi6_bits(int * b1, int * b2, int * b3, int * b4, ulong b) { *b4 = b % 2; b = b >> 1; *b3 = b % 2; b = b >> 1; *b2 = b % 2; b = b >> 1; *b1 = b % 2; } static slong g2_psi6_sgn(ulong b, ulong c, ulong d) { slong sgn; int b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4; g2_psi6_bits(&b1, &b2, &b3, &b4, b); g2_psi6_bits(&c1, &c2, &c3, &c4, c); g2_psi6_bits(&d1, &d2, &d3, &d4, d); sgn = b1 + b2 + c1 + c2 + d1 + d2 + b1 * c1 + b2 * c2 + b4 * c2 + b1 * c3 - b2 * c4 + b1 * d1 - b3 * d1 + c1 * d1 + b2 * d2 + c2 * d2 + c4 * d2 + c1 * d3 - b2 * b3 * c1 - b2 * b4 * c2 - b1 * b2 * c3 - b2 * b3 * d1 - b3 * c1 * d1 - b1 * c3 * d1 - b2 * c3 * d1 - b2 * b4 * d2 - b4 * c2 * d2 - b1 * b2 * d3 - b1 * c1 * d3 - b2 * c1 * d3; sgn = (sgn % 2 == 1 ? -1 : 1); return sgn; } void acb_theta_g2_psi6(acb_t res, acb_srcptr th2, slong prec) { slong g = 2; ulong ch1, ch2, ch3; ulong n = 1 << (2 * g); slong sgn; acb_t s, t; acb_init(s); acb_init(t); for (ch1 = 0; ch1 < n; ch1++) { for (ch2 = ch1 + 1; ch2 < n; ch2++) { for (ch3 = ch2 + 1; ch3 < n; ch3++) { if (acb_theta_char_is_syzygous(ch1, ch2, ch3, g)) { sgn = g2_psi6_sgn(ch1, ch2, ch3); acb_mul(t, &th2[ch1], &th2[ch2], prec); acb_mul(t, t, &th2[ch3], prec); acb_sqr(t, t, prec); acb_mul_si(t, t, sgn, prec); acb_add(s, s, t, prec); } } } } acb_mul_2exp_si(res, s, -2); acb_clear(s); acb_clear(t); } flint-3.1.3/src/acb_theta/g2_sextic.c000066400000000000000000000011371461254215100173710ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_g2_sextic(acb_poly_t res, const acb_mat_t tau, slong prec) { acb_t chi5; acb_init(chi5); acb_theta_g2_sextic_chi5(res, chi5, tau, prec); acb_clear(chi5); } flint-3.1.3/src/acb_theta/g2_sextic_chi5.c000066400000000000000000000036301461254215100203010ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" #define ACB_THETA_G2_JET_NAIVE_THRESHOLD 10000 void acb_theta_g2_sextic_chi5(acb_poly_t res, acb_t chi5, const acb_mat_t tau, slong prec) { slong g = 2; slong n2 = 1 << (2 * g); slong nb = acb_theta_jet_nb(1, g); fmpz_mat_t mat; acb_mat_t w, c, cinv; acb_ptr z, dth, th; acb_t det; slong k; fmpz_mat_init(mat, 2 * g, 2 * g); acb_mat_init(w, g, g); acb_mat_init(c, g, g); acb_mat_init(cinv, g, g); dth = _acb_vec_init(n2 * nb); th = _acb_vec_init(n2); z = _acb_vec_init(g); acb_init(det); acb_siegel_reduce(mat, tau, prec); acb_siegel_transform_cocycle_inv(w, c, cinv, mat, tau, prec); if (prec < ACB_THETA_G2_JET_NAIVE_THRESHOLD) { acb_theta_g2_jet_naive_1(dth, w, prec); } else { acb_theta_jet_ql_all(dth, z, w, 1, prec); } for (k = 0; k < n2; k++) { acb_set(&th[k], &dth[k * nb]); } acb_theta_g2_chi3_6(res, dth, prec); acb_theta_g2_chi5(chi5, th, prec); acb_poly_scalar_div(res, res, chi5, prec); acb_theta_g2_detk_symj(res, cinv, res, -2, 6, prec); acb_mat_det(det, cinv, prec); acb_pow_ui(det, det, 5, prec); if (acb_theta_g2_character(mat) == 1) { acb_neg(det, det); } acb_mul(chi5, chi5, det, prec); fmpz_mat_clear(mat); acb_mat_clear(w); acb_mat_clear(c); acb_mat_clear(cinv); _acb_vec_clear(dth, n2 * nb); _acb_vec_clear(th, n2); _acb_vec_clear(z, g); acb_clear(det); } flint-3.1.3/src/acb_theta/g2_transvectant.c000066400000000000000000000044361461254215100206130ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_theta.h" void acb_theta_g2_transvectant(acb_poly_t res, const acb_poly_t g, const acb_poly_t h, slong m, slong n, slong k, slong prec) { acb_poly_t aux, s, t; acb_t x; fmpz_t num, f; slong i, j; acb_poly_init(aux); acb_poly_init(s); acb_poly_init(t); acb_init(x); fmpz_init(num); fmpz_init(f); for (j = 0; j <= k; j++) { /* Set s to d^k g / dx^{k-j} dy^j; g was of degree m */ acb_poly_zero(s); for (i = 0; i <= m - k; i++) { fmpz_fac_ui(num, i + (k - j)); fmpz_fac_ui(f, (m - k - i) + j); fmpz_mul(num, num, f); fmpz_bin_uiui(f, m - k, i); fmpz_mul(num, num, f); acb_poly_get_coeff_acb(x, g, i + (k - j)); acb_mul_fmpz(x, x, num, prec); acb_poly_set_coeff_acb(s, i, x); } /* Set t to d^k h / dx^j dy^{k-j}; h was of degree n */ acb_poly_zero(t); for (i = 0; i <= n - k; i++) { fmpz_fac_ui(num, i + j); fmpz_fac_ui(f, (n - k - i) + (k - j)); fmpz_mul(num, num, f); fmpz_bin_uiui(f, n - k, i); fmpz_mul(num, num, f); acb_poly_get_coeff_acb(x, h, i + j); acb_mul_fmpz(x, x, num, prec); acb_poly_set_coeff_acb(t, i, x); } acb_poly_mul(s, s, t, prec); fmpz_bin_uiui(f, k, j); if ((k - j) % 2 == 1) { fmpz_neg(f, f); } acb_set_fmpz(x, f); acb_poly_scalar_mul(s, s, x, prec); acb_poly_add(aux, aux, s, prec); } fmpz_fac_ui(num, m); fmpz_fac_ui(f, n); fmpz_mul(num, num, f); acb_one(x); acb_div_fmpz(x, x, num, prec); acb_poly_scalar_mul(res, aux, x, prec); acb_poly_clear(aux); acb_poly_clear(s); acb_poly_clear(t); acb_clear(x); fmpz_clear(num); fmpz_clear(f); } flint-3.1.3/src/acb_theta/g2_transvectant_lead.c000066400000000000000000000030011461254215100215630ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_theta.h" void acb_theta_g2_transvectant_lead(acb_t res, const acb_poly_t g, const acb_poly_t h, slong m, slong n, slong k, slong prec) { acb_ptr s, t; fmpz_t num, f; slong j; s = _acb_vec_init(k + 1); t = _acb_vec_init(k + 1); fmpz_init(num); fmpz_init(f); /* Set i = m - k (resp. n - k) in g2_transvectant and use acb_dot */ for (j = 0; j <= k; j++) { acb_poly_get_coeff_acb(&s[j], g, m - j); acb_poly_get_coeff_acb(&t[j], h, n - k + j); /* Put all factorials in s */ fmpz_fac_ui(num, m - j); fmpz_fac_ui(f, n - k + j); fmpz_mul(num, num, f); if ((k - j) % 2 == 1) { fmpz_neg(num, num); } acb_mul_fmpz(&s[j], &s[j], num, prec); } acb_dot(res, NULL, 0, s, 1, t, 1, k + 1, prec); fmpz_fac_ui(num, k); acb_set_fmpz(t, num); fmpz_fac_ui(num, m); fmpz_fac_ui(f, n); fmpz_mul(num, num, f); acb_div_fmpz(t, t, num, prec); acb_mul(res, res, t, prec); _acb_vec_clear(s, k + 1); _acb_vec_clear(t, k + 1); fmpz_clear(num); fmpz_clear(f); } flint-3.1.3/src/acb_theta/jet_all.c000066400000000000000000000115351461254215100171170ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" /* Compute jet of exp (z^T N z) */ static void acb_theta_jet_exp_qf(acb_ptr res, acb_srcptr z, const acb_mat_t N, slong ord, slong prec) { slong g = acb_mat_nrows(N); slong nb = acb_theta_jet_nb(ord, g); acb_mat_t tp; acb_poly_t pol; acb_ptr aux; acb_ptr y; acb_t c; slong * tup; slong j, k, l, i; acb_mat_init(tp, g, g); acb_poly_init(pol); aux = _acb_vec_init(nb); y = _acb_vec_init(g); acb_init(c); tup = flint_malloc(g * sizeof(slong)); /* exp((z+h)^T N (z+h)) = exp(z^T N z) exp(z^T (N+N^T) h) exp(h^T N h) */ _acb_vec_zero(res, nb); acb_mat_vector_mul_col(y, N, z, prec); acb_dot(&res[0], NULL, 0, z, 1, y, 1, g, prec); acb_exp(&res[0], &res[0], prec); acb_mat_transpose(tp, N); acb_mat_add(tp, tp, N, prec); acb_mat_vector_mul_row(y, z, tp, prec); for (j = 0; j < g; j++) { _acb_vec_zero(aux, nb); acb_poly_zero(pol); acb_poly_set_coeff_acb(pol, 1, &y[j]); acb_poly_exp_series(pol, pol, ord + 1, prec); for (l = 0; l <= ord; l++) { for (i = 0; i < g; i++) { tup[i] = 0; } tup[j] = l; acb_poly_get_coeff_acb(&aux[acb_theta_jet_index(tup, g)], pol, l); } acb_theta_jet_mul(res, res, aux, ord, g, prec); } for (j = 0; j < g; j++) { for (k = j; k < g; k++) { _acb_vec_zero(aux, nb); acb_poly_zero(pol); acb_add(c, acb_mat_entry(N, k, j), acb_mat_entry(N, j, k), prec); if (j == k) { acb_mul_2exp_si(c, c, -1); } acb_poly_set_coeff_acb(pol, 1, c); acb_poly_exp_series(pol, pol, (ord / 2) + 1, prec); for (l = 0; l <= (ord / 2); l++) { for (i = 0; i < g; i++) { tup[i] = 0; } tup[j] += l; tup[k] += l; acb_poly_get_coeff_acb(&aux[acb_theta_jet_index(tup, g)], pol, l); } acb_theta_jet_mul(res, res, aux, ord, g, prec); } } acb_mat_clear(tp); acb_poly_clear(pol); _acb_vec_clear(aux, nb); _acb_vec_clear(y, g); acb_clear(c); flint_free(tup); } void acb_theta_jet_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong n2 = 1 << (2 * g); slong nb = acb_theta_jet_nb(ord, g); fmpz_mat_t mat, gamma; acb_mat_t w, c, cinv, N; acb_ptr aux, x, units; acb_t s, t; ulong ab, image_ab; slong kappa, e; fmpz_mat_init(mat, 2 * g, 2 * g); acb_mat_init(w, g, g); acb_mat_init(c, g, g); acb_mat_init(cinv, g, g); acb_mat_init(N, g, g); x = _acb_vec_init(g); aux = _acb_vec_init(n2 * nb); units = _acb_vec_init(8); acb_init(s); acb_init(t); acb_siegel_reduce(mat, tau, prec); acb_siegel_transform_cocycle_inv(w, c, cinv, mat, tau, prec); _acb_vec_unit_roots(units, 8, 8, prec); if (acb_siegel_is_reduced(w, -10, prec)) { sp2gz_inv(mat, mat); acb_mat_transpose(cinv, cinv); acb_mat_vector_mul_col(x, cinv, z, prec); acb_theta_jet_ql_all(aux, x, w, ord, prec); kappa = acb_theta_transform_kappa(s, mat, w, prec); for (ab = 0; ab < n2; ab++) { image_ab = acb_theta_transform_char(&e, mat, ab); acb_mul(t, s, &units[(kappa + e) % 8], prec); _acb_vec_scalar_mul(dth + ab * nb, aux + image_ab * nb, nb, t, prec); acb_theta_jet_compose(dth + ab * nb, dth + ab * nb, cinv, ord, prec); } fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); acb_mat_set_fmpz_mat(N, gamma); acb_mat_mul(N, N, cinv, prec); acb_const_pi(t, prec); acb_mul_onei(t, t); acb_mat_scalar_mul_acb(N, N, t, prec); fmpz_mat_window_clear(gamma); acb_theta_jet_exp_qf(aux, z, N, ord, prec); for (ab = 0; ab < n2; ab++) { acb_theta_jet_mul(dth + ab * nb, dth + ab * nb, aux, ord, g, prec); } } else { _acb_vec_indeterminate(dth, n2 * nb); } fmpz_mat_clear(mat); acb_mat_clear(w); acb_mat_clear(c); acb_mat_clear(cinv); acb_mat_clear(N); _acb_vec_clear(x, g); _acb_vec_clear(aux, n2 * nb); _acb_vec_clear(units, 8); acb_clear(s); acb_clear(t); } flint-3.1.3/src/acb_theta/jet_compose.c000066400000000000000000000044721461254215100200160ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb_mat.h" #include "acb_theta.h" void acb_theta_jet_compose(acb_ptr res, acb_srcptr v, const acb_mat_t N, slong ord, slong prec) { slong g = acb_mat_nrows(N); slong nb = acb_theta_jet_nb(ord, g); acb_ptr aux; acb_t x; fmpz_t m, p; slong * tups; slong * term; slong n, k, j, i, l, t; tups = flint_malloc(nb * g * sizeof(slong)); term = flint_malloc(g * sizeof(slong)); aux = _acb_vec_init(nb); acb_init(x); fmpz_init(m); fmpz_init(p); acb_theta_jet_tuples(tups, ord, g); for (k = 0; k < nb; k++) { n = acb_theta_jet_total_order(tups + k * g, g); for (j = 0; j < n_pow(g, n); j++) { for (i = 0; i < g; i++) { term[i] = 0; } for (i = 0; i < n; i++) { term[(j / n_pow(g, i)) % g]++; } /* multiply by factorials */ fmpz_one(p); for (i = 0; i < g; i++) { fmpz_fac_ui(m, term[i]); fmpz_mul(p, p, m); } acb_mul_fmpz(x, &v[acb_theta_jet_index(term, g)], p, prec); /* view tup as a collection of n indices, enumerate them */ i = 0; for (l = 0; l < g; l++) { for (t = 0; t < tups[k * g + l]; t++) { acb_mul(x, x, acb_mat_entry(N, (j / n_pow(g, i) % g), l), prec); i++; } } acb_add(&aux[k], &aux[k], x, prec); } fmpz_one(p); for (i = 0; i < g; i++) { fmpz_fac_ui(m, tups[k * g + i]); fmpz_mul(p, p, m); } acb_div_fmpz(&aux[k], &aux[k], p, prec); } _acb_vec_set(res, aux, nb); flint_free(tups); flint_free(term); _acb_vec_clear(aux, nb); acb_clear(x); fmpz_clear(m); fmpz_clear(p); } flint-3.1.3/src/acb_theta/jet_error_bounds.c000066400000000000000000000066121461254215100210520ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" void acb_theta_jet_error_bounds(arb_ptr err, acb_srcptr z, const acb_mat_t tau, acb_srcptr dth, slong ord, slong prec) { slong g = acb_mat_nrows(tau); arb_ptr abs_der; arb_mat_t tau_err; arb_ptr z_err; arb_t e, f; slong nb = acb_theta_jet_nb(ord, g); slong nb_dth = acb_theta_jet_nb(ord + 2, g); slong * tups; slong * new_tups; slong j, l, m, i; abs_der = _arb_vec_init(nb_dth); arb_mat_init(tau_err, g, g); z_err = _arb_vec_init(g); arb_init(e); arb_init(f); tups = flint_malloc(nb * g * sizeof(slong)); new_tups = flint_malloc(g * sizeof(slong)); /* Get input errors on z, tau */ for (l = 0; l < g; l++) { for (m = l; m < g; m++) { acb_get_rad_ubound_arf(arb_midref(e), acb_mat_entry(tau, l, m), prec); arb_set(arb_mat_entry(tau_err, l, m), e); } acb_get_rad_ubound_arf(arb_midref(e), &z[l], prec); arb_set(&z_err[l], e); } /* We need order ord + 2 to use the heat equation. */ for (j = 0; j < nb_dth; j++) { acb_get_abs_ubound_arf(arb_midref(&abs_der[j]), &dth[j], prec); } /* Loop over tuples to compute the correct bounds */ acb_theta_jet_tuples(tups, ord, g); for (j = 0; j < nb; j++) { arb_zero(&err[j]); /* Add error corresponding to entries of tau */ for (l = 0; l < g; l++) { for (m = l; m < g; m++) { /* Heat equation: d/dzl d/dzm = 2pi i (1 + delta) d/dtaulm */ for (i = 0; i < g; i++) { new_tups[i] = tups[j * g + i]; } new_tups[l] += 1; new_tups[m] += 1; i = acb_theta_jet_index(new_tups, g); arb_mul(e, arb_mat_entry(tau_err, l, m), &abs_der[i], prec); arb_const_pi(f, prec); if (l == m) { arb_mul_2exp_si(f, f, 2); arb_mul_si(e, e, new_tups[l] * (new_tups[l] - 1), prec); } else { arb_mul_2exp_si(f, f, 1); arb_mul_si(e, e, new_tups[l] * new_tups[m], prec); } arb_div(e, e, f, prec); arb_add(&err[j], &err[j], e, prec); } } /* Add error corresponding to entries of z */ for (l = 0; l < g; l++) { for (i = 0; i < g; i++) { new_tups[i] = tups[j * g + i]; } new_tups[l] += 1; i = acb_theta_jet_index(new_tups, g); arb_mul(e, &z_err[l], &abs_der[i], prec); arb_mul_si(e, e, new_tups[l], prec); arb_add(&err[j], &err[j], e, prec); } } _arb_vec_clear(abs_der, nb_dth); arb_mat_clear(tau_err); _arb_vec_clear(z_err, g); arb_clear(e); arb_clear(f); flint_free(tups); flint_free(new_tups); } flint-3.1.3/src/acb_theta/jet_exp_pi_i.c000066400000000000000000000027061461254215100201430ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_jet_exp_pi_i(acb_ptr res, arb_srcptr a, slong ord, slong g, slong prec) { slong nb = acb_theta_jet_nb(ord, g); slong * tups; acb_t c; arb_t t; fmpz_t den, m; slong k, l; tups = flint_malloc(nb * g * sizeof(slong)); acb_init(c); arb_init(t); fmpz_init(den); fmpz_init(m); acb_one(&res[0]); acb_theta_jet_tuples(tups, ord, g); for (k = 1; k < nb; k++) { acb_one(&res[k]); fmpz_one(den); for (l = 0; l < g; l++) { arb_pow_ui(t, &a[l], tups[k * g + l], prec); acb_mul_arb(&res[k], &res[k], t, prec); fmpz_fac_ui(m, tups[k * g + l]); fmpz_mul(den, den, m); } acb_const_pi(c, prec); acb_mul_onei(c, c); acb_pow_ui(c, c, acb_theta_jet_total_order(tups + k * g, g), prec); acb_mul(&res[k], &res[k], c, prec); acb_div_fmpz(&res[k], &res[k], den, prec); } flint_free(tups); acb_clear(c); arb_clear(t); fmpz_clear(den); fmpz_clear(m); } flint-3.1.3/src/acb_theta/jet_index.c000066400000000000000000000015651461254215100174600ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" slong acb_theta_jet_index(const slong * tup, slong g) { slong ord, res, k; slong j; /* Get total derivation order */ ord = acb_theta_jet_total_order(tup, g); if (ord == 0 || g == 1) { return ord; } /* Count tuples with smaller total order */ res = acb_theta_jet_nb(ord - 1, g); for (j = 0; j < g - 1; j++) { k = tup[j]; res += acb_theta_jet_nb(ord - k - 1, g - 1 - j); ord -= k; } return res; } flint-3.1.3/src/acb_theta/jet_mul.c000066400000000000000000000030151461254215100171360ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" static int acb_theta_jet_le(const slong * tup1, const slong * tup2, slong g) { slong k; for (k = 0; k < g; k++) { if (tup1[k] > tup2[k]) { return 0; } } return 1; } void acb_theta_jet_mul(acb_ptr res, acb_srcptr v1, acb_srcptr v2, slong ord, slong g, slong prec) { slong nb = acb_theta_jet_nb(ord, g); acb_ptr aux; slong * tups; slong * diff; slong j, k, l; aux = _acb_vec_init(nb); tups = flint_malloc(nb * g * sizeof(slong)); diff = flint_malloc(g * sizeof(slong)); acb_theta_jet_tuples(tups, ord, g); for (j = 0; j < nb; j++) { for (k = 0; k < nb; k++) { if (!acb_theta_jet_le(tups + k * g, tups + j * g, g)) { continue; } for (l = 0; l < g; l++) { diff[l] = tups[j * g + l] - tups[k * g + l]; } acb_addmul(&aux[j], &v1[k], &v2[acb_theta_jet_index(diff, g)], prec); } } _acb_vec_set(res, aux, nb); _acb_vec_clear(aux, nb); flint_free(tups); flint_free(diff); } flint-3.1.3/src/acb_theta/jet_naive_00.c000066400000000000000000000113401461254215100177420ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_modular.h" #include "acb_theta.h" static void worker(acb_ptr dth, acb_srcptr v1, acb_srcptr v2, const slong * precs, slong len, const acb_t cofactor, const slong * coords, slong ord, slong g, slong prec, slong fullprec) { slong nb = acb_theta_jet_nb(ord, g); slong * tups; acb_ptr v3, aux; acb_t x; fmpz_t num, t; slong j, i; tups = flint_malloc(g * nb * sizeof(slong)); v3 = _acb_vec_init(len); aux = _acb_vec_init(nb); acb_init(x); fmpz_init(num); fmpz_init(t); /* Compute products in v3 */ for (i = 0; i < len; i++) { acb_mul(&v3[i], &v1[i], &v2[i], precs[i]); } acb_theta_jet_tuples(tups, ord, g); for (j = 0; j < nb; j++) { fmpz_one(num); for (i = 1; i < g; i++) { fmpz_set_si(t, coords[i]); fmpz_pow_ui(t, t, tups[j * g + i]); fmpz_mul(num, num, t); } /* Loop over lattice points */ for (i = 0; i < len; i++) { fmpz_set_si(t, coords[0] + i); fmpz_pow_ui(t, t, tups[j * g]); acb_mul_fmpz(x, &v3[i], t, precs[i]); acb_add(&aux[j], &aux[j], x, prec); } /* Multiply by cofactor * num */ acb_mul_fmpz(x, cofactor, num, prec); acb_mul(&aux[j], &aux[j], x, prec); } _acb_vec_add(dth, dth, aux, nb, fullprec); flint_free(tups); _acb_vec_clear(v3, len); _acb_vec_clear(aux, nb); acb_clear(x); fmpz_clear(num); fmpz_clear(t); } static void acb_theta_jet_naive_00_gen(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong nb = acb_theta_jet_nb(ord, g); slong * tups; acb_theta_eld_t E; arb_mat_t C; arf_t R2, eps; acb_ptr new_z, aux; arb_ptr v, a; acb_t c; arb_t u; fmpz_t m, t; slong j, k; int b; tups = flint_malloc(g * nb * sizeof(slong)); acb_theta_eld_init(E, g, g); arb_mat_init(C, g, g); arf_init(R2); arf_init(eps); new_z = _acb_vec_init(g); aux = _acb_vec_init(nb); a = _arb_vec_init(g); v = _arb_vec_init(g); acb_init(c); arb_init(u); fmpz_init(m); fmpz_init(t); acb_siegel_cho(C, tau, prec); acb_theta_naive_reduce(v, new_z, a, c, u, z, 1, tau, prec); acb_theta_jet_naive_radius(R2, eps, C, v, ord, prec); b = acb_theta_eld_set(E, C, R2, v); if (b) { acb_theta_naive_worker(dth, nb, new_z, 1, tau, E, ord, prec, worker); arb_mul_arf(u, u, eps, prec); for (k = 0; k < nb; k++) { acb_mul(&dth[k], &dth[k], c, prec); acb_add_error_arb(&dth[k], u); } acb_theta_jet_tuples(tups, ord, g); for (k = 0; k < nb; k++) { acb_const_pi(c, prec); acb_mul_2exp_si(c, c, 1); acb_mul_onei(c, c); acb_pow_ui(c, c, acb_theta_jet_total_order(tups + k * g, g), prec); fmpz_one(m); for (j = 0; j < g; j++) { fmpz_fac_ui(t, tups[k * g + j]); fmpz_mul(m, m, t); } acb_div_fmpz(c, c, m, prec); acb_mul(&dth[k], &dth[k], c, prec); } _arb_vec_neg(a, a, g); _arb_vec_scalar_mul_2exp_si(a, a, g, 1); acb_theta_jet_exp_pi_i(aux, a, ord, g, prec); acb_theta_jet_mul(dth, dth, aux, ord, g, prec); } else { for (k = 0; k < nb; k++) { acb_indeterminate(&dth[k]); } } flint_free(tups); acb_theta_eld_clear(E); arb_mat_clear(C); arf_clear(R2); arf_clear(eps); _acb_vec_clear(new_z, g); _acb_vec_clear(aux, nb); _arb_vec_clear(v, g); _arb_vec_clear(a, g); acb_clear(c); arb_clear(u); fmpz_clear(m); fmpz_clear(t); } void acb_theta_jet_naive_00(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong nb = acb_theta_jet_nb(ord, g); acb_ptr res; if (g == 1) { res = _acb_vec_init(4 * nb); acb_modular_theta_jet(res, res + nb, res + 2 * nb, res + 3 * nb, z, acb_mat_entry(tau, 0, 0), nb, prec); _acb_vec_set(dth, res + 2 * nb, nb); _acb_vec_clear(res, 4 * nb); } else { acb_theta_jet_naive_00_gen(dth, z, tau, ord, prec); } } flint-3.1.3/src/acb_theta/jet_naive_all.c000066400000000000000000000150651461254215100203030ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_modular.h" #include "acb_theta.h" /* Use a big ellipsoid to avoid complicated formulas for derivatives; this introduces powers of i in worker */ static void worker(acb_ptr dth, acb_srcptr v1, acb_srcptr v2, const slong * precs, slong len, const acb_t cofactor, const slong * coords, slong ord, slong g, slong prec, slong fullprec) { slong n = 1 << g; slong nb = acb_theta_jet_nb(ord, g); slong * tups; slong a0, a1; slong * dots; acb_ptr v3, aux; acb_t x, y; fmpz_t num, t; slong j, i; ulong b; tups = flint_malloc(g * nb * sizeof(slong)); dots = flint_malloc(n * sizeof(slong)); v3 = _acb_vec_init(len); aux = _acb_vec_init(nb * n * n); acb_init(x); acb_init(y); fmpz_init(num); fmpz_init(t); /* Precompute a0, a1, dots */ a0 = acb_theta_char_get_a(coords, g); a1 = a0 ^ (1 << (g - 1)); for (b = 0; b < n; b++) { dots[b] = acb_theta_char_dot_slong(b, coords, g); } /* Compute products in v3 */ for (i = 0; i < len; i++) { acb_mul(&v3[i], &v1[i], &v2[i], precs[i]); } acb_theta_jet_tuples(tups, ord, g); for (j = 0; j < nb; j++) { fmpz_one(num); for (i = 1; i < g; i++) { fmpz_set_si(t, coords[i]); fmpz_pow_ui(t, t, tups[j * g + i]); fmpz_mul(num, num, t); } /* Loop over lattice points */ for (i = 0; i < len; i++) { fmpz_set_si(t, coords[0] + i); fmpz_pow_ui(t, t, tups[j * g]); acb_mul_fmpz(x, &v3[i], t, precs[i]); /* Loop over b, adding coefficients in both a0b and a1b */ for (b = 0; b < n; b++) { acb_mul_i_pow_si(y, x, (dots[b] + i * (b >> (g - 1))) % 4); if (i % 2 == 0) { acb_add(&aux[(n * a0 + b) * nb + j], &aux[(n * a0 + b) * nb + j], y, prec); } else { acb_add(&aux[(n * a1 + b) * nb + j], &aux[(n * a1 + b) * nb + j], y, prec); } } } /* Multiply by cofactor * num */ acb_mul_fmpz(x, cofactor, num, prec); for (b = 0; b < n; b++) { acb_mul(&aux[(n * a0 + b) * nb + j], &aux[(n * a0 + b) * nb + j], x, prec); acb_mul(&aux[(n * a1 + b) * nb + j], &aux[(n * a1 + b) * nb + j], x, prec); } } _acb_vec_add(dth, dth, aux, nb * n * n, fullprec); flint_free(tups); flint_free(dots); _acb_vec_clear(v3, len); _acb_vec_clear(aux, nb * n * n); acb_clear(x); acb_clear(y); fmpz_clear(num); fmpz_clear(t); } static void acb_theta_jet_naive_all_gen(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong n2 = 1 << (2 * g); slong nb = acb_theta_jet_nb(ord, g); slong * tups; acb_theta_eld_t E; arb_mat_t C; arf_t R2, eps; acb_ptr aux, new_z; acb_mat_t new_tau; arb_ptr v, a; acb_t c; arb_t u; fmpz_t m, t; slong k, j; int b; tups = flint_malloc(g * nb * sizeof(slong)); acb_theta_eld_init(E, g, g); arb_mat_init(C, g, g); arf_init(R2); arf_init(eps); aux = _acb_vec_init(n2 * nb); new_z = _acb_vec_init(g); acb_mat_init(new_tau, g, g); v = _arb_vec_init(g); a = _arb_vec_init(g); acb_init(c); arb_init(u); fmpz_init(m); fmpz_init(t); _acb_vec_scalar_mul_2exp_si(new_z, z, g, -1); acb_mat_scalar_mul_2exp_si(new_tau, tau, -2); acb_siegel_cho(C, new_tau, prec); acb_theta_naive_reduce(v, new_z, a, c, u, new_z, 1, new_tau, prec); acb_theta_jet_naive_radius(R2, eps, C, v, ord, prec); b = acb_theta_eld_set(E, C, R2, v); if (b) { acb_theta_naive_worker(dth, nb * n2, new_z, 1, new_tau, E, ord, prec, worker); arb_mul_arf(u, u, eps, prec); for (k = 0; k < nb * n2; k++) { acb_mul(&dth[k], &dth[k], c, prec); acb_add_error_arb(&dth[k], u); } acb_theta_jet_tuples(tups, ord, g); for (k = 0; k < nb; k++) { acb_const_pi(c, prec); /* not 2 pi because of rescaling */ acb_mul_onei(c, c); acb_pow_ui(c, c, acb_theta_jet_total_order(tups + k * g, g), prec); fmpz_one(m); for (j = 0; j < g; j++) { fmpz_fac_ui(t, tups[k * g + j]); fmpz_mul(m, m, t); } acb_div_fmpz(c, c, m, prec); for (j = 0; j < n2; j++) { acb_mul(&dth[j * nb + k], &dth[j * nb + k], c, prec); } } _arb_vec_neg(a, a, g); acb_theta_jet_exp_pi_i(aux, a, ord, g, prec); for (k = 0; k < n2; k++) { acb_theta_jet_mul(dth + k * nb, dth + k * nb, aux, ord, g, prec); arb_zero(u); for (j = 0; j < g; j++) { if ((k >> (g - 1 - j)) % 2 == 1) { arb_add(u, u, &a[j], prec); } } acb_onei(c); acb_pow_arb(c, c, u, prec); _acb_vec_scalar_mul(dth + k * nb, dth + k * nb, nb, c, prec); } } else { for (k = 0; k < nb * n2; k++) { acb_indeterminate(&dth[k]); } } flint_free(tups); acb_theta_eld_clear(E); arb_mat_clear(C); arf_clear(R2); arf_clear(eps); _acb_vec_clear(aux, n2 * nb); _acb_vec_clear(new_z, g); acb_mat_clear(new_tau); _arb_vec_clear(v, g); _arb_vec_clear(a, g); acb_clear(c); arb_clear(u); fmpz_clear(m); fmpz_clear(t); } void acb_theta_jet_naive_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong nb = acb_theta_jet_nb(ord, g); if (g == 1) { acb_modular_theta_jet(dth + 3 * nb, dth + 2 * nb, dth, dth + nb, z, acb_mat_entry(tau, 0, 0), nb, prec); _acb_vec_neg(dth + 3 * nb, dth + 3 * nb, nb); } else { acb_theta_jet_naive_all_gen(dth, z, tau, ord, prec); } } flint-3.1.3/src/acb_theta/jet_naive_fixed_ab.c000066400000000000000000000036061461254215100212720ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_theta_jet_naive_fixed_ab(acb_ptr dth, ulong ab, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong nb = acb_theta_jet_nb(ord, g); ulong a = ab >> g; ulong b = ab; acb_ptr v, w, new_z, aux; arb_ptr u; acb_t c, x; v = _acb_vec_init(g); w = _acb_vec_init(g); new_z = _acb_vec_init(g); aux = _acb_vec_init(nb); u = _arb_vec_init(g); acb_init(c); acb_init(x); acb_theta_char_get_acb(v, a, g); acb_theta_char_get_acb(w, b, g); acb_theta_char_get_arb(u, a, g); _arb_vec_scalar_mul_2exp_si(u, u, g, 1); /* Get jet at new_z */ acb_mat_vector_mul_col(new_z, tau, v, prec); _acb_vec_add(new_z, new_z, w, g, prec); _acb_vec_add(new_z, new_z, z, g, prec); acb_theta_jet_naive_00(dth, new_z, tau, ord, prec); /* Get exponential factor */ acb_mat_vector_mul_col(v, tau, v, prec); acb_theta_char_dot_acb(c, a, v, g, prec); _acb_vec_add(w, w, z, g, prec); acb_theta_char_dot_acb(x, a, w, g, prec); acb_mul_2exp_si(x, x, 1); acb_add(x, x, c, prec); acb_exp_pi_i(x, x, prec); /* Get other coefficients */ acb_theta_jet_exp_pi_i(aux, u, ord, g, prec); _acb_vec_scalar_mul(aux, aux, nb, x, prec); acb_theta_jet_mul(dth, dth, aux, ord, g, prec); _acb_vec_clear(new_z, g); _acb_vec_clear(v, g); _acb_vec_clear(w, g); _acb_vec_clear(aux, nb); _arb_vec_clear(u, g); acb_clear(c); acb_clear(x); } flint-3.1.3/src/acb_theta/jet_naive_radius.c000066400000000000000000000041311461254215100210120ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_theta.h" void acb_theta_jet_naive_radius(arf_t R2, arf_t eps, const arb_mat_t C, arb_srcptr v, slong ord, slong prec) { slong g = arb_mat_nrows(C); slong lp = ACB_THETA_LOW_PREC; arb_mat_t mat; arb_ptr vec; arb_t na, nx, t, u; arf_t cmp; mag_t norm; arb_mat_init(mat, g, g); vec = _arb_vec_init(g); arb_init(na); arb_init(nx); arb_init(t); arb_init(u); arf_init(cmp); mag_init(norm); /* Get norms of C^{-1} and v */ arb_mat_one(mat); arb_mat_solve_triu(mat, C, mat, 0, lp); arb_mat_bound_inf_norm(norm, mat); arf_set_mag(arb_midref(na), norm); arb_mat_vector_mul_col(vec, mat, v, prec); _arb_vec_get_mag(norm, vec, g); arf_set_mag(arb_midref(nx), norm); /* Get R2, eps assuming R <= nx/na */ acb_theta_naive_radius(R2, eps, C, 0, prec); arb_mul_2exp_si(t, nx, 1); arb_one(u); arb_max(t, t, u, lp); arb_pow_ui(t, t, ord, lp); arb_mul_arf(t, t, eps, lp); arb_get_ubound_arf(eps, t, lp); /* If R too large, assume R >= nx/na instead */ arb_div(t, nx, na, lp); arb_sqr(t, t, lp); arb_get_lbound_arf(cmp, t, lp); if (arf_cmp(cmp, R2) <= 0) { acb_theta_naive_radius(R2, eps, C, ord, prec); arb_div(t, nx, na, lp); arb_get_ubound_arf(cmp, t, lp); arf_max(R2, R2, cmp); arb_mul_2exp_si(t, na, 1); arb_one(u); arb_max(t, t, u, lp); arb_pow_ui(t, t, ord, lp); arb_mul_arf(t, t, eps, lp); arb_get_ubound_arf(eps, t, lp); } arb_mat_clear(mat); _arb_vec_clear(vec, g); arb_clear(na); arb_clear(nx); arb_clear(t); arb_clear(u); arf_clear(cmp); mag_clear(norm); } flint-3.1.3/src/acb_theta/jet_nb.c000066400000000000000000000012561461254215100167450ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" slong acb_theta_jet_nb(slong ord, slong g) { fmpz_t x; slong res; FLINT_ASSERT(g >= 0); if (ord < 0) { return 0; } fmpz_init(x); fmpz_bin_uiui(x, g + ord, g); res = fmpz_get_si(x); fmpz_clear(x); return res; } flint-3.1.3/src/acb_theta/jet_ql_all.c000066400000000000000000000120641461254215100176110ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb_mat.h" #include "acb_theta.h" static void acb_theta_jet_ql_all_red(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong n2 = 1 << (2 * g); slong b = ord + 1; slong hprec; slong lp = ACB_THETA_LOW_PREC; slong nb = acb_theta_jet_nb(ord, g); slong nb_low = acb_theta_jet_nb(ord + 2, g); int hasz = !_acb_vec_is_zero(z, g); arb_t c, rho, t; arf_t eps, err, e; acb_mat_t tau_mid; acb_ptr z_mid, zetas, new_z, all_val, val, jet, dth_low; arb_ptr err_vec; slong k, kmod, j; arb_init(c); arb_init(rho); arb_init(t); arf_init(eps); arf_init(err); /* Get bounds and high precision, fail if too large */ acb_theta_jet_ql_bounds(c, rho, z, tau, ord); acb_theta_jet_ql_radius(eps, err, c, rho, ord, g, prec); arb_set_arf(t, eps); arb_log_base_ui(t, t, 2, lp); arb_neg(t, t); /* we expect that the second bound holds if finite, but still check */ if (!arb_is_finite(t) || (arf_cmpabs_2exp_si(arb_midref(t), 20) > 0)) { _acb_vec_indeterminate(dth, n2 * nb); arb_clear(c); arb_clear(rho); arb_clear(t); arf_clear(eps); arf_clear(err); return; } arf_init(e); acb_mat_init(tau_mid, g, g); z_mid = _acb_vec_init(g); zetas = _acb_vec_init(b); new_z = _acb_vec_init(g); all_val = _acb_vec_init(n2 * n_pow(b, g)); val = _acb_vec_init(n_pow(b, g)); jet = _acb_vec_init(nb); dth_low = _acb_vec_init(n2 * nb_low); err_vec = _arb_vec_init(nb); hprec = prec + ord * (arf_get_si(arb_midref(t), ARF_RND_CEIL) + g); arf_one(e); arf_mul_2exp_si(e, e, -hprec); /* Get midpoint at precision hprec */ for (j = 0; j < g; j++) { for (k = 0; k < g; k++) { acb_get_mid(acb_mat_entry(tau_mid, j, k), acb_mat_entry(tau, j, k)); acb_add_error_arf(acb_mat_entry(tau_mid, j, k), e); acb_set(acb_mat_entry(tau_mid, k, j), acb_mat_entry(tau_mid, j, k)); } acb_get_mid(&z_mid[j], &z[j]); if (hasz) { acb_add_error_arf(&z_mid[j], e); } } /* Collect values around midpoint */ _acb_vec_unit_roots(zetas, b, b, hprec); for (k = 0; k < n_pow(b, g); k++) { kmod = k; for (j = g - 1; j >= 0; j--) { acb_set(&new_z[j], &zetas[kmod % b]); kmod = kmod / b; } arb_set_arf(t, eps); _acb_vec_scalar_mul_arb(new_z, new_z, g, t, hprec); _acb_vec_add(new_z, new_z, z_mid, g, hprec); acb_theta_ql_all(all_val + k * n2, new_z, tau_mid, 0, hprec); } /* Make finite differences */ for (k = 0; k < n2; k++) { for (j = 0; j < n_pow(b, g); j++) { acb_set(&val[j], &all_val[j * n2 + k]); } acb_theta_jet_ql_finite_diff(jet, eps, err, rho, val, ord, g, hprec); _acb_vec_set(dth + k * nb, jet, nb); } /* Add error */ acb_theta_jet_naive_all(dth_low, z, tau, ord + 2, lp); for (k = 0; k < n2; k++) { acb_theta_jet_error_bounds(err_vec, z, tau, dth_low + k * nb_low, ord, lp); for (j = 0; j < nb; j++) { acb_add_error_arb(&dth[k * nb + j], &err_vec[j]); } } arb_clear(c); arb_clear(rho); arb_clear(t); arf_clear(eps); arf_clear(err); arf_clear(e); acb_mat_clear(tau_mid); _acb_vec_clear(z_mid, g); _acb_vec_clear(zetas, b); _acb_vec_clear(new_z, g); _acb_vec_clear(all_val, n2 * n_pow(b, g)); _acb_vec_clear(val, n_pow(b, g)); _acb_vec_clear(jet, nb); _acb_vec_clear(dth_low, n2 * nb_low); _arb_vec_clear(err_vec, nb); } void acb_theta_jet_ql_all(acb_ptr dth, acb_srcptr z, const acb_mat_t tau, slong ord, slong prec) { slong g = acb_mat_nrows(tau); slong n2 = 1 << (2 * g); slong nb = acb_theta_jet_nb(ord, g); acb_ptr aux, new_z; arb_ptr v, a; acb_t c; arb_t u; slong k; aux = _acb_vec_init(nb); new_z = _acb_vec_init(g); v = _arb_vec_init(g); a = _arb_vec_init(g); acb_init(c); arb_init(u); acb_theta_naive_reduce(v, new_z, a, c, u, z, 1, tau, prec); acb_theta_jet_ql_all_red(dth, new_z, tau, ord, prec); _acb_vec_scalar_mul(dth, dth, n2 * nb, c, prec); _arb_vec_neg(a, a, g); _arb_vec_scalar_mul_2exp_si(a, a, g, 1); acb_theta_jet_exp_pi_i(aux, a, ord, g, prec); for (k = 0; k < n2; k++) { acb_theta_jet_mul(dth + k * nb, dth + k * nb, aux, ord, g, prec); } _acb_vec_clear(aux, nb); _acb_vec_clear(new_z, g); _arb_vec_clear(v, g); _arb_vec_clear(a, g); acb_clear(c); arb_clear(u); } flint-3.1.3/src/acb_theta/jet_ql_bounds.c000066400000000000000000000065461461254215100203430ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" /* Compute c0, c1, c2 such that |theta_{a,b}(z,tau)| on a ball of radius rho around z is bounded above by c0 exp((c1 + c2 rho)^2) */ static void acb_theta_jet_ql_ci(arb_t c0, arb_t c1, arb_t c2, acb_srcptr z, const acb_mat_t tau) { slong lp = ACB_THETA_LOW_PREC; slong g = acb_mat_nrows(tau); arb_mat_t Yinv; arb_mat_t cho; arb_ptr y, w; arb_t t, s; slong k, j; arb_mat_init(Yinv, g, g); arb_mat_init(cho, g, g); y = _arb_vec_init(g); w = _arb_vec_init(g); arb_init(t); arb_init(s); _acb_vec_get_imag(y, z, g); acb_siegel_yinv(Yinv, tau, lp); acb_siegel_cho(cho, tau, lp); /* c0 is 2^g \prod_{i=1}^g (1 + 2/\sqrt{\gamma_i}) */ arb_one(c0); arb_mul_2exp_si(c0, c0, g); for (k = 0; k < g; k++) { arb_mul_2exp_si(t, arb_mat_entry(cho, k, k), 1); arb_add_si(t, t, 1, lp); arb_mul(c0, c0, t, lp); } /* c1 is sqrt(\pi y Y^{-1} y) */ arb_const_pi(t, lp); arb_mat_scalar_mul_arb(Yinv, Yinv, t, lp); arb_mat_vector_mul_col(w, Yinv, y, lp); arb_dot(c1, NULL, 0, y, 1, w, 1, g, lp); arb_nonnegative_part(c1, c1); arb_sqrt(c1, c1, lp); /* c2 is sqrt(max of \pi x Y^{-1} x where |x| \leq 1) */ arb_zero(c2); arb_mat_cho(cho, Yinv, lp); arb_mat_transpose(cho, cho); for (k = 0; k < g; k++) { arb_zero(s); for (j = k; j < g; j++) { arb_abs(t, arb_mat_entry(cho, k, j)); arb_add(s, s, t, lp); } arb_sqr(s, s, lp); arb_add(c2, c2, s, lp); } arb_nonnegative_part(c2, c2); arb_sqrt(c2, c2, lp); arb_mat_clear(Yinv); arb_mat_clear(cho); _arb_vec_clear(y, g); _arb_vec_clear(w, g); arb_clear(t); arb_clear(s); } /* Pick rho and c such that |theta_{a,b}(z,tau)| on a ball of radius rho around z is bounded above by c, and is a good choice to bound derivatives up to order ord */ void acb_theta_jet_ql_bounds(arb_t c, arb_t rho, acb_srcptr z, const acb_mat_t tau, slong ord) { slong lp = ACB_THETA_LOW_PREC; slong b = ord + 1; arb_t t, c0, c1, c2; arf_t x; arb_init(t); arb_init(c0); arb_init(c1); arb_init(c2); arf_init(x); /* Get ci */ acb_theta_jet_ql_ci(c0, c1, c2, z, tau); /* Set rho to positive root of 2 c_2 rho (c_1 + c_2 rho) = 2 b - 1 */ arb_mul(t, c1, c2, lp); arb_mul_2exp_si(t, t, 1); arb_sqr(rho, t, lp); arb_sqr(t, c2, lp); arb_mul_si(t, t, 8 * (2 * b - 1), lp); arb_add(rho, rho, t, lp); arb_sqrt(rho, rho, lp); arb_mul(t, c1, c2, lp); arb_submul_si(rho, t, 2, lp); arb_sqr(t, c2, lp); arb_mul_2exp_si(t, t, 2); arb_div(rho, rho, t, lp); /* Set c to corresponding bound */ arb_mul(c, c2, rho, lp); arb_add(c, c, c1, lp); arb_sqr(c, c, lp); arb_exp(c, c, lp); arb_mul(c, c, c0, lp); arb_clear(t); arb_clear(c0); arb_clear(c1); arb_clear(c2); arf_clear(x); } flint-3.1.3/src/acb_theta/jet_ql_finite_diff.c000066400000000000000000000041001461254215100212770ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dft.h" #include "acb_theta.h" /* Given values of f at (x_1 + eps zeta^{n_1}, ..., x_g + eps zeta^{n_g}), make Fourier transforms to get Taylor coefficients and add error bound */ void acb_theta_jet_ql_finite_diff(acb_ptr dth, const arf_t eps, const arf_t err, const arb_t rho, acb_srcptr val, slong ord, slong g, slong prec) { slong nb = acb_theta_jet_nb(ord, g); slong lp = ACB_THETA_LOW_PREC; acb_ptr aux; arb_t t, e; slong b = ord + 1; slong * tups; slong * cyc; slong j, i, l; slong k; aux = _acb_vec_init(n_pow(b, g)); arb_init(t); arb_init(e); tups = flint_malloc(g * nb * sizeof(slong)); cyc = flint_malloc(g * sizeof(slong)); for (j = 0; j < g; j++) { cyc[j] = b; } acb_dft_prod(aux, val, cyc, g, prec); arb_set_si(t, n_pow(b, g)); _acb_vec_scalar_div_arb(aux, aux, n_pow(b, g), t, prec); /* Get Taylor coefficients, divide by eps^k, add error */ acb_theta_jet_tuples(tups, ord, g); k = 0; arb_one(t); arb_pow_ui(e, rho, ord, lp); arb_mul_arf(e, e, err, lp); for (j = 0; j < nb; j++) { l = 0; for (i = 0; i < g; i++) { l *= b; l += tups[j * g + i]; } acb_set(&dth[j], &aux[l]); if (acb_theta_jet_total_order(tups + j * g, g) > k) { k++; arb_mul_arf(t, t, eps, prec); arb_pow_ui(e, rho, ord - k, lp); arb_mul_arf(e, e, err, lp); } acb_div_arb(&dth[j], &dth[j], t, prec); acb_add_error_arb(&dth[j], e); } _acb_vec_clear(aux, n_pow(b, g)); arb_clear(t); arb_clear(e); flint_free(tups); flint_free(cyc); } flint-3.1.3/src/acb_theta/jet_ql_radius.c000066400000000000000000000022101461254215100203200ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb_theta.h" void acb_theta_jet_ql_radius(arf_t eps, arf_t err, const arb_t c, const arb_t rho, slong ord, slong g, slong prec) { slong lp = ACB_THETA_LOW_PREC; slong b = ord + 1; arb_t x, y; arb_init(x); arb_init(y); /* Set x to min of (1/2g)^(1/b)*rho, (2^(-prec)/2cg)^(1/b)*rho^(2b-1)/b */ arb_set_si(x, 2 * g); arb_inv(x, x, lp); arb_root_ui(x, x, b, lp); arb_mul(x, x, rho, lp); arb_pow_ui(y, rho, 2 * b - 1, prec); arb_mul_2exp_si(y, y, -prec); arb_div(y, y, c, lp); arb_div_si(y, y, 2 * g, lp); arb_root_ui(y, y, b, lp); arb_min(x, x, y, lp); arb_get_lbound_arf(eps, x, lp); arf_one(err); arf_mul_2exp_si(err, err, -prec); arb_clear(x); arb_clear(y); } flint-3.1.3/src/acb_theta/jet_total_order.c000066400000000000000000000011031461254215100206530ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" slong acb_theta_jet_total_order(const slong * tup, slong g) { slong k; slong res = 0; for (k = 0; k < g; k++) { res += tup[k]; } return res; } flint-3.1.3/src/acb_theta/jet_tuples.c000066400000000000000000000024231461254215100176570ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void acb_theta_jet_tuples(slong * tups, slong ord, slong g) { slong k, j, l, nb_rec, ind; slong * rec; if (g == 1) { for (k = 0; k <= ord; k++) { tups[k] = k; } return; } /* Generate tuples in dimension g - 1 */ nb_rec = acb_theta_jet_nb(ord, g - 1); rec = flint_malloc((g - 1) * nb_rec * sizeof(slong)); acb_theta_jet_tuples(rec, ord, g - 1); for (k = 0; k <= ord; k++) { /* Construct tuples of total order k from rec */ ind = acb_theta_jet_nb(k - 1, g); for (j = 0; j < acb_theta_jet_nb(k, g - 1); j++) { tups[(ind + j) * g] = k - acb_theta_jet_total_order(rec + j * (g - 1), g - 1); for (l = 0; l < g - 1; l++) { tups[(ind + j) * g + l + 1] = rec[j * (g - 1) + l]; } } } flint_free(rec); } flint-3.1.3/src/acb_theta/naive_00.c000066400000000000000000000060631461254215100171060ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_modular.h" #include "acb_theta.h" static void worker(acb_ptr th, acb_srcptr v1, acb_srcptr v2, const slong * precs, slong len, const acb_t cofactor, const slong * coords, slong ord, slong g, slong prec, slong fullprec) { acb_t sum; acb_init(sum); acb_dot(sum, NULL, 0, v1, 1, v2, 1, len, prec); acb_addmul(th, sum, cofactor, fullprec); acb_clear(sum); } static void acb_theta_naive_00_gen(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); acb_theta_eld_t E; arb_mat_t C; arf_t R2, eps; acb_ptr cs; arb_ptr v, as, us; acb_ptr new_zs; slong k; int b; acb_theta_eld_init(E, g, g); arb_mat_init(C, g, g); arf_init(R2); arf_init(eps); cs = _acb_vec_init(nb); us = _arb_vec_init(nb); as = _arb_vec_init(g * nb); v = _arb_vec_init(g); new_zs = _acb_vec_init(g * nb); acb_siegel_cho(C, tau, prec); acb_theta_naive_radius(R2, eps, C, 0, prec); acb_theta_naive_reduce(v, new_zs, as, cs, us, zs, nb, tau, prec); b = acb_theta_eld_set(E, C, R2, v); if (b) { acb_theta_naive_worker(th, 1, new_zs, nb, tau, E, 0, prec, worker); for (k = 0; k < nb; k++) { acb_mul(&th[k], &th[k], &cs[k], prec); arb_mul_arf(&us[k], &us[k], eps, prec); acb_add_error_arb(&th[k], &us[k]); } } else { for (k = 0; k < nb; k++) { acb_indeterminate(&th[k]); } } acb_theta_eld_clear(E); arb_mat_clear(C); arf_clear(R2); arf_clear(eps); _acb_vec_clear(cs, nb); _arb_vec_clear(us, nb); _arb_vec_clear(as, g * nb); _arb_vec_clear(v, g); _acb_vec_clear(new_zs, g * nb); } static void acb_theta_naive_00_g1(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { acb_t q, w; acb_ptr res; int w_is_unit; slong k; acb_init(q); acb_init(w); res = _acb_vec_init(4); acb_exp_pi_i(q, acb_mat_entry(tau, 0, 0), prec); for (k = 0; k < nb; k++) { acb_exp_pi_i(w, &zs[k], prec); w_is_unit = arb_is_zero(acb_imagref(&zs[k])); acb_modular_theta_sum(&res[0], &res[1], &res[2], &res[3], w, w_is_unit, q, 1, prec); acb_set(&th[k], &res[2]); } acb_clear(q); acb_clear(w); _acb_vec_clear(res, 4); } void acb_theta_naive_00(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); if (g == 1) { acb_theta_naive_00_g1(th, zs, nb, tau, prec); } else { acb_theta_naive_00_gen(th, zs, nb, tau, prec); } } flint-3.1.3/src/acb_theta/naive_0b.c000066400000000000000000000101451461254215100171640ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_modular.h" #include "acb_theta.h" static void worker(acb_ptr th, acb_srcptr v1, acb_srcptr v2, const slong * precs, slong len, const acb_t cofactor, const slong * coords, slong ord, slong g, slong prec, slong fullprec) { slong n = 1 << g; acb_t s0, s1, add, sub; ulong b; slong dot; acb_init(s0); acb_init(s1); acb_init(add); acb_init(sub); /* Compute alternate sums to adjust signs */ acb_dot(s0, NULL, 0, v1, 2, v2, 2, (len + 1) / 2, prec); acb_dot(s1, NULL, 0, v1 + 1, 2, v2 + 1, 2, len / 2, prec); acb_add(add, s0, s1, prec); acb_sub(sub, s0, s1, prec); acb_mul(add, add, cofactor, prec); acb_mul(sub, sub, cofactor, prec); for (b = 0; b < n; b++) { dot = acb_theta_char_dot_slong(b, coords, g) % 2; if ((b >> (g - 1)) && dot) { acb_sub(&th[b], &th[b], sub, fullprec); } else if ((b >> (g - 1))) { acb_add(&th[b], &th[b], sub, fullprec); } else if (dot) { acb_sub(&th[b], &th[b], add, fullprec); } else { acb_add(&th[b], &th[b], add, fullprec); } } acb_clear(s0); acb_clear(s1); acb_clear(add); acb_clear(sub); } static void acb_theta_naive_0b_gen(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); acb_theta_eld_t E; arb_mat_t C; arf_t R2, eps; acb_ptr cs; arb_ptr v, as, us; acb_ptr new_zs; slong len = 1 << g; slong k, l; int b; acb_theta_eld_init(E, g, g); arb_mat_init(C, g, g); arf_init(R2); arf_init(eps); cs = _acb_vec_init(nb); as = _arb_vec_init(g * nb); us = _arb_vec_init(nb); v = _arb_vec_init(g); new_zs = _acb_vec_init(nb * g); acb_siegel_cho(C, tau, prec); acb_theta_naive_radius(R2, eps, C, 0, prec); acb_theta_naive_reduce(v, new_zs, as, cs, us, zs, nb, tau, prec); b = acb_theta_eld_set(E, C, R2, v); if (b) { acb_theta_naive_worker(th, len, new_zs, nb, tau, E, 0, prec, worker); for (k = 0; k < nb; k++) { _acb_vec_scalar_mul(th + k * len, th + k * len, len, &cs[k], prec); arb_mul_arf(&us[k], &us[k], eps, prec); for (l = 0; l < len; l++) { acb_add_error_arb(&th[k * len + l], &us[k]); } } } else { for (k = 0; k < nb * len; k++) { acb_indeterminate(&th[k]); } } acb_theta_eld_clear(E); arb_mat_clear(C); arf_clear(R2); arf_clear(eps); _acb_vec_clear(cs, nb); _arb_vec_clear(as, g * nb); _arb_vec_clear(us, nb); _arb_vec_clear(v, g); _acb_vec_clear(new_zs, nb * g); } static void acb_theta_naive_0b_g1(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { acb_t q, w; acb_ptr res; int w_is_unit; slong k; acb_init(q); acb_init(w); res = _acb_vec_init(4); acb_exp_pi_i(q, acb_mat_entry(tau, 0, 0), prec); for (k = 0; k < nb; k++) { acb_exp_pi_i(w, &zs[k], prec); w_is_unit = arb_is_zero(acb_imagref(&zs[k])); acb_modular_theta_sum(&res[0], &res[1], &res[2], &res[3], w, w_is_unit, q, 1, prec); acb_set(&th[2 * k], &res[2]); acb_set(&th[2 * k + 1], &res[3]); } acb_clear(q); acb_clear(w); _acb_vec_clear(res, 4); } void acb_theta_naive_0b(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); if (g == 1) { acb_theta_naive_0b_g1(th, zs, nb, tau, prec); } else { acb_theta_naive_0b_gen(th, zs, nb, tau, prec); } } flint-3.1.3/src/acb_theta/naive_all.c000066400000000000000000000062751461254215100174440ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_modular.h" #include "acb_theta.h" static void acb_theta_naive_all_gen(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; acb_ptr all_zs, ata, v; acb_t c; slong a, b, d, k; all_zs = _acb_vec_init(g * n * nb); ata = _acb_vec_init(n); v = _acb_vec_init(g); acb_init(c); for (a = 0; a < n; a++) { acb_theta_char_get_acb(v, a, g); acb_mat_vector_mul_col(v, tau, v, prec); for (k = 0; k < nb; k++) { _acb_vec_add(all_zs + k * g * n + a * g, zs + k * g, v, g, prec); } acb_theta_char_dot_acb(&ata[a], a, v, g, prec); } acb_theta_naive_0b(th, all_zs, n * nb, tau, prec); for (a = 0; a < n; a++) { /* Factors depending on z, not on b */ for (k = 0; k < nb; k++) { acb_theta_char_dot_acb(c, a, zs + k * g, g, prec); acb_mul_2exp_si(c, c, 1); acb_add(c, c, &ata[a], prec); acb_exp_pi_i(c, c, prec); _acb_vec_scalar_mul(th + k * n * n + a * n, th + k * n * n + a * n, n, c, prec); } /* Factors depending on b, not on z */ for (b = 0; b < n; b++) { d = acb_theta_char_dot(a, b, g); for (k = 0; k < nb; k++) { acb_mul_i_pow_si(&th[k * n * n + a * n + b], &th[k * n * n + a * n + b], d); } } } _acb_vec_clear(all_zs, g * n * nb); _acb_vec_clear(ata, n); _acb_vec_clear(v, g); acb_clear(c); } static void acb_theta_naive_all_g1(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { acb_t q4, q, w; acb_ptr res; int w_is_unit; slong k; acb_init(q4); acb_init(q); acb_init(w); res = _acb_vec_init(4); acb_mul_2exp_si(q4, acb_mat_entry(tau, 0, 0), -2); acb_exp_pi_i(q4, q4, prec); acb_pow_ui(q, q4, 4, prec); for (k = 0; k < nb; k++) { acb_exp_pi_i(w, &zs[k], prec); w_is_unit = arb_is_zero(acb_imagref(&zs[k])); acb_modular_theta_sum(&res[0], &res[1], &res[2], &res[3], w, w_is_unit, q, 1, prec); acb_set(&th[4 * k], &res[2]); acb_set(&th[4 * k + 1], &res[3]); acb_mul(&th[4 * k + 2], &res[1], q4, prec); acb_mul(&th[4 * k + 3], &res[0], q4, prec); acb_neg(&th[4 * k + 3], &th[4 * k + 3]); } acb_clear(q4); acb_clear(q); acb_clear(w); _acb_vec_clear(res, 4); } void acb_theta_naive_all(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); if (g == 1) { acb_theta_naive_all_g1(th, zs, nb, tau, prec); } else { acb_theta_naive_all_gen(th, zs, nb, tau, prec); } } flint-3.1.3/src/acb_theta/naive_fixed_a.c000066400000000000000000000031371461254215100202650ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_theta_naive_fixed_a(acb_ptr th, ulong a, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; acb_ptr new_zs; acb_ptr v, w; acb_t c, x; slong k, b; new_zs = _acb_vec_init(nb * g); v = _acb_vec_init(g); w = _acb_vec_init(g); acb_init(c); acb_init(x); acb_theta_char_get_acb(v, a, g); acb_mat_vector_mul_col(v, tau, v, prec); /* tau.a/2 */ for (k = 0; k < nb; k++) { _acb_vec_add(new_zs + k * g, zs + k * g, v, g, prec); } acb_theta_naive_0b(th, new_zs, nb, tau, prec); acb_theta_char_dot_acb(c, a, v, g, prec); for (k = 0; k < nb; k++) { for (b = 0; b < n; b++) { acb_theta_char_get_acb(w, b, g); _acb_vec_add(w, w, zs + k * g, g, prec); acb_theta_char_dot_acb(x, a, w, g, prec); acb_mul_2exp_si(x, x, 1); acb_add(x, x, c, prec); acb_exp_pi_i(x, x, prec); acb_mul(&th[k * n + b], &th[k * n + b], x, prec); } } _acb_vec_clear(new_zs, nb * g); _acb_vec_clear(v, g); _acb_vec_clear(w, g); acb_clear(c); acb_clear(x); } flint-3.1.3/src/acb_theta/naive_fixed_ab.c000066400000000000000000000031321461254215100204220ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_theta_naive_fixed_ab(acb_ptr th, ulong ab, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); ulong a = ab >> g; ulong b = ab; acb_ptr new_zs; acb_ptr v, w; acb_t c, x; slong k; new_zs = _acb_vec_init(nb * g); v = _acb_vec_init(g); w = _acb_vec_init(g); acb_init(c); acb_init(x); acb_theta_char_get_acb(v, a, g); acb_mat_vector_mul_col(v, tau, v, prec); /* tau.a/2 */ acb_theta_char_get_acb(w, b, g); _acb_vec_add(w, v, w, g, prec); for (k = 0; k < nb; k++) { _acb_vec_add(new_zs + k * g, zs + k * g, w, g, prec); } acb_theta_naive_00(th, new_zs, nb, tau, prec); acb_theta_char_dot_acb(c, a, v, g, prec); for (k = 0; k < nb; k++) { acb_theta_char_get_acb(w, b, g); _acb_vec_add(w, w, zs + k * g, g, prec); acb_theta_char_dot_acb(x, a, w, g, prec); acb_mul_2exp_si(x, x, 1); acb_add(x, x, c, prec); acb_exp_pi_i(x, x, prec); acb_mul(&th[k], &th[k], x, prec); } _acb_vec_clear(new_zs, nb * g); _acb_vec_clear(v, g); _acb_vec_clear(w, g); acb_clear(c); acb_clear(x); } flint-3.1.3/src/acb_theta/naive_radius.c000066400000000000000000000053121461254215100201520ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_theta.h" /* Assuming a >= 0, return R2 such that x - (a/2)*log(x)\geq b for all x\geq R2, and R2 is close to the smallest possible */ static void invert_lin_plus_log(arf_t R2, slong a, const arb_t b, slong prec) { arb_t x, y, t; arf_t z; slong k; arb_init(x); arb_init(y); arb_init(t); arf_init(z); if (a == 0) { arb_get_ubound_arf(R2, b, prec); goto exit; } /* minimum is at x=a/2 */ arb_set_si(x, a); arb_div_si(x, x, 2, prec); arb_log(y, x, prec); arb_mul(y, y, x, prec); arb_sub(y, x, y, prec); /* x = max(a, 2*(b - min) + a log 2) is always large enough; then iterate function a few times */ arb_sub(y, b, y, prec); arb_const_log2(t, prec); arb_mul_2exp_si(t, t, -1); arb_mul_si(t, t, a, prec); arb_add(y, y, t, prec); arb_max(y, y, x, prec); arb_mul_si(x, y, 2, prec); arb_get_ubound_arf(z, x, prec); arb_set_arf(x, z); for (k = 0; k < 4; k++) { arb_log(y, x, prec); arb_mul_si(y, y, a, prec); arb_div_si(y, y, 2, prec); arb_add(x, b, y, prec); arb_get_ubound_arf(z, x, prec); arb_set_arf(x, z); } arb_get_ubound_arf(R2, x, prec); goto exit; exit: { arb_clear(x); arb_clear(y); arb_clear(t); arf_clear(z); } } void acb_theta_naive_radius(arf_t R2, arf_t eps, const arb_mat_t C, slong ord, slong prec) { slong g = arb_mat_nrows(C); slong lp = ACB_THETA_LOW_PREC; arb_t b, temp; arf_t cmp; slong k; arb_init(b); arb_init(temp); arf_init(cmp); arf_one(eps); arf_mul_2exp_si(eps, eps, -prec); arb_set_arf(b, eps); arb_mul_2exp_si(b, b, -2 * g - 2); /* Solve R2^((g-1)/2+ord) exp(-R2) \leq b */ arb_log(b, b, lp); arb_neg(b, b); invert_lin_plus_log(R2, g - 1 + 2 * ord, b, lp); /* Max with 4, 2*ord for formula to be valid */ arf_set_si(cmp, FLINT_MAX(4, 2 * ord)); arf_max(R2, R2, cmp); /* Set error */ arb_one(b); for (k = 0; k < g; k++) { arb_inv(temp, arb_mat_entry(C, k, k), lp); arb_add_si(temp, temp, 1, lp); arb_mul(b, b, temp, lp); } arb_mul_arf(b, b, eps, lp); arb_get_ubound_arf(eps, b, lp); arb_clear(b); arb_clear(temp); arf_clear(cmp); } flint-3.1.3/src/acb_theta/naive_reduce.c000066400000000000000000000102651461254215100201350ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" static void acb_theta_naive_round(arb_ptr a, arb_srcptr v, slong g) { slong j; fmpz_t m; fmpz_init(m); for (j = 0; j < g; j++) { if (arb_is_finite(&v[j]) && arf_cmpabs_2exp_si(arb_midref(&v[j]), 1000000) <= 0) { arf_get_fmpz(m, arb_midref(&v[j]), ARF_RND_NEAR); arb_set_fmpz(&a[j], m); } else { arb_zero(&a[j]); } } fmpz_clear(m); } static void _arb_vec_union(arb_ptr res, arb_srcptr v1, arb_srcptr v2, slong len, slong prec) { slong j; for (j = 0; j < len; j++) { arb_union(&res[j], &v1[j], &v2[j], prec); } } static void acb_theta_naive_reduce_one(arb_ptr v, acb_ptr new_z, arb_ptr a, acb_t c, arb_t u, acb_srcptr z, const arb_mat_t X, const arb_mat_t Y, const arb_mat_t Yinv, const arb_mat_t C, slong prec) { slong g = arb_mat_nrows(X); arb_ptr x, y, t, r, new_x, new_y; x = _arb_vec_init(g); y = _arb_vec_init(g); t = _arb_vec_init(g); r = _arb_vec_init(g); new_x = _arb_vec_init(g); new_y = _arb_vec_init(g); acb_zero(c); _acb_vec_get_real(x, z, g); _acb_vec_get_imag(y, z, g); /* Get center t = Yinv y of ellipsoid, set c = - i y^T Yinv y and u */ arb_mat_vector_mul_col(t, Yinv, y, prec); arb_dot(acb_imagref(c), acb_imagref(c), 1, y, 1, t, 1, g, prec); arb_const_pi(u, prec); arb_mul(u, u, acb_imagref(c), prec); arb_neg(u, u); arb_exp(u, u, prec); /* Round to nearest vector a = 0 mod 2 to not mess with characteristics */ _arb_vec_scalar_mul_2exp_si(t, t, g, -1); acb_theta_naive_round(a, t, g); _arb_vec_scalar_mul_2exp_si(a, a, g, 1); _arb_vec_scalar_mul_2exp_si(t, t, g, 1); /* Get r = t - a and v = C.r */ _arb_vec_sub(r, t, a, g, prec); arb_mat_vector_mul_col(v, C, r, prec); /* new_z is (x - Xa) + iYr; set new_x = x - Xa mod 4, t = Xa */ arb_mat_vector_mul_col(t, X, a, prec); _arb_vec_sub(new_x, x, t, g, prec); _arb_vec_scalar_mul_2exp_si(new_x, new_x, g, -2); acb_theta_naive_round(new_y, new_x, g); _arb_vec_sub(new_x, new_x, new_y, g, prec); _arb_vec_scalar_mul_2exp_si(new_x, new_x, g, 2); arb_mat_vector_mul_col(new_y, Y, r, prec); _acb_vec_set_real_imag(new_z, new_x, new_y, g); /* add a^T X a - 2 a^T x + i r^T Y r to c */ arb_dot(acb_realref(c), acb_realref(c), 0, a, 1, t, 1, g, prec); _arb_vec_scalar_mul_2exp_si(a, a, g, 1); arb_dot(acb_realref(c), acb_realref(c), 1, a, 1, x, 1, g, prec); arb_dot(acb_imagref(c), acb_imagref(c), 0, r, 1, new_y, 1, g, prec); _arb_vec_scalar_mul_2exp_si(a, a, g, -1); acb_exp_pi_i(c, c, prec); _arb_vec_clear(x, g); _arb_vec_clear(y, g); _arb_vec_clear(t, g); _arb_vec_clear(r, g); _arb_vec_clear(new_x, g); _arb_vec_clear(new_y, g); } void acb_theta_naive_reduce(arb_ptr v, acb_ptr new_zs, arb_ptr as, acb_ptr cs, arb_ptr us, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); arb_mat_t X, Y, C, Yinv; arb_ptr v1; slong k; arb_mat_init(X, g, g); arb_mat_init(Y, g, g); arb_mat_init(C, g, g); arb_mat_init(Yinv, g, g); v1 = _arb_vec_init(g); acb_mat_get_real(X, tau); acb_mat_get_imag(Y, tau); acb_siegel_cho(C, tau, prec); acb_siegel_yinv(Yinv, tau, prec); for (k = 0; k < nb; k++) { acb_theta_naive_reduce_one(v1, new_zs + k * g, as + k * g, &cs[k], &us[k], zs + k * g, X, Y, Yinv, C, prec); if (k == 0) { _arb_vec_set(v, v1, g); } else { _arb_vec_union(v, v, v1, g, prec); } } arb_mat_clear(X); arb_mat_clear(Y); arb_mat_clear(C); arb_mat_clear(Yinv); _arb_vec_clear(v1, g); } flint-3.1.3/src/acb_theta/naive_term.c000066400000000000000000000026351461254215100176370ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_theta_naive_term(acb_t res, acb_srcptr z, const acb_mat_t tau, const slong * tup, const slong * n, slong prec) { slong g = acb_mat_nrows(tau); acb_ptr v, w; acb_t dot; fmpz_t m, t; slong k; v = _acb_vec_init(g); w = _acb_vec_init(g); acb_init(dot); fmpz_init(m); fmpz_init(t); for (k = 0; k < g; k++) { acb_set_si(&v[k], n[k]); } acb_mat_vector_mul_col(w, tau, v, prec); acb_dot(res, NULL, 0, v, 1, w, 1, g, prec); acb_dot(dot, NULL, 0, v, 1, z, 1, g, prec); acb_mul_2exp_si(dot, dot, 1); acb_add(res, res, dot, prec); acb_exp_pi_i(res, res, prec); if (tup != NULL) { fmpz_one(m); for (k = 0; k < g; k++) { fmpz_set_si(t, n[k]); fmpz_pow_ui(t, t, tup[k]); fmpz_mul(m, m, t); } acb_mul_fmpz(res, res, m, prec); } _acb_vec_clear(v, g); _acb_vec_clear(w, g); acb_clear(dot); fmpz_clear(m); fmpz_clear(t); } flint-3.1.3/src/acb_theta/naive_worker.c000066400000000000000000000275051461254215100202040ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "acb_mat.h" #include "acb_theta.h" static slong acb_theta_naive_fullprec(const acb_theta_eld_t E, slong prec) { return prec + FLINT_MAX(prec + ceil(n_flog(1 + acb_theta_eld_nb_pts(E), 2)), ACB_THETA_LOW_PREC); } ACB_INLINE slong acb_theta_naive_newprec(slong prec, slong coord, slong dist, slong max_dist, slong ord) { double r = ((double) FLINT_MAX(0, dist - 1)) / (max_dist + 2); double neg = r * r * prec; double pos = ord * n_clog(1 + FLINT_ABS(coord), 2); return FLINT_MAX(ACB_THETA_LOW_PREC, ceil((double) prec - neg + pos)); } /* Call worker in dimension 1: make vectors to use in acb_dot */ static void acb_theta_naive_call_dim1(acb_ptr th, acb_ptr v1, acb_ptr v2, slong * precs, const acb_t lin, const acb_t lin_inv, const acb_t cf, acb_srcptr sqr_pow, const acb_theta_eld_t E, slong ord, slong prec, slong fullprec, acb_theta_naive_worker_t worker) { slong *coords; slong g = acb_theta_eld_ambient_dim(E); slong min = acb_theta_eld_min(E); slong mid = acb_theta_eld_mid(E); slong max = acb_theta_eld_max(E); slong len = acb_theta_eld_nb_pts(E); slong k; coords = flint_malloc(g * sizeof(slong)); coords[0] = min; for (k = 1; k < g; k++) { coords[k] = acb_theta_eld_coord(E, k); } /* Store lin^k in v1 and square powers in v2; then call worker */ for (k = mid; k <= max; k++) { precs[k - min] = acb_theta_naive_newprec(prec, k, k - mid, max - mid, ord); if ((k == mid) && (k >= 0)) { acb_pow_ui(&v1[mid - min], lin, mid, prec); } else if ((k == mid) && (k <= 0)) { acb_pow_ui(&v1[mid - min], lin_inv, -mid, prec); } else if ((k > FLINT_MAX(2 * mid, 0)) && (k % 2 == 0)) { acb_sqr(&v1[k - min], &v1[(k / 2) - min], precs[k - min]); } else { acb_mul(&v1[k - min], &v1[k - 1 - min], lin, precs[k - min]); } acb_set_round(&v2[k - min], &sqr_pow[FLINT_ABS(k)], precs[k - min]); } for (k = mid - 1; k >= min; k--) { precs[k - min] = acb_theta_naive_newprec(prec, k, k - mid, max - mid, ord); if ((k < FLINT_MIN(2 * mid, 0)) && (k % 2 == 0)) { acb_sqr(&v1[k - min], &v1[(k / 2) - min], precs[k - min]); } else { acb_mul(&v1[k - min], &v1[k + 1 - min], lin_inv, precs[k - min]); } acb_set_round(&v2[k - min], &sqr_pow[FLINT_ABS(k)], precs[k - min]); } worker(th, v1, v2, precs, len, cf, coords, ord, g, prec, fullprec); flint_free(coords); } /* Recursive call to smaller dimension; fall back to dim1 when appropriate */ static void acb_theta_naive_worker_rec(acb_ptr th, acb_ptr v1, acb_ptr v2, slong * precs, acb_mat_t lin_pow, acb_mat_t lin_pow_inv, const acb_t cf, acb_srcptr exp_z, acb_srcptr exp_z_inv, const acb_mat_t exp_tau, const acb_mat_t exp_tau_inv, const acb_ptr * sqr_pow, const acb_theta_eld_t E, slong ord, slong prec, slong fullprec, acb_theta_naive_worker_t worker) { slong d = acb_theta_eld_dim(E); slong g = acb_theta_eld_ambient_dim(E); slong nr = acb_theta_eld_nr(E); slong nl = acb_theta_eld_nl(E); slong min = acb_theta_eld_min(E); slong mid = acb_theta_eld_mid(E); slong max = acb_theta_eld_max(E); acb_t start_cf, diff_cf, diff_cf_inv, lin_cf, lin_cf_inv, full_cf; acb_ptr start_lin_pow, start_lin_pow_inv, diff_lin_pow, diff_lin_pow_inv; slong newprec; slong k, j, c; /* Catch cases: no points in ellipsoid; d=1 */ if (acb_theta_eld_nb_pts(E) == 0) { return; } else if (d == 1) { acb_init(lin_cf); acb_init(lin_cf_inv); acb_set(lin_cf, &exp_z[0]); acb_set(lin_cf_inv, &exp_z_inv[0]); for (k = 1; k < g; k++) { acb_mul(lin_cf, lin_cf, acb_mat_entry(lin_pow, 0, k), prec); acb_mul(lin_cf_inv, lin_cf_inv, acb_mat_entry(lin_pow_inv, 0, k), prec); } acb_theta_naive_call_dim1(th, v1, v2, precs, lin_cf, lin_cf_inv, cf, sqr_pow[0], E, ord, prec, fullprec, worker); acb_clear(lin_cf); acb_clear(lin_cf_inv); return; } acb_init(start_cf); acb_init(diff_cf); acb_init(diff_cf_inv); acb_init(lin_cf); acb_init(full_cf); start_lin_pow = _acb_vec_init(d - 1); start_lin_pow_inv = _acb_vec_init(d - 1); diff_lin_pow = _acb_vec_init(d - 1); diff_lin_pow_inv = _acb_vec_init(d - 1); /* Set up things for new cofactor */ acb_set(diff_cf, &exp_z[d - 1]); acb_set(diff_cf_inv, &exp_z_inv[d - 1]); for (k = d; k < g; k++) { acb_mul(diff_cf, diff_cf, acb_mat_entry(lin_pow, d - 1, k), prec); acb_mul(diff_cf_inv, diff_cf_inv, acb_mat_entry(lin_pow_inv, d - 1, k), prec); } if (mid >= 0) { acb_pow_ui(start_cf, diff_cf, mid, prec); } else { acb_pow_ui(start_cf, diff_cf_inv, -mid, prec); } acb_mul(start_cf, start_cf, cf, prec); /* Set up things to update entries (k,d) of lin_pow, k < d */ for (k = 0; k < d - 1; k++) { acb_set(&diff_lin_pow[k], acb_mat_entry(exp_tau, k, d - 1)); acb_set(&diff_lin_pow_inv[k], acb_mat_entry(exp_tau_inv, k, d - 1)); if (mid >= 0) { acb_pow_ui(&start_lin_pow[k], &diff_lin_pow[k], mid, prec); acb_pow_ui(&start_lin_pow_inv[k], &diff_lin_pow_inv[k], mid, prec); } else { acb_pow_ui(&start_lin_pow[k], &diff_lin_pow_inv[k], -mid, prec); acb_pow_ui(&start_lin_pow_inv[k], &diff_lin_pow[k], -mid, prec); } } /* Right loop */ acb_set(lin_cf, start_cf); for (k = 0; k < d - 1; k++) { acb_set(acb_mat_entry(lin_pow, k, d - 1), &start_lin_pow[k]); acb_set(acb_mat_entry(lin_pow_inv, k, d - 1), &start_lin_pow_inv[k]); } for (k = 0; k < nr; k++) { c = mid + k; newprec = acb_theta_naive_newprec(prec, c, c - mid, max - mid, ord); if (k > 0) /* Update lin_cf, lin_pow using diff */ { for (j = 0; j < d - 1; j++) { acb_mul(acb_mat_entry(lin_pow, j, d - 1), acb_mat_entry(lin_pow, j, d - 1), &diff_lin_pow[j], newprec); acb_mul(acb_mat_entry(lin_pow_inv, j, d - 1), acb_mat_entry(lin_pow_inv, j, d - 1), &diff_lin_pow_inv[j], newprec); } acb_mul(lin_cf, lin_cf, diff_cf, newprec); } acb_mul(full_cf, lin_cf, &sqr_pow[d - 1][FLINT_ABS(c)], newprec); acb_theta_naive_worker_rec(th, v1, v2, precs, lin_pow, lin_pow_inv, full_cf, exp_z, exp_z_inv, exp_tau, exp_tau_inv, sqr_pow, acb_theta_eld_rchild(E, k), ord, newprec, fullprec, worker); } /* Left loop */ acb_set(lin_cf, start_cf); for (k = 0; k < d - 1; k++) { acb_set(acb_mat_entry(lin_pow, k, d - 1), &start_lin_pow[k]); acb_set(acb_mat_entry(lin_pow_inv, k, d - 1), &start_lin_pow_inv[k]); } for (k = 0; k < nl; k++) { c = mid - (k + 1); newprec = acb_theta_naive_newprec(prec, c, mid - c, mid - min, ord); for (j = 0; j < d - 1; j++) { acb_mul(acb_mat_entry(lin_pow, j, d - 1), acb_mat_entry(lin_pow, j, d - 1), &diff_lin_pow_inv[j], newprec); acb_mul(acb_mat_entry(lin_pow_inv, j, d - 1), acb_mat_entry(lin_pow_inv, j, d - 1), &diff_lin_pow[j], newprec); } acb_mul(lin_cf, lin_cf, diff_cf_inv, newprec); acb_mul(full_cf, lin_cf, &sqr_pow[d - 1][FLINT_ABS(c)], newprec); acb_theta_naive_worker_rec(th, v1, v2, precs, lin_pow, lin_pow_inv, full_cf, exp_z, exp_z_inv, exp_tau, exp_tau_inv, sqr_pow, acb_theta_eld_lchild(E, k), ord, newprec, fullprec, worker); } acb_clear(start_cf); acb_clear(diff_cf); acb_clear(diff_cf_inv); acb_clear(lin_cf); acb_clear(full_cf); _acb_vec_clear(start_lin_pow, d - 1); _acb_vec_clear(start_lin_pow_inv, d - 1); _acb_vec_clear(diff_lin_pow, d - 1); _acb_vec_clear(diff_lin_pow_inv, d - 1); } static void acb_theta_naive_precompute(acb_mat_t exp_tau, acb_mat_t exp_tau_inv, acb_ptr * sqr_pow, const acb_mat_t tau, const acb_theta_eld_t E, slong prec) { slong g = acb_mat_nrows(tau); acb_t c, dc, ddc; slong k, j; acb_init(c); acb_init(dc); acb_init(ddc); for (k = 0; k < g; k++) { for (j = k; j < g; j++) { acb_set(c, acb_mat_entry(tau, k, j)); if (k != j) { acb_mul_2exp_si(c, c, 1); } acb_exp_pi_i(acb_mat_entry(exp_tau, k, j), c, prec); acb_inv(acb_mat_entry(exp_tau_inv, k, j), acb_mat_entry(exp_tau, k, j), prec); } } /* Addition chains do not make a huge difference here. */ for (k = 0; k < g; k++) { acb_one(c); acb_set(dc, acb_mat_entry(exp_tau, k, k)); acb_sqr(ddc, dc, prec); for (j = 0; j <= acb_theta_eld_box(E, k); j++) { acb_set(&sqr_pow[k][j], c); acb_mul(c, c, dc, prec); acb_mul(dc, dc, ddc, prec); } } acb_clear(c); acb_clear(dc); acb_clear(ddc); } /* User function */ void acb_theta_naive_worker(acb_ptr th, slong len, acb_srcptr zs, slong nb, const acb_mat_t tau, const acb_theta_eld_t E, slong ord, slong prec, acb_theta_naive_worker_t worker) { slong g = acb_theta_eld_ambient_dim(E); slong fullprec = acb_theta_naive_fullprec(E, prec); slong width = 0; acb_mat_t exp_tau, exp_tau_inv, lin_pow, lin_pow_inv; acb_ptr * sqr_pow; acb_ptr v1, v2, exp_z, exp_z_inv, res; slong * precs; acb_t cf; slong j, k; for (j = 0; j < g; j++) { width = FLINT_MAX(width, 2 * acb_theta_eld_box(E, j) + 1); } acb_mat_init(exp_tau, g, g); acb_mat_init(exp_tau_inv, g, g); acb_mat_init(lin_pow, g, g); acb_mat_init(lin_pow_inv, g, g); sqr_pow = flint_malloc(g * sizeof(acb_ptr)); for (j = 0; j < g; j++) { sqr_pow[j] = _acb_vec_init(acb_theta_eld_box(E, j) + 1); } v1 = _acb_vec_init(width); v2 = _acb_vec_init(width); exp_z = _acb_vec_init(g); exp_z_inv = _acb_vec_init(g); res = _acb_vec_init(len * nb); acb_init(cf); precs = flint_malloc(width * sizeof(slong)); acb_theta_naive_precompute(exp_tau, exp_tau_inv, sqr_pow, tau, E, prec); acb_one(cf); for (j = 0; j < nb; j++) { for (k = 0; k < g; k++) { acb_mul_2exp_si(&exp_z[k], &zs[j * g + k], 1); acb_exp_pi_i(&exp_z[k], &exp_z[k], prec); acb_inv(&exp_z_inv[k], &exp_z[k], prec); } acb_mat_set(lin_pow, exp_tau); acb_mat_set(lin_pow_inv, exp_tau_inv); acb_theta_naive_worker_rec(res + j * len, v1, v2, precs, lin_pow, lin_pow_inv, cf, exp_z, exp_z_inv, exp_tau, exp_tau_inv, sqr_pow, E, ord, fullprec, fullprec, worker); } _acb_vec_set(th, res, len * nb); acb_mat_clear(exp_tau); acb_mat_clear(exp_tau_inv); acb_mat_clear(lin_pow); acb_mat_clear(lin_pow_inv); for (j = 0; j < g; j++) { _acb_vec_clear(sqr_pow[j], acb_theta_eld_box(E, j) + 1); } flint_free(sqr_pow); _acb_vec_clear(v1, width); _acb_vec_clear(v2, width); _acb_vec_clear(exp_z, g); _acb_vec_clear(exp_z_inv, g); _acb_vec_clear(res, len * nb); acb_clear(cf); flint_free(precs); } flint-3.1.3/src/acb_theta/profile/000077500000000000000000000000001461254215100167745ustar00rootroot00000000000000flint-3.1.3/src/acb_theta/profile/p-all.c000066400000000000000000000053661461254215100201570ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "acb_mat.h" #include "acb_theta.h" static int usage(char * argv[]) { flint_printf("usage: %s g nb_steps hasz\n", argv[0]); return 1; } int main(int argc, char * argv[]) { slong prec; acb_mat_t tau; acb_ptr th, z, t; arb_ptr d0, d; slong g, n, nb_steps, nbz, k; slong guard = 16; int hasz; if (argc < 4) { return usage(argv); } g = atol(argv[1]); n = 1 << (2 * g); nb_steps = atol(argv[2]); hasz = (int) atol(argv[3]); nbz = (hasz ? 2 : 1); acb_mat_init(tau, g, g); th = _acb_vec_init(n * nbz); z = _acb_vec_init(g); t = _acb_vec_init(g); d0 = _arb_vec_init(1 << g); d = _arb_vec_init(1 << g); acb_mat_onei(tau); for (k = 0; k < g - 1; k++) { acb_onei(acb_mat_entry(tau, k, k + 1)); acb_mul_2exp_si(acb_mat_entry(tau, k, k + 1), acb_mat_entry(tau, k, k + 1), -2); acb_set(acb_mat_entry(tau, k + 1, k), acb_mat_entry(tau, k, k + 1)); } prec = 32; if (hasz) { acb_set_si(z, 2); acb_sqrt(z, z, prec); } acb_theta_dist_a0(d0, t, tau, prec); acb_theta_dist_a0(d, z, tau, prec); for (k = 0; k < nb_steps; k++) { if (hasz) { acb_set_si(z, 2); acb_sqrt(z, z, prec); } flint_printf("prec = %wd, acb_theta_naive_all:\n", prec); TIMEIT_START; acb_theta_naive_all(th, z, 1, tau, prec); TIMEIT_STOP; acb_printd(&th[0], 5); flint_printf("\n"); flint_printf("prec = %wd, acb_theta_ql_a0:\n", prec); TIMEIT_START; acb_theta_ql_a0(th, t, z, d0, d, tau, guard, prec); TIMEIT_STOP; acb_printd(&th[hasz * n], 5); flint_printf("\n"); flint_printf("prec = %wd, acb_theta_ql_all:\n", prec); TIMEIT_START; acb_theta_ql_all(th, z, tau, 0, prec); TIMEIT_STOP; acb_printd(&th[0], 5); flint_printf("\n"); flint_printf("prec = %wd, acb_theta_all:\n", prec); TIMEIT_START; acb_theta_all(th, z, tau, 0, prec); TIMEIT_STOP; acb_printd(&th[0], 5); flint_printf("\n\n"); prec *= 2; } acb_mat_clear(tau); _acb_vec_clear(th, n * nbz); _arb_vec_clear(d0, 1 << g); _arb_vec_clear(d, 1 << g); _acb_vec_clear(z, g); _acb_vec_clear(t, g); } flint-3.1.3/src/acb_theta/profile/p-jet_all.c000066400000000000000000000027431461254215100210150ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "ulong_extras.h" #include "acb_mat.h" #include "acb_theta.h" int main(void) { slong prec; acb_mat_t tau; acb_ptr dth, z; slong nb = 3 * 16; acb_mat_init(tau, 2, 2); dth = _acb_vec_init(nb); z = _acb_vec_init(2); acb_onei(acb_mat_entry(tau, 0, 0)); acb_onei(acb_mat_entry(tau, 1, 1)); acb_onei(acb_mat_entry(tau, 1, 0)); acb_mul_2exp_si(acb_mat_entry(tau, 1, 0), acb_mat_entry(tau, 1, 0), -2); acb_set(acb_mat_entry(tau, 0, 1), acb_mat_entry(tau, 1, 0)); acb_mat_printd(tau, 5); for (prec = 32; prec <= n_pow(2, 15); prec *= 2) { flint_printf("prec = %wd, naive:\n", prec); TIMEIT_START; acb_theta_jet_naive_all(dth, z, tau, 1, prec); TIMEIT_STOP; acb_printd(&dth[0], 5); flint_printf("\n"); flint_printf("prec = %wd, ql:\n", prec); TIMEIT_START; acb_theta_jet_all(dth, z, tau, 1, prec); TIMEIT_STOP; acb_printd(&dth[0], 5); flint_printf("\n\n"); } acb_mat_clear(tau); _acb_vec_clear(dth, nb); _acb_vec_clear(z, 2); } flint-3.1.3/src/acb_theta/profile/p-ql_a0.c000066400000000000000000000057751461254215100204070ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "acb_mat.h" #include "acb_theta.h" static int usage(char * argv[]) { flint_printf("usage: %s g pstep pmax\n", argv[0]); return 1; } int main(int argc, char * argv[]) { slong iter = 0; flint_rand_t state; slong g, n, pstep, pmax, prec; if (argc < 4) { return usage(argv); } g = atol(argv[1]); n = 1 << g; pstep = atol(argv[2]); pmax = atol(argv[3]); flint_randinit(state); /* Profile with different number of steps on reduced input */ for (prec = pstep; prec <= pmax; prec += pstep) { int hast = iter % 2; int hasz = (iter % 4) / 2; slong nbt = (hast ? 3 : 1); slong nbz = (hasz ? 2 : 1); slong guard = 2 * ACB_THETA_LOW_PREC; slong lp = ACB_THETA_LOW_PREC; acb_mat_t tau; acb_ptr z, t, r; arb_ptr dist, dist0; arb_t test; slong k; int res = 0; iter++; acb_mat_init(tau, g, g); z = _acb_vec_init(g); t = _acb_vec_init(g); r = _acb_vec_init(nbz * nbt * n); dist = _arb_vec_init(n); dist0 = _arb_vec_init(n); arb_init(test); while (!res) { acb_siegel_randtest_reduced(tau, state, prec, 4); arb_sub_si(test, acb_imagref(acb_mat_entry(tau, g - 1, g - 1)), 3, prec); res = arb_is_negative(test); } for (k = 0; k < g; k++) { if (hasz) { acb_urandom(&z[k], state, prec); } if (hast) { arb_urandom(acb_realref(&t[k]), state, prec); } } acb_theta_dist_a0(dist, z, tau, lp); acb_theta_dist_a0(dist0, t, tau, lp); flint_printf("g = %wd, prec = %wd, hast = %wd, hasz = %wd, tau:\n", g, prec, hast, hasz); acb_mat_printd(tau, 2); TIMEIT_START; res = acb_theta_ql_a0(r, t, z, dist0, dist, tau, guard, prec); TIMEIT_STOP; if (res) { flint_printf("result (expected rad e-%wd):\n", (slong) ceil((double) prec * log(2)/log(10))); acb_printd(&r[0], 5); flint_printf("\n"); } else { flint_printf("FAIL\n"); } flint_printf("\n"); acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(t, g); _acb_vec_clear(r, nbz * nbt * n); _arb_vec_clear(dist, n); _arb_vec_clear(dist0, n); arb_clear(test); } flint_randclear(state); flint_cleanup(); return 0; } flint-3.1.3/src/acb_theta/profile/p-ql_a0_split.c000066400000000000000000000103601461254215100216040ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "acb_mat.h" #include "acb_theta.h" static int usage(char * argv[]) { flint_printf("usage: %s g prec cstep cmax\n", argv[0]); return 1; } int main(int argc, char * argv[]) { flint_rand_t state; slong g, n, prec, c, cstep, cmax; if (argc < 5) { return usage(argv); } g = atol(argv[1]); n = 1 << g; prec = atol(argv[2]); cstep = atol(argv[3]); cmax = atol(argv[4]); flint_randinit(state); /* Profile with different splittings on reduced input */ for (c = cstep; c <= cmax; c += cstep) { slong guard = 2 * ACB_THETA_LOW_PREC; slong lp = ACB_THETA_LOW_PREC; acb_mat_t tau, tau1; arb_mat_t cho; acb_ptr t, r1, r2, r3; arb_ptr dist0; arb_t test; slong nb_steps_1, nb_steps_2, split; slong j, k; int res = 0; acb_mat_init(tau, g, g); acb_mat_init(tau1, g, g); arb_mat_init(cho, g, g); t = _acb_vec_init(g); r1 = _acb_vec_init(n); r2 = _acb_vec_init(n); r3 = _acb_vec_init(n); dist0 = _arb_vec_init(n); arb_init(test); while (!res) { acb_siegel_randtest_reduced(tau, state, prec, 4); arb_sub_si(test, acb_imagref(acb_mat_entry(tau, g - 1, g - 1)), 3, prec); res = arb_is_negative(test); } for (split = 1; split < g; split++) { acb_mat_set(tau1, tau); for (j = split; j < g; j++) { for (k = split; k < g; k++) { acb_mul_si(acb_mat_entry(tau1, j, k), acb_mat_entry(tau1, j, k), c, prec); } } flint_printf("g = %wd, prec = %wd, c = %wd, split = %wd, matrix:\n", g, prec, c, split); acb_mat_printd(tau1, 2); acb_theta_dist_a0(dist0, t, tau1, lp); acb_siegel_cho(cho, tau1, lp); nb_steps_1 = acb_theta_ql_a0_nb_steps(cho, split, prec); nb_steps_2 = acb_theta_ql_a0_nb_steps(cho, 0, prec); flint_printf("time for split (nb_steps = %wd):\n", nb_steps_1); TIMEIT_START; res = acb_theta_ql_a0_steps(r1, t, t, dist0, dist0, tau1, nb_steps_1, split, guard, prec, &acb_theta_ql_a0); TIMEIT_STOP; if (res) { flint_printf("time for non-split (nb_steps = %wd):\n", nb_steps_2); TIMEIT_START; res = acb_theta_ql_a0_steps(r2, t, t, dist0, dist0, tau1, nb_steps_2, 0, guard, prec, &acb_theta_ql_a0); TIMEIT_STOP; } if (res) { flint_printf("time for ql_a0:\n"); TIMEIT_START; res = acb_theta_ql_a0(r3, t, t, dist0, dist0, tau1, guard, prec); TIMEIT_STOP; } if (res) { flint_printf("result for split (expected prec loss %wd):\n", (guard + g) * nb_steps_1); acb_printd(&r1[0], 5); flint_printf("\nresult for non-split (expected prec loss %wd):\n", (guard + g) * nb_steps_2); acb_printd(&r2[0], 5); flint_printf("\nresult for ql_a0:\n"); acb_printd(&r3[0], 5); flint_printf("\n\n"); } else { flint_printf("FAIL\n\n"); } } acb_mat_clear(tau); acb_mat_clear(tau1); arb_mat_clear(cho); _acb_vec_clear(t, g); _acb_vec_clear(r1, n); _acb_vec_clear(r2, n); _acb_vec_clear(r3, n); _arb_vec_clear(dist0, n); arb_clear(test); } flint_randclear(state); flint_cleanup(); return 0; } flint-3.1.3/src/acb_theta/profile/p-ql_a0_steps.c000066400000000000000000000067761461254215100216270ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" static int usage(char * argv[]) { flint_printf("usage: %s g pstep pmax\n", argv[0]); return 1; } int main(int argc, char * argv[]) { slong iter = 0; flint_rand_t state; slong g, n, pstep, pmax, prec; if (argc < 4) { return usage(argv); } g = atol(argv[1]); n = 1 << g; pstep = atol(argv[2]); pmax = atol(argv[3]); flint_randinit(state); /* Profile with different number of steps on reduced input */ for (prec = pstep; prec <= pmax; prec += pstep) { int hast = iter % 2; int hasz = (iter % 4) / 2; slong nbt = (hast ? 3 : 1); slong nbz = (hasz ? 2 : 1); slong guard = 2 * ACB_THETA_LOW_PREC; slong lp = ACB_THETA_LOW_PREC; acb_mat_t tau; arb_mat_t cho; acb_ptr z, t, r; arb_ptr dist, dist0; arb_t test; slong nb_steps, split; slong k; int res = 0; iter++; acb_mat_init(tau, g, g); arb_mat_init(cho, g, g); z = _acb_vec_init(g); t = _acb_vec_init(g); r = _acb_vec_init(nbz * nbt * n); dist = _arb_vec_init(n); dist0 = _arb_vec_init(n); arb_init(test); while (!res) { acb_siegel_randtest_reduced(tau, state, prec, 4); arb_sub_si(test, acb_imagref(acb_mat_entry(tau, g - 1, g - 1)), 3, prec); res = arb_is_negative(test); } acb_siegel_cho(cho, tau, lp); for (k = 0; k < g; k++) { if (hasz) { acb_urandom(&z[k], state, prec); } if (hast) { arb_urandom(acb_realref(&t[k]), state, prec); } } acb_theta_dist_a0(dist, z, tau, lp); acb_theta_dist_a0(dist0, t, tau, lp); split = 0; nb_steps = acb_theta_ql_a0_nb_steps(cho, 0, prec); flint_printf("(g = %wd, prec = %wd, hast = %wd, hasz = %wd) ideal nb_steps: %wd, tau:\n", g, prec, hast, hasz, nb_steps); acb_mat_printd(tau, 2); for (k = -FLINT_MIN(nb_steps, 2); k <= 2; k++) { flint_printf("nb_steps = %wd: ", nb_steps + k); TIMEIT_START; res = acb_theta_ql_a0_steps(r, t, z, dist0, dist, tau, nb_steps + k, split, guard, prec, &acb_theta_ql_a0_naive); TIMEIT_STOP; if (res) { flint_printf("result (expected prec loss %wd):\n", (guard + g) * (nb_steps + k)); acb_printd(&r[0], 5); flint_printf("\n"); } else { flint_printf("FAIL\n"); } } flint_printf("\n"); acb_mat_clear(tau); arb_mat_clear(cho); _acb_vec_clear(z, g); _acb_vec_clear(t, g); _acb_vec_clear(r, nbz * nbt * n); _arb_vec_clear(dist, n); _arb_vec_clear(dist0, n); arb_clear(test); } flint_randclear(state); flint_cleanup(); return 0; } flint-3.1.3/src/acb_theta/profile/p-siegel_reduce.c000066400000000000000000000040771461254215100222040ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "acb_mat.h" #include "acb_theta.h" static int usage(char * argv[]) { flint_printf("usage: %s g pstep pmax dstep dmax\n", argv[0]); return 1; } int main(int argc, char * argv[]) { slong g; slong prec, pmax, pstep; slong d, dmax, dstep; flint_rand_t state; acb_mat_t tau, w; arb_t r; fmpz_mat_t mat; slong j, k; if (argc < 6) { return usage(argv); } g = atol(argv[1]); pstep = atol(argv[2]); pmax = atol(argv[3]); dstep = atol(argv[4]); dmax = atol(argv[5]); flint_randinit(state); acb_mat_init(tau, g, g); acb_mat_init(w, g, g); arb_init(r); fmpz_mat_init(mat, 2 * g, 2 * g); acb_siegel_randtest_reduced(tau, state, pmax, 2); flint_printf("Starting matrix:\n"); acb_mat_printd(tau, 5); for (prec = pstep; prec <= pmax; prec += pstep) { for (d = dstep; d <= dmax; d += dstep) { acb_mat_scalar_div_si(w, tau, d, prec); for (j = 0; j < g; j++) { for (k = 0; k <= j; k++) { arb_urandom(r, state, prec); acb_add_arb(acb_mat_entry(w, j, k), acb_mat_entry(w, j, k), r, prec); acb_set(acb_mat_entry(w, k, j), acb_mat_entry(w, j, k)); } } flint_printf("prec = %wd, d = %wd\n", prec, d); TIMEIT_START; acb_siegel_reduce(mat, w, prec); TIMEIT_STOP; } } flint_randclear(state); acb_mat_clear(tau); acb_mat_clear(w); arb_clear(r); fmpz_mat_clear(mat); flint_cleanup(); return 0; } flint-3.1.3/src/acb_theta/ql_a0.c000066400000000000000000000074411461254215100165020ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" static slong acb_theta_ql_split(const arb_mat_t cho) { slong g = arb_mat_nrows(cho); arb_t cmp; slong k; arb_init(cmp); for (k = g - 1; k >= 1; k--) { arb_mul_2exp_si(cmp, arb_mat_entry(cho, k - 1, k - 1), FLINT_MAX(1, 6 + k - 2 * g)); if (arb_lt(cmp, arb_mat_entry(cho, k, k))) { break; } } arb_clear(cmp); return k; } int acb_theta_ql_a0(acb_ptr r, acb_srcptr t, acb_srcptr z, arb_srcptr dist0, arb_srcptr dist, const acb_mat_t tau, slong guard, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; int has_t = !_acb_vec_is_zero(t, g); int has_z = !_acb_vec_is_zero(z, g); slong nbt = (has_t ? 3 : 1); slong nbz = (has_z ? 2 : 1); slong nb_der = acb_theta_jet_nb(2, g); arb_mat_t cho; slong split, nb_steps, padding, lp; acb_mat_t tau_mid; acb_ptr t_mid, z_mid, dth; arb_t err; arf_t e; slong k, j, a; int res; arb_mat_init(cho, g, g); acb_mat_init(tau_mid, g, g); t_mid = _acb_vec_init(g); z_mid = _acb_vec_init(g); dth = _acb_vec_init(nb_der); arb_init(err); arf_init(e); acb_siegel_cho(cho, tau, ACB_THETA_LOW_PREC); split = acb_theta_ql_split(cho); nb_steps = acb_theta_ql_a0_nb_steps(cho, split, prec); if (has_t || has_z) { nb_steps += 1; /* cf p-ql_a0_steps */ } padding = nb_steps * (guard + g); arf_one(e); arf_mul_2exp_si(e, e, -prec - padding); /* Expect precision loss of (guard + g) * nb_steps, so call ql_a0_steps at midpoint */ acb_mat_get_mid(tau_mid, tau); for (k = 0; k < g; k++) { for (j = 0; j <= k; j++) { acb_add_error_arf(acb_mat_entry(tau_mid, k, j), e); acb_set(acb_mat_entry(tau_mid, j, k), acb_mat_entry(tau_mid, k, j)); } } for (k = 0; k < g; k++) { acb_get_mid(&z_mid[k], &z[k]); acb_get_mid(&t_mid[k], &t[k]); if (has_z) { acb_add_error_arf(&z_mid[k], e); } if (has_t) { arb_add_error_arf(acb_realref(&t_mid[k]), e); } } res = acb_theta_ql_a0_steps(r, t_mid, z_mid, dist0, dist, tau_mid, nb_steps, split, guard, prec + padding, &acb_theta_ql_a0); /* Add error, using z_mid as temp */ for (k = 0; (k < nbz * nbt) && res; k++) { _acb_vec_zero(z_mid, g); if (has_t) { _acb_vec_scalar_mul_ui(t_mid, t, g, k % 3, prec); _acb_vec_add(z_mid, z_mid, t_mid, g, prec); } if (has_z && (k >= nbt)) { _acb_vec_add(z_mid, z_mid, z, g, prec); } for (a = 0; a < n; a++) { if (has_z && (k >= nbt)) { lp = FLINT_MAX(ACB_THETA_LOW_PREC, acb_theta_dist_addprec(&dist[a])); } else { lp = FLINT_MAX(ACB_THETA_LOW_PREC, acb_theta_dist_addprec(&dist0[a])); } acb_theta_jet_naive_fixed_ab(dth, a << g, z_mid, tau, 2, lp); acb_theta_jet_error_bounds(err, z_mid, tau, dth, 0, lp); acb_add_error_arb(&r[k * n + a], err); } } arb_mat_clear(cho); acb_mat_clear(tau_mid); _acb_vec_clear(t_mid, g); _acb_vec_clear(z_mid, g); _acb_vec_clear(dth, nb_der); arb_clear(err); arf_clear(e); return res; } flint-3.1.3/src/acb_theta/ql_a0_naive.c000066400000000000000000000101051461254215100176530ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_modular.h" #include "acb_theta.h" static int acb_theta_ql_a0_naive_gen(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; int hast = !_acb_vec_is_zero(t, g); int hasz = !_acb_vec_is_zero(z, g); slong nbt = (hast ? 3 : 1); slong nbz = (hasz ? 2 : 1); acb_ptr x, aux; slong j, k; int res; x = _acb_vec_init(g * nbt); aux = _acb_vec_init(nbt); for (k = 0; k < nbt; k++) { _acb_vec_scalar_mul_ui(x + k * g, t, g, k, prec); } for (k = 0; k < n; k++) { acb_theta_naive_fixed_ab(aux, k << g, x, nbt, tau, prec + acb_theta_dist_addprec(&d0[k])); for (j = 0; j < nbt; j++) { acb_set(&th[j * n + k], &aux[j]); } } if (hasz) { for (k = 0; k < nbt; k++) { _acb_vec_add(x + k * g, x + k * g, z, g, prec); } for (k = 0; k < n; k++) { acb_theta_naive_fixed_ab(aux, k << g, x, nbt, tau, prec + acb_theta_dist_addprec(&d[k])); for (j = 0; j < nbt; j++) { acb_set(&th[nbt * n + j * n + k], &aux[j]); } } } res = _acb_vec_is_finite(th, n * nbz * nbt); _acb_vec_clear(x, g * nbt); _acb_vec_clear(aux, nbt); return res; } /* when g = 1, we don't go as far near the cusp and computing exponentials is relatively more expensive */ static int acb_theta_ql_a0_naive_g1(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec) { int hast = !acb_is_zero(t); int hasz = !acb_is_zero(z); slong nbt = (hast ? 3 : 1); slong nbz = (hasz ? 2 : 1); acb_t q4, q, u, v, w, t3, t1; slong k; int res, w_is_unit; acb_init(q4); acb_init(q); acb_init(u); acb_init(v); acb_init(w); acb_init(t3); acb_init(t1); for (k = 0; k < 2; k++) { prec = prec + FLINT_MAX(0, acb_theta_dist_addprec(&d[k])); prec = prec + FLINT_MAX(0, acb_theta_dist_addprec(&d0[k])); } /* compute q_{1/4}, q */ acb_mul_2exp_si(q4, acb_mat_entry(tau, 0, 0), -2); acb_exp_pi_i(q4, q4, prec); acb_pow_ui(q, q4, 4, prec); /* compute v, w */ acb_exp_pi_i(v, t, prec); acb_exp_pi_i(w, z, prec); w_is_unit = arb_is_zero(acb_imagref(z)); acb_one(u); for (k = 0; k < nbt; k++) { if (k > 0) { acb_mul(u, u, v, prec); } acb_modular_theta_sum(t3, &th[2 * k + 1], &th[2 * k], t1, u, 1, q, 1, prec); acb_mul(&th[2 * k + 1], &th[2 * k + 1], q4, prec); } if (hasz) { acb_set(u, w); for (k = 0; k < nbt; k++) { if (k > 0) { acb_mul(u, u, v, prec); } acb_modular_theta_sum(t3, &th[2 * nbt + 2 * k + 1], &th[2 * nbt + 2 * k], t1, u, w_is_unit, q, 1, prec); acb_mul(&th[2 * nbt + 2 * k + 1], &th[2 * nbt + 2 * k + 1], q4, prec); } } res = _acb_vec_is_finite(th, 2 * nbz * nbt); acb_clear(q4); acb_clear(q); acb_clear(u); acb_clear(v); acb_clear(w); acb_clear(t3); acb_clear(t1); return res; } int acb_theta_ql_a0_naive(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec) { slong g = acb_mat_nrows(tau); if (g == 1) { return acb_theta_ql_a0_naive_g1(th, t, z, d0, d, tau, guard, prec); } else { return acb_theta_ql_a0_naive_gen(th, t, z, d0, d, tau, guard, prec); } } flint-3.1.3/src/acb_theta/ql_a0_nb_steps.c000066400000000000000000000025741461254215100204010ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_theta.h" slong acb_theta_ql_a0_nb_steps(const arb_mat_t C, slong s, slong prec) { slong g = arb_mat_nrows(C); slong lp = ACB_THETA_LOW_PREC; arb_t x, t; slong res; FLINT_ASSERT(s >= 0 && s < g); arb_init(x); arb_init(t); arb_sqr(x, arb_mat_entry(C, s, s), lp); arb_const_log2(t, lp); arb_div(x, x, t, lp); arb_div_si(x, x, prec, lp); arb_log(x, x, lp); arb_div(x, x, t, lp); if (!arb_is_finite(x) || arf_cmpabs_2exp_si(arb_midref(x), FLINT_BITS - 4) > 0) { arb_clear(x); arb_clear(t); return 0; } res = -arf_get_si(arb_midref(x), ARF_RND_NEAR); if (s == 0) { if (g == 1) { res -= 7; } else if (g == 2) { res -= 3; } else if (g <= 5) { res -= 1; } } else { res += 1; } res = FLINT_MAX(0, res); arb_clear(x); arb_clear(t); return res; } flint-3.1.3/src/acb_theta/ql_a0_split.c000066400000000000000000000153211461254215100177110ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" static int acb_theta_ql_a0_eld_points(slong ** pts, slong * nb_pts, arb_ptr v, slong * fullprec, arf_t eps, arb_srcptr d, ulong a, arb_srcptr w, const arb_mat_t C, const arb_mat_t C1, slong prec) { slong g = arb_mat_nrows(C); slong s = g - arb_mat_nrows(C1); slong n = 1 << g; slong nba = 1 << (g - s); slong lp = ACB_THETA_LOW_PREC; arb_t max_d; arf_t R2; acb_theta_eld_t E; slong k; int res; acb_theta_eld_init(E, g - s, g - s); arf_init(R2); arb_init(max_d); /* Get offset */ acb_theta_char_get_arb(v, a, g - s); _arb_vec_add(v, v, w + s, g - s, prec); arb_mat_vector_mul_col(v, C1, v, prec); /* Get R2 */ arb_zero(max_d); for (k = a; k < n; k += nba) { arb_max(max_d, max_d, &d[k], lp); } *fullprec = prec + acb_theta_dist_addprec(max_d); acb_theta_naive_radius(R2, eps, C, 0, *fullprec); /* List points in ellipsoid */ res = acb_theta_eld_set(E, C1, R2, v); if (res) { *nb_pts = acb_theta_eld_nb_pts(E); *pts = flint_malloc(acb_theta_eld_nb_pts(E) * (g - s) * sizeof(slong)); acb_theta_eld_points(*pts, E); } else { *nb_pts = 0; *pts = flint_malloc(0); } acb_theta_eld_clear(E); arf_clear(R2); arb_init(max_d); return res; } static int acb_theta_ql_a0_split_term(acb_ptr th, slong * pt, ulong a, acb_srcptr t, acb_srcptr z, arb_srcptr v, arb_srcptr d, arb_srcptr new_d0, const acb_mat_t tau0, const acb_mat_t star, const acb_mat_t tau1, const arb_mat_t C1, slong guard, slong prec, slong fullprec, acb_theta_ql_worker_t worker) { slong s = acb_mat_nrows(tau0); slong g = s + acb_mat_nrows(tau1); slong lp = ACB_THETA_LOW_PREC; slong n = 1 << g; slong nba = 1 << (g - s); slong nbth = 1 << s; slong nbt = (_acb_vec_is_zero(t, g) ? 1 : 3); slong new_prec; acb_ptr u, w, new_z, new_th; acb_t f, c; arb_ptr new_d; arb_t orth, x; slong j, k; int res; u = _acb_vec_init(g - s); w = _acb_vec_init(g - s); new_z = _acb_vec_init(s); new_th = _acb_vec_init(2 * nbth * nbt); new_d = _arb_vec_init(nbth); acb_init(f); acb_init(c); arb_init(orth); arb_init(x); /* Set u to pt + a1/2 */ acb_theta_char_get_acb(u, a, g - s); for (j = 0; j < g - s; j++) { acb_add_si(&u[j], &u[j], pt[j], prec); } /* Get new_z and cofactor at 0 */ acb_mat_vector_mul_col(new_z, star, u, prec); _acb_vec_add(new_z, new_z, z, s, prec); acb_dot(f, NULL, 0, u, 1, z + s, 1, g - s, prec); acb_mul_2exp_si(f, f, 1); acb_mat_vector_mul_col(w, tau1, u, prec); acb_dot(f, f, 0, w, 1, u, 1, g - s, prec); /* Get new distances and relative precision */ acb_theta_dist_a0(new_d, new_z, tau0, lp); acb_theta_dist_pt(orth, v, C1, pt, lp); new_prec = prec; for (j = 0; j < nbth; j++) { arb_sub(x, &d[a + j * nba], orth, lp); arb_sub(x, x, &new_d[j], lp); new_prec = FLINT_MIN(new_prec, prec + acb_theta_dist_addprec(x)); } new_prec = FLINT_MAX(new_prec, lp); /* Call worker */ res = worker(new_th, t, new_z, new_d0, new_d, tau0, guard, new_prec); if (!_acb_vec_is_zero(new_z, s)) { /* We are only interested in the values at z */ _acb_vec_set(new_th, new_th + nbth * nbt, nbth * nbt); } /* Rescale to set th; cofactor depends on t */ for (k = 0; k < nbt; k++) { acb_dot(c, NULL, 0, u, 1, t + s, 1, g - s, prec); acb_mul_si(c, c, 2 * k, prec); acb_add(c, c, f, prec); acb_exp_pi_i(c, c, prec); _acb_vec_scalar_mul(new_th + k * nbth, new_th + k * nbth, nbth, c, prec); for (j = 0; j < nbth; j++) { acb_add(&th[k * n + j * nba + a], &th[k * n + j * nba + a], &new_th[k * nbth + j], fullprec); } } _acb_vec_clear(u, g - s); _acb_vec_clear(w, g - s); _acb_vec_clear(new_z, s); _acb_vec_clear(new_th, 2 * nbth * nbt); _arb_vec_clear(new_d, nbth); acb_clear(f); acb_clear(c); arb_clear(orth); arb_clear(x); return res; } int acb_theta_ql_a0_split(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d, const acb_mat_t tau, slong s, slong guard, slong prec, acb_theta_ql_worker_t worker) { slong g = acb_mat_nrows(tau); slong n = 1 << g; slong nba = 1 << (g - s); slong nbth = 1 << s; slong nbt = (_acb_vec_is_zero(t, g) ? 1 : 3); slong lp = ACB_THETA_LOW_PREC; arb_mat_t C, C1, Yinv; acb_mat_t tau0, star, tau1; arb_ptr v, w, new_d0; arf_t eps; slong * pts; slong fullprec, nb_pts; slong a, j, k; int res = 1; FLINT_ASSERT(s >= 1 && s < g); arb_mat_init(C, g, g); arb_mat_init(Yinv, g, g); acb_mat_window_init(tau0, tau, 0, 0, s, s); acb_mat_window_init(star, tau, 0, s, s, g); acb_mat_window_init(tau1, tau, s, s, g, g); v = _arb_vec_init(g - s); w = _arb_vec_init(g); new_d0 = _arb_vec_init(nbth); arf_init(eps); acb_siegel_yinv(Yinv, tau, prec); acb_siegel_cho(C, tau, prec); arb_mat_window_init(C1, C, s, s, g, g); acb_theta_dist_a0(new_d0, z, tau0, lp); _acb_vec_get_imag(w, z, g); arb_mat_vector_mul_col(w, Yinv, w, prec); _acb_vec_zero(th, n * nbt); for (a = 0; (a < nba) && res; a++) { /* Get offset, fullprec, error and list of points in ellipsoid */ res = acb_theta_ql_a0_eld_points(&pts, &nb_pts, v, &fullprec, eps, d, a, w, C, C1, prec); /* Sum terms at each point using worker */ for (k = 0; (k < nb_pts) && res; k++) { res = acb_theta_ql_a0_split_term(th, pts + k * (g - s), a, t, z, v, d, new_d0, tau0, star, tau1, C1, guard, prec, fullprec, worker); } /* Add error */ for (k = 0; k < nbth; k++) { for (j = 0; j < nbt; j++) { acb_add_error_arf(&th[j * n + k * nba + a], eps); } } flint_free(pts); } arb_mat_clear(C); arb_mat_window_clear(C1); arb_mat_clear(Yinv); acb_mat_window_clear(tau0); acb_mat_window_clear(star); acb_mat_window_clear(tau1); _arb_vec_clear(v, g - s); _arb_vec_clear(w, g); _arb_vec_clear(new_d0, nbth); arf_clear(eps); return res; } flint-3.1.3/src/acb_theta/ql_a0_steps.c000066400000000000000000000241421461254215100177150ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" static int acb_theta_ql_roots_1(acb_ptr rts, acb_srcptr z, arb_srcptr d, const arb_t f, const acb_mat_t tau, slong nb_steps, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; acb_mat_t w; acb_ptr x; arb_t c, h; slong hprec, guard; slong k, a; int res = 1; acb_mat_init(w, g, g); x = _acb_vec_init(g); arb_init(c); arb_init(h); for (k = 0; (k < nb_steps) && res; k++) { acb_mat_scalar_mul_2exp_si(w, tau, k); _acb_vec_scalar_mul_2exp_si(x, z, g, k); arb_mul_2exp_si(c, f, k); arb_exp(c, c, prec); for (a = 0; (a < n) && res; a++) { arb_mul_2exp_si(h, &d[a], k); res = 0; for (guard = 16; (guard <= prec) && !res; guard += 16) { hprec = guard + acb_theta_dist_addprec(h); acb_theta_naive_fixed_ab(&rts[k * n + a], a << g, x, 1, w, hprec); if (acb_is_finite(&rts[k * n + a]) && !acb_contains_zero(&rts[k * n + a])) { res = 1; } } } _acb_vec_scalar_mul_arb(rts + k * n, rts + k * n, n, c, prec); } acb_mat_clear(w); _acb_vec_clear(x, g); arb_clear(c); arb_clear(h); return res; } static int acb_theta_ql_roots_3(acb_ptr rts, acb_srcptr t, acb_srcptr z, arb_srcptr d, const acb_mat_t tau, slong nb_steps, slong guard, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; int has_t = !_acb_vec_is_zero(t, g); arb_mat_t Yinv; acb_ptr x; arb_ptr y, w; arb_t f, pi; slong k; int res = 1; arb_mat_init(Yinv, g, g); x = _acb_vec_init(g); y = _arb_vec_init(g); w = _arb_vec_init(g); arb_init(f); arb_init(pi); acb_siegel_yinv(Yinv, tau, prec); _acb_vec_get_imag(y, z, g); arb_mat_vector_mul_col(w, Yinv, y, prec); arb_dot(f, NULL, 1, y, 1, w, 1, g, prec); arb_const_pi(pi, prec); arb_mul(f, f, pi, prec); if (!has_t) { res = acb_theta_ql_roots_1(rts, z, d, f, tau, nb_steps, guard); } else { for (k = 1; (k < 3) && res; k++) { _acb_vec_scalar_mul_ui(x, t, g, k, prec); _acb_vec_add(x, x, z, g, prec); res = acb_theta_ql_roots_1(rts + (k - 1) * nb_steps * n, x, d, f, tau, nb_steps, guard); } } arb_mat_clear(Yinv); _acb_vec_clear(x, g); _arb_vec_clear(y, g); _arb_vec_clear(w, g); arb_clear(f); arb_clear(pi); return res; } static int acb_theta_ql_roots(acb_ptr rts, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong nb_steps, slong guard, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; int hasz = !_acb_vec_is_zero(z, g); int hast = !_acb_vec_is_zero(t, g); slong nbt = (hast ? 2 : 1); acb_ptr x; int res; x = _acb_vec_init(g); res = acb_theta_ql_roots_3(rts, t, x, d0, tau, nb_steps, guard, prec); if (res && hasz) { res = acb_theta_ql_roots_3(rts + nbt * n * nb_steps, t, z, d, tau, nb_steps, guard, prec); } _acb_vec_clear(x, g); return res; } static int acb_theta_ql_a0_start(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const arb_t f, const acb_mat_t tau, slong nb_steps, slong s, slong guard, slong prec, acb_theta_ql_worker_t worker) { slong g = acb_mat_nrows(tau); slong n = 1 << g; int hast = !_acb_vec_is_zero(t, g); int hasz = !_acb_vec_is_zero(z, g); slong nbt = (hast ? 3 : 1); acb_mat_t w; acb_ptr x, u, zero; arb_ptr new_d0, new_d; arb_t c; int res; acb_mat_init(w, g, g); x = _acb_vec_init(g); u = _acb_vec_init(g); zero = _acb_vec_init(g); new_d0 = _arb_vec_init(n); new_d = _arb_vec_init(n); arb_init(c); acb_mat_scalar_mul_2exp_si(w, tau, nb_steps); _acb_vec_scalar_mul_2exp_si(u, t, g, nb_steps); _acb_vec_scalar_mul_2exp_si(x, z, g, nb_steps); _arb_vec_scalar_mul_2exp_si(new_d0, d0, n, nb_steps); _arb_vec_scalar_mul_2exp_si(new_d, d, n, nb_steps); arb_mul_2exp_si(c, f, nb_steps); arb_exp(c, c, prec); if (s > 0) { res = acb_theta_ql_a0_split(th, u, zero, new_d0, w, s, guard, prec, worker); if (res && hasz) { res = acb_theta_ql_a0_split(th + nbt * n, u, x, new_d, w, s, guard, prec, worker); } } else { res = acb_theta_ql_a0_naive(th, u, x, new_d0, new_d, w, guard, prec); } if (hasz) { _acb_vec_scalar_mul_arb(th + nbt * n, th + nbt * n, nbt * n, c, prec); } acb_mat_clear(w); _acb_vec_clear(x, g); _acb_vec_clear(u, g); _acb_vec_clear(zero, g); _arb_vec_clear(new_d0, n); _arb_vec_clear(new_d, n); arb_clear(c); return res; } static void acb_theta_ql_step_1(acb_ptr res, acb_srcptr th0, acb_srcptr th, acb_srcptr rts, arb_srcptr d0, arb_srcptr d, slong g, slong prec) { slong n = 1 << g; acb_theta_agm_mul_tight(res, th0, th, d0, d, g, prec); _acb_vec_scalar_mul_2exp_si(res, res, n, g); acb_theta_agm_sqrt(res, res, rts, n, prec); } static void acb_theta_ql_step_2(acb_ptr res, acb_srcptr th0, acb_srcptr th, acb_srcptr rts, arb_srcptr d0, arb_srcptr d, slong g, slong prec) { slong n = 1 << g; acb_ptr aux; aux = _acb_vec_init(3 * n); acb_theta_agm_mul_tight(aux + n, th0, th + n, d0, d, g, prec); acb_theta_agm_mul_tight(aux + 2 * n, th0, th + 2 * n, d0, d, g, prec); _acb_vec_scalar_mul_2exp_si(aux + n, aux + n, 2 * n, g); acb_theta_agm_sqrt(aux + n, aux + n, rts, 2 * n, prec); _acb_vec_set(res, aux, 3 * n); _acb_vec_clear(aux, 3 * n); } static void acb_theta_ql_step_3(acb_ptr res, acb_srcptr th0, acb_srcptr th, acb_srcptr rts, arb_srcptr d0, arb_srcptr d, slong g, slong prec) { slong n = 1 << g; acb_ptr aux; ulong a; aux = _acb_vec_init(3 * n); acb_theta_agm_mul_tight(aux + n, th0, th + n, d0, d, g, prec); acb_theta_agm_mul_tight(aux + 2 * n, th0, th + 2 * n, d0, d, g, prec); _acb_vec_scalar_mul_2exp_si(aux + n, aux + n, 2 * n, g); acb_theta_agm_sqrt(aux + n, aux + n, rts, 2 * n, prec); acb_theta_agm_mul_tight(aux, th0 + n, th + n, d0, d, g, prec); _acb_vec_scalar_mul_2exp_si(aux, aux, n, g); for (a = 0; a < n; a++) { acb_div(&aux[a], &aux[a], &aux[2 * n + a], prec); } _acb_vec_set(res, aux, 3 * n); _acb_vec_clear(aux, 3 * n); } static void acb_theta_ql_a0_step(acb_ptr th, acb_srcptr all_rts, arb_srcptr d0, arb_srcptr d, slong k, slong nb_steps, int hast, int hasz, slong g, slong prec) { slong n = 1 << g; arb_ptr new_d, new_d0; acb_ptr next; acb_ptr rts; slong nbt = (hast ? 3 : 1); slong nbr = (hast ? 2 : 1); slong nbz = (hasz ? 2 : 1); slong j; new_d = _arb_vec_init(n); new_d0 = _arb_vec_init(n); next = _acb_vec_init(nbz * nbt * n); rts = _acb_vec_init(nbr * nbz * n); _arb_vec_scalar_mul_2exp_si(new_d, d, n, k + 1); _arb_vec_scalar_mul_2exp_si(new_d0, d0, n, k + 1); for (j = 0; j < nbz * nbr; j++) { _acb_vec_set(rts + j * n, all_rts + j * nb_steps * n + k * n, n); } if (hast) { acb_theta_ql_step_3(next, th, th, rts, new_d0, new_d0, g, prec); if (hasz && (k == 0)) { acb_theta_ql_step_3(next + nbt * n, th, th + nbt * n, rts + nbr * n, new_d0, new_d, g, prec); } else if (hasz) { acb_theta_ql_step_2(next + nbt * n, th, th + nbt * n, rts + nbr * n, new_d0, new_d, g, prec); } } else { acb_theta_ql_step_1(next, th, th, rts, new_d0, new_d0, g, prec); if (hasz) { acb_theta_ql_step_1(next + nbt * n, th, th + nbt * n, rts + nbr * n, new_d0, new_d, g, prec); } } _acb_vec_set(th, next, nbz * nbt * n); _arb_vec_clear(new_d, n); _arb_vec_clear(new_d0, n); _acb_vec_clear(next, nbz * nbt * n); _acb_vec_clear(rts, nbr * nbz * n); } int acb_theta_ql_a0_steps(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong nb_steps, slong s, slong guard, slong prec, acb_theta_ql_worker_t worker) { slong g = acb_mat_nrows(tau); slong n = 1 << g; int hast = !_acb_vec_is_zero(t, g); int hasz = !_acb_vec_is_zero(z, g); slong nbt = (hast ? 3 : 1); slong nbr = (hast ? 2 : 1); slong nbz = (hasz ? 2 : 1); arb_mat_t Yinv; acb_ptr x, rts; arb_ptr y, w; arb_t f, c; slong k; int res = 1; arb_mat_init(Yinv, g, g); x = _acb_vec_init(g); y = _arb_vec_init(g); w = _arb_vec_init(g); rts = _acb_vec_init(nbz * nbr * n * nb_steps); arb_init(f); arb_init(c); acb_siegel_yinv(Yinv, tau, prec); _acb_vec_get_imag(y, z, g); arb_mat_vector_mul_col(w, Yinv, y, prec); arb_dot(f, NULL, 1, y, 1, w, 1, g, prec); arb_const_pi(c, prec); arb_mul(f, f, c, prec); res = acb_theta_ql_roots(rts, t, z, d0, d, tau, nb_steps, guard, prec); if (res) { res = acb_theta_ql_a0_start(th, t, z, d0, d, f, tau, nb_steps, s, guard, prec, worker); } if (res) { for (k = nb_steps - 1; k >= 0; k--) { acb_theta_ql_a0_step(th, rts, d0, d, k, nb_steps, hast, hasz, g, prec); } } if (res && hasz) { arb_neg(f, f); arb_exp(c, f, prec); _acb_vec_scalar_mul_arb(th + nbt * n, th + nbt * n, n * nbt, c, prec); } arb_mat_clear(Yinv); _acb_vec_clear(x, g); _arb_vec_clear(y, g); _arb_vec_clear(w, g); _acb_vec_clear(rts, nbz * nbr * n * nb_steps); arb_clear(f); arb_clear(c); return res; } flint-3.1.3/src/acb_theta/ql_all.c000066400000000000000000000245231461254215100167520ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" #define ACB_THETA_QL_TRY 100 static void acb_theta_ql_dupl(acb_ptr th2, acb_srcptr th0, acb_srcptr th, arb_srcptr d0, arb_srcptr d, slong g, slong prec) { slong n = 1 << g; acb_ptr v; ulong a, b; v = _acb_vec_init(n); for (a = 0; a < n; a++) { _acb_vec_set(v, th, n); for (b = 0; b < n; b++) { if (acb_theta_char_dot(a, b, g) % 2 == 1) { acb_neg(&v[b], &v[b]); } } acb_theta_agm_mul_tight(v, th0, v, d0, d, g, prec); for (b = 0; b < n; b++) { acb_set(&th2[b * n + a], &v[b]); } } _acb_vec_scalar_mul_2exp_si(th2, th2, n * n, g); _acb_vec_clear(v, n); } static int acb_theta_ql_all_with_t(acb_ptr th, acb_srcptr t, acb_srcptr z, arb_srcptr d0, arb_srcptr d, const acb_mat_t tau, slong guard, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; int hasz = !_acb_vec_is_zero(z, g); int hast = !_acb_vec_is_zero(t, g); slong nbz = (hasz ? 2 : 1); slong nbt = (hast ? 3 : 1); acb_mat_t new_tau; acb_ptr rts, new_z, th_a0, aux; arb_ptr new_d0, new_d; slong hprec; slong k, a; int res = 1; acb_mat_init(new_tau, g, g); rts = _acb_vec_init(n * n); new_z = _acb_vec_init(g); th_a0 = _acb_vec_init(n * nbz * nbt); aux = _acb_vec_init(n * n); new_d0 = _arb_vec_init(n); new_d = _arb_vec_init(n); /* Collect roots: we only need theta_{a,b}(z + t, tau) */ _acb_vec_add(new_z, z, t, g, prec); for (a = 0; (a < n) && res; a++) { hprec = guard + acb_theta_dist_addprec(&d[a]); acb_theta_naive_fixed_a(rts + a * n, a, new_z, 1, tau, hprec); for (k = 0; (k < n) && res; k++) { /* Ignore theta constants if z = t = 0 */ if (acb_contains_zero(&rts[a * n + k]) && (hasz || hast || acb_theta_char_is_even(a * n + k, g))) { res = 0; } } } /* Get ql_a0 at 2z, t, 2tau */ if (res) { acb_mat_scalar_mul_2exp_si(new_tau, tau, 1); _acb_vec_scalar_mul_2exp_si(new_z, z, g, 1); _arb_vec_scalar_mul_2exp_si(new_d, d, n, 1); _arb_vec_scalar_mul_2exp_si(new_d0, d0, n, 1); res = acb_theta_ql_a0(th_a0, t, new_z, new_d0, new_d, new_tau, guard, prec); } if (res) { /* Get theta_{a,b}(z + t, tau) from square roots */ acb_theta_ql_dupl(th, th_a0, th_a0 + (nbz * nbt - 1) * n, new_d0, new_d, g, prec); acb_theta_agm_sqrt(th, th, rts, n * n, prec); if (hast) { /* Get theta_{a,b}(z, tau) from division */ acb_theta_ql_dupl(aux, th_a0 + n, th_a0 + (3 * nbz - 2) * n, new_d0, new_d, g, prec); for (k = 0; k < n * n; k++) { acb_div(&th[k], &aux[k], &th[k], prec); } } } /* Set odd theta constants to zero */ if (!hasz) { for (a = 0; a < n * n; a++) { if (!acb_theta_char_is_even(a, g)) { acb_zero(&th[a]); } } } acb_mat_clear(new_tau); _acb_vec_clear(rts, n * n); _acb_vec_clear(new_z, g); _acb_vec_clear(th_a0, n * nbz * nbt); _acb_vec_clear(aux, n * n); _arb_vec_clear(new_d0, n); _arb_vec_clear(new_d, n); return res; } static void acb_theta_ql_all_red(acb_ptr th, acb_srcptr z, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; slong lp = ACB_THETA_LOW_PREC; slong guard = ACB_THETA_LOW_PREC; slong nb_der = acb_theta_jet_nb(2, g); flint_rand_t state; arb_ptr d, d0; acb_mat_t tau_mid; acb_ptr t, z_mid, dth; arb_t err; arf_t e; slong j, k; int hasz = !_acb_vec_is_zero(z, g); int res; flint_randinit(state); d = _arb_vec_init(n); d0 = _arb_vec_init(n); acb_mat_init(tau_mid, g, g); t = _acb_vec_init(g); z_mid = _acb_vec_init(g); dth = _acb_vec_init(n * n * nb_der); arb_init(err); arf_init(e); acb_theta_dist_a0(d, z, tau, lp); acb_theta_dist_a0(d0, t, tau, lp); /* Get midpoints; ql_all_with_t is expected to lose guard + g bits of precision */ arf_one(e); arf_mul_2exp_si(e, e, -prec - guard - g); for (j = 0; j < g; j++) { for (k = j; k < g; k++) { acb_get_mid(acb_mat_entry(tau_mid, j, k), acb_mat_entry(tau, j, k)); acb_add_error_arf(acb_mat_entry(tau_mid, j, k), e); acb_set(acb_mat_entry(tau_mid, k, j), acb_mat_entry(tau_mid, j, k)); } acb_get_mid(&z_mid[j], &z[j]); if (hasz) { acb_add_error_arf(&z_mid[j], e); } } res = acb_theta_ql_all_with_t(th, t, z_mid, d0, d, tau_mid, guard, prec + guard + g); for (j = 0; (j < ACB_THETA_QL_TRY) && !res; j++) { for (k = 0; k < g; k++) { arb_urandom(acb_realref(&t[k]), state, prec + guard + g); } _acb_vec_scalar_mul_2exp_si(t, t, g, 1); res = acb_theta_ql_all_with_t(th, t, z_mid, d0, d, tau_mid, guard, prec + guard + g); guard += ACB_THETA_LOW_PREC; } if (!res) { _acb_vec_indeterminate(th, n * n); } else { acb_theta_jet_naive_all(dth, z, tau, 2, ACB_THETA_LOW_PREC); for (j = 0; j < n * n; j++) { acb_theta_jet_error_bounds(err, z, tau, dth + j * nb_der, 0, ACB_THETA_LOW_PREC); acb_add_error_arb(&th[j], err); } } flint_randclear(state); _arb_vec_clear(d, n); _arb_vec_clear(d0, n); acb_mat_clear(tau_mid); _acb_vec_clear(t, g); _acb_vec_clear(z_mid, g); _acb_vec_clear(dth, n * n * nb_der); arb_clear(err); arf_clear(e); } static void acb_theta_ql_all_sqr_red(acb_ptr th2, acb_srcptr z, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); slong n = 1 << g; slong lp = ACB_THETA_LOW_PREC; slong guard = ACB_THETA_LOW_PREC; int hasz = !_acb_vec_is_zero(z, g); slong nbz = (hasz ? 2 : 1); slong nbt = 1; flint_rand_t state; acb_mat_t w; arb_ptr d, d0; acb_ptr t, x, th; slong j, k; int res; flint_randinit(state); acb_mat_init(w, g, g); x = _acb_vec_init(g); d = _arb_vec_init(n); d0 = _arb_vec_init(n); t = _acb_vec_init(g); th = _acb_vec_init(n * 3 * nbz); acb_mat_scalar_mul_2exp_si(w, tau, 1); _acb_vec_scalar_mul_2exp_si(x, z, g, 1); acb_theta_dist_a0(d, x, w, lp); acb_theta_dist_a0(d0, t, w, lp); res = acb_theta_ql_a0(th, t, x, d0, d, w, guard, prec); for (j = 0; (j < ACB_THETA_QL_TRY) && !res; j++) { nbt = 3; for (k = 0; k < g; k++) { arb_urandom(acb_realref(&t[k]), state, prec); } _acb_vec_scalar_mul_2exp_si(t, t, g, 1); res = acb_theta_ql_a0(th, t, x, d0, d, w, guard, prec); guard += ACB_THETA_LOW_PREC; } if (!res) { _acb_vec_indeterminate(th2, n * n); } else if (hasz) { acb_theta_ql_dupl(th2, th, th + nbt * n, d0, d, g, prec); } else { acb_theta_ql_dupl(th2, th, th, d0, d0, g, prec); } flint_randclear(state); acb_mat_clear(w); _acb_vec_clear(x, g); _arb_vec_clear(d, n); _arb_vec_clear(d0, n); _acb_vec_clear(t, g); _acb_vec_clear(th, n * 3 * nbz); } void acb_theta_ql_all(acb_ptr th, acb_srcptr z, const acb_mat_t tau, int sqr, slong prec) { slong g = acb_mat_nrows(tau); slong n2 = 1 << (2 * g); acb_mat_t tau0; acb_ptr new_z, aux; acb_t c; arb_t u, v; arf_t b; slong s; slong * n1; ulong ab, a0, a1, b0, b1, fixed_a1; acb_init(c); arb_init(u); arb_init(v); arf_init(b); new_z = _acb_vec_init(g); n1 = flint_malloc(g * sizeof(slong)); s = acb_theta_ql_reduce(new_z, c, u, n1, z, tau, prec); if (sqr) { acb_sqr(c, c, prec); arb_sqr(u, u, prec); } if (s == -1) { _acb_vec_zero(th, n2); for (ab = 0; ab < n2; ab++) { acb_add_error_arb(&th[ab], u); } } else { fixed_a1 = acb_theta_char_get_a(n1, g - s); acb_mat_window_init(tau0, tau, 0, 0, s, s); aux = _acb_vec_init(1 << (2 * s)); if (acb_is_finite(c)) { if (s > 0 && !sqr) { acb_theta_ql_all_red(aux, new_z, tau0, prec); } else if (s > 0) { acb_theta_ql_all_sqr_red(aux, new_z, tau0, prec); } else { acb_one(&aux[0]); } _acb_vec_scalar_mul(aux, aux, 1 << (2 * s), c, prec); } else { _acb_vec_indeterminate(aux, 1 << (2 * s)); } for (ab = 0; ab < n2; ab++) { /* Write ab as a0 a1 b0 b1 */ a0 = ab >> (g + (g - s)); a1 = (ab >> g) % (1 << (g - s)); b0 = (ab >> (g - s)) % (1 << s); b1 = ab % (1 << (g - s)); if (a1 != fixed_a1) { acb_zero(&th[ab]); } else { acb_mul_i_pow_si(&th[ab], &aux[(a0 << s) + b0], (sqr ? 2 : 1) * acb_theta_char_dot_slong(b1, n1, g - s)); if (sqr) { acb_abs(v, &th[ab], prec); arb_mul(v, v, u, prec); arb_get_ubound_arf(b, v, prec); arb_set_arf(v, b); arb_sqrt(v, v, prec); arb_mul_2exp_si(v, v, 1); acb_add_error_arb(&th[ab], v); } } acb_add_error_arb(&th[ab], u); } acb_mat_window_clear(tau0); _acb_vec_clear(aux, 1 << (2 * s)); } _acb_vec_clear(new_z, g); acb_clear(c); arb_clear(u); arb_clear(v); arf_clear(b); flint_free(n1); } flint-3.1.3/src/acb_theta/ql_reduce.c000066400000000000000000000065051461254215100174510ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" slong acb_theta_ql_reduce(acb_ptr new_z, acb_t c, arb_t u, slong * n1, acb_srcptr z, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); acb_theta_eld_t E; arb_mat_t C, W, C1; acb_mat_t tau0, tau1, x; acb_ptr t, w; arb_ptr v, a; acb_t f; arf_t R2, eps; slong s, k; int r = 1; arb_mat_init(C, g, g); v = _arb_vec_init(g); a = _arb_vec_init(g); acb_init(f); arf_init(R2); arf_init(eps); acb_siegel_cho(C, tau, prec); acb_theta_naive_radius(R2, eps, C, 0, prec); acb_theta_naive_reduce(v, new_z, a, c, u, z, 1, tau, prec); arb_mul_arf(u, u, eps, prec); for (s = g; (s >= 1) && r; ) { s--; acb_theta_eld_init(E, g - s, g - s); arb_mat_window_init(W, C, s, s, g, g); arb_mat_init(C1, g - s, g - s); arb_mat_set(C1, W); arb_mat_scalar_mul_2exp_si(C1, C1, -1); r = acb_theta_eld_set(E, C1, R2, v + s); r = r && (acb_theta_eld_nb_pts(E) <= 1); if (r && (acb_theta_eld_nb_pts(E) == 0)) { s = -2; } acb_theta_eld_clear(E); arb_mat_window_clear(W); arb_mat_clear(C1); } s++; if ((s >= 0) && (s < g)) { /* We know E has exactly one point */ acb_theta_eld_init(E, g - s, g - s); arb_mat_window_init(W, C, s, s, g, g); arb_mat_init(C1, g - s, g - s); acb_mat_window_init(tau0, tau, 0, 0, s, s); acb_mat_window_init(tau1, tau, s, s, g, g); acb_mat_window_init(x, tau, 0, s, s, g); t = _acb_vec_init(g); w = _acb_vec_init(g); arb_mat_set(C1, W); arb_mat_scalar_mul_2exp_si(C1, C1, -1); acb_theta_eld_set(E, C1, R2, v + s); acb_theta_eld_points(n1, E); /* Update new_z and c */ for (k = 0; k < g - s; k++) { acb_set_si(&t[k], n1[k]); } _acb_vec_scalar_mul_2exp_si(t, t, g - s, -1); acb_mat_vector_mul_col(w, x, t, prec); _acb_vec_add(new_z, new_z, w, s, prec); acb_mat_vector_mul_col(w, tau1, t, prec); _acb_vec_scalar_mul_2exp_si(w, w, g - s, -1); _acb_vec_add(w, w, new_z + s, g - s, prec); _acb_vec_scalar_mul_2exp_si(w, w, g - s, 1); acb_dot(f, NULL, 0, t, 1, w, 1, g - s, prec); acb_exp_pi_i(f, f, prec); acb_mul(c, c, f, prec); acb_theta_eld_clear(E); arb_mat_window_clear(W); arb_mat_clear(C1); acb_mat_window_clear(tau0); acb_mat_window_clear(tau1); acb_mat_window_clear(x); _acb_vec_clear(t, g); _acb_vec_clear(w, g); } if (!arb_mat_is_finite(C)) /* early abort in ql_all */ { acb_indeterminate(c); arb_pos_inf(u); s = -1; } arb_mat_clear(C); _arb_vec_clear(v, g); _arb_vec_clear(a, g); acb_clear(f); arf_clear(R2); arf_clear(eps); return s; } flint-3.1.3/src/acb_theta/siegel_cho.c000066400000000000000000000014501461254215100176010ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_cho(arb_mat_t C, const acb_mat_t tau, slong prec) { arb_t pi; int res; arb_init(pi); arb_const_pi(pi, prec); acb_mat_get_imag(C, tau); arb_mat_scalar_mul_arb(C, C, pi, prec); res = arb_mat_cho(C, C, prec); arb_mat_transpose(C, C); if (!res) { arb_mat_indeterminate(C); } arb_clear(pi); } flint-3.1.3/src/acb_theta/siegel_cocycle.c000066400000000000000000000017051461254215100204540ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_cocycle(acb_mat_t c, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) { slong g = sp2gz_dim(mat); fmpz_mat_t gamma, delta; acb_mat_t r; fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); fmpz_mat_window_init(delta, mat, g, g, 2 * g, 2 * g); acb_mat_init(r, g, g); acb_mat_set_fmpz_mat(c, gamma); acb_mat_set_fmpz_mat(r, delta); acb_mat_mul(c, c, tau, prec); acb_mat_add(c, c, r, prec); fmpz_mat_window_clear(gamma); fmpz_mat_window_clear(delta); acb_mat_clear(r); } flint-3.1.3/src/acb_theta/siegel_is_reduced.c000066400000000000000000000034701461254215100211420ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" int acb_siegel_is_reduced(const acb_mat_t tau, slong tol_exp, slong prec) { slong g = acb_mat_nrows(tau); fmpz_mat_t mat; acb_mat_t c; arb_mat_t im; acb_t det; arb_t abs, t, u; slong j, k; int res = 1; fmpz_mat_init(mat, 2 * g, 2 * g); acb_mat_init(c, g, g); arb_mat_init(im, g, g); acb_init(det); arb_init(abs); arb_init(t); arb_init(u); arb_one(u); arb_mul_2exp_si(u, u, tol_exp); arb_one(t); arb_mul_2exp_si(t, t, -1); arb_add(t, t, u, prec); for (j = 0; (j < g) && res; j++) { for (k = 0; (k < g) && res; k++) { arb_abs(abs, acb_realref(acb_mat_entry(tau, j, k))); if (!arb_lt(abs, t)) { res = 0; } } } if (res) { acb_mat_get_imag(im, tau); res = arb_mat_spd_is_lll_reduced(im, tol_exp, prec); } arb_one(t); arb_sub(t, t, u, prec); for (k = 0; k < sp2gz_nb_fundamental(g); k++) { sp2gz_fundamental(mat, k); acb_siegel_cocycle(c, mat, tau, prec); acb_mat_det(det, c, prec); acb_abs(abs, det, prec); if (!arb_gt(abs, t)) { res = 0; } } fmpz_mat_clear(mat); acb_mat_clear(c); arb_mat_clear(im); acb_clear(det); arb_clear(abs); arb_clear(t); arb_clear(u); return res; } flint-3.1.3/src/acb_theta/siegel_randtest.c000066400000000000000000000020341461254215100206530ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_randtest(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits) { slong g = arb_mat_nrows(tau); arb_mat_t re, im; slong k, j; arb_mat_init(re, g, g); arb_mat_init(im, g, g); for (k = 0; k < g; k++) { for (j = k; j < g; j++) { arb_randtest_precise(arb_mat_entry(re, k, j), state, prec, mag_bits); arb_set(arb_mat_entry(re, j, k), arb_mat_entry(re, k, j)); } } arb_mat_randtest_spd(im, state, prec, mag_bits); acb_mat_set_real_imag(tau, re, im); arb_mat_clear(re); arb_mat_clear(im); } flint-3.1.3/src/acb_theta/siegel_randtest_reduced.c000066400000000000000000000026711461254215100223550ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_randtest_reduced(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits) { slong g = acb_mat_nrows(tau); slong s = n_randint(state, g + 1); slong n = n_randint(state, FLINT_MAX(1, mag_bits)); fmpz_mat_t mat; arb_t test; int r = 0; slong j, k; fmpz_mat_init(mat, 2 * g, 2 * g); arb_init(test); for (k = 0; (k < 10) && !r; k++) { acb_siegel_randtest(tau, state, prec, 2); acb_siegel_reduce(mat, tau, prec); acb_siegel_transform(tau, mat, tau, prec); r = acb_siegel_is_reduced(tau, -1, prec); } if (!r) { acb_mat_onei(tau); } for (j = s; j < g; j++) { for (k = 0; k < g; k++) { arb_mul_2exp_si(acb_imagref(acb_mat_entry(tau, j, k)), acb_imagref(acb_mat_entry(tau, j, k)), n); arb_mul_2exp_si(acb_imagref(acb_mat_entry(tau, k, j)), acb_imagref(acb_mat_entry(tau, k, j)), n); } } fmpz_mat_clear(mat); arb_clear(test); } flint-3.1.3/src/acb_theta/siegel_randtest_vec.c000066400000000000000000000021041461254215100215060ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_siegel_randtest_vec(acb_ptr z, flint_rand_t state, slong g, slong prec) { slong mag_bits = n_randint(state, 4); slong k; for (k = 0; k < g; k++) { switch (n_randint(state, 10)) { case 0: acb_randtest_param(&z[k], state, prec, mag_bits); break; case 1: acb_randtest(&z[k], state, prec, mag_bits); break; case 2: acb_randtest_precise(&z[k], state, prec, mag_bits); break; case 3: acb_randtest(&z[k], state, prec, 20); break; default: acb_urandom(&z[k], state, prec); } } } flint-3.1.3/src/acb_theta/siegel_reduce.c000066400000000000000000000120671461254215100203050ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" #define ACB_SIEGEL_REDUCE_MAG_BOUND 1000000 static void fmpz_mat_bound_inf_norm(mag_t b, const fmpz_mat_t mat) { slong r = acb_mat_nrows(mat); slong c = acb_mat_ncols(mat); arb_mat_t m; arb_mat_init(m, r, c); arb_mat_set_fmpz_mat(m, mat); arb_mat_bound_inf_norm(b, m); arb_mat_clear(m); } /* Todo: better choice of precision here? */ static slong acb_siegel_reduce_real_lowprec(const mag_t ntau, const mag_t nmat, slong g, slong prec) { slong lp = ACB_THETA_LOW_PREC; slong res; mag_t b; mag_init(b); mag_mul(b, ntau, nmat); res = FLINT_MIN(prec, g * (lp + FLINT_MAX(0, mag_get_d_log2_approx(b)))); mag_clear(b); return res; } static void acb_siegel_reduce_real(fmpz_mat_t mat, const acb_mat_t tau) { slong g = acb_mat_nrows(tau); slong j, k; fmpz_t c; fmpz_init(c); fmpz_mat_one(mat); for (j = 0; j < g; j++) { for (k = j; k < g; k++) { /* this must succeed given the bounds on ndet and ntau */ arf_get_fmpz(c, arb_midref(acb_realref(acb_mat_entry(tau, j, k))), ARF_RND_NEAR); fmpz_neg(fmpz_mat_entry(mat, j, k + g), c); } for (k = 0; k < j; k++) { fmpz_set(fmpz_mat_entry(mat, j, k + g), fmpz_mat_entry(mat, k, j + g)); } } fmpz_clear(c); } static slong acb_siegel_reduce_imag_lowprec(const mag_t ntau, const mag_t ndet, const mag_t nmat, slong g, slong prec) { slong lp = ACB_THETA_LOW_PREC; slong res; mag_t b; mag_init(b); mag_mul(b, ntau, nmat); mag_mul(b, b, b); mag_mul(b, b, ntau); mag_div(b, b, ndet); res = FLINT_MIN(prec, g * (lp + FLINT_MAX(0, mag_get_d_log2_approx(b)))); mag_clear(b); return res; } static void acb_siegel_reduce_imag(fmpz_mat_t mat, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); arb_mat_t im; fmpz_mat_t U; arb_mat_init(im, g, g); fmpz_mat_init(U, g, g); acb_mat_get_imag(im, tau); arb_mat_spd_lll_reduce(U, im, prec); sp2gz_block_diag(mat, U); arb_mat_clear(im); fmpz_mat_clear(U); } void acb_siegel_reduce(fmpz_mat_t mat, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); slong lp; fmpz_mat_t m; acb_mat_t w, c; arb_mat_t im; acb_t det; arb_t abs; arb_t t; mag_t ntau, nmat, ndet; int stop = 0; slong j, j0; fmpz_mat_init(m, 2 * g, 2 * g); acb_mat_init(w, g, g); acb_mat_init(c, g, g); arb_mat_init(im, g, g); acb_init(det); arb_init(abs); arb_init(t); mag_init(ntau); mag_init(nmat); mag_init(ndet); acb_mat_bound_inf_norm(ntau, tau); acb_mat_get_imag(im, tau); arb_mat_det(abs, im, prec); arb_get_mag_lower(ndet, abs); if (mag_cmp_2exp_si(ntau, ACB_SIEGEL_REDUCE_MAG_BOUND) >= 0 || mag_cmp_2exp_si(ndet, -ACB_SIEGEL_REDUCE_MAG_BOUND) <= 0) { stop = 1; } fmpz_mat_one(mat); while (!stop) { /* Choose precision, reduce imaginary part */ fmpz_mat_bound_inf_norm(nmat, mat); lp = acb_siegel_reduce_imag_lowprec(ntau, ndet, nmat, g, prec); acb_siegel_transform(w, mat, tau, lp); acb_siegel_reduce_imag(m, w, lp); fmpz_mat_mul(mat, m, mat); /* Choose precision, check transform is reduced, reduce real part */ fmpz_mat_bound_inf_norm(nmat, mat); lp = acb_siegel_reduce_real_lowprec(ntau, nmat, g, prec); acb_siegel_transform(w, m, w, lp); acb_mat_get_imag(im, w); if (!arb_mat_spd_is_lll_reduced(im, -10, lp)) { stop = 1; break; } acb_siegel_reduce_real(m, w); fmpz_mat_mul(mat, m, mat); /* Loop over fundamental matrices (keeping same precision) */ acb_siegel_transform(w, m, w, lp); j0 = -1; arb_one(t); for (j = 0; j < sp2gz_nb_fundamental(g); j++) { sp2gz_fundamental(m, j); acb_siegel_cocycle(c, m, w, lp); acb_mat_det(det, c, lp); acb_abs(abs, det, lp); if (arb_lt(abs, t)) { j0 = j; arb_set(t, abs); } } /* Apply fundamental matrix if found */ if (j0 != -1) { sp2gz_fundamental(m, j0); fmpz_mat_mul(mat, m, mat); } else { stop = 1; } } fmpz_mat_clear(m); acb_mat_clear(w); acb_mat_clear(c); arb_mat_clear(im); acb_clear(det); arb_clear(abs); arb_clear(t); mag_clear(ntau); mag_clear(nmat); mag_clear(ndet); } flint-3.1.3/src/acb_theta/siegel_transform.c000066400000000000000000000013531461254215100210450ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_transform(acb_mat_t w, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) { slong g = sp2gz_dim(mat); acb_mat_t c, cinv; acb_mat_init(c, g, g); acb_mat_init(cinv, g, g); acb_siegel_transform_cocycle_inv(w, c, cinv, mat, tau, prec); acb_mat_clear(c); acb_mat_clear(cinv); } flint-3.1.3/src/acb_theta/siegel_transform_cocycle_inv.c000066400000000000000000000023641461254215100234250ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_transform_cocycle_inv(acb_mat_t w, acb_mat_t c, acb_mat_t cinv, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) { slong g = sp2gz_dim(mat); fmpz_mat_t alpha; fmpz_mat_t beta; acb_mat_t x, num; int r; fmpz_mat_window_init(alpha, mat, 0, 0, g, g); fmpz_mat_window_init(beta, mat, 0, g, g, 2 * g); acb_mat_init(x, g, g); acb_mat_init(num, g, g); acb_mat_set_fmpz_mat(x, alpha); acb_mat_mul(num, x, tau, prec); acb_mat_set_fmpz_mat(x, beta); acb_mat_add(num, num, x, prec); acb_siegel_cocycle(c, mat, tau, prec); r = acb_mat_inv(cinv, c, prec); if (!r) { acb_mat_indeterminate(cinv); } acb_mat_mul(w, num, cinv, prec); fmpz_mat_window_clear(alpha); fmpz_mat_window_clear(beta); acb_mat_clear(x); acb_mat_clear(num); } flint-3.1.3/src/acb_theta/siegel_transform_z.c000066400000000000000000000015331461254215100213760ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_transform_z(acb_ptr r, acb_mat_t w, const fmpz_mat_t mat, acb_srcptr z, const acb_mat_t tau, slong prec) { slong g = sp2gz_dim(mat); acb_mat_t c, cinv; acb_mat_init(c, g, g); acb_mat_init(cinv, g, g); acb_siegel_transform_cocycle_inv(w, c, cinv, mat, tau, prec); acb_mat_transpose(cinv, cinv); acb_mat_vector_mul_col(r, cinv, z, prec); acb_mat_clear(c); acb_mat_clear(cinv); } flint-3.1.3/src/acb_theta/siegel_yinv.c000066400000000000000000000012351461254215100200160ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" void acb_siegel_yinv(arb_mat_t Yinv, const acb_mat_t tau, slong prec) { int res; acb_mat_get_imag(Yinv, tau); res = arb_mat_inv(Yinv, Yinv, prec); if (!res) { arb_mat_indeterminate(Yinv); } } flint-3.1.3/src/acb_theta/sp2gz_block_diag.c000066400000000000000000000016111461254215100207020ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" void sp2gz_block_diag(fmpz_mat_t mat, const fmpz_mat_t U) { slong g = sp2gz_dim(mat); fmpz_mat_t D, zero; fmpz_t den; fmpz_mat_init(D, g, g); fmpz_mat_init(zero, g, g); fmpz_init(den); fmpz_mat_inv(D, den, U); fmpz_mat_transpose(D, D); if (!fmpz_is_one(den)) { fmpz_neg(den, den); fmpz_mat_neg(D, D); } sp2gz_set_blocks(mat, U, zero, zero, D); fmpz_mat_clear(D); fmpz_mat_clear(zero); fmpz_clear(den); } flint-3.1.3/src/acb_theta/sp2gz_decompose.c000066400000000000000000000253701461254215100206120ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" /* todo: move out? */ static int fmpz_mat_is_diagonal(const fmpz_mat_t A) { slong r = fmpz_mat_nrows(A); slong c = fmpz_mat_ncols(A); slong j, k; for (j = 0; j < r; j++) { for (k = 0; k < c; k++) { if (j != k && !fmpz_is_zero(fmpz_mat_entry(A, j, k))) { return 0; } } } return 1; } /* todo: move out? Adapt fmpz_mat_snf algorithms to also output transform? */ /* Compute Smith normal form of A and invertible U, V s.t. S = UAV assuming A is square */ static void fmpz_mat_snf_transform(fmpz_mat_t S, fmpz_mat_t U, fmpz_mat_t V, const fmpz_mat_t A) { slong g = fmpz_mat_nrows(A); fmpz_mat_t X, M; fmpz_t d, u, v, p, q; slong j, k; fmpz_mat_init(X, g, g); fmpz_mat_init(M, g, g); fmpz_init(d); fmpz_init(u); fmpz_init(v); fmpz_init(p); fmpz_init(q); fmpz_mat_set(X, A); fmpz_mat_one(U); fmpz_mat_one(V); while (!fmpz_mat_is_diagonal(X)) { fmpz_mat_hnf_transform(X, M, X); fmpz_mat_mul(U, M, U); fmpz_mat_transpose(X, X); fmpz_mat_hnf_transform(X, M, X); fmpz_mat_transpose(X, X); fmpz_mat_transpose(M, M); fmpz_mat_mul(V, V, M); } for (j = 0; j < g; j++) { if (fmpz_is_one(fmpz_mat_entry(X, j, j))) { continue; } for (k = j + 1; k < g; k++) { if (fmpz_is_zero(fmpz_mat_entry(X, k, k))) { continue; } fmpz_xgcd_canonical_bezout(d, u, v, fmpz_mat_entry(X, j, j), fmpz_mat_entry(X, k, k)); fmpz_divexact(p, fmpz_mat_entry(X, j, j), d); fmpz_divexact(q, fmpz_mat_entry(X, k, k), d); fmpz_mat_one(M); fmpz_set(fmpz_mat_entry(M, j, k), v); fmpz_set(fmpz_mat_entry(M, k, j), q); fmpz_mul(fmpz_mat_entry(M, k, k), v, q); fmpz_add_si(fmpz_mat_entry(M, k, k), fmpz_mat_entry(M, k, k), -1); fmpz_mat_mul(U, M, U); fmpz_mat_mul(X, M, X); fmpz_mat_one(M); fmpz_set(fmpz_mat_entry(M, j, j), u); fmpz_one(fmpz_mat_entry(M, k, j)); fmpz_neg(fmpz_mat_entry(M, k, k), p); fmpz_mul(fmpz_mat_entry(M, j, k), fmpz_mat_entry(M, k, k), u); fmpz_add_si(fmpz_mat_entry(M, j, k), fmpz_mat_entry(M, j, k), 1); fmpz_mat_mul(V, V, M); fmpz_mat_mul(X, X, M); } } fmpz_mat_set(S, X); fmpz_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(d); fmpz_clear(u); fmpz_clear(v); fmpz_clear(p); fmpz_clear(q); } static fmpz_mat_struct * sp2gz_decompose_g1(slong * nb, const fmpz_mat_t mat) { fmpz_mat_struct * res; res = flint_malloc(1 * sizeof(fmpz_mat_struct)); fmpz_mat_init(res, 2, 2); fmpz_mat_set(res, mat); *nb = 1; return res; } static fmpz_mat_struct * sp2gz_decompose_nonsimplified(slong * nb, const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t gamma, delta, last; fmpz_mat_t u, v, d; fmpz_mat_t cur, left, right, m; fmpz_mat_t w; fmpz_mat_struct * vec; fmpz_mat_struct * rec = NULL; fmpz_mat_struct * res; fmpz_t a; slong nb_rec = 0; slong nb_max; slong nb_vec = 0; slong r, k, j; if (g == 1) { return sp2gz_decompose_g1(nb, mat); } fmpz_mat_init(u, g, g); fmpz_mat_init(v, g, g); fmpz_mat_init(d, g, g); fmpz_mat_init(cur, 2 * g, 2 * g); fmpz_mat_init(left, 2 * g, 2 * g); fmpz_mat_init(right, 2 * g, 2 * g); fmpz_mat_init(m, 2 * g, 2 * g); fmpz_init(a); fmpz_mat_set(cur, mat); fmpz_mat_window_init(gamma, cur, g, 0, 2 * g, g); fmpz_mat_snf_transform(d, u, v, gamma); fmpz_mat_window_clear(gamma); r = fmpz_mat_rank(d); fmpz_mat_transpose(u, u); sp2gz_block_diag(left, u); sp2gz_inv(left, left); sp2gz_block_diag(right, v); fmpz_mat_mul(cur, left, cur); fmpz_mat_mul(cur, cur, right); nb_max = 3 * fmpz_bits(fmpz_mat_entry(d, 0, 0)) + 4; vec = flint_malloc(nb_max * sizeof(fmpz_mat_struct)); for (k = 0; k < nb_max; k++) { fmpz_mat_init(&vec[k], 2 * g, 2 * g); } fmpz_mat_set(&vec[nb_vec], right); nb_vec++; while (r == g) { /* Set u such that delta + gamma*u is reduced, update vec */ fmpz_mat_zero(u); for (j = 0; j < g; j++) { for (k = j; k < g; k++) { fmpz_smod(a, fmpz_mat_entry(cur, g + j, g + k), fmpz_mat_entry(cur, g + j, j)); fmpz_sub(a, a, fmpz_mat_entry(cur, g + j, g + k)); fmpz_divexact(fmpz_mat_entry(u, j, k), a, fmpz_mat_entry(cur, g + j, j)); fmpz_set(fmpz_mat_entry(u, k, j), fmpz_mat_entry(u, j, k)); } } sp2gz_trig(right, u); fmpz_mat_set(&vec[nb_vec], right); fmpz_mat_mul(cur, cur, right); nb_vec++; /* Swap c, d */ sp2gz_j(&vec[nb_vec]); sp2gz_inv(&vec[nb_vec], &vec[nb_vec]); fmpz_mat_mul(cur, cur, &vec[nb_vec]); nb_vec++; /* Recompute SNF */ fmpz_mat_window_init(gamma, cur, g, 0, 2 * g, g); fmpz_mat_snf_transform(d, u, v, gamma); fmpz_mat_window_clear(gamma); r = fmpz_mat_rank(d); fmpz_mat_transpose(u, u); sp2gz_block_diag(m, u); sp2gz_inv(m, m); fmpz_mat_mul(left, m, left); fmpz_mat_mul(cur, m, cur); sp2gz_block_diag(&vec[nb_vec], v); fmpz_mat_mul(cur, cur, &vec[nb_vec]); nb_vec++; } /* Now r < g: make HNF on colums for the bottom of delta and recursive call */ fmpz_mat_init(last, g, g - r); for (k = 0; k < g - r; k++) { for (j = 0; j < g; j++) { fmpz_set(fmpz_mat_entry(last, j, k), fmpz_mat_entry(cur, g + r + k, g + j)); } } fmpz_mat_hnf_transform(last, u, last); for (j = 0; j < g - r; j++) { fmpz_mat_swap_rows(u, NULL, g - 1 - j, g - 1 - j - r); } sp2gz_block_diag(&vec[nb_vec], u); sp2gz_inv(&vec[nb_vec], &vec[nb_vec]); fmpz_mat_mul(cur, cur, &vec[nb_vec]); nb_vec++; if (r > 0) { fmpz_mat_init(w, 2 * r, 2 * r); sp2gz_restrict(w, cur); rec = sp2gz_decompose(&nb_rec, w); sp2gz_embed(right, w); sp2gz_inv(right, right); fmpz_mat_mul(cur, right, cur); fmpz_mat_window_init(delta, cur, g, g, 2 * g, 2 * g); sp2gz_block_diag(&vec[nb_vec], delta); fmpz_mat_transpose(&vec[nb_vec], &vec[nb_vec]); fmpz_mat_mul(cur, cur, &vec[nb_vec]); nb_vec++; fmpz_mat_window_clear(delta); fmpz_mat_clear(w); } sp2gz_inv(&vec[nb_vec], cur); nb_vec++; /* Make final vector */ *nb = 1 + nb_rec + nb_vec; res = flint_malloc(*nb * sizeof(fmpz_mat_struct)); for (k = 0; k < *nb; k++) { fmpz_mat_init(&res[k], 2 * g, 2 * g); } sp2gz_inv(&res[0], left); for (k = 0; k < nb_rec; k++) { sp2gz_embed(&res[1 + k], &rec[k]); } for (k = 0; k < nb_vec; k++) { sp2gz_inv(&res[1 + nb_rec + k], &vec[nb_vec - 1 - k]); } fmpz_mat_clear(u); fmpz_mat_clear(v); fmpz_mat_clear(d); fmpz_mat_clear(cur); fmpz_mat_clear(left); fmpz_mat_clear(right); fmpz_mat_clear(m); fmpz_mat_clear(last); fmpz_clear(a); for (k = 0; k < nb_max; k++) { fmpz_mat_clear(&vec[k]); } flint_free(vec); if (r > 0) { for (k = 0; k < nb_rec; k++) { fmpz_mat_clear(&rec[k]); } flint_free(rec); } return res; } fmpz_mat_struct * sp2gz_decompose(slong * nb, const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_struct * rec; slong nb_rec; fmpz_mat_struct * res; fmpz_mat_t u, beta, delta; slong k, next_k, j; fmpz_mat_init(u, g, g); rec = sp2gz_decompose_nonsimplified(&nb_rec, mat); /* Move block-diagonal matrices to the left of rec as much as possible */ k = 0; while (k < nb_rec) { for (j = k; j < nb_rec; j++) if (!sp2gz_is_block_diag(&rec[j]) && !sp2gz_is_trig(&rec[j]) && !sp2gz_is_j(&rec[j])) break; next_k = j + 1; /* Move all block-diag matrices between k and next_k to the left */ for (j = next_k - 2; j >= k; j--) if (sp2gz_is_block_diag(&rec[j])) break; for (; j >= k + 1; j--) { /* Commutation of rec[j-1] and rec[j] */ if (sp2gz_is_block_diag(&rec[j - 1])) { fmpz_mat_mul(&rec[j - 1], &rec[j - 1], &rec[j]); fmpz_mat_one(&rec[j]); } else if (sp2gz_is_trig(&rec[j - 1])) { fmpz_mat_window_init(beta, &rec[j - 1], 0, g, g, 2 * g); fmpz_mat_window_init(delta, &rec[j], g, g, 2 * g, 2 * g); fmpz_mat_transpose(u, delta); fmpz_mat_mul(u, u, beta); fmpz_mat_mul(u, u, delta); fmpz_mat_set(&rec[j - 1], &rec[j]); sp2gz_trig(&rec[j], u); fmpz_mat_window_clear(beta); fmpz_mat_window_clear(delta); } else if (sp2gz_is_j(&rec[j - 1])) { sp2gz_inv(&rec[j - 1], &rec[j]); fmpz_mat_transpose(&rec[j - 1], &rec[j - 1]); sp2gz_j(&rec[j]); } } k = next_k; } /* Move trigonal matrices to the left of rec as much as possible */ for (k = nb_rec - 1; k >= 1; k--) { if (sp2gz_is_trig(&rec[k]) && sp2gz_is_trig(&rec[k - 1])) { fmpz_mat_mul(&rec[k - 1], &rec[k - 1], &rec[k]); fmpz_mat_one(&rec[k]); } } *nb = 0; for (k = 0; k < nb_rec; k++) { if (!fmpz_mat_is_one(&rec[k])) { (*nb)++; } } res = flint_malloc(*nb * sizeof(fmpz_mat_struct)); for (k = 0; k < *nb; k++) { fmpz_mat_init(&res[k], 2 * g, 2 * g); } k = 0; for (j = 0; j < nb_rec; j++) { if (!fmpz_mat_is_one(&rec[j])) { fmpz_mat_set(&res[k], &rec[j]); k++; } } fmpz_mat_clear(u); for (k = 0; k < nb_rec; k++) { fmpz_mat_clear(&rec[k]); } flint_free(rec); return res; } flint-3.1.3/src/acb_theta/sp2gz_embed.c000066400000000000000000000015241461254215100177030ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" void sp2gz_embed(fmpz_mat_t res, const fmpz_mat_t mat) { slong j, k, u, v; slong g = sp2gz_dim(res); slong g1 = sp2gz_dim(mat); fmpz_mat_one(res); for (j = 0; j < 2 * g1; j++) { for (k = 0; k < 2 * g1; k++) { u = j + (j >= g1 ? g - g1 : 0); v = k + (k >= g1 ? g - g1 : 0); fmpz_set(fmpz_mat_entry(res, u, v), fmpz_mat_entry(mat, j, k)); } } } flint-3.1.3/src/acb_theta/sp2gz_fundamental.c000066400000000000000000000124661461254215100211340ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" static void sp2gz_fundamental_g2(fmpz_mat_t mat, slong j) { slong g = 2; fmpz_mat_t a, b, c, d; fmpz_mat_init(a, g, g); fmpz_mat_init(b, g, g); fmpz_mat_init(c, g, g); fmpz_mat_init(d, g, g); if (j < 15) { fmpz_mat_zero(a); fmpz_mat_one(c); fmpz_mat_neg(b, c); } if (15 <= j && j < 17) { fmpz_mat_one(a); fmpz_mat_neg(b, a); } if (17 <= j && j < 19) { fmpz_mat_zero(b); fmpz_one(fmpz_mat_entry(c, 0, 0)); fmpz_set_si(fmpz_mat_entry(c, 0, 1), -1); fmpz_set_si(fmpz_mat_entry(c, 1, 0), -1); fmpz_one(fmpz_mat_entry(c, 1, 1)); } switch (j) { case 0: fmpz_mat_zero(d); break; case 1: fmpz_one(fmpz_mat_entry(d, 0, 0)); break; case 2: fmpz_set_si(fmpz_mat_entry(d, 0, 0), -1); break; case 3: fmpz_one(fmpz_mat_entry(d, 1, 1)); break; case 4: fmpz_set_si(fmpz_mat_entry(d, 1, 1), -1); break; case 5: fmpz_mat_one(d); break; case 6: fmpz_mat_one(d); fmpz_mat_neg(d, d); break; case 7: fmpz_set_si(fmpz_mat_entry(d, 0, 0), -1); fmpz_one(fmpz_mat_entry(d, 1, 1)); break; case 8: fmpz_one(fmpz_mat_entry(d, 0, 0)); fmpz_set_si(fmpz_mat_entry(d, 1, 1), -1); break; case 9: fmpz_one(fmpz_mat_entry(d, 0, 1)); fmpz_one(fmpz_mat_entry(d, 1, 0)); break; case 10: fmpz_set_si(fmpz_mat_entry(d, 0, 1), -1); fmpz_set_si(fmpz_mat_entry(d, 1, 0), -1); break; case 11: fmpz_one(fmpz_mat_entry(d, 0, 0)); fmpz_one(fmpz_mat_entry(d, 0, 1)); fmpz_one(fmpz_mat_entry(d, 1, 0)); break; case 12: fmpz_set_si(fmpz_mat_entry(d, 0, 0), -1); fmpz_set_si(fmpz_mat_entry(d, 0, 1), -1); fmpz_set_si(fmpz_mat_entry(d, 1, 0), -1); break; case 13: fmpz_one(fmpz_mat_entry(d, 0, 1)); fmpz_one(fmpz_mat_entry(d, 1, 0)); fmpz_one(fmpz_mat_entry(d, 1, 1)); break; case 14: fmpz_set_si(fmpz_mat_entry(d, 0, 1), -1); fmpz_set_si(fmpz_mat_entry(d, 1, 0), -1); fmpz_set_si(fmpz_mat_entry(d, 1, 1), -1); break; case 15: fmpz_one(fmpz_mat_entry(c, 0, 0)); fmpz_one(fmpz_mat_entry(d, 1, 1)); break; case 16: fmpz_one(fmpz_mat_entry(c, 1, 1)); fmpz_one(fmpz_mat_entry(d, 0, 0)); break; case 17: fmpz_mat_one(a); fmpz_mat_one(d); break; default: //case 18: fmpz_mat_one(a); fmpz_mat_neg(a, a); fmpz_mat_set(d, a); } sp2gz_set_blocks(mat, a, b, c, d); fmpz_mat_clear(a); fmpz_mat_clear(b); fmpz_mat_clear(c); fmpz_mat_clear(d); } static void sp2gz_fundamental_gen_1(fmpz_mat_t mat, slong j) { slong g = sp2gz_dim(mat); slong k = 0; slong cnt = 0; slong l, u, v; fmpz_mat_t mat_g2; fmpz_mat_init(mat_g2, 4, 4); while (cnt + (g - 1 - k) <= j/19) { cnt += g - 1 - k; k++; } l = k + 1 + (j/19 - cnt); sp2gz_fundamental_g2(mat_g2, j % 19); fmpz_mat_one(mat); for (u = 0; u < 2; u++) { for (v = 0; v < 2; v++) { fmpz_set(fmpz_mat_entry(mat, k + u * g, k + v * g), fmpz_mat_entry(mat_g2, 2 * u, 2 * v)); fmpz_set(fmpz_mat_entry(mat, k + u * g, l + v * g), fmpz_mat_entry(mat_g2, 2 * u, 2 * v + 1)); fmpz_set(fmpz_mat_entry(mat, l + u * g, k + v * g), fmpz_mat_entry(mat_g2, 2 * u + 1, 2 * v)); fmpz_set(fmpz_mat_entry(mat, l + u * g, l + v * g), fmpz_mat_entry(mat_g2, 2 * u + 1, 2 * v + 1)); } } fmpz_mat_clear(mat_g2); } static void sp2gz_fundamental_gen_2(fmpz_mat_t mat, slong j) { slong g = sp2gz_dim(mat); slong k; fmpz_mat_one(mat); for (k = g - 1; k >= 0; k--) { if (j % 2 == 1) { fmpz_zero(fmpz_mat_entry(mat, k, k)); fmpz_one(fmpz_mat_entry(mat, k, k + g)); fmpz_set_si(fmpz_mat_entry(mat, k + g, k), -1); fmpz_zero(fmpz_mat_entry(mat, k + g, k + g)); } } } void sp2gz_fundamental(fmpz_mat_t mat, slong j) { slong g = sp2gz_dim(mat); slong nb_1 = 19 * ((g * (g - 1))/2); if (g == 1) { sp2gz_j(mat); } else if (g == 2) { sp2gz_fundamental_g2(mat, j); } else if (j < nb_1) { sp2gz_fundamental_gen_1(mat, j); } else { sp2gz_fundamental_gen_2(mat, j - nb_1); } } flint-3.1.3/src/acb_theta/sp2gz_inv.c000066400000000000000000000013051461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void sp2gz_inv(fmpz_mat_t inv, const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t j; fmpz_mat_init(j, 2 * g, 2 * g); sp2gz_j(j); fmpz_mat_transpose(inv, mat); fmpz_mat_mul(inv, inv, j); fmpz_mat_mul(inv, j, inv); fmpz_mat_neg(inv, inv); fmpz_mat_clear(j); } flint-3.1.3/src/acb_theta/sp2gz_is_block_diag.c000066400000000000000000000014111461254215100213730ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int sp2gz_is_block_diag(const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t beta, gamma; int res; fmpz_mat_window_init(beta, mat, 0, g, g, 2 * g); fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); res = fmpz_mat_is_zero(beta) && fmpz_mat_is_zero(gamma); fmpz_mat_window_clear(beta); fmpz_mat_window_clear(gamma); return res; } flint-3.1.3/src/acb_theta/sp2gz_is_correct.c000066400000000000000000000016501461254215100207630ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int sp2gz_is_correct(const fmpz_mat_t mat) { slong r = fmpz_mat_nrows(mat); slong c = fmpz_mat_ncols(mat); slong g = r / 2; fmpz_mat_t J, test; int res; if (r != c || r % 2 != 0) { return 0; } fmpz_mat_init(J, 2 * g, 2 * g); fmpz_mat_init(test, 2 * g, 2 * g); sp2gz_j(J); fmpz_mat_transpose(test, mat); fmpz_mat_mul(test, test, J); fmpz_mat_mul(test, test, mat); res = fmpz_mat_equal(test, J); fmpz_mat_clear(J); fmpz_mat_clear(test); return res; } flint-3.1.3/src/acb_theta/sp2gz_is_embedded.c000066400000000000000000000012601461254215100210500ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int sp2gz_is_embedded(fmpz_mat_t res, const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t t; int r; fmpz_mat_init(t, 2 * g, 2 * g); sp2gz_restrict(res, mat); sp2gz_embed(t, res); r = fmpz_mat_equal(t, mat); fmpz_mat_clear(t); return r; } flint-3.1.3/src/acb_theta/sp2gz_is_j.c000066400000000000000000000017121461254215100175520ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int sp2gz_is_j(const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t block; int res; fmpz_mat_window_init(block, mat, 0, 0, g, g); res = fmpz_mat_is_zero(block); fmpz_mat_window_clear(block); if (res) { fmpz_mat_window_init(block, mat, 0, g, g, 2 * g); res = fmpz_mat_is_one(block); fmpz_mat_window_clear(block); } if (res) { fmpz_mat_window_init(block, mat, g, g, 2 * g, 2 * g); res = fmpz_mat_is_zero(block); fmpz_mat_window_clear(block); } return res; } flint-3.1.3/src/acb_theta/sp2gz_is_trig.c000066400000000000000000000014021461254215100202620ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" int sp2gz_is_trig(const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t alpha, gamma; int res; fmpz_mat_window_init(alpha, mat, 0, 0, g, g); fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); res = fmpz_mat_is_one(alpha) && fmpz_mat_is_zero(gamma); fmpz_mat_window_clear(alpha); fmpz_mat_window_clear(gamma); return res; } flint-3.1.3/src/acb_theta/sp2gz_j.c000066400000000000000000000014341461254215100170600ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void sp2gz_j(fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t zero, one, minus_one; fmpz_mat_init(zero, g, g); fmpz_mat_init(one, g, g); fmpz_mat_init(minus_one, g, g); fmpz_mat_one(one); fmpz_mat_neg(minus_one, one); sp2gz_set_blocks(mat, zero, one, minus_one, zero); fmpz_mat_clear(zero); fmpz_mat_clear(one); fmpz_mat_clear(minus_one); } flint-3.1.3/src/acb_theta/sp2gz_nb_fundamental.c000066400000000000000000000010741461254215100216040ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" slong sp2gz_nb_fundamental(slong g) { if (g == 1) return 1; if (g == 2) return 19; else return 19 * ((g * (g - 1)) / 2) + (1 << g); } flint-3.1.3/src/acb_theta/sp2gz_randtest.c000066400000000000000000000035131461254215100204530ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" static void sp2gz_randtest_trig(fmpz_mat_t mat, flint_rand_t state, slong bits) { slong g = sp2gz_dim(mat); fmpz_mat_t b, bt; fmpz_mat_init(b, g, g); fmpz_mat_init(bt, g, g); bits = FLINT_MAX(bits, 1); fmpz_mat_randbits(b, state, bits); fmpz_mat_transpose(bt, b); fmpz_mat_add(b, b, bt); fmpz_mat_scalar_tdiv_q_2exp(b, b, 1); sp2gz_trig(mat, b); fmpz_mat_clear(b); fmpz_mat_clear(bt); } static void sp2gz_randtest_block_diag(fmpz_mat_t mat, flint_rand_t state, slong bits) { slong g = sp2gz_dim(mat); fmpz_mat_t u; fmpz_mat_init(u, g, g); bits = FLINT_MAX(bits, 1); fmpz_mat_one(u); fmpz_mat_randops(u, state, 2 * bits * g); sp2gz_block_diag(mat, u); fmpz_mat_clear(u); } void sp2gz_randtest(fmpz_mat_t mat, flint_rand_t state, slong bits) { slong g = sp2gz_dim(mat); slong b = bits/5 + 1; fmpz_mat_t aux; fmpz_mat_init(aux, 2 * g, 2 * g); sp2gz_randtest_block_diag(mat, state, b); sp2gz_randtest_trig(aux, state, b); fmpz_mat_mul(mat, mat, aux); sp2gz_j(aux); fmpz_mat_mul(mat, mat, aux); sp2gz_randtest_trig(aux, state, b); fmpz_mat_mul(mat, mat, aux); sp2gz_j(aux); fmpz_mat_mul(mat, mat, aux); sp2gz_randtest_trig(aux, state, b); fmpz_mat_mul(mat, mat, aux); sp2gz_j(aux); fmpz_mat_mul(mat, mat, aux); sp2gz_randtest_trig(aux, state, b); fmpz_mat_mul(mat, mat, aux); fmpz_mat_clear(aux); } flint-3.1.3/src/acb_theta/sp2gz_restrict.c000066400000000000000000000016321461254215100204660ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void sp2gz_restrict(fmpz_mat_t res, const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); slong g1 = sp2gz_dim(res); fmpz_mat_t a, b, c, d; fmpz_mat_window_init(a, mat, 0, 0, g1, g1); fmpz_mat_window_init(b, mat, 0, g, g1, g + g1); fmpz_mat_window_init(c, mat, g, 0, g + g1, g1); fmpz_mat_window_init(d, mat, g, g, g + g1, g + g1); sp2gz_set_blocks(res, a, b, c, d); fmpz_mat_window_clear(a); fmpz_mat_window_clear(b); fmpz_mat_window_clear(c); fmpz_mat_window_clear(d); } flint-3.1.3/src/acb_theta/sp2gz_set_blocks.c000066400000000000000000000020031461254215100207500ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" void sp2gz_set_blocks(fmpz_mat_t mat, const fmpz_mat_t alpha, const fmpz_mat_t beta, const fmpz_mat_t gamma, const fmpz_mat_t delta) { slong g = sp2gz_dim(mat); slong j, k; for (j = 0; j < g; j++) { for (k = 0; k < g; k++) { fmpz_set(fmpz_mat_entry(mat, j, k), fmpz_mat_entry(alpha, j, k)); fmpz_set(fmpz_mat_entry(mat, j, k + g), fmpz_mat_entry(beta, j, k)); fmpz_set(fmpz_mat_entry(mat, j + g, k), fmpz_mat_entry(gamma, j, k)); fmpz_set(fmpz_mat_entry(mat, j + g, k + g), fmpz_mat_entry(delta, j, k)); } } } flint-3.1.3/src/acb_theta/sp2gz_trig.c000066400000000000000000000012721461254215100175740ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_theta.h" void sp2gz_trig(fmpz_mat_t mat, const fmpz_mat_t S) { slong g = sp2gz_dim(mat); fmpz_mat_t zero, one; fmpz_mat_init(zero, g, g); fmpz_mat_init(one, g, g); fmpz_mat_one(one); sp2gz_set_blocks(mat, one, S, zero, one); fmpz_mat_clear(zero); fmpz_mat_clear(one); } flint-3.1.3/src/acb_theta/test/000077500000000000000000000000001461254215100163135ustar00rootroot00000000000000flint-3.1.3/src/acb_theta/test/main.c000066400000000000000000000126701461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-agm_hadamard.c" #include "t-agm_mul.c" #include "t-agm_mul_tight.c" #include "t-agm_sqrt.c" #include "t-all.c" #include "t-char_dot.c" #include "t-char_get_a.c" #include "t-char_is_even.c" #include "t-char_is_goepel.c" #include "t-char_is_syzygous.c" #include "t-dist_a0.c" #include "t-dist_lat.c" #include "t-dist_pt.c" #include "t-eld_border.c" #include "t-eld_points.c" #include "t-g2_character.c" #include "t-g2_chi10.c" #include "t-g2_chi12.c" #include "t-g2_chi35.c" #include "t-g2_chi3_6.c" #include "t-g2_chi5.c" #include "t-g2_covariants.c" #include "t-g2_covariants_lead.c" #include "t-g2_detk_symj.c" #include "t-g2_jet_naive_1.c" #include "t-g2_psi4.c" #include "t-g2_psi6.c" #include "t-g2_sextic.c" #include "t-g2_sextic_chi5.c" #include "t-g2_transvectant.c" #include "t-g2_transvectant_lead.c" #include "t-jet_all.c" #include "t-jet_compose.c" #include "t-jet_error_bounds.c" #include "t-jet_mul.c" #include "t-jet_naive_00.c" #include "t-jet_naive_all.c" #include "t-jet_naive_fixed_ab.c" #include "t-jet_naive_radius.c" #include "t-jet_ql_all.c" #include "t-jet_ql_bounds.c" #include "t-jet_ql_finite_diff.c" #include "t-jet_ql_radius.c" #include "t-jet_tuples.c" #include "t-naive_00.c" #include "t-naive_all.c" #include "t-naive_fixed_ab.c" #include "t-naive_fixed_a.c" #include "t-naive_radius.c" #include "t-naive_reduce.c" #include "t-naive_term.c" #include "t-ql_a0.c" #include "t-ql_a0_split.c" #include "t-ql_a0_steps.c" #include "t-ql_all.c" #include "t-ql_reduce.c" #include "t-siegel_cocycle.c" #include "t-siegel_is_reduced.c" #include "t-siegel_reduce.c" #include "t-siegel_transform.c" #include "t-siegel_transform_z.c" #include "t-sp2gz_decompose.c" #include "t-sp2gz_inv.c" #include "t-sp2gz_is_correct.c" #include "t-sp2gz_set_blocks.c" #include "t-transform_char.c" #include "t-transform_kappa.c" #include "t-transform_proj.c" #include "t-transform_sqrtdet.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acb_theta_agm_hadamard), TEST_FUNCTION(acb_theta_agm_mul), TEST_FUNCTION(acb_theta_agm_mul_tight), TEST_FUNCTION(acb_theta_agm_sqrt), TEST_FUNCTION(acb_theta_all), TEST_FUNCTION(acb_theta_char_dot), TEST_FUNCTION(acb_theta_char_get_a), TEST_FUNCTION(acb_theta_char_is_even), TEST_FUNCTION(acb_theta_char_is_goepel), TEST_FUNCTION(acb_theta_char_is_syzygous), TEST_FUNCTION(acb_theta_dist_a0), TEST_FUNCTION(acb_theta_dist_lat), TEST_FUNCTION(acb_theta_dist_pt), TEST_FUNCTION(acb_theta_eld_border), TEST_FUNCTION(acb_theta_eld_points), TEST_FUNCTION(acb_theta_g2_character), TEST_FUNCTION(acb_theta_g2_chi10), TEST_FUNCTION(acb_theta_g2_chi12), TEST_FUNCTION(acb_theta_g2_chi35), TEST_FUNCTION(acb_theta_g2_chi3_6), TEST_FUNCTION(acb_theta_g2_chi5), TEST_FUNCTION(acb_theta_g2_covariants), TEST_FUNCTION(acb_theta_g2_covariants_lead), TEST_FUNCTION(acb_theta_g2_detk_symj), TEST_FUNCTION(acb_theta_g2_jet_naive_1), TEST_FUNCTION(acb_theta_g2_psi4), TEST_FUNCTION(acb_theta_g2_psi6), TEST_FUNCTION(acb_theta_g2_sextic), TEST_FUNCTION(acb_theta_g2_sextic_chi5), TEST_FUNCTION(acb_theta_g2_transvectant), TEST_FUNCTION(acb_theta_g2_transvectant_lead), TEST_FUNCTION(acb_theta_jet_all), TEST_FUNCTION(acb_theta_jet_compose), TEST_FUNCTION(acb_theta_jet_error_bounds), TEST_FUNCTION(acb_theta_jet_mul), TEST_FUNCTION(acb_theta_jet_naive_00), TEST_FUNCTION(acb_theta_jet_naive_all), TEST_FUNCTION(acb_theta_jet_naive_fixed_ab), TEST_FUNCTION(acb_theta_jet_naive_radius), TEST_FUNCTION(acb_theta_jet_ql_all), TEST_FUNCTION(acb_theta_jet_ql_bounds), TEST_FUNCTION(acb_theta_jet_ql_finite_diff), TEST_FUNCTION(acb_theta_jet_ql_radius), TEST_FUNCTION(acb_theta_jet_tuples), TEST_FUNCTION(acb_theta_naive_00), TEST_FUNCTION(acb_theta_naive_all), TEST_FUNCTION(acb_theta_naive_fixed_ab), TEST_FUNCTION(acb_theta_naive_fixed_a), TEST_FUNCTION(acb_theta_naive_radius), TEST_FUNCTION(acb_theta_naive_reduce), TEST_FUNCTION(acb_theta_naive_term), TEST_FUNCTION(acb_theta_ql_a0), TEST_FUNCTION(acb_theta_ql_a0_split), TEST_FUNCTION(acb_theta_ql_a0_steps), TEST_FUNCTION(acb_theta_ql_all), TEST_FUNCTION(acb_theta_ql_reduce), TEST_FUNCTION(acb_theta_siegel_cocycle), TEST_FUNCTION(acb_theta_siegel_is_reduced), TEST_FUNCTION(acb_theta_siegel_reduce), TEST_FUNCTION(acb_theta_siegel_transform), TEST_FUNCTION(acb_theta_siegel_transform_z), TEST_FUNCTION(acb_theta_sp2gz_decompose), TEST_FUNCTION(acb_theta_sp2gz_inv), TEST_FUNCTION(acb_theta_sp2gz_is_correct), TEST_FUNCTION(acb_theta_sp2gz_set_blocks), TEST_FUNCTION(acb_theta_transform_char), TEST_FUNCTION(acb_theta_transform_kappa), TEST_FUNCTION(acb_theta_transform_proj), TEST_FUNCTION(acb_theta_transform_sqrtdet) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acb_theta/test/t-agm_hadamard.c000066400000000000000000000031101461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_agm_hadamard, state) { slong iter; /* Test: twice Hadamard should be multiplication by 2^g */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 5); slong prec = 20 + n_randint(state, 200); slong mag_bits = n_randint(state, 4); acb_ptr s; acb_ptr r; acb_ptr test; slong n = 1 << g; slong k; s = _acb_vec_init(n); r = _acb_vec_init(n); test = _acb_vec_init(n); for (k = 0; k < n; k++) { acb_randtest_precise(&s[k], state, prec, mag_bits); } acb_theta_agm_hadamard(r, s, g, prec); acb_theta_agm_hadamard(test, r, g, prec); _acb_vec_scalar_mul_2exp_si(test, test, n, -g); if (!_acb_vec_contains(test, s, n)) { flint_printf("FAIL (overlap):\n"); _acb_vec_printd(s, n, 10); _acb_vec_printd(test, n, 10); flint_abort(); } _acb_vec_clear(s, n); _acb_vec_clear(r, n); _acb_vec_clear(test, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-agm_mul.c000066400000000000000000000051251461254215100203440ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_agm_mul, state) { slong iter; /* Test: duplication formula */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong prec = 100 + n_randint(state, 200); slong mag_bits = n_randint(state, 2); slong rad_exp = -5; slong n = 1 << g; acb_mat_t tau; acb_ptr z; arf_t rad; acb_ptr th; acb_ptr th_dupl; acb_ptr test; arb_t err; slong k; acb_mat_init(tau, g, g); arf_init(rad); z = _acb_vec_init(2 * g); th = _acb_vec_init(2 * n); th_dupl = _acb_vec_init(2 * n); test = _acb_vec_init(2 * n); arb_init(err); acb_siegel_randtest_reduced(tau, state, prec, mag_bits); arf_one(rad); arf_mul_2exp_si(rad, rad, rad_exp); for (k = 0; k < g; k++) { acb_urandom(&z[k], state, prec); } _acb_vec_scalar_mul_2exp_si(z, z, g, rad_exp); acb_theta_naive_0b(th, z, 2, tau, prec); acb_mat_scalar_mul_2exp_si(tau, tau, 1); acb_theta_naive_0b(th_dupl, z, 2, tau, prec); _acb_vec_sqr(th_dupl, th_dupl, 2 * n, prec); acb_theta_agm_mul(test, th, th + n, g, prec); acb_theta_agm_mul(test + n, th + n, th + n, g, prec); if (!_acb_vec_overlaps(test, th_dupl, 2 * n)) { flint_printf("FAIL (overlap)\n"); flint_printf("g = %wd, prec = %wd, tau, z:\n", g, prec); acb_mat_printd(tau, 10); _acb_vec_printd(z, g, 10); flint_printf("theta:\n"); _acb_vec_printd(th, 2 * n, 10); flint_printf("dupl:\n"); _acb_vec_printd(th_dupl, 2 * n, 10); flint_printf("test:\n"); _acb_vec_printd(test, 2 * n, 10); fflush(stdout); flint_abort(); } acb_mat_clear(tau); arf_clear(rad); _acb_vec_clear(z, 2 * g); _acb_vec_clear(th, 2 * n); _acb_vec_clear(th_dupl, 2 * n); _acb_vec_clear(test, 2 * n); arb_clear(err); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-agm_mul_tight.c000066400000000000000000000077721461254215100215550ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_agm_mul_tight, state) { slong iter; /* Test: respects relative precision */ for (iter = 0; iter < 50 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong n = 1 << g; slong mprec = 50 + n_randint(state, 500); slong prec = mprec + 50; slong bits = n_randint(state, 3); slong delta = 25; acb_mat_t tau; acb_ptr z; acb_ptr th, th0, r; arb_ptr d, d0; arb_t x, t; arf_t eps; slong k; acb_mat_init(tau, g, g); z = _acb_vec_init(g); r = _acb_vec_init(n); th = _acb_vec_init(n); th0 = _acb_vec_init(n); d = _arb_vec_init(n); d0 = _arb_vec_init(n); arb_init(x); arb_init(t); arf_init(eps); /* Generate distances, not too crazy */ acb_siegel_randtest_reduced(tau, state, prec, bits); acb_theta_dist_a0(d0, z, tau, prec); for (k = 0; k < g; k++) { acb_randtest_precise(&z[k], state, prec, bits); } acb_theta_dist_a0(d, z, tau, prec); /* Generate values */ for (k = 0; k < n; k++) { arb_neg(x, &d[k]); arb_exp(x, x, prec); acb_urandom(&th[k], state, prec); acb_mul_arb(&th[k], &th[k], x, prec); arb_neg(x, &d0[k]); arb_exp(x, x, prec); acb_urandom(&th0[k], state, prec); acb_mul_arb(&th0[k], &th0[k], x, prec); } acb_theta_agm_mul_tight(r, th0, th, d0, d, g, mprec); for (k = 0; k < n; k++) { acb_abs(x, &r[k], prec); arb_neg(t, &d[k]); arb_exp(t, t, prec); if (arb_gt(x, t)) { flint_printf("FAIL (absolute value, k = %wd)\n", k); flint_printf("g = %wd, prec = %wd, tau:\n", g, prec); acb_mat_printd(tau, 5); flint_printf("distances:\n"); _arb_vec_printd(d0, n, 5); _arb_vec_printd(d, n, 5); flint_printf("values:\n"); _acb_vec_printd(th0, n, 5); _acb_vec_printd(th, n, 5); flint_printf("result:\n"); _acb_vec_printd(r, n, 5); flint_abort(); } acb_get_rad_ubound_arf(eps, &r[k], prec); arb_set_arf(x, eps); arb_mul_2exp_si(t, t, -mprec + delta); if (arb_gt(x, t)) { flint_printf("FAIL (precision loss, k = %wd)\n", k); flint_printf("g = %wd, prec = %wd, tau:\n", g, prec); acb_mat_printd(tau, 5); flint_printf("distances:\n"); _arb_vec_printd(d0, n, 5); _arb_vec_printd(d, n, 5); flint_printf("values:\n"); _acb_vec_printd(th0, n, 5); _acb_vec_printd(th, n, 5); flint_printf("result:\n"); _acb_vec_printd(r, n, 5); flint_printf("x, t:\n"); arb_printd(x, 5); flint_printf("\n"); arb_printd(t, 5); flint_printf("\n"); flint_abort(); } } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(r, n); _acb_vec_clear(th, n); _acb_vec_clear(th0, n); _arb_vec_clear(d, n); _arb_vec_clear(d0, n); arb_clear(x); arb_clear(t); arf_clear(eps); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-agm_sqrt.c000066400000000000000000000051211461254215100205340ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_agm_sqrt, state) { slong iter; /* Test: - if nonzero, value of square root should agree; precision remains high - no abort on wrong values of rt_low */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong prec = 100 + n_randint(state, 1000); slong mag_bits = n_randint(state, 4); slong lowprec = 10 + n_randint(state, 10); slong delta = (1 << mag_bits) + 10; acb_t rt, x, rt_low, t; arf_t err; acb_init(rt); acb_init(x); acb_init(rt_low); acb_init(t); arf_init(err); acb_randtest_precise(rt, state, prec, mag_bits); if (iter % 10 == 0) { acb_union(rt, rt, x, prec); } acb_sqr(x, rt, prec); acb_one(t); acb_mul_2exp_si(t, t, -lowprec); acb_add_si(t, t, 1, lowprec); acb_mul(rt_low, rt, t, lowprec); acb_theta_agm_sqrt(t, x, rt_low, 1, prec); acb_get_rad_ubound_arf(err, t, prec); if (!acb_contains(t, rt)) { flint_printf("FAIL (value)\n"); acb_printd(rt, 5); flint_printf("\n"); acb_printd(t, 5); flint_printf("\n"); acb_printd(rt_low, 5); flint_printf("\n"); flint_abort(); } if (!acb_is_finite(t)) { flint_printf("FAIL (infinite)\n"); flint_abort(); } if (!acb_contains_zero(rt) && (arf_cmp_2exp_si(err, -prec + delta) > 0)) { flint_printf("FAIL (precision)\n"); flint_printf("prec = %wd, result:\n", prec, mag_bits); acb_printd(t, 10); flint_printf("\nrt_low:\n"); acb_printd(rt_low, 10); flint_printf("\n"); flint_abort(); } if (iter % 10 == 1) { acb_randtest(rt_low, state, prec, mag_bits); acb_theta_agm_sqrt(t, x, rt_low, 1, prec); } acb_clear(rt); acb_clear(x); acb_clear(rt_low); acb_clear(t); arf_clear(err); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-all.c000066400000000000000000000043441461254215100174750ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_all, state) { slong iter; /* Test: agrees with naive_all */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 2); slong n2 = 1 << (2 * g); slong prec = 100 + n_randint(state, 400); slong bits = n_randint(state, 4); int sqr = iter % 2; acb_mat_t tau; acb_ptr z; acb_ptr th, test; slong k; acb_mat_init(tau, g, g); z = _acb_vec_init(g); th = _acb_vec_init(n2); test = _acb_vec_init(n2); /* Sample tau not too far from reduced domain */ acb_siegel_randtest_reduced(tau, state, prec, bits); acb_mat_scalar_mul_2exp_si(tau, tau, -1); acb_siegel_randtest_vec(z, state, g, prec); /* Sometimes phony input too */ if (n_randint(state, 20) == 0) { k = n_randint(state, g); arb_zero(acb_imagref(acb_mat_entry(tau, k, k))); } acb_theta_all(th, z, tau, sqr, prec); acb_theta_naive_all(test, z, 1, tau, prec); if (sqr) { for (k = 0; k < n2; k++) { acb_sqr(&test[k], &test[k], prec); } } if (!_acb_vec_overlaps(th, test, n2)) { flint_printf("FAIL\n"); flint_printf("g = %wd, prec = %wd, sqr = %wd, tau, z:\n", g, prec, sqr); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("th, test:\n"); _acb_vec_printd(th, n2, 5); _acb_vec_printd(test, n2, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(th, n2); _acb_vec_clear(test, n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-char_dot.c000066400000000000000000000042021461254215100205010ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_char_dot, state) { slong iter; /* Test: various dots are the same */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 10); slong prec = 100; ulong a, b; slong * n; acb_ptr v, w; fmpz_t m; slong x1, x2; acb_t x3, x4; int res; n = flint_malloc(g * sizeof(slong)); v = _acb_vec_init(g); w = _acb_vec_init(g); a = n_randint(state, 1 << g); b = n_randint(state, 1 << g); acb_init(x3); acb_init(x4); fmpz_init(m); x1 = acb_theta_char_dot(a, b, g); acb_theta_char_get_slong(n, b, g); x2 = acb_theta_char_dot_slong(a, n, g); acb_theta_char_get_acb(v, b, g); acb_theta_char_dot_acb(x3, a, v, g, prec); acb_theta_char_get_acb(w, a, g); acb_dot(x4, NULL, 0, v, 1, w, 1, g, prec); if (x1 != x2 || !acb_overlaps(x3, x4)) { flint_printf("FAIL\n"); flint_printf("x1 = %wd, x2 = %wd, x3, x4:\n", x1, x2); acb_printd(x3, 10); flint_printf("\n"); acb_printd(x4, 10); flint_printf("\n"); flint_abort(); } acb_mul_2exp_si(x3, x3, 2); res = acb_get_unique_fmpz(m, x3); fmpz_sub_si(m, m, x1); if (!res || !fmpz_divisible_si(m, 4)) { flint_printf("FAIL (mod 4)\n"); flint_abort(); } flint_free(n); _acb_vec_clear(v, g); _acb_vec_clear(w, g); acb_clear(x3); acb_clear(x4); fmpz_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-char_get_a.c000066400000000000000000000020701461254215100207730ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_char_get_a, state) { slong iter; /* Test: inverse of char_get_slong */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 10); slong * n; ulong a, t; n = flint_malloc(g * sizeof(slong)); a = n_randint(state, 1 << g); acb_theta_char_get_slong(n, a, g); t = acb_theta_char_get_a(n, g); if (a != t) { flint_printf("FAIL\n"); flint_printf("a, t: %wd, %wd\n", a, t); flint_abort(); } flint_free(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-char_is_even.c000066400000000000000000000024341461254215100213500ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_char_is_even, state) { slong iter; /* Test: values for g = 2 */ for (iter = 0; iter < 1; iter++) { slong g = 2; slong even[10] = {0, 1, 2, 3, 4, 6, 8, 9, 12, 15}; slong odd[6] = {5, 7, 10, 11, 13, 14}; slong i; for (i = 0; i < 10; i++) { if (!acb_theta_char_is_even(even[i], g)) { flint_printf("FAIL (even)\n"); flint_printf("i = %wd, ab = %wd\n", i, even[i]); flint_abort(); } } for (i = 0; i < 6; i++) { if (acb_theta_char_is_even(odd[i], g)) { flint_printf("FAIL (odd)\n"); flint_printf("i = %wd, ab = %wd\n", i, odd[i]); flint_abort(); } } } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-char_is_goepel.c000066400000000000000000000025041461254215100216640ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_char_is_goepel, state) { slong iter; /* Test: there are 15 Goepel quadruples for g = 2 */ for (iter = 0; iter < 1; iter++) { slong g = 2; slong n = 1 << (2 * g); ulong ch1, ch2, ch3, ch4; slong cnt = 0; for (ch1 = 0; ch1 < n; ch1++) { for (ch2 = ch1; ch2 < n; ch2++) { for (ch3 = ch2; ch3 < n; ch3++) { for (ch4 = ch3; ch4 < n; ch4++) { if (acb_theta_char_is_goepel(ch1, ch2, ch3, ch4, g)) { cnt++; } } } } } if (cnt != 15) { flint_printf("FAIL (cnt = %wd)\n", cnt); flint_abort(); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-char_is_syzygous.c000066400000000000000000000023151461254215100223250ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_char_is_syzygous, state) { slong iter; /* Test: there are 60 syzygous triples for g = 2 */ for (iter = 0; iter < 1; iter++) { slong g = 2; slong n = 1 << (2 * g); ulong ch1, ch2, ch3; slong cnt = 0; for (ch1 = 0; ch1 < n; ch1++) { for (ch2 = ch1; ch2 < n; ch2++) { for (ch3 = ch2; ch3 < n; ch3++) { if (acb_theta_char_is_syzygous(ch1, ch2, ch3, g)) { cnt++; } } } } if (cnt != 60) { flint_printf("FAIL (cnt = %wd)\n", cnt); flint_abort(); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-dist_a0.c000066400000000000000000000035061461254215100202470ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_dist_a0, state) { slong iter; /* Test: find zero value when z = tau a/2 + real stuff */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong n = 1 << g; slong prec = ACB_THETA_LOW_PREC; slong hprec = 200; slong bits = n_randint(state, 5); acb_mat_t tau; acb_ptr z; arb_ptr d; arb_t c; ulong a = n_randint(state, n); slong k; acb_mat_init(tau, g, g); z = _acb_vec_init(g); d = _arb_vec_init(n); arb_init(c); acb_siegel_randtest_reduced(tau, state, hprec, bits); acb_theta_char_get_acb(z, a, g); acb_mat_vector_mul_col(z, tau, z, prec); for (k = 0; k < g; k++) { arb_urandom(c, state, prec); acb_add_arb(&z[k], &z[k], c, prec); } acb_theta_dist_a0(d, z, tau, prec); if (!arb_contains_zero(&d[a])) { flint_printf("FAIL\n"); flint_printf("g = %wd, a = %wd, tau:\n", g, a); acb_mat_printd(tau, 5); flint_printf("distances:\n"); _arb_vec_printd(d, n, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _arb_vec_clear(d, n); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-dist_lat.c000066400000000000000000000066311461254215100205310ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_dist_lat, state) { slong iter; /* Test: make ellipsoid to check it is indeed the minimal distance */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong prec = ACB_THETA_LOW_PREC; slong hprec = 200; slong bits = n_randint(state, 5); acb_mat_t tau; arb_mat_t C; acb_ptr z; arb_ptr v, y; arb_t d, test, x, s; arf_t R2; acb_theta_eld_t E; slong *pts; slong k; int r; acb_mat_init(tau, g, g); arb_mat_init(C, g, g); z = _acb_vec_init(g); v = _arb_vec_init(g); y = _arb_vec_init(g); arb_init(d); arb_init(test); arb_init(x); arb_init(s); acb_theta_eld_init(E, g, g); arf_init(R2); /* Get reduced C */ acb_siegel_randtest_reduced(tau, state, hprec, bits); acb_siegel_randtest_vec(z, state, g, prec); _acb_vec_get_imag(v, z, g); acb_siegel_cho(C, tau, prec); acb_theta_dist_lat(d, v, C, prec); arb_get_ubound_arf(R2, d, prec); /* Test: ellipsoid has points and d is the minimum distance */ r = acb_theta_eld_set(E, C, R2, v); if (r) { if (acb_theta_eld_nb_pts(E) == 0) { flint_printf("FAIL (no points)\n"); flint_printf("g = %wd, C:\n", g); arb_mat_printd(C, 10); flint_printf("offset:\n"); _arb_vec_printn(v, g, 10, 0); flint_printf("\n"); flint_printf("Distance: "); arf_printd(R2, 10); flint_printf("\n"); flint_abort(); } pts = flint_malloc(acb_theta_eld_nb_pts(E) * sizeof(slong) * g); acb_theta_eld_points(pts, E); arb_pos_inf(test); for (k = 0; k < acb_theta_eld_nb_pts(E); k++) { acb_theta_dist_pt(x, v, C, pts + k * g, prec); arb_min(test, test, x, prec); } if (!arb_overlaps(d, test)) { flint_printf("FAIL (wrong distance)\n"); flint_printf("g = %wd, C:\n", g); arb_mat_printd(C, 10); flint_printf("offset:\n"); _arb_vec_printn(v, g, 10, 0); flint_printf("\n"); flint_printf("Distance: "); arf_printd(R2, 10); flint_printf("\n"); flint_abort(); } flint_free(pts); } acb_mat_clear(tau); arb_mat_clear(C); _acb_vec_clear(z, g); _arb_vec_clear(v, g); _arb_vec_clear(y, g); arb_clear(d); arb_clear(test); arb_clear(x); arb_clear(s); acb_theta_eld_clear(E); arf_clear(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-dist_pt.c000066400000000000000000000042701461254215100203710ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_dist_pt, state) { slong iter; /* Test: symmetric using C * pt as offset */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 6); slong prec = ACB_THETA_LOW_PREC; slong bits = n_randint(state, 3); arb_mat_t C; arb_ptr v; arb_t d1, d2; slong * pt1; slong * pt2; slong k; arb_mat_init(C, g, g); v = _arb_vec_init(g); arb_init(d1); arb_init(d2); pt1 = flint_malloc(g * sizeof(slong)); pt2 = flint_malloc(g * sizeof(slong)); arb_mat_randtest_cho(C, state, prec, bits); arb_mat_transpose(C, C); for (k = 0; k < g; k++) { pt1[k] = n_randint(state, 100); pt2[k] = n_randint(state, 100); } for (k = 0; k < g; k++) { arb_set_si(&v[k], pt1[k]); } arb_mat_vector_mul_col(v, C, v, prec); acb_theta_dist_pt(d1, v, C, pt2, prec); for (k = 0; k < g; k++) { arb_set_si(&v[k], pt2[k]); } arb_mat_vector_mul_col(v, C, v, prec); acb_theta_dist_pt(d2, v, C, pt1, prec); if (!arb_overlaps(d1, d2)) { flint_printf("FAIL\n"); flint_printf("C:\n"); arb_mat_printd(C, 5); flint_printf("distances:\n"); arb_printd(d1, 10); flint_printf("\n"); arb_printd(d2, 10); flint_printf("\n"); flint_abort(); } arb_mat_clear(C); _arb_vec_clear(v, g); arb_clear(d1); arb_clear(d2); flint_free(pt1); flint_free(pt2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-eld_border.c000066400000000000000000000056021461254215100210240ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_eld_border, state) { slong iter; /* Test: border points are not contained in the ellipsoid, nor any children */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong prec = ACB_THETA_LOW_PREC; slong mag_bits = n_randint(state, 2); acb_theta_eld_t E; arb_mat_t C; arb_t x; arf_t R2; arb_ptr v; slong k, j; slong *all_pts; int r; acb_theta_eld_init(E, g, g); arb_mat_init(C, g, g); arf_init(R2); v = _arb_vec_init(g); arb_init(x); arb_mat_randtest_cho(C, state, prec, mag_bits); arb_mat_transpose(C, C); arb_randtest_positive(x, state, prec, mag_bits); arf_set(R2, arb_midref(x)); arf_mul_si(R2, R2, 1 + n_randint(state, 10), prec, ARF_RND_UP); for (k = 0; k < g; k++) { arb_randtest_precise(&v[k], state, prec, mag_bits); } r = acb_theta_eld_set(E, C, R2, v); if (!r) { flint_printf("FAIL (ellipsoid)\n"); flint_abort(); } all_pts = flint_malloc(acb_theta_eld_nb_border(E) * g * sizeof(slong)); acb_theta_eld_border(all_pts, E); for (k = 0; k < acb_theta_eld_nb_border(E); k++) { for (j = 0; j < g; j++) { if (acb_theta_eld_contains(E, all_pts + k * g)) { flint_printf("FAIL: point inside ellipsoid\n"); flint_abort(); } } for (j = 0; j < acb_theta_eld_nr(E); j++) { if (acb_theta_eld_contains(acb_theta_eld_rchild(E, j), all_pts + k * g)) { flint_printf("FAIL: point inside right child %wd\n", j); flint_abort(); } } for (j = 0; j < acb_theta_eld_nl(E); j++) { if (acb_theta_eld_contains(acb_theta_eld_lchild(E, j), all_pts + k * g)) { flint_printf("FAIL: point inside left child %wd\n", j); flint_abort(); } } } acb_theta_eld_clear(E); arb_mat_clear(C); arf_clear(R2); _arb_vec_clear(v, g); arb_clear(x); flint_free(all_pts); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-eld_points.c000066400000000000000000000136541461254215100210710ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_eld_points, state) { slong iter; /* Test: all ellipsoid points must be within the box Then, generate random points: - points inside ellipsoid must appear in all_pts - points outside ellipsoid must have norm greater than R2 */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong prec = ACB_THETA_LOW_PREC; slong mag_bits = n_randint(state, 2); acb_theta_eld_t E; arb_mat_t C; arf_t R2; arb_ptr v; slong k, j; slong try; slong *all_pts; slong *pt; int res; arb_mat_t vec; arb_t sqr, sum; acb_theta_eld_init(E, g, g); arb_mat_init(C, g, g); arf_init(R2); v = _arb_vec_init(g); pt = flint_malloc(g * sizeof(slong)); arb_mat_init(vec, g, 1); arb_init(sqr); arb_init(sum); arb_mat_randtest_cho(C, state, prec, mag_bits); arb_mat_transpose(C, C); arb_randtest_positive(sqr, state, prec, mag_bits); arf_set(R2, arb_midref(sqr)); arf_mul_si(R2, R2, 1 + n_randint(state, 10), prec, ARF_RND_UP); for (k = 0; k < g; k++) { arb_randtest_precise(&v[k], state, prec, mag_bits); } res = acb_theta_eld_set(E, C, R2, v); if (!res) { flint_printf("FAIL (ellipsoid)\n"); flint_abort(); } all_pts = flint_malloc(acb_theta_eld_nb_pts(E) * g * sizeof(slong)); acb_theta_eld_points(all_pts, E); for (k = 0; k < acb_theta_eld_nb_pts(E); k++) { for (j = 0; j < g; j++) { if (FLINT_ABS(all_pts[k * g + j]) > acb_theta_eld_box(E, j)) { flint_printf("FAIL: point outside box\n"); flint_printf("\n"); flint_abort(); } } } for (try = 0; try < 100; try++) { for (k = 0; k < g; k++) { pt[k] = n_randint(state, acb_theta_eld_box(E, k) + 1); } if (acb_theta_eld_contains(E, pt)) { for (k = 0; k < acb_theta_eld_nb_pts(E); k++) { res = 1; for (j = 0; j < g; j++) { if (all_pts[k * g + j] != pt[j]) { res = 0; break; } } if (res == 1) { break; } } if (!res) { flint_printf("FAIL: point not listed:\n"); for (j = 0; j < g; j++) { flint_printf("%wd ", pt[j]); } flint_abort(); } } if (!acb_theta_eld_contains(E, pt)) { arb_mat_zero(vec); for (k = 0; k < g; k++) { arb_set_si(arb_mat_entry(vec, k, 0), pt[k]); } arb_mat_mul(vec, C, vec, prec); arb_zero(sum); for (k = 0; k < g; k++) { arb_add(arb_mat_entry(vec, k, 0), arb_mat_entry(vec, k, 0), &v[k], prec); arb_sqr(sqr, arb_mat_entry(vec, k, 0), prec); arb_add(sum, sum, sqr, prec); } arb_sub_arf(sum, sum, R2, prec); if (arb_is_negative(sum)) { flint_printf("FAIL: small point not in ellipsoid\n"); for (j = 0; j < g; j++) { flint_printf("%wd ", pt[j]); } flint_printf("\nCholesky:\n"); arb_mat_printd(C, 10); flint_printf("Norm of point: "); arb_printd(sum, 10); flint_printf("\nCoordinates:\n"); for (j = 0; j < g; j++) { arb_printd(arb_mat_entry(vec, j, 0), 10); flint_printf("\n"); } flint_printf("Upper bound: "); arf_printd(R2, 10); flint_printf("\ntotal nb of points = %wd\n", acb_theta_eld_nb_pts(E)); flint_printf("Offset:\n"); for (j = 0; j < g; j++) { arb_printd(&v[j], 10); flint_printf("\n"); } flint_printf("Points:\n"); for (k = 0; k < acb_theta_eld_nb_pts(E); k++) { for (j = 0; j < g; j++) { flint_printf("%wd ", all_pts[k * g + j]); } flint_printf("\n"); } flint_abort(); } } } acb_theta_eld_clear(E); arb_mat_clear(C); arf_clear(R2); _arb_vec_clear(v, g); flint_free(all_pts); flint_free(pt); arb_mat_clear(vec); arb_clear(sqr); arb_clear(sum); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_character.c000066400000000000000000000031311461254215100212420ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_character, state) { slong iter; /* Test: agrees with kappa2 */ for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { fmpz_mat_t mat; slong bits = n_randint(state, 10); slong ab, eps, u, test; fmpz_mat_init(mat, 4, 4); sp2gz_randtest(mat, state, bits); eps = acb_theta_g2_character(mat); test = 10 * acb_theta_transform_kappa2(mat); /* 10 theta constants */ for (ab = 0; ab < 16; ab++) { if (acb_theta_char_is_even(ab, 2)) { acb_theta_transform_char(&u, mat, ab); test += u; } } if (test % 4 != 0) { flint_printf("FAIL (%wd mod 4)\n", test % 4); fmpz_mat_print_pretty(mat); flint_printf("\n"); flint_abort(); } test = (test / 4) % 2; if (eps != test) { flint_printf("FAIL (%wd != %wd)\n", eps, test); fmpz_mat_print_pretty(mat); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_chi10.c000066400000000000000000000034031461254215100202140ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_chi10, state) { slong iter; /* Test: is a modular form */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 2; slong n2 = 16; slong prec = 100 + n_randint(state, 500); slong mag_bits = n_randint(state, 2); fmpz_mat_t mat; acb_ptr th2; acb_t r, s; slong k; fmpz_mat_init(mat, 2 * g, 2 * g); th2 = _acb_vec_init(n2); acb_init(r); acb_init(s); sp2gz_randtest(mat, state, mag_bits); for (k = 0; k < n2; k++) { acb_randtest_precise(&th2[k], state, prec, mag_bits); } acb_theta_g2_chi10(r, th2, prec); acb_theta_transform_proj(th2, mat, th2, 1, prec); acb_theta_g2_chi10(s, th2, prec); if (acb_theta_transform_kappa2(mat) % 2 == 1) { acb_neg(s, s); } if (!acb_overlaps(r, s)) { flint_printf("FAIL\n"); fmpz_mat_print_pretty(mat); acb_printd(r, 10); flint_printf("\n"); acb_printd(s, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); _acb_vec_clear(th2, n2); acb_clear(r); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_chi12.c000066400000000000000000000032361461254215100202220ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_chi12, state) { slong iter; /* Test: is a modular form */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 2; slong n2 = 16; slong prec = 100 + n_randint(state, 500); slong mag_bits = n_randint(state, 4); fmpz_mat_t mat; acb_ptr th2; acb_t r, s; slong k; fmpz_mat_init(mat, 2 * g, 2 * g); th2 = _acb_vec_init(n2); acb_init(r); acb_init(s); sp2gz_randtest(mat, state, mag_bits); for (k = 0; k < n2; k++) { acb_randtest_precise(&th2[k], state, prec, mag_bits); } acb_theta_g2_chi12(r, th2, prec); acb_theta_transform_proj(th2, mat, th2, 1, prec); acb_theta_g2_chi12(s, th2, prec); if (!acb_overlaps(r, s)) { flint_printf("FAIL\n"); fmpz_mat_print_pretty(mat); acb_printd(r, 10); flint_printf("\n"); acb_printd(s, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); _acb_vec_clear(th2, n2); acb_clear(r); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_chi35.c000066400000000000000000000035031461254215100202240ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_chi35, state) { slong iter; /* Test: transforms like a modular form */ for (iter = 0; iter < 50 * flint_test_multiplier(); iter++) { slong g = 2; slong n2 = 1 << (2 * g); slong prec = 100 + n_randint(state, 500); slong mag_bits = n_randint(state, 2); fmpz_mat_t mat; acb_mat_t tau; acb_ptr th, z; acb_t r, s; fmpz_mat_init(mat, 2 * g, 2 * g); acb_mat_init(tau, g, g); th = _acb_vec_init(n2); z = _acb_vec_init(g); acb_init(r); acb_init(s); sp2gz_randtest(mat, state, mag_bits); acb_siegel_randtest_reduced(tau, state, prec, mag_bits); acb_theta_all(th, z, tau, 0, prec); acb_theta_g2_chi35(r, th, prec); acb_theta_transform_proj(th, mat, th, 0, prec); acb_theta_g2_chi35(s, th, prec); acb_mul_i_pow_si(s, s, -acb_theta_transform_kappa2(mat)); if (!acb_overlaps(r, s)) { flint_printf("FAIL\n"); acb_printd(r, 10); flint_printf("\n"); acb_printd(s, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); acb_mat_clear(tau); _acb_vec_clear(th, n2); _acb_vec_clear(z, g); acb_clear(r); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_chi3_6.c000066400000000000000000000050131461254215100203620ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" static void acb_theta_g2_chi8_6(acb_poly_t res, const acb_mat_t tau, slong prec) { acb_ptr z, dth; acb_t c; slong k; dth = _acb_vec_init(3 * 16); z = _acb_vec_init(2); acb_init(c); acb_theta_jet_all(dth, z, tau, 1, prec); acb_theta_g2_chi3_6(res, dth, prec); for (k = 0; k < 16; k++) { acb_set(&dth[k], &dth[3 * k]); } acb_theta_g2_chi5(c, dth, prec); acb_poly_scalar_mul(res, res, c, prec); _acb_vec_clear(dth, 3 * 16); _acb_vec_clear(z, 2); acb_clear(c); } TEST_FUNCTION_START(acb_theta_g2_chi3_6, state) { slong iter; /* Test: chi5 * chi3_6 transforms like a modular form */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 2; slong prec = 100 + n_randint(state, 200); slong mag_bits = n_randint(state, 2); fmpz_mat_t mat; acb_mat_t tau, w, c, cinv; acb_poly_t r, s; fmpz_mat_init(mat, 2 * g, 2 * g); acb_mat_init(tau, g, g); acb_mat_init(w, g, g); acb_mat_init(c, g, g); acb_mat_init(cinv, g, g); acb_poly_init(r); acb_poly_init(s); sp2gz_randtest(mat, state, mag_bits); acb_siegel_randtest_reduced(tau, state, prec, mag_bits); acb_theta_g2_chi8_6(r, tau, prec); acb_siegel_transform_cocycle_inv(w, c, cinv, mat, tau, prec); acb_theta_g2_chi8_6(s, w, prec); acb_theta_g2_detk_symj(s, cinv, s, 8, 6, prec); if (!acb_poly_overlaps(r, s)) { flint_printf("FAIL\n"); acb_mat_printd(tau, 5); fmpz_mat_print_pretty(mat); flint_printf("values at tau, m*tau:\n"); acb_poly_printd(r, 10); flint_printf("\n"); acb_poly_printd(s, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); acb_mat_clear(tau); acb_mat_clear(w); acb_mat_clear(c); acb_mat_clear(cinv); acb_poly_clear(r); acb_poly_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_chi5.c000066400000000000000000000027651461254215100201520ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_chi5, state) { slong iter; /* Test: square is chi10 */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 2; slong n2 = 1 << (2 * g); slong prec = 100 + n_randint(state, 500); slong mag_bits = n_randint(state, 10); acb_ptr th; slong k; acb_t r, s; th = _acb_vec_init(n2); acb_init(r); acb_init(s); for (k = 0; k < n2; k++) { acb_randtest_precise(&th[k], state, prec, mag_bits); } acb_theta_g2_chi5(r, th, prec); acb_sqr(r, r, prec); _acb_vec_sqr(th, th, n2, prec); acb_theta_g2_chi10(s, th, prec); if (!acb_overlaps(r, s)) { flint_printf("FAIL\n"); acb_printd(r, 10); flint_printf("\n"); acb_printd(s, 10); flint_printf("\n"); flint_abort(); } _acb_vec_clear(th, n2); acb_clear(r); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_covariants.c000066400000000000000000000116611461254215100214660ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" #define ACB_THETA_G2_COV_K {1,2,2,2,3,3,3,3,4,4,4,4,5,5,5,6,6,6,7,7,8,9,10,10,12,15} #define ACB_THETA_G2_COV_J {6,0,4,8,2,6,8,12,0,4,6,10,2,4,8,0,6,6,2,4,2,4,0,2,2,0} TEST_FUNCTION_START(acb_theta_g2_covariants, state) { slong iter; /* Test: - agrees with g2_psi4 using psi4 = -(Co20 - 3*Co40)/20 - covariants transform as det^(k-j/2)Sym^j - covariants take integral values on integral polynomials */ for (iter = 0; iter < 5 * flint_test_multiplier(); iter++) { slong prec = 200 + n_randint(state, 200); slong g = 2; slong n = 1 << (2 * g); slong bits = 2; slong jlist[26] = ACB_THETA_G2_COV_J; slong klist[26] = ACB_THETA_G2_COV_K; fmpz_mat_t mat; acb_mat_t tau, w, c; acb_ptr z, th2; acb_poly_struct * cov1; acb_poly_struct * cov2; acb_poly_t u, v; fmpz_poly_t pol; acb_t psi4, test; slong k; fmpz_mat_init(mat, 2 * g, 2 * g); acb_mat_init(tau, g, g); acb_mat_init(w, g, g); acb_mat_init(c, g, g); z = _acb_vec_init(g); th2 = _acb_vec_init(n); cov1 = flint_malloc(26 * sizeof(acb_poly_struct)); cov2 = flint_malloc(26 * sizeof(acb_poly_struct)); for (k = 0; k < 26; k++) { acb_poly_init(&cov1[k]); acb_poly_init(&cov2[k]); } acb_poly_init(u); acb_poly_init(v); fmpz_poly_init(pol); acb_init(psi4); acb_init(test); acb_siegel_randtest_reduced(tau, state, prec, bits); sp2gz_randtest(mat, state, bits); acb_theta_all(th2, z, tau, 1, prec); acb_theta_g2_psi4(psi4, th2, prec); acb_theta_g2_sextic(u, tau, prec); acb_theta_g2_covariants(cov1, u, prec); acb_siegel_transform(w, mat, tau, prec); acb_siegel_cocycle(c, mat, tau, prec); acb_theta_g2_sextic(u, w, prec); acb_theta_g2_covariants(cov2, u, prec); /* Test psi4 */ acb_poly_set_si(u, -3); acb_poly_mul(u, u, &cov1[8], prec); acb_poly_mul(v, &cov1[1], &cov1[1], prec); acb_poly_add(u, u, v, prec); acb_poly_get_coeff_acb(test, u, 0); acb_div_si(test, test, -20, prec); if (!acb_overlaps(psi4, test)) { flint_printf("FAIL (psi4)\n"); acb_mat_printd(tau, 5); flint_printf("psi4, test:\n"); acb_printd(psi4, 10); flint_printf("\n"); acb_printd(test, 10); flint_printf("\nu:\n"); acb_poly_printd(u, 5); flint_printf("\ncovariants:\n"); for (k = 0; k < 26; k++) { acb_poly_printd(&cov1[k], 5); flint_printf("\n"); } flint_abort(); } /* Test transformation */ for (k = 0; k < 26; k++) { acb_theta_g2_detk_symj(u, c, &cov1[k], klist[k] - jlist[k]/2, jlist[k], prec); if (!acb_poly_overlaps(u, &cov2[k])) { flint_printf("FAIL (transform, k = %wd)\n", k); acb_mat_printd(tau, 5); fmpz_mat_print_pretty(mat); flint_printf("\n"); acb_poly_printd(u, 5); flint_printf("\n"); acb_poly_printd(&cov2[k], 5); flint_printf("\n"); flint_abort(); } } /* Test integrality */ acb_poly_zero(u); for (k = 0; k <= 6; k++) { acb_poly_set_coeff_si(u, k, n_randint(state, 10)); } acb_theta_g2_covariants(cov1, u, prec); for (k = 0; k < 26; k++) { if (!acb_poly_get_unique_fmpz_poly(pol, &cov1[k])) { flint_printf("FAIL (integrality, k = %wd)\n", k); acb_poly_printd(&cov1[k], 5); flint_printf("\n"); flint_abort(); } } fmpz_mat_clear(mat); acb_mat_clear(tau); acb_mat_clear(w); acb_mat_clear(c); _acb_vec_clear(z, g); _acb_vec_clear(th2, n); for (k = 0; k < 26; k++) { acb_poly_clear(&cov1[k]); acb_poly_clear(&cov2[k]); } flint_free(cov1); flint_free(cov2); acb_poly_clear(u); acb_poly_clear(v); fmpz_poly_clear(pol); acb_clear(psi4); acb_clear(test); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_covariants_lead.c000066400000000000000000000041371461254215100224530ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_theta.h" #define ACB_THETA_G2_COV_J {6,0,4,8,2,6,8,12,0,4,6,10,2,4,8,0,6,6,2,4,2,4,0,2,2,0} TEST_FUNCTION_START(acb_theta_g2_covariants_lead, state) { slong iter; /* Test: agrees with g2_covariants */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong prec = 200 + n_randint(state, 100); slong bits = 2; slong nb = ACB_THETA_G2_COV_NB; slong jlist[] = ACB_THETA_G2_COV_J; acb_poly_struct * cov; acb_ptr res, test; acb_poly_t r; slong k; cov = flint_malloc(nb * sizeof(acb_poly_struct)); for (k = 0; k < nb; k++) { acb_poly_init(&cov[k]); } acb_poly_init(r); res = _acb_vec_init(nb); test = _acb_vec_init(nb); acb_poly_randtest(r, state, 7, prec, bits); acb_theta_g2_covariants(cov, r, prec); acb_theta_g2_covariants_lead(res, r, prec); for (k = 0; k < nb; k++) { acb_poly_get_coeff_acb(&test[k], &cov[k], jlist[k]); } if (!_acb_vec_overlaps(res, test, nb)) { flint_printf("FAIL\n"); _acb_vec_printd(res, nb, 5); _acb_vec_printd(test, nb, 5); flint_printf("\ncovariants:\n"); for (k = 0; k < nb; k++) { acb_poly_printd(&cov[k], 5); flint_printf("\n"); } flint_abort(); } for (k = 0; k < nb; k++) { acb_poly_clear(&cov[k]); } flint_free(cov); acb_poly_clear(r); _acb_vec_clear(res, nb); _acb_vec_clear(test, nb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_detk_symj.c000066400000000000000000000037771461254215100213170ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_detk_symj, state) { slong iter; /* Test: chain rule */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 2; acb_mat_t c1, c2, c3; acb_poly_t s, r, t; slong k = n_randint(state, 10); slong j = n_randint(state, 10); slong bits = 2; slong prec = 100 + n_randint(state, 200); acb_mat_init(c1, g, g); acb_mat_init(c2, g, g); acb_mat_init(c3, g, g); acb_poly_init(s); acb_poly_init(r); acb_poly_init(t); acb_mat_randtest(c1, state, prec, bits); acb_mat_randtest(c2, state, prec, bits); acb_mat_mul(c3, c1, c2, prec); acb_poly_randtest(s, state, j + 1, prec, bits); acb_theta_g2_detk_symj(r, c2, s, k, j, prec); acb_theta_g2_detk_symj(r, c1, r, k, j, prec); acb_theta_g2_detk_symj(t, c3, s, k, j, prec); if (!acb_poly_overlaps(t, r)) { flint_printf("FAIL\n"); acb_mat_printd(c1, 5); acb_mat_printd(c2, 5); flint_printf("source:\n"); acb_poly_printd(s, 5); flint_printf("\nvalues:\n"); acb_poly_printd(r, 5); flint_printf("\n"); acb_poly_printd(t, 5); flint_printf("\n"); flint_abort(); } acb_mat_clear(c1); acb_mat_clear(c2); acb_mat_clear(c3); acb_poly_clear(s); acb_poly_clear(r); acb_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_jet_naive_1.c000066400000000000000000000041461461254215100215010ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_jet_naive_1, state) { slong iter; /* Test: agrees with usual jet_naive at the right indices */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 2; slong n = 1 << (2 * g); slong nb = acb_theta_jet_nb(1, g + 1); slong prec = 100 + n_randint(state, 3000); slong bits = n_randint(state, 4); acb_mat_t tau; acb_ptr z, dth, test; slong k; int res; acb_mat_init(tau, g, g); z = _acb_vec_init(g); dth = _acb_vec_init(n * nb); test = _acb_vec_init(n * nb); acb_siegel_randtest_reduced(tau, state, prec, bits); if (iter % 10 == 0) { acb_zero(acb_mat_entry(tau, 0, 0)); } acb_theta_g2_jet_naive_1(dth, tau, prec); acb_theta_jet_naive_all(test, z, tau, 1, prec); for (k = 0; k < n; k++) { if (acb_theta_char_is_even(k, 2)) { res = acb_overlaps(&dth[3 * k], &test[3 * k]); } else { res = _acb_vec_overlaps(&dth[3 * k + 1], &test[3 * k + 1], 2); } if (!res) { flint_printf("FAIL (k = %wd)\n", k); acb_mat_printd(tau, 5); flint_printf("values:\n"); _acb_vec_printd(&dth[3 * k], 3, 5); _acb_vec_printd(&test[3 * k], 3, 5); flint_abort(); } } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(dth, n * nb); _acb_vec_clear(test, n * nb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_psi4.c000066400000000000000000000032331461254215100201700ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_psi4, state) { slong iter; /* Test: is a modular form */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 2; slong n2 = 16; slong prec = 100 + n_randint(state, 500); slong mag_bits = n_randint(state, 4); fmpz_mat_t mat; acb_ptr th2; acb_t r, s; slong k; fmpz_mat_init(mat, 2 * g, 2 * g); th2 = _acb_vec_init(n2); acb_init(r); acb_init(s); sp2gz_randtest(mat, state, mag_bits); for (k = 0; k < n2; k++) { acb_randtest_precise(&th2[k], state, prec, mag_bits); } acb_theta_g2_psi4(r, th2, prec); acb_theta_transform_proj(th2, mat, th2, 1, prec); acb_theta_g2_psi4(s, th2, prec); if (!acb_overlaps(r, s)) { flint_printf("FAIL\n"); fmpz_mat_print_pretty(mat); acb_printd(r, 10); flint_printf("\n"); acb_printd(s, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); _acb_vec_clear(th2, n2); acb_clear(r); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_psi6.c000066400000000000000000000034001461254215100201660ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_psi6, state) { slong iter; /* Test: is a modular form */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 2; slong n2 = 16; slong prec = 100 + n_randint(state, 500); slong mag_bits = n_randint(state, 2); fmpz_mat_t mat; acb_ptr th2; acb_t r, s; slong k; fmpz_mat_init(mat, 2 * g, 2 * g); th2 = _acb_vec_init(n2); acb_init(r); acb_init(s); sp2gz_randtest(mat, state, mag_bits); for (k = 0; k < n2; k++) { acb_randtest_precise(&th2[k], state, prec, mag_bits); } acb_theta_g2_psi6(r, th2, prec); acb_theta_transform_proj(th2, mat, th2, 1, prec); acb_theta_g2_psi6(s, th2, prec); if (acb_theta_transform_kappa2(mat) % 2 == 1) { acb_neg(s, s); } if (!acb_overlaps(r, s)) { flint_printf("FAIL\n"); fmpz_mat_print_pretty(mat); acb_printd(r, 10); flint_printf("\n"); acb_printd(s, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); _acb_vec_clear(th2, n2); acb_clear(r); acb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_sextic.c000066400000000000000000000051531461254215100206130ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_sextic, state) { slong iter; /* Test: discriminant of sextic is chi10 */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 2; slong n = 1 << (2 * g); slong prec = 100 + n_randint(state, 100); slong bits = n_randint(state, 4); acb_mat_t tau; acb_ptr z, th2, roots; acb_poly_t f; acb_t d, t; slong nb, k, j; if (iter % 20 == 0) { prec += 10000; /* necessary for full test coverage */ } acb_mat_init(tau, g, g); z = _acb_vec_init(g); th2 = _acb_vec_init(n); roots = _acb_vec_init(6); acb_poly_init(f); acb_init(d); acb_init(t); acb_siegel_randtest_reduced(tau, state, prec, bits); acb_mat_scalar_mul_2exp_si(tau, tau, -2); acb_theta_g2_sextic(f, tau, prec); nb = acb_poly_find_roots(roots, f, NULL, 0, prec); if (nb == 6) { acb_one(d); for (k = 0; k < 6; k++) { for (j = k + 1; j < 6; j++) { acb_sub(t, &roots[k], &roots[j], prec); acb_mul(d, d, t, prec); } } acb_sqr(d, d, prec); acb_poly_get_coeff_acb(t, f, 6); acb_pow_ui(t, t, 10, prec); acb_mul(d, d, t, prec); acb_mul_2exp_si(d, d, -12); acb_theta_all(th2, z, tau, 1, prec); acb_theta_g2_chi10(t, th2, prec); if (!acb_overlaps(d, t)) { flint_printf("FAIL\n"); flint_printf("roots, discr, chi10:\n"); _acb_vec_printd(roots, 6, 5); acb_printd(d, 5); flint_printf("\n"); acb_printd(t, 5); flint_printf("\n"); flint_abort(); } } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(th2, n); _acb_vec_clear(roots, 6); acb_poly_clear(f); acb_clear(d); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_sextic_chi5.c000066400000000000000000000041341461254215100215210ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_sextic_chi5, state) { slong iter; /* Test: agrees with sextic and chi5 */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 2; slong n = 1 << (2 * g); slong prec = 100 + n_randint(state, 100); slong bits = n_randint(state, 4); acb_mat_t tau; acb_ptr z, th; acb_poly_t s1, s2; acb_t c1, c2; acb_mat_init(tau, g, g); z = _acb_vec_init(g); th = _acb_vec_init(n); acb_poly_init(s1); acb_poly_init(s2); acb_init(c1); acb_init(c2); acb_siegel_randtest_reduced(tau, state, prec, bits); acb_mat_scalar_mul_2exp_si(tau, tau, -2); acb_theta_g2_sextic_chi5(s1, c1, tau, prec); acb_theta_g2_sextic(s2, tau, prec); if (!acb_poly_overlaps(s1, s2)) { flint_printf("FAIL (sextic)\n"); acb_poly_printd(s1, 5); flint_printf("\n"); acb_poly_printd(s2, 5); flint_printf("\n"); flint_abort(); } acb_theta_all(th, z, tau, 0, prec); acb_theta_g2_chi5(c2, th, prec); if (!acb_overlaps(c1, c2)) { flint_printf("FAIL (chi5)\n"); acb_printd(c1, 10); flint_printf("\n"); acb_printd(c2, 10); flint_printf("\n"); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(th, n); acb_poly_clear(s1); acb_poly_clear(s2); acb_clear(c1); acb_clear(c2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_transvectant.c000066400000000000000000000042671461254215100220350ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_transvectant, state) { slong iter; /* Test: (f,f)_6 = -3*a3^2 + 8*a2*a4 - 20*a1*a5 + 120*a0*a6 */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong prec = 200; slong bits = 2; acb_poly_t f, g; acb_t c, test; acb_poly_init(f); acb_poly_init(g); acb_init(c); acb_init(test); acb_poly_randtest(f, state, 6, prec, bits); acb_poly_set_coeff_si(f, 6, 1); acb_theta_g2_transvectant(g, f, f, 6, 6, 6, prec); if (acb_poly_degree(g) > 0) { flint_printf("FAIL (degree)\n"); acb_poly_printd(f, 5); flint_printf("\n"); acb_poly_printd(g, 5); flint_printf("\n"); flint_abort(); } acb_mul(c, acb_poly_get_coeff_ptr(f, 0), acb_poly_get_coeff_ptr(f, 6), prec); acb_addmul_si(test, c, 120, prec); acb_mul(c, acb_poly_get_coeff_ptr(f, 1), acb_poly_get_coeff_ptr(f, 5), prec); acb_addmul_si(test, c, -20, prec); acb_mul(c, acb_poly_get_coeff_ptr(f, 2), acb_poly_get_coeff_ptr(f, 4), prec); acb_addmul_si(test, c, 8, prec); acb_sqr(c, acb_poly_get_coeff_ptr(f, 3), prec); acb_addmul_si(test, c, -3, prec); acb_poly_get_coeff_acb(c, g, 0); acb_mul_si(c, c, 60, prec); if (!acb_overlaps(test, c)) { flint_printf("FAIL (value)\n"); acb_printd(test, 5); flint_printf("\n"); acb_printd(c, 5); flint_printf("\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_clear(c); acb_clear(test); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-g2_transvectant_lead.c000066400000000000000000000036641461254215100230220ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_poly.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_g2_transvectant_lead, state) { slong iter; /* Test: matches leading coefficient of g2_transvectant */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong prec = 200; slong bits = 2; acb_poly_t f, g, h; acb_t c, t; slong m = n_randint(state, 10); slong n = n_randint(state, 10); slong k = n_randint(state, FLINT_MIN(m, n) + 1); acb_poly_init(f); acb_poly_init(g); acb_poly_init(h); acb_init(c); acb_init(t); acb_poly_randtest(f, state, m, prec, bits); acb_poly_set_coeff_si(f, m, 1); acb_poly_randtest(g, state, n, prec, bits); acb_poly_set_coeff_si(g, n, 1); acb_theta_g2_transvectant(h, f, g, m, n, k, prec); acb_poly_get_coeff_acb(t, h, m + n - 2 * k); acb_theta_g2_transvectant_lead(c, f, g, m, n, k, prec); if (!acb_overlaps(c, t)) { flint_printf("FAIL\n"); flint_printf("m = %wd, n = %wd, k = %wd, f, g:\n", m, n, k); acb_poly_printd(f, 5); acb_poly_printd(g, 5); flint_printf("lead, test:\n"); acb_printd(c, 5); flint_printf("\n"); acb_printd(t, 5); flint_printf("\n"); flint_abort(); } acb_poly_clear(f); acb_poly_clear(g); acb_poly_clear(h); acb_clear(c); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_all.c000066400000000000000000000045041461254215100203350ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_all, state) { slong iter; /* Test: agrees with jet_naive_all */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 2); slong ord = n_randint(state, 3); slong nb = acb_theta_jet_nb(ord, g); slong n2 = 1 << (2 * g); slong prec = 100 + n_randint(state, 400); slong bits = n_randint(state, 4); acb_mat_t tau; acb_ptr z, dth, test; slong k; acb_mat_init(tau, g, g); z = _acb_vec_init(g); dth = _acb_vec_init(nb * n2); test = _acb_vec_init(nb * n2); /* Sample tau not too far from reduced domain */ acb_siegel_randtest_reduced(tau, state, prec, bits); acb_mat_scalar_mul_2exp_si(tau, tau, -1); acb_siegel_randtest_vec(z, state, g, prec); /* Sometimes phony input too */ if (n_randint(state, 20) == 0) { k = n_randint(state, g); arb_zero(acb_imagref(acb_mat_entry(tau, k, k))); } acb_theta_jet_all(dth, z, tau, ord, prec); acb_theta_jet_naive_all(test, z, tau, ord, prec); if (!_acb_vec_overlaps(dth, test, nb * n2)) { flint_printf("FAIL\n"); flint_printf("g = %wd, prec = %wd, ord = %wd, tau, z:\n", g, prec, ord); _acb_vec_printd(z, g, 5); acb_mat_printd(tau, 5); flint_printf("th, test:\n"); _acb_vec_printd(dth, nb * n2, 5); _acb_vec_printd(test, nb * n2, 5); flint_printf("difference:\n"); _acb_vec_sub(test, dth, test, nb * n2, prec); _acb_vec_printd(test, nb * n2, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(dth, nb * n2); _acb_vec_clear(test, nb * n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_compose.c000066400000000000000000000037541461254215100212400ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_compose, state) { slong iter; /* Test: chain rule */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong ord = n_randint(state, 4); slong nb = acb_theta_jet_nb(ord, g); slong prec = 200; slong mag_bits = 2; acb_mat_t N1, N2, N3; acb_ptr v1, v2, v3, test; slong k; acb_mat_init(N1, g, g); acb_mat_init(N2, g, g); acb_mat_init(N3, g, g); v1 = _acb_vec_init(nb); v2 = _acb_vec_init(nb); v3 = _acb_vec_init(nb); test = _acb_vec_init(nb); for (k = 0; k < nb; k++) { acb_randtest_precise(&v3[k], state, prec, mag_bits); } acb_mat_randtest(N1, state, prec, mag_bits); acb_mat_randtest(N2, state, prec, mag_bits); acb_mat_mul(N3, N2, N1, prec); acb_theta_jet_compose(v2, v3, N2, ord, prec); acb_theta_jet_compose(v1, v2, N1, ord, prec); acb_theta_jet_compose(test, v3, N3, ord, prec); if (!_acb_vec_overlaps(test, v1, nb)) { flint_printf("FAIL (g = %wd, ord = %wd)\n", g, ord); _acb_vec_printd(v3, nb, 5); _acb_vec_printd(test, nb, 5); flint_abort(); } acb_mat_clear(N1); acb_mat_clear(N2); acb_mat_clear(N3); _acb_vec_clear(v1, nb); _acb_vec_clear(v2, nb); _acb_vec_clear(v3, nb); _acb_vec_clear(test, nb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_error_bounds.c000066400000000000000000000110571461254215100222710ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_error_bounds, state) { slong iter; /* Test: compute theta values at two points in a common ball */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong n = 1 << (2 * g); slong ord = n_randint(state, 2); slong bits = 2; slong nb = acb_theta_jet_nb(ord, g); slong nb_der = acb_theta_jet_nb(ord + 2, g); slong lprec = ACB_THETA_LOW_PREC; slong mprec = ACB_THETA_LOW_PREC + n_randint(state, 50); slong hprec = mprec + n_randint(state, 50); acb_mat_t tau1, tau2, tau3; acb_ptr z1, z2, z3, dth; arb_ptr err; acb_ptr d1, d2, test; acb_t x; slong j, k; acb_mat_init(tau1, g, g); acb_mat_init(tau2, g, g); acb_mat_init(tau3, g, g); z1 = _acb_vec_init(g); z2 = _acb_vec_init(g); z3 = _acb_vec_init(g); dth = _acb_vec_init(n * nb_der); err = _arb_vec_init(n * nb); d1 = _acb_vec_init(n * nb); d2 = _acb_vec_init(n * nb); test = _acb_vec_init(n * nb); acb_init(x); acb_siegel_randtest_reduced(tau1, state, hprec, bits); acb_siegel_randtest_vec(z1, state, g, hprec); for (j = 0; j < g; j++) { for (k = j; k < g; k++) { acb_set(acb_mat_entry(tau1, k, j), acb_mat_entry(tau1, j, k)); acb_urandom(x, state, hprec); acb_mul_2exp_si(x, x, -mprec); acb_add(acb_mat_entry(tau2, j, k), acb_mat_entry(tau1, j, k), x, hprec); acb_set(acb_mat_entry(tau2, k, j), acb_mat_entry(tau2, j, k)); acb_union(acb_mat_entry(tau3, j, k), acb_mat_entry(tau1, j, k), acb_mat_entry(tau2, j, k), hprec); acb_set(acb_mat_entry(tau3, k, j), acb_mat_entry(tau3, j, k)); } acb_urandom(x, state, hprec); acb_mul_2exp_si(x, x, -mprec); acb_add(&z2[j], &z1[j], x, hprec); acb_union(&z3[j], &z1[j], &z2[j], hprec); } if (!acb_mat_contains(tau3, tau2) || !acb_mat_contains(tau3, tau1) || !_acb_vec_contains(z3, z1, g) || !_acb_vec_contains(z3, z1, g)) { flint_printf("FAIL (input)\n"); flint_printf("mprec = %wd, hprec = %wd\n", mprec, hprec); acb_mat_printd(tau1, 5); acb_mat_printd(tau2, 5); acb_mat_printd(tau3, 5); _acb_vec_printd(z1, g, 5); _acb_vec_printd(z2, g, 5); _acb_vec_printd(z3, g, 5); flint_abort(); } acb_theta_jet_naive_all(d1, z1, tau1, ord, hprec); acb_theta_jet_naive_all(d2, z2, tau2, ord, hprec); acb_theta_jet_naive_all(dth, z3, tau3, ord + 2, lprec); for (k = 0; k < n; k++) { acb_theta_jet_error_bounds(err + k * nb, z3, tau3, dth + k * nb_der, ord, lprec); } /* Errors are wrt midpoint, so multiply by 2 */ _arb_vec_scalar_mul_2exp_si(err, err, n * nb, 1); _acb_vec_set(test, d1, n * nb); for (k = 0; k < n * nb; k++) { acb_add_error_arb(&test[k], &err[k]); } if (!_acb_vec_overlaps(test, d2, n * nb)) { flint_printf("FAIL (bounds)\n"); flint_printf("values:\n"); _acb_vec_printd(d1, n * nb, 5); _acb_vec_printd(d2, n * nb, 5); flint_printf("bounds:\n"); _arb_vec_printd(err, n * nb, 5); flint_printf("difference:\n"); _acb_vec_sub(d1, d1, d2, n * nb, hprec); _acb_vec_printd(d1, n * nb, 5); flint_abort(); } acb_mat_clear(tau1); acb_mat_clear(tau2); acb_mat_clear(tau3); _acb_vec_clear(z1, g); _acb_vec_clear(z2, g); _acb_vec_clear(z3, g); _acb_vec_clear(dth, n * nb_der); _arb_vec_clear(err, n * nb); _acb_vec_clear(d1, n * nb); _acb_vec_clear(d2, n * nb); _acb_vec_clear(test, n * nb); acb_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_mul.c000066400000000000000000000051711461254215100203630ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_mul, state) { slong iter; /* Test: matches multiplication of fmpz_mpoly_t */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong ord = n_randint(state, 10); slong nb = acb_theta_jet_nb(ord, g); slong prec = 100; slong * tups; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t p1, p2, p3; fmpz_t c; acb_ptr v1, v2, v3; acb_t x; slong k, t; tups = flint_malloc(g * nb * sizeof(slong)); fmpz_mpoly_ctx_init(ctx, g, ORD_LEX); fmpz_mpoly_init(p1, ctx); fmpz_mpoly_init(p2, ctx); fmpz_mpoly_init(p3, ctx); fmpz_init(c); v1 = _acb_vec_init(nb); v2 = _acb_vec_init(nb); v3 = _acb_vec_init(nb); acb_init(x); acb_theta_jet_tuples(tups, ord, g); for (k = 0; k < nb; k++) { t = n_randint(state, 100); acb_set_si(&v1[k], t); fmpz_mpoly_set_coeff_si_ui(p1, t, (ulong *) tups + k * g, ctx); t = n_randint(state, 100); acb_set_si(&v2[k], t); fmpz_mpoly_set_coeff_si_ui(p2, t, (ulong *) tups + k * g, ctx); } acb_theta_jet_mul(v3, v1, v2, ord, g, prec); fmpz_mpoly_mul(p3, p1, p2, ctx); for (k = 0; k < nb; k++) { fmpz_mpoly_get_coeff_fmpz_ui(c, p3, (ulong *) tups + k * g, ctx); acb_set_fmpz(x, c); if (!acb_eq(x, &v3[k])) { flint_printf("FAIL\n"); flint_printf("g = %wd, ord = %wd, k = %wd, vectors:\n", g, ord, k); _acb_vec_printd(v1, nb, 5); _acb_vec_printd(v2, nb, 5); _acb_vec_printd(v3, nb, 5); flint_abort(); } } flint_free(tups); fmpz_mpoly_clear(p1, ctx); fmpz_mpoly_clear(p2, ctx); fmpz_mpoly_clear(p3, ctx); fmpz_mpoly_ctx_clear(ctx); fmpz_clear(c); _acb_vec_clear(v1, nb); _acb_vec_clear(v2, nb); _acb_vec_clear(v3, nb); acb_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_naive_00.c000066400000000000000000000036421461254215100211700ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_naive_00, state) { slong iter; /* Test: values match jet_naive_all */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong prec = ACB_THETA_LOW_PREC + n_randint(state, 100); slong bits = n_randint(state, 4); slong ord = n_randint(state, 3); slong g = 1 + n_randint(state, 3); slong n2 = 1 << (2 * g); slong nb = acb_theta_jet_nb(ord, g); acb_mat_t tau; acb_ptr z, dth, test; acb_mat_init(tau, g, g); z = _acb_vec_init(g); dth = _acb_vec_init(nb); test = _acb_vec_init(nb * n2); acb_siegel_randtest_reduced(tau, state, prec, bits); acb_siegel_randtest_vec(z, state, g, prec); acb_theta_jet_naive_00(dth, z, tau, ord, prec); acb_theta_jet_naive_all(test, z, tau, ord, prec); if (!_acb_vec_overlaps(dth, test, nb)) { flint_printf("FAIL (overlap)\n"); flint_printf("g = %wd, prec = %wd, ord = %wd\n", g, prec, ord); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("jet_naive_00:\n"); _acb_vec_printd(dth, nb, 5); flint_printf("jet_naive_all:\n"); _acb_vec_printd(test, nb, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(dth, nb); _acb_vec_clear(test, nb * n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_naive_all.c000066400000000000000000000064551461254215100215260ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_naive_all, state) { slong iter; /* Test: values match acb_modular_theta_jet on diagonal matrices */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 2 + n_randint(state, 2); slong mprec = ACB_THETA_LOW_PREC + n_randint(state, 100); slong prec = mprec + 50; slong bits = n_randint(state, 4); slong ord = n_randint(state, 3); slong n2 = 1 << (2 * g); slong nb = acb_theta_jet_nb(ord, g); acb_mat_t tau, tau11; acb_ptr z, dth, dth_g1, test; acb_t prod, t; slong * tups; slong k, j, l, ab; acb_mat_init(tau, g, g); acb_mat_init(tau11, 1, 1); z = _acb_vec_init(g); dth = _acb_vec_init(nb * n2); dth_g1 = _acb_vec_init((ord + 1) * g * 4); test = _acb_vec_init(nb * n2); acb_init(prod); acb_init(t); tups = flint_malloc(nb * g * sizeof(slong)); for (k = 0; k < g; k++) { acb_siegel_randtest_reduced(tau11, state, prec, bits); acb_set(acb_mat_entry(tau, k, k), acb_mat_entry(tau11, 0, 0)); } acb_siegel_randtest_vec(z, state, g, prec); acb_theta_jet_naive_all(dth, z, tau, ord, mprec); for (k = 0; k < g; k++) { acb_set(acb_mat_entry(tau11, 0, 0), acb_mat_entry(tau, k, k)); acb_theta_jet_naive_all(dth_g1 + k * (ord + 1) * 4, &z[k], tau11, ord, prec); } /* Make test vector using products of derivatives wrt each variable */ acb_theta_jet_tuples(tups, ord, g); for (j = 0; j < nb; j++) { for (k = 0; k < n2; k++) { acb_one(prod); for (l = 0; l < g; l++) { ab = 2 * ((k >> (2 * g - l - 1)) % 2) + ((k >> (g - l - 1)) % 2); acb_mul(prod, prod, &dth_g1[l * (ord + 1) * 4 + ab * (ord + 1) + tups[j * g + l]], prec); } acb_set(&test[k * nb + j], prod); } } if (!_acb_vec_overlaps(dth, test, n2 * nb)) { flint_printf("FAIL (overlap)\n"); flint_printf("g = %wd, prec = %wd, ord = %wd\n", g, prec, ord); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("jet_naive_all:\n"); _acb_vec_printd(dth, nb * n2, 5); flint_printf("test:\n"); _acb_vec_printd(test, nb * n2, 5); flint_abort(); } acb_mat_clear(tau); acb_mat_clear(tau11); _acb_vec_clear(z, g); _acb_vec_clear(dth, nb * n2); _acb_vec_clear(dth_g1, (ord + 1) * g * 4); _acb_vec_clear(test, nb * n2); acb_clear(prod); acb_clear(t); flint_free(tups); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_naive_fixed_ab.c000066400000000000000000000040031461254215100225020ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_naive_fixed_ab, state) { slong iter; /* Test: values match jet_naive_all */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong prec = ACB_THETA_LOW_PREC + n_randint(state, 100); slong bits = n_randint(state, 4); slong ord = n_randint(state, 2); slong g = 1 + n_randint(state, 3); slong n2 = 1 << (2 * g); ulong ab = n_randint(state, n2); slong nb = acb_theta_jet_nb(ord, g); acb_mat_t tau; acb_ptr z, dth, test; acb_mat_init(tau, g, g); z = _acb_vec_init(g); dth = _acb_vec_init(nb); test = _acb_vec_init(nb * n2); acb_siegel_randtest_reduced(tau, state, prec, bits); acb_siegel_randtest_vec(z, state, g, prec); acb_theta_jet_naive_fixed_ab(dth, ab, z, tau, ord, prec); acb_theta_jet_naive_all(test, z, tau, ord, prec); if (!_acb_vec_overlaps(dth, test + ab * nb, nb)) { flint_printf("FAIL (overlap)\n"); flint_printf("g = %wd, prec = %wd, ord = %wd, ab = %wd\n", g, prec, ord, ab); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("jet_naive_fixed_ab:\n"); _acb_vec_printd(dth, nb, 5); flint_printf("jet_naive_all:\n"); _acb_vec_printd(test + ab * nb, nb, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(dth, nb); _acb_vec_clear(test, nb * n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_naive_radius.c000066400000000000000000000074511461254215100222420ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_naive_radius, state) { slong iter; /* Test: sum of terms on border of ellipsoid must be less than bound */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong mprec = 50 + n_randint(state, 100); slong prec = mprec + 50; slong bits = n_randint(state, 4); slong ord = n_randint(state, 4); slong nb = acb_theta_jet_nb(ord, g); acb_theta_eld_t E; acb_mat_t tau; arb_mat_t C; arf_t R2, eps; acb_ptr z, new_z; arb_ptr v, a; acb_t c, term; arb_t u, abs, sum; slong nb_pts; slong * pts; slong * tups; slong j, k; int res; acb_mat_init(tau, g, g); arb_mat_init(C, g, g); arf_init(R2); arf_init(eps); acb_theta_eld_init(E, g, g); z = _acb_vec_init(g); new_z = _acb_vec_init(g); v = _arb_vec_init(g); a = _arb_vec_init(g); acb_init(c); acb_init(term); arb_init(u); arb_init(abs); arb_init(sum); tups = flint_malloc(g * nb * sizeof(slong)); acb_siegel_randtest_reduced(tau, state, prec, bits); for (k = 0; k < g; k++) { acb_randtest_precise(&z[k], state, prec, bits); } acb_siegel_cho(C, tau, prec); acb_theta_naive_reduce(v, new_z, a, c, u, z, 1, tau, prec); acb_theta_jet_naive_radius(R2, eps, C, v, ord, mprec); arb_mul_arf(u, u, eps, prec); /* Test: sum of terms on the border of ellipsoid is less than u */ res = acb_theta_eld_set(E, C, R2, v); if (!res) { flint_printf("FAIL (ellipsoid)\n"); flint_abort(); } nb_pts = acb_theta_eld_nb_border(E); pts = flint_malloc(g * nb_pts * sizeof(slong)); acb_theta_eld_border(pts, E); acb_theta_jet_tuples(tups, ord, g); for (j = 0; j < nb; j++) { arb_zero(sum); for (k = 0; k < nb_pts; k++) { acb_theta_naive_term(term, new_z, tau, tups + j * g, pts + k * g, prec); acb_abs(abs, term, prec); arb_add(sum, sum, abs, prec); } acb_abs(abs, c, prec); arb_mul(sum, sum, abs, prec); arb_sub(abs, sum, u, prec); if (arb_is_positive(abs)) { flint_printf("FAIL\n"); flint_printf("sum, bound:\n"); arb_printd(sum, 10); flint_printf("\n"); arb_printd(u, 10); flint_printf("\ntau:\n"); acb_mat_printd(tau, 5); flint_printf("z:\n"); _acb_vec_printd(z, g, 10); acb_theta_eld_print(E); flint_abort(); } } acb_mat_clear(tau); arb_mat_clear(C); arf_clear(R2); arf_clear(eps); acb_theta_eld_clear(E); _acb_vec_clear(z, g); _acb_vec_clear(new_z, g); _arb_vec_clear(v, g); _arb_vec_clear(a, g); acb_clear(c); acb_clear(term); arb_clear(u); arb_clear(abs); arb_clear(sum); flint_free(pts); flint_free(tups); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_ql_all.c000066400000000000000000000036161461254215100210340ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_ql_all, state) { slong iter; /* Test: matches jet_naive_all */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong prec = ACB_THETA_LOW_PREC + n_randint(state, 100); slong ord = n_randint(state, 3); slong g = 1 + n_randint(state, 2); slong n2 = 1 << (2 * g); slong nb = acb_theta_jet_nb(ord, g); slong bits = 6; acb_mat_t tau; acb_ptr z, dth, test; acb_mat_init(tau, g, g); z = _acb_vec_init(g); dth = _acb_vec_init(nb * n2); test = _acb_vec_init(nb * n2); acb_siegel_randtest_reduced(tau, state, prec, bits); acb_siegel_randtest_vec(z, state, g, prec); acb_theta_jet_ql_all(dth, z, tau, ord, prec); acb_theta_jet_naive_all(test, z, tau, ord, prec); if (!_acb_vec_overlaps(dth, test, nb * n2)) { flint_printf("FAIL (overlap)\n"); flint_printf("g = %wd, prec = %wd, ord = %wd\n", g, prec, ord); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("dth:\n"); _acb_vec_printd(dth, nb * n2, 5); flint_printf("test:\n"); _acb_vec_printd(test, nb * n2, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(dth, nb * n2); _acb_vec_clear(test, nb * n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_ql_bounds.c000066400000000000000000000055571461254215100215640ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_ql_bounds, state) { slong iter; /* Test: bounds are finite, theta values correctly bounded */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong lp = ACB_THETA_LOW_PREC; slong prec = lp + 100; slong bits = n_randint(state, 4); slong ord = 1 + n_randint(state, 10); slong g = 1 + n_randint(state, 3); slong n2 = 1 << (2 * g); acb_mat_t tau; acb_ptr z, x, th; arb_t c, rho, abs, t; slong k; acb_mat_init(tau, g, g); z = _acb_vec_init(g); x = _acb_vec_init(g); th = _acb_vec_init(n2); arb_init(c); arb_init(rho); arb_init(abs); arb_init(t); acb_siegel_randtest_reduced(tau, state, prec, bits); acb_mat_scalar_mul_2exp_si(tau, tau, -2); for (k = 0; k < g; k++) { acb_urandom(&z[k], state, prec); } acb_theta_jet_ql_bounds(c, rho, z, tau, ord); if (!arb_is_finite(rho) || !arb_is_finite(c)) { flint_printf("FAIL (infinite)\n"); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("c, rho:\n"); arb_printd(c, 10); flint_printf("\n"); arb_printd(rho, 10); flint_printf("\n"); flint_abort(); } for (k = 0; k < g; k++) { acb_urandom(&x[k], state, prec); } _acb_vec_scalar_mul_arb(x, x, g, rho, prec); _acb_vec_add(x, x, z, g, prec); acb_theta_naive_all(th, x, 1, tau, lp); arb_zero(abs); for (k = 0; k < n2; k++) { acb_abs(t, &th[k], lp); arb_max(abs, abs, t, lp); } if (arb_gt(abs, c)) { flint_printf("FAIL (bound)\n"); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("rho, c, abs:\n"); arb_printd(rho, 10); flint_printf("\n"); arb_printd(c, 10); flint_printf("\n"); arb_printd(abs, 10); flint_printf("\n"); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(x, g); _acb_vec_clear(th, n2); arb_clear(c); arb_clear(rho); arb_clear(abs); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_ql_finite_diff.c000066400000000000000000000065741461254215100225400ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "acb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_ql_finite_diff, state) { slong iter; /* Test: find correct coefficients for exp function */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong prec = 100 + n_randint(state, 1000); slong ord = n_randint(state, 4); slong g = 1 + n_randint(state, 4); slong b = ord + 1; slong nb_val = n_pow(b, g); slong nb_fd = acb_theta_jet_nb(ord, g); slong * tups; arb_t c, rho; arf_t eps, err; acb_ptr val, df, test; acb_t x, t; fmpz_t m; slong k, kk, j, i; tups = flint_malloc(g * nb_fd * sizeof(slong)); arb_init(c); arb_init(rho); arf_init(eps); arf_init(err); val = _acb_vec_init(nb_val); df = _acb_vec_init(nb_fd); test = _acb_vec_init(nb_fd); acb_init(x); acb_init(t); fmpz_init(m); /* Get c, rho, eps, err */ arb_one(rho); arb_set_si(c, g); arb_exp(c, c, prec); acb_theta_jet_ql_radius(eps, err, c, rho, ord, g, prec); /* Fill in values, apply jet_fd at 2*prec */ for (k = 0; k < nb_val; k++) { acb_zero(x); kk = k; for (j = 0; j < g; j++) { acb_unit_root(t, b, 2 * prec); acb_pow_ui(t, t, (kk % b), 2 * prec); acb_add(x, x, t, 2 * prec); kk = kk / b; } acb_zero(t); arb_set_arf(acb_realref(t), eps); acb_mul(x, x, t, 2 * prec); acb_exp(&val[k], x, 2 * prec); } acb_theta_jet_ql_finite_diff(df, eps, err, rho, val, ord, g, 2 * prec); /* Fill in test */ acb_theta_jet_tuples(tups, ord, g); for (j = 0; j < nb_fd; j++) { acb_one(x); for (i = 0; i < g; i++) { fmpz_fac_ui(m, tups[j * g + i]); acb_div_fmpz(x, x, m, prec); } acb_set(&test[j], x); } if (!_acb_vec_overlaps(df, test, nb_fd)) { flint_printf("FAIL\n"); flint_printf("g = %wd, ord = %wd, values:\n", g, ord); _acb_vec_printd(val, nb_val, 5); flint_printf("taylor coeffs:\n"); _acb_vec_printd(df, nb_fd, 5); flint_printf("test:\n"); _acb_vec_printd(test, nb_fd, 5); flint_printf("difference:\n"); _acb_vec_sub(test, test, df, nb_fd, prec); _acb_vec_printd(test, nb_fd, 5); flint_abort(); } flint_free(tups); arb_clear(c); arb_clear(rho); arf_clear(eps); arf_clear(err); _acb_vec_clear(val, nb_val); _acb_vec_clear(df, nb_fd); _acb_vec_clear(test, nb_fd); acb_clear(x); acb_clear(t); fmpz_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_ql_radius.c000066400000000000000000000046761461254215100215620ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_ql_radius, state) { slong iter; /* Test: inequalities are satisfied */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong prec = 100 + n_randint(state, 500); slong mag_bits = n_randint(state, 10); slong ord = n_randint(state, 10); slong g = n_randint(state, 10); arb_t c, rho, t, u; arf_t eps, err; arb_init(c); arb_init(rho); arb_init(t); arb_init(u); arf_init(eps); arf_init(err); arb_randtest_positive(c, state, prec, mag_bits); arb_randtest_positive(rho, state, prec, mag_bits); acb_theta_jet_ql_radius(eps, err, c, rho, ord, g, prec); arb_set_si(t, 2 * g); arb_root_ui(t, t, ord + 1, prec); arb_mul_arf(t, t, eps, prec); if (arb_gt(t, rho)) { flint_printf("FAIL (1st bound)\n"); flint_printf("c, rho, eps, err:\n"); arb_printd(c, 10); flint_printf("\n"); arb_printd(rho, 10); flint_printf("\n"); arf_printd(eps, 10); flint_printf("\n"); flint_abort(); } arb_set_arf(t, eps); arb_pow_ui(t, t, ord + 1, prec); arb_pow_ui(u, rho, 2 * ord + 1, prec); arb_div(t, t, u, prec); arb_mul(t, t, c, prec); arb_mul_si(t, t, 2 * g, prec); arb_sub_arf(t, t, err, prec); if (arb_is_positive(t)) { flint_printf("FAIL (2nd bound)\n"); flint_printf("c, rho, eps, err:\n"); arb_printd(c, 10); flint_printf("\n"); arb_printd(rho, 10); flint_printf("\n"); arf_printd(eps, 10); flint_printf("\n"); arf_printd(err, 10); flint_abort(); } arb_clear(c); arb_clear(rho); arb_clear(t); arb_clear(u); arf_clear(eps); arf_clear(err); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-jet_tuples.c000066400000000000000000000030351461254215100210770ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_jet_tuples, state) { slong iter; /* Test: get the right index */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 6); slong ord = n_randint(state, 6); slong nb = acb_theta_jet_nb(ord, g); slong * tups; slong i = n_randint(state, nb); slong test; slong j, k; tups = flint_malloc(nb * g * sizeof(slong)); acb_theta_jet_tuples(tups, ord, g); test = acb_theta_jet_index(tups + i * g, g); if (test != i) { flint_printf("FAIL\n"); flint_printf("g = %wd, ord = %wd, nb = %wd\n", g, ord, nb); flint_printf("tups:\n"); for (j = 0; j < nb; j++) { for (k = 0; k < g; k++) { flint_printf("%wd ", tups[j * g + k]); } flint_printf("\n"); } flint_printf("i = %wd, test = %wd\n", i, test); flint_abort(); } flint_free(tups); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-naive_00.c000066400000000000000000000042431461254215100203240ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_naive_00, state) { slong iter; /* Test: agrees with first entry of naive_0b */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong n = 1 << g; acb_mat_t tau; acb_ptr z; slong nbz = 1 + n_randint(state, 4); acb_ptr th, th_0b, test; slong prec1 = 100 + n_randint(state, 200); slong prec = prec1 + n_randint(state, 200); slong mag_bits = n_randint(state, 10); slong k; acb_mat_init(tau, g, g); z = _acb_vec_init(g * nbz); th = _acb_vec_init(nbz); th_0b = _acb_vec_init(n * nbz); test = _acb_vec_init(nbz); acb_siegel_randtest_reduced(tau, state, prec, mag_bits); acb_siegel_randtest_vec(z, state, g * nbz, prec); acb_theta_naive_00(th, z, nbz, tau, prec1); acb_theta_naive_0b(th_0b, z, nbz, tau, prec); for (k = 0; k < nbz; k++) { acb_set(&test[k], &th_0b[k * n]); } if (!_acb_vec_overlaps(th, test, nbz)) { flint_printf("FAIL: overlap\n"); flint_printf("g = %wd, prec1 = %wd, prec = %wd, nbz = %wd, tau:\n", g, prec1, prec, nbz); acb_mat_printd(tau, 5); flint_printf("z:\n"); _acb_vec_printd(z, g * nbz, 5); flint_printf("th, test:\n"); _acb_vec_printd(th, nbz, 5); _acb_vec_printd(test, nbz, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g * nbz); _acb_vec_clear(th, nbz); _acb_vec_clear(th_0b, n * nbz); _acb_vec_clear(test, nbz); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-naive_all.c000066400000000000000000000063571461254215100206650ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_naive_all, state) { slong iter; /* Test: agrees with built-in genus 1 on diagonal matrices */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 2 + n_randint(state, 2); slong nb = n_pow(2, 2 * g); slong prec1 = ACB_THETA_LOW_PREC + n_randint(state, 200); slong prec = prec1 + n_randint(state, 100); slong mag_bits = n_randint(state, 2); slong nbz = 1 + n_randint(state, 4); acb_mat_t tau, tau11; acb_ptr z, th, th_test, th_g1; slong k, j; ulong ab, a, b; acb_mat_init(tau, g, g); acb_mat_init(tau11, 1, 1); z = _acb_vec_init(g * nbz); th = _acb_vec_init(nb * nbz); th_test = _acb_vec_init(nb * nbz); th_g1 = _acb_vec_init(4 * g); for (k = 0; k < g; k++) { acb_siegel_randtest_reduced(tau11, state, prec, mag_bits); acb_set(acb_mat_entry(tau, k, k), acb_mat_entry(tau11, 0, 0)); } acb_siegel_randtest_vec(z, state, g * nbz, prec); acb_theta_naive_all(th, z, nbz, tau, prec1); for (j = 0; j < nbz; j++) { for (k = 0; k < g; k++) { acb_set(acb_mat_entry(tau11, 0, 0), acb_mat_entry(tau, k, k)); acb_theta_naive_all(&th_g1[4 * k], &z[j * g + k], 1, tau11, prec); } /* Could use a more efficient recursive algorithm here */ for (ab = 0; ab < n_pow(2, 2 * g); ab++) { a = ab >> g; b = ab; acb_one(&th_test[j * nb + ab]); for (k = g - 1; k >= 0; k--) { acb_mul(&th_test[j * nb + ab], &th_test[j * nb + ab], &th_g1[4 * k + 2 * (a % 2) + (b % 2)], prec); a = a >> 1; b = b >> 1; } } } if (!_acb_vec_overlaps(th, th_test, nb * nbz)) { flint_printf("FAIL: overlap\n"); flint_printf("g = %wd, prec = %wd, nbz = %wd, tau:\n", g, prec, nbz); acb_mat_printd(tau, 10); flint_printf("z:\n"); _acb_vec_printd(z, g * nbz, 10); flint_printf("th, th_test:\n"); _acb_vec_printd(th, nb * nbz, 10); _acb_vec_printd(th_test, nb * nbz, 10); flint_printf("difference:\n"); _acb_vec_sub(th_test, th_test, th, nb * nbz, prec); _acb_vec_printd(th_test, nb * nbz, 10); flint_abort(); } acb_mat_clear(tau); acb_mat_clear(tau11); _acb_vec_clear(z, g * nbz); _acb_vec_clear(th, nb * nbz); _acb_vec_clear(th_test, nb * nbz); _acb_vec_clear(th_g1, 4 * g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-naive_fixed_a.c000066400000000000000000000046271461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_naive_fixed_a, state) { slong iter; /* Test: agrees with naive_all */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong n = 1 << g; slong nbz = 1 + n_randint(state, 2); acb_mat_t tau; acb_ptr z; acb_ptr th, th_all, th_test; slong prec = 20 + n_randint(state, 100); slong mag_bits = n_randint(state, 2); slong k, a; acb_mat_init(tau, g, g); z = _acb_vec_init(g * nbz); th = _acb_vec_init(n * nbz); th_all = _acb_vec_init(n * n * nbz); th_test = _acb_vec_init(n * nbz); acb_siegel_randtest_reduced(tau, state, prec, mag_bits); acb_siegel_randtest_vec(z, state, g * nbz, prec); acb_theta_naive_all(th_all, z, nbz, tau, prec); for (a = 0; a < n; a++) { acb_theta_naive_fixed_a(th, a, z, nbz, tau, prec); for (k = 0; k < nbz; k++) { _acb_vec_set(th_test + k * n, th_all + k * n * n + a * n, n); } if (!_acb_vec_overlaps(th, th_test, n * nbz)) { flint_printf("FAIL\n"); flint_printf("g = %wd, prec = %wd, nbz = %wd, a = %wd, tau:\n", g, prec, nbz, a); acb_mat_printd(tau, 5); flint_printf("z:\n"); _acb_vec_printd(z, g * nbz, 10); flint_printf("th, th_test:\n"); _acb_vec_printd(th, n * nbz, 10); _acb_vec_printd(th_test, n * nbz, 10); flint_printf("th_all:\n"); _acb_vec_printd(th_all, n * n * nbz, 10); flint_abort(); } } acb_mat_clear(tau); _acb_vec_clear(z, g * nbz); _acb_vec_clear(th, n * nbz); _acb_vec_clear(th_all, n * n * nbz); _acb_vec_clear(th_test, n * nbz); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-naive_fixed_ab.c000066400000000000000000000046271461254215100216540ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_naive_fixed_ab, state) { slong iter; /* Test: agrees with naive_all */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong nb = n_pow(2, g); slong nbz = 1 + n_randint(state, 2); acb_mat_t tau; acb_ptr z; acb_ptr th, th_all, th_test; slong prec = 20 + n_randint(state, 100); slong mag_bits = n_randint(state, 2); ulong ab; slong k; acb_mat_init(tau, g, g); z = _acb_vec_init(g * nbz); th = _acb_vec_init(nbz); th_all = _acb_vec_init(nb * nb * nbz); th_test = _acb_vec_init(nbz); acb_siegel_randtest_reduced(tau, state, prec, mag_bits); acb_siegel_randtest_vec(z, state, g * nbz, prec); acb_theta_naive_all(th_all, z, nbz, tau, prec); for (ab = 0; ab < nb * nb; ab++) { acb_theta_naive_fixed_ab(th, ab, z, nbz, tau, prec); for (k = 0; k < nbz; k++) { acb_set(&th_test[k], &th_all[k * nb * nb + ab]); } if (!_acb_vec_overlaps(th, th_test, nbz)) { flint_printf("FAIL\n"); flint_printf("g = %wd, prec = %wd, nbz = %wd, ab = %wd, tau:\n", g, prec, nbz, ab); acb_mat_printd(tau, 5); flint_printf("z:\n"); _acb_vec_printd(z, g * nbz, 10); flint_printf("th, th_test:\n"); _acb_vec_printd(th, nbz, 10); _acb_vec_printd(th_test, nbz, 10); flint_printf("th_all:\n"); _acb_vec_printd(th_all, nb * nb * nbz, 10); flint_abort(); } } acb_mat_clear(tau); _acb_vec_clear(z, g * nbz); _acb_vec_clear(th, nbz); _acb_vec_clear(th_all, nb * nb * nbz); _acb_vec_clear(th_test, nbz); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-naive_radius.c000066400000000000000000000070571461254215100214020ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_naive_radius, state) { slong iter; /* Test: sum of terms on border of ellipsoid must be less than bound */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong mprec = 50 + n_randint(state, 100); slong prec = mprec + 50; slong bits = n_randint(state, 4); acb_theta_eld_t E; acb_mat_t tau; arb_mat_t C; arf_t R2, eps; acb_ptr z, new_z; arb_ptr v, a; acb_t c, term; arb_t u, abs, sum; slong nb_pts; slong * pts; slong k; int res; acb_mat_init(tau, g, g); arb_mat_init(C, g, g); arf_init(R2); arf_init(eps); acb_theta_eld_init(E, g, g); z = _acb_vec_init(g); new_z = _acb_vec_init(g); v = _arb_vec_init(g); a = _arb_vec_init(g); acb_init(c); arb_init(u); acb_init(term); arb_init(abs); arb_init(sum); acb_siegel_randtest_reduced(tau, state, prec, bits); for (k = 0; k < g; k++) { acb_randtest_precise(&z[k], state, prec, bits); } acb_siegel_cho(C, tau, prec); acb_theta_naive_reduce(v, new_z, a, c, u, z, 1, tau, prec); acb_theta_naive_radius(R2, eps, C, 0, mprec); arb_mul_arf(u, u, eps, prec); /* Test: sum of terms on the border of ellipsoid is less than u */ res = acb_theta_eld_set(E, C, R2, v); if (!res) { flint_printf("FAIL (ellipsoid)\n"); acb_mat_printd(tau, 5); arb_mat_printd(C, 5); _acb_vec_printd(z, g, 5); _arb_vec_printd(v, g, 5); flint_abort(); } nb_pts = acb_theta_eld_nb_border(E); pts = flint_malloc(g * nb_pts * sizeof(slong)); acb_theta_eld_border(pts, E); arb_zero(sum); for (k = 0; k < nb_pts; k++) { acb_theta_naive_term(term, new_z, tau, NULL, pts + k * g, prec); acb_abs(abs, term, prec); arb_add(sum, sum, abs, prec); } acb_abs(abs, c, prec); arb_mul(sum, sum, abs, prec); arb_sub(abs, sum, u, prec); if (arb_is_positive(abs)) { flint_printf("FAIL\n"); flint_printf("sum, bound:\n"); arb_printd(sum, 10); flint_printf("\n"); arb_printd(u, 10); flint_printf("\ntau:\n"); acb_mat_printd(tau, 5); flint_printf("new_z:\n"); _acb_vec_printd(new_z, g, 10); acb_theta_eld_print(E); flint_abort(); } acb_mat_clear(tau); arb_mat_clear(C); arf_clear(R2); arf_clear(eps); acb_theta_eld_clear(E); _acb_vec_clear(z, g); _acb_vec_clear(new_z, g); _arb_vec_clear(v, g); _arb_vec_clear(a, g); acb_clear(c); arb_clear(u); acb_clear(term); arb_clear(abs); arb_clear(sum); flint_free(pts); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-naive_reduce.c000066400000000000000000000122301461254215100213470ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_naive_reduce, state) { slong iter; /* Test: special values of z */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 5); slong nbz = n_randint(state, 5); slong bits = n_randint(state, 5); slong prec = 100 + n_randint(state, 200); acb_mat_t tau; arb_mat_t Y, C; acb_ptr z, new_z, c; arb_ptr u, v, w, a; acb_t t, x; slong *n, *zero; slong err_exp = - 10 - n_randint(state, 20); slong k, j; int res; acb_mat_init(tau, g, g); arb_mat_init(Y, g, g); arb_mat_init(C, g, g); z = _acb_vec_init(g * nbz); new_z = _acb_vec_init(g * nbz); c = _acb_vec_init(nbz); u = _arb_vec_init(nbz); v = _arb_vec_init(g); w = _arb_vec_init(g * nbz); a = _arb_vec_init(g * nbz); acb_init(t); acb_init(x); n = flint_malloc(g * nbz * sizeof(slong)); zero = flint_malloc(g * sizeof(slong)); /* Set tau, cho, Y */ acb_siegel_randtest_reduced(tau, state, prec, bits); acb_siegel_cho(C, tau, prec); acb_mat_get_imag(Y, tau); /* Test: if z is real, c = 1, u = 1 and v = 0 */ for (k = 0; k < g * nbz; k++) { arb_randtest_precise(acb_realref(&z[k]), state, prec, bits); } acb_theta_naive_reduce(v, new_z, a, c, u, z, nbz, tau, prec); res = 1; for (k = 0; k < nbz; k++) { res = res && acb_is_one(&c[k]); res = res && arb_is_one(&u[k]); } if (!_arb_vec_is_zero(v, g) || !res) { flint_printf("FAIL\n"); flint_abort(); } /* Test: if im(z) = - Y . (even integral vector n) + small error, then terms for n and 0 correspond and v is small */ for (j = 0; j < g; j++) { zero[j] = 0; } for (k = 0; k < nbz; k++) { for (j = k * g; j < (k + 1) * g; j++) { n[j] = 2 * n_randint(state, 10); arb_set_si(&w[j], n[j]); } arb_mat_vector_mul_col(w + k * g, Y, w + k * g, prec); for (j = k * g; j < (k + 1) * g; j++) { arb_urandom(acb_imagref(&z[j]), state, prec); arb_mul_2exp_si(acb_imagref(&z[j]), acb_imagref(&z[j]), err_exp); arb_sub(acb_imagref(&z[j]), acb_imagref(&z[j]), &w[j], prec); } } acb_theta_naive_reduce(v, new_z, a, c, u, z, nbz, tau, prec); for (k = 0; k < g * nbz; k++) { if (!arb_equal_si(&a[k], -n[k])) { flint_printf("FAIL (integral vector)\n"); _arb_vec_printd(a, g * nbz, 5); flint_printf("k = %wd, n[k] = %wd\n", k, n[k]); flint_abort(); } } for (k = 0; k < nbz; k++) { acb_theta_naive_term(x, z + k * g, tau, NULL, n + k * g, prec); acb_theta_naive_term(t, new_z + k * g, tau, NULL, zero, prec); acb_mul(t, t, &c[k], prec); if (!acb_overlaps(x, t)) { flint_printf("FAIL (value, k = %wd)\n", k); flint_printf("tau:\n"); acb_mat_printd(tau, 10); flint_printf("z:\n"); _acb_vec_printd(z + k * g, g, 10); flint_printf("values:\n"); acb_printd(x, 10); flint_printf("\n"); acb_printd(t, 10); flint_printf("\n"); acb_printd(&c[k], 10); flint_printf("\nNew z:\n"); _acb_vec_printd(new_z + k * g, g, 10); flint_abort(); } } arb_mat_inv(C, C, prec); arb_mat_vector_mul_col(v, C, v, prec); for (k = 0; k < g; k++) { arb_mul_2exp_si(&v[k], &v[k], - err_exp - 2); arb_sub_si(&v[k], &v[k], 1, prec); if (!arb_is_negative(&v[k])) { flint_printf("FAIL (offset)\n"); arb_printd(&v[k], 10); flint_printf("\n"); flint_abort(); } } acb_mat_clear(tau); arb_mat_clear(Y); arb_mat_clear(C); _acb_vec_clear(z, g * nbz); _acb_vec_clear(new_z, g * nbz); _acb_vec_clear(c, nbz); _arb_vec_clear(u, nbz); _arb_vec_clear(v, g); _arb_vec_clear(w, g * nbz); _arb_vec_clear(a, g * nbz); acb_clear(t); acb_clear(x); flint_free(n); flint_free(zero); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-naive_term.c000066400000000000000000000033021461254215100210470ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_naive_term, state) { slong iter; /* Test: agrees with genus 1 */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong g = 1; slong prec = 100 + n_randint(state, 200); slong bits = n_randint(state, 5); slong n = n_randint(state, 100); slong k = n_randint(state, 10); acb_mat_t tau; acb_t z; acb_t x, t; fmpz_t m; acb_mat_init(tau, g, g); acb_init(z); acb_init(x); acb_init(t); fmpz_init(m); acb_siegel_randtest(tau, state, prec, bits); acb_randtest_precise(z, state, prec, bits); acb_theta_naive_term(x, z, tau, &k, &n, prec); acb_mul_si(t, acb_mat_entry(tau, 0, 0), n, prec); acb_addmul_si(t, z, 2, prec); acb_mul_si(t, t, n, prec); acb_exp_pi_i(t, t, prec); fmpz_set_si(m, n); fmpz_pow_ui(m, m, k); acb_mul_fmpz(t, t, m, prec); if (!acb_overlaps(x, t)) { flint_printf("FAIL\n"); flint_abort(); } acb_mat_clear(tau); acb_clear(z); acb_clear(x); acb_clear(t); fmpz_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-ql_a0.c000066400000000000000000000060121461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_ql_a0, state) { slong iter; /* Test: agrees with ql_a0_naive */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong n = 1 << g; slong prec = (g > 1 ? 200 : 500) + n_randint(state, 500); slong bits = n_randint(state, 5); slong hprec = prec + 100; int hast = iter % 2; int hasz = (iter % 4) / 2; slong nbt = (hast ? 3 : 1); slong nbz = (hasz ? 2 : 1); slong guard = ACB_THETA_LOW_PREC; slong lp = ACB_THETA_LOW_PREC; acb_mat_t tau; acb_ptr z, t, r, test; arb_ptr d, d0; arb_t y; slong k; int res; acb_mat_init(tau, g, g); z = _acb_vec_init(g); t = _acb_vec_init(g); r = _acb_vec_init(nbz * nbt * n); test = _acb_vec_init(nbz * nbt * n); d = _arb_vec_init(n); d0 = _arb_vec_init(n); arb_init(y); res = 0; while(!res) { acb_siegel_randtest_reduced(tau, state, prec, bits); arb_sub_si(y, acb_imagref(acb_mat_entry(tau, g - 1, g - 1)), 200, prec); res = arb_is_negative(y); } if (hast) { for (k = 0; k < g; k++) { arb_urandom(acb_realref(&t[k]), state, hprec); } } acb_theta_dist_a0(d0, z, tau, lp); if (hasz) { acb_siegel_randtest_vec(z, state, g, prec); } acb_theta_dist_a0(d, z, tau, lp); res = acb_theta_ql_a0(r, t, z, d0, d, tau, guard, prec); acb_theta_ql_a0_naive(test, t, z, d0, d, tau, guard, hprec); if (res && !_acb_vec_overlaps(r, test, nbz * nbt * n)) { flint_printf("FAIL\n"); flint_printf("g = %wd, prec = %wd, hprec = %wd, hasz = %wd, hast = %wd, tau:\n", g, prec, hprec, hasz, hast); acb_mat_printd(tau, 5); flint_printf("output:\n"); _acb_vec_printd(r, nbz * nbt * n, 5); _acb_vec_printd(test, nbz * nbt * n, 5); flint_printf("difference:\n"); _acb_vec_sub(r, r, test, nbz * nbt * n, hprec); _acb_vec_printd(r, nbz * nbt * n, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(t, g); _acb_vec_clear(r, nbz * nbt * n); _acb_vec_clear(test, nbz * nbt * n); _arb_vec_clear(d, n); _arb_vec_clear(d0, n); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-ql_a0_split.c000066400000000000000000000054631461254215100211370ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_ql_a0_split, state) { slong iter; /* Test: agrees with ql_a0_naive using ql_a0_naive as worker */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 2 + n_randint(state, 2); slong n = 1 << g; slong s = 1 + n_randint(state, g - 1); int hast = iter % 2; slong nbt = (hast ? 3 : 1); slong prec = 50 + n_randint(state, 50); slong hprec = prec + 25; slong guard = 0; slong lp = ACB_THETA_LOW_PREC; slong bits = n_randint(state, 4); acb_mat_t tau; acb_ptr z, t, r, test; arb_ptr d, d0; slong k; int res; acb_mat_init(tau, g, g); z = _acb_vec_init(g); t = _acb_vec_init(g); r = _acb_vec_init(nbt * n); test = _acb_vec_init(2 * nbt * n); d = _arb_vec_init(n); d0 = _arb_vec_init(n); acb_siegel_randtest_reduced(tau, state, hprec, bits); acb_siegel_randtest_vec(z, state, g, hprec); if (hast) { for (k = 0; k < g; k++) { arb_urandom(acb_realref(&t[k]), state, hprec); } } acb_theta_dist_a0(d0, t, tau, lp); acb_theta_dist_a0(d, z, tau, lp); res = acb_theta_ql_a0_split(r, t, z, d, tau, s, guard, prec, &acb_theta_ql_a0_naive); acb_theta_ql_a0_naive(test, t, z, d0, d, tau, guard, hprec); if (!_acb_vec_is_zero(z, g)) { _acb_vec_set(test, test + nbt * n, nbt * n); } if (res && !_acb_vec_overlaps(r, test, nbt * n)) { flint_printf("FAIL\n"); flint_printf("g = %wd, s = %wd, prec = %wd, tau, z:\n", g, s, prec); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("output:\n"); _acb_vec_printd(r, nbt * n, 5); _acb_vec_printd(test, nbt * n, 5); flint_printf("difference:\n"); _acb_vec_sub(test, test, r, nbt * n, prec); _acb_vec_printd(test, nbt * n, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(t, g); _acb_vec_clear(r, nbt * n); _acb_vec_clear(test, 2 * nbt * n); _arb_vec_clear(d, n); _arb_vec_clear(d0, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-ql_a0_steps.c000066400000000000000000000054321461254215100211360ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_ql_a0_steps, state) { slong iter; /* Test: agrees with ql_a0_naive using ql_a0_naive as worker */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 2 + n_randint(state, 2); slong n = 1 << g; slong s = 1 + n_randint(state, g - 1); slong nb_steps = n_randint(state, 5); slong bits = n_randint(state, 4); int hast = iter % 2; int hasz = (iter % 4) / 2; slong nbt = (hast ? 3 : 1); slong nbz = (hasz ? 2 : 1); slong prec = 200 + n_randint(state, 500); slong hprec = prec + 50; slong guard = ACB_THETA_LOW_PREC; slong lp = ACB_THETA_LOW_PREC; acb_mat_t tau; acb_ptr z, t, r, test; arb_ptr d, d0; slong k; int res; acb_mat_init(tau, g, g); z = _acb_vec_init(g); t = _acb_vec_init(g); r = _acb_vec_init(nbz * nbt * n); test = _acb_vec_init(nbz * nbt * n); d = _arb_vec_init(n); d0 = _arb_vec_init(n); acb_siegel_randtest_reduced(tau, state, hprec, bits); if (hast) { for (k = 0; k < g; k++) { arb_urandom(acb_realref(&t[k]), state, hprec); } } if (hasz) { acb_siegel_randtest_vec(z, state, g, prec); } acb_theta_dist_a0(d0, t, tau, lp); acb_theta_dist_a0(d, z, tau, lp); res = acb_theta_ql_a0_steps(r, t, z, d0, d, tau, nb_steps, s, guard, prec, &acb_theta_ql_a0_naive); acb_theta_ql_a0_naive(test, t, z, d0, d, tau, guard, hprec); if (res && !_acb_vec_overlaps(r, test, nbz * nbt * n)) { flint_printf("FAIL\n"); flint_printf("g = %wd, prec = %wd, s = %wd, hasz = %wd, hast = %wd, tau:\n", g, prec, s, hasz, hast); acb_mat_printd(tau, 5); flint_printf("output:\n"); _acb_vec_printd(r, nbz * nbt * n, 5); _acb_vec_printd(test, nbz * nbt * n, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(t, g); _acb_vec_clear(r, nbz * nbt * n); _acb_vec_clear(test, nbz * nbt * n); _arb_vec_clear(d, n); _arb_vec_clear(d0, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-ql_all.c000066400000000000000000000037361461254215100201750ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_ql_all, state) { slong iter; /* Test: agrees with naive_all */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong n = 1 << g; int hasz = iter % 2; int sqr = iter % 3; slong prec = (g > 1 ? 100 : 1000) + n_randint(state, 200); slong hprec = prec + 25; slong bits = 6; acb_mat_t tau; acb_ptr z, th, test; acb_mat_init(tau, g, g); z = _acb_vec_init(g); th = _acb_vec_init(n * n); test = _acb_vec_init(n * n); acb_siegel_randtest_reduced(tau, state, hprec, bits); if (hasz) { acb_siegel_randtest_vec(z, state, g, prec); } acb_theta_ql_all(th, z, tau, sqr, prec); acb_theta_naive_all(test, z, 1, tau, hprec); if (sqr) { _acb_vec_sqr(test, test, n * n, prec); } if (!_acb_vec_overlaps(th, test, n * n)) { flint_printf("FAIL\n"); flint_printf("g = %wd, prec = %wd, hasz = %wd, tau, z:\n", g, prec, hasz); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("output:\n"); _acb_vec_printd(th, n * n, 5); _acb_vec_printd(test, n * n, 5); flint_abort(); } acb_mat_clear(tau); _acb_vec_clear(z, g); _acb_vec_clear(th, n * n); _acb_vec_clear(test, n * n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-ql_reduce.c000066400000000000000000000113701461254215100206650ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_ql_reduce, state) { slong iter; /* Test: agrees with naive algorithms */ for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { slong g = 2 + n_randint(state, 2); slong n = 1 << g; slong prec = ACB_THETA_LOW_PREC + n_randint(state, 100); slong bits = 6; acb_mat_t tau, tau0; arb_mat_t Y; acb_ptr z, new_z, th, th0, test; arb_ptr x; acb_t c; arb_t u, abs; ulong a0, a1, b0, b1, fixed_a1; slong * n1; slong k, s; acb_mat_init(tau, g, g); arb_mat_init(Y, g, g); z = _acb_vec_init(g); new_z = _acb_vec_init(g); th = _acb_vec_init(n * n); th0 = _acb_vec_init(n * n); test = _acb_vec_init(n * n); x = _arb_vec_init(g); acb_init(c); arb_init(u); arb_init(abs); n1 = flint_malloc(g * sizeof(slong)); acb_siegel_randtest_reduced(tau, state, prec, bits); /* Choose z as Y.v + error with v either 0, 1/4 or 1/2 entries, or random values */ acb_mat_get_imag(Y, tau); for (k = 0; k < g; k++) { arb_set_si(&x[k], n_randint(state, 3)); } _arb_vec_scalar_mul_2exp_si(x, x, g, -2); arb_mat_vector_mul_col(x, Y, x, prec); if (iter % 2 == 0) { for (k = 0; k < g; k++) { acb_urandom(&z[k], state, prec); arb_add(acb_imagref(&z[k]), acb_imagref(&z[k]), &x[k], prec); } } else { acb_siegel_randtest_vec(z, state, g, prec); } s = acb_theta_ql_reduce(new_z, c, u, n1, z, tau, prec); acb_theta_naive_all(th, z, 1, tau, prec); /* If s == -1, check that theta values are small */ if (s == -1) { for (k = 0; k < n * n; k++) { acb_abs(abs, &th[k], prec); if (arb_gt(abs, u)) { flint_printf("FAIL (g = %wd, s = %wd)", g, s); acb_mat_printd(tau, 5); flint_printf("values, bound:\n"); _acb_vec_printd(th, n * n, 5); arb_printd(u, 5); flint_printf("\n"); flint_abort(); } } } /* Otherwise, construct test vector */ else { fixed_a1 = acb_theta_char_get_a(n1, g - s); if (s == 0) { acb_one(&th0[0]); } else { acb_mat_window_init(tau0, tau, 0, 0, s, s); acb_theta_naive_all(th0, new_z, 1, tau0, prec); acb_mat_window_clear(tau0); } for (k = 0; k < n * n; k++) { a0 = k >> (g + g - s); a1 = (k >> g) % (1 << (g - s)); b0 = (k >> (g - s)) % (1 << s); b1 = k % (1 << (g - s)); if (a1 == fixed_a1) { acb_mul(&test[k], c, &th0[(a0 << s) + b0], prec); acb_mul_i_pow_si(&test[k], &test[k], acb_theta_char_dot_slong(b1, n1, g - s)); } acb_add_error_arb(&test[k], u); } if (!_acb_vec_overlaps(th, test, n * n)) { flint_printf("FAIL (g = %wd, s = %wd)\n", g, s); flint_printf("tau, z:\n"); acb_mat_printd(tau, 5); _acb_vec_printd(z, g, 5); flint_printf("th, test:\n"); _acb_vec_printd(th, n * n, 5); _acb_vec_printd(test, n * n, 5); flint_printf("difference:\n"); _acb_vec_sub(test, test, th, n * n, prec); _acb_vec_printd(test, n * n, 5); flint_abort(); } } acb_mat_clear(tau); arb_mat_clear(Y); _acb_vec_clear(z, g); _acb_vec_clear(new_z, g); _acb_vec_clear(th, n * n); _acb_vec_clear(th0, n * n); _acb_vec_clear(test, n * n); _arb_vec_clear(x, g); acb_clear(c); arb_clear(u); arb_clear(abs); flint_free(n1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-siegel_cocycle.c000066400000000000000000000041711461254215100216740ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_siegel_cocycle, state) { slong iter; /* Test: chain rule */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 6); slong prec = 100 + n_randint(state, 200); slong mag_bits = n_randint(state, 10); fmpz_mat_t m1, m2, m3; acb_mat_t tau1, tau2; acb_mat_t c1, c2, c3, t; fmpz_mat_init(m1, 2 * g, 2 * g); fmpz_mat_init(m2, 2 * g, 2 * g); fmpz_mat_init(m3, 2 * g, 2 * g); acb_mat_init(tau1, g, g); acb_mat_init(tau2, g, g); acb_mat_init(c1, g, g); acb_mat_init(c2, g, g); acb_mat_init(c3, g, g); acb_mat_init(t, g, g); acb_siegel_randtest(tau1, state, prec, mag_bits); sp2gz_randtest(m1, state, mag_bits); sp2gz_randtest(m2, state, mag_bits); /* Test: chain rule */ acb_siegel_cocycle(c1, m1, tau1, prec); acb_siegel_transform(tau2, m1, tau1, prec); acb_siegel_cocycle(c2, m2, tau2, prec); fmpz_mat_mul(m3, m2, m1); acb_siegel_cocycle(c3, m3, tau1, prec); acb_mat_mul(t, c2, c1, prec); if (!acb_mat_overlaps(t, c3)) { flint_printf("FAIL\n\n"); acb_mat_printd(c3, 10); flint_printf("\n"); acb_mat_printd(t, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(m1); fmpz_mat_clear(m2); fmpz_mat_clear(m3); acb_mat_clear(tau1); acb_mat_clear(tau2); acb_mat_clear(c1); acb_mat_clear(c2); acb_mat_clear(c3); acb_mat_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-siegel_is_reduced.c000066400000000000000000000033651461254215100223650ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_siegel_is_reduced, state) { slong iter; /* Test: correct values on some matrices */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong prec = ACB_THETA_LOW_PREC; slong tol_exp = -10; slong j = n_randint(state, g); slong k = n_randint(state, g); acb_mat_t tau; acb_mat_init(tau, g, g); acb_mat_onei(tau); if (!acb_siegel_is_reduced(tau, tol_exp, prec)) { flint_printf("FAIL (1)\n"); acb_mat_printd(tau, 5); flint_abort(); } acb_add_si(acb_mat_entry(tau, j, k), acb_mat_entry(tau, j, k), 1, prec); acb_set(acb_mat_entry(tau, k, j), acb_mat_entry(tau, j, k)); if (acb_siegel_is_reduced(tau, tol_exp, prec)) { flint_printf("FAIL (2)\n"); acb_mat_printd(tau, 5); flint_abort(); } acb_mat_onei(tau); acb_mul_2exp_si(acb_mat_entry(tau, j, j), acb_mat_entry(tau, j, j), -1); if (acb_siegel_is_reduced(tau, tol_exp, prec)) { flint_printf("FAIL (3)\n"); acb_mat_printd(tau, 5); flint_abort(); } acb_mat_clear(tau); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-siegel_reduce.c000066400000000000000000000034671461254215100215310ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_siegel_reduce, state) { slong iter; /* Test: mat is symplectic and image passes acb_siegel_is_reduced */ for (iter = 0; iter < 50 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong prec = 100 + n_randint(state, 200); slong mag_bits = n_randint(state, 5); slong tol_exp = -10; int fail = iter % 10; acb_mat_t tau; acb_mat_t w; fmpz_mat_t mat; acb_mat_init(tau, g, g); acb_mat_init(w, g, g); fmpz_mat_init(mat, 2 * g, 2 * g); if (fail) { mag_bits = 100; } acb_siegel_randtest(tau, state, prec, mag_bits); acb_siegel_reduce(mat, tau, prec); if (!sp2gz_is_correct(mat)) { flint_printf("FAIL (symplectic)\n"); fmpz_mat_print(mat); flint_abort(); } acb_siegel_transform(w, mat, tau, prec); if (!fail && !acb_siegel_is_reduced(w, tol_exp, prec)) { flint_printf("FAIL (not reduced)\n"); acb_mat_printd(tau, 10); fmpz_mat_print_pretty(mat); flint_printf("\n"); acb_mat_printd(w, 10); flint_abort(); } acb_mat_clear(tau); acb_mat_clear(w); fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-siegel_transform.c000066400000000000000000000036271461254215100222730ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_siegel_transform, state) { slong iter; /* Test: chain rule */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 6); slong prec = 100 + n_randint(state, 200); slong mag_bits = n_randint(state, 10); fmpz_mat_t m1, m2, m3; acb_mat_t tau1, tau2, tau3, test; fmpz_mat_init(m1, 2 * g, 2 * g); fmpz_mat_init(m2, 2 * g, 2 * g); fmpz_mat_init(m3, 2 * g, 2 * g); acb_mat_init(tau1, g, g); acb_mat_init(tau2, g, g); acb_mat_init(tau3, g, g); acb_mat_init(test, g, g); acb_siegel_randtest(tau1, state, prec, mag_bits); sp2gz_randtest(m1, state, mag_bits); sp2gz_randtest(m2, state, mag_bits); acb_siegel_transform(tau2, m1, tau1, prec); acb_siegel_transform(tau3, m2, tau2, prec); fmpz_mat_mul(m3, m2, m1); acb_siegel_transform(test, m3, tau1, prec); if (!acb_mat_overlaps(test, tau3)) { flint_printf("FAIL\n\n"); acb_mat_printd(test, 10); flint_printf("\n"); acb_mat_printd(tau3, 10); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(m1); fmpz_mat_clear(m2); fmpz_mat_clear(m3); acb_mat_clear(tau1); acb_mat_clear(tau2); acb_mat_clear(tau3); acb_mat_clear(test); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-siegel_transform_z.c000066400000000000000000000047461461254215100226270ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_mat.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_siegel_transform_z, state) { slong iter; /* Test: matches siegel_transform, inverse matrix gives inverse transformation */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 6); slong prec = 100 + n_randint(state, 200); slong bits = n_randint(state, 10); acb_mat_t tau1, w, tau2; acb_ptr z1, r, z2; fmpz_mat_t m; acb_mat_init(tau1, g, g); acb_mat_init(w, g, g); acb_mat_init(tau2, g, g); z1 = _acb_vec_init(g); r = _acb_vec_init(g); z2 = _acb_vec_init(g); fmpz_mat_init(m, 2 * g, 2 * g); acb_siegel_randtest(tau1, state, prec, bits); acb_siegel_randtest_vec(z1, state, g, prec); sp2gz_randtest(m, state, bits); acb_siegel_transform_z(r, w, m, z1, tau1, prec); /* Test: agrees with transform */ acb_siegel_transform(tau2, m, tau1, prec); if (!acb_mat_overlaps(tau2, w)) { flint_printf("FAIL (transform)\n\n"); acb_mat_printd(w, 10); flint_printf("\n"); acb_mat_printd(tau2, 10); flint_printf("\n"); flint_abort(); } /* Test: inverse transformation */ sp2gz_inv(m, m); acb_siegel_transform_z(z2, tau2, m, r, w, prec); if (!acb_mat_contains(tau2, tau1) || !_acb_vec_contains(z2, z1, g)) { flint_printf("FAIL (inverse)\n\n"); acb_mat_printd(tau1, 10); flint_printf("\n"); acb_mat_printd(tau2, 10); flint_printf("\n\n"); _acb_vec_printd(z1, g, 10); flint_printf("\n\n"); _acb_vec_printd(z2, g, 10); flint_printf("\n"); flint_abort(); } acb_mat_clear(tau1); acb_mat_clear(w); acb_mat_clear(tau2); _acb_vec_clear(z1, g); _acb_vec_clear(r, g); _acb_vec_clear(z2, g); fmpz_mat_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-sp2gz_decompose.c000066400000000000000000000070531461254215100220300ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" static int sp2gz_comes_from_g1(const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t x, y; slong k, l; int res = 0; fmpz_mat_init(x, 2, 2); fmpz_mat_init(y, 2 * g, 2 * g); for (k = 0; k < 2; k++) { for (l = 0; l < 2; l++) { fmpz_set(fmpz_mat_entry(x, k, l), fmpz_mat_entry(mat, k * g, l * g)); } } if (sp2gz_is_correct(x)) { sp2gz_embed(y, x); res = fmpz_mat_equal(mat, y); } fmpz_mat_clear(x); fmpz_mat_clear(y); return res; } static int sp2gz_is_allowed_in_dec(const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t alpha, beta, gamma, x, y; slong r; int res; if (g == 1 || sp2gz_comes_from_g1(mat)) { return 1; } fmpz_mat_window_init(alpha, mat, 0, 0, g, g); fmpz_mat_window_init(beta, mat, 0, g, g, 2 * g); fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); fmpz_mat_init(x, 2 * g, 2 * g); if (!fmpz_mat_is_zero(gamma)) { r = fmpz_mat_rank(gamma); fmpz_mat_init(y, 2 * r, 2 * r); sp2gz_j(y); sp2gz_embed(x, y); fmpz_mat_clear(y); } else if (!fmpz_mat_is_zero(beta)) { sp2gz_trig(x, beta); } else { sp2gz_block_diag(x, alpha); } res = fmpz_mat_equal(mat, x); fmpz_mat_window_clear(alpha); fmpz_mat_window_clear(beta); fmpz_mat_window_clear(gamma); fmpz_mat_clear(x); return res; } TEST_FUNCTION_START(acb_theta_sp2gz_decompose, state) { slong iter; /* Test: decomposition consists of elementary matrices and product is the original matrix */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 2 + n_randint(state, 5); slong bits = n_randint(state, 20); fmpz_mat_t m, x; fmpz_mat_struct * dec = NULL; slong nb_dec = 0; slong k; fmpz_mat_init(m, 2 * g, 2 * g); fmpz_mat_init(x, 2 * g, 2 * g); sp2gz_randtest(m, state, bits); dec = sp2gz_decompose(&nb_dec, m); for (k = 0; k < nb_dec; k++) { if (!sp2gz_is_allowed_in_dec(&dec[k])) { flint_printf("FAIL (not elementary)\n"); fmpz_mat_print_pretty(&dec[k]); flint_printf("\n"); flint_abort(); } } fmpz_mat_one(x); for (k = 0; k < nb_dec; k++) { fmpz_mat_mul(x, x, &dec[k]); } if (!fmpz_mat_equal(m, x)) { flint_printf("FAIL (product)\n"); fmpz_mat_print_pretty(x); flint_printf("\n"); fmpz_mat_print_pretty(m); flint_printf("\ndecomposition in %wd matrices:\n", nb_dec); for (k = 0; k < nb_dec; k++) { fmpz_mat_print_pretty(&dec[k]); flint_printf("\n"); } flint_abort(); } fmpz_mat_clear(m); fmpz_mat_clear(x); for (k = 0; k < nb_dec; k++) { fmpz_mat_clear(&dec[k]); } flint_free(dec); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-sp2gz_inv.c000066400000000000000000000023171461254215100206440ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_sp2gz_inv, state) { slong iter; /* Test: matches fmpz_mat_inv */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 10); slong bits = n_randint(state, 10); fmpz_mat_t m1, m2; fmpz_t den; fmpz_mat_init(m1, 2 * g, 2 * g); fmpz_mat_init(m2, 2 * g, 2 * g); fmpz_init(den); sp2gz_randtest(m1, state, bits); sp2gz_inv(m2, m1); fmpz_mat_inv(m1, den, m1); if (!fmpz_mat_equal(m1, m2) || !fmpz_is_one(den)) { flint_printf("FAIL\n\n"); flint_abort(); } fmpz_mat_clear(m1); fmpz_mat_clear(m2); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-sp2gz_is_correct.c000066400000000000000000000041101461254215100221750ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_sp2gz_is_correct, state) { slong iter; /* Test: return 1 on various kinds of symplectic matrices; return 0 on non-square of even size */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 10); fmpz_mat_t a, b, m, n; slong r = n_randint(state, 10); slong c = n_randint(state, 10); slong bits = n_randint(state, 100); fmpz_mat_init(a, g, g); fmpz_mat_init(b, g, g); fmpz_mat_init(m, 2 * g, 2 * g); fmpz_mat_init(n, r, c); if (iter == 0) { sp2gz_j(m); } else if (iter <= sp2gz_nb_fundamental(g)) { sp2gz_fundamental(m, iter - 1); } else if (iter % 2 == 0) { fmpz_mat_one(a); fmpz_mat_randops(a, state, bits); sp2gz_block_diag(m, a); } else { fmpz_mat_randtest(a, state, bits); fmpz_mat_transpose(b, a); fmpz_mat_add(a, a, b); sp2gz_trig(m, a); } if (!sp2gz_is_correct(m)) { flint_printf("FAIL\n"); fmpz_mat_print_pretty(m); flint_printf("\n"); flint_abort(); } fmpz_mat_one(n); if ((r != c || r % 2 == 1) && sp2gz_is_correct(n)) { flint_printf("FAIL\n"); fmpz_mat_print_pretty(n); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(a); fmpz_mat_clear(b); fmpz_mat_clear(m); fmpz_mat_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-sp2gz_set_blocks.c000066400000000000000000000031371461254215100222010ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_sp2gz_set_blocks, state) { slong iter; /* Test: set_abcd is inverse of get_abcd */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 10); fmpz_mat_t a, b, c, d; fmpz_mat_t m, n; slong bits = n_randint(state, 10); fmpz_mat_init(m, 2 * g, 2 * g); fmpz_mat_init(n, 2 * g, 2 * g); sp2gz_randtest(m, state, bits); fmpz_mat_window_init(a, m, 0, 0, g, g); fmpz_mat_window_init(b, m, 0, g, g, 2 * g); fmpz_mat_window_init(c, m, g, 0, 2 * g, g); fmpz_mat_window_init(d, m, g, g, 2 * g, 2 * g); sp2gz_set_blocks(n, a, b, c, d); if (!fmpz_mat_equal(m, n)) { flint_printf("FAIL\n\n"); fmpz_mat_print_pretty(m); flint_printf("\n\n"); fmpz_mat_print_pretty(n); flint_abort(); flint_printf("\n\n"); } fmpz_mat_window_clear(a); fmpz_mat_window_clear(b); fmpz_mat_window_clear(c); fmpz_mat_window_clear(d); fmpz_mat_clear(m); fmpz_mat_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-transform_char.c000066400000000000000000000030011461254215100217220ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_transform_char, state) { slong iter; /* Test: on trigonal symplectic matrices, a remains the same */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 10); slong bits = 8; fmpz_mat_t mat; slong e; ulong ab = n_randint(state, 1 << (2 * g)); ulong test; slong j, k; fmpz_mat_init(mat, 2 * g, 2 * g); for (j = 0; j < g; j++) { for (k = j; k < g; k++) { fmpz_randtest(fmpz_mat_entry(mat, j, k), state, bits); fmpz_set(fmpz_mat_entry(mat, k, j), fmpz_mat_entry(mat, j, k)); } } sp2gz_trig(mat, mat); test = acb_theta_transform_char(&e, mat, ab); if ((test >> g) != (ab >> g)) { flint_printf("FAIL\n"); flint_printf("ab = %wd, test = %wd, matrix:\n", ab, test); fmpz_mat_print_pretty(mat); flint_abort(); } fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-transform_kappa.c000066400000000000000000000033111461254215100221050ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_transform_kappa, state) { slong iter; /* Test: kappa and kappa2 agree */ for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong bits = n_randint(state, 4); slong prec = 200; fmpz_mat_t mat; fmpz_mat_t x; acb_mat_t tau; acb_t sqrtdet; slong kappa, kappa2; fmpz_mat_init(mat, 2 * g, 2 * g); fmpz_mat_init(x, 2, 2); acb_mat_init(tau, g, g); acb_init(sqrtdet); sp2gz_randtest(mat, state, bits); acb_siegel_randtest_reduced(tau, state, prec, bits); kappa = acb_theta_transform_kappa(sqrtdet, mat, tau, prec); kappa2 = acb_theta_transform_kappa2(mat); if (kappa % 4 != kappa2) { flint_printf("FAIL\n"); flint_printf("tau, mat:\n"); acb_mat_printd(tau, 5); fmpz_mat_print_pretty(mat); flint_printf("kappa = %wd, kappa2 = %wd, sqrtdet:\n", kappa, kappa2); acb_printd(sqrtdet, 5); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(mat); fmpz_mat_clear(x); acb_mat_clear(tau); acb_clear(sqrtdet); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-transform_proj.c000066400000000000000000000037221461254215100217710ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_transform_proj, state) { slong iter; /* Test: inverse matrix gives back the same projective point */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 3); slong n2 = 1 << (2 * g); slong prec = 100; slong bits = n_randint(state, 5); int sqr = iter % 2; fmpz_mat_t mat, inv; acb_ptr th, aux, test; acb_t scal; slong k; fmpz_mat_init(mat, 2 * g, 2 * g); fmpz_mat_init(inv, 2 * g, 2 * g); th = _acb_vec_init(n2); aux = _acb_vec_init(n2); test = _acb_vec_init(n2); acb_init(scal); sp2gz_randtest(mat, state, bits); sp2gz_inv(inv, mat); for (k = 0; k < n2; k++) { acb_urandom(&test[k], state, prec); } acb_theta_transform_proj(aux, mat, test, sqr, prec); acb_theta_transform_proj(th, inv, aux, sqr, prec); acb_div(scal, &test[0], &th[0], prec); _acb_vec_scalar_mul(th, th, n2, scal, prec); if (!_acb_vec_overlaps(th, test, n2)) { flint_printf("FAIL (sqr = %wd)\n", sqr); flint_printf("test, th:\n"); _acb_vec_printd(test, n2, 5); _acb_vec_printd(th, n2, 5); flint_abort(); } fmpz_mat_clear(mat); fmpz_mat_clear(inv); _acb_vec_clear(th, n2); _acb_vec_clear(aux, n2); _acb_vec_clear(test, n2); acb_clear(scal); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/test/t-transform_sqrtdet.c000066400000000000000000000025671461254215100225130ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb_theta.h" TEST_FUNCTION_START(acb_theta_transform_sqrtdet, state) { slong iter; /* Test: square of sqrtdet is det */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); acb_mat_t tau; acb_t r, t; slong prec = 2 + n_randint(state, 200); slong mag_bits = n_randint(state, 4); acb_mat_init(tau, g, g); acb_init(r); acb_init(t); acb_siegel_randtest(tau, state, prec, mag_bits); acb_theta_transform_sqrtdet(r, tau, prec); acb_sqr(r, r, prec); acb_mat_det(t, tau, prec); if (!acb_overlaps(r, t)) { flint_printf("FAIL\n"); acb_printd(r, 10); flint_printf("\n"); acb_printd(t, 10); flint_printf("\n"); flint_abort(); } acb_mat_clear(tau); acb_clear(r); acb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acb_theta/transform_char.c000066400000000000000000000103601461254215100205100ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "acb_theta.h" ulong acb_theta_transform_char(slong * e, const fmpz_mat_t mat, ulong ab) { slong g = sp2gz_dim(mat); fmpz_mat_t a, b, c, d; fmpz_mat_t mat_tp; fmpz_mat_t block; /* CD^t or AB^t */ fmpz_mat_t alphabeta, alpha, beta; fmpz_mat_t Cvec_1, Cvec_2, Lvec; fmpz_mat_t coef; fmpz_t eps, x; ulong res = 0; slong i; fmpz_mat_window_init(a, mat, 0, 0, g, g); fmpz_mat_window_init(b, mat, 0, g, g, 2 * g); fmpz_mat_window_init(c, mat, g, 0, 2 * g, g); fmpz_mat_window_init(d, mat, g, g, 2 * g, 2 * g); fmpz_mat_init(mat_tp, 2 * g, 2 * g); fmpz_mat_init(block, g, g); fmpz_mat_init(alphabeta, 2 * g, 1); fmpz_mat_init(Cvec_1, g, 1); fmpz_mat_init(Cvec_2, g, 1); fmpz_mat_init(Lvec, 1, g); fmpz_mat_init(coef, 1, 1); fmpz_init(eps); fmpz_init(x); fmpz_mat_transpose(mat_tp, mat); /* Compute blocks and substract diagonals in alphabeta */ fmpz_mat_transpose(block, d); fmpz_mat_mul(block, c, block); for (i = 0; i < g; i++) { fmpz_sub(fmpz_mat_entry(alphabeta, i, 0), fmpz_mat_entry(alphabeta, i, 0), fmpz_mat_entry(block, i, i)); } fmpz_mat_transpose(block, b); fmpz_mat_mul(block, a, block); for (i = 0; i < g; i++) { fmpz_sub(fmpz_mat_entry(alphabeta, g + i, 0), fmpz_mat_entry(alphabeta, g + i, 0), fmpz_mat_entry(block, i, i)); } /* Turn ab into a 2g x 1 fmpz matrix, and update alphabeta */ for (i = 0; i < 2 * g; i++) { /* Least significant bits first */ fmpz_add_si(fmpz_mat_entry(alphabeta, 2 * g - 1 - i, 0), fmpz_mat_entry(alphabeta, 2 * g - 1 - i, 0), ab & 1); ab = ab >> 1; } /* Perform matrix-vector multiplication */ fmpz_mat_mul(alphabeta, mat_tp, alphabeta); /* Compute eps */ fmpz_mat_window_init(alpha, alphabeta, 0, 0, g, 1); fmpz_mat_window_init(beta, alphabeta, g, 0, 2 * g, 1); fmpz_zero(eps); fmpz_mat_mul(Cvec_1, c, beta); fmpz_mat_mul(Cvec_2, b, alpha); fmpz_mat_transpose(Lvec, Cvec_2); fmpz_mat_mul(coef, Lvec, Cvec_1); fmpz_addmul_ui(eps, fmpz_mat_entry(coef, 0, 0), 2); fmpz_mat_mul(Cvec_1, b, alpha); fmpz_mat_mul(Cvec_2, d, alpha); fmpz_mat_transpose(Lvec, Cvec_2); fmpz_mat_mul(coef, Lvec, Cvec_1); fmpz_sub(eps, eps, fmpz_mat_entry(coef, 0, 0)); fmpz_mat_mul(Cvec_1, a, beta); fmpz_mat_mul(Cvec_2, c, beta); fmpz_mat_transpose(Lvec, Cvec_2); fmpz_mat_mul(coef, Lvec, Cvec_1); fmpz_sub(eps, eps, fmpz_mat_entry(coef, 0, 0)); fmpz_mat_transpose(block, b); fmpz_mat_mul(block, a, block); for (i = 0; i < g; i++) { fmpz_set(fmpz_mat_entry(Lvec, 0, i), fmpz_mat_entry(block, i, i)); } fmpz_mat_mul(Cvec_1, d, alpha); fmpz_mat_mul(Cvec_2, c, beta); fmpz_mat_sub(Cvec_1, Cvec_1, Cvec_2); fmpz_mat_mul(coef, Lvec, Cvec_1); fmpz_addmul_ui(eps, fmpz_mat_entry(coef, 0, 0), 2); /* Convert alphabeta mod 2 to ulong */ for (i = 0; i < 2 * g; i++) { res = res << 1; res += fmpz_tstbit(fmpz_mat_entry(alphabeta, i, 0), 0); } /* Adjust sign of eps and reduce mod 8 */ for (i = 0; i < g; i++) { if (fmpz_mod_ui(x, fmpz_mat_entry(alphabeta, i, 0), 2) == 1 && fmpz_mod_ui(x, fmpz_mat_entry(alphabeta, i + g, 0), 4) > 1) { fmpz_add_ui(eps, eps, 4); } } *e = fmpz_mod_ui(eps, eps, 8); fmpz_mat_window_clear(a); fmpz_mat_window_clear(b); fmpz_mat_window_clear(c); fmpz_mat_window_clear(d); fmpz_mat_clear(mat_tp); fmpz_mat_clear(block); fmpz_mat_clear(alphabeta); fmpz_mat_window_clear(alpha); fmpz_mat_window_clear(beta); fmpz_mat_clear(Cvec_1); fmpz_mat_clear(Cvec_2); fmpz_mat_clear(Lvec); fmpz_mat_clear(coef); fmpz_clear(eps); fmpz_clear(x); return res; } flint-3.1.3/src/acb_theta/transform_kappa.c000066400000000000000000000110441461254215100206670ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "acb_modular.h" #include "acb_theta.h" static slong transform_kappa_g1(acb_t sqrtdet, const fmpz_mat_t mat, const fmpz_mat_t x, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); psl2z_t y; int R[4]; int S[4]; int C; ulong ab; slong e, res; psl2z_init(y); /* set y to corresponding psl2z_t and use acb_modular_theta_transform */ fmpz_set(&y->a, fmpz_mat_entry(x, 0, 0)); fmpz_set(&y->b, fmpz_mat_entry(x, 0, 1)); fmpz_set(&y->c, fmpz_mat_entry(x, 1, 0)); fmpz_set(&y->d, fmpz_mat_entry(x, 1, 1)); acb_modular_theta_transform(R, S, &C, y); acb_mul_fmpz(sqrtdet, acb_mat_entry(tau, 0, 0), &y->c, prec); acb_add_fmpz(sqrtdet, sqrtdet, &y->d, prec); acb_sqrt(sqrtdet, sqrtdet, prec); /* find out where theta_00 is going */ if (S[2] == 1) /* theta_2 */ { ab = 1 << (2 * g - 1); } else if (S[2] == 2) /* theta_0 */ { ab = 0; } else /* theta_1, since -theta_3 cannot happen (odd) */ { ab = 1 << (g - 1); } acb_theta_transform_char(&e, mat, ab); /* adjust root of unity based on R */ if (fmpz_is_zero(&y->c)) { res = -R[2] - e; } else { res = -R[2] - 1 - e; } psl2z_clear(y); return res; } static slong transform_kappa_j(acb_t sqrtdet, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) { slong g = sp2gz_dim(mat); fmpz_mat_t gamma; acb_mat_t tau0; slong r, res; fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); r = fmpz_mat_rank(gamma); fmpz_mat_window_clear(gamma); /* Mumford: theta_00(mtau) = det(tau0/i)^{1/2} theta_00(tau), and transform_sqrtdet(tau0) = i^{r/2} det(tau0/i)^{1/2} */ acb_mat_window_init(tau0, tau, 0, 0, r, r); acb_theta_transform_sqrtdet(sqrtdet, tau0, prec); acb_mat_window_clear(tau0); res = -r; if (r % 2 == 1) { acb_mul_onei(sqrtdet, sqrtdet); res -= 2; } return res; } slong acb_theta_transform_kappa(acb_t sqrtdet, const fmpz_mat_t mat, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); fmpz_mat_struct * dec; fmpz_mat_t delta; fmpz_t det; slong nb_dec; fmpz_mat_t x; acb_mat_t w; acb_t c; slong k, res, e; ulong ab; fmpz_mat_init(x, 2, 2); acb_mat_init(w, g, g); acb_init(c); fmpz_init(det); dec = sp2gz_decompose(&nb_dec, mat); acb_one(sqrtdet); acb_mat_set(w, tau); res = 0; for (k = nb_dec - 1; k >= 0; k--) { if (sp2gz_is_trig(&dec[k]) || sp2gz_is_block_diag(&dec[k])) { /* theta_00(mtau) = theta_ab(tau) */ fmpz_mat_window_init(delta, &dec[k], g, g, 2 * g, 2 * g); fmpz_mat_det(det, delta); fmpz_mat_window_clear(delta); if (fmpz_is_one(det)) { acb_one(c); } else { acb_onei(c); res -= 2; } } else if (sp2gz_is_embedded(x, &dec[k])) { if (fmpz_cmp_si(fmpz_mat_entry(x, 1, 0), 0) < 0 || (fmpz_is_zero(fmpz_mat_entry(x, 1, 0)) && fmpz_cmp_si(fmpz_mat_entry(x, 1, 1), 0) < 0)) { fmpz_mat_neg(x, x); res += transform_kappa_g1(c, &dec[k], x, w, prec); acb_div_onei(c, c); res += 2; } else { res += transform_kappa_g1(c, &dec[k], x, w, prec); } } else /* embedded j */ { res += transform_kappa_j(c, &dec[k], w, prec); } acb_siegel_transform(w, &dec[k], w, prec); acb_mul(sqrtdet, sqrtdet, c, prec); } /* Adjust final sign based on transformation of coordinates */ acb_theta_transform_char(&e, mat, 0); res -= e; ab = 0; for (k = 0; k < nb_dec; k++) { ab = acb_theta_transform_char(&e, &dec[k], ab); res += e; } fmpz_mat_clear(x); acb_mat_clear(w); acb_clear(c); for (k = 0; k < nb_dec; k++) { fmpz_mat_clear(&dec[k]); } flint_free(dec); return res & 7; } flint-3.1.3/src/acb_theta/transform_kappa2.c000066400000000000000000000067461461254215100207660ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_modular.h" #include "acb_theta.h" static slong transform_kappa2_g1(const fmpz_mat_t mat, const fmpz_mat_t x) { slong g = sp2gz_dim(mat); psl2z_t y; int R[4]; int S[4]; int C; ulong ab; slong e, res; psl2z_init(y); /* set y to corresponding psl2z_t and use acb_modular_theta_transform */ fmpz_set(&y->a, fmpz_mat_entry(x, 0, 0)); fmpz_set(&y->b, fmpz_mat_entry(x, 0, 1)); fmpz_set(&y->c, fmpz_mat_entry(x, 1, 0)); fmpz_set(&y->d, fmpz_mat_entry(x, 1, 1)); acb_modular_theta_transform(R, S, &C, y); /* find out where theta_00 is going */ if (S[2] == 1) /* theta_2 */ { ab = 1 << (2 * g - 1); } else if (S[2] == 2) /* theta_0 */ { ab = 0; } else /* theta_1, since -theta_3 cannot happen (odd) */ { ab = 1 << (g - 1); } acb_theta_transform_char(&e, mat, ab); /* adjust root of unity based on R */ if (fmpz_is_zero(&y->c)) { res = -R[2] - e; } else { res = -R[2] - 1 - e; } psl2z_clear(y); return res; } static slong transform_kappa2_j(const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_t gamma; slong r, res; fmpz_mat_window_init(gamma, mat, g, 0, 2 * g, g); r = fmpz_mat_rank(gamma); fmpz_mat_window_clear(gamma); res = -r; if (r % 2 == 1) { res -= 2; } return res; } slong acb_theta_transform_kappa2(const fmpz_mat_t mat) { slong g = sp2gz_dim(mat); fmpz_mat_struct * dec; fmpz_mat_t delta; fmpz_t det; slong nb_dec; fmpz_mat_t x; slong k, res, e; ulong ab; fmpz_mat_init(x, 2, 2); fmpz_init(det); dec = sp2gz_decompose(&nb_dec, mat); res = 0; for (k = nb_dec - 1; k >= 0; k--) { if (sp2gz_is_trig(&dec[k]) || sp2gz_is_block_diag(&dec[k])) { /* theta_00(mtau) = theta_ab(tau) */ fmpz_mat_window_init(delta, &dec[k], g, g, 2 * g, 2 * g); fmpz_mat_det(det, delta); fmpz_mat_window_clear(delta); if (!fmpz_is_one(det)) { res += 2; } } else if (sp2gz_is_embedded(x, &dec[k])) { if (fmpz_cmp_si(fmpz_mat_entry(x, 1, 0), 0) < 0 || (fmpz_is_zero(fmpz_mat_entry(x, 1, 0)) && fmpz_cmp_si(fmpz_mat_entry(x, 1, 1), 0) < 0)) { fmpz_mat_neg(x, x); res += transform_kappa2_g1(&dec[k], x); res += 2; } else { res += transform_kappa2_g1(&dec[k], x); } } else /* embedded j */ { res += transform_kappa2_j(&dec[k]); } } /* Adjust final sign based on transformation of coordinates */ acb_theta_transform_char(&e, mat, 0); res -= e; ab = 0; for (k = 0; k < nb_dec; k++) { ab = acb_theta_transform_char(&e, &dec[k], ab); res += e; } fmpz_mat_clear(x); for (k = 0; k < nb_dec; k++) { fmpz_mat_clear(&dec[k]); } flint_free(dec); return res & 3; } flint-3.1.3/src/acb_theta/transform_proj.c000066400000000000000000000020351461254215100205450ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "acb_theta.h" void acb_theta_transform_proj(acb_ptr res, const fmpz_mat_t mat, acb_srcptr th, int sqr, slong prec) { slong g = sp2gz_dim(mat); ulong n2 = 1 << (2 * g); slong k = (sqr ? 4 : 8); acb_ptr aux; ulong ab, image_ab; slong e; acb_t c; aux = _acb_vec_init(n2); acb_init(c); for (ab = 0; ab < n2; ab++) { image_ab = acb_theta_transform_char(&e, mat, ab); acb_unit_root(c, k, prec); acb_pow_ui(c, c, e, prec); acb_mul(c, c, &th[image_ab], prec); acb_set(&aux[ab], c); } _acb_vec_set(res, aux, n2); _acb_vec_clear(aux, n2); acb_clear(c); } flint-3.1.3/src/acb_theta/transform_sqrtdet.c000066400000000000000000000122141461254215100212610ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "acb_mat.h" #include "acb_theta.h" static void acb_theta_sqrt_branch(acb_t res, const acb_t x, acb_srcptr rts_neg, slong nb_neg, acb_srcptr rts_pos, slong nb_pos, const acb_t sqrt_lead, slong prec) { acb_t s, t; slong k; acb_init(s); acb_init(t); acb_set(s, sqrt_lead); for (k = 0; k < nb_neg; k++) { acb_sub(t, x, &rts_neg[k], prec); acb_sqrt_analytic(t, t, 1, prec); acb_mul(s, s, t, prec); } for (k = 0; k < nb_pos; k++) { acb_sub(t, &rts_pos[k], x, prec); acb_sqrt_analytic(t, t, 1, prec); acb_mul(s, s, t, prec); } acb_set(res, s); acb_clear(s); acb_clear(t); } void acb_theta_transform_sqrtdet(acb_t res, const acb_mat_t tau, slong prec) { slong g = acb_mat_nrows(tau); flint_rand_t state; acb_mat_t A, B, C; acb_poly_t pol, h; acb_ptr rts, rts_neg, rts_pos; acb_t z, rt, mu; arb_t x; slong k, j, nb_neg, nb_pos; int success = 0; flint_randinit(state); acb_mat_init(A, g, g); acb_mat_init(B, g, g); acb_mat_init(C, g, g); acb_poly_init(pol); acb_poly_init(h); rts = _acb_vec_init(g); rts_neg = _acb_vec_init(g); rts_pos = _acb_vec_init(g); acb_init(z); acb_init(rt); acb_init(mu); arb_init(x); /* Choose a purely imaginary matrix A and compute pol s.t. pol(-1) = det(A) and pol(1) = det(tau): pol(t) is det(A + (t+1)/2 (tau - A)) = det(A) det(I - (t+1)/2 (I - A^{-1}tau)) We want to get the g roots of this polynomial to compute the branch cuts. This can fail e.g. when det(tau - A) = 0, so pick A at random until the roots can be found */ for (k = 0; (k < 100) && !success; k++) { acb_mat_onei(A); for (j = 0; j < g; j++) { arb_urandom(x, state, prec); arb_add(acb_imagref(acb_mat_entry(A, j, j)), acb_imagref(acb_mat_entry(A, j, j)), x, prec); } acb_mat_inv(B, A, prec); acb_mat_mul(B, B, tau, prec); acb_mat_one(C); acb_mat_sub(C, C, B, prec); /* Get reverse of charpoly */ acb_mat_charpoly(h, C, prec); acb_poly_zero(pol); for (j = 0; j <= g; j++) { acb_poly_get_coeff_acb(z, h, j); acb_poly_set_coeff_acb(pol, g - j, z); } acb_poly_one(h); acb_poly_set_coeff_si(h, 1, 1); acb_poly_scalar_mul_2exp_si(h, h, -1); acb_poly_compose(pol, pol, h, prec); success = (acb_poly_find_roots(rts, pol, NULL, 0, prec) == g); /* Check that no root intersects the [-1,1] segment */ for (j = 0; (j < g) && success; j++) { if (arb_contains_zero(acb_imagref(&rts[j]))) { arb_abs(x, acb_realref(&rts[j])); arb_sub_si(x, x, 1, prec); success = arb_is_positive(x); } } } if (success) { /* Partition the roots between positive & negative real parts to compute branch for sqrt(pol) */ nb_neg = 0; nb_pos = 0; for (k = 0; k < g; k++) { if (arb_is_negative(acb_realref(&rts[k]))) { acb_set(&rts_neg[nb_neg], &rts[k]); nb_neg++; } else { acb_set(&rts_pos[nb_pos], &rts[k]); nb_pos++; } } acb_mat_det(rt, A, prec); acb_mul(rt, rt, acb_poly_get_coeff_ptr(pol, g), prec); acb_sqrts(rt, z, rt, prec); /* Set mu to +-1 such that mu*sqrt_branch gives the correct value at A, i.e. i^(g/2) * something positive */ acb_mat_det(mu, A, prec); acb_mul_i_pow_si(mu, mu, -g); acb_sqrt(mu, mu, prec); acb_set_si(z, g); acb_mul_2exp_si(z, z, -2); acb_exp_pi_i(z, z, prec); acb_mul(mu, mu, z, prec); acb_set_si(z, -1); acb_theta_sqrt_branch(z, z, rts_neg, nb_neg, rts_pos, nb_pos, rt, prec); acb_div(mu, mu, z, prec); /* Compute square root branch at z=1 to get sqrtdet */ acb_set_si(z, 1); acb_theta_sqrt_branch(rt, z, rts_neg, nb_neg, rts_pos, nb_pos, rt, prec); acb_mul(rt, rt, mu, prec); acb_mat_det(res, tau, prec); acb_theta_agm_sqrt(res, res, rt, 1, prec); } else { acb_mat_det(res, tau, prec); acb_sqrts(res, z, res, prec); acb_union(res, res, z, prec); } flint_randclear(state); acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(C); acb_poly_clear(pol); acb_poly_clear(h); _acb_vec_clear(rts, g); _acb_vec_clear(rts_pos, g); _acb_vec_clear(rts_neg, g); acb_clear(z); acb_clear(rt); acb_clear(mu); arb_clear(x); } flint-3.1.3/src/acb_types.h000066400000000000000000000017311461254215100155460ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACB_TYPES_H #define ACB_TYPES_H #include "arb_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { arb_struct real; arb_struct imag; } acb_struct; typedef acb_struct acb_t[1]; typedef acb_struct * acb_ptr; typedef const acb_struct * acb_srcptr; typedef struct { acb_ptr entries; slong r; slong c; acb_ptr * rows; } acb_mat_struct; typedef acb_mat_struct acb_mat_t[1]; typedef struct { acb_ptr coeffs; slong alloc; slong length; } acb_poly_struct; typedef acb_poly_struct acb_poly_t[1]; #ifdef __cplusplus } #endif #endif /* ACB_TYPES_H */ flint-3.1.3/src/acf.h000066400000000000000000000110651461254215100143270ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACF_H #define ACF_H #ifdef ACF_INLINES_C #define ACF_INLINE #else #define ACF_INLINE static inline #endif #include "arf.h" #include "acf_types.h" #ifdef __cplusplus extern "C" { #endif #define acf_realref(x) (&(x)->real) #define acf_imagref(x) (&(x)->imag) ACF_INLINE void acf_init(acf_t x) { arf_init(acf_realref(x)); arf_init(acf_imagref(x)); } ACF_INLINE void acf_clear(acf_t x) { arf_clear(acf_realref(x)); arf_clear(acf_imagref(x)); } ACF_INLINE acf_ptr _acf_vec_init(slong n) { return (acf_ptr) _arf_vec_init(2 * n); } ACF_INLINE void _acf_vec_clear(acf_ptr v, slong n) { _arf_vec_clear((arf_ptr) v, 2 * n); } ACF_INLINE arf_ptr acf_real_ptr(acf_t z) { return acf_realref(z); } ACF_INLINE arf_ptr acf_imag_ptr(acf_t z) { return acf_imagref(z); } ACF_INLINE void acf_set(acf_t z, const acf_t x) { arf_set(acf_realref(z), acf_realref(x)); arf_set(acf_imagref(z), acf_imagref(x)); } ACF_INLINE void acf_swap(acf_t z, acf_t x) { FLINT_SWAP(acf_struct, *z, *x); } ACF_INLINE int acf_equal(const acf_t x, const acf_t y) { return arf_equal(acf_realref(x), acf_realref(y)) && arf_equal(acf_imagref(x), acf_imagref(y)); } /* todo: document */ ACF_INLINE void acf_printd(const acf_t x, slong n) { arf_printd(acf_realref(x), n); flint_printf(" + "); arf_printd(acf_imagref(x), n); flint_printf("*I"); } /* todo: document */ ACF_INLINE slong acf_bits(const acf_t x) { slong b1, b2; b1 = arf_bits(acf_realref(x)); b2 = arf_bits(acf_imagref(x)); return FLINT_MAX(b1, b2); } ACF_INLINE slong acf_allocated_bytes(const acf_t x) { return arf_allocated_bytes(acf_realref(x)) + arf_allocated_bytes(acf_imagref(x)); } /* todo: document */ ACF_INLINE void acf_randtest(acf_t x, flint_rand_t state, slong bits, slong mag_bits) { arf_randtest(acf_realref(x), state, bits, mag_bits); arf_randtest(acf_imagref(x), state, bits, mag_bits); } /* todo: document */ ACF_INLINE void acf_get_mag(mag_t res, const acf_t x) { mag_t t, u; mag_init(t); mag_init(u); arf_get_mag(t, acf_realref(x)); arf_get_mag(u, acf_imagref(x)); mag_hypot(res, t, u); mag_clear(t); mag_clear(u); } /* todo: document */ ACF_INLINE void acf_neg(acf_t z, const acf_t x) { arf_neg(acf_realref(z), acf_realref(x)); arf_neg(acf_imagref(z), acf_imagref(x)); } /* todo: document */ ACF_INLINE int acf_set_round(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd) { return arf_set_round(acf_realref(res), acf_realref(x), prec, rnd) | (arf_set_round(acf_imagref(res), acf_imagref(x), prec, rnd) << 1); } /* todo: document */ ACF_INLINE int acf_neg_round(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd) { return arf_neg_round(acf_realref(res), acf_realref(x), prec, rnd) | (arf_neg_round(acf_imagref(res), acf_imagref(x), prec, rnd) << 1); } ACF_INLINE int acf_add(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) { return arf_add(acf_realref(res), acf_realref(x), acf_realref(y), prec, rnd) | (arf_add(acf_imagref(res), acf_imagref(x), acf_imagref(y), prec, rnd) << 1); } ACF_INLINE int acf_sub(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) { return arf_sub(acf_realref(res), acf_realref(x), acf_realref(y), prec, rnd) | (arf_sub(acf_imagref(res), acf_imagref(x), acf_imagref(y), prec, rnd) << 1); } ACF_INLINE int acf_mul(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) { if (x == y) return arf_complex_sqr(acf_realref(res), acf_imagref(res), acf_realref(x), acf_imagref(x), prec, rnd); else return arf_complex_mul(acf_realref(res), acf_imagref(res), acf_realref(x), acf_imagref(x), acf_realref(y), acf_imagref(y), prec, rnd); } void acf_approx_inv(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd); void acf_approx_div(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd); void acf_approx_sqrt(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd); void acf_approx_dot(acf_t res, const acf_t initial, int subtract, acf_srcptr x, slong xstep, acf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/acf/000077500000000000000000000000001461254215100141535ustar00rootroot00000000000000flint-3.1.3/src/acf/approx_div.c000066400000000000000000000070541461254215100165000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acf.h" void acf_approx_inv(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd) { if (arf_is_zero(acf_imagref(x))) { /* todo: arf_inv */ arf_ui_div(acf_realref(res), 1, acf_realref(x), prec, rnd); arf_zero(acf_imagref(res)); } else if (arf_is_zero(acf_realref(x))) { /* todo: arf_inv */ arf_si_div(acf_imagref(res), -1, acf_imagref(x), prec, rnd); arf_zero(acf_realref(res)); } else { arf_t t; arf_init(t); arf_sosq(t, acf_realref(x), acf_imagref(x), prec, rnd); arf_div(acf_realref(res), acf_realref(x), t, prec, rnd); arf_div(acf_imagref(res), acf_imagref(x), t, prec, rnd); arf_neg(acf_imagref(res), acf_imagref(res)); arf_clear(t); } } #define a acf_realref(x) #define b acf_imagref(x) #define c acf_realref(y) #define d acf_imagref(y) void acf_approx_div(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd) { if (arf_is_zero(d)) { if (arf_is_zero(b)) { arf_div(acf_realref(res), a, c, prec, rnd); arf_zero(acf_imagref(res)); } else if (arf_is_zero(a)) { arf_div(acf_imagref(res), b, c, prec, rnd); arf_zero(acf_realref(res)); } else if (res != y) { arf_div(acf_realref(res), a, c, prec, rnd); arf_div(acf_imagref(res), b, c, prec, rnd); } else { arf_t t; arf_init(t); arf_set(t, c); arf_div(acf_realref(res), a, t, prec, rnd); arf_div(acf_imagref(res), b, t, prec, rnd); arf_clear(t); } } else if (arf_is_zero(c)) { if (arf_is_zero(b)) { arf_div(acf_imagref(res), a, d, prec, rnd); arf_neg(acf_imagref(res), acf_imagref(res)); arf_zero(acf_realref(res)); } else if (arf_is_zero(a)) { arf_div(acf_realref(res), b, d, prec, rnd); arf_zero(acf_imagref(res)); } else if (res != y) { arf_div(acf_realref(res), a, d, prec, rnd); arf_div(acf_imagref(res), b, d, prec, rnd); arf_swap(acf_realref(res), acf_imagref(res)); arf_neg(acf_imagref(res), acf_imagref(res)); } else { arf_t t; arf_init(t); arf_set(t, d); arf_div(acf_realref(res), a, t, prec, rnd); arf_div(acf_imagref(res), b, t, prec, rnd); arf_swap(acf_realref(res), acf_imagref(res)); arf_neg(acf_imagref(res), acf_imagref(res)); arf_clear(t); } } else { arf_t t; acf_t u; arf_init(t); arf_sosq(t, acf_realref(y), acf_imagref(y), prec, rnd); arf_init_set_shallow(acf_realref(u), acf_realref(y)); arf_init_neg_shallow(acf_imagref(u), acf_imagref(y)); acf_mul(res, x, u, prec, rnd); arf_div(acf_realref(res), acf_realref(res), t, prec, rnd); arf_div(acf_imagref(res), acf_imagref(res), t, prec, rnd); arf_clear(t); } } #undef a #undef b #undef c #undef d flint-3.1.3/src/acf/approx_dot.c000066400000000000000000000522651461254215100165100ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acf.h" #include "mpn_extras.h" /* We need uint64_t instead of mp_limb_t on 32-bit systems for safe summation of 30-bit error bounds. */ #include void _arb_dot_addmul_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, mp_srcptr yptr, mp_size_t yn, int negative, flint_bitcnt_t shift); void _arb_dot_add_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, int negative, flint_bitcnt_t shift); static void _arb_dot_output(arf_t res, mp_ptr sum, mp_size_t sn, int negative, slong sum_exp, slong prec, arf_rnd_t rnd) { slong exp_fix; if (sum[sn - 1] >= LIMB_TOP) { mpn_neg(sum, sum, sn); negative ^= 1; } exp_fix = 0; if (sum[sn - 1] == 0) { slong sum_exp2; mp_size_t sn2; sn2 = sn; sum_exp2 = sum_exp; while (sn2 > 0 && sum[sn2 - 1] == 0) { sum_exp2 -= FLINT_BITS; sn2--; } if (sn2 == 0) { arf_zero(res); } else { _arf_set_round_mpn(res, &exp_fix, sum, sn2, negative, prec, rnd); _fmpz_set_si_small(ARF_EXPREF(res), exp_fix + sum_exp2); } } else { if (sn == 2) /* unnecessary? */ _arf_set_round_uiui(res, &exp_fix, sum[1], sum[0], negative, prec, rnd); else _arf_set_round_mpn(res, &exp_fix, sum, sn, negative, prec, rnd); _fmpz_set_si_small(ARF_EXPREF(res), exp_fix + sum_exp); } } /* xxx: don't use surrounding variables */ #define ARB_DOT_ADD(s_sum, s_serr, s_sn, s_sum_exp, s_subtract, xm) \ if (!arf_is_special(xm)) \ { \ mp_srcptr xptr; \ xexp = ARF_EXP(xm); \ xn = ARF_SIZE(xm); \ xnegative = ARF_SGNBIT(xm); \ shift = s_sum_exp - xexp; \ if (shift >= s_sn * FLINT_BITS) \ { \ } \ else \ { \ xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); \ _arb_dot_add_generic(s_sum, &s_serr, tmp, s_sn, xptr, xn, xnegative ^ s_subtract, shift); \ } \ } \ static void _arf_complex_mul_gauss(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d) { mp_srcptr ap, bp, cp, dp; int asgn, bsgn, csgn, dsgn; mp_size_t an, bn, cn, dn; slong aexp, bexp, cexp, dexp; fmpz texp, uexp; fmpz_t za, zb, zc, zd, t, u, v; slong abot, bbot, cbot, dbot; ARF_GET_MPN_READONLY(ap, an, a); asgn = ARF_SGNBIT(a); aexp = ARF_EXP(a); ARF_GET_MPN_READONLY(bp, bn, b); bsgn = ARF_SGNBIT(b); bexp = ARF_EXP(b); ARF_GET_MPN_READONLY(cp, cn, c); csgn = ARF_SGNBIT(c); cexp = ARF_EXP(c); ARF_GET_MPN_READONLY(dp, dn, d); dsgn = ARF_SGNBIT(d); dexp = ARF_EXP(d); /* Karstsuba multiplication e = ac - bd f = (a+b)(c+d) - ac - bd */ abot = aexp - an * FLINT_BITS; bbot = bexp - bn * FLINT_BITS; cbot = cexp - cn * FLINT_BITS; dbot = dexp - dn * FLINT_BITS; texp = FLINT_MIN(abot, bbot); uexp = FLINT_MIN(cbot, dbot); fmpz_init(za); fmpz_init(zb); fmpz_init(zc); fmpz_init(zd); fmpz_init(t); fmpz_init(u); fmpz_init(v); fmpz_lshift_mpn(za, ap, an, asgn, abot - texp); fmpz_lshift_mpn(zb, bp, bn, bsgn, bbot - texp); fmpz_lshift_mpn(zc, cp, cn, csgn, cbot - uexp); fmpz_lshift_mpn(zd, dp, dn, dsgn, dbot - uexp); fmpz_add(t, za, zb); fmpz_add(v, zc, zd); fmpz_mul(u, t, v); fmpz_mul(t, za, zc); fmpz_mul(v, zb, zd); fmpz_sub(u, u, t); fmpz_sub(u, u, v); fmpz_sub(t, t, v); texp += uexp; arf_set_fmpz_2exp(e, t, &texp); arf_set_fmpz_2exp(f, u, &texp); fmpz_clear(za); fmpz_clear(zb); fmpz_clear(zc); fmpz_clear(zd); fmpz_clear(t); fmpz_clear(u); fmpz_clear(v); } FLINT_DLL extern slong acb_dot_gauss_dot_cutoff; #define GAUSS_CUTOFF acb_dot_gauss_dot_cutoff void acf_approx_dot_simple(acf_t res, const acf_t initial, int subtract, acf_srcptr x, slong xstep, acf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd) { slong i; if (len <= 0) { if (initial == NULL) { arf_zero(acf_realref(res)); arf_zero(acf_imagref(res)); } else { arf_set_round(acf_realref(res), acf_realref(initial), prec, rnd); arf_set_round(acf_imagref(res), acf_imagref(initial), prec, rnd); } return; } if (initial == NULL && len == 1) { arf_complex_mul(acf_realref(res), acf_imagref(res), acf_realref(x), acf_imagref(x), acf_realref(y), acf_imagref(y), prec, rnd); } else { arf_t e, f; arf_init(e); arf_init(f); if (initial != NULL) { if (subtract) { arf_neg(acf_realref(res), acf_realref(initial)); arf_neg(acf_imagref(res), acf_imagref(initial)); } else { arf_set(acf_realref(res), acf_realref(initial)); arf_set(acf_imagref(res), acf_imagref(initial)); } } for (i = 0; i < len; i++) { arf_complex_mul(e, f, (acf_realref(x + i * xstep)), (acf_imagref(x + i * xstep)), (acf_realref(y + i * ystep)), (acf_imagref(y + i * ystep)), prec, rnd); if (i == 0 && initial == NULL) { arf_set(acf_realref(res), e); arf_set(acf_imagref(res), f); } else { arf_add(acf_realref(res), acf_realref(res), e, prec, rnd); arf_add(acf_imagref(res), acf_imagref(res), f, prec, rnd); } } arf_clear(e); arf_clear(f); } if (subtract) { arf_neg(acf_realref(res), acf_realref(res)); arf_neg(acf_imagref(res), acf_imagref(res)); } } void acf_approx_dot(acf_t res, const acf_t initial, int subtract, acf_srcptr x, slong xstep, acf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd) { slong i, j, padding, extend; slong xexp, yexp, exp; slong re_nonzero, im_nonzero; slong re_max_exp, re_min_exp, re_sum_exp; slong im_max_exp, im_min_exp, im_sum_exp; slong re_prec, im_prec; int xnegative, ynegative; mp_size_t xn, yn, re_sn, im_sn, alloc; flint_bitcnt_t shift; arf_srcptr xi, yi; arf_srcptr xm, ym; mp_limb_t re_serr, im_serr; /* Sum over arithmetic errors */ mp_ptr tmp, re_sum, im_sum; /* Workspace */ slong xoff, yoff; char * use_gauss; ARF_ADD_TMP_DECL; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { acf_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec, rnd); return; } /* Number of nonzero midpoint terms in sum. */ re_nonzero = 0; im_nonzero = 0; /* Terms are bounded by 2^max_exp (with WORD_MIN = -infty) */ re_max_exp = WORD_MIN; im_max_exp = WORD_MIN; /* Used to reduce the precision. */ re_min_exp = WORD_MAX; im_min_exp = WORD_MAX; /* Account for the initial term. */ if (initial != NULL) { if (!ARF_IS_LAGOM(acf_realref(initial)) || !ARF_IS_LAGOM(acf_imagref(initial))) { acf_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec, rnd); return; } xm = acf_realref(initial); if (!arf_is_special(xm)) { re_max_exp = ARF_EXP(xm); re_nonzero++; if (prec > 2 * FLINT_BITS) re_min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } xm = acf_imagref(initial); if (!arf_is_special(xm)) { im_max_exp = ARF_EXP(xm); im_nonzero++; if (prec > 2 * FLINT_BITS) im_min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } } for (xoff = 0; xoff < 2; xoff++) { for (yoff = 0; yoff < 2; yoff++) { slong nonzero, max_exp, min_exp; if (xoff == yoff) { nonzero = re_nonzero; max_exp = re_max_exp; min_exp = re_min_exp; } else { nonzero = im_nonzero; max_exp = im_max_exp; min_exp = im_min_exp; } /* Determine maximum exponents for the main sum and the radius sum. */ for (i = 0; i < len; i++) { xi = ((arf_srcptr) x) + 2 * i * xstep + xoff; yi = ((arf_srcptr) y) + 2 * i * ystep + yoff; /* Fallback for huge exponents or non-finite values. */ if (!ARF_IS_LAGOM(xi) || !ARF_IS_LAGOM(yi)) { acf_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec, rnd); return; } xm = xi; ym = yi; /* (xm+xr)(ym+yr) = xm ym + [xr ym + xm yr + xr yr] */ if (!arf_is_special(xm)) { xexp = ARF_EXP(xm); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_exp = FLINT_MAX(max_exp, xexp + yexp); nonzero++; if (prec > 2 * FLINT_BITS) { slong bot; bot = (xexp + yexp) - (ARF_SIZE(xm) + ARF_SIZE(ym)) * FLINT_BITS; min_exp = FLINT_MIN(min_exp, bot); } } } } if (xoff == yoff) { re_nonzero = nonzero; re_max_exp = max_exp; re_min_exp = min_exp; } else { im_nonzero = nonzero; im_max_exp = max_exp; im_min_exp = min_exp; } } } re_prec = prec; im_prec = prec; if (re_max_exp == WORD_MIN && im_max_exp == WORD_MIN) { arf_zero(acf_realref(res)); arf_zero(acf_imagref(res)); return; } /* The midpoint sum is zero. */ if (re_max_exp == WORD_MIN) { re_prec = 2; } else { if (re_min_exp != WORD_MAX) re_prec = FLINT_MIN(re_prec, re_max_exp - re_min_exp + MAG_BITS); re_prec = FLINT_MAX(re_prec, 2); } if (im_max_exp == WORD_MIN) { im_prec = 2; } else { if (re_min_exp != WORD_MAX) im_prec = FLINT_MIN(im_prec, im_max_exp - im_min_exp + MAG_BITS); im_prec = FLINT_MAX(im_prec, 2); } extend = FLINT_BIT_COUNT(re_nonzero) + 1; padding = 4 + FLINT_BIT_COUNT(len); re_sn = (re_prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; re_sn = FLINT_MAX(re_sn, 2); re_sum_exp = re_max_exp + extend; extend = FLINT_BIT_COUNT(im_nonzero) + 1; padding = 4 + FLINT_BIT_COUNT(len); im_sn = (im_prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; im_sn = FLINT_MAX(im_sn, 2); im_sum_exp = im_max_exp + extend; /* We need sn + 1 limb for the sum (sn limbs + 1 dummy limb for carry or borrow that avoids an extra branch). We need 2 * (sn + 2) limbs to store the product of two numbers with up to (sn + 2) limbs, plus 1 extra limb for shifting the product. */ alloc = (re_sn + 1) + (im_sn + 1) + 2 * (FLINT_MAX(re_sn, im_sn) + 2) + 1; ARF_ADD_TMP_ALLOC(re_sum, alloc) im_sum = re_sum + (re_sn + 1); tmp = im_sum + (im_sn + 1); /* Set sum to 0 */ re_serr = 0; for (j = 0; j < re_sn + 1; j++) re_sum[j] = 0; im_serr = 0; for (j = 0; j < im_sn + 1; j++) im_sum[j] = 0; if (initial != NULL) { xm = acf_realref(initial); ARB_DOT_ADD(re_sum, re_serr, re_sn, re_sum_exp, subtract, xm); xm = acf_imagref(initial); ARB_DOT_ADD(im_sum, im_serr, im_sn, im_sum_exp, subtract, xm); } use_gauss = NULL; if (re_prec >= GAUSS_CUTOFF * FLINT_BITS && im_prec >= GAUSS_CUTOFF * FLINT_BITS) { arf_t e, f; for (i = 0; i < len; i++) { arf_srcptr ai, bi, ci, di; mp_size_t an, bn, cn, dn; slong aexp, bexp, cexp, dexp; ai = ((arf_srcptr) x) + 2 * i * xstep; bi = ((arf_srcptr) x) + 2 * i * xstep + 1; ci = ((arf_srcptr) y) + 2 * i * ystep; di = ((arf_srcptr) y) + 2 * i * ystep + 1; an = ARF_SIZE(ai); bn = ARF_SIZE(bi); cn = ARF_SIZE(ci); dn = ARF_SIZE(di); aexp = ARF_EXP(ai); bexp = ARF_EXP(bi); cexp = ARF_EXP(ci); dexp = ARF_EXP(di); if (an >= GAUSS_CUTOFF && bn >= GAUSS_CUTOFF && bn >= GAUSS_CUTOFF && cn >= GAUSS_CUTOFF && FLINT_ABS(an - bn) <= 2 && FLINT_ABS(cn - dn) <= 2 && FLINT_ABS(aexp - bexp) <= 64 && FLINT_ABS(cexp - dexp) <= 64 && re_sum_exp - (aexp + cexp) < 0.1 * re_prec && im_sum_exp - (aexp + dexp) < 0.1 * im_prec && an + cn < 2.2 * re_sn && an + dn < 2.2 * im_sn) { if (use_gauss == NULL) { use_gauss = flint_calloc(len, sizeof(char)); arf_init(e); arf_init(f); } use_gauss[i] = 1; _arf_complex_mul_gauss(e, f, ai, bi, ci, di); ARB_DOT_ADD(re_sum, re_serr, re_sn, re_sum_exp, 0, e); ARB_DOT_ADD(im_sum, im_serr, im_sn, im_sum_exp, 0, f); } } if (use_gauss != NULL) { arf_clear(e); arf_clear(f); } } for (xoff = 0; xoff < 2; xoff++) { for (yoff = 0; yoff < 2; yoff++) { slong sum_exp; mp_ptr sum; mp_size_t sn; mp_limb_t serr; int flipsign; if (xoff == yoff) { sum_exp = re_sum_exp; sum = re_sum; sn = re_sn; if (re_max_exp == WORD_MIN) continue; } else { sum_exp = im_sum_exp; sum = im_sum; sn = im_sn; if (im_max_exp == WORD_MIN) continue; } serr = 0; flipsign = (xoff + yoff == 2); for (i = 0; i < len; i++) { xi = ((arf_srcptr) x) + 2 * i * xstep + xoff; yi = ((arf_srcptr) y) + 2 * i * ystep + yoff; xm = xi; ym = yi; /* The midpoints of x[i] and y[i] are both nonzero. */ if (!arf_is_special(xm) && !arf_is_special(ym)) { xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); yexp = ARF_EXP(ym); yn = ARF_SIZE(ym); ynegative = ARF_SGNBIT(ym); exp = xexp + yexp; shift = sum_exp - exp; if (shift >= sn * FLINT_BITS) { } else if (xn <= 2 && yn <= 2 && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; if (xn == 1 && yn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; umul_ppmm(u3, u2, x0, y0); u1 = u0 = 0; } else if (xn == 2 && yn == 2) { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); } else if (xn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X1(u3, u2, u1, y1, y0, x0); u0 = 0; } else { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; FLINT_MPN_MUL_2X1(u3, u2, u1, x1, x0, y0); u0 = 0; } if (sn == 2) { if (shift < FLINT_BITS) { u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u2 = u3; u3 = 0; } else /* FLINT_BITS < shift < 2 * FLINT_BITS */ { u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } if (xnegative ^ ynegative ^ flipsign) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else if (sn == 3) { if (shift < FLINT_BITS) { u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u1 = u2; u2 = u3; u3 = 0; } else if (shift < 2 * FLINT_BITS) { u1 = (u3 << (2 * FLINT_BITS - shift)) | (u2 >> (shift - FLINT_BITS)); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } else if (shift == 2 * FLINT_BITS) { u1 = u3; u2 = 0; u3 = 0; } else /* 2 * FLINT_BITS < shift < 3 * FLINT_BITS */ { u1 = (u3 >> (shift - 2 * FLINT_BITS)); u2 = 0; u3 = 0; } if (xnegative ^ ynegative ^ flipsign) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } else { mp_srcptr xptr, yptr; xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); yptr = (yn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(ym) : ARF_PTR_D(ym); if (use_gauss == NULL || use_gauss[i] == 0) _arb_dot_addmul_generic(sum, &serr, tmp, sn, xptr, xn, yptr, yn, xnegative ^ ynegative ^ flipsign, shift); } } } } } _arb_dot_output(acf_realref(res), re_sum, re_sn, subtract, re_sum_exp, re_prec, rnd); _arb_dot_output(acf_imagref(res), im_sum, im_sn, subtract, im_sum_exp, im_prec, rnd); ARF_ADD_TMP_FREE(re_sum, alloc); if (use_gauss != NULL) flint_free(use_gauss); } flint-3.1.3/src/acf/approx_sqrt.c000066400000000000000000000044311461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acf.h" void acf_approx_sqrt(acf_t y, const acf_t x, slong prec, arf_rnd_t rnd) { arf_t r, t, u; slong wp; int sgn; #define a acf_realref(x) #define b acf_imagref(x) #define c acf_realref(y) #define d acf_imagref(y) if (arf_is_zero(b)) { if (arf_sgn(a) >= 0) { arf_sqrt(c, a, prec, rnd); arf_zero(d); return; } else { arf_neg(d, a); arf_sqrt(d, d, prec, rnd); arf_zero(c); return; } } if (arf_is_zero(a)) { if (arf_sgn(b) >= 0) { arf_mul_2exp_si(c, b, -1); arf_sqrt(c, c, prec, rnd); arf_set(d, c); return; } else { arf_mul_2exp_si(c, b, -1); arf_neg(c, c); arf_sqrt(c, c, prec, rnd); arf_neg(d, c); return; } } wp = prec + 4; arf_init(r); arf_init(t); arf_init(u); /* r = |a+bi| */ arf_sosq(r, acf_realref(x), acf_imagref(x), wp, rnd); arf_sqrt(r, r, wp, rnd); if (arf_sgn(a) >= 0) { /* sqrt(a+bi) = sqrt((r+a)/2) + b/sqrt(2*(r+a))*i */ arf_add(t, r, a, wp, rnd); arf_mul_2exp_si(u, t, 1); arf_sqrt(u, u, wp, rnd); arf_div(d, b, u, prec, rnd); arf_set_round(c, u, prec, rnd); arf_mul_2exp_si(c, c, -1); } else { /* sqrt(a+bi) = |b|/sqrt(2*(r-a)) + sgn(b)*sqrt((r-a)/2)*i */ arf_sub(u, r, a, wp, rnd); sgn = arf_sgn(b); arf_mul_2exp_si(t, u, 1); arf_sqrt(t, t, wp, rnd); arf_div(c, b, t, prec, rnd); arf_abs(c, c); arf_set_round(d, t, prec, rnd); arf_mul_2exp_si(d, d, -1); if (sgn < 0) arf_neg(d, d); } arf_clear(r); arf_clear(t); arf_clear(u); #undef a #undef b #undef c #undef d } flint-3.1.3/src/acf/inlines.c000066400000000000000000000006461461254215100157660ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ACF_INLINES_C #include "acf.h" flint-3.1.3/src/acf/test/000077500000000000000000000000001461254215100151325ustar00rootroot00000000000000flint-3.1.3/src/acf/test/main.c000066400000000000000000000014771461254215100162330ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-approx_dot.c" #include "t-init_clear.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(acf_approx_dot), TEST_FUNCTION(acf_init_clear) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/acf/test/t-approx_dot.c000066400000000000000000000174101461254215100177210ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acf.h" #include "acb.h" TEST_FUNCTION_START(acf_approx_dot, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { acf_ptr x, y; acf_t s1, s2, z; slong i, len, prec, xbits, ybits, ebits; int initial, subtract, revx, revy; if (n_randint(state, 100) == 0) len = n_randint(state, 100); else if (n_randint(state, 10) == 0) len = n_randint(state, 10); else len = n_randint(state, 3); if (n_randint(state, 10) != 0 || len > 10) { prec = 2 + n_randint(state, 500); xbits = 2 + n_randint(state, 500); ybits = 2 + n_randint(state, 500); } else { prec = 2 + n_randint(state, 4000); xbits = 2 + n_randint(state, 4000); ybits = 2 + n_randint(state, 4000); } if (n_randint(state, 100) == 0) ebits = 2 + n_randint(state, 100); else ebits = 2 + n_randint(state, 10); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _acf_vec_init(len); y = _acf_vec_init(len); acf_init(s1); acf_init(s2); acf_init(z); switch (n_randint(state, 3)) { case 0: for (i = 0; i < len; i++) { acf_randtest(x + i, state, xbits, ebits); acf_randtest(y + i, state, ybits, ebits); } break; /* Test with cancellation */ case 1: for (i = 0; i < len; i++) { if (i <= len / 2) { acf_randtest(x + i, state, xbits, ebits); acf_randtest(y + i, state, ybits, ebits); } else { acf_neg(x + i, x + len - i - 1); acf_set(y + i, y + len - i - 1); } } break; default: for (i = 0; i < len; i++) { if (i <= len / 2) { acf_randtest(x + i, state, xbits, ebits); acf_randtest(y + i, state, ybits, ebits); } else { acf_neg_round(x + i, x + len - i - 1, 2 + n_randint(state, 500), ARF_RND_NEAR); acf_set_round(y + i, y + len - i - 1, 2 + n_randint(state, 500), ARF_RND_NEAR); } } break; } acf_randtest(s1, state, 200, 100); acf_randtest(s2, state, 200, 100); acf_randtest(z, state, xbits, ebits); acf_approx_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec, ARB_RND); /* With the fast algorithm, we expect identical results when reversing the vectors. */ if (ebits <= 12 && 0) { acf_approx_dot(s2, initial ? z : NULL, subtract, !revx ? (x + len - 1) : x, !revx ? -1 : 1, !revy ? (y + len - 1) : y, !revy ? -1 : 1, len, prec, ARB_RND); if (!acf_equal(s1, s2)) { flint_printf("FAIL (reversal)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); acf_printd(z, 100); flint_printf(" (%wd)\n\n", acf_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acf_printd(x + i, 100); flint_printf(" (%wd)\n", acf_bits(x + i)); flint_printf("y[%wd] = ", i); acf_printd(y + i, 100); flint_printf(" (%wd)\n", acf_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acf_printd(s1, 100); flint_printf("\n\n"); flint_printf("s2 = "); acf_printd(s2, 100); flint_printf("\n\n"); flint_abort(); } } /* Compare with acb_dot */ { acb_ptr ax, ay; acb_t as2, az; ax = _acb_vec_init(len); ay = _acb_vec_init(len); acb_init(as2); acb_init(az); for (i = 0; i < len; i++) { arb_set_arf(acb_realref(ax + i), acf_realref(x + i)); arb_set_arf(acb_imagref(ax + i), acf_imagref(x + i)); arb_set_arf(acb_realref(ay + i), acf_realref(y + i)); arb_set_arf(acb_imagref(ay + i), acf_imagref(y + i)); } if (initial) { arb_set_arf(acb_realref(az), acf_realref(z)); arb_set_arf(acb_imagref(az), acf_imagref(z)); } acb_dot(as2, initial ? az : NULL, subtract, revx ? (ax + len - 1) : ax, revx ? -1 : 1, revy ? (ay + len - 1) : ay, revy ? -1 : 1, len, prec); { mag_t err, xx, yy; mag_init(err); mag_init(xx); mag_init(yy); if (initial) acf_get_mag(err, z); for (i = 0; i < len; i++) { acf_get_mag(xx, revx ? x + len - 1 - i : x + i); acf_get_mag(yy, revx ? y + len - 1 - i : y + i); mag_addmul(err, xx, yy); } mag_mul_2exp_si(err, err, -prec + 2); acb_add_error_mag(as2, err); if (!arb_contains_arf(acb_realref(as2), acf_realref(s1)) || !arb_contains_arf(acb_imagref(as2), acf_imagref(s1))) { flint_printf("FAIL (inclusion)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); acf_printd(z, 100); flint_printf(" (%wd)\n\n", acf_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); acf_printd(x + i, 100); flint_printf(" (%wd)\n", acf_bits(x + i)); flint_printf("y[%wd] = ", i); acf_printd(y + i, 100); flint_printf(" (%wd)\n", acf_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); acf_printd(s1, 100); flint_printf("\n\n"); flint_printf("s2 = "); acb_printd(as2, 100); flint_printf("\n\n"); flint_abort(); } mag_clear(err); mag_clear(xx); mag_clear(yy); } _acb_vec_clear(ax, len); _acb_vec_clear(ay, len); acb_clear(as2); acb_clear(az); } acf_clear(s1); acf_clear(s2); acf_clear(z); _acf_vec_clear(x, len); _acf_vec_clear(y, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acf/test/t-init_clear.c000066400000000000000000000015201461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acf.h" TEST_FUNCTION_START(acf_init_clear, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { acf_t x, y; acf_init(x); acf_init(y); arf_randtest(acf_realref(x), state, 200, 100); arf_randtest(acf_imagref(x), state, 200, 100); acf_set(y, x); acf_clear(x); acf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/acf_types.h000066400000000000000000000013101461254215100155430ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ACF_TYPES_H #define ACF_TYPES_H #include "arf_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { arf_struct real; arf_struct imag; } acf_struct; typedef acf_struct acf_t[1]; typedef acf_struct * acf_ptr; typedef const acf_struct * acf_srcptr; #ifdef __cplusplus } #endif #endif /* ACF_TYPES_H */ flint-3.1.3/src/aprcl.h000066400000000000000000000202211461254215100146710ustar00rootroot00000000000000/* Copyright (C) 2015, Vladimir Glazchev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef APRCL_H #define APRCL_H #include "limb_types.h" #include "fmpz_types.h" #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif #define SQUARING_SPACE 70 /* Configuration struct */ typedef struct { ulong R; fmpz_t s; n_factor_t rs; fmpz_factor_t qs; int * qs_used; } _aprcl_config; typedef _aprcl_config aprcl_config[1]; /* Z[unity_root_q, unity_root_p]/(n) struct */ typedef struct { fmpz_mod_poly_t *polys; ulong p; ulong q; fmpz_mod_ctx_t ctx; } _unity_zpq; typedef _unity_zpq unity_zpq[1]; /* Z[unity_root]/(n) struct */ typedef struct { fmpz_mod_poly_t poly; ulong p; ulong exp; fmpz_mod_ctx_t ctx; } _unity_zp; typedef _unity_zp unity_zp[1]; /* Primality test status */ typedef enum { UNKNOWN, PRIME, COMPOSITE, PROBABPRIME } primality_test_status; int _aprcl_p_ind(const aprcl_config conf, ulong p); ulong aprcl_p_power_in_q(ulong q, ulong p); int aprcl_is_mul_coprime_ui_ui(ulong x, ulong y, const fmpz_t n); int aprcl_is_mul_coprime_ui_fmpz(ulong x, const fmpz_t y, const fmpz_t n); /* primality tests ***********************************************************/ int aprcl_is_prime(const fmpz_t n); /* Gauss test configuration */ void aprcl_config_gauss_init(aprcl_config conf, const fmpz_t n); void aprcl_config_gauss_init_min_R(aprcl_config conf, const fmpz_t n, ulong R); void aprcl_config_gauss_clear(aprcl_config conf); /* Jacobi test configuration */ ulong aprcl_R_value(const fmpz_t n); void aprcl_config_jacobi_init(aprcl_config conf, const fmpz_t n); void aprcl_config_jacobi_clear(aprcl_config conf); /* Gauss sums primality test */ int aprcl_is_prime_gauss(const fmpz_t n); int aprcl_is_prime_gauss_min_R(const fmpz_t n, ulong R); primality_test_status _aprcl_is_prime_gauss(const fmpz_t n, const aprcl_config config); int _aprcl_is_gausspower_2q_equal_first(ulong q, const fmpz_t n); int _aprcl_is_gausspower_2q_equal_second(ulong q, const fmpz_t n); slong _aprcl_is_gausspower_from_unity_p(ulong q, ulong r, const fmpz_t n); /* Jacobi sums primality test */ int aprcl_is_prime_jacobi(const fmpz_t n); primality_test_status _aprcl_is_prime_jacobi(const fmpz_t n, const aprcl_config config); slong _aprcl_is_prime_jacobi_check_pk(const unity_zp j, const fmpz_t u, ulong v); slong _aprcl_is_prime_jacobi_check_21(ulong q, const fmpz_t n); slong _aprcl_is_prime_jacobi_check_22(const unity_zp j, const fmpz_t u, ulong v, ulong q); slong _aprcl_is_prime_jacobi_check_2k(const unity_zp j, const unity_zp j2_1, const unity_zp j2_2, const fmpz_t u, ulong v); int _aprcl_is_prime_jacobi_additional_test(const fmpz_t n, ulong p); /* Final division function */ int aprcl_is_prime_final_division(const fmpz_t n, const fmpz_t s, ulong r); /* Z[unity_root]/(n) operations **********************************************/ /* Memory management */ void unity_zp_init(unity_zp f, ulong p, ulong exp, const fmpz_t n); void unity_zp_clear(unity_zp f); void unity_zp_copy(unity_zp f, const unity_zp g); void unity_zp_swap(unity_zp f, unity_zp g); void unity_zp_set_zero(unity_zp f); /* Comparison */ slong unity_zp_is_unity(unity_zp f); int unity_zp_equal(unity_zp f, unity_zp g); /* Coefficient management */ void unity_zp_coeff_set_fmpz(unity_zp f, ulong ind, const fmpz_t x); void unity_zp_coeff_set_ui(unity_zp f, ulong ind, ulong x); void unity_zp_coeff_add_fmpz(unity_zp f, ulong ind, const fmpz_t x); void unity_zp_coeff_add_ui(unity_zp f, ulong ind, ulong x); void unity_zp_coeff_inc(unity_zp f, ulong ind); void unity_zp_coeff_dec(unity_zp f, ulong ind); /* Scalar multiplication */ void unity_zp_mul_scalar_ui(unity_zp f, const unity_zp g, ulong s); /* Addition */ void unity_zp_add(unity_zp f, const unity_zp g, const unity_zp h); /* General multiplication and squaring */ void unity_zp_mul(unity_zp f, const unity_zp g, const unity_zp h); void unity_zp_sqr(unity_zp f, const unity_zp g); /* Special multiplication and squaring */ void unity_zp_mul_inplace(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_sqr_inplace(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_ar1(fmpz_t * t); void unity_zp_ar2(fmpz_t * t); void unity_zp_ar3(fmpz_t * t); void unity_zp_ar4(fmpz_t * t); void unity_zp_mul3(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_mul4(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_mul5(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_mul7(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_mul8(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_mul9(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_mul11(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_mul16(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); void unity_zp_sqr3(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_sqr4(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_sqr5(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_sqr7(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_sqr8(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_sqr9(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_sqr11(unity_zp f, const unity_zp g, fmpz_t * t); void unity_zp_sqr16(unity_zp f, const unity_zp g, fmpz_t * t); /* Powering functions */ void unity_zp_pow_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow); void unity_zp_pow_ui(unity_zp f, const unity_zp g, ulong pow); ulong _unity_zp_pow_select_k(const fmpz_t n); void unity_zp_pow_2k_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow); void unity_zp_pow_2k_ui(unity_zp f, const unity_zp g, ulong pow); void unity_zp_pow_sliding_fmpz(unity_zp f, unity_zp g, const fmpz_t pow); /* Cyclotomic reduction */ void _unity_zp_reduce_cyclotomic_divmod(unity_zp f); void _unity_zp_reduce_cyclotomic(unity_zp f); void unity_zp_reduce_cyclotomic(unity_zp f, const unity_zp g); /* Automorphism and inverse computation */ void unity_zp_aut(unity_zp f, const unity_zp g, ulong x); void unity_zp_aut_inv(unity_zp f, const unity_zp g, ulong x); /* Jacobi sum computation. */ mp_ptr aprcl_f_table(const ulong q); void _unity_zp_jacobi_sum_pq_general(unity_zp f, const mp_ptr table, ulong p, ulong q, ulong k, ulong a, ulong b); void unity_zp_jacobi_sum_pq(unity_zp f, ulong q, ulong p); void unity_zp_jacobi_sum_2q_one(unity_zp f, ulong q); void unity_zp_jacobi_sum_2q_two(unity_zp f, ulong q); /* Z[unity_root_q, unity_root_p]/(n) operations ******************************/ /* Memory management */ void unity_zpq_init(unity_zpq f, ulong q, ulong p, const fmpz_t n); void unity_zpq_clear(unity_zpq f); void unity_zpq_copy(unity_zpq f, const unity_zpq g); void unity_zpq_swap(unity_zpq f, unity_zpq g); /* Comparison */ int unity_zpq_equal(const unity_zpq f, const unity_zpq g); /* Coefficient management */ void unity_zpq_coeff_set_fmpz(unity_zpq f, slong i, slong j, const fmpz_t x); void unity_zpq_coeff_set_ui(unity_zpq f, slong i, slong j, ulong x); void unity_zpq_coeff_add(unity_zpq f, slong i, slong j, const fmpz_t x); void unity_zpq_coeff_add_ui(unity_zpq f, slong i, slong j, ulong x); /* Addition and multiplication */ void unity_zpq_add(unity_zpq f, const unity_zpq g, const unity_zpq h); void unity_zpq_mul(unity_zpq f, const unity_zpq g, const unity_zpq h); void _unity_zpq_mul_unity_p(unity_zpq f); void unity_zpq_mul_unity_p_pow(unity_zpq f, const unity_zpq g, slong p); /* Powering */ void unity_zpq_pow(unity_zpq f, const unity_zpq g, const fmpz_t p); void unity_zpq_pow_ui(unity_zpq f, const unity_zpq g, ulong pow); /* Gauss sum computation */ void unity_zpq_gauss_sum(unity_zpq f, ulong q, ulong p); void unity_zpq_gauss_sum_character_pow(unity_zpq f, ulong q, ulong p, ulong pow); void unity_zpq_gauss_sum_sigma_pow(unity_zpq f, ulong q, ulong p); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/aprcl/000077500000000000000000000000001461254215100145235ustar00rootroot00000000000000flint-3.1.3/src/aprcl/config_gauss.c000066400000000000000000000037701461254215100173450ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" #include "aprcl.h" static void _aprcl_config_gauss_update(aprcl_config conf) { ulong prime = 2; fmpz_set_ui(conf->s, 1); fmpz_factor_clear(conf->qs); fmpz_factor_init(conf->qs); conf->qs->sign = 1; while (2 * (prime - 1) <= conf->R) { if ((conf->R % (prime - 1)) == 0) { _fmpz_factor_append_ui(conf->qs, prime, 1); fmpz_mul_ui(conf->s, conf->s, prime); } prime++; while (n_is_prime(prime) == 0) prime++; } } void aprcl_config_gauss_init(aprcl_config conf, const fmpz_t n) { fmpz_t s2; fmpz_init_set_ui(s2, 0); fmpz_init(conf->s); fmpz_factor_init(conf->qs); conf->R = 1; while (fmpz_cmp(s2, n) <= 0) { conf->R += 1; _aprcl_config_gauss_update(conf); fmpz_mul(s2, conf->s, conf->s); } n_factor_init(&conf->rs); n_factor(&conf->rs, conf->R, 1); conf->qs_used = NULL; /* not used */ fmpz_clear(s2); } void aprcl_config_gauss_init_min_R(aprcl_config conf, const fmpz_t n, ulong R) { fmpz_t s2; fmpz_init_set_ui(s2, 0); fmpz_init(conf->s); fmpz_factor_init(conf->qs); conf->R = R - 1; while (fmpz_cmp(s2, n) <= 0) { conf->R += 1; _aprcl_config_gauss_update(conf); fmpz_mul(s2, conf->s, conf->s); } n_factor_init(&conf->rs); n_factor(&conf->rs, conf->R, 1); conf->qs_used = NULL; /* not used */ fmpz_clear(s2); } void aprcl_config_gauss_clear(aprcl_config conf) { fmpz_clear(conf->s); fmpz_factor_clear(conf->qs); } flint-3.1.3/src/aprcl/config_jacobi.c000066400000000000000000000137531461254215100174540ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __GNUC__ # define log __builtin_log #else # include #endif #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" #include "aprcl.h" ulong aprcl_R_value(const fmpz_t n) { ulong bits = fmpz_bits(n); if (bits <= 17) return 6; /* 2 * 3 */ if (bits <= 31) return 12; /* 2^2 * 3 */ if (bits <= 54) return 36; /* 2^2 * 3^2 */ if (bits <= 68) return 72; /* 2^3 * 3^2 */ if (bits <= 101) return 180; /* 2^2 * 3^2 * 5 */ if (bits <= 127) return 360; /* 2^3 * 3^2 * 5 */ if (bits <= 152) return 720; /* 2^4 * 3^2 * 5 */ if (bits <= 204) return 1260; /* 2^2 * 3^2 * 5 * 7 */ if (bits <= 268) return 2520; /* 2^3 * 3^2 * 5 * 7 */ if (bits <= 344) return 5040; /* 2^4 * 3^2 * 5 * 7 */ if (bits <= 525) return 27720; /* 2^3 * 3^2 * 5 * 7 * 11 */ if (bits <= 650) return 55440; /* 2^4 * 3^2 * 5 * 7 * 11 */ if (bits <= 774) return 110880; /* 2^5 * 3^2 * 5 * 7 * 11 */ if (bits <= 1566) return 720720; /* 2^4 * 3^2 * 5 * 7 * 11 * 13 */ if (bits <= 1999) return 1441440; /* 2^5 * 3^2 * 5 * 7 * 11 * 13 */ if (bits <= 2096) return 1663200; if (bits <= 2165) return 1965600; if (bits <= 2321) return 2162160; if (bits <= 2377) return 2827440; if (bits <= 2514) return 3326400; if (bits <= 2588) return 3341520; if (bits <= 2636) return 3603600; if (bits <= 3028) return 4324320; if (bits <= 3045) return 5654880; if (bits <= 3080) return 6652800; if (bits <= 3121) return 6683040; if (bits <= 3283) return 7207200; if (bits <= 3491) return 8648640; /* 2^6 * 3^3 * 5 * 7 * 11 * 13 */ if (bits <= 3726) return 10810800; if (bits <= 3818) return 12972960; if (bits <= 3977) return 14414400; if (bits <= 4762) return 21621600; if (bits <= 5068) return 36756720; if (bits <= 5658) return 43243200; if (bits <= 5960) return 64864800; if (bits <= 6423) return 73513440; if (bits <= 6900) return 122522400; if (bits <= 9977) return 367567200; if (bits <= 12713) return 1396755360; #if FLINT64 /* 2^5 * 3^3 * 5^2 * 7 * 11 * 13 * 17 * 19 */ return UWORD(6983776800); #else flint_throw(FLINT_ERROR, "APRCL not supported for huge numbers on 32 bits\n"); return 0; #endif } static void _aprcl_config_jacobi_reduce_s2(aprcl_config conf, const fmpz_t n) { ulong i, j, q; double * w; n_factor_t q_factors; fmpz_t new_s, p; fmpz_init(new_s); fmpz_init(p); w = (double *) flint_malloc(sizeof(double) * conf->qs->num); for (i = 0; i < conf->qs->num; i++) { conf->qs_used[i] = 1; q = fmpz_get_ui(conf->qs->p + i); n_factor_init(&q_factors); n_factor(&q_factors, q - 1, 1); w[i] = 0; for (j = 0; j < q_factors.num; j++) { ulong p, euler_phi; p = q_factors.p[j]; euler_phi = n_pow(p, q_factors.exp[j] - 1) * (p - 1); euler_phi = euler_phi * euler_phi; w[i] += euler_phi; } w[i] /= log((double) n_pow(q, conf->qs->exp[i])); } while (1) { double w_max; slong ind; w_max = -1; ind = -1; for (i = 0; i < conf->qs->num; i++) { if (conf->qs_used[i] == 0) continue; fmpz_pow_ui(p, conf->qs->p + i, conf->qs->exp[i]); fmpz_fdiv_q(new_s, conf->s, p); fmpz_mul(new_s, new_s, new_s); if (fmpz_cmp(new_s, n) > 0) if (w_max <= w[i]) { w_max = w[i]; ind = i; } } if (ind == -1) break; fmpz_pow_ui(p, conf->qs->p + ind, conf->qs->exp[ind]); fmpz_fdiv_q(new_s, conf->s, p); fmpz_set(conf->s, new_s); conf->qs_used[ind] = 0; } fmpz_clear(new_s); fmpz_clear(p); flint_free(w); } static void _aprcl_config_jacobi_update(aprcl_config conf) { ulong prime = 2; fmpz_set_ui(conf->s, 1); fmpz_factor_clear(conf->qs); fmpz_factor_init(conf->qs); conf->qs->sign = 1; _fmpz_factor_append_ui(conf->qs, prime, aprcl_p_power_in_q(conf->R, prime) + 2); fmpz_mul_ui(conf->s, conf->s, n_pow(prime, aprcl_p_power_in_q(conf->R, prime) + 2)); prime = 3; while (2 * (prime - 1) <= conf->R) { if ((conf->R % (prime - 1)) == 0) { _fmpz_factor_append_ui(conf->qs, prime, aprcl_p_power_in_q(conf->R, prime) + 1); fmpz_mul_ui(conf->s, conf->s, n_pow(prime, aprcl_p_power_in_q(conf->R, prime) + 1)); } prime++; while (n_is_prime(prime) == 0) prime++; } if (n_is_prime(conf->R + 1)) { _fmpz_factor_append_ui(conf->qs, conf->R + 1, 1); fmpz_mul_ui(conf->s, conf->s, conf->R + 1); } } /* Computes s = \prod q^(k + 1) ; q - prime, q - 1 | R; q^k | R and q^(k + 1) not | R */ void aprcl_config_jacobi_init(aprcl_config conf, const fmpz_t n) { fmpz_init(conf->s); fmpz_factor_init(conf->qs); conf->R = aprcl_R_value(n); _aprcl_config_jacobi_update(conf); n_factor_init(&conf->rs); n_factor(&conf->rs, conf->R, 1); conf->qs_used = (int *) flint_malloc(sizeof(int) * conf->qs->num); _aprcl_config_jacobi_reduce_s2(conf, n); } void aprcl_config_jacobi_clear(aprcl_config conf) { fmpz_clear(conf->s); fmpz_factor_clear(conf->qs); flint_free(conf->qs_used); } flint-3.1.3/src/aprcl/f_table.c000066400000000000000000000024641461254215100162710ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "aprcl.h" /* Returns a table of the function f: [1,2,...,q-2] -> [1,2,...,q-2] defined by $1 - g^x \equiv gf(x) \bmod q$, where $g$ is a primitive root modulo $q$. f_table[x - 1] = f(x). */ mp_ptr aprcl_f_table(const ulong q) { int i; ulong g, g_pow, qinv; mp_ptr g_table, f_table; g = n_primitive_root_prime(q); g_table = _nmod_vec_init(q); f_table = _nmod_vec_init(q); qinv = n_preinvert_limb(q); g_pow = g; /* g_table[g^i mod q] = i */ for (i = 1; i < q; i++) { g_table[g_pow] = i; g_pow = n_mulmod2_preinv(g_pow, g, q, qinv); } g_pow = g; /* f_table[i] such that g^f_table[i] = 1 - g^i mod q*/ for (i = 1; i < q; i++) { f_table[i] = g_table[n_submod(1, g_pow, q)]; g_pow = n_mulmod2_preinv(g_pow, g, q, qinv); } _nmod_vec_clear(g_table); return f_table; } flint-3.1.3/src/aprcl/is_mul_coprime.c000066400000000000000000000026231461254215100177000ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "aprcl.h" /* Returns 1 if gcd(x * y, n) == 1; otherwise returns 0. */ int aprcl_is_mul_coprime_ui_ui(ulong x, ulong y, const fmpz_t n) { ulong a, rem; int result = 0; rem = fmpz_tdiv_ui(n, x); a = n_gcd(x, rem); /* a = gcd(x, n % x) */ if (a == 1) { rem = fmpz_tdiv_ui(n, y); result = n_gcd(y, rem) == 1; /* result = gcd(y, m % y) */ } return result; } /* Returns 1 if gcd(x * y, n) == 1; otherwise returns 0. */ int aprcl_is_mul_coprime_ui_fmpz(ulong x, const fmpz_t y, const fmpz_t n) { int is_coprime = 0; ulong a, rem; fmpz_t result; fmpz_init(result); rem = fmpz_tdiv_ui(n, x); a = n_gcd(x, rem); /* a = gcd(x, n % x) */ if (a == 1) { fmpz_fdiv_r(result, n, y); /* result = n % y */ fmpz_gcd(result, result, y); /* result = gcd(y, n % y) */ is_coprime = fmpz_is_one(result); } fmpz_clear(result); return is_coprime; } flint-3.1.3/src/aprcl/is_prime.c000066400000000000000000000007401461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "aprcl.h" int aprcl_is_prime(const fmpz_t n) { return aprcl_is_prime_jacobi(n); } flint-3.1.3/src/aprcl/is_prime_final_division.c000066400000000000000000000024441461254215100215570ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "aprcl.h" int aprcl_is_prime_final_division(const fmpz_t n, const fmpz_t s, ulong r) { int result = 1; ulong i; fmpz_t npow, nmul, rem; fmpz_init(rem); fmpz_init_set(npow, n); fmpz_mod(npow, npow, s); /* npow = n mod s */ fmpz_init_set(nmul, npow); for (i = 1; i <= r; i++) { if (fmpz_is_one(npow)) break; fmpz_mod(rem, n, npow); /* if npow | n */ if (fmpz_is_zero(rem)) { /* if npow != n and npow != 1 */ if (!fmpz_equal(n, npow) && !fmpz_is_one(npow)) { /* npow | n, so n is composite */ result = 0; break; } } /* npow = n^i mod s */ fmpz_mul(npow, npow, nmul); fmpz_mod(npow, npow, s); } fmpz_clear(npow); fmpz_clear(nmul); fmpz_clear(rem); return result; } flint-3.1.3/src/aprcl/is_prime_gauss.c000066400000000000000000000271011461254215100177010ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "aprcl.h" /* Returns 1 if \tau^{\sigma_n-n}(\chi)=-1; otherwise returns 0. It is equal to check: (\chi(-1) * q)^((n - 1) / 2) congruent -1 mod n \tau is the Gauss sum; \chi is the character of conductor q and order 2 (quadratic character); \tau(\chi)^\sigma_n means \sigma_n(\tau(\chi)), there \sigma_n is the ring automorphism */ int _aprcl_is_gausspower_2q_equal_first(ulong q, const fmpz_t n) { int result; fmpz_t npow, nval, ncmp; fmpz_init_set(npow, n); fmpz_init_set_ui(nval, q); fmpz_init_set(ncmp, n); /* ncmp = -1 mod n */ fmpz_sub_ui(ncmp, ncmp, 1); /* nval = (\chi(-1) * q) = ((-1)^((q - 1) / 2) * q) */ if ((q - 1) % 2 == 1) { fmpz_neg(nval, nval); fmpz_add(nval, nval, n); } /* npow = (n - 1) / 2 */ fmpz_sub_ui(npow, npow, 1); fmpz_fdiv_q_2exp(npow, npow, 1); /* nval = (\chi(-1) * q)^((n - 1) / 2) mod n */ fmpz_powm(nval, nval, npow, n); result = 0; if (fmpz_equal(nval, ncmp)) result = 1; fmpz_clear(npow); fmpz_clear(nval); fmpz_clear(ncmp); return result; } /* Returns 1 if \tau^{\sigma_n-n}(\chi^{p / 2}) = -1; otherwise returns 0. It is equal to check: q^((n - 1) / 2) congruent -1 mod n \tau is the Gauss sum; \chi is the character of conductor q and order 2 (quadratic character); \tau(\chi)^\sigma_n means \sigma_n(\tau(\chi)), there \sigma_n is the ring automorphism */ int _aprcl_is_gausspower_2q_equal_second(ulong q, const fmpz_t n) { int result; fmpz_t npow, nval, ncmp; fmpz_init_set(npow, n); fmpz_init_set_ui(nval, q); fmpz_init_set(ncmp, n); /* ncmp = -1 mod n */ fmpz_sub_ui(ncmp, ncmp, 1); /* nval = q^((n - 1) / 2) mod n */ fmpz_sub_ui(npow, npow, 1); fmpz_fdiv_q_2exp(npow, npow, 1); fmpz_powm(nval, nval, npow, n); result = 0; if (fmpz_equal(nval, ncmp)) result = 1; fmpz_clear(npow); fmpz_clear(nval); fmpz_clear(ncmp); return result; } /* Returns non-negative value if \tau(\chi)^(\sigma_n - n) from <\zeta_p> cyclic group. It is equal to check that for some i from 0 to p - 1 \tau(\chi^n) == \zeta_p^i * \tau^n(\chi). If such i exists returns i. Otherwise returns -1. \tau is the Gauss sum; \chi is the character of conductor q and order r; \tau(\chi)^\sigma_n means \sigma_n(\tau(\chi)), there \sigma_n is the ring automorphism */ slong _aprcl_is_gausspower_from_unity_p(ulong q, ulong r, const fmpz_t n) { slong result; ulong i; unity_zpq temp, gauss, gausspow, gausssigma; unity_zpq_init(gauss, q, r, n); unity_zpq_init(gausssigma, q, r, n); unity_zpq_init(gausspow, q, r, n); unity_zpq_init(temp, q, r, n); /* gauss = \tau(\chi) */ unity_zpq_gauss_sum(gauss, q, r); /* gausssigma = \tau(\chi^n) */ unity_zpq_gauss_sum_sigma_pow(gausssigma, q, r); /* gausspow = \tau^n(\chi) */ unity_zpq_pow(gausspow, gauss, n); result = -1; for (i = 0; i < r; i++) { /* temp = \zeta_p^i * \tau^n(\chi) */ unity_zpq_mul_unity_p_pow(temp, gausspow, i); if (unity_zpq_equal(gausssigma, temp)) { result = i; break; } } unity_zpq_clear(gauss); unity_zpq_clear(gausssigma); unity_zpq_clear(gausspow); unity_zpq_clear(temp); return result; } primality_test_status _aprcl_is_prime_gauss(const fmpz_t n, const aprcl_config config) { int *lambdas; ulong i, j, k, nmod4; primality_test_status result; /* Condition (Lp) is satisfied iff: For each p | R we must show that for all prime r | n and all positive integers a there exists l such that: r^(p-1) congruent n^(l(p-1)) mod p^a If (Lp), then lambdas_p = 3. */ lambdas = (int*) flint_malloc(sizeof(int) * config->rs.num); for (i = 0; i < config->rs.num; i++) lambdas[i] = 0; result = PROBABPRIME; /* nmod4 = n % 4 */ nmod4 = fmpz_tdiv_ui(n, 4); /* for every prime q | s */ for (i = 0; i < config->qs->num; i++) { n_factor_t q_factors; ulong q; if (result == COMPOSITE) break; q = fmpz_get_ui(config->qs->p + i); /* n == q, q - prime => n - prime */ if (fmpz_equal_ui(n, q)) { result = PRIME; break; } /* find prime factors of q - 1 */ n_factor_init(&q_factors); n_factor(&q_factors, q - 1, 1); /* for every prime p | q - 1 */ for (j = 0; j < q_factors.num; j++) { int state, pind; ulong p; if (result == COMPOSITE) break; p = q_factors.p[j]; pind = _aprcl_p_ind(config, p); state = lambdas[pind]; /* (Lp.a) if p == 2 and n = 1 mod 4 then (Lp) is equal to: for quadratic character \chi (\tau(\chi))^(\sigma_n-n) = -1 */ if (p == 2 && state == 0 && nmod4 == 1) { if (_aprcl_is_gausspower_2q_equal_first(q, n) == 1) { state = 3; lambdas[pind] = state; } } /* (Lp.b) if p == 2, r = 2^k >= 4 and n = 3 mod 4 then (Lp) is equal to: 1) for quadratic character \chi (\tau(\chi^(r / 2)))^(\sigma_n-n) = -1 2) for character \chi = \chi_{r, q} (\tau(\chi))^(\sigma_n-n) is a generator of cyclic group <\zeta_r> if 1) is true, then lambdas_p = 1 if 2) is true, then lambdas_p = 2 if 1) and 2) is true, then lambdas_p = 3 */ if (p == 2 && (state == 0 || state == 2) && nmod4 == 3) { if (_aprcl_is_gausspower_2q_equal_second(q, n) == 1) { if (state == 2) state = 3; else state = 1; lambdas[pind] = state; } } /* for every prime power p^k | q - 1 */ for (k = 1; k <= q_factors.exp[j]; k++) { int unity_power; ulong r; /* r = p^k */ r = n_pow(p, k); /* if gcd(q*r, n) != 1 */ if (aprcl_is_mul_coprime_ui_ui(q, r, n) == 0) { result = COMPOSITE; break; } /* if exists z such that \tau(\chi^n) = \zeta_r^z*\tau^n(\chi) unity_power = z; otherwise unity_power = -1 */ unity_power = _aprcl_is_gausspower_from_unity_p(q, r, n); /* if unity_power < 0 then n is composite */ if (unity_power < 0) { result = COMPOSITE; break; } /* (Lp.c) if p > 2 then (Lp) is equal to: (\tau(\chi))^(\sigma_n - n) is a generator of cyclic group <\zeta_r> */ if (p > 2 && state == 0 && unity_power > 0) { ulong upow = unity_power; /* if gcd(r, unity_power) = 1 then (\tau(\chi))^(\sigma_n - n) is a generator */ if (n_gcd(r, upow) == 1) { state = 3; lambdas[pind] = state; } } /* (Lp.b) check 2) of (Lp) if p == 2 and nmod4 == 3 */ if (p == 2 && unity_power > 0 && (state == 0 || state == 1) && nmod4 == 3) { ulong upow = unity_power; if (n_gcd(r, upow) == 1) { if (state == 0) { state = 2; lambdas[pind] = state; } if (state == 1) { state = 3; lambdas[pind] = state; } } } } } } /* if for some p we have not proved (Lp) then n can be as prime or composite */ if (result == PROBABPRIME) for (i = 0; i < config->rs.num; i++) if (lambdas[i] != 3) result = UNKNOWN; /* if n can be prime we do final division */ if (result == UNKNOWN || result == PROBABPRIME) { int f_division; f_division = aprcl_is_prime_final_division(n, config->s, config->R); /* if (Lp) is true for all p | R and f_division == 1 then n - prime */ if (result == PROBABPRIME && f_division == 1) result = PRIME; /* if we not prove (Lp) for some p and f_division == 1 then n still can be prime */ if (result == UNKNOWN && f_division == 1) result = PROBABPRIME; /* if f_division == 0 so we find the divisor of n, so n - composite */ if (f_division == 0) result = COMPOSITE; } flint_free(lambdas); return result; } int aprcl_is_prime_gauss_min_R(const fmpz_t n, ulong R) { primality_test_status result; aprcl_config config; aprcl_config_gauss_init_min_R(config, n, R); result = _aprcl_is_prime_gauss(n, config); aprcl_config_gauss_clear(config); if (result == PRIME) return 1; return 0; } int aprcl_is_prime_gauss(const fmpz_t n) { ulong R; primality_test_status result; aprcl_config config; if (fmpz_cmp_ui(n, 2) < 0) return 0; aprcl_config_gauss_init_min_R(config, n, 180); result = _aprcl_is_prime_gauss(n, config); R = config->R; aprcl_config_gauss_clear(config); /* if result == PROBABPRIME it means that we have not proved (Lp) for some p (most likely we fail L.c step); we can try to use bigger R */ if (result == PROBABPRIME) { R = R * 2; aprcl_config_gauss_init_min_R(config, n, R); result = _aprcl_is_prime_gauss(n, config); aprcl_config_gauss_clear(config); } if (result == PROBABPRIME) { R = R * 3; aprcl_config_gauss_init_min_R(config, n, R); result = _aprcl_is_prime_gauss(n, config); aprcl_config_gauss_clear(config); } if (result == PROBABPRIME) { R = R * 5; aprcl_config_gauss_init_min_R(config, n, R); result = _aprcl_is_prime_gauss(n, config); aprcl_config_gauss_clear(config); } if (result == PROBABPRIME || result == UNKNOWN) { flint_throw(FLINT_ERROR, "aprcl_is_prime_gauss: failed to prove n prime for n = %s\n", fmpz_get_str(NULL, 10, n)); } if (result == PRIME) return 1; return 0; } flint-3.1.3/src/aprcl/is_prime_jacobi.c000066400000000000000000000565431461254215100200220ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "aprcl.h" /* Below is the implementation of primality test using Jacobi sums. The steps are described in: [1] "A Course in Computational Algebraic Number Theory" by H. Cohen For a different version of the algorithm, also see: [2] "Implementation of a New Primality Test" by H. Cohen and A.K. Lenstra The algorithm consist of 4 steps: (1.) Precomutation; (2.) Pseudoprime tests with Jacobi sums; (3.) Additional tests; (4.) Final trial division and primality proving. This file contains the implementation of steps (2.) and (3.). It also contains the Jacobi sum primality test. A small part of implementation of step (1.) is here and most are in config_jacobi.c file. (4.) implemented in function aprcl_is_prime_final_division(). Standard variables: n - number to check for primality; R - configuration parameter; s - configuration parameter depends on the R; s^2 > n; a^R = 1 mod s for all integer a coprime to s; q - prime number such that (q | s); p - prime number such that (p | q - 1); r - prime power p^k such that (r | q - 1) and not (r * p | q - 1); k - power of p in r; v - n % r; u - n / r; Standard notation: \zeta_p - p-th root of unity; \sigma_x - automorphism of Z[\zeta_p] for which \sigma_x(\zeta_p) = \zeta_p^x; \sigma_x^{-1} - inverse of \sigma_x; \chi_{p, q} - character defined by \chi_{p, q}(g^x) = \zeta_{p^k}^x, there g is a primitive root modulo q; J(p, q) - jacobi sum j(\chi_{p, q}, \chi_{p, q}); J_2(q) - jacobi sum ( j(\chi_{2, q}^{2^{k - 3}}, \chi_{2, q}^{3 * 2^{k - 3}}) )^2; J_3(q) - jacobi sum j(\chi_{2, q}, \chi_{2, q}, \chi_{2, q}) = J(2, q) * j(\chi_{2, q}^2, \chi_{2, q}); */ /*----------------------------------------------------------------------------*/ /* Checks the case p != 2. Computes j0 = j_{0, p, q}, jv = j_{v, p, q} and checks that j0^u * jv is root of unity. Parameters: j = J(p, q); u, v from standard variables; Returns: If there exist h such that j0^u * jv = \zeta_{p^k}^h returns h; otherwise returns -1. For details about j0 and jv see (i1a) in [2] or algorithm (9.1.28) step 4.a in [1]. */ slong _aprcl_is_prime_jacobi_check_pk(const unity_zp j, const fmpz_t u, ulong v) { slong h; ulong i, r; unity_zp j0, jv, temp, aut; /* initialization */ r = n_pow(j->p, j->exp); /* r = p^k */ unity_zp_init(j0, j->p, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(jv, j->p, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(temp, j->p, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(aut, j->p, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_coeff_set_ui(j0, 0, 1); /* j0 = 1 */ unity_zp_coeff_set_ui(jv, 0, 1); /* jv = 1 */ /* for i in 1..p^k */ for (i = 1; i <= r; i++) { /* only for i that coprime to p */ if (i % j->p == 0) continue; /* update j0 = \prod{\sigma_i^{-1}(j^i)} */ unity_zp_pow_ui(temp, j, i); _unity_zp_reduce_cyclotomic(temp); /* aut = \sigma_i^{-1}(temp) */ unity_zp_aut_inv(aut, temp, i); /* j0 *= aut */ unity_zp_mul(temp, j0, aut); unity_zp_swap(temp, j0); /* update jv = \prod{\sigma_i^{-1}(j^{(v * i) / r})} */ /* note: overflow in v * i is not a concern here */ unity_zp_pow_ui(temp, j, (v * i) / r); _unity_zp_reduce_cyclotomic(temp); /* aut = \sigma_i^{-1}(temp) */ unity_zp_aut_inv(aut, temp, i); /* jv *= aut */ unity_zp_mul(temp, jv, aut); unity_zp_swap(temp, jv); } /* temp = j0^u */ unity_zp_pow_sliding_fmpz(temp, j0, u); /* j0 = j0^u * jv */ unity_zp_mul(j0, jv, temp); /* try to find h */ h = unity_zp_is_unity(j0); /* clear */ unity_zp_clear(aut); unity_zp_clear(j0); unity_zp_clear(jv); unity_zp_clear(temp); return h; } /* Check the case p = 2 and k = 1. Computes j0 = j_{0, 2, q}, jv = j_{v, 2, q} and checks that j0^u * jv is root of unity. j^0^u * jv = (-q)^{(n - 1) / 2}. Parameters: q, n from standard variables; Returns: if j0^u * jv = 1 returns 0; if j0^u * jv = -1 returns 1; otherwise returns -1. For details see algorithm (9.1.28) step 4.d in [1]. */ slong _aprcl_is_prime_jacobi_check_21(ulong q, const fmpz_t n) { slong h; fmpz_t qpow, ndec, temp; /* initialization */ fmpz_init(temp); fmpz_init_set_ui(qpow, q); fmpz_init_set(ndec, n); /* qpow = -q mod n */ fmpz_sub(qpow, n, qpow); fmpz_sub_ui(ndec, ndec, 1); /* temp = (n - 1) / 2 */ fmpz_fdiv_q_2exp(temp, ndec, 1); /* qpow = (-q)^{(n - 1) / 2} */ fmpz_powm(qpow, qpow, temp, n); h = -1; /* check if qpow == +-1 */ if (fmpz_equal_ui(qpow, 1)) h = 0; if (fmpz_equal(qpow, ndec)) h = 1; /* clear */ fmpz_clear(temp); fmpz_clear(qpow); fmpz_clear(ndec); return h; } /* Check the case p = 2 and k = 2. Computes j0 = j_{0, 2, q}, jv = j_{v, 2, q} and checks that j0^u * jv is root of unity. Parameters: j = J(2, q); u, v, q from standard variables; Returns: If there exist h such that j0^u * jv = \zeta_{4}^h returns h \zeta_4^h \in (1, i, -1, -i); otherwise returns -1. For details see algorithm (9.1.28) step 4.c in [1]. */ slong _aprcl_is_prime_jacobi_check_22(const unity_zp j, const fmpz_t u, ulong v, ulong q) { slong h; unity_zp j0, jv, j_pow; /* initialization */ unity_zp_init(j_pow, 2, 2, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(j0, 2, 2, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(jv, 2, 2, fmpz_mod_ctx_modulus(j->ctx)); /* set j0 = q * j^2 */ unity_zp_mul(j_pow, j, j); unity_zp_mul_scalar_ui(j0, j_pow, q); /* if v == 1 jv = 1 if v == 3 jv = j^2 */ if (v == 1) unity_zp_coeff_set_ui(jv, 0, 1); else if (v == 3) unity_zp_swap(jv, j_pow); /* j0 = j0^u * jv */ unity_zp_pow_sliding_fmpz(j_pow, j0, u); unity_zp_mul(j0, jv, j_pow); /* try to find h */ h = unity_zp_is_unity(j0); /* clear */ unity_zp_clear(j_pow); unity_zp_clear(j0); unity_zp_clear(jv); return h; } /* Check the case p = 2 and k >= 3. Computes j0 = j_{0, 2, q}, jv = j_{v, 2, q} and checks that j0^u * jv is root of unity. Parameters: j = J(2, q); j2_1 = J_3(q); j2_2 = j_2(q); u, v from standard variables; Returns: If there exist h such that j0^u * jv = \zeta_{2^k}^h returns h otherwise returns -1. For details see algorithm (9.1.28) step 4.b in [1]. */ slong _aprcl_is_prime_jacobi_check_2k(const unity_zp j, const unity_zp j2_1, const unity_zp j2_2, const fmpz_t u, ulong v) { slong h; ulong i, r; unity_zp j_j0, j0, jv, temp, aut; /* initialization */ r = n_pow(j->p, j->exp); unity_zp_init(temp, 2, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(j_j0, 2, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(aut, 2, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(j0, 2, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_init(jv, 2, j->exp, fmpz_mod_ctx_modulus(j->ctx)); unity_zp_coeff_set_ui(j0, 0, 1); /* j0 = 1 */ unity_zp_coeff_set_ui(jv, 0, 1); /* jv = 1 */ /* j_j0 = J(2, q) * J_3(q) */ unity_zp_mul(j_j0, j, j2_1); /* for i in 1..p^k and (i == 1 or i == 3 mod 8) */ for (i = 1; i < r;) { /* i == 1 mod 8 */ /* update j0 = \prod{\sigma_i^{-1}(j^i)} */ unity_zp_pow_ui(temp, j_j0, i); _unity_zp_reduce_cyclotomic(temp); /* aut = \sigma_i^{-1}(temp) */ unity_zp_aut_inv(aut, temp, i); /* j0 *= aut */ unity_zp_mul(temp, j0, aut); unity_zp_swap(temp, j0); /* update jv = \prod{\sigma_i^{-1}(j^{(v * i) / r})} */ unity_zp_pow_ui(temp, j_j0, (v * i) / r); _unity_zp_reduce_cyclotomic(temp); /* aut = \sigma_i^{-1}(temp) */ unity_zp_aut_inv(aut, temp, i); /* jv *= aut */ unity_zp_mul(temp, jv, aut); unity_zp_swap(temp, jv); /* i == 3 mod 8 */ i += 2; /* update j0 = \prod{\sigma_i^{-1}(j^i)} */ unity_zp_pow_ui(temp, j_j0, i); _unity_zp_reduce_cyclotomic(temp); /* aut = \sigma_i^{-1}(temp) */ unity_zp_aut_inv(aut, temp, i); /* j0 *= aut */ unity_zp_mul(temp, j0, aut); unity_zp_swap(temp, j0); /* update jv = \prod{\sigma_i^{-1}(j^{(v * i) / r})} */ unity_zp_pow_ui(temp, j_j0, (v * i) / r); _unity_zp_reduce_cyclotomic(temp); /* aut = \sigma_i^{-1}(temp) */ unity_zp_aut_inv(aut, temp, i); /* jv *= aut */ unity_zp_mul(temp, jv, aut); unity_zp_swap(temp, jv); /* now again i == 1 mod 8 */ i += 6; } /* if v % 8 not congruent 1 or 3 modulo 8 then jv *= J_2(q)^2 */ if (v % 8 != 1 && v % 8 != 3) { unity_zp_mul(temp, j2_2, j2_2); unity_zp_mul(j_j0, jv, temp); unity_zp_swap(j_j0, jv); } /* set j0 = j0^u * jv */ unity_zp_pow_sliding_fmpz(temp, j0, u); unity_zp_mul(j0, jv, temp); /* try to find h */ h = unity_zp_is_unity(j0); /* clear */ unity_zp_clear(aut); unity_zp_clear(j0); unity_zp_clear(jv); unity_zp_clear(j_j0); unity_zp_clear(temp); return h; } /* Try to find prime number q such that: q == mod 2p; n^{(q - 1) / p} != 1 mod q; if p == 2 then 4 | q - 1 and 8 not | q - 1. If the q is found we have two cases: - if p == 2 verify 1) h from above is a primitive root; 2) q^{(n - 1) / 2} = -1 mod n; - if p != 2 verify 1) h from above is a primitive root; if this is not the case for (p, q) then n is composite. If we can't find q check p | n or if n is a perfect power; if so then n is composite. Otherwise n can be prime but we can't prove its primality. Parameters: n, p from standard variables; Returns: if n composite : returns 2; if n can be prime : returns 1; if we do not find q and n can be prime : returns 0. For details see algorithm (9.1.28) step 5 in [1]. */ int _aprcl_is_prime_jacobi_additional_test(const fmpz_t n, ulong p) { int result, p_counter, m; ulong q; fmpz_t npow, qmod; /* initialization */ result = 0; p_counter = 50; /* check only first 50 primes q = 2mp + 1 */ m = 9; /* begin from q = 2*9*p + 1 */ fmpz_init(npow); fmpz_init(qmod); /* check first 50 primes */ while (p_counter > 0) { /* q = 2mp + 1 and m is odd, so if p == 2 then q - 1 | 4 and not q - 1 | 8. */ q = 2 * m * p + 1; /* if q prime */ if (n_is_prime(q) && fmpz_fdiv_ui(n, q) != 0) { fmpz_set_ui(qmod, q); /* npow = n^{(q - 1) / p} */ fmpz_powm_ui(npow, n, (q - 1) / p, qmod); /* if n^{(q - 1) / p} != 1 mod n then we find q */ if (!fmpz_equal_ui(npow, 1)) break; /* else decrease the prime counter */ p_counter--; } /* m is still odd */ m += 2; } /* if we find q */ if (p_counter != 0) { if (fmpz_fdiv_ui(n, q) == 0 && !fmpz_equal_ui(n, q)) result = 2; else { ulong v, k; slong h; fmpz_t u; unity_zp jacobi_sum; fmpz_init(u); /* find max k such that p^k | q - 1; if p = 2 => k = 2 */ k = aprcl_p_power_in_q(q - 1, p); /* compute J(p, q) */ unity_zp_init(jacobi_sum, p, k, n); unity_zp_jacobi_sum_pq(jacobi_sum, q, p); /* compute u and v */ fmpz_tdiv_q_ui(u, n, n_pow(p, k)); v = fmpz_tdiv_ui(n, n_pow(p, k)); /* if p == 2 */ if (p == 2) { /* find h using p = 2, k = 2 */ h = _aprcl_is_prime_jacobi_check_22(jacobi_sum, u, v, q); /* if h not found or h not primitive root then n is composite */ if (h < 0 || h % 2 == 0) result = 2; else /* else verify condition for p = 2 */ { fmpz_t ndec, ndecdiv, qpow; fmpz_init_set(ndec, n); fmpz_init(ndecdiv); fmpz_init_set_ui(qpow, q); /* ndec = n - 1 */ fmpz_sub_ui(ndec, ndec, 1); /* ndecdiv = (n - 1) / 2 */ fmpz_fdiv_q_2exp(ndecdiv, ndec, 1); /* qpow = q^{(n - 1) / 2} */ fmpz_powm(qpow, qpow, ndecdiv, n); /* if q^{(n - 1) / 2} = -1 mod n then n can be prime */ if (fmpz_equal(qpow, ndec)) result = 1; else /* else n is composite */ result = 2; fmpz_clear(ndec); fmpz_clear(ndecdiv); fmpz_clear(qpow); } } else /* if p != 2 */ { /* find h using (2.a) */ h = _aprcl_is_prime_jacobi_check_pk(jacobi_sum, u, v); /* if h not found or h not primitive root then n is composite */ if (h < 0 || h % p == 0) result = 2; else /* else n can be prime */ result = 1; } fmpz_clear(u); unity_zp_clear(jacobi_sum); } } /* if we do not find a q then check (4.c) */ if (p_counter == 0) { fmpz_t root; if (fmpz_tdiv_ui(n, p) == 0) /* if p | n then n is composite */ result = 2; fmpz_init(root); if (fmpz_is_perfect_power(root, n)) /* if n is perfect power, composite */ result = 2; fmpz_clear(root); } /* otherwise we can't prove composite or prime */ /* clear */ fmpz_clear(npow); fmpz_clear(qmod); return result; } primality_test_status _aprcl_is_prime_jacobi(const fmpz_t n, const aprcl_config config) { int *lambdas; ulong i, j, nmod4; primality_test_status result; fmpz_t temp, p2, ndec, ndecdiv, u, q_pow; /* deal with primes that can divide R */ if (fmpz_cmp_ui(n, 2) == 0) return PRIME; if (fmpz_cmp_ui(n, 3) == 0) return PRIME; /* initialization */ fmpz_init(q_pow); fmpz_init(u); fmpz_init(temp); fmpz_init(p2); fmpz_init(ndecdiv); fmpz_init_set(ndec, n); fmpz_sub_ui(ndec, ndec, 1); fmpz_fdiv_q_2exp(ndecdiv, ndec, 1); result = PROBABPRIME; /* Condition (Lp) is satisfied iff: For each p | R we must show that for all prime r | n and all positive integers a there exists l such that: r^(p-1) congruent n^(l(p-1)) mod p^a If (Lp), then lambdas_p = 1. */ lambdas = (int*) flint_malloc(sizeof(int) * config->rs.num); /* nmod4 = n % 4 */ nmod4 = fmpz_tdiv_ui(n, 4); /* For every prime p | R, set lambdas_p: to 1 if p >= 3 and n^{p - 1} != 1 mod p^2; to 0 otherwise. */ for (i = 0; i < config->rs.num; i++) { ulong p = config->rs.p[i]; if (p > 2) { fmpz_set_ui(p2, p * p); fmpz_powm_ui(temp, n, p - 1, p2); if (fmpz_equal_ui(temp, 1) == 0) lambdas[i] = 1; else lambdas[i] = 0; } else lambdas[i] = 0; } /* check that s*R and n are coprime; if not then n is composite */ if (aprcl_is_mul_coprime_ui_fmpz(config->R, config->s, n) == 0) result = COMPOSITE; /* Begin pseudoprime tests with Jacobi sums step. */ /* for every prime q | s */ for (i = 0; i < config->qs->num; i++) { n_factor_t q_factors; ulong q; if (config->qs_used[i] == 0) continue; if (result == COMPOSITE) break; q = fmpz_get_ui(config->qs->p + i); /* set q; q must get into ulong */ /* if n == q; q - prime => n - prime */ if (fmpz_equal_ui(n, q)) { result = PRIME; break; } /* find prime factors of q - 1 */ n_factor_init(&q_factors); n_factor(&q_factors, q - 1, 1); /* for every prime p | q - 1 */ for (j = 0; j < q_factors.num; j++) { int pind; slong h; ulong v, p, r, k; unity_zp jacobi_sum, jacobi_sum2_1, jacobi_sum2_2; if (result == COMPOSITE) break; p = q_factors.p[j]; /* set p; p | q - 1 */ k = q_factors.exp[j]; /* set max k for which p^k | q - 1 */ r = n_pow(p, k); /* set r = p^k */ pind = _aprcl_p_ind(config, p); /* find index of p in lambdas */ /* if lambdas_p == 0 set q_pow = q^{(n - 1) / 2} and p == 2 */ fmpz_set_ui(q_pow, q); if (lambdas[pind] == 0 && p == 2) fmpz_powm(q_pow, q_pow, ndecdiv, n); /* compute u = n / r and v = n % r */ fmpz_tdiv_q_ui(u, n, r); v = fmpz_tdiv_ui(n, r); /* init unity_zp for jacobi sums */ unity_zp_init(jacobi_sum, p, k, n); unity_zp_init(jacobi_sum2_1, p, k, n); unity_zp_init(jacobi_sum2_2, p, k, n); /* compute set jacobi_sum = J(p, q) */ unity_zp_jacobi_sum_pq(jacobi_sum, q, p); /* if p == 2 and k >= 3 we also need to compute J_2(q) and J_3(q) */ if (p == 2 && k >= 3) { /* compute J_3(q) */ unity_zp_jacobi_sum_2q_one(jacobi_sum2_1, q); /* compute J_2(q) */ unity_zp_jacobi_sum_2q_two(jacobi_sum2_2, q); } if (p == 2 && k == 1) { h = _aprcl_is_prime_jacobi_check_21(q, n); /* if h not found then n is composite */ if (h < 0) result = COMPOSITE; /* check (Lp); if h == 1 (unity root = -1) and n % 4 == 1 then lambdas_2 = 1 */ if (lambdas[pind] == 0 && h == 1 && nmod4 == 1) lambdas[pind] = 1; } if (p == 2 && k == 2) { h = _aprcl_is_prime_jacobi_check_22(jacobi_sum, u, v, q); /* if h not found then n is composite */ if (h < 0) result = COMPOSITE; /* check (Lp); if h == 1 or 3 (unity root = -i or i) and q^{(n - 1) / 2} = -1 mod n then lambdas_2 = 1 */ if (h % 2 != 0 && lambdas[pind] == 0 && fmpz_equal(q_pow, ndec)) lambdas[pind] = 1; } if (p == 2 && k >= 3) { h = _aprcl_is_prime_jacobi_check_2k(jacobi_sum, jacobi_sum2_1, jacobi_sum2_2, u, v); /* if h not found then n is composite */ if (h < 0) result = COMPOSITE; /* check (Lp); if h % 2 != 0 (primitive unity root) and q^{(n - 1) / 2} = -1 mod n then lambdas_2 = 1 */ if (h % 2 != 0 && lambdas[pind] == 0 && fmpz_equal(q_pow, ndec)) lambdas[pind] = 1; } if (p != 2) { h = _aprcl_is_prime_jacobi_check_pk(jacobi_sum, u, v); /* if h not found then n is composite */ if (h < 0) result = COMPOSITE; /* check (Lp); if h % p != 0 (primitive unity root) then lambdas_p = 1 */ if (h % p != 0 && lambdas[pind] == 0) lambdas[pind] = 1; } /* clear unity_zp for jacobi sums */ unity_zp_clear(jacobi_sum); unity_zp_clear(jacobi_sum2_1); unity_zp_clear(jacobi_sum2_2); } } /* Begin L_p tests */ /* if n can be prime */ if (result == PROBABPRIME) { /* for every lambdas_p */ for (i = 0; i < config->rs.num; i++) { /* if lambdas_p == 0 need run additional test for p */ if (lambdas[i] == 0) { int r = _aprcl_is_prime_jacobi_additional_test(n, config->rs.p[i]); /* if r == 2 then we prove that n is composite */ if (r == 2) { result = COMPOSITE; } else if (r == 1) { /* if r == 1 then we check that n still can be prime */ lambdas[i] = 1; } else { /* if r == 0 then we can't find q and we can't prove n prime or composite */ result = UNKNOWN; } } } } /* Trial division and primality proving step */ /* If result = PROBAPRIME then all lambdas_p = 1. Using this information we know that: for every divisor p of f of n there exists i from 0..R-1 such that f == n^i mod s. This is done in aprcl_is_prime_final_division() function. */ if (result == PROBABPRIME) { /* if we don't find divisors of n then n is composite */ if (aprcl_is_prime_final_division(n, config->s, config->R) == 1) result = PRIME; else result = COMPOSITE; } /* clear */ flint_free(lambdas); fmpz_clear(u); fmpz_clear(q_pow); fmpz_clear(p2); fmpz_clear(ndec); fmpz_clear(ndecdiv); fmpz_clear(temp); return result; } int aprcl_is_prime_jacobi(const fmpz_t n) { primality_test_status result; aprcl_config config; /* Choose R and s values for n and store its factorisation. See definition in config_jacobi functions documentation. s^2 > n. */ aprcl_config_jacobi_init(config, n); result = _aprcl_is_prime_jacobi(n, config); aprcl_config_jacobi_clear(config); if (result == PROBABPRIME || result == UNKNOWN) { flint_throw(FLINT_ERROR, "aprcl_is_prime_jacobi: failed to prove n prime for n = %s\n", fmpz_get_str(NULL, 10, n)); } /* if we prove primality, returns 1 */ if (result == PRIME) return 1; return 0; } flint-3.1.3/src/aprcl/profile/000077500000000000000000000000001461254215100161635ustar00rootroot00000000000000flint-3.1.3/src/aprcl/profile/p-is_prime_aprcl.c000066400000000000000000001177301461254215100215650ustar00rootroot00000000000000/* Copyright 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "aprcl.h" void p_is_prime_repeat(fmpz_t * ns, int len) { int i; TIMEIT_START for (i = 0; i < len; i++) if (aprcl_is_prime(ns[i]) == 0) { flint_printf("Primality test failed\n"); flint_abort(); } TIMEIT_STOP } int main(void) { const int len = 5; FLINT_TEST_INIT(state); /* Using the primes from: https://primes.utm.edu/lists/small/ */ flint_printf("Primality test profiling for numbers from 10 to 300 digits\n"); flint_printf("All timings given for 5 numbers\n"); /* 10 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "5915587277", 10); fmpz_set_str(ns[1], "9576890767", 10); fmpz_set_str(ns[2], "5463458053", 10); fmpz_set_str(ns[3], "3367900313", 10); fmpz_set_str(ns[4], "2860486313", 10); flint_printf("10 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 20 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "48112959837082048697", 10); fmpz_set_str(ns[1], "29497513910652490397", 10); fmpz_set_str(ns[2], "71755440315342536873", 10); fmpz_set_str(ns[3], "66405897020462343733", 10); fmpz_set_str(ns[4], "12764787846358441471", 10); flint_printf("20 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 30 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "671998030559713968361666935769", 10); fmpz_set_str(ns[1], "590872612825179551336102196593", 10); fmpz_set_str(ns[2], "416064700201658306196320137931", 10); fmpz_set_str(ns[3], "115756986668303657898962467957", 10); fmpz_set_str(ns[4], "280829369862134719390036617067", 10); flint_printf("30 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 40 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "2425967623052370772757633156976982469681", 10); fmpz_set_str(ns[1], "6075380529345458860144577398704761614649", 10); fmpz_set_str(ns[2], "4384165182867240584805930970951575013697", 10); fmpz_set_str(ns[3], "6847944682037444681162770672798288913849", 10); fmpz_set_str(ns[4], "5570373270183181665098052481109678989411", 10); flint_printf("40 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 50 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "22953686867719691230002707821868552601124472329079", 10); fmpz_set_str(ns[1], "46484729803540183101830167875623788794533441216779", 10); fmpz_set_str(ns[2], "64495327731887693539738558691066839103388567300449", 10); fmpz_set_str(ns[3], "15452417011775787851951047309563159388840946309807", 10); fmpz_set_str(ns[4], "95647806479275528135733781266203904794419563064407", 10); flint_printf("50 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 60 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "622288097498926496141095869268883999563096063592498055290461", 10); fmpz_set_str(ns[1], "668486051696691190102895306426999370394054817506916629001851", 10); fmpz_set_str(ns[2], "361720912810755408215708460645842859722715865206816237944587", 10); fmpz_set_str(ns[3], "511704374946917490638851104912462284144240813125071454126151", 10); fmpz_set_str(ns[4], "470287785858076441566723507866751092927015824834881906763507", 10); flint_printf("60 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 70 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "4669523849932130508876392554713407521319117239637943224980015676156491", 10); fmpz_set_str(ns[1], "2409130781894986571956777721649968801511465915451196376269177305066867", 10); fmpz_set_str(ns[2], "7595009151080016652449223792726748985452052945413160073645842090827711", 10); fmpz_set_str(ns[3], "5885903965180586669073549360644800583458138238012033647539649735017287", 10); fmpz_set_str(ns[4], "9547848065153773335707495885453566120069130270246768806790708393909999", 10); flint_printf("70 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 80 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "18532395500947174450709383384936679868383424444311405679463280782405796233163977", 10); fmpz_set_str(ns[1], "54875133386847519273109693154204970395475080920935355580245252923343305939004903", 10); fmpz_set_str(ns[2], "40979218404449071854385509743772465043384063785613460568705289173181846900181503", 10); fmpz_set_str(ns[3], "19469495355310348270990592580191998639221450743640952620236903851789700309402857", 10); fmpz_set_str(ns[4], "67120333368520272532940669112228025474970578938046280618394371551488988323794243", 10); flint_printf("80 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 90 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "282755483533707287054752184321121345766861480697448703443857012153264407439766013042402571", 10); fmpz_set_str(ns[1], "463199005416013829210323411514132845972525641604435693287586851332821637442813833942427923", 10); fmpz_set_str(ns[2], "664869143773196608462001772779382650311673568542237852546715913135688434614731717844868261", 10); fmpz_set_str(ns[3], "204005728266090048777253207241416669051476369216501266754813821619984472224780876488344279", 10); fmpz_set_str(ns[4], "976522637021306403150551933319006137720124048624544172072735055780411834104862667155922841", 10); flint_printf("90 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 100 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077", 10); fmpz_set_str(ns[1], "5371393606024775251256550436773565977406724269152942136415762782810562554131599074907426010737503501", 10); fmpz_set_str(ns[2], "2908511952812557872434704820397229928450530253990158990550731991011846571635621025786879881561814989", 10); fmpz_set_str(ns[3], "7212610147295474909544523785043492409969382148186765460082500085393519556525921455588705423020751421", 10); fmpz_set_str(ns[4], "6513516734600035718300327211250928237178281758494417357560086828416863929270451437126021949850746381", 10); flint_printf("100 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 110 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "10513733234846849736873637829838635104309714688896631127438692162131857778044158273164093838937083421380041997", 10); fmpz_set_str(ns[1], "24684249032065892333066123534168930441269525239006410135714283699648991959894332868446109170827166448301044689", 10); fmpz_set_str(ns[2], "32998886283809577512914881459957314326750856532546837122557861905096711274255431870995137546575954361422085081", 10); fmpz_set_str(ns[3], "36261430139487433507414165833468680972181038593593271409697364115931523786727274410257181186996611100786935727", 10); fmpz_set_str(ns[4], "76921421106760125285550929240903354966370431827792714920086011488103952094969175731459908117375995349245839343", 10); flint_printf("110 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 120 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "171989218832470870857923701742780850419373475175043795375607676047792517311566339217543754147263751973899368604441353849", 10); fmpz_set_str(ns[1], "371132472088173209741153184981742771278849120163424101995797949338636074962048027958518451774716413729510755717494155299", 10); fmpz_set_str(ns[2], "420145406901811857791227072284165226561693483222287527567496017033892563342686752247587935117119306171161848593337649107", 10); fmpz_set_str(ns[3], "506283312611011343355256478253272463245968105632679003983305635125224133331073348553775052064302641255435067238306718511", 10); fmpz_set_str(ns[4], "897503957504227472139484199430066010338139343163145419280183314291067450988520718807102741476596034735471026312154231263", 10); flint_printf("120 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 130 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "1182911141497541140586615359230243592834259935951457923890100901143724702295750543180757886003762250822014770432406785975220712551", 10); fmpz_set_str(ns[1], "3007481519774841700447169103699480479257075158004429172505493169624211738165626204221653115518171895124254955050192476647393240549", 10); fmpz_set_str(ns[2], "4578487274208482739785211870551459143579948064875277467213620367693698827278583879146069992097475604136147868628836746016239588907", 10); fmpz_set_str(ns[3], "6539010935836249262943170849578201335017375258186767902505297465587122376751466876714291620849745334794779375900778144335240097113", 10); fmpz_set_str(ns[4], "8714772976381697859557965355791745997987728300226812732519702250463329265826033268926171610392211750044957719896320776794555146581", 10); flint_printf("130 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 140 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "11972074619991162245806805523618114505186632677199227008626207635331666111231564033315528198753090956109606784942142173066807025406537144269", 10); fmpz_set_str(ns[1], "21384673207444598953944295269132432413002706756010583952155931098725644623031415143234836631619334100621702323118864487149301235435577193841", 10); fmpz_set_str(ns[2], "40715419051417482519286539367794251058952189812236314107150220232148457082328798652774511688107134820082466929596616575469866935012183992821", 10); fmpz_set_str(ns[3], "49105133753678962419391374496727457097027115514864975959094375339860082156189031654878635228598019107441653554142227931036658923353143622433", 10); fmpz_set_str(ns[4], "66584720460899785255133191060974440278633915171229599356820775802394462756364476093414927157574862478083047015999630105316838183873438847653", 10); flint_printf("140 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 150 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "204616454475328391399619135615615385636808455963116802820729927402260635621645177248364272093977747839601125961863785073671961509749189348777945177811", 10); fmpz_set_str(ns[1], "291550339212810520584591717024643003222896524222464547399033563270236499245759688372706177143834849792024373534800701771810502419549113758796692666163", 10); fmpz_set_str(ns[2], "375558729886621567205449255384643401545510736101936314566046534513364279097663141755273454199533071264570131949667792104742749053406471675458926748329", 10); fmpz_set_str(ns[3], "533791764536500962982816454877600313815808544134584704665367971790938714376754987723404131641943766815146845004667377003395107827504566198008424339207", 10); fmpz_set_str(ns[4], "656692050181897513638241554199181923922955921760928836766304161790553989228223793461834703506872747071705167995972707253940099469869516422893633357693", 10); flint_printf("150 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 160 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "1081298104698286063813737967304568031406522676857739555339880517562925221530558524296599584286163751908713364829390795648074146197550782524900963175263757603219", 10); fmpz_set_str(ns[1], "3453221202185876906638629632175359499099670410652382616441386629981117932849225524689308950511055601388422752776562037360817653410867799137900072936906881621341", 10); fmpz_set_str(ns[2], "5527520013513581326121882167187180752073463254277609911934750350965822023838543172229709244319844670433804038920304644097364765738975596420673642099039975011363", 10); fmpz_set_str(ns[3], "8726641590503419650325196619937603416439489172580927797921688450581350540574217626151578525827423033276197489219680752921410238881917731681447358498204217268973", 10); fmpz_set_str(ns[4], "9379635662817322614032764342613018955177071738482024436203544111095204370743225356112956525567890031429756904091450073222354327129541982170431394374683183905361", 10); flint_printf("160 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 170 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "11067896864151107888327210475457768522190748228130894643297732650458556828346322177345544084702872726772673298479414374934206448595620856513559764913452487779500078246341", 10); fmpz_set_str(ns[1], "21160656367574879904377656869692416560544398642776271862237616754494681129688319299114321001429667792412314306472092655735101612562676478693400212218038544113953364215017", 10); fmpz_set_str(ns[2], "32559552391090806972524986110685454429554861128146958282307580573550839559287659656080789996587490910999032609385668148399053113719642305511467653200258413635664259044077", 10); fmpz_set_str(ns[3], "37745683039627526420239498495450014901855006768892775749597403587571970429951577000073551065765218057239528311184736067680411048526187122288661901211789066482483802580969", 10); fmpz_set_str(ns[4], "61666372912245863887684510042656975220774126438327774649153997946400603024380560713336470674573893680427095868805106128483007129797880040347838399734458883689665738771401", 10); flint_printf("170 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 180 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "142421590971309087406926930527203509136940618029846108794169863876683171607366571570400885831140555590135576733907110189937788062898855050894112651266072474307203583352058594056699", 10); fmpz_set_str(ns[1], "278344420100310216738042441752470108332323908618219525487053710207384771998286597135290418719526702385178365896340210957041552257518693488098683242070746473230980005141419410511409", 10); fmpz_set_str(ns[2], "539813721464880304831529082014022773775683060863538731923720954030918288330963319766918459920070168122735288577580167859459419843291482297756648680136952821437700382745720613744889", 10); fmpz_set_str(ns[3], "702859775508284030177919822558533006622440218103436237875100165464040768114702545328008730929739757973342358123790248243520711425000515624162703794316531258568583660237867578953203", 10); fmpz_set_str(ns[4], "988024003287850859144419046035039824149244726706784277084869779315425892879684597047236357710409517227957670271186515606462572615012822834344038901575679797975183588867579172966813", 10); flint_printf("180 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 190 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "2555480246614015637242066218495468367958491958791520916609927980929585688386540022963356429758954681777165591120866518535295021508514987925230304828573354059077193219265153006831360318167711", 10); fmpz_set_str(ns[1], "3643214290461749241398376492190485585384494258388704356737409156502890948489887688353135368121060124798243703432841307147301729071453564875847359568200406818058535340069409695144897237869317", 10); fmpz_set_str(ns[2], "4837500633209442055641398894165176677263201858612849667774338162796452956137875114054119135158253792745804801331435807680095292929070880966039245167637417105254552418199073193006899620258743", 10); fmpz_set_str(ns[3], "5077461915617371651811593607389848534613910665160223569902404065418076795944656510340577164207672426574638345121648036693344561339868694500127046808526397857391514634557427341972391976756821", 10); fmpz_set_str(ns[4], "6455677032078134615122923256047783642469165615329330252550539894033032422509072781300599341862693333305369588191523252516876513543095490001221889525858323800754356138220797092839047522855519", 10); flint_printf("190 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 200 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "15474811206486587193258690501682404626361341756658894201908294153626080782693777003022566996735796983239343580281979005677758015801189957392350213806122307985157041153484138150252828152419133170303749", 10); fmpz_set_str(ns[1], "28591045597720075832628274729885724490653298360003309382769144463123258670807750560985604954275365591715208615509779345682419533206637382048824349415329839450792353652240682445321955199147316594996133", 10); fmpz_set_str(ns[2], "41184172451867371867686906412307989908388177848827102865167949679167771021417488428983978626721272105583120243720400358313998904049755363682307706550788498535402989510396285940007396534556364659633739", 10); fmpz_set_str(ns[3], "58021664585639791181184025950440248398226136069516938232493687505822471836536824298822733710342250697739996825938232641940670857624514103125986134050997697160127301547995788468137887651823707102007839", 10); fmpz_set_str(ns[4], "71611195866368241734230315014260885890178941731009368469658803702463720956633120935294831101757574996161931982864195542669330457046568876289241536680683601749507786059442920003278263334056542642264651", 10); flint_printf("200 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 210 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593", 10); fmpz_set_str(ns[1], "110975366417606590833967199024636437460214709654546954443361638176229883140910302915147996598210506836614251268964446338737195911448213015377273363573074752120243818732263682864461580384738021460717565715722503", 10); fmpz_set_str(ns[2], "449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163", 10); fmpz_set_str(ns[3], "643808006803554439230129854961492699151386107534013432918073439524138264842370630061369715394739134090922937332590384720397133335969549256322620979036686633213903952966175107096769180017646161851573147596390153", 10); fmpz_set_str(ns[4], "964274047248418797145090983157197980855078966882276492572788532954904112655338439361306213898569516593744267391754033306465125919199692703323878557833023573312685002670662846477592597659826113460619815244721311", 10); flint_printf("210 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 220 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "1686497341353711305611314533713892867476872069660265164960400834285140167272334456461153902160145656434656190916734048745690082065807224646832960020851742291098965544262163963976377940891936112842489791084937115229985523", 10); fmpz_set_str(ns[1], "3082620745243449401694587258115336002381779641367375950273829476342471735062725180901036226278130762025829992363923955707979142964213859746930138447696031315806586014398729784266819509742760398915336761425413832264717163", 10); fmpz_set_str(ns[2], "4024609901503260810269407468691203815597240980490831121441008103456384399515806457060473646208324881470459201945576188438333273668474345882626708030947627287590124455488557086128125418355846343248375161824453194911368553", 10); fmpz_set_str(ns[3], "5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993", 10); fmpz_set_str(ns[4], "5569632747079549601598178420932244414970531646975337735765307429600364098163302494170010799604994405157512160053825953960398479355068806977610414154008753377194113913520943719945884635263031964263024822919752634970219699", 10); flint_printf("220 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 230 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "21300201301629210452464119866388466834939209799796743744566215971019835934873713391025654608111703142839573952969146866196732314492859634538441409805139418615474981665588472532863079300348061212642715504474934450531890795747236331", 10); fmpz_set_str(ns[1], "12245442024374614689109712434724272673056459509314527349744503469345912205668622170940248748257546033159240098557771252551702406748969563113679865954698092482472205671770925537241038679473374235787361928891214113717891603697678797", 10); fmpz_set_str(ns[2], "38762217770011076543812558980103749234859497948714246622214162442205108754782773687842018087751465069758232680421784403844939497206445510513337080943785005155511815286799602210383243566108920435480682463875028936997633500773799647", 10); fmpz_set_str(ns[3], "56125680981752282333498088313568935051383833838594899821664631784577337171193624243181360054669678410455329112434552942717084003541384594864129940145043086760031292483340068923506115878221189886491132772739661669044958531131327771", 10); fmpz_set_str(ns[4], "63556399829835331952308746203320003046976892440596186268797010059920148204359911235920191263570262537797901436399163646602402069151710265676725083444680749168670016260057105903268204928263311884485983112346974646808220605856122413", 10); flint_printf("230 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 240 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "120815570979701484704906977000760567182871429114712069861589084706550626575967516787438008593490722779337547394120718248995900363209947025063336882559539208430319216688889117222633155838468458047056355241515415159736436403445579777425189969", 10); fmpz_set_str(ns[1], "255112508897622985310494621898578485506502699374200456279537176322071752799387264311493082040326094068304025184818529912661589221508006459487667465358421280596050439152052898117848487594823639685476220238281599236511128329403379244547324431", 10); fmpz_set_str(ns[2], "429658446338661686643493725510284110493599954226035820905785008443520381887917251101430906695273248229134343944968312754799687049087615143654956740908022486161773863760198918360760883640680471523406895493680359160538947211150254456062366151", 10); fmpz_set_str(ns[3], "658385546911733550164516088405238961461880256029834598831972039469421755117818013653494814438931957316403111689187691446941406788869098983929874080332195117465344344350008880118042764943201875870917468833709791733282363323948005998269792207", 10); fmpz_set_str(ns[4], "963776490226810914179127416979112736599358462343660979133704637052985987395814985567964199253678349130533981848158045863245610061240372125223976414165504075241141636320276071785214612776961231843830877454050632964032066734998244033965101749", 10); flint_printf("240 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 250 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "1389116249243716847348088927848659359447606893455263094651000788996986658678996011997982077310912124848525958777046944012259203097866174509363711195882419322015576431662790538354378481778662165275630720476067089175069283834501499113947948000501538579", 10); fmpz_set_str(ns[1], "3416125484651880824649192099235033527914617803403701054777894769025318772710175775793367341953921714553521186823810932269184143033013016793222402163346724187114477766138018341566351560693965548954433712778344922065660960958894751416275568079834471541", 10); fmpz_set_str(ns[2], "5236828875479032067717626462856300906381035007260718615838669162211131824655260246937578375433262328206499459275581209388342892208784057258717047490425447217362253059951830269996579032687344642379285373251685453043862105987293264183501516155981651569", 10); fmpz_set_str(ns[3], "5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721", 10); fmpz_set_str(ns[4], "6325427919960049066585247837578372385418559154923477553398129089734082978096069693032859784967901396775824948679013568274245239986849282715816927424255093730637896848500237375779410539868274303393510928400955586603945601202203906813552017713600173613", 10); flint_printf("250 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 260 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "16107407153096872818493782945957787561325375534122812732915532201840816254400467958193423121840372946330339589450123508622134774121104116098949168616561321246035895208358144099325905467103390396346965217633409955370491728893923457194644438929148135544797769069", 10); fmpz_set_str(ns[1], "25290181317443223202462289639535568588026980307751030325846138922434211534444969788237980189518561067454419530259429589051181436567403701018238964718203056168955426581729913704293743890489851209326371108494646496297959925452431230546049667449322574935832180327", 10); fmpz_set_str(ns[2], "49642196519287563890219771644794994818956271978536893649678493707106697740616207443433039867021200759433868948129547546653564382798817640018032929084872815787149827529492755939735263141371178259217768571082104248486704273772193856448675375667327678108529811271", 10); fmpz_set_str(ns[3], "50985706168761488366316382338014644105350894561341788683522249832194333902444754897729974158787863583439645933374661244079621367847162487366917832904994676462834272619451739021241059378594481762281376106663491397418420352316354537398792605354478235631207230857", 10); fmpz_set_str(ns[4], "67456772536997811174562843827334166492604722726798354062809571765666143205478154891520988418820829227136251602140592962830914859588069638333300746582776692720637910854613289610057151587251089921722318897093966945777208101090776716402383331743368026418397556891", 10); flint_printf("260 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 270 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "170902679027143614381480059391075460977748667084652490023526958676379938833341709136279594902205355969210787455441130248035902265317439239727527609176424101012027295635928382169934598883924161721713564178522447830194403641544177926621519514748243624424803053704080264159", 10); fmpz_set_str(ns[1], "341542941372464534497852047268105389138631890905646486032000153894901449540580129450122392139802619604292752498326041347480618250352488051163893646047131867622060323720251466252698326430731130611964327062361372397940193111039277572779594686777531915056404892709536037639", 10); fmpz_set_str(ns[2], "471475783779117473437696117802417626487839062434599064863035821968629035024980502377134378815374602544529087517402940868050418215262184298226449528574182158863791371813026718349131181672601351927241854659801579851938035856589600671154437708549060762345454578611174965613", 10); fmpz_set_str(ns[3], "533908591185102096721484909806413036775185183352706309151302910709983373762043847868389077713822984385951546710427861029531444058770240205707393053275752747465332797251246740378632048744214547340674874776350282974442698782288381468714759061146399901895491734760806078183", 10); fmpz_set_str(ns[4], "630401459981890925871943502656990828862174194616722524583664885334493959070286140976851072711744928475299148378810029026986307409791403597358746752833626753147802185593071445295784983543019670778723774980356622160978299480879244289586779357458029514963543350008665423257", 10); flint_printf("270 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 280 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "2472773490088428133980402514441160210616362471988372788573252776560313375548879579643617872035716953544469744723310736110488902356856738414994328039965984433249491556806522755609731304100884485833876145266471071156842673554540732151138408860390316340855518308224087245071159274479", 10); fmpz_set_str(ns[1], "4502627151660440701021925419329909839338324685276222991558243422906343244255978228150075701850481154561057205207514930885060886603445774420800514839637354644396387390585531622698158148515281319634118340188729326221225299940392408901441649535445332397302718287942088535978634236221", 10); fmpz_set_str(ns[2], "5433381957526079619502954301327211367491752117714541408014490376067456113285722791097965934635155872134552184960882819005997047037814265447050608697209373083125903651449532919407946144950853232347970900124595900080331923968470611977246337077886181977132283382211753065664038103921", 10); fmpz_set_str(ns[3], "6761310901839275572586265703525965167391700024715455969978251868036124196491638874957886928031547478720430809462609191151492313143792903392719106050713843902317385520764341022452298421899503012580175228138841759425959660620124299740103602713372417764600890682511057074682657737071", 10); fmpz_set_str(ns[4], "8036474984942099540833063531872969308026120828502186792023446855615691106313478083033164185643655131177550064421680055607368972403502030505525586634272348294932475045273750810461772447879143316699989478715170989152555192208636375418186997456472778736820533608167526171909181155851", 10); flint_printf("280 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 290 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "16471581891701794764704009719057349996270239948993452268812975037240586099924712715366967486587417803753916334331355573776945238871512026832810626226164346328807407669366029926221415383560814338828449642265377822759768011406757061063524768140567867350208554439342320410551341675119078050953", 10); fmpz_set_str(ns[1], "28911710017320205966167820725313234361535259163045867986277478145081076845846493521348693253530011243988160148063424837895971948244167867236923919506962312185829914482993478947657472351461336729641485069323635424692930278888923450060546465883490944265147851036817433970984747733020522259537", 10); fmpz_set_str(ns[2], "36997438997453671132166865292569847244619444010395996997269402633033171733524207782461697123413414988859119764706460324782855919613943534861045216286685374559389860714010358938897470990143322775796082401132386180536650715835089633575578638914905606853502795766373129779823319637155282395679", 10); fmpz_set_str(ns[3], "47636001527157843615510166362212813825553995166349359052560828063795751982743949356281378571281356684995526346349689115319412565735006540850254022130876377867983398374239198108049044484863543699346022227692817853215225730056764957039852693911896900286014520659611654434776741074401112976951", 10); fmpz_set_str(ns[4], "66411949393245949268811711602826765576402057646975003006251042260813215340087318062380031915073315092183806206493533345953281647263552710655695269967337089850144857674638489475995919778552032603791816048265084649175429768094838031170157033168866305251844356097795408000548418783227194651709", 10); flint_printf("290 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } /* 300 digits primes */ { int i; fmpz_t * ns; ns = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * len); for (i = 0; i < 5; i++) fmpz_init(ns[i]); fmpz_set_str(ns[0], "203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123", 10); fmpz_set_str(ns[1], "250556952327646214427246777488032351712139094643988394726193347352092526616305469220133287929222242315761834129196430398011844978805263868522770723615504744438638381670321613949280530254014602887707960375752016807510602846590492724216092721283154099469988532068424757856392563537802339735359978831013", 10); fmpz_set_str(ns[2], "290245329165570025116016487217740287508837913295571609463914348778319654489118435855243301969001872061575755804802874062021927719647357060447135321577028929269578574760547268310055056867386875959045119093967972205124270441648450825188877095173754196346551952542599226295413057787340278528252358809329", 10); fmpz_set_str(ns[3], "319705304701141539155720137200974664666792526059405792539680974929469783512821793995613718943171723765238853752439032835985158829038528214925658918372196742089464683960239919950882355844766055365179937610326127675178857306260955550407044463370239890187189750909036833976197804646589380690779463976173", 10); fmpz_set_str(ns[4], "531872289054204184185084734375133399408303613982130856645299464930952178606045848877129147820387996428175564228204785846141207532462936339834139412401975338705794646595487324365194792822189473092273993580587964571659678084484152603881094176995594813302284232006001752128168901293560051833646881436219", 10); flint_printf("300 digit primes\n"); p_is_prime_repeat(ns, len); for (i = 0; i < 5; i++) fmpz_clear(ns[i]); flint_free(ns); } return 0; } flint-3.1.3/src/aprcl/profile/p-is_prime_aprcl_big.c000066400000000000000000000205271461254215100224030ustar00rootroot00000000000000/* Copyright 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "aprcl.h" void p_is_prime_repeat(fmpz_t n) { TIMEIT_START if (aprcl_is_prime(n) == 0) { flint_printf("Primality test failed\n"); flint_abort(); } TIMEIT_STOP } int main(void) { FLINT_TEST_INIT(state); /* Using the primes from mpz_aprcl implementation readme.txt file link : https://sourceforge.net/projects/mpzaprcl/ */ flint_printf("Primality test profiling for numbers from 350 to 2000 digits\n"); flint_printf("All timings given for one number\n"); /* 350 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 1160); fmpz_pow_ui(n, n, 114); fmpz_add_ui(n, n, 7); flint_printf("350 digit prime : 1160^114 + 7\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 400 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 291); fmpz_pow_ui(n, n, 163); fmpz_sub_ui(n, n, 1); fmpz_fdiv_q_ui(n, n, 290); flint_printf("400 digit prime : (291^163 - 1) / 290\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 450 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 232); fmpz_pow_ui(n, n, 190); fmpz_add_ui(n, n, 7); flint_printf("450 digit prime : 232^190 + 7\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 500 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 1014); fmpz_pow_ui(n, n, 166); fmpz_add_ui(n, n, 7); flint_printf("500 digit prime : 1014^166 + 7\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 550 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 549); fmpz_mul_ui(n, n, 9); fmpz_sub_ui(n, n, 7); flint_printf("550 digit prime : 10^549 * 9 - 7\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 600 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 1432); fmpz_pow_ui(n, n, 190); fmpz_add_ui(n, n, 7); flint_printf("600 digit prime : 1432^190 + 7\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 650 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 2); fmpz_pow_ui(n, n, 2159); fmpz_add_ui(n, n, 375); flint_printf("650 digit prime : 2^2159 + 375\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 700 digits prime */ { fmpz_t n1, n2; fmpz_init(n1); fmpz_init(n2); fmpz_set_ui(n1, 157); fmpz_pow_ui(n1, n1, 319); fmpz_set_ui(n2, 319); fmpz_pow_ui(n2, n2, 157); fmpz_add(n1, n1, n2); fmpz_fdiv_q_ui(n1, n1, 28); flint_printf("700 digit prime : (157^319 + 319^157) / 28\n"); p_is_prime_repeat(n1); fmpz_clear(n1); fmpz_clear(n2); } /* 750 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 749); fmpz_mul_ui(n, n, 2); fmpz_add_ui(n, n, 89); flint_printf("750 digit prime : 10^749 * 2 + 89\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 800 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 799); fmpz_mul_ui(n, n, 61); fmpz_sub_ui(n, n, 7); fmpz_fdiv_q_ui(n, n, 9); flint_printf("800 digit prime : (10^799 * 61 - 7) / 9\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 850 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 2); fmpz_pow_ui(n, n, 2821); fmpz_sub_ui(n, n, 183); flint_printf("850 digit prime : 2^2821 - 183\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 900 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 24); fmpz_pow_ui(n, n, 653); fmpz_sub_ui(n, n, 1); fmpz_fdiv_q_ui(n, n, 23); flint_printf("900 digit prime : (24^653 - 1) / 23\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 950 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 949); fmpz_mul_ui(n, n, 4); fmpz_sub_ui(n, n, 9); flint_printf("950 digit prime : 10^949 * 4 - 9\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1000 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 999); fmpz_add_ui(n, n, 7); flint_printf("1000 digit prime : 10^999 + 7\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1100 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 2); fmpz_pow_ui(n, n, 3653); fmpz_add_ui(n, n, 41); flint_printf("1100 digit prime : 2^3653 + 41\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1200 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 1199); fmpz_mul_ui(n, n, 5); fmpz_add_ui(n, n, 9); flint_printf("1200 digit prime : 10^1199 * 5 + 9\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1300 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 2); fmpz_pow_ui(n, n, 4318); fmpz_add_ui(n, n, 165); flint_printf("1300 digit prime : 2^4318 + 165\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1400 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 187); fmpz_pow_ui(n, n, 617); fmpz_sub_ui(n, n, 1); fmpz_fdiv_q_ui(n, n, 186); flint_printf("1400 digit prime : (187^617 - 1) / 186\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1500 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 2); fmpz_pow_ui(n, n, 4972); fmpz_mul_ui(n, n, 1779); fmpz_sub_ui(n, n, 1); flint_printf("1500 digit prime : 2^4972 * 1779 - 1\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1600 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 12); fmpz_pow_ui(n, n, 1483); fmpz_add_ui(n, n, 1); fmpz_fdiv_q_ui(n, n, 13); flint_printf("1600 digit prime : (12^1483 + 1) / 13\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1700 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 2); fmpz_pow_ui(n, n, 5644); fmpz_sub_ui(n, n, 227); flint_printf("1700 digit prime : 2^5644 - 227\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1800 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 1800); fmpz_sub_ui(n, n, 87); flint_printf("1800 digit prime : 10^1800 - 87\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 1900 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 10); fmpz_pow_ui(n, n, 1900); fmpz_add_ui(n, n, 3); fmpz_fdiv_q_ui(n, n, 7); flint_printf("1900 digit prime : (10^1900 + 3) / 7\n"); p_is_prime_repeat(n); fmpz_clear(n); } /* 2000 digits prime */ { fmpz_t n; fmpz_init(n); fmpz_set_ui(n, 2); fmpz_pow_ui(n, n, 6643); fmpz_mul_ui(n, n, 113); fmpz_add_ui(n, n, 1); fmpz_fdiv_q_ui(n, n, 115); flint_printf("2000 digit prime : (2^6643 * 113 + 1) / 115\n"); p_is_prime_repeat(n); fmpz_clear(n); } return 0; } flint-3.1.3/src/aprcl/test/000077500000000000000000000000001461254215100155025ustar00rootroot00000000000000flint-3.1.3/src/aprcl/test/main.c000066400000000000000000000062101461254215100165710ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-config_gauss.c" #include "t-config_jacobi.c" #include "t-f_table.c" #include "t-is_prime.c" #include "t-is_prime_gauss.c" #include "t-is_prime_jacobi.c" #include "t-unity_zp_add.c" #include "t-unity_zp_aut_inv.c" #include "t-unity_zp_equal.c" #include "t-unity_zp_init.c" #include "t-unity_zp_is_unity.c" #include "t-unity_zp_jacobi_sum.c" #include "t-unity_zp_mul11.c" #include "t-unity_zp_mul2.c" #include "t-unity_zp_mul3.c" #include "t-unity_zp_mul5.c" #include "t-unity_zp_mul7.c" #include "t-unity_zp_mul.c" #include "t-unity_zp_pow_2k.c" #include "t-unity_zp_pow.c" #include "t-unity_zp_pow_sliding.c" #include "t-unity_zpq_add.c" #include "t-unity_zpq_equal.c" #include "t-unity_zpq_gauss_sum.c" #include "t-unity_zpq_init.c" #include "t-unity_zpq_mul.c" #include "t-unity_zpq_mul_unity_p.c" #include "t-unity_zpq_pow.c" #include "t-unity_zp_reduce_cyclotomic.c" #include "t-unity_zp_sqr11.c" #include "t-unity_zp_sqr2.c" #include "t-unity_zp_sqr3.c" #include "t-unity_zp_sqr5.c" #include "t-unity_zp_sqr7.c" #include "t-unity_zp_sqr.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(aprcl_config_gauss), TEST_FUNCTION(aprcl_config_jacobi), TEST_FUNCTION(aprcl_f_table), TEST_FUNCTION(aprcl_is_prime), TEST_FUNCTION(aprcl_is_prime_gauss), TEST_FUNCTION(aprcl_is_prime_jacobi), TEST_FUNCTION(aprcl_unity_zp_add), TEST_FUNCTION(aprcl_unity_zp_aut_inv), TEST_FUNCTION(aprcl_unity_zp_equal), TEST_FUNCTION(aprcl_unity_zp_init), TEST_FUNCTION(aprcl_unity_zp_is_unity), TEST_FUNCTION(aprcl_unity_zp_jacobi_sum), TEST_FUNCTION(aprcl_unity_zp_mul11), TEST_FUNCTION(aprcl_unity_zp_mul2), TEST_FUNCTION(aprcl_unity_zp_mul3), TEST_FUNCTION(aprcl_unity_zp_mul5), TEST_FUNCTION(aprcl_unity_zp_mul7), TEST_FUNCTION(aprcl_unity_zp_mul), TEST_FUNCTION(aprcl_unity_zp_pow_2k), TEST_FUNCTION(aprcl_unity_zp_pow), TEST_FUNCTION(aprcl_unity_zp_pow_sliding), TEST_FUNCTION(aprcl_unity_zpq_add), TEST_FUNCTION(aprcl_unity_zpq_equal), TEST_FUNCTION(aprcl_unity_zpq_gauss_sum), TEST_FUNCTION(aprcl_unity_zpq_init), TEST_FUNCTION(aprcl_unity_zpq_mul), TEST_FUNCTION(aprcl_unity_zpq_mul_unity_p), TEST_FUNCTION(aprcl_unity_zpq_pow), TEST_FUNCTION(aprcl_unity_zp_reduce_cyclotomic), TEST_FUNCTION(aprcl_unity_zp_sqr11), TEST_FUNCTION(aprcl_unity_zp_sqr2), TEST_FUNCTION(aprcl_unity_zp_sqr3), TEST_FUNCTION(aprcl_unity_zp_sqr5), TEST_FUNCTION(aprcl_unity_zp_sqr7), TEST_FUNCTION(aprcl_unity_zp_sqr) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/aprcl/test/t-config_gauss.c000066400000000000000000000022521461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_config_gauss, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t n, s2; aprcl_config conf; fmpz_init(s2); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); aprcl_config_gauss_init(conf, n); fmpz_mul(s2, conf->s, conf->s); if (fmpz_cmp(s2, n) <= 0) { flint_printf("FAIL:\n"); flint_printf("s^2 = "); fmpz_print(s2); flint_printf(" <= "); fmpz_print(n); fflush(stdout); flint_abort(); } aprcl_config_gauss_clear(conf); fmpz_clear(n); fmpz_clear(s2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-config_jacobi.c000066400000000000000000000022561461254215100206700ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_config_jacobi, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t n, s2; aprcl_config conf; fmpz_init(n); fmpz_init(s2); fmpz_randtest_unsigned(n, state, 1000); aprcl_config_jacobi_init(conf, n); fmpz_mul(s2, conf->s, conf->s); if (fmpz_cmp(s2, n) <= 0) { flint_printf("FAIL:\n"); flint_printf("s^2 = "); fmpz_print(s2); flint_printf(" <= "); fmpz_print(n); fflush(stdout); flint_abort(); } aprcl_config_jacobi_clear(conf); fmpz_clear(s2); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-f_table.c000066400000000000000000000025611461254215100175070ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_f_table, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong len, q, p, g; mp_ptr table; len = n_randint(state, 16); while (len < 2) len = n_randint(state, 16); q = n_randprime(state, len, 1); g = n_primitive_root_prime(q); p = q - 2; table = aprcl_f_table(q); for (j = 1; j <= p; j++) { ulong g_powx, g_powfx; g_powx = n_powmod(g, j, q); g_powfx = n_powmod(g, table[j], q); if (n_submod(1, g_powx, q) != g_powfx) { flint_printf("FAIL:\n"); flint_printf("1 - %wu != %wu mod %wu\n", g_powx, g_powfx, q); fflush(stdout); flint_abort(); } } _nmod_vec_clear(table); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-is_prime.c000066400000000000000000000023521461254215100177200ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_is_prime, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { int pbprime, cycloprime; fmpz_t n; fmpz_init(n); fmpz_randtest_unsigned(n, state, 1000); while (fmpz_cmp_ui(n, 100) <= 0) fmpz_randtest_unsigned(n, state, 1000); pbprime = fmpz_is_probabprime(n); cycloprime = aprcl_is_prime_jacobi(n); if (pbprime != cycloprime) { flint_printf("FAIL\n"); flint_printf("Testing number = "); fmpz_print(n); flint_printf("\nis_probabprime = %i, aprcl_is_prime_jacobi = %i\n", pbprime, cycloprime); fflush(stdout); flint_abort(); } fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-is_prime_gauss.c000066400000000000000000000052401461254215100211210ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_is_prime_gauss, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { int pbprime, cycloprime; fmpz_t n; fmpz_init(n); fmpz_randtest_unsigned(n, state, 50); while (fmpz_cmp_ui(n, 100) <= 0) fmpz_randtest_unsigned(n, state, 50); pbprime = fmpz_is_probabprime(n); cycloprime = aprcl_is_prime_gauss(n); if (pbprime != cycloprime) { flint_printf("FAIL\n"); flint_printf("Testing number = "); fmpz_print(n); flint_printf("\nis_probabprime = %i, aprcl_is_prime_gauss = %i\n", pbprime, cycloprime); fflush(stdout); flint_abort(); } fmpz_clear(n); } { int result; fmpz_t n; fmpz_init(n); result = 1; /* Test big primes. */ fmpz_set_str(n, "40206835204840513073", 10); if (aprcl_is_prime_gauss(n) == 0) result = 0; /* 521419622856657689423872613771 % 4 == 3 */ fmpz_set_str(n, "521419622856657689423872613771", 10); if (aprcl_is_prime_gauss(n) == 0) result = 0; /* Very slow. */ if (flint_test_multiplier() > 10) { /* 5991810554633396517767024967580894321153 % 4 == 1 */ fmpz_set_str(n, "5991810554633396517767024967580894321153", 10); if (aprcl_is_prime_gauss(n) == 0) result = 0; } /* Test big composite. */ /* 1500450271 * 5915587277 */ fmpz_set_str(n, "8876044532898802067", 10); if (aprcl_is_prime_gauss(n) == 1) result = 0; /* 5915587277 * 54673257461630679457 */ fmpz_set_str(n, "323424426232167763068694468589", 10); if (aprcl_is_prime_gauss(n) == 1) result = 0; /* 48112959837082048697 * 66405897020462343733 */ fmpz_set_str(n, "3194984256290911228520362769161858765901", 10); if (aprcl_is_prime_gauss(n) == 1) result = 0; if (result == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-is_prime_jacobi.c000066400000000000000000000141061461254215100212270ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_is_prime_jacobi, state) { int i; /* Test _aprcl_is_prime_jacobi_check_pk() */ { ulong p, q, v, k, p_pow; unity_zp j; fmpz_t n, u; q = 19; p = 3; k = 2; p_pow = n_pow(p, k); fmpz_init(u); fmpz_init_set_ui(n, 31); fmpz_tdiv_q_ui(u, n, p_pow); v = fmpz_tdiv_ui(n, p_pow); unity_zp_init(j, p, k, n); unity_zp_jacobi_sum_pq(j, q, p); if (_aprcl_is_prime_jacobi_check_pk(j, u, v) < 0) { flint_printf("FAIL\n"); flint_printf("in function _aprcl_is_prime_jacobi_check_pk() wrong answer\n"); fflush(stdout); flint_abort(); } unity_zp_clear(j); fmpz_clear(n); fmpz_clear(u); } /* Test _aprcl_is_prime_jacobi_check_21() */ { ulong q; fmpz_t n; q = 7; fmpz_init_set_ui(n, 101); if (_aprcl_is_prime_jacobi_check_21(q, n) < 0) { flint_printf("FAIL\n"); flint_printf("in function _aprcl_is_prime_jacobi_check_21() wrong answer\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); } /* Test _aprcl_is_prime_jacobi_check_22() */ { ulong p, q, v, k, p_pow; unity_zp j; fmpz_t n, u; q = 13; p = 2; k = 2; p_pow = n_pow(p, k); fmpz_init(u); fmpz_init_set_ui(n, 659); fmpz_tdiv_q_ui(u, n, p_pow); v = fmpz_tdiv_ui(n, p_pow); unity_zp_init(j, p, k, n); unity_zp_jacobi_sum_pq(j, q, p); if (_aprcl_is_prime_jacobi_check_22(j, u, v, q) < 0) { flint_printf("FAIL\n"); flint_printf("in function _aprcl_is_prime_jacobi_check_22() wrong answer\n"); fflush(stdout); flint_abort(); } unity_zp_clear(j); fmpz_clear(n); fmpz_clear(u); } /* Test _aprcl_is_prime_jacobi_check_2k() */ { ulong p, q, v, k, p_pow; unity_zp j, j2_1, j2_2; fmpz_t n, u; q = 41; p = 2; k = 3; p_pow = n_pow(p, k); fmpz_init(u); fmpz_init_set_ui(n, 101); fmpz_tdiv_q_ui(u, n, p_pow); v = fmpz_tdiv_ui(n, p_pow); unity_zp_init(j, p, k, n); unity_zp_init(j2_1, p, k, n); unity_zp_init(j2_2, p, k, n); unity_zp_jacobi_sum_pq(j, q, p); unity_zp_jacobi_sum_2q_one(j2_1, q); unity_zp_jacobi_sum_2q_two(j2_2, q); if (_aprcl_is_prime_jacobi_check_2k(j, j2_1, j2_2, u, v) < 0) { flint_printf("FAIL\n"); flint_printf("in function _aprcl_is_prime_jacobi_check_2k() wrong answer\n"); fflush(stdout); flint_abort(); } unity_zp_clear(j); unity_zp_clear(j2_1); unity_zp_clear(j2_2); fmpz_clear(n); fmpz_clear(u); } /* Test aprcl_is_prime_jacobi. */ { for (i = 0; i < 200 * flint_test_multiplier(); i++) { int pbprime, cycloprime; fmpz_t n; fmpz_init(n); fmpz_randtest_unsigned(n, state, 1000); while (fmpz_cmp_ui(n, 100) <= 0) fmpz_randtest_unsigned(n, state, 1000); pbprime = fmpz_is_probabprime(n); cycloprime = aprcl_is_prime_jacobi(n); if (pbprime != cycloprime) { flint_printf("FAIL\n"); flint_printf("Testing number = "); fmpz_print(n); flint_printf("\nis_probabprime = %i, aprcl_is_prime_jacobi = %i\n", pbprime, cycloprime); fflush(stdout); flint_abort(); } fmpz_clear(n); } { int result; fmpz_t n; fmpz_init(n); result = 1; /* Test big primes. */ fmpz_set_str(n, "40206835204840513073", 10); if (aprcl_is_prime_jacobi(n) == 0) result = 0; /* 521419622856657689423872613771 % 4 == 3 */ fmpz_set_str(n, "521419622856657689423872613771", 10); if (aprcl_is_prime_jacobi(n) == 0) result = 0; /* 5991810554633396517767024967580894321153 % 4 == 1 */ fmpz_set_str(n, "5991810554633396517767024967580894321153", 10); if (aprcl_is_prime_jacobi(n) == 0) result = 0; fmpz_set_str(n, "2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077", 10); if (aprcl_is_prime_jacobi(n) == 0) result = 0; /* prime power */ fmpz_pow_ui(n, n, 7); if (aprcl_is_prime_jacobi(n) == 1) result = 0; /* Test big composite. */ /* 1500450271 * 5915587277 */ fmpz_set_str(n, "8876044532898802067", 10); if (aprcl_is_prime_jacobi(n) == 1) result = 0; /* 5915587277 * 54673257461630679457 */ fmpz_set_str(n, "323424426232167763068694468589", 10); if (aprcl_is_prime_jacobi(n) == 1) result = 0; /* 48112959837082048697 * 66405897020462343733 */ fmpz_set_str(n, "3194984256290911228520362769161858765901", 10); if (aprcl_is_prime_jacobi(n) == 1) result = 0; if (result == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_add.c000066400000000000000000000036231461254215100206040ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_add, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g, h1, h2; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h1, p, 1, n); unity_zp_init(h2, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1, val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, p); fmpz_randtest_not_zero(val1, state, 200); fmpz_randtest_not_zero(val2, state, 200); unity_zp_coeff_set_fmpz(h1, ind, val1); unity_zp_coeff_set_fmpz(h2, ind, val2); fmpz_add(val1, val1, val2); unity_zp_coeff_set_fmpz(g, ind, val1); fmpz_clear(val1); fmpz_clear(val2); } unity_zp_add(f, h1, h2); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h1); unity_zp_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_aut_inv.c000066400000000000000000000043001461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_aut_inv, state) { ulong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong ind, q, p, k, x; fmpz_t n; unity_zp f, g, h; n_factor_t q_factors; n_factor_init(&q_factors); q = n_randprime(state, 2 + n_randint(state, 6), 0); while (q < 3) q = n_randprime(state, 2 + n_randint(state, 6), 0); n_factor(&q_factors, q - 1, 1); ind = n_randint(state, q_factors.num); p = q_factors.p[ind]; k = q_factors.exp[ind]; x = n_randint(state, n_pow(p, k)); while (n_gcd(p, x) != 1 || x == 0) x = n_randint(state, n_pow(p, k)); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(h, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(g, ind, val); fmpz_clear(val); } /* reduce random element h */ unity_zp_reduce_cyclotomic(h, g); /* \sigma_x(f) == h now */ unity_zp_aut_inv(f, h, x); /* g = \sigma_x(f) */ unity_zp_aut(g, f, x); if (unity_zp_equal(h, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_equal.c000066400000000000000000000030161461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_equal, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_not_zero(val, state, 300); unity_zp_coeff_set_fmpz(f, ind, val); unity_zp_coeff_set_fmpz(g, ind, val); fmpz_clear(val); } if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_init.c000066400000000000000000000016211461254215100210130ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_init, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); fmpz_add_ui(n, n, 1); unity_zp_init(f, p, 1, n); unity_zp_clear(f); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_is_unity.c000066400000000000000000000025001461254215100217100ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_is_unity, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, exp; fmpz_t n; unity_zp f; ulong ind; p = n_randprime(state, 2 + n_randint(state, 4), 0); exp = n_randint(state, 5); while (exp == 0) exp = n_randint(state, 5); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); ind = n_randint(state, n_pow(p, exp)); unity_zp_coeff_set_ui(f, ind, 1); if (unity_zp_is_unity(f) < 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_jacobi_sum.c000066400000000000000000000106611461254215100221670ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_vec.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_jacobi_sum, state) { int i, j; /* test computation of j(\chi_{p, q}, \chi_{p, q}) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong ind, q, p, k; fmpz_t n; unity_zp f, g; n_factor_t q_factors; mp_ptr table; n_factor_init(&q_factors); q = n_randprime(state, 2 + n_randint(state, 4), 0); while (q < 3) q = n_randprime(state, 2 + n_randint(state, 4), 0); n_factor(&q_factors, q - 1, 1); ind = n_randint(state, q_factors.num); p = q_factors.p[ind]; k = q_factors.exp[ind]; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); table = aprcl_f_table(q); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); for (j = 1; j < q - 1; j++) { unity_zp_coeff_inc(g, j + table[j]); } _unity_zp_reduce_cyclotomic(g); unity_zp_jacobi_sum_pq(f, q, p); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); _nmod_vec_clear(table); } /* test computation of j(\chi_{2, q}^{2^{k - 3}}, \chi_{2, q}^{3 * 2^{k - 3}}))^2 */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong q, p, k; fmpz_t n; unity_zp f, g; n_factor_t q_factors; mp_ptr table; n_factor_init(&q_factors); q = n_randprime(state, 2 + n_randint(state, 4), 0); while (q < 3) q = n_randprime(state, 2 + n_randint(state, 4), 0); n_factor(&q_factors, q - 1, 1); p = 2; k = q_factors.exp[0]; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); table = aprcl_f_table(q); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); for (j = 1; j < q - 1; j++) { unity_zp_coeff_inc(g, 2 * j + table[j]); } _unity_zp_reduce_cyclotomic(g); unity_zp_jacobi_sum_2q_one(f, q); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); _nmod_vec_clear(table); } /* test computation of j(\chi_{2, q}, \chi_{2, q}, \chi_{2, q}) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong a, b, q, p, k; fmpz_t n; unity_zp f, g; n_factor_t q_factors; mp_ptr table; n_factor_init(&q_factors); q = n_randprime(state, 2 + n_randint(state, 6), 0); while (q < 3) q = n_randprime(state, 2 + n_randint(state, 6), 0); n_factor(&q_factors, q - 1, 1); p = 2; k = q_factors.exp[0]; if (k < 3) continue; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); table = aprcl_f_table(q); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); b = n_pow(2, k - 3); a = 3 * b; for (j = 1; j < q - 1; j++) { unity_zp_coeff_inc(g, a * j + b * table[j]); } _unity_zp_reduce_cyclotomic(g); unity_zp_jacobi_sum_2q_two(f, q); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); _nmod_vec_clear(table); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_mul.c000066400000000000000000000057361461254215100206600ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_mul, state) { int i, j; /* test that \zeta_p^i * \zeta_p^j computest correctly */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, ind1, ind2; fmpz_t n; unity_zp f, g, h1, h2; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h1, p, 1, n); unity_zp_init(h2, p, 1, n); ind1 = n_randint(state, p); unity_zp_coeff_set_ui(h1, ind1, 1); ind2 = n_randint(state, p); unity_zp_coeff_set_ui(h2, ind2, 1); ind1 = (ind1 + ind2) % p; unity_zp_coeff_set_ui(g, ind1, 1); unity_zp_mul(f, h1, h2); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h1); unity_zp_clear(h2); } /* test commutative */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g, h1, h2; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h1, p, 1, n); unity_zp_init(h2, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1, val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, p); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(h1, ind, val1); unity_zp_coeff_set_fmpz(h2, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } unity_zp_mul(f, h1, h2); unity_zp_mul(g, h2, h1); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h1); unity_zp_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_mul11.c000066400000000000000000000042541461254215100210140ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_mul11, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test multiplication in Z[\zeta_5] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f1, f2, g, h; p = 11; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, 1, n); unity_zp_init(f2, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, p); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul11(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_mul2.c000066400000000000000000000120721461254215100207310ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_mul2, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test multiplication in Z[\zeta_2^2] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f1, f2, g, h; p = 2; k = 2; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, k, n); unity_zp_init(f2, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(h, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul4(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } /* test multiplication in Z[\zeta_2^3] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f1, f2, g, h; p = 2; k = 3; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, k, n); unity_zp_init(f2, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(h, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul8(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } /* test multiplication in Z[\zeta_2^4] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f1, f2, g, h; p = 2; k = 4; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, k, n); unity_zp_init(f2, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(h, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul16(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_mul3.c000066400000000000000000000071421461254215100207340ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_mul3, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test multiplication in Z[\zeta_3] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f1, f2, g, h; p = 3; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, 1, n); unity_zp_init(f2, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, p); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul3(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } /* test multiplication in Z[\zeta_3^2] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f1, f2, g, h; p = 3; k = 2; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, k, n); unity_zp_init(f2, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(h, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul9(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_mul5.c000066400000000000000000000042511461254215100207340ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_mul5, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test multiplication in Z[\zeta_5] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f1, f2, g, h; p = 5; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, 1, n); unity_zp_init(f2, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, p); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul5(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_mul7.c000066400000000000000000000042511461254215100207360ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_mul7, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test multiplication in Z[\zeta_5] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f1, f2, g, h; p = 7; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f1, p, 1, n); unity_zp_init(f2, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_t val2; fmpz_init(val1); fmpz_init(val2); ind = n_randint(state, p); fmpz_randtest_unsigned(val1, state, 200); fmpz_randtest_unsigned(val2, state, 200); unity_zp_coeff_set_fmpz(g, ind, val1); unity_zp_coeff_set_fmpz(h, ind, val2); fmpz_clear(val1); fmpz_clear(val2); } _unity_zp_reduce_cyclotomic(g); _unity_zp_reduce_cyclotomic(h); unity_zp_mul7(f1, g, h, t); unity_zp_mul(f2, g, h); if (unity_zp_equal(f1, f2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f1); unity_zp_clear(f2); unity_zp_clear(g); unity_zp_clear(h); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_pow.c000066400000000000000000000037141461254215100206620ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_pow, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, pow; fmpz_t n; unity_zp f, g, h1, h2; p = n_randprime(state, 2 + n_randint(state, 6), 0); pow = n_randint(state, 100); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h1, p, 1, n); unity_zp_init(h2, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(h1, ind, val); fmpz_clear(val); } unity_zp_copy(h2, h1); unity_zp_pow_ui(f, h2, pow); if (pow == 0) { unity_zp_coeff_set_ui(g, 0, 1); } else { for (j = 0; j < pow; j++) { unity_zp_mul(g, h1, h2); unity_zp_swap(h2, g); } } if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h1); unity_zp_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_pow_2k.c000066400000000000000000000034641461254215100212600ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_pow_2k, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n, pow; unity_zp f, g, h; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); fmpz_init(pow); fmpz_randtest_unsigned(pow, state, 200); while (fmpz_equal_ui(pow, 0) != 0) fmpz_randtest_unsigned(pow, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(h, ind, val); fmpz_clear(val); } unity_zp_pow_2k_fmpz(f, h, pow); unity_zp_pow_fmpz(g, h, pow); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_clear(pow); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_pow_sliding.c000066400000000000000000000035461461254215100223760ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_pow_sliding, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n, pow; unity_zp f, g, h; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); fmpz_init(pow); fmpz_randtest_unsigned(pow, state, 200); while (fmpz_equal_ui(pow, 0) != 0) fmpz_randtest_unsigned(pow, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(h, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(h); unity_zp_pow_sliding_fmpz(f, h, pow); unity_zp_pow_fmpz(g, h, pow); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_clear(pow); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_reduce_cyclotomic.c000066400000000000000000000041571461254215100235530ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_reduce_cyclotomic, state) { int i, j; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_poly_t cyclo_poly; ulong p, exp; fmpz_t n; unity_zp f, g; p = n_randprime(state, 2 + n_randint(state, 2), 0); exp = n_randint(state, 4); while (exp == 0) exp = n_randint(state, 4); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_cmp_ui(n, 2) < 0) fmpz_randtest_unsigned(n, state, 200); fmpz_mod_ctx_set_modulus(ctx, n); unity_zp_init(f, p, exp, n); unity_zp_init(g, p, exp, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, n_pow(p, exp)); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(f, ind, val); fmpz_clear(val); } unity_zp_reduce_cyclotomic(g, f); fmpz_mod_poly_init(cyclo_poly, ctx); for (j = 0; j < p; j++) fmpz_mod_poly_set_coeff_ui(cyclo_poly, j * n_pow(p, exp - 1), 1, ctx); fmpz_mod_poly_rem(f->poly, f->poly, cyclo_poly, ctx); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_poly_clear(cyclo_poly, ctx); unity_zp_clear(f); unity_zp_clear(g); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_sqr.c000066400000000000000000000031351461254215100206570ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_sqr, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g, h; p = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(h, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val1; fmpz_init(val1); ind = n_randint(state, p); fmpz_randtest_unsigned(val1, state, 200); unity_zp_coeff_set_fmpz(h, ind, val1); fmpz_clear(val1); } unity_zp_mul(f, h, h); unity_zp_sqr(g, h); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_sqr11.c000066400000000000000000000036011461254215100210170ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_sqr11, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test squaring in Z[\zeta_11] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g, temp; p = 11; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(temp, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr11(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_sqr2.c000066400000000000000000000102611461254215100207370ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_sqr2, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test squaring in Z[\zeta_4] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f, g, temp; p = 2; k = 2; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(temp, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr4(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } /* test squaring in Z[\zeta_8] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f, g, temp; p = 2; k = 3; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(temp, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr8(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } /* test squaring in Z[\zeta_16] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f, g, temp; p = 2; k = 4; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(temp, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr16(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_sqr3.c000066400000000000000000000060101461254215100207350ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_sqr3, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test squaring in Z[\zeta_3] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g, temp; p = 3; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(temp, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr3(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } /* test squaring in Z[\zeta_9] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, k; fmpz_t n; unity_zp f, g, temp; p = 3; k = 2; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, k, n); unity_zp_init(g, p, k, n); unity_zp_init(temp, p, k, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, n_pow(p, k)); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr9(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_sqr5.c000066400000000000000000000035751461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_sqr5, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test squaring in Z[\zeta_5] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g, temp; p = 5; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(temp, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr5(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zp_sqr7.c000066400000000000000000000035751461254215100207560ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zp_sqr7, state) { int i, j; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * (SQUARING_SPACE)); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); /* test squaring in Z[\zeta_7] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p; fmpz_t n; unity_zp f, g, temp; p = 7; fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zp_init(f, p, 1, n); unity_zp_init(g, p, 1, n); unity_zp_init(temp, p, 1, n); for (j = 0; j < 100; j++) { ulong ind; fmpz_t val; fmpz_init(val); ind = n_randint(state, p); fmpz_randtest_unsigned(val, state, 200); unity_zp_coeff_set_fmpz(temp, ind, val); fmpz_clear(val); } _unity_zp_reduce_cyclotomic(temp); unity_zp_sqr7(f, temp, t); unity_zp_sqr(g, temp); if (unity_zp_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(temp); } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zpq_add.c000066400000000000000000000040111461254215100207550ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zpq_add, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, q; fmpz_t n; unity_zpq f, g, h1, h2; fmpz_init(n); p = n_randprime(state, 2 + n_randint(state, 6), 0); q = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zpq_init(f, q, p, n); unity_zpq_init(g, q, p, n); unity_zpq_init(h1, q, p, n); unity_zpq_init(h2, q, p, n); for (j = 0; j < 100; j++) { ulong x, y; fmpz_t val1, val2; fmpz_init(val1); fmpz_init(val2); x = n_randint(state, p); y = n_randint(state, q); fmpz_randtest_not_zero(val1, state, 200); fmpz_randtest_not_zero(val2, state, 200); unity_zpq_coeff_set_fmpz(h1, y, x, val1); unity_zpq_coeff_set_fmpz(h2, y, x, val2); fmpz_add(val1, val1, val2); unity_zpq_coeff_set_fmpz(g, y, x, val1); fmpz_clear(val1); fmpz_clear(val2); } unity_zpq_add(f, h1, h2); if (unity_zpq_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); unity_zpq_clear(h1); unity_zpq_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zpq_equal.c000066400000000000000000000031741461254215100213450ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zpq_equal, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, q; fmpz_t n; unity_zpq f, g; p = n_randprime(state, 2 + n_randint(state, 6), 0); q = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_init(n); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zpq_init(f, q, p, n); unity_zpq_init(g, q, p, n); for (j = 0; j < 100; j++) { ulong x, y; fmpz_t val; fmpz_init(val); x = n_randint(state, p); y = n_randint(state, q); fmpz_randtest_not_zero(val, state, 300); unity_zpq_coeff_set_fmpz(f, y, x, val); unity_zpq_coeff_set_fmpz(g, y, x, val); fmpz_clear(val); } if (unity_zpq_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zpq_gauss_sum.c000066400000000000000000000037021461254215100222410ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zpq_gauss_sum, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { int result; ulong p, q, pnum, ppow; fmpz_t n; unity_zpq gausssigma, gauss, gausspower; n_factor_t factors; n_factor_init(&factors); q = n_randprime(state, 6, 0); if (q == 2) q = 7; n_factor(&factors, q - 1, 0); pnum = n_randint(state, factors.num); p = factors.p[pnum]; ppow = n_randint(state, factors.exp[pnum]); if (ppow == 0) ppow = 1; p = n_pow(p, ppow); fmpz_init_set_ui(n, n_randprime(state, 16, 0)); unity_zpq_init(gausssigma, q, p, n); unity_zpq_init(gauss, q, p, n); unity_zpq_init(gausspower, q, p, n); unity_zpq_gauss_sum(gauss, q, p); unity_zpq_gauss_sum_sigma_pow(gausssigma, q, p); unity_zpq_pow(gausspower, gauss, n); result = 0; for (j = 0; j < p; j++) { unity_zpq_mul_unity_p_pow(gauss, gausspower, j); if (unity_zpq_equal(gauss, gausssigma)) { result = 1; break; } } if (result == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } unity_zpq_clear(gausssigma); unity_zpq_clear(gauss); unity_zpq_clear(gausspower); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zpq_init.c000066400000000000000000000017271461254215100212030ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zpq_init, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, q; fmpz_t n; unity_zpq f; fmpz_init(n); p = n_randprime(state, 2 + n_randint(state, 16), 0); q = n_randprime(state, 2 + n_randint(state, 16), 0); fmpz_randtest_unsigned(n, state, 200); fmpz_add_ui(n, n, 1); unity_zpq_init(f, q, p, n); unity_zpq_clear(f); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zpq_mul.c000066400000000000000000000037151461254215100210340ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zpq_mul, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, q; fmpz_t n; unity_zpq f, g, h1, h2; fmpz_init(n); p = n_randprime(state, 2 + n_randint(state, 6), 0); q = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zpq_init(f, q, p, n); unity_zpq_init(g, q, p, n); unity_zpq_init(h1, q, p, n); unity_zpq_init(h2, q, p, n); for (j = 0; j < 100; j++) { ulong x, y; fmpz_t val1, val2; fmpz_init(val1); fmpz_init(val2); x = n_randint(state, p); y = n_randint(state, q); fmpz_randtest_not_zero(val1, state, 200); fmpz_randtest_not_zero(val2, state, 200); unity_zpq_coeff_set_fmpz(h1, y, x, val1); unity_zpq_coeff_set_fmpz(h2, y, x, val2); fmpz_clear(val1); fmpz_clear(val2); } unity_zpq_mul(f, h1, h2); unity_zpq_mul(g, h2, h1); if (unity_zpq_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); unity_zpq_clear(h1); unity_zpq_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zpq_mul_unity_p.c000066400000000000000000000037311461254215100226010ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zpq_mul_unity_p, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, q; fmpz_t n; unity_zpq f, g; fmpz_init(n); p = n_randprime(state, 2 + n_randint(state, 6), 0); q = n_randprime(state, 2 + n_randint(state, 6), 0); fmpz_randtest_unsigned(n, state, 200); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 200); unity_zpq_init(f, q, p, n); unity_zpq_init(g, q, p, n); for (j = 0; j < 100; j++) { ulong x, y; fmpz_t val; fmpz_init(val); x = n_randint(state, p); y = n_randint(state, q); fmpz_randtest_unsigned(val, state, 200); unity_zpq_coeff_set_fmpz(g, y, x, val); fmpz_clear(val); } for (j = 0; j < p; j++) { unity_zpq h1, h2; unity_zpq_init(h1, q, p, n); unity_zpq_init(h2, q, p, n); unity_zpq_coeff_set_ui(h1, 0, j, 1); unity_zpq_mul(h2, g, h1); unity_zpq_mul_unity_p_pow(f, g, j); if (unity_zpq_equal(f, h2) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } unity_zpq_clear(h1); unity_zpq_clear(h2); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/test/t-unity_zpq_pow.c000066400000000000000000000041251461254215100210400ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "aprcl.h" TEST_FUNCTION_START(aprcl_unity_zpq_pow, state) { int i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong p, q, pow; fmpz_t n; unity_zpq f, g, h1, h2; p = n_randprime(state, 2 + n_randint(state, 5), 0); q = n_randprime(state, 2 + n_randint(state, 5), 0); pow = n_randint(state, 32); fmpz_init(n); fmpz_randtest_unsigned(n, state, 100); while (fmpz_equal_ui(n, 0) != 0) fmpz_randtest_unsigned(n, state, 100); unity_zpq_init(f, q, p, n); unity_zpq_init(g, q, p, n); unity_zpq_init(h1, q, p, n); unity_zpq_init(h2, q, p, n); for (j = 0; j < 50; j++) { ulong x, y; fmpz_t val; fmpz_init(val); x = n_randint(state, p); y = n_randint(state, q); fmpz_randtest_not_zero(val, state, 100); unity_zpq_coeff_set_fmpz(h1, y, x, val); fmpz_clear(val); } unity_zpq_copy(h2, h1); unity_zpq_pow_ui(f, h2, pow); if (pow == 0) { unity_zpq_coeff_set_ui(g, 0, 0, 1); } else { for (j = 0; j < pow; j++) { unity_zpq_mul(g, h1, h2); unity_zpq_swap(h2, g); } } if (unity_zpq_equal(f, g) == 0) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); unity_zpq_clear(h1); unity_zpq_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/aprcl/unity_zp_add.c000066400000000000000000000015431461254215100173630ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" #if FLINT_WANT_ASSERT # include "fmpz.h" # include "fmpz_mod.h" #endif void unity_zp_add(unity_zp f, const unity_zp g, const unity_zp h) { FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(h->ctx))); fmpz_mod_poly_add(f->poly, g->poly, h->poly, f->ctx); } flint-3.1.3/src/aprcl/unity_zp_aut.c000066400000000000000000000022271461254215100174240ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "aprcl.h" /* Computes f such that \sigma_x(g) = f. */ void unity_zp_aut(unity_zp f, const unity_zp g, ulong x) { ulong i, p_pow, p_pow_preinv; fmpz_t coeff; fmpz_init(coeff); p_pow = n_pow(f->p, f->exp); p_pow_preinv = n_preinvert_limb(p_pow); unity_zp_set_zero(f); /* for i = 0, 1,..., p^k set f[i * x mod p^k] = g[i] */ for (i = 0; i < p_pow; i++) { /* compute x * i mod p^k */ ulong ind = n_mulmod2_preinv(x, i, p_pow, p_pow_preinv); /* set f[ind] = g[i] */ fmpz_mod_poly_get_coeff_fmpz(coeff, g->poly, i, g->ctx); unity_zp_coeff_add_fmpz(f, ind, coeff); } _unity_zp_reduce_cyclotomic(f); fmpz_clear(coeff); } flint-3.1.3/src/aprcl/unity_zp_aut_inv.c000066400000000000000000000045641461254215100203060ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "aprcl.h" /* Computes f such that \sigma_x(f) = g. */ void unity_zp_aut_inv(unity_zp f, const unity_zp g, ulong x) { ulong i, j, p_pow1, p_pow2, m, p_pow_preinv; fmpz_t f_coeff, g_coeff; fmpz_init(f_coeff); fmpz_init(g_coeff); p_pow1 = n_pow(f->p, f->exp - 1); /* p_pow1 = p^{k - 1} */ p_pow2 = p_pow1 * f->p; /* p_pow2 = p^k */ m = (f->p - 1) * p_pow1; /* m = (p - 1) * p^{k - 1} */ p_pow_preinv = n_preinvert_limb(p_pow2); unity_zp_set_zero(f); /* for i = 0, 1,..., m - 1 set f[i] = g[xi mod p^k] */ for (i = 0; i < m; i++) { /* set g_ind = x * i mod p^k */ ulong g_ind = n_mulmod2_preinv(x, i, p_pow2, p_pow_preinv); /* set g_coeff to g[g_ind] */ fmpz_mod_poly_get_coeff_fmpz(g_coeff, g->poly, g_ind, g->ctx); /* set f[i] = g[x * i mod p^k] */ unity_zp_coeff_set_fmpz(f, i, g_coeff); } /* for i = m, m + 1,..., p^k - 1 for j = 1, 2,..., p - 1 set f[i - j * p^{k - 1}] = (f[i - j * p^{k - 1}] - g[x * i mod p^k]) mod n */ for (i = m; i < p_pow2; i++) { /* set g_ind = x * i mod p^k */ ulong g_ind = n_mulmod2_preinv(x, i, p_pow2, p_pow_preinv); for (j = 1; j < f->p; j++) { /* set f_ind = i - j * p^{k - 1} */ ulong f_ind = i - j * p_pow1; /* set g_coeff = g[x * i mod p^k] */ fmpz_mod_poly_get_coeff_fmpz(g_coeff, g->poly, g_ind, g->ctx); /* set f_coeff = f[i - j * p^{k - 1}] */ fmpz_mod_poly_get_coeff_fmpz(f_coeff, f->poly, f_ind, f->ctx); /* set f_coeff = f[i - j * p^{k - 1}] - g[x * i mod p^k] */ fmpz_sub(f_coeff, f_coeff, g_coeff); /* set f[i - j * p^{k - 1}] = f_coeff */ unity_zp_coeff_set_fmpz(f, f_ind, f_coeff); } } fmpz_clear(f_coeff); fmpz_clear(g_coeff); } flint-3.1.3/src/aprcl/unity_zp_auxiliary_routine.c000066400000000000000000000274401461254215100224130ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "aprcl.h" /* Input a0, a1, a2 store in t[0 .. 2] and b0, b1, b2 store in t[3 .. 5]. Output c0, ..., c4 store in t[6 .. 10]. Used t[0 .. 17]. c0 = a0 * b0; c1 = a0 * b1 + b0 * a1; c2 = a0 * b2 + a1 * b1 + a2 * b0; c3 = a1 * b2 + a2 * b1; c4 = a2 * b2. */ void unity_zp_ar1(fmpz_t * t) { /* a0 = t[0]; a1 = t[1]; a2 = t[2]; b0 = t[3]; b1 = t[4]; b2 = t[5]; c0 = t[6]; c1 = t[7]; c2 = t[8]; c3 = t[9]; c4 = t[10]; m1 = t[11]; m2 = t[12]; d1 = t[13]; d2 = t[14]; d3 = t[15]; d4 = t[16]; d5 = t[17]. */ fmpz_mul(t[6], t[0], t[3]); /* c0 = a0 * b0 */ fmpz_mul(t[13], t[1], t[4]); /* d1 = a1 * b1 */ fmpz_mul(t[10], t[2], t[5]); /* c4 = a2 * b2 */ fmpz_add(t[11], t[0], t[1]); /* m1 = a0 + a1 */ fmpz_add(t[12], t[3], t[4]); /* m2 = b0 + b1 */ fmpz_mul(t[15], t[11], t[12]); /* d3 = m1 * m2 */ fmpz_add(t[11], t[0], t[2]); /* m1 = a0 + a2 */ fmpz_add(t[12], t[3], t[5]); /* m2 = b0 + b2 */ fmpz_mul(t[16], t[11], t[12]); /* d4 = m1 * m2 */ fmpz_add(t[11], t[1], t[2]); /* m1 = a1 + a2 */ fmpz_add(t[12], t[4], t[5]); /* m2 = b1 + b2 */ fmpz_mul(t[17], t[11], t[12]); /* d5 = m1 * m2 */ fmpz_add(t[14], t[6], t[13]); /* d2 = c0 + d1 */ fmpz_sub(t[7], t[15], t[14]); /* c1 = d3 - d2 */ fmpz_add(t[14], t[16], t[13]); /* d2 = d4 + d1 */ fmpz_add(t[16], t[6], t[10]); /* d4 = c0 + c4 */ fmpz_sub(t[8], t[14], t[16]); /* c2 = d2 - d4 */ fmpz_add(t[14], t[13], t[10]); /* d2 = d1 + c4 */ fmpz_sub(t[9], t[17], t[14]); /* c3 = d5 - d2 */ } /* Input a0, ..., a3 store in t[0 .. 3] and b0, ..., b3 store in t[4 .. 7]. Output c0, ..., c6 store in t[8 .. 14]. Used t[0 .. 27]. c0 = a0 * b0; c1 = a0 * b1 + b0 * a1; c2 = a0 * b2 + a1 * b1 + a2 * b0; c3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; c4 = a1 * b3 + a2 * b2 + a3 * b1; c5 = a2 * b3 + a3 * b2; c6 = a3 * b3. */ void unity_zp_ar2(fmpz_t * t) { /* a0 = t[0]; a1 = t[1]; a2 = t[2]; a3 = t[3]; b0 = t[4]; b1 = t[5]; b2 = t[6]; b3 = t[7]; c0 = t[8]; c1 = t[9]; c2 = t[10]; c3 = t[11]; c4 = t[12]; c5 = t[13]; c6 = t[14]; m1 = t[15]; m2 = t[16]; m3 = t[17]; m4 = t[18]; m5 = t[19]; d1 = t[20]; d2 = t[21]; d3 = t[22]; d4 = t[23]; d5 = t[24]; d6 = t[25]; d7 = t[26]; d8 = t[27]; d9 = t[28]. */ fmpz_mul(t[8], t[0], t[4]); /* c0 = a0 * b0 */ fmpz_mul(t[20], t[1], t[5]); /* d1 = a1 * b1 */ fmpz_mul(t[21], t[2], t[6]); /* d2 = a2 * b2 */ fmpz_mul(t[14], t[3], t[7]); /* c6 = a3 * b3 */ fmpz_add(t[15], t[0], t[1]); /* m1 = a0 + a1 */ fmpz_add(t[16], t[4], t[5]); /* m2 = b0 + b1 */ fmpz_mul(t[22], t[15], t[16]); /* d3 = m1 * m2 */ fmpz_add(t[15], t[0], t[2]); /* m1 = a0 + a2 */ fmpz_add(t[16], t[4], t[6]); /* m2 = b0 + b2 */ fmpz_mul(t[23], t[15], t[16]); /* d4 = m1 * m2 */ fmpz_add(t[17], t[2], t[3]); /* m3 = a2 + a3 */ fmpz_add(t[18], t[6], t[7]); /* m4 = b2 + b3 */ fmpz_mul(t[24], t[17], t[18]); /* d5 = m3 * m4 */ fmpz_add(t[17], t[1], t[3]); /* m3 = a1 + a3 */ fmpz_add(t[18], t[5], t[7]); /* m4 = b1 + b3 */ fmpz_mul(t[25], t[17], t[18]); /* d6 = m3 * m4 */ fmpz_add(t[26], t[8], t[20]); /* d7 = c0 + d1 */ fmpz_sub(t[9], t[22], t[26]); /* c1 = d3 - d7 */ fmpz_add(t[26], t[8], t[21]); /* d7 = c0 + d2 */ fmpz_add(t[27], t[20], t[23]); /* d8 = d1 + d4 */ fmpz_sub(t[10], t[27], t[26]); /* c2 = d8 - d7 */ fmpz_add(t[19], t[15], t[17]); /* m5 = m1 + m3 */ fmpz_add(t[17], t[16], t[18]); /* m3 = m2 + m4 */ fmpz_add(t[26], t[21], t[14]); /* d7 = d2 + c6 */ fmpz_sub(t[13], t[24], t[26]); /* c5 = d5 - d7 */ fmpz_mul(t[26], t[17], t[19]); /* d7 = m3 * m5 */ fmpz_add(t[27], t[9], t[13]); /* d8 = c1 + c5 */ fmpz_add(t[28], t[27], t[25]); /* d9 = d8 + d6 */ fmpz_add(t[27], t[28], t[23]); /* d8 = d9 + d4 */ fmpz_sub(t[11], t[26], t[27]); /* c3 = d7 - d8 */ fmpz_add(t[26], t[25], t[21]); /* d7 = d6 + d2 */ fmpz_add(t[27], t[20], t[14]); /* d8 = d1 + c6 */ fmpz_sub(t[12], t[26], t[27]); /* c4 = d7 - d8 */ } /* Input a0, ... , a4 store in t[0 .. 4] and b0, ..., b4 in t[5 .. 9]. Output c0, ..., c8 store in t[10 .. 18]. Used t[0 .. 38]. c0 = a0 * b0; c1 = a0 * b1 + a1 * b0; c2 = a0 * b2 + a1 * b1 + a2 * b0; c3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; c4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; c5 = a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1; c6 = a2 * b4 + a3 * b3 + a4 * b2; c7 = a3 * b4 + a4 * b3; c8 = a4 * b4. */ void unity_zp_ar3(fmpz_t * t) { /* a0 = t[0] = t[20]; a1 = t[1] = t[21]; a2 = t[2] = t[22]; a3 = t[3] = t[23]; a4 = t[4] = t[24]; b0 = t[5] = t[25]; b1 = t[6] = t[26]; b2 = t[7] = t[27]; b3 = t[8] = t[28]; b4 = t[9] = t[29]; c0 = t[30] = t[10]; c1 = t[31] = t[11]; c2 = t[31] = t[12]; c3 = t[33] = t[13]; c4 = t[34] = t[14]; c5 = t[35] = t[15]; c6 = t[36] = t[16]; c7 = t[37] = t[17]; c8 = t[38] = t[18]; m0 = t[0]; m1 = t[1]; m2 = t[2]; m3 = t[3]; m4 = t[15]; m5 = t[16]; d0 = t[6]; d1 = t[7]; d2 = t[8]; d3 = t[9]; d4 = t[10]; d5 = t[11]; d6 = t[12]; d7 = t[13]. */ fmpz_set(t[20], t[0]); /* store a0 */ fmpz_set(t[21], t[1]); /* store a1 */ fmpz_set(t[22], t[2]); /* store a2 */ fmpz_set(t[23], t[3]); /* store a3 */ fmpz_set(t[24], t[4]); /* store a4 */ fmpz_set(t[25], t[5]); /* store b0 */ fmpz_set(t[26], t[6]); /* store b1 */ fmpz_set(t[27], t[7]); /* store b2 */ fmpz_set(t[28], t[8]); /* store b3 */ fmpz_set(t[29], t[9]); /* store b4 */ fmpz_set(t[3], t[25]); /* set t[3] = b0 */ fmpz_set(t[4], t[26]); /* set t[4] = b1 */ fmpz_set(t[5], t[27]); /* set t[5] = b2 */ /* apply ar1 to a0, a1, a2 and b0, b1, b2 */ unity_zp_ar1(t); fmpz_set(t[30], t[6]); /* store c0 */ fmpz_set(t[31], t[7]); /* store c1 */ fmpz_set(t[32], t[8]); /* store c2 */ fmpz_set(t[33], t[9]); /* store c3 */ fmpz_set(t[34], t[10]); /* store c4 */ fmpz_add(t[0], t[20], t[23]); /* m0 = a0 + a3 */ fmpz_add(t[1], t[21], t[24]); /* m1 = a1 + a4 */ fmpz_add(t[3], t[25], t[28]); /* m2 = b0 + b3 */ fmpz_add(t[4], t[26], t[29]); /* m3 = b1 + b4 */ /* apply ar1 to m0, m1, a2 and m2, m3, b2 */ unity_zp_ar1(t); fmpz_add(t[15], t[23], t[24]); /* m4 = a3 + a4 */ fmpz_add(t[16], t[28], t[29]); /* m5 = b3 + b4 */ fmpz_mul(t[11], t[23], t[28]); /* d5 = a3 * b3 */ fmpz_mul(t[38], t[24], t[29]); /* c8 = a4 * b4 */ fmpz_mul(t[12], t[15], t[16]); /* d6 = m4 * m5 */ fmpz_add(t[13], t[11], t[38]); /* d7 = d5 + c8 */ fmpz_sub(t[37], t[12], t[13]); /* c7 = d6 - d7 */ fmpz_add(t[12], t[9], t[11]); /* d6 = d3 + d5 */ fmpz_sub(t[36], t[12], t[33]); /* c6 = d6 - c3 */ fmpz_add(t[12], t[30], t[11]); /* d6 = c0 + d5 */ fmpz_add(t[13], t[33], t[6]); /* d7 = c3 + d0 */ fmpz_sub(t[33], t[13], t[12]); /* c3 = d7 - d6 */ fmpz_add(t[12], t[31], t[37]); /* d6 = c1 + c7 */ fmpz_add(t[13], t[34], t[7]); /* d7 = c4 + d1 */ fmpz_sub(t[34], t[13], t[12]); /* c4 = d7 - d6 */ fmpz_add(t[12], t[32], t[38]); /* d6 = c2 + c8 */ fmpz_sub(t[35], t[8], t[12]); /* c5 = d2 - d6 */ fmpz_set(t[10], t[30]); /* store c0 */ fmpz_set(t[11], t[31]); /* store c1 */ fmpz_set(t[12], t[32]); /* store c2 */ fmpz_set(t[13], t[33]); /* store c3 */ fmpz_set(t[14], t[34]); /* store c4 */ fmpz_set(t[15], t[35]); /* store c5 */ fmpz_set(t[16], t[36]); /* store c6 */ fmpz_set(t[17], t[37]); /* store c7 */ fmpz_set(t[18], t[38]); /* store c8 */ } /* Input a0, ... , a4 store in t[0 .. 4]. Output c0, ..., c8 store in t[5 .. 13]. Used t[0 .. 29]. c0 = a0 * a0; c1 = 2 * a0 * a1; c2 = 2 * a0 * a2 + a1 * a1; c3 = 2 * a0 * a3 + a * a1 * a2; c4 = 2 * a0 * a4 + 2 * a1 * a3 + a2 * a2; c5 = 2 * a1 * a4 + 2 * a2 * a3; c6 = 2 * a2 * a4 + a3 * a3; c7 = 2 * a3 * a4; c8 = a4 * a4. */ void unity_zp_ar4(fmpz_t * t) { /* a0 = t[0]; a1 = t[1]; a2 = t[2]; a3 = t[3]; a4 = t[4]; c0 = t[5]; c1 = t[6]; c2 = t[7]; c3 = t[8]; c4 = t[9]; c5 = t[10]; c6 = t[11]; c7 = t[12]; c8 = t[13]; m1 = t[14]; m2 = t[15]; m3 = t[16]; m4 = t[17]; m5 = t[18]; m6 = t[19]; m7 = t[20]; m8 = t[21]; m9 = t[22]; m10 = t[23]; d1 = t[24]; d2 = t[25]; d3 = t[26]; d4 = t[27]; d5 = t[28]; d6 = t[29]. */ fmpz_add(t[14], t[2], t[2]); /* m1 = a2 + a2 */ fmpz_add(t[15], t[0], t[1]); /* m2 = a0 + a1 */ fmpz_add(t[16], t[1], t[14]); /* m3 = a1 + m1 */ fmpz_add(t[17], t[3], t[4]); /* m4 = a3 + a4 */ fmpz_add(t[18], t[3], t[14]); /* m5 = a3 + m1 */ fmpz_add(t[19], t[0], t[0]); /* m6 = a0 + a0 */ fmpz_add(t[19], t[19], t[14]); /* m6 = m6 + m1 */ fmpz_add(t[20], t[1], t[3]); /* m7 = a1 + a3 */ fmpz_add(t[21], t[4], t[4]); /* m8 = a4 + a4 */ fmpz_add(t[21], t[21], t[14]); /* m8 = m8 + m1 */ fmpz_add(t[22], t[0], t[3]); /* m9 = a0 + a3 */ fmpz_add(t[23], t[1], t[4]); /* m10 = a1 + a4 */ fmpz_mul(t[5], t[0], t[0]); /* c0 = a0 * a0 */ fmpz_mul(t[24], t[0], t[1]); /* d1 = a0 * a1 */ fmpz_mul(t[13], t[4], t[4]); /* c8 = a4 * a4 */ fmpz_mul(t[25], t[3], t[4]); /* d2 = a3 * a4 */ fmpz_mul(t[26], t[1], t[14]); /* d3 = a1 * m1 */ fmpz_mul(t[27], t[3], t[14]); /* d4 = a3 * m1 */ fmpz_add(t[6], t[24], t[24]); /* c1 = d1 + d1 */ fmpz_add(t[12], t[25], t[25]); /* c7 = d2 + d2 */ fmpz_mul(t[28], t[15], t[16]); /* d5 = m2 * m3 */ fmpz_add(t[29], t[24], t[26]); /* d6 = d1 + d3 */ fmpz_sub(t[7], t[28], t[29]); /* c2 = d5 - d6 */ fmpz_mul(t[28], t[17], t[18]); /* d5 = m4 * m5 */ fmpz_add(t[29], t[25], t[27]); /* d6 = d2 + d4 */ fmpz_sub(t[11], t[28], t[29]); /* c6 = d5 - d6 */ fmpz_mul(t[28], t[19], t[20]); /* d5 = m6 * m7 */ fmpz_add(t[29], t[6], t[27]); /* d6 = c1 + d4 */ fmpz_sub(t[8], t[28], t[29]); /* c3 = d5 - d6 */ fmpz_mul(t[28], t[20], t[21]); /* d5 = m7 * m8 */ fmpz_add(t[29], t[12], t[26]); /* d6 = c7 + d3 */ fmpz_sub(t[10], t[28], t[29]); /* c5 = d5 - d6 */ fmpz_mul(t[28], t[22], t[23]); /* d5 = m9 * m10 */ fmpz_add(t[29], t[24], t[25]); /* d6 = d1 + d2 */ fmpz_sub(t[28], t[28], t[29]); /* d6 = d5 - d6 */ fmpz_add(t[29], t[28], t[28]); /* d6 = d5 + d5 */ fmpz_mul(t[28], t[2], t[2]); /* d5 = a2 * a2 */ fmpz_add(t[9], t[28], t[29]); /* c4 = d5 + d6 */ } flint-3.1.3/src/aprcl/unity_zp_coeff.c000066400000000000000000000053151461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zp_coeff_add_fmpz(unity_zp f, ulong ind, const fmpz_t x) { fmpz_t coeff; fmpz_init(coeff); fmpz_mod_poly_get_coeff_fmpz(coeff, f->poly, ind, f->ctx); if (fmpz_is_zero(coeff)) { fmpz_clear(coeff); fmpz_mod_poly_set_coeff_fmpz(f->poly, ind, x, f->ctx); return; } fmpz_clear(coeff); fmpz_add(f->poly->coeffs + ind, f->poly->coeffs + ind, x); if (fmpz_cmp(f->poly->coeffs + ind, fmpz_mod_ctx_modulus(f->ctx)) >= 0) fmpz_sub(f->poly->coeffs + ind, f->poly->coeffs + ind, fmpz_mod_ctx_modulus(f->ctx)); } void unity_zp_coeff_add_ui(unity_zp f, ulong ind, ulong x) { fmpz_t coeff; fmpz_init(coeff); fmpz_mod_poly_get_coeff_fmpz(coeff, f->poly, ind, f->ctx); if (fmpz_is_zero(coeff)) { fmpz_clear(coeff); fmpz_mod_poly_set_coeff_ui(f->poly, ind, x, f->ctx); return; } fmpz_clear(coeff); fmpz_add_ui(f->poly->coeffs + ind, f->poly->coeffs + ind, x); if (fmpz_cmp(f->poly->coeffs + ind, fmpz_mod_ctx_modulus(f->ctx)) >= 0) fmpz_sub(f->poly->coeffs + ind, f->poly->coeffs + ind, fmpz_mod_ctx_modulus(f->ctx)); } void unity_zp_coeff_inc(unity_zp f, ulong ind) { if (ind >= f->poly->length) { fmpz_mod_poly_set_coeff_ui(f->poly, ind, 1, f->ctx); return; } fmpz_add_ui(f->poly->coeffs + ind, f->poly->coeffs + ind, 1); if (fmpz_equal(f->poly->coeffs + ind, fmpz_mod_ctx_modulus(f->ctx))) fmpz_set_ui(f->poly->coeffs + ind, 0); } void unity_zp_coeff_dec(unity_zp f, ulong ind) { if (ind >= f->poly->length) { fmpz_mod_poly_set_coeff_si(f->poly, ind, -1, f->ctx); return; } fmpz_sub_ui(f->poly->coeffs + ind, f->poly->coeffs + ind, 1); if (fmpz_equal_si(f->poly->coeffs + ind, -1)) fmpz_add(f->poly->coeffs + ind, f->poly->coeffs + ind, fmpz_mod_ctx_modulus(f->ctx)); } void unity_zp_coeff_set_fmpz(unity_zp f, ulong ind, const fmpz_t x) { fmpz_mod_poly_set_coeff_fmpz(f->poly, ind, x, f->ctx); } void unity_zp_coeff_set_ui(unity_zp f, ulong ind, ulong x) { fmpz_mod_poly_set_coeff_ui(f->poly, ind, x, f->ctx); } flint-3.1.3/src/aprcl/unity_zp_copy.c000066400000000000000000000013241461254215100176020ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" #if FLINT_WANT_ASSERT # include "fmpz.h" # include "fmpz_mod.h" #endif void unity_zp_copy(unity_zp f, const unity_zp g) { FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); fmpz_mod_poly_set(f->poly, g->poly, f->ctx); } flint-3.1.3/src/aprcl/unity_zp_equal.c000066400000000000000000000013251461254215100177400ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" int unity_zp_equal(unity_zp f, unity_zp g) { /* f and g can be reduced only by modylo x^{p^k} - 1, so reduce by cyclotomic polynomial */ _unity_zp_reduce_cyclotomic(f); _unity_zp_reduce_cyclotomic(g); return fmpz_mod_poly_equal(f->poly, g->poly, f->ctx); } flint-3.1.3/src/aprcl/unity_zp_init.c000066400000000000000000000013461461254215100175770ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zp_init(unity_zp f, ulong p, ulong exp, const fmpz_t n) { f->p = p; f->exp = exp; fmpz_mod_ctx_init(f->ctx, n); fmpz_mod_poly_init(f->poly, f->ctx); } void unity_zp_clear(unity_zp f) { fmpz_mod_poly_clear(f->poly, f->ctx); fmpz_mod_ctx_clear(f->ctx); } flint-3.1.3/src/aprcl/unity_zp_is_unity.c000066400000000000000000000022021461254215100204670ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" slong unity_zp_is_unity(unity_zp f) { ulong result; ulong i, p_pow; unity_zp unity; p_pow = n_pow(f->p, f->exp); unity_zp_init(unity, f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); /* if the power was not found returns -1 */ result = -1; for (i = 0; i < p_pow; i++) { /* set unity = \zeta_{p^k}^i */ unity_zp_set_zero(unity); unity_zp_coeff_set_ui(unity, i, 1); /* check if f = zeta_{p^k}^i */ if (unity_zp_equal(unity, f) == 1) { /* if so, returns \zeta_{p^k} power */ result = i; break; } } unity_zp_clear(unity); return result; } flint-3.1.3/src/aprcl/unity_zp_jacobi_sum.c000066400000000000000000000046211461254215100207460ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "aprcl.h" /* Computes sum \zeta_{p^k}^{a * x + b * f(x)} for x = 1, 2, ..., q - 2. */ void _unity_zp_jacobi_sum_pq_general(unity_zp f, const mp_ptr table, ulong p, ulong q, ulong k, ulong a, ulong b) { int i, j; ulong size, pow, pow_dec; unity_zp_set_zero(f); pow_dec = n_pow(p, k - 1); size = (p - 1) * pow_dec; pow = pow_dec * p; for (i = 1; i < q - 1; i++) { /* l = a * i + b * f[i] */ ulong l = (a * (i) + b * table[i]) % pow; /* if l < (p - 1)p^{k - 1} increase f[l] by one */ if (l < size) { unity_zp_coeff_inc(f, l); } else /* else decrease f[l - jp^{k - 1}] by one for j in [0; p - 2] */ { for (j = 0; j < p - 1; j++) { l -= pow_dec; unity_zp_coeff_dec(f, l); } } } } /* Computes sum \zeta_{p^k}^{x + f(x)} for x = 1, 2, ..., q - 2. */ void unity_zp_jacobi_sum_pq(unity_zp f, ulong q, ulong p) { ulong k; mp_ptr table; table = aprcl_f_table(q); k = aprcl_p_power_in_q(q - 1, p); _unity_zp_jacobi_sum_pq_general(f, table, p, q, k, 1, 1); _nmod_vec_clear(table); } /* Computes sum \zeta_{p^k}^{2 * x + b * f(x)} for x = 1, 2, ..., q - 2. */ void unity_zp_jacobi_sum_2q_one(unity_zp f, ulong q) { ulong k; mp_ptr table; table = aprcl_f_table(q); k = aprcl_p_power_in_q(q - 1, 2); _unity_zp_jacobi_sum_pq_general(f, table, 2, q, k, 2, 1); _nmod_vec_clear(table); } /* Computes sum \zeta_{p^k}^{3 * 2^{k - 3} * x + 2^{k - 3} * f(x)} for x = 1, 2, ..., q - 2. */ void unity_zp_jacobi_sum_2q_two(unity_zp f, ulong q) { ulong a, b, k; mp_ptr table; table = aprcl_f_table(q); k = aprcl_p_power_in_q(q - 1, 2); b = n_pow(2, k - 3); /* b = 2^{k - 3} */ a = 3 * b; /* a = 3 * 2^{k - 3} */ _unity_zp_jacobi_sum_pq_general(f, table, 2, q, k, a, b); _nmod_vec_clear(table); } flint-3.1.3/src/aprcl/unity_zp_mul.c000066400000000000000000001007271461254215100174340ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "aprcl.h" #if FLINT_WANT_ASSERT # include "fmpz_mod.h" #endif void unity_zp_mul(unity_zp f, const unity_zp g, const unity_zp h) { slong glen, hlen; FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(h->ctx))); glen = g->poly->length; hlen = h->poly->length; if (glen == 0 || hlen == 0) { fmpz_mod_poly_zero(f->poly, f->ctx); return; } fmpz_mod_poly_fit_length(f->poly, glen + hlen - 1, f->ctx); if (glen >= hlen) _fmpz_poly_mul(f->poly->coeffs, g->poly->coeffs, glen, h->poly->coeffs, hlen); else _fmpz_poly_mul(f->poly->coeffs, h->poly->coeffs, hlen, g->poly->coeffs, glen); _fmpz_mod_poly_set_length(f->poly, glen + hlen - 1); _unity_zp_reduce_cyclotomic_divmod(f); } void unity_zp_mul_inplace(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { /* multiplication for p^k = 4 */ if (f->p == 2 && f->exp == 2) { unity_zp_mul4(f, g, h, t); return; } /* multiplication for p^k = 8 */ if (f->p == 2 && f->exp == 3) { unity_zp_mul8(f, g, h, t); return; } /* multiplication for p^k = 16 */ if (f->p == 2 && f->exp == 4) { unity_zp_mul16(f, g, h, t); return; } /* multiplication for p^k = 3 */ if (f->p == 3 && f->exp == 1) { unity_zp_mul3(f, g, h, t); return; } /* multiplicatiom for p^k = 9 */ if (f->p == 3 && f->exp == 2) { unity_zp_mul9(f, g, h, t); return; } /* multiplication for p^k = 5 */ if (f->p == 5 && f->exp == 1) { unity_zp_mul5(f, g, h, t); return; } /* multiplication for p^k = 7 */ if (f->p == 7 && f->exp == 1) { unity_zp_mul7(f, g, h, t); return; } /* multiplication for p^k = 11 */ if (f->p == 11 && f->exp == 1) { unity_zp_mul11(f, g, h, t); return; } /* traditional multiplication */ unity_zp_mul(f, g, h); } /* Computes f = g * h for p = 11. g and h must be reduced by F_11 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 60. Resulting f reduced by F_11 cyclotomic polynomial. */ void unity_zp_mul11(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { int i; /* g = (x0, ... , x9); h = (y0, ... , y9); f = (z0, ... , z9); x0 = t[40]; ... ; x9 = t[49]; y0 = t[50]; ... ; y9 = t[59]; for auxiliary routine 4: a0 = t[0]; ... ; a4 = t[4]; c0 = t[5]; ... ; c8 = t[13]; for auxiliary routine 3: a0 = t[0]; ... ; a4 = t[4]; b0 = t[5]; ... ; a4 = b[9]; c0 = t[10]; ... ; t[18]; d_{1, i} = t[50 + i] for i in [0, 9]; d_{2, i} = t[10 + i] for i in [0, 9]; d_{3, i} = t[40 + i] for i in [0, 9]. */ /* set xi */ for (i = 0; i < 10; i++) fmpz_mod_poly_get_coeff_fmpz(t[40 + i], g->poly, i, g->ctx); /* set yi */ for (i = 0; i < 10; i++) fmpz_mod_poly_get_coeff_fmpz(t[50 + i], h->poly, i, h->ctx); /* set ai = xi + x{i + 5} and bi = yi + y{i + 5} */ for (i = 0; i < 5; i++) { fmpz_add(t[i], t[40 + i], t[45 + i]); fmpz_add(t[5 + i], t[50 + i], t[55 + i]); } /* apply auxiliary routine 3 with (a0, ... , a4) and (b0, ... , b4) store result in (c0, ... , c8) */ unity_zp_ar3(t); /* set d_{3, i} = c_i */ for (i = 0; i < 9; i++) fmpz_set(t[40 + i], t[10 + i]); /* set ai = xi and bi = yi */ for (i = 0; i < 5; i++) { fmpz_mod_poly_get_coeff_fmpz(t[i], g->poly, i, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[5 + i], h->poly, i, h->ctx); } /* apply auxiliary routine 3 with (a0, ... , a4) and (b0, ... , b4) store result in (c0, ... , c8) */ unity_zp_ar3(t); /* set d_{1, i} = c_i */ for (i = 0; i < 9; i++) fmpz_set(t[50 + i], t[10 + i]); /* set ai = x{i + 5} and bi = y{i + 5} */ for (i = 0; i < 5; i++) { fmpz_mod_poly_get_coeff_fmpz(t[i], g->poly, 5 + i, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[5 + i], h->poly, 5 + i, h->ctx); } /* apply auxiliary routine 3 with (a0, ... , a4) and (b0, ... , b4) store result in (c0, ... , c8) */ unity_zp_ar3(t); /* now we call c_i as d_{2, i} */ /* set d_{3, i} = d_{3, i} - d_{2, i} - d_{1, i} */ for (i = 0; i < 9; i++) { fmpz_sub(t[40 + i], t[40 + i], t[10 + i]); fmpz_sub(t[40 + i], t[40 + i], t[50 + i]); } /* a1 = d_{2, 0} + d_{3, 5} */ fmpz_add(t[1], t[10], t[45]); /* d_{1, i} += d_{2, i} */ for (i = 0; i < 8; i++) fmpz_add(t[50 + i], t[50 + i], t[11 + i]); /* d_{1, i} += d_{3, i + 6}, i in 0, 1, 2 */ for (i = 0; i < 3; i++) fmpz_add(t[50 + i], t[50 + i], t[46 + i]); /* d_{1, i} += d_{3, i - 5}, i in 5, 6, 7, 8 */ for (i = 5; i < 9; i++) fmpz_add(t[50 + i], t[50 + i], t[35 + i]); /* yi = d_{1, i} - a1 */ for (i = 0; i < 9; i++) { fmpz_sub(t[0], t[50 + i], t[1]); unity_zp_coeff_set_fmpz(f, i, t[0]); } /* a0 = d_{3, 4} - a1 */ fmpz_sub(t[0], t[44], t[1]); unity_zp_coeff_set_fmpz(f, 9, t[0]); /* y9 = a0 mod n */ } /* Computes f = g * h for p = 2^2. g and h must be reduced by F_4 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 9. Resulting f reduced by F_4 cyclotomic polynomial. */ void unity_zp_mul4(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { /* g = (x0, x1); h = (y0, y1); f = (z0, z1); x0 = t[0]; x1 = t[1]; y0 = t[2]; y1 = t[3]; m1 = t[4]; m2 = t[5]; m3 = t[6]; d1 = t[7]; d2 = t[8]; d3 = t[9]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); /* set yi */ fmpz_mod_poly_get_coeff_fmpz(t[2], h->poly, 0, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[3], h->poly, 1, h->ctx); fmpz_add(t[4], t[0], t[1]); /* m1 = x0 + x1 */ fmpz_add(t[5], t[2], t[3]); /* m2 = y0 + y1 */ fmpz_sub(t[6], t[3], t[2]); /* m3 = y1 - y0 */ fmpz_mul(t[7], t[4], t[2]); /* d1 = m1 * y0 */ fmpz_mul(t[8], t[5], t[1]); /* d2 = m2 * x1 */ fmpz_mul(t[9], t[6], t[0]); /* d3 = m3 * x0 */ fmpz_sub(t[0], t[7], t[8]); /* t[0] = d1 - d2 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* z0 = t[0] mod n */ fmpz_add(t[0], t[7], t[9]); /* t[0] = d1 + d3 */ unity_zp_coeff_set_fmpz(f, 1, t[0]); /* z1 = t[0] mod n */ } /* Computes f = g * h for p = 2^3. g and h must be reduced by F_8 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 27. Resulting f reduced by F_8 cyclotomic polynomial. */ void unity_zp_mul8(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { /* g = (x0, x1, x2, x3); h = (y0, y1, y2, y3); f = (z0, z1, z2, z3); x0 = t[0]; x1 = t[1]; x2 = t[2]; x3 = t[3]; y0 = t[4]; y1 = t[5]; y2 = t[6]; y3 = t[7]; m1 = t[8]; ... ; m8 = t[15]; d1 = t[16]; ... ; d12 = t[28]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[2], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[3], g->poly, 3, g->ctx); /* set yi */ fmpz_mod_poly_get_coeff_fmpz(t[4], h->poly, 0, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[5], h->poly, 1, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[6], h->poly, 2, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[7], h->poly, 3, h->ctx); fmpz_add(t[8], t[1], t[3]); /* m1 = x1 + x3 */ fmpz_add(t[9], t[5], t[7]); /* m2 = y1 + y3 */ fmpz_add(t[10], t[2], t[3]); /* m3 = x2 + x3 */ fmpz_add(t[11], t[6], t[7]); /* m4 = y2 + y3 */ fmpz_add(t[12], t[0], t[1]); /* m5 = x0 + x1 */ fmpz_add(t[13], t[4], t[5]); /* m6 = y0 + y1 */ fmpz_add(t[14], t[0], t[2]); /* m7 = x0 + x2 */ fmpz_add(t[15], t[4], t[6]); /* m8 = y0 + y2 */ fmpz_mul(t[16], t[0], t[4]); /* d0 = x0 * y0 */ fmpz_mul(t[17], t[1], t[5]); /* d1 = x1 * y1 */ fmpz_mul(t[18], t[2], t[6]); /* d2 = x2 * y2 */ fmpz_mul(t[19], t[3], t[7]); /* d3 = x3 * y3 */ fmpz_mul(t[22], t[12], t[13]); /* d6 = m5 * m6 */ fmpz_mul(t[23], t[14], t[15]); /* d7 = m7 * m8 */ fmpz_mul(t[24], t[8], t[9]); /* d8 = m1 * m2 */ fmpz_mul(t[25], t[10], t[11]); /* d9 = m3 * m4 */ fmpz_add(t[10], t[8], t[14]); /* m3 = m1 + m7 */ fmpz_add(t[11], t[9], t[15]); /* m4 = m2 + m8 */ fmpz_mul(t[20], t[10], t[11]); /* d4 = m3 * m4 */ fmpz_add(t[26], t[16], t[17]); /* d10 = d0 + d1 */ fmpz_add(t[27], t[18], t[19]); /* d11 = d2 + d3 */ fmpz_add(t[28], t[26], t[19]); /* d12 = d10 + d3 */ fmpz_add(t[21], t[24], t[18]); /* d5 = d8 + d2 */ fmpz_sub(t[0], t[28], t[21]); /* t[0] = d12 - d5 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* z0 = t[0] mod n */ fmpz_add(t[28], t[22], t[27]); /* d12 = d6 + d11 */ fmpz_add(t[21], t[26], t[25]); /* d5 = d10 + d9 */ fmpz_sub(t[0], t[28], t[21]); /* t[0] = d12 - d5 */ unity_zp_coeff_set_fmpz(f, 1, t[0]); /* z1 = t[0] mod n */ fmpz_add(t[28], t[17], t[23]); /* d12 = d1 + d7 */ fmpz_add(t[21], t[16], t[27]); /* d5 = d0 + d11 */ fmpz_sub(t[0], t[28], t[21]); /* t[0] = d12 - d5 */ unity_zp_coeff_set_fmpz(f, 2, t[0]); /* z2 = t[0] mod n */ fmpz_add(t[28], t[23], t[22]); /* d12 = d7 + d6 */ fmpz_add(t[21], t[28], t[24]); /* d5 = d12 + d8 */ fmpz_add(t[28], t[21], t[25]); /* d12 = d5 + d8 */ fmpz_add(t[19], t[26], t[27]); /* d3 = d10 + d11 */ fmpz_add(t[21], t[19], t[20]); /* d5 = d3 + d4 */ fmpz_sub(t[0], t[21], t[28]); /* t[0] = d5 - d12 */ unity_zp_coeff_set_fmpz(f, 3, t[0]); /* z3 = t[0] mod n */ } /* Computes f = g * h for p = 2^4. g and h must be reduced by F_16 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 63. Resulting f reduced by F_16 cyclotomic polynomial. */ void unity_zp_mul16(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { int i; /* g = (x0, ... , x7); h = (y0, ... , y7); f = (z0, ... , z7); x0 = t[30]; x1 = t[31]; x2 = t[32]; x3 = t[33]; x4 = t[34]; x5 = t[35]; x6 = t[36]; x7 = t[37]; y0 = t[40]; y1 = t[41]; y2 = t[42]; y3 = t[43]; y4 = t[44]; y5 = t[45]; y6 = t[46]; y7 = t[47]; a0 = t[0]; ... ; a3 = t[3]; b0 = t[4]; ... ; b3 = t[7]; c0 = t[8]; ... ; t[14]; d0 = t[50]; ... ; d12 = t[62]; */ /* set xi */ for (i = 0; i < 8; i++) fmpz_mod_poly_get_coeff_fmpz(t[30 + i], g->poly, i, g->ctx); /* set yi */ for (i = 0; i < 8; i++) fmpz_mod_poly_get_coeff_fmpz(t[40 + i], h->poly, i, h->ctx); fmpz_add(t[0], t[30], t[34]); /* a0 = x0 + x4 */ fmpz_add(t[1], t[31], t[35]); /* a1 = x1 + x5 */ fmpz_add(t[2], t[32], t[36]); /* a2 = x2 + x6 */ fmpz_add(t[3], t[33], t[37]); /* a3 = x3 + x7 */ fmpz_set(t[4], t[40]); /* set b0 = y0 */ fmpz_set(t[5], t[41]); /* set b1 = y1 */ fmpz_set(t[6], t[42]); /* set b2 = y2 */ fmpz_set(t[7], t[43]); /* set b3 = y3 */ /* apply auxiliary routine 2 with (a0, .. , a3) and (b0, .. , b3) store result in (c0, .. , c6) */ unity_zp_ar2(t); /* set d_i = c_i */ for (i = 0; i < 7; i++) fmpz_set(t[50 + i], t[8 + i]); fmpz_add(t[0], t[40], t[44]); /* a0 = y0 + y4 */ fmpz_add(t[1], t[41], t[45]); /* a1 = y1 + y5 */ fmpz_add(t[2], t[42], t[46]); /* a2 = y2 + y6 */ fmpz_add(t[3], t[43], t[47]); /* a3 = y3 + y7 */ fmpz_set(t[4], t[34]); /* set b0 = x4 */ fmpz_set(t[5], t[35]); /* set b1 = x5 */ fmpz_set(t[6], t[36]); /* set b2 = x6 */ fmpz_set(t[7], t[37]); /* set b3 = x7 */ /* apply auxiliary routine 2 with (a0, .. , a3) and (b0, .. , b3) store result in (c0, .. , c6) */ unity_zp_ar2(t); /* set d_{7 + i} = c_i */ for (i = 0; i < 7; i++) fmpz_set(t[57 + i], t[8 + i]); fmpz_sub(t[0], t[44], t[40]); /* a0 = y4 - y0 */ fmpz_sub(t[1], t[45], t[41]); /* a1 = y5 - y1 */ fmpz_sub(t[2], t[46], t[42]); /* a2 = y6 - y2 */ fmpz_sub(t[3], t[47], t[43]); /* a3 = y7 - y3 */ fmpz_set(t[4], t[30]); /* set b0 = x0 */ fmpz_set(t[5], t[31]); /* set b1 = x1 */ fmpz_set(t[6], t[32]); /* set b2 = x2 */ fmpz_set(t[7], t[33]); /* set b3 = x3 */ /* apply auxiliary routine 2 with (a0, .. , a3) and (b0, .. , b3) store result in (c0, .. , c6) */ unity_zp_ar2(t); fmpz_add(t[1], t[54], t[57]); /* a1 = d4 + d7 */ fmpz_add(t[2], t[1], t[12]); /* a2 = a1 + c3 */ fmpz_sub(t[0], t[50], t[2]); /* a0 = d0 - a2 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* z0 = a0 mod n */ fmpz_add(t[1], t[55], t[58]); /* a1 = d5 + d8 */ fmpz_add(t[2], t[1], t[13]); /* a2 = a1 + c4 */ fmpz_sub(t[0], t[51], t[2]); /* a0 = d1 - a2 */ unity_zp_coeff_set_fmpz(f, 1, t[0]); /* z1 = a0 mod n */ fmpz_add(t[1], t[56], t[59]); /* a1 = d6 + d9 */ fmpz_add(t[2], t[1], t[14]); /* a2 = a1 + c5 */ fmpz_sub(t[0], t[52], t[2]); /* a0 = d2 - a2 */ unity_zp_coeff_set_fmpz(f, 2, t[0]); /* z2 = a0 mod n */ fmpz_sub(t[0], t[53], t[60]); /* a0 = d3 - d10 */ unity_zp_coeff_set_fmpz(f, 3, t[0]); /* z3 = a0 mod n */ fmpz_add(t[1], t[54], t[50]); /* a1 = d4 + d0 */ fmpz_add(t[2], t[1], t[8]); /* a2 = a1 + c0 */ fmpz_sub(t[0], t[2], t[61]); /* a0 = a2 - d11 */ unity_zp_coeff_set_fmpz(f, 4, t[0]); /* z4 = a0 mod n */ fmpz_add(t[1], t[55], t[51]); /* a1 = d5 + d1 */ fmpz_add(t[2], t[1], t[9]); /* a2 = a1 + c0 */ fmpz_sub(t[0], t[2], t[62]); /* a0 = a2 - d12 */ unity_zp_coeff_set_fmpz(f, 5, t[0]); /* z5 = a0 mod n */ fmpz_add(t[1], t[56], t[52]); /* a1 = d6 + d2 */ fmpz_add(t[2], t[1], t[10]); /* a2 = a1 + c1 */ fmpz_sub(t[0], t[2], t[63]); /* a0 = a2 - a13 */ unity_zp_coeff_set_fmpz(f, 6, t[0]); /* z6 = a0 mod n */ fmpz_add(t[1], t[53], t[11]); /* a1 = d3 + c2 */ unity_zp_coeff_set_fmpz(f, 7, t[1]); /* z7 = a1 mod n */ } /* Computes f = g * h for p = 3. g and h must be reduced by F_3 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 3. Resulting f reduced by F_3 cyclotomic polynomial. */ void unity_zp_mul3(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { /* g = (x0, x1); h = (y0, y1); f = (z0, z1); x0 = t[0]; x1 = t[1]; y0 = t[2]; y1 = t[3]; m1 = t[4]; m2 = t[5]; d1 = t[6]; d2 = t[7]; d3 = t[8]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); /* set yi */ fmpz_mod_poly_get_coeff_fmpz(t[2], h->poly, 0, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[3], h->poly, 1, h->ctx); fmpz_mul(t[6], t[0], t[2]); /* d1 = x0 * y0 */ fmpz_mul(t[7], t[1], t[3]); /* d2 = x1 * y1 */ fmpz_sub(t[4], t[0], t[1]); /* m1 = x0 - x1 */ fmpz_sub(t[5], t[3], t[2]); /* m2 = y1 - y0 */ fmpz_mul(t[8], t[4], t[5]); /* d3 = m1 * m2 */ fmpz_add(t[8], t[8], t[6]); /* d3 = d3 + d1 */ unity_zp_coeff_set_fmpz(f, 1, t[8]); /* z1 = d3 mod n */ fmpz_sub(t[0], t[6], t[7]); /* x0 = d1 - d2 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* z0 = x0 mod n */ } /* Computes f = g * h for p = 3^2. g and h must be reduced by F_9 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 50. Resulting f reduced by F_9 cyclotomic polynomial. */ void unity_zp_mul9(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { /* g = (x0, ... , x5); h = (y0, ... , y5); f = (z0, ... , z5); x0 = t[20]; ... ; x5 = t[25]; y0 = t[26]; ... ; y5 = t[31]; a0 = t[0]; a1 = t[1]; a2 = t[2]; b0 = t[3]; b1 = t[4]; b2 = t[5]; c0 = t[6]; ... ; c4 = t[10]; d0 = t[32]; ... ; d19 = t[51]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[20], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[21], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[22], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[23], g->poly, 3, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[24], g->poly, 4, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[25], g->poly, 5, g->ctx); /* set yi */ fmpz_mod_poly_get_coeff_fmpz(t[26], h->poly, 0, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[27], h->poly, 1, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[28], h->poly, 2, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[29], h->poly, 3, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[30], h->poly, 4, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[31], h->poly, 5, h->ctx); fmpz_set(t[0], t[20]); /* set a0 = x0 */ fmpz_set(t[1], t[21]); /* set a1 = x1 */ fmpz_set(t[2], t[22]); /* set a2 = x2 */ fmpz_set(t[3], t[26]); /* set b0 = y0 */ fmpz_set(t[4], t[27]); /* set b1 = y1 */ fmpz_set(t[5], t[28]); /* set b2 = y2 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_set(t[32], t[6]); /* set d0 = c0 */ fmpz_set(t[33], t[7]); /* set d1 = c1 */ fmpz_set(t[34], t[8]); /* set d2 = c2 */ fmpz_set(t[35], t[9]); /* set d3 = c3 */ fmpz_set(t[36], t[10]); /* set d4 = c4 */ fmpz_set(t[0], t[23]); /* set a0 = x3 */ fmpz_set(t[1], t[24]); /* set a1 = x4 */ fmpz_set(t[2], t[25]); /* set a2 = x5 */ fmpz_set(t[3], t[29]); /* set b0 = y3 */ fmpz_set(t[4], t[30]); /* set b1 = y4 */ fmpz_set(t[5], t[31]); /* set b2 = y5 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_set(t[38], t[6]); /* set d6 = c0 */ fmpz_set(t[39], t[7]); /* set d7 = c1 */ fmpz_set(t[40], t[8]); /* set d8 = c2 */ fmpz_set(t[41], t[9]); /* set d9 = c3 */ fmpz_set(t[42], t[10]); /* set d10 = c4 */ fmpz_sub(t[0], t[20], t[23]); /* a0 = x0 - x3 */ fmpz_sub(t[1], t[21], t[24]); /* a1 = x1 - x4 */ fmpz_sub(t[2], t[22], t[25]); /* a2 = x2 - x5 */ fmpz_sub(t[3], t[29], t[26]); /* b0 = y3 - y0 */ fmpz_sub(t[4], t[30], t[27]); /* b1 = y4 - y1 */ fmpz_sub(t[5], t[31], t[28]); /* b2 = y5 - y2 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_set(t[43], t[6]); /* set d11 = c0 */ fmpz_set(t[44], t[7]); /* set d12 = c1 */ fmpz_set(t[45], t[8]); /* set d13 = c2 */ fmpz_set(t[46], t[9]); /* set d14 = c3 */ fmpz_set(t[47], t[10]); /* set d15 = c4 */ fmpz_add(t[50], t[38], t[46]); /* d18 = d6 + d14 */ fmpz_add(t[48], t[50], t[35]); /* d16 = d18 + d3 */ fmpz_add(t[50], t[39], t[47]); /* d18 = d7 + d15 */ fmpz_add(t[49], t[50], t[36]); /* d17 = d18 + d4 */ fmpz_add(t[50], t[35], t[43]); /* d18 = d3 + d11 */ fmpz_add(t[35], t[50], t[32]); /* d3 = d18 + d0 */ fmpz_add(t[50], t[36], t[44]); /* d18 = d4 + d12 */ fmpz_add(t[36], t[50], t[33]); /* d4 = d18 + d1 */ fmpz_add(t[37], t[34], t[45]); /* d5 = d2 + d13 */ fmpz_sub(t[0], t[32], t[48]); /* a0 = d0 - d16 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* z0 = a0 mod n */ fmpz_sub(t[0], t[33], t[49]); /* a0 = d1 - d17 */ unity_zp_coeff_set_fmpz(f, 1, t[0]); /* z1 = a0 mod n */ fmpz_sub(t[0], t[34], t[40]); /* a0 = d2 - d8 */ unity_zp_coeff_set_fmpz(f, 2, t[0]); /* z2 = a0 mod n */ unity_zp_coeff_set_fmpz(f, 5, t[37]); /* z5 = d5 mod n */ fmpz_add(t[50], t[35], t[38]); /* d18 = d3 + d6 */ fmpz_add(t[51], t[48], t[41]); /* d19 = d16 + d9 */ fmpz_sub(t[0], t[50], t[51]); /* a0 = d18 - d19 */ unity_zp_coeff_set_fmpz(f, 3, t[0]); /* z3 = a0 mod n */ fmpz_add(t[50], t[36], t[39]); /* d18 = d4 + d7 */ fmpz_add(t[51], t[42], t[49]); /* d19 = d10 + d17 */ fmpz_sub(t[0], t[50], t[51]); /* a0 = d18 - d19 */ unity_zp_coeff_set_fmpz(f, 4, t[0]); /* z4 = a0 mod n */ } /* Computes f = g * h for p = 5. g and h must be reduced by F_5 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 24. Resulting f reduced by F_5 cyclotomic polynomial. */ void unity_zp_mul5(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { /* g = (x0, x1, x2, x3); h = (y0, y1, y2, y3); f = (z0, z1, z2, z3); x0 = t[0]; x1 = t[1]; x2 = t[2]; x3 = t[3]; y0 = t[4]; y1 = t[5]; y2 = t[6]; y3 = t[7]; m1 = t[8]; m2 = t[9]; m3 = t[10]; m4 = t[11]; m5 = t[12]; m6 = t[13]; m7 = t[14]; m8 = t[15]; d0 = t[16]; d1 = t[17]; d2 = t[18]; d3 = t[19]; d4 = t[20]; d5 = t[21]; d6 = t[22]; d7 = t[23]; d8 = t[24]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[2], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[3], g->poly, 3, g->ctx); /* set yi */ fmpz_mod_poly_get_coeff_fmpz(t[4], h->poly, 0, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[5], h->poly, 1, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[6], h->poly, 2, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[7], h->poly, 3, h->ctx); fmpz_sub(t[8], t[1], t[3]); /* m1 = x1 - x3 */ fmpz_sub(t[9], t[5], t[7]); /* m2 = y1 - y3 */ fmpz_sub(t[10], t[2], t[3]); /* m3 = x2 - x3 */ fmpz_sub(t[11], t[7], t[6]); /* m4 = y3 - y2 */ fmpz_sub(t[12], t[0], t[1]); /* m5 = x0 - x1 */ fmpz_sub(t[13], t[5], t[4]); /* m6 = y1 - y0 */ fmpz_sub(t[14], t[0], t[2]); /* m7 = x0 - x2 */ fmpz_sub(t[15], t[6], t[4]); /* m8 = y2 - y0 */ fmpz_mul(t[16], t[0], t[4]); /* d0 = x0 * y0 */ fmpz_mul(t[18], t[8], t[9]); /* d2 = m1 * m2 */ fmpz_add(t[17], t[16], t[18]); /* d1 = d0 + d2 */ fmpz_mul(t[18], t[10], t[11]); /* d2 = m3 * m4 */ fmpz_mul(t[19], t[12], t[13]); /* d3 = m5 * m6 */ fmpz_mul(t[20], t[14], t[15]); /* d4 = m7 * m8 */ fmpz_mul(t[21], t[1], t[5]); /* d5 = x1 * y1 */ fmpz_mul(t[22], t[2], t[6]); /* d6 = x2 * y2 */ fmpz_mul(t[23], t[3], t[7]); /* d7 = x3 * y3 */ fmpz_add(t[24], t[17], t[18]); /* d8 = d1 + d2 */ fmpz_sub(t[0], t[24], t[21]); /* x0 = d8 - d5 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* z0 = x0 mod n */ fmpz_add(t[24], t[17], t[19]); /* d8 = d1 + d3 */ fmpz_sub(t[0], t[24], t[22]); /* x0 = d8 - d6 */ unity_zp_coeff_set_fmpz(f, 1, t[0]); /* z1 = x0 mod n */ fmpz_add(t[24], t[17], t[20]); /* d8 = d1 + d4 */ fmpz_sub(t[0], t[24], t[23]); /* x0 = d8 - d7 */ unity_zp_coeff_set_fmpz(f, 2, t[0]); /* z2 = x0 mod n */ fmpz_sub(t[10], t[8], t[14]); /* m3 = m1 - m7 */ fmpz_add(t[11], t[9], t[15]); /* m4 = m2 + m8 */ fmpz_mul(t[17], t[10], t[11]); /* d1 = m3 * m4 */ fmpz_add(t[24], t[16], t[17]); /* d8 = d0 + d1 */ fmpz_add(t[23], t[24], t[18]); /* d7 = d8 + d2 */ fmpz_add(t[24], t[23], t[19]); /* d8 = d7 + d3 */ fmpz_add(t[0], t[24], t[20]); /* d7 = d8 + d4 */ unity_zp_coeff_set_fmpz(f, 3, t[0]); /* z3 = d7 mod n */ } /* Computes f = g * h for p = 7. g and h must be reduced by F_7 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 68. Resulting f reduced by F_7 cyclotomic polynomial. */ void unity_zp_mul7(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t) { /* g = (x0, ... , x5); h = (y0, ... , y5); f = (z0, ... , z5); x0 = t[30]; x1 = t[31]; x2 = t[32]; x3 = t[33]; x4 = t[34]; x5 = t[35]; y0 = t[40]; y1 = t[41]; y2 = t[42]; y3 = t[43]; y4 = t[44]; y5 = t[45]; a0 = t[0]; a1 = t[1] ; a2 = t[2]; b0 = t[3]; b1 = t[4] ; b2 = t[5]; c0 = t[6]; ... ; c4 = t[10]; d0 = t[50]; ... ; d18 = t[68]; */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[30], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[31], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[32], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[33], g->poly, 3, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[34], g->poly, 4, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[35], g->poly, 5, g->ctx); /* set yi */ fmpz_mod_poly_get_coeff_fmpz(t[40], h->poly, 0, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[41], h->poly, 1, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[42], h->poly, 2, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[43], h->poly, 3, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[44], h->poly, 4, h->ctx); fmpz_mod_poly_get_coeff_fmpz(t[45], h->poly, 5, h->ctx); fmpz_set(t[0], t[30]); /* set a0 = x0 */ fmpz_set(t[1], t[31]); /* set a1 = x1 */ fmpz_set(t[2], t[32]); /* set a2 = x2 */ fmpz_set(t[3], t[40]); /* set b0 = y0 */ fmpz_set(t[4], t[41]); /* set b1 = y1 */ fmpz_set(t[5], t[42]); /* set b2 = y2 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_set(t[50], t[6]); /* set d0 = c0 */ fmpz_set(t[51], t[7]); /* set d1 = c1 */ fmpz_set(t[52], t[8]); /* set d2 = c2 */ fmpz_set(t[53], t[9]); /* set d3 = c3 */ fmpz_set(t[54], t[10]); /* set d4 = c4 */ fmpz_set(t[0], t[33]); /* set a0 = x3 */ fmpz_set(t[1], t[34]); /* set a1 = x4 */ fmpz_set(t[2], t[35]); /* set a2 = x5 */ fmpz_set(t[3], t[43]); /* set b0 = y3 */ fmpz_set(t[4], t[44]); /* set b1 = y4 */ fmpz_set(t[5], t[45]); /* set b2 = y5 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_set(t[56], t[6]); /* set d6 = c0 */ fmpz_set(t[57], t[7]); /* set d7 = c1 */ fmpz_set(t[58], t[8]); /* set d8 = c2 */ fmpz_set(t[59], t[9]); /* set d9 = c3 */ fmpz_set(t[60], t[10]); /* set d10 = c4 */ fmpz_sub(t[0], t[30], t[33]); /* a0 = x0 - x3 */ fmpz_sub(t[1], t[31], t[34]); /* a1 = x1 - x4 */ fmpz_sub(t[2], t[32], t[35]); /* a2 = x2 - x5 */ fmpz_sub(t[3], t[43], t[40]); /* b0 = y3 - y0 */ fmpz_sub(t[4], t[44], t[41]); /* b1 = y4 - y1 */ fmpz_sub(t[5], t[45], t[42]); /* b2 = y5 - y2 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_set(t[61], t[6]); /* set d11 = c0 */ fmpz_set(t[62], t[7]); /* set d12 = c1 */ fmpz_set(t[63], t[8]); /* set d13 = c2 */ fmpz_set(t[64], t[9]); /* set d14 = c3 */ fmpz_set(t[65], t[10]); /* set d15 = c4 */ fmpz_add(t[68], t[56], t[64]); /* d18 = d6 + d14 */ fmpz_add(t[66], t[68], t[53]); /* d16 = d18 + d3 */ fmpz_add(t[68], t[57], t[65]); /* d18 = d7 + d15 */ fmpz_add(t[67], t[68], t[54]); /* d17 = d18 + d4 */ fmpz_add(t[68], t[53], t[61]); /* d18 = d3 + d11 */ fmpz_add(t[53], t[68], t[50]); /* d3 = d18 + d0 */ fmpz_add(t[68], t[54], t[62]); /* d18 = d4 + d12 */ fmpz_add(t[54], t[68], t[51]); /* d4 = d18 + d1 */ fmpz_add(t[55], t[52], t[63]); /* d5 = d2 + d13 */ fmpz_add(t[63], t[53], t[56]); /* d13 = d3 + d6 */ fmpz_add(t[64], t[54], t[57]); /* d14 = d4 + d7 */ fmpz_add(t[65], t[55], t[58]); /* d15 = d5 + d8 */ fmpz_add(t[56], t[66], t[59]); /* d6 = d16 + d9 */ fmpz_add(t[57], t[67], t[60]); /* d7 = d17 + d10 */ fmpz_add(t[68], t[50], t[57]); /* d18 = d10 + d7 */ fmpz_sub(t[0], t[68], t[56]); /* a0 = d18 - d6 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* z0 = a0 mod n */ fmpz_add(t[68], t[51], t[58]); /* d18 = d1 + d8 */ fmpz_sub(t[0], t[68], t[56]); /* a0 = d18 - d6 */ unity_zp_coeff_set_fmpz(f, 1, t[0]); /* z1 = a0 mod n */ fmpz_add(t[68], t[52], t[59]); /* d18 = d2 + d9 */ fmpz_sub(t[0], t[68], t[56]); /* a0 = d18 - d6 */ unity_zp_coeff_set_fmpz(f, 2, t[0]); /* z2 = a0 mod n */ fmpz_add(t[68], t[63], t[60]); /* d18 = d13 + d10 */ fmpz_sub(t[0], t[68], t[56]); /* a0 = d18 - d6 */ unity_zp_coeff_set_fmpz(f, 3, t[0]); /* z3 = a0 mod n */ fmpz_sub(t[0], t[64], t[56]); /* a0 = d14 - d6 */ unity_zp_coeff_set_fmpz(f, 4, t[0]); /* z4 = a0 mod n */ fmpz_sub(t[0], t[65], t[56]); /* a0 = d15 - d6 */ unity_zp_coeff_set_fmpz(f, 5, t[0]); /* z5 = a0 mod n */ } void unity_zp_mul_scalar_ui(unity_zp f, const unity_zp g, ulong s) { FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); fmpz_mod_poly_scalar_mul_ui(f->poly, g->poly, s, f->ctx); } flint-3.1.3/src/aprcl/unity_zp_pow.c000066400000000000000000000021701461254215100174350ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "aprcl.h" void unity_zp_pow_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow) { slong i; unity_zp temp; unity_zp_init(temp, f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); unity_zp_set_zero(f); unity_zp_coeff_set_ui(f, 0, 1); i = fmpz_bits(pow) - 1; while (i >= 0) { unity_zp_sqr(temp, f); unity_zp_swap(f, temp); if (fmpz_tstbit(pow, i) == 1) { unity_zp_mul(temp, f, g); unity_zp_swap(f, temp); } i--; } unity_zp_clear(temp); } void unity_zp_pow_ui(unity_zp f, const unity_zp g, ulong pow) { fmpz_t p; fmpz_init_set_ui(p, pow); unity_zp_pow_fmpz(f, g, p); fmpz_clear(p); } flint-3.1.3/src/aprcl/unity_zp_pow_2k.c000066400000000000000000000065431461254215100200410ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "aprcl.h" void unity_zp_pow_2k_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow) { ulong j, k, pow2k; slong i, e; fmpz_t digit; unity_zp temp; unity_zp *g_powers; fmpz_init(digit); unity_zp_init(temp, f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); /* g_sqr = g * g */ unity_zp_sqr(temp, g); /* selects optimal k value for n */ k = _unity_zp_pow_select_k(pow); /* selects e such that 2^(ek) < n < 2^((e + 1) * k) */ e = (fmpz_bits(pow) - 1) / k; /* g_powers store odd powers of g up to 2^k - 1; g_powers[(i + 1) / 2] = g^i */ pow2k = 1 << (k - 1); g_powers = (unity_zp*) flint_malloc(sizeof(unity_zp) * (pow2k + 1)); /* sets g_powers[0] = 1 */ unity_zp_init(g_powers[0], f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); unity_zp_coeff_set_ui(g_powers[0], 0, 1); /* sets g_powers[1] = g */ unity_zp_init(g_powers[1], f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); unity_zp_copy(g_powers[1], g); /* sets g_powers[i] = g^2 * g_powers[i - 1] */ for (i = 2; i <= pow2k; i++) { unity_zp_init(g_powers[i], f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); unity_zp_mul(g_powers[i], g_powers[i - 1], temp); } /* for all digits[i] */ for (i = e; i >= 0; i--) { /* digit contains i-th digit of pow in k-ary base; k <= 11 so digit < 2^11 and fit into ulong */ fmpz_fdiv_q_2exp(digit, pow, i * k); fmpz_fdiv_r_2exp(digit, digit, k); /* if digit == 0 set f = f^(2^k) */ if (*digit == 0) { for (j = 0; j < k; j++) { /* sets f = f^2 */ unity_zp_sqr(temp, f); unity_zp_swap(temp, f); } } else { ulong t, b; /* digit = 2^t * b and b is odd */ t = aprcl_p_power_in_q(*digit, 2); b = *digit / (1 << t); if (i == e) { unity_zp_copy(f, g_powers[(b + 1) / 2]); } else { /* sets f = f^(2^(k - t)) */ for (j = 0; j < k - t; j++) { unity_zp_sqr(temp, f); unity_zp_swap(temp, f); } /* sets f = f * g^b */ unity_zp_mul(temp, f, g_powers[(b + 1) / 2]); unity_zp_swap(temp, f); } /* sets f = f^(2^t) */ for (j = 0; j < t; j++) { unity_zp_sqr(temp, f); unity_zp_swap(temp, f); } } } for (i = 0; i <= pow2k; i++) unity_zp_clear(g_powers[i]); flint_free(g_powers); fmpz_clear(digit); unity_zp_clear(temp); } void unity_zp_pow_2k_ui(unity_zp f, const unity_zp g, ulong pow) { fmpz_t p; fmpz_init_set_ui(p, pow); unity_zp_pow_2k_fmpz(f, g, p); fmpz_clear(p); } flint-3.1.3/src/aprcl/unity_zp_pow_select_k.c000066400000000000000000000017001461254215100213040ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "aprcl.h" /* returns smallest integer k satisfies: log(n) < (k * (k + 1) * 2^(2 * k)) / (2^(k + 1) - k - 2) + 1 */ ulong _unity_zp_pow_select_k(const fmpz_t n) { ulong bits; bits = fmpz_bits(n); if (bits <= 8) return 1; if (bits <= 24) return 2; if (bits <= 69) return 3; if (bits <= 196) return 4; if (bits <= 538) return 5; if (bits <= 1433) return 6; if (bits <= 3714) return 7; if (bits <= 9399) return 8; if (bits <= 23290) return 9; if (bits <= 56651) return 10; return 11; } flint-3.1.3/src/aprcl/unity_zp_pow_sliding.c000066400000000000000000000063231461254215100211520ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "aprcl.h" void unity_zp_pow_sliding_fmpz(unity_zp f, unity_zp g, const fmpz_t pow) { ulong h, k, value; slong i, j; unity_zp temp; unity_zp *g_powers; fmpz_t * t; t = (fmpz_t*) flint_malloc(sizeof(fmpz_t) * SQUARING_SPACE); for (i = 0; i < SQUARING_SPACE; i++) fmpz_init(t[i]); unity_zp_init(temp, f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); /* reduce g by cyclopoly */ _unity_zp_reduce_cyclotomic(g); /* temp = g * g */ unity_zp_sqr_inplace(temp, g, t); /* selects optimal k value for n */ k = _unity_zp_pow_select_k(pow); /* g_powers store odd powers of g up to 2^k - 1; g_powers[(i + 1) / 2] = g^i */ g_powers = (unity_zp*) flint_malloc(sizeof(unity_zp) * (n_pow(2, k - 1) + 1)); /* sets g_powers[0] = 1 */ unity_zp_init(g_powers[0], f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); unity_zp_coeff_set_ui(g_powers[0], 0, 1); /* sets g_powers[1] = g */ unity_zp_init(g_powers[1], f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); unity_zp_copy(g_powers[1], g); /* sets g_powers[i] = g^2 * g_powers[i - 1] */ for (i = 2; i <= n_pow(2, k - 1); i++) { unity_zp_init(g_powers[i], f->p, f->exp, fmpz_mod_ctx_modulus(f->ctx)); unity_zp_mul_inplace(g_powers[i], g_powers[i - 1], temp, t); } unity_zp_set_zero(f); unity_zp_coeff_set_ui(f, 0, 1); i = fmpz_bits(pow) - 1; /* working with pow = (e_l, e_{l-1}, ... , e_0) in 2 base */ while (i >= 0) { if (fmpz_tstbit(pow, i) == 0) { unity_zp_sqr_inplace(temp, f, t); unity_zp_swap(temp, f); i--; } else { /* finds length of chain; chain is length of longest bitstring less then k ending on 1 */ j = FLINT_MAX(i - k + 1, 0); while (fmpz_tstbit(pow, j) == 0 && j <= i) j++; /* f = f^(2^(i - j + 1)) */ for (h = 0; h < i - j + 1; h++) { unity_zp_sqr_inplace(temp, f, t); unity_zp_swap(temp, f); } /* value = binary number (e_i, ... , e_j) in decimal base */ value = 0; for (h = 0; h < i - j + 1; h++) value += fmpz_tstbit(pow, j + h) << h; /* f = f * g^value */ unity_zp_mul_inplace(temp, f, g_powers[(value + 1) / 2], t); unity_zp_swap(temp, f); /* increase i */ i = j - 1; } } for (i = 0; i < SQUARING_SPACE; i++) fmpz_clear(t[i]); flint_free(t); for (i = 0; i <= n_pow(2, k - 1); i++) unity_zp_clear(g_powers[i]); flint_free(g_powers); unity_zp_clear(temp); } flint-3.1.3/src/aprcl/unity_zp_reduce_cyclotomic.c000066400000000000000000000047331461254215100223330ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void _unity_zp_reduce_cyclotomic_divmod(unity_zp f) { ulong i, j, ppow1, ppow2, cycl_pow; ppow2 = n_pow(f->p, f->exp - 1); ppow1 = ppow2 * f->p; cycl_pow = (f->p - 1) * ppow2; for (i = f->poly->length - 1; i >= ppow1; i--) { fmpz_add(f->poly->coeffs + i - ppow1, f->poly->coeffs + i - ppow1, f->poly->coeffs + i); fmpz_set_ui(f->poly->coeffs + i, 0); } for (i = f->poly->length - 1; i >= cycl_pow; i--) { if (fmpz_is_zero(f->poly->coeffs + i)) continue; for (j = 0; j < f->p - 1; j++) { ulong ind = i - cycl_pow + j * ppow2; fmpz_sub(f->poly->coeffs + ind, f->poly->coeffs + ind, f->poly->coeffs + i); } fmpz_set_ui(f->poly->coeffs + i, 0); } _fmpz_mod_poly_normalise(f->poly); _fmpz_vec_scalar_mod_fmpz(f->poly->coeffs, f->poly->coeffs, f->poly->length, fmpz_mod_ctx_modulus(f->ctx)); _fmpz_mod_poly_normalise(f->poly); } void _unity_zp_reduce_cyclotomic(unity_zp f) { ulong i, j, ppow, cycl_pow; if (f->poly->length == 0) return; ppow = n_pow(f->p, f->exp - 1); cycl_pow = (f->p - 1) * ppow; for (i = f->poly->length - 1; i >= cycl_pow; i--) { if (fmpz_is_zero(f->poly->coeffs + i)) continue; for (j = 0; j < f->p - 1; j++) { ulong ind = i - cycl_pow + j * ppow; fmpz_sub(f->poly->coeffs + ind, f->poly->coeffs + ind, f->poly->coeffs + i); if (fmpz_cmp_ui(f->poly->coeffs + ind, 0) < 0) fmpz_add(f->poly->coeffs + ind, f->poly->coeffs + ind, fmpz_mod_ctx_modulus(f->ctx)); } fmpz_set_ui(f->poly->coeffs + i, 0); } _fmpz_mod_poly_normalise(f->poly); } void unity_zp_reduce_cyclotomic(unity_zp f, const unity_zp g) { unity_zp_copy(f, g); _unity_zp_reduce_cyclotomic(f); } flint-3.1.3/src/aprcl/unity_zp_set_zero.c000066400000000000000000000007771461254215100204750ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zp_set_zero(unity_zp f) { fmpz_mod_poly_zero(f->poly, f->ctx); } flint-3.1.3/src/aprcl/unity_zp_sqr.c000066400000000000000000000574631461254215100174540ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zp_sqr(unity_zp f, const unity_zp g) { if (g->poly->length == 0) { fmpz_mod_poly_zero(f->poly, f->ctx); return; } fmpz_mod_poly_fit_length(f->poly, g->poly->length * 2 - 1, f->ctx); _fmpz_poly_sqr(f->poly->coeffs, g->poly->coeffs, g->poly->length); _fmpz_mod_poly_set_length(f->poly, 2 * g->poly->length - 1); _unity_zp_reduce_cyclotomic_divmod(f); } void unity_zp_sqr_inplace(unity_zp f, const unity_zp g, fmpz_t * t) { /* squaring for p^k = 4 */ if (f->p == 2 && f->exp == 2) { unity_zp_sqr4(f, g, t); return; } /* squaring for p^k = 8 */ if (f->p == 2 && f->exp == 3) { unity_zp_sqr8(f, g, t); return; } /* squaring for p^k = 16 */ if (f->p == 2 && f->exp == 4) { unity_zp_sqr16(f, g, t); return; } /* squaring for p^k = 3 */ if (f->p == 3 && f->exp == 1) { unity_zp_sqr3(f, g, t); return; } /* squaring for p^k = 9 */ if (f->p == 3 && f->exp == 2) { unity_zp_sqr9(f, g, t); return; } /* squaring for p^k = 5 */ if (f->p == 5 && f->exp == 1) { unity_zp_sqr5(f, g, t); return; } /* squaring for p^k = 7 */ if (f->p == 7 && f->exp == 1) { unity_zp_sqr7(f, g, t); return; } /* squaring for p^k = 11 */ if (f->p == 11 && f->exp == 1) { unity_zp_sqr11(f, g, t); return; } /* traditional squaring */ unity_zp_sqr(f, g); } /* Computes f = g * g for p = 11. g must be reduced by F_11 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 69. Resulting f reduced by F_11 cyclotomic polynomial. */ void unity_zp_sqr11(unity_zp f, const unity_zp g, fmpz_t * t) { int i; /* g = (x0, ... , x9); f = (y0, ... , y9); x0 = t[30]; ... ; x9 = t[39]; for auxiliary routine 4: a0 = t[0]; ... ; a4 = t[4]; c0 = t[5]; ... ; c8 = t[13]; for auxiliary routine 3: a0 = t[0]; ... ; a4 = t[4]; b0 = t[5]; ... ; a4 = b[9]; c0 = t[10]; ... ; t[18]; d_{1, i} = t[50 + i] for i in [0, 9]; d_{2, i} = t[60 + i] for i in [0, 9]; d_{3, i} = t[10 + i] for i in [0, 9]. */ /* set xi */ for (i = 0; i < 10; i++) fmpz_mod_poly_get_coeff_fmpz(t[30 + i], g->poly, i, g->ctx); fmpz_set(t[0], t[30]); /* set a0 = x0 */ fmpz_set(t[1], t[31]); /* set a1 = x1 */ fmpz_set(t[2], t[32]); /* set a2 = x2 */ fmpz_set(t[3], t[33]); /* set a3 = x3 */ fmpz_set(t[4], t[34]); /* set a4 = x4 */ /* apply auxiliary routine 4 with (a0, .. , a4) store result in (c0, .. , c8) */ unity_zp_ar4(t); /* set d_{1, i} = c_i */ for (i = 0; i < 9; i++) fmpz_set(t[50 + i], t[5 + i]); fmpz_set(t[0], t[35]); /* set a0 = x5 */ fmpz_set(t[1], t[36]); /* set a1 = x6 */ fmpz_set(t[2], t[37]); /* set a2 = x7 */ fmpz_set(t[3], t[38]); /* set a3 = x8 */ fmpz_set(t[4], t[39]); /* set a4 = x9 */ /* apply auxiliary routine 4 with (a0, ... , a4) store result in (c0, ... , c8) */ unity_zp_ar4(t); /* set d_{2, i} = c_i */ for (i = 0; i < 9; i++) fmpz_set(t[60 + i], t[5 + i]); fmpz_set(t[0], t[35]); /* set a0 = x5 */ fmpz_set(t[1], t[36]); /* set a1 = x6 */ fmpz_set(t[2], t[37]); /* set a2 = x7 */ fmpz_set(t[3], t[38]); /* set a3 = x8 */ fmpz_set(t[4], t[39]); /* set a4 = x9 */ fmpz_mul_2exp(t[5], t[30], 1); /* b0 = 2 * x0 */ fmpz_mul_2exp(t[6], t[31], 1); /* b1 = 2 * x1 */ fmpz_mul_2exp(t[7], t[32], 1); /* b2 = 2 * x2 */ fmpz_mul_2exp(t[8], t[33], 1); /* b3 = 2 * x3 */ fmpz_mul_2exp(t[9], t[34], 1); /* b4 = 2 * x4 */ /* apply auxiliary routine 3 with (a0, ... , a4) and (b0, ... , b4) store result in (c0, ... , c8) */ unity_zp_ar3(t); /* now we call c_i as d_{3, i} */ /* a1 = d_{2, 0} + d_{3, 5} */ fmpz_add(t[1], t[60], t[15]); /* d_{1, i} += d_{2, i} */ for (i = 0; i < 8; i++) fmpz_add(t[50 + i], t[50 + i], t[61 + i]); /* d_{1, i} += d_{3, i + 6}, i in 0, 1, 2 */ for (i = 0; i < 3; i++) fmpz_add(t[50 + i], t[50 + i], t[16 + i]); /* d_{1, i} += d_{3, i - 5}, i in 5, 6, 7, 8 */ for (i = 5; i < 9; i++) fmpz_add(t[50 + i], t[50 + i], t[5 + i]); /* yi = d_{1, i} - a1 */ for (i = 0; i < 9; i++) { fmpz_sub(t[0], t[50 + i], t[1]); unity_zp_coeff_set_fmpz(f, i, t[0]); } /* a0 = d_{3, 4} - a1 */ fmpz_sub(t[0], t[14], t[1]); unity_zp_coeff_set_fmpz(f, 9, t[0]); /* y9 = a0 mod n */ } /* Computes f = g * g for p = 2^2. g must be reduced by F_4 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 3. Resulting f reduced by F_4 cyclotomic polynomial. */ void unity_zp_sqr4(unity_zp f, const unity_zp g, fmpz_t * t) { /* g = (x0, x1); f = (y0, y1); x0 = t[0]; x1 = t[1]; m1 = t[2]; m2 = t[3]; d1 = t[4]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); fmpz_sub(t[2], t[0], t[1]); /* m1 = x0 - x1 */ fmpz_add(t[3], t[0], t[1]); /* m2 = x0 + x1 */ fmpz_mul(t[4], t[2], t[3]); /* d1 = m1 * m2 */ fmpz_add(t[2], t[0], t[0]); /* m1 = x0 + x0 */ unity_zp_coeff_set_fmpz(f, 0, t[4]); /* y0 = d1 mod n */ fmpz_mul(t[4], t[2], t[1]); /* d1 = m1 * x1 */ unity_zp_coeff_set_fmpz(f, 1, t[4]); /* y1 = d1 mod n */ } /* Computes f = g * g for p = 2^3. g must be reduced by F_8 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 16. Resulting f reduced by F_8 cyclotomic polynomial. */ void unity_zp_sqr8(unity_zp f, const unity_zp g, fmpz_t * t) { /* g = (x0, x1, x2, x3); f = (y0, y1, y2, y3); x0 = t[0]; x1 = t[1]; x2 = t[2]; x3 = t[3]; m1 = t[4]; m2 = t[5]; m3 = t[6]; m4 = t[7]; m5 = t[8]; m6 = t[9]; m7 = t[10]; m8 = t[11]; d1 = t[12]; d2 = t[13]; d3 = t[14]; d4 = t[15]; d5 = t[16]; d6 = t[17]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[2], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[3], g->poly, 3, g->ctx); fmpz_sub(t[4], t[0], t[2]); /* m1 = x0 - x2 */ fmpz_add(t[5], t[0], t[2]); /* m2 = x0 + x2 */ fmpz_sub(t[6], t[1], t[3]); /* m3 = x1 - x3 */ fmpz_add(t[7], t[1], t[3]); /* m4 = x1 + x3 */ fmpz_add(t[8], t[0], t[0]); /* m5 = x0 + x0 */ fmpz_add(t[9], t[1], t[1]); /* m6 = x1 + x1 */ fmpz_add(t[10], t[4], t[6]); /* m7 = m1 + m3 */ fmpz_add(t[11], t[5], t[7]); /* m8 = m2 + m4 */ fmpz_mul(t[12], t[4], t[5]); /* d1 = m1 * m2 */ fmpz_mul(t[13], t[6], t[7]); /* d2 = m3 * m4 */ fmpz_mul(t[14], t[9], t[3]); /* d3 = m6 * x3 */ fmpz_mul(t[15], t[8], t[2]); /* d4 = m5 * x2 */ fmpz_add(t[5], t[2], t[3]); /* m2 = x2 + x3 */ fmpz_sub(t[16], t[12], t[14]); /* d5 = d1 - d3 */ unity_zp_coeff_set_fmpz(f, 0, t[16]); /* y0 = d5 mod n */ fmpz_add(t[17], t[13], t[15]); /* d6 = d2 + d4 */ unity_zp_coeff_set_fmpz(f, 2, t[17]); /* y2 = d6 mod n */ fmpz_mul(t[16], t[10], t[11]); /* d5 = m7 * m8 */ fmpz_add(t[17], t[12], t[13]); /* d6 = d1 + d2 */ fmpz_sub(t[13], t[16], t[17]); /* d2 = d5 - d6 */ unity_zp_coeff_set_fmpz(f, 1, t[13]); /* y1 = d2 mod n */ fmpz_add(t[4], t[8], t[9]); /* m1 = m5 + m6 */ fmpz_mul(t[12], t[4], t[5]); /* d1 = m1 * m2 */ fmpz_add(t[17], t[14], t[15]); /* d6 = d3 + d4 */ fmpz_sub(t[13], t[12], t[17]); /* d2 = d1 - d6 */ unity_zp_coeff_set_fmpz(f, 3, t[13]); /* y3 = d2 mod n */ } /* Computes f = g * g for p = 2^4. g must be reduced by F_16 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 44. Resulting f reduced by F_16 cyclotomic polynomial. */ void unity_zp_sqr16(unity_zp f, const unity_zp g, fmpz_t * t) { ulong i; /* g = (x0, x1, x2, x3, x4, x5, x6, x7); f = (y0, y1, y2, y3, y4, y5, y6, y7); x0 = t[30]; x1 = t[31]; x2 = t[32]; x3 = t[33]; x4 = t[34]; x5 = t[35]; x6 = t[37]; a0 = t[0]; a1 = t[1]; a2 = t[2]; a3 = t[3]; b0 = t[4]; b1 = t[5]; b2 = t[6]; b3 = t[7]; c0 = t[8]; c1 = t[9]; c2 = t[10]; c3 = t[11]; c4 = t[12]; c5 = t[13]; c6 = t[14]; d0 = t[38]; d1 = t[39]; d2 = t[40]; d3 = t[41]; d4 = t[42]; d5 = t[43]; d6 = t[44]; d7 = t[45]. */ /* set xi */ for (i = 0; i < 8; i++) fmpz_mod_poly_get_coeff_fmpz(t[30 + i], g->poly, i, g->ctx); fmpz_add(t[0], t[30], t[34]); /* a0 = x0 + x4 */ fmpz_add(t[1], t[31], t[35]); /* a1 = x1 + x5 */ fmpz_add(t[2], t[32], t[36]); /* a2 = x2 + x6 */ fmpz_add(t[3], t[33], t[37]); /* a3 = x3 + x7 */ fmpz_sub(t[4], t[30], t[34]); /* b0 = x0 - x4 */ fmpz_sub(t[5], t[31], t[35]); /* b1 = x1 - x5 */ fmpz_sub(t[6], t[32], t[36]); /* b2 = x2 - x6 */ fmpz_sub(t[7], t[33], t[37]); /* b3 = x3 - x7 */ /* apply auxiliary routine 2 with (a0, .. , a3) and (b0, .. , b3) store result in (c0, .. , c6) */ unity_zp_ar2(t); /* set d_i = c_i */ for (i = 8; i < 15; i++) fmpz_set(t[30 + i], t[i]); fmpz_add(t[0], t[30], t[30]); /* a0 = x0 + x0 */ fmpz_add(t[1], t[31], t[31]); /* a1 = x1 + x1 */ fmpz_add(t[2], t[32], t[32]); /* a2 = x2 + x2 */ fmpz_add(t[3], t[33], t[33]); /* a3 = x3 + x3 */ fmpz_set(t[4], t[34]); /* set b0 = x4 */ fmpz_set(t[5], t[35]); /* set b1 = x5 */ fmpz_set(t[6], t[36]); /* set b2 = x6 */ fmpz_set(t[7], t[37]); /* set b3 = x7 */ /* apply auxiliary routine 2 with (a0, .. , a3) and (b0, .. , b3) store result in (c0, .. , c6) */ unity_zp_ar2(t); fmpz_sub(t[16], t[38], t[12]); /* d7 = d0 - c4 */ unity_zp_coeff_set_fmpz(f, 0, t[16]); /* y0 = d7 mod n */ fmpz_sub(t[16], t[39], t[13]); /* d7 = d1 - c5 */ unity_zp_coeff_set_fmpz(f, 1, t[16]); /* y1 = d7 mod n */ fmpz_sub(t[16], t[40], t[14]); /* d7 = d2 - c6 */ unity_zp_coeff_set_fmpz(f, 2, t[16]); /* y2 = d7 mod n */ unity_zp_coeff_set_fmpz(f, 3, t[41]); /* y3 = d3 mod n */ fmpz_add(t[16], t[42], t[8]); /* d7 = d4 + c0 */ unity_zp_coeff_set_fmpz(f, 4, t[16]); /* y4 = d7 mod n */ fmpz_add(t[16], t[43], t[9]); /* d7 = d5 + c1 */ unity_zp_coeff_set_fmpz(f, 5, t[16]); /* y5 = d7 mod n */ fmpz_add(t[16], t[44], t[10]); /* d7 = d6 + c2 */ unity_zp_coeff_set_fmpz(f, 6, t[16]); /* y6 = d7 mod n */ unity_zp_coeff_set_fmpz(f, 7, t[11]); /* y7 = c3 mod n */ } /* Computes f = g * g for p = 3. g must be reduced by F_3 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 3. Resulting f reduced by F_3 cyclotomic polynomial. */ void unity_zp_sqr3(unity_zp f, const unity_zp g, fmpz_t * t) { /* g = (x0, x1); f = (y0, y1); x0 = t[0]; x1 = t[1]; m1 = t[2]; m2 = t[3]; d1 = t[4]. */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); fmpz_sub(t[2], t[0], t[1]); /* m1 = x0 - x1 */ fmpz_add(t[3], t[0], t[1]); /* m2 = x0 + x1 */ fmpz_mul(t[4], t[2], t[3]); /* d1 = m1 * m2 */ fmpz_add(t[3], t[2], t[0]); /* m2 = m1 + m0 */ unity_zp_coeff_set_fmpz(f, 0, t[4]); /* y0 = d1 mod n */ fmpz_mul(t[4], t[1], t[3]); /* d1 = x1 * m2 */ unity_zp_coeff_set_fmpz(f, 1, t[4]); /* y1 = d1 mod n */ } /* Computes f = g * g for p = 3. g must be reduced by F_3 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 30. Resulting f reduced by F_3 cyclotomic polynomial. */ void unity_zp_sqr9(unity_zp f, const unity_zp g, fmpz_t * t) { /* g = (x0, x1, x2, x3, x4, x5); f = (y0, y1, y2, y3, y4, y5); x0 = t[20]; x1 = t[21]; x2 = t[22]; x3 = t[23]; x4 = t[24]; x5 = t[25]; a0 = t[0]; a1 = t[1]; a2 = t[2]; b0 = t[3]; b1 = t[4]; b2 = t[5]; c0 = t[6]; c1 = t[7]; c2 = t[8]; c3 = t[9]; c4 = t[10]; d0 = t[26]; d1 = t[27]; d2 = t[28]; d3 = t[29]; d4 = t[30]. */ fmpz_mod_poly_get_coeff_fmpz(t[20], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[21], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[22], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[23], g->poly, 3, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[24], g->poly, 4, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[25], g->poly, 5, g->ctx); fmpz_sub(t[0], t[20], t[23]); /* a0 = x0 - x3 */ fmpz_sub(t[1], t[21], t[24]); /* a1 = x1 - x4 */ fmpz_sub(t[2], t[22], t[25]); /* a2 = x2 - x5 */ fmpz_add(t[3], t[20], t[23]); /* b0 = x0 + x3 */ fmpz_add(t[4], t[21], t[24]); /* b1 = x1 + x4 */ fmpz_add(t[5], t[22], t[25]); /* b2 = x2 + x5 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_set(t[26], t[6]); /* set d0 = c0 */ fmpz_set(t[27], t[7]); /* set d1 = c1 */ fmpz_set(t[28], t[8]); /* set d2 = c2 */ fmpz_set(t[29], t[9]); /* set d3 = c3 */ fmpz_set(t[30], t[10]); /* set d4 = c4 */ fmpz_add(t[3], t[20], t[0]); /* b0 = x0 + a0 */ fmpz_add(t[4], t[21], t[1]); /* b1 = x1 + a1 */ fmpz_add(t[5], t[22], t[2]); /* b2 = x2 + a2 */ fmpz_set(t[0], t[23]); /* set a0 = x3 */ fmpz_set(t[1], t[24]); /* set a1 = x4 */ fmpz_set(t[2], t[25]); /* set a2 = x5 */ /* apply auxiliary routine 2 with (a0, a1, a2) and (b0, b1, b2) store result in (c0, .. , c4) */ unity_zp_ar1(t); fmpz_sub(t[0], t[26], t[9]); /* a0 = d0 - c3 */ unity_zp_coeff_set_fmpz(f, 0, t[0]); /* y0 = a0 mod n */ fmpz_sub(t[0], t[27], t[10]); /* a0 = d1 - c4 */ unity_zp_coeff_set_fmpz(f, 1, t[0]); /* y1 = a0 mod n */ unity_zp_coeff_set_fmpz(f, 2, t[28]); /* y2 = d2 mod n */ fmpz_add(t[0], t[29], t[6]); /* a0 = d3 + c0 */ fmpz_sub(t[1], t[0], t[9]); /* a1 = a0 - c3 */ unity_zp_coeff_set_fmpz(f, 3, t[1]); /* y3 = a1 mod n */ fmpz_add(t[0], t[30], t[7]); /* a0 = d4 + c1 */ fmpz_sub(t[1], t[0], t[10]); /* a1 = a0 - c4 */ unity_zp_coeff_set_fmpz(f, 4, t[1]); /* y4 = a1 mod n */ unity_zp_coeff_set_fmpz(f, 5, t[8]); /* y5 = c2 mod n */ } /* Computes f = g * g for p = 5. g must be reduced by F_5 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 14. Resulting f reduced by F_5 cyclotomic polynomial. */ void unity_zp_sqr5(unity_zp f, const unity_zp g, fmpz_t * t) { /* g = (x0, x1, x2, x3); f = (y0, y1, y2, y3); x0 = t[0]; x1 = t[1]; x2 = t[2]; x3 = t[3]; m1 = t[4]; m2 = t[5]; m3 = t[6]; m4 = t[7]; m5 = t[8]; m6 = t[9]; m7 = t[10]; m8 = t[11]; d1 = t[12]; d2 = t[13]; d3 = t[14]; d4 = t[15]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[2], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[3], g->poly, 3, g->ctx); fmpz_sub(t[4], t[0], t[2]); /* m1 = x0 - x2 */ fmpz_add(t[5], t[0], t[2]); /* m2 = x0 + x2 */ fmpz_sub(t[6], t[2], t[1]); /* m3 = x2 - x1 */ fmpz_sub(t[7], t[0], t[3]); /* m4 = x0 - x3 */ fmpz_sub(t[8], t[1], t[0]); /* m5 = x1 - x0 */ fmpz_sub(t[9], t[2], t[3]); /* m6 = x2 - x3 */ fmpz_sub(t[10], t[1], t[3]); /* m7 = x1 - x3 */ fmpz_add(t[11], t[3], t[3]); /* m8 = x3 + x3 */ fmpz_mul(t[12], t[4], t[5]); /* d1 = m1 * m2 */ fmpz_mul(t[13], t[6], t[11]); /* d2 = m3 * m8 */ fmpz_add(t[14], t[12], t[13]); /* d3 = d1 + d2 */ unity_zp_coeff_set_fmpz(f, 0, t[14]); /* y0 = d3 mod n */ fmpz_add(t[11], t[8], t[10]); /* m8 = m5 + m7 */ fmpz_mul(t[13], t[7], t[11]); /* d2 = m4 * m8 */ fmpz_add(t[15], t[12], t[13]); /* d4 = d1 + d2 */ unity_zp_coeff_set_fmpz(f, 1, t[15]); /* y1 = d4 mod n */ fmpz_add(t[6], t[4], t[0]); /* m3 = m1 + x0 */ fmpz_mul(t[12], t[2], t[6]); /* d1 = x2 * m3 */ fmpz_sub(t[5], t[10], t[3]); /* m2 = m7 - x3 */ fmpz_mul(t[13], t[5], t[1]); /* d2 = m2 * x1 */ fmpz_add(t[14], t[12], t[13]); /* d3 = d1 + d2 */ unity_zp_coeff_set_fmpz(f, 2, t[14]); /* y2 = d3 mod n */ fmpz_add(t[10], t[9], t[9]); /* m7 = m6 + m6 */ fmpz_mul(t[13], t[10], t[8]); /* d2 = m7 * m5 */ fmpz_add(t[14], t[12], t[13]); /* d3 = d1 + d2 */ unity_zp_coeff_set_fmpz(f, 3, t[14]); /* y3 = d3 mod n */ } /* Computes f = g * g for p = 7. g must be reduced by F_7 cyclotomic polynomial. t is the memory for fmpz_t; size of t must be > 31. Resulting f reduced by F_7 cyclotomic polynomial. */ void unity_zp_sqr7(unity_zp f, const unity_zp g, fmpz_t * t) { /* g = (x0, ... , x5); f = (y0, ... , y5); x0 = t[0]; x1 = t[1]; x2 = t[2]; x3 = t[3]; x4 = t[4]; x5 = t[5]; m1 = t[6]; m2 = t[7]; ... ; m18 = t[23]; d1 = t[24]; ... ; d8 = t[31]. */ /* set xi */ fmpz_mod_poly_get_coeff_fmpz(t[0], g->poly, 0, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[1], g->poly, 1, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[2], g->poly, 2, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[3], g->poly, 3, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[4], g->poly, 4, g->ctx); fmpz_mod_poly_get_coeff_fmpz(t[5], g->poly, 5, g->ctx); fmpz_sub(t[6], t[0], t[1]); /* m1 = x0 - x1 */ fmpz_sub(t[7], t[1], t[2]); /* m2 = x1 - x2 */ fmpz_sub(t[8], t[2], t[3]); /* m3 = x2 - x3 */ fmpz_sub(t[9], t[3], t[4]); /* m4 = x3 - x4 */ fmpz_sub(t[10], t[5], t[4]); /* m5 = x5 - x4 */ fmpz_add(t[11], t[6], t[7]); /* m6 = x6 + x7 */ fmpz_add(t[12], t[7], t[8]); /* m7 = m2 + m3 */ fmpz_add(t[13], t[8], t[9]); /* m8 = m3 + m4 */ fmpz_sub(t[14], t[3], t[5]); /* m9 = x3 - x5 */ fmpz_add(t[15], t[8], t[11]); /* m10 = m3 + m6 */ fmpz_add(t[16], t[9], t[12]); /* m11 = m4 + m7 */ fmpz_add(t[18], t[11], t[13]); /* m13 = m6 + m8 */ fmpz_add(t[19], t[12], t[14]); /* m14 = m7 + m9 */ fmpz_add(t[21], t[0], t[1]); /* m16 = x0 + x1 */ fmpz_add(t[22], t[0], t[15]); /* m17 = m8 + m2 */ fmpz_mul(t[24], t[3], t[22]); /* d1 = x3 * m17 */ fmpz_sub(t[22], t[19], t[4]); /* m17 = m14 - m9 */ fmpz_add(t[23], t[19], t[4]); /* m18 = m14 + m9 */ fmpz_mul(t[25], t[22], t[23]); /* d2 = m17 * m18 */ fmpz_sub(t[22], t[13], t[7]); /* m17 = m8 - m2 */ fmpz_mul(t[26], t[16], t[22]); /* d3 = m11 * m17 */ fmpz_add(t[22], t[19], t[14]); /* m17 = m14 + m9 */ fmpz_mul(t[27], t[22], t[12]); /* d4 = m17 * m7 */ fmpz_add(t[22], t[1], t[1]); /* m17 = x1 + x1 */ fmpz_mul(t[28], t[22], t[11]); /* d5 = m17 * m6 */ fmpz_mul(t[29], t[6], t[21]); /* d6 = m1 * m16 */ fmpz_add(t[22], t[8], t[8]); /* m17 = m3 + m3 */ fmpz_add(t[7], t[0], t[18]); /* m2 = x0 + m13 */ fmpz_mul(t[30], t[22], t[10]); /* d7 = m17 * m5 */ fmpz_add(t[31], t[24], t[25]); /* d8 = d1 + d2 */ fmpz_add(t[24], t[31], t[26]); /* d1 = d8 + d5 */ unity_zp_coeff_set_fmpz(f, 3, t[24]); /* y3 = d1 mod n */ fmpz_add(t[31], t[26], t[27]); /* d8 = d3 + d4 */ fmpz_add(t[24], t[31], t[28]); /* d1 = d8 + d5 */ unity_zp_coeff_set_fmpz(f, 1, t[24]); /* y1 = d1 mod n */ fmpz_add(t[31], t[27], t[29]); /* d8 = d4 + d6 */ fmpz_add(t[24], t[31], t[30]); /* d1 = d8 + d7 */ unity_zp_coeff_set_fmpz(f, 0, t[24]); /* y0 = d1 mod n */ fmpz_add(t[22], t[12], t[19]); /* m17 = m7 + m14 */ fmpz_mul(t[24], t[14], t[22]); /* d1 = m9 * m17 */ fmpz_sub(t[22], t[13], t[5]); /* m17 = m8 - x5 */ fmpz_add(t[23], t[2], t[10]); /* m18 = x2 + m5 */ fmpz_mul(t[25], t[22], t[23]); /* d2 = m17 * m18 */ fmpz_mul(t[26], t[7], t[4]); /* d3 = m2 * x4 */ fmpz_add(t[22], t[8], t[13]); /* m17 = m3 + m8 */ fmpz_mul(t[27], t[22], t[9]); /* d4 = m17 * m4 */ fmpz_add(t[22], t[6], t[6]); /* m17 = m1 + m1 */ fmpz_mul(t[28], t[22], t[10]); /* d5 = m17 * m5 */ fmpz_sub(t[22], t[19], t[10]); /* m17 = m14 - m5 */ fmpz_mul(t[29], t[22], t[16]); /* d6 = m17 * m11 */ fmpz_add(t[22], t[2], t[2]); /* m17 = x2 + x2 */ fmpz_mul(t[30], t[22], t[15]); /* d7 = m17 * m10 */ fmpz_add(t[31], t[24], t[25]); /* d8 = d1 + d2 */ fmpz_add(t[24], t[31], t[26]); /* d1 = d8 + d3 */ unity_zp_coeff_set_fmpz(f, 4, t[24]); /* y4 = d1 mod n */ fmpz_add(t[31], t[26], t[27]); /* d8 = d3 + d4 */ fmpz_add(t[24], t[31], t[28]); /* d1 = d8 + d5 */ unity_zp_coeff_set_fmpz(f, 5, t[24]); /* y5 = d1 mod n */ fmpz_add(t[31], t[27], t[29]); /* d8 = d4 + d6 */ fmpz_add(t[24], t[31], t[30]); /* d1 = d8 + d7 */ unity_zp_coeff_set_fmpz(f, 2, t[24]); /* y2 = d1 mod n */ } flint-3.1.3/src/aprcl/unity_zp_swap.c000066400000000000000000000013171461254215100176040ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" #if FLINT_WANT_ASSERT # include "fmpz.h" # include "fmpz_mod.h" #endif void unity_zp_swap(unity_zp f, unity_zp g) { FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); fmpz_mod_poly_swap(f->poly, g->poly, f->ctx); } flint-3.1.3/src/aprcl/unity_zpq_add.c000066400000000000000000000016611461254215100175450ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" #if FLINT_WANT_ASSERT # include "fmpz.h" # include "fmpz_mod.h" #endif void unity_zpq_add(unity_zpq f, const unity_zpq g, const unity_zpq h) { ulong i; FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(h->ctx))); for (i = 0; i < f->p; i++) { fmpz_mod_poly_add(f->polys[i], g->polys[i], h->polys[i], f->ctx); } } flint-3.1.3/src/aprcl/unity_zpq_clear.c000066400000000000000000000012561461254215100201030ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zpq_clear(unity_zpq f) { slong i; for (i = 0; i < f->p; i++) { fmpz_mod_poly_clear(f->polys[i], f->ctx); } f->p = 0; f->q = 0; fmpz_mod_ctx_clear(f->ctx); flint_free(f->polys); } flint-3.1.3/src/aprcl/unity_zpq_coeff_add.c000066400000000000000000000027411461254215100207070ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zpq_coeff_add(unity_zpq f, slong i, slong j, const fmpz_t x) { if (i >= fmpz_mod_poly_length(f->polys[j], f->ctx)) { fmpz_mod_poly_set_coeff_fmpz(f->polys[j], i, x, f->ctx); return; } fmpz_add(f->polys[j]->coeffs + i, f->polys[j]->coeffs + i, x); if (fmpz_cmp(f->polys[j]->coeffs + i, fmpz_mod_ctx_modulus(f->ctx)) >= 0) fmpz_sub(f->polys[j]->coeffs + i, f->polys[j]->coeffs + i, fmpz_mod_ctx_modulus(f->ctx)); } void unity_zpq_coeff_add_ui(unity_zpq f, slong i, slong j, ulong x) { if (i >= fmpz_mod_poly_length(f->polys[j], f->ctx)) { fmpz_mod_poly_set_coeff_ui(f->polys[j], i, x, f->ctx); return; } fmpz_add_ui(f->polys[j]->coeffs + i, f->polys[j]->coeffs + i, x); if (fmpz_cmp(f->polys[j]->coeffs + i, fmpz_mod_ctx_modulus(f->ctx)) >= 0) fmpz_sub(f->polys[j]->coeffs + i, f->polys[j]->coeffs + i, fmpz_mod_ctx_modulus(f->ctx)); } flint-3.1.3/src/aprcl/unity_zpq_coeff_set.c000066400000000000000000000013011461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zpq_coeff_set_fmpz(unity_zpq f, slong i, slong j, const fmpz_t x) { fmpz_mod_poly_set_coeff_fmpz(f->polys[j], i, x, f->ctx); } void unity_zpq_coeff_set_ui(unity_zpq f, slong i, slong j, ulong x) { fmpz_mod_poly_set_coeff_ui(f->polys[j], i, x, f->ctx); } flint-3.1.3/src/aprcl/unity_zpq_copy.c000066400000000000000000000011351461254215100177630ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zpq_copy(unity_zpq f, const unity_zpq g) { slong i; for (i = 0; i < f->p; i++) { fmpz_mod_poly_set(f->polys[i], g->polys[i], g->ctx); } } flint-3.1.3/src/aprcl/unity_zpq_equal.c000066400000000000000000000015411461254215100201210ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" int unity_zpq_equal(const unity_zpq f, const unity_zpq g) { slong i; if (f->p != g->p) return 0; if (f->q != g->q) return 0; if (!fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))) return 0; for (i = 0; i < f->p; i++) if (!fmpz_mod_poly_equal(f->polys[i], g->polys[i], g->ctx)) return 0; return 1; } flint-3.1.3/src/aprcl/unity_zpq_gauss_sum.c000066400000000000000000000015451461254215100210240ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "aprcl.h" /* Computes gauss sum for character \chi corresponding (q, p). */ void unity_zpq_gauss_sum(unity_zpq f, ulong q, ulong p) { slong i, qinv, qpow, ppow, g; g = n_primitive_root_prime(q); qinv = n_preinvert_limb(q); qpow = 1; ppow = 0; for (i = 1; i < q; i++) { qpow = n_mulmod2_preinv(qpow, g, q, qinv); ppow = n_addmod(ppow, 1, p); unity_zpq_coeff_add_ui(f, qpow, ppow, 1); } } flint-3.1.3/src/aprcl/unity_zpq_gauss_sum_character_pow.c000066400000000000000000000023241461254215100237210ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "aprcl.h" /* Computes gauss sum for character \chi^n corresponding (q, p). */ void unity_zpq_gauss_sum_character_pow(unity_zpq f, ulong q, ulong p, ulong pow) { slong i, qinv, pinv, qpow, ppow, g; g = n_primitive_root_prime(q); qinv = n_preinvert_limb(q); pinv = n_preinvert_limb(p); qpow = 1; for (i = 1; i < q; i++) { qpow = n_mulmod2_preinv(qpow, g, q, qinv); ppow = n_mulmod2_preinv(i, pow, p, pinv); unity_zpq_coeff_add_ui(f, qpow, ppow, 1); } } /* Computes gauss sum for character \chi^n corresponding (q, p). */ void unity_zpq_gauss_sum_sigma_pow(unity_zpq f, ulong q, ulong p) { ulong n; n = fmpz_fdiv_ui(fmpz_mod_ctx_modulus(f->ctx), p); unity_zpq_gauss_sum_character_pow(f, q, p, n); } flint-3.1.3/src/aprcl/unity_zpq_init.c000066400000000000000000000014011461254215100177500ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zpq_init(unity_zpq f, ulong q, ulong p, const fmpz_t n) { slong i; f->p = p; f->q = q; fmpz_mod_ctx_init(f->ctx, n); f->polys = (fmpz_mod_poly_t *) flint_malloc(p * sizeof(fmpz_mod_poly_t)); for (i = 0; i < p; i++) { fmpz_mod_poly_init(f->polys[i], f->ctx); } } flint-3.1.3/src/aprcl/unity_zpq_mul.c000066400000000000000000000035151461254215100176120ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "aprcl.h" void unity_zpq_mul(unity_zpq f, const unity_zpq g, const unity_zpq h) { slong i, j, k; ulong p, q; fmpz_mod_poly_t temp; FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(h->ctx))); q = f->q; p = f->p; fmpz_mod_poly_init(temp, f->ctx); for (i = 0; i < p; i++) { fmpz_mod_poly_zero(f->polys[i], f->ctx); } for (i = 0; i < p; i++) { for (j = 0; j < p; j++) { ulong qpow; qpow = n_addmod(i, j, p); fmpz_mod_poly_mul(temp, g->polys[i], h->polys[j], f->ctx); if (temp->length == 0) continue; for (k = temp->length - 1; k >= q; k--) { fmpz_add(temp->coeffs + k - q, temp->coeffs + k - q, temp->coeffs + k); fmpz_set_ui(temp->coeffs + k, 0); fmpz_mod(temp->coeffs + k - q, temp->coeffs + k - q, fmpz_mod_ctx_modulus(f->ctx)); } _fmpz_mod_poly_normalise(temp); fmpz_mod_poly_add(f->polys[qpow], f->polys[qpow], temp, f->ctx); } } fmpz_mod_poly_clear(temp, f->ctx); } flint-3.1.3/src/aprcl/unity_zpq_mul_unity_p.c000066400000000000000000000015041461254215100213550ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "aprcl.h" void _unity_zpq_mul_unity_p(unity_zpq f) { slong i; for (i = f->p - 1; i > 0; i--) fmpz_mod_poly_swap(f->polys[i], f->polys[i - 1], f->ctx); } /* Computes unity_zpq * \zeta_p by swapping poly coeffs. */ void unity_zpq_mul_unity_p_pow(unity_zpq f, const unity_zpq g, slong k) { slong i; unity_zpq_copy(f, g); for (i = 0; i < k; i++) _unity_zpq_mul_unity_p(f); } flint-3.1.3/src/aprcl/unity_zpq_pow.c000066400000000000000000000031411461254215100176150ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "aprcl.h" void unity_zpq_pow(unity_zpq f, const unity_zpq g, const fmpz_t pow) { unity_zpq value; fmpz_t power, rem; unity_zpq_init(value, f->q, f->p, fmpz_mod_ctx_modulus(f->ctx)); fmpz_init_set(power, pow); fmpz_init(rem); unity_zpq_coeff_set_ui(f, 0, 0, 1); unity_zpq_copy(value, g); while (fmpz_is_zero(power) == 0) { unity_zpq temp_pow; fmpz_fdiv_r_2exp(rem, power, 1); if (fmpz_is_zero(rem) == 0) { unity_zpq temp; unity_zpq_init(temp, f->q, f->p, fmpz_mod_ctx_modulus(f->ctx)); unity_zpq_mul(temp, f, value); unity_zpq_swap(f, temp); unity_zpq_clear(temp); } unity_zpq_init(temp_pow, f->q, f->p, fmpz_mod_ctx_modulus(f->ctx)); unity_zpq_mul(temp_pow, value, value); unity_zpq_swap(value, temp_pow); fmpz_fdiv_q_2exp(power, power, 1); unity_zpq_clear(temp_pow); } fmpz_clear(power); fmpz_clear(rem); unity_zpq_clear(value); } void unity_zpq_pow_ui(unity_zpq f, const unity_zpq g, ulong pow) { fmpz_t p; fmpz_init_set_ui(p, pow); unity_zpq_pow(f, g, p); fmpz_clear(p); } flint-3.1.3/src/aprcl/unity_zpq_swap.c000066400000000000000000000010321461254215100177570ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "aprcl.h" void unity_zpq_swap(unity_zpq f, unity_zpq g) { fmpz_mod_poly_t *temp = f->polys; f->polys = g->polys; g->polys = temp; } flint-3.1.3/src/aprcl/utility.c000066400000000000000000000016011461254215100163700ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* Returns the index of divisor p on R factors list. */ int _aprcl_p_ind(const aprcl_config conf, ulong p) { int i; for (i = 0; i < conf->rs.num; i++) if (p == conf->rs.p[i]) return i; return -1; } /* Returns k such that p^k | q and p^{k + 1} not | q */ ulong aprcl_p_power_in_q(ulong q, ulong p) { ulong k, q_temp; k = 0; q_temp = q; while (q_temp % p == 0 && q_temp != 0) { k++; q_temp /= p; } return k; } flint-3.1.3/src/arb.h000066400000000000000000001056101461254215100143420ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_H #define ARB_H #ifdef ARB_INLINES_C #define ARB_INLINE #else #define ARB_INLINE static inline #endif #include "arf.h" #include "arb_types.h" #ifdef __cplusplus extern "C" { #endif #define arb_midref(x) (&(x)->mid) #define arb_radref(x) (&(x)->rad) #define ARB_IS_LAGOM(x) (ARF_IS_LAGOM(arb_midref(x)) && MAG_IS_LAGOM(arb_radref(x))) #define ARB_RND ARF_RND_DOWN ARB_INLINE void arb_init(arb_t x) { arf_init(arb_midref(x)); mag_init(arb_radref(x)); } void arb_clear(arb_t x); arb_ptr _arb_vec_init(slong n); void _arb_vec_clear(arb_ptr v, slong n); ARB_INLINE arf_ptr arb_mid_ptr(arb_t z) { return arb_midref(z); } ARB_INLINE mag_ptr arb_rad_ptr(arb_t z) { return arb_radref(z); } ARB_INLINE int arb_is_exact(const arb_t x) { return mag_is_zero(arb_radref(x)); } ARB_INLINE int arb_equal(const arb_t x, const arb_t y) { return arf_equal(arb_midref(x), arb_midref(y)) && mag_equal(arb_radref(x), arb_radref(y)); } ARB_INLINE int arb_equal_si(const arb_t x, slong y) { return arf_equal_si(arb_midref(x), y) && mag_is_zero(arb_radref(x)); } /* implementations are in arb/richcmp.c */ int arb_eq(const arb_t x, const arb_t y); int arb_ne(const arb_t x, const arb_t y); int arb_lt(const arb_t x, const arb_t y); int arb_le(const arb_t x, const arb_t y); int arb_gt(const arb_t x, const arb_t y); int arb_ge(const arb_t x, const arb_t y); void arb_zero(arb_t x); ARB_INLINE int arb_is_zero(const arb_t x) { return arf_is_zero(arb_midref(x)) && mag_is_zero(arb_radref(x)); } ARB_INLINE void arb_pos_inf(arb_t x) { arf_pos_inf(arb_midref(x)); mag_zero(arb_radref(x)); } ARB_INLINE void arb_neg_inf(arb_t x) { arf_neg_inf(arb_midref(x)); mag_zero(arb_radref(x)); } ARB_INLINE void arb_zero_pm_inf(arb_t x) { arf_zero(arb_midref(x)); mag_inf(arb_radref(x)); } ARB_INLINE void arb_zero_pm_one(arb_t x) { arf_zero(arb_midref(x)); mag_one(arb_radref(x)); } ARB_INLINE void arb_unit_interval(arb_t x) { arf_one(arb_midref(x)); mag_one(arb_radref(x)); ARF_EXP(arb_midref(x))--; MAG_EXP(arb_radref(x))--; } void arb_indeterminate(arb_t x); int arb_is_finite(const arb_t x); void arb_set(arb_t x, const arb_t y); ARB_INLINE void arb_swap(arb_t x, arb_t y) { FLINT_SWAP(arb_struct, *x, *y); } void arb_set_round(arb_t z, const arb_t x, slong prec); void arb_trim(arb_t y, const arb_t x); void arb_neg(arb_t y, const arb_t x); void arb_neg_round(arb_t x, const arb_t y, slong prec); void arb_abs(arb_t y, const arb_t x); void arb_nonnegative_abs(arb_t y, const arb_t x); void arb_sgn(arb_t res, const arb_t x); int arb_sgn_nonzero(const arb_t x); void _arb_digits_round_inplace(char * s, flint_bitcnt_t * shift, fmpz_t error, slong n, arf_rnd_t rnd); int arb_set_str(arb_t res, const char * inp, slong prec); #define ARB_STR_MORE UWORD(1) #define ARB_STR_NO_RADIUS UWORD(2) #define ARB_STR_CONDENSE UWORD(16) char * arb_get_str(const arb_t x, slong n, ulong flags); ARB_INLINE void arb_set_arf(arb_t x, const arf_t y) { arf_set(arb_midref(x), y); mag_zero(arb_radref(x)); } void arb_set_si(arb_t x, slong y); void arb_set_ui(arb_t x, ulong y); void arb_set_d(arb_t x, double y); void arb_set_fmpz(arb_t x, const fmpz_t y); ARB_INLINE void arb_set_fmpz_2exp(arb_t x, const fmpz_t y, const fmpz_t exp) { arf_set_fmpz_2exp(arb_midref(x), y, exp); mag_zero(arb_radref(x)); } void arb_set_round_fmpz_2exp(arb_t y, const fmpz_t x, const fmpz_t exp, slong prec); void arb_set_round_fmpz(arb_t y, const fmpz_t x, slong prec); ARB_INLINE int arb_is_one(const arb_t f) { return arf_is_one(arb_midref(f)) && mag_is_zero(arb_radref(f)); } void arb_one(arb_t f); #ifdef FLINT_HAVE_FILE void arb_fprint(FILE * file, const arb_t x); void arb_fprintd(FILE * file, const arb_t x, slong digits); void arb_fprintn(FILE * file, const arb_t x, slong digits, ulong flags); #endif void arb_print(const arb_t x); void arb_printd(const arb_t x, slong digits); void arb_printn(const arb_t x, slong digits, ulong flags); void _arb_vec_printn(arb_srcptr vec, slong len, slong ndigits, ulong flags); void _arb_vec_printd(arb_srcptr vec, slong len, slong ndigits); void arb_mul_2exp_si(arb_t y, const arb_t x, slong e); ARB_INLINE void arb_mul_2exp_fmpz(arb_t y, const arb_t x, const fmpz_t e) { arf_mul_2exp_fmpz(arb_midref(y), arb_midref(x), e); mag_mul_2exp_fmpz(arb_radref(y), arb_radref(x), e); } ARB_INLINE int arb_is_int(const arb_t x) { return mag_is_zero(arb_radref(x)) && arf_is_int(arb_midref(x)); } ARB_INLINE int arb_is_int_2exp_si(const arb_t x, slong e) { return mag_is_zero(arb_radref(x)) && arf_is_int_2exp_si(arb_midref(x), e); } /* implementations are in arb/richcmp.c */ int arb_contains_zero(const arb_t x); int arb_is_nonzero(const arb_t x); int arb_is_positive(const arb_t x); int arb_is_nonnegative(const arb_t x); int arb_is_negative(const arb_t x); int arb_is_nonpositive(const arb_t x); int arb_contains_negative(const arb_t x); int arb_contains_nonpositive(const arb_t x); int arb_contains_positive(const arb_t x); int arb_contains_nonnegative(const arb_t x); void arb_get_mag_lower(mag_t z, const arb_t x); void arb_get_mag_lower_nonnegative(mag_t z, const arb_t x); ARB_INLINE void arb_get_mag(mag_t z, const arb_t x) { mag_t t; mag_init_set_arf(t, arb_midref(x)); mag_add(z, t, arb_radref(x)); mag_clear(t); } ARB_INLINE void arb_get_mid_arb(arb_t z, const arb_t x) { arf_set(arb_midref(z), arb_midref(x)); mag_zero(arb_radref(z)); } ARB_INLINE void arb_get_rad_arb(arb_t z, const arb_t x) { arf_set_mag(arb_midref(z), arb_radref(x)); mag_zero(arb_radref(z)); } void arb_get_abs_ubound_arf(arf_t u, const arb_t x, slong prec); void arb_get_abs_lbound_arf(arf_t u, const arb_t x, slong prec); void arb_get_ubound_arf(arf_t u, const arb_t x, slong prec); void arb_get_lbound_arf(arf_t u, const arb_t x, slong prec); void arb_nonnegative_part(arb_t res, const arb_t x); slong arb_rel_error_bits(const arb_t x); ARB_INLINE slong arb_rel_accuracy_bits(const arb_t x) { return -arb_rel_error_bits(x); } slong arb_rel_one_accuracy_bits(const arb_t x); ARB_INLINE slong arb_bits(const arb_t x) { return arf_bits(arb_midref(x)); } void arb_randtest_exact(arb_t x, flint_rand_t state, slong prec, slong mag_bits); void arb_randtest_wide(arb_t x, flint_rand_t state, slong prec, slong mag_bits); void arb_randtest_precise(arb_t x, flint_rand_t state, slong prec, slong mag_bits); void arb_randtest_positive(arb_t x, flint_rand_t state, slong prec, slong mag_bits); void arb_randtest(arb_t x, flint_rand_t state, slong prec, slong mag_bits); void arb_randtest_special(arb_t x, flint_rand_t state, slong prec, slong mag_bits); void arb_urandom(arb_t x, flint_rand_t state, slong prec); void arb_add_error_arf(arb_t x, const arf_t err); void arb_add_error_2exp_si(arb_t x, slong err); void arb_add_error_2exp_fmpz(arb_t x, const fmpz_t err); void arb_add_error(arb_t x, const arb_t error); ARB_INLINE void arb_add_error_mag(arb_t x, const mag_t err) { mag_add(arb_radref(x), arb_radref(x), err); } int arb_contains_arf(const arb_t x, const arf_t y); int arb_contains_fmpq(const arb_t x, const fmpq_t y); int arb_contains_fmpz(const arb_t x, const fmpz_t y); int arb_contains_si(const arb_t x, slong y); #ifdef __MPFR_H int arb_contains_mpfr(const arb_t x, const mpfr_t y); #endif int arb_overlaps(const arb_t x, const arb_t y); int arb_contains(const arb_t x, const arb_t y); int arb_contains_interior(const arb_t x, const arb_t y); int arb_contains_int(const arb_t x); void arb_get_interval_fmpz_2exp(fmpz_t a, fmpz_t b, fmpz_t exp, const arb_t x); int arb_get_unique_fmpz(fmpz_t z, const arb_t x); void arb_get_fmpz_mid_rad_10exp(fmpz_t mid, fmpz_t rad, fmpz_t exp, const arb_t x, slong n); void arb_floor(arb_t z, const arb_t x, slong prec); void arb_ceil(arb_t z, const arb_t x, slong prec); void arb_nint(arb_t res, const arb_t x, slong prec); void arb_trunc(arb_t res, const arb_t x, slong prec); void arb_set_interval_arf(arb_t x, const arf_t a, const arf_t b, slong prec); #ifdef __MPFR_H void arb_set_interval_mpfr(arb_t x, const mpfr_t a, const mpfr_t b, slong prec); #endif void arb_get_interval_arf(arf_t a, arf_t b, const arb_t x, slong prec); #ifdef __MPFR_H void arb_get_interval_mpfr(mpfr_t a, mpfr_t b, const arb_t x); #endif void arb_set_interval_mag(arb_t res, const mag_t a, const mag_t b, slong prec); void arb_set_interval_neg_pos_mag(arb_t res, const mag_t a, const mag_t b, slong prec); void arb_union(arb_t z, const arb_t x, const arb_t y, slong prec); int arb_intersection(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_get_rand_fmpq(fmpq_t q, flint_rand_t state, const arb_t x, slong bits); void arb_min(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_max(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_minmax(arb_t z1, arb_t z2, const arb_t x, const arb_t y, slong prec); int arb_can_round_arf(const arb_t x, slong prec, arf_rnd_t rnd); #ifdef __MPFR_H int arb_can_round_mpfr(const arb_t x, slong prec, mpfr_rnd_t rnd); #endif void arb_add(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_add_arf(arb_t z, const arb_t x, const arf_t y, slong prec); void arb_add_ui(arb_t z, const arb_t x, ulong y, slong prec); void arb_add_si(arb_t z, const arb_t x, slong y, slong prec); void arb_add_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec); void arb_add_fmpz_2exp(arb_t z, const arb_t x, const fmpz_t man, const fmpz_t exp, slong prec); void arb_sub(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_sub_arf(arb_t z, const arb_t x, const arf_t y, slong prec); void arb_sub_ui(arb_t z, const arb_t x, ulong y, slong prec); void arb_sub_si(arb_t z, const arb_t x, slong y, slong prec); void arb_sub_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec); void arb_mul(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_mul_arf(arb_t z, const arb_t x, const arf_t y, slong prec); void arb_mul_si(arb_t z, const arb_t x, slong y, slong prec); void arb_mul_ui(arb_t z, const arb_t x, ulong y, slong prec); void arb_mul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec); void arb_addmul(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_addmul_arf(arb_t z, const arb_t x, const arf_t y, slong prec); void arb_addmul_si(arb_t z, const arb_t x, slong y, slong prec); void arb_addmul_ui(arb_t z, const arb_t x, ulong y, slong prec); void arb_addmul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec); void arb_submul(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_submul_arf(arb_t z, const arb_t x, const arf_t y, slong prec); void arb_submul_si(arb_t z, const arb_t x, slong y, slong prec); void arb_submul_ui(arb_t z, const arb_t x, ulong y, slong prec); void arb_submul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec); void arb_fma(arb_t res, const arb_t x, const arb_t y, const arb_t z, slong prec); void arb_fma_arf(arb_t res, const arb_t x, const arf_t y, const arb_t z, slong prec); void arb_fma_si(arb_t res, const arb_t x, slong y, const arb_t z, slong prec); void arb_fma_ui(arb_t res, const arb_t x, ulong y, const arb_t z, slong prec); void arb_fma_fmpz(arb_t res, const arb_t x, const fmpz_t y, const arb_t z, slong prec); void arb_dot_simple(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec); void arb_dot_precise(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec); void arb_dot(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec); void arb_approx_dot(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec); void arb_dot_ui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec); void arb_dot_si(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const slong * y, slong ystep, slong len, slong prec); void arb_dot_uiui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec); void arb_dot_siui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec); void arb_dot_fmpz(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const fmpz * y, slong ystep, slong len, slong prec); void arb_div(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_div_arf(arb_t z, const arb_t x, const arf_t y, slong prec); void arb_div_si(arb_t z, const arb_t x, slong y, slong prec); void arb_div_ui(arb_t z, const arb_t x, ulong y, slong prec); void arb_div_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec); void arb_fmpz_div_fmpz(arb_t z, const fmpz_t x, const fmpz_t y, slong prec); void arb_ui_div(arb_t z, ulong x, const arb_t y, slong prec); void arb_div_arf_newton(arb_t res, const arb_t x, const arf_t y, slong prec); void arb_div_newton(arb_t res, const arb_t x, const arb_t y, slong prec); void arb_fmpz_divapprox(fmpz_t res, const fmpz_t x, const fmpz_t y); ARB_INLINE void arb_inv(arb_t y, const arb_t x, slong prec) { arb_ui_div(y, 1, x, prec); } ARB_INLINE void arb_set_fmpq(arb_t y, const fmpq_t x, slong prec) { arb_fmpz_div_fmpz(y, fmpq_numref(x), fmpq_denref(x), prec); } void arb_sqrt(arb_t z, const arb_t x, slong prec); void arb_sqrt_arf(arb_t z, const arf_t x, slong prec); void arb_sqrt_fmpz(arb_t z, const fmpz_t x, slong prec); void arb_sqrt_ui(arb_t z, ulong x, slong prec); void arb_sqrtpos(arb_t z, const arb_t x, slong prec); void arb_hypot(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_rsqrt(arb_t z, const arb_t x, slong prec); void arb_rsqrt_ui(arb_t z, ulong x, slong prec); void arb_sqrt1pm1(arb_t r, const arb_t z, slong prec); void arb_rsqrt_arf_newton(arb_t res, const arf_t x, slong prec); void arb_sqrt_arf_newton(arb_t res, const arf_t x, slong prec); void arb_sqrt_newton(arb_t z, const arb_t x, slong prec); void arb_pow_fmpz_binexp(arb_t y, const arb_t b, const fmpz_t e, slong prec); void arb_pow_fmpz(arb_t y, const arb_t b, const fmpz_t e, slong prec); void arb_pow_ui(arb_t y, const arb_t b, ulong e, slong prec); void arb_ui_pow_ui(arb_t y, ulong b, ulong e, slong prec); void arb_si_pow_ui(arb_t y, slong b, ulong e, slong prec); void arb_pow_fmpq(arb_t y, const arb_t x, const fmpq_t a, slong prec); void arb_div_2expm1_ui(arb_t z, const arb_t x, ulong n, slong prec); void arb_pow(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_root_ui(arb_t z, const arb_t x, ulong k, slong prec); void arb_root(arb_t z, const arb_t x, ulong k, slong prec); /* back compat */ void arb_log(arb_t z, const arb_t x, slong prec); void arb_log_arf(arb_t z, const arf_t x, slong prec); void arb_log_ui(arb_t z, ulong x, slong prec); void arb_log_fmpz(arb_t z, const fmpz_t x, slong prec); void arb_log1p(arb_t r, const arb_t z, slong prec); void arb_log_base_ui(arb_t res, const arb_t x, ulong b, slong prec); void arb_log_hypot(arb_t res, const arb_t x, const arb_t y, slong prec); void arb_exp(arb_t z, const arb_t x, slong prec); void arb_expm1(arb_t z, const arb_t x, slong prec); void arb_exp_invexp(arb_t z, arb_t w, const arb_t x, slong prec); void arb_sin(arb_t s, const arb_t x, slong prec); void arb_cos(arb_t c, const arb_t x, slong prec); void arb_sin_cos(arb_t s, arb_t c, const arb_t x, slong prec); void arb_sin_pi(arb_t s, const arb_t x, slong prec); void arb_cos_pi(arb_t c, const arb_t x, slong prec); void arb_sin_cos_pi(arb_t s, arb_t c, const arb_t x, slong prec); void arb_tan(arb_t y, const arb_t x, slong prec); void arb_cot(arb_t y, const arb_t x, slong prec); void arb_tan_pi(arb_t y, const arb_t x, slong prec); void arb_cot_pi(arb_t y, const arb_t x, slong prec); void _arb_sin_pi_fmpq_algebraic(arb_t s, ulong p, ulong q, slong prec); void _arb_cos_pi_fmpq_algebraic(arb_t c, ulong p, ulong q, slong prec); void _arb_sin_cos_pi_fmpq_algebraic(arb_t s, arb_t c, ulong p, ulong q, slong prec); void arb_sin_cos_pi_fmpq(arb_t s, arb_t c, const fmpq_t x, slong prec); void arb_sin_pi_fmpq(arb_t s, const fmpq_t x, slong prec); void arb_cos_pi_fmpq(arb_t c, const fmpq_t x, slong prec); void arb_sinc(arb_t z, const arb_t x, slong prec); void arb_sinc_pi(arb_t z, const arb_t x, slong prec); void arb_sinh(arb_t z, const arb_t x, slong prec); void arb_cosh(arb_t z, const arb_t x, slong prec); void arb_sinh_cosh(arb_t s, arb_t c, const arb_t x, slong prec); void arb_tanh(arb_t y, const arb_t x, slong prec); void arb_coth(arb_t y, const arb_t x, slong prec); void arb_atan_arf(arb_t z, const arf_t x, slong prec); void arb_atan(arb_t z, const arb_t x, slong prec); void arb_atan2(arb_t z, const arb_t b, const arb_t a, slong prec); void arb_asin(arb_t z, const arb_t x, slong prec); void arb_acos(arb_t z, const arb_t x, slong prec); void arb_atanh(arb_t z, const arb_t x, slong prec); void arb_asinh(arb_t z, const arb_t x, slong prec); void arb_acosh(arb_t z, const arb_t x, slong prec); void arb_sec(arb_t res, const arb_t x, slong prec); void arb_csc(arb_t res, const arb_t x, slong prec); void arb_csc_pi(arb_t res, const arb_t x, slong prec); void arb_sech(arb_t res, const arb_t x, slong prec); void arb_csch(arb_t res, const arb_t x, slong prec); void arb_fac_ui(arb_t z, ulong n, slong prec); void arb_doublefac_ui(arb_t z, ulong n, slong prec); void arb_bin_ui(arb_t z, const arb_t n, ulong k, slong prec); void arb_bin_uiui(arb_t z, ulong n, ulong k, slong prec); void arb_fib_fmpz(arb_t z, const fmpz_t n, slong prec); void arb_fib_ui(arb_t z, ulong n, slong prec); void arb_const_pi(arb_t z, slong prec); void arb_const_sqrt_pi(arb_t z, slong prec); void arb_const_log_sqrt2pi(arb_t z, slong prec); void arb_const_log2(arb_t z, slong prec); void arb_const_log10(arb_t z, slong prec); void arb_const_euler(arb_t z, slong prec); void arb_const_catalan(arb_t z, slong prec); void arb_const_e(arb_t z, slong prec); void arb_const_khinchin(arb_t z, slong prec); void arb_const_glaisher(arb_t z, slong prec); void arb_const_reciprocal_fibonacci(arb_t res, slong prec); void arb_agm(arb_t z, const arb_t x, const arb_t y, slong prec); void arb_lgamma(arb_t z, const arb_t x, slong prec); void arb_rgamma(arb_t z, const arb_t x, slong prec); void arb_gamma(arb_t z, const arb_t x, slong prec); void arb_gamma_fmpq(arb_t z, const fmpq_t x, slong prec); void arb_gamma_fmpz(arb_t z, const fmpz_t x, slong prec); void arb_digamma(arb_t y, const arb_t x, slong prec); void arb_zeta(arb_t z, const arb_t s, slong prec); void arb_hurwitz_zeta(arb_t z, const arb_t s, const arb_t a, slong prec); void arb_rising_ui(arb_t z, const arb_t x, ulong n, slong prec); void arb_rising_fmpq_ui(arb_t y, const fmpq_t x, ulong n, slong prec); void arb_rising(arb_t z, const arb_t x, const arb_t n, slong prec); void arb_rising2_ui(arb_t u, arb_t v, const arb_t x, ulong n, slong prec); void arb_log_ui_from_prev(arb_t s, ulong k, arb_t log_prev, ulong prev, slong prec); void arb_const_apery(arb_t s, slong prec); void arb_zeta_ui_asymp(arb_t x, ulong s, slong prec); void arb_zeta_ui_borwein_bsplit(arb_t x, ulong s, slong prec); void arb_zeta_ui_euler_product(arb_t z, ulong s, slong prec); void arb_zeta_ui_bernoulli(arb_t x, ulong n, slong prec); void arb_zeta_ui_vec_borwein(arb_ptr z, ulong start, slong num, ulong step, slong prec); void arb_zeta_ui(arb_t x, ulong n, slong prec); void arb_zeta_ui_vec_even(arb_ptr x, ulong start, slong num, slong prec); void arb_zeta_ui_vec_odd(arb_ptr x, ulong start, slong num, slong prec); void arb_zeta_ui_vec(arb_ptr x, ulong start, slong num, slong prec); void arb_bernoulli_ui(arb_t b, ulong n, slong prec); void arb_bernoulli_ui_zeta(arb_t b, ulong n, slong prec); void arb_bernoulli_fmpz(arb_t b, const fmpz_t n, slong prec); void arb_bernoulli_poly_ui(arb_t res, ulong n, const arb_t x, slong prec); void arb_polylog(arb_t w, const arb_t s, const arb_t z, slong prec); void arb_polylog_si(arb_t w, slong s, const arb_t z, slong prec); void arb_chebyshev_t_ui(arb_t a, ulong n, const arb_t x, slong prec); void arb_chebyshev_t2_ui(arb_t a, arb_t b, ulong n, const arb_t x, slong prec); void arb_chebyshev_u_ui(arb_t a, ulong n, const arb_t x, slong prec); void arb_chebyshev_u2_ui(arb_t a, arb_t b, ulong n, const arb_t x, slong prec); void arb_power_sum_vec(arb_ptr res, const arb_t a, const arb_t b, slong len, slong prec); void arb_bell_sum_taylor(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, slong prec); void arb_bell_sum_bsplit(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, slong prec); void arb_bell_fmpz(arb_t res, const fmpz_t n, slong prec); void arb_bell_ui(arb_t res, ulong n, slong prec); void arb_euler_number_fmpz(arb_t res, const fmpz_t n, slong prec); void arb_euler_number_ui(arb_t res, ulong n, slong prec); void arb_fmpz_euler_number_ui_multi_mod(fmpz_t res, ulong n, double alpha); void arb_fmpz_euler_number_ui(fmpz_t res, ulong n); void arb_partitions_fmpz(arb_t res, const fmpz_t n, slong prec); void arb_partitions_ui(arb_t res, ulong n, slong prec); void arb_primorial_nth_ui(arb_t res, ulong n, slong prec); void arb_primorial_ui(arb_t res, ulong n, slong prec); void arb_lambertw(arb_t res, const arb_t x, int flags, slong prec); ARB_INLINE void arb_sqr(arb_t res, const arb_t val, slong prec) { arb_mul(res, val, val, prec); } #define ARB_DEF_CACHED_CONSTANT(name, comp_func) \ FLINT_TLS_PREFIX slong name ## _cached_prec = 0; \ FLINT_TLS_PREFIX arb_t name ## _cached_value; \ void name ## _cleanup(void) \ { \ arb_clear(name ## _cached_value); \ name ## _cached_prec = 0; \ } \ void name(arb_t x, slong prec) \ { \ if (name ## _cached_prec < prec) \ { \ if (name ## _cached_prec == 0) \ { \ arb_init(name ## _cached_value); \ flint_register_cleanup_function(name ## _cleanup); \ } \ comp_func(name ## _cached_value, prec + 32); \ name ## _cached_prec = prec; \ } \ arb_set_round(x, name ## _cached_value, prec); \ } /* vector functions */ ARB_INLINE arb_ptr _arb_vec_entry_ptr(arb_ptr vec, slong i) { return vec + i; } ARB_INLINE void _arb_vec_zero(arb_ptr A, slong n) { slong i; for (i = 0; i < n; i++) arb_zero(A + i); } ARB_INLINE int _arb_vec_is_zero(arb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) if (!arb_is_zero(vec + i)) return 0; return 1; } ARB_INLINE int _arb_vec_is_finite(arb_srcptr x, slong len) { slong i; for (i = 0; i < len; i++) if (!arb_is_finite(x + i)) return 0; return 1; } ARB_INLINE int _arb_vec_equal(arb_srcptr vec1, arb_srcptr vec2, slong len) { slong i; for (i = 0; i < len; i++) { if (!arb_equal(vec1 + i, vec2 + i)) return 0; } return 1; } ARB_INLINE int _arb_vec_overlaps(arb_srcptr vec1, arb_srcptr vec2, slong len) { slong i; for (i = 0; i < len; i++) { if (!arb_overlaps(vec1 + i, vec2 + i)) return 0; } return 1; } ARB_INLINE int _arb_vec_contains(arb_srcptr vec1, arb_srcptr vec2, slong len) { slong i; for (i = 0; i < len; i++) { if (!arb_contains(vec1 + i, vec2 + i)) return 0; } return 1; } ARB_INLINE void _arb_vec_set(arb_ptr res, arb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) arb_set(res + i, vec + i); } ARB_INLINE void _arb_vec_set_round(arb_ptr res, arb_srcptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) arb_set_round(res + i, vec + i, prec); } ARB_INLINE void _arb_vec_swap(arb_ptr res, arb_ptr vec, slong len) { slong i; for (i = 0; i < len; i++) arb_swap(res + i, vec + i); } ARB_INLINE void _arb_vec_neg(arb_ptr B, arb_srcptr A, slong n) { slong i; for (i = 0; i < n; i++) arb_neg(B + i, A + i); } ARB_INLINE void _arb_vec_sub(arb_ptr C, arb_srcptr A, arb_srcptr B, slong n, slong prec) { slong i; for (i = 0; i < n; i++) arb_sub(C + i, A + i, B + i, prec); } ARB_INLINE void _arb_vec_add(arb_ptr C, arb_srcptr A, arb_srcptr B, slong n, slong prec) { slong i; for (i = 0; i < n; i++) arb_add(C + i, A + i, B + i, prec); } ARB_INLINE void _arb_vec_scalar_mul(arb_ptr res, arb_srcptr vec, slong len, const arb_t c, slong prec) { slong i; for (i = 0; i < len; i++) arb_mul(res + i, vec + i, c, prec); } ARB_INLINE void _arb_vec_scalar_div(arb_ptr res, arb_srcptr vec, slong len, const arb_t c, slong prec) { slong i; for (i = 0; i < len; i++) arb_div(res + i, vec + i, c, prec); } ARB_INLINE void _arb_vec_scalar_mul_fmpz(arb_ptr res, arb_srcptr vec, slong len, const fmpz_t c, slong prec) { slong i; arf_t t; arf_init(t); arf_set_fmpz(t, c); for (i = 0; i < len; i++) arb_mul_arf(res + i, vec + i, t, prec); arf_clear(t); } ARB_INLINE void _arb_vec_scalar_mul_2exp_si(arb_ptr res, arb_srcptr src, slong len, slong c) { slong i; for (i = 0; i < len; i++) arb_mul_2exp_si(res + i, src + i, c); } ARB_INLINE void _arb_vec_scalar_addmul(arb_ptr res, arb_srcptr vec, slong len, const arb_t c, slong prec) { slong i; for (i = 0; i < len; i++) arb_addmul(res + i, vec + i, c, prec); } void _arb_vec_get_mag(mag_t bound, arb_srcptr vec, slong len); ARB_INLINE slong _arb_vec_bits(arb_srcptr x, slong len) { slong i, b, c; b = 0; for (i = 0; i < len; i++) { c = arb_bits(x + i); b = FLINT_MAX(b, c); } return b; } void _arb_vec_set_powers(arb_ptr xs, const arb_t x, slong len, slong prec); ARB_INLINE void _arb_vec_add_error_arf_vec(arb_ptr res, arf_srcptr err, slong len) { slong i; for (i = 0; i < len; i++) arb_add_error_arf(res + i, err + i); } ARB_INLINE void _arb_vec_add_error_mag_vec(arb_ptr res, mag_srcptr err, slong len) { slong i; for (i = 0; i < len; i++) mag_add(arb_radref(res + i), arb_radref(res + i), err + i); } ARB_INLINE void _arb_vec_indeterminate(arb_ptr vec, slong len) { slong i; for (i = 0; i < len; i++) arb_indeterminate(vec + i); } ARB_INLINE void _arb_vec_trim(arb_ptr res, arb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) arb_trim(res + i, vec + i); } ARB_INLINE int _arb_vec_get_unique_fmpz_vec(fmpz * res, arb_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) if (!arb_get_unique_fmpz(res + i, vec + i)) return 0; return 1; } /* arctangent implementation */ #define ARB_ATAN_TAB1_BITS 8 #define ARB_ATAN_TAB1_PREC 512 #define ARB_ATAN_TAB1_LIMBS (ARB_ATAN_TAB1_PREC / FLINT_BITS) #define ARB_ATAN_TAB21_BITS 5 #define ARB_ATAN_TAB22_BITS 5 #define ARB_ATAN_TAB2_PREC 4608 #define ARB_ATAN_TAB2_LIMBS (ARB_ATAN_TAB2_PREC / FLINT_BITS) FLINT_DLL extern const mp_limb_t arb_atan_tab1[1 << ARB_ATAN_TAB1_BITS][ARB_ATAN_TAB1_LIMBS]; FLINT_DLL extern const mp_limb_t arb_atan_tab21[1 << ARB_ATAN_TAB21_BITS][ARB_ATAN_TAB2_LIMBS]; FLINT_DLL extern const mp_limb_t arb_atan_tab22[1 << ARB_ATAN_TAB22_BITS][ARB_ATAN_TAB2_LIMBS]; FLINT_DLL extern const mp_limb_t arb_atan_pi2_minus_one[ARB_ATAN_TAB2_LIMBS]; void _arb_atan_taylor_naive(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int alternating); void _arb_atan_taylor_rs(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int alternating); #define ARB_ATAN_NEWTON_PREC 3400 void arb_atan_newton(arb_t res, const arb_t x, slong prec); void arb_atan_arf_newton(arb_t res, const arf_t x, slong prec); /* logarithm implementation */ #define ARB_LOG_TAB11_BITS 7 #define ARB_LOG_TAB12_BITS 7 #define ARB_LOG_TAB1_PREC 512 #define ARB_LOG_TAB1_LIMBS (ARB_LOG_TAB1_PREC / FLINT_BITS) #define ARB_LOG_TAB21_BITS 5 #define ARB_LOG_TAB22_BITS 5 #define ARB_LOG_TAB2_PREC 4608 #define ARB_LOG_TAB2_LIMBS (ARB_LOG_TAB2_PREC / FLINT_BITS) FLINT_DLL extern const mp_limb_t arb_log_tab11[1 << ARB_LOG_TAB11_BITS][ARB_LOG_TAB1_LIMBS]; FLINT_DLL extern const mp_limb_t arb_log_tab12[1 << ARB_LOG_TAB12_BITS][ARB_LOG_TAB1_LIMBS]; FLINT_DLL extern const mp_limb_t arb_log_tab21[1 << ARB_LOG_TAB21_BITS][ARB_LOG_TAB2_LIMBS]; FLINT_DLL extern const mp_limb_t arb_log_tab22[1 << ARB_LOG_TAB22_BITS][ARB_LOG_TAB2_LIMBS]; FLINT_DLL extern const mp_srcptr arb_log_log2_tab; void arb_log_newton(arb_t res, const arb_t x, slong prec); void arb_log_arf_newton(arb_t res, const arf_t x, slong prec); /* logarithms of primes */ #define ARB_LOG_PRIME_CACHE_NUM 13 FLINT_DLL extern const mp_limb_t arb_log_p_tab[ARB_LOG_PRIME_CACHE_NUM][ARB_LOG_TAB2_LIMBS]; void arb_log_primes_vec_bsplit(arb_ptr res, slong n, slong prec); void _arb_log_p_ensure_cached(slong prec); arb_srcptr _arb_log_p_cache_vec(void); /* exponential implementation */ /* only goes up to log(2) * 256 */ #define ARB_EXP_TAB1_NUM 178 #define ARB_EXP_TAB1_BITS 8 #define ARB_EXP_TAB1_PREC 512 #define ARB_EXP_TAB1_LIMBS (ARB_EXP_TAB1_PREC / FLINT_BITS) /* only goes up to log(2) * 32 */ #define ARB_EXP_TAB21_NUM 23 #define ARB_EXP_TAB21_BITS 5 #define ARB_EXP_TAB22_NUM (1 << ARB_EXP_TAB22_BITS) #define ARB_EXP_TAB22_BITS 5 #define ARB_EXP_TAB2_PREC 4608 #define ARB_EXP_TAB2_LIMBS (ARB_EXP_TAB2_PREC / FLINT_BITS) FLINT_DLL extern const mp_limb_t arb_exp_tab1[ARB_EXP_TAB1_NUM][ARB_EXP_TAB1_LIMBS]; FLINT_DLL extern const mp_limb_t arb_exp_tab21[ARB_EXP_TAB21_NUM][ARB_EXP_TAB2_LIMBS]; FLINT_DLL extern const mp_limb_t arb_exp_tab22[ARB_EXP_TAB22_NUM][ARB_EXP_TAB2_LIMBS]; void _arb_exp_taylor_naive(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N); void _arb_exp_taylor_rs(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N); void arb_exp_arf_bb(arb_t z, const arf_t x, slong prec, int minus_one); void arb_exp_arf_rs_generic(arb_t res, const arf_t x, slong prec, int minus_one); int _arb_get_mpn_fixed_mod_log2(mp_ptr w, fmpz_t q, mp_limb_t * error, const arf_t x, mp_size_t wn); slong _arb_exp_taylor_bound(slong mag, slong prec); void _arb_exp_sum_bs_powtab(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N); void _arb_exp_sum_bs_simple(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N); #define ARB_LOG_REDUCTION_DEFAULT_MAX_PREC 4000000 #define ARB_EXP_LOG_REDUCTION_PREC 2240 #define ARB_LOG_NEWTON_PREC 2800 void arb_exp_arf_log_reduction(arb_t res, const arf_t x, slong prec, int minus_one); void arb_exp_arf_generic(arb_t z, const arf_t x, slong prec, int minus_one); void arb_exp_arf(arb_t z, const arf_t x, slong prec, int minus_one, slong maglim); /* sin/cos implementation */ /* only goes up to (pi/4) * 256 */ #define ARB_SIN_COS_TAB1_NUM 203 #define ARB_SIN_COS_TAB1_BITS 8 #define ARB_SIN_COS_TAB1_PREC 512 #define ARB_SIN_COS_TAB1_LIMBS (ARB_SIN_COS_TAB1_PREC / FLINT_BITS) /* only goes up to (pi/4) * 32 */ #define ARB_SIN_COS_TAB21_NUM 26 #define ARB_SIN_COS_TAB21_BITS 5 #define ARB_SIN_COS_TAB22_NUM (1 << ARB_SIN_COS_TAB22_BITS) #define ARB_SIN_COS_TAB22_BITS 5 #define ARB_SIN_COS_TAB2_PREC 4608 #define ARB_SIN_COS_TAB2_LIMBS (ARB_SIN_COS_TAB2_PREC / FLINT_BITS) FLINT_DLL extern const mp_limb_t arb_sin_cos_tab1[2 * ARB_SIN_COS_TAB1_NUM][ARB_SIN_COS_TAB1_LIMBS]; FLINT_DLL extern const mp_limb_t arb_sin_cos_tab21[2 * ARB_SIN_COS_TAB21_NUM][ARB_SIN_COS_TAB2_LIMBS]; FLINT_DLL extern const mp_limb_t arb_sin_cos_tab22[2 * ARB_SIN_COS_TAB22_NUM][ARB_SIN_COS_TAB2_LIMBS]; #define ARB_PI4_TAB_LIMBS (4608 / FLINT_BITS) FLINT_DLL extern const mp_limb_t arb_pi4_tab[ARB_PI4_TAB_LIMBS]; void _arb_sin_cos_taylor_naive(mp_ptr ysin, mp_ptr ycos, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N); void _arb_sin_cos_taylor_rs(mp_ptr ysin, mp_ptr ycos, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int sinonly, int alternating); int _arb_get_mpn_fixed_mod_pi4(mp_ptr w, fmpz_t q, int * octant, mp_limb_t * error, const arf_t x, mp_size_t wn); void arb_sin_cos_arf_bb(arb_t zsin, arb_t zcos, const arf_t x, slong prec); void arb_sin_cos_arf_rs_generic(arb_t res_sin, arb_t res_cos, const arf_t x, slong prec); void arb_sin_cos_arf_generic(arb_t res_sin, arb_t res_cos, const arf_t x, slong prec); void _arb_sin_cos_wide(arb_t s, arb_t c, const arf_t x, const mag_t r, slong prec); void arb_sin_cos_wide(arb_t s, arb_t c, const arb_t x, slong prec); void _arb_sin_cos_generic(arb_t s, arb_t c, const arf_t x, const mag_t xrad, slong prec); void arb_sin_cos_generic(arb_t s, arb_t c, const arb_t x, slong prec); void arb_atan_gauss_primes_vec_bsplit(arb_ptr res, slong n, slong prec); #define ARB_ATAN_GAUSS_PRIME_CACHE_NUM 13 #define ARB_SIN_COS_ATAN_REDUCTION_DEFAULT_MAX_PREC 4000000 #define ARB_SIN_COS_ATAN_REDUCTION_PREC 2600 FLINT_DLL extern const mp_limb_t arb_atan_gauss_tab[ARB_ATAN_GAUSS_PRIME_CACHE_NUM][ARB_ATAN_TAB2_LIMBS]; void _arb_atan_gauss_p_ensure_cached(slong prec); arb_srcptr _arb_atan_gauss_p_cache_vec(void); void arb_sin_cos_arf_atan_reduction(arb_t res1, arb_t res2, const arf_t x, slong prec); ARB_INLINE flint_bitcnt_t _arb_mpn_leading_zeros(mp_srcptr d, mp_size_t n) { mp_limb_t t; mp_size_t zero_limbs; flint_bitcnt_t bits; zero_limbs = 0; while (1) { t = d[n - zero_limbs - 1]; if (t != 0) { bits = flint_clz(t); return bits + FLINT_BITS * zero_limbs; } zero_limbs++; if (zero_limbs == n) return FLINT_BITS * zero_limbs; } } void _arb_atan_sum_bs_simple(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N); void _arb_atan_sum_bs_powtab(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N); void arb_atan_arf_bb(arb_t z, const arf_t x, slong prec); void arb_atan_frac_bsplit(arb_t s, const fmpz_t p, const fmpz_t q, int hyperbolic, slong prec); ARB_INLINE slong arb_allocated_bytes(const arb_t x) { return arf_allocated_bytes(arb_midref(x)) + mag_allocated_bytes(arb_radref(x)); } ARB_INLINE slong _arb_vec_allocated_bytes(arb_srcptr vec, slong len) { slong i, size; size = len * sizeof(arb_struct); for (i = 0; i < len; i++) size += arb_allocated_bytes(vec + i); return size; } ARB_INLINE double _arb_vec_estimate_allocated_bytes(slong len, slong prec) { double size; size = len * (double) sizeof(arb_struct); if (prec > ARF_NOPTR_LIMBS * FLINT_BITS) size += len * (double) ((prec + FLINT_BITS - 1) / FLINT_BITS) * sizeof(mp_limb_t); return size; } int arb_load_str(arb_t res, const char * data); char * arb_dump_str(const arb_t x); #ifdef FLINT_HAVE_FILE int arb_load_file(arb_t res, FILE *stream); int arb_dump_file(FILE* stream, const arb_t x); #endif #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arb/000077500000000000000000000000001461254215100141665ustar00rootroot00000000000000flint-3.1.3/src/arb/abs.c000066400000000000000000000010201461254215100150700ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_abs(arb_t y, const arb_t x) { arf_abs(arb_midref(y), arb_midref(x)); mag_set(arb_radref(y), arb_radref(x)); } flint-3.1.3/src/arb/acos.c000066400000000000000000000024701461254215100152620ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_acos(arb_t z, const arb_t x, slong prec) { arb_t t, u; if (arb_is_exact(x)) { int side; if (arf_is_zero(arb_midref(x))) { arb_const_pi(z, prec); arb_mul_2exp_si(z, z, -1); return; } side = arf_cmpabs_2exp_si(arb_midref(x), 0); /* +/- 1 */ if (side == 0) { if (arf_is_one(arb_midref(x))) arb_zero(z); else arb_const_pi(z, prec); return; } else if (side > 0) { arb_indeterminate(z); return; } } arb_init(t); arb_init(u); arb_one(t); arb_submul(t, x, x, prec); arb_rsqrt(t, t, prec); arb_mul(t, x, t, prec); arb_atan(t, t, prec); arb_const_pi(u, prec); arb_mul_2exp_si(u, u, -1); arb_sub(z, u, t, prec); arb_clear(t); arb_clear(u); } flint-3.1.3/src/arb/acosh.c000066400000000000000000000014011461254215100154230ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_acosh(arb_t z, const arb_t x, slong prec) { if (arb_is_one(x)) { arb_zero(z); } else { arb_t t; arb_init(t); arb_mul(t, x, x, prec + 4); arb_sub_ui(t, t, 1, prec + 4); arb_sqrt(t, t, prec + 4); arb_add(t, t, x, prec + 4); arb_log(z, t, prec); arb_clear(t); } } flint-3.1.3/src/arb/add.c000066400000000000000000000044201461254215100150620ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_add(arb_t z, const arb_t x, const arb_t y, slong prec) { int inexact; inexact = arf_add(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); mag_add(arb_radref(z), arb_radref(x), arb_radref(y)); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } void arb_add_arf(arb_t z, const arb_t x, const arf_t y, slong prec) { int inexact; inexact = arf_add(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_add_ui(arb_t z, const arb_t x, ulong y, slong prec) { int inexact; inexact = arf_add_ui(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_add_si(arb_t z, const arb_t x, slong y, slong prec) { int inexact; inexact = arf_add_si(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_add_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) { int inexact; inexact = arf_add_fmpz(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_add_fmpz_2exp(arb_t z, const arb_t x, const fmpz_t man, const fmpz_t exp, slong prec) { int inexact; inexact = arf_add_fmpz_2exp(arb_midref(z), arb_midref(x), man, exp, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } flint-3.1.3/src/arb/add_error.c000066400000000000000000000032031461254215100162710ustar00rootroot00000000000000/* Copyright (C) 2012-2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_add_error_arf(arb_t x, const arf_t err) { mag_t t; if (arf_is_zero(err)) return; if (mag_is_zero(arb_radref(x))) { arf_get_mag(arb_radref(x), err); return; } mag_init(t); arf_get_mag(t, err); mag_add(arb_radref(x), arb_radref(x), t); mag_clear(t); } void arb_add_error_2exp_si(arb_t x, slong err) { fmpz_t t; if (mag_is_zero(arb_radref(x))) { mag_one(arb_radref(x)); mag_mul_2exp_si(arb_radref(x), arb_radref(x), err); return; } fmpz_init(t); fmpz_set_si(t, err); mag_add_2exp_fmpz(arb_radref(x), arb_radref(x), t); fmpz_clear(t); } void arb_add_error_2exp_fmpz(arb_t x, const fmpz_t err) { if (mag_is_zero(arb_radref(x))) { mag_one(arb_radref(x)); mag_mul_2exp_fmpz(arb_radref(x), arb_radref(x), err); return; } mag_add_2exp_fmpz(arb_radref(x), arb_radref(x), err); } void arb_add_error(arb_t x, const arb_t err) { mag_t u; if (arb_is_zero(err)) return; if (mag_is_zero(arb_radref(x))) { arb_get_mag(arb_radref(x), err); return; } mag_init(u); arb_get_mag(u, err); mag_add(arb_radref(x), arb_radref(x), u); mag_clear(u); } flint-3.1.3/src/arb/addmul.c000066400000000000000000000103361461254215100156030ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_addmul_arf(arb_t z, const arb_t x, const arf_t y, slong prec) { mag_t ym; int inexact; if (arb_is_exact(x)) { inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(ym, y); mag_fast_addmul(arb_radref(z), ym, arb_radref(x)); inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_fast_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else if (arf_is_inf(y) && arb_is_nonzero(x)) { if (arf_sgn(arb_midref(x)) > 0) arb_add_arf(z, z, y, prec); else arb_sub_arf(z, z, y, prec); } else { mag_init_set_arf(ym, y); mag_addmul(arb_radref(z), ym, arb_radref(x)); inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); mag_clear(ym); } } void arb_addmul(arb_t z, const arb_t x, const arb_t y, slong prec) { mag_t zr, xm, ym; int inexact; if (arb_is_exact(y)) { arb_addmul_arf(z, x, arb_midref(y), prec); } else if (arb_is_exact(x)) { arb_addmul_arf(z, y, arb_midref(x), prec); } else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(xm, arb_midref(x)); mag_fast_init_set_arf(ym, arb_midref(y)); mag_fast_init_set(zr, arb_radref(z)); mag_fast_addmul(zr, xm, arb_radref(y)); mag_fast_addmul(zr, ym, arb_radref(x)); mag_fast_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_addmul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARF_RND_DOWN); if (inexact) arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec); *arb_radref(z) = *zr; } else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y)) { if (arf_sgn(arb_midref(y)) > 0) arb_add_arf(z, z, arb_midref(x), prec); else arb_sub_arf(z, z, arb_midref(x), prec); } else if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x)) { if (arf_sgn(arb_midref(x)) > 0) arb_add_arf(z, z, arb_midref(y), prec); else arb_sub_arf(z, z, arb_midref(y), prec); } else { mag_init_set_arf(xm, arb_midref(x)); mag_init_set_arf(ym, arb_midref(y)); mag_init_set(zr, arb_radref(z)); mag_addmul(zr, xm, arb_radref(y)); mag_addmul(zr, ym, arb_radref(x)); mag_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_addmul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARF_RND_DOWN); if (inexact) arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec); else mag_set(arb_radref(z), zr); mag_clear(zr); mag_clear(xm); mag_clear(ym); } } void arb_addmul_si(arb_t z, const arb_t x, slong y, slong prec) { arf_t t; arf_init_set_si(t, y); /* no need to free */ arb_addmul_arf(z, x, t, prec); } void arb_addmul_ui(arb_t z, const arb_t x, ulong y, slong prec) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ arb_addmul_arf(z, x, t, prec); } void arb_addmul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) { arf_t t; if (!COEFF_IS_MPZ(*y)) { arf_init_set_si(t, *y); /* no need to free */ arb_addmul_arf(z, x, t, prec); } else { arf_init(t); arf_set_fmpz(t, y); arb_addmul_arf(z, x, t, prec); arf_clear(t); } } flint-3.1.3/src/arb/agm.c000066400000000000000000000136031461254215100151010ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* Use series expansion of the elliptic integral pi/(4K(z^2)) = 1/2 - z^2/8 - 5z^4/128 - 11z^6/512 - 469z^8/32768 + O(z^10) to avoid computing the last couple of AGM iterations. The higher coefficients are bounded by 1/64, so the tail is easily bounded by a geometric series (the error is passed as input here). Note: the input data is a+b, a-b; the variables z, z2 are scratch space. */ static void arb_agm_close_taylor(arb_t res, arb_t z, arb_t z2, const arb_t aplusb, const arb_t aminusb, const mag_t err, slong prec) { arb_div(z, aminusb, aplusb, prec); arb_sqr(z, z, prec); arb_sqr(z2, z, prec); arb_mul_si(res, z2, -469, prec); arb_addmul_si(res, z, -704, prec); arb_mul(res, res, z2, prec); arb_addmul_si(res, z2, -1280, prec); arb_mul_2exp_si(z, z, 12); arb_sub(res, res, z, prec); arb_add_ui(res, res, 16384, prec); arb_mul_2exp_si(res, res, -15); arb_add_error_mag(res, err); arb_mul(res, res, aplusb, prec); } void mag_agm(mag_t res, const mag_t x, const mag_t y) { if (!mag_is_finite(x) || !mag_is_finite(y)) { mag_inf(res); } else if (mag_is_zero(x) || mag_is_zero(y)) { mag_zero(res); } else { mag_t t, u, a, b, one_eps; mag_init(a); mag_init(b); mag_init(t); mag_init(u); mag_init(one_eps); /* invariant: a is an upper bound for agm(x,y) */ /* b would be a lower bound if not for rounding errors */ mag_max(a, x, y); mag_min(b, x, y); mag_one(one_eps); mag_add_ui_2exp_si(one_eps, one_eps, 1, -26); while (1) { mag_mul(t, b, one_eps); if (mag_cmp(t, a) > 0) { mag_set(res, a); break; } mag_add(t, a, b); mag_mul_2exp_si(t, t, -1); mag_mul(u, a, b); mag_sqrt(u, u); mag_swap(t, a); mag_swap(u, b); } mag_clear(a); mag_clear(b); mag_clear(t); mag_clear(u); mag_clear(one_eps); } } void mag_agm_lower(mag_t res, const mag_t x, const mag_t y) { if (mag_is_zero(x) || mag_is_zero(y)) { mag_zero(res); } else if (!mag_is_finite(x) || !mag_is_finite(y)) { mag_inf(res); } else { mag_t t, u, a, b, one_eps; mag_init(a); mag_init(b); mag_init(t); mag_init(u); mag_init(one_eps); /* invariant: b is a lower bound for agm(x,y) */ /* a would be an upper bound if not for rounding errors */ mag_max(a, x, y); mag_min(b, x, y); mag_one(one_eps); mag_add_ui_2exp_si(one_eps, one_eps, 1, -26); while (1) { mag_mul(t, b, one_eps); if (mag_cmp(t, a) > 0) { mag_set(res, b); break; } mag_add_lower(t, a, b); mag_mul_2exp_si(t, t, -1); mag_mul_lower(u, a, b); mag_sqrt_lower(u, u); mag_swap(t, a); mag_swap(u, b); } mag_clear(a); mag_clear(b); mag_clear(t); mag_clear(u); mag_clear(one_eps); } } void arb_agm(arb_t res, const arb_t x, const arb_t y, slong prec) { arb_t a, b, t, u; mag_t err, err2; slong acc1, acc2, wp; if (!arb_is_nonnegative(x) || !arb_is_nonnegative(y) || !arb_is_finite(x) || !arb_is_finite(y)) { arb_indeterminate(res); return; } if (arb_is_zero(x) || arb_is_zero(y)) { arb_zero(res); return; } arb_init(a); arb_init(b); arb_init(t); arb_init(u); mag_init(err); mag_init(err2); arb_set(a, x); arb_set(b, y); wp = prec; while (1) { acc1 = arb_rel_accuracy_bits(a); acc2 = arb_rel_accuracy_bits(b); acc1 = FLINT_MIN(acc1, acc2); /* Compute lower and upper bounds if we don't need high precision. */ if (acc1 < 20 || wp < 20) { arb_get_mag_lower(arb_radref(t), a); arb_get_mag_lower(arb_radref(u), b); mag_agm_lower(err, arb_radref(t), arb_radref(u)); arb_get_mag(arb_radref(t), a); arb_get_mag(arb_radref(u), b); mag_agm(err2, arb_radref(t), arb_radref(u)); arf_set_mag(arb_midref(t), err); arf_set_mag(arb_midref(u), err2); arb_set_interval_arf(res, arb_midref(t), arb_midref(u), prec); break; } if (acc1 < wp - 2 * MAG_BITS) wp = acc1 + 2 * MAG_BITS; arb_sub(u, a, b, wp); /* Fallback exit. */ if (arb_contains_zero(u)) { arb_union(res, a, b, wp); break; } arb_add(t, a, b, wp); arb_get_mag(err, u); arb_get_mag_lower(err2, t); mag_div(err, err, err2); mag_geom_series(err, err, 10); mag_mul_2exp_si(err, err, -6); /* Use Taylor series when we have 1/10 the accurate bits. */ if (mag_cmp_2exp_si(err, -wp) < 0) { /* pass a, b as scratch space */ arb_agm_close_taylor(res, a, b, t, u, err, wp); break; } arb_mul_2exp_si(t, t, -1); arb_mul(u, a, b, wp); arb_sqrt(u, u, wp); arb_swap(t, a); arb_swap(u, b); } arb_clear(a); arb_clear(b); arb_clear(t); arb_clear(u); mag_clear(err); mag_clear(err2); } flint-3.1.3/src/arb/approx_dot.c000066400000000000000000000336371461254215100165250ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" /* We need uint64_t instead of mp_limb_t on 32-bit systems for safe summation of 30-bit error bounds. */ #include void _arb_dot_addmul_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, mp_srcptr yptr, mp_size_t yn, int negative, flint_bitcnt_t shift); void _arb_dot_add_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, int negative, flint_bitcnt_t shift); void arb_approx_dot_simple(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) { slong i; if (len <= 0) { if (initial == NULL) arf_zero(arb_midref(res)); else arf_set_round(arb_midref(res), arb_midref(initial), prec, ARB_RND); return; } if (initial == NULL) { arf_mul(arb_midref(res), arb_midref(x), arb_midref(y), prec, ARB_RND); } else { if (subtract) arf_neg(arb_midref(res), arb_midref(initial)); else arf_set(arb_midref(res), arb_midref(initial)); arf_addmul(arb_midref(res), arb_midref(x), arb_midref(y), prec, ARB_RND); } for (i = 1; i < len; i++) arf_addmul(arb_midref(res), arb_midref(x + i * xstep), arb_midref(y + i * ystep), prec, ARB_RND); if (subtract) arf_neg(arb_midref(res), arb_midref(res)); } void arb_approx_dot(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) { slong i, j, nonzero, padding, extend; slong xexp, yexp, exp, max_exp, min_exp, sum_exp; int xnegative, ynegative; mp_size_t xn, yn, sn, alloc; flint_bitcnt_t shift; arb_srcptr xi, yi; arf_srcptr xm, ym; mp_limb_t serr; /* Sum over arithmetic errors - not used, but need dummy for calls */ mp_ptr tmp, sum; /* Workspace */ ARF_ADD_TMP_DECL; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arf_zero(arb_midref(res)); else { if (subtract) arf_neg_mul(arb_midref(res), arb_midref(x), arb_midref(y), prec, ARB_RND); else arf_mul(arb_midref(res), arb_midref(x), arb_midref(y), prec, ARB_RND); } return; } else if (len <= 0) { arf_set_round(arb_midref(res), arb_midref(initial), prec, ARB_RND); return; } } /* Number of nonzero midpoint terms in sum. */ nonzero = 0; /* Terms are bounded by 2^max_exp (with WORD_MIN = -infty) */ max_exp = WORD_MIN; /* Used to reduce the precision. */ min_exp = WORD_MAX; /* Account for the initial term. */ if (initial != NULL) { if (!ARF_IS_LAGOM(arb_midref(initial))) { arb_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(initial); if (!arf_is_special(xm)) { max_exp = ARF_EXP(xm); nonzero++; if (prec > 2 * FLINT_BITS) min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } } /* Determine maximum exponents for the main sum and the radius sum. */ for (i = 0; i < len; i++) { xi = x + i * xstep; yi = y + i * ystep; /* Fallback for huge exponents or non-finite values. */ if (!ARF_IS_LAGOM(arb_midref(xi)) || !ARF_IS_LAGOM(arb_midref(yi))) { arb_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(xi); ym = arb_midref(yi); if (!arf_is_special(xm)) { xexp = ARF_EXP(xm); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_exp = FLINT_MAX(max_exp, xexp + yexp); nonzero++; if (prec > 2 * FLINT_BITS) { slong bot; bot = (xexp + yexp) - (ARF_SIZE(xm) + ARF_SIZE(ym)) * FLINT_BITS; min_exp = FLINT_MIN(min_exp, bot); } } } } /* The midpoint sum is zero. */ if (max_exp == WORD_MIN) { arf_zero(arb_midref(res)); return; } else { /* Reduce precision based on actual sizes. */ if (min_exp != WORD_MAX) prec = FLINT_MIN(prec, max_exp - min_exp + MAG_BITS); prec = FLINT_MAX(prec, 2); } /* Extend sum so that we can use two's complement addition. */ extend = FLINT_BIT_COUNT(nonzero) + 1; /* Extra bits to improve accuracy (optional). */ padding = 4 + FLINT_BIT_COUNT(len); /* Number of limbs. */ sn = (prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; /* Avoid having to make a special case for sn = 1. */ sn = FLINT_MAX(sn, 2); /* Exponent for the main sum. */ sum_exp = max_exp + extend; /* We need sn + 1 limb for the sum (sn limbs + 1 dummy limb for carry or borrow that avoids an extra branch). We need 2 * (sn + 2) limbs to store the product of two numbers with up to (sn + 2) limbs, plus 1 extra limb for shifting the product. */ alloc = (sn + 1) + 2 * (sn + 2) + 1; ARF_ADD_TMP_ALLOC(sum, alloc) tmp = sum + (sn + 1); /* Set sum to 0 */ serr = 0; for (j = 0; j < sn + 1; j++) sum[j] = 0; if (initial != NULL) { xm = arb_midref(initial); if (!arf_is_special(xm)) { mp_srcptr xptr; xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); shift = sum_exp - xexp; if (shift < sn * FLINT_BITS) { xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); _arb_dot_add_generic(sum, &serr, tmp, sn, xptr, xn, xnegative ^ subtract, shift); } } } for (i = 0; i < len; i++) { xi = x + i * xstep; yi = y + i * ystep; xm = arb_midref(xi); ym = arb_midref(yi); /* The midpoints of x[i] and y[i] are both nonzero. */ if (!arf_is_special(xm) && !arf_is_special(ym)) { xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); yexp = ARF_EXP(ym); yn = ARF_SIZE(ym); ynegative = ARF_SGNBIT(ym); exp = xexp + yexp; shift = sum_exp - exp; if (shift >= sn * FLINT_BITS) { /* do nothing */ } #if 0 else if (xn == 1 && yn == 1 && sn == 2 && shift < FLINT_BITS) /* Fastest path. */ { mp_limb_t hi, lo, x0, y0; x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; umul_ppmm(hi, lo, x0, y0); lo = (lo >> shift) | (hi << (FLINT_BITS - shift)); hi = (hi >> shift); if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], hi, lo); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], hi, lo); } else if (xn == 2 && yn == 2 && shift < FLINT_BITS && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); if (sn == 2) { if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else { if (xnegative ^ ynegative) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } #endif else if (xn <= 2 && yn <= 2 && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; if (xn == 1 && yn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; umul_ppmm(u3, u2, x0, y0); u1 = u0 = 0; } else if (xn == 2 && yn == 2) { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); } else if (xn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X1(u3, u2, u1, y1, y0, x0); u0 = 0; } else { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; FLINT_MPN_MUL_2X1(u3, u2, u1, x1, x0, y0); u0 = 0; } if (sn == 2) { if (shift < FLINT_BITS) { u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u2 = u3; u3 = 0; } else /* FLINT_BITS < shift < 2 * FLINT_BITS */ { u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else if (sn == 3) { if (shift < FLINT_BITS) { u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u1 = u2; u2 = u3; u3 = 0; } else if (shift < 2 * FLINT_BITS) { u1 = (u3 << (2 * FLINT_BITS - shift)) | (u2 >> (shift - FLINT_BITS)); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } else if (shift == 2 * FLINT_BITS) { u1 = u3; u2 = 0; u3 = 0; } else /* 2 * FLINT_BITS < shift < 3 * FLINT_BITS */ { u1 = (u3 >> (shift - 2 * FLINT_BITS)); u2 = 0; u3 = 0; } if (xnegative ^ ynegative) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } else { mp_srcptr xptr, yptr; xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); yptr = (yn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(ym) : ARF_PTR_D(ym); _arb_dot_addmul_generic(sum, &serr, tmp, sn, xptr, xn, yptr, yn, xnegative ^ ynegative, shift); } } } xnegative = 0; if (sum[sn - 1] >= LIMB_TOP) { mpn_neg(sum, sum, sn); xnegative = 1; } if (sum[sn - 1] == 0) { slong sum_exp2; mp_size_t sn2; sn2 = sn; sum_exp2 = sum_exp; while (sn2 > 0 && sum[sn2 - 1] == 0) { sum_exp2 -= FLINT_BITS; sn2--; } if (sn2 == 0) { arf_zero(arb_midref(res)); } else { _arf_set_round_mpn(arb_midref(res), &exp, sum, sn2, xnegative ^ subtract, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp + sum_exp2); } } else { if (sn == 2) _arf_set_round_uiui(arb_midref(res), &exp, sum[1], sum[0], xnegative ^ subtract, prec, ARF_RND_DOWN); else _arf_set_round_mpn(arb_midref(res), &exp, sum, sn, xnegative ^ subtract, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp + sum_exp); } ARF_ADD_TMP_FREE(sum, alloc); } flint-3.1.3/src/arb/asin.c000066400000000000000000000024241461254215100152660ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_asin(arb_t z, const arb_t x, slong prec) { arb_t t; if (arb_is_exact(x)) { int side; if (arf_is_zero(arb_midref(x))) { arb_zero(z); return; } side = arf_cmpabs_2exp_si(arb_midref(x), 0); /* +/- 1 */ if (side == 0) { if (arf_is_one(arb_midref(x))) { arb_const_pi(z, prec); } else { arb_const_pi(z, prec); arb_neg(z, z); } arb_mul_2exp_si(z, z, -1); return; } else if (side > 0) { arb_indeterminate(z); return; } } arb_init(t); arb_one(t); arb_submul(t, x, x, prec); arb_rsqrt(t, t, prec); arb_mul(t, x, t, prec); arb_atan(z, t, prec); arb_clear(t); } flint-3.1.3/src/arb/asinh.c000066400000000000000000000016561461254215100154440ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_asinh(arb_t z, const arb_t x, slong prec) { if (arb_is_zero(x)) { arb_zero(z); } else { arb_t t; arb_init(t); arb_mul(t, x, x, prec + 4); arb_sqrt1pm1(t, t, prec + 4); if (arf_sgn(arb_midref(x)) >= 0) { arb_add(t, t, x, prec + 4); arb_log1p(z, t, prec); } else { arb_sub(t, t, x, prec + 4); arb_log1p(z, t, prec); arb_neg(z, z); } arb_clear(t); } } flint-3.1.3/src/arb/atan.c000066400000000000000000000073111461254215100152570ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_atan(arb_t res, const arb_t x, slong prec) { if (mag_is_zero(arb_radref(x))) { arb_atan_arf(res, arb_midref(x), prec); } else if (arf_is_nan(arb_midref(x))) { arb_indeterminate(res); } else if (mag_is_inf(arb_radref(x)) || arf_is_zero(arb_midref(x))) { mag_atan(arb_radref(res), arb_radref(x)); arf_zero(arb_midref(res)); } else if (arf_is_special(arb_midref(x))) /* at +/- inf */ { arb_atan_arf(res, arb_midref(x), prec); } else /* both mid(x), rad(x) non-special */ { slong acc; mag_t t, u; /* Estimate accuracy (first guess, only good near 0). */ acc = _fmpz_sub_small(ARF_EXPREF(arb_midref(x)), MAG_EXPREF(arb_radref(x))); if (acc < -10) /* Only compute a rough bound. */ { arb_get_mag(arb_radref(res), x); mag_atan(arb_radref(res), arb_radref(res)); arf_zero(arb_midref(res)); return; } mag_init(t); mag_init(u); arb_get_mag_lower(t, x); if (mag_is_zero(t)) /* Interval includes zero. */ { /* atan(rad(x) - |mid(x)|) */ arf_get_mag_lower(t, arb_midref(x)); mag_sub(t, arb_radref(x), t); mag_atan(t, t); /* atan(|mid(x)| + rad(x)) */ arf_get_mag(u, arb_midref(x)); mag_add(u, arb_radref(x), u); mag_atan(u, u); if (arf_sgn(arb_midref(x)) > 0) arb_set_interval_neg_pos_mag(res, t, u, FLINT_MIN(prec, MAG_BITS)); else arb_set_interval_neg_pos_mag(res, u, t, FLINT_MIN(prec, MAG_BITS)); } else { /* Adjust estimate of accuracy for large x. */ if (fmpz_sgn(MAG_EXPREF(t)) > 0) { /* acc = 2 * texp - radexp */ acc = _fmpz_sub_small(MAG_EXPREF(t), MAG_EXPREF(arb_radref(x))); if (acc < prec && !COEFF_IS_MPZ(MAG_EXP(t))) acc += MAG_EXP(t); } /* Clamp acc and adjust precision. */ acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); /* Compute using endpoints */ if (acc < 20) { arb_get_mag(u, x); mag_atan_lower(t, t); mag_atan(u, u); if (arf_sgn(arb_midref(x)) > 0) { arb_set_interval_mag(res, t, u, prec); } else { arb_set_interval_mag(res, t, u, prec); arb_neg(res, res); } } else { mag_mul_lower(t, t, t); mag_one(u); mag_add_lower(t, t, u); mag_div(t, arb_radref(x), t); if (mag_cmp_2exp_si(t, 0) > 0) { mag_const_pi(u); mag_min(t, t, u); } arb_atan_arf(res, arb_midref(x), prec); mag_add(arb_radref(res), arb_radref(res), t); } } mag_clear(t); mag_clear(u); } } flint-3.1.3/src/arb/atan2.c000066400000000000000000000063001461254215100153360ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_atan2(arb_t r, const arb_t b, const arb_t a, slong prec) { #define am arb_midref(a) #define ar arb_radref(a) #define bm arb_midref(b) #define br arb_radref(b) /* a + bi is a real number */ if (arb_is_zero(b)) { /* exactly zero */ if (arb_is_zero(a)) { /* define arg(0) = 0 by convention */ arb_zero(r); } /* interval contains only nonnegative numbers */ else if (arf_sgn(am) > 0 && arf_cmpabs_mag(am, ar) >= 0) { arb_zero(r); } /* interval contains only negative numbers */ else if (arf_sgn(am) < 0 && arf_cmpabs_mag(am, ar) > 0) { arb_const_pi(r, prec); } else { /* both positive and negative -- argument will be in [0, pi] */ mag_const_pi(arb_radref(r)); arf_set_mag(arb_midref(r), arb_radref(r)); arb_set_round(r, r, prec); arb_mul_2exp_si(r, r, -1); } } /* an imaginary number */ else if (arb_is_zero(a)) { /* interval contains only positive numbers */ if (arf_sgn(bm) > 0 && arf_cmpabs_mag(bm, br) > 0) { arb_const_pi(r, prec); arb_mul_2exp_si(r, r, -1); } /* interval contains only negative numbers */ else if (arf_sgn(bm) < 0 && arf_cmpabs_mag(bm, br) > 0) { arb_const_pi(r, prec); arb_neg(r, r); arb_mul_2exp_si(r, r, -1); } else { /* both positive and negative -- argument will be in 0 +/- pi/2 */ arf_zero(arb_midref(r)); mag_const_pi(arb_radref(r)); mag_mul_2exp_si(arb_radref(r), arb_radref(r), -1); } } /* strictly in the right half-plane -- atan(b/a) */ else if (arf_sgn(am) > 0 && arf_cmpabs_mag(am, ar) > 0) { arb_div(r, b, a, prec); arb_atan(r, r, prec); } /* strictly in the upper half-plane -- pi/2 - atan(a/b) */ else if (arf_sgn(bm) > 0 && arf_cmpabs_mag(bm, br) > 0) { arb_t t; arb_init(t); arb_div(r, a, b, prec); arb_atan(r, r, prec); arb_const_pi(t, prec); arb_mul_2exp_si(t, t, -1); arb_sub(r, t, r, prec); arb_clear(t); } /* strictly in the lower half-plane -- -pi/2 - atan(a/b) */ else if (arf_sgn(bm) < 0 && arf_cmpabs_mag(bm, br) > 0) { arb_t t; arb_init(t); arb_div(r, a, b, prec); arb_atan(r, r, prec); arb_const_pi(t, prec); arb_mul_2exp_si(t, t, -1); arb_add(r, t, r, prec); arb_neg(r, r); arb_clear(t); } /* overlaps the nonpositive half-axis -- [-pi, pi] */ else { arf_zero(arb_midref(r)); mag_const_pi(arb_radref(r)); } } flint-3.1.3/src/arb/atan_arf.c000066400000000000000000000201641461254215100161100ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" #define TMP_ALLOC_LIMBS(size) TMP_ALLOC((size) * sizeof(mp_limb_t)) /* atan(x) = x + eps, |eps| < x^3*/ void arb_atan_eps(arb_t z, const arf_t x, slong prec) { fmpz_t mag; fmpz_init(mag); fmpz_mul_ui(mag, ARF_EXPREF(x), 3); arb_set_arf(z, x); arb_set_round(z, z, prec); arb_add_error_2exp_fmpz(z, mag); fmpz_clear(mag); } /* atan(x) = pi/2 - eps, eps < 1/x <= 2^(1-mag) */ void arb_atan_inf_eps(arb_t z, const arf_t x, slong prec) { fmpz_t mag; fmpz_init(mag); fmpz_neg(mag, ARF_EXPREF(x)); fmpz_add_ui(mag, mag, 1); if (arf_sgn(x) > 0) { arb_const_pi(z, prec); } else { arb_const_pi(z, prec); arb_neg(z, z); } arb_mul_2exp_si(z, z, -1); arb_add_error_2exp_fmpz(z, mag); fmpz_clear(mag); } void arb_atan_arf(arb_t z, const arf_t x, slong prec) { if (arf_is_special(x)) { if (arf_is_zero(x)) { arb_zero(z); } else if (arf_is_pos_inf(x)) { arb_const_pi(z, prec); arb_mul_2exp_si(z, z, -1); } else if (arf_is_neg_inf(x)) { arb_const_pi(z, prec); arb_mul_2exp_si(z, z, -1); arb_neg(z, z); } else { arb_indeterminate(z); } } else if (COEFF_IS_MPZ(*ARF_EXPREF(x))) { if (fmpz_sgn(ARF_EXPREF(x)) < 0) arb_atan_eps(z, x, prec); else arb_atan_inf_eps(z, x, prec); } else { slong exp, wp, wn, N, r; mp_srcptr xp; mp_size_t xn, tn; mp_ptr tmp, w, t, u; mp_limb_t p1, q1bits, p2, q2bits, error, error2; int negative, inexact, reciprocal; TMP_INIT; exp = ARF_EXP(x); negative = ARF_SGNBIT(x); if (exp < -(prec/2) - 2 || exp > prec + 2) { if (exp < 0) arb_atan_eps(z, x, prec); else arb_atan_inf_eps(z, x, prec); return; } ARF_GET_MPN_READONLY(xp, xn, x); /* Special case: +/- 1 (we require |x| != 1 later on) */ if (exp == 1 && xn == 1 && xp[xn-1] == LIMB_TOP) { arb_const_pi(z, prec); arb_mul_2exp_si(z, z, -2); if (negative) arb_neg(z, z); return; } if (prec >= ARB_ATAN_NEWTON_PREC) { arb_atan_arf_newton(z, x, prec); return; } /* Absolute working precision (NOT rounded to a limb multiple) */ wp = prec - FLINT_MIN(0, exp) + 4; /* Too high precision to use table */ if (wp > ARB_ATAN_TAB2_PREC) { arb_atan_arf_bb(z, x, prec); return; } /* Working precision in limbs */ wn = (wp + FLINT_BITS - 1) / FLINT_BITS; TMP_START; tmp = TMP_ALLOC_LIMBS(4 * wn + 3); w = tmp; /* requires wn+1 limbs */ t = w + wn + 1; /* requires wn+1 limbs */ u = t + wn + 1; /* requires 2wn+1 limbs */ /* ----------------------------------------------------------------- */ /* Convert x or 1/x to a fixed-point number |w| < 1 */ /* ----------------------------------------------------------------- */ if (exp <= 0) /* |x| < 1 */ { reciprocal = 0; /* todo: just zero top */ flint_mpn_zero(w, wn); /* w = x as a fixed-point number */ error = _arf_get_integer_mpn(w, xp, xn, exp + wn * FLINT_BITS); } else /* |x| > 1 */ { slong one_exp, one_limbs, one_bits; mp_ptr one; reciprocal = 1; one_exp = xn * FLINT_BITS + wn * FLINT_BITS - exp; flint_mpn_zero(w, wn); /* 1/x becomes zero */ if (one_exp >= FLINT_BITS - 1) { /* w = 1/x */ one_limbs = one_exp / FLINT_BITS; one_bits = one_exp % FLINT_BITS; if (one_limbs + 1 >= xn) { one = TMP_ALLOC_LIMBS(one_limbs + 1); flint_mpn_zero(one, one_limbs); one[one_limbs] = UWORD(1) << one_bits; /* todo: only zero necessary part */ flint_mpn_zero(w, wn); mpn_tdiv_q(w, one, one_limbs + 1, xp, xn); /* Now w must be < 1 since x > 1 and we rounded down; thus w[wn] must be zero */ } } /* todo: moderate powers of two would be exact... */ error = 1; } /* ----------------------------------------------------------------- */ /* Table-based argument reduction */ /* ----------------------------------------------------------------- */ /* choose p such that p/q <= x < (p+1)/q */ if (wp <= ARB_ATAN_TAB1_PREC) q1bits = ARB_ATAN_TAB1_BITS; else q1bits = ARB_ATAN_TAB21_BITS; p1 = w[wn-1] >> (FLINT_BITS - q1bits); /* atan(w) = atan(p/q) + atan(w2) */ /* where w2 = (q*w-p)/(q+p*w) */ if (p1 != 0) { t[wn] = (UWORD(1) << q1bits) + mpn_mul_1(t, w, wn, p1); flint_mpn_zero(u, wn); u[2 * wn] = mpn_lshift(u + wn, w, wn, q1bits) - p1; mpn_tdiv_q(w, u, 2 * wn + 1, t, wn + 1); error++; /* w2 is computed with 1 ulp error */ } /* Do a second round of argument reduction */ if (wp <= ARB_ATAN_TAB1_PREC) { p2 = 0; } else { q2bits = ARB_ATAN_TAB21_BITS + ARB_ATAN_TAB22_BITS; p2 = w[wn-1] >> (FLINT_BITS - q2bits); if (p2 != 0) { t[wn] = (UWORD(1) << q2bits) + mpn_mul_1(t, w, wn, p2); flint_mpn_zero(u, wn); u[2 * wn] = mpn_lshift(u + wn, w, wn, q2bits) - p2; mpn_tdiv_q(w, u, 2 * wn + 1, t, wn + 1); error++; } } /* |w| <= 2^-r */ r = _arb_mpn_leading_zeros(w, wn); /* N >= (wp-r)/(2r) */ N = (wp - r + (2*r-1)) / (2*r); /* Evaluate Taylor series */ _arb_atan_taylor_rs(t, &error2, w, wn, N, 1); /* Taylor series evaluation error */ error += error2; /* Size of output number */ tn = wn; /* First table lookup */ if (p1 != 0) { if (wp <= ARB_ATAN_TAB1_PREC) mpn_add_n(t, t, arb_atan_tab1[p1] + ARB_ATAN_TAB1_LIMBS - tn, tn); else mpn_add_n(t, t, arb_atan_tab21[p1] + ARB_ATAN_TAB2_LIMBS - tn, tn); error++; } /* Second table lookup */ if (p2 != 0) { mpn_add_n(t, t, arb_atan_tab22[p2] + ARB_ATAN_TAB2_LIMBS - tn, tn); error++; } /* pi/2 - atan(1/x) */ if (reciprocal) { t[tn] = LIMB_ONE - mpn_sub_n(t, arb_atan_pi2_minus_one + ARB_ATAN_TAB2_LIMBS - tn, t, tn); /* result can be >= 1 */ tn += (t[tn] != 0); /* error of pi/2 */ error++; } /* The accumulated arithmetic error */ mag_set_ui_2exp_si(arb_radref(z), error, -wn * FLINT_BITS); /* Truncation error from the Taylor series */ mag_add_ui_2exp_si(arb_radref(z), arb_radref(z), 1, -r*(2*N+1)); /* Set the midpoint */ inexact = _arf_set_mpn_fixed(arb_midref(z), t, tn, wn, negative, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); TMP_END; } } flint-3.1.3/src/arb/atan_arf_bb.c000066400000000000000000000267041461254215100165610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz_vec.h" #include "arb.h" /* Determine N such that the error is bounded by 2^-prec. We choose an N with many trailing zeros to improve efficiency of the binary splitting. With N = 0, 1, 2, ... the highest included term is x, x^3, x^5, ... so the error is bounded by x^3, x^5, x^7, ... = x^(2N+3) */ static slong bs_num_terms(slong mag, slong prec) { slong N; if (mag >= 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); N = 0; while (mag * (2 * N + 3) > -prec) N++; if (N > 10000) while (N % 128 != 0) N++; if (N > 1000) while (N % 16 != 0) N++; if (N > 100) while (N % 2 != 0) N++; return N; } /* Argument reduction: apply atan(x) = 2 atan(x/(1+sqrt(1+x^2))) a total of r times, and convert result to a fixed-point number res together with absolute error err. With an initial inversion if xmag > 0. */ void arb_atan_bb_reduce(fmpz_t res, mag_t err, const arf_t x, slong xmag, slong r, slong prec) { int inexact; if (r == 0) { if (xmag <= 0) { inexact = arf_get_fmpz_fixed_si(res, x, -prec); mag_set_ui_2exp_si(err, inexact, -prec); } else { slong wp; arb_t t; wp = FLINT_MAX(8, prec - xmag); arb_init(t); arb_set_arf(t, x); arb_set_round(t, t, wp); arb_ui_div(t, 1, t, wp); mag_set(err, arb_radref(t)); inexact = arf_get_fmpz_fixed_si(res, arb_midref(t), -prec); mag_add_ui_2exp_si(err, err, inexact, -prec); arb_clear(t); } } else { slong k; arb_t p, p2, q, q2; arb_init(p); arb_init(p2); arb_init(q); arb_init(q2); if (xmag <= 0) { arb_set_arf(p, x); arb_set_round(p, p, prec); arb_mul(p2, p, p, prec); arb_add_ui(q, p2, 1, prec); arb_sqrt(q, q, prec); arb_add_ui(q, q, 1, prec); for (k = 1; k < r; k++) { if (k == 1) { arb_mul_2exp_si(q2, q, 1); arb_add(q2, q2, p2, prec); } else { arb_mul(q2, q, q, prec); } arb_add(q2, p2, q2, prec); arb_sqrt(q2, q2, prec); arb_add(q, q, q2, prec); } } else { arb_one(p); arb_one(p2); arb_set_arf(q, x); arb_set_round(q, q, prec); for (k = 0; k < r; k++) { arb_mul(q2, q, q, prec); arb_add(q2, p2, q2, prec); arb_sqrt(q2, q2, prec); arb_add(q, q, q2, prec); } } arb_div(p, p, q, prec); mag_set(err, arb_radref(p)); inexact = arf_get_fmpz_fixed_si(res, arb_midref(p), -prec); mag_add_ui_2exp_si(err, err, inexact, -prec); arb_clear(p); arb_clear(p2); arb_clear(q); arb_clear(q2); } } typedef struct { fmpz * s; fmpz * u; slong * r; slong wp; } work_t; static void worker(slong iter, work_t * work) { slong mag, wp, N; flint_bitcnt_t Qexp[1]; fmpz * s; fmpz * u; slong r; fmpz_t P, Q; fmpz_init(P); fmpz_init(Q); s = work->s + iter; u = work->u + iter; r = work->r[iter]; wp = work->wp; /* Binary splitting (+1 fixed-point ulp truncation error). */ mag = fmpz_bits(u) - r; N = bs_num_terms(mag, wp); if (N != 0) { _arb_atan_sum_bs_powtab(P, Q, Qexp, u, r, N); /* multiply by u/2^r */ fmpz_mul(P, P, u); *Qexp += r; /* T = T / Q (+1 fixed-point ulp error). */ if (*Qexp >= wp) { fmpz_tdiv_q_2exp(P, P, *Qexp - wp); fmpz_tdiv_q(P, P, Q); } else { fmpz_mul_2exp(P, P, wp - *Qexp); fmpz_tdiv_q(P, P, Q); } fmpz_add(s, s, P); } /* add u/2^r */ fmpz_mul_2exp(Q, u, wp - r); fmpz_add(s, s, Q); fmpz_clear(P); fmpz_clear(Q); } void arb_atan_arf_bb(arb_t z, const arf_t x, slong prec) { slong iter, bits, r, mag, q, wp, N; slong argred_bits, start_bits; flint_bitcnt_t Qexp[1]; int inverse; mag_t inp_err; fmpz_t s, t, u, P, Q, err; if (arf_is_zero(x)) { arb_zero(z); return; } if (arf_is_special(x)) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } if (ARF_SGNBIT(x)) { arf_t y; arf_init_neg_shallow(y, x); arb_atan_arf_bb(z, y, prec); arb_neg(z, z); return; } mag = arf_abs_bound_lt_2exp_si(x); /* We assume that this function only gets called with something reasonable as input (huge/tiny input will be handled by the main atan wrapper). */ if (FLINT_ABS(mag) > 2 * prec + 100) { flint_throw(FLINT_ERROR, "arb_atan_arf_bb: unexpectedly large/small input\n"); } /* approximate by x - x^3 / 3 or pi/2 - 1/x + (1/3)/x^3 */ if (mag < -prec / 4 - 2 || (mag-1) > prec / 5 + 3) { arb_t t; arb_init(t); arb_set_arf(t, x); if (mag < 0) { arb_mul(t, t, t, prec); arb_mul_arf(t, t, x, prec); arb_div_ui(t, t, 3, prec); arb_sub_arf(t, t, x, prec); arb_neg(z, t); /* error is bounded by x^5 */ mag_add_ui_2exp_si(arb_radref(z), arb_radref(z), 1, 5 * mag); } else { arb_ui_div(t, 1, t, prec); arb_mul(z, t, t, prec); arb_mul(z, z, t, prec); arb_div_ui(z, z, 3, prec); arb_sub(z, t, z, prec); arb_const_pi(t, prec + 2); arb_mul_2exp_si(t, t, -1); arb_sub(z, t, z, prec); /* error is bounded by 1/x^5, and 1/x <= 2^(1-mag) */ mag_add_ui_2exp_si(arb_radref(z), arb_radref(z), 1, 5 * (1-mag)); } arb_clear(t); return; } argred_bits = 8; start_bits = 16; /* Argument reduction q times. */ q = FLINT_MAX(0, argred_bits - FLINT_ABS(mag)); /* Determine working precision. */ wp = prec + 10 + 2 * q + 2 * FLINT_BIT_COUNT(prec); if (mag < 0) wp += (-mag); fmpz_init(s); fmpz_init(t); fmpz_init(u); fmpz_init(Q); fmpz_init(P); fmpz_init(err); /* in fixed-point ulp */ mag_init(inp_err); /* absolute error */ arb_atan_bb_reduce(t, inp_err, x, mag, q, wp); inverse = mag > 0; /* todo: compute in function, or pass to it */ /* s = 0, t = x */ if (flint_get_num_available_threads() == 1 || prec >= 1000000000) { for (iter = 0, bits = start_bits; !fmpz_is_zero(t); iter++, bits *= 2) { /* Extract bits. */ r = FLINT_MIN(bits, wp); fmpz_tdiv_q_2exp(u, t, wp - r); if (!fmpz_is_zero(u)) { /* Binary splitting (+1 fixed-point ulp truncation error). */ mag = fmpz_bits(u) - r; N = bs_num_terms(mag, wp); if (N != 0) { _arb_atan_sum_bs_powtab(P, Q, Qexp, u, r, N); /* multiply by u/2^r */ fmpz_mul(P, P, u); *Qexp += r; /* T = T / Q (+1 fixed-point ulp error). */ if (*Qexp >= wp) { fmpz_tdiv_q_2exp(P, P, *Qexp - wp); fmpz_tdiv_q(P, P, Q); } else { fmpz_mul_2exp(P, P, wp - *Qexp); fmpz_tdiv_q(P, P, Q); } fmpz_add(s, s, P); } /* add u/2^r */ fmpz_mul_2exp(Q, u, wp - r); fmpz_add(s, s, Q); /* 1 ulp from the division, 1 ulp from truncating the Taylor series */ fmpz_add_ui(err, err, 2); } /* atan(t) = atan(u/2^r) + atan((t 2^r - u)/(2^r + u t)) */ fmpz_mul_2exp(P, t, r); fmpz_mul_2exp(Q, u, wp); fmpz_sub(P, P, Q); fmpz_one(Q); fmpz_mul_2exp(Q, Q, r + wp); fmpz_addmul(Q, t, u); fmpz_mul_2exp(P, P, wp); fmpz_tdiv_q(t, P, Q); /* 1 ulp error from the division */ fmpz_add_ui(err, err, 1); } } else { fmpz * ws; fmpz * us; slong * rs; slong num = 0; ws = _fmpz_vec_init(FLINT_BITS); us = _fmpz_vec_init(FLINT_BITS); rs = flint_malloc(sizeof(slong) * FLINT_BITS); /* Bit-burst loop. */ for (iter = 0, bits = start_bits; !fmpz_is_zero(t); iter++, bits *= 2) { /* Extract bits. */ r = FLINT_MIN(bits, wp); fmpz_tdiv_q_2exp(u, t, wp - r); if (!fmpz_is_zero(u)) { fmpz_set(us + num, u); rs[num] = r; num++; /* 1 ulp from the division, 1 ulp from truncating the Taylor series */ fmpz_add_ui(err, err, 2); } /* atan(t) = atan(u/2^r) + atan((t 2^r - u)/(2^r + u t)) */ fmpz_mul_2exp(P, t, r); fmpz_mul_2exp(Q, u, wp); fmpz_sub(P, P, Q); fmpz_one(Q); fmpz_mul_2exp(Q, Q, r + wp); fmpz_addmul(Q, t, u); fmpz_mul_2exp(P, P, wp); fmpz_tdiv_q(t, P, Q); /* 1 ulp error from the division */ fmpz_add_ui(err, err, 1); } /* todo: only allocate as many temporaries as threads, reducing memory */ { work_t work; work.s = ws; work.u = us; work.r = rs; work.wp = wp; flint_parallel_do((do_func_t) worker, &work, num, -1, FLINT_PARALLEL_STRIDED); } for (iter = 0; iter < num; iter++) fmpz_add(s, s, ws + iter); _fmpz_vec_clear(ws, FLINT_BITS); _fmpz_vec_clear(us, FLINT_BITS); flint_free(rs); } /* add both err and inp_err */ arf_set_fmpz(arb_midref(z), s); mag_set_fmpz(arb_radref(z), err); arb_mul_2exp_si(z, z, -wp); mag_add(arb_radref(z), arb_radref(z), inp_err); /* argument reduction: atan(x) = 2^q atan(x') */ arb_mul_2exp_si(z, z, q); /* outmost argument reduction: atan(x) = +/-pi/2 - atan(1/x) */ if (inverse) { arb_t pi2; arb_init(pi2); arb_const_pi(pi2, wp); arb_mul_2exp_si(pi2, pi2, -1); arb_sub(z, pi2, z, wp); arb_clear(pi2); } arb_set_round(z, z, prec); fmpz_clear(s); fmpz_clear(t); fmpz_clear(u); fmpz_clear(Q); fmpz_clear(P); fmpz_clear(err); mag_clear(inp_err); } flint-3.1.3/src/arb/atan_frac_bsplit.c000066400000000000000000000066231461254215100176340ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #ifdef __GNUC__ # define ceil __builtin_ceil # define fabs __builtin_fabs #else # include #endif /* todo: arb arithmetic when sizes exceed prec */ static void bsplit(fmpz_t p1, fmpz_t q1, fmpz_t r1, const fmpz_t p, const fmpz_t q, const fmpz_t ppow2, const fmpz_t qpow2, int alternate, slong a, slong b, int cont) { if (b - a == 1) { if (a == 0) { fmpz_set(p1, p); fmpz_mul_ui(q1, q, 2*a+1); fmpz_mul_ui(r1, p, 2*a+1); } else { fmpz_set(p1, ppow2); fmpz_set(q1, qpow2); fmpz_mul_ui(q1, q1, 2*a+1); fmpz_mul_ui(r1, p1, 2*a+1); } if (alternate) { fmpz_neg(p1, p1); fmpz_neg(q1, q1); } } else { fmpz_t p2, q2, r2; slong m; m = (a + b) / 2; fmpz_init(p2); fmpz_init(q2); fmpz_init(r2); bsplit(p1, q1, r1, p, q, ppow2, qpow2, alternate, a, m, 1); bsplit(p2, q2, r2, p, q, ppow2, qpow2, alternate, m, b, cont); fmpz_mul(p1, p1, q2); fmpz_addmul(p1, r1, p2); fmpz_mul(q1, q1, q2); if (cont) fmpz_mul(r1, r1, r2); fmpz_clear(p2); fmpz_clear(q2); fmpz_clear(r2); } } #define LOG2 0.69314718055994530942 void arb_atan_frac_bsplit(arb_t s, const fmpz_t p, const fmpz_t q, int hyperbolic, slong prec) { fmpz_t P, Q, R, p2, q2; double logqp; slong N; mag_t err; if (fmpz_is_zero(p)) { arb_zero(s); return; } if (fmpz_is_zero(q)) { arb_indeterminate(s); return; } if (fmpz_sgn(p) < 0) { fmpz_t t; fmpz_init(t); fmpz_neg(t, p); arb_atan_frac_bsplit(s, t, q, hyperbolic, prec); arb_neg(s, s); fmpz_clear(t); return; } fmpz_init(P); fmpz_init(Q); fmpz_init(R); fmpz_init(p2); fmpz_init(q2); mag_init(err); /* If N >= 1 and p/q <= 1/2, the error is bounded by (p/q)^(2N+1). For error <= 2^-prec, it is sufficient to pick N >= (1/2) * (prec * log(2) / log(q/p) - 1). */ { slong qexp, pexp; double logp, logq; logp = fmpz_get_d_2exp(&pexp, p); logq = fmpz_get_d_2exp(&qexp, q); logqp = fabs(logq) / logp; logqp = mag_d_log_lower_bound(logqp) * (1.0 - 1e-12); logqp = logqp + (qexp - pexp) * LOG2 * (1.0 - 1e-12); } N = ceil((prec * (0.5 * LOG2) / logqp) * (1.0 + 1e-12)); N = FLINT_MAX(N, 1); N = FLINT_MIN(N, 4 * prec); fmpz_mul(p2, p, p); fmpz_mul(q2, q, q); bsplit(P, Q, R, p, q, p2, q2, !hyperbolic, 0, N, 0); mag_set_fmpz(err, p); mag_div_fmpz(err, err, q); mag_geom_series(err, err, 2 * N + 1); mag_div_ui(err, err, 2 * N + 1); arb_fmpz_div_fmpz(s, P, Q, prec); arb_add_error_mag(s, err); fmpz_clear(p2); fmpz_clear(q2); fmpz_clear(P); fmpz_clear(Q); fmpz_clear(R); mag_clear(err); } flint-3.1.3/src/arb/atan_newton.c000066400000000000000000000071221461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "arb_fmpz_poly.h" static const fmpz atan_coeffs[] = { 334639305, -111546435, 66927861, -47805615, 37182145, -30421755, 25741485, -22309287, 19684665, -17612595, 15935205, -14549535 }; static const ulong atan_den = 334639305; void _arb_atan_taylor(arb_t res, const arb_t x, slong prec) { slong mag; slong n; mag_t err; arb_t t; mag = arf_abs_bound_lt_2exp_si(arb_midref(x)); if (mag > -1) { arb_indeterminate(res); return; } arb_init(t); mag_init(err); if (mag < -prec) n = 1; else n = (prec + 2 * (-mag) - 1) / (2 * (-mag)); n = FLINT_MIN(n, 12); arb_get_mag(err, x); mag_geom_series(err, err, 2 * n + 1); mag_div_ui(err, err, 2 * n + 1); arb_mul(t, x, x, prec + 10); _arb_fmpz_poly_evaluate_arb_rectangular(t, atan_coeffs, n, t, prec + 10); arb_mul(res, t, x, prec + 10); arb_div_ui(res, res, atan_den, prec); arb_add_error_mag(res, err); mag_clear(err); arb_clear(t); } void arb_atan_newton(arb_t res, const arb_t x, slong prec) { arb_t t, s, c, w; slong n, wp, wp2; mag_t err; slong xmag, extra; if (arb_is_zero(x)) { arb_zero(res); return; } if (!arb_is_finite(x)) { arb_indeterminate(res); return; } xmag = arf_abs_bound_lt_2exp_si(arb_midref(x)); if (xmag > 4) { int sgn = arf_sgn(arb_midref(x)); if (arb_contains_zero(x)) { arb_indeterminate(res); return; } wp = FLINT_MAX(0, prec - xmag) + 15; arb_init(t); arb_inv(t, x, wp); arb_atan_newton(t, t, wp); arb_const_pi(res, prec + 15); arb_mul_2exp_si(res, res, -1); if (sgn < 0) arb_neg(res, res); arb_sub(res, res, t, prec); arb_clear(t); return; } arb_init(t); arb_init(s); arb_init(c); arb_init(w); mag_init(err); /* quick and accurate calculation near 0 */ if (xmag < -prec / 20) { _arb_atan_taylor(res, x, prec); } /* prec < ARB_ATAN_NEWTON_PREC / 2 if we recursed to this function, but we actually recurse by calling arb_atan, so this just needs to be a failsafe */ else if (prec <= 64) { arb_atan(res, x, prec); } else { if (prec <= 6000) n = 5; else if (prec <= 100000) n = 7; else if (prec <= 1000000) n = 9; else n = 11; wp = prec + 10 + (-xmag); wp2 = wp * (n - 1) / n; extra = 10; arb_atan(t, x, wp / n + extra); mag_zero(arb_radref(t)); arb_sin_cos(s, c, t, wp); arb_set_round(res, x, wp); arb_mul(w, c, res, wp); arb_sub(w, w, s, wp2); arb_mul(res, s, res, wp); arb_add(res, res, c, wp2); arb_div(w, w, res, wp2); _arb_atan_taylor(res, w, wp2); arb_add(res, t, res, prec); } arb_clear(t); arb_clear(s); arb_clear(c); arb_clear(w); mag_clear(err); } void arb_atan_arf_newton(arb_t res, const arf_t x, slong prec) { arb_set_arf(res, x); arb_atan_newton(res, res, prec); } flint-3.1.3/src/arb/atan_sum_bs_powtab.c000066400000000000000000000131131461254215100202000ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz_vec.h" #include "arb.h" slong _arb_compute_bs_exponents(slong * tab, slong n); slong _arb_get_exp_pos(const slong * tab, slong step); static void bsplit(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const slong * xexp, const fmpz * xpow, flint_bitcnt_t r, slong a, slong b) { if (b - a == 1) { fmpz_set(T, xpow); if (a % 2 == 0) fmpz_neg_ui(Q, 2 * a + 3); else fmpz_set_ui(Q, 2 * a + 3); *Qexp = 2 * r; } else if (b - a == 2) { fmpz_mul_ui(T, xpow, 2 * a + 5); fmpz_mul_2exp(T, T, 2 * r); fmpz_submul_ui(T, xpow + 1, 2 * a + 3); if (a % 2 == 1) fmpz_neg(T, T); fmpz_neg_ui(Q, 2 * a + 3); fmpz_mul_ui(Q, Q, 2 * a + 5); *Qexp = 4 * r; } else { slong step, m, i; flint_bitcnt_t Q2exp[1]; fmpz_t Q2, T2; step = (b - a) / 2; m = a + step; fmpz_init(Q2); fmpz_init(T2); bsplit(T, Q, Qexp, xexp, xpow, r, a, m); bsplit(T2, Q2, Q2exp, xexp, xpow, r, m, b); fmpz_mul(T, T, Q2); fmpz_mul_2exp(T, T, *Q2exp); /* find x^step in table */ i = _arb_get_exp_pos(xexp, step); fmpz_mul(T2, T2, Q); fmpz_addmul(T, xpow + i, T2); fmpz_clear(T2); fmpz_mul(Q, Q, Q2); *Qexp = *Qexp + *Q2exp; fmpz_clear(Q2); } } typedef struct { fmpz_t T; fmpz_t Q; flint_bitcnt_t Qexp; slong a; slong b; } atan_bsplit_struct; typedef atan_bsplit_struct atan_bsplit_t[1]; static void atan_bsplit_init(atan_bsplit_t x, void * args) { fmpz_init(x->T); fmpz_init(x->Q); } static void atan_bsplit_clear(atan_bsplit_t x, void * args) { fmpz_clear(x->T); fmpz_clear(x->Q); } typedef struct { const slong * xexp; const fmpz * xpow; flint_bitcnt_t r; } atan_bsplit_args; static void atan_bsplit_merge(atan_bsplit_t res, atan_bsplit_t L, atan_bsplit_t R, atan_bsplit_args * args) { slong i, step; slong a = L->a; slong b = R->b; step = (b - a) / 2; fmpz_mul(res->T, L->T, R->Q); fmpz_mul_2exp(res->T, res->T, R->Qexp); /* find x^step in table */ i = _arb_get_exp_pos(args->xexp, step); fmpz_mul(R->T, R->T, L->Q); fmpz_addmul(res->T, args->xpow + i, R->T); fmpz_zero(R->T); fmpz_mul(res->Q, L->Q, R->Q); res->Qexp = L->Qexp + R->Qexp; res->a = L->a; /* actually a no-op because of aliasing */ res->b = R->b; } static void atan_bsplit_basecase(atan_bsplit_t res, slong a, slong b, atan_bsplit_args * args) { bsplit(res->T, res->Q, &(res->Qexp), args->xexp, args->xpow, args->r, a, b); res->a = a; res->b = b; } static void bsplit2(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const slong * xexp, const fmpz * xpow, flint_bitcnt_t r, slong a, slong b) { atan_bsplit_t s; atan_bsplit_args args; slong max_threads; slong prec_hint; args.xexp = xexp; args.xpow = xpow; args.r = r; *s->T = *T; *s->Q = *Q; max_threads = flint_get_num_threads(); prec_hint = 2 * (b - a) * FLINT_MAX(r, 1); if (prec_hint < 30000) max_threads = 1; else if (prec_hint < 1000000) max_threads = FLINT_MIN(2, max_threads); else if (prec_hint < 5000000) max_threads = FLINT_MIN(4, max_threads); else max_threads = FLINT_MIN(8, max_threads); flint_parallel_binary_splitting(s, (bsplit_basecase_func_t) atan_bsplit_basecase, (bsplit_merge_func_t) atan_bsplit_merge, sizeof(atan_bsplit_struct), (bsplit_init_func_t) atan_bsplit_init, (bsplit_clear_func_t) atan_bsplit_clear, &args, a, b, 4, max_threads, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); *T = *s->T; *Q = *s->Q; *Qexp = s->Qexp; } void _arb_atan_sum_bs_powtab(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) { slong * xexp; slong length, i; fmpz * xpow; /* compute the powers of x^2 that will appear (at least x^2) */ xexp = flint_calloc(2 * FLINT_BITS, sizeof(slong)); length = _arb_compute_bs_exponents(xexp, N); xpow = _fmpz_vec_init(length); fmpz_mul(xpow, x, x); /* build x^i table */ for (i = 1; i < length; i++) { if (xexp[i] == 2 * xexp[i-1]) { fmpz_mul(xpow + i, xpow + i - 1, xpow + i - 1); } else if (xexp[i] == 2 * xexp[i-2]) /* prefer squaring if possible */ { fmpz_mul(xpow + i, xpow + i - 2, xpow + i - 2); } else if (xexp[i] == 2 * xexp[i-1] + 1) { fmpz_mul(xpow + i, xpow + i - 1, xpow + i - 1); fmpz_mul(xpow + i, xpow + i, xpow); } else if (xexp[i] == 2 * xexp[i-2] + 1) { fmpz_mul(xpow + i, xpow + i - 2, xpow + i - 2); fmpz_mul(xpow + i, xpow + i, xpow); } else { flint_throw(FLINT_ERROR, "power table has the wrong structure!\n"); } } if (flint_get_num_available_threads() == 1) bsplit(T, Q, Qexp, xexp, xpow, r, 0, N); else bsplit2(T, Q, Qexp, xexp, xpow, r, 0, N); _fmpz_vec_clear(xpow, length); flint_free(xexp); } flint-3.1.3/src/arb/atan_sum_bs_simple.c000066400000000000000000000030501461254215100201740ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void bsplit(fmpz_t P, fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong a, slong b) { if (b - a == 1) { fmpz_mul(P, x, x); fmpz_set(T, P); if (a % 2 == 0) fmpz_neg_ui(Q, 2 * a + 3); else fmpz_set_ui(Q, 2 * a + 3); *Qexp = 2 * r; } else { slong step, m; flint_bitcnt_t Q2exp[1]; fmpz_t P2, Q2, T2; step = (b - a) / 2; m = a + step; fmpz_init(P2); fmpz_init(Q2); fmpz_init(T2); bsplit(P, T, Q, Qexp, x, r, a, m); bsplit(P2, T2, Q2, Q2exp, x, r, m, b); fmpz_mul(T, T, Q2); fmpz_mul_2exp(T, T, *Q2exp); fmpz_mul(T2, T2, Q); fmpz_addmul(T, P, T2); fmpz_mul(P, P, P2); fmpz_mul(Q, Q, Q2); *Qexp = *Qexp + *Q2exp; fmpz_clear(P2); fmpz_clear(Q2); fmpz_clear(T2); } } void _arb_atan_sum_bs_simple(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) { fmpz_t P; fmpz_init(P); bsplit(P, T, Q, Qexp, x, r, 0, N); fmpz_clear(P); } flint-3.1.3/src/arb/atan_tab.c000066400000000000000000004513711461254215100161160ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #if FLINT_BITS == 64 #define Z2(a,b) UWORD(0x ## b ## a) #else #define Z2(a,b) UWORD(0x ## a), UWORD(0x ## b) #endif #define Z8(a,b,c,d,e,f,g,h) Z2(a,b), Z2(c,d), Z2(e,f), Z2(g,h), /* gaussian primes */ /* todo: first entry duplicates the pi table */ const mp_limb_t arb_atan_gauss_tab[ARB_ATAN_GAUSS_PRIME_CACHE_NUM][ARB_ATAN_TAB2_LIMBS] = {{ Z8(e6cc254b,db7f1447,ced4bb1b,44ce6cba,cf9b14ed,da3edbeb,865a8918,179727b0) Z8(9027d831,b06a53ed,413001ae,e5db382f,ad9e530e,f8ff9406,3dba37bd,c9751e76) Z8(602646de,c1d4dcb2,d27c7026,36c3fab4,34028492,4df435c9,90a6c08f,86ffb7dc) Z8(8d8fddc1,93b4ea98,d5b05aa9,d0069127,2170481c,b81bdd76,cee2d7af,1f612970) Z8(515be7ed,233ba186,a090c3a2,99b2964f,4e6bc05d,287c5947,1fbecaa6,2e8efc14) Z8(04de8ef9,dbbbc2db,2ad44ce8,2583e9ca,b6150bda,1a946834,6af4e23c,99c32718) Z8(bdba5b26,88719a10,a787e6d7,1a723c12,a9210801,4b82d120,e0fd108e,43db5bfc) Z8(74e5ab31,08e24fa0,bad946e2,770988c0,7a615d6c,bbe11757,177b200c,521f2b18) Z8(3ec86a64,d8760273,d98a0864,f12ffa06,1ad2ee6b,cee3d226,4a25619d,1e8c94e0) Z8(db0933d7,abf5ae8c,a6e1e4c7,b3970f85,5d060c7d,8aea7157,58dbef0a,ecfb8504) Z8(df1cba64,a85521ab,04507a33,ad33170d,8aaac42d,15728e5a,98fa0510,15d22618) Z8(ea956ae5,3995497c,95581718,de2bcbf6,6f4c52c9,b5c55df0,ec07a28f,9b2783a2) Z8(180e8603,e39e772c,2e36ce3b,32905e46,ca18217c,f1746c08,4abc9804,670c354e) Z8(7096966d,9ed52907,208552bb,1c62f356,dca3ad96,83655d23,fd24cf5f,69163fa8) Z8(1c55d39a,98da4836,a163bf05,c2007cb8,ece45b3d,49286651,7c4b1fe6,ae9f2411) Z8(5a899fa5,ee386bfb,f406b7ed,0bff5cb6,a637ed6b,f44c42e9,625e7ec6,e485b576) Z8(6d51c245,4fe1356d,f25f1437,302b0a6d,cd3a431b,ef9519b3,8e3404dd,514a0879) Z8(3b139b22,020bbea6,8a67cc74,29024e08,80dc1cd1,c4c6628b,2168c234,c90fdaa2) },{ Z8(d83a39e6,611bf5c2,1b8463bc,371bf122,a7497562,540ecb71,1e84d0e6,7e856259) Z8(a5211856,61d8cc64,45d203ab,fbf7e5fa,3b6b1db2,cdb4805a,c3513595,810a9e95) Z8(473bc7d7,408a336f,77080597,065a53d3,e31e0807,824213c3,ea06d2c9,f0a83b1d) Z8(ccd2045b,ed3e357d,974a3d27,8ce6bd61,6464ec39,049a5d85,35a5f778,5b8aa42e) Z8(db3e2224,105c5a61,17e7d90a,d975ed6d,c54f2579,e3d41e55,b745b2ee,b6549a31) Z8(dcd3ebaf,53c8526f,078f763f,af5a913b,041fbac3,cbf54a59,51cda3da,9ae40a1b) Z8(14e1b109,e9e1c888,2221c675,f200b82a,462529d0,82b7ada8,07d74462,d9023475) Z8(f77de100,ff1b46a6,a6f11fb8,15ff6d58,e4548e17,3f2db500,38b58b8d,bf8ec628) Z8(6a6563db,21d2058f,c6c8d09c,519ec063,97aaeb89,8eb12e0c,1c267ba9,eaf8c2ab) Z8(44bce093,a8ea0c60,7ddd34bb,c142d007,8d5224b4,c188eda4,a3921d3e,080d1156) Z8(0e986ad6,2719543f,c17b54d5,70324895,bd98c8ea,7b7a03f7,8399be6b,a6616507) Z8(9fc8a070,127a7102,0ddf61b8,4bdcdd9a,e129de9b,f20ba54b,4b6412eb,ed290ded) Z8(30ecb125,591ba108,5caa7f78,a43a6542,29a6690f,c07cef3a,d898486b,b7806bbc) Z8(4df91792,d3d97419,479363ec,a950fb54,663e0ed4,f695abc6,78732ac7,a2bb01ba) Z8(736715f0,dca56f2c,9160c8ef,72f2d30c,7ce8d9ea,4d3cb825,a955304f,3e44fc60) Z8(623481c1,b643d0e4,b22c5a9f,3731a574,241cbaa9,989c4869,91f1d7ed,8640e3a1) Z8(cbc91ed6,5a2b1ddf,33101432,7c72906a,9b912aba,cda314f5,abe93082,d2a2f233) Z8(80bb095f,c957f8ec,c0e094b3,4d7d48a6,51cd7990,68cd5110,5df22363,8db70c97) },{ Z8(ea43cd98,36c45014,c0859fd7,3ed9dfee,c5cee9f4,def2ae66,d267e292,63ee5ab0) Z8(6e6869ae,0e8b1a2c,d21c19fb,8148bbe8,48e38f1d,4011f225,3f7f0342,bb622ca7) Z8(cecd5a5a,b7fcb394,60bb7fd4,3ca8d5d1,471d8f18,b989c497,ec4fde57,79358977) Z8(d56c1e7b,b675f95c,41346b73,6490d044,5e364eff,4c9a1656,9b6d149a,3c425bf6) Z8(45e3ada6,25038334,84fe8208,5f6f40b9,83178864,a0e017d4,7f54125a,f37c57d6) Z8(8e3a0ac1,a4aedc6d,7ce81257,da579bfd,f9f90988,f5315cb6,38939277,803856fb) Z8(55045eba,bb25d092,79d09c1b,54f5e3d5,11d5e5fd,6de724a8,ba81d206,dbfd9c6b) Z8(d84d8072,cb38a0bc,5a3b6990,94080ffd,c4cf88e9,b1892ec8,37eb0879,7bcf0846) Z8(14b3e7cd,a8ebebfc,6bf5e633,bab9783c,95ca698b,25530db7,0a118493,bd7830ef) Z8(2d413c78,d1828861,221566d2,406380c2,cbfdcc0a,b5f1dacc,c174dab2,6dd93875) Z8(2b7e166d,35873498,c88b0f3d,2b51a212,2ab9ef47,c186b647,94c0bdb8,e37dfe30) Z8(46d42e9a,59872d06,bdd1cd28,9ab355a9,86812af7,cabfe476,4f3a7c24,b621d83d) Z8(a3b4c3ab,6734a999,8c35d25a,716c0cfd,5819c42e,d2f76f75,e8757678,52e80719) Z8(20193d87,1d9d0c19,50f0304d,c6ae17ee,bfacebae,07f85e9b,91375cde,5d4dfa69) Z8(cb8863ed,a5f3cc4c,808af180,85971e55,b8dfaaa1,6cd5f369,4d78de71,096ce12b) Z8(bb00d8ce,5be952d0,c31b9d4f,9261b634,cecf57dc,818d8878,643b8d55,509352f1) Z8(3fa1afbf,0f08a0ae,27ccc8e5,4d36a7a3,fadbba91,f346de40,179728b8,8aabe367) Z8(42088fd2,351d86e9,560dce43,a9936652,bbc9e141,7887af0c,0fb4d900,fb985e94) },{ Z8(7504e7bf,f5f75d82,1e298ee1,dacea7bc,e689e920,c47a2a99,f352dc02,02f8413b) Z8(68a9e5a6,0c30f525,19bc00a7,1b0344c2,2ba8abee,76a1bdad,7f7c3a79,c3c5ae6b) Z8(d8fcdd04,b004175b,c6238e75,14d3cfe1,88369961,4408190f,985ef4f0,02781944) Z8(ff984b70,b4fcf82d,2454ada9,c143234b,498eea4d,b2fe3af7,19dbc001,523da62f) Z8(00c0e97a,f94cfb73,0e20ad87,bfdb2a34,65016247,1de31fa1,71a510e6,4d757959) Z8(276b7d2c,e0ea0ab0,1802a6ad,64bdd502,7192b51a,1ae4448c,6da4341f,a10ed8e4) Z8(0831e70f,1d9731ae,5d5d993a,7482272e,81cb471b,9fb55ba4,397676c8,5603c3f3) Z8(79f53e5f,5973180c,d4f1ec18,c92269d4,a82346bd,2a6047c6,0e893a1a,ec30e266) Z8(98f42d6f,cc941afa,d73fdcee,b0bb3dc6,08ef5578,5c33dd24,8fe3e479,5914a168) Z8(8572a84f,5eadc998,fec1b4af,ba402eb8,9c4244ac,cb737733,77153d08,537e227d) Z8(c7f3c2d1,8927baab,f1c3b6f2,19028fba,b04d2505,8dd1dd26,9bf8e68e,722dd984) Z8(5713bb3b,db442739,55ace530,39948170,f7ef468f,c8a9d6bf,5f845544,2ab7c7c3) Z8(19902b6f,75a0f21d,30b43ab1,fdfc18f5,1743463a,551bc3a5,3cc5f11b,fc909225) Z8(9c40a55d,5770a1eb,15e47b68,7d6167f7,d9af5ac7,478b3269,62087d40,3177ab27) Z8(a1bf7313,5dcf02da,15ccc066,27706b38,2323381e,e79ae11f,8f5616e3,f72c951d) Z8(72be263f,f2143233,fe6a69ac,0ae5384b,fa8c71d9,f57b09d0,e5e02b7b,b0b45e8d) Z8(0cde91d6,0df8fcf8,117b4a44,68a59229,5889dfd3,8edd4828,c1175613,9ef2e3d6) Z8(a88a6635,92c46fd6,19515c06,73b258e8,c1e7d9d4,170d6eac,f4e7e4d2,a9b464a8) },{ Z8(03ddc625,c16d3c85,8b81a346,2d41b0b2,59349582,cb3d2fa1,d18ac3cf,42bb69b0) Z8(a1d8db18,fe9234cb,5ee9556d,68293067,bd7e3270,2e3aa432,f656b05e,c975080b) Z8(fab456c3,2822e851,1130e68d,bf25b33d,e53f287a,aa423997,cac35856,a34e81ef) Z8(87a6e522,915cdebb,db1c9610,e035c754,caed3502,5988464e,53dab02d,3d7110dd) Z8(96a337e0,f8494066,fa70a44e,15de021b,45f2707e,87774473,6a8011a3,b49d3439) Z8(3220b442,420b8f4f,5464906d,d767aabd,24b48584,28e5e853,b3dd7c95,1ec494c6) Z8(28819e04,52ef36c2,ca0d6135,74732d5b,38e71d42,1d3c0922,c110de6c,9ee51aee) Z8(4f4be662,0e3b5161,3bbb1c4d,889de698,44e0bea8,c3bf7c52,6fd5a4ea,32b50c9a) Z8(adefc389,86e60bb9,4d012cfb,04bcab45,5316a115,8892031a,8ded28e6,36e9a705) Z8(5b7b46ab,92aacb35,f6c45a06,7eb4c3d2,8bb23f9e,2d39010d,e4b7cd82,5da80760) Z8(99325801,2eb862f4,e26d056d,f330961e,93302b50,bbef1580,a73e7cc1,903f5f88) Z8(7fcfb490,5553e98d,7f75944a,9db38761,55786fae,d18c1791,f763d5d6,44d9683a) Z8(322e2364,a4ff8fe8,a1c020d8,5a89a8b2,786a7ee6,0d682416,974ae0bf,c31ba4ae) Z8(1f1af2f2,bdf5250a,1e6a60d6,17407710,9a97a65c,89e526b5,9d0dfb5d,c6fa1fc8) Z8(93d73b42,53ec5a4a,4b5115f7,7089c2b2,57685c57,9cae7a2b,f635d854,5d00796e) Z8(d2ed6407,69c8c107,9337339f,c7a506df,5e7c32ad,2e83f9f8,a82c8257,b95c2d98) Z8(d7855b3c,bd506baa,2c9b2d05,8e56e18b,9b025320,fea2b004,5e0ddcc8,325af6b9) Z8(d4acd2ab,a340a1c0,6b053400,c1aad262,331f260e,a9960776,526d42c4,985b6bcb) },{ Z8(17871509,99c2ee96,5549c33d,2b26412c,623f98b6,c32b3c70,f9a272a0,7f8dc8f9) Z8(8100e643,a56ea95f,1c4dd508,5d9bffd4,548a5d50,6bbeffe4,d7aaa373,c5703031) Z8(215bbf70,090a872a,e3e77155,830770db,eb3b17b6,89c127fb,ee13d5e2,f9d33b1e) Z8(45efa764,a48155bf,b7d6f403,94b18bbf,9ba118f0,3f2502bd,bdf058b9,fa3ec81e) Z8(455c4ef2,1cb7306e,a70795cc,e669d609,cec849e0,0749c8f2,868528a3,ce73c3ec) Z8(33e3ca2e,dd1ace86,31edbe63,2345b046,754f1529,ca63748d,0aa04567,ae650b32) Z8(eab675cf,7bb70852,5d4d7fca,b7992925,877c379f,b4327982,7027ef9d,352d5361) Z8(6909bc76,342f465e,bf70f917,5e0b4dc6,2cd9671b,cbb5c9ac,86cbead4,beb43581) Z8(1e118850,16ced00a,b6788c8c,1ce94010,0a3fdbba,14648e94,9a39bf3e,212dac4f) Z8(66271bff,70143d53,6515ebdc,dc665992,39548a55,904bb265,a50f940a,fdffe0ab) Z8(2ed98808,f1fcb5c6,9e7745f5,25f02834,b08b1570,d86e42f6,39283341,f85c1b8b) Z8(8202177f,30b1e7c4,2f5c08b0,38d4ecf2,9d38abc3,f8c29097,d5f1288d,ee20cd8f) Z8(eb310977,de3f31c1,4e30d183,04adda68,097e8c3f,8c29ea4c,e0e19e6c,ddebe8d9) Z8(5a17eedf,6dbc66e1,b0919c19,f1241e9c,94bb0bab,4d616731,bdd8f8e1,cf9e91d0) Z8(d0f7202d,7e6c8bcf,a055b394,e106de8e,b2c1f4e8,16f8bcfc,b49ccf9a,cde5c5a5) Z8(22de8549,a3087bfa,7816bc25,95016d09,1312eadc,a840bdf9,a5d90000,47009af1) Z8(ee4ffaba,a849e4c1,fa8cdda0,9c52a5ee,78d8c60c,93e1615f,67c95db3,babe4ca1) Z8(049d57c8,4e04afa4,124e964b,127374b4,6c89cbef,085a3c2e,e4cde4c9,b3ec431d) },{ Z8(89ec4e6a,db1a9980,bf3feb43,b4e13931,45d6446c,c84887cf,cc94cada,6bdee0ca) Z8(d0bcd144,320ad521,d529d08f,5f44cae2,8443bd13,d1cc4a4f,4a534b8b,f17b8f30) Z8(82bbf175,6adf739f,e4797a59,8f153640,677ac687,c5274670,15c56cba,214edb92) Z8(4b8263b6,fb1fc1f8,b58af536,a87f5bee,2b2da215,c6235ae6,16d2d606,459a6fef) Z8(cc99b815,fb3d9440,0500857b,89425173,db05616e,a61a46de,a5a55790,c4249574) Z8(306b483f,8a758599,b4c3d9c9,c5c8f88b,a5485ba3,05fbb884,0f4dd3b1,bcc03cfd) Z8(40ae8278,8782c1b3,42966a12,1e57f1f0,6c743b01,1d540efa,a92286a0,6ae4ec68) Z8(f760c682,834ae6ac,f6362124,a74e85d2,5d8934c4,23ff679e,c2ad5e72,0f9b96a5) Z8(d79f986f,184b79c1,35873f49,cd1d835c,61ed1041,11bcff32,b94a2688,65610637) Z8(802f2257,7f8fb304,e4df3903,45d2612a,7670b3db,05d34138,2d4ecc47,0ee8a845) Z8(79d317a0,75117766,b77efd44,3077ce9d,957e28d3,400a0e67,9e74c5b9,ad43e8a0) Z8(336d33a8,8a6c9100,5b959ce5,f5df39da,bed49eb6,6599873c,906df40b,d7874616) Z8(1e9fd182,0b307cab,5b242de1,0eb51d88,3c22c93f,9e9b3650,1d59284d,14bfb73a) Z8(03b858d8,9bec92a3,c9c5a092,cbcb09c9,135b8c91,c837d9f7,4747a1cc,44e0f505) Z8(40d283ad,0933cf54,8a7de49b,c230bb12,0bed34aa,a240a1d3,137939d7,f0bdfd90) Z8(6dd92e7c,fa16a39e,edecd4db,a86e3b4e,0d101731,c897070c,b7db4168,cf41fc9d) Z8(16ec64bb,c37f94da,3ac5504f,bb197ee7,cf002355,789fe302,ffacf1cf,bf71c721) Z8(46f73ed9,30970af9,801602c0,d210ad72,4d6629f2,5c275a31,237cf21b,e563e2bc) },{ Z8(aef74d50,677d3eea,93d11240,f1caf265,46243eb2,49bd4eae,0a985db0,eff87a8f) Z8(164a159e,6ff7ae04,0d444440,1101d243,e94f8ddb,435e59eb,6dcdc52d,2f91a836) Z8(9a42604a,331923b1,b79386c2,9896d479,7e6edf97,b5c69b07,5cfcefbf,08f7918d) Z8(60507f28,8c70d4b1,45939d3d,f9e15607,d8700ee2,1c8619ed,0bc40278,20fa6739) Z8(5386eef6,20243a89,91b112d2,0ebd2624,e49de22b,3e51b68b,37566303,a688c101) Z8(f6370190,ed846adc,eb082f87,e6a67976,3f16a417,e9133ed1,e483dfde,75187c76) Z8(d82669b7,2b1a8690,ec689668,170d45b5,47c07ed9,b86d8a9b,7fd98eb4,984483e9) Z8(732d4004,a87b64ad,27960864,43bb3d0c,7acffc36,6c460b8b,ddc3c7ba,51a05af2) Z8(407b806f,d3d1ba0c,8c0f2baf,70b7b71e,89d70dc7,b92617e7,c4d3f434,764d7491) Z8(181d7fd6,70559215,68325a86,f502c92e,dbd05eed,9056d7d1,7860250e,7b129624) Z8(4cdbc4e5,2f57d222,5f1a1a0b,c6f552b1,15e65bde,6b4cce10,4d5a45b6,5dbc2e02) Z8(45498160,231e9383,817dcd0c,6b40bdc8,713c289a,b2a3969c,939da51a,b5092d10) Z8(eb95ae87,c538b690,aae6f1bf,29846a64,a46a137f,001d8c7a,3f4ca376,248bbd53) Z8(1e7f92d2,71d3a5a1,468c4e50,aea99a9b,6cb24840,417bea1b,aa1a51c2,bfae1d33) Z8(3ca316a1,16a4fd62,63294727,927f086d,6177696b,61d0b530,5b7054f5,3433302c) Z8(c38a5443,3c094c40,5abc09b2,73c3c15c,5603240a,f66f25cf,7196b3ea,78e82094) Z8(76458175,6f6bf80d,b77b03f2,6e1cc08a,3b3f2c34,1f1386b4,7c81d423,0584faf5) Z8(648ab7ba,27634636,9151da19,3ff2e8c1,55610821,f82ebb01,2c4d2589,a57087e3) },{ Z8(bc12442c,2bf4ddd3,d97183a1,c696f515,2151907d,951f87bc,6de103e3,4080c1f6) Z8(05c07868,ee7d58fe,769aa14b,ed6978c6,49dc9594,48527316,614625c1,8fe570b4) Z8(753d4f97,c74ece61,56554cef,ee4412cc,3d65f511,b1ec9491,b1802bd4,ffa9b828) Z8(d6c00fa6,07b3f5dc,fcd556d3,c34e808d,9c3775d2,6c3cb449,b35c6523,83e726d7) Z8(371fa5bc,d05c4302,aa1e5088,48a3db72,2445e79c,8b39fa4b,529dfd91,e40ba984) Z8(a8ff2330,8cb6bb78,ebeb04ec,f02c78eb,b8e7a6df,ef554a29,bbc9bd12,193a71a6) Z8(3e7d1b8c,8723a3b3,e9824179,2b25897f,26db2fc8,002a6e96,f58a726b,0f4967ee) Z8(6a0084e9,5173a759,21a2bd1d,afec2cd9,37ab4d4b,bcc27c02,8bb9f60f,918e3b4d) Z8(68f000db,68130f74,f1c0cd67,b6ad4c22,d524f92f,2d5e03d6,294d3e41,f309a4dd) Z8(73e58259,78dbbc1c,1e84767f,409b93e2,5b9a0b66,1647a2b6,b3136164,5062bad3) Z8(507051bf,121a989b,58562481,4b43abf5,86003266,ac28768d,87f7a68e,56adcadb) Z8(6e30542f,c00f1b76,f36d95f2,107ce4e4,ec336c3d,03bd228c,6af25b58,3e32ac52) Z8(3de6c4f4,d821c239,32884e3f,173b7431,2d08bd4e,24ba92a4,ff92cae3,7a9c9384) Z8(67a0d3b5,3a18cd22,2604c26f,5f297975,bbe0ae9d,7741f384,16d7c8fc,4b8fba97) Z8(f0eb96c1,5737bf6e,142dbe07,d79fe8c8,ed58bae7,9df6de78,64eca149,98fcc2fe) Z8(31ad6676,09eb17fb,c462e806,87b668d4,a932adfc,ba3113da,5419720b,cebcf860) Z8(1a0b49bb,cc81324e,5c04ae6e,83034075,8d11e6ef,bfaf4c45,22b7ea90,117a20ac) Z8(fe9fe299,849b4b3a,23bf431e,ee0a2b32,de2c7f1c,d9306dea,b77d307d,e0455724) },{ Z8(d061657b,7f5314a0,de8b793e,bf96d7cf,b265f39c,f4b6cded,6fed9814,71e74c2f) Z8(efeaf233,95800d7a,8b32bbdb,2e9ddb22,58ea48fc,053a2176,e8e4e29a,7a9648d8) Z8(2ef37a90,739bee38,66a1273a,349244d7,4fb296d9,bb467998,d5438327,77480b0f) Z8(aab59ff2,bfd14f0c,02d01f87,3ff3e4c4,137df91e,83b77c45,b4e7e2ed,80402178) Z8(3e3cda1b,3b775279,172e10ce,501f6ea9,4f8926f1,0812afc1,af189694,2b5ae1c1) Z8(37e5c9bd,171c27ac,6d1c3ce6,c47e52dc,6b28c60b,836a1fd2,ed53502b,1ec7e071) Z8(87a08255,98e45ece,edd605a1,b09c6ee8,9d9b9bcd,13edc499,d53f9f18,a217a773) Z8(8ee38552,197fabb0,87d05259,2d862369,e7c3af6b,6476d685,6d5d9950,bc2a234c) Z8(d611404e,ba814a70,372aa0fd,2f3ec2b6,ab0ab6fc,b4fb5cce,30b7861d,16cf36e1) Z8(f1b93445,70d9606f,e131bdb9,1f76a1c8,842b749a,2416f931,28f80c7d,2c09041e) Z8(ec54ca5d,5ab6c8cd,8ab62431,4f93ad47,2822a1e3,6e745a96,89e7568b,5c20442c) Z8(63837fdf,cc44c710,491a7ee0,b2256bb4,5ec4f7be,a08b29f8,2d2ad6ce,6754c6a5) Z8(0755259f,db2930b9,81f6b25c,19103fce,1cc6fe10,174d18ba,19a92e37,9683ab47) Z8(c4b3e4a2,068f104c,da977fca,a1bd8416,a2a6dece,03c6feb1,5fd9ae72,61be195e) Z8(fe75267b,43af73f7,cd82f4cc,1d8f817b,dd51e0c0,51042e74,c14c5318,93ea7442) Z8(08156208,807dd7cd,734dd748,9401b831,8469d214,7c5d3810,b1ed0506,74e7e240) Z8(202cdaee,3dc1dec2,13a08d9f,8ea54eec,cd066626,3861e089,7fb494a8,3816f271) Z8(ae4158ea,f03ec533,9ed2b700,59a13faa,c99c8bb0,e21d9a42,57aae117,9b23a81e) },{ Z8(40616922,9d34ac2f,4bd19e0a,b12c4ea5,bd9cf851,ca926969,2e33a847,768e752d) Z8(56f4b432,c15871f2,31d478d4,0e7ca3c0,e21119b0,69524bd2,783c9f4f,02d88b1c) Z8(287ca051,aabc74a1,c8001332,40152f50,ea2de2fd,2e41d339,2ded84bc,f9a5baae) Z8(e57280db,170db21d,01b80af3,7bc76b30,a248a80c,4cd197cc,cf7bcc1a,33dfafb3) Z8(433bf0bb,08cbdbf6,06ec22ee,53e3a9c1,a84b6ec0,bce81443,da81cf5a,a2e390f9) Z8(e6af0960,f826d285,93037a42,0b3ecc3e,9afbc7a2,d7ac4450,e7ebb01c,3e917655) Z8(44a13618,5dd6965b,729bee19,8971e231,10533a8f,b9dbf97a,45a59391,4c16641c) Z8(9f5a8ae3,0fdd1871,4d8079ab,cea652e9,69aea9d1,882c520b,89f98654,6456037f) Z8(d236f1e9,d5f255c6,6660c83f,b7017592,39c34e7c,08e0bbb4,68f886d9,f7475b48) Z8(627d4f95,2cf50268,06db66c7,9afe9c05,44dc9f82,27208e86,1e31e20e,67acda83) Z8(d73584a6,9d3dea97,605bc109,edda4ba3,cc0cc876,cb54111a,fa9f02bc,28b51308) Z8(761e2553,3f63d969,e6fe9b84,d1c6884e,61a1745f,05328eae,26dbcaa6,8c309855) Z8(0dfc4ebb,00346c4f,75e13691,c091ccb6,fd35b510,73c59257,9dd0fe3f,ccfe7f0d) Z8(e040ee9d,b2f27bf2,a2522935,c2ea3c79,7d8da796,0cd7f474,8c469d93,9410cc93) Z8(64c1dd80,8323df01,c31b5b14,12aa1096,e6776a8e,b981283c,0264fad7,587bcbcf) Z8(e3bb7659,df9a4346,74075a4a,388b3911,9079b0f9,4e09ecfc,aa020a6e,09e9e4e1) Z8(1b3829a5,3519834d,3335f6d1,1b4893df,499b8def,3c2e5aca,c56d4c48,36151a0f) Z8(b1774bc9,876cec6f,57d230c5,603d1a18,4dfa012d,1684b380,a56df267,818fabf2) },{ Z8(0874073f,546b8809,49d9ad59,2d45175d,abb55aa2,ef25c890,444a20dd,c1c7e802) Z8(b028fb3e,39a3c91e,f9b38f63,4b1f4de5,41c46d08,c4c82dd2,85ce91f8,f45a456f) Z8(9217df4f,94edd499,29ad3519,8554f0a8,8bd04279,4f02e017,6d011162,ffc6422f) Z8(1c8d81dd,b8a2c8b6,22c93c58,a57e2a2d,a6e964f7,4c811310,cb4400e0,f495dc47) Z8(2a177310,3ab89fac,919f4eb7,1154bc78,79eb3420,d20fb2ff,7898d5d1,7d74b33a) Z8(8e7a0f93,3e9407ce,5eaebbc5,7af050a1,8c01ff71,32e6c421,50d70532,42423673) Z8(d9f29b5e,6a4fa1f7,c2d5f70b,a429d310,ff5879b9,bc74794a,7c3dc111,1a5fb862) Z8(ed1ed35f,07668a2c,1d2fda4d,cd157db7,81625375,b7ddc6fe,e0195125,bb4d1a7e) Z8(aae55df9,80f6fef7,7dec3f5c,3ccecb1d,72fd2dd4,93a4f921,ce340163,cfd1effe) Z8(05be746e,e3f1d21b,3b96348f,8315ac16,31552c15,5c111ac6,bbd6c847,849cf040) Z8(911a0ebc,93b4fd69,bd360cd1,f6f4767a,94b07f8c,4d27cb31,9358f89f,c63c7a41) Z8(398da5f5,81c3e162,ab68386f,33036c6d,ed79a33f,e0cd04aa,569a0fdd,1f9ee63a) Z8(70e79b80,7536dabd,6c9d0d84,4d0023f8,b50aacce,d416293a,d4987051,725d8ea6) Z8(10af4667,06a8d273,713daf56,dc5e0b57,427b542d,aab92de5,2136d626,9d2d1f2a) Z8(c736f8d1,214be8b6,30187ac9,25a52ca6,e151805e,8d9f4db9,1b6bd2d9,76205630) Z8(54ee5203,b7ab28bf,788202ad,9d42c215,49268320,4e357b97,3fcb4c19,76d460c6) Z8(caba6527,4ee62f0f,d7214ebb,be3aefe2,bf394f6c,508f7e71,3fffce9b,60d79e62) Z8(8ebd21e8,6cab8d58,096a5d53,e186b7fe,6093c5d2,29ca140f,29d124b3,93877aad) },{ Z8(7ffd1aa4,549bfc87,2c6323ef,61f292d0,f07e70f3,e962db79,c5df849a,46ebf925) Z8(112243d1,af78fb6d,28152857,afd7b3b9,3b90da9c,a74e8228,f852f1a7,c91b97d8) Z8(073736be,4c1aeed5,b7786d99,5776bfa5,76c0194c,d91014bd,a631e3f3,9a87fca3) Z8(7c1666f6,975ba816,3ac2ba67,eee18250,302f4726,f0b11474,044fff56,2611531c) Z8(fa4c3ef6,cb2f2c46,95b01e3d,76c9f0a9,4afa1071,9839756d,308dbbd7,4c6055bf) Z8(4151dd96,50551e82,a57188f3,b6d1cb4d,97749294,ad416154,1f88f149,01c0cd2a) Z8(5ad5120a,c8a73b10,c73002b5,f7647cf6,fbb73ac1,1ac55de7,f3f8bbaf,a724ac91) Z8(5693f5f9,3c76d18c,27848cc2,863c0bde,3631a309,c3aed681,32886711,9ecc2936) Z8(5ceef361,76158824,a5f8b299,5eb62e60,78f1167b,a3235dfa,9fb5d5a8,7f3f432f) Z8(3690b86e,34938604,01647ed8,cdd5ddff,958d9ffd,31370891,74d5e99c,e0ffc86e) Z8(38a12fc4,54e2821e,bf90b86f,b916cd00,b4c9dff6,3fb4e37c,7a8bb844,d8713fd2) Z8(ddf1d971,17f8646b,a7e8e618,cca864c5,df389b01,dd468084,ce75d5ac,5a4db6c1) Z8(ecc9ceea,5441a19f,c72b91cc,5ca130e0,a2d88a18,0c800745,929003de,e9726c93) Z8(6fb8fb3a,c5af516e,3e36a872,44a99aa3,de4ab316,3a21ee89,ddf4a7dc,9e3bbc7b) Z8(25733109,6d1e104e,a834e50e,8accb348,3c5c0ace,635b5e0f,d4de5b28,e45477e4) Z8(8f19b24f,966c6b8d,eb07287b,e304f773,62948331,761a63f0,99e9eafc,54e850aa) Z8(f33f2460,183210de,e93e82b1,0ab89d3d,df1ce150,03132216,302cca7e,f8bd27a4) Z8(25865183,7356c7b3,0de9bc82,58ccd7e1,b5572bd1,55f866a5,b0029c17,bc4de960) }}; const mp_limb_t arb_atan_pi2_minus_one[ARB_ATAN_TAB2_LIMBS] = { Z8(cd984a96,b6fe288f,9da97637,899cd975,9f3629da,b47db7d7,0cb51231,2f2e4f61) Z8(204fb062,60d4a7db,8260035d,cbb6705e,5b3ca61d,f1ff280d,7b746f7b,92ea3cec) Z8(c04c8dbd,83a9b964,a4f8e04d,6d87f569,68050924,9be86b92,214d811e,0dff6fb9) Z8(1b1fbb83,2769d531,ab60b553,a00d224f,42e09039,7037baec,9dc5af5f,3ec252e1) Z8(a2b7cfda,4677430c,41218744,33652c9f,9cd780bb,50f8b28e,3f7d954c,5d1df828) Z8(09bd1df2,b77785b6,55a899d1,4b07d394,6c2a17b4,3528d069,d5e9c478,33864e30) Z8(7b74b64d,10e33421,4f0fcdaf,34e47825,52421002,9705a241,c1fa211c,87b6b7f9) Z8(e9cb5662,11c49f40,75b28dc4,ee131181,f4c2bad8,77c22eae,2ef64019,a43e5630) Z8(7d90d4c8,b0ec04e6,b31410c9,e25ff40d,35a5dcd7,9dc7a44c,944ac33b,3d1929c0) Z8(b61267ae,57eb5d19,4dc3c98f,672e1f0b,ba0c18fb,15d4e2ae,b1b7de15,d9f70a08) Z8(be3974c9,50aa4357,08a0f467,5a662e1a,1555885b,2ae51cb5,31f40a20,2ba44c31) Z8(d52ad5ca,732a92f9,2ab02e30,bc5797ed,de98a593,6b8abbe0,d80f451f,364f0745) Z8(301d0c07,c73cee58,5c6d9c77,6520bc8c,943042f8,e2e8d811,95793009,ce186a9c) Z8(e12d2cda,3daa520e,410aa577,38c5e6ac,b9475b2c,06caba47,fa499ebf,d22c7f51) Z8(38aba734,31b4906c,42c77e0b,8400f971,d9c8b67b,9250cca3,f8963fcc,5d3e4822) Z8(b5133f4b,dc70d7f6,e80d6fdb,17feb96d,4c6fdad6,e89885d3,c4bcfd8d,c90b6aec) Z8(daa3848b,9fc26ada,e4be286e,605614db,9a748636,df2a3367,1c6809bb,a29410f3) Z8(76273644,04177d4c,14cf98e8,52049c11,01b839a2,898cc517,42d18469,921fb544) }; const mp_limb_t arb_atan_tab1[1 << ARB_ATAN_TAB1_BITS][ARB_ATAN_TAB1_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(800f56c0,471a535c,67be3ae1,d89ebbe4,6126f5a9,d62450d6,f625cdfb,6d688680) Z8(2682bef6,892248ad,eb9bc957,167c18ba,6b6d4f7e,4bb12afb,aaddddb9,00ffffaa) },{ Z8(d79ae2a7,570f29f8,9717e1e5,cc7790ed,ac4a4e52,6f9cb7c5,28bc8f59,2111d081) Z8(cfdd9ca1,3507a2ae,2e345e00,8ed0ad40,f77cc15e,d00c46a3,5bbba972,01fffd55) },{ Z8(61e8f518,1b37431d,e4186302,46af6bbf,91294bed,9e608b5c,ebea3e47,dc4ab848) Z8(ac4d1fad,14db0e87,1beddd8e,6f3b42e4,ee5a5b71,6d7f457b,30986134,02fff700) },{ Z8(4df9c218,85a1b8fb,797ad494,bcabe016,286e9ba4,68d09936,858d1e57,a36a1de9) Z8(c9d5872e,81a57e00,0437bbd1,2083bd97,0057dd81,ef9e3159,776e5356,03ffeaab) },{ Z8(a5a0cb92,6b52a899,206a0785,3293c311,165a6a5a,734d22a1,c5de3191,38d13644) Z8(a3132784,56335a58,5200eb10,fd306b02,04d3fd27,ec153c93,c629bfed,04ffd657) },{ Z8(a08edf4a,83a73639,cba0219c,a9c8faab,c0bef870,36a7ad69,89a224cf,6e211e53) Z8(4ac30913,c49cd215,6aaedaa2,8dd4fb81,cab5251b,ce7603f5,12970d6b,05ffb806) },{ Z8(c468bf81,d7aa9735,a501ca08,8750f3a2,175e84fc,c64cbc9c,549887da,63253408) Z8(02ffdb3c,9aaafeff,6171a4ba,cb479a5c,f7f8cafc,f209c454,ca45c470,06ff8db7) },{ Z8(6f362901,1358c95c,c276afc4,13c86927,f7a43e2d,0f282ff5,897e5f9d,3b2a91f5) Z8(a26b0830,b2380bed,a606dc40,9c036814,6ed46310,13bcebbb,ea5d892a,07ff556e) },{ Z8(879c8a25,fc7e1c8c,29974e6b,237c9daf,a9dcd26e,74fc920d,75f96824,d1bc0156) Z8(379ee4be,381d3599,1bc682b8,a4ff745e,89968a2a,0c123d1f,17624bb1,08ff0d2e) },{ Z8(59d2161b,993c1e86,eee6b8d2,aef449a6,a2c015f4,32971e8b,7d6fac19,0a0e82e9) Z8(7fd2da02,0729939d,220db88c,184ecc9b,30da72f6,918538b2,b4e4ec8b,09feb2f8) },{ Z8(b02c5942,89362e3f,c991b205,0adf3417,fcaf53f6,ec4b00d9,5f2e123c,9b020587) Z8(7c28c6a2,b6bd8276,525a72aa,3c64d55b,ff317148,76e77e9c,fd1d96a5,0afe44d2) },{ Z8(162c790b,257b0e0e,d755b36e,9b14ed68,6717017d,ed0894b8,439bbf1e,a5989626) Z8(17de7976,a7731202,f807f208,71dddd64,61df56ec,f220e10d,186d14fc,0bfdc0c2) },{ Z8(e376bcfd,068a96f1,dfbb2b41,2d70daca,1f0d1878,02748cfd,1e707ffe,8fe00659) Z8(e6d80f3a,b29c65b4,6fddb3ed,5847020d,578395ba,4520f5e1,34c26fa6,0cfd24cc) },{ Z8(8610cb40,ef5ac7c0,74a3fd6e,2ef90dd0,d44f2ce7,be000539,57af8bc6,b5ffc5d0) Z8(a8994635,0d1b3e5c,95a4be50,9a51f29e,00b0ebac,c03969ab,9ce221ce,0dfc6ef8) },{ Z8(d1766d52,3c9d4d00,98dcfd4f,d19de2a9,544ce10a,84887d3c,4a1a6eb6,00c86503) Z8(a07bc5f6,a582d3ae,c0fda8e7,6f59d19e,d0d2fcff,6b928efb,cf8c40fb,0efb9d4f) },{ Z8(4ef2a858,42521de9,625a4c0a,b1404b3e,6ac74803,493fe292,473e9b7d,d0249009) Z8(03c4b8ae,c387a9f8,f59d4b2d,1319c12c,c0e2e0d5,6cb2792d,967ef4e3,0ffaaddb) },{ Z8(311356a4,04dfff70,563610b9,5db92215,8f1c7737,74fdbeb3,665127c4,c6b9bf91) Z8(477b4061,6901c519,48fa3ec0,8cfb4ced,4ed8919d,fcb0089e,1d52a6f6,10f99ea7) },{ Z8(9ce1a4b4,050b6c31,eff0326b,655ccfe7,04d7c086,947dfc52,7fdd85df,f3fbc768) Z8(ce650b85,e438050a,1e15a474,529d558c,20fdb0fe,d447119a,082d58de,11f86dbf) },{ Z8(aa046358,42f420b7,f2798882,f832c092,b082f40a,e60a1616,5cf7d5a0,e392fa22) Z8(c0712f54,00e6fba3,518b299a,a22519ec,3003e5ca,7fa2ef37,8a4a9a02,12f71931) },{ Z8(6f670d1f,a5a33de5,c97d6dbf,8ed6a6f3,ee17ef02,36af16c3,6d3c33b4,078cb090) Z8(49818882,dc6b617d,4bf3790c,c9eb30fb,e11cd9be,1338a177,7c559d6b,13f59f0e) },{ Z8(69d09b1f,31bfc679,ee2f9557,0b1311ae,663e2829,b76dfb4a,4f11ad49,ab638665) Z8(e1e69218,3eef315f,ea17484d,e4d45ea9,2f3b2f1b,11a6c4c9,7292fb20,14f3fd67) },{ Z8(45a3b43c,3756c2f9,d997e93c,3bbfe2d2,f17a2f21,c0a38987,e97341e8,360e10c3) Z8(ad108b54,8510be0e,1c0afac1,735fa0c5,c637eace,a3691004,d2d7b262,15f2324f) },{ Z8(fe45558d,9314ca64,0abf3978,bbf07cdd,e13ab974,262264e2,2ea402ba,f6feaa8e) Z8(2d08e8b8,b14cd4e0,b1dd745c,4922f357,5e835fd9,0ff1aed0,ea4b0cec,16f03bdc) },{ Z8(e9ef63a5,f61cb520,147ccad0,b05362dd,cfc4eed0,c7006c6b,a4933246,45474c82) Z8(8c33e00b,65667e05,3055c1b8,cfc1508f,099f06ce,126acfcf,02f10e8c,17ee1826) },{ Z8(4a9522f6,34f12b4b,d47cc582,2566ac69,6f869e7a,38d9db2e,d5dfcebb,1b94fe5b) Z8(23c4c8d0,bd86f3b6,83909b1e,c78b7623,499750de,6510195a,78fb282e,18ebc544) },{ Z8(76b6d939,2b5d2c77,db955cd9,bb9fe797,dc3ae08d,07755f5e,7eb2f5a9,c1d8bf6a) Z8(24f4e839,8c91e6e3,727fec4a,9fa90ca2,11f8151e,ccb875a7,cfdcf168,19e94153) },{ Z8(6bfc6973,6d2b4b24,d2cb1484,fa19f142,597b7d78,a9a50ad8,00b991bc,ee882715) Z8(7981aea1,2c70ba3e,d88eba11,bbfe48a9,73b6e5bf,029cd221,c722b838,1ae68a71) },{ Z8(099335f2,7b563833,0f7d4806,ce55540a,9a97042b,bf2c072e,e10e85ee,91b36f11) Z8(68664f74,b1b0e0bd,d234427d,d21afca1,661cbb3d,ee3ca681,6f07c37d,1be39ebe) },{ Z8(42c48603,9e3f5b6d,c0aca8c5,4c94c1a1,7707b825,fc546c0e,8d2ed6ac,14cb3da8) Z8(5cb44d3e,b6d450fa,27c7e505,967b9dd8,314d28c1,71cc84b2,3cca3222,1ce07c5c) },{ Z8(357ca717,859d7037,8d550940,ad29bec8,4d65e896,46e04ecc,67d74e9e,028bfa2c) Z8(9bc0c871,b68ef497,f3435b28,910b169a,f95fab59,3bff35db,1eba6e65,1ddd2170) },{ Z8(7e25ed45,7953bff9,ca2d5709,2e37a5fe,bb6750b5,830963f5,b8999195,6fb3e1ca) Z8(76c0b90a,fd75ea0e,65679841,e9e36d84,c276a948,2d33d369,90043af6,1ed98c21) },{ Z8(57f08ded,a54d9b11,3e535f7f,abae7931,3c469ae3,a7ff4baa,403b384c,1a9a0100) Z8(bf6d82ed,5d926aef,2bb35b24,f1672afb,e7d111de,5912f313,ac2f6dc6,1fd5ba9a) },{ Z8(6a7adfff,5547ed24,14efc875,7df6d8e9,bee963be,793e76e9,2c350133,fce00e46) Z8(fac4ccb1,b1bc39a3,65afedb4,fcb8fbed,20176b74,e96be7f3,42567b30,20d1ab08) },{ Z8(8e763bf8,81217628,29474992,db4372f9,a57870c3,217f8cba,e62ac41e,ea493561) Z8(04a83365,86f87586,f8091428,4d87af78,97963968,72e72233,e8110314,21cd5b99) },{ Z8(63bd5bb6,362f0052,b4114288,b2df3ca8,29e9f297,84d054d0,7dbf0484,e2263753) Z8(c68fa69b,f93b0c5b,77f89387,62929db7,548d5e30,e774573f,0c10a0b5,22c8ca82) },{ Z8(d2620f4d,2c25d670,6a702710,7c24f7db,ccf5586e,f6876258,981f40da,d86815e7) Z8(0be90468,9802c41c,a7f00323,78a856b0,60e82be6,6f4dd64a,086e4dc9,23c3f5f6) },{ Z8(2299020d,7ada35c5,7d81bd76,0cff8011,41de86b1,3dc8067c,b5839fc7,5df2d3e0) Z8(999e0089,029970c1,103b7390,ad71a122,1883ce1c,36bdef0d,34a6b8be,24bedc2e) },{ Z8(80ea4d78,5352cf1c,78ebc7f7,82d4695f,412ef498,f23f2d2f,093a0e35,9135bb99) Z8(091ff212,e21eff2c,ac3c6138,b40fd271,54d14fca,ca1c1558,f743fe63,25b97b65) },{ Z8(94458a17,c31a5854,1c096d9a,c616945c,b307df04,e13ad104,7ec429b6,cd667d18) Z8(fdc4387d,3c856851,b577ec20,0b5bd245,d9ce2bd3,01458dcf,d733472d,26b3d1db) },{ Z8(be2d13b3,a4d22e76,c6fdac72,bb480a41,a8adca3f,de49b5b0,bc6aa4fc,6d60ea3b) Z8(d0a3c05b,132f0292,2eb74a37,5dd4bd3e,40d83fa1,d1d86749,8cc4d8b0,27adddd1) },{ Z8(e4774fdf,2fe9defe,653615f4,62f2a8a9,65ec851b,f242275b,d56d6f43,133b2b30) Z8(3bd019c4,790d4bc4,9165ca72,d9500829,3c5b858f,b29d9d2d,12553c8f,28a79d8c) },{ Z8(b24a7e09,a494772a,d2c966a8,630e9967,7c27bdc8,ce0f5b5d,201dcfa4,168365a5) Z8(3fcb54d0,71e7b47d,a602974f,85f820a0,8abcc1f7,991f8d6f,b49e2e8f,29a10f53) },{ Z8(72a10576,51f79d66,9871c02b,2bb9592d,6e8306a9,60b49f61,feffa815,78b884a9) Z8(c4f79607,f998a3ef,18607feb,52f68c3d,039baca9,14179442,22ae148c,2a9a3174) },{ Z8(70227d34,0d4661db,0101678b,bf80dddb,c39cd9f1,a4fd6da4,eb67c8dc,2514c715) Z8(f49ef530,07d8d94c,46c1ad33,0b4f9b75,c30b7a65,ad534ffb,7d84d3be,2b93023c) },{ Z8(7485ae76,eb2e71d3,d62dba77,953f1ebc,118ac689,bb0f3ba3,3b04b204,db25929a) Z8(b766dc2c,444ea8d2,c6d28096,18fddf54,d34c6f11,ac949883,6754e7e0,2c8b7fff) },{ Z8(bb7db1df,1ff62734,67d27ea1,b94ffed4,1e985042,ba26831a,78eca1e3,78ef8381) Z8(218ab4d9,1c29127f,79083c3e,b4ffb8c8,ef6549a0,aad627f0,1267b1b5,2d83a913) },{ Z8(0a561f65,da82afeb,700b6577,1b5a9ab0,64434707,fff7147c,17eb0d22,2cab1d24) Z8(0092d34d,a4c21996,77f6c0a1,8b622429,668d5f07,4bc24ad6,4fa403a9,2e7b7bd1) },{ Z8(54f8c53d,2a81b45b,08d5df80,e3546041,3f5c02f3,a2e0e37d,a1314740,65c41183) Z8(c79f5cb4,bc169a93,a0e28aca,e4eb4035,07271d21,1ec2d3e2,9cb6044d,2f72f697) },{ Z8(fefd4306,2bffbcce,bf0955fb,48f26c41,8acc7f96,8a388165,5eb3d2df,f9217c22) Z8(88ba6f5f,edc59923,0ade66d4,83aa9592,dbcc20fb,5bb33518,31d78fa9,306a17c7) },{ Z8(43bf3419,d021c10d,1d8a38a4,0645863e,0a7a037a,537477a5,f8da54e8,9ba2a914) Z8(a36d0e0c,eeb9d3f7,339400bd,a797d90c,9d85f2c5,39967e7b,0f385177,3160ddc5) },{ Z8(c89eb613,e5f60493,d8dce9c5,222f6b01,734adac3,37122f0d,41ef746b,df66b6f5) Z8(d621348e,784176a4,10efb2cb,bfd3e8e9,c4e1ec71,61097805,0a04e379,325746fa) },{ Z8(5dd19db4,bf646ff8,b1cd2237,a58182f3,1b8356ba,84f6edfe,64c501b4,3e50601a) Z8(2224cf0a,fc1796da,06f09d86,aafc4993,691bbace,ec03cf68,d90c4c39,334d51d2) },{ Z8(9079b934,466afaf5,cfd71a5b,1ec022dd,34bd93bd,88d7a6c9,993cb591,4d93ee4b) Z8(92927071,4e0f9b08,8664d9d8,8d8a7ad7,6463cf3b,083acfa8,21034b79,3442fcc0) },{ Z8(b893e1cd,482c2e08,6ee3bc74,ee743658,4af9b37a,24acd329,b140d9ee,9f24f2e8) Z8(75bd3ea2,82ec8d09,13c78e65,6909c145,542a8758,45df44e6,8064f287,35384636) },{ Z8(3cabd8ab,a9e22f00,da7b7f4d,4e1e1f8c,da1d0102,91d9eaa5,7d8052da,992be0f0) Z8(a1b814a0,3b878193,180edaf8,c9f4e6ac,6633f48a,951c0fa9,9af0179e,362d2cae) },{ Z8(2d953efb,d5f2f22e,9be36135,1bf788c7,bbace5d8,2a7d62b5,137701d5,10c6abd0) Z8(5fe10a3b,55881bc6,4e92c495,a19144a3,72d54bc0,bd886970,24c14408,3721aea5) },{ Z8(0b5cb505,71bcfb8f,a2a3c8ee,f32ad755,08bf886c,f2b6db3c,4023a354,f78257e7) Z8(7ff03acc,0be927c7,30228d39,92f30bc5,c9213bed,99205506,ed08cd7d,3815ca9a) },{ Z8(34995f9e,88ba3848,4b3757b8,05c7d432,efbed4bf,35845ab6,94f88a29,077a90b8) Z8(546b7e08,630280dd,c23af573,969f79c2,5766d521,908be5f4,e85cdb9a,39097f14) },{ Z8(090fd641,ad8c32cf,63714ab4,097865dd,e0ddcd03,60822f91,fb49c059,e497e262) Z8(3459a44b,5c89eeb2,1f847c4c,cc23f3b1,57dac766,dcd1fb8f,3aa72aa3,39fcca9c) },{ Z8(9ca4c5cf,f96efef5,843bc77e,c4a7522b,d7ca6cbc,b8c3e75f,560f6205,1e4e4bd1) Z8(8a276c06,79b6867e,80cbfc01,ec4b3b0a,cbef5e39,2468a9a2,40ae6ce3,3aefabbe) },{ Z8(b98a4ead,adc8eb8b,c9d1ce7d,673a4f94,aea9c1fd,218a01d8,bfd09321,ec406449) Z8(7110586a,1d0cbb9f,8b7a73c3,1c68abe9,b87f6509,7e74ac40,993b3bea,3be2210c) },{ Z8(4c43d654,590f749d,a1963ac0,de5c3e82,c43b6c29,dbdd37ed,8e027783,aa643149) Z8(0111d1fb,139179b4,4bff91cf,33bf6daf,bb281a07,3591014f,2dd89ac3,3cd4291d) },{ Z8(2319461e,f74f7152,262ecbdf,70131b7b,7eb36fcc,aa5d2e4c,b28a09ad,0999f94e) Z8(29b1e0f3,2497af53,b3d6cac6,91d7dacd,15bd423c,623dcee5,3b301999,3dc5c28a) },{ Z8(c0e660de,83d070ea,c1c793e6,8f0af089,e960c68f,c16fa316,9a395d94,64ae4945) Z8(251269d9,de8e9d9f,e22ce0da,6a9fea40,7de885f9,5b71e7bd,5901bac5,3eb6ebf2) },{ Z8(df555015,378f9610,033a32f8,b833470b,23384f63,c85b09e5,d48b6bf7,ed31c80e) Z8(ac347d38,df4f7199,b5d98d16,344f7ea1,8bd4f2b7,e28de743,81b7c826,3fa7a3f8) },{ Z8(22decba3,701977b6,36fa9167,81d25d92,dd26f167,5522dc95,4bd301ee,da5fd8b7) Z8(3ba76182,3eab212e,ace22cef,129d011d,5b85a52f,d2097cd0,1996d698,4097e944) },{ Z8(28c40514,aba26ad2,8a92b443,72170444,0a7d5cc4,d8d8727b,623ab47e,7154472a) Z8(3fe7098a,065fd18f,1fd4d38c,ff1fddaf,79fe16a0,113e49d5,f58a43d4,4187ba80) },{ Z8(fb2f32e3,fa0c0020,03fd1ec2,3eee4573,233656ac,b8e6b642,29fdcf5e,2e0b4533) Z8(02598228,742430ca,5b7e82d8,57128550,8655e9d1,e47390cb,618d8962,4277165f) },{ Z8(59675195,9ad2f74b,cf06beb4,50642b58,1adc2f84,743bdd77,b1b16b22,ec1f1489) Z8(77ca6b77,7e0be081,a05e2e0d,9af3fd40,3eae0bb7,c317bd5a,26b2cd47,4365fb94) },{ Z8(3636b048,a33d4e80,46d3bb97,267acb9c,8a97f939,65b54ac5,c0ec8aff,54b319bf) Z8(0d5e882f,876d4fea,ba0a243d,979d9a18,4613c81a,37236f88,90c726b2,445468d8) },{ Z8(2529bc52,f9c7fc1f,df3eebe6,b9e119e0,19c44f0d,930186b4,73a6679d,3cd7e9b3) Z8(48b7628b,3f9c4f95,002dbee3,4bf1726d,cd86108b,94580635,73951a86,45425cea) },{ Z8(3baa0802,9fcc00a8,e76734f4,56bac311,ae28c340,edf331ad,b8c8226d,28af6d95) Z8(a8450274,e5275dd6,e0d27de7,87e9714d,dfc414c6,6523a458,2fc5e098,462fd68c) },{ Z8(50c6afb8,60a79116,2b5c8197,07ee3283,72ddb269,229ef969,daf9f7e5,74b2522e) Z8(2de95dad,8d89bef4,f5b9dede,1131740e,86926c0d,329c39a6,b7620f41,471cd484) },{ Z8(4dd696a9,b4a3d209,e00913e9,e6ad44fa,a508fabe,e0ced958,b2094c62,b4e812be) Z8(45146f9c,15f20819,a06064a1,f2adf0ae,b78ccc11,e6e6b85e,91f25773,4809559f) },{ Z8(f2bae5e7,02a7a010,e216bae9,8871efae,3984042a,e7d92cc9,1427cc25,a7e8b5a6) Z8(9244ac7d,a985fa7c,4564b2ac,a0d090cf,fddebe99,b3a3a77f,e041078e,48f558ac) },{ Z8(f2dd3af1,4c887024,12f70f05,39a8dac3,94ce672f,51117749,d4e2af6c,77550ff3) Z8(3984379f,3d78b33a,906b1916,223e10cf,37f0a23d,8322c920,5fbd16f8,49e0dc81) },{ Z8(03d08a38,29a0dfe2,3058331b,b3c57771,f126d3e2,1e2ac1d5,84402d2d,3db4bbcc) Z8(fb74bd3d,bc11d84c,adec4ef0,f4cf1a52,6a2148aa,11e7e0e1,6d7f880a,4acbdff6) },{ Z8(57da08d2,0ca9b21f,0490a8a7,fdc85778,30017bc1,f1156669,d7bf2f67,62a6a1b6) Z8(e91ef2eb,ad4a61cc,4c2b9c5e,4f9e3ef2,964d0de3,892c7500,08f3f8dc,4bb661ea) },{ Z8(770054a9,7a1f9e42,98d14a85,93ea8da9,bf53f41a,de9d1bbc,6c80d44b,c3d2211b) Z8(6099f013,c7508825,d9a44682,a1f7c145,0d0dd218,a0f566c6,d6254656,4ca0613e) },{ Z8(97b49c80,dd8e02c6,cea6a96d,82674492,34643a2c,22033f7a,54eefbf3,699c6992) Z8(098263d7,fad2c806,8597aaff,045247c2,693d7994,e2d5da4c,1faf2f34,4d89dcdc) },{ Z8(76a38a1a,2f11f89f,877048de,240818a3,89c0247f,c63d814d,d985053b,48467703) Z8(ca70edb9,782a220b,e8ac86ab,1aa6b1c0,8ec8b08a,b25a5deb,d855eed0,4e72d3ad) },{ Z8(02d173c9,8790271e,3501bc05,588deb89,58a2ceee,8f40a28f,2c8e4f11,1124fb44) Z8(45615e28,83aa88d9,2b34e36a,98e65edf,589e8ce1,7ca41cc9,9c44d113,4f5b44a4) },{ Z8(9e6aea05,577638a0,eeff1be6,27bbd86d,492e65af,4c11bf3c,c80edeaf,7f10d8bb) Z8(17c27be7,55cb0d8f,e2d0c07d,cd697057,aedbd671,37451ec4,b1f4ca4f,50432eb5) },{ Z8(a28e0832,452f7370,3a4907e5,6c3e7633,4f3b5bde,cf10222f,26cf7aa8,ed9ec1da) Z8(e7581db1,ed22099b,1a2ec305,a7413c52,c45c6cf1,a1bc3aa4,0abc26a2,512a90db) },{ Z8(6f119a02,3defec71,d2913050,79601507,cdd18d9f,cf591d12,d3011a20,105eec8e) Z8(1427073e,c7d9a717,620f7a38,cb14d6ea,6a594645,28a7563c,43086d1e,52116a13) },{ Z8(5e042655,3557bb3f,6afb9122,1ef1c3c3,a4ff9e4a,e67e2aac,df3f25c1,21be8441) Z8(bf14c376,1792cda3,0866191f,0148a6da,c549d5fa,91c41eea,a2439b0d,52f7b961) },{ Z8(3d0026cb,528f518d,62a07664,be7904d7,ea71b5a4,04c9f360,8a9d28d8,221a4e2c) Z8(5b969c3b,e5399f1e,3089501d,587c4cf4,bbde5d5d,978c2003,1a65e39a,53dd7dce) },{ Z8(0e6d9a49,5ff2e209,61977292,daab7c7b,5e61c948,921dd49b,f930a1bb,707dd4bf) Z8(64f8f15b,d12e94ea,8f7a6be9,90961ce9,fbecf460,4cdbfbbd,4735276d,54c2b665) },{ Z8(25e6c1b8,d83fd3f0,87ab3042,85532e9b,106992ff,a12d0234,6b86a9cd,a3db34db) Z8(2d523e88,30a5e599,344c5a3e,5dbb882d,80ec7a65,9cf0c761,6d335f00,55a76238) },{ Z8(6e025da0,1b78b36c,1e7e0940,fc1d3bda,50b809cf,474c9ff1,189c2701,9c6bc20a) Z8(752d7e37,06eaecdb,6dd4ab0b,4eda313c,45741deb,b7a8f82e,783d3913,568b805d) },{ Z8(304351f2,6e34c8c8,b5ad91c6,c630ba0f,5db2c0aa,2a79d9bf,b7e3253d,aef6afec) Z8(50f634c4,2d070093,e7595d81,2cb9c490,bece25fb,0760dbb7,f9da34f5,576f0fee) },{ Z8(0f733f06,2cac7ee0,5888957e,51b401c3,1940ee0f,cae5879b,1b7c5ded,d7c10300) Z8(85005268,17eef8f6,4bd6b6b8,5a042e6f,100507e1,da8ea8ee,273f8658,5852100c) },{ Z8(b44a8d24,4327c217,6b9a5b84,d851301b,afa68266,21121830,6e932e61,3d6bd9c1) Z8(b0168cf2,9f5551d0,7cdbc7b5,848af963,242309f5,bfc183f0,d7071605,59347fd8) },{ Z8(6f87aeb4,ee01cb6c,ea24f1fa,faf57913,583a91b7,e4587223,4c5613e3,b6029dc5) Z8(36db9b4f,4038daa8,d95a515b,b58574b2,4ac7b49a,50fd65ca,7e9bf7db,5a165e7d) },{ Z8(d90bccf9,4287a50c,b71f178b,48efa71b,8c2a57a0,dfd7106b,251beac4,12e22eaf) Z8(dc549a6b,7711076d,a1ec768f,576944ac,5f6062fa,8ea70648,2f5db396,5af7ab27) },{ Z8(9a49ceae,243ead56,bd7d0d30,430b7703,0067b9e9,6e667254,1cfee06b,32662c10) Z8(19a48470,2399f2e5,d72a2ae6,9ec21cbb,6e7f2241,c5519091,937bc239,5bd86507) },{ Z8(14f80159,e6ccbf07,701bc5c5,c32a6518,36321b87,440cc956,57743f3d,938f993f) Z8(cbaa36b1,596df9e5,bf97b157,3df5116d,d8431518,36cb1860,ea8aa626,5cb88b54) },{ Z8(29dc33cf,625346c4,453bc84d,726767e2,967af23b,dadffa83,f43782dc,aec2918a) Z8(8ab750c5,5f8ad04e,98a66691,e3d8a986,13fffa13,5dd0dc67,05d407c4,5d981d4a) },{ Z8(b7bfd931,50a00100,2cf08293,1feba957,067f1ca5,c7a63e5a,fcb1fe12,5a0c8c03) Z8(e95b8ed4,7b4d1f80,74be0aa1,e2ad83c4,b0366780,ba09d077,4463440d,5e771a26) },{ Z8(475b86cb,714c74d2,34fd2cc9,ba326117,89478ccb,47d65dfc,bcd20a64,20529daa) Z8(1e74ec59,cb1fbef2,af2efb9f,12e09e0e,49a08813,c885c2b2,8ecfdd69,5f55812d) },{ Z8(4764d731,38c59383,eaca59cd,9d532dac,8362d5a5,4c4a9cb9,c9b18029,4cbfbbfc) Z8(95460575,909b7c56,372f9424,618c28f8,5e6cc5ec,606697b0,52c74218,603351a8) },{ Z8(84593dba,6a7d6ee7,e3e4ad23,76a48da9,dfb5d55f,c6eda544,984107ae,ffe7ddc0) Z8(09e11aa8,2aa1a59a,88d4dc13,8175a01c,1b5c3a3b,6a0299b4,7e575dd7,61108ae3) },{ Z8(d01d74db,c6b20f39,99972886,a764abac,199f972e,c1604fc3,e4d8d932,6e4b5b4b) Z8(fdc2df8f,67335fd6,77386fda,d580574f,8f0b9465,3055d05b,7afb6e92,61ed2c30) },{ Z8(b3ea0e6c,eb9e214c,9b5c63e5,be201df2,9f125b1d,a348ef4c,3a18f632,e3821dd4) Z8(d849a43e,413ddca5,869d50fb,e25be4f2,fa85146e,d0ba3748,286c95b6,62c934e5) },{ Z8(d3b5ae4f,8c26ef59,fcc501fb,d7a15f8e,24d8b216,95698578,6b6b5a93,05873f7a) Z8(49201fe8,d2cde838,eb360681,ee0dd669,afaf4343,0a7e12bf,d737a14c,63a4a45b) },{ Z8(af819db8,27cc0e8b,77406e1d,58b65e04,6806ec47,23d487c1,985febcd,9f56e7a5) Z8(c0bd6eb7,37a7a057,8b92df5b,37d32124,b536bec6,74188054,43198910,647f79f3) },{ Z8(c4a57c93,7e0ba8e5,c3147f3d,9832b084,2ef8bd4b,b859bebc,368062ab,4595f087) Z8(ddb0a5c7,7c311a23,68afe4fe,973e149e,795af8a9,80a9bf05,8d241ccd,6559b50e) },{ Z8(a7a7ed00,2d503b1d,f9413e9d,860ab793,bda9e833,ae70741d,11a5a672,1033627d) Z8(6dea2a48,0991b337,4410cb0a,c93d002a,a76cdbe1,6c988fd0,35ac619e,66335515) },{ Z8(74ba887f,c9afb778,dfec5842,b07edd48,3f8ba4fd,9fc246c8,ef5e863f,8178c086) Z8(106f2c72,46f78781,ef24abd8,29c10727,19f5325f,cd2c044a,16041c36,670c5973) },{ Z8(1b4a3471,48b7ba24,f3fc02a7,55afa598,71e79e20,f5eb5b4e,f6c1005c,8ab8886e) Z8(0447819e,847c5e96,03790b35,995f498a,c6581a7b,d8fb836b,5a000637,67e4c198) },{ Z8(e77539c8,68562ed4,fc57391c,59c264ae,aac58955,fee46f9f,ed5d01f4,c5f7dde1) Z8(ddbe058e,86690fdb,4831b491,67288190,21ac153c,5357de5c,794c2c60,68bc8cf9) },{ Z8(d6fa02dd,e1150332,dd66ae64,1b924c6d,29bfb62e,7bcb42c9,5e2241da,142bf420) Z8(89eebf14,1333bfc7,90b0d39e,3700206e,800f389b,213e4af4,308ff2db,6993bb0f) },{ Z8(94bf4f0e,7b8086fb,2defd0b0,3d6c4d16,0a589d30,4a6c6b43,17dc5859,40778929) Z8(7808827b,bcc0fc99,c0d45d26,c3f91d5a,b02d4a70,c85bfeeb,7a633c25,6a6a4b56) },{ Z8(c32677de,0e0a6de9,5ed2e794,ea7accca,62ee5c79,d073f531,b881b6a8,900ae95d) Z8(e3d8c4f6,f93f9ea2,014ae9c2,0a43580c,2e7eef7e,4c33891d,88162dfc,6b403d50) },{ Z8(437438a6,0f2a8783,b90c6c1a,615f314f,91f8c2b8,f04ae752,cb1ccde1,ddca2001) Z8(073ec382,6f139339,4d7b491a,ff35aaf2,baaa6bae,ec6b9c9c,ba4d0e6c,6c159082) },{ Z8(dd1cd9a8,427ecd17,a4926cd7,12095bb5,b8818fe5,d88cfb0a,e11bb506,f0b41878) Z8(aca1b3aa,6469134f,5fdb8226,aaa4088c,04031a2e,187b1ca5,9971b1ae,6cea4476) },{ Z8(f7709642,e32fc2a6,5bd87952,ff1590c9,73805eec,8ff03f2a,8f7b787f,1362259f) Z8(5d0457a4,e9c8d9f8,66ff409e,cd7949f8,863d50c8,6b2e6d9f,cdfbef8d,6dbe58b9) },{ Z8(0a725b29,c4e1a3b4,cde99b80,170485e9,45352e49,b0710485,bf4d1599,c6adc4c4) Z8(aea48300,19d62e63,d14d7353,c1897ca0,afe929ce,9a1b46e4,18929551,6e91ccde) },{ Z8(63964ecf,9dfb0b22,7c87e071,5b694f4c,4220370a,1a07fadf,1cd9af6c,4bab502e) Z8(585f6cf4,e8c8fa9b,73fc6ae7,9b4bded1,499b6620,eabc6509,4a0646b4,6f64a079) },{ Z8(49edc149,519673e7,5449ded6,6b947146,85651cfd,4fb13489,1a4d4498,56ab8ad2) Z8(2c32a5bd,ca859f5e,af9f5c11,db0a5f97,3cc65c01,e318f6cb,3b27be33,7036d325) },{ Z8(4a5df35c,9239d401,8730b4c8,3d7f72ab,d27e2dc4,a7ea6eeb,43250ba3,db58ee60) Z8(8080388c,11f68129,f5c2a636,68db9c1e,1123a708,820bcb4c,c47ada4e,7108647f) },{ Z8(4333c295,bd5631c6,658660c8,4c4a28ae,77bc6aeb,1f808d6e,6b31ca45,6bea5672) Z8(e9a08658,d35aa34a,6ae7e565,bf8b16e6,c1b87ea7,474008fb,b5c7e28b,71d9542a) },{ Z8(82e2ec1d,d416db06,bc4abe7c,a879f9b2,19227bed,fff14938,122e4bb8,7e21e4c2) Z8(6a18dbad,3e38f152,98792e64,56193985,b7a3f6a7,a833c0b1,cd8c6c0c,72a9a1cb) },{ Z8(ccebaa1c,91743da4,920b5c3c,a83eebfa,52c38f0b,33d0ce87,e08b7c3d,eb573dba) Z8(a0f59d94,0581e081,9e7941da,32592743,e536e164,305bbe70,b04d425d,73794d0c) },{ Z8(ddc9fe3a,c78f7735,92403ebe,3bb34acf,978ef7b7,b32ebc64,7f5291ec,3b05f640) Z8(8ff60eb0,aeeb3ba5,e05d438e,cebb3f7c,c302bbad,67835886,dfcab5be,7448559a) },{ Z8(6f7384b3,4d955938,7ab24ad4,5c3958e9,8e89004f,41da4ad6,535b540d,29ed1da8) Z8(43e8a4a7,9b8814c1,6ac5248f,69ae9416,c969a4a3,a108b1f7,b218acc4,7516bb27) },{ Z8(c9b2e941,195d1f4f,07bb1dd2,57fee8e5,18e3b139,2a0d8694,e3dd84e1,46fc7a78) Z8(01d2b559,f1615af4,dffeffc8,cb45b4d2,ac4fde79,f40ad24d,489bd35f,75e47d68) },{ Z8(431146de,eb6c2f1b,7e9e0009,6770f407,635230c1,43e4097c,c495a8b6,fd4e2c8b) Z8(74b12384,71678b73,930e6f80,b70a0ac3,5e1d4681,b7f222f6,86ed3da2,76b19c15) },{ Z8(e662917e,9e0ec0ef,0907c7f1,da84ef40,402f4c8f,0af8dc1c,9bf339eb,85921141) Z8(af19971a,95bbedff,83071db2,66efb530,912e14cb,ddd86050,09a5d0a1,777e16ec) },{ Z8(8f301d8c,84061563,c0543a9e,9d5d24ba,694af72c,173f4d3e,b37db4f4,43207a63) Z8(4a4bc94f,0c7167a7,f5fe0764,c787457e,ad55185b,3d9e719c,1d12bfb5,7849edac) },{ Z8(23c27c08,5313f7c8,80f03ecc,961ebfd5,bb5b14fd,09c4de93,7357a853,99b0e98a) Z8(4b055120,f8f29187,15d79e70,b11e90da,31e3ba15,4754259d,b3d46827,79152019) },{ Z8(3e6d54cf,6ba57a5c,cbe30ddc,04ecd0e8,93713515,9d0680bc,cf53d409,f87a0d00) Z8(27e899ff,eca3443d,402ec723,1790505c,4356f9fd,53dc1bf3,5d68d10e,79dfadfc) },{ Z8(f87500ba,5474f21d,33580869,65bbadf1,8a142bce,aedbe52f,0191dd6b,2082bcc0) Z8(80c7e3e4,2fb06843,0030dbc8,759edd0f,f82b549a,d967651d,3ca31097,7aa9971f) },{ Z8(e39aaf8e,a8999886,1adbf4da,55ae1bdf,ee452cb3,ea24fe10,118640d9,d9dfa295) Z8(d9859493,c806ecee,1b2d1a22,2c085d46,ec71326e,da2733dd,fe10d380,7b72db50) },{ Z8(38294033,a9a1152e,8275ef25,852f8923,047f8b07,d14dd4f5,31892a2e,09191e58) Z8(7dc1b9f2,dbf97fce,ffe98dfa,3efac40f,76bbe518,bf57834e,ce4f3ed0,7c3b7a63) },{ Z8(a6dc9901,215b810f,aab03c7d,c83a92d8,c35e080e,12df65ec,48c26c43,66ce6be1) Z8(09041335,b190087d,c5c5aac1,0806496f,aee47661,33691e3e,50505f2e,7d03742d) },{ Z8(b5a84f4c,b14dcbb7,9c52349b,6cd9771f,dcf4e3d9,7ee70918,d7aa375f,cd00a912) Z8(ff5371ff,a47f7e70,f26bdfdc,b9b4c8a2,dd004a57,27083dfa,93925452,7dcac886) },{ Z8(8a6a9f68,e5503922,98887779,82098553,e385fc82,14e05ec1,4d9894be,9db942af) Z8(99073e71,261a128e,b5412874,e6b4f66c,74b5310e,a9c23d72,0a496235,7e91774c) },{ Z8(b4fe5cbc,722959ce,c3503ee8,ab044b99,598a7168,8b2b9c42,261b465b,1aaba8ac) Z8(feda3967,17f74800,2228a703,9f93b5a8,d8a9d672,43d8f624,7f7e0c9d,7f57805d) },{ Z8(4efbf7a2,1a64cb22,0257e174,c3051249,c455de90,764e5cb1,a7a15c3b,434e6df2) Z8(9620b8c8,02f253ef,6fe2e1cc,69248632,4d938596,a6d6c6c5,0d205c99,801ce39e) },{ Z8(07722634,a680ef4a,25cddb51,f39ef511,6bc2b670,78f85250,cc9f220c,3109b636) Z8(bc199b54,0fd151a6,29b08174,ad73c708,1dbb92b1,689f9952,12116a7b,80e1a0f4) },{ Z8(840d4673,8c1d097b,d2f21932,527a6c07,02ef04a3,db10d86c,4db415e9,5f3b5ceb) Z8(e55e0781,3123f517,630bb75c,c9474f20,40ff5431,9b38d855,2824418f,81a5b849) },{ Z8(39a87e0a,b622442b,d15d449b,82fdded3,1927739b,26ab519b,510f33bd,a76401d8) Z8(6ed19a9c,3c042abe,88082c6d,bbff43ff,131d6a27,f39377a7,1a172dc6,8269298a) },{ Z8(f42af382,6ff1ea97,53ff817d,8e2871f5,d4bddc24,82c3bd5b,d4f13f4e,43d7d60c) Z8(1e5b65d0,55c6bdcf,774ddfbc,f1155cd8,61a515c0,4b6a09cb,d9867e2a,832bf4a6) },{ Z8(6389bafe,e1fbcb45,482aba2f,147fc691,5a107ad8,54615597,30d93e05,6051dd25) Z8(e2e7ff89,cd470655,797b9e09,c96ba6dc,0ac73920,0c9e0445,74d9c1b7,83ee1992) },{ Z8(7093de76,2e18760d,12a339b9,949a98ec,23c448e8,d49a7e53,6880ee04,2a95ee24) Z8(91a471e2,9e3f429f,5c56d4c5,aea47210,60d2aaea,e4df5ea5,0d2c7eed,84af9843) },{ Z8(6bc3c871,89fb68ab,551f7fa4,a7123346,cb93c484,ab8012f9,98005332,ba3ed0a5) Z8(4e7886d0,72b5a073,c037a182,75d49076,45a53e2c,5abf2de4,cc336107,857070b1) },{ Z8(b9515c90,0993b796,ebac1443,f6a5b3b9,b87b136b,c112f51c,9bd67954,45f54651) Z8(9cf54cc7,ae8bed89,94553290,92a950da,013ca37d,d3e84ed5,da1ed065,8630a2da) },{ Z8(cc6c4d2e,f66afd88,fd5036df,e4ae36b3,f40586d3,50ce16ac,1ddad3fb,c8e74cc9) Z8(7e4a61d5,208981dc,33c397b1,7c75090d,655622ba,97b4e3ad,537be67c,86f02ebd) },{ Z8(55e8c864,a1a5dd2f,3d4678f4,badcfeb3,33069252,d6dd6a02,82e42791,a2a7f4f8) Z8(1f428f58,2dea9c23,f150f32c,9bdd6bf9,4c868142,988d8bf6,3f14a800,87af145b) },{ Z8(240ab993,21e5977c,45f2d543,b3c1550b,a6636083,d0d0bc8e,37fe5a4d,9d410539) Z8(1a5e9ca1,c7b58739,98c02cf7,bce1325f,60af9f5d,867a898f,83d06ad3,886d53b9) },{ Z8(edb50f83,998d73c4,b2b51bdd,f42337e8,dfa2ae57,a2d08b4a,e396f760,31205dd0) Z8(65ff600e,28c0a22e,b9ddf67f,8fbe7b9f,472b4afb,094478fc,de9547b5,892aecdf) },{ Z8(c7e3a524,d43f64b0,e4b281a5,ff14350a,e7842a54,f607f342,3712644c,075ea1ea) Z8(a75b251f,f400d02f,aa77cc19,b2e59eef,a6f989c0,21cdf87d,d82b7262,89e7dfd8) },{ Z8(76f38bb2,12499354,a97d0535,f2d8d29b,c967a295,26225539,be81d9a5,458196e9) Z8(dc4a203b,b5fc0254,cfbbf3d6,fe76f7ec,879e8439,b0756e81,bb234d68,8aa42cb1) },{ Z8(c7832c8a,470d80d1,36ae3e59,b4b56564,9cb81009,299f56c0,9c06b113,4d37e8ad) Z8(9410115c,3f549952,ba02bf4d,99492cf6,d348634d,06fe141b,89bf0996,8b5fd37a) },{ Z8(23f2825f,c4e88cbc,5ff1e675,c7dd9b3f,88ad45d8,2a2e149b,a4a934c2,b8340b68) Z8(40364e6f,ca922e3e,0311ce06,f8e24449,60205920,439d8018,f3e09b8c,8c1ad445) },{ Z8(5083a8c0,943f5994,ccbc2484,2ae68ede,18f0d470,04c22fd8,40643c32,082c4f3d) Z8(86dca7f6,2cdaf3be,148f8aa6,8709d0f2,f9602b3b,f27a74e0,4cfcccb3,8cd52f29) },{ Z8(cda61010,9f183483,c877ab70,c488b568,12013d43,78a9fffb,e44976ce,8e0c22bd) Z8(4938f386,33d3ce86,5cb6dba3,dfc2b861,86b8a2cc,0b9ba883,8214276f,8d8ee43c) },{ Z8(807bdec7,b1171923,9d86e4e7,b7ed34dd,6b92045c,94ea9a9e,bf30f35a,adf93983) Z8(9a989102,94ca7636,885e59ba,ef9cec1a,929f8ecd,bbc9d5e7,0fb27928,8e47f39a) },{ Z8(a4333141,358f6440,7e523acc,29c4ed1d,073d6a58,66cd7dd3,918d712b,3669dcd3) Z8(13389eb2,f53da46d,652b375c,918a67e0,65c43747,5c835e16,f7f59f9b,8f005d5e) },{ Z8(63e1d8e1,e8e42d7c,9042f128,dd2e444f,1603e75f,3058e42f,31636f6c,b33adb8f) Z8(42aa3f89,6573867f,0e1ca0a2,b668d877,d47136a9,659f6d7d,b89c516c,8fb821aa) },{ Z8(ce01728d,0e32ee21,4e6ce066,1c8982a5,d8ff20fc,9b146e4e,f0d6ffa9,d44568ef) Z8(83f80434,fd954e72,419afea6,99f0a484,17850ab5,c5158289,411d8d0d,906f409f) },{ Z8(e822775f,8b370708,3cdac35e,ec0fe759,a3da5238,af657582,0c778e51,9f4f2fe1) Z8(28bd151e,25831acb,2051239d,b0b51d13,1880f6a2,a7bf114c,e8c953ad,9125ba60) },{ Z8(eda72c13,9f6e7953,2266c690,3994dadf,3eb0fb42,3ce54313,ee48c390,684ccd8d) Z8(06efbe97,6758f20e,fc353437,d995e8d1,126e021f,10e4f9c1,64f350e2,91db8f16) },{ Z8(ed880dee,027094cd,df0f70f9,2f3faad1,eb8a284b,f1315802,0716dec0,7dde84bc) Z8(86dc7ba3,24b7bedc,21bcbf2d,ea50b3e7,f3797d76,5511836c,bf280aad,9290bee8) },{ Z8(bced7f0c,222db398,a1106e41,de6c8285,3ae6bac9,303e8468,33e3fa3e,bedd38a6) Z8(feeb773f,aeaad9a7,c291b97d,c4db4f92,cf31c981,4d228131,4b6d3074,93454a03) },{ Z8(4aa2a382,e919b46a,0a1ede39,b4a83e2f,0747ee2c,78fe9f00,0275deba,2bfa01d6) Z8(4af2fbc4,d6a43647,f77c6d78,573dc02f,b3e2ecda,7e6c2a3b,9e8d9a87,93f93093) },{ Z8(0f2476cd,3ea57fe0,9fc8cdd2,307f9223,2342e027,892aebb8,b97e806e,366dbce1) Z8(8031c786,2c6b9f78,7a945eda,f38ae0f4,f78a32f8,18c4f393,847186f6,94ac72c9) },{ Z8(63d15ff5,02013b67,07e2277e,7d4977f6,3f6257a1,5faac905,3f5b6c6c,535e0730) Z8(6c550ef3,6e81047d,00ec6abf,748dbe47,45c3b111,180035a0,f6839b85,955f10d6) },{ Z8(a3017dc3,57075bdb,65b5cffa,51d623a6,72d045fa,17d7f06f,3e6ac2a3,4fb92fff) Z8(e59cc3c6,2595a117,94878366,49af3b91,683e2686,8fde4b8b,12232fd6,96110af0) },{ Z8(0d2dbc3f,7b980db2,4da61782,b8117ff7,de78a0a8,9654eff2,07b54f2d,04d4dfe8) Z8(ee5ae7c5,fbc20be4,62212fee,1fd293f4,afa42aa8,abdf5c91,0f245e0d,96c2614b) },{ Z8(ac3ea703,15f83a6a,b6e2a678,8173f3b2,cc921214,048b1a46,b871bf60,23b240c5) Z8(874c64d4,1faf20aa,4070578e,9798db27,f1aeb6b2,abd3fe19,365e538b,97731420) },{ Z8(4d3a3819,19b8255c,1683391e,986431aa,42ad7290,cbd555f9,a572d976,66cb95ff) Z8(b81de37c,1481e51f,64bdeff8,d14fc582,70cdba0e,8ed9e25e,d84856c1,982323a9) },{ Z8(efb7193c,d8a3ab60,074e1526,0efeead3,86d83c22,51c3add7,8b483675,84a48c05) Z8(9324c0a0,25f3e25b,999fc0da,fdcc108f,84892a42,9570f4f5,43a5f281,98d29024) },{ Z8(4de30a78,ad5594ba,183f9d16,0ac0a9b1,422cd579,20c62241,a9c5d9f0,d675d8ed) Z8(82d42a04,d521c6db,40b7b8af,593e8d1b,05678ad6,a5db0f75,bc42b2bb,998159cd) },{ Z8(1408e1ac,e9e70d29,9c44fa81,098e55dd,966bda9c,11620ae2,b74ad88f,4ccdbfe6) Z8(753afee4,77874d1e,17489d5c,dae46f06,204ff3bc,4226f8e2,71bdda20,9a2f80e6) },{ Z8(fff62941,d9ec50cf,b60a89e6,218780ae,0a167aca,aad9c242,b4e2ea0e,c496ecf6) Z8(43eaeb9a,643b5497,9d7f9d9b,6c03d1d8,172b7099,7433726d,766673c7,9add05b0) },{ Z8(cd48d3fe,ee73c1d8,ca15bc11,dcef5ee2,91d4f19a,e221dcf0,a60d5850,0aa57e64) Z8(25c95530,e01aa734,dab7679a,c5daac0e,7e4b6dd3,21d87f3a,b6281fac,9b89e86f) },{ Z8(359c4d88,2f36417d,8891df0e,03cc7481,0bc7c353,581ea595,4cdf5cc3,c5d14036) Z8(1d43e268,acbee350,6001e35e,e9293001,2bfbda16,e3c68283,ed88f490,9c362969) },{ Z8(252cd617,a95e1a5a,a36cef1e,f026319f,d72640ea,34d63cad,6cacdafa,c5acdb52) Z8(60d2cff2,f1e5725d,b26e793e,5a2ac6a3,174cf11c,f799c4e8,a0b8cdb9,9ce1c8e6) },{ Z8(f4481be3,cad840e0,b80a576b,a9998dd2,5ab03b8e,86e84f41,da8196d5,61ea308c) Z8(5ef33dec,eb87c63b,2e5585bb,feebfb01,d5420d93,6dde0f8a,12b256d0,9d8cc72f) },{ Z8(de7b447a,b7713e78,6d950e93,ecb6accb,4b2226f2,12a70377,360e6a28,161fda6a) Z8(54b2ce86,8c9ee65d,57c9913e,394f7ac8,8b128b9c,75ed605e,3c6e243d,9e37248e) },{ Z8(68ffebd3,664860bd,e3fc4e25,149bdb56,a5236aaf,875ccc16,0d8b79ad,9141cd38) Z8(51631e66,af09eda9,fd8b9437,925a09ff,2e1dfdf5,cc6e1e9d,c4282259,9ee0e150) },{ Z8(2c6123c8,149416e9,ed899dbd,4a8dcdfb,67674a8b,2837a0dd,77858f46,db768830) Z8(1c6f4dfb,00a35bc2,c801acaa,9d743d1b,4f0701df,f8b49264,f4b7a1ec,9f89fdc4) },{ Z8(7c231566,a8bcb9cc,4e31a5f0,de76ccd3,f1dd3e6b,7c4390ae,850b9376,99215509) Z8(ff055c49,570dac4c,99ca96f1,912c563a,a9be5a70,4ee0dc81,b4fa44aa,a0327a3a) },{ Z8(280167b1,0104baa5,be0760ad,70db77e1,524c029b,3a9aa868,5d2c3b83,dfe1392e) Z8(ad2e8823,33bc2432,f7c63704,39662ecb,b28ec568,b052993b,7f52089e,a0da5703) },{ Z8(dfbbbebf,89642133,104858ef,60a29d7d,a04b0820,9a50d136,ab6b4b52,c54d6eb8) Z8(85ab70c7,1031ccfe,017e3932,f0f53593,cc2ef763,d4ddf1e8,5936add9,a1819472) },{ Z8(98e4616e,7a2fec8c,0513d49b,96b02c2a,e6e91509,f1bc281e,2cfe1d33,345185e9) Z8(5022d783,15a11f3b,4fd55be4,d084146d,637af0e5,92fe9c08,cadaae08,a22832db) },{ Z8(db265e57,d181efda,4630d84e,4f87f3e9,f2373a5b,770208ac,b7c7b50f,b2a39eb0) Z8(5489905a,55753016,ecbcdf0a,3f56d575,6b7a893d,2d31d1c2,d6e3fa33,a2ce3295) },{ Z8(861204b6,481b5a55,353878c0,6b338fd3,b408341a,a25423e9,4c8045a6,2363a23f) Z8(1519b7d4,f1fdd467,574756da,8377a1ec,99b9efd3,232723dd,f238af63,a37393f7) },{ Z8(e2c5de2f,2f3c35f4,51157fbb,d1652a54,2afa72fe,6935ca95,37598735,1f8c1678) Z8(6777e14a,a6f75e8b,3a8e33af,d43b4e06,d63334d8,66a66626,fbdfef97,a418575a) },{ Z8(5480f6ce,c8ea0ca4,e782285a,91742ccc,d3d024b3,5762206e,933cb84f,a7f7b7db) Z8(8cc4ef3a,21486665,eeb2b9e7,e3f08689,457dac9e,19a87f2a,34f70924,a4bc7d19) },{ Z8(0f7e8e2b,4ebb7d10,b357f88c,b69b5678,9bf6f3e3,e09b3342,e9548892,4a9046c5) Z8(cddd1160,9b1cffb5,0cd0e58d,29ef1eca,2003eb46,1ce47057,38bb1364,a560058e) },{ Z8(8176c0ee,9f506f83,1f72af1a,3ebf1502,d46cd0be,45f44fad,004761ab,26d2e613) Z8(d72f6e55,ec759243,c916e8e8,464264c5,242451d4,a7c1ec1a,f4a7247e,a602f116) },{ Z8(c2658630,6068a970,0e0c3754,5b029b16,83d36f12,1ef1ec93,13545562,cc9b9d5d) Z8(1152656d,3318a32b,c2ed13cb,a1872a95,4580ee24,d448ed54,a0a740f1,a6a54011) },{ Z8(9c26849b,45f45943,a8eee072,f385b0ba,92cf61f4,09f64340,6ddbb825,39c4080f) Z8(494a1322,eb3fe5fa,d87a36a4,21b81774,2d74e019,67b7d66f,b7602294,a746f2dd) },{ Z8(cf362c29,6ac8c4f7,83cbe1ad,41da709b,12d4e3b8,c43078b5,dcbda61d,e9c2ff7d) Z8(f0d11959,566e7e8b,e235aaba,b0d212ca,4b4d1412,13f3e7c2,ee8bf1d5,a7e809db) },{ Z8(e2c7df9c,9c76be14,05d79a4b,dd835439,247e47ff,9ede3d4c,448c4b55,eca1ba5d) Z8(f257d01e,878211b1,af4bc660,e17ab4a5,63de1ee8,dcd6832a,2f6c0923,a888856e) },{ Z8(f9834a8e,d1ea5a0e,1e72816d,d998cbba,bec24271,28bfc71a,f528f87f,a88d2a6d) Z8(b62709d6,bdbab4d9,527462b0,73ca99a3,de41b9df,19217375,8f4fd7ab,a92865f7) },{ Z8(06151b1b,85c67da6,f8431ede,72eb259f,0562adec,ff7ad99b,36a1ca19,45931d74) Z8(7dbf5c4d,094f003a,e427bf1c,f9971655,be7933f5,916a84b5,4830f5c8,a9c7abdc) },{ Z8(2ee6065e,d84d5aeb,79d2847e,d4607a6b,cfa4716d,abc4e90a,102e3539,ec29e77a) Z8(f769d388,91bd6827,77ef508b,72cde548,782acc51,648ff1e8,b1647b14,aa665781) },{ Z8(632e0106,cab1b0aa,88b7fd78,9a2542b2,0e2c0151,286ac91b,e2ec9b6d,7fa5fb8a) Z8(5bca3585,9f321fca,8e69e270,fa1db9e7,11000fd4,739e1bd0,3861a332,ab04694e) },{ Z8(c13b6108,400185f2,618b50ba,cf855bad,ba485390,b40008b7,e73fb9c1,14ff539c) Z8(2a4d08e4,56a20620,e0d2c55b,03728b70,2b469fb6,fe5966f0,599dcc2b,aba1e1a9) },{ Z8(fd8a3574,d3fdb776,c3bde77f,4a195daf,6f325ae3,9b9aabd1,1ca234ff,3cc6eb35) Z8(a7edf055,b854b5cf,6c42068c,183db540,6afa8ef4,a36273a5,997dd6a1,ac3ec0fb) },{ Z8(36a498ee,4614067c,ffed0b20,f90a8bfd,39a2b99f,b278542a,9defb54c,64815216) Z8(c4e2513f,f4309a24,130dd772,1951bb83,8769f24d,f677dfb2,7d5cedc9,acdb07ae) },{ Z8(6fbacf1d,53a309f4,593da3a9,7bb25f2e,c109498e,8d0d947a,64684b8f,20410073) Z8(327860b8,361bd73d,5ac7f639,529f4f43,86cdb591,25ee2952,84a8bae6,ad76b62c) },{ Z8(42dc23e5,4c5681e8,10ced33d,c068fdf7,9c89b025,813b0f95,a482e425,1b7384af) Z8(c5f182b7,01e2dca4,c42ac104,c1476866,995154ab,8562c352,2213059c,ae11cce1) },{ Z8(c53c2cdf,5307ed4b,3b746c2d,3fd6f785,dd439af3,c6586fe1,eef1f3d7,95ee0fd1) Z8(c44fdd30,04407947,43effe26,03742b46,3e52070a,14725e2f,b4d8c080,aeac4c38) },{ Z8(19c27a4b,069518ef,608d99e1,778f23a9,43d8a1f6,3843bdcb,b6b5a68c,77bd59a9) Z8(4e3a097c,6dd5e77f,bfbb5c68,4736fc44,1904f916,08a41bae,821e7ef4,af4634a0) },{ Z8(0e621cec,cbf0d745,ef9a241a,b16df078,24d12ebd,f7f68473,916f0675,2a7b1f70) Z8(72810af7,922e6f31,f25347b4,7e411319,3aa0ae62,cc0bffd2,ae624f92,afdf8686) },{ Z8(ec62b0f9,ee29a6a0,3fcf63df,c74448b5,74cf6262,a5f8fbc4,e64810a7,1ddf854d) Z8(13d626cd,04696a5f,1149f517,a5b0f42a,cd9cdaf2,8f2ccd75,3702f448,b078425a) },{ Z8(21fb6e4b,3a0ebf2d,119ac76f,314716be,bdfca441,790bb09a,042594fc,205110bd) Z8(cce6db2b,5d3ed56b,4df9e1c7,09e2828d,b9f6a7b5,43d65788,ebdc6f6a,b110688a) },{ Z8(ea5ad26f,499d0c17,b70a6d35,52abf343,d2824dd1,06202b00,2db1af63,2e434885) Z8(d5f02eee,66a635d2,716ea56a,3ae3c1f6,b2f9e94a,5e62be56,68f9db3a,b1a7f989) },{ Z8(50442247,1a366759,6c3402d3,ead0314f,5fe4e0c5,39cb4dbb,84ef7278,25329c79) Z8(c0f40bad,3c3177a2,53734cea,b2a3bdca,b8c33242,d7eff716,105c7f84,b23ef5c7) },{ Z8(4d7b2d36,7763ad68,fc564739,c63c589b,c7c3f6c2,bdfba59e,63e3ba8f,dfe5b792) Z8(8a0944ed,ea469bc3,9071ce0e,a2d0847e,c6b9dc4b,63262866,03d81743,b2d55db6) },{ Z8(d039ae93,4785f476,9e977afb,0cfdc69c,fca71d8c,70c045a9,ef498a57,43ac8c5f) Z8(409dcd1e,751e5dec,0783f6fe,e469ff28,4462f939,59014174,1f043691,b36b31c9) },{ Z8(c06e926e,2238c933,a073dcc1,3d2abd15,7dd4e84f,75f0e008,8c44cea3,a6e1ef9d) Z8(ea37fc5f,43c06970,2ffd0ff7,69a53095,bc3f1576,56579305,f142bf9c,b4007273) },{ Z8(c024ee45,d3fdabd0,89caa556,3c2d9478,cc470fe0,0c2b1434,4359fdcf,7486ae52) Z8(551c4356,0a83bf69,8e5b3e75,7426f3bb,5971ca78,972b51d4,b7db53b2,b495202a) },{ Z8(b6b7c2b7,a308e1fb,c5632729,9a25eeaa,89f6a700,f453dc7b,ff66eee0,61ae10f0) Z8(01bbffe2,7c6c5a10,fab778f9,c0998af1,2c3f989b,934c772b,582bac12,b5293b62) },{ Z8(26ed1cad,ae8d5530,1792d5ca,ee8b0c5c,eeee6cf7,ba2ca0ef,6fa8d575,e58350f3) Z8(8cea9535,8cddaac1,b3891e07,75216f47,5e3907d5,f8f3cee7,59ecc4af,b5bcc490) },{ Z8(ac4d031e,6a18bd61,6e12b2a6,5318b2be,84d20003,7231de7d,7667216b,32f340bf) Z8(d59cf075,dc78e6d2,567914a6,ee7e3ade,80c8a0b6,9de29bd2,e18cc1c0,b64fbc2a) },{ Z8(bd39b09b,76e88d40,f851e99c,7851427f,c4551044,235a7456,37ad0b6c,e30321a9) Z8(622e4065,f25b5517,73b3fd15,0ad7a1ec,f5c86498,1de72a31,aa9d7790,b6e222a8) },{ Z8(13c3d8bd,f13b3aac,2b00266f,3d93f8ad,95595742,83f97104,eebef105,67a20c15) Z8(e0e3d97d,9bfbd896,0d67f497,f91a4955,4e3ef828,5dd460cc,02577ad2,b773f881) },{ Z8(945e8cf3,38257e41,4380781c,e8c53e21,2668272c,49c49ec7,cec98182,4655f065) Z8(64cae530,a012155f,14c79a80,3d7aecc1,10a4443d,cb2da552,c2319e73,b8053e2b) },{ Z8(47d04f2f,b7e0289b,564de9df,38d73bdc,c7501845,b772d374,edafdea6,dc6367da) Z8(fa8544aa,2801763c,aa36f135,5a4d5a41,102f7717,b2066fb1,4a8cc2b9,b895f421) },{ Z8(a91c42b1,0c4ccbf5,1fc7fb02,6a57f0ec,5ce1e224,59fc20bb,dadbb900,85a0e5c8) Z8(31debfaa,279fbde2,f28bcf2a,05fde833,266bc460,22ccb6cd,7d73d865,b9261ada) },{ Z8(4269812b,9f568d99,8d284245,929e144a,0cdd73d1,36ddd27f,7f14ee9c,fe9e8c16) Z8(ac1e21d1,2e44e671,d5d0f7a0,f01f06d4,2d100e70,5fd06a89,b96ff977,b9b5b2d0) },{ Z8(ee5469aa,c24f5187,62ea50d2,cbe25d89,37c5c425,ed6648f6,0d634fec,41a41f8d) Z8(51eece27,0672fcfd,d454a343,23228454,0942e386,654c2cb1,d470782f,ba44bc7d) },{ Z8(773d151b,a0ce4d29,31a19866,e98e80f5,f0fbf88e,cda43312,c372d285,f8603fba) Z8(989256d6,d8ae8b68,0a8c7b1e,48cca731,10da150b,95898e52,16c6c3dc,bad3385c) },{ Z8(d8317a9d,b58a00b1,5ae2bca9,3fed4473,86ae2a0f,892edee9,6927dd63,902eb955) Z8(05b79464,e2c7194d,6f8d6c65,1342deff,07915ae6,a4aa35b9,36360232,bb6126e6) },{ Z8(7ac67c19,ca1d2723,96ee2335,888ad40d,ff8f33bd,b1618881,94867be0,43eb5053) Z8(20d4c84d,877735b9,a599e7d2,740e9aaf,a7ae3e62,4c11f821,51163ae6,bbee8897) },{ Z8(c4c3c40d,994e9987,5d58da8a,920ba34f,d050067c,d4140c7b,569845f3,010c85fc) Z8(5514a995,231796bb,5ba4ab8a,13fab81f,e80fb290,d4113006,e98af280,bc7b5dea) },{ Z8(078d591c,2fc841ff,55ab5af7,75a8ca78,11f4d92f,afabb0ad,f3ec992a,04259565) Z8(c71fed79,be81bf84,8a497168,15d7d6a5,fabb5d74,e33e6c0a,e0cd1089,bd07a75c) },{ Z8(af58dc87,2b300fb3,924473f2,ce65df39,1202cd89,9f3a1bfe,5ca4f7fb,384a4671) Z8(56e4bb84,a593af0f,c726f312,89fb1e26,c09b1791,fe419f7d,7287ec62,bd936569) },{ Z8(db99522b,1495ad10,570f1ff0,64640bd9,c33c7379,a3c88dfd,639ea69e,7e4bb855) Z8(664ccbbe,9c2bf459,7fa58b32,6bbb76d2,5109b743,7965a606,30495b76,be1e988d) },{ Z8(eb3af07c,c26f2caa,16036500,14b1de73,edc0ee63,94f33cd5,014699b1,4130f65d) Z8(655bf345,74fdaef1,f13d5c3a,01438341,55282e7d,1043c5e7,fd049aac,bea94144) },{ Z8(948cdeea,3b85c8bc,189c9cdd,624975d4,49182faa,9801fe64,7bfd7059,ec13bb8d) Z8(e7738e7a,1511e852,a2606cd8,6f6bfd26,8e50ada6,a8ee913e,08a7ec6f,bf33600e) },{ Z8(91c017b8,905b317a,a99fba77,1a3acefd,f6180765,21db31c0,0de6e856,6093845c) Z8(64b3656a,6ab1d623,53934558,ce2085df,441a24b5,b9501d5a,cbc4c3fa,bfbcf565) },{ Z8(aebd0b6a,2234ea74,e80b5754,1856411b,4880f10e,215fd084,a87870f0,86e41e4e) Z8(b9a23642,548e902e,a46a50a5,59538bab,2b630d4d,19b11d41,034a55fe,c04601ca) },{ Z8(990563e3,dfe86b83,ac95ccb6,3ad03636,485bc5c2,a34ac5cf,51a62f57,44ffa53c) Z8(a10b2d25,37081467,aef436f6,d58ee867,6e92fa24,89dd62c4,ac526640,c0ce85b8) },{ Z8(f2ab784f,7d87e16d,d5ce0fad,74459366,e7517870,f29f8b05,83833ee6,8d6fdbad) Z8(d1575070,0987beec,703e16c4,695bf27c,d2425ea8,92fce924,00002945,c15681b0) },{ Z8(2de4649e,69584910,e337a1a4,4574b346,ead7180d,0458efab,16023b26,75af9aa6) Z8(815709d1,6653bbab,e3b003f2,1812b904,361448e7,838827fe,6f711098,c1ddf62e) },{ Z8(3ccfa487,5a07a42e,6570fc40,6ed05d32,b4e62c8d,c1a7586f,12dc125d,5b06891e) Z8(ce882276,fc8ce728,1847c57b,8039a8ec,c1713e2f,c9ee01f5,9fbf57e7,c264e3b2) },{ Z8(9f6c1e9a,5c930791,e8cb14e3,41f3a7c6,49d272f4,16f02476,00e8f7ef,ca811d6a) Z8(a9724511,a4a42eff,0e4baa66,e970ec0e,c61bb9fa,b373fe45,661628b5,c2eb4abb) },{ Z8(629652b2,5c2a2311,5ede1189,e88a3fcb,1159f52c,0df7a13e,df6f5268,c38e91ba) Z8(218c6d64,aa12aec8,d04b7f6a,93a72f30,c678fde0,5626eb9f,c3d72a04,c3712bc7) },{ Z8(6c572099,e2a717f3,dfd54159,31d1e173,9a81f5fb,c86286b1,826637a2,ca40809d) Z8(3061f2f3,57b7468f,cab62fb5,ce4aa623,4bc61565,f5ad957f,e2d1510a,c3f68756) },{ Z8(88c93f33,c2db39af,5903eb22,3a4558bd,438ff50d,0a313650,cb63ad19,1ccc9b7c) Z8(f32b4f93,91d85ec0,63cb83ea,97192bb8,667e2502,4b8b6951,1188c7b3,c47b5de8) },{ Z8(d28d2f5a,098b6ca9,0006bc9a,24ed1b16,f8463c22,a068eb0c,45c51352,b0fd5694) Z8(4f97d1fa,fe669d99,0039834e,4da621b6,bc9e0221,8cb43d10,bf8fbd54,c4ffaffa) },{ Z8(65f31f3b,388e1c1e,b8b30016,a8c80473,83abad85,3498d020,c61fe6c9,9ba8c506) Z8(b4ab95c9,f66d6033,14b2bfbe,6837d6da,9263d1d4,99db3524,79eff5e0,c5837e0e) },{ Z8(892289f0,149126ae,59c15a7b,1893fef7,5ce6c6be,449d5230,47a14fa2,f2db2abb) Z8(79a3ff17,442531f3,8a15c194,6f74b5da,66516455,480edb88,e7a4eb7d,c606c8a2) },{ Z8(4dd071bf,8c241234,57a88b57,cd4c845e,d58b13d2,69f86fc8,4647ee8f,6f575b7c) Z8(1422a61b,a723e05b,e3af549f,dd13c472,574ca266,e7345576,c626564f,c6899037) },{ Z8(7cd74955,f6c32fc7,4175eb9d,724d1c66,de8162ac,bb9c9bcf,b5848c7e,bd069fab) Z8(48417fda,adfde929,af9b702a,0e9c986e,09f2be38,e7d54fbd,e602ee13,c70bd54c) },{ Z8(6b4b1aa2,4d3fb729,fc0fe1f4,e0b01556,21b73f1e,b2be5028,5bb954e9,97285197) Z8(9d7e8a06,d41681b3,e8b4d30a,3c9c7639,9fe946b2,8e55c9c9,278b38ee,c78d9862) },{ Z8(e94d85d3,1eca4460,75c0f295,6f6ffd22,393e3682,9a21e260,119a5614,5c540c8c) Z8(7298a4a4,8402ae01,c708214c,3b7d29be,91ef71d4,ccbcac07,778c3ad0,c80ed9f7) },{ Z8(03e2135d,a0d8504a,644636cd,e0a59182,73ceabab,b0e884ab,01e3f55f,a5917ced) Z8(7ea0180b,d9884aae,e7b9333e,167b4c95,a90d530c,745076df,cc19d89d,c88f9a8c) }}; const mp_limb_t arb_atan_tab21[1 << ARB_ATAN_TAB21_BITS][ARB_ATAN_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(b05b5f26,0e71e093,0e01723a,81e8b531,5b7039bf,5077ba19,d2c215ef,f8683492) Z8(db5e2e25,083b4901,184e277e,48487df1,4489185c,db600462,9f50bd14,302e7051) Z8(e0ee0aa7,9a4b316c,89582fe4,32916544,dc172ba5,69a141a4,84ba4a5c,380f1768) Z8(b77501e0,9ebb1272,440d80cf,63fff32a,c8ffcd77,07e2a4dc,4e20aad8,c9bfa51b) Z8(0bdd5f0d,503f8851,1da324e4,77b05217,496d0a20,6c86a4e7,fc3f074c,1cc4f214) Z8(6fbf44e6,95583c13,d84f80dc,12dc69b0,228ce8b6,3480beea,554f25d4,3ebc36f7) Z8(62b425fb,f2bc846f,d3021773,836e1db1,1f7b3dbf,05d87ee7,bb74aa0f,407fb1b6) Z8(fe3e623f,a3d13d38,596a7b7f,dcd9e7cd,faaa0890,cece21bb,b868f38b,3aa5fd19) Z8(79ec81b3,c24479cd,157d9fd9,b1276330,aab2fb48,ef0d9133,feb17148,68ee429c) Z8(d9022ab5,8c9ed5ad,bf33872c,837e9ccd,c85eeb48,1fb2cd92,a7d87ae8,84d12671) Z8(c83e269b,8fddbe4c,53d59835,c38b6b3f,9ec9c439,27d81b23,b70c54d9,107f1ba3) Z8(f7c5f629,11fed0e8,c24d389b,535c7f97,79b53203,a94d5b55,f2204a83,e07290bf) Z8(7de781f3,1edadbe4,eb0d0d2d,2aa2c686,45a41873,2542bcea,ab381617,a96f6f0b) Z8(86bda292,90024115,9a021aa8,007cd63d,c63aee74,6b06eb7e,cb7ef091,d48c02b4) Z8(62e872f9,e79f94d2,b58df3bb,7a05eb9d,b400d0a2,4d6e16de,385e8484,d0aaa133) Z8(737b4914,e5bbc8bd,197ca05c,aac8a1ba,fb5cb3d5,a628e2f5,89d759fc,a9d14ab5) Z8(6f362901,1358c95c,c276afc4,13c86927,f7a43e2d,0f282ff5,897e5f9d,3b2a91f5) Z8(a26b0830,b2380bed,a606dc40,9c036814,6ed46310,13bcebbb,ea5d892a,07ff556e) },{ Z8(a04a314b,aee9953e,ede190bc,3d5577f9,9df5f7eb,b374863f,ddbbf656,89ae6707) Z8(bf218df6,493cd567,cd6fd15f,8d63640e,6ce8a993,fe4329a2,663f987b,0ddd0edb) Z8(6fe63d6d,1877d90e,1db23199,2e3e9d2b,497fb0f9,01a357df,788a5888,34c89866) Z8(804968ce,3060820f,0a674bdf,3398a491,88614364,67635542,68994e14,f8d8da21) Z8(dc7e331e,69234d96,734e2e85,32dd1357,0a37d6bc,ef1d7e62,e6b46593,40582814) Z8(27147ec6,624ed03d,0538d40d,3e9da0f7,e83245a2,991c58d7,fc013a81,83457bc4) Z8(e11f76b1,eb73d677,bad49ce5,8176cb83,e1da9fb3,c0af98fa,c634f7e7,4ce4dc27) Z8(fc080d7a,aa7781be,ca935085,03ebc23a,5b9dd531,83eb6d25,cb9fda8f,362c5a49) Z8(15e01e12,acc4f432,a95d6f11,de099b5b,fa8937c8,62a154da,945be2b6,d6975022) Z8(f5939c89,0808e92e,e1167691,4182e351,7f6f4729,5f0876f5,555834b1,f28da626) Z8(90f60b3a,9c0cd476,4c3695fa,d3a5535e,50d1dfec,a91e25cc,be5f7199,92286d47) Z8(61461357,e4003801,6959cd77,e4979789,6fc7575e,ae32790a,dc1e8d81,1ff3bd74) Z8(fea827e4,62c55f53,940af3d7,0c2b99ca,2ba9e91c,fe7ba779,bee42bbc,754589a4) Z8(6142a822,26407fa5,b01e7030,e08263f3,422098a2,e74c775d,8ad1d619,2abc57b8) Z8(00d679f5,6b3de22d,4ee676fe,5a437601,37fb5bf5,3d807d0d,bc1320a4,f1f6d154) Z8(4f9fcfba,99fa1886,ae1b4d65,272e54bd,eccad58c,4e8952ca,5bddaffe,d5c04e8a) Z8(4ef2a858,42521de9,625a4c0a,b1404b3e,6ac74803,493fe292,473e9b7d,d0249009) Z8(03c4b8ae,c387a9f8,f59d4b2d,1319c12c,c0e2e0d5,6cb2792d,967ef4e3,0ffaaddb) },{ Z8(b211403f,c67d3540,19dfc6a8,4cd7788a,5e0a1a09,5957a606,55eb15ab,10386d4d) Z8(d0e9aced,a922352e,f749dd95,3a80390f,eacd1a61,fc56533e,040407c6,91bf13f5) Z8(a1bc20de,8f3dffd5,a91eb7fb,e7207805,e8795f2e,899823cf,2c5d6219,2a93dedc) Z8(87e44a17,02c0b75c,01ba6087,a07475e0,b6b06206,e46f4795,334db346,e1d08bd4) Z8(5b9b070e,961df1b0,ead3d07d,a80c2169,63307a8d,1dea9f72,be4c9ec2,aebb9cb7) Z8(91ce2136,54bb304f,50c0ec8f,f8a9b3ca,526a5ee1,bdeec0e7,ab760adb,5f32ab45) Z8(7ebe8df4,73ea9791,c66070c8,445e91a3,688a6f71,5697dca4,631ff53a,22b99e04) Z8(258d455c,7aac9d55,e9d0b3ac,72c42fb6,f239fd56,13fc0525,9171d65f,37de6ad5) Z8(59664436,dcdde8d1,7eeb51d5,ba496f09,87f513d7,2c820771,cc113cc5,0ebd1a71) Z8(0fc2b166,3975b844,6970c215,7a48ba92,5c855a07,4a7703f1,26e16372,3f78d07b) Z8(cfe35126,b195310a,3dc3cad5,501ae206,90f2dd6a,41ab5f68,037d77cf,6d43eca0) Z8(d8b30834,2a526bde,f9faee38,f6883b2d,73765562,352b8e91,eb01314d,a0dcbce8) Z8(bcb15480,f885655b,2f7dce54,4ea5113f,5b5ce8fb,4680679a,f2b2af41,4799749c) Z8(db96d6be,d70f6f35,3dacfd0d,1a060c26,8668551f,9e706288,8f663655,fea59963) Z8(65382776,09b125c1,3fa3b89c,abab4e63,4a12bc39,689ee6e3,60b28ad8,3399bf1a) Z8(ebf0f3cf,ed830e7e,a722e4c5,7d741e6a,d17d6cf7,826f1b72,beab6d39,e4b108cd) Z8(e9ef63a5,f61cb520,147ccad0,b05362dd,cfc4eed0,c7006c6b,a4933246,45474c82) Z8(8c33e00b,65667e05,3055c1b8,cfc1508f,099f06ce,126acfcf,02f10e8c,17ee1826) },{ Z8(c630a635,8b739b70,768327a1,2f5e0255,88c400d0,c92ae87c,6aa1bf39,991c6a01) Z8(dbd9c6fe,b5267e9c,b987ed5b,76a7100b,2df2ac48,5b570e8f,472367e9,46b31084) Z8(bfaa3554,c917b349,8d548b59,d00bd1d5,7f1e80f5,4afa62f0,e7bdc73b,681aecc3) Z8(c437ea3c,2406719e,ed600edc,b53caa7e,6a938973,bc9aa4b4,cfdeda55,7ad2ec65) Z8(709896a2,fbb5318f,aad1300b,537c9a20,0786c28f,26c824d7,ef375383,792cdc8c) Z8(2b6dcc9d,02e1c872,9236da27,845d8678,0e466bfe,a2b937fb,6b07b53d,b58fbd3b) Z8(d4bf0358,189dc07d,ca72f0d0,8f0b8c7e,7a746da4,978836a8,552cb6be,d606cc7e) Z8(16ae418e,32fdec91,f3a6d5e1,97f6cab3,03d99344,ccd23b39,39800ea0,034e840a) Z8(c016dfea,9ab81f22,219bbb04,e884088b,998b6d86,f80f4e61,2e3b72bf,18795467) Z8(5c3884af,8051905f,d9a502a4,42221f4c,4ea67d5f,cd20007c,85af5fca,a240ea37) Z8(f1b2bf3e,18ab73e5,ba6b9a6d,b512ef18,5077a28d,356d51a8,7272bf1e,6944cbde) Z8(f8bd1246,cb6db4fe,5decf647,fd06658a,3bd2923e,19576621,478da9b3,2430439d) Z8(be249ea0,4b029876,2d1f2c96,d708bd87,fb330df0,ae026efe,c8bb1a5e,1c18d05f) Z8(7bd8f19e,8a15dc19,3e36978c,8bf3deba,0ccf31fa,e532f8f1,5faef8b1,e828090b) Z8(1b45c7f3,1357120c,a236a05f,604e87c3,40f20933,2da37ce1,0531822d,731d1796) Z8(09682ab4,109e4ef8,a13d17f0,dc0194b4,796a1d75,afab0859,bfa82285,bbee7451) Z8(57f08ded,a54d9b11,3e535f7f,abae7931,3c469ae3,a7ff4baa,403b384c,1a9a0100) Z8(bf6d82ed,5d926aef,2bb35b24,f1672afb,e7d111de,5912f313,ac2f6dc6,1fd5ba9a) },{ Z8(8c865d25,ace05c5a,9eceab05,77209dad,feebeaa4,4978a362,464b796f,9cfca9ad) Z8(9c8ffecb,5424dcc3,b511a23f,6e15030f,80652176,582c4da5,4d9f48d6,6ad6b6e1) Z8(a81fcfc0,976e01cc,b17ec185,66b3809f,080e3808,5389c498,68878e6b,8dbe319f) Z8(26716720,52ccccff,788e1d58,d3fb8660,59024b02,5476485a,aa1a1d7c,40643bf8) Z8(2d148422,e792693a,c407a5af,10d2fa42,c3988f0f,effcf38f,76a00441,aab38016) Z8(67a1c06f,cf5eea0e,1873b842,18014d10,2b437646,88c0dbdb,f25332b2,7701c0a3) Z8(a796bc80,30b8d08c,8b19b282,c6c86839,75b65a44,9083089b,59e2947e,5aebaa61) Z8(096f39ce,9d82dbef,424d0b2c,c0159236,48008c3d,144eef2b,b61490ee,7394743d) Z8(70ef749d,c080a69f,0810d12a,e6bf0cda,eaf60611,19daea3a,39ad97ca,0f9bd392) Z8(fbfe2f3e,60f8d765,c4be8483,851535fb,05eec70f,e7cffa82,8127e565,22d79df7) Z8(69ecedf4,6682dcca,8e7377ff,bb26408e,aad49692,d43b554e,9e841198,fe8680b8) Z8(f69769ac,8d970462,305f6fb0,f30522d5,f02d57fc,4f52c7d2,d6aa3237,2fb217af) Z8(80435350,c0cd9e53,60edfb24,a4cc7a7e,e9194d87,04d767d2,d59c725d,87b2e5f7) Z8(b98728e0,12fa0936,5a57e2a7,f0ade96b,e830817e,add90a80,43c5a75b,3825b54a) Z8(1c2d33d6,15b21b55,1c8af5e8,234c833a,b83dd11d,097a8fed,69a2052e,dc7bbcd9) Z8(4014967c,ce186a12,86c973c5,8b6a4ee4,8acae796,4425f0af,9b95a250,424af525) Z8(be2d13b3,a4d22e76,c6fdac72,bb480a41,a8adca3f,de49b5b0,bc6aa4fc,6d60ea3b) Z8(d0a3c05b,132f0292,2eb74a37,5dd4bd3e,40d83fa1,d1d86749,8cc4d8b0,27adddd1) },{ Z8(ad7a26d3,0cc2924f,f0995d08,755e0286,3db592a1,eb5d0679,d8271993,e2e6306b) Z8(e251fa90,1c3dc33e,8ee4812a,2a13d891,5bc8e050,eb53b323,54f91f2e,5d0e1341) Z8(a60d30e5,e51de084,81170255,2479014c,36a1af21,67090e87,e5ec39ec,309eacde) Z8(26fcf598,3e653e67,5c92c02b,d9f5314b,e8164552,2fd778d0,ac3c1600,8adf8615) Z8(f09199a3,1f8fc04e,f3927390,6a8e716e,3e9d7962,b4fb306c,00216028,e0684d9f) Z8(32c62bc1,337830da,c6f17291,6e97d077,75edd2a8,3a3be8f0,256c7808,b468e4b7) Z8(8689715b,82717c11,948d9fe4,4a191b17,0336aa10,6b6bb9e6,f00494a4,7e849ee8) Z8(f75ebe07,52c03c0c,0149d157,5b779f67,2cf6dc3e,5a30ad15,4a1c785a,24232995) Z8(ac2c3927,63ff68f9,8a8cb627,3e31ed75,e458447c,54e9d3b5,515af116,16a963cd) Z8(a6c13e85,8ed70b69,d4aa4b95,677ff24d,9cfc7472,9d9bd45a,a99c0f9f,e60b099b) Z8(7c86b41e,107cfbc6,3b3d8a6c,ad861437,b09b25e8,dfa59430,93810e95,6eb591f5) Z8(4b01c1df,21484501,e73cd6a8,3ec7c05c,202493fe,812fe2a1,9073245d,8fc03e46) Z8(7551fac3,d83a2b11,9c78e48e,0a940a44,f58754df,7f413a80,cd68b614,da16a32c) Z8(a10cf67e,3bf4630f,fdf1d4c7,0ab13e8d,0ce872d8,95cc7caa,634e4df4,39e636f2) Z8(92780162,73ff1c6b,a390fc6e,3f186ac1,c91d1f02,2927fa15,6436494c,ebdc6797) Z8(c2aba503,0b8af6b8,511f5e25,792437cf,63ccd2c2,bba5bacc,bf49b7fa,e54e79e5) Z8(54f8c53d,2a81b45b,08d5df80,e3546041,3f5c02f3,a2e0e37d,a1314740,65c41183) Z8(c79f5cb4,bc169a93,a0e28aca,e4eb4035,07271d21,1ec2d3e2,9cb6044d,2f72f697) },{ Z8(27529dc8,b0ab6422,93903fed,fbc920f3,12160667,efdc199e,502f5da1,79a4be92) Z8(be501656,4db8e927,7ac8ff35,eae59ed9,2e1855bf,7b08b763,c2a7e62a,f7f6504b) Z8(4d4ed159,c1cf3db0,a56d158f,87c37b3d,0bf7de77,befddcc8,46a0fb17,ad09725e) Z8(7c918484,2648ee07,b974bbe6,68f788d5,a167c7db,cb3978dd,d42b5117,799b6e82) Z8(5d722e25,48dbe00f,592de2fa,a117a7db,11abb2c5,ffa508ff,380a2dfe,33ad1f66) Z8(03862bd8,361e7e6e,bb125bed,97bc0b11,a1351f48,42fb1874,ad8591a5,1f40ecd6) Z8(8469af97,518fa321,26803d2a,864bf793,9d2a34ba,2dece0c0,5e2e2263,2c9070e5) Z8(337bac27,4be7e9fa,076bb994,aadace5d,cff150e5,0fec9ab3,2dec8bd4,17fe51ce) Z8(e043898f,1fd188a0,d2eebf21,30592996,6e52754a,17a516f3,18992caf,d4880a94) Z8(1557aaa7,bad2e43c,dca323ab,bb632b7e,5b44956e,c62562af,80af8d10,40afb295) Z8(2b4e600f,8688a5a3,78148111,657f242b,3ab5d43e,38fe5aec,23d36d00,d0397805) Z8(0464c5de,b6bbfc6e,5fcce8cb,3642cb21,8f807829,4e6cf20c,bd1aa56e,528ecaa9) Z8(7205cc27,727f43b3,58e16156,5448636b,22281ab1,fd838c6b,932d7b5a,35a08856) Z8(75f9f7da,5f8e83ae,244e7685,b3c74f19,f446ca9f,86f880f7,4195fb07,1148e410) Z8(7a3fc9d6,5500630a,aa093b3a,e0fa37b8,b6b33122,f49485a2,7ccdee8a,e1ca986d) Z8(9fe24284,727f75e4,c9bf110c,9ab8cc53,692d705d,f3798801,fb58fb52,1b48dab1) Z8(2d953efb,d5f2f22e,9be36135,1bf788c7,bbace5d8,2a7d62b5,137701d5,10c6abd0) Z8(5fe10a3b,55881bc6,4e92c495,a19144a3,72d54bc0,bd886970,24c14408,3721aea5) },{ Z8(e38e7b17,cb0f6d8a,61565873,d3ff89fd,d2225798,2b8962a3,260f5a2c,293dcce9) Z8(4efbe516,4872bd90,4ee8020f,95afe6da,03eb4e41,04bbacb3,7c7bfa89,0b5ee015) Z8(0e52d3b4,23a18aad,18b1c362,43e055a6,5797d662,13d83973,f08f973e,090f3d2f) Z8(1bef24a3,bd6fe4d5,62b759ff,1d86dbb9,afc2bb9e,0a3b44fd,6a0e2f5c,9a470683) Z8(a135fce5,53dd4c26,24e02c34,b3aed837,d2d4bc2b,1532734b,5c337380,c2330575) Z8(bae62399,f5a37055,25a34c75,818c2990,8904ad7f,ff604750,faa15c39,f1689c67) Z8(6b10e82d,d5b4d0c5,94549b3a,4be029c8,4eab81cb,579aeaf8,4f0d338b,dbaf3013) Z8(f5e0d9a3,5ede6f27,cbceb593,5bce3dd7,a47c2d5d,23019f21,11e3cbe5,cbdc9164) Z8(4ba879e8,17c3cef1,049456ec,80e97880,23c731e6,e55fea04,7482fa48,8aefe6ef) Z8(ab2d170f,9a8fc9e8,50406030,f2adc199,81878fa1,7eedf447,c38d6403,32fac50d) Z8(2e51ef27,3e5ace00,25198682,28610ea4,b4bb3e51,0f416267,fa023d03,47489927) Z8(27035f53,bca24487,7f5663ce,492e950c,eeba1875,da370e60,19069a95,e0df77bf) Z8(fcfcb528,dbfb0a1d,fb052714,69288aa1,65a9b682,38b150c7,1bed4dd3,d4f74652) Z8(a8abe21e,8ec90e37,1541aea6,3e0316be,05e8a59d,77b45574,3638a43e,6f3d2903) Z8(f52cc10e,76168ab6,172dfd3e,35202301,9382463f,c31b0a65,d9ea1204,6ee51de7) Z8(cf96f2cb,f848738f,eb389c81,023448d5,5756f724,fda27231,f8fca695,67a2add0) Z8(c0e660de,83d070ea,c1c793e6,8f0af089,e960c68f,c16fa316,9a395d94,64ae4945) Z8(251269d9,de8e9d9f,e22ce0da,6a9fea40,7de885f9,5b71e7bd,5901bac5,3eb6ebf2) },{ Z8(e9917bb8,76eea57f,f88e98a4,4f755ebf,a3095345,a7092ace,dcad1801,088d0318) Z8(495f04e3,28f54d8a,8c781be5,17d230a4,6091d624,e4c01e19,ce310468,1f2e4cd0) Z8(8ea58898,91c5d661,9120e753,97f53268,4dbcbf9f,0e4d4719,ae806b8e,437752ca) Z8(3801470d,ac18aa52,61b0d670,c0ca4cfe,345cdb9a,db5bd177,fee524ce,1a4e4aed) Z8(b872252f,ab67a8c4,4ecc80a3,2b4716bd,9e099671,025d2ea5,522e6f6c,40d48e9c) Z8(833ea095,9f248b41,10bb188e,6c78c14f,0d09b9dc,5892d9af,0ba3b97b,91118099) Z8(98422252,a8515cbb,daafc01d,b832b23b,fd32a7d1,84b5f2be,b9290623,2a9c1d48) Z8(e79d126e,58cc1fa1,669c65ab,76259b55,f439bce1,9520caf9,687c1395,8ad1ad02) Z8(204560d3,23e02343,41df1fb6,faad8c76,6bb331df,bf8ddb80,3990be61,cb60a595) Z8(557b7ee2,30db7a1f,7fcba68a,690d402c,ab0e6cd6,a440df1f,9353d317,71018c0c) Z8(5c238828,f4b4cbbe,1dc73dfd,88eef680,dbdaba6f,7e543f19,6ffdf36c,bd53e2e6) Z8(8a373a5e,4eaf378a,2f89fe99,2ce6e3e4,7b822a25,691564cc,f4ecc247,79457512) Z8(d87464c7,7633f333,ee180dbe,eb979053,b18c9cd2,38572510,e83f8973,1ed92da4) Z8(32325db3,f8dc9405,89caa408,a287112c,ccf9088e,76a4a66c,519b6f70,615a5589) Z8(847e278b,b7738f82,49570816,b25ba7fc,456661bb,b1e38cab,cda2ed3e,b9d373e1) Z8(fabfaa39,f3b7a912,542e4630,e691feda,7341fb34,cc8b2146,ca65990c,2c670176) Z8(3baa0802,9fcc00a8,e76734f4,56bac311,ae28c340,edf331ad,b8c8226d,28af6d95) Z8(a8450274,e5275dd6,e0d27de7,87e9714d,dfc414c6,6523a458,2fc5e098,462fd68c) },{ Z8(76c154b5,d7edba91,8b6f4b76,6062c15c,18f70c56,46651ab4,25690cea,e5a44715) Z8(1b07eaaa,c98c2bfa,4343a732,7438b8a4,7abd7693,2cfb9807,7df99f32,ce48b91e) Z8(9dcf5033,4b60bcd6,6f34e3da,40d3a7e8,0d1bf1b2,de4fc3e1,4e00fa8a,c282867f) Z8(32061b6b,53d8b228,0bddb19a,c9d26512,a61537f8,f78a814a,7b264b71,4481171c) Z8(271638aa,3411f3ff,14757e96,ff02fb69,1c7718cd,323c9cc6,10eab79f,24a5f032) Z8(d4fa8bab,5cc73e15,b4989a3a,c9fa0cfe,9d8610ea,4378d461,793eaa06,071cf7df) Z8(c6ed2dbe,bf3078f4,c508062f,8c2d860c,b3f10f39,25b81d2b,38ce793f,e81b0144) Z8(b1ac83f2,044ff60c,4bb28a8f,af5fbb0b,b6de7bec,7fdc9b56,01913fcc,4fde6138) Z8(5e44c28d,9bb6d369,faca1e4f,c8885bd5,8f772b26,e8f4cb1c,115fb824,af33e8ff) Z8(7fba3f68,8075f245,77652999,551544b7,69ed837a,b0bae561,3fee0df1,4da635be) Z8(6d912d7e,97b725bd,679f3d59,a0f6c5da,671f07fb,3f461603,bbbcd635,3191a4a6) Z8(53a81313,48be2a29,704a9604,4d4c70cf,5410febe,5f119f16,3282fe6e,a4d806b6) Z8(f8a03a02,d860ae9d,2f7f166f,c415b145,acc396da,293c96d7,8121db97,b797808c) Z8(18ee3335,bede8314,f9041881,d039d204,2a11e461,927c53cc,83f70faa,345d11c3) Z8(44981133,b10ff61c,d971bbe7,626139ac,2a907666,ece61d81,3871fb8d,5395490c) Z8(d22f5eb0,6c23414d,4b67ff1e,f92bf0b3,2061223d,a915f2e1,b3995d49,29866834) Z8(97b49c80,dd8e02c6,cea6a96d,82674492,34643a2c,22033f7a,54eefbf3,699c6992) Z8(098263d7,fad2c806,8597aaff,045247c2,693d7994,e2d5da4c,1faf2f34,4d89dcdc) },{ Z8(613ed910,76432573,50461bc3,53ab3625,30fddda0,b31c34e7,74ba1639,d0e4f925) Z8(9cf8e061,d85efdad,1399241b,2e8d1dd1,4e0b3191,836abd9a,0f237e3f,4cf97f14) Z8(f93311f2,c4313bfd,b2dc54fb,3654a1b4,379bd594,8f5258e7,b8845b17,3cea5bfb) Z8(2a7aecbc,43b282e2,80367480,91dd72d6,daf08218,e6642d9a,a98ee741,42b104b3) Z8(266afd0f,b6821900,51fb8bb1,7d0897f0,7a9e0a21,47848c3d,8c979078,3afac137) Z8(9108018d,717a99cb,575c29ba,091c213d,de9d34f2,ce63d0ff,950f9b9f,581b0296) Z8(3d284d94,b7ec73c9,94f1c966,eb2409be,1654e38d,26a159b9,d1cc0d52,42a146f9) Z8(d19e4fe1,5d4f6623,4fb6fff8,0a91fc22,02a98c64,a261ae50,80987cb1,4aa5a80f) Z8(da2b17ca,5f361134,d7e623fe,74cb12f2,9a84991a,6bec66c8,3d0e7368,e28ee05c) Z8(bd28223a,4a08fd8c,9ea05e06,4da46a2c,c955588b,83c41345,d1d4d75b,32402c2b) Z8(0f9472f9,444a497a,db257b4a,b13a85ad,8e28588b,59106189,d0071889,f637acee) Z8(0f384299,d994d27e,f8b0b243,7ff614e3,437b0f13,ae38c8a3,30aca01d,097f19b4) Z8(a3bdfdf7,854ad863,e27d0ff3,a63ae2b2,cd50d85f,a786b374,4624a687,bb6b84ad) Z8(4f4a237a,19fc15db,24ee7d41,9eb86fbb,c88e4933,e035eae0,3758a3ab,35e2090e) Z8(8d1ecd27,aa6e166e,d65f76d8,880fee1f,22450ed5,81a297e0,19968377,005c57dd) Z8(4ba745a3,b735132d,dcbdf80f,060fddbe,4da574c7,c053fe5c,0e3cc433,aedf94e4) Z8(0e6d9a49,5ff2e209,61977292,daab7c7b,5e61c948,921dd49b,f930a1bb,707dd4bf) Z8(64f8f15b,d12e94ea,8f7a6be9,90961ce9,fbecf460,4cdbfbbd,4735276d,54c2b665) },{ Z8(2cd57f9f,b857ff4e,e09283ba,0a6f29d5,3a6a42a1,cb101bfc,2cd9e207,4b5fb702) Z8(4079cbfb,35d48ce5,6bfa8ba6,6e7aba19,a9681425,e78ae520,a9aaaa47,9dbdab3a) Z8(6265989c,9c71dcf4,d7b691d8,04636bba,c89fdb72,255b7861,76c67acf,1f6f5999) Z8(c5b47b9e,a7c73717,a5c07643,202558c7,1be49dfd,68c8c262,33f5e984,3e420ff0) Z8(263e1ba3,cf889e1a,12c565a7,93264f4d,fdc532d8,40d3530b,e14c6824,066834a4) Z8(99f18a78,893f365d,7b702005,c20b2ddb,95d88b9c,2e5490c4,fb432421,f5f68d4c) Z8(6c33b1a2,df1a7684,7363c26b,d3ab9a53,170ad866,6f2a190e,177ae2ec,43876912) Z8(cc044bbd,dec547df,6611e911,9306caae,253b5c02,aed481a3,543b0d78,2bea0f97) Z8(d16e542b,3be97004,44becece,83e26ea1,df906edf,33d0eaae,32dbb700,0f7abbfe) Z8(d29fff24,76389c39,8b604e1c,2840db79,b1b52fc7,cda6f04b,5fc7c51a,81e501cc) Z8(e58fe00f,9b3cb1bb,f334ac04,bb3ed38a,c5104494,4dfc6788,1e255d09,7363c3d8) Z8(0e23d60b,daa104d9,987b306e,580cc084,210eb616,2a7467f0,7db99782,67a579fb) Z8(2172c0c8,10ea8ce6,588037be,33003cef,5aa246d8,b44ea69d,6226d39b,a111140e) Z8(57c56395,308c3175,8bdba5e3,f54ade7e,73f99d8e,ff3cbce4,3a9641da,0eb04c95) Z8(3bc15a3e,aa55a87c,a7c19472,48e1f679,1f24f4fb,f0486fba,75fd999b,35695f9d) Z8(a4e87b3a,db75285c,0171c14a,effb490b,439c36ac,efde15b2,60e2f380,df3ba66b) Z8(9a49ceae,243ead56,bd7d0d30,430b7703,0067b9e9,6e667254,1cfee06b,32662c10) Z8(19a48470,2399f2e5,d72a2ae6,9ec21cbb,6e7f2241,c5519091,937bc239,5bd86507) },{ Z8(75467468,539f7a64,81b2fd45,6c766776,fd6617c7,af3038f1,ce3a4883,cae73e23) Z8(9bc5126e,41b06448,6ad8c379,45ce99b6,3fefc3f4,82d86297,1093705a,5c046dec) Z8(2594d68b,19218519,93b1a9de,bbaa9bb7,5300853d,a63f5a65,115fe41e,a72d3fda) Z8(75bd1052,83f9754a,82050f07,ce9da08e,c6670b0a,af7746d9,0d2f9b52,649cb117) Z8(889cc04b,98dbe415,1d73f8ff,40baa433,4d054479,980b04af,9f46a275,08543eac) Z8(9dff9c34,31f8c999,15d5b9cc,63a5cc81,784b6fea,e0aa8dfc,edb24df0,5ce486c8) Z8(1e0874b4,fa954d11,5e779eab,5cc791d5,b062f132,8d5621a6,ee53e339,53bfa868) Z8(ad0a7cd8,466d2d68,763bea96,e4501215,9bbf331c,de32cd89,349ab6ab,d46076e1) Z8(a9eeb413,782eac8b,d1a934a8,ce2177ea,7ecb1528,6d390028,b9c5c626,91826012) Z8(48a980c4,519e1d36,51e15969,e5faa444,e79c8285,b8d357b2,d1a03981,c30b0f1c) Z8(f79b596f,8403e99c,d534130c,aa97de76,e0b7fa90,6830eecd,5dbdb7f0,7cf69425) Z8(0ef87b83,b3779cbf,e9e87df2,9210b736,edf97d47,26b8b7ed,2618018a,eb4873b2) Z8(98d733bf,fb9b9bee,014eba0c,5f95e12a,e37a42ec,629cd4f8,3b879b05,e21f2efd) Z8(2499fa5f,4d9b0d3a,12d873d9,606448e0,7bca3263,cb7b0ae8,4869edb0,887e4554) Z8(ab00ad8c,801acc25,3c4079b9,79edaa31,7afbaeaa,f977fcaf,fd0cc529,88f0d7a7) Z8(3dba8a62,e1ca3ea9,541e37c9,02cb4d75,6ca61d48,1f3db333,e21eb148,cbe7990a) Z8(b3ea0e6c,eb9e214c,9b5c63e5,be201df2,9f125b1d,a348ef4c,3a18f632,e3821dd4) Z8(d849a43e,413ddca5,869d50fb,e25be4f2,fa85146e,d0ba3748,286c95b6,62c934e5) },{ Z8(9eee6d63,372ea0c9,72d0d4e2,ab31fde4,d0ae5167,88bf66c7,9e35937e,0e5d3747) Z8(2fb2f8b3,515a49ec,7fdea545,19a2d45c,65762add,f1bc4bbd,6c742170,ff1070f3) Z8(43685188,c4b97bdb,9f6c77d0,8d70c509,9b9cfbfb,1a885086,64405049,d2fabeab) Z8(55445cdb,bac68ba7,80091bcf,3d0ed901,2220be0c,0539b468,80e2a4b4,fc3a1c52) Z8(4ae41a2a,aa9db4b9,98cc7b58,c82a89ad,120cb1d4,01e98468,81abce23,f396e5bf) Z8(58e9dc9d,7ccfdaa2,a5615799,03d9c7cd,54fd04b3,52170e72,897b4050,1b7c37ac) Z8(eccbc752,4a0400a1,deb600b6,da4281ae,60e37367,6e9427a5,433eda13,399718df) Z8(6f30f088,3de59566,f9d26ecb,edd7f608,0b91aea0,c35bb755,ce2ecd10,6c6d716d) Z8(c029f3ca,facb15ac,cc3e5dd5,778ad8dc,ced4f36a,acf8bba3,cd4f7258,8be20072) Z8(474cdbd3,72c477c3,cc7b1667,5bf314e5,bc323bd4,83849b50,487fbdcc,8685d378) Z8(af67b2a1,0fa2fdc1,d2abd9c4,d1420f06,ebdc3bdf,783761c7,5d371945,77cc48b9) Z8(d896bf46,71d96a81,e47c2b32,ebdf082b,cfee83df,7c49b143,29ab3c10,e235c0e7) Z8(6fa31b38,c31c15f1,8f6fb0b8,fa8f8229,ec254c74,c2cb9906,1b4a2bb0,1b850062) Z8(2265d600,a4216346,7420e4d1,79058971,cf15711a,5da290c9,0d747fcd,bed93eba) Z8(9f0e1b6d,dece0d5b,f427d1db,3984956f,0d61b841,a61f8220,bf00c21b,b848739c) Z8(41032aad,9a01e1cd,40ae2d69,de1afa50,a4fc4878,02d11ed9,b3402459,123354b6) Z8(d6fa02dd,e1150332,dd66ae64,1b924c6d,29bfb62e,7bcb42c9,5e2241da,142bf420) Z8(89eebf14,1333bfc7,90b0d39e,3700206e,800f389b,213e4af4,308ff2db,6993bb0f) },{ Z8(6b741d39,0f0c39dd,6da61e3e,81b6c039,3ae0f893,f053a8d7,0d06248c,368f5566) Z8(cc155383,a5cd3be3,359dc1fc,f91a1ed9,19081eeb,2c532c96,0c8ef07d,62294f26) Z8(dfa0b358,d643e5df,6cc27d20,1ecbd247,20b023b5,e239bf8e,0c33d34d,2ea48aae) Z8(bc5f7ed8,7dd86a92,49cd7b4e,5eee248c,7336bb58,e5290661,d4f094f8,46bac9f2) Z8(f9441ff6,b9fdb12d,d90dd53a,e36d352a,bc74afdd,827a2901,b39f78e2,cddc76ca) Z8(04cd0195,09d9a623,9032e9a0,febe2e02,a62c3a2c,58c10d9f,b7bc3644,1282846a) Z8(e99ae8ef,b3d5794f,c00f2101,7b23e663,3fe0750b,f920c9c8,c3fb67e8,75c1565d) Z8(eede0683,935e79dc,7752fb57,3ff17569,2f3eb9e1,5c2311e7,b69c8565,c9261d62) Z8(c02df446,6e21d1ea,59304c28,c4655ab5,4fbb1a5a,28f0b8ea,538fd28d,22d210b6) Z8(14d21f60,1dd8f5ab,93a478e2,ac1959ad,304a87f2,c03ec322,f3667818,8bb36195) Z8(80b94eaa,14e4cd1d,73d712f0,0ec66f68,1c57630f,653bed45,f57f9da1,ee7f2677) Z8(7202d477,318888e1,109c92b4,7fc3893f,79a44ea1,b9d29c59,4bb8281f,62c335fe) Z8(c36263e8,68db95fb,7d9466f0,d3bcf628,7de603bb,3853af4e,99bc12d8,c2c39c67) Z8(f822c3e2,ba3da124,2839bcfd,45116adf,43075665,fd569b3c,e86e4fa2,bb81bed9) Z8(3912b3cb,c544f1bc,45d17b5b,1bcbc0e4,c8de1163,c85b72b5,dd5b3bb0,522e17ef) Z8(cd687ada,62647640,9c011432,9d668065,f714d276,4b612159,515001f6,07cbeb3d) Z8(49edc149,519673e7,5449ded6,6b947146,85651cfd,4fb13489,1a4d4498,56ab8ad2) Z8(2c32a5bd,ca859f5e,af9f5c11,db0a5f97,3cc65c01,e318f6cb,3b27be33,7036d325) },{ Z8(1d23d6c8,f4c63d0a,66a0aebe,1b64f731,50a33f16,0c6020f4,cfab7065,32238aae) Z8(d60d7fb5,9d230f11,f6bbfc06,d3c6a469,e4666ab7,56962758,f4d20450,90d4ffc0) Z8(31d4fe0e,02955286,b6e8d51f,60d34dc2,a1c8f916,9764440a,4d3fdb8b,2caef97d) Z8(817bb2cb,4ced6a35,7ccc3b03,863fa78c,7a16b7c6,6702ffe1,3279c06f,87ad0a85) Z8(ec3b8b91,25be8e48,1151d530,807951c5,123935c7,895075e3,d0f22f6e,f074c3c4) Z8(50154692,0fe6e0d6,4689ad53,ec52b11e,63eaa22c,9d3e3bb7,324e7cc2,fdbe39fa) Z8(51b15439,3d1fa311,0acc40c3,50e307d1,c5f7bc60,919646f0,b24b9857,d5b24f0f) Z8(facf9460,138e11f2,27d04e52,c21436d0,2c199eaa,f966c4ad,bd8b28fe,2520c9df) Z8(a8c60d11,6d47f9c7,25826f91,3f227346,065005c5,80654833,5bfdcbe8,6727a46a) Z8(2c98a686,06174459,52096018,e4a87efc,9f67cf91,92c30765,6a93a397,c9dce75b) Z8(a1089f1d,02779ad9,85aa4abd,7a019cee,9a23f686,33f114c5,2ac08d49,dee18222) Z8(959994e8,4e35b0f4,0ef16ac0,249ddcb9,1c44e85d,87737149,41471f47,5bfceb6b) Z8(ce43a9bb,1505ac47,a3189d87,1cabf207,40e370d9,61eef99d,e4489f32,5f179322) Z8(453afdb5,95f769dc,b1e3dd9d,e623f003,eccb3d82,199f62ba,0963492f,8cb67bdd) Z8(51dd7b53,7869b213,2005ec2b,9e1b5358,dff702a6,f7d75c58,a5ebdf2d,e0b44f61) Z8(f0aa3bc8,6fe9362d,83b4ba9c,a99b6e84,04366583,b75ff501,a0d94db2,bc89a3a9) Z8(431146de,eb6c2f1b,7e9e0009,6770f407,635230c1,43e4097c,c495a8b6,fd4e2c8b) Z8(74b12384,71678b73,930e6f80,b70a0ac3,5e1d4681,b7f222f6,86ed3da2,76b19c15) },{ Z8(15b667b0,7273a8fa,9840a807,850b45b1,1b2df7f2,f3d3088d,b95726a2,29e9979a) Z8(b3dc1df4,5066dcad,7e0e36b4,de66ab89,2e3e261b,0e8b122b,b126e00d,d6d5030a) Z8(3fa11322,e0392a15,0e355b5d,7244a97a,a662a380,f89664e3,6013e98f,bbda6fcf) Z8(22c0af71,784156d0,3451095b,7932345c,02283f4e,94c81292,6d32ea13,0fe04a41) Z8(aeb4d046,715ad559,a661ba73,8e24a099,12dc987e,8f92d306,e1c76554,a54453a7) Z8(f469b06a,fbfb6096,cdfaff8e,934bfa9d,34f01ba0,655165f2,067e501b,83494359) Z8(60a5c559,d628a58e,148f694f,99d31618,e5988f86,c7a39727,2d6fa557,724bbcb8) Z8(d4da6b80,adb5025b,f4cdaff3,787007be,a793bd29,d5d47e39,2d25c5a9,c1c94a26) Z8(a529fef5,433f244c,dffb7eff,02b2e484,5c17c36b,20f3ae3d,355a26be,41065570) Z8(3fe03464,97a483a7,e0b396dd,5b483b3b,5f1d73f1,ac7c3656,2836f885,54265867) Z8(45c4491c,743dcfa4,b69661a1,46dbf7ee,3ed9d0a6,bde310b2,6056b2cf,cd648174) Z8(750f8448,d6699bd1,91ffff07,fe9d73e1,37f00b0b,efcd1c93,4db12f34,fe799546) Z8(35deda28,414e99a6,0221513e,47d654c4,ed975002,46089f15,3caa9143,7ffcd20d) Z8(bf58b8ee,6dc196c3,2b7d2098,c2a51d58,fce87a7d,6c4b7e77,2ab1f2da,df297e8e) Z8(7f5dfe25,3448544f,cfded89c,9002483b,bfd86afb,59e0c8b4,5c43d7df,bf3c0e9e) Z8(63328bd1,d0ef844a,12f2b3a7,33a838b3,f659ae87,6aa73f67,cf9848a3,593d4e63) Z8(a6dc9901,215b810f,aab03c7d,c83a92d8,c35e080e,12df65ec,48c26c43,66ce6be1) Z8(09041335,b190087d,c5c5aac1,0806496f,aee47661,33691e3e,50505f2e,7d03742d) },{ Z8(67b0a00e,ab068405,8d448d4d,09069727,254a8786,e100433e,f5f801c8,62f7ab74) Z8(ad439ab3,78c7512a,a462b61c,49d9101c,837ff50f,d7295d8e,f249a94f,7a65dc5b) Z8(12a5d604,bb3f4467,9930b909,4c27742d,43a22a1a,dcbb7e7b,12c55106,d37ea13c) Z8(4ce5dbc2,7f0dfcfe,cee94fef,83100a66,f4a5527a,55d11911,7531c70e,8e5a0551) Z8(e64eab5a,1ab2273b,c42fece2,22dcabdb,59770442,ca46c9b1,05c84522,070c5f25) Z8(59e5d6dc,49c0bb14,dfebe41c,443047d1,b39c55cf,127c6ac9,3572ac90,51d8366f) Z8(6197e352,47aa0ccb,55dce100,e46d868c,6e8dd747,e9ea4710,fc9927ab,f433c4ef) Z8(ad2efefe,e1890002,92dacaa4,49c4bb32,ef5bf268,ee096a61,e15fd069,41aae817) Z8(d88a6ef4,7ac4cbec,3e038ed3,9f4f2339,a89980d6,1cf4209f,ba2bb21d,2e1c0c39) Z8(b981b44b,922a2f9a,eff9135c,3fa03deb,c3366253,1ccffb08,d099e4fc,fc940ec1) Z8(9db366ab,b2aa9b4d,0671a515,9267b805,42b849f9,1887fe0d,f855b281,0f22bfe5) Z8(1c4fc779,945867d8,3280d00b,cc2cd433,d538fe73,070bac44,845f581d,970edb35) Z8(463bff0f,228108bb,de73e867,fe5638dc,15f03a7f,054e8ba1,443b0157,a722093a) Z8(03bf444a,612a2263,6a9adf1e,9fac12e7,ba4de235,284d8977,d69573ae,263728c7) Z8(ca543257,2f1a6972,ce264b5c,65f68207,0d8a76a5,57950537,9a599111,4d97718a) Z8(8b162808,9e6f48b8,41b9907a,266c344f,6671d2e2,b2ad63c7,735d76bc,be85a904) Z8(f42af382,6ff1ea97,53ff817d,8e2871f5,d4bddc24,82c3bd5b,d4f13f4e,43d7d60c) Z8(1e5b65d0,55c6bdcf,774ddfbc,f1155cd8,61a515c0,4b6a09cb,d9867e2a,832bf4a6) },{ Z8(2c7cb346,f34972d6,a19a82ff,c6047f47,9aa3d1af,78a9646d,874b47a2,a0c2f020) Z8(d8169f08,9f5c8302,2f7cb6a7,22057492,342e58ba,4b5f60de,6a522393,dc7e3943) Z8(5fc3805f,8c1eb333,e86a21ff,63e6368f,bfafaae5,0595e056,9fa3d198,aa13b66c) Z8(cfa5be6e,312ba1c2,fd8aff1d,77d5ad71,96892eba,d2072a0d,c4a67b22,fcd5ecad) Z8(55f9d25d,54cfad28,44826f5f,0c755fb1,6e8fc708,b19b7fe7,a87f65e3,23a7ca7e) Z8(c94ae302,b870b33c,aa5fc11c,06703791,5d97582c,40454c79,3b4c4034,ecb027ba) Z8(2a335021,d5634463,778be097,708176a4,fe4eea52,75f1392f,63d4158c,5c56e73b) Z8(f393a2e1,2da4d728,213412d6,c473c994,f43f943a,15ac0922,a3dec077,2e8e2600) Z8(cdec2769,e8c75f99,222b97ba,3fddf612,105f1634,ddbd255c,9152c444,3743c948) Z8(fbbe5ac5,34c632f2,42c09ed0,becb6283,a2661712,6aeb4e68,853002c9,1d239602) Z8(a9454d9d,6f643daa,8e2835ef,88f812f2,dd6d3379,1dfa3e97,a1180950,1a72df4f) Z8(7f0f7646,252816fa,f5714178,209fe04c,95371f46,b064e14f,bd79cb1c,ade988ec) Z8(c851eb54,4ce9e89d,1abbb62d,6a0f0265,160a867f,a384f2af,99d4563a,dc1d4322) Z8(0ed73499,57691205,94a75236,95dfe79a,242bed6d,7e71215d,aa3bbe45,90887160) Z8(00fe9e13,0c5c8ba5,50cd8206,37092d59,9762a7dc,5a3cb336,17077b53,ee6e36ca) Z8(e697f861,9a59ea31,37ba75dd,5e35144f,3c03f196,22bbff9c,914c7211,84d32e15) Z8(edb50f83,998d73c4,b2b51bdd,f42337e8,dfa2ae57,a2d08b4a,e396f760,31205dd0) Z8(65ff600e,28c0a22e,b9ddf67f,8fbe7b9f,472b4afb,094478fc,de9547b5,892aecdf) },{ Z8(4cd57851,7c94d031,06063a22,27443c2b,23fc3937,1f58e504,b04dc1a2,42116506) Z8(726647fd,de23c3f6,1eb711b3,aebd28de,971a72bd,1f5a9067,8afb30dd,8d3926b3) Z8(6f534d1b,2e30d022,14f8b9e8,ed5d96c8,93a94329,3f64c51e,c57277a6,1ab3fa5c) Z8(503ab9cb,f94e70f5,a7f09f6c,a87e4bef,fe4f4020,d6948b52,fece172a,d702f379) Z8(1c3fee63,34df8b20,33494168,8b9dd91d,4c40a33a,d7288a07,8a79f696,1756d634) Z8(3c5f0b31,c729e0aa,2fa1a54b,348a3b17,36328870,85d047c8,0612643e,b6636185) Z8(f2324a1c,5536076a,69d7f17c,2200b3c2,319b9ae3,234daf4d,36aef9f9,ef89efc1) Z8(ab16409b,f20a6e5d,dab19a6d,50c66bae,21656735,67698a98,1b033370,db924f31) Z8(d922f0f5,05075958,e652804a,745d08e8,c21f3fde,8c062ce3,c259b589,4e8a732f) Z8(f117c882,fe015848,400cfc00,3130e701,3052d9f6,c793c5a2,755419f8,0a9d5502) Z8(0fce6b7d,162e6e28,47e97254,7eb196d3,7d3bf76d,943cfa7f,3cb604a6,da3a261f) Z8(e8ee8b23,f462e026,5cb2f727,18ca874f,1b55bcd4,61259e84,8a57afd3,1dedd69b) Z8(14246e90,c6d415ba,70ab2f55,e3fd231f,99c4d8d6,fb5db361,59d7338a,341b6c81) Z8(20ab4f9f,d7c55a29,fc66530b,b2f16db8,be2c0bfe,ed1ad15e,e1bc6398,aa0ae62a) Z8(6f27ec33,2b6cd269,bc90c7e2,5eacd843,0cd9e15f,1f4e7c2a,f3cc4a1d,ac46b084) Z8(ed9c5298,1d3c5168,fffebb46,a6e8474a,2b7c78e3,4c84abda,70b8e8b1,b537a129) Z8(a4333141,358f6440,7e523acc,29c4ed1d,073d6a58,66cd7dd3,918d712b,3669dcd3) Z8(13389eb2,f53da46d,652b375c,918a67e0,65c43747,5c835e16,f7f59f9b,8f005d5e) },{ Z8(caa9ebf9,46a6fa1e,9a1d2159,233b0652,ee628099,69d65f65,ff5c3234,0d666169) Z8(dd9c8030,90556008,9f51a964,6f525981,e4a99a03,4dcf13cc,565d6e14,ced12c7b) Z8(079ebd88,59a1b35f,b63acf13,93c39fdf,d3c672e1,27931a0b,c0856df6,9f634266) Z8(1c46e066,6eccc075,3a8ac484,0b5dbb16,597c785a,81232417,d3f7cf1f,41ee6129) Z8(2530dabe,4aab6a6c,68755d93,c2f13e15,e5a3fc63,1b123ac2,8dba2742,238d3932) Z8(e2e2e172,ee219830,db17415c,34e71889,875e2dc2,95d39e4e,4247165e,79713423) Z8(649ba08e,08bb9737,06ee76d2,b6d3ee08,3266b144,e5b901eb,ba77cd50,448a0b31) Z8(b4cbba8a,a2f90020,415414dc,b4e5f910,2311ea59,646aab04,ab2aadf8,d2613ca2) Z8(2ff6b548,588f2ea1,245b60af,f4a8f0ba,cb5cfbdb,a4c50c64,bdacc078,288a4838) Z8(1308b298,6388af30,1195faa7,e4c6a1e4,87525493,e91458f8,693f3896,d29bc367) Z8(d1e2242e,822c4988,1f3f3fad,5701e2f6,bebbb0be,b920dc6e,eb0c6321,9ddf478d) Z8(2fb2b8d7,b4e5505b,50fe8007,2bc31c76,7c589af8,f6f1ee80,b0e1ee96,47f4f3ce) Z8(7cea0cfc,533af2a5,85341ef0,70b0223a,80dc3524,061a3edf,b8f94ee6,82e7e4e6) Z8(9f5f54c7,71d88859,2190a1d2,05e268d5,00fdf85d,fc13bd23,ec9b9356,f1b765b3) Z8(8f8cf5e3,f0222aa6,3610ce00,28ddd939,489a74c1,39696ee0,f2239d7e,c2016017) Z8(5d7b3e86,eaf70f03,fc4c446a,879f91b0,2bdfe01c,e7d3d270,81e2c773,95ac8cc7) Z8(0f2476cd,3ea57fe0,9fc8cdd2,307f9223,2342e027,892aebb8,b97e806e,366dbce1) Z8(8031c786,2c6b9f78,7a945eda,f38ae0f4,f78a32f8,18c4f393,847186f6,94ac72c9) },{ Z8(24670f4d,02a0a08f,39df702d,0fc067de,d901eb1e,c0ef55d1,68c85800,ba36deb1) Z8(91ca6f7c,aadadbe8,0d8ec179,85e4ac59,68a34de0,aa88127d,b0b7f482,bb61ffd2) Z8(03e97a24,8498cad4,de246ca1,4d6c46e1,a996d6e9,7225cc34,60890de6,b1d31d9e) Z8(c99a2d3d,b1c5e1a2,4c0ce241,84ef3c9e,b13028cb,8f72e807,a55cc595,78622acf) Z8(d0724d8c,cf1ec0f4,38be4361,57c61852,7224e8a5,5ed5ee2c,14d6a055,ff98c821) Z8(e8be5554,714e7555,d0089960,3e1f1de3,d737fcde,11d45cf3,ca64c72a,8a3b3257) Z8(2a92e475,502109f5,bedb90d7,08f7c667,31621080,115994ab,7aa96dc2,92111a4f) Z8(8d19f6d5,d5eaa43e,5bff1466,b730cbac,59ce4b61,c145f8be,e8a01235,3cfacb4a) Z8(f3029a17,05cbfe88,52e42f61,e1d2dab9,0651cedd,98af6fa0,91a11324,ee325539) Z8(2e256220,9eecc1b2,c1da5150,d69ee95c,2956324b,fa8efa39,d92c97a1,4f323d2e) Z8(9fa951a6,424db729,84c425b0,b74ca036,3bc4bd8d,0e7fc493,b149ad1c,d8587110) Z8(7148c1f1,91046d27,920cc78c,19c2cc7f,52d964c1,024d57b8,65f2e2b3,0985a16d) Z8(d7f3fe6d,e9f6db11,73487793,c15ea1d6,b4be7f02,0adedf90,819207ed,0b06e5da) Z8(7d21f692,5bdd041e,4cba4c83,bc691f62,3b94dd3a,14f7f1bf,d109b4da,1915baa8) Z8(ba8b333e,1c17f075,d4659f64,e2a9aa48,8de7acd4,13e21b1c,414e4f4e,662f8be6) Z8(abc86191,5309fce9,017c94b2,09ad0a86,3f57e262,f5fcf696,efd79475,fa404335) Z8(1408e1ac,e9e70d29,9c44fa81,098e55dd,966bda9c,11620ae2,b74ad88f,4ccdbfe6) Z8(753afee4,77874d1e,17489d5c,dae46f06,204ff3bc,4226f8e2,71bdda20,9a2f80e6) },{ Z8(bf71a78f,5b1e4424,45e8da61,d7794c76,f1d08a8e,ae252e1b,e1a44146,2206224d) Z8(ab93237e,0fcaafb7,25b2e28e,ef5b18d0,acfd56c0,4ac984b8,89722222,bfbd0133) Z8(9dc6ad9f,60ed7ef6,12dffcd0,24d106f6,d7cc504e,6522b0da,173d9dd5,82b75419) Z8(4285c92f,530c6698,51a5ade8,52a7ed65,f3c32ec5,4a7799eb,9e3537a4,219ceba9) Z8(08d6163d,d971199e,87230a41,0433bd8e,070e92a1,749ab22d,19a4ebe3,aed3c015) Z8(59f85a75,eefdd797,6e0e8f11,f637dd5b,41aa1ad4,488e307c,3b733549,91269719) Z8(91e20cd3,f9eecb93,a4a4725b,51d5d9d6,d7eeb7b2,1fdaee7e,2220005f,db72044f) Z8(7f7f7bbb,5385b977,49b1f19a,684e49b0,35ab617e,715d6c46,5cc1c3b1,a7c238b7) Z8(b2907ef7,fc1cc7bd,80f5d2c3,b3849b69,137aacd6,57a04b81,1f0b7eaa,cbc2dc59) Z8(be3bba7e,9f55df17,cfed2a38,a9066d08,103a9f3f,07700e56,4d7e5bcf,a2a43890) Z8(fec4600c,90cd0a59,fbfdf4b8,7d7dac05,5e34ed9e,ce2717bb,3b3db166,ab2b962f) Z8(e1f164e5,091566ff,525e5db0,d1493d6a,b040214d,5d90f330,3b04ea5c,f41795c3) Z8(28dfce48,6d73c74f,0ce42dd5,831d9e30,a8f80416,d8e0721f,7242edfc,9c612494) Z8(c3042cc5,737a72ac,b7db2e30,848969e5,641da4e8,9e27dfe2,933a9c73,860a4995) Z8(adbb3d2d,513a89b0,73b3663e,81dbab57,2a41de06,d6d4b3dc,554f4806,aa5a1c26) Z8(4af39e72,0923152a,e1938457,288fe6e2,7254f5f5,520959d1,8f8c0c5f,e34916fc) Z8(2c6123c8,149416e9,ed899dbd,4a8dcdfb,67674a8b,2837a0dd,77858f46,db768830) Z8(1c6f4dfb,00a35bc2,c801acaa,9d743d1b,4f0701df,f8b49264,f4b7a1ec,9f89fdc4) },{ Z8(93509d04,cd71ae7b,d06818b9,52d2eb12,fdefabae,9bbd75ee,6d5e3167,cae73a03) Z8(7434b0f7,268e89b7,94e80b50,2429278a,926fd0ae,44d2d95b,91d066db,71403d6a) Z8(5ca291a0,7e7f1458,3727360f,abe159e4,247316f7,6d1fe37d,86cdca07,b4a17cbe) Z8(182855ec,8d8f00c6,b1c83f4c,938dd336,4eb320ac,a231bb29,38d22e80,2f683dd7) Z8(ca40b8b7,fafa267a,1e7ddce3,32728915,7865152c,3e57c6c8,9d99366f,7c34709e) Z8(699290cc,97a9c409,c8953f2b,72627157,a454d35a,faac58fa,714ccaf2,3809da3c) Z8(d8120dd9,96a3edfe,39774c28,931e6883,c6529741,73d9145f,5d62f06d,dc5219da) Z8(f42c2da0,eaa87b5a,2611f11f,69eaa3e1,9c8f7d83,84f4a554,b3dfee1b,59fcc270) Z8(2c04baa6,d65c1157,680f31a6,641b0d81,2905d14d,9cfd13e6,dc4f2b6a,6ec9e0eb) Z8(5ce11aa1,4bbcd467,a9b1095f,9ddd2112,7b3c79d7,f04ed3e3,dc9096e5,463d3b51) Z8(7c28368e,4bbb0da4,fd4c5eed,6662f43c,e10d9b4e,c302f329,dc72ef8d,6de147ec) Z8(a9f7abf8,d6bf3110,0ccd58af,731bde7b,a60ed4d9,5ca3d94e,55810690,7e55306f) Z8(9395b890,9d3195c8,163c6169,2bc8d87d,12696146,1f0ae4d7,cce7f1a5,0fe94456) Z8(56b73170,11bb7e56,dd42ea3c,6c7e06a4,dfb0e026,d38bf4d1,e7830c60,b8bf8797) Z8(94f0b08d,40e12c45,02bba5b4,47ca52c1,19dab12e,a2a213f2,acbe8170,9bd5a95f) Z8(d3bec7b9,fc9e6b9a,e0a3faa2,c4c7dc64,44030fce,79d89bd1,830a6228,4ff82399) Z8(5480f6ce,c8ea0ca4,e782285a,91742ccc,d3d024b3,5762206e,933cb84f,a7f7b7db) Z8(8cc4ef3a,21486665,eeb2b9e7,e3f08689,457dac9e,19a87f2a,34f70924,a4bc7d19) },{ Z8(a03eb72e,d9368608,6b4c73f8,031234b8,19edcc2f,01bb895a,aa302aa2,d4dc4c45) Z8(0ef99efa,35ffd32e,dde0e6a6,cb27bb6c,db9f1a4e,6d2a791b,ec534613,b5949222) Z8(aa6fa2d1,7d6f9ade,6a50397c,a6be69bf,a7fc5a93,11bae4d6,37daf598,1782288a) Z8(fdf3dc6a,73942899,c88596a1,7297a9ae,a4d081e8,e170d9c8,714bdcfa,efdda0d5) Z8(efbee69d,24e34fda,42c3160a,c46a8be5,7bd5d4a6,c20bbfdb,aa7f5d28,24679728) Z8(a7af2265,2ff2e66e,bdee6ebd,d6b35be1,dd2ac650,cebb8f76,2edd164d,a06a7db2) Z8(32a067be,11f8c0f7,5db87ad3,3870fbcc,a23c9e5a,75b79aa3,188bd284,2ea67748) Z8(056e8948,61d5fa0f,07218ebd,afb653eb,967a414a,2b083fd3,80a769b3,f980b296) Z8(736e92bd,c6c1d5e8,bbcfe8fc,e9abd652,7372b315,5bdd9c0d,6c65babd,286530b2) Z8(55c295e0,2a9782cc,26d7c0a0,53b08878,d8e95072,dca0a169,fd97b189,03b7ee94) Z8(ca574678,679b1684,b34e6146,94de4fc8,a0afc792,9fd6e8b9,054455e4,e673f0d6) Z8(8912e931,2c4514bc,53362120,9f7f541e,f25f778a,8427c0eb,43e1bff9,d7f0b290) Z8(4b4a8a2f,b8ca42fb,7e38a883,3448ff3d,8fc49fde,736dd663,08359d39,be5493a1) Z8(687a822a,bf21bb60,73d0f571,be0ce6bb,3a39586d,290cb3f1,ee1496b0,070f6a00) Z8(9f6a76a0,653349b5,f9c485b7,6dd6c325,aaa7fbfe,3a2d3b95,9ba8ac1e,dfe2b9aa) Z8(dacd8e0f,6562fa07,e2420702,dfad7e18,1179cbb8,49d000d6,3e230bf1,43055731) Z8(06151b1b,85c67da6,f8431ede,72eb259f,0562adec,ff7ad99b,36a1ca19,45931d74) Z8(7dbf5c4d,094f003a,e427bf1c,f9971655,be7933f5,916a84b5,4830f5c8,a9c7abdc) },{ Z8(56b9327a,1e7d0c89,6beb050a,62ca6465,cf242693,ed36df44,7947869d,3b094874) Z8(5d1f1a54,f1d36093,9e8ff5fd,11dd61f9,c4e1872e,a870a1fe,6d280e17,164b1f6c) Z8(55572869,e1891a5f,551fe6db,7dc645df,ebfa1bca,1af04ea1,a9f01fd9,504eb5ca) Z8(e70840f3,dc6aef95,96e11c06,eef8735f,446ab3ee,c3cabac5,fae55182,75130e86) Z8(37411a3d,f79fd06b,fdc37e2b,4d43cb52,519daf63,fd6e787a,45b0eb5c,1eb68214) Z8(e544698c,2a2a5156,67700e30,571938ac,3ed096da,3b1c301e,69fb9d4b,0a13d78c) Z8(3851c046,a48a755d,8143e64b,55e5e5d9,3d43f6f5,cb91a2e9,1589fd23,cfb56e0c) Z8(ffbe4f1d,c83db4bd,83d1e710,285a2fc8,b3b70ff8,cfcbea38,69328618,7e65025b) Z8(05e3a039,c2cc249e,46708836,fd5b6e0c,e8d8d9a3,1b6aa661,43789d88,435f61e5) Z8(ae0435fd,719ebec9,53d25fff,d6a33c5f,bd480f81,a6981a83,1199e32b,60bf09a9) Z8(13bf4f14,c69467b3,e63b0ef7,cba22b38,7f8caebb,58a0c723,5b7edd8f,767a6b1c) Z8(042fca7e,dfc91d62,9e8c71b1,000d2465,49cfb845,34afd431,6987a3f9,d71a5f17) Z8(9f8a9e4d,4e104e71,4b2c13f9,d02f596d,1c1d2b2f,8b2ca273,aca3f091,e937dff3) Z8(e1ca194b,9d25c580,4e860c94,8e44c949,d3add568,bb8a7001,dc8dee1f,aa2fceb6) Z8(ae8e3598,7abcd96f,28dddb18,071683af,2c6bbf0e,2c93ae4c,71edac57,528380db) Z8(11bd84c6,e789f8cc,1c30d8b6,51029433,b115d3e3,711d77d0,48b5f4cf,11709982) Z8(c53c2cdf,5307ed4b,3b746c2d,3fd6f785,dd439af3,c6586fe1,eef1f3d7,95ee0fd1) Z8(c44fdd30,04407947,43effe26,03742b46,3e52070a,14725e2f,b4d8c080,aeac4c38) },{ Z8(69687098,7cba0a6d,4a0fd7c7,1c121b55,faf85bed,ef924902,fe0d1809,919599fc) Z8(64faa5dd,fa9c88fa,b0dd77b9,55511c16,95c9d16e,cbbac66a,2806f7fe,907e49f4) Z8(ac40690f,36633250,82503344,a9f404d2,048e3a5f,24883c92,41ffe3cf,a5258399) Z8(cd1c5b0c,4cf5572d,2a4bbc76,f53713bf,db657b07,7ae8ccd6,8cbb3586,e363fcbd) Z8(2742dfc9,afb801e1,a22e736a,fe2ebe08,08a54e2d,d482fd81,f80aff48,58e9e4ba) Z8(d00d1732,4508e6a0,a8ca6ddc,2586e09c,ad6a4509,fba08869,5b7de948,36179b8d) Z8(8612107b,37d6e406,6c01b1a9,e1e782ab,f2ad2ad2,9063979e,e28e0080,7c7cc766) Z8(f263d679,51119cc0,7df43885,62774128,f13cbe5f,e6943b41,ec5a406b,c6052de0) Z8(b782cc0e,7f8bb5b6,38c308e2,1dd640e8,f5537c30,d9a6690f,f976485a,cf2746d1) Z8(41ba378b,78955a98,fd0c4a66,3088b314,778d28a8,e62f8cf1,795fdc40,9df90e12) Z8(3d30ac25,90f93abb,37f1a623,92eb7cbe,5521edeb,4d340cf8,c0740a13,dfffac20) Z8(bbece057,d34625a7,a88c1547,05f9583a,b7ceb3b7,ad9251ee,805fad37,a50d6e7f) Z8(c44a2c77,9599abe9,6a8e49ff,e0bb5841,f8747207,1b633b02,c8a3507d,066b1b54) Z8(91646d1c,2b102d1b,dba8181c,891c085f,d02d7ed6,a63f48c7,bb54ccf8,a9bb7822) Z8(46788739,0fbfabb1,29467761,ed94393a,6b0ed4de,43a1aa2b,11261990,038c1815) Z8(b50e83d9,5df74865,4f199b2a,d7161160,feed62cc,da352cba,a57f54e5,4d9b0fde) Z8(d039ae93,4785f476,9e977afb,0cfdc69c,fca71d8c,70c045a9,ef498a57,43ac8c5f) Z8(409dcd1e,751e5dec,0783f6fe,e469ff28,4462f939,59014174,1f043691,b36b31c9) },{ Z8(9d11d977,e7381d15,9128302d,2e6b7838,3c4245ce,41b82fd8,374806db,379b4c9a) Z8(cd90de89,f6837c1d,47a36b9c,dfd491f0,f97b789e,0a076168,dd69125a,12fa3f90) Z8(3a8f9a03,a93885f8,e724d190,18b029b4,f372b625,b06ce708,e9ba4420,d03950a2) Z8(73b0ce2e,70bc8beb,49618b75,40aed9d4,f68fe7d2,9d315cdf,44ae4246,ef790370) Z8(3ee5dd8d,f17685d6,5aba4314,5d17b033,95a6f5b3,d5b79ce9,a5eb0431,df4dce26) Z8(90ce8ca3,72b88846,8cfddfb2,07d9719f,93998c9c,8e22b3e6,7c29621c,12186d8c) Z8(1df6340d,a78d5279,7479133b,0e623580,61acbee6,33dc3029,0a546345,38cd6542) Z8(9536db06,c54c1409,f8663f10,f18f4ca7,ba6a6cc8,e880352d,5e6d7d76,ffb5cfa7) Z8(bcfb2f08,f4428521,5abf6f4f,cfe4cadf,a56d056a,3ddd3354,5a4f43ea,276f11cb) Z8(5925de0e,4c6f36cb,a1e219f3,4c64cc00,c5a9d03a,55aa46fa,9e8a169f,b847f6cd) Z8(fa231cbd,4b9e90f0,f6c8679d,68e875d9,908c1548,b3527466,9212e000,73a96eb6) Z8(ec3bfa51,6c25ae97,2c737115,29ff348d,fc470980,6a36a59e,c8521a32,7088ecdc) Z8(ddf84780,f4ad6779,062bdf11,11fd8071,8df67aca,5662675d,a96198d8,b3d2aa71) Z8(8c064a69,7d90fa2d,e47d2110,582ea46c,c1776a0b,1adce0bd,03fec39c,5d9a6842) Z8(d542c019,baa246e3,3973153e,71452f3b,de1b70dc,8db35060,3bad774e,f51d7e62) Z8(952a0849,8817ff1d,9d2b4cea,f67a0a71,4e757ad2,146cd2b2,38a6203d,b4ed0b1b) Z8(945e8cf3,38257e41,4380781c,e8c53e21,2668272c,49c49ec7,cec98182,4655f065) Z8(64cae530,a012155f,14c79a80,3d7aecc1,10a4443d,cb2da552,c2319e73,b8053e2b) },{ Z8(d4b5d264,c86bb317,ef343f9f,79eea9de,420d4daf,bbcb7c11,18ccfc25,b5c4ff16) Z8(48c55b66,39a321ee,e661ff05,3d736972,60035f89,dd26e538,8ee379b9,a3e834cc) Z8(e635a236,ba9ab0cf,1723bb20,05b3bd89,7821fddb,e098e4d3,c3548295,e542f0d5) Z8(b417aeda,c453d481,23a3fe7e,05fc797a,f6de812b,ab0350df,c193ed33,0a63b55c) Z8(00e12381,324ce0a1,6d76f461,6edd5b4a,7bb92665,c1f5e3e4,bf0ecafb,f7b2f662) Z8(b0ce7993,30ce6feb,653f3ff3,d5bb2d2b,c5c260bf,e879c25a,4132b999,db7ac3e9) Z8(934389e3,dc6491f5,958c9ca1,530ae175,e3aea9ba,ee2bf50d,ed7fd728,073e4805) Z8(7a5a5889,84c600ab,c6ce8979,c703ffe6,bfe3333f,1b4d4722,7fb2cf44,6915020b) Z8(06a345b8,1f7ec658,cfb4e3eb,4fbf14bd,e6079781,12a0c6ef,e7b58794,9943fbca) Z8(aff9091c,1d3364b2,e9d284eb,3350ba39,3139c9df,a4d17630,8ba5e0b1,57c89ab6) Z8(18002c16,c9f0f2c2,5ca234af,bcee6155,c9c655ac,c88e0381,658325a0,9b74aa27) Z8(84857775,7f50b381,a690cae8,3ce32547,8dbd3fd4,48a17fa7,d6569a4f,0200153c) Z8(c6289c74,6ef14fd7,ed96088a,1509884c,804e33b4,29ebbb8f,27d37352,07eb95e0) Z8(2dd460a0,5b6b1b96,a8d35f9f,eb9c3f18,0107dc6d,31e63e04,0e2d33be,99d94270) Z8(f356ab87,0a219e0b,cc0383a4,4c5c1cdb,cbbaa179,5bcae903,7c9c6fd7,f52a7a4f) Z8(a5597967,922f0c49,5f4676d7,9cabf63b,943f8efd,92583a04,1c7b8bec,483c3161) Z8(c4c3c40d,994e9987,5d58da8a,920ba34f,d050067c,d4140c7b,569845f3,010c85fc) Z8(5514a995,231796bb,5ba4ab8a,13fab81f,e80fb290,d4113006,e98af280,bc7b5dea) },{ Z8(81de9d80,03b223de,d039c61d,7e1350a3,b41e3854,03b24867,53bd5c8f,fb52b21d) Z8(d0352a8e,6840e2ca,fa0842ae,5aec252b,c481027d,cc6e5e2c,081494ce,df91ecce) Z8(6f14423e,3d41b0e0,21675e1c,9858334a,b27653c3,6ac4c295,7a237820,af22dfbc) Z8(d4f409c0,4f5b0586,a5df172b,b2265cdb,f0489f92,158b5a06,243d98b2,4cc4b98f) Z8(74d35428,2e7ca208,af3560e8,3a876c71,1906e550,f27dbb63,f29cc6f7,29d810a0) Z8(1d789cc5,100a91f2,ca8da484,752caa9e,f3bcfb8d,e0595b00,5dff6ba8,8a0a2f02) Z8(cc782240,6f32870a,69b3ffad,a5a0ba2a,83b5cac7,57bf2cd5,e92290f7,c9152cc4) Z8(2935b365,eff21108,1247bfc8,8c077778,cb031e91,a68f9b3c,1869a20f,4f453917) Z8(aa4ab122,8b4e7dbc,8d412247,d033efbd,c10198af,ed731db8,ea108367,7a5ec9f2) Z8(72955ae5,fe2bb72b,af465492,d52c0a2f,35715140,552085c6,57dbb962,4a151a44) Z8(f341c314,87d3e68a,0bc84da5,3d9a69b8,9edaf68f,e366fd35,5cd6f003,8312631b) Z8(5f7d4df9,2b6a2964,38d67dd8,6c52004c,fc3ec8a9,1ad0721b,b501bcfe,da3a9b2e) Z8(e6234172,6ac6cf92,9043c38d,4f79b74a,bd49a944,da866c15,80b9acc1,8d70fc6b) Z8(ee113e6e,823eca41,d001e26e,c8957830,896bb351,6ada4790,e7a9eedd,a7cde098) Z8(03e0aa20,c09c3cec,c458a36c,c05d176f,952dd883,89da2be4,3a7a01f3,154423cf) Z8(69689b35,16e76528,1cd1ca1d,7398e294,a3ea8816,ff22073b,d98c6dc4,b3824d04) Z8(990563e3,dfe86b83,ac95ccb6,3ad03636,485bc5c2,a34ac5cf,51a62f57,44ffa53c) Z8(a10b2d25,37081467,aef436f6,d58ee867,6e92fa24,89dd62c4,ac526640,c0ce85b8) },{ Z8(bbeb1a29,4328117c,71cafe1f,018db6f2,92f225fb,c63681ef,15fb04e8,190e1926) Z8(a1c167c9,ea706133,8f8cd082,9e1ee94d,5a757c2d,7363dd22,e52d76b0,d3689e8a) Z8(48da8ace,b17bc881,6a589d4f,18cb5df7,75e2bce0,21cdbd1e,145d4827,1582e3c4) Z8(b401684e,9b6c077d,938ef323,29f687b9,5992d78c,bd85681d,086382e0,8a42abfb) Z8(31cba5c6,932f0f49,1424a207,1686df35,6000be26,3e246d4c,951ead5c,cc5453a3) Z8(080f85e0,be042309,78646572,dd51462c,8c6bee70,345e8209,4b896e0a,8c271488) Z8(422b194d,8dda6cfa,4a55ba5d,349af5a2,3d52055d,72acdb4a,adea6229,9ae13f52) Z8(2768f61c,06b3b391,4fb50b78,a62e0fc7,4d648251,4b8f850c,77b35dda,56286bbd) Z8(5be2596c,1061a783,4108d8e9,6ea5ef1f,1586930c,cf230192,b7b74435,fd232313) Z8(74a5434d,b8e58b49,4bcfe2f1,f6a831ab,1c8ae45b,0a4d1589,4de3471d,50097313) Z8(db216163,c3fd9a75,bc33fada,36e724b5,a50c86a3,68e3b607,e3c507d1,9df08637) Z8(17dd6bff,c4ccafdf,60e232ce,d9f546bc,79be3645,73135e62,a934eacb,59b99cb4) Z8(050c17ba,45e804e0,c304867d,ed957369,2d101f73,261bbf2d,bff69efd,b89bf286) Z8(b80109d4,bfc84e09,0b27532c,2adb86cc,d9e7ca85,2bd3c648,677c770c,860a284c) Z8(b444f7c2,192de355,84bd6d21,47db6fe3,0f64a8a2,94b53592,e4a4ac8a,9ead20cc) Z8(317ce959,951dcb80,6781f28f,ff54b364,c29c132a,974f5c21,5162ea6a,a7f99074) Z8(d28d2f5a,098b6ca9,0006bc9a,24ed1b16,f8463c22,a068eb0c,45c51352,b0fd5694) Z8(4f97d1fa,fe669d99,0039834e,4da621b6,bc9e0221,8cb43d10,bf8fbd54,c4ffaffa) }}; const mp_limb_t arb_atan_tab22[1 << ARB_ATAN_TAB22_BITS][ARB_ATAN_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(4c3ac38b,589e430c,2e6f7f91,c289fc70,145bf0df,0c3692f7,d6d8b040,44316380) Z8(97514b37,acaf17b3,e68a3c04,aea607e9,0af2544d,a32eeb07,b2b1aef0,946e52b4) Z8(da8596e6,053e0c45,8d91efb1,5144f76b,fa04c6a8,f3e43dc7,b0f0210e,7cdcd4e4) Z8(61ad9354,e72b4529,ef37577b,0cb3aafd,9c58b4c3,47084c92,be5e5c3a,ee4aa6e2) Z8(4b611117,7e1d9b3d,32f71430,25bc6bce,2393e8fe,002712a0,2aa40e92,945a21f0) Z8(cb630373,523772df,11736138,a787e495,23ecb6b9,ac043bec,1f2271d3,1edf1f3d) Z8(aeea9d29,68d4bb7f,8422da7c,43fbcbe0,e0a4e899,f619a8c7,fe226c86,b5a79402) Z8(9c10cd25,934e6a41,32343fbd,d045f200,ee64bebd,d7c5c12f,1d92696c,f1e08b1c) Z8(bb5d5de5,ab349bf0,a981dd9e,b0a71162,e70e4b44,4fc25e00,c44aee66,ac2167fa) Z8(a2782a18,65ccf04b,cc496f57,e7cbaf79,60590c07,bf2a9ed6,00a2d3c2,3bbbb56e) Z8(5a0931fa,1e84a88b,bf2fff8d,701fc319,72d9426c,7938c11f,3c4ae4c8,c84a5619) Z8(d39a5056,091885e3,935ee0b3,81274c2e,305ee653,acfde487,aaaeb9e8,41b1b0e3) Z8(df2eb4bc,f561157c,bef75039,c749b113,9b48b9f1,1b23e5bc,8a9432db,c4908409) Z8(179a1615,951f23f8,e072d33a,92994444,27c90056,5ab92363,0cd49ba5,0a457c22) Z8(239a43d0,bd6ac569,76e5ec3c,69f53efc,a7ebb12e,0caf2808,c0833015,e7a6cf90) Z8(2e7623fa,fe89590f,b553a459,50993e96,761acc15,5f6fe436,817c1b8a,f9aad29d) Z8(b8be4cc8,9468017e,67ffc46a,de2b462e,19a9e4ad,3a2371fa,7f3e659f,c0779364) Z8(5d60ee69,3ce83591,aaca1311,5f34dbc3,019fbcea,76e52e5a,aaaab777,003ffffe) },{ Z8(9bedac36,43075603,4bb8bf7f,1ea43d28,154f9e79,c51923d0,a5a00164,8d686a29) Z8(649d74e8,5d5cc7d9,6e986087,90389910,daa6a9a2,37da4ec8,d6351b74,ab869941) Z8(96516bdf,a8a2b71d,09f324e6,0dfc688d,7dc2b99f,8176b932,d5d53190,5ca44af3) Z8(06931603,e65496e9,8d269b5f,de7baf5b,b8c330ac,87a6ffa7,628d559e,916374b4) Z8(9a3ac382,f44dfeb1,febf70cf,401fdd32,66dc98a5,85757b7e,45a915a1,a4eb4b42) Z8(3fd4fc68,ef18a159,f975996d,158185b5,b8bc74e3,645e9bac,944515c3,76a76402) Z8(87dc6843,39cab1ee,297d2d77,4694b2d9,9aa8b29b,0bb2f763,405b73d6,642a741c) Z8(f2ee1d87,8a6d93e4,1b2e9ae3,06409eef,e63dbbee,a1b6db59,ae8fc52d,99203cc2) Z8(56a8437a,4604d946,5f8340bb,3f01e677,da2cc547,fbeb7bc7,5e54d5c5,64227064) Z8(f709e2f7,c79d77a5,d5cacaea,4df0d3c7,13e9f587,84b7dc60,81258b44,dd551780) Z8(e57682ea,5ac9e292,3e1d5210,25193aea,2bf9cc03,0a4a1daf,a7e38aac,a6890ea3) Z8(af9d01f3,944cb339,cc4a248d,2e2bf769,fbff8a90,2fa2e20a,9e2a2a72,3bfee575) Z8(ec6dbbc5,31f1fecf,813ced72,65709531,72d05b30,d4d4506f,cdd85c10,0d03883b) Z8(0562becc,a57ffeb5,897d5508,ed6fc4c6,ecd9f279,f73020e7,97dd9372,1338279e) Z8(07b0cbb1,4712c611,84c13ae1,67a9377c,fd9b98ec,a19e148d,f0406b86,5b9a202b) Z8(39aaef44,4d58fbf1,c4aa0ac1,4ee6d3d1,0fe0de91,230b2353,c47d28b1,7c68126f) Z8(a99a8d6d,ea07c22b,7ea6d959,e21904e9,35b13873,3c7b60c1,3dd3db79,891139d5) Z8(2d83ee26,ec67783a,ee23880b,e8f2409f,ab02251c,a5ca6ade,5556eeee,007ffff5) },{ Z8(4ba337dd,2c84cf1e,10eb2839,c33dd7c4,ebc43e3b,53e53828,cde9d09c,190654af) Z8(978ceca8,3ee0f584,c4e567ff,96dbf230,e5096eff,c19cb26d,b0f8d900,ceb877c8) Z8(2deb188a,359d6340,40d651e9,87f79203,4993d399,e170b48f,28ae712f,eae4743c) Z8(82f4e87c,e180b305,bfb449d4,d0b80a68,19a9b1ad,d6a333a3,ffe6f933,a601497e) Z8(51044de6,d028e9e5,12329400,da647a36,e34520a3,789c9d86,4ded2f71,333c1b25) Z8(40fd461b,9d57015c,8cc55d88,d9b25dcd,a4517127,2d0a24bb,df317366,58e42916) Z8(e8059189,9abf7e95,7a548854,34e8c574,437ddff2,d15b1dcd,90cd22fd,5613bb20) Z8(c495962a,23e7136d,90a61ccd,4397b6ac,039dd1d8,a79ca9da,86407e47,05dd44e4) Z8(9c0b0539,34c6d856,392f05cb,c61a881e,1d77ea22,90bd6222,bc065656,61f3b1a5) Z8(9c80c546,422affb2,e9bf8115,7105555b,347bd856,e28870bf,d775a863,b6d27de7) Z8(6b8078c4,9425acd4,9713191a,f59cc5c9,7eef1c39,b96712d5,9d3d3138,6600aeab) Z8(9013cdf3,da8ba674,1f3926f0,04096d05,a51a892f,2ca79b29,31161fb1,df6fc111) Z8(57d002c8,443264c8,d39ff304,9adb5c8c,16ec2085,6ca3ba0b,1f4cac86,f0536d3f) Z8(6bed9b5c,609c7a5a,ae25519f,aec4da62,627a7277,feb6de1c,fc1dae44,a80bfef4) Z8(0c09028d,57b3dba4,3aafff35,317c6588,469f17bf,f92cb860,21b7659b,d7b76314) Z8(029d5f04,df5b5676,39d6a99f,a80ca45e,4d42e4ae,00794eaa,d4aec58e,3e86e62b) Z8(00cc16e9,13ea12ff,30aeee8c,0e650304,02c3837b,90537f6e,dc05eaab,11f9f434) Z8(13a47a91,1cbb4c1a,a60ce5c4,8de69489,b3ea592d,84b1adb7,000c2661,00bfffdc) },{ Z8(597cfe73,379da73b,7161b809,3a1ff32e,e0ad98c5,81edea8d,261fbdd3,0babf3b7) Z8(18bda01a,4a06c9b0,821cb75c,1c5fe7c0,cee30ac5,e4608bee,304a7202,6a9c2057) Z8(8c18e53b,1a526cd1,6bc9dd0c,9a576c17,e106a689,7f4b6e46,203d8270,55926b22) Z8(3184a312,b7e286f2,de6f380d,e8e62ba0,86a3a22b,5711d770,12f1e361,01320723) Z8(9e96bccc,e83db15e,1d8edd1c,3b58402a,ad2a9828,a333325b,40d9261c,a27169a3) Z8(3b4b20e2,d9c2829f,1c5d63fb,c86869cf,2b028aaf,7bfb9efa,3da1e364,0856adf9) Z8(0743fcea,2a294770,94fde202,4bdd8012,615c2eed,6cf3ce5c,47596024,ca0119af) Z8(0a327790,211106ce,5018c972,263b2d2e,d9e5b140,35372f36,fba6dba9,0a3c54e6) Z8(5a9ef78e,eb194e74,fae531d6,bb6d6e0b,1af8cc3e,07e2cf6d,9487ea80,65a53ff2) Z8(21fc3fc3,0f0dd7c1,81583f10,b0f0cd49,cc9d442d,ac5a5c34,632bdc8b,4c18f2e8) Z8(6d32d099,b8775468,f04bccfe,21089cba,5f926a97,88d187b9,cd63c70d,8422b529) Z8(7b30cc41,223ce80e,9e17a8ba,04efb441,5712e797,be91d30c,2bd45592,bbe7680b) Z8(85473f30,f5ee39d0,2113fa09,4d949394,cc27dff4,68231593,e1eea31c,1dbc2268) Z8(54558210,39fb69f4,7ae4394e,410db23b,5770748e,0d8d2ec4,7e81c1b2,4ea62293) Z8(3af5c0b4,9a115f45,ec11d7b4,2d6732a5,5ed283bc,d6e151bb,39ce0b47,f92cf817) Z8(cd97455b,5b5bc45c,81eea5ec,0c132116,1e51bd83,4346f7fe,d429a60f,1191d908) Z8(800f56c0,471a535c,67be3ae1,d89ebbe4,6126f5a9,d62450d6,f625cdfb,6d688680) Z8(2682bef6,892248ad,eb9bc957,167c18ba,6b6d4f7e,4bb12afb,aaddddb9,00ffffaa) },{ Z8(fbb161b1,b0d88060,50cb27fc,5ae76d53,34d9cdb9,e1ae7dc7,dd7263f0,b43684d6) Z8(a0cc7fd2,319fd4a6,ca8511e6,deb9dad5,71f93e35,bc65973b,cc988c26,13794bd9) Z8(f4bef158,06b5bf8a,4be5aeff,ffc2a83b,1c1bc001,1ddd065c,59700d73,afbe1c8a) Z8(b6d8a5e8,483fff54,1f1ae1fc,84d4de8f,59c38a2c,d0c4ae5f,005ad885,5ceed779) Z8(70e5491b,64baeff9,df2076dd,f8e27954,8479a34e,bfca5a94,9a8a53bf,f591c7f7) Z8(59be928c,f446cd15,a10df36c,1634c942,004243c6,c937b8ec,9b50888a,58ba94a9) Z8(32360941,78a576b2,28cc9148,fd3cc2fa,5dbc8c69,ec3aefab,30c720be,36cd5192) Z8(ded1dde7,1a083b32,1efc5044,c2ac7d7f,11409098,e5a2be84,e648f509,82169dae) Z8(711193dd,d2fc15fd,cb664dc6,145be7b5,7e0b5455,400ff96f,8ac04539,d0ead211) Z8(e1bf3403,2dcebb29,6100902c,e88dd068,59e1eec5,28c7f787,4e134ca9,1ea743e5) Z8(d4fc04d5,b1a61bb4,30eec069,de9b1f33,977721dd,619b6b8d,6aed6049,6c3074dd) Z8(988b5b2d,0f495cd9,c883dda1,0baaafb2,03e88aab,d0f5c4e7,d29b5a7e,7be81e16) Z8(1f9fbac7,cbe3a562,cd046c9c,3abbdac1,4327855d,65928de4,73739a86,e45a53cd) Z8(63f0e93d,c69a9bed,a977cc16,77a131dc,076676ff,3dd80a59,ea9d8fbe,26528b0b) Z8(dc29c5ae,f99599a4,bb355c76,2682e045,4745e126,5c9f1839,a0e75bbb,284e400d) Z8(59ee623b,4d501f3a,819aecc9,fb53b338,b1fe043d,157e0c67,6d2bb5b0,586f9859) Z8(ec6453f4,80cf258f,904dc9eb,706af9d2,a67e846f,2eb0dad9,6dd89d52,0b0bfd53) Z8(37af3ca8,05728e6c,73bb5b5d,23a27b81,70ba3778,f34dd408,55f194a6,013fff59) },{ Z8(fd10d3e8,38481fc6,511cf624,873c413f,d182aaac,95c8ef13,88afab4f,94671d5b) Z8(f0f2fdc9,c8f2705d,a4bd4f9a,7baa8f29,ea8edd6c,a45879f5,94e28846,5686c6cf) Z8(7587b9ad,557255c9,8c8486c4,95938901,49ba4a9c,61622fc5,836ef927,f28b7918) Z8(2472be05,a653a100,6063b2db,a2ca6bd3,d49d21cd,6cf700b0,dca9400f,31be1c3b) Z8(3e9516b1,32eb3e21,bb096877,a17db57a,475f4a56,92b2d8e0,9573179d,740dea57) Z8(83e7b98e,d5f9ffec,83f1e256,c6399eea,31ede81b,3a7fed5f,068c1e15,caddaced) Z8(9ce3b566,02dabfab,c6a21c8b,d2a18f66,2f04ab39,184c6f50,b1c5cc66,6fbfc0f9) Z8(5e693776,df42bd4f,399bf17a,41d745c0,f605656d,a61de96a,f7db0137,7e4b597a) Z8(48e36a01,0a35d984,47e7e4cd,647b9219,6a51e59a,484a71f2,3f6a4f3f,eb58c969) Z8(f8d1d9ee,3e2fab62,c66a2ed2,231878cf,9adcbf3e,9f205f84,f6bddf45,0ff184af) Z8(d37aa099,9c5e6b26,992735ba,280cb451,d2c50437,49775b41,6d6f710e,6c157c6c) Z8(97f35aed,9ea98724,6e07ae2c,005cedd5,ee3f607e,70cd801a,67731644,b3db2bb8) Z8(65619d3f,33dc763a,371c01ea,db4f972d,9431546b,01992e40,8a754610,7bda23d6) Z8(5c2259ba,93b27323,050bfbb4,84a37025,27158537,7f81d867,4c58b5c7,5c6d38dc) Z8(df9180a4,2a756324,c5bb8cf1,2ede8624,9d72ea85,79f21f43,d7850047,65326389) Z8(9079f6a5,febc831f,19898b99,f4aa7989,9d954b47,0b60183f,08ef2aa6,4390605f) Z8(4d558e16,6d4934de,67e6cc80,6b11e270,6880033c,39898cad,14990381,390de9a0) Z8(aa95847f,fffe925f,e10f8420,e6ed4f55,6554277a,f5a48e14,0184ca5b,017ffee0) },{ Z8(1c06e14d,0977dbbb,5c024c1a,dcb8a471,71ac83bc,df11a1b3,c84ad3e9,21db78fa) Z8(e8a1dae5,4e4f20d5,fb306a58,3161c870,a76f0f81,92482eaf,88e5ef4f,8006f2d7) Z8(67d46863,648cc92c,98ae9aa9,f60522fd,894e1a07,829ba5a8,c7848407,4708c4f2) Z8(6a69313d,20d10594,1c871b79,90fd2fe6,e5c634c6,826e1948,ae865e68,d7df32ef) Z8(cabf91ca,e234e718,aaec26be,5fddfa55,66c7a700,6f06f33b,0a48a724,2603e8e4) Z8(f1f8ba3a,714336a3,dac43033,c0dd4395,baad45ce,178834e0,343906fa,7360d769) Z8(42fec8bd,7b9e99ca,f2a89908,869a188f,19bee08f,ae829c30,f5e7b0ad,01bf5f6b) Z8(979a4d6b,cd912274,f4e69450,8025fae4,d1523590,61479f14,cdffaa58,ed3e0ade) Z8(cee07b99,b6b8607a,0e2a37f5,c9003513,5c5b1bd4,10482c5f,ebb2bb23,7d6a2d60) Z8(48ddddd3,3a1a6288,45043226,11304a61,2d64dcd1,f8d58b11,57be5cb0,fa7df975) Z8(718f4a48,b7329679,5b1c1103,a48fd81b,92335be3,4af2581b,0a5d4d02,16eeb9d2) Z8(32fddd81,6c8efba2,1b0fb995,bdd91267,982a8c43,07eaeee3,4cdccd26,68b7650d) Z8(d0d5d532,60042540,f34f418e,c2f40057,f8ceded1,5352e866,d9d42742,7790bdb6) Z8(bb5906b7,3ed2985c,2071a482,116f714e,7f8dde9a,2c218425,d022ab2b,3aec6f58) Z8(72b65661,e4e1f096,a9bf513c,bd8d1fae,749658a6,428fabba,c0d98374,978179c6) Z8(76ef6186,cfe88f7f,22b3146f,a1e12f19,b0b8b8e5,0b76fa9c,d284fe11,75568631) Z8(e9d37d9f,6a336edf,3f571815,585f8329,42708cf3,047a654a,2520be19,cc79624c) Z8(88bebd94,5d86ebe1,42b0a214,9707a91b,51014a14,115ebef0,adf2fd16,01bffe36) },{ Z8(4d85dc0a,a6dc1eea,1f3a67a0,10b2f1fb,2583a620,48620e76,9c22105f,1bb7fc18) Z8(a01357f2,697dde67,7f734338,1cb72a74,9d1a818a,fbd7bfa3,1a724a11,ef1ad0c6) Z8(89041575,a477f825,8454266a,04c7ef02,3542a1ba,0cb3481c,5e8c9101,49b4b9bf) Z8(1a21494b,650fc756,f00b65a8,f97d0d48,2533ca6c,aedc2fdc,308d5da4,03bc13c5) Z8(022506a1,d95d6cae,88d53058,4e2b023f,e404b581,afe67619,5e22efa6,9977d687) Z8(835d954e,0177b581,d54193d5,baa332bc,51e4dc40,266ae108,b9431a4b,2db28206) Z8(e15bb3c1,c13177f9,14d56e6b,89a11d66,4a29bf3e,75059b2a,c581c13b,2f4a818b) Z8(0e915d5e,439c7cc6,573fab37,5d9849b8,a33d71dd,a597fec9,c3b2a35f,40937fad) Z8(f61e4af8,ac419889,19c07b15,fa721865,fa7036f9,52e18aac,658d41fa,df3c97d5) Z8(313808c1,d2cf1b46,f99d3a01,cc5c3ca8,b252df70,7204b3ba,c051e0cd,392b3098) Z8(9738f427,0f5a9a1e,48675880,03771975,fbb04ad3,909aa1d4,91a98c39,cdf3ce38) Z8(7dc9d9e6,f04c738e,c3864cbe,ecc9fd7c,9264ed7f,b16e183a,e52e7233,bd2cf82d) Z8(b820558c,404c0c0e,9a3bc518,8669deec,21fb1229,627ee732,a0eb8973,734d0bc8) Z8(6cf49dc6,6861e60a,a673c2ff,f02e59af,86eca529,df4e09f2,2cb9e9ef,a3a35b72) Z8(008e3b18,74ccbb9e,3d292a84,d1b302d1,f0be452b,b3d2479c,0ad25a2c,e42f251a) Z8(200683fb,db904cc4,058e5fb7,ef3494c9,6a4c8504,913b2c3d,76d996be,0141ac6c) Z8(d79ae2a7,570f29f8,9717e1e5,cc7790ed,ac4a4e52,6f9cb7c5,28bc8f59,2111d081) Z8(cfdd9ca1,3507a2ae,2e345e00,8ed0ad40,f77cc15e,d00c46a3,5bbba972,01fffd55) },{ Z8(e82cb716,42843d62,cb116f3a,6e868e30,a785c566,8d0d996e,9548fa94,aea1a658) Z8(e5d38270,c02b0f19,a0919373,814e9ce1,3edf6835,6a8a141e,a51f9816,a2dfebc4) Z8(f82b2043,d5733d5f,1c052ede,2345e5b7,c5c5beda,b2eda711,22cbf7b0,bd36b2d7) Z8(1c7b8031,1c37ce3d,0c8fdc6f,2076bd56,d9dc5fce,e557a48d,e648b5e0,64a75040) Z8(2ca70aba,cfa67b49,61787355,34fceb0b,6b16253b,ee890f44,d2c379a6,f919b4ad) Z8(5fdc1ce1,be16dbf7,de7fd3cc,250c3382,5770ef52,c027286e,39681789,f1b49943) Z8(e37a1725,21742fcf,9445e986,a1bc191c,0a34c5d6,8c9a6b27,5489d0c9,e2f24d9f) Z8(590a4856,73b3f649,cd5321e2,1dfebce6,6c63392b,3d320045,acc787d8,7f40f969) Z8(99a3f92a,dccc1497,e38691dd,192b6cdb,81b61cd4,c614d3d4,b9ed7ce6,23f8e67e) Z8(d8013d19,b2a54100,21ea8498,8e200de8,9745e6f2,557e29f8,a98a63e3,55330167) Z8(6d0edeca,761c3e96,9346cbb2,e13e5cd3,8c3c84f9,6dba3620,c7aff681,db932ed6) Z8(02554026,d9e6def3,90f2892d,51611976,00c4ff9a,c3b34701,e2a05a68,0155987b) Z8(14d30207,5a1146b7,9817dc4e,933e3673,b1661c73,7bf17dc6,9c8845bf,d368ac00) Z8(1955ad29,953388af,3fd9cecd,ef64b84c,aa2da777,504719d9,fa54317a,e6313ed4) Z8(eea053e1,7639974c,9bd9a0d9,70d3ce3b,3daace08,69b79d52,9cf9a9dc,7f14ae11) Z8(ae2ec4d3,17cdbceb,b1d50b4b,ddd422ce,85002815,6c05271e,a30f3002,9e92dd1f) Z8(e26472a2,97c6b76e,7fd8b3e2,e5aa24a1,00e53690,1d5f9418,8da3e630,9b48bd4b) Z8(942c718a,374a5235,b0f73f19,fa0e96ca,e7445f8c,9241c90a,0b88497f,023ffc34) },{ Z8(799429f7,51f95d7e,c76741c5,6a76c1f2,6dacd0a9,27ef6a5e,730b5d47,17cc4220) Z8(188d607c,c013b0cd,e0379807,20943db6,a59c72ad,596ee848,aee8dacc,bbd30b78) Z8(1dc2891a,548ed7ea,a2eab166,20d98903,1084122b,816c79d1,5ec42564,77ebb378) Z8(a78ec0f8,2e286f8e,54720db0,61f76c2f,9f6da730,065334db,6a937cbd,f5f40d3a) Z8(426add38,a0f0562d,1dc5bb8e,0f3c87b9,60ecf72f,8a5e8ead,6cb78dd9,be8297b4) Z8(85fceca2,9bde0940,e3b265db,56e431a0,0ce4a87f,26dd3b3d,8e35d7a6,cdf17b50) Z8(da3aa6df,950c5f6e,94dbc54d,724b1dc9,12240029,5ce1637e,fcda3e75,067dfb35) Z8(97cfba6d,0529bc77,0a29fc37,d555b44f,89537731,d83dc9a6,e86c953c,8ecb78d3) Z8(d80dbd44,fa82451a,b571b3e7,a87c2713,18c83f8c,3dd63795,40e8949e,620c403c) Z8(1fee70e2,08ac5c99,b12fd821,965d85aa,6d539f15,af30e1ec,202974be,2362e8cf) Z8(7d7a7ad1,a9aef317,ac113798,62185019,d2c1a221,3051c707,88b5d996,579a366e) Z8(1a3465db,0584cd3c,cfc3c69d,548bcd44,922abdcf,6836e4ad,dca94254,3b3c454d) Z8(b448b8d2,92c4ccef,ffd1cde5,81423eb3,601c19b4,25aa030e,8d7917b5,00014b8c) Z8(fac868c7,2de4edab,a8fe5614,f17bcd3b,e2dc4e55,967f6649,9b2814d4,92700f98) Z8(a807ba06,215b0f8c,b51b13f1,babcd156,9797ed3a,7d4aa545,ff9ab225,8b8ded4d) Z8(56d54bc1,de62fde5,5022dc95,8c978b8d,ddfbeec5,13f6d091,f0b42ae3,2b43fa17) Z8(8d6c31bc,cff9ed71,1878e684,e3658292,cd72853c,21eff0ee,ab8b29dd,f100c5ba) Z8(4d6b813b,f9ee8e47,bb897f82,a8308d4c,c7316148,e4c649bf,be32537a,027ffaca) },{ Z8(51c56eab,f95e4c2a,ddfc0614,3e2603e7,b4ee83ea,95dcc62d,92bf8b9d,1ba44761) Z8(0d687ce3,12dfd462,0f77a6e5,c7dafa04,5ef3fd04,4342605c,0830cfd4,21d2df16) Z8(c7d13425,7878d398,78ad1a9b,0830b105,7f4b94e7,109ef33f,cc22261c,8d96bdf5) Z8(ffbc376a,1aa7b283,7199f73f,174d4bc8,dbbf9b24,f0d316ab,82b21681,749b28c4) Z8(0f2adbd2,a99c29fc,fe9b96d9,a96e9dfd,1d4fa34c,bcbb3a60,ab57f649,21d1d78e) Z8(0742e599,34a1980b,e5de04b2,122eeb87,fbf51593,0322225b,45a33e82,9494d0fa) Z8(56da10cc,574a8f75,90325d1a,7e532a5b,c30898b9,d37a92c4,d0bd7484,98cf8c91) Z8(52b96d8a,e342f5d7,ce464ed8,36be66d7,944e5c74,c142bd17,079d1d9e,d3d942b3) Z8(1e7141f2,1c6ee0fd,f023ff96,973b0ac4,4c929898,24f9067d,49a8a6d3,c062382f) Z8(15ceace3,7cd55282,6535a9bb,86f67bfb,0e469d5b,6333395e,987be969,c316ba6a) Z8(4cbb2aed,4940ec1a,4353bdff,5294acfa,0ebaa3b3,76b7a732,ab90d608,eaffbdfe) Z8(8dc9fdb3,330ed6f3,2ade712c,016f8511,c9cc1d59,a058037c,6b92dafe,2f05b03b) Z8(f5f7ad29,4ec97288,839a4bc4,1810ae8e,d9bc04fe,9cdcb5a0,ac6b66f0,838231a2) Z8(f2bdba63,fa4fb1fe,b5393020,0f8a9173,448fdd87,f8cf4638,a5597fc6,6f3b2244) Z8(1d0c1a39,1d9d2d2f,61fcfb87,6f69d3b3,069e3af0,18a16c99,efea7754,8f86cc37) Z8(a2b8c630,42f5164f,d873908d,805511ea,de014b32,89ca6a72,a50cfcc0,bd5f96a0) Z8(0b56de89,f1e88be4,d1146cc2,1a924279,adf1cbb4,bef5e800,dc33eb63,387f996e) Z8(bdcfc2aa,742f884a,1560136c,d57628e7,889f0cac,e32e892c,74c9383b,02bff911) },{ Z8(201bd14a,eff8890c,adbbb07c,a28e45fb,5a1a2fa6,2c1333a7,79ea6175,90df79c1) Z8(801f8a6e,2529752a,657d750b,a56b0f98,83ac6435,5f19096b,c21a870f,4806e371) Z8(c8e97191,ddc2c188,aa4b5ce2,fa0221b8,85817bf6,27f64448,ac894c45,58f7d61a) Z8(d2a8936e,aa2833fc,5a78c1bc,67e94e2f,2613404d,7fa00c04,be9207c7,f0d53868) Z8(1132ef71,40cb5cbe,b19f9a18,715bacae,9a2582ad,c6e8b7ed,cbc9a536,02d5fa80) Z8(ab581b6c,3c885861,658d679d,1a845f1a,eb1e329b,ed95bc68,f3426207,b4116a67) Z8(f9a9a417,3ae22d7e,c93091ff,459112cf,f41fa810,4d232459,8da126ce,752be3d0) Z8(73d46c12,8731f12d,8bb19001,e48e1730,4ee967e4,747363e2,244e08be,67321426) Z8(2dd5bdb2,ef5b06f6,10b72e21,2b010046,a0f90f42,6f471d9f,aed3d46d,21570189) Z8(31c42796,ef251929,9b653c08,fcb3d0a5,45f37ee8,06d7974d,67cd0fbb,2ae7bf89) Z8(7370ceca,3d607348,a9e82b35,450fe13e,07913242,f18310b8,38e91c22,55abfa2f) Z8(4dec2bca,a2ee6e07,12749eaf,da331ae5,0d994e9d,e886336f,23a45bb6,1f923a52) Z8(9771ab9a,e022cf09,62f855d7,263bb438,e39493ac,6bd77c8e,8f134c18,6abd2ca6) Z8(bc3be294,747954a4,74a09b8b,af71a2e5,b48dce8d,7ccd7678,468db96f,1fdc0c22) Z8(b8e8522e,5d2ba527,a82fdfd3,67a84b26,eb872af1,fc322c69,20b02d00,d831dfc6) Z8(79a6b951,37a3cc03,1b0ec73b,6e3997bc,536a51be,495f74c1,19eedcf7,2fc62b7a) Z8(61e8f518,1b37431d,e4186302,46af6bbf,91294bed,9e608b5c,ebea3e47,dc4ab848) Z8(ac4d1fad,14db0e87,1beddd8e,6f3b42e4,ee5a5b71,6d7f457b,30986134,02fff700) },{ Z8(b1a84a9d,ccfb28d4,f587a2ae,56863549,b2e28627,d1294e42,4ca3dad6,d3b80ef9) Z8(8e722d84,0a6e7dca,25b6ec28,9573eafe,c662dfb5,5df27175,c47336c2,85132fab) Z8(49375382,1698e762,9581c05f,9c37f0c3,7e63ec08,37ed0f91,efa38d72,b88ed975) Z8(327abfad,bc05d149,9c7a407b,f5c140ff,c210ac0b,b8f655c5,f944a7ea,13daf2c7) Z8(965cf2a2,0d785122,f3358d75,89ba3be1,01e47d16,830fb084,95a11b35,3b6245e1) Z8(d64e065b,7c9a40f5,01f91118,318415d5,49eb8c56,04689742,2bfb1dec,a4b94a95) Z8(f6925c86,05f164cc,094b378b,55c56cd5,c80064c0,d7f53eeb,b0498516,fd60e440) Z8(372b223c,7efe8fa8,9b774a0a,9cdec2c9,96d1b365,ea2399a0,ee2dd54b,fdae04b4) Z8(44f148f9,b0c504be,eaa601bd,65c00a4f,15834805,57507203,9e74318d,d70335c9) Z8(0dadd1bc,f26a73d4,56ef7ec2,364d8ff0,11a52643,bd8a44d2,b1f1cbf3,8961f3e7) Z8(39d4423c,d08f7ddb,320ca849,2136cefc,3b03f85d,4144115e,d8e22229,274a1652) Z8(ececb9de,4ba56dec,f05f6dab,3496c70c,41bb5c07,4ed24b23,fdb7e845,94bd37f9) Z8(f6323669,a76dfb8c,c1882866,aa17f72b,0f83234b,9d7ad04f,591d2ce0,9f314178) Z8(43e3f901,2a3cbc36,c99f803c,1975d500,3f20a178,d51c455a,175a6e91,a346cbcc) Z8(02355bd8,0e441e1d,5b0da1ee,a613e878,a983dd01,59213c20,0063eb8e,3cb52136) Z8(3c45f04c,88d7d182,0b7c9674,b42bd4b4,5bc76805,091a648a,0ec0b20f,16755843) Z8(b5982ce4,6557672f,898331f7,4d9a9ec6,f429f000,e6d06d0d,78f17b4c,da242f67) Z8(be45603b,d2d478ee,9448ef1c,a09cf833,e5f06c5c,f7d17680,f32d2e02,033ff48e) },{ Z8(72a1d06f,797da9be,41211a0c,6cda1e5a,b3488a4a,cf4bb633,52cbb27f,ce67eabe) Z8(5613cf73,a617da4b,534181b4,929826ec,e11206aa,a9fb70c1,8fb3e5cd,ef38f539) Z8(5501343b,9b74e80c,4d84c161,6af4ce60,6f22f31c,b276ee91,6ef259bd,74d5ab80) Z8(b8ccfb0b,dc5e2330,9130a75a,584201dd,8b7b2ccc,304a1ff2,957ab04e,d86a75ee) Z8(eea45471,a8116355,674e1f36,6e22e8c5,0bf26a54,7246f080,a3b7dda5,9cc6d1e7) Z8(ecd6baf5,60f64b6d,15b40ffa,670b30d2,bb982e29,579822d6,c3f5a7d5,08de2e88) Z8(1dcdc82e,0e3227aa,08518b25,79b1f072,a2f7fc8a,c0ade699,d7b7c898,ad68d7ab) Z8(61d5bb1e,76f5881e,0a7e8923,8cb8e29a,bc8d76a8,582684c5,9f1f3729,9eb70fc8) Z8(11620594,f7827fe1,f02af1ea,eaeb069e,fc553b52,a229b832,3e49299a,01ca6187) Z8(47289e9b,6dc9cb85,0620eccd,68907b96,cbeb27d2,c3261a7e,c1b38216,5ae1cf73) Z8(ab3853ff,3acb9395,1036aa98,9ed946f1,8b6c0f6b,d5cc0ae3,b0e65e0e,1a97ef53) Z8(2ec1ef6f,8fb85d32,3f117484,98ae0940,1384ecb2,4132032a,5898b3f4,8e535073) Z8(c034935c,307f65c0,56c5f16b,54f27620,f9759dbd,fbf88415,77a00884,4ead9382) Z8(4321c3ac,95e1e225,beb1dabd,54545666,cd43d528,8dce1061,0f1e38f7,36606aea) Z8(915e7ee4,0724064a,bc99091d,d5e732a5,259f3573,5709a267,c0ca2734,91bed9e4) Z8(d80f3ef1,3ca4b79a,a1f29c20,dfcf51e9,32a042f3,3dac8ac0,e44f6154,8e2e008f) Z8(36d072ef,8604f609,12af1ec7,32c7662d,dac8d266,fcd56e68,e8d5015d,49b47cce) Z8(a4ea260e,691b2df3,a5fca0c2,cdd99404,a280ac9d,bc7cc8ac,be5cf188,037ff1b5) },{ Z8(32e2315d,6c33f3da,e3188649,ba5439a2,7d659795,bae33a8f,7314f9cd,9be01595) Z8(d7ef8be2,91ad2a0a,0963d4e8,aa2a1ba9,e18ca1b1,03358791,6d7bb0c2,22dfdc44) Z8(5d1e4f33,26c70b3f,7cfb803f,3f761880,f1de9e86,e41ead01,17803001,6ea09e07) Z8(eda0fb11,e4692b50,be0faeb3,802c0e1d,c2de2a90,e230b605,44b6c7c5,1038ce86) Z8(d1f6f2d8,54949a0c,39b8ab7d,a35e5284,0fab8329,edcff4f3,d2138fd3,646e837e) Z8(06e77206,6e7d569a,9e3354ea,8e3022ad,47cf37c8,bc71fbb1,b099aec4,fd4dce4a) Z8(2afb2659,998a4306,7eef7df4,ac1413f6,bb02d433,a0ef3503,e752e295,66a623dd) Z8(15facec7,e73dd08a,8ce85435,39add92f,d629d81e,777aa2b8,96090ace,2770166b) Z8(057abeac,00d0fea0,22af57eb,b37999af,8d8a07cd,e9ba0bf6,ca92a40c,59bec8bc) Z8(db00cbb5,076f75f1,59703a5b,94873c3c,6a6ab48a,7f73570a,90a8be21,1462e580) Z8(67373d91,6d34100a,63b18a05,71e50054,e6ec016b,9d1eef3d,b5e31cac,1940278c) Z8(f6243c2b,6d45d47b,928b82e4,56ca6706,faf48387,3cf95d7c,ef30ee13,66a3a06e) Z8(2548daf6,59440124,60b05375,e6f2c48d,bbe85479,364a2e36,66ed7bf7,bea95d3f) Z8(dacb608a,47857dab,de8c417b,06ddb0d3,86b21a2f,714ad65e,38a99183,5c1792b8) Z8(07751005,c0b8c271,ee1e8c34,d31a7425,8da2bfb1,7b751cc7,30835929,28bac49b) Z8(74b0bf1a,de9d6a11,15ae46f0,bd500d07,a0ba3311,2be2f296,8ba3630c,942e29e0) Z8(54c7413e,82ec6f86,0cd301de,3416968e,35656ac3,6253a758,c36a9506,d5ea2575) Z8(a06c7118,714811d7,faefb2be,6b813772,28379e10,1afcf83b,944aee79,03bfee6c) },{ Z8(c5d23ccf,fa1f45e6,dd495329,97325086,54471806,e38b8215,3d73b6b5,2a9ac341) Z8(3970522c,59179e46,5c753163,9abb4a76,60bd6c93,88c74150,2d45ac1d,fcfe35fc) Z8(7a387ac0,eb478320,65f471c1,a3b0d91a,75e5f8d7,096187d4,a7fe71eb,75a7271b) Z8(919af827,32dfff81,dd5324e2,869b37ce,3238d0b5,6ed8e518,304e2b35,6f4ffcec) Z8(d01a6bb8,2dd472ca,4b46b010,80b8f7b0,e82dbd28,7c6cc4e8,6544b249,a5d1156b) Z8(0c9b5827,77daa870,cfd9ec54,57e18e4a,b744b58d,f3af61c2,66935699,5a37a5e8) Z8(ec45182a,92046bb9,958fe975,bc32c463,724b41da,9e6a5931,6744b551,1d3473be) Z8(d028171c,c0ab3320,c4f59600,a696784b,21b31a1d,8ceac018,2dedd785,e8442116) Z8(b644db65,ba518587,7a9eaf28,c6e86b31,0cb71720,24ada163,56092d1f,a04c4631) Z8(ae851e0b,8c60d5a5,b0a89396,f7971333,69757db2,61e7a559,cdaea213,03fbead1) Z8(8593e21a,20d55ec5,053cfe2e,dca0bed7,de7b9074,53f5499d,235556fe,327dfdad) Z8(55f77979,a135ea12,02884e9a,002ef887,7caed13e,fe95301c,9018bc85,5dd8d34a) Z8(a63cfa35,0eacb307,16165f2a,b4a664d8,f810cee4,ddbfe9d9,ef005830,d8f16fbc) Z8(1b39d84f,ac4b5c16,12b36b15,6bb299fe,7e09d162,2bf68274,55020e16,76b2b560) Z8(5c915954,5f541040,9ac2c06e,10b26dca,73ae8ebd,91eaae16,0160f86d,23a6e613) Z8(0e32643a,2ca72839,aeca2042,14146677,76e749a9,729da52d,33f7b6b8,88b319a9) Z8(4df9c218,85a1b8fb,797ad494,bcabe016,286e9ba4,68d09936,858d1e57,a36a1de9) Z8(c9d5872e,81a57e00,0437bbd1,2083bd97,0057dd81,ef9e3159,776e5356,03ffeaab) },{ Z8(3adeca2f,b99ff895,bff9ff1f,d0d2b2d6,016bd791,315780b4,15fe8765,4566bb0b) Z8(cee8d832,ec979256,04c61e36,ba8b234d,abf760b3,96a68005,65dc9c12,99b8c5d2) Z8(53e1d154,0b1409cd,325878b7,6772b60f,90ed8dbc,ad4ef485,31d9bc91,69d09a27) Z8(32f0b03d,aeb4c77d,e96f75e3,8674c92a,57c7788a,0d545e40,5c66d269,49161ca5) Z8(a860f739,765a24d4,e78ae172,8c6ca493,b6fedefb,f51d8969,8fc4533e,5bc0786b) Z8(0e52eb26,487e21dd,f6bdf85c,d065ad13,f78e17e1,3eb16cb7,0465b3a1,d4b6e295) Z8(983d4f77,b304fcb2,7facc9ce,affc0579,1142a96b,973cd5f5,c2fead06,12f55b13) Z8(4981b8e0,e1fc065b,54fbe82a,74f06731,45455ad7,57e9ed15,3674b65d,44a63633) Z8(ccad9899,e7b66125,21bc4e28,1bdaf1bd,908e4ddb,4b165fbb,5eedf6b3,22981f8c) Z8(d631a99f,1d63186f,e7e41ff4,db559e4a,73a37f9b,a294293c,96d97ba5,bb53f161) Z8(f8dfbfe7,6831d090,98e393ba,47cebcbd,16f8b35a,b7b0264e,b8987f0f,7f33aa78) Z8(0f12df40,eac06e0e,e4f62be6,c77ac5f4,b46f37eb,f6ecc54a,66b19807,1e2610b1) Z8(1fbba4e8,4812a31d,46bee989,4551093c,5f48884d,289aef8f,ad8aa374,cddf680f) Z8(58c2f361,a4eaa9ee,b87b8807,e9e43a12,521de08a,c1d52b69,66d96ac2,752d4a48) Z8(ec4fb6f5,17a0764a,eb80aa06,629fa87a,c25d79f2,81d604b0,e5731704,1f00a5ff) Z8(a87c7cbe,90422c16,7783495a,99a226c8,d462537b,b2a75bc5,35e8f086,b8033fb7) Z8(67a2a273,9e04354b,ddc02a44,5d2310c8,b5c43031,cec3545f,56638f85,155cec92) Z8(9f9f6c77,4fbb4c02,b0cd4223,5d4759ef,77d83d6f,b1fb39d2,6a9835d4,043fe66a) },{ Z8(bb243cb9,58c43562,d256cc0f,64b77e8f,27a97f9f,d644dad5,4bb98a41,cffc6e19) Z8(e477c2d2,5667207b,89d9d8b1,eb65accc,b4a687c5,3d815f5f,2e31708d,50170f37) Z8(09b329a0,25063c66,dc7c752b,29a5809f,791edca2,fbbd22dc,13130613,820affeb) Z8(3b1438b9,68a28215,a14105f7,3399ec21,9a58b199,0c61170e,d816b5f4,47999358) Z8(86d91ca8,c893035d,cbe95375,db5fb8c4,e6b86391,bb828830,b1df9e4c,8dc8408d) Z8(35283cbd,74b8bf79,bc758098,7214c793,e0be50b7,9717c248,8a522c0a,dbbc989a) Z8(02683b39,9b78356d,19eb3514,ffeccd17,a6211a68,a90dcd2c,16a7ad68,bad8b6c5) Z8(c7a1c444,c1262f13,6bd59060,fc082052,41b28a5a,3f89ebaf,f6f2b543,f289577f) Z8(2164e7f3,c83a1303,4f2e4187,49ff9d98,30055bcc,b31be9d8,62cc853b,d6068019) Z8(a63c159a,5c7832df,3f64d147,88fb44b7,2d978dcc,6d2ee3e7,cc494cd9,d2ffba05) Z8(4377b259,a867d837,321039fa,270926a0,d6af6377,115a15b0,88399880,204d2b90) Z8(7d031123,5da7d59d,6bc65d00,95599d0f,89fad8bc,d7929d6b,5dfefa62,da34fc0e) Z8(c94244ca,03be8be0,4dffbbb4,048524a4,7fdd6121,d1d9ba23,419b38f1,9db6046f) Z8(bd065f46,5a70edff,fbba45e0,a28d7e79,1aeb1ec0,1cd68b6f,ff7d461a,633e2249) Z8(6ee25835,db456f5c,287540ca,971ef3b0,07cf13fe,6b0b652b,f9e8796e,6913b7d6) Z8(ac048f29,d57ec4b4,d55b6669,81731286,0d9a9b76,9761f966,1ba71959,a66ecdf4) Z8(2429ddc7,711a1e15,4e073a6a,b1822d32,7b31a20e,aebb5520,4f6adbce,4184e96f) Z8(f0186c5b,50fd2a58,ad420164,c635d0c0,22589687,2a7dd9a8,70f98d8c,047fe1a1) },{ Z8(2fac125e,3ef49e64,0adf0866,d7b0de0f,d5d83f70,22764f85,368b23db,f9cbd377) Z8(094607a7,6979f164,c9871228,7913d572,30ecf645,b5c68461,da61e082,46ca700d) Z8(a8fec524,f5fd0219,7b141f40,c1735e13,56900064,fd7a8629,6685c3ac,da1cc0ba) Z8(06f667d5,3c9e706a,9c9aedbb,c78f3971,1866606f,215e0c6c,47be03c1,45b302fd) Z8(78085a54,306a06d9,490ca52e,7fe3d0f6,88f93575,a2ed8b0c,da662739,e68bf85c) Z8(60d0f6f5,b78ce427,c744edfd,a68d20c2,bc4908b4,9efd8a2a,9f9b3887,80bdce6d) Z8(89fcc7cd,8a8572ab,905efda2,b77266e5,5a3e6f29,71e3a904,f5ebe55e,a363e9d0) Z8(d29baf72,3cd22205,6b30edb7,8878d4ea,68ad0e07,d0444452,e61f0e1b,ce060016) Z8(52b0b692,8ba4a908,14a4b521,84fd7f6b,c15962eb,fafc582c,f118fd32,b6b42db2) Z8(0abb2570,b3cfa3a7,4a86f93a,cf4c4ab6,757358a2,de35b249,fb4ec06c,a799055a) Z8(4a9d0c8b,db07e928,b17cf1ac,207e5f55,d946f65e,53e73e23,035c8a41,3fb9a351) Z8(7c104171,bf3c32a9,452aad98,811cde96,81239d55,5505f88a,c2316e3e,75961b5d) Z8(b2c3cfbc,8d95e0b0,fe722b39,39d842f2,99f596ac,fcd7df51,c4facdbe,18eafc80) Z8(92ff8f8b,abd6baf6,3a67ee95,156c6cb6,f789216e,ad7260fa,66ceccc1,99528ac6) Z8(80c3ce0f,c92ce642,8cd53a56,581bc2dd,ad86de12,46da1f18,95648532,6280f112) Z8(87ebad8e,0afc7854,872963a4,41d2796e,29236c66,8ac918e8,1e60490d,22627877) Z8(ade1d246,6685704c,4bfff2d8,4c2aa947,5b1fc2a0,ae81c5c0,e2cd515a,b4877a03) Z8(6740a755,6a85bbe7,789d30eb,1716f7ae,7caa3c94,915ead9d,8e292e02,04bfdc48) },{ Z8(357b6e00,d7477168,ffbf79e1,d80303ea,7e25c7d2,d50a6b33,21ae51dd,369aaa33) Z8(d58ae635,c2d0c1fe,9cf98dca,801bc0a2,cb7d716e,bb1fca70,f24ab64f,b56e4d7c) Z8(81e67cff,26fda7f3,c7fe035a,0e8062a0,5d317464,9185f3a1,61e19e19,99d91bc2) Z8(09630080,18496ac8,5e8aa1a8,c5a3652b,51f1b235,54840fc1,2962674c,52e66367) Z8(eaf6a40a,f8ea25b3,f6e3bfb2,12bdb05e,e67a3039,07ef6f45,9f9570cd,6b318f9a) Z8(bba8a21c,69064e01,fce0bc08,69d41340,4ab5589f,1adf9943,8de73d6d,131e37c9) Z8(92d4cdf4,720e640f,d40fd7b4,ef3de4b1,d6c12708,a01fe5d9,48d8d796,5afbde99) Z8(e83d1e42,7e889466,e3e86c0f,423136b6,dea6b1f3,7996a5ff,fb2f39ff,113b9c48) Z8(dbce0aab,386589b8,973eb260,a45539ee,2a2664ba,1466b0cc,b04b4377,42e1f3d7) Z8(bcafb4e6,1cded802,551ca696,79710fbb,e4321824,95699d79,21904744,1c401e68) Z8(8ba66f0e,dacd509e,7e7219c6,c784dc98,022312b5,7cce849d,e8e1f8a8,8a97eb2c) Z8(df14e3fe,1c8b4e7f,d2f1fe83,cbc8e2fa,b48bcfa9,f35a3d4a,d36a4b88,26b87417) Z8(86f17fe6,bba7734b,e16ff983,d0cb80d8,f5faddc5,48de4c5a,16cd2fc5,8426fa49) Z8(6ba2f910,2d78107c,bfa83c40,b7ed83f7,0e3780b0,2639c501,87d9d2b2,1a1f512c) Z8(f40fd2a1,41bdffd5,b047f860,5dc8f473,7f8f37ff,01e6c7a9,73ffa102,8162c588) Z8(1630b0bb,4026240c,c4092aeb,0c309045,064705eb,0f1cd47c,8afd68c7,5eef6576) Z8(a5a0cb92,6b52a899,206a0785,3293c311,165a6a5a,734d22a1,c5de3191,38d13644) Z8(a3132784,56335a58,5200eb10,fd306b02,04d3fd27,ec153c93,c629bfed,04ffd657) },{ Z8(1b37a109,4c741da9,62be53b1,29857ef1,d8836613,02209fcc,7d7dad24,c0e0126f) Z8(772f725a,023e304f,3f0559a0,e9f04104,7eae3245,900ecee8,43a2b014,126aea90) Z8(cc6a79fa,e761bfe4,a1fa3289,297f034f,61c9b891,db9791e1,1a4ef4bc,119f5c00) Z8(4c2eae1f,d72655a6,70110431,8efb90e2,1c842ecc,7889beda,ea3c57a2,6cce55bb) Z8(b8cabe34,25457d55,8b125d5f,40700934,0fe2cae6,a4f79a04,4dd0173a,0ef60c4c) Z8(c17823b3,7ada7ea2,941c5b73,7ea6eb17,8a189f7e,61cac60b,6ad2c5f3,1af99dfd) Z8(7c885507,75963d0a,954fcbbb,2a588f25,b4258dac,7cddaba5,613e1692,a647ec09) Z8(da1bce35,d4289b40,9418f4d3,00d873c6,7f7c755f,dc7e13ea,aa586a4e,6cefb51d) Z8(3b6ab31f,fe772295,8de44df9,6943bcc1,cbad2798,ee3913a8,16cf5004,9199010b) Z8(3c57cd12,395307e2,a876895b,69cc159a,70360a67,1d133a0d,9ea81825,0254e2da) Z8(5f437279,84d1fd65,8af906ae,6606eb88,daec1255,036bcef3,e368c82a,4f81291e) Z8(7bd87ada,1bfde5d4,01ca2f21,433c48ac,380e44a6,59525113,c9729e47,b7153c82) Z8(719d4913,ec4bbc6d,25c82079,87c9c2d3,97552557,1935c1fe,ea08a105,06c21204) Z8(1042a1f5,92828623,8dd0a97f,e5d8177d,bdb36f87,923080f7,cf09774a,3a71d773) Z8(e2b84f77,0dcbb857,c649d71e,cc2d2010,890158e4,0c12e8f3,23a7350f,3501b9ea) Z8(3454fa21,23b5e71e,054558ea,ed883750,09360fb6,59bc4083,fde667f7,ff958aa4) Z8(a0022a28,ac4bd96d,3b96de34,8e70e458,05a7ddc9,c187777c,3a6ef621,408c816d) Z8(27f35719,3113a239,97804f17,346e447d,5e67fcde,80c3c078,1d6fb9b0,053fcfc7) },{ Z8(a3dd82da,c4a58200,75aa9df5,149013b1,0d27a6b0,ee7ab0c9,6e7b98c4,361467a5) Z8(5c08ac11,81891170,87710766,cbd7564c,da35d1ef,ef092632,794843d7,18efe96e) Z8(0616a61b,96ca9566,565871d9,aea2d522,0626fa7a,3675f869,e56c9bb7,4952673d) Z8(1481ecb6,5a49bd1d,4435098a,1df0c58b,807719e9,349e4508,e96a16ab,88cf836d) Z8(df2b6853,fa47c1e0,5c74e231,baa5d1b2,a4d7dcab,da2652a7,acf1741e,f0ef58a4) Z8(968e3193,65760971,64f13e81,657aec63,af66a0ce,0ff913ca,68ad18b2,8419c801) Z8(69d83638,e22c18f2,f17acefc,f78acdba,51d37d9f,be8018f5,74f426c6,c32a4fab) Z8(3d433984,58469568,89352405,96bca865,c31c27a6,ab92490a,183f7435,ffcf35a7) Z8(84334840,b3d8e7da,dcebb2f8,283fca3d,75e6879d,0bf54ea7,e973b22e,81f427f9) Z8(4acd40c1,5341fd08,22cda7e6,75378161,569d95a0,42dd3a65,8acf4e13,635fde00) Z8(99371a7b,53505836,f6d2adef,aca482bb,192c74c5,8c81a434,11eb41cc,3ed5fbc5) Z8(0a984323,4b21cfb5,720b7075,be0dbb60,c33ed93f,91db8d83,dfa93cce,9231c3aa) Z8(662651d5,abbb7fb7,9c9ce619,15994cc7,ced8eaaf,35dab621,416ff3d3,03e404bd) Z8(dc10a0b5,b4d429e7,05c48c6b,b2b1c0e3,9c46edcb,f0c7c134,1999eb01,16235aba) Z8(a9834481,e49354a1,0971e973,52663b86,e872c250,76e498cc,700f5646,9fc1c4a2) Z8(a30945ae,10fce887,a7c9c969,1b39e93d,d7848d83,9953a1a8,7ed78f81,0e750e2d) Z8(ca493297,9f8a2497,89de5339,28aa0326,6745f7f8,f3b26ea3,fa49fb7c,28cc560b) Z8(60388160,8547e715,eebbf5d1,b6816f35,dd45b49a,39eb873e,98e756ff,057fc88e) },{ Z8(b285a5ed,3012bd04,e9fe7fdb,8873c510,f5ae677b,551862f2,30e519b3,f7addd99) Z8(0caccdcf,09f24c26,daa8ec81,954a11d1,b51aa7ef,889e5394,8b35112f,573d65a3) Z8(ba3b29cd,5fef924f,62a77bf9,a4ed4470,388d2f2e,71b9de91,65aa6716,568b671d) Z8(c32cd7d3,1fed2b99,a80eec13,4680ded2,8af3a42b,8ddfaeb0,15480db9,b3ec201d) Z8(ecfc1963,5fd00e43,2776fe50,65cc31c4,bedc459a,568f4ffd,5bf84e58,3e4a711a) Z8(c1c3abf1,58d913da,0cc3134a,b0fc2255,960a8e15,35249a2d,f1ef74c2,d476f18f) Z8(d8075023,d177a153,7444baa0,fa864fd3,e7abf7ba,cb05bf61,68e5f94a,7268a070) Z8(fefb826d,2ee32117,207fb3b3,98540bec,667ac32a,b1a46b79,93db8d43,cd8fb2ca) Z8(592d704a,b306a8fa,0d27f499,c994862b,ba45f652,45607cce,d9cad278,e870f65e) Z8(a75162f4,e8b62d1b,29c89100,c33f54d5,98b3f259,4ef60f9f,9cefa6a3,d84c6a58) Z8(af3c30da,9fb1348c,56d16a72,4cc7feda,86a6a0fd,737c5b29,8d789534,b1c8537a) Z8(a97cffae,2b81249d,83ddb4ed,875c496a,baefc4d6,c93fdba6,ee3f6bdc,8f637e7a) Z8(f423d15a,08c1652f,6c0631af,22c4d465,2dd974c0,927f2274,8bbda94c,ae643d1a) Z8(8fc2eca8,d9155a63,02abf0b4,c26632f0,5bcef349,fc0afe06,50cf1ddb,5314b56d) Z8(0b74f656,4b2b5653,be6c48e1,d1f35e2f,c4625d77,88bcffda,dad65bc7,e2037a10) Z8(f6966053,0b28aa3a,c244473a,69fe80a1,f23205aa,fd4b5486,4ce057ec,3e76388c) Z8(c74498de,de34c365,ef91291c,d6619c5b,dacc2446,4c20e2d4,f9fd17c4,9103a3c5) Z8(00ba93c5,d36a21e8,ae41b20d,a0fe8c19,99dda021,d79f0ff9,3dfa8fa7,05bfc0a6) },{ Z8(b5c0eb7c,579ca0e3,2694520e,3afbc453,5b63ca88,ccca81c0,ec061d81,12f0195b) Z8(037c96ea,314b8920,6d20b3fe,fe9ccd1f,a12953ef,da4a102b,6c4db481,c65b95ab) Z8(becea825,6d7e626c,352056be,57145de0,2a2e6f25,26b78dc7,8ff922c9,2a074823) Z8(524c3653,70a2263c,8ec61b0d,2bfc4fbc,7b81b885,ae39230a,6e2933c9,1bd43546) Z8(65795e46,cd764058,55076d09,85425eda,3fa9886d,bc11cf75,8f215a3f,d859da2e) Z8(da120739,a86942f3,f4239769,eb7fcdea,cc5e1d73,1a215f21,98fe599c,e2178184) Z8(98fb7868,d6db832e,24d2750f,7789827e,82276096,d954089c,16751c08,22b2c657) Z8(48be0521,7e4ae8ae,fc8e93cc,19eb0799,5d21bcf3,1cb671cf,2de3ccf4,da4466d6) Z8(7bef1e02,0e1233e5,9263d673,d5af6167,59bc8aef,c99f3ae6,780a7a89,5f9e11a5) Z8(06256d8d,44ee053b,e0305c59,4769e465,797241b7,07a3da37,68d87636,cf01c2a4) Z8(03429f3f,0edc22ac,05bfb0b1,70402b19,abd6330e,386d3678,13b4a790,03d3a77e) Z8(a9920273,2fbf0922,82ec5131,dd41abab,d53baeb9,7ffba57e,64757239,c11c919c) Z8(370159b6,d5a2d402,c7357931,4d69172c,0e17a3f7,77b67ec3,b0d6927e,11a5a9b7) Z8(60c951d8,32c8e705,fdb98ba8,2b7386cc,6e3e369f,a8325b8d,8fb6d774,af62cb7c) Z8(4bd894eb,d4e9b6d1,24482382,b1895ceb,7f2f16f7,2fb71700,1f631d03,bb62218f) Z8(4a4828f3,91b8b8cd,58df9fbd,d0b48247,68f3ffb1,31ab0386,416c483e,03476e6a) Z8(a08edf4a,83a73639,cba0219c,a9c8faab,c0bef870,36a7ad69,89a224cf,6e211e53) Z8(4ac30913,c49cd215,6aaedaa2,8dd4fb81,cab5251b,ce7603f5,12970d6b,05ffb806) },{ Z8(50c4fbd9,987ffac3,91340029,6817d2f3,4f283f8b,5382ddfe,e5ee4b7c,77c585e7) Z8(17a94e3c,33fd42c7,42f78ef4,cbc94418,3cf3dd2a,0b3fca9a,4c318654,3f898d48) Z8(8715b44b,d5877fe3,282afc50,955a1fc9,60b49dea,7dd4a4b6,79962b82,810a3dd1) Z8(0906771b,1ecd5874,6f08275c,1fbb6ec5,beb2eeef,c18b9bc0,36dd6378,4a538f42) Z8(563f3034,ff4d0a3f,9f73cbb7,cbdfae45,0191b1d4,f8381e14,3ce0716c,277c8641) Z8(ad3a299d,6bcf004b,cb4f55a2,faf0dd44,a82b3850,0080730f,d588a73b,2f96c0eb) Z8(85fce25f,8bd13b24,f9178912,00e41207,b92fe104,15963528,c6fe40f2,da514790) Z8(8f49d371,3bae1ff7,00edbf94,a18a4973,2ba1587b,57eae314,0ae1da80,36ea1c47) Z8(4ec42b4c,9f647ca4,0dcf02f6,cf49dba2,0125a7bc,941f852d,8c63593a,5f34d9cb) Z8(5e586512,920926bd,a51bbb64,c72cd960,77f6da1a,30a0c288,c2fb448f,27c00a5e) Z8(2a789f65,5db5b68c,e06704af,ba08a2fa,2054b0c2,84006e67,fe44b37f,8fc2e2c4) Z8(367d9c1c,7b63ffcc,18db755b,421adc93,7bf0bdb6,63b8d371,dfae3f69,9c120115) Z8(170094d0,491a1e40,2269ed58,009290df,4eb0358c,20bbabfc,19f4c72a,8d09c183) Z8(39ead666,f886c964,ef99f5d3,e6183b47,63edb2fe,72b5d327,17c5e6df,c241ad53) Z8(6e9b1003,39318494,964e1916,eef1130f,78559e7e,6917bc77,de1a46ba,335820d0) Z8(ed160381,a322e8ae,8456882a,12ce1be3,1f8a0067,44613164,b9a44bb7,e7a82de7) Z8(264e6ebe,9643837c,10b7e9aa,ff14c300,83a4de0d,5d0a42a0,0cc1db88,116d06e1) Z8(16e25ccb,b02d0983,c1f2745b,cfc148ba,1dfc186c,b7bcd1e4,1d3420e4,063faea6) },{ Z8(5f019016,219c1074,1df3e259,68b66bf5,f30042db,18b6bae4,49b1c96b,33bfecd3) Z8(31d441bb,1dd7e63b,a1b0399e,a89c90ce,d633b582,3332b363,ae0a26f4,efc9b074) Z8(d1a901f5,20d98a33,d91245d0,1ff97fb3,43e7156b,c32718db,539bc9f6,f4730630) Z8(513ce058,d6703257,98ec2a75,855d8040,c871b225,61167c6b,d62543d3,b118acfb) Z8(c6613515,0e7823f4,4c1401fb,79f2e305,5bed8ec4,2ae583f2,70cc463b,4d1869d0) Z8(9674c68f,422f492f,7ae9f885,fb9e1282,e11c5b4a,334f97be,5731e40c,76e32ab8) Z8(bd00ca18,d3a56e03,fbcf34c0,b6a076ca,242908c8,fd27746d,de278a43,96c2dfc7) Z8(b3d9dbdc,14ccd47f,8aaefbec,ec18d8ee,7e86ec4f,2898a6fa,7ec7064e,71c84305) Z8(4027d59d,aa54e477,df413ae8,e71195e5,ed06442e,bd505024,747425ef,0c31e0b6) Z8(f4274386,aa7a2d3f,69a9caed,29394477,ec7ecf4d,a824e8ab,abc8ba6d,02b38e18) Z8(3ee2c42b,aff3e7b9,1612edfc,3e9c21b8,8266076b,3498e402,10f4e41a,276c0bf5) Z8(d5a77fd6,1acfcad8,e71c4cc2,02e74438,bc106753,94716603,16b69f33,c7f503e5) Z8(ebe5c144,e88fe751,ad0c04e3,a8fe6592,718ff5cc,11a42234,abe6e6a0,a959ee2f) Z8(735be253,3ebc83db,d37814d4,14a109f5,aaaf16ab,0ab38c90,5bd39ee3,67aa8c30) Z8(f78b1f67,4eae3376,8c839fb9,5c16b554,590131bf,f461c39f,09e2443e,40cd0f54) Z8(5fd2a988,d91f27d7,d65b2e19,c136aca6,f480b68e,a0bee130,cea58b15,51cf3dbb) Z8(f8a5eabf,0f50389a,20c790a6,89dfac06,6d97eafb,418d65d8,9a930eee,99ba6cf8) Z8(d587b7fc,b334e186,95881d72,1acbf031,241d2edb,39b5f02a,64d8b567,067fa47e) },{ Z8(eec32fa3,7295d7f8,6c5436ca,fd98edd7,5f279989,e6d365c3,2849a72e,b18853ec) Z8(aede2557,5b09ea80,b2770abf,49a62223,9dab2720,fe50a0b1,151d5572,6ff00c47) Z8(1dda672f,97cab425,2f754b13,77acdb8a,cc18de68,193279be,1a1f08aa,96bd7d44) Z8(fd6a5457,f9041905,ab3e8a30,64a22282,2aeeb06b,9a81bbae,df87c710,070f729e) Z8(5db9eccc,4f11f5af,4c839d79,e86acff7,b1933f72,7532ca5e,b2370f41,7b2331f3) Z8(8245ce02,138468f7,58f2b3d2,b561ab3c,46cfe7a9,438d8a69,65574616,56e797ad) Z8(b38c9a6f,9a0ebaf0,8407b54f,78dd776f,08eb0645,71696a60,917b8fb0,943b438c) Z8(e492ceb3,a278e238,3d752242,75e57bbe,a75c76f5,3c2fa324,5e65aa1e,97216976) Z8(1ece6590,f29da766,79db2e1b,f11fff18,6102ca42,c134368f,afb1379c,6a166f02) Z8(5fdacb42,36796508,fc4968f0,3ffc0001,fdec7f58,c272233a,10750cba,f081c472) Z8(a9ef9cd4,40173012,37667b8e,c3c07752,d9817e04,54fa911c,0d063b35,47852285) Z8(2e5404a8,65d04d14,1f535d55,7b36210d,63f442a6,c988b08e,c45663f3,88dd8247) Z8(82ecddb3,e9bee6b8,5026b483,79fda580,b0ab361b,d4de84d7,0451d0c7,e9388786) Z8(4a6e210e,2eb8f836,413a53a1,7c045676,5c00d006,a0abf8bd,4efc21b6,e5f3f8f9) Z8(f5e5fc91,65e874e9,a60924bf,e5d0b7c1,31c1f0f1,d8a0caa7,60b47f9c,560b5d2d) Z8(98510280,ec7a0a8c,1fe55b20,51dcd4bf,ad72d7f3,ecb64828,3ab13479,169a05c0) Z8(aca003a4,9d5b12d9,94833f87,03563a2e,e19453ae,c1904a26,41b6eb9d,162da9b6) Z8(73d4c5db,f0baf8ef,4d90b4ab,86b2975c,67c365a9,5245904a,f12143d9,06bf9986) },{ Z8(eb73e32a,e9776273,dfc4212b,4fefe213,3444b97e,1151c398,61751a23,5e34df5c) Z8(d3c4e74a,3bb9e57e,6b44fc0b,ca31edfe,d2abd98a,23c6c3b4,b7d9ac57,7be543c3) Z8(39f923fe,76e35d5b,a1b40b94,2c20895f,57da5e81,484361c2,9a14a667,db44afb7) Z8(943d8629,eeada88a,debfd6f6,7b017751,c869b16f,a17a0077,6acc387f,5239b268) Z8(e5d484e8,dade4b16,3618096e,df71b5af,17af77dd,728f1230,8ca247f8,26555446) Z8(ec781f53,6677dae6,789a30e7,492b63b5,3461a0fa,90de1588,1451dd6f,de0722b2) Z8(649f781b,cd212c67,571c458f,ce2606a7,96004fda,dbd92fc4,990370ca,56e8361e) Z8(6dcabaa9,7d9eff18,80505c45,e12f637a,18c0fb65,67e6168c,29eca98d,e24bd478) Z8(2889c108,ff2782d0,d4e9d760,48eac1e3,55388d31,8eae9263,6d0b5a78,decc8d32) Z8(b0831db2,b1ae6c27,97a0e87b,69f654dc,e8607b43,18a71388,bbb98ef1,77084e9f) Z8(971438c0,31afbd9b,4f42e2b9,28d09d7a,274f6b0a,7894b09d,2bff7a65,ca308546) Z8(102329d1,bd6c0770,038ff935,ea17fd9c,3d1322b3,4ff9a1e5,ad96f958,941e3c41) Z8(852d74e1,10aaee12,a0fa4cc2,8ca46c05,ef91508d,1de68177,725c24ef,d76f9ee0) Z8(0b17be43,f9a89e76,3fbc02fa,d5d610a0,6d146eaa,96a67692,bb2c5dfb,d0bfb2d5) Z8(7d494f99,e01a7e5f,e618eeef,171b8ab6,d3bb7f1c,3b9819c6,a746ed67,909620dd) Z8(c463a76d,66c5bfa9,1953ea86,bb158401,57790b4d,542c01af,aa4b08a1,232e5f59) Z8(c468bf81,d7aa9735,a501ca08,8750f3a2,175e84fc,c64cbc9c,549887da,63253408) Z8(02ffdb3c,9aaafeff,6171a4ba,cb479a5c,f7f8cafc,f209c454,ca45c470,06ff8db7) },{ Z8(fc4ac5fc,068a1d4b,e7049be7,9e8686d1,67fa6559,1b1a7430,c5725f5a,88b5a43a) Z8(6ba88cab,1061ddde,7abbf96a,bc61a48c,1b161929,134ef839,344406c9,4702ba7f) Z8(4e50ff7f,a4729a23,0ba4538c,9d29e633,c896074c,312bd5a0,f6b23bb3,1af31896) Z8(762d056a,7954f5f7,e583facd,7bc92fb1,dd28d540,da7b8091,d0d0158b,a77bb664) Z8(973ec44f,94c743bc,78ea7125,52dbf317,be6f2c40,e42c0e89,899f43a1,124da656) Z8(65b5095f,8b37a110,43139bb6,2700fe0b,fb8447fe,60ea6372,550abc21,6ba87095) Z8(382c25f4,13b6646c,ec480554,f4e5a689,3c8f61ab,c63ede62,48dd4bdd,37620db5) Z8(682104f5,16a89707,5cc2d0a0,60655c96,e86671e0,14131f98,0bfe8664,d1445ccb) Z8(d2ba7764,4c260093,845177ca,4dc6c4da,d3a9c6c4,f450d21c,6960ced8,100af5a6) Z8(198d2b7f,9972dda6,5e457bd4,8f747d9f,ec467303,105ded70,3dc55218,992e2c54) Z8(c287bc3d,e21f7b82,c1989272,c2932c7c,09dc4949,272dc3cf,54045353,f6844f01) Z8(b62a653a,ea7314a6,30792202,d0117905,69f5e4c4,d174554e,b27947f0,bf0b8fa8) Z8(1f672cff,5a5a66b2,58542a57,b024ad3a,a7da2f0e,abc553a7,220efca2,4a2dc1ec) Z8(6b93e3a2,21efe994,f0a50664,d822ca7e,9e234b54,fd987f45,f358709f,a4645c46) Z8(12fb69d1,a074e864,f5399d0d,36213cf7,d3db347c,4695fde3,7db6946f,43bef286) Z8(82965bdb,e42a8399,1f6ee879,e23822d4,400f6435,e6e7ba12,c0cd3bea,5733d623) Z8(807ea90d,ba5c03fc,3cc6598b,2c56337d,887b3d84,5a362872,3e8ce8d1,dc455f1c) Z8(3e99f474,74d31e56,33106f77,93b78b49,7f3c8f18,d9b0abfd,f91f9f4f,073f8108) },{ Z8(e7768546,d74b0c38,8251b4dd,a3a0021b,c0f2d4e3,25fd4030,af99c465,1a541fb5) Z8(1fe3a6f9,f864581a,6f34419f,c09a089c,c3120e69,304c41cd,3a4c10bd,b544dd56) Z8(7b1fdf28,4861b8e2,7865b5f6,4dbddef9,48fcd5c4,43eba614,00a6308d,fe490ed0) Z8(cb94bf89,b2f34afd,cf05479d,52e4df18,ebd578f0,79cae900,7a3b99e1,b1da613c) Z8(908f6e6a,593f60a9,f3e84abc,71819373,da7642f6,d94fd3eb,244f3d42,7e181c67) Z8(f2038dd9,920d5ed8,2b15048a,9638be57,dc48f01e,537a62d8,44727a6c,64c70c44) Z8(b016a924,04413454,906c5231,4f80ba6b,33dc9142,0b2bc661,2c2aba75,d3f44dc8) Z8(a142473b,d0d9e1c9,8f2b72aa,18b99743,b4147915,e71c88ad,5dc8d7e3,94702d94) Z8(d701b66f,7f2d2ec2,77fd5cdc,9e363121,1e999424,c25b82bf,b6ea8d97,cec7824f) Z8(4793a956,e42cf060,ae488c61,c1155744,7d36f600,ef040a05,a7ecb775,3dd6eb7d) Z8(3e6589f3,6a2a5328,e037fa8a,88375d37,3f7db920,a629ae86,0c453efd,8de464e2) Z8(8b5fb864,45b166de,5e3c8c5c,a4caa98a,50b1c488,62688239,0ef01fd6,e001e459) Z8(594f14a8,b2448a61,0630eec3,47bbc1d8,4409ac6c,33c3f641,dea86bad,5a677af4) Z8(328076d8,c7bc28bb,710493c1,dc9246b2,a2a5513f,607c7e1e,62770d2c,1b53196e) Z8(ccdb79ee,2c51ff40,e17423e5,2a81eeae,9b6efa75,1a348e97,2558c9b7,67e7fdf7) Z8(fc969415,2ae52e85,b0cdac18,8e382878,317a599c,60e4cf68,db12349e,ca802f7a) Z8(f49319e8,9628d9c7,1dcade2d,524f9ef3,7100c8f7,b2c591c7,035e6af4,f6c92c85) Z8(ba400398,fad0ec5b,9e27e419,23db8ae7,eaf583f9,af541bee,872f9bf1,077f7372) },{ Z8(926247b6,5986f7dc,1a33a430,031ee945,3e7c1aa5,7fb85212,4b38a11c,f8fdf1a7) Z8(44f79c13,5a959041,a6b5d13d,fd7b000b,ba52d82d,842cbeaf,3250ea36,dda8f0ab) Z8(8ca884f5,80a630cc,2e7c90f8,62974711,d0aad592,05539fef,985273e8,f8215946) Z8(9080d4f3,afe6c0c8,1ac44ee8,479a2857,6a0d0a6a,2841bed2,fed2c5ce,15356cf0) Z8(0045008c,4ef171bc,1d6c9a2a,6b1bfbb8,8018a487,bd45a564,ab29f3cc,48f658af) Z8(56dafb27,d23bb071,9692c8fa,1c3f0d96,02628bbe,1a22f673,b5f911d4,9ff8a20e) Z8(673a54e6,7081f071,9d54449f,9735bd88,e2b036bc,c67d3643,625aa681,0d82bc9e) Z8(67297f43,c53dc131,c8608cb5,cc5a667d,1d452aac,6d3b7967,dbd6237b,02f02562) Z8(76beb762,673dfdf3,a7e9852b,06042cbf,954b3dae,6d10cdff,18187b9c,0e0d45ba) Z8(66bd6bb3,d8bc2e3a,5bead3f8,c3cf5108,a11d1999,a8e3926b,a3ccb7fd,92aa6555) Z8(179479eb,4dcc5c8c,56f25b9a,44efaad9,c25d383d,a991f8da,feb85f9c,879051cf) Z8(4a2d4607,e85ada87,0cc7e524,f9a9a5bf,9d12510c,e8fabc46,62dbf5f8,3945f05e) Z8(7f5cc6c4,59a15b94,9469a706,8a35d84b,4330e8f3,ecf9e02c,b1c0e63d,87123d46) Z8(85249d47,bdbb7177,e4c16c79,c50d545c,5569cd8a,abf8b1f1,c9cfb824,8df4cb9e) Z8(86785dbd,a36963e6,9d6c1eb0,df75e90d,43d8a56a,d49b651c,4b091a9f,14d4f048) Z8(3ddcfa3d,5e3fceb7,be08f27a,b3c09fac,73b1ef47,c96e2715,e6a83ed5,596e4d23) Z8(bd5dd2e7,67fc724d,5ebae2bf,d635b446,682bf0ac,3da7f72b,901bb0d0,7fd76470) Z8(1016ad6e,9f4ebac7,26604410,67555f4a,07bc06ce,45be4112,7ea3cf61,07bf64ec) }}; flint-3.1.3/src/arb/atan_taylor_naive.c000066400000000000000000000035501461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" void _arb_atan_taylor_naive(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int alternating) { ulong k; mp_ptr s, t, x1, x2, u; mp_size_t nn = xn + 1; if (N == 0) { flint_mpn_zero(y, xn); error[0] = 0; return; } if (N == 1) { flint_mpn_copyi(y, x, xn); error[0] = 0; } s = flint_malloc(sizeof(mp_limb_t) * nn); t = flint_malloc(sizeof(mp_limb_t) * nn); u = flint_malloc(sizeof(mp_limb_t) * 2 * nn); x1 = flint_malloc(sizeof(mp_limb_t) * nn); x2 = flint_malloc(sizeof(mp_limb_t) * nn); flint_mpn_zero(s, nn); flint_mpn_zero(t, nn); flint_mpn_zero(u, 2 * nn); flint_mpn_zero(x1, nn); flint_mpn_zero(x2, nn); /* x1 = x */ flint_mpn_copyi(x1 + 1, x, xn); /* x2 = x * x */ flint_mpn_mul_n(u, x1, x1, nn); flint_mpn_copyi(x2, u + nn, nn); /* s = t = x */ flint_mpn_copyi(s, x1, nn); flint_mpn_copyi(t, x1, nn); for (k = 1; k < N; k++) { /* t = t * x2 */ flint_mpn_mul_n(u, t, x2, nn); flint_mpn_copyi(t, u + nn, nn); /* u = t / (2k+1) */ mpn_divrem_1(u, 0, t, nn, 2 * k + 1); if (alternating & k) mpn_sub_n(s, s, u, nn); else mpn_add_n(s, s, u, nn); } flint_mpn_copyi(y, s + 1, xn); error[0] = 2; flint_free(s); flint_free(t); flint_free(u); flint_free(x1); flint_free(x2); } flint-3.1.3/src/arb/atan_taylor_rs.c000066400000000000000000000715401461254215100173620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" /* See verify_taylor.py for code to generate tables and proof of correctness */ #define TMP_ALLOC_LIMBS(size) TMP_ALLOC((size) * sizeof(mp_limb_t)) #define ODD_RECIPROCAL_TAB_SIZE 256 #if FLINT_BITS == 64 const mp_limb_t odd_reciprocal_tab_numer[ODD_RECIPROCAL_TAB_SIZE] = { UWORD(13835020108241056725), UWORD(4611673369413685575), UWORD(2767004021648211345), UWORD(1976431444034436675), UWORD(1537224456471228525), UWORD(1257729100749186975), UWORD(1064232316018542825), UWORD(922334673882737115), UWORD(813824712249473925), UWORD(728158953065318775), UWORD(658810481344812225), UWORD(601522613401785075), UWORD(553400804329642269), UWORD(512408152157076175), UWORD(477069658904864025), UWORD(446290971233582475), UWORD(419243033583062325), UWORD(395286288806887335), UWORD(373919462384893425), UWORD(354744105339514275), UWORD(337439514835147725), UWORD(321744653680024575), UWORD(307444891294245705), UWORD(294362129962575675), UWORD(43378025254434585), UWORD(41676926224848915), UWORD(40104212027684805), UWORD(38645877044859903), UWORD(37289881359075345), UWORD(36025817584191435), UWORD(34844643237168765), UWORD(33738464086782455), UWORD(32700357499496841), UWORD(31724227424884995), UWORD(30804684600975285), UWORD(29936947006581615), UWORD(18078521432946975), UWORD(17596427528068389), UWORD(17139377462404275), UWORD(16705469172216825), UWORD(16292988451915175), UWORD(15900386320543725), UWORD(15526259583589755), UWORD(15169334075921025), UWORD(14828450164102575), UWORD(14502550160495925), UWORD(14190667361345475), UWORD(34099971069969189), UWORD(33396878882959515), UWORD(32722194461081545), UWORD(32074230214327455), UWORD(31451429627641485), UWORD(30852354777591171), UWORD(30275675249038065), UWORD(29720158271991495), UWORD(29184659924748405), UWORD(28668117271213035), UWORD(70414222249896525), UWORD(69210560331094875), UWORD(68047357636454625), UWORD(66922607923455375), UWORD(65834435436895125), UWORD(64781084469904803), UWORD(63760909911323625), UWORD(62772368672388375), UWORD(61814011898764125), UWORD(60884477885248875), UWORD(59982485620282225), UWORD(22849011931010265), UWORD(22520249169412995), UWORD(22200813010981605), UWORD(21890312129709135), UWORD(21588376789989009), UWORD(21294657377880315), UWORD(21008823050660445), UWORD(20730560493698055), UWORD(20459572774826185), UWORD(11592603279646389), UWORD(11444926804746435), UWORD(11300965461290505), UWORD(11160580797175095), UWORD(11023641155491965), UWORD(10890021262698123), UWORD(10759601846378385), UWORD(10632269280149055), UWORD(10507915253480645), UWORD(3812050066792275), UWORD(3768483780314649), UWORD(3725902042683975), UWORD(3684271852262925), UWORD(3643561666050075), UWORD(3603741319973025), UWORD(3564781954351695), UWORD(3526655944144725), UWORD(3489336833624675), UWORD(56769492397408245), UWORD(56181207502098315), UWORD(55604989989256281), UWORD(55040472324390735), UWORD(54487301748266205), UWORD(53945139541815795), UWORD(53413660334507265), UWORD(52892551453194999), UWORD(52381512308719685), UWORD(7543627748528235), UWORD(7472124167973465), UWORD(7401963377663855), UWORD(7333107904383261), UWORD(7265521656416595), UWORD(7199169860467585), UWORD(7134019002001815), UWORD(7070036768800005), UWORD(827619730851221), UWORD(820327927055175), UWORD(813163491011025), UWORD(806123114465475), UWORD(799203602753325), UWORD(792401869963935), UWORD(785714934352425), UWORD(779139913981275), UWORD(1317621181161285), UWORD(1306776562386295), UWORD(1296108998611713), UWORD(1285614188906355), UWORD(1275287970521565), UWORD(1265126313385935), UWORD(1255125314861145), UWORD(1245281194744587), UWORD(30567046059275355), UWORD(30331007093566665), UWORD(30098585583271135), UWORD(29869699000888845), UWORD(29644267310316099), UWORD(29422212873534705), UWORD(29203460361463815), UWORD(28987936668759285), UWORD(438859621842675), UWORD(435667915502001), UWORD(432522298783575), UWORD(429421780512725), UWORD(426365397733275), UWORD(423352214710425), UWORD(420381321975615), UWORD(417451835411325), UWORD(22634811266652585), UWORD(22479245553479715), UWORD(22325803604309205), UWORD(22174442223941007), UWORD(22025119380682145), UWORD(21877794167433435), UWORD(21732426764327565), UWORD(21588978402846855), UWORD(19609694213279247), UWORD(19481943762378405), UWORD(19355847038997315), UWORD(19231372138424985), UWORD(19108487971406295), UWORD(18987164238254509), UWORD(18867371403943755), UWORD(18749080674138465), UWORD(9266890993958325), UWORD(9209510863964775), UWORD(9152836950955761), UWORD(9096856296821475), UWORD(9041556258542925), UWORD(8986924498672575), UWORD(8932948976158025), UWORD(8879617937494395), UWORD(552205768818165), UWORD(548947917674695), UWORD(545728281793905), UWORD(542546192687235), UWORD(539400997367309), UWORD(536292057901215), UWORD(533218750979145), UWORD(17071036886667995), UWORD(16974317130936165), UWORD(16878687175268919), UWORD(16784128703698785), UWORD(16690623808413555), UWORD(16598154978450045), UWORD(16506705088761615), UWORD(16416257389645113), UWORD(912010168967625), UWORD(907067024420375), UWORD(902177175232125), UWORD(897339764104875), UWORD(892553952029649), UWORD(887818917801375), UWORD(883133857549125), UWORD(29941527972993945), UWORD(29785175346503115), UWORD(29630447162884917), UWORD(29477318236978535), UWORD(29325763901569905), UWORD(29175759994144995), UWORD(29027282844047565), UWORD(28880309260027071), UWORD(1449018065980485), UWORD(1441754817529455), UWORD(1434564020434545), UWORD(1427444596015515), UWORD(1420395486899389), UWORD(1413415656496935), UWORD(1406504088494505), UWORD(592554335551395), UWORD(589684823030565), UWORD(586842968461743), UWORD(584028373888785), UWORD(581240648953755), UWORD(578479410716445), UWORD(575744283479015), UWORD(433241218467057), UWORD(431211985593675), UWORD(429201673306525), UWORD(427210018209975), UWORD(425236761774825), UWORD(423281650226435), UWORD(421344434435925), UWORD(2623079648743785), UWORD(2611183595915015), UWORD(2599394956655805), UWORD(2587712282693307), UWORD(2576134151674545), UWORD(2564659166589135), UWORD(2553285955207365), UWORD(210505107582315), UWORD(209579810406129), UWORD(208662612111135), UWORD(207753406829605), UWORD(206852090530995), UWORD(205958560982265), UWORD(205072717709223), UWORD(3779907202434825), UWORD(3763788195174975), UWORD(3747806079696525), UWORD(3731959119528675), UWORD(3716245607446449), UWORD(3700663864857575), UWORD(3685212241204725), UWORD(4501257379467765), UWORD(4482618632554855), UWORD(4464133607265969), UWORD(4445800409700195), UWORD(4427617176940685), UWORD(4409582076423615), UWORD(4391693305322505), UWORD(355589942551207), UWORD(354158997108345), UWORD(352739522170035), UWORD(351331380364965), UWORD(349934436506655), UWORD(348548557550193), UWORD(347173612549995), UWORD(6291002587483845), UWORD(6266380268159055), }; const mp_limb_t odd_reciprocal_tab_denom[ODD_RECIPROCAL_TAB_SIZE] = { UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(13835020108241056725), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(2125523237467294665), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(1319732064605129175), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(3239497251647072955), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(8097635558738100375), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(3130314634548406305), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(1796853508345190295), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(659484661555063575), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(10842973047904974795), UWORD(1576618199442401115), UWORD(1576618199442401115), UWORD(1576618199442401115), UWORD(1576618199442401115), UWORD(1576618199442401115), UWORD(1576618199442401115), UWORD(1576618199442401115), UWORD(1576618199442401115), UWORD(186214439441524725), UWORD(186214439441524725), UWORD(186214439441524725), UWORD(186214439441524725), UWORD(186214439441524725), UWORD(186214439441524725), UWORD(186214439441524725), UWORD(186214439441524725), UWORD(317546704659869685), UWORD(317546704659869685), UWORD(317546704659869685), UWORD(317546704659869685), UWORD(317546704659869685), UWORD(317546704659869685), UWORD(317546704659869685), UWORD(317546704659869685), UWORD(7855730837233766235), UWORD(7855730837233766235), UWORD(7855730837233766235), UWORD(7855730837233766235), UWORD(7855730837233766235), UWORD(7855730837233766235), UWORD(7855730837233766235), UWORD(7855730837233766235), UWORD(119808676763050275), UWORD(119808676763050275), UWORD(119808676763050275), UWORD(119808676763050275), UWORD(119808676763050275), UWORD(119808676763050275), UWORD(119808676763050275), UWORD(119808676763050275), UWORD(6541460456062597065), UWORD(6541460456062597065), UWORD(6541460456062597065), UWORD(6541460456062597065), UWORD(6541460456062597065), UWORD(6541460456062597065), UWORD(6541460456062597065), UWORD(6541460456062597065), UWORD(5980956735050170335), UWORD(5980956735050170335), UWORD(5980956735050170335), UWORD(5980956735050170335), UWORD(5980956735050170335), UWORD(5980956735050170335), UWORD(5980956735050170335), UWORD(5980956735050170335), UWORD(2974672009060622325), UWORD(2974672009060622325), UWORD(2974672009060622325), UWORD(2974672009060622325), UWORD(2974672009060622325), UWORD(2974672009060622325), UWORD(2974672009060622325), UWORD(2974672009060622325), UWORD(186093344091721605), UWORD(186093344091721605), UWORD(186093344091721605), UWORD(186093344091721605), UWORD(186093344091721605), UWORD(186093344091721605), UWORD(186093344091721605), UWORD(5991933947220466245), UWORD(5991933947220466245), UWORD(5991933947220466245), UWORD(5991933947220466245), UWORD(5991933947220466245), UWORD(5991933947220466245), UWORD(5991933947220466245), UWORD(5991933947220466245), UWORD(334707732011118375), UWORD(334707732011118375), UWORD(334707732011118375), UWORD(334707732011118375), UWORD(334707732011118375), UWORD(334707732011118375), UWORD(334707732011118375), UWORD(11407722157710693045), UWORD(11407722157710693045), UWORD(11407722157710693045), UWORD(11407722157710693045), UWORD(11407722157710693045), UWORD(11407722157710693045), UWORD(11407722157710693045), UWORD(11407722157710693045), UWORD(575260172194252545), UWORD(575260172194252545), UWORD(575260172194252545), UWORD(575260172194252545), UWORD(575260172194252545), UWORD(575260172194252545), UWORD(575260172194252545), UWORD(243539831911623345), UWORD(243539831911623345), UWORD(243539831911623345), UWORD(243539831911623345), UWORD(243539831911623345), UWORD(243539831911623345), UWORD(243539831911623345), UWORD(184127517848499225), UWORD(184127517848499225), UWORD(184127517848499225), UWORD(184127517848499225), UWORD(184127517848499225), UWORD(184127517848499225), UWORD(184127517848499225), UWORD(1151531965798521615), UWORD(1151531965798521615), UWORD(1151531965798521615), UWORD(1151531965798521615), UWORD(1151531965798521615), UWORD(1151531965798521615), UWORD(1151531965798521615), UWORD(95358813734788695), UWORD(95358813734788695), UWORD(95358813734788695), UWORD(95358813734788695), UWORD(95358813734788695), UWORD(95358813734788695), UWORD(95358813734788695), UWORD(1765216663537063275), UWORD(1765216663537063275), UWORD(1765216663537063275), UWORD(1765216663537063275), UWORD(1765216663537063275), UWORD(1765216663537063275), UWORD(1765216663537063275), UWORD(2165104799523994965), UWORD(2165104799523994965), UWORD(2165104799523994965), UWORD(2165104799523994965), UWORD(2165104799523994965), UWORD(2165104799523994965), UWORD(2165104799523994965), UWORD(176017021562847465), UWORD(176017021562847465), UWORD(176017021562847465), UWORD(176017021562847465), UWORD(176017021562847465), UWORD(176017021562847465), UWORD(176017021562847465), UWORD(3202120317029277105), UWORD(3202120317029277105), }; #else const mp_limb_t odd_reciprocal_tab_numer[ODD_RECIPROCAL_TAB_SIZE] = { UWORD(1673196525), UWORD(557732175), UWORD(334639305), UWORD(239028075), UWORD(185910725), UWORD(152108775), UWORD(128707425), UWORD(111546435), UWORD(98423325), UWORD(88062975), UWORD(79676025), UWORD(72747675), UWORD(66927861), UWORD(12806255), UWORD(11923065), UWORD(11153835), UWORD(10477845), UWORD(9879111), UWORD(9345105), UWORD(60902835), UWORD(57931965), UWORD(55237455), UWORD(52782457), UWORD(50536395), UWORD(48473685), UWORD(3267715), UWORD(3144405), UWORD(3030063), UWORD(2923745), UWORD(2824635), UWORD(6310395), UWORD(6110065), UWORD(5922063), UWORD(5745285), UWORD(5578755), UWORD(33304425), UWORD(32391975), UWORD(31528189), UWORD(30709275), UWORD(29931825), UWORD(18208955), UWORD(17770185), UWORD(17352063), UWORD(16953165), UWORD(16572195), UWORD(28280835), UWORD(27672645), UWORD(27090063), UWORD(26531505), UWORD(25995515), UWORD(1157205), UWORD(1134735), UWORD(1113121), UWORD(1092315), UWORD(1442445), UWORD(1416455), UWORD(1391385), UWORD(1367187), UWORD(590359), UWORD(580437), UWORD(570843), UWORD(561561), UWORD(2146173), UWORD(2112375), UWORD(2079625), UWORD(2047875), UWORD(2570805), UWORD(2532719), UWORD(2495745), UWORD(2459835), UWORD(1016015), UWORD(1001805), UWORD(987987), UWORD(974545), UWORD(3580965), UWORD(3533535), UWORD(3487345), UWORD(3442347), UWORD(4172637), UWORD(4120151), UWORD(4068969), UWORD(4019043), UWORD(1608711), UWORD(1589445), UWORD(1570635), UWORD(1552265), UWORD(5544525), UWORD(5481159), UWORD(5419225), UWORD(5358675), UWORD(6330885), UWORD(6261695), UWORD(6194001), UWORD(6127755), UWORD(2396095), UWORD(2371005), UWORD(2346435), UWORD(2322369), UWORD(8119797), UWORD(8038191), UWORD(7958209), UWORD(7879803), UWORD(9128493), UWORD(9040295), UWORD(8953785), UWORD(8868915), UWORD(3405815), UWORD(3374133), UWORD(3343035), UWORD(3312505), UWORD(11389725), UWORD(11287575), UWORD(11187241), UWORD(11088675), UWORD(12648405), UWORD(12538895), UWORD(12431265), UWORD(12325467), UWORD(4665519), UWORD(4626477), UWORD(4588083), UWORD(4550321), UWORD(15437253), UWORD(15312255), UWORD(15189265), UWORD(15068235), UWORD(16973565), UWORD(16840439), UWORD(16709385), UWORD(16580355), UWORD(6202855), UWORD(6155685), UWORD(6109227), UWORD(6063465), UWORD(73983), UWORD(73437), UWORD(72899), UWORD(77283), UWORD(76725), UWORD(76175), UWORD(80655), UWORD(80085), UWORD(79523), UWORD(84099), UWORD(83517), UWORD(82943), UWORD(87615), UWORD(87021), UWORD(86435), UWORD(91203), UWORD(90597), UWORD(89999), UWORD(94863), UWORD(94245), UWORD(93635), UWORD(98595), UWORD(97965), UWORD(97343), UWORD(102399), UWORD(101757), UWORD(101123), UWORD(106275), UWORD(105621), UWORD(104975), UWORD(110223), UWORD(109557), UWORD(108899), UWORD(114243), UWORD(113565), UWORD(112895), UWORD(118335), UWORD(117645), UWORD(116963), UWORD(122499), UWORD(121797), UWORD(121103), UWORD(126735), UWORD(126021), UWORD(125315), UWORD(131043), UWORD(130317), UWORD(129599), UWORD(135423), UWORD(134685), UWORD(133955), UWORD(139875), UWORD(139125), UWORD(138383), UWORD(144399), UWORD(143637), UWORD(142883), UWORD(148995), UWORD(148221), UWORD(147455), UWORD(153663), UWORD(152877), UWORD(152099), UWORD(158403), UWORD(157605), UWORD(156815), UWORD(163215), UWORD(162405), UWORD(161603), UWORD(168099), UWORD(167277), UWORD(166463), UWORD(173055), UWORD(172221), UWORD(171395), UWORD(178083), UWORD(177237), UWORD(176399), UWORD(183183), UWORD(182325), UWORD(181475), UWORD(188355), UWORD(187485), UWORD(186623), UWORD(193599), UWORD(192717), UWORD(191843), UWORD(198915), UWORD(198021), UWORD(197135), UWORD(204303), UWORD(203397), UWORD(202499), UWORD(209763), UWORD(208845), UWORD(207935), UWORD(215295), UWORD(214365), UWORD(213443), UWORD(220899), UWORD(219957), UWORD(219023), UWORD(226575), UWORD(225621), UWORD(224675), UWORD(232323), UWORD(231357), UWORD(230399), UWORD(238143), UWORD(237165), UWORD(236195), UWORD(244035), UWORD(243045), UWORD(242063), UWORD(249999), UWORD(248997), UWORD(248003), UWORD(256035), UWORD(255021), UWORD(254015), UWORD(262143), UWORD(261117), }; const mp_limb_t odd_reciprocal_tab_denom[ODD_RECIPROCAL_TAB_SIZE] = { UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(1673196525), UWORD(345768885), UWORD(345768885), UWORD(345768885), UWORD(345768885), UWORD(345768885), UWORD(345768885), UWORD(2375210565), UWORD(2375210565), UWORD(2375210565), UWORD(2375210565), UWORD(2375210565), UWORD(2375210565), UWORD(166653465), UWORD(166653465), UWORD(166653465), UWORD(166653465), UWORD(166653465), UWORD(384934095), UWORD(384934095), UWORD(384934095), UWORD(384934095), UWORD(384934095), UWORD(2364614175), UWORD(2364614175), UWORD(2364614175), UWORD(2364614175), UWORD(2364614175), UWORD(1474925355), UWORD(1474925355), UWORD(1474925355), UWORD(1474925355), UWORD(1474925355), UWORD(2573555985), UWORD(2573555985), UWORD(2573555985), UWORD(2573555985), UWORD(2573555985), UWORD(116877705), UWORD(116877705), UWORD(116877705), UWORD(116877705), UWORD(157226505), UWORD(157226505), UWORD(157226505), UWORD(157226505), UWORD(69072003), UWORD(69072003), UWORD(69072003), UWORD(69072003), UWORD(268271625), UWORD(268271625), UWORD(268271625), UWORD(268271625), UWORD(341917065), UWORD(341917065), UWORD(341917065), UWORD(341917065), UWORD(143258115), UWORD(143258115), UWORD(143258115), UWORD(143258115), UWORD(533563785), UWORD(533563785), UWORD(533563785), UWORD(533563785), UWORD(655104009), UWORD(655104009), UWORD(655104009), UWORD(655104009), UWORD(265437315), UWORD(265437315), UWORD(265437315), UWORD(265437315), UWORD(959202825), UWORD(959202825), UWORD(959202825), UWORD(959202825), UWORD(1145890185), UWORD(1145890185), UWORD(1145890185), UWORD(1145890185), UWORD(452861955), UWORD(452861955), UWORD(452861955), UWORD(452861955), UWORD(1599600009), UWORD(1599600009), UWORD(1599600009), UWORD(1599600009), UWORD(1871341065), UWORD(1871341065), UWORD(1871341065), UWORD(1871341065), UWORD(725438595), UWORD(725438595), UWORD(725438595), UWORD(725438595), UWORD(2517129225), UWORD(2517129225), UWORD(2517129225), UWORD(2517129225), UWORD(2896484745), UWORD(2896484745), UWORD(2896484745), UWORD(2896484745), UWORD(1105728003), UWORD(1105728003), UWORD(1105728003), UWORD(1105728003), UWORD(3782126985), UWORD(3782126985), UWORD(3782126985), UWORD(3782126985), UWORD(4294311945), UWORD(4294311945), UWORD(4294311945), UWORD(4294311945), UWORD(1618945155), UWORD(1618945155), UWORD(1618945155), UWORD(1618945155), UWORD(19901427), UWORD(19901427), UWORD(19901427), UWORD(21252825), UWORD(21252825), UWORD(21252825), UWORD(22664055), UWORD(22664055), UWORD(22664055), UWORD(24136413), UWORD(24136413), UWORD(24136413), UWORD(25671195), UWORD(25671195), UWORD(25671195), UWORD(27269697), UWORD(27269697), UWORD(27269697), UWORD(28933215), UWORD(28933215), UWORD(28933215), UWORD(30663045), UWORD(30663045), UWORD(30663045), UWORD(32460483), UWORD(32460483), UWORD(32460483), UWORD(34326825), UWORD(34326825), UWORD(34326825), UWORD(36263367), UWORD(36263367), UWORD(36263367), UWORD(38271405), UWORD(38271405), UWORD(38271405), UWORD(40352235), UWORD(40352235), UWORD(40352235), UWORD(42507153), UWORD(42507153), UWORD(42507153), UWORD(44737455), UWORD(44737455), UWORD(44737455), UWORD(47044437), UWORD(47044437), UWORD(47044437), UWORD(49429395), UWORD(49429395), UWORD(49429395), UWORD(51893625), UWORD(51893625), UWORD(51893625), UWORD(54438423), UWORD(54438423), UWORD(54438423), UWORD(57065085), UWORD(57065085), UWORD(57065085), UWORD(59774907), UWORD(59774907), UWORD(59774907), UWORD(62569185), UWORD(62569185), UWORD(62569185), UWORD(65449215), UWORD(65449215), UWORD(65449215), UWORD(68416293), UWORD(68416293), UWORD(68416293), UWORD(71471715), UWORD(71471715), UWORD(71471715), UWORD(74616777), UWORD(74616777), UWORD(74616777), UWORD(77852775), UWORD(77852775), UWORD(77852775), UWORD(81181005), UWORD(81181005), UWORD(81181005), UWORD(84602763), UWORD(84602763), UWORD(84602763), UWORD(88119345), UWORD(88119345), UWORD(88119345), UWORD(91732047), UWORD(91732047), UWORD(91732047), UWORD(95442165), UWORD(95442165), UWORD(95442165), UWORD(99250995), UWORD(99250995), UWORD(99250995), UWORD(103159833), UWORD(103159833), UWORD(103159833), UWORD(107169975), UWORD(107169975), UWORD(107169975), UWORD(111282717), UWORD(111282717), UWORD(111282717), UWORD(115499355), UWORD(115499355), UWORD(115499355), UWORD(119821185), UWORD(119821185), UWORD(119821185), UWORD(124249503), UWORD(124249503), UWORD(124249503), UWORD(128785605), UWORD(128785605), UWORD(128785605), UWORD(133430787), UWORD(133430787), }; #endif void _arb_atan_taylor_rs(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int alternating) { mp_ptr s, t, xpow; mp_limb_t new_denom, old_denom, c; slong power, k, m; TMP_INIT; TMP_START; if (N >= ODD_RECIPROCAL_TAB_SIZE) { flint_throw(FLINT_ERROR, "_arb_atan_taylor_rs: N too large!\n"); } if (N <= 2) { if (N == 0) { flint_mpn_zero(y, xn); error[0] = 0; } else if (N == 1) { flint_mpn_copyi(y, x, xn); error[0] = 0; } else { t = TMP_ALLOC_LIMBS(3 * xn); /* x * (1 - x^2 / 3) */ /* higher index ---> */ /* t = | | x^2 (lo) | x^2 (hi) | */ flint_mpn_sqr(t + xn, x, xn); /* t = | x^3 (lo) | x^3 (hi) | x^2 (hi) | */ flint_mpn_mul_n(t, t + 2 * xn, x, xn); /* y = x - x^3 / 3 */ mpn_divrem_1(t, 0, t + xn, xn, 3); if (alternating) mpn_sub_n(y, x, t, xn); else mpn_add_n(y, x, t, xn); error[0] = 3; } } else { /* Choose m ~= sqrt(num_terms) (m must be even, >= 2) */ m = 2; while (m * m < N) m += 2; /* todo: merge allocations */ xpow = TMP_ALLOC_LIMBS((m + 1) * xn); s = TMP_ALLOC_LIMBS(xn + 2); t = TMP_ALLOC_LIMBS(2 * xn + 2); /* todo: 1 limb too much? */ /* higher index ---> */ /* | ---xn--- | */ /* xpow = | | (x^2)^m | (x^2)^(m-1) | ... | (x^2)^2 | x^2 | */ #define XPOW_WRITE(__k) (xpow + (m - (__k)) * xn) #define XPOW_READ(__k) (xpow + (m - (__k) + 1) * xn) flint_mpn_sqr(XPOW_WRITE(1), x, xn); flint_mpn_sqr(XPOW_WRITE(2), XPOW_READ(1), xn); for (k = 4; k <= m; k += 2) { flint_mpn_mul_n(XPOW_WRITE(k - 1), XPOW_READ(k / 2), XPOW_READ(k / 2 - 1), xn); flint_mpn_sqr(XPOW_WRITE(k), XPOW_READ(k / 2), xn); } flint_mpn_zero(s, xn + 1); /* todo: skip one nonscalar multiplication (use x^m) when starting on x^0 */ power = (N - 1) % m; for (k = N - 1; k >= 0; k--) { c = odd_reciprocal_tab_numer[k]; new_denom = odd_reciprocal_tab_denom[k]; old_denom = odd_reciprocal_tab_denom[k+1]; /* change denominators */ if (new_denom != old_denom && k < N - 1) { /* hack when s is negative: add 1 to get a positive number */ if (alternating && (k % 2 == 0)) s[xn] += old_denom; /* multiply by new denominator */ s[xn + 1] = mpn_mul_1(s, s, xn + 1, new_denom); /* divide by old denominator */ mpn_divrem_1(s, 0, s, xn + 2, old_denom); if (s[xn + 1] != 0) { flint_throw(FLINT_ERROR, "bad division!\n"); } /* subtract 1 */ if (alternating && (k % 2 == 0)) s[xn] -= new_denom; } if (power == 0) { /* sub/add c * x^0 -- only top limb is affected */ if (alternating & k) s[xn] -= c; else s[xn] += c; /* Outer polynomial evaluation: multiply by (x^2)^m */ if (k != 0) { flint_mpn_mul(t, s, xn + 1, XPOW_READ(m), xn); flint_mpn_copyi(s, t + xn, xn + 1); } power = m - 1; } else { if (alternating & k) s[xn] -= mpn_submul_1(s, XPOW_READ(power), xn, c); else s[xn] += mpn_addmul_1(s, XPOW_READ(power), xn, c); power--; } } /* finally divide by denominator and multiply by x */ mpn_divrem_1(s, 0, s, xn + 1, odd_reciprocal_tab_denom[0]); flint_mpn_mul(t, s, xn + 1, x, xn); flint_mpn_copyi(y, t + xn, xn); /* error bound (ulp) */ error[0] = 2; } TMP_END; } flint-3.1.3/src/arb/atanh.c000066400000000000000000000014321461254215100154250ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_atanh(arb_t z, const arb_t x, slong prec) { if (arb_is_zero(x)) { arb_zero(z); } else { arb_t t; arb_init(t); arb_sub_ui(t, x, 1, prec + 4); arb_div(t, x, t, prec + 4); arb_mul_2exp_si(t, t, 1); arb_neg(t, t); arb_log1p(z, t, prec); arb_mul_2exp_si(z, z, -1); arb_clear(t); } } flint-3.1.3/src/arb/bell_fmpz.c000066400000000000000000000175521461254215100163160ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arith.h" #include "double_extras.h" #include "arb.h" /* \sum_{k=0}^{a-1} \frac{k^n}{k!} */ /* b = a * \frac{(a-1)^n}{(a-1)!} */ /* assumes n > 0, a >= 0 */ static void lower_bound(mag_t bound, const fmpz_t a, const fmpz_t n) { arb_t t, u; slong wp; if (fmpz_is_zero(a)) { mag_zero(bound); return; } wp = 10 + fmpz_bits(n); arb_init(t); arb_init(u); /* decreasing condition: a * (a-1)^n < a^n */ arb_set_fmpz(t, a); arb_pow_fmpz(t, t, n, wp); arb_set_fmpz(u, a); arb_sub_ui(u, u, 1, wp); arb_pow_fmpz(u, u, n, wp); arb_mul_fmpz(u, u, a, wp); if (arb_lt(u, t)) { arb_gamma_fmpz(t, a, wp); arb_div(t, u, t, wp); arb_get_mag(bound, t); } else { mag_inf(bound); } arb_clear(t); arb_clear(u); } /* b^n [ ((b+1)/b)^n ((b+2)/b)^n ] --- [ 1 + ----------- + ----------- + .... ] b! [ (b+1) (b+1)(b+2) ] */ static void upper_bound(mag_t bound, const fmpz_t b, const fmpz_t n) { arb_t t, u; slong wp; wp = 10 + 2 * fmpz_bits(n); arb_init(t); arb_init(u); /* decreasing condition: (1+1/b)^n / (b+1) < 1 */ /* geometric series factor: 1 + t^2 + t^3 + ... = 1/(1-t) */ arb_one(t); arb_div_fmpz(t, t, b, wp); arb_add_ui(t, t, 1, wp); arb_pow_fmpz(t, t, n, wp); arb_set_fmpz(u, b); arb_add_ui(u, u, 1, wp); arb_div(t, t, u, wp); arb_one(u); arb_sub(u, u, t, wp); if (arb_is_positive(u)) { arb_set_fmpz(t, b); arb_pow_fmpz(t, t, n, wp); arb_div(t, t, u, wp); arb_set_fmpz(u, b); arb_add_ui(u, u, 1, wp); arb_gamma(u, u, wp); arb_div(t, t, u, wp); arb_get_mag(bound, t); } else { mag_inf(bound); } arb_clear(t); arb_clear(u); } /* approximate; need not give a correct bound, but should be accurate so that we find near-optimal cutoffs (we compute correct bounds elsewhere) */ static void _arb_bell_mag(fmpz_t mmag, const fmpz_t n, const fmpz_t k) { if (fmpz_cmp_ui(k, 1) <= 0) { fmpz_set(mmag, k); } else if (fmpz_bits(n) < 50) { double dn, dk, z, u, lg; dn = fmpz_get_d(n); dk = fmpz_get_d(k); z = dk + 1.0; u = 1.0 / z; lg = 0.91893853320467274178 + (z-0.5)*log(z) - z; lg = lg + u * (0.08333333333333333 - 0.00277777777777777778 * (u * u) + 0.00079365079365079365079 * ((u * u) * (u * u))); u = (dn * log(dk) - lg) * 1.4426950408889634074 + 1.0; fmpz_set_d(mmag, u); } else { arb_t t, u; arf_t bound; slong prec; arb_init(t); arb_init(u); arf_init(bound); prec = 10 + 1.1 * fmpz_bits(n); arb_log_fmpz(t, k, prec); arb_mul_fmpz(t, t, n, prec); arb_set_fmpz(u, k); arb_add_ui(u, u, 1, prec); arb_lgamma(u, u, prec); arb_sub(t, t, u, prec); arb_const_log2(u, prec); arb_div(t, t, u, prec); arf_set_mag(bound, arb_radref(t)); arf_add(bound, arb_midref(t), bound, prec, ARF_RND_CEIL); arf_get_fmpz(mmag, bound, ARF_RND_CEIL); arb_clear(t); arb_clear(u); arf_clear(bound); } } void arb_bell_find_cutoffs(fmpz_t A, fmpz_t B, fmpz_t M, fmpz_t Mmag, const fmpz_t n, slong prec) { fmpz_t a, amag, b, bmag, m, mmag, w, wmag, Amag, Bmag; fmpz_init(a); fmpz_init(amag); fmpz_init(b); fmpz_init(bmag); fmpz_init(m); fmpz_init(mmag); fmpz_init(w); fmpz_init(wmag); fmpz_init(Amag); fmpz_init(Bmag); if (fmpz_bits(n) < 53 && 0) { double dn = fmpz_get_d(n); fmpz_set_d(M, dn / d_lambertw(dn)); _arb_bell_mag(Mmag, n, M); } else { /* do ternary search for M */ fmpz_zero(a); fmpz_mul_ui(b, n, 2); fmpz_zero(amag); fmpz_zero(bmag); while (_fmpz_sub_small(b, a) > 4) { fmpz_sub(m, b, a); fmpz_tdiv_q_ui(m, m, 3); fmpz_mul_2exp(w, m, 1); fmpz_add(m, a, m); fmpz_add(w, a, w); _arb_bell_mag(mmag, n, m); _arb_bell_mag(wmag, n, w); if (fmpz_cmp(mmag, wmag) < 0) { fmpz_swap(a, m); fmpz_swap(amag, mmag); } else { fmpz_swap(b, w); fmpz_swap(bmag, wmag); } } fmpz_set(M, a); fmpz_set(Mmag, amag); } /* bisect for A */ fmpz_zero(a); fmpz_zero(amag); fmpz_set(b, M); fmpz_set(bmag, Mmag); while (_fmpz_sub_small(b, a) > 4) { fmpz_sub(m, b, a); fmpz_tdiv_q_2exp(m, m, 1); fmpz_add(m, a, m); _arb_bell_mag(mmag, n, m); /* mmag < Mmag - p */ if (_fmpz_sub_small(mmag, Mmag) < -prec) { fmpz_swap(a, m); fmpz_swap(amag, mmag); } else { fmpz_swap(b, m); fmpz_swap(bmag, mmag); } } fmpz_set(A, a); fmpz_set(Amag, amag); /* bisect for B */ fmpz_set(a, M); fmpz_set(amag, Mmag); fmpz_mul_ui(b, n, 2); fmpz_zero(bmag); while (_fmpz_sub_small(b, a) > 4) { fmpz_sub(m, b, a); fmpz_tdiv_q_2exp(m, m, 1); fmpz_add(m, a, m); _arb_bell_mag(mmag, n, m); /* mmag < Mmag - p */ if (_fmpz_sub_small(mmag, Mmag) < -prec || fmpz_sgn(mmag) <= 0) { fmpz_swap(b, m); fmpz_swap(bmag, mmag); } else { fmpz_swap(a, m); fmpz_swap(amag, mmag); } } fmpz_set(B, a); fmpz_set(Bmag, amag); fmpz_clear(a); fmpz_clear(amag); fmpz_clear(b); fmpz_clear(bmag); fmpz_clear(m); fmpz_clear(mmag); fmpz_clear(w); fmpz_clear(wmag); fmpz_clear(Amag); fmpz_clear(Bmag); } void arb_bell_fmpz(arb_t res, const fmpz_t n, slong prec) { fmpz_t a, b, m, mmag, c; arb_t t; mag_t bound; if (fmpz_sgn(n) < 0) { arb_zero(res); return; } if (fmpz_fits_si(n)) { slong nn = fmpz_get_si(n); /* compute exactly if we would be computing at least half the bits of the exact number */ if (nn < 50 || prec > 0.5 * nn * log(0.7*nn / log(nn)) * 1.442695041) { fmpz_init(a); arith_bell_number(a, nn); arb_set_round_fmpz(res, a, prec); fmpz_clear(a); return; } } fmpz_init(a); fmpz_init(b); fmpz_init(m); fmpz_init(mmag); fmpz_init(c); arb_init(t); mag_init(bound); arb_bell_find_cutoffs(a, b, m, mmag, n, 1.03 * prec + fmpz_bits(n) + 2); /* cutoff: n > 2^12 * prec^2 */ fmpz_set_ui(c, prec); fmpz_mul_ui(c, c, prec); fmpz_mul_2exp(c, c, 12); if (fmpz_cmp(n, c) > 0) arb_bell_sum_taylor(res, n, a, b, mmag, prec + 2); else arb_bell_sum_bsplit(res, n, a, b, mmag, prec + 2); lower_bound(bound, a, n); arb_add_error_mag(res, bound); upper_bound(bound, b, n); arb_add_error_mag(res, bound); arb_const_e(t, prec + 2); arb_div(res, res, t, prec); fmpz_clear(a); fmpz_clear(b); fmpz_clear(m); fmpz_clear(mmag); fmpz_clear(c); arb_clear(t); mag_clear(bound); } void arb_bell_ui(arb_t res, ulong n, slong prec) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, n); arb_bell_fmpz(res, t, prec); fmpz_clear(t); } flint-3.1.3/src/arb/bell_sum_bsplit.c000066400000000000000000000043521461254215100175150ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void bsplit(arb_t P, arb_t Q, const fmpz_t n, const fmpz_t a, const fmpz_t b, slong prec) { fmpz_t t; fmpz_init(t); fmpz_sub(t, b, a); if (fmpz_sgn(t) <= 0) { arb_zero(P); arb_one(Q); } else if (fmpz_cmp_ui(t, 20) < 0) { slong steps, k; arb_t u; arb_init(u); arb_zero(P); arb_one(Q); steps = fmpz_get_si(t); for (k = steps - 1; k >= 0; k--) { fmpz_add_ui(t, a, k); arb_set_round_fmpz(u, t, prec); arb_pow_fmpz(u, u, n, prec); arb_addmul(P, Q, u, prec); if (!fmpz_is_zero(t)) arb_mul_fmpz(Q, Q, t, prec); } arb_clear(u); } else { fmpz_t m; arb_t P1, Q2; fmpz_init(m); arb_init(P1); arb_init(Q2); fmpz_add(m, a, b); fmpz_tdiv_q_2exp(m, m, 1); bsplit(P1, Q, n, a, m, prec); bsplit(P, Q2, n, m, b, prec); arb_mul(Q, Q, Q2, prec); arb_addmul(P, P1, Q2, prec); fmpz_clear(m); arb_clear(P1); arb_clear(Q2); } fmpz_clear(t); } void arb_bell_sum_bsplit(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, slong prec) { if (fmpz_cmp(a, b) >= 0) { arb_zero(res); } else { slong wp; arb_t P, Q; wp = _fmpz_sub_small(b, a); wp = FLINT_BIT_COUNT(FLINT_ABS(wp)); wp = prec + fmpz_bits(n) + fmpz_bits(a) + wp; arb_init(P); arb_init(Q); bsplit(P, Q, n, a, b, wp); arb_div(res, P, Q, wp); if (!fmpz_is_zero(a)) { arb_gamma_fmpz(P, a, wp); arb_div(res, res, P, wp); } arb_set_round(res, res, prec); arb_clear(P); arb_clear(Q); } } flint-3.1.3/src/arb/bell_sum_taylor.c000066400000000000000000000130621461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "arb_poly.h" /* tuning parameter */ #define RADIUS_BITS 3 void _arb_bell_sum_taylor(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, slong tol) { fmpz_t m, r, R, tmp; mag_t B, C, D, bound; arb_t t, u; slong wp, k, N; if (_fmpz_sub_small(b, a) < 5) { arb_bell_sum_bsplit(res, n, a, b, mmag, tol); return; } fmpz_init(m); fmpz_init(r); fmpz_init(R); fmpz_init(tmp); /* r = max(m - a, b - m) */ /* m = a + (b - a) / 2 */ fmpz_sub(r, b, a); fmpz_cdiv_q_2exp(r, r, 1); fmpz_add(m, a, r); fmpz_mul_2exp(R, r, RADIUS_BITS); mag_init(B); mag_init(C); mag_init(D); mag_init(bound); arb_init(t); arb_init(u); if (fmpz_cmp(R, m) >= 0) { mag_inf(C); mag_inf(D); } else { /* C = exp(R * |F'(m)| + (1/2) R^2 * (n/(m-R)^2 + 1/(m-R))) */ /* C = exp(R * (|F'(m)| + (1/2) R * (n/(m-R) + 1)/(m-R))) */ /* D = (1/2) R * (n/(m-R) + 1)/(m-R) */ fmpz_sub(tmp, m, R); mag_set_fmpz(D, n); mag_div_fmpz(D, D, tmp); mag_one(C); mag_add(D, D, C); mag_div_fmpz(D, D, tmp); mag_mul_fmpz(D, D, R); mag_mul_2exp_si(D, D, -1); /* C = |F'(m)| */ wp = 20 + 1.05 * fmpz_bits(n); arb_set_fmpz(t, n); arb_div_fmpz(t, t, m, wp); fmpz_add_ui(tmp, m, 1); arb_set_fmpz(u, tmp); arb_digamma(u, u, wp); arb_sub(t, t, u, wp); arb_get_mag(C, t); /* C = exp(R * (C + D)) */ mag_add(C, C, D); mag_mul_fmpz(C, C, R); mag_exp(C, C); } if (mag_cmp_2exp_si(C, tol / 4 + 2) > 0) { _arb_bell_sum_taylor(res, n, a, m, mmag, tol); _arb_bell_sum_taylor(t, n, m, b, mmag, tol); arb_add(res, res, t, 2 * tol); } else { arb_ptr mx, ser1, ser2, ser3; /* D = T(m) */ wp = 20 + 1.05 * fmpz_bits(n); arb_set_fmpz(t, m); arb_pow_fmpz(t, t, n, wp); fmpz_add_ui(tmp, m, 1); arb_gamma_fmpz(u, tmp, wp); arb_div(t, t, u, wp); arb_get_mag(D, t); /* error bound: (b-a) * C * D * B^N / (1 - B), B = r/R */ /* ((b-a) * C * D * 2) * 2^(-N*RADIUS_BITS) */ /* ((b-a) * C * D * 2) */ mag_mul(bound, C, D); mag_mul_2exp_si(bound, bound, 1); fmpz_sub(tmp, b, a); mag_mul_fmpz(bound, bound, tmp); /* N = (tol + log2((b-a)*C*D*2) - mmag) / RADIUS_BITS */ if (mmag == NULL) { /* estimate D ~= 2^mmag */ fmpz_add_ui(tmp, MAG_EXPREF(C), tol); fmpz_cdiv_q_ui(tmp, tmp, RADIUS_BITS); } else { fmpz_sub(tmp, MAG_EXPREF(bound), mmag); fmpz_add_ui(tmp, tmp, tol); fmpz_cdiv_q_ui(tmp, tmp, RADIUS_BITS); } if (fmpz_cmp_ui(tmp, 5 * tol / 4) > 0) N = 5 * tol / 4; else if (fmpz_cmp_ui(tmp, 2) < 0) N = 2; else N = fmpz_get_ui(tmp); /* multiply by 2^(-N*RADIUS_BITS) */ mag_mul_2exp_si(bound, bound, -N * RADIUS_BITS); mx = _arb_vec_init(2); ser1 = _arb_vec_init(N); ser2 = _arb_vec_init(N); ser3 = _arb_vec_init(N); /* estimate (this should work for moderate n and tol) */ wp = 1.1 * tol + 1.05 * fmpz_bits(n) + 5; /* increase precision until convergence */ while (1) { /* (m+x)^n / gamma(m+1+x) */ arb_set_fmpz(mx, m); arb_one(mx + 1); _arb_poly_log_series(ser1, mx, 2, N, wp); for (k = 0; k < N; k++) arb_mul_fmpz(ser1 + k, ser1 + k, n, wp); arb_add_ui(mx, mx, 1, wp); _arb_poly_lgamma_series(ser2, mx, 2, N, wp); _arb_vec_sub(ser1, ser1, ser2, N, wp); _arb_poly_exp_series(ser3, ser1, N, N, wp); /* t = a - m, u = b - m */ arb_set_fmpz(t, a); arb_sub_fmpz(t, t, m, wp); arb_set_fmpz(u, b); arb_sub_fmpz(u, u, m, wp); arb_power_sum_vec(ser1, t, u, N, wp); arb_zero(res); for (k = 0; k < N; k++) arb_addmul(res, ser3 + k, ser1 + k, wp); if (mmag != NULL) { if (_fmpz_sub_small(MAG_EXPREF(arb_radref(res)), mmag) <= -tol) break; } else { if (arb_rel_accuracy_bits(res) >= tol) break; } wp = 2 * wp; } /* add the series truncation bound */ arb_add_error_mag(res, bound); _arb_vec_clear(mx, 2); _arb_vec_clear(ser1, N); _arb_vec_clear(ser2, N); _arb_vec_clear(ser3, N); } mag_clear(B); mag_clear(C); mag_clear(D); mag_clear(bound); arb_clear(t); arb_clear(u); fmpz_clear(m); fmpz_clear(r); fmpz_clear(R); fmpz_clear(tmp); } void arb_bell_sum_taylor(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, slong prec) { _arb_bell_sum_taylor(res, n, a, b, mmag, prec + 5); } flint-3.1.3/src/arb/bernoulli_fmpz.c000066400000000000000000000026041461254215100173630ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_bernoulli_fmpz(arb_t res, const fmpz_t n, slong prec) { if (fmpz_cmp_ui(n, UWORD_MAX) <= 0) { if (fmpz_sgn(n) >= 0) arb_bernoulli_ui(res, fmpz_get_ui(n), prec); else arb_zero(res); } else if (fmpz_is_odd(n)) { arb_zero(res); } else { arb_t t; slong wp; arb_init(t); wp = prec + 2 * fmpz_bits(n); /* zeta(n) ~= 1 */ arf_one(arb_midref(res)); mag_one(arb_radref(res)); mag_mul_2exp_si(arb_radref(res), arb_radref(res), WORD_MIN); /* |B_n| = 2 * n! / (2*pi)^n * zeta(n) */ arb_gamma_fmpz(t, n, wp); arb_mul_fmpz(t, t, n, wp); arb_mul(res, res, t, wp); arb_const_pi(t, wp); arb_mul_2exp_si(t, t, 1); arb_pow_fmpz(t, t, n, wp); arb_div(res, res, t, prec); arb_mul_2exp_si(res, res, 1); if (fmpz_fdiv_ui(n, 4) == 0) arb_neg(res, res); arb_clear(t); } } flint-3.1.3/src/arb/bernoulli_poly_ui.c000066400000000000000000000051001461254215100200610ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_bernoulli_poly_ui(arb_t res, ulong n, const arb_t x, slong prec) { arb_t s, t, c, x2; ulong m, k; int negate; if (n == 0) { arb_one(res); return; } if (n == 1) { arb_mul_2exp_si(res, x, 1); arb_sub_ui(res, res, 1, prec); arb_mul_2exp_si(res, res, -1); return; } /* small integer x */ if (arb_is_int(x) && arf_cmpabs_ui(arb_midref(x), n) < 0 && n < WORD_MAX) { if (arf_sgn(arb_midref(x)) >= 0) { m = arf_get_si(arb_midref(x), ARF_RND_DOWN); negate = 0; } else { m = UWORD(1) - arf_get_si(arb_midref(x), ARF_RND_DOWN); negate = n % 2; } arb_init(t); arb_zero(res); /* todo: use a dedicated power sum function */ for (k = 1; k < m; k++) { arb_ui_pow_ui(t, k, n - 1, prec); arb_add(res, res, t, prec); } arb_mul_ui(res, res, n, prec); arb_bernoulli_ui(t, n, prec); arb_add(res, res, t, prec); if (negate) arb_neg(res, res); arb_clear(t); return; } /* assuming small n simplifies the code that follows */ if (n >> (FLINT_BITS / 2) || !arb_is_finite(x)) { arb_indeterminate(res); return; } arb_init(s); arb_init(t); arb_init(c); arb_init(x2); arb_mul(x2, x, x, prec); /* s = x^2 - x n / 2 */ arb_mul_ui(s, x, n, prec); arb_mul_2exp_si(s, s, -1); arb_sub(s, x2, s, prec); /* c = n (n-1) / 2; s = s + c / 6 */ arb_set_ui(c, n * (n - 1)); arb_mul_2exp_si(c, c, -1); arb_div_ui(t, c, 6, prec); arb_add(s, s, t, prec); for (k = 4; k <= n; k += 2) { /* c = binomial(n,k) */ arb_mul_ui(c, c, (n + 1 - k) * (n + 2 - k), prec); arb_div_ui(c, c, k * (k - 1), prec); /* s = s x^2 + b_k c */ arb_mul(s, s, x2, prec); arb_bernoulli_ui(t, k, prec); arb_addmul(s, t, c, prec); } if (n >= 3 && n % 2) arb_mul(s, s, x, prec); arb_swap(res, s); arb_clear(s); arb_clear(t); arb_clear(c); arb_clear(x2); } flint-3.1.3/src/arb/bernoulli_ui.c000066400000000000000000000020771461254215100170300ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb.h" #include "bernoulli.h" void arb_bernoulli_ui(arb_t b, ulong n, slong prec) { if (n < bernoulli_cache_num) { arb_set_fmpq(b, bernoulli_cache + n, prec); } else { int use_frac; use_frac = (n < BERNOULLI_SMALL_NUMER_LIMIT) || (n % 2 != 0); if (!use_frac && n < UWORD_MAX / 1000) use_frac = (prec > bernoulli_global_prec(n)); if (use_frac) { fmpq_t t; fmpq_init(t); bernoulli_fmpq_ui(t, n); arb_set_fmpq(b, t, prec); fmpq_clear(t); } else { arb_bernoulli_ui_zeta(b, n, prec); } } } flint-3.1.3/src/arb/bernoulli_ui_zeta.c000066400000000000000000000023411461254215100200450ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_zeta_inv_ui_euler_product(arb_t z, ulong s, slong prec); void arb_bernoulli_ui_zeta(arb_t b, ulong n, slong prec) { slong wp, piwp; arb_t t, u; if (n < 10 || n % 2 != 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); wp = prec + 8; piwp = wp + 2*FLINT_BIT_COUNT(n); arb_init(t); arb_init(u); /* |B_n| = 2 * n! / (2*pi)^n * zeta(n) */ arb_fac_ui(b, n, piwp); arb_const_pi(t, piwp); arb_mul_2exp_si(t, t, 1); arb_pow_ui(t, t, n, piwp); if (n > 0.7 * wp) { arb_zeta_ui_asymp(u, n, wp); arb_mul(b, b, u, wp); } else { arb_zeta_inv_ui_euler_product(u, n, wp); arb_mul(t, t, u, wp); } arb_div(b, b, t, prec); arb_mul_2exp_si(b, b, 1); if (n % 4 == 0) arb_neg(b, b); arb_clear(t); arb_clear(u); } flint-3.1.3/src/arb/bin.c000066400000000000000000000017701461254215100151070ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_bin_ui(arb_t x, const arb_t n, ulong k, slong prec) { if (k == 0) { arb_one(x); } else if (k == 1) { arb_set_round(x, n, prec); } else { arb_t t, u; arb_init(t); arb_init(u); arb_sub_ui(t, n, k - 1, prec); arb_rising_ui(t, t, k, prec); arb_fac_ui(u, k, prec); arb_div(x, t, u, prec); arb_clear(t); arb_clear(u); } } void arb_bin_uiui(arb_t x, ulong n, ulong k, slong prec) { arb_t t; arb_init(t); arb_set_ui(t, n); arb_bin_ui(x, t, k, prec); arb_clear(t); } flint-3.1.3/src/arb/can_round_mpfr.c000066400000000000000000000026541461254215100173350ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb.h" int mpfr_round_p(mp_srcptr, mp_size_t, mpfr_exp_t, mpfr_prec_t); int arb_can_round_arf(const arb_t x, slong prec, arf_rnd_t rnd) { return arb_can_round_mpfr(x, prec, arf_rnd_to_mpfr(rnd)); } int arb_can_round_mpfr(const arb_t x, slong prec, mpfr_rnd_t rnd) { if (!arb_is_finite(x)) { return 0; } else if (mag_is_zero(arb_radref(x))) { return 1; } else if (arf_is_zero(arb_midref(x))) { return 0; } else { slong e, bits; mp_size_t n; mp_srcptr d; e = _fmpz_sub_small(ARF_EXPREF(arb_midref(x)), MAG_EXPREF(arb_radref(x))); if (e < prec) return 0; /* The relative exponent could be tiny (in which case _fmpz_sub_small has clamped it). Looking just past the end will be enough. */ bits = arb_bits(x); e = FLINT_MIN(e, FLINT_MAX(bits, prec) + 10); ARF_GET_MPN_READONLY(d, n, arb_midref(x)); return mpfr_round_p(d, n, e, prec + (rnd == MPFR_RNDN)); } } flint-3.1.3/src/arb/ceil.c000066400000000000000000000016651461254215100152560ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_ceil(arb_t z, const arb_t x, slong prec) { if (!arb_is_finite(x)) { arb_indeterminate(z); } else if (arb_is_exact(x)) { arf_ceil(arb_midref(z), arb_midref(x)); mag_zero(arb_radref(z)); arb_set_round(z, z, prec); } else { arf_t a, b; arf_init(a); arf_init(b); arb_get_interval_arf(a, b, x, prec); arf_ceil(a, a); arf_ceil(b, b); arb_set_interval_arf(z, a, b, prec); arf_clear(a); arf_clear(b); } } flint-3.1.3/src/arb/chebyshev_t_ui.c000066400000000000000000000016621461254215100173370ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "gr_special.h" void arb_chebyshev_t2_ui(arb_t a, arb_t b, ulong n, const arb_t x, slong prec) { gr_ctx_t ctx; fmpz_t m; gr_ctx_init_real_arb(ctx, prec); fmpz_init_set_ui(m, n); GR_MUST_SUCCEED(gr_generic_chebyshev_t2_fmpz(a, b, m, x, ctx)); fmpz_clear(m); } void arb_chebyshev_t_ui(arb_t y, ulong n, const arb_t x, slong prec) { gr_ctx_t ctx; fmpz_t m; gr_ctx_init_real_arb(ctx, prec); fmpz_init_set_ui(m, n); GR_MUST_SUCCEED(gr_generic_chebyshev_t_fmpz(y, m, x, ctx)); fmpz_clear(m); } flint-3.1.3/src/arb/chebyshev_u_ui.c000066400000000000000000000016621461254215100173400ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "gr_special.h" void arb_chebyshev_u2_ui(arb_t a, arb_t b, ulong n, const arb_t x, slong prec) { gr_ctx_t ctx; fmpz_t m; gr_ctx_init_real_arb(ctx, prec); fmpz_init_set_ui(m, n); GR_MUST_SUCCEED(gr_generic_chebyshev_u2_fmpz(a, b, m, x, ctx)); fmpz_clear(m); } void arb_chebyshev_u_ui(arb_t y, ulong n, const arb_t x, slong prec) { gr_ctx_t ctx; fmpz_t m; gr_ctx_init_real_arb(ctx, prec); fmpz_init_set_ui(m, n); GR_MUST_SUCCEED(gr_generic_chebyshev_u_fmpz(y, m, x, ctx)); fmpz_clear(m); } flint-3.1.3/src/arb/clear.c000066400000000000000000000014551461254215100154250ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* The clear methods are not defined as inlines since this inflates the code size. We inline the content manually here to avoid function call overhead. */ void arb_clear(arb_t x) { ARF_DEMOTE(arb_midref(x)); if (COEFF_IS_MPZ(ARF_EXP(arb_midref(x)))) _fmpz_clear_mpz(ARF_EXP(arb_midref(x))); if (COEFF_IS_MPZ(MAG_EXP(arb_radref(x)))) _fmpz_clear_mpz(MAG_EXP(arb_radref(x))); } flint-3.1.3/src/arb/const_apery.c000066400000000000000000000030721461254215100166620ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" void arb_const_apery_eval(arb_t s, slong prec) { hypgeom_t series; arb_t t; arb_init(t); hypgeom_init(series); fmpz_poly_set_str(series->A, "12 2539221463380 55800350430619 543035311757517 3094818610007883 11495362203169095 29262452925092202 52160137207884216 65180430489299744 56019281176488240 31567339140195744 10506477648460032 1565994397644288"); fmpz_poly_set_str(series->B, "1 1"); fmpz_poly_set_str(series->P, "15 0 0 0 0 0 -30 691 -6781 37374 -127976 283232 -406224 364896 -186624 41472"); fmpz_poly_set_str(series->Q, "15 -44008272000 -2334151436400 -53522442803340 -703273183134030 -5931859745397870 -34140867105175650 -139058868850409430 -409481300311614720 -880500176512163280 -1382139595517666400 -1565294958171053280 -1244539247650560000 -658690593528960000 -208277254886400000 -29753893555200000"); prec += 4 + FLINT_CLOG2(prec); arb_hypgeom_infsum(s, t, series, prec, prec); arb_mul_ui(t, t, 1031443875, prec); arb_mul_2exp_si(t, t, 11); arb_div(s, s, t, prec); hypgeom_clear(series); arb_clear(t); } ARB_DEF_CACHED_CONSTANT(arb_const_apery, arb_const_apery_eval) flint-3.1.3/src/arb/const_catalan.c000066400000000000000000000022671461254215100171520ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" void arb_const_catalan_eval(arb_t s, slong prec) { hypgeom_t series; arb_t t; arb_init(t); hypgeom_init(series); fmpz_poly_set_str(series->A, "7 1999553 21620948 94165776 211938912 260619984 166411584 43203456"); fmpz_poly_set_str(series->B, "1 1"); fmpz_poly_set_str(series->P, "9 0 0 0 1280 -17536 86400 -195840 207360 -82944"); fmpz_poly_set_str(series->Q, "9 363825 12034680 150240200 918651040 3101725520 6073920000 6863040000 4147200000 1036800000"); prec += 4 + FLINT_CLOG2(prec); arb_hypgeom_infsum(s, t, series, prec, prec); arb_mul_ui(t, t, 2182950, prec); arb_div(s, s, t, prec); hypgeom_clear(series); arb_clear(t); } ARB_DEF_CACHED_CONSTANT(arb_const_catalan, arb_const_catalan_eval) flint-3.1.3/src/arb/const_e.c000066400000000000000000000016721461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" void arb_const_e_eval(arb_t s, slong prec) { hypgeom_t series; arb_t t; arb_init(t); hypgeom_init(series); fmpz_poly_set_str(series->A, "1 1"); fmpz_poly_set_str(series->B, "1 1"); fmpz_poly_set_str(series->P, "1 1"); fmpz_poly_set_str(series->Q, "2 0 1"); prec += FLINT_CLOG2(prec); arb_hypgeom_infsum(s, t, series, prec, prec); arb_div(s, s, t, prec); hypgeom_clear(series); arb_clear(t); } ARB_DEF_CACHED_CONSTANT(arb_const_e, arb_const_e_eval) flint-3.1.3/src/arb/const_euler.c000066400000000000000000000252051461254215100166600ustar00rootroot00000000000000/* Copyright (C) 2012, 2013, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" #include "arb_hypgeom.h" typedef struct { arb_t P; arb_t Q; arb_t T; arb_t C; arb_t D; arb_t V; slong a; slong b; } euler_bsplit_1_struct; typedef euler_bsplit_1_struct euler_bsplit_1_t[1]; static void euler_bsplit_1_init(euler_bsplit_1_t s, void * args) { arb_init(s->P); arb_init(s->Q); arb_init(s->T); arb_init(s->C); arb_init(s->D); arb_init(s->V); } static void euler_bsplit_1_clear(euler_bsplit_1_t s, void * args) { arb_clear(s->P); arb_clear(s->Q); arb_clear(s->T); arb_clear(s->C); arb_clear(s->D); arb_clear(s->V); } typedef struct { slong N; slong prec; slong a; slong b; } bsplit_args_t; static void euler_bsplit_1_merge(euler_bsplit_1_t s, euler_bsplit_1_t L, euler_bsplit_1_t R, bsplit_args_t * args) { arb_t t, u, v; slong wp = args->prec; slong b = R->b; int cont = (b != args->b); arb_init(t); arb_init(u); arb_init(v); if (cont) arb_mul(s->P, L->P, R->P, wp); arb_mul(s->Q, L->Q, R->Q, wp); arb_mul(s->D, L->D, R->D, wp); /* T = LP RT + RQ LT*/ arb_mul(t, L->P, R->T, wp); arb_mul(v, R->Q, L->T, wp); arb_add(s->T, t, v, wp); /* C = LC RD + RC LD */ if (cont) { arb_mul(s->C, L->C, R->D, wp); arb_addmul(s->C, R->C, L->D, wp); } /* V = RD (RQ LV + LC LP RT) + LD LP RV */ arb_mul(u, L->P, R->V, wp); arb_mul(u, u, L->D, wp); arb_mul(v, R->Q, L->V, wp); arb_addmul(v, t, L->C, wp); arb_mul(v, v, R->D, wp); arb_add(s->V, u, v, wp); arb_clear(t); arb_clear(u); arb_clear(v); s->a = L->a; s->b = R->b; } static void euler_bsplit_1_basecase(euler_bsplit_1_t s, slong n1, slong n2, bsplit_args_t * args) { if (n2 - n1 == 1) { slong wp = args->prec; arb_set_si(s->P, args->N); /* p = N^2 */ arb_mul(s->P, s->P, s->P, wp); arb_set_si(s->Q, n1 + 1); /* q = (k + 1)^2 */ arb_mul(s->Q, s->Q, s->Q, wp); arb_set_si(s->C, 1); arb_set_si(s->D, n1 + 1); arb_set(s->T, s->P); arb_set(s->V, s->P); s->a = n1; s->b = n2; } else { euler_bsplit_1_t L, R; slong m = n1 + (n2 - n1) / 2; euler_bsplit_1_init(L, args); euler_bsplit_1_init(R, args); euler_bsplit_1_basecase(L, n1, m, args); euler_bsplit_1_basecase(R, m, n2, args); euler_bsplit_1_merge(s, L, R, args); euler_bsplit_1_clear(L, args); euler_bsplit_1_clear(R, args); } } static void euler_bsplit_1(euler_bsplit_1_t s, slong n1, slong n2, slong N, slong wp, int cont) { bsplit_args_t args; args.N = N; args.prec = wp; args.a = n1; args.b = n2; flint_parallel_binary_splitting(s, (bsplit_basecase_func_t) euler_bsplit_1_basecase, (bsplit_merge_func_t) euler_bsplit_1_merge, sizeof(euler_bsplit_1_struct), (bsplit_init_func_t) euler_bsplit_1_init, (bsplit_clear_func_t) euler_bsplit_1_clear, &args, n1, n2, 4, -1, 0); } typedef struct { arb_t P; arb_t Q; arb_t T; slong a; slong b; } euler_bsplit_2_struct; typedef euler_bsplit_2_struct euler_bsplit_2_t[1]; static void euler_bsplit_2_init(euler_bsplit_2_t s, void * args) { arb_init(s->P); arb_init(s->Q); arb_init(s->T); } static void euler_bsplit_2_clear(euler_bsplit_2_t s, void * args) { arb_clear(s->P); arb_clear(s->Q); arb_clear(s->T); } static void euler_bsplit_2_merge(euler_bsplit_2_t s, euler_bsplit_2_t L, euler_bsplit_2_t R, bsplit_args_t * args) { arb_ptr P = s->P; arb_ptr Q = s->Q; arb_ptr T = s->T; arb_ptr P2 = R->P; arb_ptr Q2 = R->Q; arb_ptr T2 = R->T; slong wp = args->prec; slong b = R->b; int cont = (b != args->b); arb_mul(T, T, Q2, wp); arb_mul(T2, T2, P, wp); arb_add(T, T, T2, wp); if (cont) arb_mul(P, P, P2, wp); arb_mul(Q, Q, Q2, wp); s->a = L->a; s->b = R->b; } static void euler_bsplit_2_basecase(euler_bsplit_2_t s, slong n1, slong n2, bsplit_args_t * args) { if (n2 - n1 == 1) { slong wp = args->prec; slong N = args->N; arb_ptr P = s->P; arb_ptr Q = s->Q; arb_ptr T = s->T; if (n2 - n1 != 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (n1 == 0) { arb_set_si(P, 1); arb_set_si(Q, 4 * N); arb_set_si(T, 1); } else { arb_si_pow_ui(P, 1 - 2*n1, 3, wp); arb_neg(P, P); arb_set_si(Q, 32 * n1); arb_mul_ui(Q, Q, N, wp); arb_mul_ui(Q, Q, N, wp); } arb_set(T, P); s->a = n1; s->b = n2; } else { euler_bsplit_2_t R; slong m = n1 + (n2 - n1) / 2; euler_bsplit_2_init(R, args); euler_bsplit_2_basecase(s, n1, m, args); euler_bsplit_2_basecase(R, m, n2, args); euler_bsplit_2_merge(s, s, R, args); euler_bsplit_2_clear(R, args); } } static void euler_bsplit_2(arb_t P, arb_t Q, arb_t T, slong n1, slong n2, slong N, slong wp, int cont) { euler_bsplit_2_t s; bsplit_args_t args; args.N = N; args.prec = wp; args.a = n1; args.b = n2; *s->P = *P; *s->Q = *Q; *s->T = *T; flint_parallel_binary_splitting(s, (bsplit_basecase_func_t) euler_bsplit_2_basecase, (bsplit_merge_func_t) euler_bsplit_2_merge, sizeof(euler_bsplit_2_struct), (bsplit_init_func_t) euler_bsplit_2_init, (bsplit_clear_func_t) euler_bsplit_2_clear, &args, n1, n2, 4, -1, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); *P = *s->P; *Q = *s->Q; *T = *s->T; } static void atanh_bsplit(arb_t s, ulong c, slong a, slong prec) { arb_t t; hypgeom_t series; hypgeom_init(series); arb_init(t); fmpz_poly_set_ui(series->A, 1); fmpz_poly_set_coeff_ui(series->B, 0, 1); fmpz_poly_set_coeff_ui(series->B, 1, 2); fmpz_poly_set_ui(series->P, 1); fmpz_poly_set_ui(series->Q, c * c); arb_hypgeom_infsum(s, t, series, prec, prec); arb_mul_si(s, s, a, prec); arb_mul_ui(t, t, c, prec); arb_div(s, s, t, prec); arb_clear(t); hypgeom_clear(series); } static ulong next_smooth(ulong n) { ulong t, k; for (k = n; ; k++) { t = k; while (t % 2 == 0) t /= 2; while (t % 3 == 0) t /= 3; while (t % 5 == 0) t /= 5; if (t == 1) return k; } } static void arb_log_ui_smooth(arb_t s, ulong n, slong prec) { ulong m, i, j, k; arb_t t; m = n; i = j = k = 0; while (m % 2 == 0) { m /= 2; i++; } while (m % 3 == 0) { m /= 3; j++; } while (m % 5 == 0) { m /= 5; k++; } if (m != 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); arb_init(t); prec += FLINT_CLOG2(prec); atanh_bsplit(s, 31, 14*i + 22*j + 32*k, prec); atanh_bsplit(t, 49, 10*i + 16*j + 24*k, prec); arb_add(s, s, t, prec); atanh_bsplit(t, 161, 6*i + 10*j + 14*k, prec); arb_add(s, s, t, prec); arb_clear(t); } void arb_const_euler_eval(arb_t res, slong prec) { euler_bsplit_1_t sum; arb_t t, u, v, P2, T2, Q2; slong bits, wp, wp2, n, N, M; bits = prec + 10; n = 0.086643397569993163677 * bits + 1; /* log(2) / 8 */ /* round n to have many trailing zeros, speeding up arithmetic, and make it smooth to allow computing the logarithm cheaply */ if (n > 256) { int b = FLINT_BIT_COUNT(n); n = next_smooth((n >> (b-4)) + 1) << (b-4); } else { n = next_smooth(n); } /* As shown in the paper, it is sufficient to take N >= alpha n + 1 where alpha = 3/W(3/e) = 4.970625759544... */ { fmpz_t a; fmpz_init(a); fmpz_set_ui(a, n); fmpz_mul_ui(a, a, 4970626); fmpz_cdiv_q_ui(a, a, 1000000); fmpz_add_ui(a, a, 1); N = fmpz_get_ui(a); fmpz_clear(a); } M = 2 * n; wp = bits + 2 * FLINT_BIT_COUNT(n); wp2 = bits/2 + 2 * FLINT_BIT_COUNT(n); euler_bsplit_1_init(sum, NULL); arb_init(P2); arb_init(T2); arb_init(Q2); arb_init(t); arb_init(u); arb_init(v); /* Compute S0 = V / (Q D), I0 = 1 + T / Q */ euler_bsplit_1(sum, 0, N, n, wp, 0); /* I0 = T / Q */ arb_add(sum->T, sum->T, sum->Q, wp); /* Compute S0 / I0 = V / (D T) */ arb_mul(t, sum->T, sum->D, wp); arb_div(res, sum->V, t, wp); /* Compute K0 (actually I_0(2n) K_0(2n)) = T2 / Q2 */ euler_bsplit_2(P2, Q2, T2, 0, M, n, wp2, 0); /* Compute K0 / I^2 = Q^2 * T2 / (Q2 * T^2) */ arb_set_round(t, sum->Q, wp2); arb_mul(t, t, t, wp2); arb_mul(t, t, T2, wp2); arb_set_round(u, sum->T, wp2); arb_mul(u, u, u, wp2); arb_mul(u, u, Q2, wp2); arb_div(t, t, u, wp2); arb_sub(res, res, t, wp); /* subtract log(n) */ arb_log_ui_smooth(u, n, wp); arb_sub(res, res, u, wp); /* add error bound 24 exp(-8n) */ { mag_t b; mag_init(b); /* exp(-8) < 737690121 * 2^-41 */ mag_set_ui_2exp_si(b, 737690121, -41); mag_pow_ui(b, b, n); mag_mul_ui(b, b, 24); mag_add(arb_radref(res), arb_radref(res), b); mag_clear(b); } arb_clear(P2); arb_clear(T2); arb_clear(Q2); arb_clear(t); arb_clear(u); arb_clear(v); euler_bsplit_1_clear(sum, NULL); } ARB_DEF_CACHED_CONSTANT(arb_const_euler_brent_mcmillan, arb_const_euler_eval) FLINT_DLL extern const mp_limb_t arb_hypgeom_gamma_tab_limbs[]; void arb_const_euler(arb_t res, slong prec) { if (prec < ARB_HYPGEOM_GAMMA_TAB_PREC - 16) { slong exp; mp_size_t n; n = ARB_HYPGEOM_GAMMA_TAB_PREC / FLINT_BITS; /* just reading the table is known to give the correct rounding */ _arf_set_round_mpn(arb_midref(res), &exp, arb_hypgeom_gamma_tab_limbs + n, n, 0, prec, ARF_RND_NEAR); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp); /* 1/2 ulp error */ _fmpz_set_si_small(MAG_EXPREF(arb_radref(res)), exp - prec); MAG_MAN(arb_radref(res)) = MAG_ONE_HALF; } else { arb_const_euler_brent_mcmillan(res, prec); } } flint-3.1.3/src/arb/const_glaisher.c000066400000000000000000000020571461254215100173420ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb_poly.h" void arb_const_glaisher_eval(arb_t y, slong prec) { acb_struct z[2]; acb_t s, a; slong wp; acb_init(z + 0); acb_init(z + 1); acb_init(s); acb_init(a); wp = prec + 20; /* directly evaluating at s = -1 is slightly faster than evaluating at s = 2 */ acb_set_si(s, -1); acb_one(a); _acb_poly_zeta_cpx_series(z, s, a, 0, 2, wp); arb_one(y); arb_div_ui(y, y, 12, wp); arb_sub(y, y, acb_realref(z + 1), wp); arb_exp(y, y, wp); acb_clear(z + 0); acb_clear(z + 1); acb_clear(s); acb_clear(a); } ARB_DEF_CACHED_CONSTANT(arb_const_glaisher, arb_const_glaisher_eval) flint-3.1.3/src/arb/const_khinchin.c000066400000000000000000000046511461254215100173410ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb.h" void arb_const_khinchin_eval_param(arb_t s, ulong N, ulong M, slong prec) { arb_t t, u, h; arb_ptr pows; slong k, n; arb_init(t); arb_init(u); arb_init(h); if (N < 2) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* if (M < 0) flint_abort(); */ pows = _arb_vec_init(N - 2); /* sum of logarithms */ arb_zero(s); for (k = 2; k < N; k++) { arb_set_ui(t, k - 1); arb_div_ui(t, t, k, prec); arb_log(t, t, prec); arb_set_ui(u, k + 1); arb_div_ui(u, u, k, prec); arb_log(u, u, prec); arb_mul(t, t, u, prec); arb_sub(s, s, t, prec); } /* alternating harmonic numbers */ arb_one(h); /* powers */ for (k = 0; k < N - 2; k++) arb_one(pows + k); /* sum of zetas */ for (n = 1; n <= M; n++) { /* zeta(2n,N) / n */ arb_zeta_ui(t, 2 * n, prec); arb_sub_ui(t, t, 1, prec); for (k = 0; k < N - 2; k++) { arb_div_ui(pows + k, pows + k, (k + 2) * (k + 2), prec); arb_sub(t, t, pows + k, prec); } arb_div_ui(t, t, n, prec); arb_mul(t, t, h, prec); arb_add(s, s, t, prec); /* forward h by two */ arb_set_ui(u, 2 * n); arb_mul_ui(u, u, 2 * n + 1, prec); arb_inv(u, u, prec); arb_sub(h, h, u, prec); } /* error bound 1/N^(2M) */ arb_set_ui(t, N); arb_pow_ui(t, t, 2 * M, MAG_BITS); arb_inv(t, t, MAG_BITS); arb_add_error(s, t); arb_log_ui(t, 2, prec); arb_div(s, s, t, prec); arb_exp(s, s, prec); _arb_vec_clear(pows, N - 2); arb_clear(t); arb_clear(u); arb_clear(h); } void arb_const_khinchin_eval(arb_t K, slong prec) { ulong N, M; prec += 10 + 2 * FLINT_BIT_COUNT(prec); /* heuristic */ N = pow(prec, 0.35); M = (prec * 0.69314718055994530942) / (2 * log(N)); arb_const_khinchin_eval_param(K, N, M, prec); } ARB_DEF_CACHED_CONSTANT(arb_const_khinchin, arb_const_khinchin_eval) flint-3.1.3/src/arb/const_log10.c000066400000000000000000000024751461254215100164720ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" static void atanh_bsplit(arb_t s, ulong c, slong a, slong prec) { arb_t t; hypgeom_t series; hypgeom_init(series); arb_init(t); fmpz_poly_set_ui(series->A, 1); fmpz_poly_set_coeff_ui(series->B, 0, 1); fmpz_poly_set_coeff_ui(series->B, 1, 2); fmpz_poly_set_ui(series->P, 1); fmpz_poly_set_ui(series->Q, c * c); arb_hypgeom_infsum(s, t, series, prec, prec); arb_mul_si(s, s, a, prec); arb_mul_ui(t, t, c, prec); arb_div(s, s, t, prec); arb_clear(t); hypgeom_clear(series); } void arb_const_log10_eval(arb_t s, slong prec) { arb_t t; arb_init(t); prec += FLINT_CLOG2(prec); atanh_bsplit(s, 31, 46, prec); atanh_bsplit(t, 49, 34, prec); arb_add(s, s, t, prec); atanh_bsplit(t, 161, 20, prec); arb_add(s, s, t, prec); arb_clear(t); } ARB_DEF_CACHED_CONSTANT(arb_const_log10, arb_const_log10_eval) flint-3.1.3/src/arb/const_log2.c000066400000000000000000000040701461254215100164040ustar00rootroot00000000000000/* Copyright (C) 2013, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" void arb_const_log2_hypgeom_eval(arb_t s, slong prec) { hypgeom_t series; arb_t t; arb_init(t); hypgeom_init(series); fmpz_poly_set_str(series->A, "2 1497 1794"); fmpz_poly_set_str(series->B, "1 1"); fmpz_poly_set_str(series->P, "3 0 -1 2"); fmpz_poly_set_str(series->Q, "3 1080 7776 7776"); prec += FLINT_CLOG2(prec); arb_hypgeom_infsum(s, t, series, prec, prec); arb_mul_ui(t, t, 2160, prec); arb_div(s, s, t, prec); hypgeom_clear(series); arb_clear(t); } /* Note: we ought to share the log(2) cache with the log(p) cache. Note: for log(3) the corresponding formula is fmpz_poly_set_str(series->A, "2 74 88"); fmpz_poly_set_str(series->B, "1 1"); fmpz_poly_set_str(series->P, "3 0 -2 4"); fmpz_poly_set_str(series->Q, "3 135 972 972"); ... arb_mul_2exp_si(s, s, 1); arb_mul_ui(t, t, 135, prec); but currently we do not have a use for this as a standalone constant. */ ARB_DEF_CACHED_CONSTANT(arb_const_log2_hypgeom, arb_const_log2_hypgeom_eval) void arb_const_log2(arb_t res, slong prec) { if (prec < ARB_LOG_TAB2_LIMBS * FLINT_BITS - 16) { slong exp; /* just reading the table is known to give the correct rounding */ _arf_set_round_mpn(arb_midref(res), &exp, arb_log_log2_tab, ARB_LOG_TAB2_LIMBS, 0, prec, ARF_RND_NEAR); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp); /* 1/2 ulp error */ _fmpz_set_si_small(MAG_EXPREF(arb_radref(res)), exp - prec); MAG_MAN(arb_radref(res)) = MAG_ONE_HALF; } else { arb_const_log2_hypgeom(res, prec); } } flint-3.1.3/src/arb/const_log_sqrt2pi.c000066400000000000000000000012031461254215100200010ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void _arb_const_log_sqrt2pi(arb_t t, slong prec) { arb_const_pi(t, prec + 2); arb_mul_2exp_si(t, t, 1); arb_log(t, t, prec); arb_mul_2exp_si(t, t, -1); } ARB_DEF_CACHED_CONSTANT(arb_const_log_sqrt2pi, _arb_const_log_sqrt2pi) flint-3.1.3/src/arb/const_pi.c000066400000000000000000000034001461254215100161450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" void arb_const_pi_chudnovsky_eval(arb_t s, slong prec) { hypgeom_t series; arb_t t, u; arb_init(t); arb_init(u); hypgeom_init(series); fmpz_poly_set_str(series->A, "2 13591409 545140134"); fmpz_poly_set_str(series->B, "1 1"); fmpz_poly_set_str(series->P, "4 5 -46 108 -72"); fmpz_poly_set_str(series->Q, "4 0 0 0 10939058860032000"); prec += FLINT_CLOG2(prec) + 5; arb_hypgeom_infsum(s, t, series, prec, prec); arb_rsqrt_ui(u, 640320, prec); arb_mul(s, s, u, prec); arb_mul_ui(t, t, 640320 / 12, prec); arb_div(s, t, s, prec); hypgeom_clear(series); arb_clear(t); arb_clear(u); } ARB_DEF_CACHED_CONSTANT(arb_const_pi_chudnovsky, arb_const_pi_chudnovsky_eval) void arb_const_pi(arb_t res, slong prec) { if (prec < ARB_PI4_TAB_LIMBS * FLINT_BITS - 16) { slong exp; /* just reading the table is known to give the correct rounding */ _arf_set_round_mpn(arb_midref(res), &exp, arb_pi4_tab, ARB_PI4_TAB_LIMBS, 0, prec, ARF_RND_NEAR); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), 2 + exp); /* 1/2 ulp error */ _fmpz_set_si_small(MAG_EXPREF(arb_radref(res)), 2 + exp - prec); MAG_MAN(arb_radref(res)) = MAG_ONE_HALF; } else { arb_const_pi_chudnovsky(res, prec); } } flint-3.1.3/src/arb/const_reciprocal_fibonacci.c000066400000000000000000000076121461254215100216660ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "gr_special.h" #include "thread_support.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif typedef struct { arb_t P; arb_t R; arb_t Q; slong a; slong b; } bsplit_struct; typedef bsplit_struct bsplit_t[1]; typedef struct { slong N; slong prec; } bsplit_args_struct; static void bsplit_init(bsplit_t x, void * args) { arb_init(x->P); arb_init(x->R); arb_init(x->Q); x->a = x->b = 0; } static void bsplit_clear(bsplit_t x, void * args) { arb_clear(x->P); arb_clear(x->R); arb_clear(x->Q); } static void bsplit_basecase(bsplit_t res, slong n, slong n1, void * args) { fmpz_t f1, f2, f1f2, f22, f4, t; FLINT_ASSERT(n1 == n + 1); fmpz_init(f1); fmpz_init(f2); fmpz_init(f1f2); fmpz_init(f22); fmpz_init(f4); fmpz_init(t); /* We compute the Fibonacci numbers needed in each basecase node from scratch. They could be recycled from each node to the next, but the speedup would be marginal. */ /* f1, f2 = fib(2*n), fib(2*n+1) */ { fmpz nn = 2 * n + 1; gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); GR_MUST_SUCCEED(gr_generic_fib2_fmpz(f2, f1, &nn, ctx)); } fmpz_mul(f1f2, f1, f2); fmpz_mul(f22, f2, f2); /* f4 = fib(4n+3) */ fmpz_add(f4, f1f2, f22); fmpz_mul_2exp(f4, f4, 1); fmpz_addmul(f4, f1, f1); /* P = 2*f1 + f2 */ fmpz_mul_2exp(t, f1, 1); fmpz_add(t, t, f2); arb_set_fmpz(res->P, t); /* Q = (f1f2 + f22) * P */ fmpz_add(f1f2, f1f2, f22); fmpz_mul(t, t, f1f2); arb_set_fmpz(res->Q, t); /* R = (-1)^((n & 3)>>1) * (f4 + (-1)^n * (f1 + f2)) */ fmpz_add(t, f1, f2); if (n & 1) fmpz_sub(t, f4, t); else fmpz_add(t, f4, t); if ((n & 3) >> 1) fmpz_neg(t, t); arb_set_fmpz(res->R, t); res->a = n; res->b = n1; fmpz_clear(f1); fmpz_clear(f2); fmpz_clear(f1f2); fmpz_clear(f22); fmpz_clear(f4); fmpz_clear(t); } static void bsplit_merge(bsplit_t res, bsplit_t X1, bsplit_t X2, bsplit_args_struct * args) { slong prec = args->prec; slong a = X1->a; slong b = X2->b; FLINT_ASSERT(res == X1); /* P1, R1, Q1 = bsplit(a, m) P2, R2, Q2 = bsplit(m, b) Q2 *= P1; P1 *= P2; R1 *= Q2; R2 *= Q1; R1 += R2; Q1 *= Q2 */ arb_mul(X2->Q, X2->Q, X1->P, prec); if (b != args->N) /* this product is only needed internally */ arb_mul(X1->P, X1->P, X2->P, prec); else arb_one(X1->P); arb_mul(X1->R, X1->R, X2->Q, prec); arb_mul(X2->R, X2->R, X1->Q, prec); arb_add(X1->R, X1->R, X2->R, prec); arb_mul(X1->Q, X1->Q, X2->Q, prec); X1->a = a; /* actually a no-op because of aliasing */ X1->b = b; } void arb_const_reciprocal_fibonacci(arb_t res, slong prec) { slong N, max_threads, wp; bsplit_t s; bsplit_args_struct args; max_threads = (prec < 30000) ? 1 : 0; args.prec = wp = prec + 10 + FLINT_BIT_COUNT(prec); /* Truncation error < (1/phi)^(N^2) < 2^(-wp) */ args.N = N = (1.200175024907849 + 1e-12) * sqrt(wp) + 2; bsplit_init(s, NULL); flint_parallel_binary_splitting(s, (bsplit_basecase_func_t) bsplit_basecase, (bsplit_merge_func_t) bsplit_merge, sizeof(bsplit_struct), (bsplit_init_func_t) bsplit_init, (bsplit_clear_func_t) bsplit_clear, &args, 0, N, 1, max_threads, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); arb_div(res, s->R, s->Q, prec); arb_add_error_2exp_si(res, -wp); bsplit_clear(s, NULL); } flint-3.1.3/src/arb/const_sqrt_pi.c000066400000000000000000000010731461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void _arb_const_sqrt_pi(arb_t t, slong prec) { arb_const_pi(t, prec + 2); arb_sqrt(t, t, prec); } ARB_DEF_CACHED_CONSTANT(arb_const_sqrt_pi, _arb_const_sqrt_pi) flint-3.1.3/src/arb/contains.c000066400000000000000000000201201461254215100161430ustar00rootroot00000000000000/* Copyright (C) 2012-2016, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb.h" int arb_contains(const arb_t x, const arb_t y) { arf_t t; arf_t u; arf_t xr, yr; arf_struct tmp[4]; int left_ok, right_ok; if (arb_is_exact(y)) return arb_contains_arf(x, arb_midref(y)); if (arf_is_nan(arb_midref(y))) return arf_is_nan(arb_midref(x)); arf_init(t); arf_init(u); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); /* fast check */ arf_sub(t, arb_midref(x), xr, MAG_BITS, ARF_RND_CEIL); arf_sub(u, arb_midref(y), yr, MAG_BITS, ARF_RND_FLOOR); left_ok = arf_cmp(t, u) <= 0; /* exact check */ if (!left_ok) { arf_init_set_shallow(tmp + 0, arb_midref(x)); arf_init_neg_mag_shallow(tmp + 1, arb_radref(x)); arf_init_neg_shallow(tmp + 2, arb_midref(y)); arf_init_set_mag_shallow(tmp + 3, arb_radref(y)); arf_sum(t, tmp, 4, MAG_BITS, ARF_RND_DOWN); left_ok = arf_sgn(t) <= 0; } /* fast check */ arf_add(t, arb_midref(x), xr, MAG_BITS, ARF_RND_FLOOR); arf_add(u, arb_midref(y), yr, MAG_BITS, ARF_RND_CEIL); right_ok = (arf_cmp(t, u) >= 0); /* exact check */ if (!right_ok) { arf_init_set_shallow(tmp + 0, arb_midref(x)); arf_init_set_mag_shallow(tmp + 1, arb_radref(x)); arf_init_neg_shallow(tmp + 2, arb_midref(y)); arf_init_neg_mag_shallow(tmp + 3, arb_radref(y)); arf_sum(t, tmp, 4, MAG_BITS, ARF_RND_DOWN); right_ok = arf_sgn(t) >= 0; } arf_clear(t); arf_clear(u); return left_ok && right_ok; } /* decide |t| <= xr; t = xm - y */ int arb_contains_arf(const arb_t x, const arf_t y) { if (!arb_is_finite(x)) { if (arf_is_nan(arb_midref(x))) return 1; if (arf_is_nan(y)) return 0; if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) { return arf_equal(arb_midref(x), y); } return 1; } else if (!arf_is_finite(y)) { return 0; } else if (arb_is_exact(x)) { return arf_equal(arb_midref(x), y); } else { arf_t t; arf_struct tmp[3]; int result, inexact; arf_init(t); inexact = arf_sub(t, arb_midref(x), y, 2 * MAG_BITS, ARF_RND_DOWN); if (!inexact) { result = arf_cmpabs_mag(t, arb_radref(x)) <= 0; } else { mag_t a; mag_init(a); arf_get_mag_lower(a, t); if (mag_cmp(a, arb_radref(x)) > 0) { result = 0; } else { arf_get_mag(a, t); if (mag_cmp(a, arb_radref(x)) < 0) { result = 1; } else { /* y >= xm - xr <=> 0 >= xm - xr - y */ arf_init_set_shallow(tmp + 0, arb_midref(x)); arf_init_neg_mag_shallow(tmp + 1, arb_radref(x)); arf_init_neg_shallow(tmp + 2, y); arf_sum(t, tmp, 3, MAG_BITS, ARF_RND_DOWN); result = (arf_sgn(t) <= 0); if (result) { /* y <= xm + xr <=> 0 <= xm + xr - y */ arf_init_set_mag_shallow(tmp + 1, arb_radref(x)); arf_sum(t, tmp, 3, MAG_BITS, ARF_RND_DOWN); result = (arf_sgn(t) >= 0); } } } mag_clear(a); } arf_clear(t); return result; } } int arb_contains_fmpq(const arb_t x, const fmpq_t y) { if (fmpz_is_one(fmpq_denref(y)) || !arb_is_finite(x)) { return arb_contains_fmpz(x, fmpq_numref(y)); } else { arf_t t, xm, xr, ym; arf_struct tmp[3]; int result; arf_init(t); arf_init(xm); arf_init(xr); arf_init(ym); /* To compare x with p/q, compare qx with p. */ arf_mul_fmpz(xm, arb_midref(x), fmpq_denref(y), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_mag(xr, arb_radref(x)); arf_mul_fmpz(xr, xr, fmpq_denref(y), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_fmpz(ym, fmpq_numref(y)); /* y >= xm - xr <=> 0 >= xm - xr - y */ arf_init_set_shallow(tmp + 0, xm); arf_init_neg_shallow(tmp + 1, xr); arf_init_neg_shallow(tmp + 2, ym); arf_sum(t, tmp, 3, 30, ARF_RND_DOWN); result = (arf_sgn(t) <= 0); if (result) { /* y <= xm + xr <=> 0 <= xm + xr - y */ arf_init_set_shallow(tmp + 1, xr); arf_sum(t, tmp, 3, 30, ARF_RND_DOWN); result = (arf_sgn(t) >= 0); } arf_clear(t); arf_clear(xm); arf_clear(xr); arf_clear(ym); return result; } } int arb_contains_fmpz(const arb_t x, const fmpz_t y) { int ans; arf_t t; arf_init(t); arf_set_fmpz(t, y); ans = arb_contains_arf(x, t); arf_clear(t); return ans; } int arb_contains_int(const arb_t x) { if (arf_is_int(arb_midref(x))) { return 1; } else if (!arb_is_finite(x)) { return arb_contains_zero(x); } else if (arb_is_exact(x)) { return 0; } else if (mag_cmp_2exp_si(arb_radref(x), -1) >= 0) /* radius >= 1/2 */ { return 1; } else { /* radius is < 1/2, so it's enough to test the two integers bracketing the midpoint */ arf_t t; int res; arf_init(t); arf_floor(t, arb_midref(x)); res = arb_contains_arf(x, t); if (!res) { arf_ceil(t, arb_midref(x)); res = arb_contains_arf(x, t); } arf_clear(t); return res; } } int arb_contains_interior(const arb_t x, const arb_t y) { arf_t t; arf_t u; arf_t xr, yr; arf_struct tmp[4]; int left_ok, right_ok; if (arf_is_nan(arb_midref(x)) || arb_is_exact(x) || !arb_is_finite(y)) return 0; arf_init(t); arf_init(u); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); /* fast check */ arf_sub(t, arb_midref(x), xr, MAG_BITS, ARF_RND_CEIL); arf_sub(u, arb_midref(y), yr, MAG_BITS, ARF_RND_FLOOR); left_ok = arf_cmp(t, u) < 0; /* exact check */ if (!left_ok) { arf_init_set_shallow(tmp + 0, arb_midref(x)); arf_init_neg_mag_shallow(tmp + 1, arb_radref(x)); arf_init_neg_shallow(tmp + 2, arb_midref(y)); arf_init_set_mag_shallow(tmp + 3, arb_radref(y)); arf_sum(t, tmp, 4, MAG_BITS, ARF_RND_DOWN); left_ok = arf_sgn(t) < 0; } /* fast check */ arf_add(t, arb_midref(x), xr, MAG_BITS, ARF_RND_FLOOR); arf_add(u, arb_midref(y), yr, MAG_BITS, ARF_RND_CEIL); right_ok = (arf_cmp(t, u) > 0); /* exact check */ if (!right_ok) { arf_init_set_shallow(tmp + 0, arb_midref(x)); arf_init_set_mag_shallow(tmp + 1, arb_radref(x)); arf_init_neg_shallow(tmp + 2, arb_midref(y)); arf_init_neg_mag_shallow(tmp + 3, arb_radref(y)); arf_sum(t, tmp, 4, MAG_BITS, ARF_RND_DOWN); right_ok = arf_sgn(t) > 0; } arf_clear(t); arf_clear(u); return left_ok && right_ok; } int arb_contains_mpfr(const arb_t x, const mpfr_t y) { int ans; arf_t t; arf_init(t); arf_set_mpfr(t, y); ans = arb_contains_arf(x, t); arf_clear(t); return ans; } int arb_contains_si(const arb_t x, slong y) { int ans; arf_t t; arf_init(t); arf_set_si(t, y); ans = arb_contains_arf(x, t); arf_clear(t); return ans; } flint-3.1.3/src/arb/cot.c000066400000000000000000000010661461254215100151220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_cot(arb_t y, const arb_t x, slong prec) { arb_t u; arb_init(u); arb_sin_cos(y, u, x, prec + 4); arb_div(y, u, y, prec); arb_clear(u); } flint-3.1.3/src/arb/cot_pi.c000066400000000000000000000015021461254215100156050ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_cot_pi(arb_t y, const arb_t x, slong prec) { if (!arb_is_finite(x)) { arb_indeterminate(y); } else if (arb_is_int_2exp_si(x, -1)) { if (arb_is_int(x)) arb_indeterminate(y); else arb_zero(y); } else { arb_t u; arb_init(u); arb_sin_cos_pi(y, u, x, prec + 4); arb_div(y, u, y, prec); arb_clear(u); } } flint-3.1.3/src/arb/coth.c000066400000000000000000000022241461254215100152670ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_coth(arb_t y, const arb_t x, slong prec) { arb_t t, u; int sign = arf_sgn(arb_midref(x)) < 0; arb_init(t); arb_init(u); arb_mul_2exp_si(t, x, 1); if (!sign) arb_neg(t, t); if (arf_cmpabs_2exp_si(arb_midref(x), 1) > 0) { /* coth(x) = 1 + 2 exp(-2x) / (1 - exp(-2x)) */ arb_exp(t, t, prec + 4); arb_sub_ui(u, t, 1, prec + 4); arb_div(y, t, u, prec + 4); arb_mul_2exp_si(y, y, 1); arb_sub_ui(y, y, 1, prec); } else { /* coth(x) = (exp(2x) + 1) / (exp(2x) - 1) */ arb_expm1(t, t, prec + 4); arb_add_ui(y, t, 2, prec + 4); arb_div(y, y, t, prec); } if (!sign) arb_neg(y, y); arb_clear(t); arb_clear(u); } flint-3.1.3/src/arb/csc.c000066400000000000000000000010041461254215100150750ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_csc(arb_t res, const arb_t x, slong prec) { arb_sin(res, x, prec + 4); arb_inv(res, res, prec); } flint-3.1.3/src/arb/csc_pi.c000066400000000000000000000010611461254215100155700ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson Copyright (C) 2017 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_csc_pi(arb_t res, const arb_t x, slong prec) { arb_sin_pi(res, x, prec + 4); arb_inv(res, res, prec); } flint-3.1.3/src/arb/csch.c000066400000000000000000000024141461254215100152530ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_csch(arb_t res, const arb_t x, slong prec) { if (arb_contains_zero(x) || !arb_is_finite(x)) { arb_indeterminate(res); } else if (arf_cmpabs_2exp_si(arb_midref(x), 0) > 0) { arb_t t; arb_init(t); if (arf_sgn(arb_midref(x)) > 0) { arb_neg(t, x); arb_exp(t, t, prec + 4); arb_mul(res, t, t, prec + 4); arb_sub_ui(res, res, 1, prec + 4); arb_div(res, t, res, prec); arb_neg(res, res); } else { arb_exp(t, x, prec + 4); arb_mul(res, t, t, prec + 4); arb_sub_ui(res, res, 1, prec + 4); arb_div(res, t, res, prec); } arb_mul_2exp_si(res, res, 1); arb_clear(t); } else { arb_sinh(res, x, prec + 4); arb_inv(res, res, prec); } } flint-3.1.3/src/arb/digamma.c000066400000000000000000000050271461254215100157350ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arith.h" #include "arb.h" void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec); void arb_gamma_stirling_eval(arb_t s, const arb_t z, slong nterms, int digamma, slong prec); void arb_digamma(arb_t y, const arb_t x, slong prec) { int reflect; slong r, n, wp; arb_t t, u, v; if (arb_is_exact(x)) { const arf_struct * mid = arb_midref(x); if (arf_is_special(mid)) { arb_indeterminate(y); return; } else if (arf_is_int(mid)) { if (arf_sgn(mid) < 0) { arb_indeterminate(y); return; } else if (arf_cmpabs_ui(mid, 30 + prec / 2) < 0) { fmpq_t h; arb_init(t); fmpq_init(h); /* should change to fmpq_harmonic_ui when flint upgrades */ arith_harmonic_number(h, arf_get_si(mid, ARF_RND_DOWN) - 1); arb_set_fmpq(y, h, prec + 2); arb_const_euler(t, prec + 2); arb_sub(y, y, t, prec); arb_clear(t); fmpq_clear(h); return; } } } wp = prec + FLINT_BIT_COUNT(prec); arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 1, wp); arb_init(t); arb_init(u); arb_init(v); /* psi(x) = psi((1-x)+r) - h(1-x,r) - pi*cot(pi*x) */ if (reflect) { arb_sub_ui(t, x, 1, wp); arb_neg(t, t); arb_cot_pi(v, x, wp); arb_const_pi(u, wp); arb_mul(v, v, u, wp); arb_rising2_ui(y, u, t, r, wp); arb_div(u, u, y, wp); arb_add(v, v, u, wp); arb_add_ui(t, t, r, wp); arb_gamma_stirling_eval(u, t, n, 1, wp); arb_sub(y, u, v, wp); } else { arb_add_ui(t, x, r, wp); arb_gamma_stirling_eval(u, t, n, 1, wp); arb_rising2_ui(y, t, x, r, wp); arb_div(t, t, y, wp); arb_sub(y, u, t, prec); } arb_clear(t); arb_clear(u); arb_clear(v); } flint-3.1.3/src/arb/div.c000066400000000000000000000346731461254215100151310ustar00rootroot00000000000000/* Copyright (C) 2014, 2018, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* We do Newton iteration in floating-point arithmetic with some guard bits. With GUARD_BITS = 32 the result is certainly accurate to more than GUARD_BITS / 2 extra bits. With a detailed error analysis this could be set much more conservatively (see e.g. MPFR's algorithms documentation), but currently we only care about extremely high precision and we always start from an extremely high precision initial value, so fine-tuning the precision management isn't going to help performance a whole lot. */ #define GUARD_BITS 32 #define INV_NEWTON_CUTOFF 24000 #define DIV_NEWTON_CUTOFF 70000 #ifdef FLINT_HAVE_FFT_SMALL #define WANT_NEWTON(prec, xbits, ybits) (prec) >= INV_NEWTON_CUTOFF && (ybits) > (prec) * 0.5 && ((xbits) < (prec) * 0.01 || (prec) >= DIV_NEWTON_CUTOFF) #else #define WANT_NEWTON(prec, xbits, ybits) 0 #endif void _arf_inv_newton(arf_t res, const arf_t x, slong prec) { slong wp = prec + GUARD_BITS; slong hp = prec / 2 + GUARD_BITS; if (prec < INV_NEWTON_CUTOFF) { arf_set_round(res, x, wp, ARF_RND_DOWN); arf_ui_div(res, 1, res, wp, ARF_RND_DOWN); } else { arf_t r, t; arf_init(r); arf_init(t); _arf_inv_newton(r, x, hp); /* r - r*(x*r - 1) */ if (arf_bits(x) <= wp) { arf_mul(t, x, r, wp, ARF_RND_DOWN); } else { arf_set_round(t, x, wp, ARF_RND_DOWN); arf_mul(t, t, r, wp, ARF_RND_DOWN); } arf_sub_ui(t, t, 1, hp, ARF_RND_DOWN); arf_mul(t, t, r, hp, ARF_RND_DOWN); arf_sub(res, r, t, wp, ARF_RND_DOWN); arf_clear(r); arf_clear(t); } } /* Karp-Markstein */ void _arf_div_newton(arf_t res, const arf_t x, const arf_t y, slong prec) { arf_t xn, yn, t; slong wp = prec + GUARD_BITS; slong hp = prec / 2 + GUARD_BITS; arf_init(xn); arf_init(yn); arf_init(t); _arf_inv_newton(xn, y, hp); arf_set_round(t, x, hp, ARF_RND_DOWN); arf_mul(yn, xn, t, hp, ARF_RND_DOWN); arf_mul(t, y, yn, wp, ARF_RND_DOWN); arf_sub(t, x, t, hp, ARF_RND_DOWN); arf_mul(t, t, xn, hp, ARF_RND_DOWN); arf_add(res, yn, t, wp, ARF_RND_DOWN); arf_clear(xn); arf_clear(yn); arf_clear(t); } void arb_div_newton(arb_t res, const arb_t x, const arb_t y, slong prec) { mag_t zr, xm, ym, yl, yw; if (arf_is_special(arb_midref(x)) || arf_is_special(arb_midref(y))) { arb_indeterminate(res); return; } mag_init_set_arf(xm, arb_midref(x)); mag_init_set_arf(ym, arb_midref(y)); mag_init(zr); mag_init(yl); mag_init(yw); /* (|x|*yrad + |y|*xrad)/(|y|*(|y|-yrad)) */ mag_mul(zr, xm, arb_radref(y)); mag_addmul(zr, ym, arb_radref(x)); arb_get_mag_lower(yw, y); arf_get_mag_lower(yl, arb_midref(y)); mag_mul_lower(yl, yl, yw); mag_div(zr, zr, yl); _arf_div_newton(arb_midref(res), arb_midref(x), arb_midref(y), prec); arf_mag_add_ulp(arb_radref(res), zr, arb_midref(res), prec + GUARD_BITS / 2); arb_set_round(res, res, prec); mag_clear(xm); mag_clear(ym); mag_clear(zr); mag_clear(yl); mag_clear(yw); } void arb_div_arf_newton(arb_t res, const arb_t x, const arf_t y, slong prec) { mag_t zr, ym; if (arf_is_special(arb_midref(x)) || arf_is_special(y)) { arb_indeterminate(res); return; } mag_init(ym); mag_init(zr); arf_get_mag_lower(ym, y); mag_div(zr, arb_radref(x), ym); _arf_div_newton(arb_midref(res), arb_midref(x), y, prec); arf_mag_add_ulp(arb_radref(res), zr, arb_midref(res), prec + GUARD_BITS / 2); arb_set_round(res, res, prec); mag_clear(ym); mag_clear(zr); } void arb_div_arf(arb_t z, const arb_t x, const arf_t y, slong prec) { mag_t zr, ym; int inexact; if (arf_is_special(y) || !arb_is_finite(x)) { if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arf_is_finite(y) && !arf_is_zero(y)) { /* inf / finite nonzero = inf */ arf_div(arb_midref(z), arb_midref(x), y, prec, ARF_RND_DOWN); mag_zero(arb_radref(z)); } else if (arb_is_finite(x) && arf_is_inf(y)) { /* finite / inf = 0 */ arb_zero(z); } else if (!arf_is_nan(arb_midref(x)) && mag_is_inf(arb_radref(x)) && arf_is_finite(y) && !arf_is_zero(y)) { /* [+/- inf] / finite nonzero = [+/- inf] */ arb_zero_pm_inf(z); } else { arb_indeterminate(z); } } else if (mag_is_zero(arb_radref(x))) { inexact = arf_div(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); else mag_zero(arb_radref(z)); } else if (WANT_NEWTON(prec, arb_bits(x), arf_bits(y))) { arb_div_arf_newton(z, x, y, prec); } else { mag_init(ym); mag_init(zr); arf_get_mag_lower(ym, y); mag_div(zr, arb_radref(x), ym); inexact = arf_div(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec); else mag_swap(arb_radref(z), zr); mag_clear(ym); mag_clear(zr); } } static void arb_div_wide(arb_t z, const arb_t x, const arb_t y, slong prec) { mag_t a, b, t, u; mag_init(t); arb_get_mag_lower(t, y); if (mag_is_zero(t)) { arb_indeterminate(z); } else if (arf_is_zero(arb_midref(x))) { mag_div(arb_radref(z), arb_radref(x), t); arf_zero(arb_midref(z)); } else { if (arf_cmpabs_mag(arb_midref(x), arb_radref(x)) >= 0) { /* [a,b] / [t,u] = [a/u, b/t] [a,b] / -[t,u] = -[a/u, b/t] -[a,b] / [t,u] = -[a/u, b/t] -[a,b] / -[t,u] = [a/u, b/t] */ mag_init(a); mag_init(b); mag_init(u); arb_get_mag_lower(a, x); arb_get_mag(b, x); arb_get_mag(u, y); mag_div_lower(a, a, u); mag_div(b, b, t); if ((arf_sgn(arb_midref(x)) < 0) ^ (arf_sgn(arb_midref(y)) < 0)) { arb_set_interval_mag(z, a, b, prec); arb_neg(z, z); } else { arb_set_interval_mag(z, a, b, prec); } mag_clear(a); mag_clear(b); mag_clear(u); } else { /* [-a,b] / [t,u] = [-a/t, b/t] [-a,b] / -[t,u] = [-b/t, a/t] */ mag_init(a); mag_init(b); arb_get_mag(b, x); arf_get_mag_lower(a, arb_midref(x)); mag_sub(a, arb_radref(x), a); if ((arf_sgn(arb_midref(x)) < 0) ^ (arf_sgn(arb_midref(y)) < 0)) mag_swap(a, b); mag_div(a, a, t); mag_div(b, b, t); arb_set_interval_neg_pos_mag(z, a, b, prec); mag_clear(a); mag_clear(b); } } mag_clear(t); } void arb_div(arb_t z, const arb_t x, const arb_t y, slong prec) { int inexact; slong acc, xacc, yacc; if (mag_is_zero(arb_radref(y))) { arb_div_arf(z, x, arb_midref(y), prec); } else if (arf_is_zero(arb_midref(y))) /* anything / 0 = nan */ { arb_indeterminate(z); } else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y)) /* fast case */ { /* both finite, both midpoint and radius of y not special */ yacc = MAG_EXP(arb_midref(y)) - ARF_EXP(arb_radref(y)); xacc = arb_rel_accuracy_bits(x); acc = FLINT_MIN(xacc, yacc); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); if (acc <= 20) { arb_div_wide(z, x, y, prec); } else if (WANT_NEWTON(prec, arb_bits(x), arb_bits(y))) { arb_div_newton(z, x, y, prec); } else { mag_t t, u, v; mag_init(t); /* no need to free */ mag_init(u); mag_init(v); /* (x*yrad + y*xrad)/(y*(y-yrad)) <= (1+eps) (x*yrad + y*xrad)/y^2 <= (1+eps) (x*yrad/y^2 + y*xrad/y^2) <= (1+eps) ((x/y)*yrad/y + xrad/y) <= (1+eps) ((x/y)*yrad + xrad)/y */ /* t = y */ arf_get_mag_lower(t, arb_midref(y)); inexact = arf_div(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); /* u = x/y */ arf_get_mag(u, arb_midref(z)); /* v = (x/y)*yrad + xrad */ MAG_MAN(v) = MAG_MAN(arb_radref(x)); MAG_EXP(v) = MAG_EXP(arb_radref(x)); mag_fast_addmul(v, arb_radref(y), u); /* v = v / y */ mag_div(arb_radref(z), v, t); /* correct for errors */ MAG_MAN(t) = MAG_ONE_HALF + (MAG_ONE_HALF >> 16); MAG_EXP(t) = 1; mag_fast_mul(arb_radref(z), arb_radref(z), t); if (inexact) arf_mag_fast_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } } else if (!arb_is_finite(y)) { /* finite / inf = 0 */ if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_finite(x)) arb_zero(z); else arb_indeterminate(z); } else if (!arb_is_finite(x)) { if (arb_contains_zero(y) || arf_is_nan(arb_midref(x))) { arb_indeterminate(z); } else { /* +/- inf / finite nonzero = +/- inf */ if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) { arf_div(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARF_RND_DOWN); mag_zero(arb_radref(z)); } else if (!arf_is_nan(arb_midref(x)) && mag_is_inf(arb_radref(x))) { arb_zero_pm_inf(z); } else { arb_indeterminate(z); } } } else { yacc = arb_rel_accuracy_bits(y); xacc = arb_rel_accuracy_bits(x); acc = FLINT_MIN(xacc, yacc); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); if (acc <= 20) { arb_div_wide(z, x, y, prec); } else { mag_t zr, xm, ym, yl, yw; mag_init_set_arf(xm, arb_midref(x)); mag_init_set_arf(ym, arb_midref(y)); mag_init(zr); mag_init(yl); mag_init(yw); /* (|x|*yrad + |y|*xrad)/(|y|*(|y|-yrad)) */ mag_mul(zr, xm, arb_radref(y)); mag_addmul(zr, ym, arb_radref(x)); arb_get_mag_lower(yw, y); arf_get_mag_lower(yl, arb_midref(y)); mag_mul_lower(yl, yl, yw); mag_div(zr, zr, yl); inexact = arf_div(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec); else mag_swap(arb_radref(z), zr); mag_clear(xm); mag_clear(ym); mag_clear(zr); mag_clear(yl); mag_clear(yw); } } } void arb_div_si(arb_t z, const arb_t x, slong y, slong prec) { arf_t t; arf_init_set_si(t, y); /* no need to free */ arb_div_arf(z, x, t, prec); } void arb_div_ui(arb_t z, const arb_t x, ulong y, slong prec) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ arb_div_arf(z, x, t, prec); } void arb_div_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) { arf_t t; if (!COEFF_IS_MPZ(*y)) { arf_init_set_si(t, *y); /* no need to free */ arb_div_arf(z, x, t, prec); } else { arf_init(t); arf_set_fmpz(t, y); arb_div_arf(z, x, t, prec); arf_clear(t); } } void arb_fmpz_div_fmpz(arb_t z, const fmpz_t x, const fmpz_t y, slong prec) { if (WANT_NEWTON(prec, fmpz_bits(x), fmpz_bits(y))) { arb_t t; arb_init(t); arb_set_round_fmpz(t, y, prec + 10); arb_set_round_fmpz(z, x, prec + 10); arb_div_newton(z, z, t, prec); arb_clear(t); } else { int inexact = arf_fmpz_div_fmpz(arb_midref(z), x, y, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); else mag_zero(arb_radref(z)); } } void arb_ui_div(arb_t z, ulong x, const arb_t y, slong prec) { arb_t t; arb_init(t); arb_set_ui(t, x); arb_div(z, t, y, prec); arb_clear(t); } /* important: must be a valid divexact */ void _arb_fmpz_divapprox_newton(fmpz_t res, const fmpz_t x, const fmpz_t y, slong exp) { slong xb, yb, zb, prec; arf_t t, u; xb = fmpz_bits(x); yb = fmpz_bits(y); zb = xb - yb + exp; prec = FLINT_MAX(zb, 0) + 16; arf_init(t); arf_init(u); arf_set_round_fmpz(t, x, prec, ARF_RND_NEAR); arf_mul_2exp_si(t, t, exp); arf_set_round_fmpz(u, y, prec, ARF_RND_NEAR); _arf_div_newton(t, t, u, prec); arf_get_fmpz(res, t, ARF_RND_NEAR); arf_clear(t); arf_clear(u); } void arb_fmpz_divapprox(fmpz_t res, const fmpz_t x, const fmpz_t y) { #ifdef FLINT_HAVE_FFT_SMALL if (!COEFF_IS_MPZ(*x) || !COEFF_IS_MPZ(*y)) { fmpz_tdiv_q(res, x, y); } else { slong xb, yb; xb = mpz_size(COEFF_TO_PTR(*x)); yb = mpz_size(COEFF_TO_PTR(*y)); xb *= FLINT_BITS; yb *= FLINT_BITS; if (xb - yb >= DIV_NEWTON_CUTOFF && yb >= DIV_NEWTON_CUTOFF) { _arb_fmpz_divapprox_newton(res, x, y, 0); } else { fmpz_tdiv_q(res, x, y); } } #else fmpz_tdiv_q(res, x, y); #endif } flint-3.1.3/src/arb/div_2expm1_ui.c000066400000000000000000000027571461254215100170200ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_div_2expm1_ui(arb_t y, const arb_t x, ulong n, slong prec) { if (n < FLINT_BITS) { arb_div_ui(y, x, (UWORD(1) << n) - 1, prec); } else if (n < 1024 + prec / 32 || n > WORD_MAX / 4) { arb_t t; fmpz_t e; arb_init(t); fmpz_init_set_ui(e, n); arb_one(t); arb_mul_2exp_fmpz(t, t, e); arb_sub_ui(t, t, 1, prec); arb_div(y, x, t, prec); arb_clear(t); fmpz_clear(e); } else { arb_t s, t; slong i, b; arb_init(s); arb_init(t); /* x / (2^n - 1) = sum_{k>=1} x * 2^(-k*n)*/ arb_mul_2exp_si(s, x, -n); arb_set(t, s); b = 1; for (i = 2; i <= prec / n + 1; i++) { arb_mul_2exp_si(t, t, -n); arb_add(s, s, t, prec); b = i; } /* error bound: sum_{k>b} x * 2^(-k*n) <= x * 2^(-b*n - (n-1)) */ arb_mul_2exp_si(t, x, -b*n - (n-1)); arb_abs(t, t); arb_add_error(s, t); arb_set(y, s); arb_clear(s); arb_clear(t); } } flint-3.1.3/src/arb/dot.c000066400000000000000000000672541461254215100151360ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" /* We need uint64_t instead of mp_limb_t on 32-bit systems for safe summation of 30-bit error bounds. */ #include void mpfr_mulhigh_n(mp_ptr rp, mp_srcptr np, mp_srcptr mp, mp_size_t n); void mpfr_sqrhigh_n(mp_ptr rp, mp_srcptr np, mp_size_t n); /* Add ((a * b) / 2^MAG_BITS) * 2^exp into srad*2^srad_exp. Assumes that srad_exp >= exp and that overflow cannot occur. */ #define RAD_ADDMUL(srad, srad_exp, a, b, exp) \ do { \ uint64_t __a, __b; \ slong __shift; \ __a = (a); \ __b = (b); \ __shift = (srad_exp) - (exp); \ if (__shift < MAG_BITS) \ (srad) += (((__a) * (__b)) >> (MAG_BITS + __shift)) + 1; \ else \ (srad) += 1; \ } while (0) /* mag_set_ui_2exp_si but assumes no promotion can occur. Do we need this? */ void mag_set_ui_2exp_small(mag_t z, ulong x, slong e) { _fmpz_demote(MAG_EXPREF(z)); if (x == 0) { MAG_EXP(z) = 0; MAG_MAN(z) = 0; } else { slong bits; mp_limb_t overflow; bits = flint_clz(x); bits = FLINT_BITS - bits; if (bits <= MAG_BITS) { x = x << (MAG_BITS - bits); } else { x = (x >> (bits - MAG_BITS)) + 1; overflow = x >> MAG_BITS; bits += overflow; x >>= overflow; } MAG_EXP(z) = bits + e; MAG_MAN(z) = x; } } /* Sets rad to (Aerr 2^Aexp + Berr 2^Bexp + Cerr 2^Cexp) 2^(-MAG_BITS). Assumes that overflow cannot occur. */ static void add_errors(mag_t rad, uint64_t Aerr, slong Aexp, uint64_t Berr, slong Bexp, uint64_t Cerr, slong Cexp) { slong shift; if (Aerr && Berr) { if (Aexp >= Bexp) { shift = Aexp - Bexp; if (shift < 64) Aerr = Aerr + (Berr >> shift) + 1; else Aerr = Aerr + 1; } else { shift = Bexp - Aexp; if (shift < 64) Aerr = Berr + (Aerr >> shift) + 1; else Aerr = Berr + 1; Aexp = Bexp; } } else if (Berr) { Aerr = Berr; Aexp = Bexp; } if (Aerr && Cerr) { if (Aexp >= Cexp) { shift = Aexp - Cexp; if (shift < 64) Aerr = Aerr + (Cerr >> shift) + 1; else Aerr = Aerr + 1; } else { shift = Cexp - Aexp; if (shift < 64) Aerr = Cerr + (Aerr >> shift) + 1; else Aerr = Cerr + 1; Aexp = Cexp; } } else if (Cerr) { Aerr = Cerr; Aexp = Cexp; } #if FLINT_BITS == 64 mag_set_ui_2exp_small(rad, Aerr, Aexp - MAG_BITS); #else mag_set_d(rad, Aerr * (1.0 + 1e-14)); mag_mul_2exp_si(rad, rad, Aexp - MAG_BITS); #endif } static void mulhigh(mp_ptr res, mp_srcptr xptr, mp_size_t xn, mp_srcptr yptr, mp_size_t yn, mp_size_t nn) { mp_ptr tmp, xxx, yyy; slong k; ARF_MUL_TMP_DECL; ARF_MUL_TMP_ALLOC(tmp, 2 * nn); xxx = tmp; yyy = tmp + nn; mpn_copyi(xxx + nn - FLINT_MIN(xn, nn), xptr + xn - FLINT_MIN(xn, nn), FLINT_MIN(xn, nn)); mpn_copyi(yyy + nn - FLINT_MIN(yn, nn), yptr + yn - FLINT_MIN(yn, nn), FLINT_MIN(yn, nn)); for (k = 0; k < nn - xn; k++) xxx[k] = 0; for (k = 0; k < nn - yn; k++) yyy[k] = 0; if (xptr == yptr && xn == yn) mpfr_sqrhigh_n(res, xxx, nn); else mpfr_mulhigh_n(res, xxx, yyy, nn); ARF_MUL_TMP_FREE(tmp, 2 * nn); } void _arb_dot_addmul_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, mp_srcptr yptr, mp_size_t yn, int negative, flint_bitcnt_t shift) { slong shift_bits, shift_limbs, term_prec; mp_limb_t cy; mp_ptr sstart, tstart; mp_size_t tn, nn; shift_bits = shift % FLINT_BITS; shift_limbs = shift / FLINT_BITS; /* shift term_prec (discarded bits) |--------------------|--------------| | t[tn-1] | ... | t[0] | Term [ s[n-1] | s[n-2] | ... | s[0] ] Sum */ /* Upper bound for the term bit length. The actual term bit length could be smaller if the product does not extend all the way down to s. */ term_prec = sn * FLINT_BITS - shift; /* The mulhigh error relative to the top of the sum will be bounded by nn * 2^(-shift) * 2^(-FLINT_BITS*nn). One extra limb ensures that this is <1 sum-ulp. */ term_prec += FLINT_BITS; nn = (term_prec + FLINT_BITS - 1) / FLINT_BITS; /* Sanity check; must conform to the pre-allocated memory! */ if (nn > sn + 2) { flint_throw(FLINT_ERROR, "nn > sn + 2\n"); } /* Use mulhigh? */ if (term_prec >= MUL_MPFR_MIN_LIMBS * FLINT_BITS && term_prec <= MUL_MPFR_MAX_LIMBS * FLINT_BITS && xn * FLINT_BITS > 0.9 * term_prec && yn * FLINT_BITS > 0.9 * term_prec) { mulhigh(tmp, xptr, xn, yptr, yn, nn); tstart = tmp + nn; tn = nn; serr[0]++; } else { if (xn > nn || yn > nn) { if (xn > nn) { xptr += (xn - nn); xn = nn; } if (yn > nn) { yptr += (yn - nn); yn = nn; } serr[0]++; } tn = xn + yn; FLINT_MPN_MUL_WITH_SPECIAL_CASES(tmp + 1, xptr, xn, yptr, yn); tstart = tmp + 1; } if (shift_bits != 0) { tstart[-1] = mpn_rshift(tstart, tstart, tn, shift_bits); tstart = tstart - 1; tn++; } while (tstart[0] == 0) { tstart++; tn--; } if (shift_limbs + tn <= sn) { /* No truncation of the term. */ sstart = sum + sn - shift_limbs - tn; nn = tn; } else { /* The term is truncated. */ sstart = sum; tstart = tstart - (sn - shift_limbs - tn); nn = sn - shift_limbs; serr[0]++; } /* Likely case. Note: assumes 1 extra (dummy) limb in sum. */ if (shift_limbs <= 1) { if (negative) sstart[nn] -= mpn_sub_n(sstart, sstart, tstart, nn); else sstart[nn] += mpn_add_n(sstart, sstart, tstart, nn); } else { if (negative) { cy = mpn_sub_n(sstart, sstart, tstart, nn); mpn_sub_1(sstart + nn, sstart + nn, shift_limbs, cy); } else { cy = mpn_add_n(sstart, sstart, tstart, nn); mpn_add_1(sstart + nn, sstart + nn, shift_limbs, cy); } } } void _arb_dot_add_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, int negative, flint_bitcnt_t shift) { slong shift_bits, shift_limbs, term_prec; mp_limb_t cy, err; mp_ptr sstart, tstart; mp_size_t tn, nn; shift_bits = shift % FLINT_BITS; shift_limbs = shift / FLINT_BITS; term_prec = sn * FLINT_BITS - shift; term_prec += FLINT_BITS; nn = (term_prec + FLINT_BITS - 1) / FLINT_BITS; err = 0; if (xn > nn) { xptr += (xn - nn); xn = nn; err = 1; } tn = xn; if (shift_bits == 0) { mpn_copyi(tmp, xptr, tn); tstart = tmp; } else { tmp[0] = mpn_rshift(tmp + 1, xptr, tn, shift_bits); tstart = tmp; tn++; } while (tstart[0] == 0) { tstart++; tn--; } if (shift_limbs + tn <= sn) { /* No truncation of the term. */ sstart = sum + sn - shift_limbs - tn; nn = tn; } else { /* The term is truncated. */ sstart = sum; tstart = tstart - (sn - shift_limbs - tn); nn = sn - shift_limbs; err = 1; } serr[0] += err; /* Likely case. Note: assumes 1 extra (dummy) limb in sum. */ if (shift_limbs <= 1) { if (negative) sstart[nn] -= mpn_sub_n(sstart, sstart, tstart, nn); else sstart[nn] += mpn_add_n(sstart, sstart, tstart, nn); } else { if (negative) { cy = mpn_sub_n(sstart, sstart, tstart, nn); mpn_sub_1(sstart + nn, sstart + nn, shift_limbs, cy); } else { cy = mpn_add_n(sstart, sstart, tstart, nn); mpn_add_1(sstart + nn, sstart + nn, shift_limbs, cy); } } } void arb_dot(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) { slong i, j, nonzero, padding, extend; slong xexp, yexp, exp, max_exp, min_exp, sum_exp; slong xrexp, yrexp, srad_exp, max_rad_exp; int xnegative, ynegative, inexact; mp_size_t xn, yn, sn, alloc; flint_bitcnt_t shift; arb_srcptr xi, yi; arf_srcptr xm, ym; mag_srcptr xr, yr; mp_limb_t xtop, ytop; mp_limb_t xrad, yrad; mp_limb_t serr; /* Sum over arithmetic errors */ uint64_t srad; /* Sum over propagated errors */ mp_ptr tmp, sum; /* Workspace */ ARF_ADD_TMP_DECL; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arb_zero(res); else { arb_mul(res, x, y, prec); if (subtract) arb_neg(res, res); } return; } else if (len <= 0) { arb_set_round(res, initial, prec); return; } } /* Number of nonzero midpoint terms in sum. */ nonzero = 0; /* Terms are bounded by 2^max_exp (with WORD_MIN = -infty) */ max_exp = WORD_MIN; /* Propagated error terms are bounded by 2^max_rad_exp */ max_rad_exp = WORD_MIN; /* Used to reduce the precision. */ min_exp = WORD_MAX; /* Account for the initial term. */ if (initial != NULL) { if (!ARB_IS_LAGOM(initial)) { arb_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(initial); xr = arb_radref(initial); if (!arf_is_special(xm)) { max_exp = ARF_EXP(xm); nonzero++; if (prec > 2 * FLINT_BITS) min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } if (!mag_is_special(xr)) max_rad_exp = MAG_EXP(xr); } /* Determine maximum exponents for the main sum and the radius sum. */ for (i = 0; i < len; i++) { xi = x + i * xstep; yi = y + i * ystep; /* Fallback for huge exponents or non-finite values. */ if (!ARB_IS_LAGOM(xi) || !ARB_IS_LAGOM(yi)) { arb_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec); return; } xm = arb_midref(xi); ym = arb_midref(yi); xr = arb_radref(xi); yr = arb_radref(yi); /* (xm+xr)(ym+yr) = xm ym + [xr ym + xm yr + xr yr] */ if (!arf_is_special(xm)) { xexp = ARF_EXP(xm); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_exp = FLINT_MAX(max_exp, xexp + yexp); nonzero++; if (prec > 2 * FLINT_BITS) { slong bot; bot = (xexp + yexp) - (ARF_SIZE(xm) + ARF_SIZE(ym)) * FLINT_BITS; min_exp = FLINT_MIN(min_exp, bot); } if (!mag_is_special(xr)) { xrexp = MAG_EXP(xr); max_rad_exp = FLINT_MAX(max_rad_exp, yexp + xrexp); if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xexp + yrexp); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yrexp); } } else { if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xexp + yrexp); } } } else /* if y = 0, something can happen only if yr != 0 */ { if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xexp + yrexp); if (!mag_is_special(xr)) { xrexp = MAG_EXP(xr); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yrexp); } } } } else /* if x = 0, something can happen only if xr != 0 */ { if (!mag_is_special(xr)) { xrexp = MAG_EXP(xr); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yexp); } if (!mag_is_special(yr)) { yrexp = MAG_EXP(yr); max_rad_exp = FLINT_MAX(max_rad_exp, xrexp + yrexp); } } } } /* The midpoint sum is zero. */ if (max_exp == WORD_MIN) { /* The sum is exactly zero. */ if (max_rad_exp == WORD_MIN) { arb_zero(res); return; } prec = 2; } else { /* Reduce precision based on errors. */ if (max_rad_exp != WORD_MIN) prec = FLINT_MIN(prec, max_exp - max_rad_exp + MAG_BITS); /* Reduce precision based on actual sizes. */ if (min_exp != WORD_MAX) prec = FLINT_MIN(prec, max_exp - min_exp + MAG_BITS); prec = FLINT_MAX(prec, 2); } /* Extend sum so that we can use two's complement addition. */ extend = FLINT_BIT_COUNT(nonzero) + 1; /* Extra bits to improve accuracy (optional). */ padding = 4 + FLINT_BIT_COUNT(len); /* Number of limbs. */ sn = (prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; /* Avoid having to make a special case for sn = 1. */ sn = FLINT_MAX(sn, 2); /* Exponent for the main sum. */ sum_exp = max_exp + extend; /* We need sn + 1 limb for the sum (sn limbs + 1 dummy limb for carry or borrow that avoids an extra branch). We need 2 * (sn + 2) limbs to store the product of two numbers with up to (sn + 2) limbs, plus 1 extra limb for shifting the product. */ alloc = (sn + 1) + 2 * (sn + 2) + 1; ARF_ADD_TMP_ALLOC(sum, alloc) tmp = sum + (sn + 1); /* Sum of propagated errors. */ srad_exp = max_rad_exp; srad = 0; /* Set sum to 0 */ serr = 0; for (j = 0; j < sn + 1; j++) sum[j] = 0; if (initial != NULL) { xm = arb_midref(initial); xr = arb_radref(initial); if (!arf_is_special(xm)) { mp_srcptr xptr; xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); shift = sum_exp - xexp; if (shift >= sn * FLINT_BITS) { serr++; } else { xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); _arb_dot_add_generic(sum, &serr, tmp, sn, xptr, xn, xnegative ^ subtract, shift); } } if (!mag_is_special(xr)) { xrad = MAG_MAN(xr); xrexp = MAG_EXP(xr); shift = srad_exp - xrexp; if (shift < 64) srad += (xrad >> shift) + 1; else srad++; } } for (i = 0; i < len; i++) { xi = x + i * xstep; yi = y + i * ystep; xm = arb_midref(xi); ym = arb_midref(yi); xr = arb_radref(xi); yr = arb_radref(yi); /* The midpoints of x[i] and y[i] are both nonzero. */ if (!arf_is_special(xm) && !arf_is_special(ym)) { xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); yexp = ARF_EXP(ym); yn = ARF_SIZE(ym); ynegative = ARF_SGNBIT(ym); exp = xexp + yexp; shift = sum_exp - exp; if (shift >= sn * FLINT_BITS) { /* We may yet need the top limbs for bounds. */ ARF_GET_TOP_LIMB(xtop, xm); ARF_GET_TOP_LIMB(ytop, ym); serr++; } #if 0 else if (xn == 1 && yn == 1 && sn == 2 && shift < FLINT_BITS) /* Fastest path. */ { mp_limb_t hi, lo, out; xtop = ARF_NOPTR_D(xm)[0]; ytop = ARF_NOPTR_D(ym)[0]; umul_ppmm(hi, lo, xtop, ytop); out = lo << (FLINT_BITS - shift); lo = (lo >> shift) | (hi << (FLINT_BITS - shift)); hi = (hi >> shift); serr += (out != 0); if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], hi, lo); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], hi, lo); } else if (xn == 2 && yn == 2 && shift < FLINT_BITS && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; xtop = x1; ytop = y1; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); u0 = (u0 != 0) || ((u1 << (FLINT_BITS - shift)) != 0); u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); if (sn == 2) { serr += (u0 || (u1 != 0)); if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else { serr += u0; if (xnegative ^ ynegative) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } #endif else if (xn <= 2 && yn <= 2 && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; if (xn == 1 && yn == 1) { xtop = ARF_NOPTR_D(xm)[0]; ytop = ARF_NOPTR_D(ym)[0]; umul_ppmm(u3, u2, xtop, ytop); u1 = u0 = 0; } else if (xn == 2 && yn == 2) { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; xtop = x1; ytop = y1; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); } else if (xn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; xtop = x0; ytop = y1; FLINT_MPN_MUL_2X1(u3, u2, u1, y1, y0, x0); u0 = 0; } else { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; xtop = x1; ytop = y0; FLINT_MPN_MUL_2X1(u3, u2, u1, x1, x0, y0); u0 = 0; } if (sn == 2) { if (shift < FLINT_BITS) { serr += ((u2 << (FLINT_BITS - shift)) != 0) || (u1 != 0) || (u0 != 0); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { serr += (u2 != 0) || (u1 != 0) || (u0 != 0); u2 = u3; u3 = 0; } else /* FLINT_BITS < shift < 2 * FLINT_BITS */ { serr += ((u3 << (2 * FLINT_BITS - shift)) != 0) || (u2 != 0) || (u1 != 0) || (u0 != 0); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else if (sn == 3) { if (shift < FLINT_BITS) { serr += ((u1 << (FLINT_BITS - shift)) != 0) || (u0 != 0); u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { serr += (u1 != 0) || (u0 != 0); u1 = u2; u2 = u3; u3 = 0; } else if (shift < 2 * FLINT_BITS) { serr += ((u2 << (2 * FLINT_BITS - shift)) != 0) || (u1 != 0) || (u0 != 0); u1 = (u3 << (2 * FLINT_BITS - shift)) | (u2 >> (shift - FLINT_BITS)); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } else if (shift == 2 * FLINT_BITS) { serr += (u2 != 0) || (u1 != 0) || (u0 != 0); u1 = u3; u2 = 0; u3 = 0; } else /* 2 * FLINT_BITS < shift < 3 * FLINT_BITS */ { serr += ((u3 << (3 * FLINT_BITS - shift)) != 0) || (u2 != 0) || (u1 != 0) || (u0 != 0); u1 = (u3 >> (shift - 2 * FLINT_BITS)); u2 = 0; u3 = 0; } if (xnegative ^ ynegative) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } else { mp_srcptr xptr, yptr; xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); yptr = (yn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(ym) : ARF_PTR_D(ym); xtop = xptr[xn - 1]; ytop = yptr[yn - 1]; _arb_dot_addmul_generic(sum, &serr, tmp, sn, xptr, xn, yptr, yn, xnegative ^ ynegative, shift); } xrad = MAG_MAN(xr); yrad = MAG_MAN(yr); if (xrad != 0 && yrad != 0) { xrexp = MAG_EXP(xr); yrexp = MAG_EXP(yr); RAD_ADDMUL(srad, srad_exp, (xtop >> (FLINT_BITS - MAG_BITS)) + 1, yrad, xexp + yrexp); RAD_ADDMUL(srad, srad_exp, (ytop >> (FLINT_BITS - MAG_BITS)) + 1, xrad, yexp + xrexp); RAD_ADDMUL(srad, srad_exp, xrad, yrad, xrexp + yrexp); } else if (xrad != 0) { xrexp = MAG_EXP(xr); RAD_ADDMUL(srad, srad_exp, (ytop >> (FLINT_BITS - MAG_BITS)) + 1, xrad, yexp + xrexp); } else if (yrad != 0) { yrexp = MAG_EXP(yr); RAD_ADDMUL(srad, srad_exp, (xtop >> (FLINT_BITS - MAG_BITS)) + 1, yrad, xexp + yrexp); } } else { xrad = MAG_MAN(xr); yrad = MAG_MAN(yr); xexp = ARF_EXP(xm); yexp = ARF_EXP(ym); xrexp = MAG_EXP(xr); yrexp = MAG_EXP(yr); /* (xm+xr)(ym+yr) = xm ym + [xm yr + ym xr + xr yr] */ if (yrad && !arf_is_special(xm)) { ARF_GET_TOP_LIMB(xtop, xm); RAD_ADDMUL(srad, srad_exp, (xtop >> (FLINT_BITS - MAG_BITS)) + 1, yrad, xexp + yrexp); } if (xrad && !arf_is_special(ym)) { ARF_GET_TOP_LIMB(ytop, ym); RAD_ADDMUL(srad, srad_exp, (ytop >> (FLINT_BITS - MAG_BITS)) + 1, xrad, yexp + xrexp); } if (xrad && yrad) { RAD_ADDMUL(srad, srad_exp, xrad, yrad, xrexp + yrexp); } } } xnegative = 0; if (sum[sn - 1] >= LIMB_TOP) { mpn_neg(sum, sum, sn); xnegative = 1; } if (sum[sn - 1] == 0) { slong sum_exp2; mp_size_t sn2; sn2 = sn; sum_exp2 = sum_exp; while (sn2 > 0 && sum[sn2 - 1] == 0) { sum_exp2 -= FLINT_BITS; sn2--; } if (sn2 == 0) { arf_zero(arb_midref(res)); inexact = 0; } else { inexact = _arf_set_round_mpn(arb_midref(res), &exp, sum, sn2, xnegative ^ subtract, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp + sum_exp2); } } else { if (sn == 2) inexact = _arf_set_round_uiui(arb_midref(res), &exp, sum[1], sum[0], xnegative ^ subtract, prec, ARF_RND_DOWN); else inexact = _arf_set_round_mpn(arb_midref(res), &exp, sum, sn, xnegative ^ subtract, prec, ARF_RND_DOWN); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp + sum_exp); } /* Add the three sources of error. Final rounding error = inexact * 2^(exp + sum_exp - prec) 0 <= inexact <= 1 Arithmetic error = serr * 2^(sum_exp - sn * FLINT_BITS) 0 <= serr <= 3 * n Propagated error = srad * 2^(srad_exp - MAG_BITS) 0 <= srad <= 3 * n * MAG_BITS We shift the first two by MAG_BITS so that the magnitudes become similar and a reasonably accurate addition can be done by comparing exponents without normalizing first. */ add_errors(arb_radref(res), inexact << MAG_BITS, exp + sum_exp - prec, ((uint64_t) serr) << MAG_BITS, sum_exp - sn * FLINT_BITS, srad, srad_exp); ARF_ADD_TMP_FREE(sum, alloc); } flint-3.1.3/src/arb/dot_fmpz.c000066400000000000000000000074571461254215100161710ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_dot_fmpz(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const fmpz * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i, ssize, size, tmp_size; mp_ptr ztmp; fmpz v; ulong av, al; unsigned int bc; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arb_zero(res); else { arb_mul_fmpz(res, x, y, prec); if (subtract) arb_neg(res, res); } return; } else if (len <= 0) { arb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); tmp_size = 0; for (i = 0; i < len; i++) { v = y[i * ystep]; MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; if (v == 0) { ARF_XSIZE(arb_midref(t + i)) = 0; ARF_EXP(arb_midref(t + i)) = ARF_EXP_ZERO; } else if (!COEFF_IS_MPZ(v)) { av = FLINT_ABS(v); bc = flint_clz(av); ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = av << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, v < 0); } else { __mpz_struct * z = COEFF_TO_PTR(v); ssize = z->_mp_size; size = FLINT_ABS(ssize); av = z->_mp_d[size - 1]; bc = flint_clz(av); if (size == 1) { ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = av << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, ssize < 0); } else if (size == 2) { al = z->_mp_d[0]; ARF_EXP(arb_midref(t + i)) = 2 * FLINT_BITS - bc; if (bc != 0) { av = (av << bc) | (al >> (FLINT_BITS - bc)); al = al << bc; } ARF_NOPTR_D(arb_midref(t + i))[0] = al; ARF_NOPTR_D(arb_midref(t + i))[1] = av; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(2, ssize < 0); } else { if (bc != 0) { tmp_size += size; /* use to flag tmp where we need tmp storage */ MAG_MAN(arb_radref(t + i)) = bc; } ARF_EXP(arb_midref(t + i)) = size * FLINT_BITS - bc; ARF_PTR_D(arb_midref(t + i)) = z->_mp_d; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(size, ssize < 0); } } } if (tmp_size != 0) { ztmp = TMP_ALLOC(sizeof(mp_limb_t) * tmp_size); for (i = 0; i < len; i++) { bc = MAG_MAN(arb_radref(t + i)); if (bc != 0) { size = ARF_SIZE(arb_midref(t + i)); mpn_lshift(ztmp, ARF_PTR_D(arb_midref(t + i)), size, bc); ARF_PTR_D(arb_midref(t + i)) = ztmp; ztmp += size; } MAG_MAN(arb_radref(t + i)) = 0; } } arb_dot(res, initial, subtract, x, xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/arb/dot_precise.c000066400000000000000000000044441461254215100166400ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_dot_precise(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) { arf_ptr A, B; arf_t t, u; slong i; int inexact; if (len <= 0) { if (initial == NULL) arb_zero(res); else arb_set_round(res, initial, prec); return; } A = flint_calloc(len + (initial != NULL), sizeof(arf_struct)); B = flint_calloc(3 * len + 1 + (initial != NULL), sizeof(arf_struct)); for (i = 0; i < len; i++) { arb_srcptr xp = x + i * xstep; arb_srcptr yp = y + i * ystep; arf_mul(A + i, arb_midref(xp), arb_midref(yp), ARF_PREC_EXACT, ARF_RND_DOWN); if (subtract) arf_neg(A + i, A + i); arf_init_set_mag_shallow(t, arb_radref(xp)); arf_init_set_mag_shallow(u, arb_radref(yp)); arf_mul(B + 3 * i, t, u, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(B + 3 * i + 1, t, arb_midref(yp), ARF_PREC_EXACT, ARF_RND_DOWN); arf_abs(B + 3 * i + 1, B + 3 * i + 1); arf_mul(B + 3 * i + 2, u, arb_midref(xp), ARF_PREC_EXACT, ARF_RND_DOWN); arf_abs(B + 3 * i + 2, B + 3 * i + 2); } if (initial != NULL) { arf_set(A + len, arb_midref(initial)); arf_set_mag(B + 3 * len + 1, arb_radref(initial)); } inexact = arf_sum(arb_midref(res), A, len + (initial != NULL), prec, ARF_RND_DOWN); if (inexact) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec); else mag_zero(arb_radref(res)); arf_set_mag(B + 3 * len, arb_radref(res)); arf_sum(A, B, 3 * len + 1 + (initial != NULL), 3 * MAG_BITS, ARF_RND_UP); arf_get_mag(arb_radref(res), A); for (i = 0; i < len + (initial != NULL); i++) arf_clear(A + i); for (i = 0; i < 3 * len + 1 + (initial != NULL); i++) arf_clear(B + i); flint_free(A); flint_free(B); } flint-3.1.3/src/arb/dot_si.c000066400000000000000000000034471461254215100156230ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_dot_si(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const slong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; slong v; ulong av; unsigned int bc; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arb_zero(res); else { arb_mul_si(res, x, y[0], prec); if (subtract) arb_neg(res, res); } return; } else if (len <= 0) { arb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { v = y[i * ystep]; if (v == 0) { ARF_XSIZE(arb_midref(t + i)) = 0; ARF_EXP(arb_midref(t + i)) = ARF_EXP_ZERO; } else { av = FLINT_ABS(v); bc = flint_clz(av); ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = av << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, v < 0); } MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(res, initial, subtract, x, xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/arb/dot_simple.c000066400000000000000000000021151461254215100164700ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_dot_simple(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, arb_srcptr y, slong ystep, slong len, slong prec) { slong i; if (len <= 0) { if (initial == NULL) arb_zero(res); else arb_set_round(res, initial, prec); return; } if (initial == NULL) { arb_mul(res, x, y, prec); } else { if (subtract) arb_neg(res, initial); else arb_set(res, initial); arb_addmul(res, x, y, prec); } for (i = 1; i < len; i++) arb_addmul(res, x + i * xstep, y + i * ystep, prec); if (subtract) arb_neg(res, res); } flint-3.1.3/src/arb/dot_siui.c000066400000000000000000000052001461254215100161460ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void arf_shallow_set_siui(arf_t res, ulong vhi, ulong vlo) { int negative; unsigned int bc; negative = ((slong) vhi) < 0; if (negative) { vhi = -vhi - (vlo != 0); vlo = -vlo; } if (vhi == 0) { if (vlo == 0) { ARF_XSIZE(res) = 0; ARF_EXP(res) = ARF_EXP_ZERO; } else { bc = flint_clz(vlo); ARF_EXP(res) = FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, negative); } } else if (vlo == 0) { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vhi << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, negative); } else { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; if (bc == 0) ARF_NOPTR_D(res)[1] = vhi; else ARF_NOPTR_D(res)[1] = (vhi << bc) | (vlo >> (FLINT_BITS - bc)); ARF_XSIZE(res) = ARF_MAKE_XSIZE(2, negative); } } void arb_dot_siui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; ulong vhi, vlo; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arb_zero(res); else { arf_t t; arf_shallow_set_siui(t, y[1], y[0]); arb_mul_arf(res, x, t, prec); if (subtract) arb_neg(res, res); } return; } else if (len <= 0) { arb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { vlo = y[2 * i * ystep]; vhi = y[2 * i * ystep + 1]; arf_shallow_set_siui(arb_midref(t + i), vhi, vlo); MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(res, initial, subtract, x, xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/arb/dot_ui.c000066400000000000000000000033641461254215100156230ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_dot_ui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; ulong v; unsigned int bc; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arb_zero(res); else { arb_mul_ui(res, x, y[0], prec); if (subtract) arb_neg(res, res); } return; } else if (len <= 0) { arb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { v = y[i * ystep]; if (v == 0) { ARF_XSIZE(arb_midref(t + i)) = 0; ARF_EXP(arb_midref(t + i)) = ARF_EXP_ZERO; } else { bc = flint_clz(v); ARF_EXP(arb_midref(t + i)) = FLINT_BITS - bc; ARF_NOPTR_D(arb_midref(t + i))[0] = v << bc; ARF_XSIZE(arb_midref(t + i)) = ARF_MAKE_XSIZE(1, 0); } MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(res, initial, subtract, x, xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/arb/dot_uiui.c000066400000000000000000000047421461254215100161620ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void arf_shallow_set_uiui(arf_t res, ulong vhi, ulong vlo) { unsigned int bc; if (vhi == 0) { if (vlo == 0) { ARF_XSIZE(res) = 0; ARF_EXP(res) = ARF_EXP_ZERO; } else { bc = flint_clz(vlo); ARF_EXP(res) = FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, 0); } } else if (vlo == 0) { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vhi << bc; ARF_XSIZE(res) = ARF_MAKE_XSIZE(1, 0); } else { bc = flint_clz(vhi); ARF_EXP(res) = 2 * FLINT_BITS - bc; ARF_NOPTR_D(res)[0] = vlo << bc; if (bc == 0) ARF_NOPTR_D(res)[1] = vhi; else ARF_NOPTR_D(res)[1] = (vhi << bc) | (vlo >> (FLINT_BITS - bc)); ARF_XSIZE(res) = ARF_MAKE_XSIZE(2, 0); } } void arb_dot_uiui(arb_t res, const arb_t initial, int subtract, arb_srcptr x, slong xstep, const ulong * y, slong ystep, slong len, slong prec) { arb_ptr t; slong i; ulong vhi, vlo; TMP_INIT; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arb_zero(res); else { arf_t t; arf_shallow_set_uiui(t, y[1], y[0]); arb_mul_arf(res, x, t, prec); if (subtract) arb_neg(res, res); } return; } else if (len <= 0) { arb_set_round(res, initial, prec); return; } } TMP_START; t = TMP_ALLOC(sizeof(arb_struct) * len); for (i = 0; i < len; i++) { vlo = y[2 * i * ystep]; vhi = y[2 * i * ystep + 1]; arf_shallow_set_uiui(arb_midref(t + i), vhi, vlo); MAG_EXP(arb_radref(t + i)) = 0; MAG_MAN(arb_radref(t + i)) = 0; } arb_dot(res, initial, subtract, x, xstep, t, 1, len, prec); TMP_END; } flint-3.1.3/src/arb/doublefac_ui.c000066400000000000000000000014041461254215100167520ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_doublefac_ui(arb_t res, ulong n, slong prec) { if (n % 2 == 0) { arb_fac_ui(res, n / 2, prec); arb_mul_2exp_si(res, res, n / 2); } else { arb_t t; arb_init(t); arb_doublefac_ui(t, n - 1, prec + 5); arb_fac_ui(res, n, prec + 5); arb_div(res, res, t, prec); arb_clear(t); } } flint-3.1.3/src/arb/euler_number_fmpz.c000066400000000000000000000027071461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_euler_number_fmpz(arb_t res, const fmpz_t n, slong prec) { if (fmpz_cmp_ui(n, UWORD_MAX) <= 0) { if (fmpz_sgn(n) >= 0) arb_euler_number_ui(res, fmpz_get_ui(n), prec); else arb_zero(res); } else if (fmpz_is_odd(n)) { arb_zero(res); } else { arb_t t; fmpz_t m; slong wp; arb_init(t); fmpz_init(m); wp = prec + 2 * fmpz_bits(n); /* beta(n) ~= 1 */ arf_one(arb_midref(res)); mag_one(arb_radref(res)); mag_mul_2exp_si(arb_radref(res), arb_radref(res), WORD_MIN); /* |E_n| = 2 n! beta(n+1) / (pi/2)^(n+1) */ fmpz_add_ui(m, n, 1); arb_gamma_fmpz(t, m, wp); arb_mul(res, res, t, wp); arb_const_pi(t, wp); arb_mul_2exp_si(t, t, -1); arb_pow_fmpz(t, t, m, wp); arb_div(res, res, t, prec); arb_mul_2exp_si(res, res, 1); if (fmpz_fdiv_ui(n, 4) == 2) arb_neg(res, res); arb_clear(t); fmpz_clear(m); } } flint-3.1.3/src/arb/euler_number_ui.c000066400000000000000000000352171461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2016, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "arb.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif #if FLINT64 #define ARB_EULER_NUMBER_TAB_SIZE 25 #else #define ARB_EULER_NUMBER_TAB_SIZE 15 #endif static const ulong arb_euler_number_tab[] = { 1, 1, 5, 61, 1385, 50521, 2702765, 199360981, #if FLINT64 UWORD(19391512145), UWORD(2404879675441), UWORD(370371188237525), UWORD(69348874393137901), UWORD(15514534163557086905) #endif }; static double arb_euler_number_mag(double n) { double x; x = n + 2; x += ((n + 1) * log(n + 1) - n) * 1.44269504088897; /* 1/log(2) */ x -= 1.6514961294723*(n+1); /* log2(pi) */ return x; } void arb_euler_number_ui_beta(arb_t res, ulong n, slong prec) { slong pi_prec; arb_t t; const signed char chi[4] = {0, 1, 0, -1}; pi_prec = prec + 2 * FLINT_BIT_COUNT(n); arb_init(t); /* |E_n| = 2 n! beta(n+1) / (pi/2)^(n+1) */ arb_const_pi(t, pi_prec); arb_mul_2exp_si(t, t, -1); arb_pow_ui(t, t, n + 1, pi_prec); _acb_dirichlet_euler_product_real_ui(res, n + 1, chi, 4, 1, prec); arb_mul(res, res, t, prec); arb_fac_ui(t, n, pi_prec); /* todo: prec should be enough */ arb_div(res, t, res, prec); arb_mul_2exp_si(res, res, 1); if (n % 4 == 2) arb_neg(res, res); arb_clear(t); } #define LOW_MASK ((UWORD(1) << (FLINT_BITS / 2)) - 1) typedef struct { ulong n; ulong ninv; ulong F; } nmod_redc_t; static void nmod_redc_init(nmod_redc_t * rmod, nmod_t mod) { ulong n, ninv2; int bits; n = mod.n; rmod->n = n; rmod->F = (UWORD(1) << (FLINT_BITS / 2)); NMOD_RED(rmod->F, rmod->F, mod); /* Newton's method for 2-adic inversion */ ninv2 = -n; /* already correct mod 8 */ for (bits = 3; bits < FLINT_BITS / 2; bits *= 2) ninv2 = 2*ninv2 + n * ninv2 * ninv2; rmod->ninv = ninv2 & LOW_MASK; } static inline ulong nmod_redc_fast(ulong x, ulong n, ulong ninv2) { ulong y = (x * ninv2) & LOW_MASK; ulong z = x + (n * y); return z >> (FLINT_BITS / 2); } static inline ulong nmod_redc(ulong x, ulong n, ulong ninv2) { ulong y = nmod_redc_fast(x, n, ninv2); if (y >= n) y -= n; return y; } static ulong nmod_redc_mul_fast(ulong a, ulong b, nmod_redc_t rmod) { return nmod_redc_fast(a * b, rmod.n, rmod.ninv); } static ulong nmod_redc_mul(ulong a, ulong b, nmod_redc_t rmod) { return nmod_redc(a * b, rmod.n, rmod.ninv); } static ulong nmod_to_redc(ulong x, nmod_t mod, nmod_redc_t rmod) { return nmod_mul(x, rmod.F, mod); } static ulong nmod_from_redc(ulong x, nmod_redc_t rmod) { return nmod_redc(x, rmod.n, rmod.ninv); } ulong nmod_redc_pow_ui(ulong a, ulong exp, nmod_redc_t rmod) { ulong x; while ((exp & 1) == 0) { a = nmod_redc_mul(a, a, rmod); exp >>= 1; } x = a; while (exp >>= 1) { a = nmod_redc_mul(a, a, rmod); if (exp & 1) x = nmod_redc_mul(x, a, rmod); } return x; } ulong euler_mod_p_powsum_1(ulong n, ulong p) { slong j; ulong s, t; nmod_t mod; if (n % 2 == 1) return 0; n = n % (p - 1); if (n == 0) return UWORD_MAX; nmod_init(&mod, p); s = 1; for (j = 3; j <= p - 2; j += 2) { t = nmod_pow_ui(j, n, mod); s = nmod_sub(t, s, mod); } if (p % 4 == 1) s = nmod_neg(s, mod); s = nmod_add(s, s, mod); return s; } ulong euler_mod_p_powsum_noredc(ulong n, ulong p, const unsigned int * divtab) { unsigned int * pows; slong i, N, horner_point; ulong s, t, z; ulong v2n, power_of_two; nmod_t mod; TMP_INIT; if (n % 2 == 1) return 0; n = n % (p - 1); if (n == 0) return UWORD_MAX; N = p / 4; nmod_init(&mod, p); TMP_START; pows = TMP_ALLOC(sizeof(unsigned int) * (N / 3 + 1)); s = z = 0; /* Evaluate as a polynomial in 2^n */ power_of_two = 1; while (power_of_two * 2 <= N) power_of_two *= 2; horner_point = 1; v2n = nmod_pow_ui(2, n, mod); for (i = 1; i <= N / 3; i += 2) { if (divtab[i] == 1) t = nmod_pow_ui(i, n, mod); else t = nmod_mul(pows[divtab[i]], pows[divtab[i + 1]], mod); pows[i] = t; s = nmod_add(s, t, mod); if (i == horner_point) { while (i == horner_point && power_of_two != 1) { z = nmod_add(s, nmod_mul(v2n, z, mod), mod); power_of_two /= 2; horner_point = N / power_of_two; if (horner_point % 2 == 0) horner_point--; } } } /* Same as above, but here we don't need to write the powers. */ for ( ; i <= N; i += 2) { if (divtab[i] == 1) t = nmod_pow_ui(i, n, mod); else t = nmod_mul(pows[divtab[i]], pows[divtab[i + 1]], mod); s = nmod_add(s, t, mod); if (i == horner_point) { while (i == horner_point && power_of_two != 1) { z = nmod_add(s, nmod_mul(v2n, z, mod), mod); power_of_two /= 2; horner_point = N / power_of_two; if (horner_point % 2 == 0) horner_point--; } } } s = nmod_add(s, nmod_mul(v2n, z, mod), mod); if (p % 4 == 3) s = nmod_neg(s, mod); t = nmod_inv(nmod_pow_ui(4, p - n - 2, mod), mod); s = nmod_mul(s, t, mod); TMP_END; return s; } ulong euler_mod_p_powsum_redc(ulong n, ulong p, const unsigned int * divtab) { unsigned int * pows; slong i, N, horner_point; ulong s, t, z; ulong v2n, power_of_two; nmod_t mod; nmod_redc_t rmod; TMP_INIT; if (n % 2 == 1) return 0; n = n % (p - 1); if (n == 0) return UWORD_MAX; N = p / 4; nmod_init(&mod, p); nmod_redc_init(&rmod, mod); TMP_START; pows = TMP_ALLOC(sizeof(unsigned int) * (N / 3 + 1)); s = z = 0; /* Evaluate as a polynomial in 2^n */ power_of_two = 1; while (power_of_two * 2 <= N) power_of_two *= 2; horner_point = 1; v2n = nmod_redc_pow_ui(nmod_to_redc(2, mod, rmod), n, rmod); for (i = 1; i <= N / 3; i += 2) { if (divtab[i] == 1) t = nmod_redc_pow_ui(nmod_to_redc(i, mod, rmod), n, rmod); else t = nmod_redc_mul(pows[divtab[i]], pows[divtab[i + 1]], rmod); pows[i] = t; s += t; if (i == horner_point) { while (i == horner_point && power_of_two != 1) { NMOD_RED(s, s, mod); z = nmod_add(s, nmod_redc_mul(v2n, z, rmod), mod); power_of_two /= 2; horner_point = N / power_of_two; if (horner_point % 2 == 0) horner_point--; } } } /* Same as above, but here we don't need to write the powers. */ for ( ; i <= N; i += 2) { if (divtab[i] == 1) t = nmod_redc_pow_ui(nmod_to_redc(i, mod, rmod), n, rmod); else t = nmod_redc_mul_fast(pows[divtab[i]], pows[divtab[i + 1]], rmod); s += t; if (i == horner_point) { while (i == horner_point && power_of_two != 1) { NMOD_RED(s, s, mod); z = nmod_add(s, nmod_redc_mul(v2n, z, rmod), mod); power_of_two /= 2; horner_point = N / power_of_two; if (horner_point % 2 == 0) horner_point--; } } } NMOD_RED(s, s, mod); s = nmod_add(s, nmod_redc_mul(v2n, z, rmod), mod); s = nmod_from_redc(s, rmod); if (p % 4 == 3) s = nmod_neg(s, mod); t = nmod_inv(nmod_pow_ui(4, p - n - 2, mod), mod); s = nmod_mul(s, t, mod); TMP_END; return s; } ulong euler_mod_p_powsum(ulong n, ulong p, const unsigned int * divtab) { if (p < (UWORD(1) << (FLINT_BITS / 2 - 1))) return euler_mod_p_powsum_redc(n, p, divtab); else return euler_mod_p_powsum_noredc(n, p, divtab); } static void divisor_table_odd(unsigned int * tab, slong len) { slong i, j; tab[0] = 0; for (i = 1; i < len; i += 2) { tab[i] = 1; tab[i + 1] = i; } for (i = 3; i < len; i += 2) { for (j = 3; j <= i && i * j < len; j += 2) { tab[i * j] = j; tab[i * j + 1] = i; } } } typedef struct { ulong n; const unsigned int * divtab; mp_ptr primes; mp_ptr residues; } mod_p_param_t; static void mod_p_worker(slong i, void * param) { mod_p_param_t * p = (mod_p_param_t *) param; p->residues[i] = euler_mod_p_powsum(p->n, p->primes[i], p->divtab); } #define TIMING 0 #define DEBUG 0 /* todo: optimize basecase and move to flint */ void _arb_tree_crt(fmpz_t r, fmpz_t m, mp_srcptr residues, mp_srcptr primes, slong len); void arb_fmpz_euler_number_ui_multi_mod(fmpz_t num, ulong n, double alpha) { n_primes_t prime_iter; slong i, bits, mod_bits, zeta_bits, num_primes; ulong p; mp_ptr primes, residues; mag_t primes_product; unsigned int * divtab_odd; fmpz_t M; #if TIMING double t1, t2; #endif if (n % 2 != 0) { fmpz_zero(num); return; } if (n < ARB_EULER_NUMBER_TAB_SIZE) { if (n % 4 == 0) fmpz_set_ui(num, arb_euler_number_tab[n / 2]); else fmpz_neg_ui(num, arb_euler_number_tab[n / 2]); return; } if (alpha < 0) { if (n < 2000) alpha = 0.0; else if (n < 6000) alpha = 0.002 + 1.0e-5 * (n - 2000); else if (n < 90000) alpha = -0.132 + 0.02 * log(n); else alpha = FLINT_MIN(0.0085 * log(n), 0.11); } #if TIMING t1 = clock(); #endif bits = arb_euler_number_mag(n) + 2; mod_bits = bits * alpha; zeta_bits = bits - mod_bits; num_primes = 0; mag_init(primes_product); mag_one(primes_product); n_primes_init(prime_iter); p = 5; n_primes_jump_after(prime_iter, 5); for ( ; mag_cmp_2exp_si(primes_product, mod_bits) < 0; p = n_primes_next(prime_iter)) { if (n % (p - 1) != 0) { mag_mul_ui_lower(primes_product, primes_product, p); num_primes++; } } #if DEBUG printf("\nn = %lu, bits = %lu, num_primes = %ld\n", n, bits, num_primes); #endif primes = flint_malloc(sizeof(mp_limb_t) * num_primes); residues = flint_malloc(sizeof(mp_limb_t) * num_primes); p = 5; n_primes_jump_after(prime_iter, 5); for (i = 0; i < num_primes; p = n_primes_next(prime_iter)) { if (n % (p - 1) != 0) { primes[i] = p; i++; } } n_primes_clear(prime_iter); if (num_primes == 0) { divtab_odd = NULL; } else { p = primes[num_primes - 1]; divtab_odd = flint_malloc(sizeof(unsigned int) * (p / 4 + 2)); divisor_table_odd(divtab_odd, p / 4 + 1); } #if TIMING t2 = clock(); printf("init time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); printf("num_primes = %ld\n", num_primes); #endif { mod_p_param_t param; param.n = n; param.primes = primes; param.residues = residues; param.divtab = divtab_odd; flint_parallel_do(mod_p_worker, ¶m, num_primes, 0, FLINT_PARALLEL_STRIDED /* | FLINT_PARALLEL_VERBOSE */); } #if TIMING t2 = clock(); printf("mod time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); printf("start CRT\n"); t1 = clock(); #endif fmpz_init(M); _arb_tree_crt(num, M, residues, primes, num_primes); fmpz_mod(num, num, M); if (n % 4 == 2) { fmpz_sub(num, M, num); fmpz_neg(num, num); } #if TIMING printf("end CRT\n"); t2 = clock(); printf("CRT time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); t1 = clock(); #endif if (zeta_bits > 0) { slong prec; arb_t b; fmpz_t t; arb_init(b); fmpz_init(t); for (prec = zeta_bits + 10; ; prec += 32) { arb_euler_number_ui_beta(b, n, prec); arb_sub_fmpz(b, b, num, prec); arb_div_fmpz(b, b, M, prec); if (arb_get_unique_fmpz(t, b)) { fmpz_addmul(num, t, M); break; } flint_printf("euler: n = %wu, bits = %wd, mod = %wd, zeta = %wd: get_unique_fmpz failed!\n", n, bits, mod_bits, zeta_bits); } arb_clear(b); fmpz_clear(t); } #if TIMING printf("end zeta\n"); t2 = clock(); printf("zeta time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); #endif flint_free(primes); flint_free(residues); flint_free(divtab_odd); fmpz_clear(M); mag_clear(primes_product); } void arb_fmpz_euler_number_ui(fmpz_t res, ulong n) { arb_t x; double mag; if (n % 2 != 0) { fmpz_zero(res); return; } if (n < ARB_EULER_NUMBER_TAB_SIZE) { if (n % 4 == 0) fmpz_set_ui(res, arb_euler_number_tab[n / 2]); else fmpz_neg_ui(res, arb_euler_number_tab[n / 2]); return; } if (n < 2000) { mag = arb_euler_number_mag(n); arb_init(x); arb_euler_number_ui_beta(x, n, mag + 5); if (!arb_get_unique_fmpz(res, x)) { flint_throw(FLINT_ERROR, "arb_fmpz_euler_number_ui: unexpected inaccuracy\n"); } arb_clear(x); } else { arb_fmpz_euler_number_ui_multi_mod(res, n, -1.0); } } void arb_euler_number_ui(arb_t res, ulong n, slong prec) { double mag; if (n % 2 != 0) { arb_zero(res); return; } if (n < ARB_EULER_NUMBER_TAB_SIZE) { arb_set_ui(res, arb_euler_number_tab[n / 2]); if (n % 4 == 2) arb_neg(res, res); arb_set_round(res, res, prec); return; } mag = arb_euler_number_mag(n); if (prec > 0.9 * mag) { fmpz_t t; fmpz_init(t); arb_fmpz_euler_number_ui(t, n); arb_set_round_fmpz(res, t, prec); fmpz_clear(t); } else { arb_euler_number_ui_beta(res, n, prec + 5); arb_set_round(res, res, prec); } } flint-3.1.3/src/arb/exp.c000066400000000000000000000240761461254215100151370ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #define MAGLIM(prec) FLINT_MAX(128, 2 * (prec)) /* todo: min prec by MAG_BITS everywhere? */ void arb_exp_wide(arb_t res, const arb_t x, slong prec, slong maglim) { mag_t t, u; mag_init(t); mag_init(u); if (arf_cmpabs_2exp_si(arb_midref(x), 20) < 0 && mag_cmp_2exp_si(arb_radref(x), 20) < 0) { if (arf_is_zero(arb_midref(x))) { if (mag_cmp_2exp_si(arb_radref(x), -10) < 0) { mag_expm1(arb_radref(res), arb_radref(x)); arf_one(arb_midref(res)); } else { mag_expinv_lower(t, arb_radref(x)); mag_exp(u, arb_radref(x)); arb_set_interval_mag(res, t, u, prec); } } else if (arb_contains_zero(x)) { arf_get_mag_lower(t, arb_midref(x)); mag_sub(t, arb_radref(x), t); arf_get_mag(u, arb_midref(x)); mag_add(u, arb_radref(x), u); if (arf_sgn(arb_midref(x)) > 0) { mag_expinv_lower(t, t); mag_exp(u, u); arb_set_interval_mag(res, t, u, prec); } else { mag_expinv_lower(u, u); mag_exp(t, t); arb_set_interval_mag(res, u, t, prec); } } else if (arf_sgn(arb_midref(x)) < 0) { arb_get_mag(t, x); arb_get_mag_lower(u, x); mag_expinv_lower(t, t); mag_expinv(u, u); arb_set_interval_mag(res, t, u, prec); } else { arb_get_mag_lower(t, x); arb_get_mag(u, x); mag_exp_lower(t, t); mag_exp(u, u); arb_set_interval_mag(res, t, u, prec); } } else { /* use arb_exp_arf for accurate argument reduction */ arf_t q; arf_init(q); arf_set_mag(q, arb_radref(x)); arf_add(q, q, arb_midref(x), MAG_BITS, ARF_RND_CEIL); arb_exp_arf(res, q, FLINT_MIN(prec, MAG_BITS), 0, maglim); arb_get_mag(arb_radref(res), res); arf_zero(arb_midref(res)); arf_clear(q); } mag_clear(t); mag_clear(u); } void arb_exp(arb_t res, const arb_t x, slong prec) { slong maglim = MAGLIM(prec); if (mag_is_zero(arb_radref(x))) { arb_exp_arf(res, arb_midref(x), prec, 0, maglim); } else if (mag_is_inf(arb_radref(x))) { if (arf_is_nan(arb_midref(x))) arb_indeterminate(res); else arb_zero_pm_inf(res); } else if (arf_is_special(arb_midref(x))) { if (arf_is_zero(arb_midref(x))) arb_exp_wide(res, x, prec, maglim); else if (arf_is_nan(arb_midref(x))) arb_indeterminate(res); else /* infinity +/- finite */ arb_exp_arf(res, arb_midref(x), prec, 0, 1); } else /* both finite, non-special */ { slong acc, mexp, rexp; mexp = ARF_EXP(arb_midref(x)); rexp = MAG_EXP(arb_radref(x)); if (COEFF_IS_MPZ(rexp)) rexp = (fmpz_sgn(ARF_EXPREF(arb_radref(x))) < 0) ? COEFF_MIN : COEFF_MAX; if (COEFF_IS_MPZ(mexp)) mexp = (fmpz_sgn(MAG_EXPREF(arb_midref(x))) < 0) ? COEFF_MIN : COEFF_MAX; if (mexp < -prec && rexp < -prec) { arb_get_mag(arb_radref(res), x); mag_expm1(arb_radref(res), arb_radref(res)); arf_one(arb_midref(res)); return; } acc = -rexp; acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); if (acc < 20 && (rexp >= 0 || mexp <= 10)) { /* may evaluate at endpoints */ arb_exp_wide(res, x, prec, maglim); } else { /* exp(a+b) - exp(a) = exp(a) * (exp(b)-1) */ mag_t t, u; mag_init_set(t, arb_radref(x)); mag_init(u); arb_exp_arf(res, arb_midref(x), prec, 0, maglim); mag_expm1(t, t); arb_get_mag(u, res); mag_addmul(arb_radref(res), t, u); mag_clear(t); mag_clear(u); } } } void arb_expm1(arb_t res, const arb_t x, slong prec) { slong maglim = MAGLIM(prec); if (mag_is_zero(arb_radref(x))) { arb_exp_arf(res, arb_midref(x), prec, 1, maglim); } else if (mag_is_inf(arb_radref(x))) { if (arf_is_nan(arb_midref(x))) arb_indeterminate(res); else arb_zero_pm_inf(res); } else if (arf_is_special(arb_midref(x))) { if (arf_is_zero(arb_midref(x))) { if (mag_cmp_2exp_si(arb_radref(x), -10) < 0) { mag_expm1(arb_radref(res), arb_radref(x)); arf_zero(arb_midref(res)); } else { arb_exp_wide(res, x, prec, maglim); arb_sub_ui(res, res, 1, prec); } } else if (arf_is_nan(arb_midref(x))) arb_indeterminate(res); else /* infinity +/- finite */ arb_exp_arf(res, arb_midref(x), prec, 1, 1); } else /* both finite, non-special */ { if (arf_cmpabs_2exp_si(arb_midref(x), 3) < 0 && mag_cmp_2exp_si(arb_radref(x), -3) < 0) { mag_t t, u, one; slong acc, mexp, rexp; mexp = ARF_EXP(arb_midref(x)); rexp = MAG_EXP(arb_radref(x)); if (COEFF_IS_MPZ(rexp)) rexp = (fmpz_sgn(ARF_EXPREF(arb_radref(x))) < 0) ? COEFF_MIN : COEFF_MAX; if (COEFF_IS_MPZ(mexp)) mexp = (fmpz_sgn(MAG_EXPREF(arb_midref(x))) < 0) ? COEFF_MIN : COEFF_MAX; acc = FLINT_MIN(mexp, 0) - rexp; acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); /* [exp(a+b) - 1] - [exp(a) - 1] = exp(a) * (exp(b)-1) */ mag_init_set(t, arb_radref(x)); mag_init(u); mag_init(one); mag_one(one); if (arf_sgn(arb_midref(x)) >= 0) { arb_exp_arf(res, arb_midref(x), prec, 1, maglim); arb_get_mag(u, res); mag_add(u, u, one); } else { arb_exp_arf(res, arb_midref(x), prec, 1, maglim); arb_get_mag_lower(u, res); mag_sub(u, one, u); } mag_expm1(t, t); mag_addmul(arb_radref(res), t, u); mag_clear(t); mag_clear(u); mag_clear(one); } else { arb_exp(res, x, prec); arb_sub_ui(res, res, 1, prec); } } } void arb_exp_invexp(arb_t res, arb_t res2, const arb_t x, slong prec) { slong maglim = MAGLIM(prec); if (arf_is_special(arb_midref(x)) || mag_is_special(arb_radref(x))) { /* [c +/- 0] */ if (arf_is_finite(arb_midref(x)) && mag_is_zero(arb_radref(x))) { arb_exp_arf(res, arb_midref(x), prec, 0, maglim); arb_inv(res2, res, prec); } /* [nan +/- ?] */ else if (arf_is_nan(arb_midref(x))) { arb_indeterminate(res); arb_indeterminate(res2); } /* [c +/- inf] */ else if (mag_is_inf(arb_radref(x))) { arb_zero_pm_inf(res); arb_zero_pm_inf(res2); } /* [+inf +/- c] */ else if (arf_is_pos_inf(arb_midref(x))) { arb_pos_inf(res); arb_zero(res2); } /* [-inf +/- c] */ else if (arf_is_neg_inf(arb_midref(x))) { arb_zero(res); arb_pos_inf(res2); } else { arb_t t; arb_init(t); arb_neg(t, x); arb_exp_wide(res, x, prec, maglim); arb_exp_wide(res2, t, prec, maglim); arb_clear(t); } } else /* both finite, non-special */ { slong acc, mexp, rexp; mexp = ARF_EXP(arb_midref(x)); rexp = MAG_EXP(arb_radref(x)); if (COEFF_IS_MPZ(rexp)) rexp = (fmpz_sgn(ARF_EXPREF(arb_radref(x))) < 0) ? COEFF_MIN : COEFF_MAX; if (COEFF_IS_MPZ(mexp)) mexp = (fmpz_sgn(MAG_EXPREF(arb_midref(x))) < 0) ? COEFF_MIN : COEFF_MAX; if (mexp < -prec && rexp < -prec) { arb_get_mag(arb_radref(res), x); mag_expm1(arb_radref(res), arb_radref(res)); arf_one(arb_midref(res)); arb_set(res2, res); return; } acc = -rexp; acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); if (acc < 20 && (rexp >= 0 || mexp <= 10)) { /* may evaluate at endpoints */ arb_t t; arb_init(t); arb_neg(t, x); arb_exp_wide(res, x, prec, maglim); arb_exp_wide(res2, t, prec, maglim); arb_clear(t); } else { /* exp(a+b) - exp(a) = exp(a) * (exp(b)-1) */ mag_t t, u; mag_init_set(t, arb_radref(x)); mag_init(u); arb_exp_arf(res, arb_midref(x), prec, 0, maglim); arb_inv(res2, res, prec); mag_expm1(t, t); arb_get_mag(u, res); mag_addmul(arb_radref(res), t, u); arb_get_mag(u, res2); mag_addmul(arb_radref(res2), t, u); mag_clear(t); mag_clear(u); } } } flint-3.1.3/src/arb/exp_arf.c000066400000000000000000000271371461254215100157700ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "thread_support.h" #include "mpn_extras.h" #define TMP_ALLOC_LIMBS(__n) TMP_ALLOC((__n) * sizeof(mp_limb_t)) void arb_exp_arf_huge(arb_t z, const arf_t x, slong mag, slong prec, int minus_one) { arb_t ln2, t, u; fmpz_t q; slong wp; arb_init(ln2); arb_init(t); arb_init(u); fmpz_init(q); wp = prec + mag + 10; arb_const_log2(ln2, wp); arb_set_arf(t, x); arb_div(u, t, ln2, mag + 10); arf_get_fmpz(q, arb_midref(u), ARF_RND_DOWN); arb_submul_fmpz(t, ln2, q, wp); if (minus_one) { arb_exp(z, t, prec + 10); arb_mul_2exp_fmpz(z, z, q); arb_sub_ui(z, z, 1, prec); } else { arb_exp(z, t, prec); arb_mul_2exp_fmpz(z, z, q); } arb_clear(ln2); arb_clear(t); arb_clear(u); fmpz_clear(q); } /* |x| >= 2^expbound */ static void arb_exp_arf_overflow(arb_t z, slong expbound, int negative, int minus_one, slong prec) { if (!negative) { arf_zero(arb_midref(z)); mag_inf(arb_radref(z)); } else { /* x <= -2^expbound ==> 0 < exp(x) <= 2^(-2^expbound) */ fmpz_t t; fmpz_init(t); fmpz_set_si(t, -1); fmpz_mul_2exp(t, t, expbound); arf_one(arb_midref(z)); mag_one(arb_radref(z)); arb_mul_2exp_fmpz(z, z, t); if (minus_one) arb_sub_ui(z, z, 1, prec); fmpz_clear(t); } } void arb_exp_arf_generic(arb_t z, const arf_t x, slong prec, int minus_one) { slong mag; mag = arf_abs_bound_lt_2exp_si(x); /* reduce by log(2) if needed, but avoid computing log(2) unnecessarily at extremely high precision */ if (mag > 64 || (mag > 8 && prec < 1000000)) { arb_exp_arf_huge(z, x, mag, prec, minus_one); } else { int want_rs; if (prec < 10000 || mag < -prec / 16) { want_rs = 1; } else if (arf_bits(x) < prec / 128) { want_rs = 0; } else if (flint_get_num_available_threads() == 1) { want_rs = (prec < 20000) || (prec < 1000000000 && mag < -prec / 800); } else { want_rs = (prec < 10000) || (prec < 1000000000 && mag < -prec / 200); } if (want_rs) { arb_exp_arf_rs_generic(z, x, prec, minus_one); } else { arb_exp_arf_bb(z, x, prec, minus_one); } } } void arb_exp_arf(arb_t z, const arf_t x, slong prec, int minus_one, slong maglim) { if (arf_is_special(x)) { if (minus_one) { if (arf_is_zero(x)) arb_zero(z); else if (arf_is_pos_inf(x)) arb_pos_inf(z); else if (arf_is_neg_inf(x)) arb_set_si(z, -1); else arb_indeterminate(z); } else { if (arf_is_zero(x)) arb_one(z); else if (arf_is_pos_inf(x)) arb_pos_inf(z); else if (arf_is_neg_inf(x)) arb_zero(z); else arb_indeterminate(z); } } else if (COEFF_IS_MPZ(ARF_EXP(x))) { if (fmpz_sgn(ARF_EXPREF(x)) > 0) { /* huge input */ arb_exp_arf_overflow(z, maglim, ARF_SGNBIT(x), minus_one, prec); } else { /* |exp(x) - (1 + x)| <= |x^2| */ fmpz_t t; int inexact; fmpz_init(t); fmpz_mul_2exp(t, ARF_EXPREF(x), 1); inexact = arf_add_ui(arb_midref(z), x, minus_one ? 0 : 1, prec, ARB_RND); mag_one(arb_radref(z)); mag_mul_2exp_fmpz(arb_radref(z), arb_radref(z), t); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); fmpz_clear(t); } } else { slong exp, wp, wn, N, r, wprounded, finaln; fmpz_t n; mp_ptr tmp, w, t, u, finalvalue; mp_limb_t p1, q1bits, p2, q2bits, error, error2; int negative, inexact; TMP_INIT; exp = ARF_EXP(x); negative = ARF_SGNBIT(x); /* handle tiny input */ /* |exp(x) - 1| <= 2|x| */ if (!minus_one && exp < -prec - 4) { arf_one(arb_midref(z)); mag_set_ui_2exp_si(arb_radref(z), 1, exp + 1); return; } /* |exp(x) - (1 + x)| <= |x^2| */ else if (exp < (minus_one ? -prec - 4 : -(prec / 2) - 4)) { inexact = arf_add_ui(arb_midref(z), x, minus_one ? 0 : 1, prec, ARB_RND); mag_set_ui_2exp_si(arb_radref(z), 1, 2 * exp); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); return; } /* handle huge input */ if (exp > maglim) { arb_exp_arf_overflow(z, maglim, negative, minus_one, prec); return; } if (prec >= ARB_EXP_LOG_REDUCTION_PREC && prec <= ARB_LOG_REDUCTION_DEFAULT_MAX_PREC) { arb_exp_arf_log_reduction(z, x, prec, minus_one); return; } /* Absolute working precision (NOT rounded to a limb multiple) */ wp = prec + 8; if (minus_one && exp <= 0) wp += (-exp); /* Number of limbs */ wn = (wp + FLINT_BITS - 1) / FLINT_BITS; /* Precision rounded to a number of bits */ wprounded = FLINT_BITS * wn; /* Don't be close to the boundary (to allow adding adding the Taylor series truncation error without overflow) */ wp = FLINT_MAX(wp, wprounded - (FLINT_BITS - 4)); /* Too high precision to use table -- use generic algorithm */ if (wp > ARB_EXP_TAB2_PREC) { arb_exp_arf_generic(z, x, prec, minus_one); return; } TMP_START; tmp = TMP_ALLOC_LIMBS(4 * wn + 3); w = tmp; /* requires wn+1 limbs */ t = w + wn + 1; /* requires wn+1 limbs */ u = t + wn + 1; /* requires 2wn+1 limbs */ /* reduce modulo log(2) */ fmpz_init(n); if (_arb_get_mpn_fixed_mod_log2(w, n, &error, x, wn) == 0) { /* may run out of precision for log(2) */ arb_exp_arf_generic(z, x, prec, minus_one); fmpz_clear(n); TMP_END; return; } /* err(w) translates to a propagated error bounded by err(w) * exp'(x) < err(w) * exp(1) < err(w) * 3 */ error *= 3; /* Table-based argument reduction (1 or 2 steps) */ if (wp <= ARB_EXP_TAB1_PREC) { q1bits = ARB_EXP_TAB1_BITS; q2bits = 0; p1 = w[wn-1] >> (FLINT_BITS - q1bits); w[wn-1] -= (p1 << (FLINT_BITS - q1bits)); p2 = 0; } else { q1bits = ARB_EXP_TAB21_BITS; q2bits = ARB_EXP_TAB21_BITS + ARB_EXP_TAB22_BITS; p1 = w[wn-1] >> (FLINT_BITS - q1bits); w[wn-1] -= (p1 << (FLINT_BITS - q1bits)); p2 = w[wn-1] >> (FLINT_BITS - q2bits); w[wn-1] -= (p2 << (FLINT_BITS - q2bits)); } /* |w| <= 2^-r */ r = _arb_mpn_leading_zeros(w, wn); /* Choose number of terms N such that Taylor series truncation error is <= 2^-wp */ N = _arb_exp_taylor_bound(-r, wp); if (N < 60) { /* Evaluate Taylor series */ _arb_exp_taylor_rs(t, &error2, w, wn, N); /* Taylor series evaluation error */ error += error2; /* Taylor series truncation error */ error += UWORD(1) << (wprounded-wp); } else /* Compute cosh(a) from sinh(a) using a square root. */ { /* the summation for sinh is actually done to (2N-1)! */ N = (N + 1) / 2; /* Evaluate Taylor series for sinh */ _arb_sin_cos_taylor_rs(t, u, &error2, w, wn, N, 1, 0); error += error2; error += UWORD(1) << (wprounded-wp); /* 1 + sinh^2, with wn + 1 limbs */ flint_mpn_sqr(u, t, wn); u[2 * wn] = 1; /* cosh, with wn + 1 limbs */ mpn_sqrtrem(w, u, u, 2 * wn + 1); /* exp = sinh + cosh */ t[wn] = w[wn] + mpn_add_n(t, t, w, wn); /* Error for cosh */ /* When converting sinh to cosh, the error for cosh must be smaller than the error for sinh; but we also get 1 ulp extra error from the square root. */ error2 = error + 1; /* Error for sinh + cosh */ error += error2; } if (wp <= ARB_EXP_TAB1_PREC) { if (p1 == 0) { finalvalue = t; finaln = wn + 1; } else { /* Divide by 2 to get |t| <= 1 (todo: check this?) */ mpn_rshift(t, t, wn + 1, 1); error = (error >> 1) + 2; flint_mpn_mul_n(u, t, arb_exp_tab1[p1] + ARB_EXP_TAB1_LIMBS - wn, wn); /* (t + err1 * ulp) * (u + err2 * ulp) + 1ulp = t*u + (err1*u + err2*t + t*u*ulp + 1) * ulp note |u| <= 1, |t| <= 1 */ error += 4; finalvalue = u + wn; finaln = wn; /* we have effectively divided by 2^2 -- todo use inline function */ fmpz_add_ui(n, n, 2); } } else { if (p1 == 0 && p2 == 0) { finalvalue = t; finaln = wn + 1; } else { /* Divide by 2 to get |t| <= 1 (todo: check this?) */ mpn_rshift(t, t, wn + 1, 1); error = (error >> 1) + 2; flint_mpn_mul_n(u, arb_exp_tab21[p1] + ARB_EXP_TAB2_LIMBS - wn, arb_exp_tab22[p2] + ARB_EXP_TAB2_LIMBS - wn, wn); /* error of w <= 4 ulp */ flint_mpn_copyi(w, u + wn, wn); /* todo: avoid with better alloc */ flint_mpn_mul_n(u, t, w, wn); /* (t + err1 * ulp) * (w + 4 * ulp) + 1ulp = t*u + (err1*w + 4*t + t*w*ulp + 1) * ulp note |w| <= 1, |t| <= 1 */ error += 6; finalvalue = u + wn; finaln = wn; /* we have effectively divided by 2^3 -- todo use inline function */ fmpz_add_ui(n, n, 3); } } /* The accumulated arithmetic error */ mag_set_ui_2exp_si(arb_radref(z), error, -wprounded); /* Set the midpoint */ if (!minus_one) { inexact = _arf_set_mpn_fixed(arb_midref(z), finalvalue, finaln, wn, 0, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else { _arf_set_mpn_fixed(arb_midref(z), finalvalue, finaln, wn, 0, finaln * FLINT_BITS, ARB_RND); } arb_mul_2exp_fmpz(z, z, n); if (minus_one) arb_sub_ui(z, z, 1, prec); TMP_END; fmpz_clear(n); } } flint-3.1.3/src/arb/exp_arf_bb.c000066400000000000000000000204561461254215100164300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz_vec.h" #include "arb.h" /* Determine N such that the error is bounded by 2^-prec when summing the Taylor series of exp(x) up to term x^N inclusive. We choose an N with many trailing zeros to improve efficiency of the binary splitting. */ static slong bs_num_terms(slong mag, slong prec) { slong N; N = _arb_exp_taylor_bound(mag, prec); /* Convert from N exclusive to N inclusive. */ N--; if (N > 10000) while (N % 128 != 0) N++; if (N > 1000) while (N % 16 != 0) N++; if (N > 100) while (N % 2 != 0) N++; return N; } typedef struct { arb_ptr w; fmpz * u; slong * r; slong wp; } work_t; static void worker(slong iter, work_t * work) { slong mag, wp, N; flint_bitcnt_t Qexp[1]; fmpz_t T, Q; fmpz_init(T); fmpz_init(Q); wp = work->wp; /* Binary splitting (+1 fixed-point ulp truncation error). */ mag = fmpz_bits(work->u + iter) - work->r[iter]; N = bs_num_terms(mag, wp); _arb_exp_sum_bs_powtab(T, Q, Qexp, work->u + iter, work->r[iter], N); /* T = T / Q (+1 fixed-point ulp error). */ if (*Qexp >= wp) fmpz_tdiv_q_2exp(T, T, *Qexp - wp); else fmpz_mul_2exp(T, T, wp - *Qexp); arb_fmpz_divapprox(T, T, Q); /* T = 1 + T */ fmpz_one(Q); fmpz_mul_2exp(Q, Q, wp); fmpz_add(T, T, Q); /* Now T = exp(u) with at most 2 fixed-point ulp error. */ /* Set z = z * T. */ arf_set_fmpz(arb_midref(work->w + iter), T); arf_mul_2exp_si(arb_midref(work->w + iter), arb_midref(work->w + iter), -wp); mag_set_ui_2exp_si(arb_radref(work->w + iter), 2, -wp); fmpz_clear(T); fmpz_clear(Q); } typedef struct { arb_srcptr vec; slong prec; } pwork_t; static void pbasecase(arb_t res, slong a, slong b, pwork_t * work) { if (b - a == 0) { arb_one(res); } else if (b - a == 1) { arb_set(res, work->vec + a); } else if (b - a == 2) { arb_mul(res, work->vec + a, work->vec + a + 1, work->prec); } else if (b - a == 3) { arb_mul(res, work->vec + a, work->vec + a + 1, work->prec); arb_mul(res, res, work->vec + a + 2, work->prec); } else { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } } static void pmerge(arb_t res, const arb_t a, const arb_t b, pwork_t * work) { arb_mul(res, a, b, work->prec); } void _arb_vec_prod_bsplit_threaded(arb_t res, arb_srcptr vec, slong len, slong prec) { pwork_t work; work.vec = vec; work.prec = prec; flint_parallel_binary_splitting(res, (bsplit_basecase_func_t) pbasecase, (bsplit_merge_func_t) pmerge, sizeof(arb_struct), (bsplit_init_func_t) arb_init, (bsplit_clear_func_t) arb_clear, &work, 0, len, 3, -1, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); } void arb_exp_arf_bb(arb_t z, const arf_t x, slong prec, int minus_one) { slong k, bits, r, mag, q, wp, N; slong argred_bits, start_bits; slong num_threads; flint_bitcnt_t Qexp[1]; int inexact; fmpz_t t, u, T, Q; arb_t w; if (arf_is_zero(x)) { if (minus_one) arb_zero(z); else arb_one(z); return; } if (arf_is_special(x)) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } mag = arf_abs_bound_lt_2exp_si(x); /* We assume that this function only gets called with something reasonable as input (huge/tiny input will be handled by the main exp wrapper). */ if (mag > 200 || mag < -2 * prec - 100) { flint_throw(FLINT_ERROR, "arb_exp_arf_bb: unexpectedly large/small input\n"); } if (prec < 100000000) { argred_bits = 16; start_bits = 32; } else { argred_bits = 32; start_bits = 64; } /* Argument reduction: exp(x) -> exp(x/2^q). This improves efficiency of the first iteration in the bit-burst algorithm. */ q = FLINT_MAX(0, mag + argred_bits); /* Determine working precision. */ wp = prec + 10 + 2 * q + 2 * FLINT_BIT_COUNT(prec); if (minus_one && mag < 0) wp += (-mag); fmpz_init(t); fmpz_init(u); fmpz_init(Q); fmpz_init(T); arb_init(w); /* Convert x/2^q to a fixed-point number. */ inexact = arf_get_fmpz_fixed_si(t, x, -wp + q); /* Aliasing of z and x is safe now that only use t. */ /* Start with z = 1. */ arb_one(z); num_threads = flint_get_num_available_threads(); /* We have two ways to parallelize the BB algorithm: run the main loop serially and rely on parallel binary splitting, or compute all the exponentials in parallel. The latter is more efficient (empirically about 1.3x) but uses more memory, so we fall back on a serial main loop at high enough precision. */ if (num_threads == 1 || prec >= 1e9) { /* Bit-burst loop. */ for (bits = start_bits; !fmpz_is_zero(t); bits *= 2) { /* Extract bits. */ r = FLINT_MIN(bits, wp); fmpz_tdiv_q_2exp(u, t, wp - r); /* Binary splitting (+1 fixed-point ulp truncation error). */ mag = fmpz_bits(u) - r; N = bs_num_terms(mag, wp); _arb_exp_sum_bs_powtab(T, Q, Qexp, u, r, N); /* T = T / Q (+1 fixed-point ulp error). */ if (*Qexp >= wp) { fmpz_tdiv_q_2exp(T, T, *Qexp - wp); arb_fmpz_divapprox(T, T, Q); } else { fmpz_mul_2exp(T, T, wp - *Qexp); arb_fmpz_divapprox(T, T, Q); } /* T = 1 + T */ fmpz_one(Q); fmpz_mul_2exp(Q, Q, wp); fmpz_add(T, T, Q); /* Now T = exp(u) with at most 2 fixed-point ulp error. */ /* Set z = z * T. */ arf_set_fmpz(arb_midref(w), T); arf_mul_2exp_si(arb_midref(w), arb_midref(w), -wp); mag_set_ui_2exp_si(arb_radref(w), 2, -wp); arb_mul(z, z, w, wp); /* Remove used bits. */ fmpz_mul_2exp(u, u, wp - r); fmpz_sub(t, t, u); } } else { arb_ptr ws; fmpz * us; slong * rs; slong num = 0; ws = _arb_vec_init(FLINT_BITS); us = _fmpz_vec_init(FLINT_BITS); rs = flint_malloc(sizeof(slong) * FLINT_BITS); /* Bit-burst loop. */ for (bits = start_bits; !fmpz_is_zero(t); bits *= 2) { /* Extract bits. */ r = FLINT_MIN(bits, wp); fmpz_tdiv_q_2exp(u, t, wp - r); if (!fmpz_is_zero(u)) { fmpz_set(us + num, u); rs[num] = r; num++; } /* Remove used bits. */ fmpz_mul_2exp(u, u, wp - r); fmpz_sub(t, t, u); } num_threads = FLINT_MIN(num_threads, num); num_threads = FLINT_MAX(num_threads, 1); /* todo: only allocate as many temporaries as threads, reducing memory */ { work_t work; work.w = ws; work.u = us; work.r = rs; work.wp = wp; flint_parallel_do((do_func_t) worker, &work, num, -1, FLINT_PARALLEL_STRIDED); } /* Parallel product. */ _arb_vec_prod_bsplit_threaded(z, ws, num, wp); _arb_vec_clear(ws, FLINT_BITS); _fmpz_vec_clear(us, FLINT_BITS); flint_free(rs); } /* We have exp(x + eps) - exp(x) < 2*eps (by assumption that the argument reduction is large enough). */ if (inexact) arb_add_error_2exp_si(z, -wp + 1); fmpz_clear(t); fmpz_clear(u); fmpz_clear(Q); fmpz_clear(T); arb_clear(w); /* exp(x) = exp(x/2^q)^(2^q) */ for (k = 0; k < q; k++) arb_mul(z, z, z, wp); if (minus_one) arb_sub_ui(z, z, 1, wp); arb_set_round(z, z, prec); } flint-3.1.3/src/arb/exp_arf_rs_generic.c000066400000000000000000000104531461254215100201610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif void arb_exp_taylor_sum_rs_generic(arb_t res, const arb_t x, slong N, slong prec) { arb_t s; mag_t err; arb_init(s); mag_init(err); arb_get_mag(err, x); mag_exp_tail(err, err, N); if (N <= 2) { if (N == 0) arb_zero(res); else if (N == 1) arb_one(res); else if (N == 2) arb_add_ui(res, x, 1, prec); arb_add_error_mag(res, err); } else { arb_ptr tpow; slong j, k, m, M, tp, xmag; mp_limb_t c, d, chi, clo; xmag = arf_abs_bound_lt_2exp_si(arb_midref(x)); /* Convert to order as a series in x^2. */ M = N / 2; m = n_sqrt(M); /* not intended (and not 32-bit safe...) */ if (M > 30000) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } tpow = _arb_vec_init(m + 2); arb_mul(s, x, x, prec); _arb_vec_set_powers(tpow, s, m + 1, prec); arb_zero(s); c = 1; j = (M - 1) % m; for (k = M - 1; k >= 0; k--) { tp = prec - 2 * k * (-xmag) + 10; tp = FLINT_MAX(tp, 2); tp = FLINT_MIN(tp, prec); d = (2 * k) * (2 * k + 1); if (k != 0) { umul_ppmm(chi, clo, c, d); if (chi != 0) { arb_div_ui(s, s, c, tp); c = 1; } } arb_addmul_ui(s, tpow + j, c, tp); if (k != 0) { c *= d; if (j == 0) { if (tp > 300000) { arb_set_round(tpow + m + 1, tpow + m, tp); arb_mul(s, s, tpow + m + 1, tp); } else { arb_mul(s, s, tpow + m, tp); } j = m - 1; } else { j--; } } } arb_div_ui(s, s, c, prec); arb_mul(s, s, x, prec); arb_add_error_mag(s, err); /* exp = sinh + sqrt(1 + sinh^2) */ arb_mul(res, s, s, prec); arb_add_ui(res, res, 1, prec); arb_sqrt(res, res, prec); arb_add(res, res, s, prec); _arb_vec_clear(tpow, m + 2); } mag_clear(err); arb_clear(s); } void arb_exp_arf_rs_generic(arb_t res, const arf_t x, slong prec, int minus_one) { slong q, xmag, wp, k, N; arb_t t; if (arf_is_zero(x)) { if (minus_one) arb_zero(res); else arb_one(res); return; } xmag = arf_abs_bound_lt_2exp_si(x); /* 1 + x + O(x^2) */ /* We don't really need to worry too much about degenerate input because the main exp function already takes care of it. */ if (xmag < -prec - 4) { mag_t t; mag_init(t); arf_get_mag(t, x); mag_exp_tail(t, t, 2); arb_set_arf(res, x); arb_add_ui(res, res, minus_one ? 0 : 1, prec); arb_add_error_mag(res, t); mag_clear(t); return; } arb_init(t); /* generic tuning value */ q = 4.5 * pow(prec, 0.2); q = FLINT_MAX(q, 6); /* adjust to magnitude */ q = FLINT_MAX(0, xmag + q); wp = prec + 10 + 2 * q + 2 * FLINT_BIT_COUNT(prec); if (minus_one && xmag < 0) wp += (-xmag); /* t = x/2^q */ arf_mul_2exp_si(arb_midref(t), x, -q); N = _arb_exp_taylor_bound(xmag - q, wp); arb_exp_taylor_sum_rs_generic(t, t, N, wp); /* exp(x) = exp(x/2^q)^(2^q) */ for (k = 0; k < q; k++) arb_mul(t, t, t, wp); if (minus_one) arb_sub_ui(t, t, 1, wp); arb_set_round(res, t, prec); arb_clear(t); } flint-3.1.3/src/arb/exp_sum_bs_powtab.c000066400000000000000000000174201461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2014, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz_vec.h" #include "arb.h" /* When splitting [a,b) into [a,m), [m,b), we need the power x^(m-a). This function computes all the exponents (m-a) that can appear when doing binary splitting with the top-level interval [0,n), assuming that we always choose m = a + floor((b-a)/2), and that the case b-a = 2 is inlined. */ slong _arb_compute_bs_exponents(slong * tab, slong n) { slong a, b, aa, /* ab, */ ba, bb, length; if (n == 1) { tab[0] = 1; return 1; } if (n == 2 || n == 3 || n == 4) { tab[0] = 1; tab[1] = 2; return 2; } if (n == 6) { tab[0] = 1; tab[1] = 2; tab[2] = 3; return 3; } /* first binary splitting call */ a = n >> 1; b = n - (n >> 1); tab[0] = a; length = 1; for (;;) { /* split a -> aa, ab and b -> ba, bb */ aa = a >> 1; /* ab = a - aa; */ ba = b >> 1; bb = b - ba; tab[length] = ba; length++; /* at length 3, we split into 2, 1 (and maybe also 2, 2) */ if (ba == 3) { tab[length] = 2; tab[length + 1] = 1; length += 2; break; } /* stop if we have reached 1, or if at 2 and the length is a power of 2 (in which case we never reach 1) */ if (ba == 1 || (ba == 2 && (n & (n-1)) == 0)) break; /* if left and right lengths are different, also add the right length */ if (aa != ba && aa != 1) { tab[length] = aa; length++; } a = aa; b = bb; } /* we always include x^1 in the table, even if the binary splitting terminates at step length 2 */ if (tab[length-1] != 1) { tab[length] = 1; length++; } /* reverse table */ for (a = 0; a < length / 2; a++) { b = tab[a]; tab[a] = tab[length - a - 1]; tab[length - a - 1] = b; } return length; } /* just do a linear search */ slong _arb_get_exp_pos(const slong * tab, slong step) { slong i; for (i = 0; ; i++) { if (tab[i] == step) return i; if (tab[i] == 0) { flint_throw(FLINT_ERROR, "ERROR: exponent %wd not in table!\n", step); } } } static void bsplit(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const slong * xexp, const fmpz * xpow, flint_bitcnt_t r, slong a, slong b) { int cc; if (b - a == 1) { cc = flint_ctz((a + 1)); fmpz_set_ui(Q, (a + 1) >> cc); *Qexp = r + cc; fmpz_set(T, xpow); } else if (b - a == 2) { fmpz_mul_ui(T, xpow, a + 2); fmpz_mul_2exp(T, T, r); fmpz_add(T, T, xpow + 1); cc = flint_ctz((a + 2)); fmpz_set_ui(Q, (a + 2) >> cc); *Qexp = r + cc; cc = flint_ctz((a + 1)); fmpz_mul_ui(Q, Q, (a + 1) >> cc); *Qexp += r + cc; } else { slong step, m, i; flint_bitcnt_t Q2exp[1]; fmpz_t Q2, T2; step = (b - a) / 2; m = a + step; fmpz_init(Q2); fmpz_init(T2); bsplit(T, Q, Qexp, xexp, xpow, r, a, m); bsplit(T2, Q2, Q2exp, xexp, xpow, r, m, b); fmpz_mul(T, T, Q2); fmpz_mul_2exp(T, T, *Q2exp); /* find x^step in table */ i = _arb_get_exp_pos(xexp, step); fmpz_addmul(T, xpow + i, T2); fmpz_clear(T2); fmpz_mul(Q, Q, Q2); *Qexp = *Qexp + *Q2exp; fmpz_clear(Q2); } } typedef struct { fmpz_t T; fmpz_t Q; flint_bitcnt_t Qexp; slong a; slong b; } exp_bsplit_struct; typedef exp_bsplit_struct exp_bsplit_t[1]; static void exp_bsplit_init(exp_bsplit_t x, void * args) { fmpz_init(x->T); fmpz_init(x->Q); } static void exp_bsplit_clear(exp_bsplit_t x, void * args) { fmpz_clear(x->T); fmpz_clear(x->Q); } typedef struct { const slong * xexp; const fmpz * xpow; flint_bitcnt_t r; } exp_bsplit_args; static void exp_bsplit_merge(exp_bsplit_t res, exp_bsplit_t L, exp_bsplit_t R, exp_bsplit_args * args) { slong i, step; slong a = L->a; slong b = R->b; step = (b - a) / 2; fmpz_mul(res->T, L->T, R->Q); fmpz_mul_2exp(res->T, res->T, R->Qexp); /* find x^step in table */ i = _arb_get_exp_pos(args->xexp, step); fmpz_addmul(res->T, args->xpow + i, R->T); fmpz_zero(R->T); fmpz_mul(res->Q, L->Q, R->Q); res->Qexp = L->Qexp + R->Qexp; res->a = L->a; /* actually a no-op because of aliasing */ res->b = R->b; } static void exp_bsplit_basecase(exp_bsplit_t res, slong a, slong b, exp_bsplit_args * args) { bsplit(res->T, res->Q, &(res->Qexp), args->xexp, args->xpow, args->r, a, b); res->a = a; res->b = b; } static void bsplit2(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const slong * xexp, const fmpz * xpow, flint_bitcnt_t r, slong a, slong b) { exp_bsplit_t s; exp_bsplit_args args; slong max_threads; slong prec_hint; args.xexp = xexp; args.xpow = xpow; args.r = r; *s->T = *T; *s->Q = *Q; max_threads = flint_get_num_threads(); prec_hint = 2 * (b - a) * FLINT_MAX(r, 1); if (prec_hint < 30000) max_threads = 1; else if (prec_hint < 1000000) max_threads = FLINT_MIN(2, max_threads); else if (prec_hint < 5000000) max_threads = FLINT_MIN(4, max_threads); else max_threads = FLINT_MIN(8, max_threads); flint_parallel_binary_splitting(s, (bsplit_basecase_func_t) exp_bsplit_basecase, (bsplit_merge_func_t) exp_bsplit_merge, sizeof(exp_bsplit_struct), (bsplit_init_func_t) exp_bsplit_init, (bsplit_clear_func_t) exp_bsplit_clear, &args, a, b, 4, max_threads, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); *T = *s->T; *Q = *s->Q; *Qexp = s->Qexp; } void _arb_exp_sum_bs_powtab(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) { slong * xexp; slong length, i; fmpz * xpow; /* compute the powers of x that will appear (at least x^1) */ xexp = flint_calloc(2 * FLINT_BITS, sizeof(slong)); length = _arb_compute_bs_exponents(xexp, N); xpow = _fmpz_vec_init(length); xpow[0] = *x; /* create shallow copy of x */ /* build x^i table */ for (i = 1; i < length; i++) { if (xexp[i] == 2 * xexp[i-1]) { fmpz_mul(xpow + i, xpow + i - 1, xpow + i - 1); } else if (xexp[i] == 2 * xexp[i-2]) /* prefer squaring if possible */ { fmpz_mul(xpow + i, xpow + i - 2, xpow + i - 2); } else if (xexp[i] == 2 * xexp[i-1] + 1) { fmpz_mul(xpow + i, xpow + i - 1, xpow + i - 1); fmpz_mul(xpow + i, xpow + i, xpow); } else if (xexp[i] == 2 * xexp[i-2] + 1) { fmpz_mul(xpow + i, xpow + i - 2, xpow + i - 2); fmpz_mul(xpow + i, xpow + i, xpow); } else { flint_throw(FLINT_ERROR, "power table has the wrong structure!\n"); } } if (flint_get_num_available_threads() == 1) bsplit(T, Q, Qexp, xexp, xpow, r, 0, N); else bsplit2(T, Q, Qexp, xexp, xpow, r, 0, N); fmpz_init(xpow + 0); /* don't free the shallow copy of x */ _fmpz_vec_clear(xpow, length); flint_free(xexp); } flint-3.1.3/src/arb/exp_sum_bs_simple.c000066400000000000000000000026651461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void bsplit(fmpz_t P, fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, slong r, slong a, slong b, int cont) { if (b - a == 1) { fmpz_set(P, x); fmpz_set_ui(Q, a + 1); *Qexp = r; fmpz_set(T, P); } else { slong m; flint_bitcnt_t Q2exp[1]; fmpz_t P2, Q2, T2; m = a + (b - a) / 2; fmpz_init(P2); fmpz_init(Q2); fmpz_init(T2); bsplit(P, T, Q, Qexp, x, r, a, m, 1); bsplit(P2, T2, Q2, Q2exp, x, r, m, b, 1); fmpz_mul(T, T, Q2); fmpz_mul_2exp(T, T, *Q2exp); fmpz_addmul(T, P, T2); fmpz_mul(Q, Q, Q2); *Qexp = *Qexp + *Q2exp; if (cont) fmpz_mul(P, P, P2); fmpz_clear(P2); fmpz_clear(Q2); fmpz_clear(T2); } } void _arb_exp_sum_bs_simple(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) { fmpz_t P; fmpz_init(P); bsplit(P, T, Q, Qexp, x, r, 0, N, 0); fmpz_clear(P); } flint-3.1.3/src/arb/exp_tab.c000066400000000000000000003203461461254215100157640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #if FLINT_BITS == 64 #define Z2(a,b) UWORD(0x ## b ## a) #else #define Z2(a,b) UWORD(0x ## a), UWORD(0x ## b) #endif #define Z8(a,b,c,d,e,f,g,h) Z2(a,b), Z2(c,d), Z2(e,f), Z2(g,h), const mp_limb_t arb_exp_tab1[ARB_EXP_TAB1_NUM][ARB_EXP_TAB1_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,80000000) },{ Z8(ff554e0d,eaf5c2fa,5c67ff57,abee91b9,020d348f,e82f3725,fafa1201,575bd293) Z8(d0372a42,1eb90105,8676076f,de780649,3554f733,45152169,5aabbbe9,80804015) },{ Z8(7539dd57,e5a39b83,5319c8f5,32a6326f,421fa89a,c54f1230,b416c333,da17fb32) Z8(c0482614,80ab44b0,ed70fa46,37b1c91e,39b44e99,1931c15e,00222d86,810100ab) },{ Z8(e184c3b3,c58f8dbc,34da4bae,bbc6f344,767a5698,39c05a2d,27d75440,28927bad) Z8(2c5d5be9,a747371f,0ac8a0c5,b2d88edc,773b6516,6ca08d0e,b103b504,81824241) },{ Z8(c5f3a3dc,73f545e0,3415b128,87330d08,9ab33afe,5993a7fc,8b7f018c,67380747) Z8(5ec2eb5c,835210e4,a313b765,b790820f,822735a2,5c3259f4,aef1c8bd,8204055a) },{ Z8(2aff18d3,8a31a8cd,bcf94f83,66a19fd1,42d9b6fe,41da9652,16a3dd96,1a75fc21) Z8(12a99dec,c67acf4e,181af4d3,277b532d,6f1fc743,6d0fbdc3,bd1036e1,82864a77) },{ Z8(31ae8d90,71b06712,3048b19c,41ae308a,8b915b5a,6e3f14ae,271261f8,88ab6a8b) Z8(c8bf2dd3,173a4446,46104e0a,42bd2733,4adbb70d,2b2cebaf,2086e8a7,8309121b) },{ Z8(b08d6622,76f0ab8c,58614061,045cf4ca,0746e9f4,dab69d5e,fa9674f0,8a9a605e) Z8(0ba1fc43,a77c428f,30830a66,3f64c60c,cf3484c2,ed9945c8,a104277d,838c5cc7) },{ Z8(fa5e04c3,15a1b025,58c8cf5e,600ffa90,36da5eed,ab7e698e,f9e9a1cc,5c7720f2) Z8(fb0c3076,89fef98b,92234035,55280bc2,d4064bd3,05e841d5,893f64c7,84102b00) },{ Z8(314b6b0b,17b00bf5,348c1c57,d271ab7d,078067ed,fa493689,52d00e27,e9f872a7) Z8(762265a9,3720d66e,93c2ba38,5d17bac3,d6fbe6b7,2277b709,a77c8498,84947d49) },{ Z8(a6eee1fe,4f2e618a,0226a8f9,f2486800,eff57f8e,e7c949d8,a10f6f11,4bbc4e57) Z8(c20d2769,76b3175a,ca7bc0b3,9fafcc07,cd8d8884,2e60e7ca,4e0fac0a,85195427) },{ Z8(16a47ce9,2eca70dd,e5764424,ff05f601,635e0cc2,23c7725c,f8f02447,1a1a8833) Z8(910f86ab,3c5dbada,098d739d,fc17f52c,90afe905,7d6e234f,53e19398,859eb01e) },{ Z8(65f03ae8,26407119,96d943f0,58531dfb,6e386d7b,b69f8894,731f1fee,ea9a7502) Z8(369fd391,b283022a,043be481,ed3ac5a3,2594af50,967f31eb,14f45e14,862491b4) },{ Z8(b4f0d23e,e311637b,bcd99b4e,a18be517,5e3be3ee,6a86a3c1,c8a332d5,ca7a8250) Z8(c230356f,e1e4cf30,c1f52eda,622fd1b2,54712710,735b6853,72e8f4b3,86aaf96e) },{ Z8(09376634,f971d411,543de67f,26853de0,f9928040,c4230144,d85cd08a,4db3ffb7) Z8(4e94081c,7fe48459,68805db6,7d8b029e,1a0e0eae,9209beb6,d584e8b9,8731e7d3) },{ Z8(1ae82c51,3b513f8f,b8290d66,5c8bc828,44537ddb,34c177b5,a4a9bef4,c9cf2a83) Z8(0f8c48ac,a744e4ad,011547f0,ef77ad79,168701d1,b966251a,2b38db4b,87b95d6b) },{ Z8(c3ec7771,94d3ccf6,c5428436,44a1b430,410caf75,56f32f75,25d7aa18,d2f4ee1c) Z8(ef3fcf23,624bec06,c3e1237c,dd14aaba,12e4d4a8,d8d00cf1,e9a76bea,88415abb) },{ Z8(ad201cba,c49b7467,b12d3cff,78069023,19b293f5,4db3c62e,5f44189a,67cd64ec) Z8(fc907294,01e1487f,bc51f747,435c4a97,d9bcd368,f1794615,0e2cae21,88c9e04e) },{ Z8(6f450efa,c116b6e5,74dd3a44,cca4c182,091da1a2,82551654,3e65c65a,ad53eca0) Z8(74774a1b,fe2d70f4,ff6a7549,0d22651b,1e4256f6,7f0e6253,1e6626ed,8952eeaa) },{ Z8(9d4df7d7,4e574c75,6ace1e5e,f042a379,87e05013,a19ff4aa,0f7388c7,97a469e8) Z8(fea4349a,e01bcb46,31b11be1,ab7a48af,296927f1,5d2b5d3a,28bb5264,89dc8659) },{ Z8(45827151,eb233b9f,eae73603,eb8227f1,2e4df3ca,ff06158c,1283deec,a0867b97) Z8(8c3d07ab,c4c607fb,252590b5,3204d2b5,13ce2f05,af50ce37,c4e6b22a,8a66a7e4) },{ Z8(7b6f9498,a77871cb,c7852dba,944762a9,a8660859,e16afa51,0e7d6158,d5cc78d5) Z8(01f1c868,59c88bc8,15d3244e,4630d03b,089acf68,d9d7f8b7,147f6537,8af153d7) },{ Z8(bcff94a1,ecce7623,4ad6897f,17b55cd9,e25e4701,3bf5f538,c3d5aece,096ae22d) Z8(7d2ef735,13e29881,a01809dc,f6e2ba5f,82cae079,23b72aa5,c3834979,8b7c8aba) },{ Z8(f6ee0cee,17a6b464,9439ddb4,c1e11367,99080f5f,9736e366,27094655,03a51f82) Z8(628f06e9,6956229c,4767396f,1a3777e4,d3079a98,22c48dd2,08e1a7db,8c084d1b) },{ Z8(754c3938,74e5fa46,a3e485cd,73e7aae1,ca779092,27bd225f,2e1dfd17,f7da756c) Z8(f503d876,04261d08,ea6c3274,f3da3da8,40755e14,9e8c66dd,a7066b44,8c949b83) },{ Z8(3e4aefad,273c6da4,faa8f661,ae7879f5,1fd1563f,00f3c053,2f1c87bd,165e8af7) Z8(cf420806,78113051,ea50abec,90b2581c,a3ee97c2,20c13e5d,ec65e30e,8d217680) },{ Z8(0a32b41d,4539d082,52aca6e8,8099986f,71474f4f,e9ec3d99,a5004eb6,1ca3fda5) Z8(ced96c90,1a6ec938,d9e848ce,956773bc,00eedaab,f5c92a52,b4091181,8daede9f) },{ Z8(55c90bc5,41896020,fc1c67ef,7959583b,a49ae8a4,b4dd8211,59b34efb,3a95d5dd) Z8(1d84535d,c29e27c5,b1707447,5c5e1c92,1ebff081,ebf3e989,661a86f0,8e3cd46d) },{ Z8(e1ce068b,eb9216a2,ac1983f1,ad8bffb6,441648fe,f480be00,7bfe9766,705792c8) Z8(c4a424c8,f0946cb9,6a39122f,7629b2da,06c3015f,ac7a4d32,f873c9e8,8ecb5877) },{ Z8(0e9e3fa5,1a51d8f4,4c56a1f9,9d172707,b0dbab91,f76bd471,c90d28e9,884d09ab) Z8(e52992c8,68922f7d,25f11282,9701baa4,6808fb4e,1689123e,ef2b4d19,8f5a6b4d) },{ Z8(4b3208f7,b04edb2a,93ec95f7,3168b6e9,dcd7c570,000aab51,20b212a2,b4da6405) Z8(48a7a6d6,83b4124f,8eb396a0,c57d8298,e625fbf5,92485a20,5d22f376,8fea0d7e) },{ Z8(827a03ef,c230bac2,2c4330b7,3025da31,65c99270,7fabbc3a,a1605373,9ff86ee1) Z8(b3009532,21637b8e,330b7a67,6b488058,62ec47c2,e00df647,e4972327,907a3f98) },{ Z8(12b5ae61,0a584fe3,ef3e2399,178072e9,2ce1e182,4ef19144,3a8af5bb,bc3b803a) Z8(8118966c,bbb5b0f2,54ab82be,3c5f8642,7035c6a1,76b441c2,b7ae67ce,910b022d) },{ Z8(7afef92e,647f369d,7f9733ad,0cced069,6823001d,9c5901b3,83ed1e44,e2a422ac) Z8(50bbe330,83e9c1c6,c38f6f71,7f068e1b,dc0e7861,1369dfa1,9909a4b9,919c55cd) },{ Z8(16306395,56ad1e1c,b994ac18,18a8ef2d,c1d2a98b,a4794333,7f783bf5,b286404a) Z8(46779a79,be9e8a03,8c6d328f,bbebe950,5d77d732,ad38f205,dc54d790,922e3b09) },{ Z8(a4e8f4ce,71ebfa13,298ff3dc,e974b9d0,3de2fc9c,e0a935be,e51fa743,4eb040f3) Z8(3127f9b0,02421d87,dfae293a,0a70cd55,1411f170,8efecda2,66d86c10,92c0b274) },{ Z8(804c447e,d3ba6d91,0539ddb4,735d22d7,a7e1c9d0,14c5c9eb,1238e6a3,daba3c05) Z8(6f959d26,77d59047,6356c038,6763c7e8,4d070592,eb986004,b00b215a,9353bc9f) },{ Z8(c77449f0,38db74d5,a5f626bd,a5e257df,4cd4abcc,0183ea35,cf30482f,2251c46d) Z8(eb8d48c3,bfda9858,1fa50b25,d8069a7a,123ea059,d1a4052c,c224817b,93e75a1e) },{ Z8(169e5bb7,491ab6f9,fbf113a9,0af845a0,a903e47f,097985c0,0bfadb52,bd2a6016) Z8(b3113bb9,2a497a4a,fac69782,8a84bd5b,0097199a,f667f4e7,3aafebac,947b8b85) },{ Z8(a1517ce4,da86c052,47a67561,127cfaa5,97acb08f,f0a615e4,b0bd87e1,7fd15f21) Z8(64c595de,523cc7ad,d839cdfc,7f38f6e0,36a250bc,622d53a9,4b2031ed,95105167) },{ Z8(06557e3f,751a929f,8482b781,38f8d82d,5dbb18d1,fae289c7,0dba2b34,5ed19617) Z8(9bcb9778,d23a6bec,30f5450e,32a17622,cebec9a5,9bb3e062,b963ca80,95a5ac59) },{ Z8(54bc32de,dca7cbd1,fa03b236,5742f008,3db0b97e,1139e905,34b639ff,1a3ecb2f) Z8(52322710,c73ea90f,a4c2e759,8fff291b,3f6365b2,8449c43b,e07995e9,963b9cf1) },{ Z8(e1836a48,4916fbf3,407b6cd6,bd3577d4,06021fe6,9bc4fd30,b8d6f8c6,129d3a7e) Z8(f5557d0f,a2e2151a,801f08da,c3cd4cba,c2d11ea9,aa8ec61f,b10639f5,96d223c5) },{ Z8(9f929cb0,6dcac6ad,8e9f7724,12a2ab4b,908a440d,873d4b3f,3095135d,fc8afd92) Z8(f9d0e418,f1fe1c91,0381d908,ba2d8fc6,557ecedf,6efaa729,b1ea126e,9769416b) },{ Z8(16d41b76,5c56ee07,28a91c78,043e61f8,db2401d3,1d97ef3c,deb5ff7e,b6576877) Z8(35d5059d,d53a4794,764049f1,7458999f,7ffaabe3,eae44b1a,00d7b805,9800f67b) },{ Z8(be072c3c,ac83c46d,959ce10f,43441db1,aa0c6342,ba62c3b0,18b5bd1a,876f4af1) Z8(6eddc485,16620f72,f2e0ce50,90cf4044,e85fca95,21031f3a,52eb1e16,9899438b) },{ Z8(817cb6c9,000d8da1,3cd8ceda,19c9d6ec,db5aafbf,5e9350cd,facf6daf,f14adb6e) Z8(ca068ef0,7c50e649,8eb31936,1138b433,6c669095,953687e2,f54147c9,99322934) },{ Z8(7f8681bd,a190226b,ab4cd129,f7ea201c,4e5c013b,f7875ad0,99180921,1037c2d5) Z8(ac49b2cd,e784b424,f946e585,09873a27,aa22abbf,00c890e9,cd909545,99cba810) },{ Z8(87dd346f,ca85cf4b,24f1a452,34a88b53,1f7f1004,106e57b6,b021cf84,c73b9006) Z8(f1746808,230db4ad,8982478c,84735853,e33249a2,7062465b,5ac1a96a,9a65c0b8) },{ Z8(7c356e5b,69f8fa96,61870a99,0218d591,c193a385,1f1178c0,72e52501,1838941b) Z8(8f3d9be3,ed1e350d,89c119eb,9825b216,42499fc6,b181912f,b588e8ce,9b0073c5) },{ Z8(7fce8e79,aacb0e93,50656c98,684a0b97,71876338,802ef47b,3d49eb12,a5125c28) Z8(767e8763,fcbea459,701a030f,003bd2ff,40c3f393,8e72d00e,9100927a,9b9bc1d3) },{ Z8(8cb76164,fe6f09f1,9d9a6be9,30465f7b,4e482369,d3bc15e3,fae79f6a,3ec82d9c) Z8(14cc934d,bbf08610,aa8561dd,cb3f51e0,a2421e19,f19c3f91,3b437311,9c37ab7d) },{ Z8(bfaca379,4e6d26bc,9c5575c6,c0a76f8b,0db855fb,61d5796c,543e31d7,6f57b6c2) Z8(65ade5b9,b33ee3c5,4af46af4,a664dd10,1f83baa8,a34f397a,9e0832fb,9cd4315e) },{ Z8(5343d148,917c5a3c,784a2c1b,17208f4e,580c1157,b66197f0,84a4e5e5,f2be6712) Z8(e3e54163,d50253bf,5b379167,5e949a45,68a13ed6,f053f9e9,3f3d4024,9d715414) },{ Z8(17b4041f,64422b57,61e5daa6,8dbd78cb,1bebc754,6f402c61,f9500c8d,7df63d8d) Z8(131e9c0a,8f17dc02,3cde0202,49163414,55f56fbb,23008f4c,41a553fd,9e0f143b) },{ Z8(c35785e2,59c303e2,9062700a,dca43d16,12921e02,fe633e4e,2befee40,026a748a) Z8(87157ad4,47d49796,4632b2ec,26cb8d19,f105db8f,54e37937,65749645,9ead7271) },{ Z8(c19b29c7,6cfcc965,dd49750a,b76abdf7,0e8b6bdf,24273cf6,9a601d51,3db9cdea) Z8(bcef8461,23cf2474,10a259ca,abbb03b0,6028ab6b,bbdee020,08ee5d51,9f4c6f55) },{ Z8(84d3305f,1f0b6a6d,1b9ab692,283a8898,8cd868f5,679f512e,9254b255,82688a79) Z8(9158803a,f77aff77,f3e06dbe,71b89421,23395b71,3302d860,29038c5a,9fec0b85) },{ Z8(8081867d,b3a9f222,963b9eb0,63b978e2,04087ce0,1bccb9f8,c852f980,10d56a7f) Z8(5e1e3971,2b4e1fbe,1843151e,38c74d96,0b13df6a,5d846bf1,61f19078,a08c47a1) },{ Z8(d050d184,b70aa630,5254e219,c6a02b1f,65c7414f,1ffddbc0,0fe8bcda,99de91fa) Z8(b3c417d3,7d818b4e,2a2453a9,8fb39f57,3edd5bd3,60dccd8e,efe1fcf2,a12d2449) },{ Z8(57a2bf8c,ae521fcc,3830945e,e70f392e,33e630f2,f68ce37d,f707fb5d,07513ea2) Z8(3d7e35d1,c3227bed,e7ffff90,f4863dfc,2de9f407,d268bc65,af8ac771,a1cea21f) },{ Z8(a4c8c38e,a0b70a4e,c96b775a,8682fdab,cfb17d82,98e413c1,e7ef511d,5aa8151a) Z8(628d2955,703beeaf,7e431481,0575cf69,2d052d45,14cc604f,1ecf24c7,a270c1c4) },{ Z8(0d5d6bf1,51b067ac,be11f968,194e0145,85a1a23d,29a60e29,57b50061,87c1134a) Z8(58a206e7,3d297046,6c39d9a3,d806948c,002d9c0c,01ec63b3,5d6106da,a31383d9) },{ Z8(bc1b92f0,3f6626af,b238a27a,d6d622fb,f94f17a3,587ea5ae,575c9ede,057687ba) Z8(32bc5fcc,9083444b,ed3bd302,28b3b225,40fb8b02,5f7a6a31,2d633c69,a3b6e902) },{ Z8(a772363f,99ce2eb2,234be1dd,ec5ac020,1ae273a9,752a6f2f,2726e6e9,d7a1733b) Z8(ad3105f5,4c9f4678,25df1585,621c438b,d55f29a7,3de1db4d,f40c333b,a45af1e1) },{ Z8(219c31b6,e2541f1e,78978091,4fb7d16b,3c3ec0c6,a6c44f11,ad73099f,4c13f79d) Z8(94ca321c,833de234,dee34bcf,01bc6d00,67b0c196,03d2f032,ba495d61,a4ff9f1c) },{ Z8(bb2ef4f1,eaac6b84,4f9a068e,9564270e,ab604d4e,b560c83c,0ecea96e,70a5c5b3) Z8(36600374,fd5dd7d4,89c129a9,3a8c127e,0da79996,8bbdaddb,2d633a32,a5a4f157) },{ Z8(2514571f,3cd1cc8e,158ec169,7111606a,806a5823,c906bd59,4983c976,47b76cb9) Z8(d0348007,247af92a,5a45697e,1dee1c48,cf7ec6b3,5c459492,9fa203a4,a64ae936) },{ Z8(2ac7794e,bf9234a6,c6ed3c3d,ed3c2f22,a7d6b5e8,7fd92b25,9651497d,a76a206d) Z8(c80754aa,46dce364,269b57ef,185380d5,b893501c,a911f650,08f3009d,a6f18761) },{ Z8(57eef36a,63207fc0,0cdbe74d,06c43422,91691488,cf7b1dfe,aec4e707,cd984500) Z8(73d90acf,48332cb5,8c1d9119,ca532c8f,bd79f735,6e5ebba2,078e7cf3,a798cc7d) },{ Z8(a8d90bbd,67cd5b27,fcd6ad1d,cf92d187,e7089b51,4642889e,88956982,989e9224) Z8(80f0a7d3,bc45bfd6,4841384b,dd6a7226,f4c94954,9f568761,e09e67ae,a840b931) },{ Z8(691ce8ac,084ffa21,9b84ce94,ac1c87c9,5160d359,75b0eca6,10323324,42ac231f) Z8(1bb14c86,f107450a,a00346de,b2c85576,95fa5152,058a4a10,80e59844,a8e94e27) },{ Z8(c97ced2b,9252f7d8,54edb8e6,be3dd628,903aa117,6c601d5a,7b001fd3,478824b9) Z8(f71cf53f,37a84887,9bfa0a11,63232c3e,1b4fdb27,16cc14c9,7d67bb65,a9928c06) },{ Z8(3f6b1089,2699b00c,07f942ff,92eeb622,d9519893,2973ee69,0a611937,890715a8) Z8(a7224245,5a7d4043,7767446d,b4b68282,8d9a2790,ae4c0000,1411e811,aa3c7378) },{ Z8(7cb3e50a,e7c812c8,883f5cc1,2d14a344,c9ce881b,20a31109,56a1b834,4fac9001) Z8(b6b300bf,2c801f4a,9f7503d9,1869b661,7d3d3eef,3e16eba5,2c63dd93,aae70526) },{ Z8(77a829e1,b6c9c698,26b2c32d,f7d3ef20,5322ee94,b32bb84e,c8f8d16f,02791934) Z8(61469e7a,89bf3407,05d72e21,ff467b72,7a67af60,b700649a,5819eb0a,ab9241bb) },{ Z8(376d95d8,2a9a13cb,a16dc12a,9f52a62f,19664d65,d093d678,1a6ffd80,57b8dd22) Z8(66f6b422,e0a88471,229ddf14,c41ae021,936f2fa0,0e93c017,d3d7813b,ac3e29e2) },{ Z8(02d381e1,7b409c7f,bdea298b,b92c2681,c2eba22e,d4c21cda,fede402e,64081a64) Z8(8b5df900,db9d64ef,ad610a61,4cd9ad3e,4e7ea423,f4e529b5,87d26f3a,aceabe48) },{ Z8(9fc8f4c0,2b0942c6,11477286,06a69fa7,ad2fbc2c,058674cb,b1baf450,00afdae8) Z8(d5f92df3,02073979,07497710,128f49c2,758c0621,f7029f01,087ecab8,ad97ff99) },{ Z8(3b1568da,6f7e9a5d,0422f959,167c8c05,44050549,57afe5b6,9905d851,4114af9f) Z8(8d5baaec,5af88d9f,301f5a37,ca8dfde8,2d487eac,f6574e6a,973b847d,ae45ee81) },{ Z8(21a2a36d,f17c3a2c,3117f371,d3f72e33,0320c24c,777680b6,0137a911,355f7545) Z8(a117c185,f10196af,06799385,4ed96178,baa201e1,89923298,22ffa9da,aef48bb0) },{ Z8(650ade4a,233ec3c6,de91b76f,85497a73,e1872922,58f93e38,db66cc5e,1b76e360) Z8(99fcad3e,a9db5fee,4b4356ed,7da9479d,80234b29,888bbb41,490853ac,afa3d7d3) },{ Z8(7066a29d,0fdd6ba5,6c06e9f3,f7926909,4f515cce,67ec0ce6,becba3dd,75cf511f) Z8(7951b9c6,344f7ee5,800cffe5,7c495d57,235a5bdf,b23e8de5,558743aa,b053d39a) },{ Z8(53611bc7,a2a396ea,86af9e9e,9b7a80a0,71268ee6,ecab3f4d,6c1cb63f,6085ef16) Z8(c51a55f1,b98ba908,bdbbb9be,fe0dbfe0,ba5c4a72,0a2d9197,445230a5,b1047fb5) },{ Z8(8fad4018,5ae2d7b9,f7f18239,9be0d73f,29eea2f2,52f0b251,6e600e8b,d51cf072) Z8(6ec54367,ab07e2b9,6a080a77,e8761421,919e1311,39863ee4,c192c269,b1b5dcd4) },{ Z8(76c382d4,1fef9f82,34284925,05d482d1,10ede4e6,1b7cbda2,bc011498,99632470) Z8(c1a410fb,0939b1b4,3ca22fc7,afd98530,5f4349e6,eff23f44,2a773dfa,b267ebaa) },{ Z8(be33f83e,df21cc24,b91267f3,1081074f,15cd8019,8610cc02,a7392963,4258d268) Z8(9ae43567,8ba807f4,3714a029,1a0cfe1b,b3b75152,f05f75fc,8de3e2d0,b31aace7) },{ Z8(8bbf44c8,85983612,897cfac7,4001a9dd,fa35ca10,cac843d5,632d4d9f,1e0f0786) Z8(29bf636e,c469f099,42ceca33,46889a12,44f6b321,270a46f6,ad24f9c8,b3ce213f) },{ Z8(c179dd79,38b3f2dd,acf98ab1,0a586b38,672286d3,5a180e4e,54cdaf0f,d6388aaf) Z8(63a9bd88,d965ecd5,9de09776,5c9b5313,1bd3a598,d7cc0829,fca1967e,b4824965) },{ Z8(e44feb9a,29246239,a798a8ac,ff341603,bde555f2,aa4ac4ed,fbf75a6e,594e1852) Z8(f7f38c36,8c21801f,201a37d4,f799b2ba,d79b334d,a617b15f,a48f0bca,b537260e) },{ Z8(03490f37,65b6fb6e,b3bbc065,1aabcce5,b140e45f,c20d3cd7,5e9b2243,1a5c9215) Z8(55bf4cdc,c70dce6d,03e23eae,7bdce92f,62d0201f,eb29c6ae,81a513fc,b5ecb7ee) },{ Z8(6c71a6d4,f0b3ba83,0927b792,cfa1d2e1,8a3900ca,7044b6d9,d7c75558,d85d5858) Z8(1cbdeef5,0f9e0080,f8eaa509,86c75f59,8abd8d81,82bed727,25d2ada9,b6a2ffbb) },{ Z8(d2df0f17,e063510a,29437ad6,8e2c9000,225e25dd,8570a015,76551a36,43a0e83d) Z8(4d9524ae,8ae4888d,6e708486,ae77b3d8,5f9881bf,eb266eee,d8f3ada4,b759fe2a) },{ Z8(84008514,a05e484a,a4f17cc6,555450d6,757db26c,2a215c08,4a50b7b9,ba4012d9) Z8(f932ef45,4b298f88,392a69a3,0b27e884,a8612550,4abfbe36,998706ef,b811b3f4) },{ Z8(255bbad9,6ed11c6b,a413528c,3ec953a3,d3cbfe23,dbc114d1,4dbccc9e,5dda1e7d) Z8(b53b9a74,8bcd340c,5d073a51,4c8d3b25,7e43200b,a2da2b5a,1d65c942,b8ca21d0) },{ Z8(09654589,0db5b545,8c7f382a,0ff0ec27,1ef6fed7,e5558551,7b22393b,07544852) Z8(b6348584,0bbb2fb6,2345f6e2,eed6a4b6,5293db52,2e9742c7,d27ad6fb,b9834875) },{ Z8(293ea004,58100d98,00085c4b,a07fd77e,a8de6b88,7c2d5e61,fdb5ea59,e61ceb40) Z8(39d43d41,dc36bb78,9a5c6dbe,bc7d210f,849202e2,a3c5b2cd,df7b5311,ba3d289e) },{ Z8(ef137b40,279b1b9f,866ed6d1,14422eea,b334c658,96ef9504,b0f85f3b,f34797c0) Z8(4d472771,f8a43914,cfb4ac07,e07c46d5,8b43d3b0,c3bef2ad,249fc7df,baf7c305) },{ Z8(69ad3147,5d11f017,fc192280,8f7099bd,5fdf95c7,03341526,d64a50aa,3f674b05) Z8(f31b6828,d714ee7e,0d62d01b,77988166,94e852b1,631b93a6,3c5e0768,bbb31863) },{ Z8(1d6ed728,8b559e90,8dec75b6,d72618d8,65ad5298,305d7b9d,e28d3a60,d41f0180) Z8(c2b57ae5,780d7ac5,3fd2a29c,d40951a0,c73174c7,c895c116,7c23c5dc,bc6f2974) },{ Z8(2f4c05bb,92347f7f,e5a037f6,7c174c9f,e8513ce1,fef211a5,129a16b9,d32b2556) Z8(272a5656,f8cd4f6a,e4a416f4,bbe4009d,97ac8074,fdaedb70,f511ef19,bd2bf6f4) },{ Z8(a5438062,23df2039,b2b55b65,95074e6b,2c9a40d7,cfd3958a,7bc40647,da302301) Z8(3c25c931,09e080d4,06ec548b,c58ce2d6,7892eb7d,66a51b20,74b8b7d9,bde981a1) },{ Z8(0abb7e52,f73f5764,0b625d0a,d6efa031,0c8d5878,dc7d4a96,7c4925c4,fd3867e6) Z8(b71acd5b,9c553c28,cebbd558,d4f938bc,64a51aff,b2f97f72,85d46b50,bea7ca37) },{ Z8(92c74438,e7d09610,3fa58221,282465e7,12219033,2a1b41f5,1c64c1f8,ff7d43b9) Z8(93034bfe,6fb21abd,7f40ff4d,45422ccf,13425149,f435b5cb,710af5fd,bf66d175) },{ Z8(19c092f5,20a81315,8711865a,92f265e5,cf26b468,a2fa5bf5,34812af1,4e2c2982) Z8(a9e20ce6,90ca9c65,e1347404,65aa4053,44a5ecea,65cddb8c,3daa2e5d,c026981a) },{ Z8(83977506,9c00bc7d,ebc08671,dee69b9a,de44e88f,ca6c1ea3,672ec0db,1260dc86) Z8(272afe61,f2e1a444,44b59fdb,f63c0079,ead13e0a,2ee3bdea,b266dc47,c0e71ee5) },{ Z8(25028178,12037413,9ccb1c5b,63f490eb,5e9dd556,07573da0,c5837f50,1e1938dc) Z8(16dc603b,f98ed4cb,6d1ae251,093817ad,c6f57226,255944c2,561c7fb4,c1a86698) },{ Z8(03209717,f54802d2,aecbd04d,590e7f5b,fc2d0809,2c7df221,b2d2bb18,7a70191f) Z8(7c006bc0,91414899,ce7fed4a,a6ed6ae3,7ed294cc,5906c6b5,708dd7a9,c26a6ff3) },{ Z8(ea842a56,c052e96e,5fd77ccd,e87b8c0a,40ad1bc5,8c9037cf,a54d79b3,c870f8ad) Z8(ae299105,ef42b65a,3b6732a5,973c231f,52ad1394,ee10dd0a,0b262a0a,c32d3bb9) },{ Z8(423989dc,5d433de4,29d10404,655dfd06,bd089ac0,6bb5a8dc,b784184a,9aeaa364) Z8(e4a7f061,a56401d4,0c2ba283,c85f615a,635cf646,8e40acf6,f1bb4d17,c3f0caab) },{ Z8(a88dbe14,3925e22d,4c08737e,01c27c77,54e39070,27fccb82,50fbc815,90255f7d) Z8(0ebce480,5ba28aa2,237f4260,c3921216,4fd72211,7aea431b,b350734e,c4b51d8f) },{ Z8(9e450251,61d15c1c,dc0d05d5,ff20755a,f755fdbe,9c9bce2f,e1699c41,70ba4947) Z8(14d71b3d,6c746eae,383f2aa8,8141ffcb,91b2c2a2,0b574ecb,a2d9ba83,c57a3528) },{ Z8(437c3383,9fe16284,87de5042,dca079a4,03810d69,72c15684,c963000a,568ecb75) Z8(76b0c25c,3b076185,85527ef9,89bf1067,298885f7,26da076c,d8007ee1,c640123b) },{ Z8(151d2ddf,0a8e114c,cc3c2a74,b13cb635,d3ccef25,7ae5552d,8f55ce41,1321420e) Z8(6c72fdcc,2dfb9c08,0455c310,05155289,6baaabd4,0d9d1247,2fe872a7,c706b58f) },{ Z8(d5a7b8e8,3bbd8b4b,2214cd3a,43680dbf,557b21fb,3a339f99,17becf72,1b970557) Z8(d972e9d4,9838fb2a,67d26a4c,dc7cadf3,2fec566b,87fa9e46,4df57b59,c7ce1fe9) },{ Z8(f5435eee,fde1152c,e5596792,319a3ade,e329f528,f3fc39d7,792c15e3,5e12a3b0) Z8(6582ecf2,bc54ce32,67c1b712,c6c05fbf,bb81f492,599f6200,9c925538,c8965211) },{ Z8(e913bbd9,f54fe18c,cb7e4ad4,a807353e,4d5452b6,f2f6fe4b,993fe5a7,f9fefdef) Z8(e44ba29f,b393e307,eab2bd1f,8c19dc51,f9e4fa85,9bfe7ce9,4df7fdb9,c95f4cd0) },{ Z8(5667fb6c,6d21a0d6,c54c352c,c5260037,547abbfe,232e0da3,32576260,fb3baf37) Z8(92db93c5,6e9b22ab,bd9f7b87,6f0f2e74,65e90818,6aa2343e,5cf5e5d3,ca2910ee) },{ Z8(c57bef96,54de87bb,2052188b,7a330b85,3bc84734,9ab35c73,6d59fed7,dca7c99f) Z8(606a12ca,a8bf2b0a,b22a658b,ced25507,6754c87e,13b3e6e3,8dbaecdc,caf39f35) },{ Z8(5c7c1499,f2175128,b346a805,f9062eea,2fee8a52,df560f89,9993625f,2bb5dc26) Z8(d3a18680,a6301f3d,aed07ede,a504e461,567f34e6,c7ac2852,6e9f24c9,cbbef870) },{ Z8(5966214d,8a064fcd,f110f4ea,9fad9313,9b3b39b1,9323c576,2124bce1,46bc0986) Z8(a95d0bfe,e6ff9d1a,a996a9b9,54110fd9,74501497,8c7b829a,58ee609b,cc8b1d6a) },{ Z8(07a18560,c3ef438c,37565596,1c58ae4d,8fd3518e,a80aec8e,f238fa41,285141af) Z8(2ef8594b,cf0e9eb2,814e8f01,10974eb3,9248af3d,02a5b3d6,71b38db6,cd580eef) },{ Z8(2a8c2876,45019444,2adbebf2,53ba4954,ff8cd094,48f8284f,c5b98d99,2d30379f) Z8(1894f13c,4d189b4b,acc0a03b,ad33b8eb,4911dd65,55bd1e4f,aa84d8ff,ce25cdcc) },{ Z8(5bc36a9f,a874ce15,3a2c3bfd,02df602a,3d883ed1,b2e00161,7fa54fb2,563dc448) Z8(fef27101,0d5e303f,906a6f06,40c5d596,683cc396,7d6b5edd,c250a086,cef45acf) },{ Z8(711bea89,8404537b,1915acda,85fa2772,eb0f9700,76b4e01d,b19cc4de,3114031b) Z8(a1a512b4,0ffc163e,78c9882c,ee329dc2,0cc0f4e8,c0bf5eb9,462b3282,cfc3b6c7) },{ Z8(b0e2dcec,331084dd,1a094645,4eda5811,bad48876,bd2934dc,3ee5134f,6994dd65) Z8(a40efc98,06f83937,8809cb09,4b966d51,f7f1dbb5,3ad18943,921d5a79,d093e282) },{ Z8(622ab504,8708889e,9fe8f468,f393e2b2,2bf84aac,06f7b439,fdd4fcb3,0e443d49) Z8(3e8ea209,f911e058,8ba8f1c1,313b9041,baa4f7c3,edf4e0e1,d1f3bd56,d164ded1) },{ Z8(8e469c5f,b7b55c63,f4034825,b093d0f9,33c1b323,9625d23f,c09b8904,75d96488) Z8(a29020e5,42809947,9e14fbe2,b479f315,33c49361,c1a04dbc,020f054e,d236ac86) },{ Z8(15b12f49,ae19ba80,7b30f91d,a4f6acc6,cb8acc8b,9f376dfb,d4891710,177ab93c) Z8(31b3f966,e225fe48,0985a3ac,fb28f8b6,6f99fcd8,96ff7d5b,f034de4b,d3094c70) },{ Z8(4c856c5b,c45abd1b,3e4cc7b3,9f296296,827726a4,e7f0620e,29cfed99,570d38f2) Z8(586d2d29,a2d24860,9b15bb7e,4ab78332,330ffbb1,70aed201,3c61c3c7,d3dcbf65) },{ Z8(a14f9d6a,40af76b3,515a0721,3ff55e30,759d6670,d619ffb6,67792471,afecebe6) Z8(6df80c69,b7f73291,7632f559,fc19a230,a5750dbe,7b8b0556,599ba0d9,d4b10636) },{ Z8(7072207b,d5c66a4d,3f2d55f5,e8d9a37e,e43bfe85,196dc33e,fcb13687,f08ab0bc) Z8(7adacc42,5d4fc5e1,9fa9ac90,127b6b1e,d1ee3708,98b41492,8ec5434d,d58621b8) },{ Z8(a0b8389b,e3207f39,c24cb421,281ff827,7ac3d886,572605d0,4546c334,7b11f3dc) Z8(08669b56,87ffa2a7,87d1bd8b,2cd600ba,23f3b4e3,dbec9f0a,f772a298,d65c12c0) },{ Z8(445257e5,76d9efd9,dffaef61,d8f2f8b5,8fc0be5d,ced4f11c,6c5f3e88,56c3922a) Z8(8dd82973,59b92b63,f65578d4,ca749d1e,34383c6f,455be61b,84bdfb7f,d732da25) },{ Z8(835536d5,7fd2073b,17e535c4,4ef89b06,d68462e7,c2fb173e,65dff318,a2e069e3) Z8(bf6a39ef,c330c68d,fc9aab78,b9fbe8a3,4ced89db,d269ea89,fe1dc13f,d80a78bc) },{ Z8(c8116b07,39ca0c02,f7c5b7af,67d64641,52b0ff0f,ba977b87,3e7a148a,0c762a19) Z8(a928b9d5,8a36598b,b3f54253,1296e7a0,5c4b6c12,d6f38c3a,023b651c,d8e2ef5f) },{ Z8(56f34986,2fd5634e,8cfd88fb,1a084931,047b3ef1,887ca7cc,13914ed8,39b591b4) Z8(edf5bf0a,e2a71844,e704fea6,f615c6cd,1541ab5f,6670eb83,07caf517,d9bc3ee4) },{ Z8(fe0506a0,b3067371,cf018213,72f6bb3d,6262875e,a2831ae7,34757798,89f5fab6) Z8(a1e4145a,282b6931,17422c96,9e98652b,2c633a72,6bdb6d0d,5e6392b5,da966825) },{ Z8(bfcb8b97,eb2bf6f3,6a46367e,ad7a57f4,2134ae0d,f4ebbd12,8ac88ec8,ea7034b9) Z8(361b8b87,06ec1807,2a4d9a0b,6a186b0f,26322c0d,e72b8224,2f58c2aa,db716bfd) },{ Z8(ed51cca0,530b7d9c,2572b460,9a5dd026,fbe79755,592d97f4,7e666ebe,bce614e8) Z8(0c1e853a,d9488fb3,059b1481,bea17eeb,dec15a0d,a0298edf,7e94963f,dc4d4b46) },{ Z8(8e3f8906,e4640745,fd385368,2d8ea59f,7e9bdc35,f1dbab2d,9ef3d999,f88abaa1) Z8(c4808eee,d320c45a,381a9084,aa3a07c9,1ae0267b,7809cf1c,2b72af4b,dd2a06dd) },{ Z8(a6680edb,d1d16fc1,d75e8251,3d141627,69e6208d,77c35997,3cf79993,f2559850) Z8(1c201ba4,06ac6190,c4ee08d7,5ea8023c,aa5379a5,5de1cc2e,f19c1fa4,de079f9d) },{ Z8(75a0f478,68892404,1bc1112c,7818cd8e,cd8924ee,bfdc1acf,3f7c0f4c,392264f1) Z8(29c1d42c,f5a6e5bb,090d1f26,2067d94b,ac3689ee,c577aa70,69e424d9,dee61666) },{ Z8(b71e5c8c,9110d3ee,a97299c0,a22bb82c,c3f668c9,cde4401e,5cd7debc,ca0b27a4) Z8(b7cabf62,9e19db65,33aa2029,531313a2,29ea9705,5c392a65,0b25c11a,dfc56c15) },{ Z8(ba3c0b7b,c3ada609,5e23b131,8a058f3a,e3d34978,e671ef70,b8baf4c3,028a03d9) Z8(e4b48c89,92a2a7af,f3f4f547,ba617fe1,211002f5,955289dd,2b223221,e0a5a189) },{ Z8(dde01da1,004700f5,c8cc79fb,729892df,88c5c57d,5c237235,08d06681,18ac2663) Z8(0b862160,d3753405,2fa6c011,278ae0a7,9ce12dfa,83e55b19,ff60470b,e186b7a2) },{ Z8(617e0c5c,a2932f56,0e918760,6df7d9c0,65bb64e3,ae2bb304,3b1be63a,e7182eb4) Z8(d49dced0,1ccf1070,591cbf2a,ddbf01b5,a7115f8c,5945c89f,9e0c95ee,e268af43) },{ Z8(00a6dd83,e2fbbaef,c91ddb68,94372e22,522ab689,066dbfdb,dd326c06,7ea73811) Z8(f3b36886,33c03b67,382c3c69,fd90856c,134e32db,bcea731e,feda9219,e34b894c) },{ Z8(4b7067f0,e72f5e86,2c5f93ca,c69a0c3c,6b455326,dc6e8131,5f6c1d72,4e2bd082) Z8(ded6f346,6e7007ca,3d97c538,8fafb8d8,40027983,14610330,fbe683dd,e42f46a1) },{ Z8(23ebb2cb,6a0c4c6d,5e0ee797,5cb61333,d55639ac,d91f066b,879dffca,84aab7d2) Z8(09ed5c25,30c7327a,7746098d,d1ceeadd,da21eba3,b3208b98,529862b6,e513e826) },{ Z8(0bb5eb72,38e0aff6,47d6f8ef,8a0b23f8,9baf3bd7,2e6c4c75,58d9c85c,5c88230d) Z8(bff85dd1,7f7f2762,792b8628,f82a1033,96307c24,cc7bd34b,a48792ce,e5f96ebe) },{ Z8(9a542785,bfbe8dec,114166c1,ff42e769,4b368972,2beee4db,8c2ec9a3,35eae14a) Z8(2791c9b2,252c5298,f75d74e1,29134679,b400bd2a,e54173ad,785f86a1,e6dfdb50) },{ Z8(db658566,aa327d20,00a4d724,d588e59a,29e4861d,9bfd1668,512e501a,069b2197) Z8(cd31d2dd,7f2f51cd,6f678cca,583cd3bb,eccc4bb2,66c74a26,3ac545bf,e7c72ec2) },{ Z8(a190daf4,67d57aa6,6310798b,e2ca630c,2ae050b8,47ce4920,f9c612e8,4830d47d) Z8(350d0125,e8d606e1,38ba9955,ca63d36b,c2057bdc,da32f09e,3f3dd981,e8af69fb) },{ Z8(44ef9bfb,aa8a5cb4,c716215a,0f05d516,55c4c08c,e574ecd1,f62179a6,ed3c15f7) Z8(b2ea1871,23ddfc67,e54bd2eb,ca67acd8,4e2bd4f7,38caabe9,c115a0a7,e9988de3) },{ Z8(94a550a9,81186b21,73c4fd9b,fb717032,47f11980,4a01d815,94fa9b64,d558324d) Z8(1efa0239,2110bcae,5e35a24c,99ccbbf1,8696a5eb,a4fa676c,e4488ab0,ea829b64) },{ Z8(eb269c97,a19fd787,94f01cd4,545bcbf3,68d55890,df4c30f8,2c57784f,d94633d6) Z8(15239b43,5af32341,427b591d,4b0053d1,89153eb8,c77fd14b,b66b3bf1,eb6d9368) },{ Z8(dfe791e5,3d83d656,8b2d5eab,54e27e3a,6aaaf7b5,4b013a86,9838a4c1,526665e9) Z8(8cf2cacd,f994bfb7,62fb38ab,200c0692,a9c876d7,f4e061f0,2f951b38,ec5976da) },{ Z8(efdfd5b7,bea7aa27,d8c27f3e,ff9487a9,aeab4d1f,53b5d9b3,8d82d4b0,1e0e261a) Z8(385b54b9,7e395189,a20fd7f7,113f105c,47a42e7f,28e4f590,334b49fa,ed4646a5) },{ Z8(8a333813,1230ba36,70f1847f,2391a770,ae9af36f,fe997902,82b91346,1e07350a) Z8(aa17224a,9e8da19f,e9a45daa,d96fdcd1,e7d22466,d05987ce,916c87e7,ee3403b6) },{ Z8(62c86a25,66a2f427,2f60a29b,e80b2fdf,272e61fc,d8363b33,cfe1effc,51acdd2d) Z8(2c2a932d,a14067fc,050387f0,ca170f74,b6d52de2,44bd8397,071e02e5,ef22aefc) },{ Z8(602a9113,7a19eb5c,cb948e42,da909450,80c29fa2,8d28fb42,b8ba990e,56eb6cd1) Z8(2022a7e4,654f064b,85d0692e,64bdddb7,474db8f4,c9eaded3,3fb9143f,f0124964) },{ Z8(dfa0b15e,5453c30e,5fb79ce9,d394ba5a,88a8cf05,c67f83c4,42e76677,d78ae111) Z8(8c4f102e,65fcf44b,466bbe3a,c48418b3,12f35e84,cb00cf6b,d5b9ec1b,f102d3de) },{ Z8(fc5da659,e2c3f169,788963ee,861838cc,66d38d7b,549c574d,7c677430,2df90375) Z8(a0eaf3e7,37720269,7a93e758,944e1508,8c3dbdbc,02133a23,53af2c05,f1f44f5c) },{ Z8(2d5651d6,60fd715f,5cb2cb47,474f34ae,4ba4ff34,dba6d630,569c069f,d3957af6) Z8(517eb975,60edfbfd,182a7ae3,412646d9,dd47dc64,2542fa88,352a7191,f2e6bcce) },{ Z8(2e48c039,7f2369d2,af5b0a59,2982d668,5ba9f2b5,f31a1ab1,c3804243,47303c7d) Z8(ff996f4f,a28a2e1a,e4a41c5c,e3883793,d554bf61,a3f5bc94,e7b1d205,f3da1d26) },{ Z8(43c830a9,a6f5e7bb,b5816fcd,621f9b8f,b3f452ba,c0a32cba,f8169db9,5e768a9e) Z8(42a3cc44,47c4dcd9,4adde0a0,0a71d023,af6dcc17,efe744e9,cbb247f1,f4ce7159) },{ Z8(e5576823,543c4d65,abb50a5c,58f1b00b,5add5a29,7a7930dc,2a2e8894,01086ac1) Z8(055677e5,26f9b9a9,391809ca,2c4aa001,822689a6,bfc2a480,357313b0,f5c3ba5b) },{ Z8(d9d78745,2834630b,29c68f56,24644130,1c59be74,cb1a9027,0ab6e51c,9956a0e3) Z8(e0372057,d8960c5c,36404c21,5c03bf58,fed26645,abd8e26f,6e0a0fc3,f6b9f920) },{ Z8(99cbe8af,7f6fff2c,df34ce76,34b7685c,5e881ac5,c64bc3a1,9d4f1392,49155312) Z8(20ee71e3,66e5e571,6eb5ce24,40fbff04,cf6bfb78,796514df,b450f9fd,f7b12e9f) },{ Z8(861e6582,cd574dd5,14cd6868,6de97581,5b1f5d5c,265ed135,1535c340,01badaad) Z8(a2b0b4fc,3a7353f2,0c46c5f5,18755d2e,e0d3c9d5,5d9ca530,3ddbb270,f8a95bd0) },{ Z8(fa7189c6,3e60f494,5744dd78,b9d57c90,2a825301,14879d63,c399f431,ea42f6f8) Z8(214345a5,301cae1e,ebb86660,4b4ce3b2,1241192b,778e87aa,37ef7116,f9a281aa) },{ Z8(57c184cb,fd04a089,b207417a,8702866c,814b82b9,a510ed0f,3183b9ec,e48fe6cc) Z8(66066779,a0249dd4,3841bbd3,48f4753e,3b84c167,b68e7a57,c87af32b,fa9ca126) },{ Z8(16046cbc,50469526,81ef72aa,ff2e5326,e9295725,0204a6a1,5e43bd18,de07a97b) Z8(1985f4ba,94bc8820,fc38d27b,4bbd74ca,a2011b23,5a9adff8,0f0fa131,fb97bb40) },{ Z8(77c1c18b,795349da,8ec50e53,3e6d7856,f2258d3b,06fe377a,fda373ea,6d802008) Z8(59bb9bcd,3e7a7c1e,34a0f83b,60a464ae,5dd07b84,34d57a94,25dbae94,fc93d0f1) },{ Z8(031ca474,5026dbeb,7ce0bd44,f1f05b66,8c7b4b71,bca71107,488da9fd,a4ee473e) Z8(4c035694,e706cad6,eb3df6e9,71da10dd,a0e8a6a4,c7ca1e1b,22a533ef,fd90e336) },{ Z8(8e8e7f80,6a93691c,9db6f5a0,f3fb6332,c0c7dee3,1cd658c8,e1e5ce66,b6cd35dd) Z8(4749b4fd,d2a0a1dd,ad8263b1,12708a7a,32cb9121,61db6846,17c644e9,fe8ef30c) },{ Z8(56c08660,8943b13c,712a870c,b5d43da7,f9593285,b23ada82,7d7c915c,9ecde802) Z8(408864d5,d5780f49,ebee8587,e45235ee,ce1767a0,47c599e3,152a029f,ff8e0171) }}; const mp_limb_t arb_exp_tab21[ARB_EXP_TAB21_NUM][ARB_EXP_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,80000000) },{ Z8(4472c0f8,ace594d6,d38928a3,84790964,d113c005,f40c26ae,e6ddfd26,266822bf) Z8(ec3f47eb,2a8046fd,5fa366ab,686490a3,2d01a1d7,ef5202db,6190ef2b,bf300bde) Z8(29265764,53b7e301,8e705924,17a70134,8bde9ebb,6d71a7f3,294c4962,223416ec) Z8(f1e37dc1,7e973faa,ea015a21,cf66072e,bc0b2f32,0acf95a1,1f0d8b39,a713c29a) Z8(0a60ad4e,6e75a6b8,1eaafd6d,4340c7a1,34ad65b0,be61ef54,1ba5d160,e86c0152) Z8(947de038,971cdb56,6d6e060d,dd8f81d9,ffe742c3,41b4b7e6,342b3c29,76773d80) Z8(128d01f7,a26bd8b4,8c9cac7c,41caf690,ddab72e7,0236b793,c45295af,03bf738a) Z8(831a9c0d,05e1fe7f,15aa0d83,1877fa3d,5ae8db63,53c56952,49fc922e,0696cab8) Z8(583bba53,0c9efe9f,dc50cc91,046244a4,fde437d4,82fad707,f07f57b8,221fa97b) Z8(d4111811,fa7701dd,e292844e,d9c759f4,65bbeddb,eb0302f6,71f59074,6a05f80c) Z8(78bcb929,f58f419f,fbe25010,04e7ccfc,3ea91626,0cf5286c,d0bafad2,db353db4) Z8(4e0732af,e5b2867a,e76e3108,b248a16f,96528658,e05d25b6,274beb73,e7de0309) Z8(5e6ed9c6,a69d6d23,3a96cd53,d03c7a63,c5058bf2,22a3bfb7,718d90be,6ab2a3f8) Z8(ff164d22,d354c736,c36a9c62,d25988ae,2688ed67,79fa4a09,c2443036,2c6f96d6) Z8(f4bf2315,51b4eee8,a769bdd8,22e6a4f4,9e083efa,5d23675f,50864a14,e957d4f1) Z8(035d4369,afe73add,9080cf85,3ae83f20,8d50af3d,1da61115,1330bbcb,491de178) Z8(fa5e04c3,15a1b025,58c8cf5e,600ffa90,36da5eed,ab7e698e,f9e9a1cc,5c7720f2) Z8(fb0c3076,89fef98b,92234035,55280bc2,d4064bd3,05e841d5,893f64c7,84102b00) },{ Z8(663190da,ec073363,c3078b85,be25dd09,468d4ae3,14a8e07f,b304a9eb,de679fb7) Z8(4df4ae3e,119af2b1,87144778,dcf515b8,582b6aa2,517a2265,1176c096,7065504e) Z8(3d5fb6eb,bfa73cc7,a6b2ecc1,88a77afa,36280d05,a313360e,829f0ad5,c04233bf) Z8(cec1eca7,a097712b,226d9f48,d8c1857e,2714fb65,872e1b7f,df6201dc,bd114bfd) Z8(d64c72f5,f022f720,17efdab6,817cc779,1d2a0fc6,da54a3ed,db3f4e4b,bcab01a1) Z8(80620f05,bb2a4a0f,fa590326,f99d2179,1c8e0f0d,6fecaa60,4eb31827,4faa1f6d) Z8(ba890381,01a5e678,6c78c1aa,c287c738,57170015,61df12d6,6dfc9df4,5e47c53b) Z8(b43fbde3,4f3cbb04,ac900d46,7078a04b,b394a032,7e475caf,345e7a8c,b303df64) Z8(30db834b,1223c104,b9b489b9,2d25413d,402617a3,f0b6eb7c,e376fbf1,aaf5acd4) Z8(fe2babfa,ea8dca4d,a2c45b39,de03b6b2,316aec27,62d8eed9,15c4fd2b,4a4d27bb) Z8(41185619,45dc863a,f4633175,04cbbeed,e6884f97,d255e81a,5bc64cfd,58a2b00a) Z8(d755be8b,7112ba07,087b8447,3c58d622,cc5d00d6,910512f7,1540051d,f742087a) Z8(ed61440f,7d090cbb,75f6498b,ff9fd1b7,2ce07430,12418e67,a5381697,a76d34ba) Z8(9aa28205,4a072607,0a4ffad4,33a2b1ac,7aebec0b,36401fad,d2804c04,da9d9f61) Z8(8f5f8ae2,868e17be,d23d522e,de0fd4c0,b4bfe3ab,6979ba38,733f0a61,bf9407bf) Z8(5603de1a,f907a318,1273996a,02aaf44f,c38ccd92,f8300a73,c363e9a8,7a3bad21) Z8(c3ec7771,94d3ccf6,c5428436,44a1b430,410caf75,56f32f75,25d7aa18,d2f4ee1c) Z8(ef3fcf23,624bec06,c3e1237c,dd14aaba,12e4d4a8,d8d00cf1,e9a76bea,88415abb) },{ Z8(68c67282,f96bc683,edda9c98,6544adbe,be69e504,200459bd,238b11ad,7a4edca8) Z8(da99f3e2,c8d1b034,4b4e8cbb,520693eb,b1a98c20,e5fae2f9,6e67dcfb,9cb77549) Z8(a26114da,85780704,0a481621,35ebda27,27febffe,f7572d9d,cedcfad0,318f5174) Z8(ce074442,9d2f705a,64584661,cda21342,16e918af,d5a3cc14,104b15c6,3cf2ea83) Z8(c852b2c8,78699c02,ad8a5369,a3d5fa3c,09afd1a5,e706fda5,fbbbf834,648ff2d1) Z8(71b88079,a8f8eaf6,1a4004d0,50d68062,8c5e3814,ead64902,3ba8f8e1,bda1a3fc) Z8(10caf856,01919667,b6365de4,3c2c6888,121f461e,c6808726,d31b9259,e3ce6dbf) Z8(fc1e6b7b,e1d97687,f009cc7f,2e0e5211,0f9c046e,d9667624,f759ceed,78831f71) Z8(639b614d,7bfd43c4,9eec0516,f7d64f58,fea38871,f36b6110,62b0772c,f6d6a6ca) Z8(522c01b8,9fe913d5,f63bae53,f01d3bc2,bd109add,42e23021,711a64e1,c31adf80) Z8(234fc039,f2ba9071,d8549781,03047762,d3c77555,50951ec3,17eb37f9,fa20784a) Z8(f54f05a3,7524922b,09291e7f,3666f742,478f27e9,c6edfb2b,4d556278,6cefcad4) Z8(eded82a3,c9af04e8,50ef9f0b,06853a72,c4ad2a5e,c6342bfe,eff2d99a,861fb104) Z8(5f7891b5,ac9105f8,83a1fbd0,a839466d,35d23e04,26f74405,0725886c,e33b7a65) Z8(c7d4d902,cb987c53,424f268d,27bf1365,e7a26f92,ba5e9359,c130deea,02f4ac98) Z8(ab82e878,98e8a0e2,6ea0ac35,a8b532bc,3fe97008,fea35eca,da991560,f4979020) Z8(754c3938,74e5fa46,a3e485cd,73e7aae1,ca779092,27bd225f,2e1dfd17,f7da756c) Z8(f503d876,04261d08,ea6c3274,f3da3da8,40755e14,9e8c66dd,a7066b44,8c949b83) },{ Z8(ad250250,b2b19bcc,d9a7ab01,027dc694,2b2b4565,1c90126a,99696df2,20b11da7) Z8(45574cc3,823ba074,d51b00e3,35bd43c3,5650494f,804ced10,84e29133,a5edb1b7) Z8(cd59d5b7,3be8972a,cab67074,f21c925e,2ac75f56,970b15eb,37d9d833,3a902a26) Z8(2265a024,1a548db7,48b7dc78,8594921f,cfd11b44,5ad2f3c1,cfb2c1a5,757a20f3) Z8(76626895,c732f9ee,e0954098,25694b1d,bc1ab3ad,702f50e0,c7533e91,3a6e7181) Z8(a1d596f0,c7378638,3e20bb16,22f1cc82,134e1641,df9a324d,1538e1b8,1512023c) Z8(31df0feb,4ceee8d2,42b5f394,1d1cca2d,16fd9fcf,24590bcd,e50cdc3a,647c72c6) Z8(a322e9ab,67ee8abe,9851c48b,ea26f1a8,25f95443,cbf050fb,64280c6d,00cef364) Z8(93aee173,a743f1a5,8fd71bfd,9bfaf183,a6904146,90751199,26f3eca7,27302dff) Z8(a022d18e,0baa833a,ea46f860,fb4d570f,2fb14f7a,f140557b,f5674789,dce13872) Z8(3dcaadb1,e602af16,822b265a,85906b98,45e53547,4d294592,6b3c804a,42bb1493) Z8(dda641dd,221553ab,b97c6bdc,346c48fa,6ec00e6d,2a29949d,0c4cf137,a37c1fa5) Z8(578454aa,aa502868,74e6da75,a404b34d,a0e328d4,20618ccf,4dfa5b0e,a2242795) Z8(cd72b010,673e8eab,08bc7029,c032cff9,bf81b9e1,6b6de0d0,683d80c4,64fdbeee) Z8(fca37ef6,6b910290,f941c428,e725e5cf,492ae8ec,9bb7089d,7f8d4e68,a87b83f2) Z8(43d3e4f4,e0fca75c,53588b0c,ea6f9d21,f88e5662,3d723db7,15b27cdd,73ae406c) Z8(12b5ae61,0a584fe3,ef3e2399,178072e9,2ce1e182,4ef19144,3a8af5bb,bc3b803a) Z8(8118966c,bbb5b0f2,54ab82be,3c5f8642,7035c6a1,76b441c2,b7ae67ce,910b022d) },{ Z8(5cabe6fa,d179ab66,515b5f8f,572b9a31,90ef1f02,ec806ab5,db964747,ede41227) Z8(231f9219,ed090e66,595b04a8,29b11881,ca88eacc,f3a1f938,a6060f5e,430a6294) Z8(00bf388a,6f09b6e9,b5c1aa40,1448fb78,7b0af18a,80ae580a,2e540e4f,211a5104) Z8(9ec0791d,428bf47d,ffd3ce2b,84597174,af222380,3df1d306,0c3e20f4,372fd639) Z8(f1ae630d,80fa1315,579ebebb,55709b21,f5bb2c16,97e38a49,834694b1,377d32d6) Z8(31f46924,d0fc002e,cc51fc44,24a390eb,413ca80b,9f14c78b,14ae98cf,f37f7d81) Z8(818d0a3c,623d6c32,577b7671,cc441196,65bba68b,eedded17,a4638368,e63b818b) Z8(84068640,57acb3b0,abca19ae,444c11e9,4ffd32bd,9634df59,66f1e083,99a37a02) Z8(3ca2812a,ef36dbbd,604f5295,069b804e,66475ad2,4720f755,d7672c96,488247b8) Z8(f35192b7,4d13b8b6,3fc161f1,efd82a73,0d1dc805,5cb9d24f,7cba6dc1,80239192) Z8(258d3964,87da5dde,4f20af74,b795651b,3941d2cf,dfe12607,a334494d,97930939) Z8(05b58dda,ae01caee,fcfbca51,3eeedd34,065185d5,2769cb9e,ce04ef35,c90f0711) Z8(e3fbc9c1,b5522ed3,02ac1fd3,114642f1,ec8da0ad,03790ccc,e29b6b69,12fd74fb) Z8(3bc19829,b70e2461,44883b8b,9e0adb76,47bb9f9b,003378e4,cd435926,85b1f94b) Z8(827f8d06,46af0dde,eeac3f95,72937d7d,9a81fd57,075bdb50,1ce7bbcc,486cab49) Z8(83caf092,8bd21cb7,99ebc909,b4a66dbb,3082ca7c,bea710ca,dc44f8b4,fde78c8a) Z8(06557e3f,751a929f,8482b781,38f8d82d,5dbb18d1,fae289c7,0dba2b34,5ed19617) Z8(9bcb9778,d23a6bec,30f5450e,32a17622,cebec9a5,9bb3e062,b963ca80,95a5ac59) },{ Z8(a7747307,b263d7bf,f3bbc444,7d4dafad,6448214e,95325cae,376ee95c,6781c13a) Z8(2302b794,f39751a7,64b4f8e2,b9059243,2b32f391,b23943e0,efa7d4ef,6c965f30) Z8(a24f7390,3d06da7b,3c4811cd,e62626ce,122907ce,ae9ad95a,a7fbfb98,a87d8c47) Z8(989b4afb,988f60bf,b9c4c827,625b4b00,b1a977c1,4bda3b4a,fea563e7,ccece089) Z8(dee28cbf,2c155fcb,4aeca5ba,30d9a97f,9658e5e0,8624e00b,0ced991c,e0c2f0e9) Z8(a406a085,d35b1d45,ece36f6c,ff68d8bc,aa5192e5,b5896d80,5b332c6b,f7008f70) Z8(b250ccc4,a5202613,8aeddc9e,970cc1c1,4d9e01f2,2504b4f1,474f2c08,90b46ca2) Z8(049941eb,7bc557bf,a5272ac6,f965d7a0,25876a8d,c91e267f,faffefc2,69f0f737) Z8(18021930,54737195,98a94f67,9e73cff9,ccd69b30,06dbb997,b9f58e33,2b4fb23a) Z8(ad6f797d,4d800fe6,74b76750,02e31c52,162a7cac,9fb0b597,d04fc79c,ccf697c4) Z8(7c1b9f7d,010c1c56,d5962de7,49f3473f,4a30db25,db6c82a3,3b5d3f80,484327fd) Z8(0ad2ea9f,10f7b15a,26748eff,59b7d126,881a9fb2,c3b05b02,8b47b139,12c9bd77) Z8(461a3119,00e643ba,e5fd4f20,90533b85,579c7b44,8da537da,40bc7123,d787fbe8) Z8(7602b554,b3a42a9e,0e72c101,2d78f585,d4714450,a1b0faf5,7faa00d5,636f1626) Z8(50ed39d0,8a041948,5b21cced,4089dc6f,3ac6acae,c3e820f5,d1d7bc89,51f95440) Z8(7c3c9db1,54cdfb44,d6549541,305c4433,53c202cc,cbe54b73,d6e5985d,0a6fe368) Z8(87dd346f,ca85cf4b,24f1a452,34a88b53,1f7f1004,106e57b6,b021cf84,c73b9006) Z8(f1746808,230db4ad,8982478c,84735853,e33249a2,7062465b,5ac1a96a,9a65c0b8) },{ Z8(6e0137c6,7e9ec2dd,40876348,aff4a4e6,d4d74ef3,a8e84f52,a24e5464,95bc503d) Z8(9c5820e6,533ddb67,b2072ec7,96375acc,6ac8febc,973f4a46,60d20630,037e5dae) Z8(ecd84645,da68605e,6b7d54c4,4add14c4,31bd6547,48554320,10453b5f,648fb89d) Z8(c623bb02,cf74ea28,d5c3eeb6,e4021b88,43e4f9df,7d838e47,739da2fd,b1a3ef19) Z8(279e226c,62fce404,3d2bbc23,cd633e8d,31e97787,2558a943,a8b8baac,4bfa3798) Z8(6fc0d47d,d10f1501,1b14636f,db76d741,61e13ae5,ee29deab,eb765bc2,2b6d4968) Z8(76982060,6509ab31,5fd2cff1,1eb6b4f9,bd798b5a,c6ca6b20,7490bd6f,ede574a3) Z8(17df092d,2d0a0263,ea489c01,113d9c34,0f1586db,66eac017,c7400e7f,1f0a0e08) Z8(4d71957c,491cbc27,8717de76,15b9f5d9,13483331,1bf88ca0,554a2ec8,11fc9915) Z8(fb46903d,ef5ab40b,5a1d36f3,b5793cfd,96b2b718,0f732eaa,21bb88b5,f3b66917) Z8(d9c9f788,413d743e,92c24a92,f988382e,af1b1ae7,172f46d7,0eae6361,7e6dfe3a) Z8(63ae03d6,1386760f,45415014,7b694f56,5ba5be11,ea5ff8e4,e723bb41,d6296f14) Z8(f60eb550,ea165b7b,c34de712,85639ab1,1ac4b161,d155eba0,ffd05f23,5043cf23) Z8(bf2a9513,dafcef28,5928410c,7bc38168,1d25c9c2,691e581f,576e5e1e,338cf4b7) Z8(3e30966f,167a3620,a907cd8a,beb23729,26cccbef,53dfb869,cca84510,19f36644) Z8(c9d86da4,48649402,b45bcb24,606f4232,dc65b97a,f40934e1,a79d84aa,a4a01bab) Z8(c19b29c7,6cfcc965,dd49750a,b76abdf7,0e8b6bdf,24273cf6,9a601d51,3db9cdea) Z8(bcef8461,23cf2474,10a259ca,abbb03b0,6028ab6b,bbdee020,08ee5d51,9f4c6f55) },{ Z8(838671aa,1f05d0e3,ad4ea3dc,9bf8077b,58989b32,52cfcaae,8af24eb8,0c878390) Z8(44035afc,6c1408ab,3726813a,e76cfa8e,b6a0aad4,8d53a88b,c2812d6a,0e00db83) Z8(3e698770,b7fd3be7,5dc7e479,6dc6c98c,ed34df17,455d961e,9155c658,e1c8698e) Z8(4bf286ac,24269055,695a602b,e865d36b,09e93f24,1315633b,1c288d2d,f6bb157c) Z8(3a2957c0,97bcadbd,6cadd3ce,ad2b4cbe,16fb89aa,d4c7d3f1,6e72c1c7,af8633ba) Z8(1a197df4,a1b06662,fdf8d498,452c01ed,d945d3d1,28495196,864fef00,fbc9289c) Z8(fe37995e,e007d3f6,945b7a36,63bce255,82c32eba,4de7264f,23dd2638,874d75b4) Z8(6f214afc,a65f9a35,cc4ab581,253b7e11,53d42480,b15847a4,5df84b11,005143e9) Z8(920c48d8,e7b7e41e,86cb71a2,782ae3e0,4272c1c6,dacc80e2,16af710b,86d480c6) Z8(1128c53c,10218be2,da220c09,0afea2cc,8360d574,2df81fae,84e134ec,4b81452f) Z8(6f4d256e,7dd84295,8a84a02b,7ad0e2d0,844b41cc,b98f815d,11e67040,45d61734) Z8(bce26466,f226abed,3bf34f67,8e6627e4,7ff2d454,aab4c5d4,64d5eb6b,62be3d32) Z8(b8618842,68240c00,ae51c231,003094ed,476ecfb4,c45cbc80,ba9af2cc,3924ddab) Z8(f7275d84,daf4aff3,d09f2ec7,730402ac,e55c75ee,eeabab38,cb1b394a,8defcc39) Z8(f2e4e81f,7e6e4823,3ac63698,0e206f35,48d0da57,f869338a,d5210729,16dfbe98) Z8(3e52f4aa,03b77b05,314da9ff,a1944500,e6b16fb1,6d65c0df,111d967c,2179bd1f) Z8(a772363f,99ce2eb2,234be1dd,ec5ac020,1ae273a9,752a6f2f,2726e6e9,d7a1733b) Z8(ad3105f5,4c9f4678,25df1585,621c438b,d55f29a7,3de1db4d,f40c333b,a45af1e1) },{ Z8(d2b46f84,30bd288a,38681f0c,7e781609,b55f5463,1bc8ed50,c28195a0,7d0c0ade) Z8(14fe717b,36cac6ac,2225370e,2490ec4b,b724f070,81da1125,b38ffc51,d3ae1939) Z8(3934b13c,99211f3d,6d047b7e,6b720612,6339f1c5,cbd511e9,96c855d2,f8881261) Z8(99625e46,af3351b2,5022da7c,f088d8a8,eeeae21f,d3d2d461,c85882bf,2210ac39) Z8(1946bbff,f20cff9b,761440ad,e993b034,98dc8502,8415159d,5521f628,e05f9c04) Z8(7729f7ef,455a6ead,7a95138a,591788bd,f53aa567,133f7fcc,b3a2520d,a83137c5) Z8(8aa762c3,ef7e01e8,c86e5226,1d24d7fb,6024af78,8231ee0d,8453756a,e901cbab) Z8(c56b1e4b,8c6e2d3b,50dd5c8d,4b53db8d,06646510,acb7446a,395d8caf,62b4316e) Z8(5fd0b782,16ba37d9,f2db093a,0e80fa17,fb853a7d,13962c24,0e2574f3,46d755aa) Z8(c7f10c04,21b8b83e,078e2b6c,30745a95,5109b876,7b7b9206,99866ae3,98e58624) Z8(692915e8,a9b4548a,298481ab,68433778,5a1001e5,35c98119,60e90d11,fe1e05a7) Z8(b9775cda,f8470cad,03cb771d,822d8edd,35a0ac81,2cba7b5b,ab4fe314,407568b7) Z8(5f857862,02c96b1a,76048b83,cee0b207,78d57501,ae12e365,fa69fbba,2239e111) Z8(95c0816a,538754d7,5aebb1b5,cce79b35,74670b2f,fc72a059,85ac8c60,72cef602) Z8(cbce3d2d,9f711a4f,38fa3bc2,3ce6f4b5,f2445f0c,fc6cd81b,26683265,64e538d7) Z8(9d948367,0ca2a33e,b802b316,58493cc9,59eaf52d,bb322854,7e9f6ba8,8409c85d) Z8(c97ced2b,9252f7d8,54edb8e6,be3dd628,903aa117,6c601d5a,7b001fd3,478824b9) Z8(f71cf53f,37a84887,9bfa0a11,63232c3e,1b4fdb27,16cc14c9,7d67bb65,a9928c06) },{ Z8(a4964057,ec884b28,114fc8bb,f021ca10,64897b26,7672b612,76d10d02,5970f204) Z8(b2d0a91a,4bfe67b7,9d99a02c,38540e7b,0d4b2713,e3ea890d,43f8fba3,a1303002) Z8(55c617b5,b1bb0a65,89246a15,57e7104b,f54650db,c35392f8,17ec157d,97ac8991) Z8(594523df,f8f3c9cb,a2b38e1d,0357ad12,a23e773e,12ca3b81,be5cd906,532d946e) Z8(5696e684,7d8b2cd7,4acca3d2,7b0ec753,33f0e384,2630884c,f6b3a85b,ccadec62) Z8(ee31006a,370406ab,25d329cd,a1acda6f,fbd43348,de1ca3c7,c36dc313,d56bf82b) Z8(1c984c44,65a949e3,be88b2f1,31dbffe3,dd32512c,30b206c6,c0313f42,6682dd8e) Z8(33d7e0ad,021cba95,7483b413,ac623b65,f921784f,589f5702,b02b3a21,b9d312d2) Z8(3ba91944,bfc1481a,9f021d18,edaca1d6,8e624ae8,058c2dcc,91ed5f8f,319c223d) Z8(7862d041,bb10348a,6077d933,8f3832c2,8f7fefcb,5f86cdf3,cf995fb4,090e8930) Z8(1fd3b022,045de0d2,ecec83bc,b7e647e9,5f417fdf,d939f4a2,d1eb52ca,73f4acf5) Z8(a09fea67,e91a42c0,4af88551,d4a89cc1,43880051,ea92f7d6,3c249d12,511c705e) Z8(67e93ba2,76936bda,61aabaa4,e1c512b9,f7e0f1c2,99003d25,7c82e143,a1974b7c) Z8(714d64bf,86fa1d98,74b9734f,8c49507e,8a202f19,113292a2,35c9da6f,fe2981e6) Z8(dc857b8e,2fd6ecc7,e506300b,e75eaf72,a6768732,a17f76fd,2e8f8294,9eaf5e40) Z8(4283134a,29d0b8fa,8f0cd8f3,5596a8be,c3a1f0a3,9ae59493,79a94f5b,860095ab) Z8(21a2a36d,f17c3a2c,3117f371,d3f72e33,0320c24c,777680b6,0137a911,355f7545) Z8(a117c185,f10196af,06799385,4ed96178,baa201e1,89923298,22ffa9da,aef48bb0) },{ Z8(1b2ec916,638de591,6984dbb7,ca18f75e,f3beb614,11380dc9,04022e30,db611dc4) Z8(ee0174ca,43a35301,431802bf,fdca5896,1396377a,4c936e59,3438241d,3c3fe616) Z8(72c4f055,92c26e6d,1ddcb0ef,0d4d59b4,d92f851f,550045a3,58afb2c3,1e5f2365) Z8(9905fea0,a5b51815,c47dd465,9c5c3d6e,351698ff,7338bc76,438cbf93,51b50191) Z8(f1468229,b4713f2b,7044ff21,85179194,9ac70f56,4ab8b0b8,7036a809,de97cbe2) Z8(3125a1cc,48387b92,cb7e5eda,42534b6d,07866feb,7b3b8169,2e321fba,365ca9fd) Z8(1f2b25a0,f848bb53,6809e4ed,f9d3701a,316c93ad,26640e07,e65af86a,5bf309fa) Z8(813f4f09,eb5fb79b,d938e9bb,f4427c45,cf4e0e64,2bace9dd,7cd0eb3f,c9a0f457) Z8(6d7dbbf7,9c32d4a3,feb375e4,99f6ddb2,b578f4ae,0f8b0563,8a699379,ec0f798b) Z8(ccef01d6,fc67342a,c50f9be0,72f3946f,6b42e631,37f86258,67e905f1,3b93b9ff) Z8(0418a2d1,1a76ce29,aa2ff320,f5088b87,6d5728e8,7834d79f,d7bdbb32,17104888) Z8(c0ba5d18,0ed52157,65dd8582,fcaff87a,e2dc21b7,6054d04c,e864dd0b,6988c8ca) Z8(5fd98a39,f5f0ef47,12ca8387,5596afd4,df5e70df,0a5e66e0,8062c986,c701487c) Z8(f2d59cf5,3479cf66,94f274c5,9768fd5b,ff4286c5,216cad0d,52bee7bd,02ba4973) Z8(40b5b5c9,d044a2ba,4806a01b,8280d398,ad5092b4,0947ff58,d0cca23d,0cb5f9d9) Z8(b17e7875,e62d1c17,28e5b9dd,07c2076b,8aceff1e,c3370fa1,0395b732,fdf7a6b2) Z8(c179dd79,38b3f2dd,acf98ab1,0a586b38,672286d3,5a180e4e,54cdaf0f,d6388aaf) Z8(63a9bd88,d965ecd5,9de09776,5c9b5313,1bd3a598,d7cc0829,fca1967e,b4824965) },{ Z8(65ee45af,0f6acb9e,b2126e08,298dd305,455d5c75,dfac734e,41bdd19a,c9166ce2) Z8(1053c8d5,0a845e95,8b3a7199,7700c0b7,44374e56,5c5d4527,5084233b,019ed2d5) Z8(d0d21da2,eee619de,e9fb68d5,3793b9b7,cf8e806d,99d067be,e75f3e36,982ace53) Z8(06001cfa,f8605034,9dfd12a2,f15ad8b5,82964c6e,b2f9d5db,32e7798f,059a5cd2) Z8(dea7624d,ef223dff,f40c4e0d,8f51440a,7e8ca7a3,e4c17346,69e57852,2f50162a) Z8(a8beadbd,31cbda14,38edc6e3,2d999ab1,3ba2d93b,bd1bcb0e,b4e5810b,b9c6ff6f) Z8(13c74624,3ee389ea,60d8977a,a1809ed3,03b5f80e,5ef0274a,fcddc8f7,2206d2c2) Z8(84eba86c,31cc8db5,f790d0a4,59601d55,ffd5645d,609c5790,9ef16bd6,0da05b27) Z8(4b1ce83a,e45f7132,4e345055,e0adbee0,5637aabb,3a322aed,d9c143a7,a337b7bd) Z8(07cdd6df,62e309a3,b68da19a,97409397,b29e9e7b,9e1c1104,e43c490b,f8979960) Z8(43602559,8f32ec65,01444a29,45758e57,3213055b,d2d91697,a6fa5849,bc2ac3f6) Z8(c2efd543,d16c021d,0315032d,5f877688,61a1acec,697b908e,eafd5895,4a0d2abc) Z8(695aed3f,e27bcb49,11358d0b,7a52a53b,cedfda5b,15eb8c62,c7176746,9116b300) Z8(bdc42f5c,b90c0078,7a9a18f3,edf0914f,00b51778,eaef7a43,77766e97,4f94fad7) Z8(e4f4cf70,992b4536,f0ecf2ba,59bff5f6,6b4f489f,f1cb5821,5eebc284,07b1a2cd) Z8(4fef1c97,5d19b55f,f5533e47,ba40e37a,d7eb7a4c,95b7392e,57c9548a,fc5086c7) Z8(293ea004,58100d98,00085c4b,a07fd77e,a8de6b88,7c2d5e61,fdb5ea59,e61ceb40) Z8(39d43d41,dc36bb78,9a5c6dbe,bc7d210f,849202e2,a3c5b2cd,df7b5311,ba3d289e) },{ Z8(f9e0a6c3,3728272f,e449c333,4b0fe2d7,db94d5da,ab8c380c,f68113ff,c2f404a1) Z8(d833cb73,256667b2,3a602316,e2a9f674,64e70789,0daaab79,7092500a,c94bf7a0) Z8(7136fec9,20f2098e,369c8d79,98b1d039,d61babb0,cde93958,c53b2da1,c33f5cbf) Z8(6debb999,41820414,35c5b44a,bb935c15,53058854,ca2fb6c1,627868af,0eec5354) Z8(483d5512,1db1bcf4,3e8d0786,40a1574d,a4e3429b,b8ce84f6,a161dfb7,db88f99b) Z8(7098135d,74d172ac,26f5d593,c4acc4ba,debb859b,6979ec0f,78e843d4,f066dfb7) Z8(f6a8b8f1,2473703a,54426661,823d9527,f676f109,f1de5fa8,ef09f853,ff9ec293) Z8(80e44f9e,4434ef55,96c793d0,10efaf4f,818d1a94,924ade81,6a4917be,4d57040b) Z8(a0a377bb,67c2b431,84cd034e,13c78218,ecb974f1,67c264c5,54f01fae,3534a968) Z8(9eb24e12,510a365a,fda9df63,b02e9bec,78e3a6c2,b4283940,f874a1b8,58821af3) Z8(f088e8ca,94a75aeb,7552e028,0721f882,e3c7c0c2,2dac9902,b7df8e3d,304e9b3d) Z8(8e741d64,e06d9e2f,b6ca0d1a,1120c1ed,b47c4ddb,85ab2dc5,19a541cd,d3311d94) Z8(6531a155,da4d065f,50b3c08a,6776d622,f2590832,a832d4c9,2d23c870,cf3adb73) Z8(87532caa,ef740b61,fca0bff7,89adfa2e,f30fca77,bd9f8164,8e2efe3a,5d485896) Z8(e7c37807,946aaaf4,f581a76f,b08a9831,01c8b3c3,66534496,de021214,ad5263b5) Z8(73f03d69,150b7d82,ca85a628,635fd7ee,2ce538a4,3eb6bd64,8d0d244e,f5837509) Z8(19c092f5,20a81315,8711865a,92f265e5,cf26b468,a2fa5bf5,34812af1,4e2c2982) Z8(a9e20ce6,90ca9c65,e1347404,65aa4053,44a5ecea,65cddb8c,3daa2e5d,c026981a) },{ Z8(61be0eb8,e651d3f6,d679921b,ca09671c,fe34bf4b,ade102f9,e13c5f6c,cbfbccc7) Z8(8f46177e,9cfc90d3,e21843c6,daa62d1c,eafb32a9,bbc807ad,94288ee8,d9908d53) Z8(34ae79e1,939e7ac1,093610e5,70939cfa,90cc37b4,a93eab9b,73f6bff9,b07a8222) Z8(be6d0ce6,694567fc,aca45ea0,fb4bdf1c,9e1654f9,da4b9160,5ce57964,8e9bad6b) Z8(2e7bafb5,6a5310a6,bb1a379c,73d41d5f,2da421ff,c45a842e,eb55af74,ebcdba7f) Z8(0c0a8530,87cbc05f,1d281b33,84c94c3f,8eb2308c,f853b7f9,d4a9c6b6,973127b2) Z8(f6177b21,2f904eca,85d39d6a,62aa7d46,4c23e123,225ae47d,3dcdf6d5,321d4f33) Z8(c3947054,be387fc9,433857a6,246bb28b,cbc845c2,3cf14568,d543994a,aca0bc8a) Z8(aef1301f,e5d18851,dd5afc18,edb47aac,d49e7a39,af268585,f8d92693,2557a13f) Z8(3ae3f368,723296de,ebd6db7a,25fe8618,342db1fa,4b0ca909,30bac8c3,acfb44c1) Z8(d52e7c8a,d60017fe,c90f2bbd,822bf511,2f472d20,f9d734a9,56718f59,c4c6278f) Z8(90352934,63461720,f41fe3e9,bc2079c8,7e588cfa,7a58f385,5f28a6a8,18e1fc59) Z8(650adaba,f901763e,56555b1d,2f509df8,d83ba633,a45cc144,91151f45,38ba2aa3) Z8(bf436eeb,e00d876e,5ee555fb,28fe59cb,41f98955,12c792e1,7896939f,832f5c36) Z8(bf7c6ee8,973b1a0f,9080aa89,42be23ce,382a3c3b,a2605858,a5728cb0,baadefb7) Z8(2732dfaa,ac033acd,5b4d67ba,54c516a4,1cb680b7,0059efcb,a9af4f4d,6383c9a5) Z8(437c3383,9fe16284,87de5042,dca079a4,03810d69,72c15684,c963000a,568ecb75) Z8(76b0c25c,3b076185,85527ef9,89bf1067,298885f7,26da076c,d8007ee1,c640123b) },{ Z8(270a8172,63bf2b93,7e8df0ef,bf941d60,e530eb25,9541919e,e87e9b21,5798a025) Z8(a917df75,872c3c4e,e03c00ec,789ec9f0,4ad2bfe9,a1975362,42ac1b87,f7c038fd) Z8(187bbef4,24de78c9,ed72761a,76c519ec,020980ab,067a8e12,a9ece040,6049681c) Z8(4127164d,20247744,cd6d4c2e,b7d00a0d,62fc0b58,d0cfed18,b403ff6e,d4abc91a) Z8(3b4706ed,9f7a0d04,2d367a2f,48cd8034,57b774d5,3efa19db,16711959,a8209a61) Z8(5e8e73b7,2c969a6c,e805e11f,2e5dae10,ea0693a9,3af46528,dc3a09f4,9fcb138b) Z8(ec6ff269,646fe2d4,1962b3e1,330ff86a,863b8e9b,78318221,8d5ed1e5,50658e99) Z8(6dfa9624,335e9e7f,970adb15,f5d9f55f,b0e1fbee,4ec9b90e,32a93baf,68417ef5) Z8(7dad6036,da880015,59e97d79,4016f463,e4bd2aee,87f64327,e3e63e8b,07b55154) Z8(35e7a585,7e18bb10,c158d6a6,8d58fb14,4946fec7,04fd1930,b4f02bc3,b526181e) Z8(e70a7253,ffa01207,80bc7800,4e5242bf,52e459eb,46e09afe,7ec59dd7,40fd84db) Z8(12c90beb,89465382,417721d8,aadca513,5065a477,74f67256,e4cfd881,d42620ca) Z8(024837c5,38c1a7aa,1ef0b9f1,26fd0610,1fdc913b,ff25e331,7010f215,b0653a69) Z8(c5bc20c6,d0b0e7e1,6155fd64,da6336e5,23284d68,59097308,e0e76850,fd82fa91) Z8(8db617c4,51897822,1420e083,a7748dd2,79c3cd5f,ec21455e,35ba93d5,38b813ab) Z8(16438341,bc004859,f6825f8d,f49a43a3,fc55a1d9,f2ee3831,d77d3d22,70156847) Z8(5966214d,8a064fcd,f110f4ea,9fad9313,9b3b39b1,9323c576,2124bce1,46bc0986) Z8(a95d0bfe,e6ff9d1a,a996a9b9,54110fd9,74501497,8c7b829a,58ee609b,cc8b1d6a) },{ Z8(21ccd371,1811e030,3e23072c,a2d85c44,05fdd6f3,3938b2c8,858221a7,a8bd12e3) Z8(a2ff10fb,b6c3c0d0,c18212a6,c14749e8,c7e37196,6554dee8,6dc429c0,21f9e06f) Z8(ec221ede,98087e85,55e5a672,0fc4f105,ba9a6217,b6681b4c,b7c42015,a0ea443a) Z8(938ae244,ee42f239,2b73ee96,40e60b45,3f5e5b7e,1c176c51,5b6a2517,1918499a) Z8(2821152f,ae6e9aa7,c5a39b5f,06f94f80,559fdd29,d92e9663,cf4d10a2,beebc316) Z8(1c07e9b9,25e160bf,9d24900c,adda9119,b12aaabe,9600c2b7,09a66771,56d9a725) Z8(cabb5696,b5f80047,638fa0af,dae20a2a,7367f3d1,fbbbc117,1910c09e,140e74f4) Z8(a2d59952,73c0ab7a,0c63ea8a,109b93ea,bb19f494,257befeb,656c97fa,aa2619fc) Z8(0fa4756d,8a0e3254,ddaf19bb,d9bf40ff,3a2d521f,e9dc6988,1aecc34d,6f81f37d) Z8(69c4967e,9f3eeaf4,f48c6651,b664d355,44fea0c5,6a4f7dfc,724415fd,25d8c7f3) Z8(5a1c4846,3ef4a8f0,44e5fd91,004b0328,bf4f439a,3ad1ee72,b5cc193d,9aba21db) Z8(ad451031,6568e829,c0bed5ae,3a0b062f,8750590b,41550eab,c275450b,4061b2d0) Z8(6609defe,4342dc3a,2a1591b4,412553e8,a78c9e86,3c6abdb2,7ac68743,a020887f) Z8(be1f3951,93b72e2e,6506f4fc,7e62bae3,b45099fc,9bfbcb4f,49c110f8,c879f711) Z8(a8f673a1,a43fb5be,a12fdf27,3849b815,f073e973,c4ea5040,08857fec,d4ab26b0) Z8(a27e3fa6,e944e88e,99f90c2d,06da7bcc,980e9378,3e7c99a1,7ef1ed9c,fa0039d7) Z8(15b12f49,ae19ba80,7b30f91d,a4f6acc6,cb8acc8b,9f376dfb,d4891710,177ab93c) Z8(31b3f966,e225fe48,0985a3ac,fb28f8b6,6f99fcd8,96ff7d5b,f034de4b,d3094c70) },{ Z8(80a05e5f,f3544a62,55e37677,8ddc0e3a,cfb456ad,e544886f,7fdaa502,ca4395c4) Z8(34b29f89,df5f2c97,f0de0314,c564217c,c8083b73,3369964d,a7fc6697,986f1b18) Z8(1f79fca6,3344944b,4915ea85,6f9dcbf0,cdd1d752,1f9c6da5,a564f1e0,efb40b7a) Z8(22350a9e,49e5b3e5,7815ca9c,f04ee5c6,2f37a2e7,811e329b,8e71bb59,8cd7509d) Z8(35c83360,60b1732b,01e6d50a,962000de,1dfca017,23217d42,dc04173f,94003db6) Z8(f8fbe098,f669faf6,f59a087a,80deba90,f623731f,90cbebe1,b8222a3d,b6c412e1) Z8(94fb765a,6418176d,1c05122e,cdde2c83,671cf705,6f56914c,040d3aa5,22eab24c) Z8(77b36c15,b13a82a5,80dd0865,d060990b,713c4a1d,4f3f9ec1,74728e07,05ed7e11) Z8(201c8998,7b230c98,361a7053,ec3272f5,5adc02bb,469aaada,33be4ea9,f74d81a8) Z8(bd98340a,813750a4,2b18b0cb,87f83865,a7f9eee9,2ccb9278,4ed7dc45,21bfea51) Z8(6a8c9502,ae697d68,fa6bca27,3500d96a,edddeb2c,694beac7,84310df8,e4778b21) Z8(505290e6,395dea94,e07226cc,057bf97f,341d675e,48dfdba0,3b8b403f,a6c4c42c) Z8(92945bdd,3afb5b98,803f4f27,28fe724d,d3fb68db,750332e9,cf928f15,34b4b6b2) Z8(9be24a1c,e88eb1fe,c521f501,fabb5d8c,6c0d5db5,5dbc73e1,99a00edc,0bf0861f) Z8(f74f974c,c6ccf774,947e32f4,1c218554,a4c4ec0b,48cf41bb,0fdf399c,d24b5217) Z8(11a9a881,1c971000,c154e3d9,6b85eaef,7662a2f5,ec2647a7,1de839a1,ae16b6d8) Z8(56f34986,2fd5634e,8cfd88fb,1a084931,047b3ef1,887ca7cc,13914ed8,39b591b4) Z8(edf5bf0a,e2a71844,e704fea6,f615c6cd,1541ab5f,6670eb83,07caf517,d9bc3ee4) },{ Z8(8d5f7261,37be4539,14df0eab,83afe377,d1c51655,662d2c83,93a57ce3,e9510e50) Z8(eabc008f,adf6caee,62eda27b,dc264e6b,967b5ef1,3e607305,68a6a3e7,d3510c8b) Z8(8db82fac,d2e691e5,985e4d6b,12cdb909,698b165d,053c6ed4,8b8b640d,b9293be7) Z8(9d2eab19,cd8a62fa,41456141,d4c8ccba,5e2341a6,a20b5b2a,a8c96d01,0208cba0) Z8(0d57a8b8,80568840,a07d3259,319523ae,82bd3212,2d043569,b7e846e3,2d573a17) Z8(7cefb368,ae9d4303,27ccfde7,628bacb4,252efe11,5cfe1c86,c2465722,ae434b94) Z8(269beff3,2a04faa1,1dbf75b9,eeb09f8a,876e24dd,d6f3866b,424f19c5,aa190f64) Z8(e22b5222,2e545485,0a2b7d8b,1e8a1ae9,fb0114f6,b48e3f92,ee519ef5,95509203) Z8(68f15421,c7661510,743be95a,55a90c8a,49889202,e99e4a8e,ebc7df6d,8ce73e34) Z8(04a5f6cd,f2c3d6b1,6c75d69e,0e304f67,ccf41f64,24fbe67b,29c7f10e,53969ccf) Z8(b0682c13,bd842146,c4c34cfa,7ce11275,2f7969e8,90457343,c36ed54d,be1a3124) Z8(cb0f3e4b,1621316e,a6cc4717,55a524e5,3b8371af,8d55caae,ecc4f45b,b6e1224b) Z8(605ae292,601eef99,941c8c45,467e3248,2c860827,46fcc2d4,ce52c4c1,aa2093bf) Z8(f2979c71,df3d14ce,a8ed9f95,dbb6ef87,e55f721c,3561f7df,21a38e78,b87d5cef) Z8(fdeb5c9f,6ef28ced,ad6d4c00,de308ec7,677c669a,8b728db6,316975f8,2c8c94d9) Z8(6ca413ba,7addfe58,34f34bab,cc19b4ab,32652f53,a50aeeb7,9d364237,6c582d87) Z8(ba3c0b7b,c3ada609,5e23b131,8a058f3a,e3d34978,e671ef70,b8baf4c3,028a03d9) Z8(e4b48c89,92a2a7af,f3f4f547,ba617fe1,211002f5,955289dd,2b223221,e0a5a189) },{ Z8(baeeb8c1,128cef58,ba7f942a,e65ef4ac,f7b79f8d,b82aefaf,43ffd1bc,dc25ea55) Z8(b6ccbd98,2f986ea4,4e531bdf,e55fc6bb,31805a07,844cf625,9abbf13e,12d4a658) Z8(263e8d95,d3b98b37,a157bf90,d900b06b,0055615c,16b44a15,c8ec2b79,10be82cc) Z8(6f63467b,3020774b,51d506ca,3ae1b2fb,33ccd710,190a030b,79782791,32fde290) Z8(a4b86904,707dbac9,ca931244,60a08c27,0a5eff60,34f0d8f8,e70bb8fc,a94cec4f) Z8(1ef05590,5354d234,af425800,e63f4544,183395d5,94eb5fc7,6b39c237,2f3a76de) Z8(a24dc62c,7e70b37d,df2ff06e,cdefcf36,7d4e16aa,c75481ce,34138b3b,00216423) Z8(dfa9df37,3dfc9b17,b046393e,07771c1f,b7f2722a,d8cd3967,e452a3de,e092a181) Z8(236cc06c,cd2a22b1,366ff258,0b2f1b15,cb42ce82,1dbe4e2c,e99bc3f1,b1cd2a48) Z8(e769d6cc,ca5aeced,62ba1d30,c4eff7a6,4a370669,3a78fd3a,d188f373,7ff67499) Z8(e06bb75e,47c0be2a,49297daf,a06b505d,2d2b13f5,eed97c3c,cce16066,fdcd8b2d) Z8(3c3c079a,21de1d11,9986fa28,ebb8ea8d,68e90c73,c2cc3444,7e72a548,e546e3f0) Z8(5eed1740,9da3e636,d783cc4e,29e82e50,53180a9a,8957aa41,1a07c75d,9370c4a3) Z8(0c4ee88e,18f68a7d,2b2aea5f,e3dcc29f,2933108e,53fdd7e8,8b1c66ed,b3a6eb3f) Z8(18123ce0,08ecd916,352b1db3,1a6d7ebc,992433d7,28919550,1f7db2ce,eb7478a7) Z8(25875c97,ba347e64,f4bfe641,21cbb79e,fe0c2bfd,d6e29af6,f1aee623,1ffec2f4) Z8(db658566,aa327d20,00a4d724,d588e59a,29e4861d,9bfd1668,512e501a,069b2197) Z8(cd31d2dd,7f2f51cd,6f678cca,583cd3bb,eccc4bb2,66c74a26,3ac545bf,e7c72ec2) },{ Z8(e18b56ef,fe51009d,3dd362a4,60aba5f1,a26d15a2,b0b9cb4e,7fb8be09,a9f4030f) Z8(5a0754fa,48ad536d,648aea5e,d0271473,c8365a7a,8237bc10,f25c1df3,fc853cb9) Z8(74164830,d4a43f8a,3ec2eac7,7c37b50d,006d53f2,4be1e169,7d3f1fa9,b0396c9d) Z8(2df9e91d,d57bfbca,e861f5c8,52a23747,4a37955f,85ad71ab,c941fbe2,e70a9865) Z8(27428c6a,d867f61e,0b9a2554,b6b88e9c,ec908a79,269e7382,f5d530c5,4b4fb007) Z8(059edd44,d0bba717,39a3e029,116ad07c,1006a950,24b58952,ac287e74,e360e497) Z8(93b3c35d,e2f89ae1,8086df6e,f68ba6c0,afd23d15,6f56d274,5bfb532f,fedbb739) Z8(cbb97fad,1635ae5b,290c17dc,d8d84745,7ed11e22,b91f9ea0,7d1d46dd,676c60d9) Z8(dd54ac85,42856816,5a8c6b41,d148645f,8fcd4b8c,0ddabc39,5c0aaa71,ca7afd36) Z8(ace3c2fc,9af92087,c7da0e88,008db6a5,d6bd5668,e431bafd,0fac8985,a2d6cfca) Z8(123726a6,a5dcf637,cdbefde5,5b82f6fb,80196e71,56b9e3e3,89546a80,9b796d40) Z8(190be91f,0b7dc058,ad30761a,c97b4bb0,3c02b914,29686197,c6b78493,3f96591f) Z8(8d444313,5951cca9,6ac9b84b,6c42c723,78850c15,9d3d66fc,614fb520,d0b4b7df) Z8(8c521fc7,01d20075,9d8807b1,ad57e08d,f600fddd,52478101,1438b841,d267a988) Z8(c980b619,7ed83649,d6b32881,a3361838,e6d7e6ce,a8645a94,e2a9572a,1081d83d) Z8(b674c92f,2592823a,e317ca56,063f1c70,a12838f3,e4d6d8ff,f996f242,56341fad) Z8(62c86a25,66a2f427,2f60a29b,e80b2fdf,272e61fc,d8363b33,cfe1effc,51acdd2d) Z8(2c2a932d,a14067fc,050387f0,ca170f74,b6d52de2,44bd8397,071e02e5,ef22aefc) },{ Z8(51d29ed1,eb1c805e,ca64500a,438701a0,b39428de,dfb18f9f,fcdf1ab0,0a837378) Z8(23af7d34,5524aabb,2a36c8b9,88a6cd75,57b463b3,1469f859,cfd9f515,975e389a) Z8(27afadfb,0f74ce1a,6a2285aa,68b66b3d,4634b9ce,76b2d5f4,3ce74a70,a56555f6) Z8(3f9dfad4,ba5ab9bc,e11fff90,66c2f716,decad2b6,c339bb7f,65b6add0,ecd36dad) Z8(a4c141ff,bdcff26b,dbb94b8c,c47651a4,77ec0e04,797e487d,b1c18e80,d08ab3c9) Z8(be98a02c,f1c73a7d,1a5c5fd0,0abaeaef,3d73b07a,9a9e0bc2,04d5a3bc,83dda469) Z8(9835e0ce,2bf4dd82,f7681dd4,470f9998,9c7b4fab,d1f9c56a,49bfefb8,1ff2254a) Z8(c8a86731,921fd0cc,f8b4b5ff,ff51b106,01a963d9,742a8eb1,c9cad826,cbbe90d2) Z8(05f53be7,b2daa55c,9872fa6d,483280d2,d2b6b00f,399c5be3,91cf8fb6,a93c6b60) Z8(8dd877d6,af0d48d2,4b4d04a4,19167770,6286e71c,fe56f3e4,c6c4faa5,c69db1ae) Z8(859f80bf,70a13ded,f24f18cd,84514e38,f77aa802,ab2030c7,ff97ecf1,3b2f575d) Z8(d100b799,587cdfec,4f867f2d,7fdea26c,e6c5dcd5,31507573,9e65c54c,631d04de) Z8(847c31c8,3f65c927,9e3954b8,092eafbc,cfd90fc0,630a8c0e,bdc7bfdb,87b6ee33) Z8(e149bd2a,45e52513,b918055d,df0b9079,c5f8fa19,7e568a0e,73c6cebe,2fcca9ad) Z8(9a5a4cae,0ff31493,f79356f4,556f85af,f9327526,0e72064c,cc0ca4e9,d3890053) Z8(b256d2aa,8e0bea85,19363ff2,63321e2c,9cc676ac,2ff05f80,6f42273a,0b99819f) Z8(d9d78745,2834630b,29c68f56,24644130,1c59be74,cb1a9027,0ab6e51c,9956a0e3) Z8(e0372057,d8960c5c,36404c21,5c03bf58,fed26645,abd8e26f,6e0a0fc3,f6b9f920) },{ Z8(08501603,683caee5,742696cd,05d080b8,8e0078e9,8f30358e,8783ae7d,be2ac4c7) Z8(787b52d7,100d9b64,8c009439,0e7ae058,7035c9b4,94647330,bfbea8dd,06de228c) Z8(0d9b2256,f7759b21,510b5176,cb126e78,5d597b62,e48f7347,bc4b8c8d,21256cdb) Z8(733f08c6,5da01e31,5226aadf,44d5c2d1,94eba949,d3de45f5,33b247f4,5ec369d7) Z8(80e03828,c3805408,6cd2cae9,e0d56b47,2dc4ccc9,3e1890c1,f1db4994,86ecd96e) Z8(e43b0a87,3501b90b,6fd9de40,2e542da8,77d07733,d3235c22,e978e17b,6a6023b5) Z8(9f6e4736,651b28b5,94025a03,d1f0ba06,c77a627f,750a036a,6a4cd2cc,bbbb30b9) Z8(255fe91c,dc9b2962,9733ff0d,2c36d720,df47d512,ecac88e6,36f754e3,058dc86b) Z8(722d5007,908a9be7,0e618051,f9c40ffe,30cc5362,f7cb9de2,7454b97b,7332ff02) Z8(6b808f4d,f8aa64e5,d4f3b5a5,97ad4a64,df36e995,86aacd70,e54d5679,c3bb4d1c) Z8(24459835,912e8b4c,4ff40fd2,dd5136b6,d5e2e7dd,4b8900b5,74cb6d49,53bbe7c9) Z8(8e4f9cf0,e6971b76,c838b45d,ec21b17c,c78988a5,1d36f9a2,981c0c39,3f1f3ce1) Z8(1ef3b30b,512ed7a4,b68885df,59957a80,c1ff7f98,6f685d1b,e7632f69,04088e1d) Z8(4d49eb70,69fb4f22,84060732,de88d2ea,e7a8865c,b3664e87,79c635ee,3d6618e9) Z8(4af3b029,3e49bc7f,2036566b,44f0f5e5,27138b02,06132e38,d5c63bb6,6ac69456) Z8(ba01e911,27bc2083,4d6b3332,475f36c9,32083e4e,01d7c09d,8bd1891e,cbc7b1d9) Z8(8e8e7f80,6a93691c,9db6f5a0,f3fb6332,c0c7dee3,1cd658c8,e1e5ce66,b6cd35dd) Z8(4749b4fd,d2a0a1dd,ad8263b1,12708a7a,32cb9121,61db6846,17c644e9,fe8ef30c) }}; const mp_limb_t arb_exp_tab22[ARB_EXP_TAB22_NUM][ARB_EXP_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,80000000) },{ Z8(03b8b0fb,acc1e74f,d3401986,545cd9de,d54ae904,d6e786bd,ffe88931,52d43454) Z8(df46d3da,c07b2995,19f6f3fa,ffdf5aaa,0531dac6,8ed0aac1,e4c26f9e,aaa7016f) Z8(7eb44608,fef9bd87,09b26d00,16480a1e,9445a7bb,ddadd016,b31ae70c,59b6d5a2) Z8(7ba583e0,34361d34,bc8207d0,a1866c76,d32ca01f,fa81adad,b6819ef6,28042fdc) Z8(ea00267f,6451a464,2e8f1318,bc3aa440,765278c5,6f64c3ae,947ba912,63d54b04) Z8(6e60845d,b88376ff,eba6fd41,1db0d07f,db881ee2,d219f2c4,25f7340c,343c60ac) Z8(56f37f93,dcfeed59,82ece08e,46eec10c,bb758db3,e8c0fac7,ecd6ceec,005d849d) Z8(56e70113,ac3d06ed,7d145cda,67a7c824,27b378ac,8737e92f,01a44cab,5f14bc43) Z8(f1cb53c0,abdcec42,db59fbf2,7a29199b,2a333c5a,5420f425,c92d28cb,a470ff3e) Z8(76d83042,0b85cdd9,a1e8f5d8,9749698a,91592982,d84a78bb,4e33ed6f,550eff7e) Z8(b6abab11,5cc94f7e,4d2b7e8e,243b1703,4eb45f36,eeec3817,16c7e29a,4f971829) Z8(bbcc3012,a0ad1d3d,203fd476,4401471b,b9efb83c,d305d47e,197192e0,3e35f637) Z8(0ffcad45,41c2e455,44228877,56f2ed4c,d4e2f9fc,d513cbdc,462b44c0,7790f00e) Z8(0dd744dc,0796aa70,638f0f03,ff6036a9,00fb04b3,942c3e42,6f1c5388,537bdfab) Z8(12324781,8d21cc97,9c6ffd76,f4589007,0bc1b3fc,6fb370a5,3bea4f42,24d1b86b) Z8(b14d4e1c,07836c20,9cac0191,aa0ed669,670949a1,3806abc5,d84e903b,6ebc201b) Z8(c24c77cf,47f7c7bf,a452e423,d8e0ac63,f87cb252,86dec92d,851cc1a9,d0e18717) Z8(927372a0,2c6f8635,a2d3aa12,2a408ea8,37493bd5,f1c73674,555aaaee,80200400) },{ Z8(79777d59,324ee7e4,c1f44d16,8b34cd9f,93f10143,3d7fa0bb,207e9f96,4eb09eb5) Z8(48a27810,fa30f046,a73e0198,48e18ac4,28a8cee1,d784c3bf,294e0a9e,50ab3912) Z8(b21065c5,6d4cc4b2,074642ad,bacb1ec0,aeaab3f7,fa98fd22,e8ab030f,c1f49749) Z8(df519b31,8f1c0721,2efed010,65396edd,987bb849,36cfb318,8239d916,40bcf1a2) Z8(465188b0,3720f304,0b522bc3,283bea2c,0537f7c6,e2e24da4,3c78808e,e19afda9) Z8(9253dfde,a5b09543,8134b17d,51ce9636,f09b366b,d3aca3c0,5e908566,22e69369) Z8(7edb6bb4,eb30c804,598a9843,4d3c8b19,9769062b,68373103,173dce18,c1b322a5) Z8(47230b6d,8ba117dd,df088141,420f9e4e,d0e989bc,330e8c04,fd956672,57202737) Z8(a826393e,54b55414,66ebc0d1,dd44292a,63c6da41,dc1b9aee,b72b443b,c63599af) Z8(e749f0c3,e601e3ee,3ea0e3ae,e2299adf,80923f15,bfbf7faa,ad3f0f50,3b6f7d14) Z8(fed4cad9,72621213,141d166a,47ae7cd8,fd30674d,602ed8ce,45a0a2d2,38657f1b) Z8(cf3a85b7,ce49f688,b054e223,66396d44,4e245cca,b40a4f0d,89101048,3262b09a) Z8(edcb136c,2934446f,7d93a205,6f8e8424,8fafb37e,b45546c7,f4b07cc4,f890f91f) Z8(c7864953,1d1527d5,5ca0fb6d,4c0c50ab,d7cfe8a0,182e7ff0,601488a1,1def11e9) Z8(1b981f50,8ef3e807,09eba861,ab7b0576,7b75d98a,a333d8fd,3ce9ffaf,aca016a6) Z8(b915d148,b8db52f5,17ffd9e0,72df3a87,79e5a00c,3bc3ee67,51a377d1,9a670745) Z8(3f06f65d,04eb1d5c,ffafd365,049b2d7e,abf3b2ab,3fd7dc72,ffdcdd75,51f84a84) Z8(75d2909c,a202d35f,0abf4e86,cdd724d1,b97a6479,3ea0eade,ab000889,80401002) },{ Z8(96ba8909,0a0201da,6ed13830,26d70be1,87c7d74c,fdcc1a5a,5d6c1ae3,d576b23f) Z8(333b2ecd,31f713e3,5ee91c12,33d3b703,ad02e4a3,fc4344a9,bad77f34,40c468b2) Z8(a0b6f069,530a4eaf,a548d6db,6aeccbd4,53756048,d3e8b488,fe236b24,bb00951d) Z8(391b5fe4,7ea88ebf,10da122a,5602e9b2,30578cd8,a3569a69,e33ba09a,5067833c) Z8(3554d397,5ec36aa5,2b62b6de,a6a480ec,b85acb7c,5083b319,881ee588,7c5d6130) Z8(652e7695,8b95687d,f28b5482,037bbe66,ce9d701d,8913b8fe,897a6907,1a93d7f3) Z8(04bbe10a,71994759,9ac66383,a96afa3b,b9007797,ebfd954d,e06e88b6,59ed00d5) Z8(8eb679de,1a713099,6a55f947,0ecfe69c,443c1f30,9518b45c,3b275771,c5d04dfe) Z8(d3b1bea8,5daf81b8,8a15cd9c,a3014e82,f8d75f6f,d9cc25b9,424bd20c,05d84e59) Z8(5c4aaac9,fa70dfd6,8e770b4b,456fdc7d,1389e418,c721ed84,16cac398,af7d57a7) Z8(09e626b5,eba1e359,752f5f2f,5581a201,81362ddf,5821752e,fd92fe29,41c3748b) Z8(0abfd98a,f5a282f6,1aa40602,f354ebb5,66d9ea67,8cfc4b6d,5b5ebcf4,a6de9de5) Z8(8e3c8af0,e114a7f6,4c890bea,175a5a91,b2a853dd,709be027,27dedfc7,f86c485d) Z8(3eba10f2,8e401074,9aab0272,05a23bf2,c0f792a4,92d98eda,993f8c6d,adfee4ea) Z8(d0287f28,b6166d0c,107a6442,30f735b1,4871dd86,571a0d3c,6ae61f4b,2c8c8e89) Z8(f6ac196c,d81dafcf,4a3e7b5e,d898b6fc,f12ca26e,e57ebc9c,559d824f,64a80fb6) Z8(950fc9d0,3a554359,ced464f4,20889b29,096b7204,74f41faf,2ba5710f,a2283a1d) Z8(8c205922,9076afe4,65854e0f,0295b6a4,fe4d3866,e744a71e,01b040d4,80602409) },{ Z8(7dcb51e0,afe482ff,beefc606,1727322b,3e7b8164,760019d7,bbeb20ac,cc3e8676) Z8(6b8e430b,6ea24846,ab34686e,c6cf51b9,4bcae1d2,dcc70373,b8a2dc3a,e8e83af0) Z8(16bc987d,c58ed487,883868a7,4cf8cf36,d455dbbc,bcd3d67b,f0f70284,861d86c9) Z8(da0d9c7e,fe3bef24,c611ec14,f29b8087,b375e50a,695e5b19,ab1a7127,9b14d5cc) Z8(b5d0c1af,560079fb,8a72bd06,5aab4d29,3be6cc65,a1d5034d,1c8899d9,6cb4d5ac) Z8(c1eb02f2,078231d0,24447b99,9f851217,78a2b54e,1f74581e,32de2c25,254076b6) Z8(7b44413c,264694bf,4a441c3c,831e8276,2dde6ddb,56b0a084,d411a8a2,3842b59f) Z8(3afb6bf8,c004a0bf,dd425c46,a0705ace,0cbb5961,0b434b89,ca901fa3,633bb34e) Z8(3c232ed5,3e125cb8,2dff1684,66cd4af9,64cb8957,0c08696f,cbc025e1,20489d4f) Z8(90965566,084d2e55,8ec6511c,014a3737,411de64c,48b5440b,ce857dc2,6798da7e) Z8(c9f79aac,5c4347fe,11bda442,07d6aec7,3a9f0fce,81d2a25b,4a830e45,a82f082a) Z8(b4e946ef,840e7dc4,f577a676,2163a215,47dec8d1,0bef4d19,d9cb6ed3,b41876a2) Z8(eba0499a,f9db521b,6d007e01,425c65b0,e039bca1,0d8fe45e,f6c1ec9e,56db3f34) Z8(78873748,bfd44117,63ea747f,730ad69e,78773929,102c4e83,a7dadc36,3203e971) Z8(4aadf7ae,54067aaf,edadcbca,1a6765cd,afe9f0f9,e9b19b90,607bce29,302fd653) Z8(7e9a3473,9f1da49a,3c7ac797,db39e59d,40a811bc,56a00d37,57bda725,f96e18cc) Z8(ff554e0d,eaf5c2fa,5c67ff57,abee91b9,020d348f,e82f3725,fafa1201,575bd293) Z8(d0372a42,1eb90105,8676076f,de780649,3554f733,45152169,5aabbbe9,80804015) },{ Z8(b98d7006,b5b3fbb6,165a494d,79d6bc5d,29cfac64,92feec94,97e5370f,6d1ca01e) Z8(5c522f84,d210c6b9,8cee0836,9eda3628,27088025,d21c28da,0ba2b06e,04723d37) Z8(335a65af,9c618969,d0feae89,450ee3ed,a771d4f9,b06a52cd,d816f0f4,1d2d0604) Z8(86e1465c,1f6d9be4,070b89c6,0dfb88ea,8436ef7b,9281ad38,010bb79b,2384dbdb) Z8(14dd2291,6721df7a,1c499979,fc3665ef,42a57710,7d1d8a06,95790c22,1cc2328f) Z8(22be2038,8a0fb0cd,ab58c444,c76d32c7,07eff20a,8cd98047,80e2679a,c80df062) Z8(a11c935a,720750bc,7b1b1610,29128604,cce1b2b2,d97f58c9,1fc0c68e,7be8f196) Z8(c80c2a1b,8abf3276,7df23c87,bd87b4ee,ec440f3a,e60abb69,4fd0f901,46c8ed21) Z8(e9486783,02cd26ad,bf97459c,201a0ec7,5f34c72e,29c68c6f,bb13d0f8,a7bde7ba) Z8(739bfb7e,e289e191,792fdee1,047fad5f,8a77bdf1,68981ca8,53085631,ba579ae2) Z8(6b95c253,7b18951e,311870d8,e57d8f45,a92e2515,8213e7b0,1b65ce52,a312ef01) Z8(ed23063a,daaa0ba3,3fcbd91e,852b188a,656a480f,59cac7d7,cef1a6a2,5e442d15) Z8(16b0a205,a994d0b5,822195ee,0a933ebc,43d3b558,103198b8,89547d21,b83f64ef) Z8(4621214e,f0151b40,6737186d,aebdc6f0,6303391a,545005bb,74f57df6,48797ab2) Z8(58d785ff,a4382f53,d4236916,f1c815cc,9315fffc,e1a88ec7,82d4f891,f7d5195f) Z8(11f95baa,02756770,3d520122,5d4887e0,2a36f587,b0e56390,1266f519,b6dce1f2) Z8(323bbc7e,f5a060e2,c08f5456,17afdf77,9e1a904a,b2d81cf7,6d090151,2086d001) Z8(6675accc,5a6653bd,bb3124d1,005dce48,8a236bc9,10cc773a,b7b34203,80a06429) },{ Z8(876449d4,d160da90,5421bd7d,75fd8893,df1deda8,0341607a,693f4fb9,145c68e7) Z8(822b563e,cd1b4db0,a7f6df89,4e23e157,da783068,4fa1773b,d05cad09,5cc1f398) Z8(d070f00c,d5ac1209,a779fb81,77c9a42f,abb859d1,8442e79c,09ed46af,bb00315c) Z8(62ef4dad,dc2b30d2,58da2832,7e1d08f8,b88ad558,bfe88a71,fc9b7af8,dd4b9e1b) Z8(2a281f3a,c4b33f96,03a47424,8791f75b,bbe20701,1ba2b6c8,d34305c4,8fc42106) Z8(963ebff7,dc0d20ea,fe63c1f9,0dfcd3c6,66aaf8bc,a0cb48ec,5baca9b2,c3f5dab7) Z8(c94fca3c,87dda06b,19ea53f9,ea2d14c2,7c152da6,eb07491b,5bba393b,0072f2d6) Z8(c1974a90,fdbf4ce3,f7078ed0,fcabb990,9c43a4c9,6e89e546,ed9f5e83,f03cca77) Z8(dfc078fb,fcaca9bc,9f8e6e81,873c470e,7a2b803f,5aa34b9a,1accce33,fc68c38c) Z8(11f98354,88faed69,0fe0b7cb,7a36f41c,ca43c732,80707aca,2d16bb98,6785623d) Z8(12bd7a0f,701d93e2,efff4a35,11c43ee3,7e24eca0,14511eb3,e037b4dc,776fa1c8) Z8(27b1e111,aff342f2,e4724dcc,d5d3e43b,e2d7b859,6bc4df58,5849f2a2,11ac6b0f) Z8(870cb740,4f259c37,c76d4124,f163ba54,22e246e3,ba1578f9,0a45343f,f457859a) Z8(2645b431,07d2a7bd,89037290,139fc90c,7b181e29,5a380c43,838096db,5640bfab) Z8(79306d2d,03c45a17,f9876699,8c8b05d8,d3cdee15,971e09c4,f25d48e3,0b68d496) Z8(e1fab982,1787d098,f188e595,995fefa1,584689db,35c7fd88,f23d2ea5,824255ec) Z8(c166e477,29edd062,c32c5dd0,da211698,317fb710,ad10b872,d60190ed,39ff5341) Z8(9d17e8cf,617ada6e,e72f240b,3e5babe1,8cb02cd4,6f2ac8f5,1b081ba0,80c09048) },{ Z8(a3dfa477,c368c35d,d93f73fb,756097fd,fe57f5d2,35be3fb3,78a495f6,a312dea7) Z8(3bb5baa7,0d8c9e3c,6f201a87,91e0bd0d,13fd5b7c,d80423ef,bd1c637b,f2499b83) Z8(becc8dac,70c67401,83b79255,153c94e8,5dba29b2,13156b4d,30254812,e0ff64f8) Z8(852eaace,3446bd94,7d548730,16ccdd80,096a20e1,c0d6e945,e902a956,2f76ec70) Z8(e02f9897,6308fe2f,0dd10bcd,ac2e9091,587742d4,bf8f8ae0,5c603f15,d2aaa214) Z8(fe0fe206,76b2186e,e12a7a24,dd2b5436,8d94c75d,a709743f,ee4a81cc,96661b18) Z8(0a15823f,481b77b3,bd9b5384,6c3f0452,b692cbf9,66b3ce69,b1a75866,05dde90e) Z8(70df257e,9ef089ce,9afa121c,349e69ec,7e08e525,75980dd4,02a689dc,9dbc0f0c) Z8(eae1bef0,15e6cb71,214e45c1,878bb12f,65543f98,443ee3fd,6bebb3d2,b3eaaded) Z8(239df50b,ecd712ab,62bc26a9,602a70dd,2a3ec602,490f62c8,b6fb7278,c0941599) Z8(bb4eb9e5,15e60885,c5915803,bc94f8de,442e36c7,99ed9ed5,606ad26d,d51960ce) Z8(28fabcce,31d140fb,497dd53f,2a9e2f10,85a40ab3,875b51c8,299dc08c,bd3a461e) Z8(f94ae2e1,355c4ef8,fed5148a,73adaabf,154300fd,f0ef0823,8b47e192,069213e6) Z8(b04ba7c7,1b4bf38a,80fb00b4,c72bc3c6,be0bbaff,61d8ad29,011815b6,87588ca3) Z8(425292ca,9434b431,c12ced51,f1fbb9d6,5438b7c3,13f5aa78,8bd7513f,2c21dd0d) Z8(a0b2c935,70c14292,010e1846,45d21566,ccdfba4d,830dc518,aba1a73b,929081e0) Z8(8b6cf8a9,11379c60,9a856970,61c1063f,2bf40597,2adeaf85,74f1ea78,30a77885) Z8(38836f06,73456987,c9fbf71c,39440b0d,54bcea20,05a8f6f4,876c31a5,80e0c472) },{ Z8(a8796b29,e3146dc2,da57855c,62ce77fd,3779d1e4,308f4161,d15a1693,aa2c8dce) Z8(ee1520d7,8b87ef5a,1841e2a8,8b2c36b1,02c5a31b,770250fb,8df9f077,d74ead8d) Z8(181f86be,961314ad,0da43554,6c93044f,87a37ac9,c741ead9,16811e2b,1a7be856) Z8(866e3b84,b91d7ee8,d1255f92,eece105d,134e24f7,615a74a7,2d622752,467f9226) Z8(e51834cc,02a8b55c,055ddeb6,2bb89474,61e476fb,89847470,cdd8b056,514d2940) Z8(52857201,6d138082,636d6d05,c57ad739,d07e2557,fcf12555,f0338dc9,53e4a014) Z8(e07b2f98,934a3f14,e35da48c,6f014cdb,b2d2fa76,c196d7d0,a344a63e,7433b760) Z8(cd0a1d47,af676703,4fa5d1b5,15aedd21,a1f8dd6e,ead13665,bc4ebeec,778d918c) Z8(1983cfd5,38612de4,6211907e,a0ddca2a,ddffbccd,97b2ba3d,798870d8,911e3d8a) Z8(63d272ce,a1669237,3cde1e66,e48e57a2,a736f4cd,6c8e2cbc,ea882254,98af7d0a) Z8(ad739eca,00e13832,39e45865,cae16345,b98ac2a2,63c6eac0,1b59b8a1,ed2017db) Z8(ccdb5948,738b27ed,49717e93,d445d6b8,46170ffb,df4a43b7,d2c4a89b,9027befb) Z8(5907e8c7,2c41d63a,49763d4a,7a4de3df,69e739d4,87761aab,77625f6c,19ef7768) Z8(f8f807c5,9e81e94c,56514cff,086d6e12,6f0b865d,3635093c,b7e89818,0ef496cb) Z8(87b8045f,70354a50,63c1c10b,9e1d7c31,3b980664,be11a20e,acf362c3,c6f3052c) Z8(629f2ad6,61385b46,41aa6ddf,899d9bb7,ec8ca2de,ab3f0217,8b5719dc,4f7c3670) Z8(7539dd57,e5a39b83,5319c8f5,32a6326f,421fa89a,c54f1230,b416c333,da17fb32) Z8(c0482614,80ab44b0,ed70fa46,37b1c91e,39b44e99,1931c15e,00222d86,810100ab) },{ Z8(9b44642c,88d0a465,9639800d,2c7bf51f,6ab0a132,c424f54c,477ceac5,051995d4) Z8(4a0ce5f3,74a34fb2,818bb94b,3ccaff2a,1c0ad802,7c212272,2cf0d435,5f9c1350) Z8(1423fc00,377fa1cc,f1d6aa97,89801e2a,3fc57ace,5bc41912,3ecc5086,d97aff60) Z8(1f296160,7d0d9025,24f19d1e,9f011b15,daa9b8d3,3584c647,aa631166,47d8cd70) Z8(d611b62f,a5e36f5d,80f7b669,2e7ccea1,ed63a9b9,8f73ae1c,b5f54ea7,ed615a81) Z8(e2fff9e1,641afea7,14f63a22,244ab1a4,b7c46e2e,c41719ec,b7d6046e,71466069) Z8(045707a5,3c5b3e43,fc9698ad,a4f5c5e5,be19e211,710403d8,f257f196,c2dc8a2e) Z8(db5ebda6,bcd9f996,062dfea4,bb2630a3,cf4d2895,877033eb,d99e9b57,d3d37db2) Z8(3378cec8,a14e9058,78239db3,5adbc5ca,bf0a8418,11c6b024,7adfead3,8ba6c77a) Z8(7f34eb5a,7ff0fb69,c03aa1b7,c2d4d5d5,1808c29d,9be23085,ae2b3162,82ddfe10) Z8(3b746f99,dcd79b99,75985ee3,211d0cc3,3c3e30d7,376ed5bd,8a32966e,6ecd5eae) Z8(90f55019,959f4cf1,b757ae7d,18dae0be,eb3ab86f,fb542985,ab5df6ff,7a3bc2bd) Z8(06226acb,7de75f0a,524e0f07,07f23d14,0f05a071,c410886c,be4bcb7a,56bc5407) Z8(9c517ffd,e568b9b5,19087a8c,fae75b32,d5a33c2e,67027fa5,0f0da047,2c7a3334) Z8(91aac57b,598ae445,c2037f76,b4afadf2,117d1f02,5ed25fef,4d769636,04b5c182) Z8(dd27e750,e25cd4a9,533de42b,43550a76,745c0d85,1e0f36fd,52317ca5,065167cb) Z8(75ba4125,255fe84a,a06671fa,7f02085e,89b05461,d9dd34f1,dc40d87e,50030415) Z8(3be9afc7,ebda4c44,787e1e24,ea9841df,5f58b8b4,b8e40caf,88ed997e,812144f3) },{ Z8(eae7d2ba,a65ace27,7421702d,d3ab3f6a,4060ed3d,9ac89280,76c8b395,c43c36f0) Z8(aada5941,9d7c547f,2db058a0,1186c214,c3431891,4904dba9,515b5351,e9ed78da) Z8(e5e2de1d,aff0ca47,5275d5d6,6eae7b01,4aade5da,481af666,67053986,e8455da5) Z8(3e04618d,f1a445e2,cd7d2e03,51530a37,f1a12066,9d095b91,e154faf9,c8c2067f) Z8(5844bc8d,a12aabd6,c2fc1fcc,735ad5a2,1124fd62,0ea80907,ee235be2,36675f98) Z8(b4cc20b3,a9394fed,b5f764af,c305e1b1,b1cd56b4,4631ab6a,4d86f14b,4c03e297) Z8(9271e275,cf281d36,d1f64d30,87378a2e,53bd6dbd,b1786908,bfe1705d,151ee252) Z8(eaaef7a8,2efb4332,4652e89e,689098c0,7d95d46b,f90d9f69,54203e6e,9f078095) Z8(7f50e25e,04f719de,f0ddb34d,6726df44,54671db1,fe3899dd,18456418,e54b2636) Z8(a397bc8c,77fb827e,1a7ee325,fe4d8ecc,0500a2da,d7b91238,b722424f,defc0239) Z8(69fdbed4,f1c0e9b2,b2c963d4,b8912f2f,a56fb980,f79fa0ae,9fd8cbbf,a96d5d1e) Z8(b8aea754,31ba8cd7,d7ac44c2,af14a7e9,93d764a9,89696410,aebfddba,7a2ed169) Z8(0446d73c,83baa27d,1d230fdc,fba9e0f7,1fdfb76b,9fdb20a7,2566a061,ab48799e) Z8(69856f90,5bddf9ab,8f4c1833,e1c62b01,e39cf184,35e68c2e,fa8c14a1,1b6d4504) Z8(ed468922,2d938c7d,726e077a,15b804b0,080b09ef,d38d917b,ad8a0b28,d2293204) Z8(776e0db9,7fd8e20c,4bc7a8f4,47ffe2fd,45c82265,5b7067a6,56496d7f,d1eb63d5) Z8(91887fd4,dd226606,3770e3ec,392f1ec5,f87dbd1a,02b9035e,99db343b,a0694db2) Z8(2bc9060f,935e8d78,4ad9c50e,cfcda14e,ea8ed3a5,f6e18da0,261300cb,8141914e) },{ Z8(d7364855,2ee1ab21,bd0aa6e9,458e6c6b,4a061bcf,a42a849b,d0deb679,6e69d256) Z8(0f230353,464626f6,31f4b27c,ecdb2d96,ebcf951f,980ce525,3fea3291,61d4ca5b) Z8(76273a48,43028386,d35a9f24,bd362a41,f3186eb6,ec3f78f4,6eb43637,36425260) Z8(137aa6fd,90aebe4d,c4cdd569,c42d8e66,828ccf5c,bb08c3fa,8d41571b,6d7379ab) Z8(14e9b5a8,c4b8b869,dba77522,2a9f6e70,2f2b1266,5f892a3e,11f67fee,64091a08) Z8(7a77f1ed,a912e48f,97b0c5ba,098e79a3,f03104d9,8eea6418,9fc54fd2,7833af06) Z8(e61dc994,01ecc6f4,80a0fd77,288a928f,c4e12a92,54b020f7,3b85398c,9c51901d) Z8(ce561e3b,fa80ea98,8d9ee41d,76c12646,4b0ca2e7,9cc08df0,54f4d2ed,88bd2fad) Z8(bc99a598,79a37904,872a65bd,0239221a,6ea3dc85,3aa1c48e,790f9456,a66f938e) Z8(b0550da2,582b3bd6,127c464b,ce26d6e3,60ef5f08,9d721a27,cc5a0317,36dcdc91) Z8(5a33db41,af781864,75c68190,0a66973e,dd4d5d5f,be6f5456,168d9634,9bfada3a) Z8(2568e432,e2517323,7b188af4,c83e67e5,810bce71,fd188822,3d00c42f,d04f59be) Z8(c5757798,62d5047c,579efde6,7424fd60,b7f59932,a6c77fa4,94048add,389a0ba1) Z8(ed7000c0,c5178ce2,1b329880,165bd84f,24d79a78,8f8616f1,acf3ee94,88dd67cc) Z8(3b2c9467,7acf6e04,6f49a5f0,9ce6a71c,940a522e,d83476a1,f003ca5a,74da201b) Z8(5f05c74f,c0244bc7,c85bc158,02b7720f,d34cfed5,fe4fee6b,44c79cd9,b5e12a2d) Z8(27e52fe7,9e44fc62,d4ba047e,43610f64,833e86b0,6a6d4547,e1a7d729,e56a8251) Z8(0621de9e,8e58f35c,624fa028,f36f4285,78b1fca3,312da001,dc580ff1,8161e5bc) },{ Z8(a797fc05,ed2c1058,52fd11fa,1b69ccc2,550e1536,bffd3b50,09383d92,960c78f4) Z8(97184206,1de8d5e7,2eaa7799,f849fe64,27237145,73077250,c9a39bf7,da24716b) Z8(2b7cbc20,451729b3,77bd6226,0285c0b1,f6396a08,2058a990,e7058179,2f9b1173) Z8(5ce5c978,8997b953,e8b409b7,61f00eea,a17ed452,47ec3a09,33a8c843,c7ff9332) Z8(83172643,250c2bdf,57b3d321,82a8b247,b89dae9d,917ba498,138b4cfd,94deeaee) Z8(4de4a07c,f5cf87fd,4871815e,6e88a019,67c41fe2,0117e892,748c83a1,5ba0c9f0) Z8(3edaafd8,c4baf24e,8925e199,c259b6f1,ff1dfd75,f8ec78ed,9d32b19f,712c17eb) Z8(cc020e56,0e989f58,d1e05fc7,1a49ad4a,74bed6cb,ef3828a4,46bafec4,f147f0f9) Z8(786cfeaa,f6d5f9dc,4dc8f9c2,f87b8843,b69a4857,500435cf,f5d7474a,b97e81c2) Z8(4e087777,a1940bd7,3d26f9a0,59ec5272,db8c43a3,af88dea2,903a4e53,36b44570) Z8(3b7cf73b,53ac611b,7cd6066e,7f6a00e1,67d881ea,92f924b9,7709f4b9,f4190070) Z8(16ef7da3,726352fa,b4ef3d6c,7cb32b0e,ecc8ec8b,14373e75,cca65cc7,33b9c5d4) Z8(9a9b0e12,5d9db1ae,d71c4040,cf7708b8,cf259000,1729624a,55d3b7b6,69dd460f) Z8(e506f674,345f055d,d0b25a59,0254428f,f2aa4515,02a8fe83,188930a6,88852926) Z8(0c45fd4a,804736fb,01266cb9,82a7e8a7,7d7c0530,78a0a066,63d4e24e,579bd6d1) Z8(32e29ab0,96018922,3d7e2d0e,ccc873b6,b8424c1f,96721938,11038824,5690efa3) Z8(e184c3b3,c58f8dbc,34da4bae,bbc6f344,767a5698,39c05a2d,27d75440,28927bad) Z8(2c5d5be9,a747371f,0ac8a0c5,b2d88edc,773b6516,6ca08d0e,b103b504,81824241) },{ Z8(b6b2e345,083aab3a,0370f2b3,f5f00b41,3c0bd179,1dd24370,ac734e9b,8c6485e3) Z8(8d7f3ff1,ca53cbd9,a94f1132,13282d8c,f7cad936,e6e5f515,c17ff691,597d3667) Z8(2b8dcaac,9b60d5b1,5ae67a9d,b54757ce,7b3acfaa,36e1f86d,317ef412,b0ec177f) Z8(329c3436,9b001756,bf604645,7d3c3a26,3f333dbc,ebce539f,77f710a3,6f8f85b7) Z8(5067f841,8dbc42a3,fccf573a,f3c60dea,bff8f850,9536a633,1204600a,258c8c5e) Z8(61a59c1c,2a665414,bfbb97e7,a7583da9,1ca86fe8,edecb502,d7b6cfb7,fca4c5dc) Z8(b4d98521,4179fb62,11c4ab51,bb3b5b77,ceca66c0,d48543e9,61b4edb2,40f1976b) Z8(f5ddd958,c6f78d7f,1a9898ed,8af1599d,8d0ae389,94446855,a96f470c,03bdfe26) Z8(117bc3c3,05b55684,cff638eb,02015c9f,3e889ad9,f0766372,73c81b7e,cd9d72cd) Z8(d7af280c,6b1468e3,035035d2,5c1c8720,e6f25e14,f3b00aa9,1ac6995c,4dfb6ceb) Z8(30722e4b,02fc7fc9,84dc9945,dcdfffaf,ebeb85c4,8ae82921,64f1d1b0,2fceb67b) Z8(b83d9189,edc48646,ec26611c,f4df18a5,dbdca73a,c91b235d,a6595762,3a9b93bb) Z8(132f08f9,f8a1a6c5,0f45b6d5,8e33de1b,644b58e6,f56cc7b6,f551bfd4,ac8e1dea) Z8(8177f678,41af1566,024d7683,a48d82d4,55c2e0dc,f02284a6,0806eb20,7099f572) Z8(cf0d5207,10dc7c33,867fc15a,4055f8eb,719ddca0,6668cf3a,853e4a6a,affd4d86) Z8(4cc51bb5,2f5bf4e3,ae5badb2,7eb1f8ee,e094bee7,e3b709fe,41e97c82,b0be9a7f) Z8(0049424f,827ace8b,9497714c,e41a9ef5,492259de,f7aa3f29,490ac49e,a81645b6) Z8(65389168,6f49f169,309dc853,4b98f7c5,41291ccf,c3f40700,a9de4002,81a2a6de) },{ Z8(f2a378ea,aed8a7f0,9153fcaa,9884805a,aa95e9ad,bb801e9a,c31ecfac,cbd5dd2b) Z8(bf9b866e,9acd87d2,812696b9,8dc9c9af,18680d91,52c0ea58,a80f82be,1a3ff42f) Z8(6b9d5261,52bd4c6e,1261afa0,a4accde5,68c97455,52e8975f,f96821ca,bd1681d4) Z8(7c98df5e,dcbd639a,43ea19ac,995fc067,cbac828f,dfd650ca,63b0b208,9b70c739) Z8(a5a59e91,dec4eb57,07b6a482,f0af1718,fe019ac7,22dad00b,f78ca9ce,bda01e3f) Z8(715c9e0b,95587ad6,1de13094,43971eb3,b6a5d450,64b7e695,4f5e0c0a,cf5eda21) Z8(a4953eda,851de1f4,095aaa47,87ff198f,edb10927,0af23076,4b35826f,ad8604c6) Z8(62b61918,196e15d9,c0d5a94c,c2c13859,f78b36eb,5db64d23,4a908ea2,932210ff) Z8(55455c6a,742a33c6,fdc9202b,a7a3b16e,2fb1dff8,7ff65ebf,bc01b1cd,5ab9d339) Z8(95df7eb9,ddce6909,29a70002,b85507bc,ece61430,c0a7c4e8,e1760707,14112492) Z8(c75b1093,11b1f911,fb5218f7,eb1ff380,ce1ca8ba,b95f7afa,0706931c,d877e8a3) Z8(02ed299e,fe917d57,63c2ad11,dbe4158b,0fbb8f3a,5e32964f,2e6559d6,1243928f) Z8(8553db7f,20822c90,765b235f,848d9ff7,1f664406,a5f3edc2,0d856bc5,549cfaa5) Z8(03dddd0d,78940cdf,900c7b3b,444d21b8,9416c26f,0cb61af0,9d27218e,bc84d704) Z8(8aff03b1,b74a53eb,6bd545df,b9fba566,5f855c3d,748dcf48,99131457,9e8cf2fb) Z8(2e7351b6,a00f23b0,55e7927e,8a9d8be9,1d442a6a,5e982988,a1d6b849,36ac3852) Z8(887a8095,348c06bd,bbe82afc,4c41eb1a,3067d30f,a451cf48,5ecc3e13,500c58fa) Z8(0702f6df,363e1ae2,05336697,74d18ad0,7b91b34f,ecee20bc,cd31832c,81c31395) },{ Z8(644a5b7a,d54e5f0b,58172664,055d45c2,a30660ab,4355819f,62995fc5,48577a43) Z8(0c96f0bb,c48ec7a3,a657ed31,5b666192,59bb1769,380e76d9,7b1d8a02,2cce7c11) Z8(3de804c2,6bc40f1c,594e5cc5,64931cd1,20351026,742a07b1,b8f23c10,971f5f74) Z8(7474aa33,6dd1f749,f270abc2,3e3bb963,c9b1179b,6cafe989,a3fecb53,13e6b0e6) Z8(686c5b82,97e868cf,e8a69709,c812eaa7,04d6a234,a0b50542,412b9a9e,663d66e5) Z8(e898539b,297ad6c7,82338a1b,ddf423cc,8650503a,2c287f5a,29e582e6,59042c0d) Z8(38f82e17,a85406a9,bc9b15a1,e8d90ef4,003f0c18,727e85cf,47a29a63,ddaa3f7d) Z8(507a07bd,7a1c8d5c,53aa43c0,b43ed106,c05e9764,f05f9ec0,7e08c67d,98617342) Z8(418be56a,43e99e24,94c8455f,2b2ce5b1,185f4d79,0b87b7de,c3c61753,8e3b217f) Z8(ff0b33a3,5a0f0c4e,9954a97f,ea96cdf7,188a9aee,74dda751,76efd0e6,2bf76fac) Z8(470f72d6,4819d357,9e827f02,cfa52b18,283bb979,1fb47237,b9444b03,3074af1e) Z8(7fab6540,10a02e63,c253c1f8,490062e6,54e55650,4e7d22d5,e332410f,6f6b3e3a) Z8(3cf6417e,f29222fc,d047cb4d,625fa907,ec4b0a67,672a6456,2b70862a,241bf265) Z8(ff197dc1,b319f892,1af6cae9,9c0710f9,8946050a,78daa081,7d0a45ec,022908ef) Z8(e0ca1571,4e651f68,7e57768a,5d6bae01,d1fb166d,3df4d923,f3266ccd,704db470) Z8(6b1da9b1,ffdad025,24016f48,3fa8dc93,0644964c,3d4295e6,26e8f0ea,77cc8f7a) Z8(c0c4c470,b08a6de0,4e753411,2bfe9043,0a3f93af,2aea30ed,94122288,75291556) Z8(2dbbfd58,2fe48208,0ab1afbd,bf59fe83,13400594,d5b08a04,21c8f36b,81e38869) },{ Z8(d16674c1,1fc45418,70b145bc,d83df8ff,a3cf6778,ba2104ec,ae7f471c,a57d127f) Z8(508676b4,14963b4b,a47f2858,26965363,153a0051,c3be57f8,6408b5a7,2ea16d1e) Z8(ca695540,6b4a26fb,1b1c3809,b5da16ff,6bdff499,f774d8a8,43b67ab1,fcee0fc6) Z8(16573041,96421e83,ebde35fe,7e3e2ea8,46952e9b,34581df7,3aedc016,0c627da2) Z8(9cca9f9d,875a4a44,8674e0bb,66752056,01026b4a,05352d88,01f4cb81,c0bd2910) Z8(2320eb2d,2e342aaf,547c94a4,860f8b7d,136c2434,95aca993,11d6afbf,107a2453) Z8(9defd156,20a81825,765a42b8,061e2718,ecb2dafb,54dd3bdd,2f604396,e8b9ed53) Z8(bb8f191f,7742df31,467f5fc7,b4b14130,1e87eb61,9a6cfe89,df10cc82,633c803f) Z8(183d1fb4,3effc9c2,bcce8cf8,c9e3e3ee,cdfc7677,bb623a00,366dd0ef,2cb8c198) Z8(b94eac8b,cbf0108e,ae06bd64,3cffe2ec,6547d251,9d710f4f,ad591fb0,b1555ef2) Z8(4957efc9,071d4dfd,552035aa,f4c815bc,233f615f,46638da1,2d1bce3e,e4454e60) Z8(92476aa9,08b9d822,e3162676,3c691e29,5bc1a96b,212c98f3,dabbd643,d4f7b0a2) Z8(2d68d5e1,81002d0d,b4a6f876,05ec7e19,c4b75a76,a365f59f,26b5a4d9,a5bcdb24) Z8(5c00cfa5,e1a5595b,5ad30790,37963044,a3b59148,e090cca5,e1927066,265006c2) Z8(b8ae1f0d,a6b00339,38c43b0b,a2958699,4eedf015,2c697553,f353ffbe,75f95222) Z8(1d1dbaf8,5bb77ec2,11ce0e90,13386ad8,020e152f,0dacbe85,6a0a98f7,ff5a92e5) Z8(c5f3a3dc,73f545e0,3415b128,87330d08,9ab33afe,5993a7fc,8b7f018c,67380747) Z8(5ec2eb5c,835210e4,a313b765,b790820f,822735a2,5c3259f4,aef1c8bd,8204055a) },{ Z8(fdb38672,2beb4833,5bb41c60,a34ad856,01a926f2,6b3fcd6e,33c99129,415a345a) Z8(be853c81,937fc249,d80eafc4,4e9c911b,b807e7ac,0b3ff259,5a46b3e4,f64d713e) Z8(f4dff790,6dbbd9bd,cec370da,18ab1cb2,76acee5d,d4f11124,1f40d0b1,19ef40d3) Z8(376b3cd9,c0dd9c15,eb9698c4,34700413,c4a9f7c6,c9461372,921fd079,93acf5b0) Z8(d5887018,2a03e341,047de939,539ea136,abbe1307,b799e229,0d628357,06debc14) Z8(6eacf169,bd82960e,ad1098e4,0cf8d9c6,14aa8905,be84726a,651814b6,564a320b) Z8(8c0d28a2,fa642808,f232acf8,778af593,bd3fe252,cda7db55,2442a8b6,6fb35cf7) Z8(e63494c3,39a0c283,004a2fab,98a6b60f,146bb3b8,bff7cbf5,d6c9cee1,efdf9491) Z8(2912988a,08851904,9755f353,1ee6559c,f6a2c02a,5c3f5f73,e86a8bb5,964a0c55) Z8(0bf3cffe,da86b33e,a250a1f7,9a6f5d46,f5edbfd8,9b9f83b1,83e7a3d1,06f28697) Z8(e491529b,39391700,a0abfca5,a051c16a,433d05cc,fcdfec42,b51ed08d,b6ab962e) Z8(08d20fbd,e73f67af,d2d7c292,97e24dd3,5a6e4430,59642f9f,f8d12c75,d7f473f0) Z8(62bbab54,fa1abe8f,1c30d39e,eea7094d,07ee0e95,90eba736,96a75c85,7f6ec54d) Z8(0203eb4b,f71f6d5b,237443c7,9f2430ed,26d18a79,589e5298,bd2b2659,2ebff4fe) Z8(4f83574c,65ce3c36,078fbd92,6273cf32,831560cd,0299b487,6e514ddd,93fd55cd) Z8(4526652e,271744a2,a0e77dd8,dd7b028f,827729bb,1f05a407,04b7427c,6e129a69) Z8(429fec82,801ee10a,f6a9aac8,76e5c351,57aae403,7cc454b4,ecb75c28,5ff6a41f) Z8(db1d13b3,0935066f,201ac12c,d41e3f1e,ad10d664,21eb3356,7c7b1ea9,82248a6c) },{ Z8(21c50bc3,8c3e8e21,e1a11201,ebbfbdc3,0d35ece8,f20ccbf3,8c98022a,21a7a856) Z8(3d4b5ea1,6e1d2a4a,d659e91d,55aa0459,a42048fb,22458351,5fd2fccb,a480015c) Z8(6ffe5b2f,2c420ead,39e5f441,4c5a89d1,4b899739,3777042a,d0aec0ce,98107791) Z8(7c9f170f,344012e1,59e20536,22f12046,d3a410a5,464069f7,eedc72e4,4eb0e99f) Z8(81048ac5,4e8bf849,8f8ec237,5847883a,80f46a9a,2c242596,1f900e03,f690836e) Z8(ed3d12fe,3cf00394,004e9f21,64bd7275,28513c07,addb0971,e3e93c33,b01721bd) Z8(5a884e20,b1a56630,dca32bf1,57aaaae6,e5da1ae6,39b3d115,4cdddc30,0806989f) Z8(859129c1,752946b9,457fbd39,e6ff0508,e226850a,69be91b7,0d7f79d6,24f32968) Z8(da50be74,71eebebd,dc1bd182,8316a8a6,8e5382e9,5ea14cd3,7d34e98c,c667a4cd) Z8(2af65e23,2e317f40,746adb1f,bb078b3f,3fc9ec79,03c8276e,b32ab453,f809bc4c) Z8(c7f38b1b,b12720e9,29515f72,879be706,75fcb72a,b655507d,c45a94e4,926816d9) Z8(dfd0a304,5df02a1c,3e3645d7,3f99297e,d5000b64,b68259b1,1bc3622b,b86c1b29) Z8(0ee498ca,a0eec360,45a7351d,3acc7b37,c9a93c6d,bdd2e22c,a5fd43ec,5edea46b) Z8(c21b85c7,87344390,5b01076e,dde36644,5a6e6eb5,1297e062,da8c612d,bc4ddb06) Z8(f0ed37d2,8683f81c,d2ff0612,4d1099b1,85971d71,b1cc30af,402107b6,7f23589f) Z8(4f301e78,49615c0e,61f5c723,a78ced96,acef391d,30d8dc9f,f22c1f05,028c72db) Z8(e2e30744,ec068324,d03fd1ac,76691784,ace96036,bafe2ad1,555feb97,effd7135) Z8(d6d47369,e55bd24f,8b08e05f,0da8747a,c0313422,7db70ff8,92b614bd,824517a0) },{ Z8(3e773d17,edf5e690,9a37330a,2acc12df,0a907372,7388f12c,e7a41922,8857a695) Z8(57e7fecc,0b094566,19cc8db1,0e333739,07c5e468,218d021c,450ce036,70ef875c) Z8(42c3f8e7,bea7363c,0e3518e7,541b658f,a1ac6b95,ea6f3ba9,b6f2a4bf,46764eff) Z8(a30f6bc4,46d9f746,45a3b1f1,132a448a,e5f345c7,428504ec,a41e6c86,eccfaf88) Z8(c15caf04,19ae818a,57838a21,e983816b,c8c16ddc,796b3ca8,cf3c15a0,81100558) Z8(2ec1fe2c,23efaaaa,e79f2a8b,869ee81e,465eeb65,5bba71fe,c8779cd7,f98a3d2b) Z8(09e49c1a,c31b6adb,1bfaa582,a43c07cb,0e0897f9,8f451158,4619945e,8e92b854) Z8(705e55f9,f47ffbda,5b4e9122,0df68e78,6b193f36,b8dc02ad,c663a2a8,3e1aa720) Z8(8ee6881a,28d02705,28674865,932459b2,2f1bdb80,caaf7242,1f95f583,4c044c01) Z8(89ba9460,26630c17,b05c634c,207adb5c,0ce568a5,c23f5fde,10840ab9,e054c67a) Z8(32e4e333,481c96cb,e29bd222,78344cb7,589017da,04fea1ed,6337342e,6a6d2af9) Z8(12259a79,6cfdf755,7c922241,44cfd362,240de068,424f1f28,04980385,40d8bda2) Z8(8f3cece2,39dda308,d07731b2,3057910d,5cabbc15,ae74908f,88fd32d8,9470ece2) Z8(83432267,c27f4978,02e79d4a,42f58a03,b3c5ba95,21deba9d,2ec04c78,ac98040c) Z8(0218cf09,9a4ebfb2,1cc69ad8,c003b3dc,0a814256,2cf34132,969f4073,166c8be5) Z8(e8228347,11cd77c7,3022789b,4cadc159,5fa27a7f,12959880,87320a27,bbcaa038) Z8(5bac95e4,b88cc0c8,2ba5fbe3,763680d3,2b493129,70271c08,7eaa638b,709d69a0) Z8(dd02df39,df1da265,55f54621,fa774885,fc6b810d,8dfa8233,fa75ef14,8265acf8) },{ Z8(cfb6a4b7,79868402,dd0b4183,57ab98aa,307ea3c7,b1cd04c3,38b0250f,1565159b) Z8(138fa9e7,d98917f1,f294cf3d,750a0450,0266e7db,f952b9ec,ed196761,955301d8) Z8(46e7e8b8,02d57180,1f1417d1,b662177e,498f9098,460b029e,c713239c,8f49ae55) Z8(207c192b,53e44dc2,6c10c4c2,56631d8c,283d9202,347f878e,b666ebc0,19e2db81) Z8(965bc8cf,b4e50910,a17caa08,2c4d3efe,1e214ec1,011a76d0,de9015c0,f8ccf792) Z8(e3530687,6d173b8f,d1263d63,011f4615,397b979f,9904baaa,50d5b0df,cfa9ccc2) Z8(7484eaa2,83b58cd1,d464a65a,8dc5aa96,53c2ff5f,bebbc3b0,1e484214,486162dd) Z8(6980f5c2,9503b2db,32598ba2,e5da5e4d,f08d14b6,3e6b4318,4b3db22d,4a234613) Z8(60f230d6,1a3bc490,b5c67788,0ebdbd15,8c0cbf9a,f8218c41,c182e230,cef1090e) Z8(22550aa6,e84cf987,aab3f0ef,41930bbf,923a7859,0b23e0e4,1dfd3871,91e72774) Z8(a6e661df,112ffe98,7142ae71,7643bea6,02e6626a,529ac862,c35fa443,a4ee0a26) Z8(8710d918,a2827dda,5e50440c,56c6bf6d,d7976cd9,890a75c6,6386bdfb,575b581d) Z8(0ba10c08,fb2c4ee9,7a332bbb,53ae2485,394856f3,8ca8f664,2536bc28,8898dc3d) Z8(b310e0dd,6f185f89,d16861f3,2c1ced51,5aa60c53,fb8e929c,3ffe6029,0239390a) Z8(e3283544,d8d7011f,6b6f7f12,e968f51f,ed940fd8,498e3afa,333d89f5,a9f92576) Z8(839344f1,6e5a1eb7,4f4ed6d3,327b954b,d77698bc,0100a125,b18c0688,295f01bf) Z8(2aff18d3,8a31a8cd,bcf94f83,66a19fd1,42d9b6fe,41da9652,16a3dd96,1a75fc21) Z8(12a99dec,c67acf4e,181af4d3,277b532d,6f1fc743,6d0fbdc3,bd1036e1,82864a77) },{ Z8(ddf6d755,e4d98143,5ec1a861,6b369367,51a3a2bd,71feb549,b4f585e0,3e4af603) Z8(24855537,ac0a2d70,0ce3d6e2,5b7e5d08,2429e1c3,df135ffc,02961f0f,61e2a0dd) Z8(1e64a319,18ab7c59,1ff14ee8,907e6988,22c73999,d5b31998,9ac480ea,194398aa) Z8(6c99b7f9,535000e6,5b06f0af,e34458fc,7d625dfd,5eed6434,988a3e98,741689e0) Z8(897cb4c8,808c75b1,74dfc6a0,f0ba82a9,e2fad3a5,73b437c6,2f8555d1,d45f1e9f) Z8(744dce29,2a536caa,4cc95a8a,2cba0937,67b7fd18,916c2c14,072ae087,7b997ad3) Z8(b6146823,0e4c8340,794696d1,d142a9a6,1868d765,06a040b4,117e357c,0f60d2d4) Z8(3dfbc0b2,98f17a1a,47573957,ec6e4f6f,d515ea44,5831cc96,38a43956,b6004e38) Z8(10d99e20,43b0a8f5,cd6e6401,814d2920,2af06e7c,aa50f86e,df33795e,300531ed) Z8(00afdf7c,b75bc911,2139c83d,eb62bf54,afaa5402,eb8e6f13,bb730380,4daa0a1b) Z8(a830e4d6,5e5bb2c0,87b0e73e,5e856bd7,c9556ca8,decdcb73,50ccc014,70afba46) Z8(78e711db,72db03ab,e61da296,c186641e,362bb9aa,f39262aa,aef64d9b,833a0eb2) Z8(d7b20033,46b2e2c1,9f39e686,d1e58688,09b39e37,d8700cc9,9ee68d8a,62981a4f) Z8(a9f16297,6cace8e3,b2faa647,265a69f8,60ea4cd4,182fc2b1,1f414eac,2c9a532d) Z8(048138ef,4e500068,2c337898,095d1073,0b848d2a,c940f571,3b4007f2,3f787cf0) Z8(a6f97b1d,c01ded7e,ff1bf5bc,487557df,ac309e81,055b977f,8267aafe,3f28a6d4) Z8(5f34335e,a67e86fa,7c4f0aeb,7b51a154,6d94a7c4,edd97eaf,bbf4584e,2b954d25) Z8(aee04add,777733ab,730d2e1b,fd10c339,1b7f162b,8a053b35,e45cdb05,82a6f01e) },{ Z8(9e34a0e5,8e45316c,145b1d88,62b5e62a,82fbce12,de3840f4,e35de3a7,796743e3) Z8(ebdf75a6,86354660,0a862449,6ee64b13,184f2697,afa9fe7c,4e07ed8e,3627b59b) Z8(52bb4c61,504ffa38,3700f1cc,c424dc10,da6bb3b6,93abb790,3498b498,00aa8ad5) Z8(7ebade2a,60dc8b7b,a0551175,d55bca3d,04a255c3,d9a10dfc,3f9ebb66,9b913191) Z8(e6e3464b,eea61d97,9104aa7a,01df9cc7,fc13f975,99dbe485,7662b1e6,7d32a1d7) Z8(43479ba4,7de0efb5,82852a42,1e2e5c83,ac66f9aa,3c803982,a1d0f842,742d7098) Z8(90a3d729,fcb7d261,53ebcbee,e7fb86b2,9578b1f7,89632790,cc9f282a,c77922ef) Z8(88df3361,042deb9e,d4836f52,b45fc470,8349a661,85034e4b,beef064f,6f42975b) Z8(27c7c075,48b4d677,a852f205,1a89a9e2,f08f2517,982b56de,d4db0b07,d00fbf73) Z8(c42b2498,b0ec1a84,9ab08f9d,2286e67d,34429b26,b5e4d1f3,18cfcc46,d81b15fd) Z8(9b0794b8,2bf83ee3,9bff509c,d1917416,d3108b26,c3a4c0d1,1fd50966,727809b6) Z8(b0bf3c8d,64bb003b,62881a53,26d73bdc,aafd090e,9647ed58,51b2b0e9,f7800126) Z8(02f0f9e9,8aa0733d,28e3aa21,4f929c38,d40ac272,68721029,df6a8e28,9a5e372f) Z8(3576be30,c5c235bc,c44d86ff,0634547e,69dc2175,796e10b6,ba53cdb1,c87d17b2) Z8(0d008731,0166fa9a,1dabe1c2,05a53ed4,522dcd79,19417174,b0c77883,05fff956) Z8(77f38f97,d5994dd4,86032022,e0d52031,590ee22e,e670b2fe,75c019ab,d94cf216) Z8(cd4aaa03,2fe6b924,17ba3ff0,3abb9ae9,6c682b0a,504683c4,ebc85240,ef886d81) Z8(27f8a0ac,611a20a8,724def7f,cb17a122,36b9b9ef,27b74b84,7ab650ae,82c79df0) },{ Z8(9f715264,9972a371,5d4bbffb,7a82d0c5,a1fae488,53fe2822,250332c7,12b97f9e) Z8(c311069b,42172a47,6c395440,4092b214,f48d5c6d,08bcf068,02aa3405,6a381784) Z8(4f7a20c3,e64cba7e,747c1269,a53abc16,6df0a83b,d02a3ade,b9ab2684,d6eaaf8d) Z8(cf6a9b8c,43e41d53,aaedac06,66cfd836,83067c05,58b15cca,2e269c8c,0033e097) Z8(c960e09d,011c2126,f741b105,06a2a2ae,5068c9db,c2899b37,89db5786,b100fa9e) Z8(49557465,3c47cc42,ea6335cb,7540d371,a8a57c79,86c9fe04,b1577217,a67a701d) Z8(f53beb0b,09a08713,a8cd6c49,83ccb07b,40638038,1554ceb3,facf2b44,326a9ef8) Z8(6c3b601a,4ae1122f,7761bed0,2ec9cfdf,0c33bf6e,fd552f2e,165b63d9,c28ed506) Z8(c5b9d307,f8cc90ba,57245268,662110ac,58b5589a,b72f6333,2e9e3bb1,0e44e718) Z8(25f24108,3b405e5d,73448f43,34b596f5,ae3ca19a,692c6dc0,fcfdf3c5,af33f8ac) Z8(dd5589d7,fcebf18b,44565e00,020361dd,7fd7c944,99489a5f,d129eaf7,572d27f0) Z8(f33aca3b,86a6a777,047cc3ae,ac19b6da,878c189c,d765e51a,4491feaf,f02ee6ec) Z8(def28fb1,354a5570,c56fd08e,46aab18c,da2bec1c,006c89c1,2ef18f02,6a8fbf4e) Z8(c528001a,9b0a4292,77d124e2,4bc7ad22,4c8d38bf,c3729c40,452c5c87,9597e913) Z8(d54dc4e4,d4dc3e55,e552812c,2fd14e33,2081e22d,3cfb445b,c36d1f11,7172459e) Z8(70f4fc44,b271a394,d6e7d2e9,2965eef3,4c0de317,cbb43e06,97ca7899,15a8bdeb) Z8(314e9ce2,b4ab7ec9,1d815e30,afb761e4,205a7b1e,47de6859,e507a4a9,17833d99) Z8(0fecfc67,070bad1e,3b4d5cb5,ee149c78,c80bb990,044e73d0,8af9b3fa,82e853ee) },{ Z8(73d413c0,1f7ae3a4,7465c0d1,d85ff896,82ac87c1,ca95f0ae,9a0e974e,a2cf8b7b) Z8(9205133d,70d164fb,5cd8de28,2e81a632,1a9cf417,d777f8c9,dc03afb1,48d1e5c0) Z8(2752d29e,0ed2b6c8,fd1339de,bae71a1d,b53389e3,bb75cfce,5087e807,e446a3da) Z8(b0ae23ac,57afbb56,e60bd9f8,892a2ff4,5f36e9cf,05a77471,72687356,feb5700c) Z8(8d0377be,ebfa08aa,adbb7f5a,e0aea97d,37fa388b,74d2ee0b,08e60e8b,e86cf117) Z8(6f191153,a067b921,a2ca0879,5591ea0c,03c00a9b,13efb251,c8ecd6f4,69b3c825) Z8(4e81d490,b7481d78,7af2fe3d,8ea037a7,3c6be65a,d660397b,28af8be4,a7af5f53) Z8(42f4b91d,a43ae952,3fabbec3,e5f52d10,e9528fd4,fff9b9cb,a962dfb4,a622fbec) Z8(530fadd1,0011160c,144e5a8b,307cdabb,ea727153,d9b468cb,323e5e55,b689f138) Z8(cc9de433,6f322e7d,dd09e610,77ab3333,dc63db3d,3a346df4,fd40d479,6154e47e) Z8(9970326b,2d7b71c4,4b2168ca,4237fbb5,ee7e7fbe,9871cbc8,2c903f67,b25d78ca) Z8(95d9ce14,e2c17570,00735ae3,11b746ac,de90d49a,8dedd5b1,2dcf2605,20f10c0b) Z8(17af7c51,95bd9bdf,7fca9d79,45a03b9e,b43fa719,dc491d17,523a99b1,b7b59f58) Z8(05f6785e,cd97db3e,0591ff15,988ef51e,3617e492,8c484f33,133b7351,b74eab9f) Z8(bbb01b1a,afaca1cd,0b96ab99,0f0b9793,cb2e9683,86d0f570,5b6f9e63,222e2c7c) Z8(985e4c0b,4ef1bdca,a6ed00d9,86ac418e,d32506de,a3d2f307,bbbf864b,0c38e828) Z8(31ae8d90,71b06712,3048b19c,41ae308a,8b915b5a,6e3f14ae,271261f8,88ab6a8b) Z8(c8bf2dd3,173a4446,46104e0a,42bd2733,4adbb70d,2b2cebaf,2086e8a7,8309121b) },{ Z8(3f8c1df1,e4322c82,94a6483f,97ae87f3,ea89ccd3,610040b3,08ee1d83,390d58ce) Z8(1b053e8e,d32bcdfb,4f4e847b,06d91cdc,64c56d11,c3158e31,d1574064,944539ef) Z8(f8ef7352,ac8d28d8,4d3e8af2,38aecf89,291765a1,70ef1b6d,102d664f,59bb3eba) Z8(41d68f52,88d2d42c,7d7ddbf8,b1ab14e6,1aea0781,750e33c3,acd4c566,892e3925) Z8(110302c4,432eaf53,c21746c0,8ed70838,034ec83c,733f5327,efa8cf7e,60799031) Z8(b9d6bc2f,c3067ec1,5fa0ce80,2c52d965,0e0c2c4f,c109a004,f3173aad,3ead62c3) Z8(67b410a2,6f5959f9,9c721f9a,dd0a972b,d8565384,a90e780e,8f0d0709,9a3225ea) Z8(8a760ca1,cc19b08d,2687812c,389f1184,cfd447d0,17164516,c0baa1c5,f39f1f79) Z8(da652b2c,36b5dd25,9bd6afa3,b3dc511e,0a60a879,42abf824,02687364,0b50e4d4) Z8(6a703a69,306020a3,b5f21bc8,9465b928,3a2b8c92,162c334e,18692e26,2210d4e1) Z8(5a688353,11731406,a6488979,39e5785d,573733da,a9516a53,313f06e0,bc561397) Z8(aec0abb9,3211ad6a,0ab470f5,5a4d7b75,9a55dee8,16b241c3,99514d86,81793655) Z8(bbc0247b,127a5542,34ec3dce,c1a6a9fd,27ad1dff,9b95eda7,2654ff36,f42f9ec1) Z8(3dd6f891,5fbb500f,0e68477b,c73d801e,9dc26d66,13b9b242,e9ab98cf,3a023dc8) Z8(e92114de,6cb7b2ff,45ebf158,6aec3697,f1cc372c,ffed27c0,4701d314,8df1bf98) Z8(e845fd5b,77311012,663bb5a9,93cf0bb8,da38d0d2,c2aa570c,57324a12,c0999c31) Z8(3a5b6d14,bbf8c2e2,b5ba21a6,d36859be,7dcc8112,2675cf97,5a170b76,b165739b) Z8(f1070c4b,c64a4de6,838c37bb,2d051cd5,e3f800e1,f3561b31,4740bac8,8329d878) },{ Z8(c34eb12c,905e975e,127ca3b5,e234dcde,f8000483,773640d7,a5e657f5,0668391d) Z8(ac46031a,228f3da4,97e0eb8b,21ab198e,e86ca9e9,9852bfd4,975b4acc,81cac866) Z8(3f99d704,88256372,c493168e,c0d41eb8,fe9e0eb3,9407d438,59b1f289,a7467702) Z8(23a85c95,0b187e48,b47db0d4,54a7adec,27110129,8bc68e90,20a5ccf6,d26f9e99) Z8(4f32d150,8a7faff3,e4c921bf,1ef10b20,a2adc345,14e7f308,7c7dd77c,22b5e4b1) Z8(abc25196,052d6ad0,981a0055,034fc6a0,26ab493f,12ca3f77,aabcdf85,61253c29) Z8(a386e3bd,3e9dfbf2,528b1c95,1734209f,0fdecc2a,5cf85d9e,2f301463,ead330e4) Z8(ff80fd77,4329ffbf,be094b8b,1e6c163e,67c6478b,cb30bf55,8cd6b9ae,063d0e2b) Z8(f19ba52a,b1225cc7,d84b2bc0,1f53ef95,83fd8a3c,1777b7aa,a17a76a1,fb3cef0d) Z8(d1722162,863183f3,5263a314,9d0efb8f,574010e6,51ff61f0,947f6721,0cd353e0) Z8(6519bae1,b30d556b,71da75d5,d1120156,a48e6459,bd58c0f7,f08ef6dc,6a7722be) Z8(3938742d,74ca530c,130b800b,c2295540,2c8056b6,6592025d,14311f60,5d393b5b) Z8(831a1977,a892829b,3cfc046f,2303de25,e592056c,a4b3b3e1,96d940f2,c6c01fec) Z8(2ec5801b,46cb55a8,02f7eff5,037b792a,b78f86fa,09cc8011,4cde211c,3635f154) Z8(3bcd4bbb,0096cf1c,3084f14a,7a4957fd,de43ae23,7e3fb84f,57e3fe17,e0e8ba01) Z8(7b4121ad,4f3deace,4be99716,7a413e43,fd200b07,4dbe9978,fb5979c7,1d0544e1) Z8(04bd9cf5,053a80d2,e357ac36,e3143be3,d405dc9e,bc80b9b7,86c177cd,cc475afb) Z8(05136fed,b05103c1,8f0e13de,b1fbb029,5ba79cff,2c5b7894,0b8cff86,834aa708) },{ Z8(10840286,3344252e,c62725c7,fbc55b14,fa5072b6,7d68fa8c,3a0822e6,9ca0d28f) Z8(ee51e8b5,a454badb,1b89eaff,9e5d04a2,f4baa9e8,eb0b78f6,d95382c9,c76224b3) Z8(15a8a55a,5e053a74,f4f1072c,1f1ef6e7,fe91b150,6cf51e7b,ff45ccc0,67c7a0b7) Z8(664f174e,b3cedada,f02e0599,2e9c1b3f,67268103,07e82992,57ad2723,d2f204ba) Z8(85f67903,ccaf64f1,93de39c1,c36b9307,db95b313,b175e1b2,a623be7c,e659cf05) Z8(1f159e3b,9acb138a,d8448b76,2221e262,73090d86,6cd994ff,54e0dfc1,3f290c0c) Z8(2787b53e,57e66134,bd7fbcdd,7ed1d8a3,dbc81f2f,bf8756dc,38bfb7a3,f34e9651) Z8(616a8a4d,f7a97e47,5d803dcf,a559ef08,4dcf9dd8,f98effd6,0da29bc7,c9b65924) Z8(46ff5391,81c79f42,3804cfee,1369f16b,3b441aa4,c5385f68,b8901d61,a83102d6) Z8(7914b5cc,2ea4acc2,0dd3e939,364416ab,d2e84eef,2b8e000e,1457469c,fd9f7102) Z8(aa26647f,fdc15186,62322cb0,7ecd4175,377cc543,174ec0e8,56389e3e,1d56555e) Z8(740d707d,2cd606b1,2965ff8d,ffa0c334,2d01d6c0,0f17b9b8,8b979a2a,88b77400) Z8(cdee758d,c640d768,0f9d7005,d69d15aa,a14aa456,bcf6e661,4361a1d0,dd2df57d) Z8(1fb36886,128882f8,154bee83,2de36d34,49030bbb,9ec414d7,9d4d7b7b,55ee77a4) Z8(757c4992,b1f8c839,43f1570f,f6f832f2,f1688e13,52f077af,95e8c092,1bbf64a0) Z8(84c38992,7fbbb6fb,63759b1d,f6d3dbeb,5eec379a,95fba491,c96e64e8,cde4e7d3) Z8(f6019f17,65ffbbfa,a7c65176,b0bd9b51,2a7f9aee,a1a8b2f2,76b7ddfb,96a6b277) Z8(1d28664e,394cf091,ce2e513f,0e041143,64edccbd,7bdaa85c,7a54b5df,836b7dcc) },{ Z8(de41663a,99ebab9e,a6ac30df,d06c8e5c,9f4bdb0c,36098828,754bc75a,654c728f) Z8(d3b735cb,4f1f7f10,4952b0d6,74f2031f,0ef0700f,91d0812b,3bab0ed3,203a54b4) Z8(b9fe8670,d483f6c2,fab02170,9c894aca,90833137,7cfd9ac6,891a7f91,ab90b004) Z8(e43818f5,d2965197,fe34ef38,a46dd584,bb9a7588,93635323,af40f0d1,ec72ff86) Z8(cdada7de,e6d77f3a,8f1ac358,330d9994,d9012617,d9026dea,91641d65,5c7c8778) Z8(cbc6a1b9,e02af9c6,33b8aee9,78269a91,8bff3930,bd4b644e,ce20e423,f3bf8bc5) Z8(815975d4,cdec5ac1,6181f6ff,a87eeff6,715fa20f,f3dbcfba,1e70d689,9f48653b) Z8(428c9366,5f550b5f,726a4ff6,75671b0a,29aff8d4,034c6e1a,40369684,bf9bfb51) Z8(40fa121c,c9e0f6e5,7180d3a6,639abb6b,affccb58,d35a2cc0,37b621fd,4b6dce9d) Z8(ea9820e0,fc53df1c,a9163ad0,4de0c220,3c3f5aaa,9f40d5bd,9e0047f2,beb6f5ff) Z8(382c983a,ec2b7ead,df9af3e0,a91aea59,ca7e6b6e,21e3bf08,04e9b52a,2395a6d3) Z8(b86c0de0,a53aa038,101a324c,055b0d93,cf396c79,07bddc64,4e63f0d0,25bd4763) Z8(1b8aeb13,554a0c62,e4b5c2df,4ef3a8c4,48a43578,f0c6b8d4,5efe56c6,5224d534) Z8(b616f25a,ecd8dfa7,4773c333,5e2336f8,7b17b005,7a0c4566,a5c5c63a,c3ac242f) Z8(570fd17c,f1e1d9b3,c7da6177,dfa9a67a,c681fc71,fcc4ff78,7d3f729b,c94ced0b) Z8(59b3da90,b00249ee,870dbe26,044679c6,78f3b93a,13d691d1,12faab31,531a9fe9) Z8(b08d6622,76f0ab8c,58614061,045cf4ca,0746e9f4,dab69d5e,fa9674f0,8a9a605e) Z8(0ba1fc43,a77c428f,30830a66,3f64c60c,cf3484c2,ed9945c8,a104277d,838c5cc7) },{ Z8(670b6f10,dbc446dd,d3954564,eb1122e2,bc7f17b6,e04ab0e4,c8c9e19b,b10c5e44) Z8(05d5920a,fcb4ea0a,8a18441f,e5e98b1f,7062ff81,96a76cea,85196240,d1801f17) Z8(e477b581,0012a52a,5993c8d3,4f1d0cf7,b84ef443,de5df3d7,75bfae21,a4695f77) Z8(77223e50,d7858f4e,9c2ea463,873eb49b,b9dc7b95,949515b1,fce9102d,fe909358) Z8(1ce16e0b,c5322b1f,250bb958,4d3f7c5e,0041bbfd,5f498731,13e877b5,b7c836ae) Z8(5e32e0b3,2adf7bb2,c8b941df,26b88261,a06b4fc7,dcc9b37c,edbf19ba,e2c0aa44) Z8(8a90f2f5,12e9a338,e2e061bd,20c49b13,72c9f7e2,3bac46e2,11c5e32a,8be03cfa) Z8(9a75f681,6d54be1c,811efadc,8ee37b5d,254b880b,6b28d48c,16d55b9d,5426affc) Z8(6e8c9949,b54ac27f,780a3017,99fa1cac,7e88716e,a8eb803d,66381ce4,f5782a33) Z8(f80f0163,01385e91,a51888d4,f6319343,fd6aeb59,d4e8b19e,865e46f9,2a6b2c64) Z8(129cb795,b3d73a67,cb148868,c219b304,df5cc89b,3df449b7,6508b16d,4468435e) Z8(511203a4,47a40d3d,182e9cc6,6a63a0c0,d67ecfe6,fd101365,7a76c65c,8b4f4de7) Z8(76469065,a732e2bd,23a0e573,b4c0da5c,3791a7f9,50602810,9fe9839e,3e0d053e) Z8(b793c856,a26daf3a,0d124ee1,cd80439a,9e5f1556,1ac73bf8,03f534ff,ca68f1d6) Z8(00c0a4ef,5dafece0,1e90086d,f5483978,f625ba36,a5f78e71,9aa514db,5f4738e9) Z8(f46fd33b,003bfff4,6bb9cdbf,4ef637b6,cc3b93a0,1e357509,7a71463f,04758447) Z8(7d17438a,b33ce5e8,0f41c670,4a4cfb89,a9867bac,7aaa01f4,d66c8f57,2153dcb0) Z8(aea6dd81,4a153cb2,2f3c452a,7aed07ea,1ac6253f,b84b3c94,8d8b0989,83ad43fb) },{ Z8(15f79984,82e633cf,42fdc5ff,daf04198,d677761e,9bf9da32,aa495f79,bb45a080) Z8(1862e2d4,e37bea61,2f78ec3e,d48fea60,728257c0,66c0bd11,3e551602,ce8aeb6a) Z8(3f27cd8e,39e1af4a,6380535c,d0271f82,3fe19e7c,ab0a5467,693e8deb,c39435fe) Z8(16982fce,4468bf44,af704a39,8e77d97b,c3e46abe,52faffc0,6269fa1a,36e0f307) Z8(43f90176,dc3b5d52,641915a4,62844894,2d09adb2,5f48b72e,cb2d9e47,196ec667) Z8(272527b5,2847c160,ceb2c6da,a3122105,2fc9e25d,6b6517f8,42178292,1a2e34a0) Z8(b675b8a7,5da754e3,91a07155,71f1f29c,b37e91d4,9ea78fcb,df5201fc,ed7dbc76) Z8(161348bb,709f41c7,394c7f1a,f19950e4,34356def,cb64e1b9,368a6967,d9c64ee2) Z8(c766e14a,2a415c73,76ea0ee8,6fd4ae07,a975e709,6d0f1884,889fbf08,5fc4fdf6) Z8(cbfaadef,1cf057f9,a0948ffb,1d4af9b1,a41090b9,4ee66a5e,9dc96ae2,b6fcba5a) Z8(fc4d3696,fdeaaf7a,108d77f6,670adff6,0337411b,ec968529,00d69769,6baa9ef2) Z8(f8842548,79c1ad91,3c5ce97e,3bb4ff1b,07931255,5a37e1c2,12f7c7ce,46050794) Z8(457fd26f,3803f4a7,29f9d8dd,ad6c4e5d,f8432d51,79d77b93,673b83b6,b23f682d) Z8(504d71e3,9841f102,b00446a1,9fdea7f9,ae5b7d29,780c0eb4,1811851f,c981e0fb) Z8(05cdddcb,4766e0e8,9abff3f9,f1ee1b24,38a11570,bc8aa198,2c8e9bf3,de798f84) Z8(9422f785,b11e300e,83a93790,e6a38105,36b7cbcc,fe581a20,46bcd3e6,cd3c6130) Z8(c33732f1,e32670a7,fa9542b2,c885dba8,638b96bf,0cd6f265,48f34e84,6f8a790d) Z8(e4cf116e,f92cd86c,1ea56221,98c33887,924302f7,39112059,4e5c9d89,83ce336a) },{ Z8(980a6d14,45b265b0,927d1ebf,982633ab,0bad903f,f824647c,64791718,feb25b07) Z8(ba9e2173,313f6ad2,215fb159,cb53805a,54f4c674,ad2e7ab8,f2e583dd,d5af9385) Z8(6db3c27c,60919709,a0a1dfd5,39ef44d9,ca194999,ee7f2d59,bf910ca2,09a3bccd) Z8(310d9f7e,76560e3e,14d0d050,f88e67b4,1376e14a,e2d058a3,fa9f3a4a,474edff1) Z8(a7d74daf,6c637128,3b5a3115,19aadb37,b8eedc41,acb2f943,9ea33b84,4f465104) Z8(af96a84f,acdb6210,78723e4a,6cdd9743,bf97656f,4e1b63b3,bb475cd6,324fe765) Z8(f9fe83f1,5a58c09a,583b8ab1,666b63e2,f04b3a5f,962a18a5,11aec1e8,15814857) Z8(cbeaeff9,d0deccf3,336aed3d,f5cd32b9,54c0561a,5cd6723f,dc69ba6a,f0f161df) Z8(2b718884,a6b416d0,3465bdae,151de167,f023c71c,88deaf97,e1d438d2,f81f4c9e) Z8(001bf582,01c3d0a5,a163750d,259d7c59,32f3629c,2e48b09d,4610b706,cc2ad7c5) Z8(bc19d6d0,a8f8bf96,30ec3190,9bbc4bda,98576ff0,c630dc4b,128f36c8,0cb87b4a) Z8(81b78882,119850ab,33d3ae36,4e85426e,8a84d83d,063d0e81,f4a8357f,a01196df) Z8(7b0bba13,09ae65c6,986ad834,fd0535e5,8d108d10,bc9c5cc0,103ecbff,fbe03879) Z8(41643aa5,d2eb49c4,661cce39,bcf3134f,4131119e,57c0ea21,9b8fac86,1cc07da2) Z8(3229416d,ec45cad3,121f4b23,386b4f13,5c1236be,8d8e84d5,ceaa823a,f87d396a) Z8(3b8f3b04,b98d2785,6b39013d,414a26e1,6e4708c0,1582cd67,680379f4,c750387f) Z8(3ff6a04e,fac0f617,19c31758,9c3d1729,51d3f338,bc414a7f,2a31b689,90223629) Z8(0d371e0d,232759e7,95cc9009,6f7c685d,8bc8b40e,27bc7157,f26fd248,83ef2b15) }}; flint-3.1.3/src/arb/exp_taylor_bound.c000066400000000000000000000053701461254215100177140ustar00rootroot00000000000000/* Copyright (C) 2013, 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #define TABSIZE 256 /* bounds for log2(1/n!) */ static const short rec_fac_bound_2exp_si_tab[TABSIZE] = { 0, 0, -1, -2, -4, -6, -9, -12, -15, -18, -21, -25, -28, -32, -36, -40, -44, -48, -52, -56, -61, -65, -69, -74, -79, -83, -88, -93, -97, -102, -107, -112, -117, -122, -127, -132, -138, -143, -148, -153, -159, -164, -169, -175, -180, -186, -191, -197, -202, -208, -214, -219, -225, -231, -237, -242, -248, -254, -260, -266, -272, -278, -284, -289, -295, -302, -308, -314, -320, -326, -332, -338, -344, -350, -357, -363, -369, -375, -382, -388, -394, -401, -407, -413, -420, -426, -433, -439, -446, -452, -458, -465, -472, -478, -485, -491, -498, -504, -511, -518, -524, -531, -538, -544, -551, -558, -564, -571, -578, -585, -591, -598, -605, -612, -619, -626, -632, -639, -646, -653, -660, -667, -674, -681, -688, -695, -702, -709, -716, -723, -730, -737, -744, -751, -758, -765, -772, -779, -786, -793, -801, -808, -815, -822, -829, -836, -844, -851, -858, -865, -872, -880, -887, -894, -901, -909, -916, -923, -931, -938, -945, -952, -960, -967, -975, -982, -989, -997, -1004, -1011, -1019, -1026, -1034, -1041, -1049, -1056, -1064, -1071, -1078, -1086, -1093, -1101, -1108, -1116, -1123, -1131, -1139, -1146, -1154, -1161, -1169, -1176, -1184, -1192, -1199, -1207, -1214, -1222, -1230, -1237, -1245, -1253, -1260, -1268, -1276, -1283, -1291, -1299, -1306, -1314, -1322, -1329, -1337, -1345, -1353, -1360, -1368, -1376, -1384, -1391, -1399, -1407, -1415, -1423, -1430, -1438, -1446, -1454, -1462, -1470, -1477, -1485, -1493, -1501, -1509, -1517, -1525, -1532, -1540, -1548, -1556, -1564, -1572, -1580, -1588, -1596, -1604, -1612, -1620, -1628, -1636, -1644, -1652, -1660, -1668, -1675 }; static inline slong rec_fac_bound_2exp_si(slong n) { if (n < TABSIZE) { return rec_fac_bound_2exp_si_tab[n]; } else { mag_t t; mag_init(t); mag_rfac_ui(t, n); /* todo: check for overflow */ return MAG_EXP(t); } } slong _arb_exp_taylor_bound(slong mag, slong prec) { slong i; /* assume x <= 1/4 */ if (mag > -2) { flint_throw(FLINT_ERROR, "_arb_exp_taylor_bound: too large input %wd\n", mag); } for (i = 1; ; i++) { if (mag * i + rec_fac_bound_2exp_si(i) < -prec - 1) return i; } } flint-3.1.3/src/arb/exp_taylor_naive.c000066400000000000000000000026261461254215100177100ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" void _arb_exp_taylor_naive(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N) { ulong k; mp_ptr s, t, u, v; mp_size_t nn = xn + 1; if (N == 0) { flint_mpn_zero(y, xn + 1); error[0] = 0; return; } s = flint_malloc(sizeof(mp_limb_t) * (nn + 1)); t = flint_malloc(sizeof(mp_limb_t) * nn); v = flint_malloc(sizeof(mp_limb_t) * nn); u = flint_malloc(sizeof(mp_limb_t) * 2 * nn); /* s = 1 */ flint_mpn_zero(s, nn); s[nn] = 1; /* t = v = x */ flint_mpn_zero(t, nn); flint_mpn_copyi(t + 1, x, xn); flint_mpn_copyi(v, t, nn); for (k = 1; k < N; k++) { s[nn] += mpn_add_n(s, s, t, nn); /* t = t * x / (k + 1) */ flint_mpn_mul_n(u, t, v, nn); flint_mpn_copyi(t, u + nn, nn); mpn_divrem_1(t, 0, t, nn, k + 1); } flint_mpn_copyi(y, s + 1, xn + 1); error[0] = 2; flint_free(s); flint_free(t); flint_free(u); flint_free(v); } flint-3.1.3/src/arb/exp_taylor_rs.c000066400000000000000000000742411461254215100172340ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" /* See verify_taylor.py for code to generate tables and proof of correctness */ #define TMP_ALLOC_LIMBS(size) TMP_ALLOC((size) * sizeof(mp_limb_t)) #define FACTORIAL_TAB_SIZE 288 #if FLINT_BITS == 64 const mp_limb_t factorial_tab_numer[FACTORIAL_TAB_SIZE] = { UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(1216451004088320000), UWORD(405483668029440000), UWORD(101370917007360000), UWORD(20274183401472000), UWORD(3379030566912000), UWORD(482718652416000), UWORD(60339831552000), UWORD(6704425728000), UWORD(670442572800), UWORD(60949324800), UWORD(5079110400), UWORD(390700800), UWORD(27907200), UWORD(1860480), UWORD(116280), UWORD(6840), UWORD(380), UWORD(20), UWORD(1), UWORD(169958063987712000), UWORD(7725366544896000), UWORD(335885501952000), UWORD(13995229248000), UWORD(559809169920), UWORD(21531121920), UWORD(797448960), UWORD(28480320), UWORD(982080), UWORD(32736), UWORD(1056), UWORD(33), UWORD(1), UWORD(405179306820288000), UWORD(11576551623436800), UWORD(321570878428800), UWORD(8691104822400), UWORD(228713284800), UWORD(5864443200), UWORD(146611080), UWORD(3575880), UWORD(85140), UWORD(1980), UWORD(45), UWORD(1), UWORD(129210868410624000), UWORD(2749167412992000), UWORD(57274321104000), UWORD(1168863696000), UWORD(23377273920), UWORD(458377920), UWORD(8814960), UWORD(166320), UWORD(3080), UWORD(56), UWORD(1), UWORD(13431688016947200), UWORD(231580827878400), UWORD(3925098777600), UWORD(65418312960), UWORD(1072431360), UWORD(17297280), UWORD(274560), UWORD(4290), UWORD(66), UWORD(1), UWORD(51698307350592000), UWORD(760269225744000), UWORD(11018394576000), UWORD(157405636800), UWORD(2216980800), UWORD(30791400), UWORD(421800), UWORD(5700), UWORD(76), UWORD(1), UWORD(166872705665702400), UWORD(2139393662380800), UWORD(27080932435200), UWORD(338511655440), UWORD(4179156240), UWORD(50965320), UWORD(614040), UWORD(7310), UWORD(86), UWORD(1), UWORD(4900933563926400), UWORD(55692426862800), UWORD(625757605200), UWORD(6952862280), UWORD(76405080), UWORD(830490), UWORD(8930), UWORD(95), UWORD(1), UWORD(10385445095625600), UWORD(107066444284800), UWORD(1092514737600), UWORD(11035502400), UWORD(110355024), UWORD(1092624), UWORD(10712), UWORD(104), UWORD(1), UWORD(20632508204394240), UWORD(194646303815040), UWORD(1819124334720), UWORD(16843743840), UWORD(154529760), UWORD(1404816), UWORD(12656), UWORD(113), UWORD(1), UWORD(38823716505974400), UWORD(337597534834560), UWORD(2910323576160), UWORD(24874560480), UWORD(210801360), UWORD(1771440), UWORD(14762), UWORD(122), UWORD(1), UWORD(69746158460160000), UWORD(562469019840000), UWORD(4499752158720), UWORD(35712318720), UWORD(281199360), UWORD(2196870), UWORD(17030), UWORD(131), UWORD(1), UWORD(120384786168259200), UWORD(905148768182400), UWORD(6754841553600), UWORD(50035863360), UWORD(367910760), UWORD(2685480), UWORD(19460), UWORD(140), UWORD(1), UWORD(1346749373249280), UWORD(9484150515840), UWORD(66322730880), UWORD(460574520), UWORD(3176376), UWORD(21756), UWORD(148), UWORD(1), UWORD(1961463552048000), UWORD(13076423680320), UWORD(86598832320), UWORD(569729160), UWORD(3723720), UWORD(24180), UWORD(156), UWORD(1), UWORD(2802505908948480), UWORD(17737379170560), UWORD(111555843840), UWORD(697224024), UWORD(4330584), UWORD(26732), UWORD(164), UWORD(1), UWORD(3935446603320960), UWORD(23707509658560), UWORD(141961135680), UWORD(845006760), UWORD(5000040), UWORD(29412), UWORD(172), UWORD(1), UWORD(5440248896544000), UWORD(31265798256000), UWORD(178661704320), UWORD(1015123320), UWORD(5735160), UWORD(32220), UWORD(180), UWORD(1), UWORD(7413519413139840), UWORD(40733623149120), UWORD(222588104640), UWORD(1209717960), UWORD(6539016), UWORD(35156), UWORD(188), UWORD(1), UWORD(9970981685683200), UWORD(52478850977280), UWORD(274758382080), UWORD(1431033240), UWORD(7414680), UWORD(38220), UWORD(196), UWORD(1), UWORD(13250183553129600), UWORD(66920118955200), UWORD(336282004800), UWORD(1681410024), UWORD(8365224), UWORD(41412), UWORD(204), UWORD(1), UWORD(17413448982209280), UWORD(84531305738880), UWORD(408363795840), UWORD(1963287480), UWORD(9393720), UWORD(44732), UWORD(212), UWORD(1), UWORD(22651084881532800), UWORD(105846191035200), UWORD(492307865280), UWORD(2279203080), UWORD(10503240), UWORD(48180), UWORD(220), UWORD(1), UWORD(29184853478054400), UWORD(131463303955200), UWORD(589521542400), UWORD(2631792600), UWORD(11696856), UWORD(51756), UWORD(228), UWORD(1), UWORD(37271720825539200), UWORD(162050960111040), UWORD(701519307840), UWORD(3023790120), UWORD(12977640), UWORD(55460), UWORD(236), UWORD(1), UWORD(47207892014680320), UWORD(198352487456640), UWORD(829926725760), UWORD(3458028024), UWORD(14348664), UWORD(59292), UWORD(244), UWORD(1), UWORD(59333143654512000), UWORD(241191640872000), UWORD(976484376000), UWORD(3937437000), UWORD(15813000), UWORD(63252), UWORD(252), UWORD(1), UWORD(284751785364480), UWORD(1121070021120), UWORD(4396353024), UWORD(17173254), UWORD(66822), UWORD(259), UWORD(1), UWORD(334679402201760), UWORD(1282296560160), UWORD(4894261680), UWORD(18609360), UWORD(70490), UWORD(266), UWORD(1), UWORD(391698294099840), UWORD(1461560798880), UWORD(5433311520), UWORD(20123376), UWORD(74256), UWORD(273), UWORD(1), UWORD(456592291848000), UWORD(1660335606720), UWORD(6015708720), UWORD(21717360), UWORD(78120), UWORD(280), UWORD(1), UWORD(530208485286480), UWORD(1880171933640), UWORD(6643717080), UWORD(23393370), UWORD(82082), UWORD(287), UWORD(1), }; const mp_limb_t factorial_tab_denom[FACTORIAL_TAB_SIZE] = { UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(2432902008176640000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(3569119343741952000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(13776096431889792000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(5943699946888704000), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(765606216965990400), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(3463786592489664000), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(12849198336259084800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(426381220061596800), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(997002729180057600), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(2166413361461395200), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(4425903681681081600), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(8578777490599680000), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(15890791774210214400), UWORD(189891661628148480), UWORD(189891661628148480), UWORD(189891661628148480), UWORD(189891661628148480), UWORD(189891661628148480), UWORD(189891661628148480), UWORD(189891661628148480), UWORD(189891661628148480), UWORD(292258069255152000), UWORD(292258069255152000), UWORD(292258069255152000), UWORD(292258069255152000), UWORD(292258069255152000), UWORD(292258069255152000), UWORD(292258069255152000), UWORD(292258069255152000), UWORD(439993427704911360), UWORD(439993427704911360), UWORD(439993427704911360), UWORD(439993427704911360), UWORD(439993427704911360), UWORD(439993427704911360), UWORD(439993427704911360), UWORD(439993427704911360), UWORD(649348689547958400), UWORD(649348689547958400), UWORD(649348689547958400), UWORD(649348689547958400), UWORD(649348689547958400), UWORD(649348689547958400), UWORD(649348689547958400), UWORD(649348689547958400), UWORD(941163059102112000), UWORD(941163059102112000), UWORD(941163059102112000), UWORD(941163059102112000), UWORD(941163059102112000), UWORD(941163059102112000), UWORD(941163059102112000), UWORD(941163059102112000), UWORD(1341847013778311040), UWORD(1341847013778311040), UWORD(1341847013778311040), UWORD(1341847013778311040), UWORD(1341847013778311040), UWORD(1341847013778311040), UWORD(1341847013778311040), UWORD(1341847013778311040), UWORD(1884515538594124800), UWORD(1884515538594124800), UWORD(1884515538594124800), UWORD(1884515538594124800), UWORD(1884515538594124800), UWORD(1884515538594124800), UWORD(1884515538594124800), UWORD(1884515538594124800), UWORD(2610286159966531200), UWORD(2610286159966531200), UWORD(2610286159966531200), UWORD(2610286159966531200), UWORD(2610286159966531200), UWORD(2610286159966531200), UWORD(2610286159966531200), UWORD(2610286159966531200), UWORD(3569757041352902400), UWORD(3569757041352902400), UWORD(3569757041352902400), UWORD(3569757041352902400), UWORD(3569757041352902400), UWORD(3569757041352902400), UWORD(3569757041352902400), UWORD(3569757041352902400), UWORD(4824681079766486400), UWORD(4824681079766486400), UWORD(4824681079766486400), UWORD(4824681079766486400), UWORD(4824681079766486400), UWORD(4824681079766486400), UWORD(4824681079766486400), UWORD(4824681079766486400), UWORD(6449852618650022400), UWORD(6449852618650022400), UWORD(6449852618650022400), UWORD(6449852618650022400), UWORD(6449852618650022400), UWORD(6449852618650022400), UWORD(6449852618650022400), UWORD(6449852618650022400), UWORD(8535224069048476800), UWORD(8535224069048476800), UWORD(8535224069048476800), UWORD(8535224069048476800), UWORD(8535224069048476800), UWORD(8535224069048476800), UWORD(8535224069048476800), UWORD(8535224069048476800), UWORD(11188270407479235840), UWORD(11188270407479235840), UWORD(11188270407479235840), UWORD(11188270407479235840), UWORD(11188270407479235840), UWORD(11188270407479235840), UWORD(11188270407479235840), UWORD(11188270407479235840), UWORD(14536620195355440000), UWORD(14536620195355440000), UWORD(14536620195355440000), UWORD(14536620195355440000), UWORD(14536620195355440000), UWORD(14536620195355440000), UWORD(14536620195355440000), UWORD(14536620195355440000), UWORD(72042201697213440), UWORD(72042201697213440), UWORD(72042201697213440), UWORD(72042201697213440), UWORD(72042201697213440), UWORD(72042201697213440), UWORD(72042201697213440), UWORD(87016644572457600), UWORD(87016644572457600), UWORD(87016644572457600), UWORD(87016644572457600), UWORD(87016644572457600), UWORD(87016644572457600), UWORD(87016644572457600), UWORD(104583444524657280), UWORD(104583444524657280), UWORD(104583444524657280), UWORD(104583444524657280), UWORD(104583444524657280), UWORD(104583444524657280), UWORD(104583444524657280), UWORD(125106287966352000), UWORD(125106287966352000), UWORD(125106287966352000), UWORD(125106287966352000), UWORD(125106287966352000), UWORD(125106287966352000), UWORD(125106287966352000), UWORD(148988584365500880), UWORD(148988584365500880), UWORD(148988584365500880), UWORD(148988584365500880), UWORD(148988584365500880), UWORD(148988584365500880), UWORD(148988584365500880), }; #else const mp_limb_t factorial_tab_numer[FACTORIAL_TAB_SIZE] = { UWORD(479001600), UWORD(479001600), UWORD(239500800), UWORD(79833600), UWORD(19958400), UWORD(3991680), UWORD(665280), UWORD(95040), UWORD(11880), UWORD(1320), UWORD(132), UWORD(12), UWORD(1), UWORD(19535040), UWORD(1395360), UWORD(93024), UWORD(5814), UWORD(342), UWORD(19), UWORD(1), UWORD(165765600), UWORD(7893600), UWORD(358800), UWORD(15600), UWORD(650), UWORD(26), UWORD(1), UWORD(24165120), UWORD(863040), UWORD(29760), UWORD(992), UWORD(32), UWORD(1), UWORD(60233040), UWORD(1771560), UWORD(50616), UWORD(1406), UWORD(38), UWORD(1), UWORD(2961840), UWORD(74046), UWORD(1806), UWORD(43), UWORD(1), UWORD(4669920), UWORD(103776), UWORD(2256), UWORD(48), UWORD(1), UWORD(7027800), UWORD(140556), UWORD(2756), UWORD(53), UWORD(1), UWORD(10182480), UWORD(185136), UWORD(3306), UWORD(58), UWORD(1), UWORD(14295960), UWORD(238266), UWORD(3906), UWORD(63), UWORD(1), UWORD(19545240), UWORD(300696), UWORD(4556), UWORD(68), UWORD(1), UWORD(26122320), UWORD(373176), UWORD(5256), UWORD(73), UWORD(1), UWORD(34234200), UWORD(456456), UWORD(6006), UWORD(78), UWORD(1), UWORD(44102880), UWORD(551286), UWORD(6806), UWORD(83), UWORD(1), UWORD(635970), UWORD(7482), UWORD(87), UWORD(1), UWORD(728910), UWORD(8190), UWORD(91), UWORD(1), UWORD(830490), UWORD(8930), UWORD(95), UWORD(1), UWORD(941094), UWORD(9702), UWORD(99), UWORD(1), UWORD(1061106), UWORD(10506), UWORD(103), UWORD(1), UWORD(1190910), UWORD(11342), UWORD(107), UWORD(1), UWORD(1330890), UWORD(12210), UWORD(111), UWORD(1), UWORD(1481430), UWORD(13110), UWORD(115), UWORD(1), UWORD(1642914), UWORD(14042), UWORD(119), UWORD(1), UWORD(1815726), UWORD(15006), UWORD(123), UWORD(1), UWORD(2000250), UWORD(16002), UWORD(127), UWORD(1), UWORD(2196870), UWORD(17030), UWORD(131), UWORD(1), UWORD(2405970), UWORD(18090), UWORD(135), UWORD(1), UWORD(2627934), UWORD(19182), UWORD(139), UWORD(1), UWORD(2863146), UWORD(20306), UWORD(143), UWORD(1), UWORD(3111990), UWORD(21462), UWORD(147), UWORD(1), UWORD(3374850), UWORD(22650), UWORD(151), UWORD(1), UWORD(3652110), UWORD(23870), UWORD(155), UWORD(1), UWORD(3944154), UWORD(25122), UWORD(159), UWORD(1), UWORD(4251366), UWORD(26406), UWORD(163), UWORD(1), UWORD(4574130), UWORD(27722), UWORD(167), UWORD(1), UWORD(4912830), UWORD(29070), UWORD(171), UWORD(1), UWORD(5267850), UWORD(30450), UWORD(175), UWORD(1), UWORD(5639574), UWORD(31862), UWORD(179), UWORD(1), UWORD(6028386), UWORD(33306), UWORD(183), UWORD(1), UWORD(6434670), UWORD(34782), UWORD(187), UWORD(1), UWORD(6858810), UWORD(36290), UWORD(191), UWORD(1), UWORD(7301190), UWORD(37830), UWORD(195), UWORD(1), UWORD(7762194), UWORD(39402), UWORD(199), UWORD(1), UWORD(8242206), UWORD(41006), UWORD(203), UWORD(1), UWORD(8741610), UWORD(42642), UWORD(207), UWORD(1), UWORD(9260790), UWORD(44310), UWORD(211), UWORD(1), UWORD(9800130), UWORD(46010), UWORD(215), UWORD(1), UWORD(10360014), UWORD(47742), UWORD(219), UWORD(1), UWORD(10940826), UWORD(49506), UWORD(223), UWORD(1), UWORD(11542950), UWORD(51302), UWORD(227), UWORD(1), UWORD(12166770), UWORD(53130), UWORD(231), UWORD(1), UWORD(12812670), UWORD(54990), UWORD(235), UWORD(1), UWORD(13481034), UWORD(56882), UWORD(239), UWORD(1), UWORD(14172246), UWORD(58806), UWORD(243), UWORD(1), UWORD(14886690), UWORD(60762), UWORD(247), UWORD(1), UWORD(15624750), UWORD(62750), UWORD(251), UWORD(1), UWORD(16386810), UWORD(64770), UWORD(255), UWORD(1), UWORD(66306), UWORD(258), UWORD(1), UWORD(67860), UWORD(261), UWORD(1), UWORD(69432), UWORD(264), UWORD(1), UWORD(71022), UWORD(267), UWORD(1), UWORD(72630), UWORD(270), UWORD(1), UWORD(74256), UWORD(273), UWORD(1), UWORD(75900), UWORD(276), UWORD(1), UWORD(77562), UWORD(279), UWORD(1), UWORD(79242), UWORD(282), UWORD(1), UWORD(80940), UWORD(285), UWORD(1), UWORD(82656), UWORD(288), }; const mp_limb_t factorial_tab_denom[FACTORIAL_TAB_SIZE] = { UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(479001600), UWORD(253955520), UWORD(253955520), UWORD(253955520), UWORD(253955520), UWORD(253955520), UWORD(253955520), UWORD(253955520), UWORD(3315312000), UWORD(3315312000), UWORD(3315312000), UWORD(3315312000), UWORD(3315312000), UWORD(3315312000), UWORD(3315312000), UWORD(652458240), UWORD(652458240), UWORD(652458240), UWORD(652458240), UWORD(652458240), UWORD(652458240), UWORD(1987690320), UWORD(1987690320), UWORD(1987690320), UWORD(1987690320), UWORD(1987690320), UWORD(1987690320), UWORD(115511760), UWORD(115511760), UWORD(115511760), UWORD(115511760), UWORD(115511760), UWORD(205476480), UWORD(205476480), UWORD(205476480), UWORD(205476480), UWORD(205476480), UWORD(344362200), UWORD(344362200), UWORD(344362200), UWORD(344362200), UWORD(344362200), UWORD(549853920), UWORD(549853920), UWORD(549853920), UWORD(549853920), UWORD(549853920), UWORD(843461640), UWORD(843461640), UWORD(843461640), UWORD(843461640), UWORD(843461640), UWORD(1250895360), UWORD(1250895360), UWORD(1250895360), UWORD(1250895360), UWORD(1250895360), UWORD(1802440080), UWORD(1802440080), UWORD(1802440080), UWORD(1802440080), UWORD(1802440080), UWORD(2533330800), UWORD(2533330800), UWORD(2533330800), UWORD(2533330800), UWORD(2533330800), UWORD(3484127520), UWORD(3484127520), UWORD(3484127520), UWORD(3484127520), UWORD(3484127520), UWORD(53421480), UWORD(53421480), UWORD(53421480), UWORD(53421480), UWORD(64144080), UWORD(64144080), UWORD(64144080), UWORD(64144080), UWORD(76405080), UWORD(76405080), UWORD(76405080), UWORD(76405080), UWORD(90345024), UWORD(90345024), UWORD(90345024), UWORD(90345024), UWORD(106110600), UWORD(106110600), UWORD(106110600), UWORD(106110600), UWORD(123854640), UWORD(123854640), UWORD(123854640), UWORD(123854640), UWORD(143736120), UWORD(143736120), UWORD(143736120), UWORD(143736120), UWORD(165920160), UWORD(165920160), UWORD(165920160), UWORD(165920160), UWORD(190578024), UWORD(190578024), UWORD(190578024), UWORD(190578024), UWORD(217887120), UWORD(217887120), UWORD(217887120), UWORD(217887120), UWORD(248031000), UWORD(248031000), UWORD(248031000), UWORD(248031000), UWORD(281199360), UWORD(281199360), UWORD(281199360), UWORD(281199360), UWORD(317588040), UWORD(317588040), UWORD(317588040), UWORD(317588040), UWORD(357399024), UWORD(357399024), UWORD(357399024), UWORD(357399024), UWORD(400840440), UWORD(400840440), UWORD(400840440), UWORD(400840440), UWORD(448126560), UWORD(448126560), UWORD(448126560), UWORD(448126560), UWORD(499477800), UWORD(499477800), UWORD(499477800), UWORD(499477800), UWORD(555120720), UWORD(555120720), UWORD(555120720), UWORD(555120720), UWORD(615288024), UWORD(615288024), UWORD(615288024), UWORD(615288024), UWORD(680218560), UWORD(680218560), UWORD(680218560), UWORD(680218560), UWORD(750157320), UWORD(750157320), UWORD(750157320), UWORD(750157320), UWORD(825355440), UWORD(825355440), UWORD(825355440), UWORD(825355440), UWORD(906070200), UWORD(906070200), UWORD(906070200), UWORD(906070200), UWORD(992565024), UWORD(992565024), UWORD(992565024), UWORD(992565024), UWORD(1085109480), UWORD(1085109480), UWORD(1085109480), UWORD(1085109480), UWORD(1183979280), UWORD(1183979280), UWORD(1183979280), UWORD(1183979280), UWORD(1289456280), UWORD(1289456280), UWORD(1289456280), UWORD(1289456280), UWORD(1401828480), UWORD(1401828480), UWORD(1401828480), UWORD(1401828480), UWORD(1521390024), UWORD(1521390024), UWORD(1521390024), UWORD(1521390024), UWORD(1648441200), UWORD(1648441200), UWORD(1648441200), UWORD(1648441200), UWORD(1783288440), UWORD(1783288440), UWORD(1783288440), UWORD(1783288440), UWORD(1926244320), UWORD(1926244320), UWORD(1926244320), UWORD(1926244320), UWORD(2077627560), UWORD(2077627560), UWORD(2077627560), UWORD(2077627560), UWORD(2237763024), UWORD(2237763024), UWORD(2237763024), UWORD(2237763024), UWORD(2406981720), UWORD(2406981720), UWORD(2406981720), UWORD(2406981720), UWORD(2585620800), UWORD(2585620800), UWORD(2585620800), UWORD(2585620800), UWORD(2774023560), UWORD(2774023560), UWORD(2774023560), UWORD(2774023560), UWORD(2972539440), UWORD(2972539440), UWORD(2972539440), UWORD(2972539440), UWORD(3181524024), UWORD(3181524024), UWORD(3181524024), UWORD(3181524024), UWORD(3401339040), UWORD(3401339040), UWORD(3401339040), UWORD(3401339040), UWORD(3632352360), UWORD(3632352360), UWORD(3632352360), UWORD(3632352360), UWORD(3874938000), UWORD(3874938000), UWORD(3874938000), UWORD(3874938000), UWORD(4129476120), UWORD(4129476120), UWORD(4129476120), UWORD(4129476120), UWORD(16974336), UWORD(16974336), UWORD(16974336), UWORD(17575740), UWORD(17575740), UWORD(17575740), UWORD(18191184), UWORD(18191184), UWORD(18191184), UWORD(18820830), UWORD(18820830), UWORD(18820830), UWORD(19464840), UWORD(19464840), UWORD(19464840), UWORD(20123376), UWORD(20123376), UWORD(20123376), UWORD(20796600), UWORD(20796600), UWORD(20796600), UWORD(21484674), UWORD(21484674), UWORD(21484674), UWORD(22187760), UWORD(22187760), UWORD(22187760), UWORD(22906020), UWORD(22906020), UWORD(22906020), UWORD(23639616), UWORD(23639616), }; #endif void _arb_exp_taylor_rs(mp_ptr y, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N) { mp_ptr s, t, xpow; mp_limb_t new_denom, old_denom, c; slong power, k, m; TMP_INIT; TMP_START; if (N >= FACTORIAL_TAB_SIZE - 1) { flint_throw(FLINT_ERROR, "_arb_exp_taylor_rs: N too large!\n"); } if (N <= 3) { if (N <= 1) { flint_mpn_zero(y, xn); y[xn] = N; error[0] = 0; } else if (N == 2) { flint_mpn_copyi(y, x, xn); y[xn] = 1; error[0] = 0; } else { /* 1 + x + x^2 / 2 */ t = TMP_ALLOC_LIMBS(2 * xn); flint_mpn_sqr(t, x, xn); mpn_rshift(t + xn, t + xn, xn, 1); y[xn] = mpn_add_n(y, x, t + xn, xn) + 1; error[0] = 2; } } else { /* Choose m ~= sqrt(num_terms) (m must be even, >= 2) */ /* TODO: drop evenness assumption since we don't have sign issues here? */ /* TODO: then just need to fix power construction below... */ m = 2; while (m * m < N) m += 2; /* todo: merge allocations */ xpow = TMP_ALLOC_LIMBS((m + 1) * xn); s = TMP_ALLOC_LIMBS(xn + 2); t = TMP_ALLOC_LIMBS(2 * xn + 2); /* todo: 1 limb too much? */ /* higher index ---> */ /* | ---xn--- | */ /* xpow = | | x^m | x^(m-1) | ... | x^2 | x | */ #define XPOW_WRITE(__k) (xpow + (m - (__k)) * xn) #define XPOW_READ(__k) (xpow + (m - (__k) + 1) * xn) flint_mpn_copyi(XPOW_READ(1), x, xn); flint_mpn_sqr(XPOW_WRITE(2), XPOW_READ(1), xn); for (k = 4; k <= m; k += 2) { flint_mpn_mul_n(XPOW_WRITE(k - 1), XPOW_READ(k / 2), XPOW_READ(k / 2 - 1), xn); flint_mpn_sqr(XPOW_WRITE(k), XPOW_READ(k / 2), xn); } flint_mpn_zero(s, xn + 1); /* todo: skip one nonscalar multiplication (use x^m) when starting on x^0 */ power = (N - 1) % m; for (k = N - 1; k >= 0; k--) { c = factorial_tab_numer[k]; new_denom = factorial_tab_denom[k]; old_denom = factorial_tab_denom[k+1]; /* change denominators */ if (new_denom != old_denom && k < N - 1) { mpn_divrem_1(s, 0, s, xn + 1, old_denom); } if (power == 0) { /* add c * x^0 -- only top limb is affected */ s[xn] += c; /* Outer polynomial evaluation: multiply by x^m */ if (k != 0) { flint_mpn_mul(t, s, xn + 1, XPOW_READ(m), xn); flint_mpn_copyi(s, t + xn, xn + 1); } power = m - 1; } else { s[xn] += mpn_addmul_1(s, XPOW_READ(power), xn, c); power--; } } /* finally divide by denominator */ mpn_divrem_1(y, 0, s, xn + 1, factorial_tab_denom[0]); /* error bound (ulp) */ error[0] = 2; } TMP_END; } flint-3.1.3/src/arb/fac.c000066400000000000000000000011071461254215100150620ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_fac_ui(arb_t x, ulong n, slong prec) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, n); fmpz_add_ui(t, t, 1); arb_gamma_fmpz(x, t, prec); fmpz_clear(t); } flint-3.1.3/src/arb/fib.c000066400000000000000000000013631461254215100150750ustar00rootroot00000000000000/* Copyright (C) 2012, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "gr_special.h" void arb_fib_fmpz(arb_t f, const fmpz_t n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); GR_MUST_SUCCEED(gr_generic_fib_fmpz(f, n, ctx)); } void arb_fib_ui(arb_t f, ulong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); GR_MUST_SUCCEED(gr_generic_fib_ui(f, n, ctx)); } flint-3.1.3/src/arb/floor.c000066400000000000000000000016711461254215100154600ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_floor(arb_t z, const arb_t x, slong prec) { if (!arb_is_finite(x)) { arb_indeterminate(z); } else if (arb_is_exact(x)) { arf_floor(arb_midref(z), arb_midref(x)); mag_zero(arb_radref(z)); arb_set_round(z, z, prec); } else { arf_t a, b; arf_init(a); arf_init(b); arb_get_interval_arf(a, b, x, prec); arf_floor(a, a); arf_floor(b, b); arb_set_interval_arf(z, a, b, prec); arf_clear(a); arf_clear(b); } } flint-3.1.3/src/arb/fma.c000066400000000000000000000113161461254215100150770ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_fma_arf(arb_t res, const arb_t x, const arf_t y, const arb_t z, slong prec) { mag_t ym; int inexact; if (arb_is_exact(x)) { inexact = arf_fma(arb_midref(res), arb_midref(x), y, arb_midref(z), prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(res), arb_radref(z), arb_midref(res), prec); else mag_set(arb_radref(res), arb_radref(z)); } else if (ARB_IS_LAGOM(res) && ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_t tm; mag_fast_init_set_arf(ym, y); *tm = *arb_radref(z); mag_fast_addmul(tm, ym, arb_radref(x)); *arb_radref(res) = *tm; inexact = arf_fma(arb_midref(res), arb_midref(x), y, arb_midref(z), prec, ARB_RND); if (inexact) arf_mag_fast_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec); } else if (arf_is_inf(y) && arb_is_nonzero(x)) { if (arf_sgn(arb_midref(x)) > 0) arb_add_arf(res, z, y, prec); else arb_sub_arf(res, z, y, prec); } else { mag_t tm; mag_init(tm); mag_init_set_arf(ym, y); mag_set(tm, arb_radref(z)); mag_addmul(tm, ym, arb_radref(x)); mag_set(arb_radref(res), tm); inexact = arf_fma(arb_midref(res), arb_midref(x), y, arb_midref(z), prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec); mag_clear(tm); mag_clear(ym); } } void arb_fma(arb_t res, const arb_t x, const arb_t y, const arb_t z, slong prec) { mag_t zr, xm, ym; int inexact; if (arb_is_exact(y)) { arb_fma_arf(res, x, arb_midref(y), z, prec); } else if (arb_is_exact(x)) { arb_fma_arf(res, y, arb_midref(x), z, prec); } else if (ARB_IS_LAGOM(res) && ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(xm, arb_midref(x)); mag_fast_init_set_arf(ym, arb_midref(y)); mag_fast_init_set(zr, arb_radref(z)); mag_fast_addmul(zr, xm, arb_radref(y)); mag_fast_addmul(zr, ym, arb_radref(x)); mag_fast_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_fma(arb_midref(res), arb_midref(x), arb_midref(y), arb_midref(z), prec, ARF_RND_DOWN); if (inexact) arf_mag_fast_add_ulp(zr, zr, arb_midref(res), prec); *arb_radref(res) = *zr; } else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y)) { if (arf_sgn(arb_midref(y)) > 0) arb_add_arf(res, z, arb_midref(x), prec); else arb_sub_arf(res, z, arb_midref(x), prec); } else if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x)) { if (arf_sgn(arb_midref(x)) > 0) arb_add_arf(res, z, arb_midref(y), prec); else arb_sub_arf(res, z, arb_midref(y), prec); } else { mag_init_set_arf(xm, arb_midref(x)); mag_init_set_arf(ym, arb_midref(y)); mag_init_set(zr, arb_radref(z)); mag_addmul(zr, xm, arb_radref(y)); mag_addmul(zr, ym, arb_radref(x)); mag_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_fma(arb_midref(res), arb_midref(x), arb_midref(y), arb_midref(z), prec, ARF_RND_DOWN); if (inexact) arf_mag_add_ulp(arb_radref(res), zr, arb_midref(res), prec); else mag_set(arb_radref(res), zr); mag_clear(zr); mag_clear(xm); mag_clear(ym); } } void arb_fma_ui(arb_t res, const arb_t x, ulong y, const arb_t z, slong prec) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ arb_fma_arf(res, x, t, z, prec); } void arb_fma_si(arb_t res, const arb_t x, slong y, const arb_t z, slong prec) { arf_t t; arf_init_set_si(t, y); /* no need to free */ arb_fma_arf(res, x, t, z, prec); } void arb_fma_fmpz(arb_t res, const arb_t x, const fmpz_t y, const arb_t z, slong prec) { arf_t t; if (!COEFF_IS_MPZ(*y)) { arf_init_set_si(t, *y); /* no need to free */ arb_fma_arf(res, x, t, z, prec); } else { arf_init(t); arf_set_fmpz(t, y); arb_fma_arf(res, x, t, z, prec); arf_clear(t); } } flint-3.1.3/src/arb/gamma.c000066400000000000000000000157001461254215100154170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "bernoulli.h" /* todo: move/cleanup helper functions */ void acb_gamma_bound_phase(mag_t bound, const acb_t z) { arf_t x, y, t, u; int xsign; slong prec; arf_init(x); arf_init(y); arf_init(t); arf_init(u); prec = MAG_BITS; /* first compute x, y such that |arg(z)| <= arg(x+yi) */ /* argument increases with smaller real parts */ arf_set_mag(x, arb_radref(acb_realref(z))); arf_sub(x, arb_midref(acb_realref(z)), x, prec, ARF_RND_FLOOR); xsign = arf_sgn(x); if (xsign >= 0) /* argument increases away from the real axis */ arb_get_abs_ubound_arf(y, acb_imagref(z), prec); else /* argument increases closer to the real axis */ arb_get_abs_lbound_arf(y, acb_imagref(z), prec); if (arf_is_zero(y)) { if (xsign > 0) mag_one(bound); else mag_inf(bound); } else { if (xsign >= 0) { /* compute upper bound for t = y / (sqrt(x^2 + y^2) + x) */ arf_mul(t, x, x, prec, ARF_RND_DOWN); arf_mul(u, y, y, prec, ARF_RND_DOWN); arf_add(t, t, u, prec, ARF_RND_DOWN); arf_sqrt(t, t, prec, ARF_RND_DOWN); arf_add(t, t, x, prec, ARF_RND_DOWN); arf_div(t, y, t, prec, ARF_RND_UP); } else { /* compute upper bound for t = (sqrt(x^2 + y^2) - x) / y */ arf_mul(t, x, x, prec, ARF_RND_UP); arf_mul(u, y, y, prec, ARF_RND_UP); arf_add(t, t, u, prec, ARF_RND_UP); arf_sqrt(t, t, prec, ARF_RND_UP); arf_sub(t, t, x, prec, ARF_RND_UP); arf_div(t, t, y, prec, ARF_RND_UP); } /* compute upper bound for sqrt(1 + t^2) */ arf_mul(t, t, t, prec, ARF_RND_UP); arf_add_ui(t, t, 1, prec, ARF_RND_UP); arf_sqrt(t, t, prec, ARF_RND_UP); arf_get_mag(bound, t); } arf_clear(x); arf_clear(y); arf_clear(t); arf_clear(u); } /* 2 |B_{2n}| G(2n+k-1) / (G(k+1) G(2n+1)) |z| (T |z|^{-1})^(2n+k) TODO: CHECK n >= 1 ? */ void acb_gamma_stirling_bound(mag_ptr err, const acb_t z, slong k0, slong knum, slong n) { mag_t c, t, u, v; slong i, k; if (arb_contains_zero(acb_imagref(z)) && arb_contains_nonpositive(acb_realref(z))) { for (i = 0; i < knum; i++) mag_inf(err + i); return; } mag_init(c); mag_init(t); mag_init(u); mag_init(v); /* t = lower bound for |z| */ acb_get_mag_lower(t, z); /* v = upper bound for |z| */ acb_get_mag(v, z); /* c = upper bound for 1/(cos(arg(z)/2) |z|) */ acb_gamma_bound_phase(c, z); mag_div(c, c, t); /* numerator: 2 B_{2n} gamma(2n+k-1) |z| */ mag_bernoulli_div_fac_ui(err, 2 * n); mag_mul_2exp_si(err, err, 1); mag_fac_ui(u, 2 * n + k0 - 2); mag_mul(err, err, u); mag_mul(err, err, v); /* denominator gamma(k+1) gamma(2n+1) */ mag_rfac_ui(t, k0); mag_mul(err, err, t); /* multiply by c^(2n+k) */ mag_pow_ui(t, c, 2 * n + k0); mag_mul(err, err, t); for (i = 1; i < knum; i++) { /* recurrence factor: c * (2n+k-2) / k */ k = k0 + i; mag_mul(err + i, err + i - 1, c); mag_mul_ui(err + i, err + i, 2 * n + k - 2); mag_div_ui(err + i, err + i, k); } mag_clear(c); mag_clear(t); mag_clear(u); mag_clear(v); } void arb_gamma_stirling_bound(mag_ptr err, const arb_t x, slong k0, slong knum, slong n) { acb_t z; acb_init(z); acb_set_arb(z, x); acb_gamma_stirling_bound(err, z, k0, knum, n); acb_clear(z); } void arb_gamma_stirling_coeff(arb_t b, ulong k, int digamma, slong prec) { fmpz_t d; fmpz_init(d); BERNOULLI_ENSURE_CACHED(2 * k); arb_set_round_fmpz(b, fmpq_numref(bernoulli_cache + 2 * k), prec); if (digamma) fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * k), 2 * k); else fmpz_mul2_uiui(d, fmpq_denref(bernoulli_cache + 2 * k), 2 * k, 2 * k - 1); arb_div_fmpz(b, b, d, prec); fmpz_clear(d); } void arb_gamma_stirling_eval(arb_t s, const arb_t z, slong nterms, int digamma, slong prec) { arb_t b, t, logz, zinv, zinv2; mag_t err; slong k, term_prec; double z_mag, term_mag; arb_init(b); arb_init(t); arb_init(logz); arb_init(zinv); arb_init(zinv2); arb_log(logz, z, prec); arb_inv(zinv, z, prec); nterms = FLINT_MAX(nterms, 1); arb_zero(s); if (nterms > 1) { arb_mul(zinv2, zinv, zinv, prec); z_mag = arf_get_d(arb_midref(logz), ARF_RND_UP) * 1.44269504088896; for (k = nterms - 1; k >= 1; k--) { term_mag = bernoulli_bound_2exp_si(2 * k); term_mag -= (2 * k - 1) * z_mag; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); if (prec > 2000) { arb_set_round(t, zinv2, term_prec); arb_mul(s, s, t, term_prec); } else arb_mul(s, s, zinv2, term_prec); arb_gamma_stirling_coeff(b, k, digamma, term_prec); arb_add(s, s, b, term_prec); } if (digamma) arb_mul(s, s, zinv2, prec); else arb_mul(s, s, zinv, prec); } /* remainder bound */ mag_init(err); arb_gamma_stirling_bound(err, z, digamma ? 1 : 0, 1, nterms); mag_add(arb_radref(s), arb_radref(s), err); mag_clear(err); if (digamma) { arb_neg(s, s); arb_mul_2exp_si(zinv, zinv, -1); arb_sub(s, s, zinv, prec); arb_add(s, s, logz, prec); } else { /* (z-0.5)*log(z) - z + log(2*pi)/2 */ arb_one(t); arb_mul_2exp_si(t, t, -1); arb_sub(t, z, t, prec); arb_mul(t, logz, t, prec); arb_add(s, s, t, prec); arb_sub(s, s, z, prec); arb_const_log_sqrt2pi(t, prec); arb_add(s, s, t, prec); } arb_clear(t); arb_clear(b); arb_clear(zinv); arb_clear(zinv2); arb_clear(logz); } void arb_gamma_fmpq(arb_t y, const fmpq_t x, slong prec) { arb_hypgeom_gamma_fmpq(y, x, prec); } void arb_gamma_fmpz(arb_t y, const fmpz_t x, slong prec) { arb_hypgeom_gamma_fmpz(y, x, prec); } void arb_gamma(arb_t y, const arb_t x, slong prec) { arb_hypgeom_gamma(y, x, prec); } void arb_rgamma(arb_t y, const arb_t x, slong prec) { arb_hypgeom_rgamma(y, x, prec); } void arb_lgamma(arb_t y, const arb_t x, slong prec) { arb_hypgeom_lgamma(y, x, prec); } flint-3.1.3/src/arb/get_abs_lbound_arf.c000066400000000000000000000014211461254215100201270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_get_abs_lbound_arf(arf_t u, const arb_t x, slong prec) { arf_t t; arf_init_set_mag_shallow(t, arb_radref(x)); if (arf_sgn(arb_midref(x)) > 0) { arf_sub(u, arb_midref(x), t, prec, ARF_RND_DOWN); } else { arf_add(u, arb_midref(x), t, prec, ARF_RND_DOWN); arf_neg(u, u); } if (arf_sgn(u) < 0) arf_zero(u); } flint-3.1.3/src/arb/get_abs_ubound_arf.c000066400000000000000000000013041461254215100201400ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_get_abs_ubound_arf(arf_t u, const arb_t x, slong prec) { arf_t t; arf_init_set_mag_shallow(t, arb_radref(x)); if (arf_sgn(arb_midref(x)) < 0) arf_sub(u, arb_midref(x), t, prec, ARF_RND_UP); else arf_add(u, arb_midref(x), t, prec, ARF_RND_UP); arf_abs(u, u); } flint-3.1.3/src/arb/get_fmpz_mid_rad_10exp.c000066400000000000000000000046731461254215100206530ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* todo: make arb_pow_fmpz automatic */ void _arb_10_pow_fmpz(arb_t res, const fmpz_t m, slong prec) { slong bits = fmpz_bits(m); if (bits <= FLINT_BITS) { arb_ui_pow_ui(res, 10, fmpz_get_ui(m), prec); } else if (bits < 128) { arb_set_ui(res, 10); arb_pow_fmpz_binexp(res, res, m, prec + 2 * bits); } else { arb_const_log10(res, prec + bits); arb_mul_fmpz(res, res, m, prec + bits); arb_exp(res, res, prec + bits); } } void arb_get_fmpz_mid_rad_10exp(fmpz_t mid, fmpz_t rad, fmpz_t exp, const arb_t x, slong n) { fmpz_t e, m; arb_t t, u; arf_t r; slong prec; int roundmid, roundrad; if (!arb_is_finite(x) || arb_is_zero(x)) { fmpz_zero(mid); fmpz_zero(rad); fmpz_zero(exp); return; } /* We compute m such that x * 10^m ~= 10^(n+5). If x = 2^e then m = (n+5) - e*log(2)/log(10). */ fmpz_init(e); fmpz_init(m); arb_init(t); arb_init(u); arf_init(r); if (arf_cmpabs_mag(arb_midref(x), arb_radref(x)) > 0) fmpz_set(e, ARF_EXPREF(arb_midref(x))); else fmpz_set(e, ARF_EXPREF(arb_radref(x))); prec = fmpz_bits(e); prec = FLINT_MAX(prec, FLINT_BIT_COUNT(n)) + 15; arb_const_log2(t, prec); arb_const_log10(u, prec); arb_div(t, t, u, prec); arb_mul_fmpz(t, t, e, prec); arb_neg(t, t); arb_add_ui(t, t, n + 5, prec); arf_get_fmpz(m, arb_midref(t), ARF_RND_FLOOR); fmpz_neg(exp, m); prec = n * 3.32192809488736 + 30; if (fmpz_sgn(m) >= 0) { _arb_10_pow_fmpz(t, m, prec); arb_mul(t, x, t, prec); } else { fmpz_neg(m, m); _arb_10_pow_fmpz(t, m, prec); arb_div(t, x, t, prec); } roundmid = arf_get_fmpz_fixed_si(mid, arb_midref(t), 0); arf_set_mag(r, arb_radref(t)); roundrad = arf_get_fmpz_fixed_si(rad, r, 0); fmpz_add_ui(rad, rad, roundmid + roundrad); fmpz_clear(e); fmpz_clear(m); arb_clear(t); arb_clear(u); arf_clear(r); } flint-3.1.3/src/arb/get_interval_arf.c000066400000000000000000000012061461254215100176440ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_get_interval_arf(arf_t a, arf_t b, const arb_t x, slong prec) { arf_t r; arf_init_set_mag_shallow(r, arb_radref(x)); arf_sub(a, arb_midref(x), r, prec, ARF_RND_FLOOR); arf_add(b, arb_midref(x), r, prec, ARF_RND_CEIL); } flint-3.1.3/src/arb/get_interval_fmpz_2exp.c000066400000000000000000000041001461254215100210020ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_get_interval_fmpz_2exp(fmpz_t a, fmpz_t b, fmpz_t exp, const arb_t x) { if (!arb_is_finite(x)) { flint_throw(FLINT_ERROR, "expected finite input in %s\n", __func__); } else if (arb_is_exact(x)) { arf_get_fmpz_2exp(a, exp, arb_midref(x)); fmpz_set(b, a); } else if (arf_is_zero(arb_midref(x))) { arf_t t; arf_init_set_mag_shallow(t, arb_radref(x)); arf_get_fmpz_2exp(b, exp, t); fmpz_neg(a, b); } else { arf_t rad; fmpz_t tmp; slong shift; flint_bitcnt_t aval, bval; fmpz_init(tmp); arf_get_fmpz_2exp(a, exp, arb_midref(x)); arf_init_set_mag_shallow(rad, arb_radref(x)); arf_get_fmpz_2exp(b, tmp, rad); shift = _fmpz_sub_small(exp, tmp); if (FLINT_ABS(shift) >= WORD_MAX / 2) flint_throw(FLINT_ERROR, "too large shift in %s\n", __func__); if (shift >= 0) { fmpz_mul_2exp(a, a, shift); fmpz_set(exp, tmp); } else fmpz_mul_2exp(b, b, -shift); fmpz_sub(tmp, a, b); fmpz_add(b, a, b); fmpz_swap(tmp, a); if (fmpz_is_zero(a)) { aval = fmpz_val2(b); } else if (fmpz_is_zero(b)) { aval = fmpz_val2(a); } else { aval = fmpz_val2(a); bval = fmpz_val2(b); aval = FLINT_MIN(aval, bval); } if (aval > 0) { fmpz_add_ui(exp, exp, aval); fmpz_tdiv_q_2exp(a, a, aval); fmpz_tdiv_q_2exp(b, b, aval); } fmpz_clear(tmp); } } flint-3.1.3/src/arb/get_interval_mpfr.c000066400000000000000000000014231461254215100200410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb.h" void arb_get_interval_mpfr(mpfr_t a, mpfr_t b, const arb_t x) { arf_t r, t; arf_init(t); arf_init_set_mag_shallow(r, arb_radref(x)); arf_sub(t, arb_midref(x), r, mpfr_get_prec(a), ARF_RND_FLOOR); arf_get_mpfr(a, t, MPFR_RNDD); arf_add(t, arb_midref(x), r, mpfr_get_prec(b), ARF_RND_CEIL); arf_get_mpfr(b, t, MPFR_RNDU); arf_clear(t); } flint-3.1.3/src/arb/get_lbound_arf.c000066400000000000000000000011061461254215100173020ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_get_lbound_arf(arf_t u, const arb_t x, slong prec) { arf_t t; arf_init_set_mag_shallow(t, arb_radref(x)); arf_sub(u, arb_midref(x), t, prec, ARF_RND_FLOOR); } flint-3.1.3/src/arb/get_mag_lower.c000066400000000000000000000050541461254215100171510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static inline void _arb_get_mag_lower(mag_t z, const arf_t mid, const mag_t rad) { if (arf_is_special(mid) || mag_is_special(rad)) { if (mag_is_zero(rad)) { arf_get_mag_lower(z, mid); } else if (arf_is_inf(mid) && mag_is_finite(rad)) { mag_inf(z); } else { mag_zero(z); } } else { slong shift, fix; shift = _fmpz_sub_small(MAG_EXPREF(mid), MAG_EXPREF(rad)); /* mid < rad */ if (shift < 0) { mag_zero(z); } else { mp_limb_t m, xm, rm; ARF_GET_TOP_LIMB(xm, mid); xm = xm >> (FLINT_BITS - MAG_BITS); if (shift <= MAG_BITS) rm = (MAG_MAN(rad) >> shift) + 1; else rm = 1; m = xm - rm; if (shift > 1) /* more than one bit cancellation not possible */ { fix = !(m >> (MAG_BITS - 1)); m <<= fix; MAG_MAN(z) = m; _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(mid), -fix); } else if (rm < xm && m > (1 << (MAG_BITS - 4))) /* not too much cancellation */ { fix = MAG_BITS - FLINT_BIT_COUNT(m); m <<= fix; MAG_MAN(z) = m; _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(mid), -fix); } else { arf_t t; arf_init(t); arf_set_mag(t, rad); if (arf_sgn(mid) > 0) { arf_sub(t, mid, t, MAG_BITS, ARF_RND_DOWN); } else { arf_add(t, mid, t, MAG_BITS, ARF_RND_DOWN); arf_neg(t, t); } if (arf_sgn(t) <= 0) mag_zero(z); else arf_get_mag_lower(z, t); arf_clear(t); } } } } void arb_get_mag_lower(mag_t z, const arb_t x) { _arb_get_mag_lower(z, arb_midref(x), arb_radref(x)); } flint-3.1.3/src/arb/get_mag_lower_nonnegative.c000066400000000000000000000046521461254215100215510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static inline void _arb_get_mag_lower_nonnegative(mag_t z, const arf_t mid, const mag_t rad) { if (arf_sgn(mid) < 0) { mag_zero(z); } else if (arf_is_special(mid) || mag_is_special(rad)) { if (mag_is_zero(rad)) { arf_get_mag_lower(z, mid); } else if (arf_is_pos_inf(mid) && mag_is_finite(rad)) { mag_inf(z); } else { mag_zero(z); } } else { slong shift, fix; shift = _fmpz_sub_small(MAG_EXPREF(mid), MAG_EXPREF(rad)); /* mid < rad */ if (shift < 0) { mag_zero(z); } else { mp_limb_t m, xm, rm; ARF_GET_TOP_LIMB(xm, mid); xm = xm >> (FLINT_BITS - MAG_BITS); if (shift <= MAG_BITS) rm = (MAG_MAN(rad) >> shift) + 1; else rm = 1; m = xm - rm; if (shift > 1) /* more than one bit cancellation not possible */ { fix = !(m >> (MAG_BITS - 1)); m <<= fix; MAG_MAN(z) = m; _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(mid), -fix); } else if (rm < xm && m > (1 << (MAG_BITS - 4))) /* not too much cancellation */ { fix = MAG_BITS - FLINT_BIT_COUNT(m); m <<= fix; MAG_MAN(z) = m; _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(mid), -fix); } else { arf_t t; arf_init(t); arf_set_mag(t, rad); arf_sub(t, mid, t, MAG_BITS, ARF_RND_DOWN); if (arf_sgn(t) <= 0) mag_zero(z); else arf_get_mag_lower(z, t); arf_clear(t); } } } } void arb_get_mag_lower_nonnegative(mag_t z, const arb_t x) { _arb_get_mag_lower_nonnegative(z, arb_midref(x), arb_radref(x)); } flint-3.1.3/src/arb/get_mpn_fixed_mod_log2.c000066400000000000000000000106261461254215100207310ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #define TMP_ALLOC_LIMBS(__n) TMP_ALLOC((__n) * sizeof(mp_limb_t)) /* Compute wn-limb fixed-point number w, a number of ulps error, and an exponent q such that x = (w + xi * error) - q * log(2) where 0 <= w < log(2) and |xi| <= 1. Returns 0 if unsuccessful (high enough precision for log(2) to be available) and 1 if successful. Assumes nonspecial x; its exponent must not be an mpz. Error analysis: We first set n = |x| - e1 d = log(2) - e2 where 0 <= e1, e2 <= 1 ulp are the errors resulting from truncating to fixed-point numbers (note that the value of log(2) is correctly rounded). Next, we compute q, r such that 0 <= r < d and q*d + r = n (this is just integer division with remainder, done exactly). The real number we want to approximate is r_exact = |x| - q * log(2). The approximation r satisfies |r_exact - r| = |(|x| - q * log(2)) - (n - q * d)| = ||x| - q * log(2) - (|x| - e1) + q * (log(2) - e2)| = |e1 - q * e2| <= (q + 1) ulp. We select the working precision so that (q + 1) ulp is at most 1 ulp in the target precision. It is sufficient to use tn extra limbs where (q + 1) <= 2^(FLINT_BITS * tn). Note that q + 1 <= n / d + 1 <= |x| * 1.5 + 1 < 2^(exp+2). So it is sufficient to choose tn = ceil((exp+2)/FLINT_BITS). Now we round the result to the final precision: w = r - e3. This can add 1 more ulp of error, so the error may be 2 ulp. Finally, if x < 0, we correct the sign by setting,x = log(2) - x, q = -(q+1). This adds 1 more ulp (from the approximation of log(2)), for a total of 3 ulp. */ int _arb_get_mpn_fixed_mod_log2(mp_ptr w, fmpz_t q, mp_limb_t * error, const arf_t x, mp_size_t wn) { mp_srcptr xp; mp_size_t xn; int negative; slong exp; ARF_GET_MPN_READONLY(xp, xn, x); exp = ARF_EXP(x); negative = ARF_SGNBIT(x); if (exp <= -1) { /* todo: just zero top */ flint_mpn_zero(w, wn); *error = _arf_get_integer_mpn(w, xp, xn, exp + wn * FLINT_BITS); if (!negative) { fmpz_zero(q); } else { if (wn > ARB_LOG_TAB2_LIMBS) return 0; mpn_sub_n(w, arb_log_log2_tab + ARB_LOG_TAB2_LIMBS - wn, w, wn); *error += 1; /* log(2) has 1 ulp error */ fmpz_set_si(q, -1); } return 1; /* success */ } else { mp_ptr qp, rp, np; mp_srcptr dp; mp_size_t qn, rn, nn, dn, tn, alloc; TMP_INIT; tn = ((exp + 2) + FLINT_BITS - 1) / FLINT_BITS; dn = wn + tn; /* denominator */ nn = wn + 2 * tn; /* numerator */ qn = nn - dn + 1; /* quotient */ rn = dn; /* remainder */ if (dn > ARB_LOG_TAB2_LIMBS) return 0; TMP_START; alloc = qn + rn + nn; qp = TMP_ALLOC_LIMBS(alloc); rp = qp + qn; np = rp + rn; dp = arb_log_log2_tab + ARB_LOG_TAB2_LIMBS - dn; /* todo: prove that zeroing is unnecessary */ flint_mpn_zero(np, nn); _arf_get_integer_mpn(np, xp, xn, exp + dn * FLINT_BITS); mpn_tdiv_qr(qp, rp, 0, np, nn, dp, dn); if (!negative) { flint_mpn_copyi(w, rp + tn, wn); *error = 2; } else { if (mpn_add_1(qp, qp, qn, 1)) { /* I believe this cannot happen (should prove it) */ flint_throw(FLINT_ERROR, "mod log(2): unexpected carry\n"); } mpn_sub_n(w, dp + tn, rp + tn, wn); *error = 3; } /* read the exponent */ while (qn > 1 && qp[qn-1] == 0) qn--; if (qn == 1) { if (!negative) fmpz_set_ui(q, qp[0]); else fmpz_neg_ui(q, qp[0]); } else { fmpz_set_mpn_large(q, qp, qn, negative); } TMP_END; return 1; } } flint-3.1.3/src/arb/get_mpn_fixed_mod_pi4.c000066400000000000000000000055401461254215100205610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #define TMP_ALLOC_LIMBS(__n) TMP_ALLOC((__n) * sizeof(mp_limb_t)) int _arb_get_mpn_fixed_mod_pi4(mp_ptr w, fmpz_t q, int * octant, mp_limb_t * error, const arf_t x, mp_size_t wn) { mp_srcptr xp; mp_size_t xn; slong exp; ARF_GET_MPN_READONLY(xp, xn, x); exp = ARF_EXP(x); if (exp <= -1) { flint_mpn_zero(w, wn); *error = _arf_get_integer_mpn(w, xp, xn, exp + wn * FLINT_BITS); *octant = 0; if (q != NULL) fmpz_zero(q); return 1; } else if (exp == 0) { mp_srcptr dp; if (wn > ARB_PI4_TAB_LIMBS) return 0; flint_mpn_zero(w, wn); *error = _arf_get_integer_mpn(w, xp, xn, exp + wn * FLINT_BITS); dp = arb_pi4_tab + ARB_PI4_TAB_LIMBS - wn; if (mpn_cmp(w, dp, wn) < 0) { *octant = 0; if (q != NULL) fmpz_zero(q); } else { *octant = 1; if (q != NULL) fmpz_one(q); mpn_sub_n(w, w, dp, wn); mpn_sub_n(w, dp, w, wn); *error += 2; } return 1; } else { mp_ptr qp, rp, np; mp_srcptr dp; mp_size_t qn, rn, nn, dn, tn, alloc; TMP_INIT; tn = ((exp + 2) + FLINT_BITS - 1) / FLINT_BITS; dn = wn + tn; /* denominator */ nn = wn + 2 * tn; /* numerator */ qn = nn - dn + 1; /* quotient */ rn = dn; /* remainder */ if (dn > ARB_PI4_TAB_LIMBS) return 0; TMP_START; alloc = qn + rn + nn; qp = TMP_ALLOC_LIMBS(alloc); rp = qp + qn; np = rp + rn; dp = arb_pi4_tab + ARB_PI4_TAB_LIMBS - dn; flint_mpn_zero(np, nn); _arf_get_integer_mpn(np, xp, xn, exp + dn * FLINT_BITS); mpn_tdiv_qr(qp, rp, 0, np, nn, dp, dn); *octant = qp[0] % 8; if (*octant % 2 == 0) { flint_mpn_copyi(w, rp + tn, wn); *error = 2; } else { mpn_sub_n(w, dp + tn, rp + tn, wn); *error = 3; } if (q != NULL) { /* read the exponent */ while (qn > 1 && qp[qn-1] == 0) qn--; if (qn == 1) fmpz_set_ui(q, qp[0]); else fmpz_set_mpn_large(q, qp, qn, 0); } TMP_END; return 1; } } flint-3.1.3/src/arb/get_rand_fmpq.c000066400000000000000000000040651461254215100171450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb.h" void _arb_get_rand_fmpq(fmpz_t num, fmpz_t den, flint_rand_t state, const fmpz_t den_mult, const arb_t x) { fmpz_t a, b, exp; fmpz_init(a); fmpz_init(b); fmpz_init(exp); arb_get_interval_fmpz_2exp(a, b, exp, x); if (COEFF_IS_MPZ(*exp)) { flint_throw(FLINT_ERROR, "exception: arb_get_rand_fmpq: too large exponent\n"); } if (*exp >= 0) { fmpz_mul_2exp(a, a, *exp); fmpz_mul_2exp(b, b, *exp); } /* generate random integer in [a*den, b*den] */ fmpz_mul(a, a, den_mult); fmpz_mul(b, b, den_mult); fmpz_add_ui(b, b, UWORD(1)); fmpz_sub(b, b, a); /* return one endpoint with high probability (used for stress testing rounding) */ if (n_randint(state, 6) == 0) { if (n_randint(state, 2)) fmpz_zero(num); else fmpz_sub_ui(num, b, UWORD(1)); } else { fmpz_randtest_mod(num, state, b); } fmpz_add(num, num, a); fmpz_set(den, den_mult); if (*exp < 0) fmpz_mul_2exp(den, den, -(*exp)); fmpz_clear(a); fmpz_clear(b); fmpz_clear(exp); } void arb_get_rand_fmpq(fmpq_t q, flint_rand_t state, const arb_t x, slong bits) { /* there is only one rational */ if (arb_is_exact(x)) { arf_get_fmpq(q, arb_midref(x)); return; } /* pick a denominator */ fmpz_randbits(fmpq_denref(q), state, n_randint(state, bits + 1)); fmpz_abs(fmpq_denref(q), fmpq_denref(q)); if (fmpz_is_zero(fmpq_denref(q))) fmpz_one(fmpq_denref(q)); _arb_get_rand_fmpq(fmpq_numref(q), fmpq_denref(q), state, fmpq_denref(q), x); fmpq_canonicalise(q); } flint-3.1.3/src/arb/get_str.c000066400000000000000000000301711461254215100160030ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "arb.h" #define RADIUS_DIGITS 3 char * _arb_condense_digits(char * s, slong n) { slong i, j, run, out; char * res; res = flint_malloc(strlen(s) + 128); /* space for some growth */ out = 0; for (i = 0; s[i] != '\0'; ) { if (isdigit(s[i])) { run = 0; for (j = 0; isdigit(s[i + j]); j++) run++; if (run > 3 * n) { for (j = 0; j < n; j++) { res[out] = s[i + j]; out++; } out += flint_sprintf(res + out, "{...%wd digits...}", run - 2 * n); for (j = run - n; j < run; j++) { res[out] = s[i + j]; out++; } } else { for (j = 0; j < run; j++) { res[out] = s[i + j]; out++; } } i += run; } else { res[out] = s[i]; i++; out++; } } res[out] = '\0'; res = flint_realloc(res, strlen(res) + 1); flint_free(s); return res; } /* Format (digits=d, exponent=e) as floating-point or fixed-point. Reallocates the input and mutates the exponent. */ void _arb_digits_as_float_str(char ** d, fmpz_t e, slong minfix, slong maxfix) { slong i, n, alloc, dotpos; /* do nothing with 0 or something non-numerical */ if (!((*d)[0] >= '1' && (*d)[0] <= '9')) return; n = strlen(*d); fmpz_add_ui(e, e, n - 1); /* fixed-point or integer format */ /* we require e < n - 1; otherwise we would have to insert trailing zeros [todo: could allow e < n, if printing integers without radix point] */ if (fmpz_cmp_si(e, minfix) >= 0 && fmpz_cmp_si(e, maxfix) <= 0 && fmpz_cmp_si(e, n - 1) < 0) { slong exp = *e; /* 0.000xxx */ if (exp < 0) { /* 0. + (-1-exp) zeros + digits + null terminator */ alloc = 2 + (-1-exp) + n + 1; *d = flint_realloc(*d, alloc); /* copy in reverse order, including null terminator */ for (i = n; i >= 0; i--) (*d)[2 + (-1-exp) + i] = (*d)[i]; for (i = 0; i < 2 + (-1-exp); i++) (*d)[i] = (i == 1) ? '.' : '0'; } else /* xxx.yyy --- must have dotpos < n - 1 */ { dotpos = exp + 1; alloc = n + 2; /* space for . and null terminator */ (*d) = flint_realloc(*d, alloc); /* copy fractional part in reverse order, including null */ for (i = n; i >= dotpos; i--) (*d)[i + 1] = (*d)[i]; (*d)[dotpos] = '.'; } } else { /* format as xe+zzz or x.yyye+zzz */ alloc = n + 1 + 2 + fmpz_sizeinbase(e, 10) + 1; *d = flint_realloc(*d, alloc); /* insert . */ if (n > 1) { /* copy fractional part in reverse order */ for (i = n; i >= 1; i--) (*d)[i + 1] = (*d)[i]; (*d)[1] = '.'; } (*d)[n + (n > 1)] = 'e'; if (fmpz_sgn(e) >= 0) { (*d)[n + (n > 1) + 1] = '+'; } else { (*d)[n + (n > 1) + 1] = '-'; fmpz_neg(e, e); } fmpz_get_str((*d) + n + (n > 1) + 2, 10, e); /* writes null byte */ } } /* Rounds a string of decimal digits (null-terminated). to length at most n. The rounding mode can be ARF_RND_DOWN, ARF_RND_UP or ARF_RND_NEAR. The string is overwritten in-place, truncating it as necessary. The input should not have a leading sign or leading zero digits, but can have trailing zero digits. Computes shift and error such that int(input) = int(output) * 10^shift + error exactly. */ void _arb_digits_round_inplace(char * s, flint_bitcnt_t * shift, fmpz_t error, slong n, arf_rnd_t rnd) { slong i, m; int up; if (n < 1) { flint_throw(FLINT_ERROR, "_arb_digits_round_inplace: require n >= 1\n"); } m = strlen(s); if (m <= n) { *shift = 0; fmpz_zero(error); return; } /* always round down */ if (rnd == ARF_RND_DOWN) { up = 0; } else if (rnd == ARF_RND_UP) /* round up if tail is nonzero */ { up = 0; for (i = n; i < m; i++) { if (s[i] != '0') { up = 1; break; } } } else /* round to nearest (up on tie -- todo: round-to-even?) */ { up = (s[n] >= '5' && s[n] <= '9'); } if (!up) { /* simply truncate */ fmpz_set_str(error, s + n, 10); s[n] = '\0'; *shift = m - n; } else { int digit, borrow, carry; /* error = 10^(m-n) - s[n:], where s[n:] is nonzero */ /* i.e. 10s complement the truncated digits */ borrow = 0; for (i = m - 1; i >= n; i--) { digit = 10 - (s[i] - '0') - borrow; if (digit == 10) { digit = 0; borrow = 0; } else { borrow = 1; } s[i] = digit + '0'; } if (!borrow) { flint_throw(FLINT_ERROR, "expected borrow!\n"); } fmpz_set_str(error, s + n, 10); fmpz_neg(error, error); /* add 1 ulp to the leading digits */ carry = 1; for (i = n - 1; i >= 0; i--) { digit = (s[i] - '0') + carry; if (digit > 9) { digit = 0; carry = 1; } else { carry = 0; } s[i] = digit + '0'; } /* carry-out -- only possible if we started with all 9s, so now the rest will be 0s which we don't have to shift explicitly */ if (carry) { s[0] = '1'; *shift = m - n + 1; } else { *shift = m - n; } s[n] = '\0'; /* truncate */ } } void arb_get_str_parts(int * negative, char **mid_digits, fmpz_t mid_exp, char **rad_digits, fmpz_t rad_exp, const arb_t x, slong n, int more) { fmpz_t mid, rad, exp, err; slong good; flint_bitcnt_t shift; if (!arb_is_finite(x)) { *negative = 0; fmpz_zero(mid_exp); *mid_digits = flint_malloc(4); if (arf_is_nan(arb_midref(x))) strcpy(*mid_digits, "nan"); else strcpy(*mid_digits, "0"); fmpz_zero(rad_exp); *rad_digits = flint_malloc(4); strcpy(*rad_digits, "inf"); return; } fmpz_init(mid); fmpz_init(rad); fmpz_init(exp); fmpz_init(err); /* heuristic part */ if (!more) { good = arb_rel_accuracy_bits(x) * 0.30102999566398119521 + 2; n = FLINT_MIN(n, good); } arb_get_fmpz_mid_rad_10exp(mid, rad, exp, x, FLINT_MAX(n, 1)); *negative = arf_sgn(arb_midref(x)) < 0; fmpz_abs(mid, mid); *mid_digits = fmpz_get_str(NULL, 10, mid); *rad_digits = NULL; /* Truncate further so that 1 ulp error can be guaranteed (rigorous part) Note: mid cannot be zero here if n >= 1 and rad != 0. */ if (n >= 1 && !(more || fmpz_is_zero(rad))) { slong lenmid, lenrad, rem; *rad_digits = fmpz_get_str(NULL, 10, rad); lenmid = strlen(*mid_digits); lenrad = strlen(*rad_digits); if (lenmid > lenrad) { /* we will truncate at n or n-1 */ good = lenmid - lenrad; /* rounding to nearest can add at most 0.5 ulp */ /* look at first omitted digit */ rem = ((*mid_digits)[good]) - '0'; if (rem < 5) rem = rem + 1; else rem = 10 - rem; /* and include the leading digit of the radius */ rem = rem + ((*rad_digits)[0] - '0') + 1; /* if error is <= 1.0 ulp, we get to keep the extra digit */ if (rem > 10) good -= 1; n = FLINT_MIN(n, good); } else { n = 0; } /* todo: avoid recomputing? */ flint_free(*rad_digits); } /* no accurate digits -- output 0 +/- rad */ if (n < 1) { fmpz_add(rad, rad, mid); fmpz_zero(mid); strcpy(*mid_digits, "0"); /* must have space already! */ } else { _arb_digits_round_inplace(*mid_digits, &shift, err, n, ARF_RND_NEAR); fmpz_add_ui(mid_exp, exp, shift); fmpz_abs(err, err); fmpz_add(rad, rad, err); } /* write radius */ if (fmpz_is_zero(rad)) { *rad_digits = fmpz_get_str(NULL, 10, rad); fmpz_zero(rad_exp); } else { *rad_digits = fmpz_get_str(NULL, 10, rad); _arb_digits_round_inplace(*rad_digits, &shift, err, RADIUS_DIGITS, ARF_RND_UP); fmpz_add_ui(rad_exp, exp, shift); } fmpz_clear(mid); fmpz_clear(rad); fmpz_clear(exp); fmpz_clear(err); } char * arb_get_str(const arb_t x, slong n, ulong flags) { char * res; char * mid_digits; char * rad_digits; int negative, more, skip_rad, skip_mid; fmpz_t mid_exp; fmpz_t rad_exp; slong condense; if (arb_is_zero(x)) { res = flint_malloc(2); strcpy(res, "0"); return res; } more = flags & ARB_STR_MORE; condense = flags / ARB_STR_CONDENSE; if (!arb_is_finite(x)) { res = flint_malloc(10); if (arf_is_nan(arb_midref(x))) strcpy(res, "nan"); else strcpy(res, "[+/- inf]"); return res; } fmpz_init(mid_exp); fmpz_init(rad_exp); arb_get_str_parts(&negative, &mid_digits, mid_exp, &rad_digits, rad_exp, x, n, more); if ((flags & ARB_STR_NO_RADIUS) && mid_digits[0] == '0') { fmpz_add_ui(rad_exp, rad_exp, strlen(rad_digits)); res = flint_malloc(fmpz_sizeinbase(rad_exp, 10) + 4); res[0] = '0'; res[1] = 'e'; if (fmpz_sgn(rad_exp) >= 0) { res[2] = '+'; fmpz_get_str(res + 3, 10, rad_exp); } else { fmpz_get_str(res + 2, 10, rad_exp); } } else { skip_mid = mid_digits[0] == '0'; skip_rad = (rad_digits[0] == '0') || ((flags & ARB_STR_NO_RADIUS) && !skip_mid); _arb_digits_as_float_str(&mid_digits, mid_exp, -4, FLINT_MAX(6, n - 1)); _arb_digits_as_float_str(&rad_digits, rad_exp, -2, 2); if (skip_rad) { res = flint_malloc(strlen(mid_digits) + 2); if (negative) strcpy(res, "-"); else strcpy(res, ""); strcat(res, mid_digits); } else if (skip_mid) { res = flint_malloc(strlen(rad_digits) + 7); strcpy(res, "[+/- "); strcat(res, rad_digits); strcat(res, "]"); } else { res = flint_malloc(strlen(mid_digits) + strlen(rad_digits) + 9); strcpy(res, "["); if (negative) strcat(res, "-"); strcat(res, mid_digits); strcat(res, " +/- "); strcat(res, rad_digits); strcat(res, "]"); } } if (condense) res = _arb_condense_digits(res, condense); flint_free(mid_digits); flint_free(rad_digits); fmpz_clear(mid_exp); fmpz_clear(rad_exp); return res; } flint-3.1.3/src/arb/get_ubound_arf.c000066400000000000000000000011051461254215100173120ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_get_ubound_arf(arf_t u, const arb_t x, slong prec) { arf_t t; arf_init_set_mag_shallow(t, arb_radref(x)); arf_add(u, arb_midref(x), t, prec, ARF_RND_CEIL); } flint-3.1.3/src/arb/get_unique_fmpz.c000066400000000000000000000046171461254215100175430ustar00rootroot00000000000000/* Copyright (C) 2012, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" int arb_get_unique_fmpz(fmpz_t z, const arb_t x) { if (!arb_is_finite(x)) { return 0; } else if (arb_is_exact(x)) { /* x = b*2^e, e >= 0 */ if (arf_is_int(arb_midref(x))) { /* arf_get_fmpz aborts on overflow */ arf_get_fmpz(z, arb_midref(x), ARF_RND_DOWN); return 1; } else { return 0; } } /* if the radius is >= 1, there are at least two integers */ else if (mag_cmp_2exp_si(arb_radref(x), 0) >= 0) { return 0; } /* there are 0 or 1 integers if the radius is < 1 */ else { fmpz_t a, b, exp; int res; /* if the midpoint is exactly an integer, it is what we want */ if (arf_is_int(arb_midref(x))) { /* arf_get_fmpz aborts on overflow */ arf_get_fmpz(z, arb_midref(x), ARF_RND_DOWN); return 1; } fmpz_init(a); fmpz_init(b); fmpz_init(exp); /* if the radius is tiny, it can't be an integer */ arf_bot(a, arb_midref(x)); if (fmpz_cmp(a, MAG_EXPREF(arb_radref(x))) > 0) { res = 0; } else { arb_get_interval_fmpz_2exp(a, b, exp, x); if (COEFF_IS_MPZ(*exp)) { flint_throw(FLINT_ERROR, "arb_get_unique_fmpz: input too large\n"); } if (*exp >= 0) { res = fmpz_equal(a, b); if (res) { fmpz_mul_2exp(a, a, *exp); fmpz_mul_2exp(b, b, *exp); } } else { fmpz_cdiv_q_2exp(a, a, -(*exp)); fmpz_fdiv_q_2exp(b, b, -(*exp)); res = fmpz_equal(a, b); } if (res) fmpz_set(z, a); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(exp); return res; } } flint-3.1.3/src/arb/hurwitz_zeta.c000066400000000000000000000017331461254215100170750ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb.h" void arb_hurwitz_zeta(arb_t res, const arb_t s, const arb_t z, slong prec) { if (!arb_contains_si(s, 1) && (arb_is_positive(z) || (arb_is_int(z) && arb_is_int(s) && arb_is_nonpositive(s)))) { acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c); acb_set_arb(a, s); acb_set_arb(b, z); acb_hurwitz_zeta(c, a, b, prec); arb_set(res, acb_realref(c)); acb_clear(a); acb_clear(b); acb_clear(c); } else { arb_indeterminate(res); } } flint-3.1.3/src/arb/hypot.c000066400000000000000000000015211461254215100154740ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_hypot(arb_t z, const arb_t x, const arb_t y, slong prec) { if (arb_is_zero(y)) { arb_abs(z, x); } else if (arb_is_zero(x)) { arb_abs(z, y); } else { arb_t t; arb_init(t); /* TODO: use arb_fmma */ arb_mul(t, x, x, prec + 4); arb_mul(z, y, y, prec + 4); arb_add(t, t, z, prec + 4); arb_sqrtpos(z, t, prec); arb_clear(t); } } flint-3.1.3/src/arb/indeterminate.c000066400000000000000000000007551461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_indeterminate(arb_t x) { arf_nan(arb_midref(x)); mag_inf(arb_radref(x)); } flint-3.1.3/src/arb/inlines.c000066400000000000000000000006461461254215100160010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ARB_INLINES_C #include "arb.h" flint-3.1.3/src/arb/intersection.c000066400000000000000000000026751461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" int arb_intersection(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t left, right, t, xr, yr; int result; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) { arb_indeterminate(z); return 1; } if (mag_is_inf(arb_radref(x)) && mag_is_inf(arb_radref(y))) { arb_zero_pm_inf(z); return 1; } result = arb_overlaps(x, y); if (result) { arf_init(left); arf_init(right); arf_init(t); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); arf_sub(left, arb_midref(x), xr, prec, ARF_RND_FLOOR); arf_sub(t, arb_midref(y), yr, prec, ARF_RND_FLOOR); arf_max(left, left, t); arf_add(right, arb_midref(x), xr, prec, ARF_RND_CEIL); arf_add(t, arb_midref(y), yr, prec, ARF_RND_CEIL); arf_min(right, right, t); arb_set_interval_arf(z, left, right, prec); arf_clear(left); arf_clear(right); arf_clear(t); } return result; } flint-3.1.3/src/arb/io.c000066400000000000000000000072141461254215100147450ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson Copyright (C) 2015 Arb authors Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "arb.h" #include "arf.h" #include "mag.h" /* strings ********************************************************************/ char * arb_dump_str(const arb_t x) { char * mid; char * mag; size_t res_len; char * res; mid = arf_dump_str(arb_midref(x)); mag = mag_dump_str(arb_radref(x)); res_len = strlen(mid) + 1 + strlen(mag); res = (char*)flint_malloc(res_len + 1); strcpy(res, mid); strcat(res, " "); strcat(res, mag); flint_free(mid); flint_free(mag); return res; } int arb_load_str(arb_t x, const char* data) { size_t midlen, maglen; char * mid; char * mag; int err = 0; const char* split = strchr(data, ' '); if (split == NULL) { return 1; } split = strchr(split + 1, ' '); if (split == NULL) { return 1; } midlen = (size_t)(split - data); mid = (char*)flint_malloc(midlen + 1); strncpy(mid, data, midlen); mid[midlen] = '\0'; maglen = strlen(data) - midlen - 1; mag = (char*)flint_malloc(maglen + 1); strncpy(mag, split + 1, maglen); mag[maglen] = '\0'; err = arf_load_str(arb_midref(x), mid); if (err) { flint_free(mid); flint_free(mag); return err; } err = mag_load_str(arb_radref(x), mag); flint_free(mid); flint_free(mag); return err; } /* printing *******************************************************************/ void arb_fprint(FILE * file, const arb_t x) { arf_fprint(file, arb_midref(x)); flint_fprintf(file, " +/- "); mag_fprint(file, arb_radref(x)); } void arb_fprintd(FILE * file, const arb_t x, slong digits) { arf_fprintd(file, arb_midref(x), FLINT_MAX(digits, 1)); flint_fprintf(file, " +/- "); mag_fprintd(file, arb_radref(x), 5); } void arb_fprintn(FILE * file, const arb_t x, slong digits, ulong flags) { char * s = arb_get_str(x, digits, flags); flint_fprintf(file, "%s", s); flint_free(s); } void arb_print(const arb_t x) { arb_fprint(stdout, x); } void arb_printd(const arb_t x, slong digits) { arb_fprintd(stdout, x, digits); } void arb_printn(const arb_t x, slong digits, ulong flags) { arb_fprintn(stdout, x, digits, flags); } void _arb_vec_printn(arb_srcptr vec, slong len, slong ndigits, ulong flags) { slong i; for (i = 0; i < len; i++) { arb_printn(vec + i, ndigits, flags); if (i < len - 1) flint_printf(", "); } } void _arb_vec_printd(arb_srcptr vec, slong len, slong ndigits) { slong i; for (i = 0; i < len; i++) { arb_printd(vec + i, ndigits); if (i < len - 1) { flint_printf(", "); } } flint_printf("\n"); } /* file I/O *******************************************************************/ int arb_dump_file(FILE* stream, const arb_t x) { int nwrite; char* data = arb_dump_str(x); nwrite = fputs(data, stream); if (nwrite == EOF) return nwrite; flint_free(data); return 0; } int arb_load_file(arb_t x, FILE* stream) { int err; err = arf_load_file(arb_midref(x), stream); if (err) return err; err = mag_load_file(arb_radref(x), stream); return err; } flint-3.1.3/src/arb/is_finite.c000066400000000000000000000007771461254215100163160ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" int arb_is_finite(const arb_t x) { return arf_is_finite(arb_midref(x)) && mag_is_finite(arb_radref(x)); } flint-3.1.3/src/arb/lambertw.c000066400000000000000000000401141461254215100161470ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "double_extras.h" /* Helper functions to compute W_{-1}(x) on (-1/e,0) in double precision -- just to get a good starting value for the multiprecision code, and not optimized for accuracy. Has underflow problems very close to 0. In part based on d_lambertw in flint/double_extras which implements the principal branch. */ #define ONE_OVER_E ldexp(6627126856707895.0, -54) #define CORRECTION 4.3082397558469466e-17 #define POLY(p, x) d_polyval((p), sizeof(p) / sizeof(double), (x)) static double d_halley(double x, double w) { double t, u, v; t = exp(w); u = 2*w + 2; v = w*t - x; t = w - u*v / (u*t*(w+1) - (w+2)*v); return t; } static const double pol1[11] = { -1.0000000000000000000, 2.3316439815971242034, -1.8121878856393634902, 1.9366311144923597554, -2.3535512018816145168, 3.0668589010506319129, -4.1753356002581771389, 5.8580237298747741488, -8.4010322175239773710, 12.250753501314460424, -18.100697012472442755 }; static const double pol2[4] = { -5.2012020327515463962,-24.075862656446909233, -26.500221957196285366,2.3340178581744999812 }; static const double pol3[4] = { 1.0000000000000000000,0.14831080741950550754, -13.649088405005569258,-18.975103873227202378 }; static const double pol4[5] = { -8.4834127832006526854,634.84191267691313548,-2640.6635889188399862, -12935.640726994524734,-7875.3418281832619890 }; static const double pol5[5] = { 1.0,-121.07185283214167442,1287.5430771188798866, 1550.0693150055578327,-3278.4808321541988073 }; static const double pol6[5] = { -12.169991898228748602,32778.761570863291802,-1.0480461503378867869e7, 4.7898751364090879209e8,-7.802332913704000874e8 }; static const double pol7[5] = { 1.0,-3556.4306263369027831,1.4761527435056145298e6, -9.8425904825010893103e7,7.0373606710750560344e8 }; double d_lambertw_branch1(double x) { double w, u; if (x < -ONE_OVER_E || x >= 0.0) { return D_NAN; } else if (x < -ONE_OVER_E + 1/32.) { w = POLY(pol1, -sqrt((x + ONE_OVER_E) + CORRECTION)); if (x + ONE_OVER_E > 0.0003) w = d_halley(x, w); return w; } else if (x <= -1/4.) { return d_halley(x, POLY(pol2,x) / POLY(pol3,x)); } else if (x < -1/32.) { return d_halley(x, POLY(pol4,x) / POLY(pol5,x)); } else if (x < - 1/1024.) { return d_halley(x, POLY(pol6,x) / POLY(pol7,x)); } else { w = log(-x); u = log(-w); w = (2*w*w*w - 2*(1+(w-1)*w)*u + u*u)/(2*w*w); if (x < -1e-15) w = d_halley(x, w); return d_halley(x, w); } } /* If branch == 0, bounds |W'(x)|. If branch != 0, bounds W_{-1}'(x). For the principal branch: For x >= 0, W'(x) <= 1/(x+1). For x > -1/e, W'(x) < 2 / sqrt(1+e*x). For the -1 branch: |W'(x)| <= 2 / sqrt(1+e*x) + 2/|x|. */ void arb_lambertw_bound_prime(mag_t w, const arb_t x, int branch, slong prec) { arb_t t; mag_t u, v; arb_init(t); mag_init(u); mag_init(v); if (arb_is_nonnegative(x) && branch == 0) { arb_get_mag_lower(w, x); mag_one(u); mag_add_lower(w, w, u); mag_div(w, u, w); } else { arb_const_e(t, prec); arb_mul(t, t, x, prec); arb_add_ui(t, t, 1, prec); arb_get_mag_lower(w, t); mag_rsqrt(w, w); mag_mul_2exp_si(w, w, 1); if (branch != 0) { if (arb_is_negative(x)) { arb_get_mag_lower(u, x); mag_set_ui(v, 2); mag_div(v, v, u); mag_add(w, w, v); } else { mag_inf(w); } } } arb_clear(t); mag_clear(u); mag_clear(v); } /* Given an approximation w for W(x), compute a rigorous error bound. The precomputed value ew = e^w is optional. */ void arb_lambertw_bound_error(mag_t res, const arb_t x, const arf_t w, const arb_t ew, int branch, slong prec) { arb_t r, x2; mag_t m; /* Make sure that we are somewhere on the right branch. */ if ((branch == 0 && arf_cmp_si(w, -1) < 0) || (branch == 1 && arf_cmp_si(w, -1) > 0)) { mag_inf(res); return; } arb_init(r); arb_init(x2); mag_init(m); if (ew != NULL) { arb_set(r, ew); } else { arb_set_arf(r, w); arb_exp(r, r, prec); } /* x2 = w e^w */ arb_mul_arf(x2, r, w, prec); /* r = x2 - x */ arb_sub(r, x2, x, prec); arb_get_mag(m, r); /* x2 = min(x, x+r) (W'(t) is decreasing with t) */ if (branch == 0) { arb_min(x2, x, x2, prec); } else { arb_union(x2, x, x2, prec); } arb_lambertw_bound_prime(res, x2, branch, prec); mag_mul(res, res, m); arb_clear(r); arb_clear(x2); mag_clear(m); } /* Halley iteration: res = w - (w e^w - x) / (e^w (w+1) - (w+2)(w e^w - x) / (2w+2)) If certify is set, writes rigorous error bound to the radius. */ static void arb_lambertw_halley_step(arb_t res, const arb_t x, const arf_t w, int branch, int certify, slong prec) { arf_t t, u, v; arb_t ew; mag_t err; arb_init(ew); arf_init(t); arf_init(u); arf_init(v); mag_init(err); arb_set_arf(ew, w); arb_exp(ew, ew, prec); /* todo: extra precision with large exponents? */ arf_add_ui(u, w, 2, prec, ARF_RND_DOWN); arf_add_ui(v, w, 1, prec, ARF_RND_DOWN); arf_mul_2exp_si(v, v, 1); arf_div(v, u, v, prec, ARF_RND_DOWN); /* v = (w + 2) / (2w + 2) */ arf_mul(t, arb_midref(ew), w, prec, ARF_RND_DOWN); /* t = w e^w */ arf_sub(u, t, arb_midref(x), prec, ARF_RND_DOWN); /* u = w e^w - x */ arf_mul(v, v, u, prec, ARF_RND_DOWN); arf_neg(v, v); arf_add(v, v, t, prec, ARF_RND_DOWN); arf_add(v, v, arb_midref(ew), prec, ARF_RND_DOWN); arf_div(t, u, v, prec, ARF_RND_DOWN); /* t is our new approximation for W */ arf_sub(t, w, t, prec, ARF_RND_DOWN); if (certify) { arb_t et; arb_init(et); /* Inverse: x2 = t e^t. We already have e^w, so compute e^t = e^w e^(t-w). */ arb_set_arf(et, w); arb_sub_arf(et, et, t, prec); arb_neg(et, et); arb_exp(et, et, prec); arb_mul(et, et, ew, prec); arb_lambertw_bound_error(err, x, t, et, branch, prec); arb_clear(et); } arf_swap(arb_midref(res), t); mag_swap(arb_radref(res), err); arb_clear(ew); arf_clear(t); arf_clear(u); arf_clear(v); mag_clear(err); } /* Double precision approximation good for x >= 2^1000, or roughly |x| <= 2^(1000-60) for the -1 branch. */ slong arb_lambertw_initial_asymp1(arf_t res, const arf_t x, int branch, slong prec) { fmpz_t e; double l, ll, h, t2, t3, t4; fmpz_init(e); arf_frexp(res, e, x); l = arf_get_d(res, ARF_RND_DOWN); if (branch) l = -l; l = log(l); l += fmpz_get_d(e) * 0.6931471805599453; ll = l; if (branch) ll = -ll; ll = log(ll); h = 1.0 / l; t2 = ll * (ll - 2) * 0.5; t3 = ll * (6 + ll * (2 * ll - 9)) * (1.0 / 6.0); t4 = ll * (-12 + ll * (36 + ll*(-22 + 3*ll))) * (1.0 / 12.0); l = l - ll + h * (ll + h * (t2 + h * (t3 + t4 * h))); arf_set_d(res, l); fmpz_clear(e); return 50; } /* First terms of asymptotic series, with higher precision, for huge exponents... */ static void _arf_log(arf_t res, const arf_t x, slong prec) { arb_t t; arb_init(t); arb_set_arf(t, x); arb_log(t, t, prec); arf_swap(res, arb_midref(t)); arb_clear(t); } slong arb_lambertw_initial_asymp2(arf_t res, const arf_t x, int branch, slong prec) { arf_t l, ll; slong wp, acc; acc = 2 * fmpz_bits(ARF_EXPREF(x)) - 10; arf_init(l); arf_init(ll); wp = acc + 4; if (branch) { arf_neg(l, x); _arf_log(l, l, wp); arf_neg(ll, l); _arf_log(ll, ll, wp); } else { _arf_log(l, x, wp); _arf_log(ll, l, wp); } arf_div(res, ll, l, wp, ARF_RND_DOWN); arf_sub(res, res, ll, wp, ARF_RND_DOWN); arf_add(res, res, l, wp, ARF_RND_DOWN); arf_clear(l); arf_clear(ll); return acc; } /* Computes initial approximation of W(x). Returns estimated accuracy in bits, clamped between 0 and a reasonable value related to the bit length of the exponent of x; thus the return value plus 2 can be used as a precision. */ slong arb_lambertw_initial(arf_t res, const arf_t x, int branch, slong prec) { if (arf_cmp_d(x, -ONE_OVER_E + 0.001) >= 0) { if (branch == 0) { if (arf_cmpabs_2exp_si(x, -prec) < 0) { arf_set(res, x); return prec; } else if (arf_cmpabs_2exp_si(x, -30) < 0) { slong acc; arf_set(res, x); acc = -arf_abs_bound_lt_2exp_si(res); return FLINT_MIN(acc, prec); } else if (arf_cmpabs_2exp_si(x, 1000) > 0) { if (fmpz_bits(ARF_EXPREF(x)) > 40) return arb_lambertw_initial_asymp2(res, x, branch, prec); else return arb_lambertw_initial_asymp1(res, x, branch, prec); } else { arf_set_d(res, d_lambertw(arf_get_d(x, ARF_RND_DOWN))); return 50; } } else { /* slightly smaller than the double exponent limit since d_lambertw_branch1 is unclever about underflowing */ if (arf_cmpabs_2exp_si(x, -940) < 0) { if (fmpz_bits(ARF_EXPREF(x)) > 40) return arb_lambertw_initial_asymp2(res, x, branch, prec); else return arb_lambertw_initial_asymp1(res, x, branch, prec); } else { arf_set_d(res, d_lambertw_branch1(arf_get_d(x, ARF_RND_DOWN))); return 50; } } } else { /* Expand at -1/e */ static const int coeffs[] = {-130636800,130636800,-43545600,19958400, -10402560,5813640,-3394560,2042589,-1256320}; arb_t v; arf_t s; slong wp, k, acc; /* todo: could change precision dynamically depending on the closeness to -1/e */ wp = 2 * prec + 20; arb_init(v); arf_init(s); arb_const_e(v, wp); arb_mul_arf(v, v, x, wp); arb_add_ui(v, v, 1, wp); arb_mul_2exp_si(v, v, 1); arb_sqrt(v, v, wp); if (branch) arb_neg(v, v); for (k = 8; k >= 0; k--) { arf_mul(s, s, arb_midref(v), wp, ARF_RND_DOWN); arf_add_si(s, s, coeffs[k], wp, ARF_RND_DOWN); } arf_div_si(s, s, -coeffs[0], wp, ARF_RND_DOWN); arf_set(res, s); arb_clear(v); arf_clear(s); /* Due to the arithmetic we should get no more than wp accurate bits */ acc = wp; /* Truncation error is of order v^9 */ if (!arf_is_special(arb_midref(v))) acc = FLINT_MIN(acc, 9 * (-ARF_EXP(arb_midref(v)))); acc = FLINT_MAX(acc, 0); return acc; } } void arb_lambertw(arb_t res, const arb_t x, int flags, slong prec) { slong acc, wp, goal; slong ebits, ebits2; arb_t t, w; mag_t err; int branch; branch = flags & 1; if (!arb_is_finite(x)) { arb_indeterminate(res); return; } if (branch == 1 && !arb_is_negative(x)) { arb_indeterminate(res); return; } if (arb_is_zero(x)) { arb_zero(res); return; } /* Quick estimate of log(x) and log(log(x)). */ ebits = fmpz_bits(ARF_EXPREF(arb_midref(x))); ebits2 = FLINT_BIT_COUNT(ebits) + 2; /* Estimated accuracy goal. */ goal = arb_rel_accuracy_bits(x); goal = FLINT_MAX(goal, 0); goal = FLINT_MIN(goal, prec); /* For huge x, we gain bits from the exponent. */ if (branch == 0 && goal > 0 && arf_cmp_2exp_si(arb_midref(x), 10) > 0) goal = FLINT_MIN(goal + ebits - ebits2, prec); wp = goal + 4; /* Handle huge x directly. For x >= e, |W(x) - (log(x) - log(log(x)))| < 2/log(log(x))/log(x). (J. Inequal. Pure and Appl. Math., 9 (2) (2008), Art. 51). Note W(x) ~= log(x), so relative error is ~= log(log(x)) / log(x)^2. */ if (branch == 0 && arf_cmp_2exp_si(arb_midref(x), 10) > 0 && 2 * ebits - ebits2 > wp) { mag_t l, ll; arb_init(t); mag_init(l); mag_init(ll); arb_log(t, x, wp); arb_log(res, t, FLINT_MAX(wp - ebits + ebits2, 10)); if (arb_is_positive(res)) { arb_get_mag_lower(l, t); arb_get_mag(ll, res); arb_sub(res, t, res, prec); mag_div(l, ll, l); mag_mul_2exp_si(l, l, 1); arb_add_error_mag(res, l); } else { arb_indeterminate(res); } arb_clear(t); mag_clear(l); mag_clear(ll); return; } /* Handle tiny x directly. For k >= 2, |c_k| <= 4^k / 16. */ if (branch == 0 && arf_cmpabs_2exp_si(arb_midref(x), -10) < 0 && ebits > wp / 2) { mag_init(err); arb_get_mag(err, x); mag_mul_2exp_si(err, err, 2); if (ebits > wp) { arb_set_round(res, x, prec); mag_geom_series(err, err, 2); } else { arb_set(res, x); arb_submul(res, res, res, prec); mag_geom_series(err, err, 3); } mag_mul_2exp_si(err, err, -4); arb_add_error_mag(res, err); mag_clear(err); return; } arb_init(t); arb_init(w); mag_init(err); acc = arb_lambertw_initial(arb_midref(w), arb_midref(x), branch, wp); if (acc <= 2) { arb_indeterminate(w); } else if (acc >= wp) { arb_lambertw_bound_error(arb_radref(w), x, arb_midref(w), NULL, branch, FLINT_MAX(acc, 30)); } else { slong k, padding, nextstep, maxstep, *steps; double rate, nearm1; steps = flint_malloc(sizeof(slong) * FLINT_BITS); /* Asymptotically, the Halley iteration triples the number of accurate bits. However, with a very large exponent we need some guard bits (due to evaluating the exponential?). This is heuristic. A better analysis should be possible. */ rate = 2.0 + 1.0 / (1.0 + 0.01 * ebits); padding = 6 * ebits2; /* extra padding near -1/e */ nearm1 = arf_get_d(arb_midref(w), ARF_RND_DOWN); if (fabs(nearm1 + 1.0) < 0.01) { arf_add_ui(arb_midref(t), arb_midref(w), 1, 30, ARF_RND_DOWN); if (arf_is_zero(arb_midref(t))) padding += prec; else { slong ee = -ARF_EXP(arb_midref(t)); padding += FLINT_MIN(FLINT_MAX(2 * ee, 0), prec); } } maxstep = 0; steps[0] = wp; for (k = 1; k < FLINT_BITS; k++) { nextstep = steps[k - 1] / rate + padding; if (nextstep > acc) { steps[k] = nextstep; maxstep = k; } else break; } for (k = maxstep; k >= 0; k--) { arb_lambertw_halley_step(w, x, arb_midref(w), branch, (k == 0), steps[k] + 5); } flint_free(steps); } arb_set_round(res, w, prec); arb_clear(t); arb_clear(w); mag_clear(err); } flint-3.1.3/src/arb/log.c000066400000000000000000000051161461254215100151160ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_log(arb_t res, const arb_t x, slong prec) { if (arb_is_exact(x)) { arb_log_arf(res, arb_midref(x), prec); } else { /* Let the input be [a-b, a+b]. We require a > b >= 0 (otherwise the interval contains zero or a negative number and the logarithm is not defined). The error is largest at a-b, and we have log(a) - log(a-b) = log(1 + b/(a-b)). */ mag_t t; mag_init(t); arb_get_mag_lower_nonnegative(t, x); if (mag_is_zero(t)) { arf_nan(arb_midref(res)); mag_inf(arb_radref(res)); } else if (mag_is_inf(t)) { arf_pos_inf(arb_midref(res)); mag_zero(arb_radref(res)); } else { slong acc; acc = arb_rel_accuracy_bits(x); acc = FLINT_MIN(acc, prec); acc += fmpz_bits(MAG_EXPREF(t)); if (acc < 20) { mag_t u; mag_init(u); arb_get_mag(u, x); if (mag_cmp_2exp_si(t, 0) >= 0) { mag_log_lower(t, t); mag_log(u, u); arb_set_interval_mag(res, t, u, prec); } else if (mag_cmp_2exp_si(u, 0) <= 0) { mag_neg_log_lower(u, u); mag_neg_log(t, t); arb_set_interval_mag(res, u, t, prec); arb_neg(res, res); } else { mag_neg_log(t, t); mag_log(u, u); arb_set_interval_neg_pos_mag(res, t, u, prec); } mag_clear(u); } else { acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); mag_div(t, arb_radref(x), t); mag_log1p(t, t); arb_log_arf(res, arb_midref(x), prec); mag_add(arb_radref(res), arb_radref(res), t); } } mag_clear(t); } } flint-3.1.3/src/arb/log1p.c000066400000000000000000000026231461254215100153570ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void arb_log1p_tiny(arb_t r, const arb_t z, slong prec) { mag_t b, c; arb_t t; mag_init(b); mag_init(c); arb_init(t); /* if |z| < 1, then |log(1+z) - [z - z^2/2]| <= |z|^3/(1-|z|) */ arb_get_mag(b, z); mag_one(c); mag_sub_lower(c, c, b); mag_pow_ui(b, b, 3); mag_div(b, b, c); arb_mul(t, z, z, prec); arb_mul_2exp_si(t, t, -1); arb_sub(r, z, t, prec); if (mag_is_finite(b)) arb_add_error_mag(r, b); else arb_indeterminate(r); mag_clear(b); mag_clear(c); arb_clear(t); } void arb_log1p(arb_t r, const arb_t z, slong prec) { slong magz; if (arb_is_zero(z)) { arb_zero(r); return; } magz = arf_abs_bound_lt_2exp_si(arb_midref(z)); if (magz < -prec) { arb_log1p_tiny(r, z, prec); } else { if (magz < 0) arb_add_ui(r, z, 1, prec + (-magz) + 4); else arb_add_ui(r, z, 1, prec + 4); arb_log(r, r, prec); } } flint-3.1.3/src/arb/log_arf.c000066400000000000000000000253261461254215100157530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" int _arb_log_ui_smooth(arb_t res, ulong n, slong prec); #define TMP_ALLOC_LIMBS(size) TMP_ALLOC((size) * sizeof(mp_limb_t)) #if 0 /* requires x != 1 */ static void arf_log_via_mpfr(arf_t z, const arf_t x, slong prec, arf_rnd_t rnd) { mpfr_t xf, zf; mp_ptr zptr, tmp; mp_srcptr xptr; mp_size_t xn, zn, val; TMP_INIT; TMP_START; zn = (prec + FLINT_BITS - 1) / FLINT_BITS; tmp = TMP_ALLOC(zn * sizeof(mp_limb_t)); ARF_GET_MPN_READONLY(xptr, xn, x); xf->_mpfr_d = (mp_ptr) xptr; xf->_mpfr_prec = xn * FLINT_BITS; xf->_mpfr_sign = ARF_SGNBIT(x) ? -1 : 1; xf->_mpfr_exp = ARF_EXP(x); zf->_mpfr_d = tmp; zf->_mpfr_prec = prec; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; mpfr_set_emin(MPFR_EMIN_MIN); mpfr_set_emax(MPFR_EMAX_MAX); mpfr_log(zf, xf, arf_rnd_to_mpfr(rnd)); val = 0; while (tmp[val] == 0) val++; ARF_GET_MPN_WRITE(zptr, zn - val, z); flint_mpn_copyi(zptr, tmp + val, zn - val); if (zf->_mpfr_sign < 0) ARF_NEG(z); fmpz_set_si(ARF_EXPREF(z), zf->_mpfr_exp); TMP_END; } #endif void arb_log_arf_huge(arb_t z, const arf_t x, slong prec) { arf_t t; arb_t c; fmpz_t exp; slong wp; arf_init(t); arb_init(c); fmpz_init(exp); fmpz_neg(exp, ARF_EXPREF(x)); arf_mul_2exp_fmpz(t, x, exp); wp = prec + 4 - fmpz_bits(exp); wp = FLINT_MAX(wp, 4); arb_log_arf(z, t, wp); arb_const_log2(c, prec + 4); arb_submul_fmpz(z, c, exp, prec); arf_clear(t); arb_clear(c); fmpz_clear(exp); } void arb_log_arf(arb_t z, const arf_t x, slong prec) { if (arf_is_special(x)) { if (arf_is_pos_inf(x)) arb_pos_inf(z); else arb_indeterminate(z); } else if (ARF_SGNBIT(x)) { arb_indeterminate(z); } else if (ARF_IS_POW2(x)) { if (fmpz_is_one(ARF_EXPREF(x))) { arb_zero(z); } else { fmpz_t exp; fmpz_init(exp); _fmpz_add_fast(exp, ARF_EXPREF(x), -1); arb_const_log2(z, prec + 2); arb_mul_fmpz(z, z, exp, prec); fmpz_clear(exp); } } else if (COEFF_IS_MPZ(ARF_EXP(x))) { arb_log_arf_huge(z, x, prec); } else { slong exp, wp, wn, N, r, closeness_to_one; mp_srcptr xp; mp_size_t xn, tn; mp_ptr tmp, w, t, u; mp_limb_t p1, q1bits, p2, q2bits, error, error2, cy; int negative, inexact, used_taylor_series; TMP_INIT; exp = ARF_EXP(x); negative = 0; ARF_GET_MPN_READONLY(xp, xn, x); /* compute a c >= 0 such that |x-1| <= 2^(-c) if c > 0 */ closeness_to_one = 0; if (exp == 0) { slong i; closeness_to_one = FLINT_BITS - FLINT_BIT_COUNT(~xp[xn - 1]); if (closeness_to_one == FLINT_BITS) { for (i = xn - 2; i > 0 && xp[i] == LIMB_ONES; i--) closeness_to_one += FLINT_BITS; closeness_to_one += (FLINT_BITS - FLINT_BIT_COUNT(~xp[i])); } } else if (exp == 1) { closeness_to_one = FLINT_BITS - FLINT_BIT_COUNT(xp[xn - 1] & (~LIMB_TOP)); if (closeness_to_one == FLINT_BITS) { slong i; for (i = xn - 2; xp[i] == 0; i--) closeness_to_one += FLINT_BITS; closeness_to_one += (FLINT_BITS - FLINT_BIT_COUNT(xp[i])); } closeness_to_one--; } /* if |t-1| <= 0.5 */ /* |log(1+t) - t| <= t^2 */ /* |log(1+t) - (t-t^2/2)| <= t^3 */ if (closeness_to_one > prec + 1) { inexact = arf_sub_ui(arb_midref(z), x, 1, prec, ARB_RND); mag_set_ui_2exp_si(arb_radref(z), 1, -2 * closeness_to_one); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); return; } else if (2 * closeness_to_one > prec + 1) { arf_t t, u; arf_init(t); arf_init(u); arf_sub_ui(t, x, 1, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(u, t, t, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_2exp_si(u, u, -1); inexact = arf_sub(arb_midref(z), t, u, prec, ARB_RND); mag_set_ui_2exp_si(arb_radref(z), 1, -3 * closeness_to_one); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); arf_clear(t); arf_clear(u); return; } /* Absolute working precision (NOT rounded to a limb multiple) */ wp = prec + closeness_to_one + 5; /* Too high precision to use table */ if (wp > ARB_LOG_NEWTON_PREC || wp > ARB_LOG_TAB2_PREC) { /* Special case: check for smooth integers */ if (xn == 1 && exp <= FLINT_BITS && exp >= 1) { ulong n; n = xp[0] >> (FLINT_BITS - exp); if ((n << (FLINT_BITS - exp)) == xp[0]) { if (_arb_log_ui_smooth(z, n, prec)) { return; } } } #if 0 /* The earlier test for COEFF_IS_MPZ(ARF_EXP(x)) rules out too large exponents for MPFR, except on Windows 64 where MPFR still uses 32-bit exponents. */ if (exp < MPFR_EMIN_MIN || exp > MPFR_EMAX_MAX) { arb_log_arf_huge(z, x, prec); } else { arf_log_via_mpfr(arb_midref(z), x, prec, ARB_RND); arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); } #else arb_log_arf_newton(z, x, prec); #endif return; } /* Working precision in limbs */ wn = (wp + FLINT_BITS - 1) / FLINT_BITS; TMP_START; tmp = TMP_ALLOC_LIMBS(4 * wn + 3); w = tmp; /* requires wn+1 limbs */ t = w + wn + 1; /* requires wn+1 limbs */ u = t + wn + 1; /* requires 2wn+1 limbs */ /* read x-1 */ if (xn <= wn) { flint_mpn_zero(w, wn - xn); mpn_lshift(w + wn - xn, xp, xn, 1); error = 0; } else { mpn_lshift(w, xp + xn - wn, wn, 1); error = 1; } /* First table-based argument reduction */ if (wp <= ARB_LOG_TAB1_PREC) q1bits = ARB_LOG_TAB11_BITS; else q1bits = ARB_LOG_TAB21_BITS; p1 = w[wn-1] >> (FLINT_BITS - q1bits); /* Special case: covers logarithms of small integers */ if (xn == 1 && (w[wn-1] == (p1 << (FLINT_BITS - q1bits)))) { p2 = 0; flint_mpn_zero(t, wn); used_taylor_series = 0; N = r = 0; /* silence compiler warning */ } else { /* log(1+w) = log(1+p/q) + log(1 + (qw-p)/(p+q)) */ w[wn] = mpn_mul_1(w, w, wn, UWORD(1) << q1bits) - p1; mpn_divrem_1(w, 0, w, wn + 1, p1 + (UWORD(1) << q1bits)); error += 1; /* Second table-based argument reduction (fused with log->atanh conversion) */ if (wp <= ARB_LOG_TAB1_PREC) q2bits = ARB_LOG_TAB11_BITS + ARB_LOG_TAB12_BITS; else q2bits = ARB_LOG_TAB21_BITS + ARB_LOG_TAB22_BITS; p2 = w[wn-1] >> (FLINT_BITS - q2bits); u[2 * wn] = mpn_lshift(u + wn, w, wn, q2bits); flint_mpn_zero(u, wn); flint_mpn_copyi(t, u + wn, wn + 1); t[wn] += p2 + (UWORD(1) << (q2bits + 1)); u[2 * wn] -= p2; mpn_tdiv_q(w, u, 2 * wn + 1, t, wn + 1); /* propagated error from 1 ulp error: 2 atanh'(1/3) = 2.25 */ error += 3; /* |w| <= 2^-r */ r = _arb_mpn_leading_zeros(w, wn); /* N >= (wp-r)/(2r) */ N = (wp - r + (2*r-1)) / (2*r); N = FLINT_MAX(N, 0); /* Evaluate Taylor series */ _arb_atan_taylor_rs(t, &error2, w, wn, N, 0); /* Multiply by 2 */ mpn_lshift(t, t, wn, 1); /* Taylor series evaluation error (multiply by 2) */ error += error2 * 2; used_taylor_series = 1; } /* Size of output number */ tn = wn; /* First table lookup */ if (p1 != 0) { if (wp <= ARB_LOG_TAB1_PREC) mpn_add_n(t, t, arb_log_tab11[p1] + ARB_LOG_TAB1_LIMBS - tn, tn); else mpn_add_n(t, t, arb_log_tab21[p1] + ARB_LOG_TAB2_LIMBS - tn, tn); error++; } /* Second table lookup */ if (p2 != 0) { if (wp <= ARB_LOG_TAB1_PREC) mpn_add_n(t, t, arb_log_tab12[p2] + ARB_LOG_TAB1_LIMBS - tn, tn); else mpn_add_n(t, t, arb_log_tab22[p2] + ARB_LOG_TAB2_LIMBS - tn, tn); error++; } /* add exp * log(2) */ exp--; if (exp > 0) { cy = mpn_addmul_1(t, arb_log_log2_tab + ARB_LOG_TAB2_LIMBS - tn, tn, exp); t[tn] = cy; tn += (cy != 0); error += exp; } else if (exp < 0) { t[tn] = 0; u[tn] = mpn_mul_1(u, arb_log_log2_tab + ARB_LOG_TAB2_LIMBS - tn, tn, -exp); if (mpn_cmp(t, u, tn + 1) >= 0) { mpn_sub_n(t, t, u, tn + 1); } else { mpn_sub_n(t, u, t, tn + 1); negative = 1; } error += (-exp); tn += (t[tn] != 0); } /* The accumulated arithmetic error */ mag_set_ui_2exp_si(arb_radref(z), error, -wn * FLINT_BITS); /* Truncation error from the Taylor series */ if (used_taylor_series) mag_add_ui_2exp_si(arb_radref(z), arb_radref(z), 1, -r*(2*N+1) + 1); /* Set the midpoint */ inexact = _arf_set_mpn_fixed(arb_midref(z), t, tn, wn, negative, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); TMP_END; } } flint-3.1.3/src/arb/log_base_ui.c000066400000000000000000000122111461254215100165770ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define ldexp __builtin_ldexp # define log __builtin_log #else # include #endif static double _arf_get_mantissa_d(const arf_t x) { mp_srcptr xp; mp_size_t xn; ARF_GET_MPN_READONLY(xp, xn, x); if (xn == 1) return (double) xp[0] * ldexp(1.0, -FLINT_BITS); else return ((double) xp[xn - 1]) * ldexp(1.0, -FLINT_BITS) + ((double) xp[xn - 2]) * ldexp(1.0, -2 * FLINT_BITS); } void arb_log_base_ui(arb_t res, const arb_t x, ulong b, slong prec) { arb_t t; slong xexp, xbits; if (b <= 1) { arb_indeterminate(res); return; } if (arb_is_exact(x) && arf_sgn(arb_midref(x)) > 0) { xbits = arb_bits(x); xexp = ARF_EXP(arb_midref(x)); /* x = 1 */ if (xbits == 1 && ARF_EXP(arb_midref(x)) == 1) { arb_zero(res); return; } /* powers of two */ if ((b & (b - 1)) == 0 && xbits == 1) { fmpz_t e; fmpz_init(e); fmpz_sub_ui(e, ARF_EXPREF(arb_midref(x)), 1); if (b == 2) { arb_set_round_fmpz(res, e, prec); } else { arb_set_fmpz(res, e); arb_div_ui(res, res, FLINT_BIT_COUNT(b) - 1, prec); } fmpz_clear(e); return; } /* check for other exact powers */ if ((b & (b - 1)) != 0 && xbits != 1) { /* exactness is only possible if x is moderate, and an integer */ if (!COEFF_IS_MPZ(xexp) && xbits <= xexp) { ulong b_reduced; int b_exp; /* Write b as (b_reduced)^(1/2^(b_exp)). */ /* More generally, we could look for nth roots, but the result will not be exact when dividing by a non-power-of-two, so that is just a possible optimization at high precision. */ b_reduced = b; b_exp = 0; if (b >= 25 || b == 9) { ulong s, r; s = n_sqrtrem(&r, b_reduced); while (r == 0) { b_reduced = s; b_exp++; s = n_sqrtrem(&r, b_reduced); } } /* x fits a ulong */ if (xexp <= FLINT_BITS) { ulong n, a, hi, v; ARF_GET_TOP_LIMB(v, arb_midref(x)); v >>= (FLINT_BITS - xexp); for (a = b_reduced, n = 1, hi = 0; a <= v && hi == 0; n++) { if (a == v) { arf_set_ui_2exp_si(arb_midref(res), n, -b_exp); mag_zero(arb_radref(res)); arb_set_round(res, res, prec); return; } umul_ppmm(hi, a, a, b_reduced); } } /* general case (if b = 10, first count bits to rule out many non-powers-of-10 -- could perhaps generalize this to other b) */ else if (b_reduced != 10 || (xbits < xexp && xexp < xbits * 2)) { ulong n; double xlog; /* libm.log should be accurate enough since we will certainly have bits(n) << 53. Worst case, we will not get the exact logarithm and fall back to compute an approximate logarithm. */ xlog = _arf_get_mantissa_d(arb_midref(x)); xlog = log(xlog) + xexp * 0.69314718055994530942; xlog = xlog / log(b_reduced); n = (ulong) (xlog + 0.5); if (n >= 2 && fabs(xlog - n) < 0.01) { arb_init(t); arb_ui_pow_ui(t, b_reduced, n, xbits + 10); if (arb_equal(t, x)) { arf_set_ui_2exp_si(arb_midref(res), n, -b_exp); mag_zero(arb_radref(res)); arb_set_round(res, res, prec); arb_clear(t); return; } arb_clear(t); } } } } } /* generic case */ arb_init(t); arb_log(res, x, prec + 3); arb_log_ui(t, b, prec + 3); arb_div(res, res, t, prec); arb_clear(t); } flint-3.1.3/src/arb/log_hypot.c000066400000000000000000000113741461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void arb_log_abs(arb_t res, const arb_t a, slong prec) { if (arb_is_positive(a)) { arb_log(res, a, prec); } else if (arb_is_negative(a)) { arb_neg(res, a); arb_log(res, res, prec); } else { arb_indeterminate(res); } } static int arf_close_to_one(const arf_t z) { mp_limb_t top; if (ARF_EXP(z) == 0) { ARF_GET_TOP_LIMB(top, z); return (top >> (FLINT_BITS - 4)) == 15; } else if (ARF_EXP(z) == 1) { ARF_GET_TOP_LIMB(top, z); return (top >> (FLINT_BITS - 4)) == 8; } return 0; } void arb_log_hypot(arb_t res, const arb_t a, const arb_t b, slong prec) { slong acc; arb_t x; if (arb_is_zero(b)) { arb_log_abs(res, a, prec); return; } if (arb_is_zero(a)) { arb_log_abs(res, b, prec); return; } if (!arb_is_finite(a) || !arb_is_finite(b)) { if (arf_is_nan(arb_midref(a)) || arf_is_nan(arb_midref(b))) { arb_indeterminate(res); } else if ((!arb_is_finite(a) && !arb_contains_zero(a)) || (!arb_is_finite(b) && !arb_contains_zero(b))) { arb_pos_inf(res); } else { arb_indeterminate(res); } return; } /* a close to 1 -- for accurate arb_log1p */ if (mag_cmp_2exp_si(arb_radref(a), -3) < 0 && mag_cmp_2exp_si(arb_radref(b), -3) < 0 && arf_cmpabs_2exp_si(arb_midref(b), -3) < 0 && arf_close_to_one(arb_midref(a))) { arb_t y; arb_init(x); arb_init(y); if (arf_sgn(arb_midref(a)) > 0) { arb_sub_ui(y, a, 1, prec + 8); arb_mul(x, y, y, prec + 8); arb_addmul(x, b, b, prec + 8); arb_mul_2exp_si(y, y, 1); arb_add(x, x, y, prec + 8); } else { arb_add_ui(y, a, 1, prec + 8); arb_mul(x, y, y, prec + 8); arb_addmul(x, b, b, prec + 8); arb_mul_2exp_si(y, y, 1); arb_sub(x, x, y, prec + 8); } arb_log1p(res, x, prec); arb_mul_2exp_si(res, res, -1); arb_clear(x); arb_clear(y); return; } arb_init(x); /* todo: write an arb_sosq function */ /* todo: for very wide input, we could predict that a^2+b^2 will have low accuracy without computing it and go more quickly to the interval case -- however, a first failed attempt to write such code proved that it's actually somewhat complicated to do... */ arb_mul(x, a, a, FLINT_MAX(MAG_BITS, prec) + 8); arb_addmul(x, b, b, FLINT_MAX(MAG_BITS, prec) + 8); acc = arb_rel_accuracy_bits(x); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); if (acc > 10) { arb_log(res, x, prec); arb_mul_2exp_si(res, res, -1); } else { mag_t t, u, v; mag_init(t); mag_init(u); mag_init(v); arb_get_mag_lower(t, a); arb_get_mag_lower(u, b); if (!arb_contains_zero(x)) acc += fmpz_bits(ARF_EXPREF(arb_midref(x))); if (mag_is_zero(t) && mag_is_zero(u)) { arb_indeterminate(res); } else if (acc < 20) { /* t = lower bound for a^2 + b^2 */ mag_mul_lower(t, t, t); mag_mul_lower(u, u, u); mag_add_lower(t, t, u); /* u = upper bound for a^2 + b^2 */ arb_get_mag(u, x); if (mag_cmp_2exp_si(t, 0) >= 0) { mag_log_lower(t, t); mag_log(u, u); arb_set_interval_mag(res, t, u, prec); } else if (mag_cmp_2exp_si(u, 0) <= 0) { mag_neg_log_lower(u, u); mag_neg_log(t, t); arb_set_interval_mag(res, u, t, prec); arb_neg(res, res); } else { mag_neg_log(t, t); mag_log(u, u); arb_set_interval_neg_pos_mag(res, t, u, prec); } arb_mul_2exp_si(res, res, -1); } else { arb_log(res, x, prec); arb_mul_2exp_si(res, res, -1); } mag_clear(t); mag_clear(u); mag_clear(v); } arb_clear(x); } flint-3.1.3/src/arb/log_newton.c000066400000000000000000000066051461254215100165140ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "arb_fmpz_poly.h" static const fmpz log_coeffs[] = { 0, 232792560, -116396280, 77597520, -58198140, 46558512, -38798760, 33256080, -29099070, 25865840, -23279256, 21162960, -19399380, 17907120, -16628040, 15519504, -14549535, 13693680, -12932920, 12252240, -11639628 }; static const ulong log_den = 232792560; void arb_log_newton(arb_t res, const arb_t x, slong prec) { arb_t t, w; slong wp, wp2; mag_t err; slong n, x1mag, extra, ebits; if (arb_is_one(x)) { arb_zero(res); return; } arb_init(t); arb_init(w); mag_init(err); arf_sub_ui(arb_midref(t), arb_midref(x), 1, 8, ARF_RND_DOWN); x1mag = arf_abs_bound_lt_2exp_si(arb_midref(t)); /* quick and accurate calculation near 1 */ if (x1mag < -prec / 16) { n = prec / (-x1mag) + 2; arb_sub_ui(t, x, 1, prec + 10); arb_get_mag(err, t); mag_geom_series(err, err, n); mag_div_ui(err, err, n); _arb_fmpz_poly_evaluate_arb_rectangular(res, log_coeffs, n, t, prec + 10); arb_div_ui(res, res, log_den, prec); arb_add_error_mag(res, err); } /* catch well below ARB_LOG_NEWTON_PREC so that we never hit infinite recursion */ else if (prec <= ARB_LOG_NEWTON_PREC / 2) { arb_log(res, x, prec); } else { if (prec <= 3200) n = 4; else if (prec <= 6000) n = 6; else if (prec <= 300000) n = 7; else if (prec <= 1000000) n = 9; else n = 12; n = FLINT_MAX(n, 2); n = FLINT_MIN(n, 16); extra = 10; ebits = fmpz_bits(ARF_EXPREF(arb_midref(x))); extra += ebits; if (extra > 30) { fmpz_t q; fmpz_init(q); fmpz_set(q, ARF_EXPREF(arb_midref(x))); fmpz_neg(q, q); arb_mul_2exp_fmpz(t, x, q); arb_log_newton(res, t, prec + 5 - ebits); arb_const_log2(t, prec + 5); arb_submul_fmpz(res, t, q, prec); fmpz_clear(q); } else { wp = prec + 10; if (x1mag < 0) wp += (-x1mag); wp2 = wp * (n - 1) / n; arb_log(t, x, wp / n + extra); mag_zero(arb_radref(t)); arb_neg(w, t); arb_exp(w, w, wp); arb_set_round(res, x, wp); arb_mul(w, w, res, wp); arb_sub_ui(w, w, 1, wp2); arb_get_mag(err, w); mag_geom_series(err, err, n); mag_div_ui(err, err, n); _arb_fmpz_poly_evaluate_arb_rectangular(res, log_coeffs, n, w, wp2); arb_div_ui(res, res, log_den, wp2); arb_add_error_mag(res, err); arb_add(res, t, res, prec); } } arb_clear(t); arb_clear(w); mag_clear(err); } void arb_log_arf_newton(arb_t res, const arf_t x, slong prec) { arb_set_arf(res, x); arb_log_newton(res, res, prec); } flint-3.1.3/src/arb/log_precompute_reductions.c000066400000000000000000000050001461254215100216100ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #include "arb.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define log __builtin_log # define pow __builtin_pow #else # include #endif #define TERMINATOR -32768 void _arb_log_precompute_reductions(short * rel, double * eps, arb_srcptr alpha, slong n, slong max_rel, double C) { slong i, j, d, prec, row; arb_t x, y; fmpz_mat_t M; fmpz_lll_t ctx; fmpz * prev; fmpz_mat_init(M, n, n + 1); arb_init(x); arb_init(y); prev = _fmpz_vec_init(n); prec = 100 + n * 32; fmpz_lll_context_init(ctx, 0.75, 0.51, 1, 0); d = 0; for (i = 1; i < max_rel; i++) { prec = log(C) / log(2) * i + 100; fmpz_mat_zero(M); for (j = 0; j < n; j++) { fmpz_one(fmpz_mat_entry(M, j, j)); arb_set_round(x, alpha + j, prec); arb_set_d(y, pow(C, i)); arb_mul(x, x, y, prec); arb_set_d(y, 0.5); arb_mul(x, x, y, prec); arb_floor(x, x, prec); if (!arb_get_unique_fmpz(fmpz_mat_entry(M, j, n), x)) { flint_throw(FLINT_ERROR, "failure\n"); } } fmpz_lll(M, NULL, ctx); row = 0; for (j = 0; j < n; j++) { if (!fmpz_is_zero(fmpz_mat_entry(M, row, j))) { if (fmpz_sgn(fmpz_mat_entry(M, row, 0)) < 0) fmpz_mat_neg(M, M); break; } } if (_fmpz_vec_equal(M->rows[row], prev, n)) continue; if (FLINT_ABS(_fmpz_vec_max_bits(M->rows[row], n)) >= 16) break; _fmpz_vec_set(prev, M->rows[row], n); arb_dot_fmpz(x, NULL, 0, alpha, 1, M->rows[row], 1, n, prec); for (j = 0; j < n; j++) rel[n * d + j] = fmpz_get_si(fmpz_mat_entry(M, row, j)); eps[d] = arf_get_d(arb_midref(x), ARF_RND_NEAR); if (fabs(eps[d]) < 1e-300) break; d++; } rel[d * n] = TERMINATOR; _fmpz_vec_clear(prev, n); fmpz_mat_clear(M); arb_clear(x); arb_clear(y); } flint-3.1.3/src/arb/log_primes.c000066400000000000000000001772771461254215100165170ustar00rootroot00000000000000/* Copyright (C) 2013-2014 Fredrik Johansson Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "ulong_extras.h" #include "arb.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define HAVE_64_BIT (FLINT_BITS == 64) /* one coefficient doesn't fit in 64 bits */ #define L24_FIXME 0 #define L24_FIXME_STR "19182937474703818751" static const ulong log_atanh_4_x[] = {251, 449, 4801, 8749}; static const ulong log_atanh_4_den = 1; static const slong log_atanh_4_c[] = { 144, 54, -38, 62, 228, 86, -60, 98, 334, 126, -88, 144, 404, 152, -106, 174, }; static const ulong log_atanh_8_x[] = {57799, 74359, 87361, 388961, 672281, 1419263, 11819521, 23718421}; static const ulong log_atanh_8_den = 1; static const slong log_atanh_8_c[] = { 17078, 16538, 6790, 24056, 20056, 8490, -2564, 2356, 27068, 26212, 10762, 38128, 31788, 13456, -4064, 3734, 39654, 38400, 15766, 55856, 46568, 19712, -5954, 5470, 47944, 46428, 19062, 67534, 56304, 23834, -7198, 6614, 59080, 57212, 23490, 83220, 69382, 29370, -8870, 8150, 63196, 61198, 25126, 89018, 74216, 31416, -9488, 8718, 69806, 67598, 27754, 98328, 81978, 34702, -10480, 9630, 72546, 70252, 28844, 102188, 85196, 36064, -10892, 10008, }; #if HAVE_64_BIT static const ulong log_atanh_12_x[] = {36171409, 42772001, 55989361, 100962049, 143687501, 287080366, 362074049, 617831551, 740512499, UWORD(3222617399), UWORD(6926399999), UWORD(9447152318)}; static const ulong log_atanh_12_den = 1; static const slong log_atanh_12_c[] = { 17325186, 3191278, 1683636, -1195752, 3410458, 18802224, 7208106, 6805862, -482400, -837914, 7774420, 9161220, 27459770, 5058056, 2668500, -1895222, 5405448, 29800820, 11424578, 10787036, -764586, -1328062, 12322164, 14520190, 40227836, 7409918, 3909282, -2776450, 7918838, 43657412, 16736704, 15802722, -1120098, -1945576, 18051644, 21271694, 48637946, 8959050, 4726564, -3356900, 9574366, 52784516, 20235712, 19106470, -1354268, -2352322, 21825556, 25718796, 59935296, 11040008, 5824424, -4136622, 11798246, 65045008, 24935950, 23544414, -1668830, -2898706, 26895074, 31692614, 64110806, 11809132, 6230194, -4424808, 12620194, 69576496, 26673162, 25184682, -1785092, -3100650, 28768772, 33900542, 70816054, 13044230, 6881800, -4887592, 13940120, 76853392, 29462866, 27818708, -1971792, -3424942, 31777652, 37446146, 73596134, 13556318, 7151964, -5079468, 14487378, 79870484, 30619512, 28910808, -2049200, -3559398, 33025172, 38916198, 78371552, 14435944, 7616032, -5409058, 15427418, 85053024, 32606314, 30786738, -2182166, -3790356, 35168070, 41441346, 84165424, 15503168, 8179072, -5808940, 16567940, 91340846, 35016842, 33062748, -2343490, -4070570, 37767984, 44505032, 85832372, 15810218, 8341064, -5923990, 16896078, 93149908, 35710372, 33717576, -2389904, -4151190, 38516002, 45386482, 90254748, 16624814, 8770824, -6229214, 17766622, 97949308, 37550292, 35454820, -2513040, -4365074, 40500478, 47724948, }; #endif #if HAVE_64_BIT static const ulong log_atanh_13_x[] = {51744295, 170918749, 265326335, 287080366, 362074049, 587270881, 831409151, WORD(2470954914), UWORD(3222617399), UWORD(6926399999), UWORD(9447152318), UWORD(90211378321), UWORD(127855050751)}; static const slong log_atanh_13_den = 1; static const slong log_atanh_13_c[] = { 3191278, 35138256, 17325186, 62225852, 26216928, 22419280, 9733920, 31220668, 40902078, -34447972, 9161220, 6323462, 19491222, 5058056, 55692818, 27459770, 98625642, 41552848, 35533718, 15427898, 49483588, 64828260, -54598744, 14520190, 10022450, 30892856, 7409918, 81588504, 40227836, 144483954, 60873822, 52055956, 22601462, 72492146, 94971684, -79985714, 21271694, 14682624, 45257216, 8959050, 98645556, 48637946, 174690052, 73600222, 62938876, 27326568, 87647496, 114826650, -96707684, 25718796, 17752202, 54718778, 11040008, 121558394, 59935296, 215266080, 90695670, 77557966, 33673830, 108005766, 141497942, -119170404, 31692614, 21875584, 67428550, 11809132, 130026998, 64110806, 230263014, 97014162, 82961194, 36019784, 115530200, 151355674, -127472644, 33900542, 23399590, 72126092, 13044230, 143626316, 70816054, 254345858, 107160720, 91637974, 39787036, 127613320, 167185724, -140804806, 37446146, 25846916, 79669646, 13556318, 149264764, 73596134, 264330908, 111367610, 95235476, 41348986, 132623134, 173749062, -146332488, 38916198, 26861608, 82797298, 14435944, 158950078, 78371552, 281482496, 118593898, 101415002, 44031990, 141228626, 185023084, -155827536, 41441346, 28604572, 88169750, 15503168, 170700980, 84165424, 302292006, 127361338, 108912436, 47287198, 151669412, 198701518, -167347594, 44505032, 30719258, 94687986, 15810218, 174081818, 85832372, 308279086, 129883808, 111069514, 48223750, 154673318, 202636924, -170662016, 45386482, 31327672, 96563340, 16624814, 183051106, 90254748, 324162674, 136575864, 116792194, 50708402, 162642614, 213077468, -179455104, 47724948, 32941780, 101538612, 17097438, 188255034, 92820584, 333378238, 140458556, 120112458, 52149982, 167266352, 219135010, -184556802, 49081712, 33878276, 104425236, }; #else /* Arndt formula with 32-bit x */ static const ulong log_atanh_13_x[] = { 51744295, 170918749, 265326335, 287080366, 362074049, 587270881, 617831551, 740512499, 831409151, 1752438401, UWORD(2151548801), UWORD(2470954914), UWORD(3222617399) }; static const slong log_atanh_13_den = 1; static const slong log_atanh_13_c[] = { 3191278, 35138256, 17325186, 62225852, 26216928, 22419280, 25814684, -19491222, 3410458, 24117970, -9161220, -9550766, 25945328, 5058056, 55692818, 27459770, 98625642, 41552848, 35533718, 40915306, -30892856, 5405448, 38226078, -14520190, -15137606, 41122372, 7409918, 81588504, 40227836, 144483954, 60873822, 52055956, 59939840, -45257216, 7918838, 56000192, -21271694, -22176192, 60243186, 8959050, 98645556, 48637946, 174690052, 73600222, 62938876, 72470980, -54718778, 9574366, 67707702, -25718796, -26812390, 72837744, 11040008, 121558394, 59935296, 215266080, 90695670, 77557966, 89304134, -67428550, 11798246, 83434468, -31692614, -33040222, 89756088, 11809132, 130026998, 64110806, 230263014, 97014162, 82961194, 95525682, -72126092, 12620194, 89247094, -33900542, -35342034, 96009122, 13044230, 143626316, 70816054, 254345858, 107160720, 91637974, 105516562, -79669646, 13940120, 98581306, -37446146, -39038402, 106050564, 13556318, 149264764, 73596134, 264330908, 111367610, 95235476, 109658906, -82797298, 14487378, 102451388, -38916198, -40570962, 110213872, 14435944, 158950078, 78371552, 281482496, 118593898, 101415002, 116774322, -88169750, 15427418, 109099132, -41441346, -43203482, 117365298, 15503168, 170700980, 84165424, 302292006, 127361338, 108912436, 125407244, -94687986, 16567940, 117164640, -44505032, -46397440, 126041910, 15810218, 174081818, 85832372, 308279086, 129883808, 111069514, 127891012, -96563340, 16896078, 119485158, -45386482, -47316370, 128538248, 16624814, 183051106, 90254748, 324162674, 136575864, 116792194, 134480392, -101538612, 17766622, 125641440, -47724948, -49754270, 135160976, 17097438, 188255034, 92820584, 333378238, 140458556, 120112458, 138303512, -104425236, 18271706, 129213278, -49081712, -51168726, 139003444, }; #endif #if HAVE_64_BIT static const ulong log_atanh_16_x[] = {UWORD(9943658495), UWORD(15913962107), UWORD(19030755899), UWORD(22429958849), UWORD(22623739319), UWORD(36974504449), UWORD(90211378321), UWORD(123679505951), UWORD(127855050751), UWORD(187753824257), UWORD(384918250001), UWORD(569165414399), UWORD(842277599279), UWORD(1068652740673), UWORD(2218993446251), UWORD(2907159732049)}; static const ulong log_atanh_16_den = 1; static const slong log_atanh_16_c[] = { WORD(2795845166), WORD(4115492742), WORD(653556516), WORD(2293232066), WORD(974581744), WORD(-2713448948), WORD(894308352), WORD(387970172), WORD(2837123522), WORD(1960851594), WORD(-546800620), WORD(-845945652), WORD(-60363442), WORD(2786163756), WORD(477501928), WORD(4560908494), WORD(4431309746), WORD(6522901668), WORD(1035862570), WORD(3634686830), WORD(1544675518), WORD(-4300714830), WORD(1417445202), WORD(614918174), WORD(4496734392), WORD(3107876246), WORD(-866658478), WORD(-1340792136), WORD(-95673792), WORD(4415965074), WORD(756822650), WORD(7228868932), WORD(6491751440), WORD(9555878222), WORD(1517511236), WORD(5324719962), WORD(2262908732), WORD(-6300433346), WORD(2076519688), WORD(900838842), WORD(6587596814), WORD(4552956406), WORD(-1269631722), WORD(-1964224976), WORD(-140159572), WORD(6469271902), WORD(1108725142), WORD(10590101570), WORD(7848929688), WORD(11553648806), WORD(1834765102), WORD(6437916328), WORD(2735996856), WORD(-7617614260), WORD(2510640954), WORD(1089169972), WORD(7964812684), WORD(5504806374), WORD(-1535063412), WORD(-2374869690), WORD(-169461606), WORD(7821750534), WORD(1340517388), WORD(12804088910), WORD(9672035168), WORD(14237265718), WORD(2260934076), WORD(7933279518), WORD(3371498900), WORD(-9386991086), WORD(3093798590), WORD(1342156280), WORD(9814834818), WORD(6783432004), WORD(-1891619354), WORD(-2926491136), WORD(-208823200), WORD(9638542992), WORD(1651885268), WORD(15778151054), WORD(10345856498), WORD(15229132802), WORD(2418446490), WORD(8485967020), WORD(3606380994), WORD(-10040954260), WORD(3309334146), WORD(1435660234), WORD(10498604566), WORD(7256013120), WORD(-2023402732), WORD(-3130370890), WORD(-223371278), WORD(10310031024), WORD(1766967100), WORD(16877366942), WORD(11427913226), WORD(16821923656), WORD(2671387974), WORD(9373500856), WORD(3983566664), WORD(-11091121746), WORD(3655452158), WORD(1585813662), WORD(11596636972), WORD(8014908028), WORD(-2235027216), WORD(-3457771418), WORD(-246733326), WORD(11388340822), WORD(1951771388), WORD(18642543992), WORD(11876547604), WORD(17482314850), WORD(2776260706), WORD(9741483588), WORD(4139952604), WORD(-11526534442), WORD(3798957054), WORD(1648069168), WORD(12051895068), WORD(8329555436), WORD(-2322769398), WORD(-3593515810), WORD(-256419526), WORD(11835421676), WORD(2028393578), WORD(19374408678), WORD(12647178828), WORD(18616686398), WORD(2956403392), WORD(10373577330), WORD(4408580900), WORD(-12274454430), WORD(4045459238), WORD(1755007110), WORD(12833904028), WORD(8870033672), WORD(-2473486482), WORD(-3826687568), WORD(-273057770), WORD(12603384370), WORD(2160009556), WORD(20631552148), WORD(13582162682), WORD(19992985526), WORD(3174965134), WORD(11140477794), WORD(4734499590), WORD(-13181883420), WORD(4344532978), WORD(1884751722), WORD(13782692150), WORD(9525779778), WORD(-2656347020), WORD(-4109587900), WORD(-293244454), WORD(13535130576), WORD(2319695292), WORD(22156806784), WORD(13851165806), WORD(20388958958), WORD(3237847280), WORD(11361121840), WORD(4828269280), WORD(-13442958766), WORD(4430579138), WORD(1922080394), WORD(14055666884), WORD(9714443732), WORD(-2708957614), WORD(-4190980828), WORD(-299052342), WORD(13803202200), WORD(2365638290), WORD(22595636032), WORD(14564825010), WORD(21439467516), WORD(3404672192), WORD(11946485504), WORD(5077038146), WORD(-14135585754), WORD(4658857654), WORD(2021112518), WORD(14779862680), WORD(10214964936), WORD(-2848532330), WORD(-4406914424), WORD(-314460536), WORD(14514390156), WORD(2487524026), WORD(23759840104), WORD(14978885874), WORD(22048966390), WORD(3501463022), WORD(12286110052), WORD(5221372376), WORD(-14537443850), WORD(4791303504), WORD(2078570372), WORD(15200036812), WORD(10505364388), WORD(-2929512758), WORD(-4532197824), WORD(-323400280), WORD(14927017216), WORD(2558241412), WORD(24435304444), WORD(15170996084), WORD(22331753214), WORD(3546370688), WORD(12443684334), WORD(5288338568), WORD(-14723892390), WORD(4852753890), WORD(2105228870), WORD(15394983372), WORD(10640099894), WORD(-2967084932), WORD(-4590325076), WORD(-327548018), WORD(15118462190), WORD(2591051882), WORD(24748697010), WORD(15529770390), WORD(22859870104), WORD(3630237738), WORD(12737961268), WORD(5413400890), WORD(-15072093276), WORD(4967515202), WORD(2155014792), WORD(15759054686), WORD(10891724404), WORD(-3037252628), WORD(-4698880288), WORD(-335294102), WORD(15475994138), WORD(2652326886), WORD(25333971474), WORD(16014378714), WORD(23573215058), WORD(3743519736), WORD(13135450858), WORD(5582326706), WORD(-15542419732), WORD(5122527102), WORD(2222262284), WORD(16250817854), WORD(11231601954), WORD(-3132030456), WORD(-4845509404), WORD(-345756994), WORD(15958924368), WORD(2735093060), WORD(26124521054), }; static const ulong log_atanh_20_x[] = {UWORD(932784765626), UWORD(1986251708497), UWORD(2200009162625), UWORD(2218993446251), UWORD(2907159732049), UWORD(5175027061249), UWORD(7233275252995), UWORD(8152552404881), UWORD(8949772845287), UWORD(9164582675249), UWORD(12066279000049), UWORD(13055714577751), UWORD(22518692773919), UWORD(25640240468751), UWORD(31041668486401), UWORD(41257182408961), UWORD(63774701665793), UWORD(115445619421397), UWORD(121336489966251), UWORD(238178082107393)}; static const ulong log_atanh_20_den = 1; static const slong log_atanh_20_c[] = { WORD(-116089335710), WORD(-440487517368), WORD(804976818014), WORD(-442021938612), WORD(2027028904414), WORD(-2259886314980), WORD(1755029607116), WORD(2232338696382), WORD(231770587740), WORD(419733644928), WORD(-445576594600), WORD(820684665848), WORD(282573414662), WORD(-955021371140), WORD(582451140742), WORD(1373640195020), WORD(-1386573872206), WORD(-391661105906), WORD(-546462355792), WORD(72583300802), WORD(-183997243834), WORD(-698156197064), WORD(1275858070502), WORD(-700588197196), WORD(3212764801374), WORD(-3581835065136), WORD(2781656114934), WORD(3538173122674), WORD(367347690338), WORD(665262087502), WORD(-706222193640), WORD(1300754420286), WORD(447868265940), WORD(-1513673060644), WORD(923163216578), WORD(2177168198590), WORD(-2197667591926), WORD(-620768165852), WORD(-866122341986), WORD(115041809950), WORD(-269551090102), WORD(-1022780342024), WORD(1869098289480), WORD(-1026343157820), WORD(4706615362308), WORD(-5247293526004), WORD(4075052552122), WORD(5183329936434), WORD(538154639242), WORD(974591342528), WORD(-1034596813426), WORD(1905570782676), WORD(656115150372), WORD(-2217490952868), WORD(1352409667588), WORD(3189493761084), WORD(-3219524829512), WORD(-909408925478), WORD(-1268846296712), WORD(168533205352), WORD(-325903968004), WORD(-1236604799988), WORD(2259855632194), WORD(-1240912465020), WORD(5690589571960), WORD(-6344302969650), WORD(4926991005894), WORD(6266967026988), WORD(650662300280), WORD(1178341314042), WORD(-1250891646004), WORD(2303953136126), WORD(793283866494), WORD(-2681083946940), WORD(1635147076820), WORD(3856295562626), WORD(-3892604984934), WORD(-1099531733444), WORD(-1534113784252), WORD(203767086766), WORD(-401603118542), WORD(-1523836445198), WORD(2784762256508), WORD(-1529144670566), WORD(7012367883822), WORD(-7817922172568), WORD(6071404914502), WORD(7722623069772), WORD(801794499498), WORD(1452039842670), WORD(-1541441759884), WORD(2839102481966), WORD(977543405268), WORD(-3303831127796), WORD(2014949892594), WORD(4752014323284), WORD(-4796757495086), WORD(-1354924813562), WORD(-1890449152022), WORD(251096965780), WORD(-429581588714), WORD(-1629997504614), WORD(2978768189562), WORD(-1635675537930), WORD(7500898267714), WORD(-8362573078436), WORD(6494381264686), WORD(8260634776436), WORD(857653088370), WORD(1553199050732), WORD(-1648829328132), WORD(3036894133574), WORD(1045645886906), WORD(-3533999013440), WORD(2155325335078), WORD(5083072736088), WORD(-5130933028848), WORD(-1449318312346), WORD(-2022151005842), WORD(268590129162), WORD(-474510845980), WORD(-1800476359276), WORD(3290312831700), WORD(-1806748249094), WORD(8285405324932), WORD(-9237201337930), WORD(7173618304380), WORD(9124601470546), WORD(947353665082), WORD(1715645676866), WORD(-1821277773358), WORD(3354518076038), WORD(1155008332356), WORD(-3903614367134), WORD(2380747394626), WORD(5614703254392), WORD(-5667569179290), WORD(-1600900216754), WORD(-2233644573442), WORD(296681544924), WORD(-493139083180), WORD(-1871159044356), WORD(3419483172926), WORD(-1877677154576), WORD(8610671853606), WORD(-9599833254658), WORD(7455238554976), WORD(9482812967686), WORD(984544656468), WORD(1782998098608), WORD(-1892777075548), WORD(3486208971918), WORD(1200351382710), WORD(-4056861558392), WORD(2474210225994), WORD(5835123977998), WORD(-5890065301166), WORD(-1663747987724), WORD(-2321332476230), WORD(308328600494), WORD(-525137302522), WORD(-1992572575684), WORD(3641362509476), WORD(-1999513625248), WORD(9169390835836), WORD(-10222735759458), WORD(7938985162504), WORD(10098122399988), WORD(1048428613234), WORD(1898691147874), WORD(-2015593331842), WORD(3712417932350), WORD(1278238348358), WORD(-4320098341710), WORD(2634753821522), WORD(6213746527504), WORD(-6272252817574), WORD(-1771703278344), WORD(-2471956323078), WORD(328335058154), WORD(-563959786616), WORD(-2139879987964), WORD(3910562083430), WORD(-2147334177206), WORD(9847267894216), WORD(-10978484769320), WORD(8525900477254), WORD(10844658961710), WORD(1125937110470), WORD(2039058070076), WORD(-2164602628440), WORD(3986870509682), WORD(1372736278156), WORD(-4639475670938), WORD(2829536572314), WORD(6673117961550), WORD(-6735949519516), WORD(-1902682209022), WORD(-2654703738990), WORD(352608295860), WORD(-575129358650), WORD(-2182261633316), WORD(3988013181752), WORD(-2189863457382), WORD(10042299119296), WORD(-11195920443568), WORD(8694761204194), WORD(11059444133150), WORD(1148236990638), WORD(2079442875048), WORD(-2207473920962), WORD(4065832943536), WORD(1399924168332), WORD(-4731363353242), WORD(2885577292444), WORD(6805283185968), WORD(-6869359161762), WORD(-1940366005802), WORD(-2707281786830), WORD(359591921030), WORD(-604761980628), WORD(-2294699179870), WORD(4193489193856), WORD(-2302692675784), WORD(10559712548326), WORD(-11772772369510), WORD(9142744893568), WORD(11629264335090), WORD(1207398068356), WORD(2186582849238), WORD(-2321210490384), WORD(4275318494622), WORD(1472053026048), WORD(-4975139296132), WORD(3034252055452), WORD(7155914537110), WORD(-7223291925256), WORD(-2040340266348), WORD(-2846770158570), WORD(378119320652), WORD(-621954653248), WORD(-2359934781684), WORD(4312705165022), WORD(-2368155523296), WORD(10859912770262), WORD(-12107458457030), WORD(9402662389768), WORD(11959870657788), WORD(1241722976958), WORD(2248744830790), WORD(-2387199777610), WORD(4396860776674), WORD(1513901764174), WORD(-5116576661404), WORD(3120512276674), WORD(7359348780454), WORD(-7428641628588), WORD(-2098344743078), WORD(-2927700489722), WORD(388868808714), WORD(-629931470760), WORD(-2390201890380), WORD(4368017335942), WORD(-2398528066296), WORD(10999195500784), WORD(-12262741460610), WORD(9523255300552), WORD(12113260788736), WORD(1257648571430), WORD(2277585883836), WORD(-2417816570798), WORD(4453252277016), WORD(1533318160596), WORD(-5182198806204), WORD(3160534096344), WORD(7453735375880), WORD(-7523916932542), WORD(-2125256854766), WORD(-2965249421006), WORD(393856206922), WORD(-644828529934), WORD(-2446727053276), WORD(4471315259200), WORD(-2455250132412), WORD(11259312154488), WORD(-12552739331248), WORD(9748467890052), WORD(12399723636094), WORD(1287390322808), WORD(2331447824792), WORD(-2474994784934), WORD(4558565895664), WORD(1569579138862), WORD(-5304751061248), WORD(3235276613012), WORD(7630006513476), WORD(-7701847772584), WORD(-2175516412502), WORD(-3035373709344), WORD(403170393454), WORD(-664950480570), WORD(-2523077460712), WORD(4610843181352), WORD(-2531866503542), WORD(11610660323584), WORD(-12944449048562), WORD(10052669984964), WORD(12786658480520), WORD(1327563490282), WORD(2404200930252), WORD(-2552227290284), WORD(4700816484258), WORD(1618558041758), WORD(-5470286446298), WORD(3336233802840), WORD(7868101770266), WORD(-7942184844372), WORD(-2243403659776), WORD(-3130092905390), WORD(415751373324), WORD(-682912123820), WORD(-2591230832376), WORD(4735391283388), WORD(-2600257284842), WORD(11924287495408), WORD(-13294104523166), WORD(10324212719726), WORD(13132051716094), WORD(1363423637016), WORD(2469143208920), WORD(-2621168057182), WORD(4827794945270), WORD(1662278533696), WORD(-5618049830928), WORD(3426352154678), WORD(8080634945560), WORD(-8156719151760), WORD(-2304002482364), WORD(-3214642979038), WORD(426981649964), WORD(-688495357788), WORD(-2612415765984), WORD(4774106070468), WORD(-2621516015348), WORD(12021776007726), WORD(-13402792146898), WORD(10408619619450), WORD(13239414456718), WORD(1374570478458), WORD(2489329999806), WORD(-2642597746338), WORD(4867265190110), WORD(1675868700938), WORD(-5663980903990), WORD(3454364727704), WORD(8146699192982), WORD(-8223405435180), WORD(-2322839144468), WORD(-3240924697068), WORD(430472492150), WORD(-704208264478), WORD(-2672036567638), WORD(4883061174324), WORD(-2681344503760), WORD(12296138125812), WORD(-13708671946964), WORD(10646166128660), WORD(13541565635564), WORD(1405941056956), WORD(2546141726370), WORD(-2702907364024), WORD(4978346380276), WORD(1714115536192), WORD(-5793244816128), WORD(3533200568824), WORD(8332623938590), WORD(-8411080777960), WORD(-2375851200860), WORD(-3314889389462), WORD(440296776404), WORD(-713920057888), WORD(-2708886841112), WORD(4950403867850), WORD(-2718323143738), WORD(12465715166074), WORD(-13897729355958), WORD(10792988271008), WORD(13728318467836), WORD(1425330504340), WORD(2581255773856), WORD(-2740183379160), WORD(5047003159822), WORD(1737755042866), WORD(-5873139926234), WORD(3581927225030), WORD(8447539832562), WORD(-8527078676580), WORD(-2408616757868), WORD(-3360605298450), WORD(446368945032), }; static const ulong log_atanh_24_x[] = {UWORD(134543112911873), UWORD(148569359956291), UWORD(166019820559361), UWORD(201842423186689), UWORD(206315395261249), UWORD(211089142289024), UWORD(217172824950401), UWORD(238178082107393), UWORD(259476225058051), UWORD(330190746672799), UWORD(386624124661501), UWORD(473599589105798), UWORD(478877529936961), UWORD(1796745215731101), UWORD(1814660314218751), UWORD(2767427997467797), UWORD(2838712971108351), UWORD(4573663454608289), UWORD(9747977591754401), UWORD(11305332448031249), UWORD(17431549081705001), UWORD(34903240221563713), UWORD(332110803172167361), L24_FIXME}; static const ulong log_atanh_24_den = 2; static const slong log_atanh_24_c[] = { WORD(95300949339891), WORD(8383110436820), WORD(-33446555503183), WORD(-57342856225640), WORD(52380491656263), WORD(102208933748031), WORD(6896245322375), WORD(38607613905573), WORD(-85720402524046), WORD(25043219434553), WORD(131214305964926), WORD(114563664023695), WORD(-76722528792182), WORD(-31877386468039), WORD(-22332023559694), WORD(3666995585797), WORD(90133674519724), WORD(45155648723502), WORD(-3541965146654), WORD(-61019828808695), WORD(35149960568702), WORD(-16630104641178), WORD(-24161266171881), WORD(-23606318798422), WORD(151048430986854), WORD(13286915681764), WORD(-53011536250834), WORD(-90886276801884), WORD(83021115044514), WORD(161997327229322), WORD(10930290231738), WORD(61191620282654), WORD(-135863623547336), WORD(39692563701098), WORD(207969754512560), WORD(181579111422774), WORD(-121602331096108), WORD(-50524462172838), WORD(-35395419907336), WORD(5812050493798), WORD(142858494165968), WORD(71570009922488), WORD(-5613881936308), WORD(-96714140462206), WORD(55711369403220), WORD(-26358092239336), WORD(-38294700852374), WORD(-37415130075568), WORD(221281951741730), WORD(19464979645796), WORD(-77660496900050), WORD(-133145988911400), WORD(121623735200690), WORD(237321794818034), WORD(16012585763258), WORD(89644103403914), WORD(-199036610925636), WORD(58148554791518), WORD(304670183471108), WORD(266008590149854), WORD(-178144195113372), WORD(-74016999231722), WORD(-51853352918940), WORD(8514500074490), WORD(209283911162780), WORD(104848169413964), WORD(-8224188385128), WORD(-141683654856126), WORD(81615680978652), WORD(-38613907187268), WORD(-56100722732542), WORD(-54812174834924), WORD(267543589206106), WORD(23534366346960), WORD(-93896352217734), WORD(-160981749669892), WORD(147050631071006), WORD(286936753235794), WORD(19360208249486), WORD(108385274926710), WORD(-240647593946640), WORD(70305205343762), WORD(368365127695008), WORD(321620866085874), WORD(-215387368837440), WORD(-89491137803382), WORD(-62693916259812), WORD(10294558106950), WORD(253037214806084), WORD(126767932702628), WORD(-9943553288216), WORD(-171304316749202), WORD(98678414812676), WORD(-46686606118744), WORD(-67829249510774), WORD(-66271315270412), WORD(329687117432571), WORD(29000797307664), WORD(-115706071642219), WORD(-198373689929952), WORD(181206729035443), WORD(353584817115143), WORD(23857089118103), WORD(133560400265081), WORD(-296543870854002), WORD(86635305144365), WORD(453926918872614), WORD(396325161670511), WORD(-265416341965486), WORD(-110277638667055), WORD(-77256108410558), WORD(12685720474909), WORD(311811283537496), WORD(156212878954162), WORD(-12253186220446), WORD(-211093925144635), WORD(121598884985222), WORD(-57530709816938), WORD(-83584248141317), WORD(-81664445650894), WORD(352655418113885), WORD(31021194821972), WORD(-123766962418989), WORD(-212193782729012), WORD(193830851780593), WORD(378217997990065), WORD(25519140096961), WORD(142865147918839), WORD(-317203182155022), WORD(92670923865743), WORD(485550629380930), WORD(423935932609053), WORD(-283907092818814), WORD(-117960346996865), WORD(-82638306966754), WORD(13569496111931), WORD(333534229134788), WORD(167095756034874), WORD(-13106828508950), WORD(-225800198117865), WORD(130070310179518), WORD(-61538699731058), WORD(-89407308983007), WORD(-87353759680782), WORD(389539089162686), WORD(34265652404600), WORD(-136711552787078), WORD(-234386794033464), WORD(214103313251398), WORD(417775218738894), WORD(28188146499354), WORD(157807187228370), WORD(-350378960054060), WORD(102363228864014), WORD(536333599872088), WORD(468274719654342), WORD(-313600485524804), WORD(-130297632664286), WORD(-91281316470176), WORD(14988708195974), WORD(368418045344724), WORD(184572036229868), WORD(-14477650921952), WORD(-249416282834998), WORD(143674157695984), WORD(-67974934766920), WORD(-98758277675122), WORD(-96489950907260), WORD(404831524758217), WORD(35610845472804), WORD(-142078543351889), WORD(-243588296660336), WORD(222508531674341), WORD(434176141787993), WORD(29294750244373), WORD(164002345337891), WORD(-364134056345354), WORD(106381780861243), WORD(557388860465814), WORD(486658140447161), WORD(-325911740957278), WORD(-135412827034257), WORD(-94864817310094), WORD(15577131440583), WORD(382881315880104), WORD(191817922599958), WORD(-15046011198130), WORD(-259207809662073), WORD(149314484596246), WORD(-70643479056706), WORD(-102635307331167), WORD(-100277931114938), WORD(431099748810048), WORD(37921519445424), WORD(-151297566035348), WORD(-259393962873952), WORD(236946399295832), WORD(462348444271744), WORD(31195592979932), WORD(174643933477388), WORD(-387761551715668), WORD(113284554691332), WORD(593556042553364), WORD(518235832124084), WORD(-347059112416804), WORD(-144199332685348), WORD(-101020292176400), WORD(16587881724940), WORD(407725261017048), WORD(204264374666708), WORD(-16022298787084), WORD(-276026976164124), WORD(159003024385484), WORD(-75227308680080), WORD(-109294984465288), WORD(-106784645639096), WORD(462970200710807), WORD(40724991182128), WORD(-162482730986943), WORD(-278570505750492), WORD(254463432981563), WORD(496529057680187), WORD(33501828713835), WORD(187555054620497), WORD(-416428086356502), WORD(121659484069869), WORD(637436604666466), WORD(556548102559291), WORD(-372716586770550), WORD(-154859737636071), WORD(-108488546035734), WORD(17814194865017), WORD(437867677837832), WORD(219365283321430), WORD(-17206799367850), WORD(-296433168678579), WORD(170757840422238), WORD(-80788732293826), WORD(-117374971881217), WORD(-114679048087658), WORD(472139611596056), WORD(41531574795660), WORD(-165700801869020), WORD(-284087766740112), WORD(259503238499708), WORD(506363122463072), WORD(34165353131632), WORD(191269698363832), WORD(-424675701909508), WORD(124069025322872), WORD(650061430481412), WORD(567570881610592), WORD(-380098469065780), WORD(-157926830424736), WORD(-110637228722908), WORD(18167016001360), WORD(446539917747228), WORD(223709948299100), WORD(-17547590661072), WORD(-302304210744476), WORD(174139804959708), WORD(-82388803054672), WORD(-119699655723008), WORD(-116950337492960), WORD(496465851286329), WORD(43671422879532), WORD(-174238271134753), WORD(-298724935359436), WORD(272873728552017), WORD(532452673911025), WORD(35925668404849), WORD(201124564199291), WORD(-446556439431958), WORD(130461483769519), WORD(683554807827650), WORD(596814065127021), WORD(-399682435835998), WORD(-166063758223381), WORD(-116337635294350), WORD(19103042496175), WORD(469547174083276), WORD(235236246219806), WORD(-18451702254178), WORD(-317879952557557), WORD(183112080386350), WORD(-86633754593746), WORD(-125866989376963), WORD(-122976016914550), WORD(510579792177940), WORD(44912950125720), WORD(-179191660483648), WORD(-307217334322204), WORD(280631208075892), WORD(547589677891640), WORD(36946992951228), WORD(206842299273324), WORD(-459251514379372), WORD(134170350483680), WORD(702987467956960), WORD(613780787846540), WORD(-411044937929924), WORD(-170784755773828), WORD(-119644977589416), WORD(19646119551612), WORD(482895848606740), WORD(241923736338428), WORD(-18976262471744), WORD(-326916906155476), WORD(188317741707096), WORD(-89096650457352), WORD(-129445240013272), WORD(-126472080600140), WORD(517128182492702), WORD(45488976698092), WORD(-181489865293110), WORD(-311157519671140), WORD(284230415708346), WORD(554612734812622), WORD(37420852932582), WORD(209495134598958), WORD(-465141598975108), WORD(135891138961986), WORD(712003563770176), WORD(621652772261310), WORD(-416316753876636), WORD(-172975138663538), WORD(-121179472343144), WORD(19898088902858), WORD(489089181258168), WORD(245026505144048), WORD(-19219640637672), WORD(-331109746402578), WORD(190732992163116), WORD(-90239350681432), WORD(-131105427057454), WORD(-128094135684140), WORD(529357590757654), WORD(46564731774744), WORD(-185781864324998), WORD(-318515989914292), WORD(290952094999270), WORD(567728603938670), WORD(38305807386098), WORD(214449421789770), WORD(-476141592221384), WORD(139104787481286), WORD(728841521093396), WORD(636354050993358), WORD(-426162103101572), WORD(-177065775495990), WORD(-124045209100076), WORD(20368652800018), WORD(500655503647996), WORD(250821062989836), WORD(-19674160116636), WORD(-338940060832054), WORD(195243579111820), WORD(-92373393842120), WORD(-134205899720746), WORD(-131123395226864), WORD(545876257063253), WORD(48017789743924), WORD(-191579209401365), WORD(-328455319097920), WORD(300031289577985), WORD(585444642254441), WORD(39501144641717), WORD(221141341391611), WORD(-490999646990874), WORD(143445568847291), WORD(751585107067814), WORD(656211554511029), WORD(-439460541994554), WORD(-182591133988297), WORD(-127916054539358), WORD(21004259022679), WORD(516278517926468), WORD(258647963962418), WORD(-20288094612870), WORD(-349516725567269), WORD(201336178118558), WORD(-95255916535730), WORD(-138393810714063), WORD(-135215116302422), WORD(560621467231895), WORD(49314846343192), WORD(-196754147255895), WORD(-337327554606316), WORD(308135735163871), WORD(601258673695539), WORD(40568149612363), WORD(227114811594065), WORD(-504262530096578), WORD(147320320740317), WORD(771886924961410), WORD(673937141878415), WORD(-451331250728794), WORD(-187523285938031), WORD(-131371323171618), WORD(21571626094829), WORD(530224233926896), WORD(265634563102734), WORD(-20836116651046), WORD(-358957871814719), WORD(206774671224818), WORD(-97828969477586), WORD(-142132104509797), WORD(-138867547200558), WORD(565204898555282), WORD(49718026072564), WORD(-198362735535598), WORD(-340085418459904), WORD(310654937625698), WORD(606174339611938), WORD(40899819622402), WORD(228971617303994), WORD(-508385191840280), WORD(148524756553286), WORD(778197583608588), WORD(679446999753338), WORD(-455021166140040), WORD(-189056406149922), WORD(-132445365948808), WORD(21747987637362), WORD(534559148845864), WORD(267806291886348), WORD(-21006464943608), WORD(-361892577047422), WORD(208465183558664), WORD(-98628782523012), WORD(-143294123408370), WORD(-140002876300216), WORD(578104058631076), WORD(50852695603208), WORD(-202889788795904), WORD(-347846880300328), WORD(317744734226920), WORD(620008508177144), WORD(41833239204804), WORD(234197229381964), WORD(-519987607152804), WORD(151914402706204), WORD(795957683047256), WORD(694953403953372), WORD(-465405702570840), WORD(-193371069473816), WORD(-135468046716508), WORD(22244322284460), WORD(546758908700336), WORD(273918192609744), WORD(-21485876489096), WORD(-370151723940008), WORD(213222795850820), WORD(-100879698000032), WORD(-146564395553020), WORD(-143198035289608), WORD(586076738689057), WORD(51554009261324), WORD(-205687858363053), WORD(-352644064897800), WORD(322126777681341), WORD(628559095904597), WORD(42410164806673), WORD(237427062406747), WORD(-527158798505034), WORD(154009466580767), WORD(806934800145610), WORD(704537562829621), WORD(-471824150440838), WORD(-196037865609161), WORD(-137336297558938), WORD(22551095540991), WORD(554299305248044), WORD(277695820666722), WORD(-21782189958022), WORD(-375256516448941), WORD(216163368758078), WORD(-102270938114146), WORD(-148585677044111), WORD(-145172891032706), WORD(589896156708638), WORD(51889982861632), WORD(-207028310663546), WORD(-354942219741792), WORD(324226053660146), WORD(632655368250502), WORD(42686548660498), WORD(238974356712474), WORD(-530594252740420), WORD(155013134689418), WORD(812193533538096), WORD(709128981129146), WORD(-474898992937228), WORD(-197315429632778), WORD(-138231307879280), WORD(22698059334270), WORD(557911632124284), WORD(279505543440892), WORD(-21924142851456), WORD(-377702034938714), WORD(217572089171816), WORD(-102937430124708), WORD(-149553998724346), WORD(-146118971843224), WORD(600756289731806), WORD(52845290181468), WORD(-210839752673802), WORD(-361476793120676), WORD(330195134882802), WORD(644302708852546), WORD(43472418497894), WORD(243373933271006), WORD(-540362623157072), WORD(157866964543910), WORD(827146215827120), WORD(722184219713198), WORD(-483641999951620), WORD(-200948055119426), WORD(-140776180183436), WORD(23115936177398), WORD(568182922199896), WORD(284651309094660), WORD(-22327771702192), WORD(-384655622101314), WORD(221577644732168), WORD(-104832533477228), WORD(-152307324545886), WORD(-148809057976824), WORD(607547309886602), WORD(53442659592064), WORD(-213223110175526), WORD(-365562969544512), WORD(333927699742014), WORD(651585982879622), WORD(43963835858382), WORD(246125060998246), WORD(-546470946161724), WORD(159651511383150), WORD(836496374483224), WORD(730347875550638), WORD(-489109146322812), WORD(-203219595702034), WORD(-142367530774816), WORD(23377241454030), WORD(574605729155428), WORD(287869041160376), WORD(-22580167474376), WORD(-389003814749470), WORD(224082384635764), WORD(-106017572834936), WORD(-154029024557010), WORD(-150491213168888), WORD(617143543643169), WORD(54286788511200), WORD(-216590977622637), WORD(-371337051087476), WORD(339202100948917), WORD(661877809215553), WORD(44658246382249), WORD(250012616058163), WORD(-555102476340862), WORD(162173213311363), WORD(849708867758126), WORD(741883749092245), WORD(-496834644607818), WORD(-206429457242917), WORD(-144616231546638), WORD(23746485906151), WORD(583681649343220), WORD(292415944035758), WORD(-22936822111506), WORD(-395148145368313), WORD(227621774751894), WORD(-107692124585346), WORD(-156461919083727), WORD(-152868227824994), }; #endif /* Consecutively, real and imaginary parts of first 64 nonreal Gaussian primes. */ static const signed char small_gaussian_primes[] = { 1, 1, 1, 2, 2, 3, 1, 4, 2, 5, 1, 6, 4, 5, 2, 7, 5, 6, 3, 8, 5, 8, 4, 9, 1, 10, 3, 10, 7, 8, 4, 11, 7, 10, 6, 11, 2, 13, 9, 10, 7, 12, 1, 14, 2, 15, 8, 13, 4, 15, 1, 16, 10, 13, 9, 14, 5, 16, 2, 17, 12, 13, 11, 14, 9, 16, 5, 18, 8, 17, 7, 18, 10, 17, 6, 19, 1, 20, 3, 20, 14, 15, 12, 17, 7, 20, 4, 21, 10, 19, 5, 22, 11, 20, 10, 21, 14, 19, 13, 20, 1, 24, 8, 23, 5, 24, 17, 18, 16, 19, 4, 25, 13, 22, 6, 25, 12, 23, 1, 26, 5, 26, 15, 22, 2, 27, 9, 26 }; static const ulong atan_3_x[] = { 18, 57, 239 }; static const ulong atan_3_den = 1; static const slong atan_3_c[] = { 12, 8, -5, 17, 11, -7, 15, 10, -6, }; static const ulong atan_4_x[] = { 38, 57, 239, 268 }; static const ulong atan_4_den = 1; static const slong atan_4_c[] = { 12, 20, 7, 24, 17, 28, 10, 34, 15, 25, 9, 30, 20, 34, 12, 41, }; static const ulong atan_8_x[] = { 931, 1772, 2943, 6118, 34208, 44179, 85353, 485298 }; static const ulong atan_8_den = 1; static const slong atan_8_c[] = { 398, 525, 163, 68, -295, 71, 215, -183, 561, 740, 230, 96, -416, 100, 303, -258, 498, 657, 204, 85, -369, 89, 269, -229, 672, 886, 275, 115, -498, 120, 363, -309, 603, 796, 247, 103, -447, 108, 326, -277, 712, 940, 292, 122, -529, 127, 385, -328, 454, 599, 186, 78, -337, 81, 245, -209, 655, 864, 268, 112, -485, 117, 354, -301, }; static const ulong atan_12_x[] = { 157318, 330182, 390112, 478707, 485298, 617427, 1984933, 2343692, 3449051, 6225244, 22709274, 24208144 }; static const ulong atan_12_den = 1; static const slong atan_12_c[] = { 96032, 52094, 29861, 50539, -56156, -13587, -91675, 50539, 19970, -52094, 23407, -25106, 135373, 73435, 42094, 71243, -79161, -19153, -129231, 71243, 28151, -73435, 32996, -35391, 120168, 65187, 37366, 63241, -70270, -17002, -114716, 63241, 24989, -65187, 29290, -31416, 162110, 87939, 50408, 85314, -94796, -22936, -154755, 85314, 33711, -87939, 39513, -42381, 145539, 78950, 45255, 76593, -85106, -20592, -138936, 76593, 30265, -78950, 35474, -38049, 171871, 93234, 53443, 90451, -100504, -24317, -164073, 90451, 35741, -93234, 41892, -44933, 109562, 59434, 34068, 57659, -64067, -15501, -104591, 57659, 22783, -59433, 26705, -28643, 158036, 85729, 49141, 83170, -92414, -22360, -150866, 83170, 32864, -85729, 38520, -41316, 107117, 58107, 33308, 56373, -62638, -15155, -102257, 56373, 22275, -58107, 26109, -28004, 148196, 80392, 46081, 77991, -86658, -20967, -141472, 77990, 30816, -80390, 36122, -38743, 123763, 67137, 38484, 65133, -72372, -17510, -118148, 65133, 25737, -67137, 30166, -32356, 140927, 76448, 43821, 74166, -82409, -19939, -134533, 74166, 29306, -76448, 34350, -36843, }; static const ulong atan_13_x[] = { 683982, 1984933, 2343692, 2809305, 3014557, 6225244, 6367252, 18975991, 22709274, 24208144, 193788912, 201229582, UWORD(2189376182) }; static const ulong atan_13_den = 2; static const slong atan_13_c[] = { 893758, -387440, 344740, 738156, 36462, -653018, 732158, 560616, 202968, -58948, -1125574, -560064, -432616, 1259900, -546161, 485968, 1040553, 51399, -920537, 1032098, 790281, 286117, -83097, -1586683, -789503, -609844, 1118388, -484816, 431384, 923678, 45626, -817142, 916172, 701516, 253980, -73764, -1408466, -700826, -541346, 1508738, -654031, 581950, 1246069, 61551, -1102349, 1235944, 946367, 342627, -99509, -1900063, -945435, -730292, 1354512, -587175, 522462, 1118693, 55259, -989665, 1109604, 849627, 307603, -89337, -1705835, -848791, -655640, 1599582, -693411, 616990, 1321097, 65257, -1168723, 1310362, 1003349, 363257, -105501, -2014469, -1002361, -774264, 1019682, -442027, 393312, 842157, 41599, -745023, 835314, 639603, 231565, -67253, -1284159, -638973, -493568, 1470820, -637594, 567324, 1214752, 60004, -1074644, 1204882, 922582, 334016, -97008, -1852310, -921674, -711938, 996926, -432163, 384534, 823363, 40671, -728397, 816672, 625329, 226397, -65753, -1255501, -624713, -482554, 1379246, -597896, 532002, 1139122, 56268, -1007736, 1129866, 865142, 313220, -90968, -1736984, -864290, -667612, 1151848, -499321, 444290, 951313, 46991, -841589, 943582, 722505, 261579, -75971, -1450605, -721793, -557542, 1311590, -568568, 505906, 1083244, 53508, -958304, 1074442, 822704, 297856, -86506, -1651780, -821894, -634864, 1674096, -725713, 645732, 1382639, 68297, -1223167, 1371404, 1050089, 380179, -110415, -2108311, -1049055, -810332, }; static const ulong atan_16_x[] = { 4079486, 6367252, 7691443, 8296072, 9639557, 10292025, 18975991, 19696179, 22709274, 24208144, 168623905, 193788912, 201229582, 284862638, 599832943, UWORD(2189376182) }; static const ulong atan_16_den = 1; static const slong atan_16_c[] = { -234928, 371891, 1821154, 2095663, 2092544, -619249, 3406969, -1705235, 801522, 537775, -718269, -1808724, 317867, -446879, 1201905, -1341875, -331170, 524242, 2567218, 2954184, 2949787, -872934, 4802687, -2403811, 1129878, 758083, -1012519, -2549696, 448086, -629950, 1694284, -1891595, -293973, 465359, 2278868, 2622370, 2618467, -774886, 4263249, -2133815, 1002970, 672935, -898793, -2263314, 397757, -559194, 1503982, -1679131, -396578, 627783, 3074260, 3537654, 3532389, -1045344, 5751248, -2878579, 1353036, 907809, -1212498, -3053277, 536586, -754369, 2028916, -2265197, -356039, 563610, 2760003, 3176028, 3171301, -938487, 5163344, -2584325, 1214726, 815011, -1088554, -2741165, 481735, -677256, 1821516, -2033644, -420457, 665583, 3259367, 3750663, 3745081, -1108286, 6097542, -3051904, 1434505, 962470, -1285505, -3237121, 568895, -799791, 2151081, -2401589, -268028, 424288, 2077742, 2390928, 2387369, -706497, 3886988, -1945491, 914451, 613544, -819468, -2063561, 362652, -509841, 1371245, -1530936, -386611, 612006, 2996996, 3448744, 3443611, -1019072, 5606705, -2806233, 1319031, 884994, -1182025, -2976541, 523100, -735410, 1977924, -2208267, -262046, 414819, 2031373, 2337569, 2334090, -690730, 3800241, -1902073, 894043, 599851, -801180, -2017508, 354559, -498463, 1340643, -1496770, -362541, 573902, 2810403, 3234025, 3229212, -955624, 5257631, -2631517, 1236908, 829894, -1108432, -2791221, 490532, -689623, 1854779, -2070780, -302768, 479282, 2347047, 2700826, 2696806, -798069, 4390797, -2197654, 1032977, 693068, -925683, -2331028, 409657, -575924, 1548978, -1729367, -344757, 545750, 2672544, 3075386, 3070809, -908748, 4999728, -2502433, 1176234, 789185, -1054060, -2654303, 466470, -655795, 1763796, -1969202, -440043, 696588, 3411200, 3925382, 3919540, -1159914, 6381586, -3194072, 1501329, 1007305, -1345388, -3387917, 595396, -837048, 2251286, -2513463, -382676, 605775, 2966488, 3413638, 3408557, -1008698, 5549632, -2777667, 1305604, 875985, -1169992, -2946241, 517775, -727924, 1957790, -2185788, -254840, 403411, 1975510, 2273286, 2269903, -671735, 3695735, -1849767, 869457, 583355, -779148, -1962027, 344809, -484755, 1303776, -1455609, -365532, 578637, 2833590, 3260707, 3255854, -963509, 5301009, -2653228, 1247113, 836741, -1117577, -2814250, 494579, -695313, 1870081, -2087865, }; #if HAVE_64_BIT static const ulong atan_22_x[] = {UWORD(1479406293), UWORD(1892369318), UWORD(2112819717), UWORD(2189376182), UWORD(2701984943), UWORD(2971354082), UWORD(3558066693), UWORD(4038832337), UWORD(5271470807), UWORD(6829998457), UWORD(7959681215), UWORD(8193535810), UWORD(12139595709), UWORD(12185104420), UWORD(12957904393), UWORD(14033378718), UWORD(18710140581), UWORD(18986886768), UWORD(20746901917), UWORD(104279454193), UWORD(120563046313), UWORD(69971515635443)}; static const ulong atan_22_den = 1; static const slong atan_22_c[] = { WORD(-686576870), WORD(1656337239), WORD(-259447943), WORD(-1575862355), WORD(-586963256), WORD(2831731070), WORD(-713071113), WORD(1093399495), WORD(462322718), WORD(-1204188516), WORD(1196364387), WORD(1658902), WORD(-46276061), WORD(42040652), WORD(2649880866), WORD(1607783027), WORD(325822937), WORD(-351517254), WORD(909623840), WORD(-657099816), WORD(-765606746), WORD(241797349), WORD(-967843747), WORD(2334881511), WORD(-365734822), WORD(-2221438841), WORD(-827421869), WORD(3991793678), WORD(-1005191768), WORD(1541327578), WORD(651720399), WORD(-1697503042), WORD(1686473637), WORD(2338497), WORD(-65233768), WORD(59263258), WORD(3735445714), WORD(2266436312), WORD(459301363), WORD(-495521756), WORD(1282265372), WORD(-926290960), WORD(-1079249439), WORD(340853388), WORD(-859135493), WORD(2072627513), WORD(-324655470), WORD(-1971926729), WORD(-734485807), WORD(3543435230), WORD(-892288583), WORD(1368205594), WORD(578519134), WORD(-1506839423), WORD(1497048841), WORD(2075837), WORD(-57906708), WORD(52606806), WORD(3315880281), WORD(2011870082), WORD(407712613), WORD(-439864730), WORD(1138241267), WORD(-822249917), WORD(-958028093), WORD(302568720), WORD(-1158999071), WORD(2796035528), WORD(-437969786), WORD(-2660187206), WORD(-990842975), WORD(4780198435), WORD(-1203723565), WORD(1845749623), WORD(780439342), WORD(-2032770739), WORD(2019562956), WORD(2800365), WORD(-78117854), WORD(70968130), WORD(4473220110), WORD(2714071965), WORD(550016317), WORD(-593390469), WORD(1535520976), WORD(-1109239343), WORD(-1292408099), WORD(408174110), WORD(-1040523885), WORD(2510219225), WORD(-393199645), WORD(-2388257588), WORD(-889557039), WORD(4291557060), WORD(-1080676552), WORD(1657073432), WORD(700661283), WORD(-1824976878), WORD(1813119221), WORD(2514106), WORD(-70132492), WORD(63713627), WORD(4015958669), WORD(2436634140), WORD(493792557), WORD(-532732917), WORD(1378556973), WORD(-995850695), WORD(-1160295577), WORD(366449742), WORD(-1228784594), WORD(2964390108), WORD(-464340774), WORD(-2820362102), WORD(-1050503502), WORD(5068023211), WORD(-1276202034), WORD(1956885694), WORD(827431069), WORD(-2155167704), WORD(2141164656), WORD(2968980), WORD(-82821478), WORD(75241255), WORD(4742561141), WORD(2877491364), WORD(583133838), WORD(-629119629), WORD(1627977594), WORD(-1176028739), WORD(-1370226431), WORD(432751044), WORD(-783310848), WORD(1889703810), WORD(-296002381), WORD(-1797890566), WORD(-669662358), WORD(3230702580), WORD(-813537948), WORD(1247451994), WORD(527460822), WORD(-1373850429), WORD(1364923934), WORD(1892630), WORD(-52796041), WORD(47963892), WORD(3023230928), WORD(1834308642), WORD(371729157), WORD(-401043627), WORD(1037783608), WORD(-749680679), WORD(-873475492), WORD(275864939), WORD(-1129870629), WORD(2725764411), WORD(-426962549), WORD(-2593330285), WORD(-965940701), WORD(4660060518), WORD(-1173471088), WORD(1799361483), WORD(760825019), WORD(-1981682307), WORD(1968806468), WORD(2729985), WORD(-76154564), WORD(69184530), WORD(4360797299), WORD(2645860790), WORD(536193080), WORD(-578477135), WORD(1496929630), WORD(-1081361483), WORD(-1259926766), WORD(397915710), WORD(-765829642), WORD(1847531151), WORD(-289396474), WORD(-1757766910), WORD(-654717454), WORD(3158602753), WORD(-795382162), WORD(1219612516), WORD(515689440), WORD(-1343190108), WORD(1334462826), WORD(1850392), WORD(-51617788), WORD(46893478), WORD(2955761261), WORD(1793372241), WORD(363433250), WORD(-392093507), WORD(1014623315), WORD(-732950000), WORD(-853982075), WORD(269708441), WORD(-1059524736), WORD(2556057963), WORD(-400379805), WORD(-2431869203), WORD(-905801107), WORD(4369924542), WORD(-1100410625), WORD(1687333002), WORD(713455954), WORD(-1858302508), WORD(1846228320), WORD(2560016), WORD(-71413171), WORD(64877092), WORD(4089293490), WORD(2481129152), WORD(502809629), WORD(-542461073), WORD(1403730596), WORD(-1014035776), WORD(-1181483561), WORD(373141426), WORD(-884839166), WORD(2134636521), WORD(-334368534), WORD(-2030922964), WORD(-756460202), WORD(3649447961), WORD(-918984132), WORD(1409139660), WORD(595827308), WORD(-1551921145), WORD(1541837648), WORD(2137942), WORD(-59639165), WORD(54180700), WORD(3415085008), WORD(2072061345), WORD(419910586), WORD(-453024632), WORD(1172295245), WORD(-846850045), WORD(-986690441), WORD(311620991), WORD(-1007551725), WORD(2430675304), WORD(-380739920), WORD(-2312578392), WORD(-861368722), WORD(4155566039), WORD(-1046432033), WORD(1604564027), WORD(678458702), WORD(-1767146942), WORD(1755665031), WORD(2434439), WORD(-67910131), WORD(61694667), WORD(3888700820), WORD(2359421986), WORD(478145240), WORD(-515851656), WORD(1334873208), WORD(-964294141), WORD(-1123528087), WORD(354837669), WORD(-1286025714), WORD(3102481854), WORD(-485971405), WORD(-2951744515), WORD(-1099439660), WORD(5304109606), WORD(-1335652026), WORD(2048044331), WORD(865975726), WORD(-2255563017), WORD(2240907657), WORD(3107286), WORD(-86679594), WORD(78746258), WORD(4963486365), WORD(3011535060), WORD(610298269), WORD(-658426241), WORD(1703814532), WORD(-1230812305), WORD(-1434056411), WORD(452910114), WORD(-1118368966), WORD(2698017143), WORD(-422616229), WORD(-2566931147), WORD(-956107784), WORD(4612622835), WORD(-1161525589), WORD(1781044652), WORD(753080103), WORD(-1961509518), WORD(1948764750), WORD(2702195), WORD(-75379339), WORD(68480257), WORD(4316406004), WORD(2618926911), WORD(530734834), WORD(-572588453), WORD(1481691443), WORD(-1070353625), WORD(-1247101180), WORD(393865076), WORD(-744769216), WORD(1796723777), WORD(-281438029), WORD(-1709428066), WORD(-636712629), WORD(3071740720), WORD(-773509038), WORD(1186072995), WORD(501507906), WORD(-1306252186), WORD(1297764905), WORD(1799506), WORD(-50198291), WORD(45603901), WORD(2874477399), WORD(1744054245), WORD(353438783), WORD(-381310879), WORD(986721027), WORD(-712793769), WORD(-830497445), WORD(262291420), WORD(-1068266212), WORD(2577146400), WORD(-403683088), WORD(-2451933036), WORD(-913274306), WORD(4405978059), WORD(-1109489426), WORD(1701254132), WORD(719342233), WORD(-1873634201), WORD(1861460396), WORD(2581137), WORD(-72002356), WORD(65412352), WORD(4123031695), WORD(2501599398), WORD(506957997), WORD(-546936581), WORD(1415311900), WORD(-1022401951), WORD(-1191231244), WORD(376219983), WORD(-839271258), WORD(2024705898), WORD(-317149049), WORD(-1926333436), WORD(-717503621), WORD(3461506790), WORD(-871657809), WORD(1336571052), WORD(565143083), WORD(-1471999502), WORD(1462435290), WORD(2027841), WORD(-56567836), WORD(51390474), WORD(3239213182), WORD(1965353251), WORD(398285812), WORD(-429694534), WORD(1111923774), WORD(-803238520), WORD(-935877343), WORD(295572971), WORD(-936636410), WORD(2259595150), WORD(-353941999), WORD(-2149810347), WORD(-800742322), WORD(3863081528), WORD(-972780175), WORD(1491628720), WORD(630706203), WORD(-1642768433), WORD(1632094662), WORD(2263094), WORD(-63130358), WORD(57352362), WORD(3614999296), WORD(2193356911), WORD(444491563), WORD(-479544059), WORD(1240919765), WORD(-896423459), WORD(-1044449916), WORD(329862847), WORD(-1239711235), WORD(2990750161), WORD(-468469801), WORD(-2845441424), WORD(-1059844826), WORD(5113089264), WORD(-1287550323), WORD(1974286781), WORD(834788780), WORD(-2174331962), WORD(2160204395), WORD(2995381), WORD(-83557945), WORD(75910318), WORD(4784733109), WORD(2903078693), WORD(588319201), WORD(-634713910), WORD(1642453953), WORD(-1186486262), WORD(-1382410807), WORD(436599168), WORD(-732543763), WORD(1767230397), WORD(-276818199), WORD(-1681367652), WORD(-626260935), WORD(3021317824), WORD(-760811818), WORD(1166603502), WORD(493275609), WORD(-1284809940), WORD(1276461979), WORD(1769967), WORD(-49374282), WORD(44855308), WORD(2827292597), WORD(1715425440), WORD(347637054), WORD(-375051627), WORD(970523914), WORD(-701093196), WORD(-816864755), WORD(257985883), WORD(-911523298), WORD(2199010843), WORD(-344452100), WORD(-2092169592), WORD(-779272804), WORD(3759504514), WORD(-946697974), WORD(1451635144), WORD(613795697), WORD(-1598722495), WORD(1588334910), WORD(2202416), WORD(-61437706), WORD(55814630), WORD(3518073868), WORD(2134548585), WORD(432573847), WORD(-466686514), WORD(1207648201), WORD(-872388537), WORD(-1016446105), WORD(321018558), WORD(-1310818407), WORD(3162293162), WORD(-495340222), WORD(-3008649828), WORD(-1120635247), WORD(5406365074), WORD(-1361401442), WORD(2087527627), WORD(882670470), WORD(-2299046970), WORD(2284109076), WORD(3167190), WORD(-88350649), WORD(80264371), WORD(5059175116), WORD(3069593047), WORD(622063926), WORD(-671119736), WORD(1736661582), WORD(-1254540564), WORD(-1461702920), WORD(461641558), }; #endif typedef struct { const ulong * x; arb_ptr res; slong prec; int hyperbolic; } atan_work; static void parallel_atan_worker(slong i, atan_work * work) { fmpz_t p, q; fmpz_init(p); fmpz_init(q); fmpz_one(p); if (work->x[i] == L24_FIXME) fmpz_set_str(q, L24_FIXME_STR, 10); else fmpz_set_ui(q, work->x[i]); arb_atan_frac_bsplit(work->res + i, p, q, work->hyperbolic, work->prec); fmpz_clear(p); fmpz_clear(q); } void arb_log_primes_vec_bsplit(arb_ptr res, slong n, slong prec) { ulong den, prime; const ulong * x; ulong * primes; const slong * c; slong i, j, k, wp, ln; arb_ptr y; arb_t t; fmpz_t p, q; n_primes_t iter; wp = prec + 64; switch (n) { #if HAVE_64_BIT case 1: case 2: case 3: case 4: case 5: ln = 4; x = log_atanh_4_x; den = log_atanh_4_den; c = log_atanh_4_c; break; case 6: case 7: case 8: case 9: ln = 8; x = log_atanh_8_x; den = log_atanh_8_den; c = log_atanh_8_c; break; case 10: case 11: case 12: ln = 12; x = log_atanh_12_x; den = log_atanh_12_den; c = log_atanh_12_c; break; case 13: case 14: ln = 13; x = log_atanh_13_x; den = log_atanh_13_den; c = log_atanh_13_c; break; case 15: case 16: case 17: ln = 16; x = log_atanh_16_x; den = log_atanh_16_den; c = log_atanh_16_c; break; case 18: case 19: case 20: case 21: ln = 20; x = log_atanh_20_x; den = log_atanh_20_den; c = log_atanh_20_c; break; case 22: case 23: case 24: default: ln = 24; x = log_atanh_24_x; den = log_atanh_24_den; c = log_atanh_24_c; break; #else case 1: case 2: case 3: case 4: case 5: ln = 4; x = log_atanh_4_x; den = log_atanh_4_den; c = log_atanh_4_c; break; case 6: case 7: case 8: case 9: ln = 8; x = log_atanh_8_x; den = log_atanh_8_den; c = log_atanh_8_c; break; case 10: case 11: case 13: default: ln = 13; x = log_atanh_13_x; den = log_atanh_13_den; c = log_atanh_13_c; break; #endif } y = _arb_vec_init(ln); arb_init(t); fmpz_init(p); fmpz_init(q); primes = flint_malloc(sizeof(ulong) * n); n_primes_init(iter); for (i = 0; i < n; i++) primes[i] = n_primes_next(iter); n_primes_clear(iter); { atan_work work; work.x = x; work.res = y; work.prec = wp; work.hyperbolic = 1; flint_parallel_do((do_func_t) parallel_atan_worker, &work, ln, -1, FLINT_PARALLEL_STRIDED); } for (i = 0; i < FLINT_MIN(n, ln); i++) { arb_dot_si(res + i, NULL, 0, y, 1, c + i * ln, 1, ln, wp); if (den == 1) arb_set_round(res + i, res + i, prec); else arb_div_ui(res + i, res + i, den, prec); } /* todo: sieving instead of factoring */ /* todo: parallel comp here as well */ for (i = ln; i < n; i++) { n_factor_t fac; prime = primes[i]; fmpz_one(p); fmpz_set_ui(q, 2 * prime * prime - 1); arb_atan_frac_bsplit(res + i, p, q, 1, wp); arb_mul_2exp_si(res + i, res + i, 1); n_factor_init(&fac); n_factor(&fac, (prime - 1) / 2, 1); for (j = 0; j < fac.num; j++) for (k = 0; k < i; k++) if (fac.p[j] == primes[k]) arb_addmul_ui(res + i, res + k, fac.exp[j], wp); n_factor_init(&fac); n_factor(&fac, (primes[i] + 1) / 2, 1); for (j = 0; j < fac.num; j++) for (k = 0; k < i; k++) if (fac.p[j] == primes[k]) arb_addmul_ui(res + i, res + k, fac.exp[j], wp); arb_mul_2exp_si(res + i, res + i, -1); arb_add(res + i, res + i, res + 0, prec); } _arb_vec_clear(y, ln); arb_clear(t); fmpz_clear(p); fmpz_clear(q); flint_free(primes); } FLINT_TLS_PREFIX arb_struct _arb_log_p_cache[ARB_LOG_PRIME_CACHE_NUM]; FLINT_TLS_PREFIX slong _arb_log_p_cache_prec = 0; void _arb_log_p_cleanup(void) { slong i; for (i = 0; i < ARB_LOG_PRIME_CACHE_NUM; i++) arb_clear(_arb_log_p_cache + i); _arb_log_p_cache_prec = 0; } arb_srcptr _arb_log_p_cache_vec(void) { return _arb_log_p_cache; } void _arb_log_p_ensure_cached(slong prec) { slong i, wp; if (_arb_log_p_cache_prec < prec) { if (_arb_log_p_cache_prec == 0) { for (i = 0; i < ARB_LOG_PRIME_CACHE_NUM; i++) arb_init(_arb_log_p_cache + i); flint_register_cleanup_function(_arb_log_p_cleanup); } wp = prec + 32; if (wp <= ARB_LOG_TAB2_PREC - 16) { for (i = 0; i < ARB_LOG_PRIME_CACHE_NUM; i++) { slong exp, exp_fix; mp_size_t n; arb_ptr res = _arb_log_p_cache + i; n = ARB_LOG_TAB2_PREC / FLINT_BITS; /* exponent of log(prime(i+1)) */ exp = (i >= 1) + (i >= 4) + (i >= 16) + (i >= 429); /* just reading the table is known to give the correct rounding */ _arf_set_round_mpn(arb_midref(res), &exp_fix, arb_log_p_tab[i], n, 0, wp, ARF_RND_NEAR); exp += exp_fix; _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp); /* 1/2 ulp error */ _fmpz_set_si_small(MAG_EXPREF(arb_radref(res)), exp - wp); MAG_MAN(arb_radref(res)) = MAG_ONE_HALF; } } else { prec = FLINT_MAX(prec, _arb_log_p_cache_prec * 1.25); arb_log_primes_vec_bsplit(_arb_log_p_cache, ARB_LOG_PRIME_CACHE_NUM, prec + 32); } _arb_log_p_cache_prec = prec; } } static int factor_smooth(ulong * c, ulong n) { slong i; for (i = 0; i < ARB_LOG_PRIME_CACHE_NUM; i++) c[i] = 0; /* Hardcoded so that the compiler can remove divisions */ while (n != 1 && n % 2 == 0) { n /= 2; c[0]++; } while (n != 1 && n % 3 == 0) { n /= 3; c[1]++; } while (n != 1 && n % 5 == 0) { n /= 5; c[2]++; } while (n != 1 && n % 7 == 0) { n /= 7; c[3]++; } while (n != 1 && n % 11 == 0) { n /= 11; c[4]++; } while (n != 1 && n % 13 == 0) { n /= 13; c[5]++; } while (n != 1 && n % 17 == 0) { n /= 17; c[6]++; } while (n != 1 && n % 19 == 0) { n /= 19; c[7]++; } while (n != 1 && n % 23 == 0) { n /= 23; c[8]++; } while (n != 1 && n % 29 == 0) { n /= 29; c[9]++; } while (n != 1 && n % 31 == 0) { n /= 31; c[10]++; } while (n != 1 && n % 37 == 0) { n /= 37; c[11]++; } while (n != 1 && n % 41 == 0) { n /= 41; c[12]++; } return n == 1; } /* todo: use in log_ui in appropriates ranges */ int _arb_log_ui_smooth(arb_t res, ulong n, slong prec) { ulong c[ARB_LOG_PRIME_CACHE_NUM]; if (factor_smooth(c, n)) { _arb_log_p_ensure_cached(prec); arb_dot_ui(res, NULL, 0, _arb_log_p_cache, 1, c, 1, ARB_LOG_PRIME_CACHE_NUM, prec); return 1; } else { return 0; } } void arb_atan_gauss_primes_vec_bsplit(arb_ptr res, slong n, slong prec) { const ulong * x; const slong * c; slong i, j, wp, ln; arb_ptr y; arb_t t; fmpz_t p, q; ulong den; /* not implemented */ if (n > 64) flint_throw(FLINT_ERROR, "(%s)\n", __func__); wp = prec + 64; switch (n) { case 1: case 2: case 3: ln = 3; x = atan_3_x; den = atan_3_den; c = atan_3_c; break; case 4: ln = 4; x = atan_4_x; den = atan_4_den; c = atan_4_c; break; case 5: case 6: case 7: case 8: ln = 8; x = atan_8_x; den = atan_8_den; c = atan_8_c; break; case 9: case 10: case 11: case 12: ln = 12; x = atan_12_x; den = atan_12_den; c = atan_12_c; break; case 13: ln = 13; x = atan_13_x; den = atan_13_den; c = atan_13_c; break; case 14: case 15: case 16: ln = 16; x = atan_16_x; den = atan_16_den; c = atan_16_c; break; #if HAVE_64_BIT case 17: case 18: case 19: case 20: case 21: case 22: default: ln = 22; x = atan_22_x; den = atan_22_den; c = atan_22_c; break; #else default: ln = 16; x = atan_16_x; den = atan_16_den; c = atan_16_c; break; #endif } y = _arb_vec_init(ln); arb_init(t); fmpz_init(p); fmpz_init(q); { atan_work work; work.x = x; work.res = y; work.prec = wp; work.hyperbolic = 0; flint_parallel_do((do_func_t) parallel_atan_worker, &work, ln, -1, FLINT_PARALLEL_STRIDED); } for (i = 0; i < FLINT_MIN(n, ln); i++) { arb_dot_si(res + i, NULL, 0, y, 1, c + i * ln, 1, ln, wp); if (den == 1) arb_set_round(res + i, res + i, prec); else arb_div_ui(res + i, res + i, den, prec); } for (i = ln; i < n; i++) { double best = 100, t; slong xa, xb, ya, yb; slong best_j = 0; xa = small_gaussian_primes[2 * i]; xb = small_gaussian_primes[2 * i + 1]; for (j = 0; j < FLINT_MIN(i, 100); j++) { ya = small_gaussian_primes[2 * j]; yb = small_gaussian_primes[2 * j + 1]; t = (xb*ya - xa*yb) / (double) (xa*ya + xb*yb); if (fabs(t) < best) { best = fabs(t); best_j = j; } } ya = small_gaussian_primes[2 * best_j]; yb = small_gaussian_primes[2 * best_j + 1]; fmpz_set_si(p, xb*ya - xa*yb); fmpz_set_si(q, xa*ya + xb*yb); arb_atan_frac_bsplit(res + i, p, q, 0, wp); arb_add(res + i, res + i, res + best_j, prec); } _arb_vec_clear(y, ln); arb_clear(t); fmpz_clear(p); fmpz_clear(q); } FLINT_TLS_PREFIX arb_struct _arb_atan_gauss_p_cache[ARB_ATAN_GAUSS_PRIME_CACHE_NUM]; FLINT_TLS_PREFIX slong _arb_atan_gauss_p_cache_prec = 0; void _arb_atan_gauss_p_cleanup(void) { slong i; for (i = 0; i < ARB_ATAN_GAUSS_PRIME_CACHE_NUM; i++) arb_clear(_arb_atan_gauss_p_cache + i); _arb_atan_gauss_p_cache_prec = 0; } arb_srcptr _arb_atan_gauss_p_cache_vec(void) { return _arb_atan_gauss_p_cache; } void _arb_atan_gauss_p_ensure_cached(slong prec) { slong i, wp; if (_arb_atan_gauss_p_cache_prec < prec) { if (_arb_atan_gauss_p_cache_prec == 0) { for (i = 0; i < ARB_ATAN_GAUSS_PRIME_CACHE_NUM; i++) arb_init(_arb_atan_gauss_p_cache + i); flint_register_cleanup_function(_arb_atan_gauss_p_cleanup); } wp = prec + 32; /* todo */ if (wp <= ARB_ATAN_TAB2_PREC - 16) { for (i = 0; i < ARB_ATAN_GAUSS_PRIME_CACHE_NUM; i++) { slong exp, exp_fix; mp_size_t n; static const char exponents[24] = {0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1}; arb_ptr res = _arb_atan_gauss_p_cache + i; n = ARB_LOG_TAB2_PREC / FLINT_BITS; if (i >= 24) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* exponent of 2*atan(x) */ exp = exponents[i] + 1; /* just reading the table is known to give the correct rounding */ _arf_set_round_mpn(arb_midref(res), &exp_fix, arb_atan_gauss_tab[i], n, 0, wp, ARF_RND_NEAR); exp += exp_fix; _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp); /* 1/2 ulp error */ _fmpz_set_si_small(MAG_EXPREF(arb_radref(res)), exp - wp); MAG_MAN(arb_radref(res)) = MAG_ONE_HALF; } } else { prec = FLINT_MAX(prec, _arb_atan_gauss_p_cache_prec * 1.25); arb_atan_gauss_primes_vec_bsplit(_arb_atan_gauss_p_cache, ARB_ATAN_GAUSS_PRIME_CACHE_NUM, prec + 32); _arb_vec_scalar_mul_2exp_si(_arb_atan_gauss_p_cache, _arb_atan_gauss_p_cache, ARB_ATAN_GAUSS_PRIME_CACHE_NUM, 1); } _arb_atan_gauss_p_cache_prec = prec; } } flint-3.1.3/src/arb/log_reduce.c000066400000000000000000000672531461254215100164570ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "arb.h" #ifdef __GNUC__ # define floor __builtin_floor # define ldexp __builtin_ldexp #else # include #endif #define TERMINATOR -32768 /* Precomputed data for ARB_LOG_PRIME_CACHE_NUM primes */ static const short small_primes[ARB_LOG_PRIME_CACHE_NUM] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 }; /* log2 of primes */ static const float log_weights[ARB_LOG_PRIME_CACHE_NUM] = { 0.0, /* log(2) is free */ 1.5849625007210761, 2.3219280948874257, 2.807354922057584, 3.4594316186371543, 3.700439718141297, 4.087462841250272, 4.247927513443756, 4.523561956057165, 4.857980995127946, 4.954196310386578, 5.209453365629088, 5.357552004617901, }; /* Output of _arb_log_precompute_reductions with n = 13, C = 8 */ static const short log_rel_d[] = { 1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 1, -1, -1, 0, 1, 1, 0, -1, 0, 0, 0, 0, 0, 1, 1, 0, -1, 0, 1, -1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 1, -1, 1, -1, 0, 0, 0, 1, 1, -2, -1, -1, 0, 1, 1, -1, 1, 0, 0, 0, 1, 0, -1, -1, 0, 2, -1, 0, -1, -1, 1, 1, 1, -1, 0, 1, 1, 2, -1, 0, -2, 1, -1, -1, 1, 1, 0, 4, -1, -2, 0, 0, 2, 0, -2, -2, 1, 1, 0, -2, 0, 0, -2, 0, 0, 2, -4, 4, -1, 1, 0, 1, 1, 4, 1, -1, 1, -2, -3, 0, -4, 3, 1, 1, 3, 5, 1, 1, 0, -2, -2, 1, 1, 0, -4, 1, 1, 0, -2, -1, 0, 2, 4, 4, 0, 3, 1, -6, -1, -3, 3, 2, -1, -6, 2, 3, -2, -2, 3, 1, 5, -4, -2, 0, -5, -1, -1, -9, 7, 2, -9, 3, 7, -3, 3, 0, 1, -1, -7, -2, 5, 5, -6, 2, 0, -10, 5, 2, 3, 3, -2, -7, -9, 6, 6, 3, 9, 1, 8, -15, -4, 0, 10, -7, -4, -17, 4, -3, 7, -10, 9, 1, 7, 2, -4, 2, -3, 2, -2, 15, -16, -4, 7, -11, 15, 0, -9, 4, 1, -13, 6, 2, 2, 0, 17, -2, -11, -21, 17, 2, -2, 6, -9, 0, 9, 9, -2, -4, -22, 4, -7, 0, 5, 11, 2, 27, -5, 3, 15, 18, -16, 9, 0, -15, -9, -4, 1, 13, 9, -30, 7, 9, -23, -3, 16, -21, 17, -5, 5, 6, 4, -5, 8, -8, 6, -25, -38, -16, 24, 13, -10, 10, 24, 36, -49, 11, 12, -24, -25, 7, 7, 7, 44, -44, 19, -5, 101, -32, -31, 6, 36, -11, 30, 20, 8, -11, -47, -7, 0, 48, -31, 21, -27, 34, -23, -29, 41, -50, -65, 33, 20, 40, 58, -85, 42, -67, 51, 37, 61, 4, -65, -40, -9, 18, 5, 68, 31, 2, 50, -12, 27, -42, 147, -38, -81, -7, -24, -9, 26, 20, -35, 16, -1, 75, -13, 2, -128, -100, 130, 46, -13, 0, 78, 91, -120, 149, -170, 156, 22, 5, 54, -80, -105, 8, 226, -31, -128, -57, -35, -20, 46, -103, -5, 176, -118, 70, 21, 137, -26, 127, 45, -14, -73, -66, -166, 71, 76, 122, -154, 53, 146, -222, 350, -77, -31, 20, -49, -162, -179, 116, 43, 25, 81, 286, 326, -203, 64, 71, 158, 60, -159, -69, 53, -194, 17, 3, 254, -11, -64, 83, -168, -28, 302, -225, 459, -403, -77, 37, 29, 169, -89, 290, -118, -605, 1100, -34, 112, 384, -141, -468, -266, -6, 145, 375, 543, -140, -101, -298, 451, -172, -839, -201, 670, 92, -55, 29, -159, -25, -881, 467, 368, 356, 476, -238, -301, -15, 249, -445, 200, -51, -52, -515, 1004, -73, 319, -303, -239, -352, 674, -176, -262, 201, 211, 1009, 127, -518, -180, 263, 108, -941, 742, -219, -722, 595, 355, 1305, -493, -1371, 230, -720, 463, 99, 1334, 238, -612, -129, -254, 615, 881, -82, -16, -1392, 229, 1458, 887, -961, 579, -1042, -125, -35, 467, 771, 929, -1054, 222, -1676, 1466, -148, 642, 287, 176, -344, -783, 556, -1642, 158, -934, 1001, -19, -1652, -329, 280, 1866, -1196, 1141, -241, 820, -1599, 612, -2431, 2075, 187, 265, -1984, -1622, 227, 352, 1459, 650, 2179, -1220, -281, 1277, 1083, -796, 95, -1410, -1120, 405, 2450, -3100, 1630, 747, -2433, 64, -671, -1482, -1592, 921, 1140, 1339, -723, 3483, -1933, -462, 1432, 1213, -345, 1948, 2565, 796, -826, -2550, -2459, 1128, -1033, -1167, 2092, 1221, 2993, -4115, 5545, -506, -1116, 1103, -2881, -2076, -955, 2418, -675, 1344, 1552, -1319, 1811, 403, -1630, -2912, 3300, 4551, -3903, -56, -2748, 1501, 470, 3704, -2349, 1775, 3414, 1348, -2094, -3296, 3503, -8959, -260, 6149, 742, -849, 5687, -1783, -4739, -4752, 2449, 2663, -640, -3687, -3290, -835, 9424, -3052, 1789, 12240, 4587, -3750, 1958, -2949, 4395, -5453, 9129, -538, 5578, -8137, -3979, -462, 4747, 6252, -10020, 14096, -3541, 2170, 15553, -8762, -12673, 1007, 3368, -159, -3083, 957, 1485, -4231, 23117, -5115, -5577, 3009, -5806, -726, -8789, 1836, 17445, -11513, 5052, -1053, -26095, -2312, -12870, 13692, 994, 5315, 12997, 9530, -7231, -3893, -3373, 1708, 10103, -13905, 43, -1923, 3702, -4720, -19980, -10488, 6503, 29007, 3602, -6543, TERMINATOR, }; static const double log_rel_epsilon[] = { 0.18232155679395462, 0.0266682470821613254, 0.00350263055120206366, 0.000442184398095918677, 8.24980407183236868e-05, 9.84232593854523219e-06, 1.52063732951784046e-06, 3.23154886181859914e-08, 4.38246503661907078e-09, -2.11704006951314627e-10, -7.07426669244763431e-11, -2.21701523380274833e-11, 3.33036400488437696e-12, 2.54265619979145741e-13, -7.00024276392618185e-14, -9.51714644892047648e-15, 6.80693234263194677e-16, 1.38172686218446643e-16, -8.19305834374777461e-18, 3.5176906074023809e-18, 4.67118192241310654e-19, 8.17891052982097575e-20, -1.19179263459574717e-20, -8.51393042738715997e-23, 3.76392698342906217e-23, 5.28766891158120376e-24, 5.2060634410123273e-26, -1.63504294042364847e-26, 1.90067819717850597e-27, -3.33141349620465382e-29, 2.07178082822512832e-30, -4.74225218175538935e-31, -1.42274363523616913e-31, -7.47394389255809103e-33, -1.73829895124503976e-33, 8.26424285905383777e-36, -4.71875282737164478e-37, 4.63703613472910643e-37, 2.80042458117148945e-38, -3.73163451438722246e-39, -1.74597092800142613e-40, -1.88295877456676773e-40, -2.26444799388392757e-41, 5.60832045421886576e-43, -1.00422711325320322e-43, 2.92831247865346646e-44, -1.13961060638254883e-45, -1.32337722847336868e-45, 1.83766622090819767e-46, 5.95732915783458014e-48, -2.24487689239035057e-48, -1.56518141370651064e-49, -2.78642033949683251e-51, 5.88762413433732367e-52, 3.40338106058818415e-53, -4.48648864933766729e-54, 1.23840947437945835e-54, -8.98741915925760203e-56, }; static const double log_rel_epsilon_inv[] = { 5.48481494774707734, 37.4977776724181737, 285.499708114180407, 2261.49996315130011, 12121.4999931251623, 101601.999999179796, 657618.999999873224, 30944913.5, 228182082.833333343, -4723576159.0, -14135740755.5412464, -45105689160.5, 300267477829.264465, 3932895057074.63574, -14285218866311.6641, -105073511831209.594, 1469090553077751.25, 7237320394994939.0, -122054543986387264.0, 284277417091676640.0, 2.1407858152598039e+18, 1.22265672958998426e+19, -8.39072143065557074e+19, -1.17454565612053038e+22, 2.65679967864033022e+22, 1.8911925400808879e+23, 1.92083713794611083e+25, -6.11604732375343398e+25, 5.26127990253408999e+26, -3.00172884914844711e+28, 4.82676539128267243e+29, -2.10870270427044347e+30, -7.02867315821099744e+30, -1.33798167925198604e+32, -5.75275040742422151e+32, 1.21003220386300296e+35, -2.11920402823260834e+36, 2.15654994040373068e+36, 3.57088709591912793e+37, -2.67979084271121742e+38, -5.72747222741376142e+39, -5.31079072737575268e+39, -4.4160872879435118e+40, 1.78306501592245647e+42, -9.95790680019075144e+42, 3.41493610155919096e+43, -8.77492710579701471e+44, -7.55642441538447421e+44, 5.44168461400888913e+45, 1.67860457850458665e+47, -4.45458725772350707e+47, -6.38903574526800067e+48, -3.58883398109482076e+50, 1.69847798905483982e+51, 2.93825458330304179e+52, -2.22891458813258854e+53, 8.07487362369445356e+53, -1.11266647552533214e+55, }; void _arb_log_reduce_fixed(slong * rel, const short * d, const double * epsilon, const double * epsilon_inv, const fmpz * alpha, const float * weights, slong num_alpha, const fmpz_t x, slong prec, double max_weight) { slong i, j, n; slong * new_rel; const short * d_row; double dalpha; double weight, dx; fmpz_t t; new_rel = flint_malloc(num_alpha * sizeof(slong)); fmpz_init(t); for (i = 0; i < num_alpha; i++) rel[i] = 0; dx = fmpz_get_d(x); dx = ldexp(dx, -prec); /* Reduce by the first alpha, which is assumed to be free */ dalpha = fmpz_get_d(alpha + 0); dalpha = ldexp(dalpha, -prec); n = floor(dx / dalpha + 0.5); dx -= dalpha * n; rel[0] = n; /* Recompute accurately if there is significant cancellation */ if (FLINT_ABS(n) > 10) { fmpz_set(t, x); fmpz_submul_si(t, alpha + 0, rel[0]); dx = fmpz_get_d(t); dx = ldexp(dx, -prec); } for (i = 0; ; i++) { d_row = d + i * num_alpha; if (d_row[0] == TERMINATOR) break; for (j = 0; j < num_alpha; j++) new_rel[j] = d_row[j]; n = floor(dx * epsilon_inv[i] + 0.5); if (n != 0) { weight = 0.0; for (j = 0; j < num_alpha; j++) { new_rel[j] = rel[j] + n * new_rel[j]; if (j != 0) weight += FLINT_ABS(new_rel[j]) * weights[j] * 1.442695; } if (weight > max_weight) break; for (j = 0; j < num_alpha; j++) rel[j] = new_rel[j]; dx -= n * epsilon[i]; } if (i % 8 == 7) { fmpz_set(t, x); for (j = 0; j < num_alpha; j++) fmpz_submul_si(t, alpha + j, rel[j]); dx = fmpz_get_d(t); dx = ldexp(dx, -prec); } } fmpz_clear(t); flint_free(new_rel); } static void rel_product(fmpz_t p, fmpz_t q, const short * primes, const slong * rel, slong len) { slong i; if (len <= 4) { fmpz_t r; fmpz_init(r); for (i = 0; i < len; i++) { fmpz_ui_pow_ui(r, primes[i], FLINT_ABS(rel[i])); if (rel[i] >= 0) fmpz_mul(p, p, r); else fmpz_mul(q, q, r); } fmpz_clear(r); } else { fmpz_t p2, q2; fmpz_init_set_ui(p2, 1); fmpz_init_set_ui(q2, 1); rel_product(p, q, primes, rel, len / 2); rel_product(p2, q2, primes + len / 2, rel + len / 2, len - len / 2); fmpz_mul(p, p, p2); fmpz_mul(q, q, q2); fmpz_clear(p2); fmpz_clear(q2); } } /* todo: error propagation */ void _arb_exp_arf_precomp(arb_t res, const arf_t x, slong prec, int minus_one, slong num_logs, arb_srcptr logs, const short * primes, const float * weights, const short * log_rel_d, const double * epsilon, const double * epsilon_inv, double max_weight) { arb_t t; fmpz_t p, r, q; slong wp; slong * rel; slong i; fmpz * alpha; slong mag; mag_t err, err2; mag = arf_abs_bound_lt_2exp_si(x); arb_init(t); rel = flint_malloc(num_logs * sizeof(slong)); alpha = _fmpz_vec_init(num_logs); fmpz_init(r); if (prec <= 10000) wp = 256; else if (prec <= 100000) wp = 512; else wp = 768; for (i = 0; i < num_logs; i++) arf_get_fmpz_fixed_si(alpha + i, arb_midref(logs + i), -wp); arf_get_fmpz_fixed_si(r, x, -wp); _arb_log_reduce_fixed(rel, log_rel_d, epsilon, epsilon_inv, alpha, weights, num_logs, r, wp, max_weight); fmpz_clear(r); _fmpz_vec_clear(alpha, num_logs); wp = prec + 5 + 2 * FLINT_BIT_COUNT(prec); if (minus_one && mag < 0) wp += (-mag); else if (mag > 0) wp += mag; arb_set_arf(t, x); arb_dot_si(t, t, 1, logs, 1, rel, 1, num_logs, wp); arb_exp_arf_generic(res, arb_midref(t), wp, 0); /* exp(a+b) - exp(a) = exp(a) * (exp(b)-1) */ mag_init(err); mag_init(err2); arb_get_mag(err, res); mag_expm1(err2, arb_radref(t)); mag_mul(arb_radref(res), err, err2); mag_clear(err); mag_clear(err2); fmpz_init(p); fmpz_init(q); fmpz_one(p); fmpz_one(q); rel_product(p, q, primes + 1, rel + 1, num_logs - 1); arb_mul_fmpz(res, res, p, wp); arb_div_fmpz(res, res, q, wp); arb_mul_2exp_si(res, res, rel[0]); if (minus_one) arb_sub_ui(res, res, 1, prec); else arb_set_round(res, res, prec); flint_free(rel); fmpz_clear(p); fmpz_clear(q); arb_clear(t); } void arb_exp_arf_huge(arb_t z, const arf_t x, slong mag, slong prec, int minus_one); void arb_exp_arf_log_reduction(arb_t res, const arf_t x, slong prec, int minus_one) { slong wp; slong mag; mag = arf_abs_bound_lt_2exp_si(x); if (mag < -prec / 16 || mag < -768 || arf_bits(x) < prec / 128) { arb_exp_arf_generic(res, x, prec, minus_one); return; } /* multiprecision log(2) reduction not implemented here */ if ((FLINT_BITS == 32 && mag > 20) || (FLINT_BITS == 64 && mag > 40)) { arb_exp_arf_huge(res, x, mag, prec, minus_one); return; } wp = prec + 5 + 2 * FLINT_BIT_COUNT(prec); wp += FLINT_BITS; if (minus_one && mag < 0) wp += (-mag); else if (mag > 0) wp += mag; _arb_log_p_ensure_cached(wp); _arb_exp_arf_precomp(res, x, prec, minus_one, ARB_LOG_PRIME_CACHE_NUM, _arb_log_p_cache_vec(), small_primes, log_weights, log_rel_d, log_rel_epsilon, log_rel_epsilon_inv, prec); } /* Output of _arb_log_precompute_reductions with n = 13, C = 8 */ static const short atan_rel_d[] = { 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, -1, 0, -1, -1, 0, 0, 0, 1, 0, 0, -1, 0, 2, -2, 1, 0, 0, 0, 0, 1, 0, 2, 1, 0, 0, -1, -1, -1, 0, -1, 0, 0, 1, -1, 1, 0, 2, -1, -1, 0, -2, 0, 1, 0, 0, 2, -1, -1, -1, 2, 0, 0, 0, 1, 1, 0, -1, -1, 2, -1, 0, -3, 1, 2, 2, 1, 1, -2, -2, 0, 0, 1, 1, -1, 1, -2, 1, -5, -1, 1, 3, 0, 0, 0, 3, -1, -4, 1, -1, 4, 1, 0, 1, -4, 0, 0, 0, 1, 4, 0, -1, 1, 1, 0, 0, -4, 3, -3, 2, -4, 6, -1, -4, 1, 2, -1, 5, -3, 2, -3, -1, -1, 1, 1, 1, 3, 0, -8, -3, 9, 0, 0, -3, 1, 3, 0, 2, -6, 5, -1, 8, -3, 3, -3, -6, 9, -3, -2, -2, 10, 0, 1, 1, -3, 4, 5, -2, -9, -7, 4, 1, -2, 4, -1, -4, 9, -2, -4, -7, 5, 1, -2, 2, -10, 6, 6, -3, 3, 1, 9, 8, -7, -2, 2, -16, -3, -6, 6, 8, -16, 7, 15, 2, -5, -8, -18, -5, 1, 16, 2, 3, 9, 4, 14, -14, 7, -3, -3, -1, 10, -17, 5, 14, -11, 11, 5, -2, -19, -1, 13, -9, 32, -5, -1, -11, -9, -7, 16, -12, 1, 8, -4, -7, -12, -19, 0, 38, 10, 3, -14, 22, 28, -12, -23, 17, 15, -19, -25, -2, -3, 12, 1, -4, 29, -12, -57, 7, 8, -5, -21, -5, 10, 12, 32, -9, 10, 16, -24, -28, 35, -5, -11, -41, 26, -36, 9, 19, 17, 1, 30, -3, -35, 13, 27, -48, 6, 28, 13, -9, 7, -44, 23, 57, -47, -4, 5, -29, -39, 7, 39, 18, -13, 35, -1, 2, 67, -33, 30, -32, 35, -14, 46, -25, -24, -15, -36, 31, 4, 85, 0, -56, -55, 34, 49, -41, 24, -26, -52, 23, 57, -31, 94, 56, -19, -46, -5, -44, -42, 97, -72, -21, 42, -21, -4, 71, 8, 11, -90, 23, -63, 16, 61, -9, 22, -109, 114, -19, 61, 84, -48, -45, 44, 21, -76, -101, -12, 140, 26, -19, -55, 31, 5, -27, -161, -48, -14, 111, 98, 107, -134, 31, 80, 4, 123, 71, 232, 60, -122, -18, -89, -91, 78, 21, -137, -122, 48, 103, 72, 89, -37, -191, -114, 43, -221, 121, -49, 167, 99, 72, 3, 17, -213, -119, 78, -288, 75, 172, 2, 198, 101, 205, -144, 159, -64, -322, -12, -176, 113, 131, -113, 94, 250, 219, 127, -269, 59, -63, 314, -143, -197, -92, -49, -247, 238, 8, 29, -272, 474, 213, 348, 157, -13, -330, 5, 130, -235, 391, -279, 404, -313, -115, 955, 583, -50, -17, -661, -551, 609, 175, 206, 568, -558, -702, -20, 722, -845, -386, -616, -191, 401, -239, -149, 261, 315, -17, 1057, -120, 956, 633, 756, -363, 485, -946, -326, -317, 638, -930, 804, -651, 167, 33, 903, -543, -480, 743, -1215, -529, 1153, 465, 329, -1217, 224, 81, 827, 870, 400, -2055, -46, -163, -274, -403, 1386, -351, -103, -93, 810, 835, -715, 361, -605, 718, -504, 585, -1261, -2215, 1242, 1418, 948, -374, 920, 1589, 246, -1177, 431, 454, 1773, -1914, 2094, 273, -733, -1921, -434, 2756, 439, -4600, -1257, 203, -236, 170, 882, -709, 112, 1537, 1139, -33, 421, 929, 437, -1348, -726, 14, -2779, 482, -376, 4079, -2349, 75, 263, 2232, -1, -1422, -2336, 51, -1110, 32, -138, 1759, -1659, -449, 5580, -758, 3580, 2219, -3655, 621, -2663, -3013, 1514, 2122, -1830, 1379, 613, -285, 303, 552, -73, 1931, 1173, 2996, 2068, -1537, -6303, -1709, 3036, -888, -3248, 1159, 6910, -975, 1627, -4656, -2198, 806, 816, 488, -5351, -61, 2584, 419, 1367, 3654, 908, -3351, 3322, 3756, -188, -5526, -6717, 659, 1268, -2439, 981, 2491, 1399, 799, -201, -12786, -496, 817, -4024, -2854, 1994, 6715, 5058, 7304, -1034, 10766, 2634, -4717, -11608, 13220, -439, 4745, -4531, 877, -6377, 4026, 919, -2062, 6681, 8657, -13597, 2365, 10250, -15771, -3429, -3937, 7729, 7705, -6614, 3664, -77, 2758, 1687, 7487, -6228, -12131, 4700, -4955, 8159, -7737, 4290, -11033, -856, 8378, 2208, 11561, 12976, -4695, -3548, -6284, -9489, 14311, 1618, -11582, -2191, -5323, 2021, TERMINATOR, }; static const double atan_rel_epsilon[] = { -0.173476677351970227, -0.0223454388774785954, 0.00128205110644710632, 0.000288281360613411243, 6.85045457391394872e-05, -7.68170103583961137e-06, 1.88903816788068906e-06, 3.14107247522162372e-07, 3.60382589100899355e-08, 2.30422019129227609e-09, -2.44844124508091911e-11, 2.23459868879649284e-11, 3.2395002722044953e-12, -1.56086482655246759e-13, 7.86852949977718263e-14, 2.53358872969273241e-15, 1.36684250633406726e-16, -1.88898282274272967e-17, -6.11528577252688818e-18, 4.16106814336004848e-19, -1.15870736413119656e-19, -7.26808460743467943e-21, -1.34460335720689059e-21, -1.74879293883426177e-22, 2.42423537248796431e-23, 3.44752491607855886e-24, 1.27781124932914143e-24, 1.2549010572015403e-25, 1.03942931028640925e-26, 4.21297694421461175e-28, -2.92661121716782517e-28, 1.8230225414191675e-29, -7.69697348215511531e-30, 8.18317973694973991e-31, 3.3397435446138834e-32, -2.0652387701662598e-33, 4.12098270703490994e-34, -2.48239782714370514e-35, -2.09089355854803352e-37, 1.79284542976957409e-38, -3.1023746937711625e-39, -2.18563968265354802e-40, -1.58372422053366887e-41, 9.34770379319223233e-43, 2.45395255787610972e-43, 6.17759436911079761e-44, 6.74607123796430894e-45, 1.07933195581448629e-45, -1.12874568171945665e-46, 3.10654538624269495e-47, -3.23151092800219037e-48, -1.20395281889678775e-49, 3.13727375286930455e-50, 1.49070768725901436e-50, 1.1297354831437476e-51, 1.78899506256453627e-52, -5.40834261290673985e-54, -8.55551512269855731e-55, }; static const double atan_rel_epsilon_inv[] = { -5.76446364585990079, -44.751862135403158, 780.000106837595126, 3468.8333573567802, 14597.5714342801421, -130179.500000640139, 529369.928571585915, 3183626.00000002654, 27748288.3536313549, 433986302.081299722, -40842311491.4056549, 44750764645.735054, 308689586656.368835, -6406704686969.80078, 12708854939519.7363, 394697050977676.875, 7316131854005951.0, -52938543853354840.0, -163524655624849312.0, 2.40322908817470925e+18, -8.63030676213751398e+18, -1.37587831459347431e+20, -7.43713746243556868e+20, -5.71822985897115963e+21, 4.12501199903585143e+22, 2.90063168314230962e+23, 7.82588195654879406e+23, 7.96875573784298291e+24, 9.62066385952167685e+25, 2.37361849647250142e+27, -3.41692123003523425e+27, 5.4853956946770965e+28, -1.29921195950386045e+29, 1.22201886326005041e+30, 2.99424188307133198e+31, -4.84205513883266896e+32, 2.42660566930529655e+33, -4.02836317799479912e+34, -4.78264422362286039e+36, 5.57772568340442614e+37, -3.22333727775617956e+38, -4.57531956404596819e+39, -6.31423064088158743e+40, 1.06978143737104965e+42, 4.07505840644897284e+42, 1.6187530942468466e+43, 1.4823442633875291e+44, 9.26499020632979687e+44, -8.85939159011147709e+45, 3.21900978633207794e+46, -3.09452767538133538e+47, -8.30597332639932817e+48, 3.18748084729748152e+49, 6.70822327238893038e+49, 8.85162956214556664e+50, 5.5897303515555453e+51, -1.84899528667719736e+53, -1.16883669265794326e+54, }; /* Consecutively, real and imaginary parts of first 64 nonreal Gaussian primes. */ static const char small_gaussian_primes[] = { 1, 1, 1, 2, 2, 3, 1, 4, 2, 5, 1, 6, 4, 5, 2, 7, 5, 6, 3, 8, 5, 8, 4, 9, 1, 10, 3, 10, 7, 8, 4, 11, 7, 10, 6, 11, 2, 13, 9, 10, 7, 12, 1, 14, 2, 15, 8, 13, 4, 15, 1, 16, 10, 13, 9, 14, 5, 16, 2, 17, 12, 13, 11, 14, 9, 16, 5, 18, 8, 17, 7, 18, 10, 17, 6, 19, 1, 20, 3, 20, 14, 15, 12, 17, 7, 20, 4, 21, 10, 19, 5, 22, 11, 20, 10, 21, 14, 19, 13, 20, 1, 24, 8, 23, 5, 24, 17, 18, 16, 19, 4, 25, 13, 22, 6, 25, 12, 23, 1, 26, 5, 26, 15, 22, 2, 27, 9, 26 }; static const float small_gaussian_prime_weights[] = { 0.0, 1.60943791243410037, 2.56494935746153674, 2.83321334405621608, 3.36729582998647403, 3.61091791264422444, 3.7135720667043078, 3.97029191355212183, 4.11087386417331125, 4.29045944114839113, 4.48863636973213984, 4.57471097850338282, 4.61512051684125945, 4.6913478822291437, 4.72738781871234057, 4.91998092582812492, 5.00394630594545914, 5.05624580534830806, 5.15329159449777895, 5.19849703126582575, 5.26269018890488555, 5.28320372873798851, 5.43372200355423965, 5.45103845356570057, 5.484796933490655, 5.5490760848952198, 5.59471137960183911, 5.6240175061873385, 5.63835466933374576, 5.68017260901706731, 5.74620319054015322, 5.75890177387728061, 5.82008293035236172, 5.85507192220242716, 5.86646805693329677, 5.92157841964381554, 5.96357934361844629, 5.98393628068719041, 5.99396142730656919, 6.01371515604280175, 6.04263283368238142, 6.07073772800248985, 6.10702288774225429, 6.1246833908942047, 6.13339804299664852, 6.23244801655052274, 6.25575004175336692, 6.29341927884648152, 6.32256523992728402, 6.34388043412633092, 6.35784226650809956, 6.38519439899772545, 6.39859493453520758, 6.4183649359362114, 6.42486902390538781, 6.46302945692067004, 6.48157712927643106, 6.49375383985168629, 6.5117453296447278, 6.51767127291227499, 6.55250788703459009, 6.5638555265321275, 6.59714570188665149, 6.62936325343744878 }; #include "fmpzi.h" #include "acb.h" static void gaussian_rel_product(fmpzi_t p, fmpzi_t q, const char * primes, const slong * rel, slong len) { slong i; if (len <= 4) { fmpzi_t r; fmpzi_init(r); for (i = 0; i < len; i++) { fmpzi_set_si_si(r, primes[2 * i], primes[2 * i + 1]); fmpzi_pow_ui(r, r, FLINT_ABS(rel[i])); if (rel[i] >= 0) fmpzi_mul(p, p, r); else fmpzi_mul(q, q, r); } fmpzi_clear(r); } else { fmpzi_t p2, q2; fmpzi_init(p2); fmpzi_init(q2); fmpzi_one(p2); fmpzi_one(q2); gaussian_rel_product(p, q, primes, rel, len / 2); gaussian_rel_product(p2, q2, primes + 2 * (len / 2), rel + len / 2, len - len / 2); fmpzi_mul(p, p, p2); fmpzi_mul(q, q, q2); fmpzi_clear(p2); fmpzi_clear(q2); } } void _arb_sin_cos_arf_precomp(arb_t res1, arb_t res2, const arf_t x, slong prec, slong num_logs, arb_srcptr logs, const char * primes, const float * weights, const short * log_rel_d, const double * epsilon, const double * epsilon_inv, double max_weight) { arb_t t; acb_t u, v; slong wp; slong * rel; slong i; fmpz * alpha; fmpz_t r; slong mag; arb_init(t); rel = flint_malloc(num_logs * sizeof(slong)); alpha = _fmpz_vec_init(num_logs); fmpz_init(r); if (prec <= 10000) wp = 256; else if (prec <= 100000) wp = 512; else wp = 768; for (i = 0; i < num_logs; i++) arf_get_fmpz_fixed_si(alpha + i, arb_midref(logs + i), -wp); arf_get_fmpz_fixed_si(r, x, -wp); _arb_log_reduce_fixed(rel, log_rel_d, epsilon, epsilon_inv, alpha, weights, num_logs, r, wp, max_weight); /* { slong i; for (i = 0; i < num_logs; i++) printf("%ld ", rel[i]); printf("\n"); } */ fmpz_clear(r); _fmpz_vec_clear(alpha, num_logs); wp = prec + 5 + 2 * FLINT_BIT_COUNT(prec); mag = arf_abs_bound_lt_2exp_si(x); mag = FLINT_MAX(mag, 0); wp += mag; arb_set_arf(t, x); arb_dot_si(t, t, 1, logs, 1, rel, 1, num_logs, wp); acb_init(u); acb_init(v); arb_sin_cos_arf_generic(acb_imagref(u), acb_realref(u), arb_midref(t), wp); arb_add_error_mag(acb_imagref(u), arb_radref(t)); arb_add_error_mag(acb_realref(u), arb_radref(t)); { fmpzi_t p, r, s, q; fmpzi_init(p); fmpzi_init(q); fmpzi_init(r); fmpzi_init(s); fmpzi_one(p); fmpzi_one(q); gaussian_rel_product(p, q, small_gaussian_primes + 2, rel + 1, num_logs - 1); fmpzi_conj(r, p); fmpzi_conj(s, q); fmpzi_mul(p, p, s); fmpzi_mul(q, q, r); /* printf("bits %ld %ld %ld\n", prec, _fmpz_vec_max_bits(p, 2), _fmpz_vec_max_bits(q, 2)); */ arb_set_fmpz(acb_realref(v), fmpzi_realref(p)); arb_set_fmpz(acb_imagref(v), fmpzi_imagref(p)); acb_mul(u, u, v, wp); arb_set_fmpz(acb_realref(v), fmpzi_realref(q)); arb_set_fmpz(acb_imagref(v), fmpzi_imagref(q)); acb_div(u, u, v, wp); if ((rel[0] & 3) == 1) acb_mul_onei(u, u); else if ((rel[0] & 3) == 2) acb_neg(u, u); else if ((rel[0] & 3) == 3) acb_div_onei(u, u); fmpzi_clear(p); fmpzi_clear(q); fmpzi_clear(r); fmpzi_clear(s); } if (res1 != NULL) arb_set_round(res1, acb_imagref(u), prec); if (res2 != NULL) arb_set_round(res2, acb_realref(u), prec); flint_free(rel); arb_clear(t); acb_clear(u); acb_clear(v); } void arb_sin_cos_arf_atan_reduction(arb_t res1, arb_t res2, const arf_t x, slong prec) { slong wp; slong mag; mag = arf_abs_bound_lt_2exp_si(x); if (mag < -prec / 16 || mag < -768 || arf_bits(x) < prec / 128) { arb_sin_cos_arf_generic(res1, res2, x, prec); return; } /* multiprecision pi reduction not implemented here */ if ((FLINT_BITS == 32 && mag > 20) || (FLINT_BITS == 64 && mag > 40)) { arb_sin_cos_arf_generic(res1, res2, x, prec); return; } wp = prec + 5 + 2 * FLINT_BIT_COUNT(prec); if (mag > 0) wp += mag; _arb_atan_gauss_p_ensure_cached(wp); _arb_sin_cos_arf_precomp(res1, res2, x, prec, ARB_ATAN_GAUSS_PRIME_CACHE_NUM, _arb_atan_gauss_p_cache_vec(), small_gaussian_primes, small_gaussian_prime_weights, atan_rel_d, atan_rel_epsilon, atan_rel_epsilon_inv, 0.5 * prec); } flint-3.1.3/src/arb/log_tab.c000066400000000000000000004456551461254215100157640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #if FLINT_BITS == 64 #define Z2(a,b) UWORD(0x ## b ## a) #else #define Z2(a,b) UWORD(0x ## a), UWORD(0x ## b) #endif #define Z8(a,b,c,d,e,f,g,h) Z2(a,b), Z2(c,d), Z2(e,f), Z2(g,h), /* logarithms of primes */ const mp_limb_t arb_log_p_tab[ARB_LOG_PRIME_CACHE_NUM][ARB_LOG_TAB2_LIMBS] = {{ Z8(78b63c9f,897a39ce,1e238438,52ab3316,a6c4c60c,062b1a63,e8f70edd,3ea8449f) Z8(26fac51c,6425a415,f95884e0,c5e5767d,8a0e23fa,c0b1b31d,3a49bd0d,85db6ab0) Z8(c8daadd8,175eb4af,a892374e,f07afff3,0dea891e,8f682625,9c38339d,cecb72f1) Z8(ac9f45ae,5f6f7ceb,e76115c0,6c472096,fbbd9d42,972cd18b,bd67c724,0ab111bb) Z8(a0c238b9,473826fd,d24aaebd,61c1696d,2413d5e3,156e0c29,dc4e7487,95184460) Z8(901e646a,d7622658,d7373958,ef2f0ce2,c4e9207c,2ac5b61c,beba7d05,57339ba2) Z8(08391a0c,0060e499,6af50302,62136319,3d0bd2f9,05c128d5,cee886b9,36e02b20) Z8(f3d949f2,0bbb16fa,c9942109,422183ed,8c66d3c5,5e9222b8,6b1ca3cf,61affd44) Z8(9538b982,268a5c1f,fbcf0755,8d6f5177,228a4ef9,a17293d1,731cdc8e,44a02554) Z8(30af889b,96d4e6d3,8f969834,5570b6c6,1ae273ee,7598a195,b365853d,4d162db3) Z8(5064c18b,5f50b518,1b2db31b,078f735d,6c606cb1,ae313cdb,b1e17b9d,955d5179) Z8(17350d2c,0c480a54,5cfe7aa3,074db601,5e148e82,6a9c7f8a,3564a337,25669b33) Z8(d1d6095d,4c1a1e0b,9393514c,cccc4e65,b479cd33,c943e732,db8990e5,17460775) Z8(1400b396,7d2e23de,fc1efa15,ee569d6d,8fe551a2,610d30f8,fb5bfb90,07f4ca11) Z8(0f3fd5c6,da2d97c5,2f20e3a2,655fa187,38303248,f5dfa6bd,9d6548ca,72ce87b1) Z8(7657f74b,256fa0ec,b136603b,b9ea9bc3,317c387e,1acbda11,224ae8c5,3e96ca16) Z8(1169b825,27573b29,c1382144,ed2eae35,4afa1b10,559552fb,6debac98,e7b87620) Z8(8baafa2b,8a0d175b,7298b62d,40f34326,03f2f6af,c9e3b398,d1cf79ab,b17217f7) },{ Z8(26e78590,05885a11,f08484f1,b253e794,9bcced9e,1cd14b79,abea3dc9,8d63cfad) Z8(530af849,448ecf17,60198589,6f8b4b7a,51cae669,2169e77d,c54bba1a,01dfb4e7) Z8(a81391b7,2a7b140f,7557a3e4,5d25b77c,6baeac2a,254da387,2e7ac9f1,8748db97) Z8(b0417b56,c9934f13,504fcf13,f69f7136,b9cc4046,71c78f45,8ae9bdb7,632d549b) Z8(4de6bf44,6a32ec9d,1d092086,83e9180d,43e18425,035310ee,b28b4e7a,4a7b4338) Z8(c7c87ae6,d28ba123,69c04266,4c6d466e,d8a974fe,ddacd9b4,1863f56a,e2547da3) Z8(85224463,715a39ab,b369a2e6,0bc2119a,1a8e2e74,3e109712,3bfe61e2,2222559e) Z8(236af1fb,a9ea1441,cb4750ac,7cc5f441,ef3db6d2,0ab88672,f906fe21,5c557344) Z8(1a1d6d97,89efbbb1,01b44e9e,01e29403,c26414cb,d681bdee,d111bf14,5ed8404a) Z8(c2997336,3782a59a,26cd9a1b,89070a61,90849848,7fb8e5fd,04945d18,20232405) Z8(f59ce813,8d10e71e,6943feeb,93f329fc,10682df4,e36c5ad7,b9128d62,2d1ed026) Z8(8a4401ce,f1623751,2f6bfc3e,170472a5,b0b16e9b,cac8ccc5,d844a26c,31e54161) Z8(a748a225,e5025aae,a1d28568,64963b76,994c6984,0c418e3e,918d8b3f,4b01bb09) Z8(edb9a465,568d0dec,e459c2b9,54ec9716,e0a0ed51,16a0eb89,c076f0af,7f524cdd) Z8(1decb8d1,e4e236c4,82084c53,7a35fd89,3c51ef8c,f2ae6027,3cf832a6,684c2062) Z8(5a1f3232,94c0b741,dc410073,8f859791,fe48baa5,a3efb748,0f3a6852,43684a71) Z8(88126332,e79bec78,8f53de50,b12e0a83,81cd476a,2838fb99,06634c28,554bc169) Z8(28a49ac6,1ecbf775,dbf046f8,df0a216c,829dbe5a,520cc6aa,681854bb,8c9f53d5) },{ Z8(b2d7b0ae,177f4c60,0c7b2d0e,71640ac1,d2806a67,4b270eea,e4b45838,38213eb1) Z8(a0987db7,d6f2cf1f,93e5e16f,12f7ddee,53a77808,14e23f24,9434405b,b3d0582e) Z8(909a3905,111dbb7d,d36021a6,f7fb14bc,358198d9,c99e6bac,a30122ad,de4843a9) Z8(d73df8c3,66ca1c7e,8d2755e4,534cd5b6,d21cea0e,ec34ea8c,3b45f9fd,790842aa) Z8(9b5e4a4b,6fe2d6e0,7c860558,238ce8e2,d5bfca69,ed6dbd7c,c3140ef7,73ed7535) Z8(34198220,345cde3d,da225dab,bc161dab,b5b86cce,d741c074,23e32fde,af3994aa) Z8(6d2afd55,e8283f71,aa9c54e6,3cf4baee,540f4563,bed2f056,f893dde4,68cdd630) Z8(5cbfbf7b,3813288e,b02c54c9,7e894e6d,48eb8dc8,657c91c0,0b3a0546,69e509dc) Z8(763013a7,aaf53ec8,de4b8721,b2122c44,d358603c,0412bf61,483cd3ce,c97950e7) Z8(c28e9641,2b77864a,ea59a8c2,e7cc678c,bb4a8598,b838fe4e,137bdbcd,38a87af2) Z8(9b426858,e9b8324e,22ac9a86,d7103e51,498c250a,effc0f94,c437b4f2,a44dc603) Z8(b3394ab5,cc6fd02b,479bf94f,cd59b4e2,9053f054,bb4351df,4e6a8940,e9472b09) Z8(6a837b8d,390381d7,0c84781b,02992ba9,f2c98d1e,a64ac622,4e635c61,bc74e3dd) Z8(a5a9a1b6,f7a33fe5,31093d94,d1d24796,8c5b8361,0924cfe0,5cc7df69,c094ba8c) Z8(9e6be820,20267f3a,144b524d,83618fec,ecd91f7a,a23699bb,780dfca5,db6822dd) Z8(690793d1,100ba61d,bccc5dd7,81d84f7e,c8f247b8,5f4f607e,03f3adda,510e8c3a) Z8(7d15519a,e3735373,a17bb513,e22cf115,b3410d47,6e16ee02,2c5a4a6d,3881ca9f) Z8(3e0addcf,4285b156,7b6f9706,24a63860,03ac98fa,efbbd28b,6c699b57,ce020fbf) },{ Z8(6a96e733,9b307a0d,a4f947df,624b7422,ba147575,ad611e8c,f2104f32,d47f0f40) Z8(d775f1db,a0fa3e17,0e6e400b,93065dcd,73bf2745,c7df5bab,f05a13b5,737afffb) Z8(bd2ce8c3,9c9d602f,cd3ccd32,f9c7b0ef,4b0061b3,75b5572e,4640befb,bd1b7264) Z8(3d9b6ebe,63e55e94,d5f96442,72234400,2c007386,5611ea34,d73b429c,a9fd96b4) Z8(1c1c04cf,436796cf,9a1b4cef,f316356b,1dba181e,feaf9dee,478bf6b9,be673964) Z8(fd72492e,87ea7a8c,23c17294,fcfdaf49,c92c7a80,31575e11,a8b80ec0,f2762236) Z8(5551e6fa,a1f4aeca,65c0dcf3,7b7cccfb,d5669b5d,3d10333a,b0574a59,507a4f98) Z8(275c9368,d942ed5a,553c8ad6,0b5bf4d6,d0f5f7a4,ac53a66e,075a5f88,7749b291) Z8(b9795ecb,34f3de96,ad8de845,40f96b06,6960c0b4,614cb0c9,6c8eb5fc,5b47c6ac) Z8(4a66d682,9cd47241,db9dfaee,36792ba4,72de6b2b,a05ff15c,5b83072e,012aad38) Z8(208fffa5,df03dbd8,17de3ea4,e7dd93f7,e98b7751,36dedf5c,83a94323,1b993bd8) Z8(a54edbab,6a52cb1d,e98c9509,8a11f3cd,b47dfa47,55d7767e,8f364909,847882da) Z8(9811832f,eaf7b5e6,85c6a9da,6bdb1c5a,fb8c97ca,4bef7293,7562537e,d1f16003) Z8(49f66488,32b14183,c4faa9ef,46d8f3f1,f546f1f6,a1c34c0c,72987622,2deba261) Z8(9a13eeff,bf7b3c24,23ac8cad,ee445357,5ea3e08b,233aa45d,c8f1780a,9329479b) Z8(ca0e721d,91c3fcb9,ffdfb4a4,dcfdae37,037f470f,80d1c353,c665e64c,855edcc2) Z8(a5dd5ee4,cf0a4b81,2fbe1d2b,6c0df95c,ba503b59,48d1b5aa,439817a0,1ef0beb1) Z8(b97b611d,5732a55e,274e1ffd,261ae732,930df023,7b4a4b67,92d2baa3,f9139571) },{ Z8(5c0d6059,223a401d,aee0ded2,2517cd08,3c849fb8,5b27db5e,0adc9c67,5852689b) Z8(263775b2,093c10e5,0680db68,7306dbfe,75330cab,7745a04f,5ff9c83c,92f44bfa) Z8(18f8f1c9,ce4ac66a,d3640637,4c997143,ed00994b,eabd29a4,76dd652a,b07c05c9) Z8(6a843642,e656a972,4f0f60ec,d3c43bad,afe2d61e,49b27955,6300406c,cde8924f) Z8(dfabb559,1c6ac81d,d6cb7b7a,d6afc04a,1adf221d,1f187ce9,aeb9f096,45a5ba74) Z8(5cd07e15,fb355269,a777eab3,95078e67,4cf485a4,41e4deab,475c8dfc,54f733b2) Z8(21a71a78,aaa8a56c,5a3f2f8a,c645153c,cdc41d03,ebee644e,1c2a7353,14d73417) Z8(51d5bdb2,b5e4c8ed,482f058d,be7b0348,ab190f2d,15fdbc63,cc784010,414e2409) Z8(22d16c06,a42a2684,8f8ca765,0ac948b7,1a8574f5,5eb02218,5d1f1a17,e1936c8b) Z8(f9508eef,52b5b464,838a0739,ff76535c,88ca10f6,05d2cbaa,cb247261,e33d3126) Z8(c292ea3d,31700609,839b8979,9d509493,590cee45,add79458,1b53bb96,26e489d3) Z8(2295fa57,f7a924bb,dce8d928,515586ea,6723c950,06e10629,d0b06e23,203d1f28) Z8(8dbc7f12,bcf6ad6a,36fe8cd3,2d9db92e,8d5b698a,efa13161,0c38bb09,3e9a2dd7) Z8(b40576d1,eedfd1ec,63ef8016,af8363f3,4f4839b2,869b132e,60e8b63f,fded5b41) Z8(beb97588,257a48fd,89f46bc2,e694eb86,cb080b3d,17432271,bb0d5c91,b347c3b1) Z8(8ad2d182,b683c568,9fd2504d,925e19df,e1ff3466,4d3adab1,317c2374,ec674d36) Z8(30e79931,fde3b374,adb7c8fa,b71c258d,14fb72d8,ac5493dc,015ad951,198edbf4) Z8(d31d3ac7,55057edb,d8c396f1,4d69bb8c,3f697d19,e2e5fe65,f9ba5dbd,99771dbb) },{ Z8(e061c168,8e0093c6,54bc7678,552956f1,781b18f8,4b0e1227,29eff278,ab25f72a) Z8(b7ed53c9,6397ad3f,8110ff1a,3b19bb04,2b7327d5,dc4c01e5,2c27dd2d,3527ee24) Z8(57c2d2c4,94836f62,50c9f2e3,dc9fc08a,34d0de38,83823d41,88e0ec31,72475a20) Z8(06982678,44c2f8c9,89bf012e,761c17aa,e1eb5610,27a0432c,3249a397,c8881395) Z8(2273c139,cf0a3574,cadbec8f,06ef5dbd,2c088812,e4ccda8b,f4fae5a4,0866c116) Z8(7d1ece77,6a1ccc50,98b967cc,01d4abfd,437be6c8,840e3d12,432534d6,9e91bbc6) Z8(9fa0cfcc,c8f1375f,e01ad944,83166860,db1fad13,e7631cb8,496a22f2,459f82e1) Z8(7682ac9e,0fc694be,7efc388b,6116cfef,0741643f,89edf495,b38580f7,82825d99) Z8(0f7d7e7d,ae953f45,27d3f189,f555aad0,4ba11c34,5402905e,9c646aaa,767507b8) Z8(a4cf6b09,e7f1035a,b0f612dc,7f67e126,a05e91f8,8b45137b,f144d5df,7473d97c) Z8(1aa846e8,b4636062,d9675399,47bf2fa3,b02f7148,93df7a96,4dd0154b,14195805) Z8(c1b74c1e,340ab3f3,ad432308,688ce241,8b490ce1,fb84e901,d742822a,a6351f00) Z8(a30241df,497d930b,0c4229f6,a67fa254,0fef563c,1f751b19,1422993e,8b14a30e) Z8(2d4e84d2,221c1707,b8ae1300,542d56ee,96ea5103,5aa40dba,cba446bd,7ca26f0e) Z8(874de3ee,6e28cbe9,32993b81,da010a00,7811b08e,044396e0,5f50ecd4,32c7a8e4) Z8(d677315d,31f70a8e,49d58cf8,eb9305f5,bd0bb342,15ca6f6e,59f58699,bab0869a) Z8(a350d3ba,034b6758,1fea0ef5,a14cd0f0,3abe7e68,a764f12b,2c17d0f0,1dea3905) Z8(903f943b,a22109df,7da45a8e,c9dab82d,1fec1040,33ee77c5,8c6287f4,a4282159) },{ Z8(6c35010d,c90eba4c,1c32055b,2aa90200,f254362f,c939122b,9243c9d9,d6e30441) Z8(db97c53e,9fa52796,71f99d69,f98aadd7,81039adc,ffbc3489,fdcef97e,710de9e7) Z8(8db60b51,8e3f9e44,f514a396,a5ca1dc6,b771def0,451d7232,9be95d93,ac28dc04) Z8(98d64a20,ec5b46a2,fe3982e7,30aed1a3,f9c1f155,2f998e14,8d43dac7,f0086035) Z8(39fbcccb,53fcb959,1f0f4784,a5ef7d27,4dd7899f,8ea34f2e,7f67e3e3,76189ef5) Z8(74c575a9,5172caa3,22086e40,e710d190,f6ee3e25,4bb86257,6908065d,39ec3aa8) Z8(768bb8a4,9000765e,6881959f,dd127c4c,45b1bbca,3530bd4e,a65f3234,8b4c6675) Z8(11f3f778,d58c8b64,6adf6f1d,cf720cde,40b29752,922b8472,57665e24,6f07c9e9) Z8(b1e599c2,1c110261,038588c3,d7f4255c,fd260a01,f393909d,10f1a5ed,b492eddd) Z8(7e6e1974,2a51d6a1,0872a991,370a37b0,e767b95a,aa7f374d,b20ea681,fcd595d1) Z8(6772233c,d2fb2ffa,d0aa7cf5,533f043c,c1a34428,22d0f781,eb0118d4,af509e45) Z8(521aff1e,b96bb7a4,39d22b34,c39c2830,c1ad1cf6,5b578b62,3475976a,62105fac) Z8(6d62eddf,d7df4a82,59bb6fd8,6e808422,dc67c497,f0ad05f1,cc3d927c,399ed3c0) Z8(766bcdf9,ed81c67b,bdd83e2b,5ef55f61,bfdb4e34,920af523,2034b89c,215a6295) Z8(78b647bc,58458b8e,1d36cc7c,695a38e6,5eaca447,84f6ae08,836881a6,96b37fc6) Z8(b2126c21,da09ebdb,0e2ae797,ed23fd3b,3a6d7014,53093022,7a189550,d8d6486d) Z8(6f63672a,ce48110b,3b2272ab,93aae13d,ac68d243,f9b71bb1,658d3099,40152cbb) Z8(3168a03e,266e5f1e,5005ff93,75c51673,e15954d5,f97ce1c5,d3fbce77,b5535e0f) },{ Z8(1b46f9e9,bcb7bcfc,ee5c6c19,741fdc8d,7efa4284,a932927b,9d2648cf,cd0eb909) Z8(7b0163fe,681d90d3,13f59f8b,d836c6ec,6cd9dc99,8db2e81f,c8249b83,df3da68f) Z8(dd91c6ef,8292f26b,e4968487,b16de667,5fd895e0,88ec0c1b,541ab2ef,cc01d9dd) Z8(85875de2,9fbac633,c47d2066,867f9146,713adf5e,2b089a0f,7558bfe5,960cb865) Z8(90f7ed55,c3630ec5,deb7d49b,d7ff3c9b,6c7d5eb8,f30df5c4,36e8da8e,cffc3424) Z8(fe37a7a6,13665d97,068e4e4e,f36319fa,acae107f,9da617a9,5bf5e860,b0215128) Z8(7f9dc4d2,a4f438fd,a4566931,6bd58bd2,30128628,843e8b68,0f9aba66,9b3e6299) Z8(78701b6a,0a6c890b,8a137428,cdef2221,deccd156,7240cd91,4831ec07,d2329643) Z8(e120beea,1c6308d0,f9ec3e84,257f2206,a6761aa0,6022792d,8b055679,9b626711) Z8(2fecef5a,c3258e8d,3e20f805,8b41a8ac,030bbbd9,ad85d9aa,40d2cff7,f291dfff) Z8(6a88b2b8,7b6db797,5ec73177,c5d1d429,2fd1e9c3,cfd9fd94,91a00f3c,3cfd0a84) Z8(0d2db53e,eaf8f867,5d00cd41,cf88bf1f,39c140f4,5e9f067e,21b53f9c,62689d09) Z8(85026c84,7e63eb65,4fef7cfe,d4ef3573,1107c6bb,0912923f,77b6f9f9,538a0f4f) Z8(8b98746d,2b74055f,b6b0f78f,aa7b2665,01b07972,e97b1721,d12609a2,820159a3) Z8(6b32b80a,d37d7098,bb26b7e9,1a6a525b,0d515a73,d96eb325,50a505b8,38350ba7) Z8(150032a5,6b66b4c3,9bb912a6,9b3b2d78,a340af26,678d3458,2b9e1de6,93a147db) Z8(10411a12,92b54d63,2f5abe21,c01a5bdc,b84a64b4,bb8a662c,ae787116,6327359f) Z8(41f50473,fa385711,f215afb9,764a5ffb,9484d42e,03d4b89b,25996390,bc71b030) },{ Z8(3dd9f80e,3f2d7dba,c9909d93,d0480ef0,f622e15d,aedf3f19,83de762c,67219580) Z8(1c0648b3,c9b2022d,bd3f3c75,add44ba1,33499272,d3618194,c331042e,0e4af48c) Z8(0b32108a,18aea7ad,18de2436,41bf909f,1438a19a,25bb4f30,202873d7,7d85a621) Z8(807b1960,d47bdd67,c9a8829a,231440dd,fabed1b4,d925a3bc,f620e361,f79107ee) Z8(ac2f2a3a,3efdf054,12e097d2,43226ff7,a0ad9f8c,17068f81,a0e03f1e,f384f6a1) Z8(39785dce,7f2ff85f,4d2ffdf6,a2071cd1,1a834017,e40b10c6,ff6431f5,4028276c) Z8(4f2ac9c4,c112d26c,abe147b7,30ce2b2c,87e8d525,a0f595ba,35aeb0ac,9ebe2ebf) Z8(a1375f05,e3bde836,a9183bba,503c87df,8be95c88,c2279b1f,7e897065,4e7eb400) Z8(55171691,cb256897,46287c3c,2311f249,0a4621fd,6811479a,4f21de0d,f98a89a0) Z8(edba7189,0b1ef528,1010897a,13430dd2,c7f2f040,12ca474f,53875d86,f4c2db5d) Z8(6d3aa776,925a3959,317cbe7b,2d8d1fb8,60203c46,fa6a8a42,792ca7e8,7fb70904) Z8(c6bd484e,3566d22c,afd1d9e6,f89f9cbe,224c4b42,250f84c1,4d41ee40,4e3fba92) Z8(15cee945,f808ce55,87fd6a7b,52766216,9db45ee1,6271060f,174833b5,9d1bd58a) Z8(a842c292,70c47fe3,7faf0172,93f85744,c12c4171,fb63a346,e9bea813,171754df) Z8(569440b2,a77ffcf1,200b63e9,564f11f8,2987f784,4b9bb3b3,e3e2e585,3756b1de) Z8(0f407137,d5695cce,f1be35c2,98c078c4,5b2a7bd5,cb4e4aa6,1e243883,63eb7d8e) Z8(fdb6fd87,6f3005b4,a734b71e,253f4e33,327f43ab,06bc321a,c09d43e3,7bcfc190) Z8(d47c15ec,7931b56e,1bfe8c1c,f86b869a,d7e27019,ac300792,8d9f8048,c8abefee) },{ Z8(011abf71,20b0f213,cf3f1a0d,aab02a15,5d79e76f,617ef635,d3f1484c,6fe7eee8) Z8(deb370df,a7ecdad2,bf81fd89,c86d5651,0666b358,a3933f06,f959fa76,9462ca48) Z8(73aee478,654871c7,ba5ec947,5d804c34,707f0d2e,bce734f6,dbdd9d2f,ce0428da) Z8(92dbf132,b78f185b,41eb84b2,953f7946,113898e3,f05e740d,1a53f253,f7360265) Z8(cf088b94,175e0fe7,16f6e924,5295cc3f,a672a273,abd45f65,e485dd39,bb738a7a) Z8(71df7d70,cb834c1c,69512488,93428c2a,43afaffa,c19c66e4,ef11f3e6,4ec326a8) Z8(3aca0dfd,4178a9fe,7937626b,50f499e9,9ca71091,a288b803,7ef83c9a,f6913738) Z8(9ba2263d,9fb1092e,68d62a1d,a6952b89,9ece8221,4df9997a,cfe28c1d,c7c301eb) Z8(dec8b920,2b213942,58e3f45c,148151b3,6bca7864,0df8f741,4f14450b,effdd51c) Z8(d000af47,cc2756ee,58762c0e,3216bf99,bf96249b,47b0bf3f,2c903a98,f6d5094c) Z8(b8310813,7d618dd3,b57d0538,41306942,03ec0edc,99c2a33a,69996360,a0fbc315) Z8(66ec0b3c,165b7567,81cff3ff,61df1854,b13c1660,372c23f5,cf36cf9c,47bc7fb8) Z8(a9f31f5d,ec2f12bc,1fa0fbad,15cf7b80,ff83615e,f2947d0a,d9a2532a,3a001956) Z8(586a7e9f,18a6f389,96761139,2df0aeb0,f384af10,a8861e65,296e5ad8,a285abda) Z8(6463b7d7,00985375,e0f67775,09cf57c0,bf54c999,554ea724,e9ae6a0d,541a419b) Z8(8d4c86d6,b20626b6,da01a3a7,6599e12a,7e00097e,3cbdad73,28baa6d9,9b1fc158) Z8(562aedd5,de206cce,34e2eb02,3e844f01,9f971baa,f77d3e8f,67bdec7e,5ca79b0e) Z8(a486773d,da1d9982,52df24d1,43cf47f3,d1a67235,3504f782,6ff0f5eb,d781c65e) },{ Z8(d8c2492f,58b42a1b,85dd4962,6dc57002,41f060bd,3ecef8b7,bdfb0f82,20a4dc9a) Z8(dcf06623,29ef7f53,c62854db,1bd4716e,070d81cb,353016cd,3e63aed9,0cc34ac1) Z8(c4a39784,13eeb43f,e285fb37,64b70216,dccf112f,38c03dc1,27d0a877,367925cc) Z8(bc77764a,5b4c538b,28570fd0,9374362b,4c80788f,1d7aeef0,e75427f6,350fb9a3) Z8(3b2cb911,0ec23bb3,727db31f,3307853c,eb29de51,763dec87,117d52c1,bc1c45cc) Z8(db4f8c67,da38cbe8,e508b512,0fcf9fd0,99c942f8,965fce33,4811be54,ef9e3b27) Z8(3581637f,d594e77d,12f722e0,8e199213,81f0a747,b33e4a46,0500a47e,a7c62b37) Z8(45d21c04,ed4a78a9,9fe7f2f8,6c032450,f355095c,0565d9b6,c63d04f5,225608f9) Z8(c28d6737,83c5b1ea,29f51118,e1f21057,8f2cdd3c,6d0288ac,3ab931a7,cc407342) Z8(5aa2d76a,3d146b09,1ddc9a22,f55af573,ed802d76,d4b2e022,6771ce7e,1dee98d3) Z8(e1961e1d,5a34feb7,1d92aada,a77a769d,9b17ac0f,e16b5eba,4d138d88,2602bea5) Z8(e98df7a4,bdc6ce85,8d69f3b0,74866437,eab8d9dc,25149c6d,ebc3f439,d4a4b414) Z8(5d7a6c56,8c4341c9,2782efb9,061cfb33,46f2517d,03496a93,a575b025,55f04f64) Z8(4ce4e92b,93e29837,9a0d9d20,d87cd8cc,7764343b,aa714875,1cb12f19,d973e014) Z8(e6a86d0e,210d72f2,2c7cf809,cb016510,85be5fe1,5ff58355,6f9fe0f9,dd30aa2d) Z8(6f9a1559,eb11cd80,c9dbb4ca,75c11076,975237d2,db6a84d6,f702ec66,36ed9de6) Z8(01e18fd5,09f6d21e,b6d5f8ec,5c26b100,c634e2e6,165cdf13,7d79b3c1,da3d59d8) Z8(56203500,32ef44e8,05a722f5,f517c701,69dea09e,b97511c3,895acf88,dbc67244) },{ Z8(b04de533,da9e13ab,b20a66f0,6cdd1d45,b2b30713,505f7126,cddd4f08,c2d10b34) Z8(37492345,d2c80b85,dc96a5e2,a506bf85,2cb10cec,d742d631,02bbbf2d,042ecf2d) Z8(5c17ab87,4b3971ef,db60f7d2,82b6c83a,20c9daf8,9c258d59,78790e71,1e247177) Z8(59a806cd,cae9c3f3,504c8013,847e2edf,8c88cfaf,478ab766,d3d1143f,072c4a01) Z8(8f69c701,556cf004,aa520ea2,9344456e,aa65c974,bcdf4e57,1b4d549d,fa368234) Z8(2792e20a,52eeb32d,f245c761,66b8e52c,68594996,6be27c0b,5f5906ac,51c628cb) Z8(7978f1f4,f8c746a2,7ebfc1a9,1b1d9032,5f3b863b,f9b71f3f,399177d5,2ae02d23) Z8(edb7bba9,38a08903,bc50b569,3ecc2953,0b534151,2c2c4050,48bf451c,1694717d) Z8(87c80690,7fd4c793,64590a45,108cf924,0865bc48,600a03ed,28867398,cad6d2d5) Z8(269c8e38,21c46752,dcce15ea,0bf69ba4,45eb1942,3d76f42b,cc7a591d,b0bc4b1f) Z8(4ab494f0,c3824266,503a075b,f2268fab,656f88b7,8f645d4f,4e2f2858,8576a646) Z8(219d5b82,f4ded809,fe05237e,5233e603,e4e7e349,0cb7f766,da5d8b96,a83cce0e) Z8(6e6846b6,e953448c,fc68b833,4b1cbbb2,a2b86b23,6c4b1e4b,ed2092f8,5cba930c) Z8(11ebf18c,5b7fc0cf,42a42078,b139eb5f,649b97be,f0f2131f,f9e9f169,e2dea833) Z8(9e845510,3e49f815,4a762305,e59207cf,d7c9f50d,0a6fdf45,593248ca,136163a5) Z8(bac1a453,75f35780,274828df,1e7d8ee1,0bafc100,0e43677e,2e332b09,e19f38d1) Z8(c6d03079,031b863d,5014f329,83d67574,ab6bedde,63e111f7,bb6c797e,51225f3b) Z8(2629ed87,3a1159bc,eec962a4,902255b3,006ce89d,bf4ad8ff,d63de9bc,e7194771) },{ Z8(5dd6edbe,2eb4f5df,4579aefe,71386986,60c8d7fa,47fe42d8,c660876b,7ccd88d5) Z8(a5ee849c,4061a56e,450342f9,dd1cdee0,49580e14,b2a04a1f,50f2b397,2215037a) Z8(6ace8b1c,f073f888,5ef32ccd,409ece8b,1c3f8e1e,ca8b4179,0d8851d2,4ac533ca) Z8(90fef0ac,f6a1494f,217f2f83,f4b39e89,b256b1c8,59e1a209,6c339a64,31b6f66b) Z8(467fcd69,f90e546b,acbc77e4,562518da,0b5b1a7e,db5f1bdf,cde88961,93e406d0) Z8(a6eb4af4,5b8f28fb,3dfb03d0,8eef805a,0d87c33c,1eba2dac,452e5351,51675084) Z8(2ea8e4d9,61c119f1,555728fb,e5b3c4bb,1b1f51a4,cabd4792,1171dbb1,0cb0e649) Z8(a9afbc15,8d8929cc,8243bb25,0f83c66f,80b12741,13115907,31754c32,fa495a86) Z8(11edcebf,0f0d2333,c30d0fec,a44a19db,be82bf19,afc594fd,cbbf4ea5,601c6d03) Z8(9238808c,b4deb22d,34587001,f99b9ad7,ec9d896b,2b345bd3,afd7e661,53e80d45) Z8(c8b12250,c14ac828,17db9653,04653ea8,cbec1d9e,9887a611,e85d0406,edea53e2) Z8(749af5c4,6a508049,07637136,8e39fd4e,e806b310,57952432,f514c7ac,7fdca741) Z8(0f43389a,9bf92baf,0e9b2547,e6e89860,451c2cd4,11cb233e,d2eb1c35,8f4e9461) Z8(d4d92808,510d4471,c67a3427,14747b55,ace488f0,5222c791,3638c118,ecc33078) Z8(295e169a,fae9dd8b,f272e5a2,90c5e54e,15cfb43c,bd8c58b3,35941995,c71e62c4) Z8(ccec6568,d32cea7d,1b1fe429,7193aba1,67412fe6,793b7391,50fcfda3,75478d31) Z8(5084516f,ca167108,025cbac6,99db5a82,5ffda43a,dcc0444f,62c91046,9c18a32c) Z8(c8db7021,b2283a67,7bca0417,a1462505,cf59195f,66ffd699,75626d5d,edab2a2c) }}; const mp_srcptr arb_log_log2_tab = arb_log_p_tab[0]; const mp_limb_t arb_log_tab11[1 << ARB_LOG_TAB11_BITS][ARB_LOG_TAB1_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(90d465bf,d4520ee2,9bb0f82e,d99e1b46,facf68d7,e4c4a44a,51bc9855,d122f7ff) Z8(6b5788c3,76702788,f9a073a8,b3db2c3e,1dc282d2,c3769039,b106788f,01fe02a6) },{ Z8(1ef3a140,e808e153,3b4ede62,ba7510a9,8f9f71cc,7841aece,758dcd0b,7a59b490) Z8(77122f83,d140fe05,3ddc5335,eb03be90,6f57aadb,f3db4e9a,1f807c79,03f81516) },{ Z8(31e125ae,9bb5ffe0,140b9e2f,086d1607,45ddab78,67ded6c5,0efcad2b,d0f00eba) Z8(3a835116,96efb673,87466226,53c40a94,5af00773,49fd531c,f56c46aa,05ee46c1) },{ Z8(7cb29271,02127ef4,0f6e3a39,9ce34431,e0a5d2e3,55d9a7ba,ec979e9d,8a38a3ff) Z8(e3673dcd,df6c758f,ddf35ad1,aefae14c,ef229fae,3e3f04f1,9e0cc013,07e0a6c3) },{ Z8(12db1d0e,d5872e70,d45e4a00,5c3e9eb0,48f34c0f,28b7bf29,3fa03b71,747318fe) Z8(a91dfcd4,d0eb0381,f4c603a3,5eb87846,5c8a7235,80ad9015,ff5eafd4,09cf43dc) },{ Z8(5d61ffe8,c6e2905e,afeeec68,457ce7cd,97a6304c,f5c2a876,9f71bf4e,e9b91ebf) Z8(a3a2b779,7d674deb,a89d8cb0,9bf701b2,252c163c,1a7950f7,196e7e23,0bba2c7b) },{ Z8(b0b4ed5d,212b939a,5665b730,6f275dc8,647b0999,766e7cbf,7d96a5a1,1abee2d1) Z8(9e448511,77778bea,fc53dc9e,bce26340,fb66e94a,468a63ec,8cb8df61,0da16eb8) },{ Z8(77e6bc16,9bc35789,e7a9459e,99f0cc1d,85badcca,908722d9,de861006,6172da6b) Z8(96f69849,71851f0a,75b52596,d3474d33,75997898,be64b8b7,08b15330,0f851860) },{ Z8(fe8e2388,8e4540e2,7a5a64e0,8b8cbbc7,7b015b41,0d7918c7,2c6a3b15,8b8cbcb1) Z8(264acee4,37e6cb88,685a6aad,a42905a6,d325e46d,625c173d,a37ae0e8,116536ee) },{ Z8(9e866ba2,9fec8cce,3429d182,68413893,0bbafb1c,69e2cdb8,7bb59c4a,2b83c452) Z8(5d37b037,e6103880,78467950,1a0eca5b,4d137502,99837610,1bd1d092,1341d796) },{ Z8(9de15b17,ed9027ae,f8ee1435,bb355b22,f457addf,3e6b4fb0,e7a295c0,84d7db82) Z8(7aa339ed,96961165,c3e10deb,c9c7e09b,2f91584b,278e686a,06183f69,151b073f) },{ Z8(eed4c843,a047161c,dc5afe2a,fa8c6dd6,644009ed,c1e6a872,ba4a6521,284ac3fe) Z8(34b59afd,812f38a0,087fdf23,50c1ef65,19b640ce,e499b9ed,e56b4b9b,16f0d28a) },{ Z8(c69d37d7,d1080d7c,1025284d,ff89c5d4,5de8d145,cecb8c1d,5115bbde,0ae26ff9) Z8(00e87966,799d33d0,d7c4c4b4,02603e40,edab4357,acb42a65,319b20f5,18c345d6) },{ Z8(427b81cc,48646831,a02b9473,7748a795,ab52ff3b,f726f31b,7818f6b5,ef3f32ca) Z8(2911a622,eab11fa4,d398d01d,9f67e22e,3aa4c79a,0bd22a9c,4ad56365,1a926d3a) },{ Z8(d6fdaaad,f159cd13,edfe76e2,e55d167e,3211078e,f7d0cf3e,b458f0de,87d91901) Z8(bbc664d5,163e7f6c,3772cac1,966af8dc,61b1769d,d617ef81,5bc74315,1c5e548f) },{ Z8(ec0c6459,286a0066,f9a71577,fd2c1f6c,2646cc77,a023f574,cfca2ad7,9e05a342) Z8(ff917c95,dd0897c1,17f6f957,b94ebc40,fe9e155d,ea87ffe1,2af2e5e9,1e27076e) },{ Z8(d8f25186,2c05bc00,cdfa2d56,42245ab7,d807cbc2,630d9164,f63a8eac,8d96c694) Z8(3c82c160,27262536,202ec615,91e2ba81,324e3bfe,2e5199f9,dbeabaaa,1fec9131) },{ Z8(48281841,03ee435a,cbb335eb,043a6981,289698cb,d424a286,d8c48b9f,17139cd6) Z8(8c17ff3a,80c71686,03860ef8,4cb4fd8d,855d1c48,2ee2f481,a11cb2cd,21aefcf9) },{ Z8(2db638f1,f7fe68d8,95174873,964d36ff,e004bec4,1ca388fe,19b53ea7,d04f42b4) Z8(6589e2cd,d406e0e4,32ec12a6,8fd90995,35ce7e77,0c08d1cb,5ecf4052,236e55aa) },{ Z8(c430292d,47b9f129,7a3b264f,6d706ec4,36cd3025,e399a8f6,c81786ff,bdef2e4c) Z8(de50d341,3603f226,7e29fbad,fbc9070f,edf4d109,0bb8e203,3fea4698,252aa5f0) },{ Z8(2e492011,ca484bb6,960168fc,50a7553d,815edc13,727dc7fd,ca360847,3dce1f32) Z8(e20dbc5c,744e54fd,5290329f,f326daa7,627f2e81,9b2d8abc,3d1ee877,26e3f840) },{ Z8(9bffbbee,70f9c3c8,1d45c958,5bf7c41b,0ec2218f,074dbd5a,2aa9b674,1e4be88c) Z8(0372cfc2,0b60281e,f60aa4f8,caf99174,fc3c1882,a7b2a1f0,96fa3ccf,289a56d9) },{ Z8(08278a9d,0cfa87ee,59700ee3,22d074e0,8ae86452,c8651fb1,23162370,7c45f286) Z8(a66f4587,b14f7cda,8aa87317,98c76a88,96334db7,c803adc7,43686f45,2a4dcbc7) },{ Z8(fb5d87b5,ad7848e7,b88a7375,4baeb699,b541268f,97d44cc5,023311f9,edbafdfd) Z8(d928291d,c0acfed6,fdf3e631,d55c7355,424775fc,e7c4140e,4f27a790,2bfe60e1) },{ Z8(63f3206f,c42d57f0,e1505b15,971ceb8a,ac01a942,30ab184d,ae503ade,ff787dae) Z8(968814de,4e8db6cc,8dac1eee,8c960973,74378df6,a8ecb899,33a4391a,2dac1fce) },{ Z8(a6ded1b1,a99801dd,8f0a96aa,257473ac,06b19fb0,4175c8e2,f91588f5,35ca286f) Z8(7969d04f,c62cba07,021656ae,fc2929b1,0c100c8f,c6d65ad4,21b21237,2f571204) },{ Z8(87ccd984,db5f513f,d5c664fa,b8ade2b5,727ee8b2,de8c1375,4d29abb4,83edc1bd) Z8(02e9b86e,8a6cd2cd,eb4ebea2,5704b6b7,932ef5a5,401202fb,41922120,30ff40ca) },{ Z8(46577c95,17b14e86,d8375221,45a5f1ba,77b20123,421b1cf7,978b7d19,9ba61844) Z8(d7f0a39d,13daa19e,71766947,a0bed3cf,712cec4c,8260ea71,e8ad68ec,32a4b539) },{ Z8(b58674cb,1e544a43,07d3dd44,0d91f714,43732b59,d7c1d20a,d4945cea,a048eef8) Z8(c2c7880f,99f2aab1,65bcc380,e36cdb16,33184fc7,6e2360f5,c56ac632,3447783f) },{ Z8(7d1d4ffe,3b6ab9a1,6c95595e,b5322b03,8124d050,b9509e41,adc20980,c52dbae0) Z8(036bf0e3,7622eb26,d50ca14a,69b8b9a5,99eb9767,9cc0326f,017fe5b1,35e7929d) },{ Z8(54f5bfa1,148f89ff,84d501a8,c271e752,7a1bf371,87f65b0b,66f4429f,e6ccfad9) Z8(1118cc85,cbd35203,079ada33,87b948d9,3d53c3c5,f39d121c,5b19ac53,37850ce8) },{ Z8(d75732ea,78383094,c087279f,e9fc85bf,d08de46d,3103360e,7cdd3baa,a192a8fd) Z8(64bfc746,70f133f5,11adc1b1,c765ea74,ff734495,4bb03de5,35344358,391fef8f) },{ Z8(c8b2aae1,47720fb7,b3c62df4,f0d2680e,31c6c7e8,557eeedf,883386a2,d71548c2) Z8(f33a42b8,ccd07cf7,9c69752d,673d12bf,6a00e1e3,221acbf2,9f7722b7,3ab842d6) },{ Z8(d818c8b2,50d400cd,f34e2aee,fa583ed9,4c8d98ef,4047eae8,9f9455af,3c0b4685) Z8(ff22f92b,ba112f83,2fedf2af,729d7880,fd3c2abb,d50fffc3,55e5cbd3,3c4e0edc) },{ Z8(2aa5fc55,51af64df,60784393,56ed2331,e4ebb654,1f3c6b40,82bad112,4ec45e67) Z8(19f5f6a3,a5834a1a,a47c3a3c,a5098683,106429f5,31bca86e,b8b26ca4,3de15b97) },{ Z8(eb00ad03,63a59c53,435a44c6,c58402fb,09140995,c7167255,6589e221,e9c83e0f) Z8(6916ddaa,165f74d5,b22c817b,40584455,29a59412,aa8cd86f,bc7c551a,3f7230da) },{ Z8(5409c55c,7a4aaf89,cff561d8,86dfc9f0,b133b751,86dcddc9,6974da47,2bcb4cfd) Z8(48270514,505da985,efa11c83,7660cbc0,ee95e444,89ef42d7,d341036b,41009652) },{ Z8(b593b0e7,5fdd4e11,5d032b5d,c283489d,bc5a554a,d18ef4d0,4166ef5c,154ca709) Z8(7a329bfb,dde3a1dc,0972de36,e035afbe,c030e28d,cfde8061,ce438d7d,428c9389) },{ Z8(b5e7b48f,d76ad167,9d09ded5,2c0c163b,c40830ce,61dab337,515ef682,eb3fa702) Z8(2e0e2fd5,e31965f6,3912b4d3,e58b9bf1,cc73e14c,7e82ad32,b92b5462,44162fe6) },{ Z8(1638a398,cfef8350,794371e8,85bd4ee8,4c529944,8bc0169b,dc48152f,499727b2) Z8(95940f17,c3c8dc39,3c19f534,067d04a4,1b8b823f,731f55c4,ae98380e,459d72ae) },{ Z8(a0a294d1,06f89ca5,b6c78ecb,8e1fc408,c91d35ce,e412447a,5f4ccf5a,99468d46) Z8(b04fcaa5,4aacab7b,caf5d936,882eeb5e,e3bbc33b,1a39d500,a667ebef,47226305) },{ Z8(4f3def00,13fb881e,a8306d3e,83ed51dd,5648c138,c18a58e8,5b634bb0,03058369) Z8(fbb65f90,e27652ff,8762e747,9aad37a7,750cbd2e,0a14f69d,3de59689,48a507ef) },{ Z8(e769ec0e,d5e2494e,b23188ec,48dad606,db87f307,37f84239,d1fd3cd1,8bc0a13f) Z8(d8b9a5b3,9db59698,15eadf89,8eab2f96,40e58b5a,d24c13f0,7a1a8d7a,4a25684f) },{ Z8(a3830fa5,53c8ac43,ff797e15,519f62aa,8d291024,3f7d530e,20cd5936,f5fc616e) Z8(3164478e,4cf26755,26f15213,77ad6fb2,206cf37b,b3246a14,8474c270,4ba38aeb) },{ Z8(c2614cde,58defae2,55731574,0957c917,ae0ffe68,5ee0ecb5,589a72d3,8bec4a7d) Z8(ccdd5195,7944fcf1,61deaff0,14b01676,3043dca2,159d3fb7,61f55359,4d1f766a) },{ Z8(00562cdb,5bae2934,6ae2a114,cd553bc9,c01a5b18,2ce6ff8d,18383eba,aee32a49) Z8(9d61357a,69bfc8cf,53c8dc26,479dcfc0,34237d6f,bcd735d0,a517a71c,4e993155) },{ Z8(c62bfb2d,187f46b1,9ce225ca,e488f396,34cdee5b,f2e9de81,3727a0cb,c9dd6cfc) Z8(99756243,f2206c95,1a2da0d4,1827d9d9,19298564,3049f7d3,1a9f8ef4,5010c21a) },{ Z8(8f613c57,81891c55,7336c01f,14e48b95,72ff7a30,b092567e,bba85f7d,af120d6e) Z8(a973fc98,b5eeb55c,0b44393c,72cd24c0,f1cd1057,2decdecc,717b09f4,51862f08) },{ Z8(364f586a,031e755c,fdccd96a,b5f790cb,ab6cfc39,4dc65b36,e66f28fb,973e059b) Z8(5b6423f7,6b656878,d2f053f5,53458673,f6191eb9,326527db,dde2836d,52f97e55) },{ Z8(698a8e93,6656eb99,c5bc69cd,7cf05d1a,53d7e4fb,59dd7433,f28d4eb6,530626d4) Z8(eb0a988a,1f9a5c5a,f5c12be2,e9e6af97,abc623a9,24f5833e,b7e0b427,546ab61c) },{ Z8(8667d12d,039642d1,32197790,f694717f,4d975abc,daacd3be,f128ae8a,8cdf71b2) Z8(f884f564,314796aa,3f7be028,b8343319,60bd00f8,6adb2836,1569b152,55d9dc5d) },{ Z8(c3639743,a0a230fb,ba2e3d16,e728a52c,f6d4b0e5,d1272b82,4ca76681,3f984c40) Z8(645143dc,4df9cbb7,29a4bb09,80b4a6b4,fe1159f3,36383dc7,60272942,5746f6fd) },{ Z8(82541b8e,6a800985,828e3253,bc837911,58ca07d9,42a51959,1cfcf075,8f0834da) Z8(512b4182,0b2333cf,5fd12d40,9b157749,0728b9c8,bd7c8a98,e71e54bd,58b20bca) },{ Z8(7083bbd4,bf36d16f,57d3ae92,ce372136,9dbdcdef,2db73e1e,a4096771,47379cb4) Z8(6df3361f,fa9ae616,95996523,eded1c33,8e1a592d,0af84053,6c52bb11,5a1b207a) },{ Z8(23ee0a2b,dd2941c2,44bb4bc0,603b6420,b20273f7,d7723dca,0c449327,fee3c8c7) Z8(bedf033a,856f669f,81f708d9,ab9f4e65,5f0bc0c5,4e4c635c,ae878e30,5b823aa8) },{ Z8(b1351588,1f632a2f,97f25769,e0427ff7,9e14a268,c49b7c7b,4ac65d2a,505d2dc1) Z8(23446f02,bc92784d,a59757bb,dde10dce,4fbde5aa,89314feb,ef401a73,5ce75fda) },{ Z8(9b875c17,bff221be,3ac24dee,576cf484,075b1493,149cdf05,44f4c2aa,5f81d74a) Z8(43109a88,a6f5261c,8fd7bd5e,c32ef183,ed68159f,57691fe9,751e89f0,5e4a957f) },{ Z8(af30b4d9,0b07be72,72aed8b9,43dec3c7,5a917809,a865819e,6f275bc2,a53a2571) Z8(63c82c88,cd067666,1ee8d4b3,0cbfcbf7,95043716,ce979ed2,0abf0d92,5fabe0ee) },{ Z8(0747f86e,1d4c73df,5ae005be,aed557b3,f8ba56fa,41197957,9a2e6f84,1084e7da) Z8(406a94e2,2773d467,80f95ed3,461471f3,676688f0,ec519784,7a2c5d24,610b4768) },{ Z8(d94be1bd,507eaadd,73edae34,778b0d38,f0427892,29843ae0,20267cbf,2fbbd968) Z8(c6f53831,501f739c,0515a31f,c63281b4,f055b3ff,9c620440,05096ad6,6268ce1b) },{ Z8(024507f1,f85983b7,72ea875f,82e96e55,729965bc,2be40c0f,ac124007,e79ccaf5) Z8(95258bac,a0d173fb,5410ee8c,bfcbc0e4,1a29979c,5da755a6,d98b1df8,63c47a1c) },{ Z8(d2b4ba9f,25b0797c,79119b15,35ab3c59,85cf0afd,c8d782d4,7f104da3,8f4da6fa) Z8(3de7f064,319e32cc,0fa1a7e3,9cc25dca,41baba92,337451f4,845beae9,651e5070) },{ Z8(bd1d19ce,ef36c7bb,244db6e1,cfc3fac0,1fc77988,ff4f6e88,5a75462f,129be5cd) Z8(3ffdd7f5,ec7c7be1,251912da,db8e4afa,0c6fdd25,a4bbb11e,5f822b2e,66765604) },{ Z8(febb0e3f,a7e09dc7,5d6f9b5d,752d66d1,b8a073c4,fadca437,9edaebb7,c2df0cb1) Z8(c59e3b60,b38ad78e,4547d7c2,7d20ffb3,01488606,da35d9bd,fe612fca,67cc8fb2) },{ Z8(3ad738fe,faeee814,e0205868,d2abcb73,111baed5,9faad02b,56cb539a,c15be7c7) Z8(fc13c079,03289542,c6bda28d,adea18d6,d3a4b273,f29adc3a,96ec28af,69210243) },{ Z8(181342cf,e875edb0,573447c1,871bbf43,7df08a48,2fb43fcd,adf8a19b,c08704e2) Z8(763554ce,f35aa69b,768c44e9,1fc8ee26,950d7be1,213fd4bc,68212635,6a73b26a) },{ Z8(1daeaf7f,8fe97f1b,98be79c0,2fa2777a,483fe591,731e5306,1468b8c3,3d38c142) Z8(3cb06ae4,84cbd594,83242af8,6824be43,70a030e2,ce112857,1de1ac44,6bc4a4c9) },{ Z8(4064e2d7,77750639,f8dfce5a,0e4e7e63,725e6611,775c37c2,e8c5ff87,f528ac22) Z8(2b96a198,aa8920b1,603cf111,53ab4d08,3878ef20,fbb6aba6,323d8a32,6d13ddef) },{ Z8(86ae07d5,0d2b4651,b7cd15b4,9cb28ef4,524e778b,0b479be1,97b8243a,fc2b97f7) Z8(6133b646,c95f4009,20505b04,73ab4620,bc39ef20,3ec53e23,4c43ed66,6e61625a) },{ Z8(7b6da0b1,a9f31cbc,6cddd596,1210ab02,994646a8,50b64bf2,8b728a55,4d17b0b1) Z8(a905792e,92f74d1e,233b3294,2c1be100,f06b25b5,1874deae,9c6defde,6fad3676) },{ Z8(94468a54,d7b83c67,98048347,0c272ece,a2533c60,82649140,682717c8,9e8a6c59) Z8(f0a1b552,d2bd6d07,4099fe79,18e57d81,69b60bb5,cf052dea,36b535ce,70f75e9f) },{ Z8(aeae65d4,f0706129,810e4f3e,d3f90b7f,a11bc8db,62066c1d,f9ba7754,432551fa) Z8(c97f8e8d,e1e267ea,235b8362,8ecbd4e8,fee6892b,97607bcb,6a6886b0,723fdf1e) },{ Z8(5c1d0e27,6ec32e26,0d5e87c6,baaa4e9f,5046a410,f09f4cae,3e4cab06,ac982b71) Z8(6940f2da,30f2257a,ede56473,19180165,26749c43,f4af2ab4,17cfaded,7386bc2e) },{ Z8(efccd9a7,17c86357,90b72371,2651580b,0abb7696,e57cd327,6915d53c,e48da163) Z8(025705ed,1279aed9,d6e583ff,b4dff5ef,a36fd18a,7b232faf,03af5587,74cbf9f8) },{ Z8(2a826c1a,0333ac1d,ea7efd86,55e66b44,e62627e5,188320b4,24b62912,5a74aeb9) Z8(3363c7fc,50800d47,77ebd803,94cc1824,5110ea50,456e8bb2,28bcf941,760f9c96) },{ Z8(76a1ca55,43a3f551,4518e0fc,0f1e32ef,3e5b508f,8b63c711,7d60fbbe,2451e71d) Z8(5c94d3aa,250ff699,bafcfd59,50684ce6,76e1fe9f,989a9274,071282fb,7751a813) },{ Z8(c257dfed,dbddcce8,03e16c65,af8088bb,d9a1ee03,f819a863,e2671dcb,8b5ae70c) Z8(cdd6a4f1,8750a8ca,c3da432c,07be2ec9,2918d8a8,f63d1655,f1b09872,78922069) },{ Z8(d0dde8c5,a9caba57,0f3da399,19386ee6,ee0ef38a,b9a877bb,946cb64f,b2114303) Z8(1899206a,a956c38f,ee015120,a18e2aa5,ed1bb404,f68dbcf2,5a1e1f8d,79d10987) },{ Z8(9d4179e1,47cd2a96,91996ce0,dd6e9f64,c45b6ee0,64bf71ef,1a908802,ee62d104) Z8(22d5eb97,999b100f,bd8e5113,972fca0e,4e5bfb08,73b94fcd,1a33005d,7b0e6749) },{ Z8(5906267b,9727ebe7,3bffd807,bda7391f,0a0ba86f,9cd3cbbb,669c3df9,c07f81b3) Z8(9dfd6268,ea5ce16b,9ec747b1,64911742,73d75cf5,720ec44c,bc1bb2cd,7c4a3d7e) },{ Z8(8abec40d,2f01653d,2bc13395,6093422f,2840a0bf,4866a344,bddb7177,9ccd0b6b) Z8(829c25b6,769bb433,09381f6e,48299816,34148654,15b0f2db,c0a2b185,7d848fe9) },{ Z8(ed8fd682,4827b3e4,39ca9988,6fb9d4a8,1ce07db2,bcc34caa,592550d9,eb29d0b0) Z8(fa53d65d,34ba102e,4dc7b6e6,cde2ef18,1afec6d4,becf93aa,e3cc7b66,7ebd623d) },{ Z8(9d15cc1e,12704f76,383503a1,8a334b0f,1fc312eb,f921e345,73b2b50d,eee7b8f9) Z8(1790e838,3b38ae3b,8e29866b,379d3ea6,1af246e3,5f40d932,5fd26156,7ff4b821) },{ Z8(67a46987,94062760,e89d878e,3a732eb6,0c759abe,e2af09cf,3605037f,0ba66448) Z8(d7258b51,a25591cf,34ebb89e,4b8b8c4c,3ffe346e,e34aebf7,2e87f634,812a952d) },{ Z8(4136900c,f04505f9,fd9b2fd0,ec760e66,63f372ff,f2039753,16f3e26d,b21e3f7c) Z8(eeafe183,9e3bf732,18e0a7e0,1c88e1e2,3bed4da1,e6080459,4936932f,825efced) },{ Z8(53b65adc,76def4c8,e81a013e,690afdf2,184fb062,23989734,20e6ea98,297156dc) Z8(aa7c2a28,80a11439,210f75ce,a5d75211,b755b2b7,bcb1c488,e6fa0272,8391f2e0) },{ Z8(7ada428f,cc00dcd8,c000a5b4,3b9be86a,5db6f492,7080891d,9daa94e0,978f0a6b) Z8(96240ed5,bde39b4a,389f13c4,3f135a26,1fe03811,fed4a7fa,b9a905c8,84c37a7a) },{ Z8(eac77298,d04a9e2e,5716b0d4,7259863e,dee7403c,9b0099ab,6ea5168f,60e4aff4) Z8(c52fb7f6,90936f50,5d3ed11a,366fbbf3,ffe69b64,c4bdd99e,295415b4,85f39721) },{ Z8(d95cf419,b28d415b,f24b352a,cc6ff342,809d44d5,9401a2c5,7ba5461a,50cba9e1) Z8(f9cabf0a,b3c6badd,430bd090,59ee145b,b1f1a3f7,572ef4b4,8e645fb7,87224c2e) },{ Z8(0eb07925,e5b1269d,ed9b187a,d1d2fd21,3b889e3b,f02ede9f,9f62ab2c,2e64de1d) Z8(945a0a58,a2072c7e,7e4ae138,63e6f990,c8c5f241,1f64d85b,6a64b7ef,884f9cf1) },{ Z8(46e32681,abcee122,2922d148,7967d053,e1370c8f,cf0146bd,779f7757,d9f2a988) Z8(51b63a9a,3451ee15,48cde6bb,c9d5fd40,86a5a24e,0918ce3e,9f7de298,897b8cac) },{ Z8(66b86f42,f9c14cea,33bde7be,fee11155,438d5e9d,e1958c8d,38859b27,50a4b66c) Z8(0e33c3df,26dfe952,1cf1faee,3a330f34,f14054ed,799d1cb2,a6af4d4c,8aa61e97) },{ Z8(d0ece291,32eb4370,23a91da6,5798053d,8fc6853a,2d5aee94,45224e00,21f25c1f) Z8(34f3fab2,5be20076,147c6d48,37d86476,e970d58e,30737d03,c4cd05fe,8bcf55de) },{ Z8(c2eb376c,ef9a8ef1,d7aac1ac,e29dd595,ef6da3e9,de764d2d,66f272b7,80ce3afe) Z8(a3ef0ea2,e98ec9b5,c371d36f,78ea06c2,ef3d5710,e5eebbc0,3e4b7662,8cf735a3) },{ Z8(a482791d,13c9d868,6dfa8df5,b660ecca,7dbcefc9,4eccce8c,02e8f0cc,411af4cc) Z8(8a493f54,81559525,ef8dce37,4c2379b2,e2efc77f,a7c766fd,89e125e4,8e1dc0fb) },{ Z8(28e74d7e,4f6620b1,dd0bf7cf,fdbe964c,deac4090,e678c55e,ab58d60f,6e709121) Z8(5ba0cde2,9a4b1c06,696ad39f,ca4f4817,1e35f2e7,62cd2f9f,820681ef,8f42faf3) },{ Z8(9abaca2d,18da6190,7ab564b6,d1252aec,c7629553,022a6191,c984a22c,e12af53d) Z8(c9110b22,beeaffac,3b527cba,481a9128,fd849e89,81e87bad,955b6c9a,9066e68c) },{ Z8(44f5ae8c,46563067,d9225675,228fec0c,20b70553,37e3a916,53349bf8,f29881dc) Z8(8150f4a5,5a9f0930,5b0c6c60,bcdfcc1f,5240a471,f1b43916,f5fa1416,918986bd) },{ Z8(0075384d,9003f45b,8607f720,d3e059e8,1c66423a,3a28cb9e,ac221819,72804429) Z8(3894e474,feca10f4,01ae8308,50a06eb3,1e710847,21d6d688,c7be59e0,92aade74) },{ Z8(fa1895f4,5558e6af,15fa0ed3,c0dc1d6b,6de19a53,92b0f0fd,a10dfdb1,b09a0aae) Z8(9ec6647e,7437d665,433bbdf4,527d7309,438ffc03,c1f9edcb,4d88d75b,93caf094) },{ Z8(c23e9c20,fa880bc2,44803285,36d6e47d,b25cde63,0c7b750c,e0814130,53a0d1b8) Z8(1d0d3dfd,33a48e4f,6a10aa67,fc1f5596,67db5d0c,e6b65d2e,15845642,94e9bff6) },{ Z8(888c4872,979b5ac4,58797f08,ca3f05b7,6ea286d6,f59eb28a,c7a398d4,f1efd6be) Z8(88043648,2d83ac42,b745196d,a546f842,4f312a40,d4e18dd1,24745dcb,96074f6a) },{ Z8(a599dff0,51789fa5,ec7a3208,9aa1da7d,bf521374,3c526d19,97f074ad,f8a93521) Z8(3f080baf,79b79196,475e2e71,794a2964,0d589296,a10c3491,20134202,9723a1b7) },{ Z8(1304d6c1,db24c695,ceab26fa,4556832d,52740265,879fae51,e748ff9a,d3bc93b7) Z8(636df445,4042089c,8119ba91,0b701333,36cdee18,ac850fab,7885f0fd,983eb99a) },{ Z8(a5640a3c,8297bef5,57cb315a,0dc0b96c,bc7ef3d3,a6b569fe,246215d1,d14142a8) Z8(56157af9,6b3a547a,ddf94bde,ba133462,16b06715,2ab5b3d9,90eb8990,995899c8) },{ Z8(45128ad4,bf91ec4e,35a6ed7e,bad3588c,305274e7,3cf7c12f,366668d1,5e8524f6) Z8(9d8edefe,c765792d,b6be4109,1ddfd382,72757253,5c96c42e,e70e98b7,9a7144ec) },{ Z8(b0a314a7,c8b6db72,3474d5d3,618792f8,c0d05d00,5a8770ef,9d03b869,d14e8265) Z8(2bb4ff77,c110a792,16c364d0,8d986c28,efc8f895,e8124226,3a3dae2e,9b88bdaa) },{ Z8(48fe0250,829512bd,61955f50,2df8d830,3dc6a386,a87f09fa,b57fe9db,bc176f0a) Z8(2170e2c2,41e7a845,00413260,1717c9e7,f8c38f62,221301b6,b150cd4e,9c9f069a) },{ Z8(7bd85e3d,e34b5769,ca04f4bb,2a5f91d4,39c54415,b42d4279,4c9cf538,880cc792) Z8(c90a2c44,29adc2b4,1a54790d,e6d9b959,9b341d6d,76f60c2c,ffe1157c,9db4224f) },{ Z8(a0ce0994,eb29783a,c4b53d6d,97af626a,64671d5b,76ffe838,89dee616,cfe36b8d) Z8(f297662b,0bd03b10,df1ff936,9d96954a,93cf6b80,2131e856,8ab7d520,9ec81353) },{ Z8(6fa22492,9d4d0b6b,045b8bbc,2e916e2d,c5cd1a0d,ed2d7b5a,4f170359,d8c6dbf6) Z8(bba84ce8,71168dc1,4b72b4f9,ecf33acb,5dde6c84,74ea82e5,8b7a12da,9fdadc26) },{ Z8(d6124129,2018ce5c,1df6c2fd,5f29ec91,892e5832,2bdfda46,1bb82762,6471b5af) Z8(2a5e02a7,247c0b84,56f59974,4486ea27,00bbca9c,25e617a3,33957323,a0ec7f42) },{ Z8(82f9c9e0,48f0123e,eafb93f5,4995554c,a3bb3481,72e33343,751d317a,0a091231) Z8(76d75442,e23ae16a,7ce6611a,b774c2fe,70cb6c1b,93dcdb07,ce733bd3,a1fcff17) },{ Z8(1ec278af,031238ab,e66d803f,29c9172a,e5fef460,6124acfc,7750befb,5e241add) Z8(52e7f931,6bdd6ab9,16887279,e59a4980,e39a20ae,5bd9bd99,e2f613e8,a30c5e10) },{ Z8(d6d3d6f1,f8b49e95,50bdc64b,6f85a5ab,052e0cb4,3b248f20,3e6f4167,feea5337) Z8(c4c1348b,6d9c0712,7535ca72,efbe7833,fe84b0c1,af45d980,5446fb9e,a41a9e8f) },{ Z8(369cb411,5c9fdf23,a883d1a7,d83cab84,445c1b43,322aec8e,db555408,23bd3235) Z8(84ebc206,5bf1a66c,af47e744,6f7191d8,61b6316e,3dfa3d37,81f5d811,a527c2ed) },{ Z8(17bc15c2,efad36ce,b966f5f9,f84b0423,42ec4a7e,a85f6dd1,65a33b31,96bb5520) Z8(905668df,1b7a54a6,71eab2c3,1b11377c,37ec33b6,4766e98c,6771cd8b,a633cd7e) },{ Z8(e9bbbb42,0b863a1b,a0c9e024,3ab169cc,c1b47d5a,c1f3168c,0464cdd9,aca74ac1) Z8(2eb5190b,c9ea4c64,f774593d,bd794408,2aee1a18,84c2b22c,badd84e5,a73ec08d) },{ Z8(5463ae30,44a034cf,f48a4b7d,0955efb8,bf4cceff,34a81880,68cf4ff3,ae3a7fb0) Z8(77258b86,ab09e042,9cbb2de3,39ed8a98,b61ed2f2,59d2d85a,0b435a5e,a8489e60) },{ Z8(c1df5ebf,8a7e5bd3,d6775e9f,bbe00b2b,eceb1f55,031e3061,3e381ca3,ca138ee0) Z8(29d4eb53,a388b633,4c39b31e,d0920f6a,97aea7be,be4578ad,de2d5773,a9516932) },{ Z8(b44ebf27,07bdebd9,ba72c6bb,37b0af6e,74fac90f,cc6b9908,e041db14,d82bb3ba) Z8(3fd0d75b,916e796b,4ebab5f9,5d56af71,c1796894,aa145a1e,cca4bd48,aa59233c) },{ Z8(860598be,68a891be,419576de,bdf5913f,71a9ad49,9309a22c,7697b2fe,e4b7faf8) Z8(2e3f55d3,52d39be0,35094514,5631bf5c,fe59cdc1,e310b9b1,9f9cca08,ab5fcead) },{ Z8(12c4fabd,800743a3,a2cbcafc,9f7e13a3,3754421a,dbe424b0,90272b07,cbf0d848) Z8(6848f351,cefc72f5,c446c7b7,601ab2b5,4585513c,9792ec98,6bcc4984,ac656dae) },{ Z8(14f3b1d7,77d02118,d6b30d46,faeab5b9,04f30d08,869cbad3,7b2300e7,0c763464) Z8(5b324a78,7753b3c8,8161ccf7,839e0457,1cd40845,4d552f81,acf967d9,ad6a0261) },{ Z8(409651e0,a0ec4685,0b291788,f5270b8d,11141c98,752dd2fa,066ebca8,ff6f3b30) Z8(ccb86b9a,72812da9,b0db90f8,50ae328e,418af602,b71e2eb8,60bb2467,ae6d8ee3) },{ Z8(6e5357ef,6502ee16,4e559a75,486c32a2,2036cccd,46a4f082,c523dc46,5f3cbd97) Z8(51d2f00f,e6688102,e7a29309,29f04ae4,103ef4c6,b04afe92,20b3ab86,af701549) },{ Z8(4df8fd3f,bbdc25e6,05a0089b,f91ab8af,0ee934fc,bc66fd20,fa3e3768,c5e4901a) Z8(c1549af0,96012a8e,ccaabf0a,17ce375a,76554335,e44ad05a,3c46c653,b07197a2) }}; const mp_limb_t arb_log_tab12[1 << ARB_LOG_TAB12_BITS][ARB_LOG_TAB1_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(0c7e47ed,4b04b13f,e5e46287,7785988e,adc4b604,455be77f,db837e0c,9876d250) Z8(3228bbda,f7b8170b,08a27c47,0dcf437a,809be9c1,56221f77,00155515,0003fff8) },{ Z8(5d3950db,eb8cb58a,5bc2ca6a,2f9fd6b9,795b75ca,f576ffd9,c36eede8,f2added6) Z8(c4b26860,46c08a95,de4647be,6a90d794,2bc2bf0f,c443999e,00aaa6aa,0007ffe0) },{ Z8(df684222,3331882a,5bbccd32,ed548b07,37bf2957,dd4f60be,63e70f62,0c11e6c9) Z8(e4fe2376,1761433d,33f47284,631e94d2,7ea01f6c,c25eceb4,023febc0,000bffb8) },{ Z8(e976cdd1,bd5c2e9e,116cb84f,f6577335,de7bf63a,add50321,e5b794e8,83c3767c) Z8(8222f25f,c9b2e919,8002d083,49c8cd0b,e271ee05,885de026,05551558,000fff80) },{ Z8(8ffd6108,b5f4be26,13bf8e54,580566be,3e42853f,73edc4f2,385d2695,26f78ace) Z8(7c2eb67c,624afcb5,b1195c2e,ead9fd07,6f07f956,6e07f2e5,0a6a0e74,0013ff38) },{ Z8(8397d72e,9cb25d77,08872f77,6259b85d,79f21fa0,fe7e018f,94cff6d6,a6ba5f7e) Z8(6496860f,112126f4,fce97760,ec66a6b4,4fcc8cbf,4ae6f3d7,11febc18,0017fee0) },{ Z8(dd783371,6ebe5d38,e52d4841,07891503,a142f477,c716cde1,a8180ccf,f533be7a) Z8(86f4eca4,a36b3c59,41bf2ab6,05302d4d,867db3af,d625df1d,1c92fd49,001bfe78) },{ Z8(71564207,2e395e6a,648d0b5c,d4954a65,10a5afda,2369cbdd,a5e80ec2,7dcd939c) Z8(5c09d7ac,4e588a36,e5e0fc9e,545eb8e9,b318cb38,06678ad8,2aa6ab11,001ffe00) },{ Z8(a74c1f7b,c8174f2c,4cc3b548,280cd516,fc13a506,be31314c,9f59c45d,72151c08) Z8(9ada2548,b3fa3abb,cee967f2,6704965e,74d6486d,7195f625,3cb99878,0023fd78) },{ Z8(0a8bc7fd,5940caeb,5946eabe,3329656e,197b2784,204f6b19,e73d96eb,e2ce3906) Z8(f3403917,958fda30,07f8f64e,4dd54982,e472577d,acaa1d02,534b928d,0027fce0) },{ Z8(ba15b9c1,9d400eff,63997eef,1f52bf03,b96cd7b8,4e6f8931,72908d79,9584befb) Z8(0731c1c5,a523ed83,746ceba4,481e5b33,9460290d,ab6c51d6,6edc6061,002bfc38) },{ Z8(865897d0,e4422d88,804121a1,f719dc94,0b06bab2,564bce4a,77837236,a2ac2a15) Z8(4b0345d4,0ddb364e,f20ddf24,c18ae3fd,6fe9680e,202d1d41,8febc309,002ffb80) },{ Z8(c67f8e67,c756b402,e95530fa,d96a8508,8b260572,d27384a1,ed01736c,aa92f585) Z8(142fe815,681298a2,2666f5a6,84fdf71e,bea16a3c,db76a4f8,b6f9759c,0033fab8) },{ Z8(96ee51c7,2b4aae3a,37445efc,3528f10b,2447a3a2,262fd12e,8aea37ae,ee8fa41d) Z8(25bfe902,6aa3cc1f,44187b24,fc0ffe45,7dfc3806,2bb69a56,e4852d3a,0037f9e0) },{ Z8(01761986,7a9639e1,83ebcae9,a207aeaf,93202e05,e12a8362,f7ed7dc7,9b5cfe21) Z8(5907d500,08937816,b236f63b,0a6da4ba,2f4485b6,3ce0b154,190e9903,003bf8f9) },{ Z8(88455ab2,2cbec254,033072c1,ac4e6045,5f35b760,d3878b77,f158acdd,453519e9) Z8(a6eb720c,6e34c564,62ef4eb0,8e30d617,2499268e,7809a0a3,5515621f,003ff801) },{ Z8(d6aba998,7285ccad,cb6da537,24bbd3dd,1faaf79f,dde40d3a,a21dbeca,002ff1cb) Z8(dc6eb7a7,da5b99de,a85e4861,d7bec86c,440a6381,e2faab95,99192bbb,0043f6f9) },{ Z8(d575a542,48cdff42,994b5242,fbff851d,e7243654,915506af,2f36d303,5936d46d) Z8(10692284,4e70a24f,51898a1e,9fec675c,2461f0fe,7fbdb689,e599930b,0047f5e1) },{ Z8(af26aa96,52ad5bde,e081969a,48cd173c,ce824ace,d0826b70,62e17050,20a86cd9) Z8(daf119ce,ff749b05,a14a8966,4b07e3b0,5395028d,ac21e68c,3b162f47,004bf4ba) },{ Z8(685dfb6e,8d4c6e65,55162dbf,38f0cd96,104ddebd,f89cfd12,bd249dfa,7640a942) Z8(613f9246,fc8a64a0,058d0887,d9833ed3,83572e9c,8138cce6,9a0e91b0,004ff382) },{ Z8(78ab6fd9,e7933509,c718a462,696a6f1b,1c6a54fd,0b9fd618,4442f2b3,dca8f510) Z8(6c1f25dd,5b91d0e7,db87d3a7,07a40d57,44be78f3,32cc1f40,0302458d,0053f23b) },{ Z8(b557a2c6,cb980ff1,34d846af,b21606e2,60e26967,f35f9cc9,839cfa15,5c829c59) Z8(cbe42378,7018362a,f78f231b,1eccc4c2,e864ee39,6ecbfd17,7670d02c,0057f0e3) },{ Z8(ec6ddbc8,be4b0986,ecfd04b0,cbc438cc,55568294,93488199,7850d920,9eae7246) Z8(c457bd71,4b82fd69,d36c3bcd,3c567cfd,04f2bec8,bcb5c337,f4d9b0e4,005bef7b) },{ Z8(be74810b,d894e323,98edb02e,920c9408,9773d6d9,28e2348d,2fb5401a,00363f50) Z8(f3be6b53,7c709a06,c0ac0e4c,c0ddec2d,127cb9cb,dcf36ddb,7ebc6114,005fee04) },{ Z8(3871e636,405de324,bb58daf4,2ced0f06,6461184f,d371a235,13c5374c,0d89f57e) Z8(c6cde11d,96882352,2916016e,b25c09a2,75a66bb7,28338a43,14985424,0063ec7d) },{ Z8(ad3ad3aa,1f836e0a,485ca611,79290a36,c05b5262,e36f54aa,7aaae2e7,7e4dffc1) Z8(7e20fd0c,942d752f,00b70606,a40a07a5,41fcf393,eeb9b857,b6ecf782,0067eae5) },{ Z8(aeddfa03,238faa80,3a62f688,76f05527,6b941071,0d9112b3,1f81a47a,39cc664c) Z8(68b37ab7,18ca1d62,fddce551,c73608bb,e787e161,d7a7bd14,6639b2aa,006be93e) },{ Z8(f51d41d1,22af678e,14ac3c62,150b3c79,3b137670,e89ac098,071dd1cb,fbcbf077) Z8(67a834f5,6c677666,30a82b21,c3c19825,ec181c9d,403f267d,22fde71f,006fe787) },{ Z8(36633b46,ab056e1c,b4d2a7fd,8372a606,f0f5668f,ffa99523,aab69a6b,86afcf8f) Z8(f922917a,6deb4874,8b04680d,8f944d03,bd69ec18,9b1b81b0,edb8f06d,0073e5bf) },{ Z8(40af2f8e,071c3a37,d3dddbb2,6922123f,dcffcc29,1bad4e7c,9b7da841,9a6e6a11) Z8(084753f8,18476ec7,38f1ec7f,7109e475,95bebffe,cf6523e2,c6ea242d,0077e3e8) },{ Z8(63b45d84,8f388c03,a81dc11e,50993dbb,8f985fba,488cc34c,97294de8,98bbfdbf) Z8(a84e262d,0ed48b36,a7ef8946,7614f608,59255343,97fc86eb,af10d202,007be201) },{ Z8(d4bb4228,566babed,4e690306,d0d98ea2,492e4bba,dd3f9376,02ec7bf0,66e737d1) Z8(12ace6e8,c73356cc,e89a011e,cad8ec22,3e3b1ab1,e29e3a15,a6ac4399,007fe00a) },{ Z8(54920bb5,d39b5c6a,94602541,f62afd99,de32f9e1,9eb075e7,1c008530,07c2308a) Z8(a1e4a056,4fd3b446,3ac46170,66d8d540,01c8c50d,2eff67e2,ae3bbcad,0083de03) },{ Z8(bf1027ca,5ead48b3,ff3f51ce,708c8a5b,fd6dfed4,cc06d25b,7766afcf,a9e9ce8c) Z8(93379645,cf48be75,715ee9c6,75134f09,5134c8da,ede2f177,c63e7b01,0087dbec) },{ Z8(35785e9e,3e942680,e875d7a5,26988f31,a6bb3588,3d8a1f2e,ba07bff1,5095a608) Z8(6b004d41,8fae0503,af5583cb,ac9ee56c,0462a0f8,e0272064,ef33b669,008bd9c5) },{ Z8(fb21f68e,753260fe,8537dd47,e3500179,5c237884,b75c1e8a,1e417876,4b22e850) Z8(000ffc2f,70ef6ef4,846a1e3e,95466fab,ac33691e,75cbef6f,299aa0c3,008fd78f) },{ Z8(75a1dee5,ac4f21b5,4b573dbd,bdb47dc4,37b11727,13d31b84,de086ae3,b78ca501) Z8(6ba71552,fb24c1f1,f6c179cc,8c808eac,e77d05f5,2cf1eb25,75f265fa,0093d548) },{ Z8(2deabd12,63bec9e0,37a6edac,12c1ecc8,2527fd67,8b4d62f5,97a8d5c8,13aeb9bf) Z8(c4241c37,67d35c35,e4cdbc59,76b21c7f,dcefe9d3,f0d1aace,d4ba2c06,0097d2f1) },{ Z8(76ffbe27,b1e95072,49c84b76,e92313df,932d2871,cb9160a9,a902e528,63a4a86e) Z8(3c7c239a,e0a5bd0d,8dfbd4c2,984bca93,2508d67a,78abe286,467112f0,009bd08b) },{ Z8(e5063188,bb5ad7a6,67234eef,800aff74,f5305fa7,57b2808f,c02ba4e9,e7e5cdfa) Z8(f4f87b33,b0574dfc,edf272ee,60d8ba6e,5bd3b58c,a6b20f21,cb9634cb,009fce14) },{ Z8(d1792a4a,f57169c1,8530795c,e830e638,a4ff130d,80b9b11c,345d8133,10861bf4) Z8(c97e1031,b5a4fed7,cc3fd585,53dc4b8e,7eeec422,e6e7bc97,64a8a5bb,00a3cb8e) },{ Z8(4f36714e,1ba838d6,628f13b3,3434af35,61f66e9c,e9376e9b,0d56f2cd,20dfd11b) Z8(e5b72558,af61cbda,d971aec0,12487785,28e9d9f2,8dfc679a,122773f3,00a7c8f8) },{ Z8(933a153a,5a3e565d,21d72452,a23255c7,c22b78d0,04b61a2d,f572a9bd,4f7ff0d9) Z8(6335e23e,c8d3b0ea,f3596f8f,42c370ad,a7cc8928,381dfb11,d491a7b4,00abc651) },{ Z8(75b1a874,0ffd44f2,90adc6b8,62df9624,db40b8fe,6c7aa328,c11e4d1f,5704f32a) Z8(f694e7b8,9585a480,cf0318ef,33bfcaab,d93f316b,27c3ea2c,ac66434f,00afc39b) },{ Z8(e06e5919,2927744d,d60abeec,e630945a,e6f8d6aa,6f7c9599,781a348d,1f5fd896) Z8(6026f361,b151520d,b29c00f3,1aee5793,a386e5e3,a472e7b5,9a244325,00b3c0d5) },{ Z8(de078ae7,480e3d76,fd2bcb45,05f26336,33fa6860,6ba5ca49,1543029c,a7dbafe5) Z8(4e644993,a2b54d41,ada1c113,619cffdd,cf3a3364,59793b5a,9e4a9da9,00b7bdff) },{ Z8(06735d75,24c626a3,422cc204,98c9b76e,e27f608a,9b6f45c6,4e4260c0,6562056f) Z8(4954a379,9eb7a003,18716269,22719505,f24d6892,b4a3b59f,b958435c,00bbbb19) },{ Z8(c4b9be54,ab3b6a5f,e75d1021,85aab5ec,40365daf,008f1701,a6729ae2,9df4c673) Z8(15be5920,d672b536,013b32ce,8d568dc2,09cffdad,44eb4324,ebcc1ed3,00bfb823) },{ Z8(1a6b1ba5,ebc85846,e1a91850,1887f224,63edfd20,0bf7c3ae,9c5fd129,577c039e) Z8(9e1ff4f5,bff5d508,10741031,128f38bf,4c721c74,191b1fef,362514b2,00c3b51e) },{ Z8(1f979973,e2792fa5,08a8dfaf,e765456a,0aa680e1,ccafedc8,5eedcd19,7aabe19a) Z8(978d1afd,e6cdd79f,ba155a9d,cb5e4d97,aca91193,1e6fab78,98e203b0,00c7b208) },{ Z8(83ac4f59,57383936,0d4c8f45,51d4573b,e8e4ee54,d2231c8e,69bf13de,33817b57) Z8(7f1a47ce,20d61862,fee7a1a6,707f3119,6e0ba085,7f2dde13,1481c496,00cbaee3) },{ Z8(5e6bdd6f,8cba337c,fb61b972,25c2e73b,69be5817,fecbecf9,9fbdc30a,e6b7953b) Z8(447782dc,b8c60248,5217ec2a,355d10db,1e43c7af,01336075,a9832a41,00cfabad) },{ Z8(3ae610e7,a927c538,2f2c100c,99c6b780,7ff1e2e1,be1a1eeb,0be27aae,0227f915) Z8(39bade0f,67addee3,ec5cff24,08512895,2eba7d3e,647f4604,5865019e,00d3a868) },{ Z8(c0d31800,a4721cba,e859f70d,ddf2e3c9,a58d5bc3,65471a81,60f772db,7157132d) Z8(283fb5d9,54c9fdca,e82b32cf,078770a2,58eb4ccd,c1b36a9f,21a611b0,00d7a513) },{ Z8(8e146caa,44554af8,9852903c,93e46ed6,e09ea2fb,890a66c3,55883b20,4f2e9654) Z8(ce8136f4,41fd6636,00fbaf66,801f157d,e4198267,e88e748d,05c51b8d,00dba1ae) },{ Z8(c336ac8c,8706d416,d7190699,fd87fa22,b9359862,e3c3a012,da36b5de,0845fc3f) Z8(c4fdd760,d255bfb0,4cb74df3,a7bcaca7,cfeeb85a,be5e7b48,0540da5f,00df9e39) },{ Z8(76fde9b7,fdc4e4af,f1ed4448,a6243802,62664345,d8b98000,6694e0e3,cc1bf9ac) Z8(c480c726,7b62fca9,fdd12923,9b78e3d1,d45b2a53,9c6c53cc,20980364,00e39ab4) },{ Z8(3f8e1951,55bdc61f,e01d5bb1,50552a83,621f646e,9415d382,d7aa2620,60611de5) Z8(02dc658c,e000bbb1,dde4dd76,42a65998,13e32116,ae5f8325,584945ef,00e7971f) },{ Z8(f1317ca8,2cb071c1,1c950730,630ffbe9,e7b9a5c4,0335b8a1,565ed229,aec77f1e) Z8(a6dbc6fb,8084256f,35411485,c6764d7e,4a5a1e5c,509ad7de,acd34b69,00eb937a) },{ Z8(d5a00b9a,2d07b7cd,e8c44bd7,8dad7157,120834e2,2813c281,aba7a595,661255d3) Z8(270a5d03,7895fa76,4ccd48f6,b48862e2,2ee427cf,6e91ab12,1eb4b74f,00ef8fc6) },{ Z8(4e203afb,619decaf,853fd4a7,c26d6e00,55b97354,97da2ecd,0e10dd1b,921079a0) Z8(b81fa0f2,b9b51453,7c1f2e00,fabeadf8,acefaa2e,e115c9ba,ae6c2735,00f38c01) },{ Z8(a668a43f,f83ec6c9,5c9ed99a,d960d82a,182f3c6b,0a5a4916,6cd7c7c8,31a2f869) Z8(1e75ba80,2896dc3d,dab452e3,24699801,84b6ea5e,cc9e06fc,5c7832c6,00f7882d) },{ Z8(0f8ac595,a9a2d75c,a1ff3231,741f2266,cd465675,98c110c8,14c76f39,402f3cf7) Z8(adf9dc5c,ed38e322,31f2f4e0,177d8fa4,d0b6d8bd,ff857818,29576bc2,00fb8449) },{ Z8(f0697e38,b4baf715,3a53ec28,699b4749,cc95af15,d137bfbc,4192b38f,7ed64a06) Z8(5a1a3322,91ba6e33,6d725824,8ccd29dd,da6a5bb4,50435ab4,15885e02,00ff8055) },{ Z8(f2fbe39a,b0a09e7d,ab4d937d,c932ef50,8b1f8a6b,3aba97dc,7eda3fab,f0f5e77c) Z8(3e20633c,0610e9f7,c212c043,3648bfe0,957cc84d,fb9ba627,21898f73,01037c51) },{ Z8(8e0e24c5,41a6b666,4f97b2ba,6ee55299,da164bdd,c6d8c666,e96270f2,11e0d043) Z8(d4bfa049,b832c8d6,acaa8dc6,9d671866,058c42b4,02c8487c,4dd9801f,0107783d) },{ Z8(ddc1e10f,ca511896,f32d8b54,53fbe765,5c0904f4,b1e637d3,c46293f9,7f2b1db5) Z8(0593c102,0da1943f,42704593,eac055ae,bf7d2465,899b0fd7,9af6aa22,010b7419) },{ Z8(609407ed,a94e9ec2,5e6ddebe,fc430e2c,f62e1599,e5cf9a05,16a05246,ed4c214b) Z8(94a725a4,4d4ba377,f58fe6f1,bc7aa84e,a44a49f1,349840f4,095f81b6,010f6fe6) },{ Z8(94059f3e,8464485f,bc962d00,50404911,f1c7192d,7e8a375b,c7ba304b,43799dfe) Z8(f93dd648,603e12ee,37198f3e,bea0bdb4,e02b4ec1,8709db5c,9992752a,01136ba2) },{ Z8(ed8d842c,58edf35e,dab9e859,52826990,b5c2b215,a81db272,28f71d7a,5ecfcb75) Z8(036dce40,d03b94ef,b83a73c1,b747f61c,25d9415d,410b8c18,4c0dece9,0117674f) },{ Z8(8436764f,78504291,aa9dea40,c9869312,08043c08,f84a42e8,8c4f7b86,61a3a120) Z8(f69ba443,afe9215c,453de490,0e432596,0aac3e53,bd8f4f79,21504b75,011b62ec) },{ Z8(853f7ca1,777e550b,0cdea499,d68b3513,20bfb619,9c167cdb,e7eb2269,d7de7f28) Z8(5e33974e,53557268,19a4e1e2,77ee538d,5540a298,505ac2b9,19d7ed6d,011f5e79) },{ Z8(f105959d,9db851db,46444cee,2f7e1d45,e5bb3d85,76bcdaea,6a0eebd3,89c34913) Z8(ac0d8e1d,169adf00,e5a4857f,5493f88f,fd4927c8,a3fd2613,36232987,012359f6) },{ Z8(d203908e,02ca62d3,4f34347e,e2aa8e94,4c7af8fd,e5a7ad41,9d52858e,a2d55b1d) Z8(63d691aa,c506387e,8d073984,9768cf4f,882c3c80,17be100b,76b05097,01275563) },{ Z8(056e4b9d,cb547362,85d30619,0774c3cc,7b76e77d,62feab55,548d2205,c2f25a83) Z8(af1e55b3,c94991fd,965a9e22,bbbb20f2,5b064949,1d84d28b,dbfdad89,012b50c0) },{ Z8(43c0bf69,99519342,d5fa1e25,88a414fc,c298ab06,437c8525,e6ba0238,87d5c579) Z8(0f34341c,9630b883,20673da0,9c847e0c,87a84e42,97b89292,66898566,012f4c0e) },{ Z8(d416551e,e6cef8a5,af4390de,0ca7a65d,bb045932,a09689d9,e7aad825,54bfb4ec) Z8(33815654,ae5ec783,7f40727b,1f120f44,872a5f20,37191316,16d21754,0133474c) },{ Z8(343c1335,c30433ec,9700948f,2e37bb15,5b7d91ff,c57703c4,77ed2379,97f3c2c3) Z8(73ff4d94,a8611edc,eeec0c6f,cf20cd6c,41abf980,d89033cc,ed559c92,01374279) },{ Z8(09091dd8,42208d0e,2ff745c0,900fcd07,a4ad11d9,af23eb6c,7de4f9b6,4b9989aa) Z8(90a20265,2defe197,08c9080e,18f6394d,afe104d1,e2fc2485,ea92487f,013b3d97) },{ Z8(4533ce4b,200d4e60,b0eb1eff,a6dd1f16,73b6e444,ad86fb62,5722681e,57075db5) Z8(357fb684,e444e58f,29be3018,19350e86,50117ab0,a4f24dd2,0f064895,013f38a6) },{ Z8(f3a83285,fef1d22e,3f469677,e72ea369,1038de7d,18e5003d,c99664c8,cacf87fe) Z8(a27038e6,3c826b1b,13003313,6c225df5,953b429a,b27aef90,5b2fc46b,014333a4) },{ Z8(7d0c6591,d8332a29,b302dadc,cb9be321,410944d7,2bcfc6e4,dfe028f9,265b03bd) Z8(3b590bc2,c72671de,687bfb68,759bab55,6411b343,42c5761e,cf8cddb7,01472e92) },{ Z8(e73a7b96,da4c756c,df5ff9c8,117a037f,a5f765ff,dbe54cc2,fc107cd5,b4474cf0) Z8(c499edb6,5ad22684,f01e84a9,cc1fc4ed,9ea46f21,8dd586d6,6c9bb04b,014b2971) },{ Z8(26332e90,fba231d8,08d3adb4,e9a84341,a0b1e214,49b2fd3e,ce035f1d,f5842953) Z8(901e6a3a,63ccf79c,727a81b6,5521fdc1,ac87eff4,2a28c489,32da521a,014f2440) },{ Z8(71e6a2a3,e976e893,168d772e,8f55352a,6125ba6b,77e347bb,0c95d6d1,ae102c35) Z8(a04a112f,660461a5,52edfe67,d5aa24f6,da6d0e16,6a554c9e,22c6d333,01531eff) },{ Z8(d5e7e949,56743794,3db16793,5a355b17,5ddd09cc,53041652,eb004d11,56c39ee6) Z8(97854ceb,495c1afb,39030db5,eb60b1f3,592a2409,baa0ed8c,3cdf3dc6,015719ae) },{ Z8(e16e1f3d,025f9fcb,1929bfa2,9d8bec12,ab8dbab8,1ac7047c,531aab4e,ee875b6e) Z8(33737d75,7bb1028a,82d1dc36,480f5056,91501c47,fe911753,81a19622,015b144d) },{ Z8(4416a069,fc31f39d,ad9e9a29,cf707c8d,b2cce68f,29314e71,f17649b8,db435061) Z8(00d4a03c,a0e610e5,e219d481,69e4b23b,6d7fbf03,ee7386af,f18bdab6,015f0edc) },{ Z8(d87c55fc,65885a99,241478cc,078f0771,2e5d38d8,5e29e3b5,f02e7126,8bc74965) Z8(41089ae5,cd34fd1f,bc0d52f3,b818ca49,2acff685,74dfaba2,8d1c0411,0163095c) },{ Z8(575a3b04,6d8341c5,be54b372,4ef7a209,9d661c04,46ae6e72,acc0f8a7,1b8d1725) Z8(e769cb62,c31f7727,c63b3e1b,c5a28c43,2bb47af2,0c30cc10,54d004e2,016703cc) },{ Z8(012c7add,9a9acd1d,68ebabdc,17fa0b44,19745604,1aef3cc3,5d8b8345,d65ae94a) Z8(785c0766,636cd4c7,89ee9874,6f5ae2f0,36f5696e,1bf8e315,4925c9f9,016afe2c) },{ Z8(d1f287d9,7933958e,5b32f32a,a9591ae6,eb12cd3d,4032326d,6656effc,d5fb7469) Z8(0fdc295f,d3b37d89,6fe06366,920acf95,796bb608,566c3dc1,6a9b3a48,016ef87c) },{ Z8(ccabebb6,d760c7b1,1ab86a22,21073e23,a56ebd93,72024eea,b0b8805c,82e0477b) Z8(6ca3fca0,3a9e6470,13fa14fd,366bdb39,8e5c2ba3,15c5d5eb,b9ae36e3,0172f2bc) },{ Z8(e92b7468,f91fbb7c,b5ec76a4,a150c369,d4073501,0f790d1a,ac10c6f5,7783092b) Z8(983b004b,bcc0b6e5,b08d164f,610d389b,bf72c898,b9a46bc4,36dc9afe,0176eced) },{ Z8(a8aac846,2f645b37,349ad849,8b4ec729,9208251e,16159412,90ab2734,b7e5eb7c) Z8(caacc5c2,54b1db46,bb561c2e,5361e455,9a8aba04,04605edc,e2a43bf3,017ae70d) },{ Z8(96cb638a,faabafc3,0e8ca9f4,16064670,73a2bce7,95165acf,a35e4561,6beb75e0) Z8(f1aded85,903ae028,8d165ca4,2800d1f3,e89c01eb,785a4740,bd82e93a,017ee11e) },{ Z8(53083785,2f7d6353,6717bc37,23d6413e,e25020f7,e7c074ba,fe2117de,d3ac8cb2) Z8(7faafde2,b24fdc38,067c90d5,896910a8,fe56f5a2,b5424f66,c7f66c72,0182db1f) },{ Z8(35b40305,ab118f51,8f80ab48,92ffa364,0e609295,62206c08,35eae090,aea7f360) Z8(46acd659,bd4482f4,2d792fc0,187d0295,4c2739a6,d5584f8b,027c895c,0186d511) },{ Z8(e4586812,8267f186,b664f802,9903520b,324fc988,7180dffd,d2e2b8e7,c724f4f2) Z8(055fdbce,c814fa3e,12b05de7,43763ab0,008badf3,caa4ab34,6d92fddd,018acef2) },{ Z8(c3cc6dd6,78a51015,586a5595,c46c3051,4a14d3ee,97527cf8,4f886a54,f5b8b4e0) Z8(f983e17b,5846fd06,4728876c,3162cbfa,7ce6e1e4,bc29f183,09b781fe,018ec8c4) },{ Z8(91ac9328,3f24c2ff,80665588,901d1d86,15598dfa,3eefcbb9,bfce012c,a3ba4988) Z8(31706441,449fa385,40ebc439,705c8708,4a241fed,630f4107,d767c7ed,0192c285) },{ Z8(f5f17f0c,e417372a,b09692a5,b0f7c682,0ec096e3,8cb94c7d,443f2d9d,7b3122b3) Z8(473030df,e0abfed8,ec606f07,c1a49f5e,27c7f04b,67c36fb0,d7217bfc,0196bc37) },{ Z8(b5a017c6,67e1505d,398efcd9,401068d1,8da15e2d,a8ac79c0,738e3b3a,d23494a1) Z8(3e5b020d,a26fdf99,063009b2,37a4216f,bd401543,bf18f79f,096244a3,019ab5da) },{ Z8(9ce14854,fb9ad100,7cef26b8,46d455b4,8da98fca,570a1785,425fbf6f,09edfedb) Z8(90f3c067,86a00eb5,0f6eed91,747aceb0,62867bbb,075aa978,6ea7c281,019eaf6c) },{ Z8(e2c19157,9434f3ec,e1f9e66b,8032d462,faa4d041,b0872bc5,2a616571,62bda43a) Z8(580bfe3f,75aec43b,f0a26462,d72d1652,626c6772,e55924db,076f9057,01a2a8ef) },{ Z8(55e779aa,d51a3aa5,3e2c93bb,1dda62eb,893f3070,9ba945ba,9b7040b3,dbd4122b) Z8(e640ba32,4bc3e23f,8b567604,7982e2a7,06274260,617117c2,d4374312,01a6a261) },{ Z8(fcbed80f,15e25d10,774d3bfb,a9a3f88a,868dfa18,017af617,5ce0f30c,1c922a28) Z8(8d3502f4,cd19aee6,5120781c,c60ec200,a6feead7,448a455d,d57c69c1,01aa9bc4) },{ Z8(c350c3a9,38ae4f1a,e99d875c,2aeffba6,eae45054,d6409c8f,0fecab7b,56ce31be) Z8(4747edfc,ea66a259,ce670094,ee57448a,f0462344,750f552a,0bbc8d9c,01ae9518) },{ Z8(5871e10a,4808a045,b2bad39d,1ada7eeb,eabb563e,9329dc9d,f878bf3d,f2b07d64) Z8(6593c333,ac5cd41d,ca2d5319,7b5d8bc5,6910e094,53de6ae4,77753203,01b28e5b) },{ Z8(f6efedab,88013657,01f0718b,0e1eba94,2d91f351,47667de4,6a68c633,0dd1e97c) Z8(176e511a,56f7f603,bceedd0b,7a46a98d,4a69a136,19328800,1923d47d,01b6878f) },{ Z8(dc428b95,bef79abf,182edfb8,122b110c,23123d4d,8b3bef01,aa1eda86,fe9452ab) Z8(f2a0c323,68563aeb,8e635f8b,543266ab,9416b5dc,3185b765,f145ecb9,01ba80b2) },{ Z8(d2f30446,a066ddcc,39b9e717,15e9f367,405db65e,2b4f58fd,0525be43,32b68b50) Z8(20ecce05,4a9e0f8f,d51f7739,309e2f1e,3f52763c,9a6c0404,0058ec8f,01be79c7) },{ Z8(fa460a86,6942bea1,8493f488,cd2e702a,43412b1c,b62dfa51,19907817,81af1ecf) Z8(12cc5e38,b6f595a2,1bea4f90,df4cce9d,5c2dbefa,3f673afc,46da4001,01c272cb) },{ Z8(7bb40ea9,22ed3898,e39d6b1c,399ba758,fe53830d,b672f8a0,be0d7aff,21f3a892) Z8(81bdf9b4,5159085b,ebf9c52b,c8a18685,d3aaca0a,56b379ff,c5474d38,01c66bbf) },{ Z8(8f529643,64ea9670,e9cbfb1b,552bc14e,e269a902,77ef4c52,ef2bf716,e0b5a3aa) Z8(903cb0f8,0d8eef1e,a5dd757e,6da264e5,75f77800,be0c8a9a,7c1d7488,01ca64a4) },{ Z8(f14e730b,4363d589,8fcb8fd3,6daa273a,0755651c,934df6ec,f543a503,873828d7) Z8(85fb9975,a832fa14,a063e9b8,c4395d82,e98976c0,576c0b0b,6bda1070,01ce5d79) },{ Z8(77667c69,61052bf8,e5f22c61,4403a1c2,ae9aa9cf,ac609e23,3819a51e,5d96c7f1) Z8(5c2f57be,4b4e13f3,142be1fa,76753283,fd3c5830,65c0655e,94fa7597,01d2563e) },{ Z8(5748ea25,342c8e69,26fd9300,36a2ad59,699004de,dcd12487,5d14cb33,1751acf8) Z8(dcef186a,2d4c6ff0,fb1f13b7,06f93d9b,ccf1a1da,e99c9569,f7fbf2d0,01d64ef3) },{ Z8(538cbbbb,628c87b2,30868ffc,ee809ce2,3a204807,cb3c1dd8,558a2e3b,3b87d7d8) Z8(07b71510,0e752d45,1cc16136,70d0c31c,15952489,fde0be62,955bd11a,01da4799) },{ Z8(c4b271ea,cdef4ed7,8ca00d36,b5f7a740,6c919cb5,5aa90462,4ded25e3,0cfa2376) Z8(30c94590,8392a755,baa9fb98,699d2ddf,02cc804b,345b90b1,6d97539f,01de402f) },{ Z8(2243d44e,bb5a11a4,194c2b5c,98651b98,bd6b9d38,9b405ae3,4cd5b301,7b3f709a) Z8(7f40419f,7ec4adca,7b140cef,6b8c28b3,adff9dc2,f26480b1,812bb7b2,01e238b5) },{ Z8(356b1f60,ec2ee5cf,29868a31,16291d8b,ffd69d70,98e63e9c,1c34017a,f5adccfe) Z8(0a0aa162,843652e0,960f78f0,966ecbc5,73d11909,cd6ecf05,d09634d7,01e6312b) },{ Z8(c33f9f65,e4fac114,15927c6b,3afcfbaf,8798e474,0cbf09f4,4ae7f878,d91d7bdf) Z8(4f9bcbf7,68830083,588d3104,d73dab8f,32891c12,e7956329,5c53fcbb,01ea2992) },{ Z8(2cdbf61c,89ec95d9,339e0db4,b744434d,708140bd,606ce0c7,8e9e5c21,0260a55a) Z8(d9cd3411,3e1d81e3,01ce9e9b,32a7d697,7162f640,4c1f78f6,24e23b3a,01ee21e9) },{ Z8(8c8d9511,04878ca0,8fcfc9ef,2f7f2907,33514767,0ee8e7f0,80be14b0,77d91940) Z8(da35fb25,eededab8,8812028f,2e1d8afb,5e1ddc95,4bfe21bb,2abe165b,01f21a30) },{ Z8(7bdd410a,25b49440,c86c5794,15b29515,64dc2389,69514c55,ccc5fcb9,f1ddfc07) Z8(3d3a2566,2d9c67ac,b2e63012,d400c64e,7ba3a8f2,da429994,6e64ae54,01f61267) },{ Z8(f6725be6,4314e3b5,d71e6baf,2896befc,5e6b55ff,ac21ee8a,fdb1ce5f,7a42502b) Z8(fa5d1c6e,62b187fd,6bac0a8b,70ef0e95,ca0d270c,e88d71b2,f0531d8a,01fa0a8e) }}; const mp_limb_t arb_log_tab21[1 << ARB_LOG_TAB21_BITS][ARB_LOG_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(62755d69,e496938f,05daf00f,5baf03de,e7d47be0,876a8079,f673a2de,42c7eaa7) Z8(7c0dedcf,b951ad59,fb7be050,cdb6b676,c61b4b9a,5c71d0a4,e70de3e1,b2478447) Z8(c7c58559,1947ba58,ed644c21,3a4a3445,45cb0fe7,28872ee9,2b52267a,c6888f9c) Z8(ab77734d,4f53d356,57f7b519,1eec2e2f,486fc6bd,1678ec26,eecd9969,c88799c9) Z8(f6b13852,e1f836bd,79cac542,79ca2220,3edc6351,17e1d8b3,d27618a9,c2141a5f) Z8(323af80c,5d01cc32,3d4c10e1,410d860d,0c975e1e,ed109f87,9495b1ac,6483bfe1) Z8(67c3706b,8b72920a,b906f4ed,463788a7,3af1b218,0f14f335,de1bef77,8540a3f4) Z8(caee6903,f0bfd950,c7661262,a8d061ff,ccdd8781,948d50d9,0c5fc975,d573845b) Z8(d564ebbb,e3d444d4,56901629,6bbdb38c,422a728a,00872128,d70f97be,ecdd781c) Z8(77077723,c7b39aa9,8dd25814,64b3d053,bdc530c5,cac1d2bb,b4bee981,4bcc2822) Z8(638db165,034e5ceb,5911a433,775b6575,6721f58a,1740d6c6,660c9f0c,0afd3039) Z8(2ad6ab1a,8400cdeb,0182f7f2,4eda72ef,278b39ed,9c07347d,e853cd50,29bdf766) Z8(6c5511c1,415cd4cc,3dbea7a3,7fa5d3aa,e1a5772e,e8b45e05,0a4e2e28,1c0e0822) Z8(4785a221,f6b2b036,6bd6a362,c035aad5,2ee8293e,626c2ef2,1bc4d08a,ce921467) Z8(ea801ae8,1cc99aa5,403dd582,93e18189,8bd310a6,750b0863,532b6b9b,5faea913) Z8(8fd1d5f6,48625f86,c1bb60f6,c6ee8bcf,8d212c6b,f6cf9703,38eed29c,ff7bd74c) Z8(7cb29271,02127ef4,0f6e3a39,9ce34431,e0a5d2e3,55d9a7ba,ec979e9d,8a38a3ff) Z8(e3673dcd,df6c758f,ddf35ad1,aefae14c,ef229fae,3e3f04f1,9e0cc013,07e0a6c3) },{ Z8(cdfb11b8,fe5201f7,f83a048c,5ff73ba7,2e3dc08b,0c37df21,a532ebf3,60eafe86) Z8(d274008a,edfe0e06,e2846224,ce94dd65,dbd5db88,fc2a05af,0e14f1c4,acc9fcdf) Z8(136d75e3,db83a653,3209b121,d53c774d,a61d5746,d6d53036,fec4a7d6,7575a44b) Z8(b0dc11c7,33af26db,5b61b49e,119ec434,f811504b,61b2f223,3f704e8a,955d39e7) Z8(64e6504b,3312496e,3312631c,10b84ee5,a70ecef1,e4d50c14,8c65bd71,84016a52) Z8(929c44fb,e842912b,2b44d39d,df8712b5,c81476a3,83cab0ec,a9362560,8ae27c16) Z8(b94a7a5f,3e7e4715,f6324a76,ebfc64cb,2297a345,bdbe51e4,5ddaadec,51b0ed53) Z8(786ab619,2745d1a4,852d3853,354223c2,d12f0e36,ce6586e6,b126e954,355f3293) Z8(72b38100,d61a9908,1eda05b7,2a134f90,6a6eec21,4883f333,7753257d,bfcb2222) Z8(36fa4365,4df3bf39,e3704572,866603a5,321515af,d39a56e3,faa48510,befda077) Z8(5c3586c6,cea9eb88,d5f32769,2ebe437e,550b5ddd,d27eea99,e47e74d9,67cd3330) Z8(eb97c7c8,b48eb540,734ec246,f139c8bb,8e6239d2,c2ec2f61,fc43d0cb,f2a711e3) Z8(6e339208,2f14b1da,18a07a32,86d0d6f3,9fb7dd8e,9da47afc,c2d0065c,8963312b) Z8(89ac698c,c14e8a75,06e51059,c27b07cf,bfd7f245,c3f710ac,9362f430,6596620c) Z8(a5d9c7d8,f85fcf25,b857a365,0fea5d7b,99f1c7fc,3c5c1d2c,980ce36e,8f93e053) Z8(eee9d358,d2692bbc,73d21d72,cce585dd,23c4de58,e0f55844,5f36b22c,68fdf95d) Z8(77e6bc16,9bc35789,e7a9459e,99f0cc1d,85badcca,908722d9,de861006,6172da6b) Z8(96f69849,71851f0a,75b52596,d3474d33,75997898,be64b8b7,08b15330,0f851860) },{ Z8(df4e00a8,b5fc6bd3,cc3754c0,0a06fe58,d751e17c,d238d6fc,20b60484,dff744c6) Z8(2d370598,fb1de605,65edaa94,6e812701,dc868ab5,f60ab60b,e5abf6dc,b14d9ae3) Z8(af48de57,e69cafeb,f65ec92a,311e8b96,bb6f4781,b19ec6fb,c56ac13e,2cce2d63) Z8(ca96729b,b831858b,415c078b,6d7c907c,1186a8dd,90ad91c6,71fb957d,10965a13) Z8(4b298299,027c186b,11cd3add,447f2d77,3290979f,6d147a08,c7b7c4c0,7b30074f) Z8(927fa089,43a3f1d9,c7b381c3,c63c597b,253c2c2e,3b55ae7d,df920c24,8f5d6393) Z8(5bdc4663,1255657a,09f154ab,86822055,21b0a2a2,db007af8,474baede,602f73ef) Z8(44fa340c,e804b8ea,1aed1a12,c922f2e3,75c0e7fe,4ac5c2c3,0d999691,d9ed8684) Z8(75374559,ff1e6e20,2ca7ba23,22ea973f,ccbeb702,a381fd40,2a06c4cb,f2617481) Z8(267d2e7f,9e6f6ef8,bdfe4e5a,91579482,d5e59de0,6536b76c,5d022bc5,f2376bd2) Z8(e5ad0841,b4e492d3,ed3132ce,580e63be,484d1944,e6bfad99,165a8617,94fb6c58) Z8(3d070ae2,301d02ee,9158b783,8a52c359,b33d0cae,0d271308,b04a747f,207e53c7) Z8(ebfbcea9,cb73d940,42b5ad6e,dceb080b,564b47cd,f620ed70,3ddb8b42,a86e6274) Z8(7b3c8a90,e2c24f7b,ff6cec9c,89a563e9,33ca5281,708e4300,b5f4c145,b538c781) Z8(24c08161,7c5f7fe5,844b4bc7,e86d9ee2,7e0904a2,bd843a80,6f047d68,9f1a2e7a) Z8(16743765,88712110,034843cf,1c16f09b,a1760317,3a47054d,e93c9c74,73e8df8a) Z8(eed4c843,a047161c,dc5afe2a,fa8c6dd6,644009ed,c1e6a872,ba4a6521,284ac3fe) Z8(34b59afd,812f38a0,087fdf23,50c1ef65,19b640ce,e499b9ed,e56b4b9b,16f0d28a) },{ Z8(317b6065,79b2bad9,67a7871a,d14e0511,7ae56455,60c3debb,f4c3ca8d,799670d6) Z8(d73b91d1,e5ca501d,945c8783,6c7cca6f,a9012db5,4392849c,6651b13f,75ec938e) Z8(45be3d52,63d0322f,dba7e9a6,a325de16,84fb154c,e6fe1bae,e5428ceb,b0c11587) Z8(bb281c4d,07fec58b,8b1bfb0e,95a86314,f3f82954,0197c872,f36fa170,6ca21d3a) Z8(555452e6,d3233d7c,fd4475e1,ea6023ea,a34a8eeb,cd021f3d,3541dc52,6aa43fc0) Z8(6ec6be59,c4081185,215b5d90,6427f311,13ea7282,f662447d,25605e9b,83b723a4) Z8(fbddc36a,c44638e2,8cc78293,08ce1d1e,b31540e4,e6fee1c8,833ff35d,e3e8d516) Z8(b21fea15,84770c13,d060df97,2cb3453d,17c25ffa,0f2bb1a2,a2c60d16,4c45d546) Z8(a8cb89d6,b41fda65,1364247a,5f3c5ba4,a1f1663f,75af3c47,eaf066a7,ad80912d) Z8(78573307,198be1f1,ec729fcf,23ca0530,f16b0557,9e19b336,f820e4a9,994a06f8) Z8(e5455baa,16517d32,5386e25c,391e4dda,fc7f71bf,831db4c9,cea5c2b2,f4634c2d) Z8(e370dfb2,a0b0be49,a6b48112,4628a890,a8880ee6,eb4db477,c0e4a00c,576133ed) Z8(27a06c7d,afbb1097,cc9021be,2bf402a9,47c43e76,d53a8362,b3997a4a,e634d5c4) Z8(7ae476d2,e2a9cc19,9d0a1ca4,88ae8411,d2d3c05c,375c1b3d,0fc7d00b,e56ad541) Z8(49f361f3,050013c1,7abe8667,b8b91190,48b72758,e91a8c65,1bb0f03a,48c4ea74) Z8(0574e2e7,e2b3fa40,5d60e11c,10568afc,64ae411a,3f5b4ef0,d608e6fb,51dccb81) Z8(ec0c6459,286a0066,f9a71577,fd2c1f6c,2646cc77,a023f574,cfca2ad7,9e05a342) Z8(ff917c95,dd0897c1,17f6f957,b94ebc40,fe9e155d,ea87ffe1,2af2e5e9,1e27076e) },{ Z8(65a865b0,bb152da6,317806a8,161c75a8,88f43e10,22a640a8,aaa1f1d0,d1fad5b3) Z8(1a3eb389,5663f9ab,939fff29,b69fada1,007d7fcc,9992d931,e77e4b72,73722742) Z8(841948e1,b80c404e,22a8cac2,58742129,3d92be47,a38d76ab,d4cb37b2,6e988725) Z8(0783beca,4e799f33,bc4c938d,f495188a,476f2c71,2a4ac5de,9c3d6d46,e73bcf5c) Z8(19dc0066,f19afd1e,8dd2d0d6,644a0695,f533f861,8856fc90,1fad0bd3,ff60b2ec) Z8(cdb39216,16d00cf9,9502fec9,eef85445,c8d783e8,d9ad619d,c3bfa997,931698ff) Z8(bcc64593,e138a38c,e435f79d,8215514a,4bb2fa0d,ca16b0d3,dbbb3dba,991fdce8) Z8(f3a07ce9,a7dab128,015e3077,b08911aa,6f4ae26a,d7d653a5,0b6de163,71e1d39f) Z8(35047ab4,3e9f51b0,a659046c,7f074d39,74e36640,58eb2c9e,62897f98,d43a90ae) Z8(a7048dda,94e91b28,a5475ea1,84a6dcb2,91402160,a9e0a8c3,b0edca41,418247fc) Z8(98da8c0a,3175801f,b9039de6,a2ccfddb,77dc036a,d69b44f4,bf55374d,2b0801b8) Z8(126c2c2b,96132c80,271c28cc,244b0a09,bd38c49b,1dd15fe7,5e7efe43,e5f2303b) Z8(a072ec08,28ca7bf6,0fc24a52,2c7566d0,0480aa8a,c2d8f531,6ad27764,fe8c26e6) Z8(e3ac4442,fc184fe5,1df59f75,1d369a57,c2f3c6cc,de8657a2,fedbdbd5,63b2ae75) Z8(2dd22765,b643e97d,3e3419e6,9b69f799,4636d8cd,5c613b65,51ceb731,0f7ce81d) Z8(9b4ebcd3,1c9f3964,2710c256,d86130b2,3751e986,b3125ba2,0d56204a,4d8af0d6) Z8(c430292d,47b9f129,7a3b264f,6d706ec4,36cd3025,e399a8f6,c81786ff,bdef2e4c) Z8(de50d341,3603f226,7e29fbad,fbc9070f,edf4d109,0bb8e203,3fea4698,252aa5f0) },{ Z8(8a42f529,ccf60cb6,40e39f84,85d2a5df,60d5f1e0,8c1de05f,d0bce7ca,3999d1a6) Z8(501a7b8a,0fdfb2f9,6a746aac,494541b8,8b2ee27c,3404d407,376b79d7,6588ef7e) Z8(52dc645d,acd0f6f0,f01134e5,03cb99d0,47b83307,e60f97d9,df89fd47,f4d99bae) Z8(63a060cf,012d251f,74702a99,68e1c2bf,d5f50870,4f6f220d,dfc3e302,2d6e9aa6) Z8(c0d6d272,f0ab9f1f,31b49779,d8f74cb8,21a62355,767fa66d,6a69981f,eb8fbf0d) Z8(b8650cf0,f010dcfd,bd5c53d4,10d0345c,9f13c00c,cb818633,74edad6d,63b6d616) Z8(dd92ab19,924d5191,e58598be,2708a2e4,cc1accbc,f9f58a4b,02c8ceb5,9178dde1) Z8(125b45e1,fac5c842,01fd4c7b,2f3678cf,4997f646,4ebaab65,745520e0,c20a63fb) Z8(2fa015a1,d762b2c5,f874dcbb,603f423b,0faf2e9a,fabf9572,5fa1e7aa,5b0906f4) Z8(fcf59afd,b1429ee7,ba297f44,d743c796,a0a51fac,dfb4e053,35b52ae8,95eec92e) Z8(688fc4b6,707409fc,0e65f970,f9098331,0dc5f44a,86a302e3,7efa4e7c,9e7ee42b) Z8(d7e2a046,7ac3b84b,00094a7b,20ec2478,6eb2c9cb,d00a1bcf,b1427193,f4080757) Z8(ccb18c9c,c9273566,f170aec8,208b9c36,7237e620,ff3aac31,70b5a44c,f1101f66) Z8(de5f035c,b9178605,ea47f5e6,f09223de,c72c9f3e,21b798a1,5728384a,e8323e47) Z8(6fcb8911,e53f634d,3017511b,d42ac352,5484a0aa,8e3c319f,ccfef3b7,159a0fd6) Z8(7aa0ed67,17dc4f5a,aa0ac9ad,854246d3,c711da9f,3305691d,254cd485,5429f714) Z8(fb5d87b5,ad7848e7,b88a7375,4baeb699,b541268f,97d44cc5,023311f9,edbafdfd) Z8(d928291d,c0acfed6,fdf3e631,d55c7355,424775fc,e7c4140e,4f27a790,2bfe60e1) },{ Z8(73c6e1a8,93afe235,9d494ea9,1bf52b80,d62e60e1,47035b9e,72c0fb22,8e1624e4) Z8(c2e5662c,22c01ec3,e5bc6f1a,ee023290,9f1bb841,f08b56fb,17c637a6,3b160cef) Z8(c2ed0944,322a5e39,e2fbfed0,7a63715f,650c239d,8b9b7d5a,73604294,cdb5e0f8) Z8(1bc73424,c90510b1,42b6361e,a84b9e24,1091c683,8e301383,2bf32614,b3059ee1) Z8(01d167d2,ac75ec17,4a0c8999,3ac897ec,8381fb22,2eb34f3b,eb79ece4,cd1834e8) Z8(b3743993,189fb3ce,02520543,f441fc65,e6b4e2ab,f5b61922,83b84d15,8aede031) Z8(5faa45bc,0494d9d8,d0759bd6,397cd539,705ff257,fce7d4dd,931aadf2,4861df1d) Z8(5da224b4,58470895,a29ade58,333f949c,3d7edbc8,644e319f,a894cd13,da446a9a) Z8(88153598,0d80a7d8,b7ad3eba,15ef3bee,06990f8a,d5d0da41,d424da09,4063e4d1) Z8(2502e78a,1ca0d680,438286a3,647a077c,1c1734cb,e08af200,4d40777b,90a6c97b) Z8(c3e3240f,0f1bc64c,b040ccb5,2115d1b6,c3ac0195,af606fbf,2ffe05df,bfd06902) Z8(a75bf235,75870acd,42ec1f6f,abb7e04a,b8204831,6e96bfdd,029c1d70,419df6c7) Z8(c16c1cf7,73786b50,92cd1c2d,632d7841,ebf529f8,a80404e3,29f5a6f9,4df7dcfe) Z8(2ca9da26,c3a3c4a0,bed0ef07,52dd76c2,4d708681,b2901923,c6b31281,c966639c) Z8(0cd1d47e,3f83a655,e2d1147f,6191fb6f,3ff9a5ea,290cda1e,e439aca7,5dae3ddd) Z8(be635560,362f741f,69c853a0,2bc23c26,f95327dd,190de9f6,dad45f30,38a0bcdc) Z8(46577c95,17b14e86,d8375221,45a5f1ba,77b20123,421b1cf7,978b7d19,9ba61844) Z8(d7f0a39d,13daa19e,71766947,a0bed3cf,712cec4c,8260ea71,e8ad68ec,32a4b539) },{ Z8(7442e81f,1c0a2524,dcaf51ab,3d71af55,577748b6,89f7e90e,f77a92b6,f2f1f423) Z8(f33b7135,e59a5614,351ab91e,9a24cee1,9332a81a,a861180d,b3d5069a,5be9dafc) Z8(8f7f165a,f37e0d9b,559bd4af,0f002992,4f2e1f76,746c8b0e,0d91de20,1ef9a170) Z8(553d662a,0eb53f26,4b8c8048,ce0b6a3f,acbe9997,aa103201,fbbc65b2,dcae61dc) Z8(f5382324,51555fc5,5476ad36,8396fee9,6357e90b,afff62a7,cd8b34e1,bdaa61a9) Z8(47f63b6b,b9f56fc9,05d648a4,99ce2192,e19e98a3,58f814af,ca5165b3,b00bf20e) Z8(c9e3c692,cf8eb5b0,7f4ea3c9,b5c2afaa,2e06e4d3,72238f02,5356ae57,63db5620) Z8(d1cceb12,58b02326,cd306780,78cf94ff,79097406,0dd4de0f,403ac2ee,106a192f) Z8(c1eeb44a,08d5c551,c4f8ff99,4945b599,619c2286,c5405721,aa3fee7e,09b25725) Z8(23be1b4d,29453eef,b586211b,24b7618c,40d02355,8540b973,c02cad20,d7249a7c) Z8(95bb4d99,14cefa6c,0efdced7,9f0195e8,ba5770b3,8395a571,24ac72aa,1de0e914) Z8(38087b12,804f8baf,d53afd59,8c17fdc1,647ec3a5,a14da4aa,320bcc12,87c11fac) Z8(315ae461,d9d2c797,f1e24d9d,6b99ba86,7c9f7fd4,ba0dbde0,e5b396f7,4a5db8ce) Z8(2351dc41,f4ea380f,69d486fe,c6f75450,f8ec637d,502f3dcf,c2d7c7b1,713fe0f4) Z8(1e5824b5,8bf1ceeb,ca54dd54,3c03dcc9,6951da64,58ade5fd,b55167b5,d1333657) Z8(e55f390c,d5380a61,172bfb37,8fdb6776,2eec1e73,89070cdb,c3518a2a,24ef8447) Z8(d75732ea,78383094,c087279f,e9fc85bf,d08de46d,3103360e,7cdd3baa,a192a8fd) Z8(64bfc746,70f133f5,11adc1b1,c765ea74,ff734495,4bb03de5,35344358,391fef8f) },{ Z8(1bcc87dc,0b70b675,7f3526de,2789a6aa,414b81ac,0121876f,8caed35c,b9eccc37) Z8(d4d438e4,0cca6150,35527383,96f82b0b,7319846d,0708a8e9,205a1d1a,eb0af878) Z8(bef4c735,4cf65ab2,30f19eb1,50143a6b,2b698ade,5d24472b,29084537,211b9070) Z8(e4df6647,fd57b4a3,0117514d,b56ad732,dea6b4d7,73a6706a,fdc785da,91668102) Z8(f6341a07,80208eb8,977c75e1,6fcd5445,79093c88,025632ae,ea19dee4,6616c55e) Z8(cb1535bd,3951e433,c3d7f085,8fd2c0fa,5d916a81,a50c2820,5b14dc2a,919b37e3) Z8(91861127,851ff0c7,3e9394e3,ac6e236e,3b4227b4,0e2f521e,3b3ccd2a,2062c180) Z8(e3807e99,fb7d344b,192a4768,f3678619,44c27a29,736ab683,ae45fdbb,00b577c2) Z8(5d9b9b74,7b80c02e,21291b06,cdfbd017,4d577186,97d970e1,ef6cebcd,2950f968) Z8(55745729,e1524696,0370c6ff,3b3ad97c,2c09e208,60d64766,3e63ff51,ce315094) Z8(90ccc188,28979729,d789d9c6,ebc7b9ce,11ce5702,fb2867fe,280ca605,ccd6b82b) Z8(5e629534,6bd9cd81,4c955faa,14636731,c9b403b8,49461317,c95bee9c,44719507) Z8(23deb398,f3621881,588bfea0,9ba4d984,8e0fb150,58d908fb,01fc9c57,c8dc2c3a) Z8(ef611e33,d24e5e70,2d4dee31,aa20da31,e4178b91,6349296b,f0171a8f,8b44cf86) Z8(59392d8d,a8c37f53,de27245d,48396d97,3e4dd588,28d3211a,c355fa60,de70e498) Z8(e3f9c129,91858558,f66faf7f,24b9a3b1,a597a520,5ef28bef,987d6ab4,9c2c4256) Z8(eb00ad03,63a59c53,435a44c6,c58402fb,09140995,c7167255,6589e221,e9c83e0f) Z8(6916ddaa,165f74d5,b22c817b,40584455,29a59412,aa8cd86f,bc7c551a,3f7230da) },{ Z8(4023e70b,1b88c103,b26d88bf,de91eb16,10afadf6,7bb86a7e,9818de83,c924ab5d) Z8(b916bfd9,3a7b8a09,f7ad77a8,ed8d7896,62db8b72,cfcbb9db,8224a768,d347bf06) Z8(a7163d92,30b615bf,e2e004f5,ebeed109,35b3f740,f8655cd7,78964362,4d9ad030) Z8(293cbd6f,dd3367a1,af0e0faa,2068e812,dca2f291,32ffacc3,ceaae415,ef918fb1) Z8(50fca543,3e546ae2,251e1ff6,66f8f53a,32e7e0fb,ae4d2d14,82f4b84b,bd63e7b6) Z8(49fbf67f,57639dff,be268493,d619b7e3,30075d0a,72f1971a,874e1441,4cc6d128) Z8(9403ee8c,251a3e87,8680f3ac,863030c6,ebba47bd,df3cf144,9d093d92,09b89dea) Z8(c629e2fe,d76da74a,1ab732e2,07bdc279,4ecc0dd8,f3cfcee1,54502c15,207e569a) Z8(524ab2bc,e39dc411,6f485072,4ffab833,cd606f18,e9d28e2b,aecd77e7,61bf789c) Z8(57427104,4d5a946b,c67cc941,293d90f1,9b3c372e,69cf285f,f298b398,0e42ebab) Z8(eac6c943,5ae6b18c,958daeb3,d963ae72,426597c8,7bd180fa,b1f1b295,3bfad217) Z8(02518640,8649db8e,bdf73804,24f5f4e0,520c97bd,96ce885f,f9634a0e,d7211bab) Z8(375c2534,6f8ba8fb,00e51956,6db1760c,57cacdce,8b5264da,9fb979e3,dcce1842) Z8(1f5d4383,1dc40f68,622cf0fb,7e30a059,6c3a7803,ec93ab4b,78aedf61,3aa8b636) Z8(3301f889,e00486bd,8ee62377,3b761ba4,552ad70f,54536e14,963e3236,2bb0b135) Z8(6efb6b72,b74ae444,f367e943,f15c1c84,3d9f216f,de538cf3,2214fa29,9733260f) Z8(1638a398,cfef8350,794371e8,85bd4ee8,4c529944,8bc0169b,dc48152f,499727b2) Z8(95940f17,c3c8dc39,3c19f534,067d04a4,1b8b823f,731f55c4,ae98380e,459d72ae) },{ Z8(9ae9d495,f96e9f6d,564e2260,8481c7ac,8806d5df,4a5cf091,1629b65e,4c9c0a05) Z8(e9f6a21a,9fbb6f3e,fba695be,dfa02307,05443e68,ad216579,2ad242ce,b7584b1f) Z8(247b56cf,15eda691,92647eef,6c0c8109,a83b791b,6e61c067,d31669f6,39862d51) Z8(c81dbe77,ca8c09d5,b685d840,eb238ccc,b85834f8,b8509493,0bfbc590,fdecafdd) Z8(aff2b441,743d2c1a,ce4e0c53,825eaab4,4a935e33,1ac16cca,82c0e49c,e6bae41a) Z8(ae00a625,61c11258,25ef48c2,4af2159d,902854bb,05dd8267,2a15421e,a8d3c3fb) Z8(9f60e612,0f26144b,722f0ad7,16e210eb,95577e60,c8a12dd2,e5fc4548,0812d7d9) Z8(2d104dbf,b24d6c2c,5b8496f6,5172b1f5,0cdc9a51,eb7d32cf,4413f2fc,579325f8) Z8(a79cf4b6,55b497a4,029be484,c78b0c4f,277b499e,c61a28ab,c7c05c1f,b06ffcb6) Z8(cbf64eef,4f4fa24a,e9e94d0c,9eed2c7e,bd8d5b21,c1594f22,c288316b,36a89942) Z8(867893f0,7000e7b6,6143c1ef,85b677c0,2aa8b45c,c08c4489,c85dabb9,3186234d) Z8(49fa6233,3480816c,40679b49,dafd513d,d77fe56f,bd5ea8fb,1327cb42,bae01451) Z8(767ce498,cf645102,ca71cbf0,0f2347b0,751ceac2,c5b92fdf,db7ee0c8,d605469d) Z8(c8e9bd28,126ab045,e84e95f3,725cf347,6623566d,9f673ead,1bc9473e,51255aa4) Z8(56548f5a,bf140405,fac38038,a70524cf,8eb79992,57858cfc,ec9786d3,fc108b85) Z8(e7ca878e,8d7338b0,0e1e896f,16ca0ea3,7ebe01ee,1f85c6f1,cac6b8b4,49361936) Z8(a3830fa5,53c8ac43,ff797e15,519f62aa,8d291024,3f7d530e,20cd5936,f5fc616e) Z8(3164478e,4cf26755,26f15213,77ad6fb2,206cf37b,b3246a14,8474c270,4ba38aeb) },{ Z8(0612cb86,ec7a530a,6118ee9e,9c5d9ae0,fdc42cbb,5a1e1e4d,708d4506,a550d48c) Z8(23ed8774,f87f5755,2df9defe,7a6b0c7e,36a1c6bd,9b0167e5,d109e9c8,ba3eefd8) Z8(0953bd9c,f30efb99,53d972f4,60f4c534,8a42c9d0,fcbc3424,06ccf9d2,558dbe51) Z8(a43307fe,7b0c2f06,861a4272,0a3b8cf0,cc5280b4,614370b2,53c9ac43,178f140a) Z8(9c682b3c,9c02ab7e,e44de1b0,357ac4e1,ff4106cd,3c17cf28,25fc64c3,574e1cb0) Z8(c2e6cb15,66aed69b,1839fec5,869112f6,e516b51b,87425856,e142c0e1,4e41fbe0) Z8(6df11bbc,a97fe7e5,281db524,f2da2ba5,7fecfb22,9e7616bb,03f03924,aebc4efa) Z8(6bcb18f1,b461dec4,c3ffb31b,33878157,072fc167,3c408965,f08b14d2,e0289859) Z8(cb9b8391,1d0985b1,4ac58797,82d72e76,0276e6e7,9668cced,1b25d2b1,b86d4230) Z8(5333a1ed,86581d1a,5f645447,fd87291e,d280e810,b68149ea,126139cb,a5b23b80) Z8(191d6455,a7cdf8de,bce50c92,5e93f836,1f127303,acca9acf,57aa7b81,db7a32df) Z8(44b8c1d6,b9cc73f0,5ca7f4ba,2f6cf9a7,825179bb,dbae9a06,a293cee5,10c0ab09) Z8(c16fe031,0f8c5b86,21403f6a,5011f988,18003e8d,62b90fee,9e463976,b496a0fa) Z8(9413c082,43f4dc18,9b61121b,f309b783,8d70f1e1,f744b9cf,918ee64c,dfd70ecf) Z8(cd2654d1,07605ca7,9a6f0420,6a34c984,838f961e,7b6d958f,140597e3,74b377b2) Z8(c8436028,69c032dc,6ba62085,1bb89433,f388281e,e487dc93,5f0fd381,f5d8d696) Z8(8f613c57,81891c55,7336c01f,14e48b95,72ff7a30,b092567e,bba85f7d,af120d6e) Z8(a973fc98,b5eeb55c,0b44393c,72cd24c0,f1cd1057,2decdecc,717b09f4,51862f08) },{ Z8(a5be4884,95bcdffd,4456d8c5,0ebfb467,d25cad0c,eabbc7c9,ec3e5d43,6c8864fa) Z8(ca770307,cb64a632,c97740a2,06a19950,3c33d5d0,ebf39caa,1a26b7d9,d1d66e8b) Z8(d53d53ac,574e3fca,3143be56,b22607a9,d42934c2,5b6aa6bc,f2d46b0c,cfbab6f7) Z8(10658277,16b404b2,d6a87b56,63b3cd53,a0b6c2ec,aba7fa74,ef2c0722,49507f17) Z8(4a8c760b,24789d42,51bb2318,6df722d4,06a277f7,7d0181e5,02cd1134,284ea16a) Z8(b6bcf9c5,7dfd814e,2731a635,fdf614a3,f5890b25,4f5a592c,efb1c44f,33c315b2) Z8(c5c189fd,93d4ee93,0c16265d,be90ccc9,e11c25b7,592270ca,d696a1b5,47c42b36) Z8(83ecd528,dd272f3a,9d914717,a582da3d,90cbd400,1d008fb1,e300d004,5cafee75) Z8(6aba3e20,bcf59fb7,d85d2413,a882113d,038d88c5,3aef9369,95305526,b732e853) Z8(9c154e54,42d120e0,a1f8c0ea,488166bd,323b28ac,235a6caa,b84d91ca,706ea175) Z8(7b00a944,2b20779f,6284b133,d81fe3c2,b6d6e272,06b35a3b,f352355d,12443541) Z8(1b795ac5,210049f9,7bef7e6c,d240a652,0d06d28b,8c9b5922,f2f06c1f,df225399) Z8(58fb50de,898dd82e,be726f5c,978dbd30,c463be4a,8f484142,994d1142,30928e93) Z8(9e365314,d7940428,06dea3a3,4fa5d862,cbc023da,878b590d,d29f97bc,56aab635) Z8(684b86a9,90f1e2ac,451363bb,f4bcee5a,b20901bc,41c87262,d10257f0,19f820cb) Z8(ead41bf4,b7ec04a1,748cdc54,a031f272,939a5f8d,c8625bcb,995a7125,76cc4fc9) Z8(c3639743,a0a230fb,ba2e3d16,e728a52c,f6d4b0e5,d1272b82,4ca76681,3f984c40) Z8(645143dc,4df9cbb7,29a4bb09,80b4a6b4,fe1159f3,36383dc7,60272942,5746f6fd) },{ Z8(148eedbd,d6cd0faf,adb4656a,f6736f6a,3d786d45,a2d092d9,6b9d9d3e,a1e54382) Z8(d42e0e5c,9631785f,0f9ade55,9fbb548f,a4edb9df,4abf39da,239d1c84,21be2772) Z8(095d8ac6,053fcbf5,c12fb3a0,451242ad,193861ed,594ca42c,0fc100e6,bae8ccbe) Z8(4f6f4ec6,d43181ef,891db369,db34811b,fc04d1c6,07e348c3,e2e470f5,b37fd8cc) Z8(2db3c607,df17255c,0257a453,85841a25,f26726a3,06620d61,12472a5c,79b2c903) Z8(a567e591,9f37481a,d7e31276,cb603fb9,56687e6a,e5156aa5,02a6d3c2,a3d22f29) Z8(1bc6bedf,02c7b74d,03b112d7,3aeb204d,2b7408af,6cd1b395,9b18a7ce,9f780e79) Z8(b578544d,600b44ee,7e106ac7,386c0fc7,fe0a230c,8e55e19b,4db33259,b33adaf0) Z8(ff79743b,926c31de,2965d39e,568a8345,9eef4c0e,1a7acf23,701405fb,d3a9912f) Z8(f42ba3ba,d1283956,01e7c515,f7495c2e,b441f146,74c696ea,80876122,9eb2b6a6) Z8(735797ae,cc261104,593c2d80,97f6b16c,ceff3e54,30e5359b,1d2cb12d,a966de2b) Z8(be20ec87,a47b1f62,4b4d7d0c,c5479af5,10def303,e9cc14db,5f752c22,a3647d7c) Z8(0fe37fa0,afbac125,d1a864be,16a84ec3,a4ea46b6,64b47b73,eefa8b3e,17573850) Z8(51083bf2,ce597016,0e401d73,9686e75a,c51bbf3a,6959c938,b98ab20e,3c8a2b37) Z8(1d51abb0,354994b1,c3aa011b,c3bdc1c3,c55f14ef,56f033d7,19f672e9,1220a8b5) Z8(63a1e7af,bfe6ef86,021f561e,7b577405,a6b90d5b,c209c254,ef653efa,9552cddf) Z8(b1351588,1f632a2f,97f25769,e0427ff7,9e14a268,c49b7c7b,4ac65d2a,505d2dc1) Z8(23446f02,bc92784d,a59757bb,dde10dce,4fbde5aa,89314feb,ef401a73,5ce75fda) },{ Z8(82bfc4cd,da827cf4,2bc7431a,388c9aec,9b4592a9,aae22a29,12a167ac,33a320f6) Z8(ab5a21b4,c80b11f9,8c28d4d2,da4840c9,e228818d,4a330ece,555329c9,b97bec3b) Z8(cea22e35,e07e6485,d1ebeb1d,d557826f,f0e0756e,c43eb060,a6e43e14,6fe7fcf7) Z8(b6c13dd7,23bc7ff2,d2e907e3,7c79fd89,a581d91b,44550be9,e41698b8,13996c2d) Z8(54862521,0960d624,455cb796,a94103ed,b260c21f,33e29ce6,7db2571b,37457fde) Z8(ace36dc9,496d9dea,4757bdeb,646f727e,cca2673f,33e3484c,d459bce5,25b3d375) Z8(224c4315,1f1f0a63,82690701,c36d8543,12fdc746,d0b4e277,cf651227,ccd734b4) Z8(4d991f4b,1b82456a,79abd6b4,b8f70481,04c2ec5e,14426231,ffabd88d,fe32a07a) Z8(615c61bc,aa44bbc8,66e6de4b,9ab5a04f,01c53d5a,7e65f583,ffaabbd3,4b921152) Z8(e1fb36ad,b76429bc,73396fb9,49964a84,90634cf8,3cfa893d,63cfbf93,a9a9e551) Z8(22976cf1,f149270f,4e174d5c,db99363c,1bc46f67,e24a10e8,fda6d2f9,9b7103e2) Z8(e1036e90,e9477824,10230f1e,d3845aed,450c052a,9f430e67,98f70e42,5572b165) Z8(f730da65,3369e9e1,a0a55e7c,ea4cdb3f,cb17e86b,0d5ff8dc,2cfeb350,9f1c3739) Z8(899253a6,40ad49b4,1a15170b,882e9896,7d0707b3,b8ac12c5,f4bbd8fe,fef59505) Z8(39be50ab,517142b5,c48fd2df,77fc94ee,d4d65095,5a7d27e6,a9f65bf8,d5a40aee) Z8(122a2c73,a121e9bb,285e0cb4,189c6b4b,67672a39,33da365a,66257014,710925df) Z8(d94be1bd,507eaadd,73edae34,778b0d38,f0427892,29843ae0,20267cbf,2fbbd968) Z8(c6f53831,501f739c,0515a31f,c63281b4,f055b3ff,9c620440,05096ad6,6268ce1b) },{ Z8(d518ce82,81967a53,c2e585a9,11fc9c13,90d51531,33777c8f,6edd6cb5,dc1f5abb) Z8(7f1b2b76,24f7fa19,c6da8632,19312076,1987a8d8,82221bdd,504db726,7de3ff1f) Z8(874c7595,3d97736f,421d107a,c9d06f05,c972cf35,bb3320e9,c0bd6044,3fc6443c) Z8(b3e3b0fe,33b7213b,b93e8867,80f7c1d5,77dae34b,4c624cff,586bb44a,bba9977b) Z8(fb0b45cf,8d2db23c,67c7924f,a610c6ac,63af3267,f13815b3,88c8286c,ffde4210) Z8(ff729161,cdb51bee,fc494b74,a9ab7ff9,ec69c97f,9093fd4c,720d6dd0,6d755fa3) Z8(020b6ebb,e2538ebe,fbde42ca,b570c01b,f81089ee,7660054e,a9143d0b,0d64801b) Z8(52fc9a04,48191187,ccfa8050,b76a6495,521499df,b6deea2d,86f15872,56fae945) Z8(9f0221ac,ed551b42,079995e7,7655d68e,623dda9c,0b90e80c,2f06a19b,79105b41) Z8(54835dd1,d8306462,be049c01,bc9d5dfb,0626bca2,89d92a66,55c334f3,f3301a56) Z8(9ad50e9a,bad11925,b75a4abb,2056e09b,b46fef38,18a778d2,c0439f28,c4e04ed3) Z8(fd52f66f,d67c644e,01d97dda,26bb2f49,034e4eb4,2af51a01,7b24a1a2,3e63e790) Z8(7cbb3aed,7dea9751,b011b985,fc602887,7e1f05d4,4f3f354a,47918598,7ebd6e9d) Z8(c7729534,2febf7fb,cc948b5d,bb8290bf,315c88ff,cc34a61b,8591e5cd,f6afcfa9) Z8(2c999bdc,ef96d5c3,d4efb504,8f0c598b,4073acd0,ef7d1991,dc8b1c82,5dc9b912) Z8(3de66d19,0411cd96,074ba0ac,65209360,cb153ccc,2d139480,fc29e7e0,4839cacb) Z8(febb0e3f,a7e09dc7,5d6f9b5d,752d66d1,b8a073c4,fadca437,9edaebb7,c2df0cb1) Z8(c59e3b60,b38ad78e,4547d7c2,7d20ffb3,01488606,da35d9bd,fe612fca,67cc8fb2) },{ Z8(4ecc6db1,bd5ec72d,fd338a63,ebd5d11b,a679f797,96acf640,3b6df279,18b2e5e4) Z8(9af1ede2,8f2cc3f5,5afe67cc,6e9e26be,1cb5e930,5c04ef1a,9df79d92,30a2ea7e) Z8(086e3dd3,fd9bf950,ea182043,34b7c3fc,e66cd935,09cc9dff,0be9f9da,ea748ad9) Z8(97515e90,b26809b6,d3002447,ab296d10,c54dbbcd,64679114,a9e626ba,72810228) Z8(4ca4f7a1,a9859848,4cf7ca0a,e391c689,c285330a,8f983aea,d0a79444,10238fac) Z8(25312ea6,eabf2a79,5af1ab95,480b7cb6,4c244793,ef80e9b7,e93bc9e6,15d67eac) Z8(2c2a19ae,85ee442c,803a64c4,0392446e,245f4e97,d77b00c1,b6d287c7,2f8866be) Z8(da33dbe6,2a644281,650d862e,e2c83fb4,85d5bbb5,d873ec20,05da4b15,f4b6d7ee) Z8(fbc9dba1,131badbc,cb2c7c6b,40b914c2,f8cf77f1,5df5e00f,72aa8928,15fe600b) Z8(362daf01,812946e5,a086f2b3,2eb11cb2,450d6905,35849d88,ed108287,833bd05e) Z8(f04836db,9f7be5e6,d7947b0a,79a90f0a,884bbdd2,74854d2a,953da278,83925801) Z8(21322ccd,6be2f8d2,d539eef6,03c34130,fb912094,424f5c46,31e1f410,56e1036a) Z8(4717ddec,2f5c415f,353a10ee,af6ee96e,67d15d26,416a4652,8bd9797c,d3675ac0) Z8(c3d61034,58de52b6,274fc551,73b2bca1,05a12faa,a1cb3b59,e195eeb8,8fe6972b) Z8(1c108f1e,bb08f9b9,a30dc088,be3325b8,619e86c5,bf8c4fc3,10cb7431,0e9c77f7) Z8(d881f3fd,8be1ce48,896ef16a,d261ae0d,169001c5,7d4bcaf6,6e210d58,dc89809c) Z8(4064e2d7,77750639,f8dfce5a,0e4e7e63,725e6611,775c37c2,e8c5ff87,f528ac22) Z8(2b96a198,aa8920b1,603cf111,53ab4d08,3878ef20,fbb6aba6,323d8a32,6d13ddef) },{ Z8(e885d03e,38144a48,b95ea356,7ae35eab,aeee916c,13efd21c,eef5256d,e5e3e847) Z8(e676e26b,cb34ac29,6a35723d,34499dc2,26655035,50c2301b,67aa0d35,b7d3b5f9) Z8(1efe2cb4,e6fc1b37,ab37a95f,1e005324,9e5c3eec,e8d9161c,1b23bc40,3df342e0) Z8(aa7acc54,1d6a7e4c,97190090,9c16d47e,597d332f,54206403,f778cb65,b95cc3b9) Z8(ea704649,a2aabf8b,a8ed5a6c,072dfdd2,c6afd217,5ffec54e,9b1669c3,7b54c353) Z8(8fec76d7,73eadf92,0bac9149,339c4324,c33d3147,b1f0295f,94a2cb66,6017e41d) Z8(93c78d25,9f1d6b61,fe9d4793,6b855f54,5c0dc9a7,e4471e04,a6ad5cae,c7b6ac40) Z8(a399d624,b160464d,9a60cf00,f19f29ff,f212e80c,1ba9bc1e,807585dc,20d4325e) Z8(83dd6894,11ab8aa3,89f1ff32,928b6b33,c338450c,8a80ae42,547fdcfd,1364ae4b) Z8(477c369a,528a7dde,6b0c4236,496ec319,81a046aa,0a8172e6,80595a41,ae4934f9) Z8(2b769b33,299df4d9,1dfb9dae,3e032bd0,74aee167,072b4ae3,4958e555,3bc1d228) Z8(7010f624,009f175e,aa75fab3,182ffb83,c8fd874b,429b4954,64179825,0f823f58) Z8(62b5c8c3,b3a58f2e,e3c49b3b,d733750d,f93effa8,741b7bc0,cb672def,94bb719d) Z8(46a3b882,e9d4701e,d3a90dfd,8deea8a0,f1d8c6fb,a05e7b9f,85af8f62,e27fc1e9) Z8(3cb0496a,17e39dd6,94a9baa9,7807b993,d2a3b4c8,b15bcbfa,6aa2cf6a,a2666caf) Z8(cabe7219,aa7014c3,2e57f66f,1fb6ceec,5dd83ce7,120e19b6,86a31455,49df088f) Z8(aeae65d4,f0706129,810e4f3e,d3f90b7f,a11bc8db,62066c1d,f9ba7754,432551fa) Z8(c97f8e8d,e1e267ea,235b8362,8ecbd4e8,fee6892b,97607bcb,6a6886b0,723fdf1e) },{ Z8(a313e03a,7fe87c4b,bb1f8a36,71f3d7bb,bf12d5bc,3faf5bb0,141058a8,3d0a5942) Z8(518f2c01,12f60820,a95ee857,e7c5fddc,f55d8460,7e4c218c,5e62a8eb,2aadfbfe) Z8(9ab9eb79,191b19c2,7426c19c,9f0ce652,6f90267c,92085120,bf82081b,b53be888) Z8(64bfc2c5,67664817,14a03d05,9296860a,6fec3396,ae153f23,97dc02d4,5106d162) Z8(5ff1961b,c03ffbab,9ad9f56b,b6c91591,0abe0158,d60d21c8,152de5de,83dfac63) Z8(920ed65d,b5f7ad1a,278e1f12,893292af,b47e4023,145eae39,1b439331,f857dbba) Z8(bb55e91a,20d1d5d3,f2108d41,a16d24e7,1aa82d34,341e5733,06eeeaf8,5f156d6f) Z8(cb67501d,6f5ee32b,5227b8a3,ecac8858,2343a815,85447114,381841c7,8c5a1bd9) Z8(11b5a2ac,c36fb44b,26739b9f,a069261e,ccacc6bd,5414db3f,a659c718,38db7d63) Z8(8b7da137,2624239b,a174e174,430361a1,383bd252,5d738149,5067ba04,b22dbace) Z8(f70a9561,897b04ad,8d4d7225,4f15241a,097b4d15,eb26636c,a4c21401,2cad8204) Z8(e8eabe38,8b0b198f,75284021,17f4f804,91b08887,ede14962,7768726d,310af974) Z8(eaeeccf6,acff492b,c8b233b7,8330ff7a,1dd6e363,ece3b047,0a618bf4,08209fc9) Z8(511efec1,f13a8271,d3799bb6,7dfd988e,f1347b45,902bb6c7,18f4d9fe,5c4631b6) Z8(d27363b5,e7f6a4e8,8d47586a,9ef6b707,da6574cc,2bd936bd,7497fff1,ed5d9966) Z8(2cd04071,d67af953,7b1dbe1e,3206193d,eeda1b25,0e08ecc4,5b609a0d,b137c429) Z8(76a1ca55,43a3f551,4518e0fc,0f1e32ef,3e5b508f,8b63c711,7d60fbbe,2451e71d) Z8(5c94d3aa,250ff699,bafcfd59,50684ce6,76e1fe9f,989a9274,071282fb,7751a813) },{ Z8(17644fc5,9b93a1b0,f8874d38,5ca3c282,ec1e11bc,19b6f972,ecda9d4a,f09f0ec8) Z8(6ac4ffd1,61edc8bf,183a6dc8,9ab68898,0fa23364,2f1aee3c,01c23d8e,430d7880) Z8(047b4187,0bf19f7a,497125a4,a10e024e,a983dd86,5fd08295,4edb15ed,5cbb0fad) Z8(1482c8d5,f4bd6c61,70d8c377,939afce5,9474807a,d8fa980f,90ef38ee,020d1921) Z8(a7885abc,668060d7,b48fa607,f6793aad,43e69e9d,52e945b1,3f0038fe,62523739) Z8(44200c9c,224cbe38,dd3ff327,39c5894d,bf3439a9,8fe7d1f2,d0655c4a,74ac1c30) Z8(65d7f10d,22a22fb3,3f8c5c0d,e61f7837,b55b3b61,8c48f863,b8eef7a0,71dd8a22) Z8(fe7ed4a2,1be90e08,9f347f11,bdf6b3f4,77d115ad,0c016a2a,8cc01870,e4f97e99) Z8(7e4bcd6e,46b5e8b5,abe2b027,2d08b6d8,c6e583e7,6bb28605,183b14fd,0bf3aee5) Z8(012f1254,db4558f1,151482d5,fd4d6047,30d2ec16,cc4a692f,aae2c7c5,ea8cdcd8) Z8(7972d6ff,b39b623f,14143514,084e6478,7b9c7f0e,44ea33c8,219be255,904d6ba8) Z8(c13e08f2,ab52b0d2,9e111c37,8c4a6702,12e687ff,ae3e2567,bcdc1f05,28a0aa69) Z8(1686eb67,41a7f20b,764eb3f4,33999e1f,224ff157,2208b6cc,bdedb247,e68075d6) Z8(7937f887,10e5f082,ee5b5dc0,85b18370,abf94f24,4768a400,3c7d2844,daab5e05) Z8(ef780e67,2a1a6856,3d02431d,37e5436b,37b62b62,2f6f674a,a513d8ef,72b30c7c) Z8(f6d4df92,578d4775,13b3132f,808c448a,5fba238f,06c62f87,00f56015,2efdbc27) Z8(5906267b,9727ebe7,3bffd807,bda7391f,0a0ba86f,9cd3cbbb,669c3df9,c07f81b3) Z8(9dfd6268,ea5ce16b,9ec747b1,64911742,73d75cf5,720ec44c,bc1bb2cd,7c4a3d7e) },{ Z8(2a845ddc,53856b5c,66f9a838,3972d501,1f858389,f9eae419,39f7cf10,95d52505) Z8(2877bf38,a3a36d4b,0a307098,2e34610d,00baccbf,13e3c694,03fe8f6e,5692b8f7) Z8(08a3267f,20e96ae5,be43777f,c9274ecd,69419601,b4305fc4,c075202e,1130b6fa) Z8(b9f90ca9,6dfd8367,00753cdc,6d46aef6,939e29be,ed483c7d,141e7310,492e58d9) Z8(995e270c,ca0e2e80,3ae3557e,1eaf401a,eab4a5bb,5caff1b9,589053ee,7b91846f) Z8(ded9d692,eb677521,73124140,5c6938da,08595186,552860e0,210f4873,bed733a2) Z8(cedfd939,53296c2e,8d106222,f7736696,a47ec4ab,e7ee9e1d,84966b97,479b4934) Z8(b49883a7,9772993d,e60334ba,3676c920,5384b3b3,c5fab07a,96859997,4e892a11) Z8(77eb2f2c,4adf3a18,5bc37e9e,ac8371b2,909a4a20,7a766c45,7fd42d1f,ab201fb4) Z8(831d2e7b,f5f9d8c7,7321ac0c,e2059eff,3f1184e1,c68f89cb,5e417cda,99e2cf80) Z8(c6177eba,3c338e70,f764708e,97143743,71563b19,3a054dfc,3aa87bf8,1361a0dd) Z8(71d3e5dd,e52fd660,a6d2d83c,93111d1d,a468e40a,0f0c567b,54d8246d,a9d31b31) Z8(befd8d7f,07b01df4,f0602dc5,8e5a3d59,dafd81e9,9c7f447e,80a57de5,a521b433) Z8(7344fd31,7ebcca07,690224f0,cd64f760,6b6541a3,d05f7fb9,9a710c66,8f38bf09) Z8(832c5329,a35b87ed,c70e161d,54dca374,5c191bef,98136998,228b9a7c,33b034fa) Z8(527c1c88,421c64ba,0e899c5e,dba87315,d12e60aa,fc5ba321,3aa6edbd,92d8387e) Z8(67a46987,94062760,e89d878e,3a732eb6,0c759abe,e2af09cf,3605037f,0ba66448) Z8(d7258b51,a25591cf,34ebb89e,4b8b8c4c,3ffe346e,e34aebf7,2e87f634,812a952d) },{ Z8(06942ee7,fb49352d,2a8d0cc3,e34aa125,0bba7986,943b5b4b,63a13742,55b5cb92) Z8(5656bd48,0ac24a37,5b370db6,85adeae6,c288d68d,c5b4a079,b69f6865,f3d092ad) Z8(cd0ab2e7,a167a59e,1dc4fa20,6cf64d1c,4e6de482,a2313c98,a5ffed30,f08759c4) Z8(6f0bcd4b,3bb5e6c7,445a8375,16a024ea,6bd30ca0,4dfa1572,4bdb55ba,284bb4b6) Z8(505f98b6,6050efb9,650c0831,9070ea97,06f9c153,be3a34f1,be0a04bf,6a8281d0) Z8(6e394fbb,91bd2d74,1da4a905,0dd3730b,00543c02,86f641ca,976dcc6c,f12c8347) Z8(fde93225,a699c7a0,88a5c55e,be3edd3a,ab25cad2,5d5ee717,2c543069,f14d5532) Z8(051c8419,cc901d9b,9d5b5fe7,e41da9d3,69d6f9d9,c60a9bcf,29b76588,a340be8c) Z8(47cdab82,a174f5a8,1afdba62,d5923232,042f40db,81402454,19f70842,2690ec6f) Z8(ccda90d9,f1bc4653,aa773bd0,e067632c,f791c1f9,27f2dd9c,4de4199d,8c7a214f) Z8(801a6a45,d1229658,0ae12d17,59752e76,b0ef60f7,9bc52d9c,8ee961da,b9439b01) Z8(e0c3d622,772d2298,a88dfeed,6ce3d7d9,abd65d9a,1642ce78,3c0941af,95c51b7e) Z8(a45ba76a,2da5a7e8,7ca1db44,28542b31,c5e3444b,2479b8ac,fb2affe3,64f24461) Z8(42570c07,1295c415,699ea802,443114d1,0430495c,0390c159,9559b5d9,dc1aa4ea) Z8(768cfdd0,f496e984,4fae3b6b,47c56b1c,892ad429,d897a5f6,f83c0cbd,a68ea386) Z8(435b5000,e6c5c7d6,64ac81c8,75771e5c,2fc37de6,6c6ee371,d232cedb,9a16964d) Z8(eac77298,d04a9e2e,5716b0d4,7259863e,dee7403c,9b0099ab,6ea5168f,60e4aff4) Z8(c52fb7f6,90936f50,5d3ed11a,366fbbf3,ffe69b64,c4bdd99e,295415b4,85f39721) },{ Z8(7a55b3a6,0884782e,3dc8404a,d9cf4a36,553b7571,e416075c,6807d7bc,9842c8b0) Z8(1728f8aa,de19ad6a,6314981d,148fdb5f,c9d46ed8,43627ff2,84def063,1628cad5) Z8(98d2d3f7,e68d0934,a97547a4,6ff4eec6,d970e946,7128bf32,145ed7f3,74875fc1) Z8(f9706e28,89c16e2c,d1a6c2ba,d846f72f,79111a4b,0b53a2b4,4f8611f6,f43d75e7) Z8(91a04e60,ed580b44,38c48ee6,b911c3cb,6298efd8,ec1731d0,f38799a4,14f87e59) Z8(0add0681,20a44665,1e10476a,205f3488,c6b54dbf,e03a6d06,ab942694,fe4dedef) Z8(37d4e24e,790e9d96,a76c58ee,a89cdb4f,adf3dff6,1099a5bd,5746e77c,1297a51a) Z8(3d980404,0d1201eb,91301a9c,ac571657,8039356d,4a156774,30c5d7c0,f092b189) Z8(8d8a37db,25df4b03,0fbe8730,cc1ce410,6413096d,5ba9240e,c565c130,c21f9955) Z8(76f1bd3a,af9d5c09,14ea7562,223e8aab,13510b66,3bc2035e,d28de6ec,7cd6d5fc) Z8(aed8b1ef,bc9cf34a,cbe2db69,fd958e1e,d969e3b6,30604040,7c56ee2c,f95b1bf3) Z8(7cc13ce8,3a1bff9f,31e2f214,bb84f769,e6d03d60,7cfc3eb0,d49f9af8,9881cab5) Z8(f2cac492,e95f231d,13228d07,bbabb40f,949fbe61,1cc6cdce,83f9d06e,fef459c9) Z8(b7659cc3,38df1427,0535991a,ba010bd4,865d555f,4773f79f,5466adfe,5116efc4) Z8(eb7e7987,93522b92,64c3e174,a638a64e,ece17082,d41b7b8c,c956ff98,45e6ae09) Z8(ada29935,3ef83d3e,82d21bbd,ab93fba9,22744691,6d8ee96f,22615dac,1ac85ade) Z8(66b86f42,f9c14cea,33bde7be,fee11155,438d5e9d,e1958c8d,38859b27,50a4b66c) Z8(0e33c3df,26dfe952,1cf1faee,3a330f34,f14054ed,799d1cb2,a6af4d4c,8aa61e97) },{ Z8(e3c15528,236c807d,0dab874e,1f408219,269f5ed2,4e6c0852,123280ab,2bad9542) Z8(60f6597f,79a93405,2a2b7656,9a41ce9e,d3620695,0e5b511b,6c20ad50,db3f2a97) Z8(e8a475d5,0a7d56ff,49552bc9,129961f8,7a2bb12a,cc9a6212,541116bb,dc9ffee5) Z8(21f8521f,08ebc351,dd309d04,0bb846d3,6085ac88,7dca3150,33a6f6ef,3e9909f2) Z8(f6b3982d,f85edfa2,8fa13c63,22a997fb,f34c8477,d2832389,d67b0465,529dea06) Z8(daa7c988,6110a868,99147277,1b9d44cc,0886b408,0d234fea,d3fb2376,36850d27) Z8(9a3199dd,43279462,f597b3e3,32d2d3c3,30b590c8,6e9e14cb,c2dd8740,333448ef) Z8(670692ec,9b0facbe,1750d39b,9274e1d1,891e47bd,9b83076c,387b7772,2b336a99) Z8(48814a92,1cd304ee,637dc1e0,6714331d,8dace375,7fb439f0,f2e3b2db,2d4f42af) Z8(336e9bce,0bff16dc,980ec574,c210e9bc,aff7ee79,558e9f8e,503b03e2,6828ff09) Z8(a0567c33,ff664d7f,f9611712,c09c4133,fa561541,115b4502,a38f8f0b,0c77d4bd) Z8(1c339cfd,bc158193,191c34cc,05887b99,acd2d78b,d675ede8,b3a34ba3,be23cf4e) Z8(8c76f3a4,3dbb2fb5,e466b11d,3e1d9be9,8e25952d,055716c2,33b18531,7556b11b) Z8(6beb61e5,6b063b4a,91b75fb3,b104ad07,cac340a6,816c3628,ee78f524,4bedb09e) Z8(15a83272,ca9b48bf,e9175215,11c9639f,4ce75c87,5ab5fb40,57185e7e,40b57fd4) Z8(a76cf5a4,d8a8b79a,9d52a8d2,462624e8,a4061d22,cc0bd283,4835fb0e,8d902559) Z8(28e74d7e,4f6620b1,dd0bf7cf,fdbe964c,deac4090,e678c55e,ab58d60f,6e709121) Z8(5ba0cde2,9a4b1c06,696ad39f,ca4f4817,1e35f2e7,62cd2f9f,820681ef,8f42faf3) },{ Z8(5f5bc3ab,4e8c870a,03c9252e,97cf41f3,f1ab0711,bf955cee,3f9a547f,15b92c62) Z8(cf35a701,34d7ad12,314ef0de,6276622f,a4b68b54,b626efe4,87b930fd,e36cee9d) Z8(da28d9f2,ea686a5f,322e455f,cd9c08d6,112b023c,a142b8c3,a0475d8c,349fdfeb) Z8(178411ce,34e4465b,2daeb300,e9d98495,4dcfebbb,9bd16f0d,382f974c,e9183222) Z8(bbe21841,7dd9515c,997c29c9,7f081364,855555bd,67b7bc20,f331c08c,eb6e011d) Z8(b7d79e52,bdc5f8ec,b9a59f49,ba7bb456,8b7d898b,5c158380,e6fb1b3e,d12c35b9) Z8(df9e19d4,74a0e04f,e163db89,dc796300,c42b56aa,70558f9a,abdd0bc1,9edd5dfc) Z8(6557dfe5,42ded9c9,cef7cccc,e6a0dd64,9bac9025,05999592,fb467953,19054d40) Z8(cea2374e,c4b7ce07,000e72a3,d69518ca,71ed0936,06507d7e,8ea88946,d4196235) Z8(5178f8ce,8973034a,782e1b46,93e12592,a6cbdc4f,698e0ab9,8b785fdc,891ee384) Z8(0364d351,2b452322,c5c0442c,196063cc,c235e383,9f4a7bb5,3f3deda4,635f32ff) Z8(d53596b6,51401c9a,01e2c856,47a753c1,7201187f,faff35d0,2c671335,326beee8) Z8(496cc78a,4711ccb8,a182684e,1cebc4be,f056ebf5,4e79e17b,b84729e5,6fcd8e03) Z8(a5d19891,e9037e01,b6dc8143,ac14b49e,f889283e,edec3ebc,dcba1e17,dee20df0) Z8(9c6524ee,d4d63910,05070620,63371cde,94f84d7b,7db94b30,a98a103a,7363c8e9) Z8(b8875a80,1bee1cf0,b1566a59,ea62da33,9227176b,6018fd9e,2176bc65,9c63c1e0) Z8(fa1895f4,5558e6af,15fa0ed3,c0dc1d6b,6de19a53,92b0f0fd,a10dfdb1,b09a0aae) Z8(9ec6647e,7437d665,433bbdf4,527d7309,438ffc03,c1f9edcb,4d88d75b,93caf094) },{ Z8(21920b48,5cdae112,c46e5752,6013dbfe,dad4858d,6d4f6f46,abe8e5bd,c4fea923) Z8(dee2af0c,0f1cdaf6,18a5e2a5,0a1f7f4f,f1623d78,8b862fa1,fc40f5a3,3a1d7e62) Z8(ab50da80,37a6f45e,473247e5,b4153104,8a52103d,b5fc3b45,fe95a648,fce2d7a4) Z8(98f2ae0f,607e6dbf,6a29bbc9,a3e162bd,55ebee84,64c68a04,73b0acbd,b213c2a5) Z8(b9194b6f,4097a3a8,12b0e99b,c3518b45,097b323f,59994cf2,20dda2ca,996d1868) Z8(87046418,d084970f,4867acbf,904dfd1e,fb1a3df6,5b5ac31d,c15ddb86,de3e2c18) Z8(ca43cfc3,045f1594,39097da5,bb84db40,7e6cf65f,731e3cb9,c03ed786,fec4305e) Z8(9f23712e,4fd7c8ce,7d082452,91ce9e6e,499eb971,bd9ddb08,9317a137,984c129d) Z8(263ffe79,125b748d,7453b41c,1c4800ed,2500a5aa,b2198dc1,6fdda1f1,ad76bf1f) Z8(7d449ab2,d549c06e,237e4f68,7298234b,92cec2b3,486076aa,e4aad56b,a6fb6e61) Z8(9f311a22,784362ed,693d4874,e683d796,5e2e88ac,ae45997a,dedf9f0b,2e79c66e) Z8(3edbf840,284dac4d,9345e570,6a45894c,4c9e1f79,323e91ad,6748b193,89579216) Z8(60745800,8053d2c3,3036a986,240cb46a,2c2650a9,a5425761,f8630914,8ae84783) Z8(11a72c24,6de33ead,695c5c8e,fe68450a,8e7d75b4,1de3b5b5,b8497d21,6a438720) Z8(548f8846,99aaeec1,c7564f48,91bed8e6,1c925d42,7dbc019e,31248509,852ee7a9) Z8(5bd23e2b,325a1728,a32d0db2,aebd159c,320f43fe,87c74d89,19bef850,7223dd08) Z8(1304d6c1,db24c695,ceab26fa,4556832d,52740265,879fae51,e748ff9a,d3bc93b7) Z8(636df445,4042089c,8119ba91,0b701333,36cdee18,ac850fab,7885f0fd,983eb99a) },{ Z8(21e887d8,2eceebdd,9f23dc7b,366ce595,5675a166,c3a5cb83,41452c76,420bacb6) Z8(251fb00e,e5dd4cb2,d97461ca,332ee1a3,9876d98e,4ee0cc26,68407d0a,8fd9e0db) Z8(23a3765c,9ff90564,eb797c6f,e26ad3e5,8629332f,2ce2a36c,84f819aa,16c6bb86) Z8(ae3e0558,ce00d1ad,a15861ef,4d0d83f3,ab96c4c0,2b3124a1,61f58587,3c6ec6d3) Z8(48505f38,ddbfe9e2,d8a9c922,5cc1ef06,75a663a3,238dfb9f,17318be4,57d44fe7) Z8(98dec9c7,a6629139,c34019fa,3d76e682,1d1ed74c,0bcb3392,2863b978,031b3b13) Z8(7d386dcf,faa94346,15a52e6f,89e817d9,132d945f,cac99645,08cd2cbd,25ad3d1d) Z8(cf590976,7107bd77,2bbf67c6,1cd4fe04,e0d17b91,003521b7,aaa52884,013f8140) Z8(c068dac8,c835f76f,f7227e98,e3b4fb1a,b802e45f,1b90ac77,538d181c,18b1ae23) Z8(1444eb25,46254ffc,622330f4,07517145,7b05e841,d18acdc2,9063fe62,84eb1e89) Z8(71d7f70e,e515744c,b456440a,41e0182a,ca719a6e,67b7c57a,be60b1a7,6d465ecb) Z8(e20b25a0,bd61698b,9dff96db,baf7f6fc,fd776a07,668004d9,93eac8d5,a4196990) Z8(5a498920,186a2fcc,a711662d,8df1b6c7,028fb6c5,b8f3d28b,79992842,aceafe50) Z8(b87edb43,5c42a910,c4da0173,29cfbe83,bc7d2a91,789aa82e,802a5319,7f49b521) Z8(a7d79f40,d8645c21,8be97053,cfaeac71,a43b2af7,b11bed46,c685ef55,452ad576) Z8(d534ac6a,01d333f2,f8f275d8,09df0a3d,8f098f86,32ff3f4a,fc56c332,05ee137d) Z8(48fe0250,829512bd,61955f50,2df8d830,3dc6a386,a87f09fa,b57fe9db,bc176f0a) Z8(2170e2c2,41e7a845,00413260,1717c9e7,f8c38f62,221301b6,b150cd4e,9c9f069a) },{ Z8(495bb6a1,9da09f78,9f94d754,4f6e4b69,e84c5de7,bd6f659d,6657ff6b,cf114edf) Z8(72569cac,0a92502e,fbf53f51,b355ef57,acba50f2,2a8333ea,0422bdc1,d9cdda1c) Z8(16cb8bef,3115810b,97b8e52a,d8d09897,18a0eeab,2f9fabf8,ce4f3e65,5ebfe5ac) Z8(09211728,426c6062,04cb08af,4f032c15,24997ce3,f6727f01,542819fc,9857f958) Z8(f04368f4,de831202,bc3e3f85,29a7c595,c7071b73,a137785a,56535d4e,bd88a3ba) Z8(4768cccd,87aa8bb8,021f9419,4379a18c,ce086223,e98c11fc,3c5ed383,1d8151b2) Z8(cbef354e,b1e2446e,7b2ce694,6b336fc6,26176ec2,e8839451,fc6aeb62,713fd63b) Z8(24c98516,a0c934ae,9a2ae7d0,3039f995,cb1e0de6,c4b3c83c,c72c1b60,67650274) Z8(60f0d5f6,f62ae094,cc929580,bf9b8c27,c3d9fd22,d0d13f2d,d9469019,82c2b266) Z8(7841791e,0175a351,738abd1d,e154bf88,46f6dff7,0f19e3d9,15efe214,ca54b4d3) Z8(30905c34,cfa01392,c6581992,bf587683,6ec75feb,9c3d1e44,e4f011d2,e2c137e7) Z8(355b7181,56cbeffe,d7147b34,b2d32d0a,67cd1259,cc42beab,ad306db4,c625073c) Z8(ae161f4e,57bd5ee8,a1f40723,67f9e30e,fabe85a9,094cf32a,2d451c90,c91b276c) Z8(eac47175,24d6300a,3669125c,8279e510,2a48ec7d,1c63e3eb,4869ad7f,67efb09e) Z8(4af1c092,7b88a4ae,9f449259,cb103655,a9c58734,482aff8e,91dc8438,2efcef6a) Z8(2345a626,d949d7f8,1e779be3,f4fbfad6,fa015b3f,b61aa15b,bf7b720a,6d294f13) Z8(d6124129,2018ce5c,1df6c2fd,5f29ec91,892e5832,2bdfda46,1bb82762,6471b5af) Z8(2a5e02a7,247c0b84,56f59974,4486ea27,00bbca9c,25e617a3,33957323,a0ec7f42) },{ Z8(9ab1da34,c87e3e81,ebe448ed,96e02eba,8c739c68,1eb47c1d,9330fd62,af9a6b1d) Z8(ace02290,f63dfa4a,68333517,2199e668,56d26eeb,9e5f6730,8903b3e1,4e9b2092) Z8(1d0ccf70,034d0486,43041d1b,76cfd831,be20c427,da75f047,d7d2b62c,d712cc72) Z8(f0f348ba,f9676f0e,3a2097fe,a9b7ea9c,5476609f,4fb6ef9a,2e61b2bc,5af9e430) Z8(4247b0b8,146ab745,41fe31ca,da0458b0,15bde2dc,6c5a0809,44780f24,a1652b5a) Z8(d3c69e56,34db62ef,8242dc88,035fb169,c60915a2,ac79484e,d5201f02,55f4022d) Z8(cb008ed8,4c35db85,dfc81573,dce69d09,6caa0c67,a652939b,46d5a928,3068a21e) Z8(2ea4385b,f7966d4a,c780c795,73e00924,e270c79f,ec40202e,93033f0c,0a15da75) Z8(e03f42cf,64d8c55b,6671e69e,1e0685e1,9fe23a89,554cf137,5e4bdfe7,b91998b1) Z8(d05e6f51,c242e4c7,3a6779f8,ca3acb5e,e0b0db2d,b7f9d519,6a109ebe,3872c2e0) Z8(ef10e1d9,373e4acd,cb889d1b,8d33cab0,eea29b4a,1624c779,e365d3e5,2e0ece13) Z8(71c93def,84a3557a,4e83bc17,d2e949fb,b31bb612,199b9b6b,ea6e5b34,55362a56) Z8(399dcf3d,b29c2756,abdaed78,fddf3f7f,11b5c09b,46ec37ae,fa2454ff,148c7b4f) Z8(7173d8ac,5927f1db,fff4a82c,fe69079b,c9846d37,93897d1f,018031c3,42c50043) Z8(4ae4ca08,6dba9a87,2f448d13,47c646fb,5f94fef6,56ed27e8,6bb532fe,2de04fdb) Z8(6361cdc0,0c647874,98d9763a,77281ec0,4a98f47d,e3d6b5db,aa76f580,1899e517) Z8(369cb411,5c9fdf23,a883d1a7,d83cab84,445c1b43,322aec8e,db555408,23bd3235) Z8(84ebc206,5bf1a66c,af47e744,6f7191d8,61b6316e,3dfa3d37,81f5d811,a527c2ed) },{ Z8(80303242,3ce7c135,9ee714a7,6c68f3b1,6cae6ac4,e28f794e,54100294,87f25feb) Z8(d7d6841b,17276cfa,333f3feb,57bbebc3,f3fd7741,d1f98ebd,1067c72d,1b9f8044) Z8(ef23a6ae,f23ffe3f,e7cf0fa3,d0f0088c,3b922041,a5605e73,2e61d366,9eb6cb6a) Z8(3f60c26d,ef735a80,03d7e83f,9cb45651,430b6d34,19387591,a7b18346,a97a9fa0) Z8(69aa0160,1e2852d6,80cc1187,45186f3a,1c5821b7,833f817b,d4bb78e9,9c1005ac) Z8(2cc49ff4,0b5a9641,3745eee8,82824bb8,538089ec,ae68605b,255d053d,61aa7e12) Z8(b52125ce,54d00b90,a0087f7b,b018bbe6,13935138,b5f485c5,d8607716,c3980058) Z8(47e34849,863d86b9,594f47bf,a786818b,9bb8d65c,9b4edbf9,6c818496,02982ed5) Z8(b552b6d3,74ed572c,b898270d,520afb7c,b28a390d,2e3fd36d,1e715463,1e8137b7) Z8(a7cd3b3e,98fe10d8,391807b6,7fa8fab2,4a76e622,7c68fa37,d0312505,4361ac7e) Z8(44c57247,eb91267e,0993defb,7fac0d00,badcfd7a,cce8877c,6cc847ac,4295b4ae) Z8(4963a9de,c5fb10c7,c1ade436,b4e2b8d8,32912d69,e9e0738e,d97d4406,bcf86386) Z8(2e918be6,00a48ef6,4fbe79b5,e542b336,49e21124,e8160d82,27b07cfc,faa91fbb) Z8(e390d654,5ad1d164,77ba8c2c,a898ed7a,9dfb8a63,25905df3,8554ce25,45fc5808) Z8(5da25d23,1b7f6cb7,f5705199,96870e23,3638b665,a8577261,48ea60b9,a98889ef) Z8(e5087839,1688b24f,6295523f,ef59d2cc,9757fd4e,027aab15,52e00e87,e15b4f43) Z8(c1df5ebf,8a7e5bd3,d6775e9f,bbe00b2b,eceb1f55,031e3061,3e381ca3,ca138ee0) Z8(29d4eb53,a388b633,4c39b31e,d0920f6a,97aea7be,be4578ad,de2d5773,a9516932) },{ Z8(153cb58d,9d1f3b57,75530e68,f08e872a,a184c327,af2fe70d,06f64b38,a5440619) Z8(3831eb50,5f738423,be87fdda,06be990d,7c63344b,51edd5b8,d2725e8f,512bbe25) Z8(2e62b328,6e4d892f,24fd156f,b5bf400f,ff26c676,b3987dc0,3953a3a7,8d61146d) Z8(dd206e6d,10ea88dc,684c9812,a160a9e8,547dd5dc,7f61f9c3,2716985f,ab3b272d) Z8(4c07eb13,cb821d1f,8ce5b245,0d09bbe6,96971363,9f8542c7,0bbce0b8,bd4229c7) Z8(496e87e1,2518b9ee,ba6fd008,7fc537dd,1c71268a,03859467,f95b8212,ba3c30cb) Z8(960f5d47,076dcd45,825f3677,3ba0f0e2,e3cad1ac,559cf693,461d7a9e,171d1e06) Z8(19267d02,1f86b8d2,e7b1b333,bf28270e,a0e0a7b7,aaaeb90e,db418488,77793fdf) Z8(f14cd468,d0f2df53,76e1e65a,c6508ec1,2f9e49b4,f5637638,ddd41982,dacfd3dd) Z8(abc5ced5,258af8cd,84816543,e5daeeed,a162f3d0,f3a852c5,485be88b,01730602) Z8(859bd7de,15b7cab2,4ce7f96f,f9ba8f0e,f6d58700,9478f9cc,723551bd,00db20eb) Z8(ffa47cb0,5cc63fdc,bfd0b5df,4bb12429,555ae671,c1c3a260,7487ebb0,1585033c) Z8(b4176022,ed76404c,b0f6d2db,6a119e93,d5e9d3a3,da919a24,e74aff7b,5b8b86df) Z8(e6cfd8b8,4db00763,2ec17c58,39b33119,9d970103,b8c85166,fe40c52f,315885df) Z8(5f9b9466,cf9b5c80,63d5d87c,ca827530,959e83df,43d087a5,72c94eb9,897a6a48) Z8(ace1d88b,bb5cb1da,fab389ef,567cafe4,08b45e3c,0b672174,1e3ee20a,df6cf0db) Z8(14f3b1d7,77d02118,d6b30d46,faeab5b9,04f30d08,869cbad3,7b2300e7,0c763464) Z8(5b324a78,7753b3c8,8161ccf7,839e0457,1cd40845,4d552f81,acf967d9,ad6a0261) }}; const mp_limb_t arb_log_tab22[1 << ARB_LOG_TAB22_BITS][ARB_LOG_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(8b9c1b7b,ba0ac6ef,1a7045fb,4fc1d240,49754d0c,0ee63f28,92ace9ec,61286fdf) Z8(94505634,73d96965,a62f60e0,055c524f,0f70b0a8,971925e7,4dba6d41,1d0343c1) Z8(15184612,1c93c13a,339710c3,7d998d9c,bbdb40ab,b6953722,a7f3cdda,9043605e) Z8(e2baecec,bb52b604,b0cf3c1d,e53a8b19,3c664ac4,309a02e2,37d88a1b,40123301) Z8(3fe22798,db932747,6e1f2190,1539e8aa,1ba538bc,4ce6ebd4,a8e1d420,4c534451) Z8(cae3482a,d5da9d6d,f84d4875,d43ff73b,5be57b4b,2c369b63,30fd2a8c,9a7f805e) Z8(1d148440,23dc7790,d23bd975,b5e01fa9,5a441e62,ecb5474d,1301a31f,b13942a0) Z8(93410acb,a122639e,e9f6f560,a2e52c2a,aa6e8e71,30824fe9,c39edfc8,bfd9acdc) Z8(4c404a85,66a1eeb2,af4c12e3,d317e9d2,ee056799,80e78b52,d0cfec3c,f815825f) Z8(6c410527,9d07dda1,dee67101,2f38e5ce,92c7b4c4,f5bf18b7,0b57d454,2f6457da) Z8(6bde9b31,f2e4d6ea,da57c458,223b7241,1a1ccbb9,54227606,bf840fbd,733b38d9) Z8(b73e7e2c,6030da8b,9a0cdfba,2545acb3,349cfc81,2144dce2,f80ee38a,2e8d392c) Z8(b4be72fe,5aed89a3,a8bd4890,a60c002c,d2d4e3c5,03b09d89,f1da3961,46519661) Z8(22042320,3ef4aab1,04d8021a,49b8e564,460b00ea,a29a7413,7a6aae61,65cfc75e) Z8(86a9a132,e6798564,43affb63,5ae185a4,d8c15808,e44f4657,909380ff,0e08c996) Z8(38603bf8,1685f930,739145b4,8a85d6da,d1f3a988,5634cb94,fcd59644,a77480cf) Z8(88455ab2,2cbec254,033072c1,ac4e6045,5f35b760,d3878b77,f158acdd,453519e9) Z8(a6eb720c,6e34c564,62ef4eb0,8e30d617,2499268e,7809a0a3,5515621f,003ff801) },{ Z8(1820e771,3ec50815,4d4d2810,167213ee,c5cba55b,1a2e2146,4b671030,50a75899) Z8(7f7673b6,b67c591b,cc52f381,090db620,c3a9950f,3907c163,b3c1252f,d37e177b) Z8(570c696c,36d9e7df,6543f7b8,8046e6f9,883b8e6a,f8d8ae4c,e951b6da,16958281) Z8(260ce86d,dd738efb,d169984d,133ac712,460a77ce,063c65f4,6e377198,4b093da1) Z8(7074326f,09c467db,c475f0ee,07a6cde1,048c0ec6,1f4bcf35,4c252858,c0f9fc7d) Z8(967ff841,aa6be419,03c9c381,2f749a85,da7edb91,27b211e0,4da0fcd5,fdafbdbb) Z8(d342c332,38863499,03365b1b,83341d06,3a34c495,5193488e,60347866,4be607f2) Z8(239e8009,bb9acee2,d5c48b5a,d1329eb4,27081c5a,b633247c,32efe299,039b2543) Z8(e23507a2,524d4c4d,17a38fc9,a86222f6,f154207c,da8d25f4,067c135e,3cf9ce0f) Z8(9920a33b,0c29fe68,d50a22e1,623a73fc,7d546db8,920f1c5b,d033bf48,d552bcc9) Z8(98456d70,e245eb3c,fe19736c,4aef3e49,5254e891,7436f3a4,5c0234b9,c2652db3) Z8(a171693c,e5a8d090,4b98cec5,86824650,bc7498e3,7bb06abd,b7e7100b,646687a2) Z8(9f372aaa,aab2bf43,da7f38c0,7c137902,83a15d37,5a707dab,9057134a,3ebc5c52) Z8(0cb55bce,4e7f263d,57c7a3d3,466c9b42,3b7796f8,c43b2902,f125f292,bc58191f) Z8(d718b11c,ffa8b50c,50a4a8e4,b6908ce7,a57f428b,70f430d8,27d5b7aa,495a2bac) Z8(47a4461c,d9327644,5d80eb3a,40cec96c,c5592007,84a8727d,d534ba9b,afa9c34b) Z8(d4bb4228,566babed,4e690306,d0d98ea2,492e4bba,dd3f9376,02ec7bf0,66e737d1) Z8(12ace6e8,c73356cc,e89a011e,cad8ec22,3e3b1ab1,e29e3a15,a6ac4399,007fe00a) },{ Z8(7bd45892,87ef1432,93549182,4e728fff,a17c9125,da83839d,a6de1efb,1d4a0b1f) Z8(1e586971,ece7bad2,0fd32d12,9f11b41b,3657dd9c,b33685d5,7bc0c31d,e8bcac58) Z8(80b3eebf,fab0f545,539ecd49,ee6beb53,30f670e9,d454f238,dbc65ab6,d0af3118) Z8(45a79682,a847a930,938dbc27,bc78ee6c,843f9f24,63431555,a8ba07a4,faa828c9) Z8(33959f27,cb625266,f07a9c49,5ae75939,279a7691,27b5a542,55dc3d88,a05ddb9c) Z8(0f4d7c27,70678ab5,477b4b67,9a89a333,6b725bd3,4291c99b,8b2095fc,268ec52f) Z8(62dac762,7547581f,aaa6ba30,c628bc03,0afff1d9,db3df166,2c75639f,a7b1a6df) Z8(96ae84ad,643a671e,8af38941,c0670dd4,ceb649a7,26523995,e7622e82,37f66b02) Z8(3572e1c0,083ee489,f6b9e6ba,46492d42,3762c6d1,442e03a9,0d4716e6,d684c7f3) Z8(bbc8c4ab,d2e80ad4,78bb6f2a,f4ccb747,e6efad6a,853af45c,98068b82,f9a00236) Z8(093fb52a,551d5ccc,0630c57b,2c74921c,b2b6e3fc,585291c4,8a609eb2,4b1a2568) Z8(944c1d45,1363d727,3937a37e,4c23ba0d,50818dbf,23688c83,8ed17760,1078bd24) Z8(ebe8d2bb,51a8fcbf,08be40b1,e83ffe1b,a6855626,15c0cb36,5dd54d65,a7660cd9) Z8(e6611264,18716941,7f00d1bd,9cb2f10d,9a6ea927,e16e59e0,059da5d3,4f589431) Z8(bdacdedf,7a79a587,3934d586,d54fd545,9c7a1a87,29e3fc75,50e1ce1a,f6a61f85) Z8(98212551,f82a20a4,7ef1937e,38645e42,8689e34d,bbd64d47,a3a3f54c,8d40afbb) Z8(c4b9be54,ab3b6a5f,e75d1021,85aab5ec,40365daf,008f1701,a6729ae2,9df4c673) Z8(15be5920,d672b536,013b32ce,8d568dc2,09cffdad,44eb4324,ebcc1ed3,00bfb823) },{ Z8(159dfc29,0420113d,f0e9b3e6,b7936a46,60530cb1,f5cd5799,d8a0c647,da1edbd5) Z8(1fd5c6c7,989a5d1f,1c1bfb1c,03db7723,88285f8e,c11b6f9d,fb78539b,685d0a7e) Z8(7aee5a5f,9280afe4,cd6de643,3373848f,fa3e66b3,9c96bea8,58aea360,8af4141e) Z8(2e993e91,c92da4df,3621c5f7,2dc22291,bcac49cc,eec45274,a35ff6b7,2f803695) Z8(21deeaec,1edaa6e5,c14426a6,977a092b,3509370a,8b74c1be,b241a9c4,d7c03a18) Z8(dd303505,b20fb3e9,aedb3496,f8ba7565,11d343b9,effc119a,fa42f81c,563f7da4) Z8(cf33ca5b,519232b1,1028b9f1,62b9516c,7e216a4a,359c3a23,f1865ed8,d15cb138) Z8(cf8e12aa,23a2797d,e867994f,e397895a,b54a3b53,70dd7510,6713f112,27ce9645) Z8(65e81ed6,8248dab8,7809567f,591b205e,a19551ba,349e37cf,64252869,45689adf) Z8(09c7e224,c8c909b3,287ab29e,4453ea2d,5195f48f,9751eb89,43905827,71644fac) Z8(e1d514a0,fa29f816,fbbb0296,7da66aff,0fb28fab,a96edf95,39d54a86,fb85b2fa) Z8(2233dba2,4b86566c,e395110e,ea7f2a23,b18e035d,2165e381,52423ede,e85275f1) Z8(5261af84,a1582928,55dd750b,5d0932d4,00bc47c3,ff02871b,db020f7d,7356e4f5) Z8(98e0e51b,0094d420,99eb61d1,afb8deac,90122dc4,b2855ff8,41112acf,3f8c2665) Z8(78983289,ff71220b,0282b5cd,55a3a8c2,da1a5e4c,7813a608,2c5278bd,30120813) Z8(edf7e201,07b4996d,0f632916,d438bb96,430ecb69,82b09d3b,ac79813d,89db3dfe) Z8(f0697e38,b4baf715,3a53ec28,699b4749,cc95af15,d137bfbc,4192b38f,7ed64a06) Z8(5a1a3322,91ba6e33,6d725824,8ccd29dd,da6a5bb4,50435ab4,15885e02,00ff8055) },{ Z8(163a181d,4f6d4e62,917d8eea,77bc891c,1064df82,0c3a465b,ea8fc220,a32f4ca1) Z8(2d0de89f,6582a9ea,59535a94,964628d7,f58350a8,6b1ef5d7,e5d287ed,7e0f3ed4) Z8(e6a9cd8d,16f35a5f,2465edeb,302b9513,0e364757,72c9d4b2,e848099f,6943e817) Z8(13eed651,302bf46c,9aad1e32,5f4b348c,a633111c,003a6c4c,bb2943ab,5761801e) Z8(fcdf642c,a0a1dc2c,9fcb3b43,e8c95255,d1593e22,28775bd5,774dd809,386f3302) Z8(df0ec0bb,6ac0a21f,41e0f6d0,2ef627b7,b7428421,37accab4,b1cf6123,0b69b432) Z8(b7f4ee2e,aaa79e1a,9bc6556e,27af121b,d30dc35b,b0f6c930,84f33ea1,0260d988) Z8(ac8474f2,f616d2d1,b6309807,a8647e3f,483af5c8,6db19849,ef0dd35c,b3853143) Z8(b8dbd4db,d02f15ae,3ea5c588,03447b7e,a3a59810,a655da6a,ae5b2481,331db353) Z8(5cc0976a,37aef47d,d76d23c0,027df6dd,c5672c45,29bb2452,2c43b0e2,44688e57) Z8(8aaa3e93,9b11e25b,51f476a2,4b7d4a20,5e50e8ea,42259149,954dd970,2a2fd89f) Z8(0c4ea5e1,e5e4ca0c,3632ac57,216b8010,ef8929cf,6e81651b,f5e09ae7,089b83e2) Z8(ac9df9c4,52cdcc4e,a28bd8f8,50541114,0b225dc1,0378c3fa,5009627a,98ef6b8d) Z8(cf32a022,f9743e40,8d5dbc36,038cbf8c,e1f6560b,2d51b5ab,5ee8d28a,c29a8350) Z8(3fd2b1e1,c0dfe8b1,02d3005d,94499fd6,7e992b8c,1e00171a,09a45d9d,c77ea17b) Z8(d1256823,1dbd11a0,cba07a73,09d32ece,22b2eab7,40d37dd8,6deb1ebd,3525dc95) Z8(4533ce4b,200d4e60,b0eb1eff,a6dd1f16,73b6e444,ad86fb62,5722681e,57075db5) Z8(357fb684,e444e58f,29be3018,19350e86,50117ab0,a4f24dd2,0f064895,013f38a6) },{ Z8(b6d927ef,2dadc888,915de342,2b4f6ab8,8c0ab401,a89beec6,4d35a509,f1879dbb) Z8(c15674f8,6147567d,81977456,712f397a,10d85abb,e5114af3,c37a9f23,4ff380a7) Z8(0b968932,723778dc,ee888c13,b8923376,eee291f0,79bf0802,6fd1f78d,219ee90d) Z8(b456aadc,f93259cd,e4526f25,68c1f275,7654332b,d667a1bd,a0de82a0,e3c73b24) Z8(86a1cc6e,2b44ac9c,ef0753f4,0a1e1547,b87bb88b,0ab81f39,0a422432,dcd030fe) Z8(bb3435c1,a60fd723,f320ccff,806caec6,15ac24a9,aafedd83,c00972c3,389f689c) Z8(33c6f737,ceb7a640,cbde462d,8520a153,cb8a23cf,d872bcc7,ce23f62a,a5391b84) Z8(47283289,764df5e5,528d20fc,c5dcb614,43c16e02,1d9188db,7f7ebe30,fad8a6b9) Z8(95de8bb5,7ba69284,86b5fca1,485a7070,9404a9b1,ac1aef31,a34a7ada,57e47774) Z8(5c146598,0606f86c,acd4e9e2,4150bcfb,93c99f83,719d0376,bece1034,9bba59a4) Z8(dc51a41f,4e4ea224,b18e5608,66b1ec80,2be01ca1,215340da,797d53e7,3ad0a97e) Z8(6bea07d5,3fb637bc,30a6e3de,66dc519d,2134d5d6,d58d048b,ff690887,616f321a) Z8(4d3f1203,7b69e111,4123d8e6,636baa17,92fc4fb2,e1189a7b,dbb29855,8634c60d) Z8(19ddc4eb,c84544d4,dd160b19,240f1c39,db986bd7,74d1cdc9,5fe65ca8,5daaa81c) Z8(e0cb53c9,6a8f6671,03c41668,2cd38aeb,bc9346ea,73b640e7,b0542801,001d58fd) Z8(c6388d39,48b06b91,373f9fde,d61bb167,705e24db,440d4f96,b197b8ee,6a24d5eb) Z8(96cb638a,faabafc3,0e8ca9f4,16064670,73a2bce7,95165acf,a35e4561,6beb75e0) Z8(f1aded85,903ae028,8d165ca4,2800d1f3,e89c01eb,785a4740,bd82e93a,017ee11e) },{ Z8(cf3a1be4,63afd436,9b560d1d,ab80e16f,7f3ffcef,46e47c32,c1bf0472,f5a9f01a) Z8(0aa50d58,694510a8,ac140b11,b7a0de0b,d773812d,b63e717b,3aa487ec,17d75929) Z8(33f38e01,d03d7d23,7b78605b,9dbd5945,2deca3ef,dacc0972,b66d1fab,5478b89f) Z8(6c8d604e,8ccb6228,56402f4f,6928d694,364ba4dc,b2e31d10,e7b09ed8,fafd3006) Z8(5664e5b5,818130b4,f02a5932,8fcdf74c,878a7fdc,2124693f,4b625ac8,8760d4cc) Z8(fbc3f0a8,d1fdf130,ee3b4bc8,45eb702c,5e2c16d2,87cf864f,22f7526f,7095fddc) Z8(33a6afe4,e3880a59,ed7defd6,ad38cb99,5740ebfc,f9fb8b41,091292ce,670ba3e7) Z8(a4b0fcd0,171ec2ab,da497e07,cab51d6a,06e053c2,113ea9eb,f120900c,a718dd95) Z8(a1cb5819,32258f47,17786fda,0f7d2d89,85c9e03b,0f862316,a4e15b37,41b090c9) Z8(ed376256,2a2d735c,05d62d79,cd168e50,a6104590,8b8b0c50,06390c6f,0ed79ca9) Z8(d1182bca,62af2ec5,9e8841e5,710ba75a,e6242703,1b18c13d,bcf7abd8,e2ed4bec) Z8(3c899785,b2240eb0,8a4b651f,24457964,62fb3bc3,c4b9c61f,4b0ff0af,8eecb46d) Z8(b5d3eaa1,52b1cecb,9303ba6d,8c5fc2fa,d5cd511d,55098de4,523a0262,4251b2eb) Z8(a04e49ee,116b023e,685ecd1c,14afff9b,1a4035ab,16119597,025dcc76,68445587) Z8(2b28244c,95eedce3,175e07a9,00370dfa,0e90654f,40ba428b,637d121e,67a74fb9) Z8(b67900f1,dbb1eb48,150d611f,b9e1f6e3,7b4d80b2,de15aaef,fc7703b0,57afa332) Z8(d2f30446,a066ddcc,39b9e717,15e9f367,405db65e,2b4f58fd,0525be43,32b68b50) Z8(20ecce05,4a9e0f8f,d51f7739,309e2f1e,3f52763c,9a6c0404,0058ec8f,01be79c7) },{ Z8(f74c6678,f18adff2,fb1023d1,43d330a9,72172504,77a952bd,9c101436,ea132020) Z8(42170874,608dc543,c9289710,32ebcd00,94bdc346,6e91ce38,40d63ce7,af60df8e) Z8(e2ed1e8c,3c266550,2bef581b,4561f01b,63c3bf32,9a2cbb2c,f79b969d,aa80fe9c) Z8(cf6229c6,9ed3ae25,88634ae7,ffd42e0b,34757b01,6d861007,a6ffb2b6,aee5359c) Z8(0a3bc158,ba32b75a,63caefe5,c6ae07f3,8a2ebab7,f68b7654,2f3a9881,5180e1ca) Z8(1d54d31d,581407ef,4b015ade,056e88b4,b7a8fdbe,6babc997,dd6832e9,bf1587fb) Z8(99333ac1,f118be70,03184a9f,6a3f6dee,505c3555,39400a4c,c027fb9b,de972cd4) Z8(8c339dd0,eeab66b8,5eeaf63d,c6bb929d,d28a606b,43c9fa43,5fe8a7a0,4cde11f9) Z8(b1665ce0,1c7f56c7,0e667317,b0719165,672ed541,30387ce6,83aa212c,e4e032a3) Z8(efca2425,90ab1fd9,185750d9,0619d3b4,a8d1a3d6,d599d7f3,64e5e121,dcc285e5) Z8(d0e8e0ff,cb814bc3,fd70598f,9e7de4fe,72b836e3,2b028080,d6bfcf44,610920a7) Z8(30184b76,feb4db67,e5429e80,fa6aca84,7cb9a5a1,7db74372,58e7c9ad,d3dd60ae) Z8(21621628,0134ca48,e6f0342a,3eb721d2,3ec22363,4bb47df7,4786d57b,3d7cadc5) Z8(7c5b9ec7,c5288463,b8c4273a,3f88e699,079a8dca,0a8eb3d0,a5ff317c,3fe0603b) Z8(73ae5571,d47d4203,a092519a,d0b1dcd4,96fb141a,5122ffd0,2bbd5a8b,e70bbce7) Z8(af58fd5c,6c15655a,6433c9e0,c200063f,1857063b,31cd8161,a4a5b7cf,52d919ec) Z8(90d465bf,d4520ee2,9bb0f82e,d99e1b46,facf68d7,e4c4a44a,51bc9855,d122f7ff) Z8(6b5788c3,76702788,f9a073a8,b3db2c3e,1dc282d2,c3769039,b106788f,01fe02a6) },{ Z8(b8c5860c,397267a6,7ef0abc5,e5622038,ec948e09,19810aa3,de5e59a0,0e0c98c7) Z8(26e3ae5a,d79f4b3f,5135e8ce,c66db329,373d21fb,68372486,4af5fdad,57fe2d95) Z8(ce696229,64b6a5f6,485f4902,8b406eae,3235f11f,0b73adb3,b36a77d8,5ff1a4b1) Z8(a09da7d7,7e160af8,e23b15b6,f7e81172,7f2a7ead,7ff7cb9c,27632f90,8691f2a6) Z8(2f08871c,b6094941,9416d943,7aedea45,0fe00269,45079252,c92631b3,61f6fcd5) Z8(41f215c9,e6f47d2c,bc205f60,522f0bf1,ae1751e6,23e491d1,aabe85af,a28c04ce) Z8(e80ad76f,5be93559,145d5725,b71d665c,f49a9222,00799f42,d5d96fb1,05534a04) Z8(1ddaae9a,0a8a229f,058ee4ea,58eb20d9,07fdeba5,ce669de4,e3dbd78f,6231fab8) Z8(20297258,305dc65b,10d8aa21,31d07f18,9819d38b,6f279cf4,501bb703,3d19daef) Z8(fa52c1c7,3c7006ab,bbcbe27c,24486e52,6cc7ee13,230e1a64,eacb5a91,c90ed9ee) Z8(49e54cc4,60c05af9,713c4104,1e18f970,26ff4407,2502017d,21c84442,ed0e2bec) Z8(d2fc7e3d,643c1e7e,e63585fd,6a28513a,208430c1,c71220d3,69431665,485bb2b9) Z8(ae0c1056,c119fa70,9972bed4,ec8bff73,28462909,88105262,82ee0c2b,47e23bbf) Z8(dbea93f6,8625c04f,eb5402a3,8739fb3f,6689b965,e78d131b,5a6bb9c5,114d1e5c) Z8(a78c79b9,1f306be1,3e517354,cd92d42e,b9780639,67c24b06,700c45cb,80faf8d7) Z8(6ed6e98c,ee884564,767dfe84,c4f4f91d,3990a056,8d323dc3,9368e92b,fd661d9f) Z8(9e735ce5,f8f7a1ea,f0f7b184,9c5a2157,cd225ee7,4194c38d,2ce8f767,85a6e302) Z8(50649ad5,7296e998,6635feec,de835234,d137f0c6,005b91e4,a332fcbe,023d7bc5) },{ Z8(101c53b4,3d829630,6ebcad81,823f02b6,f244f958,fed52e13,9a379dd5,9a4bb0e2) Z8(a84ce40c,5c64c539,c0ca2ef1,8ecdd6c9,8ebc2450,2482c396,ec135684,eddf7163) Z8(0f1b3df9,bc2eab6f,7d3326c4,45d147b0,6d38b620,3192be60,1179044a,f6aa4857) Z8(ae550026,3f59320d,71a23495,1a6e69e3,7616bc8d,0e6bab10,7a787dd7,20776e7c) Z8(502c17a4,5e2b5aa5,575fea89,7cfa5f61,8d8df309,5a8c5fe6,c7604757,f97b582d) Z8(dfabd473,d8ba4e2d,885a8357,fbd17891,eccffbdd,905fea86,f6e200c1,1cc233b3) Z8(880444c5,c83e0daf,3f91b923,54344dcf,55deef70,6969d05d,046cc493,44b3588e) Z8(c58aee4b,c4290d33,741768c6,aa5d01eb,7f8bda00,f1f0c8dd,851a498f,7cab3b90) Z8(97bf2bcc,a0c3e55a,b5dd5e8d,901d7d4d,e1b1d548,735c2e9e,a7b3b1f6,bf5f2e2e) Z8(047f4fff,a6e76004,43072bcc,f1acbcdc,4801c11a,7de33193,c2cb7421,0245f31d) Z8(eb500fbc,39c66ad4,efcea6d4,329dbb15,ce7675ba,e0e36edb,a36fd2dd,e18de548) Z8(0e87233a,96cbe1c1,0fcc8936,fba39e93,6948f063,105528e3,062639f1,40ccc13c) Z8(e6cab139,f6dc275c,2e524c99,6d928662,2e9e59c5,a6d52198,efbb5be0,3c6cd0bd) Z8(09a56093,077401ef,b9572f11,8ce1b2ab,7a92a7f2,4ee39b9c,8aeec3bb,d6d7d9c3) Z8(f7a4cfb7,7ea40797,2fddf35c,7cd1bcec,2035b46b,e00b16b9,2096ab10,d788faef) Z8(64159550,e5727bab,e2cdccfe,7a6a63ba,297319d8,fd9638dd,a2ea5ad0,284b325f) Z8(574365f0,aab08c0a,25ec4d0f,9f40ea98,1847d7b1,84813e64,6de32fa4,f71570b6) Z8(e4be3a9d,7c01119d,9dc1262e,f80c634d,de2fcda7,006b2f75,a4b4fb1f,027ce52b) },{ Z8(4196f9a2,e30fb5de,d3e7b9f7,b287f0bb,69105445,8761403f,6ee4eba5,cfc563dd) Z8(77aa4c47,fd707a7d,dfb99a17,e0777761,57136bb4,76012367,037a1750,6db92b4d) Z8(15c0309a,452f5710,49e13aa8,06bd4a63,df770d91,254f24c3,665d3855,bbd810c4) Z8(b3358b8f,8b7609b5,786518ff,d2a12dd8,a0fdf770,1c5e71ac,14a8b0f3,f21f4629) Z8(d77e0359,bc579ba0,81c818ae,91b9d38b,d4f5c8b7,6df5831d,38c5c709,0ce9260c) Z8(cc067aec,45d2a310,27dd7f53,da27477a,87086913,09aa0db5,339e1b0d,8061a939) Z8(d94f2ed0,963bc147,a4d23632,976889fc,cf845b6d,c032fb8a,a2c6c2ca,b05c0e8f) Z8(458bdf83,31775d2e,520d90d6,9bcd6617,026f2347,4cc44e95,c5975e8e,ae3acc21) Z8(d4faf8d9,28d77576,05f3f05d,719d430b,7ff285da,b3f7cebb,92277e92,463c542e) Z8(5f916974,7d247364,1449edcb,ea5a0c25,cb9aa604,228861ff,856f6daf,c20b2a68) Z8(9df37f67,97f5d38b,a0932b98,688721d1,1975b416,896752fc,5e9d6aec,264dc1f3) Z8(c2653a20,b9335f07,6a3e80d5,903a8b46,bfd1370d,0bcaee72,1d00f50b,5d2035e3) Z8(9708c722,ed2e7b47,fc8782ce,e169bd8e,b4d437cc,2ab8d583,acbe0b9b,30a3bf6e) Z8(db3ddb70,28bf5060,18ffc702,f7d6224e,00f69171,8fd7f14e,90ce4e3a,8b40175b) Z8(765d5c93,ec0ddf98,d99c8133,531b0e96,3f37e464,a2d8ff7d,4d93820e,b94a41cf) Z8(d81e0c57,5263533b,c575d238,619ecab3,08d7346a,6fa0440f,6674c75b,cd885393) Z8(632ef4a6,98ae2002,90e8733b,da3c76ee,49ef383d,402d5503,29821714,a83d03e1) Z8(fbeab8b2,807f2ca8,5ca35c97,1da2715c,49dc48ef,f585da1b,7d97ca09,02bc3ee0) },{ Z8(d0b37e39,55077455,210009be,e2b1c4ab,08ced6d5,6ae72e97,d3dd639e,bf002655) Z8(543a47ec,6be7899b,c472f09f,8afc05c1,49d16267,e73c772f,19553bb4,c8d5e72a) Z8(a3e310de,ab2ae29e,c36bbf3d,7a92832d,a9d3e652,e0bfb298,8ca41ad0,7c6d1319) Z8(7cdccb3b,f7f5e598,b21c1ad0,94063ec7,ac373bb7,10e825a2,127c9d11,1b23c793) Z8(6fcd5fdb,a2c1b5c3,4b295e7d,25323523,c46ca6f5,456c13f1,19d99bb2,bce65892) Z8(183cf734,a07e8f0a,56e037e7,1b668c2f,0c751774,bc0afb6b,d9005008,72680a84) Z8(4ebec564,23ff5356,6ed8a87f,52d4c1f5,3f5cb7dc,32f39cc9,cfb03e42,9573fab7) Z8(66cdc5e3,372f46ec,4f1ae30a,00dc6f8d,6c025663,14c73859,d8ccb507,3b6540f3) Z8(e84d0bc4,34e7fa7e,0e07bef7,58ac2edf,e005fabc,372cd2bd,e25055e5,bce9ae09) Z8(a9c3a10d,0a134b31,adbf8be1,f1470fa8,26559beb,89d6a6bd,4dc348e6,5c951952) Z8(e8cc46b2,d18b1886,973701dd,5bd9cbb2,05d1abfb,39c54d1c,b1034abb,a22284fc) Z8(176abbfb,45e0a3bf,e339e2f6,2285cfa0,0bf70da4,89aace46,dcbda6af,7eaf6456) Z8(5b13d650,1a6b8da0,6095aa23,9dc6b454,de2c7283,feec24c0,c2fa6baf,5c9cd08b) Z8(3b96f292,e9f06752,b38e0513,dfe4a9f0,fdd1b5cf,fee55cd2,f1f8d569,a7ab9502) Z8(343a8411,a6b19a77,f82a8859,47d3b9b1,5aee030c,c1378fe8,0b81cce4,dd63e040) Z8(cc63bb2b,cfd85012,132d0aed,649cb9d7,a9dbce2a,64525414,33413294,9c844c19) Z8(dbadbe86,6fc8d6b1,960efcda,7e0056db,ca7f55a5,747d1b59,0584b077,44a7494e) Z8(ae46a6f8,4641f6d1,74fc191f,85250c00,0837cd42,a4a25e0b,f0214edb,02fb88eb) },{ Z8(eff6af4e,3d5606aa,c5fac942,a42c374c,13ec96e7,24c140db,4f6cda78,d1dd2504) Z8(58595dfe,8016643c,515f125c,2a494d50,a89a2679,d9d7b9c2,5ccee898,7589b2c1) Z8(679f977b,c771f629,cc7b96ee,5b914f8a,5653924f,21e2fa59,3a5f2a66,7dbcfdcd) Z8(f53014d3,cda718fe,ae2136dc,4f0f8e39,50ca13a8,1a3d1032,b06a3a22,e5a60c5b) Z8(066bc84a,0044d9b6,a2c5e629,88fb3e27,98b8dbea,3bc107f4,f48f580f,904e514b) Z8(d6447ee7,45bbcdc2,d65076cd,f3b7b73b,c9346bc8,057e431e,bf9bc75e,89a2e2a1) Z8(7c11ef2b,8a533e02,6b055ce7,66cf9ebc,5235dcb4,5e4fbcaa,d5c7d05c,4b396450) Z8(b335a482,132127f3,8319dee0,6700a8f9,27390210,5c13845d,d90d8492,ddc50fc4) Z8(bdba0a4c,14690244,897ce501,baaa83f9,e7c6d7b0,fc5e5099,628228d5,3444957f) Z8(d6a92a1c,7961bd2d,8e412736,fb30183d,f7e37cee,15fb8a67,b14f9e92,aa5a35a4) Z8(fae1a714,a697813d,864e1169,b4629ad2,d74d8c76,3a727537,1602cd21,007eafcb) Z8(462bf88b,2cea0067,64d403bb,bcd55cb5,e3696163,71eb4b42,b14d88c8,2276a107) Z8(d5fb57e9,9596bb24,30e8165e,b7e3c80d,fcf3d0f6,1b4ccb77,e16aca76,86a9a505) Z8(e71f8ea2,9d485872,0ababe70,d28d71fd,f9770dda,f6735cd3,99872a63,a066983d) Z8(e17ebc1a,8becd1e7,b87b4cd6,f25102ef,c15694a9,9d699e57,665ccda1,4aa5a87d) Z8(dbf3a9cd,b95e0344,5b753371,8a2308da,3ce19a57,aa00340e,e762bee8,4301145e) Z8(9d19b802,d10bfb83,cef4f601,84fec96c,7f1cdcfd,6d1cbc6c,4befb776,9d779681) Z8(90376023,4369ae1b,b26456ad,01c59be5,d35cb358,327b4256,b8d7b196,033ac355) },{ Z8(029beaf3,0d37bf81,1ca8bdd5,e260e76e,e20637e3,2bd854eb,a14e842e,df992f34) Z8(1274240f,9651b076,d0dad1e2,d9f60637,84709305,de7d5f1b,d6ad8622,43d28a33) Z8(a895711f,3cbacf8f,20c79b7a,4dfb60e4,94f6a6f9,413ba06b,e780106f,66bef67d) Z8(55f7464a,f4a137d2,78d89161,faea4b71,08e14b5c,1444668b,1e114480,27b2b9b7) Z8(c47fb75f,3214a251,9fbea60f,95ce97cf,54c36032,d8514193,4705eb99,97bdbd4a) Z8(a80e0111,f93c18a1,6a392179,da093c31,c9292081,5739c9b6,7e358caa,9304ed03) Z8(16d10b55,6b6fd6e9,2c56e827,036e795e,1fb7cba8,cef092da,79e2c0b8,c44c9987) Z8(49f906a3,ceae3a81,1605c9ff,29c085c4,27a9a54e,1e6d4fb7,0ea49631,9a99cfb7) Z8(08dd32ae,77c14abf,1b68d980,433fbe56,b5839822,1f4333de,e3bc83a2,dae3247b) Z8(bf6f9201,3aa20feb,64ffe483,436f9181,e524b96c,2e2b487c,2d0365b1,dc4f694b) Z8(4370bbd0,711bda19,087e5a88,116e6872,0ec0467e,61fd7533,0fefa186,b3554ea9) Z8(870b745a,6ba096e4,d00b13a1,b1a32b07,725fbf02,47b12e83,0d7f9016,8ab24db7) Z8(58afa49d,e9026dac,9a924d29,f26cf734,acee4a10,58b0206c,026c0348,4b91b19c) Z8(feccb3c1,f0a78d83,af592247,707d135b,16383883,4e34dbd7,d7bbad87,d8ab4330) Z8(9d20b4af,0645d8a2,d1be30ce,eabe0a84,2d6dab57,91844e4c,59898a31,4e265615) Z8(2ba27461,33e75cb7,efc2f3c5,814b9960,b5e0a141,36ce7942,6d806136,e2a795f4) Z8(afb2a2f8,d9685d81,f1aa8f8d,915681b2,1bb6571b,04283df2,8989b1f3,6712e10e) Z8(06d092ca,a2c2bd25,348dd185,50ddd303,2d996bf9,25ef65dc,8e870978,0379ee25) },{ Z8(708ae387,b55a7a9b,49ef93d5,69116798,000e2c98,3e9bfa00,13459641,c5ef2f12) Z8(7dc07e2e,aff93b01,0e9ba971,3ead9875,37a74c01,025d52fa,84fc6774,adb586a6) Z8(1f9e4617,983881bc,d83da580,0350f2ff,42c79fc6,14f447f1,e672b5ea,734e7872) Z8(2a5c24bf,01c697d1,f802fc1a,4084582c,5e09e0a1,f5a1b882,4acc7c26,23b5dbdf) Z8(ea96bbe7,530c75cc,c3fcf5cd,b2912ee8,4383f0ad,ae6e89a5,84970483,46f53baa) Z8(32c9894a,25ab7744,6faa3544,6eecf141,83f44b69,4b2ffe2c,330f25be,09388d0d) Z8(04d46993,feaf32a0,f65251d2,1745d97b,4778e3cd,7bc339bc,78987831,2888eae5) Z8(805a25f7,2674fd22,74e91399,472cfbe1,bfac6b75,fb7ae3fe,7ed88b99,c45baa37) Z8(f9cb2e29,fb285d54,e9ff7f9c,9dd91864,42cd7971,1d8f6ff8,67e36b8a,a44706e4) Z8(2c5185ea,561f5067,37967862,f75de657,189a0dc8,8b7f2526,81a2f042,d7473598) Z8(27805f6b,8e13e378,ef356f48,a0f0d2fc,4c8d7b5b,6d84f28d,97b0509d,64f583df) Z8(21b6ded7,103e2620,dd736b8d,a56a6710,11e7e834,8c5c5968,4ab275f8,8f65844c) Z8(e822602c,39ee80f2,0bcdf4b5,a3371c2e,b7517108,12107baa,d6afa1c5,453dd768) Z8(5a3347f3,61e5a89d,17084b05,7a86a067,9be99417,f6a730c5,f61fd3fb,60618ff4) Z8(a174d99f,189a4320,1c993793,62e36683,45df684c,b94d7380,aca5bb10,9d6e7cef) Z8(dee291d4,5d845d46,aaf61c17,6dd0bc95,acfcce42,ad4d7d1d,d29a2de8,0a1bb837) Z8(c877d8a1,c6b74310,0bef184c,cedfed6b,e92f5d83,52c20e14,9c15cbc2,9b9d4477) Z8(549e114c,dfb437ee,3d630d8b,41f8076f,13ef95d4,078e96cc,22470295,03b90963) },{ Z8(12f0fb45,2e238d06,b7131aab,476a3ec2,9cd09466,9d83c81d,fb5e2123,a4e8be4c) Z8(3705abeb,e3627abf,53fca206,6ef5e0fb,18c6b784,16ca532c,7b4d871b,191be8cc) Z8(cb1faa09,e810f865,f67ac305,bf932bec,eac773dd,44d4e77e,c034c070,ace93e2b) Z8(bd20e950,a4032e9b,d5042dff,f55f468d,45757ccf,ebddf885,cf43d77c,d40a6942) Z8(fbfe4527,709d999f,36bba480,184ed029,832ab1c6,ed7a9c2f,303cf958,8ae45482) Z8(fbf7e39d,04e007a8,0bdf0273,e4649dfd,dbe9b1cf,be1a3085,dbfc44f8,cd84729c) Z8(27829d93,f1d000cb,53e5fcd4,39cec4c8,a6564d3c,f8ab5e90,3d5d1f3e,9ed8b522) Z8(dc7275c2,68de1a34,a2d0c588,f4a4c506,6473b5ee,bb442581,61de378e,93b39a84) Z8(ab01c836,290151e7,750ca86b,e8df1afa,05f75773,8f804956,4f5e26ed,d105e0b6) Z8(f43da505,6db5b10c,3b040bbc,cc940b0d,56c09b7d,dbf2810d,b7a9efa8,749b49a1) Z8(bec9630e,6919a793,07e450d0,9fc08703,c9938310,1a4e9c5e,9466d962,18d10342) Z8(e21176d8,1f5a322d,164d9eee,1114aec3,1950bd23,e4ef4a87,b98347e0,8afb2ee2) Z8(760bc66b,cf609b96,d49db045,d2670a40,ea75a3f7,12d28d79,c817b859,1998272f) Z8(88892133,88a204b3,5c10eaa9,5e523a53,150060ff,368ab0d8,03f8f465,43f674e8) Z8(fe905d57,dbde9f7c,d8363cce,0e897ead,68d7d37e,923da68a,bcfff7d9,d117bb22) Z8(65dc2153,0755b0eb,79a8ae2c,567d103c,5d2a0984,75016251,a1fc017a,15567658) Z8(1ef3a140,e808e153,3b4ede62,ba7510a9,8f9f71cc,7841aece,758dcd0b,7a59b490) Z8(77122f83,d140fe05,3ddc5335,eb03be90,6f57aadb,f3db4e9a,1f807c79,03f81516) },{ Z8(163db538,c9e63567,9b36f943,cda572a4,cd668dbc,ba76e4b4,2367c160,5922694e) Z8(17a206e4,8372326a,f04c6517,5487b9dc,fda97fed,d31b54ef,513698cc,b364d232) Z8(5032acc2,f8d36c20,ebaccfff,140651fb,5cc7d99a,3b2c51cc,a8b44dae,e76772ef) Z8(bcc11679,bde5d0a5,feb96730,1bf0ee82,7e225a13,7bde795c,a2650462,2ebcdf23) Z8(edcf0f34,4adfea10,2fb5c5ef,3c935a2e,f7928110,c7d7690b,6c8ea4f6,b5500cc3) Z8(3cfd3afd,68bd1e69,0fec52ae,2a124356,2d6e9d4f,67ae02b2,03ed0778,49c76c68) Z8(30b3f9d8,2d80b6a5,2432c296,71cd3477,9bd27620,46992920,e0fa9ec8,d6ecf79c) Z8(b236844a,e35a537c,f1ae6d00,a04c0df8,c21abef2,92fbdef3,a431c4e5,e6742218) Z8(b1af2e1f,5d3a25f8,db086156,a0b20b4c,a28f7907,a37187ba,b256c918,74489a93) Z8(9b3b8bd4,0356861a,686c7103,ea439b6b,c2560288,adff468c,232ceb58,6391bfa8) Z8(f7659d64,a7e3f0a5,326a32ce,cd890ea7,94129e90,801efe84,8dbee3a9,afa12271) Z8(b7db7b3d,81fe1c90,cae56407,a93fe924,68869c53,d56d7ceb,9c24180f,d4fc3fc2) Z8(19f24a27,e9e2224b,ddd691c7,45bf49aa,e67480d7,819dcbd1,5a6e7a60,aa22b436) Z8(018b2d45,f9f5f589,72660e3e,c6786ae5,757dcbfd,b891261b,7e47d0c7,8fdd5f2b) Z8(fd551fb2,d992ba3b,7c24b177,9bef23c4,409c8370,b91f9c9f,f502d83a,b619924c) Z8(47667a58,6ffc7355,73c21e85,0fa47c33,06d0903c,f361094b,318979b6,2782afea) Z8(fbaec97f,e97cf293,700a7df2,64ced1d0,e6221780,137e70f1,1ab02780,5412d654) Z8(d664dace,75e6564b,d11ef23c,fd896bd5,01884bdd,63fe7602,2bf321e8,04371146) },{ Z8(cb2f2a01,a705313e,5fdf55e8,22d6376a,c930db99,03e37e8c,0dc9cb66,068e526b) Z8(865a839b,32a75ae7,2c60783f,da801644,7b927779,ceb0f6c5,fe28a7ad,90c11e82) Z8(342e3340,91d86065,aa005a5d,d8420e82,9d7444e9,f2d36854,bda9641d,fe72e425) Z8(feb462af,9086e6de,f34ecf44,10dd5f51,904e453b,f134997d,52616131,f9761f13) Z8(79fa1cec,5d99a6b8,c77017af,e63f7e04,5dd317cc,e261c681,3acaaf15,3a076b9e) Z8(eaab0c5a,24282b35,c7f870f3,668a7525,a8570012,073da901,6f9f23c3,7086f204) Z8(57f45936,5a4b0149,7de91f55,48a4f5c6,9c002a73,0f09c281,ec34ca8e,d69da79e) Z8(8edceaf1,55f55040,1f3097cb,b7cef409,266653a9,81f6e6ec,ec4ec2bb,6d35009e) Z8(1f5bde44,ac3e7cd6,df3347a6,0edd937b,cc53dc51,00db2709,95b3a9a5,0b166442) Z8(be71b186,9aa2fe90,51fbdd97,366f7515,55d61457,31a99cb5,6271f1ff,2f0d705c) Z8(210aa18c,e7f3f0c8,00576a7b,93d4d3c7,2346ed7e,bb383117,6f98d013,406dffcc) Z8(ac260a05,2463f8ca,6e3586a5,424feacc,23f7579a,d2e12243,15dea851,28d36193) Z8(6e639257,efcc04fe,42b682e6,469bdc74,f75b1f81,4f9a092e,056c1963,3f873bc7) Z8(88a1d754,1a746c8b,de923d79,e9a4374d,f3975953,677e7856,3778c00e,c2867aab) Z8(9620c351,0c469a40,32b77b44,0538c5b9,bc112701,92cbdf38,7dd17c14,3ab47239) Z8(7b89aabf,1d697eb0,fe38dbc0,7f73d127,3e584998,b8d9870e,600afc71,551b07c6) Z8(607ea1db,3173312e,f64eea82,e092cba8,b55ba15a,b4f1ab11,900a0b45,a9a2e09e) Z8(284574d6,93caeb7a,3675bcb0,832cfd8b,92038956,5f00ce16,e7baf9b1,0475fdfa) },{ Z8(5ef647c0,fcfdd376,bf892459,43109ea0,fe30f79d,5cf5833c,2d2e5e3b,ac03041b) Z8(1dd2b9fb,4651278e,9c09bc51,c7aa405b,90e43af8,fa19926e,dc3e52a6,af6b454d) Z8(647391f2,38d49352,b6c2cff6,fd2c3a86,f85957c3,0477cca0,f60e0a54,a9e9a8c9) Z8(7eb70030,c989981e,e8d66d44,51292ef8,6750d65b,6f657686,3b90bc8b,fd7f3828) Z8(8865e982,ac90effa,2b87f6eb,41984774,7e23a16e,56a97f6b,44c33e2f,4e82224d) Z8(2dc9a40f,05c3730d,a9d063ab,1a433dc6,7369fc64,af6e68f1,969f56ed,96f60bd9) Z8(b264d59e,e3d5b8d9,a4a76ccd,e629f53a,e0f5701f,5139a7fb,6a9abb26,0212b3ca) Z8(b4511588,ff35e5a3,cbba05a3,a3f627c3,3d7a3f56,621e37ca,ad8e0c00,caee789b) Z8(8d6875ad,7fcd1896,94cbf398,501fef80,d889fbcb,a8422a47,b6070b25,086de5a3) Z8(8af9569f,4bf97366,3cd7791e,b8a70402,496c2e77,7b55c380,7b3b2bb3,703ffc52) Z8(a88f45ed,e7240f1f,7b3f396a,4b0396c9,43919489,53d066d4,8726112d,eb7767c8) Z8(5a48a76b,81faf156,06cb8b9f,4791b794,05d56c93,26aef6dc,65e54c2f,341b07e8) Z8(c0b4c04a,4a4ba8fb,0d820f5d,f86e26a3,b6599623,97ecbc9a,7beecfaa,1950a2ff) Z8(943240eb,0d4d54a6,8a69ca74,5ff52cab,67e3bfc7,843919c6,8c55fc71,174ec48d) Z8(ce7b2024,0a853218,c8d27531,e7fc7f2f,2bd0cf0f,4b8d1c7b,2def3291,b32fcf32) Z8(117fe340,a1d2638c,9ffb5db2,5c69ffb5,ae67236e,c54ae137,cc4d52dd,0959f4d6) Z8(45c6b56b,f257313e,b1d53f87,61373d54,15110193,03613a61,07a331bf,c4863a34) Z8(b2039012,848c59a8,49625011,7c82df98,7cc22aba,341706c3,ed55f0bb,04b4db3b) },{ Z8(da572f0e,4d13621c,0df25a34,deb6adfa,aef523d6,c7e8339e,b7b5a16d,ffecd55a) Z8(8f237bc1,90c186ff,b3a9e548,b0b6d340,10554732,0e670121,2848e9d5,2a2ea741) Z8(283469fa,841871de,7a47fa3d,66c00f27,01629c6b,0d9230cf,479fff97,ded87a3b) Z8(a77b84ae,090db65f,0de4a117,cd42a53b,4e267a96,cf3180eb,a9b88708,1404ce24) Z8(6dab659d,cc82ba27,3daab0bf,4bf045c2,88b1eb48,112d6006,79d10a96,6ef913c7) Z8(65acbe07,bd2a823c,928bd0f7,0546e34c,4a1b8ffc,26f7517e,2803bd1d,0ac1b41a) Z8(bde87922,c84469de,5adbfd36,623f9545,f476644a,545bf5ac,7496442b,abccda54) Z8(5d6a1152,c893bde7,83d4e2e0,7c605fbe,d4fa45a6,6e3769f1,cac10a7e,82e1ea9f) Z8(39d2cecd,9ff0f2d3,8be8d141,ee150b19,a467bcef,86563637,e7b12c0a,16572af8) Z8(c4ec451f,5800bb8c,805a5703,40f171b5,6957541c,70e1884c,296634d7,f32f47a7) Z8(3411b441,2f442b08,a19677b5,1812b213,ee4d8dbb,83321168,fba3e620,8d7fc122) Z8(0b17cac6,bcb66043,dcfbebdf,a9207bdb,97119fdd,b2efc69a,f2c8ae68,bb522ad0) Z8(b63ebb20,e3f4c54e,693379f8,833468ae,bf70c1eb,b138f390,d072f279,59d715d2) Z8(788aef61,d35ee6e8,0a477f1d,98c02bae,d16be46e,f4329ffa,ccb5519b,47b9924f) Z8(8f431474,c47d6abd,12f3f20c,e51848f0,2d195252,70f6e746,af702c79,5b254a6b) Z8(eaef29c7,ef9e707b,4f578e93,052904d5,65414c9a,ac56c268,cd7cf686,8569de73) Z8(eda782f5,dc378bd2,071a1b2d,5553f465,2dc0b3cc,d22e50ca,49277dd9,8a09c0da) Z8(d75476af,933d8902,2677fdbb,83cb8c4d,31790cc6,cd295bf5,d1a95d3b,04f3a910) },{ Z8(8be26c30,4c004b16,60885b96,0cf6bcff,0f4ca146,6a08cd58,4fcdb0aa,933455b7) Z8(4048af18,89d3bc4e,d4307de9,97efa699,caf52d59,b6b5a0dc,8200ad2c,f5d64fa3) Z8(22d48a7b,7bff4b75,f0f4453c,834588a3,133e932e,c7d030e7,57b0a19d,9a95887e) Z8(b0718949,2b7f1660,5eb5d793,d4e19958,53488579,c395f336,71e22dd3,16fafed2) Z8(b1b4e81a,96cb8366,982e77a3,3047a715,602b3d4b,4d28cc14,81a2bd3d,6b6ff906) Z8(3323af07,3952fd0a,043561e6,42005c02,a0dfed4e,80f63d1d,61c756fd,0ad12863) Z8(0d2e735c,0afb0a8f,21fceeab,6d921b1b,3d02d9b9,04ce0734,8b272f79,6d3057da) Z8(5c19fff3,fc1cb332,c999460e,996c0b38,3d6a57ee,3a3df021,39fe54d1,50ed1840) Z8(27f193fb,d6b7a1a9,0c645c96,9eecd4d4,5137e90e,b4f625af,b1eacc4c,d8887af5) Z8(4337cf9c,ca0b141e,3f7d5c72,a4119b7b,9913b724,a5de421c,54dd8c97,c5af7177) Z8(c703b51a,cdc0482e,bf1b21be,ef0f9df2,7acf6b50,08d20648,496fc10b,027caea5) Z8(3d6ed003,a897ad97,d4edc1ec,d52365df,f76e78a9,e269daf5,507d6954,672336da) Z8(eda647d2,666c3a78,70ffea84,0f6b01e0,525dd74e,52bd92cd,1925e3d5,d8be71ba) Z8(81c3ec8a,74c8764f,f35e94eb,bc3c9244,bda4a2fb,081e5f48,b032eab8,315463f9) Z8(4c0a2cd3,9e63f71b,65ba4eed,1503c819,0935dee5,6c78066f,f8f0aa85,e8b2362e) Z8(b1eb8f50,3164ebac,7ba6852f,76eba6b9,b809e8b2,85c8787b,2563496c,305b87dc) Z8(50ac3ed2,7fe25aa9,2b1039f0,5d6119b9,add46a1c,23d48657,cccd0089,56a73e48) Z8(5bb0f2d1,5d7fd0cd,a84d2af2,ce9c3f63,2f94d43a,977d7d29,24077b31,05326781) },{ Z8(fa9e1452,a2ec69b7,5bae3f9c,61ec7219,eb482bd9,8b64adf1,28a84723,bf892b3e) Z8(b6456d75,39759602,3e15c2b8,6ee073da,e8e930ac,15302fa0,13040f46,d97158b3) Z8(ec63dc7d,db395529,8350aec0,094c3256,86625f5b,3edb45c8,cdb1fcca,24008f01) Z8(3e3607ce,357795ae,09ec481c,855b610b,69fad719,4a2064e6,b5059bfc,7770e7a0) Z8(61b2f8f0,79787e04,16954afb,1a574fb2,15e478b5,cfea48de,74a77122,5e123088) Z8(e8a676e9,0a5d0e3c,b54e1ae6,22453cc7,d813363c,c68479f4,00d7ebe5,2c8a7abf) Z8(e0491fef,0b6bc8d9,0a2f4ded,83df8077,c08318dc,e0ef32ee,c1aaee4f,eac99e23) Z8(8b956bd3,f1bc4f9e,cdb2b826,bcbab5ed,ec44b91d,8e9ea535,2e9e5952,b9c6d046) Z8(950488cb,e2d74fa4,fa19545b,ee093e24,55828f38,9a2a123c,8aadae82,e5b08040) Z8(70555df2,06b5c5f6,2250151a,91e9ca97,0762d616,353ef9f7,13323d2d,dc8fee96) Z8(ab1c12d0,c8a798b8,27476727,f3c1d8a1,53858ad7,85778366,a8d83a9a,48198e29) Z8(29a55592,996d76d4,cad3935d,f3ed080a,40e2c534,07fa59a9,5233dc3d,ad30be9a) Z8(9f5a5dd3,0aac91ac,8846c278,7b2fa6ae,b0b1d941,462f0be2,52c7eb05,66a64409) Z8(be777821,5f6b3e5e,9333aafc,5168bfa7,36f15cfa,f2e417fa,43e13869,8880c50c) Z8(bf0180cc,2bed8cd5,abfe3a42,7dbc997d,008d5777,2605ed1f,aaf95e32,7c39f30c) Z8(1f6c0f1b,6ca3476d,eb2146bb,b58a3edc,74632ab4,b2265f98,88dda7ea,6d713b17) Z8(dce9c5af,765b8ffa,511e98db,6c1c5d87,3cba5864,315c9ec0,b228bcac,d667ed58) Z8(14f71a2e,1c790cd7,457d1ef0,955d55e7,de4c2c17,ef493c13,6e34e224,05711694) },{ Z8(bb56b016,2e4d0c17,bf87ec44,3b1fdaa7,d843b80a,39ae3e1b,0f5bcec9,5bd542ee) Z8(0f73888a,8b197062,f39470b6,d8d3b857,a9916e98,2c4cb001,a22ad515,7c7c4a8f) Z8(3cab01c8,7b443457,9caefa58,4c75e32a,65d7722b,69fceead,6883d841,d7c8409e) Z8(7c08dfd4,53152375,a9591fdf,fd046cf4,25377ec7,0577e21b,e8beefdd,a20b5531) Z8(693267e9,f578765a,afe4c7eb,35e2eef6,befa438e,194b7633,0ab81da6,38ffcedc) Z8(840a9b18,9de6c8a6,ee256108,0f1860c6,968dd4d7,f9cf11bc,9e6f9c3b,76ff832e) Z8(e40fe013,4be1afdc,2a330703,6615d6b9,5403f219,0c69e0f1,ec8fb9be,36f28bc8) Z8(52284db7,afc84dfd,a6ecb2bf,ebcf0236,8d4c91ff,0d02cec6,97a06e64,e443afc5) Z8(7dfe214d,28628961,8950870c,10e2b3d1,883738ae,9c29ec42,4beea27b,ceb49a47) Z8(e173dd5c,d5f03d21,1e0a521c,f78abad6,e75305f7,cb16f34d,02f60518,126a150f) Z8(24d1e4e7,702bc5d2,91012da5,996c265a,4a551b2c,acdde710,9dcbb952,0e6a42df) Z8(633f1f85,218dcf42,a96188c8,5ba9d7d5,caf0d5d2,fbee344e,314e23a1,78bb26dd) Z8(6f0b58fb,08b90ec3,740a0c78,d81caa9b,1a38123d,3bce3da6,10667756,b85f69ee) Z8(72cc8751,e00ec18a,5fc7c44c,86089367,412f6321,e8deb2ff,cbd4949c,cd0cec78) Z8(67a9d380,c9b9ee65,bb339aa3,7e0c53a5,5141998e,8a04daee,18d0bcb7,9d12f2a3) Z8(f7d04569,1b638930,e84361f0,1614c07b,a1953880,b4108203,cb370351,7756a89b) Z8(d495d718,aa0f4ec8,ca0383c3,466f70d5,96e04600,a1dad4c7,e195df49,b3cba022) Z8(d99a1cfd,62dffef7,e17cbe0a,01f661af,6487d494,e9f5bc08,346df43b,05afb652) },{ Z8(4721c8a6,bbf66cd8,276a339e,5bd99769,e95d05a3,7afd5c57,fc6a1571,bd932e24) Z8(a65dd006,e3f44b06,abdc0309,16eabdf9,31206e04,36cfef33,4c050db7,18e10476) Z8(776b5cf9,e7a8dce7,97784e81,89ffd7d9,44389b74,e93f218c,51b14ac6,9ea14aa5) Z8(ed5f987b,46f09437,d742c766,3d7595cd,4c4fd33b,e4d2e4a9,b1a95d26,744b0159) Z8(a3898580,64f38012,674f5774,715750d4,3ac64985,4830c525,0485187f,31311473) Z8(7dfd0baf,10cd59a1,79810105,eb13755a,4d7afff2,ae16aa4f,c8a54cf0,41daedf1) Z8(806fcfbf,f86a2fe4,80c57d80,6196b728,adf47418,56a58176,8eded60a,ead91ce1) Z8(10d7da19,b56d1395,3942acfb,2f2ccbf1,efd45b86,0355a4f5,efe82f51,cdbeb1cd) Z8(807e86f3,bfdd1f34,0b271746,6bfaa2a3,3dc12483,1789a3ae,a8f5654d,a8cea408) Z8(ad59430d,609f446e,db96ec1f,09fd449b,00d18a96,94b1ceba,9c9589b4,8f876a3f) Z8(10a609f0,9b47fc64,b7c15d80,3c1806ec,b8a331cb,c62baedd,3d6308da,d997c68f) Z8(acf4fefa,b10554f3,155fbbe5,469dad29,802da824,43f84d19,f6869fe5,f5185580) Z8(7c204da8,ad26a9dc,53141562,13d6010e,620bfe87,68eacd59,7aac09a3,fa8b1481) Z8(e5b5a387,7fb0a7fa,58aaa5ea,a3ae6a7a,e76f60bf,042c672c,4c044aab,74f0b9aa) Z8(9890e6f1,183ea7a0,c45bf738,4159d14a,9813a0aa,927fd911,47e7951a,09abdca6) Z8(ecb2a27c,4836b43e,cf1fa379,1f9c224f,81c5bfcb,bccb8a12,ff26439e,1c64fa78) Z8(31e125ae,9bb5ffe0,140b9e2f,086d1607,45ddab78,67ded6c5,0efcad2b,d0f00eba) Z8(3a835116,96efb673,87466226,53c40a94,5af00773,49fd531c,f56c46aa,05ee46c1) },{ Z8(0e1ef5f4,0c0aba65,67d93493,c63d4fab,ec4f7edf,2e5285ee,a51fd253,8709d080) Z8(9e9da774,3f44fbbf,b86f7a37,44eab559,a39ef21f,1ef78815,eb155652,b6529cfd) Z8(a0742b6c,97fd08c8,459006de,5258e61e,042055ad,baae4f16,498efded,1016a8e2) Z8(89b968bd,5a6acebb,53485137,26addc62,0c8fd308,30eabf4e,8ea1d3ae,0190bcb2) Z8(0d4a5452,39d6218e,eaad6bec,fc5c0c1f,e98b71f5,07378fd9,5c914b68,2a6cf9fe) Z8(dcbc06a2,c3274877,99e9312c,5cde7527,539cfc0d,b781f2f0,f0b55398,760a7367) Z8(22357cb1,99b8f71e,9e5d7cdb,420f4812,dea6bbf3,faaad2ec,e3db1fdf,b162c28d) Z8(21c08cb5,fa52c599,724a7165,2f7ccef6,7fa6fdcf,d0ef31e0,38d21af6,28c27984) Z8(910ae92e,6bfbde01,cbcdbc01,87865c93,c9c0020c,1ab25081,52a8fced,595c515c) Z8(8c5c129d,20098635,bf5f97f0,898bb3c9,dc73723e,0af3ef92,f5a04a55,ba5549c2) Z8(882ecf38,d35ddf2a,ee2ceca8,e34b10ea,a7d18a91,310952cd,34af382c,ecb7c0e7) Z8(48e3cdb2,9436da17,01258875,6fe792bb,416faf07,c4fc9a30,058875e4,a8e7074b) Z8(7dc919b8,3f16ec2a,9ae9301e,564813ef,14a230e4,994da409,e2fcfaef,9e8d705f) Z8(26651e77,553c7ca9,56ea8d7c,e71764a7,0a999f86,3d71ed6c,f8d64db6,ff163382) Z8(3f26a731,658e9d44,b7ef25d7,0d38bca0,529b1a45,33bc9870,a10b5eab,8b4c7a5e) Z8(9fb0992a,d394879e,4a401d1a,9dac6a3a,643eaf4d,00a0fba4,51cf017f,4dd885d6) Z8(43f64265,a2d2d612,891af42e,14f91c4e,f83011bf,86b83575,3a33f6ad,ef686497) Z8(05e8bbe3,9132368c,4f979df5,a323f16f,d9dc732f,5691b69b,2a6c0387,062cc7eb) },{ Z8(aff37aaa,ca22d17d,4da8a7dc,06ca16ac,18d97957,897d2237,9e16f513,70604f05) Z8(7892dd29,a18a921e,688a6505,5bf19fdb,ff32b7ad,5fdc36d8,af84f790,05400a4f) Z8(fd39bc6f,00537c46,e5857707,1974243a,c625ad0e,51d64cce,f781cc06,bcc2a01e) Z8(27184414,9b2e6902,5ec5fa7a,50389bfa,3a62887e,eff33f3b,08bbe855,9e3d41b0) Z8(9aaab2d4,99c70370,fbc0cba5,0c65899e,d583dd2f,f8dde639,41bcad87,a3a066a9) Z8(49ca08ec,f3ec5739,f29bdc83,1a86ee24,2e5b6dd5,fa1c0a5d,5d3662a2,55ab19a3) Z8(1f9261a5,c3d6c550,1a29383d,8fa22d02,0abc3e6b,bdc2e674,74ce1388,9a8f1f0a) Z8(75ea6f30,7d12d69d,eb83e0da,b73b688a,b478221f,b0e76847,69a90e22,dfa28bb4) Z8(40ef61cd,cebef295,fd6b484f,5516d1ee,6e0e652b,d2e0a89d,90307856,30840193) Z8(6e0f1f03,09102b76,a1f27343,1d3b9d44,01fa09ea,feb7f9b1,bf8c889b,6f75f2f1) Z8(c5d8a2eb,2533f14d,985b9946,0fd766e5,4ab40c7f,d4cb8f02,49691c4c,e25f52c6) Z8(5b2d6f37,7aa0e898,0b6eb814,35d83a63,bcf59086,6ecd5229,28163efc,c13cbfd1) Z8(c83be49a,d7171a1d,51166345,78189cb4,9c900043,3629f968,8f9716ed,5a43826a) Z8(52004870,8a6a5ba8,39b704e3,1dc8ab8c,ce2ded5c,2be4f5f2,03027334,1533ae0e) Z8(60726c2e,1dba8cce,f46efa7e,4e1e33b0,ef9e598f,0fcf9351,637bb8d6,5b489633) Z8(c361e640,3c4b581b,70897f78,57284fad,69fb25d8,d595cc98,866d25b9,a27b6488) Z8(b37d5147,9908a950,39199fe3,6c87ac32,a274470f,98312fbd,6816dfeb,a504038d) Z8(d368a378,1b9e2cc8,ecdcc26a,54559665,167f14bb,409c1df8,47314513,066b39d5) },{ Z8(be0038dc,751b788b,0f9b7ffb,5b212afa,e0dbbbfc,34055ddd,c744fed5,861dae00) Z8(9fdd99c7,23ec8f66,4f99a141,459f0bac,afb868e5,21164c56,875142c9,74c00e30) Z8(e55b3321,b498bee5,20cbf9da,f0fcc957,ebd3e5cd,74e3fbcc,ade1ec4e,1c147958) Z8(de7f92ce,4e47f81e,0464ed12,d3ab8fe9,54f8cb75,ac21695a,368ba5aa,fc8cbaa4) Z8(19f98fa1,33c328e4,c8b5ed66,44657b62,43a40d4c,15e7f696,927f6b48,889ee15c) Z8(dfc9bb83,700ba2e4,5e82449f,57b8d6d4,1f1d430e,20813840,b0cb006f,ae0e3190) Z8(6b09552f,9b454a69,5bba59fe,59ee3258,e49225ee,bc9db60c,e11c3c9c,a11178d9) Z8(f76764ba,f7eeac1f,44c9cd40,35cb7eb3,c1b63658,89cfc036,3655e9f7,75d45cf8) Z8(40c7c293,20ecf925,8125642b,7845fc46,9db66dba,517711d0,6fe7f6b0,84f07d08) Z8(b424e99f,0c68d4ba,077ca960,88cdd408,eaeadad9,f8297ff9,3b6fefe0,711e41c0) Z8(2d5613cb,b4e20646,99778a7a,e7d727b4,a515882f,c54a1deb,a4d86ddc,8b61e520) Z8(7c54d151,4b3185c5,29cc184d,887715b7,fad5f7fe,3801b492,682729c8,32ea1363) Z8(d7406399,41e36217,74ef24fb,6adab348,e6f73660,c2a3e433,06275791,6b7cab2e) Z8(f06d1db1,78328c7b,c3a484e9,d724439e,2bd848aa,ede51de8,626db81a,c10e16f3) Z8(620fc557,e23769c5,af2d036b,b64cc638,0eba2743,9dcf5fd2,4325d4ec,40396b90) Z8(cb957a24,8164341e,662a5fe8,131af729,6d18da1d,ed836767,27d8dc31,dd64c2d2) Z8(9b429d9c,786747f0,1396e6e3,e032ce67,d10bc015,8f6de378,70ab5436,fda21c12) Z8(02988981,68e15d73,9c1314e2,d6bd36cf,d4ef6fbf,ae2d7a49,ba0d6a75,06a99c87) },{ Z8(70e8ea8c,615b856a,688b0b51,aab0458c,1d8d5b8f,54bba7ea,7e5e6b1d,cd2645c5) Z8(a201d318,66569a3c,dc86f805,d5fd5231,a59b1c27,d25d68c8,f411d831,7243dca7) Z8(affe4e9d,df89dc17,ec7570ab,96b48fc5,40389ff8,dbfb5cf4,ab14f32c,5157858f) Z8(941abbe3,ad754a1f,71591a1b,663ee34c,adb3b00a,73fd77ba,e0e5f7a5,d6715d5b) Z8(b708713d,a7a36eb1,b948a28b,86fe44d5,9dca3afa,8b711078,c471a2df,8dc5e53d) Z8(cc94533c,7286a2d7,4f17dd96,7f2067b3,2d808d46,98f476e6,085e52c1,47174c02) Z8(46e3416a,c35283b4,3e3bfbb4,d6715062,e2b72d91,563cb459,61ddaf82,04ca691b) Z8(2649807f,17772207,d3802e0a,7b1bed44,3da0b93d,3935c92c,c89743a9,abcba6d9) Z8(82d8c444,da4a2e8a,ca795fd9,a44e1a87,605af533,69c2aabc,a7771b80,5495df4f) Z8(e05cafa7,611a34f6,a16fb648,13571d21,82109b58,0b2c6b27,289bdd1d,6382d9a5) Z8(5d319990,e8be03e0,8f23a207,d108636d,98987bec,5aa0ed21,a95b32d1,f245bec7) Z8(485d8ef2,513e6cf6,23c8524c,52012516,85776eb7,13473f66,10a6e3c3,d044b30b) Z8(a70b9e7d,caeb7a04,679514bb,dd02b650,9e281815,6424a799,cadda2ae,2c7d0d54) Z8(00526fbf,1742bb5a,d68e13db,60055d20,f7d23fc5,1ca1abf8,b5326ead,2fcb76d9) Z8(b65341bf,b20a9a64,5f8b6449,f947d48e,4413aa3f,19b92876,75e6680f,3bd10a84) Z8(0869f15b,c009e034,9bd626e6,b54a70e4,c7f749da,20251a75,2e5db2b7,cc60184a) Z8(42ea37c9,ab1818bf,7219242b,a6bcc014,59343416,84d1855b,d32356b1,0ad8aaae) Z8(722da717,5890e9ad,14dcddcc,f6d4cc7d,2379867f,f5196dd6,ebe465fe,06e7f009) },{ Z8(01a4d3f0,057edd94,a9b2d735,ac94998f,3b24145b,d5139c86,ed6b2387,a523abd6) Z8(f2415e58,c95cc4e5,479af7ef,adcaa6f9,d7966ad4,f58e4457,941be2fe,a90b34ec) Z8(c71d0e53,bc334f28,582ec1a2,f6debe88,a58f7f00,9e6493cd,7d27fc27,ef71c7cb) Z8(de33bbc1,a54b7a8c,9fafa3d3,52a4a277,80a735e1,44fd5769,ba66b4aa,d0a041db) Z8(b16ec7cf,c58eb4d2,dccde30d,69781915,6667e692,d77f7803,cd357d1c,a2827258) Z8(918f24e4,d2fabaea,48bf74ef,12e6628d,221ffe31,51e6a4d0,5c6b9c7d,24e6c7d6) Z8(555a5dd6,aacdbce0,ee265e32,95a84f5a,de79ea30,5485931f,f08657a3,02cf092e) Z8(6ee55edc,191c0f35,76621d37,d53bba82,1aef01dc,cbc6aab6,672f8ecc,1bd52be2) Z8(3aaa2799,886b4161,d6dbf1c7,5e121ca8,e83e016c,b59e6ac3,7aff05bd,2254abec) Z8(c12defc8,77883600,5e632a3f,ef70b3e2,f8c682d6,92e52e07,e7bf0bdb,d00abd16) Z8(f398ccc9,80eda78c,9ff446b1,72fb8ccf,083af5db,9cf46081,0d05ec1c,e3b6b28a) Z8(70eabb2b,e06c2312,8e7ba3b9,114e0222,05e2174a,1a3d0ecc,0940bbe8,b1fc7712) Z8(93f1bb04,5503f52d,7bdba625,beb5550d,fd5ea10f,0339d65d,499715f7,9ba419ea) Z8(5b003297,590b64d7,2c509cf4,a8b7ee26,c1bb7e3a,5513a983,60b0ccca,9d8c3e75) Z8(741efc89,59ecf814,035e6c48,43f7c505,90f447cb,0bc4d957,3f10709a,916e59b3) Z8(8b66ae15,f7859b09,1d3e752d,e74ebebf,f79a6d44,6ab0f356,8abc4546,94208914) Z8(1fb53708,c0a4b18c,6e15e1b1,cad0c9c3,0b9f264e,878663a8,9844e710,14d25218) Z8(11756168,1a60f994,5c1c8434,963b4c9c,6d209101,7d3b1078,403204f5,07263463) },{ Z8(d575075b,b1bf895e,78fd94fb,79b4fc43,f4276543,e89c3e0b,104bdfaa,aa3519d2) Z8(834fbf89,a0ffd6ec,1c6b1d2f,606b52ab,45c52ecf,0d71e150,e432fbe5,428e1272) Z8(39b66eb9,b664efe3,71468977,b5b17fe6,d3c4ee69,eccd6884,90ee479f,4560fcc4) Z8(439d8e86,c3b30470,77d8871d,420bf9ee,3f5f203d,e3be9629,29ba0aab,3426c7cc) Z8(2dce18f3,0a027547,e193c5e6,f40f54b1,9f531ac4,52a68166,84d2c1d4,8af92b9e) Z8(2f428085,1c3b0114,8b53892d,72da518a,56abe013,076d5b2b,0fd8ad99,95595e86) Z8(66328621,92ed6e0d,2b45c6ef,3a01bd99,f91f2185,6df1aed3,67529e4a,de68c28b) Z8(cc74b470,a1c84162,14e85f09,9aa72160,e08110cd,0b224027,b28bca1c,d6476424) Z8(92cd7e50,247d9415,dba32570,eeaef994,fa6ed634,d55132cf,22a79d51,99ac3485) Z8(ae17f608,501ce93e,8cf1b4f4,b09e4791,61a987e3,da6aaf85,177024d8,b5491f43) Z8(50963782,5aea5cee,c459534a,a6dadd21,a387eea6,f136353a,9f6540e8,15059665) Z8(1dc6647a,6e41bbb4,d7fe2bda,9ececb92,62ded8ba,42302365,a05c719b,8a38da37) Z8(caef1492,e39f22c4,d4cba29a,9f473bc3,3520217f,bc76a14c,0ef6f273,6cc64971) Z8(593c8c4b,9ef237fc,8280a270,7cbd57db,cdee2b06,887a3da7,1d5bc6c5,a39df003) Z8(f43c4f35,39b1a417,7ea7115c,4111ca18,97fa4c19,eed3e8d0,4391fb5c,c64de291) Z8(5d9a5446,c3823d20,25310f76,0254bce6,89a0a329,c8a42948,8fcbd7ee,0bc27e8a) Z8(285c62b1,feea7834,fce882f9,68a22913,27abe10f,3e100040,aed28011,43cdf32b) Z8(35208971,8b00bde2,4f562287,62e61977,095529a8,b2c67dcd,150f30f8,0764699b) },{ Z8(62efed4a,55d9387e,8c14c622,8c591b98,21463246,d317fffb,8f7446d6,60a2476f) Z8(3f121620,6a0714c6,aa6efd2b,ef804980,226aa06b,6e670d15,85ed5130,24387392) Z8(f07e8607,c53088ef,2d173656,ac9137b0,bac63b66,537145d5,1122fd72,3c77d04c) Z8(b8f79cb0,7fa04398,ae00a8bc,3e9cea5d,78557d53,77742a8e,583acdc8,c3831771) Z8(c0186f48,d9e720cd,8187d24b,6e98d06b,f2b79f98,7b259256,6c3a8dfb,a9d5c488) Z8(587d5097,b8f34624,db93947b,b704b541,b105084e,4fd6257d,5f8d20c0,27b21e5f) Z8(c2a50d89,72efb36f,86f04428,2d787c2f,f4a8efa3,cf507845,747a7d69,029a22f9) Z8(d25a9931,8a785631,4c9ed692,aa7dc6e1,08cef331,1bb51ece,ed8aa4ba,2794a522) Z8(b67bff11,c515eb2e,afae91ac,a9b4c4dd,7798b9bc,fd09a602,9ceb2b26,de469963) Z8(bcedbceb,d908c4c5,5d01d3ad,5ce60c54,e4fb5689,4f07e9b1,72ca5e44,895eeaaa) Z8(8a5c7f50,0e370696,dccb0b50,4ae1431f,583d8943,8747770e,cf945c43,3e8770a4) Z8(6a05d1cf,6ee574c1,5cba0c6b,806ecba7,25c682f6,cc4da9e3,238b71f4,477c1c6d) Z8(a9c6160a,4c35ad28,0192c602,c0453095,9aa9efe2,45f82774,5acfc755,be1a90a3) Z8(fac4999f,840947cf,eef0e341,8e48c91d,82b60837,1cdf2664,80cf22ff,ab5874db) Z8(ab845e92,508f74a5,07f63095,4b573425,9a7a2074,bd351766,a8f73d53,0c41f64f) Z8(99facf27,e3de9df4,22b8d3ec,e2a022cd,5ea2d09c,26edce1c,494feb0d,d629cd56) Z8(630346e3,635144e2,378409fc,87012299,a556dc48,d48fc658,82a4441f,a8c1ebd6) Z8(f0a5b553,221ccad4,2d3e91ef,be0fe5f4,167294c9,e10d6380,c3372b02,07a28fb8) }}; flint-3.1.3/src/arb/log_ui.c000066400000000000000000000040751461254215100156160ustar00rootroot00000000000000/* Copyright (C) 2013-2014 Fredrik Johansson Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "arb.h" /* Assumption: p/q <= 2 */ static void atanh_bs(arb_t s, ulong p, ulong q, slong prec) { fmpz_t pp, qq; fmpz_init_set_ui(pp, p); fmpz_init_set_ui(qq, q); arb_atan_frac_bsplit(s, pp, qq, 1, prec); fmpz_clear(pp); fmpz_clear(qq); } static int n_width(ulong k) { int a, b; a = flint_clz(k); b = flint_ctz(k); return FLINT_BITS - a - b; } void arb_log_ui_from_prev(arb_t s, ulong k, arb_t log_prev, ulong prev, slong prec) { if (prev < 2 || prec < 600 || (prec < ARB_LOG_TAB2_PREC - 64 && n_width(k) <= ARB_LOG_TAB21_BITS + 1) || k < prev || (k + prev) < prev || (k - prev) >= 0.25 * (k + prev)) { arf_t t; arf_init_set_ui(t, k); arb_log_arf(s, t, prec); /* no need to clear t */ } else { arb_t t; ulong p, q; arb_init(t); p = k - prev; q = k + prev; if ((p % 2 == 0) && (q % 2 == 0)) { p >>= 1; q >>= 1; } atanh_bs(t, p, q, prec); arb_mul_2exp_si(t, t, 1); arb_add(s, log_prev, t, prec); arb_clear(t); } } void arb_log_ui(arb_t z, ulong x, slong prec) { if (x == 2) { arb_const_log2(z, prec); } else if (x == 10) { arb_const_log10(z, prec); } else { arf_t t; arf_init(t); arf_set_ui(t, x); arb_log_arf(z, t, prec); arf_clear(t); } } void arb_log_fmpz(arb_t z, const fmpz_t x, slong prec) { arf_t t; arf_init(t); arf_set_fmpz(t, x); arb_log_arf(z, t, prec); arf_clear(t); } flint-3.1.3/src/arb/max.c000066400000000000000000000032141461254215100151170ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_max(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t left, right, t, xr, yr; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) { arb_indeterminate(z); return; } if (!arb_is_finite(x) || !arb_is_finite(y)) { if ( (arf_is_pos_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) || (arf_is_pos_inf(arb_midref(y)) && mag_is_finite(arb_radref(y))) ) { arb_pos_inf(z); } else if (!mag_is_finite(arb_radref(x)) || !mag_is_finite(arb_radref(y))) { arb_zero_pm_inf(z); } else if (arf_is_neg_inf(arb_midref(x))) { arb_set(z, y); } else { /* In this case must have y = -inf */ arb_set(z, x); } return; } arf_init(left); arf_init(right); arf_init(t); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); arf_sub(left, arb_midref(x), xr, prec, ARF_RND_FLOOR); arf_sub(t, arb_midref(y), yr, prec, ARF_RND_FLOOR); arf_max(left, left, t); arf_add(right, arb_midref(x), xr, prec, ARF_RND_CEIL); arf_add(t, arb_midref(y), yr, prec, ARF_RND_CEIL); arf_max(right, right, t); arb_set_interval_arf(z, left, right, prec); arf_clear(left); arf_clear(right); arf_clear(t); } flint-3.1.3/src/arb/min.c000066400000000000000000000032221461254215100151140ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_min(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t left, right, t, xr, yr; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) { arb_indeterminate(z); return; } if (!arb_is_finite(x) || !arb_is_finite(y)) { if ( (arf_is_neg_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) || (arf_is_neg_inf(arb_midref(y)) && mag_is_finite(arb_radref(y))) ) { arb_neg_inf(z); } else if (!mag_is_finite(arb_radref(x)) || !mag_is_finite(arb_radref(y))) { arb_zero_pm_inf(z); } else if (arf_is_pos_inf(arb_midref(x))) { arb_set(z, y); } else { /* In this case must have y = +inf */ arb_set(z, x); } return; } arf_init(left); arf_init(right); arf_init(t); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); arf_sub(left, arb_midref(x), xr, prec, ARF_RND_FLOOR); arf_sub(t, arb_midref(y), yr, prec, ARF_RND_FLOOR); arf_min(left, left, t); arf_add(right, arb_midref(x), xr, prec, ARF_RND_CEIL); arf_add(t, arb_midref(y), yr, prec, ARF_RND_CEIL); arf_min(right, right, t); arb_set_interval_arf(z, left, right, prec); arf_clear(left); arf_clear(right); arf_clear(t); } flint-3.1.3/src/arb/minmax.c000066400000000000000000000042621461254215100156270ustar00rootroot00000000000000/* Copyright (C) 2023 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_minmax(arb_t z1, arb_t z2, const arb_t x, const arb_t y, slong prec) { arf_t xleft, xright, yleft, yright, xr, yr; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) { arb_indeterminate(z1); arb_indeterminate(z2); return; } if (!arb_is_finite(x) || !arb_is_finite(y)) { if (z1 != x && z1 != y) { arb_min(z1, x, y, prec); arb_max(z2, x, y, prec); } else { arb_t t; arb_init(t); arb_min(t, x, y, prec); arb_max(z2, x, y, prec); arb_swap(z1, t); arb_clear(t); } return; } arf_init(xleft); arf_init(xright); arf_init(yleft); arf_init(yright); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); arf_sub(xleft, arb_midref(x), xr, prec, ARF_RND_FLOOR); arf_sub(yleft, arb_midref(y), yr, prec, ARF_RND_FLOOR); arf_add(xright, arb_midref(x), xr, prec, ARF_RND_CEIL); arf_add(yright, arb_midref(y), yr, prec, ARF_RND_CEIL); if (arf_cmp(xleft, yleft) < 0) { /* xleft < yleft */ if (arf_cmp(xright, yright) < 0) { /* xright < yright */ arb_set_interval_arf(z1, xleft, xright, prec); arb_set_interval_arf(z2, yleft, yright, prec); } else { /* xright >= yright */ arb_set_interval_arf(z1, xleft, yright, prec); arb_set_interval_arf(z2, yleft, xright, prec); } } else { /* xleft >= yleft */ if (arf_cmp(xright, yright) < 0) { /* xright < yright */ arb_set_interval_arf(z1, yleft, xright, prec); arb_set_interval_arf(z2, xleft, yright, prec); } else { /* xright >= yright */ arb_set_interval_arf(z1, yleft, yright, prec); arb_set_interval_arf(z2, xleft, xright, prec); } } arf_clear(xleft); arf_clear(xright); arf_clear(yleft); arf_clear(yright); } flint-3.1.3/src/arb/mul.c000066400000000000000000000102221461254215100151240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_mul_arf(arb_t z, const arb_t x, const arf_t y, slong prec) { mag_t zr, ym; int inexact; if (arb_is_exact(x)) { inexact = arf_mul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); else mag_zero(arb_radref(z)); } else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(ym, y); mag_init(zr); mag_fast_mul(zr, ym, arb_radref(x)); inexact = arf_mul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec); *arb_radref(z) = *zr; } else if (arf_is_inf(y) && arb_is_nonzero(x)) { mag_zero(arb_radref(z)); if (arf_sgn(arb_midref(x)) * arf_sgn(y) > 0) arf_pos_inf(arb_midref(z)); else arf_neg_inf(arb_midref(z)); } else { mag_init_set_arf(ym, y); mag_init(zr); mag_mul(zr, ym, arb_radref(x)); inexact = arf_mul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec); else mag_swap(arb_radref(z), zr); mag_clear(ym); mag_clear(zr); } } void arb_mul(arb_t z, const arb_t x, const arb_t y, slong prec) { mag_t zr, xm, ym; int inexact; if (arb_is_exact(x)) { arb_mul_arf(z, y, arb_midref(x), prec); } else if (arb_is_exact(y)) { arb_mul_arf(z, x, arb_midref(y), prec); } else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(xm, arb_midref(x)); mag_fast_init_set_arf(ym, arb_midref(y)); mag_init(zr); mag_fast_mul(zr, xm, arb_radref(y)); mag_fast_addmul(zr, ym, arb_radref(x)); mag_fast_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_mul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); if (inexact) arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec); *arb_radref(z) = *zr; } else if ((arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y)) || (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x))) { mag_zero(arb_radref(z)); if (arf_sgn(arb_midref(x)) * arf_sgn(arb_midref(y)) > 0) arf_pos_inf(arb_midref(z)); else arf_neg_inf(arb_midref(z)); } else { mag_init_set_arf(xm, arb_midref(x)); mag_init_set_arf(ym, arb_midref(y)); mag_init(zr); mag_mul(zr, xm, arb_radref(y)); mag_addmul(zr, ym, arb_radref(x)); mag_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_mul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec); else mag_swap(arb_radref(z), zr); mag_clear(xm); mag_clear(ym); mag_clear(zr); } } void arb_mul_si(arb_t z, const arb_t x, slong y, slong prec) { arf_t t; arf_init_set_si(t, y); /* no need to free */ arb_mul_arf(z, x, t, prec); } void arb_mul_ui(arb_t z, const arb_t x, ulong y, slong prec) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ arb_mul_arf(z, x, t, prec); } void arb_mul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) { arf_t t; if (!COEFF_IS_MPZ(*y)) { arf_init_set_si(t, *y); /* no need to free */ arb_mul_arf(z, x, t, prec); } else { arf_init(t); arf_set_fmpz(t, y); arb_mul_arf(z, x, t, prec); arf_clear(t); } } flint-3.1.3/src/arb/mul_2exp_si.c000066400000000000000000000017551461254215100165700ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* mag_mul_2exp_si is non-inline, but avoid overhead here */ static inline void _mag_mul_2exp_si(mag_t z, const mag_t x, slong y) { if (mag_is_special(x)) { mag_set(z, x); } else { if (y >= ADD2_FAST_MIN && y <= ADD2_FAST_MAX) _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(x), y); else fmpz_add_si(MAG_EXPREF(z), MAG_EXPREF(x), y); MAG_MAN(z) = MAG_MAN(x); } } void arb_mul_2exp_si(arb_t y, const arb_t x, slong e) { arf_mul_2exp_si(arb_midref(y), arb_midref(x), e); _mag_mul_2exp_si(arb_radref(y), arb_radref(x), e); } flint-3.1.3/src/arb/neg.c000066400000000000000000000010201461254215100150740ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_neg(arb_t y, const arb_t x) { arf_neg(arb_midref(y), arb_midref(x)); mag_set(arb_radref(y), arb_radref(x)); } flint-3.1.3/src/arb/neg_round.c000066400000000000000000000007761461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_neg_round(arb_t x, const arb_t y, slong prec) { arb_set_round(x, y, prec); arb_neg(x, x); } flint-3.1.3/src/arb/nint.c000066400000000000000000000022641461254215100153060ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_nint(arb_t res, const arb_t x, slong prec) { if (arb_is_int(x)) { arb_set(res, x); } else { arb_t t, u; arb_init(t); arb_init(u); arb_set_d(t, 0.5); arb_add(t, x, t, prec); arb_mul_2exp_si(u, x, 1); arb_sub_ui(u, u, 1, prec); arb_mul_2exp_si(u, u, -2); arb_floor(res, t, prec); /* nint(x) = floor(x+0.5) - isint((2*x-1)/4) */ if (arb_is_int(u)) { arb_sub_ui(res, res, 1, prec); } else if (arb_contains_int(u)) { arf_one(arb_midref(u)); mag_one(arb_radref(u)); arb_mul_2exp_si(u, u, -1); arb_sub_ui(res, res, 1, prec); } arb_clear(t); arb_clear(u); } } flint-3.1.3/src/arb/nonnegative_abs.c000066400000000000000000000023131461254215100174730ustar00rootroot00000000000000/* Copyright (C) 2022 Erik Postma This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_nonnegative_abs(arb_t y, const arb_t x) { if(arb_is_finite(x) && arb_contains_zero(x)) { /* We need to round to MAG_BITS down below, anyway. */ arb_get_abs_ubound_arf(arb_midref(y), x, MAG_BITS+1); /* Now t := arb_midref(y) is the upper bound of the interval x; we need to set arb_midref(y) and arb_radref(y) to (approximations of) t/2. */ arf_mul_2exp_si(arb_midref(y), arb_midref(y), -1); arf_get_mag(arb_radref(y), arb_midref(y)); /* The above is inexact (rounding up), so we need to update arb_midref(y) to match arb_radref(y) again. (That is exact.) */ arf_set_mag(arb_midref(y), arb_radref(y)); } else { arf_abs(arb_midref(y), arb_midref(x)); mag_set(arb_radref(y), arb_radref(x)); } } flint-3.1.3/src/arb/nonnegative_part.c000066400000000000000000000023011461254215100176710ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_nonnegative_part(arb_t res, const arb_t x) { if (!arb_contains_negative(x)) { arb_set(res, x); } else if (!arb_is_finite(x)) { arb_indeterminate(res); } else { arf_t t; arf_init(t); arf_set_mag(t, arb_radref(x)); arf_add(arb_midref(res), arb_midref(x), t, MAG_BITS, ARF_RND_CEIL); if (arf_sgn(arb_midref(res)) <= 0) { arf_zero(arb_midref(res)); mag_zero(arb_radref(res)); } else { arf_mul_2exp_si(arb_midref(res), arb_midref(res), -1); arf_get_mag(arb_radref(res), arb_midref(res)); /* needed since arf_get_mag is inexact */ arf_set_mag(arb_midref(res), arb_radref(res)); } arf_clear(t); } } flint-3.1.3/src/arb/one.c000066400000000000000000000007441461254215100151200ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_one(arb_t f) { arf_one(arb_midref(f)); mag_zero(arb_radref(f)); } flint-3.1.3/src/arb/overlaps.c000066400000000000000000000053211461254215100161660ustar00rootroot00000000000000/* Copyright (C) 2012, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* decide |xm - ym| <= xr + yr */ int arb_overlaps(const arb_t x, const arb_t y) { arf_t t; mag_t a, b; int inexact, result; if (!arb_is_finite(x) || !arb_is_finite(y)) { /* special cases: positive and negative infinity */ if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) { if (mag_is_finite(arb_radref(y)) && (arf_is_finite(arb_midref(y)) || (arf_is_inf(arb_midref(y)) && !arf_equal(arb_midref(x), arb_midref(y))))) return 0; } if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y))) { if (mag_is_finite(arb_radref(x)) && (arf_is_finite(arb_midref(x)) || (arf_is_inf(arb_midref(x)) && !arf_equal(arb_midref(x), arb_midref(y))))) return 0; } return 1; } if (arf_equal(arb_midref(x), arb_midref(y))) return 1; arf_init(t); mag_init(a); mag_init(b); /* t = lower bound for |xm - ym| */ inexact = arf_sub(t, arb_midref(x), arb_midref(y), 2 * MAG_BITS, ARF_RND_DOWN); /* u = lower bound for |xm - ym|; v = upper bound for xr + yr */ arf_get_mag_lower(a, t); mag_add(b, arb_radref(x), arb_radref(y)); if (mag_cmp(a, b) > 0) { result = 0; } else { /* a = upper bound for |xm - ym|; b = lower bound for xr + yr */ arf_get_mag(a, t); if (inexact) { MAG_MAN(a)++; MAG_ADJUST_ONE_TOO_LARGE(a); } mag_add_lower(b, arb_radref(x), arb_radref(y)); if (mag_cmp(a, b) < 0) { result = 1; } else { arf_struct u[4]; if (arf_cmp(arb_midref(x), arb_midref(y)) >= 0) { arf_init_set_shallow(u + 0, arb_midref(x)); arf_init_neg_shallow(u + 1, arb_midref(y)); } else { arf_init_neg_shallow(u + 0, arb_midref(x)); arf_init_set_shallow(u + 1, arb_midref(y)); } arf_init_neg_mag_shallow(u + 2, arb_radref(x)); arf_init_neg_mag_shallow(u + 3, arb_radref(y)); arf_sum(t, u, 4, MAG_BITS, ARF_RND_DOWN); result = arf_sgn(t) <= 0; } } arf_clear(t); mag_clear(a); mag_clear(b); return result; } flint-3.1.3/src/arb/partitions_fmpz.c000066400000000000000000000034761461254215100175740ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "partitions.h" /* defined in flint*/ FLINT_DLL extern const unsigned int partitions_lookup[128]; /* we get log2(p(n))/2 bits with the leading term */ static int use_exact(const fmpz_t n, slong prec) { if (fmpz_size(n) >= 3) return 0; return (prec + 20.0) * (prec + 20.0) > 3.42 * fmpz_get_d(n); } void arb_partitions_fmpz(arb_t res, const fmpz_t n, slong prec) { if (fmpz_cmp_ui(n, 128) < 0) { arb_set_ui(res, fmpz_sgn(n) >= 0 ? partitions_lookup[*n] : 0); arb_set_round(res, res, prec); } else if (use_exact(n, prec)) { fmpz_t t; fmpz_init(t); partitions_fmpz_fmpz(t, n, 0); arb_set_round_fmpz(res, t, prec); fmpz_clear(t); } else { mag_t err; mag_init(err); partitions_leading_fmpz(res, n, prec + 10); /* n >= 128; it is easy to check that the error is bounded by the square root of the leading approximation */ arb_get_mag(err, res); mag_sqrt(err, err); arb_add_error_mag(res, err); arb_set_round(res, res, prec); mag_clear(err); } } void arb_partitions_ui(arb_t res, ulong n, slong prec) { if (n < 128) { arb_set_ui(res, partitions_lookup[n]); arb_set_round(res, res, prec); } else { fmpz_t t; fmpz_init_set_ui(t, n); arb_partitions_fmpz(res, t, prec); fmpz_clear(t); } } flint-3.1.3/src/arb/polylog.c000066400000000000000000000020021461254215100160110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb.h" int polylog_is_real(const acb_t s, const acb_t z); void arb_polylog(arb_t w, const arb_t s, const arb_t z, slong prec) { acb_t ss, zz; acb_init(ss); acb_init(zz); acb_set_arb(ss, s); acb_set_arb(zz, z); if (polylog_is_real(ss, zz)) { acb_polylog(zz, ss, zz, prec); arb_set(w, acb_realref(zz)); } else { arb_indeterminate(w); } acb_clear(ss); acb_clear(zz); } void arb_polylog_si(arb_t w, slong s, const arb_t z, slong prec) { arb_t t; arb_init(t); arb_set_si(t, s); arb_polylog(w, t, z, prec); arb_clear(t); } flint-3.1.3/src/arb/pow.c000066400000000000000000000103531461254215100151410ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #define BINEXP_LIMIT 64 typedef enum {POSITIVE = 0, NEGATIVE_EVEN, NEGATIVE_ODD} sign_type; void _arb_pow_exp(arb_t z, const arb_t x, sign_type negx, const arb_t y, slong prec) { arb_t t; arb_init(t); if (negx == POSITIVE) arb_log(t, x, prec); else { arb_neg(t, x); arb_log(t, t, prec); } arb_mul(t, t, y, prec); arb_exp(z, t, prec); if (negx == NEGATIVE_ODD) arb_neg(z, z); arb_clear(t); } void arb_pow(arb_t z, const arb_t x, const arb_t y, slong prec) { sign_type s; if (arb_is_zero(y)) { arb_one(z); return; } if (arb_is_zero(x)) { if (arb_is_positive(y)) arb_zero(z); else arb_indeterminate(z); return; } s = POSITIVE; if (arb_is_exact(y) && !arf_is_special(arb_midref(x))) { const arf_struct * ymid = arb_midref(y); /* small half-integer or integer */ if (arf_cmpabs_2exp_si(ymid, BINEXP_LIMIT) < 0 && arf_is_int_2exp_si(ymid, -1)) { fmpz_t e; fmpz_init(e); if (arf_is_int(ymid)) { arf_get_fmpz_fixed_si(e, ymid, 0); arb_pow_fmpz_binexp(z, x, e, prec); } else { arf_get_fmpz_fixed_si(e, ymid, -1); if (fmpz_sgn(e) >= 0) { arb_sqrt(z, x, prec + fmpz_bits(e)); arb_pow_fmpz_binexp(z, z, e, prec); } else { fmpz_neg(e, e); arb_rsqrt(z, x, prec + fmpz_bits(e)); arb_pow_fmpz_binexp(z, z, e, prec); } } fmpz_clear(e); return; } else if (arf_is_int(ymid) && arf_sgn(arb_midref(x)) < 0) /* use (-x)^n = (-1)^n * x^n to avoid NaNs at least at high enough precision */ s = arf_is_int_2exp_si(ymid, 1) ? NEGATIVE_EVEN : NEGATIVE_ODD; /* Fallthrough */ } if (arf_cmp_si(arb_midref(x), 0) > 0 && arf_cmpabs_mag(arb_midref(x), arb_radref(x)) == 0 && arb_is_nonnegative(y)) { /* x is an interval of the form , y is an interval of the form with b >= c. (x, y) -> x^y is nondecreasing in x for y >= 0, and it is 0 for x=0 and y>0. The lower bound of the interval for x is 0, and we have points with y>0 (because the case arb_is_zero(y) is excluded above). So the lowerbound of the result is 0, and the upperbound can be found somewhere at (2*a)^y. We compute this upperbound by computing z^y with z = <3*a/2 +- a/2>, which has the same upperbound (2*a) as x, then keeping the upper bound of this result and setting the lower bound to 0. This necessarily drops the precision to MAG_BITS, so we might as well do that from the start. */ prec = (prec > MAG_BITS) ? MAG_BITS : prec; arf_mul_ui(arb_midref(z), arb_midref(x), 3, prec, ARF_RND_UP); arf_mul_2exp_si(arb_midref(z), arb_midref(z), -1); mag_mul_2exp_si(arb_radref(z), arb_radref(x), -1); arb_pow(z, z, y, prec); /* Now we keep the upper bound of z (we may need to round up) and set the lower bound to zero. That is, if currently, z = , we set it to <(zc + zr)/2 +/- (zc + zr)/2>. */ arb_get_ubound_arf(arb_midref(z), z, prec); arf_mul_2exp_si(arb_midref(z), arb_midref(z), -1); arf_get_mag(arb_radref(z), arb_midref(z)); /* Note the above is inexact (rounding up), so need to update arb_midref(z) to match again */ arf_set_mag(arb_midref(z), arb_radref(z)); return; } _arb_pow_exp(z, x, s, y, prec); } flint-3.1.3/src/arb/pow_fmpq.c000066400000000000000000000022601461254215100161620ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_pow_fmpq(arb_t y, const arb_t x, const fmpq_t a, slong prec) { if (fmpz_is_one(fmpq_denref(a))) { arb_pow_fmpz(y, x, fmpq_numref(a), prec); } else { int use_exp; slong k = *fmpq_denref(a); if (k == 2 || k == 4) use_exp = 0; else if (k > 1 && k < 50) use_exp = prec < (WORD(1) << ((k / 8) + 8)); else use_exp = 1; if (use_exp) { arb_log(y, x, prec + 10); arb_mul_fmpz(y, y, fmpq_numref(a), prec + 10); arb_div_fmpz(y, y, fmpq_denref(a), prec + 10); arb_exp(y, y, prec); } else { arb_root_ui(y, x, k, prec); arb_pow_fmpz(y, y, fmpq_numref(a), prec); } } } flint-3.1.3/src/arb/pow_fmpz.c000066400000000000000000000012511461254215100161720ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_pow_fmpz(arb_t y, const arb_t b, const fmpz_t e, slong prec) { arb_pow_fmpz_binexp(y, b, e, prec); } void arb_pow_ui(arb_t y, const arb_t b, ulong e, slong prec) { fmpz_t f; fmpz_init_set_ui(f, e); arb_pow_fmpz(y, b, f, prec); fmpz_clear(f); } flint-3.1.3/src/arb/pow_fmpz_binexp.c000066400000000000000000000033221461254215100175400ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_pow_fmpz_binexp(arb_t y, const arb_t b, const fmpz_t e, slong prec) { slong i, wp, bits; if (-WORD(2) <= *e && *e <= WORD(2)) { if (*e == WORD(0)) arb_one(y); else if (*e == WORD(1)) arb_set_round(y, b, prec); else if (*e == -WORD(1)) arb_inv(y, b, prec); else if (*e == WORD(2)) arb_mul(y, b, b, prec); else { arb_inv(y, b, prec); arb_mul(y, y, y, prec); } return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); if (arb_is_exact(b)) { arb_pow_fmpz_binexp(y, b, f, prec + 2); arb_inv(y, y, prec); } else { arb_inv(y, b, prec + fmpz_bits(e) + 2); arb_pow_fmpz_binexp(y, y, f, prec); } fmpz_clear(f); return; } if (y == b) { arb_t t; arb_init(t); arb_set(t, b); arb_pow_fmpz_binexp(y, t, e, prec); arb_clear(t); return; } arb_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { arb_mul(y, y, y, wp); if (fmpz_tstbit(e, i)) arb_mul(y, y, b, wp); } } flint-3.1.3/src/arb/power_sum_vec.c000066400000000000000000000030011461254215100172010ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "bernoulli.h" #include "arb_poly.h" /* todo: don't use exact bernoulli numbers for large len */ /* todo: output exact integers when precise enough */ void arb_power_sum_vec(arb_ptr res, const arb_t a, const arb_t b, slong len, slong prec) { arb_ptr t, u, v; slong k; if (len < 1) return; t = _arb_vec_init(len + 1); u = _arb_vec_init(len + 1); v = _arb_vec_init(len + 1); /* exp(ax), exp(bx) */ arb_set(t + 1, a); arb_set(u + 1, b); _arb_poly_exp_series(t, t, 2, len + 1, prec); _arb_poly_exp_series(u, u, 2, len + 1, prec); _arb_vec_sub(t, u, t, len + 1, prec); /* x/(exp(x)-1) */ BERNOULLI_ENSURE_CACHED(len + 1); for (k = 0; k <= len; k++) arb_set_fmpq(u + k, bernoulli_cache + k, prec); _arb_poly_borel_transform(u, u, len + 1, prec); _arb_poly_mullow(v, t, len + 1, u, len + 1, len + 1, prec); _arb_poly_inv_borel_transform(v, v, len + 1, prec); for (k = 0; k < len; k++) arb_div_ui(res + k, v + k + 1, k + 1, prec); _arb_vec_clear(t, len + 1); _arb_vec_clear(u, len + 1); _arb_vec_clear(v, len + 1); } flint-3.1.3/src/arb/primorial.c000066400000000000000000000076311461254215100163370ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb.h" #define NUM_BASECASE 30 static int basecase(arb_t res, n_primes_t primes, ulong a, ulong b, ulong nmax, slong prec) { ulong n, p, pp; mp_limb_t prod[NUM_BASECASE]; mp_limb_t top; mp_size_t nlimbs; mp_limb_t hi, lo; int inexact, more; slong shift; nlimbs = 0; pp = 1; more = 1; for (n = a; n < b; n++) { p = n_primes_next(primes); if (p > nmax) { more = 0; break; } umul_ppmm(hi, lo, pp, p); if (hi != 0) { if (nlimbs == 0) { prod[0] = lo; prod[1] = hi; pp = 1; nlimbs = 2; } else { prod[nlimbs] = top = mpn_mul_1(prod, prod, nlimbs, pp); nlimbs += (top != 0); pp = p; } } else { pp = lo; } } if (nlimbs == 0) { arb_set_ui(res, pp); arb_set_round(res, res, prec); return more; } if (pp != 1) { prod[nlimbs] = top = mpn_mul_1(prod, prod, nlimbs, pp); nlimbs += (top != 0); } inexact = _arf_set_round_mpn(arb_midref(res), &shift, prod, nlimbs, 0, prec, ARB_RND); fmpz_set_si(ARF_EXPREF(arb_midref(res)), nlimbs * FLINT_BITS + shift); if (inexact) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec); else mag_zero(arb_radref(res)); return more; } static int bsplit(arb_t res, n_primes_t primes, ulong a, ulong b, ulong nmax, slong prec) { if (b - a < NUM_BASECASE) { return basecase(res, primes, a, b, nmax, prec); } else { int more; more = bsplit(res, primes, a, a + (b - a) / 2, nmax, prec + 3); if (more) { arb_t t; arb_init(t); more = bsplit(t, primes, a + (b - a) / 2, b, nmax, prec + 3); arb_mul(res, res, t, prec); arb_clear(t); } else { arb_set_round(res, res, prec); } return more; } } void arb_primorial_nth_ui(arb_t res, ulong n, slong prec) { if (n < 10) { const unsigned int tab[] = { 1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690, 223092870 }; arb_set_ui(res, tab[n]); arb_set_round(res, res, prec); } else if (FLINT_BITS == 32 && n >= 203280220) { arb_indeterminate(res); /* p_n will not fit a ulong */ } else { n_primes_t primes; n_primes_init(primes); bsplit(res, primes, 0, n, UWORD_MAX, prec); n_primes_clear(primes); } } void arb_primorial_ui(arb_t res, ulong n, slong prec) { if (n < 17) { const unsigned short tab[] = { 1, 1, 2, 6, 6, 30, 30, 210, 210, 210, 210, 2310, 2310, 30030, 30030, 30030, 30030 }; arb_set_ui(res, tab[n]); arb_set_round(res, res, prec); } else if (n >= UWORD_MAX / 2) { /* avoid potential slong/ulong issues and overflow in the multiply by two below. in any case, this would be quite big on 64-bit... */ arb_indeterminate(res); } else { n_primes_t primes; n_primes_init(primes); /* crude upper bound for pi(n) just to balance the binary splitting; we stop the prime iterator at the actual correct count */ bsplit(res, primes, 0, 2 * n / FLINT_BIT_COUNT(n) + 1, n, prec); n_primes_clear(primes); } } flint-3.1.3/src/arb/randtest.c000066400000000000000000000047231461254215100161640ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_randtest_exact(arb_t x, flint_rand_t state, slong prec, slong mag_bits) { arf_randtest(arb_midref(x), state, prec, mag_bits); mag_zero(arb_radref(x)); } void arb_randtest_wide(arb_t x, flint_rand_t state, slong prec, slong mag_bits) { arf_randtest(arb_midref(x), state, prec, mag_bits); mag_randtest(arb_radref(x), state, mag_bits); } void arb_randtest_precise(arb_t x, flint_rand_t state, slong prec, slong mag_bits) { arf_randtest(arb_midref(x), state, prec, mag_bits); if (arf_is_zero(arb_midref(x)) || (n_randint(state, 8) == 0)) { mag_zero(arb_radref(x)); } else { mag_randtest(arb_radref(x), state, 0); if (!mag_is_zero(arb_radref(x))) { fmpz_add_si(MAG_EXPREF(arb_radref(x)), ARF_EXPREF(arb_midref(x)), -prec + 2 - n_randint(state, 8)); } } } void arb_randtest_positive(arb_t x, flint_rand_t state, slong prec, slong mag_bits) { int stop = 0; while (!stop) { arb_randtest_precise(x, state, prec, mag_bits); stop = !arb_contains_zero(x); } if (!arb_is_positive(x)) { arb_neg(x, x); } } void arb_randtest(arb_t x, flint_rand_t state, slong prec, slong mag_bits) { switch (n_randint(state, 8)) { case 0: arb_randtest_exact(x, state, prec, mag_bits); break; case 1: arb_randtest_wide(x, state, prec, mag_bits); break; default: arb_randtest_precise(x, state, prec, mag_bits); } } void arb_randtest_special(arb_t x, flint_rand_t state, slong prec, slong mag_bits) { arb_randtest(x, state, prec, mag_bits); if (n_randint(state, 10) == 0) mag_inf(arb_radref(x)); switch (n_randint(state, 10)) { case 0: arf_pos_inf(arb_midref(x)); break; case 1: arf_neg_inf(arb_midref(x)); break; case 2: arf_nan(arb_midref(x)); mag_inf(arb_radref(x)); break; default: break; } } flint-3.1.3/src/arb/rel_error_bits.c000066400000000000000000000030541461254215100173500ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" slong arb_rel_error_bits(const arb_t x) { fmpz_t t; slong result; /* fast path for small exponents */ if (ARB_IS_LAGOM(x)) { if (mag_is_zero(arb_radref(x))) return -ARF_PREC_EXACT; else if (arf_is_special(arb_midref(x))) return ARF_PREC_EXACT; else return MAG_EXP(arb_radref(x)) + 1 - ARF_EXP(arb_midref(x)); } if (mag_is_zero(arb_radref(x))) { if (arf_is_nan(arb_midref(x))) return ARF_PREC_EXACT; else return -ARF_PREC_EXACT; } if (arf_is_special(arb_midref(x)) || mag_is_inf(arb_radref(x))) return ARF_PREC_EXACT; fmpz_init(t); fmpz_add_ui(t, MAG_EXPREF(arb_radref(x)), 1); result = _fmpz_sub_small(t, ARF_EXPREF(arb_midref(x))); fmpz_clear(t); return result; } slong arb_rel_one_accuracy_bits(const arb_t x) { if (arf_cmpabs_2exp_si(arb_midref(x), -1) < 0) { arb_t t; arf_init(arb_midref(t)); arf_one(arb_midref(t)); *arb_radref(t) = *arb_radref(x); return arb_rel_accuracy_bits(t); } else { return arb_rel_accuracy_bits(x); } } flint-3.1.3/src/arb/richcmp.c000066400000000000000000000141721461254215100157640ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" int arb_eq(const arb_t x, const arb_t y) { if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) return 0; if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y))) return 0; if (arf_is_inf(arb_midref(x)) || arf_is_inf(arb_midref(y)) || (mag_is_zero(arb_radref(x)) && mag_is_zero(arb_radref(y)))) return arf_equal(arb_midref(x), arb_midref(y)); return 0; } int arb_ne(const arb_t x, const arb_t y) { if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) return 0; if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y))) return 0; if (arf_is_inf(arb_midref(x)) || arf_is_inf(arb_midref(y)) || (mag_is_zero(arb_radref(x)) && mag_is_zero(arb_radref(y)))) return !arf_equal(arb_midref(x), arb_midref(y)); return !arb_overlaps(x, y); } int arb_lt(const arb_t x, const arb_t y) { if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) return 0; if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y))) return 0; if (arf_is_inf(arb_midref(x)) || arf_is_inf(arb_midref(y)) || (mag_is_zero(arb_radref(x)) && mag_is_zero(arb_radref(y)))) return arf_cmp(arb_midref(x), arb_midref(y)) < 0; if (arb_overlaps(x, y)) return 0; return arf_cmp(arb_midref(x), arb_midref(y)) < 0; } int arb_le(const arb_t x, const arb_t y) { arf_struct u[4]; arf_t t; int res; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) return 0; if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y))) return (arf_is_neg_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) || (arf_is_pos_inf(arb_midref(y)) && mag_is_finite(arb_radref(y))); if (arf_is_inf(arb_midref(x)) || arf_is_inf(arb_midref(y)) || (mag_is_zero(arb_radref(x)) && mag_is_zero(arb_radref(y)))) return arf_cmp(arb_midref(x), arb_midref(y)) <= 0; if (!arb_overlaps(x, y)) return arf_cmp(arb_midref(x), arb_midref(y)) < 0; /* need to check for the case where a single point overlaps */ /* todo: optimize this */ /* xm + xr <= ym - yr <=> xm + xr - ym + yr <= 0 */ arf_init_set_shallow(u + 0, arb_midref(x)); arf_init_neg_shallow(u + 1, arb_midref(y)); arf_init_set_mag_shallow(u + 2, arb_radref(x)); arf_init_set_mag_shallow(u + 3, arb_radref(y)); arf_init(t); arf_sum(t, u, 4, MAG_BITS, ARF_RND_DOWN); res = (arf_sgn(t) <= 0); arf_clear(t); return res; } int arb_gt(const arb_t x, const arb_t y) { if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) return 0; if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y))) return 0; if (arf_is_inf(arb_midref(x)) || arf_is_inf(arb_midref(y)) || (mag_is_zero(arb_radref(x)) && mag_is_zero(arb_radref(y)))) return arf_cmp(arb_midref(x), arb_midref(y)) > 0; if (arb_overlaps(x, y)) return 0; return arf_cmp(arb_midref(x), arb_midref(y)) > 0; } int arb_ge(const arb_t x, const arb_t y) { arf_struct u[4]; arf_t t; int res; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) return 0; if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y))) return (arf_is_pos_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) || (arf_is_neg_inf(arb_midref(y)) && mag_is_finite(arb_radref(y))); if (arf_is_inf(arb_midref(x)) || arf_is_inf(arb_midref(y)) || (mag_is_zero(arb_radref(x)) && mag_is_zero(arb_radref(y)))) return arf_cmp(arb_midref(x), arb_midref(y)) >= 0; if (!arb_overlaps(x, y)) return arf_cmp(arb_midref(x), arb_midref(y)) > 0; /* need to check for the case where a single point overlaps */ /* todo: optimize this */ /* xm - xr >= ym + yr <=> xm - xr - ym - yr >= 0 */ arf_init_set_shallow(u + 0, arb_midref(x)); arf_init_neg_shallow(u + 1, arb_midref(y)); arf_init_neg_mag_shallow(u + 2, arb_radref(x)); arf_init_neg_mag_shallow(u + 3, arb_radref(y)); arf_init(t); arf_sum(t, u, 4, MAG_BITS, ARF_RND_DOWN); res = (arf_sgn(t) >= 0); arf_clear(t); return res; } int arb_contains_zero(const arb_t x) { return arf_cmpabs_mag(arb_midref(x), arb_radref(x)) <= 0; } int arb_is_nonzero(const arb_t x) { return !arb_contains_zero(x); } int arb_is_positive(const arb_t x) { return (arf_sgn(arb_midref(x)) > 0) && (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) < 0) && !arf_is_nan(arb_midref(x)); } int arb_is_nonnegative(const arb_t x) { return (arf_sgn(arb_midref(x)) >= 0) && (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) <= 0) && !arf_is_nan(arb_midref(x)); } int arb_is_negative(const arb_t x) { return (arf_sgn(arb_midref(x)) < 0) && (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) < 0) && !arf_is_nan(arb_midref(x)); } int arb_is_nonpositive(const arb_t x) { return (arf_sgn(arb_midref(x)) <= 0) && (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) <= 0) && !arf_is_nan(arb_midref(x)); } int arb_contains_negative(const arb_t x) { return (arf_sgn(arb_midref(x)) < 0) || (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) > 0) || arf_is_nan(arb_midref(x)); } int arb_contains_nonpositive(const arb_t x) { return (arf_sgn(arb_midref(x)) <= 0) || (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) >= 0) || arf_is_nan(arb_midref(x)); } int arb_contains_positive(const arb_t x) { return (arf_sgn(arb_midref(x)) > 0) || (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) > 0) || arf_is_nan(arb_midref(x)); } int arb_contains_nonnegative(const arb_t x) { return (arf_sgn(arb_midref(x)) >= 0) || (arf_mag_cmpabs(arb_radref(x), arb_midref(x)) >= 0) || arf_is_nan(arb_midref(x)); } flint-3.1.3/src/arb/rising2_ui.c000066400000000000000000000015311461254215100164040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "arb_hypgeom.h" void arb_rising2_ui(arb_t u, arb_t v, const arb_t x, ulong n, slong prec) { if (x == u || x == v) { arb_t t; arb_init(t); arb_set(t, x); arb_rising2_ui(u, v, t, n, prec); arb_clear(t); } else { arb_struct tmp[2]; tmp[0] = *u; tmp[1] = *v; arb_hypgeom_rising_ui_jet(tmp, x, n, 2, prec); *u = tmp[0]; *v = tmp[1]; } } flint-3.1.3/src/arb/rising_fmpq_ui.c000066400000000000000000000034001461254215100173420ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void bsplit(arb_t y, const fmpz_t p, const fmpz_t q, ulong a, ulong b, slong prec) { if (b - a <= 8) { fmpz_t t, u; ulong c; fmpz_init(t); fmpz_init(u); fmpz_mul_ui(t, q, a); fmpz_add(t, t, p); fmpz_set(u, t); for (c = a + 1; c < b; c++) { fmpz_add(u, u, q); fmpz_mul(t, t, u); } arb_set_round_fmpz(y, t, prec); fmpz_clear(t); fmpz_clear(u); } else { arb_t w; ulong m = a + (b - a) / 2; arb_init(w); bsplit(y, p, q, a, m, prec); bsplit(w, p, q, m, b, prec); arb_mul(y, y, w, prec); arb_clear(w); } } void arb_rising_fmpq_ui(arb_t y, const fmpq_t x, ulong n, slong prec) { if (n == 0) { arb_one(y); } else if (n == 1) { arb_set_fmpq(y, x, prec); } else { slong wp; wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); bsplit(y, fmpq_numref(x), fmpq_denref(x), 0, n, wp); if (fmpz_is_one(fmpq_denref(x))) { arb_set_round(y, y, prec); } else { arb_t t; arb_init(t); arb_set_fmpz(t, fmpq_denref(x)); arb_pow_ui(t, t, n, wp); arb_div(y, y, t, prec); arb_clear(t); } } } flint-3.1.3/src/arb/rising_ui.c000066400000000000000000000012071461254215100163220ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "arb_hypgeom.h" void arb_rising_ui(arb_t y, const arb_t x, ulong n, slong prec) { arb_hypgeom_rising_ui(y, x, n, prec); } void arb_rising(arb_t y, const arb_t x, const arb_t n, slong prec) { arb_hypgeom_rising(y, x, n, prec); } flint-3.1.3/src/arb/root_ui.c000066400000000000000000000046461461254215100160240ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void arb_root_arf(arb_t z, const arf_t x, ulong k, slong prec) { int inexact = arf_root(arb_midref(z), x, k, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); else mag_zero(arb_radref(z)); } void arb_root_ui_algebraic(arb_t res, const arb_t x, ulong k, slong prec) { mag_t r, msubr, m1k, t; if (arb_is_exact(x)) { arb_root_arf(res, arb_midref(x), k, prec); return; } if (!arb_is_nonnegative(x)) { arb_indeterminate(res); return; } mag_init(r); mag_init(msubr); mag_init(m1k); mag_init(t); /* x = [m-r, m+r] */ mag_set(r, arb_radref(x)); /* m - r */ arb_get_mag_lower(msubr, x); /* m^(1/k) */ arb_root_arf(res, arb_midref(x), k, prec); /* bound for m^(1/k) */ arb_get_mag(m1k, res); /* C = min(1, log(1+r/(m-r))/k) */ mag_div(t, r, msubr); mag_log1p(t, t); mag_div_ui(t, t, k); if (mag_cmp_2exp_si(t, 0) > 0) mag_one(t); /* C m^(1/k) */ mag_mul(t, m1k, t); mag_add(arb_radref(res), arb_radref(res), t); mag_clear(r); mag_clear(msubr); mag_clear(m1k); mag_clear(t); } void arb_root_ui_exp(arb_t res, const arb_t x, ulong k, slong prec) { arb_log(res, x, prec + 4); arb_div_ui(res, res, k, prec + 4); arb_exp(res, res, prec); } void arb_root_ui(arb_t res, const arb_t x, ulong k, slong prec) { if (k == 0) { arb_indeterminate(res); } else if (k == 1) { arb_set_round(res, x, prec); } else if (k == 2) { arb_sqrt(res, x, prec); } else if (k == 4) { arb_sqrt(res, x, prec + 2); arb_sqrt(res, res, prec); } else { if (k > 50 || prec < (WORD(1) << ((k / 8) + 8))) arb_root_ui_exp(res, x, k, prec); else arb_root_ui_algebraic(res, x, k, prec); } } /* backwards compatible alias */ void arb_root(arb_t res, const arb_t x, ulong k, slong prec) { arb_root_ui(res, x, k, prec); } flint-3.1.3/src/arb/sec.c000066400000000000000000000010041461254215100150770ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sec(arb_t res, const arb_t x, slong prec) { arb_cos(res, x, prec + 4); arb_inv(res, res, prec); } flint-3.1.3/src/arb/sech.c000066400000000000000000000017741461254215100152650ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sech(arb_t res, const arb_t x, slong prec) { if (arf_cmpabs_2exp_si(arb_midref(x), 0) > 0) { arb_t t; arb_init(t); if (arf_sgn(arb_midref(x)) > 0) { arb_neg(t, x); arb_exp(t, t, prec + 4); } else { arb_exp(t, x, prec + 4); } arb_mul(res, t, t, prec + 4); arb_add_ui(res, res, 1, prec + 4); arb_div(res, t, res, prec); arb_mul_2exp_si(res, res, 1); arb_clear(t); } else { arb_cosh(res, x, prec + 4); arb_inv(res, res, prec); } } flint-3.1.3/src/arb/set.c000066400000000000000000000030761461254215100151330ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static inline void _arf_set_inline(arf_t y, const arf_t x) { /* Fast path */ if (!COEFF_IS_MPZ(ARF_EXP(x)) && !COEFF_IS_MPZ(ARF_EXP(y))) ARF_EXP(y) = ARF_EXP(x); else fmpz_set(ARF_EXPREF(y), ARF_EXPREF(x)); /* Fast path */ if (!ARF_HAS_PTR(x)) { ARF_DEMOTE(y); (y)->d = (x)->d; } else { mp_ptr yptr; mp_srcptr xptr; mp_size_t n; ARF_GET_MPN_READONLY(xptr, n, x); ARF_GET_MPN_WRITE(yptr, n, y); flint_mpn_copyi(yptr, xptr, n); } /* Important. */ ARF_XSIZE(y) = ARF_XSIZE(x); } void arb_set(arb_t x, const arb_t y) { if (x != y) { _arf_set_inline(arb_midref(x), arb_midref(y)); mag_set(arb_radref(x), arb_radref(y)); } } void arb_set_d(arb_t x, double y) { arf_set_d(arb_midref(x), y); mag_zero(arb_radref(x)); } void arb_set_fmpz(arb_t x, const fmpz_t y) { arf_set_fmpz(arb_midref(x), y); mag_zero(arb_radref(x)); } void arb_set_si(arb_t x, slong y) { arf_set_si(arb_midref(x), y); mag_zero(arb_radref(x)); } void arb_set_ui(arb_t x, ulong y) { arf_set_ui(arb_midref(x), y); mag_zero(arb_radref(x)); } flint-3.1.3/src/arb/set_interval.c000066400000000000000000000153511461254215100170360ustar00rootroot00000000000000/* Copyright (C) 2013, 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb.h" void arb_set_interval_arf(arb_t x, const arf_t a, const arf_t b, slong prec) { arf_t t; int inexact; /* [-inf, -inf] or [+inf, +inf] */ if (arf_is_inf(a) && arf_equal(a, b)) { arf_set(arb_midref(x), a); mag_zero(arb_radref(x)); return; } /* any nan -> [nan +/- inf] */ if (arf_is_nan(a) || arf_is_nan(b)) { arb_indeterminate(x); return; } /* [-inf, x] or [x, +inf] = [+/- inf] */ if (arf_is_neg_inf(a) || arf_is_pos_inf(b)) { arf_zero(arb_midref(x)); mag_inf(arb_radref(x)); return; } /* [(a + b) +/- (b - a)] / 2 */ arf_init(t); arf_sub(t, b, a, MAG_BITS, ARF_RND_UP); if (arf_sgn(t) < 0) { flint_throw(FLINT_ERROR, "exception: arb_set_interval_arf: endpoints not ordered\n"); } arf_get_mag(arb_radref(x), t); inexact = arf_add(arb_midref(x), a, b, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(x), arb_radref(x), arb_midref(x), prec); arb_mul_2exp_si(x, x, -1); arf_clear(t); } void arb_set_interval_mag(arb_t res, const mag_t a, const mag_t b, slong prec) { if (MAG_IS_LAGOM(a) && MAG_IS_LAGOM(b)) { slong aexp, bexp; mp_limb_t aman, bman, mman, rman, tmp; aman = MAG_MAN(a); bman = MAG_MAN(b); aexp = MAG_EXP(a); bexp = MAG_EXP(b); if (aman == 0 && bman == 0) { arb_zero(res); return; } if (bman == 0 || (aman != 0 && (aexp > bexp || (aexp == bexp && aman > bman)))) { flint_throw(FLINT_ERROR, "exception: arb_set_interval_mag: endpoints not ordered\n"); } /* now a = 0 or bexp >= aexp */ if (aman == 0 || bexp - aexp > MAG_BITS) { mman = bman; /* midpoint a+b */ rman = bman + (aman != 0); /* radius b-a */ } else { tmp = (aman >> (bexp - aexp)); mman = bman + tmp; /* midpoint a+b */ rman = bman - tmp; /* radius b-a */ rman += ((tmp << (bexp - aexp)) != aman); /* rounding error */ } arf_set_ui(arb_midref(res), mman); /* m can't be zero */ ARF_EXP(arb_midref(res)) += bexp - MAG_BITS - 1; mag_set_ui(arb_radref(res), rman); if (rman != 0) /* r can be zero */ MAG_EXP(arb_radref(res)) += bexp - MAG_BITS - 1; arb_set_round(res, res, prec); } else { int inexact; arf_t aa, bb; if (mag_cmp(a, b) > 0) { flint_throw(FLINT_ERROR, "exception: arb_set_interval_mag: endpoints not ordered\n"); } if (mag_is_inf(a)) { arb_pos_inf(res); return; } if (mag_is_inf(b)) { arb_zero_pm_inf(res); return; } arf_init_set_mag_shallow(aa, a); arf_init_set_mag_shallow(bb, b); inexact = arf_add(arb_midref(res), aa, bb, prec, ARB_RND); mag_sub(arb_radref(res), b, a); if (inexact) arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec); arb_mul_2exp_si(res, res, -1); } } void arb_set_interval_mpfr(arb_t x, const mpfr_t a, const mpfr_t b, slong prec) { arf_t aa, bb; arf_init(aa); arf_init(bb); arf_set_mpfr(aa, a); arf_set_mpfr(bb, b); arb_set_interval_arf(x, aa, bb, prec); arf_clear(aa); arf_clear(bb); } void arb_set_interval_neg_pos_mag(arb_t res, const mag_t a, const mag_t b, slong prec) { if (MAG_IS_LAGOM(a) && MAG_IS_LAGOM(b)) { slong aexp, bexp, mexp, shift; mp_limb_t aman, bman, mman, rman, tmp; int negative; aman = MAG_MAN(a); bman = MAG_MAN(b); aexp = MAG_EXP(a); bexp = MAG_EXP(b); if (aman == 0) { if (bman == 0) { arb_zero(res); return; } negative = 0; mexp = bexp; mman = bman; rman = bman; } else if (bman == 0) { negative = 1; mexp = aexp; mman = aman; rman = aman; } else if (aexp == bexp) { mexp = aexp; negative = aman >= bman; if (negative) mman = aman - bman; else mman = bman - aman; rman = aman + bman; } else if (aexp > bexp) { negative = 1; mexp = aexp; shift = aexp - bexp; if (shift > MAG_BITS) { mman = aman; rman = aman + 2; } else { tmp = bman >> shift; mman = aman - tmp; rman = aman + tmp; rman += 2 * ((tmp << shift) != bman); } } else { negative = 0; mexp = bexp; shift = bexp - aexp; if (shift > MAG_BITS) { mman = bman; rman = bman + 2; } else { tmp = aman >> shift; mman = bman - tmp; rman = bman + tmp; rman += 2 * ((tmp << shift) != aman); } } arf_set_ui(arb_midref(res), mman); if (negative) arf_neg(arb_midref(res), arb_midref(res)); if (mman != 0) ARF_EXP(arb_midref(res)) += mexp - MAG_BITS - 1; mag_set_ui(arb_radref(res), rman); /* r can't be zero */ MAG_EXP(arb_radref(res)) += mexp - MAG_BITS - 1; arb_set_round(res, res, prec); } else { arf_t aa, bb; int inexact; if (mag_is_inf(a) || mag_is_inf(b)) { arb_zero_pm_inf(res); return; } arf_init_set_mag_shallow(aa, a); arf_init_set_mag_shallow(bb, b); inexact = arf_sub(arb_midref(res), bb, aa, prec, ARB_RND); mag_add(arb_radref(res), b, a); if (inexact) arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec); arb_mul_2exp_si(res, res, -1); } } flint-3.1.3/src/arb/set_round.c000066400000000000000000000024021461254215100163320ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_set_round(arb_t z, const arb_t x, slong prec) { int inexact; inexact = arf_set_round(arb_midref(z), arb_midref(x), prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_set_round_fmpz_2exp(arb_t y, const fmpz_t x, const fmpz_t exp, slong prec) { int inexact; inexact = arf_set_round_fmpz_2exp(arb_midref(y), x, exp, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(y), arb_midref(y), prec); else mag_zero(arb_radref(y)); } void arb_set_round_fmpz(arb_t y, const fmpz_t x, slong prec) { int inexact; inexact = arf_set_round_fmpz(arb_midref(y), x, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(y), arb_midref(y), prec); else mag_zero(arb_radref(y)); } flint-3.1.3/src/arb/set_str.c000066400000000000000000000122511461254215100160160ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "arb.h" static int arb_set_float_str(arb_t res, const char * inp, slong prec) { char * emarker; char * buf; int error; slong i; fmpz_t exp; fmpz_t man; slong num_int, num_frac; int after_radix; if (inp[0] == '+') { return arb_set_float_str(res, inp + 1, prec); } if (inp[0] == '-') { error = arb_set_float_str(res, inp + 1, prec); arb_neg(res, res); return error; } if (strcmp(inp, "inf") == 0) { arb_pos_inf(res); return 0; } if (strcmp(inp, "nan") == 0) { arb_indeterminate(res); return 0; } error = 0; fmpz_init(exp); fmpz_init(man); buf = flint_malloc(strlen(inp) + 1); emarker = strchr(inp, 'e'); /* parse exponent (0 by default) */ if (emarker != NULL) { /* allow e+42 as well as e42 */ if (emarker[1] == '+') { if (!(emarker[2] >= '0' && emarker[2] <= '9')) error = 1; else error = fmpz_set_str(exp, emarker + 2, 10); } else { if (emarker[1] == '-' && !(emarker[2] >= '0' && emarker[2] <= '9')) error = 1; else error = fmpz_set_str(exp, emarker + 1, 10); } if (error) goto cleanup; } /* parse floating-point part */ { num_int = 0; num_frac = 0; after_radix = 0; for (i = 0; inp + i != emarker && inp[i] != '\0'; i++) { if (inp[i] == '.' && !after_radix) { after_radix = 1; } else if (inp[i] >= '0' && inp[i] <= '9') { buf[num_int + num_frac] = inp[i]; num_frac += after_radix; num_int += !after_radix; } else { error = 1; goto cleanup; } } buf[num_int + num_frac] = '\0'; /* put trailing zeros into the exponent */ while (num_int + num_frac > 1 && buf[num_int + num_frac - 1] == '0') { buf[num_int + num_frac - 1] = '\0'; num_frac--; } fmpz_sub_si(exp, exp, num_frac); error = fmpz_set_str(man, buf, 10); if (error) goto cleanup; } if (fmpz_is_zero(man)) { arb_zero(res); } else if (fmpz_is_zero(exp)) { arb_set_round_fmpz(res, man, prec); } else { arb_t t; arb_init(t); arb_set_ui(t, 10); arb_set_fmpz(res, man); if (fmpz_sgn(exp) > 0) { arb_pow_fmpz_binexp(t, t, exp, prec + 4); arb_mul(res, res, t, prec); } else { fmpz_neg(exp, exp); arb_pow_fmpz_binexp(t, t, exp, prec + 4); arb_div(res, res, t, prec); } arb_clear(t); } cleanup: fmpz_clear(exp); fmpz_clear(man); flint_free(buf); if (error) arb_indeterminate(res); return error; } int arb_set_str(arb_t res, const char * inp, slong prec) { char * buf; char * split; char * first; char * last; slong i, len; int error; error = 0; len = strlen(inp); buf = flint_malloc(len + 1); for (i = 0; i <= len; i++) buf[i] = tolower(inp[i]); split = strstr(buf, "+/-"); if (split == NULL) { /* strip whitespace and brackets */ first = buf; while (isspace(first[0]) || first[0] == '[') first++; last = buf + len; while (last - first > 0 && (isspace(last[-1]) || last[-1] == ']')) last--; last[0] = '\0'; error = arb_set_float_str(res, first, prec); } else { arb_t rad; arb_init(rad); /* strip whitespace and brackets */ first = buf; while (isspace(first[0]) || first[0] == '[') first++; last = split; while (last - first > 0 && (isspace(last[-1]) || last[-1] == ']')) last--; last[0] = '\0'; if (first == last) arb_zero(res); else error = arb_set_float_str(res, first, prec); if (!error) { /* strip whitespace and brackets */ first = split + 3; while (isspace(first[0]) || first[0] == '[') first++; last = buf + len; while (last - first > 0 && (isspace(last[-1]) || last[-1] == ']')) last--; last[0] = '\0'; error = arb_set_float_str(rad, first, prec); arb_abs(rad, rad); arb_add_error(res, rad); } arb_clear(rad); } flint_free(buf); return error; } flint-3.1.3/src/arb/sgn.c000066400000000000000000000012611461254215100151210ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sgn(arb_t res, const arb_t x) { if (arb_is_zero(x)) { arb_zero(res); } else if (arb_contains_zero(x)) { arf_zero(arb_midref(res)); mag_one(arb_radref(res)); } else { arb_set_si(res, arf_sgn(arb_midref(x))); } } flint-3.1.3/src/arb/sgn_nonzero.c000066400000000000000000000010651461254215100166750ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" int arb_sgn_nonzero(const arb_t x) { if (arb_is_positive(x)) return 1; else if (arb_is_negative(x)) return -1; else return 0; } flint-3.1.3/src/arb/sin_cos.c000066400000000000000000000402251461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "arb.h" #define TMP_ALLOC_LIMBS(__n) TMP_ALLOC((__n) * sizeof(mp_limb_t)) #define MAGLIM(prec) FLINT_MAX(65536, (4*prec)) static void mag_nonzero_fast_mul(mag_t z, const mag_t x, const mag_t y) { MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + LIMB_ONE; MAG_EXP(z) = MAG_EXP(x) + MAG_EXP(y); MAG_FAST_ADJUST_ONE_TOO_SMALL(z); } static void mag_nonzero_fast_add(mag_t z, const mag_t x, const mag_t y) { slong shift = MAG_EXP(x) - MAG_EXP(y); if (shift == 0) { MAG_EXP(z) = MAG_EXP(x); MAG_MAN(z) = MAG_MAN(x) + MAG_MAN(y); MAG_FAST_ADJUST_ONE_TOO_LARGE(z); /* may need two adjustments */ } else if (shift > 0) { MAG_EXP(z) = MAG_EXP(x); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(x) + LIMB_ONE; else MAG_MAN(z) = MAG_MAN(x) + (MAG_MAN(y) >> shift) + LIMB_ONE; } else { shift = -shift; MAG_EXP(z) = MAG_EXP(y); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(y) + LIMB_ONE; else MAG_MAN(z) = MAG_MAN(y) + (MAG_MAN(x) >> shift) + LIMB_ONE; } MAG_FAST_ADJUST_ONE_TOO_LARGE(z); } static int mag_nonzero_fast_cmp(const mag_t x, const mag_t y) { if (MAG_EXP(x) == MAG_EXP(y)) return (MAG_MAN(x) < MAG_MAN(y)) ? -1 : 1; else return (MAG_EXP(x) < MAG_EXP(y)) ? -1 : 1; } static void mag_fast_set(mag_t x, const mag_t y) { MAG_EXP(x) = MAG_EXP(y); MAG_MAN(x) = MAG_MAN(y); } void _arb_sin_cos(arb_t zsin, arb_t zcos, const arf_t x, const mag_t xrad, slong prec) { int want_sin, want_cos; slong radexp, exp, wp, wn, N, r, wprounded, maglim, orig_prec; mp_ptr tmp, w, sina, cosa, sinb, cosb, ta, tb; mp_ptr sinptr, cosptr; mp_limb_t p1, q1bits, p2, q2bits, error, error2, p1_tab1, radman; int negative, inexact, octant; int sinnegative, cosnegative, swapsincos; TMP_INIT; /* PART 1: special cases and setup. */ orig_prec = prec; /* Below, both x and xrad will be finite, and x will be nonzero. */ if (mag_is_inf(xrad) || arf_is_special(x)) { _arb_sin_cos_generic(zsin, zcos, x, xrad, prec); return; } exp = ARF_EXP(x); maglim = MAGLIM(prec); negative = ARF_SGNBIT(x); /* Unlikely: tiny or huge midpoint. As written, this test also catches any bignum exponents. */ if (exp < -(prec/2) - 2 || exp > maglim) { _arb_sin_cos_generic(zsin, zcos, x, xrad, prec); return; } want_sin = (zsin != NULL); want_cos = (zcos != NULL); /* Copy the radius data. */ radexp = MAG_EXP(xrad); radman = MAG_MAN(xrad); if (radman != 0) { /* Clamp the radius exponent to a safe range. */ if (radexp < MAG_MIN_LAGOM_EXP || radexp > MAG_MAX_LAGOM_EXP) { /* Very wide... */ if (fmpz_sgn(MAG_EXPREF(xrad)) > 0) { _arb_sin_cos_wide(zsin, zcos, x, xrad, prec); return; } radman = MAG_ONE_HALF; radexp = MAG_MIN_LAGOM_EXP + 1; } /* Use wide algorithm. */ if (radexp >= -24) { _arb_sin_cos_wide(zsin, zcos, x, xrad, prec); return; } /* Regular case: decrease precision to match generic max. accuracy. */ /* Note: near x=0, the error can be quadratic for cos. */ if (want_cos && exp < -2) prec = FLINT_MIN(prec, 20 - FLINT_MAX(exp, radexp) - radexp); else prec = FLINT_MIN(prec, 20 - radexp); } if (prec >= ARB_SIN_COS_ATAN_REDUCTION_PREC && prec <= ARB_SIN_COS_ATAN_REDUCTION_DEFAULT_MAX_PREC) { mag_t err; mag_init(err); mag_set(err, xrad); arb_sin_cos_arf_atan_reduction(zsin, zcos, x, prec); if (zsin != NULL) arb_add_error_mag(zsin, err); if (zcos != NULL) arb_add_error_mag(zcos, err); mag_clear(err); return; } /* Absolute working precision (NOT rounded to a limb multiple) */ wp = prec + 8; if (want_sin && exp <= 0) wp += (-exp); /* Number of limbs */ wn = (wp + FLINT_BITS - 1) / FLINT_BITS; /* Precision rounded to a number of bits */ wprounded = FLINT_BITS * wn; /* Don't be close to the boundary (to allow adding adding the Taylor series truncation error without overflow) */ wp = FLINT_MAX(wp, wprounded - (FLINT_BITS - 4)); /* Too high precision to use table -- use generic algorithm */ if (wp > ARB_SIN_COS_TAB2_PREC) { _arb_sin_cos_generic(zsin, zcos, x, xrad, orig_prec); return; } /* PART 2: the actual computation. */ TMP_START; tmp = TMP_ALLOC_LIMBS(9 * wn); w = tmp; /* requires wn limbs */ sina = w + wn; /* requires wn limbs */ cosa = sina + wn; /* requires wn limbs */ sinb = cosa + wn; /* requires wn limbs */ cosb = sinb + wn; /* requires wn limbs */ ta = cosb + wn; /* requires 2*wn limbs */ tb = ta + 2*wn; /* requires 2*wn limbs */ /* reduce modulo pi/4 */ if (_arb_get_mpn_fixed_mod_pi4(w, NULL, &octant, &error, x, wn) == 0) { /* may run out of precision for pi/4 */ _arb_sin_cos_generic(zsin, zcos, x, xrad, orig_prec); TMP_END; return; } sinnegative = (octant >= 4) ^ negative; cosnegative = (octant >= 2 && octant <= 5); swapsincos = (octant == 1 || octant == 2 || octant == 5 || octant == 6); /* Table-based argument reduction (1 or 2 steps) */ if (wp <= ARB_SIN_COS_TAB1_PREC) { q1bits = ARB_SIN_COS_TAB1_BITS; q2bits = 0; p1 = p1_tab1 = w[wn-1] >> (FLINT_BITS - q1bits); w[wn-1] -= (p1 << (FLINT_BITS - q1bits)); p2 = 0; /* p1_tab1 will be used for the error bounds at the end. */ p1_tab1 = p1; } else { q1bits = ARB_SIN_COS_TAB21_BITS; q2bits = ARB_SIN_COS_TAB21_BITS + ARB_SIN_COS_TAB22_BITS; /* p1_tab1 will be used for the error bounds at the end. */ p1_tab1 = w[wn-1] >> (FLINT_BITS - ARB_SIN_COS_TAB1_BITS); p1 = w[wn-1] >> (FLINT_BITS - q1bits); w[wn-1] -= (p1 << (FLINT_BITS - q1bits)); p2 = w[wn-1] >> (FLINT_BITS - q2bits); w[wn-1] -= (p2 << (FLINT_BITS - q2bits)); } /* |w| <= 2^-r */ r = _arb_mpn_leading_zeros(w, wn); /* Choose number of terms N such that Taylor series truncation error is <= 2^-wp */ N = _arb_exp_taylor_bound(-r, wp); /* the summation for sin/cos is actually done to (2N-1)! */ N = (N + 1) / 2; if (N < 14) { /* Evaluate Taylor series */ _arb_sin_cos_taylor_rs(sina, cosa, &error2, w, wn, N, 0, 1); /* Taylor series evaluation error */ error += error2; /* Taylor series truncation error */ error += UWORD(1) << (wprounded-wp); } else /* Compute cos(a) from sin(a) using a square root. */ { /* Evaluate Taylor series */ _arb_sin_cos_taylor_rs(sina, cosa, &error2, w, wn, N, 1, 1); error += error2; error += UWORD(1) << (wprounded-wp); if (flint_mpn_zero_p(sina, wn)) { flint_mpn_store(cosa, wn, LIMB_ONES); error = FLINT_MAX(error, 1); } else { flint_mpn_sqr(ta, sina, wn); /* 1 - s^2 (negation guaranteed to have borrow) */ mpn_neg(ta, ta, 2 * wn); /* top limb of ta must be nonzero, so no need to normalize before calling mpn_sqrtrem */ mpn_sqrtrem(cosa, ta, ta, 2 * wn); /* When converting sin to cos, the error for cos must be smaller than the error for sin; but we also get 1 ulp extra error from the square root. */ error += 1; } } /* sin(a+b) = sin(a)*cos(b) + cos(a)*sin(b) cos(a+b) = cos(a)*cos(b) - sin(a)*sin(b) [F1+e1]*[F2+e2] + [F3+e3]*[F4+e4] - F1 F2 + F3 F4 = e1 e2 + e3 e4 + e2 F1 + e1 F2 + e4 F3 + e3 F4 <= (e1 + e2 + e3 + e4) + 1 (ulp) <= 2*left_err + 2*right_err + 1 (ulp) Truncating both terms before adding adds another 2 ulp, so the error is bounded by <= 2*left_err + 2*right_err + 3 (ulp) */ if (p1 == 0 && p2 == 0) /* no table lookups */ { sinptr = sina; cosptr = cosa; } else if (p1 == 0 || p2 == 0) /* only one table lookup */ { mp_srcptr sinc, cosc; if (wp <= ARB_SIN_COS_TAB1_PREC) /* must be in table 1 */ { sinc = arb_sin_cos_tab1[2 * p1] + ARB_SIN_COS_TAB1_LIMBS - wn; cosc = arb_sin_cos_tab1[2 * p1 + 1] + ARB_SIN_COS_TAB1_LIMBS - wn; } else if (p1 != 0) { sinc = arb_sin_cos_tab21[2 * p1] + ARB_SIN_COS_TAB2_LIMBS - wn; cosc = arb_sin_cos_tab21[2 * p1 + 1] + ARB_SIN_COS_TAB2_LIMBS - wn; } else { sinc = arb_sin_cos_tab22[2 * p2] + ARB_SIN_COS_TAB2_LIMBS - wn; cosc = arb_sin_cos_tab22[2 * p2 + 1] + ARB_SIN_COS_TAB2_LIMBS - wn; } if ((want_sin && !swapsincos) || (want_cos && swapsincos)) { flint_mpn_mul_n(ta, sina, cosc, wn); flint_mpn_mul_n(tb, cosa, sinc, wn); mpn_add_n(w, ta + wn, tb + wn, wn); } if ((want_cos && !swapsincos) || (want_sin && swapsincos)) { flint_mpn_mul_n(ta, cosa, cosc, wn); flint_mpn_mul_n(tb, sina, sinc, wn); mpn_sub_n(ta, ta + wn, tb + wn, wn); } sinptr = w; cosptr = ta; error = 2 * error + 2 * 1 + 3; } else /* two table lookups, must be in table 2 */ { mp_srcptr sinc, cosc, sind, cosd; sinc = arb_sin_cos_tab21[2 * p1] + ARB_SIN_COS_TAB2_LIMBS - wn; cosc = arb_sin_cos_tab21[2 * p1 + 1] + ARB_SIN_COS_TAB2_LIMBS - wn; sind = arb_sin_cos_tab22[2 * p2] + ARB_SIN_COS_TAB2_LIMBS - wn; cosd = arb_sin_cos_tab22[2 * p2 + 1] + ARB_SIN_COS_TAB2_LIMBS - wn; flint_mpn_mul_n(ta, sinc, cosd, wn); flint_mpn_mul_n(tb, cosc, sind, wn); mpn_add_n(sinb, ta + wn, tb + wn, wn); flint_mpn_mul_n(ta, cosc, cosd, wn); flint_mpn_mul_n(tb, sinc, sind, wn); mpn_sub_n(cosb, ta + wn, tb + wn, wn); error2 = 2 * 1 + 2 * 1 + 3; if ((want_sin && !swapsincos) || (want_cos && swapsincos)) { flint_mpn_mul_n(ta, sina, cosb, wn); flint_mpn_mul_n(tb, cosa, sinb, wn); mpn_add_n(w, ta + wn, tb + wn, wn); } if ((want_cos && !swapsincos) || (want_sin && swapsincos)) { flint_mpn_mul_n(ta, cosa, cosb, wn); flint_mpn_mul_n(tb, sina, sinb, wn); mpn_sub_n(ta, ta + wn, tb + wn, wn); } error = 2 * error + 2 * error2 + 3; sinptr = w; cosptr = ta; } /* PART 3: compute propagated error and write output */ if (swapsincos) { mp_ptr tmptr = sinptr; sinptr = cosptr; cosptr = tmptr; } /* We have two sources of error. 1. Computation error: error * 2^(-wprounded) 2. With input radius r != 0, the propagated error bound: sin(x): min(2, r, |cos(x)|*r + 0.5*r^2) cos(x): min(2, r, |sin(x)|*r + 0.5*r^2) We skip the min by 2 since this is unnecessary with the separate code for wide intervals. */ if (radman == 0) { if (want_sin) { mag_set_ui_2exp_si(arb_radref(zsin), error, -wprounded); if (want_cos) mag_set(arb_radref(zcos), arb_radref(zsin)); } else { mag_set_ui_2exp_si(arb_radref(zcos), error, -wprounded); } } else { mag_t sin_err, cos_err, quadratic, comp_err, xrad_copy; mp_limb_t A_sin, A_cos, A_exp; /* Copy xrad to support aliasing (note: the exponent has also been clamped earlier). */ MAG_MAN(xrad_copy) = radman; MAG_EXP(xrad_copy) = radexp; /* Bound computed error. */ if (error != 0) { mag_init(comp_err); /* no need to free */ mag_set_ui_2exp_si(comp_err, error, -wprounded); } /* Bound quadratic term for propagated error: 0.5*r^2 */ mag_init(quadratic); /* no need to free */ mag_nonzero_fast_mul(quadratic, xrad_copy, xrad_copy); MAG_EXP(quadratic) -= 1; /* Bound linear term for propagated error: cos(x)*r, sin(x)*r. */ /* Note: we could have used the computed values, but then we would need to incorporate the computed error which would be slightly messier, and we would also need extra cases when only computing one of the functions. */ A_cos = arb_sin_cos_tab1[2 * p1_tab1][ARB_SIN_COS_TAB1_LIMBS - 1]; A_sin = arb_sin_cos_tab1[2 * p1_tab1 + 1][ARB_SIN_COS_TAB1_LIMBS - 1]; /* Note: ARB_SIN_COS_TAB1_BITS == 8 */ /* Adding 2 ulps (here ulp = 2^-8) gives an upper bound. The truncated table entry underestimates the sine or cosine of x by at most 1 ulp, and the top bits of x underestimate x by at most 1 ulp. */ A_sin = (A_sin >> (FLINT_BITS - ARB_SIN_COS_TAB1_BITS)) + 2; A_cos = (A_cos >> (FLINT_BITS - ARB_SIN_COS_TAB1_BITS)) + 2; A_exp = -ARB_SIN_COS_TAB1_BITS; if (swapsincos) { mp_limb_t tt = A_sin; A_sin = A_cos; A_cos = tt; } A_sin *= ((MAG_MAN(xrad_copy) >> (MAG_BITS - ARB_SIN_COS_TAB1_BITS)) + LIMB_ONE); A_cos *= ((MAG_MAN(xrad_copy) >> (MAG_BITS - ARB_SIN_COS_TAB1_BITS)) + LIMB_ONE); A_exp -= ARB_SIN_COS_TAB1_BITS; A_exp += radexp; if (want_sin) { mag_init(sin_err); mag_set_ui_2exp_si(sin_err, A_sin, A_exp); mag_nonzero_fast_add(sin_err, sin_err, quadratic); /* The propagated error is certainly at most r */ if (mag_nonzero_fast_cmp(sin_err, xrad_copy) > 0) mag_fast_set(sin_err, xrad_copy); /* Add the computed error. */ if (error != 0) mag_nonzero_fast_add(sin_err, sin_err, comp_err); /* Set it, and clear the original output variable which could have a bignum exponent. */ mag_swap(arb_radref(zsin), sin_err); mag_clear(sin_err); } /* The same as above. */ if (want_cos) { mag_init(cos_err); mag_set_ui_2exp_si(cos_err, A_cos, A_exp); mag_nonzero_fast_add(cos_err, cos_err, quadratic); if (mag_nonzero_fast_cmp(cos_err, xrad_copy) > 0) mag_fast_set(cos_err, xrad_copy); if (error != 0) mag_nonzero_fast_add(cos_err, cos_err, comp_err); mag_swap(arb_radref(zcos), cos_err); mag_clear(cos_err); } } /* Set the midpoints. */ if (want_sin) { inexact = _arf_set_mpn_fixed(arb_midref(zsin), sinptr, wn, wn, sinnegative, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(zsin), arb_radref(zsin), arb_midref(zsin), prec); } if (want_cos) { inexact = _arf_set_mpn_fixed(arb_midref(zcos), cosptr, wn, wn, cosnegative, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(zcos), arb_radref(zcos), arb_midref(zcos), prec); } TMP_END; } void arb_sin_cos(arb_t s, arb_t c, const arb_t x, slong prec) { _arb_sin_cos(s, c, arb_midref(x), arb_radref(x), prec); } void arb_sin(arb_t s, const arb_t x, slong prec) { _arb_sin_cos(s, NULL, arb_midref(x), arb_radref(x), prec); } void arb_cos(arb_t c, const arb_t x, slong prec) { _arb_sin_cos(NULL, c, arb_midref(x), arb_radref(x), prec); } flint-3.1.3/src/arb/sin_cos_arf_bb.c000066400000000000000000000346261461254215100172750ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz_vec.h" #include "arb.h" #include "acb.h" slong _arb_compute_bs_exponents(slong * tab, slong n); slong _arb_get_exp_pos(const slong * tab, slong step); static void bsplit(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const slong * xexp, const fmpz * xpow, flint_bitcnt_t r, slong a, slong b) { int cc; if (b - a == 1) { cc = flint_ctz((2 * a + 2)); fmpz_neg_ui(Q, (2 * a + 2) >> cc); fmpz_mul_ui(Q, Q, 2 * a + 3); *Qexp = 2 * r + cc; fmpz_set(T, xpow); } else if (b - a == 2) { fmpz_mul2_uiui(T, xpow, (2 * a + 4), (2 * a + 5)); fmpz_mul_2exp(T, T, 2 * r); fmpz_neg(T, T); fmpz_add(T, T, xpow + 1); cc = flint_ctz((2 * a + 4)); fmpz_neg_ui(Q, (2 * a + 4) >> cc); fmpz_mul_ui(Q, Q, 2 * a + 5); *Qexp = 2 * r + cc; cc = flint_ctz((2 * a + 2)); fmpz_mul2_uiui(Q, Q, (2 * a + 2) >> cc, (2 * a + 3)); fmpz_neg(Q, Q); *Qexp += 2 * r + cc; } else { slong step, m, i; flint_bitcnt_t Q2exp[1]; fmpz_t Q2, T2; step = (b - a) / 2; m = a + step; fmpz_init(Q2); fmpz_init(T2); bsplit(T, Q, Qexp, xexp, xpow, r, a, m); bsplit(T2, Q2, Q2exp, xexp, xpow, r, m, b); fmpz_mul(T, T, Q2); fmpz_mul_2exp(T, T, *Q2exp); /* find x^step in table */ i = _arb_get_exp_pos(xexp, step); fmpz_addmul(T, xpow + i, T2); fmpz_clear(T2); fmpz_mul(Q, Q, Q2); *Qexp = *Qexp + *Q2exp; fmpz_clear(Q2); } } typedef struct { fmpz_t T; fmpz_t Q; flint_bitcnt_t Qexp; slong a; slong b; } cos_bsplit_struct; typedef cos_bsplit_struct cos_bsplit_t[1]; static void cos_bsplit_init(cos_bsplit_t x, void * args) { fmpz_init(x->T); fmpz_init(x->Q); } static void cos_bsplit_clear(cos_bsplit_t x, void * args) { fmpz_clear(x->T); fmpz_clear(x->Q); } typedef struct { const slong * xexp; const fmpz * xpow; flint_bitcnt_t r; } cos_bsplit_args; static void cos_bsplit_merge(cos_bsplit_t res, cos_bsplit_t L, cos_bsplit_t R, cos_bsplit_args * args) { slong i, step; slong a = L->a; slong b = R->b; step = (b - a) / 2; fmpz_mul(res->T, L->T, R->Q); fmpz_mul_2exp(res->T, res->T, R->Qexp); /* find x^step in table */ i = _arb_get_exp_pos(args->xexp, step); fmpz_addmul(res->T, args->xpow + i, R->T); fmpz_zero(R->T); fmpz_mul(res->Q, L->Q, R->Q); res->Qexp = L->Qexp + R->Qexp; res->a = L->a; /* actually a no-op because of aliasing */ res->b = R->b; } static void cos_bsplit_basecase(cos_bsplit_t res, slong a, slong b, cos_bsplit_args * args) { bsplit(res->T, res->Q, &(res->Qexp), args->xexp, args->xpow, args->r, a, b); res->a = a; res->b = b; } static void bsplit2(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const slong * xexp, const fmpz * xpow, flint_bitcnt_t r, slong a, slong b) { cos_bsplit_t s; cos_bsplit_args args; slong max_threads; slong prec_hint; args.xexp = xexp; args.xpow = xpow; args.r = r; *s->T = *T; *s->Q = *Q; max_threads = flint_get_num_threads(); prec_hint = 2 * (b - a) * FLINT_MAX(r, 1); if (prec_hint < 30000) max_threads = 1; else if (prec_hint < 1000000) max_threads = FLINT_MIN(2, max_threads); else if (prec_hint < 5000000) max_threads = FLINT_MIN(4, max_threads); else max_threads = FLINT_MIN(8, max_threads); flint_parallel_binary_splitting(s, (bsplit_basecase_func_t) cos_bsplit_basecase, (bsplit_merge_func_t) cos_bsplit_merge, sizeof(cos_bsplit_struct), (bsplit_init_func_t) cos_bsplit_init, (bsplit_clear_func_t) cos_bsplit_clear, &args, a, b, 4, max_threads, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); *T = *s->T; *Q = *s->Q; *Qexp = s->Qexp; } /* todo: also allow computing cos, using the same table... */ void _arb_sin_sum_bs_powtab(fmpz_t T, fmpz_t Q, flint_bitcnt_t * Qexp, const fmpz_t x, flint_bitcnt_t r, slong N) { slong * xexp; slong length, i; fmpz * xpow; /* compute the powers of x^2 that will appear (at least x^2) */ xexp = flint_calloc(2 * FLINT_BITS, sizeof(slong)); length = _arb_compute_bs_exponents(xexp, N); xpow = _fmpz_vec_init(length); fmpz_mul(xpow, x, x); /* build x^i table */ for (i = 1; i < length; i++) { if (xexp[i] == 2 * xexp[i-1]) { fmpz_mul(xpow + i, xpow + i - 1, xpow + i - 1); } else if (xexp[i] == 2 * xexp[i-2]) /* prefer squaring if possible */ { fmpz_mul(xpow + i, xpow + i - 2, xpow + i - 2); } else if (xexp[i] == 2 * xexp[i-1] + 1) { fmpz_mul(xpow + i, xpow + i - 1, xpow + i - 1); fmpz_mul(xpow + i, xpow + i, xpow); } else if (xexp[i] == 2 * xexp[i-2] + 1) { fmpz_mul(xpow + i, xpow + i - 2, xpow + i - 2); fmpz_mul(xpow + i, xpow + i, xpow); } else { flint_throw(FLINT_ERROR, "power table has the wrong structure!\n"); } } if (flint_get_num_available_threads() == 1) bsplit(T, Q, Qexp, xexp, xpow, r, 0, N); else bsplit2(T, Q, Qexp, xexp, xpow, r, 0, N); _fmpz_vec_clear(xpow, length); flint_free(xexp); } /* Determine N such that the error is bounded by 2^-prec when summing the Taylor series of sin(x) up to term x^(2N+1) inclusive. We choose an N with many trailing zeros to improve efficiency of the binary splitting. */ static slong bs_num_terms(slong mag, slong prec) { slong N; N = _arb_exp_taylor_bound(mag, prec); N = N / 2 - 1; N = FLINT_MAX(N, 1); if (N > 10000) while (N % 128 != 0) N++; if (N > 1000) while (N % 16 != 0) N++; if (N > 100) while (N % 2 != 0) N++; return N; } void arb_sin_cos_fmpz_div_2exp_bsplit(arb_t wsin, arb_t wcos, const fmpz_t x, flint_bitcnt_t r, slong prec) { fmpz_t T, Q; slong N, xmag; flint_bitcnt_t Qexp[1]; /* slightly reduce memory usage at very high precision */ arb_zero(wsin); arb_zero(wcos); fmpz_init(T); fmpz_init(Q); if (r > prec) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* Binary splitting (+1 fixed-point ulp truncation error). */ xmag = fmpz_bits(x) - r; N = bs_num_terms(xmag, prec); _arb_sin_sum_bs_powtab(T, Q, Qexp, x, r, N); /* we still need to multiply and add x/2^r to get sine */ fmpz_mul(T, T, x); Qexp[0] += r; /* T = T / Q (+1 fixed-point ulp error). */ if (Qexp[0] >= prec) fmpz_tdiv_q_2exp(T, T, Qexp[0] - prec); else fmpz_mul_2exp(T, T, prec - Qexp[0]); arb_fmpz_divapprox(T, T, Q); fmpz_mul_2exp(Q, x, prec - r); fmpz_add(T, T, Q); /* T = sin(u) with at most 2 fixed-point ulp error. */ arf_set_fmpz(arb_midref(wsin), T); arf_mul_2exp_si(arb_midref(wsin), arb_midref(wsin), -prec); mag_set_ui_2exp_si(arb_radref(wsin), 2, -prec); /* compute cos from sin */ arb_mul(wcos, wsin, wsin, prec); arb_sub_ui(wcos, wcos, 1, prec); arb_neg(wcos, wcos); arb_sqrt(wcos, wcos, prec); fmpz_clear(T); fmpz_clear(Q); } typedef struct { acb_ptr vs; fmpz * u; slong * r; slong wp; } work_t; static void worker(slong iter, work_t * work) { arb_sin_cos_fmpz_div_2exp_bsplit(acb_imagref(work->vs + iter), acb_realref(work->vs + iter), work->u + iter, work->r[iter], work->wp); } /* parallel product of complex numbers; destructive (overwrites input) */ typedef struct { acb_ptr vec; slong prec; } pwork_t; static void pbasecase(acb_t res, slong a, slong b, pwork_t * work) { if (b - a == 0) { acb_one(res); } else if (b - a == 1) { acb_swap(res, work->vec + a); } else { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } } static void pmerge(acb_t res, acb_t a, acb_t b, pwork_t * work) { arb_t tmp1; arb_ptr zsin, zcos, wsin, wcos; slong wp = work->prec; zcos = acb_realref(res); zsin = acb_imagref(res); wcos = acb_realref(b); wsin = acb_imagref(b); arb_init(tmp1); arb_add(tmp1, zsin, zcos, wp); arb_mul(zcos, zcos, wcos, wp); arb_add(wcos, wcos, wsin, wp); arb_mul(wsin, wsin, zsin, wp); arb_mul(wcos, tmp1, wcos, wp); arb_zero(tmp1); arb_sub(zsin, wcos, wsin, wp); arb_zero(wcos); arb_sub(zsin, zsin, zcos, wp); arb_sub(zcos, zcos, wsin, wp); arb_zero(wsin); arb_clear(tmp1); } void _acb_vec_prod_bsplit_threaded(acb_t res, acb_ptr vec, slong len, slong prec) { pwork_t work; work.vec = vec; work.prec = prec; flint_parallel_binary_splitting(res, (bsplit_basecase_func_t) pbasecase, (bsplit_merge_func_t) pmerge, sizeof(acb_struct), (bsplit_init_func_t) acb_init, (bsplit_clear_func_t) acb_clear, &work, 0, len, 1, -1, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); } void arb_sin_cos_arf_bb(arb_t zsin, arb_t zcos, const arf_t x, slong prec) { slong k, bits, r, xmag, q, wp; slong argred_bits, start_bits; int inexact, negative; fmpz_t t, u; arb_t wcos, wsin, tmp1; if (zsin == NULL) { arb_init(tmp1); arb_sin_cos_arf_bb(tmp1, zcos, x, prec); arb_clear(tmp1); return; } if (zcos == NULL) { arb_init(tmp1); arb_sin_cos_arf_bb(zsin, tmp1, x, prec); arb_clear(tmp1); return; } if (arf_is_zero(x)) { arb_zero(zsin); arb_one(zcos); return; } xmag = arf_abs_bound_lt_2exp_si(x); negative = arf_sgn(x) < 0; /* We assume that this function only gets called with something reasonable as input (huge/tiny input will be handled by the main sin/cos wrapper). */ if (arf_is_special(x) || arf_cmpabs_d(x, 3.15) > 0 || xmag < -2 * prec - 100) { flint_throw(FLINT_ERROR, "arb_sin_cos_arf_bb: unexpectedly large/small input\n"); } argred_bits = 24; start_bits = argred_bits * 3; q = FLINT_MAX(0, xmag + argred_bits); if (q <= 2) q = 0; wp = prec + 10 + 2 * (q - xmag) + 2 * FLINT_BIT_COUNT(prec); fmpz_init(t); fmpz_init(u); arb_init(wcos); arb_init(wsin); arb_init(tmp1); /* Convert x/2^q to a fixed-point number. */ inexact = arf_get_fmpz_fixed_si(t, x, -wp + q); fmpz_abs(t, t); /* Aliasing of z and x is safe now that only use t. */ /* Start with z = 1. */ arb_one(zcos); arb_zero(zsin); /* We have two ways to parallelize the BB algorithm: run the main loop serially and rely on parallel binary splitting, or compute all the sines/cosines in parallel. The latter is more efficient (empirically about 1.7x) but uses more memory, so we fall back on a serial main loop at high enough precision. */ if (flint_get_num_available_threads() == 1 || prec >= 4e8) { /* Bit-burst loop. */ for (bits = start_bits; !fmpz_is_zero(t); bits *= 3) { /* Extract bits. */ r = FLINT_MIN(bits, wp); fmpz_tdiv_q_2exp(u, t, wp - r); arb_sin_cos_fmpz_div_2exp_bsplit(wsin, wcos, u, r, wp); /* Remove used bits. */ fmpz_mul_2exp(u, u, wp - r); fmpz_sub(t, t, u); /* zsin, zcos = zsin wcos + zcos wsin, zcos wcos - zsin wsin */ /* using karatsuba */ arb_add(tmp1, zsin, zcos, wp); arb_mul(zcos, zcos, wcos, wp); arb_add(wcos, wcos, wsin, wp); arb_mul(wsin, wsin, zsin, wp); arb_mul(tmp1, tmp1, wcos, wp); arb_sub(zsin, tmp1, wsin, wp); arb_sub(zsin, zsin, zcos, wp); arb_sub(zcos, zcos, wsin, wp); arb_zero(tmp1); /* slightly reduce memory usage */ } } else { acb_ptr vs; fmpz * us; slong * rs; slong num = 0; vs = _acb_vec_init(FLINT_BITS); us = _fmpz_vec_init(FLINT_BITS); rs = flint_malloc(sizeof(slong) * FLINT_BITS); /* Bit-burst loop. */ for (bits = start_bits; !fmpz_is_zero(t); bits *= 3) { /* Extract bits. */ r = FLINT_MIN(bits, wp); fmpz_tdiv_q_2exp(u, t, wp - r); if (!fmpz_is_zero(u)) { fmpz_set(us + num, u); rs[num] = r; num++; } /* Remove used bits. */ fmpz_mul_2exp(u, u, wp - r); fmpz_sub(t, t, u); } /* todo: only allocate as many temporaries as threads, reducing memory */ { work_t work; work.vs = vs; work.u = us; work.r = rs; work.wp = wp; flint_parallel_do((do_func_t) worker, &work, num, -1, FLINT_PARALLEL_STRIDED); } { acb_t z; *acb_realref(z) = *zcos; *acb_imagref(z) = *zsin; _acb_vec_prod_bsplit_threaded(z, vs, num, wp); *zcos = *acb_realref(z); *zsin = *acb_imagref(z); } _acb_vec_clear(vs, FLINT_BITS); _fmpz_vec_clear(us, FLINT_BITS); flint_free(rs); } /* Initial fixed-point truncation error. */ if (inexact) { arb_add_error_2exp_si(zcos, -wp); arb_add_error_2exp_si(zsin, -wp); } if (q != 0) { /* cos(x) = 2 cos(x/2)^2 - 1 */ for (k = 0; k < q; k++) { arb_mul(zcos, zcos, zcos, wp); arb_mul_2exp_si(zcos, zcos, 1); arb_sub_ui(zcos, zcos, 1, wp); } arb_mul(tmp1, zcos, zcos, wp); arb_sub_ui(tmp1, tmp1, 1, wp); arb_neg(tmp1, tmp1); arb_sqrt(zsin, tmp1, wp); } if (negative) arb_neg(zsin, zsin); arb_set_round(zsin, zsin, prec); arb_set_round(zcos, zcos, prec); fmpz_clear(t); fmpz_clear(u); arb_clear(wcos); arb_clear(wsin); arb_clear(tmp1); } flint-3.1.3/src/arb/sin_cos_arf_generic.c000066400000000000000000000224431461254215100203200ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "thread_support.h" #include "arb.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif /* Computes sin(x) or cos(x) using Taylor series truncated at x^N exclusive. Computes error bound automatically. Does not allow aliasing of s and x. */ void arb_sin_cos_taylor_sum_rs(arb_t s, const arb_t x, slong N, int cosine, slong prec) { mag_t err; mag_init(err); arb_get_mag(err, x); mag_exp_tail(err, err, N); if (N == 0 || (!cosine && N == 1)) { arb_zero(s); } else if (cosine && N <= 2) { arb_one(s); } else if (!cosine && N <= 3) /* x */ { arb_set_round(s, x, prec); } else if (cosine && N <= 4) /* 1 - x^2/2 */ { arb_mul(s, x, x, prec / 2 + 4); arb_mul_2exp_si(s, s, -1); arb_sub_ui(s, s, 1, prec); arb_neg(s, s); } else if (!cosine && N <= 5) /* x - x^3/6 */ { arb_mul(s, x, x, prec / 2 + 4); arb_div_ui(s, s, 6, prec / 2 + 4); arb_mul(s, s, x, prec / 2 + 4); arb_sub(s, x, s, prec); } else { arb_ptr tpow; slong j, k, m, M, tp, xmag; mp_limb_t c, d, chi, clo; xmag = arf_abs_bound_lt_2exp_si(arb_midref(x)); /* Convert to order as a series in x^2. */ if (cosine) M = (N + 1) / 2; else M = N / 2; m = n_sqrt(M); /* not intended (and not 32-bit safe...) */ if (M > 30000) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } tpow = _arb_vec_init(m + 2); arb_mul(s, x, x, prec); _arb_vec_set_powers(tpow, s, m + 1, prec); arb_zero(s); c = 1; j = (M - 1) % m; for (k = M - 1; k >= 0; k--) { tp = prec - 2 * k * (-xmag) + 10; tp = FLINT_MAX(tp, 2); tp = FLINT_MIN(tp, prec); if (cosine) d = (2 * k - 1) * (2 * k); else d = (2 * k) * (2 * k + 1); if (k != 0) { umul_ppmm(chi, clo, c, d); if (chi != 0) { arb_div_ui(s, s, c, tp); c = 1; } } if (k % 2 == 0) arb_addmul_ui(s, tpow + j, c, tp); else arb_submul_ui(s, tpow + j, c, tp); if (k != 0) { c *= d; if (j == 0) { if (tp > 300000) { arb_set_round(tpow + m + 1, tpow + m, tp); arb_mul(s, s, tpow + m + 1, tp); } else { arb_mul(s, s, tpow + m, tp); } j = m - 1; } else { j--; } } } arb_div_ui(s, s, c, prec); if (!cosine) arb_mul(s, s, x, prec); _arb_vec_clear(tpow, m + 2); } arb_add_error_mag(s, err); mag_clear(err); } void arb_sin_cos_arf_rs_generic(arb_t res_sin, arb_t res_cos, const arf_t x, slong prec) { slong q, xmag, wp, k, N; arb_t s, t; int negate; if (arf_is_zero(x)) { if (res_sin != NULL) arb_zero(res_sin); if (res_cos != NULL) arb_one(res_cos); return; } xmag = arf_abs_bound_lt_2exp_si(x); /* x + O(x^3), 1 + O(x^2) */ if (xmag < -(prec / 2) - 4) { arb_init(t); arf_set(arb_midref(t), x); if (res_sin != NULL) arb_sin_cos_taylor_sum_rs(res_sin, t, 3, 0, prec); if (res_cos != NULL) arb_sin_cos_taylor_sum_rs(res_cos, t, 2, 1, prec); arb_clear(t); return; } xmag = FLINT_MAX(xmag, -prec); /* could include sanity test, but we assume that the function gets called with a valid |x| < pi/2 if (xmag > 0) { if (res_sin != NULL) arb_indeterminate(res_sin); if (res_cos != NULL) arb_indeterminate(res_cos); return; } */ arb_init(s); arb_init(t); negate = arf_sgn(x) < 0; /* generic tuning value */ q = 4.5 * pow(prec, 0.2); q = FLINT_MAX(q, 6); /* adjust to magnitude */ q = FLINT_MAX(0, xmag + q); /* don't do a redundant square root */ if (q <= 2) q = 0; wp = prec + 10 + 2 * FLINT_BIT_COUNT(prec); /* t = x/2^q */ arf_mul_2exp_si(arb_midref(t), x, -q); if (q == 0 && res_sin != NULL) { /* compute cos from sin since the square root has less cancellation */ wp += (-xmag); N = _arb_exp_taylor_bound(xmag, wp); arb_sin_cos_taylor_sum_rs(s, t, N, 0, wp); if (res_sin != NULL) arb_set_round(res_sin, s, prec); if (res_cos != NULL) { arb_mul(t, s, s, wp); arb_sub_ui(t, t, 1, wp); arb_neg(t, t); arb_sqrt(res_cos, t, prec); } } else { /* compute sin from cos */ wp = prec + 10 + 2 * FLINT_BIT_COUNT(prec); wp += 2 * (q - xmag); /* todo: too much when only computing cos? */ N = _arb_exp_taylor_bound(xmag - q, wp); arb_sin_cos_taylor_sum_rs(s, t, N, 1, wp); for (k = 0; k < q; k++) { arb_mul(s, s, s, wp); arb_mul_2exp_si(s, s, 1); arb_sub_ui(s, s, 1, wp); } if (res_cos != NULL) arb_set_round(res_cos, s, prec); if (res_sin != NULL) { arb_mul(s, s, s, wp); arb_sub_ui(s, s, 1, wp); arb_neg(s, s); arb_sqrtpos(res_sin, s, prec); if (negate) arb_neg(res_sin, res_sin); } } arb_clear(s); arb_clear(t); } void arb_sin_cos_arf_generic(arb_t res_sin, arb_t res_cos, const arf_t x, slong prec) { arb_t pi4, t, u, v; fmpz_t q; slong wp, mag; int octant, swapsincos, sinnegative, cosnegative, negative; mag = arf_abs_bound_lt_2exp_si(x); if (mag > FLINT_MAX(65536, 4 * prec)) { if (res_sin != NULL) arb_zero_pm_one(res_sin); if (res_cos != NULL) arb_zero_pm_one(res_cos); } else if (mag <= 0) /* todo: compare with pi/4-eps instead? */ { int want_rs; if (prec < 20000 || mag < -prec / 16) { want_rs = 1; } else if (arf_bits(x) < prec / 128) { want_rs = 0; } else if (flint_get_num_available_threads() == 1) { want_rs = (prec < 200000) || (prec < 1000000000 && mag < -prec / 5000); } else { want_rs = (prec < 20000) || (prec < 1000000000 && mag < -prec / 400); } if (want_rs) arb_sin_cos_arf_rs_generic(res_sin, res_cos, x, prec); else arb_sin_cos_arf_bb(res_sin, res_cos, x, prec); } else { arb_init(pi4); arb_init(t); arb_init(u); arb_init(v); fmpz_init(q); wp = prec + mag + 10; negative = arf_sgn(x) < 0; arb_const_pi(pi4, wp); arb_mul_2exp_si(pi4, pi4, -2); arb_set_arf(t, x); arb_abs(t, t); arb_set_round(v, t, mag + 10); arb_set_round(u, pi4, mag + 10); arb_div(u, v, u, mag + 10); arf_get_fmpz(q, arb_midref(u), ARF_RND_DOWN); arb_submul_fmpz(t, pi4, q, wp); octant = fmpz_fdiv_ui(q, 8); if (octant & 1) arb_sub(t, pi4, t, wp); arb_clear(pi4); arb_clear(u); arb_clear(v); sinnegative = (octant >= 4) ^ negative; cosnegative = (octant >= 2 && octant <= 5); swapsincos = (octant == 1 || octant == 2 || octant == 5 || octant == 6); /* guard against infinite recursion */ if (arf_cmpabs_2exp_si(arb_midref(t), 0) > 0) { flint_throw(FLINT_ERROR, "mod pi/4 reduction unexpectedly failed!\n"); } /* todo: allow NULL in arb_sin_cos and simplify here */ if (swapsincos) { if (res_sin != NULL && res_cos != NULL) arb_sin_cos(res_cos, res_sin, t, prec); else if (res_sin != NULL) arb_cos(res_sin, t, prec); else arb_sin(res_cos, t, prec); } else { if (res_sin != NULL && res_cos != NULL) arb_sin_cos(res_sin, res_cos, t, prec); else if (res_sin != NULL) arb_sin(res_sin, t, prec); else arb_cos(res_cos, t, prec); } if (sinnegative && res_sin != NULL) arb_neg(res_sin, res_sin); if (cosnegative && res_cos != NULL) arb_neg(res_cos, res_cos); arb_clear(t); fmpz_clear(q); } } flint-3.1.3/src/arb/sin_cos_generic.c000066400000000000000000000056611461254215100174730ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void _arb_sin_cos_generic(arb_t s, arb_t c, const arf_t x, const mag_t xrad, slong prec) { int want_sin, want_cos; slong maglim; want_sin = (s != NULL); want_cos = (c != NULL); if (arf_is_zero(x) && mag_is_zero(xrad)) { if (want_sin) arb_zero(s); if (want_cos) arb_one(c); return; } if (!arf_is_finite(x) || !mag_is_finite(xrad)) { if (arf_is_nan(x)) { if (want_sin) arb_indeterminate(s); if (want_cos) arb_indeterminate(c); } else { if (want_sin) arb_zero_pm_one(s); if (want_cos) arb_zero_pm_one(c); } return; } maglim = FLINT_MAX(65536, 4 * prec); if (mag_cmp_2exp_si(xrad, -16) > 0 || arf_cmpabs_2exp_si(x, maglim) > 0) { _arb_sin_cos_wide(s, c, x, xrad, prec); return; } if (arf_cmpabs_2exp_si(x, -(prec/2) - 2) <= 0) { mag_t t, u, v; mag_init(t); mag_init(u); mag_init(v); arf_get_mag(t, x); mag_add(t, t, xrad); mag_mul(u, t, t); /* |sin(z)-z| <= z^3/6 */ if (want_sin) { arf_set(arb_midref(s), x); mag_set(arb_radref(s), xrad); arb_set_round(s, s, prec); mag_mul(v, u, t); mag_div_ui(v, v, 6); arb_add_error_mag(s, v); } /* |cos(z)-1| <= z^2/2 */ if (want_cos) { arf_one(arb_midref(c)); mag_mul_2exp_si(arb_radref(c), u, -1); } mag_clear(t); mag_clear(u); mag_clear(v); return; } if (mag_is_zero(xrad)) { arb_sin_cos_arf_generic(s, c, x, prec); } else { mag_t t; slong exp, radexp; mag_init_set(t, xrad); exp = arf_abs_bound_lt_2exp_si(x); radexp = MAG_EXP(xrad); if (radexp < MAG_MIN_LAGOM_EXP || radexp > MAG_MAX_LAGOM_EXP) radexp = MAG_MIN_LAGOM_EXP; if (want_cos && exp < -2) prec = FLINT_MIN(prec, 20 - FLINT_MAX(exp, radexp) - radexp); else prec = FLINT_MIN(prec, 20 - radexp); arb_sin_cos_arf_generic(s, c, x, prec); /* todo: could use quadratic bound */ if (want_sin) mag_add(arb_radref(s), arb_radref(s), t); if (want_cos) mag_add(arb_radref(c), arb_radref(c), t); mag_clear(t); } } void arb_sin_cos_generic(arb_t s, arb_t c, const arb_t x, slong prec) { _arb_sin_cos_generic(s, c, arb_midref(x), arb_radref(x), prec); } flint-3.1.3/src/arb/sin_cos_pi.c000066400000000000000000000071541461254215100164660ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sin_pi(arb_t y, const arb_t x, slong prec) { arb_t t; arb_t u; fmpz_t v; if (!arb_is_finite(x)) { arb_indeterminate(y); return; } if (arf_cmpabs_2exp_si(arb_midref(x), FLINT_MAX(65536, (4*prec))) > 0) { arf_zero(arb_midref(y)); mag_one(arb_radref(y)); return; } arb_init(t); arb_init(u); fmpz_init(v); arb_mul_2exp_si(t, x, 1); arf_get_fmpz(v, arb_midref(t), ARF_RND_NEAR); arb_sub_fmpz(t, t, v, prec); arb_const_pi(u, prec); arb_mul(t, t, u, prec); arb_mul_2exp_si(t, t, -1); switch (fmpz_fdiv_ui(v, 4)) { case 0: arb_sin(y, t, prec); break; case 1: arb_cos(y, t, prec); break; case 2: arb_sin(y, t, prec); arb_neg(y, y); break; default: arb_cos(y, t, prec); arb_neg(y, y); break; } fmpz_clear(v); arb_clear(t); arb_clear(u); } void arb_cos_pi(arb_t y, const arb_t x, slong prec) { arb_t t; arb_t u; fmpz_t v; if (!arb_is_finite(x)) { arb_indeterminate(y); return; } if (arf_cmpabs_2exp_si(arb_midref(x), FLINT_MAX(65536, (4*prec))) > 0) { arf_zero(arb_midref(y)); mag_one(arb_radref(y)); return; } arb_init(t); arb_init(u); fmpz_init(v); arb_mul_2exp_si(t, x, 1); arf_get_fmpz(v, arb_midref(t), ARF_RND_NEAR); arb_sub_fmpz(t, t, v, prec); arb_const_pi(u, prec); arb_mul(t, t, u, prec); arb_mul_2exp_si(t, t, -1); switch (fmpz_fdiv_ui(v, 4)) { case 0: arb_cos(y, t, prec); break; case 1: arb_sin(y, t, prec); arb_neg(y, y); break; case 2: arb_cos(y, t, prec); arb_neg(y, y); break; default: arb_sin(y, t, prec); break; } fmpz_clear(v); arb_clear(t); arb_clear(u); } void arb_sin_cos_pi(arb_t s, arb_t c, const arb_t x, slong prec) { arb_t t; arb_t u; fmpz_t v; if (!arb_is_finite(x)) { arb_indeterminate(s); arb_indeterminate(c); return; } if (arf_cmpabs_2exp_si(arb_midref(x), FLINT_MAX(65536, (4*prec))) > 0) { arf_zero(arb_midref(s)); mag_one(arb_radref(s)); arf_zero(arb_midref(c)); mag_one(arb_radref(c)); return; } arb_init(t); arb_init(u); fmpz_init(v); arb_mul_2exp_si(t, x, 1); arf_get_fmpz(v, arb_midref(t), ARF_RND_NEAR); arb_sub_fmpz(t, t, v, prec); arb_const_pi(u, prec); arb_mul(t, t, u, prec); arb_mul_2exp_si(t, t, -1); switch (fmpz_fdiv_ui(v, 4)) { case 0: arb_sin_cos(s, c, t, prec); break; case 1: arb_sin_cos(c, s, t, prec); arb_neg(c, c); break; case 2: arb_sin_cos(s, c, t, prec); arb_neg(s, s); arb_neg(c, c); break; default: arb_sin_cos(c, s, t, prec); arb_neg(s, s); break; } fmpz_clear(v); arb_clear(t); arb_clear(u); } flint-3.1.3/src/arb/sin_cos_pi_fmpq.c000066400000000000000000000107061461254215100175060ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static int use_algebraic(const fmpz_t v, const fmpz_t w, slong prec) { fmpz q = *w; int r; if (COEFF_IS_MPZ(q)) return 0; if (q <= 6) return 1; r = flint_ctz(q); q >>= r; if (r >= 4 && prec < (r - 3) * 300) return 0; if (q > 1000) return 0; if (prec < 1500 + 150 * q) return 0; return 1; } void _arb_sin_cos_pi_fmpq_oct(arb_t s, arb_t c, const fmpz_t v, const fmpz_t w, slong prec) { if (use_algebraic(v, w, prec)) { _arb_sin_cos_pi_fmpq_algebraic(s, c, *v, *w, prec); } else { arb_const_pi(s, prec); arb_mul_fmpz(s, s, v, prec); arb_div_fmpz(s, s, w, prec); arb_sin_cos(s, c, s, prec); } } void _arb_sin_pi_fmpq_oct(arb_t s, const fmpz_t v, const fmpz_t w, slong prec) { if (use_algebraic(v, w, prec)) { _arb_sin_pi_fmpq_algebraic(s, *v, *w, prec); } else { arb_const_pi(s, prec); arb_mul_fmpz(s, s, v, prec); arb_div_fmpz(s, s, w, prec); arb_sin(s, s, prec); } } void _arb_cos_pi_fmpq_oct(arb_t c, const fmpz_t v, const fmpz_t w, slong prec) { if (use_algebraic(v, w, prec)) { _arb_cos_pi_fmpq_algebraic(c, *v, *w, prec); } else { arb_const_pi(c, prec); arb_mul_fmpz(c, c, v, prec); arb_div_fmpz(c, c, w, prec); arb_cos(c, c, prec); } } static unsigned int reduce_octant(fmpz_t v, fmpz_t w, const fmpq_t x) { const fmpz * p = fmpq_numref(x); const fmpz * q = fmpq_denref(x); unsigned int octant; flint_bitcnt_t vval, wval; if (*p > COEFF_MIN / 8 && *p < COEFF_MAX / 8 && *q > 0 && *q < COEFF_MAX / 4) { slong pp, qq, ww, vv, tt; pp = *p; qq = *q; tt = pp * 4; ww = tt / qq; vv = tt - qq * ww; /* compute correct (floor) quotient and remainder */ if (vv < 0) { ww--; vv += qq; } octant = ((ulong) ww) % 8; ww = qq * 4; if (octant % 2 != 0) vv = qq - vv; if (vv != 0) { vval = flint_ctz(vv); wval = flint_ctz(ww); vval = FLINT_MIN(vval, wval); vv >>= vval; ww >>= vval; } fmpz_set_si(v, vv); fmpz_set_si(w, ww); } else { fmpz_mul_2exp(w, p, 2); fmpz_fdiv_qr(w, v, w, q); octant = fmpz_fdiv_ui(w, 8); fmpz_mul_2exp(w, q, 2); if (octant % 2 != 0) fmpz_sub(v, q, v); vval = fmpz_val2(v); wval = fmpz_val2(w); vval = FLINT_MIN(vval, wval); if (vval != 0) { fmpz_tdiv_q_2exp(v, v, vval); fmpz_tdiv_q_2exp(w, w, vval); } } return octant; } void arb_sin_cos_pi_fmpq(arb_t s, arb_t c, const fmpq_t x, slong prec) { fmpz_t v, w; unsigned int octant; fmpz_init(v); fmpz_init(w); octant = reduce_octant(v, w, x); if ((octant + 1) % 4 < 2) _arb_sin_cos_pi_fmpq_oct(s, c, v, w, prec); else _arb_sin_cos_pi_fmpq_oct(c, s, v, w, prec); if ((octant + 6) % 8 < 4) arb_neg(c, c); if (octant >= 4) arb_neg(s, s); fmpz_clear(v); fmpz_clear(w); } void arb_sin_pi_fmpq(arb_t s, const fmpq_t x, slong prec) { fmpz_t v, w; unsigned int octant; fmpz_init(v); fmpz_init(w); octant = reduce_octant(v, w, x); if ((octant + 1) % 4 < 2) _arb_sin_pi_fmpq_oct(s, v, w, prec); else _arb_cos_pi_fmpq_oct(s, v, w, prec); if (octant >= 4) arb_neg(s, s); fmpz_clear(v); fmpz_clear(w); } void arb_cos_pi_fmpq(arb_t c, const fmpq_t x, slong prec) { fmpz_t v, w; unsigned int octant; fmpz_init(v); fmpz_init(w); octant = reduce_octant(v, w, x); if ((octant + 1) % 4 < 2) _arb_cos_pi_fmpq_oct(c, v, w, prec); else _arb_sin_pi_fmpq_oct(c, v, w, prec); if ((octant + 6) % 8 < 4) arb_neg(c, c); fmpz_clear(v); fmpz_clear(w); } flint-3.1.3/src/arb/sin_cos_pi_fmpq_algebraic.c000066400000000000000000000114671461254215100215040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "arb_poly.h" #include "arb_fmpz_poly.h" /* for minpoly */ void _arb_cos_pi_fmpq_algebraic(arb_t c, ulong p, ulong q, slong prec) { /* handle simple angles using exact formulas */ if (q <= 6) { if (p == 0) { arb_one(c); } else if (q == 2) /* p/q must be 1/2 */ { arb_zero(c); } else if (q == 3) /* p/q must be 1/3 */ { arb_set_ui(c, 1); arb_mul_2exp_si(c, c, -1); } else if (q == 4) /* p/q must be 1/4 */ { arb_sqrt_ui(c, 2, prec); arb_mul_2exp_si(c, c, -1); } else if (q == 5) /* p/q must be 1/5 or 2/5 */ { arb_sqrt_ui(c, 5, prec + 3); arb_add_si(c, c, (p == 1) ? 1 : -1, prec); arb_mul_2exp_si(c, c, -2); } else if (q == 6) /* p/q must be 1/6 */ { arb_sqrt_ui(c, 3, prec); arb_mul_2exp_si(c, c, -1); } } /* reduce even denominator */ else if (q % 2 == 0) { slong extra = 2 * FLINT_BIT_COUNT(q) + 2; if (4 * p <= q) { _arb_cos_pi_fmpq_algebraic(c, p, q / 2, prec + extra); arb_add_ui(c, c, 1, prec + extra); } else { _arb_cos_pi_fmpq_algebraic(c, q / 2 - p, q / 2, prec + extra); arb_sub_ui(c, c, 1, prec + extra); arb_neg(c, c); } arb_mul_2exp_si(c, c, -1); arb_sqrt(c, c, prec); } else { /* compute root of the minimal polynomial */ slong start_prec, eval_extra_prec; fmpz_poly_t poly; arb_poly_t fpoly; arf_t interval_bound; arb_t interval; arf_init(interval_bound); arb_init(interval); fmpz_poly_init(poly); arb_poly_init(fpoly); if (p % 2 == 0) fmpz_poly_cos_minpoly(poly, q); else fmpz_poly_cos_minpoly(poly, 2 * q); eval_extra_prec = fmpz_poly_max_bits(poly) * 2; /* heuristic */ eval_extra_prec = FLINT_ABS(eval_extra_prec); arb_poly_set_fmpz_poly(fpoly, poly, ARF_PREC_EXACT); /* todo: smallify for accuracy */ start_prec = 100 + eval_extra_prec; arb_const_pi(c, start_prec); arb_mul_ui(c, c, p, start_prec); arb_div_ui(c, c, q, start_prec); arb_cos(c, c, start_prec); arb_mul_2exp_si(c, c, 1); /* poly is for 2*cos */ if (100 + eval_extra_prec - 10 < prec) { arb_set(interval, c); mag_mul_2exp_si(arb_radref(interval), arb_radref(interval), 1); _arb_poly_newton_convergence_factor(interval_bound, fpoly->coeffs, fpoly->length, interval, start_prec); _arb_poly_newton_refine_root(c, fpoly->coeffs, fpoly->length, c, interval, interval_bound, eval_extra_prec, prec); } arb_mul_2exp_si(c, c, -1); fmpz_poly_clear(poly); arb_poly_clear(fpoly); arf_clear(interval_bound); arb_clear(interval); } } void _arb_sin_pi_fmpq_algebraic(arb_t s, ulong p, ulong q, slong prec) { if (q % 2 == 0) { p = q / 2 - p; while ((p % 2 == 0) && (q % 2 == 0)) { p /= 2; q /= 2; } _arb_cos_pi_fmpq_algebraic(s, p, q, prec); } else { _arb_cos_pi_fmpq_algebraic(s, q - 2 * p, 2 * q, prec); } } void _arb_sin_cos_pi_fmpq_algebraic(arb_t s, arb_t c, ulong p, ulong q, slong prec) { slong wp; if (q <= 6) { if (p == 0) { arb_one(c); arb_zero(s); return; } else if (q == 2) /* p/q must be 1/2 */ { arb_zero(c); arb_one(s); return; } else if (q == 4) /* p/q must be 1/4 */ { arb_sqrt_ui(c, 2, prec); arb_mul_2exp_si(c, c, -1); arb_set(s, c); return; } } wp = prec + 3; /* prefer the formula with less cancellation */ if (p <= q / 4) { _arb_sin_pi_fmpq_algebraic(s, p, q, wp); arb_mul(c, s, s, wp); arb_sub_ui(c, c, 1, wp); arb_neg(c, c); arb_sqrt(c, c, prec); } else { _arb_cos_pi_fmpq_algebraic(c, p, q, wp); arb_mul(s, c, c, wp); arb_sub_ui(s, s, 1, wp); arb_neg(s, s); arb_sqrt(s, s, prec); } } flint-3.1.3/src/arb/sin_cos_tab.c000066400000000000000000007023111461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #if FLINT_BITS == 64 #define Z2(a,b) UWORD(0x ## b ## a) #else #define Z2(a,b) UWORD(0x ## a), UWORD(0x ## b) #endif #define Z8(a,b,c,d,e,f,g,h) Z2(a,b), Z2(c,d), Z2(e,f), Z2(g,h), const mp_limb_t arb_pi4_tab[ARB_PI4_TAB_LIMBS] = { Z8(e6cc254b,db7f1447,ced4bb1b,44ce6cba,cf9b14ed,da3edbeb,865a8918,179727b0) Z8(9027d831,b06a53ed,413001ae,e5db382f,ad9e530e,f8ff9406,3dba37bd,c9751e76) Z8(602646de,c1d4dcb2,d27c7026,36c3fab4,34028492,4df435c9,90a6c08f,86ffb7dc) Z8(8d8fddc1,93b4ea98,d5b05aa9,d0069127,2170481c,b81bdd76,cee2d7af,1f612970) Z8(515be7ed,233ba186,a090c3a2,99b2964f,4e6bc05d,287c5947,1fbecaa6,2e8efc14) Z8(04de8ef9,dbbbc2db,2ad44ce8,2583e9ca,b6150bda,1a946834,6af4e23c,99c32718) Z8(bdba5b26,88719a10,a787e6d7,1a723c12,a9210801,4b82d120,e0fd108e,43db5bfc) Z8(74e5ab31,08e24fa0,bad946e2,770988c0,7a615d6c,bbe11757,177b200c,521f2b18) Z8(3ec86a64,d8760273,d98a0864,f12ffa06,1ad2ee6b,cee3d226,4a25619d,1e8c94e0) Z8(db0933d7,abf5ae8c,a6e1e4c7,b3970f85,5d060c7d,8aea7157,58dbef0a,ecfb8504) Z8(df1cba64,a85521ab,04507a33,ad33170d,8aaac42d,15728e5a,98fa0510,15d22618) Z8(ea956ae5,3995497c,95581718,de2bcbf6,6f4c52c9,b5c55df0,ec07a28f,9b2783a2) Z8(180e8603,e39e772c,2e36ce3b,32905e46,ca18217c,f1746c08,4abc9804,670c354e) Z8(7096966d,9ed52907,208552bb,1c62f356,dca3ad96,83655d23,fd24cf5f,69163fa8) Z8(1c55d39a,98da4836,a163bf05,c2007cb8,ece45b3d,49286651,7c4b1fe6,ae9f2411) Z8(5a899fa5,ee386bfb,f406b7ed,0bff5cb6,a637ed6b,f44c42e9,625e7ec6,e485b576) Z8(6d51c245,4fe1356d,f25f1437,302b0a6d,cd3a431b,ef9519b3,8e3404dd,514a0879) Z8(3b139b22,020bbea6,8a67cc74,29024e08,80dc1cd1,c4c6628b,2168c234,c90fdaa2) }; const mp_limb_t arb_sin_cos_tab1[2 * ARB_SIN_COS_TAB1_NUM][ARB_SIN_COS_TAB1_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) },{ Z8(c584231f,42c62544,77e886cc,aa20f9f8,fe4f25a3,210a5354,2c1d4109,1721956d) Z8(e9e36b4d,c4405259,25cbf0c7,20e25319,b26e498b,6a76a798,55577777,00ffffd5) },{ Z8(0370b3ba,94cd273e,2b207969,23a42900,14c6dcb3,23a6dbba,dbd88646,159e76d5) Z8(c276c47f,596a5b46,b54082cd,09039032,f7502b17,a4fbefbe,0aaaaa4f,ffff8000) },{ Z8(caec7acc,0d534b7e,4ae2e1bb,d3da4dc1,c8be6a05,16fa88a2,4353efc3,20596653) Z8(cd9c4aa4,943448d9,32d90612,ca4a3d86,1221010c,6e8744e6,aaeeeee8,01fffeaa) },{ Z8(e7c976ee,c55d8730,f47670bb,d4ba6011,ffc81fb4,d9fe3873,c6c9dd2e,f9b9ba8e) Z8(4c4ab792,64b0f827,585b1e5f,283c5951,b5b41832,4034032d,aaaa93e9,fffe0000) },{ Z8(8fdee34a,3fc81c11,4ce297c3,b59ee6f6,fb0e8d78,082af7b6,821e7854,3584d0b3) Z8(11de693e,b5ab634a,85d81bd2,cef9d52c,7e126af1,5082ea0d,020665f7,02fffb80) },{ Z8(a40379e7,ad1cfcf5,b7ac5136,6de072e9,f4ad5f6b,18c2a1eb,3c74e210,4a1df9d1) Z8(d94391b8,36bc82aa,f68391c5,18efb2d1,090fa8bf,f6750326,5ffefccc,fffb8003) },{ Z8(fdaf9747,8e9b8e30,566197ee,72435801,c62e2cf7,eb4498fb,5ea2034d,a1bd4211) Z8(985b1d56,077ec1bd,f5624024,62c181f7,1f113dca,aa938cac,5dddda9d,03fff555) },{ Z8(b77519c6,3a897fe0,6eb671be,01e286c4,edc98229,4942277e,e7d32643,9b3ed7ad) Z8(6ac7f294,121a3235,8d241e94,104dd21b,de6ace45,4514074b,aaa4fa51,fff8000a) },{ Z8(e3463014,cf3d5b67,78186dc9,3801a36e,ce2161f8,0373d0bf,6276fde2,4cf23b8a) Z8(f0bfed96,50fae5a7,7c6e0e96,4a14e87a,cccea63e,19b3218a,c4b545d5,04ffeb2a) },{ Z8(0aa8cc75,71ebe6b5,3da0bebf,2c3d56ff,aeedaac3,0b0e9804,0840625f,1e268993) Z8(1f19c22d,8bbdf397,c116c793,644d7b15,9a68ae63,21ed0e0d,0a94f726,fff3801a) },{ Z8(5bacb364,5423d214,a7f1a284,d474869f,89626be2,c4224296,a2fb6ce6,8fda35a7) Z8(4ec65078,057e5d7c,5e37ac6b,848a2e8e,27336737,efe2b515,40cc9541,05ffdc00) },{ Z8(555152bc,0b70a74a,ba9a9f17,8d823963,f1545bab,8a7f9869,ae2388f8,29fa7dd4) Z8(24020b86,f3a5aeed,50c100b1,135c2400,f79e495c,db5d0d2e,ffbf335c,ffee0035) },{ Z8(2e956a62,54707381,b634a0df,4304d14f,986f637c,02c0513f,a293758b,51d78b0e) Z8(a7332c80,bcb27f61,d2358820,03e277d3,4f02b7c5,f20c232a,e163a0dd,06ffc6d5) },{ Z8(b2849471,f41b4606,fa909aed,3958ae98,d8b099fd,0463c8a9,5a06813c,e1bc72de) Z8(9bd85d30,80c5648e,373fe8f1,4ab4504c,5a0fbdb7,382f503a,0a074478,ffe78064) },{ Z8(d76c7aa2,144d32b9,855bd545,58df22c8,b8e9f930,cc5797fe,df450ee3,b1e32374) Z8(5a7ebde5,7c101591,c611113c,e5790d2e,b51e4655,2bf904dd,bbba1ba3,07ffaaab) },{ Z8(b371a8ac,4d44035b,0403f94b,fc753c97,a918e8cd,f252a14b,87eae02a,c062a312) Z8(178307b4,79a38edb,4a661fc5,419c52ed,94946fb9,576da4ec,a93e9589,ffe000aa) },{ Z8(c61d8c05,a71c4e0e,0cfe31ff,702a3eb2,624cf7b0,a4bc4379,e61acfcd,f7950005) Z8(89a8a121,ff98c884,e65f65ab,f5141b95,98feaf9e,e9c9543e,ec0f7e36,08ff8681) },{ Z8(de7dd82e,dfe5e5f2,4874af27,0dee380e,6e9d51d0,f5afeb4b,7508921a,f6287824) Z8(80ed3526,bf270888,13470ce3,34833556,0a46279e,cff60078,5d1de75e,ffd78111) },{ Z8(f2acdfb5,ad9a1227,247ae519,6c2ccd63,7213726b,74fb0fff,a766e63c,1d510a43) Z8(7192725d,98c546be,66df98bd,36a42cf3,1c114647,ec54203d,96a2ea94,09ff5958) },{ Z8(cf146d17,e913f328,856c1462,dca08a12,309a4596,53f62a16,df4bb46b,f9409165) Z8(a0172d2f,485f7aee,45d15a02,ebe3652d,cdf8fb4f,8fa5f362,a53dd0cc,ffce01a0) },{ Z8(b618ab25,3f4a3c93,92c9dbc5,318e0099,2596d03f,91650a8a,80c84678,6e74cb9b) Z8(4d8a9237,43fe8112,a06ac39b,5954c63e,6f26ef10,f4dc6f44,e8b307ba,0aff222f) },{ Z8(686b0cf2,d2546d0a,e9821f82,e2067cbe,8a475a5b,3734a811,a44e2e43,7aebede2) Z8(ad087eb2,1cabe8c4,f7d76b34,2c96bc25,4e76a53b,f9d36cda,010e3f13,ffc38262) },{ Z8(5e326a2e,e353aa84,9dafa9fb,15b99cf8,41a5a79a,85dbb05e,3d0c7ad8,55017ddb) Z8(28e8fa0a,641e30ad,34d0d55c,75f5ca5a,cd0cc475,cc841722,197dd454,0bfee008) },{ Z8(0bde6e4e,85e59162,283b77ba,915b3322,e201480c,be6ad5ee,7acfde55,a0af570b) Z8(c4cb657e,1bf14a18,ee13e78a,299a949c,2a141836,c4a9f9b7,efccf674,ffb8035f) },{ Z8(27f3831d,d9dc50c1,0249e0a1,e39058d0,45873b27,a1436733,362605af,b5f0607e) Z8(87e6150e,700bc36e,47457856,2456f2a8,0a6fa210,f4e5d45a,6b406f68,0cfe91e1) },{ Z8(c7c18c80,c8c66321,5e9e4705,3e2ac7dd,0e50ea29,de046e8f,730584ac,4c07615d) Z8(1ccbf3a3,5bdbd6ab,761964e8,c5ccace4,59264716,14dad735,f07b12f0,ffab84a5) },{ Z8(05bc9d34,5af7980e,490e1805,24f43ec0,a992b594,ae530c17,3acffe21,9d5179da) Z8(16700538,e7b691c7,ed0929d7,1fb4cf74,fc8d840b,393f40f6,2c36d606,0dfe36bc) },{ Z8(02f2378b,14d13a0a,c6e4611c,9ed8df66,b74f80cc,2b81821c,3960c270,6c33282f) Z8(ec6120da,c19da3e5,004fb872,de514ab6,e6638e54,56dbddc0,81d18948,ff9e0640) },{ Z8(430cc0de,34eef08c,3a1329bd,4616f118,cf066ab4,1e1e1b58,607948b5,76cddbec) Z8(8c4d75af,21e7b727,f0bb7a22,6ea98795,80c49f44,62926993,b79b94f2,0efdcd98) },{ Z8(1ee1bfb3,cb84531b,f39b1732,06cf65a1,12243c85,a1fae32c,50ea1854,b8add525) Z8(87f658b2,bbef43f5,a033819b,eabd3c9a,4f571255,54b47558,2234a849,ff8f883d) },{ Z8(7e56278a,89187c07,eb2f7c1d,707140fb,f05f828c,7df2b307,50480352,ccb76f0a) Z8(d8b57b62,c2fd5380,b9cbf2d7,fb074dfb,692d4aca,5d259b2f,76a76d5a,0ffd5577) },{ Z8(a4b2a421,ccd95f9d,8283e803,a116e80b,db02969c,383c3ab7,342fe205,b609267a) Z8(c3e646d1,fff062e6,5a2928bd,f80466e8,4de215b8,070f7328,4fa69a65,ff800aaa) },{ Z8(ea105cbf,8f242ded,485f60a4,729705b9,b64f58a0,56468049,8a56a73f,bd523e59) Z8(f95f4db6,d07bd440,069af9be,5d56f1e0,2310b0a2,2ac69219,e190eb84,10fccd58) },{ Z8(25c9cc84,9d41b74d,7ec991a3,1626bf29,3907baf5,5b6acc2d,d3ae574f,6e8610d8) Z8(3912767f,c39d5e77,5162f111,b9224777,9d896f22,9ff3ef71,87b8e7b2,ff6f8d97) },{ Z8(af957b22,65e00256,9caf7677,a502d63f,74ed61fe,43d02548,93a4f706,6f996eaa) Z8(fa8e70ea,dc423804,1333b122,9d01f567,06c367f3,0b346431,808bee83,11fc343d) },{ Z8(2926e2b2,bec7bb97,b1274918,930d59c0,d84a3e5c,3a2429f0,8874ff44,cd25c62c) Z8(8464f2dd,421cc3f5,c0fe04fe,e564aa36,31dc4f1c,4d24d3d5,477cf85e,ff5e1115) },{ Z8(b1bf37d2,66af74fb,9aff687a,3897d0c1,30a9ff12,a76a1900,0b45a631,01b083c2) Z8(1cb8e835,ef221a58,268cbc2e,d6c70725,b448ff77,5311496b,ecc91fee,12fb8925) },{ Z8(f95d4ba4,1e85b5a2,e0692cc8,f52a985a,8d4a5c5f,ce9ba136,78af5602,673fc263) Z8(0d809f91,ba2688f6,f6a90446,e48a761a,aadeb56b,2fb61530,0b739799,ff4b9535) },{ Z8(ab68b561,5bfb6a58,1993388b,da0d0faa,3ae46c1f,9a61bb82,27c3ed45,4ea73543) Z8(3f537695,d0227066,f70faa38,058ee45e,e5d278c9,79bab59a,d1755a9b,13facb12) },{ Z8(286858cd,479546ad,cfc3c87e,e61cffa9,1a4c8daf,ed7df6d7,99386baf,43698254) Z8(daecd3a9,3d4c4669,ae6d2f79,b9df9716,834be062,05e641b4,4f7b771a,ff381a09) },{ Z8(4e732490,d0c331fc,5c6f829c,aa0498aa,33c32e71,7c57c71d,5d6bc519,d10b0cca) Z8(d9021f07,5163be06,20dc13d8,20864f53,69d7daa8,f762fe33,ecb8ff5b,14f9f904) },{ Z8(7c6947be,81cb80a2,6d18f2c9,1b9c4b49,de75722f,b08ba501,305b0279,c94d2283) Z8(c0d3c8c0,bb3a52b4,0e832d8a,ec6f57ab,da869d0c,03ba444f,8ebeb340,ff239fa5) },{ Z8(f59870b9,b0304ef0,18049042,86b6ffd7,06c44e8a,2b76f95f,17ee1716,3e712d95) Z8(8c318a2b,39d3e770,62f294a2,70bc6bdc,bbf76e6d,9ec3f505,10b736bf,15f911fd) },{ Z8(548b838e,41e7e7e7,57082561,bdbdb5b6,ba2dd0f9,d97a71c7,0fcd03fc,f77b6923) Z8(b329d0a7,5a664a6b,bd40392d,c5c1d16a,b5fd8a7d,5636fa83,439f57ea,ff0e261e) },{ Z8(83f689ea,efe10703,1c1f1a6c,4384b68b,6e9d52a3,596e264f,0e007ece,18c8e97e) Z8(af07ad8b,a57447cf,1a5a85de,6b4eba44,c92cdcce,30bd63b0,248d1edc,16f814fc) },{ Z8(4523e228,bc493f2b,c2d10cdd,234f720b,17b62a10,8cb91c0a,5f4a7270,8cda3c77) Z8(b5ed0cf0,462f9e3b,da551dd2,bbc1fd4c,7cf9f237,cc5f79cb,e7a2e617,fef7ad88) },{ Z8(0566391d,9e5c45f0,77b2a1c0,669ee14c,a4e4c850,27c6f292,1adeb42c,0a60fc19) Z8(db21f7ef,cdeae791,c393f5aa,e59085f4,501a1007,fc2d1800,2550e41a,17f70103) },{ Z8(76835799,629120d0,53e6ac1a,dacc91af,01b35920,6ffb549f,ef3f03ff,dfef1c85) Z8(d817f7af,f56a11fe,b961faad,c3813d8e,1b6b28df,2056a6bf,f35cda63,fee035fb) },{ Z8(a4e73e3b,d40b012f,4257c48c,70ed1cce,86889664,15230d12,ebeb5525,fea63914) Z8(17b61e98,efa07ec7,fc8c685d,0a90054e,3e43dc1f,7148236f,2710c40d,18f5d513) },{ Z8(62ed8ec0,209158eb,489539ab,04833c81,6cc0ec19,2a3dda43,d49c3386,a32002e2) Z8(69e18b9c,eabe2efd,e241ecf9,0c2469ee,f49478bd,5a260aac,de583471,fec7bf8e) },{ Z8(8d4da807,4e0d8065,b9304511,a5f02377,f85f6690,402559e8,1b1db1c3,436d35e0) Z8(d31d8bbd,9ffd4ea0,4bce6926,f8f43d55,77057fed,a5b5fab0,55d1f949,19f4902d) },{ Z8(a553bef3,7c7f2939,d24f4f92,62592faf,b5e4b3a8,fd12d6fa,fecfc368,15101e2f) Z8(9992d651,8283e936,8db3438a,e3ad0116,683996b6,c4b9a583,1effff68,feae4a5a) },{ Z8(4f045470,63bfce84,3a3e8fd7,73fb16e0,8787f997,36cec84b,ac97d990,b88ad604) Z8(c06aa038,dc416b66,f0232d76,2c5f9dd5,8fc2d005,dda62f74,f68f8f4f,1af33152) },{ Z8(5c98ca1c,87228a90,a03f5e42,77e3e076,b4040fb8,6e7e65db,9e7afdb9,e635b654) Z8(662af19e,d885a3f0,7bd7541f,0e5506fc,68251eef,ec97d26d,2a86db87,fe93d677) },{ Z8(c7066510,bbbd94dd,240c2ef3,f4e632dc,93169355,2189fab6,36431a8c,8d20af40) Z8(982e55fc,908d103d,4b090171,127f3274,331f2958,461077a9,68391d7a,1bf1b785) },{ Z8(5d948d86,6ee2bf5b,aec45210,fb4dc741,503e607f,c4da16a0,cc9ce305,b0378c13) Z8(6d8c8afb,f818c271,3aa13760,d38361e9,35611b2a,1ebc368c,74cd88f5,fe786400) },{ Z8(e33a955f,cf3546b8,949a11d7,8120ca71,446966a9,0f24ced4,399b2ee4,04d1d814) Z8(f9059dcc,1706070b,55e54f48,3ffd150f,13b03e4d,25448230,24b167f8,1cf021c6) },{ Z8(adf46942,a2388da1,d5466af5,64e86d26,2e9ab459,21f5fbd0,32b13254,b80a206a) Z8(3edc9ebe,ba309ffe,db072b72,3a34f6a2,0869db87,dcc41bda,704873df,fe5bf311) },{ Z8(94df5b1e,12ca6964,3abc9187,63e0408d,ae61d6e3,e44efc1a,39d75460,0edc3bbb) Z8(63c8027d,93b7af14,c6e6a3e6,b4bff38c,d31ab219,e0e3a091,c1cce5d5,1dee6f16) },{ Z8(460094ec,4b0d0c5b,18b6a474,8cc0c65a,84003219,81ccc41f,6b5e91d6,b8b4ca4a) Z8(c5758c70,eb1cd1ae,52fc525c,bd08c2eb,d0a10db2,ba488fb6,8de4420e,fe3e83c6) },{ Z8(d086de7c,551fed65,5509260d,c756bd7e,fad0a838,52307b68,45a5e91d,a1a39aa5) Z8(0a1e26af,eeec4318,6e163f89,0a9f3865,7f667db7,53517588,f2502b13,1eec9e78) },{ Z8(201c25d8,5780059f,d13d9302,1c048b26,af78c89e,38d3c38e,66bb5421,c58b80ae) Z8(efab5ff3,e6e23df4,e0cfe54d,2df1cdc9,7d15c02f,15d61e3b,3ce961f5,fe20163d) },{ Z8(c3450e07,fa68567c,427dc1a3,e5bd5ed0,497e9b70,9c828f90,1ad10ae2,d190d545) Z8(59fd631e,007995f0,5e671884,5995027b,1f89f85a,069a8672,86ee35ca,1feaaeee) },{ Z8(b7a7f8bb,65f0ab60,6d2a89ea,f2a44834,6b128c15,b1146ebf,41c56b3b,34935607) Z8(e7026cf1,962ddb33,783f8310,649bab98,f6f18ce5,1e6a129d,eade9b6d,fe00aa93) },{ Z8(a62d54fb,8074f616,c56e9754,58170296,7aa0ca6f,79823197,d1890ddb,b83f4334) Z8(434101fd,1e3bd662,5d761f2a,0f709e0f,8dcb5faa,07bfa5dc,6f469d65,20e89f79) },{ Z8(17899f6f,507af05c,b2bb6bc7,24c81bd0,ca1a50f8,64f99661,5c027437,dd1725ca) Z8(09aae2da,dd89d1c9,3a1bcefd,a03a1762,228a7597,94b8c338,036aa233,fde040ea) },{ Z8(60d10493,9737abda,a47115de,1d5f2427,cafbe64b,2ead12fa,54b24032,63894f67) Z8(c133934d,468079cf,efa586a3,694337c5,7cf273ae,23439278,bae3a2ec,21e66f1b) },{ Z8(1aedb10c,e1d26be9,59389d07,5224f5ae,3f0163e4,b75f394f,87a792da,e12ae5f5) Z8(3e3042b8,0a1c0555,c9f01e19,bc7d13e5,56262d4b,b5be9ecb,f034aa43,fdbed95f) },{ Z8(40622711,76bd567a,aef43b37,050f8dd6,2840b796,5522c0c0,782d4de8,5420c993) Z8(04842db9,f3c3b91b,8f6c1556,b6d9b1f0,99b81198,7ac4b9eb,9a382164,22e41cd7) },{ Z8(8f82702f,ffee6801,88f5b597,1caa9490,6a1a5d64,076e9dd2,2df5461e,36ebb7c6) Z8(a1cf8174,5b28854f,d4b33767,152f1a34,a30f5a1a,ba3d7221,18c3fe32,fd9c7417) },{ Z8(d37be716,e3e0b905,ad7c3033,a866ded9,2fd17173,f608a6bd,22b21c87,ac146ba0) Z8(2e7a881e,d9f0deda,bf5269e0,4194f3c5,b2da517a,8357b344,5f9d5d48,23e1a7af) },{ Z8(14c65cbf,10a0db89,bd87f6a1,e60e5f47,f5b973c1,df989770,2865dcb2,0e9b3e85) Z8(1f0f43d9,56dba79a,76b5a002,578c42df,625d2cc1,54c7b317,e25e97ab,fd791131) },{ Z8(3b5b78e1,321b7100,83db7f75,8e73b897,b9ab8d58,d7226748,60e55315,d6d78c4b) Z8(932ecb31,4e88cb59,f77eedc7,8c078c50,0e166fd3,9d3f9956,8050b219,24df0ea5) },{ Z8(9d20a707,c6cf89a1,10dbae84,c335a2bd,1bd2260f,b699ff0b,08b4d627,f30b13ef) Z8(ee6341b3,50aa7578,1866de04,86962c63,71fb1b51,95db8a61,afe6ba2a,fd54b0d3) },{ Z8(8284ef6a,a4bc2772,17a3af8f,d7493d3e,0792be5c,647a8999,9ea0c655,7420e9cc) Z8(68f35665,8b1a1129,b7a1e36e,959ee0bf,fd438cf5,9787d108,95711d0d,25dc50bc) },{ Z8(f5b07c65,97f130c9,906afbd4,38e9939f,e7096102,6548dd92,358ce0f0,6bc837c4) Z8(6d03cb00,bc524376,f1014b0f,a7b873af,98f79caa,9b4dda2f,e1b79020,fd2f5320) },{ Z8(290eddf7,daedd153,03c15f3d,873c5939,4ed3dfbe,68f42a67,c974b4ef,950f973e) Z8(8d13bd33,803887e4,343a06b5,e9fef5cf,03e64f6a,94e6d8f4,5cfca3da,26d96cf7) },{ Z8(7f9a2933,98aef8d1,f9a1cf4d,9b2b6c98,86d1360f,540b614a,9142fb26,535b01bf) Z8(b523e6eb,f0f6f474,c37c929d,fc113842,343f9dfb,6de19f58,d580ca98,fd08f83e) },{ Z8(5303bf5b,945bf567,97cc631a,101fee1a,c9a382ba,946c7b36,d8e715c9,bb6bdc22) Z8(6234ffde,9b8db9d3,b56a489e,38c5142b,5c87d594,eb335b36,bacd96a3,27d66258) },{ Z8(73c8905f,3b423688,f9e8c865,269f96c0,271485b0,a5a9a65c,649ac8f6,9813c9cb) Z8(ec796a24,10e95144,6f922acc,9dc71aa1,8c45bf0a,6d60c76e,e621438b,fce1a053) },{ Z8(b686bff2,ddca4706,e3a38c84,9ef55bf4,3fb654f1,3d5af067,d686df53,df56e55f) Z8(4d5c4e34,24dc8f60,04c9388f,e7c0cc0c,d52615ec,bb93bcf6,b997ac0a,28d32fe3) },{ Z8(3328b8b1,e961cbf7,2fc12eb2,f11a59f9,ba59a1a1,cad45d81,dc86617e,4ad98645) Z8(c87549b9,f8f4e14b,005fa5d6,429906c2,611352cb,a8dff287,6b80a305,fcb94b87) },{ Z8(0e821d24,ec5c5c2e,232db060,8bea56a6,462ff518,5280d9b7,ce1fb70d,53ff7c6c) Z8(1450f62e,226e410b,d105473b,34906c3d,cbf04269,276cab01,8be4f665,29cfd49b) },{ Z8(079516b4,a3670a4a,018dbf1c,bf4affe5,bb1c37e8,c3c52bc8,7a3cfd2b,acdb4030) Z8(fa50a6c7,e08019bf,07d22e19,ddb0cc4c,0d9fdf1f,7e05962b,ba680741,fc8ffa01) },{ Z8(69cae50c,52c42911,719180a3,61970d72,213f2b77,77dbf7ba,0d5430fd,d7f2d28d) Z8(9063d905,815f583f,2d073b04,7b270c83,5038d871,2cec8306,8d12b11f,2acc4f83) },{ Z8(e943c791,24da9455,8ed481c8,5022655d,b3145951,61574cf9,9e4bd137,69bdc509) Z8(50ea4f08,89aa03d0,51b6d271,171463e1,3367cc21,d7359adb,2459afe1,fc65abec) },{ Z8(a673db34,272c4b73,f8226336,a2aed2f6,c7b9d34e,af83672d,53bfbc62,f3b58a92) Z8(dbb9da49,736feb95,8c3244d4,b9faf564,b2514952,5de7ce03,424de548,2bc89f9f) },{ Z8(086825b4,e348ecce,1692070c,1b441897,bd7aeb72,01a567ed,0e3980c8,6bf361b8) Z8(0ed82b53,5d585585,f153a426,b5e59d3e,9d439e1d,5d63d99a,f767ac73,fc3a6170) },{ Z8(530e7239,b201f60d,38f2e7cf,e1d3851d,3c6eaf0f,7bb2a34b,db3f48a1,aea4099d) Z8(9ba9c0ae,df615113,c430d741,f7353fa0,ce212c18,cc8e22c0,5b8fe451,2cc4c3f2) },{ Z8(80a5e0c0,4fba1d9b,a61a7bd6,a9aaadaa,2b028755,a8be45ed,275f1dce,c467ff32) Z8(366e5194,dcb67a39,84cf822c,bda2a6bd,bd807d00,ef08d62f,7e098e5d,fc0e1abb) },{ Z8(2af80f28,9db27e1a,566f6f41,52929550,9b0559f4,536a1319,cacb565a,da02c04e) Z8(48cae929,8e7827e0,cf58b12c,af47ed2d,f8db9df7,b34e8dd1,b49a97ff,2dc0bb80) },{ Z8(62ff4a31,0744c695,a089bb0f,6209a983,34ee4949,4b3acbe9,c0bb557f,b3c7b981) Z8(bbe9ce04,781f9821,3f676b47,cea20c8f,f4f6a457,aa43b8ab,fef11e70,fbe0d7f7) },{ Z8(353e0183,b81af745,4a9b2bc8,6ab49d86,b0103e78,c57717e3,1b15e006,4877f9a6) Z8(397b18a5,be0adc98,82b525d4,7cc342a6,ef093831,880eddf1,55f4a692,2ebc854e) },{ Z8(c2d2970a,3ceebc00,b7011917,547e18d0,81c6d2a6,e9df07a5,b7a65f52,7c027f28) Z8(ea98f374,5f617294,ecd06179,0b585e0a,1e8ccecb,d499e08c,bcde1633,fbb29953) },{ Z8(cebbb957,432de451,392a9edf,9420aa30,7b858240,ad4158c3,5151ea43,4b44a6ea) Z8(59a6b00e,2c05e4df,e0189ef7,769af396,2f856258,56a1c479,75e56a2b,2fb8205f) },{ Z8(f29c7c34,b36ec3de,a7ac174b,92950edb,f914f757,8c62b2e5,3bc76154,26e8b67b) Z8(9f43aa56,9b783f4f,e9cdb389,ea358867,697eea13,e6fe7924,f670dd2c,fb835efc) },{ Z8(472a11a6,b8f66361,5d3a47fb,494f448e,3931fe0a,d27caa6c,ca161ab7,13c532a8) Z8(8106cc5a,095add11,3cae53a0,beca2111,4ca9c252,6b2c6ec5,7970ba6f,30b38bb8) },{ Z8(78b64c55,3aac246b,aad59e35,f72f30a7,c15ef140,1bf9109a,023cc002,08b17312) Z8(a104d886,d793fac3,3cd2bc79,d6f332da,6481a438,00da3dc0,e5fc4a42,fb532922) },{ Z8(a29f44dc,17abf4ff,35c8dea0,d4052966,b362968f,ca06bed0,0c108e9c,c15d57c3) Z8(6e1da919,b0b3698d,983d7011,6eba6799,35671324,82ece9a2,f552876f,31aec65d) },{ Z8(0af47eb5,44175df9,0a31272f,1c486f4a,a2e217ae,3daf385c,57cf029a,cc413862) Z8(99005dec,a46c6843,df80d9c8,674a92b4,8ac5fd76,00ac1fe2,c156696b,fb21f7f5) },{ Z8(8641e1f4,a74b57a1,c69985c9,cdba1007,40a3e9aa,cd92e011,64e7d7cd,33611ab5) Z8(91848e48,726fb98e,8a96f45c,1d1bd8f9,a40755cf,e88f1581,aefa44d6,32a9cf54) },{ Z8(9da7b864,67a4a5e2,a905091a,7943f26f,be87f569,51c92769,42c011f6,e4cc980b) Z8(aef3677b,679371a0,8500ea7b,0006144d,3aeaec85,7c8dc77c,b9a845df,faefcba6) },{ Z8(4b8f6574,73876ee7,98f8fd28,c86d0e9f,71b6631f,7eec963c,fd47188a,3a188879) Z8(e0a7ed58,eabb82e8,938477ae,3f4639ce,4df4fa51,10f602c4,9d862467,33a4a5a1) },{ Z8(3041d24c,887c78bb,9c277e34,12363c24,6fce6d7e,2dd47028,334e579b,726c3301) Z8(bcf3676e,f7b7609b,6ecd1cc9,5bfd6829,8ea33ade,d069f01d,fb3cb8f1,fabca467) },{ Z8(f827078f,54af72e4,b15b1a67,76112e76,c54e6406,1c1cfe1f,973560ef,1a401513) Z8(bfbdd303,6f87055e,106bb22e,5635c551,12a7dd92,7e1308d5,eabe1ec4,349f4849) },{ Z8(17db4da8,eaa50adb,dde92e41,5bc2e23d,8af5a107,3d270829,ae903e3b,5106869f) Z8(8aeb28b0,30a13383,b05395da,bb0764f2,1a0a1321,73057b79,ad4e3dc8,fa88826c) },{ Z8(8aa21f3b,79a77c70,d15156dc,e12eb7ff,04062f5e,cf92d656,93e8ff18,8df5f4f0) Z8(886f715d,18b97f48,54555de5,59c98d4e,c8561de1,df12a0a4,f40ec999,3599b652) },{ Z8(204f1879,5560e0af,aacb0461,a7a378b7,9a119b9d,dbca10c1,bc18cad5,49953a09) Z8(7a380df9,65a2b8c6,ab0f4ccf,3d7470a4,6ae64d98,be1db5d7,f1d3ca27,fa5365e8) },{ Z8(eee0fc74,7c870012,e8745cf0,2cf1187e,a24e377d,cfe151f5,0f6564df,f5bfca8d) Z8(abfea583,956ad6a3,68abb74f,9034a33b,b1915674,97d0c986,4b83fa16,3693eec2) },{ Z8(0ee24e4e,74b214bc,ce7ff12a,0de8faf5,ee0defbe,f9dffbad,bb995d1a,c73c9949) Z8(f765bbd7,a78b42f8,aa305870,9907eda6,a320fc87,50cdc117,e54cac7f,fa1d4f11) },{ Z8(3f3dbaa9,271dbe0e,0dabe8ba,d8ee03d6,6c3015ac,2bc1ba1f,5232ea30,1bb9f1da) Z8(11c1cd24,2b496c6d,768f68c3,26ea336c,65582e45,0d2b53d8,b8c332ce,378df09d) },{ Z8(62fca407,508dd123,53b9335c,0d26d438,17a36a41,311495c3,b4ec686e,65e72f7d) Z8(bed24b63,7bde901a,e11e09fc,1fd7fa2f,5b5ed9c1,2e296bae,9e8b6f6f,f9e63e1d) },{ Z8(b18c367f,7450450b,1e1cf3c4,2a4964a3,e7463b2f,86ec0904,a6b43640,da605a0a) Z8(acc640bb,91dc8e20,84ab9fa6,45aaa1b2,733b4832,4867a39f,3a05dbfd,3887baeb) },{ Z8(38ab1d3a,0e905326,1862e65e,35d0ea9f,d21fa777,e39e98e2,7aca61a0,527af66b) Z8(110b0dd4,d9d81bff,44aec93a,e4aeb34b,df0f350c,b483e7fd,2e7fc2f9,f9ae3343) },{ Z8(414796c0,142875fa,76f2bbf9,8a242e2a,78ccdf68,c187e30c,0c85ca6b,473934e2) Z8(36a10ab1,03bc09a4,675ab855,b150c21a,1ca6a337,b97b21bc,0513453c,39814cb1) },{ Z8(329fd9c0,4129920c,264eb5e2,d50e1950,6e7e8818,8e5ee38b,61b9e6ca,aeb6e52f) Z8(9b148921,6b2288d0,875ae63d,fb0f8d5b,b054a932,842beada,9fff6b98,f9752eba) },{ Z8(9dd69757,6eeb4648,29e9c996,759dd204,3151d8ef,6345f815,4204a3aa,4a74f4b1) Z8(fe1e4d05,f1965677,6209b1e0,62b4daec,7b2fc27a,16996ee1,883a6fa4,3a7aa4f5) },{ Z8(65a9745f,173be354,c2959358,1ed16683,1356ee74,1a4ae06a,3f97918d,87e9c06a) Z8(98efcc1e,5f4527f5,1d0cbba5,b7a6b6fe,1a508f3d,6683b3c2,f78e376b,f93b30bc) },{ Z8(91df6e48,02edc2f9,b401611d,73942968,6624a6c5,42e4a4a5,e02d31f1,1412f8c2) Z8(0515c18c,e58cb847,fa64b086,087f1753,81f0d965,8ef9499c,6b4b9f66,3b73c2bf) },{ Z8(479b5441,91b850ed,501eb4d1,a20cc972,3e42faa1,4b9639bf,6742eeff,57cae032) Z8(50493ce6,5788a861,7354d426,1fc733d9,84b6cbed,40416c19,3324f9b9,f9003984) },{ Z8(102f656e,78624014,1791524a,115d9dbd,43af1d83,d54ddaae,90bb46fe,6357580f) Z8(ddac0faf,777e7b8a,c42c9398,47ccee4b,9c01c98f,bf48c0c6,9091b3ed,3c6ca515) },{ Z8(891856af,a661b9a4,948b8e0c,66621acc,1713922d,197348a4,d29335a8,4a819493) Z8(5477100c,b49275ff,8c42e7c4,c92921e4,6626660d,13522ad6,49f78cfc,f8c4494b) },{ Z8(b49f77da,07a9227b,5c15ea5c,f9650f9d,2c708ecd,4af0c5cc,ffaad557,ccc6dff0) Z8(309b626e,472d9d40,26609204,39a8a406,98aba330,0fca8546,15cb457a,3d654aff) },{ Z8(5277f985,7987684d,449bc9e1,e9692d7a,9faa7810,bb40dddf,97bc188e,c2c1d496) Z8(d3fcfe9c,78ba8a28,5ad99540,ffc95b27,5059a789,0e4ec582,2c39dbb2,f887604e) },{ Z8(d2a5f4ad,5c0f3956,a9386272,34c99185,5c19709e,d74d5d64,1e1c88ea,b9ef1b51) Z8(733e38cf,acee1e60,184d46f1,7c43acc7,ea47637d,5e90bf79,5523874f,3e5db383) },{ Z8(56742729,f138feb8,3d9e8edc,6614ca67,e5c62b8a,a83993a9,3d9a2eb9,499f7a33) Z8(721b6afc,fa60f463,24c78f58,5f1f1f68,db0c7d4a,a0ac7537,c2e3f02e,f8497ec9) },{ Z8(4067fb09,06ae637d,ab3570d8,bd2a7e39,50b49ce5,2b800c53,42a81914,3c7f2854) Z8(af9330f0,898d7086,8d7db525,dd567664,6a3d1635,13bd7b8e,e62aed75,3f55dda9) },{ Z8(3295498a,2b7c5621,9c7761bc,2bbdaa00,6bb135bf,3a867cc4,ee16d0b2,0795b84f) Z8(c944551c,3ef9ec13,9edc4a02,1426dbe7,5f94f8a4,83d33cb9,ef750ba7,f80aa4fb) },{ Z8(3c001d52,151ddfeb,5720449d,2b04dbb0,82e2af67,cf6bf73d,785b5de3,95279123) Z8(c0efcd45,b0842f93,c12eebc9,4f5a9ee4,31536996,fa1d5106,9ecf9510,404dc87a) },{ Z8(73b5c7ce,d4209413,cafadcc7,3cb81ac8,6965fecb,d0ba1d9c,82e6c127,c49edb12) Z8(26b105be,53bd1d9a,835f4c00,d0757657,b5d41038,a207f321,8bb5c4ba,f7cad323) },{ Z8(0b4e4419,f06bd15f,fd4cca47,52b82aa8,b1a42a7a,94dfd8df,5d54f535,006426fb) Z8(8c4705ae,2e3e370e,db527011,c0ba050c,1388dd47,73d62027,94556e64,414572fd) },{ Z8(816b3a64,4f297bd3,2fef2a05,275623c7,b15de5e9,079a929d,ad7486d6,0e2c1547) Z8(5371b897,3311b4ba,2aeb446b,8cb1ab82,91b7c5a6,bc9ee425,69792daa,f78a0980) },{ Z8(ac1bb344,0f70ba42,e6777e38,7fb2628a,15382fee,baa9fa64,d4fad9ad,ee9abeec) Z8(6941cb73,9f3401ee,d6b1c5a9,1ddd1523,c09cc1cb,e1415ed0,1c4e2773,423cdc3b) },{ Z8(c91fc0de,c8b61213,9c6f9ba5,d735d464,681ef963,6ccb8c3f,dcba28ff,a6349c9e) Z8(5385a006,952f5202,22a82e46,ae7728dd,c64325b9,ab3522e2,525d0291,f7484853) },{ Z8(4a086b50,9caaf926,0683ce54,95a6ead3,8198e56d,618f31e9,9b70d7f1,2b5ffb37) Z8(968fa796,70b50e5b,8275b774,a8715043,d4b84451,4f5f36c1,cd90d660,4334033b) },{ Z8(88ed4f73,c4cd7bef,ed046287,12213b2b,fec017be,6854cdc5,d1fc5947,df9557c0) Z8(b5940ff7,1159620a,fe8b22f4,53e3c50a,789e4f42,05b8fe88,0788dfc8,f7058fde) },{ Z8(dd9c2b8b,b9225f64,3a6851e9,6fd068a1,faab5833,da341844,95ae8e14,0da2615f) Z8(56ae66dd,a5025618,2a9eeeec,9549e059,84089e5f,c39d6a5f,8131627b,442ae708) },{ Z8(6de708df,42d9c989,6c40ae4b,9165a1ef,500e8dcd,f700a4a1,218b1462,1dd844d5) Z8(861cef46,fa36bdf1,66656c91,25916702,f56e89d3,02d488ad,416c80c3,f6c1e063) },{ Z8(b6db7d18,16e5da80,0037eb0c,60b941f3,b7722f6e,22bd789a,a1a16170,21ef3317) Z8(2c559410,8c111ad1,6ab88cf8,969f4716,52e3a06a,bbf2524f,5377ab20,452186aa) },{ Z8(a5f01ac0,13e5dd25,2040c599,95026acd,08c891eb,3a6eb853,3eb1cdef,edc3f2e1) Z8(15ea3242,f53627f2,46c031ef,efb96d5b,f8c0067f,4bd6d42a,af7d07aa,f67d3a26) },{ Z8(3d593fe8,c381e987,11cc7e5d,181d7e08,87545172,d7c2efa6,43607e25,86acb0f9) Z8(87fc981e,224dadb9,4836f20a,b60d110d,2273de56,bc890c59,a4d66b55,4617e12a) },{ Z8(328299f3,7b6294f7,918f6e85,c3ec418a,050e0c5f,3daff194,d41dba22,0f1dea7f) Z8(6ac1e297,e0bc6486,46007655,8f7c4974,2ac3d9b2,7e80892a,f7f14de8,f6379d6c) },{ Z8(2bf07d16,dbf41cea,8ccb2f71,2aaa9b54,63a979d9,3ff98c35,fd335d10,98b5ae87) Z8(639e1f42,21f8462b,8ebc6078,bb2ede61,ff47fe31,076fe0dc,1ae1d946,470df593) },{ Z8(fa289398,cb4f5054,b36a1f04,25331b20,4fadab99,74d7a229,451a7da4,29977994) Z8(168d2e7c,3b9d623c,c0f82bae,80d01ce3,78427832,0c1da8b5,b77d3dfa,f5f10a7b) },{ Z8(8430150d,bc8cdf5a,2700ba20,a022c99d,8f591548,1716410e,0ccc2d0e,f28b18e2) Z8(9daafa54,852c337c,3d534aaf,10e23a4d,ac3d905c,dee4b477,a1460098,4803c2ed) },{ Z8(749e77ec,083c9e69,796d8528,98492c95,ad74be1a,d3931535,4d3ca4a6,048f6642) Z8(f3406952,6f05ea2f,bed01908,bbc1ba33,9bf46259,1c17e81e,810c36bf,f5a98199) },{ Z8(8ee904dc,b1ddfb71,a38d2b68,78ac6427,c9e12447,846afefa,5c21c742,b933e698) Z8(49514d44,948c7cdd,b0d24b59,eccad880,0e7a1b26,f7fccb10,6abcd6b0,48f94844) },{ Z8(01bc24cf,22ada201,75f79ca9,f4b8866f,0c1f0329,38bb6699,713def78,7fd00509) Z8(155cdb0f,e9ec48b3,5547bafe,4995667f,2c652155,0ea9f4a3,dd7a7896,f561030d) },{ Z8(26996ea9,ab9a0fb1,4be4664c,abf82c72,df50da72,920ba01e,3837b3ab,13dfd56a) Z8(cecc077d,36f4e7b4,8a2eb9cd,4297e48c,fca041b4,097ceb54,f20407de,49ee84a1) },{ Z8(b68fc6dc,9356a581,fe3720fd,41dba282,0fc23032,efa231d2,52605264,4bbe0113) Z8(496e9039,703d89b2,522a5c49,b5d7a7af,fd25b4c1,32933b05,4b4d9c85,f5178f21) },{ Z8(b514701d,b76b3e5d,3b25ad21,5334651b,f9a2c714,2bd556e2,16ec3e16,aebaeb97) Z8(9f86190a,499f05c2,a1471775,ce07dc08,c03519b9,a9c4cf96,fad27c8a,4ae37710) },{ Z8(50f24f80,983a3411,04c1dc43,261a0da6,b2bf92e4,2d839243,1959a705,c91e259c) Z8(58ba924c,feb39ed1,51c0631b,0b7ace2a,630d2ac0,369c8758,3e6c15bb,f4cd261d) },{ Z8(86cbba77,905adea4,5bcead06,e6320f61,157790ef,1f0c1458,0fb8d36f,af97d249) Z8(44bceea7,279a7280,2494d22f,2f52be53,fc42e332,f6b47bd3,92cd9570,4bd81e9c) },{ Z8(2dfc4611,97030bca,cb23b842,2d59631d,f6bdcf73,d5783dec,4291ec8c,43b09e11) Z8(2bcdc8ba,aaf43840,fd2cb93b,a5985f4b,4e165229,d56700e4,1fd3bdae,f481c84c) },{ Z8(2996c96d,b735b802,d80aa63e,b24ef7d3,419310bf,ca1b43cb,02fd3247,19509072) Z8(091a3739,1ae0288d,7702b047,bded4f9e,02c651f7,cb6b40c3,127e1de0,4ccc7a50) },{ Z8(1a0ba3c6,7d21f1d4,c77fa376,6a087558,ac646cc3,3c08108b,58a91203,ea9015d7) Z8(889305a9,1034e5b2,8ddf7c65,b52df1ee,14d2a64a,2f5fb76b,4d4f6b27,f43575f9) },{ Z8(86a2f1df,1eae00bd,dc8bcf26,cb03d912,60382fee,3950fed8,acd3e042,ffbd9163) Z8(9a669973,b4ac9df5,f82c4a05,3b62fe9b,c17de107,91ae9f9d,1e44f322,4dc08937) },{ Z8(eafe1e8e,7ee8a816,c3971c4f,e0230ffb,d9d1d320,0de8a2f9,a1cfe259,c7f8e46e) Z8(6672d324,26366c62,bcf60be2,89ed2d0c,a09c8cdd,3bc9345b,192b9477,f3e82f71) },{ Z8(bcee4138,848bc08e,f0f69a78,360ab090,70f66468,b6817754,7f010355,28036dcf) Z8(05f85471,a46977b1,b3eb2542,8603ffad,f0734e28,07aaa090,a74f6002,4eb44a5d) },{ Z8(c51a72d2,f0b5b03e,2edf9702,ec828b07,bc24ee60,10c39d7d,ca275d90,81d50d3c) Z8(8e5847d1,49535086,9f101ee4,102beb56,3dab8877,ae995726,c9e9fd37,f399f500) },{ Z8(e8cc3b0d,d56fe372,16b07003,1a3e3d73,c44cd4b9,7e6bb94e,f52e5ded,029914b6) Z8(1035f44c,c566431d,78b15fcb,c987d073,b9317e2f,9e953303,ec8b2b8c,4fa7bccf) },{ Z8(33109336,c15252b9,76848b02,c3053e84,f27d19c0,0a6affec,66da1166,ff805315) Z8(7184f7ed,cf608d71,7c6fcb6b,ea37c890,e6ceed93,a56b3a9f,99f46fcb,f34ac6f6) },{ Z8(4a34956a,6d5d0a32,3d4f2c9a,45014c28,943f3656,3a1abd4a,35bac327,133853bc) Z8(c21ecb00,44fdb986,b37169a6,18859f18,a60a1994,638a8fa3,7b9a5a0f,509adf9a) },{ Z8(f04ddbe3,08855228,17dbfb86,5bf29d6c,16d92f7d,ee5ea250,ab583f8f,7e03af4f) Z8(3d12b061,ae1124bf,a945e8e5,e69b7b15,177380e8,61fa05f9,b74e82fd,f2faa5a1) },{ Z8(2b2c12e8,1684223c,3ad5ee42,dd7023bd,1d55e7f6,aa8e4ac0,e12b7f46,3b575326) Z8(536d0b41,64613bc2,df9f00c6,b538184d,f2c5f375,b1b9036c,31c69f60,518db1ca) },{ Z8(86053277,4cb272ba,3dded8e6,41d5386d,0494aabc,98105bf7,38337b37,8819b0e9) Z8(a6d0e03d,f9c774d1,642b4eef,05198611,ef7dba00,4c8169ef,43466c01,f2a99152) },{ Z8(07e20d4b,16744752,704f7c54,f506d3c8,4cbec30f,e1251874,07589e32,26098616) Z8(c92c8a42,dec7df41,c4eb4ee3,93f2bce3,eac82c20,3ba6bb08,3cf48182,5280326c) },{ Z8(28f61c25,023115eb,fde92a12,b66b85b3,53368f0c,aa3737c1,6b809bc3,f1113ca0) Z8(ae3f893d,80186897,9eae2eb5,f5ea6f47,f99cc674,6bfa2eb2,5224dd2e,f2578a59) },{ Z8(5b9ae9fb,55dc3315,461941f2,1576da94,115e493e,51178456,df758c7f,19c873f1) Z8(7879f046,aa2d87d9,edb7ee79,c3aa3193,b27b6cbc,4903c81e,1c962aa8,5372608e) },{ Z8(72a8f01b,8b94a362,54606b28,9a573d5c,47d71895,c6ab3f70,5dbc7ac9,049d090f) Z8(34c4ad17,d04f1a2c,ad4e97f2,dc9a3181,9e89202f,7573acc7,eadbf1bc,f2049108) },{ Z8(6ad05eac,0f9b03b0,2dfe81f6,0cae1c92,f5dbcd84,fbf9119c,d51f1708,6175220e) Z8(03ccd92d,1c5eb8e1,4dddd949,e66c83bf,0f332fb3,57155eef,a29de9b3,54643b3d) },{ Z8(11c9693a,f8b92fee,3fea7c8b,8058b732,bbce0bbc,e0af44b5,3e367c2a,09660bdb) Z8(b25b0000,71b48e05,c7070517,8eb9ae2a,dc8d0dcc,86c55fea,06b526d8,f1b0a5b4) },{ Z8(bf965f26,3df9c619,c79afc90,1eb801e3,6e05842e,4bf340a8,2a24ac0d,e06fa85a) Z8(057e37db,d640aa7e,e09395bd,d9a23a3c,bb7c2331,9b54e12e,f4706029,5555c188) },{ Z8(821aa279,6375e91c,d88255f4,bc2e375d,ec4f1332,ecdff968,2767516a,3dee4e68) Z8(07c4e690,1c0b5128,bd579f09,d9fff438,fa59b164,937d0351,90fe6262,f15bc8ae) },{ Z8(d1ef3f4d,f1adb65d,0a2d8a5c,517aba32,54d27068,ff875262,d0222eb0,d9ce81a7) Z8(53cdfc90,b05ae267,74a00246,ee826d96,06572290,3a5d61ff,8bd65cbe,5646f27e) },{ Z8(7f3b6732,1228f67f,29a4d642,12a5296f,b2ca036d,c26749c2,57ae7419,e60f19e5) Z8(6b06d98e,07a4f6b5,d54dfb09,5142ac8a,72520443,7d44e042,66b607a6,f105fa4d) },{ Z8(88e18bf1,383a14bb,e6682b72,3fb8b385,04c57020,f165168d,863d8907,97a9e600) Z8(c4896f13,0ffc831d,2660f7d4,88319743,d1fdd9a5,58b493a1,37ee6174,5737cd2d) },{ Z8(1fa13d65,9c3a125e,92976c60,24c3dc72,c924bac4,f0add31d,af208071,c5b2ee48) Z8(bad01f0d,49c1b664,47d3613b,6ff6a757,1abeae3d,c3023855,56361a64,f0af3ae6) },{ Z8(32e06bb8,088db45c,99a244fb,a1654119,500db61d,e524ee13,c132655a,64f1f80a) Z8(90b5f851,da427ce0,89be794d,cdfa8f31,44cdbbbf,7f602ea2,1e1dd46c,582850a4) },{ Z8(08931b70,757e6833,c2e1a515,b0eb8c2d,6d403c8b,0ee45e2b,88738be8,0446fe33) Z8(71145b3e,c5a6b137,d0efb0f4,f74f3dc8,6b984afe,a39c09dc,1ede707f,f0578ad0) },{ Z8(18f6a990,75d5ef71,9ab29cae,240f2f1c,6e902be8,e2c07455,5416d0fc,af3d16b3) Z8(c4273155,7a8a67dd,b2df208d,c84dadea,8cb9a98f,238e8742,bb01da6b,59187bf2) },{ Z8(3524bae3,a2f56352,a16eb337,76821a66,740f4591,93ea3885,c0ae6e4d,a4aed446) Z8(d1342e89,6cfd5e11,bceb29b5,0f4ccbff,72c1909f,82b5e520,70bdf2a2,effeea62) },{ Z8(2204d30f,50e31719,f48acc2d,5aa972bf,e75cf637,4e5ea36d,6c198583,d8ceec12) Z8(0c295e36,647529d5,c0b1afc4,ed2b5d17,5531d74c,76dfdbbb,e35fda27,5a084e28) },{ Z8(7881d72b,15c48961,5f6d931c,a6b2beb8,8a1548e1,313ecb77,6546b41a,b06750a1) Z8(78f1daa0,fe6147b0,62261125,fcf91894,278a2d41,4eb03319,ec3aec3a,efa559f5) },{ Z8(add979cf,82dd8804,8ff444f4,4089e8dc,52623eda,4dcefc17,3285ff45,c9ba9f42) Z8(bd954cac,0f88aff7,ca133d57,f3e6f5a6,32409198,fd1595f4,c515a771,5af7c656) },{ Z8(1e6618f0,b79a9e42,3928be21,19bd01b4,74ddf59a,b8b1e571,9e176863,b5af1f18) Z8(002bf87f,d1fed731,1a484c3c,368faa22,c845c2cf,97ee38fb,21ba6b16,ef4ad9e4) },{ Z8(adc5abdd,afdf5945,a0077f5f,bf63214e,6537d114,8f421487,99d86baf,46738fa8) Z8(3f114eeb,188af565,b2e07624,e6734bca,a0d36483,bc14ee9d,e8095542,5be6e38c) },{ Z8(a0dceb6b,99573b18,e40590d9,a2ec0bd7,dfa8c076,408fd134,afac0be3,ef69e19e) Z8(4fded40b,bd41bf8e,5d93f48c,e2e4d7e1,ea0ac0d3,f9b95ea2,9146af0b,eeef6a87) },{ Z8(b8eccaed,1c37607e,9546abed,d2bbb661,a0276948,7f322829,ce8275f5,cece3694) Z8(22d838ae,fc958676,8fb6004e,5759508f,27e23655,3442bdd5,2f18adbf,5cd5a4dc) },{ Z8(3ed74500,a8f24d48,bf152487,6abcbaba,b38258f0,0b67d64d,9a0c16d7,d168c8ff) Z8(9999e98a,6771b0c0,ac0a028f,610f59ac,bc9f4476,6517d83b,aa34a9f1,ee930c3b) },{ Z8(13d01836,1d01d8eb,a878b922,c2e6fd73,38e8398a,a220f616,cd613334,bed1ba0c) Z8(240fce6c,3f2e24de,528a6afb,51320ff5,498de5d8,a94675a2,d9084f48,5dc40955) },{ Z8(67a74c0d,6cc0feb6,16a758ba,e1496860,62c52030,7c4dac07,9b7d0d8f,6daf28a8) Z8(be0091e7,17053803,9db604e2,262e3b60,34d3a47e,cd91ddb7,cac89052,ee35bf5c) },{ Z8(e4fe6324,268971d3,9e6651f0,93e21f0b,3d1a1407,8d172d90,6d6a81d0,9f435b0e) Z8(acb9cbcd,8185c558,f7eadea1,d35d92a3,25c074e2,9e39ea9f,81726da3,5eb2100b) },{ Z8(fbc2af11,33e967f2,1e0f0960,5af8840c,088b4f7f,409b4472,f55c6c4c,a6556c09) Z8(079965b7,a58d8e18,fe0c8187,d7b864a4,5fef1e81,a72b249e,3fd97b34,edd78448) },{ Z8(6a421a39,0747e5a9,8cc88052,206d398a,4f13e9b3,843ab974,073181e2,feb2fbd7) Z8(93f99c8e,7760dc00,e0fdf130,057ff42a,50e22c53,c432540a,21b53649,5f9fb80f) },{ Z8(eef23ab8,1e5247a0,d8f4ad88,a652378c,45d99a92,2b8b50b3,4da2e57c,680eb930) Z8(c162b199,58b28572,d8f8aca6,1c6f6b85,9d338a15,93c56bcb,44741b44,ed785b5c) },{ Z8(611a100f,65d9bcbe,f0d27f0b,23678649,b6bb906b,77249f12,bfcee298,4fe0b5e1) Z8(e574f22c,3e1cf8bd,dda03b7d,dc284e80,b39765e1,f6e47269,11e0d6f7,608d0073) },{ Z8(feefb929,dd358fee,6b5a41ab,44250fef,c05108f9,2361adbc,28bda278,175064f3) Z8(1b5957c4,e653d310,cfe99acf,5ea7a822,d7dfce83,8cb3a53f,017c7dd4,ed1844f8) },{ Z8(d87cf021,512554b5,0badae78,26cb9055,43712de6,dbae8f6e,0e9c2da0,4d75fe42) Z8(0c3458e8,fe629801,d0105d93,f8b5753c,ce03e525,40e9b5fa,09a5258a,6179e84a) },{ Z8(10be1f59,4b0878cd,3ada407f,5a4d2a9f,ad991091,39bee706,41d34e24,0ec8179c) Z8(100d1019,671303c8,6fb431d9,f1466600,73aa48f1,c37aba40,8d4ee3fe,ecb7417b) },{ Z8(7a09b6fe,7fd6a0f0,4021f8ac,e3260c64,775f8530,6b5aafe9,aae96f02,3804492f) Z8(3f0827fe,7c72e8ca,bbaf90e7,e8712dd3,8f7eb1a7,3fde2ea7,213ee838,62666ea7) },{ Z8(37b7965e,e70c7aec,b594a537,71866f7a,62557e1e,c4cf2ffb,19bea541,ac8955c2) Z8(5dcfcff8,f8d1b000,48a9de3a,570aa8d0,13508cc4,62941aeb,eb5fac51,ec555147) },{ Z8(723d53a9,72260bbe,a588cd84,a6d14da0,f5cbf941,6c42e4bd,ead1c971,7b2d3776) Z8(9a3c873f,fba5b94c,8def3cae,bd9695fc,325d8aa8,a02ea766,d264bd44,6352929d) },{ Z8(3bf0cb46,607171e5,ba8281bd,e9f86641,b9549852,c304cc48,9c102065,06a20d6b) Z8(dc5c6d08,155aacc9,42b1abfd,d3013b59,93626798,447e56a0,0bda4f62,ebf274bf) },{ Z8(034101cb,03f30f24,9c75fca8,d2ebd07f,1b74537f,a9f7ebaa,4d5c376f,beb92564) Z8(c1f80446,74279bbd,abc46175,6f5149e0,a2520a8e,c8fb2f2e,f933a132,643e5341) },{ Z8(b84af8ed,3e9118d1,4b5e4833,1ac3e8a3,728403bd,f062ccc0,a2e84a0c,0a2072f8) Z8(55fcabf0,b308867d,7b1ac403,e59618a4,8a70a2fc,a47ff098,cb3f6fab,eb8eac43) },{ Z8(4a1d9b4c,fb52518f,e1b96fba,6c52462f,10c921a4,cdf402b9,01b5b58c,37ef17ef) Z8(a8371c46,feb285ca,b0a47956,d7dc5368,0a840a11,31ec197c,d51b1296,6529afa7) },{ Z8(b303e4b2,0057d360,dcc1f95d,679525f5,c516131c,05545e05,95a71665,abb4c306) Z8(a14367e1,21558265,a4e8ea4b,15c85230,7916a78f,b9379682,f201fd13,eb29f839) },{ Z8(20ad581e,80694ac8,8f229442,2801646f,bdbbd12c,24392bc1,7bc1bbae,48378d31) Z8(8cfa5d2c,ae458883,93abc759,c095d35e,7f782ea2,3f3dce2b,09c8d28f,6614a6e4) },{ Z8(d905235a,9cf7571d,1380d952,7085815f,1b90be42,67e2e553,1255d7d2,10cbb0cf) Z8(f651f1ee,e01f8aeb,b774ea3b,b58dcc1c,b116f73a,1569e19a,34236c82,eac45906) },{ Z8(24a65211,6b45a0d6,9d265ccc,9f90ed46,7b7be717,ef6a7ffb,cbea0ad5,8139e1a1) Z8(34576c65,769a9b03,bcbf9b1a,65ea0585,0a3fa5fd,e39a320b,a0144109,66ff380b) },{ Z8(9eddf1e8,68473c57,afc5b52c,fe9e0430,76933278,8e61f612,a7b4c497,1a691fdc) Z8(6824b2cd,5a99b5e8,55c3b405,ba473838,ec26515f,976ef0b1,30cf03e6,ea5dcf0e) },{ Z8(0a0ceb7e,7645eff0,74e1f619,0bc6d754,1464dd9d,64993de5,12aae920,831b8389) Z8(4efc3306,122908c2,60a4a113,5cf7c1cf,3d2b6fb8,ab94a344,06e953d2,67e96234) },{ Z8(1df256a7,83aba255,45de4813,c761e969,492a9d7e,c1901940,22260433,61fb0ab8) Z8(70c491e2,6dc344e4,c2e45ad3,5f44ea5c,7e98cd2d,9b308765,71f43b16,e9f65ab8) },{ Z8(014cf5b2,8ce338fb,82aa6cd4,6f8bc626,15b49579,05f63d74,dcbdd26d,ed8eb76a) Z8(34dc49ff,243b2059,850c0655,7630d755,c4ccddc4,3bc712bc,14332797,68d32473) },{ Z8(6e58c504,34b42acf,14014bf1,d1d3ad15,5aa2f9ff,971ab2a9,062a9063,a5ec4efc) Z8(bea45b07,5202f03d,e97f7922,b1f6b2c1,bdd18a75,0dd3089c,6be031e6,e98dfc6c) },{ Z8(6eb57696,1e704b4f,01474331,9f96d624,fdad227a,fb58acc0,5ed66b5e,ec068416) Z8(b866e66f,11864549,b273c3b9,28f4dbe0,94ecfcc4,b0a34864,05c629e7,69bc7ddf) },{ Z8(f615c6c3,7098ba1b,b057d89b,6bf6d170,8d50531b,2ca96d4f,c03bad45,ad754841) Z8(42883951,73c55c7a,ca79b384,085e2d9e,ffdae99d,ece7ad24,7cd63be2,e924b492) },{ Z8(a0ef2b3d,3673290c,e7c126fa,95698eac,5a62160c,dab1e834,615c866d,b3b70179) Z8(7f22b95d,9b0bfb78,13349ca9,be456b9e,e3f9e559,b60a761f,8249db4e,6aa56d8e) },{ Z8(09327ce8,89160064,bd4fffd2,8a51880d,d651ec9b,8a4adfc5,39ab2a1b,7ab40097) Z8(0f9ee02b,d7bad7c1,c3677f73,89b3b101,91b61011,a563d834,eca7821a,e8ba8393) },{ Z8(97aacb38,5343a4b4,46642c05,66948233,87382211,857ff91b,818dc4c2,50b20ff8) Z8(4a9d256b,d1e76a48,9cc337c7,7cf8ca6a,13123ec3,94a67c8c,9a222896,6b8df298) },{ Z8(507aaa22,811bb7b3,db8673c0,9cae616b,1e93c41e,d3b8fe15,85a66f39,238842fa) Z8(8c24d48b,371859ba,c6ea4a12,75e5de85,b755a9db,b08f7858,ec49bb51,e84f69da) },{ Z8(9b9e9111,d9916eb1,6ea5fc1a,6f11cfc9,1df095ae,6a510663,4575b527,063a637f) Z8(414348c3,3724f8b4,0887a0b6,7036a0b4,ae6c52ac,dbd34660,c8585a51,6c760c14) },{ Z8(9b0f9a6f,7df537d2,5e335ae9,a6c9351e,ad884424,387fc8ac,0ff8d974,b630d6d5) Z8(6fe2b72b,4297e6a7,6455bf06,7f5c132a,419cd005,b6aa11e5,956cfb16,e7e367d2) },{ Z8(45abf26c,b354c791,577cf72f,83bea555,ff880ea8,e0a423e3,cbbc3629,a0c7dcc7) Z8(b104b84d,64919228,e58e927e,8b24d735,e8912c3f,b8a2f9cd,f38399be,6d5db91a) },{ Z8(8fe784a7,4e632877,6f32f497,2e6333a2,ee997e02,f8f0b040,f4161be9,0829c511) Z8(8708ba8f,05bf84ff,146f3522,26587359,e903be01,682a76d7,ea10981b,e7767de6) },{ Z8(e3b418a4,852cafd5,33eb1f29,ea31b56f,ca4f92f4,dcbf7a1f,9e357e87,7d06e724) Z8(68459e67,316442f1,215d26b0,a446ac4c,00f4d47b,752d093c,6eb10a1c,6e44f8c3) },{ Z8(d1cba51c,1248bb11,78ce0f55,649055a2,b151f5e8,2b2fd27a,9aac350d,0df8273e) Z8(1a7e7041,72a8f110,e702e77d,021074d7,13429e14,27376622,d4172a3e,e708ac84) },{ Z8(136c26fb,be6aa27f,0d0d8a26,40b01d9f,a94ae03a,17cd11ae,81156ebf,9934e65e) Z8(7bb82f03,9927a7b9,c4a0a9a2,c5d55c25,aabbe0a4,06e5fb8d,fa4b758b,6f2bca26) },{ Z8(f3174f49,10bd6668,7b10bb5f,7551fb3d,ab01d13e,ca8482df,c04add39,541fc68d) Z8(f64c99cb,cc79957d,a07f390e,83c21666,d4fb8fb9,834668b6,24d9a0b0,e699f41a) },{ Z8(16733f09,58d895b1,8ade085e,35678ae3,5c7afc67,afd1dd07,001f08f8,86060cbb) Z8(2b10b725,4f9a5269,79b09cf0,382e0383,fd340ccc,ff33abf4,c5028c8c,70122c5e) },{ Z8(2a2b91c9,60e5b82d,4fcdfd10,3cac4bdf,33884212,64845fa7,31e79e82,e6a71eb0) Z8(3a94ae49,66f9e7ac,0111df69,e47aca55,d4c0e483,70b15d41,94b970a7,e62a5515) },{ Z8(9659e871,e58f655b,cbca2f26,041d49ee,820ae5af,245029c7,ab4820c0,58164ca2) Z8(79b3befb,d7768559,a29f13a0,9c4d1996,ddc5e215,9ecf5610,6cb1b744,70f81e84) },{ Z8(87007065,ab03e21f,91f993d0,277f93bc,92ecf050,7ec576db,95be4879,bec821c9) Z8(31a03ab3,3def4011,686189e4,694708a8,2bcf803e,0d89542b,c2b1dd03,e5b9cfe6) },{ Z8(94a81bb7,1099ac70,fc425123,03444634,f4ff699f,0d97dd32,851b3216,9e98e49d) Z8(f1f98e8b,66c77413,b1c57cea,e3aac247,9f6729c6,3acb970a,ff467785,71dd9fb1) },{ Z8(4fb36d24,5b6ed80b,cb31f13e,9716ddae,f9911856,9965ea1a,5d5f9117,2603ae35) Z8(735820dd,fa6b6539,61702450,bc7c0d5f,5cf1b1a8,abf5bd0e,33e8575c,e54864fe) },{ Z8(809cc9c5,590ea2ee,9a4c0d8f,f80e6cc5,b35bc04c,b92ffc8d,b0952f43,d642b96f) Z8(5f9fb583,b80172ff,a626d4e7,ebc3b741,fb07c5c2,91403183,fba65ad2,72c2af01) },{ Z8(826337f1,2650e3b0,7a037833,ac36e9ec,4e7c28a6,6c651a92,d2ed1c99,c61e873e) Z8(d3e3a62c,908d3a6d,591ded6e,3d4cfd8a,aefb6ff6,c1088e06,533bfaea,e4d614cd) },{ Z8(266052ed,f59044e2,efdd5c62,57be7e22,1734b856,6144dfe4,9d537b9e,9fc63ff1) Z8(5ec60aad,a9b1cdb7,9bad0e3a,769bf477,eb3fb021,1baf6928,52947b68,73a74b8f) },{ Z8(3a89e3c9,03e56c2e,72b932d9,7553e766,416e19ca,c81f5b04,fa4a2e1a,77966bc4) Z8(1859aef5,01f91443,202bf5ab,a0547011,1228f146,3d1a1590,70d421ab,e462dfc6) },{ Z8(6783ce9d,699ba5c8,3cf3cfde,26d496b5,137b820f,7828d4b5,35348a70,81a10db6) Z8(bf2437aa,4798f789,cdf8dd1f,3ef0d7ff,5e00ccf9,de30c395,67968f62,748b7475) },{ Z8(b989ff3b,6deae6b7,179df131,95fb689a,96f3b371,86f62b25,a7590561,e67019f1) Z8(6c8aa52e,e1231db3,36ad6e97,6a2e3a07,412d5870,b878ab0f,c1ae1445,e3eec65c) },{ Z8(a99e863e,0fb66baa,53efb78d,21e1f1a7,0b54946f,87ae6b0a,92fd338d,0b2d3ad2) Z8(4be54cfd,b68a4c4c,582fdb74,734ecdfb,29c779bd,a44a75fc,11d98528,756f28d0) },{ Z8(e2743b29,97382411,43d0d9d8,ba4c67bb,4c2c415b,2447fbb5,952bc98a,dbf33d8e) Z8(b36e3f0b,2d4d0698,76c0dc30,2b3d109e,97c2057b,c4808aa4,5f29d517,e379c904) },{ Z8(6d33841a,d96f7468,46e33672,b9e75573,3a28f6fb,e1ccd7fd,99025c29,f086966c) Z8(f993355e,b6e416b5,b8af15b3,32e8708b,d0790138,0f254fbd,9d15ac28,765267bb) },{ Z8(eddc83aa,7c0e66aa,756f2efe,86bbae26,ef2514f6,ec33fe73,cfd4a91a,93ad19fe) Z8(0b2d7f40,eca149e5,b0d6e486,7ee50275,1b9271ca,9605f173,469606de,e303e832) },{ Z8(ff2215e7,f0aaed52,4d56fea6,6437823b,978cb216,9872d14d,c32d4494,3a9cd3c5) Z8(5340970a,964534c7,5f052fd2,fa8e1ede,d99e6b39,4c6e171f,ca72690d,77353054) },{ Z8(5148c9cf,5aeaa91d,cc755029,90fbad4e,bee7db2c,ab66a430,5fbc4034,c7f945ae) Z8(76cf512a,2ab7fe76,4fc2808c,66acd9eb,bc003c43,225e232a,58baef72,e28d245c) },{ Z8(5a8c9b7f,968b2186,751152b2,ff3df137,3bd59367,86374c21,3a23cd57,8ab0fe68) Z8(dc2a4f86,8f8c38bd,00f1617a,3ec30676,d49586ce,c1c29af1,d1697487,781781b8) },{ Z8(bcabde58,7f0ff458,283dbb03,11f8bdf1,ac15c83d,a2af36f6,eb71be86,c3aaafc6) Z8(d213fe0f,184de2c0,bf7beade,fd53f968,58d1d159,ac427c07,59649706,e2157df9) },{ Z8(c60bc44a,ec29cde8,0b375797,1332dac6,f31f1456,43900d9e,bcb383ba,0767dfcb) Z8(3b579e9e,32e605e5,20631ea9,224d08bc,1dc38c61,6df7bd98,60a9a3bd,78f95b05) },{ Z8(5cf700e4,84332c5e,4383e0da,5b0d2f1c,d1be4964,d4018669,7907fe2a,3691e5bd) Z8(22d94019,0a00f700,94e7b5f2,b2a1911c,4807ecef,a1422fa7,eeec046a,e19cf580) },{ Z8(09483c9c,e8463dba,8551c330,63b30eb5,7514a314,9ad22898,c693aa5e,4649923b) Z8(31ecf1a3,c0f7de46,04338baa,e43665ff,57ea801f,37d7fe3f,9ef93989,79dabb58) },{ Z8(068b6cf7,2e39f183,efcb4d4f,20117330,80c6692c,767387d7,99b2b6a5,601f8986) Z8(dcf766d7,2ff5140d,7b25c6fa,756b82eb,6d96b1dd,8b7af1a2,a1bf96b7,e1238b6b) },{ Z8(e88eb7cf,d296299d,0f56236e,0d0467b8,2ebbf6cc,5cfe8e99,3a9cfb75,db35ae8a) Z8(d2a0db47,8b303693,caf13cd5,92f45b4f,f60ded99,d92f0d93,2c17bfa1,7abba1d1) },{ Z8(c53ccdbf,72a25e5b,fa33e62f,005ab15e,8adf28ed,f8007990,e2efe077,01204d8f) Z8(3e8b19e8,d72350af,89f43eab,56566b3a,fafad985,bddd9da2,dbea7ced,e0a94032) },{ Z8(7f81b6cb,9ba656ac,cb010ade,19496af8,78d4098d,67f5c1bc,e2c45358,0d0b297c) Z8(639f60f3,91fe3a3e,c49a8888,4a25ad58,342b56ac,8d0e550a,219f66c7,7b9c0d8e) },{ Z8(49809a79,258af897,cdb8df8c,c178cd46,005f0c91,53160225,fb808fde,dcfa8eea) Z8(9a472ef5,e224795f,bdbbeb69,62b0fd73,d2a39b09,4359275d,e89b4bf3,e02e1450) },{ Z8(f8e7de33,cc21d763,66fd59a2,8129e9a1,854de0bc,460a7592,0f03489f,6bca0c91) Z8(850b6371,8d59282a,1b5362bb,aba6c074,25bfb113,212f8a75,13e5ed17,7c7bfdaf) },{ Z8(41a1775c,21c8d067,d204adbf,95c1e965,03913a67,554bd5b6,98b9b80c,83f25534) Z8(4d311123,029e9509,66cc2b55,ec583b83,342890b5,7ae2c515,f3a9b36f,dfb20840) },{ Z8(d921c485,eb2956f3,a62367a2,dcdefc80,97f50db0,55506abe,e7baabe1,c52b8507) Z8(596a389f,d3e7778e,9edc0c55,e1cc1e07,e8080aa5,8434fc65,12dd09a1,7d5b7154) },{ Z8(d1509b92,2a65d991,85a20be5,8635b755,000b760a,42274970,34ad88e2,2df3b7a2) Z8(c12c9ade,80daca87,7e7da500,21879f7e,2ac0775e,ab7587b0,091b51fd,df351c7f) },{ Z8(a344bb83,9257d97a,d7762f8d,ca80bb87,7e18cbff,7a866e49,699d64a7,073f6283) Z8(0d886dbd,f0c3a907,21823a4e,172961c9,028d0964,6542bcb4,aaf25c67,7e3a679d) },{ Z8(e4ccffa4,163105c1,422a535a,6f981a19,73210cf3,c43c16a9,91c59388,dc58f27d) Z8(d57574f7,6628d1d3,f20ae8c3,0bf8bb48,09cd41c5,bbcc88c1,14a7a931,deb75188) },{ Z8(a31a423c,5106025d,4907d9e3,98b5b8e0,c6f0c862,b51100f1,529390df,41c977c6) Z8(15a50d90,d1cdb528,aac06fb5,619c8682,2429c714,f507b2ea,e5eee1d8,7f18dfac) },{ Z8(48b0da57,7da091e2,08ca1580,9defba79,774e7a6f,9dc7cdc5,cca28a2c,f41c81e4) Z8(73f42a92,0da71e48,ecd05918,6580db61,30fc8dcf,19c8a06c,e13b31eb,de38a7d9) },{ Z8(3c2e74d8,62509b3e,16518d7c,84f6c985,4d0837c2,8d86127b,257978f5,fcf40900) Z8(939b5d4d,48b9eea8,8419c0b4,1f24e803,db5159df,54c97482,4bd5e8fa,7ff6d8a3) },{ Z8(76250108,1cd4bc58,88f1095a,a0a0fc27,b21958d8,8be9cb0b,0be7ddf1,a68955a8) Z8(7640a2eb,aa7dcf0d,94bcf0b8,69c64a00,a3889f51,bd2452d0,18799172,ddb91ff3) },{ Z8(636f4c67,a531aa94,15f46c8a,ad6b8920,8c96f0f6,88600799,8293a0f1,9bd5f3b4) Z8(02448ec8,02507817,e93b9376,656800f6,dc0a6a79,bd61086b,e3c38b4d,80d451a2) },{ Z8(06f15790,9b7059c2,758a57b1,6e3b7c3a,50d130b4,bcfc5231,33c48859,1b9f5617) Z8(43d075b4,ae836ac7,1337331b,c7267071,09896f4e,104d76ac,423eefe2,dd38ba53) },{ Z8(00295bfb,2528d664,f6997e46,b38e89d6,9e178116,313a4746,ad2b5f44,bb0f7fdf) Z8(d294d25d,074c83b2,ca951a93,74206c32,9fd4d6aa,e650f8d0,34caa5a4,81b149ce) },{ Z8(9be67be1,893b4335,657b211f,1b6b633a,0d0e08c3,0c1fec74,7341e221,56059fcd) Z8(eb7f21e5,522f5407,62843b54,939ecada,b780ce9c,68f31e3e,c4207051,dcb7777a) },{ Z8(e33b3b0b,78b65402,2b57bd39,515ebdb4,a7be3cb0,4094e3ff,05e8ef44,072dba13) Z8(972bf9e7,b642f7f7,9e5a3030,e541beb6,786d2cd2,b435cb7c,46d250fb,828dc048) },{ Z8(4b31d9de,752c5687,87a75854,1e7139ad,1043f0aa,b9b61875,dd1b5315,49a6228b) Z8(7d503d6a,8e630162,f80e4931,7b2543e1,62a44ac7,980ea93b,e0ebcb4d,dc3557ea) },{ Z8(6cc7a25f,f914d879,a74481dd,cf67b2c9,7a4c306b,d459df16,c3c749f8,401940d1) Z8(56b3678c,bcaec2a5,f5cb2e38,b2b493f6,e36ce1e0,b5c8a71f,a372da7e,8369b434) },{ Z8(917e083e,0ddb7324,f7bbcb1d,b6e97d1e,076b0699,b357d33f,055dd1b9,62183cfa) Z8(b229d4dd,bad20cc7,8b0ab628,c6533519,ec991b70,f6e7bc98,b8260c14,dbb25c25) },{ Z8(2f925e97,1980bb01,ab165007,86388f35,7c627ffe,2e4d6349,be7a526a,bfc69099) Z8(4aeba2a9,17fa3d9e,3d8572f9,ff202e92,66caad39,77801276,56d239e0,844524b7) },{ Z8(4b3b831d,c1273c39,1d265af1,47e7c4b2,64187766,5b05d4d5,419b9f92,9c34c9ee) Z8(b21f25cb,b2ecad63,df00e304,530ca02f,6bd12a0a,33cb4db2,4589711d,db2e84ae) },{ Z8(f3d618bd,2dcc67ad,2399de2e,0258719c,44801786,5b4bb4cb,a5863a0b,4f464f06) Z8(2f535740,9947b913,775ffc60,80c2e9e0,614753d0,378bd8dd,f0800521,852010f4) },{ Z8(eb1489dc,b345bb37,6e8f3076,76f3ef2f,101a5565,2639d62a,e2721d84,c6a0ec42) Z8(41ae1f3b,267a899d,3e7244fd,2e1b1714,e855e993,fde51c09,60827063,daa9d208) },{ Z8(981fc1fc,25f010c7,58957fae,944c8444,8ac1e406,d46d6396,ca4a488a,13789552) Z8(da2c66c3,c96d772a,965e44ea,a6762946,f21bfbe7,0676b4af,8450e0ed,85fa7812) },{ Z8(bfd60d07,47f46919,0eb3c71a,a7c7df5a,2b2ca944,e09bf92e,bee15be4,13a8ea36) Z8(16fc822a,5cec0fa9,9f8a0159,4655ae00,140a75a2,8be00386,bbabe00d,da2444b8) },{ Z8(38d06a2c,6c1506e4,6250cf31,00835da7,83b1e793,e428c10a,b18e8b45,1a1cc195) Z8(31f5ad98,c23401d2,aa782184,62dfcefe,dee54f35,e421e822,ab396cb4,86d45935) },{ Z8(31db8872,48d7ebe5,985e1e8d,ecdcf73a,25beec95,4f171510,2adeaab4,a89b7c18) Z8(c2c72be7,5c0da0b7,8c768454,fd54d78e,95204106,d4a3a3ed,e44a43d4,d99ddd44) },{ Z8(83dfa98b,1f88fafb,272f6d13,3f0dcf44,91b3763d,f7b5b104,6a32aa8a,d86ab2e3) Z8(2ec1429a,68884404,7c504f66,e9d6167d,b056eaed,ed13e5fb,8428a9a7,87adb384) },{ Z8(75e42688,d3cb1b7c,601e2dbc,10c2ce5c,ed653c83,a1d77cd5,68e7205d,3195b9c4) Z8(16200ef5,3a354718,5b01738a,f77f130f,4905032a,2cb41601,41c63fd2,d9169c33) },{ Z8(6c6f18b2,18079375,fe02182f,9baa1442,d9fd2440,9d924d29,40ffbb9c,2e98511f) Z8(e82459ff,b7daf8ad,cb16637c,00c143a5,30225272,31331013,b4e1dbb2,88868625) },{ Z8(54ad6bcd,98e8c786,d911d9cb,20f45700,d4862d5c,d45fa91a,3c87146c,2556da84) Z8(6a7e0fd4,44b13ca2,5d246c57,75eb26f6,0c1a9a53,d561efbc,1526311d,d88e820b) },{ Z8(3b76bac4,a748ff1d,5dbd4741,828bf0a6,a5c8b989,fa6500e1,e602994b,9c61f271) Z8(149deb2f,64735680,c68fb805,80bc19f9,2b2ed536,52ffdcfd,6ad5e3a7,895ed040) },{ Z8(8fc46d6c,489be650,82aa6826,8bfcffa3,389cb7c6,35bef9ca,7682947c,afbde054) Z8(10a360d7,708414f7,fd2734e2,f6223693,9825e4aa,e51cd540,7886ecd4,d8058f54) },{ Z8(68cedb8c,ce9bc14f,480d8d78,efe51fba,c07827f3,caa965fe,0aa9fa0d,cbb2861b) Z8(f9b4650f,fc18d530,514bbed7,48a41251,9a8512f4,9535e273,5bfc11bf,8a3690fc) },{ Z8(d4e38ebd,79c20bc7,5b72ed9c,56373513,be72d280,74baa84f,65e60f59,d814827f) Z8(6fc91bd4,58468b82,814acb03,e3a04258,06bbc6bb,c9d868b9,5e93a607,d77bc498) },{ Z8(3de18a2d,df8e30ff,5b1ac98b,ab34c5e0,d040f42e,fb23f519,576c7fcc,26c514b6) Z8(5498a46b,aae6d27e,b40f6845,b2d8cad0,fa211ba2,8468c86d,c7aa6f8e,8b0dc781) },{ Z8(0d66dc01,5c966084,60000e93,b1f9b0a2,70d1ff95,cda47857,5ff4d84b,86f63422) Z8(0d09de09,f9751cf3,5c0241e6,758db6d2,f3732ed5,7f89bf41,91fcfb1a,d6f12260) },{ Z8(d60e032d,35abfdaf,97472b00,0afe8632,6a7ca20a,8ae73c43,d572ec74,6ff729c5) Z8(65a0e3f2,e023fbc1,739cc894,6dfceeeb,243d63d6,f2b88171,776d809a,8be472f9) },{ Z8(6cdf3c68,6092a34d,a52a179d,af1b96fa,cc7d9205,63d83eb4,50ae774d,c03713f9) Z8(31117efa,fa151d76,faf31a9e,9c1d7051,d988a441,6d51bad6,b4ef2b1f,d665a937) },{ Z8(5b58fde5,d50dd8fc,651ee66b,b4653491,3a1cbaf2,529df076,6c4aab8d,ee7916b3) Z8(cdf05bb8,06534c44,62fe93db,ff94abc6,3453e17d,8516c71a,bfdf78c0,8cba928c) },{ Z8(54c3be24,23774b3d,a6502c9a,e1fde4c9,8977f598,e51f6d9b,9bac488d,de5361ba) Z8(7a8f8033,1e23c7e4,595a40bd,08c06b3f,f21c10e6,b3edf087,408773b6,d5d959a9) },{ Z8(330107bf,a5e94ea2,cad3e305,72c21d8b,ba777651,67069841,5d48bb2e,8377ddbf) Z8(e9132480,30d7f8bd,42d82ada,492cd36d,28060119,9bce3cd1,817ee783,8d902565) },{ Z8(67b80b2d,f2024af6,036648fc,ce04f33e,82e862df,f0bc71c1,5ac2a0bc,a5136f82) Z8(d9d9146c,1171d862,d7439dbb,5eba9fbf,55f1ba69,8f853f06,844897fc,d54c3441) },{ Z8(52997c82,761cb85e,fd6fa1dd,72ed0df2,16aa46d3,8ae54973,3c2542cd,f9a5de06) Z8(62d92089,10b8f7ec,d6a788ad,aec2841d,d5f2155a,eb0933b7,2984d780,8e652aae) },{ Z8(d3330138,cde8e1be,8cbabe05,0c46f3ef,b9d3cc47,b89eb267,fb61c0cf,3e8761ab) Z8(47e56d12,8b0ed44c,b7e0b6a1,548898b7,0cd443f7,45d6144e,a58e9112,d4be398d) },{ Z8(f3f0a1bb,b5fcad13,947a01b2,2d9ea398,50da2540,9f895450,9d128af3,5b4b28b2) Z8(c8fce5c7,0a14f7fc,f19a2223,21417d46,d5a3ffd4,a3fa4f41,b2ba6122,8f39a191) },{ Z8(90efd895,d9a725f4,7a5ecf8e,d9708ec1,69ee9a34,85c651f1,bdfe1ac9,18d1fd5b) Z8(241427fc,b68ca0f2,cb1d5fcc,d86f8d34,3c8d9304,f031c2f6,9f0168cd,d42f6a1b) },{ Z8(c66b3ade,fe702b25,980ddaff,9800fd23,378d0587,79e77105,b589cf7a,deb39345) Z8(83a69e49,8e5cc8bd,023aed60,1085bd8d,df977065,9c03ad85,a64dafc5,900d893b) },{ Z8(cae39e0f,b99c122a,b4f613cd,10f26991,c0419cca,64fcbe7f,00f56001,6570d5b4) Z8(389ef575,d604f62a,615060b4,0d4b0bd4,8204cfb5,46895a10,40073f1e,d39fc67a) },{ Z8(7019017c,d24c7503,6c9c83cf,80264695,4d1987e2,0b23440f,83039961,33237e0e) Z8(571e096a,8576aacc,be571bfa,c72ca78a,a8c2815b,6cc92c8e,1ca67879,90e0e0d8) },{ Z8(53254913,03a24761,f659f86d,ee4de1b8,5f9f0b61,a70cab10,097b83f3,7cf410eb) Z8(9eddba08,a22379ff,214b1d19,27846fef,a7d9b266,661c5fa8,2c357ab0,d30f4f39) },{ Z8(6ffb7b48,75c6be5c,bfc6a458,98755876,96d29724,936e6fe4,7d7af89f,8b0d4f82) Z8(9048f955,d67f9fea,1337eb5c,fc80b530,5fee29ee,167f6128,be39e187,91b3a793) },{ Z8(4d241d30,939c2924,da1881aa,e50b3fb3,53d79089,cbdae1ca,deed571a,41cc3c80) Z8(f9e1c82b,bb3e2536,00724339,877bf04f,8b6f0ddb,6317c099,dac12566,d27e04e8) },{ Z8(bc7fcace,b13828e0,86c1495c,1f07386c,31bde0b4,49c1cb3d,4fb88d3c,dba03287) Z8(fdace200,87195525,7929a8d2,75aab6ff,cce59c41,3d02457b,c45dd9ea,9285dc9b) },{ Z8(edcbaeeb,3c64c0bc,3f192951,651671d4,6db6f5f6,8ca2bf63,fa61cfd9,69b9dd1d) Z8(4b563172,930795e8,ad2232f6,d7eb44b8,32d6e922,48a26bcd,95ee752e,d1ebe81a) },{ Z8(dfe43caf,034a9047,8543e666,4e27649b,c474bcba,bfda182c,cce93cbc,6e2cf79a) Z8(4298bfae,90393e62,a97d4d9b,e7254ec3,3c59c186,a84bfeff,fa1bdfe9,93577f1d) },{ Z8(164b0763,039986b6,67ef8f9d,6bdefa35,4d3b8143,7eb28a7e,7f8f704a,dca31c8c) Z8(8e9bdcc2,00d5d0b9,1968a525,46ccf29b,c9c6ebe5,fe748eed,7a7f81c9,d158f960) },{ Z8(b79adb93,cb35a13f,e107e568,34e01b6b,3b3db018,cac3e829,e6900d5c,d208a0db) Z8(e2a53ffd,81f90c27,5c99fa00,f5d1d818,920497a8,41c4cbd2,bd0335fc,94288e48) },{ Z8(ea14d097,4ecc4293,b3fe668c,a71ad5dd,433626f6,e5dafee8,1e11afb3,26f5deff) Z8(7518e9e4,3914bfe2,344b13bd,de0af1ca,03574707,5e25736c,77222819,d0c5394d) },{ Z8(cb4e7dc5,c1140403,448e26c3,5d656419,df234433,19149a38,4bab6cf2,aa926d65) Z8(f41dec41,f86e6e9f,f22a7e32,be46bc5a,68a6c240,59989e9e,fdfa8528,94f9094a) },{ Z8(7731c120,0dd18365,2f67e325,08ff01d6,5114462f,8001b5d9,06596d00,75fb44ee) Z8(e36d365a,566e9cd7,f70a6727,a204e0c5,4288702f,94d9b97e,4bdd1b78,d030a875) },{ Z8(e5cdc91d,27f8d5f0,c52be852,efd5aff7,05125480,e80594be,8f90401f,f3c2ec26) Z8(445b61eb,f8c232a6,6ebb10f5,5fa61a15,aa09e851,91c49bd2,4210ec0b,95c8ef54) },{ Z8(228bcc6f,d1537178,3d3e077f,78e48ebc,bab40852,676aac6b,8789424c,db1974b5) Z8(445043dc,870f4200,0179a256,7bcc1ed0,3f308eaf,bfe750dd,897c25c5,cf9b476c) },{ Z8(d7cdbba5,b357fc93,7588455d,22bb495f,47e63558,d30f6f45,73e5d0af,5c1f89d3) Z8(27823dcb,1a3607f2,1c7be4fb,9495f18a,e0b5c442,5fe5f921,a34e79ba,96983f94) },{ Z8(f9efc524,c7d90c13,997b59d9,9c37eebd,9fbd54d4,c0ce9a8f,98ac4200,4523322e) Z8(b7d79603,a4d94834,4a914ebf,0bf2d2ef,0f5d54e0,845d429b,90fb96a1,cf0516c8) },{ Z8(af9ced0d,d3c9f468,f337977a,8ff9552c,b4191b08,7343c02a,903936c8,0acc5f78) Z8(215d3eb6,ae3f48c3,ce349901,6817bf94,6fc28abb,aafc1cfc,d18413a6,9766f93c) },{ Z8(d788a7ef,e344e046,2e8a3178,d5848d7a,9435adf8,b18ba526,d1a01d38,3f88c87e) Z8(369aabe7,8ceee1ae,13efc0e5,efae2484,ec440dda,32225327,92f2e27f,ce6e171f) },{ Z8(24f49964,9710732e,c557784f,4c661f77,3c70a162,20748af0,3fcd112a,e16fc39a) Z8(e58aad5b,2d632597,addeaf58,f0d0196e,8a9c466e,9f48b371,131ac5bd,98351b7e) },{ Z8(62ab8685,63c1d4c4,683ba2bd,bbbb958f,c35eccf7,9b4c5da7,f44d9006,8931a7cb) Z8(79c999ce,d51f2d07,8e49a3e2,2126c140,d3373464,d38de6a7,8efe7219,cdd64908) },{ Z8(91485289,0485c77e,e0ede29f,1ebd5113,7c0e616b,8effb27d,4bee5f3c,7319a7f9) Z8(df04daf6,373f42ca,c8172e0d,03f54d14,6b675ed5,68412b42,45e27bed,9902a58a) },{ Z8(44462c5d,55fe078a,f9613b48,123a28f2,8c914e50,46df8a94,826d0384,61631a06) Z8(51cc8a25,81c7adad,eba9604e,faccbc4e,f5108819,59f993f4,5328a2e4,cd3dad1b) },{ Z8(5f5b047c,d4a88b2e,d7d4616a,178453a2,9a095e66,c920002f,fb563009,feb5c048) Z8(200d9dde,9c5a6498,87899edc,c963a87b,321b75fd,171d1b56,dfe02444,99cf9693) },{ Z8(8640c911,4d78b141,ae43656b,23cd1e06,10f713f2,eae7fc26,476043cc,0e2d5d74) Z8(b9fcf6f3,ed552af8,d12c2b8c,d4234127,d024621d,e6cea471,7b51f90b,cca443f0) },{ Z8(226481db,5d31d8ab,2737535e,d63a9a2f,49b82842,9bc735ad,490b6a8f,845b5fa8) Z8(3a6e463f,39313dbe,3b89e28f,2033ead7,0781de29,93f3d782,f01b38d9,9a9bedcd) },{ Z8(5b17a7a4,d5c07768,7a1d731b,44225e62,637a5b36,f9b18754,44a2c2bd,ae64b8b7) Z8(91170761,9be02647,4e081be9,bd7ea2b0,11a07ee3,ff00911e,709883a3,cc0a0e21) },{ Z8(477d9562,09be9d76,8d8adfff,b900b878,831ff9f9,651884b9,09ce70be,46d3fdef) Z8(4ccb161e,21387ac8,ea8c1eff,dc77d77c,dbe8ceeb,0f90645a,1f6ab0b7,9b67aa6c) },{ Z8(37cfb87e,ac681235,d19bb1ab,a8b18fb6,1d77b6ad,3f7f55f5,5fa19ed7,54f55757) Z8(9ed300d0,6f8db35e,360e9dd0,fff2f2a6,32111fdd,44bb91cd,68be7395,cb6f0c48) },{ Z8(307cd9e6,d6d14ec2,8d9242b0,952e6f6a,24f1dd6b,8f14cad5,d045cab1,648a462b) Z8(bd7b9183,8e62a282,ceb1ac8a,6a547cd7,857991ca,05256c4f,b14156ef,9c32cba2) },{ Z8(d1df7c8f,fb375501,21d4b453,b25c3ad9,b0493a9c,0acc4600,787a6268,ca0e0e62) Z8(b3db1448,43d7be83,87a780b2,a773f879,3a66a0e6,204bbc0f,658fe5e8,cad33f00) },{ Z8(1b0e64ff,cb7db449,24615176,82029b38,8cbcc658,c3028a81,46bab7ef,673ad504) Z8(abefa250,7280b4f5,e3300699,90435c79,b7ecdef6,74da3b98,84798719,9cfd50a6) },{ Z8(1f462ccd,70f4445e,adcbf9ea,fa92a9b1,f53f9ae5,6b99fbc2,d437c2a4,43b373f9) Z8(cf7174e9,42037586,4bb9abe2,726e60a8,e3a45bd1,8de52f15,3447e205,ca36a6e5) },{ Z8(e97c1e35,46ea126e,379e0dac,786c6e86,11796b5f,44cf8f64,5254e08c,424dc9d3) Z8(b8488d55,2e08cf2b,886cfefe,0feece34,f8582659,9ac582d0,14204e68,9dc738ad) },{ Z8(5fe59211,a24c5d20,2c4e8bf5,e6df49fe,268b4389,989e0803,7b914ad9,bc3bc9cf) Z8(44878c62,203577de,daf6aae1,981e414b,64b3ddb7,11ff93fe,6cf48c89,c9994493) },{ Z8(27fa60ab,ddc6b473,4dfaa2b1,38b94eb6,48526969,dbae43ba,708ba13f,ed213d83) Z8(6e7fb1e1,870aac84,dc636c6c,069417ce,9e9e2d58,015216a5,783ff08b,9e9082ec) },{ Z8(60df74d1,c54a55ab,c83ecaed,27a66fcb,284c6390,a14b5b0d,4e999059,7a255737) Z8(041b5ee0,4f75f241,6ad7f15a,84891349,068fb449,a1660261,71da8f3f,c8fb18a8) },{ Z8(13b4bb64,54ab6869,0f005d79,c66d69cb,e5e0de6a,0afae163,dbfeaf35,5f266059) Z8(8101780c,59731103,c3f0a747,9040c45e,c1019984,6a3c7aa3,66a9cf90,9f592e9b) },{ Z8(f268261d,f7deea62,7ec4adcd,2ab491c7,34643dd5,412b54db,74f5aa51,6e32cd41) Z8(7d820c74,aff3c424,bf157de0,122876bf,47929682,14ef546c,6ed7b6f0,c85c23c2) },{ Z8(f28301ed,0d175c6b,e51ca4c9,fa8d59cf,e601f617,cde40777,2be41884,26cceee7) Z8(43f85dd0,9e38d91f,afc59c70,383f369d,02e31f6e,a6552176,33bfb607,a0213af1) },{ Z8(a045d1a2,12b3aeaa,3fab41be,27cf56e5,9ece4c11,4db25c3c,0e7c06db,25af3495) Z8(4679640b,cde9ce0b,4cfc0dff,99fd0fb8,08b49c99,8b09594f,58c4c78a,c7bc6680) },{ Z8(62c7faa4,000a21a6,d5c577d8,084c77e2,e4fa0d9d,388f4620,7dc82b30,42b1e8c6) Z8(68656948,076b9b0f,3e534358,ecfad43f,9e9a15ff,11fa50fd,d33c828c,a0e8a725) },{ Z8(cf4f372d,509e6f8a,a7533ca6,62e30d91,388d1e0e,10e96fe7,6ee476c8,59ccddd0) Z8(56437f1a,c40a4f00,dfb0a1d6,7d9adcb9,a03cca20,e2da5615,ecd6875c,c71be181) },{ Z8(d0eaca40,52441e30,7da798fb,3c501091,c3c7eb97,3f796a65,df7f6935,6320cbec) Z8(1094e8cf,ea4ec71f,c82b9b58,0ad3ae83,aca5adad,0acce6c2,d8fc33fa,a1af7271) },{ Z8(0982c705,4018a644,29b10c97,45d445f7,e561e9a3,e3d5ee51,02fef304,e28f1559) Z8(42b30f7d,bd6965c7,4333b6c2,066c35b9,cc55b98a,45b71ac7,affe01eb,c67a9567) },{ Z8(d517276e,b70ff3ad,973634be,ef29ee5f,93f211d4,6ca11f40,914f1901,7bda4332) Z8(4ad66f31,bb0b7cdf,cb1d9eb7,82c66160,5f5405c1,527c32b5,79c35582,a2759c0e) },{ Z8(d1b06f8b,122b6b60,8dbe2d11,02336e0f,29d5350a,e9896341,5da0dddd,4676a1cc) Z8(16de6ad4,365389b7,f93655d2,4f82ed4c,981e3480,7c07d28e,ee48030c,c5d882d2) },{ Z8(e6ad2e98,28730c2f,be4161b8,a4aff1fe,6ee08661,da71bdf6,4834c677,0496f5fb) Z8(cb558558,e7849d9e,8b2579da,ab28cb60,bd34862d,f2a623ca,8c05c9d4,a33b2335) },{ Z8(9fc86c65,bb040495,66c6dc11,3e69ea0f,dca2de26,0462a339,86a5b775,2e71debb) Z8(8b024b74,bb0e0230,aae8b1fa,623f1eda,86f32a1f,9271d995,ba3bcaea,c535aa65) },{ Z8(6ba387bb,62a14d7d,df192ccb,33f91922,6f7e7f0e,711adcf9,ed8758ba,06e3e927) Z8(455e21e5,cc364cea,1afe642b,f105e130,5e038346,d6b17382,88acf49c,a4000721) },{ Z8(a5764264,41b7e613,44f2d217,569a58c3,99d81f84,0f57cf7f,515ed81a,b093ee31) Z8(bcfd3bb7,885b981b,c2052ca8,66371ac4,b08884fc,1b38827d,ec38fb89,c4920cc2) },{ Z8(c2f0dc57,1dd2cd8b,e5d4a44f,f770bd16,358ae087,827c7ff2,b77857fa,7c3b618b) Z8(525b3f19,ecb08b0b,a6a090d6,9bc62f2f,691bfd87,f236b9ef,8bdd4185,a4c4470d) },{ Z8(d3b977c0,97790ae0,12bf54fd,0cb86957,7ccf7016,31335dec,942639c5,1d0b40ac) Z8(ef8179bf,0f24d3cb,c086722d,621f8db2,566629d8,1e410878,21d4c073,c3edaa8e) },{ Z8(b59e76d8,ebcbbcb3,8135b970,ca67bcb8,1112d213,3b933649,b9eee978,bdb97a99) Z8(810cce73,634a21b1,08d93793,16c3e9bd,62cdd293,6d02b9c6,55bb0808,a587e235) },{ Z8(5d951b21,af0ddcf7,f210dd4b,155ae8da,896dbd42,24b3c22f,aa953d08,c4542be0) Z8(1bf5caac,fe376bad,c51b4c13,35b4e9c0,9dd1381a,8ffe2bfe,bd363133,c348846b) },{ Z8(65621b65,c5bd01fa,d4acaafe,2a53dbec,5dc52f57,f4e0a47e,8e450c7c,33ce3c5c) Z8(fc6435e1,a41f60e4,64de18d4,a47220c4,dedd6862,f0f720bd,4b2ecb33,a64ad7d5) },{ Z8(40cab1ea,de676c83,f39fef84,483c80e1,d33a2acd,9fb0c4f4,bdfbddec,644cbd64) Z8(5453898a,50b7417b,9b834dd2,589e0206,4fac0bbc,ecbd60c5,e471ef3b,c2a29b00) },{ Z8(ce32a23f,99865f07,caf12b08,a9f717aa,006142fd,7d0d50ea,30372f5c,ed0e2843) Z8(6e58ead4,f3db7eea,c3079246,96dabf88,12bb748b,da0ec907,76a8d4b6,a70d272a) },{ Z8(ebfdca6f,f9d19c3f,824996aa,4ed7d4a9,e622f071,72f6910a,69f13e45,a7b77d3d) Z8(24fdc9f2,b5496272,343e53ad,fe814ec2,722f643f,5a613ec8,80e4ffdd,c1fbeef3) },{ Z8(1d531087,dfc6382a,2378f667,484bb783,b518e14a,eee14b02,b7c8256a,69ce99ef) Z8(755165aa,26a49b0b,dc708c02,84394ea1,bee3c202,ad8e98c4,88e42a5d,a7cecf72) },{ Z8(691e5e6a,266aeda1,dd19990d,0bf9c1b4,fc54adb5,42438571,012ad137,cae4d306) Z8(21d398b7,486d9ff4,dcf71e73,42542cbd,83b0fe27,76825189,3e8ee2f9,c15480ea) },{ Z8(215eddce,6525549f,55430115,ff9d7a6e,72ac7226,1a0fe34d,a9975ce8,4214f8cf) Z8(c6f12a2d,c985491e,e735f8bc,20f7e7fb,f9e24399,e2f3c76e,d9a8dd47,a88fcfeb) },{ Z8(6db6a625,4148ab97,27ed8b40,9e2eb1dd,e2f2afa8,fb6290b1,4361b8cc,9660116b) Z8(7de9aa6d,7a48a6e9,4356fb50,ebcb8bed,b90cb15a,ba37a3ee,8b6ae710,c0ac518c) },{ Z8(ac56ec04,890c3730,d422d132,ff83b0db,c29b765c,1e13a30a,8f606b95,01038993) Z8(cca5cff1,a3d8a26d,b88ee895,fceac47a,73819370,af7af179,688db20f,a95027d5) },{ Z8(1e6fbc6c,60d1c2dc,e7c30f32,9619cb3e,2b62c8de,4bca8792,51b3819d,e9b6ce2a) Z8(e43a043f,ce6e660a,1bdb7eed,ebcc6e6e,b2a73066,1f6ac151,96c8bb55,c0036182) },{ Z8(48a44a6d,a44af301,b6066288,e6ab77f2,bd9c04a5,f1f67e10,3f16aac5,9294d3a7) Z8(d5bb8102,ac216fbc,187f1471,3193b47f,3911b8a0,2c28520d,ddb92123,aa0fd66e) },{ Z8(0ca836a7,3320e22c,a88c1652,37c0d3c6,0e2fe16a,0a605af0,292cfca7,3da58f49) Z8(5fad5a6c,11c6cae8,1877c028,b4e48306,567cf3e3,75969296,50a44068,bf59b175) },{ Z8(f9f9b33e,7248794f,88ec1dfc,0529d89d,0df30a43,c1441a52,a41619d3,32912522) Z8(14f9e381,71e34834,8ad5534f,35b862cb,faf9f80b,d6081229,8aa1ae8d,aacedaf8) },{ Z8(54b9549b,9827b85d,fd615c97,79d8c10e,60f8ed0e,02c23a19,497cc6ca,9d776ab3) Z8(1e4ff94f,2be7f6e0,fbdfad15,e9da1856,4624c532,9524be9b,68fc986e,beaf420e) },{ Z8(cb130e48,de9a0465,19d3aa6e,13da5dd7,65686c06,38664d38,9ec7f704,d2cc1f1b) Z8(f55b9e01,c8d57dfd,fce43d55,dc2e7109,c65d7e3a,10ed343e,6acd9872,ab8d34b3) },{ Z8(3d0097bb,acb3f967,18b3a28f,e3981a86,aab2a1f9,bcf88c51,8b3002ee,8a52d51d) Z8(ea4a4846,283fefa0,243de8f2,d75a5560,8cbf4da1,614946a8,4f2a771c,be0413f8) },{ Z8(c71baf37,feee7693,1def3e87,c00d7342,d3b5f168,8905b801,a932296e,3052e595) Z8(5a4227e6,24607c29,10bc61d4,c3a65366,89d0d9f9,fe4592af,2491db72,ac4ae2e1) },{ Z8(f45194f7,62c09480,62754be0,fb383dfd,ba10a2c1,f696a48f,044f2aaf,f2eff911) Z8(a91c3918,d119698e,e35b4c83,c7a88750,a1373c37,483f3902,3135b26d,bd5827de) },{ Z8(0c02f411,1ff32882,cef2f697,a350cff6,7b2c8614,44556858,97ab55d4,e2546438) Z8(07cbd9f5,d6b23197,6f51e09b,636e74e7,b0ac24b8,a3a9057b,09d08c4f,ad07e4c4) },{ Z8(2b506e3a,80a59c78,ab1cad5d,23020c5f,346397fe,87a14359,25dc1e2b,3ac99c0f) Z8(21761101,1b34047e,c64a4e73,8ab14808,a376bec9,b122c574,fb2a14a9,bcab7e6b) },{ Z8(f7569076,70c9d4ad,80dc17ca,ac32e85e,f6ff8689,29267ea8,65ee7ef9,71e3bee3) Z8(9badf8c4,d5daf23e,b7a7d9fd,837f508a,15d858e3,07986543,18b685f1,adc4399f) },{ Z8(c3c551b0,9026ae27,199070fa,1d0a39d8,09f2b280,824d3570,5aa9da99,37c47c53) Z8(0e553a43,d3883121,79c768aa,b3cf8cf9,6d948663,85540223,566b7069,bbfe184e) },{ Z8(f5459f68,b53cadf4,06f81956,e7c8e051,27e858ee,ef13e9a8,a6a40f98,0a971a49) Z8(cd044cb1,7533f532,646425fc,476747c2,f140a488,966e1d6a,fc786b2d,ae7fe0b5) },{ Z8(8c9582b2,94980cc7,5304c25d,1fa13c55,d8e7df66,cc891f2d,d069f9b5,106dbe6f) Z8(e35575c3,e4aee845,0e7e44e6,e0bfb8f2,b9d993b4,c151839c,a908f73e,bb4ff632) },{ Z8(c677e41b,9143c42d,c266f052,b509c11e,7ab985bc,619d8270,62b33d6f,072b8bc7) Z8(38ade61b,d1c17663,23d57fe2,15606dd8,4519dcaf,cdcca897,0e0efb84,af3ad94d) },{ Z8(4da93476,ef62efbe,a51d4c60,cec5f580,6e1e1ff7,d45aa122,c42ed5cf,468b46b4) Z8(424db0af,ae64c22d,722801a1,2f94f99f,77159480,b651d3d6,150fd3b4,baa118c7) },{ Z8(14aa239b,5ca19494,f01dd6c9,bf408993,bd88ab79,4f0ff52a,1dddf51d,17a7b385) Z8(27ff6e25,bc4d5213,6c228e0a,9a5dfd5a,16e33f5e,d9defdc4,54f2ba16,aff522a9) },{ Z8(bdc5bd4f,12332859,5fc193fd,c3d84b49,1d084321,d228c5af,360e0103,56d55b53) Z8(d122de5b,4c3f8862,becacdd1,12230f14,95082990,628e135a,77dd0751,b9f180ba) },{ Z8(40bceafa,32bea5dd,d2ef9124,3326d7f1,b6e13602,abd4e97c,43831456,96047e2a) Z8(6d1d1abe,d0586057,3e912af0,ca6cb5fc,ceb0f64f,7d82f3fc,87d6e61c,b0aebc10) },{ Z8(479b3a66,997ffb26,67eed7d6,c8eb495f,6f5aa8c8,d4a72b22,ee097db0,682e9672) Z8(c908f94c,65aa441a,bd6d47ff,37a95ec6,eae2bc42,022de97f,696e8d47,b9412ebc) },{ Z8(bb6195f7,f25f9130,1b9549c0,e65999ff,92b101df,0963f8c7,0e6b7a1f,537a1a26) Z8(b926281f,53d6d400,078baa0c,c3c1225e,7cc23bd3,4cf5493b,0d63c424,b167a4c9) },{ Z8(86802969,6b056974,8fcdb467,2276059c,81be199f,b036479c,371dd16e,dda15e63) Z8(e58884d3,95e185f8,df940fa8,053730bb,9016bfa1,b614a053,3bb3c284,b890237d) },{ Z8(6b25eded,6c355392,d60a2c0d,cd4c4f37,bc7bc645,e4c0a8cc,4db2ce0e,d8038e83) Z8(ffa4d664,f6ed4a1c,231d611e,acbd3dc9,e999db8d,f1d197dd,fcf0375a,b21fdc19) },{ Z8(8f63fe0d,b442ef46,3cbe3801,2adc91be,47820e40,356b6c1c,cb456399,96399059) Z8(3645ae2a,ede1d3cb,faeace7b,86e6fe7f,6ba0965b,d8702367,f9dd13d5,b7de5fad) },{ Z8(a4ba456e,337f8452,91cfce6b,280080ed,d4011d71,42e8bd78,674d79fd,adc9eb89) Z8(3324815f,b026e673,3e29c1bc,e6d838c0,a77e1ca3,df2d6e20,1f3aaa24,b2d7614b) },{ Z8(8c842515,2adf15a5,b1c84bf3,79d6bf35,2646465b,94570eeb,b3b7ab27,fd5c5984) Z8(8e92b508,fe55d6ec,f0224a4a,f203f6b3,14c3d7d4,50dbdb7a,67aaf2c0,b72be400) },{ Z8(aeaf3f7e,dbc46936,4825ea3d,70d3a1ac,6c5d41f1,68bbf9f9,33a43ffa,7645763d) Z8(c2e66b84,768e7579,41f16117,ff47c12e,04145dc1,8d443c3c,ef214550,b38e33a4) },{ Z8(f9d28424,773bd205,da771ce0,71968fb0,627d099b,800a19de,1577763d,8a95419f) Z8(d0d646ec,d9f91389,acde57f6,f1a81925,2e79c13f,f32a51e8,00bc11d2,b678b127) },{ Z8(efb95d69,6f114a27,eb08228f,b5536120,2b4ae134,539ad8d9,5b30f6ab,111ddc38) Z8(2aeb4aae,d103207e,b2b133f7,11f0433e,434a59d1,05913765,9a597529,b4445270) },{ Z8(72c91199,73399f6c,2c4ab755,4da5f5b0,4e622c2f,62ec3d35,3e185eac,81bddfc3) Z8(6d6b90e8,9d9c53ee,e74fe751,3e73b6e5,4b1a498d,ac786ccf,f7dae915,b5c4c7d4) },{ Z8(4006f8a9,d5713745,2be2d16b,721dc592,34a02103,ade26dcf,99e2b9c0,e002efe7) Z8(f06a5b98,76efbf2e,da395601,3bbc9894,9f0d41d6,3a53f0b0,0226bbb1,b4f9bcf8) },{ Z8(a8140fbb,4ae92cf8,c2be9804,8c19f8b9,fd595376,694150c3,2cd0280f,5b1a4e4d) Z8(6c2d0fbf,6a1bbeb8,db5c1c7f,8406fdde,4974fe3f,fa0b372e,364a834d,b51028be) },{ Z8(f641a4ee,ba070aa1,7c9828e2,76e9d345,5b14a748,b3db3b6d,5d804b74,e8ad23b6) Z8(80f7b8b0,35098806,29d77010,e0a580d9,8f8b7a30,5753847e,bc10cf51,b5ae7285) },{ Z8(2a0c4b42,3726790d,f61b2a70,8b698cc6,4e1e4fa2,d7160eff,140ca7b3,5215df18) Z8(85e8e950,37e63acb,5835239a,8cd14b17,ec8f22a6,dca4cf40,5b1294ca,b45ad497) }}; const mp_limb_t arb_sin_cos_tab21[2 * ARB_SIN_COS_TAB21_NUM][ARB_SIN_COS_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) },{ Z8(e0c338fe,88ff112b,0c6e3774,88fa840c,ecc8f425,0a577f0f,e81559b4,da7478d1) Z8(85478845,528aa663,586b7744,fbc1d444,d865d6dc,d5ba05a7,41cb9c87,baade981) Z8(68403ffc,f11542a0,6437deb2,ce79b337,a2f156f6,0c75859c,07c31166,972d7430) Z8(ceb0c3bc,a4861b3b,8bf80ab7,b0abbc78,8b68d1e0,0d110d31,cc05e7ea,ce593092) Z8(af5dc645,593ad65d,03993f4a,eeaefea1,4b00a2fc,2dc7f173,d2bd9b37,9bea135c) Z8(1971c7b0,dc728536,23b1b1e8,211f57c5,93279c9b,943a5015,358fbebf,4fd0cd79) Z8(a81be4ef,2b15338a,c6d82eaa,1a19316a,a4e8bc2f,1beb1df5,d6ce0dea,a253092d) Z8(5036e35b,57c43b8d,09d059b1,98b8b569,46e2bf16,9393a979,f23e30fd,b163120b) Z8(5aa3c321,8a3ff9fe,120a3094,62122e17,108c46fd,9495201f,cd8948b7,15742c86) Z8(172ba7dd,4a122176,2be75224,65987e66,3c2980cc,fe0950e3,fbe7dfa9,a7a384c4) Z8(97531f52,4bba608f,d0e66952,61312726,91ef1758,9d5c5167,49655abd,e8eda144) Z8(ae32ae0d,67f16e15,97a3fe69,c315e024,855d6f35,04dcf0f5,fd68973c,5ed90796) Z8(a4360923,e70151ff,795df5fe,5c0966aa,7456952d,041e08d0,20a3dd14,56d51c04) Z8(423f2dab,06934477,d4e3a491,1d377066,246ed9be,8ba70628,47b3334f,c45e01ec) Z8(f9df42b4,1fba9602,069ee165,49a69418,7d0d19d9,4fd549a6,b641cc46,c156b690) Z8(f2dc36a3,3f3539c2,d3587a93,151646ca,0cc2644d,a6030f37,fa92f8d4,258f0365) Z8(d76c7aa2,144d32b9,855bd545,58df22c8,b8e9f930,cc5797fe,df450ee3,b1e32374) Z8(5a7ebde5,7c101591,c611113c,e5790d2e,b51e4655,2bf904dd,bbba1ba3,07ffaaab) },{ Z8(dd3a35ab,a15a52d5,c9ebf51e,8dcdb495,63d2504b,4cd532c0,417a36e0,aadd2678) Z8(425eccff,a5334f82,97e2777e,a19621c2,8fb7277a,40dccd39,0069ebf0,2c565ea4) Z8(45dbb553,ff159123,0aa763a9,8067cb39,6d765f9c,7102991f,5e6f33d1,d400589c) Z8(d27406df,36f6e1c2,a41e26c6,8565c202,efa3a9ae,07795e34,1c2ec4de,9aeb3038) Z8(e333b9f5,6033bf50,3508b960,8b9906b5,94c2061f,99c0fdb0,c975f687,477ae548) Z8(ea6bfde2,42d94539,0a6a6402,4935dfe7,ca4be966,74ec36d6,8f29a707,77284117) Z8(7ead6d11,fb8a01e2,f9191758,9c025d24,cb2f59a0,44286806,8ed8459a,660b6c56) Z8(eabaf865,5d070793,dd6e089d,bfbe29ea,4b674685,68074183,a0a1596c,13b55eca) Z8(8ee3bc75,4492431b,24d83de6,2f7c8de7,f9afed5d,0e5ef52a,9e48460e,cbd6e11b) Z8(022f6cf9,428bf4d7,6b9b1e25,2188d2f6,c66f5ca2,7d2ec765,cf0ae1d2,2da2960e) Z8(25c58808,0c947978,6d5dd635,fb0accf3,b29a49f8,2a02c8ba,28313397,d036ade4) Z8(83385cf8,6834d913,72a40660,3b42a69a,f7d6b0a8,49d92c20,02a48b6b,2aec3026) Z8(f056272e,e7bc96a7,b42abbd1,84df4b33,d3711284,b11a8231,aaf43244,a23cef69) Z8(26fd8cc9,120b47d0,0c3f418a,a09e7cef,967f14fa,8753c6ea,1ef7bc6a,d046890f) Z8(48dddb88,75943bdf,cd78fa4e,997993d2,3bcf102a,a6b0cab5,8dc658f8,de7d7416) Z8(11a56ec0,8a3d60b8,4b5fd1ec,a15eb205,4c229c78,85d6503e,670f22e7,2b1b8482) Z8(b371a8ac,4d44035b,0403f94b,fc753c97,a918e8cd,f252a14b,87eae02a,c062a312) Z8(178307b4,79a38edb,4a661fc5,419c52ed,94946fb9,576da4ec,a93e9589,ffe000aa) },{ Z8(62ec14eb,a8e0a5f6,10afa743,975ecb18,d37d0c3e,24f9e99f,3ae6cbba,1d5cb8d0) Z8(7ca7f6cb,a3bd8631,b1ade456,d67016f4,b1f5b7ec,8031d97b,de1e475a,5d5e11a4) Z8(8917d7f6,ea72c1eb,810bde4f,3603770e,a0c0e737,fffe2db1,4ded6e59,6e868a46) Z8(43f15442,d69ba718,5724d3e7,ef652979,7025dca0,c0068509,4b342437,ae721382) Z8(24ca37d2,d61a1d73,4daa0a71,136b22cb,55b8706b,339e8a36,fdd055f0,624d3f59) Z8(a052837f,4e51b4e1,7e11b078,4b4c4dde,68c94ff6,49f8c5c6,a6172898,b52dcca1) Z8(334cfb1e,b5fc541d,19aed5e5,67d74d90,f0c6885e,1b9b0c74,1c52627c,c834a323) Z8(8f3c774a,04cc5f69,a3c0e8e8,9e3d729d,ff026a90,c1e4d4be,f0ede5dd,ce220649) Z8(d2fa75cf,b2561b40,4d1ddf9a,106bff9e,faf3e806,49ba3a59,4e95a076,e844a836) Z8(eb29b59b,a70ce192,8f9d760a,91acde33,ff330c56,6ba95433,36c50df5,46cd586c) Z8(0bd428b5,0560d6e5,a8baab3a,5a2435f9,33e20ce5,c743f8cc,ad9c8f5e,feb33871) Z8(3426381e,d962c4e0,1e7ff5fe,2c85d140,e0abbc15,d6bf70b4,1731ba78,da613cf3) Z8(c0a3ef50,6746ec3c,747ada6c,bc53937a,d4d6469d,c3a81549,f66065bf,e443936e) Z8(b1e5ed23,a1e0ca43,52f5e750,fc00982b,1279c284,b4288c0f,fa05ab98,e3a1c261) Z8(0db2566e,0c35a5cf,08aaf2ee,43c1dad3,4ede8cdc,4e28f222,bf778a8e,5032c8c0) Z8(1ac0d7d8,8ed7557c,30c72f4c,47dfd0f8,c5a0de7e,78296297,96f19a00,cb583a45) Z8(7e56278a,89187c07,eb2f7c1d,707140fb,f05f828c,7df2b307,50480352,ccb76f0a) Z8(d8b57b62,c2fd5380,b9cbf2d7,fb074dfb,692d4aca,5d259b2f,76a76d5a,0ffd5577) },{ Z8(b2f3a461,bcc05676,e32fde39,c97fda49,5f5f3732,b5ffe9c6,3a485acb,5ae8e291) Z8(9f2a8018,61770423,3f4f8063,f5136161,dda87ae5,1c93b4cf,20980571,ed54ff71) Z8(395760ef,21a27ad4,ae85347f,b10b210f,df345326,b354754e,1576c5a5,d7b91567) Z8(8696d86d,07c16269,e61cd462,0c9747a1,a7e0f9f8,d8f7ac1b,8c698bc2,75ada6c3) Z8(ab912147,4bdc7922,69f16066,4c3ee0f1,945c03ea,e2c2253b,a36256c7,07972402) Z8(476c4263,20a2e7f8,6390abe6,611d379d,5ac779a8,f6e2efb8,9cfc47ac,b0502507) Z8(eb3f410c,00e83e70,01989b9f,d1ab1d06,2874e6ff,a6f64f9a,0d55dc43,94ffbeb7) Z8(1b2cc713,52891210,7ef259a1,f9cd7e0a,9489f286,90a7b3df,707073b8,67eb7d50) Z8(6af0edc1,e3d7ff4c,c0aab52e,9e1a05c6,fab4bdfb,b75e84b9,8debe52d,ec150670) Z8(75e2a407,ad4094c5,a73d4f2b,bae254a0,960dcafd,09a88275,e0fe9c25,e3b0e3f1) Z8(5f545f16,5b74e740,1f33c07a,1a80077f,9437fb62,5329e655,5df6de9a,d3150c03) Z8(9ea77159,75d9ce75,3f4ba064,e1ae5385,5bfd83ff,8bded550,27fd19c5,d22dfdc5) Z8(de4b45d6,8f58de60,e18c3aa1,b498d248,04e57a1b,acbc896c,d6c388f1,5439bea4) Z8(bebe8e59,f1467c91,1cbb2c01,bde418ed,19e2e127,bb2fcc2b,5d2603eb,8e28b193) Z8(95bc6bec,2b99c9a3,0a290389,cfb2759f,67fa0196,cccfcf16,af6b4d46,eb2c5f58) Z8(b1ae7846,d02b97e8,84c1e0f4,96ee711f,4a0e45f7,41602038,fb825705,86f62731) Z8(a4b2a421,ccd95f9d,8283e803,a116e80b,db02969c,383c3ab7,342fe205,b609267a) Z8(c3e646d1,fff062e6,5a2928bd,f80466e8,4de215b8,070f7328,4fa69a65,ff800aaa) },{ Z8(7e3d1af6,306e1398,1f737361,e0edd53e,c3b2c911,6eb951b7,82593dce,77339be5) Z8(dedc46b3,fe78a065,29a1f9f4,19182e34,a575361b,0cc235e3,c63b29ee,37172d63) Z8(ecc25c5d,90edabbb,2a1ad5d6,9f8688e5,324ac1cb,9938fb49,d683a12e,39b31ae6) Z8(1f6894c8,a79baafc,670f5399,47760acd,b8711b88,d966d630,fb7a21cb,2f3b9786) Z8(7aae678f,dcfd3d4b,5389393c,8f65e3f1,439f7fc9,b2a716c2,c2937690,0644349a) Z8(814a9296,b437ee90,5d97aab6,11cf9373,15bb199c,11c6387e,f7ecad17,fd9c1287) Z8(fdd5c3f7,78efaa15,f4b43663,6d370f11,513cc759,35522296,67ea06cf,619bda6b) Z8(e88c58c4,8eb31996,7aa3df00,8bbf1ba0,ac316236,9e74b423,f49310fd,fac7d829) Z8(abd1884c,834814e3,8d305e8b,d2e1ad20,f00a35f9,aa4e003a,fd4e3808,c6e3e2ad) Z8(687d53e3,473d7d3b,cdb504a0,9c554870,29045ed7,8eecfe5b,9c5054cc,a7aeabe9) Z8(5f98af21,639ff111,0c74eb09,f5e082be,d4d04a2d,596380c4,1687fe49,31587c86) Z8(b3a0cf25,d9d29464,b07c1169,3defaa77,63965af6,9149a497,08487555,171c586a) Z8(c431c150,2d3c3440,8b7e1f3d,bc9d8a89,3749f89a,b3f0f6d2,6b67ecb2,69df13a4) Z8(7a8f745f,dc6230f8,9f242116,61ddd376,44b8e911,8ddd0266,b5799624,4a4e3552) Z8(c4b699ef,c646f1d7,979d9cf2,38a5ab15,836bcdf0,a4c2fbba,32bff9ce,1f92ef97) Z8(1146a05b,ac6c29a4,aaf430c3,c5f5c19a,28ed8b5c,6ba19947,bda60cad,fc9fb9d6) Z8(0566391d,9e5c45f0,77b2a1c0,669ee14c,a4e4c850,27c6f292,1adeb42c,0a60fc19) Z8(db21f7ef,cdeae791,c393f5aa,e59085f4,501a1007,fc2d1800,2550e41a,17f70103) },{ Z8(717e2dee,8181dd09,4fbe442d,9f7710c4,25197ff7,6b5cb80f,495a19b3,8fb336eb) Z8(ad5fa360,b03f488d,e0350c6c,67389da2,feba6bb4,dc469f07,8bc497ba,ad8209a7) Z8(fd7f504f,93c5c665,4c35b590,d8db2f2b,8ecad7b1,51d59c53,cb60d901,e192f6c9) Z8(46440e95,58a04ebb,5820b109,dbe6f75b,f45d4003,e754dbe0,44194525,172b408f) Z8(d77f665b,86fbd691,cfb76d85,287e0e00,3c95c390,4655a400,aac98b30,f2fb2eed) Z8(54fee76f,5d532986,a2d09494,9fe0b07c,c06a8c62,5ef24a5f,d6357ec1,bda668ba) Z8(3246f86c,0806152a,728caba1,1494a85a,e89c6071,fbb05174,770d8a1f,81476141) Z8(f56b96e8,6a942c92,993435c1,3672b8cb,83174794,8a58a19e,c5071b25,7f71a072) Z8(37c1de49,de8ff2bc,63074017,46037024,7d316fac,7e399f63,4f7dc79c,507d066e) Z8(10c0a5e3,6996d46c,ca174c1e,0bb3e3b5,da387f6f,a760b60d,46fee35f,84394e7a) Z8(2ba8b8ba,a743a6a7,87ca2639,5e3ac7f9,8b60d39a,16c7862b,3bac9bfa,3370b3e4) Z8(2712f19c,d097e6f9,3cb39a62,8a86eb33,7a101267,f80922c9,a9bc4f88,6a1f9fe8) Z8(b6c41169,53eed228,90c9f40e,ec201e7b,71db85c8,e2786ac7,0c770c0e,1259c928) Z8(b062bdbb,fe68b0b8,010b5eb2,6425f375,5192867d,66c86d32,f44635b7,8d13b867) Z8(e849ee34,e9f8c4c4,3d89164c,016a3c1b,8d767fa8,bc290f6f,ce789107,1c967b97) Z8(4fda24a8,c0b74c3f,043aded3,8580b7fa,ccbf3c84,4f06a287,5ac5a313,2b22b952) Z8(76835799,629120d0,53e6ac1a,dacc91af,01b35920,6ffb549f,ef3f03ff,dfef1c85) Z8(d817f7af,f56a11fe,b961faad,c3813d8e,1b6b28df,2056a6bf,f35cda63,fee035fb) },{ Z8(9285662d,68ba398d,3b2de5b6,9c699e5e,a2b81b46,c98095a4,c21ce9ea,3342e3b8) Z8(665f3670,f2150d02,3175ca01,c80977fe,929f681b,b5b4c832,c52d661c,55fa7f07) Z8(04edc321,5dd1ea90,7a5864af,75aec5dd,3c3ca06b,79952f1e,c1a1912c,41281b8a) Z8(af9e96a2,bc896c56,42f4ff0a,59f26c0e,c7954044,c8d44eb7,315b23b2,9ba58dcd) Z8(d551a20b,27dccc71,01971d0c,f6774470,3cf54616,6f677f73,4d3fcdf5,915ff9e2) Z8(a48f12f1,b4fdb069,9347d23b,7fc4ae02,5bd79112,c3d70fa3,4f17cb25,c60fc0be) Z8(de9a11fc,2eaa8bfd,0d0f918a,bd92cf7c,4a1cd81a,6ed6ef9f,fcc20b8b,b015e493) Z8(7aea54e4,3baca448,63000f9a,ea64383f,ad9a4ff9,8e0ae851,5acda69f,e664345e) Z8(9f488c0c,358e70e4,4060242a,2a87e378,ebf9639d,e5d22873,6cfea8ee,f61b09e3) Z8(9b544346,19bfb12d,355b2570,73858e70,86c11b6b,6165c197,14cc2524,ae838a8d) Z8(bbd8d13b,ea3df091,780aa0bf,1df65e24,d422c944,f4fc75c7,be9b4efe,be4feec5) Z8(fb94423b,f8e6b977,34674541,1f359d5e,4834fe21,32c4a768,b8231781,15056776) Z8(f90d0057,e8c71924,e08ddb95,6e99bdf0,986f913e,d1662ac0,4f1e78b6,08c09a8e) Z8(a29cafd3,a4fbfb5c,493c2b1e,bbb58379,58ef9359,2694ae12,6cce4526,041432da) Z8(0a4770f0,176272e3,45c49bc0,289b9c51,0f0abf41,e5324ee0,ddc6d5c4,c9740eb8) Z8(88012cbc,beb05538,52f75f62,c7ed3324,ac4dec0a,3702f2fa,6c96888b,a69c919c) Z8(c3450e07,fa68567c,427dc1a3,e5bd5ed0,497e9b70,9c828f90,1ad10ae2,d190d545) Z8(59fd631e,007995f0,5e671884,5995027b,1f89f85a,069a8672,86ee35ca,1feaaeee) },{ Z8(b906ac44,d31d2737,071aae53,a81afbe1,1d0b38fb,e486e131,86fab677,43e453c4) Z8(fb679d1a,6b01f0ee,013b5a4f,85b61a97,0fd1d34f,1a07514e,e9fc3ac7,7e85e745) Z8(113c120c,c12388df,9374012e,6a8ef806,aa9c3d43,eec33f69,b728d8d7,6d9990e7) Z8(51ac8ec9,dd3cb025,543878e6,c5616c41,2a00de1f,081c375f,94dbdc7e,b14531ec) Z8(7edededf,2bfa77bf,6142767d,329e99a8,8caafb05,66800987,aff490cd,55fcc5a1) Z8(f4783c3e,cb3ee0b7,b41a05b6,b546fc3e,77ac426a,ed2ede34,813e3302,b7c6bae1) Z8(c4d2a3ff,44fc18e1,f1d72b79,077fe168,b1a4f0ba,1b37c6a1,ae525476,c82c8f15) Z8(512662e4,3c3e5961,655dcde4,cca52963,5efb4506,c17c34c5,fcbeeab1,ef9d3fac) Z8(fca17389,fdaf92fb,a37e0c54,ddfd90ef,8f34f1cc,ebc44c35,703099e5,09145a3a) Z8(0f583d8e,360ad060,fdf75e54,cb0fa961,b6bd91b5,c6680c51,374f5feb,0cddc52f) Z8(630c7b46,a25d5ade,6408e48d,a2267716,190483e7,99dc1842,6b98b0f4,e43c6d12) Z8(d708bb4b,f7bb4bf1,e7a3900d,8e27fc26,a4b7b501,ade110f7,c987082b,9ddc2cc2) Z8(3cc973c9,21777ce8,cbdaeec8,fa457f1e,2d288e3e,e3de84c9,131b0e16,dec6b5a8) Z8(40bff4dd,fa0f98f5,6e4f53d7,9b07d7c5,f1023070,63bc9832,af0cc648,045c373d) Z8(7711011e,0b477e89,c44052ea,8f6b96dc,ea22a4fa,dbb5f983,b00d7ec7,da201c52) Z8(ca721152,37343867,d0792aa9,da0120b0,954bd6b7,6509c28b,b5912d38,0f28806d) Z8(b7a7f8bb,65f0ab60,6d2a89ea,f2a44834,6b128c15,b1146ebf,41c56b3b,34935607) Z8(e7026cf1,962ddb33,783f8310,649bab98,f6f18ce5,1e6a129d,eade9b6d,fe00aa93) },{ Z8(d6c90eeb,5efbae71,ff432f81,60f0cc69,5715412c,bfce4e56,2344d121,0965d777) Z8(2163e83c,0046a728,bb9c3fb8,864cf453,6c3ecee0,45228657,320e21b0,5364fc9c) Z8(0333b45e,227e6637,7dca7f31,98225247,10d79b41,913e73a4,f2afc29a,cea093ed) Z8(cf057c7d,48cd7cb0,691e37cd,307f20a2,049f865d,da31d7ae,075f79bb,4f489d5f) Z8(77dd2ee8,7e58fff4,f59c5157,a71a1455,de35f4f4,2449393e,fb2f77a6,35de80f7) Z8(b1d83f9e,901ec905,50f6af5a,0eb56d43,f560303a,0cc55115,eefeb90f,fc069560) Z8(b2b60a59,f7cbae33,3b11826f,f1a103c1,405ab789,32b0fd12,d86c706d,cdafe8a8) Z8(64c490f2,5fe195a8,f5f204fd,2b072d8d,2c8982e9,47ad4c9b,e545143f,98be4251) Z8(061e2608,3e2b80c1,28650fa0,05963c91,b431178f,50e53848,263ff639,4d7dfb61) Z8(f0c1f6c8,6c790418,67da1798,1c0bd8d9,5f4302d7,ca80ff4b,1d0faef5,f2981188) Z8(a6330c9d,7866ec89,b263d3e7,03e611e5,91983e07,3a264e54,8951deae,f08eba6d) Z8(fd3fa44f,20d5c4c6,8c8da320,4ba620f6,dfb63bf1,e55fcfc0,a4ee6f56,8e51a449) Z8(99438e09,70946b37,484121e7,8d5f60f9,38117297,081f2a29,846ed588,193d3f3b) Z8(0d10f2a4,1cd14d47,aea5d9e2,ccb6ba65,f8d33f2f,fb77f119,d49c0fea,33546a79) Z8(fee109b8,2929955a,2da69309,6e143774,9d8aa54c,3ebc25ae,ff474070,84073474) Z8(8b06f120,7b364de3,69aa07d3,fb7bced6,dee40d72,ef995402,bd534ab5,1dbee581) Z8(5303bf5b,945bf567,97cc631a,101fee1a,c9a382ba,946c7b36,d8e715c9,bb6bdc22) Z8(6234ffde,9b8db9d3,b56a489e,38c5142b,5c87d594,eb335b36,bacd96a3,27d66258) },{ Z8(5e12f35c,68696d5e,10dd4783,102542c8,77892630,58f73581,f646babb,be682f10) Z8(b93bfce0,308366e2,20e5956a,9780d712,3653f238,0de586a3,dad9c87c,4d529306) Z8(39693b5b,a53f9f0c,2bfb04f3,a16b6459,9aa4e938,4214cb73,93602c3e,ba0042d1) Z8(9939fd9e,fed7481e,04b95eef,a4a16095,0a1949b6,2485420a,89a68672,fb062e83) Z8(db7a7de4,f3d1c202,bde24f55,2138afd0,b6639cff,d53e76de,dfe9b806,81f31918) Z8(46d3cb6d,a152e818,ffb15c50,8d5cfa56,9d0e1c52,d3a2823b,a8cb14ef,3cd6ff24) Z8(a990d32a,becd566f,9d7e9a2b,5ab11ad9,7ea3b116,7af7a26e,1d34226a,f12ea1d1) Z8(458ca4fb,2f782353,d2fa2ba8,eab2b7c4,f3c7327a,1107595a,a4dfb194,6dedf560) Z8(2e3853f7,8ade9d69,367fc153,5954fa8a,8b489a0c,25849675,c2959237,3032e839) Z8(44a35a6c,513735a1,7a0da995,455d500b,0d382bc5,dcf7dc75,04447bc0,c69877b9) Z8(f19053c9,b6dfded5,e16b083e,bb826fc2,bf16dd8f,61229267,f3bee9c0,4771f362) Z8(0fc27152,b9d6de50,8397862c,7a1b9f15,038f66be,062a83b5,8f84dab2,71f01f90) Z8(1aa69ee6,7d062493,abd7af62,50d8e1a9,4c6f6ed4,f2bf1b4d,593bbf02,e5b0cd3b) Z8(e4778360,e1dc14b8,c3f92800,31aa3931,64366cb4,fda3dd33,dd1cd326,6bc62d1f) Z8(f5819147,bc1a969c,f254d583,4b3e8a71,fbd79678,523ca325,50d5dfec,a81d6822) Z8(ecd11c36,dbde0ebe,b67d05c5,bbdd0f90,09eae33b,0408d187,25c0245d,cf0afacb) Z8(73c8905f,3b423688,f9e8c865,269f96c0,271485b0,a5a9a65c,649ac8f6,9813c9cb) Z8(ec796a24,10e95144,6f922acc,9dc71aa1,8c45bf0a,6d60c76e,e621438b,fce1a053) },{ Z8(8e602d79,b75923a5,46742dec,e0f34f66,5c65f549,5a84e693,29b30ab6,f685627e) Z8(3f616732,b46c144a,20eed860,bcba0aec,70fc0edf,5020985e,e3aaf28b,4ca61f2d) Z8(8d00016a,484ed26c,5d26a525,5a358509,4a15b5e1,a1404d86,9c0477a9,20dc268e) Z8(af22ed71,2f26e2f7,72f6eb7e,554f6fcb,bdf64b86,fcde2f23,e07e0878,e2ee03e6) Z8(34e2cf9a,30df7366,732d86b1,ec8924f0,02e870f7,64cf7a4b,50e74d69,02ef152c) Z8(54ca1803,d7861965,de5ddbd8,4765e3c9,78320497,13d3a798,6d9dfde4,60d2acb4) Z8(08eb06c7,6cae6f06,01904423,a98df786,c36a3584,6d159a6c,605dac4e,9423adc2) Z8(bd0dbffd,dbef6441,7bc94d1c,c661fba2,cee7aa03,145404b0,e1855fc4,f596e657) Z8(cb20af50,d5702076,3f7e9645,d8699d4f,4a6979be,caee70d4,b1451bcd,693c9748) Z8(9c306350,bc2bf666,b1b6e32f,0b1fcdad,40b207c3,497d4adc,59d13275,38559384) Z8(6ad47c8a,cfeaab4a,f9d18d13,4e6e04d5,2597221a,d72b96ff,339db714,c772ddd2) Z8(3df7cdf9,c047956b,c3401f7a,85c269b4,6dfc1938,26b46a28,ad474d52,9c47bd60) Z8(b0dd0c0c,2910ef5b,872af2f1,4d9ce74f,f7253fe4,c5a86573,3b084a3a,f50ac9b0) Z8(5410b3fb,1423aa40,d93c355b,6ad5da45,f07e8725,d4f3d009,480a737c,e2fa759c) Z8(81b5de24,5a184229,4335f1f9,4b9339a7,e7cb689d,50a495e2,db7840b6,529d6fa1) Z8(67a1c812,9f3ea571,149fc547,f472261d,ef91b3a9,d9be3dd6,0a6edf10,2ffb6c18) Z8(cebbb957,432de451,392a9edf,9420aa30,7b858240,ad4158c3,5151ea43,4b44a6ea) Z8(59a6b00e,2c05e4df,e0189ef7,769af396,2f856258,56a1c479,75e56a2b,2fb8205f) },{ Z8(807ea336,409f1d94,9dcf1be0,6dc44bb9,ed55acb1,32e94bce,c95e0fd8,5dc9f9a2) Z8(bf5e862a,30137bf6,87cddf46,a6270dd5,acdcb600,576158ae,3f97926b,432cc4bc) Z8(16b60325,7fed69ce,fb53b708,3313b0da,73b79b89,6fe8d1de,dfd2c778,b419b62a) Z8(9fb1af82,95872034,365c4ebd,12195f24,a4c04f51,5e64acd9,96fda853,a65f7894) Z8(3f09cc9e,86e3c8f8,37b6d6bb,90ff06c4,54928ae6,bb6ff537,3b6d8d1e,293c60a7) Z8(660f9aac,adfc4321,578d2b46,6828f7b1,13929da6,e8c831e7,5e346e24,c1047baa) Z8(ca71b75b,591e92ed,629ffa3d,445c44a7,e11b806f,135cb589,1211c0cd,e907a55a) Z8(18675dc6,4a527b4a,ef07a4a2,512a2f93,a10520fa,fff23185,337ce9d9,3af4a900) Z8(2c97f5ac,45700f76,0b2fe32c,72ffae11,0e161536,8977f1ce,20978375,726dbd5f) Z8(3de1e3af,e79c9776,c251bcf9,6d7bb4f2,12707c32,35758e76,446a1c73,89e0817e) Z8(14789d0f,8a47c6d3,17b2991f,ac6740c1,053a3a16,d9c60639,00dc3855,2de07dce) Z8(28c31eae,3d719b9a,c8f7d057,266b26a5,898a4039,89a10b0a,d0537ca3,81a0d78a) Z8(5d508092,5a47c05f,92b75088,10434675,616900cb,2032f566,9fb3cf9f,882e098d) Z8(fbf1cd39,8fec6a1e,31022c31,ffeb46f4,fc96afc2,fdd50ff8,55bd7175,32dd97d2) Z8(de6f59ce,f79d0ac1,6865f9d4,909f2f84,f9c9c03d,8478a90e,205e3954,6ac2df82) Z8(e3955ed1,34f6498a,106f9e8f,14677bce,6f64fd3a,b271972e,96b141b0,ee84ef81) Z8(f29c7c34,b36ec3de,a7ac174b,92950edb,f914f757,8c62b2e5,3bc76154,26e8b67b) Z8(9f43aa56,9b783f4f,e9cdb389,ea358867,697eea13,e6fe7924,f670dd2c,fb835efc) },{ Z8(a7b8db7a,73db1c99,1aca5f52,82f79bad,394ce5de,b3038026,ac33bb1f,11e5554b) Z8(26fa53c8,24996480,450e4486,5dfa8298,c399be91,be007b76,db1bfc63,1b6fcc23) Z8(17bb2e16,3ce4393d,301bd52e,77a3eca3,cf9deeef,0695e444,a5dfc765,b37f20b2) Z8(8e47e176,998625bc,2299c18b,c5b8c3dd,18fac754,8ebf7a75,e448d1ff,ebf68862) Z8(b2b9fddd,3097dd93,d320bcc7,ad88f722,c4b381b9,200e6534,df9c5a32,8a7fb2d8) Z8(1b82a341,2357dd79,84aaced6,e0720f60,9aa69e9c,cc663b62,5316218d,f24efbbf) Z8(fe2cd03f,527dd776,0e89cce7,f63a4c86,52be197c,2c5841e0,3e9556dd,f97d43be) Z8(509e56bb,43a0cd72,c0ac1a37,372dda10,88a59705,d3cc48fd,f5356b1b,9158cd7d) Z8(3ea3f789,0f0ef5e5,9d9530a2,4633af29,a60c0f3f,9ea64098,8c8515ea,1a5e2131) Z8(7eb0daf2,ea0e0dc8,29d45251,86ea65b6,963a98fd,5e297cc3,457aeb2b,f0d2a4d9) Z8(84ef502b,18740906,91e713ea,9bc97c89,dbd6f499,3c0f7d53,4436cf5d,0c48a29a) Z8(9c3add43,870f7ee6,ab7b59a0,6534745e,e10ce1a2,3c6b2515,d58f3d47,8aab6c74) Z8(f39f6d9c,b23c0de5,9d43d6e2,c1783f91,ffcd8aa9,6bce54c7,8e3ddea8,7104ac57) Z8(6a02832f,514335b5,52fdf84e,34e29594,9f36739b,67f3e2c6,2978da94,010686ee) Z8(cd06b5df,2c503cc8,32ef2461,8bdeb418,13378a71,4bbbf710,04866acc,e3812056) Z8(7c8cecbe,b095ef6b,21642ebe,cda71c58,465f0975,5c354c28,ab5ab64a,4548b927) Z8(3f3dbaa9,271dbe0e,0dabe8ba,d8ee03d6,6c3015ac,2bc1ba1f,5232ea30,1bb9f1da) Z8(11c1cd24,2b496c6d,768f68c3,26ea336c,65582e45,0d2b53d8,b8c332ce,378df09d) },{ Z8(8d2fc448,01883acc,d239fcb5,86bd281d,e7e10f7d,4527bbdf,560c7a76,222be7d1) Z8(55810d06,f666042f,5cf0aa3d,b8d96388,1c9b0c3d,a5fabe4c,0cfea960,91ca386f) Z8(41af1c0b,313b7985,32faab26,d6d12c15,db7e6888,fa58bff7,ffc3b6c5,bbe2860b) Z8(09eba40e,4765739d,c9af87e7,a50a5978,2cffaf5c,11015817,38d3b317,45e1eab1) Z8(37e0a574,e630e526,8f84312e,d57b455c,075f07c3,50117f1e,ddeffa0b,fe955e66) Z8(96ec7ccb,8f3b0712,a7b28fb8,d59e3dda,31c9d2e3,20f83452,b50a0729,e844d6c1) Z8(e90da717,b74ff029,2029ab23,81ccc3af,7c6f1a49,b746b340,51b9a177,6124915c) Z8(91a07ae6,3ef184fd,65b0ba5b,727c2fed,79645315,900cc21b,5a445a91,ad4cd4f4) Z8(c1daabe4,2f82b998,e42f13be,3bc1a3a2,575743e7,4911e831,5af9eee8,f2c4c858) Z8(a13bb978,51cf0eab,d023b6b5,0a7b9a45,f1949b62,e72fa9a5,9e08e90e,8e819cfd) Z8(5e15635a,3c911bdb,40de9d2b,648f694d,9c5786ec,9db5aaa7,551c51b7,1e49bbab) Z8(c09a60e8,18d76efe,623248bd,c7be1c79,95472115,31044865,c908a576,21e11df3) Z8(8b7cd5eb,f129c6ed,6aacc64a,8893b696,a822a026,74552784,f705eed9,2cef4b30) Z8(15afe4ab,c5d68698,eaf46cf3,711ac20d,415a010d,6dd4a603,a985285c,180a8af1) Z8(437fad60,5f3470b4,cd508a37,58ed8983,a4ab74a4,fd81f7ca,07cc3107,25c347f2) Z8(48a1aa42,034fdf8c,11b29223,e5fd0384,717e640a,197ec082,a9a10d81,af945024) Z8(62fca407,508dd123,53b9335c,0d26d438,17a36a41,311495c3,b4ec686e,65e72f7d) Z8(bed24b63,7bde901a,e11e09fc,1fd7fa2f,5b5ed9c1,2e296bae,9e8b6f6f,f9e63e1d) },{ Z8(b8e13d69,88c390b8,7dcfcdd8,2127888b,96065c17,0b78d5b3,52d55d98,1505e30a) Z8(1eab523c,d817681c,8490b96d,4764ea2e,c301d9c1,75dee1e5,0c37916f,2ee25f7f) Z8(11e2618b,a07c7950,0ca661aa,bd448234,18811f0d,c8cf443a,546bad8d,695c9894) Z8(a2636796,77198c2e,7e914f9e,59fb1cf2,ed194c56,d7310b55,3645bd99,668f6490) Z8(364692b4,1356eddc,ae8f6be1,d46f1619,2477476a,93a056de,f984f9fc,ee4237a4) Z8(c23e81ee,d37edbab,da38594f,3da276a9,7eb593e2,6d9f0277,fcbef52a,e44ae853) Z8(3e1c7d11,97673321,446a2175,8a0f1c94,7ab92e26,e842179a,a926eb9d,f683dce2) Z8(0c7a57a7,fd7775e2,ab33b8ab,7a98033e,2476979f,8d110d1b,de25c50d,38cbd9b4) Z8(145719b3,e7e8c2a2,f052031d,f557a52b,6d9106d8,d8ed170c,37f27248,f5c53e87) Z8(39b4527a,40fb7137,38ab2f52,e5eb7cd8,c771d782,9603966d,313f3b6f,2a3e7004) Z8(82ed1368,9d7f68b8,ce5f87cd,ad8f2a0e,bc9708d4,aef930a2,334a3c06,76a5ff93) Z8(5382af74,1a2bb834,41d9cb22,3fe865e6,0e5d4404,9044da8b,48fab53d,b6056afa) Z8(ede4c268,a2d01f91,bdbadb51,5e4ac05d,b737f868,e2d88c05,ef4c2147,741fac63) Z8(8ac09df7,e5e413c4,bafbd900,523b9c47,714ae638,2c7f3fdb,be984aba,1caace1b) Z8(b07e2a1d,85981902,68322690,9d8d2d9a,0b5c16a5,7047d743,1a9e72b6,5e981fa1) Z8(b3ea9e10,5a90781f,6746788c,acac168d,285c1399,d5de8857,198a89cb,efb5415f) Z8(4067fb09,06ae637d,ab3570d8,bd2a7e39,50b49ce5,2b800c53,42a81914,3c7f2854) Z8(af9330f0,898d7086,8d7db525,dd567664,6a3d1635,13bd7b8e,e62aed75,3f55dda9) },{ Z8(4199ce08,6d518285,33246122,0ae26a3b,9b0d4695,edde6b77,b825b53e,cd23d9a1) Z8(1600a160,533a60ab,ace9614a,25f844b4,da617d0f,914ba3c6,a2b5749a,ae8fccbf) Z8(b8aa08f4,ec37e5bf,8a6e64c1,d9a1d060,9afe1389,8c8916e2,4031cbaf,e7ffb3d2) Z8(459f5557,e9582dab,ad0b76cb,22056e5b,962cf535,25660e54,56973d81,4eb070ef) Z8(f8725653,f5d017b9,c7b6df50,53b3db67,b2e5cf9c,9dc43f98,6f03d9a6,cca7e64a) Z8(771fa350,47c5c428,6a28f9cc,9b7170b3,2680987b,082ee995,46271b64,a063728c) Z8(2fa5221f,ef1dcb37,95595ef2,cfa32807,92e9fa58,2917adb9,e7024465,da4dae33) Z8(d447adec,1e05440a,32d6d7a8,02c44685,e49b618c,b9e29b5c,c8d2dd5c,14081a9e) Z8(72be8628,e1b0da3f,d52e462c,7e34143f,90bf5b2c,1afb61c9,e6617ef5,1a31ef5b) Z8(c33a6227,db194899,c4b08e10,57a59cfd,66fbdf76,622e22c9,1fcdccf7,80ee30a3) Z8(335fbb1a,ff776bc3,b7d7c5df,886c8e04,314ab5ba,12823b3a,0f76c78a,9253c6ab) Z8(5403dd58,f27416c2,430e0500,178c8c4e,a25720f0,ec36ec86,fbd239dd,6a6614aa) Z8(d2ffe2e3,e5bdd91c,b1702031,1cd5874e,aa4c4e06,35bd7d77,a911dad4,ff976cfb) Z8(0ea8291e,f8c76d83,76f935bf,151c9ffb,6e222fb1,7be899ab,3e07a85b,531b9e60) Z8(2a6cee0f,37362ed9,705d7f6f,6d709942,c37eb320,3f31b66a,fc3f01a8,258c828c) Z8(19934f37,629234b8,6a27341a,a3435251,bda011eb,04bb5812,af6de116,48986a09) Z8(3295498a,2b7c5621,9c7761bc,2bbdaa00,6bb135bf,3a867cc4,ee16d0b2,0795b84f) Z8(c944551c,3ef9ec13,9edc4a02,1426dbe7,5f94f8a4,83d33cb9,ef750ba7,f80aa4fb) },{ Z8(658901a8,afb76b74,4e8352d3,d6a5a865,8cd0f19c,3909ef3e,6bd99518,7d01113f) Z8(f0455467,de092c92,9a991ccf,0b4b2a53,1c581d98,9311f90d,02c586b9,976848fa) Z8(4d659162,120a8be1,dc95d5fe,801c2a71,f7ec2d7c,72c3d96a,96beb9e2,793b37fc) Z8(de570b2a,c0be83a3,92d7e27a,71e7d6b7,d2562831,3ae1551d,5bdef1d4,f046b7f5) Z8(42a88c63,0a555989,94de40d0,4537fe73,d244f748,43105905,5b676e01,d1b60ee1) Z8(34f0b645,e39ce7b7,19070f02,12d84223,60b4c48d,c292117b,de2e4dcd,24f7b2fc) Z8(a3267ea8,26b60f69,095c7e33,b23ed300,0d3691f1,57c203be,aa96cd9b,c65decbb) Z8(0b3377ef,f1c0421d,b3cd6584,8901e493,114fe65e,59db0057,0298eb95,4c484b96) Z8(e39c9e37,c1bd1c12,a996a0a0,b2c051cf,8baa5c96,6dd418d3,e2c7b3ca,8f7e6c82) Z8(a850ef2d,513fd2b5,baf376d3,5d9af598,5da37d64,722cbb04,40dd5626,8c6b32f7) Z8(428d434d,ae3f64ed,dc7e5991,bc14cc2d,53138c05,c064bbf9,2c270e80,b4469fcc) Z8(40c2ae37,78d73472,50028ca6,b3833d45,6b8206f7,90d6c2ba,f18dc4ce,d2116630) Z8(5ef11ffc,f52f9631,1478dd0a,891454b2,aa02f870,29df6673,bff4e564,6a3a10d6) Z8(2f9ce4ab,8f723769,04487612,add1b618,13995af1,1d870653,370736d7,76c7f067) Z8(b5b6af67,f35e9b43,635cc97d,f040dae6,a6168bba,91b508f8,f25c1c61,d74195ff) Z8(b47bb43a,08e1c3d2,a24dd725,55674a8f,f8794226,14fc6498,2c445910,c28accaa) Z8(2bf07d16,dbf41cea,8ccb2f71,2aaa9b54,63a979d9,3ff98c35,fd335d10,98b5ae87) Z8(639e1f42,21f8462b,8ebc6078,bb2ede61,ff47fe31,076fe0dc,1ae1d946,470df593) },{ Z8(991b423c,a4084c7d,bfe6ce7d,b6d2fa69,c818114c,6f16ced1,0a4a3dd9,aa1c113c) Z8(8c405b1e,2605f8c6,0df298a3,ccdaae7f,db4aa3cd,a9f1cf71,45f86418,d4bf16a0) Z8(16325412,534e7e53,422ac10d,9e1a54bc,86d7df27,2aff0bc3,f01ff86c,6bbf46c5) Z8(ea821e63,83df41ce,d54caa8d,f888c076,e41438d1,d474a49d,2fb1ad44,6c99f3a8) Z8(7cbaf1c5,1b3e77b8,ebb1bc87,f086eb37,eefb8c96,e7919ae8,5920d6eb,1aead620) Z8(383558f6,1a812705,34450e94,33482906,e1e88395,ab0a1670,515b7765,711261e8) Z8(1676bd18,1e6309b4,97b7c05b,87ea55e5,b48b298d,677170a3,29de4429,eaebfa11) Z8(58cf0a04,3c34da0a,fd7da0c8,97548159,81d6a85c,43f69b76,c1c7e657,b36fdd0c) Z8(de64c266,15940c3c,9d18d004,24dd9191,0e231753,5ef025fd,2669cd3e,623077ba) Z8(f5932c5f,c6812e5d,a680ee87,e25e3fae,a55aab31,a9ce23e3,e6f4b2cc,9fd835f2) Z8(b436866e,9b4fe07c,f73f87b1,1985f017,6c9db731,1cd9379b,e135874e,dee5eaec) Z8(5df97a16,0305d1d7,e4697a06,3f444cd3,b22a8643,a1c8fc36,3bc8166c,6cf6bdee) Z8(b719965a,e6c40cb9,1e4eefaa,5033c3a9,719b5f40,950a8ea1,8ca08d56,f153905c) Z8(6f10c542,5e1011e8,6211ff84,0f899e08,e91c031b,fbe3cdbe,66bf4830,64eca749) Z8(1ad21d3d,6fe4b411,d2f0df55,94f3702d,b2ef60f8,ec3f66bb,01fb9e88,a389942d) Z8(53b38892,07b39c1d,279769e3,7ca3f502,2f86f959,83cbe64f,24a5e5a8,4947778f) Z8(fa289398,cb4f5054,b36a1f04,25331b20,4fadab99,74d7a229,451a7da4,29977994) Z8(168d2e7c,3b9d623c,c0f82bae,80d01ce3,78427832,0c1da8b5,b77d3dfa,f5f10a7b) },{ Z8(a38b076c,5e1e6f88,51293819,64faa216,1faff346,dd3d5bee,d172eda9,4d077ac0) Z8(093b60f3,282c6925,1f1db066,bc7a7df8,16bb43f2,e8b07391,0f6c69f7,c906c608) Z8(c4391ffc,645c470a,1c57f5e0,289d0b5c,b434c586,d9efd754,92cd26e0,b99396f4) Z8(39dc8066,c4c3e0b3,6014525a,58dbdd56,b7ed04bd,bd631d68,529dab91,0230861c) Z8(51880305,9153df8c,eeb53562,1f10d66f,ef6b3334,778a96b8,11734dd4,ed19cf56) Z8(ec13c796,264152c9,a9462c92,15d73aca,c03f1b1a,5e67392a,36fbb97e,4b8f6676) Z8(16a6f718,362332d1,b8182685,dcefcfa6,df65a914,a6b9172e,2917075a,636b1d51) Z8(2bb7309c,d7f47ee7,aa113fac,a38874f2,ece74ceb,04851219,d0ef8da6,2ef6bfbf) Z8(c7647e4f,5bbf6e89,4cc2b136,142d5be4,4b97ff59,e5dae53b,b73c6bca,32c81a37) Z8(567293ca,6082aec5,22a21df3,d47d6686,142662c4,34380928,f9792459,3b3f4bd7) Z8(6bdfca60,df50345b,20a8f2ee,6e0c6059,dd9aeb3a,69e9d146,064dd736,f5f7e936) Z8(b1ec4311,4f31747d,f7e08d1f,41270617,fbb0182e,902cf2ca,23ea22e3,584932f4) Z8(bba30075,521e0d23,4afd1409,69544017,f25f90c8,279141c9,05288130,aedc2552) Z8(ea9d9cda,3b93fa5a,c78cfaaf,7419e147,2300ed27,b6a104c4,0a31f2f4,0350334e) Z8(47c1eba9,cebe9bbc,bf82d1b4,71771ce1,502ce7bd,98d55e93,fbae1b39,75c4acbf) Z8(09dbd5a1,62486a57,0958b41c,9e7c9d11,4cc62cde,6416304c,56b1ac3e,9a0fca39) Z8(bcee4138,848bc08e,f0f69a78,360ab090,70f66468,b6817754,7f010355,28036dcf) Z8(05f85471,a46977b1,b3eb2542,8603ffad,f0734e28,07aaa090,a74f6002,4eb44a5d) },{ Z8(11a0322c,96ba4a01,7449c99a,e6addc1c,45f715c2,d1b115ad,59400c1b,d577402b) Z8(e44c0835,ebc5cfc2,4f5e58a4,19e1d245,bb4c016c,8fcccc1f,558f03d9,c8768e5d) Z8(f6c4b265,8e1d846c,23dfa3cd,5c6b83a4,514fb750,2d1b94ff,2c30b25d,86d538fb) Z8(8363caba,cfd8d47a,b22dba78,6a9d978c,e7de140f,b81f9b31,9bc8c52d,f64e839f) Z8(dd62b2bf,0a42f5ae,d7e11572,0e1537c8,4604d4df,6cddcd6c,854b3506,6b76633f) Z8(fc09e0e5,05aeadc4,8c2569d0,649d3844,ba0199dd,5620f428,0ae11889,89f6aeeb) Z8(2091d695,1237808b,c230b3cb,920a9d9c,aa5e8426,18a90271,c8099072,bf4e7e4e) Z8(408fdc7c,379930d4,d8fa4838,d8c1e2ab,c992088b,8b1f2268,f30078b6,ea95432a) Z8(5d5dc118,4da95e47,3e3865d0,4abedb1c,28ac87d6,bab110b8,60ca6ca1,5c6b6b5f) Z8(95e18395,c7bb269e,9c3ab328,b36f636e,55715123,066fe445,4af3fb03,12ef02dc) Z8(b5e71766,bd1ac7fa,a6ea3b76,e6d5e849,7e352636,2467d7bd,b0468f48,41c8566a) Z8(2d4d1771,054b69f2,d8f32bad,cad56c19,dc35bbd1,f2213deb,120c7651,6b982d7d) Z8(d06706fe,f53123a1,b3d2d5de,0af9bf65,4620aebf,61a8f091,0160d70a,7c0340fb) Z8(3ebad401,583c4e54,08362686,64269612,11488ebf,0fb2fbb8,76813439,9a2d6b99) Z8(6d012ae4,700145b9,13a5ab6f,8df8ec13,879327bd,bcab7729,eb1fd332,157a061a) Z8(30d688fe,a7efd763,db99ca8f,efee2e83,43ac00d6,50c7809f,9f1aecdf,060f2277) Z8(c51a72d2,f0b5b03e,2edf9702,ec828b07,bc24ee60,10c39d7d,ca275d90,81d50d3c) Z8(8e5847d1,49535086,9f101ee4,102beb56,3dab8877,ae995726,c9e9fd37,f399f500) },{ Z8(3706931f,05ed0c9c,701554d2,c29b0ee8,732866b4,1dd1a2bd,b4749fec,7d7db5f3) Z8(ca61e943,c70bb3f7,c39da7b1,e6d1cb16,e0afd06c,2b179dda,54dd287d,b374d62d) Z8(76109c45,18d0533b,bf958a6b,2dfeec0d,541e83e2,7659c439,4d6b7608,a66f5177) Z8(c33026d4,6c899756,3c44afea,9c57df98,f15c08e4,a32a0479,eea420a0,29445d68) Z8(7217caa5,819b825f,874a2662,dde28854,3aeb4992,4abfb2e5,7e07a740,bba329c0) Z8(21c31c4f,eb8591a2,8a9257f0,80182260,55280e9d,5cf2654f,83f6d5b2,6e271cf0) Z8(367e69e3,b5262ce0,1758bc66,e57bd7a1,e153715d,a7532a19,cbc826f2,c3bb3186) Z8(8d036cd8,b8d468db,6bdf37b2,102d6d48,ac01cd37,cf584e00,758fe886,e18ec1e4) Z8(a3b2ca80,54fd5839,ef9809ed,c48aeb29,f02e0eb2,40a831be,64b93309,78d5b6c2) Z8(1c6a2572,8d88b360,3908b39c,61bb3d90,f4e750d7,89161ee1,32adac24,1e411f75) Z8(a4259676,7d91b8ec,789d7ad2,27a9c752,da37efe2,f2d99a1a,c2bc9e11,7d279d5f) Z8(001d5116,c14082b9,ad86660f,9e014b98,a91cf6f6,98ef4a35,240090ce,66238d9c) Z8(47f4d5e6,1d7f490b,58086812,3fe6af37,9a0f7aee,2b7b044c,f6c71180,dc8c82f0) Z8(c7ef4049,d94c5c9b,ee7280d0,4aa7f194,45a3580c,7e7e8c1c,ef68d405,16611ee0) Z8(68700445,a48a3543,c62636ae,d6f51132,9d64caac,b10d76b3,644823d1,2b763fb1) Z8(2eee2b1f,b33fa2a8,0cec9c4a,3007af5e,ea98dede,e5fba6a6,8efa3ac5,e6806e20) Z8(d1ef3f4d,f1adb65d,0a2d8a5c,517aba32,54d27068,ff875262,d0222eb0,d9ce81a7) Z8(53cdfc90,b05ae267,74a00246,ee826d96,06572290,3a5d61ff,8bd65cbe,5646f27e) },{ Z8(17efb865,c381859b,07c1503d,e9709536,4870f925,764509f8,989adeba,7427f66b) Z8(e85662d0,3845f656,682b6325,0ad20fcb,43c60b2d,64f426f0,6cbc82a8,ce8551f1) Z8(68fe7baa,fd558e2e,0cfa1772,1e6dfab2,7d558792,4bd46f38,ee530ff2,9208a132) Z8(fa6dd952,91c2d0fe,cb85886b,029b0fb1,75bbd48c,da91039a,142791e5,c27049d0) Z8(e6a3fb42,21fd0a51,74efac80,e8cfc6b0,8a7d2ea9,5c1cfc5c,2da8457e,4f967cc8) Z8(49197888,90797dfd,c3a4ca9a,4ac8a92a,7fd9cad2,cfa0d0ed,d86d1a4b,1e746f0b) Z8(64ecc70f,f71ce45d,e181a191,c98fafb4,c5e573d1,90b3069e,70b80dc0,769ab688) Z8(d067eb28,36d7021d,b26b9701,74ec1a71,c3378ee8,b8aefa78,13939721,3e88bf16) Z8(c3ae6b46,ad9a092d,d56c59ca,09bc35a4,87689ad3,1a2f1fd5,dd3f6609,ae658555) Z8(fdee2013,bf40a73b,940f2843,9f90b7bf,4dd52bc1,4ed1944b,0f5e4fc1,cd153550) Z8(ae0e29c2,f7753c6b,9f230a2c,393488ee,e5bf9fe9,64d5fcc2,a86d927d,009d753d) Z8(16a2f266,5a544be5,cf4dd91e,1e8a868a,a38da902,e09ea76c,fa68b3f0,1de2208a) Z8(6084f467,b129b646,3c81c9f1,80b7dcde,12bc9718,d1687293,f56b88e9,36b9d87c) Z8(b21a575f,d587d304,d1d2fcad,2ddc72b4,1ecf7ced,02c5d20c,fa265e7f,3405b6cb) Z8(901db0a1,96906cfc,ff6fa7e3,d3fdc053,f44c1565,163954a4,3de4223b,2a99512b) Z8(73a9f7e1,abc68551,945b3a89,08410cfa,21e3fd1f,406a1b0b,8f28a6c8,597aefd2) Z8(7f3b6732,1228f67f,29a4d642,12a5296f,b2ca036d,c26749c2,57ae7419,e60f19e5) Z8(6b06d98e,07a4f6b5,d54dfb09,5142ac8a,72520443,7d44e042,66b607a6,f105fa4d) },{ Z8(d3a32e12,03e39233,6bce4a98,11ff267e,9c967e11,fff2e53f,abab2958,38d569ac) Z8(4a83e1c7,6671e463,ff59fdc5,f66d95ce,2260c80d,4a1cc8b5,02814849,488aa58c) Z8(03d3b19b,1d460235,fb16e508,9b2b863c,800fbaee,3522e7b7,8d673da3,28996912) Z8(b542635d,975e90d6,621f1aae,019c0a83,68697ecf,18894905,b36d6b12,76701de0) Z8(7119b74c,b4d0c075,f701729e,c970f383,91cdc2a5,4319951c,2671c893,e3ab1c10) Z8(25f56ef6,ea229835,4c6a32f9,9b86a542,bbb373e1,94f1cd2e,fb3b13f6,e03ea787) Z8(a97c82fa,8b61a989,cc3f76cd,e9efcd9f,336ab0ef,6453a53d,e0b061f9,db197653) Z8(d0b5f317,80c52f9d,3cf43af2,45f29fa4,7ffb515e,0dde8883,6937ea4a,00551055) Z8(762d3737,110a5601,bd41231c,18fe8d6a,81b028b8,cf528998,48aa51e9,f46cf699) Z8(da0a7c42,c3b5bac0,52b7e24b,ea09bf14,5557f941,ce0dd26e,a463d263,15e1bec4) Z8(435171ea,7f39f29d,7c289293,69dffff6,f23de214,0fc3f758,adc5482d,307facdf) Z8(f5d44084,abf1cbb7,57bab448,d4bfd11c,3b277f95,817dc230,ba403fc6,4a460f94) Z8(f43e2b0e,30c77951,f7fd94b2,15a3ac92,7273f4e5,b2ee1fcc,f3728e7a,632d0b39) Z8(162b9ad1,62936527,21ba95b8,ae581ff1,e8f63118,eb9a215e,df49c65b,270c9491) Z8(e88c8f25,c2d0a80c,48f77a6b,aeb7bbf3,35be79fa,1097db85,6c22e0cd,f4689347) Z8(2b16dabf,e01eefe2,7f6a8301,55ca0396,7700ea3b,8e61be54,a6f281b5,e49ea260) Z8(13d01836,1d01d8eb,a878b922,c2e6fd73,38e8398a,a220f616,cd613334,bed1ba0c) Z8(240fce6c,3f2e24de,528a6afb,51320ff5,498de5d8,a94675a2,d9084f48,5dc40955) },{ Z8(3fc97fde,1a4ddf02,26b84246,941ec763,ae6aa302,8b1d1295,34d6e5e5,884242cb) Z8(8206badd,bc4dbc2b,5e4c070d,94e4aafa,d5812794,c09d1dfa,4010ff72,ea62b2f6) Z8(38e7153d,69e7c308,4d8a0693,30984219,099a6585,2611bd57,75b2d5ff,1d1511e6) Z8(36a9eb3c,897cfaf7,787d8c00,4f915a21,bb3656fe,79f5300a,d7b9a4da,c9fa2e05) Z8(2750e8ba,1ed11a81,a08eefb6,4783eede,1107aed5,e5cabc08,ccbc7106,626e0147) Z8(feab5658,cddab506,be16d0ee,3b9b4db8,a61235fa,ce419907,53fc4516,418be4cf) Z8(1fa6bd83,a2f2d7b5,40f5f1d2,482a75db,dce2192d,3b449b2f,92cc69ad,0b13412f) Z8(da596fb3,faee3f62,4e875f0e,e320730c,5bef4549,2d21208f,24f49b80,7d012c33) Z8(f9f1093c,2c621e28,12f04d73,7b983ae0,ff79c413,e4f2071c,2a1faf57,23efaa0a) Z8(14642e16,d537db68,32500051,32ca0411,013f4977,4e8217a8,163372b4,bf74f9f3) Z8(612fd4cf,729e2f5e,8a90baa1,24f28913,a4ffadfe,5ba93e59,4323d173,e860eddd) Z8(0f77cace,16a75e7f,8ad3d0f3,e4beec90,4cb3f427,ab881fa0,a4a93551,6e0c28b6) Z8(ebfb7158,2c0dd06c,b9aadbb1,eeb880d3,caa64ef3,fe6b43b9,c6662a05,b2382daa) Z8(0327049d,e342106a,446ba297,646941eb,f1d0bd91,119e238a,cb87c2b1,f63f9b40) Z8(c29b231d,cd3e1ca5,30da7eb8,d9257c44,13d5f22a,599c654d,d885d77c,c0f43656) Z8(dbfc77e0,fb1fc9c7,b7632269,29aeefd2,e7e7d263,82033cb0,3a1d081c,17ec2316) Z8(67a74c0d,6cc0feb6,16a758ba,e1496860,62c52030,7c4dac07,9b7d0d8f,6daf28a8) Z8(be0091e7,17053803,9db604e2,262e3b60,34d3a47e,cd91ddb7,cac89052,ee35bf5c) },{ Z8(c79b22d2,c048221f,c8b7e867,de95c888,c7d35006,dbd670bc,7d729711,f20f4b16) Z8(f3c3f96e,db26476a,536efbd5,16eb519d,4f30c9d0,e7250bcd,c58492bb,2d8a53b4) Z8(1b5d853d,3a82c329,a035071d,a5663ad2,a3a5f6d2,e1a6d3de,c9a2bccc,b08c0ce8) Z8(3b8e161a,bb5e2c14,60977a17,646dadee,7b27ee6c,97bb69d3,f51dfc1e,05b465bb) Z8(31c2607e,2796071b,9ea62f27,e431cef0,15235027,bd803ae6,84676b48,6c2bcaa8) Z8(1967a4d9,8df58f47,206c6637,f9d4e9d7,8d45cc2d,ac615256,d8bc1e75,2826662a) Z8(6b059940,26c5a612,9f570818,60f28a5f,ee2e5eec,51e98125,1afe4386,775771bf) Z8(e6904fa3,0d19dc4f,7cfa1110,d99640b9,61d83a75,daff383d,d6aadde8,660878f4) Z8(50af25ee,d8f51218,1089cb80,fd199db5,4067b52b,94938faa,8cb50d6f,40e05939) Z8(a9f8736d,6bd0da22,5c5b35b3,76f5ca3c,93cd91b8,3f7aa4fa,650dc307,4468c521) Z8(d55c5119,06c6eae5,01b6adf0,53040e97,4b27be9d,a7cb1450,892a6dc8,6b19ab16) Z8(dcadeda3,ea83fce4,e1db5e66,7d937e9d,c5c6e4c0,b53ac651,232de996,1f15800d) Z8(52030864,6e8d2a07,16f71ebc,712be573,5921e41e,26e2fb64,c3430191,60c0e6af) Z8(3637a8af,d2954102,0b56a7ea,9570c4dd,f85de6a5,6d6283f1,46aa15c6,01d2c492) Z8(02f913f6,a0e5b9cb,9c1b24b1,341ce0de,ed1e2b6b,51f38d5d,85118daf,75a74457) Z8(81fc602b,e4f7206c,34b0b0e0,a78a9510,17d11471,9e8d617b,ad836757,31330d23) Z8(4a1d9b4c,fb52518f,e1b96fba,6c52462f,10c921a4,cdf402b9,01b5b58c,37ef17ef) Z8(a8371c46,feb285ca,b0a47956,d7dc5368,0a840a11,31ec197c,d51b1296,6529afa7) },{ Z8(cc9258f4,8333652b,5c5d2440,af5a7f6f,6a0df4f1,763c8e88,985bea95,8d06823f) Z8(a5210761,f9240d57,ffc1907b,f6e265e3,6c5ff90b,79b74a06,62a7f487,34d3af11) Z8(28e6d9db,62c06926,344fd00e,5fe99e8c,b375eb55,6d3129b7,110a1af7,7d01c168) Z8(c20512de,43b8358e,2ec26a13,cdb8172d,9102b6d0,d4e65bd5,cf2b25b7,2a8daec0) Z8(7da0ba82,00f8fa19,cc5ddfec,c56ecde3,491054c1,aaacddf7,22b3f20d,eb52e11d) Z8(0af89b3b,b7092411,6ebbd750,c121bbda,2c6a29f9,4f5a7032,998c5724,bed53c70) Z8(0c978b89,167d23c8,6673a9b7,6c56b148,75553dbf,4b2943ff,006ea26a,df1ccdf3) Z8(899491fa,66c3fa86,cf0fd541,e871b8fd,938e1650,c8b4c595,a2d8f3d7,3be06dfd) Z8(796a73cc,4ba45c75,e9fe04a9,7c850d52,4cc1468e,7b5d0885,53540d85,81647ff9) Z8(75ac9589,5b4a0d70,d341a550,88120d31,3f9845d8,b4f2fbd1,6064b38d,4d878278) Z8(9f6144a2,10fa3bbe,81484ae0,a941a8ef,6c134c8f,cb15edae,c6c083a8,e19b0410) Z8(63d15d94,ce0c0114,146bb6b0,8bb4328f,66c966ca,788ca439,44a82506,f6c89444) Z8(b8d2e8f2,3d61130a,790b18e4,e65eedb4,794c4b6b,5e097b88,069e7e56,ca9a8079) Z8(0bf3c7c1,519065d1,4ec2e6ba,b95470e0,f0e58402,4030c771,b9077591,62880fb1) Z8(3f208770,5556629b,b0e523c5,75bcda01,60ff4935,493989b1,a276ad09,08198845) Z8(e3d61506,bc0d115a,e04c8e9a,e766fade,748157a5,ebdb7aba,ac5a5dca,a0d7d4d2) Z8(b303e4b2,0057d360,dcc1f95d,679525f5,c516131c,05545e05,95a71665,abb4c306) Z8(a14367e1,21558265,a4e8ea4b,15c85230,7916a78f,b9379682,f201fd13,eb29f839) },{ Z8(2627282f,125cbe56,cd0d4c71,0ca740e9,4828f8ad,0e9e1794,856dd47a,af2781f6) Z8(4290f256,fb2fbcf3,3035ee50,0d46ec54,971b3d52,fd0184ec,c6f29e21,e5a982ac) Z8(f3f6e83a,ab689874,88d5c5a6,ad05b36f,6689b8f4,f397ceba,c6de87b2,05967223) Z8(991b5e82,e9c90555,53c2d4e0,8d22f3dc,6d7f5ad9,7d1d59ea,19e2e136,b7326100) Z8(a003eaff,f79181e1,f86ab668,b3692dfa,8a9cd1b6,93ea9813,15d34c04,033b3ec8) Z8(13da73cd,7113977d,f81cb75d,d7ac1ddc,fb16f72e,ccdfb5f7,cced9646,5e5c83d6) Z8(4ff6ce75,a42d4969,ba8abfa2,49958e83,05a17638,74a08640,b9f0f561,666c151d) Z8(074ce687,66fab7b5,615b3167,38a2232e,3bbb479f,bf4223ab,fefeeec1,565ff818) Z8(0fb48e6c,16ed3fdd,44da0cfb,fe299461,dd4f9077,8ff354f1,ab9be386,9ce21b86) Z8(48a0d667,1976864f,7c9b816c,b5895413,bc6e2806,29bdbb41,e279cab6,00a3aa40) Z8(cb244c62,94be494c,c3899fd0,509d1bfd,6f25fe36,04e77de0,9696a3c6,6791c277) Z8(04413599,de93581c,2438c5f8,65502e0b,eebfde4f,5e540019,7410bc80,1166bf31) Z8(0abd6082,539e3626,ff8a9814,047df7d6,e00d0572,14a1b657,7d7a1a81,867b92c3) Z8(a0f8a663,4672bf20,a641a6c2,138d0612,acdd0fe4,6cdf20f1,03fb3c72,93950547) Z8(20ac6c58,e94a68ec,93d4c4e4,7780914f,3e72b948,ef025561,894d7921,0598b6a5) Z8(02566f0e,e85962b9,9487258f,fa179dc4,3f3d2c27,9f614a63,e3873c7d,df8287cd) Z8(9b9e9111,d9916eb1,6ea5fc1a,6f11cfc9,1df095ae,6a510663,4575b527,063a637f) Z8(414348c3,3724f8b4,0887a0b6,7036a0b4,ae6c52ac,dbd34660,c8585a51,6c760c14) },{ Z8(f3a08ccb,5ff91449,9083ec5f,47eda00e,ef464dbf,ef5aaea0,b5b26f42,e54140f3) Z8(9871ce6d,39c4c66a,83ce9ee1,f10a8b8b,1168167a,eae04e7e,76e813fc,6e4858d9) Z8(5a2b38fa,ba3d55df,46574da8,df7ae0c7,a13ae982,b0ce5cc7,5eb02737,e753ba80) Z8(2d8706f2,9e4a1662,8c34fc6c,4970a842,8520bbe2,23634fdb,a8e1ee06,25fbf355) Z8(19c160d0,83d84d8e,8a8e0047,bb5925ec,4749bd11,b1b9f7db,b691a679,8bb97553) Z8(bfa2dbaa,46a97371,1d74eb96,27fd682c,77cdaf8a,7d4bbe46,c22d9c4d,6787ef31) Z8(c2efd7a6,0ca1a317,a6370e05,1e8b07e2,a4b9432f,56a1ebe4,dc8aa320,71d741b4) Z8(770a4d58,a0e1f12b,ee515335,93d4b6c6,59ba05ba,5083f113,831ce522,2a42acd1) Z8(dce777d9,7667862a,7be52361,3872e19e,20fd908a,c348ccb3,a0e9183a,6b0baf37) Z8(42c6f25b,51071f83,0cf8786b,16af5763,6c3aaf6d,654d57aa,59d29bfe,635acc55) Z8(82a086f2,298b0d78,c1801872,6d9fcccb,7d607966,e567d7b3,75b44114,88f16440) Z8(091495ba,e66f397d,8f41ec92,fba2624e,f2666db1,581e4448,205401ef,2e67c31b) Z8(e31c6844,786217b7,148588c4,56a17952,8582ea87,cc64d901,1645572e,3a857f74) Z8(80eac365,e3f4111c,0929829f,b39c5982,8c2372ab,5d85440f,e34ff9f3,f3031551) Z8(4f54d651,99522214,0fae82c4,d89ad287,53f3343f,21061c8f,1f842a07,aeef0e84) Z8(80f81535,fa6a7ee3,1656d6ad,d69325b9,115bcc7a,9e2f1b5c,f7449074,8f1017dc) Z8(9b0f9a6f,7df537d2,5e335ae9,a6c9351e,ad884424,387fc8ac,0ff8d974,b630d6d5) Z8(6fe2b72b,4297e6a7,6455bf06,7f5c132a,419cd005,b6aa11e5,956cfb16,e7e367d2) },{ Z8(12878625,8932f7af,2d6d4d49,65510988,109763fd,f406bea0,f1740121,31fd77b9) Z8(19d33f75,1084af2e,f888e13c,dc47e79a,1dd7e9f3,c704d9e0,27dd6433,edaa7b22) Z8(e30d4081,29c18b32,7335dc8f,d1ac7628,86a67d61,b8647848,e843efd2,bb6ff514) Z8(2d4e913a,d2a6b946,82c9a283,5344ef35,f709ceb6,f3d60fc9,e1724f4a,6f5ee09a) Z8(e5625625,4750b377,6eda66dc,df0dadd3,e707abe9,92af0aa4,dad29e7f,f01b64a7) Z8(3c925432,de01621c,08903c59,c3afcb5e,0de5bebd,4bfe26b3,4a67081f,0d8c451d) Z8(2e89f7c9,56b5a895,5b03c3dd,e00e5ddd,4c492af8,e3b74966,90118d40,be56bc97) Z8(0a76d39e,3e5a8f09,3553c55b,0cec762b,20fb0570,0f48d90c,e6b96c14,9f4dec14) Z8(1732f0dc,78ebc947,20e3fce2,8c94274d,3082bc18,77a5f5a7,3fac3ca8,ee2f8c55) Z8(4d70ac75,f20e38ca,66d13210,a2c5b035,4265ee37,fb0c6b64,2cfec8a9,e8bd82f7) Z8(931f13bd,b00bd2dc,e6cb962a,56ff82a7,6f3f1c85,38c839df,21c4531a,c81e7c40) Z8(ef8dd813,0fe870f7,868b8d37,fb248af0,cd9b8485,402f4545,4239c717,80ce29f8) Z8(3151891d,9bfab360,7c1615b2,bba72a89,827e64a2,0e21e3fa,a0625f5c,b9c707a3) Z8(9526b4d0,86fc190f,a3ba04ab,6156e2a1,d2b673ef,23b6e243,6fa66807,0073ec10) Z8(9d4e66f3,0b4659f2,6786c991,a52d1591,d1969f6b,53affcc9,b632e671,9b95e8d9) Z8(ce2912a5,856758aa,032093d7,40b2a460,ddd9203b,2b8a78d5,f5d4bd0a,d94f306a) Z8(266052ed,f59044e2,efdd5c62,57be7e22,1734b856,6144dfe4,9d537b9e,9fc63ff1) Z8(5ec60aad,a9b1cdb7,9bad0e3a,769bf477,eb3fb021,1baf6928,52947b68,73a74b8f) },{ Z8(3372fbac,1b226e45,f326a37a,570dd744,bb755f89,426017e2,ba4c10f1,fd521ff7) Z8(8f5c8a09,89db79ae,cc9ad947,c7c8620e,1b473940,f471115c,07905ac9,8e0f9ba6) Z8(6169c956,b000e7f0,e49eaa7b,4428322e,132d9fff,2ff24762,cfb1a252,cdb0fe9a) Z8(0d764b2b,25f5fec8,6c04239d,f89ff10c,7e12fcb9,76d36cb1,2901ad2d,21ec6d89) Z8(1e4b4a9a,e4d7ee42,5f2666ef,13a7ebdd,adef0f1d,b8017c2b,c73264dd,afdd5706) Z8(4123ebf5,61edfab2,2479e60e,c7eca630,d5ce3269,0fb0e9e3,871882ab,35f3b704) Z8(6f18eb7c,085bb698,43a8c811,6f2100a8,d0d4c25f,55dfba73,8c659338,f172d8d0) Z8(2885e3bf,8e98102b,be72823c,569152d6,e34879e0,cb7853c2,c4ddec13,5ab239f1) Z8(64c7cf11,664aef6e,3ada0b4e,d3c61c52,4aaaef60,3cbc839f,39021569,d9e73b07) Z8(b5b454ee,751bda20,f5dc0bb5,368805c7,2e1c27e1,f7f58c12,fac1c5ce,3543e455) Z8(9ba9a33a,5716c6d5,2c5fa83d,8fd59d79,6be816c6,6f3513b4,80983ca6,3b86c96d) Z8(6a93b56f,8daeb401,dcde127c,05ca3c7a,171724ca,ebb72ea8,fa2a5d7e,30f11940) Z8(96b72328,1e40fd15,9d3674e0,d13d4ba0,ee9b2f6e,6351f592,e748e8fa,e4112435) Z8(884608a7,3af38be0,435a58bd,2096bfb9,a067fbc9,9846ec94,84a0ec42,315ba6d5) Z8(8c9817a5,7274e03f,4fdf5c9e,48ea6a02,8efc8682,8260a2cb,7edd269e,de95473b) Z8(695bc50f,3ed3cc1a,0958bc6e,d1435bbc,dfa1824c,2854f7bc,4f42e7ae,1fe6f62c) Z8(3a89e3c9,03e56c2e,72b932d9,7553e766,416e19ca,c81f5b04,fa4a2e1a,77966bc4) Z8(1859aef5,01f91443,202bf5ab,a0547011,1228f146,3d1a1590,70d421ab,e462dfc6) },{ Z8(06a098e1,f4644c9b,748a7e3b,26f90701,ece36468,bb37f5f0,a9c95dc9,ad0f4097) Z8(86d80447,ec64203a,a90733e9,d02b2bb0,c95aa227,a5cce01e,4df3584f,2614c684) Z8(62a42625,0fdd162a,7c32a50f,52298403,e341b2a3,f365b353,976a8099,87efa7de) Z8(97691590,a7e74a0c,cb631ac7,754443cc,984af0d1,9b61659a,ecff868b,c3e5ad1a) Z8(a39c3d7d,8264ce53,0f6f9d72,f8002296,2f2867a4,259ae52e,45fe97a2,4bdec755) Z8(52c51597,e8023624,ee05c95c,adee53c0,d78a8b00,970a4c14,a92b4848,3242927f) Z8(00e4541f,6897dd79,b926a6e9,1bb021c2,f187e9f7,4578f8d4,64597cb1,7c9d1c1f) Z8(56d700e7,23c8171f,32bebe77,378b13fd,653f78c5,900b84a4,1dc3ec79,18ed926c) Z8(45c060a8,cb092c05,6d16b08f,0f67d5ba,ca63341a,6aeb188c,524df2c1,11a6fbe7) Z8(56b6161b,fef77a4b,10110bb6,12dd9276,9acc53d3,dadffb27,cec6a4c5,588271ca) Z8(9b0b45c1,541aab94,a8ced993,6cb9acac,a3eb2584,f63b6b68,d1c7cc9e,c6e09748) Z8(a07575ff,91a06ebe,3ce5bb8b,5a5160e3,e945d22e,43bc4157,da2e84f0,1d1d33d1) Z8(48779c25,27d22ce2,ade1936a,915d8a56,50138d33,21865127,e5f6c2fc,8f226abd) Z8(dd1ae876,98cda20d,16d8dde7,ff9384c4,406cebec,7ef9c972,ff8cc6c4,f5eaca2c) Z8(ce510e83,5d18613b,c5fde765,4e8b7f6f,923184df,671c41ea,0548011f,30e54430) Z8(84041175,e45770db,deb5662a,c26e6b0e,a95e5367,731f0bd4,a2f47178,e3c22408) Z8(e88eb7cf,d296299d,0f56236e,0d0467b8,2ebbf6cc,5cfe8e99,3a9cfb75,db35ae8a) Z8(d2a0db47,8b303693,caf13cd5,92f45b4f,f60ded99,d92f0d93,2c17bfa1,7abba1d1) },{ Z8(642953b1,469d3dad,73b9c08e,072f804c,b1796082,e88cbf06,0017379f,e2c71b62) Z8(8bff77d7,a01bc011,9bb50619,cadf4a28,3a4c997b,cfa6acd2,dc575f23,5a942c7a) Z8(45a961b9,9b33286f,b02d2c5c,ffece9c0,eccdb311,096e8dc5,82fc1ad5,02709a39) Z8(14531a29,66d50213,c6b588c0,7c32bc49,eb67d2d5,b3333ed3,3ad89a37,c426c86b) Z8(a15fb942,34019f68,e57af7e9,4fbc88a6,021f5f54,f1812929,a114ebff,f3f45805) Z8(7a2e7615,9d5dd9a3,83e9902d,85437ea0,b1166dd1,12369a22,f0cd3ce8,f4fd87af) Z8(bba8f25a,0c70fcaf,276fff5f,f74ce9ab,65f9eeb4,7ca6a1f0,2a47f759,eec34a26) Z8(9587220e,55c518de,79d56606,1bfafdac,830d5131,bce2cb7d,9d49ca32,cc6f6e8f) Z8(03732189,f487ac50,8041dc28,448debfd,96ce1e3a,8f081dc7,7e4d12e2,5caa664c) Z8(2b221531,6a33bb13,d577c701,98a17ce4,8b86ea74,bf078147,4d87983b,3b992a7f) Z8(56f32197,ddea2bfb,6c3bd9a0,a528c631,e9fa51eb,79f66285,c603e82e,556c4600) Z8(f2197234,a2b86956,c41eede5,851fc9f3,e85c7231,319b42a1,ff91e6d7,dfa02980) Z8(8ee27946,4177a9de,44b5f352,3f2e60d2,6c5650bb,d01b9c69,aa9126ab,921bd2ad) Z8(67701623,0e8861eb,f3c97ea3,d67358c8,8959bab5,d763f1b9,80703ab6,2f346a14) Z8(f7e1b94d,9205c824,f4522f36,cf14daa7,c76d5b8a,496b807d,10e44651,45d97b93) Z8(36ce5c4a,21a13286,d6d24009,c2be73e4,60fc2dc6,b5bbbbd9,bd1729ff,8852aec3) Z8(c53ccdbf,72a25e5b,fa33e62f,005ab15e,8adf28ed,f8007990,e2efe077,01204d8f) Z8(3e8b19e8,d72350af,89f43eab,56566b3a,fafad985,bddd9da2,dbea7ced,e0a94032) },{ Z8(f2633da1,543b7af1,d6e06f7b,37317d9c,11b56d68,ca3d6070,5fc007bc,11a0bf62) Z8(a29ac0c9,80eb11b9,51b7f561,943dd04f,b6ee6ac4,d1da5a32,cccab534,e19a1e4f) Z8(f262685b,e413da3e,5a03fc8f,92341feb,bb9ed428,57b825f4,51abdc72,edab1794) Z8(e2c226fb,00a95da3,9692634c,d32ff5a1,f98416d1,cdbcaebe,8c244990,cb37121a) Z8(7602c56a,e598ad86,e676d740,057a8ef5,7cfdf5d7,f4f6c7c0,020ab6ad,80ca5157) Z8(e4136bab,5de12ad9,c7b99576,db1f9775,3d7bee4d,8a9b484e,9e365e3a,c5941bee) Z8(753f9193,dc881402,6e414e8d,c7acbcc2,57b0d40a,cbd2fa14,64853d82,3b7476ab) Z8(40f678d7,a72cec98,f42662fa,6214a188,34ed20b0,1768cd61,6257bd11,8c35e318) Z8(4a7497bc,122d2f86,1f41764d,730d479c,0533c7a9,7aff187a,abb69ed1,b475dee6) Z8(5a8a97f7,ffddcc5f,0c4c3afc,8df534aa,875c7743,8fe0dad4,1d10fb46,14d1bb30) Z8(9bfe4be9,ec6903ac,9c988670,e253b4da,225a574e,0ff12cbc,8aacc911,6761e975) Z8(919647e7,2b7cb2ce,68ff562c,4f7692fd,2c26b028,ea98df8c,d89e1740,705c556f) Z8(ac0a7dfc,55aa1815,a75b26c8,dd88b31d,889fc448,80cc8161,7b1a0741,b54d530e) Z8(53318060,feff0b03,b50eeb23,2ba15797,160f45c8,d98e4b21,c90d0c2d,71c9004f) Z8(1df69374,d8fabb48,a772774b,1cb51dbe,b21bd707,73efe6c2,27b9338b,cf29ccc2) Z8(488132de,21c8c03b,bc5c4361,9925c116,87d794de,8e889659,5e481778,41a72398) Z8(00295bfb,2528d664,f6997e46,b38e89d6,9e178116,313a4746,ad2b5f44,bb0f7fdf) Z8(d294d25d,074c83b2,ca951a93,74206c32,9fd4d6aa,e650f8d0,34caa5a4,81b149ce) },{ Z8(868291e8,b149a0fc,47bf2bc1,cc5b3f34,33315820,5c4a2c19,4982ad4d,cab704e6) Z8(d6717639,39ac0fdb,46ba7613,67715fad,e8a95917,12e835f9,0887f8c2,bdb07a8d) Z8(5042dace,c659be8f,51fe433c,cbe7fea2,4b66ad2e,dc99ac44,38e5f951,91fc3578) Z8(f4887705,0acf9931,ca119164,bdcd35fe,998cade0,eccd3f6c,017cfa63,d4005b16) Z8(051db187,f7375936,13ba6c21,35c4cbc2,2873043c,923c2ae2,4dba68c1,55a11219) Z8(d86a9eda,71440428,0f9260da,5a5ad4da,db4c0b26,ec7aa414,a1daa78b,66bc04f7) Z8(1e4cfb8a,f2bfc63d,e083b697,35d16ef5,a86d81ed,c9e5f9f3,31f37f92,631960c8) Z8(fbb89cf9,0faace1f,379a6724,b849966b,be27dfb9,8318b67a,6b2a76dc,58615e59) Z8(1a20221e,4606dab8,16533d08,6d8d05dc,6765f54b,04a637c8,2fb70001,4be8d061) Z8(190aaaeb,b0e7f2ae,8db1d8ef,07d05b62,93472932,44a0b369,11745b45,1d7b5444) Z8(82ffd699,522b6174,d1607dc5,eaa77d6c,e1b1e270,162acba5,d5808084,a2c7c043) Z8(20e13e1a,0007ca23,0d74d047,ca2a736c,ffd3e270,8b2a6ba7,48c74248,cc18781c) Z8(c95448fc,3b23b3d3,df21dfcd,f1d2a64f,119fb5ac,3577b166,c9fd4ef7,396207a8) Z8(d45571ce,aee8bc90,73df053e,76a77dc2,571a5482,6746806f,94a7056b,9047d2ca) Z8(70f345c0,6c7ea4f6,dbacd433,d2a49638,ea3e8f4b,fb741592,0375df09,886ed9c0) Z8(2332705c,524c4fd1,a45bd272,31678b03,5f981867,edd70bc8,5670fb75,56f65639) Z8(9be67be1,893b4335,657b211f,1b6b633a,0d0e08c3,0c1fec74,7341e221,56059fcd) Z8(eb7f21e5,522f5407,62843b54,939ecada,b780ce9c,68f31e3e,c4207051,dcb7777a) },{ Z8(86b3dc5a,92f4a0c4,df88730a,ebf5b31a,90ab0817,eea18533,dba6abf2,cedc8d32) Z8(a9ccac7c,88a1605c,f78fb136,c80cdad2,e38a7900,39202e82,f091c780,0a55b4f3) Z8(15a43dfa,874aa3d1,1fe475da,255fe17a,10f7f793,d4dec8b1,ec26582d,1b58c715) Z8(007c42e1,82095a56,43312a50,8bbd14f0,ff0a754d,f30f8455,1130e5ed,aa9565fa) Z8(42e1deab,3874d75d,ae38c8d5,409c8dcd,5c54df95,a2526a79,a1659bf2,f5b6113a) Z8(4172e517,e3cf254f,7327089b,0e7496f5,f2c5e3e6,839e9ce7,67273dae,7ff334d4) Z8(ed507413,0683a4e1,413fbb05,f8957674,de2ea121,36cb54c8,e6046a56,ea223276) Z8(cfdf0bcb,d123057c,b850322b,b747b544,6f271073,4c8b06f9,5988feab,663bb60c) Z8(8416a9d1,6baa1f0e,c52e672c,fb39d1e6,59f39c99,09f018ef,1cbf3fee,9fce3f31) Z8(e744a12f,58187667,2ef124e9,e711448c,c5dcb3bd,e68572e1,b58d0d02,e6f8b288) Z8(2a538117,545e428e,5fbda996,5ccf7ec6,db26bc87,70213918,cf0e01b3,7af2f464) Z8(c7fe55cc,db4c8ac7,66f0fb42,4dab0ca4,49a8f45a,e099650e,e5aa1998,3719ba9f) Z8(002cf89d,3224cf1e,61c17f8d,556ea15d,a7f76f77,f181611a,64c931d0,0e67aaeb) Z8(013a3bf6,d0935eb0,b957f3aa,4b75521f,169fa734,d2f0ea1b,76447569,b2bfc5b2) Z8(10e5db78,25de698c,4c4d5221,dcec6cad,83bed06b,80463648,dc9e5134,3941bfce) Z8(a930e0ba,6c22ce62,5f2db9da,61f9e13b,de51beba,4f044b29,2e5d8410,c0300b90) Z8(6c6f18b2,18079375,fe02182f,9baa1442,d9fd2440,9d924d29,40ffbb9c,2e98511f) Z8(e82459ff,b7daf8ad,cb16637c,00c143a5,30225272,31331013,b4e1dbb2,88868625) },{ Z8(199145d2,4554ae5f,da1c3ded,1e6d7227,b11b34a8,222051aa,df867774,e62d7b6b) Z8(097a0750,e6c15308,9f12a714,9437ca09,28fddea1,286a1350,7f0002a3,2cd2fe3e) Z8(1433a800,8383c878,11c1f4bd,8ba6cc33,38d02d40,277ff01c,db97b7b0,e2ce597d) Z8(76a634d5,c6542b04,db08d831,8219c5ad,983c9548,c380256f,680073f7,1f6e017c) Z8(b86146e6,e482f35d,1e509c81,548bcc26,3f922d0d,508dbf6b,a8a10f5d,56b72717) Z8(bf9f8cda,1bf24835,1e3a4ff6,6e0a2181,9839fc0e,416b7f3b,76385c2d,bbfe75d7) Z8(8ef71662,0fb965a5,90b53c5c,1e45580d,ce418095,f0e34cee,ae5d38c1,ecaa201a) Z8(3c56a4d9,fe9d2bf8,526740f0,eafac849,85cae338,e540f22a,e876f25a,7d33fad8) Z8(2120b92f,453c5601,7be5304b,12d22972,20770012,e6dc0473,f54ac0d9,f91ffe85) Z8(0a7983f6,1edf2732,430f5ecf,73117c05,b68baedd,9fe7ec21,80e89127,952f83f7) Z8(87f08724,3235a3fd,6902b81f,1b845a52,afaea64a,c07cea6a,f83a2083,30f72627) Z8(85e697f8,2f5d95d3,04657951,f4bcc8bb,c35ac00d,ed1a73f8,0cccbc58,24dd6244) Z8(d2c2e9f5,7acd29df,aa698a38,b9943de9,98217007,012b3055,9fa2d471,c8407cb4) Z8(7640da09,b1a679ba,84e556c5,468c8fc9,5f2a0a28,8222f482,07ae30d6,b819a0d2) Z8(4c72ea2d,a8ae5fe5,4089ba0e,2404485d,a0542ac1,604f5d4c,b7fc39dc,40dcdba4) Z8(830afe4e,6bff8d1c,a57de353,a40d66f0,593a47f0,e3156f4c,1efcfd3d,90199701) Z8(54ad6bcd,98e8c786,d911d9cb,20f45700,d4862d5c,d45fa91a,3c87146c,2556da84) Z8(6a7e0fd4,44b13ca2,5d246c57,75eb26f6,0c1a9a53,d561efbc,1526311d,d88e820b) },{ Z8(70915b44,78221239,b4c5bdf6,2b4cd1e4,e64d98ee,496e8ba3,ccc5c3a8,2e75184e) Z8(33ccf672,a3213ed9,2dbf3052,55625d94,8f743223,658aa0b6,f0dfc541,a77b005f) Z8(3adf0dc1,3832bf32,cfde793f,dfbb8627,7bd7391b,570fafa2,8f84a790,1613a215) Z8(cd87e562,3d3f3de1,79149c02,a7e9acdf,0b3b26a0,050297e8,03c34fe5,c607cc02) Z8(00550082,a8c14011,bd9a9921,fcd9762b,ea120581,31a4236f,76ccc3a7,847aa2d2) Z8(3d19ae97,8f8e1db3,54726732,850ae9b9,5d4e3204,60d06320,f1e11bc2,40bd5238) Z8(465caa0a,58a54671,994b3887,f721d800,e3b82376,90f069cd,876b6ee8,138d680b) Z8(aa10c2d9,3ba6afcc,d7609a72,b82390d1,44b5535e,73b12a49,a681085e,a0ca2f84) Z8(b4b06438,55fd156f,70bb968f,2eff8eda,bec75566,163c3237,6227469f,e91a2b16) Z8(6d564fb6,9e2cd17b,d2e0a8ec,f09398f2,9a035b1b,06ee5e44,8b1543f0,55f76a15) Z8(daa49030,102fa89f,565de8bb,89e2de78,ffd3f1bb,ae8b325f,930b85b7,afd5156b) Z8(9dabd83b,1d215579,8615d730,ffdd6e5a,8ec363dc,f2383263,31a8b72b,83a666b4) Z8(e7dc8fda,0b788c55,cf059505,b272e815,192984c1,e9c78c99,744cc3be,4af5e107) Z8(9749a43c,9a2d97e4,64fd5909,acb45d8d,a19a8ba7,ace6c6d4,e2597cad,3d21c246) Z8(23948b74,af904ae2,1ed5f791,e40471d4,3a06823f,c3d44f2a,9cfa402e,7dbbf2b0) Z8(6b7e1b76,d3f8d17c,c8fc793d,7eaafc0d,b6055076,21689cff,e3c4be9d,bf70affd) Z8(f3f0a1bb,b5fcad13,947a01b2,2d9ea398,50da2540,9f895450,9d128af3,5b4b28b2) Z8(c8fce5c7,0a14f7fc,f19a2223,21417d46,d5a3ffd4,a3fa4f41,b2ba6122,8f39a191) },{ Z8(11fde46a,b0ec8483,192fe680,d5fd2e82,21491754,ab14fbaa,0a3b05dd,b271c498) Z8(50319442,a38e7d6a,5d349f95,c81ec3d1,5cbf9d7b,092dcf6b,8fa18f9b,2564f5e9) Z8(821bee27,28a531f6,b377a377,5958e669,b11ec868,40748370,e42047c0,e36ef3e6) Z8(9f733be5,049dca0a,632a8694,b7168e8b,d5c7e62a,80050f84,92ca2d2e,7d0f6dcf) Z8(e77497a0,774dba62,e706ad6b,12590b8c,17e91138,28e37ae6,a9d6b7af,c81ab034) Z8(376cad1f,2354baaa,ca3fb288,3257d015,86565542,8d1a299f,e3bef6c1,e30be40f) Z8(a508c917,eff14bfc,288968bd,1a836311,5e6d01bc,443d3ca5,f27d74a3,cdcd93ec) Z8(20f45db0,c4765296,0ea9ad78,6ddc02ff,c6b943ac,83f14d53,d283c07d,54d931ea) Z8(dc26fe2d,c3679a4e,b2767653,1c429e78,3b26632c,e1bf2f68,f0ba47a1,4e5fe7a6) Z8(ce5d41f0,3d86bd64,042925ca,a7889b0f,b98323cb,06187227,0a4d9fe2,05684711) Z8(a9426152,689b8d46,e99f8dac,4f6a4926,84743135,453a50c0,1d068eb2,b123ef4b) Z8(cbdba753,317753b5,311736ba,413e67b4,1bef794d,5e541db6,89fb228f,86ba041f) Z8(4f7ad377,baf131a7,1cd2c7b8,fdd8ba22,7c0619ec,c7e0e991,f5439383,cf170048) Z8(6eecfc51,dbd659f4,1cf885cd,45f839c9,4f8c7de3,96ff3b9e,c3bb3b89,99a15991) Z8(75aea318,e2a0386c,d0e4c0a5,84e88742,401bc26c,089013be,986bdea4,7608a6ad) Z8(4d0e3661,37b12f3b,e66a4b20,48736ba2,e00b117c,1cd6a41c,1b7960c5,a3ebefd2) Z8(90efd895,d9a725f4,7a5ecf8e,d9708ec1,69ee9a34,85c651f1,bdfe1ac9,18d1fd5b) Z8(241427fc,b68ca0f2,cb1d5fcc,d86f8d34,3c8d9304,f031c2f6,9f0168cd,d42f6a1b) },{ Z8(d881ba4a,32deab9c,6c56b5c9,59fc4f69,37790596,26d9c577,32d48c1d,4e3e7f28) Z8(73da8849,e6b0a703,c707210f,b18a5cfb,6d82893f,63babf47,1ce1c5d7,045a3597) Z8(f61bd745,2d15cf54,2664786c,2a7de8a5,8bdd43c0,077e7a1b,b0f08c3a,bc004bc4) Z8(923fd2ac,f9ae178b,77530553,90555248,eb6742a4,88582037,7fe8d5a9,1ad0d4a0) Z8(138be571,c23ccd95,880861d9,5afaaf7f,6e870f3a,c846b7c5,da488ebd,2696a4f8) Z8(41108363,8fcac41f,83b36342,508311eb,da290ac3,8bed3bc3,d1812b8d,2885260d) Z8(f9075942,a91dcdae,5de197b2,68c7d9a9,eb75f6f5,92b452d9,c55d2a9f,f83ec4aa) Z8(69eff276,76ce34de,5f7b8222,866b3694,9e120b1f,cbad5b5e,5d400d36,202baf4c) Z8(a428d468,f7048c56,986506b8,187a6558,13ac4561,e4672563,b01a2470,d9daf1f7) Z8(dedb8d30,3012b0cc,a3d00fac,d401d488,86107d94,fc44212b,bd3c0aec,979759d1) Z8(468d0447,61d7853c,64f6cd01,51682acf,db9b3961,c823b119,87a1cc7d,73f132f1) Z8(e2e0cd77,192821e2,b15e473b,54c350e4,7efaa243,639da0f8,50dd021c,c8dce081) Z8(1d78644a,4725fdcc,f9b31139,71587719,f21f4e91,718b93ed,a656247d,6c61d702) Z8(0e93f975,f31f5e74,f7f293cd,be4d4c42,0916e6e3,d5cab316,d2089162,e79f616e) Z8(55e113cd,4b51ecb7,3bd666e1,c4ff42ec,bf3cb880,fa371967,0bc3ff50,afdc4761) Z8(9da5bdd8,babe901f,cfa16516,47940b49,3ab9d457,6c585133,f92ebdf0,de759e14) Z8(e5cdc91d,27f8d5f0,c52be852,efd5aff7,05125480,e80594be,8f90401f,f3c2ec26) Z8(445b61eb,f8c232a6,6ebb10f5,5fa61a15,aa09e851,91c49bd2,4210ec0b,95c8ef54) },{ Z8(8a74526f,e740d1ff,281d2a0d,cf505283,b3ab412b,bfb8c163,f7d588d6,21eae431) Z8(3f9268ce,94154b51,bb29b94a,adf839ae,a92d135e,bee4ef55,94ef0839,4245d8ec) Z8(4824046a,3649b306,54c58b4c,5a7216fa,8824c197,f4b89228,9cf285d2,6532332a) Z8(6f7d304c,d35952f7,8b572692,7ab8f80d,876f2de2,ebef0b19,f9d92dc0,075d859b) Z8(6f4bd444,d2f55f03,573c37e7,d0bf12d8,024e833e,1b2f9705,d26c0292,2a779419) Z8(0165c3b7,de03142a,13ff09be,72c0ea63,c4cf0eb0,aa60e05a,9a408ad9,3448a2b6) Z8(98f60b03,51377e73,8d35cd51,b1d29845,f7ed3bef,7f64b3cd,8033b006,83901f06) Z8(bda90349,44e20144,7d89b058,f0689f15,45766f6d,b9324153,422505a3,c2660806) Z8(15de8ce5,59311871,a8319de3,a5a37c84,b682f00d,b97ae596,2abeaa32,c7261416) Z8(df89235f,6d10baaa,51335a18,513ef75e,53137aeb,be22c3fe,fe9165fa,7698d9fc) Z8(ae96338c,736df6bb,6314e7ae,a89ef087,5c9b5868,43175037,ad455325,a12a8360) Z8(007e6aa9,41f4610b,fdb3ad4b,c504da5a,2a5b5779,845a3287,acd4ccc2,59ea0f40) Z8(3970543b,b9efa8d4,03383bcf,361ade79,cbf5fc06,e5276002,14dcb4e9,8dd52ea9) Z8(88a97251,c2b4f1e7,a01d3d37,63e8c503,c6e49c4d,cae8d11e,2030fe80,cb335382) Z8(cbecc5dd,5575cbec,e794655b,6e2ab7df,4305aebd,a3bd6ed7,ba1f97db,f4d23ead) Z8(2a3da43e,f7d4faf7,4cb7a3bb,ed1760de,e2b9f96f,76b26b1d,de103ac8,58df8d78) Z8(228bcc6f,d1537178,3d3e077f,78e48ebc,bab40852,676aac6b,8789424c,db1974b5) Z8(445043dc,870f4200,0179a256,7bcc1ed0,3f308eaf,bfe750dd,897c25c5,cf9b476c) },{ Z8(2fec1d10,29b19213,311c948a,0e9bbfac,1721df97,3a05d7e1,21cf8a68,ac71c15f) Z8(33223616,f4c7d2e1,6a820e1f,f1328338,01403689,14aa32ef,6e802a59,2a1038d3) Z8(dc9a9033,b5846019,eacc2b16,c734a4b8,eb21ff9f,1bcd2fa0,8baefe92,7b4fb2b8) Z8(01659ece,0453281a,4e8cd4d4,4bbe5fd7,686097cc,4ed71e66,f3ba3954,72d80f48) Z8(486c207c,891a9a81,3d20f121,58c3c706,bfc95007,95b3e423,97c1ac7d,4e322d8a) Z8(555a143b,fd057f37,a691f840,903963d1,c87cf1c3,01195760,871d96f6,c4908929) Z8(81f4dccf,44367d05,55e35209,d20a98e3,d20e264d,530fdb1b,52af0d74,03e46cc4) Z8(a0c76b62,1ec49fa2,24b0fd9e,92b6bef6,32bab5e2,40c90cd6,36be955c,3cd3bee6) Z8(f32a62ea,3b0ccb0b,88458608,a74f7006,e3cb3ffb,5b9749c6,071ed0f4,c103307a) Z8(c33e108c,d8fa558a,d8134f8e,5605793f,19277773,2fb0bbb0,3716c5af,46b9083d) Z8(60ca69b6,16c116c7,ead99d44,25f8f4e1,1a7db835,06ac3787,de9c60af,c352a6a1) Z8(269c6394,74f2c81e,8cc56eec,1c2d38a2,5adc0416,e521cb11,d6af3455,e42264bd) Z8(8d2f5dfd,64f57d3a,cd570976,ca581afe,49df832a,853131f4,ca5900eb,ce2126bf) Z8(c560cd29,27a08b2f,2ebd613e,43e705cf,23fb0c02,4355087c,738ab7d7,f0cee866) Z8(b01bc204,01d259ca,42a2899a,6c9969f0,077d654f,de90f3b8,d70ac6ac,bbb92db3) Z8(178fb379,62b3a3d7,ef6c71e6,847d431b,9204a05e,bdb184e6,361d1046,23cba554) Z8(307cd9e6,d6d14ec2,8d9242b0,952e6f6a,24f1dd6b,8f14cad5,d045cab1,648a462b) Z8(bd7b9183,8e62a282,ceb1ac8a,6a547cd7,857991ca,05256c4f,b14156ef,9c32cba2) },{ Z8(03b84ba4,3d5237d2,5ba5697b,d646a88f,9c0ff08c,285955ac,e057593c,0a8774a9) Z8(7d4fefa8,c5036fe0,cfd9da80,3d240b28,33a321a2,a043f8e9,cc2159f0,c3d36f3a) Z8(f419c096,c8c8712f,1a7bceaf,ec349c90,524b58f8,bbe44176,3362a922,584c06f0) Z8(88b5c3e7,d63db159,091c88df,a8980e48,337282d7,b4a0a058,fbf735cb,29be8b0f) Z8(c21efa2f,c07a5caa,4e1bbc07,0eb2e2b6,e8dcb238,940ffd84,e4d6ec7e,f59383e5) Z8(ba6f0de4,eeff8066,3874a148,9626e36b,7f10de8f,240b04a0,3864ba92,7f8a129d) Z8(fb71bdc3,02d3fbde,80f9ca94,7e701be7,9d278a70,3bd4b959,bd5188a1,a66f71fc) Z8(06b7cf6a,63ac889c,6ea88304,62c0cebb,8763be2c,d93107b7,62c59afa,3066bb22) Z8(204a61d6,a3a5efc4,49934b16,d86c6609,972465fc,c2757f71,f79c0b29,e588c915) Z8(e03e1482,6969b9b7,4f64c738,ee35ff7a,2bca682b,0bf5cdd7,48d584e5,9a69bbd1) Z8(cb7de008,5749336d,203ce4a3,f891d728,e590234a,141d89fa,8be36e67,b2e59b37) Z8(2d415c38,908f7722,6f91859f,35d777cb,cbf9adc1,a89a9b1b,1bcb63a1,c1f9dddc) Z8(eb736331,6e455494,abd01265,b6f223d2,c145aca5,696a6d8d,58a9d010,fedf3bf9) Z8(73556876,f00a4dc3,03bc564e,c2b5c693,a0d6a476,b33ee6b3,efa90800,e2d2b13a) Z8(619a2841,12a98b58,39af4242,e72605fe,faf3dbcd,3da7bc62,6fc50a95,8e5ad663) Z8(945d02eb,15c7a822,d8a0e632,ba653704,68736294,c8fed5db,1c5b749c,155fef19) Z8(d1df7c8f,fb375501,21d4b453,b25c3ad9,b0493a9c,0acc4600,787a6268,ca0e0e62) Z8(b3db1448,43d7be83,87a780b2,a773f879,3a66a0e6,204bbc0f,658fe5e8,cad33f00) },{ Z8(8d6d70e3,e1b7f9aa,6d9184ca,8d0832be,9405d6d7,8fb94978,73b05491,38df2d94) Z8(00b8d279,ee14a39e,89b1244f,569956c9,1abbd0e7,f97ede86,b8bf597b,2d190e11) Z8(37044f29,24cc70ab,d0877263,c56fe8d5,46bdca3e,55483dc1,c4c574f8,91327289) Z8(0398e235,fdb10941,48325ebc,acc692c6,e7d6b6ab,79665e7a,52180adb,75a82d01) Z8(216d7d42,21562010,8b8ecf97,792a17c2,d272a21c,8034269d,e4bbc453,096ca489) Z8(3819c31d,4f420c50,3aaa3746,2af2716e,158760df,872038a3,2e1d98fc,193ef418) Z8(cf9c07e0,8a14d35a,e139c061,0522a6cc,758f3119,d45d8ebf,6ca92c66,2216f6e7) Z8(b1e16b7f,6840b21c,3e1087d3,b8f0d3f6,08670457,f0bd9650,423b6b67,62f8e2b5) Z8(8f320c80,23c9209e,6629b88b,c9ae21f6,2e61613d,e36a6cfb,222e7c37,ab8cde4a) Z8(ad7a1947,c5a6d2b4,e384e189,8774f2e8,46f048d9,c1978c6e,f394f878,9c9d8ed3) Z8(63e9be95,462762ee,76983983,d085c22b,02f99be8,b80fc4c7,d4ac8a7e,c503f211) Z8(df0d343d,58c1b818,f0a0409d,8557f2ce,60a3205f,9623e31c,0827bcb0,9cc4a821) Z8(b2bbfee2,40efc916,b29e78e8,52f47075,9364d504,056260c7,a05d11e3,1a84141b) Z8(6df825d0,092efa4e,1e6eee31,cbcd918b,22a317fd,4a51cc83,ab477ae2,9998c8fa) Z8(31f892f2,d478a67c,2ceda66f,7ddeecc9,3042a8fc,6b4c4b1a,5054eeb6,928c5bda) Z8(044f8786,5a23b635,1cc391d3,8f7cb21d,6967127d,b7e285f1,88305cc1,5953d866) Z8(d517276e,b70ff3ad,973634be,ef29ee5f,93f211d4,6ca11f40,914f1901,7bda4332) Z8(4ad66f31,bb0b7cdf,cb1d9eb7,82c66160,5f5405c1,527c32b5,79c35582,a2759c0e) },{ Z8(72aa41c8,9fb203cf,7298571b,58bd4295,52dbfac0,962c0f81,4075fb9a,80fe6803) Z8(48dcd218,49732822,9156640e,22f61d42,c3409dd6,7191d056,bc1bd3f1,e718a5ef) Z8(625ac2ec,e01263b6,59ac32a6,228c0ee2,748cb89c,ed296aab,8786f98f,210f655e) Z8(bab1b39c,c3c6c160,f4ff7481,c95b27ec,3a17d185,49d839c3,be472402,64314abf) Z8(2e35ecc3,3704b188,27be2bc0,54068d4d,e2e60be9,6bc735fa,faa8c0c1,638b4bc4) Z8(e9eadc25,4bc7c705,a0172e0a,62475449,9736efcc,684c0f88,a1a55bb9,1310cafa) Z8(f6bfb3d2,6f2b86dc,2f9b0c1c,dd1f93c4,32e888e4,69c11bdd,2d09c6b0,335685dd) Z8(fb01afad,e171f05f,c89f543c,139d89f7,8f0b8822,21861ef5,c07cda47,f3614101) Z8(3ff70794,702d995d,7d723fb4,0770831b,52749355,b4bdcb43,1cc21619,c7474526) Z8(f9470fc1,18c59c2c,5fa775aa,5466d2b8,4b0daa10,80aa5f60,6269bfb1,d6dffb6c) Z8(576f7700,6ab267d8,e8aaad8c,9bf2299e,953caa46,3e95db5b,e04690cd,e678b61e) Z8(6890f398,93ee0c2b,70ee01ae,cfa1715b,03e22d67,76942d1f,7d69b519,ed39dd27) Z8(4b49b807,bdfd9a4b,b26a67c8,019f2c2a,5e312275,4f413b69,abf7586a,03ae445d) Z8(9fd9c44c,8c232192,9be7611e,e34b07ad,570940e6,592317b3,176a22db,c6678387) Z8(1316bc5c,3936d6e6,a01fd034,174bcc0c,0246b9f0,1eb4a9cb,28aba4bc,fc90b2a3) Z8(1f4707f7,8dd119a9,ddc90133,2376174e,ad789019,1ad326f1,499cf19d,2b7190a6) Z8(d1b06f8b,122b6b60,8dbe2d11,02336e0f,29d5350a,e9896341,5da0dddd,4676a1cc) Z8(16de6ad4,365389b7,f93655d2,4f82ed4c,981e3480,7c07d28e,ee48030c,c5d882d2) },{ Z8(f7584d16,c902f221,79441dfc,1549088a,d62f96c4,c94c04c3,9c706888,aa6dbea4) Z8(219cb083,75184036,62755020,09229c82,241b0570,c88c813c,377a8bdc,076bbfbb) Z8(14b7b42b,093bc633,5396af98,9fd5847c,37cfc00c,72cc073a,e55ccfd8,051263d4) Z8(6656b24e,4f8021a0,f9360152,530c44d9,e5293e7d,3ae9033f,f27dc100,09f9dd34) Z8(042a2a9a,093075fb,6b86357c,4f357641,33e5edf3,e2e12f08,b38904ea,64d23074) Z8(bef69d49,cbd474c6,0a75d7e7,de712688,55b1bcbb,57991c7c,8e01507b,8feef664) Z8(f111e8a3,759dc600,f0620105,f711c6df,7aeed988,de4134e7,364f50ad,6422c14e) Z8(cdfc1ee0,f55865d0,a9c8e599,4c00da19,3092a183,5bd28923,fe14fd9e,f29a4c86) Z8(ea5bcfd6,2dc5e461,66a1e991,d5ef515b,8b293454,c1efadf1,df97088e,d8dc1c89) Z8(10c06d93,9dc38e9f,1ccf9a7f,cbccf897,0cf65b84,8e5f1281,0e78fac1,ead6a85b) Z8(937f349a,b3583913,4e3edd6a,1d41cafa,a4cd41fa,deb460a3,d9ae0ed0,3a008302) Z8(17aa26de,107b36c8,d50e638c,d7589b70,127b6f53,1aa09e34,b936cf34,f4ccd990) Z8(af43e24f,55673787,a3955ab5,562cbf5f,d7052875,99a69d00,6d8b6197,2206e66a) Z8(58eff311,6d2e172f,ab69ef04,acc07956,d0d13a69,9cbb57f0,dae4cb3b,487eb980) Z8(305fe6c9,5cc9110f,d8a26db0,d20dad38,2419c5b8,886c0911,20474b35,26988b3d) Z8(520d3776,e7a8e1a4,731500a7,4679930c,291c2bba,f1eed1c0,efa4a395,e1664007) Z8(215eddce,6525549f,55430115,ff9d7a6e,72ac7226,1a0fe34d,a9975ce8,4214f8cf) Z8(c6f12a2d,c985491e,e735f8bc,20f7e7fb,f9e24399,e2f3c76e,d9a8dd47,a88fcfeb) },{ Z8(eaaa1bc9,de763a75,13c798a6,cfa29156,2ea80de2,20b6f242,a3ec9d9e,7284b3cc) Z8(09f62682,a7fb5284,851df16c,5145bec7,f6d39dbe,0e2e33ca,c741fcff,4e9863db) Z8(4e4f85ee,5fe3ba1f,93b98c3b,a2eb9d63,5ce31e54,004ac3e0,5079a14c,84cf855e) Z8(0104ec51,7cc3e197,7a693862,5f1f55ab,b50deae6,d8264515,a9b8c109,7260179f) Z8(30ab6920,5b4078c6,5f102123,a6967ce1,1fe4927c,b1bc8977,3c5c5720,f03e07b6) Z8(c65cb58c,49f36308,f04b07e5,57f0f36f,af8d3dee,a857c4ae,09f586b7,d8208c2b) Z8(8f0ba46b,5d2a3875,11345820,5deecccf,d65ea79d,2da5ca60,e01416df,1223a4b5) Z8(047859d6,6fc50ced,3eb0fddc,3656a9f2,41650d0c,2b3b3647,17c5cdb7,daa2832a) Z8(839def48,5e075cb8,a91dd93d,97db7162,23eae84b,a5adc77e,ced34a63,940e7c4b) Z8(91582da7,2a909a07,f4cfdae0,b5554ea9,c21d97fe,14e3e2d7,f7e8d1a7,b4a4e017) Z8(92d41587,cabbc49e,c785e823,157b0273,f3e9b93c,8c32e17c,f67e464e,c374cdc9) Z8(4a81efe2,955278e7,64635805,aa0a5d71,346c9bc4,1084f03a,de4eabb0,8f792bed) Z8(dd1b163a,1d92c613,5d57b0c9,73908bae,73c86030,33206ea2,72e6343c,ea4438e5) Z8(5e5b27fd,14eae6c7,d6b05a55,bd0caf33,0522a926,ccbada42,5696dcf0,4a5cd73d) Z8(84f7ff86,0eaa3926,e5d9f74a,7805fa5d,87131de0,9e4384a4,2311ed73,54a416b7) Z8(8c3b7fe8,b3d03a08,5ddb2b2d,53093eec,61521ba8,85079f3c,dae799cc,55fc77f7) Z8(6db6a625,4148ab97,27ed8b40,9e2eb1dd,e2f2afa8,fb6290b1,4361b8cc,9660116b) Z8(7de9aa6d,7a48a6e9,4356fb50,ebcb8bed,b90cb15a,ba37a3ee,8b6ae710,c0ac518c) },{ Z8(8146ef86,1e21b0dc,94c239d9,623028c9,ac786783,be3796c8,440729c5,d45214a1) Z8(1081f102,88d48b28,3fa8beb4,fbed0e70,9950a057,44a6512b,53fd0174,41b9a64d) Z8(c015231a,718bcf5a,6a02369f,d6282f4c,c62db523,34350b99,fad983af,8a0cdc41) Z8(8dc6c5c6,de938b26,28814d70,83f9f67b,ef2657d0,6f0634fd,69e5ce84,c92c78fa) Z8(a4050f2a,96922b50,b6cc64aa,07c3c387,60fce5eb,03bfc115,7248092e,4421b282) Z8(db44a9d6,5101b96a,856a916d,7ce2d831,276a2e3d,9319571f,2cd6b8a8,3f559bc1) Z8(95a29215,22e5433e,5b4a21f3,25fc5a3b,f657f56a,43fc92f8,bf62a7a1,50b6d44f) Z8(47c37a9d,0372faf6,aa6181be,dc7c451d,10acbb5a,4efb18e6,5b572710,da1eed73) Z8(8cda5bde,3eb68632,e9000f08,b03b2b7a,b376b138,2e9915d0,6b13fed7,8e2ac220) Z8(579c696e,758d0bd1,3490dc1c,0dfd46de,82784e52,aff26b40,a42d0fdb,a8b1cde2) Z8(72b4ab24,7589b939,7b6f83b2,a4848d27,73c6f602,d0f83096,72fed717,e49d90a9) Z8(01b29481,802c4c4e,4211755b,28421097,4f3f9b27,afc857ff,1a6997cc,2643b076) Z8(bab6556c,cc49be09,f0d6011b,c5a2b785,346b867c,002920f1,96eead01,c7e4e3ee) Z8(15b65fbe,6ef9c4d4,9459d0ce,635b6f39,0e987bc6,af4964ea,93a037c6,80148dbd) Z8(2aaaa784,5c8f6855,2b7bd8b9,2d7fa7d7,cf257516,2d946de2,4e6beb47,d3042a20) Z8(8b6899b8,cfc6e9e0,e76d4989,ffc3c398,e64d7717,af419799,baa33593,988fd59e) Z8(f5459f68,b53cadf4,06f81956,e7c8e051,27e858ee,ef13e9a8,a6a40f98,0a971a49) Z8(cd044cb1,7533f532,646425fc,476747c2,f140a488,966e1d6a,fc786b2d,ae7fe0b5) },{ Z8(0a4d46f3,053a6f92,63f7193b,c8fc3cf7,ec20c825,ba9b6b4a,83a0e662,c7a8a3bd) Z8(ed9f5064,5c84708c,6141681d,9391c70b,98265a57,7fb2563e,13952c30,155299bc) Z8(2042f165,0abd82d4,527cff24,c3a77dea,8fa224d7,9fcfbbd9,8884e95b,9627d11a) Z8(140fac51,d4a637ab,e7b34121,29959997,77757122,9a05d2bc,4ab5cc04,4988b9cb) Z8(bec6b81d,d0f88e68,6c1fb45a,2d0ffd4a,773ca5d3,aba196ea,f184954a,4223581a) Z8(d53fc8aa,320b2554,7a0b722b,8db9e36d,7f507b2b,7ec19166,14e221c2,f82ac027) Z8(4e1713ac,bc45ba04,2a0e32d8,ad6414c3,53d3e2ce,0c7116cd,3ed8700f,e5b64cd2) Z8(4b76aa52,803182c7,75d8eee1,cb0320a3,3b735c99,638ac7a2,a1576b36,a769f620) Z8(a8ab7d9b,06756c7b,49d48083,3eda1e85,09efccc4,2d84e559,c191c446,f9edb8fc) Z8(8dd703b4,9c537e22,6e64fcce,4819e217,b676a260,b43d6216,4b028e6d,0fa0280c) Z8(434cb844,09e535ab,273f87bf,a1a1bca4,d7adb95b,68075b88,54d5f6a7,47824569) Z8(ce76d5ad,6f306378,0a8c5a46,fcf01054,24783339,b396bfab,416e64cb,5e1cfab8) Z8(d11590c9,ee2a2ac8,4bc91bfc,38b91773,98c4b344,30891746,ff67184b,9a7bb115) Z8(b25f8b0e,582006c5,ce2b0da4,dbe46dd5,01dafb04,6509c104,107c00cf,44f065e5) Z8(e25903ed,560d0916,21f76bb4,ea5c6808,c92bd72c,b7c6323b,610fc749,c98b64d0) Z8(1587b4ff,61fb608e,4a1b4868,ebc25092,75e04249,420d95f0,37c8d3ad,03bbc7be) Z8(8c9582b2,94980cc7,5304c25d,1fa13c55,d8e7df66,cc891f2d,d069f9b5,106dbe6f) Z8(e35575c3,e4aee845,0e7e44e6,e0bfb8f2,b9d993b4,c151839c,a908f73e,bb4ff632) },{ Z8(fced3a0f,73677216,f37a50a9,e6695f15,4624fae8,5b5dbe47,1fcb5803,1b618f2a) Z8(44748b8b,4e422175,d610c7f3,481937c8,aa2fc15e,f2a754f7,b335eb6d,94d0bcec) Z8(42853eec,96281e02,bc1a8adb,0e126ae4,7b45363c,86241398,6cfd0947,bb064960) Z8(e8cb845a,ba927717,cdc91aab,450bdfe9,ca254e12,24fb7ebb,2f51dd96,a527b371) Z8(d6e80d1c,e4c150e9,56e6c8be,0634ba41,9a21e798,6412cdd2,8c11784f,20a647f6) Z8(765396ef,7fa6f231,35121b53,81df0464,1db74c5e,aaeafceb,d39812d8,68e4b744) Z8(863ffe20,8ec917ea,c7b8096e,d5ab3930,8ae89c08,2e60d986,de336329,1f59adef) Z8(ee0d65b5,0fe00c04,209acbe8,7ca1179d,9a922749,c5850c77,242a80f8,2915180c) Z8(a632ebeb,110bfc7b,9b7b9e2c,f5b6c47b,44286c2b,5bdc8b25,506931c5,a28824d3) Z8(bb9dc8d0,2c67480c,c36e94e8,1cc3f53c,54e523b4,8c3d033b,cbde12b8,65c9087a) Z8(bf65b70b,cf607731,5b4059ae,56e00b0c,fd3d2993,797cc00a,8663963d,f4b6d78e) Z8(afcb1316,b5d50883,2dd1f440,28e01507,caacaefd,84afec08,d3d9266e,f9a4e2ab) Z8(3cee5f18,107f795d,cd38e678,6a0006a8,a79954b1,86693808,d42f67d3,c50addf2) Z8(7c54858d,e006a1b0,c4ac0e7a,af271db5,40213653,e7bd897e,e5a3d995,c2cc42b9) Z8(140314d0,2ba9e707,6186e48b,619e024e,caabb84e,c1557feb,e302502a,12d40ff5) Z8(a45c539a,86433a5b,fcbe505b,560cc7ca,abad4678,2824f2d8,089039d5,7373ca7c) Z8(efb95d69,6f114a27,eb08228f,b5536120,2b4ae134,539ad8d9,5b30f6ab,111ddc38) Z8(2aeb4aae,d103207e,b2b133f7,11f0433e,434a59d1,05913765,9a597529,b4445270) },{ Z8(55c52d9b,2079293f,266bccbd,995de7ad,49ccdbfa,1a909571,c7c27258,2b7c55b6) Z8(68e6e000,35cefd5f,42673e65,b37174b6,61fc186f,2073140c,86ebc13a,cf9ec9b2) Z8(2a242841,eded5651,78cdb97e,cb2c4a14,1f58f98a,51bb3bff,3e06b766,f63baa4b) Z8(b5a04397,c1db6437,ef4463c5,a9cea0cc,90aeac4f,2c49133b,aa41a566,e6666420) Z8(0c993034,8c6fe4b8,2949592e,133ffd5c,5e9d1767,9b370b6b,a895ff88,00bf9512) Z8(a43d36be,ef0954d7,4b9cc316,ce3dded0,dd05e790,6830b134,1c3264af,e45f8e45) Z8(61c06257,894d833b,7efd7967,503148da,cbe786b7,6f2204af,479fa7bd,325294e6) Z8(c847cf24,952d8577,8caf3a8b,6087ef81,589b3077,af032009,a2563029,31570933) Z8(fc2c2331,836a09de,4286198a,c91079f4,8b48ca43,45f05078,9c669b00,be0cabb9) Z8(339ea3d5,f44277fa,2c58e1b2,cc7db996,4f763bb5,aeff479b,e05d6d65,737d3847) Z8(08907b9b,488bed29,7607d91d,0a66b840,48718e94,9c642786,94d49441,de7f33e1) Z8(602dd604,f66a5a2e,fcc461b2,644f3463,32ade9d7,ca4983dd,6d4b1494,07f139b9) Z8(6901d476,0b073c68,643749df,a4c5b89e,db6a49c3,c5a04680,799585f9,fba170a5) Z8(ff58729e,a7a24cc2,4f2af059,4281c9bc,a9f6f666,d22d4e06,87314c18,9b2269e1) Z8(c8dcd584,0eadb51a,90ee9223,bc139a86,366cea4a,01f4e5c0,ad20f6e4,ab016631) Z8(b1571fa9,023600ee,6f3cc5b1,9e0793d8,05f49514,49244449,e7dc3024,dbe3c930) Z8(72c91199,73399f6c,2c4ab755,4da5f5b0,4e622c2f,62ec3d35,3e185eac,81bddfc3) Z8(6d6b90e8,9d9c53ee,e74fe751,3e73b6e5,4b1a498d,ac786ccf,f7dae915,b5c4c7d4) }}; const mp_limb_t arb_sin_cos_tab22[2 * ARB_SIN_COS_TAB22_NUM][ARB_SIN_COS_TAB2_LIMBS] = {{ Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) },{ Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) Z8(ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff) },{ Z8(370d0dbb,d133d2af,293f7660,41e6d1e0,3fd9988f,ef7a65da,bb5ab0cc,58f10d37) Z8(196aca8b,c62227a0,9b63185b,00a7cd98,19c8d7f0,35b3b678,8ebe6c24,fddcaaf9) Z8(87ed9056,cadfcac7,27b89df2,5ee474a5,e23fef08,cc39d58f,9afef193,715ca371) Z8(a6ea982c,ab6c35bb,1dc09422,50e88862,60d5c943,a70a47fc,c40034c0,e9e27117) Z8(ecd40cd3,f4fc351e,e054beea,0b4e7847,cef43bb3,b0a54a59,b02e604f,b3ddbc1f) Z8(204ce260,9efaadc1,25ddcf5e,b0836434,fc104e98,cdb73d54,06ead7d6,9cd83f53) Z8(eb156721,6abde0e6,06a4e3d6,43b5daae,441d8598,1dad0bb4,3791885a,ef90f16c) Z8(7bc256b8,deb9ac6d,b865b6dc,1939d5ca,c82a5a16,71fa50f1,4ad21c2a,bba8b41c) Z8(4cc06a44,2dff89d8,1578d90e,cd0833ea,efd9e91f,99a92841,2465bb99,7fc15d08) Z8(bb14e72f,f8b556db,b768057c,6eb27835,6552d95e,efe9a77e,42629efe,24d4c293) Z8(df89adfd,1726b1d9,e26ac62d,f7064fa9,0351da06,a820f727,a38b2408,b2c53a09) Z8(c9db9024,1e42f4bc,b723cf34,2e734481,d6f1e198,c97f9d1c,d9a5784b,9f51a9b2) Z8(9b578483,2153ad4a,47c08884,bf3cfdcf,1f397f2d,d0167a11,6b9c78ba,5065084e) Z8(cf8445f1,e90dd1ff,b3442520,8a5a4eab,a172dfa3,970d3618,352d2816,282cf9df) Z8(30e3d8c6,40af04b0,80fd8a20,9df6ec49,05453097,2b56558d,545de355,95609223) Z8(0018c1d0,4195be37,94e6d7e8,b9fb06bc,56cc89b6,1980f945,a033e3c8,cc347db6) Z8(78f33770,541a5b9b,cf786c4c,5fc14621,6abe2f10,90736720,4c533f8a,247a7949) Z8(8b0b60ae,da38f350,4f4348a9,7ad79ced,9db5698f,dddda9da,555555dd,003fffff) },{ Z8(7e01d160,8c2baa1b,ea2e971a,924d8012,b0fd9af6,24a61dc5,2e93fae5,91b6e434) Z8(7174e535,a9a51a76,d7a55dba,d8753355,00c2a6b8,482cef0c,5c4f508f,94e15efa) Z8(4e8d03d6,adb5ddf9,7839b1da,d1d52495,924e52bc,bda48b7b,a1fd8e80,0605265d) Z8(6dcdfd10,796eee9f,30a2c491,0b7a2616,4a01e13a,856b8b77,ca5c61e5,77fe5ce1) Z8(333a7443,569753bc,f16b29f9,0bafb325,a7516313,302b0d10,88aaf76d,f1a74f0a) Z8(7501a20f,c477cb51,b3f36f5b,553198fe,d4077777,53e1fdc0,9d98742d,74b2598f) Z8(0b017caf,3bb28410,e23e29d0,a75eac1f,68d0f715,9aab33cc,8f6af827,b3830188) Z8(1a283d2a,8fc68f6f,5c5c9daa,476c9e26,80ea38ed,0e2e52dc,1d5709b4,a3307a04) Z8(0ccebd55,e5fd575a,eb2af906,e60c3325,e1261516,6ff9d168,48e43c7a,218b8cec) Z8(8bad869e,773d8e88,c4784a1f,fbebbc6f,805b8591,46c9383f,2e79b290,56981513) Z8(1f880e0b,3cef1bf7,ffd45881,1bad0c36,00cc2276,fb9adbfe,44e18d5c,846c8dde) Z8(d4671611,6ae5cad4,f22ac6e9,25a110e7,8c15b58a,66a64e77,8ae8c517,863026ad) Z8(12d2fe3d,ef0538a1,e85366a4,c13496f5,5f38c369,46f2416e,eee8efa8,3b1f4639) Z8(61a00174,4cf4d454,731cf33c,19e4151c,12a5ba52,62b5c14c,8652ce6e,613ca3d0) Z8(b7a89315,cf78da75,672013cd,04bb6006,d6014f31,774dc4a4,cc1858c5,01b31089) Z8(f556eba4,6f881f68,5bebf492,2cdff950,6e353b24,52e5d955,5aacf241,f3683b91) Z8(a43b3321,786d5656,2638f6f6,ce32b63d,f29d77c3,3ce4ca6b,f1606a99,249478c7) Z8(218ac62a,3b56be83,959fd08b,7067c57e,9a69a650,a4fa4fa6,000aaaaa,fffff800) },{ Z8(b8403cf9,59492746,a3fc925c,98a2d108,3393d104,33ca9ea1,3916d291,cd7592dc) Z8(15400b44,8127c82d,d604db6e,f31de919,3c6010a3,c4606cf3,f2b4905b,b2fcd8cc) Z8(94b2efa1,7db51491,b6c05e21,e08ff0a9,f87a4dd8,630d587d,99a06095,e5d92ab6) Z8(0eb7f022,bb701754,cbe96eb6,742b8337,2665e2e3,ff8bfbca,4934ffef,1b5864ea) Z8(dc40e984,6655281b,05ab8352,26fc716b,ea584194,02b24b4d,79ededd2,d2755fb7) Z8(64b8eb7c,5ac77d2d,6f4dba8d,bb544f07,df4ddce3,e0790fcd,af2a7725,0bca5906) Z8(d981e911,7751548b,bdd32701,a29a875f,56b97f40,97b53a5b,24a2b0c1,f86588bb) Z8(dff807ea,1e001421,b49d2d0a,21591d79,1916dd50,c039759d,26ae3c9a,6d3ea427) Z8(eea05437,0f6b6e06,8a82e4e5,8c2943f5,7211aa7b,f9a61a45,acb9dcc8,b3bba369) Z8(069ad198,47410694,d710a819,691381b4,10f0da94,728411a2,7572776f,d37da6b7) Z8(73f7abc7,4cd10511,162118c7,5f6643e6,fca179a4,180aa255,dda681f2,11ce00ae) Z8(7267e588,01d01117,419899ee,dddeda31,cbb86aab,b923bc22,e2926b11,1e9ca5cf) Z8(8a442cb7,a1fdd976,18cae98f,06e7098a,37e76e75,89f23f0a,5876010c,ddc0259c) Z8(a86094cd,8c547a5e,d68056b8,a75f5c4e,8c5870b4,1daed039,096d40c7,2fd1f89c) Z8(073559bc,06427156,b6429d2a,41051985,b7126c57,691a4111,bfa3bb13,0477f492) Z8(e2fc83b4,a3856fee,c7f8f950,b4e1dc3d,cf5cabbd,73a2004d,cc5f04ee,8c603843) Z8(d586e1e8,36f73cf2,8ce764d3,bed5a942,e5a1f7a0,7a2b9bfc,76ad2efb,f813d949) Z8(8f5d3f78,521a69e0,b574f652,9dc026d3,b8d7ff39,bba1ba1b,aaaabbbb,007ffffa) },{ Z8(7748a6f3,54ae9cd1,9fc02d0e,5b252e65,43ad733c,4d3e1ec2,f0f1df98,aea5a2fe) Z8(f90eea6a,87ab92c7,06143123,cb33e447,ccc229d3,1af3afe2,3a762420,0bf6e2c1) Z8(e6326408,4f51875f,7b99bde3,43f7486e,e4d1b2d9,90e2855f,5e9469c5,fbd9eb10) Z8(825372db,66cc8790,8f50d40a,8fb44d25,898db129,7d2d8bf5,40f4b5a0,0c24e8a7) Z8(c32580ed,9dbea8d0,99057e43,af54a33a,8a049ad7,76ab19b5,a2439c63,f0b2f899) Z8(468cbe03,35af469e,41f8335c,8c164cfd,00e95f73,d3072c9e,b22f8a37,a2b745be) Z8(87846e40,10a79463,f9e4190d,02d196d3,feb3c960,847d82e5,c5019dc2,8d43e048) Z8(78de10ad,dc83fd38,43ec9c28,30170e16,0c539e65,dd793965,985d2375,0f58b6f0) Z8(f07c121c,1dd341d3,8baaf5a7,464bc351,7a4cdf97,9cba4e88,38d19f47,95c5b900) Z8(1a06bf4c,bad2a45e,35bde4ac,8e6941ca,c5499d8a,d47b0227,194d6579,39b6ea2c) Z8(9ba75f17,b2c0fa1b,17cb6891,e21f76a7,9c4d65d8,f8a427e4,9ba94020,93ebb975) Z8(17e2d921,41f6a291,75855735,5f172c57,27d4d614,42a0971b,0297fb8e,5b315551) Z8(d2862c2d,24e4c0a8,e575e389,2690ec07,95cb4f57,c6a3576f,ce6a51f0,d384c264) Z8(fab24def,7c4a7aa9,e9d3529b,de91c0ca,24e75625,5659d422,34f2001c,808b6d93) Z8(0d73c947,72ab9e48,83c0e9f3,de7b2ee4,aa7a61ec,4df3d374,e62428c0,a03795f4) Z8(f5c8525d,0f8e5a53,c1ace188,2a7633ee,474bbe68,d1e9e3a4,d9c9454a,dc506239) Z8(267301f4,58e7d5bc,64f6761b,420f2eec,4d7a6842,69678391,5c7fd885,72c23b20) Z8(f3ed34bc,77280380,64d2d641,eff69abc,ade9b6c8,3e93eade,00aaaaa9,ffffe000) },{ Z8(e8bc7449,34367665,ebda10af,96191907,9875c971,ef2a7d2b,351acf73,b6fd5957) Z8(19b803b8,4e9a9870,a20f171e,1169a751,9b1e71fe,d0d3bef0,6f13c4bc,89eea4c7) Z8(15642ea5,3006b1ba,b6208140,9a9ded53,f7707705,8a0239e3,274b1eca,144c5e4d) Z8(b9e7a938,dc62d5f6,1a2bd09e,d921ecd8,6aae1e27,8395b24c,702556f3,0c6ab967) Z8(02f78234,2a4ee510,ba43a9e9,87f35503,ff74887b,f9b47659,970b9c49,13934c77) Z8(5da154f0,f77cf547,fd728bc4,f17fb420,7e0d8454,9742d987,dee7e723,589a9502) Z8(daf3747e,f6baf4df,a22ff49c,2d18a868,c47ba0a3,0f8161c9,1cc1c763,28ddaf72) Z8(be93ec20,affb8983,e36c6d3f,432edef6,25b8e98f,94fae5af,b4762b7f,a1d9056c) Z8(0bce268f,3c3f55b5,bf638fb8,0bc79005,d24de3b6,bff33254,3f35ae1c,054132a9) Z8(e7c28112,f26a27b7,8bad5c45,6301bbfb,31300d05,be99abb8,cb844e6b,69cd2eb4) Z8(4c1f8ec4,48a6a8b1,a01c89a0,1c0596c4,78fabea0,fb1896f2,77fbe917,c28b4d79) Z8(da4deae0,f7a3a396,a9b6b7bb,f2120c7a,5210f19b,01f8fd5b,15350496,07a9cab5) Z8(56c219fc,0dffd9b3,5fdfe98a,9e9b1194,5e0fc10b,0d322877,f8792962,a5a8eeb8) Z8(5da52fa7,30192382,ece5fd02,203e7e65,d81a02e2,552ce3f8,2f50f2a9,5e80751c) Z8(d50126c7,063b8f01,3877db14,2b55b49d,f527a81c,7aae9902,acedf552,345f51e6) Z8(bae60ae9,af5c5c27,575d6bcd,3da8b2df,f66d310e,bf076ad4,9e1a0ee2,4264bfde) Z8(7506a5b5,3d438ab1,df9414bc,a27ac426,a558d4b5,b0522a7f,7edffaf3,86ef829a) Z8(4620ec5e,013de67f,54a8e0b4,92916d53,95f15a8a,97dd41d7,00008199,00bfffee) },{ Z8(0bc5789c,5a1c70a6,66ba25d1,904daae1,7f1af3a2,a6824c94,d2afc156,8ae0cd0f) Z8(aac25b86,99086514,251ff782,2b7e1c57,61c49cbe,4d221c93,b4e6654f,a38b68f0) Z8(40b0c40c,0c05714a,798d9ec9,da087e15,5fcb9076,36a6399c,83bab7ee,ef5a4a32) Z8(957473d8,9cd0c502,11b47c1c,6d9e130d,fdeacee1,49fd9107,930f3f9b,e88bbafb) Z8(a2b24e3b,35070a52,fe03b7f8,512ce54e,fee4e660,b857f05e,c5af1154,7ab958a5) Z8(f0b49864,10c2212c,1eb1d1bf,2edb32af,6c8e5eaf,d1cf2704,ac24b38c,3e36f38f) Z8(c1d7d826,a605af57,0923d3c2,4a63c25b,ac10735a,9cb1f4a7,d2367645,af9e81b5) Z8(7b7f9131,8f8c5083,1f384078,089fd245,5ee98bc7,7b7dacf9,d86f676e,7430ce5c) Z8(9e1b171a,4d87ad0c,f98c307d,f39ca5bc,646585f5,d5b62884,6878dc7e,0f2eaf89) Z8(631c8edf,87aba042,478d2633,42d2642d,fd54fce8,30bbe038,c3002e8d,80c390d7) Z8(678caf32,8c22e158,87780ba5,50220857,fcd87257,ccc4fd92,fda08a8a,8a2fb609) Z8(fe89755f,793938b1,040907bc,6e9c30fd,807d1412,3921c98c,afe37b21,c7025973) Z8(f27cea7b,8eeebaae,e07c2630,22bdfd0a,e883bb00,be0b324d,15065158,b5e54cc1) Z8(1669f01f,8a845674,16acdf97,d9876386,ee1948e4,9df1e68e,7d282342,92296d85) Z8(98b8bc07,1a7f19da,1f0a145b,0826e888,393468c0,09a6b316,70725193,c90eb4c9) Z8(99167b4c,c3e0d245,4b4df671,c1672008,b8175879,641b799a,6617b259,9d5dacda) Z8(b90824eb,0648d5e1,1c9a4ac9,58d7f79b,fd106c29,143f347b,667c4285,95152607) Z8(28d7483f,d9065bf8,8852eb83,9350fcfb,070dce43,ccccf675,035fffef,ffffb800) },{ Z8(d379d4f2,7d6ee2c3,60eba55f,3104dc97,a6f4f97d,b0479229,f4891e01,10afb56c) Z8(e84d11a6,e698b668,535042c2,d18db85f,e76557d2,9e3decb0,d507eae3,a9b06d81) Z8(fe4dbafb,18e4f25e,c9043d08,b08e918f,1874524b,fec3ff9b,743213b5,c0795288) Z8(d4edf2c6,29d573da,ec07d2a3,74503f45,f04e93cd,08ef672b,8afa93ef,469593df) Z8(1a3242b4,0caf6168,8993eb7a,afcfca79,cc207ad4,a0a623ee,66a718b5,0ac873c2) Z8(fc6d7172,f114bc29,c8fd84d2,129bdae2,84ecb14d,3c18b93f,a5847540,a92ae8b0) Z8(0ecc4391,33182948,aaab5a3d,e5a0f29c,4eeb0521,97cd2992,b5e4222c,01ce4397) Z8(f9fd5e02,84f2ab17,53a1d200,cd925400,ef81a2e7,665a1e61,0e944094,542b913b) Z8(ee90787f,e374acb7,556c4c8a,f5ff29a2,8cfb22c9,f93e7f02,c785ea9f,af0f6021) Z8(aa213678,d149325d,4bb225ee,fdfaedfa,80b09588,61b10d62,68a060a6,b16acee6) Z8(1523d2dd,9cfd9c2e,4e270948,bdf6a68b,6c64d15b,7a8f75fc,4ff8d59a,d16bb654) Z8(c339250a,e691ec0b,5b926a68,1836f3d6,502a3b12,7db020ca,87eac12f,ef1454a9) Z8(4f3b93f3,83d3f535,3a5a9abb,ef63b1e5,8156ab65,f02388cc,b6391642,d5024d2b) Z8(4357dd3a,c2726045,d4605fca,2482a424,6ae33f28,077c1143,b760a707,a48f16f6) Z8(aa4c4ff1,e6db3644,9a0d2450,8f3c8c64,4e330b9f,af5db8d3,f58638a7,70153c77) Z8(48927f69,4f111940,c1e8c4db,c18685a6,6f763f7b,49147aaf,887096d1,d2500397) Z8(c584231f,42c62544,77e886cc,aa20f9f8,fe4f25a3,210a5354,2c1d4109,1721956d) Z8(e9e36b4d,c4405259,25cbf0c7,20e25319,b26e498b,6a76a798,55577777,00ffffd5) },{ Z8(a525ce04,08dbedaf,7b19cb49,027b64f5,4ad6470e,10ad730e,10b1460b,3d79d8db) Z8(1ca3ded9,a32ab1b9,c1dd7af0,7c0095db,26957436,ad400174,3993ca07,9ac315c1) Z8(5d2ffde4,2c145796,adfec139,257e5769,2a1452ab,fbc877d5,4e6f985c,ecb350a1) Z8(a7753d8a,ba6004d1,41674415,d71a4d69,d2c7f624,39dcd12c,4cf5d32c,04e1c1a3) Z8(48e3bc31,365bf995,d92713a1,4d7a66cd,91c76350,d64d9c8c,e973a90b,cee0a81c) Z8(13f93c89,2806c058,753bf848,6ccd274b,f70d0f09,bfedeb00,1a5378ea,eee68cb5) Z8(263ab744,7df65926,92d4a774,d9962b8d,15252e81,bc703b0b,ccd8e799,0aba5c47) Z8(94bfd8c6,0fa99596,5eaaa6b5,89a98e5e,6363198d,c002e988,e324ca13,692cc3b0) Z8(0a7cac0d,2cf9d0ef,094500fe,5bf12978,89e1df2e,e34dcc45,548f6fe0,7b88ab57) Z8(8f03fa21,ff0ea778,8e1a7a90,e4a64d8c,e3aabc5d,bc1d47be,030649c1,de657ea2) Z8(80dee586,aa08cde3,61a16429,73dc8ff2,dba31915,17399dac,05a4633d,fcf0f5f3) Z8(645210a5,fe1b3491,e288cb86,1e199dff,1703d6bc,d7b5e9b4,c72e2804,8ff223d9) Z8(4940c14e,4b120363,2c59e6fd,5ed9e3c9,ea43d14b,5cff4bb0,bec28fa3,2847c865) Z8(66c24fa3,1937fad9,dd598e21,a658dce7,ed1a3db3,51a46b37,04442ac8,31f21f14) Z8(e6dfd030,a84d9527,85115961,5019c176,56e78761,72754e44,df033d10,5ac98331) Z8(d22d7675,241959a7,1fed516a,a7b6873c,11eaa8f7,31b8f827,4707f5a9,8e868251) Z8(0370b3ba,94cd273e,2b207969,23a42900,14c6dcb3,23a6dbba,dbd88646,159e76d5) Z8(c276c47f,596a5b46,b54082cd,09039032,f7502b17,a4fbefbe,0aaaaa4f,ffff8000) },{ Z8(f64071c4,f0a0c43c,d8a3095b,9ffc87e1,bfe3df20,4417fa07,ac8808f9,e4d1fd9b) Z8(43f01855,a00623ad,a4ce1a71,1ab486a2,5b0ebd1a,7ea12350,295d43c4,771cbdcd) Z8(4333ecd9,efdb8e71,d2a845c6,c80c9596,c4991018,48272b2d,be84ec65,d3ba08c7) Z8(5b80474b,00f9b332,fc114590,57cf0c0b,565416d7,f56df51c,358908c2,5ad18019) Z8(3108fbf8,e17631e1,f8abc148,1264a17f,cc928e94,a5239eb3,a88b6ef7,77f985c9) Z8(5d3cf27e,2bcaa535,f72ea91d,7a8d0e72,ba5e5977,8a5c3e3a,1c6f633c,6ee1bc11) Z8(332bd0af,a9c32ff9,08779cb3,19e4f65e,c2055e35,32247c0c,ee48cc95,3495a769) Z8(42948453,8c3f00e1,b162e1aa,e6ffa22d,a493655b,4c5620bc,1d191482,2a745fc0) Z8(a3f307a2,5a217707,a455a30b,34467846,f6ed0578,78df6580,14c861ef,66ed4972) Z8(9a50fc37,6d259d96,1414a7d0,07dff49f,3688afca,59f7b75f,c27d13ff,bf33c617) Z8(d5c6b032,dd708040,cd5eb750,3d358269,aef58500,821ede04,3924addc,e065564c) Z8(21cdc163,0d91ca74,7480c427,bb7ee402,93f534fc,df176a22,a3364e56,a78bae88) Z8(c8706c49,34f62b6d,558c65d0,fc19409a,5fba740d,60bc4391,d3bf9b34,46acc67a) Z8(77599852,f1660552,a273074f,a8fcb86e,dd2c0419,1348ef81,1df1c641,c9e68942) Z8(a7bbab4e,4394e6cb,acf22844,2a49a570,8e71a356,c5c5284f,ba946252,766cdf17) Z8(432fab46,3e36b556,ea4f7b31,de770bda,faeb8d38,8b26bf0e,d32b99c5,859a93b7) Z8(125a511a,5842cdd4,50c08d09,1fd44cdb,017988cc,b926bc56,39546916,d7b8adad) Z8(dee84423,fa9c2180,43d419ca,05db1128,8bb848ff,1754529d,aab12d55,013fffac) },{ Z8(5756052c,75a3f2f2,26d4f03a,dfca728f,7e0c17cf,22dfd54e,b1c170bb,9324e2c2) Z8(ffdb2be0,aa956b62,d756ec1b,45e55af1,ec668e71,d6dbffd6,a97aaa18,d11d3b48) Z8(ab246587,b3a6400b,a64f8e5e,b24b71ec,2c647631,fb24b0ea,b58b0970,907b95f7) Z8(a02f6bdd,62cc6e4d,67442729,ab05b82c,a12b5926,8de23522,3ff28ebf,4caf74d1) Z8(025104d2,52b553e2,971d4a4f,8463c8f9,6a7db9fd,a8af0cfb,355cd7a4,affab816) Z8(d448d550,d7420d29,df96cc07,cd1d98e9,157929b3,59f4f52a,94ae4867,4d52fc2f) Z8(02474219,dd9cc9fe,27622275,18b3e5cc,503aa5c6,7f6a45a0,e043e5d0,bc4b32bd) Z8(75286a9e,3d0b6151,ff5a06ca,eb4d3db7,6729550d,cdb3b3f8,9e01bb4b,a5a4292e) Z8(08524ea8,d1f82d12,e9ca6fd5,cba4f300,f0504cd6,7be01ae5,2be5ea02,f26347c9) Z8(01af1d0a,e36df157,148f45f0,565cff03,949abe11,d2fe8eee,ff6c2f03,a02e5802) Z8(77070c88,815ea76b,b0ea7723,6ec1d85e,6c79640c,80516311,fac74fb6,294f4bc3) Z8(6820174f,284193c8,5b6525ca,30c5af0c,aa5ac6bd,aedfdb8b,a4137c2e,472e8f75) Z8(685b8470,b3276149,6345a780,e433d122,ca601df9,c547e2e4,3e140632,7d1bdab6) Z8(f8945e60,1bcad5d8,10c09618,a26a91e8,ac0e2d51,71790e52,9f56735f,f0addd12) Z8(f6d59b5f,15309089,51f90843,f4b9c58a,9cdf8672,76e38b0a,f4abc527,feee42aa) Z8(1f512849,7a941c6c,c7eae2d6,e16aa754,9aee681e,20fd5789,0181b2b3,318d7eba) Z8(0ef67b12,4e80c212,42d9b12f,a3e23762,773f5771,b3cc1a58,8def3e63,8b910138) Z8(5214ad60,8ab14f18,4fb532d1,10b45ae7,3e97ad6f,71d0cc9a,1a0aa94f,ffff3800) },{ Z8(232a626d,4cd558bf,76207143,44336656,49a5be76,48c3d3a6,621a7bcb,f3e0d75a) Z8(ee2d24c6,12573c86,a3ec4f8f,14717de9,c2447f9c,ea510491,4dab1a74,82e20a0b) Z8(473c1059,39e751f6,4ea0741d,b404fcbd,f71cd4dc,dfbf01c7,0753c6db,f3861581) Z8(f178711d,1606f011,ca438d97,90c11ed8,922c428b,9a5da29e,00a70b70,65741054) Z8(1897754b,a658bb20,f693f3ac,bbfff017,a2e99fa1,d2f51956,9abfc86a,04912e56) Z8(f3ce2e6b,91b92900,e6a3697e,713045ce,a24939c0,2842e134,40ea622c,bfe3ee76) Z8(046a8a0a,fa45b598,c520c760,4ee576b0,1e9654d8,c505ee87,a2c296ad,1d287152) Z8(329d1467,90859b23,40433d43,95421bb4,fc7ef01b,71812973,e71a4f97,d46902f8) Z8(f86a6a62,7bc49420,7d23c2ae,67d5ecd5,3f8fad24,ed57598d,47cd45f7,4f4e30e6) Z8(e8f7791c,004f9710,09230d53,810b6c56,1cd5b089,9942e72f,3e14da32,e179c270) Z8(f3a51db1,51b169a6,c223af96,f0167f7e,51d3b53a,7968d89a,567e1b49,edfee7e2) Z8(d2e96aa4,445581a9,b342caa9,53bb086a,c038e4c0,adf699e5,4997a5c5,19217b6a) Z8(4073f9e0,9cb38572,a1e2681d,09e70f0f,44244408,b1d59ec1,5672e054,7712f066) Z8(86d5bce5,0f5d83d7,e55c9390,8fbc8c09,c1a82408,287cd351,99ed7fee,2f0ba84c) Z8(72c0de87,ee984624,cfe1af3a,43e36b6b,fc16dc7d,f2b33199,38ac5f6b,13dde9a0) Z8(1c11a950,ab2081f1,cbf4ddad,a99ea124,3465404c,af5e49f4,9e4fdb17,d7a74e20) Z8(b043a53b,17790849,9d116d28,47edff7e,033642c7,a9918844,388208a5,dc1e8c07) Z8(261cd2c4,1ada463c,cd22603e,5dce95a7,66420b70,55075766,00103332,017fff70) },{ Z8(082152f2,f124b328,37cc9579,6402be16,af9108eb,3c92c67f,0bfba1d0,a9857c05) Z8(6c683009,dc0c90cb,f8564503,bf3a99d2,463100d3,85b91e69,82845746,e5b71a61) Z8(00bc1abb,e605c6a3,63cb693c,c008b71f,b753973d,b39a3b21,eeab71eb,d256683d) Z8(056ec108,630a41e4,657fc44f,f8fdbd52,b896f171,ea866a93,d09de235,bebc22f4) Z8(36c982fa,3fa5976a,7abbd985,3533e70f,18cfa583,1aa5c634,78866af6,a32675e7) Z8(52ac2488,a6bf856a,bf014bf5,d917aa99,8ed576d3,cefb2662,70e6ac01,4c581849) Z8(23abb1a6,80474d94,f9724d6d,c8fa00e9,899ee827,1a323aab,c08d84ac,6571e8bb) Z8(ffc0854b,c123f850,c356687c,6fcaa0c8,5e7f7350,a129c4af,4a3d6d91,e7661631) Z8(320b1360,4f1f1dc4,3db33895,b5dc6d24,37fe0c43,c3658b1a,071a81c2,a885a09e) Z8(d7e0d5db,1e3ef422,24fd103f,4894de7b,2436bde4,ddf38491,34985b16,a03278a0) Z8(75a4705d,01340079,b5ca2aef,95137dbc,c819de09,886fa9d6,8f9b2b57,6b7055e2) Z8(a06e437d,9c73931c,1eed0945,e8547e08,3f3d86e8,fd5e83b4,6ca506ca,d1dfbecb) Z8(743bc06e,fc8bbcb4,4c044622,e716ce1b,e59d5262,0bfe2bf1,cf992f40,be1d13b2) Z8(10afb7f8,138d12e8,ab38affb,4ea90d57,b8a221d3,c0f6f9b7,40af79ce,0da5d81f) Z8(3d9d121a,a26b162e,1b87118d,c42be599,6bcd34d8,d8509af2,71bc9fba,6a8c3fc2) Z8(c0495f54,844c1fa7,988f53b0,0990f69c,f35558ff,c7f974fd,f553bca4,5ffb9a6b) Z8(329f19eb,d414ca2d,c79d7592,55b268d4,5d890db4,dc27a47c,75957223,7304ce77) Z8(10c9ceaf,10be56b2,2b576bab,d2544b46,ac40622a,335cdb6c,35fffbf3,fffee000) },{ Z8(02c3d20f,c03368e9,e9f26b33,524a0b96,9b559b2d,0a60607f,09445e76,b810a8d6) Z8(24269b85,313c8e02,dae8fdae,1b949d75,3b62c25d,8be8fce5,feeb95b8,155e5cb3) Z8(c87df239,27035eca,2941c7de,4277fefc,f399d9bc,abc79b1a,1986c75f,d7a2865b) Z8(3a7a73d1,40ace5b8,a8717906,84dbb10c,7753db2e,d38a042b,9a34ad12,3b23f1a4) Z8(80e4e7a7,4924366e,ba07e434,bd98cf90,9259368e,ce3a6db4,b3e56529,0f38848f) Z8(a546bca2,d6235d32,78c82337,105f1536,6f924271,a6494fc4,5d36934d,5b4bdfe5) Z8(e1485bae,247ecbe6,25006f82,ce407ac8,74677f46,1a367366,03185419,7676dd58) Z8(054e6a5a,864361d5,413f0bdd,04b55bdd,30e0b415,8435f41a,35bbfe37,9e00711e) Z8(0ca2ec29,db5fc360,7ddcb601,5227dd49,06c7531c,17cc0bd3,f92d7d72,09595c58) Z8(ced7dcfa,de451a88,90dffbb9,dc4760d0,24eee049,229891b8,8ebc51c6,adfc25d4) Z8(edb7b0cb,695cdd11,77463eb2,503d9e37,b7939c0b,535a2c4c,1701b26a,7c629ff3) Z8(c27dd8db,442387fb,482fc1f3,1b07b873,9353f95f,3e819f0e,536d8483,c318634a) Z8(94c9d54e,b4a7129c,806e87bc,26312074,48311e73,d7f1d98f,446d524e,1a64c26f) Z8(7014e478,77fa8d19,3619af74,6d4801dc,329f36bd,894f2ee0,63791dff,948687ea) Z8(03f0935e,7d16bb46,133df952,9d434b28,2e1a4f2d,03042a79,f01f7d67,fed188e5) Z8(2d17756f,4507ec8d,fe5cc22b,707fb5ab,16c856ea,f84ed1fd,22a6ae2a,dbf302cc) Z8(699bee4f,bc0d65a8,85288d08,38808b11,42c6361e,a1c4364d,1ecb2235,71d0a04e) Z8(46fdd0b1,844616e6,2e6d9544,e143bd1f,bf1166a2,8376272d,5578590e,01bfff1b) },{ Z8(f92efe58,378808f4,cb206f95,513fe000,61f9d569,2a34c401,64ecb7f3,5e023fac) Z8(b38476a5,0bcea69e,6b3df89c,f7cfba00,1df0957b,722dc3da,373ca8d4,339c94cf) Z8(262dba48,ad755bf9,33ae1ee1,721c58c9,7699dc8b,d13e2293,2e58c13a,4dacb89f) Z8(d618d3f1,f4afb85c,863e9414,443af678,47431141,3fc9d9b8,0ce23d27,f10a21cd) Z8(bdfe5e80,62315411,0851f31f,d1ac14f6,5c7c48f4,491f119d,904262ae,5e932c40) Z8(149a3a1a,a5fba725,c6ceef50,83238367,752a4e5a,6a5d1c13,3f016171,5c9768cc) Z8(fe3a345b,cd29f12e,3ded0a00,e371c7fd,3be181ab,2db115ae,6ad26b3b,1e7b878d) Z8(5c76d99d,5d80e64c,12c28cfe,e0571af1,b6229bc8,6a7bfdba,12c43a57,47d5b013) Z8(c119994f,2f237d6a,1885e361,e1e243a2,c6731a23,d33cb518,579eb744,526f0b63) Z8(848fea1c,eb4d0aa8,6568f941,5cf94eb5,da12e0f5,e9c1a6dd,bb52f4d3,6300ad02) Z8(cff4aa3e,725b6e29,728a3815,eb7a9e59,0d7d965b,c51da7d5,1c21d405,07428f71) Z8(717af0bf,cab2c4aa,4826a3cc,79a275ff,64377101,04cbbb88,7c5d7d08,ffbb33f2) Z8(6491a473,8ba62d92,e38fb8d3,b9d3bff1,9930e761,c40af9a5,ca0f2ca4,21d04cd3) Z8(f9647862,b147cfa0,cdb7c13c,362ef02b,118ce664,8a24f786,2b463108,e94e532c) Z8(cf301f12,fc22d8b5,b3b4dfdd,451d1712,8558bc0a,52960c6a,c5c6a6ec,6b0993dc) Z8(ea16a65b,984f83b8,6a0da499,45420df1,c886d048,6cd94b22,37b3fb2d,6cc4eca0) Z8(e7af2e86,89408458,554aa371,554d9abd,b90ff68b,bc39bb85,d6645e39,b127519b) Z8(eaabb869,18a31f6b,4ea4cc5b,5f180396,f501f430,3f22e322,640aa074,fffe7800) },{ Z8(545cfd07,ad7d5717,d74f0705,0012c733,a9ed1c1a,6d93163f,ed6439ed,66b501fc) Z8(96f38c4d,94a7dfce,f551a5e9,469d8489,452e2a6e,72664405,804171f1,7ee56d9c) Z8(737ffe70,5f3b3267,f9f45d9b,de1383d4,c6119b79,fc85daff,1c1d7f5b,2d844df0) Z8(acfd9949,1bd7c22a,eadb229c,db37a93c,1b57ab4d,7ec06836,630ca3cf,8e4e12b2) Z8(a0e522a7,a54e1bac,34f00b41,9792a4e0,ecd8a32f,a289584c,24a7a596,207a81a8) Z8(552175c2,25f4db17,b1d1121f,634066c0,73e26f5f,46637f8e,393a8c4d,f3ca3226) Z8(cad2a87f,8e845b84,36cec214,f6b1e7b5,f0245e0e,92d3943b,b3af407f,96884269) Z8(5eef30b3,9050fd38,773fb35a,70368973,51051fb6,a454a0fb,338d0858,1d3cbd11) Z8(0b0be3cc,db3b46a0,e7995861,10d2c431,ffaf3f20,ca18b0a5,6d1b8e36,af496798) Z8(5bf414a8,67244c2f,e0b0d221,b82bc6df,4f1f700e,b9147a66,9da4aff3,20716fd8) Z8(802a8370,5b14e5ff,d226596f,6cf2287b,ba60c77c,7c842b74,53d0062e,915751ce) Z8(b0802db4,0f9b631b,7155abe0,d2221277,8e2a49d3,9dd716cb,ee280b28,cb03117b) Z8(76e87acf,82931842,1e7d1d6f,0887bba0,fcd2ad3d,cc265048,de755943,f43855e1) Z8(01157bdc,8ab11029,b8509572,af3dbcc3,1071f7d2,41a3d980,6abf31d5,ee2e1e4d) Z8(dfbb1d0b,b28082fc,4d073bc2,e4e8edfd,23819b74,17fbb57a,af54a128,50ae742a) Z8(12fdedf7,61b22f48,a74a13bd,f005279c,e3cbad08,4a92af3b,1fef377a,a6729aec) Z8(caec7acc,0d534b7e,4ae2e1bb,d3da4dc1,c8be6a05,16fa88a2,4353efc3,20596653) Z8(cd9c4aa4,943448d9,32d90612,ca4a3d86,1221010c,6e8744e6,aaeeeee8,01fffeaa) },{ Z8(8286027b,43591dee,a466a739,e62478db,2d12077b,5b804346,1a77b88e,c9d88679) Z8(1c875f92,ee57e63d,e9b381b3,ca2daa68,21b72ef9,4f3bce41,9576f802,ace21709) Z8(73983318,33e37d82,761bff86,f16e2141,78fa2609,23874bb0,6014f8c1,ae6f8d95) Z8(ff539bfe,13fc458f,e12f0c6a,da680d15,20566eef,00e3dd9f,21f65cae,15d3dcbf) Z8(a4ca3235,3728e64e,f716c9b8,16b6cdba,ec6b2180,79ed0e85,0f938b84,27e7488f) Z8(12fa2ed0,165d9c39,7505f1b6,ae33c68a,9ea210c3,3de450be,db6672a5,c691e7aa) Z8(9830b290,f7f0fc2d,83ef96ad,e473ce89,2ede69f4,05a0bbae,758e40be,c06e3779) Z8(82ae0687,19d4795a,13900a74,b50bb030,2664a59d,f0a1bf37,6530f034,28288266) Z8(1b9b1571,1aababd6,70be3e9b,d64afaed,dd01d0f5,c3544d0c,0ce2c7c2,071661db) Z8(152fd4e0,4d89dc36,5a8a81d1,1fe8d0c0,bb5f87df,6afa7c54,cf0ae0d8,ebf3b9f0) Z8(81fb5cf1,8394a9d3,7e019805,5866db93,da442bc0,ba9040d5,c92e509e,1d55aa76) Z8(56d56619,58ca6650,e27b9e67,3e8b73c2,44db0536,67b3d9d1,59661a9c,0fa16e05) Z8(9c5ac6dc,2d404b42,f9bfa633,41c6af2c,bea5de95,fd202894,f15c7807,4fb2faf9) Z8(e144ebe3,2369b26d,2b669b84,488e296e,87ef51de,a4f40ae6,b2494e0d,1040176a) Z8(a0b31f2e,71f77c88,716026cd,4d7b2ae6,7e9e552b,7bda8ff9,e8422429,20786d50) Z8(16a5888d,abe60530,1d59257a,eb039e71,505a0c52,f63db1c1,ed70d326,8af90516) Z8(e7c976ee,c55d8730,f47670bb,d4ba6011,ffc81fb4,d9fe3873,c6c9dd2e,f9b9ba8e) Z8(4c4ab792,64b0f827,585b1e5f,283c5951,b5b41832,4034032d,aaaa93e9,fffe0000) },{ Z8(90250f5d,23ec91b1,bb68e5cc,89c11ada,3d8110cd,914d2439,d356b0a7,03bb1338) Z8(988d2fbb,cee45916,9dc84098,26cad172,1d42ecc1,21a496ad,43e7449d,2e26f621) Z8(39043953,d58bf1c3,fba54cad,1084e762,bacfe77d,5d2d842c,9674a719,7a50d7b3) Z8(37be3faf,b6f2ec29,e2cd04fc,f052ab80,69c7f710,c06a50d9,c252eadf,8a7729f0) Z8(e1f27a33,3fda4500,6af464b2,5f2fd915,f67b2145,c73727df,5dbb52a8,139b9222) Z8(0ca90d83,3945f43a,7392efcb,358b5875,d3e29595,2647f000,73a763a1,5d2e4fde) Z8(30c78c11,0027e8fe,d12be9c2,2bc729b4,88fe4593,664318dc,d3ed58f2,12ef72f3) Z8(30614753,91aec3af,d22d6c8c,e079f995,440663d1,68d443b6,91c4d17e,f9dfdf09) Z8(ccd1e8bc,b0b61e8c,fd7ca987,d8c433c1,48527cab,3a45823d,e79bcf80,42e97a61) Z8(8961ea07,ccd8be95,fb6f3296,f1a344c9,972a4a91,37353337,5ce18229,3191086c) Z8(ca198ea1,990374c5,b469d782,f43fddbb,d50440af,fa77242b,57e36b38,09595be7) Z8(c324ac0c,7ac824a2,0303554e,6c6d03df,efd66b4e,44fbdaca,088c8eed,e6e98617) Z8(4912b8f3,2d2f7089,acd36367,2eeb1b2d,e9edf732,efc0d5c0,56ec6215,df6ae696) Z8(3d3c47a4,339e3013,a6ef22e3,75d444f5,98a53abc,297e0e0d,1744fa55,95aed54c) Z8(75684159,d6af7eab,6ae5794e,18f264eb,4307fdc6,95c6b216,2cc6afe6,6bd7d24d) Z8(05a12ac9,bd250e8c,d4bfe93a,1e2c6753,42d073e9,764c1eec,8e27e09c,6e5386af) Z8(e578aad9,3b13c6d2,d1084a64,1a93cb56,9e3ef262,ea367b7b,87717a77,964117c6) Z8(bc105d91,18faa193,4c2def14,86f6b553,9f9a18fb,f8cc0397,007b04bd,023ffe1a) },{ Z8(1bb23550,663a3e0d,8e3c8b34,c48e6b40,e67ef873,dde3afc0,3d8a4fff,bad424ff) Z8(18c9da12,985e8d2a,a8d0c40d,80543cd8,71180e37,972acf9d,b98667dc,69b8e6be) Z8(ebde9e4d,bcaa7acf,57cda2d9,b7aecddc,2634de22,31d78b40,819a1ba0,90500b6d) Z8(07fb783e,0c1bd96b,a26f2b6a,7f8dbd9b,45fc29c2,4dd743f1,afc0967e,21fd4b60) Z8(46bb0e75,d4dfea42,35ee0acd,561fe7cc,4d932704,3b3171d7,e48881b7,ebdd58ee) Z8(5754a6a9,d55e7014,a130cebc,ee7b9b24,f25dce45,60665156,bad7caeb,2627e8a3) Z8(cb4634d5,48b5b977,0469b2c7,20e1c2f3,e55fbd96,aed347c6,f7bfa178,292cd689) Z8(8cb7fc18,f09d7aa9,dff2da23,bd1a5ada,82370275,bf67e901,c87508eb,58fcca61) Z8(bc96a04d,fc3b156d,558781fd,0b2002c8,8c6d47d9,4aa0397f,bd870ab2,d64fc0b0) Z8(fadf9592,3c7815da,9d3be168,1df69f0f,9131d2d8,4c3af0b2,c59ac2a8,df2dcfe7) Z8(50214c4e,21a5f50c,a9bdfcf9,f79fae9c,4fef59d1,422b9091,04b466d2,76b48fb9) Z8(7510f84d,3f99868a,cb16272a,140602d0,676e1357,1426c171,2a047834,e626c6e3) Z8(796ea514,1513fa43,d2de1517,184b5dfa,5464347d,ced3d216,982eec43,50c711bb) Z8(cae2bb62,9a08b0a5,bf47069c,5c9722be,e1d6125f,33a6e570,70d4b9c3,a08ed967) Z8(e7f3aa09,6e1c4bf1,ac0e2f19,e016d1a2,86216d11,b4a32875,bcf43b3b,a2212c26) Z8(564c7594,284d1e73,4fff8caf,ecd19f13,715430cd,cffc24eb,bead3165,70f8f11b) Z8(a02853bb,1bb73131,c5eb8ca4,20115c1b,edcbfd44,52855122,a43d1beb,95072824) Z8(f243d541,b227a130,ab634ff1,b8825f6b,cd9bcfd0,375ed37a,115fd1de,fffd7801) },{ Z8(c88cc59b,53802b1a,d9fe8118,f84c3957,8fcac84c,21a774a9,36adaed3,404d13ac) Z8(ee2a70a8,b6dd6d3f,e1312af9,574bf723,2ea63a0b,c0e6402e,59780871,7b4918df) Z8(85f885bc,5322a29c,3867f11b,3c17d568,64e47e9b,868965da,e1e1ae2e,9a871d09) Z8(9bed1e06,08b906a1,21843546,09eb639d,41128863,7a5dfe57,a1e448cd,bb0970b5) Z8(3db9e22a,d5ff3d54,894f15fb,0b9dc833,262f1200,2fb18db5,d87a415d,6412b1b4) Z8(e2f69b6f,b314fb51,f20b0b8b,d1d84710,0b9abed0,8790416d,7b7d8d42,d248509b) Z8(ca7c37dc,48fef532,f6fae069,5786dfbf,7724db3c,34255f58,1b338f2f,c4d411e3) Z8(a93f3e08,fb8498df,65639fd1,ceae5bee,e8067688,648a476d,d7a79848,70f614df) Z8(fc1848be,bf9efc5f,61656113,ec0b65b8,81c4d0ea,383bc3e9,a024f0eb,3d8506fa) Z8(0ca33dda,eb8ae2eb,8793ae34,c10723af,ba3aaac2,d71e827d,857b0e06,9667b645) Z8(5a567d40,2a08df35,10c18f2b,9af303d2,f2051e3c,e80a4a49,066f0402,4d2470ab) Z8(fb62fd28,6c13f2e2,0a57c482,056fbe03,ed193490,df6b0fb6,cac03911,6324b30b) Z8(c4168ebb,73d22bce,c792aeab,4419cc88,19553404,3723093e,98f6cfe0,ae956c45) Z8(d22cb086,dfca4b65,c7cef277,44a82f9d,5093d5cb,ed043847,ede22b4f,4a3579b9) Z8(3e12e212,23d772df,fdf8dac5,e3d0a9e7,9bdd489e,568fde0a,b1a0afa3,16e919f5) Z8(dc78baf6,f4b66cdd,282ad066,1d9df975,4f3584b9,e724aefd,2d69005b,a40b4031) Z8(8105582d,4d31c6a6,8f109482,448fccb1,6806445c,3f900b82,ce7d6682,294d3f75) Z8(a9f61923,9d167011,a5592d84,a5578bdd,d94ebf1d,aa2b5378,5625aa8b,027ffd65) },{ Z8(994d7baf,723e593d,34a60c3e,5fb64e41,42f115da,0cd86857,d50f9278,16c27d5e) Z8(f9a1d2ae,b8d57e99,7fd190fa,fd20448d,42c09c2c,b36fa204,518b6690,c4f41d54) Z8(465199b9,d3dd65d4,97781b16,7040257a,a814192b,47f219a8,4a89960c,0e80d426) Z8(46b66c7b,3daf7f36,ef09458e,e75b9383,c2d31447,468a4d1e,d4f6dfc1,3c5ab168) Z8(9dfbb738,e8c78aff,6ff75d20,1c7a6c1c,b3e5dfa5,ccf889a0,123e7962,f89f9ae7) Z8(40120079,717057cc,97336e1e,82b4c77f,e309cbf5,1196543e,2c266422,7ff44402) Z8(79aa395e,e50839b3,cb83585e,0bbcb52c,27f2ec47,b828e04d,d3647dc8,d9f18080) Z8(83ba983d,2c7991c1,3da38a8a,c89e538a,e83f8e6d,3686aaee,cca1a60e,97e0e0da) Z8(49b96242,b2a8940c,2d842951,8c6722e3,b197fb44,cb6c7511,fe9e15a6,ca8924a1) Z8(15be094e,75d0e53e,f210e6dd,fe45a431,fb3edb64,c8891fb2,64c1dd5f,cf436887) Z8(0cc36b47,2b8b89f9,02f21ec3,3e7a95c9,b014bed4,64d9feda,2830d8fd,65b405a3) Z8(322a9c6e,cff3201b,46764c31,3feede35,54852f8c,09826aa1,07ba7967,2b975841) Z8(92945fdd,06e29494,dea20078,4693b04a,b3d0563f,60c4d65b,2d275066,417fb81f) Z8(e9a73212,088973ec,3846a570,99d296bc,cdbc2363,99e02a30,7cc6db9c,369b8365) Z8(8a75e958,cfe1f257,45633481,73b893a8,8dbf1c2a,c9ffd0f9,b91a7182,481e19df) Z8(d2ffba6d,37a5e685,930f670f,99cf43cf,fda9a04f,58bdd1c8,de842efd,c4db3281) Z8(09128fe3,e02e79ab,6af78705,05df117e,de2e68f5,e4dd5f4a,e536f810,c4e4019a) Z8(c18c3620,ee0336d3,36f4cd0e,2595971a,159747bb,7b774468,a0aa53dc,fffce001) },{ Z8(d1fc94bf,e77f7b4c,17282c71,3fd487c5,8b706f7b,ccb2e605,61902f2b,ad02be4d) Z8(4719d832,a68f2c8c,20d65ea1,156f2c50,731f2a85,ede6ac0f,50f41611,1eb1f0d4) Z8(234975ef,d4f65410,d0e7b671,e73bb192,6e59a8d8,ac419fa2,9857c73b,966d9f45) Z8(ca8a6b5e,33c8b7d4,91bfad59,3b42c72a,bc823cc1,b0c46934,c72f7ac7,927dec4a) Z8(54ea2524,5ebb92cd,6991c173,a668a412,d6fbde77,3c0fd53a,a19fca95,7d25cff7) Z8(5ecb0e93,3708b26c,6a4a752f,86959de9,d7c4fca6,ea837f7a,09abe724,aaaafff2) Z8(186d3a32,0601727d,b4b02e6e,b15f319e,bf8784c5,4ff419cf,36bd7b0e,b6b0f503) Z8(21f93736,7fa05120,e55d9125,5442ed90,64bdfb8a,2d1436ea,60d010d8,a375fce5) Z8(e5128f75,cface491,c32cf755,8b7b1134,1c568ff5,97f6e9bc,6050f547,f376f7ae) Z8(dc78aead,bece546b,29c006b4,dcfb75b0,268a3350,1c74f021,d84b1049,c3016e85) Z8(cd2c195a,0fab52c4,9aed5bcd,997656f9,ae3af6f1,a73356a0,3f6ae5be,0071776a) Z8(48077c64,ff46ac4f,65dc3330,c7e9e437,a2a2e2b4,c2b805d2,8f18dacf,c9673501) Z8(fee00f1b,73d5ff7b,759c495b,349ae274,3c9e4d60,74d905aa,242eec0f,2c6810a3) Z8(b12e14ff,32a6af7c,458bf74c,6dda1e41,e7902431,394aeedb,00f24247,66de7e54) Z8(b46d0724,0a714de0,39f1c0d2,e1e75217,7819d7f2,645f36e3,c3d81e09,5d66dccc) Z8(89586805,89199e65,64971cc0,f1d106e5,ef44561a,81ff772c,d944dad1,6b6273fb) Z8(761f51a6,1c5c654a,d31ef08b,dd18b4b3,659345fb,396cbc4d,aa5bbdf9,abc29929) Z8(96bc6f82,165b3967,9a8412cc,441feac6,20eede53,1e8ca4dc,abfa304c,02bffc88) },{ Z8(a1ac661a,582a5b87,8df6520f,bf319cfc,63202431,894908ad,6c6293d3,0d267264) Z8(909b4f81,95afeb36,60edbdc5,9a2c59c5,9cd18ea7,896ea1bb,9be4473e,dba93582) Z8(2e2c587b,8113d321,9f21e319,e279dc6a,1ff02649,3969c431,a89240b2,8e12146b) Z8(2649d160,df95f683,f8ae5a24,737e5fe6,cb12f6e6,6d8ccdeb,dcdf6aec,9a1796aa) Z8(7c839764,f965d05c,880fd111,2b3c1181,97e7507a,9de0285c,c601632b,29aa7363) Z8(91395c3a,562d134d,81b0c7da,8a4eabe2,ccdb4ffa,188daa07,dc0fc93c,bc59496d) Z8(37a02b3c,85b6e3f1,03e5bad1,d5c8c2ae,9af8a84d,da472ab1,61971f26,67e04dee) Z8(4f48e780,768c6abd,c1ba3e89,88b1269f,b0ae77b3,85315236,b939f6b3,b91115ea) Z8(377e657e,202428ac,2566b22f,8cb30bde,2d133b25,fb2c7ed3,83e7e502,033cddba) Z8(0242486f,0befd950,90307a02,d509134d,34c013d0,69c1a99b,6eb69fd9,6d2680ca) Z8(e352f71d,d86f86c9,3c531748,1725f341,0e78e12d,88a1dc76,1b8f4074,35775be5) Z8(e710622f,d2ac0c58,9ee08dde,576e7b44,9244232a,b8bb6172,540f9521,72cb2cbb) Z8(6da98d30,8e2e768d,7f97ffc3,ac0cee93,35f4a305,b6d7627c,7931a017,d96aa031) Z8(40fe06e3,3e6dd8f6,07c050fa,8b0ce813,1fffd904,53e1bd5d,96f21b94,fef85a4b) Z8(2337aed5,b15d16ac,a09cd9c5,f5ba20ce,a3605d4e,06553e85,31b2a6c7,2b1ddd72) Z8(49292ac8,2e62a716,7b516267,d3fabb43,ff403ced,d7644899,5c0f345f,bed7167d) Z8(1c0495f3,d2af538b,290e7012,a8ae1b50,14664149,84c797cd,9f83f688,03ca8400) Z8(20f1480d,ebbc1abc,b32acbe5,2506505a,ec292b5e,b9bebeaa,620a10e2,fffc3802) },{ Z8(acf6b7eb,999596e4,bc5ef240,5fc26fc2,57dde96c,788f77cf,951461fb,02633677) Z8(2d9894bf,54c4d380,a084e882,9c9ad42a,123deb65,9d48f3f8,b6f3cf56,b503c507) Z8(5f5ea4f2,cee88ae4,2dcdf172,36bc211b,37f01699,f23c0945,02ee38d5,0495a158) Z8(a035e435,1f6c8e4a,e39fef4c,cc2468d9,4bcb73f4,7eb7f141,1e66e9ef,9565d579) Z8(32589ea0,aa40e404,641ed9ed,e04c571a,9dfb9cca,b2be4565,c1a10165,dfdb65b6) Z8(33e1a5b7,214fe8b6,8d4a126d,41ee5c78,24b7502f,8d09df06,0722d3e7,4d35d1ca) Z8(cd4fb7d9,1d9b7ca7,a9d0bf96,68cea71b,edd576ca,d8b0cf60,50038a0a,201cd019) Z8(5e1f44e6,f1454106,0a6d263c,044ae11c,07f04545,92245c0d,7c272d10,b7026216) Z8(0b06d037,8616eb59,84069f95,bcd68a4e,7c1d6369,119d18c6,79db1437,4d1f018c) Z8(8990e03d,6228a4d8,c557c11d,a6090c6c,a00247dd,77c0d023,e46663bf,9b01fcee) Z8(98e07f5a,3a06e825,bf677586,1b13df5a,59ba4239,949435b7,656b3614,fb867579) Z8(c258ea25,9e99b188,e36a0ef5,d79da795,15f82002,abedd9a8,73ac6edf,977c7b2a) Z8(6e9a3f60,c93c6a45,2b7a9306,406946fd,89fc4aca,9084f825,8db8ffe7,66df2202) Z8(d4606ada,451bd100,e4ae9eeb,7af3164f,fdd08b64,3312a994,55b28246,e0293e70) Z8(51330db3,e11e2b4c,d7751eda,5c238f6e,4074fdcb,f016448d,4b9df823,96aa0be6) Z8(b671f7d8,5feb5edb,0872d38c,fd684545,1c96a055,be571eee,8e1f2800,3b0183f2) Z8(8fdee34a,3fc81c11,4ce297c3,b59ee6f6,fb0e8d78,082af7b6,821e7854,3584d0b3) Z8(11de693e,b5ab634a,85d81bd2,cef9d52c,7e126af1,5082ea0d,020665f7,02fffb80) },{ Z8(c1518066,f10bb1e1,21698944,77dcbd57,d74e2d91,6940b757,5ea26f21,854b343c) Z8(53ee7043,0b3af485,9078436f,63a670c5,148047fb,564f6c5b,f54540bf,3ab95d26) Z8(f8a1bdb7,56ec684f,0c7cd0f3,299eb14b,1e995a49,dd9a6bf1,fc0d3a94,479fb7a3) Z8(78fe09fc,42973ab2,ae70344d,952cca3e,d7ab21a9,3fd1992d,210bb4c6,38e4c0f0) Z8(365f15ee,e1b59a99,df751d88,1d3cea30,5f7ccfd0,2b898ef8,1bfcac92,90b2f031) Z8(37316039,9319211c,e79d001a,93d27ac8,ca2c1e34,e0881f93,ce461204,be891045) Z8(33edb83b,f3cd3c83,f831614b,cc4a02b4,f2c9895c,9acab1df,20aa4722,ee322dae) Z8(181c8a26,a608b5d4,9b0e2919,3be2d26f,66482e66,521b01b3,6d76f662,b5d2bce3) Z8(96c1f03a,5abf2743,8678383a,0511d802,2ad1be28,b9f7f270,65084a45,ff07f72f) Z8(2d7b282e,4277c133,f969b89a,5e9889c2,ce4c64de,06892b3b,cf3763f9,c2e84afb) Z8(47308cfa,1e3742c4,34154a54,c607c3a8,f206d940,48eaea98,36d38a30,f49a3d0e) Z8(a24cbe32,da12cc06,68fe87ac,2cc5c1d8,0be0f2ef,868d3926,a76ce7c5,d265911d) Z8(4efb6e76,a4c00293,dd0030c4,8475b8a4,68d28e1d,3e106491,ee11f0d2,70bfe8b0) Z8(3cf46008,6e79d0fc,18fcb347,29e7e7bc,86cce2a1,9217e42a,141dac37,8eaab723) Z8(52f4d9b6,70cb6f73,a2ef2362,9cce9b5e,90df7f10,87443cba,6881a82f,f8e5193b) Z8(449aa2d5,52f8edaa,fcd16fb6,049e2201,746840c5,2af2df70,314226f0,b4eb930f) Z8(a40379e7,ad1cfcf5,b7ac5136,6de072e9,f4ad5f6b,18c2a1eb,3c74e210,4a1df9d1) Z8(d94391b8,36bc82aa,f68391c5,18efb2d1,090fa8bf,f6750326,5ffefccc,fffb8003) },{ Z8(f6a525f7,7979c8c1,1598b577,e7ca3074,f869958f,d071a389,44a48b63,54c8bca8) Z8(da6a87ff,72dee4e3,1262017a,dd32d409,db84dfd4,5b35bb7a,e8c80923,a638e7b4) Z8(b3233e84,28bae309,362ffb05,ad14d198,d1d6aa11,fd5115b0,998827f1,3bcc1db6) Z8(7bcfe3a4,d582f572,72846d8c,74e42431,6230375d,0ad05962,af48bfe3,9f8908b1) Z8(7f452f62,02ead4dd,4f0808cc,b4e57690,6807fdd9,f9a03b0e,4212ca7b,e1b3bbc4) Z8(edd7063e,5d1c7d29,1a20703b,70a5110f,88c1ee61,da59ca77,60c461d1,f17ce4e1) Z8(075febe1,b19e7120,950cd42e,b7580770,3c7dded6,6026c57d,8db4f0ec,58518717) Z8(232a487d,a6fe0f8b,a922f565,e1a36d4e,6a23ae27,22474d9e,d66095ab,042a6966) Z8(81e099c5,c566634f,6a48f063,b59c1105,32e56e9b,d8518f4d,5b32aba6,95aaf33e) Z8(863e438d,3fbd83ba,4aa3d220,6a4b8905,5c752ca2,43f6380e,f3386ad2,0e009149) Z8(f7b52ebf,01511c4f,214f2691,bb743837,e852a6f9,33b713e2,269a9829,a714bdd1) Z8(b119ff92,392763c3,31d94d23,40a27034,7d6bae67,c4d8ccfd,39f62582,449861b7) Z8(c2f19edf,d34a27ed,4939c83a,52bde187,185c5d34,4c1fff9b,c8406421,c35da683) Z8(464a431e,e9c2bf38,d20e6f1a,56dd6087,3cb5840c,38257026,60d66f52,913ec194) Z8(dc9c4f95,22ec2bd3,f9f5fdd8,b88b261f,0e6b8f39,1880c8f2,4e34f3a6,edae1d7d) Z8(f89a64a6,b74c23d7,3c291af1,850f1327,fffc9fb1,820e7741,6229d77a,f3efca2f) Z8(2f9b12bc,7a302ed3,624c1cda,9414b2a3,9705c9a1,84a5eeb2,ae61a891,75e8913c) Z8(33b08063,033c308d,ccabf770,109216aa,f141142d,bbf7c37a,585adb81,033ffa47) },{ Z8(e17368eb,28c437a6,07e07d96,5966cc13,b564b409,1c7586bc,e63a5175,8abb16fa) Z8(21e30419,7348e11e,b9bd4e1c,4155c2ea,ffab15cd,ca2cbab0,c750cb5a,973c8d33) Z8(5884ab60,79c4479d,a9c2db34,f65d1e87,5450c02c,efdb12b8,57273bc2,ae554884) Z8(566fab78,405afbcc,e4c9ad26,0c3bb3e5,f9fd7e11,16f12684,b1fe2da1,60d5a54b) Z8(28a7adf8,1d29a981,628b3242,58a63c6e,2a64b87a,787f0f21,8efa2d4c,a365835a) Z8(88118c56,a120d07c,4cb2b9d3,5fbd2a07,c0ca4914,8c58cfb8,e53ec2df,0dace61b) Z8(3067237d,a36babeb,a1161235,7b33a316,c0af0982,4f529980,a079f408,724490bb) Z8(b7c1f3c4,fa3f915a,2020ca00,0c6cc06a,9180e903,107f7e0f,297841e7,bee67c41) Z8(07f7d675,8ecc3587,a9353602,6119fb52,5b90edb3,bcba6623,a5f48ff8,200b0f2e) Z8(758bcd84,34ab3a52,a6e06431,c02a70b9,e323388a,5402c488,8791af7e,d7740da8) Z8(dbc72eb5,25a470c4,32c38e9d,eae9b47c,8aaaea9c,3ebc6ca5,2416495b,c63dd3e5) Z8(0d3c9813,e08cc3d3,43b08c65,ecdb59f7,bc44b484,57e8ad8a,fa03667e,ca0f9134) Z8(77e8c006,9752c492,0ab8d81a,ad165047,f7dd61b0,50820ed3,26f81f24,73f74c33) Z8(ec3dc240,cc91fdcd,8f47c9f8,48e63148,78bfb5a3,236df82d,8b1fe1bb,65edae00) Z8(e876ad95,c4621bd9,63008a6e,bbc29999,2d9b91f7,0df2ae47,a3614096,15299a1e) Z8(2f9b45f7,d539f362,c23d64b4,f305cfb8,8ff21f7f,367b01e8,31085ba7,ad4c309c) Z8(34e9d9c7,2a85ef25,f722cfdf,87f804a1,98d747cb,496024f9,9105c160,e75a7492) Z8(087ba8db,7a3d593f,d4851b07,61edaf45,7dbf28b8,8d9b4aa4,a60907ac,fffab804) },{ Z8(7841996a,d98d255f,b7fce581,c5d562dd,d566c7af,c98a4102,304d7c83,15754324) Z8(b396bb3c,38246b75,8965f2c4,23c89881,7c8fe42d,80bc6d12,81261966,c500b714) Z8(f687c6fb,7e87fb72,0c2b45c2,22b09394,54a7234f,47d3732e,b0df45e1,a924ac12) Z8(93bc93fb,26f017a1,b0ce37e6,29b34b26,4469604a,f578cbf6,1736c9bf,61233efc) Z8(758da5ce,387a0e65,09af1b33,ca16d756,7f445a28,f1eaeb6f,376565f7,8215fb85) Z8(6fb58751,fc62d500,2125b89f,7be45b2a,83a16ddd,e8bec672,195cefe0,2621fa8d) Z8(3ac866d7,ec3ed615,dee7493b,685b86c3,ba8f96dd,3db3abc4,8befe674,675e6db3) Z8(47506205,b051da0b,ae8c3379,900e36da,fa3c2d19,96eb3b5a,6ccee8c0,c2c52868) Z8(d1dbe3e6,2409a583,a252a11e,02bd0d56,29068804,1d8263e5,79af9a37,ce347ead) Z8(1a59f125,e15c9376,7aeff4c8,a35db0e5,92872c4d,e40ce315,9bee77c3,d158a20a) Z8(523bb1cf,6efdd5dd,bd999fba,2c998369,a3354927,b195bcf2,4f29c926,a6c3fb50) Z8(4695b7a3,59f2ff90,e8de6238,7dd9c04d,19dcf7fc,8f65f06a,2d0281a0,30e211e7) Z8(fa991dd2,dc25d183,6aa021bb,3af1da59,3e71cddf,2771fac7,8301b238,cbdb2d7d) Z8(c7d4320c,81c45f19,aaef9123,44e7426f,a8a4625b,c5fb4f70,2a81bce5,3155eaa8) Z8(15d9149d,ab42c56a,dbac5fb3,3f94ea6e,62a186be,e0f6496b,ff231fb7,34a6ab2f) Z8(2e85dd26,cfd056ee,92cc7048,561dc212,9f31ef24,8b4c6053,a6334228,0f71121b) Z8(ffc028cc,6b8b958c,df3022be,9e9844ac,09e268cd,46179b97,9535b306,caf89de6) Z8(afddd67c,07aefe2c,14c0179e,fef7f3d5,0677d335,54d6e402,af0b20db,037ff8da) },{ Z8(5209c5c7,2b73574a,8b6db333,8fde69af,90409176,60cb5349,0f45f1ad,32f5e40e) Z8(9d390d6c,d6557f48,a5064ba1,9bf826ad,5d3181e6,0f785f65,53dbd0bf,964f8d2a) Z8(2a18c308,723a820a,f60ede4f,f93606a4,b8380485,e2b3a83c,12719162,71b23a76) Z8(f02bf70b,9cdc1bc1,b7464b47,34d76953,987f7ccb,f9d52dd4,5b9a5459,40e08d50) Z8(f3c76f0f,513dc325,fbaedfd7,caa472dc,f4403440,f716248b,4328d7bd,5a2e3fca) Z8(f852b3b5,dfe368f9,bebcd33f,8860da3d,c15459a0,f35c0650,f0de0dae,a6c46cb9) Z8(75836cb7,48a82923,8a1d4988,52918699,f4816b0b,97cafdef,972cd2d0,b081aa75) Z8(ee018207,fd06ce31,715cc95d,af41a08e,cf5ecbe4,cbc01106,6f59e4b1,43821fed) Z8(810fb0a6,5dd1d223,ea4d0cc0,d9228078,4c3515cc,0358e713,3677f5d6,b38255bd) Z8(d8313c94,f06c70e4,b4ee9a52,f05e2aa4,7c439aec,99fe8be5,daa9451a,dcc54ca5) Z8(d8ce41fe,c2ff5704,a9a476de,73041559,57146407,32d5f450,b145494a,36de7e4c) Z8(8be22725,96ce1299,f7af7a2e,597f487d,ba90b216,79154c02,615e704a,7d69b192) Z8(df2964c9,ee559391,5584ac32,47810dec,bd2dba5a,9f493a52,b1567850,a903261c) Z8(48dc8a62,00a3e2ca,9a5bdaea,527ec3f8,03441501,f6a1d9fe,1e827ff7,c1fecea5) Z8(a21a82f8,367b653f,867ccb9d,d94ca157,deb513a6,fdefd9e5,12a7bcf9,4b913adc) Z8(368dea46,5dae5229,8f914959,f2e7038b,3dc5ddcb,d2d31571,e321f43a,21b874bd) Z8(972c07b6,cb9a3f33,6ca4fc79,d2fadd1b,8a750899,a74b1c3b,5d64fcb5,1b987741) Z8(b5ebb004,112782f7,7d909277,673892b9,a2c51bd9,33f4256d,40a81d10,fff9e006) },{ Z8(33589e47,3031c5f0,303cf21c,5621eefb,42bc9ceb,fdf044ea,faa41f23,c405c0ba) Z8(92616920,c9d37220,1d79a589,17f7da8b,d5a44e40,7dd3c084,8ddad853,9ddef75b) Z8(ae0f8419,0cc1482c,12b84c58,3a4b6ce6,2caec421,1ba7f6b3,12713a63,83123d74) Z8(7ec52084,8c739978,f620120e,b7bc7642,e1009222,8286bf08,2d7835d7,09a924f2) Z8(c80c2603,84bd960e,b01c5722,6caf29c6,b0636921,91639bf2,ce8863cc,59316de2) Z8(27ec7d7b,e1a3d15f,3d4f0ee1,94133e2b,c166e890,19463c38,cb99993d,f041960e) Z8(6641d3a6,f37d8016,5fcd0ec4,8d43fcb1,0383b37e,9a70c5b4,113de068,f47576bf) Z8(341311d1,276d0c6c,fec90b30,19de61ca,09576362,0c544bff,159cbb2d,aa151d94) Z8(3533b20e,591a5cca,2f3f4051,5233ccf8,6934ccda,5d6a523a,7919903c,1764172d) Z8(f2254e5d,d3b16bcc,ccc483ec,98ace46e,c247d5a2,014dbb79,29306188,a5086ccd) Z8(6a9ac41d,3aab8e94,a9b5a940,0a26024b,d1d049be,d55767ab,27af636b,d8aca7ac) Z8(c24cc81e,f8a25298,ef193605,b9bdad2a,df225465,3e88411d,b6dab238,91d5d34c) Z8(372fb12a,5a18bd62,932daf36,0ae01286,a5ddcb98,933ff4c6,ce1d200b,293648cd) Z8(ceb07d4e,90c6b228,7d55b2cf,4d61e8f5,da1253f5,182f60f2,c3b2cbb2,c924e012) Z8(5f45089f,e03f052a,728b369a,5b6aaac6,ff0cd22f,b89f4882,1521fc24,5aeb220d) Z8(8c4d5922,8c68917d,195891f0,6d6c5d8b,dc51b218,021a2cf1,7aa47790,0fddba8a) Z8(32fe285d,26fa8974,4240b66c,ccb58fca,a3fd5b87,55ecd26a,9a105a20,a2322756) Z8(b2fc2c7d,806f73d1,5ce0bbe9,ce1e66d3,4626b501,4db9bdfd,062e05ee,03bff736) },{ Z8(7e448dce,6cf482d3,89933037,51b02b64,8cf57dce,82d03d1d,5e9cd87b,bae09404) Z8(946db25c,b7316e0a,263afcaa,309139c7,f1ac2ae3,8337b795,5bd9a416,db9db091) Z8(5ea1e8c9,6da4b76d,ed31fbbc,8ef2e00d,af1f69fb,64b5eec9,a98dd858,2aff3bcd) Z8(ccc21dae,75f45cc3,c65c4a26,a92c92f2,edf493c2,801d7dc8,97ef2d1b,dbd0ca0f) Z8(d6b72b91,c6723f2f,02eaf03f,04ddb115,512da717,1abef62a,8e1081b2,abef50e6) Z8(27294d93,14537af1,8ff67ed9,33166425,09888efa,0e695b07,2adcdf67,da3d63d6) Z8(7e5c2458,da1ee229,c1606b74,d7f9e727,0328e0b9,b849e926,7b116648,41ff3c3e) Z8(0f79b1e0,5b78fa63,fb6ee976,dfaf9a63,043779be,2e3af270,6548358c,f170860b) Z8(ae703850,4440641a,742b317b,c0536f12,efc11222,b41c57fe,ec38a67b,bd9b4020) Z8(39a4807d,c51213d2,7995cfa0,737a3b30,45d3dfb7,00b5aff3,8353b906,68e5da73) Z8(b70ae76d,0845d388,9019cc98,c16b31bd,d3a1979c,1412b2d6,fc8f7996,bac1ff73) Z8(86ac1be1,40825c8d,3ed80fd4,a0b8dff6,9d862e1a,8ac8a6ef,71824e74,bee2fc5d) Z8(09c49fb5,7e870140,207570a5,d72db992,44244ea2,2f747d37,5fd30f14,332da58c) Z8(caa4b1ce,53367173,45b6ed80,b0e9081d,7ab37128,19aa04ce,a5399cb1,cb7a6906) Z8(73ea41db,a6fda334,952cd526,56676b37,2cac8dea,ece666ba,223c622e,c3f2a0a1) Z8(aabf14c2,809c0858,68ae1c16,3696a89e,3a0219d8,1ca4811d,7ba7d6f5,269a1a91) Z8(ced39ebb,27d1d873,41d11528,095fdec0,711983f2,41ee9060,e6e27262,52c7cda6) Z8(c442a703,b1caf8c0,9dc02d02,a1e37978,e4c45d19,f84b9aa1,3d5c233b,fff8f808) },{ Z8(164017c1,d0c9fe78,78856893,58ba5e47,0c93655e,a9af3b9b,33383006,74f5ea54) Z8(e22f7932,892d31a3,e3a02564,f7bbc241,5f620b4b,2c3c24e5,5753959f,209590f4) Z8(42a3d46e,c9001792,7cff2d58,01ba3fff,1df21db7,8077707c,a67dd958,b1da81d1) Z8(93342368,1629629a,f7ca4d6c,689a241d,ead99205,2415c3ae,87c60899,dd48d51c) Z8(b0ffc81b,52daa1a5,62dcb8e5,384dbad8,1a073e67,a224f911,cbf0722c,726113db) Z8(7c15a00d,3f6a63b4,cd391ff9,82b74a28,dca70dde,da38a972,724db7d1,3bc88188) Z8(7953a228,a360d91e,0478a668,e19d19a5,513226f5,cb6d8999,49d48ca5,ac3beb0f) Z8(b4042738,b15e4049,7e818482,8cdb87a7,28edf83f,17987d83,d0fc19c3,526f0d0b) Z8(2d74e4a0,3c532836,7ed69591,515760fe,42ee5466,7e4fa00a,d56fa58b,2611c602) Z8(0ab57a3b,471f96ab,473e1fec,18196160,5c919066,ed0cf6a4,f998674c,e8c7eb0b) Z8(296630b1,509950c6,aa30cfa5,3d43eaa8,87d6e66a,fac60b19,9d09e2b2,ce005481) Z8(9f5ec938,7714fbe2,314b3233,832e5618,642d6ec0,be58f64e,3357d03b,f45206b5) Z8(6ef5d017,cf8fc9d9,7b797895,36af96de,ce8793ea,35a73eb3,3e5038f9,23fac825) Z8(ba44cf25,6be96ff1,e40d251b,aff6307b,957e0afa,e9fcdb91,79365d7a,9354a105) Z8(a07f3326,95b1f4bd,2760c4ac,635ccdf6,392d3aca,fa1521eb,b33fe641,f6cddc99) Z8(2bfde828,05706765,7764c10c,031dfd78,3fb5e9c9,3cb35998,1bf507fd,a8c351ab) Z8(fdaf9747,8e9b8e30,566197ee,72435801,c62e2cf7,eb4498fb,5ea2034d,a1bd4211) Z8(985b1d56,077ec1bd,f5624024,62c181f7,1f113dca,aa938cac,5dddda9d,03fff555) },{ Z8(132dfb51,1c6840a8,6e4da03b,dd311dd3,7ff8d829,da7964ce,edbbd254,fafd6cd2) Z8(e20c4b52,58af214d,a44b685f,e4070dbb,9ce76286,903ef6d2,a4d60fa0,f5865c16) Z8(a5fb57a7,5779911b,d0956208,89acf67e,5fc89237,8beeef4e,87277c75,2d5227d8) Z8(2e1ab1f1,8270be12,652858f0,5470115b,aee5d70a,b418b83d,8e59ed32,674a1aaa) Z8(4dcc455c,6626159d,759ea347,af6911f2,84467826,2b781491,6b571705,1b78e9f8) Z8(a968c57c,b4f2e62a,3866f075,a41dcfe9,9e8752a6,4790281f,b5a22165,9373e4ed) Z8(910c914f,c4c72ba6,672e55f8,ae7c4cb4,a5da6a78,11a5e096,cd382fd6,fe7d7663) Z8(4a2768ca,629e4622,4d0ae329,f70ae17d,677272a6,ea552804,bf5fed9b,57e6a546) Z8(47ebfaad,46efc1fd,f5030314,ef530284,7b4378a0,0567dbc5,bc79625f,fac22941) Z8(50d23b5d,1663a006,0e20388e,ce49dbb8,a57ec1fd,3b82ff63,4207ebea,5ab8689a) Z8(fb6ca96d,a068b5fa,db4ba31d,1fc00d03,b8c1933a,57822bfa,9c80c7ce,b3111559) Z8(d8d8c519,866078b0,dad11f51,18ccf4a2,44cf5a38,490103ee,69c84da8,3c94bf6c) Z8(dc92b670,80b5809f,73325b5a,24ba49d1,408d86d5,2457f80e,def240e1,66333d42) Z8(4305b43c,3de4c5a7,90cda035,a9e29e61,e2c790aa,70a1469d,9a803791,37b9e15a) Z8(719ae310,7fc75619,efa2a828,edb80de6,9be94aa7,65fbe5e9,6fb28871,43e6e97f) Z8(d3588aca,46ae2710,7f5262fc,c9f13d2b,2e8a1ecf,7095ca07,5424f909,b263f5f0) Z8(b77519c6,3a897fe0,6eb671be,01e286c4,edc98229,4942277e,e7d32643,9b3ed7ad) Z8(6ac7f294,121a3235,8d241e94,104dd21b,de6ace45,4514074b,aaa4fa51,fff8000a) },{ Z8(06955414,d8cf002d,d7c470a1,2474b7a0,a968e502,1f7f093f,1ab5406f,0ceb57d0) Z8(c3c87ba5,cd9de1d4,165cfc78,803504cb,3f747395,1eb44006,540be673,3bc4a286) Z8(12e25547,cdd74637,ad16e5b6,ee1593f0,b44e3177,4608d95e,f6254b27,d2e1c3f9) Z8(84f7b56f,0eadfa2d,7f1a6d94,15670c54,2c8cfead,03c4e6ef,c4450888,13ca544a) Z8(f31bf90b,d939dc44,8e4035af,65fc1a65,6d6cdadf,76d39174,62cc8a89,9ced7f03) Z8(cf5bade6,f1df26d2,36a1f120,76545178,222d8baf,e9821d3f,c83cae62,4bb27f22) Z8(ed3298c7,0a0f696f,6421c9f9,736abc93,9dcd3e8c,559f0cc9,055124ee,d308a7c1) Z8(768568a5,4837e3d0,1e653ce3,617959a4,9e6c9276,d20e6acb,d658ba70,c58072e8) Z8(585729f5,31592e96,53d2fb42,d0b1c4c7,c9e066d7,fd478fe9,f5d952e4,bec81e12) Z8(450c3b58,6bd7b713,76609434,b0616423,785b7635,56bb979e,55700fc2,b98417bb) Z8(dc6c4bc7,1e3aa39f,91e5fd0b,4b672968,f2613af1,5f1ec920,985bc6f3,35989357) Z8(9e5ab52a,87ff33ee,2ee79a07,e791395f,b7aa249a,b7445f7b,6aa17230,f96c959e) Z8(71b633ed,6a70305e,bdffcbb2,cf220246,e4d9276f,6b363cfd,815dbed8,301958c2) Z8(f6ea2209,d21a1254,07145009,362e8b84,22f3515c,defeed1d,1aa00a7a,fa9696fc) Z8(363d3c72,f70d934e,371e23f0,75d0e24f,9c411c3a,54cdfdb3,94c6f8a2,0c235a75) Z8(2bf259d2,79d0d9d9,5f8a00ae,b7ba8a3d,5ca7adb1,0352db17,671295e8,0118efc5) Z8(ed83fdc5,e9ca207c,cf51788a,b3a5ef3f,82be84cc,933b1f06,4ffd5a0f,0824eb80) Z8(8987a7b0,39d50c30,6c7a51be,75860538,ddb1c87d,9b5dd0cf,b638aec3,043ff334) },{ Z8(427df3d5,59c276f6,30249f13,93b211c8,814069c7,de254dd7,15e43f9e,e9a73aa5) Z8(db37e58a,12ce19fb,01394e2b,b6935d02,223987e2,15354b5c,2c18816a,cdfc7f6f) Z8(282cb8b8,5be6d76b,bd16f79a,866d8e9b,598785bf,3ec9f84b,fe8bf847,4cc95393) Z8(cace4975,30dea243,c72cc709,ab88b374,092383e6,51d89be2,5ee197e5,a7d0dde6) Z8(2f009285,7bc2d2f0,bbb90f82,53a98d55,0189c120,2db9bc76,33997137,60c05fe4) Z8(331a63dd,3bd8f01d,c4418b79,7c0c61e0,88ab8f08,790c4095,3b6b14cc,296ff1a2) Z8(d3bdf72f,877d1dc6,4c39e22a,90f1b332,9f1877bf,343ff81d,3d80c028,64270846) Z8(20590f2a,4366c823,bc8ba44a,155d4980,856c83e7,ddf01a1a,6f8c8e79,66df0e45) Z8(258e0b7e,6359d8eb,4ed47a4b,fbf361ef,20795c7f,2d6bf821,cae2cc4f,d9bc8bb1) Z8(5da40fb9,0c23e4c1,0141dbde,3704169a,4fc1eb38,b4b75716,ab72cedf,710e29b2) Z8(bca40f55,4cef01a3,3b4a4846,984d6fbf,81d8fea7,3b48ed76,c1ee8701,7f8f7a12) Z8(3ffae8fd,643e91e7,d595eb24,1f7bdb17,fb599e55,2b365242,6275d350,bdfc3f83) Z8(75db139c,87bb2753,18fd3817,2d3038fd,9571bbda,08e979e4,109fb9bc,6461ec14) Z8(f3734e59,901d241f,77d71bd3,4d9b53ba,17881ff3,2e36e5df,0f0e6a1e,09e7d6f2) Z8(59910a2d,576060ba,96876272,bfdeaad9,c68cb99a,3c228c5d,2782b9a9,47266926) Z8(d040252a,b82cb273,731b9686,29336167,3004a776,6ba0c58f,8041b71b,bd33e62e) Z8(c2190e8f,2c8e605b,55a6f28e,ec6590ce,44a1a631,34355c64,2802380c,15f9549a) Z8(3ac2ed22,13e63182,4f0bd8fd,3d9fe5bc,df6f3ef4,e2653d0b,98027b66,fff6f80d) },{ Z8(653b135c,e4647f3e,f2dc191d,8776c725,d79a8741,b30ac316,c5f95bb6,ff3218eb) Z8(802107b9,4ea9169c,2128fca6,eece940e,460677d7,c37a5799,15284ba4,9720bcf2) Z8(e2f96097,d1214cb3,69eb4758,bab97e85,34e85762,37db6dee,24ed8905,a28aa2a5) Z8(e508b0e9,c3e0aed8,6663cfb4,2fc8033c,45162538,72b83cac,44ee5abb,078eed80) Z8(881bc7ee,4877038b,058e9cf0,c3b3900c,9612b339,401c2f73,ca950554,05a563ba) Z8(0a6af183,fd854410,aa2dc3a1,16a17aa6,eb28afe6,fdb1483e,2eab532a,35778044) Z8(74a6b09d,332bb3f1,cfe14f00,084e1092,2ae42be0,8fec846a,349934d7,86dc35ac) Z8(effe756b,41258be1,173d7e0b,dae90ec0,2afc3e42,8479ed4b,a77a174d,687c8148) Z8(14639686,50925e7c,b07fad62,6e1c1636,6eddbb9c,65c8737f,83aac48b,758634f0) Z8(d3094742,afebea6f,77153f39,ccc8e3ba,d8033529,29555bf0,bb27b3f8,99087283) Z8(f9bf590e,210de2ee,391a4e87,12c74b37,36feba7e,500a866e,cdb4f9bb,39aa7e7a) Z8(9a1efa36,1346f70f,7d3e0109,37e5b621,681c6689,06dac5b9,5fe11a6c,5a7ee11a) Z8(4ac97c4a,afc6dc96,baba8f9b,ea9a3463,86317ae0,80ded43c,a4b5f908,7e7e488e) Z8(58768f6a,edd78b8d,9c17b915,bc075b21,afa8551d,38831b22,0232b450,ee0d79a8) Z8(d2430024,ceeebe71,d3e85dcd,ff485924,934db7e7,62cd4325,3732771e,a3f55f15) Z8(36464913,f6d49302,d19365a3,b17a8514,813eee65,ce7c34ee,d2096b36,4ada09a0) Z8(74763332,aca214fb,bf760103,8cc3bf35,d01ed556,d0fa3513,494bf88b,76903bad) Z8(38d0ce72,6354fa38,d7908e87,77fde0b6,3e8848d6,9ac55ad8,0f60922f,047ff0d0) },{ Z8(0f73d7f5,ab9389e9,ac33a49a,39f104b2,11c8f942,26e74f0b,a0f49211,8cbaf305) Z8(b76e4db7,17c02f0d,f863b902,288d2308,65341f0d,84d834ff,422deea7,d0dc3b78) Z8(e73bc79d,f881b9e4,fcdd2a86,b5c83c39,1d5ecb19,1129be12,407a8d4f,cd3a8fb1) Z8(6d725467,fd2f256f,34898437,736e0d1a,c4cf1caf,087a707d,dbe2ee11,068aee91) Z8(c0f5c955,b3c8e0e6,c1bb4518,abba6fb1,ad394d21,bdb7b91e,235889d2,82cdbe7f) Z8(c0197740,6c5865a4,9cdf6ca1,6ac83922,27b1e23c,8258ebd6,015ea26e,79f12c9c) Z8(a632410e,9d29d90e,814f7f6a,f5f463a7,5a1a03d6,dd06a6fc,ef2f5aa2,2706b56b) Z8(3ee69444,53263303,a13a85ca,bee0a36f,cb25afbb,9cb4587d,d33047d8,2a2635a1) Z8(3c3d054a,390ba045,78be49b3,b6dd2a06,f9d8f225,77b3f17f,7b4e151c,8b640249) Z8(1831782a,9bf32912,297ba07f,1a595072,fdffe71e,f3dea97d,44d1f143,41da87f7) Z8(bd0356e1,54efbca1,701c407f,f5ef7972,6914b016,a11a87b9,ff8eb648,dcf2899b) Z8(94e70d40,a4ca09f6,4bbcd161,424df9a7,f9d4e136,e17479db,da3fae1f,c3f8a97d) Z8(9d06502a,f9d92e5b,47404f9f,90389232,52ddd98f,b929ca73,114e7ce1,25a14479) Z8(0fa0d742,ef393304,983cebc9,c2b14171,9f80e687,b2cf9713,17a447c4,2e430836) Z8(167f8491,c5f04741,c7b45389,fd23640d,27a09bcf,635ce4c3,f1882608,613dcbb3) Z8(77aa3dcc,78e9b9ff,82d1c672,71c7f783,607988cd,cb0eb328,c99b782c,0c022cc4) Z8(a2226ea2,ce0034cb,a32eb5ed,555c71f8,46bfc5e0,4117d8c0,063da242,8fd463bf) Z8(67b4a608,73791d88,fddec6af,dcbc64ac,db57baec,f86c603d,15f47790,fff5e011) },{ Z8(3d193e7a,e57eca97,64f293f8,9382db2b,53ce7096,9c4fd523,b32cb313,ae2b5968) Z8(cdbfce58,25a25cba,163a94f6,9fd4ab87,8549d1f3,989d0633,d867c58b,f4373d84) Z8(0ad7c50c,aa42f13e,bec82d05,9ea167d9,769957cd,49067808,b8a48ef4,82d8671e) Z8(0d13b7f8,c76bc343,f001755e,b09593c3,e13be7cc,21ddab68,4c9646ad,436a4970) Z8(15bd07b0,fabfb15f,8983ab35,f2f50cf7,1e49c868,43cd0b7a,2f30e248,6de1b32f) Z8(1c2749b9,f8435316,463bc544,ff2203ac,c3fb5c0e,a0d88cce,c725979d,19849e0c) Z8(5d8679ca,37ad2036,de254ac4,9c97ad1c,88e84ea4,b17ac78a,3f7bcdeb,e501ced1) Z8(f0f2062f,e5ec45ac,ff6f7af8,1674d386,6b22f1f9,edd2d5d5,f7d0033e,00120a5e) Z8(0d014037,36d0846f,0785199b,63ffa8a1,9b3240bd,870d7c26,19f0715d,4fa0036b) Z8(50a13851,766cdfbd,ca4e7059,7da6eae8,b23f6cb5,0e88fc84,435cfc64,980f1265) Z8(2071eca4,c35b66e9,05c948c7,d358eceb,1c059005,34504567,719bef0a,abf1c136) Z8(5aff1164,fa3700a6,9cd879aa,eb620226,86272403,df080639,351845a8,05f73fd8) Z8(00e9dfe4,3f9d452b,17160d20,4fdd05c9,9013dd2f,c15c290b,4627d469,37370174) Z8(9beb0195,e8ae1b17,9b2c5fea,74076e06,94c6c479,6aae0768,f6d780cc,0cc82cc6) Z8(da1c2fbb,c4dd61c0,6f8a3979,5a1d5ff5,918286c1,9c76b656,dfa9a4b2,fb82aada) Z8(d5f0b479,70b02509,c126f4c4,328aa09d,63dfc2d0,5dfdad0a,d9697866,6ab2ebaa) Z8(b934085d,58693c16,8be9ce9b,036966af,fceaf652,ac8afe91,a250df99,2e9d0c29) Z8(5a7d450c,6c6b1030,637e8ac2,65b3ea67,1fdedd3c,4cd800ba,697bd4a4,04bfee23) },{ Z8(0ca17b8c,69cd8dbe,bb9da9b5,c34b3121,9ca6f98d,ca52b03a,e03cc442,bf9a96c2) Z8(56620874,c4977725,bac436bd,498808f9,6b4b6faf,f6542751,77eceea0,17416127) Z8(906cfb5e,f3e05fb8,f8949b66,a5deed90,9188a83d,d7d14f01,2f27ca90,d9fadd8a) Z8(d09537dd,3f644db8,838da7f6,c74812a5,afc0e6f5,2da3cbb4,550e0725,013a1ca8) Z8(65bd24da,ad26b3a0,b2e65020,e2bade84,6e0feed6,e5da133a,c030982d,4230044a) Z8(82ba66aa,507856e5,85515351,4ee33518,9ffb25d6,4f9b96e0,fb8f456c,785fb8e4) Z8(7ec4fbb1,2f425bba,98e86872,d0299fac,9d27d232,3afc9c45,721b215c,e1d62401) Z8(0b5c9eef,c55a008f,f61d140b,65a6b00f,cb58ebc9,10d3d32a,904c46b2,a587a07f) Z8(0d31928c,f53bae5f,c6b1d0f5,8121a865,40dcd543,ea225eb7,b3431076,86d1461a) Z8(31596430,6d441571,c0f5d97c,b66c7639,4d9f681c,0efebc5f,e0e224b2,d51e58d0) Z8(33a77edc,f55cee1b,19c10bd4,5b834ec9,9ff8de82,1fe50316,bb4dc05a,66c1511e) Z8(c41becc4,7384bae6,f69c91b4,ab596ca8,3e08dbe8,60421a4c,2c77aa09,17463225) Z8(78615382,eac71c59,e3f4e95b,024a8b98,a7aa08a9,4ad81036,ba0d38fc,04b1fa7e) Z8(93fde3e0,8989d5ef,e0c541d4,0d93c939,c5ceddf0,0f1b5135,8fa7a700,489094a6) Z8(0c8ba07c,fc585258,3df540b1,0c9ec4e1,bb8d464e,97bcd9ff,6f6f30ef,1fc7e603) Z8(8a8f6b00,d797db6e,36598dec,9af04291,489b04ce,ad167d1c,20b79d69,f126e509) Z8(07eb829c,c9711a5e,63e9cfc5,2ea4c25a,5ced66c5,9079531c,4c827777,0001611a) Z8(79707df0,9d149c02,b02fec1e,1a7ec6d6,ad7b6a5c,125c0572,35fab6d9,fff4b815) },{ Z8(39a69d79,5d38ca4b,199486af,a9595bd4,4af40e59,eda04154,fadf5072,9520f1f8) Z8(8ae3dfd0,f81d8f12,1c38b893,1b81b428,add20497,1d340f2c,09d2bb96,c92a802e) Z8(ef3b5747,f752d978,ffc55cdd,3c3a5233,e69f4408,75381d6e,40a97631,2822b170) Z8(bc5d9d36,6fb9654e,4cbf2040,030c09be,9de33f5e,76b0150e,e5730ad0,0d48f076) Z8(a1aed8da,5d73826e,d7f0e850,1fcbfc05,5151f5b2,0512633e,91032939,aa45df3e) Z8(aafdff5a,a111b15b,dbf99285,1bbd8979,9c105e6c,b8a7c0af,fe5fa9bf,1a227f1e) Z8(d3e43604,3342f3b3,fc67ff41,2a88f8bd,2adf37e9,a862078d,a9c9ad60,fd846679) Z8(d7ab9898,454f928f,e772d7ed,d6fdc733,e5eb0626,a582f8c8,55023fcc,daff45b3) Z8(c5964358,642c0999,3a9a567a,f1f3d341,c0226a52,bbb1b926,412c6121,47d8c4bc) Z8(f32a54fd,510e1d86,a1c5d338,c6dffae4,51f7a389,6f8aba80,dc12f069,75e168e5) Z8(995fbaca,8f205242,5429cfdc,d7babe91,7f2b0b92,6002edf9,1c7d2c4f,a0320309) Z8(e1737d94,b7586a35,30c28271,963f6d3f,76824b71,21894523,43c1cee9,8b96eb32) Z8(b555630a,54004b3d,7bb47c93,8b6a4750,cf8365ae,b9011182,d3bf928d,9528556e) Z8(f5a4699c,a79ecb23,5f888970,8d7ccfb8,786829a4,5669d741,12295701,e0059744) Z8(d562e60a,5ec6cd88,c7eaf6b3,e9344c45,27bd2c2e,66f47f7d,32252d04,71c1e44a) Z8(8441fc0e,3822fd41,c285a67a,9bc474b0,851f883c,7f7152a2,c8e09c07,54587842) Z8(e3463014,cf3d5b67,78186dc9,3801a36e,ce2161f8,0373d0bf,6276fde2,4cf23b8a) Z8(f0bfed96,50fae5a7,7c6e0e96,4a14e87a,cccea63e,19b3218a,c4b545d5,04ffeb2a) },{ Z8(febf3d9b,074493e5,10711f14,105c81ba,7158abd0,c856e764,3f18f8a9,9c34723e) Z8(95dbee56,430a0968,5b7c7a4c,4d087761,4a87d77c,6b016c0e,83b8b022,d9f287a8) Z8(75740038,f6a98df9,0ba0c6f6,f888c0c9,c754a736,79702e8e,653d68e4,11f67ee4) Z8(1c7d081e,200e0041,a0f7d342,24c54ae2,b2b60b73,28fcce79,26e5f1d9,b5f00462) Z8(43b09c72,ca8aeae1,0f20a263,8c14f409,21f35d18,4b67b636,941896f3,c16a8142) Z8(9e25a490,6fdcce02,3c1ea289,672f252c,b087712c,f9f9fe65,7ae37409,f54d8c69) Z8(a813a677,4aa5a273,132ea988,4d77b9a8,68c0e799,4e462505,a06e2e9a,70e5c649) Z8(feef80c1,cec819df,0ee9ed1f,cf9cbe8f,ca19d568,543670e2,99d4ee91,d5aee545) Z8(ff47db39,5d22f683,20b8bdd3,3f158e2a,039a0dc0,5be1698c,af5641fa,f7419cff) Z8(b2cc033c,21209e7f,841baa1f,2d7fea4f,afe21664,468d7ad8,a6d66b04,1b864a5e) Z8(c81ff57e,9951e92c,91e23991,e3c2fdf8,3d326eab,1a96a7ce,7ff111ec,d2b71793) Z8(11703218,d86a3c4e,9c3df620,470ca099,7519cab9,69b07169,a6d5faa5,4fab7b5c) Z8(df8904ba,00ccd1f0,77616676,0110f59d,8a6461af,5aa94392,43d8ad5b,64fabb52) Z8(2d49a875,16f1082e,b0e3453b,e9001824,d4181410,383b0325,a0a576de,3f1f7447) Z8(91924f43,150bf444,113d6a24,aed72ed7,38aaf72f,c713c725,ab19f15b,7df222cf) Z8(cfbb7ac2,57bf1e03,fd7ad0af,8d1c83dc,666b8e16,f300230b,3da1138c,f13a121f) Z8(0aa8cc75,71ebe6b5,3da0bebf,2c3d56ff,aeedaac3,0b0e9804,0840625f,1e268993) Z8(1f19c22d,8bbdf397,c116c793,644d7b15,9a68ae63,21ed0e0d,0a94f726,fff3801a) },{ Z8(6e22da5a,5efcf478,44bd1bd3,e6631fb5,633b40a0,f54bcd95,e8bd6b14,06f474ff) Z8(ae7a1de8,a0b7f5d0,9bc273e9,d9101062,975ffd9d,0d5bb973,47a4153c,0b41b5ed) Z8(3c23cfde,0daa366e,dfed4ea4,20d60fd7,c4d96002,49a94b4a,2caf7f4d,9e7493c7) Z8(a63a2d25,cd7a5f99,214424f0,ff0addbb,7025e6d2,56ecf9fa,fa024524,187ceed5) Z8(c8d94d44,b1ce9ecd,cbb03d6d,86371644,7aca7a4f,1bce57f3,4d72608c,ecc04c8f) Z8(64867d41,44356bf4,0255969c,27e3ba06,f8f27b1b,9605054f,677af06e,25ccafae) Z8(0d81f72d,b25326e7,6e490c24,fc9df80b,bf1f321a,f692dc6c,279bf1ac,7c867c4e) Z8(fe2dfd5a,be0e17bc,49eb6cb0,77365589,7cfae2ad,cdebda01,08886267,e85b6b59) Z8(301bfe08,df7de8c8,8429ff9e,9a122f14,26234696,7c95d80e,c140b6d5,4d349f0e) Z8(a78d8a47,9f1e30ee,f9382f1e,c9bd84a0,6a241e23,e1f93b02,fefe280d,23dee60b) Z8(696868e6,5f8b3653,852ed809,b2f1adfe,a3517372,bad9d9c5,3585931e,5cda001c) Z8(b8f97d64,2d554b10,184ed5d3,912afc23,068124f3,ec70c1fb,1534e3f6,87b4c502) Z8(058e7000,bac54ded,20479e9b,2a6b6d8e,7da58f73,f1d15f2c,1ea550b9,d072c2ec) Z8(ff610eb8,34e5e564,3eaf1677,29185b04,8f28691e,964beebb,bcfd79d9,d4c8b17e) Z8(aa4bc305,bf5b1ff4,80127dbe,31f3cd25,893381e1,e2a1f57a,86563188,c751fee8) Z8(9c455c5e,8466f4e6,be46e35b,ebb4ff2d,e8492838,04eaa0f2,06e95699,b4fd17de) Z8(ad1acda2,2667d353,aa58bf9d,76779248,efe922c6,9dad6b88,424ce583,cbe2bac2) Z8(d7b1475e,adff56d8,254a25d6,bdc49376,4e6d655b,80331d3a,213c7563,053fe7e2) },{ Z8(5235cb26,41ca6459,060bcb5d,07f37cc4,66c82df5,ab6d90b0,9323d4eb,6be6dcc3) Z8(384a803b,8b11311a,97664490,e290d6bf,02fe1a72,d18bd1ae,820f1746,ee85f9f8) Z8(8b963f85,4ae2ee2f,732a87a8,e4b5ebf5,b09f0853,db04b09d,e8254886,722e925c) Z8(65a061bc,016b6a98,0afa51e2,82301de9,c1653bb7,508f5203,22495a12,cd307af8) Z8(4758f46a,877b2da1,4723b760,bf1a0654,251c3201,c5adc8e2,ac8817a7,f5578eac) Z8(631b0569,916b6e36,8e826bcc,6b91f4f2,bba4e2c4,154939ce,99c1c1a1,7d9c1f96) Z8(25d007e3,0fc0179b,b8ecf18e,f2e7a9a9,009d027f,a7275248,3b131727,41ff594f) Z8(06342486,d6962016,cb62f343,10fd2442,3e9faf8a,b34f7766,4c092cdc,e21f6875) Z8(d16e690f,7e2d71ef,e32c00ae,1a2c04e2,3991ffe2,6c2e987f,91434a7f,fb922815) Z8(be7733bb,2b983b4e,5c3f70c0,21f44d42,c0b6ad27,aa3fa60c,3c15c72b,ad7f8a8e) Z8(52cde49e,d1a3a92c,2b0d3911,b595f9bf,c409c853,f8326673,304a454d,36b8f36a) Z8(cc68342f,088da43d,6332e66f,275d7c79,da8a2e5c,fd0d1428,6d3eafb0,fb55ba19) Z8(49095e02,b0c95ed1,67771510,681abb46,37128aa0,7b6b5d58,bd8b41e0,4754e268) Z8(5cf60df5,79844350,1a6c40bf,f037698b,da6f5b54,5361e180,ff7f44de,464ac5ed) Z8(4dcede95,b189b6f9,65bba3bd,30efc5eb,5a3024a6,ee5458c7,d44c08d6,cb0fdf32) Z8(88751a13,43280d31,c6cfa7c5,bd74ebab,2de219b6,c29ff096,68fcca12,ebe59800) Z8(43fac8c9,f0cd9b47,b45a3671,ccefa359,81924715,9bb5a72c,8d9e6381,3e93f221) Z8(649723b0,96a59a71,0f3110e9,6aa11e45,e9909755,8381c3cd,a742eb14,fff2381f) },{ Z8(4882f7bd,8298d940,f496a446,7a6d34ad,aff15e94,397204a9,8f834c0e,12a93722) Z8(8f3841fa,5a7148b6,b143f880,bc0c4ced,846d93d1,41ecf7ff,a0b3ef84,4ff3405b) Z8(9601a9f4,df79a0a6,1d8c7833,9cfd8244,54c66466,83d805fe,88a14640,69d30878) Z8(5ad7318b,4d32b64d,43356113,7aa51619,539cdc29,747d8a51,8f9c973f,8c5bd6d3) Z8(e071ddef,1a68a38f,4646095d,ddd43dc4,3ccd97ba,e4e5eab6,e77970e4,d4bcb8dd) Z8(b3d919fc,d14e4e53,be2829ee,aaf4922a,7b02f782,af0d6b76,a315dfb3,e91afc25) Z8(f4b7e175,fcbccf14,fcc11404,772a4b8e,655b4e93,c47c825b,af9228b8,e8d7d2e3) Z8(57b15d26,c5a3dc84,f7409ce9,0de8e352,0c33fd83,05b9269d,b4b3383b,0a7509c8) Z8(535baeab,75004ef2,91d9958e,6f6084a8,a6f3ac3d,43d11cc4,2e8afd4c,1f7f1c44) Z8(12a49359,3da4f391,ec74b744,b56a48e9,d42852cc,f6d9f172,0ad977b3,b8491f28) Z8(57d90664,04cd5b4d,4c006a02,cd95ba77,1bd6f53e,0be9e34e,3950fb6c,42fd2611) Z8(f26cdd53,01ef2402,71939e98,c122efc1,4fd19343,bd55673d,773032b4,9578b603) Z8(1fa1b134,05473938,7fc425ad,8ee2b392,6f96374a,ef3569c9,15c4fa39,cd0879b5) Z8(b398cd12,d35f94fd,0a938347,e74c867b,74ae34da,5eb4a9ea,757e2505,012a7a26) Z8(b8b310ae,1ba710b0,b8ee2cbc,17e152aa,2f933bb9,2fe9ae80,c4fedebc,6d4a09fb) Z8(950ba3e3,63b65a87,983774d8,4b52d360,01dfec65,0e06da3a,a0d65296,9b402f8d) Z8(e88f51a5,f97ecfc7,09c644a0,32046db1,c8695522,ec24d8f2,045559f3,2d450f2a) Z8(9ee5227e,703ef91d,ad8f5210,6c96c9db,20c47478,1ca3eb47,7f45f2dc,057fe445) },{ Z8(8ebe4614,dbb97880,a9ad2463,e6f8053b,2cc29cab,b79275ac,40142338,0b97d4cc) Z8(056abce8,6c4aa56e,6b920e21,6cbd4023,5922dc4e,488edce7,9726193b,803f2b15) Z8(07460d6a,2c36d2d9,88fd6668,02db7f5b,c523a36c,56cdced6,625665e2,145b04bc) Z8(bcd3118d,021968cc,d580403a,7c8c0088,569decf0,35ae8514,c06a72a7,c29ec830) Z8(7dfe7c1d,896c21a7,4c297cc2,d3002f02,6b2f32e0,a648da3c,28733ea1,5ddc59ca) Z8(08cacbab,325d61e9,98cdac90,8f35a929,3ea58333,2c460400,13278a6b,b92ae3a0) Z8(298f8d7d,b195edad,3adf3ddf,568cad7d,7a4410a7,6ad89cdd,53e69184,b7723cbb) Z8(5fd5565f,4761e176,4721575e,0854c1da,e4dd39e7,d4a13f56,4f52de77,083c8243) Z8(06467610,4f5d6822,5d2c7e4e,19cf5fef,f652396e,fdfe7906,70dbc585,3cd6be36) Z8(db09bba1,c76bc3d9,b0499267,8c91b1dd,032e816a,74c0b120,2069604f,aa1c5b39) Z8(1f884a3e,dc2c8f10,6e5bd0d0,52824d74,88d1ef7d,3bdc5903,4ac3719d,9a099eb7) Z8(ad86f301,5486369f,3d67ea3d,7cd011d3,5cfb7dcd,d0ce4faa,0c8b16fe,3872b2b9) Z8(65b75f9b,7875cd14,13bf258e,9965f6fe,34bb2bed,070bcd3a,1585de56,add73a0c) Z8(74c705fa,4a125101,5b5a673f,8b05c514,da7e90db,d9b4cd40,d5c244ad,d52396a0) Z8(cbc46e56,eb8fcb1e,4b0bb6f8,e7a86883,729df6fc,195022c0,931f7f3a,2e76ddcb) Z8(4d0f4f97,60783ac3,1ecdfdd6,8a9c537b,bc7a9476,e412c964,16c3dec0,7a41d0c7) Z8(5e0f125f,5a677bb9,91310b25,6f2379d1,1f9f50a5,fb3c6a5f,b56d7989,eb747999) Z8(ee4db8bc,db8fe8c8,db3a6b2d,708d1f34,4cd4c8ad,02fdb302,208438be,fff0e026) },{ Z8(2fd3337a,ed99e6b1,9822f7e9,a19f77d9,5a568195,584dac44,ae00801a,f97f8143) Z8(6ccca5d2,182b5e24,7b6cc28f,b020899d,dbd969f9,edb7fab4,7c0573c6,ddc597b1) Z8(4c118eb9,9c3699e5,e4872a1d,3185519e,b3849051,f9a380f1,1a1c083f,33b7e8eb) Z8(c1d7d910,7cdfaec8,b76c9a5c,e2e2d790,f3093869,090ffc3e,b1c71074,8b47fd36) Z8(ca2cbcc1,f5062fd1,70b00ac9,3c77973a,9982fb39,2f171378,cca0efcc,3d34344e) Z8(d7c518c3,1aecbea9,7c196b97,1cd03988,0c9d44ed,e5ee43d6,fb4bdf98,ecd650a3) Z8(efa2475a,9742d62d,20f8e418,f4f7527d,c84045b5,d693f559,82d2b3d4,f3d9d0bd) Z8(1a8ca89f,5ef79495,558340fb,70f93a62,9e7416db,2a188ae8,1e866456,2db9e336) Z8(4c60b3b2,3c5a0539,90ba331d,06457203,1b857e9a,dfcb1b04,9d566fab,37657e26) Z8(b3fc53f5,2f845b03,536e1804,a6e08812,c9727ce1,c9c076f8,92ca0530,1f804800) Z8(4a79528b,826c5557,26c055a6,69357db1,57155355,759e0f95,be2fb411,556d02c9) Z8(9f3ee910,73bf71e2,bbf3c039,1140ec12,563dc8dd,8cb649c3,7b09891b,e80a52fd) Z8(707f77dd,e4d5914a,c70bcbd9,08df6b8f,af09469b,9d34919e,423c8dd8,38352908) Z8(4fe93786,785323e8,35889822,6705d56f,9d80d5a0,00d96150,5aa21f12,dc0e07d1) Z8(ea928c9f,12995ba3,c9ba31bb,49102ffd,81fd83cd,afaa6cf5,097cb331,5613760d) Z8(adf7edea,9d651acf,13901c8b,99fe66a3,e0f92e45,7b800e59,023e912e,88e4ce90) Z8(30c340ae,bdd2adbb,48997b50,16897058,afa96d59,17772c97,31b45a84,37bc5389) Z8(b740c8fc,4ce58223,5d8d95a7,b80378bd,973bbbdf,5f730005,df0b8db3,05bfe050) },{ Z8(e5eafb5f,ffd81142,a4585b8e,c7b9632d,04c42784,5e4b49aa,91d288b3,b7f030d9) Z8(8baedd01,fb2555e4,a524c2c2,750d743e,c9465c84,5e778e49,cfda42b0,603b58ee) Z8(28e637b4,faf85e5d,fa030591,3c5795ff,8c8ffefc,20235ac5,75fee8bd,e8fd4d56) Z8(4eeccc58,dd9827cd,1a824b10,f17ebc63,db4b7da5,1b7e1b9b,2945ec50,01b2b13a) Z8(95556c3c,45f96035,3d18335e,9fde858c,3afc5233,6c9a5328,02acc18e,597a42d9) Z8(35e2d092,3c7dc2a1,0122c2f0,3dd70a53,d769e5f0,5ae86490,6447b742,0703ca96) Z8(1d78f050,ce2a4a8f,f5d07c47,4479ffbf,b123d901,605a3b9f,f93439be,066d764c) Z8(41993220,72b7ed8d,0af3306a,ae28abe0,964aaebd,6a5e3438,9046bf11,2ef652ec) Z8(da363379,5503b6ed,2b8c3593,0cd453fa,39469149,764dd97f,2c5af574,56ee520e) Z8(c5559f74,58e04371,5cd18f8c,de2188c2,57a37d8a,c794b8b9,7b319b5e,33e55419) Z8(9db51b3b,ac05a7b3,9781b6c7,19a66f63,293ac5f1,534ff057,2cb5e5a1,3056dcf3) Z8(3e326cc0,fa26e309,ade8c47a,c229f10f,90339e04,d0747410,18c8e26b,951e2373) Z8(2cbbaa0e,89db8112,168eba6f,85f18e62,2868053b,bdf5efdb,0a0251ac,63210854) Z8(49f0c726,59ebbb3c,a8e3a8ce,3eb4ded6,bc327b38,339bd77e,c3e5f5e3,35713ffc) Z8(fdb9865e,3e36f707,603952a0,3ef3b10b,da51c83e,e17731ec,92d4a809,c9635390) Z8(69a64f13,1a8f6b5d,19391545,32fd3822,9cfd4d19,761da990,87bde19d,f4f8aaaf) Z8(b4496af3,bc9ff45c,eed06b28,f2bc947e,acb56373,656d631d,dae080ac,3165af51) Z8(d2da4da5,8544cb76,b4851a95,16a4658b,7e54fba8,e165c318,8bd87871,ffef782d) },{ Z8(50c7be0b,d6fc7383,74321d11,976f460d,fe161827,aced4c22,a38d316b,152554b4) Z8(2a226df1,23f3fd43,279edb7e,77d46cc6,c1cb5273,eb069f97,6ce955da,be586234) Z8(04aa26ed,72c38cba,0a015f21,5c055efc,0f0ef828,8abe466e,a5ce85b7,d2bf74ad) Z8(edeb21ea,10a22e60,aac19a0c,6eec03e4,9b7a6497,f67591bc,ff2d34e9,c2d67aa0) Z8(f6c03c76,abba831b,6875bf0f,b8c159b6,c84d47d0,bfa3c674,d347ac90,e79eff1d) Z8(c1676386,d8c5d069,68bad8e9,089bbee2,efc630fa,bc28d416,c85568dc,94376898) Z8(e61bb309,b69a8c82,d236c3ba,b29f9975,ab90c27c,75b99c4a,b408e692,8bd621f5) Z8(29f70b2f,907cdacb,9bcbc796,d6de7841,c55a3d44,9b7e19c8,9a32d218,957c1030) Z8(916ee237,71a68e25,16e09de9,bde41e44,9aa64006,fb608e2b,4a932101,a1b491b5) Z8(f0131fc6,c5f6af4c,74e572c1,95b4c1f1,91e789aa,1a8813c6,43e26abe,e83123a1) Z8(bfa7b783,94de2aa8,5396a1a2,c89069cf,5ef27199,b05d9003,8f20d727,d1c0f5e6) Z8(c04fb06b,6fae461f,b6f58424,bbc32f14,5d184f28,cee044ac,1ca1425a,7123eebb) Z8(c386ab0c,a9eec7b8,e5bd873f,c0b30d84,b3010d28,3c46f79f,cf4b7a5c,b1772e4b) Z8(fc93122f,456cd25c,4eef8f0d,b130b337,274c54f5,cf314946,cf78ecf7,16945e41) Z8(17af6439,891abda2,500634df,72ada566,ba71b00a,4ca5f229,15c33fb0,e1c55f88) Z8(dfb07db3,0efd99cd,a20cb058,64efe7e2,5b9f6b89,91f7e2a4,04f1d767,c7cbd9b9) Z8(5bacb364,5423d214,a7f1a284,d474869f,89626be2,c4224296,a2fb6ce6,8fda35a7) Z8(4ec65078,057e5d7c,5e37ac6b,848a2e8e,27336737,efe2b515,40cc9541,05ffdc00) },{ Z8(af253b4e,65535844,82c49e25,1bcab93f,f0531a6d,6480b5e8,4852751a,12880461) Z8(8f1e3e5d,fd4cff54,f8baf6d3,49420983,32845c92,c1ae550f,adb4acc2,d8135b89) Z8(e26a9881,5fd3da8a,0b9dcdf5,b7f6a13a,0d61e535,be4e691e,3160545b,3e63dbf0) Z8(53c941eb,9c176e3d,b588aa4d,764370dc,843bd251,590334bc,b4ae5a1c,b9365abd) Z8(4e0c3178,33358ee4,4d952438,cc31b965,2af918f0,7cfde73f,600edb9c,7da16c56) Z8(9cdba02a,a35dc802,587d8af2,7f73b32e,7030c321,238b7ae0,7cf914b3,0236b985) Z8(c384dbfe,fde7998e,102744c4,a64e27a8,f84aa5b0,f33bf56d,304126a1,c2da1dc7) Z8(19d6f3b9,1947ee29,08834601,eac9138b,a309b9c7,4b2ba879,0715c996,002eac09) Z8(ddd46bc5,a077cb4b,790e3f08,be44a1e4,08527558,719e05b7,906d7404,b848546f) Z8(d38b0bc5,1d6b3872,9c2b2d8c,cb3df97c,e5879656,6a29769d,280fd530,bf856d54) Z8(0c34387b,3a1f4b0e,068151b0,083ad6f2,c354686d,322698de,21ecb0b5,c779d84a) Z8(ff333653,1083182d,f55ce40f,bb6b87c8,cefc24f6,22043cae,cb6a73dc,ada5cad8) Z8(5d091941,5130a8b8,923c8784,e6881f4c,16afb496,7dce4a08,ae480825,f92f5517) Z8(7e4eabf3,607df764,994b23d3,adf6ea40,3e82710e,f01fe0f6,8ad4bc3e,62257bda) Z8(f61f6762,f22f164b,2efa0591,945b6eb5,aeb92097,2cccb633,24546d9b,0844eb49) Z8(5abe6ae4,85646629,30f8b40f,584eb597,94c7a512,7bfde352,e2774375,48331c09) Z8(555152bc,0b70a74a,ba9a9f17,8d823963,f1545bab,8a7f9869,ae2388f8,29fa7dd4) Z8(24020b86,f3a5aeed,50c100b1,135c2400,f79e495c,db5d0d2e,ffbf335c,ffee0035) },{ Z8(e1ae2b31,ca61c955,b4bc74b8,b9b1a066,51b6abef,ea021cd3,37e7f457,1ec67a4d) Z8(955c8e48,017bac80,8e3f68a0,d8a8f5a4,8c7a1323,dce0965c,f7239f64,9725439c) Z8(760a2c35,c6f294e8,2a883723,d8954b9e,a0e025a4,51484942,51f7a26a,2d1a63d5) Z8(f8da989e,0c5b4977,285a8371,53b35da6,b68a5808,fe4575ee,96795715,3805f411) Z8(1843c2a7,85bbbe79,34d6a09f,2ecbf9a0,c0e00ab4,878404a8,47e0cee4,a0f69069) Z8(18d7f17b,8e0fa1d6,a0febc4f,7b85e28f,be4d9e06,cb5f553b,6ed004ef,cdf2dadf) Z8(64bb24ff,bf6e7fb2,6238dbaf,99c9aaf1,04df4863,33413514,8649a531,2bf323e7) Z8(656abf16,79b90351,1d1a8e4a,ccd923c8,a879cda4,76f39105,b7c9ccf8,61bf41ab) Z8(4d7cbdb8,bbcab29c,496c78ae,067d3232,fc67646c,d67e0d28,edbdafe8,7ddf1865) Z8(280cbc72,f3e7b2e0,e8dfa028,7b55baf9,26283819,5dd6d555,03992136,1becd708) Z8(7ed2d4e2,f6f9215b,8b51832f,7ea3ff72,a9da44da,547bd527,6e861d6a,b0fe7a64) Z8(2b9ca4b6,82826df3,a9a0394a,eecf6eee,421e75cd,50380244,4a5b7991,fae6aebf) Z8(43cd7c61,22ec7467,315c2261,015f5567,8991c20e,d2d02a6a,2b0619f4,f41c353e) Z8(23b417bd,ad89fd2f,d10f20f3,22fed282,17ad64fb,ee42e729,dbbf6ac3,0618480c) Z8(3e4794ef,6b0960d1,6ec26037,2bce6b3f,d90a3870,b19d9cf4,bdf70ae1,2af4d930) Z8(cd027ecd,d1f97581,1313b548,22ab959c,a42db987,a47912aa,65b0ed2f,6352e4e8) Z8(0fb568de,661c0206,328735af,07e9a6af,1bc05584,097bf812,e210509b,5d6ed45f) Z8(ce86ffee,01653978,7d7c212c,9c1a33dd,b74d3b7e,b6bf6edd,a4ce18c0,063fd74f) },{ Z8(94f5267f,5d7b9178,364eaafb,14fb3c5d,5c7e6961,d11a658f,63b955fa,66723e98) Z8(39a82630,90dd51b9,7087571b,8778eb47,a0f13d33,39fe5cf4,53153f78,ac563a84) Z8(2b5ba059,74b03a9f,710a5c6d,d0bac4df,901e1a09,d922a155,b77d193a,db72b1d2) Z8(7a628035,f79099bd,517c1aee,4f22de96,10e263d7,9d31cb8b,121178da,0bd6cd4c) Z8(de332b82,221b4e53,8e101ed9,ac18eb93,2d8584c0,12632c47,03219fff,ff13d660) Z8(025da9eb,d47dd418,3161d960,013a6099,2c423f81,5a9a7f99,f19aa012,836a9ec0) Z8(338762f6,cc9bc351,93bc83c7,e3f1382b,9f6e61df,77d4c8e8,00b5b4d4,22fa54ee) Z8(add9a4f6,597d453f,a41e2d34,82d7aa61,5f797ec8,d2e91709,c08f0b05,4b27a624) Z8(57e8da2b,0bcfd5ae,52533c87,af5c0601,cc44ae0e,ce6785f0,9d797141,76bd3674) Z8(5631939a,07739044,6fc2ca82,472fb44c,8a9a887a,3831e072,224aa081,39085bfd) Z8(00b8491f,3f7de85a,f9ae56c8,70a4556d,7ccc3048,5454fdbb,6d7043a6,dd04807f) Z8(1c8ca0c1,3506d46a,8695d151,3984f187,9b38972a,b711fc44,1f186284,dc95e914) Z8(df09a7de,bcc2e6f2,9e3768d4,19fcade0,c10b3cd4,3bcbab30,5b39b5c7,ba9c61bd) Z8(23e83258,d43c02b4,b8d4a3ed,7862ac89,10e51140,49bb767b,2a78254a,92807039) Z8(26f61423,39f78c88,9a5a1bf1,ee6cbbb4,d36d67ca,f67ae4a6,efeea53d,06846e8a) Z8(a6b93786,2d6f904c,c5dbbf7c,2a70fcfe,a6c20269,d20e7918,fbb5dc8e,4c26343a) Z8(b7a365a9,7b08ddeb,0ed1661f,46d680ac,40d06d94,b7a9af12,7465dae3,e4d6f3cb) Z8(1b56d0b5,413d53d4,4e9a0efb,ba1aadf2,d82900ab,3093f040,93b7e221,ffec783f) },{ Z8(eec4ab0e,ffb61eec,ee1613b0,f8a18a45,9013aab0,dcc3f76c,eb2e8d73,a7e9cfeb) Z8(f9450a25,bc1edfb9,e63ab97d,ffaa1c3f,ee7f63df,3d1e3fa8,3a93190e,0d5734e5) Z8(e1bc8b99,2de17285,d816a689,c1769d6f,6d83a50a,8b0782ba,5d79dac3,bd7ef6e2) Z8(4ba292cb,514b6225,69c065bd,d304530e,663003ef,58ec33cc,43b5636d,2fc66674) Z8(1a83dd07,ec7fa619,d420db42,202e8100,a32d67ce,02cd1bcb,be21f2f5,9fe7005f) Z8(5ac4576b,77473c94,359fc3b2,f9d3bb45,91050304,5f46e951,67348ddc,03525c78) Z8(032327d1,115983ca,ee365180,0976c571,f39e5802,a7978768,e02e8946,a81cfde0) Z8(fac9e295,521cea91,18396379,525133d9,ee30c410,7f06e878,95c54d76,b48aadd9) Z8(87c49418,9def9f98,5131874e,6674d559,956e2b26,09b77a70,69f1aea2,53d744fe) Z8(169a09b1,10c4ef89,d8904003,027b8341,8758ecee,dbf4395a,9dc4d213,2b0e97c1) Z8(068d9f30,c24f7c01,059892ba,d9402453,30152b5e,099b6a4e,6e3801b8,fbd11f81) Z8(a571b75e,e414cb06,96116b50,a760c300,ed3890cb,fb06801e,c68d2f72,e7fd9f5e) Z8(75862281,166ff3fe,b7678be8,95f4d6c9,9b8f1319,e93b588d,c6c15b52,60bdcb2c) Z8(a7161cc6,461ccb6b,491fb7e3,a6be37b1,6ea81422,21140f9b,a13059f4,5bf3b8b7) Z8(c6773042,20646d44,5a39fe2c,e302f93a,655e3e42,14206cfa,faec3898,a6e89a8d) Z8(6a3e7af2,2da2b9a1,d92aeecd,541b8db1,9aacaaed,b60c567f,e0d2b088,f84bc1d5) Z8(3f1dfc77,f6dccb87,b03aa937,dc9652f0,d8096eb0,be7ab42f,22a43a24,6f248807) Z8(df94ab7e,110d1bdd,3c42e8e2,da1785c9,f60e9ab7,8d16be6e,0b5b2744,067fd23b) },{ Z8(3a76c04f,aeedd18f,06fe41cd,0bfe25bc,1abce867,f358eac5,04f6f923,6f5f0cfb) Z8(3bb04525,8e869c83,0bffeba4,a842b81f,c827312e,0aeea878,6938b390,8cd542c4) Z8(31b4e49e,3947da8b,28ed52fd,bc0265a5,79a510de,d2c6ea76,0c5f0c83,4a6e7c41) Z8(2d593159,4983f611,0ae42d3c,3bae6059,6344191c,e8458e09,e73149c5,8887ceed) Z8(ba0beb05,e24306d2,a70099d4,7b5378c3,d36a3f5d,a8fcc154,ddf53297,668b6922) Z8(6741087c,1ea6ad62,9984a0f6,1ff23751,06bdf793,af24f7bb,c0795543,494b9e78) Z8(9aa3f14a,21538ff6,c92ef8cd,22fce0e7,c2f65f24,7414316a,f71afa15,4efa50e9) Z8(99cb626d,00da2e57,a86be69a,7a16336f,3f62e83e,094318f6,b1ac3d07,148ab348) Z8(451450de,8548667c,c130b237,6555c85a,ca1676f9,cca0c7c5,e6911d0d,013248dd) Z8(cd93188a,0e2bbdbf,96f38221,c1059935,d416d6ed,514175b0,71941955,b0fd8585) Z8(320b8e0f,66ed7f7c,3064bc3d,c042f1bd,3c18bdaf,362f0fed,dfaa31ad,96a39d76) Z8(19f90ee8,cdee5070,3bb6281c,bfc59d48,a663bdb7,5f4df90d,50538e87,b8a16188) Z8(cacd4673,2da7b0da,ad1ac901,7bc0fd1a,bf19626e,0025eeee,99cbab0c,b9059fc2) Z8(5458b4d9,48986484,f3e1701d,2da9c918,b219c905,5c8eab1c,fdb61250,6559c18a) Z8(8ec3ee7c,e6fb7487,a62e4d85,07eebf24,44ac89d0,72a31dc0,329f4c32,5a4536a5) Z8(3347ebb8,37b1993c,36ebcdac,9616b918,fdb20335,a9e784b7,977e87d7,6c84828b) Z8(6820c3fb,88689982,1db7caa5,99988758,899c8c0c,1bdd50f9,c6067da6,628a6eb6) Z8(7ac4fecd,dc09c364,835ccaba,76e7290c,ebe2e84e,ac3fe274,6041eb5e,ffeae04a) },{ Z8(00c9f09c,8702bc5a,f2bac302,044d5061,94d26d40,945f9774,5e010f8e,308e0529) Z8(2eef9e92,a4f1b676,d1bd82f8,10f5a90d,b5b98b3e,a7e64122,f0b5ca81,2029ca83) Z8(e2b30c63,06d61c95,128ea09b,b20d3602,8889a030,6338a379,0ba873e2,3b0413c6) Z8(ec42f0f8,e709f1a7,49d1a87e,296508fa,acc722ef,dbe78f5d,d1a79e6f,a91a7113) Z8(d662bd18,409fc8d6,26e11cd0,ab9b5ab8,7cc202d5,4fb1d928,597a0aed,140052d3) Z8(6b4b462b,c4bc7de0,633e7915,db110fb5,596befd9,f58e7cbb,54d7db8f,6b838c37) Z8(347a379d,e939275a,1075a55b,2a1ea2b5,6eed7072,c189fd2a,7b9fdead,428dc9a8) Z8(0800c776,9c26414c,377c863c,a73c0139,e042d507,2eb794f2,852f2604,165c2d38) Z8(d717807e,e8063cb0,e820aba8,45702e91,ed1c8d69,9c270471,eacd3e5b,53892eb8) Z8(a010ad0f,f2f18d8a,bd015c36,533a232a,e8a19c93,eb13a4cb,d3888ae5,70a2c4ac) Z8(dfdd16c1,4db70723,0c880410,99c1a24c,5c15f3d8,b10db17d,88560b4d,515a685b) Z8(c8bc1f21,72714d62,cb3b83aa,3c9fbeb8,2ed597ba,5f923234,28db9eba,616316ba) Z8(b88aaf04,7a8d900b,0c635ff4,c35d8414,a14cec5c,8c452632,5cac2895,67bf08e2) Z8(ad0fbe66,bc7c75fd,70dc49df,be415944,a991373e,f9900e4f,85fac335,3cf6c610) Z8(d5a616a3,4d41299f,846f463b,4887f7cc,8f342d1b,04164174,19678503,96dd73f0) Z8(a6720ffd,9eafc78a,900d618a,1ab89e67,a17bea60,49f03dc0,e4308067,f347f1fa) Z8(d56ba800,89470e8c,8ac3e462,c7906e3f,d8f91c20,ebf7a5b4,af416325,a97f8639) Z8(a6c40ba0,40c67438,e53cba02,81a6de42,9ab676ed,8af0c4db,74c50fb9,06bfccbe) },{ Z8(b60366bf,6cc54c75,fe18d496,4da77ea6,49d49305,a69609ad,b8808b0e,d01938e2) Z8(7a93235b,b3de603a,8a9ace50,09f5b452,f8efc7a3,17632bf3,e97d1e1e,015ff767) Z8(53fd618a,0f859294,fad81d80,4c91c7b5,c018687c,81888164,a0d95acc,d4e55c26) Z8(6a8d45fe,7c3d0608,0cc36e83,6e74c915,11d09578,9fc64253,a5028070,21db87ec) Z8(ba839ef8,d1829e34,e23d9139,2f727d57,ea49b660,6319e47e,bbc2b2c9,50aa08e1) Z8(bbaf42ba,178d953b,ed0184fa,f6ed1a5f,7e7bba4b,9d142c01,292294e1,ce3dcbda) Z8(edb2189d,38b96160,d1c7a7c6,90264f8e,5e2b8a53,af8e2c81,80eb386b,097e7860) Z8(9fac1544,159e6f5a,e747c496,42b512a8,bd095aba,6f66e820,e761beb5,c7215616) Z8(05bccd53,7bec3faf,62dfe0fd,c6b17391,91c0d0a3,8f9d684f,aac2cc59,c32336a6) Z8(c4b3ec2d,20bb565c,5b6d9dee,a594b5c1,459436f6,5e14e633,d7684a42,efacb58f) Z8(2208eaef,9ee7e916,c7806883,5f2bb42a,5cbcb93b,7f2a2cf2,b89c60d8,d3fcaa85) Z8(1f826b1b,26179226,3a19dfd0,dcbf8f2f,980b295b,8c3c664f,15a5ba00,9e4fb8ba) Z8(504589d5,21f9009e,123733a2,d6ddfb0a,39a3e61d,85789b5d,b780ca20,e84c45cb) Z8(1b0e0e6e,40fb1f22,0caffb40,e5884c5b,d0f7e460,30cec49b,3508af73,f2daeea5) Z8(d2d8f94e,27abd448,2903f30c,7dbcb929,8186a2e7,0b393700,77340556,d46dc973) Z8(d82731ff,7448cd19,4aa14539,fd410b65,8852246a,96c0872a,fe96a5dd,58e02e86) Z8(d7615cd9,5c07a6e1,433575af,c61e54b9,ecbc6d41,fc9fdb2a,042e1cec,dc46c8f0) Z8(f83e8ba4,a3e40661,c1c37011,c18511b8,355c5beb,aeb37f08,7edca22a,ffe93856) },{ Z8(f5083898,ca7aa421,1692e5e9,99127133,f75e2bd9,aa0a6392,d4b3ec6a,152d0b5e) Z8(6475ca86,75271b17,c8a155e9,c7ba8ec1,29e58d31,07f06c39,dac1214d,fc56d0a2) Z8(bbbce99c,d26f438f,b5cad56f,39ce4e2a,1df2677a,c05d81a0,0d1f82bc,adc81084) Z8(505773d3,64c5a818,eeb34c90,2b3f2e06,1ca43ae2,cc132820,a25266d9,7da4ef8d) Z8(aa4c0517,f0c68094,b9393b06,63cdaa56,1c8bc744,39cc0483,75653b9a,c8686a43) Z8(1945ecb6,263b4452,b38a3dd4,73b7074d,3d27c37e,b7bcbac6,430be3b9,9957fe50) Z8(4b8f50a7,4b52bb13,a964462d,c7005ee5,c4ef03ed,5a8f25f6,e4443ce0,589cd340) Z8(4f25dfc6,1694b28d,2025c938,a4a28ee5,190f52d6,e1693d95,83f13e25,3817d651) Z8(d05990c9,39285fbd,0887dd02,ebb2edb3,c582c3a6,67cf9a7e,9a78f6c7,4bfe5128) Z8(b39c759d,9b856bd5,411775cf,ec3ed91d,9217b22e,970992d0,9e7d812d,6d9e6bfc) Z8(229371e9,6d8fa7c0,e446fa8f,acfee884,a450b161,5641f8f8,3ea7ebfd,b4a46f7d) Z8(5bb21d3f,aa389162,84f2d9e3,28e24647,977991e8,5e14260a,f09cc690,0bf4219f) Z8(b21e09d7,996c9e54,c16fb459,a4829b41,c639bc03,cbc848d9,d04d56b4,cbdd5f45) Z8(13178492,780be53b,0c828e9a,e150d397,4dcb40ed,bb476b78,937bb97e,e0d10695) Z8(0e8d0c2b,8f136af1,c2f4ee40,0c1f399d,2b67877b,b4f10119,0616d700,d90d3618) Z8(820b8870,aa57260b,a3f8c7f9,6c147ef4,0bedee10,f8be03bf,c88b87b6,0f568cce) Z8(2e956a62,54707381,b634a0df,4304d14f,986f637c,02c0513f,a293758b,51d78b0e) Z8(a7332c80,bcb27f61,d2358820,03e277d3,4f02b7c5,f20c232a,e163a0dd,06ffc6d5) },{ Z8(3168392f,824f6319,6a768e1a,89455c4c,49d4ba77,d90a3424,03fe5c73,6ef45fff) Z8(eef0dea2,0c67aa7c,292dee00,cf0fbd4e,bb417849,2b2c093a,1360208f,81737528) Z8(a2f551c5,fb77140d,ba6599c8,11d7107f,961c27aa,555ae8d6,960b9fa7,bac96c16) Z8(6b560476,21a3194e,61a7dc78,50ab88de,eac7ab91,7222d170,dcdf5e29,29ee04fc) Z8(8f0d8d41,35813120,38873052,fb72f092,87819ab6,373e5825,332ca43b,38a3b938) Z8(76ee2a63,e36bf7e0,306afd4e,46c366bb,1b1ace42,578bb7c4,af55c32e,e69a94b1) Z8(36584b6b,fc4fe710,c011e17a,1b90c6af,f5e65121,f602e5be,c8feee2a,a5f11bc6) Z8(93525375,03ac22a0,0ade8b16,58b2bcfb,29fad303,b9f4a00f,33501a21,646ea2a9) Z8(a274cfca,7d82b577,40863707,973c8f41,7969ae62,e00ccc2c,07337e53,6f31cd9e) Z8(5c8c707d,8af4a9f1,0f7ed350,fa0ba7fe,c3c0c72f,bcfbdc34,e8b2e34c,2234108b) Z8(b88ab5c0,6ec79dc9,6a73db02,d65b5eaf,3240346e,134302bf,6cb42e9b,8be15750) Z8(aba831fa,b05b0b6d,bd763849,c0807ff4,ae3a9a7b,e3f0ee91,6e3b8321,23e316dc) Z8(bd3bdeb5,392c946e,aef58b25,894228f9,17aac9e7,fa90632f,e8f217d3,53ce8107) Z8(e1a3577d,04dbe248,a368534a,2e7550a6,2649c69c,bcabadfe,637eef8c,6b03873e) Z8(9134d7a6,68bcddbf,882b0053,2509f977,243f98ea,13f88527,70222412,68f3b7df) Z8(e75924b5,f3f1104c,d6384f68,1b175c93,2dbfef1e,012eeb06,bbcac937,9afeb860) Z8(b2849471,f41b4606,fa909aed,3958ae98,d8b099fd,0463c8a9,5a06813c,e1bc72de) Z8(9bd85d30,80c5648e,373fe8f1,4ab4504c,5a0fbdb7,382f503a,0a074478,ffe78064) },{ Z8(99a5ff40,ed250449,91b175ba,7ce808ca,5e9c714d,5eab5fb2,c2f58fc7,b35482ea) Z8(150e2be5,9b71aa01,7aeba496,e0b916d6,624484f3,c8b87e7c,fef84e0b,30f25173) Z8(a88823df,2b88494e,078b5e46,759991fe,18f06758,1a1a777c,cb37e23c,b50895c2) Z8(433a5350,5294850f,b7b08889,d50b756b,7d799cd7,2306cb43,7a505cb0,8c9173eb) Z8(e91b8abf,ead9967c,50555741,f91647bc,94328d82,75825f60,9d83ba08,6120cdb7) Z8(5dc8a264,ca8e7c04,4871c7fe,a0715596,082a8ce2,5a56eb43,68d6432f,2dbf038e) Z8(dfb66c5f,87cd53c2,91a424c2,08f5b1d5,2e47ea89,d6cf62e5,778db7e9,a1fde7cd) Z8(26fd0e9a,999430f9,26cd65c7,5ccb9dcd,3c9ffc4a,bfebd3b2,99af36e5,aa6e7f9e) Z8(e8e8a12c,272adace,a88d7b25,95c39020,baf7b80c,52ba9ea9,9026c37a,41910935) Z8(c6d715d1,1203e36d,5e93aa68,68df2a16,f7a3443f,83a53fa6,c261cd78,e3b167c6) Z8(0ce3a657,750574c6,dc6262c4,b9a35586,e097c678,76d5f9a6,1e832085,d0ec1f75) Z8(e68a28ed,9a890b5a,2d5e3988,fbdd1960,29aa5b7c,61b4f832,9465fa96,85779941) Z8(c910720e,fb2db811,377dec5d,1bebbe3f,7a33781c,4b6cc7b2,cbcc94c6,c8475f8e) Z8(7cf89e15,eab94e2f,35833b7e,afe0d908,6462a58e,5eb1834a,2e3bb012,5e399540) Z8(ec8642e7,05a00180,61b2d1eb,947effe1,0300c3a3,5653a525,4b872d67,261941bd) Z8(057defe9,612fa5af,381c22e7,86dca66a,36132a9a,eae074ec,4ed97e7d,1de20a19) Z8(06acae3a,e8f61e64,75d6bde9,9c4f66da,6ffd0348,76bede27,9c6fc57b,4bf8b364) Z8(77c8377b,8075646b,918c1bd7,955a9c52,d7cee62d,b09cc835,5195693c,073fc07d) },{ Z8(ffb0352a,a97a36af,07793aec,ddc60323,bedc8893,3b3192a7,8418c193,72ee8e7d) Z8(04528bfb,1867c2af,aeb7fe11,2075dd47,674da3f7,dee403fe,03168e44,01d14e26) Z8(3724f526,1f663e44,21dc8e6c,c06e1c60,d62aaccf,ca8c9dc3,108d749e,7e4bf24a) Z8(ef0d3616,2b4b2e3d,671306f1,23e6722c,c3aa314d,59bf9975,a63d302c,95e698c8) Z8(fe9e52d6,1903bc0c,3511470e,a6a4a515,bad8d052,f69ef44b,e52750bf,2b1b5ba1) Z8(db298952,cac0570d,e1060394,c6af2f69,1e1d3d77,432bbaf8,5c2fbbc7,b32ff79a) Z8(cc092865,cb8f7e2d,7e4fe5eb,d8795b13,75f90d2e,a4e98d1a,f0ba5a78,f1b29487) Z8(19366f50,340fd506,aabd0a13,c81dbcd7,547492b4,81e22300,35797bac,f51a7800) Z8(aaffce9c,80cbffac,920f1664,da4dab9d,aa1fa44d,bea6d729,22a54e21,3236c571) Z8(cef026cf,d3a8b4f8,6c27be72,b86015cb,0e03a8d1,efa5cbbd,4152be9f,25324c91) Z8(cc7c3164,491d48ed,ed793ca6,8fcb181e,cccc21d4,5e8e03e7,d827c697,5c2e8ec3) Z8(0eeb8bdf,c24443b0,44a947aa,eb12320b,cbf42b9b,1501a7bc,a0506d75,71994b92) Z8(205b238e,561cb8eb,24a3fd9c,f48d0da6,79270be2,d653ad49,7eea2258,d26f15cf) Z8(7fbd7818,29dbc73c,cf2f706f,24451f1a,da786a2b,5e2c948b,571c01a1,ecdee7ca) Z8(55c08ff2,e3ca67d4,e7aab3ab,46bb434f,0c6e19aa,3916a6ce,0cb9fa02,7922119a) Z8(9586696b,0e3005bd,d82b4410,941712fe,dd979139,5ac8d1f7,ae1042d4,c3da4846) Z8(49a8f053,99e2c18d,c8e63104,1414c6d5,32ac61b1,6721bd39,87b9e915,74ab7627) Z8(7b8da3b0,8f42a7ee,fc987924,8c8185ab,c2255c97,f504d48e,1d40f96f,ffe5b873) },{ Z8(cc8afa8a,ab7b19f0,4dc42e10,b48153f3,18cd1bdf,b7416084,6759b67c,9aec99af) Z8(665478cb,353dc8d8,d9a78522,180cc22a,5a3b5459,04e5bd03,5831acec,265ec10a) Z8(463c950e,254e017a,d1a1eed0,c5a50704,4aa2d6b5,4c9974ef,c12739ad,b5c839ec) Z8(230261b6,cd3d9cf1,c7513394,845d14c6,f9e6335e,a6ed7865,5205275c,612dea0f) Z8(bcef932a,ec6c6b2b,9d157def,1b6a7548,ee7d6b74,75d48305,f39eb96a,a28c7998) Z8(20440fe3,3bd29d55,49c291c1,f9aacf1d,f8ca1e32,f625bf0f,dee6c223,a204de88) Z8(943a9d62,50f0abc3,d88dd1ee,f59eb5e9,e65c8d20,7155ea75,44361b4d,6949f210) Z8(1fbfdf0e,53bc45b5,6c294663,60c5fa6c,53e9985e,bfbcf8a6,85abed98,28769f24) Z8(8d3c926e,fdcb674e,49aa391b,4b1152d3,567a6231,ec3b422b,8a9e661f,2ae13ad9) Z8(06aa76ae,7dc3212a,456936b6,7884c959,017e8f59,e201fc39,e64b073b,ec6f9850) Z8(4c6eecb3,595f6e8d,a0283666,77c6a0ec,544bfc50,1f256417,6d006a37,b1db2887) Z8(f264ae7a,3775ef65,87e14ef7,a538203d,60b12b3e,03d32f7f,f8dd70d1,0d47b82e) Z8(ae73ef90,ccd2a182,5640e820,3588cf3a,f5e5355c,dfc34545,4c957c3e,205dcd6b) Z8(f9a9567f,db31686f,372d2831,c635315b,9660e977,40b67003,b2281c96,02b4fb0d) Z8(d55e0622,754daf29,5ea19f13,e1959f03,9c97bd76,345233c6,5884ab38,8ac56592) Z8(c2adf480,c0250371,8c9ad0a5,39f0b078,1c0fe62b,ad19a564,856db36b,66cdbdca) Z8(1348c050,c3960698,28f39bf4,8a330217,0143c678,82e781f4,ceda6eee,fc135a98) Z8(602c315e,358d5e18,cf92e53f,e11d1c70,e48e5358,780df455,c5bff727,077fb9b0) },{ Z8(c2249889,03363e8d,c216b563,aa7097bf,c23f2095,deb8649b,c7ad3b5e,000620b3) Z8(6d8ff8de,093d654a,3bbe901e,4a88b2a3,a776dee4,b83881da,0064983f,2626dfdc) Z8(e43b5380,88a0a954,e67ea023,f8a0c097,6f449d75,fbc7a82f,81e84ab1,4352371d) Z8(8b0b59ef,1c2b1527,c4894555,053ec7a9,62a9c896,b8b50b62,1d569a82,e0ccedd5) Z8(177343e6,915b2beb,f7f8e36b,917d1be4,d12ddfe8,e50405f7,c2f80eb0,cafa8e8c) Z8(87433dc2,65bc5246,49cb69e5,288629a4,126af65f,36a67be0,cae9c873,5232af1a) Z8(cfc77839,4872deb5,df522260,eb802ac6,5c132b14,80e2dba7,75d046a8,5ab94e89) Z8(dcb1e85a,663cc10b,cdb813b0,e977750c,d02e951c,e473d63b,6ac1e49c,974583e9) Z8(aced11a2,e724ce93,24b1c5cd,610af596,169611f1,c4d755d3,16e2b859,3c893f59) Z8(efc087eb,91bb54aa,814382bc,0c67f681,9cf7037d,9654525a,90f0ca8a,22d80880) Z8(730a64b0,242b02a5,4b2f0278,ac9c9e9f,96830d7e,ff226fde,3f149f2e,6a4f224d) Z8(934ab39e,db28a312,8dd94b4e,7ffeff23,eb6498b3,61bb0f09,77e1a933,d9ecd5de) Z8(b20beea8,a7284ff8,db7a4324,4777aed5,fa197128,a78f8e67,84015b38,1fded28b) Z8(0beb6869,4c149190,1850f478,bcf87632,4f045fd8,aa51dbbe,e12fb274,53da86be) Z8(bf6790bb,8ab9c0d6,e7f9c881,90e29df9,cdda1be9,cb907d5c,db91e0b7,3567279e) Z8(4ac9e39e,379487fc,7226006a,91b9f4ed,4f496f92,5cbd5e68,da6e21b4,077c5dfb) Z8(6703a645,6f35d80e,67a160b1,0dd3d997,caf13d7e,48ca1222,4a9f00bf,2edfde4a) Z8(8d72ed4c,c95d63bf,cd24476c,1c54dd30,180b6a83,4b263ea0,d508cfb8,ffe3e083) },{ Z8(d0af47f2,fff68991,0c4f4089,798d9e9d,026d4904,4cd285ea,9e9123c9,13eba9f4) Z8(20f01965,32fded1a,09f67dfe,e11720c0,f5cae49d,4ddb6257,c035386c,edb9f29a) Z8(ba205689,41f7624b,15dcc811,784ea3e1,a45be301,972c5fc1,e3106665,7142d42d) Z8(f228a918,54997f8c,99ca57ec,5ad49717,ef8f3811,782cf04f,8bf5a502,581183ce) Z8(5e2c7cde,c2b51430,671cac5a,b7771b04,bcbf732c,5af858da,e8a389bc,2e4642a5) Z8(222cd6fa,6a2fde63,5db1df9b,30b46d52,d9442711,801f9095,9102bea8,b9184a7d) Z8(6321034b,da48ac33,8ede6674,fee0f96c,a8289ecd,92cd1cd9,51bca194,618a3e4d) Z8(b89c4cd3,3c1a3263,7786cfc2,aa0f1fce,003fc678,3be611b8,d7ab2b24,2aa15d8b) Z8(e739dcd2,2f90cf28,0267fbcd,30422e44,0140c51b,d73da67d,8a59d886,426b19d2) Z8(bbf70664,b49aaf4a,62e3cb4a,20319960,a6dea411,2d463c91,cbf80414,e8e8d7f7) Z8(d631f996,1ca60f9e,46db5a26,50ae5f8b,7ee74da1,4eb3c065,7aa2dbf2,64ea2ff7) Z8(ba994626,b3722d67,91ea6a1f,d962515c,64561234,367a6190,8a75f681,37e9ec59) Z8(60a66da3,061686fe,c701fced,b4c85e67,e92dddfe,08f1e6ab,797493bd,ee04d7a2) Z8(99a6f3be,1c59f59f,8309a279,94ce05b5,f0ad121d,7aa1215a,ec334796,52b639df) Z8(0981786e,905d83dc,91508790,b06e2087,97ad3716,63b5eee0,c4fa5bb2,bb92ec09) Z8(1d843143,dd2c810c,45359f2c,414e05db,a37dfac8,ab989866,24535faa,0426ac56) Z8(a9121bef,c59edbb2,72e0ac36,27df521a,c32d5cf6,58971e70,47da7ebd,0d02503c) Z8(73905803,1680c4b6,c4de8419,effa116c,ba3e6603,63c7d169,3e5018b0,07bfb26c) },{ Z8(deec5c26,db8ed1a7,05bd7d1d,4fd38b06,3367b1eb,05e2570e,b14207d3,1d07a4ac) Z8(d11a1dcd,c77989c5,9bed1249,05ecb233,f533352b,eba8b51f,973a69bb,f9a79603) Z8(0a204b77,919178b8,2134b24a,68e08353,8c3da985,e1fbeda1,d7816d8c,684e6a74) Z8(b80d3c1a,64401998,63d32ead,2ac2f24e,28217c8e,f21317c2,6bc3ee14,2098ed29) Z8(a5830a59,0ad4e504,4d25ed24,3440e93c,fffaf097,1492a6ed,862f915e,63b7e836) Z8(afa228b0,49bd1db7,d146c767,3d40ad9e,bf64c3b6,3bce64f3,e7b0bea6,d2b29a4d) Z8(0603cc19,9783ab12,ab8d53f6,036259ab,30a24b86,32a47654,cb202c34,a5a39278) Z8(cab13889,531ec96d,dccbea36,3cf9fa24,4e2597fd,35cf8e51,709a5e8a,28fdb81a) Z8(8d44b046,3053b695,7157ea17,0578864a,27a0fcf9,e76d9305,8bbc6f44,bcdece62) Z8(23b24595,fb93441e,426d2535,de660905,d51df433,1c11b677,c0288110,e0767420) Z8(e5455b20,c705ae7c,b90a24b4,32bd9ef9,4e3ddd65,63921798,4cdeb18a,da61b9e2) Z8(45bb25a6,ea960a01,542e6c62,6250c141,beffe55a,e07d8b20,1d22f180,8fb3ee17) Z8(c849557d,4da47aba,8a81ae40,465492db,81ae1a10,e9e4358c,8e3fed91,46560d4f) Z8(e21b660b,d8da90c0,6a3661cd,ad71cc57,61ba637f,8769953d,fad12744,b2f6c867) Z8(caa48e0d,e9287446,0798d8a0,14f74eb5,5ef39dcc,9f5ff1e1,c9e99daa,9ea35b57) Z8(34529182,f6f71374,81b29466,4fc50765,12fe4f23,31ee72a0,adb91867,aef63b1e) Z8(6d843aa5,68dad114,fa7dd2a0,2207284f,50bffa10,d862be6f,36f2b1d6,37bf5acb) Z8(28028625,d4aeb2b1,b86cbdad,1e98172a,073b41d4,693e6ead,4eddbbad,ffe1f896) }}; flint-3.1.3/src/arb/sin_cos_taylor_naive.c000066400000000000000000000037721461254215100205540ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" void _arb_sin_cos_taylor_naive(mp_ptr ysin, mp_ptr ycos, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N) { ulong k; mp_ptr s, s2, t, u, v; mp_size_t nn = xn + 1; if (N == 0) { flint_mpn_zero(ysin, xn); flint_mpn_zero(ycos, xn); error[0] = 0; return; } s = flint_malloc(sizeof(mp_limb_t) * (nn + 1)); s2 = flint_malloc(sizeof(mp_limb_t) * (nn + 1)); t = flint_malloc(sizeof(mp_limb_t) * nn); v = flint_malloc(sizeof(mp_limb_t) * nn); u = flint_malloc(sizeof(mp_limb_t) * 2 * nn); /* s = 1 */ flint_mpn_zero(s, nn); s[nn] = 1; /* s2 = 0 */ flint_mpn_zero(s2, nn + 1); /* t = v = x */ flint_mpn_zero(t, nn); flint_mpn_copyi(t + 1, x, xn); flint_mpn_copyi(v, t, nn); for (k = 1; k < 2 * N; k++) { if (k % 4 == 0) s[nn] += mpn_add_n(s, s, t, nn); else if (k % 4 == 1) s2[nn] += mpn_add_n(s2, s2, t, nn); else if (k % 4 == 2) s[nn] -= mpn_sub_n(s, s, t, nn); else s2[nn] -= mpn_sub_n(s2, s2, t, nn); /* t = t * x / (k + 1) */ flint_mpn_mul_n(u, t, v, nn); flint_mpn_copyi(t, u + nn, nn); mpn_divrem_1(t, 0, t, nn, k + 1); } if (s[nn] != 0) { flint_mpn_store(ycos, xn, LIMB_ONES); flint_mpn_copyi(ysin, s2 + 1, xn); } else { flint_mpn_copyi(ycos, s + 1, xn); flint_mpn_copyi(ysin, s2 + 1, xn); } error[0] = 2; flint_free(s); flint_free(s2); flint_free(t); flint_free(u); flint_free(v); } flint-3.1.3/src/arb/sin_cos_taylor_rs.c000066400000000000000000000117371461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" /* See verify_taylor.py for code to generate tables and proof of correctness */ #define TMP_ALLOC_LIMBS(size) TMP_ALLOC((size) * sizeof(mp_limb_t)) #define FACTORIAL_TAB_SIZE 288 FLINT_DLL extern const mp_limb_t factorial_tab_numer[FACTORIAL_TAB_SIZE]; FLINT_DLL extern const mp_limb_t factorial_tab_denom[FACTORIAL_TAB_SIZE]; void _arb_sin_cos_taylor_rs(mp_ptr ysin, mp_ptr ycos, mp_limb_t * error, mp_srcptr x, mp_size_t xn, ulong N, int sinonly, int alternating) { mp_ptr s, t, xpow; mp_limb_t new_denom, old_denom, c; slong power, k, m; int cosorsin; TMP_INIT; TMP_START; if (2 * N >= FACTORIAL_TAB_SIZE - 1) { flint_throw(FLINT_ERROR, "_arb_sin_cos_taylor_rs: N too large!\n"); } if (N <= 1) { if (N == 0) { flint_mpn_zero(ysin, xn); if (!sinonly) flint_mpn_zero(ycos, xn); error[0] = 0; } else if (N == 1) { flint_mpn_copyi(ysin, x, xn); if (!sinonly) flint_mpn_store(ycos, xn, LIMB_ONES); error[0] = 1; } } else { /* Choose m ~= sqrt(num_terms) (m must be even, >= 2) */ m = 2; while (m * m < N) m += 2; /* todo: merge allocations */ xpow = TMP_ALLOC_LIMBS((m + 1) * xn); s = TMP_ALLOC_LIMBS(xn + 2); t = TMP_ALLOC_LIMBS(2 * xn + 2); /* todo: 1 limb too much? */ /* higher index ---> */ /* | ---xn--- | */ /* xpow = | | x^m | x^(m-1) | ... | x^2 | x | */ #define XPOW_WRITE(__k) (xpow + (m - (__k)) * xn) #define XPOW_READ(__k) (xpow + (m - (__k) + 1) * xn) flint_mpn_sqr(XPOW_WRITE(1), x, xn); flint_mpn_sqr(XPOW_WRITE(2), XPOW_READ(1), xn); for (k = 4; k <= m; k += 2) { flint_mpn_mul_n(XPOW_WRITE(k - 1), XPOW_READ(k / 2), XPOW_READ(k / 2 - 1), xn); flint_mpn_sqr(XPOW_WRITE(k), XPOW_READ(k / 2), xn); } for (cosorsin = sinonly; cosorsin < 2; cosorsin++) { flint_mpn_zero(s, xn + 1); /* todo: skip one nonscalar multiplication (use x^m) when starting on x^0 */ power = (N - 1) % m; for (k = N - 1; k >= 0; k--) { c = factorial_tab_numer[2 * k + cosorsin]; new_denom = factorial_tab_denom[2 * k + cosorsin]; old_denom = factorial_tab_denom[2 * k + cosorsin + 2]; /* change denominators */ if (new_denom != old_denom && k < N - 1) { if (alternating && (k % 2 == 0)) s[xn] += old_denom; mpn_divrem_1(s, 0, s, xn + 1, old_denom); if (alternating && (k % 2 == 0)) s[xn] -= 1; } if (power == 0) { /* add c * x^0 -- only top limb is affected */ if (alternating & k) s[xn] -= c; else s[xn] += c; /* Outer polynomial evaluation: multiply by x^m */ if (k != 0) { flint_mpn_mul(t, s, xn + 1, XPOW_READ(m), xn); flint_mpn_copyi(s, t + xn, xn + 1); } power = m - 1; } else { if (alternating & k) s[xn] -= mpn_submul_1(s, XPOW_READ(power), xn, c); else s[xn] += mpn_addmul_1(s, XPOW_READ(power), xn, c); power--; } } /* finally divide by denominator */ if (cosorsin == 0) { mpn_divrem_1(t, 0, s, xn + 1, factorial_tab_denom[0]); /* perturb down to a number < 1 if necessary. note that this does not invalidate the error bound: 1 - ulp is either 1 ulp too small or must be closer to the exact value */ if (t[xn] == 0) flint_mpn_copyi(ycos, t, xn); else flint_mpn_store(ycos, xn, LIMB_ONES); } else { mpn_divrem_1(s, 0, s, xn + 1, factorial_tab_denom[0]); flint_mpn_mul(t, s, xn + 1, x, xn); flint_mpn_copyi(ysin, t + xn, xn); } } /* error bound (ulp) */ error[0] = 2; } TMP_END; } flint-3.1.3/src/arb/sin_cos_wide.c000066400000000000000000000150571461254215100170070ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp # define floor __builtin_floor #else # include #endif #define ONE_OVER_PI 0.31830988618379067154 #define PI 3.1415926535897932385 /* We use doubles in a way that keeps the final error <= EPSILON. */ #define EPSILON ldexp(1.0, -30) /* For |x| <= 2^MAX_EXP, doubles can be used directly for quadrant reduction. Note: 2^MAX_EXP must also fit in an int. */ #define MAX_EXP 20 /* Lookup tables, steps of 1/16. */ static const double sin_tab[] = { 0.0,0.062459317842380198585,0.12467473338522768996, 0.18640329676226988455,0.24740395925452292960,0.30743851458038085067, 0.36627252908604756137,0.42367625720393801036,0.47942553860420300027, 0.53330267353602017333,0.58509727294046215481,0.63460708001526929685, 0.68163876002333416673,0.72600865526071254966,0.76754350223602703963, 0.80608110826069299518,0.84147098480789650665,0.87357493516707112023, 0.90226759409909516292,0.92743691738486767172,0.94898461935558621435, 0.96682655669618022997,0.98089305702315569609,0.99112919095376166988, 0.99749498660405443094,0.99996558567824887530, }; static const double cos_tab[] = { 1.0,0.99804751070009914963,0.99219766722932905315, 0.98247331310125525749,0.96891242171064478414,0.95156794804817220215, 0.93050762191231429115,0.90581368342593642074,0.87758256189037271612, 0.84592449923106795446,0.81096311950521790219,0.77283494615247154481, 0.73168886887382088631,0.68768556222050484451,0.64099685816332513036, 0.59180507509247750546,0.54030230586813971740,0.48668966770196333087, 0.43117651679866617655,0.37397963082453319229,0.31532236239526866545, 0.25543376688881169791,0.19454770798898718445,0.13290194445282520566, 0.070737201667702910088,0.0082962316238583774779, }; /* Computes sin(a) and cos(a) and also sets q to the (approximate) quadrant of a. The absolute error of the straightforward algorithm below can be bounded as the error in the mod pi/2 reduction plus the negligible contribution (O(1) * 2^-53) of all other steps. Since |a| < 2^20 by assumption, we have 3 bits of margin for the final error bound of 2^-30 for the entire algorithm. */ static void sin_cos(double * sin_a, double * cos_a, int * q, double a) { double as, ac, t, b, bs, bc, v; int i, qa; *q = qa = floor(a * (2.0 * ONE_OVER_PI)); a = a - qa * (0.5 * PI); if (a < 0.0) a = 0.0; if (a > 0.5 * PI) a = 0.5 * PI; i = a * 16.0; if (i < 0 || i > 25) flint_throw(FLINT_ERROR, "(%s)\n", __func__); as = sin_tab[i]; ac = cos_tab[i]; b = a - i * (1 / 16.0); v = b * b; /* Just use the Taylor series. */ bs = 2.7557319223985890653e-6 * v; bs = (-0.0001984126984126984127 + bs) * v; bs = (0.0083333333333333333333 + bs) * v; bs = (-0.16666666666666666667 + bs) * v; bs = (1.0 + bs) * b; bc = -2.7557319223985890653e-7 * v; bc = (0.000024801587301587301587 + bc) * v; bc = (-0.0013888888888888888889 + bc) * v; bc = (0.041666666666666666667 + bc) * v; bc = (-0.5 + bc) * v; bc = 1.0 + bc; t = as * bc + ac * bs; ac = ac * bc - as * bs; as = t; if ((qa & 3) == 0) { *sin_a = as; *cos_a = ac; } else if ((qa & 3) == 1) { *sin_a = ac; *cos_a = -as; } else if ((qa & 3) == 2) { *sin_a = -as; *cos_a = -ac; } else { *sin_a = -ac; *cos_a = as; } } /* FIXME: this is the bottleneck -- an mpn version would be better */ static void _arb_mod_2pi(arb_t x, slong mag) { arb_t t; arf_t q; arf_init(q); arb_init(t); arb_const_pi(t, mag + 53); arb_mul_2exp_si(t, t, 1); arf_div(q, arb_midref(x), arb_midref(t), mag + 10, ARF_RND_NEAR); arf_floor(q, q); arb_submul_arf(x, t, q, 53); arf_clear(q); arb_clear(t); } void _arb_sin_cos_wide(arb_t sinx, arb_t cosx, const arf_t xmid, const mag_t xrad, slong prec) { double m, a, b, r, cos_min, cos_max, sin_min, sin_max; double as, ac, bs, bc; int i, qa, qb; slong mag; mag = arf_abs_bound_lt_2exp_si(xmid); if (mag > FLINT_MAX(65536, 4 * prec) || mag_cmp_2exp_si(xrad, 3) >= 0) { if (sinx != NULL) arb_zero_pm_one(sinx); if (cosx != NULL) arb_zero_pm_one(cosx); return; } else if (mag <= MAX_EXP) { m = arf_get_d(xmid, ARF_RND_DOWN); r = mag_get_d(xrad); } else { arb_t t; arb_init(t); arf_set(arb_midref(t), xmid); mag_set(arb_radref(t), xrad); _arb_mod_2pi(t, mag); /* this should not happen */ if (arf_cmpabs_2exp_si(arb_midref(t), 5) > 0 || mag_cmp_2exp_si(arb_radref(t), 5) > 0) { flint_printf("unexpected precision loss in sin_cos_wide\n"); if (sinx != NULL) arb_zero_pm_one(sinx); if (cosx != NULL) arb_zero_pm_one(cosx); arb_clear(t); return; } m = arf_get_d(arb_midref(t), ARF_RND_DOWN); r = mag_get_d(arb_radref(t)); arb_clear(t); } a = m - r; b = m + r; sin_cos(&as, &ac, &qa, a); sin_cos(&bs, &bc, &qb, b); sin_min = FLINT_MIN(as, bs); sin_max = FLINT_MAX(as, bs); cos_min = FLINT_MIN(ac, bc); cos_max = FLINT_MAX(ac, bc); /* Handle the quadrant crossings. */ for (i = qa; i < qb; i++) { if ((i & 3) == 1) cos_min = -1.0; if ((i & 3) == 3) cos_max = 1.0; if ((i & 3) == 2) sin_min = -1.0; if ((i & 3) == 0) sin_max = 1.0; } if (sinx != NULL) { a = (sin_max + sin_min) * 0.5; r = (sin_max - sin_min) * 0.5 + EPSILON; arf_set_d(arb_midref(sinx), a); mag_set_d(arb_radref(sinx), r); arb_set_round(sinx, sinx, prec); } if (cosx != NULL) { a = (cos_max + cos_min) * 0.5; r = (cos_max - cos_min) * 0.5 + EPSILON; arf_set_d(arb_midref(cosx), a); mag_set_d(arb_radref(cosx), r); arb_set_round(cosx, cosx, prec); } } void arb_sin_cos_wide(arb_t sinx, arb_t cosx, const arb_t x, slong prec) { _arb_sin_cos_wide(sinx, cosx, arb_midref(x), arb_radref(x), prec); } flint-3.1.3/src/arb/sinc.c000066400000000000000000000037651461254215100153010ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void _arb_sinc_derivative_bound(mag_t d, const arb_t x) { /* |f'(x)| < min(arb_get_mag(x), 1) / 2 */ mag_t r, one; mag_init(r); mag_init(one); arb_get_mag(r, x); mag_one(one); mag_min(d, r, one); mag_mul_2exp_si(d, d, -1); mag_clear(r); mag_clear(one); } void _arb_sinc_direct(arb_t z, const arb_t x, slong prec) { /* z = sin(x) / x */ slong wp; arb_t y; wp = prec + 2; arb_init(y); arb_sin(y, x, wp); arb_div(z, y, x, prec); arb_clear(y); } void arb_sinc(arb_t z, const arb_t x, slong prec) { mag_t c, r; mag_init(c); mag_init(r); mag_set_ui_2exp_si(c, 5, -1); arb_get_mag_lower(r, x); if (mag_cmp(c, r) < 0) { /* x is not near the origin */ _arb_sinc_direct(z, x, prec); } else if (mag_cmp_2exp_si(arb_radref(x), 1) < 0) { /* determine error magnitude using the derivative bound */ if (arb_is_exact(x)) { mag_zero(c); } else { _arb_sinc_derivative_bound(r, x); mag_mul(c, arb_radref(x), r); } /* evaluate sinc at the midpoint of x */ if (arf_is_zero(arb_midref(x))) { arb_one(z); } else { arb_get_mid_arb(z, x); _arb_sinc_direct(z, z, prec); } /* add the error */ mag_add(arb_radref(z), arb_radref(z), c); } else { /* x has a large radius and includes points near the origin */ arf_zero(arb_midref(z)); mag_one(arb_radref(z)); } mag_clear(c); mag_clear(r); } flint-3.1.3/src/arb/sinc_pi.c000066400000000000000000000024201461254215100157540ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sinc_pi(arb_t res, const arb_t x, slong prec) { mag_t m; arb_t t; if (!arb_is_finite(x)) { if (arf_is_nan(arb_midref(x))) arb_indeterminate(res); else if (arb_contains_zero(x)) arb_zero_pm_one(res); else arb_zero(res); return; } if (arb_is_int(x)) { if (arb_is_zero(x)) arb_one(res); else arb_zero(res); return; } mag_init(m); arb_init(t); arb_get_mag_lower(m, x); if (mag_cmp_2exp_si(m, -1) > 0) { arb_const_pi(t, prec + 4); arb_mul(t, t, x, prec + 4); arb_sin_pi(res, x, prec + 4); arb_div(res, res, t, prec); } else { arb_const_pi(t, prec + 4); arb_mul(t, t, x, prec + 4); arb_sinc(res, t, prec); } mag_clear(m); arb_clear(t); } flint-3.1.3/src/arb/sinh_cosh.c000066400000000000000000000123171461254215100163130ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sinh_cosh_wide(arb_t s, arb_t c, const arb_t x, slong prec) { mag_t t, u, v, w; mag_init(t); mag_init(u); mag_init(v); mag_init(w); arb_get_mag_lower(t, x); arb_get_mag(u, x); if (c != NULL) { mag_cosh_lower(v, t); mag_cosh(w, u); } if (s != NULL) { if (mag_is_zero(t)) { arf_get_mag_lower(t, arb_midref(x)); mag_sub(t, arb_radref(x), t); mag_sinh(t, t); mag_sinh(u, u); if (arf_sgn(arb_midref(x)) > 0) arb_set_interval_neg_pos_mag(s, t, u, prec); else arb_set_interval_neg_pos_mag(s, u, t, prec); } else { mag_sinh_lower(t, t); mag_sinh(u, u); if (arf_sgn(arb_midref(x)) > 0) { arb_set_interval_mag(s, t, u, prec); } else { arb_set_interval_mag(s, t, u, prec); arb_neg(s, s); } } } if (c != NULL) arb_set_interval_mag(c, v, w, prec); mag_clear(t); mag_clear(u); mag_clear(v); mag_clear(w); } void arb_cosh(arb_t c, const arb_t x, slong prec) { if (arb_is_zero(x)) { arb_one(c); } else if (!arb_is_finite(x)) { if (arf_is_nan(arb_midref(x))) arb_indeterminate(c); else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) arb_pos_inf(c); else arb_zero_pm_inf(c); } else if (mag_cmp_2exp_si(arb_radref(x), -20) > 0 && mag_cmp_2exp_si(arb_radref(x), 10) < 0 && arf_cmpabs_2exp_si(arb_midref(x), 4) < 0) { arb_sinh_cosh_wide(NULL, c, x, prec); } else { arb_t t; slong wp = prec + 4; /* todo: close to 0, could use derivative to bound propagated error more tightly */ arb_init(t); arb_exp_invexp(c, t, x, wp); arb_add(c, c, t, prec); arb_mul_2exp_si(c, c, -1); arb_clear(t); } } void arb_sinh(arb_t s, const arb_t x, slong prec) { if (arb_is_zero(x)) { arb_zero(s); } else if (!arb_is_finite(x)) { if (arf_is_nan(arb_midref(x))) arb_indeterminate(s); else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) { arf_set(arb_midref(s), arb_midref(x)); mag_zero(arb_radref(s)); } else arb_zero_pm_inf(s); } else if (mag_cmp_2exp_si(arb_radref(x), -20) > 0 && mag_cmp_2exp_si(arb_radref(x), 10) < 0 && arf_cmpabs_2exp_si(arb_midref(x), 4) < 0) { /* for sinh this is not more accurate, but slightly faster */ arb_sinh_cosh_wide(s, NULL, x, prec); } else { arb_t t; slong wp = prec + 4; arb_init(t); if (arf_cmpabs_2exp_si(arb_midref(x), -1) <= 0 && mag_cmp_2exp_si(arb_radref(x), -4) <= 0) { arb_expm1(s, x, wp); arb_add_ui(t, s, 1, wp); arb_div(t, s, t, wp); arb_add(s, s, t, prec); } else { arb_exp_invexp(s, t, x, wp); arb_sub(s, s, t, prec); } arb_mul_2exp_si(s, s, -1); arb_clear(t); } } void arb_sinh_cosh(arb_t s, arb_t c, const arb_t x, slong prec) { if (arb_is_zero(x)) { arb_zero(s); arb_one(c); } else if (!arb_is_finite(x)) { if (arf_is_nan(arb_midref(x))) { arb_indeterminate(s); arb_indeterminate(c); } else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) { arf_set(arb_midref(s), arb_midref(x)); mag_zero(arb_radref(s)); arf_abs(arb_midref(c), arb_midref(s)); mag_zero(arb_radref(c)); } else { arb_zero_pm_inf(s); arb_zero_pm_inf(c); } } else if (mag_cmp_2exp_si(arb_radref(x), -20) > 0 && mag_cmp_2exp_si(arb_radref(x), 10) < 0 && arf_cmpabs_2exp_si(arb_midref(x), 4) < 0) { arb_sinh_cosh_wide(s, c, x, prec); } else { arb_t t; slong wp = prec + 4; arb_init(t); if (arf_cmpabs_2exp_si(arb_midref(x), -1) <= 0 && mag_cmp_2exp_si(arb_radref(x), -4) <= 0) { arb_expm1(s, x, wp); arb_add_ui(t, s, 1, wp); arb_inv(c, t, wp); arb_addmul(s, s, c, prec); arb_add(c, c, t, prec); } else { arb_exp_invexp(c, t, x, wp); arb_sub(s, c, t, prec); arb_add(c, c, t, prec); } arb_mul_2exp_si(s, s, -1); arb_mul_2exp_si(c, c, -1); arb_clear(t); } } flint-3.1.3/src/arb/sqrt.c000066400000000000000000000250231461254215100153250ustar00rootroot00000000000000/* Copyright (C) 2014, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* see comments in div.c */ #define GUARD_BITS 32 #define RSQRT_NEWTON_CUTOFF 4000 #define SQRT_NEWTON_CUTOFF 200000 void _arf_rsqrt_newton(arf_t res, const arf_t x, slong prec) { slong wp = prec + GUARD_BITS; slong hp = prec / 2 + GUARD_BITS; if (prec < RSQRT_NEWTON_CUTOFF) { arf_set_round(res, x, wp, ARF_RND_DOWN); arf_rsqrt(res, res, wp, ARF_RND_DOWN); } else { arf_t r, t, u; arf_init(r); arf_init(t); arf_init(u); _arf_rsqrt_newton(r, x, hp); /* r - r*(x*r^2 - 1)/2 */ arf_mul(t, r, r, wp, ARF_RND_DOWN); if (arf_bits(x) <= wp) { arf_mul(t, t, x, wp, ARF_RND_DOWN); } else { arf_set_round(u, x, wp, ARF_RND_DOWN); arf_mul(t, t, u, wp, ARF_RND_DOWN); } arf_sub_ui(t, t, 1, hp, ARF_RND_DOWN); arf_mul_2exp_si(t, t, -1); arf_mul(t, t, r, hp, ARF_RND_DOWN); arf_sub(res, r, t, wp, ARF_RND_DOWN); arf_clear(r); arf_clear(t); arf_clear(u); } } void _arf_sqrt_newton(arf_t res, const arf_t x, slong prec) { arf_t t, u, v; slong wp = prec + GUARD_BITS; slong hp = prec / 2 + GUARD_BITS; arf_init(t); arf_init(u); arf_init(v); _arf_rsqrt_newton(t, x, hp); if (arf_bits(x) <= hp) { arf_mul(v, t, x, hp, ARF_RND_DOWN); } else { arf_set_round(u, x, hp, ARF_RND_DOWN); arf_mul(v, t, u, hp, ARF_RND_DOWN); } arf_mul(u, v, v, wp, ARF_RND_DOWN); arf_sub(u, x, u, hp, ARF_RND_DOWN); arf_mul(u, u, t, wp, ARF_RND_DOWN); arf_mul_2exp_si(u, u, -1); arf_add(res, v, u, wp, ARF_RND_DOWN); arf_clear(t); arf_clear(u); arf_clear(v); } void arb_rsqrt_arf_newton(arb_t res, const arf_t x, slong prec) { if (arf_is_special(x) || arf_sgn(x) < 0) { arb_indeterminate(res); return; } /* special case: handle 2^(2n) exactly */ if (ARF_IS_POW2(x) && fmpz_is_odd(ARF_EXPREF(x))) { arf_rsqrt(arb_midref(res), x, prec, ARF_RND_DOWN); mag_zero(arb_radref(res)); return; } _arf_rsqrt_newton(arb_midref(res), x, prec); arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec + GUARD_BITS / 2); arb_set_round(res, res, prec); } void arb_rsqrt_arf(arb_t res, const arf_t x, slong prec) { if (arf_is_special(x) || arf_sgn(x) < 0) { if (arf_is_pos_inf(x)) arb_zero(res); else arb_indeterminate(res); return; } #ifdef FLINT_HAVE_FFT_SMALL if (prec > RSQRT_NEWTON_CUTOFF) { arb_rsqrt_arf_newton(res, x, prec); } else #endif { int inexact; inexact = arf_rsqrt(arb_midref(res), x, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec); else mag_zero(arb_radref(res)); } } void arb_rsqrt(arb_t z, const arb_t x, slong prec) { if (!arb_is_finite(x) || arf_sgn(arb_midref(x)) <= 0) { if (arf_is_pos_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) arb_zero(z); else arb_indeterminate(z); } else if (mag_is_zero(arb_radref(x))) { arb_rsqrt_arf(z, arb_midref(x), prec); } else { mag_t t, u; slong acc; mag_init(t); arb_get_mag_lower(t, x); acc = arb_rel_accuracy_bits(x); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); if (acc <= 20) { if (mag_is_zero(t)) { arb_indeterminate(z); } else { mag_init(u); arb_get_mag(u, x); mag_rsqrt(t, t); mag_rsqrt_lower(u, u); arb_set_interval_mag(z, u, t, prec); mag_clear(u); } } else { /* error bound: (1/2) (x-r)^(-3/2) * r */ mag_init(u); mag_rsqrt(u, t); mag_div(t, u, t); mag_mul(t, t, arb_radref(x)); mag_mul_2exp_si(t, t, -1); arb_rsqrt_arf(z, arb_midref(x), prec); mag_add(arb_radref(z), arb_radref(z), t); mag_clear(u); } mag_clear(t); } } void arb_sqrt_arf_newton(arb_t res, const arf_t x, slong prec) { if (arf_is_special(x) || arf_sgn(x) < 0) { if (arf_is_zero(x) || arf_is_pos_inf(x)) arb_set_arf(res, x); else arb_indeterminate(res); return; } /* special case: handle 2^(2n) exactly */ /* todo: detect other simple squares? */ if (ARF_IS_POW2(x) && fmpz_is_odd(ARF_EXPREF(x))) { arf_sqrt(arb_midref(res), x, prec, ARF_RND_DOWN); mag_zero(arb_radref(res)); return; } _arf_sqrt_newton(arb_midref(res), x, prec); arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec + GUARD_BITS / 2); arb_set_round(res, res, prec); } void arb_sqrt_arf(arb_t res, const arf_t x, slong prec) { if (arf_is_special(x) || arf_sgn(x) < 0) { if (arf_is_zero(x) || arf_is_pos_inf(x)) arb_set_arf(res, x); else arb_indeterminate(res); return; } #ifdef FLINT_HAVE_FFT_SMALL if (prec > SQRT_NEWTON_CUTOFF) { arb_sqrt_arf_newton(res, x, prec); } else #endif { if (arf_sqrt(arb_midref(res), x, prec, ARB_RND)) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec); else mag_zero(arb_radref(res)); } } void arb_sqrt_newton(arb_t z, const arb_t x, slong prec) { mag_t zr, rx; mag_init(zr); mag_init(rx); /* rx = upper bound for r / x */ arf_get_mag_lower(rx, arb_midref(x)); mag_div(rx, arb_radref(x), rx); arb_sqrt_arf_newton(z, arb_midref(x), prec); /* zr = upper bound for sqrt(x) */ arb_get_mag(zr, z); /* propagated error: sqrt(x) - sqrt(x-r) = sqrt(x) * [1 - sqrt(1 - r/x)] <= sqrt(x) * 0.5 * (rx + rx^2) */ mag_addmul(rx, rx, rx); mag_mul(zr, zr, rx); mag_mul_2exp_si(zr, zr, -1); mag_add(arb_radref(z), arb_radref(z), zr); mag_clear(zr); mag_clear(rx); } void arb_sqrt(arb_t z, const arb_t x, slong prec) { mag_t rx, zr; int inexact; if (mag_is_zero(arb_radref(x))) { arb_sqrt_arf(z, arb_midref(x), prec); } else if (arf_is_special(arb_midref(x)) || arf_sgn(arb_midref(x)) < 0 || mag_is_inf(arb_radref(x))) { if (arf_is_pos_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))) arb_sqrt_arf(z, arb_midref(x), prec); else arb_indeterminate(z); } else /* now both mid and rad are non-special values, mid > 0 */ { slong acc; acc = _fmpz_sub_small(ARF_EXPREF(arb_midref(x)), MAG_EXPREF(arb_radref(x))); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); if (acc < 0) { arb_indeterminate(z); } else if (acc <= 20) { mag_t t, u; mag_init(t); mag_init(u); arb_get_mag_lower(t, x); if (mag_is_zero(t) && arb_contains_negative(x)) { arb_indeterminate(z); } else { arb_get_mag(u, x); mag_sqrt_lower(t, t); mag_sqrt(u, u); arb_set_interval_mag(z, t, u, prec); } mag_clear(t); mag_clear(u); } #ifdef FLINT_HAVE_FFT_SMALL else if (prec > SQRT_NEWTON_CUTOFF) { arb_sqrt_newton(z, x, prec); } #endif else if (ARB_IS_LAGOM(x)) /* small exponents, acc *and* prec >= 20 */ { mag_t t; mag_init(t); /* no need to free */ inexact = arf_sqrt(arb_midref(z), arb_midref(x), prec, ARB_RND); /* sqrt(x) - sqrt(x-r) <= 0.5 * r * rsqrt(x-r) */ /* we have rsqrt(x-r) ~= 1/sqrt(x) */ arf_get_mag_lower(t, arb_midref(z)); /* note: we need to write rad(z) first to use fast_mul later */ mag_div(arb_radref(z), arb_radref(x), t); /* We are guaranteed to have acc and prec >= 20. */ /* 0.5 + eps corrects for errors */ MAG_MAN(t) = MAG_ONE_HALF + (MAG_ONE_HALF >> 16); MAG_EXP(t) = 0; mag_fast_mul(arb_radref(z), arb_radref(z), t); if (inexact) arf_mag_fast_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else { mag_init(zr); mag_init(rx); /* rx = upper bound for r / x */ arf_get_mag_lower(rx, arb_midref(x)); mag_div(rx, arb_radref(x), rx); inexact = arf_sqrt(arb_midref(z), arb_midref(x), prec, ARB_RND); /* zr = upper bound for sqrt(x) */ arf_get_mag(zr, arb_midref(z)); if (inexact) arf_mag_add_ulp(zr, zr, arb_midref(z), prec); /* propagated error: sqrt(x) - sqrt(x-r) = sqrt(x) * [1 - sqrt(1 - r/x)] <= sqrt(x) * 0.5 * (rx + rx^2) */ mag_addmul(rx, rx, rx); mag_mul(zr, zr, rx); mag_mul_2exp_si(zr, zr, -1); /* add the rounding error */ if (inexact) arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec); else mag_swap(arb_radref(z), zr); mag_clear(zr); mag_clear(rx); } } } void arb_rsqrt_ui(arb_t z, ulong x, slong prec) { arf_t t; arf_init_set_ui(t, x); /* no need to free */ arb_rsqrt_arf(z, t, prec); } void arb_sqrt_ui(arb_t z, ulong x, slong prec) { arf_t t; arf_init_set_ui(t, x); /* no need to free */ arb_sqrt_arf(z, t, prec); } void arb_sqrt_fmpz(arb_t z, const fmpz_t x, slong prec) { arf_t t; arf_init(t); arf_set_fmpz(t, x); arb_sqrt_arf(z, t, prec); arf_clear(t); } flint-3.1.3/src/arb/sqrt1pm1.c000066400000000000000000000030071461254215100160220ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" static void arb_sqrt1pm1_tiny(arb_t r, const arb_t z, slong prec) { mag_t b, c; arb_t t; mag_init(b); mag_init(c); arb_init(t); /* if |z| < 1, then |(sqrt(1+z)-1) - (z/2-z^2/8)| <= |z|^3/(1-|z|)/16 */ arb_get_mag(b, z); mag_one(c); mag_sub_lower(c, c, b); mag_pow_ui(b, b, 3); mag_div(b, b, c); mag_mul_2exp_si(b, b, -4); arb_mul(t, z, z, prec); arb_mul_2exp_si(t, t, -2); arb_sub(r, z, t, prec); arb_mul_2exp_si(r, r, -1); if (mag_is_finite(b)) arb_add_error_mag(r, b); else arb_indeterminate(r); mag_clear(b); mag_clear(c); arb_clear(t); } void arb_sqrt1pm1(arb_t r, const arb_t z, slong prec) { slong magz, wp; if (arb_is_zero(z)) { arb_zero(r); return; } magz = arf_abs_bound_lt_2exp_si(arb_midref(z)); if (magz < -prec) { arb_sqrt1pm1_tiny(r, z, prec); } else { if (magz < 0) wp = prec + (-magz) + 4; else wp = prec + 4; arb_add_ui(r, z, 1, wp); arb_sqrt(r, r, wp); arb_sub_ui(r, r, 1, wp); } } flint-3.1.3/src/arb/sqrtpos.c000066400000000000000000000023121461254215100160430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sqrtpos(arb_t z, const arb_t x, slong prec) { if (!arb_is_finite(x)) { if (mag_is_zero(arb_radref(x)) && arf_is_pos_inf(arb_midref(x))) arb_pos_inf(z); else arb_zero_pm_inf(z); } else if (arb_contains_nonpositive(x)) { arf_t t; arf_init(t); arf_set_mag(t, arb_radref(x)); arf_add(t, arb_midref(x), t, MAG_BITS, ARF_RND_CEIL); if (arf_sgn(t) <= 0) { arb_zero(z); } else { arf_sqrt(t, t, MAG_BITS, ARF_RND_CEIL); arf_mul_2exp_si(t, t, -1); arf_set(arb_midref(z), t); arf_get_mag(arb_radref(z), t); } arf_clear(t); } else { arb_sqrt(z, x, prec); } arb_nonnegative_part(z, z); } flint-3.1.3/src/arb/sub.c000066400000000000000000000036561461254215100151350ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_sub(arb_t z, const arb_t x, const arb_t y, slong prec) { int inexact; inexact = arf_sub(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); mag_add(arb_radref(z), arb_radref(x), arb_radref(y)); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } void arb_sub_arf(arb_t z, const arb_t x, const arf_t y, slong prec) { int inexact; inexact = arf_sub(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_sub_ui(arb_t z, const arb_t x, ulong y, slong prec) { int inexact; inexact = arf_sub_ui(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_sub_si(arb_t z, const arb_t x, slong y, slong prec) { int inexact; inexact = arf_sub_si(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } void arb_sub_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) { int inexact; inexact = arf_sub_fmpz(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); } flint-3.1.3/src/arb/submul.c000066400000000000000000000103361461254215100156440ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_submul_arf(arb_t z, const arb_t x, const arf_t y, slong prec) { mag_t ym; int inexact; if (arb_is_exact(x)) { inexact = arf_submul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(ym, y); mag_fast_addmul(arb_radref(z), ym, arb_radref(x)); inexact = arf_submul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_fast_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else if (arf_is_inf(y) && arb_is_nonzero(x)) { if (arf_sgn(arb_midref(x)) > 0) arb_sub_arf(z, z, y, prec); else arb_add_arf(z, z, y, prec); } else { mag_init_set_arf(ym, y); mag_addmul(arb_radref(z), ym, arb_radref(x)); inexact = arf_submul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); mag_clear(ym); } } void arb_submul(arb_t z, const arb_t x, const arb_t y, slong prec) { mag_t zr, xm, ym; int inexact; if (arb_is_exact(y)) { arb_submul_arf(z, x, arb_midref(y), prec); } else if (arb_is_exact(x)) { arb_submul_arf(z, y, arb_midref(x), prec); } else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(xm, arb_midref(x)); mag_fast_init_set_arf(ym, arb_midref(y)); mag_fast_init_set(zr, arb_radref(z)); mag_fast_addmul(zr, xm, arb_radref(y)); mag_fast_addmul(zr, ym, arb_radref(x)); mag_fast_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_submul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARF_RND_DOWN); if (inexact) arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec); *arb_radref(z) = *zr; } else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y)) { if (arf_sgn(arb_midref(y)) > 0) arb_sub_arf(z, z, arb_midref(x), prec); else arb_add_arf(z, z, arb_midref(x), prec); } else if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x)) { if (arf_sgn(arb_midref(x)) > 0) arb_sub_arf(z, z, arb_midref(y), prec); else arb_add_arf(z, z, arb_midref(y), prec); } else { mag_init_set_arf(xm, arb_midref(x)); mag_init_set_arf(ym, arb_midref(y)); mag_init_set(zr, arb_radref(z)); mag_addmul(zr, xm, arb_radref(y)); mag_addmul(zr, ym, arb_radref(x)); mag_addmul(zr, arb_radref(x), arb_radref(y)); inexact = arf_submul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARF_RND_DOWN); if (inexact) arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec); else mag_set(arb_radref(z), zr); mag_clear(zr); mag_clear(xm); mag_clear(ym); } } void arb_submul_si(arb_t z, const arb_t x, slong y, slong prec) { arf_t t; arf_init_set_si(t, y); /* no need to free */ arb_submul_arf(z, x, t, prec); } void arb_submul_ui(arb_t z, const arb_t x, ulong y, slong prec) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ arb_submul_arf(z, x, t, prec); } void arb_submul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) { arf_t t; if (!COEFF_IS_MPZ(*y)) { arf_init_set_si(t, *y); /* no need to free */ arb_submul_arf(z, x, t, prec); } else { arf_init(t); arf_set_fmpz(t, y); arb_submul_arf(z, x, t, prec); arf_clear(t); } } flint-3.1.3/src/arb/tan.c000066400000000000000000000010661461254215100151170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_tan(arb_t y, const arb_t x, slong prec) { arb_t u; arb_init(u); arb_sin_cos(y, u, x, prec + 4); arb_div(y, y, u, prec); arb_clear(u); } flint-3.1.3/src/arb/tan_pi.c000066400000000000000000000015011461254215100156010ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_tan_pi(arb_t y, const arb_t x, slong prec) { if (!arb_is_finite(x)) { arb_indeterminate(y); } else if (arb_is_int_2exp_si(x, -1)) { if (arb_is_int(x)) arb_zero(y); else arb_indeterminate(y); } else { arb_t u; arb_init(u); arb_sin_cos_pi(y, u, x, prec + 4); arb_div(y, y, u, prec); arb_clear(u); } } flint-3.1.3/src/arb/tanh.c000066400000000000000000000022241461254215100152640ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_tanh(arb_t y, const arb_t x, slong prec) { arb_t t, u; int sign = arf_sgn(arb_midref(x)) < 0; arb_init(t); arb_init(u); arb_mul_2exp_si(t, x, 1); if (!sign) arb_neg(t, t); if (arf_cmpabs_2exp_si(arb_midref(x), 1) > 0) { /* tanh(x) = 1 - 2 exp(-2x) / (1 + exp(-2x)) */ arb_exp(t, t, prec + 4); arb_add_ui(u, t, 1, prec + 4); arb_div(y, t, u, prec + 4); arb_mul_2exp_si(y, y, 1); arb_sub_ui(y, y, 1, prec); } else { /* tanh(x) = (exp(2x) - 1) / (exp(2x) + 1) */ arb_expm1(t, t, prec + 4); arb_add_ui(y, t, 2, prec + 4); arb_div(y, t, y, prec); } if (!sign) arb_neg(y, y); arb_clear(t); arb_clear(u); } flint-3.1.3/src/arb/test/000077500000000000000000000000001461254215100151455ustar00rootroot00000000000000flint-3.1.3/src/arb/test/main.c000066400000000000000000000313411461254215100162370ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-acos.c" #include "t-acosh.c" #include "t-add_arf.c" #include "t-add.c" #include "t-add_error.c" #include "t-add_fmpz_2exp.c" #include "t-add_fmpz.c" #include "t-addmul_arf.c" #include "t-addmul.c" #include "t-addmul_fmpz.c" #include "t-addmul_si.c" #include "t-addmul_ui.c" #include "t-add_si.c" #include "t-add_ui.c" #include "t-agm.c" #include "t-approx_dot.c" #include "t-asin.c" #include "t-asinh.c" #include "t-atan2.c" #include "t-atan_arf_bb.c" #include "t-atan_arf.c" #include "t-atan_arf_newton.c" #include "t-atan.c" #include "t-atan_frac_bsplit.c" #include "t-atan_gauss_primes_vec_bsplit.c" #include "t-atanh.c" #include "t-atan_newton.c" #include "t-atan_sum_bs_powtab.c" #include "t-atan_tab.c" #include "t-atan_taylor_rs.c" #include "t-bell_fmpz.c" #include "t-bell_sum_taylor.c" #include "t-bernoulli_poly_ui.c" #include "t-bernoulli_ui.c" #include "t-can_round_mpfr.c" #include "t-ceil.c" #include "t-chebyshev_t_ui.c" #include "t-chebyshev_u_ui.c" #include "t-const_apery.c" #include "t-const_catalan.c" #include "t-const_e.c" #include "t-const_euler.c" #include "t-const_glaisher.c" #include "t-const_khinchin.c" #include "t-const_log10.c" #include "t-const_log2.c" #include "t-const_pi.c" #include "t-const_reciprocal_fibonacci.c" #include "t-contains_arf.c" #include "t-contains.c" #include "t-contains_fmpq.c" #include "t-contains_int.c" #include "t-contains_interior.c" #include "t-cos.c" #include "t-cosh.c" #include "t-cos_pi.c" #include "t-cos_pi_fmpq_algebraic.c" #include "t-cos_pi_fmpq.c" #include "t-coth.c" #include "t-cot_pi.c" #include "t-csc.c" #include "t-csch.c" #include "t-csc_pi.c" #include "t-digamma.c" #include "t-digits_round_inplace.c" #include "t-div_2expm1_ui.c" #include "t-div_arf.c" #include "t-div.c" #include "t-div_fmpz.c" #include "t-div_newton.c" #include "t-div_si.c" #include "t-div_ui.c" #include "t-dot.c" #include "t-dot_fmpz.c" #include "t-dot_si.c" #include "t-dot_siui.c" #include "t-dot_ui.c" #include "t-dot_uiui.c" #include "t-doublefac_ui.c" #include "t-dump_file.c" #include "t-dump_str.c" #include "t-euler_number_fmpz.c" #include "t-euler_number_ui.c" #include "t-exp_arf_bb.c" #include "t-exp_arf_rs_generic.c" #include "t-exp.c" #include "t-exp_invexp.c" #include "t-expm1.c" #include "t-exp_sum_bs_powtab.c" #include "t-exp_tab.c" #include "t-exp_taylor_rs.c" #include "t-fac_ui.c" #include "t-fib.c" #include "t-floor.c" #include "t-fma.c" #include "t-gamma.c" #include "t-gamma_fmpq.c" #include "t-get_abs_lbound_arf.c" #include "t-get_fmpz_mid_rad_10exp.c" #include "t-get_interval_arf.c" #include "t-get_interval_fmpz_2exp.c" #include "t-get_interval_mpfr.c" #include "t-get_lbound_arf.c" #include "t-get_mag.c" #include "t-get_mag_lower.c" #include "t-get_mag_lower_nonnegative.c" #include "t-get_mpn_fixed_mod_log2.c" #include "t-get_mpn_fixed_mod_pi4.c" #include "t-get_rand_fmpq.c" #include "t-get_str.c" #include "t-get_unique_fmpz.c" #include "t-hurwitz_zeta.c" #include "t-intersection.c" #include "t-lambertw.c" #include "t-lgamma.c" #include "t-log1p.c" #include "t-log_arf.c" #include "t-log_base_ui.c" #include "t-log.c" #include "t-log_hypot.c" #include "t-log_newton.c" #include "t-log_primes_vec_bsplit.c" #include "t-log_tab.c" #include "t-log_ui_from_prev.c" #include "t-max.c" #include "t-min.c" #include "t-minmax.c" #include "t-mul_arf.c" #include "t-mul.c" #include "t-mul_fmpz.c" #include "t-mul_more.c" #include "t-mul_si.c" #include "t-mul_ui.c" #include "t-nonnegative_abs.c" #include "t-overlaps.c" #include "t-partitions_fmpz.c" #include "t-pos_times_posinf.c" #include "t-pow.c" #include "t-power_sum_vec.c" #include "t-pow_fmpq.c" #include "t-pow_fmpz.c" #include "t-primorial.c" #include "t-rgamma.c" #include "t-richcmp.c" #include "t-rising2_ui.c" #include "t-rising_ui.c" #include "t-root_ui.c" #include "t-rsqrt.c" #include "t-sec.c" #include "t-sech.c" #include "t-set_interval_arf.c" #include "t-set_interval_mag.c" #include "t-set_interval_mpfr.c" #include "t-set_interval_neg_pos_mag.c" #include "t-set_str.c" #include "t-sgn.c" #include "t-sin.c" #include "t-sinc.c" #include "t-sin_cos_arf_bb.c" #include "t-sin_cos_arf_generic.c" #include "t-sin_cos.c" #include "t-sin_cos_generic.c" #include "t-sin_cos_pi.c" #include "t-sin_cos_pi_fmpq_algebraic.c" #include "t-sin_cos_pi_fmpq.c" #include "t-sin_cos_tab.c" #include "t-sin_cos_taylor_rs.c" #include "t-sinc_pi.c" #include "t-sinh.c" #include "t-sinh_cosh.c" #include "t-sin_pi.c" #include "t-sin_pi_fmpq_algebraic.c" #include "t-sin_pi_fmpq.c" #include "t-special.c" #include "t-sqrt1pm1.c" #include "t-sqrt.c" #include "t-sqrt_newton.c" #include "t-sqrtpos.c" #include "t-sub_arf.c" #include "t-sub.c" #include "t-sub_fmpz.c" #include "t-submul_arf.c" #include "t-submul.c" #include "t-submul_fmpz.c" #include "t-submul_si.c" #include "t-submul_ui.c" #include "t-sub_si.c" #include "t-sub_ui.c" #include "t-tanh.c" #include "t-tan_pi.c" #include "t-trim.c" #include "t-ui_pow_ui.c" #include "t-union.c" #include "t-urandom.c" #include "t-zeta.c" #include "t-zeta_ui_asymp.c" #include "t-zeta_ui_bernoulli.c" #include "t-zeta_ui_borwein_bsplit.c" #include "t-zeta_ui.c" #include "t-zeta_ui_euler_product.c" #include "t-zeta_ui_vec_borwein.c" #include "t-zeta_ui_vec.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arb_acos), TEST_FUNCTION(arb_acosh), TEST_FUNCTION(arb_add_arf), TEST_FUNCTION(arb_add), TEST_FUNCTION(arb_add_error), TEST_FUNCTION(arb_add_fmpz_2exp), TEST_FUNCTION(arb_add_fmpz), TEST_FUNCTION(arb_addmul_arf), TEST_FUNCTION(arb_addmul), TEST_FUNCTION(arb_addmul_fmpz), TEST_FUNCTION(arb_addmul_si), TEST_FUNCTION(arb_addmul_ui), TEST_FUNCTION(arb_add_si), TEST_FUNCTION(arb_add_ui), TEST_FUNCTION(arb_agm), TEST_FUNCTION(arb_approx_dot), TEST_FUNCTION(arb_asin), TEST_FUNCTION(arb_asinh), TEST_FUNCTION(arb_atan2), TEST_FUNCTION(arb_atan_arf_bb), TEST_FUNCTION(arb_atan_arf), TEST_FUNCTION(arb_atan_arf_newton), TEST_FUNCTION(arb_atan), TEST_FUNCTION(arb_atan_frac_bsplit), TEST_FUNCTION(arb_atan_gauss_primes_vec_bsplit), TEST_FUNCTION(arb_atanh), TEST_FUNCTION(arb_atan_newton), TEST_FUNCTION(arb_atan_sum_bs_powtab), TEST_FUNCTION(arb_atan_tab), TEST_FUNCTION(arb_atan_taylor_rs), TEST_FUNCTION(arb_bell_fmpz), TEST_FUNCTION(arb_bell_sum_taylor), TEST_FUNCTION(arb_bernoulli_poly_ui), TEST_FUNCTION(arb_bernoulli_ui), TEST_FUNCTION(arb_can_round_mpfr), TEST_FUNCTION(arb_ceil), TEST_FUNCTION(arb_chebyshev_t_ui), TEST_FUNCTION(arb_chebyshev_u_ui), TEST_FUNCTION(arb_const_apery), TEST_FUNCTION(arb_const_catalan), TEST_FUNCTION(arb_const_e), TEST_FUNCTION(arb_const_euler), TEST_FUNCTION(arb_const_glaisher), TEST_FUNCTION(arb_const_khinchin), TEST_FUNCTION(arb_const_log10), TEST_FUNCTION(arb_const_log2), TEST_FUNCTION(arb_const_pi), TEST_FUNCTION(arb_const_reciprocal_fibonacci), TEST_FUNCTION(arb_contains_arf), TEST_FUNCTION(arb_contains), TEST_FUNCTION(arb_contains_fmpq), TEST_FUNCTION(arb_contains_int), TEST_FUNCTION(arb_contains_interior), TEST_FUNCTION(arb_cos), TEST_FUNCTION(arb_cosh), TEST_FUNCTION(arb_cos_pi), TEST_FUNCTION(arb_cos_pi_fmpq_algebraic), TEST_FUNCTION(arb_cos_pi_fmpq), TEST_FUNCTION(arb_coth), TEST_FUNCTION(arb_cot_pi), TEST_FUNCTION(arb_csc), TEST_FUNCTION(arb_csch), TEST_FUNCTION(arb_csc_pi), TEST_FUNCTION(arb_digamma), TEST_FUNCTION(arb_digits_round_inplace), TEST_FUNCTION(arb_div_2expm1_ui), TEST_FUNCTION(arb_div_arf), TEST_FUNCTION(arb_div), TEST_FUNCTION(arb_div_fmpz), TEST_FUNCTION(arb_div_newton), TEST_FUNCTION(arb_div_si), TEST_FUNCTION(arb_div_ui), TEST_FUNCTION(arb_dot), TEST_FUNCTION(arb_dot_fmpz), TEST_FUNCTION(arb_dot_si), TEST_FUNCTION(arb_dot_siui), TEST_FUNCTION(arb_dot_ui), TEST_FUNCTION(arb_dot_uiui), TEST_FUNCTION(arb_doublefac_ui), TEST_FUNCTION(arb_dump_file), TEST_FUNCTION(arb_dump_str), TEST_FUNCTION(arb_euler_number_fmpz), TEST_FUNCTION(arb_euler_number_ui), TEST_FUNCTION(arb_exp_arf_bb), TEST_FUNCTION(arb_exp_arf_rs_generic), TEST_FUNCTION(arb_exp), TEST_FUNCTION(arb_exp_invexp), TEST_FUNCTION(arb_expm1), TEST_FUNCTION(arb_exp_sum_bs_powtab), TEST_FUNCTION(arb_exp_tab), TEST_FUNCTION(arb_exp_taylor_rs), TEST_FUNCTION(arb_fac_ui), TEST_FUNCTION(arb_fib), TEST_FUNCTION(arb_floor), TEST_FUNCTION(arb_fma), TEST_FUNCTION(arb_gamma), TEST_FUNCTION(arb_gamma_fmpq), TEST_FUNCTION(arb_get_abs_lbound_arf), TEST_FUNCTION(arb_get_fmpz_mid_rad_10exp), TEST_FUNCTION(arb_get_interval_arf), TEST_FUNCTION(arb_get_interval_fmpz_2exp), TEST_FUNCTION(arb_get_interval_mpfr), TEST_FUNCTION(arb_get_lbound_arf), TEST_FUNCTION(arb_get_mag), TEST_FUNCTION(arb_get_mag_lower), TEST_FUNCTION(arb_get_mag_lower_nonnegative), TEST_FUNCTION(arb_get_mpn_fixed_mod_log2), TEST_FUNCTION(arb_get_mpn_fixed_mod_pi4), TEST_FUNCTION(arb_get_rand_fmpq), TEST_FUNCTION(arb_get_str), TEST_FUNCTION(arb_get_unique_fmpz), TEST_FUNCTION(arb_hurwitz_zeta), TEST_FUNCTION(arb_intersection), TEST_FUNCTION(arb_lambertw), TEST_FUNCTION(arb_lgamma), TEST_FUNCTION(arb_log1p), TEST_FUNCTION(arb_log_arf), TEST_FUNCTION(arb_log_base_ui), TEST_FUNCTION(arb_log), TEST_FUNCTION(arb_log_hypot), TEST_FUNCTION(arb_log_newton), TEST_FUNCTION(arb_log_primes_vec_bsplit), TEST_FUNCTION(arb_log_tab), TEST_FUNCTION(arb_log_ui_from_prev), TEST_FUNCTION(arb_max), TEST_FUNCTION(arb_min), TEST_FUNCTION(arb_minmax), TEST_FUNCTION(arb_mul_arf), TEST_FUNCTION(arb_mul), TEST_FUNCTION(arb_mul_fmpz), TEST_FUNCTION(arb_mul_more), TEST_FUNCTION(arb_mul_si), TEST_FUNCTION(arb_mul_ui), TEST_FUNCTION(arb_nonnegative_abs), TEST_FUNCTION(arb_overlaps), TEST_FUNCTION(arb_partitions_fmpz), TEST_FUNCTION(arb_pos_times_posinf), TEST_FUNCTION(arb_pow), TEST_FUNCTION(arb_power_sum_vec), TEST_FUNCTION(arb_pow_fmpq), TEST_FUNCTION(arb_pow_fmpz), TEST_FUNCTION(arb_primorial), TEST_FUNCTION(arb_rgamma), TEST_FUNCTION(arb_richcmp), TEST_FUNCTION(arb_rising2_ui), TEST_FUNCTION(arb_rising_ui), TEST_FUNCTION(arb_root_ui), TEST_FUNCTION(arb_rsqrt), TEST_FUNCTION(arb_sec), TEST_FUNCTION(arb_sech), TEST_FUNCTION(arb_set_interval_arf), TEST_FUNCTION(arb_set_interval_mag), TEST_FUNCTION(arb_set_interval_mpfr), TEST_FUNCTION(arb_set_interval_neg_pos_mag), TEST_FUNCTION(arb_set_str), TEST_FUNCTION(arb_sgn), TEST_FUNCTION(arb_sin), TEST_FUNCTION(arb_sinc), TEST_FUNCTION(arb_sin_cos_arf_bb), TEST_FUNCTION(arb_sin_cos_arf_generic), TEST_FUNCTION(arb_sin_cos), TEST_FUNCTION(arb_sin_cos_generic), TEST_FUNCTION(arb_sin_cos_pi), TEST_FUNCTION(arb_sin_cos_pi_fmpq_algebraic), TEST_FUNCTION(arb_sin_cos_pi_fmpq), TEST_FUNCTION(arb_sin_cos_tab), TEST_FUNCTION(arb_sin_cos_taylor_rs), TEST_FUNCTION(arb_sinc_pi), TEST_FUNCTION(arb_sinh), TEST_FUNCTION(arb_sinh_cosh), TEST_FUNCTION(arb_sin_pi), TEST_FUNCTION(arb_sin_pi_fmpq_algebraic), TEST_FUNCTION(arb_sin_pi_fmpq), TEST_FUNCTION(arb_special), TEST_FUNCTION(arb_sqrt1pm1), TEST_FUNCTION(arb_sqrt), TEST_FUNCTION(arb_sqrt_newton), TEST_FUNCTION(arb_sqrtpos), TEST_FUNCTION(arb_sub_arf), TEST_FUNCTION(arb_sub), TEST_FUNCTION(arb_sub_fmpz), TEST_FUNCTION(arb_submul_arf), TEST_FUNCTION(arb_submul), TEST_FUNCTION(arb_submul_fmpz), TEST_FUNCTION(arb_submul_si), TEST_FUNCTION(arb_submul_ui), TEST_FUNCTION(arb_sub_si), TEST_FUNCTION(arb_sub_ui), TEST_FUNCTION(arb_tanh), TEST_FUNCTION(arb_tan_pi), TEST_FUNCTION(arb_trim), TEST_FUNCTION(arb_ui_pow_ui), TEST_FUNCTION(arb_union), TEST_FUNCTION(arb_urandom), TEST_FUNCTION(arb_zeta), TEST_FUNCTION(arb_zeta_ui_asymp), TEST_FUNCTION(arb_zeta_ui_bernoulli), TEST_FUNCTION(arb_zeta_ui_borwein_bsplit), TEST_FUNCTION(arb_zeta_ui), TEST_FUNCTION(arb_zeta_ui_euler_product), TEST_FUNCTION(arb_zeta_ui_vec_borwein), TEST_FUNCTION(arb_zeta_ui_vec) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arb/test/t-acos.c000066400000000000000000000056061461254215100165060ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_acos, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_acos(t, t, MPFR_RNDN); arb_acos(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 100); flint_printf("\n\n"); flint_abort(); } arb_acos(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* check large arguments */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 100); arb_acos(b, a, prec1); arb_acos(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check sin(asin(x)) = x */ arb_cos(c, b, prec1); if (!arb_contains(c, a)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-acosh.c000066400000000000000000000043321461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_acosh, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_acosh(a, x, prec1); arb_acosh(b, x, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check cosh(acosh(x)) = x */ arb_cosh(b, b, prec1); if (!arb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } arb_acosh(x, x, prec1); if (!arb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-add.c000066400000000000000000000103701461254215100163030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_add, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t x, y, z; arb_init(a); arb_init(b); arb_init(c); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_add(c, a, b, 2 + n_randint(state, 200)); fmpq_add(z, x, y); if (!arb_contains_fmpq(c, z)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_add(a, a, b, 2 + n_randint(state, 200)); fmpq_add(z, x, y); if (!arb_contains_fmpq(a, z)) { flint_printf("FAIL: aliasing (c, a)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and b */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_add(b, a, b, 2 + n_randint(state, 200)); fmpq_add(z, x, y); if (!arb_contains_fmpq(b, z)) { flint_printf("FAIL: aliasing (c, b)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-add_arf.c000066400000000000000000000054171461254215100171410ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_add_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_add_arf(c, a, x, prec); arb_add(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arf_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_add_arf(c, a, x, prec); arb_add_arf(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-add_error.c000066400000000000000000000177551461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2012-2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_add_error, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t m, r; arb_init(a); arb_init(b); arb_init(c); arf_init(m); arf_init(r); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 10); arf_randtest_special(m, state, 1 + n_randint(state, 2000), 10); arf_randtest_special(r, state, 1 + n_randint(state, 2000), 10); /* c = a plus error bounds */ arb_set(c, a); arf_set(arb_midref(b), m); arf_get_mag(arb_radref(b), r); arb_add_error(c, b); /* b = a + random point */ arb_set(b, a); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), r, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), r, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { flint_printf("FAIL (arb_add_error)\n\n"); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(m); arf_clear(r); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t m; arb_init(a); arb_init(b); arb_init(c); arf_init(m); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 10); arf_randtest_special(m, state, 1 + n_randint(state, 2000), 10); /* c = a plus error bounds */ arb_set(c, a); arb_add_error_arf(c, m); /* b = a + random point */ arb_set(b, a); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { flint_printf("FAIL (arb_add_error_arf)\n\n"); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(m); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t t; mag_t r; arb_init(a); arb_init(b); arb_init(c); mag_init(r); arf_init(t); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); mag_randtest(r, state, 10); /* c = a plus error bounds */ arb_set(c, a); arb_add_error_mag(c, r); /* b = a + random point */ arb_set(b, a); arf_set_mag(t, r); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { flint_printf("FAIL (arb_add_error_mag)\n\n"); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); mag_clear(r); arf_clear(t); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t t; slong e; arb_init(a); arb_init(b); arb_init(c); arf_init(t); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); e = n_randint(state, 10) - 10; /* c = a plus error bounds */ arb_set(c, a); arb_add_error_2exp_si(c, e); /* b = a + random point */ arb_set(b, a); arf_one(t); arf_mul_2exp_si(t, t, e); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { flint_printf("FAIL (arb_add_error_2exp_si)\n\n"); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(t); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t t; fmpz_t e; arb_init(a); arb_init(b); arb_init(c); arf_init(t); fmpz_init(e); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); fmpz_randtest(e, state, 10); /* c = a plus error bounds */ arb_set(c, a); arb_add_error_2exp_fmpz(c, e); /* b = a + random point */ arb_set(b, a); arf_one(t); arf_mul_2exp_fmpz(t, t, e); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { flint_printf("FAIL (arb_add_error_2exp_fmpz)\n\n"); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(t); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-add_fmpz.c000066400000000000000000000054031461254215100173400ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_add_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_add_fmpz(c, a, x, prec); arb_add(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_add_fmpz(c, a, x, prec); arb_add_fmpz(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-add_fmpz_2exp.c000066400000000000000000000054471461254215100203060ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_add_fmpz_2exp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t x, e; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(x); fmpz_init(e); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); fmpz_randtest(e, state, 1 + n_randint(state, 200)); prec = 2 + n_randint(state, 2000); arb_set_fmpz_2exp(b, x, e); arb_add_fmpz_2exp(c, a, x, e, prec); arb_add(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(x); fmpz_clear(e); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, c; fmpz_t x, e; slong prec; arb_init(a); arb_init(c); fmpz_init(x); fmpz_init(e); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); fmpz_randtest(e, state, 1 + n_randint(state, 200)); prec = 2 + n_randint(state, 2000); arb_add_fmpz_2exp(c, a, x, e, prec); arb_add_fmpz_2exp(a, a, x, e, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(c); fmpz_clear(x); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-add_si.c000066400000000000000000000051701461254215100170000ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "long_extras.h" TEST_FUNCTION_START(arb_add_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_add_si(c, a, x, prec); arb_add(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_add_si(c, a, x, prec); arb_add_si(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-add_ui.c000066400000000000000000000051711461254215100170030ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "ulong_extras.h" TEST_FUNCTION_START(arb_add_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_add_ui(c, a, x, prec); arb_add(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_add_ui(c, a, x, prec); arb_add_ui(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-addmul.c000066400000000000000000000226371461254215100170320ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" #ifndef mag_close #define mag_close mag_close int mag_close(const mag_t am, const mag_t bm) { arf_t t, a, b; int res1, res2; arf_init(t); arf_init(a); arf_init(b); arf_set_mag(a, am); arf_set_mag(b, bm); arf_mul_ui(t, b, 257, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(t, t, -8); res1 = arf_cmp(a, t) <= 0; arf_mul_ui(t, a, 257, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(t, t, -8); res2 = arf_cmp(b, t) <= 0; arf_clear(t); arf_clear(a); arf_clear(b); return res1 && res2; } #endif #ifndef arb_equal_mid_close_mag #define arb_equal_mid_close_mag arb_equal_mid_close_mag int arb_equal_mid_close_mag(const arb_t a, const arb_t b) { return arf_equal(arb_midref(a), arb_midref(b)) && (mag_close(arb_radref(a), arb_radref(b)) || /* If a's and b's centres are infinite but their radii are finite, the radii don't need to be close: they represent signed infinity regardless. If their centres are NaN, then we should ignore their radii. */ (arf_is_inf(arb_midref(a)) && arf_is_inf(arb_midref(b)) && mag_is_finite(arb_radref(a)) && mag_is_finite(arb_radref(b))) || (arf_is_nan(arb_midref(a)) && arf_is_nan(arb_midref(b)))); } #endif void arb_addmul_naive(arb_t z, const arb_t x, const arb_t y, slong prec) { arb_t t; arb_init(t); arb_mul(t, x, y, ARF_PREC_EXACT); arb_add(z, z, t, prec); arb_clear(t); } TEST_FUNCTION_START(arb_addmul, state) { slong iter, iter2; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t x, y, z; arb_init(a); arb_init(b); arb_init(c); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_get_rand_fmpq(z, state, c, 1 + n_randint(state, 200)); arb_addmul(c, a, b, 2 + n_randint(state, 200)); fmpq_addmul(z, x, y); if (!arb_contains_fmpq(c, z)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); fmpq_set(z, x); arb_addmul(a, a, b, 2 + n_randint(state, 200)); fmpq_addmul(z, x, y); if (!arb_contains_fmpq(a, z)) { flint_printf("FAIL: aliasing (c, a)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and b */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); fmpq_set(z, y); arb_addmul(b, a, b, 2 + n_randint(state, 200)); fmpq_addmul(z, x, y); if (!arb_contains_fmpq(b, z)) { flint_printf("FAIL: aliasing (c, b)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* main test */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z, v; slong prec; arb_init(x); arb_init(y); arb_init(z); arb_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arb_randtest_special(x, state, n_randint(state,2) ? 2000 : 200, 200); arb_randtest_special(y, state, n_randint(state,2) ? 2000 : 200, 200); arb_randtest_special(z, state, n_randint(state,2) ? 2000 : 200, 200); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 5)) { case 0: arb_set(v, z); arb_addmul(z, x, y, prec); arb_addmul_naive(v, x, y, prec); if (!arb_equal_mid_close_mag(z, v)) { flint_printf("FAIL!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 1: arb_set(y, x); arb_set(z, v); arb_addmul(z, x, y, prec); arb_addmul(v, x, x, prec); if (!arb_equal_mid_close_mag(z, v)) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 2: arb_set(v, x); arb_addmul(v, x, x, prec); arb_addmul(x, x, x, prec); if (!arb_equal_mid_close_mag(x, v)) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 3: arb_set(v, x); arb_addmul(v, x, y, prec); arb_addmul(x, x, y, prec); if (!arb_equal_mid_close_mag(x, v)) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; default: arb_set(v, x); arb_addmul(v, x, y, prec); arb_addmul(x, y, x, prec); if (!arb_equal_mid_close_mag(x, v)) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; } } arb_clear(x); arb_clear(y); arb_clear(z); arb_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-addmul_arf.c000066400000000000000000000055141461254215100176550ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_addmul_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_set(d, c); arb_addmul_arf(c, a, x, prec); arb_addmul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arf_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_set(c, a); arb_addmul_arf(c, a, x, prec); arb_addmul_arf(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-addmul_fmpz.c000066400000000000000000000055001461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_addmul_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_set(d, c); arb_addmul_fmpz(c, a, x, prec); arb_addmul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_set(c, a); arb_addmul_fmpz(c, a, x, prec); arb_addmul_fmpz(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-addmul_si.c000066400000000000000000000052651461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "long_extras.h" TEST_FUNCTION_START(arb_addmul_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_set(d, c); arb_addmul_si(c, a, x, prec); arb_addmul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_set(c, a); arb_addmul_si(c, a, x, prec); arb_addmul_si(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-addmul_ui.c000066400000000000000000000052661461254215100175260ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "ulong_extras.h" TEST_FUNCTION_START(arb_addmul_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_set(d, c); arb_addmul_ui(c, a, x, prec); arb_addmul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_set(c, a); arb_addmul_ui(c, a, x, prec); arb_addmul_ui(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-agm.c000066400000000000000000000101531461254215100163160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_agm, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t q, r; mpfr_t t, u; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); fmpq_init(q); fmpq_init(r); mpfr_init2(t, prec + 100); mpfr_init2(u, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_randtest(c, state, 1 + n_randint(state, 200), 3); arb_agm(c, a, b, prec); if (arb_equal(a, b)) { if (!arb_contains(c, a)) { flint_printf("FAIL: containment (identity)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } } else { arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(r, state, b, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); fmpq_get_mpfr(u, r, MPFR_RNDN); mpfr_agm(t, t, u, MPFR_RNDN); if (!arb_contains_mpfr(c, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(q); fmpq_clear(r); mpfr_clear(t); mpfr_clear(u); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x1, x2, y1, y2, r1, r2; slong prec1, prec2; arb_init(x1); arb_init(x2); arb_init(y1); arb_init(y2); arb_init(r1); arb_init(r2); arb_randtest_special(x1, state, 1 + n_randint(state, 200), 100); arb_randtest_special(y1, state, 1 + n_randint(state, 200), 100); if (n_randint(state, 2)) { arb_randtest_special(r1, state, 1 + n_randint(state, 200), 100); arb_randtest_special(r2, state, 1 + n_randint(state, 200), 100); } else { arb_zero(r1); arb_zero(r2); } prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); arb_add(x2, x1, r1, prec2); arb_sub(x2, x2, r1, prec2); arb_add(y2, y1, r2, prec2); arb_sub(y2, y2, r2, prec2); arb_agm(r1, x1, y1, prec1); arb_agm(r2, x2, y2, prec2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x1 = "); arb_printn(x1, 30, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 30, 0); flint_printf("\n\n"); flint_printf("y1 = "); arb_printn(y1, 30, 0); flint_printf("\n\n"); flint_printf("y2 = "); arb_printn(y2, 30, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 30, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 30, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x1); arb_clear(x2); arb_clear(y1); arb_clear(y2); arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-approx_dot.c000066400000000000000000000202431461254215100177320ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_approx_dot, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr x, y; arb_t s1, s2, z; slong i, len, prec, xbits, ybits, ebits; int initial, subtract, revx, revy; if (n_randint(state, 100) == 0) len = n_randint(state, 100); else if (n_randint(state, 10) == 0) len = n_randint(state, 10); else len = n_randint(state, 3); if (n_randint(state, 10) != 0 || len > 10) { prec = 2 + n_randint(state, 500); xbits = 2 + n_randint(state, 500); ybits = 2 + n_randint(state, 500); } else { prec = 2 + n_randint(state, 4000); xbits = 2 + n_randint(state, 4000); ybits = 2 + n_randint(state, 4000); } if (n_randint(state, 100) == 0) ebits = 2 + n_randint(state, 100); else ebits = 2 + n_randint(state, 10); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arb_vec_init(len); y = _arb_vec_init(len); arb_init(s1); arb_init(s2); arb_init(z); switch (n_randint(state, 3)) { case 0: for (i = 0; i < len; i++) { arb_randtest(x + i, state, xbits, ebits); arb_randtest(y + i, state, ybits, ebits); } break; /* Test with cancellation */ case 1: for (i = 0; i < len; i++) { if (i <= len / 2) { arb_randtest(x + i, state, xbits, ebits); arb_randtest(y + i, state, ybits, ebits); } else { arb_neg(x + i, x + len - i - 1); arb_set(y + i, y + len - i - 1); } } break; default: for (i = 0; i < len; i++) { if (i <= len / 2) { arb_randtest(x + i, state, xbits, ebits); arb_randtest(y + i, state, ybits, ebits); } else { arb_neg_round(x + i, x + len - i - 1, 2 + n_randint(state, 500)); arb_set_round(y + i, y + len - i - 1, 2 + n_randint(state, 500)); } } break; } arb_randtest(s1, state, 200, 100); arb_randtest(s2, state, 200, 100); arb_randtest(z, state, xbits, ebits); arb_approx_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); mag_zero(arb_radref(s1)); /* With the fast algorithm, we expect identical results when reversing the vectors. */ if (ebits <= 12) { arb_approx_dot(s2, initial ? z : NULL, subtract, !revx ? (x + len - 1) : x, !revx ? -1 : 1, !revy ? (y + len - 1) : y, !revy ? -1 : 1, len, prec); mag_zero(arb_radref(s2)); if (!arb_equal(s1, s2)) { flint_printf("FAIL (reversal)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } } /* Verify that radii are ignored */ for (i = 0; i < len; i++) { arb_get_mid_arb(x + i, x + i); arb_get_mid_arb(y + i, y + i); } arb_get_mid_arb(z, z); arb_approx_dot(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); mag_zero(arb_radref(s2)); if (!arb_equal(s1, s2)) { flint_printf("FAIL (radii)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } /* Compare with arb_dot */ arb_approx_dot(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); { mag_t err, xx, yy; mag_init(err); mag_init(xx); mag_init(yy); if (initial) arb_get_mag(err, z); for (i = 0; i < len; i++) { arb_get_mag(xx, revx ? x + len - 1 - i : x + i); arb_get_mag(yy, revx ? y + len - 1 - i : y + i); mag_addmul(err, xx, yy); } mag_mul_2exp_si(err, err, -prec + 2); arb_add_error_mag(s2, err); if (!arb_contains(s2, s1)) { flint_printf("FAIL (inclusion)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } mag_clear(err); mag_clear(xx); mag_clear(yy); } arb_clear(s1); arb_clear(s2); arb_clear(z); _arb_vec_clear(x, len); _arb_vec_clear(y, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-asin.c000066400000000000000000000055721461254215100165150ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_asin, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_asin(t, t, MPFR_RNDN); arb_asin(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_asin(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* check large arguments */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 100); arb_asin(b, a, prec1); arb_asin(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check sin(asin(x)) = x */ arb_sin(c, b, prec1); if (!arb_contains(c, a)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-asinh.c000066400000000000000000000043321461254215100166560ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_asinh, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_asinh(a, x, prec1); arb_asinh(b, x, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check sinh(asinh(x)) = x */ arb_sinh(b, b, prec1); if (!arb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } arb_asinh(x, x, prec1); if (!arb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan.c000066400000000000000000000156371461254215100165110ustar00rootroot00000000000000/* Copyright (C) 2012-2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_atan, state) { slong iter; /* Compare with MPFR */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_atan(t, t, MPFR_RNDN); arb_atan(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_atan(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* Check large arguments. */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 100); arb_atan(b, a, prec1); arb_atan(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check tan(atan(x)) = x */ arb_sin_cos(c, d, b, prec1); arb_div(c, c, d, prec1); if (!arb_contains(c, a)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* Compare with MPFR, higher precision. */ for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 5000); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 5000), 8); arb_randtest(b, state, 1 + n_randint(state, 5000), 8); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_atan(t, t, MPFR_RNDN); arb_atan(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 50); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 50); flint_printf("\n\n"); flint_abort(); } arb_atan(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* Higher precision + large arguments. */ for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 5000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(a, state, 1 + n_randint(state, 5000), 100); arb_atan(b, a, prec1); arb_atan(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check tan(atan(x)) = x */ arb_sin_cos(c, d, b, prec1); arb_div(c, c, d, prec1); if (!arb_contains(c, a)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* Check wide arguments. */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 100); arb_randtest_precise(b, state, 1 + n_randint(state, 1000), 100); if (n_randint(state, 2)) arb_add(a, a, b, 2 + n_randint(state, 1000)); arb_union(d, a, b, 2 + n_randint(state, 1000)); arb_atan(a, a, 2 + n_randint(state, 2000)); arb_atan(b, b, 2 + n_randint(state, 2000)); arb_atan(c, d, 2 + n_randint(state, 2000)); if (!arb_overlaps(c, a) || !arb_overlaps(c, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan2.c000066400000000000000000000036001461254215100165560ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_atan2, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t q, r; mpfr_t t, u; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); fmpq_init(q); fmpq_init(r); mpfr_init2(t, prec + 100); mpfr_init2(u, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_randtest(c, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(r, state, b, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); fmpq_get_mpfr(u, r, MPFR_RNDN); mpfr_atan2(t, u, t, MPFR_RNDN); arb_atan2(c, b, a, prec); if (!arb_contains_mpfr(c, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(q); fmpq_clear(r); mpfr_clear(t); mpfr_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_arf.c000066400000000000000000000046171461254215100173350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_atan_arf, state) { slong iter; /* self-consistency test */ for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; arb_t y1, y2; slong prec1, prec2, acc1, acc2; prec1 = 2 + n_randint(state, 9000); prec2 = 2 + n_randint(state, 9000); arf_init(x); arb_init(y1); arb_init(y2); arf_randtest_special(x, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y1, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y2, state, 1 + n_randint(state, 9000), 200); if (n_randint(state, 2)) arf_add_ui(x, x, 1, 2 + n_randint(state, 9000), ARF_RND_DOWN); arb_atan_arf(y1, x, prec1); arb_atan_arf(y2, x, prec2); if (!arb_overlaps(y1, y2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y1 = "); arb_print(y1); flint_printf("\n\n"); flint_printf("y2 = "); arb_print(y2); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(y1); acc2 = arb_rel_accuracy_bits(y2); if (!arf_is_nan(x)) { if (acc1 < prec1 - 2 || acc2 < prec2 - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("acc1 = %wd, acc2 = %wd\n\n", acc1, acc2); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("y1 = "); arb_printd(y1, 50); flint_printf("\n\n"); flint_printf("y2 = "); arb_printd(y2, 50); flint_printf("\n\n"); flint_abort(); } } arf_clear(x); arb_clear(y1); arb_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_arf_bb.c000066400000000000000000000061021461254215100177670ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" #ifndef arb_atan_arf_via_mpfr #define arb_atan_arf_via_mpfr arb_atan_arf_via_mpfr void arb_atan_arf_via_mpfr(arb_t z, const arf_t x, slong prec) { mpfr_t t, u; int exact; mpfr_init2(t, 2 + arf_bits(x)); mpfr_init2(u, prec); mpfr_set_emin(MPFR_EMIN_MIN); mpfr_set_emax(MPFR_EMAX_MAX); arf_get_mpfr(t, x, MPFR_RNDD); exact = (mpfr_atan(u, t, MPFR_RNDD) == 0); arf_set_mpfr(arb_midref(z), u); if (!exact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); mpfr_clear(t); mpfr_clear(u); } #endif TEST_FUNCTION_START(arb_atan_arf_bb, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; slong prec, prec2; arb_init(x); arb_init(y); arb_init(z); prec = 2 + n_randint(state, 8000); if (n_randint(state, 100) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); arb_randtest(x, state, 1 + n_randint(state, 8000), 3); mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_mul_2exp_si(x, x, 1 + n_randint(state, 40)); else arb_mul_2exp_si(x, x, -n_randint(state, 1.5 * prec)); if (!arf_is_special(arb_midref(x))) prec2 = prec + 100 + 2 * (-ARF_EXP(arb_midref(x))); else prec2 = prec + 100; arb_atan_arf_via_mpfr(y, arb_midref(x), prec2); arb_atan_arf_bb(z, arb_midref(x), prec); if (!arb_contains(z, y)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 50); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(z) < prec - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd, acc = %wd\n\n", prec, arb_rel_accuracy_bits(z)); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 50); flint_printf("\n\n"); flint_abort(); } arb_atan_arf_bb(x, arb_midref(x), prec); if (!arb_overlaps(x, z)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_arf_newton.c000066400000000000000000000061361461254215100207250ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" #ifndef arb_atan_arf_via_mpfr #define arb_atan_arf_via_mpfr arb_atan_arf_via_mpfr void arb_atan_arf_via_mpfr(arb_t z, const arf_t x, slong prec) { mpfr_t t, u; int exact; mpfr_init2(t, 2 + arf_bits(x)); mpfr_init2(u, prec); mpfr_set_emin(MPFR_EMIN_MIN); mpfr_set_emax(MPFR_EMAX_MAX); arf_get_mpfr(t, x, MPFR_RNDD); exact = (mpfr_atan(u, t, MPFR_RNDD) == 0); arf_set_mpfr(arb_midref(z), u); if (!exact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); mpfr_clear(t); mpfr_clear(u); } #endif TEST_FUNCTION_START(arb_atan_arf_newton, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; slong prec, prec2; arb_init(x); arb_init(y); arb_init(z); prec = 2 + n_randint(state, 8000); if (n_randint(state, 100) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); arb_randtest(x, state, 1 + n_randint(state, 8000), 3); mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_mul_2exp_si(x, x, n_randint(state, 1.5 * prec)); else arb_mul_2exp_si(x, x, -n_randint(state, 1.5 * prec)); if (!arf_is_special(arb_midref(x))) prec2 = prec + 100 + 2 * FLINT_MAX(0, -ARF_EXP(arb_midref(x))); else prec2 = prec + 100; arb_atan_arf_via_mpfr(y, arb_midref(x), prec2); arb_atan_arf_newton(z, arb_midref(x), prec); if (!arb_contains(z, y)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 50); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(z) < prec - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd, acc = %wd\n\n", prec, arb_rel_accuracy_bits(z)); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 50); flint_printf("\n\n"); flint_abort(); } arb_atan_arf_newton(x, arb_midref(x), prec); if (!arb_overlaps(x, z)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_frac_bsplit.c000066400000000000000000000040341461254215100210460ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_atan_frac_bsplit, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s, t; fmpz_t p, q; slong prec; int hyperbolic; arb_init(s); arb_init(t); fmpz_init(p); fmpz_init(q); prec = 2 + n_randint(state, 800); hyperbolic = n_randint(state, 2); fmpz_randtest(p, state, 100); fmpz_randtest_not_zero(q, state, 100); arb_atan_frac_bsplit(s, p, q, hyperbolic, prec); if (arb_is_finite(s)) { arb_set_fmpz(t, p); arb_div_fmpz(t, t, q, prec); if (hyperbolic) arb_atanh(t, t, prec); else arb_atan(t, t, prec); if (!arb_overlaps(s, t)) { flint_printf("FAIL: overlap\n\n"); flint_printf("s = "); arb_printd(s, 100); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 100); flint_printf("\n\n"); flint_abort(); } } if (fabs(fmpz_get_d(p) / fmpz_get_d(q)) < 0.75 && arb_rel_accuracy_bits(s) < prec - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("s = "); arb_printd(s, 100); flint_printf("\n\n"); flint_printf("%wd, %wd\n", prec, arb_rel_accuracy_bits(s)); flint_abort(); } arb_clear(s); arb_clear(t); fmpz_clear(p); fmpz_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_gauss_primes_vec_bsplit.c000066400000000000000000000043721461254215100234760ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" /* Consecutively, real and imaginary parts of first 64 nonreal Gaussian primes. */ static const signed char small_gaussian_primes[] = { 1, 1, 1, 2, 2, 3, 1, 4, 2, 5, 1, 6, 4, 5, 2, 7, 5, 6, 3, 8, 5, 8, 4, 9, 1, 10, 3, 10, 7, 8, 4, 11, 7, 10, 6, 11, 2, 13, 9, 10, 7, 12, 1, 14, 2, 15, 8, 13, 4, 15, 1, 16, 10, 13, 9, 14, 5, 16, 2, 17, 12, 13, 11, 14, 9, 16, 5, 18, 8, 17, 7, 18, 10, 17, 6, 19, 1, 20, 3, 20, 14, 15, 12, 17, 7, 20, 4, 21, 10, 19, 5, 22, 11, 20, 10, 21, 14, 19, 13, 20, 1, 24, 8, 23, 5, 24, 17, 18, 16, 19, 4, 25, 13, 22, 6, 25, 12, 23, 1, 26, 5, 26, 15, 22, 2, 27, 9, 26 }; TEST_FUNCTION_START(arb_atan_gauss_primes_vec_bsplit, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr v; arb_t t; slong n, j, prec; prec = 2 + n_randint(state, 700); n = n_randint(state, 30); flint_set_num_threads(1 + n_randint(state, 3)); v = _arb_vec_init(n); arb_init(t); arb_atan_gauss_primes_vec_bsplit(v, n, prec); for (j = 0; j < n; j++) { arb_set_ui(t, small_gaussian_primes[2 * j + 1]); arb_div_ui(t, t, small_gaussian_primes[2 * j], prec); arb_atan(t, t, prec); if (!arb_overlaps(v + j, t) || arb_rel_accuracy_bits(v + j) < prec - 5) { flint_printf("FAIL\n\n"); flint_printf("n = %wu, j = %wd\n", n, j); flint_printf("v = "); arb_printd(v + j, 100); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 100); flint_printf("\n\n"); flint_printf("%wd, %wd\n", prec, arb_rel_accuracy_bits(v + j)); flint_abort(); } } _arb_vec_clear(v, n); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_newton.c000066400000000000000000000110301461254215100200620ustar00rootroot00000000000000/* Copyright (C) 2012-2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_atan_newton, state) { slong iter; /* Check large arguments. */ for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 100); arb_atan_newton(b, a, prec1); arb_atan_newton(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check tan(atan(x)) = x */ arb_sin_cos(c, d, b, prec1); arb_div(c, c, d, prec1); if (!arb_contains(c, a)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* Higher precision + large arguments. */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 5000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(a, state, 1 + n_randint(state, 5000), 100); arb_atan_newton(b, a, prec1); arb_atan_newton(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check tan(atan(x)) = x */ arb_sin_cos(c, d, b, prec1); arb_div(c, c, d, prec1); if (!arb_contains(c, a)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* Check wide arguments. */ for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 100); arb_randtest_precise(b, state, 1 + n_randint(state, 1000), 100); if (n_randint(state, 2)) arb_add(a, a, b, 2 + n_randint(state, 1000)); arb_union(d, a, b, 2 + n_randint(state, 1000)); arb_atan_newton(a, a, 2 + n_randint(state, 2000)); arb_atan_newton(b, b, 2 + n_randint(state, 2000)); arb_atan_newton(c, d, 2 + n_randint(state, 2000)); if (!arb_overlaps(c, a) || !arb_overlaps(c, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_sum_bs_powtab.c000066400000000000000000000037601461254215100214270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_atan_sum_bs_powtab, state) { slong iter; for (iter = 0; iter < 2500 * 0.1 * flint_test_multiplier(); iter++) { slong N; fmpz_t x, T, Q; fmpq_t S, V; flint_bitcnt_t Qexp, r; fmpz_init(x); fmpz_init(T); fmpz_init(Q); fmpq_init(S); fmpq_init(V); if (n_randint(state, 100) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); N = 1 + n_randint(state, 200); r = n_randint(state, 10); fmpz_randtest(x, state, 30); _arb_atan_sum_bs_simple(T, Q, &Qexp, x, r, N); fmpq_set_fmpz_frac(S, T, Q); fmpq_div_2exp(S, S, Qexp); _arb_atan_sum_bs_powtab(T, Q, &Qexp, x, r, N); fmpq_set_fmpz_frac(V, T, Q); fmpq_div_2exp(V, V, Qexp); if (!fmpq_equal(S, V)) { flint_printf("FAIL\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("r = %wu\n\n", r); flint_printf("x = "); fmpz_print(x); flint_printf("\n\n"); flint_printf("T = "); fmpz_print(T); flint_printf("\n\n"); flint_printf("Q = "); fmpz_print(T); flint_printf("\n\n"); flint_printf("V = "); fmpq_print(V); flint_printf("\n\n"); flint_printf("S = "); fmpq_print(S); flint_printf("\n\n"); flint_abort(); } fmpz_clear(x); fmpz_clear(T); fmpz_clear(Q); fmpq_clear(S); fmpq_clear(V); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_tab.c000066400000000000000000000120341461254215100173230ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_atan_tab, state) { slong i; mpfr_t tabx, atanx, y1, y2; mpz_t tt; { slong prec, bits, num; prec = ARB_ATAN_TAB1_LIMBS * FLINT_BITS; bits = ARB_ATAN_TAB1_BITS; num = 1 << ARB_ATAN_TAB1_BITS; mpfr_init2(tabx, prec); mpfr_init2(atanx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_atan_tab1[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(atanx, i, MPFR_RNDD); mpfr_div_2ui(atanx, atanx, bits, MPFR_RNDD); mpfr_atan(atanx, atanx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, atanx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(atanx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_ATAN_TAB2_LIMBS * FLINT_BITS; bits = ARB_ATAN_TAB21_BITS; num = 1 << ARB_ATAN_TAB21_BITS; mpfr_init2(tabx, prec); mpfr_init2(atanx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_atan_tab21[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(atanx, i, MPFR_RNDD); mpfr_div_2ui(atanx, atanx, bits, MPFR_RNDD); mpfr_atan(atanx, atanx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, atanx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(atanx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_ATAN_TAB2_LIMBS * FLINT_BITS; bits = ARB_ATAN_TAB21_BITS + ARB_ATAN_TAB22_BITS; num = 1 << ARB_ATAN_TAB22_BITS; mpfr_init2(tabx, prec); mpfr_init2(atanx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_atan_tab22[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(atanx, i, MPFR_RNDD); mpfr_div_2ui(atanx, atanx, bits, MPFR_RNDD); mpfr_atan(atanx, atanx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, atanx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(atanx); mpfr_clear(y1); mpfr_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atan_taylor_rs.c000066400000000000000000000043071461254215100205770ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_atan_taylor_rs, state) { slong iter; _flint_rand_init_gmp(state); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mp_ptr x, y1, y2, t; mp_limb_t err1, err2; ulong N; mp_size_t xn; int alternating, cmp, result; N = n_randint(state, 256); alternating = n_randint(state, 2); xn = 1 + n_randint(state, 20); x = flint_malloc(sizeof(mp_limb_t) * xn); y1 = flint_malloc(sizeof(mp_limb_t) * xn); y2 = flint_malloc(sizeof(mp_limb_t) * xn); t = flint_malloc(sizeof(mp_limb_t) * xn); flint_mpn_rrandom(x, state->gmp_state, xn); x[xn - 1] &= (LIMB_ONES >> 4); _arb_atan_taylor_naive(y1, &err1, x, xn, N, alternating); _arb_atan_taylor_rs(y2, &err2, x, xn, N, alternating); cmp = mpn_cmp(y1, y2, xn); if (cmp == 0) { result = 1; } else if (cmp > 0) { mpn_sub_n(t, y1, y2, xn); result = flint_mpn_zero_p(t + 1, xn - 1) && (t[0] <= err2); } else { mpn_sub_n(t, y2, y1, xn); result = flint_mpn_zero_p(t + 1, xn - 1) && (t[0] <= err2); } if (!result) { flint_printf("FAIL\n"); flint_printf("N = %wd xn = %wd alternating = %d\n", N, xn, alternating); flint_printf("x ="); flint_mpn_debug(x, xn); flint_printf("y1 ="); flint_mpn_debug(y1, xn); flint_printf("y2 ="); flint_mpn_debug(y2, xn); flint_abort(); } flint_free(x); flint_free(y1); flint_free(y2); flint_free(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-atanh.c000066400000000000000000000043321461254215100166470ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_atanh, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_atanh(a, x, prec1); arb_atanh(b, x, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* check tanh(atanh(x)) = x */ arb_tanh(b, b, prec1); if (!arb_contains(b, x)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_abort(); } arb_atanh(x, x, prec1); if (!arb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-bell_fmpz.c000066400000000000000000000044151461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_bell_fmpz, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t b1, b2; fmpz_t n; slong prec1, prec2, acc1, acc2; fmpz_init(n); arb_init(b1); arb_init(b2); if (iter % 100 == 0) { fmpz_randtest(n, state, 1 + n_randint(state, 100)); fmpz_abs(n, n); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); } else { fmpz_randtest(n, state, 1 + n_randint(state, 20)); fmpz_abs(n, n); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); } arb_bell_fmpz(b1, n, prec1); arb_bell_fmpz(b2, n, prec2); if (!arb_overlaps(b1, b2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("b1 = "); arb_printn(b1, 50, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, 50, 0); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(b1); acc2 = arb_rel_accuracy_bits(b2); if (acc1 < prec1 - 4 || acc2 < prec2 - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd\n", prec1, acc1); flint_printf("prec2 = %wd, acc2 = %wd\n", prec2, acc2); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("b1 = "); arb_printn(b1, 50, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(b1); arb_clear(b2); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-bell_sum_taylor.c000066400000000000000000000035631461254215100207550ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_bell_sum_taylor, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s1, s2; fmpz_t a, b, n; slong prec; arb_init(s1); arb_init(s2); fmpz_init(a); fmpz_init(b); fmpz_init(n); prec = 2 + n_randint(state, 300); fmpz_randtest_unsigned(n, state, 1 + n_randint(state, 100)); fmpz_randtest_unsigned(a, state, 1 + n_randint(state, 100)); fmpz_add_ui(b, a, n_randint(state, 100)); arb_bell_sum_bsplit(s1, n, a, b, NULL, prec); arb_bell_sum_taylor(s2, n, a, b, NULL, prec); if (!arb_overlaps(s1, s2) || (arb_rel_accuracy_bits(s1) < prec - 4) || (arb_rel_accuracy_bits(s2) < prec - 4)) { flint_printf("FAIL: overlap or accuracy\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); fmpz_clear(a); fmpz_clear(b); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-bernoulli_poly_ui.c000066400000000000000000000041441461254215100213100ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_bernoulli_poly_ui, state) { slong iter; /* test multiplication theorem */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, t, res1, res2; ulong n, m, k; slong prec; n = n_randint(state, 50); m = 1 + n_randint(state, 5); prec = 2 + n_randint(state, 200); arb_init(x); arb_init(t); arb_init(res1); arb_init(res2); arb_randtest(x, state, 2 + n_randint(state, 200), 20); arb_randtest(res1, state, 2 + n_randint(state, 200), 20); arb_mul_ui(t, x, m, prec); arb_bernoulli_poly_ui(res1, n, t, prec); arb_zero(res2); for (k = 0; k < m; k++) { arb_set_ui(t, k); arb_div_ui(t, t, m, prec); arb_add(t, t, x, prec); arb_bernoulli_poly_ui(t, n, t, prec); arb_add(res2, res2, t, prec); } if (n > 0) { arb_ui_pow_ui(t, m, n - 1, prec); arb_mul(res2, res2, t, prec); } else { arb_div_ui(res2, res2, m, prec); } if (!arb_overlaps(res1, res2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu, m = %wu\n\n", n, m); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("res1 = "); arb_printd(res1, 15); flint_printf("\n\n"); flint_printf("res2 = "); arb_printd(res2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(t); arb_clear(res1); arb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-bernoulli_ui.c000066400000000000000000000034171461254215100202470ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_bernoulli_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t b1, b2; ulong n; slong prec1, prec2, acc1, acc2; n = n_randint(state, 10000); prec1 = 2 + n_randint(state, 10000); prec2 = prec1 + 100; arb_init(b1); arb_init(b2); arb_bernoulli_ui(b1, n, prec1); arb_bernoulli_ui(b2, n, prec2); if (!arb_overlaps(b1, b2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("b1 = "); arb_print(b1); flint_printf("\n\n"); flint_printf("b2 = "); arb_print(b2); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(b1); acc2 = arb_rel_accuracy_bits(b2); if (acc1 < prec1 - 2 || acc2 < prec2 - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec1 = %wd\n", prec1); flint_printf("prec2 = %wd\n", prec2); flint_printf("b1 = "); arb_printd(b1, prec1 / 3.33); flint_printf("\n\n"); flint_printf("b2 = "); arb_printd(b2, prec2 / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(b1); arb_clear(b2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-can_round_mpfr.c000066400000000000000000000041371461254215100205530ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_can_round_mpfr, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { mpfr_t x, y1, y2; int r1, r2; arb_t t; slong prec; mpfr_rnd_t rnd; prec = 2 + n_randint(state, 300); mpfr_init2(x, 2 + n_randint(state, 300)); mpfr_init2(y1, prec); mpfr_init2(y2, prec); arb_init(t); switch (n_randint(state, 5)) { case 0: rnd = MPFR_RNDN; break; case 1: rnd = MPFR_RNDZ; break; case 2: rnd = MPFR_RNDU; break; case 3: rnd = MPFR_RNDD; break; default: rnd = MPFR_RNDA; } arf_randtest(arb_midref(t), state, mpfr_get_prec(x), 1 + n_randint(state, 10)); arf_abs(arb_midref(t), arb_midref(t)); arf_get_mpfr(x, arb_midref(t), MPFR_RNDN); arb_root_ui(t, t, 4, 2 + n_randint(state, 300)); if (arb_can_round_mpfr(t, prec, rnd)) { r1 = mpfr_rootn_ui(y1, x, 4, rnd); r2 = arf_get_mpfr(y2, arb_midref(t), rnd); if (r1 != r2 || !mpfr_equal_p(y1, y2)) { flint_printf("FAIL!\n"); flint_printf("r1 = %d, r2 = %d, prec = %wd\n", r1, r2, prec); flint_printf("x = "); mpfr_dump(x); flint_printf("\n"); flint_printf("y1 = "); mpfr_dump(y1); flint_printf("\n"); flint_printf("y2 = "); mpfr_dump(y2); flint_printf("\n"); flint_abort(); } } arb_clear(t); mpfr_clear(x); mpfr_clear(y1); mpfr_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-ceil.c000066400000000000000000000035741461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_ceil, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x; fmpz_t y; slong prec; arb_init(a); arb_init(b); fmpq_init(x); fmpz_init(y); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_ceil(b, a, prec); fmpz_cdiv_q(y, fmpq_numref(x), fmpq_denref(x)); if (!arb_contains_fmpz(b, y)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_abort(); } arb_ceil(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-chebyshev_t_ui.c000066400000000000000000000062421461254215100205560ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_chebyshev_t_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; ulong n; slong prec; n = n_randtest(state); prec = 2 + n_randint(state, 300); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest(a, state, 1 + n_randint(state, 300), 5); arb_randtest(c, state, 1 + n_randint(state, 300), 5); arb_cos(b, a, prec); arb_chebyshev_t_ui(c, n, b, prec); arb_mul_ui(d, a, n, prec); arb_cos(d, d, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: c = T_n(cos(a)) = d = cos(n*a)\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("d = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_chebyshev_t_ui(b, n, b, prec); if (!arb_equal(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_randtest(a, state, 1 + n_randint(state, 300), 5); arb_randtest(b, state, 1 + n_randint(state, 300), 5); arb_randtest(c, state, 1 + n_randint(state, 300), 5); arb_chebyshev_t2_ui(b, c, n, a, prec); arb_chebyshev_t_ui(d, n, a, prec); if (!arb_overlaps(b, d)) { flint_printf("FAIL: T_n\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } if (n == 0) arb_set(d, a); else arb_chebyshev_t_ui(d, n - 1, a, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: T_{n-1}\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-chebyshev_u_ui.c000066400000000000000000000071421461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_chebyshev_u_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d, e; ulong n; slong prec; n = n_randtest(state); prec = 2 + n_randint(state, 300); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_init(e); arb_randtest_precise(a, state, 1 + n_randint(state, 300), 5); arb_randtest_precise(c, state, 1 + n_randint(state, 300), 5); arb_sin_cos(d, b, a, prec); arb_chebyshev_u_ui(c, n, b, prec); arb_mul(d, c, d, prec); if (n == LIMB_ONES) arb_mul_2exp_si(e, a, FLINT_BITS); else arb_mul_ui(e, a, n + 1, prec); arb_sin(e, e, prec); if (!arb_overlaps(d, e)) { flint_printf("FAIL: sin(a)*U_n(cos(a)) = sin((n+1)a)\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 15); flint_printf("\n\n"); flint_printf("e = "); arb_printd(e, 15); flint_printf("\n\n"); flint_abort(); } arb_chebyshev_u_ui(b, n, b, prec); if (!arb_equal(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_randtest(a, state, 1 + n_randint(state, 300), 5); arb_randtest(b, state, 1 + n_randint(state, 300), 5); arb_randtest(c, state, 1 + n_randint(state, 300), 5); arb_chebyshev_u2_ui(b, c, n, a, prec); arb_chebyshev_u_ui(d, n, a, prec); if (!arb_overlaps(b, d)) { flint_printf("FAIL: U_n\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } if (n == 0) arb_zero(d); else arb_chebyshev_u_ui(d, n - 1, a, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: U_{n-1}\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arb_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_apery.c000066400000000000000000000027511461254215100201050ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_const_apery, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; mpfr_t s; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 17)); arb_init(r); mpfr_init2(s, prec + 1000); arb_const_apery(r, prec); mpfr_zeta_ui(s, 3, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_catalan.c000066400000000000000000000027601461254215100203700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_const_catalan, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; mpfr_t s; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 16)); arb_init(r); mpfr_init2(s, prec + 1000); arb_const_catalan(r, prec); mpfr_const_catalan(s, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_e.c000066400000000000000000000030031461254215100172000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_const_e, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; mpfr_t s; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 16)); arb_init(r); mpfr_init2(s, prec + 1000); arb_const_e(r, prec); mpfr_set_ui(s, 1, MPFR_RNDN); mpfr_exp(s, s, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_euler.c000066400000000000000000000030431461254215100200740ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_const_euler, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; mpfr_t s; slong accuracy, prec; flint_set_num_threads(1 + n_randint(state, 3)); prec = 2 + n_randint(state, 1 << n_randint(state, 16)); arb_init(r); mpfr_init2(s, prec + 1000); arb_const_euler(r, prec); mpfr_const_euler(s, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_glaisher.c000066400000000000000000000041221461254215100205550ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_const_glaisher, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r, s, t; fmpz_t v; slong accuracy, prec; prec = 2 + n_randint(state, 2000); arb_init(r); arb_init(s); arb_init(t); fmpz_init(v); arb_const_glaisher(r, prec); arb_const_glaisher(s, prec + 100); if (!arb_overlaps(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 30) == 0) { flint_cleanup(); } fmpz_set_str(v, "128242712910062263687534256886979172776768892732500", 10); arb_set_fmpz(t, v); mag_one(arb_radref(t)); fmpz_ui_pow_ui(v, 10, 50); arb_div_fmpz(t, t, v, 170); if (!arb_overlaps(r, t)) { flint_printf("FAIL: reference value\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); arb_clear(s); arb_clear(t); fmpz_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_khinchin.c000066400000000000000000000026761461254215100205660ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_const_khinchin, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r, s; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 14)); arb_init(r); arb_init(s); arb_const_khinchin(r, prec); arb_const_khinchin(s, prec + 1000); if (!arb_overlaps(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); arb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_log10.c000066400000000000000000000030141461254215100177000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_const_log10, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; mpfr_t s; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 16)); arb_init(r); mpfr_init2(s, prec + 1000); arb_const_log10(r, prec); mpfr_set_ui(s, 10, MPFR_RNDN); mpfr_log(s, s, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_log2.c000066400000000000000000000027471461254215100176350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_const_log2, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; mpfr_t s; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 16)); arb_init(r); mpfr_init2(s, prec + 1000); arb_const_log2(r, prec); mpfr_const_log2(s, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_pi.c000066400000000000000000000030321461254215100173660ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_const_pi, state) { slong iter; for (iter = 0; iter < 250 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; mpfr_t s; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 18)); flint_set_num_threads(1 + n_randint(state, 3)); arb_init(r); mpfr_init2(s, prec + 1000); arb_const_pi(r, prec); mpfr_const_pi(s, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-const_reciprocal_fibonacci.c000066400000000000000000000032131461254215100230770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_const_reciprocal_fibonacci, state) { slong iter; for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { arb_t r, s, t; slong accuracy, prec; prec = 2 + n_randint(state, 1 << n_randint(state, 14)); arb_init(r); arb_init(s); arb_init(t); arb_const_reciprocal_fibonacci(r, prec); arb_const_reciprocal_fibonacci(s, prec + 100); arb_set_str(t, "3.3598856662431775531720113029189271797 +/- 2.82e-38", 128); if (!arb_overlaps(r, s) || !arb_overlaps(r, t) || !arb_overlaps(s, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); arb_clear(s); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-contains.c000066400000000000000000000044321461254215100173730ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_contains, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t am, ar, bm, br, t, u; int c1, c2; arb_init(a); arb_init(b); fmpq_init(am); fmpq_init(ar); fmpq_init(bm); fmpq_init(br); fmpq_init(t); fmpq_init(u); arb_randtest(a, state, 1 + n_randint(state, 500), 14); arb_randtest(b, state, 1 + n_randint(state, 500), 14); arf_get_fmpq(am, arb_midref(a)); mag_get_fmpq(ar, arb_radref(a)); arf_get_fmpq(bm, arb_midref(b)); mag_get_fmpq(br, arb_radref(b)); c1 = arb_contains(a, b); fmpq_sub(t, am, ar); fmpq_sub(u, bm, br); c2 = fmpq_cmp(t, u) <= 0; fmpq_add(t, am, ar); fmpq_add(u, bm, br); c2 = c2 && (fmpq_cmp(t, u) >= 0); if (c1 != c2) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("am = "); fmpq_print(am); flint_printf("\n\n"); flint_printf("ar = "); fmpq_print(ar); flint_printf("\n\n"); flint_printf("bm = "); fmpq_print(bm); flint_printf("\n\n"); flint_printf("br = "); fmpq_print(br); flint_printf("\n\n"); flint_printf("t = "); fmpq_print(t); flint_printf("\n\n"); flint_printf("u = "); fmpq_print(u); flint_printf("\n\n"); flint_printf("c1 = %d, c2 = %d\n\n", c1, c2); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(am); fmpq_clear(ar); fmpq_clear(bm); fmpq_clear(br); fmpq_clear(t); fmpq_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-contains_arf.c000066400000000000000000000037171461254215100202300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_contains_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a; arf_t b; fmpq_t am, ar, bm, t; int c1, c2; arb_init(a); arf_init(b); fmpq_init(am); fmpq_init(ar); fmpq_init(bm); fmpq_init(t); arb_randtest(a, state, 1 + n_randint(state, 500), 14); arf_randtest(b, state, 1 + n_randint(state, 500), 14); arf_get_fmpq(am, arb_midref(a)); mag_get_fmpq(ar, arb_radref(a)); arf_get_fmpq(bm, b); c1 = arb_contains_arf(a, b); fmpq_sub(t, am, ar); c2 = fmpq_cmp(t, bm) <= 0; fmpq_add(t, am, ar); c2 = c2 && (fmpq_cmp(t, bm) >= 0); if (c1 != c2) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("am = "); fmpq_print(am); flint_printf("\n\n"); flint_printf("ar = "); fmpq_print(ar); flint_printf("\n\n"); flint_printf("bm = "); fmpq_print(bm); flint_printf("\n\n"); flint_printf("t = "); fmpq_print(t); flint_printf("\n\n"); flint_printf("c1 = %d, c2 = %d\n\n", c1, c2); flint_abort(); } arb_clear(a); arf_clear(b); fmpq_clear(am); fmpq_clear(ar); fmpq_clear(bm); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-contains_fmpq.c000066400000000000000000000045171461254215100204220ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_contains_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; fmpq_t y; fmpz_t a, b, t; int c1, c2; slong shift; arb_init(x); fmpq_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(t); arb_randtest_special(x, state, 1 + n_randint(state, 500), 12); if (n_randint(state, 2) && arb_is_finite(x)) { arb_get_rand_fmpq(y, state, x, 1 + n_randint(state, 500)); fmpz_add_si(fmpq_numref(y), fmpq_numref(y), n_randint(state, 3) - 1); } else fmpq_randtest(y, state, 1 + n_randint(state, 500)); c1 = arb_contains_fmpq(x, y); if (arb_is_finite(x)) { arb_get_interval_fmpz_2exp(a, b, t, x); shift = fmpz_get_si(t); fmpz_mul(a, a, fmpq_denref(y)); fmpz_mul(b, b, fmpq_denref(y)); fmpz_set(t, fmpq_numref(y)); if (shift >= 0) { fmpz_mul_2exp(a, a, shift); fmpz_mul_2exp(b, b, shift); } else { fmpz_mul_2exp(t, t, -shift); } c2 = (fmpz_cmp(a, t) <= 0) && (fmpz_cmp(t, b) <= 0); } else { fmpz_tdiv_q(t, fmpq_numref(y), fmpq_denref(y)); c2 = arb_contains_fmpz(x, t); } if (c1 != c2) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c1 = %d, c2 = %d\n\n", c1, c2); flint_abort(); } arb_clear(x); fmpq_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-contains_int.c000066400000000000000000000023371461254215100202470ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_contains_int, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a; slong c; int r, ok; arb_init(a); arb_randtest_special(a, state, 1 + n_randint(state, 500), 2); r = arb_contains_int(a); ok = !r; for (c = 0; c < 10; c++) { if (arb_contains_si(a, c) || arb_contains_si(a, -c)) { ok = !ok; break; } } if (!ok) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("r = %d\n\n", r); flint_abort(); } arb_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-contains_interior.c000066400000000000000000000044521461254215100213100ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_contains_interior, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t am, ar, bm, br, t, u; int c1, c2; arb_init(a); arb_init(b); fmpq_init(am); fmpq_init(ar); fmpq_init(bm); fmpq_init(br); fmpq_init(t); fmpq_init(u); arb_randtest(a, state, 1 + n_randint(state, 500), 14); arb_randtest(b, state, 1 + n_randint(state, 500), 14); arf_get_fmpq(am, arb_midref(a)); mag_get_fmpq(ar, arb_radref(a)); arf_get_fmpq(bm, arb_midref(b)); mag_get_fmpq(br, arb_radref(b)); c1 = arb_contains_interior(a, b); fmpq_sub(t, am, ar); fmpq_sub(u, bm, br); c2 = fmpq_cmp(t, u) < 0; fmpq_add(t, am, ar); fmpq_add(u, bm, br); c2 = c2 && (fmpq_cmp(t, u) > 0); if (c1 != c2) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("am = "); fmpq_print(am); flint_printf("\n\n"); flint_printf("ar = "); fmpq_print(ar); flint_printf("\n\n"); flint_printf("bm = "); fmpq_print(bm); flint_printf("\n\n"); flint_printf("br = "); fmpq_print(br); flint_printf("\n\n"); flint_printf("t = "); fmpq_print(t); flint_printf("\n\n"); flint_printf("u = "); fmpq_print(u); flint_printf("\n\n"); flint_printf("c1 = %d, c2 = %d\n\n", c1, c2); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(am); fmpq_clear(ar); fmpq_clear(bm); fmpq_clear(br); fmpq_clear(t); fmpq_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-cos.c000066400000000000000000000067621461254215100163510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_cos, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec0, prec; prec0 = 400; if (iter % 100 == 0) prec0 = 8000; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec0 + 100); arb_randtest(a, state, 1 + n_randint(state, prec0), 6); arb_randtest(b, state, 1 + n_randint(state, prec0), 6); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, prec0)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_cos(t, t, MPFR_RNDN); arb_cos(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_cos(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* check large arguments */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec0, prec1, prec2; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, prec0), prec0); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(d, state, 1 + n_randint(state, prec0), 100); arb_cos(b, a, prec1); arb_cos(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check cos(2a) = 2cos(a)^2-1 */ arb_mul_2exp_si(c, a, 1); arb_cos(c, c, prec1); arb_mul(b, b, b, prec1); arb_mul_2exp_si(b, b, 1); arb_sub_ui(b, b, 1, prec1); if (!arb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-cos_pi.c000066400000000000000000000026701461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_cos_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_const_pi(b, prec); arb_mul(b, b, a, prec); arb_cos(b, b, prec); arb_cos_pi(c, a, prec); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-cos_pi_fmpq.c000066400000000000000000000027221461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_cos_pi_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t c1, c2; fmpq_t x; slong prec; prec = 2 + n_randint(state, 5000); arb_init(c1); arb_init(c2); fmpq_init(x); fmpq_randtest(x, state, 1 + n_randint(state, 200)); arb_cos_pi_fmpq(c1, x, prec); arb_const_pi(c2, prec); arb_mul_fmpz(c2, c2, fmpq_numref(x), prec); arb_div_fmpz(c2, c2, fmpq_denref(x), prec); arb_cos(c2, c2, prec); if (!arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("c1 = "); arb_printd(c1, 15); flint_printf("\n\n"); flint_printf("c2 = "); arb_printd(c2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(c1); arb_clear(c2); fmpq_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-cos_pi_fmpq_algebraic.c000066400000000000000000000036751461254215100220550ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_cos_pi_fmpq_algebraic, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t c1, c2; ulong p, q, g; slong prec; prec = 2 + n_randint(state, 5000); q = 1 + n_randint(state, 500); p = n_randint(state, q / 2 + 1); g = n_gcd(q, p); q /= g; p /= g; arb_init(c1); arb_init(c2); _arb_cos_pi_fmpq_algebraic(c1, p, q, prec); arb_const_pi(c2, prec); arb_mul_ui(c2, c2, p, prec); arb_div_ui(c2, c2, q, prec); arb_cos(c2, c2, prec); if (!arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("c1 = "); arb_printd(c1, 15); flint_printf("\n\n"); flint_printf("c2 = "); arb_printd(c2, 15); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(c1) < prec - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("prec=%wd eff=%wd\n", prec, arb_rel_accuracy_bits(c1)); flint_printf("c1 = "); arb_printd(c1, 15); flint_printf("\n\n"); flint_printf("c2 = "); arb_printd(c2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(c1); arb_clear(c2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-cosh.c000066400000000000000000000032031461254215100165040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_cosh, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_cosh(t, t, MPFR_RNDN); arb_cosh(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_cosh(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-cot_pi.c000066400000000000000000000066061461254215100170370ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_cot_pi, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(x); arb_init(y); arb_init(a); arb_init(b); arb_init(c); arb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_cot_pi(a, x, prec1); arb_cot_pi(b, x, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } /* compare with cot */ arb_const_pi(c, prec1); arb_mul(y, x, c, prec1); arb_cot(c, y, prec1); if (!arb_overlaps(a, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_cot_pi(x, x, prec1); if (!arb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(a); arb_clear(b); arb_clear(c); } /* Check a few special points. */ { arb_t x, y; slong i, prec; arb_init(x); arb_init(y); prec = 32; for (i = -1; i <= 1; i++) { int arbitrary_integer = 7; /* integer */ arb_set_d(x, arbitrary_integer*i); arb_cot_pi(y, x, prec); if (arb_is_finite(y)) { flint_printf("FAIL: (integer)\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } /* integer + 1/2 */ arb_set_d(x, arbitrary_integer*i + 0.5); arb_cot_pi(y, x, prec); if (!arb_is_zero(y)) { flint_printf("FAIL: (integer + 1/2)\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-coth.c000066400000000000000000000050531461254215100165120ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_coth, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(x); arb_init(y); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(x, state, 1 + n_randint(state, 1000), 100); arb_randtest_precise(y, state, 1 + n_randint(state, 1000), 100); arb_coth(a, x, prec1); arb_coth(b, x, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } /* check coth(x+y) = (1 + coth(x) coth(y)) / (coth(x) + coth(y)) */ arb_add(b, x, y, prec1); arb_coth(b, b, prec1); arb_coth(c, y, prec1); arb_add(d, a, c, prec1); arb_mul(c, a, c, prec1); arb_add_ui(c, c, 1, prec1); arb_div(d, c, d, prec1); if (!arb_overlaps(b, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_coth(x, x, prec1); if (!arb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-csc.c000066400000000000000000000032531461254215100163250ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_csc, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 300), 100); arb_randtest_special(a, state, 1 + n_randint(state, 300), 100); arb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { arb_csc(a, x, prec1); } else { arb_set(a, x); arb_csc(a, a, prec1); } arb_sin(b, x, prec2); arb_inv(b, b, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-csc_pi.c000066400000000000000000000033361461254215100170170ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_csc_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 300), 100); arb_randtest_special(a, state, 1 + n_randint(state, 300), 100); arb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { arb_csc_pi(a, x, prec1); } else { arb_set(a, x); arb_csc_pi(a, a, prec1); } arb_sin_pi(b, x, prec2); arb_inv(b, b, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-csch.c000066400000000000000000000032571461254215100165010ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_csch, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 300), 100); arb_randtest_special(a, state, 1 + n_randint(state, 300), 100); arb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { arb_csch(a, x, prec1); } else { arb_set(a, x); arb_csch(a, a, prec1); } arb_sinh(b, x, prec2); arb_inv(b, b, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-digamma.c000066400000000000000000000043441461254215100171560ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_digamma, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 10); arb_digamma(b, a, prec1); arb_digamma(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_set(c, a); arb_digamma(c, c, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check digamma(z+1) = digamma(z) + 1/z */ arb_inv(c, a, prec1); arb_add(b, b, c, prec1); arb_add_ui(c, a, 1, prec1); arb_digamma(c, c, prec1); if (!arb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-digits_round_inplace.c000066400000000000000000000045311461254215100217420ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_digits_round_inplace, state) { { char s[30]; slong i, j, len, n; flint_bitcnt_t shift; fmpz_t inp, out, err, t; arf_rnd_t rnd; fmpz_init(inp); fmpz_init(out); fmpz_init(err); fmpz_init(t); for (i = 0; i < 100000 * 0.1 * flint_test_multiplier(); i++) { len = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); s[0] = (n_randint(state, 9) + '1'); for (j = 1; j < len; j++) s[j] = (n_randint(state, 10) + '0'); s[len] = '\0'; fmpz_set_str(inp, s, 10); switch (n_randint(state, 3)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; default: rnd = ARF_RND_NEAR; break; } _arb_digits_round_inplace(s, &shift, err, n, rnd); fmpz_set_str(out, s, 10); fmpz_set_ui(t, 10); fmpz_pow_ui(t, t, shift); fmpz_mul(t, t, out); fmpz_add(t, t, err); if (!fmpz_equal(t, inp) || (rnd == ARF_RND_UP && fmpz_sgn(err) > 0)) { flint_printf("FAIL!\n"); flint_printf("inp = "); fmpz_print(inp); flint_printf("\n\n"); flint_printf("shift = %wd\n\n", shift); flint_printf("err = "); fmpz_print(err); flint_printf("\n\n"); flint_printf("out = "); fmpz_print(out); flint_printf("\n\n"); flint_printf(" t = "); fmpz_print(t); flint_printf("\n\n"); flint_abort(); } } fmpz_clear(inp); fmpz_clear(out); fmpz_clear(err); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-div.c000066400000000000000000000175301461254215100163420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_div, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t x, y, z; arb_init(a); arb_init(b); arb_init(c); fmpq_init(x); fmpq_init(y); fmpq_init(z); do { arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); } while (fmpq_is_zero(y)); arb_div(c, a, b, 2 + n_randint(state, 200)); fmpq_div(z, x, y); if (!arb_contains_fmpq(c, z)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); do { arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); } while (fmpq_is_zero(y)); arb_div(a, a, b, 2 + n_randint(state, 200)); fmpq_div(z, x, y); if (!arb_contains_fmpq(a, z)) { flint_printf("FAIL: aliasing (c, a)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and b */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); do { arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); } while (fmpq_is_zero(y)); arb_div(b, a, b, 2 + n_randint(state, 200)); fmpq_div(z, x, y); if (!arb_contains_fmpq(b, z)) { flint_printf("FAIL: aliasing (c, b)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* test special values */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(c, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_div(c, a, b, 2 + n_randint(state, 200)); arb_mul(d, c, b, 2 + n_randint(state, 200)); if (!arb_contains(d, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 15); flint_printf("\n\n"); flint_abort(); } if (arf_is_nan(arb_midref(a)) || arf_is_nan(arb_midref(b)) || arb_contains_zero(b) || (!arb_is_finite(a) && !arb_is_finite(b))) { if (!arf_is_nan(arb_midref(c)) || !mag_is_inf(arb_radref(c))) { flint_printf("FAIL: special value 1\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_abort(); } } if (!arb_is_finite(a) && !arb_contains_zero(a) && !arb_contains_zero(b) && arb_is_finite(b)) { if (!arf_is_inf(arb_midref(c)) || !mag_is_zero(arb_radref(c)) || arf_sgn(arb_midref(a)) * arf_sgn(arb_midref(b)) != arf_sgn(arb_midref(c))) { flint_printf("FAIL: special value 2\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_abort(); } } if (!arb_is_finite(a) && !arf_is_nan(arb_midref(a)) && arb_contains_zero(a) && !arb_contains_zero(b) && arb_is_finite(b)) { if (!arf_is_zero(arb_midref(c)) || !mag_is_inf(arb_radref(c))) { flint_printf("FAIL: special value 3\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_abort(); } } if (arb_is_finite(a) && !arb_is_finite(b) && !arb_contains_zero(b)) { if (!arb_is_zero(c)) { flint_printf("FAIL: special value 4\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-div_2expm1_ui.c000066400000000000000000000051161461254215100202300ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_div_2expm1_ui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong n; slong prec, acc1, acc2; fmpz_t t; arb_init(a); arb_init(b); arb_init(c); fmpz_init(t); prec = 2 + n_randint(state, 10000); arb_randtest(a, state, 1 + n_randint(state, 10000), 10); if (n_randint(state, 2)) n = 1 + (n_randtest(state) % (10 * prec)); else n = n_randtest(state); arb_div_2expm1_ui(b, a, n, prec); arb_one(c); if (n >= (UWORD(1) << (FLINT_BITS-1))) { arb_mul_2exp_si(c, c, (UWORD(1) << (FLINT_BITS-2))); arb_mul_2exp_si(c, c, (UWORD(1) << (FLINT_BITS-2))); arb_mul_2exp_si(c, c, n - (UWORD(1) << (FLINT_BITS-1))); } else { arb_mul_2exp_si(c, c, n); } arb_sub_ui(c, c, 1, prec); arb_div(c, a, c, prec); acc1 = arb_rel_accuracy_bits(a); acc2 = arb_rel_accuracy_bits(b); if (!arb_overlaps(b, c)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } if (n > 0 && acc1 > 1 && (acc2 < FLINT_MIN(prec, acc1) - 10) && !(acc1 == -ARF_PREC_EXACT && acc2 == -ARF_PREC_EXACT)) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec=%wd, acc1=%wd, acc2=%wd\n\n", prec, acc1, acc2); flint_printf("n = %wu\n\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-div_arf.c000066400000000000000000000054171461254215100171730ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_div_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_div_arf(c, a, x, prec); arb_div(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arf_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_div_arf(c, a, x, prec); arb_div_arf(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-div_fmpz.c000066400000000000000000000054031461254215100173720ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_div_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_div_fmpz(c, a, x, prec); arb_div(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_div_fmpz(c, a, x, prec); arb_div_fmpz(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-div_newton.c000066400000000000000000000073631461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_div_newton, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); prec = 2 + n_randint(state, 200000); arb_randtest(a, state, 1 + n_randint(state, 200000), 10); arb_randtest(b, state, 1 + n_randint(state, 200000), 10); arb_randtest(c, state, 1 + n_randint(state, 200000), 10); if (n_randint(state, 2)) { arb_set(c, a); arb_div_newton(c, c, b, prec); } else if (n_randint(state, 2)) { arb_set(c, b); arb_div_newton(c, a, c, prec); } else { arb_div_newton(c, a, b, prec); } arb_div(d, a, b, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 100); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 100); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 100); flint_printf("\n\n"); flint_abort(); } arb_randtest(c, state, 1 + n_randint(state, 100000), 10); mag_zero(arb_radref(b)); if (n_randint(state, 2)) { arb_set(c, a); arb_div_arf_newton(c, c, arb_midref(b), prec); } else if (n_randint(state, 2)) { arb_set(c, b); arb_div_arf_newton(c, a, arb_midref(c), prec); } else { arb_div_arf_newton(c, a, arb_midref(b), prec); } arb_div_arf(d, a, arb_midref(b), prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 100); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 100); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 100); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, b, c, d, e; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(e); fmpz_randtest(a, state, 400000); fmpz_randtest_not_zero(b, state, 200000); arb_fmpz_divapprox(c, a, b); fmpz_fdiv_q(d, a, b); fmpz_cdiv_q(e, a, b); if (!(fmpz_equal(c, d) || fmpz_equal(c, e))) { flint_printf("FAIL: fmpz_divapprox\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-div_si.c000066400000000000000000000051701461254215100170320ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "long_extras.h" TEST_FUNCTION_START(arb_div_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_div_si(c, a, x, prec); arb_div(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_div_si(c, a, x, prec); arb_div_si(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-div_ui.c000066400000000000000000000051711461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "ulong_extras.h" TEST_FUNCTION_START(arb_div_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_div_ui(c, a, x, prec); arb_div(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_div_ui(c, a, x, prec); arb_div_ui(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dot.c000066400000000000000000000143141461254215100163430ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_dot, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr x, y; arb_t s1, s2, z; slong i, len, prec, xbits, ybits, ebits; int ok, initial, subtract, revx, revy; if (n_randint(state, 100) == 0) len = n_randint(state, 100); else if (n_randint(state, 10) == 0) len = n_randint(state, 10); else len = n_randint(state, 3); if (n_randint(state, 10) != 0 || len > 10) { prec = 2 + n_randint(state, 500); xbits = 2 + n_randint(state, 500); ybits = 2 + n_randint(state, 500); } else { prec = 2 + n_randint(state, 4000); xbits = 2 + n_randint(state, 4000); ybits = 2 + n_randint(state, 4000); } if (n_randint(state, 100) == 0) ebits = 2 + n_randint(state, 100); else ebits = 2 + n_randint(state, 10); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arb_vec_init(len); y = _arb_vec_init(len); arb_init(s1); arb_init(s2); arb_init(z); switch (n_randint(state, 3)) { case 0: for (i = 0; i < len; i++) { arb_randtest(x + i, state, xbits, ebits); arb_randtest(y + i, state, ybits, ebits); } break; /* Test with cancellation */ case 1: for (i = 0; i < len; i++) { if (i <= len / 2) { arb_randtest(x + i, state, xbits, ebits); arb_randtest(y + i, state, ybits, ebits); } else { arb_neg(x + i, x + len - i - 1); arb_set(y + i, y + len - i - 1); } } break; default: for (i = 0; i < len; i++) { if (i <= len / 2) { arb_randtest(x + i, state, xbits, ebits); arb_randtest(y + i, state, ybits, ebits); } else { arb_neg_round(x + i, x + len - i - 1, 2 + n_randint(state, 500)); arb_set_round(y + i, y + len - i - 1, 2 + n_randint(state, 500)); } } break; } arb_randtest(s1, state, 200, 100); arb_randtest(s2, state, 200, 100); arb_randtest(z, state, xbits, ebits); arb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); arb_dot_precise(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, ebits <= 12 ? ARF_PREC_EXACT : 2 * prec + 100); if (ebits <= 12) ok = arb_contains(s1, s2); else ok = arb_overlaps(s1, s2); if (!ok) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } /* With the fast algorithm, we expect identical results when reversing the vectors. */ if (ebits <= 12) { revx ^= 1; revy ^= 1; arb_dot(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); if (!arb_equal(s1, s2)) { flint_printf("FAIL (reversal)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } } arb_clear(s1); arb_clear(s2); arb_clear(z); _arb_vec_clear(x, len); _arb_vec_clear(y, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dot_fmpz.c000066400000000000000000000056241461254215100174030ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "arb.h" TEST_FUNCTION_START(arb_dot_fmpz, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr x, y; fmpz * w; arb_t s1, s2, z; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arb_vec_init(len); y = _arb_vec_init(len); w = _fmpz_vec_init(len); arb_init(s1); arb_init(s2); arb_init(z); for (i = 0; i < len; i++) { arb_randtest(x + i, state, 2 + n_randint(state, 200), 10); fmpz_randtest(w + i, state, 1 + n_randint(state, 200)); arb_set_fmpz(y + i, w + i); } arb_randtest(s1, state, 200, 10); arb_randtest(s2, state, 200, 10); arb_randtest(z, state, 200, 10); arb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); arb_dot_fmpz(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + len - 1) : w, revy ? -1 : 1, len, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(z); _arb_vec_clear(x, len); _arb_vec_clear(y, len); _fmpz_vec_clear(w, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dot_si.c000066400000000000000000000055331461254215100170410ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_dot_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr x, y; slong * w; arb_t s1, s2, z; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arb_vec_init(len); y = _arb_vec_init(len); w = flint_malloc(sizeof(ulong) * len); arb_init(s1); arb_init(s2); arb_init(z); for (i = 0; i < len; i++) { arb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[i] = n_randtest(state); arb_set_si(y + i, w[i]); } arb_randtest(s1, state, 200, 10); arb_randtest(s2, state, 200, 10); arb_randtest(z, state, 200, 10); arb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); arb_dot_si(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + len - 1) : w, revy ? -1 : 1, len, prec); if (!arb_equal(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(z); _arb_vec_clear(x, len); _arb_vec_clear(y, len); flint_free(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dot_siui.c000066400000000000000000000060271461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_dot_siui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr x, y; ulong * w; arb_t s1, s2, z; fmpz_t c; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arb_vec_init(len); y = _arb_vec_init(len); w = flint_malloc(2 * sizeof(ulong) * len); arb_init(s1); arb_init(s2); arb_init(z); fmpz_init(c); for (i = 0; i < len; i++) { arb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[2 * i] = n_randtest(state); w[2 * i + 1] = n_randtest(state); fmpz_set_signed_uiui(c, w[2 * i + 1], w[2 * i]); arb_set_fmpz(y + i, c); } arb_randtest(s1, state, 200, 10); arb_randtest(s2, state, 200, 10); arb_randtest(z, state, 200, 10); arb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); arb_dot_siui(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + 2 * len - 2) : w, revy ? -1 : 1, len, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(z); _arb_vec_clear(x, len); _arb_vec_clear(y, len); flint_free(w); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dot_ui.c000066400000000000000000000055331461254215100170430ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_dot_ui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr x, y; ulong * w; arb_t s1, s2, z; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arb_vec_init(len); y = _arb_vec_init(len); w = flint_malloc(sizeof(ulong) * len); arb_init(s1); arb_init(s2); arb_init(z); for (i = 0; i < len; i++) { arb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[i] = n_randtest(state); arb_set_ui(y + i, w[i]); } arb_randtest(s1, state, 200, 10); arb_randtest(s2, state, 200, 10); arb_randtest(z, state, 200, 10); arb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); arb_dot_ui(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + len - 1) : w, revy ? -1 : 1, len, prec); if (!arb_equal(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(z); _arb_vec_clear(x, len); _arb_vec_clear(y, len); flint_free(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dot_uiui.c000066400000000000000000000060201461254215100173710ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_dot_uiui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr x, y; ulong * w; arb_t s1, s2, z; fmpz_t c; slong i, len, prec; int initial, subtract, revx, revy; len = n_randint(state, 5); prec = 2 + n_randint(state, 200); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arb_vec_init(len); y = _arb_vec_init(len); w = flint_malloc(2 * sizeof(ulong) * len); arb_init(s1); arb_init(s2); arb_init(z); fmpz_init(c); for (i = 0; i < len; i++) { arb_randtest(x + i, state, 2 + n_randint(state, 200), 10); w[2 * i] = n_randtest(state); w[2 * i + 1] = n_randtest(state); fmpz_set_uiui(c, w[2 * i + 1], w[2 * i]); arb_set_fmpz(y + i, c); } arb_randtest(s1, state, 200, 10); arb_randtest(s2, state, 200, 10); arb_randtest(z, state, 200, 10); arb_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec); arb_dot_uiui(s2, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (w + 2 * len - 2) : w, revy ? -1 : 1, len, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd\n\n", iter, len, prec); if (initial) { flint_printf("z = ", i); arb_printn(z, 100, ARB_STR_MORE); flint_printf(" (%wd)\n\n", arb_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arb_printn(x + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(x + i)); flint_printf("y[%wd] = ", i); arb_printn(y + i, 100, ARB_STR_MORE); flint_printf(" (%wd)\n", arb_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, ARB_STR_MORE); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(z); _arb_vec_clear(x, len); _arb_vec_clear(y, len); flint_free(w); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-doublefac_ui.c000066400000000000000000000026451461254215100202020ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_doublefac_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong n; slong prec1, prec2; prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); arb_init(a); arb_init(b); arb_init(c); n = n_randtest(state); if (n + 1 == 0 || n + 2 == 0) n -= 2; arb_doublefac_ui(a, n, prec1); arb_doublefac_ui(b, n + 2, prec1); arb_mul_ui(c, a, n + 2, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dump_file.c000066400000000000000000000052271461254215100175240ustar00rootroot00000000000000/* Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_dump_file, state) { slong iter; /* assume tmpfile() is broken on windows */ #if !defined(_MSC_VER) && !defined(__MINGW32__) /* just test no crashing... */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; FILE* tmp; arb_init(x); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); tmp = tmpfile(); if (tmp == NULL) { flint_printf("FAIL (creating temporary file) iter = %wd\n\n", iter); flint_abort(); } arb_dump_file(tmp, x); fflush(tmp); rewind(tmp); arb_load_file(x, tmp); fclose(tmp); arb_clear(x); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; int conversion_error; FILE* tmp; arb_init(x); arb_init(y); arb_init(z); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); tmp = tmpfile(); arb_dump_file(tmp, x); fputc(' ', tmp); arb_dump_file(tmp, y); fflush(tmp); rewind(tmp); conversion_error = arb_load_file(z, tmp); if (conversion_error || !arb_equal(x, z)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 50); flint_printf("\n\n"); flint_abort(); } conversion_error = arb_load_file(z, tmp); if (conversion_error || !arb_equal(y, z)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 50); flint_printf("\n\n"); flint_abort(); } fclose(tmp); arb_clear(x); arb_clear(y); arb_clear(z); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-dump_str.c000066400000000000000000000034011461254215100174050ustar00rootroot00000000000000/* Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_dump_str, state) { slong iter; /* just test no crashing... */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; char * s; arb_init(x); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); s = arb_dump_str(x); flint_free(s); arb_clear(x); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y; char * s; int conversion_error; arb_init(x); arb_init(y); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); s = arb_dump_str(x); conversion_error = arb_load_str(y, s); if (conversion_error || !arb_equal(x, y)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("s = %s", s); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } flint_free(s); arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-euler_number_fmpz.c000066400000000000000000000060671461254215100213030ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arith.h" #include "arb.h" TEST_FUNCTION_START(arb_euler_number_fmpz, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t b1, b2; fmpz_t n, bv; slong prec1, prec2, acc1, acc2; fmpz_init(n); fmpz_init(bv); arb_init(b1); arb_init(b2); if (iter % 100 == 0) { fmpz_randtest(n, state, 1 + n_randint(state, 1000)); fmpz_abs(n, n); } else { fmpz_randtest(n, state, 1 + n_randint(state, 20)); fmpz_abs(n, n); } prec1 = 2 + n_randint(state, 1000); if (iter % 100 == 0) { fmpz_one(n); fmpz_mul_2exp(n, n, 64); arb_euler_number_fmpz(b1, n, prec1); arb_set_str(b2, "3.69772629631570244101368532955e+343764398125858671130", 64); prec2 = 64; } else if (iter % 100 == 1) { fmpz_one(n); fmpz_mul_2exp(n, n, 64); fmpz_add_ui(n, n, 2); arb_euler_number_fmpz(b1, n, prec1); arb_set_str(b2, "-5.09958051083474382772175848886e+343764398125858671168", 64); prec2 = 64; } else { prec2 = 2 + n_randint(state, 1000); arb_euler_number_fmpz(b1, n, prec1); arb_euler_number_fmpz(b2, n, prec2); } if (fmpz_cmp_ui(n, 300) < 0) { arith_euler_number(bv, fmpz_get_ui(n)); } if (!arb_overlaps(b1, b2) || (fmpz_cmp_ui(n, 100) < 0 && !arb_contains_fmpz(b1, bv))) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("b1 = "); arb_printn(b1, 50, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, 50, 0); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(b1); acc2 = arb_rel_accuracy_bits(b2); if (acc1 < prec1 - 4 || acc2 < prec2 - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd\n", prec1, acc1); flint_printf("prec2 = %wd, acc2 = %wd\n", prec2, acc2); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("b1 = "); arb_printn(b1, 50, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(b1); arb_clear(b2); fmpz_clear(n); fmpz_clear(bv); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-euler_number_ui.c000066400000000000000000000074621461254215100207440ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "arith.h" #include "arb.h" ulong euler_mod_p_powsum_noredc(ulong n, ulong p, const unsigned int * divtab); ulong euler_mod_p_powsum(ulong n, ulong p, const unsigned int * divtab); ulong euler_mod_p_powsum_1(ulong n, ulong p); static void divisor_table_odd(unsigned int * tab, slong len) { slong i, j; tab[0] = 0; for (i = 1; i < len; i += 2) { tab[i] = 1; tab[i + 1] = i; } for (i = 3; i < len; i += 2) { for (j = 3; j <= i && i * j < len; j += 2) { tab[i * j] = j; tab[i * j + 1] = i; } } } TEST_FUNCTION_START(arb_euler_number_ui, state) { slong iter; { slong nmax; unsigned int * divtab_odd; fmpz * En; nmax = 1000 * FLINT_MIN(1.0, 0.1 * flint_test_multiplier()); En = _fmpz_vec_init(nmax); arith_euler_number_vec(En, nmax); { fmpz_t E; slong n; double alpha; fmpz_init(E); for (n = 0; n < nmax; n++) { if (n_randint(state, 2)) alpha = -1.0; else alpha = n_randint(state, 11) / (double) 10; arb_fmpz_euler_number_ui_multi_mod(E, n, alpha); if (!fmpz_equal(En + n, E)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("vec: "); fmpz_print(En + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(E); flint_printf("\n"); flint_abort(); } arb_fmpz_euler_number_ui(E, n); if (!fmpz_equal(En + n, E)) { flint_printf("FAIL (2): n = %wd\n", n); flint_printf("vec: "); fmpz_print(En + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(E); flint_printf("\n"); flint_abort(); } } fmpz_clear(E); } /* test the mod p code */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { ulong p, n, m, m1, m5; n = n_randint(state, nmax); p = 4 + n_randint(state, 10000); p = n_nextprime(p, 1); divtab_odd = flint_malloc(sizeof(unsigned int) * (p / 4 + 2)); divisor_table_odd(divtab_odd, p / 4 + 1); m = fmpz_fdiv_ui(En + n, p); if (n_randint(state, 2)) m5 = euler_mod_p_powsum(n, p, divtab_odd); else m5 = euler_mod_p_powsum_noredc(n, p, divtab_odd); if (n_randint(state, 30) == 0) { m1 = euler_mod_p_powsum_1(n, p); if (m1 != UWORD_MAX && m != m1) { flint_printf("FAIL\n\n"); flint_printf("n = %wu, p = %wu, m = %wu, m1 = %wu\n\n", n, p, m, m1); flint_abort(); } } if (m5 != UWORD_MAX && m != m5) { flint_printf("FAIL\n\n"); flint_printf("n = %wu, p = %wu, m = %wu, m5 = %wu\n\n", n, p, m, m5); flint_abort(); } flint_free(divtab_odd); } _fmpz_vec_clear(En, nmax); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-exp.c000066400000000000000000000151711461254215100163530ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" /* check accuracy compared to reference algorithm */ void arb_exp_simple(arb_t res, const arb_t x, slong prec) { mag_t t, u; mag_init_set(t, arb_radref(x)); mag_init(u); arf_set(arb_midref(res), arb_midref(x)); mag_zero(arb_radref(res)); arb_exp(res, x, prec); mag_expm1(t, t); arb_get_mag(u, res); mag_addmul(arb_radref(res), t, u); mag_clear(t); mag_clear(u); } TEST_FUNCTION_START(arb_exp, state) { slong iter; /* check large arguments + compare with exp_simple */ for (iter = 0; iter < 100000 *0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec0, prec1, prec2, acc1, acc2; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_exp(b, a, prec1); arb_exp(c, a, prec2); arb_exp_simple(d, a, prec1); if (!arb_overlaps(b, c) || !arb_overlaps(b, d) || !arb_overlaps(c, d)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } /* compare accuracy with exp_simple */ acc1 = arb_rel_accuracy_bits(b); acc2 = arb_rel_accuracy_bits(d); if (acc2 > 0 && acc1 < acc2 - 1) { flint_printf("FAIL: accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd, acc2 = %wd\n\n", prec1, acc1, acc2); flint_printf("a = "); arb_printd(a, 50); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 50); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 50); flint_printf("\n\n"); flint_abort(); } arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); /* check exp(a)*exp(b) = exp(a+b) */ arb_exp(c, a, prec1); arb_exp(d, b, prec1); arb_mul(c, c, d, prec1); arb_add(d, a, b, prec1); arb_exp(d, d, prec1); if (!arb_overlaps(c, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* test union */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d, e; slong prec0, prec1, prec2, prec3, prec4; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); prec3 = 2 + n_randint(state, prec0); prec4 = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_init(e); arb_randtest_special(a, state, 1 + n_randint(state, prec0), 200); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 200); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 200); arb_randtest_special(d, state, 1 + n_randint(state, prec0), 200); arb_randtest_special(e, state, 1 + n_randint(state, prec0), 200); arb_exp(c, a, prec1); arb_exp(d, b, prec2); arb_union(e, a, b, prec3); arb_exp(e, e, prec4); if (!arb_overlaps(e, c) || !arb_overlaps(e, d)) { flint_printf("FAIL: union\n\n"); flint_printf("a = "); arb_printn(a, 1000, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 1000, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 1000, 0); flint_printf("\n\n"); flint_printf("d = "); arb_printn(d, 1000, 0); flint_printf("\n\n"); flint_printf("e = "); arb_printn(e, 1000, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arb_clear(e); } /* comparison with mpfr */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec0, prec; prec0 = 400; if (iter % 100 == 0) prec0 = 10000; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, prec0), 4); arb_randtest(b, state, 1 + n_randint(state, prec0), 4); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, prec0)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_exp(t, t, MPFR_RNDN); arb_exp(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("iter = %wd, prec = %wd\n\n", iter, prec); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_exp(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("iter = %wd, prec = %wd\n\n", iter, prec); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-exp_arf_bb.c000066400000000000000000000057721461254215100176540ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" void arb_exp_arf_via_mpfr(arb_t z, const arf_t x, slong prec) { mpfr_t t, u; int exact; mpfr_init2(t, 2 + arf_bits(x)); mpfr_init2(u, prec); mpfr_set_emin(MPFR_EMIN_MIN); mpfr_set_emax(MPFR_EMAX_MAX); arf_get_mpfr(t, x, MPFR_RNDD); exact = (mpfr_exp(u, t, MPFR_RNDD) == 0); arf_set_mpfr(arb_midref(z), u); if (!exact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); mpfr_clear(t); mpfr_clear(u); } TEST_FUNCTION_START(arb_exp_arf_bb, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; slong prec = 2 + n_randint(state, 8000); arb_init(x); arb_init(y); arb_init(z); if (n_randint(state, 100) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); arb_randtest(x, state, 1 + n_randint(state, 8000), 3); mag_zero(arb_radref(x)); if (n_randint(state, 2)) { if ((FLINT_BITS == 64) && (sizeof(mpfr_exp_t) >= sizeof(slong))) arb_mul_2exp_si(x, x, 1 + n_randint(state, 40)); else arb_mul_2exp_si(x, x, 1 + n_randint(state, 20)); } else { arb_mul_2exp_si(x, x, -n_randint(state, 1.5 * prec)); } arb_exp_arf_via_mpfr(y, arb_midref(x), prec + 100); arb_exp_arf_bb(z, arb_midref(x), prec, 0); if (!arb_contains(z, y)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 50); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(z) < prec - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd, acc = %wd\n\n", prec, arb_rel_accuracy_bits(z)); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } arb_exp_arf_bb(x, arb_midref(x), prec, 0); if (!arb_overlaps(x, z)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-exp_arf_rs_generic.c000066400000000000000000000073661461254215100214120ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" /* these functions are not exposed to the public for now, but it still makes sense to test them explicitly */ void arb_exp_taylor_sum_rs_generic(arb_t s, const arb_t x, slong N, slong prec); TEST_FUNCTION_START(arb_exp_arf_rs_generic, state) { slong iter; /* test the rs algorithm explicitly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, s1, s2; slong prec; int minus1; arb_init(x); arb_init(s1); arb_init(s2); prec = 2 + n_randint(state, 2000); minus1 = n_randint(state, 2); arb_randtest(x, state, 1 + n_randint(state, 2000), 3); mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_mul_2exp_si(x, x, -n_randint(state, 2 * prec)); if (minus1) arb_expm1(s1, x, prec); else arb_exp(s1, x, prec); switch (n_randint(state, 2)) { case 0: arb_exp_arf_rs_generic(s2, arb_midref(x), prec, minus1); break; case 1: arb_set(s2, x); arb_exp_arf_rs_generic(s2, arb_midref(s2), prec, minus1); break; } if (!arb_overlaps(s1, s2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd, minus1 = %d\n\n", prec, minus1); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(s2) < prec - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd, acc1 = %wd, minus1 = %d\n\n", prec, arb_rel_accuracy_bits(s2), minus1); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(s1); arb_clear(s2); } /* test the series evaluation code directly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; slong prec; slong N; arb_init(x); arb_init(y); arb_init(z); prec = 2 + n_randint(state, 2000); N = n_randint(state, 100); arb_randtest(x, state, 1 + n_randint(state, 2000), 1); mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_mul_2exp_si(x, x, -n_randint(state, 2 * prec)); arb_exp(y, x, prec); arb_exp_taylor_sum_rs_generic(z, x, N, prec); if (!arb_overlaps(z, y)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd, N = %wd\n\n", prec, N); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 500, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 500, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-exp_invexp.c000066400000000000000000000056251461254215100177470ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_exp_invexp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec, acc1, acc2; if (iter % 10 == 0) prec = 10000; else prec = 1000; prec = 2 + n_randint(state, prec); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, prec), 1 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, prec), 1 + n_randint(state, 100)); arb_randtest_special(c, state, 1 + n_randint(state, prec), 1 + n_randint(state, 100)); if (n_randint(state, 2)) { arb_exp_invexp(b, c, a, prec); } else if (n_randint(state, 2)) { arb_set(b, a); arb_exp_invexp(b, c, b, prec); } else { arb_set(c, a); arb_exp_invexp(b, c, c, prec); } arb_exp(d, a, prec); acc1 = arb_rel_accuracy_bits(b); acc2 = arb_rel_accuracy_bits(d); if (!arb_overlaps(b, d) || ((acc1 > 0 || acc2 > 0) && acc1 < FLINT_MIN(acc2, prec) - 3)) { flint_printf("FAIL: overlap 1\n\n"); flint_printf("prec = %wd, acc1 = %wd, acc2 = %wd\n\n", prec, acc1, acc2); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_neg(d, a); arb_exp(d, d, prec); acc1 = arb_rel_accuracy_bits(c); acc2 = arb_rel_accuracy_bits(d); if (!arb_overlaps(c, d) || ((acc1 > 0 || acc2 > 0) && acc1 < FLINT_MIN(acc2, prec) - 3)) { flint_printf("FAIL: overlap 2\n\n"); flint_printf("prec = %wd, acc1 = %wd, acc2 = %wd\n\n", prec, acc1, acc2); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-exp_sum_bs_powtab.c000066400000000000000000000037561461254215100213050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_exp_sum_bs_powtab, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong N; fmpz_t x, T, Q; fmpq_t S, V; flint_bitcnt_t Qexp, r; fmpz_init(x); fmpz_init(T); fmpz_init(Q); fmpq_init(S); fmpq_init(V); if (n_randint(state, 100) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); N = 1 + n_randint(state, 300); r = n_randint(state, 10); fmpz_randtest(x, state, 80); _arb_exp_sum_bs_simple(T, Q, &Qexp, x, r, N); fmpq_set_fmpz_frac(S, T, Q); fmpq_div_2exp(S, S, Qexp); _arb_exp_sum_bs_powtab(T, Q, &Qexp, x, r, N); fmpq_set_fmpz_frac(V, T, Q); fmpq_div_2exp(V, V, Qexp); if (!fmpq_equal(S, V)) { flint_printf("FAIL\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("r = %wu\n\n", r); flint_printf("x = "); fmpz_print(x); flint_printf("\n\n"); flint_printf("T = "); fmpz_print(T); flint_printf("\n\n"); flint_printf("Q = "); fmpz_print(T); flint_printf("\n\n"); flint_printf("V = "); fmpq_print(V); flint_printf("\n\n"); flint_printf("S = "); fmpq_print(S); flint_printf("\n\n"); flint_abort(); } fmpz_clear(x); fmpz_clear(T); fmpz_clear(Q); fmpq_clear(S); fmpq_clear(V); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-exp_tab.c000066400000000000000000000117541461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_exp_tab, state) { slong i; mpfr_t tabx, expx, y1, y2; mpz_t tt; { slong prec, bits, num; prec = ARB_EXP_TAB1_LIMBS * FLINT_BITS; bits = ARB_EXP_TAB1_BITS; num = ARB_EXP_TAB1_NUM; mpfr_init2(tabx, prec); mpfr_init2(expx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_exp_tab1[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(expx, i, MPFR_RNDD); mpfr_div_2ui(expx, expx, bits, MPFR_RNDD); mpfr_exp(expx, expx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, expx, prec - 1, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(expx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_EXP_TAB2_LIMBS * FLINT_BITS; bits = ARB_EXP_TAB21_BITS; num = ARB_EXP_TAB21_NUM; mpfr_init2(tabx, prec); mpfr_init2(expx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_exp_tab21[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(expx, i, MPFR_RNDD); mpfr_div_2ui(expx, expx, bits, MPFR_RNDD); mpfr_exp(expx, expx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, expx, prec - 1, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(expx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_EXP_TAB2_LIMBS * FLINT_BITS; bits = ARB_EXP_TAB21_BITS + ARB_EXP_TAB22_BITS; num = ARB_EXP_TAB22_NUM; mpfr_init2(tabx, prec); mpfr_init2(expx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_exp_tab22[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(expx, i, MPFR_RNDD); mpfr_div_2ui(expx, expx, bits, MPFR_RNDD); mpfr_exp(expx, expx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, expx, prec - 1, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(expx); mpfr_clear(y1); mpfr_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-exp_taylor_rs.c000066400000000000000000000043501461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_exp_taylor_rs, state) { slong iter; _flint_rand_init_gmp(state); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mp_ptr x, y1, y2, t; mp_limb_t err1, err2; ulong N; mp_size_t xn; int cmp, result; N = n_randint(state, 288 - 1); xn = 1 + n_randint(state, 20); x = flint_malloc(sizeof(mp_limb_t) * xn); y1 = flint_malloc(sizeof(mp_limb_t) * (xn + 1)); y2 = flint_malloc(sizeof(mp_limb_t) * (xn + 1)); t = flint_malloc(sizeof(mp_limb_t) * (xn + 1)); flint_mpn_rrandom(x, state->gmp_state, xn); flint_mpn_rrandom(y1, state->gmp_state, xn + 1); flint_mpn_rrandom(y2, state->gmp_state, xn + 1); x[xn - 1] &= (LIMB_ONES >> 4); _arb_exp_taylor_naive(y1, &err1, x, xn, N); _arb_exp_taylor_rs(y2, &err2, x, xn, N); cmp = mpn_cmp(y1, y2, xn + 1); if (cmp == 0) { result = 1; } else if (cmp > 0) { mpn_sub_n(t, y1, y2, xn + 1); result = flint_mpn_zero_p(t + 1, xn) && (t[0] <= err2); } else { mpn_sub_n(t, y2, y1, xn + 1); result = flint_mpn_zero_p(t + 1, xn) && (t[0] <= err2); } if (!result) { flint_printf("FAIL\n"); flint_printf("N = %wd xn = %wd\n", N, xn); flint_printf("x ="); flint_mpn_debug(x, xn); flint_printf("y1 ="); flint_mpn_debug(y1, xn + 1); flint_printf("y2 ="); flint_mpn_debug(y2, xn + 1); flint_abort(); } flint_free(x); flint_free(y1); flint_free(y2); flint_free(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-expm1.c000066400000000000000000000077401461254215100166140ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_expm1, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec0, prec; prec0 = 400; if (iter % 100 == 0) prec0 = 10000; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, prec0), 4); arb_randtest(b, state, 1 + n_randint(state, prec0), 4); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, prec0)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_expm1(t, t, MPFR_RNDN); arb_expm1(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("iter = %wd, prec = %wd\n\n", iter, prec); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_expm1(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("iter = %wd, prec = %wd\n\n", iter, prec); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* check large arguments */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec0, prec1, prec2, acc1, acc2; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_expm1(b, a, prec1); arb_set(c, a); /* also tests aliasing */ arb_expm1(c, c, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); /* compare with exp */ arb_expm1(c, a, prec1); arb_exp(d, a, prec1); arb_sub_ui(d, d, 1, prec1); acc1 = arb_rel_accuracy_bits(c); acc2 = arb_rel_accuracy_bits(d); if (!arb_overlaps(c, d) || ((acc2 > 0) && acc1 < FLINT_MIN(acc2, prec1) - 3)) { flint_printf("FAIL: comparison with exp\n\n"); flint_printf("prec = %wd, acc1 = %wd, acc2 = %wd\n\n", prec1, acc1, acc2); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-fac_ui.c000066400000000000000000000026021461254215100170000ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_fac_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong n; slong prec1, prec2; prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); arb_init(a); arb_init(b); arb_init(c); n = n_randtest(state); if (n + 1 == 0) n--; arb_fac_ui(a, n, prec1); arb_fac_ui(b, n + 1, prec1); arb_mul_ui(c, a, n + 1, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-fib.c000066400000000000000000000015661461254215100163220ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_fib, state) { /* trivial test because functions are based on gr */ { fmpz_t n; arb_t t; fmpz_init_set_ui(n, 10); arb_init(t); arb_fib_fmpz(t, n, 32); if (!arb_equal_si(t, 55)) flint_abort(); arb_fib_ui(t, 11, 32); if (!arb_equal_si(t, 89)) flint_abort(); arb_clear(t); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-floor.c000066400000000000000000000035771461254215100167070ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_floor, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x; fmpz_t y; slong prec; arb_init(a); arb_init(b); fmpq_init(x); fmpz_init(y); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); prec = 2 + n_randint(state, 200); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_floor(b, a, prec); fmpz_fdiv_q(y, fmpq_numref(x), fmpq_denref(x)); if (!arb_contains_fmpz(b, y)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_abort(); } arb_floor(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-fma.c000066400000000000000000000067201461254215100163220ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" void arb_fma_naive(arb_t res, const arb_t x, const arb_t y, const arb_t z, slong prec) { arb_t t; arb_init(t); arb_set(t, z); arb_addmul(t, x, y, prec); arb_set(res, t); arb_clear(t); } TEST_FUNCTION_START(arb_fma, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z, res1, res2; slong prec; int aliasing; arb_init(x); arb_init(y); arb_init(z); arb_init(res1); arb_init(res2); prec = 2 + n_randint(state, 200); arb_randtest_special(x, state, 200, 100); arb_randtest_special(y, state, 200, 100); arb_randtest_special(z, state, 200, 100); arb_randtest_special(res1, state, 200, 100); arb_randtest_special(res2, state, 200, 100); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(arb_midref(x))) < 10 && fmpz_bits(ARF_EXPREF(arb_midref(y))) < 10 && fmpz_bits(ARF_EXPREF(arb_midref(z))) < 10) { prec = ARF_PREC_EXACT; } aliasing = n_randint(state, 7); switch (aliasing) { case 0: arb_fma(res1, x, y, z, prec); arb_fma_naive(res2, x, y, z, prec); break; case 1: arb_set(res1, z); arb_fma(res1, x, y, res1, prec); arb_fma_naive(res2, x, y, z, prec); break; case 2: arb_set(res1, x); arb_fma(res1, res1, y, z, prec); arb_fma_naive(res2, x, y, z, prec); break; case 3: arb_set(res1, y); arb_fma(res1, x, res1, z, prec); arb_fma_naive(res2, x, y, z, prec); break; case 4: arb_fma(res1, x, x, z, prec); arb_fma_naive(res2, x, x, z, prec); break; case 5: arb_set(res1, x); arb_fma(res1, res1, res1, z, prec); arb_fma_naive(res2, x, x, z, prec); break; default: arb_set(res1, x); arb_fma(res1, res1, res1, res1, prec); arb_fma_naive(res2, x, x, x, prec); break; } if (!arb_equal(res1, res2)) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, aliasing = %d\n\n", prec, aliasing); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); arb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); arb_printd(res2, 30); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); arb_clear(res1); arb_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-gamma.c000066400000000000000000000034511461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_gamma, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 3); arb_gamma(b, a, prec1); arb_gamma(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check gamma(z+1) = z gamma(z) */ arb_mul(b, b, a, prec1); arb_add_ui(c, a, 1, prec1); arb_gamma(c, c, prec1); if (!arb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-gamma_fmpq.c000066400000000000000000000075041461254215100176650ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq.h" #include "arb.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif TEST_FUNCTION_START(arb_gamma_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r, s; fmpq_t q; slong accuracy, prec, pp, qq; prec = 2 + n_randint(state, 1 << n_randint(state, 12)); prec += 20; arb_init(r); arb_init(s); fmpq_init(q); pp = -100 + n_randint(state, 10000); qq = 1 + n_randint(state, 20); fmpq_set_si(q, pp, qq); arb_gamma_fmpq(r, q, prec); arb_set_fmpq(s, q, prec); arb_gamma(s, s, prec); if (!arb_overlaps(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); arb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_abort(); } if (!(fmpz_is_one(fmpq_denref(q)) && fmpz_sgn(fmpq_numref(q)) <= 0) && FLINT_ABS(pp / qq) < 10) { accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 6) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } arb_clear(r); arb_clear(s); fmpq_clear(q); } for (iter = 0; iter < 50 * 0.1 * flint_test_multiplier(); iter++) { arb_t r, s; fmpq_t q; slong accuracy, prec; prec = 2 + n_randint(state, 25000); arb_init(r); arb_init(s); fmpq_init(q); fmpz_randtest(fmpq_numref(q), state, 3 + n_randlimb(state) % 30); fmpz_randtest_not_zero(fmpq_denref(q), state, 3 + n_randlimb(state) % 30); fmpq_canonicalise(q); arb_gamma_fmpq(r, q, prec); arb_set_fmpq(s, q, prec); arb_gamma(s, s, prec); if (!arb_overlaps(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); arb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_abort(); } if (!(fmpz_is_one(fmpq_denref(q)) && fmpz_sgn(fmpq_numref(q)) <= 0) && fabs(fmpq_get_d(q)) < 10.0) { accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 6) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, prec / 3.33, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, prec / 3.33, 0); flint_printf("\n\n"); flint_abort(); } } arb_clear(r); arb_clear(s); fmpq_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_abs_lbound_arf.c000066400000000000000000000057661461254215100213670ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_get_abs_lbound_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; arf_t b, b2, b3; fmpq_t q; arb_init(x); arf_init(b); arf_init(b2); arf_init(b3); fmpq_init(q); arb_randtest(x, state, 1 + n_randint(state, 200), 10); arb_get_abs_lbound_arf(b, x, 2 + n_randint(state, 200)); arb_get_rand_fmpq(q, state, x, 1 + n_randint(state, 200)); arf_mul_fmpz(b2, b, fmpq_denref(q), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_fmpz(b3, fmpq_numref(q)); arf_abs(b3, b3); if (arf_cmp(b2, b3) > 0) { flint_printf("FAIL (abs_lbound):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("b2 = "); arf_print(b2); flint_printf("\n\n"); flint_printf("b3 = "); arf_print(b3); flint_printf("\n\n"); flint_abort(); } arb_get_abs_ubound_arf(b, x, 2 + n_randint(state, 200)); arb_get_rand_fmpq(q, state, x, 1 + n_randint(state, 200)); arf_mul_fmpz(b2, b, fmpq_denref(q), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_fmpz(b3, fmpq_numref(q)); arf_abs(b3, b3); if (arf_cmp(b2, b3) < 0) { flint_printf("FAIL (abs_ubound):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("b2 = "); arf_print(b2); flint_printf("\n\n"); flint_printf("b3 = "); arf_print(b3); flint_printf("\n\n"); flint_abort(); } arb_randtest_special(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); arb_get_abs_lbound_arf(b, x, 2 + n_randint(state, 200)); arb_get_abs_ubound_arf(b2, x, 2 + n_randint(state, 200)); if (arf_cmp(b, b2) > 0) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("b2 = "); arf_print(b2); flint_printf("\n\n"); flint_abort(); } arb_clear(x); fmpq_clear(q); arf_clear(b); arf_clear(b2); arf_clear(b3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_fmpz_mid_rad_10exp.c000066400000000000000000000047331461254215100220700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_fmpz_mid_rad_10exp, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, t; fmpz_t mid, rad, exp; slong n, prec; arb_init(x); arb_init(y); arb_init(t); fmpz_init(mid); fmpz_init(rad); fmpz_init(exp); arb_randtest_special(x, state, 1 + n_randint(state, 500), 1 + n_randint(state, 500)); n = 1 + n_randint(state, 500); prec = 2 + n_randint(state, 1500); arb_get_fmpz_mid_rad_10exp(mid, rad, exp, x, n); arf_set_fmpz(arb_midref(y), mid); mag_set_fmpz(arb_radref(y), rad); arb_set_ui(t, 10); arb_pow_fmpz(t, t, exp, prec); arb_mul(y, y, t, prec); if (arb_is_finite(x) && !arb_is_zero(x) && fmpz_sizeinbase(mid, 10) < n && fmpz_sizeinbase(rad, 10) < n) { flint_printf("FAIL (too few digits):\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("mid = "); fmpz_print(mid); flint_printf("\n\n"); flint_printf("rad = "); fmpz_print(rad); flint_printf("\n\n"); flint_printf("exp = "); fmpz_print(exp); flint_printf("\n\n"); flint_abort(); } if (arb_is_finite(x) && !arb_contains(y, x)) { flint_printf("FAIL (containment):\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_printf("mid = "); fmpz_print(mid); flint_printf("\n\n"); flint_printf("rad = "); fmpz_print(rad); flint_printf("\n\n"); flint_printf("exp = "); fmpz_print(exp); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(t); fmpz_clear(mid); fmpz_clear(rad); fmpz_clear(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_interval_arf.c000066400000000000000000000026031461254215100210660ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_interval_arf, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y; arf_t a, b; arb_init(x); arf_init(a); arf_init(b); arb_init(y); arb_randtest_special(x, state, 200, 100); arb_get_interval_arf(a, b, x, 2 + n_randint(state, 200)); arb_set_interval_arf(y, a, b, 2 + n_randint(state, 200)); if (!arb_contains(y, x)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arf_clear(a); arf_clear(b); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_interval_fmpz_2exp.c000066400000000000000000000042341461254215100222320ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_interval_fmpz_2exp, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; arf_t y; fmpz_t a, b, exp; arb_init(x); arf_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(exp); arb_randtest(x, state, 200, 10); arb_get_interval_fmpz_2exp(a, b, exp, x); arf_set_fmpz_2exp(y, a, exp); if (!arb_contains_arf(x, y)) { flint_printf("FAIL (a):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf(" exp = "); fmpz_print(exp); flint_printf("\n\n"); flint_abort(); } arf_set_fmpz_2exp(y, b, exp); if (!arb_contains_arf(x, y)) { flint_printf("FAIL (b):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf(" exp = "); fmpz_print(exp); flint_printf("\n\n"); flint_abort(); } if (fmpz_is_even(a) && fmpz_is_even(b) && !(fmpz_is_zero(a) && fmpz_is_zero(b))) { flint_printf("FAIL (odd):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf(" exp = "); fmpz_print(exp); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arf_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_interval_mpfr.c000066400000000000000000000027371461254215100212720ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_get_interval_mpfr, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y; mpfr_t aa, bb; arb_init(x); arb_init(y); mpfr_init2(aa, 2 + n_randint(state, 200)); mpfr_init2(bb, 2 + n_randint(state, 200)); arb_randtest_special(x, state, 200, 10); arb_get_interval_mpfr(aa, bb, x); arb_set_interval_mpfr(y, aa, bb, 2 + n_randint(state, 200)); if (!arb_contains(y, x)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("aa = "); mpfr_printf("%.50Rg", aa); flint_printf("\n\n"); flint_printf("bb = "); mpfr_printf("%.50Rg", bb); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); mpfr_clear(aa); mpfr_clear(bb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_lbound_arf.c000066400000000000000000000056501461254215100205320ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_get_lbound_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; arf_t b, b2, b3; fmpq_t q; arb_init(x); arf_init(b); arf_init(b2); arf_init(b3); fmpq_init(q); arb_randtest(x, state, 1 + n_randint(state, 200), 10); arb_get_lbound_arf(b, x, 2 + n_randint(state, 200)); arb_get_rand_fmpq(q, state, x, 1 + n_randint(state, 200)); arf_mul_fmpz(b2, b, fmpq_denref(q), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_fmpz(b3, fmpq_numref(q)); if (arf_cmp(b2, b3) > 0) { flint_printf("FAIL (lbound):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("b2 = "); arf_print(b2); flint_printf("\n\n"); flint_printf("b3 = "); arf_print(b3); flint_printf("\n\n"); flint_abort(); } arb_get_ubound_arf(b, x, 2 + n_randint(state, 200)); arb_get_rand_fmpq(q, state, x, 1 + n_randint(state, 200)); arf_mul_fmpz(b2, b, fmpq_denref(q), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_fmpz(b3, fmpq_numref(q)); if (arf_cmp(b2, b3) < 0) { flint_printf("FAIL (ubound):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("b2 = "); arf_print(b2); flint_printf("\n\n"); flint_printf("b3 = "); arf_print(b3); flint_printf("\n\n"); flint_abort(); } arb_randtest_special(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); arb_get_lbound_arf(b, x, 2 + n_randint(state, 200)); arb_get_ubound_arf(b2, x, 2 + n_randint(state, 200)); if (arf_cmp(b, b2) > 0) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("b2 = "); arf_print(b2); flint_printf("\n\n"); flint_abort(); } arb_clear(x); fmpq_clear(q); arf_clear(b); arf_clear(b2); arf_clear(b3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_mag.c000066400000000000000000000025561461254215100171650ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_mag, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; mag_t m; arb_init(a); arb_init(b); mag_init(m); arb_randtest_special(a, state, 200, 1 + n_randint(state, 100)); arb_get_mag(m, a); MAG_CHECK_BITS(m) if (arf_is_nan(arb_midref(a))) arf_nan(arb_midref(b)); else arf_zero(arb_midref(b)); mag_set(arb_radref(b), m); if (!arb_contains(b, a)) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("m = "); mag_print(m); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); mag_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_mag_lower.c000066400000000000000000000035061461254215100203710ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_mag_lower, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a; mag_t m; int result; arf_struct t[3]; arf_t s; arb_init(a); mag_init(m); arf_init(s); arb_randtest_special(a, state, 200, 1 + n_randint(state, 100)); arb_get_mag_lower(m, a); MAG_CHECK_BITS(m) if (arb_contains_zero(a)) { result = mag_is_zero(m); } else if (arb_contains_negative(a)) { arf_init_set_shallow(t + 0, arb_midref(a)); arf_init_set_mag_shallow(t + 1, arb_radref(a)); arf_init_set_mag_shallow(t + 2, m); arf_sum(s, t, 3, 16, ARF_RND_DOWN); result = (arf_sgn(s) <= 0); } else { arf_init_set_shallow(t + 0, arb_midref(a)); arf_init_neg_mag_shallow(t + 1, arb_radref(a)); arf_init_neg_mag_shallow(t + 2, m); result = (arf_sgn(s) >= 0); } if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("m = "); mag_print(m); flint_printf("\n\n"); flint_abort(); } arb_clear(a); mag_clear(m); arf_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_mag_lower_nonnegative.c000066400000000000000000000031321461254215100227610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_mag_lower_nonnegative, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a; mag_t m; int result; arf_struct t[3]; arf_t s; arb_init(a); mag_init(m); arf_init(s); arb_randtest_special(a, state, 200, 1 + n_randint(state, 100)); arb_get_mag_lower_nonnegative(m, a); MAG_CHECK_BITS(m) if (arb_contains_nonpositive(a)) { result = mag_is_zero(m); } else { arf_init_set_shallow(t + 0, arb_midref(a)); arf_init_neg_mag_shallow(t + 1, arb_radref(a)); arf_init_neg_mag_shallow(t + 2, m); arf_sum(s, t, 3, 16, ARF_RND_DOWN); result = (arf_sgn(s) >= 0); } if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("m = "); mag_print(m); flint_printf("\n\n"); flint_abort(); } arb_clear(a); mag_clear(m); arf_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_mpn_fixed_mod_log2.c000066400000000000000000000054161461254215100221520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_mpn_fixed_mod_log2, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; fmpz_t q; mp_ptr w; arb_t wb, t; mp_size_t wn; slong prec, prec2; int success; mp_limb_t error; prec = 2 + n_randint(state, 10000); wn = 1 + n_randint(state, 200); prec2 = FLINT_MAX(prec, wn * FLINT_BITS) + 100; arf_init(x); arb_init(wb); arb_init(t); fmpz_init(q); w = flint_malloc(sizeof(mp_limb_t) * wn); arf_randtest(x, state, prec, 14); /* this should generate numbers close to multiples of log(2) */ if (n_randint(state, 4) == 0) { arb_const_log2(t, prec); fmpz_randtest(q, state, 200); arb_mul_fmpz(t, t, q, prec); arf_add(x, x, arb_midref(t), prec, ARF_RND_DOWN); } success = _arb_get_mpn_fixed_mod_log2(w, q, &error, x, wn); if (success) { _arf_set_mpn_fixed(arb_midref(wb), w, wn, wn, 0, FLINT_BITS * wn, ARB_RND); mag_set_ui_2exp_si(arb_radref(wb), error, -FLINT_BITS * wn); arb_const_log2(t, prec2); arb_mul_fmpz(t, t, q, prec2); arb_add(t, t, wb, prec2); if (!arb_contains_arf(t, x)) { flint_printf("FAIL (containment)\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 50); flint_printf("\n\n"); flint_abort(); } arb_const_log2(t, prec2); if (arf_sgn(arb_midref(wb)) < 0 || arf_cmp(arb_midref(wb), arb_midref(t)) >= 0) { flint_printf("FAIL (expected 0 <= w < log(2))\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); flint_abort(); } } flint_free(w); fmpz_clear(q); arf_clear(x); arb_clear(wb); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_mpn_fixed_mod_pi4.c000066400000000000000000000063361461254215100220050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_mpn_fixed_mod_pi4, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; int octant; fmpz_t q; mp_ptr w; arb_t wb, t, u; mp_size_t wn; slong prec, prec2; int success; mp_limb_t error; prec = 2 + n_randint(state, 10000); wn = 1 + n_randint(state, 200); prec2 = FLINT_MAX(prec, wn * FLINT_BITS) + 100; arf_init(x); arb_init(wb); arb_init(t); arb_init(u); fmpz_init(q); w = flint_malloc(sizeof(mp_limb_t) * wn); arf_randtest(x, state, prec, 14); /* this should generate numbers close to multiples of pi/4 */ if (n_randint(state, 4) == 0) { arb_const_pi(t, prec); arb_mul_2exp_si(t, t, -2); fmpz_randtest(q, state, 200); arb_mul_fmpz(t, t, q, prec); arf_add(x, x, arb_midref(t), prec, ARF_RND_DOWN); } arf_abs(x, x); success = _arb_get_mpn_fixed_mod_pi4(w, q, &octant, &error, x, wn); if (success) { /* could round differently */ if (fmpz_fdiv_ui(q, 8) != octant) { flint_printf("bad octant\n"); flint_abort(); } _arf_set_mpn_fixed(arb_midref(wb), w, wn, wn, 0, FLINT_BITS * wn, ARB_RND); mag_set_ui_2exp_si(arb_radref(wb), error, -FLINT_BITS * wn); arb_const_pi(u, prec2); arb_mul_2exp_si(u, u, -2); arb_set(t, wb); if (octant % 2 == 1) arb_sub(t, u, t, prec2); arb_addmul_fmpz(t, u, q, prec2); if (!arb_contains_arf(t, x)) { flint_printf("FAIL (containment)\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 50); flint_printf("\n\n"); flint_abort(); } arb_const_pi(t, prec2); arb_mul_2exp_si(t, t, -2); if (arf_sgn(arb_midref(wb)) < 0 || arf_cmp(arb_midref(wb), arb_midref(t)) >= 0) { flint_printf("FAIL (expected 0 <= w < pi/4)\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); flint_abort(); } } flint_free(w); fmpz_clear(q); arf_clear(x); arb_clear(wb); arb_clear(t); arb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_rand_fmpq.c000066400000000000000000000022301461254215100203550ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_get_rand_fmpq, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; fmpq_t q; arb_init(x); fmpq_init(q); arb_randtest(x, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(q, state, x, 1 + n_randint(state, 200)); if (!arb_contains_fmpq(x, q) || !fmpq_is_canonical(q)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_abort(); } arb_clear(x); fmpq_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_str.c000066400000000000000000000074031461254215100172250ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_get_str, state) { slong iter; /* just test no crashing... */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; char * s; slong n; arb_init(x); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); n = 1 + n_randint(state, 300); s = arb_get_str(x, n, (n_randint(state, 2) * ARB_STR_MORE) | (n_randint(state, 2) * ARB_STR_NO_RADIUS) | (ARB_STR_CONDENSE * n_randint(state, 50))); flint_free(s); arb_clear(x); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y; char * s; slong n, prec; int conversion_error; arb_init(x); arb_init(y); arb_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); n = 1 + n_randint(state, 300); prec = 2 + n_randint(state, 1000); s = arb_get_str(x, n, n_randint(state, 2) * ARB_STR_MORE); conversion_error = arb_set_str(y, s, prec); if (conversion_error || !arb_contains(y, x)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("s = %s", s); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } flint_free(s); arb_clear(x); arb_clear(y); } /* test ARB_STR_NO_RADIUS */ { arb_t x; char * s; arb_init(x); arb_set_str(x, "3.1415926535897932", 53); s = arb_get_str(x, 10, ARB_STR_NO_RADIUS); if (strcmp(s, "3.141592654")) { flint_printf("FAIL (ARB_STR_NO_RADIUS)\n"); flint_printf("%s\n", s); flint_abort(); } flint_free(s); arb_set_str(x, "+/- 3.45e-10", 53); s = arb_get_str(x, 10, ARB_STR_NO_RADIUS); if (strcmp(s, "0e-9")) { flint_printf("FAIL (ARB_STR_NO_RADIUS)\n"); flint_printf("%s\n", s); flint_abort(); } flint_free(s); arb_set_str(x, "+/- 3.45e10", 53); s = arb_get_str(x, 10, ARB_STR_NO_RADIUS); if (strcmp(s, "0e+11")) { flint_printf("FAIL (ARB_STR_NO_RADIUS)\n"); flint_printf("%s\n", s); flint_abort(); } flint_free(s); arb_set_str(x, "5e10 +/- 6e10", 53); s = arb_get_str(x, 10, ARB_STR_NO_RADIUS); if (strcmp(s, "0e+12")) { flint_printf("FAIL (ARB_STR_NO_RADIUS)\n"); flint_printf("%s\n", s); flint_abort(); } flint_free(s); arb_set_str(x, "5e-100000000000000000002 +/- 5e-100000000000000000002", 53); s = arb_get_str(x, 10, ARB_STR_NO_RADIUS); if (strcmp(s, "0e-100000000000000000000")) { flint_printf("FAIL (ARB_STR_NO_RADIUS)\n"); flint_printf("%s\n", s); flint_abort(); } flint_free(s); arb_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-get_unique_fmpz.c000066400000000000000000000116171461254215100207610ustar00rootroot00000000000000/* Copyright (C) 2012, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_get_unique_fmpz, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, z; fmpz_t y, a, b, exp; int unique, unique2; arb_init(x); arb_init(z); fmpz_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(exp); arb_randtest(x, state, 2000, 10); /* generate tiny and huge radii */ if (iter % 2 == 0) { mag_randtest_special(arb_radref(x), state, 100); unique = arb_get_unique_fmpz(y, x); arf_get_fmpz(a, arb_midref(x), ARF_RND_FLOOR); fmpz_add_ui(b, a, 1); if (unique) { if (arb_contains_fmpz(x, a) == arb_contains_fmpz(x, b)) { flint_printf("FAIL (1):\n\n"); flint_printf("x = "); arb_printd(x, 100); flint_printf("\n\n"); flint_printf("unique = %d\n\n", unique); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_abort(); } } else { if (arb_contains_fmpz(x, a) != arb_contains_fmpz(x, b)) { flint_printf("FAIL (2):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("unique = %d\n\n", unique); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_abort(); } } } else { unique = arb_get_unique_fmpz(y, x); arb_get_interval_fmpz_2exp(a, b, exp, x); if (fmpz_sgn(exp) >= 0) { fmpz_mul_2exp(a, a, fmpz_get_si(exp)); fmpz_mul_2exp(b, b, fmpz_get_si(exp)); } else { fmpz_cdiv_q_2exp(a, a, -fmpz_get_si(exp)); fmpz_fdiv_q_2exp(b, b, -fmpz_get_si(exp)); } unique2 = fmpz_equal(a, b); if ((unique != unique2) || (unique && !fmpz_equal(y, a))) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("unique = %d, unique2 = %d\n\n", unique, unique2); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf(" exp = "); fmpz_print(exp); flint_printf("\n\n"); flint_abort(); } if (unique) { arb_set_fmpz(z, y); arb_set_round(z, z, 2 + n_randint(state, 1000)); if (!arb_overlaps(x, z)) { flint_printf("FAIL (overlap):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } fmpz_add_ui(b, y, 1); if (arb_contains_fmpz(x, b)) { flint_printf("FAIL (contains a + 1):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_abort(); } fmpz_sub_ui(b, y, 1); if (arb_contains_fmpz(x, b)) { flint_printf("FAIL (contains a - 1):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_abort(); } } } arb_clear(x); arb_clear(z); fmpz_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-hurwitz_zeta.c000066400000000000000000000037341461254215100203200ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "acb.h" TEST_FUNCTION_START(arb_hurwitz_zeta, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; acb_t d, e, f; slong prec; prec = 2 + n_randint(state, 300); arb_init(a); arb_init(b); arb_init(c); acb_init(d); acb_init(e); acb_init(f); arb_randtest_precise(a, state, 1 + n_randint(state, 300), 5); arb_randtest_precise(b, state, 1 + n_randint(state, 300), 5); arb_randtest_precise(c, state, 1 + n_randint(state, 300), 5); acb_set_arb(d, a); acb_set_arb(e, b); arb_hurwitz_zeta(c, a, b, prec); acb_hurwitz_zeta(f, d, e, prec); if (!arb_overlaps(c, acb_realref(f)) || (arb_is_finite(c) && !arb_contains_zero(acb_imagref(f)))) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 15); flint_printf("\n\n"); flint_printf("e = "); acb_printd(e, 15); flint_printf("\n\n"); flint_printf("f = "); acb_printd(f, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); acb_clear(d); acb_clear(e); acb_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-intersection.c000066400000000000000000000131441461254215100202630ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_intersection, state) { slong iter; /* check a containment requirement */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z, w; arb_t xy, yz; slong pa, pb, pc; int alias; arb_init(x); arb_init(y); arb_init(z); arb_init(w); arb_init(xy); arb_init(yz); arb_randtest_special(x, state, 200, 10); arb_randtest_special(y, state, 200, 10); arb_randtest_special(z, state, 200, 10); arb_randtest_special(w, state, 200, 10); arb_randtest_special(xy, state, 200, 10); arb_randtest_special(yz, state, 200, 10); pa = 2 + n_randint(state, 200); pb = 2 + n_randint(state, 200); pc = 2 + n_randint(state, 200); arb_union(xy, x, y, pa); arb_union(yz, y, z, pb); arb_intersection(w, xy, yz, pc); if (!arb_contains(w, y)) { flint_printf("FAIL (containment):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("w = "); arb_print(w); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { arb_intersection(xy, xy, yz, pc); alias = arb_equal(xy, w); } else { arb_intersection(yz, xy, yz, pc); alias = arb_equal(yz, w); } if (!alias) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("w = "); arb_print(w); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); arb_clear(w); arb_clear(xy); arb_clear(yz); } /* require that the return value is the same as for arb_overlaps */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, y; fmpq_t am, ar, bm, br, t, u; int c1, c2, c3; slong prec; prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(y); fmpq_init(am); fmpq_init(ar); fmpq_init(bm); fmpq_init(br); fmpq_init(t); fmpq_init(u); arb_randtest(a, state, 1 + n_randint(state, 500), 14); arb_randtest(b, state, 1 + n_randint(state, 500), 14); arf_get_fmpq(am, arb_midref(a)); mag_get_fmpq(ar, arb_radref(a)); arf_get_fmpq(bm, arb_midref(b)); mag_get_fmpq(br, arb_radref(b)); fmpq_sub(t, am, bm); fmpz_abs(fmpq_numref(t), fmpq_numref(t)); fmpq_add(u, ar, br); c1 = arb_overlaps(a, b); c2 = (fmpq_cmp(t, u) <= 0); c3 = arb_intersection(y, a, b, prec); if (c1 != c2 || c1 != c3) { flint_printf("FAIL (compatibility with arb_overlaps):\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("am = "); fmpq_print(am); flint_printf("\n\n"); flint_printf("ar = "); fmpq_print(ar); flint_printf("\n\n"); flint_printf("bm = "); fmpq_print(bm); flint_printf("\n\n"); flint_printf("br = "); fmpq_print(br); flint_printf("\n\n"); flint_printf("t = "); fmpq_print(t); flint_printf("\n\n"); flint_printf("u = "); fmpq_print(u); flint_printf("\n\n"); flint_printf("c1 = %d, c2 = %d, c3 = %d\n\n", c1, c2, c3); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(y); fmpq_clear(am); fmpq_clear(ar); fmpq_clear(bm); fmpq_clear(br); fmpq_clear(t); fmpq_clear(u); } /* check a simple hardcoded example */ { slong prec; arb_t xy, yz, y, v, w; prec = 32; arb_init(xy); arb_init(yz); arb_init(y); arb_init(v); arb_init(w); arb_set_str(xy, "1 +/- 1", prec); arb_set_str(yz, "2 +/- 1", prec); arb_set_str(y, "1.5 +/- 0.6", prec); arb_set_str(v, "1.5 +/- 0.4", prec); arb_intersection(w, xy, yz, prec); if (!arb_contains(y, w) || !arb_contains(w, v)) { flint_printf("FAIL (hardcoded example)\n\n"); flint_printf("xy = "); arb_print(xy); flint_printf("\n\n"); flint_printf("yx = "); arb_print(yz); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("w = "); arb_print(w); flint_printf("\n\n"); flint_abort(); } arb_clear(xy); arb_clear(yz); arb_clear(y); arb_clear(v); arb_clear(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-lambertw.c000066400000000000000000000067111461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_lambertw, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x1, x2, t, w1, w2; slong prec1, prec2, ebits; int branch; arb_init(x1); arb_init(x2); arb_init(t); arb_init(w1); arb_init(w2); branch = n_randint(state, 2); if (n_randint(state, 4) == 0) { prec1 = 2 + n_randint(state, 3000); prec2 = 2 + n_randint(state, 3000); ebits = 1 + n_randint(state, 1000); } else { prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 50); } arb_randtest(x1, state, 1 + n_randint(state, 1000), ebits); arb_randtest(x2, state, 1 + n_randint(state, 1000), ebits); arb_randtest(t, state, 1 + n_randint(state, 1000), ebits); arb_randtest(w1, state, 1 + n_randint(state, 1000), ebits); arb_randtest(w2, state, 1 + n_randint(state, 1000), ebits); if (n_randint(state, 4) == 0) { arb_const_e(t, 2 * prec1); arb_inv(t, t, 2 * prec1); arb_sub(x1, x1, t, 2 * prec1); } if (n_randint(state, 2)) { arb_set(x2, x1); } else { arb_add(x2, x1, t, 2 * prec1); arb_sub(x2, x2, t, 2 * prec1); } arb_lambertw(w1, x1, branch, prec1); if (n_randint(state, 2)) { arb_set(w2, x2); arb_lambertw(w2, w2, branch, prec1); } else { arb_lambertw(w2, x2, branch, prec1); } if (!arb_overlaps(w1, w2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("branch = %d, prec1 = %wd, prec2 = %wd\n\n", branch, prec1, prec2); flint_printf("x1 = "); arb_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); arb_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); arb_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); arb_printd(w2, 50); flint_printf("\n\n"); flint_abort(); } arb_exp(t, w1, prec1); arb_mul(t, t, w1, prec1); if (!arb_contains(t, x1)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("branch = %d, prec1 = %wd, prec2 = %wd\n\n", branch, prec1, prec2); flint_printf("x1 = "); arb_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); arb_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); arb_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); arb_printd(w2, 50); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 50); flint_printf("\n\n"); flint_abort(); } arb_clear(x1); arb_clear(x2); arb_clear(t); arb_clear(w1); arb_clear(w2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-lgamma.c000066400000000000000000000027261461254215100170170ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_lgamma, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 3); arb_lgamma(b, a, prec1); arb_lgamma(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_lgamma(a, a, prec2); if (!arb_equal(a, c)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log.c000066400000000000000000000120571461254215100163400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_log, state) { slong iter; /* compare with mpfr */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); do { arb_randtest(a, state, 1 + n_randint(state, 200), 10); } while (arb_contains_nonpositive(a)); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); /* todo: estimate cancellation precisely */ if (mpfr_cmp_d(t, 1 - 1e-10) > 0 && mpfr_cmp_d(t, 1 + 1e-10) < 0) { mpfr_set_prec(t, prec + 1000); fmpq_get_mpfr(t, q, MPFR_RNDN); } mpfr_log(t, t, MPFR_RNDN); arb_log(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_log(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* compare with mpfr (higher precision) */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 6000); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); do { arb_randtest(a, state, 1 + n_randint(state, 6000), 10); } while (arb_contains_nonpositive(a)); if (n_randint(state, 10) == 0) arb_set_ui(a, n_randint(state, 100)); arb_randtest(b, state, 1 + n_randint(state, 6000), 10); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); /* todo: estimate cancellation precisely */ if (mpfr_cmp_d(t, 1 - 1e-10) > 0 && mpfr_cmp_d(t, 1 + 1e-10) < 0) { mpfr_set_prec(t, prec + 10000); fmpq_get_mpfr(t, q, MPFR_RNDN); } mpfr_log(t, t, MPFR_RNDN); arb_log(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_log(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* test large numbers */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, ab, lab, la, lb, lalb; slong prec = 2 + n_randint(state, 6000); arb_init(a); arb_init(b); arb_init(ab); arb_init(lab); arb_init(la); arb_init(lb); arb_init(lalb); arb_randtest(a, state, 1 + n_randint(state, 400), 400); arb_randtest(b, state, 1 + n_randint(state, 400), 400); arb_log(la, a, prec); arb_log(lb, b, prec); arb_mul(ab, a, b, prec); arb_log(lab, ab, prec); arb_add(lalb, la, lb, prec); if (!arb_overlaps(lab, lalb)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("la = "); arb_print(la); flint_printf("\n\n"); flint_printf("lb = "); arb_print(lb); flint_printf("\n\n"); flint_printf("ab = "); arb_print(ab); flint_printf("\n\n"); flint_printf("lab = "); arb_print(lab); flint_printf("\n\n"); flint_printf("lalb = "); arb_print(lalb); flint_printf("\n\n"); flint_abort(); } arb_log(a, a, prec); if (!arb_overlaps(a, la)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(ab); arb_clear(lab); arb_clear(la); arb_clear(lb); arb_clear(lalb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log1p.c000066400000000000000000000046531461254215100166040ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_log1p, state) { slong iter; for (iter = 0; iter < 20000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec0, prec1, prec2; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); arb_log1p(b, a, prec1); arb_log1p(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* compare with log */ arb_add_ui(d, a, 1, prec2); arb_log(d, d, prec2); if (!arb_overlaps(c, d)) { flint_printf("FAIL: comparison with log\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_log1p(a, a, prec1); if (!arb_overlaps(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log_arf.c000066400000000000000000000045351461254215100171720ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_log_arf, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; arb_t y1, y2; slong prec1, prec2, acc1, acc2; prec1 = 2 + n_randint(state, 9000); prec2 = 2 + n_randint(state, 9000); arf_init(x); arb_init(y1); arb_init(y2); arf_randtest_special(x, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y1, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y2, state, 1 + n_randint(state, 9000), 200); if (n_randint(state, 2)) arf_add_ui(x, x, 1, 2 + n_randint(state, 9000), ARF_RND_DOWN); arb_log_arf(y1, x, prec1); arb_log_arf(y2, x, prec2); if (!arb_overlaps(y1, y2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y1 = "); arb_print(y1); flint_printf("\n\n"); flint_printf("y2 = "); arb_print(y2); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(y1); acc2 = arb_rel_accuracy_bits(y2); if (arf_sgn(x) > 0) { if (acc1 < prec1 - 2 || acc2 < prec2 - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("acc1 = %wd, acc2 = %wd\n\n", acc1, acc2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y1 = "); arb_print(y1); flint_printf("\n\n"); flint_printf("y2 = "); arb_print(y2); flint_printf("\n\n"); flint_abort(); } } arf_clear(x); arb_clear(y1); arb_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log_base_ui.c000066400000000000000000000067111461254215100200270ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_log_base_ui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, bx, lbx, lbx1; ulong n, b, b2, r; slong prec; arb_init(x); arb_init(bx); arb_init(lbx); arb_init(lbx1); prec = 2 + n_randint(state, 500); b = n_randtest(state); b = n_pow(b, 1 + n_randint(state, 4)); if (n_randint(state, 2)) arb_set_ui(x, n_randtest(state)); else arb_randtest(x, state, 2 + n_randint(state, 500), 1 + n_randint(state, 200)); arb_randtest(bx, state, 2 + n_randint(state, 500), 1 + n_randint(state, 200)); arb_randtest(lbx, state, 2 + n_randint(state, 500), 1 + n_randint(state, 200)); arb_set_ui(bx, b); arb_pow(bx, bx, x, 2 + n_randint(state, 500)); arb_log_base_ui(lbx, bx, b, prec); /* test log_b(b^x) = x */ if (!arb_overlaps(lbx, x)) { flint_printf("FAIL: overlap\n\n"); flint_printf("b = %wu\n\n", b); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("bx = "); arb_printd(bx, 30); flint_printf("\n\n"); flint_printf("lbx = "); arb_printd(lbx, 30); flint_printf("\n\n"); flint_abort(); } arb_log_base_ui(bx, bx, b, prec); if (!arb_overlaps(bx, lbx)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("b = %wu\n\n", b); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("bx = "); arb_printd(bx, 30); flint_printf("\n\n"); flint_printf("lbx = "); arb_printd(lbx, 30); flint_printf("\n\n"); flint_abort(); } /* test exact computation of log_{b^(2^r)}(b^n)*/ n = n_randint(state, 100); b = 2 + n_randint(state, 10); r = n_randint(state, 4); b2 = n_pow(b, 1 << r); arb_set_ui(lbx1, n); arb_mul_2exp_si(lbx1, lbx1, -r); for (prec = 20; ; prec *= 2) { arb_set_ui(bx, b); arb_pow_ui(bx, bx, n, prec); arb_log_base_ui(lbx, bx, b2, prec); if (!arb_contains(lbx, lbx1) || prec > 10000) { flint_printf("FAIL: containment or exactness\n\n"); flint_printf("b = %wu\n\n", b); flint_printf("b2 = %wu\n\n", b2); flint_printf("r = %wu\n\n", r); flint_printf("n = %wu\n\n", n); flint_printf("bx = "); arb_printd(bx, 30); flint_printf("\n\n"); flint_printf("lbx = "); arb_printd(lbx, 30); flint_printf("\n\n"); flint_printf("lbx1 = "); arb_printd(lbx1, 30); flint_printf("\n\n"); flint_abort(); } if (arb_is_exact(lbx)) break; } arb_clear(x); arb_clear(bx); arb_clear(lbx); arb_clear(lbx1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log_hypot.c000066400000000000000000000103761461254215100175650ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_log_hypot, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, r, s; slong prec1, prec2, acc1, acc2; prec1 = 2 + n_randint(state, 400); prec2 = 2 + n_randint(state, 400); arb_init(a); arb_init(b); arb_init(r); arb_init(s); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(r, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_randtest_special(s, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); if (n_randint(state, 2)) { arb_log_hypot(r, a, b, prec1); } else if (n_randint(state, 2)) { arb_set(r, a); arb_log_hypot(r, r, b, prec1); } else { arb_set(r, b); arb_log_hypot(r, a, r, prec1); } arb_hypot(s, a, b, prec2); arb_log(s, s, prec2); /* check consistency */ if (!arb_overlaps(r, s)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_abort(); } if (!arb_is_finite(r) && arb_is_finite(a) && arb_is_finite(b) && (!arb_contains_zero(a) || !arb_contains_zero(b))) { flint_printf("FAIL: not finite\n\n"); flint_printf("prec1 = %wd\n\n", prec1); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(r); acc2 = arb_rel_accuracy_bits(s); if (prec2 <= prec1 && acc1 > 0 && acc2 > 0 && acc1 < acc2 - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd, acc2 = %wd\n\n", prec1, acc1, acc2); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_abort(); } if (!arf_is_nan(arb_midref(a)) && !arf_is_nan(arb_midref(b))) { if ((!arb_is_finite(a) && !arb_contains_zero(a)) || (!arb_is_finite(b) && !arb_contains_zero(b))) { if (arf_is_nan(arb_midref(r)) || arb_is_finite(r) || !arb_is_positive(r)) { flint_printf("FAIL: infinite\n\n"); flint_printf("prec1 = %wd, acc1 = %wd, acc2 = %wd\n\n", prec1, acc1, acc2); flint_printf("a = "); arb_printn(a, 50, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 50, 0); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_abort(); } } } arb_clear(a); arb_clear(b); arb_clear(r); arb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log_newton.c000066400000000000000000000072751461254215100177400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_log_newton, state) { slong iter; /* compare with mpfr (higher precision) */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 6000); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); do { arb_randtest(a, state, 1 + n_randint(state, 6000), 10); } while (arb_contains_nonpositive(a)); if (n_randint(state, 10) == 0) arb_set_ui(a, n_randint(state, 100)); arb_randtest(b, state, 1 + n_randint(state, 6000), 10); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); /* todo: estimate cancellation precisely */ if (mpfr_cmp_d(t, 1 - 1e-10) > 0 && mpfr_cmp_d(t, 1 + 1e-10) < 0) { mpfr_set_prec(t, prec + 10000); fmpq_get_mpfr(t, q, MPFR_RNDN); } mpfr_log(t, t, MPFR_RNDN); arb_log_newton(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_log_newton(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* test large numbers */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, ab, lab, la, lb, lalb; slong prec = 2 + n_randint(state, 6000); arb_init(a); arb_init(b); arb_init(ab); arb_init(lab); arb_init(la); arb_init(lb); arb_init(lalb); arb_randtest(a, state, 1 + n_randint(state, 400), 400); arb_randtest(b, state, 1 + n_randint(state, 400), 400); arb_log_newton(la, a, prec); arb_log_newton(lb, b, prec); arb_mul(ab, a, b, prec); arb_log_newton(lab, ab, prec); arb_add(lalb, la, lb, prec); if (!arb_overlaps(lab, lalb)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("la = "); arb_print(la); flint_printf("\n\n"); flint_printf("lb = "); arb_print(lb); flint_printf("\n\n"); flint_printf("ab = "); arb_print(ab); flint_printf("\n\n"); flint_printf("lab = "); arb_print(lab); flint_printf("\n\n"); flint_printf("lalb = "); arb_print(lalb); flint_printf("\n\n"); flint_abort(); } arb_log_newton(a, a, prec); if (!arb_overlaps(a, la)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(ab); arb_clear(lab); arb_clear(la); arb_clear(lb); arb_clear(lalb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log_primes_vec_bsplit.c000066400000000000000000000033631461254215100221310ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_log_primes_vec_bsplit, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr v; arb_t t; slong n, j, prec; ulong p, pprev; prec = 2 + n_randint(state, 700); n = n_randint(state, 30); flint_set_num_threads(1 + n_randint(state, 3)); v = _arb_vec_init(n); arb_init(t); arb_log_primes_vec_bsplit(v, n, prec); pprev = 1; for (j = 0; j < n; j++) { p = n_nextprime(pprev, 1); if (p == 2) arb_const_log2(t, prec); else arb_log_ui_from_prev(t, p, t, pprev, prec); pprev = p; if (!arb_overlaps(v + j, t) || arb_rel_accuracy_bits(v + j) < prec - 5) { flint_printf("FAIL\n\n"); flint_printf("n = %wu, j = %wd\n", n, j); flint_printf("v = "); arb_printd(v + j, 100); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 100); flint_printf("\n\n"); flint_printf("%wd, %wd\n", prec, arb_rel_accuracy_bits(v + j)); flint_abort(); } } _arb_vec_clear(v, n); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log_tab.c000066400000000000000000000152651461254215100171720ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_log_tab, state) { slong i; mpfr_t tabx, logx, y1, y2; mpz_t tt; { slong prec, bits, num; prec = ARB_LOG_TAB1_LIMBS * FLINT_BITS; bits = ARB_LOG_TAB11_BITS; num = 1 << ARB_LOG_TAB11_BITS; mpfr_init2(tabx, prec); mpfr_init2(logx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_log_tab11[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(logx, i, MPFR_RNDD); mpfr_div_2ui(logx, logx, bits, MPFR_RNDD); mpfr_add_ui(logx, logx, 1, MPFR_RNDD); mpfr_log(logx, logx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(logx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_LOG_TAB1_LIMBS * FLINT_BITS; bits = ARB_LOG_TAB11_BITS + ARB_LOG_TAB12_BITS; num = 1 << ARB_LOG_TAB12_BITS; mpfr_init2(tabx, prec); mpfr_init2(logx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_log_tab12[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(logx, i, MPFR_RNDD); mpfr_div_2ui(logx, logx, bits, MPFR_RNDD); mpfr_add_ui(logx, logx, 1, MPFR_RNDD); mpfr_log(logx, logx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(logx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_LOG_TAB2_LIMBS * FLINT_BITS; bits = ARB_LOG_TAB21_BITS; num = 1 << ARB_LOG_TAB21_BITS; mpfr_init2(tabx, prec); mpfr_init2(logx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_log_tab21[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(logx, i, MPFR_RNDD); mpfr_div_2ui(logx, logx, bits, MPFR_RNDD); mpfr_add_ui(logx, logx, 1, MPFR_RNDD); mpfr_log(logx, logx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(logx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_LOG_TAB2_LIMBS * FLINT_BITS; bits = ARB_LOG_TAB21_BITS + ARB_LOG_TAB22_BITS; num = 1 << ARB_LOG_TAB22_BITS; mpfr_init2(tabx, prec); mpfr_init2(logx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_log_tab22[i]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(logx, i, MPFR_RNDD); mpfr_div_2ui(logx, logx, bits, MPFR_RNDD); mpfr_add_ui(logx, logx, 1, MPFR_RNDD); mpfr_log(logx, logx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } mpfr_clear(tabx); mpfr_clear(logx); mpfr_clear(y1); mpfr_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-log_ui_from_prev.c000066400000000000000000000035551461254215100211170ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_log_ui_from_prev, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t z1, z2, z3; ulong n1, n2; slong prec, accuracy; prec = 2 + n_randint(state, 3000); n1 = n_randint(state, 100000); n2 = n1 + 1 + n_randint(state, 1000); arb_init(z1); arb_init(z2); arb_init(z3); arb_log_ui(z1, n1, prec); arb_log_ui(z2, n2, prec); arb_log_ui_from_prev(z3, n2, z1, n1, prec); if (!arb_overlaps(z2, z3)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd, n1 = %wu, n2 = %wu\n\n", prec, n1, n2); flint_printf("z1 = "); arb_printd(z1, prec / 3.33); flint_printf("\n\n"); flint_printf("z2 = "); arb_printd(z2, prec / 3.33); flint_printf("\n\n"); flint_printf("z3 = "); arb_printd(z3, prec / 3.33); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(z3); if (accuracy < prec - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec); flint_printf("n1 = %wu, n2 = %wu\n\n", n1, n2); flint_printf("z3 = "); arb_printd(z3, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(z1); arb_clear(z2); arb_clear(z3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-max.c000066400000000000000000000107061461254215100163430ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #define ASSERT(cond) if (!(cond)) { flint_printf("FAIL: %d\n", __LINE__); flint_abort(); } #ifndef _sample_arf_in_arb #define _sample_arf_in_arb _sample_arf_in_arb /* sample (x, y) so that x /in y */ void _sample_arf_in_arb(arf_t x, arb_t y, flint_rand_t state) { slong bits, prec, expbits; arf_t a, b; slong i, n; arf_init(a); arf_init(b); bits = 2 + n_randint(state, 1000); prec = 2 + n_randint(state, 1000); expbits = n_randint(state, 14); n = n_randint(state, 3); arf_randtest(x, state, bits, expbits); arf_set(a, x); arf_set(b, x); for (i = 0; i < n; i++) { arf_randtest(x, state, bits, expbits); arf_min(a, a, x); arf_max(b, b, x); } arb_set_interval_arf(y, a, b, prec); arf_clear(a); arf_clear(b); } #endif TEST_FUNCTION_START(arb_max, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t a, b, c; arb_t x, y, z; slong prec; arf_init(a); arf_init(b); arf_init(c); arb_init(x); arb_init(y); arb_init(z); _sample_arf_in_arb(a, x, state); _sample_arf_in_arb(b, y, state); prec = 2 + n_randint(state, 200); arf_max(c, a, b); arb_max(z, x, y, prec); if (!arb_contains_arf(x, a) || !arb_contains_arf(y, b) || !arb_contains_arf(z, c)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } /* aliasing */ { int alias; if (n_randint(state, 2)) { arb_max(x, x, y, prec); alias = arb_equal(x, z); } else { arb_max(y, x, y, prec); alias = arb_equal(y, z); } if (!alias) { flint_printf("FAIL: aliasing\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } } arf_clear(a); arf_clear(b); arf_clear(c); arb_clear(x); arb_clear(y); arb_clear(z); } /* test special cases with non-finite input */ { slong prec; arb_t zero, special, z; prec = 64; arb_init(zero); arb_init(special); arb_init(z); /* -Inf +/- Inf */ mag_inf(arb_radref(special)); arf_neg_inf(arb_midref(special)); arb_max(z, zero, special, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_max(z, special, zero, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); /* Inf +/- Inf */ mag_inf(arb_radref(special)); arf_pos_inf(arb_midref(special)); arb_max(z, zero, special, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_max(z, special, zero, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); /* NaN +/- 1*/ mag_one(arb_radref(special)); arf_nan(arb_midref(special)); arb_max(z, zero, special, prec); ASSERT(arf_is_nan(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_max(z, special, zero, prec); ASSERT(arf_is_nan(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_clear(zero); arb_clear(special); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-min.c000066400000000000000000000107061461254215100163410ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #define ASSERT(cond) if (!(cond)) { flint_printf("FAIL: %d\n", __LINE__); flint_abort(); } #ifndef _sample_arf_in_arb #define _sample_arf_in_arb _sample_arf_in_arb /* sample (x, y) so that x /in y */ void _sample_arf_in_arb(arf_t x, arb_t y, flint_rand_t state) { slong bits, prec, expbits; arf_t a, b; slong i, n; arf_init(a); arf_init(b); bits = 2 + n_randint(state, 1000); prec = 2 + n_randint(state, 1000); expbits = n_randint(state, 14); n = n_randint(state, 3); arf_randtest(x, state, bits, expbits); arf_set(a, x); arf_set(b, x); for (i = 0; i < n; i++) { arf_randtest(x, state, bits, expbits); arf_min(a, a, x); arf_max(b, b, x); } arb_set_interval_arf(y, a, b, prec); arf_clear(a); arf_clear(b); } #endif TEST_FUNCTION_START(arb_min, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t a, b, c; arb_t x, y, z; slong prec; arf_init(a); arf_init(b); arf_init(c); arb_init(x); arb_init(y); arb_init(z); _sample_arf_in_arb(a, x, state); _sample_arf_in_arb(b, y, state); prec = 2 + n_randint(state, 200); arf_min(c, a, b); arb_min(z, x, y, prec); if (!arb_contains_arf(x, a) || !arb_contains_arf(y, b) || !arb_contains_arf(z, c)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } /* aliasing */ { int alias; if (n_randint(state, 2)) { arb_min(x, x, y, prec); alias = arb_equal(x, z); } else { arb_min(y, x, y, prec); alias = arb_equal(y, z); } if (!alias) { flint_printf("FAIL: aliasing\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } } arf_clear(a); arf_clear(b); arf_clear(c); arb_clear(x); arb_clear(y); arb_clear(z); } /* test special cases with non-finite input */ { slong prec; arb_t zero, special, z; prec = 64; arb_init(zero); arb_init(special); arb_init(z); /* -Inf +/- Inf */ mag_inf(arb_radref(special)); arf_neg_inf(arb_midref(special)); arb_min(z, zero, special, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_min(z, special, zero, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); /* Inf +/- Inf */ mag_inf(arb_radref(special)); arf_pos_inf(arb_midref(special)); arb_min(z, zero, special, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_min(z, special, zero, prec); ASSERT(arf_is_zero(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); /* NaN +/- 1*/ mag_one(arb_radref(special)); arf_nan(arb_midref(special)); arb_min(z, zero, special, prec); ASSERT(arf_is_nan(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_min(z, special, zero, prec); ASSERT(arf_is_nan(arb_midref(z))); ASSERT(mag_is_inf(arb_radref(z))); arb_clear(zero); arb_clear(special); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-minmax.c000066400000000000000000000047231461254215100170510ustar00rootroot00000000000000/* Copyright (C) 2023 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_minmax, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z1, z2, w1, w2; slong prec; arb_init(x); arb_init(y); arb_init(z1); arb_init(z2); arb_init(w1); arb_init(w2); prec = 2 + n_randint(state, 200); arb_randtest_special(x, state, 1 + n_randint(state, 200), 10); arb_randtest_special(y, state, 1 + n_randint(state, 200), 10); arb_min(w1, x, y, prec); arb_max(w2, x, y, prec); arb_minmax(z1, z2, x, y, prec); if (!arb_equal(w1, z1) || !arb_equal(w2, z2)) { flint_printf("FAIL: same as min and max\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z1 = "); arb_print(z1); flint_printf("\n\n"); flint_printf("z2 = "); arb_print(z2); flint_printf("\n\n"); flint_printf("w1 = "); arb_print(w1); flint_printf("\n\n"); flint_printf("w2 = "); arb_print(w2); flint_printf("\n\n"); flint_abort(); } /* aliasing */ { int alias; if (n_randint(state, 2)) { arb_minmax(x, y, x, y, prec); alias = arb_equal(x, z1) && arb_equal(y, z2); } else { arb_minmax(y, x, x, y, prec); alias = arb_equal(y, z1) && arb_equal(x, z2); } if (!alias) { flint_printf("FAIL: aliasing\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z1 = "); arb_print(z1); flint_printf("\n\n"); flint_printf("z2 = "); arb_print(z2); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(y); arb_clear(z1); arb_clear(z2); arb_clear(w1); arb_clear(w2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-mul.c000066400000000000000000000254031461254215100163530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" #ifndef mag_close #define mag_close mag_close int mag_close(const mag_t am, const mag_t bm) { arf_t t, a, b; int res1, res2; arf_init(t); arf_init(a); arf_init(b); arf_set_mag(a, am); arf_set_mag(b, bm); arf_mul_ui(t, b, 257, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(t, t, -8); res1 = arf_cmp(a, t) <= 0; arf_mul_ui(t, a, 257, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(t, t, -8); res2 = arf_cmp(b, t) <= 0; arf_clear(t); arf_clear(a); arf_clear(b); return res1 && res2; } #endif #ifndef arb_equal_mid_close_mag #define arb_equal_mid_close_mag arb_equal_mid_close_mag int arb_equal_mid_close_mag(const arb_t a, const arb_t b) { return arf_equal(arb_midref(a), arb_midref(b)) && (mag_close(arb_radref(a), arb_radref(b)) || /* If a's and b's centres are infinite but their radii are finite, the radii don't need to be close: they represent signed infinity regardless. If their centres are NaN, then we should ignore their radii. */ (arf_is_inf(arb_midref(a)) && arf_is_inf(arb_midref(b)) && mag_is_finite(arb_radref(a)) && mag_is_finite(arb_radref(b))) || (arf_is_nan(arb_midref(a)) && arf_is_nan(arb_midref(b)))); } #endif void arb_mul_naive(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t zm_exact, zm_rounded, zr, t, u; arf_init(zm_exact); arf_init(zm_rounded); arf_init(zr); arf_init(t); arf_init(u); arf_mul(zm_exact, arb_midref(x), arb_midref(y), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_round(zm_rounded, zm_exact, prec, ARB_RND); /* rounding error */ if (arf_equal(zm_exact, zm_rounded)) { arf_zero(zr); } else { fmpz_t e; fmpz_init(e); /* more accurate, but not what we are testing arf_sub(zr, zm_exact, zm_rounded, MAG_BITS, ARF_RND_UP); arf_abs(zr, zr); */ fmpz_sub_ui(e, ARF_EXPREF(zm_rounded), prec); arf_one(zr); arf_mul_2exp_fmpz(zr, zr, e); fmpz_clear(e); } /* propagated error - note that (signed infinity) * nonzero should be a signed infinity, meaning the error should *not* propagate */ if (!arb_is_exact(x) && !( arb_is_nonzero(x) && arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)))) { arf_set_mag(t, arb_radref(x)); arf_abs(u, arb_midref(y)); arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP); } if (!arb_is_exact(y) && !( arb_is_nonzero(y) && arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)))) { arf_set_mag(t, arb_radref(y)); arf_abs(u, arb_midref(x)); arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP); } if (!arb_is_exact(x) && !arb_is_exact(y)) { arf_set_mag(t, arb_radref(x)); arf_set_mag(u, arb_radref(y)); arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP); } arf_set(arb_midref(z), zm_rounded); arf_get_mag(arb_radref(z), zr); arf_clear(zm_exact); arf_clear(zm_rounded); arf_clear(zr); arf_clear(t); arf_clear(u); } TEST_FUNCTION_START(arb_mul, state) { slong iter, iter2; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t x, y, z; arb_init(a); arb_init(b); arb_init(c); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_mul(c, a, b, 2 + n_randint(state, 200)); fmpq_mul(z, x, y); if (!arb_contains_fmpq(c, z)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_mul(a, a, b, 2 + n_randint(state, 200)); fmpq_mul(z, x, y); if (!arb_contains_fmpq(a, z)) { flint_printf("FAIL: aliasing (c, a)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and b */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_mul(b, a, b, 2 + n_randint(state, 200)); fmpq_mul(z, x, y); if (!arb_contains_fmpq(b, z)) { flint_printf("FAIL: aliasing (c, b)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* main test */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z, v; slong prec; arb_init(x); arb_init(y); arb_init(z); arb_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arb_randtest_special(x, state, n_randint(state,2) ? 2000 : 200, 200); arb_randtest_special(y, state, n_randint(state,2) ? 2000 : 200, 200); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 5)) { case 0: arb_mul(z, x, y, prec); arb_mul_naive(v, x, y, prec); if (!arb_equal_mid_close_mag(z, v)) { flint_printf("FAIL!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 1: arb_set(y, x); arb_mul(z, x, y, prec); arb_mul(v, x, x, prec); if (!arb_equal_mid_close_mag(z, v)) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 2: arb_mul(v, x, x, prec); arb_mul(x, x, x, prec); if (!arb_equal(v, x)) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 3: arb_mul(v, x, y, prec); arb_mul(x, x, y, prec); if (!arb_equal(v, x)) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; default: arb_mul(v, x, y, prec); arb_mul(x, y, x, prec); if (!arf_equal(arb_midref(x), arb_midref(v)) || !mag_close(arb_radref(x), arb_radref(v))) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; } } arb_clear(x); arb_clear(y); arb_clear(z); arb_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-mul_arf.c000066400000000000000000000054171461254215100172060ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_mul_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_mul_arf(c, a, x, prec); arb_mul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arf_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_mul_arf(c, a, x, prec); arb_mul_arf(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-mul_fmpz.c000066400000000000000000000054031461254215100174050ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_mul_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_mul_fmpz(c, a, x, prec); arb_mul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_mul_fmpz(c, a, x, prec); arb_mul_fmpz(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-mul_more.c000066400000000000000000000103751461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_mul_more, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t x, y, z; arb_init(a); arb_init(b); arb_init(c); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_mul(c, a, b, 2 + n_randint(state, 200)); fmpq_mul(z, x, y); if (!arb_contains_fmpq(c, z)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_mul(a, a, b, 2 + n_randint(state, 200)); fmpq_mul(z, x, y); if (!arb_contains_fmpq(a, z)) { flint_printf("FAIL: aliasing (c, a)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and b */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_mul(b, a, b, 2 + n_randint(state, 200)); fmpq_mul(z, x, y); if (!arb_contains_fmpq(b, z)) { flint_printf("FAIL: aliasing (c, b)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-mul_si.c000066400000000000000000000051701461254215100170450ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "long_extras.h" TEST_FUNCTION_START(arb_mul_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_mul_si(c, a, x, prec); arb_mul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_mul_si(c, a, x, prec); arb_mul_si(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-mul_ui.c000066400000000000000000000051711461254215100170500ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "ulong_extras.h" TEST_FUNCTION_START(arb_mul_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_mul_ui(c, a, x, prec); arb_mul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_mul_ui(c, a, x, prec); arb_mul_ui(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-nonnegative_abs.c000066400000000000000000000117541461254215100207240ustar00rootroot00000000000000/* Copyright (C) 2022 Erik Postma This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #define ASSERT(cond) if (!(cond)) { flint_printf("FAIL: %d\n", __LINE__); flint_abort(); } void naive_nonnegative_abs(arb_t y, const arb_t x) { if(y == x) { /* We don't want to worry about aliasing */ arb_t z; arb_init(z); naive_nonnegative_abs(z, x); arb_swap(y, z); arb_clear(z); return; } if(! arb_is_finite(x)) { if(arf_cmp_si(arb_midref(x), 0) < 0) { /* Negative infinity, or "whole real line" represented with a negative centre. We can't represent the correct half interval we would like to return for the latter case; in order to match arb_abs and arb_nonnegative_abs, we flip the sign for the centre in both cases. */ arb_neg(y, x); } else { /* Positive infinity, whole real line represented with a negative centre, or NaN. */ arb_set(y, x); } return; } if(arf_cmp_si(arb_midref(x), 0) > 0) { if(arf_cmpabs_mag(arb_midref(x), arb_radref(x)) < 0) { arf_set_mag(arb_midref(y), arb_radref(x)); arf_add(arb_midref(y), arb_midref(y), arb_midref(x), MAG_BITS+10, ARF_RND_UP); arf_mul_2exp_si(arb_midref(y), arb_midref(y), -1); arf_get_mag(arb_radref(y), arb_midref(y)); arf_set_mag(arb_midref(y), arb_radref(y)); } else { arb_set(y, x); } } else if(arf_cmp_si(arb_midref(x), 0) < 0) { if(arf_cmpabs_mag(arb_midref(x), arb_radref(x)) < 0) { arf_set_mag(arb_midref(y), arb_radref(x)); arf_sub(arb_midref(y), arb_midref(y), arb_midref(x), MAG_BITS+10, ARF_RND_UP); arf_mul_2exp_si(arb_midref(y), arb_midref(y), -1); arf_get_mag(arb_radref(y), arb_midref(y)); arf_set_mag(arb_midref(y), arb_radref(y)); } else { arb_neg(y, x); } } else { ASSERT(arf_equal_si(arb_midref(x), 0)); mag_mul_2exp_si(arb_radref(y), arb_radref(x), -1); arf_set_mag(arb_midref(y), arb_radref(y)); } } /* Let u equal 1 ulp of y's radius. Are x's centre and radius within u of y's centre and radius, respectively? */ int nearly_equal(const arb_t x, const arb_t y) { arf_t s, t; mag_t ulp; int res; arf_init(t); arf_init(s); mag_init(ulp); arf_set_mag(t, arb_radref(y)); if(mag_is_special(arb_radref(y))) { mag_zero(ulp); } else { arf_mag_set_ulp(ulp, t, MAG_BITS); } arf_set_mag(s, arb_radref(x)); arf_sub(t, t, s, MAG_BITS, ARF_RND_UP); res = mag_equal(arb_radref(x), arb_radref(y)) || (arf_cmpabs_mag(t, ulp) <= 0); arf_sub(t, arb_midref(x), arb_midref(y), MAG_BITS+2, ARF_RND_UP); res = res && (arf_equal(arb_midref(x), arb_midref(y)) || (arf_cmpabs_mag(t, ulp) <= 0)); mag_clear(ulp); arf_clear(s); arf_clear(t); return res; } TEST_FUNCTION_START(arb_nonnegative_abs, state) { slong iter, wide; for (wide = 0; wide < 2; wide++) { for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arb_init(a); arb_init(b); arb_init(c); if(wide) { arb_randtest_wide(a, state, 1 + n_randint(state, 2000), 100); } else { arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); } arb_nonnegative_abs(b, a); naive_nonnegative_abs(c, a); if(! nearly_equal(b, c)) { flint_printf("FAIL: nonnegative_abs\n\n"); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 100); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 100); flint_printf("\n\n"); flint_abort(); } arb_set(b, a); arb_nonnegative_abs(b, b); if(! nearly_equal(b, c)) { flint_printf("FAIL: aliasing (nonnegative_abs)\n\n"); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 100); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 100); flint_printf("\n\n"); flint_abort(); } arb_clear(c); arb_clear(b); arb_clear(a); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-overlaps.c000066400000000000000000000043521461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_overlaps, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t am, ar, bm, br, t, u; int c1, c2; arb_init(a); arb_init(b); fmpq_init(am); fmpq_init(ar); fmpq_init(bm); fmpq_init(br); fmpq_init(t); fmpq_init(u); arb_randtest(a, state, 1 + n_randint(state, 500), 14); arb_randtest(b, state, 1 + n_randint(state, 500), 14); arf_get_fmpq(am, arb_midref(a)); mag_get_fmpq(ar, arb_radref(a)); arf_get_fmpq(bm, arb_midref(b)); mag_get_fmpq(br, arb_radref(b)); fmpq_sub(t, am, bm); fmpz_abs(fmpq_numref(t), fmpq_numref(t)); fmpq_add(u, ar, br); c1 = arb_overlaps(a, b); c2 = (fmpq_cmp(t, u) <= 0); if (c1 != c2) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("am = "); fmpq_print(am); flint_printf("\n\n"); flint_printf("ar = "); fmpq_print(ar); flint_printf("\n\n"); flint_printf("bm = "); fmpq_print(bm); flint_printf("\n\n"); flint_printf("br = "); fmpq_print(br); flint_printf("\n\n"); flint_printf("t = "); fmpq_print(t); flint_printf("\n\n"); flint_printf("u = "); fmpq_print(u); flint_printf("\n\n"); flint_printf("c1 = %d, c2 = %d\n\n", c1, c2); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(am); fmpq_clear(ar); fmpq_clear(bm); fmpq_clear(br); fmpq_clear(t); fmpq_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-partitions_fmpz.c000066400000000000000000000041331461254215100210030ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_partitions_fmpz, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_t b1, b2; fmpz_t n; slong prec1, prec2, acc1, acc2; fmpz_init(n); arb_init(b1); arb_init(b2); if (iter % 100 == 0) fmpz_randtest(n, state, 1 + n_randint(state, 1000)); else fmpz_randtest(n, state, 1 + n_randint(state, 20)); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); arb_partitions_fmpz(b1, n, prec1); arb_partitions_fmpz(b2, n, prec2); if (!arb_overlaps(b1, b2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("b1 = "); arb_printn(b1, 50, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, 50, 0); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(b1); acc2 = arb_rel_accuracy_bits(b2); if (acc1 < prec1 - 4 || acc2 < prec2 - 4) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd\n", prec1, acc1); flint_printf("prec2 = %wd, acc2 = %wd\n", prec2, acc2); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("b1 = "); arb_printn(b1, 50, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(b1); arb_clear(b2); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-pos_times_posinf.c000066400000000000000000000321061461254215100211340ustar00rootroot00000000000000#include #include "test_helpers.h" #include "arb.h" #define PRINT_PRECISION 20 typedef enum { ALL_POSITIVE = 0, CONTAINS_ZERO = 1, ALL_NEGATIVE = 2, ANY_FINITE = 3, /* used only to represent either of the previous three */ POSITIVE_INFINITY = 4, NEGATIVE_INFINITY = 5, WHOLE_LINE = 6, ANY_INFINITE = 7, /* used only to represent either of the previous three */ NOT_A_NUMBER = 8, NUM_VALUE_TYPES = 9 /* used only to count the number of enum values */ } value_type; typedef struct { const char *value; value_type type; } string_with_type; const string_with_type test_values_arb[] = { {"5.3 +/- 1.2", ALL_POSITIVE}, {"1.2 +/- 5.3", CONTAINS_ZERO}, {"-1.2 +/- 5.3", CONTAINS_ZERO}, {"-5.3 +/- 1.2", ALL_NEGATIVE}, {"inf +/- 17", POSITIVE_INFINITY}, {"-inf +/- 17", NEGATIVE_INFINITY}, {"17 +/- inf", WHOLE_LINE}, {"-inf +/- inf", WHOLE_LINE}, {"nan +/- 17", NOT_A_NUMBER}, {"nan +/- inf", NOT_A_NUMBER}, {NULL, NOT_A_NUMBER}, }; const string_with_type test_values_arf[] = { {"5.3", ALL_POSITIVE}, {"0", CONTAINS_ZERO}, {"-5.3", ALL_NEGATIVE}, {"inf", POSITIVE_INFINITY}, {"-inf", NEGATIVE_INFINITY}, {"nan", NOT_A_NUMBER}, {NULL, NOT_A_NUMBER}, }; /* Multiplying value_type i with value_type j should yield value_type multiplication[i][j]. */ const value_type multiplication[NUM_VALUE_TYPES][NUM_VALUE_TYPES] = { {ALL_POSITIVE, CONTAINS_ZERO, ALL_NEGATIVE, ANY_FINITE, POSITIVE_INFINITY,NEGATIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {CONTAINS_ZERO, CONTAINS_ZERO, CONTAINS_ZERO, ANY_FINITE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {ALL_NEGATIVE, CONTAINS_ZERO, ALL_POSITIVE, ANY_FINITE, NEGATIVE_INFINITY,POSITIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {ANY_FINITE, ANY_FINITE, ANY_FINITE, ANY_FINITE, ANY_INFINITE, ANY_INFINITE, WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {POSITIVE_INFINITY,WHOLE_LINE, NEGATIVE_INFINITY,ANY_INFINITE, POSITIVE_INFINITY,NEGATIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {NEGATIVE_INFINITY,WHOLE_LINE, POSITIVE_INFINITY,ANY_INFINITE, NEGATIVE_INFINITY,POSITIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, NOT_A_NUMBER}, {ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER}, }; /* Adding value_type i to value_type j should yield value_type addition[i][j]. */ const value_type addition[NUM_VALUE_TYPES][NUM_VALUE_TYPES] = { {ALL_POSITIVE, ANY_FINITE, ANY_FINITE, ANY_FINITE, POSITIVE_INFINITY,NEGATIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {ANY_FINITE, CONTAINS_ZERO, ANY_FINITE, ANY_FINITE, POSITIVE_INFINITY,NEGATIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {ANY_FINITE, ANY_FINITE, ALL_NEGATIVE, ANY_FINITE, POSITIVE_INFINITY,NEGATIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {ANY_FINITE, ANY_FINITE, ANY_FINITE, ANY_FINITE, POSITIVE_INFINITY,NEGATIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {POSITIVE_INFINITY,POSITIVE_INFINITY,POSITIVE_INFINITY,POSITIVE_INFINITY,POSITIVE_INFINITY,WHOLE_LINE, WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {NEGATIVE_INFINITY,NEGATIVE_INFINITY,NEGATIVE_INFINITY,NEGATIVE_INFINITY,WHOLE_LINE, NEGATIVE_INFINITY,WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, WHOLE_LINE, NOT_A_NUMBER}, {ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, ANY_INFINITE, WHOLE_LINE, ANY_INFINITE, NOT_A_NUMBER}, {NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER, NOT_A_NUMBER}, }; int arb_satisfies_value_type(const arb_t x, const value_type t) { switch(t) { case ALL_POSITIVE: return arb_is_finite(x) && arb_is_positive(x); case CONTAINS_ZERO: return arb_is_finite(x) && arb_contains_zero(x); case ALL_NEGATIVE: return arb_is_finite(x) && arb_is_negative(x); case ANY_FINITE: return arb_is_finite(x); case POSITIVE_INFINITY: return !arb_is_finite(x) && arb_is_positive(x); case NEGATIVE_INFINITY: return !arb_is_finite(x) && arb_is_negative(x); case WHOLE_LINE: return !arb_is_finite(x) && arb_contains_zero(x); case ANY_INFINITE: return !arb_is_finite(x) && !arf_is_nan(arb_midref(x)); case NOT_A_NUMBER: return arf_is_nan(arb_midref(x)); default: printf("unexpected condition\n"); flint_abort(); } } void print_arb_and_type(arb_t x, const char *s, const value_type t) { flint_printf("%s: ", s); arb_printd(x, PRINT_PRECISION); flint_printf(" of type: %d\n", t); } void print_arf_and_type(arf_t x, const char *s, const value_type t) { flint_printf("%s: ", s); arf_printd(x, PRINT_PRECISION); flint_printf(" of type: %d\n", t); } TEST_FUNCTION_START(arb_pos_times_posinf, state) { slong i, j, k, prec; arb_t t, u, v, w; arf_t x; arb_init(t); arb_init(u); arb_init(v); arb_init(w); arf_init(x); for(prec = 20; prec <= 100; prec += 80) for(i = 0; test_values_arb[i].value != NULL; ++i) { for(j = 0; test_values_arb[j].value != NULL; ++j) { value_type vt = test_values_arb[i].type, vu = test_values_arb[j].type, expected = multiplication[vt][vu]; arb_set_str(t, test_values_arb[i].value, prec); arb_set_str(u, test_values_arb[j].value, prec); arb_mul(v, t, u, prec); if(!arb_satisfies_value_type(v, expected)) { flint_printf("FAIL (arb_mul): %s, %s\n", test_values_arb[i].value, test_values_arb[j].value); print_arb_and_type(t, "t", vt); print_arb_and_type(u, "u", vu); flint_printf("v: "); arb_printd(v, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", expected); flint_abort(); } for(k = 0; test_values_arb[k].value != NULL; ++k) { value_type vw = test_values_arb[k].type, expected = addition[vw][multiplication[vt][vu]]; arb_set_str(w, test_values_arb[k].value, prec); arb_addmul(w, t, u, prec); if(!arb_satisfies_value_type(w, expected)) { flint_printf("FAIL (arb_addmul): %s, %s, %s\n", test_values_arb[k].value, test_values_arb[i].value, test_values_arb[j].value); print_arb_and_type(t, "t", vt); print_arb_and_type(u, "u", vu); flint_printf("w (after): "); arb_printd(w, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", expected); flint_abort(); } expected = addition[vw][multiplication[ALL_NEGATIVE][multiplication[vt][vu]]]; arb_set_str(w, test_values_arb[k].value, prec); arb_submul(w, t, u, prec); if(!arb_satisfies_value_type(w, expected)) { flint_printf("FAIL (arb_submul): %s, %s, %s\n", test_values_arb[k].value, test_values_arb[i].value, test_values_arb[j].value); print_arb_and_type(t, "t", vt); print_arb_and_type(u, "u", vu); flint_printf("w (after): "); arb_printd(w, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", expected); flint_abort(); } expected = addition[vw][multiplication[vt][vu]]; arb_set_str(w, test_values_arb[k].value, prec); arb_fma(v, t, u, w, prec); if(!arb_satisfies_value_type(v, expected)) { flint_printf("FAIL (arb_fma): %s, %s, %s\n", test_values_arb[k].value, test_values_arb[i].value, test_values_arb[j].value); print_arb_and_type(t, "t", vt); print_arb_and_type(u, "u", vu); flint_printf("v (after): "); arb_printd(v, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", expected); flint_abort(); } } } for(j = 0; test_values_arf[j].value != NULL; ++j) { value_type vt = test_values_arb[i].type, vx = test_values_arf[j].type; arb_set_str(t, test_values_arb[i].value, prec); arb_set_str(w, test_values_arf[j].value, prec); arf_set(x, arb_midref(w)); arb_mul_arf(v, t, x, prec); if(!arb_satisfies_value_type(v, multiplication[vt][vx])) { flint_printf("FAIL (arb_mul_arf): %s, %s\n", test_values_arb[i].value, test_values_arf[j].value); print_arb_and_type(t, "t", vt); print_arf_and_type(x, "x", vx); flint_printf("v: "); arb_printd(v, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", multiplication[vt][vx]); flint_abort(); } for(k = 0; test_values_arb[k].value != NULL; ++k) { value_type vw = test_values_arb[k].type, expected = addition[vw][multiplication[vt][vx]]; arb_set_str(w, test_values_arb[k].value, prec); arb_addmul_arf(w, t, x, prec); if(!arb_satisfies_value_type(w, expected)) { flint_printf("FAIL (arb_addmul_arf): %s, %s, %s\n", test_values_arb[k].value, test_values_arb[i].value, test_values_arf[j].value); print_arb_and_type(t, "t", vt); print_arf_and_type(x, "x", vx); flint_printf("w (after): "); arb_printd(w, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", expected); flint_abort(); } expected = addition[vw][multiplication[ALL_NEGATIVE][multiplication[vt][vx]]]; arb_set_str(w, test_values_arb[k].value, prec); arb_submul_arf(w, t, x, prec); if(!arb_satisfies_value_type(w, expected)) { flint_printf("FAIL (arb_submul_arf): %s, %s, %s\n", test_values_arb[k].value, test_values_arb[i].value, test_values_arf[j].value); print_arb_and_type(t, "t", vt); print_arf_and_type(x, "x", vx); flint_printf("w (after): "); arb_printd(w, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", expected); flint_abort(); } expected = addition[vw][multiplication[vt][vx]]; arb_set_str(w, test_values_arb[k].value, prec); arb_fma_arf(v, t, x, w, prec); if(!arb_satisfies_value_type(v, expected)) { flint_printf("FAIL (arb_fma): %s, %s, %s\n", test_values_arb[k].value, test_values_arb[i].value, test_values_arf[j].value); print_arb_and_type(t, "t", vt); print_arf_and_type(x, "x", vx); flint_printf("v (after): "); arb_printd(v, PRINT_PRECISION); flint_printf("\nexpected type: %d\n", expected); flint_abort(); } } } } arf_clear(x); arb_clear(w); arb_clear(v); arb_clear(u); arb_clear(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-pow.c000066400000000000000000000132641461254215100163650ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "double_extras.h" TEST_FUNCTION_START(arb_pow, state) { slong iter; /* check large arguments */ for (iter = 0; iter < 20000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d, e, f; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_init(e); arb_init(f); arb_randtest(a, state, 1 + n_randint(state, 1000), 200); arb_randtest(b, state, 1 + n_randint(state, 1000), 200); arb_pow(c, a, b, prec1); arb_pow(d, a, b, prec2); if (!arb_overlaps(c, d)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_randtest(c, state, 1 + n_randint(state, 1000), 200); /* check a^(b+c) = a^b*a^c */ arb_add(e, b, c, prec1); arb_pow(d, a, e, prec1); arb_pow(e, a, b, prec1); arb_pow(f, a, c, prec1); arb_mul(e, e, f, prec1); if (!arb_overlaps(d, e)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("e = "); arb_print(e); flint_printf("\n\n"); flint_abort(); } arb_pow(c, a, b, prec1); arb_set(d, a); arb_pow(d, d, b, prec2); if (!arb_overlaps(c, d)) { flint_printf("FAIL: aliasing 1\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_set(d, b); arb_pow(d, a, d, prec2); if (!arb_overlaps(c, d)) { flint_printf("FAIL: aliasing 2\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arb_clear(e); arb_clear(f); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ulong n, prec; double epsilon, delta; arb_t a, b, c, d; arb_init(a); arb_init(b); arb_init(c); arb_init(d); prec = 2 + n_randint(state, 100); mag_randtest(arb_radref(a), state, 1 + n_randint(state, 1000)); arf_set_mag(arb_midref(a), arb_radref(a)); n = 1 + n_randint(state, 100); epsilon = d_randtest(state) / 16; /* 1/32 <= epsilon < 1/16 */ if (n_randint(state, 2)) epsilon = -epsilon; delta = d_randtest(state) / 4; /* 1/8 <= delta < 1/4 */ arf_set_d(arb_midref(b), n + epsilon); mag_set_d(arb_radref(b), delta); arb_pow(c, a, b, prec); arb_pow_ui(d, a, n, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: interval from zero\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("n = %d\n\n", n); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_set(c, a); arb_pow(c, c, b, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: interval from zero; alias 1\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("n = %d\n\n", n); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_set(c, b); arb_pow(c, a, c, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: interval from zero; alias 2\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("n = %d\n\n", n); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(d); arb_clear(c); arb_clear(b); arb_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-pow_fmpq.c000066400000000000000000000050431461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_pow_fmpq, state) { slong iter; /* check large arguments */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpq_t e1, e2, e3; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpq_init(e1); fmpq_init(e2); fmpq_init(e3); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 200); arb_randtest_precise(b, state, 1 + n_randint(state, 1000), 200); fmpq_randtest(e1, state, 200); fmpq_randtest(e2, state, 200); arb_pow_fmpq(b, a, e1, prec1); arb_pow_fmpq(c, a, e1, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("e1 = "); fmpq_print(e1); flint_printf("\n\n"); flint_abort(); } /* check a^(e1+e2) = a^e1*a^e2 */ arb_pow_fmpq(c, a, e2, prec1); arb_mul(d, b, c, prec1); fmpq_add(e3, e1, e2); arb_pow_fmpq(c, a, e3, prec1); if (!arb_overlaps(c, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("e1 = "); fmpq_print(e1); flint_printf("\n\n"); flint_printf("e2 = "); fmpq_print(e2); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpq_clear(e1); fmpq_clear(e2); fmpq_clear(e3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-pow_fmpz.c000066400000000000000000000050211461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_pow_fmpz, state) { slong iter; /* check large arguments */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t e1, e2, e3; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(e1); fmpz_init(e2); fmpz_init(e3); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 200); arb_randtest_precise(b, state, 1 + n_randint(state, 1000), 200); fmpz_randtest(e1, state, 200); fmpz_randtest(e2, state, 200); arb_pow_fmpz(b, a, e1, prec1); arb_pow_fmpz(c, a, e1, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("e1 = "); fmpz_print(e1); flint_printf("\n\n"); flint_abort(); } /* check a^(e1+e2) = a^e1*a^e2 */ arb_pow_fmpz(c, a, e2, prec1); arb_mul(d, b, c, prec1); fmpz_add(e3, e1, e2); arb_pow_fmpz(c, a, e3, prec1); if (!arb_overlaps(c, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("e1 = "); fmpz_print(e1); flint_printf("\n\n"); flint_printf("e2 = "); fmpz_print(e2); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(e1); fmpz_clear(e2); fmpz_clear(e3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-power_sum_vec.c000066400000000000000000000035171461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_power_sum_vec, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, s, t; arb_ptr res; slong aa, bb, k, n, len; slong prec; len = n_randint(state, 30); prec = 2 + n_randint(state, 500); aa = n_randint(state, 50) - 50; bb = aa + n_randint(state, 50); arb_init(a); arb_init(b); arb_init(s); arb_init(t); res = _arb_vec_init(len); arb_set_si(a, aa); arb_set_si(b, bb); arb_power_sum_vec(res, a, b, len, prec); for (n = 0; n < len; n++) { arb_zero(s); for (k = aa; k < bb; k++) { arb_set_si(t, k); arb_pow_ui(t, t, n, prec); arb_add(s, s, t, prec); } if (!arb_overlaps(res + n, s)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = %wd, b = %wd, n = %wd\n\n", aa, bb, n); flint_printf("res = "); arb_printd(res + n, 30); flint_printf("\n\n"); flint_printf("s = "); arb_printd(s, 30); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); arb_clear(s); arb_clear(t); _arb_vec_clear(res, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-primorial.c000066400000000000000000000036131461254215100175530ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_primorial, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { ulong n, m; fmpz_t y; arb_t x; slong prec; arb_init(x); fmpz_init(y); if (n_randint(state, 10) == 0) n = n_randint(state, 5000); else n = n_randint(state, 500); prec = 2 + n_randint(state, 500); arb_primorial_ui(x, n, prec); fmpz_primorial(y, n); if (!arb_contains_fmpz(x, y)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n", n); flint_printf("x = "); arb_printd(x, 100); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_abort(); } m = n_randint(state, 500); if (m == 0) n = 0; else n = n_nth_prime(m); prec = 2 + n_randint(state, 500); arb_primorial_nth_ui(x, m, prec); fmpz_primorial(y, n); if (!arb_contains_fmpz(x, y)) { flint_printf("FAIL: containment (2)\n\n"); flint_printf("m = %wu\n", m); flint_printf("x = "); arb_printd(x, 100); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_abort(); } arb_clear(x); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-rgamma.c000066400000000000000000000034611461254215100170220ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_rgamma, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_randtest_precise(a, state, 1 + n_randint(state, 1000), 3); arb_rgamma(b, a, prec1); arb_rgamma(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check 1/gamma(z+1) = 1/gamma(z)/z */ arb_div(b, b, a, prec1); arb_add_ui(c, a, 1, prec1); arb_rgamma(c, c, prec1); if (!arb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-richcmp.c000066400000000000000000000071121461254215100172000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" static void arb_supremum(arf_t res, const arb_t x) { if (arf_is_nan(arb_midref(x))) { arf_nan(res); } else if (mag_is_inf(arb_radref(x))) { arf_pos_inf(res); } else { arf_set_mag(res, arb_radref(x)); arf_add(res, res, arb_midref(x), ARF_PREC_EXACT, ARF_RND_CEIL); } } static void arb_infimum(arf_t res, const arb_t x) { if (arf_is_nan(arb_midref(x))) { arf_nan(res); } else if (mag_is_inf(arb_radref(x))) { arf_neg_inf(res); } else { arf_set_mag(res, arb_radref(x)); arf_sub(res, arb_midref(x), res, ARF_PREC_EXACT, ARF_RND_FLOOR); } } int arb_richcmp(const arb_t x, const arb_t y, int op) { switch (op) { case 0: return arb_eq(x, y); case 1: return arb_ne(x, y); case 2: return arb_le(x, y); case 3: return arb_lt(x, y); case 4: return arb_ge(x, y); default: return arb_gt(x, y); } } int arb_richcmp_fallback(const arb_t x, const arb_t y, int op) { arf_t xa, xb, ya, yb; int res; arf_init(xa); arf_init(xb); arf_init(ya); arf_init(yb); arb_infimum(xa, x); arb_supremum(xb, x); arb_infimum(ya, y); arb_supremum(yb, y); if (arf_is_nan(xa) || arf_is_nan(ya)) { res = 0; } else { if (op == 0) /* eq */ { res = arf_equal(xa, xb) && arf_equal(ya, yb) && arf_equal(xa, ya); } else if (op == 1) /* ne */ { res = (arf_cmp(yb, xa) < 0) || (arf_cmp(xb, ya) < 0); } else if (op == 2) /* le */ { res = (arf_cmp(xb, ya) <= 0); } else if (op == 3) /* lt */ { res = (arf_cmp(xb, ya) < 0); } else if (op == 4) /* ge */ { res = (arf_cmp(xa, yb) >= 0); } else /* gt */ { res = (arf_cmp(xa, yb) > 0); } } arf_clear(xa); arf_clear(xb); arf_clear(ya); arf_clear(yb); return res; } TEST_FUNCTION_START(arb_richcmp, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; int op, res1, res2; arb_init(a); arb_init(b); arb_randtest_special(a, state, 1 + n_randint(state, 100), 5); arb_randtest_special(b, state, 1 + n_randint(state, 100), 5); op = n_randint(state, 6); res1 = arb_richcmp(a, b, op); res2 = arb_richcmp_fallback(a, b, op); if (res1 != res2) { flint_printf("FAIL:\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 30); flint_printf("\n\n"); flint_printf("op = %d\n\n", op); flint_printf("res1 (cmp) = %d\n\n", res1); flint_printf("res2 (fallback) = %d\n\n", res2); flint_abort(); } arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-rising2_ui.c000066400000000000000000000062161461254215100176310ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "arith.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_rising2_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, u, v, u2, v2; fmpz *f; arb_ptr g; ulong n; slong i, prec; arb_init(a); arb_init(u); arb_init(v); arb_init(u2); arb_init(v2); arb_randtest(a, state, 1 + n_randint(state, 4000), 10); arb_randtest(u, state, 1 + n_randint(state, 4000), 10); arb_randtest(v, state, 1 + n_randint(state, 4000), 10); n = n_randint(state, 120); f = _fmpz_vec_init(n + 1); g = _arb_vec_init(n + 1); prec = 2 + n_randint(state, 4000); arb_rising2_ui(u, v, a, n, prec); arith_stirling_number_1u_vec(f, n, n + 1); for (i = 0; i <= n; i++) arb_set_fmpz(g + i, f + i); _arb_poly_evaluate(u2, g, n + 1, a, prec); _arb_poly_derivative(g, g, n + 1, prec); _arb_poly_evaluate(v2, g, n, a, prec); if (!arb_overlaps(u, u2) || !arb_overlaps(v, v2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n", n); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("u = "); arb_printd(u, 15); flint_printf("\n\n"); flint_printf("u2 = "); arb_printd(u2, 15); flint_printf("\n\n"); flint_printf("v = "); arb_printd(v, 15); flint_printf("\n\n"); flint_printf("v2 = "); arb_printd(v2, 15); flint_printf("\n\n"); flint_abort(); } arb_set(u2, a); arb_rising2_ui(u2, v, u2, n, prec); if (!arb_equal(u2, u)) { flint_printf("FAIL: aliasing 1\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("u = "); arb_printd(u, 15); flint_printf("\n\n"); flint_printf("u2 = "); arb_printd(u2, 15); flint_printf("\n\n"); flint_printf("n = %wu\n", n); flint_abort(); } arb_set(v2, a); arb_rising2_ui(u, v2, v2, n, prec); if (!arb_equal(v2, v)) { flint_printf("FAIL: aliasing 2\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("v = "); arb_printd(v, 15); flint_printf("\n\n"); flint_printf("v2 = "); arb_printd(v2, 15); flint_printf("\n\n"); flint_printf("n = %wu\n", n); flint_abort(); } arb_clear(a); arb_clear(u); arb_clear(v); arb_clear(u2); arb_clear(v2); _fmpz_vec_clear(f, n + 1); _arb_vec_clear(g, n + 1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-rising_ui.c000066400000000000000000000052451461254215100175500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_rising_ui, state) { slong iter; /* compare with fmpq */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; ulong n; slong i; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 1000), 10); arb_randtest(b, state, 1 + n_randint(state, 1000), 10); n = n_randint(state, 80); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 10)); arb_rising_ui(b, a, n, 2 + n_randint(state, 1000)); fmpq_one(y); for (i = 0; i < n; i++) { fmpq_set_si(z, i, 1); fmpq_add(z, x, z); fmpq_mul(y, y, z); } if (!arb_contains_fmpq(b, y)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n", n); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of y and x */ for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y; ulong n; slong prec; arb_init(x); arb_init(y); arb_randtest(x, state, 1 + n_randint(state, 200), 10); arb_randtest(y, state, 1 + n_randint(state, 200), 10); n = n_randint(state, 100); prec = 2 + n_randint(state, 1000); arb_rising_ui(y, x, n, prec); arb_rising_ui(x, x, n, prec); if (!arb_equal(x, y)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("n = %wu\n", n); flint_abort(); } arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-root_ui.c000066400000000000000000000032121461254215100172300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_root_ui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong k; slong prec; prec = 2 + n_randint(state, 2000); k = n_randtest_not_zero(state); arb_init(a); arb_init(b); arb_init(c); arb_randtest(a, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); arb_randtest(b, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); arb_root_ui(b, a, k, prec); arb_pow_ui(c, b, k, prec); if (!arb_contains(c, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("k = %wu\n", k); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_root_ui(a, a, k, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-rsqrt.c000066400000000000000000000026671461254215100167400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_rsqrt, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_rsqrt(b, a, prec); arb_inv(c, b, prec); arb_mul(c, c, c, prec); if (!arb_contains(c, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_rsqrt(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sec.c000066400000000000000000000032531461254215100163270ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sec, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 300), 100); arb_randtest_special(a, state, 1 + n_randint(state, 300), 100); arb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { arb_sec(a, x, prec1); } else { arb_set(a, x); arb_sec(a, a, prec1); } arb_cos(b, x, prec2); arb_inv(b, b, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sech.c000066400000000000000000000032571461254215100165030ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sech, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a, b; slong prec1, prec2; prec1 = 2 + n_randint(state, 200); prec2 = prec1 + 30; arb_init(x); arb_init(a); arb_init(b); arb_randtest_special(x, state, 1 + n_randint(state, 300), 100); arb_randtest_special(a, state, 1 + n_randint(state, 300), 100); arb_randtest_special(b, state, 1 + n_randint(state, 300), 100); if (n_randint(state, 2)) { arb_sech(a, x, prec1); } else { arb_set(a, x); arb_sech(a, a, prec1); } arb_cosh(b, x, prec2); arb_inv(b, b, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printn(x, 20, 0); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 20, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 20, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-set_interval_arf.c000066400000000000000000000026511461254215100211050ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_set_interval_arf, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; arf_t a, b; arb_init(x); arf_init(a); arf_init(b); arf_randtest_special(a, state, 200, 10); arf_randtest_special(b, state, 200, 10); if (arf_cmp(a, b) > 0) arf_swap(a, b); arb_set_interval_arf(x, a, b, 2 + n_randint(state, 200)); if ((!arb_contains_arf(x, a) || !arb_contains_arf(x, b)) || (!arf_is_nan(a) && !arf_is_nan(b) && arf_is_nan(arb_midref(x)))) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arf_clear(a); arf_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-set_interval_mag.c000066400000000000000000000030331461254215100210740ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_set_interval_mag, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; mag_t u, v; arf_t a, b; arb_init(x); mag_init(u); mag_init(v); arf_init(a); arf_init(b); mag_randtest_special(u, state, 1 + n_randint(state, 100)); mag_randtest_special(v, state, 1 + n_randint(state, 100)); if (mag_cmp(u, v) > 0) mag_swap(u, v); arf_set_mag(a, u); arf_set_mag(b, v); arb_set_interval_mag(x, u, v, 2 + n_randint(state, 200)); if (!arb_contains_arf(x, a) || !arb_contains_arf(x, b)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arf_clear(a); arf_clear(b); mag_clear(u); mag_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-set_interval_mpfr.c000066400000000000000000000031001461254215100212670ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_set_interval_mpfr, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; arf_t a, b; mpfr_t aa, bb; arb_init(x); arf_init(a); arf_init(b); mpfr_init2(aa, 200); mpfr_init2(bb, 200); arf_randtest_special(a, state, 200, 10); arf_randtest_special(b, state, 200, 10); if (arf_cmp(a, b) > 0) arf_swap(a, b); arf_get_mpfr(aa, a, MPFR_RNDD); arf_get_mpfr(bb, b, MPFR_RNDU); arb_set_interval_mpfr(x, aa, bb, 2 + n_randint(state, 200)); if (!arb_contains_arf(x, a) || !arb_contains_arf(x, b)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arf_clear(a); arf_clear(b); mpfr_clear(aa); mpfr_clear(bb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-set_interval_neg_pos_mag.c000066400000000000000000000030071461254215100226070ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_set_interval_neg_pos_mag, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x; mag_t u, v; arf_t a, b; arb_init(x); mag_init(u); mag_init(v); arf_init(a); arf_init(b); mag_randtest_special(u, state, 1 + n_randint(state, 100)); mag_randtest_special(v, state, 1 + n_randint(state, 100)); arf_set_mag(a, u); arf_neg(a, a); arf_set_mag(b, v); arb_set_interval_neg_pos_mag(x, u, v, 2 + n_randint(state, 200)); if (!arb_contains_arf(x, a) || !arb_contains_arf(x, b)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arf_clear(a); arf_clear(b); mag_clear(u); mag_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-set_str.c000066400000000000000000000137551461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include #include "arb.h" const char * testdata_floats[] = { "0", /* repeated to test empty string later */ "0", "0.0", "0.", ".0", "+0", "+0.0", "+0.", " +.0 ", "-0", "-0.0", "-0.", "-.0", " 0e3", "0.0e3", "0.e3", " .0e3", "+0e3", "+0.0e3", "+0.e3", "+.0e3", "-0e3", "-0.0e3", "-0.e3", "-.0e3", "0e+3", "0.0e+3", "0.e+3", " .0e+3", "+0e+3", "+0.0e+3", "+0.e+3", "+.0e+3", "-0E+3", "-0.0E+3 ", "-0.e+3", "-.0e+3", "0e-3", "0.0e-3", "0.e-3", ".0E-3", "+0e-3", "+0.0e-3", "+0.E-3", "+.0e-3", "-0e-3", "-0.0e-3", "-0.e-3", "-.0e-3", "03.125", "+03.125", "-03.125", "03.12500", "+03.12500", "-03.12500", "03.125e+3", "+03.125e+3", " -03.125e+3 ", "03.12500e+3", "+03.12500e+3", "-03.12500e+3", "03.125e3", "+03.125E3", "-03.125e3", "03.12500e3", "+03.12500E3", "-03.12500E3", "25000.0e-2", "-25000.0e-2", " 25000.0000000000000000000e-2", "-25000.0000000000000000000e-2", " 000025000.0000000000000000000e-2 ", "-000025000.0000000000000000000e-2", "25000.e-2", "-25000.e-2", "12345.125", "-12345.125", "+12345.125", "inf", "-inf", "+inf", "Inf", "-INF", "+Inf", "NAN", "-NaN", "+NAN", NULL, }; const char * testdata_invalid[] = { "", ".", "+.", "-.", ".e+3", "-.e+5", "+.e-5", "2+3", "12 34", "150a.25", "-e+4", "10.25x", "10.3.5", "125e3.6", "125e-3.6", "3.14 e+5", "3.140 e3", "3.14+e5", "3.14e+ 5", " 3.14e- 5", "3.14e+-5", "3.14e+/-5", ".0.", "..", ":)", " +/- ", " 0 0", " +/- EEE ", "-3.5e+x5 +/-", "4.7 +/- -3.5e+x5", "4.7 +/-", NULL, }; TEST_FUNCTION_START(arb_set_str, state) { arb_t t, u, v; double x; int error, bracket; char tmp[256]; slong i, j; arb_init(t); arb_init(u); arb_init(v); for (i = 0; testdata_floats[i] != NULL; i++) { arb_const_pi(t, 53); error = arb_set_str(t, testdata_floats[i], 53); x = strtod(testdata_floats[i], NULL); if (x != x) { arb_indeterminate(u); } else { arf_set_d(arb_midref(u), x); mag_zero(arb_radref(u)); } if (error != 0 || !arb_equal(t, u)) { flint_printf("FAIL (valid input): %s\n", testdata_floats[i]); arb_printd(t, 15); flint_printf("\n"); arb_printd(u, 15); flint_printf("\n"); flint_abort(); } } for (i = 0; testdata_floats[i] != NULL; i++) { for (j = 0; testdata_floats[j] != NULL; j++) { for (bracket = 0; bracket < 2; bracket++) { arb_const_pi(t, 53); bracket = n_randint(state, 2); strcpy(tmp, ""); if (bracket) strcat(tmp, "["); /* allow empty string for midpoint */ strcat(tmp, (i == 0) ? "" : testdata_floats[i]); strcat(tmp, "+/-"); strcat(tmp, testdata_floats[j]); if (bracket) strcat(tmp, "]"); error = arb_set_str(t, tmp, 53); x = strtod((i == 0) ? "0" : testdata_floats[i], NULL); if (x != x) { arb_indeterminate(u); } else { arf_set_d(arb_midref(u), x); mag_zero(arb_radref(u)); } x = strtod(testdata_floats[j], NULL); arf_set_d(arb_midref(v), x); mag_zero(arb_radref(v)); arb_abs(v, v); arb_add_error(u, v); if (error != 0 || !arb_equal(t, u)) { flint_printf("FAIL (valid input): %s\n", tmp); arb_printd(t, 15); flint_printf("\n"); arb_printd(u, 15); flint_printf("\n"); flint_abort(); } } } } for (i = 0; testdata_invalid[i] != NULL; i++) { arb_const_pi(t, 53); error = arb_set_str(t, testdata_invalid[i], 53); if (error == 0) { flint_printf("FAIL (invalid input): %s\n", testdata_invalid[i]); arb_printd(t, 15); flint_printf("\n"); flint_abort(); } } for (i = 0; testdata_invalid[i] != NULL; i++) { for (j = 0; testdata_invalid[j] != NULL; j++) { for (bracket = 0; bracket < 2; bracket++) { arb_const_pi(t, 53); bracket = n_randint(state, 2); strcpy(tmp, ""); if (bracket) strcat(tmp, "["); strcat(tmp, testdata_invalid[i]); strcat(tmp, "+/-"); strcat(tmp, testdata_invalid[j]); if (bracket) strcat(tmp, "]"); error = arb_set_str(t, tmp, 53); if (error == 0) { flint_printf("FAIL (invalid input): %s\n", tmp); arb_printd(t, 15); flint_printf("\n"); flint_abort(); } } } } arb_clear(t); arb_clear(u); arb_clear(v); TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sgn.c000066400000000000000000000026271461254215100163500ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sgn, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; int result; arb_init(a); arb_init(b); arb_randtest_special(a, state, 1 + n_randint(state, 200), 10); arb_randtest_special(b, state, 1 + n_randint(state, 200), 10); arb_sgn(b, a); result = 1; if (arb_contains_zero(a)) result = result & arb_contains_si(b, 0); if (arb_contains_positive(a)) result = result & arb_contains_si(b, 1); if (arb_contains_negative(a)) result = result & arb_contains_si(b, -1); if (!result) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin.c000066400000000000000000000067561461254215100163610ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sin, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec0, prec; prec0 = 400; if (iter % 100 == 0) prec0 = 8000; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec0 + 100); arb_randtest(a, state, 1 + n_randint(state, prec0), 6); arb_randtest(b, state, 1 + n_randint(state, prec0), 6); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, prec0)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_sin(t, t, MPFR_RNDN); arb_sin(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_sin(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* check large arguments */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec0, prec1, prec2; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, prec0), prec0); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(d, state, 1 + n_randint(state, prec0), 100); arb_sin(b, a, prec1); arb_sin(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* check sin(2a) = 2sin(a)cos(a) */ arb_mul_2exp_si(c, a, 1); arb_sin(c, c, prec1); arb_cos(d, a, prec1); arb_mul(b, b, d, prec1); arb_mul_2exp_si(b, b, 1); if (!arb_overlaps(b, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos.c000066400000000000000000000136111461254215100172110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_cos, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t q; mpfr_t t, u; slong prec0, prec; prec0 = 400; if (iter % 100 == 0) prec0 = 8000; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); fmpq_init(q); mpfr_init2(t, prec + 200); mpfr_init2(u, prec + 200); arb_randtest(a, state, 1 + n_randint(state, prec0), 6); arb_randtest(b, state, 1 + n_randint(state, prec0), 6); arb_randtest(c, state, 1 + n_randint(state, prec0), 6); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, prec0)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_sin_cos(t, u, t, MPFR_RNDN); arb_sin_cos(b, c, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment (sin)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } if (!arb_contains_mpfr(c, u)) { flint_printf("FAIL: containment (cos)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(q); mpfr_clear(t); mpfr_clear(u); } /* check large arguments */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d, e; slong prec0, prec1, prec2, prec3; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); if (iter % 10 == 0) prec3 = 50000; else prec3 = 100; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_init(e); arb_randtest_special(a, state, 1 + n_randint(state, prec0), prec3); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(d, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(e, state, 1 + n_randint(state, prec0), 100); arb_sin_cos(b, c, a, prec1); arb_sin_cos(d, e, a, prec2); if (!arb_overlaps(b, d) || !arb_overlaps(c, e)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("e = "); arb_print(e); flint_printf("\n\n"); flint_abort(); } /* check sin(a)^2 + cos(a)^2 = 1 */ arb_mul(d, b, b, prec1); arb_mul(e, c, c, prec1); arb_add(d, d, e, prec1); arb_sub_ui(d, d, 1, prec1); if (!arb_contains_zero(d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arb_clear(e); } /* check accuracy */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, s, c; slong prec0, prec; mag_t allow; if (iter % 10 == 0) prec0 = 10000; else prec0 = 400; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(s); arb_init(c); mag_init(allow); arb_randtest_special(a, state, 1 + n_randint(state, prec0), 12); arb_randtest_special(s, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); if (n_randint(state, 2)) { arb_sin_cos(s, c, a, prec); } else { arb_sin_cos(s, NULL, a, prec); arb_sin_cos(NULL, c, a, prec); } if (!arb_is_finite(a)) { mag_inf(allow); } else { mag_set_ui_2exp_si(allow, 1, -prec + 1); mag_max(allow, allow, arb_radref(a)); mag_mul_2exp_si(allow, allow, 1); } if (mag_cmp(arb_radref(s), allow) > 0 || mag_cmp(arb_radref(c), allow) > 0) { flint_printf("FAIL: accuracy\n\n"); flint_printf("a = "); arb_printn(a, 3000, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 3000, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 3000, 0); flint_printf("\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("allow = "); mag_printd(allow, 5); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(s); arb_clear(c); mag_clear(allow); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_arf_bb.c000066400000000000000000000127261461254215100205120ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" void arb_sin_cos_fmpz_div_2exp_bsplit(arb_t wsin, arb_t wcos, const fmpz_t x, flint_bitcnt_t r, slong prec); TEST_FUNCTION_START(arb_sin_cos_arf_bb, state) { slong iter; /* test the series evaluation code directly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t x; slong r; arb_t t, s1, s2, c1, c2; slong prec1, prec2; fmpz_init(x); arb_init(t); arb_init(s1); arb_init(s2); arb_init(c1); arb_init(c2); if (n_randint(state, 100) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); prec1 = 10 + n_randint(state, 2000); prec2 = 10 + n_randint(state, 2000); r = n_randint(state, prec2); r = FLINT_MAX(r, 4); fmpz_randtest(x, state, r - 3); arb_set_fmpz(t, x); arb_mul_2exp_si(t, t, -r); arb_sin_cos(s1, c1, t, prec1); arb_sin_cos_fmpz_div_2exp_bsplit(s2, c2, x, r, prec2); if (!arb_overlaps(s1, s2) || !arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_printf("t = "); arb_printn(t, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_printf("c1 = "); arb_printn(c1, 500, 0); flint_printf("\n\n"); flint_printf("c2 = "); arb_printn(c2, 500, 0); flint_printf("\n\n"); flint_abort(); } fmpz_clear(x); arb_clear(t); arb_clear(s1); arb_clear(s2); arb_clear(c1); arb_clear(c2); } /* test the bb algorithm */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, s1, s2, c1, c2; slong prec = 2 + n_randint(state, 4000); arb_init(x); arb_init(s1); arb_init(s2); arb_init(c1); arb_init(c2); if (n_randint(state, 100) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); arb_randtest(x, state, 1 + n_randint(state, 4000), 0); mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_mul_2exp_si(x, x, -n_randint(state, 2 * prec)); while (arf_cmpabs_d(arb_midref(x), 3.141) > 0) arb_mul_2exp_si(x, x, -1); arb_sin_cos(s1, c1, x, prec); switch (n_randint(state, 6)) { case 0: arb_sin_cos_arf_bb(s2, c2, arb_midref(x), prec); break; case 1: arb_sin_cos_arf_bb(s2, NULL, arb_midref(x), prec); arb_sin_cos_arf_bb(NULL, c2, arb_midref(x), prec); break; case 2: arb_set(s2, x); arb_sin_cos_arf_bb(NULL, c2, arb_midref(s2), prec); arb_sin_cos_arf_bb(s2, NULL, arb_midref(s2), prec); break; case 3: arb_set(c2, x); arb_sin_cos_arf_bb(s2, NULL, arb_midref(c2), prec); arb_sin_cos_arf_bb(NULL, c2, arb_midref(c2), prec); break; case 4: arb_set(c2, x); arb_sin_cos_arf_bb(s2, c2, arb_midref(c2), prec); break; default: arb_set(s2, x); arb_sin_cos_arf_bb(s2, c2, arb_midref(s2), prec); break; } if (!arb_overlaps(s1, s2) || !arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_printf("c1 = "); arb_printn(c1, 500, 0); flint_printf("\n\n"); flint_printf("c2 = "); arb_printn(c2, 500, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(s2) < prec - 2 || arb_rel_accuracy_bits(c2) < prec - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd, acc1 = %wd, acc2 = %wd\n\n", prec, arb_rel_accuracy_bits(s2), arb_rel_accuracy_bits(c2)); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_printf("c1 = "); arb_printn(c1, 500, 0); flint_printf("\n\n"); flint_printf("c2 = "); arb_printn(c2, 500, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(s1); arb_clear(s2); arb_clear(c1); arb_clear(c2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_arf_generic.c000066400000000000000000000206121461254215100215340ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" /* these functions are not exposed to the public for now, but it still makes sense to test them explicitly */ void arb_sin_cos_arf_rs_generic(arb_t res_sin, arb_t res_cos, const arf_t x, slong prec); void arb_sin_cos_taylor_sum_rs(arb_t s, const arb_t x, slong N, int cosine, slong prec); TEST_FUNCTION_START(arb_sin_cos_arf_generic, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, s1, s2, c1, c2; slong prec = 2 + n_randint(state, 2000); arb_init(x); arb_init(s1); arb_init(s2); arb_init(c1); arb_init(c2); if (n_randint(state, 2)) arb_randtest(x, state, 1 + n_randint(state, 2000), 15); else arb_randtest(x, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 10000)); mag_zero(arb_radref(x)); arb_sin_cos(s1, c1, x, prec); switch (n_randint(state, 6)) { case 0: arb_sin_cos_arf_generic(s2, c2, arb_midref(x), prec); break; case 1: arb_sin_cos_arf_generic(s2, NULL, arb_midref(x), prec); arb_sin_cos_arf_generic(NULL, c2, arb_midref(x), prec); break; case 2: arb_set(s2, x); arb_sin_cos_arf_generic(NULL, c2, arb_midref(s2), prec); arb_sin_cos_arf_generic(s2, NULL, arb_midref(s2), prec); break; case 3: arb_set(c2, x); arb_sin_cos_arf_generic(s2, NULL, arb_midref(c2), prec); arb_sin_cos_arf_generic(NULL, c2, arb_midref(c2), prec); break; case 4: arb_set(c2, x); arb_sin_cos_arf_generic(s2, c2, arb_midref(c2), prec); break; default: arb_set(s2, x); arb_sin_cos_arf_generic(s2, c2, arb_midref(s2), prec); break; } if (!arb_overlaps(s1, s2) || !arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_printf("c1 = "); arb_printn(c1, 500, 0); flint_printf("\n\n"); flint_printf("c2 = "); arb_printn(c2, 500, 0); flint_printf("\n\n"); flint_abort(); } if (arf_cmpabs_ui(arb_midref(x), 1) <= 0 && (arb_rel_accuracy_bits(s2) < prec - 2 || arb_rel_accuracy_bits(c2) < prec - 2)) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd, acc1 = %wd, acc2 = %wd\n\n", prec, arb_rel_accuracy_bits(s2), arb_rel_accuracy_bits(c2)); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_printf("c1 = "); arb_printn(c1, 500, 0); flint_printf("\n\n"); flint_printf("c2 = "); arb_printn(c2, 500, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(s1); arb_clear(s2); arb_clear(c1); arb_clear(c2); } /* test the rs algorithm explicitly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, s1, s2, c1, c2; slong prec = 2 + n_randint(state, 2000); arb_init(x); arb_init(s1); arb_init(s2); arb_init(c1); arb_init(c2); arb_randtest(x, state, 1 + n_randint(state, 2000), 0); mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_mul_2exp_si(x, x, -n_randint(state, 2 * prec)); while (arf_cmpabs_d(arb_midref(x), 3.141) > 0) arb_mul_2exp_si(x, x, -1); arb_sin_cos(s1, c1, x, prec); switch (n_randint(state, 6)) { case 0: arb_sin_cos_arf_rs_generic(s2, c2, arb_midref(x), prec); break; case 1: arb_sin_cos_arf_rs_generic(s2, NULL, arb_midref(x), prec); arb_sin_cos_arf_rs_generic(NULL, c2, arb_midref(x), prec); break; case 2: arb_set(s2, x); arb_sin_cos_arf_rs_generic(NULL, c2, arb_midref(s2), prec); arb_sin_cos_arf_rs_generic(s2, NULL, arb_midref(s2), prec); break; case 3: arb_set(c2, x); arb_sin_cos_arf_rs_generic(s2, NULL, arb_midref(c2), prec); arb_sin_cos_arf_rs_generic(NULL, c2, arb_midref(c2), prec); break; case 4: arb_set(c2, x); arb_sin_cos_arf_rs_generic(s2, c2, arb_midref(c2), prec); break; default: arb_set(s2, x); arb_sin_cos_arf_rs_generic(s2, c2, arb_midref(s2), prec); break; } if (!arb_overlaps(s1, s2) || !arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_printf("c1 = "); arb_printn(c1, 500, 0); flint_printf("\n\n"); flint_printf("c2 = "); arb_printn(c2, 500, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(s2) < prec - 2 || arb_rel_accuracy_bits(c2) < prec - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd, acc1 = %wd, acc2 = %wd\n\n", prec, arb_rel_accuracy_bits(s2), arb_rel_accuracy_bits(c2)); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 500, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 500, 0); flint_printf("\n\n"); flint_printf("c1 = "); arb_printn(c1, 500, 0); flint_printf("\n\n"); flint_printf("c2 = "); arb_printn(c2, 500, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(s1); arb_clear(s2); arb_clear(c1); arb_clear(c2); } /* test the series evaluation code directly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; slong prec; slong N; int cosine; arb_init(x); arb_init(y); arb_init(z); prec = 2 + n_randint(state, 2000); N = n_randint(state, 100); cosine = n_randint(state, 2); arb_randtest(x, state, 1 + n_randint(state, 2000), 1); mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_mul_2exp_si(x, x, -n_randint(state, 2 * prec)); if (cosine) { arb_cos(y, x, prec); arb_sin_cos_taylor_sum_rs(z, x, N, 1, prec); } else { arb_sin(y, x, prec); arb_sin_cos_taylor_sum_rs(z, x, N, 0, prec); } if (!arb_overlaps(z, y)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd, N = %wd, cosine = %d\n\n", prec, N, cosine); flint_printf("x = "); arb_printn(x, 500, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 500, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 500, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_generic.c000066400000000000000000000136751461254215100207170ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_cos_generic, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t q; mpfr_t t, u; slong prec0, prec; prec0 = 400; if (iter % 100 == 0) prec0 = 8000; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); fmpq_init(q); mpfr_init2(t, prec + 200); mpfr_init2(u, prec + 200); arb_randtest(a, state, 1 + n_randint(state, prec0), 6); arb_randtest(b, state, 1 + n_randint(state, prec0), 6); arb_randtest(c, state, 1 + n_randint(state, prec0), 6); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, prec0)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_sin_cos(t, u, t, MPFR_RNDN); arb_sin_cos_generic(b, c, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment (sin)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } if (!arb_contains_mpfr(c, u)) { flint_printf("FAIL: containment (cos)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(q); mpfr_clear(t); mpfr_clear(u); } /* check large arguments */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d, e; slong prec0, prec1, prec2, prec3; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); if (iter % 10 == 0) prec3 = 50000; else prec3 = 100; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_init(e); arb_randtest_special(a, state, 1 + n_randint(state, prec0), prec3); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(d, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(e, state, 1 + n_randint(state, prec0), 100); arb_sin_cos_generic(b, c, a, prec1); arb_sin_cos_generic(d, e, a, prec2); if (!arb_overlaps(b, d) || !arb_overlaps(c, e)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("e = "); arb_print(e); flint_printf("\n\n"); flint_abort(); } /* check sin(a)^2 + cos(a)^2 = 1 */ arb_mul(d, b, b, prec1); arb_mul(e, c, c, prec1); arb_add(d, d, e, prec1); arb_sub_ui(d, d, 1, prec1); if (!arb_contains_zero(d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arb_clear(e); } /* check accuracy */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, s, c; slong prec0, prec; mag_t allow; if (iter % 10 == 0) prec0 = 10000; else prec0 = 400; prec = 2 + n_randint(state, prec0); arb_init(a); arb_init(s); arb_init(c); mag_init(allow); arb_randtest_special(a, state, 1 + n_randint(state, prec0), 12); arb_randtest_special(s, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); if (n_randint(state, 2)) { arb_sin_cos_generic(s, c, a, prec); } else { arb_sin_cos_generic(s, NULL, a, prec); arb_sin_cos_generic(NULL, c, a, prec); } if (!arb_is_finite(a)) { mag_inf(allow); } else { mag_set_ui_2exp_si(allow, 1, -prec + 1); mag_max(allow, allow, arb_radref(a)); mag_mul_2exp_si(allow, allow, 1); } if (mag_cmp(arb_radref(s), allow) > 0 || mag_cmp(arb_radref(c), allow) > 0) { flint_printf("FAIL: accuracy\n\n"); flint_printf("a = "); arb_printn(a, 500, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 500, 0); flint_printf("\n\n"); flint_printf("c = "); arb_printn(c, 500, 0); flint_printf("\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("allow = "); mag_printd(allow, 5); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(s); arb_clear(c); mag_clear(allow); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_pi.c000066400000000000000000000035071461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_cos_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d, e; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_init(e); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_randtest(d, state, 1 + n_randint(state, 200), 10); arb_randtest(e, state, 1 + n_randint(state, 200), 10); arb_const_pi(b, prec); arb_mul(b, b, a, prec); arb_sin_cos(b, d, b, prec); arb_sin_cos_pi(c, e, a, prec); if (!arb_overlaps(b, c) || !arb_overlaps(d, e)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_printf("e = "); arb_print(e); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arb_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_pi_fmpq.c000066400000000000000000000033731461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_cos_pi_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s1, c1, s2, c2; fmpq_t x; slong prec; prec = 2 + n_randint(state, 5000); arb_init(s1); arb_init(c1); arb_init(s2); arb_init(c2); fmpq_init(x); fmpq_randtest(x, state, 1 + n_randint(state, 200)); arb_sin_cos_pi_fmpq(s1, c1, x, prec); arb_const_pi(s2, prec); arb_mul_fmpz(s2, s2, fmpq_numref(x), prec); arb_div_fmpz(s2, s2, fmpq_denref(x), prec); arb_sin_cos(s2, c2, s2, prec); if (!arb_overlaps(s1, s2) || !arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("s1 = "); arb_printd(s1, 15); flint_printf("\n\n"); flint_printf("c1 = "); arb_printd(c1, 15); flint_printf("\n\n"); flint_printf("s2 = "); arb_printd(s2, 15); flint_printf("\n\n"); flint_printf("c2 = "); arb_printd(c2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(c1); arb_clear(s2); arb_clear(c2); fmpq_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_pi_fmpq_algebraic.c000066400000000000000000000055321461254215100227200ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_cos_pi_fmpq_algebraic, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s1, s2, c1, c2; ulong p, q, g; slong prec; prec = 2 + n_randint(state, 5000); q = 1 + n_randint(state, 500); p = n_randint(state, q / 2 + 1); g = n_gcd(q, p); q /= g; p /= g; arb_init(s1); arb_init(s2); arb_init(c1); arb_init(c2); _arb_sin_cos_pi_fmpq_algebraic(s1, c1, p, q, prec); arb_const_pi(s2, prec); arb_mul_ui(s2, s2, p, prec); arb_div_ui(s2, s2, q, prec); arb_sin_cos(s2, c2, s2, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("s1 = "); arb_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); arb_printd(s2, 15); flint_printf("\n\n"); flint_abort(); } if (!arb_overlaps(c1, c2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("c1 = "); arb_printd(c1, 15); flint_printf("\n\n"); flint_printf("c2 = "); arb_printd(c2, 15); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(s1) < prec - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("prec=%wd eff=%wd\n", prec, arb_rel_accuracy_bits(s1)); flint_printf("s1 = "); arb_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); arb_printd(s2, 15); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(c1) < prec - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("prec=%wd eff=%wd\n", prec, arb_rel_accuracy_bits(c1)); flint_printf("c1 = "); arb_printd(c1, 15); flint_printf("\n\n"); flint_printf("c2 = "); arb_printd(c2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(c1); arb_clear(c2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_tab.c000066400000000000000000000155011461254215100200370ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_sin_cos_tab, state) { slong i, which; mpfr_t tabx, sinx, y1, y2; mpz_t tt; { slong prec, bits, num; prec = ARB_SIN_COS_TAB1_LIMBS * FLINT_BITS; bits = ARB_SIN_COS_TAB1_BITS; num = ARB_SIN_COS_TAB1_NUM; mpfr_init2(tabx, prec); mpfr_init2(sinx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (which = 0; which < 2; which++) { for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_sin_cos_tab1[2 * i + which]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(sinx, i, MPFR_RNDD); mpfr_div_2ui(sinx, sinx, bits, MPFR_RNDD); if (which) mpfr_cos(sinx, sinx, MPFR_RNDD); else mpfr_sin(sinx, sinx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, sinx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (which && i == 0) /* special case */ { mpfr_set_ui(y2, 1, MPFR_RNDD); mpfr_mul_2ui(y2, y2, prec, MPFR_RNDD); mpfr_sub_ui(y2, y2, 1, MPFR_RNDD); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); } if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: which = %wd, i = %wd, bits = %wd, prec = %wd\n", which, i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } } mpfr_clear(tabx); mpfr_clear(sinx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_SIN_COS_TAB2_LIMBS * FLINT_BITS; bits = ARB_SIN_COS_TAB21_BITS; num = ARB_SIN_COS_TAB21_NUM; mpfr_init2(tabx, prec); mpfr_init2(sinx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (which = 0; which < 2; which++) { for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_sin_cos_tab21[2 * i + which]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(sinx, i, MPFR_RNDD); mpfr_div_2ui(sinx, sinx, bits, MPFR_RNDD); if (which) mpfr_cos(sinx, sinx, MPFR_RNDD); else mpfr_sin(sinx, sinx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, sinx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (which && i == 0) /* special case */ { mpfr_set_ui(y2, 1, MPFR_RNDD); mpfr_mul_2ui(y2, y2, prec, MPFR_RNDD); mpfr_sub_ui(y2, y2, 1, MPFR_RNDD); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); } if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } } mpfr_clear(tabx); mpfr_clear(sinx); mpfr_clear(y1); mpfr_clear(y2); } { slong prec, bits, num; prec = ARB_SIN_COS_TAB2_LIMBS * FLINT_BITS; bits = ARB_SIN_COS_TAB21_BITS + ARB_SIN_COS_TAB22_BITS; num = ARB_SIN_COS_TAB22_NUM; mpfr_init2(tabx, prec); mpfr_init2(sinx, prec); mpfr_init2(y1, prec); mpfr_init2(y2, prec); for (which = 0; which < 2; which++) { for (i = 0; i < num; i++) { tt->_mp_d = (mp_ptr) arb_sin_cos_tab22[2 * i + which]; tt->_mp_size = prec / FLINT_BITS; tt->_mp_alloc = tt->_mp_size; while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0) tt->_mp_size--; mpfr_set_z(tabx, tt, MPFR_RNDD); mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD); mpfr_set_ui(sinx, i, MPFR_RNDD); mpfr_div_2ui(sinx, sinx, bits, MPFR_RNDD); if (which) mpfr_cos(sinx, sinx, MPFR_RNDD); else mpfr_sin(sinx, sinx, MPFR_RNDD); mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD); mpfr_floor(y1, y1); mpfr_div_2ui(y1, y1, prec, MPFR_RNDD); mpfr_mul_2ui(y2, sinx, prec, MPFR_RNDD); mpfr_floor(y2, y2); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); if (which && i == 0) /* special case */ { mpfr_set_ui(y2, 1, MPFR_RNDD); mpfr_mul_2ui(y2, y2, prec, MPFR_RNDD); mpfr_sub_ui(y2, y2, 1, MPFR_RNDD); mpfr_div_2ui(y2, y2, prec, MPFR_RNDD); } if (!mpfr_equal_p(y1, y2)) { flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec); mpfr_printf("y1 = %.1500Rg\n", y1); mpfr_printf("y2 = %.1500Rg\n", y2); flint_abort(); } } } mpfr_clear(tabx); mpfr_clear(sinx); mpfr_clear(y1); mpfr_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_cos_taylor_rs.c000066400000000000000000000064211461254215100213100ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_cos_taylor_rs, state) { slong iter; _flint_rand_init_gmp(state); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mp_ptr x, y1s, y1c, y2s, y2c, t; mp_limb_t err1, err2; ulong N; mp_size_t xn; int cmp, result; N = n_randint(state, 144 - 1); xn = 1 + n_randint(state, 20); x = flint_malloc(sizeof(mp_limb_t) * xn); y1s = flint_malloc(sizeof(mp_limb_t) * xn); y1c = flint_malloc(sizeof(mp_limb_t) * xn); y2s = flint_malloc(sizeof(mp_limb_t) * xn); y2c = flint_malloc(sizeof(mp_limb_t) * xn); t = flint_malloc(sizeof(mp_limb_t) * xn); flint_mpn_rrandom(x, state->gmp_state, xn); flint_mpn_rrandom(y1s, state->gmp_state, xn); flint_mpn_rrandom(y1c, state->gmp_state, xn); flint_mpn_rrandom(y2s, state->gmp_state, xn); flint_mpn_rrandom(y2c, state->gmp_state, xn); x[xn - 1] &= (LIMB_ONES >> 4); _arb_sin_cos_taylor_naive(y1s, y1c, &err1, x, xn, N); _arb_sin_cos_taylor_rs(y2s, y2c, &err2, x, xn, N, 0, 1); cmp = mpn_cmp(y1s, y2s, xn); if (cmp == 0) { result = 1; } else if (cmp > 0) { mpn_sub_n(t, y1s, y2s, xn); result = flint_mpn_zero_p(t + 1, xn - 1) && (t[0] <= err2); } else { mpn_sub_n(t, y2s, y1s, xn); result = flint_mpn_zero_p(t + 1, xn - 1) && (t[0] <= err2); } if (!result) { flint_printf("FAIL\n"); flint_printf("N = %wd xn = %wd\n", N, xn); flint_printf("x ="); flint_mpn_debug(x, xn); flint_printf("y1s ="); flint_mpn_debug(y1s, xn); flint_printf("y2s ="); flint_mpn_debug(y2s, xn); flint_abort(); } cmp = mpn_cmp(y1c, y2c, xn); if (cmp == 0) { result = 1; } else if (cmp > 0) { mpn_sub_n(t, y1c, y2c, xn); result = flint_mpn_zero_p(t + 1, xn - 1) && (t[0] <= err2); } else { mpn_sub_n(t, y2c, y1c, xn); result = flint_mpn_zero_p(t + 1, xn - 1) && (t[0] <= err2); } if (!result) { flint_printf("FAIL\n"); flint_printf("N = %wd xn = %wd\n", N, xn); flint_printf("x ="); flint_mpn_debug(x, xn); flint_printf("y1c ="); flint_mpn_debug(y1c, xn); flint_printf("y2c ="); flint_mpn_debug(y2c, xn); flint_abort(); } flint_free(x); flint_free(y1s); flint_free(y1c); flint_free(y2s); flint_free(y2c); flint_free(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_pi.c000066400000000000000000000026701461254215100170400ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_const_pi(b, prec); arb_mul(b, b, a, prec); arb_sin(b, b, prec); arb_sin_pi(c, a, prec); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_pi_fmpq.c000066400000000000000000000027221461254215100200610ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_pi_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s1, s2; fmpq_t x; slong prec; prec = 2 + n_randint(state, 5000); arb_init(s1); arb_init(s2); fmpq_init(x); fmpq_randtest(x, state, 1 + n_randint(state, 200)); arb_sin_pi_fmpq(s1, x, prec); arb_const_pi(s2, prec); arb_mul_fmpz(s2, s2, fmpq_numref(x), prec); arb_div_fmpz(s2, s2, fmpq_denref(x), prec); arb_sin(s2, s2, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("s1 = "); arb_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); arb_printd(s2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); fmpq_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sin_pi_fmpq_algebraic.c000066400000000000000000000036751461254215100220620ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "arb.h" TEST_FUNCTION_START(arb_sin_pi_fmpq_algebraic, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s1, s2; ulong p, q, g; slong prec; prec = 2 + n_randint(state, 5000); q = 1 + n_randint(state, 500); p = n_randint(state, q / 2 + 1); g = n_gcd(q, p); q /= g; p /= g; arb_init(s1); arb_init(s2); _arb_sin_pi_fmpq_algebraic(s1, p, q, prec); arb_const_pi(s2, prec); arb_mul_ui(s2, s2, p, prec); arb_div_ui(s2, s2, q, prec); arb_sin(s2, s2, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("s1 = "); arb_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); arb_printd(s2, 15); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(s1) < prec - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("p/q = %wu/%wu", p, q); flint_printf("\n\n"); flint_printf("prec=%wd eff=%wd\n", prec, arb_rel_accuracy_bits(s1)); flint_printf("s1 = "); arb_printd(s1, 15); flint_printf("\n\n"); flint_printf("s2 = "); arb_printd(s2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sinc.c000066400000000000000000000074371461254215100165210ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sinc, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, a; slong prec, mag_bits; prec = 2 + n_randint(state, 500); mag_bits = 6 + n_randint(state, 500); arb_init(x); arb_randtest(x, state, 1 + n_randint(state, prec), mag_bits); arb_init(a); arb_sinc(a, x, prec); /* sinc(x) approximately in [-2, 2] */ { arb_t b; arb_init(b); arb_zero(b); mag_set_d(arb_radref(b), 1.01); mag_mul_2exp_si(arb_radref(b), arb_radref(b), 1); if (!arb_contains(b, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(b); } /* sinc(x) * x = sin(x) */ { arb_t b, c; arb_init(b); arb_init(c); arb_mul(b, a, x, prec); arb_sin(c, x, prec); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap (sin)\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(b); arb_clear(c); } /* aliasing */ { arb_t b; arb_init(b); arb_set(b, x); arb_sinc(b, b, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(b); } arb_clear(x); arb_clear(a); } /* Check a few special intervals. */ { arb_t x, y; slong prec; arb_init(x); arb_init(y); prec = 32; arb_neg_inf(x); arb_sinc(y, x, prec); if (!arb_is_zero(y)) { flint_printf("FAIL: negative infinity\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } arb_pos_inf(x); arb_sinc(y, x, prec); if (!arb_is_zero(y)) { flint_printf("FAIL: positive infinity\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } arb_zero_pm_inf(x); arb_sinc(y, x, prec); if (!(arb_is_finite(y) && arb_contains_negative(y) && arb_contains_positive(y) && arb_contains_zero(y))) { flint_printf("FAIL: the whole extended real line\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sinc_pi.c000066400000000000000000000076251461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sinc_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; slong prec; arb_init(x); arb_init(y); arb_init(z); prec = 2 + n_randint(state, 200); arb_randtest(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest(y, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); if (n_randint(state, 2)) { arb_set(y, x); arb_sinc_pi(y, y, prec); } else arb_sinc_pi(y, x, prec); arb_const_pi(z, prec); arb_mul(z, z, x, prec); arb_sinc(z, z, prec); if (!arb_overlaps(y, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_abort(); } if (arb_is_int(x)) { if (arb_is_zero(x) && !arb_is_one(y)) { flint_printf("FAIL: zero\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } if (arb_is_positive(x) && !arb_is_zero(y)) { flint_printf("FAIL: positive integer\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } if (arb_is_negative(x) && !arb_is_zero(y)) { flint_printf("FAIL: negative integer\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(y); arb_clear(z); } /* Check a few special intervals. */ { arb_t x, y; slong prec; arb_init(x); arb_init(y); prec = 32; arb_neg_inf(x); arb_sinc_pi(y, x, prec); if (!arb_is_zero(y)) { flint_printf("FAIL: negative infinity\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } arb_pos_inf(x); arb_sinc_pi(y, x, prec); if (!arb_is_zero(y)) { flint_printf("FAIL: positive infinity\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } arb_zero_pm_inf(x); arb_sinc_pi(y, x, prec); if (!(arb_is_finite(y) && arb_contains_negative(y) && arb_contains_positive(y) && arb_contains_zero(y))) { flint_printf("FAIL: the whole extended real line\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sinh.c000066400000000000000000000032031461254215100165110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sinh, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_sinh(t, t, MPFR_RNDN); arb_sinh(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_sinh(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sinh_cosh.c000066400000000000000000000037051461254215100175340ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sinh_cosh, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t q; mpfr_t t, u; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); fmpq_init(q); mpfr_init2(t, prec + 100); mpfr_init2(u, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_randtest(c, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_sinh_cosh(t, u, t, MPFR_RNDN); arb_sinh_cosh(b, c, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment (sin)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } if (!arb_contains_mpfr(c, u)) { flint_printf("FAIL: containment (cos)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(q); mpfr_clear(t); mpfr_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-special.c000066400000000000000000000672141461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #define ASSERT(cond) if (!(cond)) { flint_printf("FAIL: %d\n", __LINE__); flint_abort(); } TEST_FUNCTION_START(arb_special, state) { arb_t zero, pos, neg, pos_inf, neg_inf, pos_inf_err, neg_inf_err, zero_pm_inf, pos_pm_inf, neg_pm_inf, indet_exact, indet_pos_rad, indet_inf_rad; arb_init(zero); arb_init(pos); arb_init(neg); arb_init(pos_inf); arb_init(neg_inf); arb_init(pos_inf_err); arb_init(neg_inf_err); arb_init(zero_pm_inf); arb_init(pos_pm_inf); arb_init(neg_pm_inf); arb_init(indet_exact); arb_init(indet_pos_rad); arb_init(indet_inf_rad); arb_set_si(pos, 3); arb_div_ui(pos, pos, 5, 53); arb_neg(neg, pos); arb_pos_inf(pos_inf); arb_neg_inf(neg_inf); arb_pos_inf(pos_inf_err); arf_get_mag(arb_radref(pos_inf_err), arb_midref(pos)); arb_neg(neg_inf_err, pos_inf_err); arb_zero_pm_inf(zero_pm_inf); arf_set_si(arb_midref(pos_pm_inf), 3); mag_inf(arb_radref(pos_pm_inf)); arf_set_si(arb_midref(neg_pm_inf), -3); mag_inf(arb_radref(neg_pm_inf)); arf_nan(arb_midref(indet_exact)); mag_zero(arb_radref(indet_exact)); arf_nan(arb_midref(indet_pos_rad)); arf_get_mag(arb_radref(indet_pos_rad), arb_midref(pos)); arf_nan(arb_midref(indet_inf_rad)); arf_get_mag(arb_radref(indet_inf_rad), arb_midref(pos)); ASSERT(arb_is_zero(zero)); ASSERT(!arb_is_zero(pos)); ASSERT(!arb_is_zero(neg)); ASSERT(!arb_is_zero(pos_inf)); ASSERT(!arb_is_zero(neg_inf)); ASSERT(!arb_is_zero(pos_inf_err)); ASSERT(!arb_is_zero(neg_inf_err)); ASSERT(!arb_is_zero(zero_pm_inf)); ASSERT(!arb_is_zero(pos_pm_inf)); ASSERT(!arb_is_zero(neg_pm_inf)); ASSERT(!arb_is_zero(indet_exact)); ASSERT(!arb_is_zero(indet_pos_rad)); ASSERT(!arb_is_zero(indet_inf_rad)); ASSERT(!arb_is_nonzero(zero)); ASSERT(arb_is_nonzero(pos)); ASSERT(arb_is_nonzero(neg)); ASSERT(arb_is_nonzero(pos_inf)); ASSERT(arb_is_nonzero(neg_inf)); ASSERT(arb_is_nonzero(pos_inf_err)); ASSERT(arb_is_nonzero(neg_inf_err)); ASSERT(!arb_is_nonzero(zero_pm_inf)); ASSERT(!arb_is_nonzero(pos_pm_inf)); ASSERT(!arb_is_nonzero(neg_pm_inf)); ASSERT(!arb_is_nonzero(indet_exact)); ASSERT(!arb_is_nonzero(indet_pos_rad)); ASSERT(!arb_is_nonzero(indet_inf_rad)); ASSERT(!arb_is_positive(zero)); ASSERT(arb_is_positive(pos)); ASSERT(!arb_is_positive(neg)); ASSERT(arb_is_positive(pos_inf)); ASSERT(!arb_is_positive(neg_inf)); ASSERT(arb_is_positive(pos_inf_err)); ASSERT(!arb_is_positive(neg_inf_err)); ASSERT(!arb_is_positive(zero_pm_inf)); ASSERT(!arb_is_positive(pos_pm_inf)); ASSERT(!arb_is_positive(neg_pm_inf)); ASSERT(!arb_is_positive(indet_exact)); ASSERT(!arb_is_positive(indet_pos_rad)); ASSERT(!arb_is_positive(indet_inf_rad)); ASSERT(!arb_is_negative(zero)); ASSERT(!arb_is_negative(pos)); ASSERT(arb_is_negative(neg)); ASSERT(!arb_is_negative(pos_inf)); ASSERT(arb_is_negative(neg_inf)); ASSERT(!arb_is_negative(pos_inf_err)); ASSERT(arb_is_negative(neg_inf_err)); ASSERT(!arb_is_negative(zero_pm_inf)); ASSERT(!arb_is_negative(pos_pm_inf)); ASSERT(!arb_is_negative(neg_pm_inf)); ASSERT(!arb_is_negative(indet_exact)); ASSERT(!arb_is_negative(indet_pos_rad)); ASSERT(!arb_is_negative(indet_inf_rad)); ASSERT(arb_is_nonnegative(zero)); ASSERT(arb_is_nonnegative(pos)); ASSERT(!arb_is_nonnegative(neg)); ASSERT(arb_is_nonnegative(pos_inf)); ASSERT(!arb_is_nonnegative(neg_inf)); ASSERT(arb_is_nonnegative(pos_inf_err)); ASSERT(!arb_is_nonnegative(neg_inf_err)); ASSERT(!arb_is_nonnegative(zero_pm_inf)); ASSERT(!arb_is_nonnegative(pos_pm_inf)); ASSERT(!arb_is_nonnegative(neg_pm_inf)); ASSERT(!arb_is_nonnegative(indet_exact)); ASSERT(!arb_is_nonnegative(indet_pos_rad)); ASSERT(!arb_is_nonnegative(indet_inf_rad)); ASSERT(arb_is_nonpositive(zero)); ASSERT(!arb_is_nonpositive(pos)); ASSERT(arb_is_nonpositive(neg)); ASSERT(!arb_is_nonpositive(pos_inf)); ASSERT(arb_is_nonpositive(neg_inf)); ASSERT(!arb_is_nonpositive(pos_inf_err)); ASSERT(arb_is_nonpositive(neg_inf_err)); ASSERT(!arb_is_nonpositive(zero_pm_inf)); ASSERT(!arb_is_nonpositive(pos_pm_inf)); ASSERT(!arb_is_nonpositive(neg_pm_inf)); ASSERT(!arb_is_nonpositive(indet_exact)); ASSERT(!arb_is_nonpositive(indet_pos_rad)); ASSERT(!arb_is_nonpositive(indet_inf_rad)); ASSERT(!arb_contains_negative(zero)); ASSERT(!arb_contains_negative(pos)); ASSERT(arb_contains_negative(neg)); ASSERT(!arb_contains_negative(pos_inf)); ASSERT(arb_contains_negative(neg_inf)); ASSERT(!arb_contains_negative(pos_inf_err)); ASSERT(arb_contains_negative(neg_inf_err)); ASSERT(arb_contains_negative(zero_pm_inf)); ASSERT(arb_contains_negative(pos_pm_inf)); ASSERT(arb_contains_negative(neg_pm_inf)); ASSERT(arb_contains_negative(indet_exact)); ASSERT(arb_contains_negative(indet_pos_rad)); ASSERT(arb_contains_negative(indet_inf_rad)); ASSERT(arb_contains_nonpositive(zero)); ASSERT(!arb_contains_nonpositive(pos)); ASSERT(arb_contains_nonpositive(neg)); ASSERT(!arb_contains_nonpositive(pos_inf)); ASSERT(arb_contains_nonpositive(neg_inf)); ASSERT(!arb_contains_nonpositive(pos_inf_err)); ASSERT(arb_contains_nonpositive(neg_inf_err)); ASSERT(arb_contains_nonpositive(zero_pm_inf)); ASSERT(arb_contains_nonpositive(pos_pm_inf)); ASSERT(arb_contains_nonpositive(neg_pm_inf)); ASSERT(arb_contains_nonpositive(indet_exact)); ASSERT(arb_contains_nonpositive(indet_pos_rad)); ASSERT(arb_contains_nonpositive(indet_inf_rad)); ASSERT(!arb_contains_positive(zero)); ASSERT(arb_contains_positive(pos)); ASSERT(!arb_contains_positive(neg)); ASSERT(arb_contains_positive(pos_inf)); ASSERT(!arb_contains_positive(neg_inf)); ASSERT(arb_contains_positive(pos_inf_err)); ASSERT(!arb_contains_positive(neg_inf_err)); ASSERT(arb_contains_positive(zero_pm_inf)); ASSERT(arb_contains_positive(pos_pm_inf)); ASSERT(arb_contains_positive(neg_pm_inf)); ASSERT(arb_contains_positive(indet_exact)); ASSERT(arb_contains_positive(indet_pos_rad)); ASSERT(arb_contains_positive(indet_inf_rad)); ASSERT(arb_contains_nonnegative(zero)); ASSERT(arb_contains_nonnegative(pos)); ASSERT(!arb_contains_nonnegative(neg)); ASSERT(arb_contains_nonnegative(pos_inf)); ASSERT(!arb_contains_nonnegative(neg_inf)); ASSERT(arb_contains_nonnegative(pos_inf_err)); ASSERT(!arb_contains_nonnegative(neg_inf_err)); ASSERT(arb_contains_nonnegative(zero_pm_inf)); ASSERT(arb_contains_nonnegative(pos_pm_inf)); ASSERT(arb_contains_nonnegative(neg_pm_inf)); ASSERT(arb_contains_nonnegative(indet_exact)); ASSERT(arb_contains_nonnegative(indet_pos_rad)); ASSERT(arb_contains_nonnegative(indet_inf_rad)); ASSERT(arb_is_finite(zero)); ASSERT(arb_is_finite(pos)); ASSERT(arb_is_finite(neg)); ASSERT(!arb_is_finite(pos_inf)); ASSERT(!arb_is_finite(neg_inf)); ASSERT(!arb_is_finite(pos_inf_err)); ASSERT(!arb_is_finite(neg_inf_err)); ASSERT(!arb_is_finite(zero_pm_inf)); ASSERT(!arb_is_finite(pos_pm_inf)); ASSERT(!arb_is_finite(neg_pm_inf)); ASSERT(!arb_is_finite(indet_exact)); ASSERT(!arb_is_finite(indet_pos_rad)); ASSERT(!arb_is_finite(indet_inf_rad)); ASSERT(arb_contains(zero, zero)); ASSERT(!arb_contains(zero, pos)); ASSERT(!arb_contains(zero, neg)); ASSERT(!arb_contains(zero, pos_inf)); ASSERT(!arb_contains(zero, neg_inf)); ASSERT(!arb_contains(zero, pos_inf_err)); ASSERT(!arb_contains(zero, neg_inf_err)); ASSERT(!arb_contains(zero, zero_pm_inf)); ASSERT(!arb_contains(zero, pos_pm_inf)); ASSERT(!arb_contains(zero, neg_pm_inf)); ASSERT(!arb_contains(zero, indet_exact)); ASSERT(!arb_contains(zero, indet_pos_rad)); ASSERT(!arb_contains(zero, indet_inf_rad)); ASSERT(!arb_contains(pos, zero)); ASSERT(arb_contains(pos, pos)); ASSERT(!arb_contains(pos, neg)); ASSERT(!arb_contains(pos, pos_inf)); ASSERT(!arb_contains(pos, neg_inf)); ASSERT(!arb_contains(pos, pos_inf_err)); ASSERT(!arb_contains(pos, neg_inf_err)); ASSERT(!arb_contains(pos, zero_pm_inf)); ASSERT(!arb_contains(pos, pos_pm_inf)); ASSERT(!arb_contains(pos, neg_pm_inf)); ASSERT(!arb_contains(pos, indet_exact)); ASSERT(!arb_contains(pos, indet_pos_rad)); ASSERT(!arb_contains(pos, indet_inf_rad)); ASSERT(!arb_contains(neg, zero)); ASSERT(!arb_contains(neg, pos)); ASSERT(arb_contains(neg, neg)); ASSERT(!arb_contains(neg, pos_inf)); ASSERT(!arb_contains(neg, neg_inf)); ASSERT(!arb_contains(neg, pos_inf_err)); ASSERT(!arb_contains(neg, neg_inf_err)); ASSERT(!arb_contains(neg, zero_pm_inf)); ASSERT(!arb_contains(neg, pos_pm_inf)); ASSERT(!arb_contains(neg, neg_pm_inf)); ASSERT(!arb_contains(neg, indet_exact)); ASSERT(!arb_contains(neg, indet_pos_rad)); ASSERT(!arb_contains(neg, indet_inf_rad)); ASSERT(!arb_contains(pos_inf, zero)); ASSERT(!arb_contains(pos_inf, pos)); ASSERT(!arb_contains(pos_inf, neg)); ASSERT(arb_contains(pos_inf, pos_inf)); ASSERT(!arb_contains(pos_inf, neg_inf)); ASSERT(arb_contains(pos_inf, pos_inf_err)); ASSERT(!arb_contains(pos_inf, neg_inf_err)); ASSERT(!arb_contains(pos_inf, zero_pm_inf)); ASSERT(!arb_contains(pos_inf, pos_pm_inf)); ASSERT(!arb_contains(pos_inf, neg_pm_inf)); ASSERT(!arb_contains(pos_inf, indet_exact)); ASSERT(!arb_contains(pos_inf, indet_pos_rad)); ASSERT(!arb_contains(pos_inf, indet_inf_rad)); ASSERT(!arb_contains(neg_inf, zero)); ASSERT(!arb_contains(neg_inf, pos)); ASSERT(!arb_contains(neg_inf, neg)); ASSERT(!arb_contains(neg_inf, pos_inf)); ASSERT(arb_contains(neg_inf, neg_inf)); ASSERT(!arb_contains(neg_inf, pos_inf_err)); ASSERT(arb_contains(neg_inf, neg_inf_err)); ASSERT(!arb_contains(neg_inf, zero_pm_inf)); ASSERT(!arb_contains(neg_inf, pos_pm_inf)); ASSERT(!arb_contains(neg_inf, neg_pm_inf)); ASSERT(!arb_contains(neg_inf, indet_exact)); ASSERT(!arb_contains(neg_inf, indet_pos_rad)); ASSERT(!arb_contains(neg_inf, indet_inf_rad)); ASSERT(!arb_contains(pos_inf_err, zero)); ASSERT(!arb_contains(pos_inf_err, pos)); ASSERT(!arb_contains(pos_inf_err, neg)); ASSERT(arb_contains(pos_inf_err, pos_inf)); ASSERT(!arb_contains(pos_inf_err, neg_inf)); ASSERT(arb_contains(pos_inf_err, pos_inf_err)); ASSERT(!arb_contains(pos_inf_err, neg_inf_err)); ASSERT(!arb_contains(pos_inf_err, zero_pm_inf)); ASSERT(!arb_contains(pos_inf_err, pos_pm_inf)); ASSERT(!arb_contains(pos_inf_err, neg_pm_inf)); ASSERT(!arb_contains(pos_inf_err, indet_exact)); ASSERT(!arb_contains(pos_inf_err, indet_pos_rad)); ASSERT(!arb_contains(pos_inf_err, indet_inf_rad)); ASSERT(!arb_contains(neg_inf_err, zero)); ASSERT(!arb_contains(neg_inf_err, pos)); ASSERT(!arb_contains(neg_inf_err, neg)); ASSERT(!arb_contains(neg_inf_err, pos_inf)); ASSERT(arb_contains(neg_inf_err, neg_inf)); ASSERT(!arb_contains(neg_inf_err, pos_inf_err)); ASSERT(arb_contains(neg_inf_err, neg_inf_err)); ASSERT(!arb_contains(neg_inf_err, zero_pm_inf)); ASSERT(!arb_contains(neg_inf_err, pos_pm_inf)); ASSERT(!arb_contains(neg_inf_err, neg_pm_inf)); ASSERT(!arb_contains(neg_inf_err, indet_exact)); ASSERT(!arb_contains(neg_inf_err, indet_pos_rad)); ASSERT(!arb_contains(neg_inf_err, indet_inf_rad)); ASSERT(arb_contains(zero_pm_inf, zero)); ASSERT(arb_contains(zero_pm_inf, pos)); ASSERT(arb_contains(zero_pm_inf, neg)); ASSERT(arb_contains(zero_pm_inf, pos_inf)); ASSERT(arb_contains(zero_pm_inf, neg_inf)); ASSERT(arb_contains(zero_pm_inf, pos_inf_err)); ASSERT(arb_contains(zero_pm_inf, neg_inf_err)); ASSERT(arb_contains(zero_pm_inf, zero_pm_inf)); ASSERT(arb_contains(zero_pm_inf, pos_pm_inf)); ASSERT(arb_contains(zero_pm_inf, neg_pm_inf)); ASSERT(!arb_contains(zero_pm_inf, indet_exact)); ASSERT(!arb_contains(zero_pm_inf, indet_pos_rad)); ASSERT(!arb_contains(zero_pm_inf, indet_inf_rad)); ASSERT(arb_contains(pos_pm_inf, zero)); ASSERT(arb_contains(pos_pm_inf, pos)); ASSERT(arb_contains(pos_pm_inf, neg)); ASSERT(arb_contains(pos_pm_inf, pos_inf)); ASSERT(arb_contains(pos_pm_inf, neg_inf)); ASSERT(arb_contains(pos_pm_inf, pos_inf_err)); ASSERT(arb_contains(pos_pm_inf, neg_inf_err)); ASSERT(arb_contains(pos_pm_inf, zero_pm_inf)); ASSERT(arb_contains(pos_pm_inf, pos_pm_inf)); ASSERT(arb_contains(pos_pm_inf, neg_pm_inf)); ASSERT(!arb_contains(pos_pm_inf, indet_exact)); ASSERT(!arb_contains(pos_pm_inf, indet_pos_rad)); ASSERT(!arb_contains(pos_pm_inf, indet_inf_rad)); ASSERT(arb_contains(neg_pm_inf, zero)); ASSERT(arb_contains(neg_pm_inf, pos)); ASSERT(arb_contains(neg_pm_inf, neg)); ASSERT(arb_contains(neg_pm_inf, pos_inf)); ASSERT(arb_contains(neg_pm_inf, neg_inf)); ASSERT(arb_contains(neg_pm_inf, pos_inf_err)); ASSERT(arb_contains(neg_pm_inf, neg_inf_err)); ASSERT(arb_contains(neg_pm_inf, zero_pm_inf)); ASSERT(arb_contains(neg_pm_inf, pos_pm_inf)); ASSERT(arb_contains(neg_pm_inf, neg_pm_inf)); ASSERT(!arb_contains(neg_pm_inf, indet_exact)); ASSERT(!arb_contains(neg_pm_inf, indet_pos_rad)); ASSERT(!arb_contains(neg_pm_inf, indet_inf_rad)); ASSERT(arb_contains(indet_exact, zero)); ASSERT(arb_contains(indet_exact, pos)); ASSERT(arb_contains(indet_exact, neg)); ASSERT(arb_contains(indet_exact, pos_inf)); ASSERT(arb_contains(indet_exact, neg_inf)); ASSERT(arb_contains(indet_exact, pos_inf_err)); ASSERT(arb_contains(indet_exact, neg_inf_err)); ASSERT(arb_contains(indet_exact, zero_pm_inf)); ASSERT(arb_contains(indet_exact, pos_pm_inf)); ASSERT(arb_contains(indet_exact, neg_pm_inf)); ASSERT(arb_contains(indet_exact, indet_exact)); ASSERT(arb_contains(indet_exact, indet_pos_rad)); ASSERT(arb_contains(indet_exact, indet_inf_rad)); ASSERT(arb_contains(indet_pos_rad, zero)); ASSERT(arb_contains(indet_pos_rad, pos)); ASSERT(arb_contains(indet_pos_rad, neg)); ASSERT(arb_contains(indet_pos_rad, pos_inf)); ASSERT(arb_contains(indet_pos_rad, neg_inf)); ASSERT(arb_contains(indet_pos_rad, pos_inf_err)); ASSERT(arb_contains(indet_pos_rad, neg_inf_err)); ASSERT(arb_contains(indet_pos_rad, zero_pm_inf)); ASSERT(arb_contains(indet_pos_rad, pos_pm_inf)); ASSERT(arb_contains(indet_pos_rad, neg_pm_inf)); ASSERT(arb_contains(indet_pos_rad, indet_exact)); ASSERT(arb_contains(indet_pos_rad, indet_pos_rad)); ASSERT(arb_contains(indet_pos_rad, indet_inf_rad)); ASSERT(arb_contains(indet_inf_rad, zero)); ASSERT(arb_contains(indet_inf_rad, pos)); ASSERT(arb_contains(indet_inf_rad, neg)); ASSERT(arb_contains(indet_inf_rad, pos_inf)); ASSERT(arb_contains(indet_inf_rad, neg_inf)); ASSERT(arb_contains(indet_inf_rad, pos_inf_err)); ASSERT(arb_contains(indet_inf_rad, neg_inf_err)); ASSERT(arb_contains(indet_inf_rad, zero_pm_inf)); ASSERT(arb_contains(indet_inf_rad, pos_pm_inf)); ASSERT(arb_contains(indet_inf_rad, neg_pm_inf)); ASSERT(arb_contains(indet_inf_rad, indet_exact)); ASSERT(arb_contains(indet_inf_rad, indet_pos_rad)); ASSERT(arb_contains(indet_inf_rad, indet_inf_rad)); ASSERT(arb_overlaps(zero, zero)); ASSERT(!arb_overlaps(zero, pos)); ASSERT(!arb_overlaps(zero, neg)); ASSERT(!arb_overlaps(zero, pos_inf)); ASSERT(!arb_overlaps(zero, neg_inf)); ASSERT(!arb_overlaps(zero, pos_inf_err)); ASSERT(!arb_overlaps(zero, neg_inf_err)); ASSERT(arb_overlaps(zero, zero_pm_inf)); ASSERT(arb_overlaps(zero, pos_pm_inf)); ASSERT(arb_overlaps(zero, neg_pm_inf)); ASSERT(arb_overlaps(zero, indet_exact)); ASSERT(arb_overlaps(zero, indet_pos_rad)); ASSERT(arb_overlaps(zero, indet_inf_rad)); ASSERT(!arb_overlaps(pos, zero)); ASSERT(arb_overlaps(pos, pos)); ASSERT(!arb_overlaps(pos, neg)); ASSERT(!arb_overlaps(pos, pos_inf)); ASSERT(!arb_overlaps(pos, neg_inf)); ASSERT(!arb_overlaps(pos, pos_inf_err)); ASSERT(!arb_overlaps(pos, neg_inf_err)); ASSERT(arb_overlaps(pos, zero_pm_inf)); ASSERT(arb_overlaps(pos, pos_pm_inf)); ASSERT(arb_overlaps(pos, neg_pm_inf)); ASSERT(arb_overlaps(pos, indet_exact)); ASSERT(arb_overlaps(pos, indet_pos_rad)); ASSERT(arb_overlaps(pos, indet_inf_rad)); ASSERT(!arb_overlaps(neg, zero)); ASSERT(!arb_overlaps(neg, pos)); ASSERT(arb_overlaps(neg, neg)); ASSERT(!arb_overlaps(neg, pos_inf)); ASSERT(!arb_overlaps(neg, neg_inf)); ASSERT(!arb_overlaps(neg, pos_inf_err)); ASSERT(!arb_overlaps(neg, neg_inf_err)); ASSERT(arb_overlaps(neg, zero_pm_inf)); ASSERT(arb_overlaps(neg, pos_pm_inf)); ASSERT(arb_overlaps(neg, neg_pm_inf)); ASSERT(arb_overlaps(neg, indet_exact)); ASSERT(arb_overlaps(neg, indet_pos_rad)); ASSERT(arb_overlaps(neg, indet_inf_rad)); ASSERT(!arb_overlaps(pos_inf, zero)); ASSERT(!arb_overlaps(pos_inf, pos)); ASSERT(!arb_overlaps(pos_inf, neg)); ASSERT(arb_overlaps(pos_inf, pos_inf)); ASSERT(!arb_overlaps(pos_inf, neg_inf)); ASSERT(arb_overlaps(pos_inf, pos_inf_err)); ASSERT(!arb_overlaps(pos_inf, neg_inf_err)); ASSERT(arb_overlaps(pos_inf, zero_pm_inf)); ASSERT(arb_overlaps(pos_inf, pos_pm_inf)); ASSERT(arb_overlaps(pos_inf, neg_pm_inf)); ASSERT(arb_overlaps(pos_inf, indet_exact)); ASSERT(arb_overlaps(pos_inf, indet_pos_rad)); ASSERT(arb_overlaps(pos_inf, indet_inf_rad)); ASSERT(!arb_overlaps(neg_inf, zero)); ASSERT(!arb_overlaps(neg_inf, pos)); ASSERT(!arb_overlaps(neg_inf, neg)); ASSERT(!arb_overlaps(neg_inf, pos_inf)); ASSERT(arb_overlaps(neg_inf, neg_inf)); ASSERT(!arb_overlaps(neg_inf, pos_inf_err)); ASSERT(arb_overlaps(neg_inf, neg_inf_err)); ASSERT(arb_overlaps(neg_inf, zero_pm_inf)); ASSERT(arb_overlaps(neg_inf, pos_pm_inf)); ASSERT(arb_overlaps(neg_inf, neg_pm_inf)); ASSERT(arb_overlaps(neg_inf, indet_exact)); ASSERT(arb_overlaps(neg_inf, indet_pos_rad)); ASSERT(arb_overlaps(neg_inf, indet_inf_rad)); ASSERT(!arb_overlaps(pos_inf_err, zero)); ASSERT(!arb_overlaps(pos_inf_err, pos)); ASSERT(!arb_overlaps(pos_inf_err, neg)); ASSERT(arb_overlaps(pos_inf_err, pos_inf)); ASSERT(!arb_overlaps(pos_inf_err, neg_inf)); ASSERT(arb_overlaps(pos_inf_err, pos_inf_err)); ASSERT(!arb_overlaps(pos_inf_err, neg_inf_err)); ASSERT(arb_overlaps(pos_inf_err, zero_pm_inf)); ASSERT(arb_overlaps(pos_inf_err, pos_pm_inf)); ASSERT(arb_overlaps(pos_inf_err, neg_pm_inf)); ASSERT(arb_overlaps(pos_inf_err, indet_exact)); ASSERT(arb_overlaps(pos_inf_err, indet_pos_rad)); ASSERT(arb_overlaps(pos_inf_err, indet_inf_rad)); ASSERT(!arb_overlaps(neg_inf_err, zero)); ASSERT(!arb_overlaps(neg_inf_err, pos)); ASSERT(!arb_overlaps(neg_inf_err, neg)); ASSERT(!arb_overlaps(neg_inf_err, pos_inf)); ASSERT(arb_overlaps(neg_inf_err, neg_inf)); ASSERT(!arb_overlaps(neg_inf_err, pos_inf_err)); ASSERT(arb_overlaps(neg_inf_err, neg_inf_err)); ASSERT(arb_overlaps(neg_inf_err, zero_pm_inf)); ASSERT(arb_overlaps(neg_inf_err, pos_pm_inf)); ASSERT(arb_overlaps(neg_inf_err, neg_pm_inf)); ASSERT(arb_overlaps(neg_inf_err, indet_exact)); ASSERT(arb_overlaps(neg_inf_err, indet_pos_rad)); ASSERT(arb_overlaps(neg_inf_err, indet_inf_rad)); ASSERT(arb_overlaps(zero_pm_inf, zero)); ASSERT(arb_overlaps(zero_pm_inf, pos)); ASSERT(arb_overlaps(zero_pm_inf, neg)); ASSERT(arb_overlaps(zero_pm_inf, pos_inf)); ASSERT(arb_overlaps(zero_pm_inf, neg_inf)); ASSERT(arb_overlaps(zero_pm_inf, pos_inf_err)); ASSERT(arb_overlaps(zero_pm_inf, neg_inf_err)); ASSERT(arb_overlaps(zero_pm_inf, zero_pm_inf)); ASSERT(arb_overlaps(zero_pm_inf, pos_pm_inf)); ASSERT(arb_overlaps(zero_pm_inf, neg_pm_inf)); ASSERT(arb_overlaps(zero_pm_inf, indet_exact)); ASSERT(arb_overlaps(zero_pm_inf, indet_pos_rad)); ASSERT(arb_overlaps(zero_pm_inf, indet_inf_rad)); ASSERT(arb_overlaps(pos_pm_inf, zero)); ASSERT(arb_overlaps(pos_pm_inf, pos)); ASSERT(arb_overlaps(pos_pm_inf, neg)); ASSERT(arb_overlaps(pos_pm_inf, pos_inf)); ASSERT(arb_overlaps(pos_pm_inf, neg_inf)); ASSERT(arb_overlaps(pos_pm_inf, pos_inf_err)); ASSERT(arb_overlaps(pos_pm_inf, neg_inf_err)); ASSERT(arb_overlaps(pos_pm_inf, zero_pm_inf)); ASSERT(arb_overlaps(pos_pm_inf, pos_pm_inf)); ASSERT(arb_overlaps(pos_pm_inf, neg_pm_inf)); ASSERT(arb_overlaps(pos_pm_inf, indet_exact)); ASSERT(arb_overlaps(pos_pm_inf, indet_pos_rad)); ASSERT(arb_overlaps(pos_pm_inf, indet_inf_rad)); ASSERT(arb_overlaps(neg_pm_inf, zero)); ASSERT(arb_overlaps(neg_pm_inf, pos)); ASSERT(arb_overlaps(neg_pm_inf, neg)); ASSERT(arb_overlaps(neg_pm_inf, pos_inf)); ASSERT(arb_overlaps(neg_pm_inf, neg_inf)); ASSERT(arb_overlaps(neg_pm_inf, pos_inf_err)); ASSERT(arb_overlaps(neg_pm_inf, neg_inf_err)); ASSERT(arb_overlaps(neg_pm_inf, zero_pm_inf)); ASSERT(arb_overlaps(neg_pm_inf, pos_pm_inf)); ASSERT(arb_overlaps(neg_pm_inf, neg_pm_inf)); ASSERT(arb_overlaps(neg_pm_inf, indet_exact)); ASSERT(arb_overlaps(neg_pm_inf, indet_pos_rad)); ASSERT(arb_overlaps(neg_pm_inf, indet_inf_rad)); ASSERT(arb_overlaps(indet_exact, zero)); ASSERT(arb_overlaps(indet_exact, pos)); ASSERT(arb_overlaps(indet_exact, neg)); ASSERT(arb_overlaps(indet_exact, pos_inf)); ASSERT(arb_overlaps(indet_exact, neg_inf)); ASSERT(arb_overlaps(indet_exact, pos_inf_err)); ASSERT(arb_overlaps(indet_exact, neg_inf_err)); ASSERT(arb_overlaps(indet_exact, zero_pm_inf)); ASSERT(arb_overlaps(indet_exact, pos_pm_inf)); ASSERT(arb_overlaps(indet_exact, neg_pm_inf)); ASSERT(arb_overlaps(indet_exact, indet_exact)); ASSERT(arb_overlaps(indet_exact, indet_pos_rad)); ASSERT(arb_overlaps(indet_exact, indet_inf_rad)); ASSERT(arb_overlaps(indet_pos_rad, zero)); ASSERT(arb_overlaps(indet_pos_rad, pos)); ASSERT(arb_overlaps(indet_pos_rad, neg)); ASSERT(arb_overlaps(indet_pos_rad, pos_inf)); ASSERT(arb_overlaps(indet_pos_rad, neg_inf)); ASSERT(arb_overlaps(indet_pos_rad, pos_inf_err)); ASSERT(arb_overlaps(indet_pos_rad, neg_inf_err)); ASSERT(arb_overlaps(indet_pos_rad, zero_pm_inf)); ASSERT(arb_overlaps(indet_pos_rad, pos_pm_inf)); ASSERT(arb_overlaps(indet_pos_rad, neg_pm_inf)); ASSERT(arb_overlaps(indet_pos_rad, indet_exact)); ASSERT(arb_overlaps(indet_pos_rad, indet_pos_rad)); ASSERT(arb_overlaps(indet_pos_rad, indet_inf_rad)); ASSERT(arb_overlaps(indet_inf_rad, zero)); ASSERT(arb_overlaps(indet_inf_rad, pos)); ASSERT(arb_overlaps(indet_inf_rad, neg)); ASSERT(arb_overlaps(indet_inf_rad, pos_inf)); ASSERT(arb_overlaps(indet_inf_rad, neg_inf)); ASSERT(arb_overlaps(indet_inf_rad, pos_inf_err)); ASSERT(arb_overlaps(indet_inf_rad, neg_inf_err)); ASSERT(arb_overlaps(indet_inf_rad, zero_pm_inf)); ASSERT(arb_overlaps(indet_inf_rad, pos_pm_inf)); ASSERT(arb_overlaps(indet_inf_rad, neg_pm_inf)); ASSERT(arb_overlaps(indet_inf_rad, indet_exact)); ASSERT(arb_overlaps(indet_inf_rad, indet_pos_rad)); ASSERT(arb_overlaps(indet_inf_rad, indet_inf_rad)); { fmpz_t t; fmpz_init(t); ASSERT(arb_get_unique_fmpz(t, zero)); ASSERT(!arb_get_unique_fmpz(t, pos_inf)); ASSERT(!arb_get_unique_fmpz(t, neg_inf)); ASSERT(!arb_get_unique_fmpz(t, pos_inf_err)); ASSERT(!arb_get_unique_fmpz(t, neg_inf_err)); ASSERT(!arb_get_unique_fmpz(t, zero_pm_inf)); ASSERT(!arb_get_unique_fmpz(t, pos_pm_inf)); ASSERT(!arb_get_unique_fmpz(t, neg_pm_inf)); ASSERT(!arb_get_unique_fmpz(t, indet_exact)); ASSERT(!arb_get_unique_fmpz(t, indet_pos_rad)); ASSERT(!arb_get_unique_fmpz(t, indet_inf_rad)); fmpz_clear(t); } { arf_t b; slong wp = 30; arf_init(b); arb_get_abs_ubound_arf(b, zero, wp); ASSERT(arf_is_zero(b)); arb_get_abs_ubound_arf(b, pos, wp); ASSERT(arf_sgn(b) > 0); arb_get_abs_ubound_arf(b, neg, wp); ASSERT(arf_sgn(b) > 0); arb_get_abs_ubound_arf(b, pos_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_ubound_arf(b, neg_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_ubound_arf(b, pos_inf_err, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_ubound_arf(b, neg_inf_err, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_ubound_arf(b, zero_pm_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_ubound_arf(b, indet_exact, wp); ASSERT(arf_is_nan(b)); arb_get_abs_ubound_arf(b, indet_pos_rad, wp); ASSERT(arf_is_nan(b)); arb_get_abs_ubound_arf(b, indet_inf_rad, wp); ASSERT(arf_is_nan(b)); arb_get_abs_lbound_arf(b, zero, wp); ASSERT(arf_is_zero(b)); arb_get_abs_lbound_arf(b, pos, wp); ASSERT(arf_sgn(b) > 0); arb_get_abs_lbound_arf(b, neg, wp); ASSERT(arf_sgn(b) > 0); arb_get_abs_lbound_arf(b, pos_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_lbound_arf(b, neg_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_lbound_arf(b, pos_inf_err, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_lbound_arf(b, neg_inf_err, wp); ASSERT(arf_is_pos_inf(b)); arb_get_abs_lbound_arf(b, zero_pm_inf, wp); ASSERT(arf_is_zero(b)); arb_get_abs_lbound_arf(b, indet_exact, wp); ASSERT(arf_is_nan(b)); arb_get_abs_lbound_arf(b, indet_pos_rad, wp); ASSERT(arf_is_nan(b)); arb_get_abs_lbound_arf(b, indet_inf_rad, wp); ASSERT(arf_is_nan(b)); arb_get_ubound_arf(b, zero, wp); ASSERT(arf_is_zero(b)); arb_get_ubound_arf(b, pos, wp); ASSERT(arf_sgn(b) > 0); arb_get_ubound_arf(b, pos_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_ubound_arf(b, neg_inf, wp); ASSERT(arf_is_neg_inf(b)); arb_get_ubound_arf(b, pos_inf_err, wp); ASSERT(arf_is_pos_inf(b)); arb_get_ubound_arf(b, neg_inf_err, wp); ASSERT(arf_is_neg_inf(b)); arb_get_ubound_arf(b, zero_pm_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_ubound_arf(b, indet_exact, wp); ASSERT(arf_is_nan(b)); arb_get_ubound_arf(b, indet_pos_rad, wp); ASSERT(arf_is_nan(b)); arb_get_ubound_arf(b, indet_inf_rad, wp); ASSERT(arf_is_nan(b)); arb_get_lbound_arf(b, zero, wp); ASSERT(arf_is_zero(b)); arb_get_lbound_arf(b, neg, wp); ASSERT(arf_sgn(b) < 0); arb_get_lbound_arf(b, pos_inf, wp); ASSERT(arf_is_pos_inf(b)); arb_get_lbound_arf(b, neg_inf, wp); ASSERT(arf_is_neg_inf(b)); arb_get_lbound_arf(b, pos_inf_err, wp); ASSERT(arf_is_pos_inf(b)); arb_get_lbound_arf(b, neg_inf_err, wp); ASSERT(arf_is_neg_inf(b)); arb_get_lbound_arf(b, zero_pm_inf, wp); ASSERT(arf_is_neg_inf(b)); arb_get_lbound_arf(b, indet_exact, wp); ASSERT(arf_is_nan(b)); arb_get_lbound_arf(b, indet_pos_rad, wp); ASSERT(arf_is_nan(b)); arb_get_lbound_arf(b, indet_inf_rad, wp); ASSERT(arf_is_nan(b)); arf_clear(b); } arb_clear(zero); arb_clear(pos); arb_clear(neg); arb_clear(pos_inf); arb_clear(neg_inf); arb_clear(pos_inf_err); arb_clear(neg_inf_err); arb_clear(zero_pm_inf); arb_clear(pos_pm_inf); arb_clear(neg_pm_inf); arb_clear(indet_exact); arb_clear(indet_pos_rad); arb_clear(indet_inf_rad); TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sqrt.c000066400000000000000000000026371461254215100165530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sqrt, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 200), 100); arb_sqrt(b, a, prec); arb_mul(c, b, b, prec); if (!arb_contains(c, a)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_sqrt(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sqrt1pm1.c000066400000000000000000000047351461254215100172530ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sqrt1pm1, state) { slong iter; for (iter = 0; iter < 20000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong prec0, prec1, prec2; if (iter % 10 == 0) prec0 = 10000; else prec0 = 1000; prec1 = 2 + n_randint(state, prec0); prec2 = 2 + n_randint(state, prec0); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(b, state, 1 + n_randint(state, prec0), 100); arb_randtest_special(c, state, 1 + n_randint(state, prec0), 100); arb_sqrt1pm1(b, a, prec1); arb_sqrt1pm1(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } /* compare with sqrt */ arb_add_ui(d, a, 1, prec2); arb_sqrt(d, d, prec2); arb_sub_ui(d, d, 1, prec2); if (!arb_overlaps(c, d)) { flint_printf("FAIL: comparison with log\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_sqrt1pm1(a, a, prec1); if (!arb_overlaps(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sqrt_newton.c000066400000000000000000000061221461254215100201360ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sqrt_newton, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, c, d; slong prec; arb_init(a); arb_init(c); arb_init(d); prec = 2 + n_randint(state, 200000); arb_randtest(a, state, 1 + n_randint(state, 200000), 10); arb_randtest(c, state, 1 + n_randint(state, 200000), 10); if (n_randint(state, 2)) { arb_set(c, a); arb_sqrt_newton(c, c, prec); } else { arb_sqrt_newton(c, a, prec); } arb_sqrt(d, a, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 100); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 100); flint_printf("\n\n"); flint_abort(); } arb_randtest(c, state, 1 + n_randint(state, 100000), 10); mag_zero(arb_radref(a)); if (n_randint(state, 2)) { arb_set(c, a); arb_sqrt_arf_newton(c, arb_midref(a), prec); } else { arb_sqrt_arf_newton(c, arb_midref(a), prec); } arb_sqrt_arf(d, arb_midref(a), prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 100); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 100); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { arb_set(c, a); arb_rsqrt_arf_newton(c, arb_midref(c), prec); } else { arb_rsqrt_arf_newton(c, arb_midref(a), prec); } /* BUG in MPFR 4.2.0 arb_rsqrt(d, a, prec); */ arb_sqrt(d, a, prec + 10); arb_inv(d, d, prec); if (!arb_overlaps(c, d)) { flint_printf("FAIL: containment (rsqrt)\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("a = "); arb_printd(a, 100); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 100); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 100); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sqrtpos.c000066400000000000000000000030051461254215100172630ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sqrtpos, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); do { arb_randtest(a, state, 1 + n_randint(state, 200), 10); } while (arb_contains_negative(a)); arb_sqrtpos(b, a, prec); arb_mul(c, b, b, prec); if (!arb_contains(c, a) || arb_contains_negative(b)) { flint_printf("FAIL: containment / positivity\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_sqrtpos(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sub.c000066400000000000000000000103701461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" TEST_FUNCTION_START(arb_sub, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t x, y, z; arb_init(a); arb_init(b); arb_init(c); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_sub(c, a, b, 2 + n_randint(state, 200)); fmpq_sub(z, x, y); if (!arb_contains_fmpq(c, z)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_sub(a, a, b, 2 + n_randint(state, 200)); fmpq_sub(z, x, y); if (!arb_contains_fmpq(a, z)) { flint_printf("FAIL: aliasing (c, a)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and b */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_sub(b, a, b, 2 + n_randint(state, 200)); fmpq_sub(z, x, y); if (!arb_contains_fmpq(b, z)) { flint_printf("FAIL: aliasing (c, b)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sub_arf.c000066400000000000000000000054171461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sub_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_sub_arf(c, a, x, prec); arb_sub(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arf_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_sub_arf(c, a, x, prec); arb_sub_arf(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sub_fmpz.c000066400000000000000000000054031461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_sub_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_sub_fmpz(c, a, x, prec); arb_sub(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_sub_fmpz(c, a, x, prec); arb_sub_fmpz(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sub_si.c000066400000000000000000000051701461254215100170410ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "long_extras.h" TEST_FUNCTION_START(arb_sub_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_sub_si(c, a, x, prec); arb_sub(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_sub_si(c, a, x, prec); arb_sub_si(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-sub_ui.c000066400000000000000000000051711461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "ulong_extras.h" TEST_FUNCTION_START(arb_sub_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_sub_ui(c, a, x, prec); arb_sub(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_sub_ui(c, a, x, prec); arb_sub_ui(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-submul.c000066400000000000000000000226371461254215100170730ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb.h" #ifndef mag_close #define mag_close mag_close int mag_close(const mag_t am, const mag_t bm) { arf_t t, a, b; int res1, res2; arf_init(t); arf_init(a); arf_init(b); arf_set_mag(a, am); arf_set_mag(b, bm); arf_mul_ui(t, b, 257, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(t, t, -8); res1 = arf_cmp(a, t) <= 0; arf_mul_ui(t, a, 257, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(t, t, -8); res2 = arf_cmp(b, t) <= 0; arf_clear(t); arf_clear(a); arf_clear(b); return res1 && res2; } #endif #ifndef arb_equal_mid_close_mag #define arb_equal_mid_close_mag arb_equal_mid_close_mag int arb_equal_mid_close_mag(const arb_t a, const arb_t b) { return arf_equal(arb_midref(a), arb_midref(b)) && (mag_close(arb_radref(a), arb_radref(b)) || /* If a's and b's centres are infinite but their radii are finite, the radii don't need to be close: they represent signed infinity regardless. If their centres are NaN, then we should ignore their radii. */ (arf_is_inf(arb_midref(a)) && arf_is_inf(arb_midref(b)) && mag_is_finite(arb_radref(a)) && mag_is_finite(arb_radref(b))) || (arf_is_nan(arb_midref(a)) && arf_is_nan(arb_midref(b)))); } #endif void arb_submul_naive(arb_t z, const arb_t x, const arb_t y, slong prec) { arb_t t; arb_init(t); arb_mul(t, x, y, ARF_PREC_EXACT); arb_sub(z, z, t, prec); arb_clear(t); } TEST_FUNCTION_START(arb_submul, state) { slong iter, iter2; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t x, y, z; arb_init(a); arb_init(b); arb_init(c); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_randtest(c, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); arb_get_rand_fmpq(z, state, c, 1 + n_randint(state, 200)); arb_submul(c, a, b, 2 + n_randint(state, 200)); fmpq_submul(z, x, y); if (!arb_contains_fmpq(c, z)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and a */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); fmpq_set(z, x); arb_submul(a, a, b, 2 + n_randint(state, 200)); fmpq_submul(z, x, y); if (!arb_contains_fmpq(a, z)) { flint_printf("FAIL: aliasing (c, a)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* aliasing of c and b */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b; fmpq_t x, y, z; arb_init(a); arb_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); arb_randtest(a, state, 1 + n_randint(state, 200), 10); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(y, state, b, 1 + n_randint(state, 200)); fmpq_set(z, y); arb_submul(b, a, b, 2 + n_randint(state, 200)); fmpq_submul(z, x, y); if (!arb_contains_fmpq(b, z)) { flint_printf("FAIL: aliasing (c, b)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); fmpq_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* main test */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z, v; slong prec; arb_init(x); arb_init(y); arb_init(z); arb_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arb_randtest_special(x, state, n_randint(state,2) ? 2000 : 200, 200); arb_randtest_special(y, state, n_randint(state,2) ? 2000 : 200, 200); arb_randtest_special(z, state, n_randint(state,2) ? 2000 : 200, 200); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 5)) { case 0: arb_set(v, z); arb_submul(z, x, y, prec); arb_submul_naive(v, x, y, prec); if (!arb_equal_mid_close_mag(z, v)) { flint_printf("FAIL!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 1: arb_set(y, x); arb_set(z, v); arb_submul(z, x, y, prec); arb_submul(v, x, x, prec); if (!arb_equal_mid_close_mag(z, v)) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 2: arb_set(v, x); arb_submul(v, x, x, prec); arb_submul(x, x, x, prec); if (!arb_equal_mid_close_mag(x, v)) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; case 3: arb_set(v, x); arb_submul(v, x, y, prec); arb_submul(x, x, y, prec); if (!arb_equal_mid_close_mag(x, v)) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; default: arb_set(v, x); arb_submul(v, x, y, prec); arb_submul(x, y, x, prec); if (!arb_equal_mid_close_mag(x, v)) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("v = "); arb_print(v); flint_printf("\n\n"); flint_abort(); } break; } } arb_clear(x); arb_clear(y); arb_clear(z); arb_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-submul_arf.c000066400000000000000000000055141461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_submul_arf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_set(d, c); arb_submul_arf(c, a, x, prec); arb_submul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arf_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; arf_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arf_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); arf_randtest_special(x, state, 1 + n_randint(state, 2000), 100); prec = 2 + n_randint(state, 2000); arb_set_arf(b, x); arb_set(c, a); arb_submul_arf(c, a, x, prec); arb_submul_arf(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-submul_fmpz.c000066400000000000000000000055001461254215100201150ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_submul_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_set(d, c); arb_submul_fmpz(c, a, x, prec); arb_submul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); fmpz_clear(x); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; fmpz_t x; slong prec; arb_init(a); arb_init(b); arb_init(c); fmpz_init(x); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); fmpz_randtest(x, state, 1 + n_randint(state, 2000)); prec = 2 + n_randint(state, 2000); arb_set_fmpz(b, x); arb_set(c, a); arb_submul_fmpz(c, a, x, prec); arb_submul_fmpz(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-submul_si.c000066400000000000000000000052651461254215100175640ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "long_extras.h" TEST_FUNCTION_START(arb_submul_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_set(d, c); arb_submul_si(c, a, x, prec); arb_submul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_set(c, a); arb_submul_si(c, a, x, prec); arb_submul_si(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-submul_ui.c000066400000000000000000000052661461254215100175670ustar00rootroot00000000000000/* Copyright (C) 2012-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "ulong_extras.h" TEST_FUNCTION_START(arb_submul_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, d; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_set(d, c); arb_submul_ui(c, a, x, prec); arb_submul(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; ulong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = n_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_ui(b, x); arb_set(c, a); arb_submul_ui(c, a, x, prec); arb_submul_ui(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-tan_pi.c000066400000000000000000000064371461254215100170360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_tan_pi, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(x); arb_init(y); arb_init(a); arb_init(b); arb_init(c); arb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); arb_tan_pi(a, x, prec1); arb_tan_pi(b, x, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } /* compare with tan */ arb_const_pi(c, prec1); arb_mul(y, x, c, prec1); arb_tan(c, y, prec1); if (!arb_overlaps(a, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_tan_pi(x, x, prec1); if (!arb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(a); arb_clear(b); arb_clear(c); } /* Check a few special points. */ { arb_t x, y; slong i, prec; arb_init(x); arb_init(y); prec = 32; for (i = -1; i <= 1; i++) { int arbitrary_integer = 7; arb_set_d(x, arbitrary_integer*i); arb_tan_pi(y, x, prec); if (!arb_is_zero(y)) { flint_printf("FAIL: (integer)\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } arb_set_d(x, arbitrary_integer*i + 0.5); arb_tan_pi(y, x, prec); if (arb_is_finite(y)) { flint_printf("FAIL: (integer + 1/2)\n"); flint_printf("x = "); arb_printd(x, 30); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 30); flint_printf("\n\n"); flint_abort(); } } } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-tanh.c000066400000000000000000000050531461254215100165070ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_tanh, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, a, b, c, d; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(x); arb_init(y); arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_precise(x, state, 1 + n_randint(state, 1000), 100); arb_randtest_precise(y, state, 1 + n_randint(state, 1000), 100); arb_tanh(a, x, prec1); arb_tanh(b, x, prec2); /* check consistency */ if (!arb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } /* check tanh(x+y) = (tanh(x) + tanh(y)) / (1 + tanh(x) tanh(y)) */ arb_add(b, x, y, prec1); arb_tanh(b, b, prec1); arb_tanh(c, y, prec1); arb_add(d, a, c, prec1); arb_mul(c, a, c, prec1); arb_add_ui(c, c, 1, prec1); arb_div(d, d, c, prec1); if (!arb_overlaps(b, d)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); flint_abort(); } arb_tanh(x, x, prec1); if (!arb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-trim.c000066400000000000000000000035361461254215100165340ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_trim, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y; slong acc1, acc2; int accuracy_ok; arb_init(x); arb_init(y); arb_randtest_special(x, state, 1000, 100); arb_trim(y, x); if (!arb_contains(y, x)) { flint_printf("FAIL (containment):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(x); acc2 = arb_rel_accuracy_bits(y); accuracy_ok = (acc1 < 0 && acc2 <= acc1) || (acc2 >= acc1 - 1); if (!accuracy_ok) { flint_printf("FAIL (accuracy):\n\n"); flint_printf("x: %wd, y = %wd\n\n", acc1, acc2); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_abort(); } arb_trim(x, x); if (!arb_equal(y, x)) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-ui_pow_ui.c000066400000000000000000000031371461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_ui_pow_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r1, r2; ulong a, exp; slong prec; a = n_randtest(state); exp = n_randtest(state); if (n_randint(state, 10) == 0) prec = 2 + n_randint(state, 5000); else prec = 2 + n_randint(state, 500); arb_init(r1); arb_init(r2); arb_randtest(r1, state, 1 + n_randint(state, 1000), 200); arb_randtest(r2, state, 1 + n_randint(state, 1000), 200); arb_set_ui(r1, a); arb_pow_ui(r1, r1, exp, prec); arb_ui_pow_ui(r2, a, exp, prec); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = %wu\n\n", a); flint_printf("exp = %wu\n\n", exp); flint_printf("prec = %wd\n\n", prec); flint_printf("r1 = "); arb_print(r1); flint_printf("\n\n"); flint_printf("r2 = "); arb_print(r2); flint_printf("\n\n"); flint_abort(); } arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-union.c000066400000000000000000000036241461254215100167070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_union, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z; slong prec; int alias; arb_init(x); arb_init(y); arb_init(z); arb_randtest_special(x, state, 200, 10); arb_randtest_special(y, state, 200, 10); arb_randtest_special(z, state, 200, 10); prec = 2 + n_randint(state, 200); arb_union(z, x, y, prec); if (!arb_contains(z, x) || !arb_contains(z, y)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { arb_union(x, x, y, prec); alias = arb_equal(x, z); } else { arb_union(y, x, y, prec); alias = arb_equal(y, z); } if (!alias) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("x = "); arb_print(x); flint_printf("\n\n"); flint_printf("y = "); arb_print(y); flint_printf("\n\n"); flint_printf("z = "); arb_print(z); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-urandom.c000066400000000000000000000033521461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #define N 10000 TEST_FUNCTION_START(arb_urandom, state) { slong iter; slong prec; arb_ptr rand; arb_t m; /* mean */ arb_t s; /* variance */ arb_t mp; arb_t sp; arb_t tmp; arb_init(m); arb_init(s); arb_init(mp); arb_init(sp); arb_init(tmp); rand = _arb_vec_init(N); prec = 299; for (iter = 0; iter < N; iter++) { arb_urandom(rand + iter, state, prec); arb_add(m, m, rand + iter, prec); } arb_div_si(m, m, N, prec); for (iter = 0; iter < N; iter++) { arb_sub(tmp, rand + iter, m, prec); arb_sqr(tmp, tmp, prec); arb_add(s, s, tmp, prec); } arb_div_si(s, s, N, prec); /* one percent deviation */ arb_set_str(mp, "0.5 +/- 0.005", prec); arb_set_str(sp, "0.083333 +/- 0.00083", prec); if (!arb_contains(mp, m)) { flint_printf("FAIL: mean\n\n"); flint_printf("m = "); arb_printd(m, 15); flint_printf("\n\n"); flint_abort(); } if (!arb_contains(sp, s)) { flint_printf("FAIL: variance\n\n"); flint_printf("s = "); arb_printd(s, 15); flint_printf("\n\n"); flint_abort(); } _arb_vec_clear(rand, N); arb_clear(m); arb_clear(s); arb_clear(mp); arb_clear(sp); arb_clear(tmp); TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta.c000066400000000000000000000024641461254215100165230ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(arb_zeta, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 500); prec2 = prec1 + 30; arb_init(a); arb_init(b); arb_init(c); arb_randtest_precise(a, state, 1 + n_randint(state, 500), 5); arb_zeta(b, a, prec1); arb_zeta(c, a, prec2); if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta_ui.c000066400000000000000000000032611461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_zeta_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; ulong n; mpfr_t s; slong prec, accuracy; prec = 2 + n_randint(state, 1 << n_randint(state, 14)); arb_init(r); mpfr_init2(s, prec + 100); do { n = n_randint(state, 1 << n_randint(state, 10)); } while (n == 1); arb_zeta_ui(r, n, prec); mpfr_zeta_ui(s, n, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); mpfr_printf("%.275Rf\n", s); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec); flint_printf("n = %wu\n\n", n); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta_ui_asymp.c000066400000000000000000000025171461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_zeta_ui_asymp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; ulong n; mpfr_t s; slong prec; prec = 2 + n_randint(state, 1 << n_randint(state, 10)); arb_init(r); mpfr_init2(s, prec + 100); n = 2 + n_randint(state, 1 << n_randint(state, 10)); arb_zeta_ui_asymp(r, n, prec); mpfr_zeta_ui(s, n, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); mpfr_printf("%.275Rf\n", s); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta_ui_bernoulli.c000066400000000000000000000032551461254215100212720ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_zeta_ui_bernoulli, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; ulong n; mpfr_t s; slong prec, accuracy; prec = 2 + n_randint(state, 1 << n_randint(state, 14)); arb_init(r); mpfr_init2(s, prec + 100); do { n = n_randint(state, 1 << n_randint(state, 10)); } while (n % 2 || n == 0); arb_zeta_ui_bernoulli(r, n, prec); mpfr_zeta_ui(s, n, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); mpfr_printf("%.275Rf\n", s); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta_ui_borwein_bsplit.c000066400000000000000000000032421461254215100223150ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_zeta_ui_borwein_bsplit, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; ulong n; mpfr_t s; slong prec, accuracy; prec = 2 + n_randint(state, 1 << n_randint(state, 14)); arb_init(r); mpfr_init2(s, prec + 100); do { n = n_randint(state, 1 << n_randint(state, 10)); } while (n == 1); arb_zeta_ui_borwein_bsplit(r, n, prec); mpfr_zeta_ui(s, n, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); mpfr_printf("%.275Rf\n", s); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta_ui_euler_product.c000066400000000000000000000033111461254215100221440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_zeta_ui_euler_product, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r; ulong n; mpfr_t s; slong prec, accuracy; do { n = n_randint(state, 1 << n_randint(state, 10)); } while (n < 6); prec = 2 + n_randint(state, n * FLINT_BIT_COUNT(n)); arb_init(r); mpfr_init2(s, prec + 100); arb_zeta_ui_euler_product(r, n, prec); mpfr_zeta_ui(s, n, MPFR_RNDN); if (!arb_contains_mpfr(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); mpfr_printf("%.275Rf\n", s); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec); flint_printf("n = %wu\n\n", n); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } arb_clear(r); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta_ui_vec.c000066400000000000000000000036471461254215100200610ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_zeta_ui_vec, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr r; ulong n; slong i, num; mpfr_t s; slong prec, accuracy; prec = 2 + n_randint(state, 1 << n_randint(state, 13)); num = 1 + n_randint(state, 20); r = _arb_vec_init(num); mpfr_init2(s, prec + 100); do { n = n_randint(state, 1 << n_randint(state, 10)); } while (n < 2); arb_zeta_ui_vec(r, n, num, prec); for (i = 0; i < num; i++) { mpfr_zeta_ui(s, n + i, MPFR_RNDN); if (!arb_contains_mpfr(r + i, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n\n", n + i); flint_printf("r = "); arb_printd(r + i, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); mpfr_printf("%.275Rf\n", s); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r + i); if (accuracy < prec - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec); flint_printf("n = %wu\n\n", n + i); flint_printf("r = "); arb_printd(r + i, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } _arb_vec_clear(r, num); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/test/t-zeta_ui_vec_borwein.c000066400000000000000000000040001461254215100215660ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arb_zeta_ui_vec_borwein, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_ptr r; ulong n; slong i, num, step; mpfr_t s; slong prec, accuracy; prec = 2 + n_randint(state, 1 << n_randint(state, 13)); num = 1 + n_randint(state, 20); step = 1 + n_randint(state, 5); r = _arb_vec_init(num); mpfr_init2(s, prec + 100); do { n = n_randint(state, 1 << n_randint(state, 10)); } while (n < 2); arb_zeta_ui_vec_borwein(r, n, num, step, prec); for (i = 0; i < num; i++) { mpfr_zeta_ui(s, n + i * step, MPFR_RNDN); if (!arb_contains_mpfr(r + i, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("n = %wu\n\n", n + i * step); flint_printf("r = "); arb_printd(r + i, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); mpfr_printf("%.275Rf\n", s); flint_printf("\n\n"); flint_abort(); } accuracy = arb_rel_accuracy_bits(r + i); if (accuracy < prec - 4) { flint_printf("FAIL: accuracy = %wd, prec = %wd\n\n", accuracy, prec); flint_printf("n = %wu\n\n", n + i * step); flint_printf("r = "); arb_printd(r + i, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } _arb_vec_clear(r, num); mpfr_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb/trim.c000066400000000000000000000025021461254215100153040ustar00rootroot00000000000000/* Copyright (C) 2013-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #define TRIM_PADDING 16 void arb_trim(arb_t y, const arb_t x) { if (mag_is_zero(arb_radref(x)) || arf_is_special(arb_midref(x))) { arb_set(y, x); } else if (mag_is_special(arb_radref(x))) { /* midpoint must be finite, so set to 0 +/- inf */ arb_zero_pm_inf(y); } else { slong bits, accuracy; bits = arb_bits(x); accuracy = arb_rel_accuracy_bits(x); if (accuracy < -TRIM_PADDING) { mag_t t; /* set to 0 +/- r */ mag_init(t); arf_get_mag(t, arb_midref(x)); mag_add(arb_radref(y), t, arb_radref(x)); mag_clear(t); arf_zero(arb_midref(y)); } else if (accuracy < bits - TRIM_PADDING) { arb_set_round(y, x, FLINT_MAX(0, accuracy) + TRIM_PADDING); } else { arb_set(y, x); } } } flint-3.1.3/src/arb/trunc.c000066400000000000000000000020031461254215100154600ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_trunc(arb_t res, const arb_t x, slong prec) { if (arb_contains_zero(x)) { arb_t a; arb_init(a); mag_one(arb_radref(a)); if (arb_contains(a, x)) { arb_zero(res); } else { arb_t b; arb_init(b); arb_floor(a, x, prec); arb_ceil(b, x, prec); arb_union(res, a, b, prec); arb_clear(b); } arb_clear(a); } else if (arf_sgn(arb_midref(x)) > 0) { arb_floor(res, x, prec); } else { arb_ceil(res, x, prec); } } flint-3.1.3/src/arb/ui_pow_ui.c000066400000000000000000000235161461254215100163400ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb.h" #include "mpn_extras.h" void arb_si_pow_ui(arb_t res, slong b, ulong e, slong prec) { arb_ui_pow_ui(res, UI_ABS_SI(b), e, prec); if ((e & 1) && b < 0) arb_neg(res, res); } void arb_set_round_ui(arb_t res, ulong lo, slong prec) { if (lo == 0) { arb_zero(res); } else { int inexact; inexact = _arf_set_round_ui(arb_midref(res), lo, 0, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec); else mag_zero(arb_radref(res)); } } void arb_set_round_uiui(arb_t res, ulong hi, ulong lo, slong prec) { if (hi == 0 && lo == 0) { arb_zero(res); } else { int inexact; slong fix; inexact = _arf_set_round_uiui(arb_midref(res), &fix, hi, lo, 0, prec, ARB_RND); _fmpz_demote(ARF_EXPREF(arb_midref(res))); ARF_EXP(arb_midref(res)) = 2 * FLINT_BITS + fix; if (inexact) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec); else mag_zero(arb_radref(res)); } } void arb_ui_pow_ui(arb_t res, ulong a, ulong exp, slong prec) { slong wp, aexp, awidth, trailing, wp_limbs; slong exp_fix, alloc, leading; int inexact, i, ebits; mp_ptr yman, tmp; mp_size_t yn; mp_limb_t yexp_hi, yexp_lo, aman, aodd, hi, lo; ARF_MUL_TMP_DECL if (exp <= 2) { if (exp == 0) { arb_one(res); } else if (exp == 1) { arb_set_round_ui(res, a, prec); } else { mp_limb_t hi, lo; umul_ppmm(hi, lo, a, a); arb_set_round_uiui(res, hi, lo, prec); } return; } if (a <= 1) { arb_set_ui(res, a); return; } aexp = FLINT_BIT_COUNT(a); trailing = flint_ctz(a); awidth = aexp - trailing; /* a = power of two */ if (awidth == 1) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, exp); fmpz_mul_ui(t, t, aexp - 1); arb_one(res); arb_mul_2exp_fmpz(res, res, t); fmpz_clear(t); return; } umul_ppmm(hi, lo, awidth, exp); if (hi == 0) prec = FLINT_MIN(prec, lo); wp = prec + 2 * FLINT_BIT_COUNT(exp) + 4; wp_limbs = (wp + FLINT_BITS - 1) / FLINT_BITS; if (FLINT_BITS == 32 && wp_limbs % 2) wp_limbs++; /* Algorithm: as long as the result is exact, work with powers of the odd part of a as an integer. As soon as we exceed wp_limbs, switch to a floating-point product with exactly wp_limbs (it is possible that we get trailing zero limbs after this point so that the number of limbs could be reduced temporarily, but this is not worth the trouble). */ alloc = 4 * (wp_limbs + 2); ARF_MUL_TMP_ALLOC(tmp, alloc) yman = tmp + 2 * (wp_limbs + 2); /* a as a top-aligned mantissa */ aman = a << (FLINT_BITS - aexp); /* a as a bottom-aligned mantissa */ aodd = a >> trailing; /* y = a */ yn = 1; yman[0] = aodd; /* yexp will initially be the bottom exponent. we convert to a floating-point (top) exponent only when the result becomes inexact */ yexp_lo = trailing; /* the exponent can be two words wide (we only need this in the inexact case) */ yexp_hi = 0; inexact = 0; ebits = FLINT_BIT_COUNT(exp); for (i = ebits - 2; i >= 0; i--) { /* Integer case */ if (!inexact) { /* Inline code for small integers */ if (yn == 1) { yexp_lo *= 2; umul_ppmm(yman[1], yman[0], yman[0], yman[0]); yn += (yman[1] != 0); if (exp & (UWORD(1) << i)) { yexp_lo += trailing; if (yn == 1) { umul_ppmm(yman[1], yman[0], yman[0], aodd); yn += (yman[1] != 0); } else { mp_limb_t y0, y1; y0 = yman[0]; y1 = yman[1]; FLINT_MPN_MUL_2X1(yman[2], yman[1], yman[0], y1, y0, aodd); yn += (yman[2] != 0); } } } else { /* todo: if 2 * yn is significantly larger than wp_limbs, we might want to go to the floating-point code here */ yexp_lo *= 2; flint_mpn_sqr(tmp, yman, yn); yn = 2 * yn; yn -= (tmp[yn - 1] == 0); if (exp & (UWORD(1) << i)) { yexp_lo += trailing; yman[yn] = mpn_mul_1(yman, tmp, yn, aodd); yn += (yman[yn] != 0); } else { flint_mpn_copyi(yman, tmp, yn); } } /* convert to floating-point form */ /* todo: redundant if this is the last iteration */ if (yn > wp_limbs) { inexact = 1; leading = flint_clz(yman[yn - 1]); yexp_lo = yexp_lo + yn * FLINT_BITS - leading; if (leading == 0) flint_mpn_copyi(yman, yman + yn - wp_limbs, wp_limbs); else mpn_rshift(yman, yman + yn - wp_limbs - 1, wp_limbs + 1, FLINT_BITS - leading); yn = wp_limbs; } continue; } /* y = y^2: exponent */ yexp_hi = (yexp_hi << 1) | (yexp_lo >> (FLINT_BITS - 1)); yexp_lo <<= 1; /* special case for 1-limb precision */ /* note: we must have yn == 1 here if wp_limbs == 1 */ if (wp_limbs == 1) { mp_limb_t hi, lo; /* y = y^2: mantissa */ umul_ppmm(hi, lo, yman[0], yman[0]); if (!(hi >> (FLINT_BITS - 1))) { hi = (hi << 1) | (lo >> (FLINT_BITS - 1)); sub_ddmmss(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, 1); } yman[0] = hi; if (exp & (UWORD(1) << i)) { /* y = y * a: exponent */ add_ssaaaa(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, aexp); /* y = y * a: mantissa */ umul_ppmm(hi, lo, yman[0], aman); if (!(hi >> (FLINT_BITS - 1))) { hi = (hi << 1) | (lo >> (FLINT_BITS - 1)); sub_ddmmss(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, 1); } yman[0] = hi; } continue; } /* y = y^2: mantissa */ if (yn >= 25 && yn <= 10000) /* use mpfr for sqrhi */ { mpfr_t zf, xf; zf->_mpfr_d = tmp; zf->_mpfr_prec = wp_limbs * FLINT_BITS; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; xf->_mpfr_d = yman; xf->_mpfr_prec = yn * FLINT_BITS; xf->_mpfr_sign = 1; xf->_mpfr_exp = 0; mpfr_sqr(zf, xf, MPFR_RNDD); if (zf->_mpfr_exp != 0) sub_ddmmss(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, 1); yn = wp_limbs; } else /* or exactly */ { flint_mpn_sqr(tmp, yman, yn); yn = 2 * yn; } if (yn < wp_limbs) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* y = y * a */ if (exp & (UWORD(1) << i)) { tmp[yn] = mpn_mul_1(tmp + yn - wp_limbs, tmp + yn - wp_limbs, wp_limbs, aman); yn++; add_ssaaaa(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, aexp); } /* move result from tmp to yman, and normalize; at this point there can be 0, 1 or 2 leading zeros */ if (tmp[yn - 1] >> (FLINT_BITS - 1)) { flint_mpn_copyi(yman, tmp + yn - wp_limbs, wp_limbs); } else { /* assumed so that we can read one extra limb with mpn_rshift */ /* yn == wp_limbs is only possible if we used mpfr_sqr above and there was no multiplication by a, but in that case there are 0 leading zeros anyway */ if (yn == wp_limbs) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (tmp[yn - 1] >> (FLINT_BITS - 2)) { mpn_rshift(yman, tmp + yn - wp_limbs - 1, wp_limbs + 1, FLINT_BITS - 1); sub_ddmmss(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, 1); } else { mpn_rshift(yman, tmp + yn - wp_limbs - 1, wp_limbs + 1, FLINT_BITS - 2); sub_ddmmss(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, 2); } } yn = wp_limbs; } /* convert bottom exponent to floating-point (top) exponent */ if (!inexact) yexp_lo = yexp_lo + yn * FLINT_BITS; inexact |= _arf_set_round_mpn(arb_midref(res), &exp_fix, yman, yn, 0, prec, ARF_RND_DOWN); if (exp_fix) sub_ddmmss(yexp_hi, yexp_lo, yexp_hi, yexp_lo, 0, -exp_fix); fmpz_set_uiui(ARF_EXPREF(arb_midref(res)), yexp_hi, yexp_lo); if (inexact) arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec - 1); else mag_zero(arb_radref(res)); ARF_MUL_TMP_FREE(tmp, alloc) } flint-3.1.3/src/arb/union.c000066400000000000000000000024331461254215100154640ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_union(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t left, right, t, xr, yr; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) { arb_indeterminate(z); return; } if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y))) { arb_zero_pm_inf(z); return; } arf_init(left); arf_init(right); arf_init(t); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); arf_sub(left, arb_midref(x), xr, prec, ARF_RND_FLOOR); arf_sub(t, arb_midref(y), yr, prec, ARF_RND_FLOOR); arf_min(left, left, t); arf_add(right, arb_midref(x), xr, prec, ARF_RND_CEIL); arf_add(t, arb_midref(y), yr, prec, ARF_RND_CEIL); arf_max(right, right, t); arb_set_interval_arf(z, left, right, prec); arf_clear(left); arf_clear(right); arf_clear(t); } flint-3.1.3/src/arb/urandom.c000066400000000000000000000013721461254215100160020ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_urandom(arb_t x, flint_rand_t state, slong bits) { slong prec = bits; fmpz_t n; fmpz_t t; prec += 128; fmpz_init(n); fmpz_one(n); fmpz_mul_2exp(n, n, (ulong) prec); fmpz_init(t); fmpz_randm(t, state, n); arb_set_round_fmpz(x, t, bits); arb_mul_2exp_si(x, x, -prec); fmpz_clear(n); fmpz_clear(t); } flint-3.1.3/src/arb/vec_clear.c000066400000000000000000000010231461254215100162510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void _arb_vec_clear(arb_ptr v, slong n) { slong i; for (i = 0; i < n; i++) arb_clear(v + i); flint_free(v); } flint-3.1.3/src/arb/vec_get_mag.c000066400000000000000000000014151461254215100165730ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void _arb_vec_get_mag(mag_t bound, arb_srcptr vec, slong len) { if (len < 1) { mag_zero(bound); } else { mag_t t; slong i; arb_get_mag(bound, vec); mag_init(t); for (i = 1; i < len; i++) { arb_get_mag(t, vec + i); mag_max(bound, bound, t); } mag_clear(t); } } flint-3.1.3/src/arb/vec_init.c000066400000000000000000000011061461254215100161300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" arb_ptr _arb_vec_init(slong n) { slong i; arb_ptr v = (arb_ptr) flint_malloc(sizeof(arb_struct) * n); for (i = 0; i < n; i++) arb_init(v + i); return v; } flint-3.1.3/src/arb/vec_set_powers.c000066400000000000000000000014451461254215100173650ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void _arb_vec_set_powers(arb_ptr xs, const arb_t x, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { if (i == 0) arb_one(xs + i); else if (i == 1) arb_set_round(xs + i, x, prec); else if (i % 2 == 0) arb_mul(xs + i, xs + i / 2, xs + i / 2, prec); else arb_mul(xs + i, xs + i - 1, x, prec); } } flint-3.1.3/src/arb/zero.c000066400000000000000000000007461461254215100153200ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_zero(arb_t x) { arf_zero(arb_midref(x)); mag_zero(arb_radref(x)); } flint-3.1.3/src/arb/zeta.c000066400000000000000000000011311461254215100152710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb.h" void arb_zeta(arb_t y, const arb_t s, slong prec) { acb_t t; acb_init(t); acb_set_arb(t, s), acb_zeta(t, t, prec); arb_set(y, acb_realref(t)); acb_clear(t); } flint-3.1.3/src/arb/zeta_ui.c000066400000000000000000000040441461254215100157740ustar00rootroot00000000000000/* Copyright (C) 2012, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arith.h" #include "arb.h" /* The constant factor is nearly optimal up to at least 300000 bits. */ static double euler_product_cutoff(double prec) { if (prec > 200 && prec < 15000) /* This range has a slight "bulge". */ return 0.39 * pow(prec, 0.8); else return 7 + 0.535 * prec / log(prec); } void arb_zeta_ui(arb_t x, ulong n, slong prec) { if (n == 0) { arb_set_si(x, -1); arb_mul_2exp_si(x, x, -1); } else if (n == 1) { arb_indeterminate(x); } /* fast detection of asymptotic case */ else if (n > 0.7 * prec) { arb_zeta_ui_asymp(x, n, prec); } else { /* even */ if (n % 2 == 0) { if (((prec < 10000) && (n < 40 + 0.11*prec)) || ((prec >= 10000) && (arith_bernoulli_number_size(n) * 0.9 < prec))) { arb_zeta_ui_bernoulli(x, n, prec); } else { arb_zeta_ui_euler_product(x, n, prec); } } else { if (n == 3) { arb_const_apery(x, prec); } else if (n < prec * 0.0006) { /* small odd n, extremely high precision */ arb_zeta_ui_borwein_bsplit(x, n, prec); } else if (n > euler_product_cutoff(prec)) { /* large n */ arb_zeta_ui_euler_product(x, n, prec); } else { /* fallback */ arb_zeta_ui_vec_borwein(x, n, 1, 0, prec); } } } } flint-3.1.3/src/arb/zeta_ui_bernoulli.c000066400000000000000000000020201461254215100200370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb.h" #include "bernoulli.h" void arb_zeta_ui_bernoulli(arb_t x, ulong n, slong prec) { fmpq_t b; arb_t t, f; slong wp; if (n % 2) flint_throw(FLINT_ERROR, "(%s)\n", __func__); wp = prec + FLINT_BIT_COUNT(n) + 2; fmpq_init(b); arb_init(t); arb_init(f); bernoulli_fmpq_ui(b, n); arb_set_fmpq(x, b, wp); arb_const_pi(t, wp); arb_mul_2exp_si(t, t, 1); arb_pow_ui(t, t, n, wp); arb_fac_ui(f, n, wp); arb_div(t, t, f, wp); arb_mul(x, x, t, wp); arb_abs(x, x); arb_mul_2exp_si(x, x, -1); arb_clear(t); arb_clear(f); fmpq_clear(b); } flint-3.1.3/src/arb/zeta_ui_borwein_bsplit.c000066400000000000000000000076441461254215100211070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" /* With parameter n, the error is bounded by 3/(3+sqrt(8))^n */ #define ERROR_A 1.5849625007211561815 /* log2(3) */ #define ERROR_B 2.5431066063272239453 /* log2(3+sqrt(8)) */ typedef struct { arb_t A; arb_t B; arb_t C; arb_t D; arb_t Q1; arb_t Q2; arb_t Q3; } zeta_bsplit_state; typedef zeta_bsplit_state zeta_bsplit_t[1]; static inline void zeta_bsplit_init(zeta_bsplit_t S) { arb_init(S->A); arb_init(S->B); arb_init(S->C); arb_init(S->D); arb_init(S->Q1); arb_init(S->Q2); arb_init(S->Q3); } static inline void zeta_bsplit_clear(zeta_bsplit_t S) { arb_clear(S->A); arb_clear(S->B); arb_clear(S->C); arb_clear(S->D); arb_clear(S->Q1); arb_clear(S->Q2); arb_clear(S->Q3); } static inline void zeta_coeff_k(zeta_bsplit_t S, slong k, slong n, slong s) { arb_set_si(S->D, 2 * (n + k)); arb_mul_si(S->D, S->D, n - k, ARF_PREC_EXACT); arb_set_si(S->Q1, k + 1); arb_mul_si(S->Q1, S->Q1, 2*k + 1, ARF_PREC_EXACT); if (k == 0) { arb_zero(S->A); arb_one(S->Q2); } else { arb_set_si(S->A, k % 2 ? 1 : -1); arb_mul(S->A, S->A, S->Q1, ARF_PREC_EXACT); arb_ui_pow_ui(S->Q2, k, s, ARF_PREC_EXACT); } arb_mul(S->Q3, S->Q1, S->Q2, ARF_PREC_EXACT); arb_zero(S->B); arb_set(S->C, S->Q1); } static void zeta_bsplit(zeta_bsplit_t L, slong a, slong b, slong n, slong s, int cont, slong bits) { if (a + 1 == b) { zeta_coeff_k(L, a, n, s); } else { zeta_bsplit_t R; slong m = (a + b) / 2; zeta_bsplit(L, m, b, n, s, 1, bits); zeta_bsplit_init(R); zeta_bsplit(R, a, m, n, s, 1, bits); arb_mul(L->B, L->B, R->D, bits); arb_addmul(L->B, L->A, R->C, bits); arb_mul(L->B, L->B, R->Q2, bits); arb_addmul(L->B, R->B, L->Q3, bits); arb_mul(L->A, L->A, R->Q3, bits); arb_addmul(L->A, R->A, L->Q3, bits); arb_mul(L->C, L->C, R->D, bits); arb_addmul(L->C, R->C, L->Q1, bits); if (cont) { arb_mul(L->D, L->D, R->D, bits); arb_mul(L->Q2, L->Q2, R->Q2, bits); } arb_mul(L->Q1, L->Q1, R->Q1, bits); arb_mul(L->Q3, L->Q3, R->Q3, bits); zeta_bsplit_clear(R); } } /* The error for eta(s) is bounded by 3/(3+sqrt(8))^n */ void mag_borwein_error(mag_t err, slong n) { /* upper bound for 1/(3+sqrt(8)) */ mag_set_ui_2exp_si(err, 736899889, -32); mag_pow_ui(err, err, n); mag_mul_ui(err, err, 3); } void arb_zeta_ui_borwein_bsplit(arb_t x, ulong s, slong prec) { zeta_bsplit_t sum; mag_t err; slong wp, n; /* zeta(0) = -1/2 */ if (s == 0) { arb_set_si(x, -1); arb_mul_2exp_si(x, x, -1); return; } if (s == 1) { flint_throw(FLINT_ERROR, "zeta_ui_borwein_bsplit: zeta(1)"); } n = prec / ERROR_B + 2; wp = prec + 30; zeta_bsplit_init(sum); zeta_bsplit(sum, 0, n + 1, n, s, 0, wp); /* A/Q3 - B/Q3 / (C/Q1) = (A*C - B*Q1) / (Q3*C) */ arb_mul(sum->A, sum->A, sum->C, wp); arb_mul(sum->B, sum->B, sum->Q1, wp); arb_sub(sum->A, sum->A, sum->B, wp); arb_mul(sum->Q3, sum->Q3, sum->C, wp); arb_div(sum->C, sum->A, sum->Q3, wp); mag_init(err); mag_borwein_error(err, n); mag_add(arb_radref(sum->C), arb_radref(sum->C), err); mag_clear(err); /* convert from eta(s) to zeta(s) */ arb_div_2expm1_ui(x, sum->C, s - 1, wp); arb_mul_2exp_si(x, x, s - 1); zeta_bsplit_clear(sum); } flint-3.1.3/src/arb/zeta_ui_euler_product.c000066400000000000000000000016341461254215100207320ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "acb_dirichlet.h" void arb_zeta_inv_ui_euler_product(arb_t z, ulong s, slong prec) { const signed char chi[1] = {1}; _acb_dirichlet_euler_product_real_ui(z, s, chi, 1, 1, prec); } void arb_zeta_ui_euler_product(arb_t z, ulong s, slong prec) { const signed char chi[1] = {1}; _acb_dirichlet_euler_product_real_ui(z, s, chi, 1, 0, prec); } void arb_zeta_ui_asymp(arb_t z, ulong s, slong prec) { const signed char chi[1] = {1}; _acb_dirichlet_euler_product_real_ui(z, s, chi, 1, 0, prec); } flint-3.1.3/src/arb/zeta_ui_vec.c000066400000000000000000000021631461254215100166310ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_zeta_ui_vec(arb_ptr x, ulong start, slong num, slong prec) { slong i, num_odd, num_even, start_odd; arb_ptr tmp; num_odd = num / 2 + (start & num & 1); num_even = num - num_odd; start_odd = start % 2; arb_zeta_ui_vec_even(x, start + start_odd, num_even, prec); arb_zeta_ui_vec_odd(x + num_even, start + !start_odd, num_odd, prec); /* interleave */ tmp = flint_malloc(sizeof(arb_struct) * num); for (i = 0; i < num_even; i++) tmp[i] = x[i]; for (i = 0; i < num_odd; i++) tmp[num_even + i] = x[num_even + i]; for (i = 0; i < num_even; i++) x[start_odd + 2 * i] = tmp[i]; for (i = 0; i < num_odd; i++) x[!start_odd + 2 * i] = tmp[num_even + i]; flint_free(tmp); } flint-3.1.3/src/arb/zeta_ui_vec_borwein.c000066400000000000000000000045711461254215100203630ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "arb.h" /* With parameter n, the error is bounded by 3/(3+sqrt(8))^n */ #define ERROR_A 1.5849625007211561815 /* log2(3) */ #define ERROR_B 2.5431066063272239453 /* log2(3+sqrt(8)) */ void mag_borwein_error(mag_t err, slong n); void arb_zeta_ui_vec_borwein(arb_ptr z, ulong start, slong num, ulong step, slong prec) { slong j, k, s, n, wp; fmpz_t c, d, t, u; fmpz * zeta; mag_t err; if (num < 1) return; wp = prec + FLINT_BIT_COUNT(prec); n = wp / 2.5431066063272239453 + 1; fmpz_init(c); fmpz_init(d); fmpz_init(t); fmpz_init(u); zeta = _fmpz_vec_init(num); fmpz_set_ui(c, 1); fmpz_mul_2exp(c, c, 2 * n - 1); fmpz_set(d, c); for (k = n; k > 0; k--) { /* divide by first k^s */ fmpz_ui_pow_ui(u, k, start); fmpz_tdiv_q(t, d, u); if (k % 2 == 0) fmpz_neg(t, t); fmpz_add(zeta, zeta, t); /* remaining k^s */ fmpz_ui_pow_ui(u, k, step); for (j = 1; j < num; j++) { fmpz_tdiv_q(t, t, u); fmpz_add(zeta + j, zeta + j, t); } /* hypergeometric recurrence */ fmpz_mul2_uiui(c, c, k, 2 * k - 1); fmpz_divexact2_uiui(c, c, 2 * (n - k + 1), n + k - 1); fmpz_add(d, d, c); } mag_init(err); mag_borwein_error(err, n); for (k = 0; k < num; k++) { arb_ptr x = z + k; s = start + step * k; arb_set_fmpz(x, zeta + k); /* the error in each term in the main loop is < 2 */ mag_set_ui(arb_radref(x), 2 * n); arb_div_fmpz(x, x, d, wp); /* mathematical error for eta(s), bounded by 3/(3+sqrt(8))^n */ mag_add(arb_radref(x), arb_radref(x), err); /* convert from eta(s) to zeta(s) */ arb_div_2expm1_ui(x, x, s - 1, wp); arb_mul_2exp_si(x, x, s - 1); } mag_clear(err); fmpz_clear(c); fmpz_clear(d); fmpz_clear(t); fmpz_clear(u); _fmpz_vec_clear(zeta, num); } flint-3.1.3/src/arb/zeta_ui_vec_even.c000066400000000000000000000011011461254215100176350ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_zeta_ui_vec_even(arb_ptr x, ulong start, slong num, slong prec) { slong i; for (i = 0; i < num; i++) arb_zeta_ui(x + i, start + 2 * i, prec); } flint-3.1.3/src/arb/zeta_ui_vec_odd.c000066400000000000000000000015571461254215100174650ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" void arb_zeta_ui_vec_odd(arb_ptr x, ulong start, slong num, slong prec) { slong i, num_borwein; ulong cutoff; cutoff = 40 + 0.3 * prec; if (cutoff > start) { num_borwein = 1 + (cutoff - start) / 2; num_borwein = FLINT_MIN(num_borwein, num); } else num_borwein = 0; arb_zeta_ui_vec_borwein(x, start, num_borwein, 2, prec); for (i = num_borwein; i < num; i++) arb_zeta_ui(x + i, start + 2 * i, prec); } flint-3.1.3/src/arb_calc.h000066400000000000000000000057351461254215100153330ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_CALC_H #define ARB_CALC_H #include "arb.h" #ifdef __cplusplus extern "C" { #endif extern FLINT_TLS_PREFIX int arb_calc_verbose; typedef int (*arb_calc_func_t)(arb_ptr out, const arb_t inp, void * param, slong order, slong prec); #define ARB_CALC_SUCCESS 0 #define ARB_CALC_IMPRECISE_INPUT 1 #define ARB_CALC_NO_CONVERGENCE 2 /* Root-finding */ FLINT_FORCE_INLINE void arf_interval_init(arf_interval_t v) { arf_init(&v->a); arf_init(&v->b); } FLINT_FORCE_INLINE void arf_interval_clear(arf_interval_t v) { arf_clear(&v->a); arf_clear(&v->b); } FLINT_FORCE_INLINE arf_interval_ptr _arf_interval_vec_init(slong n) { slong i; arf_interval_ptr v = (arf_interval_ptr) flint_malloc(sizeof(arf_interval_struct) * n); for (i = 0; i < n; i++) arf_interval_init(v + i); return v; } FLINT_FORCE_INLINE void _arf_interval_vec_clear(arf_interval_ptr v, slong n) { slong i; for (i = 0; i < n; i++) arf_interval_clear(v + i); flint_free(v); } FLINT_FORCE_INLINE void arf_interval_set(arf_interval_t v, const arf_interval_t u) { arf_set(&v->a, &u->a); arf_set(&v->b, &u->b); } FLINT_FORCE_INLINE void arf_interval_swap(arf_interval_t v, arf_interval_t u) { arf_swap(&v->a, &u->a); arf_swap(&v->b, &u->b); } FLINT_FORCE_INLINE void arf_interval_get_arb(arb_t x, const arf_interval_t v, slong prec) { arb_set_interval_arf(x, &v->a, &v->b, prec); } #ifdef FLINT_HAVE_FILE void arf_interval_fprintd(FILE * file, const arf_interval_t v, slong n); #endif void arf_interval_printd(const arf_interval_t v, slong n); /* bisection */ int arb_calc_partition(arf_interval_t L, arf_interval_t R, arb_calc_func_t func, void * param, const arf_interval_t block, slong prec); slong arb_calc_isolate_roots(arf_interval_ptr * blocks, int ** flags, arb_calc_func_t func, void * param, const arf_interval_t block, slong maxdepth, slong maxeval, slong maxfound, slong prec); int arb_calc_refine_root_bisect(arf_interval_t r, arb_calc_func_t func, void * param, const arf_interval_t start, slong iter, slong prec); /* newton iteration */ void arb_calc_newton_conv_factor(arf_t conv_factor, arb_calc_func_t func, void * param, const arb_t conv_region, slong prec); int arb_calc_newton_step(arb_t xnew, arb_calc_func_t func, void * param, const arb_t x, const arb_t conv_region, const arf_t conv_factor, slong prec); int arb_calc_refine_root_newton(arb_t r, arb_calc_func_t func, void * param, const arb_t start, const arb_t conv_region, const arf_t conv_factor, slong eval_extra_prec, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arb_calc/000077500000000000000000000000001461254215100151505ustar00rootroot00000000000000flint-3.1.3/src/arb_calc/io.c000066400000000000000000000015041461254215100157230ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb_calc.h" /* printing *******************************************************************/ void arf_interval_fprintd(FILE * file, const arf_interval_t v, slong n) { flint_fprintf(file, "["); arf_fprintd(file, &v->a, n); flint_fprintf(file, ", "); arf_fprintd(file, &v->b, n); flint_fprintf(file, "]"); } void arf_interval_printd(const arf_interval_t v, slong n) { arf_interval_fprintd(stdout, v, n); } flint-3.1.3/src/arb_calc/isolate_roots.c000066400000000000000000000112671461254215100202110ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_calc.h" #define BLOCK_NO_ZERO 0 #define BLOCK_ISOLATED_ZERO 1 #define BLOCK_UNKNOWN 2 static int check_block(arb_calc_func_t func, void * param, const arf_interval_t block, int asign, int bsign, slong prec) { arb_struct t[2]; arb_t x; int result; arb_init(t + 0); arb_init(t + 1); arb_init(x); arf_interval_get_arb(x, block, prec); func(t, x, param, 1, prec); result = BLOCK_UNKNOWN; if (arb_is_positive(t) || arb_is_negative(t)) { result = BLOCK_NO_ZERO; } else { if ((asign < 0 && bsign > 0) || (asign > 0 && bsign < 0)) { func(t, x, param, 2, prec); if (arb_is_finite(t + 1) && !arb_contains_zero(t + 1)) { result = BLOCK_ISOLATED_ZERO; } } } arb_clear(t + 0); arb_clear(t + 1); arb_clear(x); return result; } #define ADD_BLOCK \ if (*length >= *alloc) \ { \ slong new_alloc; \ new_alloc = (*alloc == 0) ? 1 : 2 * (*alloc); \ *blocks = flint_realloc(*blocks, sizeof(arf_interval_struct) * new_alloc); \ *flags = flint_realloc(*flags, sizeof(int) * new_alloc); \ *alloc = new_alloc; \ } \ arf_interval_init((*blocks) + *length); \ arf_interval_set((*blocks) + *length, block); \ (*flags)[*length] = status; \ (*length)++; \ static void isolate_roots_recursive(arf_interval_ptr * blocks, int ** flags, slong * length, slong * alloc, arb_calc_func_t func, void * param, const arf_interval_t block, int asign, int bsign, slong depth, slong * eval_count, slong * found_count, slong prec) { int status; if (*found_count <= 0 || *eval_count <= 0) { status = BLOCK_UNKNOWN; ADD_BLOCK } else { *eval_count -= 1; status = check_block(func, param, block, asign, bsign, prec); if (status != BLOCK_NO_ZERO) { if (status == BLOCK_ISOLATED_ZERO || depth <= 0) { if (status == BLOCK_ISOLATED_ZERO) { if (arb_calc_verbose) { flint_printf("found isolated root in: "); arf_interval_printd(block, 15); flint_printf("\n"); } *found_count -= 1; } ADD_BLOCK } else { arf_interval_t L, R; int msign; arf_interval_init(L); arf_interval_init(R); msign = arb_calc_partition(L, R, func, param, block, prec); if (msign == 0 && arb_calc_verbose) { flint_printf("possible zero at midpoint: "); arf_interval_printd(block, 15); flint_printf("\n"); } isolate_roots_recursive(blocks, flags, length, alloc, func, param, L, asign, msign, depth - 1, eval_count, found_count, prec); isolate_roots_recursive(blocks, flags, length, alloc, func, param, R, msign, bsign, depth - 1, eval_count, found_count, prec); arf_interval_clear(L); arf_interval_clear(R); } } } } slong arb_calc_isolate_roots(arf_interval_ptr * blocks, int ** flags, arb_calc_func_t func, void * param, const arf_interval_t block, slong maxdepth, slong maxeval, slong maxfound, slong prec) { int asign, bsign; slong length, alloc; arb_t m, v; *blocks = NULL; *flags = NULL; length = 0; alloc = 0; arb_init(m); arb_init(v); arb_set_arf(m, &block->a); func(v, m, param, 1, prec); asign = arb_sgn_nonzero(v); arb_set_arf(m, &block->b); func(v, m, param, 1, prec); bsign = arb_sgn_nonzero(v); arb_clear(m); arb_clear(v); isolate_roots_recursive(blocks, flags, &length, &alloc, func, param, block, asign, bsign, maxdepth, &maxeval, &maxfound, prec); *blocks = flint_realloc(*blocks, length * sizeof(arf_interval_struct)); *flags = flint_realloc(*flags, length * sizeof(int)); return length; } flint-3.1.3/src/arb_calc/newton_conv_factor.c000066400000000000000000000015211461254215100212100ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_calc.h" void arb_calc_newton_conv_factor(arf_t conv_factor, arb_calc_func_t func, void * param, const arb_t conv_region, slong prec) { arb_struct t[3]; arb_init(t); arb_init(t + 1); arb_init(t + 2); func(t, conv_region, param, 3, prec); arb_div(t, t + 2, t + 1, prec); arb_mul_2exp_si(t, t, -1); arb_get_abs_ubound_arf(conv_factor, t, prec); arb_clear(t); arb_clear(t + 1); arb_clear(t + 2); } flint-3.1.3/src/arb_calc/newton_step.c000066400000000000000000000026261461254215100176670ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_calc.h" int arb_calc_newton_step(arb_t xnew, arb_calc_func_t func, void * param, const arb_t x, const arb_t conv_region, const arf_t conv_factor, slong prec) { mag_t err, v; arb_t t; arb_struct u[2]; int result; mag_init(err); mag_init(v); arb_init(t); arb_init(u + 0); arb_init(u + 1); mag_mul(err, arb_radref(x), arb_radref(x)); arf_get_mag(v, conv_factor); mag_mul(err, err, v); arf_set(arb_midref(t), arb_midref(x)); mag_zero(arb_radref(t)); func(u, t, param, 2, prec); arb_div(u, u, u + 1, prec); arb_sub(u, t, u, prec); mag_add(arb_radref(u), arb_radref(u), err); if (arb_contains(conv_region, u) && (mag_cmp(arb_radref(u), arb_radref(x)) < 0)) { arb_swap(xnew, u); result = ARB_CALC_SUCCESS; } else { arb_set(xnew, x); result = ARB_CALC_NO_CONVERGENCE; } arb_clear(t); arb_clear(u); arb_clear(u + 1); mag_clear(err); mag_clear(v); return result; } flint-3.1.3/src/arb_calc/refine_root_bisect.c000066400000000000000000000050461461254215100211650ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_calc.h" /* TODO: refactor/combine some of this code with isolate_roots.c */ int arb_calc_partition(arf_interval_t L, arf_interval_t R, arb_calc_func_t func, void * param, const arf_interval_t block, slong prec) { arb_t t, m; arf_t u; int msign; arb_init(t); arb_init(m); arf_init(u); /* Compute the midpoint (TODO: try other points) */ arf_add(u, &block->a, &block->b, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_2exp_si(u, u, -1); /* Evaluate and get sign at midpoint */ arb_set_arf(m, u); func(t, m, param, 1, prec); msign = arb_sgn_nonzero(t); /* L, R = block, split at midpoint */ arf_set(&L->a, &block->a); arf_set(&R->b, &block->b); arf_set(&L->b, u); arf_set(&R->a, u); arb_clear(t); arb_clear(m); arf_clear(u); return msign; } int arb_calc_refine_root_bisect(arf_interval_t r, arb_calc_func_t func, void * param, const arf_interval_t start, slong iter, slong prec) { int asign, bsign, msign, result; slong i; arf_interval_t t, u; arb_t m, v; arf_interval_init(t); arf_interval_init(u); arb_init(m); arb_init(v); arb_set_arf(m, &start->a); func(v, m, param, 1, prec); asign = arb_sgn_nonzero(v); arb_set_arf(m, &start->b); func(v, m, param, 1, prec); bsign = arb_sgn_nonzero(v); /* must have proper sign changes */ if (asign == 0 || bsign == 0 || asign == bsign) { result = ARB_CALC_IMPRECISE_INPUT; } else { arf_interval_set(r, start); result = ARB_CALC_SUCCESS; for (i = 0; i < iter; i++) { msign = arb_calc_partition(t, u, func, param, r, prec); /* the algorithm fails if the value at the midpoint cannot be distinguished from zero */ if (msign == 0) { result = ARB_CALC_NO_CONVERGENCE; break; } if (msign == asign) arf_interval_swap(r, u); else arf_interval_swap(r, t); } } arf_interval_clear(t); arf_interval_clear(u); arb_clear(m); arb_clear(v); return result; } flint-3.1.3/src/arb_calc/refine_root_newton.c000066400000000000000000000033111461254215100212170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_calc.h" int arb_calc_refine_root_newton(arb_t r, arb_calc_func_t func, void * param, const arb_t start, const arb_t conv_region, const arf_t conv_factor, slong eval_extra_prec, slong prec) { slong precs[FLINT_BITS]; slong i, iters, wp, padding, start_prec; int result; start_prec = arb_rel_accuracy_bits(start); if (arb_calc_verbose) flint_printf("newton initial accuracy: %wd\n", start_prec); padding = arf_abs_bound_lt_2exp_si(conv_factor); padding = FLINT_MIN(padding, prec) + 5; padding = FLINT_MAX(0, padding); precs[0] = prec + padding; iters = 1; while ((iters < FLINT_BITS) && (precs[iters-1] + padding > 2*start_prec)) { precs[iters] = (precs[iters-1] / 2) + padding; iters++; if (iters == FLINT_BITS) { return ARB_CALC_IMPRECISE_INPUT; } } arb_set(r, start); for (i = iters - 1; i >= 0; i--) { wp = precs[i] + eval_extra_prec; if (arb_calc_verbose) flint_printf("newton step: wp = %wd + %wd = %wd\n", precs[i], eval_extra_prec, wp); if ((result = arb_calc_newton_step(r, func, param, r, conv_region, conv_factor, wp)) != ARB_CALC_SUCCESS) { return result; } } return ARB_CALC_SUCCESS; } flint-3.1.3/src/arb_calc/test/000077500000000000000000000000001461254215100161275ustar00rootroot00000000000000flint-3.1.3/src/arb_calc/test/main.c000066400000000000000000000014151461254215100172200ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-isolate_roots.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arb_calc_isolate_roots) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arb_calc/test/t-isolate_roots.c000066400000000000000000000075711461254215100214340ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" #include "arb_calc.h" /* sin((pi/2)x) */ static int sin_pi2_x(arb_ptr out, const arb_t inp, void * params, slong order, slong prec) { arb_ptr x; x = _arb_vec_init(2); arb_set(x, inp); arb_one(x + 1); arb_const_pi(out, prec); arb_mul_2exp_si(out, out, -1); _arb_vec_scalar_mul(x, x, 2, out, prec); _arb_poly_sin_series(out, x, order, order, prec); _arb_vec_clear(x, 2); return 0; } TEST_FUNCTION_START(arb_calc_isolate_roots, state) { slong iter; for (iter = 0; iter < 40 * 0.1 * flint_test_multiplier(); iter++) { slong m, r, a, b, maxdepth, maxeval, maxfound, prec, i, j, num; arf_interval_ptr blocks; int * info; arf_interval_t interval; arb_t t; fmpz_t nn; prec = 2 + n_randint(state, 50); m = n_randint(state, 80); r = 1 + n_randint(state, 80); a = m - r; b = m + r; maxdepth = 1 + n_randint(state, 60); maxeval = 1 + n_randint(state, 5000); maxfound = 1 + n_randint(state, 100); arf_interval_init(interval); arb_init(t); fmpz_init(nn); arf_set_si(&interval->a, a); arf_set_si(&interval->b, b); num = arb_calc_isolate_roots(&blocks, &info, sin_pi2_x, NULL, interval, maxdepth, maxeval, maxfound, prec); /* check that all roots are accounted for */ for (i = a; i <= b; i++) { if (i % 2 == 0) { int found = 0; for (j = 0; j < num; j++) { arf_interval_get_arb(t, blocks + j, ARF_PREC_EXACT); if (arb_contains_si(t, i)) { found = 1; break; } } if (!found) { flint_printf("FAIL: missing root %wd\n", i); flint_printf("a = %wd, b = %wd, maxdepth = %wd, maxeval = %wd, maxfound = %wd, prec = %wd\n", a, b, maxdepth, maxeval, maxfound, prec); for (j = 0; j < num; j++) { arf_interval_printd(blocks + j, 15); flint_printf(" %d \n", info[i]); } flint_abort(); } } } /* check that all reported single roots are good */ for (i = 0; i < num; i++) { if (info[i] == 1) { /* b contains unique 2n -> b/2 contains unique n */ arf_interval_get_arb(t, blocks + i, ARF_PREC_EXACT); arb_mul_2exp_si(t, t, -1); if (!arb_get_unique_fmpz(nn, t)) { flint_printf("FAIL: bad root %wd\n", i); flint_printf("a = %wd, b = %wd, maxdepth = %wd, maxeval = %wd, maxfound = %wd, prec = %wd\n", a, b, maxdepth, maxeval, maxfound, prec); for (j = 0; j < num; j++) { arf_interval_printd(blocks + j, 15); flint_printf(" %d \n", info[i]); } flint_abort(); } } } _arf_interval_vec_clear(blocks, num); flint_free(info); arf_interval_clear(interval); arb_clear(t); fmpz_clear(nn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_calc/verbose.c000066400000000000000000000007011461254215100167570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_calc.h" int FLINT_TLS_PREFIX arb_calc_verbose = 0; flint-3.1.3/src/arb_fmpz_poly.h000066400000000000000000000041421461254215100164370ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_FMPZ_POLY_H #define ARB_FMPZ_POLY_H #include "fmpz_poly.h" #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif #define ARB_FMPZ_POLY_ROOTS_VERBOSE 1 void _arb_fmpz_poly_evaluate_acb_horner(acb_t res, const fmpz * f, slong len, const acb_t x, slong prec); void arb_fmpz_poly_evaluate_acb_horner(acb_t res, const fmpz_poly_t f, const acb_t a, slong prec); void _arb_fmpz_poly_evaluate_acb_rectangular(acb_t res, const fmpz * f, slong len, const acb_t x, slong prec); void arb_fmpz_poly_evaluate_acb_rectangular(acb_t res, const fmpz_poly_t f, const acb_t a, slong prec); void _arb_fmpz_poly_evaluate_acb(acb_t res, const fmpz * f, slong len, const acb_t x, slong prec); void arb_fmpz_poly_evaluate_acb(acb_t res, const fmpz_poly_t f, const acb_t a, slong prec); void _arb_fmpz_poly_evaluate_arb_horner(arb_t res, const fmpz * f, slong len, const arb_t x, slong prec); void arb_fmpz_poly_evaluate_arb_horner(arb_t res, const fmpz_poly_t f, const arb_t a, slong prec); void _arb_fmpz_poly_evaluate_arb_rectangular(arb_t res, const fmpz * f, slong len, const arb_t x, slong prec); void arb_fmpz_poly_evaluate_arb_rectangular(arb_t res, const fmpz_poly_t f, const arb_t a, slong prec); void _arb_fmpz_poly_evaluate_arb(arb_t res, const fmpz * f, slong len, const arb_t x, slong prec); void arb_fmpz_poly_evaluate_arb(arb_t res, const fmpz_poly_t f, const arb_t a, slong prec); void arb_fmpz_poly_deflate(fmpz_poly_t result, const fmpz_poly_t input, ulong deflation); ulong arb_fmpz_poly_deflation(const fmpz_poly_t input); void arb_fmpz_poly_complex_roots(acb_ptr roots, const fmpz_poly_t poly, int flags, slong target_prec); void arb_fmpz_poly_gauss_period_minpoly(fmpz_poly_t res, ulong q, ulong n); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arb_fmpz_poly/000077500000000000000000000000001461254215100162655ustar00rootroot00000000000000flint-3.1.3/src/arb_fmpz_poly/complex_roots.c000066400000000000000000000145711461254215100213360ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_poly.h" #include "arb_fmpz_poly.h" #include "profiler.h" static int check_accuracy(acb_ptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { if (acb_rel_accuracy_bits(vec + i) < prec) return 0; } return 1; } static int check_isolation(acb_srcptr roots, slong len) { slong i, j; for (i = 0; i < len; i++) { if (arf_sgn(arb_midref(acb_imagref(roots + i))) >= 0) { for (j = i + 1; j < len; j++) { if (arf_sgn(arb_midref(acb_imagref(roots + j))) >= 0) { if (acb_overlaps(roots + i, roots + j)) return 0; } } } } return 1; } void arb_fmpz_poly_complex_roots(acb_ptr roots, const fmpz_poly_t poly, int flags, slong target_prec) { slong i, j, prec, deg, deg_deflated, isolated, maxiter, deflation; slong initial_prec, num_real; acb_poly_t cpoly, cpoly_deflated; fmpz_poly_t poly_deflated; acb_ptr roots_deflated; int removed_zero; if (fmpz_poly_degree(poly) < 1) return; initial_prec = 32; fmpz_poly_init(poly_deflated); acb_poly_init(cpoly); acb_poly_init(cpoly_deflated); /* try to write poly as poly_deflated(x^deflation), possibly multiplied by x */ removed_zero = fmpz_is_zero(poly->coeffs); if (removed_zero) fmpz_poly_shift_right(poly_deflated, poly, 1); else fmpz_poly_set(poly_deflated, poly); deflation = arb_fmpz_poly_deflation(poly_deflated); arb_fmpz_poly_deflate(poly_deflated, poly_deflated, deflation); deg = fmpz_poly_degree(poly); deg_deflated = fmpz_poly_degree(poly_deflated); if (flags & ARB_FMPZ_POLY_ROOTS_VERBOSE) { flint_printf("searching for %wd roots, %wd deflated\n", deg, deg_deflated); } /* we only need deg_deflated entries, but the remainder will be useful as scratch space */ roots_deflated = _acb_vec_init(deg); for (prec = initial_prec; ; prec *= 2) { acb_poly_set_fmpz_poly(cpoly_deflated, poly_deflated, prec); maxiter = FLINT_MIN(4 * deg_deflated + 64, prec); if (flags & ARB_FMPZ_POLY_ROOTS_VERBOSE) { TIMEIT_ONCE_START flint_printf("prec=%wd: ", prec); isolated = acb_poly_find_roots(roots_deflated, cpoly_deflated, prec == initial_prec ? NULL : roots_deflated, maxiter, prec); flint_printf("%wd isolated roots | ", isolated); TIMEIT_ONCE_STOP } else { isolated = acb_poly_find_roots(roots_deflated, cpoly_deflated, prec == initial_prec ? NULL : roots_deflated, maxiter, prec); } if (isolated == deg_deflated) { if (!check_accuracy(roots_deflated, deg_deflated, target_prec)) continue; if (deflation == 1) { _acb_vec_set(roots, roots_deflated, deg_deflated); } else /* compute all nth roots */ { acb_t w, w2; acb_init(w); acb_init(w2); acb_unit_root(w, deflation, prec); acb_unit_root(w2, 2 * deflation, prec); for (i = 0; i < deg_deflated; i++) { if (arf_sgn(arb_midref(acb_realref(roots_deflated + i))) > 0) { acb_root_ui(roots + i * deflation, roots_deflated + i, deflation, prec); } else { acb_neg(roots + i * deflation, roots_deflated + i); acb_root_ui(roots + i * deflation, roots + i * deflation, deflation, prec); acb_mul(roots + i * deflation, roots + i * deflation, w2, prec); } for (j = 1; j < deflation; j++) { acb_mul(roots + i * deflation + j, roots + i * deflation + j - 1, w, prec); } } acb_clear(w); acb_clear(w2); } /* by assumption that poly is squarefree, must be just one */ if (removed_zero) acb_zero(roots + deg_deflated * deflation); if (!check_accuracy(roots, deg, target_prec)) continue; acb_poly_set_fmpz_poly(cpoly, poly, prec); if (!acb_poly_validate_real_roots(roots, cpoly, prec)) continue; for (i = 0; i < deg; i++) { if (arb_contains_zero(acb_imagref(roots + i))) arb_zero(acb_imagref(roots + i)); } if (!check_isolation(roots, deg)) { /* extremely unlikely */ if (flags & ARB_FMPZ_POLY_ROOTS_VERBOSE) flint_printf("isolation failure!\n"); continue; } if (flags & ARB_FMPZ_POLY_ROOTS_VERBOSE) flint_printf("done!\n"); break; } } _acb_vec_sort_pretty(roots, deg); /* pair conjugates */ num_real = 0; for (i = 0; i < deg; i++) if (acb_is_real(roots + i)) num_real++; if (deg != num_real) { for (i = num_real, j = 0; i < deg; i++) { if (arb_is_positive(acb_imagref(roots + i))) { acb_swap(roots_deflated + j, roots + i); j++; } } for (i = 0; i < (deg - num_real) / 2; i++) { acb_swap(roots + num_real + 2 * i, roots_deflated + i); acb_conj(roots + num_real + 2 * i + 1, roots + num_real + 2 * i); } } fmpz_poly_clear(poly_deflated); acb_poly_clear(cpoly); acb_poly_clear(cpoly_deflated); _acb_vec_clear(roots_deflated, deg); } flint-3.1.3/src/arb_fmpz_poly/deflate.c000066400000000000000000000020001461254215100200250ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "arb_fmpz_poly.h" void arb_fmpz_poly_deflate(fmpz_poly_t result, const fmpz_poly_t input, ulong deflation) { slong res_length, i; if (deflation == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_deflate). Division by zero.\n"); } if (input->length <= 1 || deflation == 1) { fmpz_poly_set(result, input); return; } res_length = (input->length - 1) / deflation + 1; fmpz_poly_fit_length(result, res_length); for (i = 0; i < res_length; i++) fmpz_set(result->coeffs + i, input->coeffs + i*deflation); result->length = res_length; } flint-3.1.3/src/arb_fmpz_poly/deflation.c000066400000000000000000000020741461254215100204010ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "arb_fmpz_poly.h" ulong arb_fmpz_poly_deflation(const fmpz_poly_t input) { slong i, coeff, deflation; if (input->length <= 1) return input->length; coeff = 1; while (fmpz_is_zero(input->coeffs + coeff)) coeff++; deflation = n_gcd(input->length - 1, coeff); while ((deflation > 1) && (coeff + deflation < input->length)) { for (i = 0; i < deflation - 1; i++) { coeff++; if (!fmpz_is_zero(input->coeffs + coeff)) deflation = n_gcd(coeff, deflation); } if (i == deflation - 1) coeff++; } return deflation; } flint-3.1.3/src/arb_fmpz_poly/evaluate_acb.c000066400000000000000000000017131461254215100210460ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_fmpz_poly.h" void _arb_fmpz_poly_evaluate_acb(acb_t res, const fmpz * f, slong len, const acb_t x, slong prec) { if (acb_is_real(x)) { _arb_fmpz_poly_evaluate_arb(acb_realref(res), f, len, acb_realref(x), prec); arb_zero(acb_imagref(res)); } else { _arb_fmpz_poly_evaluate_acb_rectangular(res, f, len, x, prec); } } void arb_fmpz_poly_evaluate_acb(acb_t res, const fmpz_poly_t f, const acb_t a, slong prec) { _arb_fmpz_poly_evaluate_acb(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_fmpz_poly/evaluate_acb_horner.c000066400000000000000000000025661461254215100224320ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_fmpz_poly.h" void _arb_fmpz_poly_evaluate_acb_horner(acb_t y, const fmpz * f, slong len, const acb_t x, slong prec) { if (len == 0) { acb_zero(y); } else if (len == 1 || acb_is_zero(x)) { acb_set_round_fmpz(y, f, prec); } else if (len == 2) { acb_mul_fmpz(y, x, f + 1, prec); acb_add_fmpz(y, y, f + 0, prec); } else { slong i = len - 1; acb_t t, u; acb_init(t); acb_init(u); acb_set_fmpz(u, f + i); for (i = len - 2; i >= 0; i--) { acb_mul(t, u, x, prec); acb_add_fmpz(u, t, f + i, prec); } acb_swap(y, u); acb_clear(t); acb_clear(u); } } void arb_fmpz_poly_evaluate_acb_horner(acb_t res, const fmpz_poly_t f, const acb_t a, slong prec) { _arb_fmpz_poly_evaluate_acb_horner(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_fmpz_poly/evaluate_acb_rectangular.c000066400000000000000000000030571461254215100234400ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "arb_fmpz_poly.h" void _arb_fmpz_poly_evaluate_acb_rectangular(acb_t y, const fmpz * poly, slong len, const acb_t x, slong prec) { slong i, m, r; acb_ptr xs; acb_t s, t, c; if (len < 3) { _arb_fmpz_poly_evaluate_acb_horner(y, poly, len, x, prec); return; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); acb_init(c); _acb_vec_set_powers(xs, x, m + 1, prec); acb_set_fmpz(y, poly + (r - 1) * m); acb_dot_fmpz(y, y, 0, xs + 1, 1, poly + (r - 1) * m + 1, 1, len - (r - 1) * m - 1, prec); for (i = r - 2; i >= 0; i--) { acb_set_fmpz(s, poly + i * m); acb_dot_fmpz(s, s, 0, xs + 1, 1, poly + i * m + 1, 1, m - 1, prec); acb_mul(y, y, xs + m, prec); acb_add(y, y, s, prec); } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); acb_clear(c); } void arb_fmpz_poly_evaluate_acb_rectangular(acb_t res, const fmpz_poly_t f, const acb_t a, slong prec) { _arb_fmpz_poly_evaluate_acb_rectangular(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_fmpz_poly/evaluate_arb.c000066400000000000000000000024421461254215100210650ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "arb_fmpz_poly.h" void _arb_fmpz_poly_evaluate_arb(arb_t res, const fmpz * f, slong len, const arb_t x, slong prec) { if (len >= 6 && len >= 5 + 2500 / (FLINT_MAX(prec, 64) + 64)) { /* todo: improve this tuning? */ if (prec > 1024) { slong fbits; fbits = _fmpz_vec_max_bits(f, len); fbits = FLINT_ABS(fbits); if (fbits > prec / 2) { _arb_fmpz_poly_evaluate_arb_horner(res, f, len, x, prec); return; } } _arb_fmpz_poly_evaluate_arb_rectangular(res, f, len, x, prec); return; } _arb_fmpz_poly_evaluate_arb_horner(res, f, len, x, prec); } void arb_fmpz_poly_evaluate_arb(arb_t res, const fmpz_poly_t f, const arb_t a, slong prec) { _arb_fmpz_poly_evaluate_arb(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_fmpz_poly/evaluate_arb_horner.c000066400000000000000000000025661461254215100224510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "arb_fmpz_poly.h" void _arb_fmpz_poly_evaluate_arb_horner(arb_t y, const fmpz * f, slong len, const arb_t x, slong prec) { if (len == 0) { arb_zero(y); } else if (len == 1 || arb_is_zero(x)) { arb_set_round_fmpz(y, f, prec); } else if (len == 2) { arb_mul_fmpz(y, x, f + 1, prec); arb_add_fmpz(y, y, f + 0, prec); } else { slong i = len - 1; arb_t t, u; arb_init(t); arb_init(u); arb_set_fmpz(u, f + i); for (i = len - 2; i >= 0; i--) { arb_mul(t, u, x, prec); arb_add_fmpz(u, t, f + i, prec); } arb_swap(y, u); arb_clear(t); arb_clear(u); } } void arb_fmpz_poly_evaluate_arb_horner(arb_t res, const fmpz_poly_t f, const arb_t a, slong prec) { _arb_fmpz_poly_evaluate_arb_horner(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_fmpz_poly/evaluate_arb_rectangular.c000066400000000000000000000030571461254215100234570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb.h" #include "arb_fmpz_poly.h" void _arb_fmpz_poly_evaluate_arb_rectangular(arb_t y, const fmpz * poly, slong len, const arb_t x, slong prec) { slong i, m, r; arb_ptr xs; arb_t s, t, c; if (len < 3) { _arb_fmpz_poly_evaluate_arb_horner(y, poly, len, x, prec); return; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = _arb_vec_init(m + 1); arb_init(s); arb_init(t); arb_init(c); _arb_vec_set_powers(xs, x, m + 1, prec); arb_set_fmpz(y, poly + (r - 1) * m); arb_dot_fmpz(y, y, 0, xs + 1, 1, poly + (r - 1) * m + 1, 1, len - (r - 1) * m - 1, prec); for (i = r - 2; i >= 0; i--) { arb_set_fmpz(s, poly + i * m); arb_dot_fmpz(s, s, 0, xs + 1, 1, poly + i * m + 1, 1, m - 1, prec); arb_mul(y, y, xs + m, prec); arb_add(y, y, s, prec); } _arb_vec_clear(xs, m + 1); arb_clear(s); arb_clear(t); arb_clear(c); } void arb_fmpz_poly_evaluate_arb_rectangular(arb_t res, const fmpz_poly_t f, const arb_t a, slong prec) { _arb_fmpz_poly_evaluate_arb_rectangular(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_fmpz_poly/gauss_period_minpoly.c000066400000000000000000000101421461254215100226620ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_fmpz_poly.h" #include "acb_dirichlet.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif void arb_fmpz_poly_gauss_period_minpoly(fmpz_poly_t res, ulong q, ulong n) { ulong k, d, e, g, gk, qinv; ulong * es; slong prec, initial_prec; int done, real; if (n == 0 || !n_is_prime(q) || ((q - 1) % n) != 0 || n_gcd(n, (q - 1) / n) != 1) { fmpz_poly_zero(res); return; } d = (q - 1) / n; /* this is much faster */ if (d == 1) { fmpz_poly_cyclotomic(res, q); return; } g = n_primitive_root_prime(q); qinv = n_preinvert_limb(q); es = flint_malloc(sizeof(ulong) * d); for (e = 0; e < d; e++) es[e] = n_powmod2(g, n * e, q); /* either all roots are real, or all roots are complex */ real = (n % 2) == 1; /* first estimate precision crudely based on d and n */ initial_prec = n * log(2 * d) * 1.4426950408889 * 1.03 + 20; initial_prec = FLINT_MAX(initial_prec, 48); /* if high, start lower to get a good estimate */ if (initial_prec > 200) initial_prec = 48; for (prec = initial_prec, done = 0; !done; ) { acb_dirichlet_roots_t zeta; arb_poly_t pz; arb_ptr roots; acb_ptr croots; acb_t t, u; arb_t v; acb_dirichlet_roots_init(zeta, q, (n * d) / 2, prec); roots = _arb_vec_init(n); croots = (acb_ptr) roots; acb_init(t); if (!real) acb_init(u); else arb_init(v); arb_poly_init(pz); for (k = 0; k < (real ? n : n / 2); k++) { gk = n_powmod2(g, k, q); if (real) { arb_zero(v); for (e = 0; e < d / 2; e++) { acb_dirichlet_root(t, zeta, n_mulmod2_preinv(gk, es[e], q, qinv), prec); arb_add(v, v, acb_realref(t), prec); } arb_mul_2exp_si(v, v, 1); /* compute conjugates */ arb_set(roots + k, v); } else { acb_zero(u); for (e = 0; e < d; e++) { acb_dirichlet_root(t, zeta, n_mulmod2_preinv(gk, es[e], q, qinv), prec); acb_add(u, u, t, prec); } if (arb_contains_zero(acb_imagref(u))) { /* todo: could increase precision */ flint_throw(FLINT_ERROR, "fail! imaginary part should be nonzero\n"); } else { acb_set(croots + k, u); } } } if (real) arb_poly_product_roots(pz, roots, n, prec); else arb_poly_product_roots_complex(pz, NULL, 0, croots, n / 2, prec); done = arb_poly_get_unique_fmpz_poly(res, pz); if (!done && prec == initial_prec) { mag_t m, mmax; mag_init(m); mag_init(mmax); for (k = 0; k < n; k++) { arb_get_mag(m, pz->coeffs + k); mag_max(mmax, mmax, m); } prec = mag_get_d_log2_approx(mmax) * 1.03 + 20; if (prec < 2 * initial_prec) prec = 2 * initial_prec; mag_clear(m); mag_clear(mmax); } else if (!done) { prec *= 2; } acb_dirichlet_roots_clear(zeta); _arb_vec_clear(roots, n); acb_clear(t); if (!real) acb_clear(u); else arb_clear(v); arb_poly_clear(pz); } flint_free(es); } flint-3.1.3/src/arb_fmpz_poly/test/000077500000000000000000000000001461254215100172445ustar00rootroot00000000000000flint-3.1.3/src/arb_fmpz_poly/test/main.c000066400000000000000000000020031461254215100203270ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-complex_roots.c" #include "t-evaluate_acb.c" #include "t-evaluate_arb.c" #include "t-gauss_period_minpoly.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arb_fmpz_poly_complex_roots), TEST_FUNCTION(arb_fmpz_poly_evaluate_acb), TEST_FUNCTION(arb_fmpz_poly_evaluate_arb), TEST_FUNCTION(arb_fmpz_poly_gauss_period_minpoly) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arb_fmpz_poly/test/t-complex_roots.c000066400000000000000000000162311461254215100225510ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_factor.h" #include "fmpq_poly.h" #include "acb.h" #include "arb_poly.h" #include "arith.h" #include "arb_fmpz_poly.h" void check_roots(const fmpz_poly_t poly, acb_srcptr roots, slong prec) { arb_ptr real; acb_ptr upper; arb_poly_t rpoly; arb_t lead; slong i, j, num_real, num_upper, deg; deg = fmpz_poly_degree(poly); num_real = 0; for (i = 0; i < deg; i++) if (acb_is_real(roots + i)) num_real++; num_upper = (deg - num_real) / 2; real = _arb_vec_init(num_real); upper = _acb_vec_init(num_upper); arb_poly_init(rpoly); arb_init(lead); for (i = 0; i < num_real; i++) arb_set(real + i, acb_realref(roots + i)); for (i = 0; i < num_upper; i++) acb_set(upper + i, roots + num_real + 2 * i); arb_poly_product_roots_complex(rpoly, real, num_real, upper, num_upper, prec); arb_set_fmpz(lead, poly->coeffs + deg); arb_poly_scalar_mul(rpoly, rpoly, lead, prec); if (!arb_poly_contains_fmpz_poly(rpoly, poly)) { flint_printf("FAIL!\n"); flint_printf("deg = %wd, num_real = %wd, num_upper = %wd\n\n", deg, num_real, num_upper); for (i = 0; i < deg; i++) { acb_printn(roots + i, 30, 0); flint_printf("\n"); } flint_printf("\npoly:\n"); fmpz_poly_print(poly); flint_printf("\n\n"); flint_printf("rpoly:\n"); arb_poly_printd(rpoly, 30); flint_printf("\n\n"); flint_abort(); } for (i = 0; i < deg; i++) { for (j = i + 1; j < deg; j++) { if (acb_overlaps(roots + i, roots + j)) { flint_printf("FAIL! (isolation)\n"); flint_printf("deg = %wd, num_real = %wd, num_upper = %wd\n\n", deg, num_real, num_upper); for (i = 0; i < deg; i++) { acb_printn(roots + i, 30, 0); flint_printf("\n"); } } } } _arb_vec_clear(real, num_real); _acb_vec_clear(upper, num_upper); arb_poly_clear(rpoly); arb_clear(lead); } TEST_FUNCTION_START(arb_fmpz_poly_complex_roots, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { fmpz_poly_t f, g; fmpq_poly_t h; fmpz_poly_factor_t fac; fmpz_t t; acb_ptr roots; slong i, j, n, deg, prec, num_factors; int flags; prec = 20 + n_randint(state, 1000); flags = 0; /* ARB_FMPZ_POLY_ROOTS_VERBOSE; */ fmpz_poly_init(f); fmpz_poly_init(g); fmpq_poly_init(h); fmpz_init(t); fmpz_poly_one(f); num_factors = 1 + n_randint(state, 3); for (i = 0; i < num_factors; i++) { n = n_randint(state, 18); switch (n_randint(state, 12)) { case 0: fmpz_poly_zero(g); for (j = 0; j <= n; j++) fmpz_poly_set_coeff_ui(g, j, j+1); break; case 1: arith_chebyshev_t_polynomial(g, n); break; case 2: arith_chebyshev_u_polynomial(g, n); break; case 3: arith_legendre_polynomial(h, n); fmpq_poly_get_numerator(g, h); break; case 4: arith_cyclotomic_polynomial(g, n); break; case 5: arith_swinnerton_dyer_polynomial(g, n % 4); break; case 6: arith_bernoulli_polynomial(h, n); fmpq_poly_get_numerator(g, h); break; case 7: fmpz_poly_zero(g); fmpz_poly_fit_length(g, n+2); arith_stirling_number_1_vec(g->coeffs, n+1, n+2); _fmpz_poly_set_length(g, n+2); fmpz_poly_shift_right(g, g, 1); break; case 8: fmpq_poly_zero(h); fmpq_poly_set_coeff_si(h, 0, 0); fmpq_poly_set_coeff_si(h, 1, 1); fmpq_poly_exp_series(h, h, n + 1); fmpq_poly_get_numerator(g, h); break; case 9: fmpz_poly_zero(g); fmpz_poly_set_coeff_ui(g, 0, 1); fmpz_poly_set_coeff_ui(g, 1, 100); fmpz_poly_pow(g, g, n_randint(state, 5)); fmpz_poly_set_coeff_ui(g, n, 1); break; default: fmpz_poly_randtest(g, state, 1 + n, 1 + n_randint(state, 300)); break; } fmpz_poly_mul(f, f, g); } if (!fmpz_poly_is_zero(f)) { fmpz_poly_factor_init(fac); fmpz_poly_factor_squarefree(fac, f); for (i = 0; i < fac->num; i++) { deg = fmpz_poly_degree(fac->p + i); roots = _acb_vec_init(deg); arb_fmpz_poly_complex_roots(roots, fac->p + i, flags, prec); check_roots(fac->p + i, roots, prec); _acb_vec_clear(roots, deg); } fmpz_poly_factor_clear(fac); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpq_poly_clear(h); fmpz_clear(t); } /* divide by zero in D-K iteration */ { fmpz_poly_t f; acb_ptr roots; fmpz_poly_init(f); roots = _acb_vec_init(6); fmpz_poly_set_str(f, "7 25402042698578724632715842150384812072165708201873598515430741927709434502441548044497536658582884343075517644457858427539077202038196334089177500850739920720211950909770464886080670804176754154963931850468594331583498 223893180314223240984084491888407141086932132045832889810633599526603312517647486257597642989561630621890634231277838275174064496550528961859898776882676932807021286 795640482736635886180831008959046125790483017543686711742925168363012610075751154572719364427044897243091617811844423305126322668210906163297113908677853824166006037 4675174622252362090426964349867694514717613116237971666947773542341728151885745558219487022927593367256013888828 8306993067199362953716207209584242447525211917662146954370874791469552420765132896500330153494280277905784766392 24405899409125496050877753569127928027275807342290477559552 28910098348753799787840354537641329148612896619499101692036"); arb_fmpz_poly_complex_roots(roots, f, 0, 128); check_roots(f, roots, 512); _acb_vec_clear(roots, 6); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_fmpz_poly/test/t-evaluate_acb.c000066400000000000000000000065711461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "arb_fmpz_poly.h" TEST_FUNCTION_START(arb_fmpz_poly_evaluate_acb, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_poly_t f, g, h; acb_t x, fx, gx, hx, fxgx; slong prec1, prec2, prec3; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); acb_init(x); acb_init(fx); acb_init(gx); acb_init(hx); acb_init(fxgx); fmpz_poly_randtest(f, state, 1 + n_randint(state, 50), 1 + n_randint(state, 1000)); fmpz_poly_randtest(g, state, 1 + n_randint(state, 50), 1 + n_randint(state, 1000)); fmpz_poly_add(h, f, g); acb_randtest(x, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); acb_randtest(fx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); acb_randtest(gx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); acb_randtest(hx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); acb_randtest(fxgx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); prec3 = 2 + n_randint(state, 2000); switch (n_randint(state, 6)) { case 0: arb_fmpz_poly_evaluate_acb_horner(fx, f, x, prec1); break; case 1: arb_fmpz_poly_evaluate_acb_rectangular(fx, f, x, prec1); break; case 2: arb_fmpz_poly_evaluate_acb(fx, f, x, prec1); break; case 3: acb_set(fx, x); arb_fmpz_poly_evaluate_acb_horner(fx, f, fx, prec1); break; case 4: acb_set(fx, x); arb_fmpz_poly_evaluate_acb_rectangular(fx, f, fx, prec1); break; default: acb_set(fx, x); arb_fmpz_poly_evaluate_acb(fx, f, fx, prec1); break; } arb_fmpz_poly_evaluate_acb(gx, g, x, prec2); arb_fmpz_poly_evaluate_acb(hx, h, x, prec3); acb_add(fxgx, fx, gx, prec3); if (!acb_overlaps(fxgx, hx)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n\n"); fmpz_poly_print(g); flint_printf("\n\n"); fmpz_poly_print(h); flint_printf("\n\n"); acb_printd(x, 30); flint_printf("\n\n"); acb_printd(fx, 30); flint_printf("\n\n"); acb_printd(gx, 30); flint_printf("\n\n"); acb_printd(hx, 30); flint_printf("\n\n"); acb_printd(fxgx, 30); flint_printf("\n\n"); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); acb_clear(x); acb_clear(fx); acb_clear(gx); acb_clear(hx); acb_clear(fxgx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_fmpz_poly/test/t-evaluate_arb.c000066400000000000000000000065711461254215100223140ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" #include "arb_fmpz_poly.h" TEST_FUNCTION_START(arb_fmpz_poly_evaluate_arb, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_poly_t f, g, h; arb_t x, fx, gx, hx, fxgx; slong prec1, prec2, prec3; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); arb_init(x); arb_init(fx); arb_init(gx); arb_init(hx); arb_init(fxgx); fmpz_poly_randtest(f, state, 1 + n_randint(state, 50), 1 + n_randint(state, 1000)); fmpz_poly_randtest(g, state, 1 + n_randint(state, 50), 1 + n_randint(state, 1000)); fmpz_poly_add(h, f, g); arb_randtest(x, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); arb_randtest(fx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); arb_randtest(gx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); arb_randtest(hx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); arb_randtest(fxgx, state, 1 + n_randint(state, 2000), 1 + n_randint(state, 100)); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); prec3 = 2 + n_randint(state, 2000); switch (n_randint(state, 6)) { case 0: arb_fmpz_poly_evaluate_arb_horner(fx, f, x, prec1); break; case 1: arb_fmpz_poly_evaluate_arb_rectangular(fx, f, x, prec1); break; case 2: arb_fmpz_poly_evaluate_arb(fx, f, x, prec1); break; case 3: arb_set(fx, x); arb_fmpz_poly_evaluate_arb_horner(fx, f, fx, prec1); break; case 4: arb_set(fx, x); arb_fmpz_poly_evaluate_arb_rectangular(fx, f, fx, prec1); break; default: arb_set(fx, x); arb_fmpz_poly_evaluate_arb(fx, f, fx, prec1); break; } arb_fmpz_poly_evaluate_arb(gx, g, x, prec2); arb_fmpz_poly_evaluate_arb(hx, h, x, prec3); arb_add(fxgx, fx, gx, prec3); if (!arb_overlaps(fxgx, hx)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n\n"); fmpz_poly_print(g); flint_printf("\n\n"); fmpz_poly_print(h); flint_printf("\n\n"); arb_printd(x, 30); flint_printf("\n\n"); arb_printd(fx, 30); flint_printf("\n\n"); arb_printd(gx, 30); flint_printf("\n\n"); arb_printd(hx, 30); flint_printf("\n\n"); arb_printd(fxgx, 30); flint_printf("\n\n"); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); arb_clear(x); arb_clear(fx); arb_clear(gx); arb_clear(hx); arb_clear(fxgx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_fmpz_poly/test/t-gauss_period_minpoly.c000066400000000000000000000057611461254215100241150ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_fmpz_poly.h" #include "acb_dirichlet.h" TEST_FUNCTION_START(arb_fmpz_poly_gauss_period_minpoly, state) { slong iter; { slong prec; ulong n, q; fmpz_poly_t pol; fmpz_poly_init(pol); /* test q = 0 separately; see issue #194 */ for (n = 0; n < 100; n++) { fmpz_poly_one(pol); arb_fmpz_poly_gauss_period_minpoly(pol, 0, n); if (!fmpz_poly_is_zero(pol)) { flint_printf("FAIL (q = 0)\n"); flint_abort(); } } for (q = 1; q < 1000; q++) { acb_dirichlet_roots_t zeta; prec = 100 + n_randint(state, 500); if (n_is_prime(q)) acb_dirichlet_roots_init(zeta, q, 30, prec); for (n = 0; n < 1000; n++) { arb_fmpz_poly_gauss_period_minpoly(pol, q, n); if (!fmpz_poly_is_zero(pol)) { ulong k, g, gk, e, d; acb_t t, u; acb_init(t); acb_init(u); d = (q - 1) / n; g = n_primitive_root_prime(q); for (iter = 0; iter < 3; iter++) { k = n_randint(state, n); gk = n_powmod2(g, k, 2 * q); acb_zero(u); for (e = 0; e < d; e++) { acb_dirichlet_root(t, zeta, n_mulmod2_preinv(gk, n_powmod2(g, n * e, 2 * q), 2 * q, n_preinvert_limb(2 * q)), prec); acb_add(u, u, t, prec); } arb_fmpz_poly_evaluate_acb(t, pol, u, prec); if (!acb_contains_zero(t) || fmpz_poly_degree(pol) != n) { flint_printf("FAIL\n"); flint_printf("q = %wu, n = %wu, k = %wu\n\n", q, n, k); fmpz_poly_print(pol); flint_printf("\n\n"); acb_printn(u, 30, 0); flint_printf("\n\n"); acb_printn(t, 30, 0); flint_printf("\n\n"); flint_abort(); } } acb_clear(t); acb_clear(u); } } if (n_is_prime(q)) acb_dirichlet_roots_clear(zeta); } fmpz_poly_clear(pol); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_fpwrap.h000066400000000000000000000437771461254215100157400ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_FPWRAP_H #define ARB_FPWRAP_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif #define FPWRAP_SUCCESS 0 #define FPWRAP_UNABLE 1 #define FPWRAP_ACCURATE_PARTS 1 #define FPWRAP_CORRECT_ROUNDING 2 #define FPWRAP_WORK_LIMIT 65536 typedef struct { double real; double imag; } complex_double; int arb_fpwrap_double_exp(double * res, double x, int flags); int arb_fpwrap_cdouble_exp(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_expm1(double * res, double x, int flags); int arb_fpwrap_cdouble_expm1(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_log(double * res, double x, int flags); int arb_fpwrap_cdouble_log(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_log1p(double * res, double x, int flags); int arb_fpwrap_cdouble_log1p(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_pow(double * res, double x, double y, int flags); int arb_fpwrap_cdouble_pow(complex_double * res, complex_double x, complex_double y, int flags); int arb_fpwrap_double_sqrt(double * res, double x, int flags); int arb_fpwrap_cdouble_sqrt(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_rsqrt(double * res, double x, int flags); int arb_fpwrap_cdouble_rsqrt(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_cbrt(double * res, double x, int flags); int arb_fpwrap_cdouble_cbrt(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_sin(double * res, double x, int flags); int arb_fpwrap_cdouble_sin(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_cos(double * res, double x, int flags); int arb_fpwrap_cdouble_cos(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_tan(double * res, double x, int flags); int arb_fpwrap_cdouble_tan(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_cot(double * res, double x, int flags); int arb_fpwrap_cdouble_cot(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_sec(double * res, double x, int flags); int arb_fpwrap_cdouble_sec(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_csc(double * res, double x, int flags); int arb_fpwrap_cdouble_csc(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_sinc(double * res, double x, int flags); int arb_fpwrap_cdouble_sinc(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_sin_pi(double * res, double x, int flags); int arb_fpwrap_cdouble_sin_pi(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_cos_pi(double * res, double x, int flags); int arb_fpwrap_cdouble_cos_pi(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_tan_pi(double * res, double x, int flags); int arb_fpwrap_cdouble_tan_pi(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_cot_pi(double * res, double x, int flags); int arb_fpwrap_cdouble_cot_pi(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_sinc_pi(double * res, double x, int flags); int arb_fpwrap_cdouble_sinc_pi(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_asin(double * res, double x, int flags); int arb_fpwrap_cdouble_asin(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_acos(double * res, double x, int flags); int arb_fpwrap_cdouble_acos(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_atan(double * res, double x, int flags); int arb_fpwrap_cdouble_atan(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_atan2(double * res, double x1, double x2, int flags); int arb_fpwrap_double_asinh(double * res, double x, int flags); int arb_fpwrap_cdouble_asinh(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_acosh(double * res, double x, int flags); int arb_fpwrap_cdouble_acosh(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_atanh(double * res, double x, int flags); int arb_fpwrap_cdouble_atanh(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_lambertw(double * res, double x, slong branch, int flags); int arb_fpwrap_cdouble_lambertw(complex_double * res, complex_double x, slong branch, int flags); int arb_fpwrap_double_rising(double * res, double x, double n, int flags); int arb_fpwrap_cdouble_rising(complex_double * res, complex_double x, complex_double n, int flags); int arb_fpwrap_double_gamma(double * res, double x, int flags); int arb_fpwrap_cdouble_gamma(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_rgamma(double * res, double x, int flags); int arb_fpwrap_cdouble_rgamma(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_lgamma(double * res, double x, int flags); int arb_fpwrap_cdouble_lgamma(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_digamma(double * res, double x, int flags); int arb_fpwrap_cdouble_digamma(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_zeta(double * res, double x, int flags); int arb_fpwrap_cdouble_zeta(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_hurwitz_zeta(double * res, double s, double z, int flags); int arb_fpwrap_cdouble_hurwitz_zeta(complex_double * res, complex_double s, complex_double z, int flags); int arb_fpwrap_double_barnes_g(double * res, double x, int flags); int arb_fpwrap_cdouble_barnes_g(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_log_barnes_g(double * res, double x, int flags); int arb_fpwrap_cdouble_log_barnes_g(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_polygamma(double * res, double s, double z, int flags); int arb_fpwrap_cdouble_polygamma(complex_double * res, complex_double s, complex_double z, int flags); int arb_fpwrap_double_polylog(double * res, double s, double z, int flags); int arb_fpwrap_cdouble_polylog(complex_double * res, complex_double s, complex_double z, int flags); int arb_fpwrap_double_lerch_phi(double * res, double z, double s, double a, int flags); int arb_fpwrap_cdouble_lerch_phi(complex_double * res, complex_double z, complex_double s, complex_double a, int flags); int arb_fpwrap_cdouble_dirichlet_eta(complex_double * res, complex_double s, int flags); int arb_fpwrap_cdouble_riemann_xi(complex_double * res, complex_double s, int flags); int arb_fpwrap_cdouble_hardy_theta(complex_double * res, complex_double z, int flags); int arb_fpwrap_cdouble_hardy_z(complex_double * res, complex_double z, int flags); int arb_fpwrap_cdouble_zeta_zero(complex_double * res, ulong n, int flags); int arb_fpwrap_double_erf(double * res, double x, int flags); int arb_fpwrap_cdouble_erf(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_erfc(double * res, double x, int flags); int arb_fpwrap_cdouble_erfc(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_erfi(double * res, double x, int flags); int arb_fpwrap_cdouble_erfi(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_erfinv(double * res, double x, int flags); int arb_fpwrap_double_erfcinv(double * res, double x, int flags); int arb_fpwrap_double_fresnel_s(double * res, double x, int normalized, int flags); int arb_fpwrap_cdouble_fresnel_s(complex_double * res, complex_double x, int normalized, int flags); int arb_fpwrap_double_fresnel_c(double * res, double x, int normalized, int flags); int arb_fpwrap_cdouble_fresnel_c(complex_double * res, complex_double x, int normalized, int flags); int arb_fpwrap_double_gamma_upper(double * res, double s, double z, int regularized, int flags); int arb_fpwrap_cdouble_gamma_upper(complex_double * res, complex_double s, complex_double z, int regularized, int flags); int arb_fpwrap_double_gamma_lower(double * res, double s, double z, int regularized, int flags); int arb_fpwrap_cdouble_gamma_lower(complex_double * res, complex_double s, complex_double z, int regularized, int flags); int arb_fpwrap_double_beta_lower(double * res, double a, double b, double z, int regularized, int flags); int arb_fpwrap_cdouble_beta_lower(complex_double * res, complex_double a, complex_double b, complex_double z, int regularized, int flags); int arb_fpwrap_double_exp_integral_e(double * res, double s, double z, int flags); int arb_fpwrap_cdouble_exp_integral_e(complex_double * res, complex_double s, complex_double z, int flags); int arb_fpwrap_double_exp_integral_ei(double * res, double x, int flags); int arb_fpwrap_cdouble_exp_integral_ei(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_sin_integral(double * res, double x, int flags); int arb_fpwrap_cdouble_sin_integral(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_cos_integral(double * res, double x, int flags); int arb_fpwrap_cdouble_cos_integral(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_sinh_integral(double * res, double x, int flags); int arb_fpwrap_cdouble_sinh_integral(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_cosh_integral(double * res, double x, int flags); int arb_fpwrap_cdouble_cosh_integral(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_log_integral(double * res, double x, int offset, int flags); int arb_fpwrap_cdouble_log_integral(complex_double * res, complex_double x, int offset, int flags); int arb_fpwrap_double_dilog(double * res, double x, int flags); int arb_fpwrap_cdouble_dilog(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_bessel_j(double * res, double nu, double x, int flags); int arb_fpwrap_cdouble_bessel_j(complex_double * res, complex_double nu, complex_double x, int flags); int arb_fpwrap_double_bessel_y(double * res, double nu, double x, int flags); int arb_fpwrap_cdouble_bessel_y(complex_double * res, complex_double nu, complex_double x, int flags); int arb_fpwrap_double_bessel_i(double * res, double nu, double x, int flags); int arb_fpwrap_cdouble_bessel_i(complex_double * res, complex_double nu, complex_double x, int flags); int arb_fpwrap_double_bessel_k(double * res, double nu, double x, int flags); int arb_fpwrap_cdouble_bessel_k(complex_double * res, complex_double nu, complex_double x, int flags); int arb_fpwrap_double_bessel_k_scaled(double * res, double nu, double x, int flags); int arb_fpwrap_cdouble_bessel_k_scaled(complex_double * res, complex_double nu, complex_double x, int flags); int arb_fpwrap_double_airy_ai(double * res, double x, int flags); int arb_fpwrap_cdouble_airy_ai(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_airy_ai_prime(double * res, double x, int flags); int arb_fpwrap_cdouble_airy_ai_prime(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_airy_bi(double * res, double x, int flags); int arb_fpwrap_cdouble_airy_bi(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_airy_bi_prime(double * res, double x, int flags); int arb_fpwrap_cdouble_airy_bi_prime(complex_double * res, complex_double x, int flags); int arb_fpwrap_double_airy_ai_zero(double * res, ulong n, int flags); int arb_fpwrap_double_airy_ai_prime_zero(double * res, ulong n, int flags); int arb_fpwrap_double_airy_bi_zero(double * res, ulong n, int flags); int arb_fpwrap_double_airy_bi_prime_zero(double * res, ulong n, int flags); int arb_fpwrap_double_coulomb_f(double * res, double l, double eta, double x, int flags); int arb_fpwrap_cdouble_coulomb_f(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags); int arb_fpwrap_double_coulomb_g(double * res, double l, double eta, double x, int flags); int arb_fpwrap_cdouble_coulomb_g(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags); int arb_fpwrap_cdouble_coulomb_hpos(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags); int arb_fpwrap_cdouble_coulomb_hneg(complex_double * res, complex_double l, complex_double eta, complex_double x, int flags); int arb_fpwrap_double_chebyshev_t(double * res, double n, double x, int flags); int arb_fpwrap_cdouble_chebyshev_t(complex_double * res, complex_double n, complex_double x, int flags); int arb_fpwrap_double_chebyshev_u(double * res, double n, double x, int flags); int arb_fpwrap_cdouble_chebyshev_u(complex_double * res, complex_double n, complex_double x, int flags); int arb_fpwrap_double_jacobi_p(double * res, double n, double a, double b, double x, int flags); int arb_fpwrap_cdouble_jacobi_p(complex_double * res, complex_double n, complex_double a, complex_double b, complex_double x, int flags); int arb_fpwrap_double_gegenbauer_c(double * res, double n, double m, double x, int flags); int arb_fpwrap_cdouble_gegenbauer_c(complex_double * res, complex_double n, complex_double m, complex_double x, int flags); int arb_fpwrap_double_laguerre_l(double * res, double n, double m, double x, int flags); int arb_fpwrap_cdouble_laguerre_l(complex_double * res, complex_double n, complex_double m, complex_double x, int flags); int arb_fpwrap_double_hermite_h(double * res, double n, double x, int flags); int arb_fpwrap_cdouble_hermite_h(complex_double * res, complex_double n, complex_double x, int flags); int arb_fpwrap_double_legendre_p(double * res, double n, double m, double x, int type, int flags); int arb_fpwrap_cdouble_legendre_p(complex_double * res, complex_double n, complex_double m, complex_double x, int type, int flags); int arb_fpwrap_double_legendre_q(double * res, double n, double m, double x, int type, int flags); int arb_fpwrap_cdouble_legendre_q(complex_double * res, complex_double n, complex_double m, complex_double x, int type, int flags); int arb_fpwrap_double_legendre_root(double * res1, double * res2, ulong n, ulong k, int flags); int arb_fpwrap_cdouble_spherical_y(complex_double * res, slong n, slong m, complex_double x1, complex_double x2, int flags); int arb_fpwrap_double_hypgeom_0f1(double * res, double a, double x, int regularized, int flags); int arb_fpwrap_cdouble_hypgeom_0f1(complex_double * res, complex_double a, complex_double x, int regularized, int flags); int arb_fpwrap_double_hypgeom_1f1(double * res, double a, double b, double x, int regularized, int flags); int arb_fpwrap_cdouble_hypgeom_1f1(complex_double * res, complex_double a, complex_double b, complex_double x, int regularized, int flags); int arb_fpwrap_double_hypgeom_u(double * res, double a, double b, double x, int flags); int arb_fpwrap_cdouble_hypgeom_u(complex_double * res, complex_double a, complex_double b, complex_double x, int flags); int arb_fpwrap_double_hypgeom_2f1(double * res, double a, double b, double c, double x, int regularized, int flags); int arb_fpwrap_cdouble_hypgeom_2f1(complex_double * res, complex_double a, complex_double b, complex_double c, complex_double x, int regularized, int flags); int arb_fpwrap_double_hypgeom_pfq(double * res, const double * a, slong p, const double * b, slong q, double z, int regularized, int flags); int arb_fpwrap_cdouble_hypgeom_pfq(complex_double * res, const complex_double * a, slong p, const complex_double * b, slong q, complex_double z, int regularized, int flags); int arb_fpwrap_double_agm(double * res, double x, double y, int flags); int arb_fpwrap_cdouble_agm(complex_double * res, complex_double x, complex_double y, int flags); int arb_fpwrap_cdouble_elliptic_k(complex_double * res, complex_double m, int flags); int arb_fpwrap_cdouble_elliptic_e(complex_double * res, complex_double m, int flags); int arb_fpwrap_cdouble_elliptic_pi(complex_double * res, complex_double n, complex_double m, int flags); int arb_fpwrap_cdouble_elliptic_f(complex_double * res, complex_double phi, complex_double m, int pi, int flags); int arb_fpwrap_cdouble_elliptic_e_inc(complex_double * res, complex_double phi, complex_double m, int pi, int flags); int arb_fpwrap_cdouble_elliptic_pi_inc(complex_double * res, complex_double n, complex_double phi, complex_double m, int pi, int flags); int arb_fpwrap_cdouble_elliptic_rf(complex_double * res, complex_double x, complex_double y, complex_double z, int option, int flags); int arb_fpwrap_cdouble_elliptic_rg(complex_double * res, complex_double x, complex_double y, complex_double z, int option, int flags); int arb_fpwrap_cdouble_elliptic_rj(complex_double * res, complex_double x, complex_double y, complex_double z, complex_double w, int option, int flags); int arb_fpwrap_cdouble_elliptic_p(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_elliptic_p_prime(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_elliptic_inv_p(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_elliptic_zeta(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_elliptic_sigma(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_jacobi_theta_1(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_jacobi_theta_2(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_jacobi_theta_3(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_jacobi_theta_4(complex_double * res, complex_double z, complex_double tau, int flags); int arb_fpwrap_cdouble_dedekind_eta(complex_double * res, complex_double tau, int flags); int arb_fpwrap_cdouble_modular_j(complex_double * res, complex_double tau, int flags); int arb_fpwrap_cdouble_modular_lambda(complex_double * res, complex_double tau, int flags); int arb_fpwrap_cdouble_modular_delta(complex_double * res, complex_double tau, int flags); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arb_fpwrap/000077500000000000000000000000001461254215100155455ustar00rootroot00000000000000flint-3.1.3/src/arb_fpwrap/fpwrap.c000066400000000000000000001217731461254215100172230ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "acb.h" #include "acb_dirichlet.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #include "acb_elliptic.h" #include "acb_modular.h" #include "arb_fpwrap.h" int arb_accurate_enough_d(const arb_t x, int flags) { if (flags & FPWRAP_CORRECT_ROUNDING) { return arb_can_round_arf(x, 53, ARF_RND_NEAR); } if (arb_rel_accuracy_bits(x) >= 53 + 1) return 1; /* Rounding will give +/- 0 (we don't worry which) */ if (mag_cmp_2exp_si(arb_radref(x), -1077) < 0 && arf_cmpabs_2exp_si(arb_midref(x), -1077) < 0) { return 1; } /* Rounding will give +/- inf */ if (arb_rel_accuracy_bits(x) > 2 && arf_cmpabs_2exp_si(arb_midref(x), 1024) > 0) { return 1; } return 0; } int acb_accurate_enough_d(const acb_t x, int flags) { if (flags & FPWRAP_CORRECT_ROUNDING) { return arb_can_round_arf(acb_realref(x), 53, ARF_RND_NEAR) && arb_can_round_arf(acb_imagref(x), 53, ARF_RND_NEAR); } if (flags & FPWRAP_ACCURATE_PARTS) { return arb_accurate_enough_d(acb_realref(x), flags) && arb_accurate_enough_d(acb_imagref(x), flags); } if (acb_rel_accuracy_bits(x) >= 53 + 1) return 1; /* Rounding will give +/- 0 (we don't worry which) */ if (mag_cmp_2exp_si(arb_radref(acb_realref(x)), -1077) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_realref(x)), -1077) < 0 && mag_cmp_2exp_si(arb_radref(acb_imagref(x)), -1077) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(x)), -1077) < 0) { return 1; } /* Rounding will give +/- inf */ if (acb_rel_accuracy_bits(x) > 2 && (arf_cmpabs_2exp_si(arb_midref(acb_realref(x)), 1024) > 0 || arf_cmpabs_2exp_si(arb_midref(acb_imagref(x)), 1024) > 0)) { return 1; } return 0; } #define WP_INITIAL 64 #define DOUBLE_CHECK_RESULT \ if (arb_accurate_enough_d(arb_res, flags)) \ { \ *res = arf_get_d(arb_midref(arb_res), ARF_RND_NEAR); \ status = FPWRAP_SUCCESS; \ break; \ } \ if (wp >= double_wp_max(flags)) \ { \ *res = D_NAN; \ status = FPWRAP_UNABLE; \ break; \ } \ #define DOUBLE_CHECK_RESULT2 \ if (arb_accurate_enough_d(arb_res1, flags) && arb_accurate_enough_d(arb_res2, flags)) \ { \ *res1 = arf_get_d(arb_midref(arb_res1), ARF_RND_NEAR); \ *res2 = arf_get_d(arb_midref(arb_res2), ARF_RND_NEAR); \ status = FPWRAP_SUCCESS; \ break; \ } \ if (wp >= double_wp_max(flags)) \ { \ *res1 = D_NAN; \ *res2 = D_NAN; \ status = FPWRAP_UNABLE; \ break; \ } \ #define CDOUBLE_CHECK_RESULT \ if (acb_accurate_enough_d(acb_res, flags)) \ { \ res->real = arf_get_d(arb_midref(acb_realref(acb_res)), ARF_RND_NEAR); \ res->imag = arf_get_d(arb_midref(acb_imagref(acb_res)), ARF_RND_NEAR); \ status = FPWRAP_SUCCESS; \ break; \ } \ if (wp >= double_wp_max(flags)) \ { \ res->real = D_NAN; \ res->imag = D_NAN; \ status = FPWRAP_UNABLE; \ break; \ } static slong double_wp_max(int flags) { int iters; iters = flags / FPWRAP_WORK_LIMIT; if (iters <= 0) return 64 << 7; if (iters >= 25) return 64 << 24; return 64 << iters; } typedef void (*arb_func_1)(arb_t, const arb_t, slong prec); typedef void (*arb_func_2)(arb_t, const arb_t, const arb_t, slong prec); typedef void (*arb_func_3)(arb_t, const arb_t, const arb_t, const arb_t, slong prec); typedef void (*arb_func_4)(arb_t, const arb_t, const arb_t, const arb_t, const arb_t, slong prec); typedef void (*acb_func_1)(acb_t, const acb_t, slong prec); typedef void (*acb_func_2)(acb_t, const acb_t, const acb_t, slong prec); typedef void (*acb_func_3)(acb_t, const acb_t, const acb_t, const acb_t, slong prec); typedef void (*acb_func_4)(acb_t, const acb_t, const acb_t, const acb_t, const acb_t, slong prec); typedef void (*arb_func_1_int)(arb_t, const arb_t, int, slong prec); typedef void (*arb_func_2_int)(arb_t, const arb_t, const arb_t, int, slong prec); typedef void (*arb_func_3_int)(arb_t, const arb_t, const arb_t, const arb_t, int, slong prec); typedef void (*arb_func_4_int)(arb_t, const arb_t, const arb_t, const arb_t, const arb_t, int, slong prec); typedef void (*acb_func_1_int)(acb_t, const acb_t, int, slong prec); typedef void (*acb_func_2_int)(acb_t, const acb_t, const acb_t, int, slong prec); typedef void (*acb_func_3_int)(acb_t, const acb_t, const acb_t, const acb_t, int, slong prec); typedef void (*acb_func_4_int)(acb_t, const acb_t, const acb_t, const acb_t, const acb_t, int, slong prec); int arb_fpwrap_double_1(double * res, arb_func_1 func, double x, int flags) { arb_t arb_res, arb_x; slong wp; int status; arb_init(arb_res); arb_init(arb_x); arb_set_d(arb_x, x); if (!arb_is_finite(arb_x)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x); arb_clear(arb_res); return status; } int arb_fpwrap_double_2(double * res, arb_func_2 func, double x1, double x2, int flags) { arb_t arb_res, arb_x1, arb_x2; slong wp; int status; arb_init(arb_res); arb_init(arb_x1); arb_init(arb_x2); arb_set_d(arb_x1, x1); arb_set_d(arb_x2, x2); if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x1, arb_x2, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x1); arb_clear(arb_x2); arb_clear(arb_res); return status; } int arb_fpwrap_double_3(double * res, arb_func_3 func, double x1, double x2, double x3, int flags) { arb_t arb_res, arb_x1, arb_x2, arb_x3; slong wp; int status; arb_init(arb_res); arb_init(arb_x1); arb_init(arb_x2); arb_init(arb_x3); arb_set_d(arb_x1, x1); arb_set_d(arb_x2, x2); arb_set_d(arb_x3, x3); if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x1, arb_x2, arb_x3, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x1); arb_clear(arb_x2); arb_clear(arb_x3); arb_clear(arb_res); return status; } int arb_fpwrap_double_4(double * res, arb_func_4 func, double x1, double x2, double x3, double x4, int flags) { arb_t arb_res, arb_x1, arb_x2, arb_x3, arb_x4; slong wp; int status; arb_init(arb_res); arb_init(arb_x1); arb_init(arb_x2); arb_init(arb_x3); arb_init(arb_x4); arb_set_d(arb_x1, x1); arb_set_d(arb_x2, x2); arb_set_d(arb_x3, x3); arb_set_d(arb_x3, x4); if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3) || !arb_is_finite(arb_x4)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x1, arb_x2, arb_x3, arb_x4, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x1); arb_clear(arb_x2); arb_clear(arb_x3); arb_clear(arb_x4); arb_clear(arb_res); return status; } int arb_fpwrap_cdouble_1(complex_double * res, acb_func_1 func, complex_double x, int flags) { acb_t acb_res, acb_x; slong wp; int status; acb_init(acb_res); acb_init(acb_x); acb_set_d_d(acb_x, x.real, x.imag); if (!acb_is_finite(acb_x)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x); acb_clear(acb_res); return status; } int arb_fpwrap_cdouble_2(complex_double * res, acb_func_2 func, complex_double x1, complex_double x2, int flags) { acb_t acb_res, acb_x1, acb_x2; slong wp; int status; acb_init(acb_res); acb_init(acb_x1); acb_init(acb_x2); acb_set_d_d(acb_x1, x1.real, x1.imag); acb_set_d_d(acb_x2, x2.real, x2.imag); if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x1, acb_x2, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x1); acb_clear(acb_x2); acb_clear(acb_res); return status; } int arb_fpwrap_cdouble_3(complex_double * res, acb_func_3 func, complex_double x1, complex_double x2, complex_double x3, int flags) { acb_t acb_res, acb_x1, acb_x2, acb_x3; slong wp; int status; acb_init(acb_res); acb_init(acb_x1); acb_init(acb_x2); acb_init(acb_x3); acb_set_d_d(acb_x1, x1.real, x1.imag); acb_set_d_d(acb_x2, x2.real, x2.imag); acb_set_d_d(acb_x3, x3.real, x3.imag); if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x1, acb_x2, acb_x3, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x1); acb_clear(acb_x2); acb_clear(acb_x3); acb_clear(acb_res); return status; } int arb_fpwrap_cdouble_4(complex_double * res, acb_func_4 func, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int flags) { acb_t acb_res, acb_x1, acb_x2, acb_x3, acb_x4; slong wp; int status; acb_init(acb_res); acb_init(acb_x1); acb_init(acb_x2); acb_init(acb_x3); acb_init(acb_x4); acb_set_d_d(acb_x1, x1.real, x1.imag); acb_set_d_d(acb_x2, x2.real, x2.imag); acb_set_d_d(acb_x3, x3.real, x3.imag); acb_set_d_d(acb_x4, x4.real, x4.imag); if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3) || !acb_is_finite(acb_x4)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x1, acb_x2, acb_x3, acb_x4, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x1); acb_clear(acb_x2); acb_clear(acb_x3); acb_clear(acb_x4); acb_clear(acb_res); return status; } int arb_fpwrap_double_1_int(double * res, arb_func_1_int func, double x, int intx, int flags) { arb_t arb_res, arb_x; slong wp; int status; arb_init(arb_res); arb_init(arb_x); arb_set_d(arb_x, x); if (!arb_is_finite(arb_x)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x, intx, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x); arb_clear(arb_res); return status; } int arb_fpwrap_double_2_int(double * res, arb_func_2_int func, double x1, double x2, int intx, int flags) { arb_t arb_res, arb_x1, arb_x2; slong wp; int status; arb_init(arb_res); arb_init(arb_x1); arb_init(arb_x2); arb_set_d(arb_x1, x1); arb_set_d(arb_x2, x2); if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x1, arb_x2, intx, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x1); arb_clear(arb_x2); arb_clear(arb_res); return status; } int arb_fpwrap_double_3_int(double * res, arb_func_3_int func, double x1, double x2, double x3, int intx, int flags) { arb_t arb_res, arb_x1, arb_x2, arb_x3; slong wp; int status; arb_init(arb_res); arb_init(arb_x1); arb_init(arb_x2); arb_init(arb_x3); arb_set_d(arb_x1, x1); arb_set_d(arb_x2, x2); arb_set_d(arb_x3, x3); if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x1, arb_x2, arb_x3, intx, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x1); arb_clear(arb_x2); arb_clear(arb_x3); arb_clear(arb_res); return status; } int arb_fpwrap_double_4_int(double * res, arb_func_4_int func, double x1, double x2, double x3, double x4, int intx, int flags) { arb_t arb_res, arb_x1, arb_x2, arb_x3, arb_x4; slong wp; int status; arb_init(arb_res); arb_init(arb_x1); arb_init(arb_x2); arb_init(arb_x3); arb_init(arb_x4); arb_set_d(arb_x1, x1); arb_set_d(arb_x2, x2); arb_set_d(arb_x3, x3); arb_set_d(arb_x4, x4); if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3) || !arb_is_finite(arb_x4)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(arb_res, arb_x1, arb_x2, arb_x3, arb_x4, intx, wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x1); arb_clear(arb_x2); arb_clear(arb_x3); arb_clear(arb_x4); arb_clear(arb_res); return status; } int arb_fpwrap_cdouble_1_int(complex_double * res, acb_func_1_int func, complex_double x, int intx, int flags) { acb_t acb_res, acb_x; slong wp; int status; acb_init(acb_res); acb_init(acb_x); acb_set_d_d(acb_x, x.real, x.imag); if (!acb_is_finite(acb_x)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x, intx, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x); acb_clear(acb_res); return status; } int arb_fpwrap_cdouble_2_int(complex_double * res, acb_func_2_int func, complex_double x1, complex_double x2, int intx, int flags) { acb_t acb_res, acb_x1, acb_x2; slong wp; int status; acb_init(acb_res); acb_init(acb_x1); acb_init(acb_x2); acb_set_d_d(acb_x1, x1.real, x1.imag); acb_set_d_d(acb_x2, x2.real, x2.imag); if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x1, acb_x2, intx, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x1); acb_clear(acb_x2); acb_clear(acb_res); return status; } int arb_fpwrap_cdouble_3_int(complex_double * res, acb_func_3_int func, complex_double x1, complex_double x2, complex_double x3, int intx, int flags) { acb_t acb_res, acb_x1, acb_x2, acb_x3; slong wp; int status; acb_init(acb_res); acb_init(acb_x1); acb_init(acb_x2); acb_init(acb_x3); acb_set_d_d(acb_x1, x1.real, x1.imag); acb_set_d_d(acb_x2, x2.real, x2.imag); acb_set_d_d(acb_x3, x3.real, x3.imag); if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x1, acb_x2, acb_x3, intx, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x1); acb_clear(acb_x2); acb_clear(acb_x3); acb_clear(acb_res); return status; } int arb_fpwrap_cdouble_4_int(complex_double * res, acb_func_4_int func, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int intx, int flags) { acb_t acb_res, acb_x1, acb_x2, acb_x3, acb_x4; slong wp; int status; acb_init(acb_res); acb_init(acb_x1); acb_init(acb_x2); acb_init(acb_x3); acb_init(acb_x4); acb_set_d_d(acb_x1, x1.real, x1.imag); acb_set_d_d(acb_x2, x2.real, x2.imag); acb_set_d_d(acb_x3, x3.real, x3.imag); acb_set_d_d(acb_x4, x4.real, x4.imag); if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3) || !acb_is_finite(acb_x4)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { func(acb_res, acb_x1, acb_x2, acb_x3, acb_x4, intx, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x1); acb_clear(acb_x2); acb_clear(acb_x3); acb_clear(acb_x4); acb_clear(acb_res); return status; } #define DEF_DOUBLE_FUN_1(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x, int flags) \ { \ return arb_fpwrap_double_1(res, arb_fun, x, flags); \ } \ #define DEF_DOUBLE_FUN_2(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x1, double x2, int flags) \ { \ return arb_fpwrap_double_2(res, arb_fun, x1, x2, flags); \ } \ #define DEF_DOUBLE_FUN_3(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, int flags) \ { \ return arb_fpwrap_double_3(res, arb_fun, x1, x2, x3, flags); \ } \ #define DEF_DOUBLE_FUN_4(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, double x4, int flags) \ { \ return arb_fpwrap_double_4(res, arb_fun, x1, x2, x3, x4, flags); \ } \ #define DEF_CDOUBLE_FUN_1(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x, int flags) \ { \ return arb_fpwrap_cdouble_1(res, acb_fun, x, flags); \ } \ #define DEF_CDOUBLE_FUN_2(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, int flags) \ { \ return arb_fpwrap_cdouble_2(res, acb_fun, x1, x2, flags); \ } \ #define DEF_CDOUBLE_FUN_3(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, int flags) \ { \ return arb_fpwrap_cdouble_3(res, acb_fun, x1, x2, x3, flags); \ } \ #define DEF_CDOUBLE_FUN_4(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int flags) \ { \ return arb_fpwrap_cdouble_4(res, acb_fun, x1, x2, x3, x4, flags); \ } \ #define DEF_DOUBLE_FUN_1_INT(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x, int intx, int flags) \ { \ return arb_fpwrap_double_1_int(res, arb_fun, x, intx, flags); \ } \ #define DEF_DOUBLE_FUN_2_INT(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x1, double x2, int intx, int flags) \ { \ return arb_fpwrap_double_2_int(res, arb_fun, x1, x2, intx, flags); \ } \ #define DEF_DOUBLE_FUN_3_INT(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, int intx, int flags) \ { \ return arb_fpwrap_double_3_int(res, arb_fun, x1, x2, x3, intx, flags); \ } \ #define DEF_DOUBLE_FUN_4_INT(name, arb_fun) \ int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, double x4, int intx, int flags) \ { \ return arb_fpwrap_double_4_int(res, arb_fun, x1, x2, x3, x4, intx, flags); \ } \ #define DEF_CDOUBLE_FUN_1_INT(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x, int intx, int flags) \ { \ return arb_fpwrap_cdouble_1_int(res, acb_fun, x, intx, flags); \ } \ #define DEF_CDOUBLE_FUN_2_INT(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, int intx, int flags) \ { \ return arb_fpwrap_cdouble_2_int(res, acb_fun, x1, x2, intx, flags); \ } \ #define DEF_CDOUBLE_FUN_3_INT(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, int intx, int flags) \ { \ return arb_fpwrap_cdouble_3_int(res, acb_fun, x1, x2, x3, intx, flags); \ } \ #define DEF_CDOUBLE_FUN_4_INT(name, acb_fun) \ int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int intx, int flags) \ { \ return arb_fpwrap_cdouble_4_int(res, acb_fun, x1, x2, x3, x4, intx, flags); \ } \ DEF_DOUBLE_FUN_1(exp, arb_exp) DEF_CDOUBLE_FUN_1(exp, acb_exp) DEF_DOUBLE_FUN_1(expm1, arb_expm1) DEF_CDOUBLE_FUN_1(expm1, acb_expm1) DEF_DOUBLE_FUN_1(log, arb_log) DEF_CDOUBLE_FUN_1(log, acb_log) DEF_DOUBLE_FUN_1(log1p, arb_log1p) DEF_CDOUBLE_FUN_1(log1p, acb_log1p) DEF_DOUBLE_FUN_2(pow, arb_pow) DEF_CDOUBLE_FUN_2(pow, acb_pow) DEF_DOUBLE_FUN_1(sqrt, arb_sqrt) DEF_CDOUBLE_FUN_1(sqrt, acb_sqrt) DEF_DOUBLE_FUN_1(rsqrt, arb_rsqrt) DEF_CDOUBLE_FUN_1(rsqrt, acb_rsqrt) static void _arb_cbrt(arb_t res, const arb_t x, slong prec) { arb_root_ui(res, x, 3, prec); } static void _acb_cbrt(acb_t res, const acb_t x, slong prec) { acb_root_ui(res, x, 3, prec); } DEF_DOUBLE_FUN_1(cbrt, _arb_cbrt) DEF_CDOUBLE_FUN_1(cbrt, _acb_cbrt) DEF_DOUBLE_FUN_1(sin, arb_sin) DEF_CDOUBLE_FUN_1(sin, acb_sin) DEF_DOUBLE_FUN_1(cos, arb_cos) DEF_CDOUBLE_FUN_1(cos, acb_cos) DEF_DOUBLE_FUN_1(tan, arb_tan) DEF_CDOUBLE_FUN_1(tan, acb_tan) DEF_DOUBLE_FUN_1(cot, arb_cot) DEF_CDOUBLE_FUN_1(cot, acb_cot) DEF_DOUBLE_FUN_1(sec, arb_sec) DEF_CDOUBLE_FUN_1(sec, acb_sec) DEF_DOUBLE_FUN_1(csc, arb_csc) DEF_CDOUBLE_FUN_1(csc, acb_csc) DEF_DOUBLE_FUN_1(sinc, arb_sinc) DEF_CDOUBLE_FUN_1(sinc, acb_sinc) DEF_DOUBLE_FUN_1(sin_pi, arb_sin_pi) DEF_CDOUBLE_FUN_1(sin_pi, acb_sin_pi) DEF_DOUBLE_FUN_1(cos_pi, arb_cos_pi) DEF_CDOUBLE_FUN_1(cos_pi, acb_cos_pi) DEF_DOUBLE_FUN_1(tan_pi, arb_tan_pi) DEF_CDOUBLE_FUN_1(tan_pi, acb_tan_pi) DEF_DOUBLE_FUN_1(cot_pi, arb_cot_pi) DEF_CDOUBLE_FUN_1(cot_pi, acb_cot_pi) DEF_DOUBLE_FUN_1(sinc_pi, arb_sinc_pi) DEF_CDOUBLE_FUN_1(sinc_pi, acb_sinc_pi) DEF_DOUBLE_FUN_1(asin, arb_asin) DEF_CDOUBLE_FUN_1(asin, acb_asin) DEF_DOUBLE_FUN_1(acos, arb_acos) DEF_CDOUBLE_FUN_1(acos, acb_acos) DEF_DOUBLE_FUN_1(atan, arb_atan) DEF_CDOUBLE_FUN_1(atan, acb_atan) DEF_DOUBLE_FUN_2(atan2, arb_atan2) DEF_DOUBLE_FUN_1(asinh, arb_asinh) DEF_CDOUBLE_FUN_1(asinh, acb_asinh) DEF_DOUBLE_FUN_1(acosh, arb_acosh) DEF_CDOUBLE_FUN_1(acosh, acb_acosh) DEF_DOUBLE_FUN_1(atanh, arb_atanh) DEF_CDOUBLE_FUN_1(atanh, acb_atanh) DEF_DOUBLE_FUN_2(rising, arb_rising) DEF_CDOUBLE_FUN_2(rising, acb_rising) DEF_DOUBLE_FUN_1(gamma, arb_gamma) DEF_CDOUBLE_FUN_1(gamma, acb_gamma) DEF_DOUBLE_FUN_1(rgamma, arb_rgamma) DEF_CDOUBLE_FUN_1(rgamma, acb_rgamma) DEF_DOUBLE_FUN_1(lgamma, arb_lgamma) DEF_CDOUBLE_FUN_1(lgamma, acb_lgamma) DEF_DOUBLE_FUN_1(digamma, arb_digamma) DEF_CDOUBLE_FUN_1(digamma, acb_digamma) DEF_DOUBLE_FUN_1(zeta, arb_zeta) DEF_CDOUBLE_FUN_1(zeta, acb_zeta) DEF_DOUBLE_FUN_2(hurwitz_zeta, arb_hurwitz_zeta) DEF_CDOUBLE_FUN_2(hurwitz_zeta, acb_hurwitz_zeta) static void _arb_polygamma(arb_t res, const arb_t s, const arb_t z, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_set_arb(t, s); acb_set_arb(u, z); acb_polygamma(v, t, u, prec); if (acb_is_real(v)) arb_set(res, acb_realref(v)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } static void _arb_dirichlet_lerch_phi(arb_t res, const arb_t z, const arb_t s, const arb_t a, slong prec) { acb_t t, u, v, w; acb_init(t); acb_init(u); acb_init(v); acb_init(w); acb_set_arb(t, z); acb_set_arb(u, s); acb_set_arb(v, a); acb_dirichlet_lerch_phi(w, t, u, v, prec); if (acb_is_real(w)) arb_set(res, acb_realref(w)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); } static void _arb_barnes_g(arb_t res, const arb_t x, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_set_arb(t, x); acb_barnes_g(u, t, prec); arb_set(res, acb_realref(u)); acb_clear(t); acb_clear(u); } static void _arb_log_barnes_g(arb_t res, const arb_t x, slong prec) { if (!arb_is_positive(x)) { arb_indeterminate(res); } else { acb_t t, u; acb_init(t); acb_init(u); acb_set_arb(t, x); acb_log_barnes_g(u, t, prec); arb_set(res, acb_realref(u)); acb_clear(t); acb_clear(u); } } DEF_DOUBLE_FUN_1(barnes_g, _arb_barnes_g) DEF_CDOUBLE_FUN_1(barnes_g, acb_barnes_g) DEF_DOUBLE_FUN_1(log_barnes_g, _arb_log_barnes_g) DEF_CDOUBLE_FUN_1(log_barnes_g, acb_log_barnes_g) DEF_DOUBLE_FUN_2(polygamma, _arb_polygamma) DEF_CDOUBLE_FUN_2(polygamma, acb_polygamma) DEF_DOUBLE_FUN_3(lerch_phi, _arb_dirichlet_lerch_phi) DEF_CDOUBLE_FUN_3(lerch_phi, acb_dirichlet_lerch_phi) DEF_DOUBLE_FUN_2(polylog, arb_polylog) DEF_CDOUBLE_FUN_2(polylog, acb_polylog) DEF_DOUBLE_FUN_1(dilog, arb_hypgeom_dilog) DEF_CDOUBLE_FUN_1(dilog, acb_hypgeom_dilog) DEF_DOUBLE_FUN_1(erf, arb_hypgeom_erf) DEF_CDOUBLE_FUN_1(erf, acb_hypgeom_erf) DEF_DOUBLE_FUN_1(erfc, arb_hypgeom_erfc) DEF_CDOUBLE_FUN_1(erfc, acb_hypgeom_erfc) DEF_DOUBLE_FUN_1(erfi, arb_hypgeom_erfi) DEF_CDOUBLE_FUN_1(erfi, acb_hypgeom_erfi) DEF_DOUBLE_FUN_1(erfinv, arb_hypgeom_erfinv) DEF_DOUBLE_FUN_1(erfcinv, arb_hypgeom_erfcinv) static void _arb_hypgeom_fresnel_s(arb_t res, const arb_t x, int normalized, slong prec) { arb_hypgeom_fresnel(res, NULL, x, normalized, prec); } static void _arb_hypgeom_fresnel_c(arb_t res, const arb_t x, int normalized, slong prec) { arb_hypgeom_fresnel(NULL, res, x, normalized, prec); } static void _acb_hypgeom_fresnel_s(acb_t res, const acb_t x, int normalized, slong prec) { acb_hypgeom_fresnel(res, NULL, x, normalized, prec); } static void _acb_hypgeom_fresnel_c(acb_t res, const acb_t x, int normalized, slong prec) { acb_hypgeom_fresnel(NULL, res, x, normalized, prec); } DEF_DOUBLE_FUN_1_INT(fresnel_s, _arb_hypgeom_fresnel_s) DEF_CDOUBLE_FUN_1_INT(fresnel_s, _acb_hypgeom_fresnel_s) DEF_DOUBLE_FUN_1_INT(fresnel_c, _arb_hypgeom_fresnel_c) DEF_CDOUBLE_FUN_1_INT(fresnel_c, _acb_hypgeom_fresnel_c) DEF_DOUBLE_FUN_2_INT(gamma_upper, arb_hypgeom_gamma_upper) DEF_CDOUBLE_FUN_2_INT(gamma_upper, acb_hypgeom_gamma_upper) DEF_DOUBLE_FUN_2_INT(gamma_lower, arb_hypgeom_gamma_lower) DEF_CDOUBLE_FUN_2_INT(gamma_lower, acb_hypgeom_gamma_lower) DEF_DOUBLE_FUN_3_INT(beta_lower, arb_hypgeom_beta_lower) DEF_CDOUBLE_FUN_3_INT(beta_lower, acb_hypgeom_beta_lower) DEF_DOUBLE_FUN_2(exp_integral_e, arb_hypgeom_expint) DEF_CDOUBLE_FUN_2(exp_integral_e, acb_hypgeom_expint) DEF_DOUBLE_FUN_1(exp_integral_ei, arb_hypgeom_ei) DEF_CDOUBLE_FUN_1(exp_integral_ei, acb_hypgeom_ei) DEF_DOUBLE_FUN_1(sin_integral, arb_hypgeom_si) DEF_CDOUBLE_FUN_1(sin_integral, acb_hypgeom_si) DEF_DOUBLE_FUN_1(cos_integral, arb_hypgeom_ci) DEF_CDOUBLE_FUN_1(cos_integral, acb_hypgeom_ci) DEF_DOUBLE_FUN_1(sinh_integral, arb_hypgeom_shi) DEF_CDOUBLE_FUN_1(sinh_integral, acb_hypgeom_shi) DEF_DOUBLE_FUN_1(cosh_integral, arb_hypgeom_chi) DEF_CDOUBLE_FUN_1(cosh_integral, acb_hypgeom_chi) DEF_DOUBLE_FUN_1_INT(log_integral, arb_hypgeom_li) DEF_CDOUBLE_FUN_1_INT(log_integral, acb_hypgeom_li) DEF_DOUBLE_FUN_2(bessel_j, arb_hypgeom_bessel_j) DEF_CDOUBLE_FUN_2(bessel_j, acb_hypgeom_bessel_j) DEF_DOUBLE_FUN_2(bessel_y, arb_hypgeom_bessel_y) DEF_CDOUBLE_FUN_2(bessel_y, acb_hypgeom_bessel_y) DEF_DOUBLE_FUN_2(bessel_i, arb_hypgeom_bessel_i) DEF_CDOUBLE_FUN_2(bessel_i, acb_hypgeom_bessel_i) DEF_DOUBLE_FUN_2(bessel_k, arb_hypgeom_bessel_k) DEF_CDOUBLE_FUN_2(bessel_k, acb_hypgeom_bessel_k) DEF_DOUBLE_FUN_2(bessel_k_scaled, arb_hypgeom_bessel_k_scaled) DEF_CDOUBLE_FUN_2(bessel_k_scaled, acb_hypgeom_bessel_k_scaled) static void _arb_hypgeom_airy_ai(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(res, NULL, NULL, NULL, x, prec); } static void _arb_hypgeom_airy_ai_prime(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(NULL, res, NULL, NULL, x, prec); } static void _arb_hypgeom_airy_bi(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(NULL, NULL, res, NULL, x, prec); } static void _arb_hypgeom_airy_bi_prime(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(NULL, NULL, NULL, res, x, prec); } static void _acb_hypgeom_airy_ai(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(res, NULL, NULL, NULL, x, prec); } static void _acb_hypgeom_airy_ai_prime(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(NULL, res, NULL, NULL, x, prec); } static void _acb_hypgeom_airy_bi(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(NULL, NULL, res, NULL, x, prec); } static void _acb_hypgeom_airy_bi_prime(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(NULL, NULL, NULL, res, x, prec); } DEF_DOUBLE_FUN_1(airy_ai, _arb_hypgeom_airy_ai) DEF_CDOUBLE_FUN_1(airy_ai, _acb_hypgeom_airy_ai) DEF_DOUBLE_FUN_1(airy_ai_prime, _arb_hypgeom_airy_ai_prime) DEF_CDOUBLE_FUN_1(airy_ai_prime, _acb_hypgeom_airy_ai_prime) DEF_DOUBLE_FUN_1(airy_bi, _arb_hypgeom_airy_bi) DEF_CDOUBLE_FUN_1(airy_bi, _acb_hypgeom_airy_bi) DEF_DOUBLE_FUN_1(airy_bi_prime, _arb_hypgeom_airy_bi_prime) DEF_CDOUBLE_FUN_1(airy_bi_prime, _acb_hypgeom_airy_bi_prime) static void _arb_hypgeom_coulomb_f(arb_t res, const arb_t l, const arb_t eta, const arb_t z, slong prec) { arb_hypgeom_coulomb(res, NULL, l, eta, z, prec); } static void _arb_hypgeom_coulomb_g(arb_t res, const arb_t l, const arb_t eta, const arb_t z, slong prec) { arb_hypgeom_coulomb(NULL, res, l, eta, z, prec); } static void _acb_hypgeom_coulomb_f(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(res, NULL, NULL, NULL, l, eta, z, prec); } static void _acb_hypgeom_coulomb_g(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(NULL, res, NULL, NULL, l, eta, z, prec); } static void _acb_hypgeom_coulomb_hpos(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(NULL, NULL, res, NULL, l, eta, z, prec); } static void _acb_hypgeom_coulomb_hneg(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(NULL, NULL, NULL, res, l, eta, z, prec); } DEF_DOUBLE_FUN_3(coulomb_f, _arb_hypgeom_coulomb_f) DEF_CDOUBLE_FUN_3(coulomb_f, _acb_hypgeom_coulomb_f) DEF_DOUBLE_FUN_3(coulomb_g, _arb_hypgeom_coulomb_g) DEF_CDOUBLE_FUN_3(coulomb_g, _acb_hypgeom_coulomb_g) DEF_CDOUBLE_FUN_3(coulomb_hpos, _acb_hypgeom_coulomb_hpos) DEF_CDOUBLE_FUN_3(coulomb_hneg, _acb_hypgeom_coulomb_hneg) DEF_DOUBLE_FUN_2(chebyshev_t, arb_hypgeom_chebyshev_t) DEF_CDOUBLE_FUN_2(chebyshev_t, acb_hypgeom_chebyshev_t) DEF_DOUBLE_FUN_2(chebyshev_u, arb_hypgeom_chebyshev_u) DEF_CDOUBLE_FUN_2(chebyshev_u, acb_hypgeom_chebyshev_u) DEF_DOUBLE_FUN_4(jacobi_p, arb_hypgeom_jacobi_p) DEF_CDOUBLE_FUN_4(jacobi_p, acb_hypgeom_jacobi_p) DEF_DOUBLE_FUN_3(gegenbauer_c, arb_hypgeom_gegenbauer_c) DEF_CDOUBLE_FUN_3(gegenbauer_c, acb_hypgeom_gegenbauer_c) DEF_DOUBLE_FUN_3(laguerre_l, arb_hypgeom_laguerre_l) DEF_CDOUBLE_FUN_3(laguerre_l, acb_hypgeom_laguerre_l) DEF_DOUBLE_FUN_2(hermite_h, arb_hypgeom_hermite_h) DEF_CDOUBLE_FUN_2(hermite_h, acb_hypgeom_hermite_h) DEF_DOUBLE_FUN_3_INT(legendre_p, arb_hypgeom_legendre_p) DEF_CDOUBLE_FUN_3_INT(legendre_p, acb_hypgeom_legendre_p) DEF_DOUBLE_FUN_3_INT(legendre_q, arb_hypgeom_legendre_q) DEF_CDOUBLE_FUN_3_INT(legendre_q, acb_hypgeom_legendre_q) int arb_fpwrap_cdouble_spherical_y(complex_double * res, slong n, slong m, complex_double x1, complex_double x2, int flags) { acb_t acb_res, acb_x1, acb_x2; slong wp; int status; acb_init(acb_res); acb_init(acb_x1); acb_init(acb_x2); acb_set_d_d(acb_x1, x1.real, x1.imag); acb_set_d_d(acb_x2, x2.real, x2.imag); if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { acb_hypgeom_spherical_y(acb_res, n, m, acb_x1, acb_x2, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x1); acb_clear(acb_x2); acb_clear(acb_res); return status; } DEF_DOUBLE_FUN_2_INT(hypgeom_0f1, arb_hypgeom_0f1) DEF_CDOUBLE_FUN_2_INT(hypgeom_0f1, acb_hypgeom_0f1) DEF_DOUBLE_FUN_3_INT(hypgeom_1f1, arb_hypgeom_1f1) DEF_CDOUBLE_FUN_3_INT(hypgeom_1f1, acb_hypgeom_1f1) DEF_DOUBLE_FUN_3(hypgeom_u, arb_hypgeom_u) DEF_CDOUBLE_FUN_3(hypgeom_u, acb_hypgeom_u) DEF_DOUBLE_FUN_4_INT(hypgeom_2f1, arb_hypgeom_2f1) DEF_CDOUBLE_FUN_4_INT(hypgeom_2f1, acb_hypgeom_2f1) int arb_fpwrap_double_hypgeom_pfq(double * res, const double * a, slong p, const double * b, slong q, double z, int regularized, int flags) { arb_t arb_res; arb_ptr t; slong wp; slong i; int status; arb_init(arb_res); t = _arb_vec_init(p + q + 1); for (i = 0; i < p; i++) arb_set_d(t + i, a[i]); for (i = 0; i < q; i++) arb_set_d(t + p + i, b[i]); arb_set_d(t + p + q, z); if (!_arb_vec_is_finite(t, p + q + 1)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { arb_hypgeom_pfq(arb_res, t, p, t + p, q, t + p + q, regularized, wp); DOUBLE_CHECK_RESULT } } _arb_vec_clear(t, p + q + 1); arb_clear(arb_res); return status; } int arb_fpwrap_cdouble_hypgeom_pfq(complex_double * res, const complex_double * a, slong p, const complex_double * b, slong q, complex_double z, int regularized, int flags) { acb_t acb_res; acb_ptr t; slong wp; slong i; int status; acb_init(acb_res); t = _acb_vec_init(p + q + 1); for (i = 0; i < p; i++) acb_set_d_d(t + i, a[i].real, a[i].imag); for (i = 0; i < q; i++) acb_set_d_d(t + p + i, b[i].real, b[i].imag); acb_set_d_d(t + p + q, z.real, z.imag); if (!_acb_vec_is_finite(t, p + q + 1)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { acb_hypgeom_pfq(acb_res, t, p, t + p, q, t + p + q, regularized, wp); CDOUBLE_CHECK_RESULT } } _acb_vec_clear(t, p + q + 1); acb_clear(acb_res); return status; } DEF_DOUBLE_FUN_2(agm, arb_agm) DEF_CDOUBLE_FUN_2(agm, acb_agm) DEF_CDOUBLE_FUN_1(elliptic_k, acb_elliptic_k) DEF_CDOUBLE_FUN_1(elliptic_e, acb_elliptic_e) DEF_CDOUBLE_FUN_2(elliptic_pi, acb_elliptic_pi) DEF_CDOUBLE_FUN_2_INT(elliptic_f, acb_elliptic_f) DEF_CDOUBLE_FUN_2_INT(elliptic_e_inc, acb_elliptic_e_inc) DEF_CDOUBLE_FUN_3_INT(elliptic_pi_inc, acb_elliptic_pi_inc) DEF_CDOUBLE_FUN_3_INT(elliptic_rf, acb_elliptic_rf) DEF_CDOUBLE_FUN_3_INT(elliptic_rg, acb_elliptic_rg) DEF_CDOUBLE_FUN_4_INT(elliptic_rj, acb_elliptic_rj) DEF_CDOUBLE_FUN_2(elliptic_p, acb_elliptic_p) DEF_CDOUBLE_FUN_2(elliptic_p_prime, acb_elliptic_p_prime) DEF_CDOUBLE_FUN_2(elliptic_inv_p, acb_elliptic_inv_p) DEF_CDOUBLE_FUN_2(elliptic_zeta, acb_elliptic_zeta) DEF_CDOUBLE_FUN_2(elliptic_sigma, acb_elliptic_sigma) static void _acb_theta1(acb_t res, const acb_t z, const acb_t tau, slong prec) { acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c); acb_modular_theta(res, a, b, c, z, tau, prec); acb_clear(a); acb_clear(b); acb_clear(c); } static void _acb_theta2(acb_t res, const acb_t z, const acb_t tau, slong prec) { acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c); acb_modular_theta(a, res, b, c, z, tau, prec); acb_clear(a); acb_clear(b); acb_clear(c); } static void _acb_theta3(acb_t res, const acb_t z, const acb_t tau, slong prec) { acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c); acb_modular_theta(a, b, res, c, z, tau, prec); acb_clear(a); acb_clear(b); acb_clear(c); } static void _acb_theta4(acb_t res, const acb_t z, const acb_t tau, slong prec) { acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c); acb_modular_theta(a, b, c, res, z, tau, prec); acb_clear(a); acb_clear(b); acb_clear(c); } DEF_CDOUBLE_FUN_2(jacobi_theta_1, _acb_theta1) DEF_CDOUBLE_FUN_2(jacobi_theta_2, _acb_theta2) DEF_CDOUBLE_FUN_2(jacobi_theta_3, _acb_theta3) DEF_CDOUBLE_FUN_2(jacobi_theta_4, _acb_theta4) DEF_CDOUBLE_FUN_1(dedekind_eta, acb_modular_eta) DEF_CDOUBLE_FUN_1(modular_j, acb_modular_j) DEF_CDOUBLE_FUN_1(modular_lambda, acb_modular_lambda) DEF_CDOUBLE_FUN_1(modular_delta, acb_modular_delta) DEF_CDOUBLE_FUN_1(dirichlet_eta, acb_dirichlet_eta) DEF_CDOUBLE_FUN_1(riemann_xi, acb_dirichlet_xi) static void _acb_hardy_theta(acb_t res, const acb_t t, slong prec) { acb_dirichlet_hardy_theta(res, t, NULL, NULL, 1, prec); } static void _acb_hardy_z(acb_t res, const acb_t t, slong prec) { acb_dirichlet_hardy_z(res, t, NULL, NULL, 1, prec); } DEF_CDOUBLE_FUN_1(hardy_theta, _acb_hardy_theta) DEF_CDOUBLE_FUN_1(hardy_z, _acb_hardy_z) int arb_fpwrap_cdouble_zeta_zero(complex_double * res, ulong n, int flags) { fmpz_t t; acb_t acb_res; slong wp; int status; if (n == 0) { res->real = D_NAN; res->imag = D_NAN; return FPWRAP_UNABLE; } acb_init(acb_res); fmpz_init(t); fmpz_set_ui(t, n); for (wp = WP_INITIAL; ; wp *= 2) { acb_dirichlet_zeta_zero(acb_res, t, wp); CDOUBLE_CHECK_RESULT } acb_clear(acb_res); return status; } int arb_fpwrap_double_legendre_root(double * res1, double * res2, ulong n, ulong k, int flags) { arb_t arb_res1, arb_res2; slong wp; int status; if (k >= n) { *res1 = D_NAN; *res2 = D_NAN; return FPWRAP_UNABLE; } arb_init(arb_res1); arb_init(arb_res2); for (wp = WP_INITIAL; ; wp *= 2) { arb_hypgeom_legendre_p_ui_root(arb_res1, arb_res2, n, k, wp); DOUBLE_CHECK_RESULT2 } arb_clear(arb_res1); arb_clear(arb_res2); return status; } int _arb_fpwrap_double_airy_zero(double * res, ulong n, int which, int flags) { fmpz_t t; arb_t arb_res; slong wp; int status; if (n == 0) { *res = D_NAN; return FPWRAP_UNABLE; } arb_init(arb_res); fmpz_init(t); fmpz_set_ui(t, n); for (wp = WP_INITIAL; ; wp *= 2) { if (which == 0) arb_hypgeom_airy_zero(arb_res, NULL, NULL, NULL, t, wp); else if (which == 1) arb_hypgeom_airy_zero(NULL, arb_res, NULL, NULL, t, wp); else if (which == 2) arb_hypgeom_airy_zero(NULL, NULL, arb_res, NULL, t, wp); else arb_hypgeom_airy_zero(NULL, NULL, NULL, arb_res, t, wp); DOUBLE_CHECK_RESULT } arb_clear(arb_res); fmpz_clear(t); return status; } int arb_fpwrap_double_airy_ai_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 0, flags); } int arb_fpwrap_double_airy_ai_prime_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 1, flags); } int arb_fpwrap_double_airy_bi_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 2, flags); } int arb_fpwrap_double_airy_bi_prime_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 3, flags); } int arb_fpwrap_double_lambertw(double * res, double x, slong branch, int flags) { arb_t arb_res, arb_x; slong wp; int status; arb_init(arb_res); arb_init(arb_x); arb_set_d(arb_x, x); if (!arb_is_finite(arb_x) || !(branch == 0 || branch == -1)) { *res = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { arb_lambertw(arb_res, arb_x, (branch == -1), wp); DOUBLE_CHECK_RESULT } } arb_clear(arb_x); arb_clear(arb_res); return status; } int arb_fpwrap_cdouble_lambertw(complex_double * res, complex_double x, slong branch, int flags) { fmpz_t t; acb_t acb_res, acb_x; slong wp; int status; acb_init(acb_res); acb_init(acb_x); fmpz_init(t); acb_set_d_d(acb_x, x.real, x.imag); fmpz_set_si(t, branch); if (!acb_is_finite(acb_x)) { res->real = D_NAN; res->imag = D_NAN; status = FPWRAP_UNABLE; } else { for (wp = WP_INITIAL; ; wp *= 2) { acb_lambertw(acb_res, acb_x, t, 0, wp); CDOUBLE_CHECK_RESULT } } acb_clear(acb_x); acb_clear(acb_res); fmpz_clear(t); return status; } /* todo: functions with multiple outputs */ /* todo: elliptic invariants, roots */ /* todo: eisenstein series */ /* todo: dirichlet functions requiring characters */ flint-3.1.3/src/arb_fpwrap/test/000077500000000000000000000000001461254215100165245ustar00rootroot00000000000000flint-3.1.3/src/arb_fpwrap/test/main.c000066400000000000000000000013721461254215100176170ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-fpwrap.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arb_fpwrap) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arb_fpwrap/test/t-fpwrap.c000066400000000000000000000451161461254215100204370ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "double_extras.h" #include "arb.h" #include "arb_fpwrap.h" #define CHECK_DOUBLE(fcall) \ do { \ int fail = fcall; \ if (fail || res != res) \ { \ flint_printf("FAIL\n"); \ flint_printf("%d\n", __LINE__); \ flint_abort(); \ } \ } while (0) #define CHECK_CDOUBLE(fcall) \ do { \ int fail = fcall; \ if (fail || cres.real != cres.real || cres.imag != cres.imag) \ { \ flint_printf("FAIL\n"); \ flint_printf("%d\n", __LINE__); \ flint_abort(); \ } \ } while (0) TEST_FUNCTION_START(arb_fpwrap, state) { slong iter; /* correct rounding test */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mpfr_t t; double x, y, z; mpfr_init2(t, 53); x = d_randtest(state) + n_randint(state, 100); mpfr_set_d(t, x, MPFR_RNDN); switch (n_randint(state, 4)) { case 0: arb_fpwrap_double_log1p(&y, x, FPWRAP_CORRECT_ROUNDING); mpfr_log1p(t, t, MPFR_RNDN); break; case 1: arb_fpwrap_double_sqrt(&y, x, FPWRAP_CORRECT_ROUNDING); mpfr_sqrt(t, t, MPFR_RNDN); break; case 2: arb_fpwrap_double_exp(&y, x, FPWRAP_CORRECT_ROUNDING); mpfr_exp(t, t, MPFR_RNDN); break; default: arb_fpwrap_double_sin(&y, x, FPWRAP_CORRECT_ROUNDING); mpfr_sin(t, t, MPFR_RNDN); break; } z = mpfr_get_d(t, MPFR_RNDN); if (z != y) { flint_printf("FAIL: correct rounding\n\n"); flint_abort(); } mpfr_clear(t); } { double a[1], b[2]; double z, y; z = 1.75; a[0] = 0.25; b[0] = 1.5; b[1] = -2.125; arb_fpwrap_double_hypgeom_pfq(&y, a, 1, b, 2, z, 0, 0); if (fabs(y - 0.68910385124070327187) > 1e-16) { flint_printf("FAIL: value 1\n\n"); flint_abort(); } arb_fpwrap_double_hypgeom_pfq(&y, a, 1, b, 2, z, 1, 0); if (fabs(y - (-0.21324224371323783595)) > 1e-16) { flint_printf("FAIL: value 2\n\n"); flint_abort(); } } { complex_double y, z; arb_fpwrap_cdouble_zeta_zero(&y, 1, FPWRAP_CORRECT_ROUNDING); arb_fpwrap_cdouble_zeta(&z, y, 0); if (fabs(z.real - (-1.0483650805588237388e-16)) > 1e-31) { flint_printf("FAIL: value 3\n\n"); flint_abort(); } if (fabs(z.imag - 6.5852592776051578103e-16) > 1e-31) { flint_printf("FAIL: value 4\n\n"); flint_abort(); } } { complex_double x, y; x.real = 1.0; x.imag = 1e-100; arb_fpwrap_cdouble_erf(&y, x, FPWRAP_ACCURATE_PARTS); if (fabs(y.imag - 4.1510749742059471164e-101) > 1e-116) { flint_printf("FAIL: value 5\n\n"); flint_abort(); } } { double y; arb_fpwrap_double_hypgeom_2f1(&y, 0.1, 0.2, 0.3, 0.4, 0, FPWRAP_CORRECT_ROUNDING); if (fabs(y - 1.0341794015503748492) > 1e-16) { flint_printf("FAIL: value 6\n\n"); flint_abort(); } arb_fpwrap_double_hypgeom_2f1(&y, 0.1, 0.2, 0.3, 0.4, 1, FPWRAP_CORRECT_ROUNDING); if (fabs(y - 0.34569799520143110351) > 1e-16) { flint_printf("FAIL: value 6\n\n"); flint_abort(); } } { double x, y, z; complex_double cx, cy, cz, ctau; double res, res2; complex_double cres; int flags; x = 0.25; y = 0.625; z = 0.75; cx.real = 0.25; cx.imag = 0.125; cy.real = 0.5; cy.imag = 0.625; cz.real = 0.75; cz.imag = 0.125; ctau.real = 0.25; ctau.imag = 1.0; flags = 0; CHECK_DOUBLE(arb_fpwrap_double_exp(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_exp(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_expm1(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_expm1(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_log(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_log(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_log1p(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_log1p(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_pow(&res, x, y, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_pow(&cres, cx, cy, flags)); CHECK_DOUBLE(arb_fpwrap_double_sqrt(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sqrt(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_rsqrt(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_rsqrt(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_cbrt(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_cbrt(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_sin(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sin(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_cos(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_cos(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_tan(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_tan(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_cot(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_cot(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_sec(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sec(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_csc(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_csc(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_sinc(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sinc(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_sin_pi(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sin_pi(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_cos_pi(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_cos_pi(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_tan_pi(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_tan_pi(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_cot_pi(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_cot_pi(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_sinc_pi(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sinc_pi(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_asin(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_asin(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_acos(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_acos(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_atan(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_atan(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_atan2(&res, x, y, flags)); CHECK_DOUBLE(arb_fpwrap_double_asinh(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_asinh(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_acosh(&res, 1.0 + x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_acosh(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_atanh(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_atanh(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_lambertw(&res, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_lambertw(&cres, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_lambertw(&res, -0.2, -1, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_lambertw(&cres, cx, -1, flags)); CHECK_DOUBLE(arb_fpwrap_double_rising(&res, x, y, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_rising(&cres, cx, cy, flags)); CHECK_DOUBLE(arb_fpwrap_double_gamma(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_gamma(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_rgamma(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_rgamma(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_lgamma(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_lgamma(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_digamma(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_digamma(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_zeta(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_zeta(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_hurwitz_zeta(&res, x, z, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hurwitz_zeta(&cres, cx, cz, flags)); CHECK_DOUBLE(arb_fpwrap_double_lerch_phi(&res, x, y, z, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_lerch_phi(&cres, cx, cy, cz, flags)); CHECK_DOUBLE(arb_fpwrap_double_barnes_g(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_barnes_g(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_log_barnes_g(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_log_barnes_g(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_polygamma(&res, x, z, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_polygamma(&cres, cx, cz, flags)); CHECK_DOUBLE(arb_fpwrap_double_polylog(&res, x, z, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_polylog(&cres, cx, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_dirichlet_eta(&cres, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_riemann_xi(&cres, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hardy_theta(&cres, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hardy_z(&cres, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_zeta_zero(&cres, 2, flags)); CHECK_DOUBLE(arb_fpwrap_double_erf(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_erf(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_erfc(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_erfc(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_erfi(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_erfi(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_erfinv(&res, x, flags)); CHECK_DOUBLE(arb_fpwrap_double_erfcinv(&res, x, flags)); CHECK_DOUBLE(arb_fpwrap_double_fresnel_s(&res, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_fresnel_s(&cres, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_fresnel_c(&res, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_fresnel_c(&cres, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_gamma_upper(&res, x, z, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_gamma_upper(&cres, cx, cz, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_gamma_lower(&res, x, z, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_gamma_lower(&cres, cx, cz, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_beta_lower(&res, x, y, z, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_beta_lower(&cres, cx, cy, cz, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_exp_integral_e(&res, x, z, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_exp_integral_e(&cres, cx, cz, flags)); CHECK_DOUBLE(arb_fpwrap_double_exp_integral_ei(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_exp_integral_ei(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_sin_integral(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sin_integral(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_cos_integral(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_cos_integral(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_sinh_integral(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_sinh_integral(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_cosh_integral(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_cosh_integral(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_log_integral(&res, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_log_integral(&cres, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_dilog(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_dilog(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_bessel_j(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_bessel_j(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_bessel_y(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_bessel_y(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_bessel_i(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_bessel_i(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_bessel_k(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_bessel_k(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_bessel_k_scaled(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_bessel_k_scaled(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_ai(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_airy_ai(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_ai_prime(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_airy_ai_prime(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_bi(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_airy_bi(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_bi_prime(&res, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_airy_bi_prime(&cres, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_ai_zero(&res, 1, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_ai_prime_zero(&res, 1, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_bi_zero(&res, 1, flags)); CHECK_DOUBLE(arb_fpwrap_double_airy_bi_prime_zero(&res, 1, flags)); CHECK_DOUBLE(arb_fpwrap_double_coulomb_f(&res, y, z, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_coulomb_f(&cres, cy, cz, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_coulomb_g(&res, y, z, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_coulomb_g(&cres, cy, cz, cx, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_coulomb_hpos(&cres, cy, cz, cx, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_coulomb_hneg(&cres, cy, cz, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_chebyshev_t(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_chebyshev_t(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_chebyshev_u(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_chebyshev_u(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_jacobi_p(&res, y, x, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_jacobi_p(&cres, cy, cx, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_gegenbauer_c(&res, y, z, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_gegenbauer_c(&cres, cy, cz, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_laguerre_l(&res, y, z, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_laguerre_l(&cres, cy, cz, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_hermite_h(&res, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hermite_h(&cres, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_legendre_p(&res, y, z, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_legendre_p(&cres, cy, cz, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_legendre_q(&res, y, z, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_legendre_q(&cres, cy, cz, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_legendre_root(&res, &res2, 2, 1, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_spherical_y(&cres, 2, 1, cx, cy, flags)); CHECK_DOUBLE(arb_fpwrap_double_hypgeom_0f1(&res, y, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hypgeom_0f1(&cres, cy, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_hypgeom_1f1(&res, x, y, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hypgeom_1f1(&cres, cx, cy, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_hypgeom_u(&res, x, y, x, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hypgeom_u(&cres, cx, cy, cx, flags)); CHECK_DOUBLE(arb_fpwrap_double_hypgeom_2f1(&res, x, y, z, x, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hypgeom_2f1(&cres, cx, cy, cz, cx, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_hypgeom_pfq(&res, &x, 1, &y, 1, z, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_hypgeom_pfq(&cres, &cx, 1, &cy, 1, cz, 0, flags)); CHECK_DOUBLE(arb_fpwrap_double_agm(&res, x, y, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_agm(&cres, cx, cy, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_k(&cres, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_e(&cres, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_pi(&cres, cy, cz, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_f(&cres, cx, cz, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_e_inc(&cres, cx, cz, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_pi_inc(&cres, cx, cy, cz, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_rf(&cres, cx, cy, cz, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_rg(&cres, cx, cy, cz, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_rj(&cres, cx, cy, cz, cx, 0, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_p(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_p_prime(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_inv_p(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_zeta(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_elliptic_sigma(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_jacobi_theta_1(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_jacobi_theta_2(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_jacobi_theta_3(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_jacobi_theta_4(&cres, cz, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_dedekind_eta(&cres, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_modular_j(&cres, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_modular_lambda(&cres, ctau, flags)); CHECK_CDOUBLE(arb_fpwrap_cdouble_modular_delta(&cres, ctau, flags)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom.h000066400000000000000000000331031461254215100160670ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_HYPGEOM_H #define ARB_HYPGEOM_H #include "arb.h" #ifdef __cplusplus extern "C" { #endif void _arb_hypgeom_rising_coeffs_1(ulong * c, ulong k, slong l); void _arb_hypgeom_rising_coeffs_2(ulong * c, ulong k, slong l); void _arb_hypgeom_rising_coeffs_fmpz(fmpz * c, ulong k, slong l); void arb_hypgeom_rising_ui_forward(arb_t res, const arb_t x, ulong n, slong prec); void arb_hypgeom_rising_ui_rs(arb_t res, const arb_t x, ulong n, ulong m, slong prec); void arb_hypgeom_rising_ui_bs(arb_t res, const arb_t x, ulong n, slong prec); void arb_hypgeom_rising_ui_rec(arb_t res, const arb_t x, ulong n, slong prec); void arb_hypgeom_rising_ui(arb_t y, const arb_t x, ulong n, slong prec); void arb_hypgeom_rising(arb_t y, const arb_t x, const arb_t n, slong prec); void arb_hypgeom_rising_ui_jet_powsum(arb_ptr res, const arb_t x, ulong n, slong len, slong prec); void arb_hypgeom_rising_ui_jet_rs(arb_ptr res, const arb_t x, ulong n, ulong m, slong len, slong prec); void arb_hypgeom_rising_ui_jet_bs(arb_ptr res, const arb_t x, ulong n, slong len, slong prec); void arb_hypgeom_rising_ui_jet(arb_ptr res, const arb_t x, ulong n, slong len, slong prec); void _arb_hypgeom_gamma_stirling_term_bounds(slong * bound, const mag_t zinv, slong N); void arb_hypgeom_gamma_stirling_sum_horner(arb_t s, const arb_t z, slong N, slong prec); void arb_hypgeom_gamma_stirling_sum_improved(arb_t s, const arb_t z, slong N, slong K, slong prec); #define ARB_HYPGEOM_GAMMA_TAB_NUM 536 #define ARB_HYPGEOM_GAMMA_TAB_PREC 3456 typedef struct { short exp; short tab_pos; char nlimbs; char negative; } arb_hypgeom_gamma_coeff_t; FLINT_DLL extern arb_hypgeom_gamma_coeff_t arb_hypgeom_gamma_coeffs[ARB_HYPGEOM_GAMMA_TAB_NUM]; int _arb_hypgeom_gamma_coeff_shallow(arf_t c, mag_t err, slong i, slong prec); void arb_hypgeom_gamma_stirling(arb_t res, const arb_t x, int reciprocal, slong prec); int arb_hypgeom_gamma_taylor(arb_t res, const arb_t x, int reciprocal, slong prec); void arb_hypgeom_gamma(arb_t y, const arb_t x, slong prec); void arb_hypgeom_rgamma(arb_t y, const arb_t x, slong prec); void arb_hypgeom_lgamma(arb_t y, const arb_t x, slong prec); void arb_hypgeom_gamma_fmpq(arb_t y, const fmpq_t x, slong prec); void arb_hypgeom_gamma_fmpz(arb_t y, const fmpz_t x, slong prec); void arb_hypgeom_pfq(arb_t res, arb_srcptr a, slong p, arb_srcptr b, slong q, const arb_t z, int regularized, slong prec); void arb_hypgeom_0f1(arb_t res, const arb_t a, const arb_t z, int regularized, slong prec); void arb_hypgeom_m(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec); void arb_hypgeom_1f1(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec); void arb_hypgeom_u(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec); void arb_hypgeom_2f1(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec); void arb_hypgeom_1f1_integration(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec); void arb_hypgeom_u_integration(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec); void arb_hypgeom_2f1_integration(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec); void arb_hypgeom_erf(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_erf_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_erf_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void arb_hypgeom_erfc(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_erfc_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_erfc_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void arb_hypgeom_erfi(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_erfi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_erfi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void arb_hypgeom_erfinv(arb_t res, const arb_t x, slong prec); void arb_hypgeom_erfcinv(arb_t res, const arb_t x, slong prec); void arb_hypgeom_fresnel(arb_t res1, arb_t res2, const arb_t z, int normalized, slong prec); void _arb_hypgeom_fresnel_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, int normalized, slong len, slong prec); void arb_hypgeom_fresnel_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, int normalized, slong len, slong prec); void arb_hypgeom_ei(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_ei_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_ei_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void _arb_hypgeom_si_asymp(arb_t res, const arb_t z, slong N, slong prec); void _arb_hypgeom_si_1f2(arb_t res, const arb_t z, slong N, slong wp, slong prec); void arb_hypgeom_si(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_si_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_si_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void _arb_hypgeom_ci_asymp(arb_t res, const arb_t z, slong N, slong prec); void _arb_hypgeom_ci_2f3(arb_t res, const arb_t z, slong N, slong wp, slong prec); void arb_hypgeom_ci(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_ci_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_ci_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void arb_hypgeom_shi(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_shi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_shi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void arb_hypgeom_chi(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_chi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_hypgeom_chi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec); void arb_hypgeom_li(arb_t res, const arb_t z, int offset, slong prec); void _arb_hypgeom_li_series(arb_ptr g, arb_srcptr h, slong hlen, int offset, slong len, slong prec); void arb_hypgeom_li_series(arb_poly_t g, const arb_poly_t h, int offset, slong len, slong prec); void arb_hypgeom_bessel_j(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_y(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_jy(arb_t res1, arb_t res2, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_i(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_k(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_i_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_k_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_i_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec); void arb_hypgeom_bessel_k_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec); void arb_hypgeom_airy(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const arb_t z, slong prec); void arb_hypgeom_airy_jet(arb_ptr ai, arb_ptr bi, const arb_t z, slong len, slong prec); void arb_hypgeom_airy_series(arb_poly_t ai, arb_poly_t ai_prime, arb_poly_t bi, arb_poly_t bi_prime, const arb_poly_t z, slong len, slong prec); void _arb_hypgeom_airy_series(arb_ptr ai, arb_ptr ai_prime, arb_ptr bi, arb_ptr bi_prime, arb_srcptr z, slong zlen, slong len, slong prec); void arb_hypgeom_airy_zero(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const fmpz_t n, slong prec); void arb_hypgeom_coulomb(arb_t F, arb_t G, const arb_t l, const arb_t eta, const arb_t z, slong prec); void arb_hypgeom_coulomb_jet(arb_ptr F, arb_ptr G, const arb_t l, const arb_t eta, const arb_t z, slong len, slong prec); void _arb_hypgeom_coulomb_series(arb_ptr F, arb_ptr G, const arb_t l, const arb_t eta, arb_srcptr z, slong zlen, slong len, slong prec); void arb_hypgeom_coulomb_series(arb_poly_t F, arb_poly_t G, const arb_t l, const arb_t eta, const arb_poly_t z, slong len, slong prec); void arb_hypgeom_expint(arb_t res, const arb_t s, const arb_t z, slong prec); void arb_hypgeom_gamma_lower(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec); void _arb_hypgeom_gamma_lower_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec); void arb_hypgeom_gamma_lower_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec); void arb_hypgeom_gamma_upper(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec); void _arb_hypgeom_gamma_upper_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec); void arb_hypgeom_gamma_upper_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec); void arb_hypgeom_gamma_upper_integration(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec); void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t c, const arb_t z, int regularized, slong prec); void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, slong len, slong prec); void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, slong zlen, int regularized, slong len, slong prec); void arb_hypgeom_chebyshev_t(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_chebyshev_u(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_jacobi_p(arb_t res, const arb_t n, const arb_t a, const arb_t b, const arb_t z, slong prec); void arb_hypgeom_gegenbauer_c(arb_t res, const arb_t n, const arb_t m, const arb_t z, slong prec); void arb_hypgeom_laguerre_l(arb_t res, const arb_t n, const arb_t m, const arb_t z, slong prec); void arb_hypgeom_hermite_h(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_legendre_p(arb_t res, const arb_t n, const arb_t m, const arb_t z, int type, slong prec); void arb_hypgeom_legendre_q(arb_t res, const arb_t n, const arb_t m, const arb_t z, int type, slong prec); void arb_hypgeom_legendre_p_ui_deriv_bound(mag_t dp, mag_t dp2, ulong n, const arb_t x, const arb_t x2sub1); void arb_hypgeom_legendre_p_ui_rec(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong prec); void arb_hypgeom_legendre_p_ui_asymp(arb_t res, arb_t res2, ulong n, const arb_t x, slong K, slong prec); void arb_hypgeom_legendre_p_ui_one(arb_t res, arb_t res2, ulong n, const arb_t x, slong K, slong prec); void arb_hypgeom_legendre_p_ui_zero(arb_t res, arb_t res2, ulong n, const arb_t x, slong K, slong prec); void arb_hypgeom_legendre_p_ui(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong prec); void arb_hypgeom_legendre_p_ui_root(arb_t res, arb_t weight, ulong n, ulong k, slong prec); void arb_hypgeom_central_bin_ui(arb_t res, ulong n, slong prec); void arb_hypgeom_dilog(arb_t res, const arb_t z, slong prec); void _arb_hypgeom_gamma_lower_sum_rs_1(arb_t res, ulong p, ulong q, const arb_t z, slong N, slong prec); void _arb_hypgeom_gamma_upper_sum_rs_1(arb_t res, ulong p, ulong q, const arb_t z, slong N, slong prec); slong _arb_hypgeom_gamma_upper_fmpq_inf_choose_N(mag_t err, const fmpq_t a, const arb_t z, const mag_t abs_tol); void _arb_hypgeom_gamma_upper_fmpq_inf_bsplit(arb_t res, const fmpq_t a, const arb_t z, slong N, slong prec); slong _arb_hypgeom_gamma_lower_fmpq_0_choose_N(mag_t err, const fmpq_t a, const arb_t z, const mag_t abs_tol); void _arb_hypgeom_gamma_lower_fmpq_0_bsplit(arb_t res, const fmpq_t a, const arb_t z, slong N, slong prec); void _arb_gamma_upper_fmpq_step_bsplit(arb_t Gz1, const fmpq_t a, const arb_t z0, const arb_t z1, const arb_t Gz0, const arb_t expmz0, const mag_t abs_tol, slong prec); slong _arb_hypgeom_gamma_upper_singular_si_choose_N(mag_t err, slong n, const arb_t z, const mag_t abs_tol); void _arb_hypgeom_gamma_upper_singular_si_bsplit(arb_t res, slong n, const arb_t z, slong N, slong prec); int arb_hypgeom_erf_bb(arb_t res, const arb_t z, int complementary, slong prec); void arb_hypgeom_sum_fmpq_arb_forward(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); void arb_hypgeom_sum_fmpq_arb_rs(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); void arb_hypgeom_sum_fmpq_arb_bs(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); void arb_hypgeom_sum_fmpq_arb(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); void arb_hypgeom_sum_fmpq_imag_arb_forward(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); void arb_hypgeom_sum_fmpq_imag_arb_rs(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); void arb_hypgeom_sum_fmpq_imag_arb_bs(arb_t res_real, arb_t res_imag, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); void arb_hypgeom_sum_fmpq_imag_arb(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arb_hypgeom/000077500000000000000000000000001461254215100157165ustar00rootroot00000000000000flint-3.1.3/src/arb_hypgeom/1f1_integration.c000066400000000000000000000225171461254215100210630ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_calc.h" #include "double_interval.h" /* Integrand: exp(f(t)) where f(z) = z*t + (a-1)*log(t) + (b-a-1)*log(1-t) Magnitude bound: |exp(f(t))| = exp(Re(f(t))) = exp(g(u,v)), t = u+v*i g(u,v) = z*u + 0.5*[(a-1)*log(u^2+v^2) + (b-a-1)*log((u-1)^2+v^2)] Evaluating g(u,v) directly gives poor results; we get better bounds using linearization. d/du g(u,v) = z + u*(a-1)/(u^2+v^2) + (u-1)*(b-a-1)/(v^2+(1-u)^2) d/dv g(u,v) = v*(a-1)/(u^2+v^2) + v*(b-a-1)/(v^2+(1-u)^2) Finding the extrema of g(u,v) is doable (solutions of a degree-4 polynomial) but for simplicity we just do interval arithmetic. */ /* z*u + 0.5 [(a-1) log(u^2+v^2) + (b-a-1) log((u-1)^2+v^2)] */ static di_t di_integrand_edge(di_t u, di_t v, di_t a1, di_t ba1, di_t z) { di_t X, Y, Z; X = di_fast_mul(z, u); Y = di_fast_mul(a1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(u), di_fast_sqr(v)))); Z = di_fast_mul(ba1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(di_fast_sub_d(u, 1.0)), di_fast_sqr(v)))); return di_fast_add(X, di_fast_mul_d(di_fast_add(Y, Z), 0.5)); } /* which == 0 - d/du g(u,v) = z + u*(a-1)/(u^2+v^2) + (u-1)*(b-a-1)/(v^2+(1-u)^2) which == 1 - d/dv g(u,v) = v*(a-1)/(u^2+v^2) + v*(b-a-1)/(v^2+(1-u)^2) */ static di_t di_integrand_edge_diff(di_t u, di_t v, di_t a1, di_t ba1, di_t z, int which) { di_t Y, Z; Y = di_fast_div(a1, di_fast_add(di_fast_sqr(u), di_fast_sqr(v))); Z = di_fast_div(ba1, di_fast_add(di_fast_sqr(di_fast_sub_d(u, 1.0)), di_fast_sqr(v))); if (which == 0) return di_fast_add(z, di_fast_add(di_fast_mul(u, Y), di_fast_mul(di_fast_sub_d(u, 1.0), Z))); else return di_fast_mul(v, di_fast_add(Y, Z)); } static di_t di_subinterval(di_t x, slong i, slong N) { di_t res; double step; step = (x.b - x.a) / N; res.a = x.a + step * i; res.b = (i == N - 1) ? x.b : x.a + step * (i + 1); return res; } static void integrand_wide_bound5(acb_t res, const acb_t t, const arb_t a1, const arb_t ba1, const arb_t z, slong prec) { slong i, N; di_t du, dv, da1, dba1, dz, dg, dgprime; double radius, bound; double start, end; int which; arb_t abound; N = 8; bound = -D_INF; da1 = arb_get_di(a1); dba1 = arb_get_di(ba1); dz = arb_get_di(z); /* left edge: left(u) + [0, right(v)] */ /* right edge: right(u) + [0, right(v)] */ for (which = 0; which < 2; which++) { du = arb_get_di(acb_realref(t)); if (which == 0) du.b = du.a; else du.a = du.b; dv = arb_get_di(acb_imagref(t)); start = 0.0; end = dv.b; for (i = 0; i < N; i++) { dv = di_subinterval(di_interval(start, end), i, N); radius = di_fast_ubound_radius(dv); /* g(u,mid(v)) + g'(u,v) * [0, radius] */ #if 1 dg = di_integrand_edge(du, di_fast_mid(dv), da1, dba1, dz); dgprime = di_integrand_edge_diff(du, dv, da1, dba1, dz, 1); dg = di_fast_add(dg, di_fast_mul(dgprime, di_interval(0.0, radius))); #else dg = di_integrand_edge(du, dv, da1, dba1, dz); #endif bound = FLINT_MAX(bound, dg.b); } } du = arb_get_di(acb_realref(t)); start = du.a; end = du.b; dv = arb_get_di(acb_imagref(t)); dv.a = dv.b; /* top edge: [left(u), right(u)] + right(v) */ for (i = 0; i < N; i++) { du = di_subinterval(di_interval(start, end), i, N); radius = di_fast_ubound_radius(du); /* g(mid(u),v) + g'(u,v) * [0, radius] */ #if 1 dg = di_integrand_edge(di_fast_mid(du), dv, da1, dba1, dz); dgprime = di_integrand_edge_diff(du, dv, da1, dba1, dz, 0); dg = di_fast_add(dg, di_fast_mul(dgprime, di_interval(0.0, radius))); #else dg = di_integrand_edge(du, dv, da1, dba1, dz); #endif bound = FLINT_MAX(bound, dg.b); } arb_init(abound); arb_set_d(abound, bound); arb_exp(abound, abound, prec); acb_zero(res); arb_add_error(acb_realref(res), abound); arb_add_error(acb_imagref(res), abound); arb_clear(abound); } /* todo: fix acb_pow(_arb) */ static void acb_my_pow_arb(acb_t res, const acb_t a, const arb_t b, slong prec) { if (acb_contains_zero(a) && arb_is_positive(b)) { /* |a^b| <= |a|^b */ arb_t t, u; arb_init(t); arb_init(u); acb_abs(t, a, prec); arb_get_abs_ubound_arf(arb_midref(t), t, prec); mag_zero(arb_radref(t)); if (arf_cmpabs_2exp_si(arb_midref(t), 0) < 0) arb_get_abs_lbound_arf(arb_midref(u), b, prec); else arb_get_abs_ubound_arf(arb_midref(u), b, prec); arb_pow(t, t, u, prec); acb_zero(res); acb_add_error_arb(res, t); arb_clear(t); arb_clear(u); } else { acb_pow_arb(res, a, b, prec); } } static int integrand(acb_ptr out, const acb_t t, void * param, slong order, slong prec) { arb_srcptr a1, ba1, z; acb_t s, u, v; a1 = ((arb_srcptr) param) + 0; ba1 = ((arb_srcptr) param) + 1; z = ((arb_srcptr) param) + 2; acb_init(s); acb_init(u); acb_init(v); acb_sub_ui(v, t, 1, prec); acb_neg(v, v); if (order == 1) { if (!arb_is_positive(acb_realref(t)) || !arb_is_positive(acb_realref(v))) acb_indeterminate(out); else integrand_wide_bound5(out, t, a1, ba1, z, prec); } else { if (acb_contains_zero(t) || acb_contains_zero(v)) { /* exp(z t) */ acb_mul_arb(s, t, z, prec); acb_exp(s, s, prec); /* t^(a-1) */ acb_my_pow_arb(u, t, a1, prec); /* (1-t)^(b-a-1) */ acb_my_pow_arb(v, v, ba1, prec); acb_mul(out, s, u, prec); acb_mul(out, out, v, prec); } else { acb_mul_arb(s, t, z, prec); /* t^(a-1) */ acb_log(u, t, prec); acb_mul_arb(u, u, a1, prec); /* (1-t)^(b-a-1) */ acb_log(v, v, prec); acb_mul_arb(v, v, ba1, prec); acb_add(out, s, u, prec); acb_add(out, out, v, prec); acb_exp(out, out, prec); } } acb_clear(s); acb_clear(u); acb_clear(v); return 0; } /* estimate integral by magnitude at peak */ static void estimate_magnitude(mag_t res, const arb_t ra, const arb_t rb, const arb_t rz) { double a, b, z, t1, t2, u, m; fmpz_t e; a = arf_get_d(arb_midref(ra), ARF_RND_NEAR); b = arf_get_d(arb_midref(rb), ARF_RND_NEAR); z = arf_get_d(arb_midref(rz), ARF_RND_NEAR); u = 4 - 4*b + b*b + 4*a*z - 2*b*z + z*z; if (u >= 0.0) { t1 = (2 - b + z + sqrt(u)) / (2 * z); t2 = (2 - b + z - sqrt(u)) / (2 * z); } else { t1 = 1e-8; t2 = 1 - 1e-8; } m = -1e300; if (t1 > 0.0 && t1 < 1.0) { t1 = z * t1 + (a - 1) * log(t1) + (b - a - 1) * log(1 - t1); m = FLINT_MAX(m, t1); } if (t2 > 0.0 && t2 < 1.0) { t2 = z * t2 + (a - 1) * log(t2) + (b - a - 1) * log(1 - t2); m = FLINT_MAX(m, t2); } m /= log(2); if (fabs(m) < 1e300) { fmpz_init(e); fmpz_set_d(e, m); mag_set_d_2exp_fmpz(res, 1.0, e); fmpz_clear(e); } else { mag_zero(res); } } void arb_hypgeom_1f1_integration(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) { acb_calc_integrate_opt_t opt; arb_struct param[3]; arb_t t, a1, ba1; acb_t zero, one, I; mag_t abs_tol; int ok; arb_init(t); arb_init(a1); arb_init(ba1); arb_sub_ui(a1, a, 1, prec); arb_sub(ba1, b, a, prec); arb_sub_ui(ba1, ba1, 1, prec); ok = arb_is_finite(z); ok = ok && arb_is_nonnegative(a1); ok = ok && arb_is_nonnegative(ba1); if (!ok) { arb_indeterminate(res); } else { mag_init(abs_tol); acb_init(zero); acb_init(one); acb_init(I); param[0] = *a1; param[1] = *ba1; param[2] = *z; acb_calc_integrate_opt_init(opt); /* opt->verbose = 2; */ /* opt->eval_limit = WORD_MAX; */ acb_one(one); estimate_magnitude(abs_tol, a, b, z); mag_mul_2exp_si(abs_tol, abs_tol, -prec); acb_calc_integrate(I, integrand, param, zero, one, prec, abs_tol, opt, prec); if (!regularized) { arb_gamma(t, b, prec); arb_mul(acb_realref(I), acb_realref(I), t, prec); } arb_rgamma(t, a, prec); arb_mul(acb_realref(I), acb_realref(I), t, prec); arb_sub(t, b, a, prec); arb_rgamma(t, t, prec); arb_mul(acb_realref(I), acb_realref(I), t, prec); arb_set(res, acb_realref(I)); mag_clear(abs_tol); acb_clear(zero); acb_clear(one); acb_clear(I); } arb_clear(t); arb_clear(a1); arb_clear(ba1); } flint-3.1.3/src/arb_hypgeom/2f1_integration.c000066400000000000000000000301031461254215100210520ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_calc.h" #include "double_interval.h" /* Integrand: exp(f(t)) where f(z) = (b-1)*log(t) + (c-b-1)*log(1-t) - a*log(1-z*t) Magnitude bound: |exp(f(t))| = exp(Re(f(t))) = exp(g(u,v)), t = u+v*i g(u,v) = 0.5*[(b-1)*log(u^2+v^2) + (c-b-1)*log((u-1)^2+v^2) + (-a)*log((v*z)^2+(u*z-1)^2)] Evaluating g(u,v) directly gives poor results; we get better bounds using linearization. d/du g(u,v) = u*(b-1)/(u^2+v^2) + (u-1)*(c-b-1)/(v^2+(1-u)^2) + (-a)*z*(uz-1)/((vz)^2+(uz-1)^2) d/dv g(u,v) = v*[(b-1)/(u^2+v^2) + (c-b-1)/(v^2+(1-u)^2) + (-a)*z^2/((vz)^2+(1-uz)^2)] */ /* 0.5*[(b-1)*log(u^2+v^2) + (c-b-1)*log((u-1)^2+v^2) + (-a)*log((v*z)^2+(u*z-1)^2)] */ static di_t di_integrand_edge(di_t u, di_t v, di_t b1, di_t cb1, di_t nega, di_t z) { di_t X, Y, Z; X = di_fast_mul(b1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(u), di_fast_sqr(v)))); if (cb1.a == 0 && cb1.b == 0) Y = di_interval(0.0, 0.0); else Y = di_fast_mul(cb1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(di_fast_sub_d(u, 1.0)), di_fast_sqr(v)))); Z = di_fast_mul(nega, di_fast_log_nonnegative(di_fast_add( di_fast_sqr(di_fast_mul(v, z)), di_fast_sqr(di_fast_sub_d(di_fast_mul(u, z), 1.0))))); return di_fast_mul_d(di_fast_add(X, di_fast_add(Y, Z)), 0.5); } /* which == 0 - d/du g(u,v) = u*(b-1)/(u^2+v^2) + (u-1)*(c-b-1)/(v^2+(1-u)^2) + (-a)*z*(uz-1)/((vz)^2+(uz-1)^2) which == 1 - d/dv g(u,v) = v*[(b-1)/(u^2+v^2) + (c-b-1)/(v^2+(1-u)^2) + (-a)*z^2/((vz)^2+(1-uz)^2)] */ static di_t di_integrand_edge_diff(di_t u, di_t v, di_t b1, di_t cb1, di_t nega, di_t z, int which) { di_t X, Y, Z, uz1; uz1 = di_fast_sub_d(di_fast_mul(u, z), 1.0); X = di_fast_div(b1, di_fast_add(di_fast_sqr(u), di_fast_sqr(v))); if (cb1.a == 0 && cb1.b == 0) Y = di_interval(0.0, 0.0); else Y = di_fast_div(cb1, di_fast_add(di_fast_sqr(di_fast_sub_d(u, 1.0)), di_fast_sqr(v))); Z = di_fast_div(nega, di_fast_add(di_fast_sqr(di_fast_mul(v, z)), di_fast_sqr(uz1))); if (which == 0) { X = di_fast_mul(X, u); Y = di_fast_mul(Y, di_fast_sub_d(u, 1.0)); Z = di_fast_mul(Z, di_fast_mul(z, uz1)); return di_fast_add(X, di_fast_add(Y, Z)); } else { Z = di_fast_mul(Z, di_fast_sqr(z)); return di_fast_mul(di_fast_add(X, di_fast_add(Y, Z)), v); } } static di_t di_subinterval(di_t x, slong i, slong N) { di_t res; double step; step = (x.b - x.a) / N; res.a = x.a + step * i; res.b = (i == N - 1) ? x.b : x.a + step * (i + 1); return res; } static void integrand_wide_bound5(acb_t res, const acb_t t, const arb_t b1, const arb_t cb1, const arb_t nega, const arb_t z, slong prec) { slong i, N; di_t du, dv, db1, dcb1, dnega, dz, dg, dgprime; double radius, bound; double start, end; int which; arb_t abound; N = 8; bound = -D_INF; db1 = arb_get_di(b1); dcb1 = arb_get_di(cb1); dnega = arb_get_di(nega); dz = arb_get_di(z); /* left edge: left(u) + [0, right(v)] */ /* right edge: right(u) + [0, right(v)] */ for (which = 0; which < 2; which++) { du = arb_get_di(acb_realref(t)); if (which == 0) du.b = du.a; else du.a = du.b; dv = arb_get_di(acb_imagref(t)); start = 0.0; end = dv.b; for (i = 0; i < N; i++) { dv = di_subinterval(di_interval(start, end), i, N); radius = di_fast_ubound_radius(dv); /* g(u,mid(v)) + g'(u,v) * [0, radius] */ #if 1 dg = di_integrand_edge(du, di_fast_mid(dv), db1, dcb1, dnega, dz); dgprime = di_integrand_edge_diff(du, dv, db1, dcb1, dnega, dz, 1); dg = di_fast_add(dg, di_fast_mul(dgprime, di_interval(0.0, radius))); #else dg = di_integrand_edge(du, dv, db1, dcb1, dnega, dz); #endif bound = FLINT_MAX(bound, dg.b); } } du = arb_get_di(acb_realref(t)); start = du.a; end = du.b; dv = arb_get_di(acb_imagref(t)); dv.a = dv.b; /* top edge: [left(u), right(u)] + right(v) */ for (i = 0; i < N; i++) { du = di_subinterval(di_interval(start, end), i, N); radius = di_fast_ubound_radius(du); /* g(mid(u),v) + g'(u,v) * [0, radius] */ #if 1 dg = di_integrand_edge(di_fast_mid(du), dv, db1, dcb1, dnega, dz); dgprime = di_integrand_edge_diff(du, dv, db1, dcb1, dnega, dz, 0); dg = di_fast_add(dg, di_fast_mul(dgprime, di_interval(0.0, radius))); #else dg = di_integrand_edge(du, dv, db1, dcb1, dnega, dz); #endif bound = FLINT_MAX(bound, dg.b); } arb_init(abound); arb_set_d(abound, bound); arb_exp(abound, abound, prec); acb_zero(res); arb_add_error(acb_realref(res), abound); arb_add_error(acb_imagref(res), abound); arb_clear(abound); } /* todo: fix acb_pow(_arb) */ static void acb_my_pow_arb(acb_t res, const acb_t a, const arb_t b, slong prec) { if (acb_contains_zero(a) && arb_is_positive(b)) { /* |a^b| <= |a|^b */ arb_t t, u; arb_init(t); arb_init(u); acb_abs(t, a, prec); arb_get_abs_ubound_arf(arb_midref(t), t, prec); mag_zero(arb_radref(t)); if (arf_cmpabs_2exp_si(arb_midref(t), 0) < 0) arb_get_abs_lbound_arf(arb_midref(u), b, prec); else arb_get_abs_ubound_arf(arb_midref(u), b, prec); arb_pow(t, t, u, prec); acb_zero(res); acb_add_error_arb(res, t); arb_clear(t); arb_clear(u); } else { acb_pow_arb(res, a, b, prec); } } static int integrand(acb_ptr out, const acb_t t, void * param, slong order, slong prec) { arb_srcptr b1, cb1, nega, z; acb_t s, u, v; b1 = ((arb_srcptr) param) + 0; cb1 = ((arb_srcptr) param) + 1; nega = ((arb_srcptr) param) + 2; z = ((arb_srcptr) param) + 3; acb_init(s); acb_init(u); acb_init(v); acb_sub_ui(v, t, 1, prec); acb_neg(v, v); acb_mul_arb(u, t, z, prec); acb_sub_ui(u, u, 1, prec); acb_neg(u, u); if (order == 1) { if (!arb_is_positive(acb_realref(t)) || !arb_is_positive(acb_realref(u)) || (!(arb_is_positive(acb_realref(v)) || arb_is_zero(cb1)))) acb_indeterminate(out); else { integrand_wide_bound5(out, t, b1, cb1, nega, z, prec); #if 0 /* t^(b-1) */ acb_log(s, t, prec); acb_mul_arb(s, s, b1, prec); /* (1-t)^(c-b-1) */ acb_log(v, v, prec); acb_mul_arb(v, v, cb1, prec); /* (1-zt)^(-a) */ acb_log(u, u, prec); acb_mul_arb(u, u, nega, prec); acb_add(out, s, u, prec); acb_add(out, out, v, prec); acb_exp(out, out, prec); #endif } } else { if (acb_contains_zero(t) || acb_contains_zero(v)) { /* t^(b-1) */ acb_my_pow_arb(s, t, b1, prec); /* (1-t)^(c-b-1) */ acb_my_pow_arb(v, v, cb1, prec); /* (1-zt)^(-a) */ acb_my_pow_arb(u, u, nega, prec); acb_mul(out, s, u, prec); acb_mul(out, out, v, prec); } else { /* t^(b-1) */ acb_log(s, t, prec); acb_mul_arb(s, s, b1, prec); /* (1-t)^(c-b-1) */ acb_log(v, v, prec); acb_mul_arb(v, v, cb1, prec); /* (1-zt)^(-a) */ if (arb_is_zero(nega)) { acb_zero(u); } else { acb_log(u, u, prec); acb_mul_arb(u, u, nega, prec); } acb_add(out, s, u, prec); acb_add(out, out, v, prec); acb_exp(out, out, prec); } } acb_clear(s); acb_clear(u); acb_clear(v); return 0; } /* estimate integral by magnitude at peak */ static void estimate_magnitude(mag_t res, const arb_t ra, const arb_t rb, const arb_t rc, const arb_t rz) { double a, b, c, z, t1, t2, u, m; fmpz_t e; a = arf_get_d(arb_midref(ra), ARF_RND_NEAR); b = arf_get_d(arb_midref(rb), ARF_RND_NEAR); c = arf_get_d(arb_midref(rc), ARF_RND_NEAR); z = arf_get_d(arb_midref(rz), ARF_RND_NEAR); u = 4*(b-1)*(2+a-c)*z + (2-c+(1+a-b)*z)*(2-c+(1+a-b)*z); if (u >= 0.0) { t1 = (2-c+z*(1+a-b) + sqrt(u)) / (2 * (2+a-c) * z); t2 = (2-c+z*(1+a-b) - sqrt(u)) / (2 * (2+a-c) * z); } else { t1 = 1e-8; t2 = 1 - 1e-8; } /* todo: more reliable solution when peak is at (or close to) 0 or 1 */ t1 = FLINT_MAX(t1, 1e-10); t2 = FLINT_MAX(t2, 1e-10); t1 = FLINT_MIN(t1, 1 - 1e-10); t2 = FLINT_MIN(t2, 1 - 1e-10); m = -1e300; if (t1 > 0.0 && t1 < 1.0 && z * t1 < 1.0) { t1 = (b - 1) * log(t1) + (c - b - 1) * log(1 - t1) - a * log(1 - z * t1); m = FLINT_MAX(m, t1); } if (t2 > 0.0 && t2 < 1.0 && z * t2 < 1.0) { t2 = (b - 1) * log(t2) + (c - b - 1) * log(1 - t2) - a * log(1 - z * t2); m = FLINT_MAX(m, t2); } m /= log(2); if (fabs(m) < 1e300) { fmpz_init(e); fmpz_set_d(e, m); mag_set_d_2exp_fmpz(res, 1.0, e); fmpz_clear(e); } else { mag_zero(res); } } int _arb_hypgeom_2f1_integration(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec) { acb_calc_integrate_opt_t opt; arb_struct param[4]; arb_t t, b1, cb1, nega; acb_t zero, one, I; mag_t abs_tol; int ok; arb_init(t); arb_init(b1); arb_init(cb1); arb_init(nega); arb_sub_ui(b1, b, 1, prec); arb_sub(cb1, c, b, prec); arb_sub_ui(cb1, cb1, 1, prec); arb_neg(nega, a); arb_one(t); ok = arb_is_finite(z) && arb_lt(z, t); ok = ok && arb_is_nonnegative(b1); ok = ok && arb_is_nonnegative(cb1); if (!ok) { arb_indeterminate(res); } else { mag_init(abs_tol); acb_init(zero); acb_init(one); acb_init(I); param[0] = *b1; param[1] = *cb1; param[2] = *nega; param[3] = *z; acb_calc_integrate_opt_init(opt); /* opt->verbose = 2; */ /* opt->eval_limit = WORD_MAX; */ acb_one(one); estimate_magnitude(abs_tol, a, b, c, z); mag_mul_2exp_si(abs_tol, abs_tol, -prec); acb_calc_integrate(I, integrand, param, zero, one, prec, abs_tol, opt, prec); if (!(regularized & 1)) { arb_gamma(t, c, prec); arb_mul(acb_realref(I), acb_realref(I), t, prec); } arb_rgamma(t, b, prec); arb_mul(acb_realref(I), acb_realref(I), t, prec); arb_sub(t, c, b, prec); arb_rgamma(t, t, prec); arb_mul(acb_realref(I), acb_realref(I), t, prec); arb_set(res, acb_realref(I)); mag_clear(abs_tol); acb_clear(zero); acb_clear(one); acb_clear(I); } arb_clear(t); arb_clear(b1); arb_clear(cb1); arb_clear(nega); return ok; } void arb_hypgeom_2f1_integration(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec) { arb_t res2; arb_init(res2); if (arf_cmp(arb_midref(a), arb_midref(b)) < 0) { if (!_arb_hypgeom_2f1_integration(res2, a, b, c, z, regularized, prec)) _arb_hypgeom_2f1_integration(res2, b, a, c, z, regularized, prec); } else { if (!_arb_hypgeom_2f1_integration(res2, b, a, c, z, regularized, prec)) _arb_hypgeom_2f1_integration(res2, a, b, c, z, regularized, prec); } arb_swap(res, res2); arb_clear(res2); } flint-3.1.3/src/arb_hypgeom/airy.c000066400000000000000000000025521461254215100170320ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void arb_hypgeom_airy(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const arb_t z, slong prec) { acb_struct tmp[5]; if (ai != NULL) acb_init(tmp); if (aip != NULL) acb_init(tmp + 1); if (bi != NULL) acb_init(tmp + 2); if (bip != NULL) acb_init(tmp + 3); acb_init(tmp + 4); acb_set_arb(tmp + 4, z); acb_hypgeom_airy(ai ? tmp : NULL, aip ? tmp + 1 : NULL, bi ? tmp + 2 : NULL, bip ? tmp + 3 : NULL, tmp + 4, prec); if (ai != NULL) arb_set(ai, acb_realref(tmp)); if (aip != NULL) arb_set(aip, acb_realref(tmp + 1)); if (bi != NULL) arb_set(bi, acb_realref(tmp + 2)); if (bip != NULL) arb_set(bip, acb_realref(tmp + 3)); if (ai != NULL) acb_clear(tmp); if (aip != NULL) acb_clear(tmp + 1); if (bi != NULL) acb_clear(tmp + 2); if (bip != NULL) acb_clear(tmp + 3); acb_clear(tmp + 4); } flint-3.1.3/src/arb_hypgeom/airy_jet.c000066400000000000000000000023251461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" static void airy_recurrence(arb_ptr ai, const arb_t z, slong len, slong prec) { slong k; if (len >= 3) { arb_mul(ai + 2, ai, z, prec); arb_mul_2exp_si(ai + 2, ai + 2, -1); } for (k = 3; k < len; k++) { arb_mul(ai + k, ai + k - 2, z, prec); arb_add(ai + k, ai + k, ai + k - 3, prec); arb_div_ui(ai + k, ai + k, k * (k - 1), prec); } } void arb_hypgeom_airy_jet(arb_ptr ai, arb_ptr bi, const arb_t z, slong len, slong prec) { if (len <= 0) return; if (len == 1) { arb_hypgeom_airy(ai, NULL, bi, NULL, z, prec); return; } arb_hypgeom_airy(ai, ai ? (ai + 1) : NULL, bi, bi ? (bi + 1) : NULL, z, prec); if (ai != NULL) airy_recurrence(ai, z, len, prec); if (bi != NULL) airy_recurrence(bi, z, len, prec); } flint-3.1.3/src/arb_hypgeom/airy_series.c000066400000000000000000000066111461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_airy_series(arb_ptr ai, arb_ptr ai_prime, arb_ptr bi, arb_ptr bi_prime, arb_srcptr z, slong zlen, slong len, slong prec) { arb_ptr t, u, v; slong tlen = len + ((ai_prime != NULL) || (bi_prime != NULL)); zlen = FLINT_MIN(zlen, len); if (zlen <= 0) return; if (zlen == 1) { arb_hypgeom_airy(ai, ai_prime, bi, bi_prime, z, prec); return; } t = _arb_vec_init(tlen); u = _arb_vec_init(tlen); v = _arb_vec_init(len); arb_hypgeom_airy_jet((ai || ai_prime) ? t : NULL, (bi || bi_prime) ? u : NULL, z, tlen, prec); /* compose with nonconstant part */ arb_zero(v); _arb_vec_set(v + 1, z + 1, zlen - 1); if (ai != NULL) _arb_poly_compose_series(ai, t, len, v, zlen, len, prec); if (bi != NULL) _arb_poly_compose_series(bi, u, len, v, zlen, len, prec); /* todo: use chain rule to avoid compositions for derivatives? */ if (ai_prime != NULL) { _arb_poly_derivative(t, t, len + 1, prec); _arb_poly_compose_series(ai_prime, t, len, v, zlen, len, prec); } if (bi_prime != NULL) { _arb_poly_derivative(u, u, len + 1, prec); _arb_poly_compose_series(bi_prime, u, len, v, zlen, len, prec); } _arb_vec_clear(t, tlen); _arb_vec_clear(u, tlen); _arb_vec_clear(v, len); } void arb_hypgeom_airy_series(arb_poly_t ai, arb_poly_t ai_prime, arb_poly_t bi, arb_poly_t bi_prime, const arb_poly_t z, slong len, slong prec) { if (len == 0) { if (ai != NULL) arb_poly_zero(ai); if (ai_prime != NULL) arb_poly_zero(ai_prime); if (bi != NULL) arb_poly_zero(bi); if (bi_prime != NULL) arb_poly_zero(bi_prime); return; } if (z->length <= 1) len = 1; if (ai != NULL) arb_poly_fit_length(ai, len); if (ai_prime != NULL) arb_poly_fit_length(ai_prime, len); if (bi != NULL) arb_poly_fit_length(bi, len); if (bi_prime != NULL) arb_poly_fit_length(bi_prime, len); if (z->length == 0) { arb_t t; arb_init(t); _arb_hypgeom_airy_series( ai ? ai->coeffs : NULL, ai_prime ? ai_prime->coeffs : NULL, bi ? bi->coeffs : NULL, bi_prime ? bi_prime->coeffs : NULL, t, 1, len, prec); arb_clear(t); } else { _arb_hypgeom_airy_series( ai ? ai->coeffs : NULL, ai_prime ? ai_prime->coeffs : NULL, bi ? bi->coeffs : NULL, bi_prime ? bi_prime->coeffs : NULL, z->coeffs, z->length, len, prec); } if (ai != NULL) { _arb_poly_set_length(ai, len); _arb_poly_normalise(ai); } if (ai_prime != NULL) { _arb_poly_set_length(ai_prime, len); _arb_poly_normalise(ai_prime); } if (bi != NULL) { _arb_poly_set_length(bi, len); _arb_poly_normalise(bi); } if (bi_prime != NULL) { _arb_poly_set_length(bi_prime, len); _arb_poly_normalise(bi_prime); } } flint-3.1.3/src/arb_hypgeom/airy_zero.c000066400000000000000000000202551461254215100200710ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp #else # include #endif /* https://dlmf.nist.gov/9.9 a_k ~ -T(3/8 pi (4k-1)) a'_k ~ -U(3/8 pi (4k-3)) b_k ~ -T(3/8 pi (4k-3)) b'_k ~ -U(3/8 pi (4k-1)) For a_k and b_k, the u^8 and u^10 truncations are known to give lower bounds. [G. Pittaluga and L. Sacripante (1991) Inequalities for the zeros of the Airy functions. SIAM J. Math. Anal. 22 (1), pp. 260–267.] We don't have proofs for a'_k and b'_k. However, in that case, we can just do a single interval Newton step to verify that we have isolated a zero (the enclosure must be for the correct zero due to sandwiching). */ #define AI 0 #define BI 1 #define AI_PRIME 2 #define BI_PRIME 3 static const double initial[4][10] = {{ -658118728906175.0,-1150655474581104.0,-1553899449042978.0,-1910288501594969.0, -2236074816421182.0,-2539650438812533.0,-2826057838960988.0, -3098624122012011.0,-3359689702679955.0,-3610979637739094.0},{ -330370902027041.0,-920730911234245.0,-1359731821477101.0,-1736658984124319.0, -2076373934490092.0,-2390271103799312.0,-2684763040788193.0, -2963907159065113.0,-3230475233555475.0,-3486466475611047.0},{ -286764727967452.0,-914286338795679.0,-1356737313209586.0,-1734816794389239.0, -2075083421171399.0,-2389296605766914.0,-2683990299959380.0, -2963272965051282.0,-3229941298662311.0,-3486008018531685.0},{ -645827356227815.0,-1146491233835383.0,-1551601459626981.0,-1908764696253222.0, -2234961611612173.0,-2538787015856429.0,-2825360342097020.0, -3098043823061022.0,-3359196018589429.0,-3610552233837226.0, }}; void _arb_hypgeom_airy_zero(arb_t res, const fmpz_t n, int which, slong prec) { slong asymp_accuracy, wp; if (fmpz_cmp_ui(n, 10) <= 0) { if (fmpz_sgn(n) <= 0) { flint_throw(FLINT_ERROR, "Airy zero only defined for index >= 1\n"); } /* The asymptotic expansions work well except when n == 1, so use precomputed starting intervals (also for the first few larger n as a small optimization). */ arf_set_d(arb_midref(res), ldexp(initial[which][fmpz_get_ui(n)-1], -48)); mag_set_d(arb_radref(res), ldexp(1.0, -48)); asymp_accuracy = 48; } else { arb_t z, u, u2, u4, s; fmpz_t c; arb_init(z); arb_init(u); arb_init(u2); arb_init(u4); arb_init(s); fmpz_init(c); if (which == AI || which == BI_PRIME) asymp_accuracy = 13 + 10 * (fmpz_bits(n) - 1); else { fmpz_sub_ui(c, n, 1); asymp_accuracy = 13 + 10 * (fmpz_bits(c) - 1); } wp = asymp_accuracy + 8; /* Reduce precision since we may not need to do any Newton steps. */ if (which == AI || which == BI) wp = FLINT_MIN(wp, prec + 8); arb_const_pi(z, wp); fmpz_mul_2exp(c, n, 2); if (which == AI || which == BI_PRIME) fmpz_sub_ui(c, c, 1); else fmpz_sub_ui(c, c, 3); fmpz_mul_ui(c, c, 3); arb_mul_fmpz(z, z, c, wp); arb_mul_2exp_si(z, z, -3); arb_inv(u, z, wp); arb_mul(u2, u, u, wp); arb_mul(u4, u2, u2, wp); if (which == AI || which == BI) { /* u^8 truncation gives lower bound */ arb_mul_si(s, u4, -108056875, wp); arb_addmul_si(s, u2, 6478500, wp); arb_add_si(s, s, -967680, wp); arb_mul(s, s, u4, wp); arb_addmul_si(s, u2, 725760, wp); arb_div_ui(s, s, 6967296, wp); /* u^10 term gives upper bound */ arb_mul(u4, u4, u4, 10); arb_mul(u4, u4, u2, 10); arb_mul_ui(u4, u4, 486, 10); } else { /* u^8 truncation gives upper bound */ arb_mul_si(s, u4, 18683371, wp); arb_addmul_si(s, u2, -1087338, wp); arb_add_si(s, s, 151200, wp); arb_mul(s, s, u4, wp); arb_addmul_si(s, u2, -181440, wp); arb_div_ui(s, s, 1244160, wp); /* u^10 term gives lower bound */ arb_mul(u4, u4, u4, 10); arb_mul(u4, u4, u2, 10); arb_mul_ui(u4, u4, 477, 10); arb_neg(u4, u4); } arb_mul_2exp_si(u4, u4, -1); arb_add(s, s, u4, wp); arb_add_error(s, u4); arb_add_ui(s, s, 1, wp); arb_root_ui(z, z, 3, wp); arb_mul(z, z, z, wp); arb_mul(res, z, s, wp); arb_neg(res, res); arb_clear(z); arb_clear(u); arb_clear(u2); arb_clear(u4); arb_clear(s); fmpz_clear(c); } /* Do interval Newton steps for refinement. Important: for the primed zeros, we need to do at least one interval Newton step to validate the initial (tentative) inclusion. */ if (asymp_accuracy < prec || (which == AI_PRIME || which == BI_PRIME)) { arb_t f, fprime, root; mag_t C, r; slong * steps; slong step, extraprec; arb_init(f); arb_init(fprime); arb_init(root); mag_init(C); mag_init(r); steps = flint_malloc(sizeof(slong) * FLINT_BITS); extraprec = 0.25 * fmpz_bits(n) + 8; wp = asymp_accuracy + extraprec; /* C = |f''| or |f'''| on the initial interval given by res */ /* f''(x) = xf(x) */ /* f'''(x) = xf'(x) + f(x) */ if (which == AI || which == AI_PRIME) arb_hypgeom_airy(f, fprime, NULL, NULL, res, wp); else arb_hypgeom_airy(NULL, NULL, f, fprime, res, wp); if (which == AI || which == BI) arb_mul(f, f, res, wp); else arb_addmul(f, fprime, res, wp); arb_get_mag(C, f); step = 0; steps[step] = prec; while (steps[step] / 2 > asymp_accuracy - extraprec) { steps[step + 1] = steps[step] / 2; step++; } arb_set(root, res); for ( ; step >= 0; step--) { wp = steps[step] + extraprec; wp = FLINT_MAX(wp, arb_rel_accuracy_bits(root) + extraprec); /* store radius, set root to the midpoint */ mag_set(r, arb_radref(root)); mag_zero(arb_radref(root)); if (which == AI || which == AI_PRIME) arb_hypgeom_airy(f, fprime, NULL, NULL, root, wp); else arb_hypgeom_airy(NULL, NULL, f, fprime, root, wp); /* f, f' = f', xf */ if (which == AI_PRIME || which == BI_PRIME) { arb_mul(f, f, root, wp); arb_swap(f, fprime); } /* f'([m+/-r]) = f'(m) +/- f''([m +/- r]) * r */ mag_mul(r, C, r); arb_add_error_mag(fprime, r); arb_div(f, f, fprime, wp); arb_sub(root, root, f, wp); /* Verify inclusion so that C is still valid, and for the primed zeros also to make sure that the initial intervals really were correct. */ if (!arb_contains(res, root)) { flint_printf("unexpected: no containment of Airy zero\n"); arb_indeterminate(root); break; } } arb_set(res, root); arb_clear(f); arb_clear(fprime); arb_clear(root); mag_clear(C); mag_clear(r); flint_free(steps); } arb_set_round(res, res, prec); } void arb_hypgeom_airy_zero(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const fmpz_t n, slong prec) { if (ai != NULL) _arb_hypgeom_airy_zero(ai, n, AI, prec); if (aip != NULL) _arb_hypgeom_airy_zero(aip, n, AI_PRIME, prec); if (bi != NULL) _arb_hypgeom_airy_zero(bi, n, BI, prec); if (bip != NULL) _arb_hypgeom_airy_zero(bip, n, BI_PRIME, prec); } flint-3.1.3/src/arb_hypgeom/bessel_i_integration.c000066400000000000000000000027431461254215100222600ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_bessel_i_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec) { arb_t t, a, b, w; arb_init(t); arb_init(a); arb_init(b); arb_init(w); arb_one(a); arb_mul_2exp_si(a, a, -1); arb_add(a, a, nu, prec); arb_mul_2exp_si(b, nu, 1); arb_add_ui(b, b, 1, prec); arb_mul_2exp_si(w, z, 1); arb_hypgeom_1f1_integration(t, a, b, w, 0, prec); if (arb_is_finite(t)) { if (!scaled) { arb_neg(a, z); arb_exp(a, a, prec); arb_mul(t, t, a, prec); } else { arb_neg(a, z); arb_mul_2exp_si(a, a, 1); arb_exp(a, a, prec); arb_mul(t, t, a, prec); } arb_mul_2exp_si(w, z, -1); arb_pow(w, w, nu, prec); arb_mul(t, t, w, prec); arb_add_ui(w, nu, 1, prec); arb_rgamma(w, w, prec); arb_mul(res, t, w, prec); } else { arb_indeterminate(res); } arb_clear(t); arb_clear(a); arb_clear(b); arb_clear(w); } flint-3.1.3/src/arb_hypgeom/bessel_k_integration.c000066400000000000000000000024321461254215100222550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_bessel_k_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec) { arb_t t, a, b, w; arb_init(t); arb_init(a); arb_init(b); arb_init(w); arb_one(a); arb_mul_2exp_si(a, a, -1); arb_add(a, a, nu, prec); arb_mul_2exp_si(b, nu, 1); arb_add_ui(b, b, 1, prec); arb_mul_2exp_si(w, z, 1); arb_hypgeom_u_integration(t, a, b, w, prec); if (arb_is_finite(t)) { if (!scaled) { arb_neg(a, z); arb_exp(a, a, prec); arb_mul(t, t, a, prec); } arb_mul_2exp_si(w, z, 1); arb_pow(w, w, nu, prec); arb_mul(res, t, w, prec); arb_const_sqrt_pi(w, prec); arb_mul(res, res, w, prec); } else { arb_indeterminate(res); } arb_clear(t); arb_clear(a); arb_clear(b); arb_clear(w); } flint-3.1.3/src/arb_hypgeom/beta_lower_series.c000066400000000000000000000055071461254215100215660ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, slong zlen, int regularized, slong len, slong prec) { arb_ptr t, u, v; arb_t c, d, e; zlen = FLINT_MIN(zlen, len); if (zlen == 1) { arb_hypgeom_beta_lower(res, a, b, z, regularized, prec); _arb_vec_zero(res + 1, len - 1); return; } t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(zlen - 1); arb_init(c); arb_init(d); arb_init(e); arb_hypgeom_beta_lower(d, a, b, z, regularized, prec); if (regularized) { /* todo: except in special cases, we already compute a bunch of gamma functions in beta_lower, so we could avoid recomputing them */ arb_add(e, a, b, prec); arb_gamma(e, e, prec); arb_rgamma(c, a, prec); arb_mul(e, e, c, prec); arb_rgamma(c, b, prec); arb_mul(e, e, c, prec); } /* u = (1-z)^(b-1) */ _arb_vec_neg(t, z, zlen); arb_add_ui(t, t, 1, prec); arb_sub_ui(c, b, 1, prec); _arb_poly_pow_arb_series(u, t, FLINT_MIN(zlen, len - 1), c, len - 1, prec); /* t = z^(a-1) */ arb_sub_ui(c, a, 1, prec); _arb_poly_pow_arb_series(t, z, FLINT_MIN(zlen, len - 1), c, len - 1, prec); /* v = z' */ _arb_poly_derivative(v, z, zlen, prec); _arb_poly_mullow(res, t, len - 1, u, len - 1, len - 1, prec); _arb_poly_mullow(t, res, len - 1, v, zlen - 1, len - 1, prec); _arb_poly_integral(res, t, len, prec); if (regularized) { _arb_vec_scalar_mul(res, res, len, e, prec); } arb_set(res, d); _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, zlen - 1); arb_clear(c); arb_clear(d); arb_clear(e); } void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, slong len, slong prec) { if (len == 0) { arb_poly_zero(res); return; } arb_poly_fit_length(res, len); if (z->length == 0) { arb_t t; arb_init(t); _arb_hypgeom_beta_lower_series(res->coeffs, a, b, t, 1, regularized, len, prec); arb_clear(t); } else { _arb_hypgeom_beta_lower_series(res->coeffs, a, b, z->coeffs, z->length, regularized, len, prec); } _arb_poly_set_length(res, len); _arb_poly_normalise(res); } flint-3.1.3/src/arb_hypgeom/central_bin_ui.c000066400000000000000000000064041461254215100210430ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" #include "bernoulli.h" static const unsigned int central_bin_tab[] = { 1, 2, 6, 20, 70, 252, 924, 3432, 12870, 48620, 184756, 705432, 2704156, 10400600, 40116600, 155117520, 601080390, 2333606220U, }; void arb_gamma_stirling_coeff(arb_t b, ulong k, int digamma, slong prec); /* See Richard P. Brent, "Asymptotic approximation of central binomial coefficients with rigorous error bounds". https://arxiv.org/abs/1608.04834 */ static void arb_hypgeom_central_bin_ui_asymp(arb_t res, ulong n, slong prec) { arb_t s, t, u; fmpz_t n2; slong j, k, term_prec, wp; double term_mag, n2_mag; mag_t err, err2; arb_init(s); arb_init(t); arb_init(u); fmpz_init(n2); mag_init(err); mag_init(err2); wp = prec + 8; n2_mag = log(n) * 1.44269504088896; for (k = 1; k < prec; k++) { term_mag = bernoulli_bound_2exp_si(2 * k + 2) - (2 * k + 1) * n2_mag; term_mag -= (FLINT_BIT_COUNT((k + 1)*(2*k+1)) - 1); if (term_mag < -wp) break; } wp += 2 * FLINT_BIT_COUNT(k); BERNOULLI_ENSURE_CACHED(2*k) fmpz_set_ui(n2, n); fmpz_mul_ui(n2, n2, n); n2_mag *= 2; for (j = 0; j <= k - 1; j++) { term_mag = bernoulli_bound_2exp_si(2 * j + 2); term_mag -= j * n2_mag; term_prec = wp + term_mag; term_prec = FLINT_MIN(term_prec, wp); term_prec = FLINT_MAX(term_prec, 10); arb_gamma_stirling_coeff(t, j + 1, 0, term_prec); arb_mul_2exp_si(u, t, -2*j - 2); arb_sub(t, u, t, term_prec); arb_mul_2exp_si(t, t, 1); arb_addmul_fmpz(t, s, n2, wp); arb_swap(s, t); } arb_set_fmpz(t, n2); arb_pow_ui(t, t, k - 1, wp); arb_mul_ui(t, t, n, wp); arb_div(s, s, t, wp); /* error term: bernoulli(2k+2) / ((k+1)(2k+1)) / n^(2k+1) */ mag_bernoulli_div_fac_ui(err, 2 * k + 2); mag_fac_ui(err2, 2 * k + 2); mag_mul(err, err, err2); mag_set_ui_lower(err2, n); mag_pow_ui_lower(err2, err2, 2 * k + 1); mag_mul_ui_lower(err2, err2, k + 1); mag_div(err, err, err2); arb_add_error_mag(s, err); arb_exp(s, s, wp); arb_const_pi(t, wp); arb_mul_ui(t, t, n, wp); arb_rsqrt(t, t, wp); arb_mul(res, s, t, prec); fmpz_set_ui(n2, n); fmpz_mul_2exp(n2, n2, 1); arb_mul_2exp_fmpz(res, res, n2); arb_clear(s); arb_clear(t); arb_clear(u); fmpz_clear(n2); mag_clear(err); mag_clear(err2); } void arb_hypgeom_central_bin_ui(arb_t res, ulong n, slong prec) { if (n <= 17) { arb_set_ui(res, central_bin_tab[n]); arb_set_round(res, res, prec); } else if (n < 6.0 * prec + 200.0) { fmpz_t t; fmpz_init(t); fmpz_bin_uiui(t, 2 * n, n); arb_set_round_fmpz(res, t, prec); fmpz_clear(t); } else { arb_hypgeom_central_bin_ui_asymp(res, n, prec); } } flint-3.1.3/src/arb_hypgeom/chi_series.c000066400000000000000000000035151461254215100202030ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_chi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { arb_t c; if (!arb_is_positive(h)) { _arb_vec_indeterminate(g, len); return; } arb_init(c); arb_hypgeom_chi(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else { arb_ptr t, u, v; t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); /* Chi(h(x)) = integral([h'(x) / h(x)] cosh(h(x)) */ _arb_poly_cosh_series(t, h, hlen, len - 1, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec); _arb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec); _arb_poly_integral(g, u, len, prec); _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_chi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_inv_series(g, h, len, prec); return; } arb_poly_fit_length(g, len); _arb_hypgeom_chi_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/ci.c000066400000000000000000000117741461254215100164670ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "arb_hypgeom.h" #define LOG2 0.69314718055994531 #define INV_LOG2 1.4426950408889634074 #define EXP1 2.7182818284590452 double arf_get_d_log2_abs_approx_clamped(const arf_t x); void _arb_hypgeom_ci_asymp(arb_t res, const arb_t z, slong N, slong prec) { arb_t s, c, sz, cz, u; fmpq a[1]; slong wp; mag_t err, t; N = FLINT_MAX(N, 1); arb_init(s); arb_init(c); arb_init(sz); arb_init(cz); arb_init(u); mag_init(err); mag_init(t); /* Error is bounded by first omitted term, N! / z^N */ arb_get_mag_lower(err, z); mag_inv(err, err); mag_pow_ui(err, err, N); mag_fac_ui(t, N); mag_mul(err, err, t); wp = prec * 1.001 + 5; arb_set(u, z); *fmpq_numref(&a[0]) = 1; *fmpq_denref(&a[0]) = 1; arb_hypgeom_sum_fmpq_imag_arb(c, s, a, 1, NULL, 0, u, 1, N, wp); arb_add_error_mag(c, err); arb_add_error_mag(s, err); arb_sin_cos(sz, cz, z, wp); arb_mul(c, c, sz, wp); arb_submul(c, s, cz, wp); arb_div(res, c, z, prec); arb_clear(s); arb_clear(c); arb_clear(sz); arb_clear(cz); arb_clear(u); mag_clear(err); mag_clear(t); } void _arb_hypgeom_ci_2f3(arb_t res, const arb_t z, slong N, slong wp, slong prec) { mag_t err, t; arb_t s, u; fmpq a[1]; fmpq b[3]; N = FLINT_MAX(N, 1); mag_init(err); mag_init(t); arb_init(s); arb_init(u); arb_sqr(u, z, wp); arb_mul_2exp_si(u, u, -2); arb_neg(u, u); *fmpq_numref(&a[0]) = 1; *fmpq_denref(&a[0]) = 1; *fmpq_numref(&b[0]) = 2; *fmpq_denref(&b[0]) = 1; *fmpq_numref(&b[1]) = 2; *fmpq_denref(&b[1]) = 1; *fmpq_numref(&b[2]) = 3; *fmpq_denref(&b[2]) = 2; /* Terms are bounded by u^N / (4 (N!)^2) */ arb_get_mag(err, u); /* u^N */ mag_set(t, err); mag_pow_ui(t, t, N); /* geometric factor for u/N^2 */ mag_div_ui(err, err, N); mag_div_ui(err, err, N); mag_geom_series(err, err, 0); mag_mul(t, t, err); /* 1/(N!)^2 */ mag_rfac_ui(err, N); mag_mul(err, err, err); mag_mul(err, err, t); /* 1/4 */ mag_mul_2exp_si(err, err, -2); arb_hypgeom_sum_fmpq_arb(s, a, 1, b, 3, u, 0, N, wp); arb_add_error_mag(s, err); arb_mul(s, s, u, wp); arb_log(u, z, wp); arb_add(s, s, u, wp); arb_const_euler(u, wp); arb_add(res, s, u, prec); mag_clear(err); mag_clear(t); arb_clear(u); arb_clear(s); } void arb_hypgeom_ci(arb_t res, const arb_t z, slong prec) { slong wp, N, acc; double dz, du; if (!arb_is_positive(z) || !arb_is_finite(z)) { arb_indeterminate(res); return; } if (ARF_IS_LAGOM(arb_midref(z))) { acc = arb_rel_accuracy_bits(z); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); acc += FLINT_MAX(0, -ARF_EXP(arb_midref(z))); prec = FLINT_MIN(prec, acc + 32); } dz = fabs(arf_get_d(arb_midref(z), ARF_RND_DOWN)); dz = FLINT_MIN(dz, 1e300); if (dz > 2.0) { double log2_err, err_prev, log2dz; log2dz = arf_get_d_log2_abs_approx_clamped(arb_midref(z)); err_prev = 0.0; for (N = 1; N < 2 * prec; N++) { log2_err = ((N + 1.0) * (log(N + 1.0) - 1.0)) * INV_LOG2 - N * log2dz; if (log2_err > err_prev) break; if (log2_err < -prec - 2) { _arb_hypgeom_ci_asymp(res, z, N, prec); return; } err_prev = log2_err; } } if (arf_cmpabs_2exp_si(arb_midref(z), -30) < 0) { N = -arf_abs_bound_lt_2exp_si(arb_midref(z)); wp = prec * 1.001 + 10; N = (prec + N - 1) / N; } else { du = 0.25 * dz * dz; wp = prec * 1.001 + 10; if (du > 1.0) wp += dz * 1.4426950408889634; N = (prec + 5) * LOG2 / (2 * d_lambertw((prec + 5) * LOG2 / (2 * EXP1 * sqrt(du)))) + 1; } if (arb_is_exact(z)) { _arb_hypgeom_ci_2f3(res, z, N, wp, prec); } else { mag_t err; mag_init(err); /* |ci'(z)| = |cos(z)/z| <= 1/z */ arb_get_mag_lower(err, z); if (mag_cmp_2exp_si(err, 0) >= 0 || 1) { arb_t zmid; arb_init(zmid); arb_get_mid_arb(zmid, z); mag_inv(err, err); mag_mul(err, err, arb_radref(z)); _arb_hypgeom_ci_2f3(res, zmid, N, wp, prec); arb_add_error_mag(res, err); arb_clear(zmid); } else { _arb_hypgeom_ci_2f3(res, z, N, wp, prec); } mag_clear(err); } } flint-3.1.3/src/arb_hypgeom/ci_series.c000066400000000000000000000035061461254215100200330ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_ci_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { arb_t c; if (!arb_is_positive(h)) { _arb_vec_indeterminate(g, len); return; } arb_init(c); arb_hypgeom_ci(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else { arb_ptr t, u, v; t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); /* Ci(h(x)) = integral([h'(x) / h(x)] cos(h(x)) */ _arb_poly_cos_series(t, h, hlen, len - 1, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec); _arb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec); _arb_poly_integral(g, u, len, prec); _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_ci_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_inv_series(g, h, len, prec); return; } arb_poly_fit_length(g, len); _arb_hypgeom_ci_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/coulomb.c000066400000000000000000000021731461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void arb_hypgeom_coulomb(arb_t F, arb_t G, const arb_t l, const arb_t eta, const arb_t z, slong prec) { acb_ptr tmp; tmp = _acb_vec_init(5); acb_set_arb(tmp + 2, l); acb_set_arb(tmp + 3, eta); acb_set_arb(tmp + 4, z); acb_hypgeom_coulomb(F ? tmp : NULL, G ? tmp + 1 : NULL, NULL, NULL, tmp + 2, tmp + 3, tmp + 4, prec); if (F != NULL) { if (acb_is_real(tmp)) arb_set(F, acb_realref(tmp)); else arb_indeterminate(F); } if (G != NULL) { if (acb_is_real(tmp + 1)) arb_set(G, acb_realref(tmp + 1)); else arb_indeterminate(G); } _acb_vec_clear(tmp, 5); } flint-3.1.3/src/arb_hypgeom/coulomb_jet.c000066400000000000000000000030341461254215100203640ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void arb_hypgeom_coulomb_jet(arb_ptr F, arb_ptr G, const arb_t l, const arb_t eta, const arb_t z, slong len, slong prec) { acb_ptr tmp, tmpF, tmpG; slong k; if (len <= 0) return; if (len == 1) { arb_hypgeom_coulomb(F, G, l, eta, z, prec); return; } tmp = _acb_vec_init(3); tmpF = _acb_vec_init(len); tmpG = _acb_vec_init(len); acb_set_arb(tmp, l); acb_set_arb(tmp + 1, eta); acb_set_arb(tmp + 2, z); acb_hypgeom_coulomb_jet(F ? tmpF : NULL, G ? tmpG : NULL, NULL, NULL, tmp, tmp + 1, tmp + 2, len, prec); if (F != NULL) { if (acb_is_real(tmpF)) for (k = 0; k < len; k++) arb_set(F + k, acb_realref(tmpF + k)); else _arb_vec_indeterminate(F, len); } if (G != NULL) { if (acb_is_real(tmpG)) for (k = 0; k < len; k++) arb_set(G + k, acb_realref(tmpG + k)); else _arb_vec_indeterminate(G, len); } _acb_vec_clear(tmpF, len); _acb_vec_clear(tmpG, len); _acb_vec_clear(tmp, 3); } flint-3.1.3/src/arb_hypgeom/coulomb_series.c000066400000000000000000000045131461254215100210770ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_coulomb_series(arb_ptr F, arb_ptr G, const arb_t l, const arb_t eta, arb_srcptr z, slong zlen, slong len, slong prec) { arb_ptr t, v; if (len == 0) return; zlen = FLINT_MIN(zlen, len); if (zlen == 1) { arb_hypgeom_coulomb(F, G, l, eta, z, prec); if (F != NULL) _arb_vec_zero(F + 1, len - 1); if (G != NULL) _arb_vec_zero(G + 1, len - 1); return; } t = _arb_vec_init(len); v = _arb_vec_init(zlen); /* copy nonconstant part first to allow aliasing */ arb_zero(v); _arb_vec_set(v + 1, z + 1, zlen - 1); arb_hypgeom_coulomb_jet(F, G, l, eta, z, len, prec); if (F != NULL) { _arb_vec_set(t, F, len); _arb_poly_compose_series(F, t, len, v, zlen, len, prec); } if (G != NULL) { _arb_vec_set(t, G, len); _arb_poly_compose_series(G, t, len, v, zlen, len, prec); } _arb_vec_clear(t, len); _arb_vec_clear(v, zlen); } void arb_hypgeom_coulomb_series(arb_poly_t F, arb_poly_t G, const arb_t l, const arb_t eta, const arb_poly_t z, slong len, slong prec) { arb_srcptr zptr; slong zlen; arb_t t; if (len == 0) { if (F != NULL) arb_poly_zero(F); if (G != NULL) arb_poly_zero(G); return; } zlen = z->length; if (zlen <= 1) len = 1; if (F != NULL) arb_poly_fit_length(F, len); if (G != NULL) arb_poly_fit_length(G, len); if (zlen == 0) { arb_init(t); zptr = t; zlen = 1; } else { zptr = z->coeffs; } _arb_hypgeom_coulomb_series( F ? F->coeffs : NULL, G ? G->coeffs : NULL, l, eta, zptr, zlen, len, prec); if (F != NULL) _arb_poly_set_length(F, len); if (G != NULL) _arb_poly_set_length(G, len); if (F != NULL) _arb_poly_normalise(F); if (G != NULL) _arb_poly_normalise(G); } flint-3.1.3/src/arb_hypgeom/ei_series.c000066400000000000000000000035071461254215100200360ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_ei_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { arb_t c; if (arb_contains_zero(h)) { _arb_vec_indeterminate(g, len); return; } arb_init(c); arb_hypgeom_ei(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else { arb_ptr t, u, v; t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); /* Ei(h(x)) = integral([h'(x) / h(x)] exp(h(x)) */ _arb_poly_exp_series(t, h, hlen, len - 1, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec); _arb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec); _arb_poly_integral(g, u, len, prec); _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_ei_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_inv_series(g, h, len, prec); return; } arb_poly_fit_length(g, len); _arb_hypgeom_ei_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/erf.c000066400000000000000000000352211461254215100166410ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpq.h" #include "arb_hypgeom.h" #define LOG2 0.69314718055994530942 #define EXP1 2.7182818284590452354 #define INV_LOG2 1.4426950408889634074 void arb_hypgeom_erf_one_eps(arb_t res, const arb_t z) { mag_t t, u; mag_init(t); mag_init(u); arb_get_mag_lower(t, z); mag_mul_lower(u, t, t); mag_expinv(u, u); mag_div(u, u, t); /* 1/sqrt(pi) < 289/512 */ mag_mul_ui(u, u, 289); mag_mul_2exp_si(arb_radref(res), u, -9); if (mag_cmp_2exp_si(arb_radref(res), 1) > 0) { mag_one(arb_radref(res)); mag_mul_2exp_si(arb_radref(res), arb_radref(res), 2); } if (arf_sgn(arb_midref(z)) > 0) arf_one(arb_midref(res)); else { arf_one(arb_midref(res)); arf_neg(arb_midref(res), arb_midref(res)); } mag_clear(t); mag_clear(u); } void arb_hypgeom_erf_propagated_error(mag_t err, const arb_t z) { mag_t x; mag_init(x); /* exp(-z^2) */ arb_get_mag_lower(x, z); mag_mul_lower(x, x, x); mag_expinv(err, x); mag_mul(err, err, arb_radref(z)); /* 2/sqrt(pi) < 289/256 */ mag_mul_ui(err, err, 289); mag_mul_2exp_si(err, err, -8); /* |erf(a) - erf(b)| <= 2 */ mag_set_ui(x, 2); mag_min(err, err, x); mag_clear(x); } void arb_hypgeom_erf_1f1b(arb_t res, const arb_t z, slong prec) { arb_t t, u; slong N; mag_t err; arb_init(t); arb_init(u); mag_init(err); if (arf_cmpabs_2exp_si(arb_midref(z), -32) < 0) { if (arf_cmpabs_2exp_si(arb_midref(z), -prec) < 0) N = 1; else N = -prec / (2 * ARF_EXP(arb_midref(z))) + 1; } else { double u, dz; dz = arf_get_d(arb_midref(z), ARF_RND_DOWN); dz = fabs(dz); u = -dz * dz + prec * LOG2 + log(dz); if (dz < 1.0) u = FLINT_MAX(u, 1e-6); u = u / d_lambertw(u / (EXP1 * dz * dz)); N = u + 1; } N = FLINT_MAX(N, 1); arb_sqr(t, z, prec); _arb_hypgeom_gamma_lower_sum_rs_1(u, 3, 2, t, N, prec); /* z^(2k) / rf(3/2,k) <= (z^2)^k / k! */ arb_get_mag(err, t); mag_exp_tail(err, err, N); arb_add_error_mag(u, err); arb_neg(t, t); arb_exp(t, t, prec); arb_mul(u, u, t, prec); arb_const_sqrt_pi(t, prec); arb_div(u, u, t, prec); arb_mul(u, u, z, prec); arb_mul_2exp_si(res, u, 1); arb_clear(t); arb_clear(u); mag_clear(err); } void arb_hypgeom_erf_asymp(arb_t res, const arb_t z, slong N, int complementary, slong prec, slong prec2) { arb_t t, u; int sgn; mag_t err, tm; if (!arb_is_exact(z) && (arf_cmpabs_ui(arb_midref(z), prec) < 0 || (complementary && arb_rel_accuracy_bits(z) < prec))) { arb_t zmid; mag_t err; arb_init(zmid); mag_init(err); arb_hypgeom_erf_propagated_error(err, z); arf_set(arb_midref(zmid), arb_midref(z)); arb_hypgeom_erf_asymp(res, zmid, N, complementary, prec, prec2); arb_add_error_mag(res, err); arb_clear(zmid); mag_clear(err); return; } arb_init(t); arb_init(u); mag_init(err); mag_init(tm); sgn = arf_sgn(arb_midref(z)); arb_sqr(t, z, prec2); arb_neg(t, t); _arb_hypgeom_gamma_upper_sum_rs_1(u, 1, 2, t, N, prec2); /* Error is bounded by first omitted term, rf(1/2,N) / z^(2N) <= N! / z^(2N) */ arb_get_mag_lower(err, t); mag_inv(err, err); mag_pow_ui(err, err, N); mag_fac_ui(tm, N); mag_mul(err, err, tm); arb_add_error_mag(u, err); arb_exp(t, t, prec2); arb_mul(u, u, t, prec2); arb_const_sqrt_pi(t, prec2); arb_mul(t, t, z, prec2); arb_div(res, u, t, prec2); if (!complementary) { if (sgn == 1) arb_sub_ui(res, res, 1, prec); else arb_add_ui(res, res, 1, prec); arb_neg(res, res); } arb_clear(t); arb_clear(u); mag_clear(err); mag_clear(tm); } void arb_hypgeom_erf_1f1(arb_t res, const arb_t z, slong prec, slong wp) { if (arb_rel_accuracy_bits(z) >= wp) { arb_hypgeom_erf_1f1b(res, z, wp); } else { arb_t zmid; mag_t err; arb_init(zmid); mag_init(err); arb_hypgeom_erf_propagated_error(err, z); arf_set(arb_midref(zmid), arb_midref(z)); arb_hypgeom_erf_1f1b(res, zmid, wp); arb_add_error_mag(res, err); arb_clear(zmid); mag_clear(err); } arb_set_round(res, res, prec); } static void _arf_trunc(arf_t x) { if (arf_sgn(x) < 0) arf_ceil(x, x); else arf_floor(x, x); } static void arb_extract_bits(arb_t t, const arb_t z, slong b) { arb_mul_2exp_si(t, z, b); _arf_trunc(arb_midref(t)); mag_zero(arb_radref(t)); arb_mul_2exp_si(t, t, -b); } /* Compute Gamma(a,z) using the bit-burst algorithm. Todo: allow passing precomputed Gamma(a) as input. */ void _arb_gamma_upper_fmpq_bb(arb_t res, const fmpq_t a, const arb_t z, const mag_t abs_tol, slong prec_lower, slong prec_upper) { slong start_bits, bits, wp, NN; arb_t Gz0, Gz1, z0, z1, expmz0, t; mag_t AE; arb_init(t); arb_init(z0); arb_init(z1); arb_init(Gz0); arb_init(Gz1); arb_init(expmz0); mag_init(AE); start_bits = 64; wp = prec_upper; /* Hack: the error bound for the local Taylor series assumes that the step size is much smaller than the expansion point, even when the expansion point is close to zero. So when close to zero, we need to take more initial bits. */ while (arf_cmpabs_2exp_si(arb_midref(z), -start_bits / 4) < 0) { if (start_bits > prec_lower) { NN = _arb_hypgeom_gamma_lower_fmpq_0_choose_N(AE, a, z, abs_tol); _arb_hypgeom_gamma_lower_fmpq_0_bsplit(Gz0, a, z, NN, prec_lower); arb_add_error_mag(Gz0, AE); arb_gamma_fmpq(t, a, FLINT_MAX(prec_lower, prec_upper)); arb_sub(res, t, Gz0, prec_upper); goto bb_cleanup; } start_bits *= 2; } arb_extract_bits(z0, z, start_bits); NN = _arb_hypgeom_gamma_upper_fmpq_inf_choose_N(AE, a, z0, abs_tol); if (NN != -1) { _arb_hypgeom_gamma_upper_fmpq_inf_bsplit(Gz0, a, z0, NN, wp); arb_add_error_mag(Gz0, AE); } else { NN = _arb_hypgeom_gamma_lower_fmpq_0_choose_N(AE, a, z0, abs_tol); _arb_hypgeom_gamma_lower_fmpq_0_bsplit(Gz0, a, z0, NN, prec_lower); arb_add_error_mag(Gz0, AE); arb_gamma_fmpq(t, a, FLINT_MAX(prec_lower, prec_upper)); arb_sub(Gz0, t, Gz0, prec_upper); } arb_neg(expmz0, z0); arb_exp(expmz0, expmz0, wp); for (bits = start_bits * 2; bits < wp / 8; bits *= 2) { arb_extract_bits(z1, z, bits); _arb_gamma_upper_fmpq_step_bsplit(Gz1, a, z0, z1, Gz0, expmz0, abs_tol, wp); arb_sub(t, z0, z1, wp); arb_exp(t, t, wp); arb_mul(expmz0, expmz0, t, wp); arb_set(Gz0, Gz1); arb_set(z0, z1); } /* Final step, including error bound */ _arb_gamma_upper_fmpq_step_bsplit(Gz1, a, z0, z, Gz0, expmz0, abs_tol, wp); arb_set(res, Gz1); bb_cleanup: arb_clear(t); arb_clear(z0); arb_clear(z1); arb_clear(Gz0); arb_clear(Gz1); arb_clear(expmz0); mag_clear(AE); } int arb_hypgeom_erf_bb(arb_t res, const arb_t z, int complementary, slong prec) { mag_t tol, tm; double x; arb_t t; fmpq_t a; slong wp_lower, wp_upper; int sgn; /* Avoid bit-burst algorithm for huge input and very close to 0. */ /* With better error bounds, this exit shouldn't be necessary. */ if (!arb_is_finite(z) || arf_cmpabs_ui(arb_midref(z), prec) > 0 || arf_cmpabs_2exp_si(arb_midref(z), -prec / 16) < 0) { return 0; } sgn = arf_sgn(arb_midref(z)); x = arf_get_d(arb_midref(z), ARF_RND_DOWN); x = fabs(x); if (!arb_is_exact(z)) { arb_t zmid; mag_t err; int success; arb_init(zmid); mag_init(err); arb_hypgeom_erf_propagated_error(err, z); arf_set(arb_midref(zmid), arb_midref(z)); success = arb_hypgeom_erf_bb(res, zmid, complementary, prec); if (success) arb_add_error_mag(res, err); arb_clear(zmid); mag_clear(err); return success; } mag_init(tol); mag_init(tm); arb_init(t); fmpq_init(a); /* Near 0, need to convert relative to absolute precision for erf */ if (x < 0.25 && !complementary) { wp_lower = prec + 20 + 0.001 * prec; arb_get_mag(tol, z); mag_mul_2exp_si(tol, tol, -wp_lower); wp_upper = wp_lower + (-MAG_EXP(tol)); } else if (complementary && sgn == 1 && x > 1.0) { wp_upper = prec + 20 + 0.001 * prec; /* We will have cancellation with the lower series */ arb_get_mag_lower(tm, z); mag_mul(tol, tm, tm); mag_expinv(tol, tol); mag_div(tol, tol, tm); mag_mul_2exp_si(tol, tol, -wp_upper); wp_lower = wp_upper + x * x * INV_LOG2; if (x >= 1) wp_lower = wp_lower - log(x) * INV_LOG2; wp_lower = FLINT_MAX(wp_lower, 30); wp_upper = FLINT_MAX(wp_upper, 30); } else { wp_lower = prec + 20 + 0.001 * prec; wp_upper = wp_lower; /* Can reduce precision with the upper series */ mag_set_ui_2exp_si(tol, 1, -wp_lower); if (x >= 1) wp_upper = wp_upper - x * x * INV_LOG2 - log(x) * INV_LOG2; wp_upper = FLINT_MAX(wp_upper, 30); } fmpq_set_si(a, 1, 2); arb_sqr(t, z, FLINT_MAX(wp_lower, wp_upper)); _arb_gamma_upper_fmpq_bb(res, a, t, tol, wp_lower, wp_upper); arb_const_sqrt_pi(t, wp_upper); arb_div(res, res, t, wp_upper); if (complementary) { if (sgn < 0) { arb_sub_ui(res, res, 2, prec); arb_neg(res, res); } } else { arb_sub_ui(res, res, 1, prec); if (sgn > 0) arb_neg(res, res); } mag_clear(tol); mag_clear(tm); arb_clear(t); fmpq_clear(a); return 1; } void arb_hypgeom_erf(arb_t res, const arb_t z, slong prec) { double abs_z2, log_z; double log2_err, err_prev; slong acc, prec2, wp, N; double x; if (!arb_is_finite(z)) { arb_indeterminate(res); return; } if (arb_is_zero(z)) { arb_zero(res); return; } if (arf_cmpabs_2exp_si(arb_midref(z), -prec / 16) < 0) { wp = prec + 20 + FLINT_BIT_COUNT(prec); arb_hypgeom_erf_1f1(res, z, prec, wp); return; } if (arf_cmpabs_2exp_si(arb_midref(z), 60) > 0) { arb_hypgeom_erf_one_eps(res, z); return; } /* exp(-z^2) / z * N! / z^(2N) < 2^p */ x = arf_get_d(arb_midref(z), ARF_RND_DOWN); x = fabs(x); acc = arb_rel_accuracy_bits(z); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + x * x * INV_LOG2 + 32); if (x * x * INV_LOG2 > prec) { arb_hypgeom_erf_one_eps(res, z); return; } if (prec > 30000 && x > 150.0 / exp(4e-3 * sqrt(prec)) && x < 0.6 * sqrt(prec)) { if (arb_hypgeom_erf_bb(res, z, 0, prec)) return; } /* Can we use the asymptotic expansion? */ if (x > 2.0) { prec2 = prec + 5 + FLINT_BIT_COUNT(prec); abs_z2 = x * x; log_z = 0.5 * log(abs_z2); if ((x * x + log_z) * INV_LOG2 > prec) { arb_hypgeom_erf_one_eps(res, z); return; } wp = prec - x * x * INV_LOG2 - log_z * INV_LOG2 + 10; wp = FLINT_MAX(wp, 30); err_prev = 0.0; for (N = 1; ; N++) { log2_err = -x * x - (2 * N + 1) * log_z + N * (log(N) - 1.0); log2_err *= INV_LOG2; if (log2_err > err_prev) break; if (log2_err < -prec2 - 10) { arb_hypgeom_erf_asymp(res, z, N, 0, prec, wp); return; } err_prev = log2_err; } } wp = prec + 10 + FLINT_BIT_COUNT(prec); arb_hypgeom_erf_1f1(res, z, prec, wp); } void arb_hypgeom_erfc(arb_t res, const arb_t z, slong prec) { double x, abs_z2, log_z; slong acc, prec2, wp, N; if (!arb_is_finite(z)) { arb_indeterminate(res); return; } if (arb_is_zero(z)) { arb_one(res); return; } if (arf_cmp_si(arb_midref(z), 1) <= 0) { arb_hypgeom_erf(res, z, prec + 5); arb_sub_ui(res, res, 1, prec); arb_neg(res, res); return; } acc = arb_rel_accuracy_bits(z); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + 32); /* Super-huge -- we only need one term of the asymptotic expansion */ if (arf_cmpabs_2exp_si(arb_midref(z), prec / 2 + 10) > 0) { arb_hypgeom_erf_asymp(res, z, 1, 1, prec, prec); return; } x = arf_get_d(arb_midref(z), ARF_RND_DOWN); x = fabs(x); if (prec > 30000 && x > 150.0 / exp(4e-3 * sqrt(prec)) && x < 0.8 * sqrt(prec) + 0.65e-14 * pow(prec, 3) + 1.5e-33*pow(prec, 6)) { if (arb_hypgeom_erf_bb(res, z, 1, prec)) return; } if (arf_cmpabs_2exp_si(arb_midref(z), 30) > 0) { log_z = ARF_EXP(arb_midref(z)) * LOG2; } else { abs_z2 = x * x; log_z = 0.5 * log(abs_z2); } /* Can we use the asymptotic expansion? */ /* N! / z^(2N) < 2^p */ if (x > 2.0) { double log2_err, err_prev; prec2 = prec + 5 + FLINT_BIT_COUNT(prec); err_prev = 0.0; for (N = 1; ; N++) { log2_err = -(2 * N) * log_z + N * (log(N) - 1.0); log2_err *= INV_LOG2; if (log2_err > err_prev) break; if (log2_err < -prec - 5) { arb_hypgeom_erf_asymp(res, z, N, 1, prec, prec2); return; } err_prev = log2_err; } } /* Compute via 1F1 - with cancellation */ if (x >= 1.0) wp = prec + (x * x + log_z) * INV_LOG2; else wp = prec - log_z * INV_LOG2; wp = wp + 10 + FLINT_BIT_COUNT(prec); arb_hypgeom_erf_1f1(res, z, wp, wp); arb_sub_ui(res, res, 1, prec); arb_neg(res, res); } flint-3.1.3/src/arb_hypgeom/erf_series.c000066400000000000000000000035031461254215100202110ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_erf_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { arb_t c; arb_init(c); arb_hypgeom_erf(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else { arb_ptr t, u; slong ulen; t = _arb_vec_init(len); u = _arb_vec_init(len); /* erf(h(x)) = integral(h'(x) exp(-h(x)^2)) * (2/sqrt(pi)) */ ulen = FLINT_MIN(len, 2 * hlen - 1); _arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); _arb_vec_neg(u, u, ulen); _arb_poly_exp_series(u, u, ulen, len, prec); _arb_poly_derivative(t, h, hlen, prec); _arb_poly_mullow(g, u, len, t, hlen - 1, len, prec); _arb_poly_integral(g, g, len, prec); arb_const_sqrt_pi(t, prec); arb_inv(t, t, prec); arb_mul_2exp_si(t, t, 1); _arb_vec_scalar_mul(g, g, len, t, prec); _arb_vec_clear(t, len); _arb_vec_clear(u, len); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_erf_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, len); _arb_hypgeom_erf_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/erfc_series.c000066400000000000000000000036461461254215100203640ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_erfc_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { arb_t c; arb_init(c); arb_hypgeom_erfc(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else { arb_ptr t, u; slong ulen; t = _arb_vec_init(len); u = _arb_vec_init(len); /* erfc(h(x)) = integral(-h'(x) exp(-h(x)^2)) * (2/sqrt(pi)) */ ulen = FLINT_MIN(len, 2 * hlen - 1); _arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); _arb_vec_neg(u, u, ulen); _arb_poly_exp_series(u, u, ulen, len, prec); _arb_poly_derivative(t, h, hlen, prec); _arb_poly_mullow(g, u, len, t, hlen - 1, len, prec); _arb_poly_integral(g, g, len, prec); arb_const_sqrt_pi(t, prec); arb_inv(t, t, prec); arb_mul_2exp_si(t, t, 1); _arb_vec_scalar_mul(g, g, len, t, prec); _arb_vec_neg(g, g, len); _arb_vec_clear(t, len); _arb_vec_clear(u, len); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_erfc_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (len == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_one(g); return; } arb_poly_fit_length(g, len); _arb_hypgeom_erfc_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/erfi_series.c000066400000000000000000000034451461254215100203670ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_erfi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { arb_t c; arb_init(c); arb_hypgeom_erfi(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else { arb_ptr t, u; slong ulen; t = _arb_vec_init(len); u = _arb_vec_init(len); /* erfi(h(x)) = integral(h'(x) exp(h(x)^2)) * (2/sqrt(pi)) */ ulen = FLINT_MIN(len, 2 * hlen - 1); _arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); _arb_poly_exp_series(u, u, ulen, len, prec); _arb_poly_derivative(t, h, hlen, prec); _arb_poly_mullow(g, u, len, t, hlen - 1, len, prec); _arb_poly_integral(g, g, len, prec); arb_const_sqrt_pi(t, prec); arb_inv(t, t, prec); arb_mul_2exp_si(t, t, 1); _arb_vec_scalar_mul(g, g, len, t, prec); _arb_vec_clear(t, len); _arb_vec_clear(u, len); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_erfi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, len); _arb_hypgeom_erfi_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/erfinv.c000066400000000000000000000326021461254215100173560ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" #include "arb_fmpz_poly.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp # define log __builtin_log # define sqrt __builtin_sqrt #else # include #endif /* Actually an enclosure for |x| < 0.99. */ static void arb_erfinv_approx_tiny(arb_t res, const arb_t x, slong prec) { arb_t t; mag_t err; arb_init(t); mag_init(err); arb_get_mag(err, x); mag_pow_ui(err, err, 3); arb_const_sqrt_pi(t, prec); arb_mul_2exp_si(t, t, -1); arb_mul(res, x, t, prec); arb_add_error_mag(res, err); arb_clear(t); mag_clear(err); } /* First terms of asymptotic expansion. */ /* http://www.ams.org/journals/mcom/1976-30-136/S0025-5718-1976-0421040-7/S0025-5718-1976-0421040-7.pdf */ static double erfinv_approx_big(double one_sub_x) { double eta, l, y; eta = -log(one_sub_x*sqrt(3.1415926535897932)); l = log(eta); y = sqrt(eta - 0.5*l + (0.25*l - 0.5)/eta + (1/16.*l*l - 3/8.*l + 7./8)/(eta*eta) + (l*l*l/48 - 7*l*l/32 + 17*l/16 - 107./48)/(eta*eta*eta) + (l*l*l*l/128 - 23*l*l*l/192 + 29*l*l/32 - 31*l/8 + 1489/192.)/(eta*eta*eta*eta)); return y; } /* First terms of asymptotic expansion, when a double can overflow. */ static void arb_erfinv_approx_huge(arb_t res, const arb_t one_minus_x, slong prec) { arb_t eta, l, y; fmpz c[5]; arb_ptr poly; mag_t err; arb_init(eta); arb_init(l); arb_init(y); mag_init(err); poly = _arb_vec_init(5); arb_const_sqrt_pi(eta, prec); arb_mul(eta, eta, one_minus_x, prec); arb_log(eta, eta, prec); arb_neg(eta, eta); arb_log(l, eta, prec); arb_mul_ui(y, eta, 12, prec); arb_inv(y, y, prec); arb_mul_2exp_si(poly + 0, l, -1); arb_neg(poly + 0, poly + 0); c[0] = -2 * 3; c[1] = 3; _arb_fmpz_poly_evaluate_arb(poly + 1, c, 2, l, prec); c[0] = 14 * 9; c[1] = -6 * 9; c[2] = 9; _arb_fmpz_poly_evaluate_arb(poly + 2, c, 3, l, prec); c[0] = -214 * 18; c[1] = 102 * 18; c[2] = -21 * 18; c[3] = 2 * 18; _arb_fmpz_poly_evaluate_arb(poly + 3, c, 4, l, prec); c[0] = 2978 * 54; c[1] = -1488 * 54; c[2] = 348 * 54; c[3] = -46 * 54; c[4] = 3 * 54; _arb_fmpz_poly_evaluate_arb(poly + 4, c, 5, l, prec); _arb_poly_evaluate(res, poly, 5, y, prec); arb_add(res, res, eta, prec); arb_sqrt(res, res, prec); /* Should be an enclosure for 1-x < 1e-300 (but not proved). */ arb_get_mag(err, res); mag_mul_2exp_si(err, err, -50); arb_clear(eta); arb_clear(l); arb_clear(y); mag_clear(err); _arb_vec_clear(poly, 5); } /* Adapted from https://people.maths.ox.ac.uk/gilesm/codes/erfinv/ with permission */ /* Only good up to about 1 - 1e-15 */ /* Todo: use a good approximation for erfcinv */ static double erfinv_approx(double x, double one_sub_x) { double w, p; w = -log(one_sub_x * (1.0 + x)); if (w < 6.250000) { w = w - 3.125000; p = -3.6444120640178196996e-21; p = -1.685059138182016589e-19 + p*w; p = 1.2858480715256400167e-18 + p*w; p = 1.115787767802518096e-17 + p*w; p = -1.333171662854620906e-16 + p*w; p = 2.0972767875968561637e-17 + p*w; p = 6.6376381343583238325e-15 + p*w; p = -4.0545662729752068639e-14 + p*w; p = -8.1519341976054721522e-14 + p*w; p = 2.6335093153082322977e-12 + p*w; p = -1.2975133253453532498e-11 + p*w; p = -5.4154120542946279317e-11 + p*w; p = 1.051212273321532285e-09 + p*w; p = -4.1126339803469836976e-09 + p*w; p = -2.9070369957882005086e-08 + p*w; p = 4.2347877827932403518e-07 + p*w; p = -1.3654692000834678645e-06 + p*w; p = -1.3882523362786468719e-05 + p*w; p = 0.0001867342080340571352 + p*w; p = -0.00074070253416626697512 + p*w; p = -0.0060336708714301490533 + p*w; p = 0.24015818242558961693 + p*w; p = 1.6536545626831027356 + p*w; } else if (w < 16.000000) { w = sqrt(w) - 3.250000; p = 2.2137376921775787049e-09; p = 9.0756561938885390979e-08 + p*w; p = -2.7517406297064545428e-07 + p*w; p = 1.8239629214389227755e-08 + p*w; p = 1.5027403968909827627e-06 + p*w; p = -4.013867526981545969e-06 + p*w; p = 2.9234449089955446044e-06 + p*w; p = 1.2475304481671778723e-05 + p*w; p = -4.7318229009055733981e-05 + p*w; p = 6.8284851459573175448e-05 + p*w; p = 2.4031110387097893999e-05 + p*w; p = -0.0003550375203628474796 + p*w; p = 0.00095328937973738049703 + p*w; p = -0.0016882755560235047313 + p*w; p = 0.0024914420961078508066 + p*w; p = -0.0037512085075692412107 + p*w; p = 0.005370914553590063617 + p*w; p = 1.0052589676941592334 + p*w; p = 3.0838856104922207635 + p*w; } else { w = sqrt(w) - 5.000000; p = -2.7109920616438573243e-11; p = -2.5556418169965252055e-10 + p*w; p = 1.5076572693500548083e-09 + p*w; p = -3.7894654401267369937e-09 + p*w; p = 7.6157012080783393804e-09 + p*w; p = -1.4960026627149240478e-08 + p*w; p = 2.9147953450901080826e-08 + p*w; p = -6.7711997758452339498e-08 + p*w; p = 2.2900482228026654717e-07 + p*w; p = -9.9298272942317002539e-07 + p*w; p = 4.5260625972231537039e-06 + p*w; p = -1.9681778105531670567e-05 + p*w; p = 7.5995277030017761139e-05 + p*w; p = -0.00021503011930044477347 + p*w; p = -0.00013871931833623122026 + p*w; p = 1.0103004648645343977 + p*w; p = 4.8499064014085844221 + p*w; } return p*x; } /* floating-point approximation of erfinv(x), to be validated */ static void arb_hypgeom_erfinv_guess(arb_t res, const arb_t x, const arb_t one_sub_x, slong extraprec) { if (arf_cmpabs_2exp_si(arb_midref(x), -30) < 0) { arb_erfinv_approx_tiny(res, x, 128); } else if (arf_cmpabs_2exp_si(arb_midref(one_sub_x), -52) >= 0) { double y; y = erfinv_approx(arf_get_d(arb_midref(x), ARF_RND_NEAR), arf_get_d(arb_midref(one_sub_x), ARF_RND_NEAR)); arf_set_d(arb_midref(res), y); mag_set_d(arb_radref(res), ldexp(y, -50)); } else if (arf_cmpabs_2exp_si(arb_midref(one_sub_x), -1000) >= 0) { double t, y; t = arf_get_d(arb_midref(one_sub_x), ARF_RND_NEAR); y = erfinv_approx_big(t); arf_set_d(arb_midref(res), y); mag_set_d(arb_radref(res), ldexp(y, -26 + 0.1 * log(t))); } else { arb_erfinv_approx_huge(res, one_sub_x, 30 + extraprec); } } void arb_hypgeom_erfinv_precise(arb_t res, const arb_t x, const arb_t one_sub_x, int near_one, slong prec) { slong wp; arb_t f, fprime, root, mid, t; slong extraprec, goal; int validated; if (arb_is_zero(x)) { arb_zero(res); return; } arb_init(f); arb_init(fprime); arb_init(root); arb_init(mid); arb_init(t); goal = prec * 1.001 + 5; extraprec = fmpz_bits(ARF_EXPREF(arb_midref(one_sub_x))); extraprec += 15; /* Start with a guess */ arb_hypgeom_erfinv_guess(root, x, one_sub_x, extraprec); validated = 0; while (!validated || arb_rel_accuracy_bits(root) <= goal) { /* We should get double the accuracy. */ wp = arb_rel_accuracy_bits(root) * 2 + extraprec; /* But don't set the precision unrealistically high. */ wp = FLINT_MIN(wp, 4 * (goal + extraprec)); /* In case of quadratic convergence, avoid doing the penultimate iteration at higher precision than needed. */ if (validated && wp < goal && wp > 0.7 * goal + 2 * extraprec) wp = goal / 2 + 2 * extraprec; arb_set(mid, root); mag_zero(arb_radref(mid)); /* f(y) = erf(y) - x OR (1 - x) - erfc(y) */ /* 1/f'(y) = exp(y^2) * sqrt(pi)/2 */ if (near_one) { arb_hypgeom_erfc(f, mid, wp); arb_sub(f, one_sub_x, f, wp); } else { arb_hypgeom_erf(f, mid, wp); arb_sub(f, f, x, wp); } arb_sqr(fprime, root, wp); arb_exp(fprime, fprime, wp); arb_const_sqrt_pi(t, wp); arb_mul(fprime, fprime, t, wp); arb_mul_2exp_si(fprime, fprime, -1); arb_mul(t, f, fprime, wp); arb_sub(t, mid, t, wp); if (arb_contains_interior(root, t)) { /* Interval Newton proves inclusion. */ /* printf("newton %d -> 1 %ld: ", validated, wp); arb_printd(t, 50); printf("\n"); */ validated = 1; arb_swap(root, t); } else { /* Try to improve the guess with a floating-point Newton step. */ /* printf("newton %d -> 0 %ld: ", validated, wp); arb_printd(t, 50); printf("\n"); */ arb_sqr(fprime, mid, wp); arb_exp(fprime, fprime, wp); arb_const_sqrt_pi(t, wp); arb_mul(fprime, fprime, t, wp); arb_mul_2exp_si(fprime, fprime, -1); arb_mul(t, f, fprime, wp); /* The Newton correction is a good guess for the error. */ arb_get_mag(arb_radref(root), t); mag_mul_2exp_si(arb_radref(root), arb_radref(root), 1); arb_sub(t, mid, t, wp); arf_swap(arb_midref(root), arb_midref(t)); /* Use more working precision to get out of any numerical difficulties */ extraprec = extraprec * 1.05 + 10; validated = 0; } /* Something went wrong. Could fall back to bisection if we want to guarantee convergence? */ if (extraprec > 10 * prec + 10000) { arb_indeterminate(root); break; } } arb_set_round(res, root, prec); arb_clear(f); arb_clear(fprime); arb_clear(root); arb_clear(mid); arb_clear(t); } static slong arb_adjust_precision(slong prec, slong acc) { acc = FLINT_MIN(acc, prec); acc = FLINT_MAX(acc, 0); prec = FLINT_MIN(prec, acc + MAG_BITS); prec = FLINT_MAX(prec, 2); return prec; } void arb_hypgeom_erfinv(arb_t res, const arb_t x, slong prec) { arb_t x1; int near_one; if (arb_is_zero(x)) { arb_zero(res); return; } if (arf_sgn(arb_midref(x)) < 0) { arb_neg(res, x); arb_hypgeom_erfinv(res, res, prec); arb_neg(res, res); return; } if (arb_is_one(x)) { arb_pos_inf(res); return; } arb_init(x1); near_one = ARF_EXP(arb_midref(x)) == 0; if (near_one) { arb_sub_ui(x1, x, 1, ARF_PREC_EXACT); arb_neg(x1, x1); } else { arb_sub_ui(x1, x, 1, prec + 30); arb_neg(x1, x1); } if (arb_is_positive(x1)) { mag_t err; slong acc; arb_t xm; mag_init(err); arb_init(xm); /* Propagated error bound based on derivative. */ /* erfinv'(x) <= (1/2) sqrt(pi) / (1 - |x|) */ arb_get_mag_lower(err, x1); mag_inv(err, err); mag_mul(err, err, arb_radref(x)); mag_mul_ui(err, err, 227); mag_mul_2exp_si(err, err, -8); acc = arb_rel_accuracy_bits(x); prec = arb_adjust_precision(prec, acc); arb_get_mid_arb(xm, x); if (near_one) { arb_sub_ui(x1, xm, 1, ARF_PREC_EXACT); arb_neg(x1, x1); } else { arb_sub_ui(x1, xm, 1, prec + 30); arb_neg(x1, x1); } arb_hypgeom_erfinv_precise(res, xm, x1, near_one, prec); arb_add_error_mag(res, err); mag_clear(err); arb_clear(xm); } else { arb_indeterminate(res); } arb_clear(x1); } void arb_hypgeom_erfcinv(arb_t res, const arb_t x1, slong prec) { arb_t x; if (arb_is_one(x1)) { arb_zero(res); return; } arb_init(x); if (arf_cmp_d(arb_midref(x1), 0.01) <= 0 && arb_is_positive(x1)) { mag_t err; slong acc; arb_t x1m, xm; mag_init(err); arb_init(x1m); arb_init(xm); /* Propagated error bound based on derivative. */ /* erfinv'(x) <= (1/2) sqrt(pi) / (1 - |x|) */ arb_get_mag_lower(err, x1); mag_inv(err, err); mag_mul(err, err, arb_radref(x1)); mag_mul_ui(err, err, 227); mag_mul_2exp_si(err, err, -8); acc = arb_rel_accuracy_bits(x1); prec = arb_adjust_precision(prec, acc); arb_get_mid_arb(x1m, x1); arb_sub_ui(xm, x1m, 1, 2 * prec + 100); arb_neg(xm, xm); arb_hypgeom_erfinv_precise(res, xm, x1m, 1, prec); arb_add_error_mag(res, err); mag_clear(err); arb_clear(xm); arb_clear(x1m); } else { arb_sub_ui(x, x1, 1, 2 * prec + 100); arb_neg(x, x); arb_hypgeom_erfinv(res, x, prec); } arb_clear(x); } flint-3.1.3/src/arb_hypgeom/fresnel_series.c000066400000000000000000000060071461254215100210750ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_fresnel_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, int normalized, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_hypgeom_fresnel(s, c, h, normalized, prec); if (s != NULL) _arb_vec_zero(s + 1, len - 1); if (c != NULL) _arb_vec_zero(c + 1, len - 1); } else { arb_t s0, c0; arb_ptr t, u, v; slong ulen; arb_init(s0); arb_init(c0); arb_hypgeom_fresnel((s != NULL) ? s0 : NULL, (c != NULL) ? c0 : NULL, h, normalized, prec); t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); /* normalized: */ /* C(h(x)) = integral(h'(x) cos(-(pi/2) h(x)^2)) */ /* S(h(x)) = -integral(h'(x) sin(-(pi/2) h(x)^2)) */ ulen = FLINT_MIN(len, 2 * hlen - 1); _arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); _arb_vec_neg(u, u, ulen); if (normalized) { _arb_vec_scalar_mul_2exp_si(u, u, ulen, -1); _arb_poly_sin_cos_pi_series(u, v, u, ulen, len, prec); } else { _arb_poly_sin_cos_series(u, v, u, ulen, len, prec); } _arb_poly_derivative(t, h, hlen, prec); if (s != NULL) { _arb_poly_mullow(s, u, len, t, hlen - 1, len, prec); _arb_poly_integral(s, s, len, prec); _arb_vec_neg(s, s, len); arb_swap(s, s0); } if (c != NULL) { _arb_poly_mullow(c, v, len, t, hlen - 1, len, prec); _arb_poly_integral(c, c, len, prec); arb_swap(c, c0); } _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); arb_clear(s0); arb_clear(c0); } } void arb_hypgeom_fresnel_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, int normalized, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { if (s != NULL) arb_poly_zero(s); if (c != NULL) arb_poly_zero(c); return; } if (s != NULL) arb_poly_fit_length(s, len); if (c != NULL) arb_poly_fit_length(c, len); _arb_hypgeom_fresnel_series((s != NULL) ? s->coeffs : NULL, (c != NULL) ? c->coeffs : NULL, h->coeffs, hlen, normalized, len, prec); if (s != NULL) _arb_poly_set_length(s, len); if (c != NULL) _arb_poly_set_length(c, len); if (s != NULL) _arb_poly_normalise(s); if (c != NULL) _arb_poly_normalise(c); } flint-3.1.3/src/arb_hypgeom/gamma.c000066400000000000000000000241661461254215100171550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "acb.h" #include "arb_hypgeom.h" #include "bernoulli.h" /* tuning factor */ double GAMMA_STIRLING_BETA = 0.0; #define PI 3.1415926535897932385 static slong choose_n(double log2z, double argz, int digamma, slong prec) { double argf, boundn, boundn_best; slong n, nbest; argf = 1.0 / cos(0.5 * argz); argf = log(argf) * (1. / log(2)); boundn_best = 1e300; nbest = 1; for (n = 1; ; n++) { if (digamma) boundn = bernoulli_bound_2exp_si(2*n) - (2*n)*log2z + (2*n+1)*argf; else boundn = bernoulli_bound_2exp_si(2*n) - (2*n-1)*log2z + (2*n)*argf; /* success */ if (boundn <= -prec) return n; if (boundn < boundn_best) { nbest = n; boundn_best = boundn; } /* if the term magnitude does not decrease, r is too small */ if (boundn > 1) { /* printf("failure: prec = %ld, nbound_best = %f [%ld, %ld]\n", prec, boundn_best, n, nbest); */ return nbest; } } } static void choose_small(int * reflect, slong * r, slong * n, double x, double y, int use_reflect, int digamma, slong prec) { double w, argz, log2z, BETA; slong rr; /* use reflection formula if very negative */ if (x < -5.0 && use_reflect) { *reflect = 1; x = 1.0 - x; } else { *reflect = 0; } BETA = GAMMA_STIRLING_BETA; if (BETA < 0.12) { if (prec <= 32768) BETA = 0.17; else if (prec <= 131072) BETA = 0.20; else BETA = 0.24; } /* argument reduction until |z| >= w */ w = FLINT_MAX(1.0, BETA * prec); rr = 0; while (x < 1.0 || x*x + y*y < w*w) { x++; rr++; } log2z = 0.5 * log(x*x + y*y) * 1.44269504088896341; argz = atan2(y, x); *r = rr; *n = choose_n(log2z, argz, digamma, prec); } static void choose_large(int * reflect, slong * r, slong * n, const arf_t a, const arf_t b, int use_reflect, int digamma, slong prec) { if (use_reflect && arf_sgn(a) < 0) *reflect = 1; else *reflect = 0; *r = 0; /* so big that we will certainly have n = 0 */ if (arf_cmpabs_2exp_si(a, WORD_MAX / 8) >= 0 || arf_cmpabs_2exp_si(b, WORD_MAX / 8) >= 0) { *n = 0; } else { slong ab, bb; double log2z, argz; ab = arf_abs_bound_lt_2exp_si(a); bb = arf_abs_bound_lt_2exp_si(b); log2z = FLINT_MAX(ab, bb); /* piecewise approximation of the argument */ if (arf_is_zero(b)) { if ((arf_sgn(a) < 0) && !(*reflect)) argz = PI; else argz = 0.0; } else { if ((arf_sgn(a) < 0) && !(*reflect)) if (arf_cmpabs(a, b) <= 0) argz = PI * 0.75; else argz = PI; else if (arf_cmpabs(a, b) <= 0) argz = PI * 0.25; else argz = PI * 0.5; } if (argz == PI) *n = 0; else *n = choose_n(log2z, argz, digamma, prec); } } void acb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const acb_t z, int use_reflect, int digamma, slong prec) { const arf_struct * a = arb_midref(acb_realref(z)); const arf_struct * b = arb_midref(acb_imagref(z)); if (!arf_is_finite(a) || !arf_is_finite(b)) { *reflect = *r = *n = 0; } else if (arf_cmpabs_2exp_si(a, 40) > 0 || arf_cmpabs_2exp_si(b, 40) > 0) { choose_large(reflect, r, n, a, b, use_reflect, digamma, prec); } else { choose_small(reflect, r, n, arf_get_d(a, ARF_RND_UP), arf_get_d(b, ARF_RND_UP), use_reflect, digamma, prec); } } void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec) { const arf_struct * a = arb_midref(x); if (arf_is_inf(a) || arf_is_nan(a)) { *reflect = *r = *n = 0; } else if (arf_cmpabs_2exp_si(a, 40) > 0) { arf_t b; arf_init(b); choose_large(reflect, r, n, a, b, use_reflect, digamma, prec); arf_clear(b); } else { choose_small(reflect, r, n, arf_get_d(a, ARF_RND_UP), 0.0, use_reflect, digamma, prec); } } void arb_gamma_stirling_bound(mag_ptr err, const arb_t x, slong k0, slong knum, slong n); void arb_hypgeom_gamma_stirling_inner(arb_t s, const arb_t z, slong N, slong prec) { arb_t logz, t; mag_t err; mag_init(err); arb_init(t); arb_init(logz); arb_gamma_stirling_bound(err, z, 0, 1, N); /* t = (z-0.5)*log(z) - z + log(2*pi)/2 */ arb_log(logz, z, prec); arb_one(t); arb_mul_2exp_si(t, t, -1); arb_sub(t, z, t, prec); arb_mul(t, logz, t, prec); arb_sub(t, t, z, prec); arb_const_log_sqrt2pi(logz, prec); arb_add(t, t, logz, prec); /* sum part */ if (prec <= 128 || (prec <= 768 && N <= 40) || (prec <= 2048 && N <= 16)) arb_hypgeom_gamma_stirling_sum_horner(s, z, N, prec); else arb_hypgeom_gamma_stirling_sum_improved(s, z, N, 0, prec); arb_add(s, s, t, prec); mag_add(arb_radref(s), arb_radref(s), err); arb_clear(t); arb_clear(logz); mag_clear(err); } int arb_hypgeom_gamma_exact(arb_t res, const arb_t x, int reciprocal, slong prec) { if (arb_is_exact(x)) { const arf_struct * mid = arb_midref(x); if (arf_is_special(mid)) { if (!reciprocal && arf_is_pos_inf(mid)) arb_set(res, x); else if (arf_is_nan(mid) || arf_is_neg_inf(mid) || !reciprocal) arb_indeterminate(res); else arb_zero(res); return 1; } else if (reciprocal && arf_is_int(mid) && arf_sgn(mid) < 0) { arb_zero(res); return 1; } else { /* todo: cutoffs for larger denominators */ /* fast gamma(n), gamma(n/2) or gamma(n/4), ... */ if (arf_cmpabs_2exp_si(mid, prec) < 0 && (arf_is_int_2exp_si(mid, -2) || (prec > 1000 && arf_is_int_2exp_si(mid, -prec / 50)))) { fmpq_t a; fmpq_init(a); arf_get_fmpq(a, mid); arb_gamma_fmpq(res, a, prec + 2 * reciprocal); if (reciprocal) arb_inv(res, res, prec); fmpq_clear(a); return 1; } } } return 0; } void arb_hypgeom_gamma_stirling(arb_t y, const arb_t x, int reciprocal, slong prec) { int reflect; slong r, n, wp, ebits; arb_t t, u, v; double acc; /* for large x (if exact or accurate enough), increase precision */ if (arf_cmpabs_2exp_si(arb_midref(x), 3) > 0) { ebits = ARF_EXP(arb_midref(x)); if (COEFF_IS_MPZ(ebits) || ebits > 10 * prec + 4096) { arb_indeterminate(y); return; } } else ebits = 0; acc = arb_rel_accuracy_bits(x); acc = FLINT_MAX(acc, 0); wp = FLINT_MIN(prec + ebits, acc + 20); wp = FLINT_MAX(wp, 2); wp = wp + FLINT_BIT_COUNT(wp); if (acc < 3) /* try to avoid divisions blowing up */ { if (arf_cmp_d(arb_midref(x), -0.5) < 0) { reflect = 1; r = 0; } else if (arf_cmp_si(arb_midref(x), 1) < 0) { reflect = 0; r = 1; } else { reflect = 0; r = 0; } n = 1; } else { arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 0, wp); } arb_init(t); arb_init(u); arb_init(v); if (reflect) { arb_sub_ui(t, x, 1, wp); arb_neg(t, t); arb_hypgeom_rising_ui_rec(u, t, r, wp); arb_const_pi(v, wp); arb_mul(u, u, v, wp); arb_add_ui(t, t, r, wp); arb_hypgeom_gamma_stirling_inner(v, t, n, wp); if (reciprocal) { /* rgamma(x) = gamma(1-x+r) sin(pi x) / ((rf(1-x, r) * pi) */ arb_exp(v, v, wp); arb_sin_pi(t, x, wp); arb_mul(v, v, t, wp); arb_mul(y, u, v, wp); arb_div(y, v, u, prec); } else { /* gamma(x) = (rf(1-x, r) * pi) rgamma(1-x+r) csc(pi x) */ arb_neg(v, v); arb_exp(v, v, wp); arb_csc_pi(t, x, wp); arb_mul(v, v, t, wp); arb_mul(y, v, u, prec); } } else { arb_add_ui(t, x, r, wp); arb_hypgeom_gamma_stirling_inner(u, t, n, wp); if (reciprocal) { /* rgamma(x) = rf(x,r) rgamma(x+r) */ arb_neg(u, u); arb_exp(u, u, wp); arb_hypgeom_rising_ui_rec(v, x, r, wp); arb_mul(y, v, u, prec); } else { /* gamma(x) = gamma(x+r) / rf(x,r) */ arb_exp(u, u, wp); arb_hypgeom_rising_ui_rec(v, x, r, wp); arb_div(y, u, v, prec); } } arb_clear(t); arb_clear(u); arb_clear(v); } void arb_hypgeom_gamma(arb_t y, const arb_t x, slong prec) { if (arb_hypgeom_gamma_exact(y, x, 0, prec)) return; if (arb_hypgeom_gamma_taylor(y, x, 0, prec)) return; arb_hypgeom_gamma_stirling(y, x, 0, prec); } void arb_hypgeom_rgamma(arb_t y, const arb_t x, slong prec) { if (arb_hypgeom_gamma_exact(y, x, 1, prec)) return; if (arb_hypgeom_gamma_taylor(y, x, 1, prec)) return; arb_hypgeom_gamma_stirling(y, x, 1, prec); } flint-3.1.3/src/arb_hypgeom/gamma_fmpq.c000066400000000000000000000401331461254215100201700ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz_poly.h" #include "fmpq.h" #include "arb_hypgeom.h" #include "hypgeom.h" void arb_gamma_const_1_3_eval(arb_t s, slong prec) { hypgeom_t series; arb_t t, u; slong wp = prec + 4 + 2 * FLINT_BIT_COUNT(prec); arb_init(t); arb_init(u); hypgeom_init(series); fmpz_poly_set_str(series->A, "2 279 9108"); fmpz_poly_set_str(series->B, "1 1"); fmpz_poly_set_str(series->P, "3 -77 216 -144"); fmpz_poly_set_str(series->Q, "3 0 0 1024000"); prec += FLINT_CLOG2(prec); arb_hypgeom_infsum(s, t, series, wp, wp); arb_mul_ui(t, t, 960, wp); arb_sqrt_ui(u, 10, wp); arb_sqrt(u, u, wp); arb_mul(t, t, u, wp); arb_div(s, t, s, wp); arb_const_pi(t, wp); arb_mul(s, s, t, wp); arb_root_ui(s, s, 3, prec); hypgeom_clear(series); arb_clear(t); arb_clear(u); } ARB_DEF_CACHED_CONSTANT(arb_gamma_const_1_3, arb_gamma_const_1_3_eval) void arb_gamma_const_1_4_eval(arb_t x, slong prec) { arb_t t, u; slong wp = prec + 4 + 2 * FLINT_BIT_COUNT(prec); arb_init(t); arb_init(u); arb_one(t); arb_sqrt_ui(u, 2, wp); arb_agm(x, t, u, wp); arb_const_pi(t, wp); arb_mul_2exp_si(t, t, 1); arb_sqrt(u, t, wp); arb_mul(u, u, t, wp); arb_div(x, u, x, wp); arb_sqrt(x, x, wp); arb_clear(t); arb_clear(u); } ARB_DEF_CACHED_CONSTANT(arb_gamma_const_1_4, arb_gamma_const_1_4_eval) void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec); void arb_hypgeom_gamma_stirling_inner(arb_t s, const arb_t z, slong N, slong prec); void arb_hypgeom_gamma_fmpq_stirling(arb_t y, const fmpq_t a, slong prec) { int reflect; slong r, n, wp; arb_t x, t, u, v; wp = (slong) fmpz_bits(fmpq_numref(a)) - (slong) fmpz_bits(fmpq_denref(a)); wp = FLINT_MAX(wp, 0); wp += prec + FLINT_BIT_COUNT(prec); arb_init(x); arb_init(t); arb_init(u); arb_init(v); arb_set_fmpq(x, a, wp); arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 0, wp); if (reflect) { /* gamma(x) = (rf(1-x, r) * pi) / (gamma(1-x+r) sin(pi x)) */ fmpq_t b; fmpq_init(b); fmpz_sub(fmpq_numref(b), fmpq_denref(a), fmpq_numref(a)); fmpz_set(fmpq_denref(b), fmpq_denref(a)); arb_rising_fmpq_ui(u, b, r, wp); fmpq_clear(b); arb_const_pi(v, wp); arb_mul(u, u, v, wp); arb_sub_ui(t, x, 1, wp); arb_neg(t, t); arb_add_ui(t, t, r, wp); arb_hypgeom_gamma_stirling_inner(v, t, n, wp); arb_exp(v, v, wp); arb_sin_pi_fmpq(t, a, wp); arb_mul(v, v, t, wp); } else { /* gamma(x) = gamma(x+r) / rf(x,r) */ arb_add_ui(t, x, r, wp); arb_hypgeom_gamma_stirling_inner(u, t, n, wp); arb_exp(u, u, prec); arb_rising_fmpq_ui(v, a, r, wp); } arb_div(y, u, v, prec); arb_clear(t); arb_clear(u); arb_clear(v); arb_clear(x); } void arb_hypgeom_gamma_small_frac(arb_t y, unsigned int p, unsigned int q, slong prec) { slong wp = prec + 4; if (q == 1) { arb_one(y); } else if (q == 2) /* p = 1 */ { arb_const_sqrt_pi(y, prec); } else if (q == 3) { if (p == 1) { arb_gamma_const_1_3(y, prec); } else /* p = 2 */ { arb_t t; arb_init(t); arb_gamma_const_1_3(y, wp); arb_sqrt_ui(t, 3, wp); arb_mul(y, y, t, wp); arb_const_pi(t, wp); arb_div(y, t, y, prec); arb_mul_2exp_si(y, y, 1); arb_clear(t); } } else if (q == 4) { if (p == 1) { arb_gamma_const_1_4(y, prec); } else /* p = 3 */ { arb_t t; arb_init(t); arb_sqrt_ui(y, 2, wp); arb_const_pi(t, wp); arb_mul(y, y, t, wp); arb_gamma_const_1_4(t, wp); arb_div(y, y, t, prec); arb_clear(t); } } else if (q == 6) { arb_t t; arb_init(t); arb_const_pi(t, wp); arb_div_ui(t, t, 3, wp); arb_sqrt(t, t, wp); arb_set_ui(y, 2); arb_root_ui(y, y, 3, wp); arb_mul(t, t, y, wp); arb_gamma_const_1_3(y, wp); arb_mul(y, y, y, prec); if (p == 1) { arb_div(y, y, t, prec); } else /* p = 5 */ { arb_div(y, t, y, wp); arb_const_pi(t, wp); arb_mul(y, y, t, prec); arb_mul_2exp_si(y, y, 1); } arb_clear(t); } else { flint_throw(FLINT_ERROR, "small fraction not implemented!\n"); } } slong _arb_compute_bs_exponents(slong * tab, slong n); slong _arb_get_exp_pos(const slong * tab, slong step); static void bsplit2(arb_t P, arb_t Q, const fmpz_t zp, const fmpz_t zq, const slong * xexp, arb_srcptr xpow, ulong N, slong a, slong b, int cont, slong prec) { if (b - a == 1) { fmpz_t t; fmpz_init(t); fmpz_set(t, zp); fmpz_addmul_ui(t, zq, a + 1); arb_set_fmpz(P, t); arb_set(Q, P); fmpz_clear(t); } else { arb_t Pb, Qb; slong step, i, m; arb_init(Pb); arb_init(Qb); step = (b - a) / 2; m = a + step; bsplit2(P, Q, zp, zq, xexp, xpow, N, a, m, 1, prec); bsplit2(Pb, Qb, zp, zq, xexp, xpow, N, m, b, 1, prec); arb_mul(P, P, Pb, prec); arb_mul(Q, Q, Pb, prec); i = (step == 1) ? 0 : _arb_get_exp_pos(xexp, step); arb_addmul(Q, Qb, xpow + i, prec); arb_clear(Pb); arb_clear(Qb); } } static void bsplit3(arb_t P, arb_t Q, const fmpz_t zp, const fmpz_t zq, const slong * xexp, arb_srcptr xpow, ulong N, slong a, slong b, int cont, slong prec) { if (b - a == 1) { fmpz_t t; fmpz_init(t); arb_set(P, xpow + 0); /* N zq */ fmpz_set(t, zp); fmpz_submul_ui(t, zq, a + 1); /* zp - (a + 1) zq */ arb_set_fmpz(Q, t); fmpz_clear(t); } else { arb_t Pb, Qb; slong step, i, m; arb_init(Pb); arb_init(Qb); step = (b - a) / 2; m = a + step; bsplit3(P, Q, zp, zq, xexp, xpow, N, a, m, 1, prec); bsplit3(Pb, Qb, zp, zq, xexp, xpow, N, m, b, 1, prec); i = _arb_get_exp_pos(xexp, m - a); arb_mul(P, P, xpow + i, prec); if (b - m != m - a) arb_mul(P, P, xpow + 0, prec); arb_addmul(P, Q, Pb, prec); if (cont) { arb_mul(Q, Q, Qb, prec); } else { i = _arb_get_exp_pos(xexp, m - a); arb_mul(Q, xpow + i, xpow + i, prec); if (b - m != m - a) arb_mul(Q, Q, xpow + 0, prec); } arb_clear(Pb); arb_clear(Qb); } } double d_lambertw_branch1(double x); static ulong more_trailing_zeros(ulong N) { ulong bc, N2; bc = FLINT_BIT_COUNT(N); if (bc >= 8) { N2 = (N >> (bc - 5)) << (bc - 5); N2 += ((N2 != N) << (bc - 5)); return N2; } else { return N; } } #define C_LOG2 0.69314718055994530942 #define C_EXP1 2.7182818284590452354 static void build_bsplit_power_table(arb_ptr xpow, const slong * xexp, slong len, slong prec) { slong i; for (i = 1; i < len; i++) { if (xexp[i] == 2 * xexp[i-1]) { arb_mul(xpow + i, xpow + i - 1, xpow + i - 1, prec); } else if (xexp[i] == 2 * xexp[i-2]) /* prefer squaring if possible */ { arb_mul(xpow + i, xpow + i - 2, xpow + i - 2, prec); } else if (xexp[i] == 2 * xexp[i-1] + 1) { arb_mul(xpow + i, xpow + i - 1, xpow + i - 1, prec); arb_mul(xpow + i, xpow + i, xpow, prec); } else if (xexp[i] == 2 * xexp[i-2] + 1) { arb_mul(xpow + i, xpow + i - 2, xpow + i - 2, prec); arb_mul(xpow + i, xpow + i, xpow, prec); } else { flint_throw(FLINT_ERROR, "power table has the wrong structure!\n"); } } } /* assumes z in [1, 2] */ static void arb_hypgeom_gamma_fmpq_general_off1(arb_t res, const fmpq_t z, slong prec) { slong wp, N, n, n2, length, length2, wp2; double alpha; arb_t P, Q; slong *xexp, *xexp2; arb_ptr xpow; mag_t err, err2; wp = prec + 30; alpha = 0.52; /* tuning parameter between 0.5 and 1 */ N = alpha * C_LOG2 * wp; N = more_trailing_zeros(N); alpha = N / (C_LOG2 * wp); /* Terms in convergent series */ n = (1 - alpha) / d_lambertw((1 - alpha) / (alpha * C_EXP1)) * C_LOG2 * wp; /* Precision and terms in asymptotic series */ wp2 = wp * (1 - alpha); wp2 = FLINT_MAX(wp2, 30); n2 = (alpha - 1) / d_lambertw_branch1((alpha - 1) / (alpha * C_EXP1)) * C_LOG2 * wp; n2 = FLINT_MAX(n2, 2); /* binary splitting correctness */ mag_init(err); mag_init(err2); arb_init(P); arb_init(Q); /* compute the powers of x = N*zq that will appear (at least x^1) */ xexp = flint_calloc(2 * FLINT_BITS, sizeof(slong)); xexp2 = flint_calloc(2 * FLINT_BITS, sizeof(slong)); length = _arb_compute_bs_exponents(xexp, n); length2 = _arb_compute_bs_exponents(xexp2, n2); xpow = _arb_vec_init(FLINT_MAX(length, length2)); arb_set_fmpz(xpow + 0, fmpq_denref(z)); arb_mul_ui(xpow + 0, xpow + 0, N, wp); build_bsplit_power_table(xpow, xexp, length, wp); /* 1F1(1, 1+z, N) */ bsplit2(P, Q, fmpq_numref(z), fmpq_denref(z), xexp, xpow, N, 0, n, 0, wp); arb_div(P, Q, P, wp); /* Convergent series error bound: N^n / n! (1 + (N/n) + ...) */ mag_set_ui(err, N); mag_pow_ui(err, err, n); mag_rfac_ui(err2, n); mag_mul(err, err, err2); mag_set_ui(err2, N); mag_div_ui(err2, err2, n); mag_geom_series(err2, err2, 0); mag_mul(err, err, err2); arb_add_error_mag(P, err); /* divide 1F1 by z */ arb_mul_fmpz(P, P, fmpq_denref(z), wp); arb_div_fmpz(P, P, fmpq_numref(z), wp); arb_swap(res, P); build_bsplit_power_table(xpow, xexp2, length2, wp2); bsplit3(P, Q, fmpq_numref(z), fmpq_denref(z), xexp2, xpow, N, 0, n2, 0, wp2); arb_div(P, P, Q, wp2); /* 2F0 error bound (bounded by first omitted term) */ mag_fac_ui(err, n2); mag_set_ui_lower(err2, N); mag_pow_ui_lower(err2, err2, n2); mag_div(err, err, err2); arb_add_error_mag(P, err); /* N^z * exp(-N) * (1F1/z + 2F0/N) */ arb_div_ui(P, P, N, wp2); arb_add(res, res, P, wp); arb_set_ui(Q, N); arb_pow_fmpq(Q, Q, z, wp); arb_mul(res, res, Q, wp); arb_set_si(Q, -N); arb_exp(Q, Q, wp); arb_mul(res, res, Q, wp); _arb_vec_clear(xpow, FLINT_MAX(length, length2)); flint_free(xexp); flint_free(xexp2); arb_clear(P); arb_clear(Q); mag_clear(err); mag_clear(err2); } /* assumes z in (0, 1] */ void arb_hypgeom_gamma_fmpq_hyp(arb_t res, const fmpq_t z, slong prec) { fmpq_t t; fmpq_init(t); fmpq_add_ui(t, z, 1); arb_hypgeom_gamma_fmpq_general_off1(res, t, prec); arb_mul_fmpz(res, res, fmpq_denref(z), prec + 30); arb_div_fmpz(res, res, fmpq_numref(z), prec); fmpq_clear(t); } void arb_hypgeom_gamma_fmpq_outward(arb_t y, const fmpq_t x, slong prec) { fmpq_t a; fmpz_t n; fmpz p, q; slong m; arb_t t, u; fmpq_init(a); fmpz_init(n); arb_init(t); arb_init(u); /* write x = a + n with 0 < a <= 1 */ if (fmpz_is_one(fmpq_denref(x))) { fmpq_one(a); fmpz_sub_ui(n, fmpq_numref(x), 1); } else { fmpz_fdiv_qr(n, fmpq_numref(a), fmpq_numref(x), fmpq_denref(x)); fmpz_set(fmpq_denref(a), fmpq_denref(x)); } if (!fmpz_fits_si(n)) { flint_throw(FLINT_ERROR, "gamma: too large fmpq to reduce to 0!\n"); } m = fmpz_get_si(n); /* evaluate gamma(a) */ p = *fmpq_numref(a); q = *fmpq_denref(a); if (q == 1 || q == 2 || q == 3 || q == 4 || q == 6) { arb_hypgeom_gamma_small_frac(t, p, q, prec + 4 * (m != 0)); } else { arb_hypgeom_gamma_fmpq_hyp(t, a, prec + 4 * (m != 0)); } /* argument reduction */ if (m >= 0) { arb_rising_fmpq_ui(u, a, m, prec + 4); arb_mul(y, t, u, prec); } else { arb_rising_fmpq_ui(u, x, -m, prec + 4); arb_div(y, t, u, prec); } fmpq_clear(a); fmpz_clear(n); arb_clear(t); arb_clear(u); } int arb_hypgeom_gamma_fmpq_taylor(arb_t y, const fmpq_t x, slong prec) { fmpq_t a; fmpz_t n; slong m; arb_t t; int success; fmpq_init(a); fmpz_init(n); arb_init(t); success = 1; /* write x = a + n with 0 < a <= 1 */ if (fmpz_is_one(fmpq_denref(x))) { fmpq_one(a); fmpz_sub_ui(n, fmpq_numref(x), 1); } else { fmpz_fdiv_qr(n, fmpq_numref(a), fmpq_numref(x), fmpq_denref(x)); fmpz_set(fmpq_denref(a), fmpq_denref(x)); } if (!fmpz_fits_si(n)) { success = 0; goto cleanup; } m = fmpz_get_si(n); if (m < -(40 + (prec - 40) / 4)) { success = 0; goto cleanup; } if (m > 70 + (prec - 40) / 8) { success = 0; goto cleanup; } arb_set_fmpq(t, a, prec + 4); success = arb_hypgeom_gamma_taylor(t, t, 0, prec + 4); if (success) { arb_t u; arb_init(u); if (m >= 0) { arb_rising_fmpq_ui(u, a, m, prec + 4); arb_mul(y, t, u, prec); } else { arb_rising_fmpq_ui(u, x, -m, prec + 4); arb_div(y, t, u, prec); } arb_clear(u); } cleanup: fmpq_clear(a); fmpz_clear(n); arb_clear(t); return success; } void arb_hypgeom_gamma_fmpq(arb_t y, const fmpq_t x, slong prec) { fmpz p, q; p = *fmpq_numref(x); q = *fmpq_denref(x); if ((q == 1 || q == 2 || q == 3 || q == 4 || q == 6) && !COEFF_IS_MPZ(p)) { if (q == 1) { if (p <= 0) { arb_indeterminate(y); return; } if (p < 1200 || 1.44265 * (p*log(p) - p) < 15.0 * prec) { fmpz_t t; fmpz_init(t); fmpz_fac_ui(t, p - 1); arb_set_round_fmpz(y, t, prec); fmpz_clear(t); return; } } p = FLINT_ABS(p); if (p < q * 500.0 || p < q * (500.0 + 0.1 * prec * sqrt(prec))) { arb_hypgeom_gamma_fmpq_outward(y, x, prec); return; } } if (q != 1 && prec > 7000 + 300 * fmpz_bits(fmpq_denref(x)) && (slong) fmpz_bits(fmpq_numref(x)) - (slong) fmpz_bits(fmpq_denref(x)) < FLINT_BITS && fabs(fmpq_get_d(x)) < 0.03 * prec * sqrt(prec)) { arb_hypgeom_gamma_fmpq_outward(y, x, prec); return; } if (fmpz_bits(fmpq_denref(x)) > 0.1 * prec || fmpz_bits(fmpq_numref(x)) > 0.1 * prec) { slong wp; wp = (slong) fmpz_bits(fmpq_numref(x)) - (slong) fmpz_bits(fmpq_denref(x)); wp = FLINT_MAX(wp, 0); wp = FLINT_MIN(wp, 10 * prec); wp += prec + 4; arb_set_fmpq(y, x, wp); if (!arb_hypgeom_gamma_taylor(y, y, 0, prec)) arb_hypgeom_gamma_stirling(y, y, 0, prec); return; } if (arb_hypgeom_gamma_fmpq_taylor(y, x, prec)) return; arb_hypgeom_gamma_fmpq_stirling(y, x, prec); } void arb_hypgeom_gamma_fmpz(arb_t y, const fmpz_t x, slong prec) { fmpq_t t; *fmpq_numref(t) = *x; *fmpq_denref(t) = WORD(1); arb_hypgeom_gamma_fmpq(y, t, prec); } flint-3.1.3/src/arb_hypgeom/gamma_lower_series.c000066400000000000000000000061771461254215100217410ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_gamma_lower_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec) { arb_t c; hlen = FLINT_MIN(hlen, n); if (regularized == 2 && arb_is_int(s) && arb_is_nonpositive(s)) { arb_t ns; arb_init(ns); arb_neg(ns, s); if (g == h) { arb_ptr t = _arb_vec_init(hlen); _arb_vec_set(t, h, hlen); _arb_poly_pow_arb_series(g, t, hlen, ns, n, prec); _arb_vec_clear(t, hlen); } else { _arb_poly_pow_arb_series(g, h, hlen, ns, n, prec); } arb_clear(ns); return; } arb_init(c); arb_hypgeom_gamma_lower(c, s, h, regularized, prec); if (hlen == 1) { _arb_vec_zero(g + 1, n - 1); } else { arb_ptr t, u, v; arb_ptr w = NULL; t = _arb_vec_init(n); u = _arb_vec_init(n); v = _arb_vec_init(n); if (regularized == 2) { w = _arb_vec_init(n); arb_neg(t, s); _arb_poly_pow_arb_series(w, h, hlen, t, n, prec); } /* gamma(s, h(x)) = integral(h'(x) h(x)^(s-1) exp(-h(x)) */ arb_sub_ui(u, s, 1, prec); _arb_poly_pow_arb_series(t, h, hlen, u, n, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_mullow(v, t, n, u, hlen - 1, n, prec); _arb_vec_neg(t, h, hlen); _arb_poly_exp_series(t, t, hlen, n, prec); _arb_poly_mullow(g, v, n, t, n, n, prec); _arb_poly_integral(g, g, n, prec); if (regularized == 1) { arb_rgamma(t, s, prec); _arb_vec_scalar_mul(g, g, n, t, prec); } else if (regularized == 2) { arb_rgamma(t, s, prec); _arb_vec_scalar_mul(g, g, n, t, prec); _arb_vec_set(u, g, n); _arb_poly_mullow(g, u, n, w, n, n, prec); _arb_vec_clear(w, n); } _arb_vec_clear(t, n); _arb_vec_clear(u, n); _arb_vec_clear(v, n); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_gamma_lower_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, n); if (hlen == 0) { arb_t t; arb_init(t); _arb_hypgeom_gamma_lower_series(g->coeffs, s, t, 1, regularized, n, prec); arb_clear(t); } else { _arb_hypgeom_gamma_lower_series( g->coeffs, s, h->coeffs, hlen, regularized, n, prec); } _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/gamma_lower_sum_rs.c000066400000000000000000000066751461254215100217620ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define ldexp __builtin_ldexp # define log __builtin_log #else # include #endif static slong exp_series_prec(slong k, double dz, double logdz, slong prec) { double gain; if (prec <= 128) return prec; if (k <= dz + 5 || k <= 5) return prec; gain = (dz - k * logdz + k * (log(k) - 1.0)) * 1.4426950408889634; gain = FLINT_MAX(gain, 0); prec = prec - gain; prec = FLINT_MAX(prec, 32); return prec; } void _arb_hypgeom_gamma_lower_sum_rs_1(arb_t res, ulong p, ulong q, const arb_t z, slong N, slong prec) { slong m, j, k, jlen, jbot, wp; double dz, logdz; mp_limb_t c, chi, clo; arb_t s; arb_ptr zpow; mp_ptr cs; m = n_sqrt(N); m = FLINT_MAX(m, 2); k = N - 1; j = k % m; jlen = 0; jbot = j; c = 1; dz = arf_get_d(arb_midref(z), ARF_RND_UP); dz = fabs(dz); if (arf_cmpabs_2exp_si(arb_midref(z), prec) >= 0) { dz = ldexp(1.0, prec); logdz = ARF_EXP(arb_midref(z)) * log(2); } else if (arf_cmpabs_2exp_si(arb_midref(z), -32) >= 0) { logdz = log(dz); } else if (arf_cmpabs_2exp_si(arb_midref(z), -prec) <= 0) { logdz = -prec * log(2); } else { logdz = ARF_EXP(arb_midref(z)) * log(2); } arb_init(s); zpow = _arb_vec_init(m + 1); cs = flint_malloc(sizeof(mp_limb_t) * (m + 1)); arb_mul_ui(zpow + m, z, q, prec); _arb_vec_set_powers(zpow, zpow + m, m + 1, prec); while (k >= 0) { if (k != 0) { /* Check if new coefficient will overflow limb */ umul_ppmm(chi, clo, c, p + (k - 1) * q); if (chi != 0) { wp = exp_series_prec(k, dz, logdz, prec); /* Denominator will change, so evaluate current dot product */ if (jlen != 0) { arb_dot_ui(s, s, 0, zpow + jbot, 1, cs + jbot, 1, jlen, wp); jlen = 0; } arb_div_ui(s, s, c, wp); c = 1; } } /* Update dot product */ cs[j] = c; jlen++; jbot = j; if (k != 0) { c = c * (p + (k - 1) * q); /* Giant-step time. */ if (j == 0) { wp = exp_series_prec(k, dz, logdz, prec); /* Evaluate current dot product */ if (jlen != 0) { arb_dot_ui(s, s, 0, zpow + jbot, 1, cs + jbot, 1, jlen, wp); jlen = 0; } arb_mul(s, s, zpow + m, wp); j = m - 1; } else { j--; } } k--; } if (jlen != 0) { arb_dot_ui(s, s, 0, zpow + jbot, 1, cs + jbot, 1, jlen, prec); jlen = 0; } arb_div_ui(res, s, c, prec); _arb_vec_clear(zpow, m + 1); arb_clear(s); flint_free(cs); } flint-3.1.3/src/arb_hypgeom/gamma_stirling_sum_horner.c000066400000000000000000000033051461254215100233210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_gamma_stirling_coeff(arb_t b, ulong k, int digamma, slong prec); void arb_hypgeom_gamma_stirling_sum_horner(arb_t s, const arb_t z, slong N, slong prec) { arb_t b, t, zinv, w; mag_t zinv_mag; slong n, term_mag, term_prec; slong * term_mags; if (N <= 1) { arb_zero(s); return; } arb_init(b); arb_init(t); arb_init(zinv); arb_init(w); mag_init(zinv_mag); arb_inv(zinv, z, prec); arb_mul(w, zinv, zinv, prec); arb_get_mag(zinv_mag, zinv); term_mags = flint_malloc(sizeof(ulong) * N); _arb_hypgeom_gamma_stirling_term_bounds(term_mags, zinv_mag, N); arb_zero(s); for (n = N - 1; n >= 1; n--) { term_mag = term_mags[n]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); if (prec - term_prec > 200) { arb_set_round(t, w, term_prec); arb_mul(s, s, t, term_prec); } else arb_mul(s, s, w, term_prec); arb_gamma_stirling_coeff(b, n, 0, term_prec); arb_add(s, s, b, term_prec); } arb_mul(s, s, zinv, prec); flint_free(term_mags); arb_clear(t); arb_clear(b); arb_clear(zinv); arb_clear(w); mag_clear(zinv_mag); } flint-3.1.3/src/arb_hypgeom/gamma_stirling_sum_improved.c000066400000000000000000000303771461254215100236620ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" #include "bernoulli.h" void arb_hypgeom_gamma_stirling_sum_improved(arb_t s, const arb_t z, slong N, slong K, slong prec) { arb_t b, t, zinv, w, u, S2, S3, S4; mag_t zinv_mag, err; slong n, term_mag, term_prec; slong * term_mags; slong i, j, k, M; slong * Mk; arb_ptr upow, ukpow; slong kodd, kpow_exp, wp; fmpz_t kpow; slong m; if (N <= 1) { arb_zero(s); return; } if (N == 2) { arb_mul_ui(s, z, 12, prec); arb_inv(s, s, prec); return; } if (K == 0) { if (prec <= 128) K = 1; else if (prec <= 1024) K = 2; else { K = 4 + 0.1 * sqrt(FLINT_MAX(prec - 4096, 0)); K = FLINT_MIN(K, 100); } } arb_init(b); arb_init(t); arb_init(zinv); arb_init(w); arb_init(u); arb_init(S2); arb_init(S3); arb_init(S4); mag_init(zinv_mag); mag_init(err); arb_inv(zinv, z, prec); arb_mul(w, zinv, zinv, prec); arb_get_mag(zinv_mag, zinv); term_mags = flint_malloc(sizeof(ulong) * (N + 1)); /* Avoid possible overflow. (This case is not interesting to handle well, but we need to handle it.) */ if (mag_cmp_2exp_si(zinv_mag, 10) > 0) K = 1; /* Avoid possible underflow. */ if (mag_cmp_2exp_si(zinv_mag, -100000) < 0) mag_set_ui_2exp_si(zinv_mag, 1, -100000); _arb_hypgeom_gamma_stirling_term_bounds(term_mags, zinv_mag, N + 1); /* We will assume below that term_mags is nonincreasing */ for (n = N - 2; n >= 1; n--) { if (term_mags[n] < term_mags[n + 1]) term_mags[n] = term_mags[n + 1]; } Mk = NULL; if (K > 1) { Mk = flint_malloc(sizeof(slong) * (K + 1)); Mk[0] = Mk[1] = N; for (k = 2; k <= K; k++) { double log2_k; Mk[k] = N; log2_k = log(k) * (1.0 / 0.693147180559945309); while (Mk[k] > 2) { slong err, Mnew; Mnew = Mk[k] - 1; err = term_mags[Mnew] - log2_k * (2 * Mnew) + FLINT_BIT_COUNT(N - Mnew); if (err < -prec) Mk[k] = Mnew; else break; } } /* We will assume that Mk is nonincreasing. */ for (k = 2; k <= K; k++) { if (Mk[k] > Mk[k - 1]) Mk[k] = Mk[k - 1]; } while (K >= 2 && Mk[K] == Mk[K - 1]) K--; M = Mk[K]; mag_hurwitz_zeta_uiui(err, 2 * M, K); mag_mul_ui(err, err, N - M); mag_mul_2exp_si(err, err, term_mags[M]); for (k = 1; k < K; k++) { mag_t t; mag_init(t); mag_set_ui_lower(t, k); mag_inv(t, t); mag_pow_ui(t, t, 2 * Mk[k]); mag_mul_ui(t, t, N - Mk[k]); mag_mul_2exp_si(t, t, term_mags[Mk[k]]); mag_add(err, err, t); mag_clear(t); } } else { M = N; } m = sqrt(N - M); m = FLINT_MAX(m, 1); /* S3 precision */ wp = prec + term_mags[M]; wp = FLINT_MIN(wp, prec); wp = FLINT_MAX(wp, 10); arb_zero(S3); /* todo: could avoid one mul + div with precomputation here */ /* u = -1 / (2 pi z)^2 */ arb_const_pi(u, wp); arb_mul(u, u, z, wp); arb_mul_2exp_si(u, u, 1); arb_mul(u, u, u, wp); arb_inv(u, u, wp); arb_neg(u, u); fmpz_init(kpow); upow = _arb_vec_init(m + 1); ukpow = _arb_vec_init(m + 1); _arb_vec_set_powers(upow, u, m + 1, wp); for (kodd = 1; kodd < K; kodd += 2) { for (k = kodd; k < K; k *= 2) { if (k == 1) { _arb_vec_set(ukpow, upow, m + 1); fmpz_one(kpow); kpow_exp = 0; } else if (k == kodd) { arb_set(ukpow + 0, upow + 0); for (j = 1; j <= FLINT_MIN(Mk[k] - M - 1, m); j++) { if (j == 1) fmpz_set_ui(kpow, k * k); else fmpz_mul_ui(kpow, kpow, k * k); arb_div_fmpz(ukpow + j, upow + j, kpow, wp); } /* set kpow = k^(2M) */ fmpz_ui_pow_ui(kpow, k * k, M); kpow_exp = 0; } else { /* compute x / k^(2j) given x / (k/2)^(2j) */ for (j = 1; j <= FLINT_MIN(Mk[k] - M - 1, m); j++) arb_mul_2exp_si(ukpow + j, ukpow + j, -2 * j); kpow_exp += 2 * M; } arb_zero(S4); for (n = Mk[k] - 1; n >= M; n--) { i = n - M; term_prec = prec + term_mags[n]; term_prec = FLINT_MIN(wp, prec); term_prec = FLINT_MAX(term_prec, 10); /* note: set_round makes small difference here */ arb_fma_ui(S4, S4, (2 * n) * (2 * n - 1), ukpow + i % m, term_prec); if (i != 0 && i % m == 0) { /* note: set_round makes small difference here */ arb_mul(S4, S4, ukpow + m, term_prec); } } /* divide by k^(2M) */ if (k != 1) { if (!fmpz_is_one(kpow)) arb_div_fmpz(S4, S4, kpow, wp); arb_mul_2exp_si(S4, S4, -kpow_exp); } arb_add(S3, S3, S4, wp); } } /* multiply by -2 (2M-2)! u^M z */ fmpz_fac_ui(kpow, 2 * M - 2); arb_mul_fmpz(S3, S3, kpow, wp); arb_pow_ui(u, u, M, wp); arb_mul(S3, S3, u, wp); arb_set_round(t, z, wp); arb_mul(S3, S3, t, wp); arb_mul_2exp_si(S3, S3, 1); arb_neg(S3, S3); arb_add_error_mag(S3, err); _arb_vec_clear(upow, m + 1); _arb_vec_clear(ukpow, m + 1); fmpz_clear(kpow); arb_zero(S2); m = sqrt(M); upow = _arb_vec_init(m + 1); _arb_vec_set_powers(upow, w, m + 1, prec); BERNOULLI_ENSURE_CACHED(2 * M - 2); { fmpz_t d, e, f, g, h; fmpz q[4]; fmpz_init(d); fmpz_init(e); fmpz_init(f); fmpz_init(g); fmpz_init(h); fmpz_init(q); fmpz_init(q + 1); fmpz_init(q + 2); fmpz_init(q + 3); for (n = M - 1; n >= 1; n--) { i = n - 1; if (i >= 4 && i % m >= 3 && prec >= 512 && prec <= 4096) { term_mag = term_mags[n - 3]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * (n - 0)), 2 * (n - 0) * (2 * (n - 0) - 1)); fmpz_mul_ui(e, fmpq_denref(bernoulli_cache + 2 * (n - 1)), 2 * (n - 1) * (2 * (n - 1) - 1)); fmpz_mul_ui(g, fmpq_denref(bernoulli_cache + 2 * (n - 2)), 2 * (n - 2) * (2 * (n - 2) - 1)); fmpz_mul_ui(h, fmpq_denref(bernoulli_cache + 2 * (n - 3)), 2 * (n - 3) * (2 * (n - 3) - 1)); /* q3 = egh q2 = dgh q1 = deh q0 = deg d = degh */ fmpz_mul(q + 3, e, g); fmpz_mul(q + 0, q + 3, d); fmpz_mul(q + 3, q + 3, h); fmpz_mul(q + 2, d, h); fmpz_mul(q + 1, q + 2, e); fmpz_mul(q + 2, q + 2, g); fmpz_mul(d, q + 3, d); fmpz_mul(q + 3, q + 3, fmpq_numref(bernoulli_cache + 2 * (n - 0))); fmpz_mul(q + 2, q + 2, fmpq_numref(bernoulli_cache + 2 * (n - 1))); fmpz_mul(q + 1, q + 1, fmpq_numref(bernoulli_cache + 2 * (n - 2))); fmpz_mul(q + 0, q + 0, fmpq_numref(bernoulli_cache + 2 * (n - 3))); arb_dot_fmpz(t, NULL, 0, upow + i % m - 3, 1, q, 1, 4, term_prec); arb_div_fmpz(t, t, d, term_prec); arb_add(S2, S2, t, term_prec); n -= 3; i -= 3; } else if (i >= 3 && i % m >= 2) { term_mag = term_mags[n - 2]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * (n - 0)), 2 * (n - 0) * (2 * (n - 0) - 1)); fmpz_mul_ui(e, fmpq_denref(bernoulli_cache + 2 * (n - 1)), 2 * (n - 1) * (2 * (n - 1) - 1)); fmpz_mul_ui(g, fmpq_denref(bernoulli_cache + 2 * (n - 2)), 2 * (n - 2) * (2 * (n - 2) - 1)); fmpz_mul(q + 2, e, g); fmpz_mul(q + 2, q + 2, fmpq_numref(bernoulli_cache + 2 * (n - 0))); fmpz_mul(q + 1, d, g); fmpz_mul(q + 1, q + 1, fmpq_numref(bernoulli_cache + 2 * (n - 1))); fmpz_mul(q + 0, d, e); fmpz_mul(d, q + 0, g); fmpz_mul(q + 0, q + 0, fmpq_numref(bernoulli_cache + 2 * (n - 2))); arb_dot_fmpz(t, NULL, 0, upow + i % m - 2, 1, q, 1, 3, term_prec); arb_div_fmpz(t, t, d, term_prec); arb_add(S2, S2, t, term_prec); n -= 2; i -= 2; } else if (i >= 1 && i % m >= 1) { term_mag = term_mags[n - 1]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * (n - 0)), 2 * (n - 0) * (2 * (n - 0) - 1)); fmpz_mul_ui(e, fmpq_denref(bernoulli_cache + 2 * (n - 1)), 2 * (n - 1) * (2 * (n - 1) - 1)); fmpz_mul(f, fmpq_numref(bernoulli_cache + 2 * (n - 0)), e); arb_set_round(u, upow + i % m, term_prec); arb_mul_fmpz(t, u, f, term_prec); /* todo: output-sensitive mul */ fmpz_mul(f, fmpq_numref(bernoulli_cache + 2 * (n - 1)), d); arb_set_round(u, upow + i % m - 1, term_prec); arb_mul_fmpz(u, u, f, term_prec); /* todo: output-sensitive mul */ arb_add(t, t, u, term_prec); fmpz_mul(d, d, e); arb_div_fmpz(t, t, d, term_prec); arb_add(S2, S2, t, term_prec); n--; i--; } else { term_mag = term_mags[n]; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); arb_set_round(u, upow + i % m, term_prec); arb_mul_fmpz(t, u, fmpq_numref(bernoulli_cache + 2 * n), term_prec); /* todo: output-sensitive mul */ fmpz_mul_ui(d, fmpq_denref(bernoulli_cache + 2 * n), 2 * n * (2 * n - 1)); arb_div_fmpz(t, t, d, term_prec); arb_add(S2, S2, t, term_prec); } if (i != 0 && i % m == 0) { arb_set_round(u, upow + m, term_prec); /* todo: output-sensitive mul */ arb_mul(S2, S2, u, term_prec); } } fmpz_clear(q); fmpz_clear(q + 1); fmpz_clear(q + 2); fmpz_clear(q + 3); fmpz_clear(d); fmpz_clear(e); fmpz_clear(f); fmpz_clear(g); fmpz_clear(h); } _arb_vec_clear(upow, m + 1); arb_mul(S2, S2, zinv, prec); arb_add(s, S2, S3, prec); flint_free(term_mags); if (Mk != NULL) flint_free(Mk); arb_clear(b); arb_clear(t); arb_clear(zinv); arb_clear(w); arb_clear(u); arb_clear(S2); arb_clear(S3); arb_clear(S4); mag_clear(zinv_mag); mag_clear(err); } flint-3.1.3/src/arb_hypgeom/gamma_stirling_term_bounds.c000066400000000000000000000022101461254215100234530ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void _arb_hypgeom_gamma_stirling_term_bounds(slong * bound, const mag_t zinv, slong N) { mag_t b, u; slong n; mag_init(b); mag_init(u); /* bound[0] = WORD_MAX; -- should not be used */ /* first term 1/(12z) */ mag_set(b, zinv); mag_div_ui(b, b, 12); bound[1] = MAG_EXP(b); /* u = 1/(2 pi z)^2 */ mag_const_pi_lower(u); mag_mul_2exp_si(u, u, 1); mag_inv(u, u); mag_mul(u, u, zinv); mag_mul(u, u, u); /* zeta(2n) 2 (2n-2)! / (2pi)^(2n) / z^(2n-1) */ /* ratio bounded by (2n-2)(2n-3)/(2 pi z)^2 */ for (n = 2; n < N; n++) { mag_mul_ui(b, b, (2*n-2) * (2*n-3)); mag_mul(b, b, u); bound[n] = MAG_EXP(b); } mag_clear(b); mag_clear(u); } flint-3.1.3/src/arb_hypgeom/gamma_tab.c000066400000000000000000011701111461254215100177740ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" #if FLINT_BITS == 64 #define Z2(a,b) UWORD(0x ## b ## a) #else #define Z2(a,b) UWORD(0x ## a), UWORD(0x ## b) #endif #define Z8(a,b,c,d,e,f,g,h) Z2(a,b), Z2(c,d), Z2(e,f), Z2(g,h), arb_hypgeom_gamma_coeff_t arb_hypgeom_gamma_coeffs[ARB_HYPGEOM_GAMMA_TAB_NUM] = { {1, 0, 54, 0}, {0, 54, 54, 0}, {0, 108, 54, 1}, {-4, 162, 54, 1}, {-2, 216, 54, 0}, {-4, 270, 54, 1}, {-6, 324, 54, 1}, {-7, 378, 54, 0}, {-9, 432, 54, 1}, {-12, 486, 54, 1}, {-12, 540, 54, 0}, {-15, 594, 54, 1}, {-19, 648, 54, 1}, {-19, 702, 54, 0}, {-22, 756, 54, 1}, {-27, 810, 54, 0}, {-27, 864, 54, 0}, {-29, 918, 54, 1}, {-33, 972, 54, 0}, {-36, 1026, 54, 0}, {-37, 1080, 54, 1}, {-40, 1134, 54, 0}, {-45, 1188, 54, 1}, {-47, 1242, 54, 1}, {-49, 1296, 54, 0}, {-52, 1350, 53, 1}, {-59, 1403, 53, 0}, {-59, 1456, 53, 0}, {-61, 1509, 53, 1}, {-65, 1562, 53, 0}, {-72, 1615, 53, 0}, {-72, 1668, 53, 1}, {-74, 1721, 53, 0}, {-78, 1774, 53, 1}, {-85, 1827, 53, 1}, {-85, 1880, 53, 0}, {-88, 1933, 53, 1}, {-92, 1986, 53, 0}, {-99, 2039, 53, 0}, {-99, 2092, 52, 1}, {-102, 2144, 52, 0}, {-106, 2196, 52, 1}, {-116, 2248, 52, 0}, {-114, 2300, 52, 0}, {-117, 2352, 52, 1}, {-121, 2404, 52, 0}, {-127, 2456, 52, 1}, {-129, 2508, 52, 1}, {-132, 2560, 52, 0}, {-136, 2612, 52, 1}, {-141, 2664, 52, 0}, {-144, 2716, 52, 0}, {-147, 2768, 52, 1}, {-151, 2820, 51, 0}, {-156, 2871, 51, 1}, {-161, 2922, 51, 1}, {-163, 2973, 51, 0}, {-167, 3024, 51, 1}, {-171, 3075, 51, 0}, {-179, 3126, 51, 1}, {-179, 3177, 51, 1}, {-183, 3228, 51, 0}, {-187, 3279, 51, 1}, {-192, 3330, 51, 0}, {-197, 3381, 51, 0}, {-199, 3432, 51, 1}, {-203, 3483, 50, 0}, {-208, 3533, 50, 1}, {-217, 3583, 50, 1}, {-216, 3633, 50, 0}, {-220, 3683, 50, 1}, {-224, 3733, 50, 0}, {-230, 3783, 50, 1}, {-234, 3833, 50, 1}, {-237, 3883, 50, 0}, {-241, 3933, 50, 1}, {-246, 3983, 50, 0}, {-256, 4033, 49, 1}, {-255, 4082, 49, 1}, {-259, 4131, 49, 0}, {-263, 4180, 49, 1}, {-269, 4229, 49, 0}, {-274, 4278, 49, 0}, {-277, 4327, 49, 1}, {-281, 4376, 49, 0}, {-285, 4425, 49, 1}, {-292, 4474, 49, 0}, {-295, 4523, 49, 0}, {-299, 4572, 49, 1}, {-303, 4621, 49, 0}, {-308, 4670, 48, 1}, {-317, 4718, 48, 1}, {-317, 4766, 48, 0}, {-321, 4814, 48, 1}, {-326, 4862, 48, 0}, {-331, 4910, 48, 1}, {-337, 4958, 48, 1}, {-340, 5006, 48, 0}, {-344, 5054, 48, 1}, {-349, 5102, 48, 0}, {-355, 5150, 48, 1}, {-359, 5198, 47, 1}, {-363, 5245, 47, 0}, {-367, 5292, 47, 1}, {-372, 5339, 47, 0}, {-379, 5386, 47, 1}, {-382, 5433, 47, 1}, {-386, 5480, 47, 0}, {-391, 5527, 47, 1}, {-396, 5574, 47, 0}, {-405, 5621, 47, 1}, {-406, 5668, 47, 1}, {-410, 5715, 46, 0}, {-415, 5761, 46, 1}, {-420, 5807, 46, 0}, {-428, 5853, 46, 0}, {-429, 5899, 46, 1}, {-434, 5945, 46, 0}, {-439, 5991, 46, 1}, {-444, 6037, 46, 0}, {-451, 6083, 46, 0}, {-454, 6129, 46, 1}, {-458, 6175, 46, 0}, {-463, 6221, 45, 1}, {-469, 6266, 45, 0}, {-475, 6311, 45, 0}, {-478, 6356, 45, 1}, {-482, 6401, 45, 0}, {-488, 6446, 45, 1}, {-494, 6491, 45, 0}, {-500, 6536, 45, 0}, {-503, 6581, 45, 1}, {-507, 6626, 45, 0}, {-512, 6671, 45, 1}, {-518, 6716, 44, 0}, {-524, 6760, 44, 0}, {-527, 6804, 44, 1}, {-532, 6848, 44, 0}, {-537, 6892, 44, 1}, {-543, 6936, 44, 0}, {-549, 6980, 44, 0}, {-553, 7024, 44, 1}, {-557, 7068, 44, 0}, {-562, 7112, 44, 1}, {-569, 7156, 44, 0}, {-575, 7200, 43, 0}, {-578, 7243, 43, 1}, {-583, 7286, 43, 0}, {-588, 7329, 43, 1}, {-594, 7372, 43, 0}, {-601, 7415, 43, 0}, {-604, 7458, 43, 1}, {-608, 7501, 43, 0}, {-613, 7544, 43, 1}, {-619, 7587, 43, 0}, {-627, 7630, 42, 0}, {-629, 7672, 42, 1}, {-634, 7714, 42, 0}, {-639, 7756, 42, 1}, {-645, 7798, 42, 0}, {-656, 7840, 42, 0}, {-655, 7882, 42, 1}, {-660, 7924, 42, 0}, {-665, 7966, 42, 1}, {-671, 8008, 42, 0}, {-679, 8050, 41, 1}, {-682, 8091, 41, 1}, {-686, 8132, 41, 0}, {-691, 8173, 41, 1}, {-697, 8214, 41, 0}, {-704, 8255, 41, 1}, {-708, 8296, 41, 1}, {-713, 8337, 41, 0}, {-718, 8378, 41, 1}, {-723, 8419, 41, 0}, {-730, 8460, 41, 1}, {-735, 8501, 40, 1}, {-739, 8541, 40, 0}, {-744, 8581, 40, 1}, {-750, 8621, 40, 0}, {-756, 8661, 40, 1}, {-763, 8701, 40, 1}, {-766, 8741, 40, 0}, {-771, 8781, 40, 1}, {-776, 8821, 40, 0}, {-782, 8861, 40, 1}, {-791, 8901, 39, 1}, {-793, 8940, 39, 0}, {-798, 8979, 39, 1}, {-803, 9018, 39, 0}, {-809, 9057, 39, 1}, {-817, 9096, 39, 0}, {-820, 9135, 39, 0}, {-825, 9174, 39, 1}, {-830, 9213, 39, 0}, {-836, 9252, 39, 1}, {-843, 9291, 38, 0}, {-848, 9329, 38, 0}, {-852, 9367, 38, 1}, {-857, 9405, 38, 0}, {-863, 9443, 38, 1}, {-869, 9481, 38, 0}, {-876, 9519, 38, 0}, {-880, 9557, 38, 1}, {-885, 9595, 38, 0}, {-890, 9633, 38, 1}, {-896, 9671, 37, 0}, {-906, 9708, 37, 1}, {-908, 9745, 37, 1}, {-912, 9782, 37, 0}, {-918, 9819, 37, 1}, {-924, 9856, 37, 0}, {-931, 9893, 37, 1}, {-936, 9930, 37, 1}, {-940, 9967, 37, 0}, {-945, 10004, 37, 1}, {-951, 10041, 36, 0}, {-958, 10077, 36, 1}, {-965, 10113, 36, 1}, {-968, 10149, 36, 0}, {-973, 10185, 36, 1}, {-979, 10221, 36, 0}, {-985, 10257, 36, 1}, {-994, 10293, 36, 0}, {-997, 10329, 36, 0}, {-1001, 10365, 35, 1}, {-1007, 10400, 35, 0}, {-1013, 10435, 35, 1}, {-1020, 10470, 35, 0}, {-1025, 10505, 35, 0}, {-1030, 10540, 35, 1}, {-1035, 10575, 35, 0}, {-1041, 10610, 35, 1}, {-1047, 10645, 35, 0}, {-1056, 10680, 34, 0}, {-1058, 10714, 34, 1}, {-1063, 10748, 34, 0}, {-1069, 10782, 34, 1}, {-1075, 10816, 34, 0}, {-1082, 10850, 34, 1}, {-1087, 10884, 34, 1}, {-1092, 10918, 34, 0}, {-1097, 10952, 34, 1}, {-1103, 10986, 34, 0}, {-1110, 11020, 33, 1}, {-1117, 11053, 33, 1}, {-1121, 11086, 33, 0}, {-1126, 11119, 33, 1}, {-1131, 11152, 33, 0}, {-1138, 11185, 33, 1}, {-1145, 11218, 33, 0}, {-1150, 11251, 33, 0}, {-1155, 11284, 33, 1}, {-1160, 11317, 33, 0}, {-1166, 11350, 32, 1}, {-1173, 11382, 32, 0}, {-1180, 11414, 32, 0}, {-1184, 11446, 32, 1}, {-1189, 11478, 32, 0}, {-1195, 11510, 32, 1}, {-1201, 11542, 32, 0}, {-1209, 11574, 32, 1}, {-1213, 11606, 32, 1}, {-1218, 11638, 32, 0}, {-1223, 11670, 31, 1}, {-1230, 11701, 31, 0}, {-1236, 11732, 31, 1}, {-1244, 11763, 31, 1}, {-1247, 11794, 31, 0}, {-1253, 11825, 31, 1}, {-1258, 11856, 31, 0}, {-1265, 11887, 31, 1}, {-1273, 11918, 31, 0}, {-1277, 11949, 30, 0}, {-1282, 11979, 30, 1}, {-1288, 12009, 30, 0}, {-1294, 12039, 30, 1}, {-1300, 12069, 30, 0}, {-1309, 12099, 30, 0}, {-1312, 12129, 30, 1}, {-1317, 12159, 30, 0}, {-1323, 12189, 30, 1}, {-1329, 12219, 29, 0}, {-1337, 12248, 29, 1}, {-1342, 12277, 29, 1}, {-1347, 12306, 29, 0}, {-1352, 12335, 29, 1}, {-1358, 12364, 29, 0}, {-1365, 12393, 29, 1}, {-1378, 12422, 29, 1}, {-1377, 12451, 29, 0}, {-1382, 12480, 29, 1}, {-1388, 12509, 28, 0}, {-1394, 12537, 28, 1}, {-1401, 12565, 28, 0}, {-1407, 12593, 28, 0}, {-1412, 12621, 28, 1}, {-1417, 12649, 28, 0}, {-1423, 12677, 28, 1}, {-1430, 12705, 28, 0}, {-1438, 12733, 27, 1}, {-1442, 12760, 27, 1}, {-1447, 12787, 27, 0}, {-1453, 12814, 27, 1}, {-1459, 12841, 27, 0}, {-1466, 12868, 27, 1}, {-1474, 12895, 27, 1}, {-1477, 12922, 27, 0}, {-1483, 12949, 27, 1}, {-1489, 12976, 27, 0}, {-1495, 13003, 26, 1}, {-1503, 13029, 26, 0}, {-1508, 13055, 26, 0}, {-1513, 13081, 26, 1}, {-1519, 13107, 26, 0}, {-1525, 13133, 26, 1}, {-1531, 13159, 26, 0}, {-1541, 13185, 26, 1}, {-1544, 13211, 26, 1}, {-1549, 13237, 25, 0}, {-1555, 13262, 25, 1}, {-1561, 13287, 25, 0}, {-1568, 13312, 25, 1}, {-1576, 13337, 25, 1}, {-1580, 13362, 25, 0}, {-1585, 13387, 25, 1}, {-1591, 13412, 25, 0}, {-1598, 13437, 25, 1}, {-1605, 13462, 24, 0}, {-1611, 13486, 24, 0}, {-1616, 13510, 24, 1}, {-1621, 13534, 24, 0}, {-1628, 13558, 24, 1}, {-1634, 13582, 24, 0}, {-1643, 13606, 24, 1}, {-1647, 13630, 24, 1}, {-1652, 13654, 24, 0}, {-1658, 13678, 23, 1}, {-1664, 13701, 23, 0}, {-1671, 13724, 23, 1}, {-1680, 13747, 23, 1}, {-1683, 13770, 23, 0}, {-1688, 13793, 23, 1}, {-1694, 13816, 23, 0}, {-1701, 13839, 23, 1}, {-1708, 13862, 23, 0}, {-1715, 13885, 22, 0}, {-1719, 13907, 22, 1}, {-1725, 13929, 22, 0}, {-1731, 13951, 22, 1}, {-1738, 13973, 22, 0}, {-1746, 13995, 22, 1}, {-1751, 14017, 22, 1}, {-1756, 14039, 22, 0}, {-1762, 14061, 22, 1}, {-1768, 14083, 21, 0}, {-1775, 14104, 21, 1}, {-1785, 14125, 21, 0}, {-1788, 14146, 21, 0}, {-1793, 14167, 21, 1}, {-1799, 14188, 21, 0}, {-1805, 14209, 21, 1}, {-1812, 14230, 21, 0}, {-1821, 14251, 21, 0}, {-1824, 14272, 20, 1}, {-1830, 14292, 20, 0}, {-1836, 14312, 20, 1}, {-1843, 14332, 20, 0}, {-1850, 14352, 20, 1}, {-1857, 14372, 20, 1}, {-1861, 14392, 20, 0}, {-1867, 14412, 20, 1}, {-1873, 14432, 20, 0}, {-1880, 14452, 19, 1}, {-1888, 14471, 19, 0}, {-1893, 14490, 19, 0}, {-1898, 14509, 19, 1}, {-1904, 14528, 19, 0}, {-1911, 14547, 19, 1}, {-1918, 14566, 19, 0}, {-1926, 14585, 19, 1}, {-1930, 14604, 19, 1}, {-1936, 14623, 18, 0}, {-1942, 14641, 18, 1}, {-1948, 14659, 18, 0}, {-1955, 14677, 18, 1}, {-1967, 14695, 18, 1}, {-1968, 14713, 18, 0}, {-1973, 14731, 18, 1}, {-1979, 14749, 18, 0}, {-1986, 14767, 18, 1}, {-1993, 14785, 17, 0}, {-2001, 14802, 17, 0}, {-2005, 14819, 17, 1}, {-2011, 14836, 17, 0}, {-2017, 14853, 17, 1}, {-2024, 14870, 17, 0}, {-2031, 14887, 17, 1}, {-2038, 14904, 17, 1}, {-2043, 14921, 16, 0}, {-2048, 14937, 16, 1}, {-2055, 14953, 16, 0}, {-2062, 14969, 16, 1}, {-2069, 14985, 16, 0}, {-2076, 15001, 16, 0}, {-2080, 15017, 16, 1}, {-2086, 15033, 16, 0}, {-2093, 15049, 16, 1}, {-2100, 15065, 15, 0}, {-2108, 15080, 15, 1}, {-2113, 15095, 15, 1}, {-2118, 15110, 15, 0}, {-2124, 15125, 15, 1}, {-2131, 15140, 15, 0}, {-2138, 15155, 15, 1}, {-2147, 15170, 15, 0}, {-2151, 15185, 15, 0}, {-2156, 15200, 14, 1}, {-2162, 15214, 14, 0}, {-2169, 15228, 14, 1}, {-2176, 15242, 14, 0}, {-2186, 15256, 14, 1}, {-2189, 15270, 14, 1}, {-2194, 15284, 14, 0}, {-2201, 15298, 14, 1}, {-2207, 15312, 14, 0}, {-2214, 15326, 13, 1}, {-2225, 15339, 13, 1}, {-2227, 15352, 13, 0}, {-2233, 15365, 13, 1}, {-2239, 15378, 13, 0}, {-2245, 15391, 13, 1}, {-2253, 15404, 13, 0}, {-2262, 15417, 13, 0}, {-2265, 15430, 12, 1}, {-2271, 15442, 12, 0}, {-2277, 15454, 12, 1}, {-2284, 15466, 12, 0}, {-2291, 15478, 12, 1}, {-2300, 15490, 12, 1}, {-2304, 15502, 12, 0}, {-2309, 15514, 12, 1}, {-2316, 15526, 12, 0}, {-2322, 15538, 11, 1}, {-2330, 15549, 11, 0}, {-2338, 15560, 11, 0}, {-2342, 15571, 11, 1}, {-2348, 15582, 11, 0}, {-2354, 15593, 11, 1}, {-2361, 15604, 11, 0}, {-2369, 15615, 11, 1}, {-2376, 15626, 10, 1}, {-2381, 15636, 10, 0}, {-2387, 15646, 10, 1}, {-2393, 15656, 10, 0}, {-2400, 15666, 10, 1}, {-2408, 15676, 10, 0}, {-2415, 15686, 10, 0}, {-2419, 15696, 10, 1}, {-2425, 15706, 10, 0}, {-2432, 15716, 9, 1}, {-2439, 15725, 9, 0}, {-2447, 15734, 9, 1}, {-2453, 15743, 9, 1}, {-2458, 15752, 9, 0}, {-2464, 15761, 9, 1}, {-2471, 15770, 9, 0}, {-2478, 15779, 9, 1}, {-2486, 15788, 8, 0}, {-2492, 15796, 8, 0}, {-2497, 15804, 8, 1}, {-2503, 15812, 8, 0}, {-2510, 15820, 8, 1}, {-2517, 15828, 8, 0}, {-2525, 15836, 8, 1}, {-2531, 15844, 8, 1}, {-2536, 15852, 8, 0}, {-2542, 15860, 7, 1}, {-2549, 15867, 7, 0}, {-2556, 15874, 7, 1}, {-2564, 15881, 7, 0}, {-2570, 15888, 7, 0}, {-2575, 15895, 7, 1}, {-2581, 15902, 7, 0}, {-2588, 15909, 7, 1}, {-2595, 15916, 7, 0}, {-2603, 15923, 6, 1}, {-2609, 15929, 6, 1}, {-2614, 15935, 6, 0}, {-2621, 15941, 6, 1}, {-2627, 15947, 6, 0}, {-2634, 15953, 6, 1}, {-2642, 15959, 6, 0}, {-2649, 15965, 6, 0}, {-2654, 15971, 5, 1}, {-2660, 15976, 5, 0}, {-2667, 15981, 5, 1}, {-2674, 15986, 5, 0}, {-2682, 15991, 5, 1}, {-2688, 15996, 5, 1}, {-2693, 16001, 5, 0}, {-2699, 16006, 5, 1}, {-2706, 16011, 5, 0}, {-2713, 16016, 4, 1}, {-2721, 16020, 4, 0}, {-2728, 16024, 4, 0}, {-2733, 16028, 4, 1}, {-2739, 16032, 4, 0}, {-2745, 16036, 4, 1}, {-2752, 16040, 4, 0}, {-2761, 16044, 4, 1}, {-2767, 16048, 3, 1}, {-2772, 16051, 3, 0}, {-2778, 16054, 3, 1}, {-2785, 16057, 3, 0}, {-2792, 16060, 3, 1}, {-2800, 16063, 3, 0}, {-2807, 16066, 3, 0}, {-2812, 16069, 3, 1}, {-2818, 16072, 3, 0}, {-2825, 16075, 2, 1}, {-2832, 16077, 2, 0}, {-2840, 16079, 2, 1}, {-2847, 16081, 2, 1}, {-2852, 16083, 2, 0}, {-2858, 16085, 2, 1}, {-2865, 16087, 2, 0}, {-2872, 16089, 2, 1}, {-2879, 16091, 1, 0}, {-2887, 16092, 1, 0}, {-2892, 16093, 1, 1}, {-2898, 16094, 1, 0}, {-2904, 16095, 1, 1}, {-2911, 16096, 1, 0}, {-2919, 16097, 1, 1}, {-2927, 16098, 1, 1}, }; const mp_limb_t arb_hypgeom_gamma_tab_limbs[] = { Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000) Z8(00000000,00000000,00000000,80000000,d44c6937,0c3f5be7,e0421838,31072b10) Z8(e1f3a067,f17903f4,7ec1b6d0,98bb22aa,ba5f3a57,9ad030aa,d8036214,1b32e5e8) Z8(512b3051,81ccae83,a8427633,81b5753e,2bce15a3,542e9f72,5a2b38e6,92bf5222) Z8(439cd03a,81c1a48e,b6612b78,1baf84db,37fb2817,e9cc3d17,5ad1f5c7,818bd307) Z8(fea32a67,4068bbca,c26e5421,b7a661e5,f5389130,7f18b93e,17fcc003,d0d62342) Z8(69ddf172,9f9c7ccc,9215f371,6223b2f0,b05e5b25,e528fdf1,6fe9554e,aea1c4bb) Z8(7031f9c0,af289048,744db679,c5d238d0,4f1b66c2,e11df242,d2238d8c,7c555302) Z8(13edf604,4c4d8c4f,5c40bf30,8e704b7c,65f004cc,2741e538,ee52e018,7db2db49) Z8(448f2a05,32fab2c7,d3ee591c,c083f22a,c9b31959,6fcaabcc,64b83989,03655949) Z8(31ced822,5a7bd469,e741e5d8,7cfde60e,e80567a4,8fc28658,63e6d09f,b54fe70e) Z8(ce3bea5d,961542a3,bd61c746,5e6ac2f0,82797722,3ec7c271,e62ff864,d2a1ea1d) Z8(b6b7b86f,0c09d4c8,7899aaae,8a96d156,154b36cf,dbe7bf38,cc86d733,58deb878) Z8(d74bafea,e43b4673,32135a08,1056ae91,621057d1,d0649ccb,03a9f0ee,8e4b59fa) Z8(709affbd,0c03df34,f65cc019,a1cecc3a,0152cb56,d1be3f81,7db0c7a4,93c467e3) Z8(8f1877ab,5c379a00,f9580af6,76b55cc4,f35f61ce,ef1c2900,294dca79,6885062b) Z8(021a094b,4756ca11,1a11d46e,04920c54,b41a7dfc,f0288d8a,2f09194b,14f2cd2a) Z8(83d8d9cf,690c95ad,8781a84d,cdb6fa0a,2302cf3a,c58aee6e,977add8d,db3059f0) Z8(19f9bd13,806423c3,8fbff045,2cffd33a,4ba3c3ef,1588a81e,182a865c,d4bad52a) Z8(6ff3e41b,59c80c6a,2359b8a7,55df6b32,5cf9734f,1388b48e,81ad3ffe,456e5d05) Z8(3956f4b4,698ca360,ad128bca,12c4585a,f72f5b25,8c2a1b45,5ec1b718,f1e5778b) Z8(af21a29d,a63ad266,e1674d69,1a937aac,7e92b6d0,a3b7721f,96f573ad,03525173) Z8(8002e7d8,6595d953,83a8e1e0,862a96a3,d8b597b8,9a1f90dd,0ade1e9e,09791289) Z8(812e6230,c51d77bb,135f63b9,725da3a8,5f42c8eb,803422ee,31d4b4c0,eb323ed6) Z8(dd941d01,4e335234,3f65391b,fa7cabd2,42fed427,e6f2cd93,08f7e03d,94ef0edb) Z8(d8eedaf9,30bc3e04,ba7acbaf,1af586d0,4a1e52bc,2d89f1e9,8f1a86ec,645ef92e) Z8(9ec407ed,d25818cf,c7473287,86f93595,edf114df,ec1ee8cf,e44ad789,5977a634) Z8(232bf00f,e15a6cbb,96dcd8c5,1e0a48ef,bcff260a,2d816c1d,d08fb45c,8ed05db9) Z8(bd611d64,c24856f3,57d16e75,a7e7a013,565580c5,909e6e1e,365bca4b,b95e7dbc) Z8(309115e1,856dde8e,a83da736,2d6cac75,714edf38,a1f3ff04,593c3b9e,791e06e8) Z8(859911dc,b7579e07,67a6c86d,233427d7,ff625deb,d2b87c32,faf32c0a,a18aec7a) Z8(3e7bcea8,3b920d0d,582e38c2,38594742,a4605c64,a6f5d49f,f60c0df7,1d8b96ba) Z8(532bac68,38bd9b08,94205465,c3478ad6,dae2519e,291e5de3,aff8e561,1b69edae) Z8(f78ca6c9,4786c982,bc0da507,930256fa,97fa264c,9325e453,f8be9c9f,d8913717) Z8(a3a4b94c,d424bb8f,84f82135,c56fc7e4,7b86b03e,8b11fcbe,9702df3c,d03a085a) Z8(22044511,fdbd1f91,1ce99bcb,be7783f9,38bb5e92,3e247510,8a82e06b,9e1f9306) Z8(30f90470,3378bb76,35174f52,00c4393a,4ebf5695,ac34dcbc,ae33cc14,3d794b9c) Z8(988a127b,8cb9a696,af813a36,4322ca0f,b6e6b7b9,e0bb7ea2,8c603663,9bf2daee) Z8(310e33ac,e5c9ce60,a293a76d,7c1e561f,9abff0db,2731a5a6,b829d246,047b6a05) Z8(043eb9c3,2273f947,21208155,b8d50305,f4b4d62a,6cda2bea,0e94d288,b1361145) Z8(69abc0cb,a9824b0e,d0377dba,09547d0d,3f0060e4,f8d3efe8,359777d7,89b4393c) Z8(b5a0bec2,dfc931dc,a9b55a20,1403ab71,9c84b042,a15a643c,13823e47,ac0af47d) Z8(e0642cde,1869cecf,717ccc7a,91b4eb03,fffd9154,834f5d81,36be40ce,9aa37f25) Z8(f86f8a67,51e24cc0,b60a3f15,f720b040,d82353fc,14d339de,e83d8700,51552cdc) Z8(fbe2f86c,e380d534,95cbba62,361a1523,e62be0f9,02053756,ce7a1475,f20dbdc1) Z8(9f32751d,ddfa310c,929b5b2e,1c97d15d,333ab386,b0bc2711,ef122799,5eecdc56) Z8(0b8c42d1,110ca5b6,6cfcda46,ca5f2ce8,862ee895,7cd9ea63,6de4bd45,73cd0446) Z8(0ff62ff2,ceb489b1,5ea0e2ec,0a84dfee,6c130226,5b095b0b,d4d5a198,33c4871b) Z8(4ad6da3d,7068516d,2c180a0a,d7f0a18f,671d0d1e,c68c2d88,3c07662b,69c9fcf8) Z8(0d37c0d9,5b4e086a,6d0b0000,babd4fd4,b0739e11,0b509a61,8d03d499,fe63031c) Z8(a54f47a8,fc60f9da,0a15abc8,de1146eb,6717e210,104e1c9d,321fd882,93acc37a) Z8(94336c18,6e146396,a4f1c553,eb7594cb,4bb48380,9fbc4857,9a8f9528,4171ba3f) Z8(2dab48ff,40854a9b,b1f527b9,dab9a53b,282c86ba,860906ab,f7cac3bd,58b5e567) Z8(7e632403,79e8932e,b8e2545a,85c569c0,5c7e176b,0beb919b,1d1cf655,821fd014) Z8(bb6b0d86,503b89b8,001b7660,b73265f9,bb596b64,acd16f79,08740560,c0b5dd3d) Z8(1ef84da1,d37fb09a,a1fdf2ef,aa891905,feece581,98b763c2,ba5ca445,b3d64aa7) Z8(0fd4e2a5,0972a12f,6aac09d6,98e5ee2a,a3745a94,7ba78b40,bbecd2f6,bc7b7024) Z8(98be1ae1,2911d234,c2569eb3,f57d6799,0327f952,b82ae4c6,270d7a73,dd839ec7) Z8(5c7c94c1,ec6a5b11,e817cf1b,020e7db2,904463b3,3a8fcebf,a3773246,e4d656c0) Z8(e7049c56,0020189c,8a673965,5b9323ab,558e48eb,d72712c7,3dc0f6fd,6cbffcd5) Z8(b079cd5b,6cb536d1,092176be,11092edd,13678662,aacf3c36,a2b1bed6,420070ce) Z8(3754b9ab,cd6a6ef1,b9738d6e,f26d4c47,529b13f4,90e40980,5bb6b5ce,9023077e) Z8(15aef90f,3955943c,e76d045a,ae63c7f2,400c9a60,51a613da,0add4e25,c2b42db0) Z8(6dadaf3e,be977b61,9f5049ba,1ea4af96,789d0620,df9c4243,425a08ac,c110359c) Z8(ad0b16d5,39e5a5c9,4831dbf4,cb823de9,ec66c0cf,d356669c,787e18d7,1769cf66) Z8(e683edc7,de95560a,987e12bd,0aac72ab,063c8c94,85de1f4f,ad06066c,35eef6d5) Z8(bbfcad39,42075aeb,de6827de,8d795ba8,6c1a14ff,ca0c1834,9297ffe5,fec1c959) Z8(3ac35dcc,eb9ec7d8,fd9a3f9f,78f4f977,9310b40b,a5d22363,18040b7f,2968ad39) Z8(5b6a43ee,e04c83b2,10646d87,b1fd891b,8caca42e,1b404838,1a0493df,acd7881e) Z8(3e6f60ed,3bb7330c,e901cb17,d36142cf,0d2ea48b,6ab5ee30,ae785c4f,73b0fcd0) Z8(90ae8a01,c7c0b55f,c28b572f,c1858400,6a0fab0e,2839fbfa,216fdab8,07db2b53) Z8(e5b926e1,6dc36d7f,b9ee08ec,2611dd53,963d2452,6cdb1158,27c7af28,0875bca6) Z8(984ff2af,604dbba7,4a820dd7,d3aa0f13,dd72e299,a9f9f273,bf8d1eca,dcf91bf8) Z8(23b2824e,0e31bd46,d247fb0b,09169797,3b285547,abc74ef1,cdd6da23,58297ccb) Z8(8d5ded39,a688b400,d60bce25,b55eff49,c50060ca,f6771ed6,32c5d186,12db0465) Z8(ccd08fac,7b79d989,5e78c1a6,d2a6d559,6419d6d1,d4e1026f,b0cab006,dc4c7db5) Z8(63f4b360,5e9b3db1,124a4299,bfe4e9a0,98103075,182268bc,0d16c2e5,8bcc2984) Z8(3e8191b3,aaf37c4d,ad12bc60,88079562,cdcfdc07,fd313971,338f9c96,4112a3ed) Z8(bc61a309,61d3c3e8,58d23a00,5807a6f1,9ba8bd61,b3c3d210,b68a49d8,b2185343) Z8(5e2c9a26,62d81332,c96257e3,60b9e78a,5e6d3f05,780df480,a8ba60d6,148d3612) Z8(8f195d8a,994cc75d,03bddb2e,32eda7b9,60b65fd3,bda99c32,fc5f362b,b868103d) Z8(bc7158db,48be4222,042e74d6,a225b4d6,b3af63d8,90e7687f,afb99a05,1f3ac55f) Z8(73539adc,b79e8182,41f10a71,9da57942,8c2e8516,49af9cff,3a6d761f,cf7beb09) Z8(5132eb17,e8f45072,de062054,51a7841f,1370dfc1,bd0ef793,5b837f7d,c508f8ec) Z8(a97d388d,2259ed32,6f1f7776,e0f7232a,2ecc9dec,7e1e9375,9717da37,33b4c61f) Z8(29f483b3,84cf5384,97a76481,17431cd3,533f7e0c,3f577698,fb727c05,60382a7b) Z8(50344115,d7316c03,2d83b31b,2e62fcba,1b8b106b,519d508d,11a47c48,5169ce92) Z8(29382723,260d6507,c20fbdf5,e33a3000,95e4b3c0,5817a304,892c9f22,9fda369d) Z8(1ffcb718,41be5a02,230a86e7,bfe7828e,7af6b3e0,f043722a,4783486e,2a0f82da) Z8(2db4313a,334bc6ee,e57d1f29,861653da,088e4428,bd150f74,1c88bbbc,9467ac30) Z8(d9b5f686,d7eb3477,1e55669e,ac5a7da4,624a73c9,e356003b,9f781f5d,cade496c) Z8(12bfa4af,9492ba7d,4dc1bb27,ebe4445e,2663befe,95e55fec,cae4902a,c7e28bbd) Z8(8b7250c1,00646f4a,77fcc751,5ebb615b,b2c655fe,689bca3f,59ca5dbd,0a3cd2b2) Z8(5e5d4ab0,f31d843f,aff5c48d,77a9699c,19e0eff1,a0f5a34f,3c6938e6,e01f5da7) Z8(88a2107a,034c5609,758c244d,bf277bce,e74ad959,5c0111c2,8f991ede,ac0cd025) Z8(e44cfe84,743ebcef,01f16923,6807e2e3,dc1e1318,d1d69dd3,fb058cad,ec8ce293) Z8(824cff8a,e3f1815f,ef92e17e,9d460c8a,a5441529,de0690f4,a2ea416d,820db6ac) Z8(561901f5,2fbc5992,c291526d,ffe3e781,04b745ec,37a21341,31ce6e2c,5887dd80) Z8(1b923790,1b9ec225,ce794fcf,393e1e10,1bfd4673,f7b73eea,c6b54e79,090de562) Z8(619958da,9fa99c16,a36b3064,758a34f6,2fa22d00,27df471c,1ccca829,f900de36) Z8(0a5dacd0,5a5ed6b7,c86f1ef8,c5e96904,f077ae83,76759f33,3b51736b,c19b532b) Z8(2288f908,2836525c,c96c7f91,c51c84a9,759f02dc,307f8cb3,6a651062,376d5a4f) Z8(69445ee6,b2aca171,77579525,e8fbe8aa,6567136b,457f0c30,9521426f,bf2961c8) Z8(3420b417,9229d3b8,3a0c5db6,783d7d76,74f987d7,7d22bf66,1147ef5f,80d1a5f1) Z8(bd8d2d69,8ed8f88f,132a0ffa,cf82f086,f9d2d4a7,e2c315b7,c27737fe,922d095b) Z8(177d8efa,2ac3ae70,a919ddb7,22a3efdb,601bb55d,95b5a93d,276b2be7,74ab206b) Z8(700db34d,ab76a034,043444a2,78a261df,9c6a0695,010f2cfc,234a2f61,cc5f0a26) Z8(3d2d949a,0063b274,7fc901f4,0b1d8ab6,3464aa67,65ecd4d1,2dd22196,3577bc51) Z8(17911e3c,f81b118e,81ddf8e3,cba8cd28,05b73bde,613a4285,9bfe7718,eac597f7) Z8(88e959c6,6edba835,1d153de9,98b88967,ba98774a,875f1318,9c6bf8b9,8a411b3a) Z8(386c1c19,ee237372,a2804472,0a3bc950,6ae598ca,c07f1177,dff9e1bf,7f5789c8) Z8(8b9989d9,6bea06c9,852aa3ce,14bb28ca,090682cd,f1679b5a,1d0ed549,8297c3e6) Z8(b3035811,1666f2d2,2b44d2ef,5616461e,eecfb86d,0760e0ed,4ca94bba,4913452f) Z8(73ecf00c,8b1e7224,06ccbb31,632b5b81,4f31a7bb,982505ae,381c25dd,9d8de329) Z8(514b33ec,6ea2a87f,010d9244,1f1e8f49,87b44cb8,1f35d5eb,e0362bac,b4786abf) Z8(0c8040b3,e80c449d,d4708327,57de11f9,258652e9,138817ad,b56dea4d,2e1ef1e2) Z8(6ce9b487,05b86ca9,39c2f841,dd5e1d18,fede1321,c9bfdf75,d8418eb7,082cd32b) Z8(6e5060e8,a2306f73,288c9835,4cd9f820,be636232,c19e2458,70661cc3,c904f3c2) Z8(029a9a0e,48cb8fc1,c24e7114,d57fc6a8,93b97c7f,f5570290,5e1c0abf,692ef2c6) Z8(773383e8,8583904c,975c80ef,97806c4f,0ae5e341,ce231541,a03cc804,78cf3b15) Z8(9687782a,51fec398,53bbc32f,5b54b2f8,a65b4201,b4463e2b,d2fd2a7b,ac1fb2ee) Z8(963e8b55,18fac703,3752d7aa,4acf480b,b2f5710d,71387366,3c303f3f,d18da812) Z8(c8ed8f57,bef3be7f,879d0688,6b46c976,8691b6ed,7c04703c,8ab1e74c,e1b27f37) Z8(71904391,ca30d70d,3dec9233,08643fc4,01b9a90f,2fab53f3,707e8941,b50a13de) Z8(aeb7c641,7f9498aa,d4cfb64e,422ef7fb,633ca9a8,cdc4b472,2496b512,8240985b) Z8(e8141cb8,c43fd3e0,ccf64e0c,8a34b11d,a9c12594,9dbb2baf,55c526b6,31348935) Z8(be4b8ecb,80eb7ec4,8b4c1f4c,484e9a70,48a53726,91f27187,fb74b71b,bffa0717) Z8(ae8ba841,adb71820,0ab1be1a,096182ea,67801cf3,1fe10129,b94933da,17cf4a23) Z8(52344e75,e1185265,4170bcfb,5cb3ea32,b274138a,dbdc048b,840b9be0,ca168459) Z8(2e80d8c8,b81f3f00,3b28de86,2ff2b406,887be281,b39d68cc,703e46f2,3b074329) Z8(8fe359ae,210b80ee,649154db,53824836,37fb02b9,4b4da73e,36883c2e,04610819) Z8(ee06b9d8,cdcf9547,a7b240ed,85e48d48,2c9089bc,cafcaf7e,babbc550,853a2b46) Z8(a79a10a7,81161907,3501846b,e0740aba,f47b540a,6ff1ac62,62177184,4f38190c) Z8(e7669481,122c4170,21fe9a28,673e3a30,26f506b4,eb519c43,6d3b6cc0,3703e87e) Z8(9aa57986,50548ae0,9a1b822b,a1046ef8,dac9c8ae,190a1b13,9eeb9e4e,580d16fa) Z8(accbfae6,fd07d290,c1c2fe74,16a22d6c,552dc83b,0814ad95,27b1abb2,a4b18b2b) Z8(cdb927f8,d83432fa,cfce8d3c,86453c66,417db143,c8e968fa,4acc61a2,da2c6db7) Z8(d1acbaaa,f4b569cd,f4276425,4a3dc2d3,58fdcc4d,4b951b14,4798f56d,51ac9e88) Z8(ee452e6b,e563f90e,77f58fb3,0d485708,033201e5,a5422c79,8574fb5a,dbb86fb3) Z8(d90a5716,6a72590c,9e9d9649,e62152b8,8b6a6b0d,ffe7525f,1dc2ae11,93618386) Z8(c3665344,b58aa6c6,53452496,04085f2d,41fb800a,c2399a66,60bd1d29,8513293e) Z8(28bf7140,fb024a7d,8ffcc437,bc8d6296,a2dc0a23,87874e30,2865b7ce,a80a7c8a) Z8(018b5b16,7f742b36,d9174f75,4e392763,8b3a1edd,fb46a158,14dedff6,0d2b8cef) Z8(b8f343cf,dc75df89,1fd2365c,98f25a77,a3653233,ea13eb11,e3689ee5,81cefe21) Z8(402445a8,6a36a885,1a4fd92f,dec1073b,131223b1,7f5353a4,862fe775,5650e6c9) Z8(35b2c2c8,3e598b22,68d71601,0c4f62f9,14944a93,d61a9765,8d10ac4b,2df4519c) Z8(9cf023be,37115c61,51859791,12690855,df8e5902,4add3e25,e0991538,322aba35) Z8(59e4bf5a,f2c4bf07,f7269612,bc633b57,ce3d177a,a31e9613,ba4d4691,2c90c164) Z8(b7ed9d5b,f452f8cf,2f6de019,eb27e870,37f0c3ed,80e8eefa,5c160015,2c1bc14d) Z8(9fb44b73,ddbbda77,8468170a,a78edf4e,34b827da,92173afe,3f55efed,a8e7457a) Z8(d6c7453a,31724824,f6cd81c1,64c046d1,26b99c14,cf3d900f,80bb424a,74472a60) Z8(a0ec0dbf,d932ee71,c34c44c5,a5648343,2d4cde24,a036ddf2,bd64d46d,ad1485c0) Z8(979cfe09,5dbef230,3674f69c,9c04754c,021306de,59e38f14,65a6caef,1fb9ec0e) Z8(99ee65de,96f8c46f,ae4b994b,0053aaeb,17593b83,3cc24c67,fe54e8fe,0ef07c5e) Z8(d85c28ca,7bb4c14f,40b8f013,4adf0cdc,2e1a3420,c8034e32,e193ee3f,95fbda7e) Z8(a2131cae,abfd1059,e645550a,58cec677,80e88d62,d610483c,da790950,08cdba6b) Z8(45a70085,b7c5cdeb,32d258a2,474c4555,c1fb8f03,468cbf8c,92adceb3,1b22809c) Z8(a1cb3de8,567bf625,74d93b0e,79de52d9,2f9c9c45,262cef5a,6197f010,825906e9) Z8(5af9aec1,bcd99b48,97118482,93e09059,4553d04b,b521706f,c174e809,65af81c6) Z8(3946a98e,94675d45,ccb143f8,cc2c969c,553fb20e,f6c19fb6,d633f4f7,402c4653) Z8(acb42b76,9e8ef8c9,10dc994d,a461b151,aaf44049,016c6405,23f8d36a,91d11b0b) Z8(177dddb7,07a086ee,4e90cac0,31d61bbf,a198fe81,db06fb79,7de6ae26,2ccfdec2) Z8(93b48254,a4882e9b,18dc91cc,58912581,06503f14,3caa142f,8c3903ca,87cf94f9) Z8(dc7ccb6c,776ab160,1a7dd901,a7d6a0fe,7b0668e5,883f3dd8,ea1c7b18,6715bf65) Z8(21456aab,3339d49a,70055fa7,32db82bd,9509b69b,65ce2a6f,5b1930ef,e426137f) Z8(67fdedd2,b1e9e4b9,7551caa4,9b33ef04,54267c98,042c6ca5,db5aa9d9,9c38599c) Z8(974b7017,58003677,9ee00b81,c978c57c,4c530300,1f9b560e,df0e4b3f,cff707cd) Z8(0bc2656f,bc23f982,a74f12aa,849aac59,c45287b7,80a580ed,c94b12b1,e843a996) Z8(530a6887,3029bdbc,53fb1e2d,1633a4d8,919f7c6d,bc153c72,9c4adabc,6102e7aa) Z8(35e6dd8b,d459f2b5,e9e8def8,6ac8599e,15bff119,e196b789,a8115e0c,58d26680) Z8(501717f4,f148bf97,f0b2ee7e,d0419128,924abf62,06b98490,c1677e10,dc0b7352) Z8(e818c113,23455571,f62e1479,70ec1c15,de72dede,b82dc5f0,ceecf3a1,e9b26631) Z8(60cbc58d,3afa494b,f85e2f7f,fcb4fd5b,08b62d40,7669dd3f,dd4abdab,0bababcc) Z8(4cefd2f0,ef33c8c6,d7d3be3c,362b4fe7,bc56e6d2,d37c63a3,41cad63e,d66c55b0) Z8(2862ac4f,11982f5a,f20f014d,da7bba60,b2206dbb,1ca8d84b,fe2e2dd1,67776002) Z8(ca270e4f,cec415a9,4636d5bc,385c3f9f,04ab7b60,02e423ee,7675749e,f8cfa777) Z8(38ba5e2d,4fe8b9f0,089cf725,72d97c3e,4e64f0b8,f6ffcb7e,e06f1640,981284ed) Z8(2a545858,e3cfa2aa,4b087f06,5a0510b5,a2dca245,0c9d6ee9,3ffbbd91,ffe2a1b1) Z8(8b3ae0e9,53b7fdfb,86183f63,b14a642d,2a369ab4,0e50b3ec,2415000b,4a20abae) Z8(674a4cb0,1df9e334,ab3d1e52,1b6799ad,09010604,3f271889,59b1ba9c,5fe6bcd2) Z8(a27f64d9,6f10d68f,09a53e53,62a051a5,27d0d7a7,696313e6,fc92fa5c,9073b402) Z8(1661d23c,703b7465,ba6a85bf,9a2ce73b,4f107f69,fe60e39b,6c557d40,aef1e5fc) Z8(84c25fa4,3c47d9ef,c4d2aeee,dad6c61f,a268b689,420f7029,37489a25,4e121ed4) Z8(3b234dde,7044587d,782a3162,2e2fcb01,592ddc10,f3e81a10,41c115f2,5579186b) Z8(e5a8f47b,849fa3ef,855f1fd1,f1bac200,5e343dff,2e2cfcdd,78a07c65,a621484f) Z8(7eb9cdf2,e518f6b1,8997e991,d9400b97,ebfd5f50,9486f827,5c379f79,321aace2) Z8(838f0ede,a81c65ed,79a8db09,ba62c507,04664879,af8b0f1b,850e54ce,37a2f13f) Z8(aa48df62,81295f39,ebae09a8,4e952a58,220a67f5,a0c2c0a0,274ba938,bc88fb06) Z8(8d09c8b4,e2d161af,bc464f11,fbf41bea,e9d636d4,bc9d598d,3966d13e,f101a4f1) Z8(4fa2bf1a,0d5c5a9d,2dec2065,6a9ed9e4,6f4f606f,3a10a560,49bcd39b,9375b64f) Z8(e809707c,9722ef2c,6112e8e8,dccc3333,b8ad8128,5562275e,e38df4ec,4c01473f) Z8(071045f3,3554d086,b574e03d,3dcb7c41,a2e64dac,94add171,68ff330e,bd020296) Z8(96d876bb,15a8f054,63a89867,9407cd41,b2b9003c,14042357,8f229ffd,97669e30) Z8(d4198f64,16f3982a,86d73878,f22f00e4,d039682a,9226c81d,01237758,82732822) Z8(3e469d18,a83fe6b8,bfb68386,1146d412,3a03a104,17f69581,5c1d7f2f,acc6a152) Z8(c047dc32,16e9ae91,e87a7325,66547d69,1b75e157,8e2e9934,43e3d3ec,1ed389f3) Z8(d5247431,4329ba83,04716c3f,192f2d4c,69eef066,a9b45d84,3d480095,573e9ee0) Z8(2e166f31,370e6f8d,3135f416,eca10709,aa412112,9ab920c9,71cfc7d5,2ac723eb) Z8(29fe827f,3a867440,3b8c4d76,d3fbcaf9,ee930bb1,3c6a2051,eeeae4d1,3df76f22) Z8(724e00fc,00a9d8de,2dbe8921,ebe5189e,0957e03b,6c4f34ce,0f3b7e37,28a7d4c7) Z8(6ec9a92e,d28fee8e,9ed145ea,c52d8614,7718c012,74104ed1,f5670614,0fbafea6) Z8(f23a8236,d6d715d1,36777389,c1b2d26d,c851fe2c,db9c753c,b947c9f1,b5b1fcdc) Z8(d3cbec78,a1742a3d,e097c05b,9f61f15e,0c9d32f9,746877b8,8172fec4,d5503879) Z8(7d5b2cb5,aeec3bd6,65b6e9e9,21c575eb,3419dc08,21cc6fd9,16b14565,d225bdd1) Z8(5245ef31,be9aa946,d2238972,34d44cbe,2caaac5d,8ab539bc,d85a0026,9e25b566) Z8(7a778618,39446cbd,9da3b989,bac0350c,79897b42,a0a08142,afbfcfdc,6af2b036) Z8(5c6fffcd,2a62f9ad,bcfe2140,0b2546d7,ef60b780,6511329e,d52a28ed,edb0e71f) Z8(07293273,d040016e,36cdb0e1,6e9155cd,979ed26b,7c887fd6,73f34935,cddda157) Z8(72aa1cb7,2614012b,47048167,5eee09cb,576a8376,30a008e1,7fc74a1e,fce74637) Z8(7e803728,63bf97e0,528bc7cf,72fdbba3,3100286f,313c56a3,e749f324,fec4fca3) Z8(0523aa81,6aba7a62,19d8698b,341f98c8,651cb191,aafef9a1,935aad11,2931c44d) Z8(761a8d46,e572fe69,f9d7aaaf,12bbe393,ec255b65,ee571552,8e61e2bb,14d76b21) Z8(52c396c6,09cc2dca,7c3486ed,e1c3fb0a,aa79c85f,202d0adf,6573e03e,d2748ad5) Z8(98f5609c,86cb914f,590ba3ee,a1ecdc59,84bd1dbb,6a01d520,8df603d7,8f433e3c) Z8(997a6d8b,6b887aac,cd9ce1df,68f56761,74fa1fda,bf11b00e,fab51efe,3bd457a7) Z8(85cb8f08,8a0a84a5,4f120fa9,94053818,7e8f9e25,31ecdf9a,ba526855,a1c8b028) Z8(3bbf2854,9e425486,ccf010f9,a5d3fd83,0f8da642,6d6d05c4,48359ff5,4447e34f) Z8(6e76d1e0,eafbbf41,c2199fd9,abde1fe1,d9e03b78,59db812d,5fc7d1e8,32da60a3) Z8(9b8443ae,a9bd8478,6d4fefa5,4323da20,3328f276,bed8394f,a3aa20a5,cc86ee7b) Z8(7806d88e,4e7c527a,ff879a04,fabc36d6,c22a64e3,f40196be,a410aa71,a74d44b3) Z8(3d337cac,472d1a34,b86b74dd,dd559082,b62f2138,ae33ae97,d0fe7495,8b7e43cf) Z8(b560a3ec,db9c77c4,aa93b59b,a2b2b853,86c1d87c,0825997c,1ff09480,0e225e25) Z8(bf98dfbb,0cd3c494,39fda330,c47735b4,68b3e92b,677c8e94,fc363ba2,87304eae) Z8(a5c93f82,5f08e819,05b85120,cc6ddff7,422d6d85,2ae06a4d,3dcdda1a,dae20c69) Z8(0473eb14,11489cc4,c6255040,2eff173d,81b45c4d,cec02831,9ed865de,8cb817ff) Z8(4105feec,4a879c90,cb9d46a2,6b16ca71,4ca330d7,c6b5c1d3,4719ee8d,4398c456) Z8(319d33ee,ef465d0e,72db532e,935d0b76,ef428db0,5dcb4f67,67a75077,45a9b1a8) Z8(0f74b1bf,2aff0faf,d6aa7d70,c7a52b42,d9daac7e,058efa80,e814c224,33038a03) Z8(cdc08abf,7bec9c36,c35059cc,b2e577b6,bdf5fe89,c5089a06,ee56dfd2,fa65579e) Z8(11bdca8e,b3471cb3,34112a78,7b5463b3,8e9f87c0,3f000f04,b124e76f,b4c0188f) Z8(ba5338e7,81b1f949,362e5a55,6aeb2772,3897ffde,89819c39,51c47be3,a25a676e) Z8(add51fff,1f3802e7,9a59711b,35287ebd,9ca20b8f,6a55bd83,b7edbb2d,c36191fa) Z8(2ac38a26,ce8bd81d,b955639e,80c23e1a,f59538fc,0df32298,e566300e,9470fca0) Z8(50c77d4a,ab9237a6,dd5b2d90,8042171e,e4d9d54e,127192b9,9afee7b2,1f881e78) Z8(dc1aad62,0f8dea33,9947d8c7,d84cbdbd,fc82fad1,1e9a850e,e1c08b30,7efbc0b3) Z8(83fac85d,0cfe9492,5a60afb3,5e917e15,c7e2c0a6,b43a3fc9,6e9992a6,26a40dcc) Z8(c0b6cd7c,dc29d874,490a9691,d1b2fbcb,70822fcf,ebdbb8df,0f0de925,b446cd5c) Z8(0ba7b0d9,15f53fec,11ac20d6,ea6ee286,c642e10e,458d7ad4,fc9513d6,4d24a8b3) Z8(afc14710,a256fe37,ab59aa8d,9dc7de22,f90a86bd,71456d41,59b02d27,9b6a0762) Z8(c3b77fad,f18820f7,b60ea211,e4c2d9b4,4c34997b,30d84003,ec1313f5,3e284292) Z8(e164928f,ed7217e7,50f9b146,060e3735,1ae6671c,4c2b80ab,ce6c5cf7,6154f916) Z8(cb174b1d,e8a2c804,9e8c3d39,1daa1f0f,fdf88c8c,ed06d60d,b8beb9ec,403d3acd) Z8(1452b436,82281f9e,c7264052,47c41f11,e06fbeca,af85e71b,794a9d2a,3dccc2c3) Z8(c0d12673,6992dcf3,f3f5a85d,fe4c77ec,8a3e243c,819b63a1,6ca458b4,5f316fb5) Z8(9563b603,bf7d3839,0c30362f,e573b3ae,9e9a2d10,e5a4ec10,4b36da3d,cec745a6) Z8(8c156914,ed81e976,d54665e5,2fe201aa,b07dcc44,e395b974,5457ea19,4412a7f4) Z8(dc99c22a,063a2695,c8ecf1fa,ddea54a8,69164be2,19f9c4fe,78efcf3a,248e6dde) Z8(babb2635,725a218d,83ad02f8,be9a51e4,37f40376,354ce094,fe653d9d,333ac2f2) Z8(d6fc9c3f,7ad92d4e,56af163f,7b65a8e4,0251999f,6142d49e,78c910f2,b269591b) Z8(6530bf38,334e2f52,7920014a,0371ba95,915e2b0f,f6da9411,f437ceef,c3242664) Z8(13120af5,45cdfe4a,34df4804,4fa5caef,031edb3a,c3a764d3,535f37a2,037ce182) Z8(7a774777,077149d2,6c8b0f61,c613e457,446a5195,3fb56ddf,4285f9bb,38119391) Z8(593266a7,0f4e9fe3,2e9865e0,fd99933f,aba19d5b,dd6484e7,8e09073d,826986cc) Z8(bd556e67,85ea82da,95d0c141,b27d0147,b60f0103,3e2e5fe4,5536b7ac,e7b5ee82) Z8(8d1f2e1c,c8c72d66,35c578a4,b940d44a,09c7a3f6,dba58117,6453dd1d,56947615) Z8(bb5e0d83,57d0934b,2c565994,53960d0d,a7225f5c,242e456b,5374557c,6e0a75ac) Z8(61990bc4,75908e5d,8ee49443,245cdcfc,b6bacb97,ecfa87b7,1abda1fa,6fa185df) Z8(a0f4e7ff,b6b7b3d1,def531ce,c0b0146e,7e71c665,6b19f0b7,d7833a2d,88e832df) Z8(bf364bdb,255cf0ad,a6dc43b1,9f4957a7,8068ba08,62043a04,3ec023b9,6cc8e699) Z8(f29d9fef,be8e422b,03b78383,01d7d7d4,319da696,e1bac4d7,644d9a9b,524064a6) Z8(51bcc378,d3ccd8e7,91a18352,56f88cae,6b67ff9f,9ccfe66c,54079417,03d802f9) Z8(0fb6ec2d,64c8ac2a,0e3a81ec,38183b05,67c509c5,268ab93b,e1422f36,5859d7f7) Z8(0333e55f,2b332493,cfc57410,9c00803a,4490b329,a69506a8,3c7c8005,2cc472d7) Z8(610a2a54,9e03eaca,ee446427,63469aee,8d9eb2cc,4815db52,dfb2a4b3,5da5234a) Z8(2fa81c4f,5b93a4f7,4981205e,25fa87be,655790e5,74250d4d,290d062f,ca17eaf1) Z8(ad76a0cf,753feb13,86b3fa5a,60cd9e6e,a1784e20,58ad488c,1e777ea7,f19e5afb) Z8(5f44e128,7a6c1d69,282c8c0e,85ef3b4f,3d8e10b9,2978a42c,7d520e68,3a22ac5c) Z8(16787a6e,a913fc9a,8b2b0900,e6942d2d,0485c40b,20c94470,efa45bfd,2fbe9e68) Z8(e0c16af2,0abbf073,f5d6bf94,6cfc6395,60b6b19a,65d1bf29,7812e263,81724f15) Z8(d6dd4be4,acc8e4e1,040bf9ca,6aa87c48,752b13c9,6e207697,64f97aa7,49bad747) Z8(e318856a,362bb7f6,55fb34e1,257f1def,828fe68b,fef81f03,f1a795cb,60f9c568) Z8(89fa0414,333c5e6f,651fd552,8211dd64,e4120a56,6d264133,74c9a54b,80bb2305) Z8(5b11cb97,59c9165d,1f65011c,0e2b72e3,9d167ab0,db9b4729,b1eeecd2,6af5bf0c) Z8(2f9605e5,a80fbea1,81ad2f63,5bcfaaa5,4c7f5af0,dabb0f5a,c88b926c,0a4289cb) Z8(1edc041d,8196331b,887a104d,4ad5ff75,e840ed15,972576ef,08ddae5a,c1d5ae3a) Z8(924f1d81,35628452,ade4432f,edaa4083,34c0eabb,d04ea2e7,e4f06e04,a73c9800) Z8(7de7648f,6fabc0da,6c9f0187,11cdcc1d,a44032e9,4edd46a2,eefda105,0d6f2b04) Z8(09348209,3a8e2c0f,f04e3e80,61016297,6af1ebb0,69753a6b,6113e8a7,86869ec1) Z8(02c322ee,fc64bb48,c24a72d0,4ce86d0e,4bf84854,65d6915d,95441441,b545c9b0) Z8(e1c0d8d9,11ca9b5a,dcc771a8,952181ea,d8be314b,680754e2,5fe634ef,42fd8083) Z8(b6c21561,8a33a328,a2fc4672,7caace45,f7de5cbf,c2b5d4f0,16e52e07,cb4dd2f6) Z8(0a3d726b,44150391,dba4f2c1,c1c375e5,79b5f27e,38f707f6,46f10dd6,99bc3b62) Z8(928e3376,279e47a7,84004249,5cc33ddc,2a387cf6,eb470539,c186d2c4,a3bc8f5a) Z8(fd9f40d5,21219b40,39f70763,813cddb0,d598fe1e,d7cd052c,ce05866e,4d1c71e9) Z8(3ffeb8b3,ce3bdcd2,aa26d3cc,38b667c6,ddba9233,f6862a8b,91e681c8,8f900a89) Z8(819ad4a5,a31e663c,027b8001,4cf5014b,18ec47b1,898a2c81,60f7420d,b22f1f01) Z8(64081ef5,c5677ffc,cccaa2b9,49506dbf,c83ab954,aa305a3d,7d5f2ac9,6fa5ee04) Z8(bd00a01f,a38d9852,485d1cfd,63893e13,3260eb86,2624de1f,970c74b2,3bc14e6f) Z8(26d4fe5c,162c495a,335bc7fa,085f62c7,ffa94d1b,2884be51,8affe4ef,2b9e4a10) Z8(8ce98941,005461ea,8a2c516e,183127c3,0b011936,35c18ee6,e40abee9,6df3bb64) Z8(0931b7eb,47a92fa0,9b449153,6de1b799,612dd296,a05f104f,30d0997d,509835f4) Z8(83d064b1,ba3062d8,b3fbbe80,0284e29c,2fee0176,d4d00d0f,3d204abf,e2db2124) Z8(517c73b4,0a0ba981,f3aae28c,cb73f073,aaf5d0da,b87390ff,d4f55752,a06f9130) Z8(71a1cab5,46645a6d,055c8cde,cc8cd986,70807b57,05c938f9,a6f907c7,18351486) Z8(d28e2d06,17a03091,b46824d3,04826338,f080559a,83a48684,29a9caa5,8fe94a8f) Z8(1f64c387,549534ad,0cacf352,1a7960a9,84c40816,35ef8038,e198faf2,8cd4749a) Z8(3fc35705,b4456a74,3aaf0be5,cdd96a83,d31ae6e2,0b4b1e1b,8f7bfb45,fa65c53f) Z8(506babf1,72b176c7,8b6d5eae,da74bb88,4854ccd2,da0aab69,1087d023,88272d7e) Z8(7f9f6a64,2a90da41,2d7373bd,b965c475,89970ec2,35b4d313,a2cda40b,22f36ed8) Z8(00fd6841,a0782276,09fe0f88,9196df7a,9ab4a758,9c94f271,e3be5439,e9f0f7a2) Z8(14096571,ca3d9b10,465bae56,d2354d09,1e78a2df,f734761f,5df73a94,653a45fd) Z8(d2e791f9,da42c901,9d33e512,7c1bec6d,c0ab7a20,ab4bb5b2,0556410c,2da2d912) Z8(3979d55a,91e94bee,bcc920dd,f24dc6f9,9c304167,51d7181d,5cd731d3,1bb9a5e6) Z8(fdee6b54,3976d6ef,afefab93,838935d0,3ad4f90a,ca36e333,af9cfd75,cd42d74c) Z8(873dbc02,ba0416de,0c600969,2ecf15f8,2faf275b,58475376,05efcae9,66475a02) Z8(ef11c4e3,a5ecbf7e,b213e4cb,9d059fd5,a2d47c4f,49b21ac2,a2fa1a21,0be897e1) Z8(0f9645ef,37448d50,c20f40c7,ec4f1c85,749840c6,12fe38a5,c7fa0911,41f83871) Z8(96cdfe6a,75daa9ae,37cde45b,315e71f3,fd3f4efe,df9ae38b,1700fc0a,2b388b92) Z8(de2590b1,1f431ec2,4d18a81c,7a6cc118,a5133d26,4b874563,b96306d1,31da3bd9) Z8(1c2e86e9,5a92bf4e,f2799c5c,885aba65,ef3f077f,a80f855b,6c742aaa,25558053) Z8(ff1c76b6,ca92ab77,9a0a592e,93a4a4da,9f2370af,9d2eab5c,2fa2b955,65da0ca9) Z8(e719dfb4,03fac65d,83c634fd,7ce1e57f,047d37d7,cb318673,2f8b79a4,c0afb950) Z8(012a81b3,a8f4d3e3,9218f1e4,1a70e020,6ac524ed,52aa6254,d6a37ce8,a998641d) Z8(f9cebbef,5d4f7698,f4f48a41,a02b7a38,51f224c9,5f732f35,7fdf432a,e5504fbe) Z8(a88e2f05,4e295ce9,3de5ab56,5670395f,80c02609,ee2423b1,9fec35c0,b902bd10) Z8(a5a02878,76e1979f,662f12ce,9b265cd7,fc96deeb,1d5ccc02,0f681d63,5eb6b6b0) Z8(f5ad88e4,b3005299,43cdd351,2fc844d3,9038ae8e,1da5fce8,3a35f93d,3e1f9879) Z8(93500a30,3f3481f9,ca0f3d1e,d1228c81,a29b994d,e7b1c973,08b8b290,435148d5) Z8(b64aca15,b59e62f0,376dcaf2,dcf4db8a,9a9ddeac,6ce2de8c,d376426e,c58f9ca1) Z8(b2bfe777,ec0be667,e6e13388,ba8c4aaa,b4dbbc32,e3433e7c,38ca798f,620ec5c3) Z8(8c774ab7,82c56d95,bdbd9e49,355c3303,f2e90307,a88738f7,2b8d332b,754837c4) Z8(0ae0310f,f5e79f78,51dc847c,49b75621,24992230,7a0b37e0,6c5bf081,2bdf3081) Z8(96489218,3b0003a5,6b8677d4,046b0ad6,d92d0a0f,f437810b,07c3d7f5,c8bb8fc4) Z8(8975d8c0,73525641,c562e3ff,fed2caef,7f0f391c,a06e76fc,b3bb1a79,b3167291) Z8(d678a207,18508254,8d03c20a,2a4bfbdb,956021cc,15ed9dbb,d953d941,455fc5ba) Z8(19748662,32c889d7,41de65f1,b0cc248d,70ed1b51,c05de5cd,a4bb95ee,4a885848) Z8(22670cf5,6f742c2a,799b494e,63447a5a,f3d456c5,7b3dd99b,71a4ad6c,8c93b4bd) Z8(41a521e0,d1b398ab,6cebfdd5,8e137ee4,7d6d144b,2faf9270,7c493d43,b02d70c3) Z8(96d12cdd,790210cb,4fa711fb,4bbe550c,4cc1c4e3,670d8e62,798ac5c5,97269f22) Z8(6a31ae8f,bc09e0b6,674c7561,45c135b3,a5eebcb4,dcc4ad8d,cf160a2b,1de4610f) Z8(dc43c0b3,fb1b3a76,36451a2f,33bf867a,fab8a543,c442c303,0246b72e,02235eb0) Z8(5a39bf41,7fb8e4ca,a7c4d286,cf81208d,62d1c65f,4812a716,ee93ca35,b6354d4b) Z8(920c0177,32c6cc16,299c14cd,bd7f15ef,346f5ac8,2d13f323,c32a48a3,30ea3925) Z8(aa4c169c,bacec4ce,160e11de,df96e25c,8988dce4,01a986f2,eb42ab5b,a12092e6) Z8(8e290691,f78f45cf,e6682a09,60ee289a,0bbe0d1b,049c0d2e,fd979819,74784a16) Z8(f7ff5380,72323d62,ce2f5757,38083a10,bddced5c,ff96efb5,2249f807,980e8f30) Z8(5620cd87,a4b2b116,01753cc7,a2fd0e89,94df8174,cd067049,424205a2,71dca628) Z8(15359599,84b5117a,eef608b7,4d503fa6,21cf3dc8,9613e554,0b79f89b,590c9c94) Z8(157f2143,900736d9,86820761,75ae6e02,2bd445ea,88309eef,6c2c3f12,103fd3d5) Z8(48a83352,f293f8a5,5083c400,2c4a1d55,2739f9be,8f3001a1,ac6b5f95,48e0ecb1) Z8(2ee3eeca,9e70375a,09c50d49,7578d538,33f85be4,7916ee55,06907ae6,a1a26fcf) Z8(2e24c445,cf80c99f,88c68402,19027320,82102ba2,3feb41b3,4e97d9b0,f8ce8ed9) Z8(0b7149f5,1b9ed568,b1df1c60,527eff8e,0899a18e,eafb8c50,a06b411b,51bdb36b) Z8(9c7200b3,57a49e61,630e1aac,8e455ebb,af793770,b2131ca7,923c900c,e9417816) Z8(5d72dd51,aa3a3d14,766837d8,656f919e,793b4b2a,a64306e9,aa1a9642,00bfa5e2) Z8(16c222b7,a8837cfa,63065529,977f2d0b,5184c500,e567e35d,6cf5ddf3,cea84345) Z8(9a656110,ac3ba59e,86651415,88f39a78,93b7de7c,9ad5210e,214621ec,adb1af3a) Z8(a50ce5c4,4a39b873,04618c27,98f3d112,f2ea6877,1121d963,791864ae,85f3476c) Z8(2b9e53b3,a257fce7,76943f0d,eb940e3c,b97f9163,0b65f0c6,3444e927,a2723ed3) Z8(e995a3a9,bc72abe0,c03185bf,b98be86d,e4a040c6,c0854bbb,3aa7585c,9cf286e0) Z8(dc974f9a,e842258e,40c98f11,ebc60262,37681905,38eee755,c9d9a699,44b24ca0) Z8(a26f3314,9fde180e,91dd5fda,b78d2500,567cf4c2,fbadaaf6,ef074e40,af1ff740) Z8(9d7efcdd,b7634c33,fa542641,6d197262,44d351cd,fe8f0136,324bec11,6d2176ce) Z8(6fa6fb31,0d171391,2b5c713e,09484346,0c7c7c34,ceb4d9d8,2c7cfa85,a15a7667) Z8(773fac44,09d29096,7e1af9e0,e36a6a54,0f611fff,47ecbf65,e8b88ad1,782b678b) Z8(42e0de73,c87bd2b6,2b3a440b,1a2883d1,104f9cdf,552048a8,8a30336c,32359f20) Z8(b8b6da84,986c328b,ec28c8dc,6d6cbd12,732a3b88,014e3795,e3d2a945,10cd66c6) Z8(34eb9a54,44642866,baa78aaa,b4fbe210,29c4f58e,23a9f811,a6a209a2,4e3f939d) Z8(2da8fbef,fe779e58,78fc754a,dc0ad026,7407466c,a2d947ae,c9145112,97474282) Z8(87f6c5a0,7804c5a9,f2d8466c,c435c9fd,5a10e825,b31c0738,71fe322a,093c2c22) Z8(dc03ee40,ed26d33d,a9b25d26,2e5e9836,9c0adbe4,d2b0c42a,9b7fc4f8,14337368) Z8(032fc35a,e9d550b3,8a482575,6a738d55,87567bd0,26ca0775,3788b71a,db3b666a) Z8(054e4e69,edab20c2,a3397ae8,cf2bf34a,b0012618,942ac74e,f05fe227,39c08c40) Z8(78fde40f,8a31056d,0887cd49,9d864f27,320ae003,bf4b8e10,d2630cb6,0e0b49fa) Z8(888d8c40,7ffa5c66,4b154cda,5833dc33,db77ce73,16623764,3c3b6f75,47e432d8) Z8(dc524cda,d06e3b87,db9615ab,a67e3e4d,f6fa153a,ab1ae872,f421d738,2ec9c2f8) Z8(66750ac4,4356d8b2,d364877b,470d310e,4d8dac3c,9a41057a,5a872b33,9c75712d) Z8(5634fda6,90f3a8bb,6909c9a8,e1f34c38,e042ec17,ccfd6b40,5ffb3cf0,3fda7a6d) Z8(a9f08b22,b79b50ed,873caf4f,f9a2b5bf,704e2b81,43943ffa,a5ab6aa1,3133b641) Z8(fc0945a5,c568f3f5,dcd58989,d8c8f252,0dc04c3b,ef9b85f9,2c55f416,581eb7c9) Z8(acc0c38b,40216de4,52df8bfa,627f6dea,a109da7f,d52722c5,f5a2fd6a,0cd2f0e8) Z8(a5aa9488,596f9884,1104dea9,c8535ea0,97985f47,150f959f,63f5bfd6,e960465d) Z8(e047dde7,6a8f3e1c,ad1355c4,04695165,4a7efe51,837903ea,36a9393b,3598f8b1) Z8(06e6f4f2,7ec41821,50e8b0b3,8841c284,ccc44173,1228f51f,d8df8842,63d89b82) Z8(8a48cf46,06167261,55af6088,f61fedcb,3a5ef9ef,f7f76ca3,93c42407,60b78669) Z8(d6b9947d,1de40880,78c6feaa,0e260616,0bf9eedb,45ef0a68,92b37630,479f6b14) Z8(3dda20eb,450c32a2,26ba2ba0,b38f211c,b5916ef5,1f428920,474c5790,86db5931) Z8(3e1f65b4,4b149f6d,fc6258c3,19074999,9b8497b2,07717189,2ad87f46,77d920ca) Z8(15c0cecd,46f23223,514f4fc7,87b1a9a2,7d60c675,85314f1d,8437fcf0,4af76589) Z8(c28c2417,680b5bbc,6fb24f10,9aca6a10,1d1cbc73,47595c9c,96397988,42e91099) Z8(31f7f77c,c664b323,66f66721,6041fece,b172444c,e58892c9,39bd245a,8372c4fe) Z8(e543fab6,58d81014,09c18e6e,f0e8e588,7f1955ca,266095d9,8c3072bd,c6598bea) Z8(03dabc5e,62a152b6,c24fd364,2aa7cb2f,47bc2cbb,80fc28d5,e203d1a0,65a93d99) Z8(907c3ec3,539b277a,df9b4c96,24c6cc17,c4e1f20f,43bb6911,ee61f093,2800d0f5) Z8(a61addfe,40d06325,fee43fef,1efc2691,fea11954,4f409032,dc598665,87c38e0a) Z8(0b5d0200,dc82a4b1,272cef4c,dcd90ddc,bed33f6f,4c95a282,c3d463e2,3cb3519c) Z8(664a5b84,337f4690,425f387f,0775ea3d,430e2ee5,2879f5c7,3818551f,15e9a53a) Z8(952a8c45,05ded2e5,53f3f0f6,6b0011b2,58fd4979,b8e33cf7,ba0c4e81,09e247b5) Z8(ee36adab,b56cb17d,83894ecc,91b9f7fc,8841d510,3c112afc,1f6bbd1b,d460ba5a) Z8(11f3d8ff,b896b844,ecfedef6,c07902ab,8564ae15,a2f9d9e1,43547967,4630504c) Z8(f8ad197c,ba91e7a5,8b461c47,08fcd404,9b098c76,cede1256,1b9af659,7df0a648) Z8(f2015b5e,09a4ef35,35e39803,9930ea5f,c8674023,a1ebcd25,32108959,02b7b5f8) Z8(7bc30d40,62c4315d,28c51420,20b12869,57361b18,ee6a3312,ecdcb1c7,e9b5ff60) Z8(e0262563,9c277f3d,adf2205a,277d101b,095f234c,b9a57105,ddecba8e,589f3a27) Z8(f23ac397,2f9c584e,2cc376f0,ba86e66b,c2b54ef2,71dc7add,5e10b017,522bdd66) Z8(0c513a4f,83886884,c2ebe392,fc97e263,aa5098b4,6d8f413d,fc499e94,5f467b48) Z8(35a27276,0087091a,c8162cb2,88a436b8,96cc26f7,f7c20c92,dd3b6407,c3204908) Z8(3bfa564a,234f93ac,e9e5f435,398e36ef,7b4245eb,7e7c7645,45f5f978,e955d3cf) Z8(6a364ce9,bfaa4dd4,93cd7b93,62d29670,e3e026ed,dc8fe1ca,eaa1c8a4,c8a3dca8) Z8(9f045891,0c9ad13e,bc29a613,d6fa50c3,224acf7b,04847f6d,0d92af70,62103175) Z8(61763c0a,7121042c,d50c9aae,9f1965df,ac92dd8f,0c6a4e74,99b4b1d4,a237a8ec) Z8(26815795,1d7e24cc,8e2330c5,d9377421,3fa6d4b9,daef41db,45f872dd,324c8c66) Z8(f87ef469,6bb9562a,4bddf664,6a63eace,f7aff23f,1dc82c8c,514ed7a4,aab89149) Z8(302ba5ee,bdb7df42,b6bf2968,2206e32d,d2bca852,5b27dea8,88fd4952,62305775) Z8(9076b5ac,7c856ac3,70b83fe7,1c611742,dc3d48fa,45ec41d7,33da10e6,a1ad0806) Z8(6cc3bb53,fe05e2d5,e451bfbd,1b5a8406,a098a341,ad72bf01,d911c27d,aca47a2f) Z8(ab733cca,486522f4,eef289e1,77fc2bde,8eb59787,3ee7f5c4,08457078,371429a5) Z8(7ff20dd9,14bfab5b,5aca1111,cc105d8d,64c6b0b1,8e9c5e59,797587cc,842ed74b) Z8(57f3ed4f,e4538437,b9dff58e,516393dd,b01e34ad,9a8e7d43,09853e16,0b1d6ef3) Z8(aa9074b0,b958ce3d,22f1d65e,d96d66e6,bb8ae192,93f51eba,7ad073af,f5e72971) Z8(39709c24,1df19224,bccf70d1,256afbfd,f859c6ae,81657f41,0cf90abe,d49c0cfe) Z8(1504b22a,a850c024,79229abe,fb279cc2,6b02971d,e8338ce9,4ad08065,a8fbf930) Z8(401f1e7d,2977f5d1,b2bd651a,c51c5657,2275b035,07d21737,9341f412,8d2121e9) Z8(71a3900c,6b19c103,0e56b370,ebd1dfb0,25ae6ea9,22d60633,229b8d18,9b3a92df) Z8(48cdbc4a,e50686b8,e94d020a,018c3093,d2d0ee61,a5b8af9a,0413abd8,64d1c02d) Z8(f332d6ba,1d0bf071,b579674e,e13af63b,8ec9d2e6,cc1f8772,10ce7e44,93661cb3) Z8(11a3518f,1fc5278e,13c5b070,e09cdf2e,9c098df1,6c2eb2f4,2b13f45d,cde8f30f) Z8(ef6f4963,66b954d8,e4f38a08,395c8b05,181581c9,92c76845,d385ff98,ee622174) Z8(d97e5ebe,f85772f7,8c642474,f39a8076,869e814e,0da01871,62f3e547,985cb394) Z8(06755492,c2db51d3,f965aad0,bda43815,84615baf,c899395e,76653a95,11b0e4e0) Z8(aa06bab5,495cc2d8,fb375309,8834a8e6,d98b5726,38d484e0,600bed68,ea8c6004) Z8(afc20a15,493143ba,916c0490,bcf22ff0,51d7602e,9a307a5a,f858c7ae,51b3fbec) Z8(84daf57a,14fbe122,7fd87549,d97dcc9b,1c674161,cd85ce86,ef167391,4ec83d36) Z8(b78c5f48,ec5fb40c,4e336dd4,9bc0b6cf,6f5eef05,3331202e,5f6b5690,68f4e690) Z8(cafc54cd,8431df00,9a4cd177,576beee0,f5afc3b0,96d1fe51,4bbdf8cf,e7d8aca2) Z8(c744c8b3,1076aedf,0d517aae,76525d26,b1b432c9,3970ea56,7e5eba36,9e264ec1) Z8(a5d171bf,24d90d96,e2fcffb1,011bf68f,00713a09,ecf69073,cc80b90a,60385e93) Z8(c7c9dc19,e175e995,7524defd,22ccb565,8dbb1885,24bde171,380f8acf,bb2a89d9) Z8(12ce9801,813d7e01,56b00700,bc0d34ec,06b4938c,b93ad22f,a8e769c8,8fcff3e1) Z8(7164a8bf,f5ae384c,52896d12,e661ed45,633d559a,8df8ac78,04b7e20d,1995aff2) Z8(f2895967,b16b535d,7c79f2de,c7978c06,0f81390c,70af22cf,c97a26b1,4b656a73) Z8(e974def6,7594e4f4,59c4b41b,844e6955,f30ea252,3ba2ad86,56e6bb84,e9fb75eb) Z8(3dab3a6a,d07e950c,cc3dd9ea,c76ef1a0,11e44ca3,28b96adb,85e8b436,cd92fd3b) Z8(aad4923e,28be47ea,2acc6205,d7f74de8,fcfbaddb,79d1b07b,87d598ca,5a95af25) Z8(979b04d7,4836c21f,83d8c3e8,34c3473d,362bbbab,83c8d7bb,8c09aa82,e0247d2b) Z8(6e964600,fceba3cd,2a115632,8c4943fb,45675ec1,8f35f457,4cbd2bc5,8fa2ffed) Z8(aedb478e,c0b0db8d,21fe9ee5,ff4cb772,b8db5fb2,73f6c64b,3ad183f8,f7be6065) Z8(ee7c65c9,4a7e0e9e,4c6bcbfb,3c2e3909,3b099536,2bccc9d3,cae91107,edb358c7) Z8(c0a791a9,9b2c52e7,30ae06f2,86164755,612cc1ad,5413c82f,17d6ede9,b446b534) Z8(6c58be20,3d91b4cc,5ba33888,53d755e1,6cc8d237,ade7bb8f,a4e4fbee,3144ef5e) Z8(6c358d76,c8348fbf,d30ae2cf,3da73773,e4aec310,0667efc4,e3fd37f5,43a00221) Z8(8a552c28,109d3ff3,49bc6f35,6dd88076,86d3ec85,d199de5a,56945b1b,e028d1a9) Z8(f22e1218,5cc58e22,d2bb5963,8a956e19,14930f07,acb66b91,42a731c8,fa32e874) Z8(99c4a7fb,28666c29,e0ccbf26,0ba46327,f59ee1bd,cd1f9e1b,adcc80e6,c0d36853) Z8(12eb7628,2923276f,e1199c4a,efdaeb2c,fdadd3d1,8608dac0,ca39ca20,a7019ede) Z8(2936aadc,6ee60c79,425e4440,fa2f5df8,998aef93,48741035,76afa27b,0e70170a) Z8(5bf2cdc6,005b9b14,1d919d74,545b7577,d13c67ad,01d0d222,856ca329,8d74bacc) Z8(72062ab8,22b0fe46,cd4a6cd4,10f2878d,d7715e15,ff7346f9,b330f0c7,e020efd9) Z8(d54773d4,2ecd8206,92b8304e,3f6e3665,4b972c9f,9df28d7e,845e8174,d4a150e9) Z8(20e149ad,cc0e5f12,af1f09dc,043f14c2,00b50ade,31886ec3,a343b364,488b7c00) Z8(ee30e398,39038916,21e33e10,2578889e,6637a911,d919c6ab,e57cf1c4,4621b73f) Z8(02a032a4,1ce6d4c8,1db9865c,a50cdc5d,c9bac550,b9719778,06653be3,4e8f7167) Z8(0847fc7d,316154b3,66035dbc,0fab2949,91658bf0,d5aaad87,90f35d7a,ec2a9a1e) Z8(217d764b,b0c9bdad,b5287f24,5b1d3a90,ec94a44b,5f976ddb,962a48cd,319f2fbf) Z8(e6a8c301,636f3a5b,b3fb63a0,905c6d03,2137d4df,c758fc04,b765b662,d2484e0c) Z8(829b303d,b3a48b66,31f9badf,098b2f28,bf315328,362ad68e,ddca5f4a,9315e3b4) Z8(e4f00bec,97ba6fbc,122fc48f,b3d3811f,7b4ee276,c7584b8f,29e8fbb6,7c21a4c4) Z8(e0b6bb59,f0b08d1c,ea6589f5,5cb9e60c,5bd008e2,539d9fb3,6f049383,e9c8cd6e) Z8(07edaac4,b8aeb6a1,2939940a,5d9ea6f3,cb2e1f02,6d049ef5,5d8da069,9eea5ede) Z8(406ca77a,9f724f3b,83a3e939,e1b27f9f,7c547041,b532267f,5331ad21,91b86857) Z8(67ff16c8,13d4179c,fd1b02de,673f0c50,460dbd36,473980d8,ab87611f,b6b290d7) Z8(5e705203,b7c85154,8229dec0,42133979,d463b65d,85a3737c,2c8f85b5,e430c302) Z8(5b3d46fc,f3ed3812,a678bc86,43e42c3a,26174347,929b59a0,9e49e59b,3567c9c6) Z8(74d3caf9,019dd823,7d7c46c8,6411e72d,e22bfdbc,945c5f3a,5e978e82,729a2a1f) Z8(a71421cc,78f5f7c5,c198c253,a1559b8c,0ecca69d,155f6547,36569ebe,0e7a61f1) Z8(e1191ff5,2bba553c,da22daf2,e47291bb,f553bb2f,0ade31ae,65b82954,85a759c5) Z8(b1a5524a,4eb8221c,5525e540,66e433e9,cea1387d,651d9b48,bc4ae3b1,4c3a037f) Z8(402c3990,bdf27b08,b1d23d82,4cd93856,ab2edaed,adbb2b1f,1d273e30,872574d9) Z8(d7fc34a5,e2a0c4a6,9dce5d39,1e77bbca,ed219ce4,5ded478e,16dec3e3,58780e49) Z8(c5e7f0e9,0ae16ba2,375d6e19,5ba080c9,075887ed,5bfbe4e4,5bb8baa2,deb6451a) Z8(342c1bc8,8f41dcd9,b1523c1b,5fb51d5e,a52ce86d,696adf3b,6d1f0696,305c94ff) Z8(3d6b6272,b8b2ef56,c5736ad9,6dd04673,a788a2dc,b92acfec,4001a471,6b86c695) Z8(7c7b0606,29bbdbc5,7bced649,f59e1cc5,931fbf9a,4214e0e4,633ce226,d98daac9) Z8(4208d152,9033fe17,f64f3541,9f5cc28f,c0b8ef8d,f0f77fce,4e0b6ded,ea8d8ec2) Z8(3a368607,bd1c15a5,5f2735eb,83fae826,c11b61a3,3d6ea890,2b00bafe,04e38275) Z8(a5f7abbf,a1c27f75,7df495d5,45708d42,19b051d8,a83c6256,debe718b,645ba8f3) Z8(88a8ed29,a11e2c89,90ceed96,05af61e5,ddc96626,6f87d260,1359b63a,4b0f6681) Z8(32da7d01,7a953318,144b6fa9,68dc2068,edc4ba95,775d69cb,5c047408,b0efa623) Z8(5f78d889,f87f5869,76ff1b2f,1f840d24,b31ba5bd,a5e72b53,47a04f10,0729cce6) Z8(89be9628,b209eb36,db812b0c,9fe3a8d8,1cec1aba,29fea239,769ce66f,fa4d2378) Z8(ca67401b,aea7b89b,28a7fdc7,45f8a728,cccdb83f,6fe5f7ed,88f5d1ca,bef87b40) Z8(f6d8a8d2,8fc76060,ba5b3933,37a1d510,a3d623cb,763c895e,1d44efbe,78728e2c) Z8(d3ee9459,8d11c07c,2b6933ed,deda871d,70dbd17a,be137ad6,579b73b7,3e90481e) Z8(dad0a3d8,73c61008,9034f434,b6a55e6d,b1b5e13f,f61e23d5,43f150f3,9cd52de9) Z8(6c57926e,3cfecbef,0633967b,afbc52f1,e58ea230,36466e8a,fe7ff80c,43869d1b) Z8(8b47e18b,f337208a,a1431164,cfe94dc5,5b1c428c,fb509344,95fc5689,0f4ae06b) Z8(e286063b,38ae3230,6e9c71ea,8409483e,8ebf1258,f1534409,173c68fa,4fec18bf) Z8(87f7f809,17ccb67d,771bb279,4d7b761a,382fbab6,bce838e4,f551c1b0,f8e00900) Z8(ba059f72,8d3b3de1,8a133c94,05781da3,a840c21c,8a78b14d,c7d32270,e029c1b4) Z8(da7a85f8,46c7a9a1,0e417c08,149e1893,8917ebf2,52031172,7bd66dec,6e97f076) Z8(fac8cd48,923f5120,226a5bc1,b9a0cf64,de128515,9bf14a39,be0e8475,deefe8b1) Z8(e98e4f76,eedb1d3d,a263b129,de30bc5a,47a3d9d7,5b426966,62a45aee,930d7749) Z8(e57e32b2,514be446,a94b8be8,3dc97181,0cf39765,4c7a11dc,48db1385,8143be8f) Z8(afecc86d,e85872fa,a4674253,6bd49108,df62e534,9c1d4b49,a832d845,aec55fe6) Z8(715b762c,738885bc,c5b04f1b,6a22967b,9e1253f5,ed49d668,8d98e350,aab7067a) Z8(c47e18c7,0e0ce093,902b3c2f,96ed0678,2006e282,89c81f69,1ce0c437,8ae66600) Z8(cae9fa6e,26338d5f,ad4f1047,d87ec9db,8de0f3a2,0b814935,9a9382a9,14451b93) Z8(78a0ec32,c53e2385,d9e77b76,37eb9454,a4369ed0,a4836ed5,7d97495f,b12843bc) Z8(ced9ca9c,04eb27e3,bad5b6ea,ff4020ff,f35a00a5,22701f7a,71725988,2617eb1a) Z8(ce6c94d7,fcb7e576,38d9fb31,a0973b5f,a6b643a9,0a8fad22,8ce60f57,41e0f9f5) Z8(08e7e4ef,4de85f7e,037e69ed,2443f8df,3f68496b,26d893b4,8afb0cb4,e51b182b) Z8(d6868f17,f413ab7f,9a465144,e5e268db,9896a976,8c45fcb7,4d2f1a6f,75135af1) Z8(2e1eab5b,7178bd61,dd20c588,4fcef5ba,e210c351,ee8c76cb,15793d0c,ec23299b) Z8(146d91cb,2bf15a03,cb74ca34,27dbc5bf,8bfb991e,dc222529,91e65de6,cf13a59e) Z8(f4dafa29,bcbeecb0,7eeed60d,2745ef1c,a0325d23,6e3e16ba,f2a6c9df,ea72b0cd) Z8(e551aed6,db88d709,b01ff673,b7b2724f,b493371c,90e45a8a,2a87d6c0,911a5951) Z8(6c3b5453,b7fd2ccb,8efaf860,d88c832c,d506bf79,8b131c97,8e56c8a0,befe194a) Z8(6e628ad3,e59020aa,8fd62e08,2cea55d5,928831b4,9c6134d5,b3d7a107,89e381ab) Z8(610b35b0,552af8ad,2b57aacd,cdbb911b,6b6101bd,86972773,031aa1c3,c0038604) Z8(671e46ad,628b811f,c9e0bc66,09d56cdc,7362cf83,af2451c8,1d888668,08347285) Z8(5fad1279,f8168863,a6455464,99551309,9a4f1ce2,11cbf2aa,31884fcf,bf94411b) Z8(f9407695,328e877d,254cf631,7cfae701,3c119069,9dba7202,7196b8d2,d90885dd) Z8(27e3043c,c79bc297,a06f0f62,254b80cd,1f8a7202,11e16a63,6e178fda,0eb344df) Z8(cf093f01,a0bb2192,c1a15531,569f406a,8693e780,b6aa28f5,ed279834,d4d89405) Z8(5e23da36,e797ccea,ef3410cd,74683042,5a8d64f7,dbc693b8,887adce0,4b9d9384) Z8(37444bb0,c1861c99,f0acc618,d277a212,c0529d15,e816fd98,2083af71,d2fce3ba) Z8(044e7e7c,a3b027fc,8bfd1670,ccbc2ee4,6c77ce45,19890f16,9c3766a0,d57747e2) Z8(b8e49b25,76247f82,cdcff962,28088802,c0fa5aa5,13e42a03,a250e54a,a4d59b5d) Z8(b1d38d77,26d2a612,40a48ec3,933e162b,4ad0bea9,67676e00,4c462745,03006c98) Z8(84f3663d,f784222e,a92f2431,7a369efb,cbc0636d,1996a4c7,d9a47887,a517cf18) Z8(4c7af17f,808c7f64,aa5fa14c,d7d01850,ceebfcf4,58e3717a,f34f00ca,11270d43) Z8(c226f4ce,74bc96e5,ab20d76b,0d278922,e4ca0879,6a112cd3,fcbab1d5,79976359) Z8(36d255ef,ab39b1ce,c75daccb,f230436a,d6d36831,43722ddb,453e3fe1,e3c90d84) Z8(cd29b207,e805dc7d,83a0bf69,202b2fac,ceca1988,feb0bc08,64dda8eb,b6796801) Z8(b171ef24,459a01a4,b2f922ad,4c7ad50f,8fbcd4a6,777212b6,5cae0f2e,69bb9cd5) Z8(67c8a88d,198fc0f4,36570e78,6f171f64,d71c0a30,4d2c8515,cc60ab38,fd2f9877) Z8(cc10fec3,13eecb4a,af8ed210,382a32de,2748a46d,1a87bab9,b341f987,d9954d0b) Z8(8bb0c828,c5f12fe8,d3c67bb4,e57e7395,ae786d8e,76f5a99d,52a10f04,16d96149) Z8(08a061ac,47d44b83,1a51b785,d964298e,0504be82,2cc2cb2e,17a9eab0,22a482fe) Z8(b0fa8008,898c527e,4324ecbe,908291cc,3a89d5c3,fff21a21,fdc057f9,79ff6720) Z8(1e5b25e8,87602c68,955c6cc1,58733cd8,0769ad3f,e7e920de,4f83dd49,f717cd3c) Z8(f0902d79,4ffcbd3f,09c6a089,12dc12ed,c3c1063b,4c8aad29,c09fbad3,7ad4fde6) Z8(c91023ea,aa285feb,d7dd6467,201a06e9,2a06fd24,889802e6,d30166ee,dee6048a) Z8(01f89035,a7daa758,0b371211,474bb586,e6f987dd,3b9a914d,1721e96f,6627a798) Z8(fbc3812c,f29d1319,cb6d16c7,6d3272b6,15c7d715,78fa0a4f,6707aa46,1a0fd266) Z8(7ed2c204,6a8d44ff,083f8563,82fb46d6,8f2cab99,077b706b,6248714c,8e6d80c7) Z8(262a1d9d,2db98b0a,1c79b792,c451a151,b3195ca0,76467ef3,66eecbd9,a5c66f27) Z8(a34398df,61fac6d5,4dff5419,d622c939,c3db45fe,b9b3f051,80356c2f,223fec13) Z8(aa411163,d57d7db2,78367aff,520d96b8,ac123857,8df6ad66,69996ecf,ebb227ca) Z8(47158733,7d1473d0,8dcf4c31,1178fc31,d30105d9,966c7a59,31cab3d6,2808484d) Z8(94dadfc3,ca03caec,4f0d9899,f262032c,66a80bec,e93ec759,be1d08a6,2f686d09) Z8(930a25c1,efc6cc9c,133c1d01,adba45f5,7ae22e37,49773382,b7037632,abb16f03) Z8(1b09d5fe,9fd54b43,30739d64,ed61ab55,8aa8635c,e3efaf02,fa6ca516,53f465d2) Z8(a1ebd856,ab5439ff,487db5ba,6d69c679,ad9495ee,d0141459,e924758e,c9c7232d) Z8(ab987f7e,ed751648,4825452d,5c728756,f81e7dc0,7c89b1ed,99f9987c,54f35104) Z8(c13e6740,eacccdba,ce3533f7,16894321,4ca26ccb,2a3c868e,98d3406d,e3eecda1) Z8(d3e61919,daa99a22,e15f3178,7adbc2ee,5df8715b,f82aa212,21e57fef,515fbde6) Z8(51d61bd2,6581a14a,23520a97,88566024,6e625b1f,b090b33d,36490dcb,17fbab08) Z8(b9e38bf5,0a22026c,626148e4,5b45a394,17d30867,e77f932c,50d5d277,eec20a4e) Z8(f56cd72d,6290c332,28f02100,602ea9c1,c98d9a12,e7f816f4,f3dfa6f0,9983b1fe) Z8(397e20a9,a9face81,35bf6508,301a9f0c,30da21ee,97ee751a,c2255a92,302ce07c) Z8(574ba65b,1712b487,61404a2f,1cce5007,aa1bb6da,a8243ef7,aac8e8b9,88734b40) Z8(720d721e,8cd086df,32486ada,d0faba63,17cdfae0,7864457d,5386bb98,64d8ad73) Z8(effe2d44,a70a4e04,c180ea9f,0786ff3b,ed29af0b,20c7d9e6,1f226342,c69b21f6) Z8(7c5cd7ad,2c0641da,0f9961c6,bab8c081,f9a21ea2,dffeda26,f6379310,26d0f1af) Z8(6fbef26c,892aace0,230a56d8,8da528dd,47798c73,154f7754,f2ee88e7,ba98a9c2) Z8(aa7ea837,da919a86,3b87aa85,c82579fe,38b91fab,94e3e43c,f42b5924,045b26bd) Z8(5a8ddffd,7b076f46,8624b69e,bb1688ca,bb84aad1,826ba890,0dff15f1,e81fc192) Z8(c164ea12,f34fb3a8,6e81ff06,defec575,3ac4a1f8,4cde6f82,8fa9e5ce,01ec1b11) Z8(cf9bf99e,213ced49,c4118115,cd8f3dbb,d90fba0c,7dda0911,d0812a38,52ac24da) Z8(811c3e04,095eab7c,f12199ef,3399ca34,7a0daaf0,75987d8b,0ab43839,900aa6d6) Z8(e18cea66,8329cc91,dfbef02f,e59aa0db,942e7554,332eda9a,0b6dd799,be01e806) Z8(07e082b9,7cc0550b,58dafab0,7ba69b5d,ea0cb108,f4496de7,3ab80504,f155ae39) Z8(0c2625cf,d11d0e01,d804b39b,4abbc7fe,c7e2952c,bbca70fa,9f6e7272,d6143d83) Z8(fa76936e,00bacf3c,6be2faae,039d9e82,5fcf40f6,fe4fa437,45c280c8,21175726) Z8(e6139128,f7c27583,681d1d98,f89ec99e,560b7a7b,f86faff5,f4636074,352b40a6) Z8(6d24e2f3,791d0baf,2312bae4,d8fe656d,089bad10,1be68196,717eaa22,755622ed) Z8(a1e29ce9,19fa4ef7,f07cdb49,120e937b,e1cf5767,e0b85703,bf66ea3d,e567d89c) Z8(c746c4f5,468cec20,c37fe1af,248dd683,3e61f62c,edfd78c5,41b2a815,68d5e5db) Z8(e75cb285,2cffeabc,7218455b,29a3b105,7f82a34f,148e4c17,3a58143f,548151ee) Z8(a5013826,1cd47535,8a83486b,8d3691c4,4f284c8b,ed60aae7,4627fdc3,dc7a3256) Z8(ec8c4f95,e4dd454d,17fa7f70,683800eb,6008d264,622d3105,ac4ee246,52297f66) Z8(ff977801,9c19e5ae,96f69800,03e84d66,43fde5b8,da324265,6798a2bf,5e96f93c) Z8(5f1b54b1,e6e36a69,17d30baa,23db82f3,0847720f,fa088cba,6280fcf9,213632fe) Z8(22af392e,98bb85ea,096a9ebe,d7444bed,d025dd23,01bd11d8,337c0e88,dfc1125f) Z8(fda70f6d,2bc4fca6,b8d0bf84,c7296894,43d17eb9,c4949220,e0895063,f6a8a0ee) Z8(483582e2,7e544a8b,15a232db,c36e3cda,98a6a38c,5991dfef,eb5b5743,fc68e012) Z8(7c908853,222142a6,18bf0a20,a04118b4,51611479,f3178440,0be348a1,0c9251fc) Z8(5ff1ee18,69dcaa6c,a8b11991,d5c6b9af,5cee51c8,10bcb274,09a6fd50,8824a730) Z8(fd24e89b,b11d3f5f,0f7e22ac,ae4fdf8e,6c7f812f,4c26a8e7,b2c73fe5,b0c57e36) Z8(dee53acc,0bc68250,2baaa8cc,0208f2bc,add666bd,d19b99f3,8480fa2e,462bf5c5) Z8(cc4ba397,2cd30f71,0ebcde52,fb3c816c,c4aec712,6550484c,7afed51a,2dc76549) Z8(f0a69683,6a4937df,bba6afa1,52498901,5c359819,82da8b95,395780e7,529ee403) Z8(9b8ac2ff,6ae9b114,5db249bc,e1079b43,12914f36,c07d10eb,2b727a8b,ec0f21d0) Z8(cbc6806f,bb8ca632,652fc8e0,fc5b4419,9d9894b8,5f09621b,83dbb96c,ecc88148) Z8(0a42e62a,5ca4e88a,59f61e67,c7dfd92a,2a0c4dbd,c1102ef3,5a894430,d132f24d) Z8(e3d2282e,627b99ac,d5ec687a,167807f2,177ada19,a5ae9429,32b0a9ba,27cb42cc) Z8(df2512fc,1d0068fb,71d8fa44,58abd59e,ccf8b086,5b066a5d,d946e01f,36c12df7) Z8(38ce18d1,ddd3e72e,ad0c64eb,65a46a7d,42e75cd0,68fa3913,1e96bac4,e373577c) Z8(fb6d60fe,0d3617cc,73446759,9ba5464d,bdd2121c,8906a162,d2bb2ffa,e3158284) Z8(16b2e4d4,53e11093,986d9999,c39f8c3c,f8fe1051,b37a3216,b73c960c,5a162266) Z8(560b4dc5,2c67d626,de9f1fc4,1b47f91d,64662bd2,45d9126d,cce5d5a6,d20262ec) Z8(218546a6,d3441175,3e7ecb2c,c16aea72,842d981e,9d6df2dd,f3609795,b046fb53) Z8(63d7de6f,21656038,8ce6790f,faef4ec3,0ec6c005,4f927376,8275e1b4,84b69493) Z8(0e4599c8,3100712f,36b72595,2ae07542,a28d4175,bb60cc7c,99d54908,f581db18) Z8(74184a4e,5e0860e5,0d4c7359,886b6310,1722075d,bf3c761c,4c60b61a,e6817706) Z8(8d22327a,72c102c1,3c2e1eba,92308a59,15fc88e6,be1e4359,3a7793eb,652f9081) Z8(a78438c3,3b3fd53d,b339755e,e8972046,b112f4b9,45741d97,9884f109,8842c4e7) Z8(993bd03a,ad701555,fb2c2202,e43f8385,c4941d2c,2b40e53e,f0f3bb4b,29875053) Z8(7c9d429d,b16b5916,9a6e4405,55aebe93,9d5f9d1f,c65a8327,7739173a,029e1a56) Z8(2fdf6144,9d66a736,8bd6f7de,c51e4b9e,f25770d5,5e798c7b,9be37040,915771f8) Z8(f482f33a,9ea1dd8f,db061a3a,7bd85d80,39d158db,12cbf015,265afbd6,da532bf0) Z8(54c454d2,97b92d81,e0c2ed3c,a105c8ce,00d1e82b,8723064e,10ec5bec,7a1b1e81) Z8(77c9dc89,e8a1ffa0,f6209708,012ad82b,af1ccb05,c9e051cf,2fc59a3b,cc8fcb02) Z8(c34779d7,d944e91e,4933f1b9,e0111c6c,0cdd1f96,d29758f7,9c2d893e,6f7b69bb) Z8(f1ee0c03,7e52e2bd,4dd397b8,731d977a,d58f1b3f,1c6fda4f,0e80a4b7,13eef8d8) Z8(6df4bcee,9ac41d15,d0f0ae16,4684c484,2baf731d,a11b1052,e0766414,dd180b1c) Z8(fe596ac7,077e0cc2,c789b6c7,aeeeddc4,3ea2686a,7a4585f6,92901bc4,038c1ca5) Z8(f321f50b,617d2442,3dc4b55a,3bec6279,41261935,24b3ccd2,1784f71d,3fe55064) Z8(6cf2fe99,9bf10249,b0173236,a7d623f1,4e27bf7b,3423bbe7,3621c63a,2ee4510c) Z8(ab573c0a,9c7b4f14,818c3028,32783458,fe54540b,9b9021d7,99705f44,c41ad29c) Z8(8a1f7c63,12a46625,2f4232d0,d389de5e,1f20fe7d,77dd21fc,bdcde05b,3a314ad1) Z8(f3f530a1,b9d08324,f7792abd,321bbd00,6c33f585,614c9885,291ca1b3,4b417ec1) Z8(d20a52ee,fe5f89fe,bcd96a7f,2b4a68b5,0a4dae89,eaf3c271,0cd608a1,ab767b50) Z8(f6d60f25,ce5a9f5b,c2642828,fda286d9,834fd0bd,4ee61392,a1b562b9,c1a4a877) Z8(f3797a18,27594946,1d260118,e5530ffb,c3eaa4e7,0e9a464f,22d3faa4,0a027085) Z8(0dbff58c,6b33725a,0801785a,4375683f,3dab76f5,8030259a,f4962146,57daf2c8) Z8(0ce15496,d76c5170,eff02254,e71e9747,c63c4ea5,9945c480,a457c807,5e0d3acd) Z8(e91e0b09,21ff1152,11fefaa9,a0e4dac5,88dc59e9,16d6ff7e,7b0f6d11,973c0441) Z8(50b11b9d,3e786ba8,94f407d6,5970f160,dc09f55f,3a437dac,b65cf062,2ded035f) Z8(e7bdbe63,d04a051a,81a1fc7a,03b42683,a08c6123,fca18bcd,0e1162f3,9d2810a9) Z8(08401a08,2c7a466b,fd1ca7bf,c7ca31ac,7f78b496,6b52e539,e69f5066,3e09fa01) Z8(d9da9945,5a26e38d,3685db3e,345731f4,2236f2c9,a5adace8,8de7858b,e6adef08) Z8(df5bcae0,28826dd5,290f1e6a,8ab7e8f5,1844d775,4931b4b6,98375d01,6589338e) Z8(29701874,b7dc826e,d094b2f2,969539f4,732f031a,4a066680,ab67eeb6,19a9fe8c) Z8(9a146fdd,1c73c423,022e62c1,5f076cef,a5cad330,fbcaaac4,a0c25b1b,135a6266) Z8(674094f0,4674a4ee,72a9ec3b,de017f93,74acf836,882ded2b,5302ed27,6ef0824c) Z8(69e744d1,e5a15552,3787e4d1,f87c480e,dcda61fb,f84cf908,585d1cac,e4705674) Z8(d520a977,047d7758,3e2adfb9,051ef955,e3bb7119,5a1ee996,8650a21e,9c9f9947) Z8(61c3df9d,b039a942,dfe25505,4b671736,344cefbe,7c15621e,b9f61ac3,5797fad8) Z8(217fcd3e,8177b05a,1abc7629,ef34f8f6,ac1346d3,61e5487b,41e8293c,ba79b96d) Z8(1fc33113,515dcfdd,c7789198,c090c0d9,b0ffeb04,2fed368b,389e3c64,263a4561) Z8(a79d7e98,85177e23,b7319177,111d9420,f41f9c30,d810f002,6d473ee9,63287910) Z8(f6cad06e,b31b80fc,3be4a06b,a2d7c20a,891acab2,b1087c04,00c9f584,bfbd79c2) Z8(f08a7089,aaa07c19,9a8ba0ed,0a6bf0fa,61b5378d,27e0ee18,64139abc,fbcdf9af) Z8(ed1ef64d,a138da4d,53ea0ea6,9514e5ac,6462d7b0,16bb4f18,aa6cf379,6001f094) Z8(6f869913,54eb1b15,1ce290a1,4892a4d8,0829d362,196a5744,245f8b16,7c4f1cc0) Z8(bda5c16d,ede58784,71321c47,a48e4ae7,f9af92f6,f245fe07,f6f53064,5086eb7b) Z8(84331ea7,c6e4e1b2,a08713a7,71157e2e,1519ce0a,e7776cee,3daed979,e08f65f8) Z8(46058801,04d305d3,307ffefd,707333a6,f776a651,4f9a3027,f36184a8,a5be4582) Z8(97b3c6d2,71e10ca6,49452f20,7039c248,2e188eef,a96e953b,5ec706cb,e5901d22) Z8(2e79104d,7e15588e,66843d03,9e306e89,11ab5412,69e967b4,8c815a09,fc1abed2) Z8(eb80c88d,10c2e53d,d5ef1431,c37d1da4,d24cb669,079a0a54,18839075,a9588308) Z8(26263fda,fd633a0f,7fe321cf,b0081acc,9da0c3dc,f9478964,fbdb5c59,d670daf9) Z8(76a3419b,04caa3ed,3bcae8b1,e6246c16,e118bcf9,bb836d61,b3d23fa3,bd544f41) Z8(f97f7c0d,a8aa7634,70c572ad,53472c5d,1655f293,1c2d8384,710025d5,802fb335) Z8(8533131c,73f7be7b,3f193ecb,a94830a2,d548173f,4bcf735b,6e9d0433,79f1f8e0) Z8(c1e7293d,68b8fefb,d83b39cd,ce0b4087,5be6cce1,a66866a7,b44ab155,af10a21d) Z8(a8018e18,ba3b13e1,163967cf,9b920be0,887efb09,a341faf8,cc0a789e,72a6fa36) Z8(543382a7,e72da19e,9ff9db2d,8d8dbb06,4fe6b95e,ba57a10b,e1ada9e8,10d3f8a4) Z8(0f00847c,477cdf38,c997a160,6492c252,aab46b5e,5cd89aa3,17234a4c,1592149e) Z8(e41d5b2f,8d0ec53e,f07c80bf,d336ffe1,56825f91,77bcd105,99380bdc,83ac8460) Z8(691c22d5,1a165108,8dbe1121,267549f7,8e1e0813,b5ca7548,8f2192b3,f2a81992) Z8(3117dbea,4f78dc66,bb85c626,2577b781,a4020ef5,80d64655,a716d23b,eb8c4132) Z8(d1884877,0ebf0393,4268d350,c657878d,212fe5ba,a08cb6d3,ffdb08cb,d00046f9) Z8(50a14b65,d4e685af,1ed971ef,e88ba4bc,8d904ae0,dd4ccb6d,b6c917d0,e37db276) Z8(ed2dd9fb,97e72c1e,77073528,3ccb77e5,1113f809,cf461cb7,17780b54,984766b3) Z8(bd202b25,ab09031d,e00b82e6,39f78913,16afb9f1,b2b2f38c,d955c760,47b9b920) Z8(3b63ea4f,435a5850,aa48a450,570766a7,3079fd9c,56c6e691,c43a3449,fd8dcd5e) Z8(caf4f624,6352b492,415625f7,12652840,0a399b9d,3b313445,748cda99,4c22b501) Z8(fc165947,e0ac4c2a,0a814318,6cb071d8,b4eab9bb,59508e75,2706cf8b,29235d81) Z8(6ae48585,814c0eb8,8644091d,49a7ffde,e1e83260,910b25b9,8cd18eca,34a6fd1f) Z8(3e2acbde,d12f448c,5a1045e9,46e85107,c9e74687,79ce1f20,a4027ef3,4ae94ac6) Z8(7521ace2,811c9269,a43553cc,25e5f94a,9aab05ac,6127a4be,d91c3712,d846ad50) Z8(de27e1d3,50b75b56,95cd8f8e,a1455a3e,85dc59d1,1b9f400a,d9071038,233d2233) Z8(cd6935d6,26545305,cb505560,05628416,b77da63c,110603bb,bbddfc9f,6a90502c) Z8(bb2e13a2,2c6dbff5,35c2bb1d,f0a94c51,3fffbe4a,21abe592,c0cd0a10,bf23dc2c) Z8(f55fbfcc,6318d89c,b8a98eb5,c667969a,c70b40f8,87118cc4,9ce0b142,c161bcd9) Z8(38ef5847,4448f8e9,255ddd22,c557e548,39a42e74,6f11874b,d7e3cef9,4d430132) Z8(afb426c9,34a0efbe,70fbf983,716b2a7c,3bd3ca15,56463faa,bc285e11,191e739a) Z8(76f4506d,7c1ec286,f356151f,82a85854,40536370,f2a0c0c1,4aba38b7,6980e9e8) Z8(117cc462,7be89bf0,edafb40c,aa2ac99a,5530a649,6d751302,9fec52c3,b5fe6ec8) Z8(37c8f4c6,42f074fd,e489d229,8e1944ae,a0a8fe86,12c9b6c1,717d0afc,539941ba) Z8(020043dc,49b30b5a,6ce30c9b,7c130719,85a92717,4d49d6c2,27093567,e5161ffe) Z8(2a88d168,be7e4e5e,127166f9,c43fc883,5ee37d6d,b9023d51,a8e5c36c,94d4bc6d) Z8(72d07160,95c03676,b933260e,89a5d419,5d51836c,167f2ba9,d7f8fc05,5324cf2a) Z8(0fa8ba41,12a91d21,14130044,8f28b23d,6a9089cb,e5b16f5c,71d83c31,4ae0a2bc) Z8(fe4a5bc1,f82d16f3,bf15911d,05bf7242,88eaef29,f0add78a,e5e9b9a3,1bcd9fae) Z8(4f20e3f8,31b011f2,8af87a6e,e2b7edd7,b1327726,2e6c320a,1279d8f9,e1594656) Z8(da293ac3,4609c318,d38d3625,def60e69,8181429e,35abd232,549afecb,8a6d41b4) Z8(a74149f2,bdfce6b8,8ee699b7,d784853b,6abbb060,1208d521,332d9907,b68870ec) Z8(e1482016,0dcde3d7,abfd968c,57979e11,dab5f990,895419fd,7f65df8a,a136c1a5) Z8(fe018a6e,aa687dee,76ff4d37,761cf1d2,76306ae6,e214f89c,84108f78,6aa0cbbd) Z8(a5706346,b28f9d14,2e5cf9a4,525f8902,ee8f57d4,bec873ad,30384b78,c93ae472) Z8(5d51f2a9,cce8ce56,8673894a,c98b2f98,e1bbbffd,8529ab1b,87de7613,e0ed4987) Z8(44d9ea90,1d1a7c25,67c52cdd,3911138d,1d003f3b,22cf6bb9,be499a67,a9a7ba99) Z8(3407f126,9e73cdf1,13177818,4c76b2cd,28315356,149e907a,b8aedeb7,0d4076f2) Z8(df61066d,7b06a5bf,87723a80,edee59a4,e2fb6e5e,eba0c445,c7bb6c7e,a9a667eb) Z8(e4244ea0,02f24910,a0f6036b,866dfac7,b10d8c96,88ccc137,b435b3cb,da1ba43a) Z8(141ddcfb,1b624a65,6222fe58,c0344625,6eddf2aa,743aa936,9dcc56b1,db0f47e7) Z8(b32655b0,fa3862cf,7b011e4f,2e261666,6eb85a17,43a4ce4a,be5421c9,4d85effc) Z8(a15ff84a,822bd87a,fdbdecd9,7162b044,02baf45f,a4884e7a,a04669ce,6c434d94) Z8(de6e1cf0,51de6191,4e1c72da,9cdb9887,f1ca58a6,e448a57c,3d620663,aaa83be1) Z8(43cc2fe1,40d0ea99,013fd238,069de9cc,f2e83a89,535907e0,586f6fa9,b5f90198) Z8(53b8beb0,2552e103,acfff366,ef717787,80462b8e,47416b22,40c8675f,46614808) Z8(7e3c98bf,6773b560,399020dd,e5056b9d,35d1dcff,2fa62ab8,53298854,99134ac3) Z8(ee668421,089fa296,17be0e30,41395bf1,56e98e53,2a8b9a4e,08680c16,230245ca) Z8(caec42af,57a5955a,4a317925,e42f898a,3cbfae47,4a4fae2a,a90a4269,9ba3b67d) Z8(791d58f0,7f59e538,c2789d6a,4070c77c,aa948ffb,256df53c,795c5133,e6c22248) Z8(53fb3ad8,016b8189,b08bd9bd,907e9d7b,f5d5a370,4b50af36,d35b6627,f16389b4) Z8(5aa4383d,af379425,404cd677,80a5b242,57e8988b,5a721895,37de7292,79eb6760) Z8(ad2f1196,1ba7de7a,a9cf354f,2594a260,6dd73dd1,b6da7d55,61b6933e,f67dc569) Z8(7744c7fb,ea3e93dc,7c2e9c88,5fa34eba,22b543f2,72458ccf,aee57ff4,6e8f75ea) Z8(41b46150,e8ae1768,69ea7467,6a49aebe,0828f2c9,3c658566,d76f9feb,22ca586a) Z8(266d2a22,73e51576,554ff29e,0690d264,5b0dfe81,b14ce557,a0f49051,b7e2fc91) Z8(ed5c8b43,71a618b9,fa4d7ed3,b418dd16,8faffb60,c010ce4a,20244474,c7f84e60) Z8(e7742d52,f605217a,ad1b67ac,e0c23c5f,6be426e8,b2e240c2,636fad7a,6158c8a0) Z8(c4fefdf0,57c30c5e,be4d08d4,3bbe2cb8,6cfb75ca,2cfc0cac,926add00,3805f10e) Z8(813ee7c9,0b3fac5d,6518a8a5,260daed8,c495f840,59bad400,6f76ebf3,fd29d22a) Z8(1187585f,2b28904f,0a376f26,2ebfacda,295b5c3a,63440b9b,c233ff69,5c8fac0c) Z8(375fee3c,cc6e8b8b,0c2ba223,f88b39c5,08647914,c9042699,258eef1c,90ae2414) Z8(7a2a9a6e,77030f2d,641d3748,a3dd9d9a,a0170b2f,6df1ff4b,64e440bc,12cb1997) Z8(6ed0b258,ec2d524f,5439cf9f,f0c99fb8,e2dd2ec2,39c1ea25,9ee8b0f0,680b0c0d) Z8(c660f792,943b0688,6f312529,80f1c8b0,db7f52f0,d1c832e6,d79fadee,469f6aed) Z8(5cbbd14d,f5565ee4,82fdece3,de65a828,6ff706f1,f68042be,2ecdc6e4,eeb79f0b) Z8(ea202155,5a50ff0d,e76f79bb,e04ee07e,b38c35c1,03d0d0d9,97edb2c4,c9ef5324) Z8(2a558477,bb4797d6,c22e28b1,b4f2d8cf,91acfe48,e18dcf87,e7d8648c,29243f5c) Z8(7682bb54,6328e8bd,010d685d,4285b74a,46b66797,788e4186,7781ea84,bcc6c1ac) Z8(96f7b431,c815cca8,482d2e98,d96dc540,5321cf31,792dd00a,aa0ff60b,ee90a2de) Z8(d0f32a40,08c297a8,48ca550c,48e323b2,6a89ee91,67e5aa12,4861bf8f,cff7513f) Z8(048a7fcb,770399c5,e7b522d2,427b7cec,a964e634,d888c265,551d1ecf,440fcf9d) Z8(ca731c92,822d639a,73433643,fa274f2a,0be7a07c,57d64d65,01d4c745,813ee404) Z8(fae17aff,e07d01e7,47f4318c,b1b90983,10410001,54401330,1cd1de52,45800d25) Z8(04d85feb,baf4db47,524e45a2,ad7bca98,e2d8a7ef,09a30e01,b206702a,503ee857) Z8(1c64036a,00977a93,ba0e0c30,59a86628,c926fe7e,001569bc,6c61dd0d,b440da7b) Z8(68c3c3bd,8bdab9c4,70a75e65,7c395874,9c05d288,4754fb10,9a4982ce,7c80862c) Z8(4a0770f9,f55bb59d,d3cad0d9,a8b8b4ef,f548fcd5,042f675f,2ccdba65,538c35c1) Z8(f3831e55,9a437fb9,fb25cc63,2985459f,6c5d9414,9a9e8192,d6fd77a7,1b1fd16b) Z8(abcdfb7a,831c8ff0,b5426fdc,ce4e9d02,cf859981,ea3697c2,2021c351,3bb716eb) Z8(4ef697a2,d20fa3cc,f3c94bf6,0952122b,40cc689c,16191c78,74cd3fda,fe001609) Z8(7935bb6f,b77fb5d9,07d502e5,8cd5cb42,2de9c18d,2c4c0d88,39346711,7db21376) Z8(427e80b1,ae328467,8fbdadd7,13deda93,4386788c,0250ac36,08ce7557,e005cc58) Z8(33006ba1,9ba11893,b22a6bf3,b6364aec,c311fa6f,f3414520,781912d1,d61a0b75) Z8(a98ed7a4,333b9a36,f2cea1fa,1379eed1,e3d465a1,afb25e64,2fa3b1bd,823355ae) Z8(748e7e82,cedd2e4f,155b5014,caffa6af,cce078ef,b2ad4cf7,33a7ef35,ba4aae7f) Z8(41c7ccf7,10a5973e,869828d6,78fd3370,e216dfd9,d7443783,7f3635e8,82044fea) Z8(422739b8,b0c0b7d3,c16ffa27,f6854e77,48d72a89,8c1a54ac,149816da,2b98d2ff) Z8(ad95b90b,41e945f1,5c33d277,d1b48aa1,b0862a95,04de73fd,563bb610,7fcc6044) Z8(96d5f0f8,84667dd3,847dbb8a,1e81c942,db76233b,f6bd319f,18ad1c64,f7d30fb3) Z8(b870766c,009d08dc,690e04b2,d3ba0eac,f648cab8,7836c8c5,2be2cbf6,a7c60b65) Z8(8d65ac02,01da00e3,d7c66c15,1f121d20,a89a5937,19bfaa9a,0866514f,b8c6cc7b) Z8(22b45632,6cb6f256,1736a34b,167c0776,2ad8c7c9,599acf06,e7238ce2,877aca0d) Z8(c415de32,198d6cc5,2d7263c3,b040144a,6f18606a,730560cc,19170952,4bda528f) Z8(5cceb92b,1761ea50,b55fa777,8ae6aaff,341bc125,5ef0a593,20921a9e,b8aa9504) Z8(c0531781,4d0896a0,df9fbc8f,7fb070f5,2e3bb085,6ad7bb36,2796a186,8047e1bd) Z8(92d66aab,10a8d0bc,aa091b18,28ef8002,496befaf,37ef27c4,35c27f3a,ac506873) Z8(c11b6772,c9b7d0f7,e84b9418,7e07493c,83887c4f,38826985,42842463,aedb2047) Z8(2bda874d,d59c8933,9acd3af4,bb3393a4,97fa4fb9,61415c31,c011d296,0e58d04d) Z8(43b9699b,f54459bb,ce7e9dd9,066e9faa,0a7d2429,f7d428b8,11d04f43,6daad4a4) Z8(598cdae7,11dc349b,d4a79046,69f9216d,bd29a456,b00044e5,9fc46399,507b5545) Z8(731dd1d1,38982526,2f6d297f,682a2642,1f00a584,405a5457,822312c5,c7acd1d5) Z8(d5b01ce3,39d38fa3,223250a5,f0ca7fbd,48dafecc,8376f1c6,a791c344,200e7152) Z8(f3c3ac58,a8cdaa10,03abef50,0afa4378,34a30f4e,5c8324e3,18dfcfe5,89714ca9) Z8(dee7fcbe,09817e5b,8dd236c8,69c99f3b,790ef06b,d87de194,8fc1d483,91396a68) Z8(66fae68a,5c83f529,7bfb3cf5,59a07c27,58e589bb,aa3ff8aa,969c4c2f,00fa0238) Z8(e00b3d1c,e17dfa88,77520d83,249cbc4e,ec9e44c1,369dcf16,47a18c76,c1697864) Z8(2d3ba74e,9ec0604c,dbae22e5,2b36bcb5,de34d65a,ec04ba63,b6ff9b88,851c4df1) Z8(f77c3c5e,96f0b55e,2ea90eaf,b0888ade,c46ec328,9b87ce73,23c489a6,0b0daf28) Z8(90b762ed,b93b9333,10a9bd0e,0dc08a91,6bfbcab2,a1064e97,ec9f4aec,0f1af0ff) Z8(a0c546b2,fb89448e,a6991627,44fd03a3,e2a538fb,a51b4f90,ac77c521,18d2ac72) Z8(2df88bb8,af617ed0,f9874556,f4314eac,00374f52,f25a1100,3ddcf5c7,75c90330) Z8(7cd9f8fb,86758dc4,116db27e,2975a373,5ae164e5,84bfa9fd,f6f7d242,0b71aa0a) Z8(45b52047,df8dd472,fcbe1260,6639f9c9,5067e0d5,ea0d5ec0,3fceb47c,cc52b7bd) Z8(9db9298a,583fbcfb,2fa80754,66f574f5,f4743d4b,0ac85039,a54bf5e1,721fd6ee) Z8(808893c6,2f767a2f,99af253e,7c50025e,0b28e49c,fcdccffe,48a97769,7bbf6268) Z8(cd8a3751,5e6346dd,6358793d,88a7e60d,ed180863,572ba2a9,00baa7e2,6db82c66) Z8(b8cb9749,d9a4bc49,d4906ef3,b04672aa,f9275db2,9ea72170,e83eb5e6,895554b6) Z8(a8befffd,22501925,370f945f,1846358e,ebc4e382,03b5aa8c,e0106774,2bc539fd) Z8(630d3888,4fd63433,fc615ce6,6e9361bd,dd8d0583,759be3b9,26f734c6,a65e0092) Z8(b26afcba,68417945,a7e70110,a74fab83,9e731d7f,0b72f549,f4d43bfa,cda64ddc) Z8(7c90bd24,c8cb940e,bba180dd,6295c497,660663dd,a8356887,87f86b73,17cba26b) Z8(041fc681,6e7acff0,ac773e7d,bb9fa0af,a60657a5,a6b75b61,a64ccc6f,b40bc174) Z8(2d6db811,c65cece4,33031f42,ccd68348,e01ccf07,e94f3ff6,b10bb018,5d57dc6f) Z8(23fe1134,ec55176c,9b8e1ab8,3d695069,726b7d3d,7f42b509,f4d35e4b,2376676b) Z8(411ddaed,f3fd1099,d8d01652,024f9894,c93be0fa,80f7bc4b,aab3efcb,42c47d3e) Z8(bd23daf2,8291b463,251309f4,987fb636,f710a9f7,78cd954c,d861f553,bddccad9) Z8(0dce5e35,a6d8430c,46385ee2,2540555d,456f1545,829a3080,5c30b85c,2348036b) Z8(a338eeb9,7fc1ddb9,0b1a258e,ccf57673,748c4cc8,83245191,1b682ac8,c720d96e) Z8(7e3c9463,bee86e8f,d6e10fff,63dbb030,895af1e9,96935c99,ed1cbcba,b1f648d4) Z8(8bfacf0f,60841f72,3b5f012c,2a50c0da,02166cca,0dff2d4a,f0e05f74,761c0f35) Z8(bef1d8bd,3f0319e3,479e1ee9,589a9862,ae09a958,1ef8126d,3f179d75,4eb6c16a) Z8(f0ae9759,0812515e,016bf128,1e866a4a,3c22d920,8947a031,58ba9c23,77e0d92a) Z8(b390f6f5,ef105868,74925c84,81ce322b,95eb1f52,d78f0be4,10eab1f9,0d9a50ab) Z8(34a12c9f,c2af4637,e9ac5cba,f9370af2,cd745f43,31479640,f434914e,3b66e8a9) Z8(37dc6feb,6c62efbc,2cab26cc,b9fe2898,10acbfb6,cff85243,897a29fd,cadd1e67) Z8(5a370222,03adb8c2,875b515d,43a7152d,1245ad0f,b6f65339,34698d3d,7aef7ec7) Z8(4f27104f,1d6eac70,d426bbbf,004de056,e33233aa,50ff3d0a,2291a7da,bf05dde6) Z8(76b5c563,a10315dd,acc1535c,7e31895f,058b44ca,cdcf5ed9,509c4d44,6098137d) Z8(d5617c40,92edfd1a,af205b38,27b0c179,28ef28f5,b76bcdb7,4acd6984,e04296a8) Z8(973088e0,5fc56642,7ab2c2d5,fc3b2904,52af82e9,a2c83474,5c71e660,e9a7db39) Z8(34cdb37b,78f97dba,e2289c66,63461839,5d053fc5,8be0725b,91f59f6c,7f86a1e1) Z8(c14fe5ca,b3c65369,22518361,95738621,c10f0499,a448652b,a8afc11d,d16961d7) Z8(b66a5f70,19080a0a,405df19d,f46700d7,5146913d,0c2407dc,07e84ae2,71cad6d6) Z8(2c834886,b17ff548,b9e9010c,75236b77,f09ea8fd,d7232e6c,91ebcf54,67f37225) Z8(065ea348,b571fb2b,99f8bf98,187c3c31,f2ba231b,6f13f53a,c80de4dc,8b9bda5e) Z8(2945dd4f,30ae13c6,47489ce6,12e4dacd,f053af50,dd10d007,0a69be6d,ccc6d63d) Z8(0ec5ec45,be9f65b2,02884af0,dac83f4e,1ac17135,8e33693d,f3c440ea,978f89bd) Z8(234aca2f,88bbb2e4,81aa4b01,eb07404e,da18e223,9a325569,262a9101,c5e2c794) Z8(28dbe1e5,242ed9d5,3e78c92b,3a21937f,4b0d6090,5416843b,7b88cc6e,13b37e69) Z8(1dffad53,95d46a3b,7da51012,2c229f71,619570b6,68c31645,6fa2ca94,c4780abc) Z8(8a048ef0,a6b61f71,571de6c9,d4be5aa1,5121a905,51e0122a,7a5006c9,f2e0d180) Z8(69448794,2da0b277,33b4bba5,133663ff,c8363ad4,af156697,6d1f45bd,3dfd994e) Z8(37fc71f5,948c2718,8060eef3,d6659632,7dc1266d,68877117,788c3af6,d81cfe7d) Z8(fccad251,1e791950,a9f5813a,0e484841,68571e42,404bb3b1,dee73fed,fd98a747) Z8(82a8329e,8c0ddb66,a92b8504,9a4501a8,0fe33f3f,c4b8168e,d9cf0fa6,69f4147a) Z8(377638d8,7b843369,9e8b4144,d4aadf65,be713533,e7fe2251,30d27ceb,885fbdc3) Z8(da2e944d,bc8570e0,1a6308cb,e446f6b9,f3c9705a,dd20b0a7,92bd4926,c1b45017) Z8(6d0d3961,315d24d5,b23f6fd5,4ef220de,50819509,d9341b33,e75204f9,bcbd1db2) Z8(a8265d03,92dd04a2,2e8c9d10,5f5c32db,ed5dd915,8c76a00d,3fd3958b,995c3034) Z8(273c7f50,51e9d844,e230f662,c9012cb7,19a7dce4,9ed40b7e,77b3d98c,7125dff1) Z8(49294e74,99d65720,81bd80a8,b6edf984,cf463229,738e650c,40357374,097468b0) Z8(5479b2c9,f50494d4,a9a337f8,b51ef439,43f820ba,a1e16fdd,dcf08419,bc987732) Z8(0ba6e370,52f3816f,bd0c2c76,9a2a5c41,8bd6411f,fabe790e,036126db,41f0b956) Z8(1862feab,b5ed48bb,cb4ae90f,60488345,8c7f29a7,e67be464,03094180,9c04cae8) Z8(c42627c6,8881662b,6c093098,d9dce969,9b8b8ea9,9840ee21,1e1ff856,79c8f543) Z8(e3c86592,3ddd1f12,6b99b854,f75e0403,750201b5,19549f7e,f0410f38,7a35a470) Z8(3fd2fe72,4f73ed16,7141754a,c28c15fc,0cc77608,df87b86d,071c068c,74264606) Z8(be8611d3,baf9df4f,6ee1b303,21d41194,d2c44836,6465b9f7,56fc23db,b6dcea6d) Z8(7b69c199,113bd6c7,12908219,e03b8e45,4552fef9,4e4bbb34,2081f51a,391a560c) Z8(e54aa52a,a6b6f679,f8e987f3,e58bc627,22c7e802,1ed7f111,7578b583,4e752531) Z8(8c448583,d13a8e71,3fa7e488,b89e7882,77227ec5,f25b17f7,b53e706c,8d2b38a7) Z8(1ac98f2d,e42443c0,91948924,c7d5c80d,1ef679db,0e09df7f,927cac5f,3baead6d) Z8(e082fe89,bcd2e3ba,c6cde42b,6e2fdd38,d39f1442,c195b375,d032990f,3163a79d) Z8(6f53b9e7,582e3015,cdfc029a,d76990df,96fb9107,839b9b8f,cfd31c0b,728fa373) Z8(352e12c0,b6de4201,8e2976e7,05c8f3c5,a92be1fb,946ede29,4a699659,55264d98) Z8(c5f7cc3a,4a61751a,fe0aa645,bce3c912,7af61dc8,f10638e3,dce0f4f4,5bc0dd9f) Z8(78bf2635,dcc0a319,044ed4c6,fc9ce7ff,13a62404,6f27fd24,ed2e33da,5ee6b90f) Z8(3b3ff878,8e7ce9b4,e3ce55cf,0d8644d3,2d9afb5d,58894603,d33a20f8,dbe1a874) Z8(f251fa9f,c030ef9c,71e213a0,3127c3d7,6ae61724,275afe54,4c06355f,ab35a276) Z8(8e7b83ee,85960e6d,6dc01534,850c2493,a84856eb,2de3ee88,74222cfc,4d4edfe8) Z8(86e7fed4,4834c6ba,eb3dc5c5,f743aa7e,52936042,f0b36adb,df6732fe,2ac64fd1) Z8(3ea35646,637c0206,d7de53b7,531c06dc,4a0eed7f,469c41a5,fd93bf63,da7ec99d) Z8(3bdbcaa9,85844f90,034c53e5,d192d7aa,1330e758,d55946fe,2a5b60aa,5502fb21) Z8(07194796,899a8acd,dd83543a,a3606728,06bd48a1,53dec2df,2c30d21e,84501cc1) Z8(f407cf9e,3e910bc4,905d3666,29b175be,c2c045be,997489e1,ae8ac909,5f982299) Z8(e52cb294,bd3b8108,455349ae,a0d62fc1,b888e0a9,00644d13,9e7c232c,411b3356) Z8(b80fd13f,eb91c402,cb145ada,815d071a,983de4d1,fcd7cc93,cf2be3f2,db71f795) Z8(600770e6,415b6fbf,6a3bf86b,85286400,cea9cc75,1702b8ce,2c6c2469,19a84711) Z8(c5e16f23,73e4a959,144fb276,29b1a74d,ff6014c2,fd494170,4a2bfeef,4754fc76) Z8(6b573143,56c0a817,6603f909,ae3c9fed,e71c58c9,c2c9eb2a,6b1fd591,468f019d) Z8(fb1fec5e,7aece16b,d66844d9,313708c5,dbc3a947,0420c8a6,38be94ea,5306637e) Z8(038a477d,e9956b1f,3aa5e583,06b8526f,ef23a74c,7bcdb679,29fd1fe4,37c2c0bf) Z8(f14d9e9f,22c27e70,a58cbb4b,2cc1e67e,25092a73,034c38c9,2703e03a,1fb21990) Z8(037571bd,822b5239,9a9743b5,8aad128b,52af2db9,1570b175,0d47c1fc,9d29d02d) Z8(969ab65b,46f441bd,43065b43,fd71e95b,2bc24468,e0436af9,923423c5,c637a033) Z8(97c6906f,fe9102b4,d3b27116,b2e17dde,ac7330a5,dd5006f5,c5f79e8d,ff35b601) Z8(9d0690ca,bc076cc1,d9901715,c85d2c01,b886afd2,0ee85e7e,83ba61bc,cc613661) Z8(f9d25229,8a185094,3fda3021,bc6d24d5,f3836fc0,74e426ec,6ead71e5,d76d2256) Z8(59a4229c,53ff1d78,c8a6dce7,f9d230cd,c4c96b3e,86610a65,0c04b8d4,9a6bf568) Z8(594cba1d,d887d560,d7add407,dcffb2f1,1db11c0b,f9c3ec7d,85dfa887,b6235a58) Z8(4eff3a9b,b1bc432a,7fc72814,41734688,c3f23d0d,d6108548,43071f8e,7fdd1661) Z8(1363f282,a20520e3,d3eaf7d7,bb46f7d4,8bd8940c,70029354,dbf4be1d,573e0723) Z8(746723a5,ca1b726f,53d887ae,7d812d35,34b3b81d,a7847d39,3616a7d8,d6cca136) Z8(2a335402,449cae80,6d4fc678,409606b9,464f6f96,d1852648,f99303e9,669e8a24) Z8(38dea4d5,01baa201,c2e4e63c,827c1fe7,411bdc1d,4f5a8b24,8ff877de,25cf642e) Z8(8ca87ca2,d288aa81,b4b7a793,d755b21f,217bb733,4b32066b,0167d08e,0c94a06f) Z8(33e31cf7,6c267976,6cda4a20,48e54861,a3faea87,cfa78099,1a1e7c40,92873c28) Z8(1378a966,31028e02,b57600ba,7b0a20fd,22def5f0,d6a3c561,416aa555,183acc26) Z8(bf3833a7,5ff2c51a,8c0d943d,a5794670,0fd405fa,9327c203,d48973ba,b1488393) Z8(9f5f2aec,e42de389,c7458d46,17ed2458,6941085b,0a4c2fa6,b65b0dd5,5cf646b0) Z8(e5ed7119,d26f88ed,1c90f13d,d59807fe,bc757228,17cd5774,a0b3038c,a30d3896) Z8(abcc4bef,21b14b72,f7f058c6,d318bf0d,59cc641a,5d2c7f54,7160e11a,a190338a) Z8(3fcd901b,11755aaa,fa64df7d,94aeaa9a,4203b81f,8e9d5942,978f6d9b,db35d11a) Z8(200481a7,e6fcc863,b6b74f94,ed177ce4,e9ace9d8,1dfc3c38,2a909fbb,1ef5d676) Z8(5d0644c8,643e78e0,dc9a3723,b428bba2,6d366f75,f0875b84,29d0125a,7b4561e0) Z8(42c15d07,c5154037,7242f4c4,b2e9877e,f3c4587a,510e7474,3b232715,15dbe128) Z8(53c0f731,006208fc,6a989bfd,1973b2c2,cadf0cf5,1b8ebba9,50aa441f,7463d86f) Z8(e8117b1e,c820723b,ea1ad5db,079b9214,04f2289d,a70d2433,dea322bd,daa698c4) Z8(25391552,baf5842d,10dc442b,eb20005f,9873732c,78886507,62a2cf7b,eb03da48) Z8(dfd0b5c3,ed4b5ed3,aeac8027,eda58084,cf4db008,f3c6ae9e,14a26c7a,2b8f8e9b) Z8(851a5b82,8d2f69c6,66305968,a19dc640,40d78303,881b9605,c28becb4,f5b273f3) Z8(faebf7a2,95cc3adb,6c36cd2c,f59964fb,05c1540a,aab636ad,6e8b9795,1d615fe6) Z8(409bb91e,aeede91f,bbed24cf,c743f6f3,77bab28a,08edb7f0,aec5da49,9683cecc) Z8(f85a2dfe,3c493b37,1c978134,47e829f3,b43c7620,b04d0e26,8983d70f,d37bcac2) Z8(9c68408d,9a423224,7247aa44,2dd13d29,7bfd70e4,106576da,5e909d05,70863195) Z8(097afb89,fc9c562a,dfcee028,a2aae63d,ecbbc134,9fc3e1c0,6c869625,09369180) Z8(d2521351,24583718,5ccc11a7,338e5c85,167bd3b8,12b60587,4a81cd2f,c62a65b2) Z8(9947768f,a1f85aa7,978c79e4,c9c7a3c1,15caf99d,4e17e23c,bf1701b8,6e17a9a6) Z8(97fdc967,343c07c5,c6fe559c,199ce32d,30ea04fb,6a851072,903052af,917857d0) Z8(a697e51c,3420da56,c110c00e,5e6e6ca6,62cdb86e,82f7acd4,b0c9387b,71b98c75) Z8(eddd15a6,7f526f4c,8937883a,dc39e74c,b73b07bb,998894d6,b5f2e738,c295159d) Z8(9fce1950,03d51b16,a1252325,fc928a75,e596298c,151c2660,bd3dfebc,650b938b) Z8(64f22a1b,2db39c58,71f3b3c7,2d33959e,fabd76f5,4d0e7ded,820bec96,6edd83d7) Z8(b0329c05,d63274ec,948215db,3721580a,3e9a128d,aa6ff57e,c1ed4fad,44b69183) Z8(8d67d02e,af6429fd,99e56677,ca5c1d2e,61d84f32,40ed9273,1e32d672,21aa643d) Z8(e21c2a8b,e9fed43f,dfcaa41e,e44a3c92,8e9adaa2,7ccaafec,720bb770,c50dd48e) Z8(a296afd9,2b4df343,ddf8aadb,fa177547,8f461442,bed699b6,51e77ed2,ad0440ee) Z8(b7915de5,c91aff8c,af71d87b,7240dc7e,0e1a86b3,e26e3290,1beae849,71cbfce0) Z8(c784df6c,65272cb1,a727c0e6,16ed3101,d06ae845,595adcdc,1b3e9d32,93dbd00a) Z8(08547516,4071b030,b86f985f,c0916505,2e3c99c8,df146fcd,166b4b94,475b995b) Z8(dd1c2e7b,682e73a5,b4c5048a,7be03d0a,67695a6b,4bf20871,16422f27,088afee6) Z8(f07ec64d,3f1c9b93,f759c525,b80b0faa,26c1ad98,c24036b7,036644bd,45b497d1) Z8(eff48d24,432baee5,13df1e26,6aca3a03,b79b229f,4c3ca48f,dbcdc748,a328cb23) Z8(226b8b56,b81572f8,cb7fd0f1,e52edaa0,3d40b3da,7d5c398a,d146c0ed,fa1a1b1a) Z8(46d71949,02bdbe54,55570161,5a07d6bb,0b0f0326,696a0e5d,0b314a86,5b5651a1) Z8(e17d4073,8fef5c4c,efaf1de7,36a4fff7,e3e5ba78,8a9de13a,8cd68d43,06854a80) Z8(9c227bb2,cdde55a2,0c7088b0,e77ad698,bef5915a,fd297e4f,615cec36,9a7d3608) Z8(0e932ce2,03965240,21dee819,b469dd02,afc106d9,0fa98ade,c7bc424d,27cf27ac) Z8(e71602c9,39cb4800,9be30796,93e588da,851fb1fa,843d8ff5,a4166d67,798249c5) Z8(659eaa0a,6d3cc401,3e89ffb2,e489be58,e2bae238,95ae99fc,68bc4c89,0cd48280) Z8(70d4e962,d610bfa5,5e81bcef,f7d70f40,b6d468d1,10ed0bbd,6ff4fa82,06bb98b9) Z8(5ce28b99,a8b6cbb1,6047b0e8,2a6d1226,23e43a43,c5c334da,b25b547e,081a8a54) Z8(7f0f45b6,85196964,918a8e43,a7865a5a,0396324f,a1a19866,95234dab,0257dd43) Z8(f102b4cc,cdb51882,8a0d6719,560e376e,1aca28b1,71860ada,70f1c98a,32168f87) Z8(d98527d8,13d1e00d,9e2ca477,5536002e,173021d3,d13267cb,5486b0c9,64782f4e) Z8(4b8cd341,74213c29,13aae1b8,6e7af832,aef0a20b,27885e0d,b00309aa,dddb790f) Z8(f9282e08,af91cf97,aa23a82a,a06ed6f6,c262673c,0c5fb6f4,7f09aa6a,fa648466) Z8(609455f6,cb1e2ee7,570a95fb,cca80795,27bbff0c,96c50c45,08745d4b,d6d7cba6) Z8(bca1727b,ca128b94,c39f576a,05fd8a12,7b9044c4,8bc9eaa2,ed67cfdb,35fbc1d2) Z8(42463a6a,34d59a1b,66cc711e,ed22b460,75162bbc,fc77d87e,fb26a033,09d05255) Z8(9b035d08,1665b5a3,69950ade,1a4c556d,bff16be4,a9fd0f4f,b23df377,bcbdcf0e) Z8(9a63bae9,64857e63,628319fd,0ceffdca,b481c25d,424a9b50,2935571c,58349d5b) Z8(3de9123a,62c6a0f9,fe008384,9a8a5273,287633b8,b6ccfa2e,d4c46cde,5c16b842) Z8(dd360c3d,aafbded1,6c16afba,530fb1cb,ee9ee3d1,494fbb02,12d836e4,325433ce) Z8(4bc0c24b,9163842d,6509ecdf,8c83e30f,23b138a4,2e8a30f2,2676a5f5,e6be4d96) Z8(7f08fb28,44fc781a,b27c5cc1,b0d92839,11278928,86db8e3c,93cddb58,570d23f6) Z8(3789c881,fff73036,ddd28685,5d193d3f,247ebda2,838fbe01,1f3ee707,258f62e9) Z8(d2dea49b,b195f39a,a78a72e3,e99c1353,dda894ef,c9375eed,f5722ade,5b127aad) Z8(1ccb7ffd,2e311775,edb307d8,e28cbabf,85723772,3cd8aef3,8f875112,71699dbc) Z8(17134dda,7f4b58c2,e8f91e60,e4714f94,32aa4fbf,36dd2933,21a791a4,d080dd0d) Z8(35b32f29,a94cdb28,51b37960,406267c3,c63f3a8a,8f4636f7,d4d80fc2,ff8c8a1f) Z8(fc6b098c,b3c0d580,085d14a5,b94a91ad,fb48a262,9f5d2d2a,f1b35da2,9a469623) Z8(457860ec,aa3a9767,8dfa267b,9323a879,9cc8b0ae,494255a6,a774b15f,09d7681d) Z8(4d6b5876,889ee15b,6f8516f8,16ed5194,5060ed45,a259cb94,e4d9f15f,906c75fa) Z8(c74a296e,02f248bb,ef45f840,e6a73cac,b352c85c,158c0a81,8d48683f,41691803) Z8(0655838b,1a545ee6,3c877d32,42347994,1c1e4692,910cf953,02846c81,fc3c8ba6) Z8(8179a55f,a883a996,d0b38871,765d2d74,0f859d20,7b85903a,bd2baac0,09e45481) Z8(17acb4a2,298652b3,578a4684,0bac8bc6,142a72be,cb1699bd,a04f9266,60ade071) Z8(ea6873f4,b1a0aad3,873e131c,94de6524,268d334b,9032513d,fb129fc7,e65881c3) Z8(f62f1c71,2e0718a8,874a06f7,ca98e056,6a366499,1f06733a,bfdc725f,088c23e6) Z8(bb8aa694,8209632d,58b3d28f,3b29f32a,bff4cd3b,d7af88d2,555f8230,3c88ae1f) Z8(3d6ec30e,e2595c56,a5a90145,8bbeaca0,cd4aa45e,899be9a4,eb2876ba,b6067b95) Z8(523f4d95,cbc1d9f9,6799fdfc,7c1d879e,106ad7ee,4f7807ab,1d27b7e9,3adb995e) Z8(2fbfdfd2,b63db525,c25c717d,3f46b735,3662dcdd,8441ed05,154997e3,5cc9259b) Z8(c5c363cd,210f448f,5affc41d,19a8bbb2,fbb10a6f,7c11ff84,0686b7ba,97b39208) Z8(183f8de6,c7b8ac27,a9b577e3,0ec91dda,e8aa64ea,b6519c39,f40cdf0f,3620d70b) Z8(3d5e76b6,c6ce4df3,063d7ffb,aafa4dfc,9108ac91,a994e6f6,536672c4,6dee9547) Z8(80a6a047,3021444d,a74fa06a,83bf50e9,39f43a20,7109a95b,1c3b0382,20242b2e) Z8(afeb3d7c,116e134e,3474fe93,f3cbae10,7b3d4444,f90e5056,ca8c974d,e51c00c4) Z8(75cf5c7b,afe40656,f41d4674,3c094201,2afe61bd,a97b85f9,3091073b,2f502792) Z8(870685b9,36e03878,d2d27968,b7e1f389,9df3033f,1fb23834,ff943d6f,71c7e4cf) Z8(d4a76e82,4431ce1f,2d2e9cf4,47a80314,de994e26,a9e41245,653387fa,21bae49a) Z8(f893d9b7,6ce4c917,4dc2e153,76241b62,ddc91be7,e59ef086,266b28ff,da936d5b) Z8(efe83c35,62b8c3f1,cfd0a097,490f5f93,a7cf1b12,54cd9c40,b0f6239f,df24dcf4) Z8(a27495e0,77ea6629,b702a2ae,96cd05b2,d131ef8b,5fd0881f,d83350a6,2fcd5d09) Z8(4efd6f88,41c6cfad,52d2ab4d,bd3b4077,b34ae921,56bb3b75,b1181e7f,a2fb4a37) Z8(c3df6255,a83eada7,e9f45fc7,f32993b7,53bb1ced,c06b98a4,b4e7dde4,01cd762b) Z8(10cbc766,3a3fa42e,6a83c709,4d170f45,8bec2394,f71c8fa5,17dd29db,f806542d) Z8(5b46049e,dd2e0de7,23933a96,80df7778,1e412239,b2919465,d711538f,1057e2a9) Z8(9d1bbe4a,82b19b48,77b38f12,8773ed26,1580787c,64a9fae4,95c9ad0e,98e06332) Z8(0cca196b,30258abe,927b986d,63847ebd,ec1aba78,8f2f2d1f,68680eae,06d37c0f) Z8(36283fbc,f3e619ca,1b662364,dbd0bbc2,43ece335,536602ab,6c7db599,795eb3d8) Z8(06bdbf7c,acf32bb2,a4d07a76,f85b1f44,829e0922,0080f5dc,58d2b4bf,7daccde0) Z8(cedf93d4,fd436441,cb6c99c8,0bf04fa4,f35abe28,a6e8615c,50d95d9b,19738d89) Z8(add2ed8d,f1edbb85,64fcf0d0,cd394ef4,11e7fc02,74d55892,2c3c63bd,4bc8db33) Z8(714ff7ac,e4ceb5bf,34d868e8,1fb4e049,da4bfe3d,446d0142,11361852,857e1bb0) Z8(0af67d36,01586305,af4cf067,1259b26d,15a4d609,8bf7cdae,e3d98955,a937c3a0) Z8(29926dbc,e0456ba7,a22369bb,4a56e822,f32be0b2,a5b50ccc,65451b7c,d780995b) Z8(19511fbc,880e1eae,1bd39297,fb6ba5ee,f25a1179,9bef1245,10144e2b,0efd6fe5) Z8(833b325e,87c9a5ff,2da23382,a49e5d86,012f4b11,6f285c21,a9dc33f7,09d64f89) Z8(21f8c3d5,a8f8879c,97065c50,15c2ac62,985b81cf,f91a22a2,0f90c0b1,0fc2c0ee) Z8(5327ad8e,184313c4,39b0bfea,05ac2020,f034ae2c,0500c809,b4723f45,0c2869d3) Z8(a40c4f1f,044a434d,de3ff27d,3c434098,73cb45b4,ed40fec3,ec6c2085,42d44786) Z8(eec9c6ec,ed9420d1,67838913,f2417baa,8f75a300,c60d07d7,47464a95,6bafd81c) Z8(cc04a724,31c9adfb,c2e90837,7f2dc70c,4fbb31d2,8b5a844f,483ac05d,1f289c21) Z8(54a1d59c,e8017c14,895de30c,e3c8a540,6292462d,7caf60a5,93c583bc,6495347f) Z8(a00b99c5,58438d0b,68a47a9b,dc8fcbdb,816adae6,ac4e2e37,2b3976e1,0de1b5a3) Z8(14f0a5a4,e9f002f4,8afb6d3e,ce9f24db,e2216fc0,3c22d43c,e2218797,847b081b) Z8(e406d4ed,a44250ca,406fdef9,ff7a52a1,4ad5d690,ba096ded,2d9ea549,aefc100c) Z8(f85c6271,c985aa1d,ba5b1057,15553e55,00a4bfca,06b41a92,5ee1df49,dbdb4c0a) Z8(5d285860,be654eba,ab9be541,58013a3b,e64ed514,6e033c73,071f38a1,cb4d5d4f) Z8(4ae864c1,9cbd4dc6,0ae326ae,e82123c5,f543e1b5,bafc3915,f7cfb396,a2a507c2) Z8(8fa5757d,07a8f4e8,dd8f91b2,36a4445c,5d6169ac,0bbbd75b,7b09c68e,b315a94e) Z8(cbd71bed,e739ab7f,2056dead,e7abeac0,593eaeb6,99f5e674,474bb1c0,1e154bd6) Z8(30ccb976,3e59222f,546c6bf4,6a2ca1e0,b0e803b3,be483c6a,b14d130b,76ef2f06) Z8(0491509e,7fdc8bbd,666c09b5,53ae470f,0cfa9c44,291b6684,5b8ebb1c,7abe4a32) Z8(022978d7,cbbd4dcd,3424faf0,9533af8e,6f3fdd54,e49c12cd,3f7645df,45555bdb) Z8(f8ff5c01,790c88a3,0fcbda5b,da978b72,9a362fb0,27b6aa33,7d8f9085,f06eb674) Z8(73e1b94f,666bbb3a,7224e99e,eb3fbb3a,782453f9,fa99d81b,48ff82fa,31724d5d) Z8(55420e5b,10be7814,0b05931a,0ee57d89,d9a8fc8f,27ea620d,725f81c4,689412c7) Z8(f3e0d55e,ec0ceb4e,43d19b5a,78712960,e55d7475,9101031f,a0295bf1,15a3cc47) Z8(6771de93,e85048ec,36315d55,29c48686,e316eb02,556df11c,75262f14,510e7ff2) Z8(5e497da1,7d54dd89,09768bee,47507c2c,b127c090,571e8279,5d297f96,3081ad86) Z8(4cd9de95,ecda9711,43a2cfc2,ff3c57f7,9d7060a8,90a0e465,0fcf9f79,64e25539) Z8(b322825e,352b3b0a,3bf45ec8,c9bc8448,8a3653b1,67bdc5f2,7eb67b25,d6cf372d) Z8(8ad8dd10,2692051e,1506e3f9,ade2d90e,5073c07f,b8a22a29,6f51dc55,61450660) Z8(4039951c,4d30b5b4,b0b6019f,e077d3c3,586d3872,886a1c76,4d58a51b,c9a36cb8) Z8(ea5e6e61,5aa1bd7c,6b5ad8bf,b4de893c,d5c64edd,352f7d23,d1f02741,a0b99983) Z8(3af7d32e,94a44876,ab086d42,32c4ae97,abd4fb4b,7c8d7736,7a2dcf1e,306c23ad) Z8(39053155,d13eb794,35792abf,29681628,6325dfa0,59e393d6,071b4981,c61b9d9d) Z8(a9bd42be,73cfeb6d,0bd84d6a,9f6255cb,42b187da,00a88c75,879c5988,9802d536) Z8(e172f101,b41b1d3f,6f9aa4bf,837c5dee,d8223918,991c4caf,90b88399,fc43be5f) Z8(4114826f,e40e978e,a0ecf3ec,3eade0cf,97ad5ec7,b5f0856c,e6ad357c,c595841a) Z8(94f42170,f95260a2,3967b320,9a2dc0af,35057e54,20849449,5f95c718,71c4f319) Z8(c3a6bd6f,a3efa109,23a07f0b,a8910025,786235ca,a696fdce,f9b4d91a,5699115b) Z8(9e2beaf1,4ecc1871,8365975e,7afe32d0,632359a3,bc32fc44,4a127650,9f1b1f0f) Z8(887c5bd3,99fee53b,f6751a08,7dcb26b9,13d13dff,1e62793e,a166fff6,1ab02ac3) Z8(473db31a,65cbf1e6,b403a01b,a9d1230a,0efd35bc,1463c090,a4edf762,7bf8e15c) Z8(0ec24d96,463758a9,2f11b148,780ad4a3,c1c21673,7067b6c7,e377c849,817daa29) Z8(eddeb113,f5c0fc54,fe8cac65,75041442,eb40fb4c,03b40842,0a0ddfd2,b9469bbb) Z8(1a786af8,53dc0fe1,ea8be441,59e23291,88d14d32,8fd2fb6b,be89288f,c29d9054) Z8(f3fcda10,34b572d4,2a8e3df0,4f1bd03b,18f89da6,b006b029,ac4c11cb,90dcdb0e) Z8(1454bc44,5e691670,3ebf3c1f,467bce1c,a2e0545b,34ca69c1,e6455722,4c966885) Z8(43132697,983c2f66,d4721a73,eacefcd3,afb16394,25256f02,f09882c5,f17a55b4) Z8(8c3b47ed,12ed5fe8,32305940,eda40c49,55f62f77,823a07a2,4684878c,62ac5afe) Z8(1e20490d,5acbd26d,d5c09ec2,3f2f2057,ad00b7fb,038841d7,c04a356d,c212d7c3) Z8(e7b1fe0b,3aaa1cbd,7c66ff13,26fd10f7,0068444f,8844fb98,b00b1f5a,978023b0) Z8(e10b718d,8a67ac25,68ee937a,4b6e20e1,63afff40,6811bc50,cf1b67a6,9cc42d0d) Z8(63651dd7,ceac0cb5,eeb2f6a6,eead14c1,cb5fb6c3,bf04e41c,b31acdb9,3d9d44af) Z8(7f0e4be5,208ebb48,48d1bafe,3d2064d2,21899d61,515ff9f0,36bb2544,3e6886e6) Z8(51cd006b,fa42e770,4be9d286,04887843,dda9e5ac,057f4d62,194f70c7,1836812e) Z8(d539648b,02344fa5,f459136c,d0968987,7ee79cc5,75d3327d,70c95959,852d05c4) Z8(682c21bd,01e44d67,0cedcb6a,19c2db78,68021beb,f843afdf,a943cd81,bb092949) Z8(ee7281f8,f04980f7,6efaa7c0,2184b9d4,855442e8,21163fff,b5e20a1c,9b5ac6e0) Z8(b9d17a61,fed2ad0e,60e33d63,d8717f7e,137c1660,0a4f017a,1ba7dc50,190d48e7) Z8(7ec05bbc,579179db,51164d66,754d4dce,280a73f8,3e6ab416,51888b53,98709578) Z8(a80611ee,e7313678,d47b314b,57c4dff9,4a7b6119,e7c4831a,37da31ed,b857631c) Z8(8b774a44,5d3982a3,a89380cf,99c79f51,470f5e5e,7c86872f,2d502ea2,caf7a7a2) Z8(43ce8827,600f8280,f5948658,eee77e6a,9265fedc,d28517d8,78f73f60,d7827e5c) Z8(9922a2ab,d7ee9a73,8008fad0,20ffdefa,425f51df,1a45afe8,aca9c4e8,88b44aa6) Z8(2483f318,d2137ddc,3c40abaa,a1807b70,4f2ab79f,b90a1efb,06fbb84b,1111d43a) Z8(9777ca11,82e6e9a1,e7874ff4,a1760cff,1e9db818,7868d3f5,fc5813da,d08f0b59) Z8(ac8207e1,95a6d918,29a0fe54,c8ad0eaa,54d2607b,30717cf2,ce40d167,4ed7a144) Z8(565b8223,0d9c5feb,3fa7dedb,9a948f29,dba50bc5,befcc145,65b2de36,1ff19bc9) Z8(f459d989,755fb0f5,b5ae55d4,8672fc6a,595e607a,13a95faf,51304f18,cbaf5aa1) Z8(e7f5a113,74c87b23,c7c801a4,b6a802c9,f9a21979,ace184c8,f84933b1,da54cd45) Z8(99a6e139,998062f2,7d517a6e,67d50696,a065d5d6,7208edd1,6be0783e,fffd1ffc) Z8(15ffa111,cd5ad73e,c2d38cf1,0c984a87,df3fb69b,0581f8ec,612efcd4,f90e191b) Z8(75cc8ad8,d4b13fca,81b23591,94491c38,8e42a03e,110ced88,a4a1af57,8a8d3acf) Z8(edadf2b7,625f0b76,6f5e3ad7,61e6b6c2,74b43370,7de92545,56898f7a,1340cc47) Z8(a3fb976f,4f18359a,80a0f3a9,b06328fb,1ba5a3b6,e56d5138,216e9cb8,104763d1) Z8(75c51dd3,4690a8c0,65ab06de,d7cd7058,be6e0a71,83a2d6d9,69d9e80f,9fb6a4ba) Z8(ddce7487,23c00d0c,f48d7a6f,21249081,849cf9f9,5b2c4c68,16b1737c,e4ae4246) Z8(daebff05,6b6b2059,8bec06b3,dc582992,8a993f14,facea004,b727a3d0,7ed11df1) Z8(42c08e50,d75f3b24,657ac1d2,b709864c,eaa24286,ea7048dd,f5981974,d9360fb4) Z8(1f5f09fc,66cd94e0,c00dc021,c9febf13,a546bbf3,40eb3682,9f1ce2b5,aee96554) Z8(37709216,e260c583,df1dc93e,eb28757f,94a2f5dd,48f24d27,b521cd57,ff964711) Z8(84fe3992,632ab8c0,485dea16,91bc3f93,2b2a3302,91ca86a1,12899699,11698ff8) Z8(db1ab4d5,7abac182,085e216f,3193740b,ccee9bc2,a080f447,56cddb6b,8d1999b2) Z8(61695627,6cca0d9c,26946db9,b9109846,4439bf13,3f4ee2b9,c0dd103c,a1aafef3) Z8(7d48fed7,0be4ff06,fee86825,816649ba,e837dfcf,0a8ae742,4f46adb6,d22df86b) Z8(4900160a,c07b974c,b3eeb184,897c32d8,695b80fa,26363171,048ccb1d,8a50f92b) Z8(d525f728,c4fe4211,e77c8cd2,932fb704,c3ac7a92,9aada34b,cf9e34d2,51ccb430) Z8(1df291e3,4085466f,90ceddc0,dd613ffd,341b40bd,72bdd279,f036b2d3,546f8a30) Z8(6742f95e,a6d713fb,f5e090c3,4ea7ef8b,e4754b7a,2fe223a6,0d55fd0d,f5333090) Z8(6d433a27,a2804aee,3e2e193c,efd269ad,70b1081f,78d7df03,8f302143,a69d5ba9) Z8(71d6bf30,7f8e78f0,f90ab530,f8d3e7bf,15b06396,3cea57bf,9ea2a66e,ed77f854) Z8(f8f9ccd3,eeb62fe1,482cccfe,63afa43d,7146be0f,fd64d0b6,d8b4ff1d,67a476ee) Z8(eaf19d53,91c7457b,a4b144b9,62246b05,12a20092,d1d1910f,9325793b,50c396db) Z8(bd9c39e9,41c68662,766a7954,ce27ce99,ab5b2533,db5d10ff,f375c85d,bbd618a1) Z8(d95c4f71,f732cca2,5f849e74,1d94bed1,155b952c,accb093c,54b46750,0004f1fe) Z8(707c7c76,bfc8a7ec,9623e0cb,85dad892,b1ee574e,0487f2b0,43a8e139,d0a8d879) Z8(f18a1d32,35292a02,6ad2d4f3,9b1e59fd,4a2bf337,a015b197,f3ae330d,55394851) Z8(d8865bbb,fa6c4019,a5b3aac3,4b23c1ec,6bf91d24,9b96be97,e5e99477,795f34e0) Z8(20e99d3c,d574bcaa,a7a8353f,1e681d5c,fd2dd2a9,023ff03e,c31e940d,be9e65b1) Z8(2f5eded2,b393c45d,b08b0cec,52604c56,8f2bfbbc,2783f8de,49bd7206,321efbb8) Z8(1f70fe19,2230c0eb,87dbe674,29003f53,61cfef78,655e6c8e,329fc38e,cfb9d4d3) Z8(863ef892,7b73cd2d,d9e0a595,e6e74e85,e48ec654,4ed0f47b,ff248243,6a430c0b) Z8(3fd2ea1e,e6982c93,75a07c23,a59b5293,8548b069,633cecfd,925ff51f,8adedacc) Z8(8cb6dc8e,27665aa8,fb1dd34b,1066f12a,7be8843a,eb4564f0,f2feb11c,4e9c0620) Z8(f0a53da1,65918ec1,9cea9a28,ea0a9f92,d19bd358,1b528451,57968b4b,7a4175b8) Z8(d9271135,4cd480ec,24c0a42f,07f4095f,b49a3afd,81206daf,eb30dd7a,37eed4ae) Z8(e6649320,6e6e316c,d3ee4178,01fbd5cd,0a6c1bc0,f4487894,c2bf66d8,29bd14b2) Z8(81b94ae4,702e3775,7b10dbbc,1adfa17f,8f39cfa9,45d4adbd,7e2aa2f2,dbbcf13e) Z8(11708b3d,d4a5dc58,5a6ac2e4,a4d4c255,5856e203,589cec29,c6cbb52a,63b2fd7b) Z8(56d96df5,a64e734e,1c1e5c0d,7b9e95a0,61ed13ea,984064c1,947d3c06,619a6be6) Z8(e92cc32d,0ee321ef,0abbe35e,91233634,b24a5bca,7e25ac90,bc3789c8,3df21ef7) Z8(4978bf3c,c7be7c43,a6d66904,28ca1ff4,2ac602a8,f2bc8d1c,5c7e388a,5cf9ccd1) Z8(8315854a,16300c2d,c2bc7405,3b88051f,fe5c74d6,7befd1c0,6c0a639f,e0fa28f8) Z8(0d110806,7d0e3c4e,953808d1,21a59a3d,f8c6ca37,d2d44977,6708bed5,710992af) Z8(6f65eee2,187ecb19,aef96e1a,e166f1d1,eec34c3b,e40a1b41,3e0d8c2f,d10e6cc2) Z8(78719c90,60078865,08c49261,4d0f32ef,df1c765d,ba8cb146,35ce5992,6c9d6703) Z8(d8cf3599,3587b144,bbd26ebe,cea29740,ac8e94fe,aa21afe0,bf042ed7,7774bced) Z8(b813b580,1e20201b,72c4fc5e,75f00619,d55ae56b,2f3d3318,1364701c,4b1f42bc) Z8(accea3bf,1cea5897,4e0381e4,84ea2d73,37efb700,ae520f69,4f82d598,dbbb72d6) Z8(7ec19c68,ad64745b,a17515f3,92e45e0a,0f2ce7da,3b843dae,ac4f1a5e,cbf960dd) Z8(1ed5bcb7,1a8aa82d,10fe1cb4,1458991c,80cc1713,2e21d15f,0e557163,36ad5f9d) Z8(281ed812,972cb8d5,4c3c4887,69429482,372b0461,06da6830,6cbffb94,c5c9b8b4) Z8(f1c1b34d,63f8b7f7,783a5100,fefabfd4,67b8edfb,86015b4a,0ca212a3,38be2f32) Z8(9518f10b,93ed7534,b3b4e499,0abc36df,dfbc5cac,df8a9fcc,16cd5b3d,5b9628bb) Z8(8cd4acf8,d6698335,1da137d5,91870a8e,4497598c,a67c1423,349c0a0c,80399fee) Z8(591d2d24,0f9ab945,851207b1,a5ad4144,a17e9723,25a81a91,d723b9c7,feaf1f83) Z8(1e482207,d8f94106,2bbcf6cf,95bda6cb,18eb481b,893a5867,e0974425,443006b0) Z8(97f7d527,e8041309,3c93cf8b,1374ed0f,d56f0fc4,d9e9c259,ff5a7346,933711d2) Z8(3eb12e05,cffc104c,33fd5576,1ae6f855,d9f6344f,addce3c1,f3e8e5ff,8fcf5b5e) Z8(319c7a72,de69d9d7,283e1d0c,fd9bb0bf,18a0ba57,b4dc1b0f,a08ed831,81e56986) Z8(29597619,a316fa62,6dccb52b,c94d5b71,959043cd,64639412,88880a3f,a24b4f07) Z8(b09cb99f,02667d6b,927d4b63,2e5f12fc,490c397a,157ba9ca,3451f25d,9f74864f) Z8(dad2ef0d,1ecb3701,c9862554,65c1dd61,af2dabe3,1f784d18,700c40a8,c539187c) Z8(7cdff604,9146d965,5559ca84,5d96a815,8899e85b,4fc9723a,8239b5cd,4184a1f4) Z8(fb179d49,8d1511d6,e2198d02,44100e48,69fccdf2,9c93adc8,e3a7f956,970a41a1) Z8(81ece8cc,f80ae81d,bb02901c,967b4f4c,18d69cac,1ab85b1a,d7910c7b,9832588c) Z8(46a30f68,2df03633,57621bca,94595a0c,3538559f,11551d80,80d6443b,8a90b44f) Z8(e685b19a,8b133050,219eb233,f3ba8b38,b6401b3f,5130fdf5,3a0a8f71,ecdc4f5a) Z8(75e22f67,ec28a16f,dd7ec3d4,8884d3df,c6021582,79205bd7,8c29a887,20022b8e) Z8(bb79bf2d,61618f97,efff8f75,c175ed29,81fabc2f,90a293f9,1f28f5bd,3093824d) Z8(65453358,4b12c895,f49cd15c,b4000661,0bfa83ee,51811312,f7e0a2ee,4bcf2e00) Z8(b7ad4f40,bdab0323,6c6cd756,bad454b5,f1a7f1cd,86352a2b,1f898da5,ecc02c3a) Z8(ea6e82a7,ac9ce282,cf8e88a5,0d8acfeb,7f301c7a,88d383bd,ca6435eb,f623c5f2) Z8(19a975fd,3a76cdce,786b94a8,6c965661,23b558a7,140c741b,debd643f,b11687d6) Z8(d1e764f1,620d1e31,d51a940c,8dea0fac,5cf770b1,508e70e0,7be1d8f7,5dfdd635) Z8(6e259b7f,11f128f3,e92e6487,fd8f7800,058f5841,31570e54,72295731,f983aa5b) Z8(e469432d,960ff56f,fb32e061,0c5bb07c,3b465346,e28c1082,32de6edb,1805cb5c) Z8(f1202545,ab555219,d7fb931f,640110c0,c54a617c,1eee7ee7,72c1bf7a,5e33c49b) Z8(84c3a776,8df9cec2,ef38d18a,69c4cdb5,8ffa4896,1ece70b0,4c5eba54,f31cc291) Z8(ba7d2af3,f725f0d1,c90d5dfb,d3892912,1a862895,7e588770,a08d15ce,2eb668c0) Z8(34efaa96,fd7768ba,811d73d1,83b974cb,e4e6dcca,e34f2f05,43071c43,cc3832d1) Z8(098da0c1,a14a448d,cbd7e3dc,aeacd0c4,2af53153,489aaa7d,a75b1ea5,b7ef4f34) Z8(71dca9ab,a8abe881,321947ca,dc544137,98fec1fc,d56ae93b,7cff14e8,a57d7c06) Z8(555ed278,8ded75b7,6147f63c,0a9ee22f,6eeb50d9,4a95f587,34b0ef94,45829bc6) Z8(2c121812,1d9781a9,555fd93b,73361733,3b191dd1,a2cb6cde,bc9a14d1,fdcef086) Z8(5cfc4d59,632cf194,a05db085,7806a933,fe954323,e82e5283,2e8b78a3,e6fc100d) Z8(7f6ace3f,11f20fb3,23c6cc78,94da158c,fbdecfb5,77ea44ed,02535bf3,476d6a1e) Z8(64d10835,d32b30ec,6ddefdc9,2fea6435,7471d352,03af6be8,d538cdba,0821b04b) Z8(29638181,24db0337,c17014aa,41cd5233,55f6d445,d5172102,ccb4bcbd,5e9ebca2) Z8(5952262c,66793e53,e835834d,02942edd,29bfbe95,2d65003d,b09f21d1,18339c3d) Z8(d22119eb,1d46239a,c9c7233d,b252e08c,bf011931,6e5dabef,3da98563,9e93ad70) Z8(8269f958,44ccea74,2a273de6,e1a6c79e,207bc70d,d3a40ead,e4931058,fe0eef84) Z8(d9117ac2,6b1ea815,1e377818,e0c38c01,586c47a4,b8cf5ecc,58c87681,c00ba529) Z8(28962720,f335a2c4,f050e591,9767d6e6,e064f209,21618579,80b234d4,89203fee) Z8(8b280839,b0436afa,be0f5b75,cd0e59df,a243017a,926f1b9f,c5df795c,69b64ea8) Z8(a4d87d65,e1291e33,927f6c9b,fa7280f4,baf39933,afea4730,61eae7d8,031a06d1) Z8(d46db5a2,1a2b14c3,156ab644,afcf0d0c,99f5bb03,da253042,7ad67e5f,94abcd6d) Z8(96879937,9954ada1,96154976,c95a100c,04d2c143,f493c5c3,4d3c49bc,44fe6d04) Z8(aba3311f,9cc421fc,c79bb796,277cb528,e491c927,e6c1ccde,1a3aad0f,beda8a51) Z8(50b5267f,4655c363,b4b66a27,6ce65a3a,68351f0e,538f0387,921a889e,21fd0747) Z8(6bae497c,3b8a980e,b025695a,118e2176,eb71f628,949bdd8e,ddcc51fb,b78dd828) Z8(52887880,42a03db3,05db6953,a17b8d0c,b6fb8890,268bdaf7,6b820913,e82e67ca) Z8(78fe90bb,76417375,aca15b76,c722313b,732c1a0f,6b039d3c,eb518c97,b38123db) Z8(51b10704,6d3ed8aa,55358ef9,6c214bba,1fd7f870,95b39ea3,a9bb8546,e02f42f7) Z8(27ee5cab,bbbe1dc3,1677ec4e,603900d5,7ce117e7,e91fe18d,b95c36a9,ad7bab25) Z8(5578785e,b8eaaf35,76ec223c,bf9949ac,f75979c5,7a1efa9e,60d15dce,91fecc60) Z8(758754b2,6238cba5,b762dd73,364d677f,37eca352,f02d2374,aecb653f,7d55ff31) Z8(10614994,2383ed5e,57a9e026,0ad27019,e56d072e,f378a2c6,5e35bdd9,f3e39db0) Z8(5ce2e454,ceb69ebc,eda4dd20,87011ad8,60266fe0,f1f8e077,47bdec4e,271dfc84) Z8(8cf4d650,b12b9ad8,0fc9da07,a3e50fa8,f21f3476,67e05630,2aadcdc9,2d32b661) Z8(c147ca79,6e777b8c,dcf961de,623b38cb,1a455c06,ac235445,4da824d2,102e07e0) Z8(15e4ed0f,99cdf865,99c4eeb9,bed8b4d4,4509190c,3738f82f,eec99626,b71cb75d) Z8(b3b85229,64e3f040,2203152f,9d45360b,3a0f086b,cff82e38,c6f0cbec,77430549) Z8(67413bb3,00651a5e,0ca29623,aa436bd0,94a2b9bb,1217e0cb,07769fbd,03c31469) Z8(b29816dc,1160eace,2e48aba5,94c84ea8,c9115fbf,8cd67f7f,c02308cd,fa88fe57) Z8(25859d89,89d5f829,91d9ce69,63899108,19b684a0,983bfa90,4413a657,36084b1d) Z8(befbbb3f,e7e231d1,b1cac89e,27658436,848d9764,c472bc16,a0338ef7,b1cb5410) Z8(c4308cf6,f21b3d34,08589e8d,269464ab,b3a2cbf9,2bac2c48,89bbddec,66435dfa) Z8(9c82b553,74856e3c,cc86c436,872e8ee2,c1121e6d,28a070d3,b799d9ba,02f50f68) Z8(7dfca024,1fdfb991,2b41e315,47747e2b,b3d0bd56,150c706d,56147655,f4d9e9f0) Z8(0c7e9c96,04c832ed,5618d166,a3733712,06591876,0cdadb21,924befc4,9f6db52f) Z8(7f78f9e9,aaacf08d,f2d5f9c2,daf0d157,15309848,10e3c770,2fa03911,ded72656) Z8(901f7247,15c222cb,a128e7f6,33729c1c,ed066f0c,6d0fac05,18958fbe,b76604c1) Z8(8b998b42,ab55835b,584506c5,aa287fe1,f3c5b4f4,84a57edc,dff76022,1cd8a7f8) Z8(e02d154f,d9dec870,ebf2139e,93c067a3,9c6aa6c0,03923b45,410853e4,d6524a2b) Z8(f7d82352,c372d0ff,ed2b3ac9,ddbbca3f,58a04713,c6ce9e6b,e8ca1b2f,975e03f6) Z8(0f47b4c8,802414fb,86157d1c,a134555d,5270f11a,ea104d86,b65c8de9,bae2e447) Z8(c7349815,0160e65e,82df1bf1,6858b990,4e4d85e9,218f87c6,3974087e,c391312d) Z8(e74f1cd7,397c120a,c95f33b4,b681e439,9980a37e,8c913194,9e881513,b5b3462b) Z8(6998a217,c54ee01a,d83e8631,b4c7821e,48dd2077,451767a4,bc4c1ac9,6351ec75) Z8(8411a18c,d6ea5b77,485ec700,ec4ee4fa,17c0356e,7f0887ba,08fdde3d,fa10fb83) Z8(7c2adf1e,b88b1386,70ad58eb,22e7d7ce,a1216533,5d2840e4,1d491ff4,cfc77d9b) Z8(c88200ed,033e0951,f8934cb9,d89fd19c,542c5130,257266b4,c5a01b4a,cd9604d7) Z8(4b6a1848,d2c2af62,0d3bdefa,7d9d60b5,5174b6f8,af48de4c,95a11293,8ba4af2c) Z8(062a715f,8dd2da65,442c63e6,4d7bbf16,5062fbf5,f6b2bc8d,fd8602ed,b8c5af7b) Z8(3d47b922,7c2b6f4b,c15dfb85,1c073af4,e20632ec,8aba9fc4,8d935aec,96bcd18b) Z8(9e7f9049,1bcbc84b,91dc5610,c072142e,6b199ea6,b25b8df6,4361eb1e,ba983f79) Z8(268f5b4c,bf75f4dd,75c119be,f4807e59,ff46868d,59e92f50,dcb89de4,8e000af8) Z8(1bce3f02,e967b29c,8695a6e1,03cd5875,fa418155,dd81f161,b2751c80,ddcb754b) Z8(505fd732,59c1e17a,7ee13b91,79eed108,994b8458,400600a7,f6f7e985,d01af557) Z8(1e17a4b6,db23b237,d0a65f19,467f8094,2a876649,8e9ea412,017526eb,f19f59e7) Z8(d9b6c13d,a5102b67,2d6fc9c6,9ccd8a63,a8d75223,c6cc91f3,eff263e2,653af79f) Z8(b2a3358d,d180c8a5,a02c2855,856cd4d9,897d2783,fb540d1f,62e81f26,be845b2e) Z8(dc3bf5c2,c7174ebc,75995259,dead9ef0,72a66b4c,e3e61943,f058daa4,208b9db4) Z8(63c8dabb,245a5b90,27837d53,e91603f3,c4d5b5f7,0f0aebd4,ffd0ce72,dbdf7acd) Z8(cd05891c,59075901,95c9c647,9bea3bb9,88edd749,78cc2ab5,2dbad4c6,7273c87f) Z8(26e4fc8c,0af6f8ab,d7e3a74b,76f8b464,8bb81240,2484bf39,6828ba2b,087f3a02) Z8(afc44c7b,75d995cb,4d1027de,4fe93b72,939843d5,e0a22434,cbadf258,a079fb79) Z8(963bfae8,da7d8360,2784483d,010ac61c,5e51ea71,f87c39be,5b38177c,7b9467f7) Z8(fd683b56,72375a05,2d68c3c7,1785242a,67ea97aa,13b2736c,fe7d95d0,3b31061d) Z8(22686fea,317aaf2e,ad0c6b26,d3c716c8,57fbaa5b,f13cef93,556f6cb7,6b688d83) Z8(4c348455,0b2a1c30,05ad32ea,7a2b1ea3,b9eaba3b,0d780ccd,c1f50087,4f77e39f) Z8(1caf02c0,57fa9070,d953f422,090a1108,0d85e2a4,aa1f9b94,821364f1,66fc84b1) Z8(c8afbb22,235f870f,fad2cfa6,b7eba71e,ca53c09e,6254971f,f5e2a470,e8cf6a4c) Z8(40cae7c0,2884ec6c,86a9b874,b14bc36c,f1f256d9,e4e5ae63,70a9a532,e963b7df) Z8(362377f1,1bcfd9bc,bb3aa87b,f17e822b,81d544bf,a4816ab5,7c009bfa,dd917ae9) Z8(5c9e4fdf,463d2e83,e42997fd,3033a194,21d81310,41d65e32,5956da38,925fbc2f) Z8(2ebda0e1,62475719,2e6dac8e,c7ca825c,8119afb7,bcb1c956,2931caca,85723a36) Z8(136e66fc,fc642407,4d6e7afc,3a6db1ec,98ae8d86,e400c82f,620bd8a0,1941def6) Z8(16e68267,907ea7e0,40859c2c,5f233042,6f78b9eb,734d89d1,24ad8655,4d389c69) Z8(fc30dc08,55923d69,24d26c28,f7ad38aa,1e1ae198,8e5c4b3a,1d5e264d,a492ec44) Z8(4d695f11,f28f5138,dc7f4ffd,0ea98c38,481c7e6e,d4db5aa4,8480e8bf,81981404) Z8(f04c3619,7dd28219,65562742,92358274,f586e018,c19edc5e,30f7d844,54915d5a) Z8(db2526af,781b309e,b661e62d,d9148c0a,0af719dd,8ebd6820,6ff2622c,c068244e) Z8(d8a492e3,63ab552f,427527fa,31e85e30,a1cd57e5,15e31260,c6c944ae,3aa1d00c) Z8(e97ec2cf,e82bf2d5,132dc3f2,a35a66d1,6260a914,3df5417f,93338f5a,d1886f84) Z8(30af4a89,cf2eb536,20eb90cc,c897d34b,b53952b8,b6e2ab02,761e8503,efaa1bcf) Z8(4e4f52dd,2d7dece8,e046d33b,9d30248f,bda00fbe,e3969963,c33528e6,f3b436e9) Z8(f524831b,0ebdbcee,977751a8,bf57cb5c,8fddcac6,86aee555,4991a480,6bc2397a) Z8(117c4d41,23e54355,9d46d3db,432ed3a8,a2783a7c,1796a7ed,594497c5,91f586a7) Z8(38763744,95531389,45b255e1,5dd4d8e3,4d649d88,b4d39e53,289c202f,0ce7d97c) Z8(1f261956,dc4a4073,318f5419,4846d9ea,45332765,f655ca2e,a60eb1a6,5a7dff86) Z8(23744f38,6492eb2c,b79da006,714df221,0984d306,70e2e1d8,1244027f,817cd12a) Z8(8b48c456,c63c93aa,bfcec52e,14122b03,6091a5fb,17f47241,3d4b0431,8997f615) Z8(83ade652,47445204,0446c9f3,205fecd5,065e42b1,279c7151,0fabd42c,2fe25761) Z8(1c52acfb,1934875e,ea54430e,bbd342a6,c62fe634,c363c11a,b323e60a,ace2cdd8) Z8(7edc8843,1f4d3c76,acb00a94,5ac26560,171fd27b,9d0955cb,74031852,4e0992a4) Z8(d7b6245b,a3e15fd4,f753a150,aa453e59,5a47992b,2e4fb601,99b9c6c2,ac135a40) Z8(4f254378,c6e6250c,e68ed0c5,f2a4141c,8db7c9d7,76f40aaf,89e123b5,9d227d07) Z8(e15b2c99,2548606a,74a6d1ca,39e88039,d6be9208,a877ba39,af09cd2d,e2769751) Z8(714e9eea,18a1f523,cc013b62,497dcccd,a4cf7a8c,8b07f5e7,8135a013,b787ee15) Z8(63c09667,b3bd8a3c,fe0ce629,ae9f81ed,28adcd7c,1612c963,bb3b7aa1,1837ec72) Z8(79323731,1e9bfdd9,07aad183,4539adf7,59a64365,ce728949,7e3782a8,2f5ce182) Z8(001c15bf,e86ee62a,08c0e147,76bfef95,2871c270,45543943,0b9ce26e,7da078da) Z8(cd73d66c,13e68864,d641f715,a6f9e8bd,3fa3d370,529469da,7c790885,efa982da) Z8(710191c0,50ab2623,d8d23179,838541da,c5800ab1,bd6a5330,e899bd2a,e18580d1) Z8(62e2fcbe,8f06ca99,0e4def12,e83ff630,fea264f3,2ae786ae,f5df6929,666274e4) Z8(4d007241,b71976aa,5d89b385,fa784db9,acdded9f,43402be3,daabf4e8,271920ab) Z8(e35e3126,8e953fa7,44b0c00f,2efc9cfa,2c1de10c,24c04c53,fbbe1384,80b3d717) Z8(f46e0ea2,938e9e47,3900bea5,d3afbe07,4f4d2510,a164fa30,9edfd6d3,febad840) Z8(c404188b,e2e71d1d,d0ac1cce,5cd27722,c857e447,a9a4e462,302213e2,6f98987c) Z8(0a336d94,39549ef9,f0d16458,5b047ae6,ec69f6eb,0f752d86,799b3c44,c539d47e) Z8(f2794f46,7cd35101,1368e9df,b3145365,b5869d41,fff938c1,978101af,07e24ed3) Z8(9c2251bd,324137fe,c024ca40,f20e5a67,84516c34,eecae227,cf35e8c9,021ff73e) Z8(86055c6c,ba5e976e,787da722,19053cc1,ff83849b,3b93c4d1,bd44b744,93009410) Z8(0639cd03,a5214273,cfd62755,bb1253b8,98d17474,f607a5a0,49b7bc5c,9b1d28e3) Z8(780708f0,6bf8107e,216d8104,bbfc0f29,fa3eb9fe,3560d91a,74947fc9,90020ff9) Z8(732bfe8d,52684573,a89e6738,4f348342,7f779c7f,251dbe5c,222cf016,687fda9f) Z8(6de2bf99,13d27d2a,91af5105,36cb901f,646a9a13,181f6eaa,079cc034,473acdad) Z8(77dd652e,e3e22501,4024bd33,96f27719,2d938989,3b4f9392,a6d50df4,c5f01a8b) Z8(8546f104,7c499967,8e58bd9c,5bf178af,52f731a4,4ddf0b2a,ecb8390b,712fed65) Z8(c8592854,2172cb96,9e38e1e8,897232b1,efc16d38,02742504,d56df423,3eb2ec63) Z8(b5cdff18,8ca727ff,e401bb41,e2d18c23,1282e091,674e9f16,6a7f4e6f,ab02cfe8) Z8(40c0553a,3ae1662c,5188b182,69ccc617,5ea8931b,57be5814,cd717988,f5b2918b) Z8(03b0ce4e,dbb93120,6969ecae,e22334e1,115ac805,10abea2b,5c4997bf,eef19a9f) Z8(b710d889,a6b2f057,50a80170,35409450,3070ac04,faa2eb99,d6ed8419,857ee505) Z8(87f81cb7,691c9f69,36d659cd,2d681486,85dfb6f9,8b7ad15b,cc19df9a,c9ebc639) Z8(70ce381c,4df36ec3,466dea5b,b3ab97d6,19a5ceb0,230b7349,589903f1,8ff85ddf) Z8(7dbdcd4a,dc8a54fa,3225170a,3bc0e4ad,1f00b519,f88f9dd7,dc352406,a549269f) Z8(cd078dc3,a4381f72,b8b0a80c,53f249ae,bd3a5b56,646f3ea7,2dfd61ca,1275bf0a) Z8(fc4be8d2,96901301,1f1c2fa2,599e8914,d3ca89ad,5506757d,c2c23c0d,3ff77bbe) Z8(e0e10639,7c3ba00d,39f63f00,3d15255d,4608453e,436f69ee,08557697,9d3b4502) Z8(4730a873,c0511349,42b7624f,88d224f9,04a9690a,2e486b6f,6febc5c1,1c82245b) Z8(f3e13254,9f27e43a,23aba80a,b61972c4,02efdb24,5599d1f5,7b648343,813d23c7) Z8(88c99668,981245bb,3bb44a0b,a5af62f3,59cf7011,a124221b,97566b20,6bd7382d) Z8(1a042461,dcd83ead,9cfe3ce5,176b3f51,b70dfc13,15c62375,0a36ec2d,283fa20b) Z8(08edf53e,4beffbb2,37cd8309,cde8c10c,6f606b14,b4b6a8ed,5c1070ae,23e6abf5) Z8(1aba7bdb,98905887,e9c5cafb,9a8e17b9,636d1eb2,f108730d,ae252184,aa55ba8e) Z8(2b073aa6,8f807db7,8654e88a,4dcca0da,7599baaf,eacd85fd,c73d9a75,447161aa) Z8(424cf602,274a9bd6,32be174f,501c8d13,c44d85ba,9e05e1a9,b089cc9b,eead7aef) Z8(cd973439,2316c0dc,0690a1f3,46da2374,70357fe6,712725f7,d3292acd,5da5010e) Z8(21c0e188,76107e9c,96543df4,72989d97,09521404,52a956ee,5d7d97a8,bdaa0900) Z8(7123f7c1,b912de49,3b27623d,ad069709,a5c745f1,79712589,24f1c98d,c38801db) Z8(fa108ad6,68743d53,97706b2c,42ec549d,0ca67057,2b29aa7b,8e487384,c3abd56e) Z8(567f761e,c9a0a856,19722fab,e83bec7f,d1f1f650,ae0d3b9d,49d23e34,0636eb19) Z8(ad33a1c8,bdbc42bb,25a6cf17,d83673f7,c6d1113b,5575e890,fd870f5d,cd94f8d1) Z8(4059787e,3d736fa9,7f2b129d,e53626ac,db1ed883,e75d458f,f922e250,fdf95703) Z8(f72483cb,f62b2fc7,1a11eb8f,bdfe158c,5fc907f6,1c293f68,1a5ceeac,b757b0f9) Z8(a37c6987,969240b3,e58ab60e,8ba172c6,4b332069,a5ec417a,579d86f7,a837df05) Z8(e858b7bb,53b8b60c,89f10a5f,fb230dce,6fa6263d,32a8db37,f6367dde,e5458e28) Z8(0636ada8,96c28fae,6aad3ff2,db8b6a3b,003562bd,c8d77356,7ede1f06,b5594e52) Z8(f06d9d39,bf727c08,ef145876,ba950c3d,8c85cce9,2bdfa68c,b603e9d6,7ede721e) Z8(262e556b,75bdc115,ad789318,7cd26e3b,9c5a214d,84825f3f,4821ad88,e52af8da) Z8(73797e0d,f2e10e9c,b2be81c9,ac222c88,152b0e16,17ce4886,a7e7dbe8,07e1758b) Z8(80524efe,454879a4,505b29fb,bb1f61f9,48ecd832,4325b6a7,c4147f4f,d25eab3f) Z8(a39253a2,5e52aa44,3ef6ff1e,bc782900,dec49381,a54b709d,c9380ac4,0f797f38) Z8(3e0df34a,730ceff8,533caefb,82645526,9abea011,6fbde1ba,a2208942,196adab7) Z8(b00f53b5,26e4a2d0,a9f58885,b84c7c8b,b8f28691,47f64841,220089a0,9dba738f) Z8(239a15ef,98090186,de8a7020,96a04a15,c6b10667,a3128437,0e55e016,1b3b3f2f) Z8(544263dd,a310d393,4a03145b,9b3f31c4,e900bfc2,8536c1af,f9f2f5dd,bd06feec) Z8(55e05aa5,c96e39dd,c4537767,66918b7d,8ae56024,53e2920c,a64c57f7,318b5795) Z8(a2d5f73f,cb0f5cc7,0c8faff3,3fcf0543,81c55f24,7e395be9,f7cd62e9,85c68ef9) Z8(0d272ce7,f2fa70d1,f5579c87,8f732dd1,de487d6f,eaad0b8c,ff18f425,5e63e5ef) Z8(2f29bd18,0b360281,ccfa08d3,1fb346ee,63006920,4dcac38b,5233426b,aeebb506) Z8(170ebde4,05268f9f,202df2a5,fbc4162f,2ed530b8,943be3d5,6145d9f3,516697d1) Z8(50eea761,c3d175ab,7429163c,1dc02218,4c90927e,860e41d6,b5c49f85,8d5e05b8) Z8(4a0d3863,98747fae,3f2527c5,7c09e6e6,3b93d9e8,661f83c1,d181f371,7dcd1a6a) Z8(17048087,71c6ff3f,f8a13fda,f4a3a2ca,f981573f,085feac7,b0f5f63d,e40fa605) Z8(53373b0b,6ba755cc,36cbe753,c0e5c623,89452be9,7ffe4a37,02cb4e66,291ba851) Z8(be972b16,a26878e3,9173e475,c2380999,3a75a8e7,01ddbafb,c62d742d,3ce3a85c) Z8(eba0c1b2,ebd230b2,0f206011,00d2ef92,0c126e90,6f2229df,363f9874,54c8df70) Z8(e5e9e294,26e9d675,6e24e54e,0098d942,6da5d965,c7169dcf,9e0a8563,ec2db046) Z8(b31ba9e2,421b1e6d,bfc4b5ac,011a231a,679bad92,24313528,a81afbcc,22c74166) Z8(9d61e1dc,bc7296f9,7bfb943c,7b5471bf,f784e940,c5aaba59,fffed1ee,6a8d5aa3) Z8(cdd14393,4e76c420,a8d7e6a4,b4284232,0ff2a8d1,0e7b0cb4,fe39f8b8,091afc64) Z8(f49bfc88,7afed6f6,53c4f243,96e56c19,cd95f46c,73f42f01,e968a65d,6fcc35db) Z8(0547e284,4192abdf,a5489a2e,813fd150,8bd78a06,cc14eb88,d8feadee,56819174) Z8(3651bc64,9ad449a3,86a9ab06,00341387,cc711092,a5782d24,701b00a3,7d8e7da5) Z8(f49d15f8,0c3f004b,04ac4a3a,1d4fd4fe,38255c44,4ee2d3b9,93c83663,de330ac8) Z8(23242aab,04b89e4e,2cfefae7,bb8aa63a,74aab751,d479bcd3,9d8d1ba9,ffb2a307) Z8(e77d653f,d8b1983e,f1307588,5a97c946,569a55be,661de221,13a768f0,9f1b5e72) Z8(902ef8c6,58a4a252,52406d87,ad9cf441,65480203,37a0e1e9,7fd93a2e,559ff47d) Z8(4c8d5215,5bd71d1f,a83b93d3,4e506170,97d13875,03df3622,e151df1a,556c6aae) Z8(cf931bcf,8a1a7c0b,67e1cb04,9d8d73c7,dc246210,7b66f121,fec7125b,51230001) Z8(d3e8f91e,a9d25c90,b2e05589,8ea29b35,1a2121b2,90da2a58,6f12f9ed,ccb986f6) Z8(716fd0da,e5b99404,fc5b8f23,3e7a545a,e0e1fd19,d1fd1bed,976c0199,14682872) Z8(4ac8752f,960a5413,0e6a3cc6,62a19b54,eed60084,b28f3df4,51422837,6b04a4cd) Z8(b02aad01,d0dec652,762c8a43,69748a1f,4716a26d,62bbce54,18408143,3c14d163) Z8(5380fc89,fb282bc8,cf6713a2,6de2e902,d87c1b1e,6e0ee632,41ef8d4c,f63a4a92) Z8(76ea1ea5,1bab7979,69dad99b,d0b0972b,e8f245ec,7b7f2836,b92a4ff0,831c2f1a) Z8(62a58184,dfb72847,d64840f8,f3a01315,8d36d95d,8394cf93,65c6fed5,6e32adb1) Z8(e89ae6d8,1fe96403,6b4a0796,3e239ed8,b2063f00,f3214bee,282b7317,f83fac8e) Z8(627c8229,8c069722,a6048960,8a376184,8bddeb44,42b6191f,6890f36b,906f8ec9) Z8(44cf655a,90ead655,0c24c74e,e9627fc9,916ffb25,28713e3c,760bd3f3,9693e1d7) Z8(4c5e0f0f,95050137,a21d1cb9,ba720644,c6f872be,8928302a,6a26b00b,66547394) Z8(607000c7,fbcc75f4,4f6638e9,eb8a93b5,dd9400d8,edbc53d3,b64de2db,b5775855) Z8(6ef524f4,888a1ecc,09227c50,d87bf90a,6cdcefd4,157ab593,e1ddd4c9,95b4b602) Z8(622cc639,a016eb5c,401364cb,aca65b30,a0aec251,4b1a434a,1986884d,bc62181a) Z8(95c3a337,0c5c096f,0d386a5b,3b91a99b,1fc0a5c1,6fad40c8,2e85e7ad,d6d6ac6b) Z8(ba9e71b0,a39283b7,0b45dd27,6fac20f8,046e111d,abd878b3,2ef9f400,a4f7eec7) Z8(1e4213d2,3ef624a4,feda5097,c34e85b9,348c4309,7ae80437,c8b38914,190bd041) Z8(8aba95a6,e4d5ffa5,4c8fa8f8,ce03cba7,f89a8f1d,bcd647c0,34d2d34d,eeb742c8) Z8(797a9c6b,57d08190,94929481,f917a480,a3e8af6a,bdbef089,5bd88e6c,f11ed253) Z8(7962ceb4,e6e1cade,9db63c13,6fe99ea1,ef97e327,fb8b25fa,0d95e3eb,63c0d8b1) Z8(249e46c2,50eb5448,8b7dd1ec,cdf41334,c31a6c20,08fca2f3,620f32a6,d825d623) Z8(270c604e,aee745b4,86d41c35,b9dc10fb,a683f736,a85e0974,ee222b86,19cda2dd) Z8(89d822c2,6b2f6b5e,c032ffa4,70dc4f5f,c5fa6dc8,21352f90,399eecc6,0ea0b745) Z8(65b2ae7e,f38dd844,634f0d3c,ba629d4d,c6c118a3,12549887,4afcc2fb,92e9158a) Z8(8bbd984f,b221afb6,e6db0177,a5280dfb,87cb2f75,1d893663,a5b470f8,4b473748) Z8(44364124,744619b5,e30cc63c,996d9ce7,544c1e09,8c07c857,fae8308a,45ca60ef) Z8(94a9af74,8a3a5a1c,159a7049,4c0c6950,703010c2,ba626a84,501ea295,df7b37cf) Z8(89bdc6cb,9cdfe9b1,2bf94ae3,291a3744,ed1660e1,4ed99d45,c18e44a0,5ea2a289) Z8(7136a1d8,a7afe5f9,d9cf0f08,07358f85,04837218,0f9de99d,4a3e605a,ee277b86) Z8(64709497,ead451ea,99def992,38c92cf1,d0900126,9bfbe4a3,86ab3852,74c5f0be) Z8(2902e218,7f5ecbd6,a8bd5c73,ac0671bc,5075a3d0,ddf87b9a,42195f70,0b05bb90) Z8(cb257300,099a691b,e0e4371f,d9bfba0a,26bd12c7,74697af3,0dbc32cf,19c2f56e) Z8(03df8d64,45adc4d5,da125dfb,2e1f9161,06c258ce,9dbeb359,e7082cd7,80a59273) Z8(5812a4a2,8ba18dd6,a14cc22f,cde15de3,beeda686,b00ae6d4,d83749bb,a94a7177) Z8(25bf6822,caf47c3a,324dc2ba,47515a2a,002d2445,c43c647a,a2e62e4e,11d1d3b4) Z8(5c6d12fe,4989973e,f628bfb4,62227827,f849353f,5544a556,c46f57d9,5f1d64bd) Z8(53dccf96,8d8916c3,a61dc8b2,560d792b,7061c43d,01209655,61f9d5fc,8c6bb70b) Z8(26202855,83378405,338c9c42,5b265795,335251a0,587ae378,7bd925dd,5a8877c6) Z8(2c06c3c2,112f161f,af8df44c,c4e83582,61e65e76,95e06828,24d8f5d5,2750fd22) Z8(cd066f77,1bd7f6e0,f7920027,6721eb63,fce8785c,6a2a4488,0ab03033,60a265d5) Z8(18f039a6,a036a529,e1969b3f,ed3d8383,905e519f,0a9e7ab8,9f8aa1ef,8fe47dac) Z8(020ae2fd,a125ce9e,34fef9a7,d4e77816,a2138074,e29661c6,685a7b76,2f9a93c8) Z8(5951094d,7f869658,aac95376,5e023399,f66b7f29,551c2920,0c7bf813,a59126c3) Z8(c4795568,6072d800,dda81ce8,77977769,21f1d0b1,3359db9d,8533bc39,a4d5e97b) Z8(e7ae833f,73302f85,ff386a6f,8e7e8c43,cc6f9b33,20fdc4ba,eb135134,032d8cf1) Z8(bb45cf31,9a2c7cc3,418ee32f,f6f1201b,3c3d681b,2382b2f3,6d8c922d,f61bbaf4) Z8(158835a6,8c2fe866,8d3e1a92,45a8c052,6e061630,4405e012,5521f46c,7578c723) Z8(fc19ac64,aad634aa,1d1dd46a,feef6f87,004e721d,c01fa38d,4e7f9b10,04302593) Z8(039f36d0,13d11db7,57adbd5a,fbcbd8b8,922f5eda,059ccdc5,ed8e15f2,283e9a67) Z8(7ae1d410,33c258c8,e392a82e,9491a0a4,0e3e2eda,5be829ae,040697f9,af714338) Z8(8c256305,f8d7fdc1,8eac7d19,0441f702,5f9506dd,019245da,40e10b34,dbdeb1da) Z8(d6503fed,ed577f29,57808b65,2cb8344d,5ce337d8,b47c6833,49bf5bfc,83acd365) Z8(6d26e729,9bd721d9,19724fde,6a6664ee,291a064d,ff949d3e,7ba11d65,25875130) Z8(fdffcf18,aecb4366,0f5aada1,fef1ab6d,6e6f4b1f,ca88e98e,5e04b492,a321876f) Z8(304095b1,161a0384,281eff11,0bff6d1f,396fd0a3,90284c3b,74e36f63,8518235b) Z8(cfe0b28f,5ba00fcd,b61f1de9,4cced297,cb281b73,477a6c1e,b56402e3,8a978309) Z8(0e55c559,900b210f,735713fb,4930a4d5,afb63241,6d6056b2,37bb63fa,d4e8da71) Z8(8bc223b5,037af640,9693d21e,4d009f5e,cc80cf26,cdb726b3,023f4dbf,6ed2bd25) Z8(634d9928,25d758a3,7fb7027d,e256ba8d,79c07867,af868ac0,9059fcbb,0cfd4cc4) Z8(5f96f2a4,47827691,3b064822,bbabf7cf,75c10f6b,266b1e5e,37f6cb84,34090f70) Z8(1671dfaa,521185df,d6a309eb,111ca154,1a6e25ac,a15390aa,a220fcfd,fc57326a) Z8(18eb6f5c,3cfc7fde,bd55a681,a6fc721a,62656dc8,de36d26c,1a837770,63578531) Z8(cc99ca81,e705fd00,9c635996,f21a28f8,087fc076,d2ba8d43,9c16be2b,28fd7f83) Z8(7ac486c5,eb631523,21b9f6f4,dccdf6c1,aa40df50,7fdb2747,0f80640c,26ca6322) Z8(bb8fc7af,b6662f95,372d0f8b,bd1777b8,563a2575,a656d499,e97d7d57,bcc27280) Z8(4a318c50,e420663a,c840d3b0,9365bb44,8b9d155d,20e8a53f,79ebc6b7,48f82af4) Z8(31c96a0a,22ec4246,8287d2c2,dfaf9214,1087a33e,92c92350,8880aa46,43515c60) Z8(7fb68a58,aa93145b,6220a898,6de91753,0c57bbde,3c892e62,38706560,92ef3972) Z8(d301aad3,fc82d2dc,97806abf,e9d115b9,9b176573,0c927165,6a3cb503,6ee1359a) Z8(b0b16ecf,f657f780,03b68478,a3f7a935,a593199e,a3b434fc,1a4d6ea0,39fdb8b9) Z8(623fef98,7fb7947a,a91a1d7c,d5eab813,025b3fd1,a842293d,8ae7b398,7b4d4b6e) Z8(f71e26b2,59ee8214,f55ac98f,26714665,e24c0c80,340503df,d6ed94ea,12e897fb) Z8(b92a2b95,31fdd14a,fb08a24b,38254794,c64fe437,1dbd364c,857ea8bb,ee4798de) Z8(c461b00a,85d5753b,54cf5fb8,59e4bb51,c2078022,0a28cd0a,32abb5c5,6eb32e38) Z8(9fa7eb6f,bb76d3be,ba27fc00,5134403f,abd8c97f,54669238,502ea8e4,563591cb) Z8(d34cc34f,e65cbb8b,b8ea57a8,ab219061,17c77790,ca2004fe,2caa06a9,19256df5) Z8(dfa1efd9,5ff3e937,da731fa9,3b359cbf,62c03724,b2294e21,65f1aa60,e3100cb6) Z8(2b5c649e,27e16eb8,95b86ee3,24e9da5e,3d12f371,98434f28,63cc4aa0,7a0e0537) Z8(7332dcee,09c5d148,62d58e02,ea47600f,5a39b742,25e3208f,84a0be7e,c5b2fa00) Z8(30bb32d9,4d5af477,a8f6a343,d0614ee3,33327990,a9900380,30512208,2a78734b) Z8(941297bd,67bee25c,1dba4a80,389b38d5,d7a18e6f,53897349,f2c00033,9fa9eb4a) Z8(8e4a8c27,672a29ec,cf30e3c7,a49a5d25,e4d63fe0,b96cd567,6e3d45be,2cd18b41) Z8(cfe59545,62e080b2,72e4c638,4571797c,37c44ed0,7cd1d1a1,8131d90d,0df056cf) Z8(c5462dbc,540b9fb9,e4521e25,8a098b25,92061f85,b330e89a,6a73ea75,909dd777) Z8(cbc30e09,0c27d6a6,d9a7babe,a668077a,19e235c3,44566edc,9f402cac,687a909f) Z8(247e88d5,dfd205f7,af0b6e8b,14ef6687,9594f6b7,11709563,5cd5b2f1,ca5f9594) Z8(f1058e79,e04ecc00,1dd47f9a,c9577682,a29ae593,0d7a5e16,9deb14a1,18aa3fef) Z8(0088cd84,648ec802,cac71dbe,2cf29060,6c274143,df4bdf11,3e7e9971,4eaf842b) Z8(92363865,5b51b787,d9acec17,a827a841,3a777bfc,e58adce2,23859641,aabd438f) Z8(8ce9a5b1,7814bdd5,1ba3f206,cf8964bc,fc142b62,bebfd5eb,b70575bb,fb445441) Z8(f302a6a8,c68b63c8,853c177b,d50cb98b,8bbe3744,b1a14f1f,011c14e4,31ec7af9) Z8(9b9c6868,b6fd3f9b,52e636bc,da0fec92,f40b434b,6fba40a9,6f133860,0ca30121) Z8(b9f4dca0,879ccded,6549e1f8,34c889a7,7ec9468a,383b1fc9,391c22b7,8f1b2b38) Z8(cf88bc24,37489b32,f5e64d6c,6e6e7c27,24aa54c9,be1ef999,d0c03cd0,b4b02aa0) Z8(be6f297a,c3888222,f17c5085,fe7a08bd,f44c8bd6,746f7618,e20ea9e9,a0c45505) Z8(304df305,b5eea4c5,84adfa5d,9e77e2cd,5837d25f,a2273a88,9eb75948,fd6ca853) Z8(923df237,52db13ee,4f988d10,fbb2caa1,90466fbf,7a75c8ea,5dd39d3a,435db652) Z8(3b9796c3,d79b158b,d3742660,a5be50f5,4494d259,2db3f4ae,7ce70195,e7b65354) Z8(d0bd1b77,3b977044,e90707bd,a59b44f2,20753875,80823269,18d6fe2a,eed7de4d) Z8(f76d44e4,fad69e49,960bcebf,ad42a379,dd3ed328,e748209c,caee1cbd,f106b1e2) Z8(29e322c1,ec0c8beb,9158b2fc,864c0d45,bc37cfd3,fc85fdf1,5cd280a3,8aebd95c) Z8(365e38f0,820e1a55,12a80d1e,7d9c47ad,c40f9a60,6ad83b3a,17cf8363,743621d6) Z8(3cff0be7,bee72213,46fc3f7c,93adaa7e,4b17da6b,bcdb1528,e78a0091,6a915482) Z8(2bf17679,aa5488f7,3f3d8af1,33dd4bbf,9acb29b2,b711d45a,f274aeb4,4f267830) Z8(3ef8e1c9,8e31790b,813bb19d,705daf8c,8203ad3e,ad8a0d86,ca9e402e,8c7bdb6a) Z8(c32ef618,a0ceda6b,fb6ed5c2,7d814beb,46dbb906,6250ef02,fe0f6a6c,eec1c0cb) Z8(7ab36ff7,ce701644,cdd7090a,bc4d613d,7481f83e,97b8393e,d028388a,88c5c9dd) Z8(a49b7ec8,a4d4f74f,f42477c0,c61022ad,ff508686,e136400b,3b979530,07e966a9) Z8(f85402ae,54b36be4,038de0f6,818a026f,808c63d4,42ac08d5,a8d9919e,c7ada550) Z8(cd81eeba,0acd0548,6b4d7396,5b5b2b1d,229e0d34,23434d91,448af11d,bc5df138) Z8(af265635,a466e08d,2b05340f,f9a50e18,3925ddab,3e4fb6c8,d9f26235,9a4d777a) Z8(3839adba,9815fba5,d9df0755,b67a2354,d20bbb67,de1bb1ee,b0da9fdd,9918b6ce) Z8(c20b20a1,fca992b2,aab0beb3,230d2f86,4c2cca32,f7999eef,166a62d0,fdb10a3c) Z8(24c484c7,dc60fd03,2437de2e,722ab150,17981405,82637471,d9e7fb08,d1fa2a46) Z8(49b9369d,a1f46f2f,46208c43,0a4f3a86,99b64c6d,2b6ad99a,b48dd161,ae6a60b3) Z8(aeabd842,bde0679c,2380c922,976a1e75,93168ea1,1a9b31be,e1b2cb46,94c56a25) Z8(929236f2,0d5f3128,576af2c5,936d7f74,7a920bc3,07c6c45e,0ba270e3,2e408e30) Z8(1f7ada45,ce29a409,4a033932,f82c9a99,fb3a6cb7,44c1b2c8,6f8f8277,8ed23610) Z8(9a15657c,b0862b25,e4f6f615,4d47985d,c858dd6e,ba18121e,77787233,1261ca22) Z8(c9d15ec3,1abc4752,02144900,70765014,b72d9c4d,7d4613be,53adad2b,92334314) Z8(ad402231,f9bfb9cf,17211cbf,713bab68,010c9524,369e13d8,3c306e45,2b032f31) Z8(a2417925,b70defe4,30c578ef,7512a2e6,51e299d1,c6157154,b6622fce,fd673540) Z8(cab2bbcd,1999016f,15783201,2c45ded9,3e938b76,3c4e7945,1dc47c6b,388bbf83) Z8(eccf1bd8,84875c39,a0151b9a,51e8069e,6eaae180,50a55c6d,6c8265e2,bb1cc0fa) Z8(e2ab2b6b,680363f5,18bb0826,2735e4bd,8527cbfd,ec2f306b,52f95fd6,fa4022c3) Z8(11a8dede,dd95778f,e24523f9,17c9fda5,41399cda,64754bf3,e077c214,5c9093b0) Z8(dc2c16aa,ea3612b4,f2545644,5a3a254e,5e11a573,dc27eb90,d6215db1,e1af90ee) Z8(d84418c0,963f8c0c,f455070d,00f90d91,334660d1,0654ca9a,a72d8bb0,f06e3989) Z8(c7a402dc,35713543,992e0544,d7164cfd,e8e9c716,ad96e2f6,6a0e37c0,56a97069) Z8(ab9acde6,e3802114,8bdeaad1,b8a3b3fc,60caa9d1,7e706e52,1c388e17,7c2efad4) Z8(8f8c9c55,969ca9fe,72b4c292,d3cf56e9,f27303df,d559cc12,451e56f3,a5852c8e) Z8(417419d5,a20a9cc5,ae739fa2,b1113f5d,a94dc1e4,a2fafdd8,1a350afc,3422a695) Z8(dde7772f,82f97329,6614dc88,d67e4cbb,36cb1191,5bcfb591,c98faee5,c65d3034) Z8(28b8cccb,3e89e88e,031672be,9655de0a,26106812,c112b1b2,a3ef7e90,75507475) Z8(bc6639b2,d837b311,29d482f5,a96f6e43,84055efc,4677754d,316c3a37,fd33f258) Z8(f882291f,1735e719,2ce6e7f2,8d44c44a,8add33f6,8a6e5866,a7857342,eadb8a1a) Z8(9981523f,b9dcdcbf,891cc8dc,e64282d5,5fecb3ac,ed2840f8,f924c821,53d738e7) Z8(85c997cd,eb88277c,ce125fe8,17f6aa1e,2676c88a,1be9d8e8,e10b7989,77977ea5) Z8(38f8aae1,d605244d,a9e51b62,9efb5d17,08c0804c,47d6c2b4,286a1bf7,e22456d1) Z8(9e9bd14e,e1a3c61f,8be919a2,2e1af62e,c1b5a523,7922ab2e,a6bf3685,ee26ed17) Z8(d8684a11,d491182d,7f7176e1,30176923,1eb94c60,3720b2fc,eebdd349,27816341) Z8(f1ecfb73,d08c2f8f,60be4a6e,01fe5481,a0e937a5,98266955,82529290,f2cfdaef) Z8(84d6b5c6,a94c32c7,635affa4,960d822c,d5afc34c,ec570a5f,34695a12,6478a993) Z8(4d832eaa,f38b1d5b,d3a829c8,f19d7613,c08d53c2,7875e720,345762d1,dd5020be) Z8(15ed8308,14c1c4aa,b56c891f,9e7b5e14,4f251692,4531a3a9,89d599ba,ca1acfdb) Z8(04f57918,074061d1,e2256d7a,6ca4258f,120f70bc,33ef05e6,c3da0a69,46fd6178) Z8(9eab1817,df0722be,70b7933f,70a5ad61,1d70f001,12baab88,ff30387c,69b4734d) Z8(f5a88191,c7d95cb1,af3af6eb,8a4e44ea,45b94188,c2663b6d,159a547c,ab71ac31) Z8(8e64dc92,8211d5e6,c5525d44,13e62232,e80ae705,640e56db,60ea1fa3,8c78ca8c) Z8(9d7fabba,0f41c568,44983036,ebb12e26,44527f11,f7a44fb7,cbe0d63a,11bb952b) Z8(d16b2429,a222e3d7,8affc27b,dedd4b6b,c523abcf,459abd6b,ed23179a,a29b7401) Z8(4210f18d,7b94915d,4db2a165,e09a6496,d5b9b4a0,53d10fb9,8f0aa441,65a61d1f) Z8(be3e0160,df71c137,8f89c578,1ccd504c,04a12c0a,80d61890,f8f8b67c,8c652fbf) Z8(87a6427a,715dea98,cd53a354,0f396334,afa686a0,92942826,a0b2a889,ede932a0) Z8(52f5ed6f,d865e852,2b1905b5,bae3d71a,f7ac0bf7,752520dc,38bb5422,4f61214a) Z8(9ba8a740,b67c4c40,4b8baee1,7f076271,e7be7261,20fae518,dd83de36,2a7f4d9d) Z8(ad1809eb,44300e09,f76ecdb8,03db5a49,25f3442f,0a93735c,3be94f05,60f32084) Z8(54ece803,d2d7e2e1,2ddab7a8,9ef6689f,8d56aca9,91c3cf7d,bca38690,46e5a728) Z8(633e5b8a,75bb351b,6e05d50f,6b693903,75725b3f,535f4476,2cd85e63,a4cbf5e6) Z8(40a06294,35e9271f,7298ddeb,737c3a28,7a86763b,0afc8e77,40d0af67,f924d5b3) Z8(1656258c,40bd8635,714553bf,6b02288c,720e7a9a,846177bb,381ec2e5,b8e34718) Z8(bfc70616,a8da6801,cf283b57,846928b4,023c7292,48d4f10a,98949a13,731720c9) Z8(e86c3b19,0ae0c9ad,01331577,51057f86,2d122d03,d7bb714f,9dda9810,a7d7e4a3) Z8(b2f7ff77,bcb04996,e2b65d3c,c0ac9dd3,5ea3e8eb,cf10c372,fafce1a4,d8dfb65a) Z8(4093ab9f,d12a8788,31704923,5fbc6ac2,55608d43,42c6a7de,ae9152d7,8967c729) Z8(54b464c9,8d7a3ccc,35a4a700,99dd5e63,c095f4f1,82937ef9,28d4f197,35780668) Z8(284e486c,580488ec,7deb3043,685dbf85,542952c7,1f24e246,ddb11b98,7d3de5b7) Z8(56cce2fd,556f5646,0eade45e,01ee9ddf,8bb04c53,604ff8ef,505f450b,77a8f82f) Z8(9c6db302,54cd100e,c13829bf,e99833a9,15f0f695,a16effb7,1f250a2e,b0555c2b) Z8(44fd2c6f,cc35b22c,bbe0441c,22e7f3eb,c575133c,2528b144,aa033fdc,0d51a93b) Z8(e0473a9b,279e101c,f9a50e0e,e5e5dc9e,cfc0c6e0,08d55816,159759ad,011330f9) Z8(5529a8d9,b16df326,6eb86363,04818720,8daeeb68,0d38f3f0,87c09b04,c95b91af) Z8(78e87cc4,79b2ad0b,d288ff93,96997a4e,7400734a,9d66d779,1ba1f8ee,f54a7b51) Z8(e38dc379,f1adfad7,c02446c4,d287abff,d78dfb56,54eedc77,a313fd01,bff717aa) Z8(f33f80ad,51a632f0,497805a9,e9019868,19486633,4accc5ed,93418c07,f99c402c) Z8(721d44d7,6d1324b3,3767a410,f60df824,d7b3e4cd,ba342453,4b39957f,48e1514a) Z8(aa90b815,5b56157d,edfd7460,5828dca3,02d68ea2,93231e2a,e3f12d86,7b92e9bd) Z8(2e15aea9,9d5fd4cd,7c236ba2,f18515c3,20d80d05,48dfa910,7715aec0,91703da8) Z8(b7719cd4,252b0a18,487d6fa8,792f0b35,8694580f,979d8b84,dd7433e8,02f90672) Z8(8acfd937,4ebf5a18,62161ec9,2cc661a5,1d0b8ae1,0f5d00cc,7ba2d37b,43b84dfa) Z8(d1bfaa37,3a897964,a928cbda,0480de58,60fdfb74,db407de1,8aeef1f8,261fbf43) Z8(4f175bfb,32070075,b88c45fa,8c78566a,f45bfebc,d780d91c,b9f56f5a,1b30402b) Z8(b823d10b,b005863d,a404cad4,8080d124,5da45544,96231d82,9d51a007,151b1c04) Z8(42c65ffc,e3aa22ab,99206756,23a9bf00,336ae318,5631549e,5e19eb01,b3723087) Z8(d0e6a1b1,80ee4d2e,af8ac680,7b8802dc,4c9fee5c,c7d8fc73,45c71b8b,776f2dac) Z8(cb44c322,60255eaa,6a1dcb9e,a3f2143d,ba350248,c8025b53,4e6d0155,d958f0fb) Z8(d898af92,72f7183a,95c7061e,c91f6542,15facdd9,c13e0fc5,317dd93a,1bdf92a4) Z8(8e0c3707,9e2498bd,a78a5002,477a4a65,874ca621,cb544703,38dc6d91,c782806f) Z8(d5f7a7e7,09e1817f,20d37d29,a2cd4b89,9d3b6842,2e18c6ad,030e9b81,d0c90c21) Z8(07ef4bc1,36afff60,49baa82b,fea6940b,25d8f0b7,df870b88,e215f9f8,08450f43) Z8(753eeb56,b0b8043e,a820efd9,04f69f90,cfb065d7,d53862ec,b8c5f9fb,4ae87be1) Z8(edd9c440,91b32c41,24d3e3e2,dbc7f4ef,4353fd91,184084aa,3dff8b49,a95516e0) Z8(8964afa3,7625df05,0389371c,e8089828,e1d9205f,e75c7aa2,3e83dd5a,98dcb36f) Z8(520d48b3,c2b52f7b,27b24f71,f9ffaf4d,54014541,9e963d37,6572d095,e4aa2c35) Z8(5797e494,c34dd16b,47c29223,9775bcd2,2b62dbd1,e4310ebf,6c7e03dd,f76270ac) Z8(4350b749,515abbae,52942da8,703580d6,b1f2e33e,dd4a3e3b,b980c5d0,6af9adcd) Z8(a0262286,0bb25bcd,c28dcca6,32dc9f0c,42d6fa12,0654d793,b5c73408,89bc7fe6) Z8(97280740,c60cb571,1d09bbab,c96012fb,ddaa5beb,10c6a4f4,aaeb970f,623d21a4) Z8(014d588d,9fb09793,8d9b1648,6bcee7db,1c59d361,3eaae9f7,26dc072c,6192d081) Z8(2231339a,f285f63f,dc593213,6198214c,d80bc2c8,1a32062c,96956976,53095cad) Z8(a51c63cc,ac54986d,f32663db,d75a31b8,52655182,b3c7d560,f34e5bb7,7f35ef60) Z8(f20ea1f7,eddcd018,5ad50d5a,701283f3,1d0f8bd6,84812393,19c13064,b95aa971) Z8(140621a0,7a440cca,aab3148a,057d1b80,74d00138,aa7c058b,af011fcd,da01f60e) Z8(59c639e8,cdc0592e,257d00c4,d8710d98,27cbbe4a,0876e36d,36e464dd,2f9403e1) Z8(2e08e4de,9e1f7269,d9209aba,0160eb50,62178979,c4cd4b77,91d01327,d0da47a3) Z8(611a770d,9821651d,5b0e2bdc,fcebab83,c9bbfb3f,ff4cfde7,570ee6df,4973aed2) Z8(94aa288e,7d8918dd,9e773b5a,3e07dcc8,fdd118fb,21d20f63,1eafb197,0cdba2d4) Z8(32fc4ecb,ea68b422,2d9e44d9,42c8fc86,cd40dc4e,7ecfec1e,38b5f023,88bca151) Z8(01461826,7d2ef73e,54d02ebf,725877fc,68c05473,75c97a39,199cceb1,3eaf648b) Z8(d1efca04,38d09f9b,d1fff6b0,cbacb3b0,832abe37,7bfdcfbe,b3a97771,a065422c) Z8(91909947,8b322320,33bc0125,8c7c62c1,18ff3879,7d6236a7,6bfcbef3,99f77ad3) Z8(23654b18,de3c58fb,b257a23a,20bdd2cc,2a2131e6,f449b192,03082dd6,a0b50fd2) Z8(4333a04a,db7cb6de,f8f8220f,67b451a2,af49ecc7,9f10c91a,01f21f28,3a46fe53) Z8(3a0f5164,9503bde5,e5f5fb4b,706d89a6,dba8d9b7,1b2d845c,80d867d8,9537fbf4) Z8(e2c4d089,5a27975f,6739d7ba,13001446,579d503d,32ced8ff,37edf3eb,6fd37131) Z8(9b466c48,5ef5cf3c,808536a7,ec720b66,290adfab,90bc3a04,6c16b12b,cf266666) Z8(f270a207,97e5ff4c,263086f7,9bfa2099,8240d705,6e20a0ff,dd9831e6,36ad0280) Z8(6ea2371b,a3b85a1e,68fd7b13,322c2bf8,6d7d6454,a493fac2,9ebe46ec,dba2f464) Z8(87520ef4,4c8b43af,cb37b3e7,e55ea834,a689f11c,8d51b36c,cca90ec0,adf734b3) Z8(7536e650,5546c15d,0fc72daf,793e8b16,d3f5c6b5,1117ac72,17e7cfb4,7bd95392) Z8(3b9ed924,52eaeb13,ab6bed4f,0a19820a,4147e6a5,31448064,a43b73b0,9acfd1ac) Z8(94b6783d,fe22e50c,70ca3031,dc2f55f8,c3e4a38e,6d82217b,8cc65e80,40c5deff) Z8(7c1f2b65,d01bc922,f6a5b85a,f5e7c780,aae29108,7bf204e1,6cb381c4,508e73c1) Z8(dd3bbb95,a1aa33e2,a330025b,fd7b93f9,041c1d9f,34aace94,e7bc6b9b,1fa3ccc1) Z8(583c2497,2e650722,80a5581e,3f2a7c9c,e501500c,5c4b5b8e,e76bdfa1,95c05088) Z8(13ec0758,bfed2378,069458cc,4637eb10,ab2b3539,4349c047,ef2ee7bd,c630ec6f) Z8(828bdc33,34453bfb,b9343e7f,37904a8c,981e74ec,a86f6b59,d2fde1dd,de9d7253) Z8(93844b59,d29cb3df,1e2f72d4,de28054c,856b5f9b,ce567322,dec08a6a,0d190223) Z8(22d3317e,1dfdfc7d,e86593ea,23fd04d3,5d2417fe,8428f4ba,c12e69dc,7addbc72) Z8(ff5cfa40,1090b562,6bb9363f,231e1f5b,237c8a33,378fc388,2d47a147,7bd52818) Z8(974e6934,9e5a01fc,ad29bc59,874ce2fc,6e04f97d,fd2590d9,f07e4bea,fbbec9bd) Z8(08cea682,4574afee,93b2aa36,4c39d2e6,6ccb9c52,d0c997b0,f2365a46,a463fca3) Z8(9a77d35a,792d7c48,90cd9d57,e64e9d36,24fc8089,e0c61a35,091bca03,ecb57460) Z8(e9b1137a,83a39371,aaa90958,c38caa09,d5d62609,c9c5f4fb,b299c30f,872c2b87) Z8(bab323fc,d82bfa26,fa81df15,ed6adc9a,b896ba82,1aa8b337,b733792b,8ae1cb8b) Z8(7488c870,3424267a,3e6ed740,4476e354,c0a584a5,aa953e2d,dd59eeb9,ba684379) Z8(58168d22,9f6d1d27,380a0504,108f93ad,b8c79819,030b413d,0975e308,b5decd20) Z8(7b02b9ac,d55d00e6,1174ccf5,46908261,1f1b9948,e503800d,313bfa92,59170a91) Z8(cb2ccd72,b85f1ed8,40b70336,caf642d2,dd60180b,0e5fef9d,d53797ca,8c7ddcc9) Z8(9ce77536,a51c8d22,aaf18d53,e84a7365,753bcc1e,7b0ebb07,95b802a8,1a003ebc) Z8(5c7f3a87,386af20e,f96b7bc4,8ef98591,f284e080,267a1916,9878c5dc,9ec122f2) Z8(0042eb1e,5108ba7d,057252a3,e7a7f105,f207691f,f34d8801,90cf8691,d29b651c) Z8(4db2a0ab,ee8327eb,280b550b,a7940453,dd7a724e,ba16c257,2ec707ca,99e7a7c6) Z8(a0d6edd7,3f14a133,70f305f4,5c48aeea,751fde9d,60f36de7,3763fe69,24491e08) Z8(a9daa465,83827655,cfdeaa27,de868ee3,cc4dcc5f,baca8d09,10f61d30,b73b52f4) Z8(d0c8beb3,47784818,2970c6d8,a91ee8bf,1466158d,7b1b3044,60b52a3e,6ac3bf2f) Z8(259616dd,25512c0d,ccdcca59,3c9a8513,85a02504,af5748fa,4ae224ce,d37028e3) Z8(181ee0f8,46aaf820,51c39433,ab926f67,81d5c728,2ad7fece,9b47c83d,f4ac33b7) Z8(4c4783f9,9ba481a1,e6d6830a,a652289e,12acc474,14115aa7,4da61704,87494edc) Z8(c5b7ad77,ec10443b,dce11b0c,c1f589a3,51f59e00,db586065,2408fe1d,77f06b9e) Z8(9c7e0b38,cde05423,e0f67847,f32401bf,4f0838ed,1f518a69,9fb003ae,1d904ae7) Z8(2e18322e,fccdfdfb,2bff2db6,dea485ff,7e43ad7f,0d81b626,efda0f76,ceb39582) Z8(180b91ec,f938d261,d1b15cc2,19165547,89b6af1d,4ba0cfbf,5bd489b2,8d5c8b0d) Z8(3728836e,be14aecd,47ceb86d,4549af3f,c319de52,08e80a14,d1d7920a,245e5bbe) Z8(f4702418,dda9a13d,ca2fa179,74ada683,b97c4918,3ce95a6f,ecc88b13,2466f155) Z8(08ca6e7e,98d10dfa,08c7621b,6a9977b0,ebf7a6b1,3e7845a5,e0dbc28d,1de34ccd) Z8(c78da9c1,123dce18,94c7494b,48be4cda,ed199e0f,a1ac78c6,622a77f2,4a8eb9d6) Z8(9e90f210,31de0bc4,b80c8ec8,2b06caa6,65fda265,69b90d1b,671f7b96,d83211d1) Z8(a24c775e,25502698,72e1d200,e31a1ba8,f899b652,df3c323c,e38e9b3f,77b228fe) Z8(d3fd1156,70fd4139,0e914fc5,d07842d6,9f19520a,509e8ed6,4a395f8e,ccff6504) Z8(69137590,1dbf1578,c54c8b11,382e885b,9f218d96,cd42d4e6,5ec82dd6,1aae09da) Z8(a62b01b7,ab9b1731,d1b7e0ab,f8f42c6b,58d00fe2,5a3b1445,bb0eeec0,24bc8002) Z8(2199aa70,3cfb9675,d9b46106,c7cbc566,382ecbfa,7e2512ca,4b5b2735,81198ecf) Z8(fce74681,3527c33e,ef971965,a9df4a0d,89a9a7b6,0cdd4b6c,65df5edc,2137d0ea) Z8(630c44d8,72358686,fe47daa2,bb3a6f96,6786c864,ef8f3db7,347a5fdc,09cf41e2) Z8(bfd425f5,1ab277bf,de65c3ca,5b8e6ba1,0627a74c,9e8c9b82,d0c7b3ae,a36a5882) Z8(e0b01b48,463c4fc8,93f4c5d7,edb95c21,142990fe,453fb14a,4394cc56,476644c4) Z8(9a23a668,7e6c577a,38bdc4a0,7c4e63b8,b3c16e35,9b39af61,4a652a7e,99ce6097) Z8(290b6935,731f83b8,7df0105a,1933ceaa,6fd94f4e,f3574565,3a14c7ea,7921624c) Z8(756b23db,ef7f966f,1e1023f1,f3b8e410,5a6e9f44,6de00f4a,f6e6f9a0,e7607f9b) Z8(46f26034,23327a8a,ff81b848,64e4038c,a61cb84a,2f9a8c1d,5cdd984e,0c925c8d) Z8(ea81cdea,2626a199,2929bf9d,81488c05,c7c15525,86577831,2b04c310,616f1fdd) Z8(7898f402,a79019a6,0080c7a4,1ebfc564,43a685a5,c9f00aed,da460ba3,e376b819) Z8(2a62760f,d18d56fe,8621cde9,07b84ab6,e012b055,d36078d7,97af6b03,e6a41441) Z8(baf86dd1,020d1c20,6d4e13b5,f1983188,30c754c4,2360ae4a,7d624c00,0e4b980a) Z8(f1dbf23b,d2518d5e,d8e3647b,b49759d1,6e0edf79,cb45a21e,4ce69ad8,74096bfd) Z8(f3fce937,75aa48c8,52188249,87b63c0f,33e9d711,29a8936e,877a941a,cf6ebd5c) Z8(7ccfe177,f06f4429,cf31b1ac,87ee5705,10620d33,3f7934d0,e2d321d0,4b3721d8) Z8(c03b8f49,b46cdf79,228d43d8,368f9f03,da5517c1,013dc2a3,1ce7661e,c857ff26) Z8(751bea46,81faee6d,38ff4daa,435058fd,17338de0,67c10455,d5120103,5d38d99e) Z8(4aa8e3bc,535bb263,ed52efa1,c44397ac,343dba42,dae4d90a,8f46fbce,e8cbd58a) Z8(31a4a929,d20aa71f,c0385d43,b3637ee9,9de04922,2a93dbba,8d365387,d954bdc5) Z8(b25bbb4d,579f7af9,0152e74c,8277cbcd,3f77d833,12da4fb1,9d1323b5,73cc5af3) Z8(68f8f4cb,76f7d7a9,c8b67e6f,139a6bfc,1d622ba2,757dd8b2,5224b055,099cf151) Z8(c87c7243,494f8a38,f369a455,dcd990e3,b2edda84,a73171d9,9a16a0ba,086b05ec) Z8(44e075ec,d44d32fc,27fc66e0,32841bb1,10ed48f8,b6e9edd7,46a3765c,611d977e) Z8(150e31e9,a071f9cf,06aef18e,fac5b78b,c29c79ff,41f99c12,db7e1585,a7a783ba) Z8(9a82b49d,c6f7999a,287eb113,9efba619,c3bd5de0,859d2187,f0e1d62b,6df60879) Z8(304da8fe,7e18e0f0,c76d5c96,5dd800dd,490acc06,d75177e4,675ce1e7,a906b56b) Z8(c65140d0,4c755c6a,90d94e56,fb62f284,f2112889,8936dffe,2ed38659,13e63c6a) Z8(80c5ac2d,0eff7b08,7256a82d,d713198e,deb6bfe5,26ec4b37,2cf1ecd5,7f383386) Z8(c0588a6f,e0e44238,f4ffd6e1,afd85a13,71a8a87e,be91b944,87321d3a,931e6354) Z8(d09096f9,fb477db8,d4b87b53,a8449dd7,ac1acfe0,b86d3076,b9439077,dab131dc) Z8(9057ab2e,b4a4e8f2,f5169920,4d5d5da2,e7236608,888fb623,4745ea64,fabc947f) Z8(35b44a34,6abad3ea,7484f02d,2ebd7ad0,d2cea2d8,6e432762,4022f31f,5cbb0de2) Z8(f9f5bce8,8e3d70c9,3d32baa2,2436b9be,a3672411,14f8c9f1,3bd7aafe,909e2711) Z8(2e920841,d044ecca,cdac3828,cc2501ab,7ceddd59,9020880a,1b11cbbd,6cc7c3d3) Z8(aef92fca,1add679a,b218043f,7192b976,4b86d4ac,d49b34d1,8c1f4c51,5f8abd9f) Z8(a1e5b13b,bc7d5d33,1be064b2,f7f75d90,37445092,58335dc9,3f95dd3f,5f9ecc3e) Z8(5c68d877,9587caa3,01a429f0,a0018fd0,6f8dd138,25e5c324,2e2fd3c3,6a0e9c64) Z8(58d38a15,fa7a7272,e1089709,a86565d6,e0593c37,f21dec9c,486b080e,2506b096) Z8(610cbded,8b493876,8a3083c6,16186ec2,7592e3b3,138e6d25,c55c0e20,c887b711) Z8(77896c91,7e5a7c54,be4939af,375038d3,e2b95c76,ed798f2a,7e692a96,bdfd2e14) Z8(532de006,400a6c6d,0c630b6f,8b109f4a,c2a9b8bb,ce0cf55b,36937885,7ea37951) Z8(f92d351a,67916341,73919042,4cfe26cc,492d3893,1d885956,c741b727,f017e303) Z8(587f79ab,3bdda4cd,d5b16721,696f6f93,5200f1ed,8f4fd2c7,c572da94,23186093) Z8(8d2ce6be,0b70a4e3,01ff60b4,fe061c7e,4ca16c97,1b3c9495,fd11ed48,34e7de5f) Z8(237add52,fae088ff,0460285f,e50ac3a5,d2f3ad70,315708aa,462210e0,45d31a4d) Z8(5e4de7e3,386bb615,27c59ac0,71b37ebe,0ee77bc9,5fb5fe5f,413d9b05,4f36e754) Z8(6e56a720,2e3a24c7,90a9f912,8929c88b,45db0db2,6d86d4b6,7afdeabb,edfce6d1) Z8(b589ccdd,049c9ddc,b12ac0b7,c94829e5,b5a3a4d5,d17d82e4,08a5e627,97930d89) Z8(30fb8873,d6655d63,a9df95ec,cb7a0bdd,1b95a40d,f785fd5e,9abc1803,7d07461b) Z8(3e6e975b,4a9a2aff,b9963359,6f434532,23cd4ace,4598d75a,cba04209,8f0b0a24) Z8(22263ab7,8f3ef602,d61531de,cd5781db,f897f469,30126888,a2bb24ce,e3537ffb) Z8(adddb49e,3c5c438b,dd202e1d,766c0503,27044eae,c144b945,e3170844,cf82f7fc) Z8(038a3476,a59a87a0,b8f22634,f9fe5a38,31c99582,87431857,633d7400,4dd2c4f5) Z8(c92f3349,556cfe3c,12076c46,fae3b105,5597d37e,0f6946a4,a6147a51,a6ab9b58) Z8(85230c4c,a5c39c9c,0c6f9991,7554c807,82c757c3,9f101934,b6ea1cf4,041f9f0a) Z8(be455c12,235947e7,c510a3ba,d5ce92ea,21c24064,adddbcd8,fb85f5e8,8f8b14ef) Z8(c044d454,1488b79f,c6c30e10,3d413e3f,0b3230f9,e120b545,dfc146f6,1a41ac2b) Z8(b2769a93,a337a159,e9208332,3c7587ff,dd1e7c23,fefe0ac0,b33084bf,0c2dd6f4) Z8(9c702421,0c6cf357,d3e34923,b3033531,5268dc2d,3bb6ae06,9581d437,6ac9d3c3) Z8(4835d324,3109b84b,649b8da8,e92fbc1d,ea444a5d,d3816f50,2def51ca,3f3e1c73) Z8(5805bf0c,12fff876,550980c5,0a5f2ad4,6ec61c4e,9a393b31,397378c4,67790811) Z8(46ed0177,a2db9593,d230c2ce,8c2bc0bf,74d81271,729b0ea1,37330114,aa472b52) Z8(54d14eea,7b5ac4a6,090bf753,0d46d356,c308cb80,0f65c5fd,a8ae8ec2,1373158f) Z8(4806011c,872cf023,232ce410,f5b45f85,00c309b3,bfe548c7,ec85c526,d64de4a9) Z8(83b9601a,e725b042,cc4b4204,33411a3b,b97487e6,6dedccd5,d764ecfc,ba013302) Z8(f7e3e5f0,a010ac5e,66993aad,a7c92188,c6c36e8c,34ac7ef2,d64cc2b1,b474db56) Z8(253cbc6a,167c9748,a5c383d1,eb9f9a5a,7910cd20,bf573dac,9674bfc8,8cc3ee79) Z8(9e2d7e93,570275da,450a6703,84c5eebc,2210adfa,3bef6b88,413cab5b,6c8b5573) Z8(46c94f8f,e1c2fcf3,04ab86d2,515bbf12,5196e9df,7a1af850,4b9f6cbb,ff6861c0) Z8(31bea978,ecaf42df,a2258cb6,0f2f2b2c,c5ca8c83,b2a8d5ab,f09edb82,4bd9290b) Z8(abbaed5a,9cf213be,234bf07f,6323274a,7f4b1091,d1b64712,4113a3ac,8819329a) Z8(7123ea0c,f0c15e6f,4a0d13b8,4365205e,86eef405,861f5d00,1634b9eb,550765a5) Z8(33d1c1dd,af0e0aba,5af86606,4b7726de,c9cbe7d6,b4392639,437fd669,36b347a7) Z8(6aa722bf,d0d5b23d,23e7520d,60c146b5,2c00b016,68185efa,95fc7d6b,5bb53c80) Z8(1e00d798,52a62474,ee7268d1,2ad34471,5bb620b4,8f2c9e89,c96970bf,534dc286) Z8(b94ed4a8,b5a08d93,50cc569d,03be6af1,3eefca5a,f16c7fdb,c0e68e0a,a7483394) Z8(4cd35bfa,6b70861d,29ad88a9,fdf5ad3a,7087926f,7f660805,1faf7094,98253b63) Z8(790cba6e,d73951f4,e1e9eeb6,2b250997,72690360,936f66cd,9dbd5b6c,c0c27dac) Z8(76bee1bf,3d99dbee,790d6cc1,8bed161b,f45ec91f,b0439a24,c0a2d8b6,57c5daff) Z8(bd4c7b7f,4849b0b6,02e18333,90319ab8,85af3769,805ca8e8,41d03a42,f576cb4f) Z8(d9566b89,fd97cb66,bf19086d,26c9e817,a824380c,0a07fc3d,9a8da5fb,77c96216) Z8(e94b08d6,cd4946b3,b89f5eac,36521f06,aabdd3e3,f6b275ee,fe231a38,a761d3be) Z8(0a8c83f6,88699b9c,2f6e4cd2,2c4f4d6a,544a6464,a942f701,83c8268d,f2576801) Z8(21fb9ce9,d358ac56,b834aeac,bdfaf51c,b5da4acd,741fcc30,d1072d1b,00fb9026) Z8(08badf33,697abe14,7a068c69,42cd55ec,ace3a6c9,708ccf4d,05b374c4,7d16311d) Z8(fd5d402d,b1004cf6,a8bc4cd2,875ef5a3,0b94c482,cd805bf1,9bf8b125,6d72215b) Z8(7679ad17,e7d589ed,1c58611c,c0054c1c,e45d269a,050d9da6,2942f9dd,3701610b) Z8(7ade70a6,b76a46df,356b0d1a,8d8fe1c2,139920de,5b9b47c1,2986d24b,ca531de8) Z8(5c52f0d5,e70019b6,d59b0845,691ebe91,57e122c8,003229b9,2b35b4a8,ae8c0772) Z8(776119d1,6dd399b2,cb923bcd,052fb98e,2ba05e80,1fe2568f,dbddc609,e937ddd1) Z8(6a475899,84cc47e6,7a63adce,90d1e82b,f352a5d7,90316f92,164caa2f,96b9e7c0) Z8(46bbdce5,fc73d794,843e0993,f2fe5c38,a6ae3b2d,69529381,3de4a7a0,ac731bd3) Z8(e66ac51a,f3657e01,6b7d88bc,5883b5e2,8a6d87f3,32c83827,2e9cc03f,7becb1e7) Z8(73d89140,480e12c6,5effbf80,943ed5a8,c18ddc09,56b3ac87,0f522160,c8e52004) Z8(4886a5a3,81dc5268,4155560a,3adb2b73,7fb426a9,fea8de12,4db626a6,52bc27b8) Z8(07276d82,c9ca533d,29b7b89b,06dc7197,5d879fed,b69758f5,58506420,452f6228) Z8(086e8bc2,70071dc1,b36405ac,e0446e90,0cc7f7a5,2fab8616,71faec92,96d1c338) Z8(cc4f650e,2bed647a,90586864,4694ba03,940a6a53,248ddce4,15a88d86,364db3e4) Z8(5fdcbc07,6343ed4b,95fe4bb2,ce86f7de,c5cc16ff,d978a042,9846ad2a,be969017) Z8(f2133494,7db9f9b7,3fe64299,bde86347,52be925b,6ae1c560,d835fe2f,ce827c3b) Z8(0a170c24,a4fbb323,f6acf6d0,42ce4990,0a13bb83,598c626e,ce20fb22,66de15cb) Z8(5b56edec,1f8f4fc3,76ed5761,5dbb1e69,2ca0accf,4ab7719e,d6b166bc,d1d7e493) Z8(02ba9518,29aaf7ae,6a47d8e1,cd77e530,da1b4709,a7cdf8b8,c6911ad6,71b982ca) Z8(f149733c,433d14be,0f0f8dec,ee7c5e6c,921862ca,91bd9068,b70ca66f,7ca6a0ac) Z8(980cce36,15bd438a,17235e58,a0c02814,267bfeaf,3d052a8e,ba05d912,501598f1) Z8(2510f1fe,75816fe2,a93e16a7,33cb178f,7d796521,acf22f9a,17f6652e,5dd47253) Z8(c5e72196,9b42c377,15e8f44e,b942075b,31c25f64,542a0630,788c6ea5,c8ac3b73) Z8(4405328a,ee74fe80,9c9083f1,118782b1,1be3b315,371ab357,9516f209,ba3902a5) Z8(3da4d693,f2ef6d33,08f3bffa,031ac558,b275ea04,7d1fb15d,e33c72f6,68f5ad6e) Z8(234afc78,dc2c6217,b06cdbe0,ee7798d1,4ac5b150,b942426b,f5153e9f,ca26d532) Z8(4fc16886,0cc1c2b1,f44b0ab6,0ac52de0,e78242da,254802a1,86e8bcdc,b9477099) Z8(0f7a8947,a6f8dcae,cbf31492,7eee200f,ae258a11,75dd7153,6542858d,75f71e7b) Z8(df5500ce,7b759721,5bfe1895,ccb3b591,e39ec991,ae1789f2,9ad124da,8868a14f) Z8(e7a2cb6e,07456f0c,f5be13df,0472edc3,c59370bd,3def6483,5d78bb17,954b0571) Z8(b95ea78d,91bffb26,eb0016f0,3aa81462,69980dbc,95b6b8e9,3815d880,83c117ce) Z8(a053a56a,6439b1f6,7105586b,3985a989,26e6c1df,fa12988f,262a4722,aa0fef89) Z8(fb04db75,f848a2ca,e3176074,1d561252,956d9a6a,dd7d78a0,1a827dcc,eb32f25e) Z8(6c28dc4d,a938e725,c6bf49a8,84e1eece,642ff0f7,01954eeb,352b320a,d83055f6) Z8(47f72d70,7da2a6d3,a11becc8,13d430eb,00e845ae,cde56a32,62e3f081,43200b26) Z8(392d8ce1,346e8b35,cb7d1911,21abde48,e83adccb,9301a4bc,b7764d2a,ed0959f3) Z8(c7ef0eb0,0dd6fb44,9cba8e52,49ac5d9f,50b095da,745f969e,ae8ef3da,02b7c8d9) Z8(9b9532ba,c5b7329c,65849245,c3aaf17a,6b5deaaa,78501306,20cc7c54,20ce4820) Z8(b3ff5cf4,eed3f4c1,1bf1a239,a1967f26,e2fdc943,cd1db626,a27b0d6d,e20a86bf) Z8(d4c9888a,a0a7ced5,b919d049,293c7093,36e4b638,158705d5,d79525b4,cfd73f55) Z8(6722a8cf,ffe57aa1,46a25a88,71d66d16,49b009c6,2dea97dc,63669d88,8e064b3f) Z8(c9be8ada,1f91d799,f865cbeb,778cbdd8,521b46d8,f359b473,4e922221,4f90b322) Z8(918282b1,024873a8,c86b9f32,5ba779fb,1bd16947,895cccc3,9a6f2f4a,8843b388) Z8(8df6dceb,d3b9533b,eaa575a3,75e3a4b7,2ee4aa93,6cfeca82,80677af0,fb6f6218) Z8(69bd8816,a394c8b8,2464905b,244dd334,19cb7c6b,93525da0,1b874f1f,b1afd8e7) Z8(86c0ee7d,d2180f30,e4e39e61,312d2ade,a4225596,682a3b29,ff38a967,a36aea8a) Z8(7a2b3083,6a2e159e,340be36d,aaea6cdc,bf607a64,d3ff39d1,ebdda28c,970f4d17) Z8(fd03dbed,5e183bd7,0782ec37,e0eb2eb4,4f362b62,f1e1f7d5,42344330,01dfb051) Z8(fb7185ce,7bc0d3d9,43f5e1ee,cae6a5ed,cac57779,61b2ed55,8afe5f00,dca425cd) Z8(9c9ea008,ddc17954,0c08df52,0052a097,6cd5a7be,46fedd33,f8bab6c5,285f3e90) Z8(83afe269,702a6cd5,2ea6becb,cab998e2,8049fa03,2a34e63b,2c2cfce9,991c1845) Z8(eba0cc74,5eed6701,20e9909f,1939ff68,098da512,5bb7e081,af26e423,93a6cbef) Z8(c11aac50,791431d0,c6f919fe,680a0ee0,ae63983e,019eb216,df7c02c1,5351e600) Z8(8bc307f9,1ee93044,5c58ea7d,e2810e80,2fb2b4fb,5c8335cc,3133594a,9011aa57) Z8(11597a56,55ac3e16,5849131c,037fa0c2,ffeefece,86b12d36,a8c57c0a,d4912a20) Z8(b656b717,33d597a8,5506c9fc,cc27d89d,300c207d,81391a43,5f93f3be,ea328a0a) Z8(ea95a777,213cbe01,2cd70c4d,8758f8ef,ad300711,5c9b12ea,54550b15,18975b26) Z8(b811f643,287dd141,a9b92e42,e9c01494,25e4841e,6d3d8859,c581aa86,15ba2a2d) Z8(76b5dc2b,153be21a,fc4172c7,aff62580,b9e2ffcb,955eb0a8,031d42a5,e1755585) Z8(5bcb50d5,38305325,5123dcda,d08ccd55,0942f9e4,ed14133e,45ba173c,d80e9b84) Z8(3a828deb,9b49b906,7b6389e9,618c66eb,4f5f391f,c5a1ce3f,e7af2675,dafbeca0) Z8(42640c63,957a94cb,d48a412b,b41c1544,3cb6f318,b61e05bd,d9ce2897,bb72ce86) Z8(cbe41a2b,3b3cc419,c9045029,5872d95c,e99d65b8,14167d88,c0a91535,83946895) Z8(36de1028,37321241,5dfc2732,93802c4c,138ce47c,c2a593a3,dc73c5da,bba63903) Z8(0868fb02,0fb3dc65,51291d5b,befe6a7b,c2869c70,2b4452c9,017ab1d6,176b0585) Z8(60901507,57a454e7,a80b2fff,ef1cac0b,1e418faf,4a341f76,995ea184,b93aaafa) Z8(e10668b0,8632b7bf,176ed32f,4e43a223,1f41b717,ce6506bb,39324a48,35f992f6) Z8(66c67fff,76909e55,48c91f2f,1b5e6948,08c11d5c,8ef713a7,71e3c85b,ccd3e78e) Z8(83a2ead0,1f4a4750,edf859e9,c04aaf63,12b23463,25418c32,7eee1220,1db3a350) Z8(d9aa5ae7,531187a0,b01933a5,1a3f0850,de463ab7,4c8142de,cf3759d0,7b715073) Z8(3ceed410,f545c91d,9f446915,04b26636,5b65afb2,e7e67bdd,495a9559,a3b9cdd5) Z8(36e3a419,c7317837,a2085985,ec7b7153,fb4df77b,d4e9384f,493b030c,4d5949f3) Z8(220f8d18,a6aa093e,6a22e4bb,d35435d9,b1dd76c5,0f47c7fa,baa82641,8fbce82a) Z8(b2446408,4852e87c,1cb50c84,66767c8a,5846e267,6ae1cbfb,f88c9f9a,af4a0fb0) Z8(c41e616c,74c0253a,0e3a4846,019eee75,77101b44,eca53360,2441c349,49c3b3f5) Z8(8b679e5e,5c56b2f2,deaab967,c8cabe90,a6b4e7c3,793853a8,d96a0b0c,22efd10e) Z8(2c1682d8,1a491b8a,82889a61,f993f6ed,653299e4,0b55d51b,ad08cc4f,e2b3d0f3) Z8(0c07d7da,c9ea2cac,e95fde9e,cc5bfc31,fb9167b0,13308fe8,1f89207d,d6d79fcf) Z8(f3f14268,df46cdc4,c76de5cd,9759574a,cf38f038,4e02fcd0,c5e17c5d,b9cd71b7) Z8(2b21fab0,7b4c07a5,c9ab6ff2,2b00982d,7bffff5b,f4e9d7d6,5091aefc,8b400da6) Z8(3f0e4133,f40c46a7,6b064188,1bbe07ca,a544f5d8,147f2aef,0bd42a7c,e3b94afa) Z8(6c1b1839,9d175111,3fdfb317,2ebdb34d,a209e18d,58bbfde5,f8e99546,ae741687) Z8(10fd4e8b,fcc8c784,0492db4c,cfd1b320,fbeb5bf7,a032f49d,30ca007a,8bb375a7) Z8(87d5c5d8,f73d5c96,734b2bd6,d236a9f0,cf4fe740,dd97c6d6,3076dd01,a0ea1598) Z8(ea4cab04,1c062458,012a3381,e8ecd823,d1696aa5,43743cf2,bcfa9f4d,974c869e) Z8(a0bde6a1,98bb0d49,d48e33cb,39081c72,a0dfa989,11ed50a6,f9f6b9df,3bed4762) Z8(d4e10d3e,ad4e61f2,8681532b,abdc4460,06863774,57147646,579f183d,28e275e1) Z8(c482a053,5bea013f,02f3f9ae,a704e316,076e9171,82eb7662,c37dbb25,43e21d5b) Z8(93b1d63a,737b80a8,00cb8e82,44f6d7b5,9b341aec,918e6ebd,a18bacee,8d4d37e8) Z8(1dff9852,7a77724f,3c9782fa,b043f425,492cefe7,f7abed11,1d050349,6d64858f) Z8(e50cede4,16c043c4,5a8680ac,7a09220a,68365a4b,843028fc,48aa1dc3,cad5d464) Z8(2ab5b79e,964d1d3e,4007f590,f31c8568,c9da8b78,4688c362,f4a6ef7c,d3720a30) Z8(3ae21974,c1c3289f,32c80296,607106ee,6fd6cb7d,3e7630b1,85327f0a,dceb64ef) Z8(f1a55f41,59a2a895,09896c2c,a35fa956,93c533ee,f8553aae,dc7416ec,e45ee4b9) Z8(5d29f522,02ff90d5,117833a8,2c140309,48de441b,bce89d8b,02fb2d10,7da4c124) Z8(d58998b4,5386bb89,85197da4,aef2ce29,31f02eb5,8ec46d05,610daef4,8cefbc10) Z8(380839d8,7dd5ec94,72c297f3,dfd25833,968848da,1e5307df,58e0ace1,95bec368) Z8(5922e359,b6d2e1a8,ef8dbee2,fe78988e,91d83558,97ef4614,619dde23,3f9d5eec) Z8(8c3e7a4b,49865a20,b6ad2a7a,3e37a8ed,12958f0e,549369c2,90448344,c8482aac) Z8(b3aba320,da606c1a,0d73d040,9b5f8780,e675eef3,57564bd6,990c8f05,49f32da7) Z8(afbab41e,ce868f4d,7495e02a,58a044ec,3deb0214,57c19884,794aada6,94f5dd8b) Z8(f4933f1d,f9d873cf,2297a79f,8c6e388a,39a29cd4,7ab7d9cd,00f25d49,5de66438) Z8(a34887d3,7f1410d7,41a06013,3d4cdbf7,d0ec6499,25cef2f5,ec61b251,c0a965b1) Z8(0efaa295,c02bdaa0,7264c926,eb0352af,6db68069,8c0d9726,6c8ff222,45928cac) Z8(57313ce3,075231dc,c1fbf763,efb77714,5fdf267e,e909a564,f0222a98,6af3783f) Z8(5a1396f8,56a4a5df,8f8ad35c,5e2eab6f,1656adaf,9c5c1d95,e59fa3db,b7ad2025) Z8(8bd3efb5,bf493276,bf693bcc,7fc22c59,280bfa83,583ce7d6,82d10d5d,87a93f10) Z8(8da862d3,bfdcbdd2,29872e75,50c44a5e,a4cccd03,88224389,ca002665,8c320b7a) Z8(9d3d4361,2e0c456f,7cc32ea6,34889ba6,98450e07,274b5ae0,1a3fb62e,c88f1232) Z8(2f1cbd02,e1de27e7,1e8800d8,9be753c0,7b463997,8a07246c,4566e636,cabbf675) Z8(31662e2c,4e1837b8,07b56f2b,fa84c76e,867b8820,0ba61f51,08e7fa13,be4e7034) Z8(61a14cba,c962f6d2,e1e3b64e,ac970c6e,b19cba06,8c8ae0ec,723d910c,886180d6) Z8(9233cd76,7987a0a6,737592fe,7440aa3a,e91fd354,97f10e9e,af4bea93,b0e6118e) Z8(15c7a0c7,c46b7406,c6aa0c04,5a4f71a2,971cf472,025922c7,eca87963,c31b0a3b) Z8(14078dd4,1622986f,dd6d1651,dc195205,3f7f425c,d438581f,6ac00761,083f5784) Z8(02a29b8b,3aa86498,99527bfc,f8f4f5f9,27ff9b66,fbe83417,67eba34f,59099dd8) Z8(9960317b,20eaf4a0,1d63c098,55bdd7ac,c38f093f,6f8aca92,72b581b1,8a65617a) Z8(1191527e,4285d260,2e853fb0,9606a334,d388bc6e,de5a11e6,b1c83a70,f11a8b79) Z8(f525db1f,61f39162,eeceeafa,c430cdd3,ef221f02,12228034,0b7f6b3b,c2d557ff) Z8(53ee8716,08953a9d,f5d8d739,94d55c8d,a77c0161,2fe7b8a4,e4d70aa1,230ac40a) Z8(f229fef3,a4c0b379,53a26b16,fd6d2337,5fe3baa6,233b1df6,9622d9b3,8e0cf071) Z8(957c7714,11d61770,b6935bc1,3763dc2b,794122cb,e6ddb461,11194f6f,cb84bbd3) Z8(744b25c5,2e509f28,02691bde,cf5ba5bc,24c35670,09d1aa3e,5a9fe595,41cf6d4b) Z8(30ed9d4d,28277b8a,3554e11f,056db1d5,73bb1a92,406a866b,4fa1de95,4ffe68e4) Z8(da1677b5,a365fcb6,0eee3b51,37d0dc71,94c249f6,bfce70f9,768739e9,52e4e4a4) Z8(3c60744b,aeda5671,8ec61c4f,7c6adfd0,12498d88,92155d00,cfcc3078,d9d832e4) Z8(e6ec7f97,b56926fb,ebe983af,33665522,2533cda8,1401b20f,433ed799,e66d9810) Z8(a264e4e0,85c6323b,cb5192a9,e871436d,028ec890,4d1e5449,5a9f00c4,4f521f15) Z8(9b0454e2,0221394b,c5314d2e,0e939efe,504418d5,e82bbc9d,f517f9a0,9d4059b0) Z8(5e0efcad,8e1d75a0,5a1f23d1,4bbeee00,749eff9f,6a307d6f,102addcf,04254dac) Z8(763f4dfa,818b6823,270c6315,d70211bc,c5ee6a08,960010b6,7d15a1ee,f74c2778) Z8(631e6b9e,0fafbe7e,82b22900,3b528bb5,2e29c890,59476f14,d331919a,3523b958) Z8(6e64b08a,c36b48cf,2e79112e,956a44fa,c10d3bed,f79ec810,12fa52ff,8f85ae6e) Z8(1f8ffb56,196e7c30,7b142c79,d8418038,078996a3,fea58906,d91648ff,4321bdeb) Z8(71d46367,f220cdc0,2a2c5ad1,051eccc2,1bd0a390,c897e7f3,88817346,cd6df0de) Z8(9b200c69,f5093969,905706df,5c6b7e66,b68abebd,fdf39988,41762eee,35870047) Z8(b9753813,66aa9d68,33d53736,c37534f5,341ba410,64131587,dfa1f6f9,e7cb73c0) Z8(526f0ff7,386624e0,b650e37d,f3ebbc68,74346f65,0aba4ff2,06609763,dac8a667) Z8(dca05fea,2d8f990d,c296f834,d1639b8d,f8dbf919,887c6bb7,67e3de7f,8aca661c) Z8(c95d7ba0,755916ac,78948a5c,c7874e50,aa150206,18c8f543,dc1b339d,855c0716) Z8(17b29f1d,7e5353ca,954590ee,2a0e4911,0c57261f,f690db32,6dd6a8eb,1c704d7a) Z8(cf52f1d6,7442a742,fab21d62,0d7c3bdd,aaebe31a,e077ca60,f79c5dae,c471dc49) Z8(68aee2a4,be32b6f7,3d10361c,ce4e1ba7,727faa0a,f0d98098,08e07365,2e68338d) Z8(392cfcd7,076acc2d,a9989733,519bdec0,79af81bb,d220ace0,cd4c0f99,af3f42b5) Z8(12768e02,1cf6e589,67484515,9dabd91a,2951cac2,789e20dd,138dae70,11c78b3e) Z8(eff14881,5040d9b3,0b09bc16,ef158fb0,8556f681,07107ff9,c56117a3,49b8c0e7) Z8(efd5333a,0d84b8ac,acc89f29,5a600153,4ddd0a63,1491317f,6044367f,be94f619) Z8(fb872c1d,cf13ae15,d5f188af,316218be,6df60ecf,ef2a985d,eec4625b,ba4c3ee3) Z8(5866ef72,e2822c20,52c13cce,c87f64f0,d9fffaff,18192ff3,11b6ecd0,fae6acac) Z8(b5803e5a,f00fa507,c04d8a5b,d792b681,dcea2df2,9df1dcac,ce8c71fd,9a7f7b66) Z8(28d9921a,c2ba6be2,6f06edc6,5f44e617,336f7008,51611c51,25529c86,fa29df27) Z8(e9b4b842,c0666356,a0a8b1d3,3791a61f,75b023cc,19a29546,1c31683d,94cb6f01) Z8(5afa4099,89566267,c850cd74,4fe4df47,4688892f,2659967a,57dd35fe,e7b6cfb7) Z8(c8080328,5b479107,9c6abd86,8515992a,32404442,9a97dab7,e012a850,9601097f) Z8(ca634d01,e4335cb3,76de156c,a33293c8,4b837ea7,d6d70776,fb9b910f,3d8db05b) Z8(d3f11194,86d8432c,a1feaa0a,f14fc860,97395d86,efaf79d0,aedb75f1,79c676fc) Z8(83aa278f,3e8f22c3,a7bd1227,b1e3534f,a720d542,8d379b22,56ca5dc7,13ee88cd) Z8(31ffab52,39d25067,a278b60c,d3d33b6a,63119530,b44ab647,2adb1191,18237ef8) Z8(34f22b51,090f2ab1,41911288,934cc14f,4ae3f63c,8aebc180,482548e6,8cf24603) Z8(104f1887,fe0caee2,256fb806,3969c5d4,5748537b,cbfaf6b5,5d5b40c4,32008fd6) Z8(27fd9d3a,5ac1e543,489061fd,58d893dc,11b1847a,f8cf2d80,0097e897,69b5ce6f) Z8(96770a6a,0b1b86fc,1b112eeb,12e966a7,572d7df5,c474e8a8,456a2dca,01167807) Z8(494cfc22,9f43b959,be85e2cd,0c0559e2,2acf87fe,a701025e,a041561c,f7832f76) Z8(b9b5fa0b,531cc86d,a863e924,b64fd5f9,6306bcc9,7d1f5f90,cee445e7,0b91942d) Z8(a335916a,fd3f7974,35bb95ca,3df7cf9b,0fe9cdcb,792e5107,9558d0f9,21c1b2fb) Z8(455fb438,404b3bcd,55757560,9cc09b93,261f3c74,800132f4,7b52b23d,c374216e) Z8(0b4d9d63,c8135a19,246663f0,8c5b0866,efed5745,a1bdd3f0,2b0da37e,d9c0d748) Z8(7b9b3231,07a9efd4,ab48427c,21d7a1db,fe6077c5,d9c8c990,67f2bdff,c38ab429) Z8(240d6bcd,b2756011,3476ad24,e92eb428,44378719,becf7645,253fdc5c,c2b44222) Z8(38779f49,20d499c1,769be459,f8119a83,de84b55e,e2d32d02,1b0a9226,3ec31c17) Z8(378abf49,01d56cbb,b9885dc2,5d3b1d5a,65e94d44,e0ce58d0,68cd3907,903f0438) Z8(77f3aede,6cbdc326,a5c6a6f2,886e45ca,a1595410,5fe4f4cb,a3d851da,bf3c6749) Z8(cf89d8b2,1eb7d0d7,552ff617,bbc8c71f,bccb72f2,920e5c68,b15e9c6a,7de0d9ed) Z8(66442932,57eb3acc,23d73566,7616b661,9926ac0c,b04d54ff,c21f101f,e24bd5c4) Z8(c751cba0,5afbcf4a,eddc1cd3,44d6ae12,818cd49d,f3709121,a3035e01,659dbfa3) Z8(adc11a63,d784be58,7235b332,e4fecfb8,412b7173,87b3d59a,d0a4f2df,b7361143) Z8(0dc59cd8,c9cc57a0,8f07a0dc,d2bcd617,57aa07ff,276c0953,134879c8,c543a017) Z8(7a0c3f01,40e1b0a3,10666b04,11388e41,5a8e5f87,d0527e11,8cb487f7,0dbe7b1f) Z8(08652ea7,f824a5b2,f34a36f3,6cc33798,3789e49f,ac6aedee,2ee38e78,d42136fa) Z8(084e9f25,bb942228,db5fd45b,3b67eac8,19327889,378748f6,035b8fa5,d4270257) Z8(937783e9,db9013c5,e968d8be,0ab07fa7,96fd5f73,22271dcd,715d950e,dbdeb0a3) Z8(1d272b72,304f25b5,e5536ea3,d5ce8752,3db315d1,764dc96d,e0100eed,5058c177) Z8(b8fb625a,1a41db4c,f81b9fd6,bebad89d,6bf22cf8,aa40c34a,1f0020b5,68430638) Z8(c4b3a894,f36277a3,f93ebb13,dd6375fe,7a70ec8d,d3a2c6d5,3535a3ca,50d5625e) Z8(002a2178,f787012c,f39a1f9f,5d5d9e38,d8d3df06,2ef31fb5,82043f4f,00275494) Z8(aee63d9a,790149d9,ad703190,8fed2f8a,9549d6ef,caa2b467,8402a9dd,7d122e47) Z8(4c9f4744,de5f442b,e8945760,920af509,6035b8e7,9ae8dbca,b9b4825a,851b9995) Z8(f3d7daef,203e8179,12e3808c,d0049540,8cac4356,50f08770,f00f5e62,e3d8053d) Z8(3d16dfe4,4f4e2b1a,b70fea41,b90ed626,7ef51d38,8e950b49,531081b3,9f59c5d0) Z8(1248b6f9,bb53e43b,a6c5053d,a392424f,9b330e07,b0b438a0,68559ab7,42a68b18) Z8(512f5ba7,35b50e20,6c9361d5,237d4b44,d52a2452,a5e839f9,42cecd23,1deaeb44) Z8(bea98ca7,841f91ee,adf0da30,1482ed18,23721a0f,260ee1bd,93239c75,8fbd791d) Z8(8ef63181,0cdb9482,513aa662,6f501995,67d3f857,c9fb6c72,cf4e62f9,41b1ea6c) Z8(9cd72189,4e3f8335,9d26a616,4ca32fe6,271e8718,3e27d444,fd97d16b,cd2ee356) Z8(141b262a,1d01e205,6eba6da9,1f082717,78395517,76728243,ff7b799f,6f93a478) Z8(c1988cff,2baa86e9,7b1ea9de,daa8bfaa,3ccdd5bd,80368961,5b094c65,b7932432) Z8(4a1934d5,403aae60,488b9de2,1b66d58f,e771e0fb,79f5f12e,041af483,5f76693b) Z8(1af267ad,6f4be88e,436fab32,9241cc9b,a5079d00,977adfee,3503543b,69ef260a) Z8(2cc740be,74a0b795,2359d710,989afd67,15a877e9,c5d5e8a9,2bb94854,e55e4532) Z8(3b26a376,99d71a20,47cdf26b,6b5561b3,13489b0e,b7baa198,70cc7ef9,150cb928) Z8(ae1ac2ef,7fc4ecd7,3a6ca36e,3804abd8,ede01f46,3198f1b0,b2fa9e73,5ed01f9b) Z8(faee366c,1f92383a,32139529,3ab501a0,489caa95,1ffde425,5b48bcfc,00380da1) Z8(e80e62e4,206b500d,7d385b8c,c89baaf2,739dfadf,f4b7a674,345ea91b,75841b16) Z8(3556fbcd,7099f371,3b57d593,6ad6f3eb,6eece405,37c5626e,44b662b7,3a3c724e) Z8(e12efdf9,87062869,e1e03ef2,3fbb6780,2c7f66ab,c62125e2,0e78354c,14529da3) Z8(d37a2ed6,bd62653d,4b577e9b,0a3192e8,ca69a059,874bb077,a0a6208b,f6a64596) Z8(d36db6de,e24e030b,a1fd2daa,4c46dab6,1686decb,1f505ffc,ed03a431,d61b49e4) Z8(c9ceb6b3,ebfea720,a8dbf39e,d913c77c,a23a2f21,e0394296,26f08608,4e28edd9) Z8(b6f27bf7,8b8bbc42,7739c858,1438742a,be1c1053,3ca73462,713b2138,e9943437) Z8(6e7dff4a,1d9303e6,187e8123,346fc1e2,59cf5d39,e3034b92,a5307f8a,3ddeab31) Z8(5557f78f,388ad3dc,af57db99,830b8eec,1ad01b1b,25f94e9e,bb92abcf,d31576ff) Z8(18b5f816,d5167116,73e11266,11e02e74,ca1ea6d9,a5252fbc,19e0a46d,ad8d5697) Z8(c600777a,e7874461,94dabec4,6b1172f9,d0e43110,a2c1f75c,54e02332,a486cac4) Z8(29bc9132,ee165314,ae3d7a61,749dbeb9,ab77eae6,5d13e354,bc8402e0,5dad978b) Z8(9eda5a08,d0d55936,efbd599e,c73497cb,a6f04e50,917ff255,ee205871,394e2047) Z8(6e3e6165,a470420f,27f0ffb1,d8ad8eea,12750660,2423bf0f,5e4615eb,5af53749) Z8(22fce5b7,ad4b8c4b,cd96f94d,cf2c404e,6774f94b,1ae80598,b39749cf,3dea2f5e) Z8(3c347bf8,0a119cde,398916d8,fac3d022,8c83dc3b,a63f25d5,13c49b6c,4cf60a21) Z8(d7cfbbff,38deb3b5,7c5153f5,140f7ed4,96a38ab6,7ff989ba,7506b093,c0ee8513) Z8(c33141ca,68055cb8,f845cdf4,a88c3b02,9d81eb55,cae61097,fa0b13c4,09f23850) Z8(472f2740,ee6f0dfa,76256e8f,d843387d,814f0387,2a164dd4,4de3cc19,6da0f0e3) Z8(1cdde009,d2f6ad35,658d1607,e9faba7a,921ca703,a71d908d,93d21b22,6a7917b0) Z8(907af181,ef4e6354,7b328fe6,21e95923,c15e1c2b,b70471b7,caf3d4f3,9ac69740) Z8(6c98cf56,d71fa87d,2b8c5538,27db6db1,346f83e8,42a8768d,aa840f4b,916cef9c) Z8(042b6024,4284b16e,82a8c1ff,21a3a737,8e2f9fe0,ad6338fc,adca5f79,a1719607) Z8(a4f52e75,b24a4af9,bc298348,89a3cc2c,f8b21e11,b158b4cc,c9061b1e,c85e3fd5) Z8(ef1f77d5,f95e82c6,312ae7f6,80aa94a9,afca6cf7,2e29edf5,92e20898,5db315bd) Z8(08f5f825,6b6cc4af,60a8184d,17fb0c46,daf512f3,3fbab2f4,d98df0f0,72070f4f) Z8(d9c8d86a,50dfd02e,4970758b,7afff5cc,b8cd9d5e,14b364f5,f314b8f1,8bf1e282) Z8(5df87172,67e5c491,83edbf4b,0d796446,627b5b0f,47f404c2,75ce847e,67b8ebf0) Z8(3a36c55c,c758790b,fd4ff1a7,db5a7cb5,19f66386,92c2479c,f9416183,d503ef96) Z8(2ae80e9d,74f7749a,a8032e59,4c22df3b,a56c3dd3,f730b811,a86b7524,4a43169e) Z8(86336353,6f4fcffe,460df641,7ad162ad,e21a7e9d,fe970f12,a5ee43b6,22334114) Z8(323c0d79,737fda5b,46e2b91a,febab074,4c99b23f,e1b326f3,7d683dc5,45fe5d0e) Z8(0b624021,36fc2c4a,b441a4af,f3cf2309,f9afa603,ac695197,dbf9deb6,f588e00a) Z8(ef2308c3,ab7f27ca,592dfd40,0debb9d2,5ecc4c70,77340cc2,d7764116,23c826c7) Z8(7a34ccd5,05120cb3,29520a8a,c656fd3c,e9626d67,f45384c9,7dff5146,a304f3e1) Z8(b4b1c0b3,6f956b7b,312b7069,d74a9232,1ef2be13,33f4634e,daa7ce67,dd533bd2) Z8(fcceedd1,fa2b5251,9c6adb93,664f6f36,dc5093aa,bf66af66,7be3c371,dfa6379b) Z8(af35febb,d38bb7c3,e242e238,5537eda2,5f321064,ed9e71e7,edc8b2a9,f95b6038) Z8(e0356b7d,9bd231ce,d5c51e2d,c589e398,8663a6af,c8506dfd,3f6b0da4,db6befda) Z8(5d78a19c,f200c6e6,60213c5a,56dea8a0,76734fd0,e6ae72f5,fd9ed41c,28e9065b) Z8(0d83015e,ed25d1a9,7cf119b5,6998f95a,e7f9b2ae,9e64064b,86622f04,24016127) Z8(6b722595,43785623,10caa688,6d095a8b,586b9ac8,76ebf0f7,199c27e0,6e88d40d) Z8(0de2d678,9227cb92,d003cbae,a4eedf8f,2ec7a941,675fc1f4,efdef86d,e35e4bbf) Z8(d22c7843,0e0d137f,b4e456f7,d0f87ce1,624cdc3b,fdabb2a1,3b8ce899,38f65c19) Z8(9c7cff3d,bcc89077,de8a054d,6c005b36,61f7cb36,20a6a433,eacc5bc5,8501d100) Z8(d6861dc8,be710da6,503e50cf,0f5d9b53,b715eec0,8a1487d6,73b81d29,d6797a0b) Z8(76d6e904,1b8bc578,ff38592e,5c81ed47,83d75092,769160d6,c2552f69,584430a6) Z8(37b59aeb,18a58364,a0eb870a,dcaff3a3,272c6106,a5ecc4ad,201005e2,3775df4d) Z8(4a026a38,a7fd681f,c7715a91,02575e0b,244972a4,3c5be0ef,a75a7805,5087a1ed) Z8(8afa6dd2,49ab17c9,694b2c47,0535ecd6,3923ec1a,27a3111e,b97fb10d,2a2b65fc) Z8(31ba26db,da0e04eb,ca7541a1,bb97b52c,a0bda983,76f6ab6b,a62b572a,3a42b8af) Z8(8f579afc,e088f148,b0a7fd96,8f5938c3,48934b9d,0234e22f,4ab00753,4bd10982) Z8(380dd1cd,0685317d,b72320ac,454eb31e,19ef87b0,4bdf25d8,6d584a5b,710cad6f) Z8(61ed02e2,5509de27,816833c8,d9212077,0c167d9b,cb54eaf5,1a7a48d3,24883bb0) Z8(a2ecd21e,d52c2e51,3f065d45,9540ee80,95636e93,5a51922e,41b3e231,5e1fa394) Z8(a9f51965,a05c3846,4f9ae951,0f1ebd76,a4f703fe,b637b4a8,824ce169,4b386d27) Z8(3c6789e3,3d655dcb,0ce4a093,8b67bc14,38729b45,abc5915f,7c568252,f4db67cf) Z8(fca97dd4,47efe23c,b71ab552,8130674b,2464c6ac,3387290b,d2308b48,e7478100) Z8(df6caf9c,acffc33e,b414d8f6,d3d8b007,d4b7e265,e7a92a97,c0437c36,3fce9c8e) Z8(c7ffa4ea,7c539d7c,fef96341,d9207c34,781188f5,7c877f23,327dfd3d,8757a134) Z8(5c6976f8,2c25bc66,007e1feb,8356df7d,d595208f,2743a82e,541ccb41,a2b3fe4b) Z8(531d508d,3d2ed6a5,eb53bd58,da570da6,90f1429c,f37d92b1,5e0b41eb,4f0b7e03) Z8(617d97af,528452d9,05ddb62a,b12bf061,2ab8ee12,45a0dcc1,5bddddba,d4aa1124) Z8(e205193c,0c1d6676,4852bb1c,da1a935e,e002f4d1,a7611d4d,18b5d3b3,aabe025a) Z8(227288b3,ee8d44e0,0eabc778,67956366,f2c170a8,835c8748,63bbf42a,37c4bc7b) Z8(99fb7e68,7af0c53e,e305d750,9058ec13,07a12e56,88abacc6,756510c0,82994a9d) Z8(e0ac4c58,d4fbdff5,bc3415b6,d9d0541b,990f1c2c,ffdeb7a1,7ee43f3c,9f54faee) Z8(495555f1,7cf75b36,70807768,f24b212a,91d609f7,ee3e9075,ac48acd3,5aafa526) Z8(d9848f05,51a85e10,d0bbe9be,b674572e,f5f865b7,fe4218c0,f959e921,0fba2735) Z8(d4fb20ec,ddd79e9e,cd3abd5e,f67a1cec,66458baa,2aa3b64d,8f6da594,fa92ac6d) Z8(0678a6df,8e64edbf,70c8bdb2,59480918,e7158502,fb565b1a,c74946f8,dcf87c74) Z8(d0e12a43,0cd65293,65aa53a0,0a8f6b04,0896bd10,903daf58,d6019a51,dc06d3cd) Z8(cf519cff,e0013882,a4b2c100,ae9048cd,ba6ea75d,573aff0e,ed183677,df367020) Z8(b34f7f6c,f417cdbe,530d90d6,38d75d22,82ec4214,326ad758,d754c52b,ca82fc1a) Z8(86452cc3,1b390a6a,4ae6661f,7853a0fe,bf2e5575,70efd24d,201d18de,379e9a89) Z8(33648767,4780cd99,415186e8,489b1457,1eabd875,49749826,15722813,12192a39) Z8(0f9d9e64,90eb856b,aaa2b10a,03742d52,070feb82,15c1c1f8,f8a829c2,97d08a83) Z8(12da5fa8,742a4c11,4244c8ee,8d3c90c6,a262f9cb,eaff7cad,92e39852,28562f48) Z8(63b89ef9,f6160bfb,58ca3259,093067ed,ecfb5b90,93cd20b1,bd3dd108,7c3a75ad) Z8(aac1d981,6e1f8126,f6ffb926,5c8eb573,6883f90f,2d8e4104,f7b04922,59d82c2c) Z8(c360f322,7b4fc8b3,e733a82c,7e4a8e59,94eba6fd,3c1cc349,75757683,bf340692) Z8(819716a6,7bbda089,3c06cafa,2cfd032b,6eb00a44,b3f440e3,ac27d3c6,e62c27ca) Z8(d9931f39,447506d4,8e959868,70693517,73267928,5f7e07e6,8df30887,0aa1f879) Z8(25331363,e02a0b4c,2fabbfbb,836f790c,d9a27574,f0e50107,979ad5ad,b89fc92f) Z8(1a6841a9,9a72bb07,c886dd3a,c6bbf512,f7e2ccb8,9f231998,840288ed,52267e55) Z8(170e5163,05e08a4a,8987792e,42377ef9,c5648a73,f8511a7e,c8dc0383,67487e08) Z8(da599547,14a879a3,87879dc1,7b6c66ee,00fb7697,15b4e05d,765703a3,81f7a129) Z8(663a6220,2240e9da,6b383b81,b390f43e,91d185d2,38a11ccc,5d30bfdb,bd724a3c) Z8(28df6cf1,60e7b069,a1c39dc5,be7728d9,45b383a8,fbe406b1,ad3313b8,aac90247) Z8(7a2336c9,8a5deb31,5b84398c,820acadb,2f3448c1,7b3b1321,90583f3a,b0c98432) Z8(0a30deca,d77d6949,bad2b9ac,210a9eeb,2a0dd401,bd51ea23,756710f7,590c92d5) Z8(b871cf3e,cbfcfafe,f102f537,7a9805dd,6fd217ca,d50c747e,397dd177,1fd2b8f2) Z8(cc4ac825,aa4f8a57,a41647bb,6df9f82e,9360ec3a,8fa17ab5,427bb9d4,223b6b39) Z8(191f2694,5ea03380,b8b2842b,d92b18bb,af7c3349,85652499,36cff368,e70e2f94) Z8(37f76237,cfe5f6aa,5f188e14,ee46cbe8,82f401fa,4604c36a,a557fa04,8467614c) Z8(fd4940c9,02d53d28,38d54b90,8fb15cf2,634a2f0a,1985ab47,46eeb283,9a485cb0) Z8(a202fef9,34fd2ee8,8530ae27,e07ed453,c55a0056,1bb14dbe,2aa12532,404fe805) Z8(346e146e,14102bb2,604a0f47,536c6d41,404e81a1,690ac879,0f74e2b7,f14081c0) Z8(fe0c784a,ad96e4d1,972cbeca,a2cec724,182c3fe8,1950e5bd,2a4ee2b1,a41fa4e0) Z8(a328da9a,f1016aa4,0b16da45,2580f54b,d5fec81a,77aeee38,7e464a08,0247a324) Z8(a0dc7375,fcde85d2,5b173e6c,e46d73ea,fb3be909,cefd0023,a36e4a18,42f55790) Z8(77cfcc5b,bfd20c0e,1744809e,4d81f48c,55829a2b,a3a2ca31,58378e31,0eb767f8) Z8(45f110ed,26446929,a2e47654,db07a5d1,c84e0262,e04246f3,84b06dbe,57020389) Z8(b37440ee,d5bbfe97,11ec6161,0bc64018,9aef84c4,37371b05,409820d8,7980c81b) Z8(59562849,f20f5a45,6bd1301d,ba606972,f973d1f7,aee644d8,23ff069c,68f1f7c4) Z8(67056da2,1b34308a,76483a4f,583c4ed4,13461ee3,9b47c50b,1beaf03f,c7f94138) Z8(e6a7fefe,92e0f63b,cd0cb793,dc699ea9,bf1da702,04a3ac23,37d93a34,ec829f52) Z8(c87a978e,b75a1465,42aa67a4,0b68d509,32af8f87,fb366819,bac621ac,d8f122af) Z8(3bf26782,9cf95acf,7f9bd344,c054d19b,d4b18126,9a847c67,cf67c550,ad75642a) Z8(bfefbdfb,cd92dccf,987fc207,b36afb86,ba1dcc14,3582866a,6575067f,9b42924b) Z8(8524b3ec,0599af72,c44e99ed,f8304f36,6b5bc313,36a01718,395d7dd8,2fe8e2f0) Z8(88462a2d,c9bbfdad,94c823d9,a67c1654,6e706f35,0bc175cc,23ebe41f,82cd4831) Z8(7e12213b,66ad63cb,0e444b9f,8b169390,998301ba,d51a4b16,c09adb02,c75d140b) Z8(3f957e2c,99865934,a1f44cd2,2bd0ec23,82836b54,637f6b39,1a2f82fb,7b00e399) Z8(b817f1be,1f2e5608,ce36828c,1cb98d19,b5cbd131,78fe92de,63c5771c,67f19e30) Z8(f3c65e8e,aefd0336,3a6b5880,3e01363b,8e9ff588,e306d2a8,1c5e0857,895db568) Z8(bedec84e,9c3e0053,18474e05,1212afad,73ceaeda,20167c53,15a1cea2,6ba852fc) Z8(df576899,315e23c7,a9e8f00e,df5d20ab,7ba11092,14b12361,d935aa0c,9c7c27f8) Z8(818c494f,8c87c5f5,6086044a,d279fca2,12c66c97,53899ddc,0038e73b,f9e2dd55) Z8(c2b30d61,1cb23304,40a32246,a7e53f5f,45d7ca20,c99f98fa,ab373836,23cd7056) Z8(3a91ece8,2fe8cdd0,182b9e95,8e5b61a8,6d80e154,b0f75d36,b0ee01f9,137d7394) Z8(2a77e398,5089b706,bc3b12d4,79c4c9c1,7235d17d,5b764b6e,27edb848,f70dd20e) Z8(437e3e63,3bfcd1ed,74375121,7e57779f,de8409f8,47556467,41dd9965,2b349d90) Z8(d3f745e3,a445ef82,f1d378d4,64434ee6,3a836239,44d3ba2a,0fa99072,3e0c00d1) Z8(f379098d,0898e848,5bd31c53,6f2b16ca,2026d022,c371546f,3cb4709a,6a743a17) Z8(16c2d5fb,08972fed,3aa4281f,71ad5ee3,9260af03,47f7a77a,dca305af,1da2c02d) Z8(36f53ef5,3d796a38,e6decc33,9a2eb35e,fcafcbe4,a78ad89b,3a2ca467,df6ac43a) Z8(a9bb21bc,a348cd1d,d98209d9,11a913c9,1598cc9e,9702a1b9,05973c3a,361fb9c5) Z8(d80432c2,4165c7bd,b342e57e,aac11329,273d262c,e6e11661,192daa12,b0953172) Z8(352e528f,e1e70657,14a355e3,7090eddf,2c00f9c7,21a816d3,ee329cdd,88251ef7) Z8(b8e1fc4b,0f1b9410,400a8ad1,76847474,7294ac7e,1a2d1841,62bfbc57,f2c21ca5) Z8(b0639035,5ec44a54,09a95236,714a7c9e,3afe86ef,8a17e2fd,23ff409f,45815384) Z8(c7ba4ae6,b0ffe725,5ea2e235,059c156c,3cc708c9,5f172c93,fcafc902,156c57cd) Z8(7e13bc73,5d75ef6b,a7bd5c1a,f445617a,88caa926,cd960952,bd1f1e2a,52a2d6b3) Z8(55a5dd23,e433f83b,5d0bd8bf,c62f4f5d,946c3cfa,46b86973,26313b0f,7ae8b690) Z8(4d581964,b9ec2f26,37e8dca4,49766248,ff8894a7,876e30d3,32930d0b,1f6cfc43) Z8(2737b38c,c94f0b7b,396003d8,ab01e0fa,7e7da00a,689c0776,a8b99234,3818d033) Z8(edeae20e,ea569480,ba2c0c99,933c5f9f,a0cd9dfc,ebf8e83c,ae57f1d5,78ce29bd) Z8(2e718916,16fbe37a,c8eb5cde,f50e3581,413bf711,a86d5736,2272566c,532f5601) Z8(0cac3d0f,191205cd,dab17120,d69840ba,a4f2a13b,ccd8f380,3347b85e,93d293b6) Z8(588c63e0,1e1d1f30,445f8abf,bf3ac884,825e12ee,3be70d19,6932ca1d,c27b373d) Z8(93a157b3,8ce89d90,124053a0,7ca79de0,32783da5,34925764,7fa19c5d,39401b7f) Z8(7f382971,737585d2,ed9eaa6c,ad0d323b,44eefe22,2f99dc51,995b442b,d99fe7fe) Z8(06994dee,78a85d0f,cd645a0c,9e18dfc1,607f2092,9f7be76a,51a428cf,2411a470) Z8(f975b5fc,b48b8f17,278ffec9,c4bc0581,29e2132f,ed7af2a6,cb918ba2,da95b0d8) Z8(81a28e7a,2779e557,6ec1c814,102172dd,530f3c46,485f6280,31add9e5,19dbdfd6) Z8(52cf6e9c,1bb66f79,e1f590e9,20789a40,c8726c8c,3c61c8e8,cb942bea,21733b0e) Z8(ec687bce,c4ab9131,40b96824,486b9da5,39e8e72a,2a323f3e,eab7a0ea,857cb599) Z8(fd538e3b,3662ff8e,0860731b,c9a0154e,5b9b5985,74901953,a4cef002,277a1967) Z8(d3a6d916,da2024f9,46f7c1f3,3e7ea0df,75eff166,d2181f68,4802b376,2a3a97a2) Z8(b5402b40,84010c3e,40763314,924c8d3f,4cfe0984,2a6695e8,644a1f20,a84d3eaf) Z8(c9425a45,9bc29b0d,4feae866,c548b907,3a1000f3,f9b6bb5b,da3f6c02,0c13f26f) Z8(edf0756f,0914adfe,400aba1e,cdea208c,c85518a5,114bc957,5d4b7b9f,0a69dccf) Z8(1ad0f7d1,81034e21,38e75a60,0c9a4e1d,2732166d,2d8013c1,d777a532,72541d67) Z8(77212d52,30eca897,c8e460a5,6a24c54e,dcdffc74,6186f682,868b003d,840abced) Z8(43c93463,50e65aa1,00c925f4,c437083d,3942e172,8e436769,f49d2928,c2d66be5) Z8(c0b21149,8dcf8652,51e77a9a,006cc427,1a2c8679,c3018d2f,68ef8843,3e37e7ad) Z8(46d725dd,a241bdc6,571c58a2,28ca9e1f,90efc2b1,a21ec147,e2407f89,75756a26) Z8(1c178395,c85e4da9,42834b10,e99607fa,3f3e2571,4bbc19b6,1e578316,95ff2eac) Z8(a42d48e0,f2ae1f2d,0cf40674,1cdef8c2,aab10703,1a50076e,e77607ca,78a569b9) Z8(5e58d6eb,4414a090,1d9e63cc,6eec1dcd,af7ded6f,c69a0dce,230cde53,74037800) Z8(647e03bb,914d6387,3f5c92f0,be1fe916,a1cde46c,5afbd37c,549b2760,6978165b) Z8(fbe7b434,1d17f0a9,a6d39a5a,9a820a1c,9f171a36,70da6e14,3bc62d66,5ca0afe6) Z8(60b97847,715606af,fc8c4249,49f5290d,0a21605c,09eb18b4,fc5b6a86,652c9e0c) Z8(3faed52b,7d5d2b35,26e4e849,67612086,6e1dd4e0,bfa96af8,0e167036,7eaa8222) Z8(9d183300,02048316,e9d480a8,7f23e2d8,38f8377d,b2951c8f,07d4b9d8,fee5c725) Z8(1a778b41,b9503cef,1cd52dd3,40ecc838,64afd17f,d8a05947,8c84dce0,f9621bb8) Z8(02e54ec4,a781cc8e,c7377e54,8ee3f7d4,8efd4a54,f5819f66,51049100,ab457256) Z8(1d4ff1ef,26f79d63,d6422f25,19224b76,1ab9880e,632dcb68,62a7a660,8c20c25e) Z8(2471e8a4,3d1d524e,5adb256f,a7fad713,51aaf23e,ae9174be,539efeda,a0f3118b) Z8(6b787f8f,d8e2c96d,9d7c845e,1d9e129b,0532044f,a97197f6,76383982,401639d3) Z8(845e7f63,db71dcc2,4916f953,3b3da736,dfb21233,9b377014,b48b57e0,5c0a8220) Z8(2e9cf2ad,ab5e8284,7052bb8d,fee04a97,6afb9ae3,4c8df78f,1bf69d3a,f3f595bf) Z8(6c048d10,4856c153,a359e3e3,96982360,e99487a9,0906d719,c66845ed,5834604b) Z8(5450aee8,2aaa1858,9898ea3c,3b4ad1cb,a00e0a64,28ac90f1,682f5ac4,7cbcfc65) Z8(0a493f83,cbd007c1,3a20c286,eb06b537,2db94e01,78f12a45,0c434f6a,cbf54311) Z8(0535fc14,13eea8ac,86f9f9ff,738456ee,44fa0b8c,c1d45e0a,1a4fb556,b84184ed) Z8(9cd46952,7659ea5c,197ec220,ae1f74dd,d71195f7,352f27b4,3ee1f106,25eb97b0) Z8(9a668b3b,53967484,105a4f51,8167948b,9e85f206,54014f7d,a7c342ed,252bf954) Z8(8f6ea3ab,c88382d9,7e4697ce,c60cc582,33a62bec,2c7cfd38,d01bb4ca,f956177f) Z8(663a5817,717fe608,23a6befb,e2604bd9,507a8543,c0edfc38,099ebd1f,71d87f1a) Z8(8ab1eab4,edacc487,3b7a0e16,4cd211e9,603a3e26,938a851a,9668047c,ddcb01d0) Z8(3f478b11,852b74e8,5f979c17,588e63db,f17ed717,c189f86d,0035c1ad,14dc23a5) Z8(498da3ff,eea2c5e7,9bc5eff0,b935f7b3,69eeefbd,b68340fc,b501d34b,767af842) Z8(13d83d53,a34aac73,b21c438a,0631f3fa,10e83743,6ad0a041,100ef1c1,e55df455) Z8(cd8edfd9,ed117627,7a3d77bb,3c451aab,927dc80d,3dad611f,55c62293,548a802b) Z8(fd40c371,685bf20e,5fa02e9e,41d1db9d,d8ce9cd8,994664d3,0430d55e,c24bdfab) Z8(bd57a154,2ced1501,5726ede7,63dd18b9,99adce08,aa63a8ed,7adeb28d,f57487ba) Z8(de7e3454,d7d20d9a,b9f57918,4f50b4b4,59f929f8,2616b827,2852959f,92007bd3) Z8(bcfd1e9b,2d533014,62820f06,73c189c0,d50558ee,acdc1df7,2b9d4abc,bb9e0dc6) Z8(d4570ad0,c963f3e7,9c650a8a,a78a59b9,6be66334,f9083c54,ae15f530,5dfc3ea9) Z8(48263fce,2c450348,17a25bc7,e2f827a4,3095cd36,35bc0552,0b87dcab,aae7583d) Z8(3a963f67,a7b13502,bb784ee8,b9015eba,386f598a,d15f8c07,40f117b1,723f54c2) Z8(37acc48d,dc95cc04,e3f9b42e,84e869b9,6318a339,cb86ba93,f2b500fd,483d09b0) Z8(a39125fd,1e9db006,abad4db1,7d22b88e,a1e61c60,006b2a9d,ac0afce4,32421a3f) Z8(9c43331d,bc009e80,27e89d4f,8197fbd5,772baf18,94f914bf,b904ed83,9381c0a1) Z8(57fd3b3e,dbdeddb4,cfe63350,e74eb6c2,996c7009,f0135247,bc9911fc,2b2d3e24) Z8(8da2a3f7,81e09bca,52063acc,e1c37b1e,2daca98b,3d10150a,5c025c82,11f1403a) Z8(4b9cd773,7c14341d,d07cfa5d,58a6d96e,6c656a74,fc35517f,3dfb491f,f8461e8b) Z8(4bb00e27,7be6823b,9cf0d4cf,98a5c79e,9cecb731,351c050d,e1c063f2,870da919) Z8(5a822112,b8adb3e7,bcea51f6,427c548f,b566cd7f,3f321159,824b16c3,5a41d26f) Z8(47d654bd,1d8878f7,fca6c531,cfd9868d,a70672fa,6467fd61,695eab96,875afc20) Z8(4f3fdec2,eda583a5,3e26e27b,98957ebc,8e42549d,4ec61f7b,057a280f,0bc59bcd) Z8(341f8be9,c2585526,f82eadce,8ca4e2bc,69a0ce6d,1ebcc56b,7ba53da5,95d1e195) Z8(dc226c77,e0be2c30,83235658,2c9841cb,bef0b79f,bf4c04d4,9d85f809,ada71dbf) Z8(be361413,5123b07b,27480dd8,067346f0,162c387f,70a276dd,5f2f833f,9770cbc0) Z8(dc98fe7b,1257f51a,0ed35c93,aed1961a,d21435f0,e18f24ad,e3a1891b,30ffc5a0) Z8(f62ea4f3,78631060,c5e8af27,bc9fcc73,9c05f856,5b2430b6,302772af,5cba64d2) Z8(ad16ea47,491d5214,df52fc9f,95468e9e,af18ff74,c1c86162,b1e26aea,41e9d4c8) Z8(cddcef17,b0550189,eaf7eaa1,47cd8b08,88bbe782,303a3487,9390b4cd,c23180cf) Z8(64b1604b,0132fc92,bbba9e18,dbc11034,1a1469dd,df3be67f,ad06dfaf,9ea20bb6) Z8(5f2de789,c75faed7,dc965921,d5facb80,e1bcb915,cc4fce47,467e02e4,0449a3c6) Z8(99027a9f,4db24449,bb26de5b,736c0a4b,45cb86e8,b71f5af9,764c249d,5fba2962) Z8(825be11c,fa962062,1c8c0cf4,b7ac75c7,44d7228f,3fe0bb44,e36d8a25,b38a5066) Z8(3ef510f2,94a9df98,6d396803,7a20d1f8,e1e6828c,80b7c103,8388c5be,b0131156) Z8(c55b12d2,f244e2cb,25b6d049,6991ddcd,bec838e3,de5a3276,ccfc9f90,ff5bc085) Z8(64fc3f08,2af7e171,54dabf78,3fca648f,77f02480,e6192d8b,53512dc7,8f224b11) Z8(de288fd8,4a6c0d72,07cb577d,8f3a49b1,9a3002e4,88d933cb,a6afc5c3,88b3714e) Z8(ec72ef00,5a503ea8,3c25147a,2dea6aae,d4f0e561,59c78f17,a26d1fd1,909ebe47) Z8(18195bb6,76cfe046,65236b5e,082371d3,3dde6946,f945c6fe,58488395,5006e1d4) Z8(4939742e,973209f4,f0eac926,4de1bb87,f229b080,8dbfdb0e,cb251d54,014e718c) Z8(b4b52238,6654e1d1,b60a1b5f,29df90ab,b352e7b1,85b5d269,58ca98dd,112f56ad) Z8(76f8db93,e86b6318,b510f8ae,e10c6f5a,d6af7452,1cb3d2ec,e1284fd9,96be7ff8) Z8(87dc0b12,77e83b72,94147d82,4fba86ca,ccfcf808,d0beed36,4316521d,b0f2dfbe) Z8(88b0c35a,ed229f83,b54b45a0,7938b958,02315fab,fdfe00fb,4915b891,83565d8a) Z8(cd5107ed,98ec091a,a171a78b,ce05e3aa,a8d5405c,3d726a17,3ea46056,e2fc7ac4) Z8(0467d7b6,3f47f6db,0362363b,c94ee58b,896078ab,2695ea17,efa1ae2a,af19e783) Z8(41d2e363,d1152db0,997fce3a,b92e8c16,8d5cc645,6d5a8c93,6d83e585,b0540923) Z8(a52feecc,195d9f50,4c490c87,d7cbd120,e0e1539e,0cb1f323,aa48c726,8d98e93e) Z8(629e7f9c,90338ede,06af7200,ee638267,14946df8,7ea54a5b,e9f39858,01d648ef) Z8(446da695,ba46e56a,d6e62337,e01b48fa,a0ab7b9d,70bd203d,b5da39c0,fbb02610) Z8(0fdc2831,8a23f915,c17eeacf,b6c66c6f,ad7ae1b7,6de2320f,52055e24,d6b27f3d) Z8(6c78b99f,f157e43a,2b34206e,80ff74dc,269a93c0,ccf3e5d7,7a3f7ef0,0133b279) Z8(8e91bf42,963ee831,edd5b7b4,d02d9d93,3b21003c,120e2a45,f43cf487,a63512a3) Z8(13571a68,c6374440,44b9d321,0d3d9dec,989034f8,bfdfc91f,b2dbbc6d,cd76c0b2) Z8(72de0ba5,a3fa58d0,9e72bb1d,f2c13675,81626e1a,91745eb5,9bfb9616,f0f12e2c) Z8(f7e7e797,4249c36b,a42b8558,b1cbe40e,2b75566f,e43e8c4d,f779d109,2e1b828e) Z8(c2d10c8b,deccd12d,11a5201a,aabbc514,85a15792,57528a77,b4b5a2b6,1bcca4e0) Z8(ee932714,a0c91f9d,05c042b4,581d559f,d9de534e,c49cfb8c,c55a7214,d969033a) Z8(a9392c4e,62b71f04,a353ac8f,2652d083,fbb5c569,119c41c5,caf8ca1d,50fe7518) Z8(21826356,eee9d959,a29ae754,c03039e6,8899cb91,3fe537af,6747d614,3b4379f7) Z8(2360dbf3,faeefc22,e8fd9549,11d5c129,b409b454,f1586a5e,622caddb,3061a6f5) Z8(2102c616,00ff3eea,fa8c2076,264bd3d5,ae9f6920,18bb041d,a2c6d51e,788cbe2d) Z8(318de655,95f6ecf8,63844730,ff2fe4bb,f2fcb247,8b654b13,642de029,f95577a7) Z8(ff146da2,b5ec9b5b,f5ab4274,67059950,3c5cce48,23c866e7,d464ba6d,9fc4b60f) Z8(3c309fd5,7d2350e7,c488dd99,d56c938e,a3f48272,60ab5359,cb1dc14e,96873755) Z8(07b801d0,7581de52,62464483,475cf3c4,2019057d,ecf4ae0a,c1caa68b,d7fafa09) Z8(7e741a33,3db10c1d,b660933b,6bd02b8a,42a0b4ff,2b0c04ad,759df1b3,e08b7bc2) Z8(9df24d34,c06f416b,1b7cfe73,9b3f30a0,11aedb6b,8dad3fab,22fefaaa,dae03aca) Z8(966ab762,fb8d5419,dc5193a8,8c29c8a9,c91fe38f,e477870a,28642cee,7192ed74) Z8(9b38a28a,8bb196ee,eb6aac61,bed30b97,0fb7391f,9b78469b,e4e81fc1,54d27446) Z8(9deda7f5,b213b57c,4c0b52c5,6ee786a8,6f1bab06,0538aec1,56be3b1a,8591c213) Z8(8e31a81b,a852e1b8,a9899296,48c5dcb4,d24b0b3f,5cc6f79a,4b59b55b,9c83b0e5) Z8(6a482f45,609477f9,941f42d0,30d2dfda,989f8903,f29cfc2d,6df451f7,79528456) Z8(7242d0ca,ddf1b444,fcb19c1e,e54bb6df,cd474df6,75cf87a0,4b6817bd,f09167d5) Z8(7bda6303,2250337d,0b1762a9,ced990f2,5bb06ac1,5f58e589,47aee0f3,8f70471b) Z8(2d28ed86,0f5e636e,425c9da7,b6788626,c821e5aa,dafb5152,4b4f1317,46b85475) Z8(2a46b82b,bfc4d94e,a84bd986,6701d3e9,5ea59406,0c86cf5d,b48ea3ad,e103f3e0) Z8(5574292b,4be769d2,ff9cff09,27d03131,ad5776aa,e97f8e57,e49b270b,6cadc168) Z8(c110c296,140ff616,b5c9483f,1d8b9eb2,c5ac635c,cfcbe6c2,f06ec0cf,656dfa4c) Z8(edbb8761,3d3d1c39,5adfc86d,a0f65511,19c327b3,110a4d8a,658248d9,fa5af7e5) Z8(91b05a75,4d3d56ec,11291a4e,7845e62f,2dd465d6,5b075370,36894876,15330055) Z8(38e14c56,4fc09d7e,020803fc,cd5814b5,5b5fd022,6a8aaf20,a81f7623,bb723044) Z8(570bb090,c8e055fe,03d22e89,ad232d4c,0603803f,6669147e,0491cf4d,9ac96796) Z8(8e70fb57,f5474f7a,0372c652,ed6b06c0,8a986e91,9eac9b26,77070578,d9f36ddc) Z8(07a7d396,4e5dd11f,795e38ea,229bccba,95f1c990,de607c9a,f9d03973,542170da) Z8(b406da15,f15181e4,34308b8e,aababa66,cf3c9209,520614a5,6f78a1ba,dc4bd0c9) Z8(c11ca492,beffc79a,53dfbd80,3a6c39ea,f0c1cc22,59e252bb,e3f5236d,fd534c4f) Z8(c656a2d9,583cd0ef,d9f7dba1,fb4fe1f5,20a8969d,91b9292e,21d1c089,9379bee9) Z8(f45e23b6,f7123315,59d542a2,f0ec6c77,bbf2413c,33b0ac14,2ea189b4,885b8b42) Z8(e65dc555,1bf1d476,6620a1d3,b21610c7,357e8376,1d5237b1,1a80064d,060e0829) Z8(cc9922cd,cb01603f,1b323389,61fec952,138d8784,a6f46a71,240ac200,d5668b7a) Z8(beee5c17,97c53a1a,7a965253,56d47515,eee564be,4e0b3095,9378ab5f,b8467c1b) Z8(ed2cc6d5,7801a681,87d30fe7,4b6b46ee,04b092b0,a2933bff,ec937742,ac7a0116) Z8(35689c30,b7723c5d,cd493ff8,3700ab70,b6058125,955aade6,cfb6fb42,eb79c685) Z8(53a4212b,fa3c15b6,7e0bef29,62728386,d3fd081f,5a565035,fd7af5df,debae30c) Z8(4c5636ab,765757af,46981736,26c3cdf8,843aa7b6,fbb47b88,85ac881c,597df775) Z8(6e0e2301,7d850c67,d71a0b6b,9c4c7d01,a7e77db2,d873bd57,9d9cafa3,f52d70c9) Z8(61cdfb62,98c1dbff,8cb3a786,cfeb69af,4ffeabda,64c38ad9,14a84fd7,4e05f853) Z8(afc36a07,8a18776a,a3699c55,2fd4e9f1,28e89134,78fc0479,6dfa8837,dd4fa9e5) Z8(2a26c6ae,ebed9cd8,fd642e3e,f8ea8e77,3eb9436b,bbf35781,6973261d,ce85dabb) Z8(db0ffe6d,92422ff8,38f41a55,0eca36a8,2bbbce91,1a887996,50e6d18d,dd09a8ef) Z8(7fcbfcc4,d2516766,9c6f0b1e,100b05f5,e6643357,98f2be9a,b23a2884,9a1b3aee) Z8(b98a403e,b2a7e949,fbd05284,e8c4b007,bfd90336,11cf9e23,c430dfcb,e217da54) Z8(344c500e,a3210550,c9be789f,316a19d5,a36c2f05,c2724e2a,d4723b63,e342ac0e) Z8(95ffc577,2feb58d1,fd72456b,d98795f3,f7eb8aa0,8fa202cd,c1cdace0,a6512bcb) Z8(ee6c3510,3f18467e,6f667c02,ccf48294,39a98801,6d014eaa,c3801a58,902e4f7b) Z8(6425a843,d77adc5f,b59cc541,babdc104,4594f4a0,5372cd90,69b5e334,8a9f5fcb) Z8(d8b22b9d,7df95802,1bb90cfb,487f3960,73e89601,3cd12f68,25a4113c,91eb158b) Z8(1033875a,37870480,142598e8,2dadfac3,d101a54d,5e5d45da,594894b3,be92d057) Z8(61a8ba27,a0e4ff10,607015bb,2997e256,66cc746a,a7d88e0f,93d9dcde,86b271e4) Z8(2f3173e5,ec52f687,742d7f94,31433249,38e20620,96e15608,aea4d485,6fcca12e) Z8(603ca4b2,3917c9d1,43c21360,c913621f,7d16b296,0f5285d8,036f03f7,c9e70144) Z8(2fcd9aac,801ad177,8169a445,d6cb327d,24b4015a,092b78e6,b023a542,3d42b13a) Z8(71b85e47,a7efea1a,db1f31ad,0ef4111c,f076b4f5,1a299a26,2023390a,649b9e53) Z8(122b5351,831924ab,b4763b66,95795aac,b9710f3f,bff2adcf,4c98d891,a98e3744) Z8(a9cf1bf7,0aedaaa6,2b84f01b,dc1cd48d,b5d49c70,0fbfff1c,b1037813,83ef5071) Z8(0c745021,02d2cf18,b1cd4a62,e0d70865,d5571a9b,fba7fb13,4d57bde4,7bd5323f) Z8(6538f897,6717387e,62e50df8,e1841b31,0272f90a,1b532f27,ffda8362,f7d1438d) Z8(a1f1892d,5b635553,d1e929bb,a8217ce8,2fbd462c,11000ecc,4bca7708,78ad18de) Z8(484f592e,e1024daf,c368c496,7cf938f4,e88c49cc,39a8f8b6,af31c372,c074eea8) Z8(d4afb568,d03a8528,d27b7465,a79f939b,9c960792,51dc4a1e,ad9eb076,d05b2b01) Z8(8e00f590,da599125,8bb7eb9e,6fca0f88,23db1250,1da5ba0a,f31ba770,adf3da4a) Z8(2637fdcb,4d817cd8,25d36ec1,94a49d95,144911e6,4a41d43e,c7a17a8c,d4406ce3) Z8(4c6607b4,a908f4e2,67e9ed7f,a034c6d8,83856782,1b1fd48a,f9872163,75e91fd1) Z8(2b1af688,e6895bfa,c6b5142e,cb6e47fb,518eef77,11a940ae,2e94b1d4,84207108) Z8(62ed29f8,7540e6d4,c8cff5ac,97da875d,3c79dd92,d9e61408,646936b7,7debb96f) Z8(7c07a506,cfb86155,8180e8a3,bbbda89e,fa3063c1,ce5b4df1,763de9f4,00b4093c) Z8(a31ab712,91f8ad74,b6d5ecd3,c3e588e0,0a3e3734,096baf6f,ba78c906,fcf93a42) Z8(97d72d91,088a0a55,aa0f5039,3eb36083,fd6d278a,e8f5f0dd,fdffb5fb,77ccfe70) Z8(2ae559a7,647cbe20,35d1f916,e11235fc,6e6c1117,285db21f,8f0a1bbf,70138071) Z8(73d66e97,ef034598,1337c5f3,13f5b314,a17c8002,d7a4656e,4dc10948,1dc398b0) Z8(b63da69c,fa9457ec,b662d2e4,2f423160,bb07415f,cd060187,d1fe3f8c,1e3c90e0) Z8(5440b34e,1227293a,2c7f128d,9d6043ea,dc292628,3c46a502,6c560a93,a9f886da) Z8(c73d8c43,e5836e3a,2c5ef6ba,29d17e18,c84bf4e3,f72ae9f5,42ee8ead,e989be14) Z8(5309331c,bfdecfcc,6c592403,1a1c54ef,4235e2e8,4ab1c52f,b2c568d8,de1fcf5b) Z8(6028cd4b,03ac1451,9ccfc687,489c479e,23ff6fea,87ea71d6,0a99609d,5f01c27c) Z8(4924c3df,af09f359,d1798462,2369ffa7,77b1760b,e8674dc6,43b83d08,66b6fed8) Z8(7a38bf41,6d751999,1f4bc3b8,f16637ea,63eaf166,a17a3e88,728b6946,09f6c0d0) Z8(9b52b216,9afcc7f0,962897c0,eec881f8,8cea66e4,b6e891d2,d2b6f345,2456f093) Z8(5137257b,fa2b23d2,d5928e54,7a3e0e19,8a65612b,6bfb99f7,ab2c5ab6,85e4d0af) Z8(5f1f9ee1,fd1a8794,b44d30b0,8becdc24,57009891,e568e6fa,1e4789f9,818ba0a5) Z8(066617b3,a3bedc0f,7c6c9df5,dfd011ad,98ae348b,0afbd340,936c4a56,8a6f8120) Z8(27fb4176,d48c6c05,9414a3ae,41f4917d,7d47cfd5,f8da0361,c0bd78ad,5dd57127) Z8(8a9ef961,ac3e364d,e1eae686,ef32db36,afc920ea,a7b95040,af4e640c,ffdc3d19) Z8(ead9401c,e2552bec,7be8235b,d1e09ca9,04f7034a,b036e70a,3abe790f,7819f0e2) Z8(a5782fae,dedec677,05eb6cff,59cdd56d,5c2ca135,ffb121a4,06e5bd27,e86b485b) Z8(2ccb7e23,a12dd97b,f1199982,9eb4ccdd,525375c7,1c6726dc,e155f8be,46e56c9d) Z8(56080695,ae816ebe,99149abd,ae389dbb,7bee9169,6d383962,e5af7fdb,f5711db8) Z8(bbdbd718,93129a63,dc6db1e3,91f345e7,22f72c53,a87a9df2,dfb0fcb1,e54f7a60) Z8(ee82f3ed,f3ee3b73,63b57aa9,6e596d88,ef137123,e4a5cb66,43d78a16,27c4ca85) Z8(3e4d4358,63433d2d,184eafe7,3ebcd3ef,60f903e1,25430744,7b6ec3eb,61de2e59) Z8(0e3105e2,87853efa,4728ff00,c4d97a75,6f010c0a,54d06da7,d0c19406,dcc9d37f) Z8(4767110f,ac72f22e,77774ead,e6f15a6d,095aef62,48945e6d,79632c86,c970d366) Z8(768c3ce0,ff2539b1,f79ef023,0b9413da,b0cf2ad7,a89b3d95,0bb2875a,5727afec) Z8(75440989,16e64272,e9162d48,ac09b365,2ee66510,dcb7c72a,b216cb8f,762d9aec) Z8(7259530f,83533aa0,08689368,00e8e86d,eeaaecb1,0d00f8b8,a582df38,77c5e11c) Z8(9411b922,4fb182ca,afc990ed,c6f0ee66,8b4cc790,1943cc5f,110d991c,ebb2dfad) Z8(6f752895,25ce0e0b,8bf752f5,a57a3fc9,4fc6eedd,0d9c2354,860c1d11,2fbfe907) Z8(77c15548,8a1800f3,39882822,44e386ca,bf0987bb,602049a5,157d2b88,9b11a3f0) Z8(cfc5ee1b,b35141bf,91be484d,8f551c4a,ed07612b,92584c70,a69f2299,01c3f41b) Z8(5acdab56,7b472e1f,7b93f306,a09b169b,cc77c271,98ef926f,422e4759,cb1be915) Z8(1376d45e,cff0fc80,dd425f2f,0929f3ad,03abe71a,7191d105,5215bfcc,5062a7e4) Z8(791c4e95,67442cbd,056e5380,2628a545,42a708ba,9e71ec5e,9a5bb933,e1a3f85f) Z8(d9d47ddd,bdf4ff77,400fae64,e9c056c6,179e2546,d4cb8ea3,477ae50e,b5a49130) Z8(797af702,992dcb34,9c565796,8c87accc,b85d30b7,e87a150b,a37a6f21,9045d361) Z8(06f07e60,b0c306ba,08df25be,25686351,7f97299d,2e141046,97faa978,a58b6c29) Z8(b80a2d6c,f1713abf,c3261afc,931e79c2,484d9b3a,262a1051,a4f0e129,ebf7169f) Z8(6f552a9b,35492e1d,99fcf251,edd3c08c,bbf622f0,bcb9acbf,a14fb1b0,11a69283) Z8(95e247fd,6db45dca,377fedac,39d022c1,296bdf6d,784e28fa,cb33b900,1c829ddd) Z8(f6ad64ce,c625bd30,a7c81f59,c1467b9d,7a4c54ff,e7169e99,2f859e9b,bac693a8) Z8(c328dd95,ec22a15f,952521e6,e4d3d933,1394fee8,033e0fe9,f19ff770,65cef723) Z8(2b9b511b,e9525a7b,d836d2aa,5feda65f,b80e4327,1b77bdc3,3ad2cf1d,bd5e5374) Z8(076e0644,37d3c42b,73c1fcc7,ee7de54e,c94b46cf,ac72d9a8,125e1ca1,db70d06a) Z8(9eef6981,ce260aae,bded63aa,4213d437,bdf7f302,7e8a258a,2c3a852f,19a5d281) Z8(cbfd7b93,4a3ac6f1,fa2ce09b,dd164031,958e49b3,328a0858,1d423a0b,df960ee6) Z8(2f71223b,d1a3f3ea,4ef7ed40,4f1d1158,0003c862,30e38c17,90cefe16,ba78c602) Z8(5f0b79dd,3f2e557f,a980581a,587f07ff,26c2b7bf,185a9759,a09b0715,48f05fd1) Z8(5f2446a8,a2e414b3,24cdd67d,d2f5fa00,f100bca0,4aab98b2,976addd7,8daae11e) Z8(e3a544dc,ccc5b710,eb917f74,cad531a6,483c0438,2abce623,a1a856c3,778e07e3) Z8(aa872f4d,07cf0bd8,b014a636,fa8dca70,9837517f,2d0d7184,0ca860cf,493a5b7a) Z8(20b9f5fb,f0b17bce,70476178,406c4c56,32e6029f,8023345f,9e0f3ff2,8b4d00cf) Z8(e1acb9d4,55e63cdb,27c57f6e,46159818,413ca327,0d45525d,9195a487,7ee6f16a) Z8(b38455e2,af229323,a905030a,763ed744,00d4e1f2,d09896c7,f9d09438,c9dcc6a6) Z8(78e3d613,953891b0,70055d2a,c7cac96b,06c4274c,5545ef4e,38cb9aba,357a92ee) Z8(796a885a,debb772e,7d6a9570,847204e0,603a675c,da4e7170,3e26ac69,ba405d33) Z8(92cd16e3,34faec15,eb9be7d9,45753d7e,a20dce93,c32d8ad0,0e2c1e8d,2f3d80e6) Z8(dfba610b,763c8bf3,6c1d6e2e,0372174b,54efbedb,7fdc684a,e2101862,ca474688) Z8(0e8c6ed9,fb81cd41,95a0cca3,a6bb8177,e9deb217,3e650ad1,084c914a,889acef5) Z8(fbde23f7,935d635e,66f21562,4a0f57cd,7b95144b,4a94272c,d0506a75,64fe41aa) Z8(cc333293,688e8c55,3b6483d5,abefe4d0,90b7ab9d,156328d5,19e2c0be,d7ad5c2f) Z8(62f75217,cfa80be4,d04570da,bcb772b5,e992da56,95a70d07,4e566505,a69f866e) Z8(a5269c45,050aab33,d7e361d6,87c14c2f,d54433d4,9e7116a0,dc2d5ea1,1a542522) Z8(66f8c9bb,c53c45b6,5b6225ab,32552fb8,69f881ae,b85c542d,a4ee61e0,2d5dc702) Z8(cf132337,84ce62ce,4664dc49,2cae07b5,27c33114,2bad602b,c42365e5,16f4b675) Z8(377b939a,9aa53c88,f34a1414,cbc0a619,6e741484,ff4c3987,d6f9be21,6085995d) Z8(9a1ed953,4f801b5e,3e008a3d,249322bc,a38ad1f6,5c73b9af,8c87b7c4,30b3719c) Z8(33845d54,1b275047,a79d10bd,9c649524,70592812,690c9801,c0381ce8,dc9cb39e) Z8(40773637,dfbd208b,5e834522,aa9b747a,5c6a2284,71a51e40,d7168a4d,9732bcea) Z8(9eceef7d,6c7d9378,f1aeac0a,b0746ddc,3dd3fb6e,f23ec644,5628ee6d,21dbceda) Z8(36b0c89f,148c7cb5,2ecfadc7,dd68b519,20bcde90,bd161211,ea198089,ce92fe1c) Z8(b8133cd8,d7b4afd4,1a5a797c,2881e7a4,7d092188,c079f617,d2568d36,f910788e) Z8(49d92407,c895ac04,f6f86016,441f966c,ea25bbb5,1bda6655,35614bfb,fd2cb96f) Z8(8ff4bc9c,fcedbaf2,f14c2cb3,7b95a096,161a4ae6,78ad5842,0183b80e,99a56c90) Z8(724b6ae2,6ce4b9db,cf0bfb24,35140fa8,65e9da8e,1af051d1,6f41ffd1,05588cb9) Z8(2ef27cc0,5a155cf0,d9f1a979,05bb443c,5341738d,a73e91de,27f77a59,3f47cae6) Z8(116d9171,2f6d5c66,240d6c2c,61c9a399,2c091e95,13182a2e,43eabe2f,38f9cefc) Z8(42e05d64,e2277056,14e88f9a,4ab3fa95,c7739240,7c34dcaf,855c739e,0cabb4d3) Z8(62ebf381,51bd9ed3,9a10bd6e,7b75f42c,d2062109,e9617bcc,eb967590,34e119b5) Z8(a558d929,b8e1bb97,c5e8734e,43d20c78,aa17a975,b8332671,641bb653,f0e21ee4) Z8(ac99bc46,471d1d3d,dba61f78,44a099ef,8e73be93,1fce56b3,e63d0ab0,1d9a5f47) Z8(5e6ba13e,85800d4a,43bd7080,e6ad6405,745aab25,1d4cadac,25517d6b,b2539f28) Z8(fc9f6c09,2321114f,3959d0b9,e6e6607e,ec2b8985,e051d233,e5efb715,7d647d92) Z8(e3641b02,3de81bda,2f4902dd,e4bdf9ad,2b49f9ff,b65f8d71,2df65e23,fd0aa30d) Z8(f965fc03,8528d9ed,0fa6370d,aa5626b2,df6ac5dc,3b011248,a546d951,b112196b) Z8(260b89f4,03ef0786,b0b12348,b4eb6cc3,9b77d3a9,899facbb,2369d688,3762dc4e) Z8(1c418a52,fdc2d958,fef1d902,e5db4a5e,096f2649,f6bab61b,a3ac7d95,a7650642) Z8(4e3e7bfe,b5013c38,025187d2,f8edaaf7,c3d508dd,b8ae6f4c,c399abcb,8b9a41e3) Z8(c8ce20f9,3ea85da0,2ed21a61,16eb9831,364d7eee,3d0e4f1a,3580ca1e,f8adac0d) Z8(49e965f2,6fa069e7,52a93a5e,7bdecfb1,3299b4de,b0566aa2,1023b459,19116d8e) Z8(13aa621d,b352198e,a7071d88,2c30b93a,ba3b9428,9bfdb470,d68970b4,68b741e6) Z8(c679e7b4,03b9b399,be381086,ab8b318c,da0d97d3,3f75a798,4bb04cc9,bb9fb5e8) Z8(ad52e737,bf14eb2b,7a0a8341,731b3c4e,db1e859a,40fed235,57656752,e4142c6b) Z8(8e1e2860,7efe471c,93feaf75,db80bf6f,b1538de9,ed9a6880,f850f9b2,2c0153fc) Z8(ffa248dc,8c827fee,58b0e672,4cf97837,798eb238,b692a0b3,edc0d6c8,21c53cfe) Z8(e1b7264f,cf471610,5f5d003e,b0629220,38a5f3c5,5c665e28,1c8dac5c,72277dbc) Z8(7eef04dc,b6955168,ebd4336d,d835c16f,95d14bf9,64145c09,4610f87f,66002690) Z8(2e7df485,0dcfe433,954d4858,c34f97eb,a1611387,47a15967,5a0e4ade,2f30a4c0) Z8(ccae53cc,58073f55,c8c36793,efbfeb82,0bc4ebed,4ade7c73,880266f3,baee76e7) Z8(0c2ca287,5f93bd53,5572fd19,0cc156d6,85a43491,45116f40,bc90311a,8693c37d) Z8(c093c432,5e957293,4746f80a,5f95dbf0,65433a4e,068ab477,baca87b3,92f33fc2) Z8(f4e0e8a3,76da80d9,a6e6c6a9,ce8970aa,91bf0837,623989d3,40ed43e1,15c1e850) Z8(a1171a39,b4bbde9c,60cc7489,007e7d9c,1eda56b4,dfcf2460,0a40a1d7,90724102) Z8(e4618fd5,aa215215,624d407b,b8225c9d,e038672b,ac018e35,039d3e2c,b86f736f) Z8(060ae3b1,2c5bcf3a,b5aa3377,3a90dca7,54f1b8d1,7af09fb6,c9732065,652bb747) Z8(e7e16ecf,caf62f64,7493a521,4280488f,c750bff6,d9e2ec57,acae33a4,0a890cf1) Z8(44a186da,8e986808,5817e290,a1980eff,5c95e9c7,d64f2ee1,40fcf79a,d81b9a3d) Z8(2921f92f,a526dfe6,d95fa4b8,85916152,0236d639,f409129d,8b703963,c516d825) Z8(8e46c5ee,eef8a59b,1e1c2b79,7d5a821f,f2d309c4,b8296629,0f986c65,17a47959) Z8(64efed58,97d79567,e845f856,51623b4c,56fcd505,40fdb1eb,30d2010a,3b48f14d) Z8(f5cd52fb,a54ad888,a200cbeb,50b41664,c63e4671,3e4158e6,3f3c6a98,6eec0125) Z8(0ca79e87,65245f6e,de0dc5cf,be8f4020,71a3e350,d9b78f04,419beab4,00266ec7) Z8(21bdc6a0,0e25e897,697e9293,9036d94f,8a8e8281,ef1c1605,1d21eb26,ace98c2e) Z8(c6a73ac5,153485d7,c5b1cc83,5f00c5a2,1ed599fe,6ceac9cf,2419d0af,adf7a49f) Z8(6e15c9d3,e9b98fa0,59bfe9b8,5d6a33ac,543ecd12,f7d98716,ba9b7aff,bb4d7936) Z8(88a3bfdc,0c333453,82a01bc4,adfcd18f,28671be0,2d43e205,598cbe14,640db20f) Z8(baefc57d,e86d152a,28b0b822,7905d0e8,9905d037,39e4bb3b,0bac4a14,689cc2e0) Z8(d20d3bdc,fedb827e,a0114b62,c2c72952,6be313cf,786ec11b,bb39cf8c,d128d10c) Z8(d500d868,72796ef6,c28397e4,8a31e818,344d3122,1907f7b4,d851959c,42096ded) Z8(f37a41d9,d623633b,a1e672dd,dfff72f3,9bcdf744,9116fc77,51ca3fc9,d75c41ea) Z8(3e8e35f2,98031d1a,254abc72,0e65b2c7,10f025d0,bd64640f,752f55b1,242e9023) Z8(1b13bb21,ebe86252,d6e8744f,7787dedb,c2f53f07,3fb1e045,777cf11f,d02e8b19) Z8(b97dd591,c2c36c61,38bcdf7a,1f256273,3c20376b,a6dc2196,be1a8454,5392cd8a) Z8(23f37b4d,c63b5c29,e5557418,33de32ce,e4241815,2d5edf0f,e9325e6c,b234d140) Z8(fffab36a,4dc8a765,91264e41,10f9624a,31896303,d8a64ac5,14c70836,61ad6c55) Z8(81ee5e90,733c6757,608b33db,d2e2d194,85191cc5,d6d3d470,1c8750c3,17ac5f93) Z8(f905a539,7441cda2,97b5b17d,ef67a51c,1c8d2c8e,20345ec3,480fc388,64de21a8) Z8(48c4d433,14bf6797,56166eb7,3531d0e5,4defa236,8c9b4bfe,442efdb8,d7d88ea6) Z8(52b21696,528b1e2e,2d186a64,dc06756a,5ccf8451,dbb362af,8cce3747,37a24e6a) Z8(6c2ef6b0,14842df2,4ec0f9b8,2a33f3be,12d353d3,bcef539d,6fffe7c4,2112a49d) Z8(8ee32558,63542e08,e1f3d94e,61899086,b0829783,093e1d69,cc605ff5,5947c529) Z8(bb601eb4,b16366b7,d20e52ca,02062e9c,2490da4c,b9ff1ae9,b4a216b0,aae2e5bb) Z8(2a493b17,b1d57457,e06ddef6,90daae5d,155fb454,9e717ff3,95271f99,f778893a) Z8(7ae5d8f4,18ca0e6e,1083822f,7d2012c0,d5d6d8f0,48d649e8,c8abca07,3892fdcc) Z8(3aa5ef04,3c373bb6,0d7cb031,9e093301,1044d707,b7a9f58c,4724f3d0,f1eae917) Z8(643f9d82,8f0bf98a,88ccfe26,0f4dee43,8759907e,2fccc86d,42cc28eb,933e0866) Z8(5065ba8f,2b56477e,947bfb3b,96a911bc,91f1d81a,03b4503f,530fc162,429c2ecd) Z8(c93b2762,d01d3980,6425dfac,8b42076b,8cb914d0,fbf3f6e0,7d3a7780,83d775aa) Z8(aaeb5f46,24a1313e,8a993cee,37a37e79,b5c98bb1,11fb4c25,1c388e5f,09641f78) Z8(8899457c,51b5610c,006d3c78,bd3fe9cd,15ffa51b,4a3828ba,9e016ae4,ecbd7a28) Z8(0350da4a,66ef0687,c1144074,c2aca536,7aa09696,b078a13b,3c21c225,5bdd7f91) Z8(b0b9e0e7,1ee48e7d,5b7e08c0,917c8a41,c695d8d4,63afa2b8,fe72a718,47acf453) Z8(d7ac9057,cb2fc73a,fa5b2c54,373b4c43,e6c95f3d,58fd4506,5eea6f81,b670bea9) Z8(abb500b8,cb1bccfd,7069f622,43c63df5,5ea568a7,0ac41139,97d4b4f2,707d8a45) Z8(76cc415d,c5af1198,844cb095,6f027ceb,3ac4b6e0,2083809d,d57b47a6,a9ac30be) Z8(9088c2c8,81c5d5aa,8b6ad0ca,6017f943,593af066,4784a26d,ea34c41f,5d658178) Z8(3aef813c,47cdac4b,b2580b90,f8c353c8,285089c8,b0ac52bc,3191ac56,0c4e0870) Z8(d8f26dca,cb44eaed,6cf71ade,1a9102ad,3d56711f,b8cf7e96,bf9395df,007785dd) Z8(4f0fa133,265be9a5,3c721c58,8127e70d,8036f2bc,c91c8b5e,b364a074,09c27921) Z8(fa9fbef3,7cd0e4d5,6837e641,f2af9439,14428b6d,a00840ed,d933e219,ca315194) Z8(80dc57ce,22e84ff7,91ec6f88,26a3d922,249cf590,558141b5,d1da09f3,783110fb) Z8(f33f24df,6395f731,2d814f65,9845f9e7,88a1e8f1,da0cd423,20aa833f,a9f9ca61) Z8(c6dbcfba,b845a7e0,065be030,9d6a8839,899b6b14,e81e2dc5,7a732fd8,59959326) Z8(84727387,9a580f07,8617bf55,6a18a118,8b63b0d1,387240cc,c6d78433,0b0b1cb7) Z8(e5f1752c,35237e67,da6ebbfb,deb51086,12223aac,a14f98ed,f447a243,349bbae6) Z8(053c74c3,23c26791,237e89ce,72f9f742,b17a7d4c,98c9eafc,d9c897d4,268764e2) Z8(3b8f57a5,39d732f5,a78a05a5,5463369e,8e689aae,47739cac,c6010098,9e6e8d0b) Z8(58f13f59,d4b41b3a,092c6c64,f0a3f218,be6e6774,bb741d86,a65a9d22,6ea4f224) Z8(764b7e32,418952e4,6e120f1b,e9eddcf6,ad1d6506,8751a5a1,0c9319c1,5ebcf0eb) Z8(d7d2a328,72a31f86,745c0b15,50e0dd97,750d31fd,74dd51cf,6bbf8d3a,1ebb5cd6) Z8(69ba8070,a862c2fd,a48e8dfe,93951e81,b56f7dcb,aef939a8,5613850d,d9f61827) Z8(341ef7d9,4c8a8a58,068ba76e,eb771978,fbac59f0,c0ed8281,ca09768e,56ed7585) Z8(83d0cf75,292bafe9,2832df7c,063c57fe,cec29804,2b0db64c,d32dd8ec,f3e48d0e) Z8(6bd1a582,c69460c4,997976a2,460099d8,9ab1a6e6,a175baa1,3c79a9f4,bdb51a59) Z8(09e6844b,0b74e21b,fee26581,a9515711,66c864eb,9fb1f926,b1b05537,31f6ced1) Z8(1d099880,b8297a30,055c6bcb,7d47ee8f,c93922e9,a0cd222a,c0606acd,f2aac943) Z8(442ebafc,889aa107,fce93189,7b3673c4,877254c0,8e5dc037,769f62f3,091fbb2c) Z8(c1d09294,d23f29a6,e9841586,f2428640,c73607cb,8ef53bc2,225b0741,069127ae) Z8(2f788c47,8aae5807,1203a9ec,1b793e84,94e2e724,f8eaf401,b96c86e9,3dcacb97) Z8(e5f9cb82,860aae79,fe21f1af,027f0223,f41589d1,e039ec5a,5e6e6677,06831b9d) Z8(db3b757b,7057679e,6ed829aa,7c8c383c,55288c4c,05f688fb,e2153642,6f8e019e) Z8(5d260f85,c620cd1a,b064a431,928c6016,3b8383cd,4984ee88,d0bddb9d,25af0332) Z8(d9ab8c9c,f89e2e62,62b6d795,8efe373f,add42122,1ea2e9ba,b6a8efab,6c7dcc55) Z8(dc438025,9b4185be,3881647c,217200f4,761f4754,eee4437c,bcd8ee36,0e0de0aa) Z8(986bed93,a5e3d35c,8fe2ae08,ebe7d2d3,fa0a3fec,699b18f1,fda51671,3e6f4ac4) Z8(bd49d4b4,810eef13,8469a875,7610f801,38b094ef,130799bf,90b4adea,6d74e8df) Z8(5e23e245,1b042486,e3e5ded0,954916b5,d2a3d027,58b9c46b,c00df9e4,bbac988c) Z8(e81ff2f5,65602033,80f00af8,1b02036f,d60d674a,82c2170e,0fa2bdce,f2645f7d) Z8(3fa3c22a,0c7af46e,7cab598a,71c94701,a65e2dfb,05d9b554,2da1d119,f97d4674) Z8(b48ddc27,9c86e488,9f67c22d,c8ccc3df,c256ee80,bffac15d,bae6cab0,98b013a3) Z8(6973b3e8,67ab6b1f,b84652b0,0f9ceb99,75e81ae8,b2d5552d,22b3dac6,013532dd) Z8(24e01427,be5551f9,fff5a123,fc836f31,af385315,9bf9e9f2,72f43017,1f9eaa6f) Z8(806fa86a,819cff7e,fe962aa9,e02824e7,7062e2fd,00a4f49a,52be905d,a049aa31) Z8(967f2743,d685468d,4d77cfd1,6771ee06,e7724a29,9b96e0a6,d663b65b,ff138a12) Z8(4359d077,80d8e55d,022230d0,e6bb0427,1fcfd8d6,c07bf262,bada1359,f29e3480) Z8(c8762f55,7a6a18b7,99000ce6,1acd4a7d,9b2f74ee,3789c5bc,facfe46e,ca638068) Z8(d17919b3,4918b1ec,9ffe10a7,f1a46e96,34d129e0,182609fe,f845e1cd,74462897) Z8(ff9ecc6e,a6b18b1b,2cd6d010,24291371,55e6e609,141f515e,3018eacb,8ea1b526) Z8(f630218e,2f6da052,8e04d3a7,d03556f2,844bf085,acb85b11,f0a53e02,d0d5e59c) Z8(06ac449f,cdb9f0a8,94c7957a,a378fd3d,8d544cae,79945a87,9d02a803,7d9e6b1c) Z8(13977c1c,a245175f,89085d9b,086e9d46,e69d5a0c,ec29d84e,19ec2c62,9bca449a) Z8(48bf61b1,95df6774,edb91f61,5d9c140f,23550f43,34fda29c,25c7276d,963ad5d2) Z8(8bd4c1d9,889f4fda,3e30e0a9,db7a7f02,1722a79a,47511164,63343d1d,80b08cce) Z8(2eb04809,811b1307,1ea35f12,7614121e,5dfc1a02,28771c85,e418ec25,0c1d0e1c) Z8(66e7bf78,cc8ac8f0,ce03c1fe,c471fff6,0372437e,46aa089c,a32668b1,c5706bb2) Z8(dbf6d062,c4015746,fba87a8e,a2cdcb10,fd35946c,a3025ac8,36bb0c67,e741a113) Z8(3ede39db,ab59169c,9b7e1421,1d9e2bd5,9f4ce05d,034c11ab,1eb33550,285c84ea) Z8(42afe364,8fbde714,0437d164,266ccf51,40d899a8,a95fd0ee,0a09f960,3d6c1366) Z8(567de8de,036c9679,72fec915,cf7d7da6,6ad8b210,ed1fec6c,5159626d,afa06bb4) Z8(047d0157,b27d2fd7,02788995,baf1bf4f,36969a6c,949ba3a8,7b7674db,6b83e67c) Z8(4c7532ec,e0e38fde,e2e7eb76,01bdc212,eadead1f,ea694993,44eb271b,c72b3176) Z8(b55b0757,84ba2992,6f0d4902,2a129aa5,e549c413,d78943db,55e68864,a4c8051b) Z8(28fb484b,5fd07fe3,1cee0791,c7e3cb5a,8a433e16,2d5a341f,7b0864af,503416ae) Z8(ac28dc4e,41b348ea,4867f571,81199df4,1bd93bc8,5dd917f0,1d7e2eff,2394dee7) Z8(7cdf7c55,97fbe543,df8cfc98,9b059eae,1155775e,1718de8e,0bcafeeb,f57e9655) Z8(9a9f25f6,d62613d5,2fff2858,59bd8c30,890e5a68,1dcd7e96,3a407b9c,18af433c) Z8(353591f0,a2e49a11,420724fe,892e52e5,42ad9e0c,aafc2061,03dba901,92e156a0) Z8(b7fae92b,845b91d4,e0cfa63e,3b7010d8,2d1729b2,b847deec,56426835,9536ad2d) Z8(7ebc8d61,72d16945,322e885b,a8f29bba,55a3518e,a797b1dd,d0805454,40d0d229) Z8(00f1e47f,ba1439af,0ce391be,5828dd2a,4bf0b73a,eef28aad,12383671,0606b905) Z8(5f3b9553,b5878241,72ad6473,cd4538cc,6bb142c5,5efbd767,221fec8d,4a222b77) Z8(51ab79d8,2857afd2,fb64aa39,47822e76,699e33ee,f46f931c,ccb53267,bf368bc5) Z8(caceea02,9526785e,2a910532,5a98ee8e,0cb44051,257801a1,f764355e,b3839e9d) Z8(94b779c0,5b833a1c,653b83c1,3577441b,d4ce6488,d456ab6a,5412ba6d,e0d740c4) Z8(425324ef,b556acc8,0b5d9925,b688bd3c,face3e50,26338b7e,ce6c4039,4ad42eda) Z8(c6f8e91a,55c0fb16,8f0f056b,a4df39ff,c63cf98d,499e1a49,f64fb205,960a20df) Z8(b1f9cd81,221e82ce,853b435d,085e6382,b106b7bd,c1aa9afc,8acbebf4,06bd4bba) Z8(9bf4a4d9,351dc11c,1d82919f,5bb6b959,3c2776ae,8d6d7c27,d8d0dbf9,63ef2a26) Z8(fc94f734,57767da3,dd2b2213,2b88d46d,f7ba9a51,85ee2b2e,ac1f6ad5,adeab1bf) Z8(9701d6f2,feeb1c62,59c20537,e49a9555,a24db612,72ca9898,904a2ca8,fea97efb) Z8(61744383,5422b5ec,b5a6032a,60b8413e,322fd0f3,58e16a2f,95e09aa8,077d05cc) Z8(a252c846,ea1e89d8,6bbf4064,2a493cd4,cd6b5ddc,1dcb2791,f305e52c,6cf68aa8) Z8(82a5aa1e,3d7a8ac3,d4d04c1d,06ea1c11,30cd1210,aa2d9d94,a8c08a63,4797a28e) Z8(759ab934,c8234314,4caed4f8,662665cf,70c8f888,a98b90e9,06146f1d,3000e784) Z8(cd2f3da8,d0074d5b,a42137e7,96234295,2ae13d13,e54cd16c,e36ba645,f52c8cd2) Z8(b858b4e7,089614e8,92fa21a6,a8640749,d423f1e8,3e8a4b7b,464ff83b,71f74b7c) Z8(4922beb8,30317100,d1175b84,4a34b019,f7a3d15a,06a38e01,58eee977,fc3f13e0) Z8(434e1a0f,e3756d3b,20c3f3ba,26f21bb7,6e210a00,6aadcf39,4ee1d26d,6a1f9eb0) Z8(9cb172b7,88d3c875,c53e5c08,2c8cb9b5,454c4284,b00dfd11,904d0464,439eda07) Z8(fbf07a3c,02bfd1ea,d47898c4,c8a7d5b8,4992f83c,6a2c5842,ac30dcc2,c60d4b3c) Z8(1855fa10,027c8f7f,4413cd25,4f0010d6,44c841f2,52ea70f5,b8ab2445,54343f7d) Z8(21528c07,9ba3fc6d,6dd3fd30,b1621276,2755a87a,71c2154f,c26a3b0a,0b01767e) Z8(f0b7d4eb,be719f12,07744c3f,b5dd45be,e566ad3c,33677009,fa0cd9f1,6913dc64) Z8(c756cec9,49848de7,84b4aa2e,f0e5a54d,629cc6c1,47d47c14,3eec7e6d,904c4f00) Z8(dd143a29,3b0bddd0,30d1d115,cef24a69,8466b26c,b9df93b7,66a4e5ad,c1c5b014) Z8(89ee14d5,c81f55fa,530241ad,cc9065c0,42146687,b303baa1,8118136c,927e5626) Z8(b4e80fa4,39af7c44,8dcdf25f,a2079845,074bdea8,e0849840,060637fd,641f37da) Z8(eb7004fe,46a927e4,2d3acee1,dc7a7c32,b9c84644,dc7686da,fc301d78,82c637bb) Z8(3525ebad,73676441,647fccdf,6811f1a8,c4852498,f348b569,5bf683e0,0174d6c6) Z8(a06efded,e2b0de09,53c35401,7093f8ad,0f76ece8,e8d60378,7a5993ec,9f8c45e0) Z8(8ccb9931,5a531600,c22d1c4a,4070e37a,ddde57fb,a30eb147,8ed86a48,b22b2296) Z8(d5d05093,e7b7ce4e,1357b282,1fa3a4e8,4fc4a44f,9c047c28,8f395a10,ca89ca50) Z8(06353f65,d6a3251b,d23aa5f4,3504de0b,242ad5da,e01e183a,694d99f0,76833885) Z8(bdeaa24a,dfcb9099,6cd36b11,ceeb8d13,ee39cf05,63ec6deb,3d1a2d81,149f5ea3) Z8(6afaa033,22e94dad,1fcb8d63,cebe7a1f,d0f59db3,098ab739,66f15283,44e103ac) Z8(61f6f273,8eac682f,c4805d99,76ea5850,64cd92f6,a2fd6d08,6a228909,bca3ff7c) Z8(6831da14,807c3220,45dac9d3,ec18c96d,c24fd23f,69dabb23,ccd18252,af037819) Z8(c83e1611,e2bed73a,b66e53fa,72557dd1,1a1c7afb,fa9cd9c1,f43f7e9c,6d78fbde) Z8(c3bd937d,b0d6b4bc,cb0a5cba,f4907faf,0ce69df1,860a774b,98040d87,538ea0c1) Z8(418fc6f8,da471fb6,02231b25,cddb4faf,40ee75fd,a00f4b5a,832544ff,aa6d43b7) Z8(d8991020,f48906b7,10bea83d,85dbf00c,d066739b,dc2ca45c,217ddf51,a59ff340) Z8(ef7651d9,f1bf1647,f2d54f6b,0eb4ff03,1e5cd0e1,4e2411c6,268137d1,0ced2476) Z8(c08fae75,4ba7e452,c06dfb35,78e8c9cc,c2058eec,f15f6eec,46ff2c83,a41b6626) Z8(a6ce14e6,cbc758db,66249a5f,cc55053f,34869c86,050d7993,7fde8c49,246d5abf) Z8(e5270234,aaa4bf05,c7bab166,d2519caa,3b140f45,393412d8,98f2d50c,407b3e5d) Z8(3a9b0baf,1b0f16aa,5b48fca1,b582d316,964f86cc,a79a7889,2a28a22b,d497bfb0) Z8(f9b6a3d0,8527c462,a03a45f6,74986758,69060803,9bed7d12,6b2422c8,613cd5f1) Z8(48f1d99d,89bfc90a,c24fdb92,bd80a7f6,2ea8af18,4a9b537e,73be392f,cada6a63) Z8(8a265a5d,5e543099,7119ffc3,abbbf34d,e0e867e0,ef580996,66911152,18ee4fed) Z8(959e7d0f,6260ba6d,95235401,a1dfce22,4a83808b,ca6d32cc,1503cb19,9f304d85) Z8(c369b05e,2549c028,2276a7f4,f2a27bdb,77ae081a,3eb3f97a,69a080e5,81ea7d9b) Z8(c1159f1e,9fac1b60,fd397588,d08ff8ee,74cda7e0,7d9d49bf,749fc5ff,d02b8dd8) Z8(668c14fc,bd8c0a3f,13ba47af,c393876b,5b780ff8,cc5d3b3e,1dcb41fc,a05efbf6) Z8(bbef38ad,cd2f0edd,0cb988d7,c02fd68c,1a0fffc1,09a7a15a,be6327f6,bd2d2e1c) Z8(989be821,7524d28b,81eeeb2b,e27c2e25,5fe06c06,be61d652,8a31f8c5,09f646c3) Z8(e1178a2e,c5e10291,72b6387a,ed68e0fc,9fb59f1d,619005f5,243b4352,8a4bd5d9) Z8(12ed07fa,a1de674f,8ea99387,cc12ad0a,bb44392e,e95524fb,f28c2de3,4825c313) Z8(705d288b,ba82e4e4,cda6fdbd,aa85d7ed,d1cb5ab6,2cc227f5,1849640b,984258a4) Z8(e15f5080,462a13fa,0182da03,b36212e9,3bc842f3,56de2510,61df0c4e,cf9c350e) Z8(1eee0dbd,34a9cd5d,68725494,2c64c059,e7fe2ae4,045b1c8a,760bd67d,3771dad1) Z8(0617b104,94819b05,9785e8fd,5745a3df,42ccfbcb,f459b117,67bb1823,ad044901) Z8(5054bc8d,4f4c4444,82ea31d7,5c2b3662,90aaaafb,38664298,3881c777,829bf0f7) Z8(38de2c5f,dcda4a61,f2b8ebc7,afe2edfe,a1fe5fa9,92656327,4706b8d8,2f41f966) Z8(b88a052b,7c0a5e1d,a80ad130,64d9e4b2,25e90503,0d662823,d12daee9,3002d95a) Z8(2fa652cd,2c2040f8,58ba309f,3405dcf6,7a8e9022,a41f5bc5,3d5c8534,2cc93381) Z8(dbb22c17,bee1744e,44ec1339,ca7fb623,26c59e33,b189e1d3,066b6dd0,47ad09b7) Z8(329820ce,b35b529f,a43b86d2,6613acc2,9160e187,c68e45a9,efa16f22,d2c990b4) Z8(56688c15,21c5e9b8,bf772dbf,1f981a6b,6a521c1c,6aaa9e9d,cca9916a,2c5f5d1e) Z8(a2b6e386,c35325b3,7df870e2,9d1b60eb,bea48e16,d034f527,112128e4,bb0f696f) Z8(7893bb42,2ba849d3,efb1a162,c5ffae81,3a240564,d49258b0,f22848fc,3c8a992a) Z8(999a07ee,d197ebf5,81847652,3030719f,a4f09e60,74c8ee10,58a09213,5c96b4cb) Z8(97a93926,e52250d1,af57830e,cb125696,974fe4ee,125f9145,98fbdfa5,ad26c2f2) Z8(f6a59084,e7aa9459,bf1294ff,9802e59a,e9b05eb1,a0bd9f53,530a19e9,0f52953a) Z8(5731365b,1a667fbf,2e953616,c23b9c5b,d2f8467e,db588768,bf30c004,30ef44eb) Z8(3773a533,73228656,d8030b46,f76e387f,34dbf9bd,3e6c7456,d7512ba1,a2a34833) Z8(b80eb18e,39e6b22f,a3b4835f,92b9b376,8aaa4fe2,80195418,bc970ef6,7dad3cf7) Z8(4bf3202f,b08cee0d,2a1b5349,3b318536,c60e5893,70987778,28356121,8de4f0cd) Z8(45349112,4157f31d,6fc656a7,297097b9,ba98742f,7ec7ee88,b8b8568b,42bfe394) Z8(03a0ee2f,677aea8e,a45fb6e7,449187e2,8ceed919,1cc3ecb8,ba847ef9,a1b50e7e) Z8(7a1c11ca,a67543f5,f87c9b22,79aefaff,38b29de8,dfda0c7b,c9118e32,f425b77f) Z8(923bff0f,bb62f54e,2fac7c2d,c5c65842,0391e3fd,4c3e4eee,56f8a9ab,1de7d666) Z8(f11a2c9b,8e9ad58a,e6609b25,689b9864,b425f197,83a3f9c3,2da146ad,65f755ae) Z8(e453bb2b,57cec152,917375e5,37b6a77c,c1822f97,bf1f14b2,d5b70003,17190c68) Z8(2fca6ce7,f6864a5d,830df26b,bd4538fa,d768adbb,9621deea,4d0784f8,71292a47) Z8(eaf6b323,15b7f882,44a11287,ba2188e0,381fbc19,72096840,b84c6eb9,b0e0df3a) Z8(d45b33c3,336d1be0,bde280c4,5c735f9a,6c2f6b73,9e5bf751,cce3247b,e0aa7b2c) Z8(d70bcaf8,63b349d3,dfb08f60,32848ff6,fd02747f,15bdb641,f0516284,9c39c2ef) Z8(4ab81b22,10f2ecb5,23cb3b98,25a1b531,f8f7f211,2386fdd5,7d71b586,d6a43be9) Z8(ef6e6ef5,fa63bf04,22c95a32,53023cec,70a95dd4,d59a37be,7adbc77b,a1972488) Z8(fadf8d51,bbdc4bcf,3c1a0118,17d9849c,65d98081,1b31742d,5d81f6f8,b0d4a197) Z8(f03e10d7,9f21032e,90c7dc8b,2e6775b9,b1ba7774,3695d7b8,73633046,1400e7e6) Z8(677a9879,061f3558,42374d6b,141690ad,263bbc14,f14a0c85,2c273826,aa369f93) Z8(3edf8771,a6e13c6e,acd7db0c,025b3f4c,f919f470,479383e4,80628501,e39513ef) Z8(13c4693a,7a8f05d8,aa67a26e,768b9a56,b34932d4,f6851cab,403dfa31,c8af55f0) Z8(e87ae715,06d6a912,d57bb8a5,fdf8e5c2,4c749446,856c0035,e893b7ee,70dde994) Z8(85ef8c3b,4ec0ec81,fa96d02d,0552992c,01c13eb9,c46462a0,6038ebcc,14521c3c) Z8(0da26cfe,c33df6fc,c78f6a24,b08d8942,aedcf2da,f849dce0,afddc324,58fa31ba) Z8(80dc506c,f04922f5,9d9c19db,972854b6,7fb81ee3,aff7871e,eb5180a3,f882184d) Z8(5d02a4c4,02fbd99d,984f9700,6ef450ed,76d86676,e05da6cc,f314b3ab,bcf17d7a) Z8(00813c9a,c9f23806,664e32f3,cfc8990e,668c25c7,719c0d9a,d72c3ae6,96aa9971) Z8(21866d3e,9c6709cc,c270559a,fb23296c,daf69535,f6a65b91,e141e0fb,42668c60) Z8(60897aec,2411fc04,cdd83b9b,1b680dbe,3b8bc47a,e0e05e9e,98ef790d,70c23100) Z8(38a3265d,eaeddae9,1fbc8b11,a17194c0,41510b45,d6e16756,48847fa7,04db7731) Z8(c0ac78d1,865f6833,17728891,3726f7c1,02868257,1c764c4c,715a68a9,cc291f30) Z8(da31ffb9,f27b7659,2609811a,0894324f,020456d9,9088539b,ee7ffeda,dc587b5c) Z8(75bbe273,6d94b140,d746626c,f396e9da,92924454,9818042b,24d94723,27f02f10) Z8(73ebfddd,62312aa8,776c1df8,40b1b278,c30f39de,c22925e6,892b504f,a097ebba) Z8(503c7238,72639546,81152d80,d8379b9d,a5a2dc03,3b52f823,2c473452,36d3e5fc) Z8(109a5ac1,a1b9ebba,7ec4294a,f4e6a5ae,f89430e2,2335ef66,2d04773c,4f2132c9) Z8(1646e845,b8ec529a,abfc155f,541123c2,be718b8e,f43776d6,4ff081c1,d825429f) Z8(3a6d2bb0,35c3e30e,acf6c48e,c0235a54,393d57b1,4be84484,f2f15206,bf0da208) Z8(1e551462,058955e9,59479af5,cdbf71f6,a6a76cff,161ccd6c,2a1ed5e6,8479a9f8) Z8(a3cb8109,eb7b06e6,bf512d65,12d37c9e,7c940527,a5d2d20a,c30d9ae1,33adc5ff) Z8(19a14011,9e818c12,8735397b,ccc62f55,d94e566b,5682760a,ec78807c,42025cd0) Z8(39f68651,395c2bb0,ab6b10e5,31c5eb47,d81effcc,2d2c49f7,dddec51c,5f9ee9e5) Z8(6b2a9372,4a0775de,04327ce2,43c990f6,a6484d53,a78a7ceb,44c98aab,e427d8ef) Z8(19761aee,be67251d,44f24725,0c7aac79,ecaf6c3a,f228cbe1,951cceff,7177d2e4) Z8(150a2f4b,43624a4f,d1d6b84c,07079dfc,1c06f1cd,a42a30f2,6e298524,fc08a739) Z8(7ca275bc,a6e45272,62c0ea01,0f1c0fd0,20e34ab2,e64ae14d,c742bcc9,c869ad60) Z8(6d7ebecc,af9387bf,2c42942a,ea1576fe,71e6f17a,9c9c72df,1ed1a0db,7269bad7) Z8(dc1cc271,11f91345,5e0fb236,23ec1a74,3a9f988d,d523ada6,e4b5c74c,a58fd1c1) Z8(2e9fcb77,d64b2fbd,340516e3,39520cf3,a2545bd0,ff657e45,14a944e2,e81c0be5) Z8(61d7deb7,e0c72489,387c24e3,d7fb023c,717bfa1f,70650c9c,691cbc34,14cc2c23) Z8(50b7117c,5585296c,5664cf66,b886a316,f4d29ab3,79bbc199,47f133aa,855c32d8) Z8(8cff4851,07b7785f,12e510b1,77fbd323,d0d55fb3,81f0fc33,d053b461,9a8b608e) Z8(63199baf,dc07ae5e,1397254a,1a38e091,682a9335,82442938,faf6b86c,5f5a4833) Z8(456dbf48,83135c13,7e85a420,750cad2b,b091a93c,6da37ce0,ce6bcd76,2c1e770a) Z8(beade43f,69ccae3a,796184f6,a09992f6,00b277bb,f27f5661,c562ca42,3caea6a9) Z8(16d557de,6dfe6971,a847bdf8,ef1b5d52,fac27958,14a2e2ed,80d629fc,615915e5) Z8(7fd5f9a5,9df4bf48,01b86e44,8f214593,6c6ccf50,18f05c3d,84f5b280,aacf8e6e) Z8(f9fe9aba,138eb9df,6083feac,5a44e2d7,e6944d4f,1a949ea2,b0fcc85f,52c927f1) Z8(e22937f1,eab0b925,820ec370,4a8476dd,2087095b,c2b83f14,cae871eb,a238d3ae) Z8(73975785,e88d65ba,d7d77452,8a3b61e3,f0c9fe3d,37fe354e,ff182afd,d5f20203) Z8(a5332598,79421d64,8dd4b23a,d8c69f86,f591f891,c1a59b84,e6149da4,e7a2d70a) Z8(d62a8347,76cad2ea,733c0f35,8b80ac5a,f123de87,4ad386bc,be621d9b,5f49c264) Z8(21b4a2fb,2fd4f186,615e3408,b2d330e8,2b159a58,483469f1,c198a803,ea6629b8) Z8(c02f6209,3e27ded8,0e116604,69d12e76,08dc55a4,2e4f7b2d,80f8cbd1,3f79728f) Z8(f5fe61b4,bcdaa9c5,fb9d42d1,40b2b299,d77996e9,6a8a768c,1bb14798,107d8375) Z8(da0f7c36,c842a490,f40888f3,529c9807,7c8dee49,7382d4cd,c6063a24,48abbe45) Z8(b8099dd6,90a03bf8,97c15dc4,22f976b2,01aa00a2,fc467b2a,5f3003ec,7a0a0303) Z8(ec29e322,a7e38d91,fed7377b,07f39ec7,332c23bc,758240ac,cd45fde9,1b038b45) Z8(54d735a7,1047c684,a7b59951,f3f3053f,11454856,4ece0ea3,1b112d11,50b38ac7) Z8(5cb82173,741fa18e,29b25b98,558bfc71,48bbf5fa,37195202,914ff712,eb0ecfe7) Z8(db1aba7e,d3b922c5,0a271dc3,70a51a96,ac99acc4,dd561cef,fb6db42e,c65c49b7) Z8(53f04181,ab1f88c3,d625e295,1afd28cf,10fd3082,504b46c9,37c23bd2,1c63228a) Z8(4ccec845,e6c04c0b,b0af5f1e,517b9d3b,cefdaf16,a3b8fd4d,a7e613bb,657577ab) Z8(8e511cfc,fb50acdb,b48f3e68,53c2904f,34303bb5,86d4ffce,97364ac9,f95e5740) Z8(b39e81eb,2f1a84b2,0808a9be,33ac3688,2b24ca55,321aa249,e92aa577,beda85c3) Z8(9e96a708,a9132578,59b83e54,3715d85a,74291f7a,30878391,39fc1d80,892420e1) Z8(27e7e69b,b4cc6118,3697793a,5f306865,c7d9ee97,b9958104,87fd5ed2,1d772ffc) Z8(09cb9d48,8a47f260,ba2ca81a,24a4e88e,66295a74,8132d4ea,5e0310bb,1728a243) Z8(192cedea,0e991793,6ec4ac58,a6875b89,f91c850c,f6f37b95,5bc43b7e,b52a5942) Z8(8c2ac657,61fd0946,f8508e78,787ef7cc,266d26d9,30339e90,1ce0acbe,846b017f) Z8(3fe89f06,9ac368ab,b9f98307,92bad912,a95e27c9,71ce6350,84effed4,59604bb5) Z8(71a74fa0,21a9bea9,b5cfcc6f,46435dca,8b0fe044,03475967,8d5d55ab,0bd0e6cb) Z8(fbf20111,832821f5,42b51b22,54aca0aa,722545df,058a715f,f64a3679,8fb5b8ba) Z8(8f4d6916,9258a9e4,c023d188,2a16b80f,dab19229,d71d0dce,34e1a6cf,856a2b6d) Z8(ec4dfbe3,e550bb9d,02ed94f1,afee3ad8,fe16e64a,865405a8,7b94a8a5,7736cfbe) Z8(fcbe7509,ccb258db,89af3603,3a7b8aaa,93aa9f3d,5811748c,40a6f672,94a56f35) Z8(0a0ea148,4b313ec6,e96dbd92,5e0f28d0,69ad0ff3,ec15caad,e0d81586,546032d2) Z8(37b68616,1c42a436,269db45b,f90fadc1,c6aa7d2d,744ce7ca,3022d936,6a5aedff) Z8(8b54c939,15abe590,7000578c,5f6f7b81,d41cf4d2,3de64f17,04b75fbf,5f4a48ec) Z8(c09d4318,022a2466,5e9f0ca1,a2d4eeb7,13ec71e3,888aa64f,a78344d0,dce4ba3f) Z8(4a3ba731,163e9b02,a0d5f085,69843e1e,0ae2207d,c14ca55e,119c9442,002db15d) Z8(31683b5a,96f571a1,e04736d5,cbeaafd9,5a75aac0,0dd2eff9,41368702,484c9bda) Z8(1c7236fd,aa25135b,3ddb29eb,e1d32ef3,9f73d0db,e15fd187,0c50a3d8,8a3fb6e4) Z8(ce33df4a,d1c57f08,6b17e4d7,b1e0f7c2,51a4e69a,82ec8497,ad5f40a6,f564cdba) Z8(b72996b0,a615ab2a,c76009e9,997f3505,5722601d,e2e8d219,705719cc,b1384e38) Z8(375101f3,82b033c5,107bf2e4,7a11b580,2165d46c,47410c23,bc922f95,af8b5018) Z8(b92a9557,4b73a717,57018778,441f0813,e188808e,025e60da,983fe53b,49098e88) Z8(adb47cb8,75770ac2,cc5be076,052467f2,67b64e3d,391f9301,bb263a81,07ffaceb) Z8(088f88a7,6be69f44,cd3be04c,fa4ef178,fcb1e87d,9b7b6ce2,57220ec0,48d28ac2) Z8(c7216dcb,e431ba12,52e0bf81,0bd29104,adc9d9cc,9455c285,a9a2b447,dd166627) Z8(92613e38,860e6971,22997ebc,1b9b0873,dad5d9cf,78add210,3152a5fd,078ccfa3) Z8(f169ae28,0e0b542e,da502d91,459d9f62,52d33073,d32b8157,8ff115a9,ffb3bc32) Z8(e4594795,a3a963c5,96f5ef57,2f6110ca,28c3971e,052f4626,b9aeb4ae,e4c4ad8a) Z8(5c902d4e,1a43be1e,774ccf98,614d0b71,d84faa6a,d72be32e,d53a8afd,b29885eb) Z8(42f6eb24,9bd4b758,f6bb38b8,8f008b00,e9b1bb03,318a57fc,0a56ec7a,21e07eb4) Z8(2041b1cd,af2091dc,55774607,ee4c92e6,9e715adf,23c30bef,362ce980,a7d584cf) Z8(b20101e4,0e94a6c6,fc3bf63c,0d8b767e,44f53136,9ad3bddf,0d8990aa,15711cf6) Z8(6808d4ca,0e23bf75,932d834b,ccaf96a5,99d7683b,c39b0c6e,cc938122,8b3a4073) Z8(74a0d14e,b1caeeee,a7dddb9c,c12a6161,750e03aa,5ffdc94e,c68f587d,91b12a78) Z8(a6240b12,a46245eb,7e37bdcf,44018366,5dd451b5,c771588b,9944fc80,3a769172) Z8(5c9abe8e,89639829,aba5d5d4,6dd1c3e7,e9e56d5b,03fd1a43,e05c9c97,a21a3ca8) Z8(b45e6a69,9f945ab9,1e795222,1c58b262,6d5997f9,48291494,64da94ab,eb0ab1b3) Z8(b57a6374,ea0a67da,b719eb8a,6cd49209,ccc753a5,94d5b21a,b15c66f1,d23f3bf9) Z8(68013a9c,f1c29456,3ffba60e,1ba92d78,5b1120c4,99daba33,c02dd0b8,00ad48f4) Z8(9135480e,20184add,718c4e48,eb06ce52,c7f04870,cad26baf,d653f325,467f5571) Z8(1e1ec4aa,a3cbb5ce,bd37f51d,dd8fdd31,735458cd,7f5d42ab,cf329319,682096dc) Z8(ac2c3898,33d0d248,01c084ea,97f76292,b9c62d1d,16c27d5f,78b99d7a,2d0958ed) Z8(6380235c,0d51933c,27ca5762,b48a515c,679b9a4d,10160c49,d31896b6,c2a9fd71) Z8(da57ec58,81abbdb2,622667bf,aa8d1aa7,1fa462fb,23a605e5,898fcc20,ce6f375f) Z8(e13f7cfc,684404d1,cd8f867b,78b31917,273c87e8,7992657c,1922ef00,4a20f8a2) Z8(edb045bb,d1154565,eefa4d2b,50eef811,47a6b1b3,b1610403,12dede6d,e9ab8674) Z8(015dff8a,78bf163d,26a89a69,08527f69,eca4db17,7f339845,09cf14a3,964a6dd6) Z8(4c0aee5c,8313d0b5,d08e8146,419a81df,e94065b1,e548497a,2f45024d,ed715d99) Z8(933e83c7,aefbac0f,a82b5ac1,b0a68b6f,61af8f1c,6afb7fc0,1d20fb8c,d400c979) Z8(5938b56c,e5bfe3b9,fdf2cb6e,5d4f3e6a,d0da9483,137c1942,f8cf2582,bba7bb14) Z8(a8253fa6,70ce52b3,f1ab488a,f52c4a8c,a2c2698d,94b7b46e,7dd3492c,dc1fb0ca) Z8(61dc716c,f3a9c9fb,fd6e2ee0,8b42d0c4,0564b7bb,5ae95e34,507360e7,cd5a2e65) Z8(25126dd3,d9ed055a,f29c6971,e81d4c23,cb0d43ee,be7a1185,c01122c4,a2356805) Z8(627900a1,ba71d0dc,4bf6976f,76c14f9e,6f2c981b,2619fb35,9d113e2a,3c4ef84b) Z8(9ddb7e3f,b446ff53,447daf4d,08ceb8fa,7141b438,5c9982d0,11e83c65,0c697c0f) Z8(f676180f,e51335ef,2395d531,bc3f4f20,0a68b767,40b51b48,bddff6d3,e8c690af) Z8(2df0557c,5c2fe528,d408429b,4b8bde06,2fc72aea,2b9380a4,f3a4ff85,8e48a5a9) Z8(ddf9f7ee,e20ec99f,b63cc257,9ffe8fb0,76b92097,64a44f75,24800835,969811c8) Z8(d8ab8137,057be1e0,4583dc90,c1c93e9f,102b37bf,3de3c238,778eb0d1,26fe71e2) Z8(b0317346,353b5083,90702a9b,20d4e067,c656f28a,58b4777c,44f48017,23ad4801) Z8(36624762,f8379e5f,1568760c,05ff0e76,b6ea671a,4d7e5a84,735304ce,76ecfda0) Z8(ba5f4da9,0754e772,5b46c84e,276b7094,b03e1cc2,455c8662,8ae3b9e8,495a0543) Z8(b2c4555a,29af9899,d2e79ef3,b5d7d157,3e350fe8,358290ee,5e801b6a,7f3e3898) Z8(823dca27,e9bc9284,2424c266,9dda246a,5a71c570,ce14db33,51331a1f,b99fe0d9) Z8(dabb82f5,4de0111d,9b2bac42,5e8b03df,01ffb8fc,0e3874f4,497ce216,2bd7b489) Z8(89bb14cd,e7678b74,84a4cfd5,16b4e8ee,62816fa8,376332c5,a0112de2,d075f273) Z8(d1d2ff69,7a6dd146,1437fd30,aba45951,45d2ceac,e28db2db,2eb5753d,e62dd852) Z8(eb760a45,a8743e44,a61b26c3,575f15aa,d9f580fa,ee294020,334858b8,0b9425ee) Z8(3279aa33,24d0b73f,3ff7ad29,2077ab72,4ee3763c,656a661d,661e41b7,d5d7efba) Z8(82f6752d,44da9534,93542145,922ab1eb,0d085e40,60a170d4,2209fe4f,a330ad78) Z8(3729f83a,0f74ccdd,5ec1f0e4,31dcc4dd,4ad6522e,7b777265,a31d9198,50de8a27) Z8(c18ab031,08b8ca8b,10006693,41523f6e,8b89e6fe,02d93560,08c38fd8,139d277a) Z8(7f363938,fc79f6f3,359749a3,1adf144c,11050a33,045f3880,f77940a1,74b6e5b6) Z8(083c6bd6,6158f109,8c1d2459,df1cd684,ad66f9e4,7f2cf4c1,339a14e1,32ad29dd) Z8(91d26e40,5e6c0376,e8a2e874,389bd169,7ca1cf97,a2fdc091,6979145e,3c18181d) Z8(a5eb6b46,595d82dc,0c0e9978,4400360c,767502ec,1c4c308e,2c8a6320,3c6bcb6b) Z8(8c2538f9,2b0b9b90,362dc818,d0e1a022,8b78b85b,1c4c24d1,c169dbcf,b51d60b3) Z8(62ff47d9,1e57dcd0,6db54da6,a09e08da,178e6d83,f6225d36,e0002f4a,15b86238) Z8(22207026,a3937199,c2eae029,ac77c7a8,6019e93c,1558ae57,d9104941,35c96e5a) Z8(5b9c76a2,bd564685,c36eef67,55f408d6,55355f91,6ba7c43e,b72b9863,243cd244) Z8(c332e663,9b714ac6,065c2adb,1e1c7e11,ff39c154,8258b9a9,9d1b5911,97b56922) Z8(79197da4,33fc298b,ecf5ce3e,322f551e,29584a6e,79917f0b,1a94e375,1950c697) Z8(9e9aaaf2,f321eec1,04648d2d,71722053,0ba6fbc1,7b6f043f,039ba2ce,ec3596e5) Z8(fff20f67,5bdef7b6,f007410b,4d9e9d7b,606f7d6b,d4fa23f3,083c5d71,5df2cd54) Z8(96c6bcd7,eef8caf1,c1af672a,f9bbed39,61ea1176,a8a8848c,e2fd042d,7a27eae7) Z8(ce83e52d,0fec39b9,62b9447d,d67e18f3,77d9b714,9fc510f4,8e15ae2c,b3d07d76) Z8(3e94a7e0,f9e86598,0c09cd81,27e78fdb,d968f581,df2dfa26,dac92d7b,af4ed43c) Z8(91c2da46,ebef374f,b355c529,a9171add,1b5f18f1,8eb0850d,4f52bd67,1b42dd5c) Z8(6075889b,3e073f0f,eab19a71,53aa849e,320de8cf,6d4f78b4,af1fa39d,bbfc88c9) Z8(7ffacf0c,104bbab8,3aa19a09,f1347443,8d675e9c,df7bd72b,c2417f70,3e9a8245) Z8(8cc68b69,1b5df9c0,7ec52e2c,be9fcfb4,0487a966,544e2721,d60e6350,d9e702e5) Z8(2810195a,f44772e6,4ba3e319,65886955,65f60a50,931ce8aa,f0e3203b,4aaf57c4) Z8(53d7640f,00c837e5,ebd48b0b,152f72c8,60f23f50,1dc89ab5,c59e6d2b,835325ac) Z8(6c3574a6,21e0a710,71a3bbbf,65df6950,adb32892,96aad8b8,58ed44d8,3d831752) Z8(cb009c94,5239d15f,afe6a040,d66188e4,cc9e94cc,82378f2d,221af444,9a1cba07) Z8(63b114b3,9c14fcfe,bbb15fc8,e267962e,98f7ede8,75467d5a,25dd0683,0a209a9d) Z8(179065e7,b41b22b5,b78d21fe,4aa56940,df23bf01,14095c69,018fc641,18f19c74) Z8(3b4638c3,e7d228c6,db473866,42e60415,bf54e4a8,576fe7c9,bac4766b,b97524a0) Z8(ac61bdd8,86f2fabb,9cbea239,e3b8d8e3,5694718e,45c68177,58624c7a,d8af97ae) Z8(889f8b10,9ba06405,6c91f976,1beecdd6,4c164dc0,dde90fe8,e1ae90d1,6625d102) Z8(3b7e5b67,cab6c4fc,6293935b,2e5791b9,65a59cab,d8a1f609,1ecd04b1,921f8f34) Z8(4869421d,00a81b0d,e83ed8f8,bb1a6827,6cc9e68c,8d02d6e1,92955027,8f6f5a9b) Z8(41cdfa82,c786c25e,7ffdd56a,098b15d3,28d998d8,1da2e26e,101f2a90,aba525e2) Z8(31c6d58f,14b34442,6e5c5823,58d689f2,a933ecdc,24ad7b5e,effcb16c,2a92c843) Z8(55dc3183,956479c9,57a50fee,21f901aa,898d1076,f2c32053,f844133a,d32bda78) Z8(76c79def,f5278fe0,c4e3aef0,c21a2120,1e2fd619,c9f68260,33d2ad27,dd965965) Z8(eb1c20f8,9752c22a,a4dd2654,bee4b389,ebbe216e,45cfa25f,994b0905,6c932ec7) Z8(2eda9a3d,e557b1e4,69dd5710,29a842a2,31276a25,32279e0b,129ada49,c27925c6) Z8(f882e2ac,e5963b3c,0c7bb52f,fc840a26,865e3ac5,9993fcd0,121cf72a,b545c72a) Z8(c9222bee,a376dd9e,a0fe034b,c2fe582c,9755753c,561f4a6c,4f4bd8b6,666a0780) Z8(ad564fea,2b16da9c,75bd3616,cde3d2e7,be440d4f,fae696ca,e4b29215,d7ca1adc) Z8(5860bc10,a1e6f9bd,baf9db0f,b8113a91,7f4bd4cd,2460a9cf,51307642,28cf9aa0) Z8(90882946,166aea6e,a774a6ee,c422d005,e693e87d,12575791,0659ebba,3e645e5e) Z8(4670d859,6fcc2185,44147d35,c452479e,e68f6fdf,63f9b0e1,48d9d5cc,fdab80d0) Z8(6beaf824,1c759f65,9324728d,bd8056ab,e7053715,e16a1d48,6e760d30,434ecbe0) Z8(8f746c5c,225e12c4,d0edfafa,d724cd96,c57e0de1,ae2a6492,833a0cea,88e59eb3) Z8(b712756d,4ac1c0f2,a3bc24ac,f6af9a66,936dfb00,6d541837,2e407e1f,c3534651) Z8(1393e5e7,dfa1539d,0393bdb6,de0006a1,aff34003,6675f9da,c08fdb43,e301c24d) Z8(7a13870e,633602af,8662bf72,c26f9ff0,680b686d,3b7aec87,b6dde0c7,9464eb9a) Z8(462c8733,d25ac32e,91a1284e,2354ee28,731bea6d,483cb9f8,da4eb473,6a7b1cac) Z8(82d13f94,c1fe05ef,2893f33a,bb8486db,5deaf7ad,f070c1a9,4413f45d,902d11e7) Z8(9532a491,aaf89f15,099faa13,bedf794d,b522fcc0,82bb4aba,b53798ce,8e80a982) Z8(a5a668e5,e90a72a8,0004ebcd,8b8b2388,afc7389b,1a98c25d,587fdd9e,80bc42d9) Z8(0270d419,f8c0fc20,33b375d4,4ac13ea0,ad7ebf2f,35f7906e,7672e77b,ee9ca31a) Z8(2e283baf,672839e6,fbc968db,09e877d3,a489c3fd,f4943a65,35d9a1f9,470483b6) Z8(bbc195bf,ba8503a7,6e083bdd,6f932771,f12807da,8e725d40,c523987f,029b2813) Z8(ad6c4971,51602236,1c020f10,81d998d0,97e95701,a1be0d65,03f91cb1,afa52910) Z8(84b53b76,94f6155c,34b4ae18,5d2c49fb,b82fd80f,631b4715,0836dc31,dc098d28) Z8(f8cdfa3c,1dda0686,04bb4b2f,1b4f5728,2d228630,c1db5f2c,10022d67,536ebeaf) Z8(138fcb2b,cdda6bad,5a00cc71,35831b14,d05e8809,4a498ea2,1953bf6a,e1d6c078) Z8(2848362b,d0d85a44,8b72a7be,6303cd97,6f659baf,9054a783,3e8fd85d,a1fdd8d5) Z8(8f19e53b,2b5771bd,25816c1c,8c9f0733,04ce7c47,f6a28d81,08644ac8,b2b7caaf) Z8(69adfa3f,142bd147,94e110d6,5c8402e6,a4979e63,c3ac6bc7,8882553e,20132a72) Z8(01b3bd8f,f8d33c19,74d3b5ea,ce96677c,98992629,7acf99b9,cf839836,27d37e58) Z8(cffb9f85,6c41d914,62caad36,f984d4e3,e7181b99,ca6b25c2,1e887aed,17d4f008) Z8(7d69cf4e,6d020b38,980e5f34,0f318132,0eceddae,5cbff485,10f7a4bb,d8e74524) Z8(a034ab8b,66372b87,b13e1af6,a9272703,40f2bec8,2ff33b8f,464eed37,69cdfb94) Z8(b02d517c,10b5056f,0675aaff,18728cf6,30a39845,0609c0ef,6a51975a,fcc66520) Z8(2ddd24d7,21149bf3,8bf918bc,c7409172,e3bf8191,41581d5f,a5a3cf40,7383c87d) Z8(f489bf36,eee6a84e,89b42956,97fecc91,5e647bd6,548416ea,6e856bb6,0d4ab22b) Z8(eabd03cf,e95a3ca2,6f9ee838,40587d47,ba0880ce,13545583,8b061311,e583a16c) Z8(ea8b6c80,b4a4af9e,6a12ca0c,d7bfd0cb,477219d0,309731b3,fd996df5,469f56d8) Z8(b7989352,f14af0d9,43a6d57b,31a07275,5b1ec477,c51738a3,b9ec3a2d,0ed9afad) Z8(52067ee8,7af5d8c3,4dabc9e8,5de2fc47,58eb4e3e,f2f981e7,ba2264ef,0cda7569) Z8(ae379af3,8f843de6,ff82c489,c02d7dad,37333f59,c1970215,ba9e85e1,737c3a8f) Z8(e02b6307,7d1b7267,17c85bef,cb0b1597,6ae6a5c4,3caebf55,bfb91bc0,fd61893e) Z8(b4a5c93e,477f0e59,e6c4f9c3,0719a761,418570a3,3d9c5b49,ca2a0510,2ea8f417) Z8(e50c3277,5edb832f,25a5af9f,1d9ff844,9d48c097,2c6ffe2f,42f85b3c,38ecd4be) Z8(b584b53b,bc64c7c8,2e3bf4f6,f314fb16,fd6f5022,e9e5957b,6e8e2a43,8621b128) Z8(eafc328f,90f315e3,26cefb4f,205c906e,c6fb0149,c5fc8835,cbf26056,76f7088a) Z8(ce86a30d,df4d01d9,5ef83340,a234ed14,6cd007e4,db9f19c0,b88936b5,b0d8667f) Z8(20d7649f,345f8a4c,42375964,3fa085e7,08c776e0,c6537f67,d0913c0b,72522a71) Z8(9eb8e439,ef6e478c,ad0d7eb9,d3104591,e9b3c850,155ebd2a,4c68bd5a,42dbf996) Z8(978a8194,5590d2b4,59ec0a43,2d537b68,cb0da98f,32a22fd3,9f64c8a8,81b79da9) Z8(0be07223,5942778d,216885f9,c42d7b98,9e1d3a21,f21af731,b03d0f27,40113a3a) Z8(4c4e779e,17f0b8e9,ea2d34f1,8528389e,01226a1b,2369dea3,7bd13de5,1aab9ef5) Z8(b6db7a5f,12adabc4,20c100f6,b23b5479,d20dfc56,a54e2efa,acf4b400,7590ca94) Z8(95c70166,faa5fc85,98f188bb,be0e841b,0b8a43ec,dd14a7cd,bb12c425,6f498dbc) Z8(6f71b9d1,d78ebe45,f3cec11d,cb944558,e06d8ecd,baf7aa8a,45998ab6,b2c0c21c) Z8(60456dae,a94425f1,84f22667,861e8c8c,310b6873,af154022,0498e2d5,ac5f69af) Z8(a6e11801,4d3c874c,1799b81b,f5a2753f,229774ce,916bce87,b1f6d7f7,d827c7cc) Z8(0fb4d504,87c40cfb,8bc0abf6,2ce2e730,41b95f5b,5e9d6cc3,369d1ebd,e62f304d) Z8(34e29a9d,d9aa67b1,5b8e0413,cc357a12,6fcd9db5,78cb9152,0cabe806,e215d180) Z8(9a584347,d07f4124,b7df0fbf,cfafe4a7,233b4ec2,2128595a,6f9359df,8acd2de3) Z8(07c13726,9cafd990,a5cfdbdb,c30af077,3e659f52,ad7f916b,c0639407,a14c8dc4) Z8(d07c1ee8,c51cc17c,f838f626,e230c892,6f36a101,0ef480f6,dbe7d200,9f7511f9) Z8(9e27bdda,4de36e50,cd10874b,7c3513fb,43fc16a3,1fa5bb66,9dc0229a,a8752870) Z8(0eda163a,4350ad27,7d97cbf8,e9054a61,32dd2691,9ab36339,934a8284,a15033c3) Z8(c910fabb,c4a49feb,943b73bd,ded03c09,f791da2d,bf58cc91,d2f6adf1,6edcf906) Z8(d0a53aee,64f5c0cc,179f3a41,47a0a83f,26d0d4d5,ba9aa43e,e9026030,c4f1c5f7) Z8(4113a267,a78a6df4,79d27ed3,4a305463,1e81ae4b,0fa5e9b5,ae2ff41f,5716f76e) Z8(c1339300,1b38deb4,9a163219,cf142472,a405275a,42cf2341,26fc00ec,e7a45556) Z8(dc586052,3e08d81a,da67f64c,1316953b,6c5752e0,a50d01c6,bdacff22,7d33b304) Z8(f4bf5a54,ffb3cd77,6435d18d,e0217ebb,5d13f71a,fe4e4b38,738b8478,fe7b2d0d) Z8(8cd54ff4,38676d0f,48e7b575,05e93340,e38d9461,19abfa01,466c7d1a,0a17c381) Z8(3709b945,2516136d,af95757c,2a5f911b,154ce075,a345a8c2,5dfba3b1,40de02a1) Z8(1483192f,e63d2eaa,b9545425,a44f45f1,d3c3ef87,42509bf0,53c96eb8,b067d886) Z8(b38f3e0e,9b0963ae,4b917df9,aea8ee8a,03a9f5d0,b7691cdc,81acfc27,4f8a5538) Z8(2cef965c,0d14581c,99957582,d616ae87,b3b9db94,c65c9598,aca524a9,9c8c94d6) Z8(0452a048,f785614e,7a4256f2,de07defd,6da2f656,0278f4fd,730280a5,e1cdfa52) Z8(cffb2cad,325948bb,26d70c1d,d43de355,9a775b00,5caa2dba,62f002f3,5a9622a0) Z8(9eef0692,14009f04,48e65abd,4f3755ba,fa949af3,d0f8c346,8b7ac9f1,9019f4f5) Z8(84bd7d37,146c6260,e931e139,97cae39e,c4e8b543,20c61d6e,ebb6bc96,bdaf93a8) Z8(ff28e4d9,05fbc893,8ce5e846,44cd1b3e,105d5836,0b9b2aec,af106256,473e1010) Z8(b66708fd,5fdb92d8,0dc8d6fe,ddcc673b,7643d6c8,6581fdc9,da88105b,da4d15a2) Z8(a7a46eef,284a352f,a4f59891,6168cb15,2c99de69,2c18c870,566043c4,f36b3d16) Z8(d01e098d,4756eb39,90cf3016,87050ae4,f9e09d05,b47fa79f,b10eca95,690de2cf) Z8(37b60998,437be0c0,8d96482e,d4b9f3a8,8f11746d,8567842d,75840827,d8d47e5d) Z8(e75ceb2d,96080452,5ba1cc3f,a28cde8a,3568d779,f242dc61,f45cfb6c,2a02647f) Z8(1acbe823,62da8daa,0dba279d,365836e9,2bd8def6,662846bf,cb89d477,615bb08b) Z8(abbe7553,d9a01605,7d31b512,13a3e19a,44d94ee4,e0469c1b,f8d3dd59,5412a33d) Z8(2d495611,f6a2128b,c0705971,7f80fcce,37b6e778,82e1233c,82032647,1252f5c3) Z8(e255580c,e8d24efe,e4f89aee,2fd21908,fc943425,35faf731,92696aa4,6f7d797c) Z8(6b415169,989675a5,781ea549,c6f1bdc5,2dba2228,7cce1a1e,08c73fa0,f9e1b338) Z8(cfa54d09,54569c2e,acbe97b5,16ca315c,c587a86a,b090e999,c3f2b082,b1ac5fa1) Z8(3fe0e335,19ec389d,3e497bdd,4ed08c11,4b2e09d2,0d4bbb08,60bceb52,10e2abb2) Z8(09878159,885869bc,2937ae37,e5b72e2e,3bdeef8b,4d2f33b4,8959a2c2,125670db) Z8(ad59b4ed,fd99813a,6f254236,bfa3e6c1,930f18b2,fb6a2a98,f35a15b1,f5bfbe95) Z8(f3378b80,35fd05a9,d66f8405,49a220d5,de7146ae,f91a74dc,424fe2fd,687d82be) Z8(ab696d48,7a48ac54,1c90f7e8,46724491,f1a78984,ef948a3c,4276d942,2af28661) Z8(99f414e2,e83df521,18783932,e934078e,2c07f089,af0a1b37,a01b17e3,87ec24dd) Z8(0f50edcb,57831ddd,f5f42367,31447178,5f17bff3,e29546d5,77ed7e32,92eabe89) Z8(cd87896d,73b24753,b89b9c24,4d00e74e,4f00c74b,7eec7007,b88ea2af,0faa8cd3) Z8(e8bc8bd5,bcac60ad,dd95915e,e4c91686,9cb3aa84,a27dc1d4,42d89afc,4a4f251b) Z8(750f5bc0,7c053d55,e9b5eb61,cb33b992,7e416ef6,0c4a3480,e258807e,82e680c1) Z8(914b19df,c8dff8ec,53c01b89,7e58508f,eab1046e,091f1651,1b501a09,075bf74e) Z8(dcdb2d43,cfbfed23,7f0c222c,b14a5792,60de8a25,1e87141d,70d1f0e0,2f0ee0e1) Z8(ac0ea292,d730302e,397c4d8f,81b4f9c5,bf482bd7,5b83e11e,7adb95c7,484bdd94) Z8(a9de16e3,38d9c127,922d9d22,ea03a07f,cb7306bc,19cf31e0,94b3f82f,ca870d45) Z8(229b5ddc,30380b61,75be285a,26c01b90,7f3cb2ae,de1d1167,1fa7e858,a556743c) Z8(8ed8bc1c,1e11a374,2e646929,9dd6f5c6,22cf000b,08cbf907,e5e7973e,62a39ad6) Z8(355d51e3,df5dbe13,4661edc4,aceb0a39,2ac558d2,72ee4b8f,7c3343fd,4e6ad7df) Z8(a02aa01f,3bcbd8be,eb75c113,2a42a009,73c16279,1ec8a187,fbcca458,bdb75556) Z8(ca883405,fb86cd77,2aacaa5a,e051242b,73093588,6e3d9374,7c852f84,a0e1a0a8) Z8(24b83823,9903ea68,466822bf,c7c6db30,eebc0309,78d23a4f,39ad5e4b,20e43a8d) Z8(a94d0de1,744ef929,cbd4f9d2,36dfa120,e6845137,f3b96f32,53f9cfa0,906217ff) Z8(54e49c38,40920db1,ba83c45f,0bd48d9e,d9ba4696,4c092e0e,77a86b6a,54baffef) Z8(693326a3,44badce6,f0dd3580,824c9b2a,34fc86da,dacd36b5,c498f408,2dc4f65c) Z8(b435327e,c4c1a0ec,1c21cf94,d85f8ba3,63d8196e,f1cf3f9b,ba51bc80,ddc72a04) Z8(34f5f9d1,cf2a0a43,0a1fb245,aa74f617,6bb9fddc,9445109c,3716c973,05abfe95) Z8(ed89adea,061d5e8d,57ad2c44,5a9decef,9bd441e3,60751740,b5060f5d,1e15681a) Z8(a059c9f9,457835a0,92cad68e,f84f07f6,6df5bf56,6397cac7,f6601a34,bda850e1) Z8(a9bdec25,4ab05b3d,ba1842e4,f98d1768,4d5c268c,48d0144f,6742ee4f,33d79fc8) Z8(aa2b095d,a4076872,0adcd0a7,db86e59e,ee004b5f,477b988e,29ea8d34,5b6ef3fb) Z8(185ef97f,35aaaf4d,630c486f,110812f4,13f8429a,e772e350,d60ee5b2,bb7e799c) Z8(b035bf38,ba515f92,49cbe723,b8992c13,9f29e360,9bbcbea3,06915971,1deced7c) Z8(48d059d2,3d6bc29b,4a32e9f6,2aaf66d3,66a6b104,23aae730,80afd8af,07c27974) Z8(525330f5,0bff6c82,240c4baa,a9a65e25,f5b74b38,93261398,361241db,25e3a52c) Z8(dd8021dd,cf10862e,03f1d701,80f76ff0,1e7af9fb,9486eaca,87bfa96a,2b761068) Z8(d1fbb33a,9f1a266b,d0cbcf01,f4ed09bf,f753265e,eb3a87c5,7b25f161,678e824c) Z8(6fcabe86,43dd87c6,a4466651,d9f4c24d,5264fd97,934df9e3,7a6023ae,db7afc26) Z8(bb5a8917,8884d576,ca1d58ea,97c20e9f,20588246,1802c32f,44955891,d2a34b70) Z8(ab7db9e6,7da88f32,f072b430,322a172b,fc0c83a9,a01ac0b6,13923e0a,6d19e59a) Z8(58c076e7,f1b85686,d3cdb8d2,52c605d2,ba4e5b62,0459e7f4,3f510e4b,f14966c4) Z8(67c0f1f7,f74fbba4,2addbf6a,c6f9d363,a78178f1,f7884fe9,4cffeec6,b34beda8) Z8(f8152ca3,4fb495e0,5073acc4,4da07cca,42244ac7,2a3dab0b,8caf5bb9,b58fc47e) Z8(d4e05a7c,525dcab8,c39ecf52,7ee62df1,2cc450fc,6b96d199,296d0d5e,15da5f99) Z8(4aeded74,2f114b43,a7447a3c,55423d67,c6ee9cc3,6d11e432,758b95b8,07e7207a) Z8(7aa6c92c,1094dead,b7ae6dfd,315438e4,d9a05df3,fab12361,42769719,c639d7b0) Z8(fb2a694a,73ba67a4,05995d97,3c7a3482,a96e677c,f76e7efd,4525e94a,09162caa) Z8(8aef8eb6,5d41e584,17a98a60,99d20154,87b23bf3,9f6ae612,c25f07d8,942edf43) Z8(f419f690,fb7ccc9e,58b544ff,b9ffa6cb,33c7a4ec,5e05a794,9e1e9e0b,29db1de5) Z8(737ba69c,f7dbc12f,71f49660,a10aa47b,ca44aa8b,6be20256,e607c389,24dd7618) Z8(09cdcef0,1e5c0cfa,00cc0bdf,7a5d0ccc,df5e265e,27e318f7,480672c9,14c0d43f) Z8(46d6485b,e9651f59,0f56b5ea,4bec5c8b,34a0c919,ee64627b,48b7ce61,300c0372) Z8(7cb825e0,7132214c,272fc944,01325ada,9aa885d1,dbad6346,a8a78851,85eda194) Z8(363c028b,651508d2,ea272261,d1d73a2e,904f6bf9,237edceb,595539e6,6de06a97) Z8(27013885,efd83dee,15862e2d,fc140408,f53f7132,5fd44606,0a6b44bc,2676266d) Z8(7e30a926,5622b2e6,d5c47413,8ae3afea,d10e8c9e,c0220924,eaf83cd3,5c19bb65) Z8(8b6735fb,c2d8023e,71d96cc7,a6bddee9,b765f740,72a94311,19276865,dbcf8ece) Z8(21d2b57e,d4fb23db,8d617a05,4c71285d,ef5a375c,fd781091,49513ff9,0f8a46ab) Z8(334a700e,ffad98f9,1dd30c06,291af134,24968172,65c19a22,15917ee9,b177804f) Z8(c6366e60,8948f982,044fe69a,89629cbf,ffb1fd20,cba4e4ce,5af3eca6,b8cca47e) Z8(0724156f,464bbd51,b6ce5232,c91d86e0,1cb5466f,4098c6f5,916f4c79,4e50f2ef) Z8(a4eab401,e4995642,a5e3bbb3,7142e289,0937d41f,9902bc48,69070d26,f9375938) Z8(18006dbe,376701e4,06cc6eb9,15271a0a,01102b39,750648b0,f6502cb4,fa115e8f) Z8(d4e51945,a0d1bd85,27c578c8,c2e061f6,41095b6f,1a11a4d7,4b10b41c,9bd0b931) Z8(a7792989,80bbd59e,905abc00,328bf05a,908638c1,96c1b21d,87622f2a,72919e2a) Z8(726e6729,62755a9f,2e9493d7,ad1eda99,1dde7ebc,adbbe7f6,78b43650,cf9a5762) Z8(10ee9fed,cb0f0e2e,b81de811,9031e2c4,6b1fd8bb,e7baaee8,4c9ac0a1,14c8cd01) Z8(0b796f15,2728dd93,6fe903fa,9704889d,68f8bba6,f5dcb53b,a3a0d75b,5f8935fd) Z8(3227648b,76007e6f,a9762390,58112c51,5048e983,fce91fb1,09f7ea9d,37c5a7d3) Z8(7bc60151,ba6d4fd2,14949515,bae4ff3f,3bf647f2,6ed68340,de3ee596,a6c848ed) Z8(675baf0c,a0cfff42,db361c4e,e445aede,1c477a67,cd9e99b6,287eb31e,42f4342d) Z8(c396313b,49de1bfb,eb07cd45,0d9aa71c,ed748d45,2bf282a6,557b6c99,29067b2b) Z8(b1a879a1,0792cb6d,024c27c8,62450b0c,2c9ad95b,cc610c47,743e5013,8944ca99) Z8(0cf3fdc4,d3d94a80,52620093,ee8f7418,e1487d39,53da2aeb,4fcd50b9,ad31ce7a) Z8(cd11dba2,121b94fc,4198babe,165e569a,84347ac6,5bbf2daf,9d55db6a,eb04c60d) Z8(65617b8f,23ad4834,8b480a94,6f2e5e4c,7772b3e5,56d02df9,70fb084b,e1f105cc) Z8(189228d5,7f243fd8,ed823b6f,c32a6acd,ff5d47f0,888cd649,715b993e,b99d2d20) Z8(c9b9fe61,80e725d1,147e9688,0eba4488,f77638d7,d167994d,c30d2707,edd25224) Z8(2e451dac,f8f63e3e,138c1970,ff4bc9e7,8e9b436b,0b2fa503,6d2b7068,0e30a696) Z8(3bbc1d39,32b7a73c,0c49178b,fc604aba,f936f647,43e9892e,194040f3,2ca4b348) Z8(a76c9708,1a5d6263,30c55c60,d8e15157,86a9777f,9f4f62a3,2f3f61e6,bf895e71) Z8(833f9b60,6a4c5122,a99ba136,fa7b4f4f,9af9d763,774ea8af,f3ab249c,ad7e6fc3) Z8(c7b9423c,06777b37,aa6e2d68,575a34af,6cb4b435,cbd7b74f,252dabd4,8583e3b6) Z8(f8dc7888,4720bb7c,851ed91c,1b4f22fd,37df42e1,dcb59519,99e40152,e9a3a985) Z8(382e98d4,8b585186,4495e0bc,5b9f3ddf,844a7e41,77c697e7,f2c00072,ec4ef5b9) Z8(251c04ef,60dec5d9,317aba73,06d70099,f82eb4ca,648f47db,ce5b0420,4f0477c1) Z8(75759116,8dc761a2,bbe588da,36d40002,a9c5fd5c,1d07aa6c,61fbdfe1,01cd69e1) Z8(bf171234,267e234c,9f485354,096e67c5,93f6c08c,fb8aa06b,e5a1efe9,beeaaa85) Z8(d8c4439e,10162c63,b75090a4,8959ab8e,ecc05889,e2a627be,f1c30e3b,2010944f) Z8(cde24be5,bbbc39ec,a8b66a5d,4bde9075,31a6de38,ab0a0047,ac1f5521,23a8cfbe) Z8(da63d849,c03b20e3,2056a027,9094272f,d1f5452a,8a44e200,3968f1fb,c250dd8c) Z8(cfb092e9,4d2e3752,621a5083,967943b8,c9166e5c,049debdd,bc42645a,bd28c1ca) Z8(e13286f9,68a34c8c,039e1fc5,ea10f141,70c13b02,4e035f29,4c6d3884,38360d8c) Z8(d7c95ab4,55a06cf9,6d7f1602,49041446,c31655ac,807d4a0e,bbda9053,75684de9) Z8(69c049d3,bd3b60e9,b51f3ea1,fe2ddb75,b85160c7,e163280f,d4841926,fa9a927d) Z8(203b7032,469571c4,c2c11011,b56d7809,48685190,4397092a,398ed421,1ca42a0b) Z8(df0fd894,92b2f87f,d6810ff3,c05a3e45,296dbbef,ff9c882f,0759bc5a,53efec0e) Z8(0d6a325a,8437e866,cebdec3b,58cce9d4,10124f53,bafd822c,552ceff4,0f1213af) Z8(6c8d9999,dd265f25,9e2b2982,4bb9fc41,7fe90463,1c78252b,e00b3527,d548bbda) Z8(8b81d54a,3c887a47,af908992,c086d09e,211c4a0f,eb5efba3,8c5af565,a5552cfe) Z8(2b161fab,888b4848,0fa72ede,c979c54e,cecb3e59,85d70e05,f28c47b4,5e1c21b9) Z8(542d3414,9fbe5ecd,5e079884,889df948,f11f755b,1e7833c4,345310f1,48cd0adc) Z8(4d0ec4ae,44008fff,15e6cfaa,910eb993,2b6d0460,aadab932,161b8291,dc7b6e51) Z8(ad03388d,bddc5451,968317bd,de0735f5,5a375fc3,6de81896,e0c0c2af,262604e8) Z8(32462c0e,1e9be548,9c48feab,8049886e,cc62f502,ea7ce1ba,ab3c9b1e,95f7c3b0) Z8(01df36fc,94006423,ebe78c69,958ed2a9,611493b8,41cb1c45,d55f5dbe,61cf98e8) Z8(8cf8f734,773c72a0,5a509320,fa5f5111,e036261c,75e43ec8,ff867e87,3e1a26e6) Z8(9df31413,845df54f,d7b70f13,b51447f9,db5f734d,ac2d7320,fa51842f,537c57fb) Z8(91e63af9,5bae7f8c,993d53d4,8c9a7498,51968628,55947c60,7bd51988,ccc85020) Z8(f6b36da6,41c65d4c,c7366e25,6003359d,d2ed36b6,97594296,550ba77b,d2e15f8a) Z8(d0857af8,01478ea1,5819585a,0b8c5538,c37088e7,dfaf7862,bb06b24d,5e511288) Z8(40f88b7a,71738bb9,997d8eaa,c892ea71,b5fd7ba6,5f6ecd27,9d238df2,8d2d75ae) Z8(8b6f72ba,a032c912,a40c42de,ce246737,667bc6da,d094d6eb,10012cfe,4c448b73) Z8(e9df77d0,e0a7b50c,0b22dc16,4f88d34a,fc2a54a8,b5e5db35,d4acf6c5,b2e01473) Z8(945945a7,43731ffd,22ea5f09,4499c099,77d1d022,a73f3f92,14ae6232,a6e33e9f) Z8(93bb3e11,f1a242d0,da9f1f2b,a5ffd7e1,4eb3260c,2cc9e42a,3485911d,f53e9551) Z8(b4380195,f15b9cf6,d83932bd,9def7d69,9ae75b42,a70b8815,6aa89d87,a35200d1) Z8(661e9b5e,fe8b9a19,fc2970ef,88b73070,b5467b24,97a45dd0,23154d6b,98208564) Z8(9d0fdea0,39fc1345,2fb0ecc4,937e9ebe,7ebcf61c,968b3d85,33447464,8a47fcbf) Z8(7031ff9e,56eeaf2f,3633ddbb,cf764b36,82c3f6b3,9b2ff617,6639b97a,a2b25b0b) Z8(b88b7bca,1276768d,82efa174,ce2a61cf,d1bb8621,84652722,1b9d0860,cc2bc145) Z8(0c58d361,d4b72631,49e5b1cf,804a36aa,e9c2bbfe,1c810ab8,9965d370,05681489) Z8(4ebf9b9e,8c1e0227,b7c00a32,f10f0c8c,c7335625,097de10a,212b15ec,3763dd66) Z8(d7c07019,5dcefef1,13705b04,874b5ee2,03ab412c,5aceb1db,7f1adc9f,944da243) Z8(a5400d1e,1dbeb865,68cdbb61,a27cf32f,9ae0e69c,4dd47cf2,fcac3f5b,c01c9f5a) Z8(066a46bf,138d5a87,295b8947,b63505aa,ad9c7acd,8b472dc0,8b821ab5,b0918a3a) Z8(778729ae,800098aa,52c72cdd,e2f1414a,98013ac9,de471951,b486f0c9,c1a2c4b8) Z8(468433f3,be17ca5c,f8bd3b3a,9e415dd0,7efa1e64,ccbe58ca,498c35c4,3aeab7d6) Z8(fa8c445c,ee0bed67,702b4dcc,dd039c81,5f3efe2e,2910812a,26086f92,716739d2) Z8(00120581,4d26d32b,702d669f,2f1f5874,bb9d4d58,0e2ed156,93ecd048,3bfef344) Z8(677538e9,69067e2e,23824d52,482988a5,be44aa96,9ae01881,20a3328d,bca60947) Z8(a06ed10f,a0542fda,744ea04e,12f55098,a100e9db,12ba2c17,5de54595,65dc1168) Z8(55cb5147,11baa11f,347f7b66,b399ca41,e5ae7aa9,85883bca,4270b97b,9d4584b3) Z8(ae81d895,8656767a,67cc16b6,b78d7691,305940c3,a252b102,07004373,bef79803) Z8(e40060a0,a3bc6755,63cfbda3,658b7045,cfc74367,07e19dd6,265b33a0,c0a13446) Z8(439e7807,edd01bb9,0092824d,1e7a168b,d25500cb,6704a627,26b8bb81,115a44d2) Z8(03e2d33d,fa66d1da,82b2aa21,c8715df6,e03b3a3d,5911c66d,4e44157e,9b682586) Z8(91cf3f89,15160c7b,99ff6278,3bc08322,8d85fbb2,96862baf,3ae77c97,61296af7) Z8(99893f23,28c8a32e,69781781,3bd98d33,3d9780aa,3270a3f3,a5953897,c5e05951) Z8(04b82965,edbb719f,203a293b,daa5347e,8d069a90,7518bf57,6f65242d,b16aa64b) Z8(858fb4e9,a2b618d4,9f266a7b,b5091681,8d0e1f43,0412c78d,69a9e192,8b121fdd) Z8(fa9fbfea,5419cb00,6513f467,d93324f4,6b4405be,07f30169,94b8652d,b5188cd7) Z8(a09de94c,3324391d,2d06238c,94f71ca2,35bfc43d,631dfcd1,a53c731e,8945a316) Z8(99321a65,858dd82a,0d256148,2a00c6b9,ca0b54b8,9ff4df96,4dc4d900,cf7d56d8) Z8(b09c6090,d591a67e,54fbd6ce,decedaa3,be7ddfb3,2e4b0c5e,2db4e4dc,3fb92934) Z8(91bd8729,31c83aa0,48d8487a,843efdbd,4ebf02ea,acfd0ec6,c682aa80,d3be8d8c) Z8(6c7424db,8ff53cd6,f2c0a968,a7457b99,a6e27773,e8fabdfc,4858bb58,568d0b6b) Z8(010637c2,2147646b,27cb06dc,93274a07,1195ec2f,c53ebab8,f9fdf1da,925bbd83) Z8(2e8666ad,f3c17291,3ea5b62a,53f10a42,903f6cf3,a35f09a5,a7fb07c8,b554ce99) Z8(c8e28fd4,2a6a0f69,656c0043,a76e05a5,2bedd1ca,bfe45d71,0953224a,aa96b19b) Z8(202f3871,e7e85874,65526f61,30917e7e,05ec8e50,aaa16998,c62d838c,0ba7d782) Z8(efe8700a,3158ba53,b699418a,0c5b7381,6ba5bfec,edbe0e10,faf985ee,ec3f0d72) Z8(d28c908a,a2bff952,4e8f1373,1af929cc,c9d8510a,0945189b,e2a7a514,9d778cc1) Z8(bfbdb80f,732edac5,fca71999,e86ac4b6,64cf7d59,5984f97b,ae2e3895,eaedf354) Z8(29dad521,0dc97c46,b317c326,41dc0852,9be45d5f,dd83573e,3b104b55,37a0fc6d) Z8(55831bc1,0acfd370,db738bea,d18c20e0,f6b102d0,da47e16a,a079c8d8,2bb41fc0) Z8(4e840101,688292f5,54772134,821ca958,6c436a00,96b5ab73,9e9d116a,9598a615) Z8(70bc7239,c5792e88,801d8d31,eaa3ae10,23636603,b15e037d,bdf5363a,591ce745) Z8(720a040b,93b88f0f,7519c557,55088be2,cf38669e,8a2a9188,f8ed0d2c,fd16ea94) Z8(b0fed025,c671a2e8,975be84e,1f9f13c3,3fb4c1f6,95f0da7b,e3cb19a1,52669e67) Z8(388b2789,ad398128,d6097a8a,20b44b00,6a3d3744,0703f1e2,fc06815a,00a8ef45) Z8(26d07950,f902a73c,634c83f8,45fb9d35,d6d65e6c,cb284d2a,f101fcf6,6f8678f6) Z8(035de03c,2ee2ef8a,2ef6ada1,ad576c77,f5d57c4e,4286700a,1e783014,915298db) Z8(5350b4dd,56680c69,4117f412,9bfa3a21,370f1333,f7bd3e4a,3c7cfcfe,cf4e4776) Z8(3e88fa73,ead0a1d9,80cf17fa,46d33348,20537c5d,29eb43a1,86402160,97eb3280) Z8(65185173,e89d8e6d,097ba7be,caf9bf04,256e7be0,1ac6ce9d,57cbb50b,d20e906b) Z8(f34567da,996f8985,afc39694,5e178392,ea8c8e98,b42a24f7,d9207c3c,278c4203) Z8(bcc509b0,7979d7b9,98903df3,966fe843,be47686f,48885dde,34e2f50c,94e764dc) Z8(62799046,808f5ba7,f54cfab5,76cd573c,b00d72d1,8bc7693f,2215400a,60921620) Z8(804650ff,83d8ccde,c21e262e,3eb9f382,031deada,f29f8cb5,1266dabf,cd75779a) Z8(b025d6b8,ad6535b9,c7460dff,69495b3b,74721dcf,1cc75cdf,a0dee2b5,71a91bba) Z8(da3850f2,e5485810,420d40e3,426e8113,a5d8ecc6,f6128e97,3b151682,10e56d03) Z8(d125f315,7e494f47,42dae8de,cb569ac2,7af1fd1b,aa2f3802,7ba49a47,3d0ae619) Z8(578357c3,ddf6ce8a,476e586f,ee81aeb6,af4c7514,381e5eca,1faebc83,cafd2d5a) Z8(c9fb1ac7,2124e8e0,c1b93461,565a3f56,9b9da690,1652a3b2,0e334f34,ebd13bab) Z8(185c3b85,609ba7ea,1e2c03a9,efdf72dc,0a3a4e1f,221b47fc,ee93c90d,5dcb2828) Z8(8f263ae7,800f49b1,24b68f54,b561095f,689f36c2,b346dde2,65f23582,6c73d698) Z8(0bfdb869,9c41a7ad,e08dd903,7e3f225d,9bf1d7c3,c044844a,a13d30cf,a8896734) Z8(2019ffc0,ae041a80,274cb80b,a67022dc,d5b736ef,7ff16054,53220ebe,60f9e42f) Z8(b3d76a43,a52c0b75,1edb7d9d,b0ea7cb8,38efb3dc,4997787f,263bb8e3,4efe568f) Z8(816c95bf,c938ed77,8fd9941c,76ce6764,28d985eb,9a204a42,5c81b7c1,720634a3) Z8(7dc7d8ff,15e43ff3,9dfe33c4,bee88ad4,21bd89fc,732809f3,1fe9e44d,0fefbf47) Z8(5db17d5f,97aa8786,6378f78c,a8414a92,e00724ef,50f42edb,2eca3790,fdddc733) Z8(b0de9b32,4b5a5f99,157b9801,dd561043,824c9338,95db7fe2,b6921d48,5cf614b8) Z8(06ff74b8,148c0692,cf6717c3,1af65de3,345a6b37,fc930a17,bc457086,dc8f36ce) Z8(16b8c180,dcf82f52,975ac1ef,73d1da2f,c9565067,275e1cb0,2ba9ceaf,27b01824) Z8(41a23b21,071fbd9d,7386560f,5d5647fd,b66ad4a5,c97a49ac,f1250324,29381c69) Z8(2b2dfd47,619375dd,06536830,c8a61536,971bbda7,b7282831,f0cb06e4,025e4f5b) Z8(d765dcb3,69e659a1,8ca62afa,e8a469ca,cb740615,9bb5527a,cb9f4bab,b91f299d) Z8(02212fae,0bf4ee53,96ac9bfe,c6b5c455,d5525c4b,6e997d67,9f023fca,b36f8dd1) Z8(2a2c3cd9,de904a40,eb36f95a,aedeca8a,1b528309,442fa9b5,948c78c8,275bb57d) Z8(2bdd88e0,853eff7c,762ea3f6,ebccb9d4,5a685d2b,d17638d8,ffb3317c,09a67004) Z8(97423234,f0b73b71,0143c41e,2f87ce69,39447a09,c9241a67,aa9c469b,41ecc7c0) Z8(df22572e,5c55d7af,77676ea1,826feff0,2de4c405,3652c90c,f3e404c4,e20fe838) Z8(de57bf57,8a0396bd,7b9ba83f,b4296d9d,64f600e9,59373a5e,dd30beef,65abeb16) Z8(aa501e66,05dcb038,b63cf8a8,79524f5b,69e233c7,911fad67,53a9ceae,908757be) Z8(c585b9ed,bf59291d,caa42e6f,68545f1a,b2771a73,56bed22a,755520ac,3310e41d) Z8(fe5e6850,1440e5ca,bcdab7c7,a0f62f8d,94ee82a8,1339d722,00abe010,9601cd6f) Z8(730086a6,b8ae0ab8,da757ea9,49734009,45d9c9ab,a285ad7c,11a4ff34,718231e9) Z8(29d13f2f,cf2cd257,74364967,826e5292,3462b18e,2977121a,33a2a591,8f5373a7) Z8(f26e5613,5788ce23,d4f72505,fae12a2d,3c058f51,9d035b07,be52f8cf,b8d14d48) Z8(34d692f7,aaa28e03,e8d298ae,e277cc10,9b772c64,ea53d222,94ed8bf4,b5b1fe61) Z8(ac19f4fc,3fc07583,495b697c,c35e6f05,6cf181f1,8f3dba54,78d92c61,ddbe98b9) Z8(6a3444d1,95db871b,bc1f4bab,5df51063,598bd8f5,560d48d0,76f6ffa6,e7bd7096) Z8(915e6a39,39303bef,06ec2a20,6b4826ba,89a75de5,f5d8e318,be83d580,992dfa53) Z8(289ab106,cbc4d2d0,73ff649e,be1f10c1,8617a282,e6a36b30,cf383168,7321a97c) Z8(40951d9b,afd4bb1e,2f9dc889,5ebcfced,20c96f5e,8853bbbf,be858fd0,3de6d6ef) Z8(b7aff58c,a2ad6403,d85b0871,b268140d,e58b6088,ac9d7639,d9225531,d062a9a6) Z8(f38aa569,54dd8046,4f767fc8,f24f4f29,4feece8f,060fe2e3,2fc91629,dfdc345d) Z8(96934cc0,781942c1,e308bde2,29535179,00e54dd8,df52d8d5,73ee2e4a,63d4b8f9) Z8(d123a8a6,85a99cbb,4ac00738,9f4c7fd3,6c77c06c,1422b16e,5e72b0ef,929e9e40) Z8(a471e317,fb52e736,86848536,ca07fe82,f5436bfb,fdf95967,9330f095,0cdaaed6) Z8(78792c33,3085d1b1,a94ab1f7,c6916edd,d7d485d4,b4ceee9b,efe6998d,12ec0a89) Z8(e72a8add,82eb036e,5ed80a21,c0ccc7fe,4966ba33,8c6dbe84,7a522e09,0bc32ef7) Z8(1a021b03,a4e673d0,f674174f,f1598dc0,2c80c820,7404e150,cfdd067d,bac814ff) Z8(984c92a3,caa32b9b,80529b80,00e3b96b,c5ba0cba,00d513f0,0eb88f1a,c92e1dd9) Z8(6e4d25e7,83f2e73f,ac5e2eb2,db819899,9dfe024d,565675fe,f483b033,400ebc26) Z8(acb01b8f,6c56768e,3aa54c66,a8a9ed9d,552cb269,e5a69730,1eb31453,9a43ba11) Z8(278eae12,c4296240,c27656b2,3002b50b,d618cafc,3e729c99,3942c09c,71e7b875) Z8(4a5c58cb,f70f0a7a,e997c6f4,952280c7,d090df6e,b6924768,6f13cf2b,75e812dd) Z8(ccb92fca,f1e4302a,47410993,cd9374e0,7106c445,3cf17277,26c539fd,fee880e4) Z8(8b451eff,b6fe32a8,1b67de2a,67b9e75c,d6ef07a9,d0a98b63,14e3cbf0,b09cd522) Z8(01f69b1c,75ebe744,92e48271,03c36f5e,6975fcbb,b0b0df6a,15ab829c,b412b07a) Z8(04ba2f1b,09304920,7e3cc92f,eb623590,c9bc8958,50704d95,a907024d,0b9c287c) Z8(e23e9bde,d981b276,488063f7,f603e75e,c13ef384,3af0934e,e7bd7ce8,9bb75a4d) Z8(d82b01cb,251b92c6,cfd818b1,0f80a7c0,7b8800f2,bcd506bd,1e059a5c,5cbef7a8) Z8(ebaae95e,2fd3bef3,0c0dbfe1,5d77f30a,eff58423,9fdc1b2d,e82c038c,1abd1a79) Z8(abaa8d61,9cb9d3a3,2ce25d7e,d640ca8c,033090fa,b4faa517,9b9577ac,7e88afa8) Z8(12bcaaee,0ada618b,24d090f5,aa411417,936c1975,9323eabf,2fb65687,cbde8ba3) Z8(cd8884f0,e5265406,79ef126b,ce9bec6a,dc29a2a9,25be2754,d4592442,0f0b86fb) Z8(a6bb76af,7978789d,abf37628,eeb5c231,01acf5cd,80493e69,bb627cb8,2124c721) Z8(e323dc24,04fc20a1,ebb08520,12603f3d,ce1cdefa,222ff0b7,f0d7e4b6,a8b3d1d6) Z8(43e1231b,ea98a3a1,197d0f84,7f4da506,24464bdf,7dac1194,ca6cfbf3,d6fdc95a) Z8(42a2f452,456cf6cb,dc468415,96e58322,9c48dc89,77af2a47,daf6ef85,036ed785) Z8(ee92edbd,8db8b57a,45b44a0b,d3a86cea,903fa6a5,54aeec10,96da36c4,4be63dff) Z8(0a9f8fb6,f5d855f2,11e5f94d,39502958,ac6b15c3,a1eda073,77fa2227,27052c6e) Z8(e008e018,c8665508,722df837,ca05f6a7,8dd1130b,56215316,bc8a795c,f4fc679a) Z8(ee5831f8,3a2bc900,ebf054fb,c10240e1,2eaf30be,b8a0ff8f,39adc3dd,978ecc75) Z8(519c5359,e2696070,72220392,275176c3,e5c7a0ef,cbe13175,9175eacf,a0c966f3) Z8(72ccb96c,b3610a4f,a08d6754,386afe7b,7a60e637,7c958a0a,0fb4468d,c33e9fbc) Z8(054dc3e4,d09f8777,57231dcd,e93a0b21,ea691ef6,8742690f,223cd47b,e21a903c) Z8(959608dc,14efbaad,3b473af4,a15601dd,09731a86,39983c8d,b81bab08,ffdba646) Z8(7254b4f1,e038f804,37118e78,81f1e264,ed5b9785,2f7179f2,a2dd458f,650b99bb) Z8(0f3aeae8,ca94f051,430d11cc,b130fd1b,2901732f,e4f09ac1,d9e82e13,806f3e9e) Z8(84da59e6,902d930b,2b36a1e2,ea5f7b4f,f12562d9,468420fc,2bcab129,a524c405) Z8(ee337e77,a6b77c57,464ef9e1,6f8f207e,6be78925,6cdb5d40,38d28db3,bbcae60b) Z8(6de1599e,e42b3d87,1fb08a99,a4091b30,6ea5a74c,4dc785b2,23eb2c1e,a0707dc2) Z8(dec35338,d666b7b0,bae5cb5b,0b362fc9,26ebca65,22c7eedf,83669603,9fd97bea) Z8(61649f52,1f3080cb,1baf44e6,2f23f67f,0747c947,b0c8788b,877ebe0e,224dc993) Z8(5aa97e23,f202b38a,6814ac26,11d4f268,231c2c2f,52e857cf,5e461b22,5e8360cb) Z8(ee11f0c5,c1cbb950,793c972c,20217edb,f79927d1,f664d0ae,b0668b7b,d1e1ad20) Z8(e6edfac7,4fa94078,bfdedc3f,54758ab8,ee747068,1d0f9c2a,a17761f0,f33daea5) Z8(80a34140,35d84a19,2c1115b1,0961f5be,0573b94a,7435532e,4423d13b,58617603) Z8(87312b0d,54cfd8c4,29cfc2fd,104fa8c5,1c40e5a5,71af55d6,078c1dbe,222689e5) Z8(6c4343fa,47d2d80d,87e0bbd1,9d9232f3,a76df00b,91cfebf6,255c3d23,e565bfd8) Z8(59907fd1,0adb17e1,3833c93d,fcf7cd3a,1ecb9ae4,50f370c5,391c509a,632f5953) Z8(05b60a81,3f853ac0,09301a03,a932f088,99dd12c5,f6737641,262bb572,b97bb62a) Z8(eee23790,671e24fa,4aad5fee,0d92e59c,d11d8f5e,b4a7fbe6,35e308a6,47603b0a) Z8(0dcee4f6,37f98f9d,e31a6f58,c43d08de,d4d044b6,837a1123,0426506e,171261d3) Z8(562962d4,7e22814a,02ba169a,e812bf25,7c649cd2,8b6cabb6,7321750d,2073f4e2) Z8(acfce43a,4ab2a841,bc26ed5d,28f4aa1a,0cd3cfbc,4d4feef0,59ff55fa,f20c2a2a) Z8(56cff010,56aec095,cd26bf67,a5da2ad9,b67243e6,2fe62195,ec210060,84a32cff) Z8(07d6db47,747faa70,f00316c9,a2653d94,1c023d10,031f11d6,c5854b89,dc44a727) Z8(35750226,470044c5,e18d55af,0b6fa655,f01224cf,fc03f8d5,e36e201b,73d44dee) Z8(23ff126e,a60d3be6,2ae801d3,64b2ba82,7b8ae956,e4e576d3,e816b5b7,c4c70a8a) Z8(fef4b3b9,34f03333,f7775447,3ff81970,a95af69b,d3f7838b,880be4d6,37b6bf30) Z8(e4828b58,af2e6a38,09972377,1fbdde09,59529e15,292d2fee,9fbe23e3,ce684ee5) Z8(2426794f,03ba72c6,23964238,dbe6a006,185046bc,f8947ccd,db9db7e2,a423bf69) Z8(d045782c,4b055c37,4bf191a4,e5588559,1d0d0c93,5700c0a8,75b1b9bd,d1eb09f5) Z8(bbddb631,f1701f07,b83f7282,5e145f60,76c9b5fc,0aa98996,afc74d3a,150a4f2b) Z8(958bf3b2,9a6900e3,23124f57,06167ed8,72fcca8f,d9a96e5d,49930ad0,56d7b3c9) Z8(db01655e,e886479a,9253fb6f,701a4b96,07aabc28,f31bbbb3,509ece29,ed00435d) Z8(17d097b9,c880f133,a597392e,0d1f9b28,2b97c779,119e8468,ae78fe5e,78a3e76b) Z8(e9b02dec,530718f3,9b09af39,1af25a91,63743d3e,0da736bc,8a1c8229,f5f2ac92) Z8(f71fbb0d,7c84cd4d,7b770931,14fee532,66ae73c3,3875022a,2e23a5c6,a31b6209) Z8(2ba441f5,fd200a8a,b6ad7a81,69576e3e,e8d133a1,58436112,9423f791,5731da9a) Z8(39129f8b,15c2c5de,1c5038b7,3944ed86,6a6166da,f3edd6f3,904cf330,6048e67c) Z8(83d79386,95d8d529,cca3129f,fc9d655b,3962ef3c,25ba8362,a310b736,476f7bb4) Z8(acfd967c,f2469124,8517a664,d3955b8f,d9ba6196,75727dc4,e0b0c562,511427ad) Z8(6cea0d01,93e86f4a,60aedb58,e23b665a,8c251e95,57e73a30,86fb8978,ab5e44f2) Z8(f8c83742,b0300016,a20a7f2e,edaacfec,44ca4738,3edba997,c8fa2b4c,58de48c6) Z8(26b5c811,92770e98,d4e47091,8c585338,41a1de8b,89c21f63,5873ecb4,2cb87493) Z8(162a205e,8cfea891,e7726d01,945289ab,84a4ed61,9da1847c,5d47bec5,7ca9ed20) Z8(c3bd51c9,219847d9,1bc79d4c,9216e4ad,4bfb14af,9e147b28,a094da06,00c8e2bf) Z8(752d4d97,9f1587e5,bc1fe24a,ca2c8585,013d9e25,88545ca9,4361d713,e31c4bcf) Z8(e887c13c,6269e046,d9c4ccbc,6c3152ae,552b082e,25eb07d1,009bfd63,b0e296a4) Z8(fe25997b,3f27d1a7,4dbe7ff6,5cd3454f,86fe6a66,9d218353,9ed334ef,c8ffc273) Z8(6bae5b17,9000b3d4,b66b47d7,6e8d4bb7,cf08ca7d,04e55267,8f348f28,c97e0fde) Z8(90635f95,79d66031,56008fd8,920c0cf4,e2db0c59,7174b123,24a5201c,0e474423) Z8(031d3202,e174784e,2e817c67,866cc559,ea1a7be9,627f656b,ef9dfc08,8079d53f) Z8(33e2d150,bc4c1215,db416fe3,3edcfdb0,ef1798ac,27d544be,993c81f1,82ea78e3) Z8(bf27686f,e9e68682,104c24cb,5e954190,d78f8a43,351f26b2,0f31ab1a,90995e4e) Z8(abe5f40a,9159eba1,42adba8f,50ce79b2,9bc73a97,a2b559ef,30221d9e,b371c92f) Z8(7654aa32,769613e2,2e9e95e1,e4519420,d74f21ea,fcbc373e,34df73b5,cfc1759c) Z8(6ee5d844,cb7843c0,6d5905c9,5e422322,67e3d4a0,a1652ce6,07973078,85c9144b) Z8(4c5d0b1d,bfa544f0,59f3d60e,87c48698,10b01da4,585246ae,183af30a,7b2691e6) Z8(e161911b,8e9d4ec8,08f22c02,45d3312c,7e1baf6d,249fff26,e4823fa0,885a4c5c) Z8(19c16b8f,9f637cf0,276f720c,e0b9bd3e,0ad39e57,ffe9c0dd,1fec3185,f3854f87) Z8(e8788a0e,56f4c167,ff4f7d40,ab104951,08165517,fed6a1ed,e6143fda,16367289) Z8(0a3b6cb7,1fe80a98,09f22683,04759f52,c2a0e0dd,0c598626,f9e0e3a0,dc169639) Z8(6dd29b32,e45282eb,7c88d0c0,35949d51,7e50d832,c165a911,eca7f605,fe118dfe) Z8(cd03620a,093e1c24,730d232e,81a89672,70a2a15e,2fca8a81,9c8f7b00,09d5d113) Z8(c2a0875a,84f5fe25,b0411d37,5ee5b509,d55ce1b6,c4384c88,ad338e16,aff86144) Z8(e3696e4a,be64dfbd,0998f07d,6c96b6f0,f5ffd3e2,b255b5d8,a620f400,c0bc3330) Z8(a9d43ab1,4e7888a5,9838e725,c6525338,e0e96310,76115644,d73e7291,1406ee81) Z8(f4663370,f6bc702d,7e2f48d3,86e5f67c,22e459f8,0250f623,329ad737,b49bd120) Z8(e16c0aac,00c32017,45fdeb1e,7f25ad41,d4b1f52c,81e0c760,fe2077da,a60f95bc) Z8(0b2e13a9,c576d9e9,a5eed11d,f6f378e5,736a68e2,7414c638,2c6e64fb,25a11bf7) Z8(a185879f,6efaf126,1b077046,77a6a858,57a54301,916b6083,08be7474,8633b54c) Z8(c383d408,99f993d2,46d17523,78cbc8b6,f326c264,439f49f2,b4a20e9e,023c1de9) Z8(09b04cdf,92457948,0610e4e1,5b254b5d,c079faf4,e3cbf0a5,ae6459fc,b1337100) Z8(e475e5dd,a939c623,2ad78545,07281f4e,f43632dc,733f9492,ab9df290,601b4832) Z8(1db1148b,f7e89d58,0af175f7,e7d242ec,4bff0b49,926acdb4,d3056f77,028265c6) Z8(42f93b37,b01f24e0,807a566a,37cf9cc6,939709fc,7d48f09a,b77ad652,9ef3f673) Z8(5f867f97,a5a794e4,fa2ef4cd,85ae6fbf,32c889d2,f0a84319,16085f4e,3f9937f1) Z8(4967da23,707e20ee,dc43f46d,cffcbbc4,af06eea2,ba1eaff4,c48a823d,2f94e4f7) Z8(62cadaad,87905774,c24c666e,ded9ae25,199ad295,e1b00573,31e361f2,859e63a3) Z8(959018be,69cc030d,ee653966,7ce36425,dbdcdff4,d0b64c4f,62c08bb9,1761c664) Z8(9ebd8c0b,ac39c38e,bae48e2a,4131bc58,93d94c8e,7521a60f,562c90e4,cd902068) Z8(14577762,d25c060f,91cb65ff,0ab9b877,c21debf7,d4b9ca64,dacb4a98,36705d2a) Z8(04db5e84,e66d8056,99ff9bb8,612ca330,11ede701,48a34967,490d26be,02555d6b) Z8(f033e201,ee7b4fff,d85bfe2e,cb118b03,19a38dc2,39dbfd91,bf96ec31,70457baa) Z8(d20d6b50,c922064a,631a8349,9b527157,8fc1c11f,4ba875a9,37908938,a5519ecc) Z8(032f043b,e5193221,5cdce7ef,c5e84d84,30791612,560a0112,cf98445b,a8023399) Z8(5fcc8b90,86b45f3c,b70702db,76c36225,027bb532,70424a5c,dab34c9c,ebf591d8) Z8(dcba30db,398c03c6,491f5f7b,c903e40f,ae981c12,7f88858c,2e50482d,984d08f6) Z8(bfd97c74,9913930a,ba2d1937,ce78fe44,06de30f6,225c9f09,0ce13157,21056b5e) Z8(0780aaf5,ab2adbe1,6e0cbacc,0c45a68a,7f752ece,e78efabb,335f1318,93598a5f) Z8(44845118,bb2c9bdb,e2c381db,6ebdf5bf,70c51c45,6695ec8b,66fd5428,a2e40181) Z8(fb349a21,bdcf353a,0845b51d,d42812f0,3ae1faf8,b2a0cabe,bee2723e,bf5d2bf0) Z8(0f09dd0e,c453c244,8d6c2f45,8f1bc235,dfb54671,d27e6707,a86a825c,245d64e2) Z8(9b5979c2,50f1d507,2f03b1a6,526badf7,81a08cc1,af95ab12,f0d50165,202a0c59) Z8(276a764f,232252f9,b2128b50,0d8dfc71,b97f920b,87283535,303bbf29,71a68de0) Z8(bdaa67d1,851454c1,0cb9948e,3a29f486,b87c9ca9,5c774fbe,6d5e65fd,c0e6d51c) Z8(82eefbc0,1346ff43,345f2b56,f820d44b,603fc15f,e4115009,fe6f90a0,964d6462) Z8(dd55cfec,c53df51b,6cd95824,1f707fff,dae750fe,7b691af6,730a6d64,c75cf0dc) Z8(455f0654,d9dd0245,90cae083,d8232e1a,8ecee101,73cab9a5,6f817f0f,55714b8e) Z8(c4731f5e,88332f8e,deb4a7ed,b21ddfe3,168ba3af,48568dc5,1fae0dd0,5e924609) Z8(9f8b4ef8,dedd77f9,fe4e0b48,b0e52504,4589727a,406e9c55,d46d964c,d6a6412e) Z8(029fb0b8,277ed871,6c4f76db,50904192,72215145,3cab3d70,5047d632,17b16be3) Z8(44d4bdbb,1b20cbac,4270b138,a6cc9803,7ca7ce75,b0b78ed5,563a695e,d44b9ee5) Z8(b771f0fa,7dd55d18,0003fcd7,4c243440,4116e216,5d055f7d,6f98726c,a9f0e582) Z8(d832021d,efc02465,9d85e121,0b995c90,d5fefeea,e19127cd,77b40c94,76f13acb) Z8(9a8c6ff6,8a6d4596,ced0ddef,0def8809,9ede288c,b4a5818c,3749e187,b9c03c02) Z8(7879c15b,6cdde013,5ee56208,5fc0ad11,1fed6329,f38703fd,98aeee88,f3386cab) Z8(2f86b562,6f7287ca,090c9933,f3df85f6,ee27d8e7,e44f7055,83921bfd,111fa4c1) Z8(a1283c2a,292b760e,d357064a,be7632d0,3be4f4ee,17cbfc49,ea4ebace,93a032d6) Z8(ede41b2d,56c05811,8f025936,f77aa1c9,5e50c26f,c7d9269f,0e62d47e,d1c2733f) Z8(c00ff2ed,1df127aa,4e48f6af,bcaf1138,f09d33d7,8e8e4926,76a8088c,006d76a9) Z8(0945cff6,b665ea1f,76194796,837f5d54,6a2ce379,1a6ba6f0,f1078af7,b4528089) Z8(29d7a089,5b8682d6,0dd776cd,bc017e6e,668c1211,04a5e750,f5e94b5f,aa555c5f) Z8(8a5202a8,8e7d1264,ab46a41d,5f06ce0e,8b14f7a0,03a81df4,a5c701e3,d385ed33) Z8(8b16a2e5,687ae1a0,bf233c95,6f23be51,8204a564,0fec210c,3c5c3dcd,e71be4e6) Z8(e85edc26,560e48e4,4fa28d73,d2718926,d5cd4c73,000aa48d,18dead09,9e21f621) Z8(c1f3b573,cfc43229,e58befef,76131e32,33b3032c,ee5aec13,b72012e5,70b92b4e) Z8(e000ca7b,5a2819a9,9f4f5fdb,042e3987,f829707a,df92d22c,33653234,9697ec75) Z8(680ef8cb,c501f18b,e8f02c96,0e0216ef,521f3908,f9db80cf,be63b27a,7e61f76e) Z8(1a43b91d,ff0ec8c4,9ab595fb,f0f17963,bf7e5000,a6249d6a,1c1cdccf,110a2bc7) Z8(55034fc0,7cdc6e13,576f2cf2,87430593,552d4939,2289c242,12c806b4,e2dcade3) Z8(2ed7eaaa,1cdaec4e,4b31813f,9ad590b9,382f2b5d,e6e284e5,d8f0f937,9a675671) Z8(c1911583,f145b052,bb1bfd61,1b4d6be3,38d9ef09,c91f9540,230c1dc3,a4b3a09a) Z8(2aacb9e4,0b56e35f,e6fff065,aac15edd,9f72c762,79dd2d63,4a00ebcc,ff5a9ba6) Z8(935f6add,c4c88194,5b4c62ad,8fdd25cb,3d5b7ccc,891cf5e1,659cd5e1,b5ed08cf) Z8(d06abe26,8128c411,a349e897,f9bda387,cfcf6f26,cc4ee9c9,ea94d464,1f01561e) Z8(4a0daaf3,00adf1ab,dc63d648,bfbbb9ef,7b43de85,f4d470fe,03dfb11f,d7d47294) Z8(160d81d6,2d237453,34e79648,97e30ba7,04f49fe9,8b0de8b1,b9d22c91,e50c9d1c) Z8(34fdb35b,5b34f837,1bb60051,67b04b88,16fe251b,0b26fd70,34efe2e4,f1ba9327) Z8(76535724,4ea04b1e,93c90efb,b99896f0,224d0376,bd7a493c,872b8445,bd8f6445) Z8(b38458a8,4e51f561,8887fb00,14474910,6c3dcf72,8d5cf1b4,b2ccc5a7,39915a38) Z8(67ec4e3b,56d23545,f8534525,bab8e493,e661ac9c,1f7fb979,eea01689,34e15d5f) Z8(065f9b44,7f18d767,9c16c362,4b18c328,709e077a,9e78a37b,90a3c285,52f53c6c) Z8(c8f8ec92,f36ddb5b,02ffcbb7,97747ffd,2055801a,fa0cde52,c9fb8a36,79bfc8ba) Z8(1a8692aa,5d994f56,c0dc5c0f,e60a3314,25e4842e,4019e737,dd7478e4,4c1e6c7f) Z8(e10ea6ed,aa9f2e1f,1ac31219,2f8b6c46,9c4d03fa,6180d09d,caef2ad8,67e66dfe) Z8(0e6ed9b9,92dc9603,e99911fe,06be5479,a024ecdc,a1b7b03e,72334516,1d8c775d) Z8(cd6bc9d6,516509dc,79a6a98b,d644b3ff,145b85e3,7e754a13,24037ec8,6e8fceec) Z8(3bf1b9e5,d44192c5,98f15ca4,620339f1,8fba0352,6e7623da,29194141,e124ba4d) Z8(59849e44,28cc7de3,10a5c496,59f1ca03,ca495b24,8461b5c8,f0915073,a6df2721) Z8(06610145,48bcef57,35621eb4,87830fc8,05da0d8b,73ba1458,76759cb4,ac0a8c9a) Z8(9c2c4eda,fec1c59e,b4427e12,b4c2e891,e545d76b,f173caec,c1c698b2,2215b5a7) Z8(96b5b649,0baf051b,bc59142f,c507be6d,b518ae12,5a295490,3270b92e,484e8932) Z8(4c47a480,bff80038,d652c3ea,7d2582e1,35ac3860,5d8680a0,98374510,87d95a82) Z8(bf3ffbbb,6de0bce3,6e1873e4,6b9275f6,7a3a6ceb,3850ab70,4c004c18,ffb2d99a) Z8(14a1cf78,01de6525,b3878380,05892047,bd842e6f,904abfd9,a1167160,d30607ab) Z8(996be2e4,517b0b93,582dc037,3ef93c4e,f1c8133f,4ef58187,073cf460,76194694) Z8(55d0ab03,f4af9b2c,6bbc3a97,61390083,8f10b0b5,cb9f968b,00d9ad26,50b41df0) Z8(74153e41,a7daf1c4,559ff1ab,aa2dee0a,266a9f32,8f474f0b,b7217238,b51920ef) Z8(38cea67a,97fa77e3,ab3e0214,d61ebc1f,154cc1f3,dec2aa66,4885cdcf,59b30967) Z8(c3b0a84f,9ca2d9be,08bf15d6,2c777f14,b19847ad,e2c90c06,c6cc44e5,22e1be80) Z8(e3b3264d,10d1c106,fe6393aa,175b0b9d,daf82315,722db653,09f0bdc3,4302bb24) Z8(b9f08fac,c270e77e,38b66870,17d902e5,7d0f9e7b,ef44894b,28844376,e03dc424) Z8(f6b4cf6f,9f96f8eb,78a5e6c3,dc99cf0f,77948144,f90d2346,0e7d2504,fef25603) Z8(0c6e4fac,28947b48,6fa68497,08063f6c,4d582b45,518c8d1f,87dd8bae,ce83ca6e) Z8(3ded8062,7690e0d3,110d3333,d424cccb,a0691c9f,8491b74b,dbbf961b,bf8ca597) Z8(b528c4e5,87831a89,25c506f4,e03b31c8,deb32601,c267d481,cdd0e613,a3577811) Z8(6e1aa6ce,2b20dcd8,95b4622c,58f8937a,2ad0e689,2a2ef558,315a24c9,797777b7) Z8(5b8f2a5a,1b7c0a29,66bb1810,abe98aae,81958558,5ecf8530,fcb391cc,a0ee86c1) Z8(4681c431,4c4be55e,53faaefb,20ecfc21,a97b03d8,46781eae,93d3a877,2ac45527) Z8(8b83e1fa,d5f74f40,4afba6b4,038a9ed4,bd187ae7,eeea49cb,dc6326e9,b9d8a0eb) Z8(211ae76a,ffb00a55,4f6f4588,8a861c50,b41a7a11,10367d40,a668f918,73fcdfef) Z8(c22ef1db,a961a13c,5a77fb4d,c3c2602c,78aec24f,85728f35,90ae43a6,544a3875) Z8(f0b2d6b7,9920cd10,62d4821e,95763947,33449cae,e5eecf9c,420606c3,1719a471) Z8(e55be920,818b2cc0,9e9a55d6,26b1cb43,396daf48,61379a62,5e401b64,d65d988d) Z8(6f40cee2,a6b5b07f,25c20877,c1145c7a,54380361,634bd886,c4e7ed7f,885517fa) Z8(85e630d5,e4c78afd,d8735255,1b66600f,0e9a4760,c22ae6ea,fa0e9fea,c79c9e84) Z8(7ce167fd,b636c927,d59a9917,56aa061f,b8724096,05892927,b9a769f6,bbf1344d) Z8(cd881354,22041a46,72542533,71a1d60c,8ac117b4,a39d9dd5,28d2ce91,15432387) Z8(48e2a3c5,9203d9a9,6e7f69ab,34db510a,2cd704d8,607733de,29154aa7,f384c842) Z8(ae9ec3d3,a865d115,8b83f017,a0f6be73,4c7598e6,95e39376,ee43d440,7c748bc3) Z8(d96795a4,9294db13,6364afc4,067705f7,b9efc03a,3d2cb687,5abc687e,ed8183f7) Z8(bd2140b4,e7f0e937,f23b4ce7,6432ee53,1f3827c3,161bd5a6,f4a78c87,68e4461b) Z8(1176185a,18a69dfb,32a89105,deaf117b,33746e9d,96d3196c,3816bb85,3d1b228e) Z8(3f59f82a,593f4ba8,4f86b14e,acd08499,7c364293,7c3f8956,6cbfa457,7ff3e620) Z8(28b686d1,a1c0e367,62b67af9,fed3295e,7e2e7391,7100403f,f553150a,bd9864e9) Z8(e3ac48b7,62e7da84,64e0c290,3dd8fa17,183dafbc,1413d3b8,4f5540c1,9fb7cfb2) Z8(00ab5d7b,da5d1341,6999e284,802c1083,0431f795,be287953,1c1f19e9,8e01b147) Z8(b1d262d1,a4e5da07,09e7f615,c21e90a9,8b30b320,595fc4c4,30ed74d9,6efb4050) Z8(1c9dd97f,970efd5e,d406ee38,b67112f3,35b7bc32,d215c40d,82d96baa,96ae1526) Z8(f2eed99a,f40e0024,672311b4,e9a0daa3,9b3c4d61,968ea93b,0174c330,fbb562cd) Z8(b1148b65,254d755c,27d5507b,27ed24a3,043545f9,17435b25,cc2773ec,ae1aa7de) Z8(76f4b4a4,419c67c9,d806f787,88691d37,90b1a165,07288378,64df2765,a19c7c82) Z8(ceff8802,dbf2b465,0b9f3d9c,14c7ec37,91410931,af5fabc5,c957e169,3af3e809) Z8(066241aa,fe847877,7d54dec3,34939e6c,6cd589ec,e8795af0,91f57914,41b01ac5) Z8(856b32c0,21f9b82a,179910ad,2470d945,bfde968c,0e465c1e,bdbd386b,32b3547b) Z8(e0ef5170,2047db49,1d9810ce,0b9c87ad,c2d5869a,906b4cfe,f4f71be7,25d7fbbc) Z8(0b540d0e,b0bb7715,cbf1ee35,8a63e752,30059855,4691d3f5,89973e96,c58dec41) Z8(da2e37b0,a6da947c,86b17659,9a13d0b8,760674ae,d1e3cdfd,97f604dd,5cd8257b) Z8(d396c0b9,a7abb4fc,3b4418e2,9784d5bb,6404fd30,58cbfddc,8c5522e0,58ac744c) Z8(0a38ae5d,06c1e882,3b2529b6,a6d2f12c,cbb990d8,e316ff97,78412080,27207a18) Z8(3ccc7dfe,d2c444b6,a9f6b0fe,be631180,7ef54272,dda820c6,a4222017,813abfad) Z8(1dbe2a60,2de557d4,2f170cd4,383e2330,ce6cb17e,aa74ddf1,08683125,dc2e90b2) Z8(b2093588,8db83717,7c2bb947,71ce5047,fc2f4108,c902ff2c,426fffb0,c0c72099) Z8(c2dba36e,e038791d,27c77d25,eb3b00f0,83d64d20,b205f6bc,bf4b1d62,3b51a9bd) Z8(1ef0d2dd,5e4d6c83,5f583cac,9bf5c702,e599349b,cb8cf949,fdf5cb9f,8aa51438) Z8(ff91b34f,1eeaaa09,7fe4216a,95871991,e7fd29a0,19ee6fe2,73cc7ae4,bc1567cf) Z8(7a2f8479,bab31bc4,56833ef2,ed8c18db,538a8025,5c2389ef,a2f878ea,58e44038) Z8(6d6b393b,b9530eb9,d094b384,c7129d69,7afd85cd,b7fb4e17,69ef68c8,2014fc9e) Z8(5c4c3747,3f4297c1,b5b55c63,074b5a3c,b4ab95fa,da06cb5a,2e4f7a15,605cb03f) Z8(37151d49,d26dffda,1869bee9,d7adc727,1133d57a,23e155b8,7b5b370a,8fafd081) Z8(d7f6161c,f336e231,d1da82aa,f2a435a9,7e8fe030,b2cddd01,f98fdb64,567c6874) Z8(03b76a46,a48b42ae,d469e90e,c6cddcf2,c94222b0,319fc670,a6bb804d,84bf96f4) Z8(335cb072,1f175952,75924165,8f743bd7,13e55433,e9fb97f8,a01b810c,fc4241f7) Z8(8c76603a,77249f43,d55e4b88,5de9d76d,9c9bb98a,0a46ebf2,57eddfdd,2c4bd824) Z8(f463f117,88d1a024,0554a960,8968fab0,fe607124,485583ac,f9f60e64,a296b2bd) Z8(372fd0ea,1326e92f,056d01b8,6cb8aced,ad2af42c,964eeb27,7cde9156,dfc786bc) Z8(96a06692,11786973,252f4312,5533046f,3578d48e,a7c13720,49df291c,31ea7acb) Z8(8a49e666,9ab1f191,4fda32d5,c5400be1,e09a22b6,00ca356a,957c8a15,bf92f6d8) Z8(b2cbf7d9,fbd173f6,d74a7486,94869d04,1e84877d,59ea3bd9,3a8b2ad7,ddb3804f) Z8(bd9c2b69,234fe71a,645ade00,5e45a8fd,26c9fac8,18c1794a,a99bbfc3,9376b166) Z8(eb63b6c2,5ffb2c1b,cc24aa73,d1d81194,dcd4b26e,c26d23cb,f03c8bb8,59d04018) Z8(4805c144,df545e0b,042cdc40,73a249a6,330b517b,918ee488,9cb9fea1,e3735701) Z8(8ebf87a7,f57adeb4,04d718f7,c5a638ad,e8b54a8d,d21d35fe,4162e92f,004cc7f3) Z8(28935de7,d2e8a79d,b79bdca9,36b63082,fe650e08,c3d395a8,55e7ab4f,95b5b57e) Z8(c94f4639,86dd290f,853feb7d,9e6540b9,b5010d28,f3ffd35e,d5fc9b4e,5b310927) Z8(c2251793,8a5216d7,369807d2,426b3191,630f3257,a55369ed,36a6cc03,3ae2b401) Z8(2b193a93,b43e591c,27ce08c7,0d425e24,6b0e2f9e,720df0b0,cdfd7884,d14d88b0) Z8(6c860d1b,41961ffc,b2c12bb5,c049432f,d499e987,e61ea278,82b71866,34446b41) Z8(aef85fa9,a027f8e2,775c8d1c,a8a390ac,e20e81b5,3facca70,5173a83b,e3148b51) Z8(079519f0,8a2f0d7b,c1c2dc18,70dc5f79,f81bfbaa,3b6e619b,73060d21,8b41faab) Z8(ccc989e0,663eebc2,bbf39a54,3bb289c9,8cbfb470,6066092e,415dc5ad,015402e3) Z8(881d1844,3edb1999,9ece38df,dc16eed7,1e024ee0,518151b4,0d3bfb7c,7e005f36) Z8(be2dab47,86efc81d,c6570f6c,d3578319,34eea96a,10931714,d6e39ed0,bbd7bbae) Z8(6052a89f,83e056b5,7dbe41bf,6dad5d38,d56c2d97,f56f57be,e33ce7bc,864b3e68) Z8(0719b540,d36b719f,0e2296f7,e9893ce8,de1d0662,64a7d918,dbd96297,b69a7c3c) Z8(29bf4b2a,a124ba97,9ca86656,739a9532,affa92d3,9db52517,5a791432,9b55f4e2) Z8(4ff6d051,e48ac777,88211b72,050af89a,3e40759c,5646e536,35227403,241990f2) Z8(8af08023,48456078,b0fa317a,179ec78f,6d695618,e494e334,ac93691e,9f2fcb45) Z8(b72ffe39,66c1cf0e,2edf7292,7ca71356,c9af32a1,b2cdfa9f,0d9f4299,0041ce7e) Z8(7b7c9e7d,ddc24efb,bb1b4623,65964d7a,bf093dd6,45ac6efe,92f33c20,d17ed003) Z8(635565b9,c8916308,7e22281e,ee5a274d,3666afb8,dd7ea11c,ce001b3a,6e20ba70) Z8(35778a9a,a79ef85b,ae6a829d,5a07dbe9,279286c3,55100386,c14fd637,f6926b4f) Z8(e0a8c0c5,dcb79263,41c8516d,d55fd5d5,7d58cc50,4721e5dd,3bff7fda,adc7279c) Z8(e0dc5dd9,dd11b946,62025438,0c646763,b793a99a,10d26442,0f761663,77482fd0) Z8(c4e18443,0f6279a7,77a55929,75d3de28,7ca0cf84,31eea43e,6b816bf5,2bb2a923) Z8(6f68fc45,523b14b1,65dc8782,b028daa2,52118787,a93964c9,48c45c39,fdf3a498) Z8(56b69e33,2674de3a,dd6cb4e9,a6166489,5c7e1523,bd306209,db0d9b89,6cdbd5c5) Z8(4e470eef,f631be45,f33519b3,64b622e7,3ec8e703,819072df,d59c7fe6,f55a959b) Z8(45c816a6,a07e8535,a7586999,56c37346,649a0bcf,fb09256d,83e4a95f,a2fe5d1a) Z8(3d7fa055,6bf63e2b,d6ba9546,146f0a56,575edc1b,5bfa306c,31368143,24a52bf4) Z8(f9215cf5,d3088453,ee792582,5bbf1d5b,80de406c,ca0d04a4,7da3edc7,07326636) Z8(db7030ac,f67d8ab0,0e99850e,0b581d00,bfd1023c,575d622e,ba179c08,9ee85149) Z8(4c6e1da2,e1896ad4,a76e2045,68c867a8,2bdee0b4,9a829a29,20c8aa55,0735c756) Z8(49c0d166,e5a18f39,b03321d8,8bc8c613,67e5ab85,c390f217,bf07a8d8,cf36aa5e) Z8(07f8c19f,6b39680b,61651e69,b1ed73cb,4fa8e837,a96f7875,3f469c75,efd3eac3) Z8(4c4cc0f0,b3e779de,5f4e7c13,959061e9,cc8593c4,a4c2696a,a30c657d,831679cc) Z8(a4d69dfe,7196c636,92812689,57917769,92c8112d,a21ddd8e,28a63a77,c47a6edc) Z8(1f90c7c5,0f88ebe1,e0ec86c1,abd312d2,1f0a3497,05a97686,f4f5938c,bf86c52d) Z8(ac882f09,dc5e1e2b,e3c2be1f,f642a458,a32a8614,2a0659e3,a5d201bf,df1e03f1) Z8(2d025790,56ba61a2,1b6a0e73,129f2100,b3771471,4d88ea03,5b02a5bd,0b71f0e0) Z8(6491312b,8a983a00,b76b1116,72da0cd7,9ec9fdd0,364eac08,df80068f,864bc793) Z8(3ae7d0ff,d7209b06,59f666dd,02aaf5ca,6cd21841,6e9d09a7,95317baa,89f3a6a9) Z8(a65efc6c,02678ad1,4f0b77b4,a5849458,0b08247f,764e4864,7a5990b0,4ed3ef88) Z8(b03f5b51,dd2bfcaa,5676a03c,125cbf15,41e84291,f5f85a37,756bfe82,978baf66) Z8(aae9048f,47abe149,1c5e06ac,85b6c0b5,f99cbb95,9a4e2bb8,9869bc88,c061475b) Z8(04602120,08e3a9cb,b340406a,f480395b,a12b481a,de0fe3f5,e417bfcd,40907dcf) Z8(4630c9b0,f89a116c,b09518e0,d5cb84f6,bc44c8b7,9abc761d,c43df93b,dc0736b4) Z8(e6b808da,16ffbd27,57c81144,ec59dffd,d0c0fbdd,51f9d24e,2d37748f,07e7d943) Z8(8653cbba,e1625f47,0745eb80,43075525,4ad5ed82,45147ac1,24425fa9,dc1da2a0) Z8(dd3a3ab0,c91df13c,234a99c8,cf216008,c63db788,d6eeb599,479c3c31,dc6cbe5b) Z8(73f3f7bc,406d5b6d,b32c5b97,991bb7b5,af04635a,c5c4d259,7a8f92a1,f0bf38e9) Z8(80d84b69,6273fad9,a621777c,05aea84c,7d2021b7,c18ffd86,367e657d,661c9a5f) Z8(2f8628c2,34455321,4fd128b9,8b3c1e72,e7afc246,19725c5b,3d8daf05,389a3653) Z8(6dc72801,469f47c4,b1194b4f,52b61fbc,2e186ae6,64d69279,af1a4915,12063b37) Z8(1315515b,f4e35fa7,9911c966,e0b4b0f9,51328da9,895a72b4,3cdbf085,bc0d5211) Z8(cde8fb76,8490e5ec,2d54e4bc,4e80a33e,7f77939c,e1fff33a,617ff84b,af3a3db6) Z8(141fa8fd,634b0391,92ac5663,f90170e1,e00019ae,dfba5fb1,54beed7a,94f416bc) Z8(9acbb1f8,0fab5c6e,e2f189e4,408bfd42,a9514a78,60edf001,739f2d6f,b7688b7e) Z8(25924489,19b9cd53,25187b9a,1b401ba9,f0beafa6,951d4331,59b1acda,0ecbc1b5) Z8(f5df288e,cdac0254,3783f2dc,76f90a07,452a8022,fc165c96,84879d2b,2526b782) Z8(193ec27e,92e19be8,beb2397a,d8999700,2702e919,de4e11d2,b7e99b37,06add8c9) Z8(9e1b8d29,e9824441,7874f244,f4b00a40,aabfdca4,acaf85ea,0d4cc54f,ebe6b8c8) Z8(fe85f485,06bb8a99,234fc00c,dfe549ea,9d20d237,ba5fa9eb,669c4277,99de8b91) Z8(058f6841,397322c0,64c81277,6605a3eb,32a11f8f,db51a05a,adcccc02,eceba96d) Z8(161d6821,7656a0ad,f6b75aa2,31ac2233,c6844e50,c75fda8e,ac84c0b0,63733e16) Z8(ef45ec9e,5cb61b19,a374b3eb,f640e5d2,9c30d95e,81716271,669764f0,5651fa55) Z8(24036f0d,6abafdb3,135b0e9f,0bd30128,665fc593,2ff57351,7299a793,e9f7b9c9) Z8(fc560ee4,6fae75d6,30981539,04147b4a,bd6b63a7,08d5489b,294b324d,c2e855ee) Z8(ee6ea129,ed8142a8,510e597c,9e32e6bd,f70c2e5d,c1bebe67,201d6abf,c5566460) Z8(36fc044a,cd7f7719,bce64d18,aa2e23b0,749adef9,aaecb789,ab5e7f2f,f843bfaa) Z8(60a0f32c,6bdf355d,1f4d65ac,6452913d,dcb03035,64be1d89,f3f81f60,54e1aff3) Z8(1aedadca,ef73cb65,4f8189a4,16a50bc4,7cd24ad1,1818e5aa,9de66898,1b326765) Z8(844e3232,cfe01ebb,8857ed9e,5b6eaa41,ead2caec,af14cbee,ed4c92c6,28d0f7c7) Z8(e5f37fcc,0a962a22,64693ae4,303ecceb,180aee96,d9a80960,a9017ec7,f664cbb8) Z8(aac9523e,a980aebe,e97724de,2c8ab22f,edddf3b3,9ab644de,87f4ace1,b81ef47d) Z8(d7df19c7,3d295919,e750fcb3,089c9f39,02da03d7,9a0f3567,49c21518,7dae2c97) Z8(b8510eec,8513f128,aa892f1a,b648e6f5,6b571617,65bd30dd,2086a5ac,4d1e7b6e) Z8(d5c6db93,92a85ffc,1385ca97,017e074e,7eb6e047,6907ec0c,0a3e663e,98100846) Z8(0fb97e22,502c1ad4,9144fa5e,49974b0e,dc226ee7,c2e83fa6,f49ffd2f,d847e14c) Z8(3744e06a,e1a37d18,add417e5,10890336,685e6626,d972eef1,e1822bad,8117dabb) Z8(6f39b9f0,6927af3c,b730d786,acae12aa,5c8c1f55,15996216,925a4791,16a497aa) Z8(bf72a56c,e3bd2524,10b5ea77,57eefd90,ac4c0ee6,45bc50c2,2be61a30,bdeee682) Z8(faa15561,63963d9a,81ba98f4,a48f3c81,943f9527,c8381cec,351d4d20,cee1996f) Z8(09548d01,a15ebd73,570255fe,dc624df8,18b2d60c,8583c567,1935335e,e2778056) Z8(5493cb8d,73ba4c3e,8dc11bbc,a5d109e1,64fc5978,bae42292,dbf944bb,d5eb595b) Z8(b31e05e4,67be010c,df2a299b,d6092164,eadc678d,3e6cb07b,e7af81cb,f00f9feb) Z8(dd0c4874,e300c536,45f9ef18,be35271e,3d137bf1,711fd392,cc9795c8,36efd196) Z8(55f62826,48699bf2,7da4fe33,10b3bcb2,88393d58,c24bbd03,c4521fb3,55560ebe) Z8(7318c070,97b5344f,9d548d41,eaee5346,19b4a1c5,b2d28b83,f7f3d109,1b870034) Z8(58fee59f,08b4e034,aeeb8204,918f5f1f,a7362fe5,da8afc86,e9fe9b96,cc31375b) Z8(407c042b,af47ab2d,8c4914fc,f1f438e9,7dcb11cf,a75f2558,ea3d4d9b,365a1123) Z8(ec7b772a,82a096c5,8a304665,f7311357,c6152618,0ff764bc,35b3b662,8ff11b74) Z8(0b903466,dc733022,70ce2fa7,25304d64,8c3bb629,4989a980,85ac35bd,345fbc62) Z8(219e46e5,63f9b00d,9ec03089,c911afe8,6f57c4ff,9f766b5d,794bf554,835b7e22) Z8(9cd0fb0e,b2ba2766,7ae30b91,3e216a48,3766a453,11557ed7,ce935969,b305031c) Z8(c79aae79,ec3f7589,2a762541,c17bcf1c,5aa2fa46,a7e01c2f,ae5d4c46,c46258d5) Z8(90847ea1,a3340143,65fe1f10,03a28358,010293eb,426d39f7,be4d6bf2,777f8e72) Z8(83089938,58236984,5a48508b,7dff077e,e7b3e0f3,cb072b3d,df127681,cde8cf48) Z8(2921d02b,224b1b33,388f4127,a6ee06fb,c1d8d051,5fe3cb84,52e3909a,3f8d69d5) Z8(64bbdfb6,73588015,47c46b2e,92a4790f,efa23215,c836e2dd,743c6f1c,4edefd78) Z8(63e516e9,978b5d66,9cd714c4,7e69a349,7694a8cd,d2165d79,c08385f9,378006c7) Z8(9314d667,4d3bc55b,659866c7,a6564e06,e641b6bf,2d6452cc,60ad4bb2,a5d1fb02) Z8(21e63146,836f8500,8e4ec160,a129bfa3,15d12e38,e4bab3e4,2807da8f,b747c1d2) Z8(b10977ee,f445d4da,07d0a9ce,7a0e4054,c01fe63d,3f17e752,67222a71,b1f22ce1) Z8(3783ebb6,ea29f33a,6a5c3f7b,ae6eef50,23c8dfcf,6eb7d446,5b86cf4b,9665e367) Z8(851c26fc,97de8586,a6dbf047,3fd3ee19,2da5b29f,2b1c9021,4fa06252,72d4385f) Z8(c3833763,6ec3e2e1,82c6442e,6856e222,b155fd88,1ee65d10,f24d28b7,5b0a9a74) Z8(20752c27,ac1d351c,669063a1,f4e11304,cb2c91ae,4d868da4,ca2d9940,76bf5e52) Z8(f2015df6,508e33c5,b208080b,820eb267,6f4798b8,a6c225c0,fbe59c25,b40fe2cb) Z8(3f4feffd,8606dcb1,b2adce1b,9f5c29b4,66f8d3e1,ae4d2f82,128e2381,5f82d83b) Z8(b17f432a,4b6cd913,08e10f54,cdff0fc1,ecabf8ad,c152597a,9c0dcc92,91451f52) Z8(7c7d6332,0b41c1ce,48f79f31,0c7f7ba3,9ccffb78,74e20b0e,bfb75a5a,7a6e4c2b) Z8(019634f5,59d19110,08f75794,8b6f497e,9bff242f,97630c2c,cc5171d4,c2c60d16) Z8(2d38fb43,89146eec,6fc36bd1,a788e2ef,776f5141,193ebce2,a2f4c4d9,0c9b3ae4) Z8(358edd9f,adc8b9fd,8c6484ca,ffbac4cf,b52b8282,e2c0a97e,835717cc,d8235068) Z8(fc5b4495,a687d2d6,2c36e856,3826824f,f26a263e,aaff03da,b64fa038,a10d486d) Z8(7a723110,c4585a90,1803be2b,d55d70c2,dd603f4f,c82fae01,05da6977,3314af3b) Z8(55dd534c,41e9db8a,564f7902,6fc6831a,4b332f08,bf771542,01d00b92,e4cd0224) Z8(78b5bd12,ca731fd8,35fc335f,4f715f8f,dbed0580,4c07fbf0,acf4e5e8,3b563438) Z8(f5b5f85b,5e4d1dc0,5498ff9d,8d2eee1d,4ca484c7,f7feb2dd,61f1e2fa,71b39c0d) Z8(1614c069,b0e19649,2031ce0c,89cf97f3,5141c2bb,85f7e594,fd95bbb0,0cc4b06d) Z8(d3aba1a7,61a9d102,f339109f,e556b012,f69487cd,3d8c13c8,677550fc,eb06723f) Z8(d9382254,debcdb33,f6b4480c,cc357526,2c0dd60c,f627b884,2438841c,c74e4ae2) Z8(253c2658,f72b4f71,28f8ea5b,7079217c,b5ab5ad7,ea879675,9e5bee01,9583dd50) Z8(65ed0c1a,5177c5da,7bb4c1d2,def1d47b,1ada435d,502138b3,d8d5820e,6284c7d4) Z8(7f493abe,9941e4b9,d9bdc7d7,c901d779,554006b1,e8881213,66e8ed52,8bf6efcd) Z8(9d2a9f60,72d76f6e,88217196,48de863b,77c04b02,d86faef0,b778e24e,d3a189b0) Z8(78a4b51f,1b78d543,548b05f2,486881cc,4beed6ab,62f38f2b,a4aef7df,46e3c64d) Z8(ab4c890e,bfcd3df4,23178a9f,1565e648,de37e7ea,ceba2b9b,cf1873de,13445283) Z8(0381fb9d,21b762ac,33beeb26,5ffff250,cdb8e3fb,0a9e7be5,d4c8945d,b411e16f) Z8(60357fdc,b1c853d3,43542d98,4757348f,30ab3308,88d82e06,8d8bfc7a,225cba7c) Z8(de44138f,6808dd09,f6daa08a,fe5b67e6,93b92780,6c1f80f3,9a836ae3,a93fad5d) Z8(666bda02,de914233,99f416e5,ccf4608c,43fa2a66,e53af166,d870a4c4,a316d3f4) Z8(f4e7f206,f33d2f06,2d60d930,4b900eac,c7702fcc,e3d60b47,902481f2,789e2902) Z8(da2afc9b,e9bc15ea,a2089bd9,d9ac60a1,3533ea2a,6b49b95c,9c93ede7,70fea71f) Z8(2cfd6563,80bbc0c5,d91130af,207747a0,4f96cebd,f6a52267,a1d56a00,6a0b5fa5) Z8(59185d86,8e2c5d0d,e6c6cc08,941e27ee,8bdcd2a2,2400c277,95ab5592,6dd35b74) Z8(555f1577,aed3e7d7,aac5e8ea,72f511e4,9d1b49e0,84ecca6e,53b6a29e,cfa74a52) Z8(5b2bb4d0,324eed99,7fc163ee,93a31d75,bb29ce85,83322f4a,ab3d7cb4,22975699) Z8(e7fcca82,46fb2174,8c58ff1c,c3ddfc50,d04e94de,40adcde6,fc10b148,f7c994ce) Z8(b4845d37,a1803ad1,ebb25c69,44f3830b,d5fbecb5,b197aa0f,937fde3c,d9680ba2) Z8(c197a308,0ead709f,8b53b2d4,fbd86a58,7b32ea38,dad85ced,f30b1d43,7defd013) Z8(114fe877,769d9137,1fc4f287,179962ff,8669ab70,00b12b98,9d00be52,12136ac6) Z8(a823e91e,9184c39e,13ce2305,bb48291e,0d0f6320,92122d87,5fcc462f,7794b64d) Z8(0d92a896,99785a4b,ddb7ddb6,7a2f3b90,73c89f93,c897136d,869fa241,b0e183e4) Z8(d474f849,59f6d145,6ac0dcae,3d1c400a,49fd8278,fd4f06ae,5e4f8019,f1002590) Z8(ddbd9d20,8009a3fd,354659c6,65f005c7,0b38910e,11769e7f,68b0ef6d,4f064571) Z8(18eab72c,e72b4cb4,1f4f13de,8751179e,5082d9d7,791b514c,62d010a2,a052410a) Z8(5228bdf8,cd28b9f5,e944ec3b,b2b9fda1,702c2408,7a801380,fc7a6a1c,04a14159) Z8(41151f0f,b81dd140,c2358875,1f2ada72,767caceb,71da3180,39c7a57e,6bf4156e) Z8(d6d387fa,966053c3,85c315ee,ec54feda,c2feebb8,432b8bda,5af8a4cf,4f5d5376) Z8(1bdfc5ac,c469bf34,affd4119,052e12e5,733e129f,00e28c6a,24026e65,063b94ad) Z8(80568719,49e45d88,ebe8412d,a36141cf,15b24aee,e3d6c51e,744c8a9a,9199875f) Z8(6a04edb1,261729a8,ce514ea7,44a6cbc3,69ed7cc3,8817d2dc,893f7534,9ffa1400) Z8(d48640da,34857205,ba1592d6,b8c10878,221ab0f0,00cf8ec8,8a12a532,9f34e04e) Z8(a7a47efa,038e8bc7,bc90ba05,d8a5ecb5,63858ecc,b8e1c8cc,c73b93c2,827310d4) Z8(42a26ac9,96e1deb2,98f04e1e,b63ae3f4,8c4d0aca,38532ccd,c763e962,68769ec0) Z8(a102fd37,6bb4590f,2305d566,a513d723,804efb71,5e2bd475,8a0589d7,a186984f) Z8(67dca50b,19da2da6,c5640310,48a6da3f,0649ff60,90094d5e,e280c057,c870e68f) Z8(6d377e19,6051283b,f8e53a58,8731792c,1ad45139,f889655a,2ea96f5c,a98e7eb4) Z8(b138ea2f,385c0ed1,9abfbee7,7149d74b,66912ee2,d125c745,a997c052,a147debf) Z8(0bb9c619,1c77c05b,a5f15700,bbf663f4,04bc7328,3cae6a50,8a689f24,70e88eae) Z8(42994778,8dda9bb5,347b2516,a5a7f18b,13dab2ea,b2f3db55,2992e3d7,ce81f2a4) Z8(102db868,63cca6fa,ca9b13c0,ba43fa97,ea868373,f290bed3,8c027270,0cd96dc4) Z8(4b4fb85b,d5019902,06d67d81,99e239aa,576cc8f3,f251f71d,5386b130,4372c17f) Z8(74a29d01,24763c14,727dc4c1,9497d631,7a5852b6,654928a9,c05837f7,a87220b7) Z8(937e38ea,4e53279d,0b023d43,9d12361b,73f921e7,dce9e47f,6ca154ee,aaa17f59) Z8(a83be356,6abb7dc8,72123154,2fdf117a,792c28f8,0e17175f,70c037b2,660e1b75) Z8(aac7f45a,fea566a8,b39dfc9a,258696e0,7a086b1f,4fc00282,4e44eca1,d4782a41) Z8(b9322c56,6663dc6b,60e9b579,1fc2138c,68da1ed6,6a858888,f5c8bf15,d36ec5e8) Z8(28efa015,3b8a79f0,4f4ba995,da0a9950,535feb30,6c62f313,7a5fe012,777e8010) Z8(338c5a38,2e716ad0,61054419,1d3c343b,2e762b84,723e7ab4,830a98d3,93c38e63) Z8(0f858b11,16a24d08,ecb3390c,64eb4cb0,626a79aa,fc4548ff,9d6aa870,2bac2c0d) Z8(15453ebc,a701355f,d6c342ee,ca2a3bc6,be6ca7ad,0ebc3ae7,fef4dfdb,a67a7ecf) Z8(4da4394b,89d6a0e7,bdbe26f8,a4e3eb9d,0fa2a98c,eaf034e6,7b653b16,994ffa77) Z8(b69532b0,74f40cf4,24ba54bc,ea3bb719,a726a53a,7e711ac3,771dadc4,01e6e881) Z8(a832d771,5c12fbc1,7e4a4bac,79ad0016,b6f9068c,20baed48,e8aef327,8af87313) Z8(4c892785,0cf694ec,8f6e82fa,6c2e0aa6,146c1a56,da84e9c9,7b14283b,029ceef5) Z8(3fc79fc1,c177b3bf,a1361edb,e2e7eb32,125b042a,6dc86660,a2afb901,6c1d5f04) Z8(fbe80f81,2ea9800b,68c30665,be682f2c,8b2f764c,a5499b92,0fd77750,6aa0b8f5) Z8(7fb5a54c,91b964fc,e8d4ce8d,3683d895,7b429b59,2632cd59,bf880628,801bf1cd) Z8(7427b7f8,29ffa438,2c43caed,a928993b,6ad5748e,9a6ad5f9,2971a477,01049254) Z8(2984c95c,2f6031ae,d09f06cd,aa2a6e24,8b16bde4,f8537b03,6b2b4461,c88fb5f4) Z8(20e749be,c19ecb17,b1e9010e,649930dd,c6af2cda,9b18a787,602292f4,ba07524d) Z8(22d169b4,8a6e2e61,b67b36c1,462b85f2,f4f1a289,6de1f549,d3e587af,f47f3044) Z8(b39e19f1,66df1718,626b3e54,d8d49d0e,780d603d,ec59ee7f,cc466a47,826aec93) Z8(90f9a939,ec7c482c,d4f01abc,82bc1a66,ce342d45,a2523247,852e364b,e8d9cacf) Z8(adf2db6d,393e4170,60e0f036,16a45a0b,3e14bd7e,a25787a9,bda649c1,27c39743) Z8(968366fa,853f035d,34d4e94d,f60ff228,f9d05dd7,cbdf5f19,f7648bc3,dea8ad30) Z8(59466820,44282bee,3e839f1d,16d876df,796f400d,71fbec38,1c8ee629,62050b1e) Z8(f4ddfcac,d8a6edd6,a7bcad2a,f2b3abf4,ac3d7779,9d82356f,51581e1a,b08ac97e) Z8(67dddb23,641a3888,ff7a246f,ee1d8d55,85d5298b,98e86851,fccfc4e4,ac4a06bf) Z8(cebb6fa4,c342bd09,24a4fbbc,e57e6ef6,02b4e380,826f9d50,d3d7115d,df88214d) Z8(a08a81f9,48b49953,00863964,9ffb047b,1fc12fd8,1d81722b,1408adae,fde7dc93) Z8(080b605e,3329a4aa,b91c8042,d4dacb65,ac2a8410,374bd953,a221dc10,515f8b28) Z8(6dede440,3a51a899,8cd35976,a446eb01,f80267fe,8d76fa03,e5261cdb,ea5ed3d8) Z8(ed0d9006,53bd35ea,a1b25f55,eb7f07bf,27279ab8,141e8d48,f26e53ce,b269cecf) Z8(2d9e915f,40656769,9cce6ac0,5625f474,04e64543,5820f080,86b5d248,2e5edfb6) Z8(61f65a5f,ac9f5513,79f42a82,6975797d,9f6e957d,ded4c491,7bfbe355,f97e70ad) Z8(6f863f53,8800fc97,51f59c1f,bd28878b,89cc5d7d,dbab0a56,4b1984d2,09f80db1) Z8(1f883dc1,0b3d46e9,872e8984,4ad3a69f,373a68e7,d6b50da1,459d7ac2,095890c1) Z8(442f56a8,1adcfaef,1651fb1a,d45ad971,afaaff4b,12197fc7,1ba57aed,a3524e61) Z8(a4198bf0,7d3db354,44212e48,7159cdb2,a17fc867,31f022eb,5661293d,2a421338) Z8(3cdc6e62,e87e6536,a070a258,2297fad7,0e016e83,af2f6f63,ba7446f1,0bf7f2dd) Z8(b3877a34,97160bad,fa2941ce,f572f914,591f31df,d16b80a6,cda7976f,a07f0d07) Z8(bda873ea,cf3a8080,30ad3848,447e2bf7,fd49196c,d47a2501,70b5c814,9a4d1823) Z8(9e82fe20,361414fe,02066304,0fcce0af,8d6b4902,03094453,46b3182d,61589e9f) Z8(235abc9d,c74c1fa8,a6c3f3a1,d73716dc,e2a08c1c,9ff2144f,e08ae6cf,f3f58f7c) Z8(ae455170,27fdf08c,24558516,c50e5f2b,0717f3c2,1a2b38f6,5ad4fbc6,a3940673) Z8(20e8de09,1b61c760,3b4d1eee,78001b19,2a8be7ed,510f7742,7b8b5803,e7903810) Z8(9fba107e,edfa3fd8,b4be7d15,a3da86c1,dbfd475b,510d1080,63b7d0e5,feb60c00) Z8(f8296782,45c14f7c,c00b840c,e09309da,7de53638,25c2877c,c821276f,157bc44a) Z8(2a71998a,fc3b1847,0523fa57,99421581,0e5b18cf,6ea02556,c060b470,3d3d4a19) Z8(a419183b,925d4a44,4876aee9,f301dfbf,2c3131be,e79b40f6,2da99587,49d3649b) Z8(4f7fc5e9,52627c89,248c7cd3,993aec89,5ce85065,4a1d6e49,10ec31dd,223425fd) Z8(13c4e909,fe0bd666,cd79d96a,8a466cfc,9f2eceb5,b402cded,d8179f34,72568612) Z8(8d04ddd5,522bd50f,e7e30d20,b891c9dc,3b3f49f9,459439a2,2f162131,e0e1e1ee) Z8(ccf5dfb6,21be7d52,35ef4646,78feaedb,fed65311,88baf0b9,6d36bd02,32c38866) Z8(60015701,6099b702,de78aabf,37ef828f,a1fdd738,0ab71ba8,9b2a0d0e,144d9edf) Z8(9722b323,aabdf7fc,a409089c,5fc1e8e9,e75c29b6,81691afa,cef3ee5d,5aa3d1ac) Z8(a0ac04b0,70bb64b5,833ad974,d1ffff36,446df649,017d35d5,100f2292,074b4543) Z8(8a50537d,8fe292af,2f08ec23,50ca5e5d,430a4ece,548d0f97,b95d2fa7,a14842d1) Z8(0b92b930,29ca5049,0fe0156a,e1318900,825aa5b5,f8cfcba9,630aabf8,fcb5445c) Z8(9a0f5d31,1c166668,7304a96e,bb93c230,078c9f55,647bda23,3753e8ff,15eac029) Z8(56fc200b,cadee2ab,192f9045,01d9c811,f46c518c,ef046684,45bb2352,54e58c95) Z8(ecf53a43,dc827246,c1cc65cc,4e8e0570,32832176,4adcdad5,e3e3f9ea,53640b1e) Z8(bdbe5ebf,deee024c,61a4a506,ccce3cf3,7efdc1b2,87642e3c,60b1f57a,c4795e52) Z8(96270959,891c654c,769a88c3,a628bc72,a88bcda5,04b2a8d1,860965c4,80f42da2) Z8(e0b600fa,cdadb41d,779666c6,8cbe391d,9d9b8fa1,7a4d362b,c4b1161b,5fc1c961) Z8(a2be4ccf,eac2b0ec,7e6a5d0f,b8dd4fd6,ba13e23c,31a36bf7,1ba6eb6d,ffbddd7a) Z8(f937a44a,e3463f88,78e73179,0052e7bc,450af890,072ce84a,88311445,9089f9fc) Z8(30a4351d,c55167a1,fa3f8b05,4c3db965,41a834c6,9e3e5c31,ce8d2f34,6e386a9c) Z8(1edfe4e9,269143d2,7be878a3,8db83ef8,237b75cd,cfe22795,6a22392a,f69e73a5) Z8(697f008d,e28ee23b,872b9211,c27ba0fa,b55197f1,10eb8972,ad4232d8,32885c70) Z8(d17f3700,0a90c686,5c1b804e,fbb9e046,74d7e87e,290f5e65,ba0eda6e,7f0a3d59) Z8(7ae4105b,ca86b8ce,f063c526,47baea9a,56c14628,9004afd9,b5cceedc,acc468a0) Z8(e8859e70,ea85f38a,cbc0c2ab,09c952b6,c23e6e90,dc4f858c,d0725a90,f074d7f2) Z8(537de54e,203211a6,0b7b3a9f,4a3913b2,00a065ee,3159bd0d,efdd1af8,d9cee46e) Z8(d0924492,4587ad9e,380e9e6c,18b990ed,f8ffb310,fc189f47,35cbf567,ba71c4b4) Z8(2c36072d,fe431c71,5a84f66a,8a9fc2ad,f7245ffb,44397ed8,caea6bc4,332258b9) Z8(3475bcb5,2e9d7db2,91f2d154,98d33054,48eec31b,cc0f2498,60065a60,fdb7e599) Z8(252505f1,4b9419d2,267726fd,eaaba8b9,92e20407,230a017d,dd6e1094,6d4bb33b) Z8(6d25f3f8,5606638b,94625ffe,cdee81e6,3ed8a673,12c39322,95425aa1,15a06324) Z8(004bc64e,1caabb1e,7f862031,b0405a54,d823f33d,55f54469,22ac404c,73372e85) Z8(21ada446,76c8145a,f93bc046,04f6d1e8,bb9b3017,67bd1edd,9c1c7847,43a1fe4b) Z8(e129d1b3,2faf1bee,2690fdaf,97289b37,f9cb1502,e2d87860,a130278c,60bf06ce) Z8(946ce444,c2e9735e,c4cfe75f,a389b800,3550dc6f,4a7776d4,3fe59cb4,b245e477) Z8(e52b1e88,486135a9,0482f361,40af30ef,7eed607e,a268d3c8,7c4fb7c3,b42c6263) Z8(2890b4e3,6901b449,24bf0b0d,2dc907b5,8b467931,f2f3ee5e,8c168473,5e6e0401) Z8(45298fe4,63055caa,a800a985,bbe6a9cc,7e224591,693de78d,39f4435e,7d8ab12d) Z8(902f1948,589f4e80,50334198,467d34be,91273ee9,3255bd4d,9cd4114d,78592c7b) Z8(d80d90cd,eae86fce,ac80776b,ffa08395,d9177d6a,b2c656e6,93e895df,216aa2fc) Z8(0a71fbe1,d4894e72,ce4e95d4,cf210c4f,2dd10905,4ef42a95,17013ce3,71ae652d) Z8(9740d3e3,3984ca9c,8420cec2,d0846dcc,b9b9609c,f2ea3294,2eb63b2b,e835cd1a) Z8(5e2e6968,71eb5b2a,8359fe73,df5c400e,45c7600f,d26aa746,d95951c8,b60de064) Z8(9b5e950b,6816a569,b38a2548,2007c1b2,0744db44,cfd53cad,bcc8b67e,1dc872b8) Z8(329a75ea,f7eefdb1,8e423a2b,f7a839bb,f0cc5e25,262d0a06,eab9c1e3,91fb17ba) Z8(2624e455,01499524,7ebbf090,d2fde5ed,3772103e,eccee225,4c1aa2b5,bf35e5ae) Z8(9d79764e,eb63b668,00fef95f,b847830e,ab74e469,ca9d69c7,84d74fa0,5fd2f477) Z8(37b35679,292e2232,1f00301e,3f253087,65fb7d99,cd788a57,824124f2,7d394584) Z8(acbdd961,af0c6cd7,c3ec9390,00d9183c,5a5ab4a5,40910d03,4c92e776,55654be4) Z8(5b8ac629,1bd25f3a,f777cd08,6beaa63a,7ff31e60,7bc7190f,bac4b9ae,5b59c410) Z8(e933f4d8,6b10589a,aebbfcb2,2a26dd52,a80bfbee,8d2dfe75,a197e480,ac5f4325) Z8(2f77d094,614b8296,8720e1cf,52d9ba2a,0a28692e,a98f6c92,0a558011,f6970078) Z8(42f8985d,cb5c8e5f,fa25b4b9,76981dc5,09ec1968,99cd7685,c6f4e9fe,5f2b94cb) Z8(fbd45424,7785d99c,f451b5f0,a1a010da,af450832,c4be8de0,01808cf2,a726c840) Z8(dff355fb,d59ccb50,d04f1049,182f84bc,971aa007,2a45b755,09c7031e,08d2e8d4) Z8(302d6db2,33b2a5de,d3206c8c,66d50802,6438ae90,acd087ca,c1ae5a33,52d49063) Z8(6d58c886,5c4b1af8,37d42920,0bcffa4f,c9a38d35,e348f131,86817382,33035112) Z8(384c1f3d,dcdc8ccf,c27be72f,67ae9bc3,c125df63,e735a48d,ae78a68f,a29bbef4) Z8(b7e5c202,a738f7cc,047e1cce,1425e52c,9bbefe03,94fe561b,6858c9cb,2b441c21) Z8(5df5a5ef,abbf9405,59184987,d65f720a,ad9692c8,b51c30c1,4cb8df58,8c9a269d) Z8(c24ba012,7b7a81f4,851e68a5,dad107c7,fecb43b1,7545a94d,3b931cba,1e3ed9dd) Z8(e36059d2,81171dac,5ed41fee,87270128,2c5f774c,b1166acd,e59be72f,1f8e56ee) Z8(cadbeebb,473def00,8dd3c28b,86396afd,dfbd9572,514574eb,db35e58d,54ed0d7c) Z8(aa833546,8c20377f,0c198654,b90edb3e,752496d0,a2184e30,779f5218,68d2b4cc) Z8(970f3e0f,453f1e03,3912c6d7,00a9077e,1a89ab00,ac106d39,1b34860f,e615641a) Z8(9dcd1915,21a90ced,feaf2b07,55288761,4ba22bfe,a85898a6,f8b5ab7d,8a8cbfb3) Z8(73d7de7d,c9139ce1,a4a4568c,1fc94472,1e63c97f,7ff71897,4f108478,87744d44) Z8(96af44bb,24dbac03,3d32d32c,d2c1f8cb,1a52af24,0c12f106,22f691cf,0f75f59c) Z8(6f1fb081,796447b0,ca8df490,f50bbd12,14c1b011,29cf944c,69a12579,062a8b42) Z8(dc87d1bc,a98b61a3,9f106a31,ccabed31,cc169e62,2ef2bca2,a9d955e1,92aa615c) Z8(983071a0,254e41ea,3cfbd511,7a2376a3,c35cc304,97ca8e09,edc279df,ada9b5f8) Z8(212e09c2,4fe1fffa,37329e09,c922bb09,777e2b20,3b9d6f7b,5cdbcd5c,399ac4e2) Z8(28a11449,4b2abc04,dec77c9c,327a4c2f,c4433986,936cf8ff,4368facc,912205a0) Z8(c62b9aa0,6fe36cba,8d95a131,b91c77bf,3cb6e1be,44f40266,3ba8d1ac,f02dfd39) Z8(0f0120e4,d81a0c88,8553f90d,9d50211e,b823d383,b760e65d,e8e54c76,e0f8623e) Z8(c7292b07,b4fbd3e1,e263a4a1,d12c56e5,9ab6dd7d,f851849e,ec783cf1,f39028ea) Z8(0dc08f80,f55471e7,12345ed4,43d6b9a8,e19bb7b7,182fc7b2,ea57304a,ead2cd07) Z8(d0d28eb7,5418a47b,2d7018a8,28f84ca9,2b0d2cb2,7fbc56de,0ede895e,3673c026) Z8(d449e604,b14a1e0f,dd268913,148ce328,eecc2a06,0e0f108d,d19e3225,4f293537) Z8(c3854642,50a343c7,6c09a496,b0f87fb6,52ac41b2,8adbd078,9e62591d,d2dc182f) Z8(d1a8b83a,87584913,eb3e2e45,ed52b0f5,8423513c,cab4d7c5,ef8bb5ff,8416ea57) Z8(a31a83fe,533d09ea,f9151f2a,4411f9d6,185ef6fd,e379d081,3209d8f9,25d15d9d) Z8(361ebd29,d9c91e28,dba363c5,6ac42c5b,68bb1661,ede6d6af,9d3dc123,afd84c1c) Z8(d4073969,c6cde809,3f41b976,2362da44,7484fe9c,8d13743f,ec28d887,e595f56f) Z8(487699c9,fb51e77b,7024402d,552217db,9f87c739,2583dd22,6470a93a,03e76ba5) Z8(a5633400,a6bf3e2b,b2c41e96,4551d9fd,83a5dcdd,61b4b601,9ffda6b8,89a9151c) Z8(120f6c9a,f13d90a2,afa44ff7,4024c741,e82b0360,82cba50e,f191ea87,6bdbe5a6) Z8(827a8825,96612551,5b7e4f96,eebb1293,8516a779,b2480b9f,0ccc6e64,e003fb61) Z8(11c2cf70,4fb61526,0aad15b4,c94c9e22,142631d1,fc2920f1,3977d08c,cc29c284) Z8(f57fc2ef,17ae64f9,7d535ebe,c7d2b38d,4db51d2f,66d855f2,e5cafebf,ceda6897) Z8(596aa5e5,9c811035,d5b88dcd,093a81dd,7aef7c6a,8f59e1a9,1152c8ce,8c1a25db) Z8(89c0e6c8,099bf63e,e6f4ad85,dcbd9c2d,de75cfe0,973cd96c,47fc10f6,b0ccb277) Z8(b58cfede,a8898045,2dbbc8cb,ba4c622b,ef2b5cc6,d78f6230,fbbaaa3d,015469dc) Z8(077faa48,9b970acb,f6887929,5b6a9cd9,f997f12c,0ff06942,6c4835f7,502370b4) Z8(a4813b16,4921e2f1,63ce5c1c,f37d1f3e,8afee107,f394f1a7,cc80db27,fed10d8a) Z8(42eee6f3,5262a2c1,da7add1e,3b773f5c,91245759,0911374a,9248777c,42c9cf54) Z8(f34ef07e,7e40e99c,f665e7a4,49f4473a,b4dbcfa0,66228e0b,9e9172e4,d32a2cfe) Z8(0372f823,a55cb7d1,52163b9f,9784bc15,ad012aca,aee6469f,7dff4543,34b0f2aa) Z8(e6b62ce9,8ccb72b1,d27fd01f,80ccb899,796159b8,5b043ece,bc193b1e,329edb5a) Z8(f383e5f7,dff48934,9991c584,247f2246,07a4040b,bd7f8c04,ed22d4ff,d6486959) Z8(d3b7568d,167d24e9,302131a3,5b42ee46,610d6dbe,a4963165,81bb476e,783b547f) Z8(4ac8eeec,e3527284,de6ba45d,02cdda41,5096861f,270c8f42,33dbe816,5f60a4c1) Z8(a59eac91,c80b6210,e10d359a,a745eac2,dc2e5483,30976893,1114ad60,155f1f88) Z8(ebbf9626,bc1380d4,a7960c02,93fe4334,4a0b7ab1,bca3e797,ee5cd8f4,911e2495) Z8(645cceed,e98a7a43,93f8690c,ba68cfe7,dd7fec63,21c59b02,b870e1c9,b8c4e7ff) Z8(8f7f74e1,577ef3db,27b1fee4,e7bdc4b1,a441575a,0e88c8a4,2406b198,f068db07) Z8(089bcb78,72b98143,e3875039,83a27f97,7315386b,43714d47,98f17b4a,9c0b5877) Z8(3ed55abf,c2a48fbb,d7c12e90,70cc9e36,8a8a24d7,eb006d9b,69209c2a,ea78348e) Z8(d36c2ce5,32fba94b,91aec466,57019f2b,021aa0ae,4c80cddc,d8826194,9fb39eaf) Z8(deae7597,84f068a6,115eb61c,695ab745,5fc75809,2f2d0d03,89188f16,63e25e12) Z8(c6ef5eea,5c51b54e,aa9402f5,5f8fd9f4,62b9569f,6f37db93,4a933d16,4c1cabd4) Z8(f52a2313,ada7860e,05a4a3bc,ee40dad8,cc7f1b9d,1d0fc3f4,0fe4b316,f4b72a65) Z8(4805a40e,815e5ca1,fdecccd5,94ea7ca1,dd26b406,f8553b1e,2ca595ab,00ad6c5d) Z8(ef79bd4e,61962ee7,6310bab8,33e5eb52,5a411cc4,2867c3aa,6f2b9623,45607157) Z8(71d98fea,a8f88bcc,14b2e044,44dfaa9a,a3a50c65,a7dfc2f9,7d507294,e76030bd) Z8(65a7a5d9,2f672e09,9af670e2,8a7fd704,d11aad45,a1a33f47,ef4e1042,82b077fd) Z8(27e385e7,0d1e0f39,7159793e,6e0ff553,1c134a40,d9655f1d,115d9a4d,e2e8bafa) Z8(b4765a54,fb1928e7,55a2e4c8,9ab73f47,04f23425,347115b8,a1b3eb19,ee618e02) Z8(fca6a07f,b0d36ab2,69085f56,d75f9988,c1b2696e,c602f5dd,5b76c47c,513597f8) Z8(7d93875d,bc0a0c71,9c0c8328,3a0163f5,ca042a30,12a37dda,7dd90c25,237db5f7) Z8(d4db5c6d,9680a2f1,878af916,f1e667ab,6bbb9463,20ead69e,829dad3d,b6ebe349) Z8(8cd4a9b9,f66bf830,1e5f55df,7732b2ce,0def00dc,022e50a9,499c9396,c249f347) Z8(818e9e74,7280dc98,b3f1a316,02adbd23,a8f24d54,1ec9016f,60c04893,ce90f461) Z8(e02839e9,6f973e40,6915cefd,a2f59c8a,6fcb5a2a,de0cc00e,e0ef1efa,e8d5cca2) Z8(b3660d7a,e4e0886e,2e83b25d,4e1edfb2,fa4f8c07,b1f19022,74bd0f2d,1325ace4) Z8(4dc4a27f,9307f63b,00f912f6,6f6d706d,e6754124,bd0544b0,b3bed437,ee3a10df) Z8(4381adba,d77f699a,5ee38403,c7dc0ccc,0877983a,8e8f32a7,952a54ec,758d8cc1) Z8(d644dde7,0b928c7f,b6f632e2,23692d91,64f7c493,3154d592,b3760ace,91b53d27) Z8(a9ca3fb6,439b4fcb,5d6e2a8b,09a88b6d,842dcab7,4610b47f,2a1c8c74,25033928) Z8(eb246d71,4e583caf,2eab27ef,44e42d5f,7a682327,51b2474a,302d30e8,ba227812) Z8(59871702,e35c2c61,7850195f,c62f1c79,20a416bf,190b35fb,9c222bd0,12564858) Z8(de179755,b1f3a6de,6e9dd3d6,947dd974,e245cba3,d4cb06b4,455a7ce6,4e21b866) Z8(77596f5f,2cc3914b,6f6dad90,4e551d4e,4bc3f82a,d228bcfc,18af315a,31d86de5) Z8(edc8b061,3bcdac29,59a1f802,8ea4a61c,4693179f,00357787,cca11095,c14823d7) Z8(f41057f0,5e51bc2f,129aab8f,d6186ecc,f54fa91a,326213b1,4d713b3e,bdac8396) Z8(f4298b3d,91e17b05,a7b00ed2,f1f222ef,348164c8,8fb0c1d3,4adfa2b3,e559f20c) Z8(c002b683,9c1c67c1,288290ef,446d3119,999cf3f2,acdaa2f3,b6b78734,ceff2b44) Z8(d84e83eb,1086ebde,577ba0b1,6a1a57ae,bfe2af66,53dcc011,df6bd592,740fa243) Z8(f25ed5bd,78e0c43b,4a05f02e,fcc14a01,e53ac818,923c9416,6b960094,9afdf883) Z8(ddcf31c2,2b2bc78b,4f42591c,53de09f8,e4079dda,21e9f481,bd9824f8,3bbf8022) Z8(06eb10ae,2b550288,720c74ec,83155412,a368c101,badb327b,dbb12b2d,a8b4f746) Z8(4dcb1f3d,116edfce,58e03cd0,a5d97b31,b0b7e538,d2c503d6,a0fb21dd,e3f043b0) Z8(0c21b10a,a99fb1dc,410d2a0a,00de55d2,8c4c158d,bf95dc52,6cefca7e,c5bfc544) Z8(d7dc4746,c6280cd1,9815f155,6f0e955e,770363d8,3658d1c7,05800221,07646e9c) Z8(e25a7a30,14d6acf1,3384fe68,89dc571a,a4ec8a69,9efa5958,dc5a7afc,7492660a) Z8(ff027ff9,66d61a5d,7f2b759e,bfb972e4,87a6e499,280aa457,e706b930,b619d4ec) Z8(458375be,2b5ae464,57573aff,5569dad0,fbb56450,4354320b,ee262d89,c50e16ca) Z8(47c41c74,5ce82396,51d822ba,a1cc5392,4742d2c3,beb2aa08,08bc6714,60234a5e) Z8(b01525c2,13534f10,d189bc14,1dce156b,1333611a,1b1e5481,6d863398,f531ae63) Z8(282d64fa,1df0bd60,acf83117,0238eb08,5f8c9eda,f5a177b7,cb8e0472,e63d3aee) Z8(7aac2e97,5f68fbc4,88a3329d,ca667aad,95b4daca,98fa3442,ab7f451b,a5e940b3) Z8(02feb3b1,c6030a80,93861b12,b1828330,b872a1c1,5162708a,cfb96575,8aa5d126) Z8(838acc46,817edbdd,eb9ed434,03a45348,f34196c0,43f366ae,e2e7e5ce,9b7744db) Z8(b5634f95,f962e5da,01712cc5,c4dc847f,9122f2b2,20daf9e1,581fe125,2a392e17) Z8(ba918552,4c096b6d,80127883,f3bb951d,d7949d18,16d0a422,a21e02c9,4d3a6ea8) Z8(4e88a691,2c8c7e90,747e2301,905e00a9,e0af05f1,ece13dc1,9b3590dd,5ae87fe0) Z8(0c6dc234,7ae10092,db9426fb,e828b048,48ed2c69,10d42061,d947e226,df786115) Z8(91578803,23acbacd,e27358fd,6f27fcca,74eb2784,ac4f9ba9,f4c89c13,249f75b6) Z8(d8127e82,a90c225e,e0570aff,34d1a0d4,284b7de8,299458f3,8d4b1eca,62c9ea50) Z8(4c500623,e46415ed,f9cd7c0b,6089563f,11b99c80,390e458c,4c388e73,2e950f92) Z8(04173472,c73e2d58,6802e5c4,fb3049ff,18a114a2,77e75608,ace26965,f02e2b7d) Z8(d6159234,85a9476b,c6aa7a91,3ded029d,4591db06,30fd9780,54210710,64748add) Z8(1fc4bda8,1a1cda87,4b82afdf,c958eabf,dac1677b,74b61381,0f16409a,a90c8577) Z8(1073eab6,bd37ebfa,80d81997,9177e89c,625b2ecb,54a72659,7929b88e,f171744f) Z8(73aca178,ea82131a,20afecde,01f42622,f27f9600,6ed74010,e0dcab4b,4be44e6c) Z8(cdbe3f20,1b7135d5,1c31c059,9d767d18,0f6e67fa,55aea6a1,dad76e16,c6bd2855) Z8(c4197a43,6621b3ed,8863448f,e3cca24a,d49f8f0c,082ff617,3a10912a,dcb4f3cd) Z8(24806456,62cae4d1,78892a49,ee3dc019,de814369,041f69ab,2e80faf7,e0e842db) Z8(eba137dc,adb093ec,90637f71,172a016b,1f0b4a69,f2040651,17220e64,7b67cc71) Z8(c36405b2,2f3f5160,2a719f9a,218b5198,c76a52d0,c9d9503d,c9e780ce,64d26aff) Z8(598799e1,2af6c81e,b0765d26,31d363b1,2c569cf2,cce37369,0d4bc042,bc714aee) Z8(a944f5a5,d02032ed,ee9d2408,de3717b4,3e6b2c39,0ea7ae92,26911948,321bb972) Z8(9bc04c2b,3be1dfd9,c0c6c045,90867aea,aac7d5b3,0a2e31b5,927d6420,58ee5ac4) Z8(cdd3a1a3,6d25d409,afc4d313,6efb0d52,d28447f8,2bf06b80,9126fb1d,bf5211c0) Z8(763f7dcf,fb510a49,55187d8f,0d9ca41e,05a990f0,01f3e80f,921e0622,ff281864) Z8(d6886516,84cfe4e9,1519687a,82120bc8,6e4bb175,b9dc5207,52b71dad,11b34067) Z8(b85d01e2,48849857,1991ba48,e7fdc522,a7ba1508,423c8397,13df8e03,bca6ca97) Z8(638a0e5b,1f84187b,cc54246d,d3f1e316,49acffac,17f36543,b3824494,6ffe58e8) Z8(e054159b,0d82366b,81091d86,eee46e3b,decf45f9,eacbe2be,a171ea79,04c47015) Z8(ea8a6a21,c2ca6dab,8d9e3d2c,9b3aa5b6,170f2970,dd240403,1a02e414,5e37913c) Z8(3741a61f,539eaa35,a8f236bf,7483c07e,df48c549,eaeafa55,28c26268,066d6e05) Z8(21f637ee,f2e8646c,9e1988a8,c4c43552,760286e4,5a4e021d,291a0969,792d9edb) Z8(89e35fd0,7420a26f,3c87e052,6c7d6b4e,c91c2ccd,733570c0,fa8a11c2,cfbb5d3c) Z8(ee80ed49,4d4d6d55,559151a2,a09b3c0a,57861192,69f5b45b,25470e04,210c9ca8) Z8(0da83c13,22e519fb,8e6b6b85,908a815a,4a9bffd8,de9bca61,f5e77c44,4eaafde1) Z8(c10aaba3,63b3288a,c6d1b459,b7202ac2,f95a37c5,549a525d,3195a948,60781ec9) Z8(49a98401,4ec37817,b6282889,837b3c3f,aa6b8475,82face54,9266bdd8,12ed5756) Z8(91f5be6e,6692af4c,bdb3839c,6213844e,8dccf1af,10bde956,777969db,969aebeb) Z8(d4e65fc5,77012615,06141239,e9574068,6ef42d78,c048751c,4b06cf6c,e2b6e620) Z8(93d9996b,2584a3cd,e7ed1fe4,c921f028,f9927f2d,83dda375,c840b2cb,6eab9fa6) Z8(aa21c65c,243e24c0,7319958e,4129446e,e3c501d4,5598b8c2,16223348,dbe5f40f) Z8(4d21417e,6c6864c6,f2b6a52a,82e2d9a9,f5bd8489,35dda92d,cbc8b330,b02633db) Z8(7c4b0087,dd761818,b578f14d,48457f58,167a69fb,604cc802,faf4ad61,8eb492c8) Z8(b3980e69,c1d30cc0,9c5c57eb,a6c53f4a,93b15700,41083d2b,8362dd01,80812390) Z8(a802d4b3,ab59dd6f,19b34b2d,5f0816d2,21fac244,6a1d9147,59799cb5,d376e23e) Z8(7b7d6aa6,60a30290,996dabc4,b0973b3e,98462f7f,99c55ee2,46501792,3b157524) Z8(eb167257,ecaa9d21,124ed480,a6d279ce,9c8cc900,d3d6545f,33b680d2,d8a44ac3) Z8(40c80840,3270655d,20bd685d,13b27c6f,00240faf,a536e81a,c929f61f,b080e63e) Z8(57e29ba5,48fb66ed,adf10907,c4227486,f8d8dc6e,ad4e8b19,c632116c,1b9bb59d) Z8(b37fbfa5,d36d6aac,92621107,ec4673ca,b2874554,a70c08f3,f0b719d9,8e0ec924) Z8(b5431b88,f89c4da2,a58be887,e748b2f5,afbe8329,c048cb5f,9c74baf1,5193a884) Z8(9231fed8,aa703019,690ac817,ac8038c9,f55ca27c,9a864ab2,b9951a6c,3397b4bb) Z8(5e2b7652,1443e0a6,f5c9e2f8,664876a4,254ee773,7a50ae65,90ed25c4,871771f7) Z8(03581bf6,02cf4380,67df8c6a,61d69624,519348c5,9812638e,1c1c4933,852459d3) Z8(c1dc9c03,870bd45e,22151c0b,662c4319,a503b0e3,a548b27e,15fa63f9,c0de97ae) Z8(498cc5e5,c5a3ca08,2399fd86,78d984a8,f39a69f4,2540f65d,86bf76a5,abe312dc) Z8(bf6d2bf4,fd61e0c4,40d5d651,8844f642,7e665574,57c99b20,fa6724d2,61714ba7) Z8(cac0cb89,fbd409aa,c45383cb,98426a99,44e1fc34,fd9039f3,b77e43de,301ce849) Z8(eb4ac384,a2ceafef,a7f55c09,f0b4267c,3cdaf3d1,db4d86f4,8efb09ef,82425308) Z8(99f52a54,6c7800e9,bd93e541,d661716c,0c75a4e9,a2891880,c4068131,b3c1f3c0) Z8(68a6c170,b3e53de0,c390f4eb,f5e16314,902f70ef,752585f4,690fec29,478e3fc0) Z8(62f350b0,ac35764d,a41d5cc8,2f078216,afe90ebc,cd9872e1,05a0da38,3db395b1) Z8(5e67830c,72b2f769,394b5447,62576bcc,b43ed7b3,316ae1ee,029f7935,bfaadf64) Z8(42c18850,a4c5e037,bddc57f7,1268a3ce,4bfcebf3,5fe8f7c6,5ee44d60,7073799d) Z8(50efd314,68eaef9a,c8ac9a77,83ba748f,352ecdca,ebd7c8f4,b8dea895,f252e857) Z8(b34c021f,deb81f16,477c0566,15d42868,b4bebba7,75b4c708,f63498c8,900ee68d) Z8(b0eb3215,57bbc454,ec89130a,f642e276,f7a227a8,9071658b,65191273,45a56f51) Z8(7c385094,5da84294,54ec305a,83140684,1c181b3a,2d972f2e,606065d2,f4637f3c) Z8(7b98c53b,d2b7ab67,33d5828a,a6041d35,c3ce9db8,bed5fc88,b671fbbc,78e22b13) Z8(283d3cf0,91da0825,b426a39c,e25fff4b,f1f75b02,8b0af774,603c62c1,af5e4891) Z8(0a7426b6,c7efda07,90cba861,70bfe178,a92101d6,93246e8a,8067262c,32682a3b) Z8(0a93e5f8,7373a7ce,e358c61d,a50f8176,632666e8,754c3f3f,dba5bce6,dee14462) Z8(7fbc33a9,42ef3bf5,bd64c87d,71e60d29,844f83c4,d0811ee5,5e1dbe8a,ad8b61b0) Z8(f59bae48,361cd11a,edb05d23,f7a3b022,f48e34dc,c76709a9,ca7b52bd,271958cd) Z8(70c63729,2f37fb49,64e1bd8e,d869694a,91deb019,96d1c10c,a1707a54,d4ad4fbf) Z8(f6f2b750,5357d69b,82e7e2d8,3442e607,bbdf799c,bba6f132,c9b663ef,8ee7741b) Z8(0dae9669,bdbafe26,6d64f8cd,c0699738,d36e21c7,ab5a4229,e031650a,4328c097) Z8(40e12adb,33c9083b,15c637f2,fb1d55b4,78b29e7f,3620d3af,c5551851,6247672d) Z8(31ae45b2,0460a394,2d5bcf1b,df7fb530,29b5331e,8da9d5ea,49108ac7,c768fdc5) Z8(29e96951,79e2ba64,117cc8cf,6c425121,f0f92276,342ad01c,8d48165c,911dc595) Z8(8df98409,d6a52336,3d9993f3,6e5fdf0f,2afe2d24,db1a3a03,967e948d,cb5b7bb4) Z8(6712196d,d8e55925,5700106b,b48933d0,b3f30994,82be857e,448d4bae,2c221575) Z8(99732e16,778b7144,35781de7,ebb4fb4c,0dfda43b,d513705e,2b5cff17,5aad6143) Z8(2ada5451,5326b4df,880bd8b0,aecc7e57,0a33d493,23f7dfda,965cfae8,849d1b37) Z8(3729806a,984d34d3,e3d70392,f583b568,1ec0504f,c07bede5,ccefa5f1,af1c5a79) Z8(07ec437e,f80ac44d,31486a57,16bbd11e,991d6261,53d573eb,26034167,2e7552ca) Z8(84a3c513,4f225e79,a8b8762c,9e192c65,80f50a59,b5183f00,0fe25f80,647bbf81) Z8(bf4ec959,eab58902,e182769c,dc75485e,7f199aed,0ceae762,f85d24e9,fdd1eb1f) Z8(09da53ce,16ed0ef5,fcf05a3c,ffcd6dc9,61a43052,7cdefdc9,0fae5c01,ebc6a72c) Z8(77c6baa8,aa27aaaa,5e1cf611,d616fcbe,b0b75c31,7d137898,e796bd48,96709a86) Z8(6ac7c376,7580eb8f,62692305,dbefd5a5,2f2ccb9b,227e074c,c1e8799f,f1f89319) Z8(7c445fc2,0c0c9503,de22647c,b6a7c562,e4655378,83fd6f63,3ee05215,65eb351e) Z8(b6a0e14d,2c79f4d9,fd70c9c0,731c4035,73d93905,add31e7e,8b9d36cf,5c260fce) Z8(b21b946f,1d954786,b47f0fc6,872dc0ec,d21c1ec1,2dac4024,ca290704,9a0e4720) Z8(3b6ed4e1,f51609a0,826396b0,59768aa0,5d4bb825,b74d9cd0,a3df4518,1b8970a7) Z8(d706a536,91fac86b,bb96fe5b,27de0b49,e3620825,a704a2f7,c05ab78a,25c288d9) Z8(6b1b506f,f7f20f4f,730fab5d,7c7017fd,180944c0,146b6fbd,17d28e37,d89de4be) Z8(91a8303a,5d8d7a59,9a23fcb2,77560230,986c636a,e00ca4b3,485ebe46,ac1c379d) Z8(07655f55,3e942dd3,b61e83e3,ada2a402,a024e51c,bafadf77,74c9ba10,de4eb10d) Z8(5cd05ac7,037100f0,70b26008,bbe6a0df,6952dc9d,8c7bac2a,6248cfdf,c880af9d) Z8(26d83d46,767010a1,643c7761,4373da67,3bc17e18,1df94c39,845bd8ef,8d01737e) Z8(f69075b0,6900a2e7,3d081cae,6a4f35ef,3ff32b3c,ddb489d6,88dc1b54,38695a9f) Z8(caeaa56d,6d871f96,34e9533f,e0bf44e0,2be6404b,74b0a43e,920cbef5,13a0a17d) Z8(cfaa2eea,d3871d7b,11ef480d,71b15235,39e92155,a0ab650b,9e56a634,7889c39f) Z8(c9ec632f,845829f9,e7d84c51,a34c0289,4cf8fa8b,55d6abd8,2b5c6bdd,b5bf38dd) Z8(63bb692d,e50ee670,e7d2582a,c777166e,02c5a991,463cd25d,236bd53f,60e1c3eb) Z8(a15c0a28,7e946d03,5de791c4,9035d106,5ea14e63,ef2ca089,99be94b5,a3c4ab93) Z8(8f9dbedf,41c71a96,2d55fadd,be537710,45221e9a,0a2bc360,0e04ee43,405d3ea3) Z8(b877a52b,b0189e44,d45a6438,4eae6589,8b5d3bff,29fc0c93,01c118a5,83800acf) Z8(35606288,bca125a1,da5bb135,a64c41ec,11ded766,709f9c89,51ac274e,a46ee066) Z8(8474b974,d662143b,4a351392,4c2418f4,667d80a7,4eb52964,04f4db26,68f590eb) Z8(b4ceca28,c7c7848f,e9663497,ffd95ad8,706842a6,84806806,6d96a5f2,686c5d1f) Z8(4c0119e0,10c1ab5e,bee871ce,0522acaf,9766c7d3,83dcc657,fc825b2a,6b593a37) Z8(f850669b,a8547a21,cbf76243,1f762b7e,3cbe5e81,9002dfcf,e15ad706,47baf7bc) Z8(44f26786,be18c6c0,a522253a,ea770e13,70ba5da1,420621a0,d7bc5482,bc98ec4b) Z8(a8682f02,e4175e4b,84a3bd78,1efc97a9,5cc0b1e7,03c0eb8c,643a53c1,dde8cba7) Z8(ec90fe1f,ed13db49,f9150018,86bb4206,e34ec2bf,b87ab0b0,88e70c9a,17924c2d) Z8(8c1c0914,5c216363,2131bc56,4bb37772,c911900a,ed0b86e5,61b6e9ac,503427a6) Z8(c023977f,e36586b6,58e604c4,e519d00e,2c2e9173,b7ab3297,166daf88,3fd2016c) Z8(488e7f31,256e3589,53a709c9,ced0968e,513e88b0,a7736131,04c5abad,d17cc56c) Z8(fbde2ed8,d7741a8d,1d8d15b4,fab3bf12,4d70eced,0fe52688,07954675,54469cc1) Z8(9485d7b2,55011a98,23a73ff3,533f93f0,43479913,9fce50f0,47e1f021,9a0e857a) Z8(ae8df869,5ab2b9b9,9823fddc,9a2f572f,48ba35d0,057479b2,42320587,cba3f3b0) Z8(0facf23d,fa37503f,77482d56,ba32e641,6da46cc1,9c14ba6a,8f86a00e,3f84e5ab) Z8(ded064d5,f0ddd50b,7a241d2a,5085f2de,fb93bb52,c873327e,5dec77f6,f601c313) Z8(b2b60b1d,01c72eab,ec340c47,98646846,e1c35ce8,9e45c238,8d8603bb,f721ae82) Z8(fb0f027a,2d4caecc,5b425923,2c1c12fc,640ffcd1,8c200e56,dbd07c5f,352098b2) Z8(6b936d54,b906f112,df134594,e4c0f392,86809efe,5ac3b0a0,855cbaa5,853a5140) Z8(211898e1,0cc39049,945a1c35,4c7859d8,4e95b15a,469ef0ec,87fee11b,51190117) Z8(f87a0e1e,f9352ba3,980ce5da,dba5dcab,8e49144d,5e303f5d,913168a5,02c6a60b) Z8(f4ea90b4,e3bfe056,851e37f7,3ff3c912,a5713bff,780d5f2f,d6aac49c,9c7e937b) Z8(25ee3844,44668c37,a72e7bab,3172ef7c,635c5b2e,1ef3e92f,675b40c8,68474056) Z8(9f1bc7d9,b1d01204,3bc5dbee,495a0723,7b30e7da,835202b7,9f6e5aaf,09256f67) Z8(3d85d7f4,cdc58d9b,cea0a492,9c3383a0,f58d2dce,cda6e53f,859a09d4,947a7151) Z8(fa1701f5,0d99e0db,46ca02fe,3485022e,ea449c59,78b823a6,8ece1cc1,2c721fb7) Z8(20e0e43e,d836eb66,a7c5b664,4111c4a0,54fb9328,4d744a2e,4c501b58,09fae7d6) Z8(daadb7d6,99aec8fc,8a9aed94,03f5e700,1e6a27c8,61a62f67,51c484e4,3098c23b) Z8(15147b25,d5e60240,2392d788,95274a3f,1f4c926f,a1c098d4,b7f69210,1273d404) Z8(f6dffa60,f395889b,72e64560,b5f46e5d,e2adfcae,5224ffc0,d35c1461,61f8c43c) Z8(aec66f93,dba92d84,8aa34369,b0eeddf1,66079fb8,3535e47f,0dce4be7,1ef182bf) Z8(95628ba7,789c4deb,ab9b555a,923347a6,5d52d629,32b4158c,98ebf57f,1b71eefb) Z8(05360d08,6910ae6c,bf1f09d3,d150787c,db8a8010,d789236c,433d31a6,63f7a06b) Z8(b78b6e03,2526ea61,e17fd6ab,d014ee12,04f5efd3,ff8b824b,173785eb,d92d90a8) Z8(cc9006b2,e27b1e7e,9e04ffa7,d6d12bb7,c501f11a,0ca69669,cf2ec8e5,d38b3a2b) Z8(ea45b79e,7f3567b2,d690c192,036a0319,2f121388,eb303b60,3186aa37,7c3c07e0) Z8(59aac509,06ef44dc,780f9fff,705aec31,83deebdd,8215fe90,5f0fcfbc,fbbee3e6) Z8(7075e7bc,9f293d02,cc7b6616,6c7effe8,23b3a2d4,8b05b489,e0551900,45711c36) Z8(52657d31,2921529b,4061a98d,172ca8b1,a70e38c8,a4ee29c9,1c508f9c,099a637c) Z8(552eea92,23736bd7,70cdd748,483caa27,f83c5cfa,df1cbbd2,03dfc2f5,df416163) Z8(6aa3317d,1b1091e1,b0b74acd,2ff17614,b0107c7e,f1ff3509,c4e44248,8fff3e01) Z8(eb5b9c24,306863e4,c513ed76,80780e60,ba4b021c,99dcbb9e,85481133,756cdaa7) Z8(e199bfec,aa94686d,738df1b1,8982340f,3b9fe348,ae4e89c4,8ab5b380,51424ba5) Z8(27f5fb41,f8400a7e,7dae8d1f,ce15b1cf,ae63263d,37205eed,2a21c0a4,2062faf6) Z8(54c5d794,d56cdbf7,b816a33d,30a39df3,eabeba2e,014fd3ea,027adf75,3598e432) Z8(723a3402,05f40424,34aaee33,f1521d13,465f307b,8ad12e9d,00812d58,86b1d868) Z8(a8df91ff,aa69b71b,1d0f3b9c,040d9f84,4bc4e4bc,9fde3cd1,afca6b96,4fdf8d5b) Z8(9f675987,7be45842,6a221300,2474bce1,b65ac2cc,8c8d6af9,9451352b,41848923) Z8(63c453fb,86f0daa2,810a5fde,5718bbba,de15705a,3a4940d2,00b915c8,69d640fa) Z8(5f219d4f,0c9d09e9,e653eeff,c467857d,05dfc0ca,55d70d7a,bcba47d9,37424277) Z8(ca6f34fa,6660b20d,88eca315,63aa0f44,be7abcec,dec5aced,de2e5c71,69a4a518) Z8(c660cb58,5a987594,8174b843,2c1516bb,82effd12,f607e461,1ca4c82c,724cc197) Z8(3398fe3c,519832ea,9c9d3ada,d3f4187e,339581d2,5d0da467,fe4e7660,784e6f4c) Z8(3c3b86a9,d996675c,804a1e1c,4473f52c,500f9cdf,2173dff5,e521e64c,fde2d994) Z8(b4c1a3d4,2d6fa9f3,598fc138,2ecee9b4,ba9c02e0,7ef144b5,9724c306,b0849f10) Z8(897fee1c,9d6107c1,4b31ccc6,ddde0df9,5a9d16f4,e2171f48,73853e35,f660373e) Z8(1d44396d,e70d716a,7c19dadd,12f7c6f0,6191a4b4,95bc60f0,f943782b,a8845013) Z8(b8e8d5bc,9c3325e3,4491f9ba,4801ea0f,28438d7f,d014610d,262692b6,c7e665f0) Z8(ee35a67b,10b1f430,848dd30a,d98206d7,8897599e,b06d0fa1,ef517827,33f2a7ac) Z8(6ba729e7,149fa756,7b9702ed,87aadadf,0e77345e,935215a0,9f05988e,2043bdc6) Z8(c806e8bb,6f437fa3,6deef38c,74204d73,d9082530,13ede77f,f55c8491,c381b245) Z8(833db8b2,e6d96795,5b0b3de9,4f01f512,27c8a13d,14d1ecd0,3a62aca3,5d187f68) Z8(713f7803,516b84c8,f8a71cb4,cdba8200,fafd0296,63f4b07b,eef717c5,aebedf35) Z8(73ff1fd2,d1aa2ed9,d80632a6,548dfa2e,585392f0,15526d7a,8a7bf48c,bff779df) Z8(93c4f36d,ca4613ec,1bd715a9,2b049478,95cd574b,2d2b4d3c,3ff5bf1d,9fbca906) Z8(fc3eb04c,35b3ad69,7ac041e4,f278382a,a007b67e,2e75b1b7,a97a7c21,926a7756) Z8(a31c5f13,9ab67b19,49b56141,ff9e8eea,a6e07319,eb593a7c,ec98dc4f,048aa839) Z8(c327dd96,76aecc17,5b9995b8,553a14ba,dd0bdc5a,2cb842a1,457514da,861c10c7) Z8(8f27f228,94b928cf,2db0c3ce,a9e3a3db,405095b0,bfc97b11,93804076,ee527e80) Z8(f46f3bf3,a6c1e533,780dd1cd,c80ebfb5,1e931831,d8950f9b,0ac54143,086c6eac) Z8(796f455c,0a747811,9224ee9f,da0c1f19,e44b74e7,b2e402ed,1940f44f,facb5e92) Z8(c23ad237,eccd8820,62f574a7,71d4acf6,d4da1c79,57e3255d,cee58e03,2dae03e7) Z8(d7d96e6a,aa9adf9d,76a0705f,52588469,34f73d10,8f7a0b32,26ee3d0f,6f69054a) Z8(ff96dd80,73765017,2f5db950,15b94207,51992dac,150f4a80,890e364c,2602c1c7) Z8(3ca8aa5e,d34c1874,c88bf95c,695fa64d,7aa65d95,95f0c6ab,5b9814b9,09a57db1) Z8(73cf0b40,c6276eef,70e1cd2a,8dd4e1eb,11d7b9a7,d751647a,194e9e9b,a55fea33) Z8(44d47153,1986a783,4307b677,18a40419,f97fce3b,502bcb8c,13a60c28,a677fda6) Z8(85fb9169,0bb6b95e,60a84616,362bdc6d,76f9feba,5bcc1bca,c3f4bdcd,7fdd0965) Z8(11cc9e18,13736553,94d6894a,320736c3,ede2cd3a,c228cead,192b162d,08cd877c) Z8(90a27140,94c5dbfc,b1c26bda,51203d97,dc4febf2,d04aba14,e0fba55a,e50d16d2) Z8(d8023014,bf41b530,a9be9dd6,419011ec,0c83798a,102396bb,d88ffb36,67726d06) Z8(18641189,d2bc0474,21f43e11,df55308a,a36d8014,8297b890,19c8f022,727e6d92) Z8(e4996f55,234936f1,6ff67e91,d39e5f19,972c19a2,0b42a858,4ec3bae0,a17cf588) Z8(8d8b78b0,c2b5bd43,b856693f,ed06c860,34780844,a30b90de,62a42989,704132aa) Z8(b3ce16ed,27e73a5a,8585a35b,87e3708f,ad121fec,55b20037,b604a263,259f4047) Z8(06ac38f9,b820034a,632061b1,b88be18e,7f2cee33,57229cdb,b5019331,4bd7538a) Z8(bc27a55d,8e8514bb,dc77724a,56715033,4dd5397f,d409fe8e,d8bdef96,ac85cb1a) Z8(cb8fc303,bf77a843,c3b4c4b7,1ae2d720,2faaabfe,3b7067f6,7ef99afe,4f3e8030) Z8(46ccf7e3,aeec0509,cf8baf83,7d2597f2,70d9f2e1,db1353e2,5e6733fd,2fe78312) Z8(93ce65e9,793a8d90,f1298529,f6242b2c,0ba837c8,ebaa3e12,6aa6c644,7e1443f1) Z8(dd517ec9,3e024e29,2bd18962,cad4559f,1e8d3817,09796bd8,23d51871,48cb7d68) Z8(a622d97f,67fe417a,94a50672,950359da,1cb626ad,9e4c8de1,7eff37e9,9c681069) Z8(db1984c4,ad2514bf,7363472e,8bd8c6c0,908b6363,e57dd0c2,08b595da,7d8fc0d0) Z8(a503c2a7,1c142e77,b9b94292,f7775e01,b40b96b3,89fded05,716ae7d5,a742ec57) Z8(523a5778,7a919807,826b0d41,66988720,9d899303,d4fb9ff8,01eb5b13,b28bdd05) Z8(92e97d24,78876130,ea8a0e85,34b23e63,c95831c7,c96bbe3e,088045f9,91f0d6e0) Z8(03a60daa,8cd87055,88a17c85,86e039e5,45244be6,1449c148,6468ca1f,2e1b644f) Z8(5d149c41,ec818db2,baf80acf,31fdf71c,588cd0b2,adbb91b9,af7e142e,731a03f3) Z8(fcf9752f,9fe6bfad,ca1c27ce,29952e4a,02c4a8b0,3c04426c,b8a374ba,ff5fa05e) Z8(0149fefb,85d7f013,783d66c4,eb0ea813,b2ccd02c,06f86b2c,bf50c08b,c369bd15) Z8(9e716dc2,70efa3bc,9044df44,ec3b31d9,93cb1f31,d4415349,eb3cf709,78cc8312) Z8(c7aecd42,95099fd9,12061e8b,92cd2be2,262f7005,60dc688d,2ce2137c,f59855b8) Z8(298f3efe,deca130d,7a98aa3c,db472f13,82b9303a,538c7f25,9658fdfe,2c2f5220) Z8(6e4de714,f49f59df,66c2e39e,08657916,2cc5a683,9bbcc584,5a75578d,34d67990) Z8(11ba4345,bde6477b,7a9029d1,94bf27bb,a3eb85da,dce22e5b,0cb4281d,7a6d9c2d) Z8(533568f3,39dbbb76,540ba85f,c1bf724c,7724b309,d8d52798,fb6fb72b,a3e2add7) Z8(7f096aec,80f85e7a,f44ebbe5,1dc19fd8,01a09689,1baa69ad,022a62db,2efe661a) Z8(c0e41ff2,9b4c8d57,35421eb4,6797c3af,90ee1d41,a1a63c6e,92b2c7f5,91d9d5cb) Z8(9ca89190,20745a2d,9c611a36,6a172900,baf817db,45107e78,d1799204,62e40b12) Z8(d520489e,a5e5d628,54fd3c70,691a0982,c135adc5,3fa0b151,8bd048f1,51c11559) Z8(62928ae8,d4752b16,d51264d0,31f642f1,76a7e23c,9d60ff4f,40109ee0,c8371791) Z8(1c7579b1,1542a2b4,84c80d22,4ec1fd4c,fc7cae0a,edfdfae6,9d73be7f,a93167b0) Z8(fc171937,d4260f03,f2636056,e73a5c26,6cb321a0,c9354bb4,57d0ec6c,006ed3d6) Z8(df2482ac,9b0ae0c8,571881c7,216dcfbe,4588cf3f,23efcc0c,94d4705e,dfcbfd3c) Z8(ea403e95,fc3f998a,e9d1067f,ad1ff45d,bf4d4e27,4659ce60,d43df4c1,f1b21b80) Z8(9b08bee4,eace6107,a6d1fffc,01a9e8b7,5a201bef,e1497a8a,f34b587f,3fe58084) Z8(af4ba266,6a546f4a,8d8098cb,5934b9b9,4e558e9d,3c1dceb5,14c3582b,bb7f03b6) Z8(7fd74ede,e6cfdf40,3ca0f816,aa543092,a912ed97,4769548d,78f9a3db,5e155118) Z8(b8cbceed,90e0e0da,0e37dc0c,d3855d87,3606942c,3a99d6e8,80b24c76,dda7ce6d) Z8(cb5d23df,c0ac44a1,f17f6646,ffeecdc4,561f8afe,9e9dc096,b52bec55,23a614b3) Z8(43b627c9,2c3de016,e8e6249f,48c9c30d,cc9fa87b,069fbe48,ba5534d0,d1dc32d7) Z8(926a20b8,cf284ba9,2c3f5be7,158a89ee,2136024b,6b840208,6267d853,586a0991) Z8(be5f4be6,fece6891,fed50429,c243206f,c5e473d8,ef77bef4,7d02eb51,005d592b) Z8(13832a2f,357b0d8f,fb283fd0,ac94278e,8f8e796d,43102f6b,457743d6,bc9c3cb4) Z8(365ed950,bcfa1576,98252780,5aaaa432,9b183388,1e465085,7333d4ef,8ea98e05) Z8(f21607cf,ab7f6943,11604ec8,9ae507e6,9ada9bd2,27140b1f,d08b9a44,9ce3d80f) Z8(27af3749,86dd4111,eeca85e6,99b2d53d,816d36a2,3d365002,2ca4f818,336d13dd) Z8(38be9f8f,bfdb9dc4,2b48cd71,e32012b7,c10c9763,f7778675,cecd49e5,cf6ef65b) Z8(d57e33d8,bc556fa4,d9990aad,27a72f87,71c1aa63,6f6668e7,001efd2e,2571f432) Z8(5428853e,c808ab0e,62c69e29,f7a1b86e,e664a9d2,ae6a25c9,65b400c2,9ebc2a23) Z8(907c669e,90d6926f,3618e558,539b48f0,c4a66f4d,c8192b8f,4f9d2149,d1836795) Z8(513dbac5,4b12d24a,da51d86f,a895ae37,08716d09,e5f35b2b,5aec8495,771bcc57) Z8(4c504178,efb1cc90,7ca5261f,f8bdfeda,c21ff2a6,b0189781,74fccc4c,acd3961e) Z8(d84f9ab4,c6f64885,cb2be5a2,d1bae8bc,8eded06f,e5c35472,0d6c1f70,0b53fc06) Z8(cf04ce76,e16029c2,5132b261,0cfe1c60,1bb89cec,7f680922,fa9fa4c8,110caa4c) Z8(7277da2b,74e64da4,6b73f8b2,5446317c,198fda21,811d926d,0a60fe36,9efeb500) Z8(c9257616,70ac1565,12e5d97a,e88a9a51,5e44b6a1,c1309165,44e3112f,d3838f8f) Z8(768f4874,62048f3b,a1f14878,bcbc7b75,bf0491d4,e8e94157,f4e5d560,f88e5c66) Z8(e36a663b,1251dd2b,0590b542,eee6b680,4f137f88,76cd03d0,d6410f8f,02908a34) Z8(155f50dc,790970fe,86cf2a5f,27b0fd77,bc6d8a6a,b54b1f83,6033cba4,ae5dde62) Z8(bdbd3079,4011e454,19fb875c,7eb45064,70ada4e7,0a63188b,c22d6c18,b1b937a0) Z8(2168f5ef,bf5cbb53,0b6b7dd1,26224bc9,54cf54c1,d6b20869,a0d92360,0f0987e1) Z8(8fcb3f9c,b1a2a908,4ad365eb,08d8118c,6e2e8f74,a20e432f,a0d4dcd2,27f36409) Z8(04903e84,ceb08e2d,a4db1287,b3abc1ae,79999a16,3ec9401a,f7ee3cae,e1c22dbf) Z8(bb3b9577,f4eb4893,2d6533f4,24eb539f,ba127f76,95cde432,9e3f0139,b1d0a32d) Z8(f640081b,efd21dfd,d4d0ee32,a84e04a3,b4a658b2,ed5b38e8,7824b128,d66c2e3f) Z8(5c52c841,724e35fe,279a6b04,4ea7fc48,de11c3cc,159778dd,eb6b29a9,e8b04dde) Z8(b06707ed,79047ac8,a1ce7aa7,f644202a,6e1841a3,100baf1f,7680d894,cd1285bc) Z8(a3bf296b,0fb37dc4,caa8b1c6,a88dcf5d,7a813b07,e5f8f4e9,6742684d,2f870b9f) Z8(8e87c3d7,94bd5f0f,8e3255b1,ccf16d30,db096081,4ef2fb7a,e2f08c21,8a8e9088) Z8(d152f285,b84da949,d51549fe,7e2e7014,3e73661e,2da23c9c,f52f2356,259b2ad2) Z8(330b0dfb,e0592f3d,fb548cf7,f3d5eb32,f4b52d25,5b3c3e8c,94792ae3,d4220690) Z8(bab4d387,338b2dba,629440ee,74db8e0c,04aaac27,04a96cf6,593a1a3b,95b60d3a) Z8(7a55178f,02b77b81,ddb81a3b,1c22c81d,3a6546fe,d6c205b2,050c83f7,59536185) Z8(4d4cb539,4caeaba4,1e468df1,38d71c7e,08f51395,8fbab561,aee61d64,9b195e95) Z8(d3a63e5d,ad53990a,49890d60,cb0b9d88,3f4d0ff3,eaa125b1,7d150c4e,aa9e439e) Z8(af165b25,e4814878,61a460e8,0e485a0f,170533f0,dcd5bd7a,9562885c,49159d0c) Z8(fb212d41,740709cf,584ed683,31222ca1,dc2a288b,011bd559,84fb4170,25eb87eb) Z8(e8ffcfc3,39dc1310,9e94a387,a3856ddf,4aaf8a6d,51632366,d4d74703,8ec3c314) Z8(98a69854,d0d34ca3,982b1ea1,1304455a,47e84d57,ba521dc0,38ad7d8d,9034d22f) Z8(f02e8511,bab7152c,70f4545d,e1eb3c85,78f26bb7,eaf29e81,35cf16a1,6c0d531c) Z8(a77aa57e,f8995f08,d759a499,c3672dd4,b1f83132,d1684b86,4f38c9c6,1c424469) Z8(bc04f269,0e32d696,295e7a7c,c8affb03,0d62db9d,ea5eaf02,359a488c,3419a4b1) Z8(9531d972,543e01de,1e71f615,56a47dc7,067cb0fe,64d457de,fb5ef4af,b03ce759) Z8(8222f5f5,fd923857,895f5f01,9b6b7aff,b362aa63,86c96dc2,93a52872,0d75abd4) Z8(d07e019b,660122b5,055168d7,cdfd4b9b,1fbd2dff,3137d761,072e8de3,4853d4d5) Z8(1fe68b11,364ea28e,0c7fb0c6,b96e902f,987c6628,86a917b3,a8ddfe23,af511657) Z8(4ea7897a,1b80c0b0,4677e3bb,b94e9d25,c62fc23a,06498f66,1bef0d0a,c1be5d15) Z8(d72f5883,4a2a2e7c,99221220,b8e76036,46dc6902,5adcfee9,5e536473,52e94498) Z8(807e106d,8d2403ff,bdb55ced,0cc07ab4,18af8977,e9c5cb13,1a56d9de,b76524c7) Z8(b553fdbb,d1ee4e9a,e79213ae,5859d08a,2790d5f3,dbdabc33,03928fc7,4fbcd518) Z8(ef3d01b6,66538aa1,b3bb2e04,9634b911,bb955e3c,b62c71a1,a58bceb2,397471cb) Z8(ac71c539,36a08669,9d697d69,fb9e1ae1,42d69189,79ed4eb6,5ec73e8b,4c782669) Z8(03aceada,a024030b,fd2003f5,632338e1,89fd1b08,185ab78d,a8ad5e91,657f86dd) Z8(666233af,38f99c40,2d9c5d3b,c3b81143,50045dc2,69c5abac,0e20ec2f,8ed238da) Z8(97796285,d5290656,81ca0216,f120f29a,7bb2f270,eed60c16,dc069c97,5dfadfca) Z8(909e6390,046d3703,7c3f88d2,6434355e,e98c65ce,e2a0d491,9ac562b0,0394c4f8) Z8(ec32578a,48c6e4fc,847e4f80,e20e37fc,fe3ca691,79220e82,718deaf7,13cc2ff8) Z8(49fbb9f2,29d89909,df976803,c854f753,7cc34a51,fd038866,88d31e10,56147a09) Z8(f3e09a8c,0f9db2ff,fad5fa20,86671e64,a05fb758,4b1f38d4,f52e1e1f,d8287a3e) Z8(1bc10381,ac96aa6f,25d2dc73,fb76ea63,5994f5ce,0c015d9f,04deb5d9,5e4e34a3) Z8(45f091ed,f50c052d,0b13b3f8,86a4cb90,5f942308,809973a1,31542797,bdcc7ac3) Z8(1ec3578a,dfce2d23,b83c79d7,abe3e237,02dd50b0,0b0ed590,8be6fc95,7872a3f3) Z8(f4d83a71,8af51b9f,f3868932,22546063,058e76fe,13af47fd,b87b6a56,cfad172d) Z8(30e2b56c,bc72d096,6f430db5,1e2d0e38,e668367f,6f72a0d0,0e587179,6f5ca671) Z8(d8bbc128,89164e16,1d7e0e2e,b4841308,a27e7f48,d1efe677,b013e62b,2c1b8ca4) Z8(f70bbbfd,f2276861,72af6661,d38b9e2c,0409cbdb,2370aa4b,4e9007f5,ab6b2ea8) Z8(e11d8a93,da967e3b,a4d3f836,f826fa52,1d6d7934,ed7daf71,3ec819fc,734e4a25) Z8(08f1bf0d,209cf241,110bdf66,751d819f,48719dfa,2e2750ed,8b1f3171,c6f5f000) Z8(3fa6f90c,0b372c1e,ca87bcad,a61eb994,dcb4c5be,799e378e,467cf8fb,f6c6de2a) Z8(48a58db6,211ba2b3,a963e3bf,fcb01eba,6d18fe59,7a7a6c08,f6bc6826,975fcc3c) Z8(b2930b1b,81b9a7ce,df976f3f,8ec810d2,3c1bfd5f,16d89bf1,72ae3422,499e4589) Z8(b42bd87a,58877cad,0e435f15,8b72f7c7,1e4bc7d0,59cfb147,77c80805,2e79d2f5) Z8(3b69e7a0,06a18dac,c9fa3f3e,4f5c36b5,2354dd96,f63efb34,cea371ed,aafa8c69) Z8(9bada3d3,e57d79ea,5a2728a5,0d0d35f9,c3b13e37,ea2ced55,8eae983c,6b00bb99) Z8(077d0fe6,c531286d,9d347760,16130d85,1f894ac7,704b4be8,0f70f9fa,fc1b7ace) Z8(85b13e2c,bd01a3c7,e5a2085f,e26dc94e,9b9035b5,1ff54f6a,85b175a3,546be6e3) Z8(7ed530fc,c21d79f0,7d0ebaa9,06e6814b,22fd6844,a5b5fad1,bc720823,e7863db8) Z8(166133da,fd66cca7,9538f204,afd64030,2e6f792e,6952038f,21ed5c09,eceb70df) Z8(6bbdbc46,fdc281d3,aec21b7d,a89dd990,6850d792,f0855f4f,bf225700,b9908133) Z8(8cab078e,25c82cb2,a3e54242,a3442020,5d3e4ccc,512aaa1b,ff96c3d1,a07f5511) Z8(a60c8f60,a66fcb0c,e7ed6c28,aec63c26,5a56e5e9,1af64e07,ac7d985a,8e99f652) Z8(f874e612,45c5bc78,213eeae8,52747fa2,2f880c55,93b20170,2cc422c3,91a4f360) Z8(423db407,19744c84,99cc04da,74dfed5c,e1eb208e,87f92e14,cf7a72a4,62c7e3a5) Z8(9da39372,926823ec,a3b6c298,dc26d367,cd8c8506,f394d632,ee008f7d,7ee297b1) Z8(bacea55d,e3008dd9,d2d15002,7365b007,f36cdf62,0623f633,a518b02e,80edf13d) Z8(c0d04054,c1299ba4,33cf8529,a30be956,37b978e3,bc3ca2fe,d22a3b42,2e9f88a6) Z8(2b86f135,e029bf24,66af3daf,a2a275fa,c7cf70a8,3514eaec,cd05c7f8,3f9c0672) Z8(f3734fd4,6979f902,371c6f3e,debe841c,ceee420f,31a5a4da,e8fe97a5,271be053) Z8(3381b85a,b8b43e2c,731e651a,c0ae127f,8f2b2373,0de2e4e0,d9b248bc,b8f0be30) Z8(7e624c67,02f54979,661500a6,f90bda96,25f8efea,a8de9dc9,783081b0,fcf54956) Z8(becc3c21,a8550fb3,63a221ea,deab5378,68c1b8b6,d0749582,ebf9e078,adae0c09) Z8(9c23baf4,382f6dfe,02e75a78,eecf7513,215ec2b5,4c1f421a,b0baf7cb,55fb49a7) Z8(289dbd18,d903e17b,d179c21e,291b1ce5,863dc547,777a5e20,8a8784ac,56bc89fa) Z8(6c209557,57193472,786c94b4,4a6e936a,f24664a7,caa90793,670e04a8,47d307b8) Z8(6b645c34,87f909d7,d4e64bc0,a4e94c59,a34e1f0f,ce5004aa,a38df28b,64143f93) Z8(6ef030a1,0ff452af,68914137,6876522c,2c4617fb,20e875f5,aef4ab8a,11a67cb2) Z8(aa9278ac,c50fe4d4,20443758,70168c57,80e9ce25,b9fd1208,289471ce,72911cc8) Z8(113cd60c,11108fe2,4a69d7c8,74c1205d,298cf268,d679b73f,b6947d5d,83f4697f) Z8(039ac61d,f6460510,b1b37584,5920d59f,43a2b6ea,ed497657,85364849,66d1aa22) Z8(14d5906f,6a932879,40be5df2,1851668d,bd024ffc,e6e34fec,6e8e6838,b3b742c5) Z8(2ec5d2c1,68eaa2cb,ddc4ef81,9d7925f1,16135b83,91e43c29,bf4fa142,a793eec2) Z8(29ea5468,d566677f,5828b077,ceca0ddc,51202b2a,4f63dfb5,556908f8,ed5130d0) Z8(760207e0,0342d023,a72b0984,5cbe92ad,e1f18a67,5cc2f7e9,b5e73dba,3451da46) Z8(31e063e4,150ab7b8,c2a09fc7,45d7c5b3,32287c60,a8934e23,64a4500e,030170f9) Z8(4b2f4a33,59908789,a6eb7cb7,cd454826,21e4c2e2,80d6d3ef,f153ccbb,7e442b55) Z8(af0fc01c,692316c6,4b753585,6110deb3,3d378a75,0701a571,e91c3ed4,808a0844) Z8(e964a153,d95c8131,4307887e,c929cabb,577d35af,f4db0f92,dceae0c3,4c6f74d0) Z8(1e8cd325,b0cfc177,6dcdce23,9c5286fd,cf5a05b4,1ab2b51c,a56bdcc4,ab2055a3) Z8(55b9aa62,a96d6df3,35c4dfe0,45035b9b,48943110,708cff46,7bac2f0d,3c13819b) Z8(a940bb46,35049bba,292512ea,14581c62,6d12bc69,2a5cd22f,f0d310c2,6a4073a5) Z8(cd2491a4,a2da8d82,6abda74b,bd1cd1f2,60e4b295,5d84c522,755056ee,a084a550) Z8(2c707edd,270b14d8,5e6fb9cb,676dda04,31f1b05a,9e9ebbc2,80e54399,7496e39b) Z8(9e13641f,6f9f6bcb,80809c50,d5558efa,d58b744f,7157d251,b8ee3a68,26810837) Z8(4e4781e0,107697a0,ddeacb86,9cdc1510,9b3c9755,af4a62d4,8671bdbf,f64e7ea1) Z8(ffe61b91,6368df7e,04236558,b2bc23ff,134bd728,82d9ac95,ff4b15d2,7ccb928f) Z8(d7af2ee0,188c47b0,1a6b10bd,326a25c4,e7e2cefd,1d2218b5,af96e547,868e9dd3) Z8(a7981d8b,0cad2d3d,e8969a85,c068c465,e95b24db,860c7667,dd115774,651e6554) Z8(7f3e76ba,1d46bfc4,de159d4a,5c1570aa,438eea33,a044dbfe,9992f161,02c55f1f) Z8(bb1cc07b,4a40bd4c,f36d7cd7,8dccd03d,7e4c46c9,b5a0ac04,1811f075,42192fe4) Z8(fccff15f,6e763ad5,6d323d48,8f7cdd91,aa884eec,4e4884ac,67f22b1c,581ec996) Z8(72950950,8e2bb317,09b3a293,4bf6bb6a,4b7b265e,88c76347,22d692d8,3c457a27) Z8(eb8b4272,ce1ed91a,9e06796e,e7cc91d6,9fd5aece,bbd4b292,2258d583,0ca93f4c) Z8(0e914edb,27ed815f,4d0d1587,fbc1ef54,b76a9713,7860d5e5,a24d5032,4c475830) Z8(f23c4eb9,a0ecd15b,86d95733,c41dd5b9,cac4fdaa,71f7c144,d89905dc,6b97430c) Z8(0334d312,71af76a9,8a64c167,cc4de934,71ffcba1,0d913b20,e7ab8a1e,e8e442ac) Z8(6f6c02b7,8b88cc78,b88ea7bd,f2a4d943,37a17788,9eedcdcc,d36f0b20,996fc4b6) Z8(803c742e,2de864b5,b909f0e5,a8322cf0,6696ee5f,96534107,af826e24,13f35fde) Z8(7f412556,66b977a6,55aaa035,448853b5,3e5e4be7,14bec8dd,4f251ed0,c29dbe5f) Z8(bb01929c,2a7ee272,82c3df59,8ad27f30,b58467c2,68c2ece0,6bce5542,63e58328) Z8(b762225e,be9d39d0,19fcea3a,97bb2627,f0440dcc,d3b4ccc4,6aa9f743,5c2976b2) Z8(32f33dfd,e5761145,2e7bd637,fea6e485,e3257ffa,5b1b302a,4eb292c2,9fd2187f) Z8(262de78d,0cc5a2e3,98aa62ac,de020f6d,a7fe02a6,bc1e0fd5,aff7407f,ed93c304) Z8(0acdd274,2ac46215,56f6a3d0,8ed91f5e,e4c49e83,89d14d60,9a17fde5,78aca16a) Z8(609f5f0a,819b393e,b169ef5f,d2ec168a,c64f63b7,e1ef1d8a,c65a3456,9032f6a4) Z8(fc4a9833,82f16037,b2dfa98c,47575f29,22712667,2985255f,f2090010,b00d04c9) Z8(9f5d7ada,ef9790b2,7e33c831,7dbfed3f,0eb4126b,28205816,a50a19a1,ece273b4) Z8(5dde89a6,a0e3b550,b95eedb9,1d4f7aed,2b9870c6,e8872878,7c74dcdf,b41b3c4c) Z8(aab19563,03e07187,6296eaca,c40debd4,07516c28,38487fb1,35a646f2,2ed28da6) Z8(1cefd4c2,4362dabd,9d985052,17ff3ca8,dfc27876,023b16f7,70197792,3bc3ee92) Z8(2ed0dff2,e8001193,926744fb,4b0d789b,d867f14b,e929b365,c69cca7a,141bcd47) Z8(d314f763,0138e4d2,aafd5c18,41090e5b,1f21e11f,a851ab21,f3d83369,f0fc1813) Z8(711f1536,403ea525,8522e91e,32a6fbd5,661a49fe,a57ddb82,173c2442,cb83581a) Z8(eb1dd975,c9cb3729,163582a6,ad6ec2cc,18b7112a,838acdfa,adf10dcb,729bff1c) Z8(65a5e013,55b3366a,b0774b7d,507d2f9d,dbdd3280,145cb134,af268b7c,3d52bb5b) Z8(d6e2d6a9,f3fd39a1,471c0889,2083184a,d813215e,8f5c75d4,5557f09a,cc0027b9) Z8(d634bf34,bd5033e8,7e74152c,330b46b6,959f92ef,10392058,9c8eaee5,d71b34fd) Z8(25180b41,13cc439b,02eac0d2,04389498,3b844db1,ee05aeed,525c49ad,9a83b4a5) Z8(4a7a82ed,35f9c367,7d699b98,527af673,c98c7d33,eded9085,8fbf6ea9,927a3134) Z8(53a93da3,1b3c98b3,0fe254e4,67f06b13,5f326a60,6a2e1528,b2481c23,95b1e6f9) Z8(94c5ef9c,0c1a0bc2,1659dfc6,1dbd626f,42725be2,00a12040,70b7c3e2,400dadb3) Z8(ec0dd4f0,9290ce11,14abb1ea,96c47756,6da0bdc3,a6ab686b,a464aa7f,5d9a05f4) Z8(92c6d772,d489312d,27f4dd4f,d79fd147,42f0a8cb,95ebde9d,23dffb38,c34249e5) Z8(c1cde5cc,c6b34229,5c3eeace,ce6aa37d,61528277,b5b90971,beab31f3,43e2c3ff) Z8(dd476ca4,d93eac00,631d7fa1,d3b34a98,0757e574,e85c48de,bb506ba2,19f77b56) Z8(91562fa0,78e80505,25f10da9,14847581,5319d8ea,a96683f8,ad293df6,a650d30d) Z8(a1b2ee52,0ed0522b,47412d3b,66e8c85a,f9fce84a,c287fd8c,0abf6c20,b694e95f) Z8(f771857a,31d88024,4b11a1ad,ab008279,f2573600,f75bebb5,90938fe0,a489c639) Z8(0172ee51,abaee167,5f18d121,fa9766f8,957eddbc,6a90eab6,f9c6bed9,8d2217aa) Z8(3c400bc3,254cc35c,c7180cfa,e5173926,0456d1a5,2abc5a44,21d67b05,89d112c1) Z8(437f0a56,e69f9956,349f598a,3c6ff291,80e0485f,cde8a361,148870b3,d62e1dff) Z8(d8d59e13,02ef6125,9accc88e,3b191d81,0f801318,df7c058f,a5ed1330,f03bea81) Z8(60af3351,646eea92,69a9c557,ca366d1e,b3156d2e,0d0bdf43,5f1129e8,992e8bf0) Z8(d3811316,af00a9f2,ce5aff81,d5f94450,665a5176,d36feba4,e53398f3,5cfe2653) Z8(0355a18e,29fdf716,980febbb,b47d2f6c,881731d1,6fb0091e,4cddc19b,6772e1c1) Z8(f1706f20,8acc9737,7e4462d4,67680548,e9e03333,b19c5671,fc74c12f,59c022cf) Z8(33551a87,3342e32c,8a2b6d5f,f6209124,f1294405,d80ae39d,e6a67730,c6bd28f6) Z8(0e4c824c,68eb3a50,10ca2a2b,e74751da,486f4e5f,175870ad,794ac59a,903f61b9) Z8(9f8f7d4d,46325785,97f70854,1c562c01,d8b88960,31e3228a,d1c102fc,15b75bde) Z8(e15aa6b9,36754cb4,89b6c436,e9e16830,17ea4675,c329d5e4,f85c63b3,1254fcbc) Z8(70890c26,58b263ad,d6f566cb,f89f149c,be17b75d,3e8dc137,4cc6dce3,076f2563) Z8(74b3213a,e7bb5d73,38b2a891,e4038c5b,c51a5719,bfa569b2,7bdc3b85,fbf03e79) Z8(f54cf3c0,69050334,021d6995,93a2857b,1eff36fc,1fcdfcf7,7722f66a,93b57b5b) Z8(f2b67a5e,ca40c491,326da01c,dbdd67fb,e81e5c0d,09017aea,eb0d5cc7,264dc8e6) Z8(c5bad264,ab103b03,e09a562c,8c2e72e2,0b527989,232bda45,3a500289,6d02cf93) Z8(a22e4b09,69c3ea4f,44921ec6,d927cda3,ce0168a0,abd97a02,9ae0cba7,0a2d6d9f) Z8(7878e417,154608ef,a882f91f,e4afd563,c9bf5ee3,24600f29,abdfd66e,8e102c14) Z8(6bbf58d5,a8289f8a,8cfc30a1,83192cd7,1f94dbf5,5ea7706a,713d263d,6c07eb72) Z8(022ca6ab,3c0f125c,7254a724,eb374792,884cbbf3,64a0ce0b,8772be90,c1dad18f) Z8(6a0bf04f,cff82cc3,609a6eff,95733b5d,7cd1cac2,a7b7f91f,da513ff8,4f034af1) Z8(6cd5fbcb,a84e534d,e37b2b4a,19ed4317,3cec4c73,95defa7f,060d1dd5,71306254) Z8(12f84189,4e7d273a,14f97c2d,de5f0476,70cf8c65,beecaf9e,cdb32cfa,637f417a) Z8(782073a4,842dfc6b,e4940071,97b801d7,4cd0cd24,2e568a96,1a0009ed,34b4e2e3) Z8(5a0c42f8,e502493d,5a02be5c,f070b44d,0378a8cb,f3d8e568,e0f705ba,256bfaf0) Z8(03a0b691,85a349ed,43e46bf6,19943080,7eaf0b9c,52b3b24a,71a3c30e,9e301f39) Z8(e8308dbc,e06a8446,13318572,a8879bfd,e74b5e84,a603c464,1f34f494,9c37a164) Z8(4fb60cfa,a50d00ec,4fd82967,054e4f83,15073d26,20ca7e8d,983b85cc,03d0fe5d) Z8(b56e7efc,5eed5612,b4d93d97,fcec56f2,91a0cf29,070e7bd3,00dff9b5,70bb57fe) Z8(55d7eff8,9f49a77a,794f830d,25c3b848,b8da4990,ada20745,2654b37f,265144af) Z8(34e42a6b,520be3a3,699823ac,61bf51f6,0c002042,f51f1c7b,80fc8e46,c0606f2a) Z8(8c251b8a,e8e7bd6e,cbc717d8,9cd1d40b,7d34a02a,c50d8279,3dcd3a75,0fec9746) Z8(c670f4b4,5a111373,e2e4d1f0,2cc3b92d,d155f6ea,fea07acf,40f74410,191dc716) Z8(b86b7fcf,6b94ae7e,ada12be6,4087d371,60dd4981,e06131cf,24faadfb,28ff6564) Z8(90bbeb7e,8c4ff063,93b35d17,b4b8b333,73923df1,7ce5db1a,cbff2326,25e28ea2) Z8(af339d7d,64c694d6,cdfd2033,50437d3a,bb06a66e,cb5baf63,746de41a,e9d50d9d) Z8(56bccec6,d65b3724,c9b0725c,bef678d9,3f2fea8b,f65ced49,cfadc3d3,24185c3e) Z8(7e4c7227,4311ca18,ab8bbb64,15e796af,bce74917,0c3d5c40,1b522997,f0f8da6c) Z8(2505ef80,2c59be2e,c106757d,62697df2,d9ad2a88,7f8d3f0a,8f50e293,01dedd69) Z8(58dcd5e6,9905583a,e23c601c,e402c855,84798d30,4e20cd03,7165fb10,b00e5f0d) Z8(fbcdb8ec,13beb580,69023714,00ab9530,eb029851,06477d02,3886e326,bda7b00a) Z8(703d0212,fd2f294b,6eb4c033,034fe823,32cba47f,65db33b5,970fbc2c,a85c021f) Z8(44a60a19,7c65f7d1,fae32eb1,83c850c1,e148eedb,78bf0282,39d4ba97,65a4f209) Z8(c49874ae,cf40dee1,d74b7750,883b63bc,9f8c24f0,578b9ad2,7d2d7f3c,a1c6c473) Z8(00051d6e,a06290b8,7a13c24d,66635be0,fd38a243,93f68283,71ed0018,80dbd25c) Z8(5954c902,c7d23725,1c237aed,e47b48a8,717ef46d,d6b06ff4,edfcab3d,e2f1957d) Z8(ea805669,eaf865a6,449eb433,17689051,b55ef213,104a5e1b,2a63981a,76ce0781) Z8(e460f597,ddb0e877,4f546447,4fadb74d,152f9b7d,e275eb72,99a0aad9,e765a0f4) Z8(a4bc6402,d2f0a67a,92900736,2cbce2dc,b5c0c205,08c8759f,151e842a,995f6f12) Z8(6f45e357,2d8284c2,79432610,dd893a6b,e318b8b0,5c265da0,be268476,e2aa85b2) Z8(88aa9967,4b3b9e6e,e95d1999,fcd1488b,25d48214,10680303,40b82502,300dd44f) Z8(6a3f038b,370d1619,bc7b21d3,ceba467f,70cbdbc4,c40e2ac9,3d12c6ab,b58bdcce) Z8(cec80eac,b6091f45,08aa8e56,8a5af446,94074f87,67071411,91ccc252,7856983f) Z8(91ee232f,0a08da1c,21380264,8d3c13b7,04f80d79,fc2d7770,6abc3830,a5c618ce) Z8(4e17f04d,9a90f9e5,d5a09d9e,2845dd5b,793db83e,3d48de11,c5f1445a,175515d4) Z8(e952acb9,abaa46a1,a8025dd4,1cd5f2b4,990a8fbc,9c248753,d4f99a0c,fdfc7261) Z8(752adc12,59f6fd8d,d9dad171,83f5f3df,dc154029,313dfeb7,01ad827a,78da7c95) Z8(599e5684,a5e48d8a,b00c2406,d769430e,43617e07,80967fd4,cd8ec19c,ce98e393) Z8(90eb334b,a491de35,0a04d4d2,383c64b6,97ebbcb5,e546436a,b92b6775,bbcc4210) Z8(4969f82e,d7c18b24,23634d43,816bf594,8195ce1d,df034c8f,64985f1c,ae7a7f19) Z8(80cd6f72,20810d01,7a5a32fe,10367aed,0a967562,f5ba33f0,31c6bcb2,cbb595d2) Z8(aef00b97,a1b48779,47604497,a322f4eb,3c2b2aa6,9fad3f7e,87b0fcb4,b1f552a3) Z8(9f82d67a,35a89a62,aa3f885e,afbf8b75,06a3a40f,ac0a1885,f4c62bbe,50b20303) Z8(9ed76ca6,e7785707,4df88a7e,8c1fd4fd,98a047a2,fa58d7af,061787c0,07767c23) Z8(4782585a,9c94e1ef,d3711a7b,98419ba1,cddcacce,bc5ecbd1,91310c15,d286551f) Z8(0b85b306,f808b683,c25008b1,968edaac,1b3229de,2ee8647e,c5d99fa9,4c19f5df) Z8(109dda22,8d24d7bf,0f046e0f,15f858cc,789d16d0,4ea3364c,e7ae120d,9f9694e2) Z8(9f171436,7eccfedc,77e3ee42,bbabfde2,d5efb316,66d7badf,0009e97a,c010c3eb) Z8(ff817fef,cfb7649c,e8229b9b,0a5cfa17,cf5de0f5,6d9374b5,bae0d062,b87a136d) Z8(e7c79266,7faf28d4,4df040c9,1c19a8be,1d8ded62,bdbe3cfa,4c43fcd9,fb801209) Z8(467a303a,6b6e6c02,fce26b37,4e06fb54,f5f20871,a8d91b99,c9e0b52e,bfd615ad) Z8(df16dcfb,af69376e,f169b463,c2272022,77aba281,c5d545c7,3c358b45,66f1917b) Z8(4a094803,2dba58f3,d4c92cfa,5c5e4156,c07b938f,963c382d,ce8a58e3,792bbbc1) Z8(78e9a729,d11e4e54,e0009a97,2c6744af,089be8db,091a4ddf,9287ff07,2de8fcf5) Z8(268a0bb1,82950d4e,632a9163,e466990e,59543ad1,61001e4d,79c0b660,84a3bf85) Z8(514b63d3,9a722c43,ae66a2b0,17a1bf74,5716f721,ef330368,6fe6831c,c76d6bc8) Z8(5e5232a6,9cfe00c1,d6f4f218,f659978c,fc8b0fd1,5d77b5e3,8de6be98,4201fb7c) Z8(c99055a0,a1004438,155b4e14,07167eb6,7951d86d,f22cc5bd,cb918e71,941e12aa) Z8(b6c31e5c,1bcbea79,7ee32c7d,bc19ae7c,3cc01232,9d84b3d6,9053d9ca,8db01b02) Z8(a40ee126,83b9a410,0964b460,a9c43a58,3e6abc1c,59fca0c0,f4aec997,2af3d893) Z8(82da3042,90ee85d6,b505e09e,30913d9f,15b8388a,9c5c7fd8,d0801614,ba8bfa2e) Z8(2f701ea6,12c5993d,06f7cd52,ac275fac,07e79d7b,f22dad17,74a3f540,76079166) Z8(6412cbfc,d10687c0,1a680d7d,7865dc53,2205a7e0,ec621f49,7a5c7111,d158404a) Z8(a2868f81,f7abd59d,1b1b075c,f2507ae6,f1096b47,4db01b6c,296c8177,e7b37fd6) Z8(7aa35c2c,be26f41e,6fae7cfb,5eb4a5bc,82801849,15198367,0930f270,e24fc040) Z8(975e9486,6e79df0b,4f7bc079,fdf487a0,b4e9f0ad,a67baea7,566d3a38,3a470c5d) Z8(46aac656,64dd6277,9bb8785f,15b7a6d1,e959f484,f70ade7a,1b7eac5c,d4080399) Z8(a552eebc,d098a593,22ba9f3b,88efc428,29e1127f,c3e17f91,6fc063fa,e5ce7b30) Z8(5a4bf444,88b5a02a,04651c80,3e2d1062,7f4ea501,93af99c5,f3d1bb13,8274f710) Z8(37353400,b442c3ad,b0b137cc,6b0279c5,34b23225,d3a1bd82,1276449f,1c173a8a) Z8(1998df6b,1ebb3dd2,cf53f2d9,9cf37661,3c55cf69,43477b11,dc047597,983ff05f) Z8(6674b4af,250e2717,442b6861,8ceb428b,c7f486c5,8de9704b,5e0a368c,f38eade7) Z8(dba6d38c,5794fe0d,13c3c48f,ba2a1bd6,c529d6dc,fd1b96f3,719bf81b,bc8f888a) Z8(c95f4727,9a7dfcb0,b76ccb37,9888f0f9,103a8165,d23a05f3,48c39bf1,b713b205) Z8(9420ef6a,9234ea85,fb9efcb8,7d498d66,97387cbe,eb11630c,a908169c,ae97a482) Z8(085f0d45,237d7a6d,bf63c439,72abb1ad,461e22d0,2766f3ff,4146a068,f7b17cfd) Z8(c5c1bee3,1be0932f,3fa309c7,bbf1e733,ff83c39e,5e8ee43e,902157cc,dc3cfeda) Z8(4e992dc8,e8ad9902,e65af6fb,b3f5191e,73d16130,ee55b105,09a39b27,c6fa01e3) Z8(da80f4ef,a638cade,9ed9c610,b6976359,f34c7a84,f8f28119,1931cf1a,83e104d1) Z8(9caf1bbd,d3856309,e70dbeb4,299d8886,d2dd641f,d465a5a4,6b568b49,8042107e) Z8(1f5f0156,2b4519a4,84ba0f04,0d40bf30,460f0242,0a116c3c,b9f83468,fda73cdf) Z8(86c2c15b,7821b36b,c4347132,4f449682,f8b702eb,9ccc6d1e,7711e670,e6d199de) Z8(a96e00d9,ca57511b,0d9956a5,90a991cb,6dd308f2,81a81df1,61cb707e,1c6406ca) Z8(04abb049,831a1f5a,50ac1a43,0cd7bd89,6d076f36,2b34c387,ef6a5ebd,add7b980) Z8(283dc9b7,58118ea5,0957884f,cb6e5527,6aa8054a,a9ea62d9,e56797d1,923b6750) Z8(05e5d0cc,4ac9af77,13c5f541,afb40fe5,444560e6,97257c06,b4bb7615,c3a1cfa2) Z8(ecf6537d,b64199c6,14cac452,21be12d9,2fa57336,a6f0cc3a,eae76dce,b1f36c4d) Z8(830d6926,b3a2b31e,219263c8,036405b6,0a591542,a26f428c,ca195ed4,7493f3cc) Z8(aea7580b,d808e62c,97a8768d,e3090288,a68189ea,d4da66f3,db3b78eb,5408ccb1) Z8(7cac9071,e77c4a09,3f93ba3f,4158580c,f6c2ee39,c139eae5,1a042a4d,fef13297) Z8(65140b3c,ccf8a858,03d7306e,289926cf,02509e47,bd48e29f,09a12dfa,1064e38c) Z8(6003e683,fd2a57d7,826daec5,9e3e63c1,85ee8a83,fc20a3be,1dbb58ff,90a8e5c5) Z8(34fa4278,b8a0ef49,4ac1cd00,dd0412e1,262dcd7b,cf7f7ba6,109291ad,8bea4f6e) Z8(1491d8af,8d2fc0f4,01e4f7cf,ab2be0ff,d44a3e6a,9b489d4c,00000000,00000000) }; int _arb_hypgeom_gamma_coeff_shallow(arf_t c, mag_t err, slong i, slong prec) { slong term_limbs; slong exp, pos; mp_size_t xn; mp_ptr xp; int negative; term_limbs = (prec + FLINT_BITS - 1) / FLINT_BITS; #if FLINT_BITS == 32 term_limbs += (term_limbs & 1); #endif exp = arb_hypgeom_gamma_coeffs[i].exp; pos = arb_hypgeom_gamma_coeffs[i].tab_pos; xn = arb_hypgeom_gamma_coeffs[i].nlimbs; negative = arb_hypgeom_gamma_coeffs[i].negative; #if FLINT_BITS == 32 pos *= 2; xn *= 2; #endif if (term_limbs > xn) return 0; xp = (mp_ptr) arb_hypgeom_gamma_tab_limbs + pos; ARF_EXP(c) = exp; ARF_XSIZE(c) = ARF_MAKE_XSIZE(term_limbs, negative); if (term_limbs == 1) { ARF_NOPTR_D(c)[0] = xp[xn - 1]; } else if (term_limbs == 2) { ARF_NOPTR_D(c)[0] = xp[xn - 2]; ARF_NOPTR_D(c)[1] = xp[xn - 1]; } else { ARF_PTR_D(c) = xp + xn - term_limbs; } if (err != NULL) { MAG_EXP(err) = exp - term_limbs * FLINT_BITS + 1; MAG_MAN(err) = MAG_ONE_HALF; } return 1; } flint-3.1.3/src/arb_hypgeom/gamma_taylor.c000066400000000000000000000437211461254215100205450ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "arb_hypgeom.h" #define DEBUG 0 const double arb_hypgeom_rgamma_d_tab[128] = { 1.0, 0.57721566490153286061, -0.65587807152025388108, -0.042002635034095235529, 0.1665386113822914895, -0.042197734555544336748, -0.0096219715278769735621, 0.0072189432466630995424, -0.0011651675918590651121, -0.00021524167411495097282, 0.00012805028238811618615, -0.000020134854780788238656, -1.2504934821426706573e-6, 1.1330272319816958824e-6, -2.0563384169776071035e-7, 6.1160951044814158179e-9, 5.0020076444692229301e-9, -1.1812745704870201446e-9, 1.0434267116911005105e-10, 7.782263439905071254e-12, -3.6968056186422057082e-12, 5.100370287454475979e-13, -2.0583260535665067832e-14, -5.3481225394230179824e-15, 1.2267786282382607902e-15, -1.1812593016974587695e-16, 1.1866922547516003326e-18, 1.4123806553180317816e-18, -2.2987456844353702066e-19, 1.7144063219273374334e-20, 1.3373517304936931149e-22, -2.0542335517666727893e-22, 2.7360300486079998448e-23, -1.7323564459105166391e-24, -2.3606190244992872873e-26, 1.8649829417172944307e-26, -2.2180956242071972044e-27, 1.2977819749479936688e-28, 1.1806974749665284062e-30, -1.1245843492770880903e-30, 1.277085175140866204e-31, -7.3914511696151408235e-33, 1.134750257554215761e-35, 4.6391346410587220299e-35, -5.3473368184391988751e-36, 3.2079959236133526229e-37, -4.4458297365507568821e-39, -1.3111745188819887129e-39, 1.6470333525438138868e-40, -1.0562331785035812186e-41, 2.6784429826430494784e-43, 2.4247154948517826897e-44, -3.736587834535612554e-45, 2.6283329809401954491e-46, -9.2981759953768862996e-48, -2.3279424186994705986e-49, 6.1696208352443874204e-50, -4.9282955867709899305e-51, 2.1835131834145106973e-52, -1.2187221891475165553e-54, -7.1171088416628746319e-55, 6.9205040543286892535e-56, -3.6764384683566763277e-57, 8.563098056275654328e-59, 4.9630454283668443848e-60, -7.1542945770816152182e-61, 4.5517276890885041177e-62, -1.6183993053202944344e-63, -3.8180434243999502464e-66, 5.1850524119058482295e-66, -4.1671368092239208861e-67, 1.9162906929373887193e-68, -3.8089281324683658733e-70, -2.2063861055924121016e-71, 2.7722310960098954165e-72, -1.5987660478100181057e-73, 5.3197307804174034028e-75, -8.0517461416842390432e-78, -1.2484629810263795113e-77, 9.6431887683992238428e-79, -4.2827980483017479213e-80, 9.5087142369030441861e-82, 2.7131392138694383464e-83, -4.0968779415069156659e-84, 2.3742980019740160598e-85, -8.2770890210072789764e-87, 9.072497609426645865e-89, 1.0645558195026985633e-89, -9.285335619603754493e-91, 4.3333135927203670323e-92, -1.1745606334673315984e-93, -2.6908010752365215433e-96, 2.3898952892036810357e-96, -1.5569361182789167325e-97, 6.0488748201074133757e-99, -1.2273370571029378615e-100, -2.540738850916238751e-102, 3.7708800953170816508e-103, -2.0089261677502892352e-104, 6.6158100911447349361e-106, -9.2404702022121568081e-108, -4.82072018655246532e-109, 4.4938898756858357188e-110, -2.0497789059725778416e-111, 5.7862770569866937508e-113, -4.5696744624334387424e-115, -5.8267365553303743945e-116, 4.2025380699297338056e-117, -1.6889318527713702846e-118, 4.1226213324018604871e-120, -8.2451196593745569675e-123, -5.2036993784470216679e-123, 3.1616685922306712047e-124, -1.1432359131094236326e-125, 2.4359648735131490197e-127, 8.8701584767164321698e-130, -3.6328610892429035156e-130, 1.9485148907440212068e-131, -6.450096583602651512e-133, 1.215186561728963791e-134, 1.0637863819629713691e-136, -2.0430980587447135517e-137, 9.9760876002985183681e-139, -3.0707428945789381066e-140, 5.2091832948433107534e-142, 6.7131589510935005823e-144, -9.434301219575868381e-145, 4.2908149482548296582e-146, }; #define GAMMA_MIN_X 1.4616321449683623413 #define GAMMA_MIN_Y 0.88560319441088870028 /* Crude upper bound for psi(x) for x > 0, adequate for perturbation bounds for gamma. */ double d_abs_digamma_ubound(double x) { if (x <= 1.0) { return (1.0 + 1e-14) / x + 0.57721566490153286061 - x + 1e-14; } else if (x <= GAMMA_MIN_X) { return -1.250380137503405359*x + 1.8275958024049382196 + 1e-14; } else if (x <= 8.0) { return (x - GAMMA_MIN_X) * (1.7581621716802087234 + x * (-0.74622516195984912595 + x * (0.17009872711678924164 + x * (-0.018637559864260712285 + x * 0.00077747045691426195132)))) + 1e-12; } else if (x <= 128.0) { return 0.75334126757115431475 + x * (0.21045131598436795981 + x * (-0.0075387469533717503617 + x * (0.00017308475161765275722 + x * (-2.4025446500822043239e-6 + x * (1.9547402969088507111e-8 + x * (-8.5654894222045481692e-11 + x * 1.5584520745423393038e-13)))))) + 1e-12; } else { return (mag_d_log_upper_bound(x) + 1.0 / x) * (1.0 + 1e-14); } } /* Upper or lower bound (depending on direction) for gamma(x), assuming x > 0, no overflow. */ double _arb_hypgeom_d_gamma(double x, int direction) { double s, t, p; int i, r; if (direction == 1) p = 1 + 1e-14; else p = 1 - 1e-14; if (x < 0.5) { s = d_polyval(arb_hypgeom_rgamma_d_tab, 19, x); s = 1.0 / (s * x); } else if (x <= 1.5) { s = 1.0 / d_polyval(arb_hypgeom_rgamma_d_tab, 19, x - 1.0); } else { r = (int) (x + 0.5); s = d_polyval(arb_hypgeom_rgamma_d_tab, 19, x - r); t = 1.0; for (i = 0; i < r - 1; i++) t *= (x - i - 1) * p; s = t / s; } return s * p; } /* Set res = [a, b]; not checking overflow or underflow. */ void arb_set_interval_d_fast(arb_t res, double a, double b, slong prec) { double mid, rad; if (a > b) { flint_throw(FLINT_ERROR, "arb_set_interval_d_fast: expected a < b\n"); } mid = a + 0.5 * (b - a); rad = (0.5 * (b - a) + (mid * 1e-15)) * (1 + 1e-15); arf_set_d(arb_midref(res), mid); mag_set_d(arb_radref(res), rad); arb_set_round(res, res, prec); } int _arf_increment_fast(arf_t x, slong prec); /* Try to compute gamma(x) using Taylor series. Returns 1 on success, 0 on failure (x too large or precision too large). */ int arb_hypgeom_gamma_taylor(arb_t res, const arb_t x, int reciprocal, slong prec) { double dx, dxerr, log2u, ds, du; slong i, n, wp, r, tail_bound, rad_exp, mid_exp; arf_t s, u, v; short term_prec[ARB_HYPGEOM_GAMMA_TAB_NUM]; int success; #if DEBUG printf("INPUT: "); arb_printd(x, 200); printf("\n"); printf("INPUT prec: %ld\n", prec); #endif /* We don't want to deal with infinities or huge/tiny exponents here. */ if (!ARB_IS_LAGOM(x)) return 0; /* 2^e bounds for the midpoint and radius. */ mid_exp = arf_is_zero(arb_midref(x)) ? WORD_MIN : ARF_EXP(arb_midref(x)); rad_exp = mag_is_zero(arb_radref(x)) ? WORD_MIN : MAG_EXP(arb_radref(x)); /* Containing zero. */ if (rad_exp >= mid_exp && arb_contains_zero(x)) { if (reciprocal) { arb_t t; arb_init(t); arb_add_ui(t, x, 1, prec + 10); if (!arb_contains_zero(t)) { success = arb_hypgeom_gamma_taylor(t, t, reciprocal, prec + 10); if (success) arb_mul(res, x, t, prec); } else { /* todo: accurate wide interval */ success = 0; } arb_clear(t); return success; } else { arb_indeterminate(res); return 1; } } /* Quick exclusion of too large numbers. */ if (mid_exp > 8 || rad_exp > 8) return 0; /* Adjust precision if the input is not precise. */ if (rad_exp != WORD_MIN) prec = FLINT_MIN(prec, -rad_exp + MAG_BITS); prec = FLINT_MAX(prec, 2); /* Midpoint and radius as doubles. */ dx = arf_get_d(arb_midref(x), ARF_RND_NEAR); dxerr = mag_get_d(arb_radref(x)); /* Too large to be efficient (high precision), or gamma(x) may overflow doubles (wide case). */ if (dx + dxerr > 160.0 || dx - dxerr < -160.0) return 0; /* Very close to 0, reduce to gamma(x) = gamma(x + 1) / x. */ if (mid_exp < -32 || (dx - dxerr >= -0.5 && dx - dxerr < ldexp(1.0, -6))) { arb_t t; arb_init(t); arb_add_ui(t, x, 1, prec + 10); #if DEBUG printf("DIVIDING NEAR 0\n"); #endif success = arb_hypgeom_gamma_taylor(t, t, reciprocal, prec + 10); if (success) { if (reciprocal) arb_mul(res, x, t, prec); else arb_div(res, t, x, prec); } arb_clear(t); return success; } /* Nearest (roughly) integer to x, to use as shift for argument reduction to move to the interval [-0.5,0.5]. It's OK that dx is approximate so that the reduced argument will actually lie in [-0.5-eps,0.5+eps]. */ if (dx >= 0.0) r = (slong) (dx + 0.5); else r = -(slong) (-dx + 0.5); /* Tuning cutoff. */ if (prec >= 40) { if (r < -(40 + (prec - 40) / 4)) return 0; if (r > 70 + (prec - 40) / 8) return 0; } /* For negative numbers, reduce to the positive case. */ /* gamma(x) = (-1)^r * gamma(1+x-r) / (rf(1+r-x,-r)*(x-r)) */ /* 1/gamma(x) = (-1)^r * rgamma(1+x-r) * rf(1+r-x,-r) * (x-r) */ if (dx < 0.0) { arb_t t, u, v; arb_init(t); arb_init(u); arb_init(v); arb_sub_si(t, x, r, prec + 10); /* Pole. */ if (!reciprocal && arb_contains_zero(t)) { arb_indeterminate(res); success = 1; } else { arb_add_si(u, x, 1 - r, prec + 10); success = 1; if (reciprocal && !arb_is_positive(u)) { /* todo: accurate wide interval */ success = 0; } success = arb_hypgeom_gamma_taylor(u, u, reciprocal, prec + 10); if (success) { /* Wide bounds for rising factorial. */ if (prec < 44) { double a, b, c, d; c = (-dx + r + 1 - dxerr) * (1 - 1e-14); d = (-dx + r + 1 + dxerr) * (1 + 1e-14); a = b = 1.0; for (i = 0; i < -r; i++) { a = a * ((c + i) * (1 - 1e-15)); b = b * ((d + i) * (1 + 1e-15)); } arb_set_interval_d_fast(v, a, b, 53); if (reciprocal) { arb_mul(res, u, v, prec + 10); arb_mul(res, res, t, prec); } else { arb_div(res, u, v, prec + 10); arb_div(res, res, t, prec); } } else { arb_neg(v, x); arb_add_si(v, v, 1 + r, prec + 10); arb_hypgeom_rising_ui_rec(v, v, -r, prec + 10); arb_mul(v, v, t, prec + 10); if (reciprocal) arb_mul(res, u, v, prec); else arb_div(res, u, v, prec); } if (r % 2) arb_neg(res, res); } } arb_clear(t); arb_clear(u); arb_clear(v); return success; } /* Wide enclosure. */ if (prec < 40 || rad_exp > -16) { double a, b, c; #if DEBUG printf("WIDE CASE\n"); #endif dxerr += ldexp(1.0, mid_exp - 51); dxerr *= (1 + 1e-15); a = (dx - dxerr) * (1 - 1e-15); b = (dx + dxerr) * (1 + 1e-15); if (a >= GAMMA_MIN_X) { a = _arb_hypgeom_d_gamma(a, -1); b = _arb_hypgeom_d_gamma(b, 1); } else if (b <= GAMMA_MIN_X) { c = _arb_hypgeom_d_gamma(a, 1); a = _arb_hypgeom_d_gamma(b, -1); b = c; } else { a = _arb_hypgeom_d_gamma(a, 1); b = _arb_hypgeom_d_gamma(b, 1); b = FLINT_MAX(a, b); a = GAMMA_MIN_Y * (1 - 1e-15); } if (reciprocal) { c = (1.0 / b) * (1 - 1e-15); b = (1.0 / a) * (1 + 1e-15); a = c; } arb_set_interval_d_fast(res, a, b, prec); return 1; } /* Propagated error. */ if (rad_exp == WORD_MIN) { dxerr = 0.0; rad_exp = WORD_MIN; } else { /* First-order relative error estimate plus safety factor to guarantee an upper bound. */ dxerr = MAG_MAN(arb_radref(x)) * ldexp(1.0, -MAG_BITS); dxerr = dxerr * d_abs_digamma_ubound(dx) * 1.001; } #if DEBUG flint_printf("propagated error = %g x 2^%wd\n", dxerr, rad_exp); #endif wp = prec + 6 + FLINT_BIT_COUNT(FLINT_ABS(r)); if (wp > ARB_HYPGEOM_GAMMA_TAB_PREC) return 0; success = 0; arf_init(s); arf_init(u); arf_init(v); /* u = x - r */ arf_sub_si(u, arb_midref(x), r, wp, ARF_RND_DOWN); /* du = dx - r; */ du = arf_get_d(u, ARF_RND_NEAR); /* bound log2(u) */ if (-0.0001 < du && du < 0.0001) log2u = arf_is_zero(u) ? -wp : ARF_EXP(u); else log2u = mag_d_log_upper_bound(du < 0 ? -du : du) * 1.4426950408889634074 * (1 + 1e-14); term_prec[0] = wp; n = 0; for (i = 1; i < ARB_HYPGEOM_GAMMA_TAB_NUM; i++) { tail_bound = arb_hypgeom_gamma_coeffs[i].exp + i * log2u + 5; if (tail_bound <= -wp) { n = i; break; } term_prec[i] = FLINT_MIN(FLINT_MAX(wp + tail_bound, 2), wp); } if (n == 0) { flint_printf("warning: gamma_taylor: unexpected failure\n"); success = 0; goto cleanup; } #if DEBUG printf("COMPUTATION: wp = %ld, du = %g, log2u = %g, n = %ld\n", wp, du, log2u, n); #endif if (wp <= 512 && n <= 128) { ds = 0.0; for (i = n - 1; i >= 1 && term_prec[i] <= 53; i--) { #if DEBUG flint_printf("add term %wd with precision %wd (doubles)\n", i, term_prec[i]); #endif ds = du * ds + arb_hypgeom_rgamma_d_tab[i]; } arf_set_d(s, ds); } else { i = n - 1; } for ( ; i >= 1; i--) { arf_t c; #if DEBUG flint_printf("add term %wd with precision %wd\n", i, term_prec[i]); #endif if (!_arb_hypgeom_gamma_coeff_shallow(c, NULL, i, term_prec[i])) { flint_throw(FLINT_ERROR, "(arb_hypgeom_gamma_taylor):" "prec = %wd, du = %g, log2u = %d, term_prec[%wd] = %wd", prec, du, log2u, i, term_prec[i]); } if (term_prec[i] < wp - 128) { arf_set_round(v, u, term_prec[i], ARF_RND_DOWN); arf_mul(s, s, v, term_prec[i], ARF_RND_DOWN); arf_add(s, s, c, term_prec[i], ARF_RND_DOWN); } else { arf_mul(s, s, u, term_prec[i], ARF_RND_DOWN); arf_add(s, s, c, term_prec[i], ARF_RND_DOWN); } } if (i == 0) { #if DEBUG flint_printf("add term %wd with precision %wd\n", i, term_prec[i]); #endif arf_mul(s, s, u, wp, ARF_RND_DOWN); arf_add_ui(s, s, 1, wp, ARF_RND_DOWN); } if (r == 0 || r == 1) { if (r == 0) arf_mul(s, s, u, wp, ARF_RND_DOWN); if (reciprocal) { arf_set_round(arb_midref(res), s, prec, ARF_RND_DOWN); } else { arf_one(u); arf_div(arb_midref(res), u, s, prec, ARF_RND_DOWN); } arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec - 1); } else if (wp <= 320 || r <= 3) { _arf_increment_fast(u, wp); arf_set(v, u); for (i = 2; i < r; i++) { _arf_increment_fast(u, wp); arf_mul(v, v, u, wp, ARF_RND_DOWN); } if (reciprocal) arf_div(arb_midref(res), s, v, prec, ARF_RND_DOWN); else arf_div(arb_midref(res), v, s, prec, ARF_RND_DOWN); arf_mag_set_ulp(arb_radref(res), arb_midref(res), prec - 1); } else { arb_t t; arb_init(t); _arf_increment_fast(u, wp); arb_set_arf(t, u); arb_hypgeom_rising_ui_rec(t, t, r - 1, wp); if (reciprocal) { arb_set_arf(res, s); arb_div(res, res, t, prec); } else arb_div_arf(res, t, s, prec); arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec - 1); arb_clear(t); } /* Add propagated error. */ if (dxerr != 0) { mag_t err; double dy; dy = arf_get_d(arb_midref(res), ARF_RND_UP); dxerr = dxerr * dy * (1 + 1e-15); MAG_SET_D_2EXP(MAG_MAN(err), MAG_EXP(err), dxerr, rad_exp); mag_add(arb_radref(res), arb_radref(res), err); } success = 1; #if DEBUG printf("OUTPUT: "); arb_printd(res, 200); printf("\n"); #endif cleanup: arf_clear(s); arf_clear(u); arf_clear(v); return success; } flint-3.1.3/src/arb_hypgeom/gamma_upper_fmpq.c000066400000000000000000000260641461254215100214120ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb_hypgeom.h" static void mag_div_fmpq(mag_t res, const mag_t x, const fmpq_t a) { mag_t t; mag_init(t); mag_set_fmpz_lower(t, fmpq_numref(a)); mag_div(res, x, t); mag_set_fmpz(t, fmpq_denref(a)); mag_mul(res, res, t); mag_clear(t); } static void mag_pow_fmpq_fast(mag_t res, const mag_t x, const fmpq_t e) { fmpz_t b; fmpz_init(b); if (mag_cmp_2exp_si(x, 0) >= 0) { fmpz_cdiv_q(b, fmpq_numref(e), fmpq_denref(e)); mag_pow_fmpz(res, x, b); } else { fmpz_fdiv_q(b, fmpq_numref(e), fmpq_denref(e)); mag_pow_fmpz(res, x, b); } fmpz_clear(b); } slong _arb_hypgeom_gamma_upper_fmpq_inf_choose_N_1(mag_t err, const fmpq_t a, const arb_t z, int prefactor, const mag_t abs_tol) { slong N, aa, ab; fmpz_t az1, az2; fmpq_t a1; mag_t t, u; fmpz_init(az1); fmpz_init(az2); fmpq_init(a1); mag_init(t); mag_init(u); fmpz_fdiv_q(az1, fmpq_numref(a), fmpq_denref(a)); fmpz_cdiv_q(az2, fmpq_numref(a), fmpq_denref(a)); if (!fmpz_fits_si(az1) || !fmpz_fits_si(az2)) { mag_inf(err); N = -1; } else { aa = fmpz_get_si(az1); ab = fmpz_get_si(az2); /* prefactor z^(a-1) * exp(-z) */ if (prefactor) { arb_get_mag_lower(t, z); mag_expinv(t, t); fmpq_sub_ui(a1, a, 1); arb_get_mag(u, z); mag_pow_fmpq_fast(u, u, a1); mag_mul(err, t, u); } else { mag_one(err); } if (mag_is_inf(err)) { N = -1; } else { arb_get_mag_lower(t, z); mag_inv(t, t); for (N = 1; ; N++) { mag_mul_ui(u, err, FLINT_MAX(FLINT_ABS(aa - N), FLINT_ABS(ab - N))); mag_mul(u, u, t); if (N >= ab - 1 && mag_cmp(u, abs_tol) < 0) { mag_swap(err, u); break; } /* Stop if terms are increasing, unless a is a positive integer in which case the series will terminate eventually. */ if (mag_cmp(u, err) > 0 && !(aa == ab && aa >= 1)) { mag_inf(err); N = -1; break; } mag_swap(err, u); } } } fmpz_clear(az1); fmpz_clear(az2); mag_clear(t); mag_clear(u); fmpq_clear(a1); return N; } slong _arb_hypgeom_gamma_upper_fmpq_inf_choose_N(mag_t err, const fmpq_t a, const arb_t z, const mag_t abs_tol) { return _arb_hypgeom_gamma_upper_fmpq_inf_choose_N_1(err, a, z, 1, abs_tol); } slong _arb_hypgeom_gamma_upper_fmpq_inf_choose_N_rel(mag_t err, const fmpq_t a, const arb_t z, slong prec) { mag_t tol; slong N; mag_init(tol); mag_set_ui_2exp_si(tol, 1, -prec); N = _arb_hypgeom_gamma_upper_fmpq_inf_choose_N_1(err, a, z, 0, tol); mag_clear(tol); return N; } static void upper_bsplit(arb_t M, arb_t S, arb_t Q, const fmpz_t ap, const fmpz_t aq, const arb_t z, slong na, slong nb, int cont, slong prec) { if (nb - na == 0) { arb_zero(M); arb_zero(S); arb_one(Q); } else if (nb - na == 1) { fmpz_t t; fmpz_init_set(t, ap); fmpz_submul_ui(t, aq, na + 1); fmpz_neg(t, t); arb_set_fmpz(M, t); arb_mul_fmpz(S, z, aq, prec); arb_neg(S, S); arb_set(Q, S); fmpz_clear(t); } else { slong m; arb_t M2, S2, Q2; m = na + (nb - na) / 2; arb_init(M2); arb_init(S2); arb_init(Q2); upper_bsplit(M, S, Q, ap, aq, z, na, m, 1, prec); upper_bsplit(M2, S2, Q2, ap, aq, z, m, nb, cont, prec); /* todo: squaring opt; power table */ arb_mul(S, S, Q2, prec); arb_addmul(S, M, S2, prec); if (cont) arb_mul(M, M, M2, prec); arb_mul(Q, Q, Q2, prec); arb_clear(M2); arb_clear(S2); arb_clear(Q2); } } void _arb_hypgeom_gamma_upper_fmpq_inf_bsplit(arb_t res, const fmpq_t a, const arb_t z, slong N, slong prec) { arb_t M, S, Q; fmpq_t a1; arb_init(M); arb_init(S); arb_init(Q); fmpq_init(a1); N = FLINT_MAX(N, 0); upper_bsplit(M, S, Q, fmpq_numref(a), fmpq_denref(a), z, 0, N, 0, prec); arb_div(S, S, Q, prec); fmpq_sub_ui(a1, a, 1); arb_pow_fmpq(M, z, a1, prec); arb_mul(S, S, M, prec); arb_neg(M, z); arb_exp(M, M, prec); arb_mul(res, S, M, prec); arb_clear(M); arb_clear(S); arb_clear(Q); fmpq_clear(a1); } /* select N and bound error for z**a * exp(-z) / a * sum(z**n / rf(a+1, n)) */ slong _arb_hypgeom_gamma_lower_fmpq_0_choose_N(mag_t err, const fmpq_t a, const arb_t z, const mag_t abs_tol) { slong N, aa, ab, c; fmpz_t az1, az2; mag_t t, u; fmpz_init(az1); fmpz_init(az2); mag_init(t); mag_init(u); fmpz_fdiv_q(az1, fmpq_numref(a), fmpq_denref(a)); fmpz_cdiv_q(az2, fmpq_numref(a), fmpq_denref(a)); if (!fmpz_fits_si(az1) || !fmpz_fits_si(az2)) { mag_inf(err); N = -1; } else { aa = fmpz_get_si(az1); ab = fmpz_get_si(az2); /* prefactor z^a * exp(-z) / a */ arb_get_mag_lower(t, z); mag_expinv(t, t); arb_get_mag(u, z); mag_pow_fmpq_fast(u, u, a); mag_mul(err, t, u); mag_div_fmpq(err, err, a); arb_get_mag(t, z); for (N = 1; ; N++) { c = FLINT_MIN(FLINT_ABS(aa + N), FLINT_ABS(ab + N)); if (c == 0) { fmpq_t q; fmpq_init(q); fmpq_add_ui(q, a, N); mag_div_fmpq(err, err, q); fmpq_clear(q); } else { mag_div_ui(err, err, c); } mag_mul(err, err, t); /* todo: condition can be relaxed */ /* todo: faster check (compare t) */ if ((aa + N) > 0 && mag_cmp(err, abs_tol) < 0) { mag_div_ui(u, t, aa + N); mag_geom_series(u, u, 0); mag_mul(u, err, u); if (mag_cmp(u, abs_tol) < 0) { mag_swap(err, u); break; } } } } fmpz_clear(az1); fmpz_clear(az2); mag_clear(t); mag_clear(u); return N; } /* todo: squaring opt; power table */ static void lower_bsplit(arb_t M, arb_t S, arb_t Q, const fmpz_t ap, const fmpz_t aq, const arb_t z, slong na, slong nb, int cont, slong prec) { if (nb - na == 0) { arb_zero(M); arb_zero(S); arb_one(Q); } else if (nb - na == 1) { fmpz_t t; fmpz_init_set(t, ap); fmpz_addmul_ui(t, aq, na + 1); arb_set_fmpz(S, t); arb_set(Q, S); arb_mul_fmpz(M, z, aq, prec); fmpz_clear(t); } else { slong m; arb_t M2, S2, Q2; m = na + (nb - na) / 2; arb_init(M2); arb_init(S2); arb_init(Q2); lower_bsplit(M, S, Q, ap, aq, z, na, m, 1, prec); lower_bsplit(M2, S2, Q2, ap, aq, z, m, nb, cont, prec); arb_mul(S, S, Q2, prec); arb_addmul(S, M, S2, prec); if (cont) arb_mul(M, M, M2, prec); arb_mul(Q, Q, Q2, prec); arb_clear(M2); arb_clear(S2); arb_clear(Q2); } } void _arb_hypgeom_gamma_lower_fmpq_0_bsplit(arb_t res, const fmpq_t a, const arb_t z, slong N, slong prec) { arb_t M, S, Q; arb_init(M); arb_init(S); arb_init(Q); N = FLINT_MAX(N, 0); lower_bsplit(M, S, Q, fmpq_numref(a), fmpq_denref(a), z, 0, N, 0, prec); arb_div(S, S, Q, prec); arb_pow_fmpq(M, z, a, prec); arb_mul(S, S, M, prec); arb_neg(M, z); arb_exp(M, M, prec); arb_mul(S, S, M, prec); arb_div_fmpz(S, S, fmpq_numref(a), prec); arb_mul_fmpz(res, S, fmpq_denref(a), prec); arb_clear(M); arb_clear(S); arb_clear(Q); } /* bounded by 1/z^n * sum z^k / k! */ slong _arb_hypgeom_gamma_upper_singular_si_choose_N(mag_t err, slong n, const arb_t z, const mag_t abs_tol) { slong k; mag_t t, u, zm; mag_init(t); mag_init(u); mag_init(zm); arb_get_mag(zm, z); arb_get_mag_lower(t, z); mag_inv(t, t); mag_pow_ui(t, t, n); for (k = 1; ; k++) { mag_mul(t, t, zm); mag_div_ui(t, t, k); if (mag_cmp(t, abs_tol) < 0) { mag_div_ui(u, zm, k); mag_geom_series(u, u, 0); mag_mul(u, t, u); if (mag_cmp(u, abs_tol) < 0) { mag_swap(err, t); break; } } } mag_clear(t); mag_clear(u); mag_clear(zm); return k; } static void singular_bsplit(arb_t M, arb_t S, arb_t Q, slong n, const arb_t z, slong na, slong nb, int cont, slong prec) { if (nb - na == 0) { arb_zero(M); arb_zero(S); arb_one(Q); } else if (nb - na == 1) { fmpz_t t; slong k; k = na; if (k == n) arb_neg(M, z); else arb_mul_si(M, z, n - k, prec); arb_set_si(S, (k != n) ? (k + 1) : 0); fmpz_init_set_si(t, k + 1); if (k != n) fmpz_mul_si(t, t, k - n); arb_set_fmpz(Q, t); fmpz_clear(t); } else { slong m; arb_t M2, S2, Q2; m = na + (nb - na) / 2; arb_init(M2); arb_init(S2); arb_init(Q2); singular_bsplit(M, S, Q, n, z, na, m, 1, prec); singular_bsplit(M2, S2, Q2, n, z, m, nb, cont, prec); arb_mul(S, S, Q2, prec); arb_addmul(S, M, S2, prec); if (cont) arb_mul(M, M, M2, prec); arb_mul(Q, Q, Q2, prec); arb_clear(M2); arb_clear(S2); arb_clear(Q2); } } void _arb_hypgeom_gamma_upper_singular_si_bsplit(arb_t res, slong n, const arb_t z, slong N, slong prec) { arb_t M, S, Q; arb_init(M); arb_init(S); arb_init(Q); N = FLINT_MAX(N, 0); singular_bsplit(M, S, Q, n, z, 0, N, 0, prec); /* (-1)**n/fac(n) * (digamma(n+1) - ln(z)) - (S/Q)/z**n */ arb_pow_ui(M, z, n, prec); arb_mul(Q, Q, M, prec); arb_div(S, S, Q, prec); arb_set_ui(M, n + 1); arb_digamma(M, M, prec); arb_log(Q, z, prec); arb_sub(M, M, Q, prec); arb_fac_ui(Q, n, prec); arb_div(M, M, Q, prec); if (n & 1) arb_neg(M, M); arb_sub(res, M, S, prec); arb_clear(M); arb_clear(S); arb_clear(Q); } flint-3.1.3/src/arb_hypgeom/gamma_upper_fmpq_step_bsplit.c000066400000000000000000000175041461254215100240210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "arb_mat.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define ceil __builtin_ceil #else # include #endif static void taylor_M(mag_t M, const arb_t a, const arb_t z, const mag_t x, slong Rexp) { arb_t t, u; arb_init(t); arb_init(u); arb_sub_ui(u, a, 1, 53); arb_sgn(t, u); arb_mul_2exp_si(t, t, Rexp); arb_add(t, z, t, 53); arb_pow(t, t, u, 53); arb_one(u); arb_mul_2exp_si(u, u, Rexp); arb_sub(u, u, z, 53); arb_exp(u, u, 53); arb_mul(t, t, u, 53); arb_get_mag(M, t); arb_clear(t); arb_clear(u); } /* choose N such that M * C^N / (1 - C) <= tol */ /* todo: fix */ static slong mag_geom_choose_N(const mag_t M, const mag_t C, const mag_t tol) { mag_t t, u; slong N; if (mag_is_finite(M) && mag_is_zero(C)) return 1; /* N = log(M / ((1 - C) tol)) / log(1/C) */ mag_init(t); mag_init(u); mag_one(t); mag_sub_lower(t, t, C); mag_mul_lower(t, t, tol); mag_div(t, M, t); mag_log(t, t); mag_inv_lower(u, C); mag_log_lower(u, u); mag_div(t, t, u); N = ceil(mag_get_d(t)); N = FLINT_MAX(N, 1); mag_clear(t); mag_clear(u); return N; } static void taylor_bound(mag_t err, const arb_t a, const arb_t z, const mag_t x, slong Rexp, slong N) { mag_t C, M; mag_init(C); mag_init(M); /* C = x / R */ mag_mul_2exp_si(C, x, -Rexp); /* M R C^n / (1 - C) / N */ mag_geom_series(err, C, N); if (!mag_is_inf(err)) { taylor_M(M, a, z, x, Rexp); mag_mul(err, err, M); mag_mul_2exp_si(err, err, Rexp); mag_div_ui(err, err, N); } mag_clear(C); mag_clear(M); } static slong taylor_N(const arb_t a, const arb_t z, const mag_t x, slong Rexp, const mag_t abs_tol) { mag_t C, M; slong N; mag_init(C); mag_init(M); /* C = x / R */ mag_mul_2exp_si(C, x, -Rexp); if (mag_cmp_2exp_si(C, 0) < 0) { taylor_M(M, a, z, x, Rexp); mag_mul_2exp_si(M, M, Rexp); N = mag_geom_choose_N(M, C, abs_tol); } else { N = WORD_MAX; } mag_clear(C); mag_clear(M); return N; } static void arb_hypgeom_gamma_upper_taylor_choose(slong * res_N, mag_t err, const arb_t a, const arb_t z, const mag_t x, const mag_t abs_tol) { slong N, New; mag_t zlow; slong Rexp; mag_init(zlow); arb_get_mag_lower(zlow, z); Rexp = 0; while (mag_cmp_2exp_si(zlow, Rexp + 1) < 0) Rexp--; N = taylor_N(a, z, x, Rexp, abs_tol); while (N > 1 && mag_cmp_2exp_si(x, Rexp - 1) < 0) { New = taylor_N(a, z, x, Rexp - 1, abs_tol); if (New <= N) { Rexp = Rexp - 1; N = New; } else { break; } } if (Rexp == 0) { while (N > 1 && mag_cmp_2exp_si(zlow, Rexp + 1) > 0) { New = taylor_N(a, z, x, Rexp + 1, abs_tol); if (New <= N) { Rexp = Rexp + 1; N = New; } else { break; } } } *res_N = N; taylor_bound(err, a, z, x, Rexp, N); if (mag_cmp(err, abs_tol) > 0) { /* TODO: Find a nice way to print this using flint_throw */ printf("err = "); mag_printd(err, 10); printf("\nabs_tol = "); mag_printd(abs_tol, 10); printf("\na = "); arb_printd(a, 10); printf("\nz = "); arb_printd(z, 10); printf("\nx = "); mag_printd(x, 10); flint_abort(); } mag_clear(zlow); } static void gamma_upper_taylor_bsplit(arb_mat_t M, arb_t Q, const fmpz_t ap, const fmpz_t aq, const arb_t z0, const arb_t x, const arb_t x2, slong a, slong b, int cont, slong prec) { if (b - a == 0) { arb_mat_one(M); } else if (b - a == 1) { slong n; fmpz_t t; n = a; fmpz_init(t); /* Q = -z0*(n+1)*(n+2)*aq */ fmpz_mul2_uiui(t, aq, n + 1, n + 2); arb_mul_fmpz(Q, z0, t, prec); arb_neg(Q, Q); /* x Q */ arb_mul(arb_mat_entry(M, 0, 1), Q, x, prec); /* aq n x */ fmpz_mul_ui(t, aq, n); arb_mul_fmpz(arb_mat_entry(M, 1, 0), x, t, prec); /* x*(-ap + aq*(n + z0 + 1))*(n + 1) */ arb_add_ui(arb_mat_entry(M, 1, 1), z0, n + 1, prec); arb_mul_fmpz(arb_mat_entry(M, 1, 1), arb_mat_entry(M, 1, 1), aq, prec); arb_sub_fmpz(arb_mat_entry(M, 1, 1), arb_mat_entry(M, 1, 1), ap, prec); arb_mul_ui(arb_mat_entry(M, 1, 1), arb_mat_entry(M, 1, 1), n + 1, prec); arb_mul(arb_mat_entry(M, 1, 1), arb_mat_entry(M, 1, 1), x, prec); arb_set(arb_mat_entry(M, 2, 0), Q); arb_set(arb_mat_entry(M, 2, 2), Q); fmpz_clear(t); } else { arb_mat_t M1, M2; arb_t Q2; slong m; arb_mat_init(M1, 3, 3); arb_mat_init(M2, 3, 3); arb_init(Q2); m = a + (b - a) / 2; gamma_upper_taylor_bsplit(M1, Q, ap, aq, z0, x, x2, a, m, 1, prec); gamma_upper_taylor_bsplit(M2, Q2, ap, aq, z0, x, x2, m, b, cont, prec); if (cont) { /* todo: parallel slowdown; arb_mat_mul needs retuning */ arb_mat_mul_classical(M, M2, M1, prec); } else { arb_mat_transpose(M1, M1); arb_dot(arb_mat_entry(M, 2, 0), NULL, 0, arb_mat_entry(M1, 0, 0), 1, arb_mat_entry(M2, 2, 0), 1, 3, prec); arb_dot(arb_mat_entry(M, 2, 1), NULL, 0, arb_mat_entry(M1, 1, 0), 1, arb_mat_entry(M2, 2, 0), 1, 3, prec); arb_dot(arb_mat_entry(M, 2, 2), NULL, 0, arb_mat_entry(M1, 2, 0), 1, arb_mat_entry(M2, 2, 0), 1, 3, prec); } arb_mul(Q, Q2, Q, prec); arb_mat_clear(M1); arb_mat_clear(M2); arb_clear(Q2); } } /* Given Gz0 = Gamma(a, z0) and expmz0 = exp(-z0), compute Gz1 = Gamma(a, z1) */ void _arb_gamma_upper_fmpq_step_bsplit(arb_t Gz1, const fmpq_t a, const arb_t z0, const arb_t z1, const arb_t Gz0, const arb_t expmz0, const mag_t abs_tol, slong prec) { arb_t x, Q, a_real; arb_mat_t M; mag_t xmag, err; slong N; fmpq_t a1; if (arb_is_zero(z0)) { mag_init(err); arb_init(x); N = _arb_hypgeom_gamma_lower_fmpq_0_choose_N(err, a, z1, abs_tol); _arb_hypgeom_gamma_lower_fmpq_0_bsplit(Gz1, a, z1, N, prec); arb_add_error_mag(Gz1, err); arb_sub(Gz1, Gz0, Gz1, prec); arb_clear(x); mag_clear(err); return; } mag_init(xmag); mag_init(err); arb_init(x); arb_init(Q); arb_init(a_real); fmpq_init(a1); arb_mat_init(M, 3, 3); arb_sub(x, z1, z0, prec); arb_get_mag(xmag, x); arb_set_fmpq(a_real, a, 53); arb_hypgeom_gamma_upper_taylor_choose(&N, err, a_real, z0, xmag, abs_tol); gamma_upper_taylor_bsplit(M, Q, fmpq_numref(a), fmpq_denref(a), z0, x, NULL, 0, N, 0, prec); arb_mul(arb_mat_entry(M, 2, 0), arb_mat_entry(M, 2, 0), Gz0, prec); fmpq_sub_ui(a1, a, 1); arb_pow_fmpq(arb_mat_entry(M, 0, 0), z0, a1, prec); arb_mul(arb_mat_entry(M, 0, 0), arb_mat_entry(M, 0, 0), expmz0, prec); arb_submul(arb_mat_entry(M, 2, 0), arb_mat_entry(M, 2, 1), arb_mat_entry(M, 0, 0), prec); arb_div(Gz1, arb_mat_entry(M, 2, 0), Q, prec); arb_add_error_mag(Gz1, err); mag_clear(xmag); mag_clear(err); arb_clear(x); arb_clear(Q); arb_clear(a_real); fmpq_clear(a1); arb_mat_clear(M); } flint-3.1.3/src/arb_hypgeom/gamma_upper_integration.c000066400000000000000000000022121461254215100227570ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_gamma_upper_integration(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec) { arb_t t, u; arb_init(t); arb_init(u); arb_one(t); arb_add_ui(u, s, 1, prec); arb_hypgeom_u_integration(u, t, u, z, prec); if (arb_is_finite(u)) { if (regularized != 2) { arb_pow(t, z, s, prec); arb_mul(u, u, t, prec); if (regularized == 1) { arb_rgamma(t, s, prec); arb_mul(u, u, t, prec); } } arb_neg(t, z); arb_exp(t, t, prec); arb_mul(res, t, u, prec); } else { arb_indeterminate(res); } arb_clear(t); arb_clear(u); } flint-3.1.3/src/arb_hypgeom/gamma_upper_series.c000066400000000000000000000051261461254215100217350ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_gamma_upper_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec) { arb_t c; arb_init(c); arb_hypgeom_gamma_upper(c, s, h, regularized, prec); hlen = FLINT_MIN(hlen, n); if (hlen == 1) { _arb_vec_zero(g + 1, n - 1); } else { arb_ptr t, u, v; arb_ptr w = NULL; t = _arb_vec_init(n); u = _arb_vec_init(n); v = _arb_vec_init(n); if (regularized == 2) { w = _arb_vec_init(n); arb_neg(t, s); _arb_poly_pow_arb_series(w, h, hlen, t, n, prec); } /* Gamma(s, h(x)) = -integral(h'(x) h(x)^(s-1) exp(-h(x)) */ arb_sub_ui(u, s, 1, prec); _arb_poly_pow_arb_series(t, h, hlen, u, n, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_mullow(v, t, n, u, hlen - 1, n, prec); _arb_vec_neg(t, h, hlen); _arb_poly_exp_series(t, t, hlen, n, prec); _arb_poly_mullow(g, v, n, t, n, n, prec); _arb_poly_integral(g, g, n, prec); _arb_vec_neg(g, g, n); if (regularized == 1) { arb_rgamma(t, s, prec); _arb_vec_scalar_mul(g, g, n, t, prec); } else if (regularized == 2) { _arb_vec_set(u, g, n); _arb_poly_mullow(g, u, n, w, n, n, prec); _arb_vec_clear(w, n); } _arb_vec_clear(t, n); _arb_vec_clear(u, n); _arb_vec_clear(v, n); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_gamma_upper_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, n); if (hlen == 0) { arb_t t; arb_init(t); _arb_hypgeom_gamma_upper_series(g->coeffs, s, t, 1, regularized, n, prec); arb_clear(t); } else { _arb_hypgeom_gamma_upper_series( g->coeffs, s, h->coeffs, hlen, regularized, n, prec); } _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/gamma_upper_sum_rs.c000066400000000000000000000065471461254215100217630ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define log __builtin_log #else # include #endif static slong asymp_prec(slong k, double logdz, slong prec) { double gain; if (prec <= 128) return prec; if (k <= 5) return prec; gain = (k * logdz - (k * (log(k) - 1.0))) * 1.4426950408889634 - 4; gain = FLINT_MAX(gain, 0); prec = prec - gain; prec = FLINT_MAX(prec, 32); return prec; } void _arb_hypgeom_gamma_upper_sum_rs_1(arb_t res, ulong p, ulong q, const arb_t z, slong N, slong prec) { slong m, i, j, k, jlen, jbot, jtop, wp; double dz, logdz; mp_limb_t c, chi, clo; arb_t s, t; arb_ptr zpow; mp_ptr cs; m = n_sqrt(N); m = FLINT_MAX(m, 2); k = N - 1; j = k % m; jlen = 0; jbot = j; if (arf_cmpabs_2exp_si(arb_midref(z), prec) >= 0) { logdz = ARF_EXP(arb_midref(z)) * log(2); } else if (arf_cmpabs_2exp_si(arb_midref(z), -32) >= 0) { dz = arf_get_d(arb_midref(z), ARF_RND_UP); dz = fabs(dz); logdz = log(dz); } else if (arf_cmpabs_2exp_si(arb_midref(z), -prec) <= 0) { logdz = -prec * log(2); } else { logdz = ARF_EXP(arb_midref(z)) * log(2); } arb_init(s); arb_init(t); zpow = _arb_vec_init(m + 1); cs = flint_malloc(sizeof(mp_limb_t) * (m + 1)); arb_mul_ui(zpow + m, z, q, prec); arb_inv(zpow + m, zpow + m, prec); _arb_vec_set_powers(zpow, zpow + m, m + 1, prec); while (k >= 0) { /* Find run of coefficients whose product fits in a limb */ jlen = 1; jtop = jbot = k; if (jtop > 0) { c = p + q * (jtop - 1); while (jlen <= j) { if (jbot >= 2) { umul_ppmm(chi, clo, c, p + q * (jbot - 2)); if (chi != 0) break; c = clo; } jbot--; jlen++; } } if (jbot != jtop - jlen + 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* Factors between jbot and jtop inclusive */ if (jbot == 0) cs[0] = 1; else cs[0] = p + q * (jbot - 1); for (i = 1; i < jlen; i++) cs[i] = cs[i - 1] * (p + q * (jbot + i - 1)); wp = asymp_prec(k - jlen, logdz, prec); /* todo: special case jlen == 1 */ arb_add(t, s, zpow + j, wp); arb_swap(zpow + j, t); arb_dot_ui(s, NULL, 0, zpow + j - jlen + 1, 1, cs, 1, jlen, wp); arb_swap(zpow + j, t); k -= jlen; j -= (jlen - 1); if (j == 0 && k >= 1) { arb_mul(s, s, zpow + m, wp); j = m - 1; } else { j--; } } arb_swap(res, s); _arb_vec_clear(zpow, m + 1); arb_clear(s); arb_clear(t); flint_free(cs); } flint-3.1.3/src/arb_hypgeom/legendre_p.c000066400000000000000000000024171461254215100201720ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void arb_hypgeom_legendre_p(arb_t res, const arb_t n, const arb_t m, const arb_t z, int type, slong prec) { if (arb_is_zero(m) && arb_is_int(n) && arf_sgn(arb_midref(n)) >= 0 && arf_cmpabs_2exp_si(arb_midref(n), FLINT_BITS - 1) < 0) { arb_hypgeom_legendre_p_ui(res, NULL, arf_get_si(arb_midref(n), ARF_RND_DOWN), z, prec); } else { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); arb_set(acb_realref(t), n); arb_set(acb_realref(u), m); arb_set(acb_realref(v), z); acb_hypgeom_legendre_p(t, t, u, v, type, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } } flint-3.1.3/src/arb_hypgeom/legendre_p_ui.c000066400000000000000000000326361461254215100206750ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp # define fabs __builtin_fabs # define log __builtin_log # define sqrt __builtin_sqrt #else # include #endif /* todo: improve for small k */ static double log2_bin_uiui_fast(ulong n, ulong k) { static const float htab[] = {0.2007, 0.3374, 0.4490, 0.5437, 0.6254, 0.6963, 0.7580, 0.8114, 0.8572, 0.8961, 0.9285, 0.9545, 0.9746, 0.9888, 0.9973, 1.0}; if (k == 0 || k >= n) return 0; if (k > n / 2) k = n - k; k = (32.0 * k) / n; return n * htab[FLINT_MIN(k, 15)]; } /* x is unused but part of the API */ void arb_hypgeom_legendre_p_ui_deriv_bound(mag_t dp, mag_t dp2, ulong n, const arb_t x, const arb_t x2sub1) { mag_t c, t, u; mag_init(c); mag_init(t); mag_init(u); arb_get_mag_lower(t, x2sub1); mag_rsqrt(t, t); /* t >= 1/(1-x^2)^(1/2) */ mag_mul_ui(u, t, n); /* u >= n/(1-x^2)^(1/2) */ mag_set_ui_2exp_si(c, 409, -8); /* c >= 2^(3/2)/sqrt(pi) */ mag_sqrt(dp, u); mag_mul(dp, dp, t); mag_mul(dp, dp, c); /* dp >= c*sqrt(n)/(1-x^2)^(3/4) */ mag_mul(dp2, dp, u); mag_mul_2exp_si(dp2, dp2, 1); /* dp2 >= 2*c*n^(3/2)/(1-x^2)^(5/4) */ mag_set_ui(t, n); mag_add_ui(t, t, 1); mag_mul(t, t, t); /* t >= (n+1)^2 */ mag_mul_2exp_si(u, t, -1); /* u >= (n+1)^2/2 */ mag_min(dp, dp, u); /* |P'(x)| <= dp */ mag_mul(t, t, t); mag_mul_2exp_si(u, t, -3); mag_min(dp2, dp2, u); /* |P''(x)| <= dp2 */ mag_clear(c); mag_clear(t); mag_clear(u); } void arb_hypgeom_legendre_p_ui(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong prec) { arb_t xsub1, x2sub1; double xx, xxsub1, cancellation_zero, cancellation_one; double cost_zero, cost_one, cost_asymp; double log2x, log2u, tolerance, asymp_error; double yy, log2nsy, log2k, size; slong wp; slong d, k, K_zero, K_one, K_asymp; int basecase_ok; if (!arb_is_finite(x) || n > UWORD_MAX / 4) { if (res != NULL) arb_indeterminate(res); if (res_prime != NULL) arb_indeterminate(res_prime); return; } if (arf_sgn(arb_midref(x)) < 0) { arb_t t; arb_init(t); arb_neg(t, x); arb_hypgeom_legendre_p_ui(res, res_prime, n, t, prec); if (n % 2 == 1 && res != NULL) arb_neg(res, res); if (n % 2 == 0 && res_prime != NULL) arb_neg(res_prime, res_prime); arb_clear(t); return; } if (arb_is_one(x) && n < UWORD_MAX) { if (res != NULL) arb_set(res, x); if (res_prime != NULL) { arb_set_ui(res_prime, n); arb_mul_ui(res_prime, res_prime, n + 1, prec); arb_mul_2exp_si(res_prime, res_prime, -1); } return; } if (n == 0) { if (res != NULL) arb_one(res); if (res_prime != NULL) arb_zero(res_prime); return; } if (n == 1) { if (res != NULL) arb_set_round(res, x, prec); if (res_prime != NULL) arb_one(res_prime); return; } xx = arf_get_d(arb_midref(x), ARF_RND_UP); /* Use basecase recurrence? */ /* The following tests are not very elegant, and not completely accurate either, but they are fast in the common case. */ if (res_prime != NULL) { basecase_ok = ((xx < 0.999999 && n < 10 && prec < 2000) || (xx < 0.999999 && n < 50 && prec < 1000) || (xx < 0.9999 && n < 100 && prec < 1000) || (xx < 0.999 && n < 350 && prec < 1000) || (xx < 0.9 && n < 400 && prec < 1000)) && ((xx > 0.00001 && n < 10 && prec < 2000) || (xx > 0.00001 && n < 60 && prec < 1000) || (xx > 0.01 && n < 200 && prec < 1000) || (xx > 0.1 && n < 400 && prec < 1000)); /* the recurrence also performs better when n ~= prec */ if (!basecase_ok) basecase_ok = (xx > 0.1 && xx < 0.99 && n < 800 && prec > 0.4 * n && prec < 1.5 * n); } else if (prec < 500) { basecase_ok = ((xx < 0.999999 && n < 20) || (xx < 0.999 && n < 60) || (xx < 0.9 && n < 100)) && ((xx > 0.00001 && n < 20) || (xx > 0.01 && n < 60) || (xx > 0.1 && n < 100)); if (!basecase_ok) basecase_ok = (xx > 0.1 && xx < 0.99 && n < 300 && prec > 0.4 * n && prec < 1.5 * n); } else { basecase_ok = 0; } if (basecase_ok) { mag_t t; mag_init(t); arb_get_mag(t, x); if (mag_cmp_2exp_si(t, 0) >= 0) basecase_ok = 0; mag_clear(t); } if (basecase_ok) { arb_hypgeom_legendre_p_ui_rec(res, res_prime, n, x, prec); return; } arb_init(xsub1); arb_init(x2sub1); arb_sub_ui(xsub1, x, 1, prec + 10); arb_mul(x2sub1, x, x, 2 * prec); arb_sub_ui(x2sub1, x2sub1, 1, prec + 10); arb_neg(x2sub1, x2sub1); /* use series at 1 unless |x| < 1-eps */ if (!arb_is_negative(xsub1) || arf_cmp_d(arb_midref(xsub1), ldexp(1.0, -2 * FLINT_BIT_COUNT(n))) > 0) { if (arf_cmp_d(arb_midref(xsub1), 2.0) >= 0) { if (n < 10000.0 * prec && n < UWORD_MAX / 4) K_one = n + 1; else K_one = 1; } else /* check for early convergence */ { xxsub1 = arf_get_d(arb_midref(xsub1), ARF_RND_UP); log2u = log(fabs(xxsub1) * 0.5) * 1.44269504088896; if (log2u < -30) log2u = arf_abs_bound_lt_2exp_si(arb_midref(xsub1)) - 1.0; K_one = n + 1; K_one = FLINT_MIN(K_one, 100000.0 * prec); K_one = FLINT_MIN(K_one, UWORD_MAX / 4); size = 0.0; if (n * (2.0 + log2u) < -prec) { for (k = 1; k < K_one; k = FLINT_MAX(k+1, k*1.05)) { size = log2_bin_uiui_fast(n, k) + log2_bin_uiui_fast(n + k, k) + k * log2u; if (size < -prec) { K_one = k; break; } } } } arb_hypgeom_legendre_p_ui_one(res, res_prime, n, x, K_one, prec); } else /* guaranteed to have |x| < 1 */ { cost_zero = 1e100; cost_one = 1e100; cost_asymp = 1e100; xx = FLINT_MAX(xx, 1e-50); xxsub1 = arf_get_d(arb_midref(xsub1), ARF_RND_UP); /* Estimate cancellation for series expansion at 0. */ /* |P_n(xi)| ~= (x+sqrt(1+x^2))^n. */ cancellation_zero = n * log(xx + sqrt(1.0 + xx * xx)) * 1.44269504088896; cancellation_zero = FLINT_MIN(cancellation_zero, 1.272 * n); cancellation_zero = FLINT_MAX(cancellation_zero, 0.0); /* Estimate cancellation for series expansion at 1. */ /* For x >= 1, P_n(x) ~= I_0(n*sqrt(2(x-1))) ~= exp(n*sqrt(2(x-1))) */ if (xxsub1 >= 0.0) { cancellation_one = 0.0; } else { cancellation_one = n * sqrt(2.0*fabs(xxsub1)) * 1.44269504088896; cancellation_one = FLINT_MIN(cancellation_one, 2.0 * n); cancellation_one = FLINT_MAX(cancellation_one, 0.0); } d = n / 2; K_zero = d + 1; K_one = n + 1; K_asymp = 1; asymp_error = 0.0; wp = 1.01 * prec + FLINT_BIT_COUNT(n); tolerance = -wp; /* adjust for relative tolerance near 0 */ if (n % 2) { tolerance += arf_abs_bound_lt_2exp_si(arb_midref(x)); } if (n > 10) { /* look for early truncation of series at 1 */ log2u = log(fabs(xxsub1) * 0.5) * 1.44269504088896; if (log2u < -30) log2u = arf_abs_bound_lt_2exp_si(arb_midref(xsub1)) - 1.0; log2x = log(fabs(xx)) * 1.44269504088896; if (log2x < -30) log2x = arf_abs_bound_lt_2exp_si(arb_midref(x)); if (n * (2.0 + log2u) < tolerance) { for (k = 1; k < K_one; k = FLINT_MAX(k+1, k*1.05)) { size = log2_bin_uiui_fast(n, k) + log2_bin_uiui_fast(n + k, k) + k * log2u; if (size < tolerance) { K_one = k; break; } } } /* look for early truncation of series at 0 */ if (n * (1.0 + log2x) < tolerance) { for (k = 1; k < K_zero; k = FLINT_MAX(k+1, k*1.05)) { size = log2_bin_uiui_fast(n, d - k) + log2_bin_uiui_fast(n+1+2*k, n) - n + 2.0 * k * log2x; if (size < tolerance) { K_zero = k; break; } } } /* look for possible convergence of asymptotic series */ /* requires information about y = sqrt(1-x^2) */ yy = arf_get_d(arb_midref(x2sub1), ARF_RND_DOWN); yy = sqrt(FLINT_MAX(0.0, yy)); log2nsy = log(2.0 * n * yy) * 1.44269504088896; cost_zero = (prec + cancellation_zero) * K_zero; cost_one = (prec + cancellation_one) * K_one; for (k = 1; k < n && prec * k < FLINT_MIN(cost_zero, cost_one); k = FLINT_MAX(k + 1, k * 1.05)) { /* todo: better account for prefactor in the asymptotic series? */ log2k = log(k) * 1.44269504088896; size = 3.0 + k * (log2k - 1.43); /* estimate K! */ size -= k * log2nsy; /* 1/(2n sin(theta))^K */ if (size < asymp_error) { asymp_error = size; K_asymp = k; } if (size < tolerance) { break; } } } cost_zero = (prec + cancellation_zero) * K_zero; cost_one = (prec + cancellation_one) * K_one; cost_asymp = (prec + 0.0) * K_asymp * 2.0; #if 0 printf("zero: K = %ld, cost = %g, cancel %g\n", K_zero, cost_zero, cancellation_zero); printf("one: K = %ld, cost = %g, cancel %g\n", K_one, cost_one, cancellation_one); printf("asymp: K = %ld, cost = %g, error = %f (tol = %f)\n", K_asymp, cost_asymp, asymp_error, tolerance); #endif if (asymp_error < tolerance && cost_asymp < FLINT_MIN(cost_zero, cost_one)) { arb_hypgeom_legendre_p_ui_asymp(res, res_prime, n, x, K_asymp, wp); } else if (FLINT_MIN(cost_zero, cost_one) < (1e6 * prec) * prec && n < UWORD_MAX / 4) { mag_t err1, err2, xrad; arb_t xmid; mag_init(err1); mag_init(err2); mag_init(xrad); arb_init(xmid); arf_set(arb_midref(xmid), arb_midref(x)); mag_zero(arb_radref(xmid)); mag_set(xrad, arb_radref(x)); arb_hypgeom_legendre_p_ui_deriv_bound(err1, err2, n, x, x2sub1); if (cost_zero < cost_one) arb_hypgeom_legendre_p_ui_zero(res, res_prime, n, xmid, K_zero, wp + cancellation_zero); else arb_hypgeom_legendre_p_ui_one(res, res_prime, n, xmid, K_one, wp + cancellation_one); if (res != NULL) { mag_mul(err1, err1, xrad); arb_add_error_mag(res, err1); arb_set_round(res, res, prec); } if (res_prime != NULL) { mag_mul(err2, err2, xrad); arb_add_error_mag(res_prime, err2); arb_set_round(res_prime, res_prime, prec); } mag_clear(err1); mag_clear(err2); mag_clear(xrad); arb_clear(xmid); } else if (asymp_error < -2.0) { /* todo -- clamp to [-1,1]? */ arb_hypgeom_legendre_p_ui_asymp(res, res_prime, n, x, K_asymp, wp); } else { if (res != NULL) { arf_zero(arb_midref(res)); mag_one(arb_radref(res)); } if (res_prime != NULL) { arf_zero(arb_midref(res_prime)); mag_set_ui(arb_radref(res_prime), n); mag_add_ui(arb_radref(res_prime), arb_radref(res_prime), 1); mag_mul_ui(arb_radref(res_prime), arb_radref(res_prime), n); mag_mul_2exp_si(arb_radref(res_prime), arb_radref(res_prime), -1); } } } arb_clear(xsub1); arb_clear(x2sub1); } flint-3.1.3/src/arb_hypgeom/legendre_p_ui_asymp.c000066400000000000000000000200571461254215100221000ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "acb.h" #include "arb_hypgeom.h" #define UNROLL 4 static void asymp_series(acb_t res, ulong n, acb_srcptr xpow, slong m, slong K, slong prec) { slong j, k, khi, klo, u, r; fmpz * c; acb_t s; acb_init(s); c = _fmpz_vec_init(UNROLL + 1); k = K - 1; while (k >= 1) { u = FLINT_MIN(UNROLL, k); khi = k; klo = k - u + 1; for (j = klo; j <= khi; j++) { ulong aa = (2 * j - 1); ulong bb = (2 * j - 1); if (j == klo) fmpz_ui_mul_ui(c + khi - j, aa, bb); else fmpz_mul2_uiui(c + khi - j, c + khi - j + 1, aa, bb); } for (j = khi; j >= klo; j--) { ulong aa = (j); ulong bb = (2 * j + 2 * n + 1); if (n < UWORD_MAX / 8) { if (j == khi) { fmpz_ui_mul_ui(c + u, aa, bb); } else { fmpz_mul(c + khi - j, c + khi - j, c + u); fmpz_mul2_uiui(c + u, c + u, aa, bb); } } else { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, n); fmpz_add_ui(t, t, j); fmpz_mul_2exp(t, t, 1); fmpz_add_ui(t, t, 1); if (j == khi) { fmpz_mul_ui(c + u, t, aa); } else { fmpz_mul(c + khi - j, c + khi - j, c + u); fmpz_mul_ui(t, t, aa); fmpz_mul(c + u, c + u, t); } fmpz_clear(t); } } while (k >= klo) { r = k % m; if (k == khi) { acb_add(s, s, xpow + r, prec); acb_mul_fmpz(s, s, c + khi - k, prec); } else if (r == 0) { acb_add_fmpz(s, s, c + khi - k, prec); } else { acb_addmul_fmpz(s, xpow + r, c + khi - k, prec); } if (r == 0 && k != 0) acb_mul(s, s, xpow + m, prec); k--; } acb_div_fmpz(s, s, c + u, prec); } acb_add_ui(res, s, 1, prec); acb_clear(s); _fmpz_vec_clear(c, UNROLL + 1); } /* error: 0.50795 / (y^K sqrt(ny)) * [K! n! / (2^K (n+K)!)] */ /* [K! / (2n)^K] */ static void _arb_hypgeom_legendre_p_ui_asymp_error(mag_t res, ulong n, const mag_t y, slong K) { mag_t t, u; mag_init(t); mag_init(u); /* t = K! / (y^K sqrt(ny)) */ mag_mul_ui_lower(t, y, n); mag_sqrt_lower(t, t); mag_pow_ui_lower(u, y, K); mag_mul_lower(t, t, u); mag_fac_ui(u, K); mag_div(t, u, t); if (K < n / 16) { /* (2n)^K */ mag_set_ui_lower(u, n); mag_mul_2exp_si(u, u, 1); mag_pow_ui_lower(u, u, K); mag_div(t, t, u); } else { /* n! */ mag_fac_ui(u, n); mag_mul(t, t, u); /* (n+K)! */ mag_rfac_ui(u, n + K); mag_mul(t, t, u); /* 2^K */ mag_mul_2exp_si(t, t, -K); } mag_mul_ui(t, t, 131); mag_mul_2exp_si(t, t, -8); mag_set(res, t); mag_clear(t); mag_clear(u); } int arb_abs_le_ui(const arb_t x, ulong n) { arf_struct u[3]; arf_t t; int res; if (!arb_is_finite(x) || arf_cmpabs_ui(arb_midref(x), n) > 0) return 0; if (arb_is_exact(x)) return 1; if (arf_sgn(arb_midref(x)) >= 0) arf_init_set_shallow(u + 0, arb_midref(x)); else arf_init_neg_shallow(u + 0, arb_midref(x)); arf_init_set_mag_shallow(u + 1, arb_radref(x)); arf_init(u + 2); /* no need to free */ arf_set_ui(u + 2, n); arf_neg(u + 2, u + 2); arf_init(t); arf_sum(t, u, 3, MAG_BITS, ARF_RND_DOWN); res = (arf_sgn(t) < 0); arf_clear(t); return res; } void _arb_hypgeom_legendre_p_ui_asymp(arb_t res, ulong n, const arb_t x, const arb_t y, acb_srcptr w4pow, const arb_t binom, slong m, slong K, slong prec) { arb_t t, u; acb_t s, z; fmpz_t e; mag_t err; arb_init(t); arb_init(u); acb_init(s); acb_init(z); mag_init(err); fmpz_init(e); /* u = n + 1/2 */ arb_set_d(u, 0.5); arb_add_ui(u, u, n, prec); arb_get_mag_lower(err, y); _arb_hypgeom_legendre_p_ui_asymp_error(err, n, err, K); /* z = (x + yi)^(n+0.5) * (1-i) */ if (n < 256 || prec > 2000) { arb_set(acb_realref(z), x); arb_set(acb_imagref(z), y); acb_pow_arb(z, z, u, prec); } else { arb_atan2(t, y, x, prec); arb_mul(t, t, u, prec); arb_sin_cos(acb_imagref(z), acb_realref(z), t, prec); } arb_one(acb_realref(s)); arb_set_si(acb_imagref(s), -1); acb_mul(z, z, s, prec); /* main series */ asymp_series(s, n, w4pow, m, K, prec); /* we will use Re(z * s) */ acb_mul(z, z, s, prec); /* prefactor: t = 4^n / (pi * sqrt(y) * (n+0.5) binomial(2n,n)) */ arb_mul(t, binom, u, prec); arb_sqrt(u, y, prec); arb_mul(t, t, u, prec); arb_const_pi(u, prec); arb_mul(t, t, u, prec); arb_div(res, acb_realref(z), t, prec); fmpz_set_ui(e, n); arb_mul_2exp_fmpz(res, res, e); arb_mul_2exp_fmpz(res, res, e); arb_add_error_mag(res, err); arb_clear(t); arb_clear(u); acb_clear(s); acb_clear(z); mag_clear(err); fmpz_clear(e); } void arb_hypgeom_legendre_p_ui_asymp(arb_t res, arb_t res2, ulong n, const arb_t x, slong K, slong prec) { arb_t y, binom; acb_t w; acb_ptr w4pow; slong m; if (n == 0) { if (res != NULL) arb_one(res); if (res2 != NULL) arb_zero(res2); return; } if (!arb_abs_le_ui(x, 1)) { if (res != NULL) arb_indeterminate(res); if (res2 != NULL) arb_indeterminate(res2); return; } K = FLINT_MAX(K, 1); if (res2 != NULL) m = n_sqrt(2 * K); else m = n_sqrt(K); arb_init(y); arb_init(binom); acb_init(w); w4pow = _acb_vec_init(m + 1); /* y = sqrt(1-x^2) */ arb_one(y); arb_submul(y, x, x, 2 * prec); arb_sqrt(y, y, prec); /* w = 1 - (x/y)i */ arb_one(acb_realref(w)); arb_div(acb_imagref(w), x, y, prec); arb_neg(acb_imagref(w), acb_imagref(w)); acb_mul_2exp_si(w, w, -2); _acb_vec_set_powers(w4pow, w, m + 1, prec); /* binomial(2n,n) */ arb_hypgeom_central_bin_ui(binom, n, prec); if (res2 == NULL) { _arb_hypgeom_legendre_p_ui_asymp(res, n, x, y, w4pow, binom, m, K, prec); } else { arb_t t, u, v; arb_init(t); arb_init(u); arb_init(v); _arb_hypgeom_legendre_p_ui_asymp(t, n, x, y, w4pow, binom, m, K, prec); /* recurrence for central binomial */ arb_mul_ui(binom, binom, n, prec); arb_set_ui(u, n); arb_mul_2exp_si(u, u, 2); arb_sub_ui(u, u, 2, prec); arb_div(binom, binom, u, prec); _arb_hypgeom_legendre_p_ui_asymp(u, n - 1, x, y, w4pow, binom, m, K, prec); /* P' = n (P[n-1] - x P) / (1 - x^2) */ arb_submul(u, t, x, prec); arb_mul(v, x, x, 2 * prec); arb_neg(v, v); arb_add_ui(v, v, 1, prec); arb_div(u, u, v, prec); arb_mul_ui(res2, u, n, prec); if (res != NULL) arb_set(res, t); arb_clear(t); arb_clear(u); arb_clear(v); } arb_clear(y); arb_clear(binom); acb_clear(w); _acb_vec_clear(w4pow, m + 1); } flint-3.1.3/src/arb_hypgeom/legendre_p_ui_one.c000066400000000000000000000105401461254215100215240ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "arb_hypgeom.h" #define UNROLL 4 static void sum_rs_inner(arb_t s, arb_srcptr xpow, slong m, ulong n, slong K, ulong prime, slong prec) { slong j, k, khi, klo, u, r; fmpz * c; arb_zero(s); c = _fmpz_vec_init(UNROLL + 1); k = K - 1; while (k >= 1) { u = FLINT_MIN(UNROLL, k); khi = k; klo = k - u + 1; for (j = klo; j <= khi; j++) { ulong aa = (n - j + 1 - prime); ulong bb = (n + j + prime); if (j == klo) fmpz_ui_mul_ui(c + khi - j, aa, bb); else fmpz_mul2_uiui(c + khi - j, c + khi - j + 1, aa, bb); } for (j = khi; j >= klo; j--) { ulong aa = (j); ulong bb = (j + prime); if (j == khi) { fmpz_ui_mul_ui(c + u, aa, bb); } else { fmpz_mul(c + khi - j, c + khi - j, c + u); fmpz_mul2_uiui(c + u, c + u, aa, bb); } } while (k >= klo) { r = k % m; if (k == khi) { arb_add(s, s, xpow + r, prec); arb_mul_fmpz(s, s, c + khi - k, prec); } else if (r == 0) arb_add_fmpz(s, s, c + khi - k, prec); else arb_addmul_fmpz(s, xpow + r, c + khi - k, prec); if (r == 0 && k != 0) arb_mul(s, s, xpow + m, prec); k--; } arb_div_fmpz(s, s, c + u, prec); } _fmpz_vec_clear(c, UNROLL + 1); } void arb_hypgeom_legendre_p_ui_one(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong K, slong prec) { arb_t s, v; arb_ptr xpow; slong m; mag_t u, a, t, err; if (n == 0) { if (res != NULL) arb_one(res); if (res_prime != NULL) arb_zero(res_prime); return; } /* overflow protection */ if (n > UWORD_MAX / 4) { if (res != NULL) arb_indeterminate(res); if (res_prime != NULL) arb_indeterminate(res_prime); } arb_init(v); arb_init(s); mag_init(u); mag_init(a); mag_init(t); mag_init(err); K = FLINT_MIN(K, n + 1); if (res != NULL && res_prime != NULL) m = n_sqrt(2 * K); else m = n_sqrt(K); xpow = _arb_vec_init(m + 1); arb_sub_ui(v, x, 1, prec); arb_mul_2exp_si(v, v, -1); _arb_vec_set_powers(xpow, v, m + 1, prec); /* truncating */ if (K < n + 1) { arb_get_mag(u, v); mag_mul_ui(t, u, n - K); mag_mul_ui(t, t, n + K + 1); mag_div_ui(t, t, K + 1); mag_div_ui(t, t, K + 1); mag_geom_series(t, t, 0); mag_pow_ui(u, u, K); mag_mul(u, u, t); } if (res != NULL) { sum_rs_inner(s, xpow, m, n, K, 0, prec); arb_add_ui(res, s, 1, prec); if (K < n + 1) { mag_set(err, u); mag_bin_uiui(t, n, K); mag_mul(err, err, t); mag_bin_uiui(t, n + K, K); mag_mul(err, err, t); arb_add_error_mag(res, err); } } if (res_prime != NULL) { K = FLINT_MIN(K, n); sum_rs_inner(s, xpow, m, n, K, 1, prec); arb_add_ui(res_prime, s, 1, prec); arb_mul_ui(res_prime, res_prime, n, prec); arb_mul_ui(res_prime, res_prime, n + 1, prec); arb_mul_2exp_si(res_prime, res_prime, -1); /* truncating */ if (K < n) { mag_set(err, u); mag_bin_uiui(t, n, K + 1); mag_mul(err, err, t); mag_bin_uiui(t, n + K + 1, K + 1); mag_mul(err, err, t); mag_mul_ui(err, err, n); arb_add_error_mag(res_prime, err); } } _arb_vec_clear(xpow, m + 1); arb_clear(s); arb_clear(v); mag_clear(u); mag_clear(a); mag_clear(t); mag_clear(err); } flint-3.1.3/src/arb_hypgeom/legendre_p_ui_rec.c000066400000000000000000000073321461254215100215210ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" #include "gmpcompat.h" void arb_hypgeom_legendre_p_ui_rec(arb_t res, arb_t res_prime, ulong n, const arb_t x, slong prec) { slong wp; ulong k, den; mp_limb_t denlo, denhi; mpz_t p0, p1, xx, tt; fmpz_t fxx; int error; arb_t t, u, x2sub1; mag_t err1, err2, xrad; if (n > (UWORD(1) << (FLINT_BITS / 2 - 1))) { if (res != NULL) arb_indeterminate(res); if (res_prime != NULL) arb_indeterminate(res); return; } if (n == 0) { if (res != NULL) arb_one(res); if (res_prime != NULL) arb_zero(res_prime); return; } mag_init(xrad); arb_get_mag(xrad, x); /* error analysis assumes |x| < 1 */ if (mag_cmp_2exp_si(xrad, 0) >= 0) { arb_hypgeom_legendre_p_ui_one(res, res_prime, n, x, n + 1, prec); mag_clear(xrad); return; } mpz_init(p0); mpz_init(p1); mpz_init(xx); mpz_init(tt); fmpz_init(fxx); arb_init(t); arb_init(u); arb_init(x2sub1); mag_init(err1); mag_init(err2); wp = -arf_abs_bound_lt_2exp_si(arb_midref(x)); wp = FLINT_MAX(wp, 0); wp = FLINT_MIN(wp, prec); wp += prec + 2 * FLINT_BIT_COUNT(n + 2); /* (n+2)^2 >= 0.75(n+1)(n+2)+1 */ arb_mul(x2sub1, x, x, ARF_PREC_EXACT); arb_neg(x2sub1, x2sub1); arb_add_ui(x2sub1, x2sub1, 1, wp); error = arf_get_fmpz_fixed_si(fxx, arb_midref(x), -wp); fmpz_get_mpz(xx, fxx); mag_set(xrad, arb_radref(x)); if (error) mag_add_ui_2exp_si(xrad, xrad, 1, -wp); mpz_set_ui(p0, 1); mpz_mul_2exp(p0, p0, wp); mpz_set(p1, xx); den = 1; for (k = 1; k < n; k++) { mpz_mul(tt, p1, xx); mpz_tdiv_q_2exp(tt, tt, wp); flint_mpz_mul_ui(p0, p0, k*k); mpz_neg(p0, p0); flint_mpz_addmul_ui(p0, tt, 2 * k + 1); mpz_swap(p0, p1); umul_ppmm(denhi, denlo, den, k + 1); if (denhi != 0) { flint_mpz_tdiv_q_ui(p0, p0, den); flint_mpz_tdiv_q_ui(p1, p1, den); den = k + 1; } else { den = denlo; } } flint_mpz_tdiv_q_ui(p0, p0, den/n); flint_mpz_tdiv_q_ui(p1, p1, den); if (!mag_is_zero(xrad)) { arb_hypgeom_legendre_p_ui_deriv_bound(err1, err2, n, x, x2sub1); mag_mul(err1, err1, xrad); mag_mul(err2, err2, xrad); } arf_set_mpz(arb_midref(t), p1); arf_mul_2exp_si(arb_midref(t), arb_midref(t), -wp); mag_set_ui_2exp_si(arb_radref(t), (n + 1) * (n + 2), -wp); mag_add(arb_radref(t), arb_radref(t), err1); if (res_prime != NULL) { /* P' = n (P[n-1] - x P) / (1 - x^2) */ arf_set_mpz(arb_midref(u), p0); arf_mul_2exp_si(arb_midref(u), arb_midref(u), -wp); mag_set_ui_2exp_si(arb_radref(u), n * (n + 1), -wp); arb_submul(u, t, x, wp); arb_div(res_prime, u, x2sub1, wp); arb_mul_ui(res_prime, res_prime, n, prec); mag_add(arb_radref(res_prime), arb_radref(res_prime), err2); } if (res != NULL) /* done last since x may be aliased with res */ { arb_set_round(res, t, prec); } mpz_clear(p0); mpz_clear(p1); mpz_clear(xx); mpz_clear(tt); fmpz_clear(fxx); arb_clear(t); arb_clear(u); arb_clear(x2sub1); mag_clear(err1); mag_clear(err2); mag_clear(xrad); } flint-3.1.3/src/arb_hypgeom/legendre_p_ui_root.c000066400000000000000000000131631461254215100217320ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" /* Compute initial isolating interval, following K. Petras. */ void arb_hypgeom_legendre_p_ui_root_initial(arb_t res, ulong n, ulong k, slong prec) { arb_t phi, psi, s, c, t, u; mag_t err, errc, errd; slong i, tol; arb_init(phi); arb_init(psi); arb_init(s); arb_init(c); arb_init(t); arb_init(u); mag_init(err); mag_init(errc); mag_init(errd); /* Petras numbering starts from 1 */ k++; if (k > n / 2) flint_throw(FLINT_ERROR, "(%s)\n", __func__); tol = -prec; /* We need slightly higher precision since the Newton iteration *arithmetic* error bounds are not self-correcting. */ prec = prec * 1.2 + 10; /* t = 4n+2 */ arb_set_ui(t, n); arb_mul_2exp_si(t, t, 2); arb_add_ui(t, t, 2, prec); /* u = (4k-1) pi */ arb_set_ui(u, k); arb_mul_2exp_si(u, u, 2); arb_sub_ui(u, u, 1, prec); arb_const_pi(phi, prec); arb_mul(u, u, phi, prec); /* phi = ((4k-1)/(4n+2)) pi */ arb_div(phi, u, t, prec); /* errc = phi^2 */ arb_get_mag_lower(errc, phi); mag_mul(errc, errc, errc); /* errd = 22*y^4 * (1 + 2*y^2), y = 1/u */ /* err = y^2 */ arb_get_mag_lower(err, u); mag_one(errd); mag_div(err, errd, err); mag_mul(err, err, err); /* errd = 1+2y^2 */ mag_mul_2exp_si(errd, err, 1); mag_add_ui(errd, errd, 1); /* err = y^4 */ mag_mul(err, err, err); /* errd *= 22y^4 */ mag_mul(errd, errd, err); mag_mul_ui(errd, errd, 22); /* s, c = sin(phi), cos(phi) */ arb_sin_cos(s, c, phi, prec); /* psi = phi + 2 cos(phi) / (t^2 sin(phi)) (1 - 11/[t^2 sin(phi)^2]) */ arb_mul(psi, t, s, prec); arb_mul(psi, psi, psi, prec); arb_ui_div(psi, 11, psi, prec); arb_sub_ui(psi, psi, 1, prec); arb_neg(psi, psi); /* (destroying t) */ arb_mul(t, t, t, prec); arb_mul(t, t, s, prec); arb_div(t, c, t, prec); arb_mul_2exp_si(t, t, 1); arb_mul(psi, psi, t, prec); arb_add(psi, psi, phi, prec); arb_cos(res, psi, prec); mag_mul(err, errc, errd); for (i = 0; i < FLINT_BITS; i++) { if (mag_cmp_2exp_si(err, tol) < 0) break; arb_hypgeom_legendre_p_ui(t, u, n, res, prec); arb_div(t, t, u, prec); arb_sub(res, res, t, prec); mag_mul(errd, errd, errd); mag_mul(err, errc, errd); } arb_add_error_mag(res, err); arb_clear(phi); arb_clear(psi); arb_clear(s); arb_clear(c); arb_clear(t); arb_clear(u); mag_clear(err); mag_clear(errc); mag_clear(errd); } void arb_hypgeom_legendre_p_ui_root(arb_t res, arb_t weight, ulong n, ulong k, slong prec) { slong padding, initial_prec, step, wp; slong steps[FLINT_BITS]; arb_t t, u, v, v0; mag_t err, err2, pb, p2b; int sign; if (k >= n) { flint_throw(FLINT_ERROR, "require n > 0 and a root index 0 <= k < n\n"); } sign = 1; if (n % 2 == 1 && k == n / 2) { sign = 0; } else if (k >= n / 2) { k = n - k - 1; sign = -1; } arb_init(t); arb_init(u); arb_init(v); arb_init(v0); mag_init(err); mag_init(err2); mag_init(pb); mag_init(p2b); padding = 8 + 2 * FLINT_BIT_COUNT(n); initial_prec = 40 + padding; if (sign == 0) { arb_zero(res); } else if (initial_prec > prec / 2) { arb_hypgeom_legendre_p_ui_root_initial(res, n, k, prec + padding); } else { step = 0; steps[step] = prec + padding; while (step < FLINT_BITS - 1 && (steps[step] / 2) > initial_prec) { steps[step + 1] = (steps[step] / 2); step++; } wp = steps[step] + padding; arb_hypgeom_legendre_p_ui_root_initial(res, n, k, wp); step--; arb_mul(t, res, res, wp); arb_sub_ui(t, t, 1, wp); arb_hypgeom_legendre_p_ui_deriv_bound(pb, p2b, n, res, t); arb_set(v0, res); for ( ; step >= 0; step--) { wp = steps[step] + padding; /* Interval Newton update: mid(x) - f(mid(x)) / f'(x) */ /* We compute f'(mid(x)) and use the bound on f'' to get f'(x) */ arb_set(v, res); mag_mul(err, p2b, arb_radref(v)); mag_zero(arb_radref(v)); arb_hypgeom_legendre_p_ui(t, u, n, v, wp); arb_add_error_mag(u, err); arb_div(t, t, u, wp); arb_sub(v, v, t, wp); if (mag_cmp(arb_radref(v), arb_radref(res)) >= 0) { /* flint_printf("unexpected Newton iteration failure...\n"); */ break; } arb_set(res, v); } } if (weight != NULL) { wp = FLINT_MAX(prec, 40) + padding; arb_hypgeom_legendre_p_ui(NULL, t, n, res, wp); arb_mul(t, t, t, wp); arb_mul(u, res, res, wp); arb_sub_ui(u, u, 1, wp); arb_neg(u, u); arb_mul(t, t, u, wp); arb_ui_div(weight, 2, t, prec); } if (sign == -1) arb_neg(res, res); arb_set_round(res, res, prec); arb_clear(t); arb_clear(u); arb_clear(v); arb_clear(v0); mag_clear(err); mag_clear(err2); mag_clear(pb); mag_clear(p2b); } flint-3.1.3/src/arb_hypgeom/legendre_p_ui_zero.c000066400000000000000000000124501461254215100217240ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "arb_hypgeom.h" #define UNROLL 4 static void sum_rs_inner(arb_t s, arb_srcptr xpow, slong m, ulong n, slong K, slong prec) { slong j, k, khi, klo, u, r; ulong d; slong sigma; fmpz * c; sigma = n % 2 ? 1 : -1; d = n / 2; arb_zero(s); c = _fmpz_vec_init(UNROLL + 1); k = K - 1; while (k >= 1) { u = FLINT_MIN(UNROLL, k); khi = k; klo = k - u + 1; for (j = klo; j <= khi; j++) { ulong aa = (d - j + 1); ulong bb = (2 * d + 2 * j + sigma); if (j == klo) fmpz_ui_mul_ui(c + khi - j, aa, bb); else fmpz_mul2_uiui(c + khi - j, c + khi - j + 1, aa, bb); } for (j = khi; j >= klo; j--) { ulong aa = (j); ulong bb = (2 * j + sigma); if (j == khi) { fmpz_ui_mul_ui(c + u, aa, bb); } else { fmpz_mul(c + khi - j, c + khi - j, c + u); fmpz_mul2_uiui(c + u, c + u, aa, bb); } } while (k >= klo) { r = k % m; if (k == khi) { arb_add(s, s, xpow + r, prec); arb_mul_fmpz(s, s, c + khi - k, prec); } else if (r == 0) arb_add_fmpz(s, s, c + khi - k, prec); else arb_addmul_fmpz(s, xpow + r, c + khi - k, prec); if (r == 0 && k != 0) arb_mul(s, s, xpow + m, prec); k--; } arb_div_fmpz(s, s, c + u, prec); } _fmpz_vec_clear(c, UNROLL + 1); } static void _arb_hypgeom_legendre_p_ui_zero(arb_t res, ulong n, const arb_t x, arb_srcptr xpow, slong m, slong K, slong prec) { arb_t s; slong d, prec2; mag_t u, a, t, err; d = n / 2; arb_init(s); mag_init(u); mag_init(a); mag_init(t); mag_init(err); K = FLINT_MIN(K, d + 1); sum_rs_inner(s, xpow, m, n, K, prec); prec2 = arb_rel_accuracy_bits(s); if (prec2 > prec) prec2 = prec; else prec2 = FLINT_MAX(0, prec2) + 20; arb_add_ui(s, s, 1, prec2); if (n % 2 == 1) arb_mul(s, s, x, prec2); arb_swap(res, s); if (d % 2 == 1) arb_neg(res, res); if (n % 2 == 0) { arb_hypgeom_central_bin_ui(s, d, prec2); arb_mul(res, res, s, prec2); arb_mul_2exp_si(res, res, -n); } else { arb_hypgeom_central_bin_ui(s, d + 1, prec2); arb_mul(res, res, s, prec2); arb_mul_ui(res, res, d + 1, prec2); arb_mul_2exp_si(res, res, -n); } if (K < d + 1) { mag_bin_uiui(err, n, d - K); mag_bin_uiui(t, n + 2 * K + (n % 2), n); mag_mul(err, err, t); arb_get_mag(t, x); mag_pow_ui(t, t, 2 * K + (n % 2)); mag_mul(err, err, t); mag_mul_2exp_si(err, err, -n); arb_get_mag(t, x); mag_mul(t, t, t); mag_mul_ui(t, t, d - K + 1); mag_mul_ui(t, t, 2 * d + 2 * K + (n % 2 ? 1 : -1)); mag_div_ui(t, t, K); mag_div_ui(t, t, 2 * K + (n % 2 ? 1 : -1)); mag_geom_series(t, t, 0); mag_mul(err, err, t); arb_add_error_mag(res, err); } arb_clear(s); mag_clear(u); mag_clear(a); mag_clear(t); mag_clear(err); } void arb_hypgeom_legendre_p_ui_zero(arb_t res, arb_t res2, ulong n, const arb_t x, slong K, slong prec) { arb_ptr xpow; arb_t t, u, v; slong m; if (n == 0) { if (res != NULL) arb_one(res); if (res2 != NULL) arb_zero(res2); return; } /* overflow protection */ if (n > UWORD_MAX / 4) { if (res != NULL) arb_indeterminate(res); if (res2 != NULL) arb_indeterminate(res2); } if (res == NULL) { arb_init(v); arb_hypgeom_legendre_p_ui_zero(v, res2, n, x, K, prec); arb_clear(v); return; } arb_init(t); arb_init(u); arb_init(v); K = FLINT_MIN(K, n / 2 + 1); if (res2 != NULL) m = n_sqrt(2 * K); else m = n_sqrt(K); xpow = _arb_vec_init(m + 1); arb_mul(v, x, x, prec); arb_neg(v, v); _arb_vec_set_powers(xpow, v, m + 1, prec); /* todo: recycle prefactor */ if (res2 == NULL) { _arb_hypgeom_legendre_p_ui_zero(t, n, x, xpow, m, K, prec); arb_set(res, t); } else { _arb_hypgeom_legendre_p_ui_zero(t, n, x, xpow, m, K, prec); _arb_hypgeom_legendre_p_ui_zero(u, n - 1, x, xpow, m, K, prec); /* P' = n (P[n-1] - x P) / (1 - x^2) */ arb_submul(u, t, x, prec); arb_add_ui(v, v, 1, prec); arb_div(u, u, v, prec); arb_mul_ui(res2, u, n, prec); arb_set(res, t); } _arb_vec_clear(xpow, m + 1); arb_clear(t); arb_clear(u); arb_clear(v); } flint-3.1.3/src/arb_hypgeom/lgamma.c000066400000000000000000000036601461254215100173250ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec); int arb_hypgeom_gamma_exact(arb_t res, const arb_t x, int reciprocal, slong prec); void arb_hypgeom_gamma_stirling_inner(arb_t s, const arb_t z, slong N, slong prec); void arb_hypgeom_lgamma_stirling(arb_t y, const arb_t x, slong prec) { int reflect; slong r, n, wp; arb_t t, u; double acc; /* todo: for large x (if exact or accurate enough), increase precision */ acc = arb_rel_accuracy_bits(x); acc = FLINT_MAX(acc, 0); wp = FLINT_MIN(prec, acc + 20); wp = FLINT_MAX(wp, 2); wp = wp + FLINT_BIT_COUNT(wp); arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, x, 0, 0, wp); arb_init(t); arb_init(u); /* log(gamma(x)) = log(gamma(x+r)) - log(rf(x,r)) */ arb_init(t); arb_init(u); arb_add_ui(t, x, r, wp); arb_hypgeom_gamma_stirling_inner(u, t, n, wp); arb_hypgeom_rising_ui_rec(t, x, r, wp); arb_log(t, t, wp); arb_sub(y, u, t, prec); arb_clear(t); arb_clear(u); } void arb_hypgeom_lgamma(arb_t res, const arb_t x, slong prec) { if (!arb_is_positive(x) || !arb_is_finite(x)) { arb_indeterminate(res); return; } if (arb_hypgeom_gamma_exact(res, x, 0, prec)) { arb_log(res, res, prec); return; } if (arb_hypgeom_gamma_taylor(res, x, 0, prec)) { arb_log(res, res, prec); return; } arb_hypgeom_lgamma_stirling(res, x, prec); } flint-3.1.3/src/arb_hypgeom/li_series.c000066400000000000000000000035501461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_li_series(arb_ptr g, arb_srcptr h, slong hlen, int offset, slong len, slong prec) { arb_t c; if (!arb_is_positive(h) || arb_contains_si(h, 1)) { _arb_vec_indeterminate(g, len); return; } arb_init(c); arb_hypgeom_li(c, h, offset, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else if (len == 2) { arb_log(g, h, prec); arb_div(g + 1, h + 1, g, prec); } else { arb_ptr t, u; t = _arb_vec_init(len); u = _arb_vec_init(hlen); /* li(h(x)) = integral(h'(x) / log(h(x))) */ _arb_poly_log_series(t, h, hlen, len - 1, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_div_series(g, u, hlen - 1, t, len - 1, len - 1, prec); _arb_poly_integral(g, g, len, prec); _arb_vec_clear(t, len); _arb_vec_clear(u, hlen); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_li_series(arb_poly_t g, const arb_poly_t h, int offset, slong len, slong prec) { slong hlen = h->length; if (len == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_inv_series(g, h, len, prec); return; } arb_poly_fit_length(g, len); _arb_hypgeom_li_series(g->coeffs, h->coeffs, hlen, offset, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/rising_ui.c000066400000000000000000000024401461254215100200520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_rising_ui(arb_t y, const arb_t x, ulong n, slong prec) { if (n < FLINT_MAX(prec, 100)) { arb_hypgeom_rising_ui_rec(y, x, n, prec); } else { arb_t t; arb_init(t); arb_add_ui(t, x, n, prec); arb_gamma(t, t, prec); arb_rgamma(y, x, prec); arb_mul(y, y, t, prec); arb_clear(t); } } void arb_hypgeom_rising(arb_t y, const arb_t x, const arb_t n, slong prec) { if (arb_is_int(n) && arf_sgn(arb_midref(n)) >= 0 && arf_cmpabs_ui(arb_midref(n), FLINT_MAX(prec, 100)) < 0) { arb_hypgeom_rising_ui_rec(y, x, arf_get_si(arb_midref(n), ARF_RND_DOWN), prec); } else { arb_t t; arb_init(t); arb_add(t, x, n, prec); arb_gamma(t, t, prec); arb_rgamma(y, x, prec); arb_mul(y, y, t, prec); arb_clear(t); } } flint-3.1.3/src/arb_hypgeom/rising_ui_bs.c000066400000000000000000000026451461254215100205450ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" static void bsplit(arb_t y, const arb_t x, ulong a, ulong b, slong prec) { if (b - a <= 16) { if (a == 0) { arb_hypgeom_rising_ui_forward(y, x, b, prec); } else { arb_add_ui(y, x, a, prec); arb_hypgeom_rising_ui_forward(y, y, b - a, prec); } } else { arb_t t, u; ulong m = a + (b - a) / 2; arb_init(t); arb_init(u); bsplit(t, x, a, m, prec); bsplit(u, x, m, b, prec); arb_mul(y, t, u, prec); arb_clear(t); arb_clear(u); } } void arb_hypgeom_rising_ui_bs(arb_t res, const arb_t x, ulong n, slong prec) { if (n <= 1) { if (n == 0) arb_one(res); else arb_set_round(res, x, prec); return; } { arb_t t; slong wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); arb_init(t); bsplit(t, x, 0, n, wp); arb_set_round(res, t, prec); arb_clear(t); } } flint-3.1.3/src/arb_hypgeom/rising_ui_forward.c000066400000000000000000000033171461254215100216020ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" int _arf_increment_fast(arf_t x, slong prec) { if (arf_sgn(x) > 0) { mp_limb_t hi, v, cy; mp_ptr xptr; mp_size_t xn; slong xexp; xexp = ARF_EXP(x); if (xexp >= 1 && xexp <= FLINT_BITS - 1) { ARF_GET_MPN_READONLY(xptr, xn, x); hi = xptr[xn - 1]; v = hi + (UWORD(1) << (FLINT_BITS - xexp)); cy = v < hi; if (cy == 0) { xptr[xn - 1] = v; return 0; } } } return arf_add_ui(x, x, 1, prec, ARF_RND_DOWN); } void _arb_increment_fast(arb_t x, slong prec) { if (_arf_increment_fast(arb_midref(x), prec)) arf_mag_add_ulp(arb_radref(x), arb_radref(x), arb_midref(x), prec); } void arb_hypgeom_rising_ui_forward(arb_t res, const arb_t x, ulong n, slong prec) { arb_t t; ulong k; slong wp; if (n <= 1) { if (n == 0) arb_one(res); else arb_set_round(res, x, prec); return; } wp = prec + FLINT_BIT_COUNT(n); arb_init(t); arb_add_ui(t, x, 1, wp); arb_mul(res, x, t, (n == 2) ? prec : wp); for (k = 2; k < n; k++) { _arb_increment_fast(t, wp); arb_mul(res, res, t, k == (n - 1) ? prec : wp); } arb_clear(t); } flint-3.1.3/src/arb_hypgeom/rising_ui_jet.c000066400000000000000000000025171461254215100207210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_rising_ui_jet(arb_ptr res, const arb_t x, ulong n, slong len, slong prec) { if (len == 1) { arb_hypgeom_rising_ui_rec(res, x, n, prec); } else if (n <= 7) { arb_hypgeom_rising_ui_jet_powsum(res, x, n, len, prec); } else if (len == 2) { if (n <= 30 || arb_bits(x) >= prec / 128) arb_hypgeom_rising_ui_jet_rs(res, x, n, 0, len, prec); else arb_hypgeom_rising_ui_jet_bs(res, x, n, len, prec); } else { if (n <= 20 || (n <= 200 && prec > 400 * n && arb_bits(x) >= prec / 4)) { arb_hypgeom_rising_ui_jet_powsum(res, x, n, len, prec); } else if (len >= 64 || (arb_bits(x) + 1 < prec / 1024 && n >= 32)) { arb_hypgeom_rising_ui_jet_bs(res, x, n, len, prec); } else { arb_hypgeom_rising_ui_jet_rs(res, x, n, 0, len, prec); } } } flint-3.1.3/src/arb_hypgeom/rising_ui_jet_bs.c000066400000000000000000000036111461254215100214010ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" static void bsplit(arb_ptr res, const arb_t x, ulong a, ulong b, slong trunc, slong prec) { trunc = FLINT_MIN(trunc, b - a + 1); if (b - a <= 12) { if (a == 0) { arb_hypgeom_rising_ui_jet_powsum(res, x, b - a, FLINT_MIN(trunc, b - a + 1), prec); } else { arb_t t; arb_init(t); arb_add_ui(t, x, a, prec); arb_hypgeom_rising_ui_jet_powsum(res, t, b - a, FLINT_MIN(trunc, b - a + 1), prec); arb_clear(t); } } else { arb_ptr L, R; slong len1, len2; slong m = a + (b - a) / 2; len1 = poly_pow_length(2, m - a, trunc); len2 = poly_pow_length(2, b - m, trunc); L = _arb_vec_init(len1 + len2); R = L + len1; bsplit(L, x, a, m, trunc, prec); bsplit(R, x, m, b, trunc, prec); _arb_poly_mullow(res, L, len1, R, len2, FLINT_MIN(trunc, len1 + len2 - 1), prec); _arb_vec_clear(L, len1 + len2); } } void arb_hypgeom_rising_ui_jet_bs(arb_ptr res, const arb_t x, ulong n, slong len, slong prec) { if (len == 0) return; if (len > n + 1) { _arb_vec_zero(res + n + 1, len - n - 1); len = n + 1; } if (len == n + 1) { arb_one(res + n); len = n; } if (n <= 1) { if (n == 1) arb_set_round(res, x, prec); return; } bsplit(res, x, 0, n, len, prec); } flint-3.1.3/src/arb_hypgeom/rising_ui_jet_powsum.c000066400000000000000000000101011461254215100223170ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fmpz_vec.h" #include "arb_hypgeom.h" void arb_hypgeom_rising_ui_jet_powsum(arb_ptr res, const arb_t x, ulong n, slong len, slong prec) { slong i, j, k, wp; arb_ptr xpow; TMP_INIT; if (len == 0) return; if (len > n + 1) { _arb_vec_zero(res + n + 1, len - n - 1); len = n + 1; } if (len == n + 1) { arb_one(res + n); len = n; } if (n <= 1) { if (n == 1) arb_set_round(res, x, prec); return; } if (len == 1) { arb_hypgeom_rising_ui_rs(res, x, n, 0, prec); return; } if (n == 2) { arb_mul_2exp_si(res + 1, x, 1); arb_add_ui(res + 1, res + 1, 1, prec); arb_mul(res, x, x, prec + 4); arb_add(res, res, x, prec); return; } if (n <= 12 || (FLINT_BITS == 64 && n <= 20)) { mp_ptr c; TMP_START; wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); c = TMP_ALLOC(sizeof(mp_limb_t) * (n + 1) * len); _nmod_vec_zero(c, (n + 1) * len); c[0] = 0; c[1] = 1; c[(n + 1) + 0] = 1; for (i = 2; i <= n; i++) { for (j = FLINT_MIN(len - 1, i); j >= 0; j--) { slong ln, pos; ln = i + 1 - j; pos = (n + 1) * j; if (i == j) { c[pos] = 1; } else { c[pos + ln - 1] = c[pos + ln - 2]; for (k = ln - 2; k >= 1; k--) c[pos + k] = c[pos + k] * (i - 1) + c[pos + k - 1]; c[pos + 0] *= (i - 1); if (j != 0) for (k = ln - 1; k >= 0; k--) c[pos + k] += c[pos - (n + 1) + k]; } } } xpow = _arb_vec_init(n + 1); _arb_vec_set_powers(xpow, x, n + 1, wp); arb_dot_ui(res, NULL, 0, xpow + 1, 1, c + 1, 1, n, prec); for (i = 1; i < len; i++) arb_dot_ui(res + i, NULL, 0, xpow, 1, c + (n + 1) * i, 1, n + 1 - i, prec); _arb_vec_clear(xpow, n + 1); TMP_END; } else { fmpz * c; wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); c = _fmpz_vec_init((n + 1) * len); fmpz_one(c + 1); fmpz_one(c + (n + 1) + 0); for (i = 2; i <= n; i++) { for (j = FLINT_MIN(len - 1, i); j >= 0; j--) { slong ln, pos; ln = i + 1 - j; pos = (n + 1) * j; if (i == j) { fmpz_one(c + pos); } else { fmpz_set(c + pos + ln - 1, c + pos + ln - 2); for (k = ln - 2; k >= 1; k--) { fmpz_mul_ui(c + pos + k, c + pos + k, i - 1); fmpz_add(c + pos + k, c + pos + k, c + pos + k - 1); } fmpz_mul_ui(c + pos + 0, c + pos + 0, i - 1); if (j != 0) for (k = ln - 1; k >= 0; k--) fmpz_add(c + pos + k, c + pos + k, c + pos - (n + 1) + k); } } } xpow = _arb_vec_init(n + 1); _arb_vec_set_powers(xpow, x, n + 1, wp); arb_dot_fmpz(res, NULL, 0, xpow + 1, 1, c + 1, 1, n, prec); for (i = 1; i < len; i++) arb_dot_fmpz(res + i, NULL, 0, xpow, 1, c + (n + 1) * i, 1, n + 1 - i, prec); _arb_vec_clear(xpow, n + 1); _fmpz_vec_clear(c, (n + 1) * len); } } flint-3.1.3/src/arb_hypgeom/rising_ui_jet_rs.c000066400000000000000000000104651461254215100214260ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "arb_poly.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif void arb_hypgeom_rising_ui_jet_rs(arb_ptr res, const arb_t x, ulong n, ulong m, slong len, slong prec) { slong i, j, k, l, m0, xmlen, tlen, ulen, climbs, climbs_max, wp; arb_ptr tmp, xpow; arb_ptr t, u; mp_ptr c; TMP_INIT; if (len == 0) return; if (len > n + 1) { _arb_vec_zero(res + n + 1, len - n - 1); len = n + 1; } if (len == n + 1) { arb_one(res + n); len = n; } if (n <= 1) { if (n == 1) arb_set_round(res, x, prec); return; } if (len == 1) { arb_hypgeom_rising_ui_rs(res, x, n, m, prec); return; } TMP_START; if (m == 0) { if (n <= 7) m = n; else if (n <= 12) m = (n + 1) / 2; else if (n <= 32) m = (n + 2) / 3; else { m0 = n_sqrt(n); m = 8 + 0.5 * pow(prec, 0.4); m = FLINT_MIN(m, m0); m = FLINT_MIN(m, 64); } } wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); climbs_max = FLINT_BIT_COUNT(n - 1) * m; c = TMP_ALLOC(sizeof(mp_limb_t) * climbs_max * m); /* length of (x+t)^m */ xmlen = FLINT_MIN(len, m + 1); tmp = _arb_vec_init(2 * len + (m + 1) * xmlen); t = tmp; u = tmp + len; xpow = tmp + 2 * len; _arb_vec_set_powers(xpow, x, m + 1, wp); tlen = 1; /* First derivatives */ for (i = 1; i <= m; i++) arb_mul_ui(xpow + (m + 1) + i, xpow + i - 1, i, wp); /* Higher derivatives if we need them */ if (len >= 3) { fmpz * f = _fmpz_vec_init(len); fmpz_one(f + 0); fmpz_one(f + 1); for (i = 2; i <= m; i++) { for (j = FLINT_MIN(xmlen - 1, i + 1); j >= 1; j--) fmpz_add(f + j, f + j, f + j - 1); for (j = 2; j < FLINT_MIN(xmlen, i + 1); j++) arb_mul_fmpz(xpow + (m + 1) * j + i, xpow + i - j, f + j, wp); } _fmpz_vec_clear(f, len); } for (k = 0; k < n; k += m) { l = FLINT_MIN(m, n - k); climbs = FLINT_BIT_COUNT(k + l - 1) * l; climbs = (climbs + FLINT_BITS - 1) / FLINT_BITS; ulen = FLINT_MIN(len, l + 1); if (l == 1) { arb_add_ui(u, x, k, wp); arb_one(u + 1); } else { if (climbs == 1) { _arb_hypgeom_rising_coeffs_1(c, k, l); for (j = 0; j < ulen; j++) arb_dot_ui(u + j, xpow + (m + 1) * j + l, 0, xpow + (m + 1) * j + j, 1, c + j, 1, l - j, wp); } else if (climbs == 2) { _arb_hypgeom_rising_coeffs_2(c, k, l); for (j = 0; j < ulen; j++) arb_dot_uiui(u + j, xpow + (m + 1) * j + l, 0, xpow + (m + 1) * j + j, 1, c + 2 * j, 1, l - j, wp); } else { fmpz * f = (fmpz *) c; for (i = 0; i < l; i++) fmpz_init(f + i); _arb_hypgeom_rising_coeffs_fmpz(f, k, l); for (j = 0; j < ulen; j++) arb_dot_fmpz(u + j, xpow + (m + 1) * j + l, 0, xpow + (m + 1) * j + j, 1, f + j, 1, l - j, wp); for (i = 0; i < l; i++) fmpz_clear(f + i); } } if (k == 0) { tlen = ulen; _arb_vec_swap(t, u, ulen); } else { _arb_poly_mullow(res, t, tlen, u, ulen, FLINT_MIN(len, tlen + ulen - 1), wp); tlen = FLINT_MIN(len, tlen + ulen - 1); _arb_vec_swap(t, res, tlen); } } _arb_vec_set_round(res, t, len, prec); _arb_vec_clear(tmp, 2 * len + (m + 1) * xmlen); TMP_END; } flint-3.1.3/src/arb_hypgeom/rising_ui_rec.c000066400000000000000000000021351461254215100207040ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_rising_ui_rec(arb_t res, const arb_t x, ulong n, slong prec) { if (n <= 1) { if (n == 0) arb_one(res); else arb_set_round(res, x, prec); return; } if (n == 2 && prec <= 1024) { if (res != x) arb_set(res, x); arb_addmul(res, x, x, prec); return; } if ((prec < 512 && n <= 20) || (n <= FLINT_MIN(80, 6000 / prec))) { arb_hypgeom_rising_ui_forward(res, x, n, prec); } else { if (n >= 20 && arb_bits(x) < prec / 8) arb_hypgeom_rising_ui_bs(res, x, n, prec); else arb_hypgeom_rising_ui_rs(res, x, n, 0, prec); } } flint-3.1.3/src/arb_hypgeom/rising_ui_rs.c000066400000000000000000000105671461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define pow __builtin_pow #else # include #endif void _arb_hypgeom_rising_coeffs_1(ulong * c, ulong k, slong l) { slong i, j; ulong d; if (l < 2) flint_throw(FLINT_ERROR, "(%s): l < 2\n", __func__); c[0] = k * (k + 1); c[1] = 2 * k + 1; for (i = 2; i < l; i++) { d = k + i; c[i] = c[i - 1] + d; for (j = i - 1; j >= 1; j--) c[j] = c[j] * d + c[j - 1]; c[0] = c[0] * d; } } void _arb_hypgeom_rising_coeffs_2(ulong * c, ulong k, slong l) { slong i, j; ulong d; mp_limb_t hi, lo; if (l < 2) flint_throw(FLINT_ERROR, "(%s): l < 2\n", __func__); umul_ppmm(c[1], c[0], k, k + 1); c[2] = 2 * k + 1; c[3] = 0; for (i = 2; i < l; i++) { d = k + i; add_ssaaaa(c[2 * i + 1], c[2 * i], c[2 * i - 1], c[2 * i - 2], 0, d); for (j = i - 1; j >= 1; j--) { umul_ppmm(hi, lo, c[2 * j], d); hi += c[2 * j + 1] * d; add_ssaaaa(c[2 * j + 1], c[2 * j], hi, lo, c[2 * j - 1], c[2 * j - 2]); } umul_ppmm(hi, lo, c[0], d); c[0] = lo; c[1] = c[1] * d + hi; } } void _arb_hypgeom_rising_coeffs_fmpz(fmpz * c, ulong k, slong l) { slong i, j; ulong d; if (l < 2) flint_throw(FLINT_ERROR, "(%s): l < 2\n", __func__); fmpz_set_ui(c + 0, k); fmpz_mul_ui(c + 0, c + 0, k + 1); fmpz_set_ui(c + 1, 2 * k + 1); for (i = 2; i < l; i++) { d = k + i; fmpz_add_ui(c + i, c + i - 1, d); for (j = i - 1; j >= 1; j--) { fmpz_mul_ui(c + j, c + j, d); fmpz_add(c + j, c + j, c + j - 1); } fmpz_mul_ui(c + 0, c + 0, d); } } void arb_hypgeom_rising_ui_rs(arb_t res, const arb_t x, ulong n, ulong m, slong prec) { slong i, k, l, m0, climbs, climbs_max, wp; arb_ptr xpow; arb_t t, u; mp_ptr c; TMP_INIT; if (n <= 1) { if (n == 0) arb_one(res); else arb_set_round(res, x, prec); return; } TMP_START; if (m == 0) { if (n <= 6) m = 1 + (prec >= 1024); else if (n <= 16) m = 4; else if (n <= 50) m = 6; else { m0 = n_sqrt(n); m = 8 + 0.2 * pow(FLINT_MAX(0, prec - 4096), 0.4); m = FLINT_MIN(m, m0); m = FLINT_MIN(m, 60); } } wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); climbs_max = FLINT_BIT_COUNT(n - 1) * m; c = TMP_ALLOC(sizeof(mp_limb_t) * climbs_max * m); xpow = _arb_vec_init(m + 1); _arb_vec_set_powers(xpow, x, m + 1, wp); arb_init(t); arb_init(u); for (k = 0; k < n; k += m) { l = FLINT_MIN(m, n - k); climbs = FLINT_BIT_COUNT(k + l - 1) * l; climbs = (climbs + FLINT_BITS - 1) / FLINT_BITS; /* assumes l >= 2 */ if (l == 1) { arb_add_ui(u, x, k, wp); } else { if (climbs == 1) { _arb_hypgeom_rising_coeffs_1(c, k, l); arb_dot_ui(u, xpow + l, 0, xpow, 1, c, 1, l, wp); } else if (climbs == 2) { _arb_hypgeom_rising_coeffs_2(c, k, l); arb_dot_uiui(u, xpow + l, 0, xpow, 1, c, 1, l, wp); } else { fmpz * f = (fmpz *) c; for (i = 0; i < l; i++) fmpz_init(f + i); _arb_hypgeom_rising_coeffs_fmpz(f, k, l); arb_dot_fmpz(u, xpow + l, 0, xpow, 1, f, 1, l, wp); for (i = 0; i < l; i++) fmpz_clear(f + i); } } if (k == 0) arb_swap(t, u); else arb_mul(t, t, u, wp); } arb_set_round(res, t, prec); arb_clear(t); arb_clear(u); _arb_vec_clear(xpow, m + 1); TMP_END; } flint-3.1.3/src/arb_hypgeom/shi_series.c000066400000000000000000000026611461254215100202240ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" /* todo: use a sinch function? */ void _arb_hypgeom_shi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_hypgeom_shi(g, h, prec); _arb_vec_zero(g + 1, len - 1); } else { acb_ptr t; slong i; t = _acb_vec_init(len); for (i = 0; i < hlen; i++) arb_set(acb_realref(t + i), h + i); _acb_hypgeom_shi_series(t, t, hlen, len, prec); for (i = 0; i < len; i++) arb_swap(g + i, acb_realref(t + i)); _acb_vec_clear(t, len); } } void arb_hypgeom_shi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, len); _arb_hypgeom_shi_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/si.c000066400000000000000000000132411461254215100164760ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "arb_hypgeom.h" #define LOG2 0.69314718055994531 #define INV_LOG2 1.4426950408889634074 #define EXP1 2.7182818284590452 double arf_get_d_log2_abs_approx_clamped(const arf_t x); /* todo: minima and maxima at multiples of pi */ void arb_hypgeom_si_wide(arb_t res, const arb_t z, slong prec) { mag_set_ui_2exp_si(arb_radref(res), 1988502269, -30); arf_zero(arb_midref(res)); } void _arb_hypgeom_si_asymp(arb_t res, const arb_t z, slong N, slong prec) { arb_t s, c, sz, cz, u; fmpq a[1]; slong wp; mag_t err, t; int negative; negative = arf_sgn(arb_midref(z)) < 0; if (negative) { arb_neg(res, z); _arb_hypgeom_si_asymp(res, res, N, prec); arb_neg(res, res); return; } N = FLINT_MAX(N, 1); arb_init(s); arb_init(c); arb_init(sz); arb_init(cz); arb_init(u); mag_init(err); mag_init(t); /* Error is bounded by first omitted term, N! / z^N */ arb_get_mag_lower(err, z); /* Do something better on wide intervals */ if (mag_cmp_2exp_si(err, 1) < 0) { arb_hypgeom_si_wide(res, z, prec); } else { mag_inv(err, err); mag_pow_ui(err, err, N); mag_fac_ui(t, N); mag_mul(err, err, t); wp = prec * 1.001 + 5; arb_set(u, z); *fmpq_numref(&a[0]) = 1; *fmpq_denref(&a[0]) = 1; arb_hypgeom_sum_fmpq_imag_arb(c, s, a, 1, NULL, 0, u, 1, N, wp); arb_add_error_mag(c, err); arb_add_error_mag(s, err); arb_sin_cos(sz, cz, z, wp); arb_mul(s, s, sz, wp); arb_addmul(s, c, cz, wp); arb_div(s, s, z, wp); arb_const_pi(u, wp); arb_mul_2exp_si(u, u, -1); arb_sub(res, u, s, prec); } arb_clear(s); arb_clear(c); arb_clear(sz); arb_clear(cz); arb_clear(u); mag_clear(err); mag_clear(t); } void _arb_hypgeom_si_1f2(arb_t res, const arb_t z, slong N, slong wp, slong prec) { mag_t err, t; arb_t s, u; fmpq a[1]; fmpq b[3]; N = FLINT_MAX(N, 1); mag_init(err); mag_init(t); arb_init(s); arb_init(u); arb_sqr(u, z, wp); arb_mul_2exp_si(u, u, -2); arb_neg(u, u); *fmpq_numref(&a[0]) = 1; *fmpq_denref(&a[0]) = 2; *fmpq_numref(&b[0]) = 3; *fmpq_denref(&b[0]) = 2; *fmpq_numref(&b[1]) = 3; *fmpq_denref(&b[1]) = 2; *fmpq_numref(&b[2]) = 1; *fmpq_denref(&b[2]) = 1; /* Terms are bounded by u^N / (4 (N!)^2) */ arb_get_mag(err, u); /* u^N */ mag_set(t, err); mag_pow_ui(t, t, N); /* geometric factor for u/N^2 */ mag_div_ui(err, err, N); mag_div_ui(err, err, N); mag_geom_series(err, err, 0); mag_mul(t, t, err); /* 1/(N!)^2 */ mag_rfac_ui(err, N); mag_mul(err, err, err); mag_mul(err, err, t); /* 1/4 */ mag_mul_2exp_si(err, err, -2); arb_hypgeom_sum_fmpq_arb(s, a, 1, b, 3, u, 0, N, wp); arb_add_error_mag(s, err); arb_mul(res, s, z, prec); mag_clear(err); mag_clear(t); arb_clear(u); arb_clear(s); } void arb_hypgeom_si(arb_t res, const arb_t z, slong prec) { slong wp, N, acc; double dz, du; if (!arb_is_finite(z)) { arb_indeterminate(res); return; } if (arb_is_zero(z)) { arb_zero(res); return; } if (ARF_IS_LAGOM(arb_midref(z))) { acc = arb_rel_accuracy_bits(z); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); acc += FLINT_MAX(0, ARF_EXP(arb_midref(z))); prec = FLINT_MIN(prec, acc + 32); } dz = fabs(arf_get_d(arb_midref(z), ARF_RND_DOWN)); dz = FLINT_MIN(dz, 1e300); if (dz > 2.0) { double log2_err, err_prev, log2dz; log2dz = arf_get_d_log2_abs_approx_clamped(arb_midref(z)); err_prev = 0.0; for (N = 1; N < 2 * prec; N++) { log2_err = ((N + 1.0) * (log(N + 1.0) - 1.0)) * INV_LOG2 - N * log2dz; if (log2_err > err_prev) break; if (log2_err < -prec - 2) { _arb_hypgeom_si_asymp(res, z, N, prec); return; } err_prev = log2_err; } } if (arf_cmpabs_2exp_si(arb_midref(z), -30) < 0) { N = -arf_abs_bound_lt_2exp_si(arb_midref(z)); wp = prec * 1.001 + 10; N = (prec + N - 1) / N; } else { du = 0.25 * dz * dz; wp = prec * 1.001 + 10; if (du > 1.0) wp += dz * 1.4426950408889634; N = (prec + 5) * LOG2 / (2 * d_lambertw((prec + 5) * LOG2 / (2 * EXP1 * sqrt(du)))) + 1; } if (arb_is_exact(z)) { _arb_hypgeom_si_1f2(res, z, N, wp, prec); } else { mag_t err; arb_t zmid; mag_init(err); arb_init(zmid); arb_get_mid_arb(zmid, z); /* |si'(z)| = |sinc(z)| <= min(1, 1/z) */ arb_get_mag_lower(err, z); mag_inv(err, err); if (mag_cmp_2exp_si(err, 0) > 0) mag_one(err); mag_mul(err, err, arb_radref(z)); /* |si(a) - si(b)| < 4 */ if (mag_cmp_2exp_si(err, 2) > 0) mag_set_ui(err, 4); _arb_hypgeom_si_1f2(res, zmid, N, wp, prec); arb_add_error_mag(res, err); arb_clear(zmid); mag_clear(err); } } flint-3.1.3/src/arb_hypgeom/si_series.c000066400000000000000000000032011461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" void _arb_hypgeom_si_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { arb_t c; arb_init(c); arb_hypgeom_si(c, h, prec); hlen = FLINT_MIN(hlen, len); if (hlen == 1) { _arb_vec_zero(g + 1, len - 1); } else if (len == 2) { arb_sinc(g, h, prec); arb_mul(g + 1, g, h + 1, prec); } else { arb_ptr t, u; t = _arb_vec_init(len - 1); u = _arb_vec_init(hlen - 1); /* Si(h(x)) = integral(h'(x) sinc(h(x))) */ _arb_poly_sinc_series(t, h, hlen, len - 1, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_mullow(g, t, len - 1, u, hlen - 1, len - 1, prec); _arb_poly_integral(g, g, len, prec); _arb_vec_clear(t, len - 1); _arb_vec_clear(u, hlen - 1); } arb_swap(g, c); arb_clear(c); } void arb_hypgeom_si_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec) { slong hlen = h->length; if (hlen == 0 || len == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, len); _arb_hypgeom_si_series(g->coeffs, h->coeffs, hlen, len, prec); _arb_poly_set_length(g, len); _arb_poly_normalise(g); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_arb.c000066400000000000000000000016761461254215100205470ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_sum_fmpq_arb(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { if (N <= 2 || (prec <= 1024 && N <= 8) || (prec <= 4096 && N <= 4)) arb_hypgeom_sum_fmpq_arb_forward(res, a, alen, b, blen, z, reciprocal, N, prec); else if (prec >= 8192 && arb_bits(z) <= 0.001 * prec) arb_hypgeom_sum_fmpq_arb_bs(res, a, alen, b, blen, z, reciprocal, N, prec); else arb_hypgeom_sum_fmpq_arb_rs(res, a, alen, b, blen, z, reciprocal, N, prec); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_arb_bs.c000066400000000000000000000074741461254215100212350ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" static void factor(arb_t A, const fmpq * a, slong alen, const fmpq * b, slong blen, const fmpz_t bden, const arb_t z, slong k, slong prec) { slong i; fmpz_t t, u; fmpz_init(t); fmpz_init(u); if (alen == 0) { if (z == NULL) arb_set_fmpz(A, bden); else if (fmpz_is_one(bden)) arb_set(A, z); else arb_mul_fmpz(A, z, bden, prec); } else { /* product of a_i + k = p/q + k = (p + k*q)/q */ fmpz_mul_ui(t, fmpq_denref(a + 0), k); fmpz_add(t, t, fmpq_numref(a + 0)); for (i = 1; i < alen; i++) { fmpz_mul_ui(u, fmpq_denref(a + i), k); fmpz_add(u, u, fmpq_numref(a + i)); fmpz_mul(t, t, u); } if (!fmpz_is_one(bden)) fmpz_mul(t, t, bden); if (z == NULL) arb_set_fmpz(A, t); else arb_mul_fmpz(A, z, t, prec); } fmpz_clear(t); fmpz_clear(u); } static void bsplit(arb_t A1, arb_t B1, arb_t C1, const fmpq * a, slong alen, const fmpz_t aden, const fmpq * b, slong blen, const fmpz_t bden, const arb_t z, int reciprocal, slong aa, slong bb, slong prec) { if (bb - aa == 1) { factor(A1, a, alen, b, blen, bden, reciprocal ? NULL : z, aa, prec); factor(C1, b, blen, a, alen, aden, reciprocal ? z : NULL, aa, prec); /* arb_set(B1, C1); but we skip this */ } else { slong m; arb_t A2, B2, C2; arb_init(A2); arb_init(B2); arb_init(C2); m = aa + (bb - aa) / 2; bsplit(A1, B1, C1, a, alen, aden, b, blen, bden, z, reciprocal, aa, m, prec); bsplit(A2, B2, C2, a, alen, aden, b, blen, bden, z, reciprocal, m, bb, prec); if (bb - m == 1) /* B2 = C2 */ { if (m - aa == 1) arb_add(B2, A1, C1, prec); else arb_add(B2, A1, B1, prec); arb_mul(B1, B2, C2, prec); } else { if (m - aa == 1) arb_mul(B1, C1, C2, prec); else arb_mul(B1, B1, C2, prec); arb_addmul(B1, A1, B2, prec); } arb_mul(A1, A1, A2, prec); arb_mul(C1, C1, C2, prec); arb_clear(A2); arb_clear(B2); arb_clear(C2); } } void arb_hypgeom_sum_fmpq_arb_bs(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { arb_t u, v, w; fmpz_t aden, bden; slong i; if (N <= 3) { arb_hypgeom_sum_fmpq_arb_forward(res, a, alen, b, blen, z, reciprocal, N, prec); return; } arb_init(u); arb_init(v); arb_init(w); fmpz_init(aden); fmpz_init(bden); fmpz_one(aden); fmpz_one(bden); for (i = 0; i < alen; i++) fmpz_mul(aden, aden, fmpq_denref(a + i)); for (i = 0; i < blen; i++) fmpz_mul(bden, bden, fmpq_denref(b + i)); /* we compute to N-1 instead of N to avoid dividing by 0 in the denominator when computing a hypergeometric polynomial that terminates right before a pole */ bsplit(u, v, w, a, alen, aden, b, blen, bden, z, reciprocal, 0, N - 1, prec); arb_add(res, u, v, prec); /* s = s + t */ arb_div(res, res, w, prec); arb_clear(u); arb_clear(v); arb_clear(w); fmpz_clear(aden); fmpz_clear(bden); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_arb_forward.c000066400000000000000000000115341461254215100222650ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_sum_fmpq_arb_forward(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { arb_t t, u, sden; slong i, k, num_max_bits, den_max_bits, bits1, bits2, Nbits, den_prec; if (N <= 1) { if (N == 1) arb_one(res); else arb_zero(res); return; } arb_init(t); arb_init(u); arb_init(sden); Nbits = FLINT_BIT_COUNT(N); num_max_bits = 0; for (i = 0; i < alen; i++) { bits1 = fmpz_bits(fmpq_numref(a + i)); bits2 = fmpz_bits(fmpq_denref(a + i)) + Nbits; num_max_bits += FLINT_MAX(bits1, bits2) + 1; } den_max_bits = 0; for (i = 0; i < blen; i++) { bits1 = fmpz_bits(fmpq_numref(b + i)); bits2 = fmpz_bits(fmpq_denref(b + i)) + Nbits; den_max_bits += FLINT_MAX(bits1, bits2) + 1; } den_prec = FLINT_MAX(128, prec + 2 * Nbits); if (num_max_bits <= FLINT_BITS - 1 && den_max_bits <= FLINT_BITS - 1) { slong num, den; den = 1; num = 1; for (i = 0; i < alen; i++) den *= *fmpq_denref(a + i); for (i = 0; i < blen; i++) num *= *fmpq_denref(b + i); if (reciprocal) { arb_mul_si(u, z, den, prec); arb_set_si(t, num); arb_div(u, t, u, prec); } else { arb_mul_si(u, z, num, prec); arb_div_si(u, u, den, prec); } arb_one(res); arb_one(t); arb_one(sden); for (k = 1; k < N && !arb_is_zero(t); k++) { arb_mul(t, t, u, prec); if (alen != 0) { num = *fmpq_denref(a + 0) * (k - 1) + *fmpq_numref(a + 0); for (i = 1; i < alen; i++) num *= (*fmpq_denref(a + i) * (k - 1) + *fmpq_numref(a + i)); arb_mul_si(t, t, num, prec); } if (blen != 0) { den = *fmpq_denref(b + 0) * (k - 1) + *fmpq_numref(b + 0); for (i = 1; i < blen; i++) den *= (*fmpq_denref(b + i) * (k - 1) + *fmpq_numref(b + i)); arb_fma_si(res, res, den, t, prec); arb_mul_si(sden, sden, den, den_prec); } else { arb_add(res, res, t, prec); } } arb_div(res, res, sden, prec); } else { fmpz_t num, den, c; fmpz_init(num); fmpz_init(den); fmpz_init(c); fmpz_one(den); fmpz_one(num); for (i = 0; i < alen; i++) fmpz_mul(den, den, fmpq_denref(a + i)); for (i = 0; i < blen; i++) fmpz_mul(num, num, fmpq_denref(b + i)); if (reciprocal) { arb_mul_fmpz(u, z, den, prec); arb_set_fmpz(t, num); arb_div(u, t, u, prec); } else { arb_mul_fmpz(u, z, num, prec); arb_div_fmpz(u, u, den, prec); } arb_one(res); arb_one(t); arb_one(sden); for (k = 1; k < N && !arb_is_zero(t); k++) { arb_mul(t, t, u, prec); if (alen != 0) { fmpz_mul_ui(num, fmpq_denref(a + 0), k - 1); fmpz_add(num, num, fmpq_numref(a + 0)); for (i = 1; i < alen; i++) { fmpz_mul_ui(c, fmpq_denref(a + i), k - 1); fmpz_add(c, c, fmpq_numref(a + i)); fmpz_mul(num, num, c); } arb_mul_fmpz(t, t, num, prec); } if (blen != 0) { fmpz_mul_ui(den, fmpq_denref(b + 0), k - 1); fmpz_add(den, den, fmpq_numref(b + 0)); for (i = 1; i < blen; i++) { fmpz_mul_ui(c, fmpq_denref(b + i), k - 1); fmpz_add(c, c, fmpq_numref(b + i)); fmpz_mul(den, den, c); } arb_fma_fmpz(res, res, den, t, prec); arb_mul_fmpz(sden, sden, den, den_prec); } else { arb_add(res, res, t, prec); } } arb_div(res, res, sden, prec); fmpz_clear(num); fmpz_clear(den); fmpz_clear(c); } arb_clear(t); arb_clear(u); arb_clear(sden); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_arb_rs.c000066400000000000000000000227411461254215100212470ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp # define log __builtin_log #else # include #endif static double d_log2_fac(double n) { return (n * (log(n) - 1.0)) * 1.4426950408889634; } static slong tail_precision(slong k, double min_k, slong alen, slong blen, double log2z, double log2max, slong prec) { double term_magnitude; slong new_prec; if (prec <= 128 || k <= 5 || k <= min_k) return prec; term_magnitude = k * log2z; if (alen != blen) term_magnitude += (alen - blen) * d_log2_fac(k); new_prec = prec - (log2max - term_magnitude) + 10; new_prec = FLINT_MIN(new_prec, prec); new_prec = FLINT_MAX(new_prec, 32); /* printf("term %ld, max %f, log2x %f, magn %f new_prec %ld\n", k, log2z, log2max, term_magnitude, new_prec); */ return new_prec; } /* Return approximation of log2(|x|), approximately clamped between COEFF_MIN and COEFF_MAX. */ double arf_get_d_log2_abs_approx_clamped(const arf_t x) { if (arf_is_zero(x)) { return (double) COEFF_MIN; } else if (!arf_is_finite(x)) { return (double) COEFF_MAX; } else if (COEFF_IS_MPZ(ARF_EXP(x))) { if (fmpz_sgn(ARF_EXPREF(x)) < 0) return (double) COEFF_MIN; else return (double) COEFF_MAX; } else { mp_srcptr tp; mp_size_t tn; double v; slong e = ARF_EXP(x); ARF_GET_MPN_READONLY(tp, tn, x); if (tn == 1) v = (double)(tp[0]); else v = (double)(tp[tn - 1]) + (double)(tp[tn - 2]) * ldexp(1.0, -FLINT_BITS); v *= ldexp(1.0, -FLINT_BITS); return 1.4426950408889634074 * mag_d_log_upper_bound(v) + (double) e; } } void arb_hypgeom_sum_fmpq_arb_rs(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { slong m, i, j, k, l, jlen, jbot, jtop, wp; double log2z, log2max, adaptive_min_k; int want_adaptive_precision; arb_t s, t; arb_ptr zpow; fmpz_t c, den; fmpz * cs; slong Nbits, acbits, bcbits, numbits, denbits; if (N <= 1) { if (N == 1) arb_one(res); else arb_zero(res); return; } m = n_sqrt(N); m = FLINT_MAX(m, 2); k = N - 1; j = k % m; jlen = 0; jbot = j; fmpz_init(c); fmpz_init(den); arb_init(s); arb_init(t); zpow = _arb_vec_init(m + 1); cs = _fmpz_vec_init(m + 1); fmpz_one(c); fmpz_one(den); for (i = 0; i < alen; i++) fmpz_mul(den, den, fmpq_denref(a + i)); for (i = 0; i < blen; i++) fmpz_mul(c, c, fmpq_denref(b + i)); if (reciprocal) { arb_mul_fmpz(zpow + m, z, den, prec); arb_set_fmpz(t, c); arb_div(zpow + m, t, zpow + m, prec); } else { arb_mul_fmpz(zpow + m, z, c, prec); arb_div_fmpz(zpow + m, zpow + m, den, prec); } want_adaptive_precision = N > 5; Nbits = FLINT_BIT_COUNT(N); acbits = 0; for (i = 0; i < alen; i++) { numbits = fmpz_bits(fmpq_numref(a + i)); denbits = fmpz_bits(fmpq_denref(a + i)); want_adaptive_precision = want_adaptive_precision && (FLINT_ABS(numbits - denbits) < 2); acbits += FLINT_MAX(denbits + Nbits, numbits) + 1; } bcbits = 0; for (i = 0; i < blen; i++) { numbits = fmpz_bits(fmpq_numref(b + i)); denbits = fmpz_bits(fmpq_denref(b + i)); want_adaptive_precision = want_adaptive_precision && (FLINT_ABS(numbits - denbits) < 2); bcbits += FLINT_MAX(denbits + Nbits, numbits) + 1; } log2max = 0.0; log2z = 0.0; adaptive_min_k = 0.0; if (want_adaptive_precision) { log2z = arf_get_d_log2_abs_approx_clamped(arb_midref(z)); if (reciprocal) log2z = -log2z; /* Terms are increasing, so don't change the precision. */ if (alen >= blen && log2z >= 0.0) { want_adaptive_precision = 0; } else { if (alen >= blen) { log2max = 0.0; } else { slong r = blen - alen; /* r = 1 -> exp(z) */ /* r = 2 -> exp(2*z^(1/2)) */ /* r = 3 -> exp(3*z^(1/3)) */ /* ... */ #ifdef __GNUC__ log2max = r * __builtin_exp(log2z * 0.693147180559945 / r) * 1.44269504088896; /* fixme */ if (r == 1) adaptive_min_k = __builtin_exp(log2z * log(2)); else adaptive_min_k = __builtin_exp(0.5 * log2z * log(2)); #else log2max = r * exp(log2z * 0.693147180559945 / r) * 1.44269504088896; /* fixme */ if (r == 1) adaptive_min_k = exp(log2z * log(2)); else adaptive_min_k = exp(0.5 * log2z * log(2)); #endif } } } _arb_vec_set_powers(zpow, zpow + m, m + 1, prec); while (k >= 0) { jlen = 1; jtop = jbot = k; if (jtop > 0) { while (jlen <= j && jlen <= 8 && jbot >= 2) { jbot--; jlen++; } } if (jbot != jtop - jlen + 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* Factors between jbot and jtop inclusive */ if (jbot == 0 || alen == 0) { fmpz_one(cs + 0); } else { if (acbits <= FLINT_BITS - 1) { slong ac; ac = 1; for (l = 0; l < alen; l++) ac *= *fmpq_denref(a + l) * (jbot - 1) + *fmpq_numref(a + l); fmpz_set_si(cs + 0, ac); } else { fmpz_mul_ui(cs + 0, fmpq_denref(a + 0), jbot - 1); fmpz_add(cs + 0, cs + 0, fmpq_numref(a + 0)); for (l = 1; l < alen; l++) { fmpz_mul_ui(c, fmpq_denref(a + l), jbot - 1); fmpz_add(c, c, fmpq_numref(a + l)); fmpz_mul(cs + 0, cs + 0, c); } } } for (i = 1; i < jlen; i++) { if (alen == 0) { fmpz_set(cs + i, cs + i - 1); } else { if (acbits <= FLINT_BITS - 1) { slong ac; ac = 1; for (l = 0; l < alen; l++) ac *= *fmpq_denref(a + l) * (jbot + i - 1) + *fmpq_numref(a + l); fmpz_mul_si(cs + i, cs + i - 1, ac); } else { fmpz_mul_ui(cs + i, fmpq_denref(a + 0), jbot + i - 1); fmpz_add(cs + i, cs + i, fmpq_numref(a + 0)); for (l = 1; l < alen; l++) { fmpz_mul_ui(c, fmpq_denref(a + l), jbot + i - 1); fmpz_add(c, c, fmpq_numref(a + l)); fmpz_mul(cs + i, cs + i, c); } fmpz_mul(cs + i, cs + i, cs + i - 1); } } } if (blen != 0) { fmpz_one(den); for (i = jlen - 1; i >= 0; i--) { if (i != jlen - 1) fmpz_mul(cs + i, cs + i, den); if (i != 0 || jbot != 0) { if (bcbits <= FLINT_BITS - 1) { slong bc; bc = 1; for (l = 0; l < blen; l++) bc *= *fmpq_denref(b + l) * (jbot + i - 1) + *fmpq_numref(b + l); fmpz_mul_si(den, den, bc); } else { for (l = 0; l < blen; l++) { fmpz_mul_ui(c, fmpq_denref(b + l), jbot + i - 1); fmpz_add(c, c, fmpq_numref(b + l)); fmpz_mul(den, den, c); } } } } } if (want_adaptive_precision) wp = tail_precision(k - jlen, adaptive_min_k, alen, blen, log2z, log2max, prec); else wp = prec; arb_add(t, s, zpow + j, wp); arb_swap(zpow + j, t); arb_dot_fmpz(s, NULL, 0, zpow + j - jlen + 1, 1, cs, 1, jlen, wp); arb_swap(zpow + j, t); if (blen != 0) arb_div_fmpz(s, s, den, wp); k -= jlen; j -= (jlen - 1); if (j == 0 && k >= 1) { arb_mul(s, s, zpow + m, wp); j = m - 1; } else { j--; } } arb_swap(res, s); _arb_vec_clear(zpow, m + 1); _fmpz_vec_clear(cs, m + 1); arb_clear(s); arb_clear(t); fmpz_clear(c); fmpz_clear(den); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_imag_arb.c000066400000000000000000000017321461254215100215350ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_sum_fmpq_imag_arb(arb_t res1, arb_t res2, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { if (N <= 10 || (prec <= 1024 && N <= 16)) arb_hypgeom_sum_fmpq_imag_arb_forward(res1, res2, a, alen, b, blen, z, reciprocal, N, prec); else if (prec >= 8192 && arb_bits(z) <= 0.001 * prec) arb_hypgeom_sum_fmpq_imag_arb_bs(res1, res2, a, alen, b, blen, z, reciprocal, N, prec); else arb_hypgeom_sum_fmpq_imag_arb_rs(res1, res2, a, alen, b, blen, z, reciprocal, N, prec); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_imag_arb_bs.c000066400000000000000000000103131461254215100222140ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" static void factor(arb_t A, const fmpq * a, slong alen, const fmpq * b, slong blen, const fmpz_t bden, const arb_t z, slong k, slong prec) { slong i; fmpz_t t, u; fmpz_init(t); fmpz_init(u); if (alen == 0) { if (z == NULL) arb_set_fmpz(A, bden); else if (fmpz_is_one(bden)) arb_set(A, z); else arb_mul_fmpz(A, z, bden, prec); } else { /* product of a_i + k = p/q + k = (p + k*q)/q */ fmpz_mul_ui(t, fmpq_denref(a + 0), k); fmpz_add(t, t, fmpq_numref(a + 0)); for (i = 1; i < alen; i++) { fmpz_mul_ui(u, fmpq_denref(a + i), k); fmpz_add(u, u, fmpq_numref(a + i)); fmpz_mul(t, t, u); } if (!fmpz_is_one(bden)) fmpz_mul(t, t, bden); if (z == NULL) arb_set_fmpz(A, t); else arb_mul_fmpz(A, z, t, prec); } fmpz_clear(t); fmpz_clear(u); } static void bsplit(acb_t A1, acb_t B1, acb_t C1, const fmpq * a, slong alen, const fmpz_t aden, const fmpq * b, slong blen, const fmpz_t bden, const arb_t z, int reciprocal, slong aa, slong bb, slong prec) { if (bb - aa == 1) { factor(acb_realref(A1), a, alen, b, blen, bden, reciprocal ? NULL : z, aa, prec); factor(acb_realref(C1), b, blen, a, alen, aden, reciprocal ? z : NULL, aa, prec); arb_zero(acb_imagref(A1)); arb_zero(acb_imagref(C1)); if (reciprocal) acb_div_onei(C1, C1); else acb_mul_onei(A1, A1); /* arb_set(B1, C1); but we skip this */ } else { slong m; acb_t A2, B2, C2; acb_init(A2); acb_init(B2); acb_init(C2); m = aa + (bb - aa) / 2; bsplit(A1, B1, C1, a, alen, aden, b, blen, bden, z, reciprocal, aa, m, prec); bsplit(A2, B2, C2, a, alen, aden, b, blen, bden, z, reciprocal, m, bb, prec); if (bb - m == 1) /* B2 = C2 */ { if (m - aa == 1) acb_add(B2, A1, C1, prec); else acb_add(B2, A1, B1, prec); acb_mul(B1, B2, C2, prec); } else { if (m - aa == 1) acb_mul(B1, C1, C2, prec); else acb_mul(B1, B1, C2, prec); acb_addmul(B1, A1, B2, prec); } acb_mul(A1, A1, A2, prec); acb_mul(C1, C1, C2, prec); acb_clear(A2); acb_clear(B2); acb_clear(C2); } } void arb_hypgeom_sum_fmpq_imag_arb_bs(arb_t res_real, arb_t res_imag, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { acb_t u, v, w; fmpz_t aden, bden; slong i; if (N <= 3) { arb_hypgeom_sum_fmpq_imag_arb_forward(res_real, res_imag, a, alen, b, blen, z, reciprocal, N, prec); return; } acb_init(u); acb_init(v); acb_init(w); fmpz_init(aden); fmpz_init(bden); fmpz_one(aden); fmpz_one(bden); for (i = 0; i < alen; i++) fmpz_mul(aden, aden, fmpq_denref(a + i)); for (i = 0; i < blen; i++) fmpz_mul(bden, bden, fmpq_denref(b + i)); /* we compute to N-1 instead of N to avoid dividing by 0 in the denominator when computing a hypergeometric polynomial that terminates right before a pole */ bsplit(u, v, w, a, alen, aden, b, blen, bden, z, reciprocal, 0, N - 1, prec); acb_add(u, u, v, prec); /* s = s + t */ acb_div(u, u, w, prec); if (!acb_is_finite(u)) acb_indeterminate(u); arb_swap(res_real, acb_realref(u)); arb_swap(res_imag, acb_imagref(u)); acb_clear(u); acb_clear(v); acb_clear(w); fmpz_clear(aden); fmpz_clear(bden); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_imag_arb_forward.c000066400000000000000000000164601461254215100232650ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_hypgeom.h" void arb_hypgeom_sum_fmpq_imag_arb_forward(arb_t s_real, arb_t s_imag, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { arb_t t, u, sden; slong i, k, num_max_bits, den_max_bits, bits1, bits2, Nbits, den_prec;; if (N <= 1) { if (N == 1) arb_one(s_real); else arb_zero(s_real); arb_zero(s_imag); return; } arb_init(t); arb_init(u); arb_init(sden); Nbits = FLINT_BIT_COUNT(N); num_max_bits = 0; for (i = 0; i < alen; i++) { bits1 = fmpz_bits(fmpq_numref(a + i)); bits2 = fmpz_bits(fmpq_denref(a + i)) + Nbits; num_max_bits += FLINT_MAX(bits1, bits2) + 1; } den_max_bits = 0; for (i = 0; i < blen; i++) { bits1 = fmpz_bits(fmpq_numref(b + i)); bits2 = fmpz_bits(fmpq_denref(b + i)) + Nbits; den_max_bits += FLINT_MAX(bits1, bits2) + 1; } den_prec = FLINT_MAX(128, prec + 2 * Nbits); if (num_max_bits <= FLINT_BITS - 1 && den_max_bits <= FLINT_BITS - 1) { slong num, den; den = 1; num = 1; for (i = 0; i < alen; i++) den *= *fmpq_denref(a + i); for (i = 0; i < blen; i++) num *= *fmpq_denref(b + i); if (reciprocal) { arb_mul_si(u, z, den, prec); arb_set_si(t, num); arb_div(u, t, u, prec); } else { arb_mul_si(u, z, num, prec); arb_div_si(u, u, den, prec); } arb_one(s_real); arb_zero(s_imag); arb_one(t); arb_one(sden); for (k = 1; k < N && !arb_is_zero(t); k++) { arb_mul(t, t, u, prec); if (alen != 0) { num = *fmpq_denref(a + 0) * (k - 1) + *fmpq_numref(a + 0); for (i = 1; i < alen; i++) num *= (*fmpq_denref(a + i) * (k - 1) + *fmpq_numref(a + i)); arb_mul_si(t, t, num, prec); } if (blen != 0) { den = *fmpq_denref(b + 0) * (k - 1) + *fmpq_numref(b + 0); for (i = 1; i < blen; i++) den *= (*fmpq_denref(b + i) * (k - 1) + *fmpq_numref(b + i)); if (k % 4 == 0) { arb_fma_si(s_real, s_real, den, t, prec); arb_mul_si(s_imag, s_imag, den, prec); } else if (k % 4 == 1) { arb_fma_si(s_imag, s_imag, den, t, prec); arb_mul_si(s_real, s_real, den, prec); } else if (k % 4 == 2) { arb_neg(t, t); arb_fma_si(s_real, s_real, den, t, prec); arb_neg(t, t); arb_mul_si(s_imag, s_imag, den, prec); } else { arb_neg(t, t); arb_fma_si(s_imag, s_imag, den, t, prec); arb_neg(t, t); arb_mul_si(s_real, s_real, den, prec); } arb_mul_si(sden, sden, den, den_prec); } else { if (k % 4 == 0) arb_add(s_real, s_real, t, prec); else if (k % 4 == 1) arb_add(s_imag, s_imag, t, prec); else if (k % 4 == 2) arb_sub(s_real, s_real, t, prec); else arb_sub(s_imag, s_imag, t, prec); } } arb_div(s_real, s_real, sden, prec); arb_div(s_imag, s_imag, sden, prec); } else { fmpz_t num, den, c; fmpz_init(num); fmpz_init(den); fmpz_init(c); fmpz_one(den); fmpz_one(num); for (i = 0; i < alen; i++) fmpz_mul(den, den, fmpq_denref(a + i)); for (i = 0; i < blen; i++) fmpz_mul(num, num, fmpq_denref(b + i)); if (reciprocal) { arb_mul_fmpz(u, z, den, prec); arb_set_fmpz(t, num); arb_div(u, t, u, prec); } else { arb_mul_fmpz(u, z, num, prec); arb_div_fmpz(u, u, den, prec); } arb_one(s_real); arb_zero(s_imag); arb_one(t); arb_one(sden); for (k = 1; k < N && !arb_is_zero(t); k++) { arb_mul(t, t, u, prec); if (alen != 0) { fmpz_mul_ui(num, fmpq_denref(a + 0), k - 1); fmpz_add(num, num, fmpq_numref(a + 0)); for (i = 1; i < alen; i++) { fmpz_mul_ui(c, fmpq_denref(a + i), k - 1); fmpz_add(c, c, fmpq_numref(a + i)); fmpz_mul(num, num, c); } arb_mul_fmpz(t, t, num, prec); } if (blen != 0) { fmpz_mul_ui(den, fmpq_denref(b + 0), k - 1); fmpz_add(den, den, fmpq_numref(b + 0)); for (i = 1; i < blen; i++) { fmpz_mul_ui(c, fmpq_denref(b + i), k - 1); fmpz_add(c, c, fmpq_numref(b + i)); fmpz_mul(den, den, c); } if (k % 4 == 0) { arb_fma_fmpz(s_real, s_real, den, t, prec); arb_mul_fmpz(s_imag, s_imag, den, prec); } else if (k % 4 == 1) { arb_fma_fmpz(s_imag, s_imag, den, t, prec); arb_mul_fmpz(s_real, s_real, den, prec); } else if (k % 4 == 2) { arb_neg(t, t); arb_fma_fmpz(s_real, s_real, den, t, prec); arb_neg(t, t); arb_mul_fmpz(s_imag, s_imag, den, prec); } else { arb_neg(t, t); arb_fma_fmpz(s_imag, s_imag, den, t, prec); arb_neg(t, t); arb_mul_fmpz(s_real, s_real, den, prec); } arb_mul_fmpz(sden, sden, den, den_prec); } else { if (k % 4 == 0) arb_add(s_real, s_real, t, prec); else if (k % 4 == 1) arb_add(s_imag, s_imag, t, prec); else if (k % 4 == 2) arb_sub(s_real, s_real, t, prec); else arb_sub(s_imag, s_imag, t, prec); } } arb_div(s_real, s_real, sden, prec); arb_div(s_imag, s_imag, sden, prec); fmpz_clear(num); fmpz_clear(den); fmpz_clear(c); } arb_clear(t); arb_clear(u); arb_clear(sden); } flint-3.1.3/src/arb_hypgeom/sum_fmpq_imag_arb_rs.c000066400000000000000000000247261461254215100222510ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif static double d_log2_fac(double n) { return (n * (log(n) - 1.0)) * 1.4426950408889634; } static slong tail_precision(slong k, double min_k, slong alen, slong blen, double log2z, double log2max, slong prec) { double term_magnitude; slong new_prec; if (prec <= 128 || k <= 5 || k <= min_k) return prec; term_magnitude = k * log2z; if (alen != blen) term_magnitude += (alen - blen) * d_log2_fac(k); new_prec = prec - (log2max - term_magnitude) + 10; new_prec = FLINT_MIN(new_prec, prec); new_prec = FLINT_MAX(new_prec, 32); /* printf("term %ld, max %f, log2x %f, magn %f new_prec %ld\n", k, log2z, log2max, term_magnitude, new_prec); */ return new_prec; } /* Return approximation of log2(|x|), clambed between COEFF_MIN and COEFF_MAX. */ double arf_get_d_log2_abs_approx_clamped(const arf_t x); void arb_hypgeom_sum_fmpq_imag_arb_rs(arb_t res_real, arb_t res_imag, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec) { slong m, i, j, k, l, jlen, jbot, jtop, wp; double log2z, log2max, adaptive_min_k; int want_adaptive_precision; arb_t s_real, s_imag, t_real, t_imag; arb_ptr zpow; fmpz_t c, den; fmpz * cs; slong Nbits, acbits, bcbits, numbits, denbits; m = n_sqrt(N); m = FLINT_MAX(m, 2); k = N - 1; j = k % m; jlen = 0; jbot = j; fmpz_init(c); fmpz_init(den); arb_init(s_real); arb_init(s_imag); arb_init(t_real); arb_init(t_imag); zpow = _arb_vec_init(m + 1); cs = _fmpz_vec_init(m + 1); fmpz_one(c); fmpz_one(den); for (i = 0; i < alen; i++) fmpz_mul(den, den, fmpq_denref(a + i)); for (i = 0; i < blen; i++) fmpz_mul(c, c, fmpq_denref(b + i)); if (reciprocal) { arb_mul_fmpz(zpow + m, z, den, prec); arb_set_fmpz(t_real, c); arb_div(zpow + m, t_real, zpow + m, prec); } else { arb_mul_fmpz(zpow + m, z, c, prec); arb_div_fmpz(zpow + m, zpow + m, den, prec); } want_adaptive_precision = N > 5; Nbits = FLINT_BIT_COUNT(N); acbits = 0; for (i = 0; i < alen; i++) { numbits = fmpz_bits(fmpq_numref(a + i)); denbits = fmpz_bits(fmpq_denref(a + i)); want_adaptive_precision = want_adaptive_precision && (FLINT_ABS(numbits - denbits) < 2); acbits += FLINT_MAX(denbits + Nbits, numbits) + 1; } bcbits = 0; for (i = 0; i < blen; i++) { numbits = fmpz_bits(fmpq_numref(b + i)); denbits = fmpz_bits(fmpq_denref(b + i)); want_adaptive_precision = want_adaptive_precision && (FLINT_ABS(numbits - denbits) < 2); bcbits += FLINT_MAX(denbits + Nbits, numbits) + 1; } log2max = 0.0; log2z = 0.0; adaptive_min_k = 0.0; if (want_adaptive_precision) { log2z = arf_get_d_log2_abs_approx_clamped(arb_midref(z)); if (reciprocal) log2z = -log2z; /* Terms are increasing, so don't change the precision. */ if (alen >= blen && log2z >= 0.0) { want_adaptive_precision = 0; } else { if (alen >= blen) { log2max = 0.0; adaptive_min_k = N; } else { slong r = blen - alen; /* r = 1 -> exp(z) */ /* r = 2 -> exp(2*z^(1/2)) */ /* r = 3 -> exp(3*z^(1/3)) */ /* ... */ #ifdef __GNUC__ log2max = r * __builtin_exp(log2z * 0.693147180559945 / r) * 1.44269504088896; /* fixme */ if (r == 1) adaptive_min_k = __builtin_exp(log2z * log(2)); else adaptive_min_k = __builtin_exp(0.5 * log2z * log(2)); #else log2max = r * exp(log2z * 0.693147180559945 / r) * 1.44269504088896; /* fixme */ if (r == 1) adaptive_min_k = exp(log2z * log(2)); else adaptive_min_k = exp(0.5 * log2z * log(2)); #endif } } } _arb_vec_set_powers(zpow, zpow + m, m + 1, prec); while (k >= 0) { jlen = 1; jtop = jbot = k; if (jtop > 0) { while (jlen <= j && jlen <= 12 && jbot >= 2) { jbot--; jlen++; } } if (jbot != jtop - jlen + 1) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* Factors between jbot and jtop inclusive */ if (jbot == 0 || alen == 0) { fmpz_one(cs + 0); } else { if (acbits <= FLINT_BITS - 1) { slong ac; ac = 1; for (l = 0; l < alen; l++) ac *= *fmpq_denref(a + l) * (jbot - 1) + *fmpq_numref(a + l); fmpz_set_si(cs + 0, ac); } else { fmpz_mul_ui(cs + 0, fmpq_denref(a + 0), jbot - 1); fmpz_add(cs + 0, cs + 0, fmpq_numref(a + 0)); for (l = 1; l < alen; l++) { fmpz_mul_ui(c, fmpq_denref(a + l), jbot - 1); fmpz_add(c, c, fmpq_numref(a + l)); fmpz_mul(cs + 0, cs + 0, c); } } } for (i = 1; i < jlen; i++) { if (alen == 0) { fmpz_set(cs + i, cs + i - 1); } else { if (acbits <= FLINT_BITS - 1) { slong ac; ac = 1; for (l = 0; l < alen; l++) ac *= *fmpq_denref(a + l) * (jbot + i - 1) + *fmpq_numref(a + l); fmpz_mul_si(cs + i, cs + i - 1, ac); } else { fmpz_mul_ui(cs + i, fmpq_denref(a + 0), jbot + i - 1); fmpz_add(cs + i, cs + i, fmpq_numref(a + 0)); for (l = 1; l < alen; l++) { fmpz_mul_ui(c, fmpq_denref(a + l), jbot + i - 1); fmpz_add(c, c, fmpq_numref(a + l)); fmpz_mul(cs + i, cs + i, c); } fmpz_mul(cs + i, cs + i, cs + i - 1); } } } if (blen != 0) { fmpz_one(den); for (i = jlen - 1; i >= 0; i--) { if (i != jlen - 1) fmpz_mul(cs + i, cs + i, den); if (i != 0 || jbot != 0) { if (bcbits <= FLINT_BITS - 1) { slong bc; bc = 1; for (l = 0; l < blen; l++) bc *= *fmpq_denref(b + l) * (jbot + i - 1) + *fmpq_numref(b + l); fmpz_mul_si(den, den, bc); } else { for (l = 0; l < blen; l++) { fmpz_mul_ui(c, fmpq_denref(b + l), jbot + i - 1); fmpz_add(c, c, fmpq_numref(b + l)); fmpz_mul(den, den, c); } } } } } if (want_adaptive_precision) wp = tail_precision(k - jlen, adaptive_min_k, alen, blen, log2z, log2max, prec); else wp = prec; /* s = 0 for i in range(jlen): s += cs[i] * zpow[j - jlen + 1 + i] * i^(j - jlen + 1 + i) s += cs[jlen - 1] * (s_real, s_imag) (s_real, s_imag) = s / den */ l = j - jlen + 1; for (i = (2 - l) & 3; i < jlen; i += 4) fmpz_neg(cs + i, cs + i); for (i = (3 - l) & 3; i < jlen; i += 4) fmpz_neg(cs + i, cs + i); if (l % 2 == 0) { arb_dot_fmpz(t_real, NULL, 0, zpow + j - jlen + 1, 2, cs, 2, (jlen + 1) / 2, wp); arb_dot_fmpz(t_imag, NULL, 0, zpow + j - jlen + 1 + 1, 2, cs + 1, 2, jlen / 2, wp); } else { arb_dot_fmpz(t_imag, NULL, 0, zpow + j - jlen + 1, 2, cs, 2, (jlen + 1) / 2, wp); arb_dot_fmpz(t_real, NULL, 0, zpow + j - jlen + 1 + 1, 2, cs + 1, 2, jlen / 2, wp); } if ((jlen - 1 + l) % 4 >= 2) { arb_submul_fmpz(t_real, s_real, cs + jlen - 1, wp); arb_submul_fmpz(t_imag, s_imag, cs + jlen - 1, wp); } else { arb_addmul_fmpz(t_real, s_real, cs + jlen - 1, wp); arb_addmul_fmpz(t_imag, s_imag, cs + jlen - 1, wp); } arb_swap(s_real, t_real); arb_swap(s_imag, t_imag); if (blen != 0) { arb_div_fmpz(s_real, s_real, den, wp); arb_div_fmpz(s_imag, s_imag, den, wp); } k -= jlen; j -= (jlen - 1); if (j == 0 && k >= 1) { arb_mul(s_real, s_real, zpow + m, wp); arb_mul(s_imag, s_imag, zpow + m, wp); if (m % 4 == 1) { arb_swap(s_real, s_imag); arb_neg(s_real, s_real); } else if (m % 4 == 2) { arb_neg(s_real, s_real); arb_neg(s_imag, s_imag); } else if (m % 4 == 3) { arb_swap(s_real, s_imag); arb_neg(s_imag, s_imag); } j = m - 1; } else { j--; } } arb_swap(res_real, s_real); arb_swap(res_imag, s_imag); _arb_vec_clear(zpow, m + 1); _fmpz_vec_clear(cs, m + 1); arb_clear(s_real); arb_clear(s_imag); arb_clear(t_real); arb_clear(t_imag); fmpz_clear(c); fmpz_clear(den); } flint-3.1.3/src/arb_hypgeom/test/000077500000000000000000000000001461254215100166755ustar00rootroot00000000000000flint-3.1.3/src/arb_hypgeom/test/main.c000066400000000000000000000064501461254215100177720ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-1f1_integration.c" #include "t-2f1_integration.c" #include "t-airy_zero.c" #include "t-bessel_i_integration.c" #include "t-bessel_j.c" #include "t-bessel_k_integration.c" #include "t-bessel_y.c" #include "t-central_bin_ui.c" #include "t-ci.c" #include "t-coulomb_series.c" #include "t-erf.c" #include "t-erfinv.c" #include "t-gamma_fmpq.c" #include "t-gamma_lower_sum_rs.c" #include "t-gamma_stirling_sum.c" #include "t-gamma_taylor.c" #include "t-gamma_taylor_tab.c" #include "t-gamma_upper_fmpq.c" #include "t-gamma_upper_integration.c" #include "t-gamma_upper_sum_rs.c" #include "t-legendre_p_ui_asymp.c" #include "t-legendre_p_ui.c" #include "t-legendre_p_ui_deriv_bound.c" #include "t-legendre_p_ui_one.c" #include "t-legendre_p_ui_rec.c" #include "t-legendre_p_ui_root.c" #include "t-legendre_p_ui_zero.c" #include "t-lgamma.c" #include "t-rising_ui.c" #include "t-rising_ui_jet.c" #include "t-si.c" #include "t-sum_fmpq_arb.c" #include "t-sum_fmpq_imag_arb.c" #include "t-u_integration.c" #include "t-wrappers.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arb_hypgeom_1f1_integration), TEST_FUNCTION(arb_hypgeom_2f1_integration), TEST_FUNCTION(arb_hypgeom_airy_zero), TEST_FUNCTION(arb_hypgeom_bessel_i_integration), TEST_FUNCTION(arb_hypgeom_bessel_j), TEST_FUNCTION(arb_hypgeom_bessel_k_integration), TEST_FUNCTION(arb_hypgeom_bessel_y), TEST_FUNCTION(arb_hypgeom_central_bin_ui), TEST_FUNCTION(arb_hypgeom_ci), TEST_FUNCTION(arb_hypgeom_coulomb_series), TEST_FUNCTION(arb_hypgeom_erf), TEST_FUNCTION(arb_hypgeom_erfinv), TEST_FUNCTION(arb_hypgeom_gamma_fmpq), TEST_FUNCTION(arb_hypgeom_gamma_lower_sum_rs), TEST_FUNCTION(arb_hypgeom_gamma_stirling_sum), TEST_FUNCTION(arb_hypgeom_gamma_taylor), TEST_FUNCTION(arb_hypgeom_gamma_taylor_tab), TEST_FUNCTION(arb_hypgeom_gamma_upper_fmpq), TEST_FUNCTION(arb_hypgeom_gamma_upper_integration), TEST_FUNCTION(arb_hypgeom_gamma_upper_sum_rs), TEST_FUNCTION(arb_hypgeom_legendre_p_ui_asymp), TEST_FUNCTION(arb_hypgeom_legendre_p_ui), TEST_FUNCTION(arb_hypgeom_legendre_p_ui_deriv_bound), TEST_FUNCTION(arb_hypgeom_legendre_p_ui_one), TEST_FUNCTION(arb_hypgeom_legendre_p_ui_rec), TEST_FUNCTION(arb_hypgeom_legendre_p_ui_root), TEST_FUNCTION(arb_hypgeom_legendre_p_ui_zero), TEST_FUNCTION(arb_hypgeom_lgamma), TEST_FUNCTION(arb_hypgeom_rising_ui), TEST_FUNCTION(arb_hypgeom_rising_ui_jet), TEST_FUNCTION(arb_hypgeom_si), TEST_FUNCTION(arb_hypgeom_sum_fmpq_arb), TEST_FUNCTION(arb_hypgeom_sum_fmpq_imag_arb), TEST_FUNCTION(arb_hypgeom_u_integration), TEST_FUNCTION(arb_hypgeom_wrappers) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arb_hypgeom/test/t-1f1_integration.c000066400000000000000000000100251461254215100222720ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_1f1_integration, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, z, r1, r2; slong prec1, prec2; int regularized; prec1 = 2 + n_randint(state, 80); prec2 = 2 + n_randint(state, 150); arb_init(a); arb_init(b); arb_init(z); arb_init(r1); arb_init(r2); regularized = n_randint(state, 2); arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(b, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_add_ui(a, a, n_randint(state, 100), prec1 + 100); arb_add_ui(b, b, n_randint(state, 200), prec1 + 100); arb_add_ui(z, z, n_randint(state, 100), prec1 + 100); arb_hypgeom_1f1_integration(r1, a, b, z, regularized, prec1); if (arb_is_finite(r1)) { if (n_randint(state, 2)) arb_hypgeom_1f1(r2, a, b, z, regularized, prec2); else arb_hypgeom_1f1_integration(r2, a, b, z, regularized, prec2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } if (iter == 0) { prec1 = 333; arb_set_str(a, "1.2e7", prec1); arb_set_str(b, "1.3e8", prec1); arb_set_str(z, "1.4e8", prec1); arb_hypgeom_1f1_integration(r1, a, b, z, 0, prec1); arb_set_str(r2, "4.490048760185759949474587200300668633822146852907335040923195547203089703047764681072928822e+11143817 +/- 4.55e+11143726", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (1)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } arb_set_str(a, "1.2e14", prec1); arb_set_str(b, "1.3e15", prec1); arb_set_str(z, "1.4e14", prec1); arb_hypgeom_1f1_integration(r1, a, b, z, 0, prec1); arb_set_str(r2, "7.52012593871057092343210829853229360099866571986384089587141298507823992233368715541e+5903762458197 +/- 5.51e+5903762458113", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); arb_clear(z); arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-2f1_integration.c000066400000000000000000000106161461254215100223010ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_2f1_integration, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c, z, r1, r2; slong prec1, prec2; int regularized; prec1 = 2 + n_randint(state, 80); prec2 = 2 + n_randint(state, 150); arb_init(a); arb_init(b); arb_init(c); arb_init(z); arb_init(r1); arb_init(r2); regularized = n_randint(state, 2); arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(b, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(c, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_add_ui(a, a, n_randint(state, 100), prec1 + 100); arb_add_ui(b, b, n_randint(state, 200), prec1 + 100); arb_add_ui(c, c, n_randint(state, 300), prec1 + 100); arb_add_ui(z, z, n_randint(state, 100), prec1 + 100); arb_hypgeom_2f1_integration(r1, a, b, c, z, regularized, prec1); if (arb_is_finite(r1)) { if (n_randint(state, 2)) arb_hypgeom_2f1(r2, a, b, c, z, regularized, prec2); else arb_hypgeom_2f1_integration(r2, a, b, c, z, regularized, prec2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } if (iter == 0) { prec1 = 333; arb_set_str(b, "2651.1", prec1); arb_set_str(a, "50131.3", prec1); arb_set_str(c, "72923.5", prec1); arb_set_str(z, "-123.5", prec1); arb_hypgeom_2f1_integration(r1, a, b, c, z, 0, prec1); arb_set_str(r2, "2.334513854528911419992516597096504294432862073292366983166036504547076680083826439493425898608e-5118 +/- 2.73e-5212", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (1)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } arb_set_str(b, "1.1e10", prec1); arb_set_str(a, "1.2e11", prec1); arb_set_str(c, "1.3e12", prec1); arb_set_str(z, "0.7", prec1); arb_hypgeom_2f1_integration(r1, a, b, c, z, 0, prec1); arb_set_str(r2, "5.86281189034275194553834976777402286036616612793483753071706787203236651175920694151330e+320059600 +/- 1.96e+320059513", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(z); arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-airy_zero.c000066400000000000000000000136731461254215100213170ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_airy_zero, state) { slong iter; /* interlacing test */ { arb_t a, ap, b, bp, ap1; fmpz_t n; arb_init(a); arb_init(ap); arb_init(b); arb_init(bp); arb_init(ap1); fmpz_init(n); for (fmpz_one(n); fmpz_cmp_ui(n, 200) <= 0; fmpz_add_ui(n, n, 1)) { arb_hypgeom_airy_zero(a, ap, b, bp, n, 53); fmpz_add_ui(n, n, 1); arb_hypgeom_airy_zero(NULL, ap1, NULL, NULL, n, 53); fmpz_sub_ui(n, n, 1); if (!arb_gt(ap, b) || !arb_gt(b, bp) || !arb_gt(bp, a) || !arb_gt(a, ap1)) { flint_printf("FAIL: interlacing\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 100, 0); flint_printf("\n\n"); flint_printf("ap = "); arb_printn(ap, 100, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 100, 0); flint_printf("\n\n"); flint_printf("bp = "); arb_printn(bp, 100, 0); flint_printf("\n\n"); flint_printf("ap1 = "); arb_printn(ap1, 100, 0); flint_printf("\n\n"); flint_abort(); } } for (fmpz_set_ui(n, 1000000); fmpz_cmp_ui(n, 1000000 + 200) <= 0; fmpz_add_ui(n, n, 1)) { arb_hypgeom_airy_zero(a, ap, b, bp, n, 53); fmpz_add_ui(n, n, 1); arb_hypgeom_airy_zero(NULL, ap1, NULL, NULL, n, 53); fmpz_sub_ui(n, n, 1); if (!arb_gt(ap, b) || !arb_gt(b, bp) || !arb_gt(bp, a) || !arb_gt(a, ap1)) { flint_printf("FAIL: interlacing\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 100, 0); flint_printf("\n\n"); flint_printf("ap = "); arb_printn(ap, 100, 0); flint_printf("\n\n"); flint_printf("b = "); arb_printn(b, 100, 0); flint_printf("\n\n"); flint_printf("bp = "); arb_printn(bp, 100, 0); flint_printf("\n\n"); flint_printf("ap1 = "); arb_printn(ap1, 100, 0); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(ap); arb_clear(b); arb_clear(bp); arb_clear(ap1); fmpz_clear(n); } /* self-consistency and accuracy test */ for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x1, x2, v1, v2; fmpz_t n; slong prec1, prec2; int which; arb_init(x1); arb_init(x2); arb_init(v1); arb_init(v2); fmpz_init(n); fmpz_randtest(n, state, 200); fmpz_abs(n, n); fmpz_add_ui(n, n, 1); prec1 = 2 + n_randtest(state) % 1000; prec2 = 2 + n_randtest(state) % 1000; which = n_randint(state, 4); if (which == 0) { arb_hypgeom_airy_zero(x1, NULL, NULL, NULL, n, prec1); arb_hypgeom_airy_zero(x2, NULL, NULL, NULL, n, prec2); arb_hypgeom_airy(v1, NULL, NULL, NULL, x1, prec1 + 30); arb_hypgeom_airy(v2, NULL, NULL, NULL, x2, prec2 + 30); } else if (which == 1) { arb_hypgeom_airy_zero(NULL, x1, NULL, NULL, n, prec1); arb_hypgeom_airy_zero(NULL, x2, NULL, NULL, n, prec2); arb_hypgeom_airy(NULL, v1, NULL, NULL, x1, prec1 + 30); arb_hypgeom_airy(NULL, v2, NULL, NULL, x2, prec2 + 30); } else if (which == 2) { arb_hypgeom_airy_zero(NULL, NULL, x1, NULL, n, prec1); arb_hypgeom_airy_zero(NULL, NULL, x2, NULL, n, prec2); arb_hypgeom_airy(NULL, NULL, v1, NULL, x1, prec1 + 30); arb_hypgeom_airy(NULL, NULL, v2, NULL, x2, prec2 + 30); } else { arb_hypgeom_airy_zero(NULL, NULL, NULL, x1, n, prec1); arb_hypgeom_airy_zero(NULL, NULL, NULL, x2, n, prec2); arb_hypgeom_airy(NULL, NULL, NULL, v1, x1, prec1 + 30); arb_hypgeom_airy(NULL, NULL, NULL, v2, x2, prec2 + 30); } if (!arb_overlaps(x1, x2) || !arb_contains_zero(v1) || !arb_contains_zero(v2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("which = %d, n = ", which); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_printf("v1 = "); arb_printn(v1, 100, 0); flint_printf("\n\n"); flint_printf("v2 = "); arb_printn(v2, 100, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(x1) < prec1 - 3 || arb_rel_accuracy_bits(x2) < prec2 - 3) { flint_printf("FAIL: accuracy\n\n"); flint_printf("which = %d, n = ", which); fmpz_print(n); flint_printf(" prec1 = %wd prec2 = %wd\n\n", prec1, prec2); flint_printf("acc(x1) = %wd, acc(x2) = %wd\n\n", arb_rel_accuracy_bits(x1), arb_rel_accuracy_bits(x2)); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x1); arb_clear(x2); arb_clear(v1); arb_clear(v2); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-bessel_i_integration.c000066400000000000000000000045521461254215100235000ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_bessel_i_integration, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, z, r1, r2; slong prec1, prec2; int scaled; prec1 = 2 + n_randint(state, 80); prec2 = 2 + n_randint(state, 150); arb_init(a); arb_init(z); arb_init(r1); arb_init(r2); scaled = n_randint(state, 2); arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_add_ui(a, a, n_randint(state, 100), prec1 + 100); arb_add_ui(z, z, n_randint(state, 100), prec1 + 100); arb_hypgeom_bessel_i_integration(r1, a, z, scaled, prec1); if (arb_is_finite(r1)) { if (n_randint(state, 2)) arb_hypgeom_bessel_i_integration(r2, a, z, scaled, prec2); else { if (scaled) arb_hypgeom_bessel_i_scaled(r2, a, z, prec2); else arb_hypgeom_bessel_i(r2, a, z, prec2); } if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(z); arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-bessel_j.c000066400000000000000000000043421461254215100210730ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_bessel_j, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, nu; slong prec; arb_init(x); arb_init(y); arb_init(nu); prec = 2 + n_randint(state, 200); arb_randtest(nu, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_pos_inf(x); arb_hypgeom_bessel_j(y, nu, x, prec); if (arb_is_finite(nu) && !arb_is_zero(y)) { flint_printf("FAIL: positive infinity\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("nu = "); arb_printd(nu, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } arb_neg_inf(x); arb_hypgeom_bessel_j(y, nu, x, prec); if (arb_is_finite(nu) && !arb_is_zero(y)) { flint_printf("FAIL: negative infinity\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("nu = "); arb_printd(nu, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } arb_indeterminate(x); arb_hypgeom_bessel_j(y, nu, x, prec); if (!arf_is_nan(arb_midref(y))) { flint_printf("FAIL: indeterminate\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("nu = "); arb_printd(nu, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(nu); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-bessel_k_integration.c000066400000000000000000000045521461254215100235020ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_bessel_k_integration, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, z, r1, r2; slong prec1, prec2; int scaled; prec1 = 2 + n_randint(state, 80); prec2 = 2 + n_randint(state, 150); arb_init(a); arb_init(z); arb_init(r1); arb_init(r2); scaled = n_randint(state, 2); arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_add_ui(a, a, n_randint(state, 100), prec1 + 100); arb_add_ui(z, z, n_randint(state, 100), prec1 + 100); arb_hypgeom_bessel_k_integration(r1, a, z, scaled, prec1); if (arb_is_finite(r1)) { if (n_randint(state, 2)) arb_hypgeom_bessel_k_integration(r2, a, z, scaled, prec2); else { if (scaled) arb_hypgeom_bessel_k_scaled(r2, a, z, prec2); else arb_hypgeom_bessel_k(r2, a, z, prec2); } if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(z); arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-bessel_y.c000066400000000000000000000043421461254215100211120ustar00rootroot00000000000000/* Copyright (C) 2020 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_bessel_y, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, nu; slong prec; arb_init(x); arb_init(y); arb_init(nu); prec = 2 + n_randint(state, 200); arb_randtest(nu, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_pos_inf(x); arb_hypgeom_bessel_y(y, nu, x, prec); if (arb_is_finite(nu) && !arb_is_zero(y)) { flint_printf("FAIL: positive infinity\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("nu = "); arb_printd(nu, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } arb_neg_inf(x); arb_hypgeom_bessel_y(y, nu, x, prec); if (arb_is_finite(nu) && !arb_is_zero(y)) { flint_printf("FAIL: negative infinity\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("nu = "); arb_printd(nu, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } arb_indeterminate(x); arb_hypgeom_bessel_y(y, nu, x, prec); if (!arf_is_nan(arb_midref(y))) { flint_printf("FAIL: indeterminate\n\n"); flint_printf("x = "); arb_printd(x, 50); flint_printf("\n\n"); flint_printf("nu = "); arb_printd(nu, 50); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 50); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(nu); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-central_bin_ui.c000066400000000000000000000040021461254215100222530ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_central_bin_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_t b1, b2, t; ulong n; slong prec1, prec2, acc1; n = n_randtest(state); prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; arb_init(b1); arb_init(b2); arb_init(t); arb_hypgeom_central_bin_ui(b1, n, prec1); arb_set_ui(t, n); arb_add_ui(t, t, n, prec2); arb_add_ui(t, t, 1, prec2); arb_gamma(t, t, prec2); arb_set_ui(b2, n); arb_add_ui(b2, b2, 1, prec2); arb_rgamma(b2, b2, prec2); arb_mul(b2, b2, b2, prec2); arb_mul(b2, b2, t, prec2); if (!arb_overlaps(b1, b2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("b1 = "); arb_printn(b1, 50, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, 50, 0); flint_printf("\n\n"); flint_abort(); } acc1 = arb_rel_accuracy_bits(b1); if (acc1 < prec1 - 2) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec1 = %wd, acc1 = %wd\n", prec1, acc1); flint_printf("b1 = "); arb_printn(b1, prec1 / 3.33, 0); flint_printf("\n\n"); flint_printf("b2 = "); arb_printn(b2, prec2 / 3.33, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(b1); arb_clear(b2); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-ci.c000066400000000000000000000047061461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_ci, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, s, t; slong prec1, prec2; arb_init(x); arb_init(s); arb_init(t); if (n_randint(state, 10) == 0) { prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); } else { prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); } arb_randtest(x, state, 2 + n_randint(state, prec1), 2 + n_randint(state, 100)); arb_randtest(s, state, 2 + n_randint(state, prec1), 2 + n_randint(state, 100)); arb_randtest(t, state, 2 + n_randint(state, prec1), 2 + n_randint(state, 100)); switch (n_randint(state, 3)) { case 0: arb_hypgeom_ci(s, x, prec1); break; case 1: _arb_hypgeom_ci_2f3(s, x, n_randint(state, prec1), prec1, prec1); break; default: _arb_hypgeom_ci_asymp(s, x, n_randint(state, prec1 / 2), prec1); break; } switch (n_randint(state, 3)) { case 0: arb_hypgeom_ci(t, x, prec2); break; case 1: _arb_hypgeom_ci_2f3(t, x, n_randint(state, prec2), prec2, prec2); break; default: _arb_hypgeom_ci_asymp(t, x, n_randint(state, prec2 / 2), prec2); break; } if (!arb_overlaps(s, t)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 100, 0); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(s); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-coulomb_series.c000066400000000000000000000111341461254215100223140ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "arb_poly.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_coulomb_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t F, G, F2, G2, z, w, t, u; arb_t c, l, eta, z0; slong n1, n2, prec1, prec2; unsigned int mask; arb_poly_init(F); arb_poly_init(G); arb_poly_init(F2); arb_poly_init(G2); arb_poly_init(z); arb_poly_init(w); arb_poly_init(t); arb_poly_init(u); arb_init(c); arb_init(l); arb_init(eta); arb_init(z0); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); n1 = n_randint(state, 8); n2 = n_randint(state, 8); arb_poly_randtest(F, state, 10, prec1, 10); arb_poly_randtest(G, state, 10, prec1, 10); arb_randtest(l, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); arb_randtest(eta, state, 1 + n_randint(state, 200), 1 + n_randint(state, 10)); arb_poly_randtest(z, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); arb_hypgeom_coulomb_series(F, G, l, eta, z, n1, prec1); /* F' G - F G' = 1 */ arb_poly_derivative(t, F, prec1); arb_poly_set(u, G); arb_poly_mullow(w, t, u, FLINT_MAX(n1 - 1, 0), prec1); arb_poly_derivative(u, u, prec1); arb_poly_mullow(t, F, u, FLINT_MAX(n1 - 1, 0), prec1); arb_poly_sub(w, w, t, prec1); arb_poly_derivative(t, z, prec1); arb_poly_truncate(t, FLINT_MAX(n1 - 1, 0)); /* hack: work around mullow(nan, 0) = 0 */ arb_poly_get_coeff_arb(z0, z, 0); if (!arb_contains_zero(z0) && !arb_poly_overlaps(w, t)) { flint_printf("FAIL: wronskian, n1 = %wd\n\n", n1); flint_printf("l = "); arb_printd(l, 30); flint_printf("\n\n"); flint_printf("eta = "); arb_printd(eta, 30); flint_printf("\n\n"); flint_printf("z = "); arb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("F = "); arb_poly_printd(F, 30); flint_printf("\n\n"); flint_printf("G = "); arb_poly_printd(G, 30); flint_printf("\n\n"); flint_printf("w = "); arb_poly_printd(w, 30); flint_printf("\n\n"); flint_printf("t = "); arb_poly_printd(t, 30); flint_printf("\n\n"); flint_abort(); } mask = n_randlimb(state); arb_poly_set(G2, z); /* for aliasing */ if (n_randint(state, 2)) { arb_poly_randtest(u, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); arb_poly_add(G2, G2, u, prec2); arb_poly_sub(G2, G2, u, prec2); } arb_hypgeom_coulomb_series((mask & 1) ? F2 : NULL, (mask & 2) ? G2 : NULL, l, eta, G2, n2, prec2); arb_poly_truncate(F, FLINT_MIN(n1, n2)); arb_poly_truncate(G, FLINT_MIN(n1, n2)); arb_poly_truncate(F2, FLINT_MIN(n1, n2)); arb_poly_truncate(G2, FLINT_MIN(n1, n2)); if (((mask & 1) && (!arb_poly_overlaps(F, F2))) || ((mask & 2) && (!arb_poly_overlaps(G, G2)))) { flint_printf("FAIL: consistency (mask)\n\n"); flint_printf("mask = %u\n\n", mask); flint_printf("len1 = %wd, len2 = %wd\n\n", n1, n2); flint_printf("l = "); arb_printd(l, 30); flint_printf("\n\n"); flint_printf("eta = "); arb_printd(eta, 30); flint_printf("\n\n"); flint_printf("z = "); arb_poly_printd(z, 30); flint_printf("\n\n"); flint_printf("F = "); arb_poly_printd(F, 30); flint_printf("\n\n"); flint_printf("F2 = "); arb_poly_printd(F2, 30); flint_printf("\n\n"); flint_printf("G = "); arb_poly_printd(G, 30); flint_printf("\n\n"); flint_printf("G2 = "); arb_poly_printd(G2, 30); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(F); arb_poly_clear(G); arb_poly_clear(F2); arb_poly_clear(G2); arb_poly_clear(z); arb_poly_clear(w); arb_poly_clear(t); arb_poly_clear(u); arb_clear(c); arb_clear(l); arb_clear(eta); arb_clear(z0); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-erf.c000066400000000000000000000146031461254215100200620ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_erf, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); switch (n_randint(state, 2)) { case 0: if (!arb_hypgeom_erf_bb(b, a, 0, prec1)) arb_hypgeom_erf(b, a, prec1); break; default: arb_hypgeom_erf(b, a, prec1); break; } switch (n_randint(state, 2)) { case 0: if (!arb_hypgeom_erf_bb(c, a, 0, prec2)) arb_hypgeom_erf(c, a, prec2); break; default: arb_hypgeom_erf(c, a, prec2); break; } if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 30); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); switch (n_randint(state, 2)) { case 0: if (!arb_hypgeom_erf_bb(b, a, 1, prec1)) arb_hypgeom_erfc(b, a, prec1); break; default: arb_hypgeom_erfc(b, a, prec1); break; } switch (n_randint(state, 2)) { case 0: if (!arb_hypgeom_erf_bb(c, a, 1, prec2)) arb_hypgeom_erfc(c, a, prec2); break; default: arb_hypgeom_erfc(c, a, prec2); break; } if (!arb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 30); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } #if 0 for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1; prec1 = 2 + n_randint(state, 5000); arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_hypgeom_erfc(b, a, prec1 + 100); arb_set_round(b, b, prec1); arb_div_ui(b, b, 3, prec1); arb_mul_ui(b, b, 3, prec1); if (n_randint(state, 2)) { if (!arb_hypgeom_erf_bb(c, a, 1, prec1)) arb_hypgeom_erfc(c, a, prec1); } else arb_hypgeom_erfc(c, a, prec1); if (arb_is_finite(b) && (arb_rel_accuracy_bits(c) < arb_rel_accuracy_bits(b) - 4.0)) { flint_printf("ACCURACY (erfc)\n\n"); flint_printf("prec = %wd\n\n", prec1); flint_printf("a = "); arb_printd(a, 200); flint_printf("\n"); flint_printf("b = "); arb_printd(b, 200); flint_printf("\n"); flint_printf("c = "); arb_printd(c, 200); flint_printf("\n\n"); } arb_clear(a); arb_clear(b); arb_clear(c); } #endif #if 0 for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, c; slong prec1; prec1 = 2 + n_randint(state, 5000); arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_randtest_special(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arb_hypgeom_erf(b, a, prec1 + 100); arb_set_round(b, b, prec1); arb_div_ui(b, b, 3, prec1); arb_mul_ui(b, b, 3, prec1); if (n_randint(state, 2)) { if (!arb_hypgeom_erf_bb(c, a, 0, prec1)) arb_hypgeom_erf(c, a, prec1); } else arb_hypgeom_erf(c, a, prec1); if (arb_is_finite(b) && (arb_rel_accuracy_bits(c) < arb_rel_accuracy_bits(b) - 4.0)) { flint_printf("ACCURACY (erf)\n\n"); flint_printf("prec = %wd\n\n", prec1); flint_printf("a = "); arb_printd(a, 200); flint_printf("\n"); flint_printf("b = "); arb_printd(b, 200); flint_printf("\n"); flint_printf("c = "); arb_printd(c, 200); flint_printf("\n\n"); } arb_clear(a); arb_clear(b); arb_clear(c); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-erfinv.c000066400000000000000000000120161461254215100205730ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_erfinv, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z, w; slong prec, prec2; arb_init(x); arb_init(y); arb_init(z); arb_init(w); prec = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); arb_init(x); arb_init(y); arb_randtest(x, state, prec, 10 + n_randint(state, 300)); arb_randtest(y, state, prec, 100); arb_hypgeom_erfcinv(y, x, prec); arb_hypgeom_erfc(z, y, prec + 10); if (!arb_overlaps(x, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_abort(); } if (arb_is_exact(x) && arf_sgn(arb_midref(x)) > 0 && arf_cmp_2exp_si(arb_midref(x), 1) < 0 && arb_rel_accuracy_bits(y) < prec - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("iter = %wd, prec = %wd\n", iter, prec); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_set(z, x); mag_zero(arb_radref(z)); if (n_randint(state, 2)) { arf_set_mag(arb_midref(w), arb_radref(x)); if (n_randint(state, 2)) arb_neg(w, w); arb_add(z, z, w, prec); } arb_hypgeom_erfcinv(z, z, prec2); if (!arb_overlaps(y, z)) { flint_printf("FAIL: overlap 2\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); arb_clear(w); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, y, z, w; slong prec, prec2; arb_init(x); arb_init(y); arb_init(z); arb_init(w); prec = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); arb_init(x); arb_init(y); arb_randtest(x, state, prec, 100); arb_randtest(y, state, prec, 100); arb_hypgeom_erfinv(y, x, prec); arb_hypgeom_erf(z, y, prec + 10); if (!arb_overlaps(x, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_abort(); } if (arb_is_exact(x) && arf_cmpabs_2exp_si(arb_midref(x), 0) < 0 && arb_rel_accuracy_bits(y) < prec - 2) { flint_printf("FAIL: accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_set(z, x); mag_zero(arb_radref(z)); if (n_randint(state, 2)) { arf_set_mag(arb_midref(w), arb_radref(x)); if (n_randint(state, 2)) arb_neg(w, w); arb_add(z, z, w, prec); } arb_hypgeom_erfinv(z, z, prec2); if (!arb_overlaps(y, z)) { flint_printf("FAIL: overlap 2\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(y); arb_clear(z); arb_clear(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_fmpq.c000066400000000000000000000075641461254215100214230ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "ulong_extras.h" #include "arb_hypgeom.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif TEST_FUNCTION_START(arb_hypgeom_gamma_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t r, s; fmpq_t q; slong accuracy, prec, pp, qq; prec = 2 + n_randint(state, 1 << n_randint(state, 12)); prec += 20; arb_init(r); arb_init(s); fmpq_init(q); pp = -100 + n_randint(state, 10000); qq = 1 + n_randint(state, 20); fmpq_set_si(q, pp, qq); arb_hypgeom_gamma_fmpq(r, q, prec); arb_set_fmpq(s, q, prec); arb_hypgeom_gamma(s, s, prec); if (!arb_overlaps(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); arb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_abort(); } if (!(fmpz_is_one(fmpq_denref(q)) && fmpz_sgn(fmpq_numref(q)) <= 0) && FLINT_ABS(pp / qq) < 10) { accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 6) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_abort(); } } arb_clear(r); arb_clear(s); fmpq_clear(q); } for (iter = 0; iter < 50 * 0.1 * flint_test_multiplier(); iter++) { arb_t r, s; fmpq_t q; slong accuracy, prec; prec = 2 + n_randint(state, 25000); arb_init(r); arb_init(s); fmpq_init(q); fmpz_randtest(fmpq_numref(q), state, 3 + n_randlimb(state) % 30); fmpz_randtest_not_zero(fmpq_denref(q), state, 3 + n_randlimb(state) % 30); fmpq_canonicalise(q); arb_hypgeom_gamma_fmpq(r, q, prec); arb_set_fmpq(s, q, prec); arb_hypgeom_gamma(s, s, prec); if (!arb_overlaps(r, s)) { flint_printf("FAIL: containment\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, prec / 3.33); flint_printf("\n\n"); flint_printf("s = "); arb_printd(s, prec / 3.33); flint_printf("\n\n"); flint_abort(); } if (!(fmpz_is_one(fmpq_denref(q)) && fmpz_sgn(fmpq_numref(q)) <= 0) && fabs(fmpq_get_d(q)) < 10.0) { accuracy = arb_rel_accuracy_bits(r); if (accuracy < prec - 6) { flint_printf("FAIL: poor accuracy\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("q = "); fmpq_print(q); flint_printf("\n\n"); flint_printf("r = "); arb_printn(r, prec / 3.33, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, prec / 3.33, 0); flint_printf("\n\n"); flint_abort(); } } arb_clear(r); arb_clear(s); fmpq_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_lower_sum_rs.c000066400000000000000000000041271461254215100231700ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_gamma_lower_sum_rs, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_t a; ulong p, q; arb_t z, r1, r2, s, t, u; slong k, N, prec; p = n_randint(state, 1000); q = 1 + n_randint(state, 1000); N = n_randint(state, 100); prec = 2 + n_randint(state, 500); fmpq_init(a); fmpq_set_si(a, p, q); arb_init(z); arb_init(r1); arb_init(r2); arb_init(s); arb_init(t); arb_init(u); arb_randtest(z, state, prec, 10); _arb_hypgeom_gamma_lower_sum_rs_1(r1, p, q, z, N, prec); arb_zero(s); arb_one(t); arb_set_fmpq(u, a, prec); for (k = 0; k < N; k++) { arb_add(s, s, t, prec); arb_mul(t, t, z, prec); arb_div(t, t, u, prec); arb_add_ui(u, u, 1, prec); } arb_set(r2, s); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("a = "); fmpq_print(a); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 100, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 100, 0); flint_printf("\n\n"); flint_abort(); } fmpq_clear(a); arb_clear(z); arb_clear(r1); arb_clear(r2); arb_clear(s); arb_clear(t); arb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_stirling_sum.c000066400000000000000000000030371461254215100231660ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_gamma_stirling_sum, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t z, s1, s2; slong prec, N, K; prec = 2 + n_randint(state, 800); N = n_randint(state, 200); K = n_randint(state, 20); arb_init(z); arb_init(s1); arb_init(s2); arb_randtest(z, state, prec, 10 + n_randint(state, 200)); arb_hypgeom_gamma_stirling_sum_horner(s1, z, N, prec); arb_hypgeom_gamma_stirling_sum_improved(s2, z, N, K, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("N = %wd, K = %wd, prec = %wd\n\n", N, K, prec); flint_printf("z = "); arb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(z); arb_clear(s1); arb_clear(s2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_taylor.c000066400000000000000000000127641461254215100217700ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_gamma_taylor, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, s1, s2, a, b; slong prec, ebits, prec2; int success, success2, alias, reciprocal; if (n_randint(state, 10) == 0) prec = 2 + n_randint(state, 4000); else prec = 2 + n_randint(state, 300); if (n_randint(state, 10) == 0) ebits = 100; else ebits = 10; prec2 = prec + 1 + n_randint(state, 30); arb_init(x); arb_init(s1); arb_init(s2); arb_init(a); arb_init(b); arb_randtest(x, state, prec, ebits); arb_randtest(s1, state, prec, 10); arb_randtest(s2, state, prec, 10); alias = n_randint(state, 2); reciprocal = n_randint(state, 2); if (alias) { success = arb_hypgeom_gamma_taylor(s1, x, reciprocal, prec); } else { arb_set(s1, x); success = arb_hypgeom_gamma_taylor(s1, s1, reciprocal, prec); } if (success) { /* printf("%ld\n", iter); */ /* Compare with Stirling series algorithm. */ arb_hypgeom_gamma_stirling(s2, x, reciprocal, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); arb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_abort(); } /* Compare with different level of precision. */ success2 = arb_hypgeom_gamma_taylor(s2, x, reciprocal, prec2); if (success2 && !arb_overlaps(s1, s2)) { flint_printf("FAIL (2)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); arb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_abort(); } arf_set_mag(arb_midref(a), arb_radref(x)); arf_set_mag(arb_midref(b), arb_radref(x)); arb_sub_arf(a, a, arb_midref(x), prec + 30); arb_neg(a, a); arb_add_arf(b, b, arb_midref(x), prec + 30); success2 = arb_hypgeom_gamma_taylor(s2, a, reciprocal, prec2); if (success2 && !arb_overlaps(s1, s2)) { flint_printf("FAIL (3)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); arb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_abort(); } success2 = arb_hypgeom_gamma_taylor(s2, b, reciprocal, prec2); if (success2 && !arb_overlaps(s1, s2)) { flint_printf("FAIL (4)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); arb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_abort(); } arb_add(a, a, b, prec + 30); arb_mul_2exp_si(a, a, -1); success2 = arb_hypgeom_gamma_taylor(s2, b, reciprocal, prec2); if (success2 && !arb_overlaps(s1, s2)) { flint_printf("FAIL (5)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("x = "); arb_printn(x, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); arb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(s1); arb_clear(s2); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_taylor_tab.c000066400000000000000000000046531461254215100226140ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_gamma_taylor_tab, state) { { slong n, prec, maxprec; arb_t c; arf_t d; arb_ptr v, f; v = _arb_vec_init(ARB_HYPGEOM_GAMMA_TAB_NUM); f = _arb_vec_init(2); arb_one(f); arb_one(f + 1); arf_init(d); _arb_poly_rgamma_series(v, f, 2, ARB_HYPGEOM_GAMMA_TAB_NUM, ARB_HYPGEOM_GAMMA_TAB_PREC + 2 * ARB_HYPGEOM_GAMMA_TAB_NUM); for (n = 1; n < ARB_HYPGEOM_GAMMA_TAB_NUM; n++) { maxprec = arb_hypgeom_gamma_coeffs[n].nlimbs; maxprec *= 64; for (prec = 2; prec <= ARB_HYPGEOM_GAMMA_TAB_PREC; prec += (prec < maxprec - 64 ? n_randint(state, 64) : 1)) { if (_arb_hypgeom_gamma_coeff_shallow(arb_midref(c), arb_radref(c), n, prec)) { if (!arb_contains(c, v + n)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd, n = %wd\n\n", prec, n); flint_printf("c = "); arb_printn(c, 1000, 0); flint_printf("\n\n"); flint_printf("v = "); arb_printn(v + n, 1000, 0); flint_printf("\n\n"); flint_abort(); } } } _arb_hypgeom_gamma_coeff_shallow(arb_midref(c), arb_radref(c), n, maxprec); arf_set_round(d, arb_midref(v + n), maxprec, ARF_RND_DOWN); if (!arf_equal(arb_midref(c), d)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd, n = %wd\n\n", prec, n); flint_printf("c = "); arb_printn(c, 1000, 0); flint_printf("\n\n"); flint_printf("d = "); arf_printd(d, 1000); flint_printf("\n\n"); flint_abort(); } } _arb_vec_clear(v, ARB_HYPGEOM_GAMMA_TAB_NUM); _arb_vec_clear(f, 2); arf_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_upper_fmpq.c000066400000000000000000000135621461254215100226310ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_gamma_upper_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_t a; arb_t z, r1, r2; mag_t tol1, tol2, err1, err2; slong N1, N2, prec1, prec2; mag_init(tol1); mag_init(tol2); mag_init(err1); mag_init(err2); fmpq_init(a); arb_init(z); arb_init(r1); arb_init(r2); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); do { fmpq_randtest(a, state, 5); } while (fmpz_is_one(fmpq_denref(a)) && fmpz_sgn(fmpq_numref(a)) <= 0); arb_set_ui(z, 1 + n_randint(state, 100)); arb_div_ui(z, z, 1 + n_randint(state, 100), 200); mag_set_ui_2exp_si(tol1, 1, -(slong) n_randint(state, 100)); mag_set_ui_2exp_si(tol2, 1, -(slong) n_randint(state, 100)); N1 = _arb_hypgeom_gamma_upper_fmpq_inf_choose_N(err1, a, z, tol1); N2 = _arb_hypgeom_gamma_upper_fmpq_inf_choose_N(err2, a, z, tol2); _arb_hypgeom_gamma_upper_fmpq_inf_bsplit(r1, a, z, N1, prec1); arb_add_error_mag(r1, err1); _arb_hypgeom_gamma_upper_fmpq_inf_bsplit(r2, a, z, N2, prec2); arb_add_error_mag(r2, err2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); fmpq_print(a); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 100, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 100, 0); flint_printf("\n\n"); flint_abort(); } fmpq_clear(a); arb_clear(z); arb_clear(r1); arb_clear(r2); mag_clear(tol1); mag_clear(tol2); mag_clear(err1); mag_clear(err2); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_t a; arb_t z, r1, r2; mag_t tol1, tol2, err1, err2; slong N1, N2, prec1, prec2; mag_init(tol1); mag_init(tol2); mag_init(err1); mag_init(err2); fmpq_init(a); arb_init(z); arb_init(r1); arb_init(r2); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); do { fmpq_randtest(a, state, 5); } while (fmpz_is_one(fmpq_denref(a)) && fmpz_sgn(fmpq_numref(a)) <= 0); arb_set_ui(z, 1 + n_randint(state, 100)); arb_div_ui(z, z, 1 + n_randint(state, 100), 200); mag_set_ui_2exp_si(tol1, 1, -(slong) n_randint(state, 100)); mag_set_ui_2exp_si(tol2, 1, -(slong) n_randint(state, 100)); N1 = _arb_hypgeom_gamma_lower_fmpq_0_choose_N(err1, a, z, tol1); N2 = _arb_hypgeom_gamma_lower_fmpq_0_choose_N(err2, a, z, tol2); _arb_hypgeom_gamma_lower_fmpq_0_bsplit(r1, a, z, N1, prec1); arb_add_error_mag(r1, err1); _arb_hypgeom_gamma_lower_fmpq_0_bsplit(r2, a, z, N2, prec2); arb_add_error_mag(r2, err2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); fmpq_print(a); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 100, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 100, 0); flint_printf("\n\n"); flint_abort(); } fmpq_clear(a); arb_clear(z); arb_clear(r1); arb_clear(r2); mag_clear(tol1); mag_clear(tol2); mag_clear(err1); mag_clear(err2); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong na; arb_t z, r1, r2; mag_t tol1, tol2, err1, err2; slong N1, N2, prec1, prec2; mag_init(tol1); mag_init(tol2); mag_init(err1); mag_init(err2); arb_init(z); arb_init(r1); arb_init(r2); prec1 = 2 + n_randint(state, 100); prec2 = 2 + n_randint(state, 100); na = n_randint(state, 50); arb_set_ui(z, 1 + n_randint(state, 100)); arb_div_ui(z, z, 1 + n_randint(state, 100), 200); mag_set_ui_2exp_si(tol1, 1, -(slong) n_randint(state, 100)); mag_set_ui_2exp_si(tol2, 1, -(slong) n_randint(state, 100)); N1 = _arb_hypgeom_gamma_upper_singular_si_choose_N(err1, na, z, tol1); N2 = _arb_hypgeom_gamma_upper_singular_si_choose_N(err2, na, z, tol2); _arb_hypgeom_gamma_upper_singular_si_bsplit(r1, na, z, N1, prec1); arb_add_error_mag(r1, err1); _arb_hypgeom_gamma_upper_singular_si_bsplit(r2, na, z, N2, prec2); arb_add_error_mag(r2, err2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("na = %wd", na); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 100, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(z); arb_clear(r1); arb_clear(r2); mag_clear(tol1); mag_clear(tol2); mag_clear(err1); mag_clear(err2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_upper_integration.c000066400000000000000000000072741461254215100242140ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_gamma_upper_integration, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, z, r1, r2; slong prec1, prec2; int regularized; prec1 = 2 + n_randint(state, 80); prec2 = 2 + n_randint(state, 150); arb_init(a); arb_init(z); arb_init(r1); arb_init(r2); regularized = n_randint(state, 3); arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_add_ui(a, a, n_randint(state, 100), prec1 + 100); arb_add_ui(z, z, n_randint(state, 100), prec1 + 100); arb_hypgeom_gamma_upper_integration(r1, a, z, regularized, prec1); if (arb_is_finite(r1)) { if (n_randint(state, 2)) arb_hypgeom_gamma_upper_integration(r2, a, z, regularized, prec2); else arb_hypgeom_gamma_upper(r2, a, z, regularized, prec2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } if (iter == 0) { prec1 = 333; arb_set_str(a, "5.25", prec1); arb_set_str(z, "1.125", prec1); arb_hypgeom_gamma_upper_integration(r1, a, z, 0, prec1); arb_set_str(r2, "35.072486673952527119466762267780775062420879980812938235868074922070540736636294202721367124421387 +/- 5.01e-97", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (1)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } arb_set_str(a, "-23515.25", prec1); arb_set_str(z, "5118.125", prec1); arb_hypgeom_gamma_upper_integration(r1, a, z, 0, prec1); arb_set_str(r2, "1.2585189324946269645868452847608400602717904014578585865177198314407671242201776909963228597279e-89448 +/- 8.86e-89543", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (1)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(z); arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-gamma_upper_sum_rs.c000066400000000000000000000041271461254215100231730ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_gamma_upper_sum_rs, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_t a; ulong p, q; arb_t z, r1, r2, s, t, u; slong k, N, prec; p = n_randint(state, 1000); q = 1 + n_randint(state, 1000); N = n_randint(state, 100); prec = 2 + n_randint(state, 500); fmpq_init(a); fmpq_set_si(a, p, q); arb_init(z); arb_init(r1); arb_init(r2); arb_init(s); arb_init(t); arb_init(u); arb_randtest(z, state, prec, 10); _arb_hypgeom_gamma_upper_sum_rs_1(r1, p, q, z, N, prec); arb_zero(s); arb_one(t); arb_set_fmpq(u, a, prec); for (k = 0; k < N; k++) { arb_add(s, s, t, prec); arb_div(t, t, z, prec); arb_mul(t, t, u, prec); arb_add_ui(u, u, 1, prec); } arb_set(r2, s); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("a = "); fmpq_print(a); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 100, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 100, 0); flint_printf("\n\n"); flint_abort(); } fmpq_clear(a); arb_clear(z); arb_clear(r1); arb_clear(r2); arb_clear(s); arb_clear(t); arb_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-legendre_p_ui.c000066400000000000000000000066461461254215100221170ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_legendre_p_ui, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, r1, r2, r3, r4, s, t; ulong n; slong prec1, prec2, prec3; arb_init(x); arb_init(r1); arb_init(r2); arb_init(r3); arb_init(r4); arb_init(s); arb_init(t); n = n_randtest(state) % 1000; prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 500); prec3 = 2 + n_randint(state, 500); arb_randtest(x, state, 2 + n_randint(state, 1000), 3); arb_mul_2exp_si(x, x, -n_randint(state, 15)); if (n_randint(state, 2)) mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_add_ui(x, x, 1, prec1); arb_hypgeom_legendre_p_ui(r1, r2, n, x, prec1); if (n_randint(state, 2)) { arb_hypgeom_legendre_p_ui(r3, NULL, n, x, prec2); arb_hypgeom_legendre_p_ui(NULL, r4, n, x, prec2); } else { arb_hypgeom_legendre_p_ui(r3, r4, n, x, prec2); } if (!arb_overlaps(r1, r3) || !arb_overlaps(r2, r4)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r3 = "); arb_printn(r3, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("r4 = "); arb_printn(r4, 50, 0); flint_printf("\n\n"); flint_abort(); } if (n != 0) { arb_hypgeom_legendre_p_ui(r3, NULL, n - 1, x, prec3); /* check (x^2-1)/n P'_n(x) = x P_n(x) - P_{n-1}(x) */ arb_mul(s, x, x, prec1); arb_sub_ui(s, s, 1, prec1); arb_mul(s, s, r2, prec1); arb_div_ui(s, s, n, prec1); arb_mul(t, x, r1, prec1); arb_sub(t, t, r3, prec1); if (!arb_overlaps(s, t)) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("r3 = "); arb_printn(r3, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(r1); arb_clear(r2); arb_clear(r3); arb_clear(r4); arb_clear(s); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-legendre_p_ui_asymp.c000066400000000000000000000067461461254215100233310ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_legendre_p_ui_asymp, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, r1, r1p, r2, r2p, r3, s; ulong n; slong prec1, prec2, K, K2, K3; arb_init(x); arb_init(r1); arb_init(r1p); arb_init(r2); arb_init(r2p); arb_init(r3); arb_init(s); n = n_randtest(state) % 500; K = n_randint(state, 50); K2 = n_randint(state, 500); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 500); arb_randtest(x, state, 2 + n_randint(state, 1000), 0); arb_mul_2exp_si(x, x, -n_randint(state, 8)); if (n_randint(state, 2)) mag_zero(arb_radref(x)); arb_hypgeom_legendre_p_ui_asymp(r1, r1p, n, x, K, prec1); arb_hypgeom_legendre_p_ui_one(r2, r2p, n, x, K2, prec2); if (!arb_overlaps(r1, r2) || !arb_overlaps(r1p, r2p)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu, K = %wd\n\n", n, K); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("r1p = "); arb_printn(r1p, 50, 0); flint_printf("\n\n"); flint_printf("r2p = "); arb_printn(r2p, 50, 0); flint_printf("\n\n"); flint_abort(); } n = n_randtest(state); if (n == UWORD_MAX) n--; if (n == 0) n++; K = n_randint(state, 50); K2 = n_randint(state, 50); K3 = n_randint(state, 50); /* test (2n+1) x P_n(x) - n P_(n-1)(x) = (n+1) P_(n+1)(x) */ arb_hypgeom_legendre_p_ui_asymp(r1, NULL, n, x, K, prec2); arb_mul(r1, r1, x, prec2); arb_set_ui(r2, n); arb_add_ui(r2, r2, n, prec2); arb_add_ui(r2, r2, 1, prec2); arb_mul(r1, r1, r2, prec2); arb_hypgeom_legendre_p_ui_asymp(r2, NULL, n - 1, x, K2, prec2); arb_mul_ui(r2, r2, n, prec2); arb_hypgeom_legendre_p_ui_asymp(r3, NULL, n + 1, x, K3, prec2); arb_mul_ui(r3, r3, n + 1, prec2); arb_sub(s, r1, r2, prec2); if (!arb_overlaps(s, r3)) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("n = %wu, K = %wd, K2 = %wd, K3 = %wd\n\n", n, K, K2, K3); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("r3 = "); arb_printn(r3, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(r1); arb_clear(r1p); arb_clear(r2); arb_clear(r2p); arb_clear(r3); arb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-legendre_p_ui_deriv_bound.c000066400000000000000000000052331461254215100244660ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_legendre_p_ui_deriv_bound, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, x2sub1, y, z; mag_t m1, m2, exact; ulong n; slong prec; arb_init(x); arb_init(x2sub1); arb_init(y); arb_init(z); mag_init(m1); mag_init(m2); mag_init(exact); n = n_randtest(state) % 10000; prec = 64; arb_randtest(x, state, 2 * prec, 0); mag_zero(arb_radref(x)); while (arf_cmpabs_2exp_si(arb_midref(x), 0) >= 0) arb_mul_2exp_si(x, x, -1); arb_mul_2exp_si(x, x, -n_randint(state, 10)); arb_mul(x2sub1, x, x, 2 * prec); arb_sub_ui(x2sub1, x2sub1, 1, 2 * prec); arb_neg(x2sub1, x2sub1); arb_hypgeom_legendre_p_ui_deriv_bound(m1, m2, n, x, x2sub1); arb_hypgeom_legendre_p_ui(y, z, n, x, prec); arb_get_mag_lower(exact, z); if (mag_cmp(m1, exact) < 0) { flint_printf("FAIL: first derivative\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 50, 0); flint_printf("\n\n"); flint_printf("m1 = "); mag_printd(m1, 15); flint_printf("\n\n"); flint_abort(); } arb_mul(z, z, x, prec); arb_mul_2exp_si(z, z, 1); arb_mul_ui(y, y, n, prec); arb_mul_ui(y, y, n + 1, prec); arb_sub(z, z, y, prec); arb_div(z, z, x2sub1, prec); arb_get_mag_lower(exact, z); if (mag_cmp(m2, exact) < 0) { flint_printf("FAIL: second derivative\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 50, 0); flint_printf("\n\n"); flint_printf("m2 = "); mag_printd(m2, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(x2sub1); arb_clear(y); arb_clear(z); mag_clear(m1); mag_clear(m2); mag_clear(exact); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-legendre_p_ui_one.c000066400000000000000000000063421461254215100227510ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_legendre_p_ui_one, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, r1, r2, r3, s, t; ulong n; slong prec1, prec2, prec3, K, K2; arb_init(x); arb_init(r1); arb_init(r2); arb_init(r3); arb_init(s); arb_init(t); n = n_randtest(state) % 500; K = n_randint(state, 300); K2 = n_randint(state, 300); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 500); prec3 = 2 + n_randint(state, 500); arb_randtest(x, state, 2 + n_randint(state, 1000), 1); arb_mul_2exp_si(x, x, -n_randint(state, 15)); if (n_randint(state, 2)) mag_zero(arb_radref(x)); if (n_randint(state, 2)) arb_add_ui(x, x, 1, prec1); arb_set_ui(r1, n); arb_set_ui(r2, 0); /* todo: replace with a different implementation later */ arb_hypgeom_legendre_p(r2, r1, r2, x, 0, prec1); arb_hypgeom_legendre_p_ui_one(r1, r3, n, x, K, prec2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu, K = %wd\n\n", n, K); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_abort(); } if (n != 0) { arb_hypgeom_legendre_p_ui_one(r2, NULL, n - 1, x, K2, prec3); /* check (x^2-1)/n P'_n(x) = x P_n(x) - P_{n-1}(x) */ arb_mul(s, x, x, prec1); arb_sub_ui(s, s, 1, prec1); arb_mul(s, s, r3, prec1); arb_div_ui(s, s, n, prec1); arb_mul(t, x, r1, prec1); arb_sub(t, t, r2, prec1); if (!arb_overlaps(s, t)) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("n = %wu, K = %wd, K2 = %wd\n\n", n, K, K2); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("r3 = "); arb_printn(r3, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(r1); arb_clear(r2); arb_clear(r3); arb_clear(s); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-legendre_p_ui_rec.c000066400000000000000000000036621461254215100227430ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_legendre_p_ui_rec, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, r1, r2, r3, r4; ulong n; slong prec1, prec2; arb_init(x); arb_init(r1); arb_init(r2); arb_init(r3); arb_init(r4); n = n_randtest(state) % 500; prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); arb_randtest(x, state, 2 + n_randint(state, 1000), 1); arb_mul_2exp_si(x, x, -n_randint(state, 15)); if (n_randint(state, 2)) mag_zero(arb_radref(x)); arb_hypgeom_legendre_p_ui_rec(r1, r3, n, x, prec1); arb_hypgeom_legendre_p_ui_zero(r2, r4, n, x, n + 1, prec2); if (!arb_overlaps(r1, r2) || !arb_overlaps(r3, r4)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("r3 = "); arb_printn(r3, 50, 0); flint_printf("\n\n"); flint_printf("r4 = "); arb_printn(r4, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(r1); arb_clear(r2); arb_clear(r3); arb_clear(r4); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-legendre_p_ui_root.c000066400000000000000000000122271461254215100231520ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" #include "arb_hypgeom.h" #include "arith.h" TEST_FUNCTION_START(arb_hypgeom_legendre_p_ui_root, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { ulong n, k; slong prec; arb_ptr roots, weights; arb_poly_t pol; arb_t s; fmpq_poly_t pol2; n = 1 + n_randint(state, 100); prec = 20 + n_randint(state, 500); roots = _arb_vec_init(n); weights = _arb_vec_init(n); arb_poly_init(pol); fmpq_poly_init(pol2); arb_init(s); for (k = 0; k < n; k++) { if (k > n / 2 && n_randint(state, 2)) { arb_neg(roots + k, roots + n - k - 1); arb_set(weights + k, weights + n - k - 1); } else { arb_hypgeom_legendre_p_ui_root(roots + k, weights + k, n, k, prec); } } arb_poly_product_roots(pol, roots, n, prec); /* fmpq_poly_legendre_p(pol2, n); */ arith_legendre_polynomial(pol2, n); arb_set_fmpz(s, pol2->coeffs + n); arb_div_fmpz(s, s, pol2->den, prec); arb_poly_scalar_mul(pol, pol, s, prec); if (!arb_poly_contains_fmpq_poly(pol, pol2)) { flint_printf("FAIL: polynomial containment\n\n"); flint_printf("n = %wu, prec = %wd\n\n", n, prec); flint_printf("pol = "); arb_poly_printd(pol, 30); flint_printf("\n\n"); flint_printf("pol2 = "); fmpq_poly_print(pol2); flint_printf("\n\n"); flint_abort(); } arb_zero(s); for (k = 0; k < n; k++) { arb_add(s, s, weights + k, prec); } if (!arb_contains_si(s, 2)) { flint_printf("FAIL: sum of weights\n\n"); flint_printf("n = %wu, prec = %wd\n\n", n, prec); flint_printf("s = "); arb_printn(s, 30, 0); flint_printf("\n\n"); flint_abort(); } _arb_vec_clear(roots, n); _arb_vec_clear(weights, n); arb_poly_clear(pol); fmpq_poly_clear(pol2); arb_clear(s); } for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { arb_t x1, x2, w1, w2; ulong n, k; slong prec1, prec2; arb_init(x1); arb_init(x2); arb_init(w1); arb_init(w2); n = 1 + n_randtest(state) % 100000; if (n_randint(state, 2) || n == 1) k = n_randtest(state) % n; else k = n / 2 - (n_randtest(state) % (n / 2)); prec1 = 2 + n_randtest(state) % 2000; prec2 = 2 + n_randtest(state) % 2000; arb_hypgeom_legendre_p_ui_root(x1, w1, n, k, prec1); if (n_randint(state, 10) == 0) arb_hypgeom_legendre_p_ui_root(x1, NULL, n, k, prec1); arb_hypgeom_legendre_p_ui_root(x2, w2, n, k, prec2); if (!arb_overlaps(x1, x2) || !arb_overlaps(w1, w2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu, k = %wu, prec1 = %wd, prec2 = %wd\n\n", n, k, prec1, prec2); flint_printf("x1 = "); arb_printn(x1, 100, 0); flint_printf("\n\n"); flint_printf("x2 = "); arb_printn(x2, 100, 0); flint_printf("\n\n"); flint_printf("w1 = "); arb_printn(w1, 100, 0); flint_printf("\n\n"); flint_printf("w2 = "); arb_printn(w2, 100, 0); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(x1) < prec1 - 3 || arb_rel_accuracy_bits(w1) < prec1 - 3) { flint_printf("FAIL: accuracy\n\n"); flint_printf("n = %wu, k = %wu, prec1 = %wd\n\n", n, k, prec1); flint_printf("acc(x1) = %wd, acc(w1) = %wd\n\n", arb_rel_accuracy_bits(x1), arb_rel_accuracy_bits(w1)); flint_printf("x1 = "); arb_printn(x1, prec1, ARB_STR_CONDENSE * 30); flint_printf("\n\n"); flint_printf("w1 = "); arb_printn(w1, prec1, ARB_STR_CONDENSE * 30); flint_printf("\n\n"); flint_abort(); } if (arb_rel_accuracy_bits(x2) < prec2 - 3 || arb_rel_accuracy_bits(w2) < prec2 - 3) { flint_printf("FAIL: accuracy 2\n\n"); flint_printf("n = %wu, k = %wu, prec2 = %wd\n\n", n, k, prec2); flint_printf("acc(x2) = %wd, acc(w2) = %wd\n\n", arb_rel_accuracy_bits(x2), arb_rel_accuracy_bits(w2)); flint_printf("x2 = "); arb_printn(x2, prec2, ARB_STR_CONDENSE * 30); flint_printf("\n\n"); flint_printf("w2 = "); arb_printn(w2, prec2, ARB_STR_CONDENSE * 30); flint_printf("\n\n"); flint_abort(); } arb_clear(x1); arb_clear(x2); arb_clear(w1); arb_clear(w2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-legendre_p_ui_zero.c000066400000000000000000000062341461254215100231470ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_legendre_p_ui_zero, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, r1, r2, r3, s, t; ulong n; slong prec1, prec2, prec3, K, K2; arb_init(x); arb_init(r1); arb_init(r2); arb_init(r3); arb_init(s); arb_init(t); n = n_randtest(state) % 500; K = n_randint(state, 300); K2 = n_randint(state, 300); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 500); prec3 = 2 + n_randint(state, 500); arb_randtest(x, state, 2 + n_randint(state, 1000), 1); arb_mul_2exp_si(x, x, -n_randint(state, 15)); if (n_randint(state, 2)) mag_zero(arb_radref(x)); arb_set_ui(r1, n); arb_set_ui(r2, 0); /* todo: replace with a different implementation later */ arb_hypgeom_legendre_p(r2, r1, r2, x, 0, prec1); arb_hypgeom_legendre_p_ui_zero(r1, r3, n, x, K, prec2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu, K = %wd\n\n", n, K); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_abort(); } if (n != 0) { arb_hypgeom_legendre_p_ui_zero(r2, NULL, n - 1, x, K2, prec3); /* check (x^2-1)/n P'_n(x) = x P_n(x) - P_{n-1}(x) */ arb_mul(s, x, x, prec1); arb_sub_ui(s, s, 1, prec1); arb_mul(s, s, r3, prec1); arb_div_ui(s, s, n, prec1); arb_mul(t, x, r1, prec1); arb_sub(t, t, r2, prec1); if (!arb_overlaps(s, t)) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("n = %wu, K = %wd, K2 = %wd\n\n", n, K, K2); flint_printf("x = "); arb_printn(x, 50, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 50, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 50, 0); flint_printf("\n\n"); flint_printf("r3 = "); arb_printn(r3, 50, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 50, 0); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } } arb_clear(x); arb_clear(r1); arb_clear(r2); arb_clear(r3); arb_clear(s); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-lgamma.c000066400000000000000000000061301461254215100205400ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_lgamma, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t z, s1, s2, a, b; slong prec, ebits, prec2; prec = 2 + n_randint(state, 200); if (n_randint(state, 10) == 0) prec = 2 + n_randint(state, 1000); if (n_randint(state, 10) == 0) ebits = 100; else ebits = 10; ebits = 2; prec2 = 2 + n_randint(state, 200); arb_init(z); arb_init(s1); arb_init(s2); arb_init(a); arb_init(b); arb_randtest(z, state, prec, ebits); arb_randtest(s1, state, prec, 10); arb_randtest(s2, state, prec, 10); if (n_randint(state, 2)) { arb_hypgeom_lgamma(s1, z, prec); } else { arb_set(s1, z); arb_hypgeom_lgamma(s1, s1, prec); } arb_add_ui(s2, z, 1, prec2); arb_hypgeom_lgamma(s2, s2, prec2); arb_log(a, z, prec2); arb_sub(s2, s2, a, prec2); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("z = "); arb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); arb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); arb_printd(s1, 1000); flint_printf("\n\n"); flint_abort(); } arb_set(a, z); mag_zero(arb_radref(a)); if (n_randint(state, 2)) { arf_set_mag(arb_midref(b), arb_radref(z)); if (n_randint(state, 2)) arb_neg(b, b); arb_add(a, a, b, prec); } arb_hypgeom_lgamma(s2, a, prec); if (!arb_overlaps(s1, s2)) { flint_printf("FAIL (2)\n\n"); flint_printf("prec = %wd\n\n", prec); flint_printf("z = "); arb_printn(z, 1000, 0); flint_printf("\n\n"); flint_printf("a = "); arb_printn(a, 1000, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 1000, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 1000, 0); flint_printf("\n\n"); arb_sub(s1, s1, s2, prec2); flint_printf("s1 - s2 = "); arb_printd(s1, 1000); flint_printf("\n\n"); flint_abort(); } arb_clear(z); arb_clear(s1); arb_clear(s2); arb_clear(a); arb_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-rising_ui.c000066400000000000000000000062071461254215100212770ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" void rising_algorithm(arb_t res, const arb_t x, ulong n, ulong m, slong prec, int alg, int alias) { if (alias) { arb_set(res, x); rising_algorithm(res, res, n, m, prec, alg, 0); return; } if (alg == 0) arb_hypgeom_rising_ui_rs(res, x, n, m, prec); else if (alg == 1) arb_hypgeom_rising_ui_forward(res, x, n, prec); else if (alg == 2) arb_hypgeom_rising_ui_bs(res, x, n, prec); else if (alg == 3) arb_hypgeom_rising_ui_rec(res, x, n, prec); else arb_hypgeom_rising_ui(res, x, n, prec); } TEST_FUNCTION_START(arb_hypgeom_rising_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, xk, y, ya, yb, yayb; ulong k, n, m1, m2, m3; slong prec; int alg1, alg2, alg3, alias1, alias2, alias3; prec = 2 + n_randint(state, 200); k = n_randint(state, 10); n = n_randint(state, 50); m1 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n + k, 1)); m2 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(k, 1)); m3 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n, 1)); alg1 = n_randint(state, 5); alg2 = n_randint(state, 5); alg3 = n_randint(state, 5); alias1 = n_randint(state, 2); alias2 = n_randint(state, 2); alias3 = n_randint(state, 2); if (n_randint(state, 100) == 0) n += 100; arb_init(x); arb_init(xk); arb_init(y); arb_init(ya); arb_init(yb); arb_init(yayb); arb_randtest(x, state, prec, 10 + n_randint(state, 200)); arb_add_ui(xk, x, k, prec); rising_algorithm(y, x, n + k, m1, prec, alg1, alias1); rising_algorithm(ya, x, k, m2, prec, alg2, alias2); rising_algorithm(yb, xk, n, m3, prec, alg3, alias3); arb_mul(yayb, ya, yb, prec); if (!arb_overlaps(y, yayb)) { flint_printf("FAIL\n\n"); flint_printf("k = %wu, n = %wu, m1 = %wu, m2 = %wu, m3 = %wu\n\n", k, n, m1, m2, m3); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); arb_printn(y, 100, 0); flint_printf("\n\n"); flint_printf("ya = "); arb_printn(ya, 100, 0); flint_printf("\n\n"); flint_printf("yb = "); arb_printn(yb, 100, 0); flint_printf("\n\n"); flint_printf("yayb = "); arb_printn(yayb, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(xk); arb_clear(y); arb_clear(ya); arb_clear(yb); arb_clear(yayb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-rising_ui_jet.c000066400000000000000000000061561461254215100221440ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" #include "arb_hypgeom.h" /* Also defined in t-rising_ui.c */ #define rising_algorithm rising_jet_algorithm void rising_algorithm(arb_ptr res, const arb_t x, ulong n, ulong m, slong len, slong prec, int alg) { if (alg == 0) arb_hypgeom_rising_ui_jet_powsum(res, x, n, len, prec); else if (alg == 1) arb_hypgeom_rising_ui_jet_rs(res, x, n, m, len, prec); else if (alg == 2) arb_hypgeom_rising_ui_jet_bs(res, x, n, len, prec); else arb_hypgeom_rising_ui_jet(res, x, n, len, prec); } TEST_FUNCTION_START(arb_hypgeom_rising_ui_jet, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, xk; arb_ptr y, ya, yb, yayb; ulong k, n, m1, m2, m3, len; slong prec; int alg1, alg2, alg3; prec = 2 + n_randint(state, 200); len = 1 + n_randint(state, 6); k = n_randint(state, 10); n = n_randint(state, 50); m1 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n + k, 1)); m2 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(k, 1)); m3 = n_randint(state, 2) ? 0 : 1 + n_randint(state, FLINT_MAX(n, 1)); alg1 = n_randint(state, 4); alg2 = n_randint(state, 4); alg3 = n_randint(state, 4); arb_init(x); arb_init(xk); y = _arb_vec_init(len); ya = _arb_vec_init(len); yb = _arb_vec_init(len); yayb = _arb_vec_init(len); arb_randtest(x, state, prec, 10); arb_add_ui(xk, x, k, prec); rising_algorithm(y, x, n + k, m1, len, prec, alg1); rising_algorithm(ya, x, k, m2, len, prec, alg2); rising_algorithm(yb, xk, n, m3, len, prec, alg3); _arb_poly_mullow(yayb, ya, len, yb, len, len, prec); if (!_arb_poly_overlaps(y, len, yayb, len)) { flint_printf("FAIL\n\n"); flint_printf("len = %wd, k = %wu, n = %wu, m1 = %wu, m2 = %wu, m3 = %wu\n\n", len, k, n, m1, m2, m3); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); _arb_vec_printn(y, len, 100, 0); flint_printf("\n\n"); flint_printf("ya = "); _arb_vec_printn(ya, len, 100, 0); flint_printf("\n\n"); flint_printf("yb = "); _arb_vec_printn(yb, len, 100, 0); flint_printf("\n\n"); flint_printf("yayb = "); _arb_vec_printn(yayb, len, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(xk); _arb_vec_clear(y, len); _arb_vec_clear(ya, len); _arb_vec_clear(yb, len); _arb_vec_clear(yayb, len); } TEST_FUNCTION_END(state); } #undef rising_algorithm flint-3.1.3/src/arb_hypgeom/test/t-si.c000066400000000000000000000047061461254215100177240ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t x, s, t; slong prec1, prec2; arb_init(x); arb_init(s); arb_init(t); if (n_randint(state, 10) == 0) { prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); } else { prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); } arb_randtest(x, state, 2 + n_randint(state, prec1), 2 + n_randint(state, 100)); arb_randtest(s, state, 2 + n_randint(state, prec1), 2 + n_randint(state, 100)); arb_randtest(t, state, 2 + n_randint(state, prec1), 2 + n_randint(state, 100)); switch (n_randint(state, 3)) { case 0: arb_hypgeom_si(s, x, prec1); break; case 1: _arb_hypgeom_si_1f2(s, x, n_randint(state, prec1), prec1, prec1); break; default: _arb_hypgeom_si_asymp(s, x, n_randint(state, prec1 / 2), prec1); break; } switch (n_randint(state, 3)) { case 0: arb_hypgeom_si(t, x, prec2); break; case 1: _arb_hypgeom_si_1f2(t, x, n_randint(state, prec2), prec2, prec2); break; default: _arb_hypgeom_si_asymp(t, x, n_randint(state, prec2 / 2), prec2); break; } if (!arb_overlaps(s, t)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); arb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("s = "); arb_printn(s, 100, 0); flint_printf("\n\n"); flint_printf("t = "); arb_printn(t, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(x); arb_clear(s); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-sum_fmpq_arb.c000066400000000000000000000053551461254215100217650ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_sum_fmpq_arb, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s1, s2, s3, z; fmpq *a, *b; slong alen, blen, N, prec; int reciprocal; alen = n_randint(state, 5); blen = n_randint(state, 5); N = n_randint(state, 100); arb_init(s1); arb_init(s2); arb_init(s3); arb_init(z); a = _fmpq_vec_init(alen); b = _fmpq_vec_init(blen); prec = 2 + n_randint(state, 500); reciprocal = n_randint(state, 2); if (n_randint(state, 10) == 0) arb_randtest_special(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); else arb_randtest(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(s1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(s2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); _fmpq_vec_randtest(a, state, alen, 1 + n_randint(state, 100)); _fmpq_vec_randtest(b, state, blen, 1 + n_randint(state, 100)); arb_hypgeom_sum_fmpq_arb_forward(s1, a, alen, b, blen, z, reciprocal, N, prec); arb_hypgeom_sum_fmpq_arb_rs(s2, a, alen, b, blen, z, reciprocal, N, prec); arb_hypgeom_sum_fmpq_arb_bs(s3, a, alen, b, blen, z, reciprocal, N, prec); if (!arb_overlaps(s1, s2) || !arb_overlaps(s1, s3)) { flint_printf("FAIL: overlap\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("a = "); _fmpq_vec_print(a, alen); flint_printf("\n\n"); flint_printf("b = "); _fmpq_vec_print(b, blen); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, 0); flint_printf("\n\n"); flint_printf("s3 = "); arb_printn(s3, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(s3); arb_clear(z); _fmpq_vec_clear(a, alen); _fmpq_vec_clear(b, blen); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-sum_fmpq_imag_arb.c000066400000000000000000000066171461254215100227640ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_sum_fmpq_imag_arb, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_t s1, s2, s3, r1, r2, r3, z; fmpq *a, *b; slong alen, blen, N, prec; int reciprocal; alen = n_randint(state, 5); blen = n_randint(state, 5); N = n_randint(state, 100); arb_init(s1); arb_init(s2); arb_init(s3); arb_init(r1); arb_init(r2); arb_init(r3); arb_init(z); a = _fmpq_vec_init(alen); b = _fmpq_vec_init(blen); prec = 2 + n_randint(state, 500); reciprocal = n_randint(state, 2); if (n_randint(state, 10) == 0) arb_randtest_special(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); else arb_randtest(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(s1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arb_randtest_special(s2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); _fmpq_vec_randtest(a, state, alen, 1 + n_randint(state, 100)); _fmpq_vec_randtest(b, state, blen, 1 + n_randint(state, 100)); arb_hypgeom_sum_fmpq_imag_arb_forward(r1, s1, a, alen, b, blen, z, reciprocal, N, prec); arb_hypgeom_sum_fmpq_imag_arb_rs(r2, s2, a, alen, b, blen, z, reciprocal, N, prec); arb_hypgeom_sum_fmpq_imag_arb_bs(r3, s3, a, alen, b, blen, z, reciprocal, N, prec); if (!arb_overlaps(r1, r2) || !arb_overlaps(s1, s2) || !arb_overlaps(r1, r3) || !arb_overlaps(s1, s3)) { flint_printf("FAIL: overlap\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("a = "); _fmpq_vec_print(a, alen); flint_printf("\n\n"); flint_printf("b = "); _fmpq_vec_print(b, blen); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 100, 0); flint_printf("\n\n"); flint_printf("r1 = "); arb_printn(r1, 100, 0); flint_printf("\n\n"); flint_printf("s1 = "); arb_printn(s1, 100, 0); flint_printf("\n\n"); flint_printf("r2 = "); arb_printn(r2, 100, 0); flint_printf("\n\n"); flint_printf("s2 = "); arb_printn(s2, 100, 0); flint_printf("\n\n"); flint_printf("r3 = "); arb_printn(r3, 100, 0); flint_printf("\n\n"); flint_printf("s3 = "); arb_printn(s3, 100, 0); flint_printf("\n\n"); flint_abort(); } arb_clear(s1); arb_clear(s2); arb_clear(s3); arb_clear(r1); arb_clear(r2); arb_clear(r3); arb_clear(z); _fmpq_vec_clear(a, alen); _fmpq_vec_clear(b, blen); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-u_integration.c000066400000000000000000000076661461254215100221700ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" TEST_FUNCTION_START(arb_hypgeom_u_integration, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { arb_t a, b, z, r1, r2; slong prec1, prec2; prec1 = 2 + n_randint(state, 80); prec2 = 2 + n_randint(state, 150); arb_init(a); arb_init(b); arb_init(z); arb_init(r1); arb_init(r2); arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(b, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8)); arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5)); if (n_randint(state, 2)) arb_add_ui(a, a, n_randint(state, 100), prec1 + 100); arb_add_ui(b, b, n_randint(state, 200), prec1 + 100); arb_add_ui(z, z, n_randint(state, 100), prec1 + 100); arb_hypgeom_u_integration(r1, a, b, z, prec1); if (arb_is_finite(r1)) { if (n_randint(state, 2)) arb_hypgeom_u(r2, a, b, z, prec2); else arb_hypgeom_u_integration(r2, a, b, z, prec2); if (!arb_overlaps(r1, r2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n"); flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n"); flint_abort(); } } if (iter == 0) { prec1 = 333; arb_set_str(a, "1.2e7", prec1); arb_set_str(b, "1.3e8", prec1); arb_set_str(z, "1.4e8", prec1); arb_hypgeom_u_integration(r1, a, b, z, prec1); arb_set_str(r2, "7.423720668435352497136323553980928479792327057967344627374385949694801879462740896706198120e-90723524 +/- 6.47e-90723615", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (1)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } arb_set_str(a, "1.0", prec1); arb_set_str(b, "1351.25", prec1); arb_set_str(z, "5118.125", prec1); arb_hypgeom_u_integration(r1, a, b, z, prec1); arb_set_str(r2, "0.0002653059837025369361090415756761601958818507141969057844945316037867908521084665825645386229229474 +/- 5.74e-101", prec1); if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10) { flint_printf("FAIL: overlap (2)\n\n"); flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); arb_clear(z); arb_clear(r1); arb_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/test/t-wrappers.c000066400000000000000000000217071461254215100211540ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_hypgeom.h" void TEST(const arb_t x1, const arb_t x2, const char * s) { if (!arb_overlaps(x1, x2)) { flint_printf("FAIL: %s\n", s); arb_printn(x1, 30, 0); printf("\n\n"); arb_printn(x2, 30, 0); printf("\n\n"); flint_abort(); } } TEST_FUNCTION_START(arb_hypgeom_wrappers, state) { { arb_t a, b, c, d, z, r, u, v; slong prec; prec = 53; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_init(z); arb_init(r); arb_init(u); arb_init(v); arb_set_d(a, 0.5); arb_set_d(b, 0.25); arb_set_d(c, 0.125); arb_set_d(z, 0.75); arb_hypgeom_pfq(r, a, 1, b, 1, z, 0, prec); arb_set_str(v, "[3.40725820729608 +/- 6.88e-15]", prec); TEST(r, v, "pfq"); arb_hypgeom_pfq(r, a, 1, b, 1, z, 1, prec); arb_set_str(v, "[0.93977518087904 +/- 3.26e-15]", prec); TEST(r, v, "pfq regularized"); arb_hypgeom_0f1(r, a, z, 0, prec); arb_set_str(v, "[2.91457744017593 +/- 4.17e-15]", prec); TEST(r, v, "0f1"); arb_hypgeom_0f1(r, a, z, 1, prec); arb_set_str(v, "[1.64437423219054 +/- 3.77e-15]", prec); TEST(r, v, "0f1 regularized"); arb_hypgeom_1f1(r, a, b, z, 0, prec); arb_set_str(v, "[3.40725820729608 +/- 6.88e-15]", prec); TEST(r, v, "1f1"); arb_hypgeom_1f1(r, a, b, z, 1, prec); arb_set_str(v, "[0.93977518087904 +/- 3.26e-15]", prec); TEST(r, v, "1f1 regularized"); arb_hypgeom_u(r, a, b, z, prec); arb_set_str(v, "[0.7761320390950 +/- 3.89e-14]", prec); TEST(r, v, "u"); arb_hypgeom_2f1(r, a, b, c, z, 0, prec); arb_set_str(v, "[3.2569394189980 +/- 8.18e-14]", prec); TEST(r, v, "2f1"); arb_hypgeom_2f1(r, a, b, c, z, 1, prec); arb_set_str(v, "[0.4323021855542 +/- 1.67e-14]", prec); TEST(r, v, "2f1 regularized"); arb_hypgeom_erf(r, z, prec); arb_set_str(v, "[0.711155633653515 +/- 2.35e-16]", prec); TEST(r, v, "erf"); arb_hypgeom_erfc(r, z, prec); arb_set_str(v, "[0.288844366346485 +/- 2.34e-16]", prec); TEST(r, v, "erfc"); arb_hypgeom_erfi(r, z, prec); arb_set_str(v, "[1.03575728441196 +/- 3.17e-15]", prec); TEST(r, v, "erfi"); arb_hypgeom_fresnel(r, NULL, z, 0, prec); arb_set_str(v, "[0.137478632382610 +/- 1.79e-16]", prec); TEST(r, v, "fresnel_s"); arb_hypgeom_fresnel(r, NULL, z, 1, prec); arb_set_str(v, "[0.208877111233384 +/- 4.63e-16]", prec); TEST(r, v, "fresnel_s normalized"); arb_hypgeom_fresnel(NULL, r, z, 0, prec); arb_set_str(v, "[0.726614618304550 +/- 2.11e-16]", prec); TEST(r, v, "fresnel_c"); arb_hypgeom_fresnel(NULL, r, z, 1, prec); arb_set_str(v, "[0.693525990787136 +/- 2.76e-16]", prec); TEST(r, v, "fresnel_c normalized"); arb_hypgeom_gamma_lower(r, a, z, 0, prec); arb_set_str(v, "[1.38132404568612 +/- 3.66e-15]", prec); TEST(r, v, "gamma_lower"); arb_hypgeom_gamma_lower(r, a, z, 1, prec); arb_set_str(v, "[0.77932863808015 +/- 4.17e-15]", prec); TEST(r, v, "gamma_lower 1"); arb_hypgeom_gamma_lower(r, a, z, 2, prec); arb_set_str(v, "[0.89989119796552 +/- 2.76e-15]", prec); TEST(r, v, "gamma_lower 2"); arb_hypgeom_gamma_upper(r, a, z, 0, prec); arb_set_str(v, "[0.39112980521940 +/- 4.21e-15]", prec); TEST(r, v, "gamma_upper"); arb_hypgeom_gamma_upper(r, a, z, 1, prec); arb_set_str(v, "[0.22067136191985 +/- 4.08e-15]", prec); TEST(r, v, "gamma_upper 1"); arb_hypgeom_beta_lower(r, a, b, z, 0, prec); arb_set_str(v, "[2.3363313667086 +/- 3.14e-14]", prec); TEST(r, v, "beta_lower"); arb_hypgeom_beta_lower(r, a, b, z, 1, prec); arb_set_str(v, "[0.44551489018313 +/- 6.22e-15]", prec); TEST(r, v, "beta_lower 1"); arb_hypgeom_expint(r, a, z, prec); arb_set_str(v, "[0.45163779666301 +/- 3.10e-15]", prec); TEST(r, v, "expint"); arb_hypgeom_ei(r, z, prec); arb_set_str(v, "[1.20733281600122 +/- 2.72e-15]", prec); TEST(r, v, "ei"); arb_hypgeom_si(r, z, prec); arb_set_str(v, "[0.72695424715009 +/- 3.99e-15]", prec); TEST(r, v, "si"); arb_hypgeom_ci(r, z, prec); arb_set_str(v, "[0.152163600980330 +/- 5.49e-16]", prec); TEST(r, v, "ci"); arb_hypgeom_shi(r, z, prec); arb_set_str(v, "[0.77383681445623 +/- 5.97e-15]", prec); TEST(r, v, "shi"); arb_hypgeom_chi(r, z, prec); arb_set_str(v, "[0.433496001544996 +/- 7.91e-16]", prec); TEST(r, v, "chi"); arb_hypgeom_li(r, z, 0, prec); arb_set_str(v, "[-0.93693001101265 +/- 5.67e-15]", prec); TEST(r, v, "li"); arb_hypgeom_li(r, z, 1, prec); arb_set_str(v, "[-1.98209379113014 +/- 3.56e-15]", prec); TEST(r, v, "li offset"); arb_hypgeom_bessel_j(r, a, z, prec); arb_set_str(v, "[0.62800587637589 +/- 4.06e-15]", prec); TEST(r, v, "bessel_j"); arb_hypgeom_bessel_y(r, a, z, prec); arb_set_str(v, "[-0.67411792914454 +/- 5.27e-15]", prec); TEST(r, v, "bessel_y"); arb_hypgeom_bessel_jy(r, u, a, z, prec); arb_set_str(v, "[0.62800587637589 +/- 4.06e-15]", prec); TEST(r, v, "bessel_jy"); arb_set_str(v, "[-0.67411792914454 +/- 5.27e-15]", prec); TEST(u, v, "bessel_jy"); arb_hypgeom_bessel_i(r, a, z, prec); arb_set_str(v, "[0.75761498638991 +/- 4.63e-15]", prec); TEST(r, v, "bessel_i"); arb_hypgeom_bessel_i_scaled(r, a, z, prec); arb_set_str(v, "[0.357871979425934 +/- 8.04e-16]", prec); TEST(r, v, "bessel_i"); arb_hypgeom_bessel_k(r, a, z, prec); arb_set_str(v, "[0.68361006034952 +/- 7.89e-15]", prec); TEST(r, v, "bessel_k"); arb_hypgeom_bessel_k_scaled(r, a, z, prec); arb_set_str(v, "[1.4472025091165 +/- 4.23e-14]", prec); TEST(r, v, "bessel_k"); arb_hypgeom_airy(r, NULL, NULL, NULL, z, prec); arb_set_str(v, "[0.179336305478645 +/- 2.36e-16]", prec); TEST(r, v, "airy ai"); arb_hypgeom_airy(NULL, r, NULL, NULL, z, prec); arb_set_str(v, "[-0.193175208104376 +/- 4.67e-16]", prec); TEST(r, v, "airy ai'"); arb_hypgeom_airy(NULL, NULL, r, NULL, z, prec); arb_set_str(v, "[1.00693090863322 +/- 3.90e-15]", prec); TEST(r, v, "airy bi"); arb_hypgeom_airy(NULL, NULL, NULL, r, z, prec); arb_set_str(v, "[0.690299702736886 +/- 2.34e-16]", prec); TEST(r, v, "airy bi'"); arb_hypgeom_coulomb(r, NULL, a, b, z, prec); arb_set_str(v, "[0.281871468006603 +/- 4.68e-16]", prec); TEST(r, v, "coulomb f"); arb_hypgeom_coulomb(NULL, r, a, b, z, prec); arb_set_str(v, "[1.38897454984644 +/- 2.23e-15]", prec); TEST(r, v, "coulomb g"); arb_hypgeom_chebyshev_t(r, a, z, prec); arb_set_str(v, "[0.935414346693485 +/- 7.02e-16]", prec); TEST(r, v, "chebyshev_t"); arb_hypgeom_chebyshev_u(r, a, z, prec); arb_set_str(v, "[1.33630620956212 +/- 3.41e-15]", prec); TEST(r, v, "chebyshev_u"); arb_hypgeom_jacobi_p(r, a, b, c, z, prec); arb_set_str(v, "[1.03224258095454 +/- 6.54e-15]", prec); TEST(r, v, "jacobi_p"); arb_hypgeom_gegenbauer_c(r, a, b, z, prec); arb_set_str(v, "[0.58153237382485 +/- 3.74e-15]", prec); TEST(r, v, "gegenbauer_c"); arb_hypgeom_laguerre_l(r, a, b, z, prec); arb_set_str(v, "[0.76858987769621 +/- 3.19e-15]", prec); TEST(r, v, "laguerre_l"); arb_hypgeom_hermite_h(r, a, z, prec); arb_set_str(v, "[1.31600493243946 +/- 6.52e-15]", prec); TEST(r, v, "hermite_h"); arb_hypgeom_legendre_p(r, a, b, z, 0, prec); arb_set_str(v, "[0.90435295129350 +/- 5.79e-15]", prec); TEST(r, v, "legendre_q"); arb_hypgeom_legendre_q(r, a, b, z, 0, prec); arb_set_str(v, "[-0.3763617490859 +/- 3.83e-14]", prec); TEST(r, v, "legendre_q"); arb_hypgeom_dilog(r, a, prec); arb_set_str(v, "[0.582240526465012 +/- 6.18e-16]", prec); TEST(r, v, "dilog"); arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); arb_clear(z); arb_clear(r); arb_clear(u); arb_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_hypgeom/u_integration.c000066400000000000000000000275661461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_calc.h" #include "double_interval.h" /* Integrand (see comments for 1f1_integration): exp(f(t)) where f(z) = -z*t + a1*log(t) + ba1*log(1+t) g(u,v) = -z*u + 0.5*[a1*log(u^2+v^2) + ba1*log((1+u)^2+v^2)] d/du g(u,v) = -z + u*a1/(u^2+v^2) + (1+u)*ba1/(v^2+(1+u)^2) d/dv g(u,v) = v*a1/(u^2+v^2) + v*ba1/(v^2+(1+u)^2) */ static di_t di_integrand_edge(di_t u, di_t v, di_t a1, di_t ba1, di_t z) { di_t X, Y, Z; X = di_neg(di_fast_mul(z, u)); if (a1.a == 0.0 && a1.b == 0.0) Y = di_interval(0.0, 0.0); else Y = di_fast_mul(a1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(u), di_fast_sqr(v)))); Z = di_fast_mul(ba1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(di_fast_add_d(u, 1.0)), di_fast_sqr(v)))); return di_fast_add(X, di_fast_mul_d(di_fast_add(Y, Z), 0.5)); } /* which == 0 - d/du g(u,v) = -z + u*(a-1)/(u^2+v^2) + (u+1)*(b-a-1)/(v^2+(1+u)^2) which == 1 - d/dv g(u,v) = v*(a-1)/(u^2+v^2) + v*(b-a-1)/(v^2+(1+u)^2) */ static di_t di_integrand_edge_diff(di_t u, di_t v, di_t a1, di_t ba1, di_t z, int which) { di_t Y, Z; if (a1.a == 0.0 && a1.b == 0.0) Y = di_interval(0.0, 0.0); else Y = di_fast_div(a1, di_fast_add(di_fast_sqr(u), di_fast_sqr(v))); Z = di_fast_div(ba1, di_fast_add(di_fast_sqr(di_fast_add_d(u, 1.0)), di_fast_sqr(v))); if (which == 0) return di_fast_add(di_neg(z), di_fast_add(di_fast_mul(u, Y), di_fast_mul(di_fast_add_d(u, 1.0), Z))); else return di_fast_mul(v, di_fast_add(Y, Z)); } static di_t di_subinterval(di_t x, slong i, slong N) { di_t res; double step; step = (x.b - x.a) / N; res.a = x.a + step * i; res.b = (i == N - 1) ? x.b : x.a + step * (i + 1); return res; } static void integrand_wide_bound5(acb_t res, const acb_t t, const arb_t a1, const arb_t ba1, const arb_t z, slong prec) { slong i, N; di_t du, dv, da1, dba1, dz, dg, dgprime; double radius, bound; double start, end; int which; arb_t abound; N = 8; bound = -D_INF; da1 = arb_get_di(a1); dba1 = arb_get_di(ba1); dz = arb_get_di(z); /* left edge: left(u) + [0, right(v)] */ /* right edge: right(u) + [0, right(v)] */ for (which = 0; which < 2; which++) { du = arb_get_di(acb_realref(t)); if (which == 0) du.b = du.a; else du.a = du.b; dv = arb_get_di(acb_imagref(t)); start = 0.0; end = dv.b; for (i = 0; i < N; i++) { dv = di_subinterval(di_interval(start, end), i, N); radius = di_fast_ubound_radius(dv); /* g(u,mid(v)) + g'(u,v) * [0, radius] */ #if 1 dg = di_integrand_edge(du, di_fast_mid(dv), da1, dba1, dz); dgprime = di_integrand_edge_diff(du, dv, da1, dba1, dz, 1); dg = di_fast_add(dg, di_fast_mul(dgprime, di_interval(0.0, radius))); #else dg = di_integrand_edge(du, dv, da1, dba1, dz); #endif bound = FLINT_MAX(bound, dg.b); } } du = arb_get_di(acb_realref(t)); start = du.a; end = du.b; dv = arb_get_di(acb_imagref(t)); dv.a = dv.b; /* top edge: [left(u), right(u)] + right(v) */ for (i = 0; i < N; i++) { du = di_subinterval(di_interval(start, end), i, N); radius = di_fast_ubound_radius(du); /* g(mid(u),v) + g'(u,v) * [0, radius] */ #if 1 dg = di_integrand_edge(di_fast_mid(du), dv, da1, dba1, dz); dgprime = di_integrand_edge_diff(du, dv, da1, dba1, dz, 0); dg = di_fast_add(dg, di_fast_mul(dgprime, di_interval(0.0, radius))); #else dg = di_integrand_edge(du, dv, da1, dba1, dz); #endif bound = FLINT_MAX(bound, dg.b); } arb_init(abound); arb_set_d(abound, bound); arb_exp(abound, abound, prec); acb_zero(res); arb_add_error(acb_realref(res), abound); arb_add_error(acb_imagref(res), abound); arb_clear(abound); } /* todo: fix acb_pow(_arb) */ static void acb_my_pow_arb(acb_t res, const acb_t a, const arb_t b, slong prec) { if (acb_contains_zero(a) && arb_is_positive(b)) { /* |a^b| <= |a|^b */ arb_t t, u; arb_init(t); arb_init(u); acb_abs(t, a, prec); arb_get_abs_ubound_arf(arb_midref(t), t, prec); mag_zero(arb_radref(t)); if (arf_cmpabs_2exp_si(arb_midref(t), 0) < 0) arb_get_abs_lbound_arf(arb_midref(u), b, prec); else arb_get_abs_ubound_arf(arb_midref(u), b, prec); arb_pow(t, t, u, prec); acb_zero(res); acb_add_error_arb(res, t); arb_clear(t); arb_clear(u); } else { acb_pow_arb(res, a, b, prec); } } static int integrand(acb_ptr out, const acb_t t, void * param, slong order, slong prec) { arb_srcptr a1, ba1, z; acb_t s, u, v; a1 = ((arb_srcptr) param) + 0; ba1 = ((arb_srcptr) param) + 1; z = ((arb_srcptr) param) + 2; acb_init(s); acb_init(u); acb_init(v); acb_add_ui(v, t, 1, prec); if (order == 1) { if (!(arb_is_positive(acb_realref(t)) || arb_is_zero(a1)) || !arb_is_positive(acb_realref(v))) acb_indeterminate(out); else integrand_wide_bound5(out, t, a1, ba1, z, prec); } else { if (acb_contains_zero(t) || acb_contains_zero(v)) { /* exp(-z t) */ acb_mul_arb(s, t, z, prec); acb_neg(s, s); acb_exp(s, s, prec); /* t^(a-1) */ acb_my_pow_arb(u, t, a1, prec); /* (1+t)^(b-a-1) */ acb_pow_arb(v, v, ba1, prec); acb_mul(out, s, u, prec); acb_mul(out, out, v, prec); } else { acb_mul_arb(s, t, z, prec); acb_neg(s, s); /* t^(a-1) */ if (arb_is_zero(a1)) { acb_zero(u); } else { acb_log(u, t, prec); acb_mul_arb(u, u, a1, prec); } /* (1+t)^(b-a-1) */ acb_log(v, v, prec); acb_mul_arb(v, v, ba1, prec); acb_add(out, s, u, prec); acb_add(out, out, v, prec); acb_exp(out, out, prec); } } acb_clear(s); acb_clear(u); acb_clear(v); return 0; } /* estimate integral by magnitude at peak */ static void estimate_magnitude(mag_t res, const arb_t ra, const arb_t rb, const arb_t rz) { double a, b, z, t1, t2, u, m; fmpz_t e; a = arf_get_d(arb_midref(ra), ARF_RND_NEAR); b = arf_get_d(arb_midref(rb), ARF_RND_NEAR); z = arf_get_d(arb_midref(rz), ARF_RND_NEAR); u = 4 - 4*b + b*b + 4*a*z - 2*b*z + z*z; if (u >= 0.0) { t1 = (-2 + b - z + sqrt(u)) / (2 * z); t2 = (-2 + b - z - sqrt(u)) / (2 * z); } else { t1 = 1e-8; t2 = 1e-8; } /* todo: better estimate when peak is at 0 */ t1 = FLINT_MAX(t1, 1e-8); t2 = FLINT_MAX(t2, 1e-8); m = -1e300; if (t1 > 0.0) { t1 = -z * t1 + (a - 1) * log(t1) + (b - a - 1) * log(1 + t1); m = FLINT_MAX(m, t1); } if (t2 > 0.0) { t2 = -z * t2 + (a - 1) * log(t2) + (b - a - 1) * log(1 + t2); m = FLINT_MAX(m, t2); } m /= log(2); if (fabs(m) < 1e300) { fmpz_init(e); fmpz_set_d(e, m); mag_set_d_2exp_fmpz(res, 1.0, e); fmpz_clear(e); } else { mag_zero(res); } } static void bound_tail(mag_t bound, const arb_t a1, const arb_t ba1, const arb_t z, const arb_t N, slong prec) { arb_t s, u, v, C; arb_init(s); arb_init(u); arb_init(v); arb_init(C); /* Assume N >= 1 and t >= 0. -z*(N+t) + (a-1)*log(N+t) + (b-a-1)*log(1+N+t) <= [-z*N + (a-1)*log(N) + (b-a-1)*log(1+N)] + [-z*t + [max(0, a-1) + max(0, b-a-1)]*log(1+t/N)] <= [-z*N + (a-1)*log(N) + (b-a-1)*log(1+N)] + [-z*t + [max(0, a-1) + max(0, b-a-1)]*(t/N)] Let C = max(0, a-1) + max(0, b-a-1). Then the remainder integral is bounded by integrand(N) * N / (N*z - C), assuming that N*z > C. */ arb_max(u, u, a1, prec); arb_max(v, v, ba1, prec); arb_add(C, u, v, prec); /* s = N*z - C */ arb_mul(s, N, z, prec); arb_sub(s, s, C, prec); if (arb_is_positive(s)) { arb_div(C, N, s, prec); /* exp(-z*N) */ arb_mul(s, N, z, prec); arb_neg(s, s); /* N^(a-1) */ arb_log(u, N, prec); arb_mul(u, u, a1, prec); /* (1+N)^(b-a-1) */ arb_add_ui(v, N, 1, prec); arb_log(v, v, prec); arb_mul(v, v, ba1, prec); arb_add(s, s, u, prec); arb_add(s, s, v, prec); arb_exp(s, s, prec); arb_mul(s, s, C, prec); arb_get_mag(bound, s); } else { mag_inf(bound); } arb_clear(s); arb_clear(u); arb_clear(v); arb_clear(C); } int _arb_hypgeom_u_integration(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec) { acb_calc_integrate_opt_t opt; arb_struct param[3]; arb_t t, a1, ba1; acb_t zero, N, I; mag_t abs_tol, tail_bound; slong i; fmpz_t n; int ok; arb_init(t); arb_init(a1); arb_init(ba1); arb_sub_ui(a1, a, 1, prec); arb_sub(ba1, b, a, prec); arb_sub_ui(ba1, ba1, 1, prec); ok = arb_is_finite(z) && arb_is_positive(z); ok = ok && arb_is_nonnegative(a1); ok = ok && arb_is_finite(b); if (!ok) { arb_indeterminate(res); } else { mag_init(abs_tol); mag_init(tail_bound); acb_init(zero); acb_init(zero); acb_init(N); acb_init(I); fmpz_init(n); param[0] = *a1; param[1] = *ba1; param[2] = *z; acb_calc_integrate_opt_init(opt); /* opt->verbose = 2; */ /* opt->eval_limit = WORD_MAX; */ estimate_magnitude(abs_tol, a, b, z); mag_mul_2exp_si(abs_tol, abs_tol, -prec); for (i = 1; i < FLINT_BITS; i++) { fmpz_one(n); fmpz_mul_2exp(n, n, i); acb_one(N); arb_mul_2exp_fmpz(acb_realref(N), acb_realref(N), n); bound_tail(tail_bound, a1, ba1, z, acb_realref(N), 64); if (mag_cmp(tail_bound, abs_tol) < 0) break; } acb_calc_integrate(I, integrand, param, zero, N, prec, abs_tol, opt, prec); arb_add_error_mag(acb_realref(I), tail_bound); arb_rgamma(t, a, prec); arb_mul(acb_realref(I), acb_realref(I), t, prec); arb_set(res, acb_realref(I)); mag_clear(abs_tol); mag_clear(tail_bound); acb_clear(zero); acb_clear(N); acb_clear(I); fmpz_clear(n); } arb_clear(t); arb_clear(a1); arb_clear(ba1); return ok; } void arb_hypgeom_u_integration(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec) { arb_t res2; arb_init(res2); if (!_arb_hypgeom_u_integration(res2, a, b, z, prec)) { arb_t c, d; arb_init(c); arb_init(d); arb_sub(c, a, b, prec); arb_add_ui(c, c, 1, prec); arb_sub_ui(d, b, 2, prec); arb_neg(d, d); if (_arb_hypgeom_u_integration(res2, c, d, z, prec)) { arb_sub_ui(c, b, 1, prec); arb_neg(c, c); arb_pow(c, z, c, prec); arb_mul(res2, res2, c, prec); } arb_clear(c); arb_clear(d); } arb_swap(res, res2); arb_clear(res2); } flint-3.1.3/src/arb_hypgeom/wrappers.c000066400000000000000000000330611461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" void arb_hypgeom_erfi(arb_t res, const arb_t z, slong prec) { if (!arb_is_finite(z)) { arb_indeterminate(res); } else { acb_t t; acb_init(t); arb_set(acb_realref(t), z); acb_hypgeom_erfi(t, t, prec); arb_swap(res, acb_realref(t)); acb_clear(t); } } void arb_hypgeom_fresnel(arb_t res1, arb_t res2, const arb_t z, int normalized, slong prec) { if (!arb_is_finite(z)) { if (res1 != NULL) arb_indeterminate(res1); if (res2 != NULL) arb_indeterminate(res2); } else { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), z); acb_hypgeom_fresnel(res1 ? t : NULL, res2 ? u : NULL, t, normalized, prec); if (res1 != NULL) arb_swap(res1, acb_realref(t)); if (res2 != NULL) arb_swap(res2, acb_realref(u)); acb_clear(t); acb_clear(u); } } void arb_hypgeom_ei(arb_t res, const arb_t z, slong prec) { if (!arb_is_finite(z)) { arb_indeterminate(res); } else { acb_t t; acb_init(t); arb_set(acb_realref(t), z); acb_hypgeom_ei(t, t, prec); arb_swap(res, acb_realref(t)); acb_clear(t); } } void arb_hypgeom_shi(arb_t res, const arb_t z, slong prec) { if (!arb_is_finite(z)) { arb_indeterminate(res); } else { acb_t t; acb_init(t); arb_set(acb_realref(t), z); acb_hypgeom_shi(t, t, prec); arb_swap(res, acb_realref(t)); acb_clear(t); } } void arb_hypgeom_chi(arb_t res, const arb_t z, slong prec) { if (!arb_is_finite(z) || !arb_is_positive(z)) { arb_indeterminate(res); } else { acb_t t; acb_init(t); arb_set(acb_realref(t), z); acb_hypgeom_chi(t, t, prec); arb_swap(res, acb_realref(t)); acb_clear(t); } } void arb_hypgeom_li(arb_t res, const arb_t z, int offset, slong prec) { if (!arb_is_finite(z) || !arb_is_nonnegative(z)) { arb_indeterminate(res); } else { acb_t t; acb_init(t); arb_set(acb_realref(t), z); acb_hypgeom_li(t, t, offset, prec); arb_swap(res, acb_realref(t)); acb_clear(t); } } void arb_hypgeom_0f1(arb_t res, const arb_t a, const arb_t z, int regularized, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), a); arb_set(acb_realref(u), z); acb_hypgeom_0f1(t, t, u, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_m(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); arb_set(acb_realref(t), a); arb_set(acb_realref(u), b); arb_set(acb_realref(v), z); acb_hypgeom_m(t, t, u, v, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } void arb_hypgeom_1f1(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) { arb_hypgeom_m(res, a, b, z, regularized, prec); } void arb_hypgeom_u(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); arb_set(acb_realref(t), a); arb_set(acb_realref(u), b); arb_set(acb_realref(v), z); acb_hypgeom_u(t, t, u, v, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } void arb_hypgeom_2f1(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec) { acb_t t, u, v, w; acb_init(t); acb_init(u); acb_init(v); acb_init(w); arb_set(acb_realref(t), a); arb_set(acb_realref(u), b); arb_set(acb_realref(v), c); arb_set(acb_realref(w), z); acb_hypgeom_2f1(t, t, u, v, w, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); } void arb_hypgeom_pfq(arb_t res, arb_srcptr a, slong p, arb_srcptr b, slong q, const arb_t z, int regularized, slong prec) { acb_ptr t; slong i; t = _acb_vec_init(p + q + 1); for (i = 0; i < p; i++) arb_set(acb_realref(t + i), a + i); for (i = 0; i < q; i++) arb_set(acb_realref(t + p + i), b + i); arb_set(acb_realref(t + p + q), z); acb_hypgeom_pfq(t, t, p, t + p, q, t + p + q, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); _acb_vec_clear(t, p + q + 1); } void arb_hypgeom_bessel_j(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_bessel_j(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_bessel_y(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_bessel_y(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_bessel_jy(arb_t res1, arb_t res2, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_bessel_jy(t, u, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res1, acb_realref(t)); else arb_indeterminate(res1); if (acb_is_finite(u) && acb_is_real(u)) arb_swap(res2, acb_realref(u)); else arb_indeterminate(res2); acb_clear(t); acb_clear(u); } void arb_hypgeom_bessel_i(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_bessel_i(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_bessel_i_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_bessel_i_scaled(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_bessel_k(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_bessel_k(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_bessel_k_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_bessel_k_scaled(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_expint(arb_t res, const arb_t s, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), s); arb_set(acb_realref(u), z); acb_hypgeom_expint(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_gamma_lower(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), s); arb_set(acb_realref(u), z); acb_hypgeom_gamma_lower(t, t, u, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_gamma_upper(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), s); arb_set(acb_realref(u), z); acb_hypgeom_gamma_upper(t, t, u, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); arb_set(acb_realref(t), a); arb_set(acb_realref(u), b); arb_set(acb_realref(v), z); acb_hypgeom_beta_lower(t, t, u, v, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } void arb_hypgeom_chebyshev_t(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_chebyshev_t(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_chebyshev_u(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_chebyshev_u(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_jacobi_p(arb_t res, const arb_t n, const arb_t a, const arb_t b, const arb_t z, slong prec) { acb_t t, u, v, w; acb_init(t); acb_init(u); acb_init(v); acb_init(w); arb_set(acb_realref(t), n); arb_set(acb_realref(u), a); arb_set(acb_realref(v), b); arb_set(acb_realref(w), z); acb_hypgeom_jacobi_p(t, t, u, v, w, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); } void arb_hypgeom_gegenbauer_c(arb_t res, const arb_t n, const arb_t m, const arb_t z, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); arb_set(acb_realref(t), n); arb_set(acb_realref(u), m); arb_set(acb_realref(v), z); acb_hypgeom_gegenbauer_c(t, t, u, v, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } void arb_hypgeom_laguerre_l(arb_t res, const arb_t n, const arb_t m, const arb_t z, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); arb_set(acb_realref(t), n); arb_set(acb_realref(u), m); arb_set(acb_realref(v), z); acb_hypgeom_laguerre_l(t, t, u, v, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } void arb_hypgeom_hermite_h(arb_t res, const arb_t nu, const arb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); arb_set(acb_realref(t), nu); arb_set(acb_realref(u), z); acb_hypgeom_hermite_h(t, t, u, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); } void arb_hypgeom_legendre_q(arb_t res, const arb_t n, const arb_t m, const arb_t z, int type, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); arb_set(acb_realref(t), n); arb_set(acb_realref(u), m); arb_set(acb_realref(v), z); acb_hypgeom_legendre_q(t, t, u, v, type, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); } void arb_hypgeom_dilog(arb_t res, const arb_t z, slong prec) { acb_t t; acb_init(t); arb_set(acb_realref(t), z); acb_hypgeom_dilog(t, t, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); } flint-3.1.3/src/arb_mat.h000066400000000000000000000332321461254215100152030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_MAT_H #define ARB_MAT_H #ifdef ARB_MAT_INLINES_C #define ARB_MAT_INLINE #else #define ARB_MAT_INLINE static inline #endif #include "fmpq_types.h" #include "arb.h" #ifdef __cplusplus extern "C" { #endif #define arb_mat_entry(mat,i,j) ((mat)->rows[i] + (j)) #define arb_mat_nrows(mat) ((mat)->r) #define arb_mat_ncols(mat) ((mat)->c) ARB_MAT_INLINE arb_ptr arb_mat_entry_ptr(arb_mat_t mat, slong i, slong j) { return arb_mat_entry(mat, i, j); } /* Memory management */ void arb_mat_init(arb_mat_t mat, slong r, slong c); void arb_mat_clear(arb_mat_t mat); ARB_MAT_INLINE void arb_mat_swap(arb_mat_t mat1, arb_mat_t mat2) { FLINT_SWAP(arb_mat_struct, *mat1, *mat2); } ARB_MAT_INLINE void arb_mat_swap_entrywise(arb_mat_t mat1, arb_mat_t mat2) { slong i, j; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) arb_swap(arb_mat_entry(mat2, i, j), arb_mat_entry(mat1, i, j)); } /* Window matrices */ void arb_mat_window_init(arb_mat_t window, const arb_mat_t mat, slong r1, slong c1, slong r2, slong c2); ARB_MAT_INLINE void arb_mat_window_clear(arb_mat_t window) { flint_free(window->rows); } /* Conversions */ void arb_mat_set(arb_mat_t dest, const arb_mat_t src); void arb_mat_set_fmpz_mat(arb_mat_t dest, const fmpz_mat_t src); void arb_mat_set_round_fmpz_mat(arb_mat_t dest, const fmpz_mat_t src, slong prec); void arb_mat_set_fmpq_mat(arb_mat_t dest, const fmpq_mat_t src, slong prec); /* Random generation */ void arb_mat_randtest(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits); void arb_mat_randtest_cho(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits); void arb_mat_randtest_spd(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits); /* I/O */ #ifdef FLINT_HAVE_FILE void arb_mat_fprintd(FILE * file, const arb_mat_t mat, slong digits); #endif void arb_mat_printd(const arb_mat_t mat, slong digits); /* Comparisons */ int arb_mat_eq(const arb_mat_t mat1, const arb_mat_t mat2); int arb_mat_ne(const arb_mat_t mat1, const arb_mat_t mat2); int arb_mat_equal(const arb_mat_t mat1, const arb_mat_t mat2); int arb_mat_overlaps(const arb_mat_t mat1, const arb_mat_t mat2); int arb_mat_contains(const arb_mat_t mat1, const arb_mat_t mat2); int arb_mat_contains_fmpq_mat(const arb_mat_t mat1, const fmpq_mat_t mat2); int arb_mat_contains_fmpz_mat(const arb_mat_t mat1, const fmpz_mat_t mat2); ARB_MAT_INLINE int arb_mat_is_empty(const arb_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } ARB_MAT_INLINE int arb_mat_is_square(const arb_mat_t mat) { return (mat->r == mat->c); } int arb_mat_is_exact(const arb_mat_t A); int arb_mat_is_zero(const arb_mat_t mat); int arb_mat_is_finite(const arb_mat_t mat); int arb_mat_is_triu(const arb_mat_t mat); int arb_mat_is_tril(const arb_mat_t mat); ARB_MAT_INLINE int arb_mat_is_diag(const arb_mat_t mat) { return arb_mat_is_tril(mat) && arb_mat_is_triu(mat); } /* Radius and interval operations */ ARB_MAT_INLINE void arb_mat_get_mid(arb_mat_t B, const arb_mat_t A) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_get_mid_arb(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j)); } ARB_MAT_INLINE void arb_mat_add_error_mag(arb_mat_t mat, const mag_t err) { slong i, j; for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) arb_add_error_mag(arb_mat_entry(mat, i, j), err); } /* Special matrices */ void arb_mat_zero(arb_mat_t mat); void arb_mat_one(arb_mat_t mat); void arb_mat_ones(arb_mat_t mat); void arb_mat_indeterminate(arb_mat_t mat); void arb_mat_hilbert(arb_mat_t mat, slong prec); void arb_mat_pascal(arb_mat_t mat, int triangular, slong prec); void arb_mat_stirling(arb_mat_t mat, int kind, slong prec); void arb_mat_dct(arb_mat_t mat, int type, slong prec); void arb_mat_transpose(arb_mat_t mat1, const arb_mat_t mat2); /* Norms */ void arb_mat_bound_inf_norm(mag_t b, const arb_mat_t A); void arb_mat_frobenius_norm(arb_t res, const arb_mat_t A, slong prec); void arb_mat_bound_frobenius_norm(mag_t b, const arb_mat_t A); /* Arithmetic */ void arb_mat_neg(arb_mat_t dest, const arb_mat_t src); void arb_mat_add(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec); void arb_mat_sub(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec); void arb_mat_mul(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec); void arb_mat_mul_classical(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec); void arb_mat_mul_threaded(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec); void _arb_mat_addmul_rad_mag_fast(arb_mat_t C, mag_srcptr A, mag_srcptr B, slong ar, slong ac, slong bc); void arb_mat_mul_block(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec); void arb_mat_mul_entrywise(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec); void arb_mat_sqr_classical(arb_mat_t B, const arb_mat_t A, slong prec); void arb_mat_sqr(arb_mat_t B, const arb_mat_t A, slong prec); void arb_mat_pow_ui(arb_mat_t B, const arb_mat_t A, ulong exp, slong prec); /* Scalar arithmetic */ ARB_MAT_INLINE void arb_mat_scalar_mul_2exp_si(arb_mat_t B, const arb_mat_t A, slong c) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_mul_2exp_si(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c); } ARB_MAT_INLINE void arb_mat_scalar_addmul_si(arb_mat_t B, const arb_mat_t A, slong c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_addmul_si(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_mul_si(arb_mat_t B, const arb_mat_t A, slong c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_mul_si(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_div_si(arb_mat_t B, const arb_mat_t A, slong c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_div_si(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_addmul_fmpz(arb_mat_t B, const arb_mat_t A, const fmpz_t c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_addmul_fmpz(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_mul_fmpz(arb_mat_t B, const arb_mat_t A, const fmpz_t c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_mul_fmpz(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_div_fmpz(arb_mat_t B, const arb_mat_t A, const fmpz_t c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_div_fmpz(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_addmul_arb(arb_mat_t B, const arb_mat_t A, const arb_t c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_addmul(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_mul_arb(arb_mat_t B, const arb_mat_t A, const arb_t c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_mul(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } ARB_MAT_INLINE void arb_mat_scalar_div_arb(arb_mat_t B, const arb_mat_t A, const arb_t c, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_div(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), c, prec); } /* Vector arithmetic */ void _arb_mat_vector_mul_row(arb_ptr res, arb_srcptr v, const arb_mat_t A, slong prec); void _arb_mat_vector_mul_col(arb_ptr res, const arb_mat_t A, arb_srcptr v, slong prec); void arb_mat_vector_mul_row(arb_ptr res, arb_srcptr v, const arb_mat_t A, slong prec); void arb_mat_vector_mul_col(arb_ptr res, const arb_mat_t A, arb_srcptr v, slong prec); /* Solving */ ARB_MAT_INLINE void arb_mat_swap_rows(arb_mat_t mat, slong * perm, slong r, slong s) { if (r != s) { if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(arb_ptr, mat->rows[r], mat->rows[s]); } } slong arb_mat_find_pivot_partial(const arb_mat_t mat, slong start_row, slong end_row, slong c); void arb_mat_solve_tril_classical(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec); void arb_mat_solve_tril_recursive(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec); void arb_mat_solve_tril(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec); void arb_mat_solve_triu_classical(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec); void arb_mat_solve_triu_recursive(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec); void arb_mat_solve_triu(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec); int arb_mat_lu_classical(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec); int arb_mat_lu_recursive(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec); int arb_mat_lu(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec); void arb_mat_solve_lu_precomp(arb_mat_t X, const slong * perm, const arb_mat_t A, const arb_mat_t B, slong prec); int arb_mat_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec); int arb_mat_solve_lu(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec); int arb_mat_solve_precond(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec); int arb_mat_solve_preapprox(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, const arb_mat_t R, const arb_mat_t T, slong prec); void arb_mat_approx_mul(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec); void arb_mat_approx_solve_triu(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec); void arb_mat_approx_solve_tril(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec); int arb_mat_approx_lu(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec); void arb_mat_approx_solve_lu_precomp(arb_mat_t X, const slong * perm, const arb_mat_t A, const arb_mat_t B, slong prec); int arb_mat_approx_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec); int arb_mat_approx_inv(arb_mat_t X, const arb_mat_t A, slong prec); int arb_mat_inv(arb_mat_t X, const arb_mat_t A, slong prec); void arb_mat_det_lu(arb_t det, const arb_mat_t A, slong prec); void arb_mat_det_precond(arb_t det, const arb_mat_t A, slong prec); void arb_mat_det(arb_t det, const arb_mat_t A, slong prec); int _arb_mat_cholesky_banachiewicz(arb_mat_t A, slong prec); int arb_mat_cho(arb_mat_t L, const arb_mat_t A, slong prec); void arb_mat_solve_cho_precomp(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, slong prec); void arb_mat_inv_cho_precomp(arb_mat_t X, const arb_mat_t L, slong prec); int arb_mat_spd_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec); int arb_mat_spd_inv(arb_mat_t X, const arb_mat_t A, slong prec); int _arb_mat_ldl_inplace(arb_mat_t A, slong prec); int _arb_mat_ldl_golub_and_van_loan(arb_mat_t A, slong prec); int arb_mat_ldl(arb_mat_t L, const arb_mat_t A, slong prec); void arb_mat_solve_ldl_precomp(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, slong prec); void arb_mat_inv_ldl_precomp(arb_mat_t X, const arb_mat_t L, slong prec); /* Special functions */ void arb_mat_exp_taylor_sum(arb_mat_t S, const arb_mat_t A, slong N, slong prec); void arb_mat_exp(arb_mat_t B, const arb_mat_t A, slong prec); void _arb_mat_charpoly(arb_ptr poly, const arb_mat_t mat, slong prec); void arb_mat_charpoly(arb_poly_t poly, const arb_mat_t mat, slong prec); void _arb_mat_companion(arb_mat_t mat, arb_srcptr poly, slong prec); void arb_mat_companion(arb_mat_t mat, const arb_poly_t poly, slong prec); void arb_mat_trace(arb_t trace, const arb_mat_t mat, slong prec); void _arb_mat_diag_prod(arb_t res, const arb_mat_t A, slong a, slong b, slong prec); void arb_mat_diag_prod(arb_t res, const arb_mat_t A, slong prec); /* Sparsity structure */ void arb_mat_entrywise_is_zero(fmpz_mat_t dest, const arb_mat_t src); void arb_mat_entrywise_not_is_zero(fmpz_mat_t dest, const arb_mat_t src); slong arb_mat_count_is_zero(const arb_mat_t mat); ARB_MAT_INLINE slong arb_mat_count_not_is_zero(const arb_mat_t mat) { slong size; size = arb_mat_nrows(mat) * arb_mat_ncols(mat); return size - arb_mat_count_is_zero(mat); } ARB_MAT_INLINE slong arb_mat_allocated_bytes(const arb_mat_t x) { return _arb_vec_allocated_bytes(x->entries, x->r * x->c) + x->r * sizeof(arb_ptr); } /* LLL reduction */ int arb_mat_spd_get_fmpz_mat(fmpz_mat_t B, const arb_mat_t A, slong prec); void arb_mat_spd_lll_reduce(fmpz_mat_t U, const arb_mat_t A, slong prec); int arb_mat_spd_is_lll_reduced(const arb_mat_t A, slong tol_exp, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arb_mat/000077500000000000000000000000001461254215100150275ustar00rootroot00000000000000flint-3.1.3/src/arb_mat/add.c000066400000000000000000000013651461254215100157300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_add(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) arb_add(arb_mat_entry(res, i, j), arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j), prec); } flint-3.1.3/src/arb_mat/addmul_rad_mag_fast.c000066400000000000000000000212061461254215100211310ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #ifdef __GNUC__ # define frexp __builtin_frexp # define ldexp __builtin_ldexp #else # include #endif #include "double_extras.h" /* Block size for better cache locality. */ #define BLOCK_SIZE 32 /* Don't convert to doubles when smaller than this block size. */ #define MIN_D_BLOCK_SIZE 5 /* With doubles, we can have an exponent range of about 1024, minus some slack for accumulated sums. */ #define DOUBLE_MAX_OFFSET 900 static inline double dot8(const double * A, const double * B) { return ((A[0] * B[0] + A[1] * B[1]) + (A[2] * B[2] + A[3] * B[3])) + ((A[4] * B[4] + A[5] * B[5]) + (A[6] * B[6] + A[7] * B[7])); } /* Upper bound of matrix product, assuming nonnegative entries and no overflow/underflow. B is pre-transposed. Straightforward blocked implementation; could use BLAS, but this matrix product is rarely going to be the bottleneck. */ static void _d_mat_addmul(double * C, const double * A, const double * B, slong ar, slong ac, slong bc) { slong ii, jj, kk, i, j, k; double t, eps; eps = ldexp(1.0, -52); for (ii = 0; ii < ar; ii += BLOCK_SIZE) { for (jj = 0; jj < bc; jj += BLOCK_SIZE) { for (kk = 0; kk < ac; kk += BLOCK_SIZE) { for (i = ii; i < FLINT_MIN(ii + BLOCK_SIZE, ar); i++) { for (j = jj; j < FLINT_MIN(jj + BLOCK_SIZE, bc); j++) { if (BLOCK_SIZE == 32 && kk + BLOCK_SIZE <= ac) { double t0, t1, t2, t3; t0 = dot8(A + i * ac + kk + 0, B + j * ac + kk + 0); t1 = dot8(A + i * ac + kk + 8, B + j * ac + kk + 8); t2 = dot8(A + i * ac + kk + 16, B + j * ac + kk + 16); t3 = dot8(A + i * ac + kk + 24, B + j * ac + kk + 24); t = (t0 + t1) + (t2 + t3); } else { t = 0.0; for (k = kk; k < FLINT_MIN(kk + BLOCK_SIZE, ac); k++) t += A[i * ac + k] * B[j * ac + k]; } C[i * bc + j] += t; } } } } } /* Compensate for possible rounding errors */ for (i = 0; i < ar; i++) for (j = 0; j < bc; j++) C[i * bc + j] *= (1.0 + 2.01 * (ac + 1) * eps); } /* We use WORD_MIN to represent zero here. */ static inline slong _mag_get_exp(const mag_t x) { if (mag_is_special(x)) return WORD_MIN; else return MAG_EXP(x); } static double mag_get_d_fixed_si(const mag_t x, slong e) { return d_mul_2exp(MAG_MAN(x), MAG_EXP(x) - e - MAG_BITS); } void _arb_mat_addmul_rad_mag_fast(arb_mat_t C, mag_srcptr A, mag_srcptr B, slong ar, slong ac, slong bc) { slong i, j, k, M, N, P, top, n, block_start, block_end; slong *A_min, *A_max, *B_min, *B_max, max_offset; double *CC, *AA, *BB; M = ar; N = ac; P = bc; /* todo: could use TMP_ALLOC */ A_min = flint_malloc(sizeof(slong) * M); A_max = flint_malloc(sizeof(slong) * M); B_min = flint_malloc(sizeof(slong) * P); B_max = flint_malloc(sizeof(slong) * P); AA = flint_malloc(ar * ac * sizeof(double)); BB = flint_malloc(ac * bc * sizeof(double)); CC = flint_malloc(ar * bc * sizeof(double)); max_offset = DOUBLE_MAX_OFFSET; block_start = 0; while (block_start < N) { block_end = block_start + 1; /* index is exclusive block_end */ /* begin with this column of A and row of B */ for (i = 0; i < M; i++) A_max[i] = A_min[i] = _mag_get_exp(A + i * N + block_start); for (i = 0; i < P; i++) B_max[i] = B_min[i] = _mag_get_exp(B + i * N + block_start); while (block_end < N) { /* check if we can extend with column [block_end] of A */ for (i = 0; i < M; i++) { top = _mag_get_exp(A + i * N + block_end); /* zeros are irrelevant */ if (top == WORD_MIN || A_max[i] == WORD_MIN) continue; /* jump will be too big */ if (top > A_min[i] + max_offset || top < A_max[i] - max_offset) goto mblocks_built; } /* check if we can extend with row [block_end] of B */ for (i = 0; i < P; i++) { top = _mag_get_exp(B + i * N + block_end); if (top == WORD_MIN || B_max[i] == WORD_MIN) continue; if (top > B_min[i] + max_offset || top < B_max[i] - max_offset) goto mblocks_built; } /* second pass to update the extreme values */ for (i = 0; i < M; i++) { top = _mag_get_exp(A + i * N + block_end); if (A_max[i] == WORD_MIN) { A_max[i] = top; A_min[i] = top; } else if (top != WORD_MIN) { if (top < A_min[i]) A_min[i] = top; if (top > A_max[i]) A_max[i] = top; } } for (i = 0; i < P; i++) { top = _mag_get_exp(B + i * N + block_end); if (B_max[i] == WORD_MIN) { B_max[i] = top; B_min[i] = top; } else if (top != WORD_MIN) { if (top < B_min[i]) B_min[i] = top; if (top > B_max[i]) B_max[i] = top; } } block_end++; } mblocks_built: n = block_end - block_start; if (n <= MIN_D_BLOCK_SIZE) { /* increment so we don't just do steps of 1 in degenerate cases */ block_end = FLINT_MIN(block_start + MIN_D_BLOCK_SIZE, N); n = block_end - block_start; for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { for (k = 0; k < n; k++) { mag_fast_addmul(arb_radref(arb_mat_entry(C, i, j)), A + i * ac + block_start + k, B + j * ac + block_start + k); } } } } else { for (i = 0; i < ar; i++) { if (A_min[i] == WORD_MIN) /* only zeros in this row */ continue; A_min[i] = (A_min[i] + A_max[i]) / 2; for (j = 0; j < n; j++) AA[i * n + j] = mag_get_d_fixed_si(A + i * ac + block_start + j, A_min[i]); } /* Note: B and BB are both transposed in memory */ for (i = 0; i < bc; i++) { if (B_min[i] == WORD_MIN) /* only zeros in this column */ continue; B_min[i] = (B_min[i] + B_max[i]) / 2; for (j = 0; j < n; j++) BB[i * n + j] = mag_get_d_fixed_si(B + i * ac + block_start + j, B_min[i]); } for (i = 0; i < ar * bc; i++) CC[i] = 0.0; _d_mat_addmul(CC, AA, BB, ar, n, bc); for (i = 0; i < ar; i++) { if (A_min[i] == WORD_MIN) continue; for (j = 0; j < bc; j++) { if (B_min[j] == WORD_MIN) continue; if (CC[i * bc + j] != 0.0) { mag_t t; MAG_SET_D_2EXP(MAG_MAN(t), MAG_EXP(t), CC[i * bc + j], A_min[i] + B_min[j]); mag_add(arb_radref(arb_mat_entry(C, i, j)), arb_radref(arb_mat_entry(C, i, j)), t); } } } } block_start = block_end; } flint_free(A_max); flint_free(A_min); flint_free(B_max); flint_free(B_min); flint_free(AA); flint_free(BB); flint_free(CC); } flint-3.1.3/src/arb_mat/approx_inv.c000066400000000000000000000014221461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_approx_inv(arb_mat_t X, const arb_mat_t A, slong prec) { if (X == A) { int r; arb_mat_t T; arb_mat_init(T, arb_mat_nrows(A), arb_mat_ncols(A)); r = arb_mat_approx_inv(T, A, prec); arb_mat_swap(T, X); arb_mat_clear(T); return r; } arb_mat_one(X); return arb_mat_approx_solve(X, A, X, prec); } flint-3.1.3/src/arb_mat/approx_lu.c000066400000000000000000000105651461254215100172130ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" static void _apply_permutation(slong * AP, arb_mat_t A, slong * P, slong n, slong offset) { if (n != 0) { arb_ptr * Atmp; slong * APtmp; slong i; Atmp = flint_malloc(sizeof(arb_ptr) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } void _arb_vec_approx_scalar_addmul(arb_ptr res, arb_srcptr vec, slong len, const arb_t c, slong prec) { slong i; for (i = 0; i < len; i++) arf_addmul(arb_midref(res + i), arb_midref(vec + i), arb_midref(c), prec, ARF_RND_DOWN); } int arb_mat_approx_lu_classical(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec) { arf_t d; arb_t e; arb_ptr * a; slong i, j, m, n, r, row, col; int result; if (arb_mat_is_empty(A)) return 1; m = arb_mat_nrows(A); n = arb_mat_ncols(A); arb_mat_get_mid(LU, A); a = LU->rows; row = col = 0; for (i = 0; i < m; i++) P[i] = i; arf_init(d); arb_init(e); result = 1; while (row < m && col < n) { r = arb_mat_find_pivot_partial(LU, row, m, col); if (r == -1) { result = 0; break; } else if (r != row) arb_mat_swap_rows(LU, P, row, r); arf_ui_div(d, 1, arb_midref(a[row] + col), prec, ARB_RND); for (j = row + 1; j < m; j++) { arf_mul(arb_midref(e), arb_midref(a[j] + col), d, prec, ARB_RND); arb_neg(e, e); _arb_vec_approx_scalar_addmul(a[j] + col, a[row] + col, n - col, e, prec); arf_zero(arb_midref(a[j] + col)); arb_neg(a[j] + row, e); } row++; col++; } arf_clear(d); arb_clear(e); return result; } int arb_mat_approx_lu_recursive(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec) { slong i, m, n, r1, r2, n1; arb_mat_t A0, A1, A00, A01, A10, A11; slong * P1; m = A->r; n = A->c; if (m <= 1 || n <= 1) { return arb_mat_approx_lu_classical(P, LU, A, prec); } arb_mat_get_mid(LU, A); n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; P1 = flint_malloc(sizeof(slong) * m); arb_mat_window_init(A0, LU, 0, 0, m, n1); arb_mat_window_init(A1, LU, 0, n1, m, n); r1 = arb_mat_approx_lu(P1, A0, A0, prec); if (!r1) { flint_free(P1); arb_mat_window_clear(A0); arb_mat_window_clear(A1); return 0; } /* r1 = rank of A0 */ r1 = FLINT_MIN(m, n1); _apply_permutation(P, LU, P1, m, 0); arb_mat_window_init(A00, LU, 0, 0, r1, r1); arb_mat_window_init(A10, LU, r1, 0, m, r1); arb_mat_window_init(A01, LU, 0, n1, r1, n); arb_mat_window_init(A11, LU, r1, n1, m, n); arb_mat_approx_solve_tril(A01, A00, A01, 1, prec); { /* arb_mat_approx_submul(A11, A11, A10, A01, prec); */ arb_mat_t T; arb_mat_init(T, A10->r, A01->c); arb_mat_approx_mul(T, A10, A01, prec); arb_mat_sub(A11, A11, T, prec); arb_mat_get_mid(A11, A11); arb_mat_clear(T); } r2 = arb_mat_approx_lu(P1, A11, A11, prec); if (!r2) r1 = r2 = 0; else _apply_permutation(P, LU, P1, m - r1, r1); flint_free(P1); arb_mat_window_clear(A00); arb_mat_window_clear(A01); arb_mat_window_clear(A10); arb_mat_window_clear(A11); arb_mat_window_clear(A0); arb_mat_window_clear(A1); return r1 && r2; } int arb_mat_approx_lu(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec) { if (arb_mat_nrows(A) < 8 || arb_mat_ncols(A) < 8) return arb_mat_approx_lu_classical(P, LU, A, prec); else return arb_mat_approx_lu_recursive(P, LU, A, prec); } flint-3.1.3/src/arb_mat/approx_mul.c000066400000000000000000000071531461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_approx_mul_classical(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) { slong ar, br, bc, i, j, k; ar = arb_mat_nrows(A); br = arb_mat_nrows(B); bc = arb_mat_ncols(B); if (br == 0) { arb_mat_zero(C); return; } if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, ar, bc); arb_mat_approx_mul_classical(T, A, B, prec); arb_mat_swap_entrywise(T, C); arb_mat_clear(T); return; } if (br <= 2) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { arf_mul(arb_midref(arb_mat_entry(C, i, j)), arb_midref(arb_mat_entry(A, i, 0)), arb_midref(arb_mat_entry(B, 0, j)), prec, ARB_RND); for (k = 1; k < br; k++) { arf_addmul(arb_midref(arb_mat_entry(C, i, j)), arb_midref(arb_mat_entry(A, i, k)), arb_midref(arb_mat_entry(B, k, j)), prec, ARB_RND); } } } } else { arb_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(sizeof(arb_struct) * br * bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) tmp[j * br + i] = *arb_mat_entry(B, i, j); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { arb_approx_dot(arb_mat_entry(C, i, j), NULL, 0, A->rows[i], 1, tmp + j * br, 1, br, prec); } } TMP_END; } } void arb_mat_approx_mul(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) { slong cutoff; /* todo: detect small-integer matrices */ if (prec <= 2 * FLINT_BITS) cutoff = 120; else if (prec <= 16 * FLINT_BITS) cutoff = 60; else cutoff = 40; if (arb_mat_nrows(A) <= cutoff || arb_mat_ncols(A) <= cutoff || arb_mat_ncols(B) <= cutoff) { arb_mat_approx_mul_classical(C, A, B, prec); } else { if (arb_mat_is_exact(A) && arb_mat_is_exact(B)) { arb_mat_mul(C, A, B, prec); } else { arb_mat_t AM, BM; if (arb_mat_is_exact(A)) { arb_mat_init(BM, arb_mat_nrows(B), arb_mat_ncols(B)); arb_mat_get_mid(BM, B); arb_mat_mul(C, A, BM, prec); arb_mat_clear(BM); } else if (arb_mat_is_exact(B)) { arb_mat_init(AM, arb_mat_nrows(A), arb_mat_ncols(A)); arb_mat_get_mid(AM, A); arb_mat_mul(C, AM, B, prec); arb_mat_clear(AM); } else { arb_mat_init(BM, arb_mat_nrows(B), arb_mat_ncols(B)); arb_mat_get_mid(BM, B); arb_mat_init(AM, arb_mat_nrows(A), arb_mat_ncols(A)); arb_mat_get_mid(AM, A); arb_mat_mul(C, AM, BM, prec); arb_mat_clear(AM); arb_mat_clear(BM); } } arb_mat_get_mid(C, C); } } flint-3.1.3/src/arb_mat/approx_solve.c000066400000000000000000000016231461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "arb_mat.h" int arb_mat_approx_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { int result; slong n, m, *perm; arb_mat_t LU; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; perm = _perm_init(n); arb_mat_init(LU, n, n); result = arb_mat_approx_lu(perm, LU, A, prec); if (result) arb_mat_approx_solve_lu_precomp(X, perm, LU, B, prec); arb_mat_clear(LU); _perm_clear(perm); return result; } flint-3.1.3/src/arb_mat/approx_solve_lu_precomp.c000066400000000000000000000024601461254215100221430ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_approx_solve_lu_precomp(arb_mat_t X, const slong * perm, const arb_mat_t A, const arb_mat_t B, slong prec) { slong i, c, n, m; n = arb_mat_nrows(X); m = arb_mat_ncols(X); if (X == B) { arb_ptr tmp = flint_malloc(sizeof(arb_struct) * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) tmp[i] = B->rows[perm[i]][c]; for (i = 0; i < n; i++) X->rows[i][c] = tmp[i]; } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { arb_set(arb_mat_entry(X, i, c), arb_mat_entry(B, perm[i], c)); } } } arb_mat_get_mid(X, X); arb_mat_approx_solve_tril(X, A, X, 1, prec); arb_mat_approx_solve_triu(X, A, X, 0, prec); } flint-3.1.3/src/arb_mat/approx_solve_tril.c000066400000000000000000000056301461254215100207520ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" static void arb_approx_div(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_div(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); } void arb_mat_approx_solve_tril_classical(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) { slong i, j, n, m; arb_ptr tmp; arb_t s; n = L->r; m = B->c; arb_init(s); tmp = flint_malloc(sizeof(arb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *arb_mat_entry(X, j, i); for (j = 0; j < n; j++) { arb_approx_dot(s, arb_mat_entry(B, j, i), 1, L->rows[j], 1, tmp, 1, j, prec); if (!unit) arb_approx_div(tmp + j, s, arb_mat_entry(L, j, j), prec); else arb_swap(tmp + j, s); } for (j = 0; j < n; j++) *arb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); arb_clear(s); } void arb_mat_approx_solve_tril_recursive(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) { arb_mat_t LA, LC, LD, XX, XY, BX, BY, T; slong r, n, m; n = L->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A 0]^ [X] == [A^ 0 ] [X] == [A^ X] [C D] [Y] == [-D^ C A^ D^] [Y] == [D^ (Y - C A^ X)] */ arb_mat_window_init(LA, L, 0, 0, r, r); arb_mat_window_init(LC, L, r, 0, n, r); arb_mat_window_init(LD, L, r, r, n, n); arb_mat_window_init(BX, B, 0, 0, r, m); arb_mat_window_init(BY, B, r, 0, n, m); arb_mat_window_init(XX, X, 0, 0, r, m); arb_mat_window_init(XY, X, r, 0, n, m); arb_mat_approx_solve_tril(XX, LA, BX, unit, prec); /* arb_mat_submul(XY, BY, LC, XX); */ arb_mat_init(T, LC->r, BX->c); arb_mat_approx_mul(T, LC, XX, prec); arb_mat_sub(XY, BY, T, prec); arb_mat_get_mid(XY, XY); arb_mat_clear(T); arb_mat_approx_solve_tril(XY, LD, XY, unit, prec); arb_mat_window_clear(LA); arb_mat_window_clear(LC); arb_mat_window_clear(LD); arb_mat_window_clear(BX); arb_mat_window_clear(BY); arb_mat_window_clear(XX); arb_mat_window_clear(XY); } void arb_mat_approx_solve_tril(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) arb_mat_approx_solve_tril_classical(X, L, B, unit, prec); else arb_mat_approx_solve_tril_recursive(X, L, B, unit, prec); } flint-3.1.3/src/arb_mat/approx_solve_triu.c000066400000000000000000000055361461254215100207700ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" static void arb_approx_div(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_div(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); } void arb_mat_approx_solve_triu_classical(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) { slong i, j, n, m; arb_ptr tmp; arb_t s; n = U->r; m = B->c; arb_init(s); tmp = flint_malloc(sizeof(arb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *arb_mat_entry(X, j, i); for (j = n - 1; j >= 0; j--) { arb_approx_dot(s, arb_mat_entry(B, j, i), 1, U->rows[j] + j + 1, 1, tmp + j + 1, 1, n - j - 1, prec); if (!unit) arb_approx_div(tmp + j, s, arb_mat_entry(U, j, j), prec); else arb_swap(tmp + j, s); } for (j = 0; j < n; j++) *arb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); arb_clear(s); } void arb_mat_approx_solve_triu_recursive(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) { arb_mat_t UA, UB, UD, XX, XY, BX, BY, T; slong r, n, m; n = U->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A B]^ [X] == [A^ (X - B D^ Y)] [0 D] [Y] == [ D^ Y ] */ arb_mat_window_init(UA, U, 0, 0, r, r); arb_mat_window_init(UB, U, 0, r, r, n); arb_mat_window_init(UD, U, r, r, n, n); arb_mat_window_init(BX, B, 0, 0, r, m); arb_mat_window_init(BY, B, r, 0, n, m); arb_mat_window_init(XX, X, 0, 0, r, m); arb_mat_window_init(XY, X, r, 0, n, m); arb_mat_approx_solve_triu(XY, UD, BY, unit, prec); arb_mat_init(T, UB->r, XY->c); arb_mat_approx_mul(T, UB, XY, prec); arb_mat_sub(XX, BX, T, prec); arb_mat_get_mid(XX, XX); arb_mat_clear(T); arb_mat_approx_solve_triu(XX, UA, XX, unit, prec); arb_mat_window_clear(UA); arb_mat_window_clear(UB); arb_mat_window_clear(UD); arb_mat_window_clear(BX); arb_mat_window_clear(BY); arb_mat_window_clear(XX); arb_mat_window_clear(XY); } void arb_mat_approx_solve_triu(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) arb_mat_approx_solve_triu_classical(X, U, B, unit, prec); else arb_mat_approx_solve_triu_recursive(X, U, B, unit, prec); } flint-3.1.3/src/arb_mat/bound_frobenius_norm.c000066400000000000000000000015221461254215100214110ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_bound_frobenius_norm(mag_t b, const arb_mat_t A) { slong i, j, r, c; mag_t t; r = arb_mat_nrows(A); c = arb_mat_ncols(A); mag_zero(b); if (r == 0 || c == 0) return; mag_init(t); for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { arb_get_mag(t, arb_mat_entry(A, i, j)); mag_addmul(b, t, t); } } mag_sqrt(b, b); mag_clear(t); } flint-3.1.3/src/arb_mat/bound_inf_norm.c000066400000000000000000000016221461254215100201720ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_bound_inf_norm(mag_t b, const arb_mat_t A) { slong i, j, r, c; mag_t s, t; r = arb_mat_nrows(A); c = arb_mat_ncols(A); mag_zero(b); if (r == 0 || c == 0) return; mag_init(s); mag_init(t); for (i = 0; i < r; i++) { mag_zero(s); for (j = 0; j < c; j++) { arb_get_mag(t, arb_mat_entry(A, i, j)); mag_add(s, s, t); } mag_max(b, b, s); } mag_clear(s); mag_clear(t); } flint-3.1.3/src/arb_mat/charpoly.c000066400000000000000000000044111461254215100170140ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_mat.h" void _arb_mat_charpoly(arb_ptr cp, const arb_mat_t mat, slong prec) { const slong n = mat->r; if (n == 0) { arb_one(cp); } else if (n == 1) { arb_neg(cp + 0, arb_mat_entry(mat, 0, 0)); arb_one(cp + 1); } else { slong i, k, t; arb_ptr a, A, s; a = _arb_vec_init(n * n); A = a + (n - 1) * n; _arb_vec_zero(cp, n + 1); arb_neg(cp + 0, arb_mat_entry(mat, 0, 0)); for (t = 1; t < n; t++) { for (i = 0; i <= t; i++) { arb_set(a + 0 * n + i, arb_mat_entry(mat, i, t)); } arb_set(A + 0, arb_mat_entry(mat, t, t)); for (k = 1; k < t; k++) { for (i = 0; i <= t; i++) { s = a + k * n + i; arb_dot(s, NULL, 0, mat->rows[i], 1, a + (k - 1) * n, 1, t + 1, prec); } arb_set(A + k, a + k * n + t); } arb_dot(A + t, NULL, 0, mat->rows[t], 1, a + (t - 1) * n, 1, t + 1, prec); for (k = 0; k <= t; k++) { arb_dot(cp + k, cp + k, 1, A, 1, cp + k - 1, -1, k, prec); arb_sub(cp + k, cp + k, A + k, prec); } } /* Shift all coefficients up by one */ for (i = n; i > 0; i--) arb_swap(cp + i, cp + (i - 1)); arb_one(cp + 0); _arb_poly_reverse(cp, cp, n + 1, n + 1); _arb_vec_clear(a, n * n); } } void arb_mat_charpoly(arb_poly_t cp, const arb_mat_t mat, slong prec) { if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (arb_mat_charpoly). Non-square matrix.\n"); } arb_poly_fit_length(cp, mat->r + 1); _arb_poly_set_length(cp, mat->r + 1); _arb_mat_charpoly(cp->coeffs, mat, prec); } flint-3.1.3/src/arb_mat/cho.c000066400000000000000000000045241461254215100157510ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int _arb_mat_cholesky_banachiewicz(arb_mat_t A, slong prec) { slong n, i, j, k; n = arb_mat_nrows(A); for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { for (k = 0; k < j; k++) { arb_submul(arb_mat_entry(A, i, j), arb_mat_entry(A, i, k), arb_mat_entry(A, j, k), prec); } arb_div(arb_mat_entry(A, i, j), arb_mat_entry(A, i, j), arb_mat_entry(A, j, j), prec); } for (k = 0; k < i; k++) { arb_submul(arb_mat_entry(A, i, i), arb_mat_entry(A, i, k), arb_mat_entry(A, i, k), prec); } if (!arb_is_positive(arb_mat_entry(A, i, i))) return 0; arb_sqrt(arb_mat_entry(A, i, i), arb_mat_entry(A, i, i), prec); } return 1; } int arb_mat_cho(arb_mat_t L, const arb_mat_t A, slong prec) { slong n; if (!arb_mat_is_square(A)) { flint_throw(FLINT_ERROR, "arb_mat_cho: a square matrix is required\n"); } if (arb_mat_nrows(L) != arb_mat_nrows(A) || arb_mat_ncols(L) != arb_mat_ncols(A)) { flint_throw(FLINT_ERROR, "arb_mat_cho: incompatible dimensions\n"); } if (arb_mat_is_empty(A)) return 1; n = arb_mat_nrows(A); if (n == 1) { if (arb_is_positive(arb_mat_entry(A, 0, 0))) { arb_sqrt(arb_mat_entry(L, 0, 0), arb_mat_entry(A, 0, 0), prec); return 1; } else { return 0; } } arb_mat_set(L, A); if (!_arb_mat_cholesky_banachiewicz(L, prec)) return 0; /* set the strictly upper triangular region of L to zero */ { slong i, j; for (i = 0; i < n; i++) for (j = i+1; j < n; j++) arb_zero(arb_mat_entry(L, i, j)); } return 1; } flint-3.1.3/src/arb_mat/clear.c000066400000000000000000000010731461254215100162620ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_clear(arb_mat_t mat) { if (mat->entries != NULL) { _arb_vec_clear(mat->entries, mat->r * mat->c); flint_free(mat->rows); } } flint-3.1.3/src/arb_mat/companion.c000066400000000000000000000022701461254215100171570ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_mat.h" void _arb_mat_companion(arb_mat_t A, arb_srcptr poly, slong prec) { slong i, j, n; arb_t c; n = arb_mat_nrows(A); if (n == 0) return; for (i = 0; i < n - 1; i++) for (j = 0; j < n; j++) arb_set_ui(arb_mat_entry(A, i, j), (i + 1) == j); arb_init(c); arb_inv(c, poly + n, prec); arb_neg(c, c); for (j = 0; j < n; j++) arb_mul(arb_mat_entry(A, n - 1, j), poly + j, c, prec); arb_clear(c); } void arb_mat_companion(arb_mat_t A, const arb_poly_t poly, slong prec) { slong n = arb_mat_nrows(A); if (n != arb_poly_degree(poly) || n != arb_mat_ncols(A)) { flint_throw(FLINT_ERROR, "arb_mat_companion: incompatible dimensions!\n"); } _arb_mat_companion(A, poly->coeffs, prec); } flint-3.1.3/src/arb_mat/contains.c000066400000000000000000000015121461254215100170100ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_contains(const arb_mat_t mat1, const arb_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 0; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (!arb_contains(arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/contains_fmpq_mat.c000066400000000000000000000016001461254215100206720ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" #include "arb_mat.h" int arb_mat_contains_fmpq_mat(const arb_mat_t mat1, const fmpq_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 0; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (!arb_contains_fmpq(arb_mat_entry(mat1, i, j), fmpq_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/contains_fmpz_mat.c000066400000000000000000000016001461254215100207030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "arb_mat.h" int arb_mat_contains_fmpz_mat(const arb_mat_t mat1, const fmpz_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 0; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (!arb_contains_fmpz(arb_mat_entry(mat1, i, j), fmpz_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/count_is_zero.c000066400000000000000000000013441461254215100200570ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" slong arb_mat_count_is_zero(const arb_mat_t mat) { slong nz; slong i, j; nz = 0; for (i = 0; i < arb_mat_nrows(mat); i++) { for (j = 0; j < arb_mat_ncols(mat); j++) { if (arb_is_zero(arb_mat_entry(mat, i, j))) { nz++; } } } return nz; } flint-3.1.3/src/arb_mat/dct.c000066400000000000000000000024651461254215100157540ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "acb_dirichlet.h" void arb_mat_dct(arb_mat_t res, int kind, slong prec) { acb_dirichlet_roots_t roots; acb_t t; arb_t v; slong n, r, c, i, j; r = arb_mat_nrows(res); c = arb_mat_ncols(res); n = FLINT_MIN(r, c); if (n == 0) return; acb_dirichlet_roots_init(roots, 4 * n, (r - 1) * c, prec); acb_init(t); arb_init(v); arb_set_ui(v, n); arb_rsqrt(v, v, prec); if (r > 0) { for (j = 0; j < c; j++) arb_set(arb_mat_entry(res, 0, j), v); } arb_set_ui(v, n); arb_mul_2exp_si(v, v, -1); arb_rsqrt(v, v, prec); for (i = 1; i < r; i++) { for (j = 0; j < c; j++) { acb_dirichlet_root(t, roots, i * (2 * j + 1), prec); arb_mul(arb_mat_entry(res, i, j), acb_realref(t), v, prec); } } acb_dirichlet_roots_clear(roots); acb_clear(t); arb_clear(v); } flint-3.1.3/src/arb_mat/det.c000066400000000000000000000043671461254215100157610ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" static void _arb_mat_det_cofactor_2x2(arb_t t, const arb_mat_t A, slong prec) { arb_mul (t, arb_mat_entry(A, 0, 0), arb_mat_entry(A, 1, 1), prec); arb_submul(t, arb_mat_entry(A, 0, 1), arb_mat_entry(A, 1, 0), prec); } static void _arb_mat_det_cofactor_3x3(arb_t t, const arb_mat_t A, slong prec) { arb_t a; arb_init(a); arb_mul (a, arb_mat_entry(A, 1, 0), arb_mat_entry(A, 2, 1), prec); arb_submul(a, arb_mat_entry(A, 1, 1), arb_mat_entry(A, 2, 0), prec); arb_mul (t, a, arb_mat_entry(A, 0, 2), prec); arb_mul (a, arb_mat_entry(A, 1, 2), arb_mat_entry(A, 2, 0), prec); arb_submul(a, arb_mat_entry(A, 1, 0), arb_mat_entry(A, 2, 2), prec); arb_addmul(t, a, arb_mat_entry(A, 0, 1), prec); arb_mul (a, arb_mat_entry(A, 1, 1), arb_mat_entry(A, 2, 2), prec); arb_submul(a, arb_mat_entry(A, 1, 2), arb_mat_entry(A, 2, 1), prec); arb_addmul(t, a, arb_mat_entry(A, 0, 0), prec); arb_clear(a); } void arb_mat_det(arb_t det, const arb_mat_t A, slong prec) { slong n; if (!arb_mat_is_square(A)) { flint_throw(FLINT_ERROR, "arb_mat_det: a square matrix is required!\n"); } n = arb_mat_nrows(A); if (n == 0) { arb_one(det); } else if (n == 1) { arb_set_round(det, arb_mat_entry(A, 0, 0), prec); } else if (n == 2) { _arb_mat_det_cofactor_2x2(det, A, prec); } else if (!arb_mat_is_finite(A)) { arb_indeterminate(det); } else if (arb_mat_is_tril(A) || arb_mat_is_triu(A)) { arb_mat_diag_prod(det, A, prec); } else if (n == 3) { _arb_mat_det_cofactor_3x3(det, A, prec); /* note: 4x4 performs worse than LU */ } else { if (n <= 10 || prec > 10.0 * n) arb_mat_det_lu(det, A, prec); else arb_mat_det_precond(det, A, prec); } } flint-3.1.3/src/arb_mat/det_lu.c000066400000000000000000000054711461254215100164560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" slong arb_mat_gauss_partial(arb_mat_t A, slong prec) { arb_t e; arb_ptr * a; slong j, m, n, r, rank, row, col, sign; m = A->r; n = A->c; a = A->rows; rank = row = col = 0; sign = 1; arb_init(e); while (row < m && col < n) { r = arb_mat_find_pivot_partial(A, row, m, col); if (r == -1) { break; } else if (r != row) { arb_mat_swap_rows(A, NULL, row, r); sign *= -1; } rank++; for (j = row + 1; j < m; j++) { arb_div(e, a[j] + col, a[row] + col, prec); arb_neg(e, e); _arb_vec_scalar_addmul(a[j] + col + 1, a[row] + col + 1, n - col - 1, e, prec); } row++; col++; } arb_clear(e); return rank * sign; } void arb_vec_get_arf_2norm_squared_bound(arf_t s, arb_srcptr vec, slong len, slong prec) { slong i; arf_t t; arf_init(t); arf_zero(s); for (i = 0; i < len; i++) { arb_get_abs_ubound_arf(t, vec + i, prec); arf_addmul(s, t, t, prec, ARF_RND_UP); } arf_clear(t); } void arb_mat_det_lu_inplace(arb_t det, arb_mat_t A, slong prec) { slong i, n, sign, rank; n = arb_mat_nrows(A); rank = arb_mat_gauss_partial(A, prec); sign = (rank < 0) ? -1 : 1; rank = FLINT_ABS(rank); arb_set_si(det, sign); for (i = 0; i < rank; i++) arb_mul(det, det, arb_mat_entry(A, i, i), prec); /* bound unreduced part using Hadamard's inequality */ if (rank < n) { arf_t t; arf_t d; arb_t b; arf_init(t); arf_init(d); arb_init(b); arf_one(d); for (i = rank; i < n; i++) { arb_vec_get_arf_2norm_squared_bound(t, A->rows[i] + rank, n - rank, MAG_BITS); arf_mul(d, d, t, MAG_BITS, ARF_RND_UP); } arf_sqrt(d, d, MAG_BITS, ARF_RND_UP); arb_add_error_arf(b, d); arb_mul(det, det, b, prec); arf_clear(d); arf_clear(t); arb_clear(b); } } void arb_mat_det_lu(arb_t det, const arb_mat_t A, slong prec) { slong n; n = arb_mat_nrows(A); if (n == 0) { arb_one(det); } else { arb_mat_t T; arb_mat_init(T, arb_mat_nrows(A), arb_mat_ncols(A)); arb_mat_set(T, A); arb_mat_det_lu_inplace(det, T, prec); arb_mat_clear(T); } } flint-3.1.3/src/arb_mat/det_precond.c000066400000000000000000000061751461254215100174720ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "arb_mat.h" static void _apply_permutation(arb_mat_t A, slong * P, slong n) { arb_ptr * Atmp; slong i; Atmp = flint_malloc(sizeof(arb_ptr) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i]]; for (i = 0; i < n; i++) A->rows[i] = Atmp[i]; flint_free(Atmp); } /* Enclosure of det(I + eps) using Gershgorin circles. Can be improved. */ void arb_mat_det_one_gershgorin(arb_t det, const arb_mat_t A) { slong n, i, j; arb_t t; mag_t r, e, f; n = arb_mat_nrows(A); arb_init(t); mag_init(r); mag_init(e); mag_init(f); for (i = 0; i < n; i++) { mag_zero(e); for (j = 0; j < n; j++) { if (i == j) { arb_sub_ui(t, arb_mat_entry(A, i, j), 1, MAG_BITS); arb_get_mag(f, t); } else { arb_get_mag(f, arb_mat_entry(A, i, j)); } mag_add(e, e, f); } mag_max(r, r, e); } /* (1 + eps)^n - 1 <= expm1(n*eps) */ mag_mul_ui(r, r, n); mag_expm1(r, r); arf_one(arb_midref(det)); mag_set(arb_radref(det), r); arb_clear(t); mag_clear(r); mag_clear(e); mag_clear(f); } void arb_mat_det_precond(arb_t det, const arb_mat_t A, slong prec) { arb_mat_t LU, Linv, Uinv; arb_t detU; slong n; slong *P; n = arb_mat_nrows(A); if (n == 0) { arb_one(det); return; } P = _perm_init(n); arb_mat_init(LU, n, n); if (!arb_mat_approx_lu(P, LU, A, prec)) { /* Fallback. */ arb_mat_det_lu(det, A, prec); } else { arb_mat_init(Linv, n, n); arb_mat_init(Uinv, n, n); arb_init(detU); arb_mat_one(Linv); arb_mat_approx_solve_tril(Linv, LU, Linv, 1, prec); arb_mat_one(Uinv); arb_mat_approx_solve_triu(Uinv, LU, Uinv, 0, prec); arb_mat_diag_prod(detU, Uinv, prec); arb_mat_mul(LU, A, Uinv, prec); _apply_permutation(LU, P, n); arb_mat_mul(Uinv, Linv, LU, prec); arb_mat_det_one_gershgorin(det, Uinv); if (_perm_parity(P, n)) arb_neg(det, det); arb_div(det, det, detU, prec); if (arb_contains_zero(det)) { /* Run the interval LU algorithm. This can give a much better bound if the Gaussian elimination manages to work through several rows, and it is not that expensive. */ arb_mat_det_lu(detU, A, prec); if (mag_cmp(arb_radref(detU), arb_radref(det)) < 0) arb_set(det, detU); } arb_mat_clear(Linv); arb_mat_clear(Uinv); arb_clear(detU); } _perm_clear(P); arb_mat_clear(LU); } flint-3.1.3/src/arb_mat/diag_prod.c000066400000000000000000000024621461254215100171270ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void _arb_mat_diag_prod(arb_t res, const arb_mat_t A, slong a, slong b, slong prec) { if (b - a == 0) { arb_one(res); } else if (b - a == 1) { arb_set_round(res, arb_mat_entry(A, a, a), prec); } else { slong i; arb_mul(res, arb_mat_entry(A, a, a), arb_mat_entry(A, a + 1, a + 1), prec); for (i = a + 2; i < b; i++) arb_mul(res, res, arb_mat_entry(A, i, i), prec); /* no advantage? */ /* arb_t t; arb_init(t); _arb_mat_diag_prod(t, A, a, a + (b - a) / 2, prec); _arb_mat_diag_prod(res, A, a + (b - a) / 2, b, prec); arb_mul(res, res, t, prec); arb_clear(t); */ } } void arb_mat_diag_prod(arb_t res, const arb_mat_t A, slong prec) { slong m, n; m = arb_mat_nrows(A); n = arb_mat_nrows(A); _arb_mat_diag_prod(res, A, 0, FLINT_MIN(m, n), prec); } flint-3.1.3/src/arb_mat/entrywise_is_zero.c000066400000000000000000000014371461254215100207630ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "arb_mat.h" void _arb_mat_entrywise_is_zero(fmpz_mat_t dest, const arb_mat_t src) { slong i, j; fmpz_mat_zero(dest); for (i = 0; i < arb_mat_nrows(src); i++) { for (j = 0; j < arb_mat_ncols(src); j++) { if (arb_is_zero(arb_mat_entry(src, i, j))) { fmpz_one(fmpz_mat_entry(dest, i, j)); } } } } flint-3.1.3/src/arb_mat/entrywise_not_is_zero.c000066400000000000000000000014431461254215100216400ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "arb_mat.h" void arb_mat_entrywise_not_is_zero(fmpz_mat_t dest, const arb_mat_t src) { slong i, j; fmpz_mat_zero(dest); for (i = 0; i < arb_mat_nrows(src); i++) { for (j = 0; j < arb_mat_ncols(src); j++) { if (!arb_is_zero(arb_mat_entry(src, i, j))) { fmpz_one(fmpz_mat_entry(dest, i, j)); } } } } flint-3.1.3/src/arb_mat/eq.c000066400000000000000000000015121461254215100155770ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_eq(const arb_mat_t mat1, const arb_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 0; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (!arb_eq(arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/equal.c000066400000000000000000000015241461254215100163040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_equal(const arb_mat_t mat1, const arb_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 0; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (!arb_equal(arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/exp.c000066400000000000000000000115551461254215100157760ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz_mat.h" #include "bool_mat.h" #include "arb_mat.h" #define LOG2_OVER_E 0.25499459743395350926 slong _arb_mat_exp_choose_N(const mag_t norm, slong prec) { if (mag_is_special(norm) || mag_cmp_2exp_si(norm, 30) > 0) { return 1; } else if (mag_cmp_2exp_si(norm, -prec) < 0) { return 2; } else if (mag_cmp_2exp_si(norm, -300) < 0) { slong N = -MAG_EXP(norm); return (prec + N - 1) / N; } else { double c, t; c = mag_get_d(norm); t = d_lambertw(prec * LOG2_OVER_E / c); t = c * exp(t + 1.0); return FLINT_MIN((slong) (t + 1.0), 2 * prec); } } static void _arb_mat_exp_diagonal(arb_mat_t B, const arb_mat_t A, slong prec) { slong n, i; n = arb_mat_nrows(A); if (B != A) { arb_mat_zero(B); } for (i = 0; i < n; i++) { arb_exp(arb_mat_entry(B, i, i), arb_mat_entry(A, i, i), prec); } } void arb_mat_exp(arb_mat_t B, const arb_mat_t A, slong prec) { slong i, j, dim, nz; bool_mat_t S; slong nildegree; if (!arb_mat_is_square(A)) { flint_throw(FLINT_ERROR, "arb_mat_exp: a square matrix is required!\n"); } if (arb_mat_is_empty(A)) return; dim = arb_mat_nrows(A); if (dim == 1) { arb_exp(arb_mat_entry(B, 0, 0), arb_mat_entry(A, 0, 0), prec); return; } nz = arb_mat_count_is_zero(A); if (nz == dim * dim) { arb_mat_one(B); return; } bool_mat_init(S, dim, dim); if (nz == 0) { nildegree = -1; bool_mat_complement(S, S); } else { for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) bool_mat_set_entry(S, i, j, !arb_is_zero(arb_mat_entry(A, i, j))); if (bool_mat_is_diagonal(S)) { _arb_mat_exp_diagonal(B, A, prec); bool_mat_clear(S); return; } else { nildegree = bool_mat_nilpotency_degree(S); } } /* evaluate using scaling and squaring of truncated taylor series */ { slong wp, N, q, r; mag_t norm, err; arb_mat_t T; wp = prec + 3 * FLINT_BIT_COUNT(prec); mag_init(norm); mag_init(err); arb_mat_init(T, dim, dim); arb_mat_bound_inf_norm(norm, A); q = pow(wp, 0.25); /* wanted magnitude */ if (mag_cmp_2exp_si(norm, 2 * wp) > 0) /* too big */ r = 2 * wp; else if (mag_cmp_2exp_si(norm, -q) < 0) /* tiny, no need to reduce */ r = 0; else r = FLINT_MAX(0, q + MAG_EXP(norm)); /* reduce to magnitude 2^(-r) */ arb_mat_scalar_mul_2exp_si(T, A, -r); mag_mul_2exp_si(norm, norm, -r); N = _arb_mat_exp_choose_N(norm, wp); if (N < 1) flint_throw(FLINT_ERROR, "(%s): N < 1", __func__); /* if positive, nildegree is an upper bound on nilpotency degree */ if (nildegree > 0) N = FLINT_MIN(N, nildegree); mag_exp_tail(err, norm, N); arb_mat_exp_taylor_sum(B, T, N, wp); /* add truncation error to entries for which it is not ruled out */ if (nz == 0) { for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) arb_add_error_mag(arb_mat_entry(B, i, j), err); } else if (nildegree < 0 || N < nildegree) { slong w; fmpz_mat_t W; fmpz_mat_init(W, dim, dim); w = bool_mat_all_pairs_longest_walk(W, S); if (w + 1 != nildegree) flint_throw(FLINT_ERROR, "(%s): w + 1 != nildegree", __func__); for (i = 0; i < dim; i++) { for (j = 0; j < dim; j++) { slong d = fmpz_get_si(fmpz_mat_entry(W, i, j)) + 1; if (d < 0 || N < d) { arb_add_error_mag(arb_mat_entry(B, i, j), err); } } } fmpz_mat_clear(W); } for (i = 0; i < r; i++) { arb_mat_sqr(T, B, wp); arb_mat_swap(T, B); } for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) arb_set_round(arb_mat_entry(B, i, j), arb_mat_entry(B, i, j), prec); mag_clear(norm); mag_clear(err); arb_mat_clear(T); } bool_mat_clear(S); } flint-3.1.3/src/arb_mat/exp_taylor_sum.c000066400000000000000000000054101461254215100202450ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb_mat.h" void arb_mat_exp_taylor_sum(arb_mat_t S, const arb_mat_t A, slong N, slong prec) { if (A == S) { arb_mat_t t; arb_mat_init(t, arb_mat_nrows(A), arb_mat_nrows(A)); arb_mat_set(t, A); arb_mat_exp_taylor_sum(S, t, N, prec); arb_mat_clear(t); } else if (N <= 0) { arb_mat_zero(S); } else if (N == 1) { arb_mat_one(S); } else if (N == 2) { arb_mat_one(S); arb_mat_add(S, S, A, prec); } else if (N == 3) { arb_mat_t T; arb_mat_init(T, arb_mat_nrows(A), arb_mat_nrows(A)); arb_mat_sqr(T, A, prec); arb_mat_scalar_mul_2exp_si(T, T, -1); arb_mat_add(S, A, T, prec); arb_mat_one(T); arb_mat_add(S, S, T, prec); arb_mat_clear(T); } else { slong i, lo, hi, m, w, dim; arb_mat_struct * pows; arb_mat_t T, U; fmpz_t c, f; dim = arb_mat_nrows(A); m = n_sqrt(N); w = (N + m - 1) / m; fmpz_init(c); fmpz_init(f); pows = flint_malloc(sizeof(arb_mat_t) * (m + 1)); arb_mat_init(T, dim, dim); arb_mat_init(U, dim, dim); for (i = 0; i <= m; i++) { arb_mat_init(pows + i, dim, dim); if (i == 0) arb_mat_one(pows + i); else if (i == 1) arb_mat_set(pows + i, A); else arb_mat_mul(pows + i, pows + i - 1, A, prec); } arb_mat_zero(S); fmpz_one(f); for (i = w - 1; i >= 0; i--) { lo = i * m; hi = FLINT_MIN(N - 1, lo + m - 1); arb_mat_zero(T); fmpz_one(c); while (hi >= lo) { arb_mat_scalar_addmul_fmpz(T, pows + hi - lo, c, prec); if (hi != 0) fmpz_mul_ui(c, c, hi); hi--; } arb_mat_mul(U, pows + m, S, prec); arb_mat_scalar_mul_fmpz(S, T, f, prec); arb_mat_add(S, S, U, prec); fmpz_mul(f, f, c); } arb_mat_scalar_div_fmpz(S, S, f, prec); fmpz_clear(c); fmpz_clear(f); for (i = 0; i <= m; i++) arb_mat_clear(pows + i); flint_free(pows); arb_mat_clear(T); arb_mat_clear(U); } } flint-3.1.3/src/arb_mat/find_pivot_partial.c000066400000000000000000000021121461254215100210440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" slong arb_mat_find_pivot_partial(const arb_mat_t mat, slong start_row, slong end_row, slong c) { slong best_row, i; best_row = -1; for (i = start_row; i < end_row; i++) { if (!arb_contains_zero(arb_mat_entry(mat, i, c))) { if (best_row == -1) { best_row = i; } /* todo: should take the radius into account */ else if (arf_cmpabs(arb_midref(arb_mat_entry(mat, i, c)), arb_midref(arb_mat_entry(mat, best_row, c))) > 0) { best_row = i; } } } return best_row; } flint-3.1.3/src/arb_mat/frobenius_norm.c000066400000000000000000000014761461254215100202320ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_frobenius_norm(arb_t res, const arb_mat_t A, slong prec) { slong i, j, r, c; r = arb_mat_nrows(A); c = arb_mat_ncols(A); arb_zero(res); if (r == 0 || c == 0) return; for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { arb_srcptr x = arb_mat_entry(A, i, j); arb_addmul(res, x, x, prec); } } arb_sqrtpos(res, res, prec); } flint-3.1.3/src/arb_mat/hilbert.c000066400000000000000000000014211461254215100166220ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_hilbert(arb_mat_t mat, slong prec) { slong R, C, i, j; R = arb_mat_nrows(mat); C = arb_mat_ncols(mat); for (i = 0; i < R; i++) { for (j = 0; j < C; j++) { arb_one(arb_mat_entry(mat, i, j)); arb_div_ui(arb_mat_entry(mat, i, j), arb_mat_entry(mat, i, j), i + j + 1, prec); } } } flint-3.1.3/src/arb_mat/indeterminate.c000066400000000000000000000011431461254215100200220ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_indeterminate(arb_mat_t A) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) arb_indeterminate(arb_mat_entry(A, i, j)); } flint-3.1.3/src/arb_mat/init.c000066400000000000000000000014151461254215100161370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_init(arb_mat_t mat, slong r, slong c) { if (r != 0 && c != 0) { slong i; mat->entries = _arb_vec_init(r * c); mat->rows = (arb_ptr *) flint_malloc(r * sizeof(arb_ptr)); for (i = 0; i < r; i++) mat->rows[i] = mat->entries + i * c; } else mat->entries = NULL; mat->r = r; mat->c = c; } flint-3.1.3/src/arb_mat/inlines.c000066400000000000000000000006561461254215100166430ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ARB_MAT_INLINES_C #include "arb_mat.h" flint-3.1.3/src/arb_mat/inv.c000066400000000000000000000013751461254215100157750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_inv(arb_mat_t X, const arb_mat_t A, slong prec) { if (X == A) { int r; arb_mat_t T; arb_mat_init(T, arb_mat_nrows(A), arb_mat_ncols(A)); r = arb_mat_inv(T, A, prec); arb_mat_swap(T, X); arb_mat_clear(T); return r; } arb_mat_one(X); return arb_mat_solve(X, A, X, prec); } flint-3.1.3/src/arb_mat/inv_cho_precomp.c000066400000000000000000000044461461254215100203550ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" static void _arb_sqr(arb_t dest, const arb_t src, slong prec) { arb_mul(dest, src, src, prec); } void arb_mat_inv_cho_precomp(arb_mat_t X, const arb_mat_t L, slong prec) { slong n; if (arb_mat_nrows(X) != arb_mat_nrows(L) || arb_mat_ncols(X) != arb_mat_ncols(L)) { flint_throw(FLINT_ERROR, "arb_mat_inv_cho_precomp: incompatible dimensions\n"); } if (arb_mat_is_empty(L)) return; n = arb_mat_nrows(L); if (n == 1) { arb_inv(arb_mat_entry(X, 0, 0), arb_mat_entry(L, 0, 0), prec); _arb_sqr(arb_mat_entry(X, 0, 0), arb_mat_entry(X, 0, 0), prec); return; } if (X == L) { flint_throw(FLINT_ERROR, "arb_mat_inv_cho_precomp: unsupported aliasing\n"); } /* invert a 2x2 or larger matrix given its L * L^T decomposition */ { slong i, j, k; arb_struct *s; arb_mat_zero(X); s = _arb_vec_init(n); for (i = 0; i < n; i++) { arb_inv(s + i, arb_mat_entry(L, i, i), prec); } for (j = n-1; j >= 0; j--) { for (i = j; i >= 0; i--) { if (i == j) { arb_set(arb_mat_entry(X, i, j), s + i); } else { arb_zero(arb_mat_entry(X, i, j)); } for (k = i + 1; k < n; k++) { arb_submul(arb_mat_entry(X, i, j), arb_mat_entry(L, k, i), arb_mat_entry(X, k, j), prec); } arb_div(arb_mat_entry(X, i, j), arb_mat_entry(X, i, j), arb_mat_entry(L, i, i), prec); arb_set(arb_mat_entry(X, j, i), arb_mat_entry(X, i, j)); } } _arb_vec_clear(s, n); } } flint-3.1.3/src/arb_mat/inv_ldl_precomp.c000066400000000000000000000037471461254215100203620ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_inv_ldl_precomp(arb_mat_t X, const arb_mat_t L, slong prec) { slong n; if (arb_mat_nrows(X) != arb_mat_nrows(L) || arb_mat_ncols(X) != arb_mat_ncols(L)) { flint_throw(FLINT_ERROR, "arb_mat_inv_ldl_precomp: incompatible dimensions\n"); } if (arb_mat_is_empty(L)) return; n = arb_mat_nrows(L); if (n == 1) { arb_inv(arb_mat_entry(X, 0, 0), arb_mat_entry(L, 0, 0), prec); return; } if (X == L) { flint_throw(FLINT_ERROR, "arb_mat_inv_ldl_precomp: unsupported aliasing\n"); } /* invert a 2x2 or larger matrix given its L * D * L^T decomposition */ { slong i, j, k; arb_struct *s; s = _arb_vec_init(n); for (i = 0; i < n; i++) { arb_inv(s + i, arb_mat_entry(L, i, i), prec); } arb_mat_zero(X); for (j = n-1; j >= 0; j--) { for (i = j; i >= 0; i--) { if (i == j) { arb_set(arb_mat_entry(X, i, j), s + i); } else { arb_zero(arb_mat_entry(X, i, j)); } for (k = i + 1; k < n; k++) { arb_submul(arb_mat_entry(X, i, j), arb_mat_entry(L, k, i), arb_mat_entry(X, k, j), prec); } arb_set(arb_mat_entry(X, j, i), arb_mat_entry(X, i, j)); } } _arb_vec_clear(s, n); } } flint-3.1.3/src/arb_mat/io.c000066400000000000000000000020701461254215100156010ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb_mat.h" /* printing *******************************************************************/ void arb_mat_fprintd(FILE * file, const arb_mat_t mat, slong digits) { slong i, j; for (i = 0; i < arb_mat_nrows(mat); i++) { flint_fprintf(file, "["); for (j = 0; j < arb_mat_ncols(mat); j++) { arb_fprintd(file, arb_mat_entry(mat, i, j), digits); if (j < arb_mat_ncols(mat) - 1) flint_fprintf(file, ", "); } flint_fprintf(file, "]\n"); } } void arb_mat_printd(const arb_mat_t mat, slong digits) { arb_mat_fprintd(stdout, mat, digits); } flint-3.1.3/src/arb_mat/is_exact.c000066400000000000000000000012271461254215100167740ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_is_exact(const arb_mat_t A) { slong i, j; for (i = 0; i < arb_mat_nrows(A); i++) for (j = 0; j < arb_mat_ncols(A); j++) if (!mag_is_zero(arb_radref(arb_mat_entry(A, i, j)))) return 0; return 1; } flint-3.1.3/src/arb_mat/is_finite.c000066400000000000000000000012531461254215100171450ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_is_finite(const arb_mat_t A) { slong i, j, n, m; n = arb_mat_nrows(A); m = arb_mat_ncols(A); for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (!arb_is_finite(arb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/is_tril.c000066400000000000000000000012531461254215100166410ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_is_tril(const arb_mat_t A) { slong i, j, n, m; n = arb_mat_nrows(A); m = arb_mat_ncols(A); for (i = 0; i < n; i++) for (j = i + 1; j < m; j++) if (!arb_is_zero(arb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/is_triu.c000066400000000000000000000012651461254215100166550ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_is_triu(const arb_mat_t A) { slong i, j, n, m; n = arb_mat_nrows(A); m = arb_mat_ncols(A); for (i = 1; i < n; i++) for (j = 0; j < FLINT_MIN(i, m); j++) if (!arb_is_zero(arb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/is_zero.c000066400000000000000000000012471461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_is_zero(const arb_mat_t A) { slong i, j, n, m; n = arb_mat_nrows(A); m = arb_mat_ncols(A); for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (!arb_is_zero(arb_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/ldl.c000066400000000000000000000067151461254215100157570ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" static void _arb_sqr(arb_t dest, const arb_t src, slong prec) { arb_mul(dest, src, src, prec); } int _arb_mat_ldl_inplace(arb_mat_t A, slong prec) { slong n, i, j, k; arb_t tmp; int result; n = arb_mat_nrows(A); arb_init(tmp); result = 1; for (i = 0; i < n && result; i++) { for (j = 0; j < i; j++) { for (k = 0; k < j; k++) { arb_mul(tmp, arb_mat_entry(A, i, k), arb_mat_entry(A, j, k), prec); arb_submul(arb_mat_entry(A, i, j), arb_mat_entry(A, k, k), tmp, prec); } arb_div(arb_mat_entry(A, i, j), arb_mat_entry(A, i, j), arb_mat_entry(A, j, j), prec); } for (k = 0; k < i; k++) { _arb_sqr(tmp, arb_mat_entry(A, i, k), prec); arb_submul(arb_mat_entry(A, i, i), arb_mat_entry(A, k, k), tmp, prec); } if (!arb_is_positive(arb_mat_entry(A, i, i))) result = 0; } arb_clear(tmp); return result; } int _arb_mat_ldl_golub_and_van_loan(arb_mat_t A, slong prec) { slong n, i, j, k; arb_struct *v; int result; n = arb_mat_nrows(A); v = _arb_vec_init(n); result = 1; for (j = 0; j < n; j++) { for (i = 0; i < j; i++) { arb_mul(v + i, arb_mat_entry(A, j, i), arb_mat_entry(A, i, i), prec); } arb_set(v + j, arb_mat_entry(A, j, j)); for (i = 0; i < j; i++) { arb_submul(v + j, arb_mat_entry(A, j, i), v + i, prec); } if (!arb_is_positive(v + j)) { result = 0; break; } arb_set(arb_mat_entry(A, j, j), v + j); for (i = j + 1; i < n; i++) { for (k = 0; k < j; k++) { arb_submul(arb_mat_entry(A, i, j), arb_mat_entry(A, i, k), v + k, prec); } arb_div(arb_mat_entry(A, i, j), arb_mat_entry(A, i, j), v + j, prec); } } _arb_vec_clear(v, n); return result; } int arb_mat_ldl(arb_mat_t L, const arb_mat_t A, slong prec) { slong n; int result; if (!arb_mat_is_square(A)) { flint_throw(FLINT_ERROR, "arb_mat_ldl: a square matrix is required\n"); } if (arb_mat_nrows(L) != arb_mat_nrows(A) || arb_mat_ncols(L) != arb_mat_ncols(A)) { flint_throw(FLINT_ERROR, "arb_mat_ldl: incompatible dimensions\n"); } if (arb_mat_is_empty(A)) return 1; n = arb_mat_nrows(A); arb_mat_set(L, A); if (n == 1) return arb_is_positive(arb_mat_entry(L, 0, 0)); result = _arb_mat_ldl_golub_and_van_loan(L, prec); /* set the strictly upper triangular region of L to zero */ { slong i, j; for (i = 0; i < n; i++) for (j = i+1; j < n; j++) arb_zero(arb_mat_entry(L, i, j)); } return result; } flint-3.1.3/src/arb_mat/lu.c000066400000000000000000000012111461254215100156060ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_lu(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec) { if (arb_mat_nrows(A) < 8 || arb_mat_ncols(A) < 8) return arb_mat_lu_classical(P, LU, A, prec); else return arb_mat_lu_recursive(P, LU, A, prec); } flint-3.1.3/src/arb_mat/lu_classical.c000066400000000000000000000027541461254215100176410ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_lu_classical(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec) { arb_t d, e; arb_ptr * a; slong i, j, m, n, r, row, col; int result; if (arb_mat_is_empty(A)) return 1; m = arb_mat_nrows(A); n = arb_mat_ncols(A); arb_mat_set(LU, A); a = LU->rows; row = col = 0; for (i = 0; i < m; i++) P[i] = i; arb_init(d); arb_init(e); result = 1; while (row < m && col < n) { r = arb_mat_find_pivot_partial(LU, row, m, col); if (r == -1) { result = 0; break; } else if (r != row) arb_mat_swap_rows(LU, P, row, r); arb_set(d, a[row] + col); for (j = row + 1; j < m; j++) { arb_div(e, a[j] + col, d, prec); arb_neg(e, e); _arb_vec_scalar_addmul(a[j] + col, a[row] + col, n - col, e, prec); arb_zero(a[j] + col); arb_neg(a[j] + row, e); } row++; col++; } arb_clear(d); arb_clear(e); return result; } flint-3.1.3/src/arb_mat/lu_recursive.c000066400000000000000000000051411461254215100177030ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" static void _apply_permutation(slong * AP, arb_mat_t A, slong * P, slong n, slong offset) { if (n != 0) { arb_ptr * Atmp; slong * APtmp; slong i; Atmp = flint_malloc(sizeof(arb_ptr) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } int arb_mat_lu_recursive(slong * P, arb_mat_t LU, const arb_mat_t A, slong prec) { slong i, m, n, r1, r2, n1; arb_mat_t A0, A1, A00, A01, A10, A11; slong * P1; m = A->r; n = A->c; if (m <= 1 || n <= 1) { return arb_mat_lu_classical(P, LU, A, prec); } if (LU != A) arb_mat_set(LU, A); n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; P1 = flint_malloc(sizeof(slong) * m); arb_mat_window_init(A0, LU, 0, 0, m, n1); arb_mat_window_init(A1, LU, 0, n1, m, n); r1 = arb_mat_lu(P1, A0, A0, prec); if (!r1) { flint_free(P1); arb_mat_window_clear(A0); arb_mat_window_clear(A1); return 0; } /* r1 = rank of A0 */ r1 = FLINT_MIN(m, n1); _apply_permutation(P, LU, P1, m, 0); arb_mat_window_init(A00, LU, 0, 0, r1, r1); arb_mat_window_init(A10, LU, r1, 0, m, r1); arb_mat_window_init(A01, LU, 0, n1, r1, n); arb_mat_window_init(A11, LU, r1, n1, m, n); arb_mat_solve_tril(A01, A00, A01, 1, prec); { /* arb_mat_submul(A11, A11, A10, A01, prec); */ arb_mat_t T; arb_mat_init(T, A10->r, A01->c); arb_mat_mul(T, A10, A01, prec); arb_mat_sub(A11, A11, T, prec); arb_mat_clear(T); } r2 = arb_mat_lu(P1, A11, A11, prec); if (!r2) r1 = r2 = 0; else _apply_permutation(P, LU, P1, m - r1, r1); flint_free(P1); arb_mat_window_clear(A00); arb_mat_window_clear(A01); arb_mat_window_clear(A10); arb_mat_window_clear(A11); arb_mat_window_clear(A0); arb_mat_window_clear(A1); return r1 && r2; } flint-3.1.3/src/arb_mat/mul.c000066400000000000000000000023171461254215100157730ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_mul(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) { slong cutoff; /* todo: detect small-integer matrices */ if (prec <= 2 * FLINT_BITS) cutoff = 60; else if (prec <= 8 * FLINT_BITS) cutoff = 50; else cutoff = 40; if (arb_mat_nrows(A) <= cutoff || arb_mat_ncols(A) <= cutoff || arb_mat_ncols(B) <= cutoff) { if (flint_get_num_threads() > 1 && ((double) arb_mat_nrows(A) * (double) arb_mat_nrows(B) * (double) arb_mat_ncols(B) * (double) prec > 100000)) { arb_mat_mul_threaded(C, A, B, prec); } else { arb_mat_mul_classical(C, A, B, prec); } } else { arb_mat_mul_block(C, A, B, prec); } } flint-3.1.3/src/arb_mat/mul_block.c000066400000000000000000000400021461254215100171360ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "arb_mat.h" int arb_mat_is_lagom(const arb_mat_t A) { slong i, j, M, N; M = arb_mat_nrows(A); N = arb_mat_ncols(A); for (i = 0; i < M; i++) { for (j = 0; j < N; j++) { if (!ARB_IS_LAGOM(arb_mat_entry(A, i, j))) return 0; } } return 1; } /* allow changing this from the test code */ FLINT_DLL slong arb_mat_mul_block_min_block_size = 0; void arb_mat_mid_addmul_block_fallback(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong block_start, slong block_end, slong prec) { slong M, P, n; slong i, j; arb_ptr tmpA, tmpB; M = arb_mat_nrows(A); P = arb_mat_ncols(B); n = block_end - block_start; tmpA = flint_malloc(sizeof(arb_struct) * (M * n + P * n)); tmpB = tmpA + M * n; for (i = 0; i < M; i++) { for (j = 0; j < n; j++) { *arb_midref(tmpA + i * n + j) = *arb_midref(arb_mat_entry(A, i, block_start + j)); mag_init(arb_radref(tmpA + i * n + j)); } } for (i = 0; i < P; i++) { for (j = 0; j < n; j++) { *arb_midref(tmpB + i * n + j) = *arb_midref(arb_mat_entry(B, block_start + j, i)); mag_init(arb_radref(tmpB + i * n + j)); } } for (i = 0; i < M; i++) { for (j = 0; j < P; j++) { arb_dot(arb_mat_entry(C, i, j), (block_start == 0) ? NULL : arb_mat_entry(C, i, j), 0, tmpA + i * n, 1, tmpB + j * n, 1, n, prec); } } flint_free(tmpA); } void arb_mat_mid_addmul_block_prescaled(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong block_start, slong block_end, const slong * A_min, /* A per-row bottom exponent */ const slong * B_min, /* B per-row bottom exponent */ slong prec) { slong M, P, n; slong i, j; slong M0, M1, P0, P1, Mstep, Pstep; int inexact; /* flint_printf("block mul from %wd to %wd\n", block_start, block_end); */ M = arb_mat_nrows(A); P = arb_mat_ncols(B); n = block_end - block_start; /* Create sub-blocks to keep matrices nearly square. Necessary? */ #if 1 Mstep = (M < 2 * n) ? M : n; Pstep = (P < 2 * n) ? P : n; #else Mstep = M; Pstep = P; #endif for (M0 = 0; M0 < M; M0 += Mstep) { for (P0 = 0; P0 < P; P0 += Pstep) { fmpz_mat_t AA, BB, CC; arb_t t; fmpz_t e; M1 = FLINT_MIN(M0 + Mstep, M); P1 = FLINT_MIN(P0 + Pstep, P); fmpz_mat_init(AA, M1 - M0, n); fmpz_mat_init(BB, n, P1 - P0); fmpz_mat_init(CC, M1 - M0, P1 - P0); /* Convert to fixed-point matrices. */ for (i = M0; i < M1; i++) { if (A_min[i] == WORD_MIN) /* only zeros in this row */ continue; for (j = 0; j < n; j++) { inexact = arf_get_fmpz_fixed_si(fmpz_mat_entry(AA, i - M0, j), arb_midref(arb_mat_entry(A, i, block_start + j)), A_min[i]); if (inexact) { flint_throw(FLINT_ERROR, "matrix multiplication: bad exponent!\n"); } } } for (i = P0; i < P1; i++) { if (B_min[i] == WORD_MIN) /* only zeros in this column */ continue; for (j = 0; j < n; j++) { inexact = arf_get_fmpz_fixed_si(fmpz_mat_entry(BB, j, i - P0), arb_midref(arb_mat_entry(B, block_start + j, i)), B_min[i]); if (inexact) { flint_throw(FLINT_ERROR, "matrix multiplication: bad exponent!\n"); } } } /* The main multiplication */ fmpz_mat_mul(CC, AA, BB); /* flint_printf("bits %wd %wd %wd\n", fmpz_mat_max_bits(CC), fmpz_mat_max_bits(AA), fmpz_mat_max_bits(BB)); */ fmpz_mat_clear(AA); fmpz_mat_clear(BB); arb_init(t); /* Add to the result matrix */ for (i = M0; i < M1; i++) { for (j = P0; j < P1; j++) { *e = A_min[i] + B_min[j]; /* The first time we write this Cij */ if (block_start == 0) { arb_set_round_fmpz_2exp(arb_mat_entry(C, i, j), fmpz_mat_entry(CC, i - M0, j - P0), e, prec); } else { arb_set_round_fmpz_2exp(t, fmpz_mat_entry(CC, i - M0, j - P0), e, prec); arb_add(arb_mat_entry(C, i, j), arb_mat_entry(C, i, j), t, prec); } } } arb_clear(t); fmpz_mat_clear(CC); } } } /* todo: squaring optimizations */ void arb_mat_mul_block(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) { slong M, N, P; slong *A_min, *A_max, *B_min, *B_max; short *A_bits, *B_bits; slong *A_bot, *B_bot; slong block_start, block_end, i, j, bot, top, max_height; slong b, A_max_bits, B_max_bits; slong min_block_size; arb_srcptr t; int A_exact, B_exact; double A_density, B_density; M = arb_mat_nrows(A); N = arb_mat_ncols(A); P = arb_mat_ncols(B); if (N != arb_mat_nrows(B) || M != arb_mat_nrows(C) || P != arb_mat_ncols(C)) { flint_throw(FLINT_ERROR, "arb_mat_mul_block: incompatible dimensions\n"); } if (M == 0 || N == 0 || P == 0 || arb_mat_is_zero(A) || arb_mat_is_zero(B)) { arb_mat_zero(C); return; } if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, M, P); arb_mat_mul_block(T, A, B, prec); arb_mat_swap_entrywise(T, C); arb_mat_clear(T); return; } /* We assume everywhere below that exponents cannot overflow/underflow the small fmpz value range. */ if (!arb_mat_is_lagom(A) || !arb_mat_is_lagom(B)) { arb_mat_mul_classical(C, A, B, prec); return; } /* bottom exponents of A */ A_bot = flint_malloc(sizeof(slong) * M * N); /* minimum bottom exponent in current row */ A_min = flint_malloc(sizeof(slong) * M); /* maximum top exponent in current row */ A_max = flint_malloc(sizeof(slong) * M); B_bot = flint_malloc(sizeof(slong) * N * P); B_min = flint_malloc(sizeof(slong) * P); B_max = flint_malloc(sizeof(slong) * P); /* save space using shorts to store the bit sizes temporarily; the block algorithm will not be used at extremely high precision */ A_bits = flint_malloc(sizeof(short) * M * N); B_bits = flint_malloc(sizeof(short) * N * P); A_exact = B_exact = 1; A_max_bits = B_max_bits = 0; A_density = B_density = 0; /* Build table of bottom exponents (WORD_MIN signifies a zero), and also collect some statistics. */ for (i = 0; i < M; i++) { for (j = 0; j < N; j++) { t = arb_mat_entry(A, i, j); if (arf_is_zero(arb_midref(t))) { A_bot[i * N + j] = WORD_MIN; A_bits[i * N + j] = 0; } else { b = arf_bits(arb_midref(t)); A_bot[i * N + j] = ARF_EXP(arb_midref(t)) - b; A_bits[i * N + j] = b; A_max_bits = FLINT_MAX(A_max_bits, b); A_density++; } A_exact = A_exact && mag_is_zero(arb_radref(t)); } } for (i = 0; i < N; i++) { for (j = 0; j < P; j++) { t = arb_mat_entry(B, i, j); if (arf_is_zero(arb_midref(t))) { B_bot[i * P + j] = WORD_MIN; B_bits[i * P + j] = 0; } else { b = arf_bits(arb_midref(t)); B_bot[i * P + j] = ARF_EXP(arb_midref(t)) - b; B_bits[i * P + j] = b; B_max_bits = FLINT_MAX(B_max_bits, b); B_density++; } B_exact = B_exact && mag_is_zero(arb_radref(t)); } } A_density = A_density / (M * N); B_density = B_density / (N * P); /* Don't shift too far when creating integer block matrices. */ max_height = 1.25 * FLINT_MIN(prec, FLINT_MAX(A_max_bits, B_max_bits)) + 192; /* Avoid block algorithm for extremely high-precision matrices? */ /* Warning: these cutoffs are completely bogus... */ if (A_max_bits > 8000 || B_max_bits > 8000 || (A_density < 0.1 && B_density < 0.1 && max_height > 1024)) { flint_free(A_bot); flint_free(A_max); flint_free(A_min); flint_free(B_bot); flint_free(B_max); flint_free(B_min); flint_free(A_bits); flint_free(B_bits); arb_mat_mul_classical(C, A, B, prec); return; } if (arb_mat_mul_block_min_block_size != 0) min_block_size = arb_mat_mul_block_min_block_size; else min_block_size = 30; block_start = 0; while (block_start < N) { /* Find a run of columns of A and rows of B such that the bottom exponents differ by at most max_height. */ block_end = block_start + 1; /* index is exclusive block_end */ /* begin with this column of A and row of B */ for (i = 0; i < M; i++) { A_max[i] = A_min[i] = A_bot[i * N + block_start]; A_max[i] += (slong) A_bits[i * N + block_start]; } for (i = 0; i < P; i++) { B_max[i] = B_min[i] = B_bot[block_start * P + i]; B_max[i] += (slong) B_bits[block_start * P + i]; } while (block_end < N) { double size; /* End block if memory would be excessive. */ /* Necessary? */ /* Should also do initial check above, if C alone is too large. */ size = (block_end - block_start) * M * (double) A_max_bits; size += (block_end - block_start) * P * (double) B_max_bits; size += (M * P) * (double) (A_max_bits + B_max_bits); size /= 8.0; if (size > 2e9) goto blocks_built; /* check if we can extend with column [block_end] of A */ for (i = 0; i < M; i++) { bot = A_bot[i * N + block_end]; /* zeros are irrelevant */ if (bot == WORD_MIN || A_max[i] == WORD_MIN) continue; top = bot + (slong) A_bits[i * N + block_end]; /* jump will be too big */ if (top > A_min[i] + max_height || bot < A_max[i] - max_height) goto blocks_built; } /* check if we can extend with row [block_end] of B */ for (i = 0; i < P; i++) { bot = B_bot[block_end * P + i]; if (bot == WORD_MIN || B_max[i] == WORD_MIN) continue; top = bot + (slong) B_bits[block_end * P + i]; if (top > B_min[i] + max_height || bot < B_max[i] - max_height) goto blocks_built; } /* second pass to update the extreme values */ for (i = 0; i < M; i++) { bot = A_bot[i * N + block_end]; top = bot + (slong) A_bits[i * N + block_end]; if (A_max[i] == WORD_MIN) { A_max[i] = top; A_min[i] = bot; } else if (bot != WORD_MIN) { if (bot < A_min[i]) A_min[i] = bot; if (top > A_max[i]) A_max[i] = top; } } for (i = 0; i < P; i++) { bot = B_bot[block_end * P + i]; top = bot + (slong) B_bits[block_end * P + i]; if (B_max[i] == WORD_MIN) { B_max[i] = top; B_min[i] = bot; } else if (bot != WORD_MIN) { if (bot < B_min[i]) B_min[i] = bot; if (top > B_max[i]) B_max[i] = top; } } block_end++; } blocks_built: if (block_end - block_start < min_block_size) { block_end = FLINT_MIN(N, block_start + min_block_size); arb_mat_mid_addmul_block_fallback(C, A, B, block_start, block_end, prec); } else { arb_mat_mid_addmul_block_prescaled(C, A, B, block_start, block_end, A_min, B_min, prec); } block_start = block_end; } flint_free(A_bot); flint_free(A_max); flint_free(A_min); flint_free(B_bot); flint_free(B_max); flint_free(B_min); flint_free(A_bits); flint_free(B_bits); /* Radius multiplications */ if (!A_exact || !B_exact) { mag_ptr AA, BB; /* Shallow (since exponents are small!) mag_struct matrices represented by linear arrays; B is transposed to improve locality. */ AA = flint_malloc(M * N * sizeof(mag_struct)); BB = flint_malloc(P * N * sizeof(mag_struct)); if (!A_exact && !B_exact) { /* (A+ar)(B+br) = AB + (A+ar)br + ar B = AB + A br + ar (B + br) */ /* A + ar */ for (i = 0; i < M; i++) for (j = 0; j < N; j++) { mag_fast_init_set_arf(AA + i * N + j, arb_midref(arb_mat_entry(A, i, j))); mag_add(AA + i * N + j, AA + i * N + j, arb_radref(arb_mat_entry(A, i, j))); } /* br */ for (i = 0; i < N; i++) for (j = 0; j < P; j++) BB[j * N + i] = *arb_radref(arb_mat_entry(B, i, j)); _arb_mat_addmul_rad_mag_fast(C, AA, BB, M, N, P); /* ar */ for (i = 0; i < M; i++) for (j = 0; j < N; j++) AA[i * N + j] = *arb_radref(arb_mat_entry(A, i, j)); /* B */ for (i = 0; i < N; i++) for (j = 0; j < P; j++) mag_fast_init_set_arf(BB + j * N + i, arb_midref(arb_mat_entry(B, i, j))); _arb_mat_addmul_rad_mag_fast(C, AA, BB, M, N, P); } else if (A_exact) { /* A(B+br) = AB + A br */ for (i = 0; i < M; i++) for (j = 0; j < N; j++) mag_fast_init_set_arf(AA + i * N + j, arb_midref(arb_mat_entry(A, i, j))); for (i = 0; i < N; i++) for (j = 0; j < P; j++) BB[j * N + i] = *arb_radref(arb_mat_entry(B, i, j)); _arb_mat_addmul_rad_mag_fast(C, AA, BB, M, N, P); } else { /* (A+ar)B = AB + ar B */ for (i = 0; i < M; i++) for (j = 0; j < N; j++) AA[i * N + j] = *arb_radref(arb_mat_entry(A, i, j)); for (i = 0; i < N; i++) for (j = 0; j < P; j++) mag_fast_init_set_arf(BB + j * N + i, arb_midref(arb_mat_entry(B, i, j))); _arb_mat_addmul_rad_mag_fast(C, AA, BB, M, N, P); } flint_free(AA); flint_free(BB); } } flint-3.1.3/src/arb_mat/mul_classical.c000066400000000000000000000045261461254215100200150ustar00rootroot00000000000000/* Copyright (C) 2012, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_mul_classical(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) { slong ar, ac, br, bc, i, j, k; if (A == B && (arb_mat_nrows(A) <= 2 || (prec >= 1024 && arb_mat_nrows(A) < 8))) { arb_mat_sqr_classical(C, A, prec); return; } ar = arb_mat_nrows(A); ac = arb_mat_ncols(A); br = arb_mat_nrows(B); bc = arb_mat_ncols(B); if (ac != br || ar != arb_mat_nrows(C) || bc != arb_mat_ncols(C)) { flint_throw(FLINT_ERROR, "arb_mat_mul: incompatible dimensions\n"); } if (br == 0) { arb_mat_zero(C); return; } if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, ar, bc); arb_mat_mul_classical(T, A, B, prec); arb_mat_swap_entrywise(T, C); arb_mat_clear(T); return; } if (br <= 2) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { /* todo: efficient fmma code */ arb_mul(arb_mat_entry(C, i, j), arb_mat_entry(A, i, 0), arb_mat_entry(B, 0, j), prec); for (k = 1; k < br; k++) { arb_addmul(arb_mat_entry(C, i, j), arb_mat_entry(A, i, k), arb_mat_entry(B, k, j), prec); } } } } else { arb_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(sizeof(arb_struct) * br * bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) tmp[j * br + i] = *arb_mat_entry(B, i, j); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { arb_dot(arb_mat_entry(C, i, j), NULL, 0, A->rows[i], 1, tmp + j * br, 1, br, prec); } } TMP_END; } } flint-3.1.3/src/arb_mat/mul_entrywise.c000066400000000000000000000017041461254215100201030ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_mul_entrywise(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) { slong i, j; if (arb_mat_nrows(A) != arb_mat_nrows(B) || arb_mat_ncols(A) != arb_mat_ncols(B)) { flint_throw(FLINT_ERROR, "arb_mat_mul_entrywise: incompatible dimensions\n"); } for (i = 0; i < arb_mat_nrows(A); i++) { for (j = 0; j < arb_mat_ncols(A); j++) { arb_mul(arb_mat_entry(C, i, j), arb_mat_entry(A, i, j), arb_mat_entry(B, i, j), prec); } } } flint-3.1.3/src/arb_mat/mul_threaded.c000066400000000000000000000062141461254215100176330ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "arb_mat.h" typedef struct { arb_ptr * C; const arb_ptr * A; const arb_ptr * B; slong ar0; slong ar1; slong bc0; slong bc1; slong br; slong prec; } _worker_arg; void _arb_mat_mul_thread(void * arg_ptr) { _worker_arg arg = *((_worker_arg *) arg_ptr); slong i, j, br, bc; arb_ptr tmp; TMP_INIT; br = arg.br; bc = arg.bc1 - arg.bc0; TMP_START; tmp = TMP_ALLOC(sizeof(arb_struct) * br * bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) tmp[j * br + i] = arg.B[i][arg.bc0 + j]; for (i = arg.ar0; i < arg.ar1; i++) { for (j = arg.bc0; j < arg.bc1; j++) { arb_dot(arg.C[i] + j, NULL, 0, arg.A[i], 1, tmp + (j - arg.bc0) * br, 1, br, arg.prec); } } TMP_END; flint_cleanup(); return; } void arb_mat_mul_threaded(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, slong prec) { slong ar, ac, br, bc, i, num_threads, num_workers; thread_pool_handle * handles; _worker_arg * args; ar = arb_mat_nrows(A); ac = arb_mat_ncols(A); br = arb_mat_nrows(B); bc = arb_mat_ncols(B); if (ac != br || ar != arb_mat_nrows(C) || bc != arb_mat_ncols(C)) flint_throw(FLINT_DOMERR, "incompatible dimensions in %s\n", __func__); if (br == 0) { arb_mat_zero(C); return; } if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, ar, bc); arb_mat_mul_threaded(T, A, B, prec); arb_mat_swap_entrywise(T, C); arb_mat_clear(T); return; } num_workers = flint_request_threads(&handles, FLINT_MAX(ar, bc)); num_threads = num_workers + 1; args = FLINT_ARRAY_ALLOC(num_threads, _worker_arg); for (i = 0; i < num_threads; i++) { args[i].C = C->rows; args[i].A = A->rows; args[i].B = B->rows; if (ar >= bc) { args[i].ar0 = (ar * i) / num_threads; args[i].ar1 = (ar * (i + 1)) / num_threads; args[i].bc0 = 0; args[i].bc1 = bc; } else { args[i].ar0 = 0; args[i].ar1 = ar; args[i].bc0 = (bc * i) / num_threads; args[i].bc1 = (bc * (i + 1)) / num_threads; } args[i].br = br; args[i].prec = prec; if (i < num_workers) thread_pool_wake(global_thread_pool, handles[i], 0, _arb_mat_mul_thread, &args[i]); else _arb_mat_mul_thread(&args[i]); } for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); flint_free(args); } flint-3.1.3/src/arb_mat/ne.c000066400000000000000000000015111461254215100155730ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_ne(const arb_mat_t mat1, const arb_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 1; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (arb_ne(arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j))) return 1; return 0; } flint-3.1.3/src/arb_mat/neg.c000066400000000000000000000012301461254215100157400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_neg(arb_mat_t dest, const arb_mat_t src) { slong i, j; for (i = 0; i < arb_mat_nrows(src); i++) for (j = 0; j < arb_mat_ncols(src); j++) arb_neg(arb_mat_entry(dest, i, j), arb_mat_entry(src, i, j)); } flint-3.1.3/src/arb_mat/one.c000066400000000000000000000012701461254215100157540ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_one(arb_mat_t mat) { slong i, j; for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) if (i == j) arb_one(arb_mat_entry(mat, i, j)); else arb_zero(arb_mat_entry(mat, i, j)); } flint-3.1.3/src/arb_mat/ones.c000066400000000000000000000011651461254215100161420ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_ones(arb_mat_t mat) { slong R, C, i, j; R = arb_mat_nrows(mat); C = arb_mat_ncols(mat); for (i = 0; i < R; i++) for (j = 0; j < C; j++) arb_one(arb_mat_entry(mat, i, j)); } flint-3.1.3/src/arb_mat/overlaps.c000066400000000000000000000015121461254215100170250ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_overlaps(const arb_mat_t mat1, const arb_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 0; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (!arb_overlaps(arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j))) return 0; return 1; } flint-3.1.3/src/arb_mat/pascal.c000066400000000000000000000011771461254215100164440ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "gr.h" #include "gr_mat.h" void arb_mat_pascal(arb_mat_t mat, int triangular, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); GR_MUST_SUCCEED(gr_mat_pascal((gr_mat_struct *) mat, triangular, ctx)); } flint-3.1.3/src/arb_mat/pow_ui.c000066400000000000000000000026351461254215100165030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_pow_ui(arb_mat_t B, const arb_mat_t A, ulong exp, slong prec) { slong d = arb_mat_nrows(A); if (exp <= 2 || d <= 1) { if (exp == 0 || d == 0) { arb_mat_one(B); } else if (d == 1) { arb_pow_ui(arb_mat_entry(B, 0, 0), arb_mat_entry(A, 0, 0), exp, prec); } else if (exp == 1) { arb_mat_set(B, A); } else if (exp == 2) { arb_mat_sqr(B, A, prec); } } else { arb_mat_t T, U; slong i; arb_mat_init(T, d, d); arb_mat_set(T, A); arb_mat_init(U, d, d); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { arb_mat_sqr(U, T, prec); if (exp & (WORD(1) << i)) arb_mat_mul(T, U, A, prec); else arb_mat_swap(T, U); } arb_mat_swap(B, T); arb_mat_clear(T); arb_mat_clear(U); } } flint-3.1.3/src/arb_mat/randtest.c000066400000000000000000000023221461254215100170160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_randtest(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) { slong i, j, density; density = n_randint(state, 100); if (n_randint(state, 2)) for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) if (n_randint(state, 100) < density) arb_randtest(arb_mat_entry(mat, i, j), state, prec, mag_bits); else arb_zero(arb_mat_entry(mat, i, j)); else for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) if (n_randint(state, 100) < density) arb_randtest_precise(arb_mat_entry(mat, i, j), state, prec, mag_bits); else arb_zero(arb_mat_entry(mat, i, j)); } flint-3.1.3/src/arb_mat/randtest_cho.c000066400000000000000000000014661461254215100176570ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_randtest_cho(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) { slong g = arb_mat_nrows(mat); slong i, j; arb_mat_zero(mat); for (i = 0; i < g; i++) { arb_randtest_positive(arb_mat_entry(mat, i, i), state, prec, mag_bits); for (j = 0; j < i; j++) { arb_randtest_precise(arb_mat_entry(mat, i, j), state, prec, mag_bits); } } } flint-3.1.3/src/arb_mat/randtest_spd.c000066400000000000000000000013211461254215100176620ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_randtest_spd(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) { slong g = arb_mat_nrows(mat); arb_mat_t tp; arb_mat_init(tp, g, g); arb_mat_randtest_cho(mat, state, prec, mag_bits); arb_mat_transpose(tp, mat); arb_mat_mul(mat, mat, tp, prec); arb_mat_clear(tp); } flint-3.1.3/src/arb_mat/set.c000066400000000000000000000013441461254215100157700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_set(arb_mat_t dest, const arb_mat_t src) { slong i, j; if (dest != src && arb_mat_ncols(src) != 0) { for (i = 0; i < arb_mat_nrows(src); i++) for (j = 0; j < arb_mat_ncols(src); j++) arb_set(arb_mat_entry(dest, i, j), arb_mat_entry(src, i, j)); } } flint-3.1.3/src/arb_mat/set_fmpq_mat.c000066400000000000000000000014201461254215100176470ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" #include "arb_mat.h" void arb_mat_set_fmpq_mat(arb_mat_t dest, const fmpq_mat_t src, slong prec) { slong i, j; if (arb_mat_ncols(dest) != 0) { for (i = 0; i < arb_mat_nrows(dest); i++) for (j = 0; j < arb_mat_ncols(dest); j++) arb_set_fmpq(arb_mat_entry(dest, i, j), fmpq_mat_entry(src, i, j), prec); } } flint-3.1.3/src/arb_mat/set_fmpz_mat.c000066400000000000000000000013761461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "arb_mat.h" void arb_mat_set_fmpz_mat(arb_mat_t dest, const fmpz_mat_t src) { slong i, j; if (arb_mat_ncols(dest) != 0) { for (i = 0; i < arb_mat_nrows(dest); i++) for (j = 0; j < arb_mat_ncols(dest); j++) arb_set_fmpz(arb_mat_entry(dest, i, j), fmpz_mat_entry(src, i, j)); } } flint-3.1.3/src/arb_mat/set_round_fmpz_mat.c000066400000000000000000000014301461254215100210700ustar00rootroot00000000000000/* Copyright (C) 2012 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "arb_mat.h" void arb_mat_set_round_fmpz_mat(arb_mat_t dest, const fmpz_mat_t src, slong prec) { slong i, j; if (arb_mat_ncols(dest) != 0) { for (i = 0; i < arb_mat_nrows(dest); i++) for (j = 0; j < arb_mat_ncols(dest); j++) arb_set_round_fmpz(arb_mat_entry(dest, i, j), fmpz_mat_entry(src, i, j), prec); } } flint-3.1.3/src/arb_mat/solve.c000066400000000000000000000012341461254215100163230ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { slong n = arb_mat_nrows(A); if (n <= 4 || prec > 10.0 * n) return arb_mat_solve_lu(X, A, B, prec); else return arb_mat_solve_precond(X, A, B, prec); } flint-3.1.3/src/arb_mat/solve_cho_precomp.c000066400000000000000000000026161461254215100207060ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_solve_cho_precomp(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, slong prec) { slong i, j, c, n, m; n = arb_mat_nrows(X); m = arb_mat_ncols(X); arb_mat_set(X, B); for (c = 0; c < m; c++) { /* solve Ly = b */ for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(L, i, j), arb_mat_entry(X, j, c), prec); } arb_div(arb_mat_entry(X, i, c), arb_mat_entry(X, i, c), arb_mat_entry(L, i, i), prec); } /* solve Ux = y */ for (i = n - 1; i >= 0; i--) { for (j = i + 1; j < n; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(L, j, i), arb_mat_entry(X, j, c), prec); } arb_div(arb_mat_entry(X, i, c), arb_mat_entry(X, i, c), arb_mat_entry(L, i, i), prec); } } } flint-3.1.3/src/arb_mat/solve_ldl_precomp.c000066400000000000000000000026031461254215100207040ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_solve_ldl_precomp(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, slong prec) { slong i, j, c, n, m; n = arb_mat_nrows(X); m = arb_mat_ncols(X); arb_mat_set(X, B); for (c = 0; c < m; c++) { /* solve Lz = b */ for (i = 1; i < n; i++) { for (j = 0; j < i; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(L, i, j), arb_mat_entry(X, j, c), prec); } } /* solve Dy = z */ for (i = 0; i < n; i++) { arb_div(arb_mat_entry(X, i, c), arb_mat_entry(X, i, c), arb_mat_entry(L, i, i), prec); } /* solve Ux = y */ for (i = n - 1; i >= 0; i--) { for (j = i + 1; j < n; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(L, j, i), arb_mat_entry(X, j, c), prec); } } } } flint-3.1.3/src/arb_mat/solve_lu.c000066400000000000000000000016121461254215100170230ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "arb_mat.h" int arb_mat_solve_lu(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { int result; slong n, m, *perm; arb_mat_t LU; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; perm = _perm_init(n); arb_mat_init(LU, n, n); result = arb_mat_lu(perm, LU, A, prec); if (result) arb_mat_solve_lu_precomp(X, perm, LU, B, prec); arb_mat_clear(LU); _perm_clear(perm); return result; } flint-3.1.3/src/arb_mat/solve_lu_precomp.c000066400000000000000000000040241461254215100205500ustar00rootroot00000000000000/* Copyright (C) 2012,2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_solve_lu_precomp(arb_mat_t X, const slong * perm, const arb_mat_t A, const arb_mat_t B, slong prec) { slong i, j, c, n, m; n = arb_mat_nrows(X); m = arb_mat_ncols(X); if (X == B) { arb_ptr tmp = flint_malloc(sizeof(arb_struct) * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) tmp[i] = B->rows[perm[i]][c]; for (i = 0; i < n; i++) X->rows[i][c] = tmp[i]; } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { arb_set(arb_mat_entry(X, i, c), arb_mat_entry(B, perm[i], c)); } } } /* solve_tril and solve_triu have some overhead */ if (n >= 4) { arb_mat_solve_tril(X, A, X, 1, prec); arb_mat_solve_triu(X, A, X, 0, prec); return; } for (c = 0; c < m; c++) { /* solve Ly = b */ for (i = 1; i < n; i++) { for (j = 0; j < i; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(A, i, j), arb_mat_entry(X, j, c), prec); } } /* solve Ux = y */ for (i = n - 1; i >= 0; i--) { for (j = i + 1; j < n; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(A, i, j), arb_mat_entry(X, j, c), prec); } arb_div(arb_mat_entry(X, i, c), arb_mat_entry(X, i, c), arb_mat_entry(A, i, i), prec); } } } flint-3.1.3/src/arb_mat/solve_preapprox.c000066400000000000000000000045561461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" /* * Helper function to compute a lower bound of 1 - inf_norm(I - A*B). * Returns zero when this lower bound is zero. */ int _mag_err_complement(mag_t m, const arb_mat_t A, const arb_mat_t B, slong prec) { slong n; arb_mat_t I, E; mag_t err; n = arb_mat_nrows(A); arb_mat_init(I, n, n); arb_mat_one(I); arb_mat_init(E, n, n); arb_mat_mul(E, A, B, prec); arb_mat_sub(E, I, E, prec); mag_init(err); arb_mat_bound_inf_norm(err, E); mag_one(m); mag_sub_lower(m, m, err); mag_clear(err); arb_mat_clear(I); arb_mat_clear(E); return !mag_is_zero(m); } int arb_mat_solve_preapprox(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, const arb_mat_t R, const arb_mat_t T, slong prec) { int result; slong m, n; mag_t d; result = 0; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; /* Use Theorem 10.2 of Rump in Acta Numerica 2010 */ mag_init(d); if (_mag_err_complement(d, R, A, prec)) { arb_mat_t C; arb_mat_init(C, n, m); arb_mat_mul(C, A, T, prec); arb_mat_sub(C, C, B, prec); arb_mat_mul(C, R, C, prec); /* Each column gets its own error bound. */ arb_mat_set(X, T); { slong i, j; mag_t e, err; mag_init(e); mag_init(err); for (j = 0; j < m; j++) { mag_zero(err); for (i = 0; i < n; i++) { arb_get_mag(e, arb_mat_entry(C, i, j)); mag_max(err, err, e); } mag_div(err, err, d); for (i = 0; i < n; i++) { arb_add_error_mag(arb_mat_entry(X, i, j), err); } } mag_clear(e); mag_clear(err); } arb_mat_clear(C); result = 1; } mag_clear(d); return result; } flint-3.1.3/src/arb_mat/solve_precond.c000066400000000000000000000060651461254215100200440ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int _arb_mat_solve_c(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { int result; slong m, n; arb_mat_t I, R; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; arb_mat_init(I, n, n); arb_mat_init(R, n, n); arb_mat_one(I); result = arb_mat_approx_solve(R, A, I, prec); if (result) { arb_mat_t RA, RB; arb_mat_init(RA, n, n); arb_mat_init(RB, n, m); arb_mat_mul(RA, R, A, prec); arb_mat_mul(RB, R, B, prec); result = arb_mat_solve_lu(X, RA, RB, prec); arb_mat_clear(RA); arb_mat_clear(RB); } arb_mat_clear(I); arb_mat_clear(R); return result; } int _arb_mat_solve_d(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { int result; slong m, n; arb_mat_t I, R; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; arb_mat_init(I, n, n); arb_mat_init(R, n, n); arb_mat_one(I); result = arb_mat_approx_solve(R, A, I, prec); if (result) { arb_mat_t RA, RB, E; mag_t d; arb_mat_init(RA, n, n); arb_mat_init(RB, n, m); arb_mat_init(E, n, n); mag_init(d); arb_mat_mul(RA, R, A, prec); arb_mat_mul(RB, R, B, prec); arb_mat_sub(E, I, RA, prec); arb_mat_bound_inf_norm(d, E); if (mag_cmp_2exp_si(d, 0) < 0) { slong i, j; mag_t e, err; mag_init(e); mag_init(err); mag_geom_series(d, d, 1); arb_mat_set(X, RB); for (j = 0; j < m; j++) { mag_zero(err); for (i = 0; i < n; i++) { arb_get_mag(e, arb_mat_entry(RB, i, j)); mag_max(err, err, e); } mag_mul(err, err, d); for (i = 0; i < n; i++) { arb_add_error_mag(arb_mat_entry(X, i, j), err); } } mag_clear(e); mag_clear(err); } else { result = arb_mat_solve_lu(X, RA, RB, prec); } arb_mat_clear(RA); arb_mat_clear(RB); arb_mat_clear(E); mag_clear(d); } arb_mat_clear(I); arb_mat_clear(R); return result; } int arb_mat_solve_precond(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { slong n = arb_mat_nrows(A); slong m = arb_mat_ncols(B); if (m < 0.1 * n + 1) return _arb_mat_solve_c(X, A, B, prec); else return _arb_mat_solve_d(X, A, B, prec); } flint-3.1.3/src/arb_mat/solve_tril.c000066400000000000000000000052311461254215100173560ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_solve_tril_classical(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) { slong i, j, n, m; arb_ptr tmp; arb_t s; n = L->r; m = B->c; arb_init(s); tmp = flint_malloc(sizeof(arb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *arb_mat_entry(X, j, i); for (j = 0; j < n; j++) { arb_dot(s, arb_mat_entry(B, j, i), 1, L->rows[j], 1, tmp, 1, j, prec); if (!unit) arb_div(tmp + j, s, arb_mat_entry(L, j, j), prec); else arb_swap(tmp + j, s); } for (j = 0; j < n; j++) *arb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); arb_clear(s); } void arb_mat_solve_tril_recursive(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) { arb_mat_t LA, LC, LD, XX, XY, BX, BY, T; slong r, n, m; n = L->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A 0]^ [X] == [A^ 0 ] [X] == [A^ X] [C D] [Y] == [-D^ C A^ D^] [Y] == [D^ (Y - C A^ X)] */ arb_mat_window_init(LA, L, 0, 0, r, r); arb_mat_window_init(LC, L, r, 0, n, r); arb_mat_window_init(LD, L, r, r, n, n); arb_mat_window_init(BX, B, 0, 0, r, m); arb_mat_window_init(BY, B, r, 0, n, m); arb_mat_window_init(XX, X, 0, 0, r, m); arb_mat_window_init(XY, X, r, 0, n, m); arb_mat_solve_tril(XX, LA, BX, unit, prec); /* arb_mat_submul(XY, BY, LC, XX); */ arb_mat_init(T, LC->r, BX->c); arb_mat_mul(T, LC, XX, prec); arb_mat_sub(XY, BY, T, prec); arb_mat_clear(T); arb_mat_solve_tril(XY, LD, XY, unit, prec); arb_mat_window_clear(LA); arb_mat_window_clear(LC); arb_mat_window_clear(LD); arb_mat_window_clear(BX); arb_mat_window_clear(BY); arb_mat_window_clear(XX); arb_mat_window_clear(XY); } void arb_mat_solve_tril(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) arb_mat_solve_tril_classical(X, L, B, unit, prec); else arb_mat_solve_tril_recursive(X, L, B, unit, prec); } flint-3.1.3/src/arb_mat/solve_triu.c000066400000000000000000000052111461254215100173650ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_solve_triu_classical(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) { slong i, j, n, m; arb_ptr tmp; arb_t s; n = U->r; m = B->c; arb_init(s); tmp = flint_malloc(sizeof(arb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *arb_mat_entry(X, j, i); for (j = n - 1; j >= 0; j--) { arb_dot(s, arb_mat_entry(B, j, i), 1, U->rows[j] + j + 1, 1, tmp + j + 1, 1, n - j - 1, prec); if (!unit) arb_div(tmp + j, s, arb_mat_entry(U, j, j), prec); else arb_swap(tmp + j, s); } for (j = 0; j < n; j++) *arb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); arb_clear(s); } void arb_mat_solve_triu_recursive(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) { arb_mat_t UA, UB, UD, XX, XY, BX, BY, T; slong r, n, m; n = U->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A B]^ [X] == [A^ (X - B D^ Y)] [0 D] [Y] == [ D^ Y ] */ arb_mat_window_init(UA, U, 0, 0, r, r); arb_mat_window_init(UB, U, 0, r, r, n); arb_mat_window_init(UD, U, r, r, n, n); arb_mat_window_init(BX, B, 0, 0, r, m); arb_mat_window_init(BY, B, r, 0, n, m); arb_mat_window_init(XX, X, 0, 0, r, m); arb_mat_window_init(XY, X, r, 0, n, m); arb_mat_solve_triu(XY, UD, BY, unit, prec); /* arb_mat_submul(XX, BX, UB, XY); */ arb_mat_init(T, UB->r, XY->c); arb_mat_mul(T, UB, XY, prec); arb_mat_sub(XX, BX, T, prec); arb_mat_clear(T); arb_mat_solve_triu(XX, UA, XX, unit, prec); arb_mat_window_clear(UA); arb_mat_window_clear(UB); arb_mat_window_clear(UD); arb_mat_window_clear(BX); arb_mat_window_clear(BY); arb_mat_window_clear(XX); arb_mat_window_clear(XY); } void arb_mat_solve_triu(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) { if (B->r < 40 || B->c < 40) arb_mat_solve_triu_classical(X, U, B, unit, prec); else arb_mat_solve_triu_recursive(X, U, B, unit, prec); } flint-3.1.3/src/arb_mat/spd_get_fmpz_mat.c000066400000000000000000000020221461254215100205110ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "arb_mat.h" int arb_mat_spd_get_fmpz_mat(fmpz_mat_t B, const arb_mat_t A, slong prec) { slong j, k; slong g = arb_mat_nrows(A); arb_t z; int res = 1; arb_init(z); for (j = 0; (j < g) && res; j++) { for (k = j; (k < g) && res; k++) { res = arb_intersection(z, arb_mat_entry(A, j, k), arb_mat_entry(A, k, j), prec); arf_get_fmpz_fixed_si(fmpz_mat_entry(B, j, k), arb_midref(z), -prec); fmpz_set(fmpz_mat_entry(B, k, j), fmpz_mat_entry(B, j, k)); } } res = res && fmpz_mat_is_spd(B); arb_clear(z); return res; } flint-3.1.3/src/arb_mat/spd_inv.c000066400000000000000000000026121461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_spd_inv(arb_mat_t X, const arb_mat_t A, slong prec) { slong n; arb_mat_t L; int result; if (!arb_mat_is_square(A)) { flint_throw(FLINT_ERROR, "arb_mat_spd_inv: a square matrix is required\n"); } if (arb_mat_nrows(X) != arb_mat_nrows(A) || arb_mat_ncols(X) != arb_mat_ncols(A)) { flint_throw(FLINT_ERROR, "arb_mat_spd_inv: incompatible dimensions\n"); } if (arb_mat_is_empty(A)) return 1; n = arb_mat_nrows(A); if (n == 1) { if (arb_is_positive(arb_mat_entry(A, 0, 0))) { arb_inv(arb_mat_entry(X, 0, 0), arb_mat_entry(A, 0, 0), prec); return 1; } else { return 0; } } arb_mat_init(L, n, n); arb_mat_set(L, A); if (_arb_mat_cholesky_banachiewicz(L, prec)) { arb_mat_inv_cho_precomp(X, L, prec); result = 1; } else { result = 0; } arb_mat_clear(L); return result; } flint-3.1.3/src/arb_mat/spd_is_lll_reduced.c000066400000000000000000000044351461254215100210200ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz_lll.h" #include "arb_mat.h" /* Adapted from fmpz_mat_is_reduced_gram */ int arb_mat_spd_is_lll_reduced(const arb_mat_t A, slong tol_exp, slong prec) { slong d = arb_mat_nrows(A); arb_mat_t r, mu; arb_ptr s; arb_t delta, eta, t; slong i, j, k; int res = 1; if (d <= 1) { return 1; } arb_mat_init(r, d, d); arb_mat_init(mu, d, d); s = _arb_vec_init(d); arb_init(delta); arb_init(eta); arb_init(t); arb_one(t); arb_mul_2exp_si(t, t, tol_exp); arb_set_si(delta, 99); arb_div_si(delta, delta, 100, prec); arb_sub(delta, delta, t, prec); arb_set_si(eta, 51); arb_div_si(eta, eta, 100, prec); arb_add(eta, eta, t, prec); arb_set(arb_mat_entry(r, 0, 0), arb_mat_entry(A, 0, 0)); for (i = 1; (i < d) && res; i++) { arb_set(&s[0], arb_mat_entry(A, i, i)); for (j = 0; (j < i) && res; j++) { arb_set(arb_mat_entry(r, i, j), arb_mat_entry(A, i, j)); for (k = 0; k < j; k++) { arb_submul(arb_mat_entry(r, i, j), arb_mat_entry(mu, j, k), arb_mat_entry(r, i, k), prec); } arb_div(arb_mat_entry(mu, i, j), arb_mat_entry(r, i, j), arb_mat_entry(r, j, j), prec); arb_abs(t, arb_mat_entry(mu, i, j)); if (!arb_le(t, eta)) { res = 0; } arb_set(&s[j + 1], &s[j]); arb_submul(&s[j + 1], arb_mat_entry(mu, i, j), arb_mat_entry(r, i, j), prec); } arb_set(arb_mat_entry(r, i, i), &s[i]); arb_mul(t, delta, arb_mat_entry(r, i - 1, i - 1), prec); if (!arb_le(t, &s[i - 1])) { res = 0; } } arb_mat_clear(r); arb_mat_clear(mu); _arb_vec_clear(s, d); arb_clear(delta); arb_clear(eta); arb_clear(t); return res; } flint-3.1.3/src/arb_mat/spd_lll_reduce.c000066400000000000000000000016621461254215100201600ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz_lll.h" #include "arb_mat.h" void arb_mat_spd_lll_reduce(fmpz_mat_t U, const arb_mat_t A, slong prec) { fmpz_lll_t fl; fmpz_mat_t N; slong g = arb_mat_nrows(A); int r; if (!arb_mat_is_finite(A)) { return; } fmpz_mat_init(N, g, g); fmpz_mat_one(U); r = arb_mat_spd_get_fmpz_mat(N, A, prec); if (r) { /* Default Flint LLL values, except Gram */ fmpz_lll_context_init(fl, 0.99, 0.51, GRAM, EXACT); fmpz_lll(N, U, fl); } fmpz_mat_clear(N); } flint-3.1.3/src/arb_mat/spd_solve.c000066400000000000000000000014541461254215100171750ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" int arb_mat_spd_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { int result; slong n, m; arb_mat_t L; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; arb_mat_init(L, n, n); result = arb_mat_cho(L, A, prec); if (result) arb_mat_solve_cho_precomp(X, L, B, prec); arb_mat_clear(L); return result; } flint-3.1.3/src/arb_mat/sqr.c000066400000000000000000000007601461254215100160030ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_sqr(arb_mat_t B, const arb_mat_t A, slong prec) { arb_mat_mul(B, A, A, prec); } flint-3.1.3/src/arb_mat/sqr_classical.c000066400000000000000000000051721461254215100200230ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_sqr_classical(arb_mat_t B, const arb_mat_t A, slong prec) { slong n, i, j, k; arb_t p, s; n = arb_mat_nrows(A); if (arb_mat_ncols(A) != n || arb_mat_nrows(B) != n || arb_mat_ncols(B) != n) { flint_throw(FLINT_ERROR, "arb_mat_sqr: incompatible dimensions\n"); } if (n == 0) return; if (n == 1) { arb_mul(arb_mat_entry(B, 0, 0), arb_mat_entry(A, 0, 0), arb_mat_entry(A, 0, 0), prec); return; } if (A == B) { arb_mat_t T; arb_mat_init(T, n, n); arb_mat_sqr_classical(T, A, prec); arb_mat_swap(T, B); arb_mat_clear(T); return; } arb_init(p); arb_init(s); /* contribution of diagonal of A to diagonal of B */ for (i = 0; i < n; i++) { arb_mul(arb_mat_entry(B, i, i), arb_mat_entry(A, i, i), arb_mat_entry(A, i, i), prec); } for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { /* contribution of off-diagonal of A to diagonal of B */ arb_mul(p, arb_mat_entry(A, i, j), arb_mat_entry(A, j, i), prec); arb_add(arb_mat_entry(B, i, i), arb_mat_entry(B, i, i), p, prec); arb_add(arb_mat_entry(B, j, j), arb_mat_entry(B, j, j), p, prec); /* contribution of diagonal of A to off-diagonal of B */ arb_add(s, arb_mat_entry(A, i, i), arb_mat_entry(A, j, j), prec); arb_mul(arb_mat_entry(B, i, j), arb_mat_entry(A, i, j), s, prec); arb_mul(arb_mat_entry(B, j, i), arb_mat_entry(A, j, i), s, prec); } } /* contribution of off-diagonal of A to off-diagonal of B */ if (n > 2) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { for (k = 0; k < n; k++) { if (i != j && j != k && k != i) { arb_addmul(arb_mat_entry(B, i, j), arb_mat_entry(A, i, k), arb_mat_entry(A, k, j), prec); } } } } } arb_clear(p); arb_clear(s); } flint-3.1.3/src/arb_mat/stirling.c000066400000000000000000000011671461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" #include "gr.h" #include "gr_mat.h" void arb_mat_stirling(arb_mat_t mat, int kind, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); GR_MUST_SUCCEED(gr_mat_stirling((gr_mat_struct *) mat, kind, ctx)); } flint-3.1.3/src/arb_mat/sub.c000066400000000000000000000013651461254215100157710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_sub(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) arb_sub(arb_mat_entry(res, i, j), arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j), prec); } flint-3.1.3/src/arb_mat/test/000077500000000000000000000000001461254215100160065ustar00rootroot00000000000000flint-3.1.3/src/arb_mat/test/main.c000066400000000000000000000060731461254215100171040ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-addmul_rad_mag_fast.c" #include "t-charpoly.c" #include "t-cho.c" #include "t-companion.c" #include "t-dct.c" #include "t-det.c" #include "t-det_precond.c" #include "t-exp.c" #include "t-exp_taylor_sum.c" #include "t-frobenius_norm.c" #include "t-inv.c" #include "t-inv_cho_precomp.c" #include "t-inv_ldl_precomp.c" #include "t-ldl.c" #include "t-lu.c" #include "t-lu_recursive.c" #include "t-mul_block.c" #include "t-mul.c" #include "t-mul_entrywise.c" #include "t-mul_threaded.c" #include "t-pascal.c" #include "t-solve.c" #include "t-solve_cho_precomp.c" #include "t-solve_ldl_precomp.c" #include "t-solve_lu.c" #include "t-solve_preapprox.c" #include "t-solve_precond.c" #include "t-solve_tril.c" #include "t-solve_triu.c" #include "t-spd_get_fmpz_mat.c" #include "t-spd_inv.c" #include "t-spd_lll_reduce.c" #include "t-spd_solve.c" #include "t-sqr.c" #include "t-stirling.c" #include "t-trace.c" #include "t-transpose.c" #include "t-vector_mul.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arb_mat_addmul_rad_mag_fast), TEST_FUNCTION(arb_mat_charpoly), TEST_FUNCTION(arb_mat_cho), TEST_FUNCTION(arb_mat_companion), TEST_FUNCTION(arb_mat_dct), TEST_FUNCTION(arb_mat_det), TEST_FUNCTION(arb_mat_det_precond), TEST_FUNCTION(arb_mat_exp), TEST_FUNCTION(arb_mat_exp_taylor_sum), TEST_FUNCTION(arb_mat_frobenius_norm), TEST_FUNCTION(arb_mat_inv), TEST_FUNCTION(arb_mat_inv_cho_precomp), TEST_FUNCTION(arb_mat_inv_ldl_precomp), TEST_FUNCTION(arb_mat_ldl), TEST_FUNCTION(arb_mat_lu), TEST_FUNCTION(arb_mat_lu_recursive), TEST_FUNCTION(arb_mat_mul_block), TEST_FUNCTION(arb_mat_mul), TEST_FUNCTION(arb_mat_mul_entrywise), TEST_FUNCTION(arb_mat_mul_threaded), TEST_FUNCTION(arb_mat_pascal), TEST_FUNCTION(arb_mat_solve), TEST_FUNCTION(arb_mat_solve_cho_precomp), TEST_FUNCTION(arb_mat_solve_ldl_precomp), TEST_FUNCTION(arb_mat_solve_lu), TEST_FUNCTION(arb_mat_solve_preapprox), TEST_FUNCTION(arb_mat_solve_precond), TEST_FUNCTION(arb_mat_solve_tril), TEST_FUNCTION(arb_mat_solve_triu), TEST_FUNCTION(arb_mat_spd_get_fmpz_mat), TEST_FUNCTION(arb_mat_spd_inv), TEST_FUNCTION(arb_mat_spd_lll_reduce), TEST_FUNCTION(arb_mat_spd_solve), TEST_FUNCTION(arb_mat_sqr), TEST_FUNCTION(arb_mat_stirling), TEST_FUNCTION(arb_mat_trace), TEST_FUNCTION(arb_mat_transpose), TEST_FUNCTION(arb_mat_vector_mul) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arb_mat/test/t-addmul_rad_mag_fast.c000066400000000000000000000072111461254215100223510ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" #define BLOCK_SIZE 32 static void fallback(arb_mat_t C, mag_srcptr A, mag_srcptr B, slong ar, slong ac, slong bc) { slong i, j, k, ii, jj, kk; for (ii = 0; ii < ar; ii += BLOCK_SIZE) { for (jj = 0; jj < bc; jj += BLOCK_SIZE) { for (kk = 0; kk < ac; kk += BLOCK_SIZE) { for (i = ii; i < FLINT_MIN(ii + BLOCK_SIZE, ar); i++) { for (j = jj; j < FLINT_MIN(jj + BLOCK_SIZE, bc); j++) { for (k = kk; k < FLINT_MIN(kk + BLOCK_SIZE, ac); k++) { mag_fast_addmul(arb_radref(arb_mat_entry(C, i, j)), A + i * ac + k, B + j * ac + k); } } } } } } } TEST_FUNCTION_START(arb_mat_addmul_rad_mag_fast, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t C, D; slong m, n, p, density, i, j, off; mag_ptr A, B; mag_t lo, hi; m = n_randint(state, 40); n = n_randint(state, 40); p = n_randint(state, 40); A = _mag_vec_init(m * n); B = _mag_vec_init(p * n); arb_mat_init(C, m, p); arb_mat_init(D, m, p); mag_init(lo); mag_init(hi); density = 1 + n_randint(state, 100); off = n_randint(state, 10000); for (i = 0; i < m * n; i++) { if (n_randint(state, 100) < density) { mag_randtest(A + i, state, 8 + n_randint(state, 10)); mag_mul_2exp_si(A + i, A + i, off); } } off = n_randint(state, 10000); for (i = 0; i < p * n; i++) { if (n_randint(state, 100) < density) { mag_randtest(B + i, state, 8 + n_randint(state, 10)); mag_mul_2exp_si(B + i, B + i, off); } } fallback(C, A, B, m, n, p); _arb_mat_addmul_rad_mag_fast(D, A, B, m, n, p); for (i = 0; i < m; i++) { for (j = 0; j < p; j++) { mag_set_d(lo, 0.9999); mag_set_d(hi, 1.0001); mag_mul(lo, lo, arb_radref(arb_mat_entry(C, i, j))); mag_mul(hi, hi, arb_radref(arb_mat_entry(C, i, j))); if (mag_cmp(arb_radref(arb_mat_entry(D, i, j)), lo) < 0 || mag_cmp(arb_radref(arb_mat_entry(D, i, j)), hi) > 0) { flint_printf("FAIL\n"); flint_printf("m = %wd, n = %wd, p = %wd\n", m, n, p); flint_printf("i = %wd, j = %wd\n", i, j); mag_printd(arb_radref(arb_mat_entry(C, i, j)), 10); flint_printf("\n"); mag_printd(arb_radref(arb_mat_entry(D, i, j)), 10); flint_printf("\n"); flint_abort(); } } } _mag_vec_clear(A, m * n); _mag_vec_clear(B, p * n); arb_mat_clear(C); arb_mat_clear(D); mag_clear(lo); mag_clear(hi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-charpoly.c000066400000000000000000000036441461254215100202430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_charpoly, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, B, C, D; arb_poly_t f, g; slong m, n; m = n_randint(state, 8); n = m; arb_mat_init(A, m, n); arb_mat_init(B, m, n); arb_mat_init(C, m, m); arb_mat_init(D, n, n); arb_poly_init(f); arb_poly_init(g); arb_mat_randtest(A, state, 1 + n_randint(state, 1000), 10); arb_mat_randtest(B, state, 1 + n_randint(state, 1000), 10); arb_mat_mul(C, A, B, 2 + n_randint(state, 1000)); arb_mat_mul(D, B, A, 2 + n_randint(state, 1000)); arb_mat_charpoly(f, C, 2 + n_randint(state, 1000)); arb_mat_charpoly(g, D, 2 + n_randint(state, 1000)); if (!arb_poly_overlaps(f, g)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), arb_mat_printd(A, 15), flint_printf("\n"); flint_printf("Matrix B:\n"), arb_mat_printd(B, 15), flint_printf("\n"); flint_printf("cp(AB) = "), arb_poly_printd(f, 15), flint_printf("\n"); flint_printf("cp(BA) = "), arb_poly_printd(g, 15), flint_printf("\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(C); arb_mat_clear(D); arb_poly_clear(f); arb_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-cho.c000066400000000000000000000144301461254215100171660ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif /* Defined in t-cho.c, t-ldl.c, t-lu.c, t-lu_recursive.c */ #ifndef fmpq_mat_is_invertible #define fmpq_mat_is_invertible fmpq_mat_is_invertible int fmpq_mat_is_invertible(const fmpq_mat_t A) { int r; fmpq_t t; fmpq_init(t); fmpq_mat_det(t, A); r = !fmpq_is_zero(t); fmpq_clear(t); return r; } #endif TEST_FUNCTION_START(arb_mat_cho, state) { slong iter; /* check special matrices */ { slong n; for (n = 1; n < 10; n++) { slong lprec; arb_mat_t L, A; arb_mat_init(L, n, n); arb_mat_init(A, n, n); for (lprec = 2; lprec < 10; lprec++) { int result; slong prec; prec = 1 << lprec; /* zero */ arb_mat_zero(A); result = arb_mat_cho(L, A, prec); if (result) { flint_printf("FAIL (zero):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } /* negative identity */ arb_mat_one(A); arb_mat_neg(A, A); result = arb_mat_cho(L, A, prec); if (result) { flint_printf("FAIL (negative identity):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } /* identity */ arb_mat_one(A); result = arb_mat_cho(L, A, prec); if (!result || !arb_mat_equal(L, A)) { flint_printf("FAIL (identity):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } } arb_mat_clear(L); arb_mat_clear(A); } } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; arb_mat_t A, L, U, T; slong n, qbits, prec; int q_invertible, r_invertible; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(L, n, n); arb_mat_init(U, n, n); arb_mat_init(T, n, n); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_cho(L, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_cho(L, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } arb_mat_transpose(U, L); arb_mat_mul(T, L, U, prec); if (!arb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); arb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("L*U = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(L); arb_mat_clear(U); arb_mat_clear(T); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-companion.c000066400000000000000000000032051461254215100203760ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_companion, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A; arb_poly_t f, g; slong n, prec; arb_poly_init(f); arb_poly_init(g); do { arb_poly_randtest(f, state, 1 + n_randint(state, 8), 1 + n_randint(state, 1000), 10); } while (arb_poly_degree(f) < 0); n = arb_poly_degree(f); prec = 2 + n_randint(state, 200); arb_mat_init(A, n, n); arb_mat_randtest(A, state, 1 + n_randint(state, 1000), 10); arb_mat_companion(A, f, prec); arb_mat_charpoly(g, A, prec); arb_poly_scalar_mul(g, g, arb_poly_get_coeff_ptr(f, n), prec); if (!arb_poly_contains(g, f)) { flint_printf("FAIL\n"); flint_printf("A:\n"), arb_mat_printd(A, 15), flint_printf("\n"); flint_printf("f:\n"), arb_poly_printd(f, 15), flint_printf("\n"); flint_printf("g:\n"), arb_poly_printd(g, 15), flint_printf("\n"); flint_abort(); } arb_mat_clear(A); arb_poly_clear(f); arb_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-dct.c000066400000000000000000000031011461254215100171600ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_dct, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, Ainv, AT; slong n, prec; n = n_randint(state, 10); prec = 53 + n_randint(state, 30); arb_mat_init(A, n, n); arb_mat_init(Ainv, n, n); arb_mat_init(AT, n, n); arb_mat_randtest(A, state, 100, 10); arb_mat_dct(A, 0, prec); if (!arb_mat_inv(Ainv, A, prec)) { flint_printf("FAIL: small DCT matrix (n = %wd) not invertible\n", n); flint_abort(); } arb_mat_transpose(AT, A); if (!arb_mat_overlaps(AT, Ainv)) { flint_printf("FAIL: overlap (n = %wd)\n", n); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_printf("AT = \n"); arb_mat_printd(AT, 15); flint_printf("\n\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(Ainv); arb_mat_clear(AT); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-det.c000066400000000000000000000074551461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2012, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_det, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; fmpq_t Qdet; arb_mat_t A; arb_t Adet; slong n, qbits, prec; n = n_randint(state, 12); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_init(Qdet); arb_mat_init(A, n, n); arb_init(Adet); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_det(Qdet, Q); arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_det(Adet, A, prec); if (!arb_contains_fmpq(Adet, Qdet)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qdet = \n"); fmpq_print(Qdet); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Adet = \n"); arb_printd(Adet, 15); flint_printf("\n\n"); flint_printf("Adet = \n"); arb_print(Adet); flint_printf("\n\n"); flint_abort(); } fmpq_mat_clear(Q); fmpq_clear(Qdet); arb_mat_clear(A); arb_clear(Adet); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, B, AB; arb_t detA, detB, detAB, t; slong n, prec1, prec2, prec3; n = n_randint(state, 12); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); prec3 = 2 + n_randint(state, 200); arb_mat_init(A, n, n); arb_mat_init(B, n, n); arb_mat_init(AB, n, n); arb_init(detA); arb_init(detB); arb_init(detAB); arb_init(t); arb_mat_randtest(A, state, 2 + n_randint(state, 200), 2 + n_randint(state, 100)); arb_mat_randtest(B, state, 2 + n_randint(state, 200), 2 + n_randint(state, 100)); arb_mat_mul(AB, A, B, prec3); arb_mat_det(detA, A, prec1); arb_mat_det(detB, B, prec2); arb_mat_det(detAB, AB, prec3); arb_mul(t, detA, detB, 1000); if (!arb_overlaps(t, detAB)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("n = %wd, prec1 = %wd, prec2 = %wd, prec3 = %wd\n", n, prec1, prec2, prec3); flint_printf("\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("detA = \n"); arb_printn(detA, 50, 0); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("detB = \n"); arb_printn(detB, 50, 0); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(AB, 15); flint_printf("\n\n"); flint_printf("detAB = \n"); arb_printn(detAB, 50, 0); flint_printf("\n\n"); flint_printf("detA*detB = \n"); arb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(AB); arb_clear(detA); arb_clear(detB); arb_clear(detAB); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-det_precond.c000066400000000000000000000075541461254215100207140ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_det_precond, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, B, AB; arb_t detA, detB, detAB, detAb, detBb, detABb, t; slong n, prec1, prec2, prec3; n = n_randint(state, 12); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); prec3 = 2 + n_randint(state, 200); arb_mat_init(A, n, n); arb_mat_init(B, n, n); arb_mat_init(AB, n, n); arb_init(detA); arb_init(detB); arb_init(detAB); arb_init(t); arb_init(detAb); arb_init(detBb); arb_init(detABb); arb_mat_randtest(A, state, 2 + n_randint(state, 200), 2 + n_randint(state, 20)); arb_mat_randtest(B, state, 2 + n_randint(state, 200), 2 + n_randint(state, 20)); arb_mat_mul(AB, A, B, prec3); arb_mat_det_precond(detA, A, prec1); arb_mat_det_precond(detB, B, prec2); arb_mat_det_precond(detAB, AB, prec3); arb_mul(t, detA, detB, 1000); if (!arb_overlaps(t, detAB)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("n = %wd, prec1 = %wd, prec2 = %wd, prec3 = %wd\n", n, prec1, prec2, prec3); flint_printf("\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("detA = \n"); arb_printn(detA, 50, 0); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("detB = \n"); arb_printn(detB, 50, 0); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(AB, 15); flint_printf("\n\n"); flint_printf("detAB = \n"); arb_printn(detAB, 50, 0); flint_printf("\n\n"); flint_printf("detA*detB = \n"); arb_printn(t, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_mat_det_lu(detAb, A, prec1); arb_mat_det_lu(detBb, B, prec2); arb_mat_det_lu(detABb, AB, prec3); if (!arb_overlaps(detA, detAb) || !arb_overlaps(detB, detBb) || !arb_overlaps(detAB, detABb)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("n = %wd, prec1 = %wd, prec2 = %wd, prec3 = %wd\n", n, prec1, prec2, prec3); flint_printf("\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("detA = \n"); arb_printn(detA, 50, 0); flint_printf("\n\n"); flint_printf("detAb = \n"); arb_printn(detAb, 50, 0); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("detB = \n"); arb_printn(detB, 50, 0); flint_printf("\n\n"); flint_printf("detBb = \n"); arb_printn(detBb, 50, 0); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(AB, 15); flint_printf("\n\n"); flint_printf("detAB = \n"); arb_printn(detAB, 50, 0); flint_printf("\n\n"); flint_printf("detABb = \n"); arb_printn(detABb, 50, 0); flint_printf("\n\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(AB); arb_clear(detA); arb_clear(detB); arb_clear(detAB); arb_clear(t); arb_clear(detAb); arb_clear(detBb); arb_clear(detABb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-exp.c000066400000000000000000000056301461254215100172130ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" void _fmpq_mat_randtest_for_exp(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong i, j; slong d, l, u; d = n_randint(state, 5); l = n_randint(state, 5); u = n_randint(state, 5); fmpq_mat_zero(mat); for (i = 0; i < fmpq_mat_nrows(mat); i++) { for (j = 0; j < fmpq_mat_ncols(mat); j++) { if ((i == j && d) || (i < j && u) || (i > j && l)) { fmpq_randtest(fmpq_mat_entry(mat, i, j), state, bits); } } } } TEST_FUNCTION_START(arb_mat_exp, state) { slong iter; /* check exp(A)*exp(c*A) = exp((1+c)*A) */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, E, F, EF, G; fmpq_mat_t Q; arb_t c, d; slong n, qbits, prec; n = n_randint(state, 5); qbits = 2 + n_randint(state, 300); prec = 2 + n_randint(state, 300); arb_init(c); arb_init(d); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(E, n, n); arb_mat_init(F, n, n); arb_mat_init(EF, n, n); arb_mat_init(G, n, n); _fmpq_mat_randtest_for_exp(Q, state, qbits); arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_exp(E, A, prec); arb_randtest(c, state, prec, 10); arb_mat_scalar_mul_arb(F, A, c, prec); arb_mat_exp(F, F, prec); arb_add_ui(d, c, 1, prec); arb_mat_scalar_mul_arb(G, A, d, prec); arb_mat_exp(G, G, prec); arb_mat_mul(EF, E, F, prec); if (!arb_mat_overlaps(EF, G)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("c = \n"); arb_printd(c, 15); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("E = \n"); arb_mat_printd(E, 15); flint_printf("\n\n"); flint_printf("F = \n"); arb_mat_printd(F, 15); flint_printf("\n\n"); flint_printf("E*F = \n"); arb_mat_printd(EF, 15); flint_printf("\n\n"); flint_printf("G = \n"); arb_mat_printd(G, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(c); arb_clear(d); fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(E); arb_mat_clear(F); arb_mat_clear(EF); arb_mat_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-exp_taylor_sum.c000066400000000000000000000042761461254215100214760ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_exp_taylor_sum, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, S1, S2, S3; fmpz_t f; slong n, N, prec1, prec2; n = n_randint(state, 5); N = n_randint(state, 40); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); arb_mat_init(A, n, n); arb_mat_init(S1, n, n); arb_mat_init(S2, n, n); arb_mat_init(S3, n, n); fmpz_init(f); arb_mat_randtest(A, state, prec1, 10); arb_mat_randtest(S1, state, prec1, 10); arb_mat_randtest(S2, state, prec1, 10); arb_mat_exp_taylor_sum(S1, A, N, prec1); arb_mat_exp_taylor_sum(S2, A, N + 1, prec2); arb_mat_pow_ui(S3, A, N, prec2); fmpz_fac_ui(f, N); arb_mat_scalar_div_fmpz(S3, S3, f, prec2); arb_mat_add(S3, S3, S1, prec2); if (!arb_mat_overlaps(S2, S3)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, N = %wd\n", n, N); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("S1 = \n"); arb_mat_printd(S1, 15); flint_printf("\n\n"); flint_printf("S2 = \n"); arb_mat_printd(S2, 15); flint_printf("\n\n"); flint_printf("S3 = \n"); arb_mat_printd(S3, 15); flint_printf("\n\n"); flint_abort(); } arb_mat_exp_taylor_sum(A, A, N, prec1); if (!arb_mat_overlaps(A, S1)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(S1); arb_mat_clear(S2); arb_mat_clear(S3); fmpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-frobenius_norm.c000066400000000000000000000140131461254215100214410ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" static void _fmpq_mat_sum_of_squares(fmpq_t res, const fmpq_mat_t Q) { slong i, j; fmpq_zero(res); for (i = 0; i < fmpq_mat_nrows(Q); i++) { for (j = 0; j < fmpq_mat_ncols(Q); j++) { fmpq_addmul(res, fmpq_mat_entry(Q, i, j), fmpq_mat_entry(Q, i, j)); } } } TEST_FUNCTION_START(arb_mat_frobenius_norm, state) { slong iter; /* compare to the exact rational norm */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; fmpq_t q; arb_mat_t A; slong n, qbits, prec; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_init(q); arb_mat_init(A, n, n); fmpq_mat_randtest(Q, state, qbits); _fmpq_mat_sum_of_squares(q, Q); arb_mat_set_fmpq_mat(A, Q, prec); /* check that the arb interval contains the exact value */ { arb_t a; arb_init(a); arb_mat_frobenius_norm(a, A, prec); arb_mul(a, a, a, prec); if (!arb_contains_fmpq(a, q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("frobenius_norm(Q)^2 = \n"); fmpq_print(q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("frobenius_norm(A)^2 = \n"); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("frobenius_norm(A)^2 = \n"); arb_print(a); flint_printf("\n\n"); flint_abort(); } arb_clear(a); } /* check that the upper bound is not less than the exact value */ { mag_t b; fmpq_t y; mag_init(b); fmpq_init(y); arb_mat_bound_frobenius_norm(b, A); mag_mul(b, b, b); mag_get_fmpq(y, b); if (fmpq_cmp(q, y) > 0) { flint_printf("FAIL (bound, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("frobenius_norm(Q)^2 = \n"); fmpq_print(q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("bound_frobenius_norm(A)^2 = \n"); mag_printd(b, 15); flint_printf("\n\n"); flint_printf("bound_frobenius_norm(A)^2 = \n"); mag_print(b); flint_printf("\n\n"); flint_abort(); } mag_clear(b); fmpq_clear(y); } fmpq_mat_clear(Q); fmpq_clear(q); arb_mat_clear(A); } /* check trace(A^T A) = frobenius_norm(A)^2 */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, prec; arb_mat_t A, AT, ATA; arb_t t; prec = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); arb_mat_init(A, m, n); arb_mat_init(AT, n, m); arb_mat_init(ATA, n, n); arb_init(t); arb_mat_randtest(A, state, 2 + n_randint(state, 100), 10); arb_mat_transpose(AT, A); arb_mat_mul(ATA, AT, A, prec); arb_mat_trace(t, ATA, prec); arb_sqrt(t, t, prec); /* check the norm bound */ { mag_t low, frobenius; mag_init(low); arb_get_mag_lower(low, t); mag_init(frobenius); arb_mat_bound_frobenius_norm(frobenius, A); if (mag_cmp(low, frobenius) > 0) { flint_printf("FAIL (bound)\n", iter); flint_printf("m = %wd, n = %wd, prec = %wd\n", m, n, prec); flint_printf("\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("lower(sqrt(trace(A^T A))) = \n"); mag_printd(low, 15); flint_printf("\n\n"); flint_printf("bound_frobenius_norm(A) = \n"); mag_printd(frobenius, 15); flint_printf("\n\n"); flint_abort(); } mag_clear(low); mag_clear(frobenius); } /* check the norm interval */ { arb_t frobenius; arb_init(frobenius); arb_mat_frobenius_norm(frobenius, A, prec); if (!arb_overlaps(t, frobenius)) { flint_printf("FAIL (overlap)\n", iter); flint_printf("m = %wd, n = %wd, prec = %wd\n", m, n, prec); flint_printf("\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("sqrt(trace(A^T A)) = \n"); arb_printd(t, 15); flint_printf("\n\n"); flint_printf("frobenius_norm(A) = \n"); arb_printd(frobenius, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(frobenius); } arb_mat_clear(A); arb_mat_clear(AT); arb_mat_clear(ATA); arb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-inv.c000066400000000000000000000073161461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_inv, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, Qinv; arb_mat_t A, Ainv; slong n, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(Qinv, n, n); arb_mat_init(A, n, n); arb_mat_init(Ainv, n, n); fmpq_mat_randtest(Q, state, qbits); q_invertible = fmpq_mat_inv(Qinv, Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_inv(Ainv, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_inv(Ainv, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(Ainv, Qinv)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qinv = \n"); fmpq_mat_print(Qinv); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = arb_mat_inv(A, A, prec); if (!arb_mat_equal(A, Ainv) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(Qinv); arb_mat_clear(A); arb_mat_clear(Ainv); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-inv_cho_precomp.c000066400000000000000000000116771461254215100216010ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif /* Defined in t-inv_cho_precomp.c and t-inv_ldl_precomp.c */ #define _spd_inv _spd_inv_cho static int _spd_inv(arb_mat_t X, const arb_mat_t A, slong prec) { slong n; arb_mat_t L; int result; n = arb_mat_nrows(A); arb_mat_init(L, n, n); arb_mat_set(L, A); if (_arb_mat_cholesky_banachiewicz(L, prec)) { arb_mat_inv_cho_precomp(X, L, prec); result = 1; } else { result = 0; } arb_mat_clear(L); return result; } TEST_FUNCTION_START(arb_mat_inv_cho_precomp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, Qinv; arb_mat_t A, Ainv; slong n, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(Qinv, n, n); arb_mat_init(A, n, n); arb_mat_init(Ainv, n, n); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); q_invertible = fmpq_mat_inv(Qinv, Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = _spd_inv(Ainv, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = _spd_inv(Ainv, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(Ainv, Qinv)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qinv = \n"); fmpq_mat_print(Qinv); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = _spd_inv(A, A, prec); if (!arb_mat_equal(A, Ainv) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(Qinv); arb_mat_clear(A); arb_mat_clear(Ainv); } TEST_FUNCTION_END(state); } #undef _spd_inv flint-3.1.3/src/arb_mat/test/t-inv_ldl_precomp.c000066400000000000000000000116651461254215100216000ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif /* Defined in t-inv_cho_precomp.c and t-inv_ldl_precomp.c */ #define _spd_inv _spd_inv_ldl static int _spd_inv(arb_mat_t X, const arb_mat_t A, slong prec) { slong n; arb_mat_t L; int result; n = arb_mat_nrows(A); arb_mat_init(L, n, n); arb_mat_set(L, A); if (_arb_mat_ldl_inplace(L, prec)) { arb_mat_inv_ldl_precomp(X, L, prec); result = 1; } else { result = 0; } arb_mat_clear(L); return result; } TEST_FUNCTION_START(arb_mat_inv_ldl_precomp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, Qinv; arb_mat_t A, Ainv; slong n, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(Qinv, n, n); arb_mat_init(A, n, n); arb_mat_init(Ainv, n, n); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); q_invertible = fmpq_mat_inv(Qinv, Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = _spd_inv(Ainv, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = _spd_inv(Ainv, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(Ainv, Qinv)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qinv = \n"); fmpq_mat_print(Qinv); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = _spd_inv(A, A, prec); if (!arb_mat_equal(A, Ainv) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(Qinv); arb_mat_clear(A); arb_mat_clear(Ainv); } TEST_FUNCTION_END(state); } #undef _spd_inv flint-3.1.3/src/arb_mat/test/t-ldl.c000066400000000000000000000154211461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif /* Defined in t-cho.c, t-ldl.c, t-lu.c, t-lu_recursive.c */ #ifndef fmpq_mat_is_invertible #define fmpq_mat_is_invertible fmpq_mat_is_invertible int fmpq_mat_is_invertible(const fmpq_mat_t A) { int r; fmpq_t t; fmpq_init(t); fmpq_mat_det(t, A); r = !fmpq_is_zero(t); fmpq_clear(t); return r; } #endif TEST_FUNCTION_START(arb_mat_ldl, state) { slong iter; /* check special matrices */ { slong n; for (n = 1; n < 10; n++) { slong lprec; arb_mat_t L, A; arb_mat_init(L, n, n); arb_mat_init(A, n, n); for (lprec = 2; lprec < 10; lprec++) { int result; slong prec; prec = 1 << lprec; /* zero */ arb_mat_zero(A); result = arb_mat_ldl(L, A, prec); if (result) { flint_printf("FAIL (zero):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } /* negative identity */ arb_mat_one(A); arb_mat_neg(A, A); result = arb_mat_ldl(L, A, prec); if (result) { flint_printf("FAIL (negative identity):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } /* identity */ arb_mat_one(A); result = arb_mat_ldl(L, A, prec); if (!result || !arb_mat_equal(L, A)) { flint_printf("FAIL (identity):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } } arb_mat_clear(L); arb_mat_clear(A); } } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; arb_mat_t A, L, D, U, T; slong n, qbits, prec; int q_invertible, r_invertible; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(L, n, n); arb_mat_init(D, n, n); arb_mat_init(U, n, n); arb_mat_init(T, n, n); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_ldl(L, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_ldl(L, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } /* multiply out the decomposition */ { slong i; arb_mat_zero(D); arb_mat_transpose(U, L); for (i = 0; i < n; i++) { arb_set(arb_mat_entry(D, i, i), arb_mat_entry(L, i, i)); arb_one(arb_mat_entry(L, i, i)); arb_one(arb_mat_entry(U, i, i)); } arb_mat_mul(T, L, D, prec); arb_mat_mul(T, T, U, prec); } if (!arb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); arb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("L*U = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(L); arb_mat_clear(D); arb_mat_clear(U); arb_mat_clear(T); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-lu.c000066400000000000000000000105271461254215100170400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-ldl.c, t-lu.c, t-lu_recursive.c */ #ifndef fmpq_mat_is_invertible #define fmpq_mat_is_invertible fmpq_mat_is_invertible int fmpq_mat_is_invertible(const fmpq_mat_t A) { int r; fmpq_t t; fmpq_init(t); fmpq_mat_det(t, A); r = !fmpq_is_zero(t); fmpq_clear(t); return r; } #endif TEST_FUNCTION_START(arb_mat_lu, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; arb_mat_t A, LU, P, L, U, T; slong i, j, n, qbits, prec, *perm; int q_invertible, r_invertible; n = n_randint(state, 10); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(LU, n, n); arb_mat_init(P, n, n); arb_mat_init(L, n, n); arb_mat_init(U, n, n); arb_mat_init(T, n, n); perm = _perm_init(n); fmpq_mat_randtest(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_lu(perm, LU, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); arb_mat_printd(LU, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_lu(perm, LU, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_abort(); } prec *= 2; } } arb_mat_one(L); for (i = 0; i < n; i++) for (j = 0; j < i; j++) arb_set(arb_mat_entry(L, i, j), arb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) for (j = i; j < n; j++) arb_set(arb_mat_entry(U, i, j), arb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) arb_one(arb_mat_entry(P, perm[i], i)); arb_mat_mul(T, P, L, prec); arb_mat_mul(T, T, U, prec); if (!arb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); arb_mat_printd(LU, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); arb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("P*L*U = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(LU); arb_mat_clear(P); arb_mat_clear(L); arb_mat_clear(U); arb_mat_clear(T); _perm_clear(perm); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-lu_recursive.c000066400000000000000000000123661461254215100211320ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-ldl.c, t-lu.c, t-lu_recursive.c */ #ifndef fmpq_mat_is_invertible #define fmpq_mat_is_invertible fmpq_mat_is_invertible int fmpq_mat_is_invertible(const fmpq_mat_t A) { int r; fmpq_t t; fmpq_init(t); fmpq_mat_det(t, A); r = !fmpq_is_zero(t); fmpq_clear(t); return r; } #endif TEST_FUNCTION_START(arb_mat_lu_recursive, state) { slong iter; /* Dummy test with rectangular matrices. Rectangular matrices are not actually supported (the output may be bogus), but the algorithm should at least not crash. */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, prec; slong *perm; arb_mat_t A, LU; n = n_randint(state, 20); m = n_randint(state, 20); prec = 2 + n_randint(state, 200); arb_mat_init(A, n, m); arb_mat_init(LU, n, m); perm = _perm_init(n); arb_mat_randtest(A, state, prec, 10); if (n_randint(state, 2)) { arb_mat_lu_recursive(perm, LU, A, prec); } else { arb_mat_set(LU, A); arb_mat_lu_recursive(perm, LU, LU, prec); } arb_mat_clear(A); arb_mat_clear(LU); _perm_clear(perm); } for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; arb_mat_t A, LU, P, L, U, T; slong i, j, n, qbits, prec, *perm; int q_invertible, r_invertible; n = n_randint(state, 20); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(LU, n, n); arb_mat_init(P, n, n); arb_mat_init(L, n, n); arb_mat_init(U, n, n); arb_mat_init(T, n, n); perm = _perm_init(n); fmpq_mat_randtest(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_lu_recursive(perm, LU, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); arb_mat_printd(LU, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_lu_recursive(perm, LU, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_abort(); } prec *= 2; } } arb_mat_one(L); for (i = 0; i < n; i++) for (j = 0; j < i; j++) arb_set(arb_mat_entry(L, i, j), arb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) for (j = i; j < n; j++) arb_set(arb_mat_entry(U, i, j), arb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) arb_one(arb_mat_entry(P, perm[i], i)); arb_mat_mul(T, P, L, prec); arb_mat_mul(T, T, U, prec); if (!arb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); arb_mat_printd(LU, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); arb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("P*L*U = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(LU); arb_mat_clear(P); arb_mat_clear(L); arb_mat_clear(U); arb_mat_clear(T); _perm_clear(perm); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-mul.c000066400000000000000000000061571461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_mul, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; arb_mat_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, k); fmpq_mat_init(C, m, k); arb_mat_init(a, m, n); arb_mat_init(b, n, k); arb_mat_init(c, m, k); arb_mat_init(d, m, k); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); fmpq_mat_mul(C, A, B); arb_mat_set_fmpq_mat(a, A, rbits1); arb_mat_set_fmpq_mat(b, B, rbits2); arb_mat_mul(c, a, b, rbits3); if (!arb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd, k = %wd, bits3 = %wd\n", m, n, k, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (arb_mat_nrows(a) == arb_mat_nrows(c) && arb_mat_ncols(a) == arb_mat_ncols(c)) { arb_mat_set(d, a); arb_mat_mul(d, d, b, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (arb_mat_nrows(b) == arb_mat_nrows(c) && arb_mat_ncols(b) == arb_mat_ncols(c)) { arb_mat_set(d, b); arb_mat_mul(d, a, d, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(c); arb_mat_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-mul_block.c000066400000000000000000000111761461254215100203700ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" FLINT_DLL extern slong arb_mat_mul_block_min_block_size; TEST_FUNCTION_START(arb_mat_mul_block, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; arb_mat_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); arb_mat_mul_block_min_block_size = n_randint(state, 10); m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, k); fmpq_mat_init(C, m, k); arb_mat_init(a, m, n); arb_mat_init(b, n, k); arb_mat_init(c, m, k); arb_mat_init(d, m, k); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); fmpq_mat_mul(C, A, B); arb_mat_set_fmpq_mat(a, A, rbits1); arb_mat_set_fmpq_mat(b, B, rbits2); arb_mat_mul_block(c, a, b, rbits3); if (!arb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd, k = %wd, bits3 = %wd\n", m, n, k, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (arb_mat_nrows(a) == arb_mat_nrows(c) && arb_mat_ncols(a) == arb_mat_ncols(c)) { arb_mat_set(d, a); arb_mat_mul_block(d, d, b, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (arb_mat_nrows(b) == arb_mat_nrows(c) && arb_mat_ncols(b) == arb_mat_ncols(c)) { arb_mat_set(d, b); arb_mat_mul_block(d, a, d, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(c); arb_mat_clear(d); } for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, B, C, D; slong m, n, p, bits1, bits2, exp1, exp2, prec1, prec2; m = n_randint(state, 40); n = n_randint(state, 40); p = n_randint(state, 40); arb_mat_mul_block_min_block_size = n_randint(state, 10); if (n_randint(state, 4) == 0) { exp1 = 4 + n_randint(state, FLINT_BITS); exp2 = 4 + n_randint(state, FLINT_BITS); } else { exp1 = exp2 = 20; } bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); prec1 = 2 + n_randint(state, 200); prec2 = 2 + n_randint(state, 200); arb_mat_init(A, m, n); arb_mat_init(B, n, p); arb_mat_init(C, m, p); arb_mat_init(D, m, p); arb_mat_randtest(A, state, bits1, exp1); arb_mat_randtest(B, state, bits2, exp2); arb_mat_randtest(C, state, bits2, exp2); arb_mat_mul_block(C, A, B, prec1); arb_mat_mul_classical(D, A, B, prec2); if (!arb_mat_overlaps(C, D)) { flint_printf("FAIL\n"); flint_printf("m = %wd, n = %wd, p = %wd\n", m, n, p); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(C); arb_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-mul_entrywise.c000066400000000000000000000070251461254215100213250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" void _fmpq_mat_mul_entrywise(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) { slong i, j; for (i = 0; i < fmpq_mat_nrows(A); i++) { for (j = 0; j < fmpq_mat_ncols(A); j++) { fmpq_mul(fmpq_mat_entry(C, i, j), fmpq_mat_entry(A, i, j), fmpq_mat_entry(B, i, j)); } } } TEST_FUNCTION_START(arb_mat_mul_entrywise, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; arb_mat_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); arb_mat_init(a, m, n); arb_mat_init(b, m, n); arb_mat_init(c, m, n); arb_mat_init(d, m, n); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); _fmpq_mat_mul_entrywise(C, A, B); arb_mat_set_fmpq_mat(a, A, rbits1); arb_mat_set_fmpq_mat(b, B, rbits2); arb_mat_mul_entrywise(c, a, b, rbits3); if (!arb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd, bits3 = %wd\n", m, n, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (arb_mat_nrows(a) == arb_mat_nrows(c) && arb_mat_ncols(a) == arb_mat_ncols(c)) { arb_mat_set(d, a); arb_mat_mul_entrywise(d, d, b, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (arb_mat_nrows(b) == arb_mat_nrows(c) && arb_mat_ncols(b) == arb_mat_ncols(c)) { arb_mat_set(d, b); arb_mat_mul_entrywise(d, a, d, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(c); arb_mat_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-mul_threaded.c000066400000000000000000000064021461254215100210520ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_mul_threaded, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; arb_mat_t a, b, c, d; flint_set_num_threads(1 + n_randint(state, 5)); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, k); fmpq_mat_init(C, m, k); arb_mat_init(a, m, n); arb_mat_init(b, n, k); arb_mat_init(c, m, k); arb_mat_init(d, m, k); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); fmpq_mat_mul(C, A, B); arb_mat_set_fmpq_mat(a, A, rbits1); arb_mat_set_fmpq_mat(b, B, rbits2); arb_mat_mul_threaded(c, a, b, rbits3); if (!arb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("threads = %d, m = %wd, n = %wd, k = %wd, bits3 = %wd\n", flint_get_num_threads(), m, n, k, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_mat_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing with a */ if (arb_mat_nrows(a) == arb_mat_nrows(c) && arb_mat_ncols(a) == arb_mat_ncols(c)) { arb_mat_set(d, a); arb_mat_mul_threaded(d, d, b, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } /* test aliasing with b */ if (arb_mat_nrows(b) == arb_mat_nrows(c) && arb_mat_ncols(b) == arb_mat_ncols(c)) { arb_mat_set(d, b); arb_mat_mul_threaded(d, a, d, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(c); arb_mat_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-pascal.c000066400000000000000000000041121461254215100176540ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_pascal, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A; fmpz_t t; slong n, m, i, j, prec; n = n_randint(state, 10); m = n_randint(state, 10); prec = 2 + n_randint(state, 200); fmpz_init(t); arb_mat_init(A, n, m); arb_mat_randtest(A, state, 100, 10); arb_mat_pascal(A, 0, prec); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { fmpz_bin_uiui(t, i + j, i); if (!arb_contains_fmpz(arb_mat_entry(A, i, j), t)) { flint_printf("FAIL: containment (0)\n"); flint_abort(); } } } arb_mat_pascal(A, 1, prec); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { fmpz_bin_uiui(t, j, i); if (!arb_contains_fmpz(arb_mat_entry(A, i, j), t)) { flint_printf("FAIL: containment (1)\n"); flint_abort(); } } } arb_mat_pascal(A, -1, prec); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { fmpz_bin_uiui(t, i, j); if (!arb_contains_fmpz(arb_mat_entry(A, i, j), t)) { flint_printf("FAIL: containment (-1)\n"); flint_abort(); } } } arb_mat_clear(A); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-solve.c000066400000000000000000000107041461254215100175450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_solve, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; arb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); m = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); arb_mat_init(A, n, n); arb_mat_init(X, n, m); arb_mat_init(B, n, m); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_solve(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_set_fmpq_mat(B, QB, prec); r_invertible = arb_mat_solve(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = arb_mat_solve(B, A, B, prec); if (!arb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-solve_cho_precomp.c000066400000000000000000000133501461254215100221230ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif /* Defined in t-solve_cho_precomp.c and t-solve_ldl_precomp.c */ #define _spd_solve _spd_solve_cho int _spd_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { slong n, m; int result; arb_mat_t L; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; n = arb_mat_nrows(A); arb_mat_init(L, n, n); result = arb_mat_cho(L, A, prec); if (result) { arb_mat_solve_cho_precomp(X, L, B, prec); } arb_mat_clear(L); return result; } TEST_FUNCTION_START(arb_mat_solve_cho_precomp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; arb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); m = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); arb_mat_init(A, n, n); arb_mat_init(X, n, m); arb_mat_init(B, n, m); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = _spd_solve(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_set_fmpq_mat(B, QB, prec); r_invertible = _spd_solve(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = _spd_solve(B, A, B, prec); if (!arb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); } TEST_FUNCTION_END(state); } #undef _spd_solve flint-3.1.3/src/arb_mat/test/t-solve_ldl_precomp.c000066400000000000000000000133501461254215100221250ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif /* Defined in t-solve_cho_precomp.c and t-solve_ldl_precomp.c */ #define _spd_solve _spd_solve_ldl int _spd_solve(arb_mat_t X, const arb_mat_t A, const arb_mat_t B, slong prec) { slong n, m; int result; arb_mat_t L; n = arb_mat_nrows(A); m = arb_mat_ncols(X); if (n == 0 || m == 0) return 1; n = arb_mat_nrows(A); arb_mat_init(L, n, n); result = arb_mat_ldl(L, A, prec); if (result) { arb_mat_solve_ldl_precomp(X, L, B, prec); } arb_mat_clear(L); return result; } TEST_FUNCTION_START(arb_mat_solve_ldl_precomp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; arb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); m = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); arb_mat_init(A, n, n); arb_mat_init(X, n, m); arb_mat_init(B, n, m); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = _spd_solve(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_set_fmpq_mat(B, QB, prec); r_invertible = _spd_solve(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = _spd_solve(B, A, B, prec); if (!arb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); } TEST_FUNCTION_END(state); } #undef _spd_solve flint-3.1.3/src/arb_mat/test/t-solve_lu.c000066400000000000000000000112001461254215100202350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_solve_lu, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; arb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; if (n_randint(state, 50) == 0) { n = n_randint(state, 20); m = n_randint(state, 20); } else { n = n_randint(state, 8); m = n_randint(state, 8); } qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); arb_mat_init(A, n, n); arb_mat_init(X, n, m); arb_mat_init(B, n, m); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_solve_lu(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_set_fmpq_mat(B, QB, prec); r_invertible = arb_mat_solve_lu(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = arb_mat_solve_lu(B, A, B, prec); if (!arb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-solve_preapprox.c000066400000000000000000000204031461254215100216420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" void _fmpq_mul_si_frac(fmpq_t res, const fmpq_t x, slong p, slong q) { fmpq_t r; fmpq_init(r); fmpq_set_si(r, p, q); fmpq_mul(res, x, r); fmpq_clear(r); } void _fmpq_max(fmpq_t p, const fmpq_t q, const fmpq_t r) { if (fmpq_cmp(q, r) < 0) fmpq_set(p, r); else fmpq_set(p, q); } void _fmpq_mat_scalar_mul_fmpq(fmpq_mat_t res, const fmpq_mat_t mat, const fmpq_t x) { slong i, j; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_mul(fmpq_mat_entry(res, i, j), fmpq_mat_entry(mat, i, j), x); } void _fmpq_mat_inf_norm(fmpq_t res, const fmpq_mat_t mat) { fmpq_t s, q; slong i, j; fmpq_init(s); fmpq_init(q); fmpq_zero(res); for (i = 0; i < mat->r; i++) { fmpq_zero(s); for (j = 0; j < mat->c; j++) { fmpq_abs(q, fmpq_mat_entry(mat, i, j)); fmpq_add(s, s, q); } _fmpq_max(res, res, s); } fmpq_clear(s); fmpq_clear(q); } TEST_FUNCTION_START(arb_mat_solve_preapprox, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t QA, QB, QR, QT, QE, QX; arb_mat_t A, B, R, T, X; slong n, m, qbits, prec; int q_invertible, r_approximable, r_approximable2; n = n_randint(state, 8); m = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(QA, n, n); fmpq_mat_init(QB, n, m); fmpq_mat_init(QR, n, n); fmpq_mat_init(QT, n, m); fmpq_mat_init(QE, n, n); fmpq_mat_init(QX, n, m); arb_mat_init(A, n, n); arb_mat_init(B, n, m); arb_mat_init(R, n, n); arb_mat_init(T, n, m); arb_mat_init(X, n, m); /* Sample a square matrix QE with inf-norm less than 1. */ { fmpq_t m; fmpq_init(m); fmpq_mat_randtest(QE, state, qbits); _fmpq_mat_inf_norm(m, QE); if (!fmpq_is_zero(m)) { slong p, q; q = 64; p = n_randint(state, q); fmpq_inv(m, m); _fmpq_mul_si_frac(m, m, p, q); _fmpq_mat_scalar_mul_fmpq(QE, QE, m); } fmpq_clear(m); } /* Sample an unrestricted square matrix QR. */ fmpq_mat_randtest(QR, state, qbits); /* Construct QA := inv(QR)(I - QE), so that I - QR*QA = QE */ fmpq_mat_one(QA); fmpq_mat_sub(QA, QA, QE); q_invertible = fmpq_mat_solve_fraction_free(QA, QR, QA); /* Sample unrestricted matrices QB and QT. */ fmpq_mat_randtest(QB, state, qbits); fmpq_mat_randtest(QT, state, qbits); arb_mat_set_fmpq_mat(A, QA, prec); arb_mat_set_fmpq_mat(B, QB, prec); arb_mat_set_fmpq_mat(R, QR, prec); arb_mat_set_fmpq_mat(T, QT, prec); if (q_invertible) { /* Construct QX := inv(QA)QB */ fmpq_mat_solve_fraction_free(QX, QA, QB); r_approximable = arb_mat_solve_preapprox(X, A, B, R, T, prec); if (r_approximable) { if (!arb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("QA = \n"); fmpq_mat_print(QA); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QR = \n"); fmpq_mat_print(QR); flint_printf("\n\n"); flint_printf("QT = \n"); fmpq_mat_print(QT); flint_printf("\n\n"); flint_printf("QE = \n"); fmpq_mat_print(QE); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("R = \n"); arb_mat_printd(R, 15); flint_printf("\n\n"); flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } /* test aliasing */ if (n_randint(state, 2)) { r_approximable2 = arb_mat_solve_preapprox(T, A, B, R, T, prec); if ((r_approximable != r_approximable2) || (r_approximable && !arb_mat_equal(X, T))) { flint_printf("FAIL (aliasing (X, T))\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } else { r_approximable2 = arb_mat_solve_preapprox(B, A, B, R, T, prec); if ((r_approximable != r_approximable2) || (r_approximable && !arb_mat_equal(X, B))) { flint_printf("FAIL (aliasing (X, B))\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } } /* test a simplified case where A = R = I */ { arb_mat_one(A); arb_mat_one(R); fmpq_mat_randtest(QB, state, qbits); fmpq_mat_randtest(QT, state, qbits); arb_mat_set_fmpq_mat(B, QB, prec); arb_mat_set_fmpq_mat(T, QT, prec); arb_mat_zero(X); r_approximable = arb_mat_solve_preapprox(X, A, B, R, T, prec); if (!r_approximable || !arb_mat_contains(X, B)) { flint_printf("FAIL (special values A = R = I))\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); } } /* test a simplified case where A = R = I and T = B */ { arb_mat_one(A); arb_mat_one(R); fmpq_mat_randtest(QB, state, qbits); arb_mat_set_fmpq_mat(B, QB, prec); arb_mat_set(T, B); arb_mat_zero(X); r_approximable = arb_mat_solve_preapprox(X, A, B, R, T, prec); if (!r_approximable || !arb_mat_contains(X, B)) { flint_printf("FAIL (special values A = R = I, T = B))\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); } } fmpq_mat_clear(QA); fmpq_mat_clear(QB); fmpq_mat_clear(QR); fmpq_mat_clear(QT); fmpq_mat_clear(QE); fmpq_mat_clear(QX); arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(R); arb_mat_clear(T); arb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-solve_precond.c000066400000000000000000000107321461254215100212600ustar00rootroot00000000000000/* Copyright (C) 2018 arbguest This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_solve_precond, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; arb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); m = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); arb_mat_init(A, n, n); arb_mat_init(X, n, m); arb_mat_init(B, n, m); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_solve_precond(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_set_fmpq_mat(B, QB, prec); r_invertible = arb_mat_solve_precond(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = arb_mat_solve_precond(B, A, B, prec); if (!arb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-solve_tril.c000066400000000000000000000057611461254215100206060ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_solve_tril, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, X, B, Y; slong rows, cols, prec, i, j; int unit; prec = 2 + n_randint(state, 200); if (n_randint(state, 10) == 0) { rows = n_randint(state, 60); cols = n_randint(state, 60); } else { rows = n_randint(state, 10); cols = n_randint(state, 10); } unit = n_randint(state, 2); arb_mat_init(A, rows, rows); arb_mat_init(B, rows, cols); arb_mat_init(X, rows, cols); arb_mat_init(Y, rows, cols); arb_mat_randtest(A, state, prec, 10); arb_mat_randtest(X, state, prec, 10); arb_mat_randtest(Y, state, prec, 10); for (i = 0; i < rows; i++) { if (unit) arb_one(arb_mat_entry(A, i, i)); else arb_set_ui(arb_mat_entry(A, i, i), 1 + n_randint(state, 100)); for (j = i + 1; j < rows; j++) arb_zero(arb_mat_entry(A, i, j)); } arb_mat_mul(B, A, X, prec); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) arb_set_ui(arb_mat_entry(A, i, i), 1 + n_randint(state, 100)); } /* Check Y = A^(-1) * (A * X) = X */ arb_mat_solve_tril(Y, A, B, unit, prec); if (!arb_mat_overlaps(Y, X)) { flint_printf("FAIL\n"); flint_printf("A = \n"); arb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); arb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } /* Check aliasing */ arb_mat_solve_tril(B, A, B, unit, prec); if (!arb_mat_equal(B, Y)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); arb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); arb_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-solve_triu.c000066400000000000000000000057521461254215100206170ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_solve_triu, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A, X, B, Y; slong rows, cols, prec, i, j; int unit; prec = 2 + n_randint(state, 200); if (n_randint(state, 10) == 0) { rows = n_randint(state, 60); cols = n_randint(state, 60); } else { rows = n_randint(state, 10); cols = n_randint(state, 10); } unit = n_randint(state, 2); arb_mat_init(A, rows, rows); arb_mat_init(B, rows, cols); arb_mat_init(X, rows, cols); arb_mat_init(Y, rows, cols); arb_mat_randtest(A, state, prec, 10); arb_mat_randtest(X, state, prec, 10); arb_mat_randtest(Y, state, prec, 10); for (i = 0; i < rows; i++) { if (unit) arb_one(arb_mat_entry(A, i, i)); else arb_set_ui(arb_mat_entry(A, i, i), 1 + n_randint(state, 100)); for (j = 0; j < i; j++) arb_zero(arb_mat_entry(A, i, j)); } arb_mat_mul(B, A, X, prec); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) arb_set_ui(arb_mat_entry(A, i, i), 1 + n_randint(state, 100)); } /* Check Y = A^(-1) * (A * X) = X */ arb_mat_solve_triu(Y, A, B, unit, prec); if (!arb_mat_overlaps(Y, X)) { flint_printf("FAIL\n"); flint_printf("A = \n"); arb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); arb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } /* Check aliasing */ arb_mat_solve_triu(B, A, B, unit, prec); if (!arb_mat_equal(B, Y)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); arb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); arb_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-spd_get_fmpz_mat.c000066400000000000000000000034371461254215100217440ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_spd_get_fmpz_mat, state) { slong iter; /* Test: construct input from an integral matrix */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong n = n_randint(state, 10); slong prec = 200; slong mag_exp = -prec - 10; slong rk = 0; fmpz_mat_t N, T; arb_mat_t A; mag_t err; int res; fmpz_mat_init(N, n, n); fmpz_mat_init(T, n, n); arb_mat_init(A, n, n); mag_init(err); while (rk < n) { fmpz_mat_randtest(N, state, 1 + n_randint(state, 50)); fmpz_mat_gram(N, N); rk = fmpz_mat_rank(N); } arb_mat_set_fmpz_mat(A, N); arb_mat_scalar_mul_2exp_si(A, A, -prec); mag_one(err); mag_mul_2exp_si(err, err, mag_exp); arb_mat_add_error_mag(A, err); res = arb_mat_spd_get_fmpz_mat(T, A, prec); if (!res || !fmpz_mat_equal(T, N)) { flint_printf("FAIL (res = %wd)\n", res); fmpz_mat_print_pretty(T); flint_printf("\n"); fmpz_mat_print_pretty(N); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(N); fmpz_mat_clear(T); arb_mat_clear(A); mag_clear(err); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-spd_inv.c000066400000000000000000000107171461254215100200630ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif TEST_FUNCTION_START(arb_mat_spd_inv, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, Qinv; arb_mat_t A, Ainv; slong n, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(Qinv, n, n); arb_mat_init(A, n, n); arb_mat_init(Ainv, n, n); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); q_invertible = fmpq_mat_inv(Qinv, Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_spd_inv(Ainv, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_spd_inv(Ainv, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(Ainv, Qinv)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qinv = \n"); fmpq_mat_print(Qinv); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = arb_mat_spd_inv(A, A, prec); if (!arb_mat_equal(A, Ainv) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Ainv = \n"); arb_mat_printd(Ainv, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(Qinv); arb_mat_clear(A); arb_mat_clear(Ainv); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-spd_lll_reduce.c000066400000000000000000000040021461254215100213670ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_spd_lll_reduce, state) { slong iter; /* Test: result satisfies arb_mat_spd_is_lll_reduced; U is I if starting matrix was reduced */ for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong g = 1 + n_randint(state, 4); slong prec = 200 + n_randint(state, 500); slong mag_bits = 1 + n_randint(state, 5); slong tol_exp = -10 - n_randint(state, 20); arb_mat_t M; arb_mat_t R; arb_mat_t T; fmpz_mat_t U; arb_mat_init(M, g, g); arb_mat_init(R, g, g); arb_mat_init(T, g, g); fmpz_mat_init(U, g, g); arb_mat_randtest_spd(M, state, prec, mag_bits); arb_mat_spd_lll_reduce(U, M, prec); arb_mat_set_fmpz_mat(T, U); arb_mat_mul(R, T, M, prec); arb_mat_transpose(T, T); arb_mat_mul(R, R, T, prec); if (!arb_mat_spd_is_lll_reduced(R, tol_exp, prec)) { flint_printf("FAIL (reduction)\n"); arb_mat_printd(M, 10); arb_mat_printd(R, 10); fmpz_mat_print_pretty(U); flint_printf("\n"); flint_abort(); } if (arb_mat_spd_is_lll_reduced(M, tol_exp, prec) && !fmpz_mat_is_one(U)) { flint_printf("FAIL (identity)\n"); arb_mat_printd(M, 10); fmpz_mat_print_pretty(U); flint_printf("\n"); } arb_mat_clear(M); arb_mat_clear(R); arb_mat_clear(T); fmpz_mat_clear(U); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-spd_solve.c000066400000000000000000000123051461254215100204120ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" /* Defined in t-cho.c, t-inv_cho_precomp.c, t-inv_ldl_precomp.c, t-ldl.c, t-solve_cho_precomp.c, t-solve_ldl_precomp.c, t-spd_inv.c, t-spd_solve.c */ #ifndef _fmpq_mat_randtest_positive_semidefinite #define _fmpq_mat_randtest_positive_semidefinite _fmpq_mat_randtest_positive_semidefinite void _fmpq_mat_randtest_positive_semidefinite(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong n; fmpq_mat_t R, RT; if (!fmpq_mat_is_square(mat)) flint_abort(); /* assert */ n = fmpq_mat_nrows(mat); fmpq_mat_init(R, n, n); fmpq_mat_init(RT, n, n); fmpq_mat_randtest(R, state, bits); fmpq_mat_transpose(RT, R); fmpq_mat_mul(mat, R, RT); fmpq_mat_clear(R); fmpq_mat_clear(RT); } #endif TEST_FUNCTION_START(arb_mat_spd_solve, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q, QX, QB; arb_mat_t A, X, B; slong n, m, qbits, prec; int q_invertible, r_invertible, r_invertible2; n = n_randint(state, 8); m = n_randint(state, 8); qbits = 1 + n_randint(state, 30); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_mat_init(QX, n, m); fmpq_mat_init(QB, n, m); arb_mat_init(A, n, n); arb_mat_init(X, n, m); arb_mat_init(B, n, m); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); fmpq_mat_randtest(QB, state, qbits); q_invertible = fmpq_mat_solve_fraction_free(QX, Q, QB); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_spd_solve(X, A, B, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_set_fmpq_mat(B, QB, prec); r_invertible = arb_mat_spd_solve(X, A, B, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_abort(); } prec *= 2; } } if (!arb_mat_contains_fmpq_mat(X, QX)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n"); flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ r_invertible2 = arb_mat_spd_solve(B, A, B, prec); if (!arb_mat_equal(X, B) || r_invertible != r_invertible2) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_mat_clear(Q); fmpq_mat_clear(QB); fmpq_mat_clear(QX); arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-sqr.c000066400000000000000000000040161461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_sqr, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong n, qbits1, rbits1, rbits2; fmpq_mat_t A, B; arb_mat_t a, b, c; qbits1 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); n = n_randint(state, 10); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); arb_mat_init(a, n, n); arb_mat_init(b, n, n); arb_mat_init(c, n, n); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_mul(B, A, A); arb_mat_set_fmpq_mat(a, A, rbits1); arb_mat_sqr(b, a, rbits2); if (!arb_mat_contains_fmpq_mat(b, B)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, bits2 = %wd\n", n, rbits2); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_mat_printd(b, 15); flint_printf("\n\n"); flint_abort(); } /* test aliasing */ arb_mat_set(c, a); arb_mat_sqr(c, c, rbits2); if (!arb_mat_equal(c, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-stirling.c000066400000000000000000000031731461254215100202520ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "arb_mat.h" #include "arith.h" TEST_FUNCTION_START(arb_mat_stirling, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { arb_mat_t A; fmpz_mat_t B; slong n, m, prec; n = n_randint(state, 10); m = n_randint(state, 10); prec = 2 + n_randint(state, 200); arb_mat_init(A, n, m); fmpz_mat_init(B, n, m); arb_mat_randtest(A, state, 100, 10); arb_mat_stirling(A, 0, prec); arith_stirling_matrix_1u(B); if (!arb_mat_contains_fmpz_mat(A, B)) { flint_printf("FAIL: containment (0)\n"); flint_abort(); } arb_mat_stirling(A, 1, prec); arith_stirling_matrix_1(B); if (!arb_mat_contains_fmpz_mat(A, B)) { flint_printf("FAIL: containment (1)\n"); flint_abort(); } arb_mat_stirling(A, 2, prec); arith_stirling_matrix_2(B); if (!arb_mat_contains_fmpz_mat(A, B)) { flint_printf("FAIL: containment (2)\n"); flint_abort(); } arb_mat_clear(A); fmpz_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-trace.c000066400000000000000000000071711461254215100175170ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_trace, state) { slong iter; /* check that the arb trace contains the fmpq trace */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_mat_t Q; fmpq_t Qtrace; arb_mat_t A; arb_t Atrace; slong n, qbits, prec; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 200); fmpq_mat_init(Q, n, n); fmpq_init(Qtrace); arb_mat_init(A, n, n); arb_init(Atrace); fmpq_mat_randtest(Q, state, qbits); fmpq_mat_trace(Qtrace, Q); arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_trace(Atrace, A, prec); if (!arb_contains_fmpq(Atrace, Qtrace)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("Qtrace = \n"); fmpq_print(Qtrace); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("Atrace = \n"); arb_printd(Atrace, 15); flint_printf("\n\n"); flint_printf("Atrace = \n"); arb_print(Atrace); flint_printf("\n\n"); flint_abort(); } fmpq_mat_clear(Q); fmpq_clear(Qtrace); arb_mat_clear(A); arb_clear(Atrace); } /* check trace(A*B) = trace(B*A) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, prec; arb_mat_t a, b, ab, ba; arb_t trab, trba; prec = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); arb_mat_init(a, m, n); arb_mat_init(b, n, m); arb_mat_init(ab, m, m); arb_mat_init(ba, n, n); arb_init(trab); arb_init(trba); arb_mat_randtest(a, state, 2 + n_randint(state, 100), 10); arb_mat_randtest(b, state, 2 + n_randint(state, 100), 10); arb_mat_mul(ab, a, b, prec); arb_mat_mul(ba, b, a, prec); arb_mat_trace(trab, ab, prec); arb_mat_trace(trba, ba, prec); if (!arb_overlaps(trab, trba)) { flint_printf("FAIL (overlap, iter = %wd)\n", iter); flint_printf("m = %wd, n = %wd, prec = %wd\n", m, n, prec); flint_printf("\n"); flint_printf("a = \n"); arb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = \n"); arb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("ab = \n"); arb_mat_printd(ab, 15); flint_printf("\n\n"); flint_printf("ba = \n"); arb_mat_printd(ba, 15); flint_printf("\n\n"); flint_printf("trace(ab) = \n"); arb_printd(trab, 15); flint_printf("\n\n"); flint_printf("trace(ba) = \n"); arb_printd(trba, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(trab); arb_clear(trba); arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(ab); arb_mat_clear(ba); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-transpose.c000066400000000000000000000031521461254215100204320ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_transpose, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n; arb_mat_t a, b, c; m = n_randint(state, 10); n = n_randint(state, 10); arb_mat_init(a, m, n); arb_mat_init(b, n, m); arb_mat_init(c, m, n); arb_mat_randtest(a, state, 2 + n_randint(state, 100), 10); arb_mat_randtest(b, state, 2 + n_randint(state, 100), 10); arb_mat_randtest(c, state, 2 + n_randint(state, 100), 10); arb_mat_transpose(b, a); arb_mat_transpose(c, b); if (!arb_mat_equal(c, a)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd\n", m, n); flint_abort(); } if (arb_mat_nrows(a) == arb_mat_ncols(a)) { arb_mat_transpose(c, a); arb_mat_transpose(a, a); if (!arb_mat_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } } arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/test/t-vector_mul.c000066400000000000000000000033121461254215100205710ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_mat.h" TEST_FUNCTION_START(arb_mat_vector_mul, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { slong nrow = n_randint(state, 10); slong ncol = n_randint(state, 10); slong bits = n_randint(state, 10); slong prec = 100 + n_randint(state, 200); arb_mat_t A, B; arb_ptr v, res, t; slong k; arb_mat_init(A, nrow, ncol); arb_mat_init(B, ncol, nrow); v = _arb_vec_init(ncol); res = _arb_vec_init(nrow); t = _arb_vec_init(nrow); arb_mat_randtest(A, state, prec, bits); for (k = 0; k < ncol; k++) { arb_randtest_precise(&v[k], state, prec, bits); } /* Test: should be equal for transpose */ arb_mat_vector_mul_col(res, A, v, prec); arb_mat_transpose(B, A); arb_mat_vector_mul_row(t, v, B, prec); if (!_arb_vec_overlaps(res, t, nrow)) { flint_printf("FAIL\n"); _arb_vec_printd(res, nrow, 5); _arb_vec_printd(t, nrow, 5); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); _arb_vec_clear(v, ncol); _arb_vec_clear(res, nrow); _arb_vec_clear(t, nrow); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_mat/trace.c000066400000000000000000000015361461254215100162760ustar00rootroot00000000000000/* Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_trace(arb_t trace, const arb_mat_t mat, slong prec) { slong i; if (!arb_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "arb_mat_trace: a square matrix is required!\n"); } if (arb_mat_is_empty(mat)) { arb_zero(trace); return; } arb_set(trace, arb_mat_entry(mat, 0, 0)); for (i = 1; i < arb_mat_nrows(mat); i++) { arb_add(trace, trace, arb_mat_entry(mat, i, i), prec); } } flint-3.1.3/src/arb_mat/transpose.c000066400000000000000000000023271461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_transpose(arb_mat_t B, const arb_mat_t A) { slong i, j; if (arb_mat_nrows(B) != arb_mat_ncols(A) || arb_mat_ncols(B) != arb_mat_nrows(A)) { flint_throw(FLINT_ERROR, "Exception (arb_mat_transpose). Incompatible dimensions.\n"); } if (arb_mat_is_empty(A)) return; if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < arb_mat_nrows(A) - 1; i++) { for (j = i + 1; j < arb_mat_ncols(A); j++) { arb_swap(arb_mat_entry(A, i, j), arb_mat_entry(A, j, i)); } } } else /* Not aliased; general case */ { for (i = 0; i < arb_mat_nrows(B); i++) for (j = 0; j < arb_mat_ncols(B); j++) arb_set(arb_mat_entry(B, i, j), arb_mat_entry(A, j, i)); } } flint-3.1.3/src/arb_mat/vector_mul.c000066400000000000000000000036061461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void _arb_mat_vector_mul_row(arb_ptr res, arb_srcptr v, const arb_mat_t A, slong prec) { slong r = arb_mat_nrows(A); slong c = arb_mat_ncols(A); arb_ptr tmp; slong k, j; if (arb_mat_is_empty(A)) { _arb_vec_zero(res, c); } else { tmp = flint_malloc(r * sizeof(arb_struct)); for (k = 0; k < c; k++) { for (j = 0; j < r; j++) { tmp[j] = *arb_mat_entry(A, j, k); } arb_dot(&res[k], NULL, 0, tmp, 1, v, 1, r, prec); } flint_free(tmp); } } void arb_mat_vector_mul_row(arb_ptr res, arb_srcptr v, const arb_mat_t A, slong prec) { slong c = arb_mat_ncols(A); arb_ptr aux; aux = _arb_vec_init(c); _arb_mat_vector_mul_row(aux, v, A, prec); _arb_vec_set(res, aux, c); _arb_vec_clear(aux, c); } void _arb_mat_vector_mul_col(arb_ptr res, const arb_mat_t A, arb_srcptr v, slong prec) { slong r = arb_mat_nrows(A); slong c = arb_mat_ncols(A); slong k; if (arb_mat_is_empty(A)) { _arb_vec_zero(res, r); } else { for (k = 0; k < r; k++) { arb_dot(&res[k], NULL, 0, A->rows[k], 1, v, 1, c, prec); } } } void arb_mat_vector_mul_col(arb_ptr res, const arb_mat_t A, arb_srcptr v, slong prec) { slong r = arb_mat_nrows(A); arb_ptr aux; aux = _arb_vec_init(r); _arb_mat_vector_mul_col(aux, A, v, prec); _arb_vec_set(res, aux, r); _arb_vec_clear(aux, r); } flint-3.1.3/src/arb_mat/window_init.c000066400000000000000000000013651461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_window_init(arb_mat_t window, const arb_mat_t mat, slong r1, slong c1, slong r2, slong c2) { slong i; window->entries = NULL; window->rows = flint_malloc((r2 - r1) * sizeof(arb_ptr)); for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; window->r = r2 - r1; window->c = c2 - c1; } flint-3.1.3/src/arb_mat/zero.c000066400000000000000000000011311461254215100161460ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_mat.h" void arb_mat_zero(arb_mat_t mat) { slong i, j; for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) arb_zero(arb_mat_entry(mat, i, j)); } flint-3.1.3/src/arb_poly.h000066400000000000000000000625111461254215100154070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_POLY_H #define ARB_POLY_H #ifdef ARB_POLY_INLINES_C #define ARB_POLY_INLINE #else #define ARB_POLY_INLINE static inline #endif #include "fmpq_types.h" #include "arb.h" #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif /* Memory management */ void arb_poly_init(arb_poly_t poly); void arb_poly_init2(arb_poly_t poly, slong len); void arb_poly_clear(arb_poly_t poly); void arb_poly_fit_length(arb_poly_t poly, slong len); void _arb_poly_set_length(arb_poly_t poly, slong len); void _arb_poly_normalise(arb_poly_t poly); ARB_POLY_INLINE void arb_poly_swap(arb_poly_t poly1, arb_poly_t poly2) { FLINT_SWAP(arb_poly_struct, *poly1, *poly2); } void arb_poly_set(arb_poly_t poly, const arb_poly_t src); void arb_poly_set_round(arb_poly_t poly, const arb_poly_t src, slong prec); void arb_poly_set_trunc(arb_poly_t res, const arb_poly_t poly, slong n); void arb_poly_set_trunc_round(arb_poly_t res, const arb_poly_t poly, slong n, slong prec); /* Basic manipulation */ ARB_POLY_INLINE slong arb_poly_length(const arb_poly_t poly) { return poly->length; } ARB_POLY_INLINE slong arb_poly_degree(const arb_poly_t poly) { return poly->length - 1; } slong arb_poly_valuation(const arb_poly_t poly); ARB_POLY_INLINE int arb_poly_is_zero(const arb_poly_t z) { return arb_poly_length(z) == 0; } ARB_POLY_INLINE int arb_poly_is_one(const arb_poly_t z) { return (arb_poly_length(z) == 1) && arb_is_one(z->coeffs); } ARB_POLY_INLINE int arb_poly_is_x(const arb_poly_t z) { return (arb_poly_length(z) == 2) && arb_is_zero(z->coeffs) && arb_is_one(z->coeffs + 1); } ARB_POLY_INLINE void arb_poly_zero(arb_poly_t poly) { poly->length = 0; } ARB_POLY_INLINE void arb_poly_one(arb_poly_t poly) { arb_poly_fit_length(poly, 1); arb_one(poly->coeffs); _arb_poly_set_length(poly, 1); } void arb_poly_set_coeff_si(arb_poly_t poly, slong n, slong x); void arb_poly_set_coeff_arb(arb_poly_t poly, slong n, const arb_t x); void arb_poly_get_coeff_arb(arb_t x, const arb_poly_t poly, slong n); #define arb_poly_get_coeff_ptr(poly, n) \ ((n) < (poly)->length ? (poly)->coeffs + (n) : NULL) void _arb_poly_reverse(arb_ptr res, arb_srcptr poly, slong len, slong n); void _arb_poly_shift_right(arb_ptr res, arb_srcptr poly, slong len, slong n); void arb_poly_shift_right(arb_poly_t res, const arb_poly_t poly, slong n); void _arb_poly_shift_left(arb_ptr res, arb_srcptr poly, slong len, slong n); void arb_poly_shift_left(arb_poly_t res, const arb_poly_t poly, slong n); ARB_POLY_INLINE void arb_poly_truncate(arb_poly_t poly, slong newlen) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) arb_zero(poly->coeffs + i); poly->length = newlen; _arb_poly_normalise(poly); } } /* Conversions */ void arb_poly_set_fmpz_poly(arb_poly_t poly, const fmpz_poly_t src, slong prec); void arb_poly_set_fmpq_poly(arb_poly_t poly, const fmpq_poly_t src, slong prec); ARB_POLY_INLINE void arb_poly_set_arb(arb_poly_t poly, const arb_t c) { arb_poly_fit_length(poly, 1); arb_set(poly->coeffs, c); _arb_poly_set_length(poly, !arb_is_zero(poly->coeffs)); } void arb_poly_set_si(arb_poly_t poly, slong c); int arb_poly_get_unique_fmpz_poly(fmpz_poly_t res, const arb_poly_t src); /* Comparisons */ int arb_poly_contains(const arb_poly_t poly1, const arb_poly_t poly2); int arb_poly_contains_fmpz_poly(const arb_poly_t poly1, const fmpz_poly_t poly2); int arb_poly_contains_fmpq_poly(const arb_poly_t poly1, const fmpq_poly_t poly2); int arb_poly_equal(const arb_poly_t A, const arb_poly_t B); int _arb_poly_overlaps(arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2); int arb_poly_overlaps(const arb_poly_t poly1, const arb_poly_t poly2); /* Bounds */ void _arb_poly_majorant(arb_ptr res, arb_srcptr vec, slong len, slong prec); void arb_poly_majorant(arb_poly_t res, const arb_poly_t poly, slong prec); /* IO */ #ifdef FLINT_HAVE_FILE void arb_poly_fprintd(FILE * file, const arb_poly_t poly, slong digits); #endif void arb_poly_printd(const arb_poly_t poly, slong digits); /* Random generation */ void arb_poly_randtest(arb_poly_t poly, flint_rand_t state, slong len, slong prec, slong mag_bits); /* Arithmetic */ void _arb_poly_add(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec); void arb_poly_add(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec); void arb_poly_add_si(arb_poly_t res, const arb_poly_t poly, slong c, slong prec); void _arb_poly_sub(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec); void arb_poly_sub(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec); void arb_poly_add_series(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong len, slong prec); void arb_poly_sub_series(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong len, slong prec); ARB_POLY_INLINE void arb_poly_neg(arb_poly_t res, const arb_poly_t poly) { arb_poly_fit_length(res, poly->length); _arb_vec_neg(res->coeffs, poly->coeffs, poly->length); _arb_poly_set_length(res, poly->length); } ARB_POLY_INLINE void arb_poly_scalar_mul_2exp_si(arb_poly_t res, const arb_poly_t poly, slong c) { arb_poly_fit_length(res, poly->length); _arb_vec_scalar_mul_2exp_si(res->coeffs, poly->coeffs, poly->length, c); _arb_poly_set_length(res, poly->length); } ARB_POLY_INLINE void arb_poly_scalar_mul(arb_poly_t res, const arb_poly_t poly, const arb_t c, slong prec) { arb_poly_fit_length(res, poly->length); _arb_vec_scalar_mul(res->coeffs, poly->coeffs, poly->length, c, prec); _arb_poly_set_length(res, poly->length); _arb_poly_normalise(res); } ARB_POLY_INLINE void arb_poly_scalar_div(arb_poly_t res, const arb_poly_t poly, const arb_t c, slong prec) { arb_poly_fit_length(res, poly->length); _arb_vec_scalar_div(res->coeffs, poly->coeffs, poly->length, c, prec); _arb_poly_set_length(res, poly->length); _arb_poly_normalise(res); } void _arb_poly_mullow_ztrunc(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, slong prec); void arb_poly_mullow_ztrunc(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec); void _arb_poly_mullow_classical(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, slong prec); void arb_poly_mullow_classical(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec); void _arb_poly_mullow_block(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong n, slong prec); void arb_poly_mullow_block(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong len, slong prec); void _arb_poly_mullow(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong n, slong prec); void arb_poly_mullow(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong len, slong prec); void _arb_poly_mul(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec); void arb_poly_mul(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec); ARB_POLY_INLINE void _arb_poly_mul_monic(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec) { if (len1 + len2 - 2 > 0) _arb_poly_mullow(res, poly1, len1, poly2, len2, len1 + len2 - 2, prec); arb_one(res + len1 + len2 - 2); } void _arb_poly_inv_series(arb_ptr Qinv, arb_srcptr Q, slong Qlen, slong len, slong prec); void arb_poly_inv_series(arb_poly_t Qinv, const arb_poly_t Q, slong n, slong prec); void _arb_poly_div_series(arb_ptr Q, arb_srcptr A, slong Alen, arb_srcptr B, slong Blen, slong n, slong prec); void arb_poly_div_series(arb_poly_t Q, const arb_poly_t A, const arb_poly_t B, slong n, slong prec); void _arb_poly_div(arb_ptr Q, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec); void _arb_poly_divrem(arb_ptr Q, arb_ptr R, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec); void _arb_poly_rem(arb_ptr R, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec); int arb_poly_divrem(arb_poly_t Q, arb_poly_t R, const arb_poly_t A, const arb_poly_t B, slong prec); void _arb_poly_div_root(arb_ptr Q, arb_t R, arb_srcptr A, slong len, const arb_t c, slong prec); /* Product trees */ void _arb_poly_product_roots(arb_ptr poly, arb_srcptr xs, slong n, slong prec); void arb_poly_product_roots(arb_poly_t poly, arb_srcptr xs, slong n, slong prec); void _arb_poly_product_roots_complex(arb_ptr poly, arb_srcptr r, slong rn, acb_srcptr c, slong cn, slong prec); void arb_poly_product_roots_complex(arb_poly_t poly, arb_srcptr r, slong rn, acb_srcptr c, slong cn, slong prec); arb_ptr * _arb_poly_tree_alloc(slong len); void _arb_poly_tree_free(arb_ptr * tree, slong len); void _arb_poly_tree_build(arb_ptr * tree, arb_srcptr roots, slong len, slong prec); /* Composition */ void _arb_poly_taylor_shift(arb_ptr poly, const arb_t c, slong n, slong prec); void arb_poly_taylor_shift(arb_poly_t g, const arb_poly_t f, const arb_t c, slong prec); void _arb_poly_compose(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec); void arb_poly_compose(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec); void _arb_poly_compose_series(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, slong prec); void arb_poly_compose_series(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec); /* Reversion */ void _arb_poly_revert_series(arb_ptr Qinv, arb_srcptr Q, slong Qlen, slong n, slong prec); void arb_poly_revert_series(arb_poly_t Qinv, const arb_poly_t Q, slong n, slong prec); /* Evaluation and interpolation */ void _arb_poly_evaluate_horner(arb_t res, arb_srcptr f, slong len, const arb_t a, slong prec); void arb_poly_evaluate_horner(arb_t res, const arb_poly_t f, const arb_t a, slong prec); void _arb_poly_evaluate_rectangular(arb_t y, arb_srcptr poly, slong len, const arb_t x, slong prec); void arb_poly_evaluate_rectangular(arb_t res, const arb_poly_t f, const arb_t a, slong prec); void _arb_poly_evaluate(arb_t res, arb_srcptr f, slong len, const arb_t a, slong prec); void arb_poly_evaluate(arb_t res, const arb_poly_t f, const arb_t a, slong prec); void _arb_poly_evaluate2_horner(arb_t y, arb_t z, arb_srcptr f, slong len, const arb_t x, slong prec); void arb_poly_evaluate2_horner(arb_t y, arb_t z, const arb_poly_t f, const arb_t x, slong prec); void _arb_poly_evaluate2_rectangular(arb_t y, arb_t z, arb_srcptr f, slong len, const arb_t x, slong prec); void arb_poly_evaluate2_rectangular(arb_t y, arb_t z, const arb_poly_t f, const arb_t x, slong prec); void _arb_poly_evaluate2(arb_t y, arb_t z, arb_srcptr f, slong len, const arb_t x, slong prec); void arb_poly_evaluate2(arb_t y, arb_t z, const arb_poly_t f, const arb_t x, slong prec); void _arb_poly_evaluate_vec_iter(arb_ptr ys, arb_srcptr poly, slong plen, arb_srcptr xs, slong n, slong prec); void arb_poly_evaluate_vec_iter(arb_ptr ys, const arb_poly_t poly, arb_srcptr xs, slong n, slong prec); void _arb_poly_evaluate_vec_fast_precomp(arb_ptr vs, arb_srcptr poly, slong plen, arb_ptr * tree, slong len, slong prec); void _arb_poly_evaluate_vec_fast(arb_ptr ys, arb_srcptr poly, slong plen, arb_srcptr xs, slong n, slong prec); void arb_poly_evaluate_vec_fast(arb_ptr ys, const arb_poly_t poly, arb_srcptr xs, slong n, slong prec); void _arb_poly_interpolate_newton(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec); void arb_poly_interpolate_newton(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec); void _arb_poly_interpolate_barycentric(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec); void arb_poly_interpolate_barycentric(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec); void _arb_poly_interpolation_weights(arb_ptr w, arb_ptr * tree, slong len, slong prec); void _arb_poly_interpolate_fast_precomp(arb_ptr poly, arb_srcptr ys, arb_ptr * tree, arb_srcptr weights, slong len, slong prec); void _arb_poly_interpolate_fast(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong len, slong prec); void arb_poly_interpolate_fast(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec); /* Derivative and integral */ void _arb_poly_derivative(arb_ptr res, arb_srcptr poly, slong len, slong prec); void arb_poly_derivative(arb_poly_t res, const arb_poly_t poly, slong prec); void _arb_poly_nth_derivative(arb_ptr res, arb_srcptr poly, ulong n, slong len, slong prec); void arb_poly_nth_derivative(arb_poly_t res, const arb_poly_t poly, ulong n, slong prec); void _arb_poly_integral(arb_ptr res, arb_srcptr poly, slong len, slong prec); void arb_poly_integral(arb_poly_t res, const arb_poly_t poly, slong prec); /* Transforms */ void arb_poly_borel_transform(arb_poly_t res, const arb_poly_t poly, slong prec); void _arb_poly_borel_transform(arb_ptr res, arb_srcptr poly, slong len, slong prec); void arb_poly_inv_borel_transform(arb_poly_t res, const arb_poly_t poly, slong prec); void _arb_poly_inv_borel_transform(arb_ptr res, arb_srcptr poly, slong len, slong prec); void _arb_poly_binomial_transform_basecase(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec); void arb_poly_binomial_transform_basecase(arb_poly_t b, const arb_poly_t a, slong len, slong prec); void _arb_poly_binomial_transform_convolution(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec); void arb_poly_binomial_transform_convolution(arb_poly_t b, const arb_poly_t a, slong len, slong prec); void _arb_poly_binomial_transform(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec); void arb_poly_binomial_transform(arb_poly_t b, const arb_poly_t a, slong len, slong prec); void _arb_poly_graeffe_transform(arb_ptr b, arb_srcptr a, slong len, slong prec); void arb_poly_graeffe_transform(arb_poly_t b, const arb_poly_t a, slong prec); /* Special functions */ void _arb_poly_pow_ui_trunc_binexp(arb_ptr res, arb_srcptr f, slong flen, ulong exp, slong len, slong prec); void arb_poly_pow_ui_trunc_binexp(arb_poly_t res, const arb_poly_t poly, ulong exp, slong len, slong prec); void _arb_poly_pow_ui(arb_ptr res, arb_srcptr f, slong flen, ulong exp, slong prec); void arb_poly_pow_ui(arb_poly_t res, const arb_poly_t poly, ulong exp, slong prec); void _arb_poly_pow_series(arb_ptr h, arb_srcptr f, slong flen, arb_srcptr g, slong glen, slong len, slong prec); void arb_poly_pow_series(arb_poly_t h, const arb_poly_t f, const arb_poly_t g, slong len, slong prec); void _arb_poly_pow_arb_series(arb_ptr h, arb_srcptr f, slong flen, const arb_t g, slong len, slong prec); void arb_poly_pow_arb_series(arb_poly_t h, const arb_poly_t f, const arb_t g, slong len, slong prec); void _arb_poly_binomial_pow_arb_series(arb_ptr h, arb_srcptr f, slong flen, const arb_t g, slong len, slong prec); void _arb_poly_rsqrt_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_rsqrt_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_sqrt_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_sqrt_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_log_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec); void arb_poly_log_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_log1p_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec); void arb_poly_log1p_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_atan_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec); void arb_poly_atan_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_asin_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec); void arb_poly_asin_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_acos_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec); void arb_poly_acos_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_exp_series_basecase(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_exp_series_basecase(arb_poly_t f, const arb_poly_t h, slong n, slong prec); void _arb_poly_exp_series(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_exp_series(arb_poly_t f, const arb_poly_t h, slong n, slong prec); void _arb_poly_sinh_cosh_series_basecase(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sinh_cosh_series_basecase(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec); void _arb_poly_sinh_cosh_series_exponential(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sinh_cosh_series_exponential(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec); void _arb_poly_sinh_cosh_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sinh_cosh_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec); void _arb_poly_sinh_series(arb_ptr s, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sinh_series(arb_poly_t s, const arb_poly_t h, slong n, slong prec); void _arb_poly_cosh_series(arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_cosh_series(arb_poly_t c, const arb_poly_t h, slong n, slong prec); void _arb_poly_sin_cos_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_sin_cos_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec); void _arb_poly_sin_cos_pi_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_sin_cos_pi_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec); void _arb_poly_sin_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sin_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_cos_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_cos_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_sin_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sin_pi_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_cos_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_cos_pi_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_cot_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_cot_pi_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_tan_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_tan_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_sinc_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sinc_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_sinc_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec); void arb_poly_sinc_pi_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec); void _arb_poly_evaluate_acb_horner(acb_t res, arb_srcptr f, slong len, const acb_t x, slong prec); void arb_poly_evaluate_acb_horner(acb_t res, const arb_poly_t f, const acb_t a, slong prec); void _arb_poly_evaluate_acb_rectangular(acb_t y, arb_srcptr poly, slong len, const acb_t x, slong prec); void arb_poly_evaluate_acb_rectangular(acb_t res, const arb_poly_t f, const acb_t a, slong prec); void _arb_poly_evaluate_acb(acb_t res, arb_srcptr f, slong len, const acb_t x, slong prec); void arb_poly_evaluate_acb(acb_t res, const arb_poly_t f, const acb_t a, slong prec); void _arb_poly_evaluate2_acb_horner(acb_t y, acb_t z, arb_srcptr f, slong len, const acb_t x, slong prec); void arb_poly_evaluate2_acb_horner(acb_t y, acb_t z, const arb_poly_t f, const acb_t x, slong prec); void _arb_poly_evaluate2_acb_rectangular(acb_t y, acb_t z, arb_srcptr f, slong len, const acb_t x, slong prec); void arb_poly_evaluate2_acb_rectangular(acb_t y, acb_t z, const arb_poly_t f, const acb_t x, slong prec); void _arb_poly_evaluate2_acb(acb_t y, acb_t z, arb_srcptr f, slong len, const acb_t x, slong prec); void arb_poly_evaluate2_acb(acb_t y, acb_t z, const arb_poly_t f, const acb_t x, slong prec); void _arb_poly_lambertw_series(arb_ptr res, arb_srcptr z, slong zlen, int flags, slong len, slong prec); void arb_poly_lambertw_series(arb_poly_t res, const arb_poly_t z, int flags, slong len, slong prec); void _arb_poly_gamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_gamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_rgamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_rgamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_lgamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_lgamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_digamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_digamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec); void _arb_poly_rising_ui_series(arb_ptr res, arb_srcptr f, slong flen, ulong r, slong trunc, slong prec); void arb_poly_rising_ui_series(arb_poly_t res, const arb_poly_t f, ulong r, slong trunc, slong prec); void _arb_poly_zeta_series(arb_ptr res, arb_srcptr h, slong hlen, const arb_t a, int deflate, slong len, slong prec); void arb_poly_zeta_series(arb_poly_t res, const arb_poly_t f, const arb_t a, int deflate, slong n, slong prec); void _arb_poly_riemann_siegel_theta_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_riemann_siegel_theta_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec); void _arb_poly_riemann_siegel_z_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec); void arb_poly_riemann_siegel_z_series(arb_poly_t res, const arb_poly_t h, slong n, slong prec); slong _arb_poly_swinnerton_dyer_ui_prec(ulong n); void _arb_poly_swinnerton_dyer_ui(arb_ptr T, ulong n, slong trunc, slong prec); void arb_poly_swinnerton_dyer_ui(arb_poly_t poly, ulong n, slong prec); /* Root-finding */ void _arb_poly_newton_convergence_factor(arf_t convergence_factor, arb_srcptr poly, slong len, const arb_t convergence_interval, slong prec); int _arb_poly_newton_step(arb_t xnew, arb_srcptr poly, slong len, const arb_t x, const arb_t convergence_interval, const arf_t convergence_factor, slong prec); void _arb_poly_newton_refine_root(arb_t r, arb_srcptr poly, slong len, const arb_t start, const arb_t convergence_interval, const arf_t convergence_factor, slong eval_extra_prec, slong prec); void _arb_poly_root_bound_fujiwara(mag_t bound, arb_srcptr poly, slong len); void arb_poly_root_bound_fujiwara(mag_t bound, arb_poly_t poly); ARB_POLY_INLINE slong arb_poly_allocated_bytes(const arb_poly_t x) { return _arb_vec_allocated_bytes(x->coeffs, x->alloc); } /* Macros */ /* counts zero bits in the binary representation of e */ FLINT_FORCE_INLINE int n_zerobits(ulong e) { #if defined(__GNUC__) # if defined(_LONG_LONG_LIMB) return FLINT_BIT_COUNT(e) - __builtin_popcountll(e); # else return FLINT_BIT_COUNT(e) - __builtin_popcountl(e); # endif #else int zeros = 0; while (e > 1) { zeros += !(e & 1); e >>= 1; } return zeros; #endif } /* Computes the length of the result when raising a polynomial of length *len* to the power *exp* and truncating to length *trunc*, without overflow. Assumes poly_len >= 1. */ FLINT_FORCE_INLINE slong poly_pow_length(slong poly_len, ulong exp, slong trunc) { mp_limb_t hi, lo; umul_ppmm(hi, lo, poly_len - 1, exp); add_ssaaaa(hi, lo, hi, lo, 0, 1); if (hi != 0 || lo > (mp_limb_t) WORD_MAX) return trunc; return FLINT_MIN((slong) lo, trunc); } #ifndef NEWTON_INIT #define NEWTON_INIT(from, to) \ { \ slong __steps[FLINT_BITS], __i, __from, __to; \ __steps[__i = 0] = __to = (to); \ __from = (from); \ while (__to > __from) \ __steps[++__i] = (__to = (__to + 1) / 2); \ #define NEWTON_BASECASE(bc_to) { slong bc_to = __to; #define NEWTON_END_BASECASE } #define NEWTON_LOOP(step_from, step_to) \ { \ for (__i--; __i >= 0; __i--) \ { \ slong step_from = __steps[__i+1]; \ slong step_to = __steps[__i]; \ #define NEWTON_END_LOOP }} #define NEWTON_END } #endif #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arb_poly/000077500000000000000000000000001461254215100152315ustar00rootroot00000000000000flint-3.1.3/src/arb_poly/acos_series.c000066400000000000000000000023431461254215100176760ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_acos_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_acos_series(g, h, hlen, n, ctx) != GR_SUCCESS) _arb_vec_indeterminate(g, n); } void arb_poly_acos_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0) { if (n == 0) arb_poly_zero(g); else { arb_poly_fit_length(g, 1); arb_const_pi(g->coeffs, prec); arb_mul_2exp_si(g->coeffs, g->coeffs, -1); _arb_poly_set_length(g, 1); } return; } arb_poly_fit_length(g, n); _arb_poly_acos_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/add.c000066400000000000000000000022621461254215100161270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_add(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) arb_add(res + i, poly1 + i, poly2 + i, prec); for (i = min; i < len1; i++) arb_set_round(res + i, poly1 + i, prec); for (i = min; i < len2; i++) arb_set_round(res + i, poly2 + i, prec); } void arb_poly_add(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec) { slong max = FLINT_MAX(poly1->length, poly2->length); arb_poly_fit_length(res, max); _arb_poly_add(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); _arb_poly_set_length(res, max); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/add_series.c000066400000000000000000000015751461254215100175070ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_add_series(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong len, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; len1 = FLINT_MIN(len1, len); len2 = FLINT_MIN(len2, len); len = FLINT_MAX(len1, len2); arb_poly_fit_length(res, len); _arb_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); _arb_poly_set_length(res, len); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/add_si.c000066400000000000000000000015321461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_add_si(arb_poly_t res, const arb_poly_t x, slong y, slong prec) { slong len = x->length; if (len == 0) { arb_poly_set_si(res, y); } else { arb_poly_fit_length(res, len); arb_add_si(res->coeffs, x->coeffs, y, prec); if (res != x) _arb_vec_set(res->coeffs + 1, x->coeffs + 1, len - 1); _arb_poly_set_length(res, len); _arb_poly_normalise(res); } } flint-3.1.3/src/arb_poly/asin_series.c000066400000000000000000000020031461254215100176740ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_asin_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_asin_series(g, h, hlen, n, ctx) != GR_SUCCESS) _arb_vec_indeterminate(g, n); } void arb_poly_asin_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, n); _arb_poly_asin_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/atan_series.c000066400000000000000000000020031461254215100176650ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_atan_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_atan_series(g, h, hlen, n, ctx) != GR_SUCCESS) _arb_vec_indeterminate(g, n); } void arb_poly_atan_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, n); _arb_poly_atan_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/binomial_transform.c000066400000000000000000000024201461254215100212600ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_binomial_transform(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec) { if (alen < 10 || len < 10) _arb_poly_binomial_transform_basecase(b, a, alen, len, prec); else _arb_poly_binomial_transform_convolution(b, a, alen, len, prec); } void arb_poly_binomial_transform(arb_poly_t b, const arb_poly_t a, slong len, slong prec) { if (len == 0 || a->length == 0) { arb_poly_zero(b); return; } if (b == a) { arb_poly_t c; arb_poly_init2(c, len); _arb_poly_binomial_transform(c->coeffs, a->coeffs, a->length, len, prec); arb_poly_swap(b, c); arb_poly_clear(c); } else { arb_poly_fit_length(b, len); _arb_poly_binomial_transform(b->coeffs, a->coeffs, a->length, len, prec); } _arb_poly_set_length(b, len); _arb_poly_normalise(b); } flint-3.1.3/src/arb_poly/binomial_transform_basecase.c000066400000000000000000000031371461254215100231140ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_binomial_transform_basecase(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec) { slong n, k; fmpz_t t; fmpz_init(t); for (n = 0; n < len; n++) { arb_zero(b + n); for (k = 0; k < FLINT_MIN(n + 1, alen); k++) { if (k == 0) { fmpz_one(t); } else { fmpz_mul_si(t, t, -(n - k + 1)); fmpz_divexact_ui(t, t, k); } arb_addmul_fmpz(b + n, a + k, t, prec); } } fmpz_clear(t); } void arb_poly_binomial_transform_basecase(arb_poly_t b, const arb_poly_t a, slong len, slong prec) { if (len == 0 || a->length == 0) { arb_poly_zero(b); return; } if (b == a) { arb_poly_t c; arb_poly_init2(c, len); _arb_poly_binomial_transform_basecase(c->coeffs, a->coeffs, a->length, len, prec); arb_poly_swap(b, c); arb_poly_clear(c); } else { arb_poly_fit_length(b, len); _arb_poly_binomial_transform_basecase(b->coeffs, a->coeffs, a->length, len, prec); } _arb_poly_set_length(b, len); _arb_poly_normalise(b); } flint-3.1.3/src/arb_poly/binomial_transform_convolution.c000066400000000000000000000032141461254215100237210ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb_poly.h" void _arb_poly_binomial_transform_convolution(arb_ptr b, arb_srcptr a, slong alen, slong len, slong prec) { slong i; arb_ptr c, d; alen = FLINT_MIN(alen, len); c = _arb_vec_init(alen); d = _arb_vec_init(len); _arb_poly_borel_transform(c, a, alen, prec); for (i = 1; i < alen; i += 2) arb_neg(c + i, c + i); arb_one(d); for (i = 1; i < len; i++) arb_div_ui(d + i, d + i - 1, i, prec); _arb_poly_mullow(b, d, len, c, alen, len, prec); _arb_poly_inv_borel_transform(b, b, len, prec); _arb_vec_clear(c, alen); _arb_vec_clear(d, len); } void arb_poly_binomial_transform_convolution(arb_poly_t b, const arb_poly_t a, slong len, slong prec) { if (len == 0 || a->length == 0) { arb_poly_zero(b); return; } if (b == a) { arb_poly_t c; arb_poly_init2(c, len); _arb_poly_binomial_transform_convolution(c->coeffs, a->coeffs, a->length, len, prec); arb_poly_swap(b, c); arb_poly_clear(c); } else { arb_poly_fit_length(b, len); _arb_poly_binomial_transform_convolution(b->coeffs, a->coeffs, a->length, len, prec); } _arb_poly_set_length(b, len); _arb_poly_normalise(b); } flint-3.1.3/src/arb_poly/borel_transform.c000066400000000000000000000017541461254215100206020ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_borel_transform(arb_ptr res, arb_srcptr poly, slong len, slong prec) { slong i; arb_t t; arb_init(t); arb_one(t); for (i = 0; i < len; i++) { if (i > 1) arb_mul_ui(t, t, i, prec); arb_div(res + i, poly + i, t, prec); } arb_clear(t); } void arb_poly_borel_transform(arb_poly_t res, const arb_poly_t poly, slong prec) { arb_poly_fit_length(res, poly->length); _arb_poly_borel_transform(res->coeffs, poly->coeffs, poly->length, prec); _arb_poly_set_length(res, poly->length); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/clear.c000066400000000000000000000010671461254215100164670ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_clear(arb_poly_t poly) { slong i; for (i = 0; i < poly->alloc; i++) arb_clear(poly->coeffs + i); flint_free(poly->coeffs); } flint-3.1.3/src/arb_poly/compose.c000066400000000000000000000035301461254215100170430ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_compose(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_compose(res, poly1, len1, poly2, len2, ctx) != GR_SUCCESS) _arb_vec_indeterminate(res, (len1 - 1) * (len2 - 1) + 1); } void arb_poly_compose(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { arb_poly_zero(res); } else if (len1 == 1 || len2 == 0) { arb_poly_set_arb(res, poly1->coeffs); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { arb_poly_fit_length(res, lenr); _arb_poly_compose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); } else { arb_poly_t t; arb_poly_init2(t, lenr); _arb_poly_compose(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); arb_poly_swap(res, t); arb_poly_clear(t); } _arb_poly_set_length(res, lenr); _arb_poly_normalise(res); } } flint-3.1.3/src/arb_poly/compose_series.c000066400000000000000000000056601461254215100204230ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_compose_series(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, slong prec) { if (len2 == 1) { arb_set_round(res, poly1, prec); _arb_vec_zero(res + 1, n - 1); } else if (!_arb_vec_is_finite(poly1, len1) || !_arb_vec_is_finite(poly2, len2)) { /* find k such that the first k coefficients of both poly1 and * poly2 are finite */ slong k = 0; while (((k >= len1) || arb_is_finite(poly1 + k)) && ((k >= len2) || arb_is_finite(poly2 + k))) k += 1; if (k > 0) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); GR_MUST_SUCCEED(_gr_poly_compose_series(res, poly1, FLINT_MIN(len1, k), poly2, FLINT_MIN(len2, k), FLINT_MIN(n, k), ctx)); _arb_vec_indeterminate(res + k, n - k); } else { _arb_vec_indeterminate(res, n); } } else { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); GR_MUST_SUCCEED(_gr_poly_compose_series(res, poly1, len1, poly2, len2, n, ctx)); } } void arb_poly_compose_series(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !arb_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "arb_poly_compose_series: " "inner polynomial must have zero constant term\n"); } if (len1 == 0 || n == 0) { arb_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { arb_poly_set_arb(res, poly1->coeffs); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { arb_poly_fit_length(res, lenr); _arb_poly_compose_series(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, prec); _arb_poly_set_length(res, lenr); _arb_poly_normalise(res); } else { arb_poly_t t; arb_poly_init2(t, lenr); _arb_poly_compose_series(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, prec); _arb_poly_set_length(t, lenr); _arb_poly_normalise(t); arb_poly_swap(res, t); arb_poly_clear(t); } } flint-3.1.3/src/arb_poly/contains.c000066400000000000000000000015001461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" int arb_poly_contains(const arb_poly_t poly1, const arb_poly_t poly2) { slong i; if (poly2->length > poly1->length) return 0; for (i = 0; i < poly2->length; i++) { if (!arb_contains(poly1->coeffs + i, poly2->coeffs + i)) return 0; } for (i = poly2->length; i < poly1->length; i++) if (!arb_contains_zero(poly1->coeffs + i)) return 0; return 1; } flint-3.1.3/src/arb_poly/contains_fmpq_poly.c000066400000000000000000000017741461254215100213120ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_poly.h" #include "arb_poly.h" int arb_poly_contains_fmpq_poly(const arb_poly_t poly1, const fmpq_poly_t poly2) { slong i; fmpq_t t; if (poly2->length > poly1->length) return 0; fmpq_init(t); for (i = 0; i < poly2->length; i++) { fmpq_poly_get_coeff_fmpq(t, poly2, i); if (!arb_contains_fmpq(poly1->coeffs + i, t)) { fmpq_clear(t); return 0; } } fmpq_clear(t); for (i = poly2->length; i < poly1->length; i++) if (!arb_contains_zero(poly1->coeffs + i)) return 0; return 1; } flint-3.1.3/src/arb_poly/contains_fmpz_poly.c000066400000000000000000000015041461254215100213120ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" int arb_poly_contains_fmpz_poly(const arb_poly_t poly1, const fmpz_poly_t poly2) { slong i; if (poly2->length > poly1->length) return 0; for (i = 0; i < poly2->length; i++) if (!arb_contains_fmpz(poly1->coeffs + i, poly2->coeffs + i)) return 0; for (i = poly2->length; i < poly1->length; i++) if (!arb_contains_zero(poly1->coeffs + i)) return 0; return 1; } flint-3.1.3/src/arb_poly/cos_pi_series.c000066400000000000000000000027661461254215100202360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_cos_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_cos_pi(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); arb_sin_cos_pi(t, g, h, prec); arb_neg(t, t); arb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ arb_const_pi(t, prec); arb_mul(g + 1, g + 1, t, prec); arb_clear(t); } else { arb_ptr t = _arb_vec_init(n); _arb_poly_sin_cos_pi_series(t, g, h, hlen, n, prec); _arb_vec_clear(t, n); } } void arb_poly_cos_pi_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_one(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_cos_pi_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/cos_series.c000066400000000000000000000026351461254215100175410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_cos_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_cos(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); arb_sin_cos(t, g, h, prec); arb_neg(t, t); arb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ arb_clear(t); } else { arb_ptr t = _arb_vec_init(n); _arb_poly_sin_cos_series(t, g, h, hlen, n, prec); _arb_vec_clear(t, n); } } void arb_poly_cos_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_one(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_cos_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/cosh_series.c000066400000000000000000000026161461254215100177100ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_cosh_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_cosh(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); arb_sinh_cosh(t, g, h, prec); arb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ arb_clear(t); } else { arb_ptr t = _arb_vec_init(n); _arb_poly_sinh_cosh_series(t, g, h, hlen, n, prec); _arb_vec_clear(t, n); } } void arb_poly_cosh_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_one(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_cosh_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/cot_pi_series.c000066400000000000000000000024251461254215100202270ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_cot_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_cot_pi(g, h, prec); _arb_vec_zero(g + 1, len - 1); } else { arb_ptr t, u; t = _arb_vec_init(len); u = _arb_vec_init(len); _arb_poly_sin_cos_pi_series(t, u, h, hlen, len, prec); _arb_poly_div_series(g, u, len, t, len, len, prec); _arb_vec_clear(t, len); _arb_vec_clear(u, len); } } void arb_poly_cot_pi_series(arb_poly_t res, const arb_poly_t f, slong len, slong prec) { arb_poly_fit_length(res, len); if (f->length == 0 || len == 0) _arb_vec_indeterminate(res->coeffs, len); else _arb_poly_cot_pi_series(res->coeffs, f->coeffs, f->length, len, prec); _arb_poly_set_length(res, len); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/derivative.c000066400000000000000000000016421461254215100175420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_derivative(arb_ptr res, arb_srcptr poly, slong len, slong prec) { slong i; for (i = 1; i < len; i++) arb_mul_ui(res + i - 1, poly + i, i, prec); } void arb_poly_derivative(arb_poly_t res, const arb_poly_t poly, slong prec) { slong len = poly->length; if (len < 2) { arb_poly_zero(res); } else { arb_poly_fit_length(res, len - 1); _arb_poly_derivative(res->coeffs, poly->coeffs, len, prec); _arb_poly_set_length(res, len - 1); } } flint-3.1.3/src/arb_poly/digamma_series.c000066400000000000000000000114761461254215100203570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec); void _arb_poly_gamma_stirling_eval2(arb_ptr res, const arb_t z, slong n, slong num, int diff, slong prec); void _arb_poly_digamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong i, r, n, rflen, wp; arb_t zr; arb_ptr t, u, v; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_digamma(res, h, prec); if (arb_is_finite(res)) _arb_vec_zero(res + 1, len - 1); else _arb_vec_indeterminate(res + 1, len - 1); return; } wp = prec + FLINT_BIT_COUNT(prec); t = _arb_vec_init(len + 1); u = _arb_vec_init(len + 1); v = _arb_vec_init(len + 1); arb_init(zr); /* use zeta values at small integers */ if (arb_is_int(h) && (arf_cmpabs_ui(arb_midref(h), prec / 2) < 0)) { r = arf_get_si(arb_midref(h), ARF_RND_DOWN); if (r <= 0) { _arb_vec_indeterminate(res, len); goto cleanup; } else if (r == 1) { arb_const_euler(u, prec); arb_zeta_ui_vec(u + 1, 2, len - 1, prec); for (i = 0; i < len; i += 2) arb_neg(u + i, u + i); } else { arb_one(v); arb_one(v + 1); rflen = FLINT_MIN(len + 1, r); _arb_poly_rising_ui_series(u, v, 2, r - 1, rflen, wp); _arb_poly_derivative(v, u, rflen, wp); _arb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp); arb_const_euler(u, prec); arb_zeta_ui_vec(u + 1, 2, len - 1, prec); for (i = 0; i < len; i += 2) arb_neg(u + i, u + i); _arb_vec_add(u, u, t, len, wp); } } else { /* use Stirling series */ arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 1, wp); /* psi(x) = psi((1-x)+r) - h(1-x,r) - pi*cot(pi*x) */ if (reflect) { if (r != 0) /* otherwise t = 0 */ { arb_sub_ui(v, h, 1, wp); arb_neg(v, v); arb_one(v + 1); rflen = FLINT_MIN(len + 1, r + 1); _arb_poly_rising_ui_series(u, v, 2, r, rflen, wp); _arb_poly_derivative(v, u, rflen, wp); _arb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp); for (i = 1; i < len; i += 2) arb_neg(t + i, t + i); } arb_sub_ui(zr, h, r + 1, wp); arb_neg(zr, zr); _arb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp); for (i = 1; i < len; i += 2) arb_neg(u + i, u + i); _arb_vec_sub(u, u, t, len, wp); arb_set(t, h); arb_one(t + 1); _arb_poly_cot_pi_series(t, t, 2, len, wp); arb_const_pi(v, wp); _arb_vec_scalar_mul(t, t, len, v, wp); _arb_vec_sub(u, u, t, len, wp); } else { if (r == 0) { arb_add_ui(zr, h, r, wp); _arb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp); } else { arb_set(v, h); arb_one(v + 1); rflen = FLINT_MIN(len + 1, r + 1); _arb_poly_rising_ui_series(u, v, 2, r, rflen, wp); _arb_poly_derivative(v, u, rflen, wp); _arb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp); arb_add_ui(zr, h, r, wp); _arb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp); _arb_vec_sub(u, u, t, len, wp); } } } /* compose with nonconstant part */ arb_zero(t); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, u, len, t, hlen, len, prec); cleanup: arb_clear(zr); _arb_vec_clear(t, len + 1); _arb_vec_clear(u, len + 1); _arb_vec_clear(v, len + 1); } void arb_poly_digamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { arb_poly_fit_length(res, n); if (f->length == 0 || n == 0) _arb_vec_indeterminate(res->coeffs, n); else _arb_poly_digamma_series(res->coeffs, f->coeffs, f->length, n, prec); _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/div_root.c000066400000000000000000000021341461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_div_root(arb_ptr Q, arb_t R, arb_srcptr A, slong len, const arb_t c, slong prec) { arb_t r, t; slong i; if (len < 2) { arb_zero(R); return; } arb_init(r); arb_init(t); arb_set(t, A + len - 2); arb_set(Q + len - 2, A + len - 1); arb_set(r, Q + len - 2); /* TODO: avoid the extra assignments (but still support aliasing) */ for (i = len - 2; i > 0; i--) { arb_mul(r, r, c, prec); arb_add(r, r, t, prec); arb_set(t, A + i - 1); arb_set(Q + i - 1, r); } arb_mul(r, r, c, prec); arb_add(R, r, t, prec); arb_clear(r); arb_clear(t); } flint-3.1.3/src/arb_poly/div_series.c000066400000000000000000000053371461254215100175410ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_div_series(arb_ptr Q, arb_srcptr A, slong Alen, arb_srcptr B, slong Blen, slong n, slong prec) { Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (Blen == 1) { _arb_vec_scalar_div(Q, A, Alen, B, prec); _arb_vec_zero(Q + Alen, n - Alen); } else if (n == 2) { if (Alen == 1) { arb_div(Q, A, B, prec); arb_div(Q + 1, Q, B, prec); arb_mul(Q + 1, Q + 1, B + 1, prec); arb_neg(Q + 1, Q + 1); } else { arb_div(Q, A, B, prec); arb_mul(Q + 1, Q, B + 1, prec); arb_sub(Q + 1, A + 1, Q + 1, prec); arb_div(Q + 1, Q + 1, B, prec); } } else if (Blen == 2 || n <= 10) { /* The basecase algorithm is faster for much larger Blen and n than this, but unfortunately has worse numerical stability. */ slong i; arb_t q; arb_init(q); arb_inv(q, B, prec); arb_div(Q, A, B, prec); for (i = 1; i < n; i++) { arb_dot(Q + i, (i < Alen) ? A + i : NULL, 1, B + 1, 1, Q + i - 1, -1, FLINT_MIN(i, Blen - 1), prec); if (!arb_is_one(q)) arb_mul(Q + i, Q + i, q, prec); } arb_clear(q); } else { arb_ptr Binv; Binv = _arb_vec_init(n); _arb_poly_inv_series(Binv, B, Blen, n, prec); _arb_poly_mullow(Q, Binv, n, A, Alen, n, prec); _arb_vec_clear(Binv, n); } } void arb_poly_div_series(arb_poly_t Q, const arb_poly_t A, const arb_poly_t B, slong n, slong prec) { if (n == 0) { arb_poly_zero(Q); return; } if (B->length == 0) { arb_poly_fit_length(Q, n); _arb_vec_indeterminate(Q->coeffs, n); _arb_poly_set_length(Q, n); return; } if (A->length == 0) { arb_poly_zero(Q); return; } if (Q == A || Q == B) { arb_poly_t t; arb_poly_init(t); arb_poly_div_series(t, A, B, n, prec); arb_poly_swap(Q, t); arb_poly_clear(t); return; } arb_poly_fit_length(Q, n); _arb_poly_div_series(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, n, prec); _arb_poly_set_length(Q, n); _arb_poly_normalise(Q); } flint-3.1.3/src/arb_poly/divrem.c000066400000000000000000000056711461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" /* TODO: tighten this code */ void _arb_poly_div(arb_ptr Q, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) { slong lenQ, lenB2; arb_ptr Arev, Brev; lenQ = lenA - lenB + 1; Arev = _arb_vec_init(2 * lenQ); Brev = Arev + lenQ; _arb_poly_reverse(Arev, A + (lenA - lenQ), lenQ, lenQ); if (lenB >= lenQ) { _arb_poly_reverse(Brev, B + (lenB - lenQ), lenQ, lenQ); lenB2 = lenQ; } else { _arb_poly_reverse(Brev, B, lenB, lenB); lenB2 = lenB; } _arb_poly_div_series(Q, Arev, lenQ, Brev, lenB2, lenQ, prec); _arb_poly_reverse(Q, Q, lenQ, lenQ); _arb_vec_clear(Arev, 2 * lenQ); } void _arb_poly_divrem(arb_ptr Q, arb_ptr R, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) { const slong lenQ = lenA - lenB + 1; _arb_poly_div(Q, A, lenA, B, lenB, prec); if (lenB > 1) { if (lenQ >= lenB - 1) _arb_poly_mullow(R, Q, lenQ, B, lenB - 1, lenB - 1, prec); else _arb_poly_mullow(R, B, lenB - 1, Q, lenQ, lenB - 1, prec); _arb_vec_sub(R, A, R, lenB - 1, prec); } } void _arb_poly_rem(arb_ptr R, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) { const slong lenQ = lenA - lenB + 1; arb_ptr Q = _arb_vec_init(lenQ); _arb_poly_divrem(Q, R, A, lenA, B, lenB, prec); _arb_vec_clear(Q, lenQ); } int arb_poly_divrem(arb_poly_t Q, arb_poly_t R, const arb_poly_t A, const arb_poly_t B, slong prec) { const slong lenA = A->length, lenB = B->length; if (lenB == 0 || arb_contains_zero(B->coeffs + lenB - 1)) { return 0; } if (lenA < lenB) { arb_poly_set(R, A); arb_poly_zero(Q); return 1; } if (Q == A || Q == B) { arb_poly_t T; arb_poly_init(T); arb_poly_divrem(T, R, A, B, prec); arb_poly_swap(Q, T); arb_poly_clear(T); return 1; } if (R == A || R == B) { arb_poly_t U; arb_poly_init(U); arb_poly_divrem(Q, U, A, B, prec); arb_poly_swap(R, U); arb_poly_clear(U); return 1; } arb_poly_fit_length(Q, lenA - lenB + 1); arb_poly_fit_length(R, lenB - 1); _arb_poly_divrem(Q->coeffs, R->coeffs, A->coeffs, lenA, B->coeffs, lenB, prec); _arb_poly_set_length(Q, lenA - lenB + 1); _arb_poly_set_length(R, lenB - 1); _arb_poly_normalise(R); return 1; } flint-3.1.3/src/arb_poly/equal.c000066400000000000000000000012251461254215100165040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" int arb_poly_equal(const arb_poly_t A, const arb_poly_t B) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) if (!arb_equal(A->coeffs + i, B->coeffs + i)) return 0; return 1; } flint-3.1.3/src/arb_poly/evaluate.c000066400000000000000000000017341461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_evaluate(arb_t res, arb_srcptr f, slong len, const arb_t x, slong prec) { if ((prec >= 1024) && (len >= 5 + 20000 / prec)) { slong fbits; fbits = _arb_vec_bits(f, len); if (fbits <= prec / 2) { _arb_poly_evaluate_rectangular(res, f, len, x, prec); return; } } _arb_poly_evaluate_horner(res, f, len, x, prec); } void arb_poly_evaluate(arb_t res, const arb_poly_t f, const arb_t a, slong prec) { _arb_poly_evaluate(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate2.c000066400000000000000000000017271461254215100172740ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_evaluate2(arb_t y, arb_t z, arb_srcptr f, slong len, const arb_t x, slong prec) { if ((prec >= 1024) && (len >= 5 + 20000 / prec)) { slong fbits; fbits = _arb_vec_bits(f, len); if (fbits <= prec / 2) { _arb_poly_evaluate2_rectangular(y, z, f, len, x, prec); return; } } _arb_poly_evaluate2_horner(y, z, f, len, x, prec); } void arb_poly_evaluate2(arb_t r, arb_t s, const arb_poly_t f, const arb_t a, slong prec) { _arb_poly_evaluate2(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate2_acb.c000066400000000000000000000013411461254215100200710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_evaluate2_acb(acb_t y, acb_t z, arb_srcptr f, slong len, const acb_t x, slong prec) { _arb_poly_evaluate2_acb_rectangular(y, z, f, len, x, prec); } void arb_poly_evaluate2_acb(acb_t r, acb_t s, const arb_poly_t f, const acb_t a, slong prec) { _arb_poly_evaluate2_acb(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate2_acb_horner.c000066400000000000000000000032721461254215100214530ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_poly.h" void _arb_poly_evaluate2_acb_horner(acb_t y, acb_t z, arb_srcptr poly, slong len, const acb_t x, slong prec) { if (len == 0) { acb_zero(y); acb_zero(z); } else if (len == 1) { acb_set_round_arb(y, poly + 0, prec); acb_zero(z); } else if (acb_is_zero(x)) { acb_set_round_arb(y, poly + 0, prec); acb_set_round_arb(z, poly + 1, prec); } else if (len == 2) { acb_mul_arb(y, x, poly + 1, prec); acb_add_arb(y, y, poly + 0, prec); acb_set_round_arb(z, poly + 1, prec); } else { acb_t t, u, v; slong i; acb_init(t); acb_init(u); acb_init(v); acb_set_round_arb(u, poly + len - 1, prec); acb_zero(v); for (i = len - 2; i >= 0; i--) { acb_mul(t, v, x, prec); acb_add(v, u, t, prec); acb_mul(t, u, x, prec); acb_add_arb(u, t, poly + i, prec); } acb_swap(y, u); acb_swap(z, v); acb_clear(t); acb_clear(u); acb_clear(v); } } void arb_poly_evaluate2_acb_horner(acb_t r, acb_t s, const arb_poly_t f, const acb_t a, slong prec) { _arb_poly_evaluate2_acb_horner(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate2_acb_rectangular.c000066400000000000000000000052361461254215100224670ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "arb_poly.h" void _arb_poly_evaluate2_acb_rectangular(acb_t y, acb_t z, arb_srcptr poly, slong len, const acb_t x, slong prec) { slong i, j, m, r; acb_ptr xs; acb_t s, t; arb_t c; if (len < 3) { if (len == 0) { acb_zero(y); acb_zero(z); } else if (len == 1) { acb_set_round_arb(y, poly + 0, prec); acb_zero(z); } else if (len == 2) { acb_mul_arb(y, x, poly + 1, prec); acb_add_arb(y, y, poly + 0, prec); acb_set_round_arb(z, poly + 1, prec); } return; } m = n_sqrt(len) + 1; m *= 1; r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); arb_init(c); _acb_vec_set_powers(xs, x, m + 1, prec); acb_set_arb(y, poly + (r - 1) * m); for (j = 1; (r - 1) * m + j < len; j++) acb_addmul_arb(y, xs + j, poly + (r - 1) * m + j, prec); for (i = r - 2; i >= 0; i--) { acb_set_arb(s, poly + i * m); for (j = 1; j < m; j++) acb_addmul_arb(s, xs + j, poly + i * m + j, prec); acb_mul(y, y, xs + m, prec); acb_add(y, y, s, prec); } len -= 1; r = (len + m - 1) / m; arb_mul_ui(acb_realref(z), poly + (r - 1) * m + 1, (r - 1) * m + 1, ARF_PREC_EXACT); arb_zero(acb_imagref(z)); for (j = 1; (r - 1) * m + j < len; j++) { arb_mul_ui(c, poly + (r - 1) * m + j + 1, (r - 1) * m + j + 1, ARF_PREC_EXACT); acb_addmul_arb(z, xs + j, c, prec); } for (i = r - 2; i >= 0; i--) { arb_mul_ui(acb_realref(s), poly + i * m + 1, i * m + 1, ARF_PREC_EXACT); arb_zero(acb_imagref(s)); for (j = 1; j < m; j++) { arb_mul_ui(c, poly + i * m + j + 1, i * m + j + 1, ARF_PREC_EXACT); acb_addmul_arb(s, xs + j, c, prec); } acb_mul(z, z, xs + m, prec); acb_add(z, z, s, prec); } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); arb_clear(c); } void arb_poly_evaluate2_acb_rectangular(acb_t r, acb_t s, const arb_poly_t f, const acb_t a, slong prec) { _arb_poly_evaluate2_acb_rectangular(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate2_horner.c000066400000000000000000000032011461254215100206360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_evaluate2_horner(arb_t y, arb_t z, arb_srcptr poly, slong len, const arb_t x, slong prec) { if (len == 0) { arb_zero(y); arb_zero(z); } else if (len == 1) { arb_set_round(y, poly + 0, prec); arb_zero(z); } else if (arb_is_zero(x)) { arb_set_round(y, poly + 0, prec); arb_set_round(z, poly + 1, prec); } else if (len == 2) { arb_mul(y, x, poly + 1, prec); arb_add(y, y, poly + 0, prec); arb_set_round(z, poly + 1, prec); } else { arb_t t, u, v; slong i; arb_init(t); arb_init(u); arb_init(v); arb_set_round(u, poly + len - 1, prec); arb_zero(v); for (i = len - 2; i >= 0; i--) { arb_mul(t, v, x, prec); arb_add(v, u, t, prec); arb_mul(t, u, x, prec); arb_add(u, t, poly + i, prec); } arb_swap(y, u); arb_swap(z, v); arb_clear(t); arb_clear(u); arb_clear(v); } } void arb_poly_evaluate2_horner(arb_t r, arb_t s, const arb_poly_t f, const arb_t a, slong prec) { _arb_poly_evaluate2_horner(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate2_rectangular.c000066400000000000000000000047401461254215100216610ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb_poly.h" void _arb_poly_evaluate2_rectangular(arb_t y, arb_t z, arb_srcptr poly, slong len, const arb_t x, slong prec) { slong i, j, m, r; arb_ptr xs; arb_t s, t, c; if (len < 3) { if (len == 0) { arb_zero(y); arb_zero(z); } else if (len == 1) { arb_set_round(y, poly + 0, prec); arb_zero(z); } else if (len == 2) { arb_mul(y, x, poly + 1, prec); arb_add(y, y, poly + 0, prec); arb_set_round(z, poly + 1, prec); } return; } m = n_sqrt(len) + 1; m *= 1; r = (len + m - 1) / m; xs = _arb_vec_init(m + 1); arb_init(s); arb_init(t); arb_init(c); _arb_vec_set_powers(xs, x, m + 1, prec); arb_dot(y, poly + (r - 1) * m, 0, xs + 1, 1, poly + (r - 1) * m + 1, 1, len - (r - 1) * m - 1, prec); for (i = r - 2; i >= 0; i--) { arb_dot(s, poly + i * m, 0, xs + 1, 1, poly + i * m + 1, 1, m - 1, prec); arb_mul(y, y, xs + m, prec); arb_add(y, y, s, prec); } /* todo: rewrite using arb_dot */ len -= 1; r = (len + m - 1) / m; arb_mul_ui(z, poly + (r - 1) * m + 1, (r - 1) * m + 1, ARF_PREC_EXACT); for (j = 1; (r - 1) * m + j < len; j++) { arb_mul_ui(c, poly + (r - 1) * m + j + 1, (r - 1) * m + j + 1, ARF_PREC_EXACT); arb_addmul(z, xs + j, c, prec); } for (i = r - 2; i >= 0; i--) { arb_mul_ui(s, poly + i * m + 1, i * m + 1, ARF_PREC_EXACT); for (j = 1; j < m; j++) { arb_mul_ui(c, poly + i * m + j + 1, i * m + j + 1, ARF_PREC_EXACT); arb_addmul(s, xs + j, c, prec); } arb_mul(z, z, xs + m, prec); arb_add(z, z, s, prec); } _arb_vec_clear(xs, m + 1); arb_clear(s); arb_clear(t); arb_clear(c); } void arb_poly_evaluate2_rectangular(arb_t r, arb_t s, const arb_poly_t f, const arb_t a, slong prec) { _arb_poly_evaluate2_rectangular(r, s, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate_acb.c000066400000000000000000000013501461254215100200070ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_evaluate_acb(acb_t res, arb_srcptr f, slong len, const acb_t x, slong prec) { _arb_poly_evaluate_acb_rectangular(res, f, len, x, prec); } void arb_poly_evaluate_acb(acb_t res, const arb_poly_t f, const acb_t a, slong prec) { _arb_poly_evaluate_acb(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate_acb_horner.c000066400000000000000000000025321461254215100213670ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_poly.h" void _arb_poly_evaluate_acb_horner(acb_t y, arb_srcptr f, slong len, const acb_t x, slong prec) { if (len == 0) { acb_zero(y); } else if (len == 1 || acb_is_zero(x)) { acb_set_round_arb(y, f, prec); } else if (len == 2) { acb_mul_arb(y, x, f + 1, prec); acb_add_arb(y, y, f + 0, prec); } else { slong i = len - 1; acb_t t, u; acb_init(t); acb_init(u); acb_set_arb(u, f + i); for (i = len - 2; i >= 0; i--) { acb_mul(t, u, x, prec); acb_add_arb(u, t, f + i, prec); } acb_swap(y, u); acb_clear(t); acb_clear(u); } } void arb_poly_evaluate_acb_horner(acb_t res, const arb_poly_t f, const acb_t a, slong prec) { _arb_poly_evaluate_acb_horner(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate_acb_rectangular.c000066400000000000000000000034261461254215100224040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "acb.h" #include "arb_poly.h" void _arb_poly_evaluate_acb_rectangular(acb_t y, arb_srcptr poly, slong len, const acb_t x, slong prec) { slong i, j, m, r; acb_ptr xs; acb_t s, t, c; if (len < 3) { if (len == 0) { acb_zero(y); } else if (len == 1) { acb_set_round_arb(y, poly + 0, prec); } else if (len == 2) { acb_mul_arb(y, x, poly + 1, prec); acb_add_arb(y, y, poly + 0, prec); } return; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); acb_init(c); _acb_vec_set_powers(xs, x, m + 1, prec); acb_set_arb(y, poly + (r - 1) * m); for (j = 1; (r - 1) * m + j < len; j++) acb_addmul_arb(y, xs + j, poly + (r - 1) * m + j, prec); for (i = r - 2; i >= 0; i--) { acb_set_arb(s, poly + i * m); for (j = 1; j < m; j++) acb_addmul_arb(s, xs + j, poly + i * m + j, prec); acb_mul(y, y, xs + m, prec); acb_add(y, y, s, prec); } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); acb_clear(c); } void arb_poly_evaluate_acb_rectangular(acb_t res, const arb_poly_t f, const acb_t a, slong prec) { _arb_poly_evaluate_acb_rectangular(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate_horner.c000066400000000000000000000024511461254215100205620ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_evaluate_horner(arb_t y, arb_srcptr f, slong len, const arb_t x, slong prec) { if (len == 0) { arb_zero(y); } else if (len == 1 || arb_is_zero(x)) { arb_set_round(y, f, prec); } else if (len == 2) { arb_mul(y, x, f + 1, prec); arb_add(y, y, f + 0, prec); } else { slong i = len - 1; arb_t t, u; arb_init(t); arb_init(u); arb_set(u, f + i); for (i = len - 2; i >= 0; i--) { arb_mul(t, u, x, prec); arb_add(u, f + i, t, prec); } arb_swap(y, u); arb_clear(t); arb_clear(u); } } void arb_poly_evaluate_horner(arb_t res, const arb_poly_t f, const arb_t a, slong prec) { _arb_poly_evaluate_horner(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate_rectangular.c000066400000000000000000000032371461254215100215770ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb_poly.h" void _arb_poly_evaluate_rectangular(arb_t y, arb_srcptr poly, slong len, const arb_t x, slong prec) { slong i, m, r; arb_ptr xs; arb_t s, t, c; if (len < 3) { if (len == 0) { arb_zero(y); } else if (len == 1) { arb_set_round(y, poly + 0, prec); } else if (len == 2) { arb_mul(y, x, poly + 1, prec); arb_add(y, y, poly + 0, prec); } return; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = _arb_vec_init(m + 1); arb_init(s); arb_init(t); arb_init(c); _arb_vec_set_powers(xs, x, m + 1, prec); arb_dot(y, poly + (r - 1) * m, 0, xs + 1, 1, poly + (r - 1) * m + 1, 1, len - (r - 1) * m - 1, prec); for (i = r - 2; i >= 0; i--) { arb_dot(s, poly + i * m, 0, xs + 1, 1, poly + i * m + 1, 1, m - 1, prec); arb_mul(y, y, xs + m, prec); arb_add(y, y, s, prec); } _arb_vec_clear(xs, m + 1); arb_clear(s); arb_clear(t); arb_clear(c); } void arb_poly_evaluate_rectangular(arb_t res, const arb_poly_t f, const arb_t a, slong prec) { _arb_poly_evaluate_rectangular(res, f->coeffs, f->length, a, prec); } flint-3.1.3/src/arb_poly/evaluate_vec_fast.c000066400000000000000000000067121461254215100210630ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" /* This gives some speedup for small lengths. */ static inline void _arb_poly_rem_2(arb_ptr r, arb_srcptr a, slong al, arb_srcptr b, slong bl, slong prec) { if (al == 2) { arb_mul(r + 0, a + 1, b + 0, prec); arb_sub(r + 0, a + 0, r + 0, prec); } else { _arb_poly_rem(r, a, al, b, bl, prec); } } void _arb_poly_evaluate_vec_fast_precomp(arb_ptr vs, arb_srcptr poly, slong plen, arb_ptr * tree, slong len, slong prec) { slong height, i, j, pow, left; slong tree_height; slong tlen; arb_ptr t, u, swap, pa, pb, pc; /* avoid worrying about some degenerate cases */ if (len < 2 || plen < 2) { if (len == 1) { arb_t tmp; arb_init(tmp); arb_neg(tmp, tree[0] + 0); _arb_poly_evaluate(vs + 0, poly, plen, tmp, prec); arb_clear(tmp); } else if (len != 0 && plen == 0) { _arb_vec_zero(vs, len); } else if (len != 0 && plen == 1) { for (i = 0; i < len; i++) arb_set(vs + i, poly + 0); } return; } t = _arb_vec_init(len); u = _arb_vec_init(len); left = len; /* Initial reduction. We allow the polynomial to be larger or smaller than the number of points. */ height = FLINT_BIT_COUNT(plen - 1) - 1; tree_height = FLINT_CLOG2(len); while (height >= tree_height) height--; pow = WORD(1) << height; for (i = j = 0; i < len; i += pow, j += (pow + 1)) { tlen = ((i + pow) <= len) ? pow : len % pow; _arb_poly_rem(t + i, poly, plen, tree[height] + j, tlen + 1, prec); } for (i = height - 1; i >= 0; i--) { pow = WORD(1) << i; left = len; pa = tree[i]; pb = t; pc = u; while (left >= 2 * pow) { _arb_poly_rem_2(pc, pb, 2 * pow, pa, pow + 1, prec); _arb_poly_rem_2(pc + pow, pb, 2 * pow, pa + pow + 1, pow + 1, prec); pa += 2 * pow + 2; pb += 2 * pow; pc += 2 * pow; left -= 2 * pow; } if (left > pow) { _arb_poly_rem(pc, pb, left, pa, pow + 1, prec); _arb_poly_rem(pc + pow, pb, left, pa + pow + 1, left - pow + 1, prec); } else if (left > 0) _arb_vec_set(pc, pb, left); swap = t; t = u; u = swap; } _arb_vec_set(vs, t, len); _arb_vec_clear(t, len); _arb_vec_clear(u, len); } void _arb_poly_evaluate_vec_fast(arb_ptr ys, arb_srcptr poly, slong plen, arb_srcptr xs, slong n, slong prec) { arb_ptr * tree; tree = _arb_poly_tree_alloc(n); _arb_poly_tree_build(tree, xs, n, prec); _arb_poly_evaluate_vec_fast_precomp(ys, poly, plen, tree, n, prec); _arb_poly_tree_free(tree, n); } void arb_poly_evaluate_vec_fast(arb_ptr ys, const arb_poly_t poly, arb_srcptr xs, slong n, slong prec) { _arb_poly_evaluate_vec_fast(ys, poly->coeffs, poly->length, xs, n, prec); } flint-3.1.3/src/arb_poly/evaluate_vec_iter.c000066400000000000000000000015361461254215100210700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_evaluate_vec_iter(arb_ptr ys, arb_srcptr poly, slong plen, arb_srcptr xs, slong n, slong prec) { slong i; for (i = 0; i < n; i++) _arb_poly_evaluate(ys + i, poly, plen, xs + i, prec); } void arb_poly_evaluate_vec_iter(arb_ptr ys, const arb_poly_t poly, arb_srcptr xs, slong n, slong prec) { _arb_poly_evaluate_vec_iter(ys, poly->coeffs, poly->length, xs, n, prec); } flint-3.1.3/src/arb_poly/exp_series.c000066400000000000000000000120451461254215100175450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif /* allow changing this from the test code */ FLINT_DLL slong arb_poly_newton_exp_cutoff = 0; /* with inverse=1 simultaneously computes g = exp(-x) to length n with inverse=0 uses g as scratch space, computing g = exp(-x) only to length (n+1)/2 */ static void _arb_poly_exp_series_newton(arb_ptr f, arb_ptr g, arb_srcptr h, slong len, slong prec, int inverse, slong cutoff) { slong alloc; arb_ptr T, U, hprime; alloc = 3 * len; T = _arb_vec_init(alloc); U = T + len; hprime = U + len; _arb_poly_derivative(hprime, h, len, prec); arb_zero(hprime + len - 1); NEWTON_INIT(cutoff, len) /* f := exp(h) + O(x^m), g := exp(-h) + O(x^m2) */ NEWTON_BASECASE(n) _arb_poly_exp_series_basecase(f, h, n, n, prec); _arb_poly_inv_series(g, f, (n + 1) / 2, (n + 1) / 2, prec); NEWTON_END_BASECASE /* extend from length m to length n */ NEWTON_LOOP(m, n) slong m2 = (m + 1) / 2; slong l = m - 1; /* shifted for derivative */ /* g := exp(-h) + O(x^m) */ _arb_poly_mullow(T, f, m, g, m2, m, prec); _arb_poly_mullow(g + m2, g, m2, T + m2, m - m2, m - m2, prec); _arb_vec_neg(g + m2, g + m2, m - m2); /* U := h' + g (f' - f h') + O(x^(n-1)) Note: should replace h' by h' mod x^(m-1) */ _arb_vec_zero(f + m, n - m); _arb_poly_mullow(T, f, n, hprime, n, n, prec); /* should be mulmid */ _arb_poly_derivative(U, f, n, prec); arb_zero(U + n - 1); /* should skip low terms */ _arb_vec_sub(U + l, U + l, T + l, n - l, prec); _arb_poly_mullow(T + l, g, n - m, U + l, n - m, n - m, prec); _arb_vec_add(U + l, hprime + l, T + l, n - m, prec); /* f := f + f * (h - int U) + O(x^n) = exp(h) + O(x^n) */ _arb_poly_integral(U, U, n, prec); /* should skip low terms */ _arb_vec_sub(U + m, h + m, U + m, n - m, prec); _arb_poly_mullow(f + m, f, n - m, U + m, n - m, n - m, prec); /* g := exp(-h) + O(x^n) */ /* not needed if we only want exp(x) */ if (n == len && inverse) { _arb_poly_mullow(T, f, n, g, m, n, prec); _arb_poly_mullow(g + m, g, m, T + m, n - m, n - m, prec); _arb_vec_neg(g + m, g + m, n - m); } NEWTON_END_LOOP NEWTON_END _arb_vec_clear(T, alloc); } void _arb_poly_exp_series(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_exp(f, h, prec); _arb_vec_zero(f + 1, n - 1); } else if (n == 2) { arb_exp(f, h, prec); arb_mul(f + 1, f, h + 1, prec); /* safe since hlen >= 2 */ } else if (_arb_vec_is_zero(h + 1, hlen - 2)) /* h = a + bx^d */ { slong i, j, d = hlen - 1; arb_t t; arb_init(t); arb_set(t, h + d); arb_exp(f, h, prec); for (i = 1, j = d; j < n; j += d, i++) { arb_mul(f + j, f + j - d, t, prec); arb_div_ui(f + j, f + j, i, prec); _arb_vec_zero(f + j - d + 1, hlen - 2); } _arb_vec_zero(f + j - d + 1, n - (j - d + 1)); arb_clear(t); } else { slong cutoff; if (arb_poly_newton_exp_cutoff != 0) cutoff = arb_poly_newton_exp_cutoff; else if (prec <= 256) cutoff = 750; else cutoff = 1e5 / pow(log(prec), 3); if (hlen <= cutoff) { _arb_poly_exp_series_basecase(f, h, hlen, n, prec); } else { arb_ptr g, t; arb_t u; int fix; g = _arb_vec_init((n + 1) / 2); fix = (hlen < n || h == f || !arb_is_zero(h)); if (fix) { t = _arb_vec_init(n); _arb_vec_set(t + 1, h + 1, hlen - 1); } else t = (arb_ptr) h; arb_init(u); arb_exp(u, h, prec); _arb_poly_exp_series_newton(f, g, t, n, prec, 0, cutoff); if (!arb_is_one(u)) _arb_vec_scalar_mul(f, f, n, u, prec); _arb_vec_clear(g, (n + 1) / 2); if (fix) _arb_vec_clear(t, n); arb_clear(u); } } } void arb_poly_exp_series(arb_poly_t f, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(f); return; } if (hlen == 0) { arb_poly_one(f); return; } if (hlen == 1) n = 1; arb_poly_fit_length(f, n); _arb_poly_exp_series(f->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(f, n); _arb_poly_normalise(f); } flint-3.1.3/src/arb_poly/exp_series_basecase.c000066400000000000000000000045541461254215100214010ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif static void _arb_poly_exp_series_basecase_rec(arb_ptr f, arb_ptr a, arb_srcptr h, slong hlen, slong n, slong prec) { slong k; arb_t s; arb_init(s); arb_exp(f, h, prec); for (k = 1; k < hlen; k++) arb_mul_ui(a + k, h + k, k, prec); for (k = 1; k < n; k++) { arb_dot(s, NULL, 0, a + 1, 1, f + k - 1, -1, FLINT_MIN(k, hlen - 1), prec); arb_div_ui(f + k, s, k, prec); } arb_clear(s); } void _arb_poly_exp_series_basecase(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(n, hlen); if (n < 20 || hlen < 0.9 * n || prec <= 2 * FLINT_BITS || n < 1000.0 / log(prec + 10) - 70) { arb_ptr t = _arb_vec_init(hlen); _arb_poly_exp_series_basecase_rec(f, t, h, hlen, n, prec); _arb_vec_clear(t, hlen); } else { slong m, v; arb_ptr t, u; m = (n + 2) / 3; v = m * 2; t = _arb_vec_init(n); u = _arb_vec_init(n - m); _arb_poly_mullow(t, h + m, hlen - m, h + m, hlen - m, n - v, prec); _arb_vec_scalar_mul_2exp_si(t, t, n - v, -1); _arb_vec_set(u, h + m, v - m); _arb_poly_add(u + v - m, t, n - v, h + v, hlen - v, prec); _arb_poly_exp_series_basecase_rec(f, t, h, m, n, prec); _arb_poly_mullow(t, f, n, u, n - m, n - m, prec); _arb_poly_add(f + m, f + m, n - m, t, n - m, prec); _arb_vec_clear(t, n); _arb_vec_clear(u, n - m); } } void arb_poly_exp_series_basecase(arb_poly_t f, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(f); return; } if (hlen == 0) { arb_poly_one(f); return; } arb_poly_fit_length(f, n); _arb_poly_exp_series_basecase(f->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(f, n); _arb_poly_normalise(f); } flint-3.1.3/src/arb_poly/fit_length.c000066400000000000000000000014261461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_fit_length(arb_poly_t poly, slong len) { slong i; if (len > poly->alloc) { if (len < 2 * poly->alloc) len = 2 * poly->alloc; poly->coeffs = flint_realloc(poly->coeffs, len * sizeof(arb_struct)); for (i = poly->alloc; i < len; i++) arb_init(poly->coeffs + i); poly->alloc = len; } } flint-3.1.3/src/arb_poly/gamma_series.c000066400000000000000000000240551461254215100200370ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_gamma_stirling_bound(mag_ptr err, const arb_t x, slong k0, slong knum, slong n); void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec); void arb_gamma_stirling_coeff(arb_t b, ulong k, int digamma, slong prec); void _arb_poly_lgamma_series_at_one(arb_ptr u, slong len, slong prec) { slong i; if (len > 0) arb_zero(u); if (len > 1) arb_const_euler(u + 1, prec); if (len > 2) arb_zeta_ui_vec(u + 2, 2, len - 2, prec); for (i = 2; i < len; i++) arb_div_ui(u + i, u + i, i, prec); for (i = 1; i < len; i += 2) arb_neg(u + i, u + i); } static void bsplit(arb_ptr Q, arb_ptr T, const arb_t z, slong a, slong b, slong num, slong prec) { if (b - a == 1) { arb_gamma_stirling_coeff(T, a, 0, prec); if (a == 1) { /* (z + t) */ arb_set(Q, z); if (num > 1) arb_one(Q + 1); if (num > 2) arb_zero(Q + 2); } else { /* (z + t)^2 */ arb_mul(Q, z, z, prec); /* TODO: precompute */ if (num > 1) arb_mul_2exp_si(Q + 1, z, 1); if (num > 2) arb_one(Q + 2); } } else { slong m, n1, n2, q1len, q2len, t1len, t2len, qlen, tlen, alloc; arb_ptr Q1, T1, Q2, T2; m = a + (b - a) / 2; n1 = m - a; n2 = b - m; q1len = FLINT_MIN(2 * n1 + 1, num); t1len = FLINT_MIN(2 * n1 - 1, num); q2len = FLINT_MIN(2 * n2 + 1, num); t2len = FLINT_MIN(2 * n2 - 1, num); qlen = FLINT_MIN(q1len + q2len - 1, num); tlen = FLINT_MIN(t1len + q2len - 1, num); alloc = q1len + q2len + t1len + t2len; Q1 = _arb_vec_init(alloc); Q2 = Q1 + q1len; T1 = Q2 + q2len; T2 = T1 + t1len; bsplit(Q1, T1, z, a, m, num, prec); bsplit(Q2, T2, z, m, b, num, prec); _arb_poly_mullow(Q, Q2, q2len, Q1, q1len, qlen, prec); _arb_poly_mullow(T, Q2, q2len, T1, t1len, tlen, prec); _arb_poly_add(T, T, tlen, T2, t2len, prec); _arb_vec_clear(Q1, alloc); } } void _arb_poly_mullow_cpx(arb_ptr res, arb_srcptr src, slong len, const arb_t c, slong trunc, slong prec) { slong i; if (len < trunc) arb_set(res + len, src + len - 1); for (i = len - 1; i > 0; i--) { arb_mul(res + i, src + i, c, prec); arb_add(res + i, res + i, src + i - 1, prec); } arb_mul(res, src, c, prec); } void _arb_poly_log_cpx_series(arb_ptr res, const arb_t c, slong num, slong prec) { slong i; for (i = 0; i < num; i++) { if (i == 0) arb_log(res + i, c, prec); else if (i == 1) arb_inv(res + i, c, prec); else arb_mul(res + i, res + i - 1, res + 1, prec); } for (i = 2; i < num; i++) { arb_div_ui(res + i, res + i, i, prec); if (i % 2 == 0) arb_neg(res + i, res + i); } } void _arb_poly_gamma_stirling_eval2(arb_ptr res, const arb_t z, slong n, slong num, int diff, slong prec) { slong k, tlen, qlen; arb_ptr T, Q; mag_ptr err; arb_t c; T = _arb_vec_init(num); Q = _arb_vec_init(num); err = _mag_vec_init(num); arb_init(c); arb_gamma_stirling_bound(err, z, 0, num, n); if (n <= 1) { _arb_vec_zero(res, num); } else { qlen = FLINT_MIN(2 * (n - 1) + 1, num); tlen = FLINT_MIN(2 * (n - 1) - 1, num); bsplit(Q, T, z, 1, n, num, prec); _arb_poly_div_series(res, T, tlen, Q, qlen, num, prec); } if (diff) { _arb_vec_add_error_mag_vec(res, err, num); _arb_poly_derivative(res, res, num, prec); if (num > 1) { /* add log(z+x) - 1/(2(z+x)) */ arb_inv(c, z, prec); _arb_vec_set_powers(T, c, num, prec); for (k = 1; k < num - 1; k++) { arb_mul_2exp_si(T, z, 1); arb_div_ui(T, T, k, prec); arb_add_ui(T, T, 1, prec); arb_mul_2exp_si(T, T, -1); if (k % 2 == 0) arb_submul(res + k, T, T + k + 1, prec); else arb_addmul(res + k, T, T + k + 1, prec); } arb_mul_2exp_si(c, c, -1); arb_sub(res, res, c, prec); arb_log(c, z, prec); arb_add(res, res, c, prec); } } else { /* ((z-1/2) + t) * log(z+t) */ _arb_poly_log_cpx_series(T, z, num, prec); arb_one(c); arb_mul_2exp_si(c, c, -1); arb_sub(c, z, c, prec); _arb_poly_mullow_cpx(T, T, num, c, num, prec); /* constant term */ arb_const_log_sqrt2pi(c, prec); arb_add(T, T, c, prec); /* subtract (z+t) */ arb_sub(T, T, z, prec); if (num > 1) arb_sub_ui(T + 1, T + 1, 1, prec); _arb_vec_add(res, res, T, num, prec); _arb_vec_add_error_mag_vec(res, err, num); } _arb_vec_clear(T, num); _arb_vec_clear(Q, num); _mag_vec_clear(err, num); arb_clear(c); } void _arb_poly_gamma_stirling_eval(arb_ptr res, const arb_t z, slong n, slong num, slong prec) { _arb_poly_gamma_stirling_eval2(res, z, n, num, 0, prec); } void _arb_poly_gamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong i, rflen, r, n, wp; arb_ptr t, u, v; arb_struct f[2]; if (hlen == 1) { arb_gamma(res, h, prec); if (arb_is_finite(res)) _arb_vec_zero(res + 1, len - 1); else _arb_vec_indeterminate(res + 1, len - 1); return; } hlen = FLINT_MIN(hlen, len); wp = prec + FLINT_BIT_COUNT(prec); t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); arb_init(f); arb_init(f + 1); /* use zeta values at small integers */ if (arb_is_int(h) && (arf_cmpabs_ui(arb_midref(h), prec / 2) < 0)) { r = arf_get_si(arb_midref(h), ARF_RND_DOWN); if (r <= 0) { _arb_vec_indeterminate(v, len); } else if (r == 1) { _arb_poly_lgamma_series_at_one(u, len, wp); _arb_poly_exp_series(v, u, len, len, wp); } else { _arb_poly_lgamma_series_at_one(u, len, wp); _arb_poly_exp_series(t, u, len, len, wp); arb_one(f); arb_one(f + 1); rflen = FLINT_MIN(len, r); _arb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), r - 1, rflen, wp); _arb_poly_mullow(v, t, len, u, rflen, len, wp); } } else { /* otherwise use Stirling series */ arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp); /* gamma(h) = (rf(1-h, r) * pi) / (gamma(1-h+r) sin(pi h)), h = h0 + t*/ if (reflect) { /* u = 1/gamma(r+1-h) */ arb_sub_ui(f, h, r + 1, wp); arb_neg(f, f); _arb_poly_gamma_stirling_eval(t, f, n, len, wp); _arb_vec_neg(t, t, len); _arb_poly_exp_series(u, t, len, len, wp); for (i = 1; i < len; i += 2) arb_neg(u + i, u + i); /* v = 1/sin(pi x) */ arb_set(f, h); arb_one(f + 1); _arb_poly_sin_pi_series(t, f, 2, len, wp); _arb_poly_inv_series(v, t, len, len, wp); _arb_poly_mullow(t, u, len, v, len, len, wp); /* rf(1-h,r) * pi */ if (r == 0) { rflen = 1; arb_const_pi(u, wp); } else { arb_sub_ui(f, h, 1, wp); arb_neg(f, f); arb_set_si(f + 1, -1); rflen = FLINT_MIN(len, r + 1); _arb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), r, rflen, wp); arb_const_pi(v, wp); _arb_vec_scalar_mul(u, u, rflen, v, wp); } /* multiply by rising factorial */ _arb_poly_mullow(v, t, len, u, rflen, len, wp); } else { /* gamma(h) = gamma(h+r) / rf(h,r) */ if (r == 0) { arb_add_ui(f, h, r, wp); _arb_poly_gamma_stirling_eval(t, f, n, len, wp); _arb_poly_exp_series(v, t, len, len, wp); } else { /* TODO: div_series may be better (once it has a good basecase), if the rising factorial is short */ arb_set(f, h); arb_one(f + 1); rflen = FLINT_MIN(len, r + 1); _arb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), r, rflen, wp); _arb_poly_inv_series(t, u, rflen, len, wp); arb_add_ui(f, h, r, wp); _arb_poly_gamma_stirling_eval(v, f, n, len, wp); _arb_poly_exp_series(u, v, len, len, wp); _arb_poly_mullow(v, u, len, t, len, len, wp); } } } /* compose with nonconstant part */ arb_zero(t); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, v, len, t, hlen, len, prec); arb_clear(f); arb_clear(f + 1); _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); } void arb_poly_gamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { arb_poly_fit_length(res, n); if (f->length == 0 || n == 0) _arb_vec_indeterminate(res->coeffs, n); else _arb_poly_gamma_series(res->coeffs, f->coeffs, f->length, n, prec); _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/get_coeff_arb.c000066400000000000000000000010751461254215100201450ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_get_coeff_arb(arb_t x, const arb_poly_t poly, slong n) { if (n < poly->length) arb_set(x, poly->coeffs + n); else arb_zero(x); } flint-3.1.3/src/arb_poly/get_unique_fmpz_poly.c000066400000000000000000000013531461254215100216430ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb_poly.h" int arb_poly_get_unique_fmpz_poly(fmpz_poly_t res, const arb_poly_t src) { int success; fmpz_poly_fit_length(res, src->length); success = _arb_vec_get_unique_fmpz_vec(res->coeffs, src->coeffs, src->length); _fmpz_poly_set_length(res, src->length); _fmpz_poly_normalise(res); return success; } flint-3.1.3/src/arb_poly/graeffe_transform.c000066400000000000000000000027451461254215100210770ustar00rootroot00000000000000/* Copyright (C) 2021 Matthias Gessinger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_graeffe_transform(arb_ptr b, arb_srcptr a, slong len, slong prec) { slong lo, le, ls, deg, i; arb_ptr pe, po; if (len <= 1) { if (len) arb_sqr(b, a, prec); return; } deg = len - 1; lo = len / 2; ls = 2 * lo - 1; le = deg / 2 + 1; po = _arb_vec_init(lo); pe = _arb_vec_init(FLINT_MAX(le, ls)); for (i = deg; i >= 0; i--) { if (i % 2 == 0) arb_set(pe + i / 2, a + i); else arb_set(po + i / 2, a + i); } _arb_poly_mul(b, pe, le, pe, le, prec); _arb_poly_mul(pe, po, lo, po, lo, prec); _arb_poly_sub(b + 1, b + 1, ls, pe, ls, prec); if (len % 2 == 0) { _arb_vec_neg(b, b, deg); arb_set(b + deg, pe + (deg - 1)); } _arb_vec_clear(pe, FLINT_MAX(le, ls)); _arb_vec_clear(po, lo); } void arb_poly_graeffe_transform(arb_poly_t b, const arb_poly_t a, slong prec) { arb_poly_fit_length(b, a->length); _arb_poly_graeffe_transform(b->coeffs, a->coeffs, a->length, prec); _arb_poly_set_length(b, a->length); } flint-3.1.3/src/arb_poly/init.c000066400000000000000000000011641461254215100163420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_init(arb_poly_t poly) { poly->coeffs = NULL; poly->length = 0; poly->alloc = 0; } void arb_poly_init2(arb_poly_t poly, slong len) { arb_poly_init(poly); arb_poly_fit_length(poly, len); } flint-3.1.3/src/arb_poly/inlines.c000066400000000000000000000006601461254215100170400ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ARB_POLY_INLINES_C #include "arb_poly.h" flint-3.1.3/src/arb_poly/integral.c000066400000000000000000000016021461254215100172010ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_integral(arb_ptr res, arb_srcptr poly, slong len, slong prec) { slong k = len - 1; for (k = len - 1; k > 0; k--) arb_div_ui(res + k, poly + k - 1, k, prec); arb_zero(res); } void arb_poly_integral(arb_poly_t res, const arb_poly_t poly, slong prec) { arb_poly_fit_length(res, poly->length + 1); _arb_poly_integral(res->coeffs, poly->coeffs, poly->length + 1, prec); _arb_poly_set_length(res, poly->length + 1); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/interpolate_barycentric.c000066400000000000000000000034161461254215100223140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_interpolate_barycentric(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) { arb_ptr P, Q, w; arb_t t; slong i, j; if (n == 1) { arb_set(poly, ys); return; } P = _arb_vec_init(n + 1); Q = _arb_vec_init(n); w = _arb_vec_init(n); arb_init(t); _arb_poly_product_roots(P, xs, n, prec); for (i = 0; i < n; i++) { arb_one(w + i); for (j = 0; j < n; j++) { if (i != j) { arb_sub(t, xs + i, xs + j, prec); arb_mul(w + i, w + i, t, prec); } } arb_inv(w + i, w + i, prec); } _arb_vec_zero(poly, n); for (i = 0; i < n; i++) { _arb_poly_div_root(Q, t, P, n + 1, xs + i, prec); arb_mul(t, w + i, ys + i, prec); _arb_vec_scalar_addmul(poly, Q, n, t, prec); } _arb_vec_clear(P, n + 1); _arb_vec_clear(Q, n); _arb_vec_clear(w, n); arb_clear(t); } void arb_poly_interpolate_barycentric(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) { if (n == 0) { arb_poly_zero(poly); } else { arb_poly_fit_length(poly, n); _arb_poly_set_length(poly, n); _arb_poly_interpolate_barycentric(poly->coeffs, xs, ys, n, prec); _arb_poly_normalise(poly); } } flint-3.1.3/src/arb_poly/interpolate_fast.c000066400000000000000000000057511461254215100207500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_interpolation_weights(arb_ptr w, arb_ptr * tree, slong len, slong prec) { arb_ptr tmp; slong i, n, height; if (len == 0) return; if (len == 1) { arb_one(w); return; } tmp = _arb_vec_init(len + 1); height = FLINT_CLOG2(len); n = WORD(1) << (height - 1); _arb_poly_mul_monic(tmp, tree[height-1], n + 1, tree[height-1] + (n + 1), (len - n + 1), prec); _arb_poly_derivative(tmp, tmp, len + 1, prec); _arb_poly_evaluate_vec_fast_precomp(w, tmp, len, tree, len, prec); for (i = 0; i < len; i++) arb_inv(w + i, w + i, prec); _arb_vec_clear(tmp, len + 1); } void _arb_poly_interpolate_fast_precomp(arb_ptr poly, arb_srcptr ys, arb_ptr * tree, arb_srcptr weights, slong len, slong prec) { arb_ptr t, u, pa, pb; slong i, pow, left; if (len == 0) return; t = _arb_vec_init(len); u = _arb_vec_init(len); for (i = 0; i < len; i++) arb_mul(poly + i, weights + i, ys + i, prec); for (i = 0; i < FLINT_CLOG2(len); i++) { pow = (WORD(1) << i); pa = tree[i]; pb = poly; left = len; while (left >= 2 * pow) { _arb_poly_mul(t, pa, pow + 1, pb + pow, pow, prec); _arb_poly_mul(u, pa + pow + 1, pow + 1, pb, pow, prec); _arb_vec_add(pb, t, u, 2 * pow, prec); left -= 2 * pow; pa += 2 * pow + 2; pb += 2 * pow; } if (left > pow) { _arb_poly_mul(t, pa, pow + 1, pb + pow, left - pow, prec); _arb_poly_mul(u, pb, pow, pa + pow + 1, left - pow + 1, prec); _arb_vec_add(pb, t, u, left, prec); } } _arb_vec_clear(t, len); _arb_vec_clear(u, len); } void _arb_poly_interpolate_fast(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong len, slong prec) { arb_ptr * tree; arb_ptr w; tree = _arb_poly_tree_alloc(len); _arb_poly_tree_build(tree, xs, len, prec); w = _arb_vec_init(len); _arb_poly_interpolation_weights(w, tree, len, prec); _arb_poly_interpolate_fast_precomp(poly, ys, tree, w, len, prec); _arb_vec_clear(w, len); _arb_poly_tree_free(tree, len); } void arb_poly_interpolate_fast(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) { if (n == 0) { arb_poly_zero(poly); } else { arb_poly_fit_length(poly, n); _arb_poly_set_length(poly, n); _arb_poly_interpolate_fast(poly->coeffs, xs, ys, n, prec); _arb_poly_normalise(poly); } } flint-3.1.3/src/arb_poly/interpolate_newton.c000066400000000000000000000043211461254215100213150ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" static void _interpolate_newton(arb_ptr ys, arb_srcptr xs, slong n, slong prec) { arb_t p, q, t; slong i, j; arb_init(p); arb_init(q); arb_init(t); for (i = 1; i < n; i++) { arb_set(t, ys + i - 1); for (j = i; j < n; j++) { arb_sub(p, ys + j, t, prec); arb_sub(q, xs + j, xs + j - i, prec); arb_set(t, ys + j); arb_div(ys + j, p, q, prec); } } arb_clear(p); arb_clear(q); arb_clear(t); } static void _newton_to_monomial(arb_ptr ys, arb_srcptr xs, slong n, slong prec) { arb_t t, u; slong i, j; arb_init(t); arb_init(u); for (i = n - 2; i >= 0; i--) { arb_set(t, ys + i); arb_set(ys + i, ys + i + 1); for (j = i + 1; j < n - 1; j++) { arb_mul(u, ys + j, xs + i, prec); arb_sub(ys + j, ys + j + 1, u, prec); } arb_mul(u, ys + n - 1, xs + i, prec); arb_sub(ys + n - 1, t, u, prec); } _arb_poly_reverse(ys, ys, n, n); arb_clear(t); arb_clear(u); } void _arb_poly_interpolate_newton(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) { if (n == 1) { arb_set(poly, ys); } else { _arb_vec_set(poly, ys, n); _interpolate_newton(poly, xs, n, prec); while (n > 0 && arb_is_zero(poly + n - 1)) n--; _newton_to_monomial(poly, xs, n, prec); } } void arb_poly_interpolate_newton(arb_poly_t poly, arb_srcptr xs, arb_srcptr ys, slong n, slong prec) { if (n == 0) { arb_poly_zero(poly); } else { arb_poly_fit_length(poly, n); _arb_poly_set_length(poly, n); _arb_poly_interpolate_newton(poly->coeffs, xs, ys, n, prec); _arb_poly_normalise(poly); } } flint-3.1.3/src/arb_poly/inv_borel_transform.c000066400000000000000000000017701461254215100214540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_inv_borel_transform(arb_ptr res, arb_srcptr poly, slong len, slong prec) { slong i; arb_t t; arb_init(t); arb_one(t); for (i = 0; i < len; i++) { if (i > 1) arb_mul_ui(t, t, i, prec); arb_mul(res + i, poly + i, t, prec); } arb_clear(t); } void arb_poly_inv_borel_transform(arb_poly_t res, const arb_poly_t poly, slong prec) { arb_poly_fit_length(res, poly->length); _arb_poly_inv_borel_transform(res->coeffs, poly->coeffs, poly->length, prec); _arb_poly_set_length(res, poly->length); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/inv_series.c000066400000000000000000000054661461254215100175560ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #define MULLOW(z, x, xn, y, yn, nn, prec) \ if ((xn) >= (yn)) \ _arb_poly_mullow(z, x, xn, y, yn, nn, prec); \ else \ _arb_poly_mullow(z, y, yn, x, xn, nn, prec); \ void _arb_poly_inv_series(arb_ptr Qinv, arb_srcptr Q, slong Qlen, slong len, slong prec) { Qlen = FLINT_MIN(Qlen, len); arb_inv(Qinv, Q, prec); if (Qlen == 1) { _arb_vec_zero(Qinv + 1, len - 1); } else if (len == 2) { arb_mul(Qinv + 1, Qinv, Qinv, prec); arb_mul(Qinv + 1, Qinv + 1, Q + 1, prec); arb_neg(Qinv + 1, Qinv + 1); } else { slong i, blen; /* The basecase algorithm is faster for much larger Qlen or len than this, but unfortunately also much less numerically stable. */ if (Qlen == 2 || len <= 8) blen = len; else blen = FLINT_MIN(len, 4); for (i = 1; i < blen; i++) { arb_dot(Qinv + i, NULL, 1, Q + 1, 1, Qinv + i - 1, -1, FLINT_MIN(i, Qlen - 1), prec); if (!arb_is_one(Qinv)) arb_mul(Qinv + i, Qinv + i, Qinv, prec); } if (len > blen) { slong Qnlen, Wlen, W2len; arb_ptr W; W = _arb_vec_init(len); NEWTON_INIT(blen, len) NEWTON_LOOP(m, n) Qnlen = FLINT_MIN(Qlen, n); Wlen = FLINT_MIN(Qnlen + m - 1, n); W2len = Wlen - m; MULLOW(W, Q, Qnlen, Qinv, m, Wlen, prec); MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m, prec); _arb_vec_neg(Qinv + m, Qinv + m, n - m); NEWTON_END_LOOP NEWTON_END _arb_vec_clear(W, len); } } } void arb_poly_inv_series(arb_poly_t Qinv, const arb_poly_t Q, slong n, slong prec) { if (n == 0) { arb_poly_zero(Qinv); return; } if (Q->length == 0) { arb_poly_fit_length(Qinv, n); _arb_vec_indeterminate(Qinv->coeffs, n); _arb_poly_set_length(Qinv, n); return; } if (Qinv == Q) { arb_poly_t t; arb_poly_init(t); arb_poly_inv_series(t, Q, n, prec); arb_poly_swap(Qinv, t); arb_poly_clear(t); return; } arb_poly_fit_length(Qinv, n); _arb_poly_inv_series(Qinv->coeffs, Q->coeffs, Q->length, n, prec); _arb_poly_set_length(Qinv, n); _arb_poly_normalise(Qinv); } flint-3.1.3/src/arb_poly/io.c000066400000000000000000000020231461254215100160010ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2015 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arb_poly.h" /* printing *******************************************************************/ void arb_poly_fprintd(FILE * file, const arb_poly_t poly, slong digits) { slong i; flint_fprintf(file, "["); for (i = 0; i < poly->length; i++) { flint_fprintf(file, "("); arb_fprintd(file, poly->coeffs + i, digits); flint_fprintf(file, ")"); if (i + 1 < poly->length) flint_fprintf(file, ", "); } flint_fprintf(file, "]"); } void arb_poly_printd(const arb_poly_t poly, slong digits) { arb_poly_fprintd(stdout, poly, digits); } flint-3.1.3/src/arb_poly/lambertw_series.c000066400000000000000000000044361461254215100205730ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_lambertw_series(arb_ptr res, arb_srcptr z, slong zlen, int flags, slong len, slong prec) { arb_ptr w, ew, t, u; arb_t ew0; zlen = FLINT_MIN(zlen, len); if (zlen == 1) { arb_lambertw(res, z, flags, prec); _arb_vec_zero(res + 1, len - 1); return; } w = _arb_vec_init(len); ew = _arb_vec_init(len); t = _arb_vec_init(len); u = _arb_vec_init(len); arb_init(ew0); arb_lambertw(w, z, flags, prec); if (arb_contains_zero(w)) arb_exp(ew0, w, prec); else arb_div(ew0, z, w, prec); arb_add(t, ew0, z, prec); arb_div(w + 1, z + 1, t, prec); NEWTON_INIT(2, len) NEWTON_LOOP(m, n) /* _arb_poly_exp_series(ew, w, m, n, prec); */ arb_zero(t); _arb_vec_set(t + 1, w + 1, m - 1); _arb_poly_exp_series(ew, t, m, n, prec); _arb_vec_scalar_mul(ew, ew, n, ew0, prec); _arb_poly_mullow(t, ew, n, w, m, n, prec); _arb_poly_sub(u, t, n, z, FLINT_MIN(zlen, n), prec); _arb_vec_add(t, t, ew, n, prec); _arb_poly_div_series(ew, u, n, t, n, n, prec); _arb_vec_neg(w + m, ew + m, n - m); NEWTON_END_LOOP NEWTON_END _arb_vec_set(res, w, len); _arb_vec_clear(w, len); _arb_vec_clear(ew, len); _arb_vec_clear(t, len); _arb_vec_clear(u, len); arb_clear(ew0); } void arb_poly_lambertw_series(arb_poly_t res, const arb_poly_t z, int flags, slong len, slong prec) { if (len == 0 || (flags == 0 && z->length == 0)) { arb_poly_zero(res); return; } if (z->length == 0) { arb_poly_fit_length(res, len); _arb_vec_indeterminate(res->coeffs, len); _arb_poly_set_length(res, len); return; } arb_poly_fit_length(res, len); _arb_poly_lambertw_series(res->coeffs, z->coeffs, z->length, flags, len, prec); _arb_poly_set_length(res, len); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/lgamma_series.c000066400000000000000000000061131461254215100202060ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "arb_hypgeom.h" slong arf_get_si(const arf_t x, arf_rnd_t rnd); void _arb_poly_lgamma_series_at_one(arb_ptr u, slong len, slong prec); void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec); void _arb_poly_gamma_stirling_eval(arb_ptr res, const arb_t z, slong n, slong num, slong prec); static inline void _log_rising_ui_series(arb_ptr t, const arb_t x, slong r, slong len, slong prec) { slong rflen; rflen = FLINT_MIN(len, r + 1); arb_hypgeom_rising_ui_jet(t, x, r, rflen, prec); _arb_poly_log_series(t, t, rflen, len, prec); } void _arb_poly_lgamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong r, n, wp; arb_t zr; arb_ptr t, u; if (!arb_is_positive(h)) { _arb_vec_indeterminate(res, len); return; } hlen = FLINT_MIN(hlen, len); wp = prec + FLINT_BIT_COUNT(prec); t = _arb_vec_init(len); u = _arb_vec_init(len); arb_init(zr); /* use zeta values at small integers */ if (arb_is_int(h) && (arf_cmpabs_ui(arb_midref(h), prec / 2) < 0)) { r = arf_get_si(arb_midref(h), ARF_RND_DOWN); if (r <= 0) { _arb_vec_indeterminate(res, len); goto cleanup; } else { _arb_poly_lgamma_series_at_one(u, len, wp); if (r != 1) { arb_one(zr); _log_rising_ui_series(t, zr, r - 1, len, wp); _arb_vec_add(u, u, t, len, wp); } } } else if (len <= 2) { arb_lgamma(u, h, wp); if (len == 2) arb_digamma(u + 1, h, wp); } else { /* otherwise use Stirling series */ arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 0, 0, wp); arb_add_ui(zr, h, r, wp); _arb_poly_gamma_stirling_eval(u, zr, n, len, wp); if (r != 0) { _log_rising_ui_series(t, h, r, len, wp); _arb_vec_sub(u, u, t, len, wp); } } /* compose with nonconstant part */ arb_zero(t); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, u, len, t, hlen, len, prec); cleanup: arb_clear(zr); _arb_vec_clear(t, len); _arb_vec_clear(u, len); } void arb_poly_lgamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { arb_poly_fit_length(res, n); if (f->length == 0 || n == 0) _arb_vec_indeterminate(res->coeffs, n); else _arb_poly_lgamma_series(res->coeffs, f->coeffs, f->length, n, prec); _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/log1p_series.c000066400000000000000000000021431461254215100177710ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_log1p_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_log1p_series(res, f, flen, n, ctx) != GR_SUCCESS) _arb_vec_indeterminate(res, n); } void arb_poly_log1p_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { slong flen = f->length; if (flen == 0 || n == 0) { arb_poly_zero(res); return; } if (flen == 1 /*&& !arb_contains_si(f->coeffs, -1)*/) n = 1; arb_poly_fit_length(res, n); _arb_poly_log1p_series(res->coeffs, f->coeffs, flen, n, prec); _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/log_series.c000066400000000000000000000021071461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_log_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_log_series(res, f, flen, n, ctx) != GR_SUCCESS) _arb_vec_indeterminate(res, n); } void arb_poly_log_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { if (n == 0) { arb_poly_zero(res); return; } arb_poly_fit_length(res, n); if (f->length == 0) _arb_vec_indeterminate(res->coeffs, n); else _arb_poly_log_series(res->coeffs, f->coeffs, f->length, n, prec); _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/majorant.c000066400000000000000000000015701461254215100172130ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_majorant(arb_ptr res, arb_srcptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { arb_get_abs_ubound_arf(arb_midref(res + i), vec + i, prec); mag_zero(arb_radref(res + i)); } } void arb_poly_majorant(arb_poly_t res, const arb_poly_t poly, slong prec) { arb_poly_fit_length(res, poly->length); _arb_poly_majorant(res->coeffs, poly->coeffs, poly->length, prec); _arb_poly_set_length(res, poly->length); } flint-3.1.3/src/arb_poly/mul.c000066400000000000000000000026601461254215100161760ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_mul(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) { _arb_poly_mullow(C, A, lenA, B, lenB, lenA + lenB - 1, prec); } void arb_poly_mul(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { arb_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { arb_poly_t temp; arb_poly_init2(temp, len_out); _arb_poly_mul(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); arb_poly_swap(res, temp); arb_poly_clear(temp); } else { arb_poly_fit_length(res, len_out); _arb_poly_mul(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); } _arb_poly_set_length(res, len_out); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/mullow.c000066400000000000000000000077201461254215100167220ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif void _arb_poly_mullow(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, slong prec) { if (n == 1) { arb_mul(res, poly1, poly2, prec); } else if (n <= 7 || len1 <= 7 || len2 <= 7) { _arb_poly_mullow_classical(res, poly1, len1, poly2, len2, n, prec); } else { slong cutoff; double p; if (prec <= 2 * FLINT_BITS) { cutoff = 110; } else { p = log(prec); cutoff = 10000.0 / (p * p * p); cutoff = FLINT_MIN(cutoff, 60); if (poly1 == poly2 && prec >= 256) cutoff *= 1.25; if (poly1 == poly2 && prec >= 4096) cutoff *= 1.25; cutoff = FLINT_MAX(cutoff, 8); } if (2 * FLINT_MIN(len1, len2) <= cutoff || n <= cutoff) _arb_poly_mullow_classical(res, poly1, len1, poly2, len2, n, prec); else _arb_poly_mullow_block(res, poly1, len1, poly2, len2, n, prec); } } void arb_poly_mullow(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; if (len1 == 0 || len2 == 0 || n == 0) { arb_poly_zero(res); return; } n = FLINT_MIN((len1 + len2 - 1), n); len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); /* Hack to avoid temporary allocations with first derivatives. */ if (n <= 2 && !(len1 == 2 && len2 == 2)) { arb_poly_fit_length(res, n); if (n == 1) { arb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); } else if (len2 == 1) { arb_mul(res->coeffs + 1, poly1->coeffs + 1, poly2->coeffs, prec); arb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); } else if (len1 == 1) { arb_mul(res->coeffs + 1, poly2->coeffs + 1, poly1->coeffs, prec); arb_mul(res->coeffs, poly2->coeffs, poly1->coeffs, prec); } else { flint_throw(FLINT_ERROR, "(%s)\n", __func__); #if 0 if (res == poly1 || res == poly2) { arb_t t; arb_init(t); arb_mul(t, poly1->coeffs, poly2->coeffs + 1, prec); arb_addmul(t, poly2->coeffs, poly1->coeffs + 1, prec); arb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); arb_swap(t, res->coeffs + 1); arb_clear(t); } else { arb_mul(res->coeffs, poly1->coeffs, poly2->coeffs, prec); arb_mul(res->coeffs + 1, poly1->coeffs, poly2->coeffs + 1, prec); arb_addmul(res->coeffs + 1, poly2->coeffs, poly1->coeffs + 1, prec); } #endif } _arb_poly_set_length(res, n); _arb_poly_normalise(res); return; } if (res == poly1 || res == poly2) { arb_poly_t t; arb_poly_init2(t, n); _arb_poly_mullow(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); arb_poly_swap(res, t); arb_poly_clear(t); } else { arb_poly_fit_length(res, n); _arb_poly_mullow(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, prec); } _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/mullow_block.c000066400000000000000000000470041461254215100200730ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "arb_poly.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp #else # include #endif void _arb_poly_get_scale(fmpz_t scale, arb_srcptr x, slong xlen, arb_srcptr y, slong ylen) { slong xa, xb, ya, yb, den; fmpz_zero(scale); /* ignore zeros (and infs/nans!); find the first and last finite nonzero entries to determine the scale */ xa = 0; xb = xlen - 1; while (xa < xlen && arf_is_special(arb_midref(x + xa))) xa++; while (xb > xa && arf_is_special(arb_midref(x + xb))) xb--; ya = 0; yb = ylen - 1; while (ya < ylen && arf_is_special(arb_midref(y + ya))) ya++; while (yb > ya && arf_is_special(arb_midref(y + yb))) yb--; /* compute average of exponent differences, weighted by the lengths */ if (xa <= xb && ya <= yb && (xa < xb || ya < yb)) { fmpz_add(scale, scale, ARF_EXPREF(arb_midref(x + xb))); fmpz_sub(scale, scale, ARF_EXPREF(arb_midref(x + xa))); fmpz_add(scale, scale, ARF_EXPREF(arb_midref(y + yb))); fmpz_sub(scale, scale, ARF_EXPREF(arb_midref(y + ya))); den = (xb - xa) + (yb - ya); /* scale = floor(scale / den + 1/2) = floor((2 scale + den) / (2 den)) */ fmpz_mul_2exp(scale, scale, 1); fmpz_add_ui(scale, scale, den); fmpz_fdiv_q_ui(scale, scale, 2 * den); } } /* Break vector into same-exponent blocks where the largest block has a height of at most ALPHA*prec + BETA bits. These are just tuning parameters. Note that ALPHA * MAG_BITS + BETA should be smaller than DOUBLE_BLOCK_MAX_HEIGHT if we want to use doubles for error bounding. */ #define ALPHA 3.0 #define BETA 512 /* Maximum length of block for which we use double multiplication (for longer blocks, we use fmpz_poly multiplication). This is essentially just a tuning parameter, but note that it must be considered when compensating for rounding error below. */ #define DOUBLE_BLOCK_MAX_LENGTH 1000 /* Computing a dot product of length DOUBLE_BLOCK_MAX_LENGTH involving only nonnegative numbers, and then multiplying by this factor, must give an upper bound for the exact dot product (we can assume that no overflow or underflow occurs). The following is certainly sufficient, but it would be nice to include a formal proof here. */ #define DOUBLE_ROUNDING_FACTOR (1.0 + 1e-9) /* Maximum height for which we use double multiplication. Since the dynamic exponent range of doubles is about +/- 1024, this must be less than about 1024 (to allow the product of two numbers). This must also account for adding MAG_BITS bits. */ #define DOUBLE_BLOCK_MAX_HEIGHT 800 /* We divide coefficients by 2^DOUBLE_BLOCK_SHIFT when converting them to doubles, in order to use the whole exponent range. Note that this means numbers of size (2^(-DOUBLE_BLOCK_SHIFT))^2 must not underflow. */ #define DOUBLE_BLOCK_SHIFT (DOUBLE_BLOCK_MAX_HEIGHT / 2) static void _mag_vec_get_fmpz_2exp_blocks(fmpz * coeffs, double * dblcoeffs, fmpz * exps, slong * blocks, const fmpz_t scale, arb_srcptr x, mag_srcptr xm, slong len) { fmpz_t top, bot, t, b, v, block_top, block_bot; slong i, j, s, block, bits, maxheight; int in_zero; mag_srcptr cur; fmpz_init(top); fmpz_init(bot); fmpz_init(t); fmpz_init(b); fmpz_init(v); fmpz_init(block_top); fmpz_init(block_bot); blocks[0] = 0; block = 0; in_zero = 1; maxheight = ALPHA * MAG_BITS + BETA; if (maxheight > DOUBLE_BLOCK_MAX_HEIGHT) flint_throw(FLINT_ERROR, "(%s): maxheight > DOUBLE_BLOCK_MAX_HEIGHT\n", __func__); for (i = 0; i < len; i++) { cur = (x == NULL) ? (xm + i) : arb_radref(x + i); /* Skip (must be zero, since we assume there are no Infs/NaNs). */ if (mag_is_special(cur)) continue; /* Bottom and top exponent of current number */ bits = MAG_BITS; fmpz_set(top, MAG_EXPREF(cur)); fmpz_submul_ui(top, scale, i); fmpz_sub_ui(bot, top, bits); /* Extend current block. */ if (in_zero) { fmpz_swap(block_top, top); fmpz_swap(block_bot, bot); } else { fmpz_max(t, top, block_top); fmpz_min(b, bot, block_bot); fmpz_sub(v, t, b); /* extend current block */ if (fmpz_cmp_ui(v, maxheight) < 0) { fmpz_swap(block_top, t); fmpz_swap(block_bot, b); } else /* start new block */ { /* write exponent for previous block */ fmpz_set(exps + block, block_bot); block++; blocks[block] = i; fmpz_swap(block_top, top); fmpz_swap(block_bot, bot); } } in_zero = 0; } /* write exponent for last block */ fmpz_set(exps + block, block_bot); /* end marker */ blocks[block + 1] = len; /* write the block data */ for (i = 0; blocks[i] != len; i++) { for (j = blocks[i]; j < blocks[i + 1]; j++) { cur = (x == NULL) ? (xm + j) : arb_radref(x + j); if (mag_is_special(cur)) { fmpz_zero(coeffs + j); dblcoeffs[j] = 0.0; } else { mp_limb_t man; double c; man = MAG_MAN(cur); /* TODO: only write and use doubles when block is short? */ /* Divide by 2^(scale * j) */ fmpz_mul_ui(t, scale, j); fmpz_sub(t, MAG_EXPREF(cur), t); fmpz_sub_ui(t, t, MAG_BITS); /* bottom exponent */ s = _fmpz_sub_small(t, exps + i); if (s < 0) flint_throw(FLINT_ERROR, "(%s): s < 0\n", __func__); fmpz_set_ui(coeffs + j, man); fmpz_mul_2exp(coeffs + j, coeffs + j, s); c = man; c = ldexp(c, s - DOUBLE_BLOCK_SHIFT); if (c < 1e-150 || c > 1e150) /* Bug catcher */ flint_throw(FLINT_ERROR, "(%s): c large or big\n", __func__); dblcoeffs[j] = c; } } } fmpz_clear(top); fmpz_clear(bot); fmpz_clear(t); fmpz_clear(b); fmpz_clear(v); fmpz_clear(block_top); fmpz_clear(block_bot); } static void _arb_vec_get_fmpz_2exp_blocks(fmpz * coeffs, fmpz * exps, slong * blocks, const fmpz_t scale, arb_srcptr x, slong len, slong prec) { fmpz_t top, bot, t, b, v, block_top, block_bot; slong i, j, s, block, bits, maxheight; int in_zero; fmpz_init(top); fmpz_init(bot); fmpz_init(t); fmpz_init(b); fmpz_init(v); fmpz_init(block_top); fmpz_init(block_bot); blocks[0] = 0; block = 0; in_zero = 1; if (prec == ARF_PREC_EXACT) maxheight = ARF_PREC_EXACT; else maxheight = ALPHA * prec + BETA; for (i = 0; i < len; i++) { bits = arf_bits(arb_midref(x + i)); /* Skip (must be zero, since we assume there are no Infs/NaNs). */ if (bits == 0) continue; /* Bottom and top exponent of current number */ fmpz_set(top, ARF_EXPREF(arb_midref(x + i))); fmpz_submul_ui(top, scale, i); fmpz_sub_ui(bot, top, bits); /* Extend current block. */ if (in_zero) { fmpz_swap(block_top, top); fmpz_swap(block_bot, bot); } else { fmpz_max(t, top, block_top); fmpz_min(b, bot, block_bot); fmpz_sub(v, t, b); /* extend current block */ if (fmpz_cmp_ui(v, maxheight) < 0) { fmpz_swap(block_top, t); fmpz_swap(block_bot, b); } else /* start new block */ { /* write exponent for previous block */ fmpz_set(exps + block, block_bot); block++; blocks[block] = i; fmpz_swap(block_top, top); fmpz_swap(block_bot, bot); } } in_zero = 0; } /* write exponent for last block */ fmpz_set(exps + block, block_bot); /* end marker */ blocks[block + 1] = len; /* write the block data */ for (i = 0; blocks[i] != len; i++) { for (j = blocks[i]; j < blocks[i + 1]; j++) { if (arf_is_special(arb_midref(x + j))) { fmpz_zero(coeffs + j); } else { /* TODO: make this a single operation */ arf_get_fmpz_2exp(coeffs + j, bot, arb_midref(x + j)); fmpz_mul_ui(t, scale, j); fmpz_sub(t, bot, t); s = _fmpz_sub_small(t, exps + i); if (s < 0) flint_throw(FLINT_ERROR, "(%s): s < 0\n", __func__); fmpz_mul_2exp(coeffs + j, coeffs + j, s); } } } fmpz_clear(top); fmpz_clear(bot); fmpz_clear(t); fmpz_clear(b); fmpz_clear(v); fmpz_clear(block_top); fmpz_clear(block_bot); } static void _arb_poly_addmullow_rad(arb_ptr z, fmpz * zz, const fmpz * xz, const double * xdbl, const fmpz * xexps, const slong * xblocks, slong xlen, const fmpz * yz, const double * ydbl, const fmpz * yexps, const slong * yblocks, slong ylen, slong n) { slong i, j, k, ii, xp, yp, xl, yl, bn; fmpz_t zexp; mag_t t; fmpz_init(zexp); mag_init(t); for (i = 0; (xp = xblocks[i]) != xlen; i++) { for (j = 0; (yp = yblocks[j]) != ylen; j++) { if (xp + yp >= n) continue; xl = xblocks[i + 1] - xp; yl = yblocks[j + 1] - yp; bn = FLINT_MIN(xl + yl - 1, n - xp - yp); xl = FLINT_MIN(xl, bn); yl = FLINT_MIN(yl, bn); fmpz_add_inline(zexp, xexps + i, yexps + j); if (xl > 1 && yl > 1 && (xl < DOUBLE_BLOCK_MAX_LENGTH || yl < DOUBLE_BLOCK_MAX_LENGTH)) { fmpz_add_ui(zexp, zexp, 2 * DOUBLE_BLOCK_SHIFT); for (k = 0; k < bn; k++) { /* Classical multiplication (may round down!) */ double ss = 0.0; for (ii = FLINT_MAX(0, k - yl + 1); ii <= FLINT_MIN(xl - 1, k); ii++) { ss += xdbl[xp + ii] * ydbl[yp + k - ii]; } /* Compensate for rounding error */ ss *= DOUBLE_ROUNDING_FACTOR; mag_set_d_2exp_fmpz(t, ss, zexp); mag_add(arb_radref(z + xp + yp + k), arb_radref(z + xp + yp + k), t); } } else { if (xl >= yl) _fmpz_poly_mullow(zz, xz + xp, xl, yz + yp, yl, bn); else _fmpz_poly_mullow(zz, yz + yp, yl, xz + xp, xl, bn); for (k = 0; k < bn; k++) { mag_set_fmpz_2exp_fmpz(t, zz + k, zexp); mag_add(arb_radref(z + xp + yp + k), arb_radref(z + xp + yp + k), t); } } } } fmpz_clear(zexp); mag_clear(t); } static void _arb_poly_addmullow_block(arb_ptr z, fmpz * zz, const fmpz * xz, const fmpz * xexps, const slong * xblocks, slong xlen, const fmpz * yz, const fmpz * yexps, const slong * yblocks, slong ylen, slong n, slong prec, int squaring) { slong i, j, k, xp, yp, xl, yl, bn; fmpz_t zexp; fmpz_init(zexp); if (squaring) { for (i = 0; (xp = xblocks[i]) != xlen; i++) { if (2 * xp >= n) continue; xl = xblocks[i + 1] - xp; bn = FLINT_MIN(2 * xl - 1, n - 2 * xp); xl = FLINT_MIN(xl, bn); _fmpz_poly_sqrlow(zz, xz + xp, xl, bn); _fmpz_add2_fast(zexp, xexps + i, xexps + i, 0); for (k = 0; k < bn; k++) arb_add_fmpz_2exp(z + 2 * xp + k, z + 2 * xp + k, zz + k, zexp, prec); } } for (i = 0; (xp = xblocks[i]) != xlen; i++) { for (j = squaring ? i + 1 : 0; (yp = yblocks[j]) != ylen; j++) { if (xp + yp >= n) continue; xl = xblocks[i + 1] - xp; yl = yblocks[j + 1] - yp; bn = FLINT_MIN(xl + yl - 1, n - xp - yp); xl = FLINT_MIN(xl, bn); yl = FLINT_MIN(yl, bn); if (xl >= yl) _fmpz_poly_mullow(zz, xz + xp, xl, yz + yp, yl, bn); else _fmpz_poly_mullow(zz, yz + yp, yl, xz + xp, xl, bn); _fmpz_add2_fast(zexp, xexps + i, yexps + j, squaring); for (k = 0; k < bn; k++) arb_add_fmpz_2exp(z + xp + yp + k, z + xp + yp + k, zz + k, zexp, prec); } } fmpz_clear(zexp); } void _arb_poly_mullow_block(arb_ptr z, arb_srcptr x, slong xlen, arb_srcptr y, slong ylen, slong n, slong prec) { slong xmlen, xrlen, ymlen, yrlen, i; fmpz *xz, *yz, *zz; fmpz *xe, *ye; slong *xblocks, *yblocks; int squaring; fmpz_t scale, t; xlen = FLINT_MIN(xlen, n); ylen = FLINT_MIN(ylen, n); squaring = (x == y) && (xlen == ylen); /* Strip trailing zeros */ xmlen = xrlen = xlen; while (xmlen > 0 && arf_is_zero(arb_midref(x + xmlen - 1))) xmlen--; while (xrlen > 0 && mag_is_zero(arb_radref(x + xrlen - 1))) xrlen--; if (squaring) { ymlen = xmlen; yrlen = xrlen; } else { ymlen = yrlen = ylen; while (ymlen > 0 && arf_is_zero(arb_midref(y + ymlen - 1))) ymlen--; while (yrlen > 0 && mag_is_zero(arb_radref(y + yrlen - 1))) yrlen--; } /* We don't know how to deal with infinities or NaNs */ if (!_arb_vec_is_finite(x, xlen) || (!squaring && !_arb_vec_is_finite(y, ylen))) { _arb_poly_mullow_classical(z, x, xlen, y, ylen, n, prec); return; } xlen = FLINT_MAX(xmlen, xrlen); ylen = FLINT_MAX(ymlen, yrlen); /* Start with the zero polynomial */ _arb_vec_zero(z, n); /* Nothing to do */ if (xlen == 0 || ylen == 0) return; n = FLINT_MIN(n, xlen + ylen - 1); fmpz_init(scale); fmpz_init(t); xz = _fmpz_vec_init(xlen); yz = _fmpz_vec_init(ylen); zz = _fmpz_vec_init(n); xe = _fmpz_vec_init(xlen); ye = _fmpz_vec_init(ylen); xblocks = flint_malloc(sizeof(slong) * (xlen + 1)); yblocks = flint_malloc(sizeof(slong) * (ylen + 1)); _arb_poly_get_scale(scale, x, xlen, y, ylen); /* Error propagation */ /* (xm + xr)*(ym + yr) = (xm*ym) + (xr*ym + xm*yr + xr*yr) = (xm*ym) + (xm*yr + xr*(ym + yr)) */ if (xrlen != 0 || yrlen != 0) { mag_ptr tmp; double *xdbl, *ydbl; tmp = _mag_vec_init(FLINT_MAX(xlen, ylen)); xdbl = flint_malloc(sizeof(double) * xlen); ydbl = flint_malloc(sizeof(double) * ylen); /* (xm + xr)^2 = (xm*ym) + (xr^2 + 2 xm xr) = (xm*ym) + xr*(2 xm + xr) */ if (squaring) { _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, x, NULL, xrlen); for (i = 0; i < xlen; i++) { arf_get_mag(tmp + i, arb_midref(x + i)); mag_mul_2exp_si(tmp + i, tmp + i, 1); mag_add(tmp + i, tmp + i, arb_radref(x + i)); } _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, NULL, tmp, xlen); _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xrlen, yz, ydbl, ye, yblocks, xlen, n); } else if (yrlen == 0) { /* xr * |ym| */ _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, x, NULL, xrlen); for (i = 0; i < ymlen; i++) arf_get_mag(tmp + i, arb_midref(y + i)); _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, NULL, tmp, ymlen); _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xrlen, yz, ydbl, ye, yblocks, ymlen, n); } else { /* |xm| * yr */ for (i = 0; i < xmlen; i++) arf_get_mag(tmp + i, arb_midref(x + i)); _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, NULL, tmp, xmlen); _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, y, NULL, yrlen); _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xmlen, yz, ydbl, ye, yblocks, yrlen, n); /* xr*(|ym| + yr) */ if (xrlen != 0) { _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, x, NULL, xrlen); for (i = 0; i < ylen; i++) arb_get_mag(tmp + i, y + i); _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, NULL, tmp, ylen); _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xrlen, yz, ydbl, ye, yblocks, ylen, n); } } _mag_vec_clear(tmp, FLINT_MAX(xlen, ylen)); flint_free(xdbl); flint_free(ydbl); } /* multiply midpoints */ if (xmlen != 0 && ymlen != 0) { _arb_vec_get_fmpz_2exp_blocks(xz, xe, xblocks, scale, x, xmlen, prec); if (squaring) { _arb_poly_addmullow_block(z, zz, xz, xe, xblocks, xmlen, xz, xe, xblocks, xmlen, n, prec, 1); } else { _arb_vec_get_fmpz_2exp_blocks(yz, ye, yblocks, scale, y, ymlen, prec); _arb_poly_addmullow_block(z, zz, xz, xe, xblocks, xmlen, yz, ye, yblocks, ymlen, n, prec, 0); } } /* Unscale. */ if (!fmpz_is_zero(scale)) { fmpz_zero(t); for (i = 0; i < n; i++) { arb_mul_2exp_fmpz(z + i, z + i, t); fmpz_add(t, t, scale); } } _fmpz_vec_clear(xz, xlen); _fmpz_vec_clear(yz, ylen); _fmpz_vec_clear(zz, n); _fmpz_vec_clear(xe, xlen); _fmpz_vec_clear(ye, ylen); flint_free(xblocks); flint_free(yblocks); fmpz_clear(scale); fmpz_clear(t); } void arb_poly_mullow_block(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec) { slong xlen, ylen, zlen; xlen = poly1->length; ylen = poly2->length; if (xlen == 0 || ylen == 0 || n == 0) { arb_poly_zero(res); return; } xlen = FLINT_MIN(xlen, n); ylen = FLINT_MIN(ylen, n); zlen = FLINT_MIN(xlen + ylen - 1, n); if (res == poly1 || res == poly2) { arb_poly_t tmp; arb_poly_init2(tmp, zlen); _arb_poly_mullow_block(tmp->coeffs, poly1->coeffs, xlen, poly2->coeffs, ylen, zlen, prec); arb_poly_swap(res, tmp); arb_poly_clear(tmp); } else { arb_poly_fit_length(res, zlen); _arb_poly_mullow_block(res->coeffs, poly1->coeffs, xlen, poly2->coeffs, ylen, zlen, prec); } _arb_poly_set_length(res, zlen); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/mullow_classical.c000066400000000000000000000064121461254215100207350ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_mullow_classical(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, slong prec) { len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) { arb_mul(res, poly1, poly2, prec); } else if (poly1 == poly2 && len1 == len2) { slong i, start, stop; arb_sqr(res, poly1, prec); arb_mul(res + 1, poly1, poly1 + 1, prec); arb_mul_2exp_si(res + 1, res + 1, 1); for (i = 2; i < FLINT_MIN(n, 2 * len1 - 3); i++) { start = FLINT_MAX(0, i - len1 + 1); stop = FLINT_MIN(len1 - 1, (i + 1) / 2 - 1); arb_dot(res + i, NULL, 0, poly1 + start, 1, poly1 + i - start, -1, stop - start + 1, prec); arb_mul_2exp_si(res + i, res + i, 1); if (i % 2 == 0 && i / 2 < len1) arb_addmul(res + i, poly1 + i / 2, poly1 + i / 2, prec); } if (len1 > 2 && n >= 2 * len1 - 2) { arb_mul(res + 2 * len1 - 3, poly1 + len1 - 1, poly1 + len1 - 2, prec); arb_mul_2exp_si(res + 2 * len1 - 3, res + 2 * len1 - 3, 1); } if (n >= 2 * len1 - 1) arb_sqr(res + 2 * len1 - 2, poly1 + len1 - 1, prec); } else if (len1 == 1) { _arb_vec_scalar_mul(res, poly2, n, poly1, prec); } else if (len2 == 1) { _arb_vec_scalar_mul(res, poly1, n, poly2, prec); } else { slong i, top1, top2; arb_mul(res, poly1, poly2, prec); for (i = 1; i < n; i++) { top1 = FLINT_MIN(len1 - 1, i); top2 = FLINT_MIN(len2 - 1, i); arb_dot(res + i, NULL, 0, poly1 + i - top2, 1, poly2 + top2, -1, top1 + top2 - i + 1, prec); } } } void arb_poly_mullow_classical(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong n, slong prec) { slong len_out; if (poly1->length == 0 || poly2->length == 0 || n == 0) { arb_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (n > len_out) n = len_out; if (res == poly1 || res == poly2) { arb_poly_t t; arb_poly_init2(t, n); _arb_poly_mullow_classical(t->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, prec); arb_poly_swap(res, t); arb_poly_clear(t); } else { arb_poly_fit_length(res, n); _arb_poly_mullow_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, prec); } _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/newton_convergence_factor.c000066400000000000000000000021211461254215100226170ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_newton_convergence_factor(arf_t convergence_factor, arb_srcptr poly, slong len, const arb_t convergence_interval, slong prec) { arb_ptr deriv; arb_t t, u; arb_init(t); arb_init(u); deriv = _arb_vec_init(len - 1); _arb_poly_derivative(deriv, poly, len, prec); _arb_poly_evaluate(t, deriv, len - 1, convergence_interval, prec); _arb_poly_derivative(deriv, deriv, len - 1, prec); _arb_poly_evaluate(u, deriv, len - 2, convergence_interval, prec); arb_div(t, u, t, prec); arb_mul_2exp_si(t, t, -1); arb_get_abs_ubound_arf(convergence_factor, t, prec); _arb_vec_clear(deriv, len - 1); arb_clear(t); arb_clear(u); } flint-3.1.3/src/arb_poly/newton_refine_root.c000066400000000000000000000031131461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" static inline slong _arf_mag(const arf_t c) { slong m = arf_abs_bound_lt_2exp_si(c); return FLINT_MAX(m, 0); } void _arb_poly_newton_refine_root(arb_t r, arb_srcptr poly, slong len, const arb_t start, const arb_t convergence_interval, const arf_t convergence_factor, slong eval_extra_prec, slong prec) { slong precs[FLINT_BITS]; slong i, iters, wp, padding, start_prec; start_prec = arb_rel_accuracy_bits(start); padding = 5 + _arf_mag(convergence_factor); precs[0] = prec + padding; iters = 1; while ((iters < FLINT_BITS) && (precs[iters-1] + padding > 2*start_prec)) { precs[iters] = (precs[iters-1] / 2) + padding; iters++; if (iters == FLINT_BITS) { flint_throw(FLINT_ERROR, "newton_refine_root: initial value too imprecise\n"); } } arb_set(r, start); for (i = iters - 1; i >= 0; i--) { wp = precs[i] + eval_extra_prec; if (!_arb_poly_newton_step(r, poly, len, r, convergence_interval, convergence_factor, wp)) { flint_printf("warning: newton_refine_root: improvement failed\n"); break; } } } flint-3.1.3/src/arb_poly/newton_step.c000066400000000000000000000025611461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" int _arb_poly_newton_step(arb_t xnew, arb_srcptr poly, slong len, const arb_t x, const arb_t convergence_interval, const arf_t convergence_factor, slong prec) { arf_t err; arb_t t, u, v; int result; arf_init(err); arb_init(t); arb_init(u); arb_init(v); arf_set_mag(err, arb_radref(x)); arf_mul(err, err, err, MAG_BITS, ARF_RND_UP); arf_mul(err, err, convergence_factor, MAG_BITS, ARF_RND_UP); arf_set(arb_midref(t), arb_midref(x)); mag_zero(arb_radref(t)); _arb_poly_evaluate2(u, v, poly, len, t, prec); arb_div(u, u, v, prec); arb_sub(u, t, u, prec); arb_add_error_arf(u, err); if (arb_contains(convergence_interval, u) && (mag_cmp(arb_radref(u), arb_radref(x)) < 0)) { arb_swap(xnew, u); result = 1; } else { arb_set(xnew, x); result = 0; } arb_clear(t); arb_clear(u); arb_clear(v); arf_clear(err); return result; } flint-3.1.3/src/arb_poly/normalise.c000066400000000000000000000011051461254215100173630ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_normalise(arb_poly_t poly) { slong i; for (i = poly->length - 1; (i >= 0) && arb_is_zero(poly->coeffs + i); i--); poly->length = i + 1; } flint-3.1.3/src/arb_poly/nth_derivative.c000066400000000000000000000024341461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2023 Joel Dahne This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_nth_derivative(arb_ptr res, arb_srcptr poly, ulong n, slong len, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_nth_derivative(res, poly, n, len, ctx) != GR_SUCCESS) _arb_vec_indeterminate(res, n); } void arb_poly_nth_derivative(arb_poly_t res, const arb_poly_t poly, ulong n, slong prec) { const slong len = poly->length; if (len <= n) { arb_poly_zero(res); } else if (n == 0) { arb_poly_set(res, poly); } else if (n == 1) { arb_poly_fit_length(res, len - 1); _arb_poly_derivative(res->coeffs, poly->coeffs, len, prec); _arb_poly_set_length(res, len - 1); } else { arb_poly_fit_length(res, len - n); _arb_poly_nth_derivative(res->coeffs, poly->coeffs, n, len, prec); _arb_poly_set_length(res, len - n); } } flint-3.1.3/src/arb_poly/overlaps.c000066400000000000000000000020411461254215100172250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" int _arb_poly_overlaps(arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2) { slong i; for (i = 0; i < len2; i++) if (!arb_overlaps(poly1 + i, poly2 + i)) return 0; for (i = len2; i < len1; i++) if (!arb_contains_zero(poly1 + i)) return 0; return 1; } int arb_poly_overlaps(const arb_poly_t poly1, const arb_poly_t poly2) { slong len1 = poly1->length; slong len2 = poly2->length; if (len1 >= len2) return _arb_poly_overlaps(poly1->coeffs, len1, poly2->coeffs, len2); else return _arb_poly_overlaps(poly2->coeffs, len2, poly1->coeffs, len1); } flint-3.1.3/src/arb_poly/pow_arb_series.c000066400000000000000000000073041461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" /* (a + bx^c)^g where a = f[0] and b = f[flen-1] */ void _arb_poly_binomial_pow_arb_series(arb_ptr h, arb_srcptr f, slong flen, const arb_t g, slong len, slong prec) { slong i, j, d; arb_t t; arb_init(t); d = flen - 1; arb_pow(h, f, g, prec); arb_div(t, f + d, f, prec); for (i = 1, j = d; j < len; i++, j += d) { arb_sub_ui(h + j, g, i - 1, prec); arb_mul(h + j, h + j, h + j - d, prec); arb_mul(h + j, h + j, t, prec); arb_div_ui(h + j, h + j, i, prec); } if (d > 1) { for (i = 1; i < len; i++) if (i % d != 0) arb_zero(h + i); } arb_clear(t); return; } void _arb_poly_pow_arb_series(arb_ptr h, arb_srcptr f, slong flen, const arb_t g, slong len, slong prec) { int f_binomial, g_exact, g_int; while (flen > 0 && arb_is_zero(f + flen - 1)) flen--; if (flen <= 1) { arb_pow(h, f, g, prec); _arb_vec_zero(h + 1, len - 1); return; } g_exact = arb_is_exact(g); g_int = arb_is_int(g); f_binomial = _arb_vec_is_zero(f + 1, flen - 2); /* g = small integer */ if (g_exact && g_int && arf_cmpabs_2exp_si(arb_midref(g), FLINT_BITS - 1) < 0) { slong e, hlen; e = arf_get_si(arb_midref(g), ARF_RND_DOWN); hlen = poly_pow_length(flen, FLINT_ABS(e), len); if (e >= 0) { _arb_poly_pow_ui_trunc_binexp(h, f, flen, e, hlen, prec); _arb_vec_zero(h + hlen, len - hlen); return; } else if (!f_binomial) { arb_ptr t; t = _arb_vec_init(hlen); _arb_poly_pow_ui_trunc_binexp(t, f, flen, -e, hlen, prec); _arb_poly_inv_series(h, t, hlen, len, prec); _arb_vec_clear(t, hlen); return; } } /* (a + bx^c)^g */ if (f_binomial) { _arb_poly_binomial_pow_arb_series(h, f, flen, g, len, prec); return; } /* g = +/- 1/2 */ if (g_exact && arf_cmpabs_2exp_si(arb_midref(g), -1) == 0) { if (arf_sgn(arb_midref(g)) > 0) _arb_poly_sqrt_series(h, f, flen, len, prec); else _arb_poly_rsqrt_series(h, f, flen, len, prec); return; } /* f^g = exp(g*log(f)) */ _arb_poly_log_series(h, f, flen, len, prec); _arb_vec_scalar_mul(h, h, len, g, prec); _arb_poly_exp_series(h, h, len, len, prec); } void arb_poly_pow_arb_series(arb_poly_t h, const arb_poly_t f, const arb_t g, slong len, slong prec) { slong flen; flen = f->length; flen = FLINT_MIN(flen, len); if (len == 0) { arb_poly_zero(h); return; } if (arb_is_zero(g)) { arb_poly_one(h); return; } if (flen == 0) { arb_poly_zero(h); return; } if (f == h) { arb_poly_t t; arb_poly_init2(t, len); _arb_poly_pow_arb_series(t->coeffs, f->coeffs, flen, g, len, prec); _arb_poly_set_length(t, len); _arb_poly_normalise(t); arb_poly_swap(t, h); arb_poly_clear(t); } else { arb_poly_fit_length(h, len); _arb_poly_pow_arb_series(h->coeffs, f->coeffs, flen, g, len, prec); _arb_poly_set_length(h, len); _arb_poly_normalise(h); } } flint-3.1.3/src/arb_poly/pow_series.c000066400000000000000000000045241461254215100175610ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_pow_series(arb_ptr h, arb_srcptr f, slong flen, arb_srcptr g, slong glen, slong len, slong prec) { if (glen == 1) { _arb_poly_pow_arb_series(h, f, flen, g, len, prec); return; } /* f^g = exp(g * log(f)) */ if (flen == 1) { arb_t t; arb_init(t); arb_log(t, f, prec); _arb_vec_scalar_mul(h, g, glen, t, prec); _arb_poly_exp_series(h, h, glen, len, prec); arb_clear(t); } else { arb_ptr t; t = _arb_vec_init(len); _arb_poly_log_series(t, f, flen, len, prec); _arb_poly_mullow(h, t, len, g, glen, len, prec); _arb_poly_exp_series(h, h, len, len, prec); _arb_vec_clear(t, len); } } void arb_poly_pow_series(arb_poly_t h, const arb_poly_t f, const arb_poly_t g, slong len, slong prec) { slong flen, glen; flen = f->length; glen = g->length; flen = FLINT_MIN(flen, len); glen = FLINT_MIN(glen, len); if (len == 0) { arb_poly_zero(h); return; } if (glen == 0) { arb_poly_one(h); return; } if (flen == 0) { arb_poly_zero(h); return; } if (flen == 1 && glen == 1) { arb_poly_fit_length(h, 1); arb_pow(h->coeffs, f->coeffs, g->coeffs, prec); _arb_poly_set_length(h, 1); _arb_poly_normalise(h); return; } if (f == h || g == h) { arb_poly_t t; arb_poly_init2(t, len); _arb_poly_pow_series(t->coeffs, f->coeffs, flen, g->coeffs, glen, len, prec); _arb_poly_set_length(t, len); _arb_poly_normalise(t); arb_poly_swap(t, h); arb_poly_clear(t); } else { arb_poly_fit_length(h, len); _arb_poly_pow_series(h->coeffs, f->coeffs, flen, g->coeffs, glen, len, prec); _arb_poly_set_length(h, len); _arb_poly_normalise(h); } } flint-3.1.3/src/arb_poly/pow_ui.c000066400000000000000000000027201461254215100167000ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_pow_ui(arb_ptr res, arb_srcptr f, slong flen, ulong exp, slong prec) { _arb_poly_pow_ui_trunc_binexp(res, f, flen, exp, exp * (flen - 1) + 1, prec); } void arb_poly_pow_ui(arb_poly_t res, const arb_poly_t poly, ulong exp, slong prec) { slong flen, rlen; flen = poly->length; if (exp == 0) { arb_poly_one(res); } else if (flen == 0) { arb_poly_zero(res); } else { rlen = exp * (flen - 1) + 1; if (res != poly) { arb_poly_fit_length(res, rlen); _arb_poly_pow_ui(res->coeffs, poly->coeffs, flen, exp, prec); _arb_poly_set_length(res, rlen); _arb_poly_normalise(res); } else { arb_poly_t t; arb_poly_init2(t, rlen); _arb_poly_pow_ui(t->coeffs, poly->coeffs, flen, exp, prec); _arb_poly_set_length(t, rlen); _arb_poly_normalise(t); arb_poly_swap(res, t); arb_poly_clear(t); } } } flint-3.1.3/src/arb_poly/pow_ui_trunc_binexp.c000066400000000000000000000040031461254215100214540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" void _arb_poly_pow_ui_trunc_binexp(arb_ptr res, arb_srcptr f, slong flen, ulong exp, slong len, slong prec) { if (exp <= 2) { if (exp == 0) arb_one(res); else if (exp == 1) _arb_vec_set_round(res, f, len, prec); else _arb_poly_mullow(res, f, flen, f, flen, len, prec); } else if (!_arb_vec_is_finite(f, flen)) { _arb_vec_indeterminate(res, len); } else { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); GR_MUST_SUCCEED(_gr_poly_pow_series_ui_binexp(res, f, flen, exp, len, ctx)); } } void arb_poly_pow_ui_trunc_binexp(arb_poly_t res, const arb_poly_t poly, ulong exp, slong len, slong prec) { slong flen, rlen; flen = poly->length; if (exp == 0 && len != 0) { arb_poly_one(res); } else if (flen == 0 || len == 0) { arb_poly_zero(res); } else { rlen = poly_pow_length(flen, exp, len); if (res != poly) { arb_poly_fit_length(res, rlen); _arb_poly_pow_ui_trunc_binexp(res->coeffs, poly->coeffs, flen, exp, rlen, prec); _arb_poly_set_length(res, rlen); _arb_poly_normalise(res); } else { arb_poly_t t; arb_poly_init2(t, rlen); _arb_poly_pow_ui_trunc_binexp(t->coeffs, poly->coeffs, flen, exp, rlen, prec); _arb_poly_set_length(t, rlen); _arb_poly_normalise(t); arb_poly_swap(res, t); arb_poly_clear(t); } } } flint-3.1.3/src/arb_poly/product_roots.c000066400000000000000000000033761461254215100203140ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_product_roots(arb_ptr poly, arb_srcptr xs, slong n, slong prec) { if (n == 0) { arb_one(poly); } else if (n == 1) { arb_neg(poly, xs); arb_one(poly + 1); } else if (n == 2) { arb_mul(poly, xs + 0, xs + 1, prec); arb_add(poly + 1, xs + 0, xs + 1, prec); arb_neg(poly + 1, poly + 1); arb_one(poly + 2); } else if (n == 3) { arb_mul(poly + 1, xs, xs + 1, prec); arb_mul(poly, poly + 1, xs + 2, prec); arb_neg(poly, poly); arb_add(poly + 2, xs, xs + 1, prec); arb_addmul(poly + 1, poly + 2, xs + 2, prec); arb_add(poly + 2, poly + 2, xs + 2, prec); arb_neg(poly + 2, poly + 2); arb_one(poly + 3); } else { const slong m = (n + 1) / 2; arb_ptr tmp; tmp = _arb_vec_init(n + 2); _arb_poly_product_roots(tmp, xs, m, prec); _arb_poly_product_roots(tmp + m + 1, xs + m, n - m, prec); _arb_poly_mul_monic(poly, tmp, m + 1, tmp + m + 1, n - m + 1, prec); _arb_vec_clear(tmp, n + 2); } } void arb_poly_product_roots(arb_poly_t poly, arb_srcptr xs, slong n, slong prec) { arb_poly_fit_length(poly, n + 1); _arb_poly_product_roots(poly->coeffs, xs, n, prec); _arb_poly_set_length(poly, n + 1); } flint-3.1.3/src/arb_poly/product_roots_complex.c000066400000000000000000000054561461254215100220440ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "arb_poly.h" void _arb_poly_product_roots_complex(arb_ptr poly, arb_srcptr r, slong rn, acb_srcptr c, slong cn, slong prec) { if (rn == 0 && cn == 0) { arb_one(poly); } else if (rn == 1 && cn == 0) { arb_neg(poly, r); arb_one(poly + 1); } else if (rn == 2 && cn == 0) { arb_mul(poly, r + 0, r + 1, prec); arb_add(poly + 1, r + 0, r + 1, prec); arb_neg(poly + 1, poly + 1); arb_one(poly + 2); } else if (rn == 3 && cn == 0) { arb_mul(poly + 1, r, r + 1, prec); arb_mul(poly, poly + 1, r + 2, prec); arb_neg(poly, poly); arb_add(poly + 2, r, r + 1, prec); arb_addmul(poly + 1, poly + 2, r + 2, prec); arb_add(poly + 2, poly + 2, r + 2, prec); arb_neg(poly + 2, poly + 2); arb_one(poly + 3); } else if (rn == 0 && cn == 1) { arb_mul(poly, acb_realref(c), acb_realref(c), prec); arb_addmul(poly, acb_imagref(c), acb_imagref(c), prec); arb_mul_2exp_si(poly + 1, acb_realref(c), 1); arb_neg(poly + 1, poly + 1); arb_one(poly + 2); } else if (rn == 1 && cn == 1) { arb_mul(poly + 1, acb_realref(c), acb_realref(c), prec); arb_addmul(poly + 1, acb_imagref(c), acb_imagref(c), prec); arb_mul(poly, poly + 1, r, prec); arb_neg(poly, poly); arb_mul_2exp_si(poly + 2, acb_realref(c), 1); arb_addmul(poly + 1, poly + 2, r, prec); arb_add(poly + 2, poly + 2, r, prec); arb_neg(poly + 2, poly + 2); arb_one(poly + 3); } else { slong rm, cm, rm2, cm2; arb_ptr tmp, tmp2; rm = (rn + 1) / 2; cm = cn / 2; rm2 = rn - rm; cm2 = cn - cm; tmp = _arb_vec_init(rn + 2 * cn + 2); tmp2 = tmp + rm + (2 * cm) + 1; _arb_poly_product_roots_complex(tmp, r, rm, c, cm, prec); _arb_poly_product_roots_complex(tmp2, r + rm, rm2, c + cm, cm2, prec); _arb_poly_mul_monic(poly, tmp, rm + 2 * cm + 1, tmp2, rm2 + 2 * cm2 + 1, prec); _arb_vec_clear(tmp, rn + 2 * cn + 2); } } void arb_poly_product_roots_complex(arb_poly_t poly, arb_srcptr r, slong rn, acb_srcptr c, slong cn, slong prec) { arb_poly_fit_length(poly, rn + 2 * cn + 1); _arb_poly_product_roots_complex(poly->coeffs, r, rn, c, cn, prec); _arb_poly_set_length(poly, rn + 2 * cn + 1); } flint-3.1.3/src/arb_poly/randtest.c000066400000000000000000000015551461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_randtest(arb_poly_t poly, flint_rand_t state, slong len, slong prec, slong mag_bits) { slong i; arb_poly_fit_length(poly, len); if (n_randint(state, 2)) for (i = 0; i < len; i++) arb_randtest(poly->coeffs + i, state, prec, mag_bits); else for (i = 0; i < len; i++) arb_randtest_precise(poly->coeffs + i, state, prec, mag_bits); _arb_poly_set_length(poly, len); _arb_poly_normalise(poly); } flint-3.1.3/src/arb_poly/reverse.c000066400000000000000000000017131461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_reverse(arb_ptr res, arb_srcptr poly, slong len, slong n) { if (res == poly) { slong i; for (i = 0; i < n / 2; i++) { arb_struct t = res[i]; res[i] = res[n - 1 - i]; res[n - 1 - i] = t; } for (i = 0; i < n - len; i++) arb_zero(res + i); } else { slong i; for (i = 0; i < n - len; i++) arb_zero(res + i); for (i = 0; i < len; i++) arb_set(res + (n - len) + i, poly + (len - 1) - i); } } flint-3.1.3/src/arb_poly/revert_series.c000066400000000000000000000027571461254215100202710ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" #include "arb_poly.h" void _arb_poly_revert_series(arb_ptr Qinv, arb_srcptr Q, slong Qlen, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_revert_series(Qinv, Q, Qlen, n, ctx) != GR_SUCCESS) _arb_vec_indeterminate(Qinv, n); } void arb_poly_revert_series(arb_poly_t Qinv, const arb_poly_t Q, slong n, slong prec) { slong Qlen = Q->length; if (Qlen < 2 || !arb_is_zero(Q->coeffs) || arb_contains_zero(Q->coeffs + 1)) { flint_throw(FLINT_ERROR, "(arb_poly_revert_series): Input must have " "zero constant term and nonzero coefficient of x^1.\n"); } if (Qinv != Q) { arb_poly_fit_length(Qinv, n); _arb_poly_revert_series(Qinv->coeffs, Q->coeffs, Qlen, n, prec); } else { arb_poly_t t; arb_poly_init2(t, n); _arb_poly_revert_series(t->coeffs, Q->coeffs, Qlen, n, prec); arb_poly_swap(Qinv, t); arb_poly_clear(t); } _arb_poly_set_length(Qinv, n); _arb_poly_normalise(Qinv); } flint-3.1.3/src/arb_poly/rgamma_series.c000066400000000000000000000133451461254215100202210ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" slong arf_get_si(const arf_t x, arf_rnd_t rnd); void _arb_poly_lgamma_series_at_one(arb_ptr u, slong len, slong prec); void arb_hypgeom_gamma_stirling_choose_param(int * reflect, slong * r, slong * n, const arb_t x, int use_reflect, int digamma, slong prec); void _arb_poly_gamma_stirling_eval(arb_ptr res, const arb_t z, slong n, slong num, slong prec); void _arb_poly_rgamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { int reflect, isint; slong i, rflen, r, n, wp; arb_ptr t, u, v; arb_struct f[2]; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_rgamma(res, h, prec); _arb_vec_zero(res + 1, len - 1); return; } isint = arb_is_int(h); if (len <= 2 && isint && arf_sgn(arb_midref(h)) <= 0) { int even = arf_is_int_2exp_si(arb_midref(h), 1); /* use res[0] as tmp to allow aliasing */ arb_sub_ui(res, h, 1, prec); arb_neg(res, res); arb_gamma(res, res, prec); arb_mul(res + 1, h + 1, res, prec); if (!even) arb_neg(res + 1, res + 1); arb_zero(res); return; } wp = prec + FLINT_BIT_COUNT(prec); t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); arb_init(f); arb_init(f + 1); /* use zeta values at small integers */ if (isint && (arf_cmpabs_ui(arb_midref(h), prec / 2) < 0)) { r = arf_get_si(arb_midref(h), ARF_RND_DOWN); _arb_poly_lgamma_series_at_one(u, len, wp); _arb_vec_neg(u, u, len); _arb_poly_exp_series(t, u, len, len, wp); if (r == 1) { _arb_vec_swap(v, t, len); } else if (r <= 0) { arb_set(f, h); arb_one(f + 1); rflen = FLINT_MIN(len, 2 - r); _arb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), 1 - r, rflen, wp); _arb_poly_mullow(v, t, len, u, rflen, len, wp); } else { arb_one(f); arb_one(f + 1); rflen = FLINT_MIN(len, r); _arb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r - 1, rflen, wp); /* TODO: use div_series? */ _arb_poly_inv_series(u, v, rflen, len, wp); _arb_poly_mullow(v, t, len, u, len, len, wp); } } else { /* otherwise use Stirling series */ arb_hypgeom_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp); /* rgamma(h) = (gamma(1-h+r) sin(pi h)) / (rf(1-h, r) * pi), h = h0 + t*/ if (reflect) { /* u = gamma(r+1-h) */ arb_sub_ui(f, h, r + 1, wp); arb_neg(f, f); _arb_poly_gamma_stirling_eval(t, f, n, len, wp); _arb_poly_exp_series(u, t, len, len, wp); for (i = 1; i < len; i += 2) arb_neg(u + i, u + i); /* v = sin(pi x) */ arb_set(f, h); arb_one(f + 1); _arb_poly_sin_pi_series(v, f, 2, len, wp); _arb_poly_mullow(t, u, len, v, len, len, wp); /* rf(1-h,r) * pi */ if (r == 0) { arb_const_pi(u, wp); _arb_vec_scalar_div(v, t, len, u, wp); } else { arb_sub_ui(f, h, 1, wp); arb_neg(f, f); arb_set_si(f + 1, -1); rflen = FLINT_MIN(len, r + 1); _arb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r, rflen, wp); arb_const_pi(u, wp); _arb_vec_scalar_mul(v, v, rflen, u, wp); /* divide by rising factorial */ /* TODO: might better to use div_series, when it has a good basecase */ _arb_poly_inv_series(u, v, rflen, len, wp); _arb_poly_mullow(v, t, len, u, len, len, wp); } } else { /* rgamma(h) = rgamma(h+r) rf(h,r) */ if (r == 0) { arb_add_ui(f, h, r, wp); _arb_poly_gamma_stirling_eval(t, f, n, len, wp); _arb_vec_neg(t, t, len); _arb_poly_exp_series(v, t, len, len, wp); } else { arb_set(f, h); arb_one(f + 1); rflen = FLINT_MIN(len, r + 1); _arb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, wp); arb_add_ui(f, h, r, wp); _arb_poly_gamma_stirling_eval(v, f, n, len, wp); _arb_vec_neg(v, v, len); _arb_poly_exp_series(u, v, len, len, wp); _arb_poly_mullow(v, u, len, t, rflen, len, wp); } } } /* compose with nonconstant part */ arb_zero(t); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, v, len, t, hlen, len, prec); arb_clear(f); arb_clear(f + 1); _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); } void arb_poly_rgamma_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { if (f->length == 0 || n == 0) { arb_poly_zero(res); } else { arb_poly_fit_length(res, n); _arb_poly_rgamma_series(res->coeffs, f->coeffs, f->length, n, prec); _arb_poly_set_length(res, n); _arb_poly_normalise(res); } } flint-3.1.3/src/arb_poly/riemann_siegel_theta_series.c000066400000000000000000000036601461254215100231220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void _arb_poly_riemann_siegel_theta_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { acb_ptr s; arb_t u; slong i; hlen = FLINT_MIN(hlen, len); s = _acb_vec_init(len); arb_init(u); /* s = 1/4 + (1/2) i h */ for (i = 0; i < hlen; i++) arb_mul_2exp_si(acb_imagref(s + i), h + i, -1); arb_one(u); arb_mul_2exp_si(u, u, -2); arb_add(acb_realref(s), acb_realref(s), u, prec); /* log gamma */ _acb_poly_lgamma_series(s, s, hlen, len, prec); /* imaginary part */ for (i = 0; i < len; i++) arb_set(res + i, acb_imagref(s + i)); /* subtract log(pi)/2 * h */ arb_const_pi(u, prec); arb_log(u, u, prec); arb_mul_2exp_si(u, u, -1); arb_neg(u, u); _arb_vec_scalar_addmul(res, h, hlen, u, prec); _acb_vec_clear(s, len); arb_clear(u); } void arb_poly_riemann_siegel_theta_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { if (n == 0 || f->length == 0) { arb_poly_zero(res); return; } if (res == f) { arb_poly_t tmp; arb_poly_init2(tmp, n); _arb_poly_riemann_siegel_theta_series(tmp->coeffs, f->coeffs, f->length, n, prec); arb_poly_swap(res, tmp); arb_poly_clear(tmp); } else { arb_poly_fit_length(res, n); _arb_poly_riemann_siegel_theta_series(res->coeffs, f->coeffs, f->length, n, prec); } _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/riemann_siegel_z_series.c000066400000000000000000000050301461254215100222570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" void _arb_poly_riemann_siegel_z_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { slong i, alloc; arb_ptr t, u, v, w, q; hlen = FLINT_MIN(hlen, len); alloc = 5 * len; t = _arb_vec_init(alloc); u = t + len; v = u + len; w = v + len; q = w + len; /* (v + wi) = zeta(1/2 + i (s+x)) */ { acb_ptr sx, z; acb_t a; slong slen = FLINT_MIN(len, 2); z = _acb_vec_init(len); sx = _acb_vec_init(slen); acb_init(a); acb_one(a); acb_one(sx); acb_mul_2exp_si(sx, sx, -1); arb_set(acb_imagref(sx), h); if (slen > 1) arb_one(acb_imagref(sx + 1)); _acb_poly_zeta_series(z, sx, slen, a, 0, len, prec); for (i = 0; i < len; i++) { arb_set(v + i, acb_realref(z + i)); arb_set(w + i, acb_imagref(z + i)); } acb_clear(a); _acb_vec_clear(z, len); _acb_vec_clear(sx, slen); } /* (t + ui) = exp(i theta(s+x)) */ arb_set(u, h); if (len > 1) arb_one(u + 1); _arb_poly_riemann_siegel_theta_series(t, u, 2, len, prec); _arb_poly_sin_cos_series(u, t, t, len, len, prec); /* (t+ui)(v+wi) = (tv-uw) + (tw+uv)i */ _arb_poly_mullow(q, t, len, v, len, len, prec); _arb_poly_mullow(t, u, len, w, len, len, prec); _arb_vec_sub(t, q, t, len, prec); /* compose with nonconstant part */ arb_zero(u); _arb_vec_set(u + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, t, len, u, hlen, len, prec); _arb_vec_clear(t, alloc); } void arb_poly_riemann_siegel_z_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { if (n == 0) { arb_poly_zero(res); return; } arb_poly_fit_length(res, n); if (f->length == 0) { arb_t t; arb_init(t); _arb_poly_riemann_siegel_z_series(res->coeffs, t, 1, n, prec); arb_clear(t); } else { _arb_poly_riemann_siegel_z_series(res->coeffs, f->coeffs, f->length, n, prec); } _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/rising_ui_series.c000066400000000000000000000047371461254215100207520ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" static void _arb_poly_rising_ui_series_bsplit(arb_ptr res, arb_srcptr f, slong flen, ulong a, ulong b, slong trunc, slong prec) { flen = FLINT_MIN(flen, trunc); if (b - a == 1) { arb_add_ui(res, f, a, prec); _arb_vec_set(res + 1, f + 1, flen - 1); } else { arb_ptr L, R; slong len1, len2; slong m = a + (b - a) / 2; len1 = poly_pow_length(flen, m - a, trunc); len2 = poly_pow_length(flen, b - m, trunc); L = _arb_vec_init(len1 + len2); R = L + len1; _arb_poly_rising_ui_series_bsplit(L, f, flen, a, m, trunc, prec); _arb_poly_rising_ui_series_bsplit(R, f, flen, m, b, trunc, prec); _arb_poly_mullow(res, L, len1, R, len2, FLINT_MIN(trunc, len1 + len2 - 1), prec); _arb_vec_clear(L, len1 + len2); } } void _arb_poly_rising_ui_series(arb_ptr res, arb_srcptr f, slong flen, ulong r, slong trunc, slong prec) { if (trunc == 1 || flen == 1) { arb_rising_ui(res, f, r, prec); _arb_vec_zero(res + 1, trunc - 1); } else if (trunc == 2) { arb_rising2_ui(res, res + 1, f, r, prec); arb_mul(res + 1, res + 1, f + 1, prec); } else { _arb_poly_rising_ui_series_bsplit(res, f, flen, 0, r, trunc, prec); } } void arb_poly_rising_ui_series(arb_poly_t res, const arb_poly_t f, ulong r, slong trunc, slong prec) { slong len; if ((f->length == 0 && r != 0) || trunc == 0) { arb_poly_zero(res); return; } if (r == 0) { arb_poly_one(res); return; } len = poly_pow_length(f->length, r, trunc); if (f == res) { arb_poly_t tmp; arb_poly_init(tmp); arb_poly_rising_ui_series(tmp, f, r, len, prec); arb_poly_swap(tmp, res); arb_poly_clear(tmp); } else { arb_poly_fit_length(res, len); _arb_poly_rising_ui_series(res->coeffs, f->coeffs, f->length, r, len, prec); _arb_poly_set_length(res, len); _arb_poly_normalise(res); } } flint-3.1.3/src/arb_poly/root_bound_fujiwara.c000066400000000000000000000023221461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_root_bound_fujiwara(mag_t bound, arb_srcptr poly, slong len) { mag_t t, u, v; slong i; if (len <= 1) { mag_inf(bound); return; } mag_init(t); mag_init(u); mag_init(v); /* u = 1/leading */ arb_get_mag_lower(t, poly + len - 1); mag_one(u); mag_div(u, u, t); mag_zero(v); for (i = 0; i < len - 1; i++) { arb_get_mag(t, poly + len - 2 - i); mag_mul(t, t, u); if (i == len - 2) mag_mul_2exp_si(t, t, -1); mag_root(t, t, i + 1); mag_max(v, v, t); } mag_mul_2exp_si(bound, v, 1); mag_clear(t); mag_clear(u); mag_clear(v); } void arb_poly_root_bound_fujiwara(mag_t bound, arb_poly_t poly) { _arb_poly_root_bound_fujiwara(bound, poly->coeffs, poly->length); } flint-3.1.3/src/arb_poly/rsqrt_series.c000066400000000000000000000044621461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_rsqrt_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); while (hlen > 0 && arb_is_zero(h + hlen - 1)) hlen--; if (hlen <= 1) { arb_rsqrt(g, h, prec); _arb_vec_zero(g + 1, len - 1); } else if (len == 2) { arb_rsqrt(g, h, prec); arb_div(g + 1, h + 1, h, prec); arb_mul(g + 1, g + 1, g, prec); arb_mul_2exp_si(g + 1, g + 1, -1); arb_neg(g + 1, g + 1); } else if (_arb_vec_is_zero(h + 1, hlen - 2)) { arb_t t; arb_init(t); arf_set_si_2exp_si(arb_midref(t), -1, -1); _arb_poly_binomial_pow_arb_series(g, h, hlen, t, len, prec); arb_clear(t); } else { arb_ptr t, u; slong tlen; t = _arb_vec_init(2 * len); u = t + len; arb_rsqrt(g, h, prec); NEWTON_INIT(1, len) NEWTON_LOOP(m, n) tlen = FLINT_MIN(2 * m - 1, n); _arb_poly_mullow(t, g, m, g, m, tlen, prec); _arb_poly_mullow(u, g, m, t, tlen, n, prec); _arb_poly_mullow(t, u, n, h, hlen, n, prec); _arb_vec_scalar_mul_2exp_si(g + m, t + m, n - m, -1); _arb_vec_neg(g + m, g + m, n - m); NEWTON_END_LOOP NEWTON_END _arb_vec_clear(t, 2 * len); } } void arb_poly_rsqrt_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { if (n == 0) { arb_poly_zero(g); return; } if (g == h) { arb_poly_t t; arb_poly_init(t); arb_poly_rsqrt_series(t, h, n, prec); arb_poly_swap(g, t); arb_poly_clear(t); return; } arb_poly_fit_length(g, n); if (h->length == 0) _arb_vec_indeterminate(g->coeffs, n); else _arb_poly_rsqrt_series(g->coeffs, h->coeffs, h->length, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/set.c000066400000000000000000000011651461254215100161730ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_set(arb_poly_t dest, const arb_poly_t src) { slong len = arb_poly_length(src); arb_poly_fit_length(dest, len); _arb_vec_set(dest->coeffs, src->coeffs, len); _arb_poly_set_length(dest, len); } flint-3.1.3/src/arb_poly/set_coeff_arb.c000066400000000000000000000013261461254215100201600ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_set_coeff_arb(arb_poly_t poly, slong n, const arb_t x) { arb_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { _arb_vec_zero(poly->coeffs + poly->length, n - poly->length); poly->length = n + 1; } arb_set(poly->coeffs + n, x); _arb_poly_normalise(poly); } flint-3.1.3/src/arb_poly/set_coeff_si.c000066400000000000000000000013221461254215100200230ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_set_coeff_si(arb_poly_t poly, slong n, slong x) { arb_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { _arb_vec_zero(poly->coeffs + poly->length, n - poly->length); poly->length = n + 1; } arb_set_si(poly->coeffs + n, x); _arb_poly_normalise(poly); } flint-3.1.3/src/arb_poly/set_fmpq_poly.c000066400000000000000000000014431461254215100202600ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "arb_poly.h" void arb_poly_set_fmpq_poly(arb_poly_t poly, const fmpq_poly_t src, slong prec) { slong i, len = src->length; arb_poly_fit_length(poly, len); _arb_poly_set_length(poly, len); for (i = 0; i < len; i++) { fmpq t; t.num = (fmpz) src->coeffs[i]; t.den = (fmpz) *src->den; arb_set_fmpq(poly->coeffs + i, &t, prec); } } flint-3.1.3/src/arb_poly/set_fmpz_poly.c000066400000000000000000000013311461254215100202650ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb_poly.h" void arb_poly_set_fmpz_poly(arb_poly_t poly, const fmpz_poly_t src, slong prec) { slong i, len = fmpz_poly_length(src); arb_poly_fit_length(poly, len); _arb_poly_set_length(poly, len); for (i = 0; i < len; i++) arb_set_round_fmpz(poly->coeffs + i, src->coeffs + i, prec); } flint-3.1.3/src/arb_poly/set_length.c000066400000000000000000000011641461254215100175330ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_set_length(arb_poly_t poly, slong len) { slong i; if (poly->length > len) { for (i = len; i < poly->length; i++) arb_zero(poly->coeffs + i); } poly->length = len; } flint-3.1.3/src/arb_poly/set_round.c000066400000000000000000000012231461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_set_round(arb_poly_t dest, const arb_poly_t src, slong prec) { slong len = arb_poly_length(src); arb_poly_fit_length(dest, len); _arb_vec_set_round(dest->coeffs, src->coeffs, len, prec); _arb_poly_set_length(dest, len); } flint-3.1.3/src/arb_poly/set_si.c000066400000000000000000000012111461254215100166560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_set_si(arb_poly_t poly, slong c) { if (c == 0) { arb_poly_zero(poly); } else { arb_poly_fit_length(poly, 1); arb_set_si(poly->coeffs, c); _arb_poly_set_length(poly, 1); } } flint-3.1.3/src/arb_poly/set_trunc.c000066400000000000000000000015321461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_set_trunc(arb_poly_t res, const arb_poly_t poly, slong n) { if (poly == res) { arb_poly_truncate(res, n); } else { slong rlen; rlen = FLINT_MIN(n, poly->length); while (rlen > 0 && arb_is_zero(poly->coeffs + rlen - 1)) rlen--; arb_poly_fit_length(res, rlen); _arb_vec_set(res->coeffs, poly->coeffs, rlen); _arb_poly_set_length(res, rlen); } } flint-3.1.3/src/arb_poly/set_trunc_round.c000066400000000000000000000017011461254215100206110ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_set_trunc_round(arb_poly_t res, const arb_poly_t poly, slong n, slong prec) { if (poly == res) { arb_poly_truncate(res, n); _arb_vec_set_round(res->coeffs, res->coeffs, res->length, prec); } else { slong rlen; rlen = FLINT_MIN(n, poly->length); while (rlen > 0 && arb_is_zero(poly->coeffs + rlen - 1)) rlen--; arb_poly_fit_length(res, rlen); _arb_vec_set_round(res->coeffs, poly->coeffs, rlen, prec); _arb_poly_set_length(res, rlen); } } flint-3.1.3/src/arb_poly/shift_left.c000066400000000000000000000024461461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_shift_left(arb_ptr res, arb_srcptr poly, slong len, slong n) { slong i; /* Copy in reverse to avoid writing over unshifted coefficients */ if (res != poly) { for (i = len; i--; ) arb_set(res + n + i, poly + i); } else { for (i = len; i--; ) arb_swap(res + n + i, res + i); } for (i = 0; i < n; i++) arb_zero(res + i); } void arb_poly_shift_left(arb_poly_t res, const arb_poly_t poly, slong n) { if (n == 0) { arb_poly_set(res, poly); return; } if (poly->length == 0) { arb_poly_zero(res); return; } arb_poly_fit_length(res, poly->length + n); _arb_poly_shift_left(res->coeffs, poly->coeffs, poly->length, n); _arb_poly_set_length(res, poly->length + n); } flint-3.1.3/src/arb_poly/shift_right.c000066400000000000000000000024121461254215100177060ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_shift_right(arb_ptr res, arb_srcptr poly, slong len, slong n) { slong i; /* Copy in forward order to avoid writing over unshifted coefficients */ if (res != poly) { for (i = 0; i < len - n; i++) arb_set(res + i, poly + n + i); } else { for (i = 0; i < len - n; i++) arb_swap(res + i, res + n + i); } } void arb_poly_shift_right(arb_poly_t res, const arb_poly_t poly, slong n) { if (n == 0) { arb_poly_set(res, poly); return; } if (poly->length <= n) { arb_poly_zero(res); return; } arb_poly_fit_length(res, poly->length - n); _arb_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n); _arb_poly_set_length(res, poly->length - n); } flint-3.1.3/src/arb_poly/sin_cos_series.c000066400000000000000000000071611461254215100204110ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif static void __arb_poly_sin_cos_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, int times_pi, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { if (times_pi) arb_sin_cos_pi(s, c, h, prec); else arb_sin_cos(s, c, h, prec); _arb_vec_zero(s + 1, n - 1); _arb_vec_zero(c + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); if (times_pi) { arb_const_pi(t, prec); arb_mul(t, t, h + 1, prec); arb_sin_cos_pi(s, c, h, prec); } else { arb_set(t, h + 1); arb_sin_cos(s, c, h, prec); } arb_mul(s + 1, c, t, prec); arb_neg(t, t); arb_mul(c + 1, s, t, prec); arb_clear(t); } else { slong cutoff; gr_ctx_t ctx; int status; if (prec <= 128) { cutoff = 1400; } else { cutoff = 100000 / pow(log(prec), 3); cutoff = FLINT_MIN(cutoff, 700); } gr_ctx_init_real_arb(ctx, prec); if (hlen < cutoff) status = _gr_poly_sin_cos_series_basecase(s, c, h, hlen, n, times_pi, ctx); else status = _gr_poly_sin_cos_series_tangent(s, c, h, hlen, n, times_pi, ctx); if (status != GR_SUCCESS) { _arb_vec_indeterminate(s, n); _arb_vec_indeterminate(c, n); } } } void _arb_poly_sin_cos_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) { __arb_poly_sin_cos_series(s, c, h, hlen, n, 0, prec); } void _arb_poly_sin_cos_pi_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) { __arb_poly_sin_cos_series(s, c, h, hlen, n, 1, prec); } void arb_poly_sin_cos_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(s); arb_poly_zero(c); return; } if (hlen == 0) { arb_poly_zero(s); arb_poly_one(c); return; } if (hlen == 1) n = 1; arb_poly_fit_length(s, n); arb_poly_fit_length(c, n); _arb_poly_sin_cos_series(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(s, n); _arb_poly_normalise(s); _arb_poly_set_length(c, n); _arb_poly_normalise(c); } void arb_poly_sin_cos_pi_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(s); arb_poly_zero(c); return; } if (hlen == 0) { arb_poly_zero(s); arb_poly_one(c); return; } if (hlen == 1) n = 1; arb_poly_fit_length(s, n); arb_poly_fit_length(c, n); _arb_poly_sin_cos_pi_series(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(s, n); _arb_poly_normalise(s); _arb_poly_set_length(c, n); _arb_poly_normalise(c); } flint-3.1.3/src/arb_poly/sin_pi_series.c000066400000000000000000000026431461254215100202350ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sin_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_sin_pi(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); arb_sin_cos_pi(g, t, h, prec); arb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ arb_const_pi(t, prec); arb_mul(g + 1, g + 1, t, prec); arb_clear(t); } else { arb_ptr t = _arb_vec_init(n); _arb_poly_sin_cos_pi_series(g, t, h, hlen, n, prec); _arb_vec_clear(t, n); } } void arb_poly_sin_pi_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { arb_poly_zero(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_sin_pi_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/sin_series.c000066400000000000000000000025121461254215100175400ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sin_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_sin(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); arb_sin_cos(g, t, h, prec); arb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ arb_clear(t); } else { arb_ptr t = _arb_vec_init(n); _arb_poly_sin_cos_series(g, t, h, hlen, n, prec); _arb_vec_clear(t, n); } } void arb_poly_sin_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { arb_poly_zero(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_sin_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/sinc_pi_series.c000066400000000000000000000034321461254215100203750ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sinc_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_sinc_pi(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else { arb_t pi; arb_ptr t, u; arb_init(pi); t = _arb_vec_init(n + 1); u = _arb_vec_init(hlen); arb_const_pi(pi, prec); _arb_vec_set(u, h, hlen); if (arb_is_zero(h)) { _arb_poly_sin_pi_series(t, u, hlen, n + 1, prec); _arb_poly_div_series(g, t + 1, n, u + 1, hlen - 1, n, prec); } else { _arb_poly_sin_pi_series(t, u, hlen, n, prec); _arb_poly_div_series(g, t, n, u, hlen, n, prec); } _arb_vec_scalar_div(g, g, n, pi, prec); arb_clear(pi); _arb_vec_clear(t, n + 1); _arb_vec_clear(u, hlen); } } void arb_poly_sinc_pi_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_one(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_sinc_pi_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/sinc_series.c000066400000000000000000000031221461254215100177010ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sinc_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_sinc(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else { arb_ptr t, u; t = _arb_vec_init(n + 1); u = _arb_vec_init(hlen); _arb_vec_set(u, h, hlen); if (arb_is_zero(h)) { _arb_poly_sin_series(t, u, hlen, n + 1, prec); _arb_poly_div_series(g, t + 1, n, u + 1, hlen - 1, n, prec); } else { _arb_poly_sin_series(t, u, hlen, n, prec); _arb_poly_div_series(g, t, n, u, hlen, n, prec); } _arb_vec_clear(t, n + 1); _arb_vec_clear(u, hlen); } } void arb_poly_sinc_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(g); return; } if (hlen == 0) { arb_poly_one(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_sinc_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/sinh_cosh_series.c000066400000000000000000000037541461254215100207350ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif void _arb_poly_sinh_cosh_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_sinh_cosh(s, c, h, prec); _arb_vec_zero(s + 1, n - 1); _arb_vec_zero(c + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); arb_set(t, h + 1); arb_sinh_cosh(s, c, h, prec); arb_mul(s + 1, c, t, prec); arb_mul(c + 1, s, t, prec); arb_clear(t); } else { slong cutoff; if (prec <= 128) cutoff = 400; else cutoff = 30000 / pow(log(prec), 3); if (hlen < cutoff) _arb_poly_sinh_cosh_series_basecase(s, c, h, hlen, n, prec); else _arb_poly_sinh_cosh_series_exponential(s, c, h, hlen, n, prec); } } void arb_poly_sinh_cosh_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(s); arb_poly_zero(c); return; } if (hlen == 0) { arb_poly_zero(s); arb_poly_one(c); return; } if (hlen == 1) n = 1; arb_poly_fit_length(s, n); arb_poly_fit_length(c, n); _arb_poly_sinh_cosh_series(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(s, n); _arb_poly_normalise(s); _arb_poly_set_length(c, n); _arb_poly_normalise(c); } flint-3.1.3/src/arb_poly/sinh_cosh_series_basecase.c000066400000000000000000000035121461254215100225530ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sinh_cosh_series_basecase(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec) { slong k, alen = FLINT_MIN(n, hlen); arb_ptr a; arb_t t, u; arb_sinh_cosh(s, c, h, prec); if (hlen == 1) { _arb_vec_zero(s + 1, n - 1); _arb_vec_zero(c + 1, n - 1); return; } arb_init(t); arb_init(u); a = _arb_vec_init(alen); for (k = 1; k < alen; k++) arb_mul_ui(a + k, h + k, k, prec); for (k = 1; k < n; k++) { arb_dot(t, NULL, 0, a + 1, 1, s + k - 1, -1, FLINT_MIN(k, hlen - 1), prec); arb_dot(u, NULL, 0, a + 1, 1, c + k - 1, -1, FLINT_MIN(k, hlen - 1), prec); arb_div_ui(c + k, t, k, prec); arb_div_ui(s + k, u, k, prec); } arb_clear(t); arb_clear(u); _arb_vec_clear(a, alen); } void arb_poly_sinh_cosh_series_basecase(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(s); arb_poly_zero(c); return; } if (hlen == 0) { arb_poly_zero(s); arb_poly_one(c); return; } arb_poly_fit_length(s, n); arb_poly_fit_length(c, n); _arb_poly_sinh_cosh_series_basecase(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(s, n); _arb_poly_normalise(s); _arb_poly_set_length(c, n); _arb_poly_normalise(c); } flint-3.1.3/src/arb_poly/sinh_cosh_series_exponential.c000066400000000000000000000047771461254215100233510ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sinh_cosh_series_exponential(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong len, slong prec) { arb_ptr t, u, v; arb_t s0, c0; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_sinh_cosh(s, c, h, prec); _arb_vec_zero(s + 1, len - 1); _arb_vec_zero(c + 1, len - 1); return; } arb_init(s0); arb_init(c0); t = _arb_vec_init(3 * len); u = t + len; v = u + len; arb_sinh_cosh(s0, c0, h, prec); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_exp_series(t, t, len, len, prec); /* todo: part of the inverse could be avoided since exp computes it internally to half the length */ _arb_poly_inv_series(u, t, len, len, prec); /* hyperbolic sine */ _arb_vec_sub(s, t, u, len, prec); _arb_vec_scalar_mul_2exp_si(s, s, len, -1); /* hyperbolic cosine */ _arb_vec_add(c, t, u, len, prec); _arb_vec_scalar_mul_2exp_si(c, c, len, -1); /* sinh(h0 + h1) = cosh(h0) sinh(h1) + sinh(h0) cosh(h1) cosh(h0 + h1) = cosh(h0) cosh(h1) + sinh(h0) sinh(h1) */ if (!arb_is_zero(s0)) { _arb_vec_scalar_mul(t, s, len, c0, prec); _arb_vec_scalar_mul(u, c, len, s0, prec); _arb_vec_scalar_mul(v, s, len, s0, prec); _arb_vec_add(s, t, u, len, prec); _arb_vec_scalar_mul(t, c, len, c0, prec); _arb_vec_add(c, t, v, len, prec); } _arb_vec_clear(t, 3 * len); arb_clear(s0); arb_clear(c0); } void arb_poly_sinh_cosh_series_exponential(arb_poly_t s, arb_poly_t c, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (n == 0) { arb_poly_zero(s); arb_poly_zero(c); return; } if (hlen == 0) { arb_poly_zero(s); arb_poly_one(c); return; } arb_poly_fit_length(s, n); arb_poly_fit_length(c, n); _arb_poly_sinh_cosh_series_exponential(s->coeffs, c->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(s, n); _arb_poly_normalise(s); _arb_poly_set_length(c, n); _arb_poly_normalise(c); } flint-3.1.3/src/arb_poly/sinh_series.c000066400000000000000000000025221461254215100177110ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sinh_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_sinh(g, h, prec); _arb_vec_zero(g + 1, n - 1); } else if (n == 2) { arb_t t; arb_init(t); arb_sinh_cosh(g, t, h, prec); arb_mul(g + 1, h + 1, t, prec); /* safe since hlen >= 2 */ arb_clear(t); } else { arb_ptr t = _arb_vec_init(n); _arb_poly_sinh_cosh_series(g, t, h, hlen, n, prec); _arb_vec_clear(t, n); } } void arb_poly_sinh_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { slong hlen = h->length; if (hlen == 0 || n == 0) { arb_poly_zero(g); return; } if (hlen == 1) n = 1; arb_poly_fit_length(g, n); _arb_poly_sinh_series(g->coeffs, h->coeffs, hlen, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/sqrt_series.c000066400000000000000000000036231461254215100177440ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sqrt_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); while (hlen > 0 && arb_is_zero(h + hlen - 1)) hlen--; if (hlen <= 1) { arb_sqrt(g, h, prec); _arb_vec_zero(g + 1, len - 1); } else if (len == 2) { arb_sqrt(g, h, prec); arb_div(g + 1, h + 1, h, prec); arb_mul(g + 1, g + 1, g, prec); arb_mul_2exp_si(g + 1, g + 1, -1); } else if (_arb_vec_is_zero(h + 1, hlen - 2)) { arb_t t; arb_init(t); arf_set_si_2exp_si(arb_midref(t), 1, -1); _arb_poly_binomial_pow_arb_series(g, h, hlen, t, len, prec); arb_clear(t); } else { arb_ptr t; t = _arb_vec_init(len); _arb_poly_rsqrt_series(t, h, hlen, len, prec); _arb_poly_mullow(g, t, len, h, hlen, len, prec); _arb_vec_clear(t, len); } } void arb_poly_sqrt_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { if (n == 0) { arb_poly_zero(g); return; } if (g == h) { arb_poly_t t; arb_poly_init(t); arb_poly_sqrt_series(t, h, n, prec); arb_poly_swap(g, t); arb_poly_clear(t); return; } arb_poly_fit_length(g, n); if (h->length == 0) _arb_vec_indeterminate(g->coeffs, n); else _arb_poly_sqrt_series(g->coeffs, h->coeffs, h->length, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/sub.c000066400000000000000000000022621461254215100161700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void _arb_poly_sub(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong prec) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) arb_sub(res + i, poly1 + i, poly2 + i, prec); for (i = min; i < len1; i++) arb_set_round(res + i, poly1 + i, prec); for (i = min; i < len2; i++) arb_neg_round(res + i, poly2 + i, prec); } void arb_poly_sub(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong prec) { slong max = FLINT_MAX(poly1->length, poly2->length); arb_poly_fit_length(res, max); _arb_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, prec); _arb_poly_set_length(res, max); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/sub_series.c000066400000000000000000000015751461254215100175500ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" void arb_poly_sub_series(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong len, slong prec) { slong len1, len2; len1 = poly1->length; len2 = poly2->length; len1 = FLINT_MIN(len1, len); len2 = FLINT_MIN(len2, len); len = FLINT_MAX(len1, len2); arb_poly_fit_length(res, len); _arb_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec); _arb_poly_set_length(res, len); _arb_poly_normalise(res); } flint-3.1.3/src/arb_poly/swinnerton_dyer_ui.c000066400000000000000000000065051461254215100213310ustar00rootroot00000000000000/* Copyright (C) 2015, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arb_poly.h" #ifdef __GNUC__ # define log __builtin_log # define sqrt __builtin_sqrt #else # include #endif /* Bound based on binomial theorem */ slong _arb_poly_swinnerton_dyer_ui_prec(ulong n) { slong i; double u, N; N = UWORD(1) << n; /* u = (sum of square roots)^(2^n) */ u = 0; for (i = 0; i < n; i++) u += sqrt(n_nth_prime(1 + i)); u = N * log(u) * 1.44269504088897; /* Central binomial coefficient C(N,N/2) < 2^N / sqrt(3*N/2) */ u += N - 0.5*(n-1) - 0.792481250360578; /* log(sqrt(3)) */ /* experimental heuristic: the bound is 2x too large */ return u * 0.5 + 15; } void _arb_poly_swinnerton_dyer_ui(arb_ptr T, ulong n, slong trunc, slong prec) { arb_ptr square_roots, tmp1, tmp2, tmp3; arb_t one; slong i, j, k, N; if (n == 0) { arb_zero(T); arb_one(T + 1); return; } if (prec == 0) prec = _arb_poly_swinnerton_dyer_ui_prec(n); N = WORD(1) << n; trunc = FLINT_MIN(trunc, N + 1); arb_init(one); arb_one(one); square_roots = _arb_vec_init(n); tmp1 = flint_malloc((N / 4 + 1) * sizeof(arb_struct)); tmp2 = flint_malloc((N / 4 + 1) * sizeof(arb_struct)); tmp3 = _arb_vec_init(N / 2); for (i = 0; i < n; i++) arb_sqrt_ui(square_roots + i, n_nth_prime(i + 1), prec); /* Build deflated quadratic factors */ for (i = 0; i < N / 2; i++) { arb_zero(T + i); for (j = 0; j < n; j++) { if ((i >> j) & 1) arb_add(T + i, T + i, square_roots + j, prec); else arb_sub(T + i, T + i, square_roots + j, prec); } arb_sqr(T + i, T + i, prec); arb_neg(T + i, T + i); } /* For each level... */ for (i = 0; i < n - 1; i++) { slong stride = UWORD(1) << i; for (j = 0; j < N / 2; j += 2 * stride) { for (k = 0; k < stride; k++) { tmp1[k] = T[j + k]; tmp2[k] = T[j + stride + k]; } tmp1[stride] = *one; tmp2[stride] = *one; _arb_poly_mullow(tmp3, tmp1, stride + 1, tmp2, stride + 1, FLINT_MIN(2 * stride, trunc), prec); _arb_vec_swap(T + j, tmp3, FLINT_MIN(2 * stride, trunc)); } } /* Inflate */ for (i = N - 2; i >= 0; i -= 2) { if (i < trunc) arb_swap(T + i, T + i / 2); if (i + 1 < trunc) arb_zero(T + i + 1); } arb_one(T + N); _arb_vec_clear(square_roots, n); flint_free(tmp1); flint_free(tmp2); _arb_vec_clear(tmp3, N / 2); arb_clear(one); } void arb_poly_swinnerton_dyer_ui(arb_poly_t poly, ulong n, slong prec) { slong N = WORD(1) << n; arb_poly_fit_length(poly, N + 1); _arb_poly_swinnerton_dyer_ui(poly->coeffs, n, N + 1, prec); _arb_poly_set_length(poly, N + 1); _arb_poly_normalise(poly); } flint-3.1.3/src/arb_poly/tan_series.c000066400000000000000000000021231461254215100175270ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" #define TAN_NEWTON_CUTOFF 20 void _arb_poly_tan_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); hlen = FLINT_MIN(hlen, len); if (_gr_poly_tan_series_newton(res, h, hlen, len, TAN_NEWTON_CUTOFF, ctx) != GR_SUCCESS) _arb_vec_indeterminate(res, len); } void arb_poly_tan_series(arb_poly_t g, const arb_poly_t h, slong n, slong prec) { if (h->length == 0 || n == 0) { arb_poly_zero(g); return; } arb_poly_fit_length(g, n); _arb_poly_tan_series(g->coeffs, h->coeffs, h->length, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); } flint-3.1.3/src/arb_poly/taylor_shift.c000066400000000000000000000031341461254215100201050ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_poly.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif int _gr_arb_poly_taylor_shift(arb_ptr res, arb_srcptr poly, slong n, const arb_t c, gr_ctx_t ctx) { slong prec; if (n <= 30) return _gr_poly_taylor_shift_horner(res, poly, n, c, ctx); prec = _gr_ctx_get_real_prec(ctx); if (n <= 30 || (n <= 500 && arb_bits(c) == 1 && n < 30 + 3 * sqrt(prec)) || (n <= 100 && arb_bits(c) < 0.01 * prec)) { return _gr_poly_taylor_shift_horner(res, poly, n, c, ctx); } else if (prec > 2 * n) { return _gr_poly_taylor_shift_convolution(res, poly, n, c, ctx); } else { return _gr_poly_taylor_shift_divconquer(res, poly, n, c, ctx); } } void _arb_poly_taylor_shift(arb_ptr poly, const arb_t c, slong n, slong prec) { gr_ctx_t ctx; gr_ctx_init_real_arb(ctx, prec); if (_gr_poly_taylor_shift(poly, poly, n, c, ctx) != GR_SUCCESS) _arb_vec_indeterminate(poly, n); } void arb_poly_taylor_shift(arb_poly_t g, const arb_poly_t f, const arb_t c, slong prec) { if (f != g) arb_poly_set_round(g, f, prec); _arb_poly_taylor_shift(g->coeffs, c, g->length, prec); } flint-3.1.3/src/arb_poly/test/000077500000000000000000000000001461254215100162105ustar00rootroot00000000000000flint-3.1.3/src/arb_poly/test/main.c000066400000000000000000000142351461254215100173050ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-acos_series.c" #include "t-add.c" #include "t-add_series.c" #include "t-add_si.c" #include "t-asin_series.c" #include "t-atan_series.c" #include "t-binomial_transform_basecase.c" #include "t-binomial_transform.c" #include "t-binomial_transform_convolution.c" #include "t-borel_transform.c" #include "t-compose.c" #include "t-compose_series.c" #include "t-cos_pi_series.c" #include "t-cot_pi_series.c" #include "t-digamma_series.c" #include "t-divrem.c" #include "t-div_series.c" #include "t-evaluate2_acb_rectangular.c" #include "t-evaluate2.c" #include "t-evaluate2_horner.c" #include "t-evaluate2_rectangular.c" #include "t-evaluate_acb_rectangular.c" #include "t-evaluate.c" #include "t-evaluate_horner.c" #include "t-evaluate_rectangular.c" #include "t-evaluate_vec_fast.c" #include "t-evaluate_vec_iter.c" #include "t-exp_series_basecase.c" #include "t-exp_series.c" #include "t-gamma_series.c" #include "t-get_coeff_ptr.c" #include "t-get_set_coeff_arb.c" #include "t-get_unique_fmpz_poly.c" #include "t-graeffe_transform.c" #include "t-interpolate_barycentric.c" #include "t-interpolate_fast.c" #include "t-interpolate_newton.c" #include "t-inv_series.c" #include "t-lambertw_series.c" #include "t-lgamma_series.c" #include "t-log1p_series.c" #include "t-log_series.c" #include "t-mul.c" #include "t-mullow_block.c" #include "t-mullow.c" #include "t-mullow_classical.c" #include "t-pow_arb_series.c" #include "t-pow_series.c" #include "t-pow_ui.c" #include "t-pow_ui_trunc_binexp.c" #include "t-product_roots.c" #include "t-product_roots_complex.c" #include "t-revert_series.c" #include "t-rgamma_series.c" #include "t-riemann_siegel_theta_series.c" #include "t-riemann_siegel_z_series.c" #include "t-rising_ui_series.c" #include "t-root_bound_fujiwara.c" #include "t-rsqrt_series.c" #include "t-set_trunc_round.c" #include "t-shift_left_right.c" #include "t-sin_cos_pi_series.c" #include "t-sin_cos_series.c" #include "t-sinc_pi_series.c" #include "t-sinc_series.c" #include "t-sinh_cosh_series.c" #include "t-sin_pi_series.c" #include "t-sin_series_cos_series.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-swinnerton_dyer_ui.c" #include "t-tan_series.c" #include "t-taylor_shift.c" #include "t-zeta_series.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arb_poly_acos_series), TEST_FUNCTION(arb_poly_add), TEST_FUNCTION(arb_poly_add_series), TEST_FUNCTION(arb_poly_add_si), TEST_FUNCTION(arb_poly_asin_series), TEST_FUNCTION(arb_poly_atan_series), TEST_FUNCTION(arb_poly_binomial_transform_basecase), TEST_FUNCTION(arb_poly_binomial_transform), TEST_FUNCTION(arb_poly_binomial_transform_convolution), TEST_FUNCTION(arb_poly_borel_transform), TEST_FUNCTION(arb_poly_compose), TEST_FUNCTION(arb_poly_compose_series), TEST_FUNCTION(arb_poly_cos_pi_series), TEST_FUNCTION(arb_poly_cot_pi_series), TEST_FUNCTION(arb_poly_digamma_series), TEST_FUNCTION(arb_poly_divrem), TEST_FUNCTION(arb_poly_div_series), TEST_FUNCTION(arb_poly_evaluate2_acb_rectangular), TEST_FUNCTION(arb_poly_evaluate2), TEST_FUNCTION(arb_poly_evaluate2_horner), TEST_FUNCTION(arb_poly_evaluate2_rectangular), TEST_FUNCTION(arb_poly_evaluate_acb_rectangular), TEST_FUNCTION(arb_poly_evaluate), TEST_FUNCTION(arb_poly_evaluate_horner), TEST_FUNCTION(arb_poly_evaluate_rectangular), TEST_FUNCTION(arb_poly_evaluate_vec_fast), TEST_FUNCTION(arb_poly_evaluate_vec_iter), TEST_FUNCTION(arb_poly_exp_series_basecase), TEST_FUNCTION(arb_poly_exp_series), TEST_FUNCTION(arb_poly_gamma_series), TEST_FUNCTION(arb_poly_get_coeff_ptr), TEST_FUNCTION(arb_poly_get_set_coeff_arb), TEST_FUNCTION(arb_poly_get_unique_fmpz_poly), TEST_FUNCTION(arb_poly_graeffe_transform), TEST_FUNCTION(arb_poly_interpolate_barycentric), TEST_FUNCTION(arb_poly_interpolate_fast), TEST_FUNCTION(arb_poly_interpolate_newton), TEST_FUNCTION(arb_poly_inv_series), TEST_FUNCTION(arb_poly_lambertw_series), TEST_FUNCTION(arb_poly_lgamma_series), TEST_FUNCTION(arb_poly_log1p_series), TEST_FUNCTION(arb_poly_log_series), TEST_FUNCTION(arb_poly_mul), TEST_FUNCTION(arb_poly_mullow_block), TEST_FUNCTION(arb_poly_mullow), TEST_FUNCTION(arb_poly_mullow_classical), TEST_FUNCTION(arb_poly_pow_arb_series), TEST_FUNCTION(arb_poly_pow_series), TEST_FUNCTION(arb_poly_pow_ui), TEST_FUNCTION(arb_poly_pow_ui_trunc_binexp), TEST_FUNCTION(arb_poly_product_roots), TEST_FUNCTION(arb_poly_product_roots_complex), TEST_FUNCTION(arb_poly_revert_series), TEST_FUNCTION(arb_poly_rgamma_series), TEST_FUNCTION(arb_poly_riemann_siegel_theta_series), TEST_FUNCTION(arb_poly_riemann_siegel_z_series), TEST_FUNCTION(arb_poly_rising_ui_series), TEST_FUNCTION(arb_poly_root_bound_fujiwara), TEST_FUNCTION(arb_poly_rsqrt_series), TEST_FUNCTION(arb_poly_set_trunc_round), TEST_FUNCTION(arb_poly_shift_left_right), TEST_FUNCTION(arb_poly_sin_cos_pi_series), TEST_FUNCTION(arb_poly_sin_cos_series), TEST_FUNCTION(arb_poly_sinc_pi_series), TEST_FUNCTION(arb_poly_sinc_series), TEST_FUNCTION(arb_poly_sinh_cosh_series), TEST_FUNCTION(arb_poly_sin_pi_series), TEST_FUNCTION(arb_poly_sin_series_cos_series), TEST_FUNCTION(arb_poly_sqrt_series), TEST_FUNCTION(arb_poly_sub), TEST_FUNCTION(arb_poly_sub_series), TEST_FUNCTION(arb_poly_swinnerton_dyer_ui), TEST_FUNCTION(arb_poly_tan_series), TEST_FUNCTION(arb_poly_taylor_shift), TEST_FUNCTION(arb_poly_zeta_series) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arb_poly/test/t-acos_series.c000066400000000000000000000044271461254215100211230ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_acos_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_randtest(b, state, 1 + n_randint(state, 30), rbits1, 5); arb_poly_acos_series(b, a, n, rbits2); /* Check cos(acos(x)) = x */ arb_poly_sin_cos_series(d, c, b, n, rbits2); fmpq_poly_truncate(A, n); if (!arb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_acos_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-add.c000066400000000000000000000043231461254215100173470ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_add, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t A, B, C; arb_poly_t a, b, c; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_add(C, A, B); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_add(c, a, b, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-add_series.c000066400000000000000000000042761461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_add_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d; slong len, prec; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10); arb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10); arb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10); arb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10); prec = 2 + n_randint(state, 100); len = n_randint(state, 10); arb_poly_add_series(c, a, b, len, prec); arb_poly_add(d, a, b, prec); arb_poly_truncate(d, len); if (!arb_poly_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_add_series(d, d, b, len, prec); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_add_series(d, a, d, len, prec); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-add_si.c000066400000000000000000000033351461254215100200440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_add_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d; slong v; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_randtest(a, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); arb_poly_randtest(b, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); arb_poly_randtest(c, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); arb_poly_randtest(d, state, 1 + n_randint(state, 10), 1 + n_randint(state, 200), 10); v = n_randtest(state); arb_poly_set_si(b, v); arb_poly_add(c, a, b, 2 + n_randint(state, 200)); arb_poly_add_si(d, a, v, 2 + n_randint(state, 200)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_abort(); } arb_poly_add_si(a, a, v, 2 + n_randint(state, 200)); if (!arb_poly_overlaps(a, d)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-asin_series.c000066400000000000000000000044271461254215100211300ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_asin_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_randtest(b, state, 1 + n_randint(state, 30), rbits1, 5); arb_poly_asin_series(b, a, n, rbits2); /* Check sin(asin(x)) = x */ arb_poly_sin_cos_series(c, d, b, n, rbits2); fmpq_poly_truncate(A, n); if (!arb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_asin_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-atan_series.c000066400000000000000000000053431461254215100211170ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_atan_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_randtest(b, state, 1 + n_randint(state, 30), rbits1, 5); arb_poly_atan_series(b, a, n, rbits2); /* Check 2 atan(x) = atan(2x/(1-x^2)) + C */ arb_poly_mullow(c, a, a, n, rbits2); arb_poly_one(d); arb_poly_sub(c, d, c, rbits2); arb_poly_add(d, a, a, rbits2); if (arb_poly_length(c) != 0) { arb_poly_div_series(c, d, c, n, rbits2); arb_poly_atan_series(c, c, n, rbits2); arb_poly_add(d, b, b, rbits2); /* TODO: also check the first coefficient */ arb_poly_set_coeff_si(c, 0, 0); arb_poly_set_coeff_si(d, 0, 0); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } } arb_poly_atan_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-binomial_transform.c000066400000000000000000000056761461254215100225200ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_binomial_transform, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d; slong j, n, prec; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); n = n_randint(state, 20); prec = 2 + n_randint(state, 200); arb_poly_randtest(a, state, n, prec, 10); arb_poly_randtest(b, state, n, prec, 10); arb_poly_randtest(c, state, n, prec, 10); /* check self-inversion property */ arb_poly_binomial_transform(b, a, n, prec); arb_poly_binomial_transform(c, b, n, prec); arb_poly_set(d, a); arb_poly_truncate(d, n); if (!arb_poly_contains(c, d)) { flint_printf("FAIL (containment)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d: "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_binomial_transform(d, d, n, prec); if (!arb_poly_equal(d, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d: "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* compare with power series operations */ arb_poly_zero(d); for (j = 1; j < n; j++) arb_poly_set_coeff_si(d, j, -1); arb_poly_compose_series(c, a, d, n, prec); for (j = 0; j < n; j++) arb_poly_set_coeff_si(d, j, 1); arb_poly_mullow(c, c, d, n, prec); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL (power series)\n\n"); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-binomial_transform_basecase.c000066400000000000000000000057421461254215100243400ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_binomial_transform_basecase, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d; slong j, n, prec; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); n = n_randint(state, 20); prec = 2 + n_randint(state, 200); arb_poly_randtest(a, state, n, prec, 10); arb_poly_randtest(b, state, n, prec, 10); arb_poly_randtest(c, state, n, prec, 10); /* check self-inversion property */ arb_poly_binomial_transform_basecase(b, a, n, prec); arb_poly_binomial_transform_basecase(c, b, n, prec); arb_poly_set(d, a); arb_poly_truncate(d, n); if (!arb_poly_contains(c, d)) { flint_printf("FAIL (containment)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d: "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_binomial_transform_basecase(d, d, n, prec); if (!arb_poly_equal(d, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d: "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* compare with power series operations */ arb_poly_zero(d); for (j = 1; j < n; j++) arb_poly_set_coeff_si(d, j, -1); arb_poly_compose_series(c, a, d, n, prec); for (j = 0; j < n; j++) arb_poly_set_coeff_si(d, j, 1); arb_poly_mullow(c, c, d, n, prec); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL (power series)\n\n"); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-binomial_transform_convolution.c000066400000000000000000000057561461254215100251560ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_binomial_transform_convolution, state) { slong iter; for (iter = 0; iter < 5000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d; slong j, n, prec; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); n = n_randint(state, 20); prec = 2 + n_randint(state, 200); arb_poly_randtest(a, state, n, prec, 10); arb_poly_randtest(b, state, n, prec, 10); arb_poly_randtest(c, state, n, prec, 10); /* check self-inversion property */ arb_poly_binomial_transform_convolution(b, a, n, prec); arb_poly_binomial_transform_convolution(c, b, n, prec); arb_poly_set(d, a); arb_poly_truncate(d, n); if (!arb_poly_contains(c, d)) { flint_printf("FAIL (containment)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d: "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_binomial_transform_convolution(d, d, n, prec); if (!arb_poly_equal(d, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d: "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* compare with power series operations */ arb_poly_zero(d); for (j = 1; j < n; j++) arb_poly_set_coeff_si(d, j, -1); arb_poly_compose_series(c, a, d, n, prec); for (j = 0; j < n; j++) arb_poly_set_coeff_si(d, j, 1); arb_poly_mullow(c, c, d, n, prec); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL (power series)\n\n"); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-borel_transform.c000066400000000000000000000033511461254215100220150ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_borel_transform, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d; slong n, prec; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); n = n_randint(state, 30); prec = n_randint(state, 200); arb_poly_randtest(a, state, n, prec, 10); arb_poly_randtest(b, state, n, prec, 10); arb_poly_randtest(c, state, n, prec, 10); arb_poly_borel_transform(b, a, prec); arb_poly_inv_borel_transform(c, b, prec); if (!arb_poly_contains(c, a)) { flint_printf("FAIL (containment)\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_borel_transform(d, d, prec); if (!arb_poly_equal(d, b)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_inv_borel_transform(d, d, prec); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-compose.c000066400000000000000000000053721461254215100202710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_compose, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t A, B, C; arb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 20), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_compose(C, A, B); arb_poly_randtest(c, state, 1 + n_randint(state, 20), rbits1, 4); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_compose(c, a, b, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_compose(d, d, b, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_compose(d, a, d, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-compose_series.c000066400000000000000000000111571461254215100216410ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_compose_series, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, n; fmpq_poly_t A, B, C; arb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); n = 2 + n_randint(state, 25); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 25), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 25), qbits2); fmpq_poly_set_coeff_ui(B, 0, 0); fmpq_poly_compose_series(C, A, B, n); arb_poly_randtest(c, state, 1 + n_randint(state, 20), rbits1, 4); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_compose_series(c, a, b, n, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, bits3 = %wd\n", n, rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_compose_series(d, d, b, n, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_compose_series(d, a, d, n, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } if (a->length > 0 && b->length > 0) { int any_finite; slong i, k, l, m; /* randomize coefficients to set to indeterminate value */ /* if the value is equal to the length we don't set an indeterminate value */ k = n_randint(state, a->length + 1); l = 1 + n_randint(state, b->length); if (k < a->length) arb_indeterminate(a->coeffs + k); else k = n; // k doesn't affect number of finite coefficients if (l < b->length) arb_indeterminate(b->coeffs + l); else l = n; // l doesn't affect number of finite coefficients arb_poly_compose_series(d, a, b, n, rbits3); /* up to this all coefficients should be finite */ m = FLINT_MIN(FLINT_MIN(k, l), d->length); /* check that coefficients after m are all non-finite */ any_finite = 0; for (i = m; i < d->length; i++) any_finite |= arb_is_finite(d->coeffs + i); if (any_finite) { flint_printf("FAIL (non-finite 1)\n\n"); flint_abort(); } /* check that coefficients up to m are all finite and contain the expected result */ if (!_arb_vec_is_finite(d->coeffs, m)) { flint_printf("FAIL (non-finite 2)\n\n"); flint_abort(); } fmpq_poly_truncate(C, m); arb_poly_truncate(d, m); if (!arb_poly_contains_fmpq_poly(d, C)) { flint_printf("FAIL (non-finite 3)\n\n"); flint_abort(); } } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-cos_pi_series.c000066400000000000000000000043101461254215100214410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_cos_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; arb_poly_t S, A, B, C; arb_t pi; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); arb_poly_init(S); arb_poly_init(A); arb_poly_init(B); arb_poly_init(C); arb_init(pi); arb_poly_randtest(S, state, m, bits1, 3); arb_poly_randtest(A, state, m, bits1, 3); arb_poly_randtest(B, state, m, bits1, 3); arb_poly_cos_pi_series(A, S, n1, bits2); arb_const_pi(pi, bits3); arb_poly_set_arb(B, pi); arb_poly_mul(B, S, B, bits3); arb_poly_cos_series(B, B, n2, bits3); arb_poly_set(C, A); arb_poly_truncate(C, FLINT_MIN(n1, n2)); arb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); arb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); arb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_cos_pi_series(S, S, n1, bits2); if (!arb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(S); arb_poly_clear(A); arb_poly_clear(B); arb_poly_clear(C); arb_clear(pi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-cot_pi_series.c000066400000000000000000000036651461254215100214560ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_cot_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, bits1, bits2, bits3; arb_poly_t S, A, B, C; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); arb_poly_init(S); arb_poly_init(A); arb_poly_init(B); arb_poly_init(C); arb_poly_randtest(S, state, m, bits1, 10); arb_poly_randtest(A, state, m, bits1, 10); arb_poly_randtest(B, state, m, bits1, 10); arb_poly_cot_pi_series(A, S, n1, bits2); arb_poly_sin_cos_pi_series(B, C, S, n1, bits3); arb_poly_div_series(B, C, B, n1, bits3); if (!arb_poly_overlaps(A, B)) { flint_printf("FAIL\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); arb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); arb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_cot_pi_series(S, S, n1, bits2); if (!arb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(S); arb_poly_clear(A); arb_poly_clear(B); arb_poly_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-digamma_series.c000066400000000000000000000053421461254215100215720ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_digamma_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; arb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 300); rbits2 = 2 + n_randint(state, 300); rbits3 = 2 + n_randint(state, 300); m = n_randint(state, 25); n1 = n_randint(state, 25); n2 = n_randint(state, 25); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_randtest(a, state, m, rbits1, 10); arb_poly_digamma_series(b, a, n1, rbits2); arb_poly_digamma_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); arb_poly_printd(a, 50); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 50); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 50); flint_printf("\n\n"); flint_abort(); } /* check psi(a) + 1/a = psi(a+1) */ arb_poly_inv_series(c, a, n1, rbits2); arb_poly_add(c, b, c, rbits2); arb_poly_add_si(d, a, 1, rbits2); arb_poly_digamma_series(d, d, n1, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_digamma_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-div_series.c000066400000000000000000000057611461254215100207620ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_div_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, p, qbits, rbits1, rbits2; fmpq_poly_t A, B, C; arb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); p = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, m, qbits); do { fmpq_poly_randtest_not_zero(B, state, n, qbits); } while (B->coeffs[0] == 0); fmpq_poly_div_series(C, A, B, p); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits1); arb_poly_div_series(c, a, b, p, rbits2); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_div_series(d, d, b, p, rbits2); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_div_series(d, a, d, p, rbits2); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_div_series(c, d, d, p, rbits2); arb_poly_div_series(d, d, d, p, rbits2); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 3)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-divrem.c000066400000000000000000000065471461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_divrem, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t A, B, Q, R; arb_poly_t a, b, q, r; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(Q); fmpq_poly_init(R); arb_poly_init(a); arb_poly_init(b); arb_poly_init(q); arb_poly_init(r); fmpq_poly_randtest(A, state, m, qbits1); fmpq_poly_randtest_not_zero(B, state, n, qbits2); fmpq_poly_divrem(Q, R, A, B); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_divrem(q, r, a, b, rbits3); if (!arb_poly_contains_fmpq_poly(q, Q) || !arb_poly_contains_fmpq_poly(r, R)) { flint_printf("FAIL\n\n"); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("Q = "); fmpq_poly_print(Q); flint_printf("\n\n"); flint_printf("R = "); fmpq_poly_print(R); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("q = "); arb_poly_printd(q, 15); flint_printf("\n\n"); flint_printf("r = "); arb_poly_printd(r, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_divrem(a, r, a, b, rbits3); if (!arb_poly_equal(a, q)) { flint_printf("FAIL (aliasing q, a)\n\n"); } arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_divrem(b, r, a, b, rbits3); if (!arb_poly_equal(b, q)) { flint_printf("FAIL (aliasing q, b)\n\n"); flint_abort(); } arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_divrem(q, a, a, b, rbits3); if (!arb_poly_equal(a, r)) { flint_printf("FAIL (aliasing r, a)\n\n"); flint_abort(); } arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_divrem(q, b, a, b, rbits3); if (!arb_poly_equal(b, r)) { flint_printf("FAIL (aliasing r, b)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(Q); fmpq_poly_clear(R); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(q); arb_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate.c000066400000000000000000000044751461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq_t X, Y; arb_poly_t f; arb_t x, y; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(F); fmpq_init(X); fmpq_init(Y); arb_poly_init(f); arb_init(x); arb_init(y); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); fmpq_randtest(X, state, qbits2); fmpq_poly_evaluate_fmpq(Y, F, X); arb_poly_set_fmpq_poly(f, F, rbits1); arb_set_fmpq(x, X, rbits2); arb_poly_evaluate(y, f, x, rbits3); if (!arb_contains_fmpq(y, Y)) { flint_printf("FAIL\n\n"); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y); flint_printf("\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 15); flint_printf("\n\n"); flint_abort(); } /* aliasing */ arb_poly_evaluate(x, f, x, rbits3); if (!arb_contains_fmpq(x, Y)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(F); fmpq_clear(X); fmpq_clear(Y); arb_poly_clear(f); arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate2.c000066400000000000000000000041321461254215100205050ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate2, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t f, g; arb_t x, y1, z1, y2, z2; arb_init(x); arb_init(y1); arb_init(z1); arb_init(y2); arb_init(z2); arb_poly_init(f); arb_poly_init(g); arb_randtest(x, state, 2 + n_randint(state, 1000), 5); arb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); arb_poly_derivative(g, f, 2 + n_randint(state, 1000)); arb_poly_evaluate2(y1, z1, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_horner(z2, g, x, 2 + n_randint(state, 1000)); if (!arb_overlaps(y1, y2) || !arb_overlaps(z1, z2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); arb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); arb_printd(y1, 15); flint_printf("\n\n"); flint_printf("z1 = "); arb_printd(z1, 15); flint_printf("\n\n"); flint_printf("y2 = "); arb_printd(y2, 15); flint_printf("\n\n"); flint_printf("z2 = "); arb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); arb_poly_clear(g); arb_clear(x); arb_clear(y1); arb_clear(z1); arb_clear(y2); arb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate2_acb_rectangular.c000066400000000000000000000042231461254215100237020ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate2_acb_rectangular, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t f, g; acb_t x, y1, z1, y2, z2; acb_init(x); acb_init(y1); acb_init(z1); acb_init(y2); acb_init(z2); arb_poly_init(f); arb_poly_init(g); acb_randtest(x, state, 2 + n_randint(state, 1000), 5); arb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); arb_poly_derivative(g, f, 2 + n_randint(state, 1000)); arb_poly_evaluate2_acb_rectangular(y1, z1, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_acb_horner(y2, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_acb_horner(z2, g, x, 2 + n_randint(state, 1000)); if (!acb_overlaps(y1, y2) || !acb_overlaps(z1, z2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); arb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 15); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 15); flint_printf("\n\n"); flint_printf("y2 = "); acb_printd(y2, 15); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); arb_poly_clear(g); acb_clear(x); acb_clear(y1); acb_clear(z1); acb_clear(y2); acb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate2_horner.c000066400000000000000000000041501461254215100220620ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate2_horner, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t f, g; arb_t x, y1, z1, y2, z2; arb_init(x); arb_init(y1); arb_init(z1); arb_init(y2); arb_init(z2); arb_poly_init(f); arb_poly_init(g); arb_randtest(x, state, 2 + n_randint(state, 1000), 5); arb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); arb_poly_derivative(g, f, 2 + n_randint(state, 1000)); arb_poly_evaluate2_horner(y1, z1, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_horner(z2, g, x, 2 + n_randint(state, 1000)); if (!arb_overlaps(y1, y2) || !arb_overlaps(z1, z2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); arb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); arb_printd(y1, 15); flint_printf("\n\n"); flint_printf("z1 = "); arb_printd(z1, 15); flint_printf("\n\n"); flint_printf("y2 = "); arb_printd(y2, 15); flint_printf("\n\n"); flint_printf("z2 = "); arb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); arb_poly_clear(g); arb_clear(x); arb_clear(y1); arb_clear(z1); arb_clear(y2); arb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate2_rectangular.c000066400000000000000000000041621461254215100230770ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate2_rectangular, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t f, g; arb_t x, y1, z1, y2, z2; arb_init(x); arb_init(y1); arb_init(z1); arb_init(y2); arb_init(z2); arb_poly_init(f); arb_poly_init(g); arb_randtest(x, state, 2 + n_randint(state, 1000), 5); arb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); arb_poly_derivative(g, f, 2 + n_randint(state, 1000)); arb_poly_evaluate2_rectangular(y1, z1, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_horner(z2, g, x, 2 + n_randint(state, 1000)); if (!arb_overlaps(y1, y2) || !arb_overlaps(z1, z2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); arb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); arb_printd(y1, 15); flint_printf("\n\n"); flint_printf("z1 = "); arb_printd(z1, 15); flint_printf("\n\n"); flint_printf("y2 = "); arb_printd(y2, 15); flint_printf("\n\n"); flint_printf("z2 = "); arb_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); arb_poly_clear(g); arb_clear(x); arb_clear(y1); arb_clear(z1); arb_clear(y2); arb_clear(z2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate_acb_rectangular.c000066400000000000000000000031441461254215100236210ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "acb.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate_acb_rectangular, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t f; acb_t x, y1, y2; acb_init(x); acb_init(y1); acb_init(y2); arb_poly_init(f); acb_randtest(x, state, 2 + n_randint(state, 1000), 5); arb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); arb_poly_evaluate_acb_rectangular(y1, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_acb_horner(y2, f, x, 2 + n_randint(state, 1000)); if (!acb_overlaps(y1, y2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); acb_printd(y1, 15); flint_printf("\n\n"); flint_printf("y2 = "); acb_printd(y2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); acb_clear(x); acb_clear(y1); acb_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate_horner.c000066400000000000000000000045221461254215100220030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate_horner, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq_t X, Y; arb_poly_t f; arb_t x, y; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(F); fmpq_init(X); fmpq_init(Y); arb_poly_init(f); arb_init(x); arb_init(y); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); fmpq_randtest(X, state, qbits2); fmpq_poly_evaluate_fmpq(Y, F, X); arb_poly_set_fmpq_poly(f, F, rbits1); arb_set_fmpq(x, X, rbits2); arb_poly_evaluate_horner(y, f, x, rbits3); if (!arb_contains_fmpq(y, Y)) { flint_printf("FAIL\n\n"); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y); flint_printf("\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y, 15); flint_printf("\n\n"); flint_abort(); } /* aliasing */ arb_poly_evaluate_horner(x, f, x, rbits3); if (!arb_contains_fmpq(x, Y)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(F); fmpq_clear(X); fmpq_clear(Y); arb_poly_clear(f); arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate_rectangular.c000066400000000000000000000031071461254215100230130ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate_rectangular, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t f; arb_t x, y1, y2; arb_init(x); arb_init(y1); arb_init(y2); arb_poly_init(f); arb_randtest(x, state, 2 + n_randint(state, 1000), 5); arb_poly_randtest(f, state, 2 + n_randint(state, 100), 2 + n_randint(state, 1000), 5); arb_poly_evaluate_rectangular(y1, f, x, 2 + n_randint(state, 1000)); arb_poly_evaluate_horner(y2, f, x, 2 + n_randint(state, 1000)); if (!arb_overlaps(y1, y2)) { flint_printf("FAIL\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x, 15); flint_printf("\n\n"); flint_printf("y1 = "); arb_printd(y1, 15); flint_printf("\n\n"); flint_printf("y2 = "); arb_printd(y2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); arb_clear(x); arb_clear(y1); arb_clear(y2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate_vec_fast.c000066400000000000000000000050321461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate_vec_fast, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq * X, * Y; arb_poly_t f; arb_ptr x, y; qbits1 = 2 + n_randint(state, 100); qbits2 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); n = n_randint(state, 10); fmpq_poly_init(F); X = _fmpq_vec_init(n); Y = _fmpq_vec_init(n); arb_poly_init(f); x = _arb_vec_init(n); y = _arb_vec_init(n); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); for (i = 0; i < n; i++) fmpq_randtest(X + i, state, qbits2); for (i = 0; i < n; i++) fmpq_poly_evaluate_fmpq(Y + i, F, X + i); arb_poly_set_fmpq_poly(f, F, rbits1); for (i = 0; i < n; i++) arb_set_fmpq(x + i, X + i, rbits2); arb_poly_evaluate_vec_fast(y, f, x, n, rbits3); for (i = 0; i < n; i++) { if (!arb_contains_fmpq(y + i, Y + i)) { flint_printf("FAIL (%wd of %wd)\n\n", i, n); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X + i); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y + i); flint_printf("\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x + i, 15); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y + i, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_poly_clear(F); _fmpq_vec_clear(X, n); _fmpq_vec_clear(Y, n); arb_poly_clear(f); _arb_vec_clear(x, n); _arb_vec_clear(y, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-evaluate_vec_iter.c000066400000000000000000000050321461254215100223030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_evaluate_vec_iter, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t F; fmpq * X, * Y; arb_poly_t f; arb_ptr x, y; qbits1 = 2 + n_randint(state, 100); qbits2 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); n = n_randint(state, 10); fmpq_poly_init(F); X = _fmpq_vec_init(n); Y = _fmpq_vec_init(n); arb_poly_init(f); x = _arb_vec_init(n); y = _arb_vec_init(n); fmpq_poly_randtest(F, state, 1 + n_randint(state, 20), qbits1); for (i = 0; i < n; i++) fmpq_randtest(X + i, state, qbits2); for (i = 0; i < n; i++) fmpq_poly_evaluate_fmpq(Y + i, F, X + i); arb_poly_set_fmpq_poly(f, F, rbits1); for (i = 0; i < n; i++) arb_set_fmpq(x + i, X + i, rbits2); arb_poly_evaluate_vec_iter(y, f, x, n, rbits3); for (i = 0; i < n; i++) { if (!arb_contains_fmpq(y + i, Y + i)) { flint_printf("FAIL (%wd of %wd)\n\n", i, n); flint_printf("F = "); fmpq_poly_print(F); flint_printf("\n\n"); flint_printf("X = "); fmpq_print(X + i); flint_printf("\n\n"); flint_printf("Y = "); fmpq_print(Y + i); flint_printf("\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("x = "); arb_printd(x + i, 15); flint_printf("\n\n"); flint_printf("y = "); arb_printd(y + i, 15); flint_printf("\n\n"); flint_abort(); } } fmpq_poly_clear(F); _fmpq_vec_clear(X, n); _fmpq_vec_clear(Y, n); arb_poly_clear(f); _arb_vec_clear(x, n); _arb_vec_clear(y, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-exp_series.c000066400000000000000000000124661461254215100207740ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" FLINT_DLL extern slong arb_poly_newton_exp_cutoff; TEST_FUNCTION_START(arb_poly_exp_series, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; arb_poly_t a, b; qbits = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 100); rbits2 = 2 + n_randint(state, 100); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); fmpq_poly_randtest(A, state, m, qbits); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); arb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); fmpq_poly_exp_series(B, A, n); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_exp_series(b, a, n, rbits2); if (!arb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); } /* test aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b; qbits = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 100); rbits2 = 2 + n_randint(state, 100); if (n_randint(state, 100) == 0) { m = 1 + n_randint(state, 300); n = 1 + n_randint(state, 300); } else { m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); } fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); fmpq_poly_randtest(A, state, m, qbits); arb_poly_randtest(a, state, 1 + n_randint(state, 300), rbits1, 5); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_exp_series(b, a, n, rbits2); arb_poly_exp_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); } /* test that log(exp(f)) contains f */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2, rbits3; fmpq_poly_t A; arb_poly_t a, b, c; qbits = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 100); rbits2 = 2 + n_randint(state, 100); rbits3 = 2 + n_randint(state, 100); if (iter > 100) { arb_poly_newton_exp_cutoff = 5 + n_randint(state, 50); } if (n_randint(state, 100) == 0) { m = 1 + n_randint(state, 100); n = 1 + n_randint(state, 100); } else { m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); } fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_randtest(b, state, 1 + n_randint(state, 300), rbits1, 5); do { fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_exp_series(b, a, n, rbits3); } while (b->length == 0 || arb_contains_zero(b->coeffs)); arb_poly_log_series(c, b, n, rbits2); fmpq_poly_truncate(A, n); if (!arb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-exp_series_basecase.c000066400000000000000000000120271461254215100226130ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq_poly.h" #include "arb_poly.h" /* hack: avoid overflow since exp currently uses mpfr */ void fmpq_poly_randtest_small(fmpq_poly_t A, flint_rand_t state, slong len, slong bits) { fmpq_poly_randtest(A, state, len, bits); if (A->length > 0) { bits = _fmpz_vec_max_bits(A->coeffs, A->length); bits = FLINT_ABS(bits); fmpz_mul_2exp(A->den, A->den, bits); _fmpq_poly_normalise(A); } } TEST_FUNCTION_START(arb_poly_exp_series_basecase, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; arb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 40); n = 1 + n_randint(state, 40); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); fmpq_poly_randtest(A, state, m, qbits); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); fmpq_poly_exp_series(B, A, n); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_exp_series_basecase(b, a, n, rbits2); if (!arb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); } /* test aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 40); n = 1 + n_randint(state, 40); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); fmpq_poly_randtest_small(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_exp_series_basecase(b, a, n, rbits2); arb_poly_exp_series_basecase(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); } /* test that log(exp(f)) contains f */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2, rbits3; fmpq_poly_t A; arb_poly_t a, b, c; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 40); n = 1 + n_randint(state, 40); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); do { fmpq_poly_randtest_small(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_exp_series_basecase(b, a, n, rbits3); } while (b->length == 0 || arb_contains_zero(b->coeffs)); arb_poly_log_series(c, b, n, rbits2); fmpq_poly_truncate(A, n); if (!arb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-gamma_series.c000066400000000000000000000061251461254215100212550ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_gamma_series, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, qbits, rbits1, rbits2, rbits3; fmpq_poly_t A; arb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 400); rbits2 = 2 + n_randint(state, 400); rbits3 = 2 + n_randint(state, 400); m = 1 + n_randint(state, 25); n1 = 1 + n_randint(state, 25); n2 = 1 + n_randint(state, 25); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest_not_zero(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_gamma_series(b, a, n1, rbits2); arb_poly_gamma_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check gamma(a) * a = gamma(a+1) */ arb_poly_mullow(c, b, a, n1, rbits2); arb_poly_set(d, a); arb_add_ui(d->coeffs, d->coeffs, 1, rbits2); arb_poly_gamma_series(d, d, n1, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation, n1 = %wd)\n\n", n1); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_gamma_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-get_coeff_ptr.c000066400000000000000000000025431461254215100214270ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_get_coeff_ptr, state) { int i, result; for (i = 0; i < 1000; i++) { arb_poly_t A; arb_t a; slong n = n_randint(state, 100); arb_poly_init(A); arb_poly_randtest(A, state, n_randint(state, 100), 100, 10); arb_init(a); arb_poly_get_coeff_arb(a, A, n); result = n < arb_poly_length(A) ? arb_equal(a, arb_poly_get_coeff_ptr(A, n)) : arb_poly_get_coeff_ptr(A, n) == NULL; if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), arb_poly_printd(A, 10), flint_printf("\n\n"); flint_printf("a = "), arb_print(a), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_abort(); } arb_poly_clear(A); arb_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-get_set_coeff_arb.c000066400000000000000000000027761461254215100222510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_get_set_coeff_arb, state) { int i, j, result; for (i = 0; i < 100; i++) { arb_poly_t a; arb_t x1, x2; slong coeff, len; arb_poly_init(a); arb_init(x1); arb_init(x2); len = n_randint(state, 100) + 1; for (j = 0; j < 100; j++) { arb_randtest(x1, state, 2 + n_randint(state, 200), 10); coeff = n_randint(state, len); arb_poly_set_coeff_arb(a, coeff, x1); arb_poly_get_coeff_arb(x2, a, coeff); result = (arb_equal(x1, x2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x1 = "), arb_print(x1), flint_printf("\n"); flint_printf("x2 = "), arb_print(x2), flint_printf("\n"); flint_printf("coeff = %wd, length = %wd\n", coeff, len); flint_abort(); } } arb_clear(x1); arb_clear(x2); arb_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-get_unique_fmpz_poly.c000066400000000000000000000040331461254215100230610ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_get_unique_fmpz_poly, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong prec, c; fmpz_poly_t A, B; arb_poly_t a, b; fmpz_poly_init(A); fmpz_poly_init(B); arb_poly_init(a); arb_poly_init(b); fmpz_poly_randtest(A, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000)); fmpz_poly_randtest(B, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000)); c = 1 + n_randint(state, 1000); prec = 2 + n_randint(state, 100); for ( ; ; ) { arb_poly_set_fmpz_poly(a, A, prec); arb_poly_set_fmpz_poly(b, B, prec); arb_poly_scalar_mul_2exp_si(b, b, -c); arb_poly_add(a, a, b, prec); arb_poly_sub(a, a, b, prec); if (arb_poly_get_unique_fmpz_poly(B, a)) { if (!fmpz_poly_equal(A, B)) { flint_printf("FAIL\n\n"); flint_printf("A = "); fmpz_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpz_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_abort(); } break; } else { prec *= 2; } } fmpz_poly_clear(A); fmpz_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-graeffe_transform.c000066400000000000000000000047101461254215100223110ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_graeffe_transform, state) { slong iter; arb_poly_t a, b, c; arb_ptr roots; arb_t leading; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_init(leading); for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong n, prec, i; n = n_randint(state, 20); prec = 2 + n_randint(state, 256); roots = _arb_vec_init(n); arb_randtest(leading, state, prec, n_randint(state, 16)); for (i = 0; i < n; i++) arb_randtest(roots + i, state, prec, n_randint(state, 16)); arb_poly_product_roots(a, roots, n, prec); arb_poly_scalar_mul(a, a, leading, prec); for (i = 0; i < n; i++) arb_sqr(roots + i, roots + i, prec); arb_sqr(leading, leading, prec); arb_poly_product_roots(c, roots, n, prec); arb_poly_scalar_mul(c, c, leading, prec); arb_poly_graeffe_transform(b, a, prec); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_graeffe_transform(a, a, prec); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("n = %wd, prec = %wd\n\n", n, prec); flint_printf("a: "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b: "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c: "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } _arb_vec_clear(roots, n); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_clear(leading); TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-interpolate_barycentric.c000066400000000000000000000046261461254215100235400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_interpolate_barycentric, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t P; arb_poly_t R, S; fmpq_t t, u; arb_ptr xs, ys; fmpq_poly_init(P); arb_poly_init(R); arb_poly_init(S); fmpq_init(t); fmpq_init(u); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 5); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_randtest(P, state, 1 + n_randint(state, 20), qbits1); n = P->length; xs = _arb_vec_init(n); ys = _arb_vec_init(n); arb_poly_set_fmpq_poly(R, P, rbits1); if (n > 0) { fmpq_randtest(t, state, qbits2); arb_set_fmpq(xs, t, rbits2); for (i = 1; i < n; i++) { fmpq_randtest_not_zero(u, state, qbits2); fmpq_abs(u, u); fmpq_add(t, t, u); arb_set_fmpq(xs + i, t, rbits2); } } for (i = 0; i < n; i++) arb_poly_evaluate(ys + i, R, xs + i, rbits2); arb_poly_interpolate_barycentric(S, xs, ys, n, rbits3); if (!arb_poly_contains_fmpq_poly(S, P)) { flint_printf("FAIL:\n"); flint_printf("P = "); fmpq_poly_print(P); flint_printf("\n\n"); flint_printf("R = "); arb_poly_printd(R, 15); flint_printf("\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(P); arb_poly_clear(R); arb_poly_clear(S); fmpq_clear(t); fmpq_clear(u); _arb_vec_clear(xs, n); _arb_vec_clear(ys, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-interpolate_fast.c000066400000000000000000000046101461254215100221610ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_interpolate_fast, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t P; arb_poly_t R, S; fmpq_t t, u; arb_ptr xs, ys; fmpq_poly_init(P); arb_poly_init(R); arb_poly_init(S); fmpq_init(t); fmpq_init(u); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 5); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_randtest(P, state, 1 + n_randint(state, 20), qbits1); n = P->length; xs = _arb_vec_init(n); ys = _arb_vec_init(n); arb_poly_set_fmpq_poly(R, P, rbits1); if (n > 0) { fmpq_randtest(t, state, qbits2); arb_set_fmpq(xs, t, rbits2); for (i = 1; i < n; i++) { fmpq_randtest_not_zero(u, state, qbits2); fmpq_abs(u, u); fmpq_add(t, t, u); arb_set_fmpq(xs + i, t, rbits2); } } for (i = 0; i < n; i++) arb_poly_evaluate(ys + i, R, xs + i, rbits2); arb_poly_interpolate_fast(S, xs, ys, n, rbits3); if (!arb_poly_contains_fmpq_poly(S, P)) { flint_printf("FAIL:\n"); flint_printf("P = "); fmpq_poly_print(P); flint_printf("\n\n"); flint_printf("R = "); arb_poly_printd(R, 15); flint_printf("\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(P); arb_poly_clear(R); arb_poly_clear(S); fmpq_clear(t); fmpq_clear(u); _arb_vec_clear(xs, n); _arb_vec_clear(ys, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-interpolate_newton.c000066400000000000000000000046141461254215100225420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_interpolate_newton, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t P; arb_poly_t R, S; fmpq_t t, u; arb_ptr xs, ys; fmpq_poly_init(P); arb_poly_init(R); arb_poly_init(S); fmpq_init(t); fmpq_init(u); qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 5); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_randtest(P, state, 1 + n_randint(state, 20), qbits1); n = P->length; xs = _arb_vec_init(n); ys = _arb_vec_init(n); arb_poly_set_fmpq_poly(R, P, rbits1); if (n > 0) { fmpq_randtest(t, state, qbits2); arb_set_fmpq(xs, t, rbits2); for (i = 1; i < n; i++) { fmpq_randtest_not_zero(u, state, qbits2); fmpq_abs(u, u); fmpq_add(t, t, u); arb_set_fmpq(xs + i, t, rbits2); } } for (i = 0; i < n; i++) arb_poly_evaluate(ys + i, R, xs + i, rbits2); arb_poly_interpolate_newton(S, xs, ys, n, rbits3); if (!arb_poly_contains_fmpq_poly(S, P)) { flint_printf("FAIL:\n"); flint_printf("P = "); fmpq_poly_print(P); flint_printf("\n\n"); flint_printf("R = "); arb_poly_printd(R, 15); flint_printf("\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(P); arb_poly_clear(R); arb_poly_clear(S); fmpq_clear(t); fmpq_clear(u); _arb_vec_clear(xs, n); _arb_vec_clear(ys, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-inv_series.c000066400000000000000000000041601461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_inv_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; arb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); do { fmpq_poly_randtest_not_zero(A, state, m, qbits); } while (A->coeffs[0] == 0); arb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); fmpq_poly_inv_series(B, A, n); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_inv_series(b, a, n, rbits2); if (!arb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_inv_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-lambertw_series.c000066400000000000000000000102661461254215100220110ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_lambertw_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t x1, x2, t, w1, w2; slong prec1, prec2, n1, n2, ebits; int branch; arb_poly_init(x1); arb_poly_init(x2); arb_poly_init(t); arb_poly_init(w1); arb_poly_init(w2); branch = n_randint(state, 2); n1 = n_randint(state, 15); n2 = n_randint(state, 15); if (n_randint(state, 4) == 0) { prec1 = 2 + n_randint(state, 3000); prec2 = 2 + n_randint(state, 3000); ebits = 1 + n_randint(state, 1000); } else { prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 50); } arb_poly_randtest(x1, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); arb_poly_randtest(x2, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); arb_poly_randtest(t, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); arb_poly_randtest(w1, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); arb_poly_randtest(w2, state, 1 + n_randint(state, 10), 1 + n_randint(state, 1000), ebits); if (n_randint(state, 4) == 0) { arb_t u; arb_init(u); arb_const_e(u, 2 * prec1); arb_inv(u, u, 2 * prec1); arb_poly_set_arb(t, u); arb_poly_sub(x1, x1, t, 2 * prec1); arb_clear(u); } if (n_randint(state, 2)) { arb_poly_set(x2, x1); } else { arb_poly_add(x2, x1, t, 2 * prec1); arb_poly_sub(x2, x2, t, 2 * prec1); } arb_poly_lambertw_series(w1, x1, branch, n1, prec1); if (n_randint(state, 2)) { arb_poly_set(w2, x2); arb_poly_lambertw_series(w2, w2, branch, n2, prec1); } else { arb_poly_lambertw_series(w2, x2, branch, n2, prec1); } arb_poly_truncate(w1, FLINT_MIN(n1, n2)); arb_poly_truncate(w2, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(w1, w2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("branch = %d, prec1 = %wd, prec2 = %wd\n\n", branch, prec1, prec2); flint_printf("x1 = "); arb_poly_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); arb_poly_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); arb_poly_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); arb_poly_printd(w2, 50); flint_printf("\n\n"); flint_abort(); } arb_poly_exp_series(t, w1, FLINT_MIN(n1, n2), prec1); arb_poly_mullow(t, t, w1, FLINT_MIN(n1, n2), prec1); arb_poly_truncate(x1, FLINT_MIN(n1, n2)); if (!arb_poly_contains(t, x1)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("branch = %d, prec1 = %wd, prec2 = %wd\n\n", branch, prec1, prec2); flint_printf("x1 = "); arb_poly_printd(x1, 50); flint_printf("\n\n"); flint_printf("x2 = "); arb_poly_printd(x2, 50); flint_printf("\n\n"); flint_printf("w1 = "); arb_poly_printd(w1, 50); flint_printf("\n\n"); flint_printf("w2 = "); arb_poly_printd(w2, 50); flint_printf("\n\n"); flint_printf("t = "); arb_poly_printd(t, 50); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(x1); arb_poly_clear(x2); arb_poly_clear(t); arb_poly_clear(w1); arb_poly_clear(w2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-lgamma_series.c000066400000000000000000000062471461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_lgamma_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, qbits, rbits1, rbits2, rbits3; fmpq_poly_t A; arb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 400); rbits2 = 2 + n_randint(state, 400); rbits3 = 2 + n_randint(state, 400); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest_not_zero(A, state, m, qbits); fmpz_abs(A->coeffs, A->coeffs); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_lgamma_series(b, a, n1, rbits2); arb_poly_lgamma_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check loggamma(a) + log(a) = loggamma(a+1) */ arb_poly_log_series(c, a, n1, rbits2); arb_poly_add(c, b, c, rbits2); arb_poly_set(d, a); arb_add_ui(d->coeffs, d->coeffs, 1, rbits2); arb_poly_lgamma_series(d, d, n1, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_lgamma_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-log1p_series.c000066400000000000000000000037131461254215100212150ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_log1p_series, state) { slong iter; /* compare with log_series */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c; slong m, n, prec; prec = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_randtest(a, state, 1 + n_randint(state, 10), prec, 5); arb_poly_randtest(b, state, 1 + n_randint(state, 10), prec, 5); arb_poly_randtest(c, state, 1 + n_randint(state, 10), prec, 5); if (n_randint(state, 2)) arb_poly_log1p_series(b, a, n, prec); else { arb_poly_set(b, a); arb_poly_log1p_series(b, b, n, prec); } arb_poly_add_si(c, a, 1, prec); arb_poly_log_series(c, c, m, prec); arb_poly_truncate(b, FLINT_MIN(m, n)); arb_poly_truncate(c, FLINT_MIN(m, n)); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd\n\n", m, n); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-log_series.c000066400000000000000000000114331461254215100207520ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_log_series, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; arb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); fmpq_poly_randtest_not_zero(A, state, m, qbits); fmpq_poly_set_coeff_ui(A, 0, UWORD(1)); fmpq_poly_log_series(B, A, n); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); arb_poly_log_series(b, a, n, rbits2); if (!arb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); } /* test aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); do { fmpq_poly_randtest_not_zero(A, state, m, qbits); } while (fmpz_sgn(A->coeffs + 0) <= 0); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_log_series(b, a, n, rbits2); arb_poly_log_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); } /* test that exp(log(f)) contains f */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2, rbits3; fmpq_poly_t A; arb_poly_t a, b, c; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); do { fmpq_poly_randtest_not_zero(A, state, m, qbits); } while (fmpz_sgn(A->coeffs + 0) <= 0); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); arb_poly_log_series(b, a, n, rbits2); arb_poly_exp_series_basecase(c, b, n, rbits3); fmpq_poly_truncate(A, n); if (!arb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-mul.c000066400000000000000000000071511461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_mul, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t A, B, C; arb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_mul(C, A, B); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_mul(c, a, b, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_mul(d, d, b, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_mul(d, a, d, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ arb_poly_set(b, a); arb_poly_mul(c, a, b, rbits3); arb_poly_mul(d, a, a, rbits3); if (!arb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_mul(a, a, a, rbits3); if (!arb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-mullow.c000066400000000000000000000074621461254215100201450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_mullow, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; arb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_mullow(C, A, B, trunc); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_mullow(c, a, b, trunc, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_mullow(d, d, b, trunc, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_mullow(d, a, d, trunc, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ arb_poly_set(b, a); arb_poly_mullow(c, a, b, trunc, rbits3); arb_poly_mullow(d, a, a, trunc, rbits3); if (!arb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_mullow(a, a, a, trunc, rbits3); if (!arb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-mullow_block.c000066400000000000000000000152551461254215100213160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_mullow_block, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; arb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 1000); qbits2 = 2 + n_randint(state, 1000); rbits1 = 2 + n_randint(state, 1000); rbits2 = 2 + n_randint(state, 1000); rbits3 = 2 + n_randint(state, 1000); trunc = n_randint(state, 100); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 100), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 100), qbits2); fmpq_poly_mullow(C, A, B, trunc); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_mullow_block(c, a, b, trunc, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_mullow_block(d, d, b, trunc, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_mullow_block(d, a, d, trunc, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ arb_poly_set(b, a); arb_poly_mullow_block(c, a, b, trunc, rbits3); arb_poly_mullow_block(d, a, a, trunc, rbits3); if (!arb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_mullow_block(a, a, a, trunc, rbits3); if (!arb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { slong rbits1, rbits2, rbits3, trunc; arb_poly_t a, b, c, ab, ac, bc, abc, abc2; rbits1 = 2 + n_randint(state, 300); rbits2 = 2 + n_randint(state, 300); rbits3 = 2 + n_randint(state, 300); trunc = n_randint(state, 100); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(ab); arb_poly_init(ac); arb_poly_init(bc); arb_poly_init(abc); arb_poly_init(abc2); arb_poly_randtest(a, state, 1 + n_randint(state, 100), rbits1, 1 + n_randint(state, 100)); arb_poly_randtest(b, state, 1 + n_randint(state, 100), rbits2, 1 + n_randint(state, 100)); arb_poly_randtest(c, state, 1 + n_randint(state, 100), rbits2, 1 + n_randint(state, 100)); /* check a*(b+c) = a*b + a*c */ arb_poly_mullow_block(ab, a, b, trunc, rbits3); arb_poly_mullow_block(ac, a, c, trunc, rbits3); arb_poly_add(abc, ab, ac, rbits3); arb_poly_add(bc, b, c, rbits3); arb_poly_mullow_block(abc2, a, bc, trunc, rbits3); if (!arb_poly_overlaps(abc, abc2)) { flint_printf("FAIL (a*(b+c) = a*b + a*c) \n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check (b+c)^2 = b^2 + 2bc + c^2 */ arb_poly_mullow_block(a, b, c, trunc, rbits3); arb_poly_scalar_mul_2exp_si(a, a, 1); arb_poly_mullow_block(abc, b, b, trunc, rbits3); arb_poly_mullow_block(abc2, c, c, trunc, rbits3); arb_poly_add(abc, abc, a, rbits3); arb_poly_add(abc, abc, abc2, rbits3); arb_poly_mullow_block(abc2, bc, bc, trunc, rbits3); if (!arb_poly_overlaps(abc, abc2)) { flint_printf("FAIL ((b+c)^2 = b^2 + 2bc + c^2) \n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("abc = "); arb_poly_printd(abc, 15); flint_printf("\n\n"); flint_printf("abc2 = "); arb_poly_printd(abc2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(ab); arb_poly_clear(ac); arb_poly_clear(bc); arb_poly_clear(abc); arb_poly_clear(abc2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-mullow_classical.c000066400000000000000000000075701461254215100221630ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_mullow_classical, state) { slong iter; /* compare with fmpq_poly */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3, trunc; fmpq_poly_t A, B, C; arb_poly_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); trunc = n_randint(state, 10); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_mullow(C, A, B, trunc); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_mullow_classical(c, a, b, trunc, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_mullow_classical(d, d, b, trunc, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_mullow_classical(d, a, d, trunc, rbits3); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } /* test squaring */ arb_poly_set(b, a); arb_poly_mullow_classical(c, a, b, trunc, rbits3); arb_poly_mullow_classical(d, a, a, trunc, rbits3); if (!arb_poly_overlaps(c, d)) /* not guaranteed to be identical */ { flint_printf("FAIL (squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_mullow_classical(a, a, a, trunc, rbits3); if (!arb_poly_equal(d, a)) { flint_printf("FAIL (aliasing, squaring)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-pow_arb_series.c000066400000000000000000000051011461254215100216150ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_pow_arb_series, state) { slong iter; /* compare with exp/log */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong prec, trunc; arb_poly_t f, g, h1, h2; arb_t c; prec = 2 + n_randint(state, 200); trunc = n_randint(state, 20); arb_poly_init(f); arb_poly_init(g); arb_poly_init(h1); arb_poly_init(h2); arb_init(c); /* generate binomials */ if (n_randint(state, 20) == 0) { arb_randtest(c, state, prec, 10); arb_poly_set_coeff_arb(f, 0, c); arb_randtest(c, state, prec, 10); arb_poly_set_coeff_arb(f, 1 + n_randint(state, 20), c); } else { arb_poly_randtest(f, state, 1 + n_randint(state, 20), prec, 10); } arb_poly_randtest(h1, state, 1 + n_randint(state, 20), prec, 10); arb_randtest(c, state, prec, 10); arb_poly_set_arb(g, c); /* f^c */ arb_poly_pow_arb_series(h1, f, c, trunc, prec); /* f^c = exp(c*log(f)) */ arb_poly_log_series(h2, f, trunc, prec); arb_poly_mullow(h2, h2, g, trunc, prec); arb_poly_exp_series(h2, h2, trunc, prec); if (!arb_poly_overlaps(h1, h2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd\n", prec); flint_printf("trunc = %wd\n", trunc); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_printf("h1 = "); arb_poly_printd(h1, 15); flint_printf("\n\n"); flint_printf("h2 = "); arb_poly_printd(h2, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_pow_arb_series(f, f, c, trunc, prec); if (!arb_poly_overlaps(f, h1)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(f); arb_poly_clear(g); arb_poly_clear(h1); arb_poly_clear(h2); arb_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-pow_series.c000066400000000000000000000054021461254215100207750ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_pow_series, state) { slong iter; for (iter = 0; iter < 50000 * 0.1 * flint_test_multiplier(); iter++) { slong rbits1, rbits2, len; arb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); len = n_randint(state, 25); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); if (n_randint(state, 4) == 0) arb_poly_randtest(a, state, 1, rbits1, 25); else arb_poly_randtest(a, state, 1 + n_randint(state, 20), rbits1, 5); if (n_randint(state, 4) == 0) arb_poly_randtest(b, state, 1, rbits1, 25); else arb_poly_randtest(b, state, 1 + n_randint(state, 20), rbits1, 5); arb_poly_randtest(c, state, 1 + n_randint(state, 20), rbits1, 5); arb_poly_pow_series(c, a, b, len, rbits2); /* a^b = exp(b log a) */ arb_poly_log_series(d, a, len, rbits2); arb_poly_mullow(d, d, b, len, rbits2); arb_poly_exp_series(d, d, len, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (iter %wd)\n\n", iter); flint_printf("bits2 = %wd\n", rbits2); flint_printf("len = %wd\n", len); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } /* check aliasing */ if (iter < 5000) { arb_poly_set(d, a); arb_poly_pow_series(d, d, b, len, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (aliasing 1)\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_pow_series(d, a, d, len, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (aliasing 2)\n"); flint_abort(); } } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-pow_ui.c000066400000000000000000000040271461254215100201220ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_pow_ui, state) { slong iter; /* compare with fmpz_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong zbits1, rbits1, rbits2; ulong e; fmpz_poly_t A, B; arb_poly_t a, b; zbits1 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); e = n_randint(state, 30); fmpz_poly_init(A); fmpz_poly_init(B); arb_poly_init(a); arb_poly_init(b); fmpz_poly_randtest(A, state, 1 + n_randint(state, 8), zbits1); fmpz_poly_pow(B, A, e); arb_poly_set_fmpz_poly(a, A, rbits1); arb_poly_pow_ui(b, a, e, rbits2); if (!arb_poly_contains_fmpz_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("e = %wu\n", e); flint_printf("A = "); fmpz_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpz_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_pow_ui(a, a, e, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpz_poly_clear(A); fmpz_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-pow_ui_trunc_binexp.c000066400000000000000000000042711461254215100227030ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_pow_ui_trunc_binexp, state) { slong iter; /* compare with fmpz_poly */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong zbits1, rbits1, rbits2, trunc; ulong e; fmpz_poly_t A, B; arb_poly_t a, b; zbits1 = 2 + n_randint(state, 100); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); e = n_randint(state, 50); trunc = n_randint(state, 40); fmpz_poly_init(A); fmpz_poly_init(B); arb_poly_init(a); arb_poly_init(b); fmpz_poly_randtest(A, state, 1 + n_randint(state, 10), zbits1); fmpz_poly_pow_trunc(B, A, e, trunc); arb_poly_set_fmpz_poly(a, A, rbits1); arb_poly_pow_ui_trunc_binexp(b, a, e, trunc, rbits2); if (!arb_poly_contains_fmpz_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("e = %wu\n", e); flint_printf("trunc = %wd\n", trunc); flint_printf("A = "); fmpz_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpz_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_pow_ui_trunc_binexp(a, a, e, trunc, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpz_poly_clear(A); fmpz_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-product_roots.c000066400000000000000000000040561461254215100215300ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_product_roots, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { slong prec, len, m, i; arb_poly_t a, b, c, d; arb_ptr r; prec = 2 + n_randint(state, 200); len = n_randint(state, 12); if (len > 0) m = n_randint(state, len); else m = 0; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); r = _arb_vec_init(len); for (i = 0; i < len; i++) arb_randtest(r + i, state, 1 + n_randint(state, 200), 10); arb_poly_product_roots(a, r, len, prec); arb_poly_product_roots(b, r, m, prec); arb_poly_product_roots(c, r + m, len - m, prec); arb_poly_mul(d, b, c, prec); if (!arb_poly_overlaps(a, d)) { flint_printf("FAIL\n\n"); flint_printf("len = %wd, m = %wd\n\n", len, m); for (i = 0; i < len; i++) { arb_printd(r + i, 15); flint_printf("\n"); } flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); _arb_vec_clear(r, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-product_roots_complex.c000066400000000000000000000050731461254215100232570ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" #include "acb_poly.h" TEST_FUNCTION_START(arb_poly_product_roots_complex, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { slong prec, len1, len2, i; arb_poly_t a; acb_poly_t b, c; arb_ptr r; acb_ptr r2, r3; prec = 2 + n_randint(state, 200); len1 = n_randint(state, 12); len2 = n_randint(state, 8); arb_poly_init(a); acb_poly_init(b); acb_poly_init(c); r = _arb_vec_init(len1); r2 = _acb_vec_init(len2); r3 = _acb_vec_init(len1 + 2 * len2); for (i = 0; i < len1; i++) arb_randtest(r + i, state, 1 + n_randint(state, 200), 3); for (i = 0; i < len2; i++) acb_randtest(r2 + i, state, 1 + n_randint(state, 200), 3); for (i = 0; i < len1; i++) acb_set_arb(r3 + i, r + i); for (i = 0; i < len2; i++) acb_set(r3 + len1 + i, r2 + i); for (i = 0; i < len2; i++) acb_conj(r3 + len1 + len2 + i, r2 + i); arb_poly_product_roots_complex(a, r, len1, r2, len2, prec); acb_poly_product_roots(b, r3, len1 + 2 * len2, prec); acb_poly_set_arb_poly(c, a); if (!acb_poly_overlaps(b, c)) { flint_printf("FAIL\n\n"); flint_printf("len1 = %wd, len2 = %wd\n\n", len1, len2); for (i = 0; i < len1; i++) { arb_printd(r + i, 15); flint_printf("\n"); } for (i = 0; i < len2; i++) { acb_printd(r2 + i, 15); flint_printf("\n"); } flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); acb_poly_clear(b); acb_poly_clear(c); _arb_vec_clear(r, len1); _acb_vec_clear(r2, len2); _acb_vec_clear(r3, len1 + 2 * len2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-revert_series.c000066400000000000000000000043001461254215100214730ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_revert_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, rbits1, rbits2, n; fmpq_poly_t A, B; arb_poly_t a, b, c; qbits1 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); n = 2 + n_randint(state, 25); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); do { fmpq_poly_randtest(A, state, 1 + n_randint(state, 25), qbits1); fmpq_poly_set_coeff_ui(A, 0, 0); } while (A->length < 2 || fmpz_is_zero(A->coeffs + 1)); fmpq_poly_revert_series(B, A, n); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_revert_series(b, a, n, rbits2); if (!arb_poly_contains_fmpq_poly(b, B)) { flint_printf("FAIL\n\n"); flint_printf("n = %wd, bits2 = %wd\n", n, rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(c, a); arb_poly_revert_series(c, c, n, rbits2); if (!arb_poly_equal(c, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-rgamma_series.c000066400000000000000000000060611461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_rgamma_series, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, qbits, rbits1, rbits2, rbits3; fmpq_poly_t A; arb_poly_t a, b, c, d; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 400); rbits2 = 2 + n_randint(state, 400); rbits3 = 2 + n_randint(state, 400); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); fmpq_poly_randtest_not_zero(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_rgamma_series(b, a, n1, rbits2); arb_poly_rgamma_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check rgamma(a) = a gamma(a+1) */ arb_poly_add_si(d, a, 1, rbits2); arb_poly_rgamma_series(d, d, n1, rbits2); arb_poly_mullow(c, d, a, n1, rbits2); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL (functional equation, n1 = %wd)\n\n", n1); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_rgamma_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-riemann_siegel_theta_series.c000066400000000000000000000056571461254215100243520ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_riemann_siegel_theta_series, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; arb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 150); rbits2 = 2 + n_randint(state, 150); rbits3 = 2 + n_randint(state, 150); m = 1 + n_randint(state, 15); n1 = 1 + n_randint(state, 15); n2 = 1 + n_randint(state, 15); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_randtest(a, state, m, rbits1, 10); /* if (a->length != 0) arb_randtest_precise(a->coeffs, state, rbits1, 1); */ arb_poly_randtest(b, state, m, rbits1, 10); arb_poly_randtest(c, state, m, rbits1, 10); arb_poly_riemann_siegel_theta_series(b, a, n1, rbits2); arb_poly_riemann_siegel_theta_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check theta(a) = -theta(-a) */ arb_poly_neg(d, a); arb_poly_riemann_siegel_theta_series(c, d, n1, rbits2); arb_poly_neg(c, c); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL (symmetry, n1 = %wd)\n\n", n1); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_riemann_siegel_theta_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-riemann_siegel_z_series.c000066400000000000000000000055601461254215100235070ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_riemann_siegel_z_series, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; arb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 150); rbits2 = 2 + n_randint(state, 150); rbits3 = 2 + n_randint(state, 150); m = 1 + n_randint(state, 15); n1 = 1 + n_randint(state, 15); n2 = 1 + n_randint(state, 15); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_randtest(a, state, m, rbits1, 10); if (a->length != 0) arb_randtest_precise(a->coeffs, state, rbits1, 1); arb_poly_randtest(b, state, m, rbits1, 10); arb_poly_randtest(c, state, m, rbits1, 10); arb_poly_riemann_siegel_z_series(b, a, n1, rbits2); arb_poly_riemann_siegel_z_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } /* check Z(a) = Z(-a) */ arb_poly_neg(d, a); arb_poly_riemann_siegel_z_series(c, d, n1, rbits2); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL (symmetry, n1 = %wd)\n\n", n1); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_riemann_siegel_z_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-rising_ui_series.c000066400000000000000000000063151461254215100221640ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_rising_ui_series, state) { slong iter; /* check rf(f, a) * rf(f + a, b) = rf(f, a + b) */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, trunc; ulong a, b; arb_poly_t f, g, h1, h2, h1h2, h3; bits = 2 + n_randint(state, 200); trunc = 1 + n_randint(state, 20); a = n_randint(state, 10); b = n_randint(state, 10); arb_poly_init(f); arb_poly_init(g); arb_poly_init(h1); arb_poly_init(h2); arb_poly_init(h1h2); arb_poly_init(h3); arb_poly_randtest(f, state, 1 + n_randint(state, 20), bits, 4); arb_poly_set(g, f); /* g = f + 1 */ if (g->length == 0) { arb_poly_fit_length(g, 1); arb_set_ui(g->coeffs, a); _arb_poly_set_length(g, 1); _arb_poly_normalise(g); } else { arb_add_ui(g->coeffs, g->coeffs, a, bits); _arb_poly_normalise(g); } arb_poly_rising_ui_series(h1, f, a, trunc, bits); arb_poly_rising_ui_series(h2, g, b, trunc, bits); arb_poly_rising_ui_series(h3, f, a + b, trunc, bits); arb_poly_mullow(h1h2, h1, h2, trunc, bits); if (!arb_poly_overlaps(h1h2, h3)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", a); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); arb_poly_printd(g, 15); flint_printf("\n\n"); flint_printf("h1 = "); arb_poly_printd(h1, 15); flint_printf("\n\n"); flint_printf("h2 = "); arb_poly_printd(h2, 15); flint_printf("\n\n"); flint_printf("h1h2 = "); arb_poly_printd(h1h2, 15); flint_printf("\n\n"); flint_printf("h3 = "); arb_poly_printd(h3, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_rising_ui_series(f, f, a, trunc, bits); if (!arb_poly_equal(f, h1)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("bits = %wd\n", bits); flint_printf("trunc = %wd\n", trunc); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", a); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("h1 = "); arb_poly_printd(h1, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); arb_poly_clear(g); arb_poly_clear(h1); arb_poly_clear(h2); arb_poly_clear(h1h2); arb_poly_clear(h3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-root_bound_fujiwara.c000066400000000000000000000043071461254215100226630ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_root_bound_fujiwara, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a; arb_ptr roots; arb_t t; mag_t mag1, mag2; slong i, deg, prec; prec = 10 + n_randint(state, 400); deg = n_randint(state, 10); arb_init(t); arb_poly_init(a); mag_init(mag1); mag_init(mag2); roots = _arb_vec_init(deg); for (i = 0; i < deg; i++) arb_randtest(roots + i, state, prec, 1 + n_randint(state, 20)); arb_poly_product_roots(a, roots, deg, prec); arb_randtest(t, state, prec, 1 + n_randint(state, 20)); arb_poly_scalar_mul(a, a, t, prec); arb_poly_root_bound_fujiwara(mag1, a); for (i = 0; i < deg; i++) { arb_get_mag(mag2, roots + i); /* arb_get_mag gives an upper bound which due to rounding could be larger than mag1, so we pick a slightly smaller number */ mag_mul_ui(mag2, mag2, 10000); mag_div_ui(mag2, mag2, 10001); if (mag_cmp(mag2, mag1) > 0) { flint_printf("FAIL\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("root = "); arb_printd(roots + i, 15); flint_printf("\n\n"); flint_printf("mag1 = "); mag_printd(mag1, 10); flint_printf("\n\n"); flint_printf("mag2 = "); mag_printd(mag2, 10); flint_printf("\n\n"); flint_abort(); } } _arb_vec_clear(roots, deg); arb_clear(t); arb_poly_clear(a); mag_clear(mag1); mag_clear(mag2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-rsqrt_series.c000066400000000000000000000043061461254215100213450ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_rsqrt_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b, c; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); fmpq_poly_randtest_not_zero(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_randtest(b, state, 1 + n_randint(state, 30), rbits1, 5); arb_poly_rsqrt_series(b, a, n, rbits2); /* Check 1/((1/sqrt(a))^2) = a */ arb_poly_mullow(c, b, b, n, rbits2); arb_poly_inv_series(c, c, n, rbits2); fmpq_poly_truncate(A, n); if (!arb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_rsqrt_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-set_trunc_round.c000066400000000000000000000042501461254215100220330ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_set_trunc_round, state) { int iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d, e; slong n, prec; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_init(e); arb_poly_randtest(a, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); arb_poly_randtest(b, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); arb_poly_randtest(c, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); arb_poly_randtest(d, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); arb_poly_randtest(e, state, n_randint(state, 10), 2 + n_randint(state, 200), 10); n = n_randint(state, 10); prec = 2 + n_randint(state, 200); arb_poly_set_trunc(b, a, n); arb_poly_set_round(b, b, prec); arb_poly_set_round(c, a, prec); arb_poly_set_trunc(c, c, n); arb_poly_set_trunc_round(d, a, n, prec); arb_poly_set(e, a); arb_poly_set_trunc_round(e, e, n, prec); if (!arb_poly_equal(b, c) || !arb_poly_equal(c, d) || !arb_poly_equal(d, e)) { flint_printf("FAIL\n\n"); arb_poly_printd(a, 50), flint_printf("\n\n"); arb_poly_printd(b, 50), flint_printf("\n\n"); arb_poly_printd(c, 50), flint_printf("\n\n"); arb_poly_printd(d, 50), flint_printf("\n\n"); arb_poly_printd(e, 50), flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); arb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-shift_left_right.c000066400000000000000000000054161461254215100221470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_shift_left_right, state) { int i, result; /* Check aliasing of a and b for left shift */ for (i = 0; i < 1000; i++) { arb_poly_t a, b; slong shift = n_randint(state, 100); arb_poly_init(a); arb_poly_init(b); arb_poly_randtest(a, state, n_randint(state, 100), 2 + n_randint(state, 200), 10); arb_poly_shift_left(b, a, shift); arb_poly_shift_left(a, a, shift); result = (arb_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); arb_poly_printd(a, 10), flint_printf("\n\n"); arb_poly_printd(b, 10), flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); } /* Check aliasing of a and b for right shift */ for (i = 0; i < 1000; i++) { arb_poly_t a, b; slong shift = n_randint(state, 100); arb_poly_init(a); arb_poly_init(b); arb_poly_randtest(a, state, n_randint(state, 100), 2 + n_randint(state, 200), 10); arb_poly_shift_right(b, a, shift); arb_poly_shift_right(a, a, shift); result = (arb_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); arb_poly_printd(a, 10), flint_printf("\n\n"); arb_poly_printd(b, 10), flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); } /* Check shift left then right does nothing */ for (i = 0; i < 1000; i++) { arb_poly_t a, b, c; slong shift = n_randint(state, 100); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_randtest(a, state, n_randint(state, 100), 2 + n_randint(state, 200), 10); arb_poly_shift_left(b, a, shift); arb_poly_shift_right(c, b, shift); result = (arb_poly_equal(c, a)); if (!result) { flint_printf("FAIL:\n"); arb_poly_printd(a, 10), flint_printf("\n\n"); arb_poly_printd(b, 10), flint_printf("\n\n"); arb_poly_printd(c, 10), flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sin_cos_pi_series.c000066400000000000000000000052301461254215100223140ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sin_cos_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; arb_poly_t a, b, c, d, e; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_init(e); fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_sin_cos_pi_series(b, c, a, n, rbits2); /* Check sin(x)^2 + cos(x)^2 = 1 */ arb_poly_mullow(d, b, b, n, rbits2); arb_poly_mullow(e, c, c, n, rbits2); arb_poly_add(d, d, e, rbits2); fmpq_poly_one(B); if (!arb_poly_contains_fmpq_poly(d, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_sin_cos_pi_series(d, c, d, n, rbits2); if (!arb_poly_equal(b, d)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_sin_cos_pi_series(b, d, d, n, rbits2); if (!arb_poly_equal(c, d)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); arb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sin_cos_series.c000066400000000000000000000052141461254215100216260ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sin_cos_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; arb_poly_t a, b, c, d, e; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_init(e); fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_sin_cos_series(b, c, a, n, rbits2); /* Check sin(x)^2 + cos(x)^2 = 1 */ arb_poly_mullow(d, b, b, n, rbits2); arb_poly_mullow(e, c, c, n, rbits2); arb_poly_add(d, d, e, rbits2); fmpq_poly_one(B); if (!arb_poly_contains_fmpq_poly(d, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_sin_cos_series(d, c, d, n, rbits2); if (!arb_poly_equal(b, d)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_sin_cos_series(b, d, d, n, rbits2); if (!arb_poly_equal(c, d)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); arb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sin_pi_series.c000066400000000000000000000043101461254215100214460ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sin_pi_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; arb_poly_t S, A, B, C; arb_t pi; bits1 = 2 + n_randint(state, 200); bits2 = 2 + n_randint(state, 200); bits3 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); arb_poly_init(S); arb_poly_init(A); arb_poly_init(B); arb_poly_init(C); arb_init(pi); arb_poly_randtest(S, state, m, bits1, 3); arb_poly_randtest(A, state, m, bits1, 3); arb_poly_randtest(B, state, m, bits1, 3); arb_poly_sin_pi_series(A, S, n1, bits2); arb_const_pi(pi, bits3); arb_poly_set_arb(B, pi); arb_poly_mul(B, S, B, bits3); arb_poly_sin_series(B, B, n2, bits3); arb_poly_set(C, A); arb_poly_truncate(C, FLINT_MIN(n1, n2)); arb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("A = "); arb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); arb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_sin_pi_series(S, S, n1, bits2); if (!arb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(S); arb_poly_clear(A); arb_poly_clear(B); arb_poly_clear(C); arb_clear(pi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sin_series_cos_series.c000066400000000000000000000052541461254215100232040ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sin_series_cos_series, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A, B; arb_poly_t a, b, c, d, e; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); fmpq_poly_init(B); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_init(e); fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_sin_series(b, a, n, rbits2); arb_poly_cos_series(c, a, n, rbits2); /* Check sin(x)^2 + cos(x)^2 = 1 */ arb_poly_mullow(d, b, b, n, rbits2); arb_poly_mullow(e, c, c, n, rbits2); arb_poly_add(d, d, e, rbits2); fmpq_poly_one(B); if (!arb_poly_contains_fmpq_poly(d, B)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_sin_series(d, d, n, rbits2); if (!arb_poly_equal(b, d)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_cos_series(d, d, n, rbits2); if (!arb_poly_equal(c, d)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); arb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sinc_pi_series.c000066400000000000000000000057711461254215100216250ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson Copyright (C) 2019 D.H.J. Polymath This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sinc_pi_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3, rbits4; arb_poly_t a, b, c, d; arb_t pi; rbits1 = 2 + n_randint(state, 300); rbits2 = 2 + n_randint(state, 300); rbits3 = 2 + n_randint(state, 300); rbits4 = 2 + n_randint(state, 300); m = n_randint(state, 15); n1 = n_randint(state, 15); n2 = n_randint(state, 15); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_init(pi); arb_poly_randtest(a, state, m, rbits1, 10); arb_poly_randtest(b, state, 10, rbits1, 10); arb_poly_randtest(c, state, 10, rbits1, 10); arb_poly_sinc_pi_series(b, a, n1, rbits2); arb_poly_sinc_pi_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); arb_const_pi(pi, rbits4); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd, bits4 = %wd\n", n1, n2, rbits2, rbits3, rbits4); flint_printf("a = "); arb_poly_printd(a, 50); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 50); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 50); flint_printf("\n\n"); flint_abort(); } /* check pi x sinc_pi(x) = sin_pi(x) */ arb_poly_mullow(c, b, a, n1, rbits2); arb_poly_scalar_mul(c, c, pi, rbits2); arb_poly_sin_pi_series(d, a, n1, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_sinc_pi_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); arb_clear(pi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sinc_series.c000066400000000000000000000053401461254215100211250ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sinc_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, rbits1, rbits2, rbits3; arb_poly_t a, b, c, d; rbits1 = 2 + n_randint(state, 300); rbits2 = 2 + n_randint(state, 300); rbits3 = 2 + n_randint(state, 300); m = n_randint(state, 15); n1 = n_randint(state, 15); n2 = n_randint(state, 15); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_randtest(a, state, m, rbits1, 10); arb_poly_randtest(b, state, 10, rbits1, 10); arb_poly_randtest(c, state, 10, rbits1, 10); arb_poly_sinc_series(b, a, n1, rbits2); arb_poly_sinc_series(c, a, n2, rbits3); arb_poly_set(d, b); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL\n\n"); flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3); flint_printf("a = "); arb_poly_printd(a, 50); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 50); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 50); flint_printf("\n\n"); flint_abort(); } /* check x sinc(x) = sin(x) */ arb_poly_mullow(c, b, a, n1, rbits2); arb_poly_sin_series(d, a, n1, rbits2); if (!arb_poly_overlaps(c, d)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_sinc_series(a, a, n1, rbits2); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sinh_cosh_series.c000066400000000000000000000076521461254215100221560ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sinh_cosh_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d, e; slong n1, n2, prec; int alg1, alg2; prec = 2 + n_randint(state, 200); if (n_randint(state, 40) == 0) { n1 = n_randint(state, 300); n2 = n_randint(state, 300); } else { n1 = n_randint(state, 30); n2 = n_randint(state, 30); } arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_init(e); arb_poly_randtest(a, state, 20, prec, 10); arb_poly_randtest(b, state, 20, prec, 10); arb_poly_randtest(c, state, 20, prec, 10); arb_poly_randtest(d, state, 20, prec, 10); arb_poly_randtest(e, state, 20, prec, 10); alg1 = n_randint(state, 4); alg2 = n_randint(state, 7); switch (alg1) { case 0: arb_poly_sinh_cosh_series(b, c, a, n1, prec); break; case 1: arb_poly_sinh_cosh_series_basecase(b, c, a, n1, prec); break; case 2: arb_poly_sinh_cosh_series_exponential(b, c, a, n1, prec); break; default: arb_poly_sinh_series(b, a, n1, prec); arb_poly_cosh_series(c, a, n1, prec); break; } switch (alg2) { case 0: arb_poly_sinh_cosh_series(d, e, a, n2, prec); break; case 1: arb_poly_sinh_cosh_series_basecase(d, e, a, n2, prec); break; case 2: arb_poly_sinh_cosh_series_exponential(d, e, a, n2, prec); break; case 3: arb_poly_sinh_series(d, a, n2, prec); arb_poly_cosh_series(e, a, n2, prec); break; case 4: arb_poly_set(d, a); arb_poly_sinh_cosh_series(d, e, d, n2, prec); break; case 5: arb_poly_set(e, a); arb_poly_sinh_cosh_series(d, e, e, n2, prec); break; default: arb_poly_set(d, a); arb_poly_sinh_series(d, d, n2, prec); arb_poly_set(e, a); arb_poly_cosh_series(e, e, n2, prec); break; } arb_poly_truncate(b, FLINT_MIN(n1, n2)); arb_poly_truncate(c, FLINT_MIN(n1, n2)); arb_poly_truncate(d, FLINT_MIN(n1, n2)); arb_poly_truncate(e, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(b, d) || !arb_poly_overlaps(c, e)) { flint_printf("FAIL\n\n"); flint_printf("alg1 = %d, alg2 = %d, n1 = %wd, n2 = %wd\n\n", alg1, alg2, n1, n2); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(d, 15); flint_printf("\n\n"); flint_printf("d = "); arb_poly_printd(e, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); arb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sqrt_series.c000066400000000000000000000041021461254215100211550ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sqrt_series, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b, c; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 30); n = 1 + n_randint(state, 30); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); fmpq_poly_randtest_not_zero(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_sqrt_series(b, a, n, rbits2); /* Check sqrt(a)^2 = a */ arb_poly_mullow(c, b, b, n, rbits2); fmpq_poly_truncate(A, n); if (!arb_poly_contains_fmpq_poly(c, A)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_sqrt_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sub.c000066400000000000000000000043231461254215100174100ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sub, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_poly_t A, B, C; arb_poly_t a, b, c; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(C); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); fmpq_poly_randtest(A, state, 1 + n_randint(state, 10), qbits1); fmpq_poly_randtest(B, state, 1 + n_randint(state, 10), qbits2); fmpq_poly_sub(C, A, B); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_set_fmpq_poly(b, B, rbits2); arb_poly_sub(c, a, b, rbits3); if (!arb_poly_contains_fmpq_poly(c, C)) { flint_printf("FAIL\n\n"); flint_printf("bits3 = %wd\n", rbits3); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_poly_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(C); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-sub_series.c000066400000000000000000000042761461254215100207710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_sub_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b, c, d; slong len, prec; arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10); arb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10); arb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10); arb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10); prec = 2 + n_randint(state, 100); len = n_randint(state, 10); arb_poly_sub_series(c, a, b, len, prec); arb_poly_sub(d, a, b, prec); arb_poly_truncate(d, len); if (!arb_poly_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_set(d, a); arb_poly_sub_series(d, d, b, len, prec); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } arb_poly_set(d, b); arb_poly_sub_series(d, a, d, len, prec); if (!arb_poly_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-swinnerton_dyer_ui.c000066400000000000000000000036731461254215100225540ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_swinnerton_dyer_ui, state) { slong iter; for (iter = 0; iter < 50 * 0.1 * flint_test_multiplier(); iter++) { arb_poly_t a, b; arb_t x, y; fmpz_poly_t c; slong i, n, prec; arb_poly_init(a); arb_poly_init(b); fmpz_poly_init(c); arb_init(x); arb_init(y); n = n_randint(state, 10); arb_poly_swinnerton_dyer_ui(a, n, 0); prec = 2 + n_randint(state, 10000); if (!arb_poly_get_unique_fmpz_poly(c, a)) { flint_printf("FAIL (uniqueness)\n\n"); flint_abort(); } arb_poly_set_fmpz_poly(b, c, prec); arb_zero(x); for (i = 0; i < n; i++) { arb_sqrt_ui(y, n_nth_prime(i + 1), prec); if (n_randint(state, 2)) arb_add(x, x, y, prec); else arb_sub(x, x, y, prec); } arb_poly_evaluate(y, b, x, prec); if (!arb_contains_zero(y)) { flint_printf("FAIL (containment)\n\n"); flint_abort(); } arb_poly_swinnerton_dyer_ui(b, n, 2 + n_randint(state, 1000)); if (!arb_poly_overlaps(a, b)) { flint_printf("FAIL (overlap)\n\n"); flint_abort(); } arb_poly_clear(a); arb_poly_clear(b); fmpz_poly_clear(c); arb_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-tan_series.c000066400000000000000000000047241461254215100207600ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_tan_series, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, qbits, rbits1, rbits2; fmpq_poly_t A; arb_poly_t a, b, c, d, e; qbits = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); m = 1 + n_randint(state, 50); n = 1 + n_randint(state, 50); fmpq_poly_init(A); arb_poly_init(a); arb_poly_init(b); arb_poly_init(c); arb_poly_init(d); arb_poly_init(e); fmpq_poly_randtest(A, state, m, qbits); arb_poly_set_fmpq_poly(a, A, rbits1); arb_poly_randtest(b, state, 1 + n_randint(state, 50), rbits1, 5); arb_poly_tan_series(b, a, n, rbits2); /* check tan(x) = 2*tan(x/2)/(1-tan(x/2)^2) */ arb_poly_scalar_mul_2exp_si(c, a, -1); arb_poly_tan_series(c, c, n, rbits2); arb_poly_mullow(d, c, c, n, rbits2); arb_poly_one(e); arb_poly_sub(e, e, d, rbits2); arb_poly_div_series(c, c, e, n, rbits2); arb_poly_scalar_mul_2exp_si(c, c, 1); if (!arb_poly_overlaps(b, c)) { flint_printf("FAIL\n\n"); flint_printf("bits2 = %wd\n", rbits2); flint_printf("A = "); fmpq_poly_print(A); flint_printf("\n\n"); flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_tan_series(a, a, n, rbits2); if (!arb_poly_equal(a, b)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } fmpq_poly_clear(A); arb_poly_clear(a); arb_poly_clear(b); arb_poly_clear(c); arb_poly_clear(d); arb_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-taylor_shift.c000066400000000000000000000043031461254215100213240ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_taylor_shift, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { slong prec1, prec2; arb_poly_t f, g; arb_t c, d, e; prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); arb_poly_init(f); arb_poly_init(g); arb_init(c); arb_init(d); arb_init(e); arb_poly_randtest(f, state, 1 + n_randint(state, 40), 1 + n_randint(state, 500), 10); arb_poly_randtest(g, state, 1 + n_randint(state, 20), 1 + n_randint(state, 500), 10); if (n_randint(state, 2)) arb_set_si(c, n_randint(state, 5) - 2); else arb_randtest(c, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); if (n_randint(state, 2)) arb_set_si(d, n_randint(state, 5) - 2); else arb_randtest(d, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); arb_add(e, c, d, prec1); /* check f(x+c)(x+d) = f(x+c+d) */ arb_poly_taylor_shift(g, f, e, prec2); arb_poly_taylor_shift(f, f, c, prec1); arb_poly_taylor_shift(f, f, d, prec1); if (!arb_poly_overlaps(f, g)) { flint_printf("FAIL\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); arb_printd(d, 15); flint_printf("\n\n"); flint_printf("f = "); arb_poly_printd(f, 15); flint_printf("\n\n"); flint_printf("g = "); arb_poly_printd(g, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_clear(f); arb_poly_clear(g); arb_clear(c); arb_clear(d); arb_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/test/t-zeta_series.c000066400000000000000000000066261461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_poly.h" TEST_FUNCTION_START(arb_poly_zeta_series, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { slong m, n1, n2, bits1, bits2, bits3; int deflate; arb_poly_t S, A, B, C, D, E, F; arb_t a, a1; bits1 = 2 + n_randint(state, 300); bits2 = 2 + n_randint(state, 300); bits3 = 2 + n_randint(state, 300); m = 1 + n_randint(state, 30); n1 = 1 + n_randint(state, 30); n2 = 1 + n_randint(state, 30); arb_poly_init(S); arb_poly_init(A); arb_poly_init(B); arb_poly_init(C); arb_poly_init(D); arb_poly_init(E); arb_poly_init(F); arb_init(a); arb_init(a1); deflate = n_randint(state, 2); arb_poly_randtest(S, state, m, bits1, 3); arb_randtest_precise(a, state, bits1, 3); arb_poly_set_coeff_arb(S, 0, a); if (n_randint(state, 2)) arb_randtest(a, state, bits1, 3); else arb_one(a); arb_poly_zeta_series(A, S, a, deflate, n1, bits2); arb_poly_zeta_series(B, S, a, deflate, n2, bits3); arb_poly_set(C, A); arb_poly_truncate(C, FLINT_MIN(n1, n2)); arb_poly_truncate(B, FLINT_MIN(n1, n2)); if (!arb_poly_overlaps(B, C)) { flint_printf("FAIL\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("A = "); arb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("B = "); arb_poly_printd(B, 15); flint_printf("\n\n"); flint_abort(); } /* check zeta(s,a) = zeta(s,a+1) + a^(-s) */ arb_poly_set_arb(D, a); arb_poly_log_series(D, D, n1, bits2); arb_poly_mullow(D, D, S, n1, bits2); arb_poly_neg(D, D); arb_poly_exp_series(D, D, n1, bits2); arb_add_ui(a1, a, 1, bits2); arb_poly_zeta_series(E, S, a1, deflate, n1, bits2); arb_poly_add(E, E, D, bits2); if (!arb_poly_overlaps(A, E)) { flint_printf("FAIL (functional equation)\n\n"); flint_printf("S = "); arb_poly_printd(S, 15); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("A = "); arb_poly_printd(A, 15); flint_printf("\n\n"); flint_printf("E = "); arb_poly_printd(A, 15); flint_printf("\n\n"); flint_abort(); } arb_poly_zeta_series(S, S, a, deflate, n1, bits2); if (!arb_poly_overlaps(A, S)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arb_poly_clear(S); arb_poly_clear(A); arb_poly_clear(B); arb_poly_clear(C); arb_poly_clear(D); arb_poly_clear(E); arb_poly_clear(F); arb_clear(a); arb_clear(a1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arb_poly/tree.c000066400000000000000000000047671461254215100163520ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" arb_ptr * _arb_poly_tree_alloc(slong len) { arb_ptr * tree = NULL; if (len) { slong i, height = FLINT_CLOG2(len); tree = flint_malloc(sizeof(arb_ptr) * (height + 1)); for (i = 0; i <= height; i++) tree[i] = _arb_vec_init(len + (len >> i) + 1); } return tree; } void _arb_poly_tree_free(arb_ptr * tree, slong len) { if (len) { slong i, height = FLINT_CLOG2(len); for (i = 0; i <= height; i++) _arb_vec_clear(tree[i], len + (len >> i) + 1); flint_free(tree); } } void _arb_poly_tree_build(arb_ptr * tree, arb_srcptr roots, slong len, slong prec) { slong height, pow, left, i; arb_ptr pa, pb; arb_srcptr a, b; if (len == 0) return; height = FLINT_CLOG2(len); /* zeroth level, (x-a) */ for (i = 0; i < len; i++) { arb_one(tree[0] + (2 * i + 1)); arb_neg(tree[0] + (2 * i), roots + i); } /* first level, (x-a)(x-b) = x^2 + (-a-b)*x + a*b */ if (height > 1) { pa = tree[1]; for (i = 0; i < len / 2; i++) { a = (arb_srcptr) (roots + (2 * i)); b = (arb_srcptr) (roots + (2 * i + 1)); arb_mul(pa + (3 * i), a, b, prec); arb_add(pa + (3 * i + 1), a, b, prec); arb_neg(pa + (3 * i + 1), pa + (3 * i + 1)); arb_one(pa + (3 * i + 2)); } if (len & 1) { arb_neg(pa + (3 * (len / 2)), roots + len - 1); arb_one(pa + (3 * (len / 2) + 1)); } } for (i = 1; i < height - 1; i++) { left = len; pow = WORD(1) << i; pa = tree[i]; pb = tree[i + 1]; while (left >= 2 * pow) { _arb_poly_mul_monic(pb, pa, pow + 1, pa + pow + 1, pow + 1, prec); left -= 2 * pow; pa += 2 * pow + 2; pb += 2 * pow + 1; } if (left > pow) { _arb_poly_mul_monic(pb, pa, pow + 1, pa + pow + 1, left - pow + 1, prec); } else if (left > 0) _arb_vec_set(pb, pa, left + 1); } } flint-3.1.3/src/arb_poly/valuation.c000066400000000000000000000011341461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" slong arb_poly_valuation(const arb_poly_t poly) { slong i, len = poly->length; for (i = 0; i < len; i++) if (!arb_is_zero(poly->coeffs + i)) return i; return -1; } flint-3.1.3/src/arb_poly/zeta_series.c000066400000000000000000000106141461254215100177140ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "acb_poly.h" /* series of c^(d+x) */ static inline void _arb_poly_pow_cpx(arb_ptr res, const arb_t c, const arb_t d, slong trunc, slong prec) { slong i; arb_t logc; arb_init(logc); arb_log(logc, c, prec); arb_mul(res + 0, logc, d, prec); arb_exp(res + 0, res + 0, prec); for (i = 1; i < trunc; i++) { arb_mul(res + i, res + i - 1, logc, prec); arb_div_ui(res + i, res + i, i, prec); } arb_clear(logc); } void _arb_poly_zeta_series(arb_ptr res, arb_srcptr h, slong hlen, const arb_t a, int deflate, slong len, slong prec) { slong i; acb_t cs, ca; acb_ptr z; arb_ptr t, u; if (arb_contains_nonpositive(a)) { _arb_vec_indeterminate(res, len); return; } hlen = FLINT_MIN(hlen, len); z = _acb_vec_init(len); t = _arb_vec_init(len); u = _arb_vec_init(len); acb_init(cs); acb_init(ca); /* use reflection formula */ if (arf_sgn(arb_midref(h)) < 0 && arb_is_one(a)) { /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */ arb_t pi; arb_ptr f, s1, s2, s3, s4; arb_init(pi); f = _arb_vec_init(2); s1 = _arb_vec_init(len); s2 = _arb_vec_init(len); s3 = _arb_vec_init(len); s4 = _arb_vec_init(len); arb_const_pi(pi, prec); /* s1 = (2*pi)**s */ arb_mul_2exp_si(pi, pi, 1); _arb_poly_pow_cpx(s1, pi, h, len, prec); arb_mul_2exp_si(pi, pi, -1); /* s2 = sin(pi*s/2) / pi */ arb_set(f, h); arb_one(f + 1); arb_mul_2exp_si(f, f, -1); arb_mul_2exp_si(f + 1, f + 1, -1); _arb_poly_sin_pi_series(s2, f, 2, len, prec); _arb_vec_scalar_div(s2, s2, len, pi, prec); /* s3 = gamma(1-s) */ arb_sub_ui(f, h, 1, prec); arb_neg(f, f); arb_set_si(f + 1, -1); _arb_poly_gamma_series(s3, f, 2, len, prec); /* s4 = zeta(1-s) */ arb_sub_ui(f, h, 1, prec); arb_neg(f, f); acb_set_arb(cs, f); acb_one(ca); _acb_poly_zeta_cpx_series(z, cs, ca, 0, len, prec); for (i = 0; i < len; i++) arb_set(s4 + i, acb_realref(z + i)); for (i = 1; i < len; i += 2) arb_neg(s4 + i, s4 + i); _arb_poly_mullow(u, s1, len, s2, len, len, prec); _arb_poly_mullow(s1, s3, len, s4, len, len, prec); _arb_poly_mullow(t, u, len, s1, len, len, prec); /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */ if (deflate) { arb_sub_ui(u, h, 1, prec); arb_neg(u, u); arb_inv(u, u, prec); for (i = 1; i < len; i++) arb_mul(u + i, u + i - 1, u, prec); _arb_vec_add(t, t, u, len, prec); } arb_clear(pi); _arb_vec_clear(f, 2); _arb_vec_clear(s1, len); _arb_vec_clear(s2, len); _arb_vec_clear(s3, len); _arb_vec_clear(s4, len); } else { acb_set_arb(cs, h); acb_set_arb(ca, a); _acb_poly_zeta_cpx_series(z, cs, ca, deflate, len, prec); for (i = 0; i < len; i++) arb_set(t + i, acb_realref(z + i)); } /* compose with nonconstant part */ arb_zero(u); _arb_vec_set(u + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, t, len, u, hlen, len, prec); _acb_vec_clear(z, len); _arb_vec_clear(t, len); _arb_vec_clear(u, len); acb_clear(cs); acb_clear(ca); } void arb_poly_zeta_series(arb_poly_t res, const arb_poly_t f, const arb_t a, int deflate, slong n, slong prec) { if (n == 0) { arb_poly_zero(res); return; } arb_poly_fit_length(res, n); if (f->length == 0) { arb_t t; arb_init(t); _arb_poly_zeta_series(res->coeffs, t, 1, a, deflate, n, prec); arb_clear(t); } else { _arb_poly_zeta_series(res->coeffs, f->coeffs, f->length, a, deflate, n, prec); } _arb_poly_set_length(res, n); _arb_poly_normalise(res); } flint-3.1.3/src/arb_types.h000066400000000000000000000021731461254215100155660ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARB_TYPES_H #define ARB_TYPES_H #include "arf_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz exp; mp_limb_t man; } mag_struct; typedef mag_struct mag_t[1]; typedef mag_struct * mag_ptr; typedef const mag_struct * mag_srcptr; typedef struct { arf_struct mid; mag_struct rad; } arb_struct; typedef arb_struct arb_t[1]; typedef arb_struct * arb_ptr; typedef const arb_struct * arb_srcptr; typedef struct { arb_ptr entries; slong r; slong c; arb_ptr * rows; } arb_mat_struct; typedef arb_mat_struct arb_mat_t[1]; typedef struct { arb_ptr coeffs; slong alloc; slong length; } arb_poly_struct; typedef arb_poly_struct arb_poly_t[1]; #ifdef __cplusplus } #endif #endif /* ARB_TYPES_H */ flint-3.1.3/src/arf.h000066400000000000000000000707221461254215100143530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARF_H #define ARF_H #ifdef ARF_INLINES_C #define ARF_INLINE #else #define ARF_INLINE static inline #endif #include "mag.h" #include "arf_types.h" #ifdef __cplusplus extern "C" { #endif typedef enum { ARF_RND_DOWN = 0, ARF_RND_UP = 1, ARF_RND_FLOOR = 2, ARF_RND_CEIL = 3, ARF_RND_NEAR = 4 } arf_rnd_t; ARF_INLINE int arf_rounds_down(arf_rnd_t rnd, int sgnbit) { if (rnd == ARF_RND_DOWN) return 1; if (rnd == ARF_RND_UP) return 0; if (rnd == ARF_RND_FLOOR) return !sgnbit; return sgnbit; } ARF_INLINE int arf_rounds_up(arf_rnd_t rnd, int sgnbit) { if (rnd == ARF_RND_DOWN) return 0; if (rnd == ARF_RND_UP) return 1; if (rnd == ARF_RND_FLOOR) return sgnbit; return !sgnbit; } #ifdef __MPFR_H ARF_INLINE mpfr_rnd_t arf_rnd_to_mpfr(arf_rnd_t rnd) { if (rnd == ARF_RND_DOWN) return MPFR_RNDZ; else if (rnd == ARF_RND_UP) return MPFR_RNDA; else if (rnd == ARF_RND_FLOOR) return MPFR_RNDD; else if (rnd == ARF_RND_CEIL) return MPFR_RNDU; else return MPFR_RNDN; } #endif /* Allow 'infinite' precision for operations where a result can be computed exactly. */ #define ARF_PREC_EXACT WORD_MAX #define ARF_PREC_ADD(prec,extra) ((prec) == ARF_PREC_EXACT ? ARF_PREC_EXACT : (prec) + (extra)) #define ARF_RESULT_EXACT 0 #define ARF_RESULT_INEXACT 1 /* Range where we can skip fmpz overflow checks for exponent manipulation. */ #define ARF_MAX_LAGOM_EXP MAG_MAX_LAGOM_EXP #define ARF_MIN_LAGOM_EXP MAG_MIN_LAGOM_EXP /* Exponent values used to encode special values. */ #define ARF_EXP_ZERO 0 #define ARF_EXP_NAN COEFF_MIN #define ARF_EXP_POS_INF (COEFF_MIN+1) #define ARF_EXP_NEG_INF (COEFF_MIN+2) /* Direct access to the exponent. */ #define ARF_EXP(x) ((x)->exp) #define ARF_EXPREF(x) (&(x)->exp) /* Finite and with lagom big exponents. */ #define ARF_IS_LAGOM(x) (ARF_EXP(x) >= ARF_MIN_LAGOM_EXP && \ ARF_EXP(x) <= ARF_MAX_LAGOM_EXP) /* More than two limbs (needs pointer). */ #define ARF_HAS_PTR(x) ((x)->size > ((2 << 1) + 1)) /* Raw size field (encodes both limb size and sign). */ #define ARF_XSIZE(x) ((x)->size) /* Construct size field value from size in limbs and sign bit. */ #define ARF_MAKE_XSIZE(size, sgnbit) ((((mp_size_t) size) << 1) | (sgnbit)) /* The limb size, and the sign bit. */ #define ARF_SIZE(x) (ARF_XSIZE(x) >> 1) #define ARF_SGNBIT(x) (ARF_XSIZE(x) & 1) /* Assumes non-special value */ #define ARF_NEG(x) (ARF_XSIZE(x) ^= 1) /* Direct access to the limb data. */ #define ARF_NOPTR_D(x) ((x)->d.noptr.d) #define ARF_PTR_D(x) ((x)->d.ptr.d) #define ARF_PTR_ALLOC(x) ((x)->d.ptr.alloc) /* Encoding for special values. */ #define ARF_IS_SPECIAL(x) (ARF_XSIZE(x) == 0) /* Value is +/- a power of two */ #define ARF_IS_POW2(x) (ARF_SIZE(x) == 1) && (ARF_NOPTR_D(x)[0] == LIMB_TOP) /* To set a special value, first call this and then set the exponent. */ #define ARF_MAKE_SPECIAL(x) \ do { \ fmpz_clear(ARF_EXPREF(x)); \ ARF_DEMOTE(x); \ ARF_XSIZE(x) = 0; \ } while (0) void _arf_promote(arf_t x, mp_size_t n); void _arf_demote(arf_t x); /* Warning: does not set size! -- also doesn't demote exponent. */ #define ARF_DEMOTE(x) \ do { \ if (ARF_HAS_PTR(x)) \ _arf_demote(x); \ } while (0) /* Get mpn pointer and size (xptr, xn) for read-only use. */ #define ARF_GET_MPN_READONLY(xptr, xn, x) \ do { \ xn = ARF_SIZE(x); \ if (xn <= ARF_NOPTR_LIMBS) \ xptr = ARF_NOPTR_D(x); \ else \ xptr = ARF_PTR_D(x); \ } while (0) /* Assumes non-special! */ #define ARF_GET_TOP_LIMB(lmb, x) \ do { \ mp_srcptr __xptr; \ mp_size_t __xn; \ ARF_GET_MPN_READONLY(__xptr, __xn, (x)); \ (lmb) = __xptr[__xn - 1]; \ } while (0) /* Get mpn pointer xptr for writing *exactly* xn limbs to x. */ #define ARF_GET_MPN_WRITE(xptr, xn, x) \ do { \ mp_size_t __xn = (xn); \ if ((__xn) <= ARF_NOPTR_LIMBS) \ { \ ARF_DEMOTE(x); \ xptr = ARF_NOPTR_D(x); \ } \ else \ { \ if (!ARF_HAS_PTR(x)) \ { \ _arf_promote(x, __xn); \ } \ else if (ARF_PTR_ALLOC(x) < (__xn)) \ { \ ARF_PTR_D(x) = (mp_ptr) \ flint_realloc(ARF_PTR_D(x), \ (xn) * sizeof(mp_limb_t)); \ ARF_PTR_ALLOC(x) = (__xn); \ } \ xptr = ARF_PTR_D(x); \ } \ ARF_XSIZE(x) = ARF_MAKE_XSIZE(__xn, 0); \ } while (0) ARF_INLINE void arf_init(arf_t x) { fmpz_init(ARF_EXPREF(x)); ARF_XSIZE(x) = 0; } void arf_clear(arf_t x); arf_ptr _arf_vec_init(slong n); void _arf_vec_clear(arf_ptr v, slong n); ARF_INLINE void arf_zero(arf_t x) { ARF_MAKE_SPECIAL(x); ARF_EXP(x) = ARF_EXP_ZERO; } ARF_INLINE void arf_pos_inf(arf_t x) { ARF_MAKE_SPECIAL(x); ARF_EXP(x) = ARF_EXP_POS_INF; } ARF_INLINE void arf_neg_inf(arf_t x) { ARF_MAKE_SPECIAL(x); ARF_EXP(x) = ARF_EXP_NEG_INF; } ARF_INLINE void arf_nan(arf_t x) { ARF_MAKE_SPECIAL(x); ARF_EXP(x) = ARF_EXP_NAN; } ARF_INLINE int arf_is_special(const arf_t x) { return ARF_IS_SPECIAL(x); } ARF_INLINE int arf_is_zero(const arf_t x) { return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_ZERO); } ARF_INLINE int arf_is_pos_inf(const arf_t x) { return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_POS_INF); } ARF_INLINE int arf_is_neg_inf(const arf_t x) { return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_NEG_INF); } ARF_INLINE int arf_is_nan(const arf_t x) { return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_NAN); } ARF_INLINE int arf_is_normal(const arf_t x) { return !ARF_IS_SPECIAL(x); } ARF_INLINE int arf_is_finite(const arf_t x) { return !ARF_IS_SPECIAL(x) || (ARF_EXP(x) == ARF_EXP_ZERO); } ARF_INLINE int arf_is_inf(const arf_t x) { return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_POS_INF || ARF_EXP(x) == ARF_EXP_NEG_INF); } ARF_INLINE void arf_one(arf_t x) { fmpz_clear(ARF_EXPREF(x)); ARF_DEMOTE(x); ARF_EXP(x) = 1; ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0); ARF_NOPTR_D(x)[0] = LIMB_TOP; } ARF_INLINE int arf_is_one(const arf_t x) { return (ARF_EXP(x) == 1) && (ARF_XSIZE(x) == ARF_MAKE_XSIZE(1, 0)) && ARF_NOPTR_D(x)[0] == LIMB_TOP; } ARF_INLINE int arf_sgn(const arf_t x) { if (arf_is_special(x)) { if (arf_is_zero(x) || arf_is_nan(x)) return 0; return arf_is_pos_inf(x) ? 1 : -1; } else { return ARF_SGNBIT(x) ? -1 : 1; } } int arf_cmp(const arf_t x, const arf_t y); int arf_cmpabs(const arf_t x, const arf_t y); int arf_cmpabs_ui(const arf_t x, ulong y); int arf_cmpabs_d(const arf_t x, double y); int arf_cmp_si(const arf_t x, slong y); int arf_cmp_ui(const arf_t x, ulong y); int arf_cmp_d(const arf_t x, double y); ARF_INLINE void arf_swap(arf_t y, arf_t x) { FLINT_SWAP(arf_struct, *x, *y); } void arf_set(arf_t y, const arf_t x); ARF_INLINE void arf_neg(arf_t y, const arf_t x) { arf_set(y, x); if (arf_is_special(y)) { if (arf_is_pos_inf(y)) arf_neg_inf(y); else if (arf_is_neg_inf(y)) arf_pos_inf(y); } else { ARF_NEG(y); } } ARF_INLINE void arf_init_set_ui(arf_t x, ulong v) { if (v == 0) { ARF_EXP(x) = ARF_EXP_ZERO; ARF_XSIZE(x) = 0; } else { unsigned int c; c = flint_clz(v); ARF_EXP(x) = FLINT_BITS - c; ARF_NOPTR_D(x)[0] = v << c; ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0); } } /* FLINT_ABS is unsafe for x = WORD_MIN */ #define UI_ABS_SI(x) (((slong)(x) < 0) ? (-(ulong)(x)) : ((ulong)(x))) ARF_INLINE void arf_init_set_si(arf_t x, slong v) { arf_init_set_ui(x, UI_ABS_SI(v)); if (v < 0) ARF_NEG(x); } ARF_INLINE void arf_set_ui(arf_t x, ulong v) { ARF_DEMOTE(x); _fmpz_demote(ARF_EXPREF(x)); if (v == 0) { ARF_EXP(x) = ARF_EXP_ZERO; ARF_XSIZE(x) = 0; } else { unsigned int c; c = flint_clz(v); ARF_EXP(x) = FLINT_BITS - c; ARF_NOPTR_D(x)[0] = v << c; ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0); } } ARF_INLINE void arf_set_si(arf_t x, slong v) { arf_set_ui(x, UI_ABS_SI(v)); if (v < 0) ARF_NEG(x); } ARF_INLINE void arf_init_set_shallow(arf_t z, const arf_t x) { *z = *x; } ARF_INLINE void arf_init_neg_shallow(arf_t z, const arf_t x) { *z = *x; arf_neg(z, z); } ARF_INLINE void arf_init_set_mag_shallow(arf_t y, const mag_t x) { mp_limb_t t = MAG_MAN(x); ARF_XSIZE(y) = ARF_MAKE_XSIZE(t != 0, 0); ARF_EXP(y) = MAG_EXP(x); ARF_NOPTR_D(y)[0] = t << (FLINT_BITS - MAG_BITS); } ARF_INLINE void arf_init_neg_mag_shallow(arf_t z, const mag_t x) { arf_init_set_mag_shallow(z, x); arf_neg(z, z); } ARF_INLINE int arf_cmpabs_mag(const arf_t x, const mag_t y) { arf_t t; arf_init_set_mag_shallow(t, y); /* no need to free */ return arf_cmpabs(x, t); } ARF_INLINE int arf_mag_cmpabs(const mag_t x, const arf_t y) { arf_t t; arf_init_set_mag_shallow(t, x); /* no need to free */ return arf_cmpabs(t, y); } /* Assumes xn > 0, x[xn-1] != 0. */ /* TBD: 1, 2 limb versions */ void arf_set_mpn(arf_t y, mp_srcptr x, mp_size_t xn, int sgnbit); ARF_INLINE void arf_set_mpz(arf_t y, const mpz_t x) { slong size = x->_mp_size; if (size == 0) arf_zero(y); else arf_set_mpn(y, x->_mp_d, FLINT_ABS(size), size < 0); } ARF_INLINE void arf_set_fmpz(arf_t y, const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) arf_set_si(y, *x); else arf_set_mpz(y, COEFF_TO_PTR(*x)); } int _arf_set_round_ui(arf_t x, ulong v, int sgnbit, slong prec, arf_rnd_t rnd); int _arf_set_round_uiui(arf_t z, slong * fix, mp_limb_t hi, mp_limb_t lo, int sgnbit, slong prec, arf_rnd_t rnd); int _arf_set_round_mpn(arf_t y, slong * exp_shift, mp_srcptr x, mp_size_t xn, int sgnbit, slong prec, arf_rnd_t rnd); ARF_INLINE int arf_set_round_ui(arf_t x, ulong v, slong prec, arf_rnd_t rnd) { return _arf_set_round_ui(x, v, 0, prec, rnd); } ARF_INLINE int arf_set_round_si(arf_t x, slong v, slong prec, arf_rnd_t rnd) { return _arf_set_round_ui(x, UI_ABS_SI(v), v < 0, prec, rnd); } ARF_INLINE int arf_set_round_mpz(arf_t y, const mpz_t x, slong prec, arf_rnd_t rnd) { int inexact; slong size = x->_mp_size; slong fix; if (size == 0) { arf_zero(y); return 0; } inexact = _arf_set_round_mpn(y, &fix, x->_mp_d, FLINT_ABS(size), (size < 0), prec, rnd); _fmpz_demote(ARF_EXPREF(y)); ARF_EXP(y) = FLINT_ABS(size) * FLINT_BITS + fix; return inexact; } ARF_INLINE int arf_set_round_fmpz(arf_t y, const fmpz_t x, slong prec, arf_rnd_t rnd) { if (!COEFF_IS_MPZ(*x)) return arf_set_round_si(y, *x, prec, rnd); else return arf_set_round_mpz(y, COEFF_TO_PTR(*x), prec, rnd); } int arf_set_round(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd); int arf_neg_round(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd); #ifdef __MPFR_H int arf_get_mpfr(mpfr_t x, const arf_t y, mpfr_rnd_t rnd); void arf_set_mpfr(arf_t x, const mpfr_t y); int _arf_call_mpfr_func(arf_ptr r1, arf_ptr r2, int (*func)(void), arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd); #endif int arf_equal(const arf_t x, const arf_t y); int arf_equal_si(const arf_t x, slong y); int arf_equal_ui(const arf_t x, ulong y); int arf_equal_d(const arf_t x, double y); ARF_INLINE void arf_min(arf_t z, const arf_t a, const arf_t b) { if (arf_cmp(a, b) <= 0) arf_set(z, a); else arf_set(z, b); } ARF_INLINE void arf_max(arf_t z, const arf_t a, const arf_t b) { if (arf_cmp(a, b) > 0) arf_set(z, a); else arf_set(z, b); } ARF_INLINE void arf_abs(arf_t y, const arf_t x) { if (arf_sgn(x) < 0) arf_neg(y, x); else arf_set(y, x); } ARF_INLINE slong arf_bits(const arf_t x) { if (arf_is_special(x)) return 0; else { mp_srcptr xp; mp_size_t xn; slong c; ARF_GET_MPN_READONLY(xp, xn, x); c = flint_ctz(xp[0]); return xn * FLINT_BITS - c; } } ARF_INLINE void arf_bot(fmpz_t e, const arf_t x) { if (arf_is_special(x)) fmpz_zero(e); else fmpz_sub_si(e, ARF_EXPREF(x), arf_bits(x)); } int arf_is_int(const arf_t x); int arf_is_int_2exp_si(const arf_t x, slong e); int arf_cmp_2exp_si(const arf_t x, slong e); int arf_cmpabs_2exp_si(const arf_t x, slong e); ARF_INLINE void arf_set_si_2exp_si(arf_t x, slong man, slong exp) { arf_set_si(x, man); if (man != 0) fmpz_add_si_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp); } ARF_INLINE void arf_set_ui_2exp_si(arf_t x, ulong man, slong exp) { arf_set_ui(x, man); if (man != 0) fmpz_add_si_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp); } ARF_INLINE void arf_mul_2exp_si(arf_t y, const arf_t x, slong e) { arf_set(y, x); if (!arf_is_special(y)) fmpz_add_si_inline(ARF_EXPREF(y), ARF_EXPREF(y), e); } ARF_INLINE void arf_mul_2exp_fmpz(arf_t y, const arf_t x, const fmpz_t e) { arf_set(y, x); if (!arf_is_special(y)) fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), e); } ARF_INLINE int arf_set_round_fmpz_2exp(arf_t y, const fmpz_t x, const fmpz_t exp, slong prec, arf_rnd_t rnd) { if (fmpz_is_zero(x)) { arf_zero(y); return 0; } else { int r = arf_set_round_fmpz(y, x, prec, rnd); fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), exp); return r; } } ARF_INLINE void arf_abs_bound_lt_2exp_fmpz(fmpz_t b, const arf_t x) { if (arf_is_special(x)) fmpz_zero(b); else fmpz_set(b, ARF_EXPREF(x)); } ARF_INLINE void arf_abs_bound_le_2exp_fmpz(fmpz_t b, const arf_t x) { if (arf_is_special(x)) fmpz_zero(b); else if (ARF_IS_POW2(x)) fmpz_sub_ui(b, ARF_EXPREF(x), 1); else fmpz_set(b, ARF_EXPREF(x)); } slong arf_abs_bound_lt_2exp_si(const arf_t x); void arf_frexp(arf_t man, fmpz_t exp, const arf_t x); void arf_get_fmpz_2exp(fmpz_t man, fmpz_t exp, const arf_t x); int _arf_get_integer_mpn(mp_ptr y, mp_srcptr x, mp_size_t xn, slong exp); int _arf_set_mpn_fixed(arf_t z, mp_srcptr xp, mp_size_t xn, mp_size_t fixn, int negative, slong prec, arf_rnd_t rnd); int arf_get_fmpz(fmpz_t z, const arf_t x, arf_rnd_t rnd); slong arf_get_si(const arf_t x, arf_rnd_t rnd); int arf_get_fmpz_fixed_fmpz(fmpz_t y, const arf_t x, const fmpz_t e); int arf_get_fmpz_fixed_si(fmpz_t y, const arf_t x, slong e); ARF_INLINE void arf_set_fmpz_2exp(arf_t x, const fmpz_t man, const fmpz_t exp) { arf_set_fmpz(x, man); if (!arf_is_zero(x)) fmpz_add_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp); } void arf_floor(arf_t z, const arf_t x); void arf_ceil(arf_t z, const arf_t x); void arf_debug(const arf_t x); char * arf_get_str(const arf_t x, slong d); #ifdef FLINT_HAVE_FILE void arf_fprint(FILE * file, const arf_t x); void arf_fprintd(FILE * file, const arf_t y, slong d); #endif void arf_print(const arf_t x); void arf_printd(const arf_t y, slong d); void arf_randtest(arf_t x, flint_rand_t state, slong bits, slong mag_bits); void arf_randtest_not_zero(arf_t x, flint_rand_t state, slong bits, slong mag_bits); void arf_randtest_special(arf_t x, flint_rand_t state, slong bits, slong mag_bits); void arf_urandom(arf_t x, flint_rand_t state, slong bits, arf_rnd_t rnd); #define MUL_MPFR_MIN_LIMBS 25 #ifdef FLINT_HAVE_FFT_SMALL #define MUL_MPFR_MAX_LIMBS 800 #else #define MUL_MPFR_MAX_LIMBS 10000 #endif #define ARF_MUL_STACK_ALLOC 40 #define ARF_MUL_TLS_ALLOC 1000 extern FLINT_TLS_PREFIX mp_ptr __arf_mul_tmp; extern FLINT_TLS_PREFIX slong __arf_mul_alloc; extern void _arf_mul_tmp_cleanup(void); #define ARF_MUL_TMP_DECL \ mp_limb_t tmp_stack[ARF_MUL_STACK_ALLOC]; \ #define ARF_MUL_TMP_ALLOC(tmp, alloc) \ if (alloc <= ARF_MUL_STACK_ALLOC) \ { \ tmp = tmp_stack; \ } \ else if (alloc <= ARF_MUL_TLS_ALLOC) \ { \ if (__arf_mul_alloc < alloc) \ { \ if (__arf_mul_alloc == 0) \ { \ flint_register_cleanup_function(_arf_mul_tmp_cleanup); \ } \ __arf_mul_tmp = flint_realloc(__arf_mul_tmp, sizeof(mp_limb_t) * alloc); \ __arf_mul_alloc = alloc; \ } \ tmp = __arf_mul_tmp; \ } \ else \ { \ tmp = flint_malloc(sizeof(mp_limb_t) * alloc); \ } #define ARF_MUL_TMP_FREE(tmp, alloc) \ if (alloc > ARF_MUL_TLS_ALLOC) \ flint_free(tmp); void arf_mul_special(arf_t z, const arf_t x, const arf_t y); int arf_mul_via_mpfr(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd); int arf_mul_rnd_any(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd); int arf_mul_rnd_down(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec); #define arf_mul(z, x, y, prec, rnd) \ ((rnd == ARF_RND_DOWN) \ ? arf_mul_rnd_down(z, x, y, prec) \ : arf_mul_rnd_any(z, x, y, prec, rnd)) ARF_INLINE int arf_neg_mul(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { if (arf_is_special(y)) { arf_mul(z, x, y, prec, rnd); arf_neg(z, z); return 0; } else { arf_t t; *t = *y; ARF_NEG(t); return arf_mul(z, x, t, prec, rnd); } } ARF_INLINE int arf_mul_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ return arf_mul(z, x, t, prec, rnd); } ARF_INLINE int arf_mul_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_si(t, y); /* no need to free */ return arf_mul(z, x, t, prec, rnd); } int arf_mul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd); ARF_INLINE int arf_mul_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd) { if (!COEFF_IS_MPZ(*y)) return arf_mul_si(z, x, *y, prec, rnd); else return arf_mul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd); } #define ARF_ADD_STACK_ALLOC 40 #define ARF_ADD_TLS_ALLOC 1000 extern FLINT_TLS_PREFIX mp_ptr __arf_add_tmp; extern FLINT_TLS_PREFIX slong __arf_add_alloc; extern void _arf_add_tmp_cleanup(void); #define ARF_ADD_TMP_DECL \ mp_limb_t tmp_stack[ARF_ADD_STACK_ALLOC]; \ #define ARF_ADD_TMP_ALLOC(tmp, alloc) \ if (alloc <= ARF_ADD_STACK_ALLOC) \ { \ tmp = tmp_stack; \ } \ else if (alloc <= ARF_ADD_TLS_ALLOC) \ { \ if (__arf_add_alloc < alloc) \ { \ if (__arf_add_alloc == 0) \ { \ flint_register_cleanup_function(_arf_add_tmp_cleanup); \ } \ __arf_add_tmp = flint_realloc(__arf_add_tmp, sizeof(mp_limb_t) * alloc); \ __arf_add_alloc = alloc; \ } \ tmp = __arf_add_tmp; \ } \ else \ { \ tmp = flint_malloc(sizeof(mp_limb_t) * alloc); \ } #define ARF_ADD_TMP_FREE(tmp, alloc) \ if (alloc > ARF_ADD_TLS_ALLOC) \ flint_free(tmp); int _arf_add_mpn(arf_t z, mp_srcptr xp, mp_size_t xn, int xsgnbit, const fmpz_t xexp, mp_srcptr yp, mp_size_t yn, int ysgnbit, flint_bitcnt_t shift, slong prec, arf_rnd_t rnd); int arf_add(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd); int arf_add_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd); int arf_add_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd); int arf_add_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd); int arf_add_fmpz_2exp(arf_ptr z, arf_srcptr x, const fmpz_t y, const fmpz_t exp, slong prec, arf_rnd_t rnd); int arf_sub(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd); int arf_sub_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd); int arf_sub_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd); int arf_sub_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd); int arf_addmul(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd); ARF_INLINE int arf_addmul_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ return arf_addmul(z, x, t, prec, rnd); } ARF_INLINE int arf_addmul_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_si(t, y); /* no need to free */ return arf_addmul(z, x, t, prec, rnd); } int arf_addmul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd); ARF_INLINE int arf_addmul_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd) { if (!COEFF_IS_MPZ(*y)) return arf_addmul_si(z, x, *y, prec, rnd); else return arf_addmul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd); } int arf_submul(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd); ARF_INLINE int arf_submul_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ return arf_submul(z, x, t, prec, rnd); } ARF_INLINE int arf_submul_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_si(t, y); /* no need to free */ return arf_submul(z, x, t, prec, rnd); } int arf_submul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd); ARF_INLINE int arf_submul_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd) { if (!COEFF_IS_MPZ(*y)) return arf_submul_si(z, x, *y, prec, rnd); else return arf_submul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd); } int arf_fma(arf_ptr res, arf_srcptr x, arf_srcptr y, arf_srcptr z, slong prec, arf_rnd_t rnd); int arf_sosq(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd); int arf_div(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd); ARF_INLINE int arf_div_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ return arf_div(z, x, t, prec, rnd); } ARF_INLINE int arf_ui_div(arf_ptr z, ulong x, arf_srcptr y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_ui(t, x); /* no need to free */ return arf_div(z, t, y, prec, rnd); } ARF_INLINE int arf_div_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_si(t, y); /* no need to free */ return arf_div(z, x, t, prec, rnd); } ARF_INLINE int arf_si_div(arf_ptr z, slong x, arf_srcptr y, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_si(t, x); /* no need to free */ return arf_div(z, t, y, prec, rnd); } ARF_INLINE int arf_div_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_fmpz(t, y); r = arf_div(z, x, t, prec, rnd); arf_clear(t); return r; } ARF_INLINE int arf_fmpz_div(arf_ptr z, const fmpz_t x, arf_srcptr y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_fmpz(t, x); r = arf_div(z, t, y, prec, rnd); arf_clear(t); return r; } ARF_INLINE int arf_fmpz_div_fmpz(arf_ptr z, const fmpz_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) { arf_t t, u; int r; arf_init(t); arf_init(u); arf_set_fmpz(t, x); arf_set_fmpz(u, y); r = arf_div(z, t, u, prec, rnd); arf_clear(t); arf_clear(u); return r; } int arf_sqrt(arf_ptr z, arf_srcptr x, slong prec, arf_rnd_t rnd); int arf_sqrt_ui(arf_t z, ulong x, slong prec, arf_rnd_t rnd); int arf_sqrt_fmpz(arf_t z, const fmpz_t x, slong prec, arf_rnd_t rnd); int arf_rsqrt(arf_ptr z, arf_srcptr x, slong prec, arf_rnd_t rnd); int arf_root(arf_ptr z, arf_srcptr x, ulong k, slong prec, arf_rnd_t rnd); /* Magnitude bounds */ void arf_get_mag(mag_t y, const arf_t x); void arf_get_mag_lower(mag_t y, const arf_t x); ARF_INLINE void arf_set_mag(arf_t y, const mag_t x) { if (mag_is_zero(x)) { arf_zero(y); } else if (mag_is_inf(x)) { arf_pos_inf(y); } else { _fmpz_set_fast(ARF_EXPREF(y), MAG_EXPREF(x)); ARF_DEMOTE(y); ARF_XSIZE(y) = ARF_MAKE_XSIZE(1, 0); ARF_NOPTR_D(y)[0] = MAG_MAN(x) << (FLINT_BITS - MAG_BITS); } } ARF_INLINE void mag_init_set_arf(mag_t y, const arf_t x) { mag_init(y); arf_get_mag(y, x); } ARF_INLINE void mag_fast_init_set_arf(mag_t y, const arf_t x) { if (ARF_IS_SPECIAL(x)) /* x == 0 */ { mag_fast_zero(y); } else { mp_srcptr xp; mp_size_t xn; ARF_GET_MPN_READONLY(xp, xn, x); MAG_MAN(y) = (xp[xn - 1] >> (FLINT_BITS - MAG_BITS)) + LIMB_ONE; MAG_EXP(y) = ARF_EXP(x); MAG_FAST_ADJUST_ONE_TOO_LARGE(y); } } ARF_INLINE void arf_mag_fast_add_ulp(mag_t z, const mag_t x, const arf_t y, slong prec) { mag_fast_add_2exp_si(z, x, ARF_EXP(y) - prec); } ARF_INLINE void arf_mag_add_ulp(mag_t z, const mag_t x, const arf_t y, slong prec) { if (ARF_IS_SPECIAL(y)) { flint_throw(FLINT_ERROR, "error: ulp error not defined for special value!\n"); } else if (MAG_IS_LAGOM(z) && MAG_IS_LAGOM(x) && ARF_IS_LAGOM(y)) { arf_mag_fast_add_ulp(z, x, y, prec); } else { fmpz_t e; fmpz_init(e); fmpz_sub_ui(e, ARF_EXPREF(y), prec); mag_add_2exp_fmpz(z, x, e); fmpz_clear(e); } } ARF_INLINE void arf_mag_set_ulp(mag_t z, const arf_t y, slong prec) { if (ARF_IS_SPECIAL(y)) { flint_throw(FLINT_ERROR, "error: ulp error not defined for special value!\n"); } else { _fmpz_add_fast(MAG_EXPREF(z), ARF_EXPREF(y), 1 - prec); MAG_MAN(z) = MAG_ONE_HALF; } } void arf_get_fmpq(fmpq_t y, const arf_t x); ARF_INLINE int arf_set_fmpq(arf_t y, const fmpq_t x, slong prec, arf_rnd_t rnd) { return arf_fmpz_div_fmpz(y, fmpq_numref(x), fmpq_denref(x), prec, rnd); } int arf_complex_mul(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d, slong prec, arf_rnd_t rnd); int arf_complex_mul_fallback(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d, slong prec, arf_rnd_t rnd); int arf_complex_sqr(arf_t e, arf_t f, const arf_t a, const arf_t b, slong prec, arf_rnd_t rnd); int arf_sum(arf_t s, arf_srcptr terms, slong len, slong prec, arf_rnd_t rnd); double arf_get_d(const arf_t x, arf_rnd_t rnd); void arf_set_d(arf_t x, double v); ARF_INLINE slong arf_allocated_bytes(const arf_t x) { slong size = fmpz_allocated_bytes(ARF_EXPREF(x)); if (ARF_HAS_PTR(x)) size += ARF_PTR_ALLOC(x) * sizeof(mp_limb_t); return size; } int arf_load_str(arf_t res, const char * data); char * arf_dump_str(const arf_t x); #ifdef FLINT_HAVE_FILE int arf_load_file(arf_t res, FILE *stream); int arf_dump_file(FILE* stream, const arf_t x); #endif void arf_approx_dot(arf_t res, const arf_t initial, int subtract, arf_srcptr x, slong xstep, arf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arf/000077500000000000000000000000001461254215100141725ustar00rootroot00000000000000flint-3.1.3/src/arf/abs_bound_lt_2exp_si.c000066400000000000000000000017341461254215100204270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" slong arf_abs_bound_lt_2exp_si(const arf_t x) { slong res; if (arf_is_special(x)) { if (arf_is_zero(x)) return -ARF_PREC_EXACT; else return ARF_PREC_EXACT; } if (!COEFF_IS_MPZ(ARF_EXP(x))) return ARF_EXP(x); if (fmpz_fits_si(ARF_EXPREF(x))) res = fmpz_get_si(ARF_EXPREF(x)); else res = fmpz_sgn(ARF_EXPREF(x)) < 0 ? -ARF_PREC_EXACT : ARF_PREC_EXACT; if (res < -ARF_PREC_EXACT) res = -ARF_PREC_EXACT; if (res > ARF_PREC_EXACT) res = ARF_PREC_EXACT; return res; } flint-3.1.3/src/arf/add.c000066400000000000000000000136511461254215100150740ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_add_special(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { if (arf_is_zero(x)) { if (arf_is_zero(y)) { arf_zero(z); return 0; } else return arf_set_round(z, y, prec, rnd); } else if (arf_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_nan(x) || arf_is_nan(y) || (arf_is_pos_inf(x) && arf_is_neg_inf(y)) || (arf_is_neg_inf(x) && arf_is_pos_inf(y))) { arf_nan(z); return 0; } else if (arf_is_special(x)) { arf_set(z, x); return 0; } else { arf_set(z, y); return 0; } } int arf_add(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; slong shift; if (arf_is_special(x) || arf_is_special(y)) { return arf_add_special(z, x, y, prec, rnd); } shift = _fmpz_sub_small(ARF_EXPREF(x), ARF_EXPREF(y)); if (shift < 0) { FLINT_SWAP(arf_srcptr, x, y); shift = -shift; } ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); return _arf_add_mpn(z, xptr, xn, ARF_SGNBIT(x), ARF_EXPREF(x), yptr, yn, ARF_SGNBIT(y), shift, prec, rnd); } int arf_add_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (y == 0) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) return arf_set_round_si(z, y, prec, rnd); else { arf_set(z, x); return 0; } } ysgnbit = (y < 0); if (ysgnbit) ytmp = -y; else ytmp = y; yptr = &ytmp; yn = 1; yexp = FLINT_BITS; /* XXX: worth the trouble to top-align y? */ shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); } int arf_add_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (y == 0) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) return arf_set_round_ui(z, y, prec, rnd); else { arf_set(z, x); return 0; } } ysgnbit = 0; ytmp = y; yptr = &ytmp; yn = 1; yexp = FLINT_BITS; shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); } int arf_add_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (fmpz_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) return arf_set_round_fmpz(z, y, prec, rnd); else { arf_set(z, x); return 0; } } FMPZ_GET_MPN_READONLY(ysgnbit, yn, yptr, ytmp, *y) yexp = yn * FLINT_BITS; shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); } int arf_add_fmpz_2exp(arf_ptr z, arf_srcptr x, const fmpz_t y, const fmpz_t exp, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit, inexact; fmpz_t yexp; slong shift; if (fmpz_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) { inexact = arf_set_round_fmpz(z, y, prec, rnd); arf_mul_2exp_fmpz(z, z, exp); return inexact; } else { arf_set(z, x); return 0; } } FMPZ_GET_MPN_READONLY(ysgnbit, yn, yptr, ytmp, *y) fmpz_init(yexp); fmpz_add_ui(yexp, exp, yn * FLINT_BITS); shift = _fmpz_sub_small(ARF_EXPREF(x), yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) inexact = _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, yptr, yn, ysgnbit, yexp, xptr, xn, xsgnbit, -shift, prec, rnd); fmpz_clear(yexp); return inexact; } flint-3.1.3/src/arf/add_mpn.c000066400000000000000000000252661461254215100157530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" FLINT_TLS_PREFIX mp_ptr __arf_add_tmp = NULL; FLINT_TLS_PREFIX slong __arf_add_alloc = 0; void _arf_add_tmp_cleanup(void) { flint_free(__arf_add_tmp); __arf_add_tmp = NULL; __arf_add_alloc = 0; } /* Assumptions: top limbs of x and y nonzero. */ int _arf_add_mpn(arf_t z, mp_srcptr xp, mp_size_t xn, int xsgnbit, const fmpz_t xexp, mp_srcptr yp, mp_size_t yn, int ysgnbit, flint_bitcnt_t shift, slong prec, arf_rnd_t rnd) { mp_size_t wn, zn, zn_original, alloc, xbase, wbase; mp_size_t shift_limbs; flint_bitcnt_t shift_bits; int inexact; slong fix; mp_limb_t cy; mp_ptr tmp; ARF_ADD_TMP_DECL /* very fast case */ if (xn == 1 && yn == 1 && shift < FLINT_BITS - 1) { mp_limb_t hi, lo, xhi, xlo, yhi, ylo; xhi = xp[0]; yhi = yp[0]; xlo = xhi << (FLINT_BITS - 1); xhi = xhi >> 1; ylo = yhi << (FLINT_BITS - (shift + 1)); yhi = yhi >> (shift + 1); if (xsgnbit == ysgnbit) { add_ssaaaa(hi, lo, xhi, xlo, yhi, ylo); } else { if (xhi > yhi) { sub_ddmmss(hi, lo, xhi, xlo, yhi, ylo); } else if (xhi < yhi) { sub_ddmmss(hi, lo, yhi, ylo, xhi, xlo); xsgnbit = ysgnbit; } else { if (xlo > ylo) { sub_ddmmss(hi, lo, xhi, xlo, yhi, ylo); } else if (xlo < ylo) { sub_ddmmss(hi, lo, yhi, ylo, xhi, xlo); xsgnbit = ysgnbit; } else { arf_zero(z); return 0; } } } inexact = _arf_set_round_uiui(z, &fix, hi, lo, xsgnbit, prec, rnd); _fmpz_add_fast(ARF_EXPREF(z), xexp, fix + 1); return inexact; } /* somewhat fast case */ if (xn <= 2 && yn <= 2 && shift <= 2 * FLINT_BITS) { mp_limb_t t[5], xtmp[4], ytmp[4], yhi, ylo; slong fix2; xtmp[0] = 0; xtmp[1] = 0; if (xn == 1) { xtmp[2] = 0; xtmp[3] = xp[0]; } else { xtmp[2] = xp[0]; xtmp[3] = xp[1]; } ytmp[0] = 0; ytmp[1] = 0; ytmp[2] = 0; ytmp[3] = 0; if (yn == 1) { yhi = yp[0]; ylo = 0; } else { yhi = yp[1]; ylo = yp[0]; } shift_limbs = shift / FLINT_BITS; shift_bits = shift % FLINT_BITS; if (shift_bits == 0) { ytmp[3 - shift_limbs] = yhi; ytmp[2 - shift_limbs] = ylo; } else { ytmp[3 - shift_limbs] = yhi >> shift_bits; ytmp[2 - shift_limbs] = (yhi << (FLINT_BITS - shift_bits)) | (ylo >> (shift_bits)); ytmp[1 - shift_limbs] = ylo << (FLINT_BITS - shift_bits); } if (xsgnbit == ysgnbit) { t[4] = cy = mpn_add_n(t, xtmp, ytmp, 4); fix2 = cy * FLINT_BITS; zn = 4 + cy; while (t[zn - 1] == 0) { zn--; fix2 -= FLINT_BITS; } } else { #if 1 cy = mpn_sub_n(t, xtmp, ytmp, 4); if (cy) { mpn_neg(t, t, 4); xsgnbit = ysgnbit; } zn = 4; fix2 = 0; while (t[zn - 1] == 0) { zn--; fix2 -= FLINT_BITS; if (zn == 0) { arf_zero(z); return 0; } } #else int cmp; cmp = mpn_cmp(xtmp, ytmp, 4); if (cmp > 0) { mpn_sub_n(t, xtmp, ytmp, 4); } else if (cmp < 0) { mpn_sub_n(t, ytmp, xtmp, 4); xsgnbit = ysgnbit; } else { arf_zero(z); return 0; } fix2 = 0; zn = 4; while (t[zn - 1] == 0) { zn--; fix2 -= FLINT_BITS; } #endif } inexact = _arf_set_round_mpn(z, &fix, t, zn, xsgnbit, prec, rnd); _fmpz_add_fast(ARF_EXPREF(z), xexp, fix + fix2); return inexact; } /* x +/- eps */ if (shift > prec + FLINT_BITS + 1 && prec != ARF_PREC_EXACT && shift > (xn + 1) * FLINT_BITS) { zn = (prec + FLINT_BITS - 1) / FLINT_BITS; zn_original = zn = FLINT_MAX(zn, xn) + 2; shift_limbs = zn - xn; alloc = zn + 1; ARF_ADD_TMP_ALLOC(tmp, alloc) flint_mpn_zero(tmp, shift_limbs); flint_mpn_copyi(tmp + shift_limbs, xp, xn); if (xsgnbit == ysgnbit) { tmp[0] = 1; } else { mpn_sub_1(tmp, tmp, zn, 1); while (tmp[zn-1] == 0) zn--; } _arf_set_round_mpn(z, &fix, tmp, zn, xsgnbit, prec, rnd); fix += (zn - zn_original) * FLINT_BITS; _fmpz_add_fast(ARF_EXPREF(z), xexp, fix); ARF_ADD_TMP_FREE(tmp, alloc) return 1; } shift_limbs = shift / FLINT_BITS; shift_bits = shift % FLINT_BITS; /* TODO: shift == 0 optimization! (common case) */ /* w = y shifted */ wn = yn + (shift_bits != 0); /* Size of sum (possibly one more limb than this for carry). */ zn_original = zn = FLINT_MAX(xn, wn + shift_limbs); alloc = zn + 1; ARF_ADD_TMP_ALLOC(tmp, alloc) /* Low limbs of both operands */ xbase = zn - xn; wbase = zn - shift_limbs - wn; /* Shift y to its correct offset in the sum. */ if (shift_bits == 0) flint_mpn_copyi(tmp + wbase, yp, yn); else tmp[wbase] = cy = mpn_rshift(tmp + wbase + 1, yp, yn, shift_bits); if (xsgnbit == ysgnbit) { if (shift_limbs >= xn) { /* XXXXXX WWWWWWW */ flint_mpn_zero(tmp + wn, zn - xn - wn); flint_mpn_copyi(tmp + zn - xn, xp, xn); cy = 0; } else if (shift_limbs == 0) { /* XXXXXX or XXXXX WWWW WWWWWWW */ if (wn < xn) { flint_mpn_copyi(tmp, xp, xn - wn); cy = mpn_add_n(tmp + wbase, xp + wbase, tmp + wbase, wn); } else { cy = mpn_add_n(tmp + xbase, xp, tmp + xbase, xn); } } else if (xbase >= wbase) { /* XXXXXX or XXXXXX WWWWWWW WWWW */ cy = mpn_add_n(tmp + xbase, tmp + xbase, xp, wn - xbase); cy = mpn_add_1(tmp + wn, xp + wn - xbase, zn - wn, cy); } else { /* XXXXXXXX todo: merge with above? WWW */ flint_mpn_copyi(tmp, xp, wbase); cy = mpn_add_n(tmp + wbase, tmp + wbase, xp + wbase, wn); cy = mpn_add_1(tmp + zn - shift_limbs, xp + xn - shift_limbs, shift_limbs, cy); } /* There could be a carry. */ tmp[zn] = cy; zn += cy; } else { if (shift_limbs >= xn) { /* XXXXXX WWWWWWW */ mpn_neg(tmp, tmp, wn); flint_mpn_store(tmp + wn, zn - xn - wn, -LIMB_ONE); mpn_sub_1(tmp + zn - xn, xp, xn, 1); } else if (shift_limbs == 0) { /* XXXXXX (1) or XXXXX (2) WWWW WWWWWWW */ if (wn <= xn) /* (1) */ { if (mpn_cmp(xp + wbase, tmp + wbase, wn) >= 0) { flint_mpn_copyi(tmp, xp, wbase); mpn_sub_n(tmp + wbase, xp + wbase, tmp + wbase, wn); } else { xsgnbit = ysgnbit; mpn_sub_n(tmp + wbase, tmp + wbase, xp + wbase, wn); if (wbase != 0) { cy = mpn_neg(tmp, xp, wbase); mpn_sub_1(tmp + wbase, tmp + wbase, wn, cy); } } } else /* (2) */ { if (mpn_cmp(tmp + xbase, xp, xn) >= 0) { xsgnbit = ysgnbit; mpn_sub_n(tmp + xbase, tmp + xbase, xp, xn); } else { cy = mpn_neg(tmp, tmp, xbase); mpn_sub_n(tmp + xbase, xp, tmp + xbase, xn); mpn_sub_1(tmp + xbase, tmp + xbase, xn, cy); } } } else if (xbase >= wbase) { /* XXXXXX or XXXXXX WWWWWWW WWWW */ if (xbase > 0) { cy = mpn_sub_n(tmp + xbase, xp, tmp + xbase, wn - xbase); cy = mpn_sub_1(tmp + wn, xp + xn - shift_limbs, shift_limbs, cy); cy = mpn_neg(tmp, tmp, xbase); mpn_sub_1(tmp + xbase, tmp + xbase, xn, cy); } else { cy = mpn_sub_n(tmp, xp, tmp, wn); cy = mpn_sub_1(tmp + wn, xp + wn, xn - wn, cy); } } else { /* XXXXXXXX WWW */ flint_mpn_copyi(tmp, xp, wbase); cy = mpn_sub_n(tmp + wbase, xp + wbase, tmp + wbase, wn); mpn_sub_1(tmp + zn - shift_limbs, xp + xn - shift_limbs, shift_limbs, cy); } /* There could be cancellation. */ while (zn > 0 && tmp[zn - 1] == 0) zn--; } if (zn == 0) { arf_zero(z); inexact = 0; } else { inexact = _arf_set_round_mpn(z, &fix, tmp, zn, xsgnbit, prec, rnd); fix += (zn - zn_original) * FLINT_BITS; _fmpz_add_fast(ARF_EXPREF(z), xexp, fix); } ARF_ADD_TMP_FREE(tmp, alloc) return inexact; } flint-3.1.3/src/arf/addmul.c000066400000000000000000000074621461254215100156150ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "mpn_extras.h" int arf_addmul(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, tn, alloc; mp_srcptr xptr, yptr, zptr; mp_ptr tptr, tptr2; fmpz_t texp; slong shift; int tsgnbit, inexact; ARF_MUL_TMP_DECL if (arf_is_special(x) || arf_is_special(y) || arf_is_special(z)) { if (arf_is_zero(z)) { return arf_mul(z, x, y, prec, rnd); } else if (arf_is_finite(x) && arf_is_finite(y)) { return arf_set_round(z, z, prec, rnd); } else { /* todo: speed up */ arf_t t; arf_init(t); arf_mul(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(z, z, t, prec, rnd); arf_clear(t); return inexact; } } tsgnbit = ARF_SGNBIT(x) ^ ARF_SGNBIT(y); ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); ARF_GET_MPN_READONLY(zptr, zn, z); fmpz_init(texp); _fmpz_add2_fast(texp, ARF_EXPREF(x), ARF_EXPREF(y), 0); shift = _fmpz_sub_small(ARF_EXPREF(z), texp); alloc = tn = xn + yn; ARF_MUL_TMP_ALLOC(tptr2, alloc) tptr = tptr2; FLINT_MPN_MUL_WITH_SPECIAL_CASES(tptr, xptr, xn, yptr, yn); tn -= (tptr[0] == 0); tptr += (tptr[0] == 0); if (shift >= 0) inexact = _arf_add_mpn(z, zptr, zn, ARF_SGNBIT(z), ARF_EXPREF(z), tptr, tn, tsgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, tptr, tn, tsgnbit, texp, zptr, zn, ARF_SGNBIT(z), -shift, prec, rnd); ARF_MUL_TMP_FREE(tptr2, alloc) fmpz_clear(texp); return inexact; } int arf_addmul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, tn, alloc; mp_srcptr xptr, yptr, zptr; mp_ptr tptr, tptr2; fmpz_t texp, yexp; slong shift; int tsgnbit, ysgnbit, inexact; ARF_MUL_TMP_DECL yn = FLINT_ABS(y->_mp_size); if (arf_is_special(x) || yn == 0 || arf_is_special(z)) { if (arf_is_zero(z)) { return arf_mul_mpz(z, x, y, prec, rnd); } else if (arf_is_finite(x)) { return arf_set_round(z, z, prec, rnd); } else { /* todo: speed up */ arf_t t; arf_init(t); arf_mul_mpz(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(z, z, t, prec, rnd); arf_clear(t); return inexact; } } ARF_GET_MPN_READONLY(xptr, xn, x); yptr = y->_mp_d; ysgnbit = (y->_mp_size < 0); *yexp = yn * FLINT_BITS; ARF_GET_MPN_READONLY(zptr, zn, z); fmpz_init(texp); tsgnbit = ARF_SGNBIT(x) ^ ysgnbit; alloc = tn = xn + yn; ARF_MUL_TMP_ALLOC(tptr2, alloc) tptr = tptr2; FLINT_MPN_MUL_WITH_SPECIAL_CASES(tptr, xptr, xn, yptr, yn); shift = (tptr[tn - 1] == 0) * FLINT_BITS; tn -= (tptr[tn - 1] == 0); _fmpz_add2_fast(texp, ARF_EXPREF(x), yexp, -shift); shift = _fmpz_sub_small(ARF_EXPREF(z), texp); if (shift >= 0) inexact = _arf_add_mpn(z, zptr, zn, ARF_SGNBIT(z), ARF_EXPREF(z), tptr, tn, tsgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, tptr, tn, tsgnbit, texp, zptr, zn, ARF_SGNBIT(z), -shift, prec, rnd); ARF_MUL_TMP_FREE(tptr2, alloc) fmpz_clear(texp); return inexact; } flint-3.1.3/src/arf/approx_dot.c000066400000000000000000000324131461254215100165200ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "mpn_extras.h" void _arb_dot_addmul_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, mp_srcptr yptr, mp_size_t yn, int negative, flint_bitcnt_t shift); void _arb_dot_add_generic(mp_ptr sum, mp_ptr serr, mp_ptr tmp, mp_size_t sn, mp_srcptr xptr, mp_size_t xn, int negative, flint_bitcnt_t shift); void arf_approx_dot_simple(arf_t res, const arf_t initial, int subtract, arf_srcptr x, slong xstep, arf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd) { slong i; if (len <= 0) { if (initial == NULL) arf_zero(res); else arf_set_round(res, initial, prec, rnd); return; } if (initial == NULL) { arf_mul(res, x, y, prec, rnd); } else { if (subtract) arf_neg(res, initial); else arf_set(res, initial); arf_addmul(res, x, y, prec, rnd); } for (i = 1; i < len; i++) arf_addmul(res, x + i * xstep, y + i * ystep, prec, rnd); if (subtract) arf_neg(res, res); } void arf_approx_dot(arf_t res, const arf_t initial, int subtract, arf_srcptr x, slong xstep, arf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd) { slong i, j, nonzero, padding, extend; slong xexp, yexp, exp, max_exp, min_exp, sum_exp; int xnegative, ynegative; mp_size_t xn, yn, sn, alloc; flint_bitcnt_t shift; arf_srcptr xi, yi; arf_srcptr xm, ym; mp_limb_t serr; /* Sum over arithmetic errors - not used, but need dummy for calls */ mp_ptr tmp, sum; /* Workspace */ ARF_ADD_TMP_DECL; /* todo: fast fma and fmma (len=2) code */ if (len <= 1) { if (initial == NULL) { if (len <= 0) arf_zero(res); else { if (subtract) arf_neg_mul(res, x, y, prec, rnd); else arf_mul(res, x, y, prec, rnd); } return; } else if (len <= 0) { arf_set_round(res, initial, prec, rnd); return; } } /* Number of nonzero midpoint terms in sum. */ nonzero = 0; /* Terms are bounded by 2^max_exp (with WORD_MIN = -infty) */ max_exp = WORD_MIN; /* Used to reduce the precision. */ min_exp = WORD_MAX; /* Account for the initial term. */ if (initial != NULL) { if (!ARF_IS_LAGOM(initial)) { arf_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec, rnd); return; } xm = initial; if (!arf_is_special(xm)) { max_exp = ARF_EXP(xm); nonzero++; if (prec > 2 * FLINT_BITS) min_exp = ARF_EXP(xm) - ARF_SIZE(xm) * FLINT_BITS; } } /* Determine maximum exponents for the main sum and the radius sum. */ for (i = 0; i < len; i++) { xi = x + i * xstep; yi = y + i * ystep; /* Fallback for huge exponents or non-finite values. */ if (!ARF_IS_LAGOM(xi) || !ARF_IS_LAGOM(yi)) { arf_approx_dot_simple(res, initial, subtract, x, xstep, y, ystep, len, prec, rnd); return; } xm = xi; ym = yi; if (!arf_is_special(xm)) { xexp = ARF_EXP(xm); if (!arf_is_special(ym)) { yexp = ARF_EXP(ym); max_exp = FLINT_MAX(max_exp, xexp + yexp); nonzero++; if (prec > 2 * FLINT_BITS) { slong bot; bot = (xexp + yexp) - (ARF_SIZE(xm) + ARF_SIZE(ym)) * FLINT_BITS; min_exp = FLINT_MIN(min_exp, bot); } } } } /* The midpoint sum is zero. */ if (max_exp == WORD_MIN) { arf_zero(res); return; } else { /* Reduce precision based on actual sizes. */ if (min_exp != WORD_MAX) prec = FLINT_MIN(prec, max_exp - min_exp + MAG_BITS); prec = FLINT_MAX(prec, 2); } /* Extend sum so that we can use two's complement addition. */ extend = FLINT_BIT_COUNT(nonzero) + 1; /* Extra bits to improve accuracy (optional). */ padding = 4 + FLINT_BIT_COUNT(len); /* Number of limbs. */ sn = (prec + extend + padding + FLINT_BITS - 1) / FLINT_BITS; /* Avoid having to make a special case for sn = 1. */ sn = FLINT_MAX(sn, 2); /* Exponent for the main sum. */ sum_exp = max_exp + extend; /* We need sn + 1 limb for the sum (sn limbs + 1 dummy limb for carry or borrow that avoids an extra branch). We need 2 * (sn + 2) limbs to store the product of two numbers with up to (sn + 2) limbs, plus 1 extra limb for shifting the product. */ alloc = (sn + 1) + 2 * (sn + 2) + 1; ARF_ADD_TMP_ALLOC(sum, alloc) tmp = sum + (sn + 1); /* Set sum to 0 */ serr = 0; for (j = 0; j < sn + 1; j++) sum[j] = 0; if (initial != NULL) { xm = initial; if (!arf_is_special(xm)) { mp_srcptr xptr; xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); shift = sum_exp - xexp; if (shift < sn * FLINT_BITS) { xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); _arb_dot_add_generic(sum, &serr, tmp, sn, xptr, xn, xnegative ^ subtract, shift); } } } for (i = 0; i < len; i++) { xi = x + i * xstep; yi = y + i * ystep; xm = xi; ym = yi; /* The midpoints of x[i] and y[i] are both nonzero. */ if (!arf_is_special(xm) && !arf_is_special(ym)) { xexp = ARF_EXP(xm); xn = ARF_SIZE(xm); xnegative = ARF_SGNBIT(xm); yexp = ARF_EXP(ym); yn = ARF_SIZE(ym); ynegative = ARF_SGNBIT(ym); exp = xexp + yexp; shift = sum_exp - exp; if (shift >= sn * FLINT_BITS) { /* do nothing */ } #if 0 else if (xn == 1 && yn == 1 && sn == 2 && shift < FLINT_BITS) /* Fastest path. */ { mp_limb_t hi, lo, x0, y0; x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; umul_ppmm(hi, lo, x0, y0); lo = (lo >> shift) | (hi << (FLINT_BITS - shift)); hi = (hi >> shift); if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], hi, lo); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], hi, lo); } else if (xn == 2 && yn == 2 && shift < FLINT_BITS && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); if (sn == 2) { if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else { if (xnegative ^ ynegative) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } #endif else if (xn <= 2 && yn <= 2 && sn <= 3) { mp_limb_t x1, x0, y1, y0; mp_limb_t u3, u2, u1, u0; if (xn == 1 && yn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; umul_ppmm(u3, u2, x0, y0); u1 = u0 = 0; } else if (xn == 2 && yn == 2) { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X2(u3, u2, u1, u0, x1, x0, y1, y0); } else if (xn == 1) { x0 = ARF_NOPTR_D(xm)[0]; y0 = ARF_NOPTR_D(ym)[0]; y1 = ARF_NOPTR_D(ym)[1]; FLINT_MPN_MUL_2X1(u3, u2, u1, y1, y0, x0); u0 = 0; } else { x0 = ARF_NOPTR_D(xm)[0]; x1 = ARF_NOPTR_D(xm)[1]; y0 = ARF_NOPTR_D(ym)[0]; FLINT_MPN_MUL_2X1(u3, u2, u1, x1, x0, y0); u0 = 0; } if (sn == 2) { if (shift < FLINT_BITS) { u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u2 = u3; u3 = 0; } else /* FLINT_BITS < shift < 2 * FLINT_BITS */ { u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } if (xnegative ^ ynegative) sub_ddmmss(sum[1], sum[0], sum[1], sum[0], u3, u2); else add_ssaaaa(sum[1], sum[0], sum[1], sum[0], u3, u2); } else if (sn == 3) { if (shift < FLINT_BITS) { u1 = (u1 >> shift) | (u2 << (FLINT_BITS - shift)); u2 = (u2 >> shift) | (u3 << (FLINT_BITS - shift)); u3 = (u3 >> shift); } else if (shift == FLINT_BITS) { u1 = u2; u2 = u3; u3 = 0; } else if (shift < 2 * FLINT_BITS) { u1 = (u3 << (2 * FLINT_BITS - shift)) | (u2 >> (shift - FLINT_BITS)); u2 = (u3 >> (shift - FLINT_BITS)); u3 = 0; } else if (shift == 2 * FLINT_BITS) { u1 = u3; u2 = 0; u3 = 0; } else /* 2 * FLINT_BITS < shift < 3 * FLINT_BITS */ { u1 = (u3 >> (shift - 2 * FLINT_BITS)); u2 = 0; u3 = 0; } if (xnegative ^ ynegative) sub_dddmmmsss(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); else add_sssaaaaaa(sum[2], sum[1], sum[0], sum[2], sum[1], sum[0], u3, u2, u1); } } else { mp_srcptr xptr, yptr; xptr = (xn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(xm) : ARF_PTR_D(xm); yptr = (yn <= ARF_NOPTR_LIMBS) ? ARF_NOPTR_D(ym) : ARF_PTR_D(ym); _arb_dot_addmul_generic(sum, &serr, tmp, sn, xptr, xn, yptr, yn, xnegative ^ ynegative, shift); } } } xnegative = 0; if (sum[sn - 1] >= LIMB_TOP) { mpn_neg(sum, sum, sn); xnegative = 1; } if (sum[sn - 1] == 0) { slong sum_exp2; mp_size_t sn2; sn2 = sn; sum_exp2 = sum_exp; while (sn2 > 0 && sum[sn2 - 1] == 0) { sum_exp2 -= FLINT_BITS; sn2--; } if (sn2 == 0) { arf_zero(res); } else { _arf_set_round_mpn(res, &exp, sum, sn2, xnegative ^ subtract, prec, rnd); _fmpz_set_si_small(ARF_EXPREF(res), exp + sum_exp2); } } else { if (sn == 2) _arf_set_round_uiui(res, &exp, sum[1], sum[0], xnegative ^ subtract, prec, rnd); else _arf_set_round_mpn(res, &exp, sum, sn, xnegative ^ subtract, prec, rnd); _fmpz_set_si_small(ARF_EXPREF(res), exp + sum_exp); } ARF_ADD_TMP_FREE(sum, alloc); } flint-3.1.3/src/arf/call_mpfr_func.c000066400000000000000000000042751461254215100173200ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpfr.h" #include "arf.h" typedef int ((*mpfr_func_1x1)(mpfr_ptr, mpfr_srcptr, mpfr_rnd_t)); typedef int ((*mpfr_func_1x2)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t)); typedef int ((*mpfr_func_2x1)(mpfr_ptr, mpfr_ptr, mpfr_srcptr, mpfr_rnd_t)); int _arf_call_mpfr_func(arf_ptr r1, arf_ptr r2, int (*func)(void), arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mpfr_t xx, yy, rr1, rr2; mpfr_rnd_t rrnd; int inexact = 0; rrnd = arf_rnd_to_mpfr(rnd); mpfr_set_emin(MPFR_EMIN_MIN); mpfr_set_emax(MPFR_EMAX_MAX); mpfr_init2(xx, 2 + arf_bits(x)); if (arf_get_mpfr(xx, x, MPFR_RNDD)) { flint_throw(FLINT_ERROR, "exception: unable to convert exactly to mpfr\n"); } if (y != NULL) { mpfr_init2(yy, 2 + arf_bits(y)); if (arf_get_mpfr(yy, y, MPFR_RNDD)) { flint_throw(FLINT_ERROR, "exception: unable to convert exactly to mpfr\n"); } } mpfr_init2(rr1, FLINT_MAX(2, prec)); if (r2 != NULL) mpfr_init2(rr2, FLINT_MAX(2, prec)); if (r2 == NULL && y == NULL) inexact = (((mpfr_func_1x1) func)(rr1, xx, rrnd) != 0); else if (r2 != NULL && y == NULL) inexact = (((mpfr_func_2x1) func)(rr1, rr2, xx, rrnd) != 0); else if (r2 == NULL && y != NULL) inexact = (((mpfr_func_1x2) func)(rr1, xx, yy, rrnd) != 0); else flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (mpfr_overflow_p() || mpfr_underflow_p()) { flint_throw(FLINT_ERROR, "exception: mpfr overflow\n"); } if (r1 != NULL) { arf_set_mpfr(r1, rr1); mpfr_clear(rr1); } if (r2 != NULL) { arf_set_mpfr(r2, rr2); mpfr_clear(rr2); } if (x != NULL) mpfr_clear(xx); if (y != NULL) mpfr_clear(yy); return inexact; } flint-3.1.3/src/arf/ceil.c000066400000000000000000000020021461254215100152440ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_ceil(arf_t z, const arf_t x) { if (arf_is_special(x) || arf_is_int(x)) { arf_set(z, x); } else { slong exp = ARF_EXP(x); /* now exp cannot be too large, as we would have caught this in arf_is_int() */ if (COEFF_IS_MPZ(exp) || exp <= 0) { if (ARF_SGNBIT(x)) arf_zero(z); else arf_one(z); } else if (exp == 1) { arf_set_si(z, ARF_SGNBIT(x) ? -1 : 2); } else { arf_set_round(z, x, exp, ARF_RND_CEIL); } } } flint-3.1.3/src/arf/clear.c000066400000000000000000000015661461254215100154340ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_clear(arf_t x) { ARF_DEMOTE(x); /* fmpz_clear(), but avoids a redundant store */ if (COEFF_IS_MPZ(ARF_EXP(x))) _fmpz_clear_mpz(ARF_EXP(x)); } arf_ptr _arf_vec_init(slong n) { slong i; arf_ptr v = (arf_ptr) flint_malloc(sizeof(arf_struct) * n); for (i = 0; i < n; i++) arf_init(v + i); return v; } void _arf_vec_clear(arf_ptr x, slong n) { slong i; for (i = 0; i < n; i++) arf_clear(x + i); flint_free(x); } flint-3.1.3/src/arf/cmp.c000066400000000000000000000106441461254215100151220ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_cmp(const arf_t x, const arf_t y) { int xs, ys, ec, mc; mp_size_t xn, yn; mp_srcptr xp, yp; if (arf_is_special(x) || arf_is_special(y)) { if (arf_equal(x, y)) return 0; if (arf_is_nan(x) || arf_is_nan(y)) return 0; if (arf_is_zero(y)) return arf_sgn(x); if (arf_is_zero(x)) return -arf_sgn(y); if (arf_is_pos_inf(x)) return 1; if (arf_is_neg_inf(y)) return 1; return -1; } xs = ARF_SGNBIT(x); ys = ARF_SGNBIT(y); if (xs != ys) return xs ? -1 : 1; ec = fmpz_cmp(ARF_EXPREF(x), ARF_EXPREF(y)); if (ec != 0) return ((ec < 0) ^ xs) ? -1 : 1; ARF_GET_MPN_READONLY(xp, xn, x); ARF_GET_MPN_READONLY(yp, yn, y); if (xn >= yn) mc = mpn_cmp(xp + xn - yn, yp, yn); else mc = mpn_cmp(xp, yp + yn - xn, xn); if (mc != 0) return ((mc < 0) ^ xs) ? -1 : 1; if (xn != yn) return ((xn < yn) ^ xs) ? -1 : 1; return 0; } int arf_cmp_si(const arf_t x, slong y) { arf_t t; arf_init_set_si(t, y); /* no need to free */ return arf_cmp(x, t); } int arf_cmp_ui(const arf_t x, ulong y) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ return arf_cmp(x, t); } int arf_cmp_d(const arf_t x, double y) { arf_t t; arf_init(t); /* no need to free */ arf_set_d(t, y); return arf_cmp(x, t); } int arf_cmpabs(const arf_t x, const arf_t y) { int ec, mc; mp_size_t xn, yn; mp_srcptr xp, yp; if (arf_is_special(x) || arf_is_special(y)) { if (arf_equal(x, y)) return 0; if (arf_is_nan(x) || arf_is_nan(y)) return 0; if (arf_is_zero(x)) return -1; if (arf_is_zero(y)) return 1; if (arf_is_inf(x)) return arf_is_inf(y) ? 0 : 1; if (arf_is_inf(y)) return -1; return -1; } ec = fmpz_cmp(ARF_EXPREF(x), ARF_EXPREF(y)); if (ec != 0) return (ec < 0) ? -1 : 1; ARF_GET_MPN_READONLY(xp, xn, x); ARF_GET_MPN_READONLY(yp, yn, y); if (xn >= yn) mc = mpn_cmp(xp + xn - yn, yp, yn); else mc = mpn_cmp(xp, yp + yn - xn, xn); if (mc != 0) return (mc < 0) ? -1 : 1; if (xn != yn) return (xn < yn) ? -1 : 1; return 0; } int arf_cmpabs_ui(const arf_t x, ulong y) { arf_t t; arf_init_set_ui(t, y); /* no need to free */ return arf_cmpabs(x, t); } int arf_cmpabs_d(const arf_t x, double y) { arf_t t; arf_init(t); /* no need to free */ arf_set_d(t, y); return arf_cmpabs(x, t); } int arf_cmp_2exp_si(const arf_t x, slong e) { if (arf_is_special(x)) { if (arf_is_zero(x)) return -1; if (arf_is_pos_inf(x)) return 1; if (arf_is_neg_inf(x)) return -1; return 0; } if (ARF_SGNBIT(x)) return -1; /* Fast path. */ if (!COEFF_IS_MPZ(ARF_EXP(x))) { if (ARF_IS_POW2(x) && (ARF_EXP(x) - 1 == e)) return 0; else return (ARF_EXP(x) <= e) ? -1 : 1; } if (ARF_IS_POW2(x)) { fmpz_t t; fmpz_init(t); fmpz_one(t); fmpz_add_si(t, t, e); if (fmpz_equal(ARF_EXPREF(x), t)) { fmpz_clear(t); return 0; } fmpz_clear(t); } return (fmpz_cmp_si(ARF_EXPREF(x), e) <= 0) ? -1 : 1; } int arf_cmpabs_2exp_si(const arf_t x, slong e) { if (arf_is_special(x)) { if (arf_is_zero(x)) return -1; if (arf_is_inf(x)) return 1; return 0; } /* Fast path. */ if (!COEFF_IS_MPZ(ARF_EXP(x))) { if (ARF_IS_POW2(x) && (ARF_EXP(x) - 1 == e)) return 0; else return (ARF_EXP(x) <= e) ? -1 : 1; } if (ARF_IS_POW2(x)) { fmpz_t t; fmpz_init(t); fmpz_one(t); fmpz_add_si(t, t, e); if (fmpz_equal(ARF_EXPREF(x), t)) { fmpz_clear(t); return 0; } fmpz_clear(t); } return (fmpz_cmp_si(ARF_EXPREF(x), e) <= 0) ? -1 : 1; } flint-3.1.3/src/arf/complex_mul.c000066400000000000000000000213341461254215100166650ustar00rootroot00000000000000/* Copyright (C) 2014, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" #include "arf.h" #include "mpn_extras.h" int arf_complex_mul_fallback(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d, slong prec, arf_rnd_t rnd) { int inex1, inex2; /* here the operations are ordered to allow aliasing */ if (arf_is_zero(d)) { /* (a + bi) * c */ inex2 = arf_mul(f, b, c, prec, rnd); inex1 = arf_mul(e, a, c, prec, rnd); } else if (arf_is_zero(b)) { /* a * (c + di) */ inex2 = arf_mul(f, a, d, prec, rnd); inex1 = arf_mul(e, a, c, prec, rnd); } else if (arf_is_zero(c)) { /* (a + bi) * di = -bd + adi */ inex2 = arf_mul(e, a, d, prec, rnd); inex1 = arf_neg_mul(f, b, d, prec, rnd); arf_swap(e, f); } else if (arf_is_zero(a)) { /* bi * (c + di) = -bd + bci */ inex2 = arf_mul(e, b, c, prec, rnd); inex1 = arf_neg_mul(f, b, d, prec, rnd); arf_swap(e, f); } else { arf_t t, u, v, w; arf_init(t); arf_init(u); arf_init(v); arf_init(w); arf_mul(t, a, c, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(u, b, d, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(v, b, c, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(w, a, d, ARF_PREC_EXACT, ARF_RND_DOWN); inex1 = arf_sub(e, t, u, prec, rnd); inex2 = arf_add(f, v, w, prec, rnd); arf_clear(t); arf_clear(u); arf_clear(v); arf_clear(w); } return inex1 | (inex2 << 1); } int arf_complex_mul(arf_t e, arf_t f, const arf_t a, const arf_t b, const arf_t c, const arf_t d, slong prec, arf_rnd_t rnd) { mp_srcptr ap, bp, cp, dp; int asgn, bsgn, csgn, dsgn, inex1, inex2; mp_ptr tmp, acp, bdp, adp, bcp; mp_size_t an, bn, cn, dn, acn, bdn, adn, bcn, alloc; slong shift; slong aexp, bexp, cexp, dexp; fmpz texp, uexp; if (!ARF_IS_LAGOM(a) || !ARF_IS_LAGOM(b) || !ARF_IS_LAGOM(c) || !ARF_IS_LAGOM(d) || ARF_IS_SPECIAL(d) || ARF_IS_SPECIAL(a) || ARF_IS_SPECIAL(b) || ARF_IS_SPECIAL(c)) { return arf_complex_mul_fallback(e, f, a, b, c, d, prec, rnd); } ARF_GET_MPN_READONLY(ap, an, a); asgn = ARF_SGNBIT(a); aexp = ARF_EXP(a); ARF_GET_MPN_READONLY(bp, bn, b); bsgn = ARF_SGNBIT(b); bexp = ARF_EXP(b); ARF_GET_MPN_READONLY(cp, cn, c); csgn = ARF_SGNBIT(c); cexp = ARF_EXP(c); ARF_GET_MPN_READONLY(dp, dn, d); dsgn = ARF_SGNBIT(d); dexp = ARF_EXP(d); /* Karatsuba multiplication e = ac - bd f = (a+b)(c+d) - ac - bd */ if (an >= 20 && cn >= 20 && FLINT_ABS(an - bn) <= 2 && FLINT_ABS(cn - dn) <= 2 && FLINT_ABS(aexp - bexp) <= 64 && FLINT_ABS(cexp - dexp) <= 64) { fmpz_t za, zb, zc, zd, t, u, v; slong abot, bbot, cbot, dbot; abot = aexp - an * FLINT_BITS; bbot = bexp - bn * FLINT_BITS; cbot = cexp - cn * FLINT_BITS; dbot = dexp - dn * FLINT_BITS; texp = FLINT_MIN(abot, bbot); uexp = FLINT_MIN(cbot, dbot); fmpz_init(za); fmpz_init(zb); fmpz_init(zc); fmpz_init(zd); fmpz_init(t); fmpz_init(u); fmpz_init(v); /* todo: could avoid two copies */ fmpz_lshift_mpn(za, ap, an, asgn, abot - texp); fmpz_lshift_mpn(zb, bp, bn, bsgn, bbot - texp); fmpz_lshift_mpn(zc, cp, cn, csgn, cbot - uexp); fmpz_lshift_mpn(zd, dp, dn, dsgn, dbot - uexp); fmpz_add(t, za, zb); fmpz_add(v, zc, zd); fmpz_mul(u, t, v); fmpz_mul(t, za, zc); fmpz_mul(v, zb, zd); fmpz_sub(u, u, t); fmpz_sub(u, u, v); fmpz_sub(t, t, v); texp += uexp; inex1 = arf_set_round_fmpz_2exp(e, t, &texp, prec, rnd); inex2 = arf_set_round_fmpz_2exp(f, u, &texp, prec, rnd); fmpz_clear(za); fmpz_clear(zb); fmpz_clear(zc); fmpz_clear(zd); fmpz_clear(t); fmpz_clear(u); fmpz_clear(v); } else { ARF_MUL_TMP_DECL acn = an + cn; bdn = bn + dn; adn = an + dn; bcn = bn + cn; alloc = acn + bdn + adn + bcn; ARF_MUL_TMP_ALLOC(tmp, alloc) acp = tmp; bdp = acp + acn; adp = bdp + bdn; bcp = adp + adn; FLINT_MPN_MUL_WITH_SPECIAL_CASES(acp, ap, an, cp, cn) acn -= (acp[0] == 0); acp += (acp[0] == 0); FLINT_MPN_MUL_WITH_SPECIAL_CASES(bdp, bp, bn, dp, dn) bdn -= (bdp[0] == 0); bdp += (bdp[0] == 0); FLINT_MPN_MUL_WITH_SPECIAL_CASES(adp, ap, an, dp, dn) adn -= (adp[0] == 0); adp += (adp[0] == 0); FLINT_MPN_MUL_WITH_SPECIAL_CASES(bcp, bp, bn, cp, cn) bcn -= (bcp[0] == 0); bcp += (bcp[0] == 0); texp = aexp + cexp; uexp = bexp + dexp; shift = texp - uexp; if (shift >= 0) inex1 = _arf_add_mpn(e, acp, acn, asgn ^ csgn, &texp, bdp, bdn, bsgn ^ dsgn ^ 1, shift, prec, rnd); else inex1 = _arf_add_mpn(e, bdp, bdn, bsgn ^ dsgn ^ 1, &uexp, acp, acn, asgn ^ csgn, -shift, prec, rnd); texp = aexp + dexp; uexp = bexp + cexp; shift = texp - uexp; if (shift >= 0) inex2 = _arf_add_mpn(f, adp, adn, asgn ^ dsgn, &texp, bcp, bcn, bsgn ^ csgn, shift, prec, rnd); else inex2 = _arf_add_mpn(f, bcp, bcn, bsgn ^ csgn, &uexp, adp, adn, asgn ^ dsgn, -shift, prec, rnd); ARF_MUL_TMP_FREE(tmp, alloc) } return inex1 | (inex2 << 1); } int arf_complex_sqr(arf_t e, arf_t f, const arf_t a, const arf_t b, slong prec, arf_rnd_t rnd) { if (!ARF_IS_LAGOM(a) || !ARF_IS_LAGOM(b) || ARF_IS_SPECIAL(a) || ARF_IS_SPECIAL(b)) { return arf_complex_mul_fallback(e, f, a, b, a, b, prec, rnd); } else { mp_srcptr ap, bp; int inex1, inex2; mp_ptr tmp, aap, bbp; mp_size_t an, bn, aan, bbn, alloc; slong shift; slong aexp, bexp; fmpz texp, uexp; TMP_INIT; ARF_GET_MPN_READONLY(ap, an, a); aexp = ARF_EXP(a); ARF_GET_MPN_READONLY(bp, bn, b); bexp = ARF_EXP(b); if (an >= 112 && FLINT_ABS(an - bn) <= 2 && FLINT_ABS(aexp - bexp) <= 64) { fmpzi_t x, z; slong abot, bbot; int asgn, bsgn; asgn = ARF_SGNBIT(a); bsgn = ARF_SGNBIT(b); abot = aexp - an * FLINT_BITS; bbot = bexp - bn * FLINT_BITS; texp = FLINT_MIN(abot, bbot); fmpzi_init(x); fmpzi_init(z); fmpz_lshift_mpn(fmpzi_realref(x), ap, an, asgn, abot - texp); fmpz_lshift_mpn(fmpzi_imagref(x), bp, bn, bsgn, bbot - texp); fmpzi_sqr(z, x); texp *= 2; inex1 = arf_set_round_fmpz_2exp(e, fmpzi_realref(z), &texp, prec, rnd); inex2 = arf_set_round_fmpz_2exp(f, fmpzi_imagref(z), &texp, prec, rnd); fmpzi_clear(x); fmpzi_clear(z); } else { aan = 2 * an; bbn = 2 * bn; alloc = aan + bbn; TMP_START; tmp = TMP_ALLOC(alloc * sizeof(mp_limb_t)); aap = tmp; bbp = tmp + aan; FLINT_MPN_MUL_WITH_SPECIAL_CASES(aap, ap, an, ap, an) aan -= (aap[0] == 0); aap += (aap[0] == 0); FLINT_MPN_MUL_WITH_SPECIAL_CASES(bbp, bp, bn, bp, bn) bbn -= (bbp[0] == 0); bbp += (bbp[0] == 0); texp = aexp + aexp; uexp = bexp + bexp; shift = texp - uexp; inex2 = arf_mul(f, a, b, prec, rnd); ARF_EXP(f) += 1; if (shift >= 0) inex1 = _arf_add_mpn(e, aap, aan, 0, &texp, bbp, bbn, 1, shift, prec, rnd); else inex1 = _arf_add_mpn(e, bbp, bbn, 1, &uexp, aap, aan, 0, -shift, prec, rnd); TMP_END; } return inex1 | (inex2 << 1); } } flint-3.1.3/src/arf/debug.c000066400000000000000000000013471461254215100154310ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_debug(const arf_t x) { mp_srcptr d; mp_size_t n; slong i; flint_printf("{exp="); fmpz_print(&x->exp); flint_printf("; size=%wu; sgnbit=%wd; digits=[", ARF_SIZE(x), ARF_SGNBIT(x)); ARF_GET_MPN_READONLY(d, n, x); for (i = 0; i < n; i++) flint_printf(" %wu", d[i]); flint_printf("]}"); } flint-3.1.3/src/arf/div.c000066400000000000000000000072141461254215100151240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "arf.h" void __gmpn_div_q(mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); void arf_div_special(arf_t z, const arf_t x, const arf_t y) { if ((arf_is_zero(x) && !arf_is_zero(y) && !arf_is_nan(y)) || (arf_is_inf(y) && !arf_is_special(x))) { arf_zero(z); } else if (arf_is_zero(y) || (arf_is_special(x) && arf_is_special(y)) || arf_is_nan(x) || arf_is_nan(y)) { arf_nan(z); } else if (arf_sgn(x) == arf_sgn(y)) arf_pos_inf(z); else arf_neg_inf(z); } int arf_div(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, sn, tn, alloc; mp_srcptr xptr, yptr; mp_ptr tmp; mp_ptr tptr, zptr; int inexact; slong fix, fix2; ARF_MUL_TMP_DECL if (arf_is_special(x) || arf_is_special(y)) { arf_div_special(z, x, y); return 0; } ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); /* Division by a power of two */ if (yn == 1 && yptr[0] == LIMB_TOP) { fmpz_t t; fmpz_init_set(t, ARF_EXPREF(y)); if (ARF_SGNBIT(y)) inexact = arf_neg_round(z, x, prec, rnd); else inexact = arf_set_round(z, x, prec, rnd); _fmpz_sub2_fast(ARF_EXPREF(z), ARF_EXPREF(z), t, 1); fmpz_clear(t); return inexact; } sn = FLINT_MAX(prec - xn * FLINT_BITS + yn * FLINT_BITS, 0) + 32; sn = (sn + FLINT_BITS - 1) / FLINT_BITS; /* Need space for numerator (tn), quotient (zn), and one extra limb at the top of tptr for the multiplication to check the remainder. */ tn = xn + sn; zn = tn - yn + 1; alloc = zn + (tn + 1); /* need tn + 1 extra temporary limbs, which we store at the end of tptr */ alloc += tn + 1; ARF_MUL_TMP_ALLOC(tmp, alloc) zptr = tmp; tptr = tmp + zn; flint_mpn_zero(tptr, sn); flint_mpn_copyi(tptr + sn, xptr, xn); /* uses tn + 1 extra temporary limbs, tn limbs after tptr */ __gmpn_div_q(zptr, tptr, tn, yptr, yn, tptr + tn); if (zptr[zn - 1] == 0) { zn--; fix2 = 0; } else { fix2 = FLINT_BITS; } /* The remainder can only be zero if the last several bits of the extended quotient are zero. */ if ((zptr[0] & ((LIMB_ONE << 24) - 1)) == 0) { /* The quotient is exact iff multiplying by y gives back the input. Note: the multiplication may write sn + xn + 1 limbs, but tptr[sn + xn] is guaranteed to be zero in that case since the approximate quotient cannot be larger than the true quotient. */ if (zn >= yn) flint_mpn_mul(tptr, zptr, zn, yptr, yn); else flint_mpn_mul(tptr, yptr, yn, zptr, zn); /* The quotient is not exact. Perturbing the approximate quotient and rounding gives the correct the result. */ if (!flint_mpn_zero_p(tptr, sn) || mpn_cmp(tptr + sn, xptr, xn) != 0) { zptr[0]++; } } inexact = _arf_set_round_mpn(z, &fix, zptr, zn, ARF_SGNBIT(x) ^ ARF_SGNBIT(y), prec, rnd); _fmpz_sub2_fast(ARF_EXPREF(z), ARF_EXPREF(x), ARF_EXPREF(y), fix + fix2); ARF_MUL_TMP_FREE(tmp, alloc) return inexact; } flint-3.1.3/src/arf/equal.c000066400000000000000000000025251461254215100154510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_equal(const arf_t x, const arf_t y) { mp_size_t n; if (x == y) return 1; if (ARF_XSIZE(x) != ARF_XSIZE(y)) return 0; if (!fmpz_equal(ARF_EXPREF(x), ARF_EXPREF(y))) return 0; n = ARF_SIZE(x); if (n == 0) return 1; if (n == 1) return ARF_NOPTR_D(x)[0] == ARF_NOPTR_D(y)[0]; if (n == 2) return (ARF_NOPTR_D(x)[0] == ARF_NOPTR_D(y)[0] && ARF_NOPTR_D(x)[1] == ARF_NOPTR_D(y)[1]); return mpn_cmp(ARF_PTR_D(x), ARF_PTR_D(y), n) == 0; } int arf_equal_si(const arf_t x, slong y) { arf_t t; arf_init_set_si(t, y); return arf_equal(x, t); /* no need to free */ } int arf_equal_ui(const arf_t x, ulong y) { arf_t t; arf_init_set_ui(t, y); return arf_equal(x, t); /* no need to free */ } int arf_equal_d(const arf_t x, double y) { arf_t t; arf_init(t); arf_set_d(t, y); return arf_equal(x, t); /* no need to free */ } flint-3.1.3/src/arf/floor.c000066400000000000000000000020131461254215100154530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_floor(arf_t z, const arf_t x) { if (arf_is_special(x) || arf_is_int(x)) { arf_set(z, x); } else { slong exp = ARF_EXP(x); /* now exp cannot be too large, as we would have caught this in arf_is_int() */ if (COEFF_IS_MPZ(exp) || exp <= 0) { if (ARF_SGNBIT(x)) arf_set_si(z, -1); else arf_zero(z); } else if (exp == 1) { arf_set_si(z, ARF_SGNBIT(x) ? -2 : 1); } else { arf_set_round(z, x, exp, ARF_RND_FLOOR); } } } flint-3.1.3/src/arf/fma.c000066400000000000000000000041261461254215100151040ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "mpn_extras.h" int arf_fma(arf_ptr res, arf_srcptr x, arf_srcptr y, arf_srcptr z, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, tn, alloc; mp_srcptr xptr, yptr, zptr; mp_ptr tptr, tptr2; fmpz_t texp; slong shift; int tsgnbit, inexact; ARF_MUL_TMP_DECL if (arf_is_special(x) || arf_is_special(y) || arf_is_special(z)) { if (arf_is_zero(z)) { return arf_mul(res, x, y, prec, rnd); } else if (arf_is_finite(x) && arf_is_finite(y)) { return arf_set_round(res, z, prec, rnd); } else { /* todo: speed up */ arf_t t; arf_init(t); arf_mul(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(res, z, t, prec, rnd); arf_clear(t); return inexact; } } tsgnbit = ARF_SGNBIT(x) ^ ARF_SGNBIT(y); ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); ARF_GET_MPN_READONLY(zptr, zn, z); fmpz_init(texp); _fmpz_add2_fast(texp, ARF_EXPREF(x), ARF_EXPREF(y), 0); shift = _fmpz_sub_small(ARF_EXPREF(z), texp); alloc = tn = xn + yn; ARF_MUL_TMP_ALLOC(tptr2, alloc) tptr = tptr2; FLINT_MPN_MUL_WITH_SPECIAL_CASES(tptr, xptr, xn, yptr, yn); tn -= (tptr[0] == 0); tptr += (tptr[0] == 0); if (shift >= 0) inexact = _arf_add_mpn(res, zptr, zn, ARF_SGNBIT(z), ARF_EXPREF(z), tptr, tn, tsgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(res, tptr, tn, tsgnbit, texp, zptr, zn, ARF_SGNBIT(z), -shift, prec, rnd); ARF_MUL_TMP_FREE(tptr2, alloc) fmpz_clear(texp); return inexact; } flint-3.1.3/src/arf/frexp.c000066400000000000000000000010731461254215100154630ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_frexp(arf_t man, fmpz_t exp, const arf_t x) { arf_set(man, x); fmpz_zero(exp); if (!arf_is_special(man)) fmpz_swap(exp, ARF_EXPREF(man)); } flint-3.1.3/src/arf/get.c000066400000000000000000000334131461254215100151210ustar00rootroot00000000000000/* Copyright (C) 2012, 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "double_extras.h" #include "fmpq.h" #include "arf.h" /* most double: (2^53-1) * 2^971 */ /* least normal: 2^-1022 */ /* least subnormal: 2^-1074 */ static double huge_double(arf_rnd_t rnd, int negative) { double v; if (rnd == ARF_RND_NEAR || arf_rounds_up(rnd, negative)) v = D_INF; else v = ldexp(9007199254740991.0, 971); return negative ? -v : v; } static double tiny_double(arf_rnd_t rnd, int negative) { double v; if (rnd == ARF_RND_NEAR || !arf_rounds_up(rnd, negative)) v = 0.0; else v = ldexp(1.0, -1074); return negative ? -v : v; } double arf_get_d(const arf_t x, arf_rnd_t rnd) { if (arf_is_special(x)) { if (arf_is_zero(x)) return 0.0; else if (arf_is_pos_inf(x)) return D_INF; else if (arf_is_neg_inf(x)) return -D_INF; else return D_NAN; } else { arf_t t; mp_srcptr tp; mp_size_t tn; double v; /* also catches bignum exponents */ if (ARF_EXP(x) > 1030 || ARF_EXP(x) < -1080) { if (fmpz_sgn(ARF_EXPREF(x)) > 0) return huge_double(rnd, ARF_SGNBIT(x)); else return tiny_double(rnd, ARF_SGNBIT(x)); } /* allow mpfr to take care of corner cases for now */ if (ARF_EXP(x) > 1020 || ARF_EXP(x) <= -1020 || rnd == ARF_RND_NEAR) { mpfr_t xx; ARF_GET_MPN_READONLY(tp, tn, x); xx->_mpfr_d = (mp_ptr) tp; xx->_mpfr_prec = tn * FLINT_BITS; xx->_mpfr_sign = ARF_SGNBIT(x) ? -1 : 1; xx->_mpfr_exp = ARF_EXP(x); return mpfr_get_d(xx, arf_rnd_to_mpfr(rnd)); } arf_init(t); arf_set_round(t, x, 53, rnd); ARF_GET_MPN_READONLY(tp, tn, t); if (tn == 1) v = (double)(tp[0]); else v = (double)(tp[1]) + (double)(tp[0]) * ldexp(1,-32); v = d_mul_2exp(v, ARF_EXP(t) - FLINT_BITS); if (ARF_SGNBIT(t)) v = -v; arf_clear(t); return v; } } void arf_get_fmpq(fmpq_t y, const arf_t x) { if (arf_is_zero(x)) { fmpq_zero(y); } else if (arf_is_special(x) || !ARF_IS_LAGOM(x)) { flint_throw(FLINT_ERROR, "exception: arf_get_fmpq: cannot convert to rational\n"); } else { fmpz_t man, exp; slong e; fmpz_init(man); fmpz_init(exp); arf_get_fmpz_2exp(man, exp, x); e = *exp; fmpz_set_ui(fmpq_denref(y), UWORD(1)); if (e >= 0) { fmpz_mul_2exp(fmpq_numref(y), man, e); } else { fmpz_set(fmpq_numref(y), man); fmpz_mul_2exp(fmpq_denref(y), fmpq_denref(y), -e); } fmpz_clear(man); fmpz_clear(exp); } } void arf_get_fmpz_2exp(fmpz_t man, fmpz_t exp, const arf_t x) { if (arf_is_special(x)) { fmpz_zero(man); fmpz_zero(exp); } else { mp_srcptr xptr; mp_size_t xn; int shift; ARF_GET_MPN_READONLY(xptr, xn, x); shift = flint_ctz(xptr[0]); fmpz_sub_ui(exp, ARF_EXPREF(x), xn * FLINT_BITS - shift); if (xn == 1) { if (ARF_SGNBIT(x)) fmpz_neg_ui(man, xptr[0] >> shift); else fmpz_set_ui(man, xptr[0] >> shift); } else { __mpz_struct * z = _fmpz_promote(man); if (z->_mp_alloc < xn) mpz_realloc(z, xn); if (shift == 0) flint_mpn_copyi(z->_mp_d, xptr, xn); else mpn_rshift(z->_mp_d, xptr, xn, shift); /* top limb cannot be zero */ z->_mp_size = ARF_SGNBIT(x) ? -xn : xn; } } } int arf_get_fmpz(fmpz_t z, const arf_t x, arf_rnd_t rnd) { slong exp; int negative, inexact, value, roundup; mp_size_t xn, zn; mp_srcptr xp; __mpz_struct * zz; mp_ptr zp; mp_limb_t v, v2, v3; if (arf_is_special(x)) { if (arf_is_zero(x)) { fmpz_zero(z); return 0; } else { flint_throw(FLINT_ERROR, "arf_get_fmpz: cannot convert infinity or nan to integer\n"); } } exp = ARF_EXP(x); negative = ARF_SGNBIT(x); if (COEFF_IS_MPZ(exp)) { /* tiny */ if (fmpz_sgn(ARF_EXPREF(x)) < 0) { if (rnd == ARF_RND_NEAR || rnd == ARF_RND_DOWN || (rnd == ARF_RND_FLOOR && !negative) || (rnd == ARF_RND_CEIL && negative)) { fmpz_zero(z); } else { fmpz_set_si(z, negative ? -1 : 1); } return 1; } else { flint_throw(FLINT_ERROR, "arf_get_fmpz: number too large to convert to integer\n"); } } /* |x| < 1 */ if (exp <= 0) { if (rnd == ARF_RND_NEAR) { if (exp == 0) { /* check for the special case +/- 1/2 */ ARF_GET_MPN_READONLY(xp, xn, x); if (xp[xn - 1] < LIMB_TOP || (xn == 1 && xp[xn - 1] == LIMB_TOP)) value = 0; else value = negative ? -1 : 1; } else { value = 0; } } else if (rnd == ARF_RND_DOWN || (rnd == ARF_RND_FLOOR && !negative) || (rnd == ARF_RND_CEIL && negative)) { value = 0; } else { value = negative ? -1 : 1; } _fmpz_demote(z); *z = value; return 1; } ARF_GET_MPN_READONLY(xp, xn, x); /* Fast case: |x| < 2^31 or 2^63 (must save 1 bit for rounding up!) */ if (exp < FLINT_BITS) { v = xp[xn - 1]; v2 = v >> (FLINT_BITS - exp); /* integral part */ v3 = v << exp; /* fractional part (truncated, at least 1 bit) */ inexact = (xn > 1) || (v3 != 0); if (inexact && rnd != ARF_RND_DOWN) { if (rnd == ARF_RND_NEAR) { /* round up of fractional part is > 1/2, or if equal to 1/2 and the integral part is odd */ v2 += (v3 > LIMB_TOP) || (v3 == LIMB_TOP && (xn > 1 || (v2 & 1))); } else { v2 += (rnd == ARF_RND_UP) || (negative ^ (rnd == ARF_RND_CEIL)); } } if (negative) fmpz_neg_ui(z, v2); else fmpz_set_ui(z, v2); return inexact; } /* |x| >= 1 */ /* Allocate space for result + 1 extra bit. We need one extra bit temporarily to check rounding to nearest. We also need one extra bit to round up. */ zn = (exp + (rnd != ARF_RND_DOWN) + FLINT_BITS - 1) / FLINT_BITS; zz = _fmpz_promote(z); if (zz->_mp_alloc < zn) mpz_realloc2(zz, zn * FLINT_BITS); zp = zz->_mp_d; if (rnd == ARF_RND_DOWN) { /* zn is the exact size */ inexact = _arf_get_integer_mpn(zp, xp, xn, exp); } else { zp[zn - 1] = 0; inexact = _arf_get_integer_mpn(zp, xp, xn, exp + (rnd == ARF_RND_NEAR)); if (rnd == ARF_RND_NEAR) { v = zp[0]; /* round up if fractional part is >= 1/2 and (there are more discarded bits, or the truncated value would be odd) */ roundup = (v & 1) & (inexact | (v >> 1)); inexact |= (v & 1); mpn_rshift(zp, zp, zn, 1); mpn_add_1(zp, zp, zn, roundup); } else if (inexact && ((rnd == ARF_RND_UP) || (negative ^ (rnd == ARF_RND_CEIL)))) { mpn_add_1(zp, zp, zn, 1); } zn -= (zp[zn - 1] == 0); } zz->_mp_size = negative ? -zn : zn; _fmpz_demote_val(z); return inexact; } int arf_get_fmpz_fixed_fmpz(fmpz_t y, const arf_t x, const fmpz_t e) { if (arf_is_special(x)) { return arf_get_fmpz(y, x, ARF_RND_DOWN); } else { int inexact; fmpz_t exp; arf_t tmp; fmpz_init(exp); fmpz_sub(exp, ARF_EXPREF(x), e); arf_init_set_shallow(tmp, x); ARF_EXP(tmp) = *exp; inexact = arf_get_fmpz(y, tmp, ARF_RND_DOWN); fmpz_clear(exp); return inexact; } } int arf_get_fmpz_fixed_si(fmpz_t y, const arf_t x, slong e) { if (arf_is_special(x)) { return arf_get_fmpz(y, x, ARF_RND_DOWN); } else { int inexact; fmpz_t exp; arf_t tmp; fmpz_init(exp); fmpz_sub_si(exp, ARF_EXPREF(x), e); arf_init_set_shallow(tmp, x); ARF_EXP(tmp) = *exp; inexact = arf_get_fmpz(y, tmp, ARF_RND_DOWN); fmpz_clear(exp); return inexact; } } int _arf_get_integer_mpn(mp_ptr y, mp_srcptr x, mp_size_t xn, slong exp) { slong bot_exp = exp - xn * FLINT_BITS; if (bot_exp >= 0) { mp_size_t bot_limbs; flint_bitcnt_t bot_bits; bot_limbs = bot_exp / FLINT_BITS; bot_bits = bot_exp % FLINT_BITS; flint_mpn_zero(y, bot_limbs); if (bot_bits == 0) flint_mpn_copyi(y + bot_limbs, x, xn); else y[bot_limbs + xn] = mpn_lshift(y + bot_limbs, x, xn, bot_bits); /* exact */ return 0; } else if (exp <= 0) { /* inexact */ return 1; } else { mp_size_t top_limbs; flint_bitcnt_t top_bits; mp_limb_t cy; top_limbs = exp / FLINT_BITS; top_bits = exp % FLINT_BITS; if (top_bits == 0) { flint_mpn_copyi(y, x + xn - top_limbs, top_limbs); /* inexact */ return 1; } else { /* can be inexact */ cy = mpn_rshift(y, x + xn - top_limbs - 1, top_limbs + 1, FLINT_BITS - top_bits); return (cy != 0) || (top_limbs + 1 != xn); } } } void arf_get_mag(mag_t y, const arf_t x) { if (arf_is_zero(x)) { mag_zero(y); } else if (arf_is_special(x)) { mag_inf(y); } else { mp_limb_t t, u; ARF_GET_TOP_LIMB(t, x); t = (t >> (FLINT_BITS - MAG_BITS)) + LIMB_ONE; /* may have rounded up to next power of two */ u = t >> MAG_BITS; /* todo: avoid the addition? check agreement with mag_fast_init_set_arf */ t = (t >> u) + (u & t); _fmpz_add_fast(MAG_EXPREF(y), ARF_EXPREF(x), u); MAG_MAN(y) = t; } } void arf_get_mag_lower(mag_t y, const arf_t x) { if (arf_is_zero(x)) { mag_zero(y); } else if (arf_is_special(x)) { if (arf_is_nan(x)) mag_zero(y); else mag_inf(y); } else { mp_limb_t t; ARF_GET_TOP_LIMB(t, x); MAG_MAN(y) = t >> (FLINT_BITS - MAG_BITS); _fmpz_set_fast(MAG_EXPREF(y), ARF_EXPREF(x)); } } int arf_get_mpfr(mpfr_t x, const arf_t y, mpfr_rnd_t rnd) { int r; if (arf_is_special(y)) { if (arf_is_zero(y)) mpfr_set_zero(x, 0); else if (arf_is_pos_inf(y)) mpfr_set_inf(x, 1); else if (arf_is_neg_inf(y)) mpfr_set_inf(x, -1); else mpfr_set_nan(x); r = 0; } else if (COEFF_IS_MPZ(*ARF_EXPREF(y))) { /* Incidentally, COEFF_MIN and COEFF_MAX are exactly the same as the minimum and maximum allowed MPFR exponents. We assert this to make sure the following code is valid. Unfortunately, MPFR provides no convenient function to assign a big exponent with automatic underflow/overflow. */ if (COEFF_MIN > mpfr_get_emin_min() || COEFF_MAX < mpfr_get_emax_max()) { flint_throw(FLINT_ERROR, "unsupported MPFR exponent range: %wd, %wd, %wd, %wd\n", COEFF_MIN, mpfr_get_emin_min(), COEFF_MAX, mpfr_get_emax_max()); } if (fmpz_sgn(ARF_EXPREF(y)) > 0) { if (arf_sgn(y) > 0) { mpfr_set_inf(x, 1); mpfr_nextbelow(x); } else { mpfr_set_inf(x, -1); mpfr_nextabove(x); } r = mpfr_mul_2si(x, x, 1, rnd); } else { if (arf_sgn(y) > 0) { mpfr_set_zero(x, 1); mpfr_nextabove(x); } else { mpfr_set_zero(x, -1); mpfr_nextbelow(x); } r = mpfr_mul_2si(x, x, -1, rnd); } } else { __mpfr_struct t; mp_size_t n; mp_srcptr d; ARF_GET_MPN_READONLY(d, n, y); t._mpfr_d = (mp_ptr) d; t._mpfr_exp = ARF_EXP(y); t._mpfr_prec = n * FLINT_BITS; t._mpfr_sign = ARF_SGNBIT(y) ? -1 : 1; r = mpfr_set(x, &t, rnd); } return r; } slong arf_get_si(const arf_t x, arf_rnd_t rnd) { fmpz_t t; slong v; fmpz_init(t); arf_get_fmpz(t, x, rnd); if (!fmpz_fits_si(t)) { flint_throw(FLINT_ERROR, "arf_get_si: result does not fit in a signed slong\n"); } v = fmpz_get_si(t); fmpz_clear(t); return v; } flint-3.1.3/src/arf/inlines.c000066400000000000000000000006461461254215100160050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ARF_INLINES_C #include "arf.h" flint-3.1.3/src/arf/io.c000066400000000000000000000132461461254215100147530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2015 Arb authors Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "arf.h" #include "arb.h" /* strings ********************************************************************/ static void arf_set_fmpz_2exp_dump(arf_t x, const fmpz_t m, const fmpz_t e) { if (fmpz_is_zero(m)) { if (fmpz_get_si(e) == 0) arf_zero(x); else if (fmpz_get_si(e) == -1) arf_pos_inf(x); else if (fmpz_get_si(e) == -2) arf_neg_inf(x); else if (fmpz_get_si(e) == -3) arf_nan(x); else { /* Impossible to happen; all the special values have been treated above. */ flint_throw(FLINT_ERROR, "(%s)\n", __func__); } return; } arf_set_fmpz_2exp(x, m, e); } static void arf_get_fmpz_2exp_dump(fmpz_t m, fmpz_t e, const arf_t x) { if (arf_is_special(x)) { fmpz_zero(m); if (arf_is_zero(x)) fmpz_zero(e); else if (arf_is_pos_inf(x)) fmpz_set_si(e, -1); else if (arf_is_neg_inf(x)) fmpz_set_si(e, -2); else if (arf_is_nan(x)) fmpz_set_si(e, -3); else { /* Impossible to happen; all the special values have been treated above. */ flint_throw(FLINT_ERROR, "(%s)\n", __func__); } return; } arf_get_fmpz_2exp(m, e, x); } char * arf_get_str(const arf_t x, slong d) { if (arf_is_special(x)) { char * s = flint_malloc(5); if (arf_is_zero(x)) strcpy(s, "0"); else if (arf_is_pos_inf(x)) strcpy(s, "+inf"); else if (arf_is_neg_inf(x)) strcpy(s, "-inf"); else strcpy(s, "nan"); return s; } else { arb_t t; *arb_midref(t) = *x; mag_init(arb_radref(t)); /* no need to free */ return arb_get_str(t, FLINT_MAX(d, 1), ARB_STR_NO_RADIUS); } } int arf_load_str(arf_t x, const char* data) { fmpz_t mantissa, exponent; char * e_str; char * m_str; int err = 0; fmpz_init(mantissa); fmpz_init(exponent); e_str = strchr(data, ' '); if (e_str == NULL) return 1; m_str = (char*)flint_malloc(e_str - data + 1); strncpy(m_str, data, e_str - data); m_str[e_str - data] = '\0'; e_str++; err = fmpz_set_str(mantissa, m_str, 16); flint_free(m_str); if (err) { fmpz_clear(exponent); fmpz_clear(mantissa); return err; } err = fmpz_set_str(exponent, e_str, 16); if (err) { fmpz_clear(exponent); fmpz_clear(mantissa); return err; } arf_set_fmpz_2exp_dump(x, mantissa, exponent); fmpz_clear(exponent); fmpz_clear(mantissa); return err; } char * arf_dump_str(const arf_t x) { size_t res_len; char * res; fmpz_t mantissa, exponent; fmpz_init(mantissa); fmpz_init(exponent); arf_get_fmpz_2exp_dump(mantissa, exponent, x); res_len = (fmpz_sgn(mantissa) < 0) + fmpz_sizeinbase(mantissa, 16) + 1 + (fmpz_sgn(exponent) < 0) + fmpz_sizeinbase(exponent, 16); res = (char*)flint_malloc(res_len + 1); fmpz_get_str(res, 16, mantissa); strcat(res, " "); fmpz_get_str(res + strlen(res), 16, exponent); fmpz_clear(mantissa); fmpz_clear(exponent); if (strlen(res) != res_len) flint_throw(FLINT_ERROR, "(%s): strlen(res) != res_len\n", __func__); return res; } /* printing *******************************************************************/ void arf_fprint(FILE * file, const arf_t x) { if (arf_is_normal(x)) { fmpz_t man, exp; fmpz_init(man); fmpz_init(exp); arf_get_fmpz_2exp(man, exp, x); flint_fprintf(file, "("); fmpz_fprint(file, man); flint_fprintf(file, " * 2^"); fmpz_fprint(file, exp); flint_fprintf(file, ")"); fmpz_clear(man); fmpz_clear(exp); } else { if (arf_is_zero(x)) flint_fprintf(file, "(0)"); else if (arf_is_pos_inf(x)) flint_fprintf(file, "(+inf)"); else if (arf_is_neg_inf(x)) flint_fprintf(file, "(-inf)"); else flint_fprintf(file, "(nan)"); } } void arf_fprintd(FILE * file, const arf_t x, slong d) { char * s = arf_get_str(x, d); fprintf(file, "%s", s); flint_free(s); } void arf_print(const arf_t x) { arf_fprint(stdout, x); } void arf_printd(const arf_t y, slong d) { arf_fprintd(stdout, y, d); } /* file I/O *******************************************************************/ int arf_load_file(arf_t x, FILE * stream) { fmpz_t mantissa, exponent; __mpz_struct *mpz_mantissa, *mpz_exponent; int err; fmpz_init(mantissa); fmpz_init(exponent); mpz_mantissa = _fmpz_promote(mantissa); mpz_exponent = _fmpz_promote(exponent); err = 0; if (mpz_inp_str(mpz_mantissa, stream, 16) == 0) err = 1; if (!err && mpz_inp_str(mpz_exponent, stream, 16) == 0) err = 1; _fmpz_demote_val(mantissa); _fmpz_demote_val(exponent); if (!err) arf_set_fmpz_2exp_dump(x, mantissa, exponent); fmpz_clear(mantissa); fmpz_clear(exponent); return err; } int arf_dump_file(FILE * stream, const arf_t x) { int nwrite; char* data = arf_dump_str(x); nwrite = fputs(data, stream); if (nwrite == EOF) return nwrite; flint_free(data); return 0; } flint-3.1.3/src/arf/is_int.c000066400000000000000000000013661461254215100156310ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_is_int(const arf_t x) { mp_size_t xn; mp_srcptr xp; slong exp, c; exp = ARF_EXP(x); if (ARF_IS_SPECIAL(x)) return exp == ARF_EXP_ZERO; if (COEFF_IS_MPZ(exp)) return mpz_sgn(COEFF_TO_PTR(exp)) > 0; ARF_GET_MPN_READONLY(xp, xn, x); c = flint_ctz(xp[0]); return exp - xn * FLINT_BITS + c >= 0; } flint-3.1.3/src/arf/is_int_2exp_si.c000066400000000000000000000012561461254215100172600ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_is_int_2exp_si(const arf_t x, slong e) { if (arf_is_special(x)) return arf_is_zero(x); else { fmpz_t t; int r; fmpz_init(t); arf_bot(t, x); r = fmpz_cmp_si(t, e) >= 0; fmpz_clear(t); return r; } } flint-3.1.3/src/arf/memory_manager.c000066400000000000000000000042541461254215100173450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #define ARF_USE_CACHE 0 #define ARF_MAX_CACHE_LIMBS 64 FLINT_TLS_PREFIX mp_ptr * arf_free_arr = NULL; FLINT_TLS_PREFIX ulong arf_free_num = 0; FLINT_TLS_PREFIX ulong arf_free_alloc = 0; FLINT_TLS_PREFIX int arf_have_registered_cleanup = 0; void _arf_cleanup(void) { slong i; for (i = 0; i < arf_free_num; i++) flint_free(arf_free_arr[i]); flint_free(arf_free_arr); arf_free_arr = NULL; arf_free_num = 0; arf_free_alloc = 0; } void _arf_promote(arf_t x, mp_size_t n) { if (ARF_USE_CACHE && n <= ARF_MAX_CACHE_LIMBS && arf_free_num != 0) { mp_ptr ptr; mp_size_t alloc; ptr = arf_free_arr[--arf_free_num]; alloc = ptr[0]; if (alloc >= n) { ARF_PTR_ALLOC(x) = ptr[0]; ARF_PTR_D(x) = ptr; } else { ptr = flint_realloc(ptr, n * sizeof(mp_limb_t)); ARF_PTR_ALLOC(x) = n; ARF_PTR_D(x) = ptr; } } else { ARF_PTR_ALLOC(x) = n; ARF_PTR_D(x) = flint_malloc(n * sizeof(mp_limb_t)); } } void _arf_demote(arf_t x) { mp_ptr ptr; mp_size_t alloc; alloc = ARF_PTR_ALLOC(x); ptr = ARF_PTR_D(x); if (ARF_USE_CACHE && alloc <= ARF_MAX_CACHE_LIMBS) { if (arf_free_num == arf_free_alloc) { if (!arf_have_registered_cleanup) { flint_register_cleanup_function(_arf_cleanup); arf_have_registered_cleanup = 1; } arf_free_alloc = FLINT_MAX(64, arf_free_alloc * 2); arf_free_arr = flint_realloc(arf_free_arr, arf_free_alloc * sizeof(mp_ptr)); } ptr[0] = alloc; arf_free_arr[arf_free_num++] = ptr; } else { flint_free(ptr); } } flint-3.1.3/src/arf/mul_rnd_any.c000066400000000000000000000027141461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "mpn_extras.h" int arf_mul_rnd_any(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; slong fix; int sgnbit, inexact; xn = ARF_XSIZE(x); yn = ARF_XSIZE(y); sgnbit = (xn ^ yn) & 1; xn >>= 1; yn >>= 1; if (yn > xn) { FLINT_SWAP(arf_srcptr, x, y); FLINT_SWAP(mp_size_t, xn, yn); } /* Either operand is a special value. */ if (yn == 0) { arf_mul_special(z, x, y); return 0; } else { mp_size_t zn, alloc; mp_srcptr xptr, yptr; mp_ptr tmp; ARF_MUL_TMP_DECL ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); alloc = zn = xn + yn; ARF_MUL_TMP_ALLOC(tmp, alloc) FLINT_MPN_MUL_WITH_SPECIAL_CASES(tmp, xptr, xn, yptr, yn); inexact = _arf_set_round_mpn(z, &fix, tmp, zn, sgnbit, prec, rnd); _fmpz_add2_fast(ARF_EXPREF(z), ARF_EXPREF(x), ARF_EXPREF(y), fix); ARF_MUL_TMP_FREE(tmp, alloc) return inexact; } } flint-3.1.3/src/arf/mul_rnd_down.c000066400000000000000000000151351461254215100170320ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "mpn_extras.h" int arf_mul_rnd_down(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec) { mp_size_t xn, yn, zn; mp_limb_t hi, lo; slong expfix; int sgnbit, ret, fix; mp_ptr zptr; xn = ARF_XSIZE(x); yn = ARF_XSIZE(y); sgnbit = (xn ^ yn) & 1; xn >>= 1; yn >>= 1; if (yn > xn) { FLINT_SWAP(arf_srcptr, x, y); FLINT_SWAP(mp_size_t, xn, yn); } /* Either operand is a special value. */ if (yn == 0) { arf_mul_special(z, x, y); return 0; } /* xn == yn == 1 */ if (xn == 1) { lo = ARF_NOPTR_D(x)[0]; hi = ARF_NOPTR_D(y)[0]; umul_ppmm(hi, lo, hi, lo); /* Shift so that the top bit is set (branch free version). */ fix = !(hi >> (FLINT_BITS - 1)); hi = (hi << fix) | ((lo >> (FLINT_BITS - 1)) & fix); lo = (lo << fix); ARF_DEMOTE(z); if (lo == 0) { zn = 1; if (prec >= FLINT_BITS) { lo = hi; ret = 0; } else { lo = MASK_LIMB(hi, FLINT_BITS - prec); ret = (lo != hi); } } else { zn = 2; if (prec <= FLINT_BITS) /* Must be inexact. */ { lo = MASK_LIMB(hi, FLINT_BITS - prec); zn = ret = 1; } else if (prec >= 2 * FLINT_BITS) /* Must be exact. */ { ret = 0; } else /* prec < FLINT_BITS < 2 * FLINT_BITS */ { ret = MASK_LIMB(lo, 2 * FLINT_BITS - prec) != lo; lo = MASK_LIMB(lo, 2 * FLINT_BITS - prec); if (lo == 0) { zn = 1; lo = hi; } } } _fmpz_add2_fast(ARF_EXPREF(z), ARF_EXPREF(x), ARF_EXPREF(y), -fix); ARF_XSIZE(z) = ARF_MAKE_XSIZE(zn, sgnbit); zptr = ARF_NOPTR_D(z); zptr[0] = lo; zptr[1] = hi; return ret; } else if (xn == 2) { mp_limb_t zz[4]; mp_limb_t x1, x0, y1, y0; x0 = ARF_NOPTR_D(x)[0]; x1 = ARF_NOPTR_D(x)[1]; if (yn == 2) { y0 = ARF_NOPTR_D(y)[0]; y1 = ARF_NOPTR_D(y)[1]; FLINT_MPN_MUL_2X2(zz[3], zz[2], zz[1], zz[0], x1, x0, y1, y0); /* Likely case, must be inexact */ if (prec <= 2 * FLINT_BITS) { ARF_DEMOTE(z); fix = !(zz[3] >> (FLINT_BITS - 1)); zz[3] = (zz[3] << fix) | ((zz[2] >> (FLINT_BITS - 1)) & fix); zz[2] = (zz[2] << fix) | ((zz[1] >> (FLINT_BITS - 1)) & fix); _fmpz_add2_fast(ARF_EXPREF(z), ARF_EXPREF(x), ARF_EXPREF(y), -fix); /* Rounding */ if (prec != 2 * FLINT_BITS) { if (prec > FLINT_BITS) { zz[2] &= (LIMB_ONES << (2 * FLINT_BITS - prec)); } else if (prec == FLINT_BITS) { zz[2] = 0; } else { zz[3] &= (LIMB_ONES << (FLINT_BITS - prec)); zz[2] = 0; } } if (zz[2] == 0) { ARF_XSIZE(z) = ARF_MAKE_XSIZE(1, sgnbit); ARF_NOPTR_D(z)[0] = zz[3]; } else { ARF_XSIZE(z) = ARF_MAKE_XSIZE(2, sgnbit); ARF_NOPTR_D(z)[0] = zz[2]; ARF_NOPTR_D(z)[1] = zz[3]; } return 1; } } else { y0 = ARF_NOPTR_D(y)[0]; FLINT_MPN_MUL_2X1(zz[2], zz[1], zz[0], x1, x0, y0); } zn = xn + yn; ret = _arf_set_round_mpn(z, &expfix, zz, zn, sgnbit, prec, ARF_RND_DOWN); _fmpz_add2_fast(ARF_EXPREF(z), ARF_EXPREF(x), ARF_EXPREF(y), expfix); return ret; } else if (yn > MUL_MPFR_MIN_LIMBS && prec != ARF_PREC_EXACT && xn + yn > 1.25 * prec / FLINT_BITS && xn < MUL_MPFR_MAX_LIMBS) /* FIXME: proper cutoffs */ { return arf_mul_via_mpfr(z, x, y, prec, ARF_RND_DOWN); } else { mp_size_t zn, alloc; mp_srcptr xptr, yptr; mp_ptr tmp; ARF_MUL_TMP_DECL ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); alloc = zn = xn + yn; ARF_MUL_TMP_ALLOC(tmp, alloc) FLINT_MPN_MUL_WITH_SPECIAL_CASES(tmp, xptr, xn, yptr, yn); ret = _arf_set_round_mpn(z, &expfix, tmp, zn, sgnbit, prec, ARF_RND_DOWN); _fmpz_add2_fast(ARF_EXPREF(z), ARF_EXPREF(x), ARF_EXPREF(y), expfix); ARF_MUL_TMP_FREE(tmp, alloc) return ret; } } int arf_mul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; slong fix, shift; int sgnbit, inexact; yn = FLINT_ABS(y->_mp_size); xn = ARF_XSIZE(x); xn >>= 1; sgnbit = ARF_SGNBIT(x) ^ (y->_mp_size < 0); /* Either operand is a special value. */ if (xn == 0 || yn == 0) { if (arf_is_finite(x)) { arf_zero(z); } else { arf_t t; arf_init_set_si(t, mpz_sgn(y)); arf_mul(z, x, t, prec, rnd); arf_clear(t); } return 0; } else { mp_size_t zn, alloc; mp_srcptr xptr, yptr; mp_ptr tmp; ARF_MUL_TMP_DECL ARF_GET_MPN_READONLY(xptr, xn, x); yptr = y->_mp_d; alloc = zn = xn + yn; ARF_MUL_TMP_ALLOC(tmp, alloc) FLINT_MPN_MUL_WITH_SPECIAL_CASES(tmp, xptr, xn, yptr, yn); shift = yn * FLINT_BITS - (tmp[zn - 1] == 0) * FLINT_BITS; zn -= (tmp[zn - 1] == 0); inexact = _arf_set_round_mpn(z, &fix, tmp, zn, sgnbit, prec, rnd); _fmpz_add_fast(ARF_EXPREF(z), ARF_EXPREF(x), fix + shift); ARF_MUL_TMP_FREE(tmp, alloc) return inexact; } } flint-3.1.3/src/arf/mul_special.c000066400000000000000000000015671461254215100166440ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_mul_special(arf_t z, const arf_t x, const arf_t y) { if (arf_is_zero(x)) { if (arf_is_finite(y)) arf_zero(z); else arf_nan(z); } else if (arf_is_zero(y)) { if (arf_is_finite(x)) arf_zero(z); else arf_nan(z); } else if (arf_is_nan(x) || arf_is_nan(y)) arf_nan(z); else if (arf_sgn(x) == arf_sgn(y)) arf_pos_inf(z); else arf_neg_inf(z); } flint-3.1.3/src/arf/mul_tmp_cleanup.c000066400000000000000000000011421461254215100175200ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" FLINT_TLS_PREFIX mp_ptr __arf_mul_tmp = NULL; FLINT_TLS_PREFIX slong __arf_mul_alloc = 0; void _arf_mul_tmp_cleanup(void) { flint_free(__arf_mul_tmp); __arf_mul_tmp = NULL; __arf_mul_alloc = 0; } flint-3.1.3/src/arf/mul_via_mpfr.c000066400000000000000000000035231461254215100170210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arf.h" int arf_mul_via_mpfr(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, val; mp_srcptr xptr, yptr; mp_ptr tmp, zptr; mpfr_t xf, yf, zf; int ret; ARF_MUL_TMP_DECL if (arf_is_special(x) || arf_is_special(y)) { arf_mul_special(z, x, y); return 0; } ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); prec = FLINT_MIN((xn + yn) * FLINT_BITS, prec); zn = (prec + FLINT_BITS - 1) / FLINT_BITS; ARF_MUL_TMP_ALLOC(tmp, zn) zf->_mpfr_d = tmp; zf->_mpfr_prec = prec; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; xf->_mpfr_d = (mp_ptr) xptr; xf->_mpfr_prec = xn * FLINT_BITS; xf->_mpfr_sign = ARF_SGNBIT(x) ? -1 : 1; xf->_mpfr_exp = 0; if (x == y) { ret = mpfr_sqr(zf, xf, arf_rnd_to_mpfr(rnd)); } else { yf->_mpfr_d = (mp_ptr) yptr; yf->_mpfr_prec = yn * FLINT_BITS; yf->_mpfr_sign = ARF_SGNBIT(y) ? -1 : 1; yf->_mpfr_exp = 0; ret = mpfr_mul(zf, xf, yf, arf_rnd_to_mpfr(rnd)); } ret = (ret != 0); _fmpz_add2_fast(ARF_EXPREF(z), ARF_EXPREF(x), ARF_EXPREF(y), zf->_mpfr_exp); val = 0; while (tmp[val] == 0) val++; ARF_GET_MPN_WRITE(zptr, zn - val, z); flint_mpn_copyi(zptr, tmp + val, zn - val); ARF_XSIZE(z) |= (zf->_mpfr_sign < 0); ARF_MUL_TMP_FREE(tmp, zn) return ret; } flint-3.1.3/src/arf/neg_round.c000066400000000000000000000020341461254215100163150ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_neg_round(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { if (arf_is_special(x)) { arf_neg(y, x); return 0; } else { int inexact; slong fix; mp_size_t xn; mp_srcptr xptr; if (y == x) { ARF_NEG(y); return arf_set_round(y, y, prec, rnd); } else { ARF_GET_MPN_READONLY(xptr, xn, x); inexact = _arf_set_round_mpn(y, &fix, xptr, xn, !ARF_SGNBIT(x), prec, rnd); _fmpz_add_fast(ARF_EXPREF(y), ARF_EXPREF(x), fix); return inexact; } } } flint-3.1.3/src/arf/randtest.c000066400000000000000000000025521461254215100161660ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_randtest(arf_t x, flint_rand_t state, slong bits, slong mag_bits) { fmpz_t t; fmpz_init(t); fmpz_randtest(t, state, bits); arf_set_fmpz(x, t); if (!arf_is_zero(x)) fmpz_randtest(ARF_EXPREF(x), state, mag_bits); fmpz_clear(t); } void arf_randtest_not_zero(arf_t x, flint_rand_t state, slong bits, slong mag_bits) { fmpz_t t; fmpz_init(t); fmpz_randtest_not_zero(t, state, bits); arf_set_fmpz(x, t); fmpz_randtest(ARF_EXPREF(x), state, mag_bits); fmpz_clear(t); } void arf_randtest_special(arf_t x, flint_rand_t state, slong bits, slong mag_bits) { switch (n_randint(state, 32)) { case 0: arf_zero(x); break; case 1: arf_pos_inf(x); break; case 2: arf_neg_inf(x); break; case 3: arf_nan(x); break; default: arf_randtest_not_zero(x, state, bits, mag_bits); } } flint-3.1.3/src/arf/root.c000066400000000000000000000037061461254215100153270ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arf.h" int arf_root(arf_ptr z, arf_srcptr x, ulong k, slong prec, arf_rnd_t rnd) { mp_size_t xn, zn, val; mp_srcptr xptr; mp_ptr tmp, zptr; mpfr_t xf, zf; fmpz_t q, r; int inexact; if (k == 0) { arf_nan(z); return 0; } if (k == 1) return arf_set_round(z, x, prec, rnd); if (k == 2) return arf_sqrt(z, x, prec, rnd); if (arf_is_special(x)) { if (arf_is_neg_inf(x)) arf_nan(z); else arf_set(z, x); return 0; } if (ARF_SGNBIT(x)) { arf_nan(z); return 0; } fmpz_init(q); fmpz_init(r); /* x = m * 2^e where e = qk + r */ /* x^(1/k) = (m * 2^(qk+r))^(1/k) */ /* x^(1/k) = (m * 2^r)^(1/k) * 2^q */ fmpz_set_ui(r, k); fmpz_fdiv_qr(q, r, ARF_EXPREF(x), r); ARF_GET_MPN_READONLY(xptr, xn, x); zn = (prec + FLINT_BITS - 1) / FLINT_BITS; zf->_mpfr_d = tmp = flint_malloc(zn * sizeof(mp_limb_t)); zf->_mpfr_prec = prec; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; xf->_mpfr_d = (mp_ptr) xptr; xf->_mpfr_prec = xn * FLINT_BITS; xf->_mpfr_sign = 1; xf->_mpfr_exp = fmpz_get_ui(r); inexact = mpfr_rootn_ui(zf, xf, k, arf_rnd_to_mpfr(rnd)); inexact = (inexact != 0); val = 0; while (tmp[val] == 0) val++; ARF_GET_MPN_WRITE(zptr, zn - val, z); flint_mpn_copyi(zptr, tmp + val, zn - val); fmpz_add_si(ARF_EXPREF(z), q, zf->_mpfr_exp); flint_free(tmp); fmpz_clear(q); fmpz_clear(r); return inexact; } flint-3.1.3/src/arf/rsqrt.c000066400000000000000000000037471461254215100155240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arf.h" int arf_rsqrt(arf_ptr z, arf_srcptr x, slong prec, arf_rnd_t rnd) { mp_size_t xn, zn, val; mp_srcptr xptr; mp_ptr tmp, zptr; mpfr_t xf, zf; int inexact, odd_exp; ARF_MUL_TMP_DECL if (arf_is_special(x)) { if (arf_is_zero(x)) arf_pos_inf(z); else if (arf_is_pos_inf(x)) arf_zero(z); else arf_nan(z); return 0; } if (ARF_SGNBIT(x)) { arf_nan(z); return 0; } if (ARF_IS_POW2(x) && fmpz_is_odd(ARF_EXPREF(x))) { arf_set(z, x); fmpz_neg(ARF_EXPREF(z), ARF_EXPREF(z)); fmpz_cdiv_q_2exp(ARF_EXPREF(z), ARF_EXPREF(z), 1); fmpz_add_ui(ARF_EXPREF(z), ARF_EXPREF(z), 1); return 0; } ARF_GET_MPN_READONLY(xptr, xn, x); odd_exp = fmpz_is_odd(ARF_EXPREF(x)) ? 1 : 0; zn = (prec + FLINT_BITS - 1) / FLINT_BITS; ARF_MUL_TMP_ALLOC(tmp, zn) zf->_mpfr_d = tmp; zf->_mpfr_prec = prec; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; xf->_mpfr_d = (mp_ptr) xptr; xf->_mpfr_prec = xn * FLINT_BITS; xf->_mpfr_sign = 1; xf->_mpfr_exp = odd_exp; inexact = mpfr_rec_sqrt(zf, xf, arf_rnd_to_mpfr(rnd)); inexact = (inexact != 0); val = 0; while (tmp[val] == 0) val++; ARF_GET_MPN_WRITE(zptr, zn - val, z); flint_mpn_copyi(zptr, tmp + val, zn - val); fmpz_fdiv_q_2exp(ARF_EXPREF(z), ARF_EXPREF(x), 1); fmpz_neg(ARF_EXPREF(z), ARF_EXPREF(z)); fmpz_add_si(ARF_EXPREF(z), ARF_EXPREF(z), zf->_mpfr_exp); ARF_MUL_TMP_FREE(tmp, zn) return inexact; } flint-3.1.3/src/arf/set.c000066400000000000000000000102131461254215100151260ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "double_extras.h" #include "arf.h" void arf_set(arf_t y, const arf_t x) { if (x != y) { /* Fast path */ if (!COEFF_IS_MPZ(ARF_EXP(x)) && !COEFF_IS_MPZ(ARF_EXP(y))) ARF_EXP(y) = ARF_EXP(x); else fmpz_set(ARF_EXPREF(y), ARF_EXPREF(x)); /* Fast path */ if (!ARF_HAS_PTR(x)) { ARF_DEMOTE(y); (y)->d = (x)->d; } else { mp_ptr yptr; mp_srcptr xptr; mp_size_t n; ARF_GET_MPN_READONLY(xptr, n, x); ARF_GET_MPN_WRITE(yptr, n, y); flint_mpn_copyi(yptr, xptr, n); } /* Important. */ ARF_XSIZE(y) = ARF_XSIZE(x); } } void arf_set_d(arf_t x, double v) { #if FLINT_BITS == 64 mp_limb_t h, sign, exp, frac; slong real_exp, real_man; union { double uf; mp_limb_t ul; } u; u.uf = v; h = u.ul; sign = h >> 63; exp = (h << 1) >> 53; frac = (h << 12) >> 12; if (exp == 0 && frac == 0) { arf_zero(x); return; } else if (exp == 0x7ff) { if (frac == 0) { if (sign) arf_neg_inf(x); else arf_pos_inf(x); } else { arf_nan(x); } return; } /* handle subnormals */ if (exp == 0 && frac != 0) { int exp2; v = frexp(v, &exp2); u.uf = v; h = u.ul; sign = h >> 63; exp = (h << 1) >> 53; frac = (h << 12) >> 12; exp += exp2; } real_exp = exp - 1023 - 52; frac |= (UWORD(1) << 52); real_man = sign ? (-frac) : frac; arf_set_si_2exp_si(x, real_man, real_exp); #else mpfr_t t; mp_limb_t tmp[2]; t->_mpfr_prec = 53; t->_mpfr_sign = 1; t->_mpfr_exp = 0; t->_mpfr_d = tmp; mpfr_set_d(t, v, MPFR_RNDD); arf_set_mpfr(x, t); #endif } void arf_set_mpfr(arf_t x, const mpfr_t y) { if (!mpfr_regular_p(y)) { if (mpfr_zero_p(y)) arf_zero(x); else if (mpfr_inf_p(y) && mpfr_sgn(y) > 0) arf_pos_inf(x); else if (mpfr_inf_p(y) && mpfr_sgn(y) < 0) arf_neg_inf(x); else arf_nan(x); } else { mp_size_t n = (y->_mpfr_prec + FLINT_BITS - 1) / FLINT_BITS; arf_set_mpn(x, y->_mpfr_d, n, y->_mpfr_sign < 0); fmpz_set_si(ARF_EXPREF(x), y->_mpfr_exp); } } void arf_set_mpn(arf_t y, mp_srcptr x, mp_size_t xn, int sgnbit) { unsigned int leading; mp_size_t yn, xn1; mp_ptr yptr; mp_limb_t bot; xn1 = xn; while (x[0] == 0) { x++; xn--; } leading = flint_clz(x[xn - 1]); bot = x[0]; /* This works when leading == 0, since x[0] != 0. */ yn = xn - ((bot << leading) == 0); ARF_GET_MPN_WRITE(yptr, yn, y); ARF_XSIZE(y) |= sgnbit; if (leading == 0) { flint_mpn_copyi(yptr, x, xn); } else if (xn == yn) { mpn_lshift(yptr, x, yn, leading); } else { mpn_lshift(yptr, x + 1, yn, leading); yptr[0] |= (bot >> (FLINT_BITS - leading)); } fmpz_set_ui(ARF_EXPREF(y), xn1 * FLINT_BITS - leading); } int _arf_set_mpn_fixed(arf_t z, mp_srcptr xp, mp_size_t xn, mp_size_t fixn, int negative, slong prec, arf_rnd_t rnd) { slong exp, exp_shift; int inexact; exp = (slong)(xn - fixn) * FLINT_BITS; while (xn > 0 && xp[xn-1] == 0) { xn--; exp -= FLINT_BITS; } if (xn == 0) { arf_zero(z); return 0; } else { inexact = _arf_set_round_mpn(z, &exp_shift, xp, xn, negative, prec, rnd); fmpz_set_si(ARF_EXPREF(z), exp + exp_shift); return inexact; } } flint-3.1.3/src/arf/set_round.c000066400000000000000000000266421461254215100163520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_set_round(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { if (arf_is_special(x)) { arf_set(y, x); return 0; } else { int inexact; slong fix; mp_size_t xn; mp_srcptr xptr; if (y == x) { mp_ptr xtmp; TMP_INIT; ARF_GET_MPN_READONLY(xptr, xn, x); /* exact */ if (xn * FLINT_BITS <= prec) return 0; if ((xn - 1) * FLINT_BITS < prec) { /* exact */ if ((xptr[0] << (prec - (xn-1) * FLINT_BITS)) == 0) return 0; } /* inexact */ TMP_START; xtmp = TMP_ALLOC(xn * sizeof(mp_limb_t)); flint_mpn_copyi(xtmp, xptr, xn); inexact = _arf_set_round_mpn(y, &fix, xtmp, xn, ARF_SGNBIT(x), prec, rnd); _fmpz_add_fast(ARF_EXPREF(y), ARF_EXPREF(x), fix); TMP_END; return inexact; } else { ARF_GET_MPN_READONLY(xptr, xn, x); inexact = _arf_set_round_mpn(y, &fix, xptr, xn, ARF_SGNBIT(x), prec, rnd); _fmpz_add_fast(ARF_EXPREF(y), ARF_EXPREF(x), fix); return inexact; } } } int _arf_set_round_mpn(arf_t y, slong * exp_shift, mp_srcptr x, mp_size_t xn, int sgnbit, slong prec, arf_rnd_t rnd) { unsigned int leading; flint_bitcnt_t exp, bc, val, val_bits; mp_size_t yn, val_limbs; mp_ptr yptr; mp_limb_t t; int increment, inexact; /* Compute the total bit length of x. */ leading = flint_clz(x[xn - 1]); exp = xn * FLINT_BITS - leading; /* Set exponent. */ *exp_shift = -(slong) leading; /* Find first nonzero bit. */ val_limbs = 0; while (x[val_limbs] == 0) val_limbs++; val_bits = flint_ctz(x[val_limbs]); val = val_limbs * FLINT_BITS + val_bits; if (exp - val <= prec) { inexact = 0; increment = 0; } else { inexact = 1; /* Limb and bit of the truncation point. */ val_limbs = (exp - prec) / FLINT_BITS; val_bits = (exp - prec) % FLINT_BITS; if (rnd == ARF_RND_DOWN) { increment = 0; } else if (rnd == ARF_RND_NEAR) { /* If exactly one excess bit, there is a tie; the rounding direction is determined by the bit to the left of the truncation point. */ if (exp - val - 1 == prec) { increment = (x[val_limbs] >> val_bits) & 1; } else { /* The bit to the right of the truncation point determines the rounding direction. */ mp_size_t exc_limbs = (exp - prec - 1) / FLINT_BITS; flint_bitcnt_t exc_bits = (exp - prec - 1) % FLINT_BITS; increment = (x[exc_limbs] >> exc_bits) & 1; } } else { if (rnd == ARF_RND_UP) increment = 1; else if (rnd == ARF_RND_FLOOR) increment = sgnbit; else increment = !sgnbit; } if (!increment) { /* Find first nonzero bit from the truncation point. */ t = x[val_limbs] & (LIMB_ONES << val_bits); while (t == 0) { val_limbs++; t = x[val_limbs]; } val_bits = flint_ctz(t); val = val_limbs * FLINT_BITS + val_bits; } else { /* Find first zero bit from the truncation point */ t = (~x[val_limbs]) & (LIMB_ONES << val_bits); while (t == 0) { val_limbs++; if (val_limbs < xn) t = ~x[val_limbs]; else /* The array is all ones up to the highest limb. */ { val_bits = 0; goto END_SCAN1; } } val_bits = flint_ctz(t); END_SCAN1: val = val_limbs * FLINT_BITS + val_bits; /* Overflow to next power of two (unlikely). */ if (val == exp) { exp_shift[0]++; ARF_DEMOTE(y); ARF_NOPTR_D(y)[0] = LIMB_TOP; ARF_XSIZE(y) = ARF_MAKE_XSIZE(1, sgnbit); return 1; } } } /* Now copy the result to destination. */ x += val_limbs; xn -= val_limbs; bc = exp - val; yn = (bc + FLINT_BITS - 1) / FLINT_BITS; ARF_GET_MPN_WRITE(yptr, yn, y); ARF_XSIZE(y) |= sgnbit; if (leading == 0) { flint_mpn_copyi(yptr, x, xn); } else if (xn == yn) { mpn_lshift(yptr, x, yn, leading); } else { mpn_lshift(yptr, x + 1, yn, leading); yptr[0] |= (x[0] >> (FLINT_BITS - leading)); } if (increment) { /* Mask off bits from the last limb. */ yptr[0] &= LIMB_ONES << (yn * FLINT_BITS - bc); /* Increment (no carry propagation). */ yptr[0] += LIMB_ONE << (yn * FLINT_BITS - bc); } else if (inexact && prec < yn * FLINT_BITS) { /* Mask off bits from the last limb. */ yptr[0] &= LIMB_ONES << (yn * FLINT_BITS - prec); } return inexact; } /* Top-aligns the single-limb integer value v and rounds it to prec bits. Writes inexact, v, exp. Warning: macro without parentheses. */ #define ARF_NORMALISE_ROUND_LIMB(inexact, exp, v, sgnbit, prec, rnd) \ do { \ exp = flint_clz(v); \ v <<= exp; \ exp = FLINT_BITS - exp; \ if (prec >= exp) \ { \ inexact = 0; \ } \ else \ { \ mp_limb_t hi_mask, lo_mask, rndn_mask, __t, __u; \ hi_mask = LIMB_ONES << (FLINT_BITS - prec); \ __t = v & hi_mask; \ inexact = (__t != v); \ if (inexact && rnd != ARF_RND_DOWN) \ { \ if (rnd == ARF_RND_NEAR) \ { \ lo_mask = LIMB_ONES >> prec; \ rndn_mask = LIMB_ONE << (FLINT_BITS - prec - 1); \ __u = v & lo_mask; \ if (__u > rndn_mask || (__u == rndn_mask && \ (__t << (prec - 1)))) \ __t += (LIMB_ONE << (FLINT_BITS - prec)); \ } \ else if (arf_rounds_up(rnd, sgnbit)) \ { \ __t += (LIMB_ONE << (FLINT_BITS - prec)); \ } \ if (__t == 0) \ { \ __t = LIMB_TOP; \ exp++; \ } \ } \ v = __t; \ } \ } while (0) int _arf_set_round_ui(arf_t x, ulong v, int sgnbit, slong prec, arf_rnd_t rnd) { _fmpz_demote(ARF_EXPREF(x)); ARF_DEMOTE(x); if (v == 0) { ARF_EXP(x) = ARF_EXP_ZERO; ARF_XSIZE(x) = 0; return 0; } else { int exp, inexact; ARF_NORMALISE_ROUND_LIMB(inexact, exp, v, sgnbit, prec, rnd); ARF_EXP(x) = exp; ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, sgnbit); ARF_NOPTR_D(x)[0] = v; return inexact; } } int _arf_set_round_uiui(arf_t z, slong * fix, mp_limb_t hi, mp_limb_t lo, int sgnbit, slong prec, arf_rnd_t rnd) { int leading, trailing, bc, inexact, zn, up, exp; if (hi == 0) { ARF_NORMALISE_ROUND_LIMB(inexact, exp, lo, sgnbit, prec, rnd); leading = 2 * FLINT_BITS - exp; zn = 1; } else if (lo == 0) { ARF_NORMALISE_ROUND_LIMB(inexact, exp, hi, sgnbit, prec, rnd); leading = FLINT_BITS - exp; lo = hi; zn = 1; } else { leading = flint_clz(hi); trailing = flint_ctz(lo); bc = 2 * FLINT_BITS - leading - trailing; if (bc <= prec) { inexact = 0; zn = 2; if (leading != 0) { if (bc <= FLINT_BITS) { lo = (hi << leading) | (lo >> (FLINT_BITS - leading)); zn = 1; } else { hi = (hi << leading) | (lo >> (FLINT_BITS - leading)); lo = (lo << leading); } } } else { inexact = 1; if (rnd == ARF_RND_DOWN) { up = 0; } else if (rnd == ARF_RND_NEAR) { if (bc == prec + 1) { /* exactly one excess bit; check the parity bit which must be either the lsb of hi or a bit in lo */ if (trailing == FLINT_BITS - 1) up = hi & 1; else up = (lo >> (trailing + 1)) & 1; } else { /* two or more excess bits; test the first excess bit */ flint_bitcnt_t pos = 2 * FLINT_BITS - leading - prec - 1; if (pos < FLINT_BITS) up = (lo >> pos) & 1; else up = (hi >> (pos - FLINT_BITS)) & 1; } } else { up = arf_rounds_up(rnd, sgnbit); } if (prec <= FLINT_BITS) { zn = 1; if (leading == 0) lo = hi; else lo = (hi << leading) | (lo >> (FLINT_BITS - leading)); lo = lo & (LIMB_ONES << (FLINT_BITS - prec)); if (up) { mp_limb_t t, ovf; t = lo + (LIMB_ONE << (FLINT_BITS - prec)); ovf = (t == 0); leading -= ovf; lo = (t >> ovf) | (ovf << (FLINT_BITS - 1)); } } else { zn = 2; if (leading != 0) { hi = (hi << leading) | (lo >> (FLINT_BITS - leading)); lo = (lo << leading); } lo = lo & (LIMB_ONES << (2 * FLINT_BITS - prec)); if (up) { add_ssaaaa(hi, lo, hi, lo, 0, (LIMB_ONE << (2 * FLINT_BITS - prec))); } if (lo == 0) { if (hi == 0) { leading -= 1; lo = LIMB_TOP; } else { lo = hi; } zn = 1; } } } } *fix = -leading; ARF_DEMOTE(z); ARF_XSIZE(z) = ARF_MAKE_XSIZE(zn, sgnbit); ARF_NOPTR_D(z)[0] = lo; ARF_NOPTR_D(z)[1] = hi; return inexact; } flint-3.1.3/src/arf/sosq.c000066400000000000000000000042271461254215100153300ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "mpn_extras.h" int arf_sosq(arf_t res, const arf_t a, const arf_t b, slong prec, arf_rnd_t rnd) { if (arf_is_special(a) || arf_is_special(b)) { if (arf_is_zero(a)) return arf_mul(res, b, b, prec, rnd); if (arf_is_zero(b)) return arf_mul(res, a, a, prec, rnd); if (arf_is_nan(a) || arf_is_nan(b)) arf_nan(res); else arf_pos_inf(res); return 0; } else { mp_srcptr ap, bp; int inexact; mp_ptr tmp, aap, bbp; mp_size_t an, bn, aan, bbn, alloc; slong shift; fmpz_t texp, uexp; ARF_MUL_TMP_DECL ARF_GET_MPN_READONLY(ap, an, a); ARF_GET_MPN_READONLY(bp, bn, b); fmpz_init(texp); fmpz_init(uexp); _fmpz_add2_fast(texp, ARF_EXPREF(a), ARF_EXPREF(a), 0); _fmpz_add2_fast(uexp, ARF_EXPREF(b), ARF_EXPREF(b), 0); shift = _fmpz_sub_small(texp, uexp); aan = 2 * an; bbn = 2 * bn; alloc = aan + bbn; ARF_MUL_TMP_ALLOC(tmp, alloc) aap = tmp; bbp = tmp + aan; FLINT_MPN_MUL_WITH_SPECIAL_CASES(aap, ap, an, ap, an) aan -= (aap[0] == 0); aap += (aap[0] == 0); FLINT_MPN_MUL_WITH_SPECIAL_CASES(bbp, bp, bn, bp, bn) bbn -= (bbp[0] == 0); bbp += (bbp[0] == 0); if (shift >= 0) inexact = _arf_add_mpn(res, aap, aan, 0, texp, bbp, bbn, 0, shift, prec, rnd); else inexact = _arf_add_mpn(res, bbp, bbn, 0, uexp, aap, aan, 0, -shift, prec, rnd); ARF_MUL_TMP_FREE(tmp, alloc) fmpz_clear(texp); fmpz_clear(uexp); return inexact; } } flint-3.1.3/src/arf/sqrt.c000066400000000000000000000042331461254215100153310ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arf.h" int arf_sqrt(arf_ptr z, arf_srcptr x, slong prec, arf_rnd_t rnd) { mp_size_t xn, zn, val; mp_srcptr xptr; mp_ptr tmp, zptr; mpfr_t xf, zf; int inexact, odd_exp; ARF_MUL_TMP_DECL if (arf_is_special(x)) { if (arf_is_neg_inf(x)) arf_nan(z); else arf_set(z, x); return 0; } if (ARF_SGNBIT(x)) { arf_nan(z); return 0; } if (ARF_IS_POW2(x) && fmpz_is_odd(ARF_EXPREF(x))) { arf_set(z, x); fmpz_cdiv_q_2exp(ARF_EXPREF(z), ARF_EXPREF(z), 1); return 0; } ARF_GET_MPN_READONLY(xptr, xn, x); odd_exp = fmpz_is_odd(ARF_EXPREF(x)) ? 1 : 0; zn = (prec + FLINT_BITS - 1) / FLINT_BITS; ARF_MUL_TMP_ALLOC(tmp, zn) zf->_mpfr_d = tmp; zf->_mpfr_prec = prec; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; xf->_mpfr_d = (mp_ptr) xptr; xf->_mpfr_prec = xn * FLINT_BITS; xf->_mpfr_sign = 1; xf->_mpfr_exp = odd_exp; inexact = mpfr_sqrt(zf, xf, arf_rnd_to_mpfr(rnd)); inexact = (inexact != 0); val = 0; while (tmp[val] == 0) val++; ARF_GET_MPN_WRITE(zptr, zn - val, z); flint_mpn_copyi(zptr, tmp + val, zn - val); fmpz_fdiv_q_2exp(ARF_EXPREF(z), ARF_EXPREF(x), 1); fmpz_add_si(ARF_EXPREF(z), ARF_EXPREF(z), zf->_mpfr_exp); ARF_MUL_TMP_FREE(tmp, zn) return inexact; } int arf_sqrt_ui(arf_t z, ulong x, slong prec, arf_rnd_t rnd) { arf_t t; arf_init_set_ui(t, x); /* no need to free */ return arf_sqrt(z, t, prec, rnd); } int arf_sqrt_fmpz(arf_t z, const fmpz_t x, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_set_fmpz(t, x); inexact = arf_sqrt(z, t, prec, rnd); arf_clear(t); return inexact; } flint-3.1.3/src/arf/sub.c000066400000000000000000000117011461254215100151270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int arf_sub_special(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { if (arf_is_zero(x)) { if (arf_is_zero(y)) { arf_zero(z); return 0; } else return arf_neg_round(z, y, prec, rnd); } else if (arf_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_nan(x) || arf_is_nan(y) || (arf_is_pos_inf(x) && arf_is_pos_inf(y)) || (arf_is_neg_inf(x) && arf_is_neg_inf(y))) { arf_nan(z); return 0; } else if (arf_is_special(x)) { arf_set(z, x); return 0; } else { arf_neg(z, y); return 0; } } int arf_sub(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; slong shift; if (arf_is_special(x) || arf_is_special(y)) { return arf_sub_special(z, x, y, prec, rnd); } shift = _fmpz_sub_small(ARF_EXPREF(x), ARF_EXPREF(y)); ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, ARF_SGNBIT(x), ARF_EXPREF(x), yptr, yn, ARF_SGNBIT(y) ^ 1, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ARF_SGNBIT(y) ^ 1, ARF_EXPREF(y), xptr, xn, ARF_SGNBIT(x), -shift, prec, rnd); } int arf_sub_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (y == 0) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) { arf_set_si(z, y); return arf_neg_round(z, z, prec, rnd); } else { arf_set(z, x); return 0; } } ysgnbit = (y < 0); if (ysgnbit) ytmp = -y; else ytmp = y; yptr = &ytmp; yn = 1; yexp = FLINT_BITS; ysgnbit ^= 1; shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); } int arf_sub_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (y == 0) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) { arf_set_ui(z, y); return arf_neg_round(z, z, prec, rnd); } else { arf_set(z, x); return 0; } } ysgnbit = 1; ytmp = y; yptr = &ytmp; yn = 1; yexp = FLINT_BITS; shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); } int arf_sub_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (fmpz_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) { arf_set_fmpz(z, y); return arf_neg_round(z, z, prec, rnd); } else { arf_set(z, x); return 0; } } FMPZ_GET_MPN_READONLY(ysgnbit, yn, yptr, ytmp, *y) yexp = yn * FLINT_BITS; shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); ysgnbit ^= 1; xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); } flint-3.1.3/src/arf/submul.c000066400000000000000000000076341461254215100156570ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "mpn_extras.h" int arf_submul(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, tn, alloc; mp_srcptr xptr, yptr, zptr; mp_ptr tptr, tptr2; fmpz_t texp; slong shift; int tsgnbit, inexact; ARF_MUL_TMP_DECL if (arf_is_special(x) || arf_is_special(y) || arf_is_special(z)) { if (arf_is_zero(z)) { return arf_neg_mul(z, x, y, prec, rnd); } else if (arf_is_finite(x) && arf_is_finite(y)) { return arf_set_round(z, z, prec, rnd); } else { /* todo: speed up */ arf_t t; arf_init(t); arf_mul(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } } tsgnbit = ARF_SGNBIT(x) ^ ARF_SGNBIT(y) ^ 1; ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); ARF_GET_MPN_READONLY(zptr, zn, z); fmpz_init(texp); _fmpz_add2_fast(texp, ARF_EXPREF(x), ARF_EXPREF(y), 0); shift = _fmpz_sub_small(ARF_EXPREF(z), texp); alloc = tn = xn + yn; ARF_MUL_TMP_ALLOC(tptr2, alloc) tptr = tptr2; FLINT_MPN_MUL_WITH_SPECIAL_CASES(tptr, xptr, xn, yptr, yn); tn -= (tptr[0] == 0); tptr += (tptr[0] == 0); if (shift >= 0) inexact = _arf_add_mpn(z, zptr, zn, ARF_SGNBIT(z), ARF_EXPREF(z), tptr, tn, tsgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, tptr, tn, tsgnbit, texp, zptr, zn, ARF_SGNBIT(z), -shift, prec, rnd); ARF_MUL_TMP_FREE(tptr2, alloc) fmpz_clear(texp); return inexact; } int arf_submul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, tn, alloc; mp_srcptr xptr, yptr, zptr; mp_ptr tptr, tptr2; fmpz_t texp, yexp; slong shift; int tsgnbit, ysgnbit, inexact; ARF_MUL_TMP_DECL yn = FLINT_ABS(y->_mp_size); if (arf_is_special(x) || yn == 0 || arf_is_special(z)) { if (arf_is_zero(z)) { /* TODO: make more efficient */ arf_mul_mpz(z, x, y, ARF_PREC_EXACT, rnd); return arf_neg_round(z, z, prec, rnd); } else if (arf_is_finite(x)) { return arf_set_round(z, z, prec, rnd); } else { /* todo: speed up */ arf_t t; arf_init(t); arf_mul_mpz(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } } ARF_GET_MPN_READONLY(xptr, xn, x); yptr = y->_mp_d; ysgnbit = (y->_mp_size > 0); *yexp = yn * FLINT_BITS; ARF_GET_MPN_READONLY(zptr, zn, z); fmpz_init(texp); tsgnbit = ARF_SGNBIT(x) ^ ysgnbit; alloc = tn = xn + yn; ARF_MUL_TMP_ALLOC(tptr2, alloc) tptr = tptr2; FLINT_MPN_MUL_WITH_SPECIAL_CASES(tptr, xptr, xn, yptr, yn); shift = (tptr[tn - 1] == 0) * FLINT_BITS; tn -= (tptr[tn - 1] == 0); _fmpz_add2_fast(texp, ARF_EXPREF(x), yexp, -shift); shift = _fmpz_sub_small(ARF_EXPREF(z), texp); if (shift >= 0) inexact = _arf_add_mpn(z, zptr, zn, ARF_SGNBIT(z), ARF_EXPREF(z), tptr, tn, tsgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, tptr, tn, tsgnbit, texp, zptr, zn, ARF_SGNBIT(z), -shift, prec, rnd); ARF_MUL_TMP_FREE(tptr2, alloc) fmpz_clear(texp); return inexact; } flint-3.1.3/src/arf/sum.c000066400000000000000000000106161461254215100151460ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" int _arf_are_close(const arf_t x, const arf_t y, slong prec) { fmpz_t xb, yb; fmpz_t delta; int result; fmpz_init(xb); fmpz_init(yb); fmpz_init(delta); arf_bot(xb, x); arf_bot(yb, y); if (fmpz_cmp(ARF_EXPREF(x), ARF_EXPREF(y)) >= 0) fmpz_sub(delta, xb, ARF_EXPREF(y)); else fmpz_sub(delta, yb, ARF_EXPREF(x)); fmpz_sub_ui(delta, delta, 64); result = (fmpz_cmp_ui(delta, prec) < 0); fmpz_clear(xb); fmpz_clear(yb); fmpz_clear(delta); return result; } int _arf_add_eps(arf_t s, const arf_t x, int sgn, slong prec, arf_rnd_t rnd) { arf_t t; slong bits; bits = arf_bits(x); if (bits == 0) { flint_throw(FLINT_ERROR, "_arf_add_eps\n"); } bits = FLINT_MAX(bits, prec) + 10; arf_init(t); arf_set_si(t, sgn); arf_mul_2exp_fmpz(t, t, ARF_EXPREF(x)); arf_mul_2exp_si(t, t, -bits); arf_add(s, x, t, prec, rnd); arf_clear(t); return 1; } int arf_sum(arf_t s, arf_srcptr terms, slong len, slong prec, arf_rnd_t rnd) { arf_ptr blocks; slong i, j, used; int have_merged, res; /* first check if the result is inf or nan */ { int have_pos_inf = 0; int have_neg_inf = 0; for (i = 0; i < len; i++) { if (arf_is_pos_inf(terms + i)) { if (have_neg_inf) { arf_nan(s); return 0; } have_pos_inf = 1; } else if (arf_is_neg_inf(terms + i)) { if (have_pos_inf) { arf_nan(s); return 0; } have_neg_inf = 1; } else if (arf_is_nan(terms + i)) { arf_nan(s); return 0; } } if (have_pos_inf) { arf_pos_inf(s); return 0; } if (have_neg_inf) { arf_neg_inf(s); return 0; } } blocks = flint_malloc(sizeof(arf_struct) * len); for (i = 0; i < len; i++) arf_init(blocks + i); /* put all terms into blocks */ used = 0; for (i = 0; i < len; i++) { if (!arf_is_zero(terms + i)) { arf_set(blocks + used, terms + i); used++; } } /* merge blocks until all are well separated */ have_merged = 1; while (used >= 2 && have_merged) { have_merged = 0; for (i = 0; i < used && !have_merged; i++) { for (j = i + 1; j < used && !have_merged; j++) { if (_arf_are_close(blocks + i, blocks + j, prec)) { arf_add(blocks + i, blocks + i, blocks + j, ARF_PREC_EXACT, ARF_RND_DOWN); /* remove the merged block */ arf_swap(blocks + j, blocks + used - 1); used--; /* remove the updated block if the sum is zero */ if (arf_is_zero(blocks + i)) { arf_swap(blocks + i, blocks + used - 1); used--; } have_merged = 1; } } } } if (used == 0) { arf_zero(s); res = 0; } else if (used == 1) { res = arf_set_round(s, blocks + 0, prec, rnd); } else { /* find the two largest blocks */ for (i = 1; i < used; i++) if (arf_cmpabs(blocks + 0, blocks + i) < 0) arf_swap(blocks + 0, blocks + i); for (i = 2; i < used; i++) if (arf_cmpabs(blocks + 1, blocks + i) < 0) arf_swap(blocks + 1, blocks + i); res = _arf_add_eps(s, blocks + 0, arf_sgn(blocks + 1), prec, rnd); } for (i = 0; i < len; i++) arf_clear(blocks + i); flint_free(blocks); return res; } flint-3.1.3/src/arf/test/000077500000000000000000000000001461254215100151515ustar00rootroot00000000000000flint-3.1.3/src/arf/test/main.c000066400000000000000000000100441461254215100162400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include /* Include functions *********************************************************/ #include "t-abs_bound_le_2exp_fmpz.c" #include "t-abs_bound_lt_2exp_fmpz.c" #include "t-abs_bound_lt_2exp_si.c" #include "t-add.c" #include "t-add_fmpz_2exp.c" #include "t-add_fmpz.c" #include "t-addmul.c" #include "t-addmul_fmpz.c" #include "t-addmul_si.c" #include "t-addmul_ui.c" #include "t-add_si.c" #include "t-add_ui.c" #include "t-approx_dot.c" #include "t-ceil.c" #include "t-cmp_2exp_si.c" #include "t-cmpabs_2exp_si.c" #include "t-cmpabs.c" #include "t-cmp.c" #include "t-complex_mul.c" #include "t-complex_sqr.c" #include "t-div.c" #include "t-dump_file.c" #include "t-dump_str.c" #include "t-floor.c" #include "t-fma.c" #include "t-frexp.c" #include "t-get_d.c" #include "t-get_fmpz.c" #include "t-get_mpfr.c" #include "t-get_str.c" #include "t-is_int_2exp_si.c" #include "t-mul.c" #include "t-mul_fmpz.c" #include "t-mul_si.c" #include "t-mul_ui.c" #include "t-mul_via_mpfr.c" #include "t-neg_round.c" #include "t-root.c" #include "t-rsqrt.c" #include "t-set_d.c" #include "t-set_fmpq.c" #include "t-set_fmpz_2exp.c" #include "t-set_round.c" #include "t-set_round_fmpz.c" #include "t-set_round_mpz.c" #include "t-set_round_ui.c" #include "t-set_round_uiui.c" #include "t-sgn.c" #include "t-sosq.c" #include "t-sqrt.c" #include "t-sub.c" #include "t-sub_fmpz.c" #include "t-submul.c" #include "t-submul_fmpz.c" #include "t-submul_si.c" #include "t-submul_ui.c" #include "t-sub_si.c" #include "t-sub_ui.c" #include "t-sum.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arf_abs_bound_le_2exp_fmpz), TEST_FUNCTION(arf_abs_bound_lt_2exp_fmpz), TEST_FUNCTION(arf_abs_bound_lt_2exp_si), TEST_FUNCTION(arf_add), TEST_FUNCTION(arf_add_fmpz_2exp), TEST_FUNCTION(arf_add_fmpz), TEST_FUNCTION(arf_addmul), TEST_FUNCTION(arf_addmul_fmpz), TEST_FUNCTION(arf_addmul_si), TEST_FUNCTION(arf_addmul_ui), TEST_FUNCTION(arf_add_si), TEST_FUNCTION(arf_add_ui), TEST_FUNCTION(arf_approx_dot), TEST_FUNCTION(arf_ceil), TEST_FUNCTION(arf_cmp_2exp_si), TEST_FUNCTION(arf_cmpabs_2exp_si), TEST_FUNCTION(arf_cmpabs), TEST_FUNCTION(arf_cmp), TEST_FUNCTION(arf_complex_mul), TEST_FUNCTION(arf_complex_sqr), TEST_FUNCTION(arf_div), TEST_FUNCTION(arf_dump_file), TEST_FUNCTION(arf_dump_str), TEST_FUNCTION(arf_floor), TEST_FUNCTION(arf_fma), TEST_FUNCTION(arf_frexp), TEST_FUNCTION(arf_get_d), TEST_FUNCTION(arf_get_fmpz), TEST_FUNCTION(arf_get_mpfr), TEST_FUNCTION(arf_get_str), TEST_FUNCTION(arf_is_int_2exp_si), TEST_FUNCTION(arf_mul), TEST_FUNCTION(arf_mul_fmpz), TEST_FUNCTION(arf_mul_si), TEST_FUNCTION(arf_mul_ui), TEST_FUNCTION(arf_mul_via_mpfr), TEST_FUNCTION(arf_neg_round), TEST_FUNCTION(arf_root), TEST_FUNCTION(arf_rsqrt), TEST_FUNCTION(arf_set_d), TEST_FUNCTION(arf_set_fmpq), TEST_FUNCTION(arf_set_fmpz_2exp), TEST_FUNCTION(arf_set_round), TEST_FUNCTION(arf_set_round_fmpz), TEST_FUNCTION(arf_set_round_mpz), TEST_FUNCTION(arf_set_round_ui), TEST_FUNCTION(arf_set_round_uiui), TEST_FUNCTION(arf_sgn), TEST_FUNCTION(arf_sosq), TEST_FUNCTION(arf_sqrt), TEST_FUNCTION(arf_sub), TEST_FUNCTION(arf_sub_fmpz), TEST_FUNCTION(arf_submul), TEST_FUNCTION(arf_submul_fmpz), TEST_FUNCTION(arf_submul_si), TEST_FUNCTION(arf_submul_ui), TEST_FUNCTION(arf_sub_si), TEST_FUNCTION(arf_sub_ui), TEST_FUNCTION(arf_sum) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arf/test/t-abs_bound_le_2exp_fmpz.c000066400000000000000000000027731461254215100221750ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_abs_bound_le_2exp_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; fmpz_t b; int cmp1, cmp2; arf_init(x); arf_init(y); fmpz_init(b); arf_randtest_not_zero(x, state, 2 + n_randint(state, 1000), 100); arf_abs_bound_le_2exp_fmpz(b, x); arf_one(y); arf_mul_2exp_fmpz(y, y, b); cmp1 = (arf_cmpabs(x, y) <= 0); arf_mul_2exp_si(y, y, -1); cmp2 = (arf_cmpabs(y, x) < 0); arf_mul_2exp_si(y, y, 1); if (!cmp1 || !cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } arf_clear(x); arf_clear(y); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-abs_bound_lt_2exp_fmpz.c000066400000000000000000000027731461254215100222140ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_abs_bound_lt_2exp_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; fmpz_t b; int cmp1, cmp2; arf_init(x); arf_init(y); fmpz_init(b); arf_randtest_not_zero(x, state, 2 + n_randint(state, 1000), 100); arf_abs_bound_lt_2exp_fmpz(b, x); arf_one(y); arf_mul_2exp_fmpz(y, y, b); cmp1 = (arf_cmpabs(x, y) < 0); arf_mul_2exp_si(y, y, -1); cmp2 = (arf_cmpabs(y, x) <= 0); arf_mul_2exp_si(y, y, 1); if (!cmp1 || !cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } arf_clear(x); arf_clear(y); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-abs_bound_lt_2exp_si.c000066400000000000000000000041341461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_abs_bound_lt_2exp_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; fmpz_t b; slong c; arf_init(x); fmpz_init(b); if (iter < 5) { arf_set_ui_2exp_si(x, 1, LONG_MIN + 2); arf_mul_2exp_si(x, x, -iter); } else if (iter < 10) { arf_set_ui_2exp_si(x, 1, WORD_MAX - 2); arf_mul_2exp_si(x, x, iter - 5); } else { arf_randtest_special(x, state, 2 + n_randint(state, 1000), 100); } arf_abs_bound_lt_2exp_fmpz(b, x); c = arf_abs_bound_lt_2exp_si(x); if (c == -ARF_PREC_EXACT) { if (!(arf_is_zero(x) || fmpz_cmp_si(b, -ARF_PREC_EXACT) <= 0)) { flint_printf("FAIL (small/zero)\n\n"); flint_abort(); } } else if (c == ARF_PREC_EXACT) { if (!(arf_is_inf(x) || arf_is_nan(x) || fmpz_cmp_si(b, ARF_PREC_EXACT) >= 0)) { flint_printf("FAIL (large/inf/nan)\n\n"); flint_abort(); } } else { if (fmpz_cmp_si(b, c) != 0) { flint_printf("FAIL (normal)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("c = %wd\n\n", c); flint_abort(); } } arf_clear(x); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-add.c000066400000000000000000000154101461254215100163070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_add_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { if (!arf_is_special(x) && !arf_is_special(y)) { fmpz_t t; int inexact; fmpz_init(t); fmpz_sub(t, ARF_EXPREF(x), ARF_EXPREF(y)); if (fmpz_cmp_si(t, 5000) > 0) { arf_t eps; arf_init(eps); arf_mul_2exp_si(eps, x, -5000); arf_abs(eps, eps); if (arf_sgn(y) < 0) arf_neg(eps, eps); arf_add(z, x, eps, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_set_round(z, z, prec, rnd); arf_clear(eps); } else if (fmpz_cmp_si(t, -5000) < 0) { arf_t eps; arf_init(eps); arf_mul_2exp_si(eps, y, -5000); arf_abs(eps, eps); if (arf_sgn(x) < 0) arf_neg(eps, eps); arf_add(z, eps, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_set_round(z, z, prec, rnd); arf_clear(eps); } else { arf_add(z, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_set_round(z, z, prec, rnd); } fmpz_clear(t); return inexact; } else { arf_add(z, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); return arf_set_round(z, z, prec, rnd); } } TEST_FUNCTION_START(arf_add, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; fmpz_t t; arf_init(x); arf_init(y); arf_init(z); arf_init(v); fmpz_init(t); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } rnd = ARF_RND_DOWN; if (arf_is_normal(x) && arf_is_normal(y)) { fmpz_sub(t, ARF_EXPREF(x), ARF_EXPREF(y)); /* if not too far apart, sometimes test exact addition */ if (fmpz_bits(t) < 10) { if (n_randint(state, 10) == 0) prec = ARF_PREC_EXACT; } } switch (n_randint(state, 5)) { case 0: r1 = arf_add(z, x, y, prec, rnd); r2 = arf_add_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_add(z, x, x, prec, rnd); r2 = arf_add_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_add_naive(v, x, x, prec, rnd); r1 = arf_add(x, x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_add_naive(v, x, y, prec, rnd); r1 = arf_add(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_add_naive(v, x, y, prec, rnd); r1 = arf_add(x, y, x, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-add_fmpz.c000066400000000000000000000064301461254215100173450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_add_fmpz_naive(arf_t z, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_fmpz(t, y); r = arf_add(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_add_fmpz, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; fmpz_t y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); fmpz_init(y); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); fmpz_randtest(y, state, 2000); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_add_fmpz(z, x, y, prec, rnd); r2 = arf_add_fmpz_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_add_fmpz_naive(v, x, y, prec, rnd); r1 = arf_add_fmpz(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-add_fmpz_2exp.c000066400000000000000000000071241461254215100203040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_add_fmpz_2exp_naive(arf_t z, const arf_t x, const fmpz_t y, const fmpz_t e, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_fmpz_2exp(t, y, e); r = arf_add(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_add_fmpz_2exp, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; fmpz_t y, e; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); fmpz_init(y); fmpz_init(e); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); fmpz_randtest(y, state, 2000); fmpz_randtest(e, state, 10); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_add_fmpz_2exp(z, x, y, e, prec, rnd); r2 = arf_add_fmpz_2exp_naive(v, x, y, e, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_add_fmpz_2exp_naive(v, x, y, e, prec, rnd); r1 = arf_add_fmpz_2exp(x, x, y, e, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); fmpz_clear(y); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-add_si.c000066400000000000000000000064301461254215100170040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "long_extras.h" int arf_add_si_naive(arf_t z, const arf_t x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_si(t, y); r = arf_add(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_add_si, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); y = z_randtest(state); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 1)) { case 0: r1 = arf_add_si(z, x, y, prec, rnd); r2 = arf_add_si_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL! (ha iter %wd, %wd)\n", iter, iter2); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_add_si_naive(v, x, y, prec, rnd); r1 = arf_add_si(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-add_ui.c000066400000000000000000000063711461254215100170120ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "ulong_extras.h" int arf_add_ui_naive(arf_t z, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_ui(t, y); r = arf_add(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_add_ui, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; ulong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); y = n_randtest(state); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_add_ui(z, x, y, prec, rnd); r2 = arf_add_ui_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_add_ui_naive(v, x, y, prec, rnd); r1 = arf_add_ui(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-addmul.c000066400000000000000000000127731461254215100170360ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_addmul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_addmul, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(y)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) { case 0: r1 = arf_addmul(z, x, y, prec, rnd); r2 = arf_addmul_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_addmul(z, x, x, prec, rnd); r2 = arf_addmul_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_addmul_naive(v, v, v, prec, rnd); r1 = arf_addmul(z, z, z, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_addmul_naive(v, v, y, prec, rnd); r1 = arf_addmul(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_addmul_naive(v, x, v, prec, rnd); r1 = arf_addmul(z, x, z, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-addmul_fmpz.c000066400000000000000000000067651461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_addmul_fmpz_naive(arf_t z, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul_fmpz(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_addmul_fmpz, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; fmpz_t y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); fmpz_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); fmpz_randtest(y, state, 2000); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_addmul_fmpz(z, x, y, prec, rnd); r2 = arf_addmul_fmpz_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_debug(z); flint_printf("\n\n"); flint_printf("v = "); arf_debug(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_addmul_fmpz_naive(v, v, y, prec, rnd); r1 = arf_addmul_fmpz(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); fmpz_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-addmul_si.c000066400000000000000000000066611461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "long_extras.h" int arf_addmul_si_naive(arf_t z, const arf_t x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul_si(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_addmul_si, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); y = z_randtest(state); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_addmul_si(z, x, y, prec, rnd); r2 = arf_addmul_si_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_debug(z); flint_printf("\n\n"); flint_printf("v = "); arf_debug(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_addmul_si_naive(v, v, y, prec, rnd); r1 = arf_addmul_si(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = %wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-addmul_ui.c000066400000000000000000000066301461254215100175260ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_addmul_ui_naive(arf_t z, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul_ui(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_addmul_ui, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; ulong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); y = n_randtest(state); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_addmul_ui(z, x, y, prec, rnd); r2 = arf_addmul_ui_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %wu", y); flint_printf("\n\n"); flint_printf("z = "); arf_debug(z); flint_printf("\n\n"); flint_printf("v = "); arf_debug(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_addmul_ui_naive(v, v, y, prec, rnd); r1 = arf_addmul_ui(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = %wu", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-approx_dot.c000066400000000000000000000165741461254215100177520ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "arb.h" TEST_FUNCTION_START(arf_approx_dot, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_ptr x, y; arf_t s1, s2, z; slong i, len, prec, xbits, ybits, ebits; int initial, subtract, revx, revy; if (n_randint(state, 100) == 0) len = n_randint(state, 100); else if (n_randint(state, 10) == 0) len = n_randint(state, 10); else len = n_randint(state, 3); if (n_randint(state, 10) != 0 || len > 10) { prec = 2 + n_randint(state, 500); xbits = 2 + n_randint(state, 500); ybits = 2 + n_randint(state, 500); } else { prec = 2 + n_randint(state, 4000); xbits = 2 + n_randint(state, 4000); ybits = 2 + n_randint(state, 4000); } if (n_randint(state, 100) == 0) ebits = 2 + n_randint(state, 100); else ebits = 2 + n_randint(state, 10); initial = n_randint(state, 2); subtract = n_randint(state, 2); revx = n_randint(state, 2); revy = n_randint(state, 2); x = _arf_vec_init(len); y = _arf_vec_init(len); arf_init(s1); arf_init(s2); arf_init(z); switch (n_randint(state, 3)) { case 0: for (i = 0; i < len; i++) { arf_randtest(x + i, state, xbits, ebits); arf_randtest(y + i, state, ybits, ebits); } break; /* Test with cancellation */ case 1: for (i = 0; i < len; i++) { if (i <= len / 2) { arf_randtest(x + i, state, xbits, ebits); arf_randtest(y + i, state, ybits, ebits); } else { arf_neg(x + i, x + len - i - 1); arf_set(y + i, y + len - i - 1); } } break; default: for (i = 0; i < len; i++) { if (i <= len / 2) { arf_randtest(x + i, state, xbits, ebits); arf_randtest(y + i, state, ybits, ebits); } else { arf_neg_round(x + i, x + len - i - 1, 2 + n_randint(state, 500), ARF_RND_NEAR); arf_set_round(y + i, y + len - i - 1, 2 + n_randint(state, 500), ARF_RND_NEAR); } } break; } arf_randtest(s1, state, 200, 100); arf_randtest(s2, state, 200, 100); arf_randtest(z, state, xbits, ebits); arf_approx_dot(s1, initial ? z : NULL, subtract, revx ? (x + len - 1) : x, revx ? -1 : 1, revy ? (y + len - 1) : y, revy ? -1 : 1, len, prec, ARB_RND); /* With the fast algorithm, we expect identical results when reversing the vectors. */ if (ebits <= 12) { arf_approx_dot(s2, initial ? z : NULL, subtract, !revx ? (x + len - 1) : x, !revx ? -1 : 1, !revy ? (y + len - 1) : y, !revy ? -1 : 1, len, prec, ARB_RND); if (!arf_equal(s1, s2)) { flint_printf("FAIL (reversal)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); arf_printd(z, 100); flint_printf(" (%wd)\n\n", arf_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arf_printd(x + i, 100); flint_printf(" (%wd)\n", arf_bits(x + i)); flint_printf("y[%wd] = ", i); arf_printd(y + i, 100); flint_printf(" (%wd)\n", arf_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arf_printd(s1, 100); flint_printf("\n\n"); flint_printf("s2 = "); arf_printd(s2, 100); flint_printf("\n\n"); flint_abort(); } } /* Compare with arb_dot */ { arb_ptr ax, ay; arb_t as2, az; ax = _arb_vec_init(len); ay = _arb_vec_init(len); arb_init(as2); arb_init(az); for (i = 0; i < len; i++) { arb_set_arf(ax + i, x + i); arb_set_arf(ay + i, y + i); } if (initial) arb_set_arf(az, z); arb_dot(as2, initial ? az : NULL, subtract, revx ? (ax + len - 1) : ax, revx ? -1 : 1, revy ? (ay + len - 1) : ay, revy ? -1 : 1, len, prec); { mag_t err, xx, yy; mag_init(err); mag_init(xx); mag_init(yy); if (initial) arf_get_mag(err, z); for (i = 0; i < len; i++) { arf_get_mag(xx, revx ? x + len - 1 - i : x + i); arf_get_mag(yy, revx ? y + len - 1 - i : y + i); mag_addmul(err, xx, yy); } mag_mul_2exp_si(err, err, -prec + 2); arb_add_error_mag(as2, err); if (!arb_contains_arf(as2, s1)) { flint_printf("FAIL (inclusion)\n\n"); flint_printf("iter = %wd, len = %wd, prec = %wd, ebits = %wd\n\n", iter, len, prec, ebits); if (initial) { flint_printf("z = ", i); arf_printd(z, 100); flint_printf(" (%wd)\n\n", arf_bits(z)); } for (i = 0; i < len; i++) { flint_printf("x[%wd] = ", i); arf_printd(x + i, 100); flint_printf(" (%wd)\n", arf_bits(x + i)); flint_printf("y[%wd] = ", i); arf_printd(y + i, 100); flint_printf(" (%wd)\n", arf_bits(y + i)); } flint_printf("\n\n"); flint_printf("s1 = "); arf_printd(s1, 100); flint_printf("\n\n"); flint_printf("s2 = "); arf_printd(s2, 100); flint_printf("\n\n"); flint_abort(); } mag_clear(err); mag_clear(xx); mag_clear(yy); } _arb_vec_clear(ax, len); _arb_vec_clear(ay, len); arb_clear(as2); arb_clear(az); } arf_clear(s1); arf_clear(s2); arf_clear(z); _arf_vec_clear(x, len); _arf_vec_clear(y, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-ceil.c000066400000000000000000000042221461254215100164720ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_ceil, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; int result; arf_init(x); arf_init(y); arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); arf_ceil(y, x); result = 1; if (arf_is_int(x) || !arf_is_finite(x)) { result = arf_equal(y, x); } else if (!arf_is_int(y)) { result = 0; } else if (arf_cmp(y, x) <= 0) { result = 0; } else { arf_t s, t[3]; /* check x - ceil(x) + 1 > 0 */ arf_init(s); arf_init(t[0]); arf_init(t[1]); arf_init(t[2]); arf_set(t[0], x); arf_neg(t[1], y); arf_one(t[2]); arf_sum(s, (arf_ptr) t, 3, 32, ARF_RND_DOWN); result = arf_sgn(s) > 0; arf_clear(s); arf_clear(t[0]); arf_clear(t[1]); arf_clear(t[2]); } if (!result) { flint_printf("FAIL!\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_abort(); } arf_ceil(x, x); if (!arf_equal(x, y)) { flint_printf("FAIL (aliasing)!\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-cmp.c000066400000000000000000000057021461254215100163410ustar00rootroot00000000000000/* Copyright (C) 2012, 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_cmp, state) { slong iter; /* compare with fmpz */ { arf_t x, y; fmpz_t X, Y; arf_init(x); arf_init(y); fmpz_init(X); fmpz_init(Y); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { int cmp1, cmp2; fmpz_randtest(X, state, 1 + n_randint(state, 1000)); switch (n_randint(state, 8)) { case 0: fmpz_neg(Y, X); break; case 1: fmpz_set(Y, X); break; default: fmpz_randtest(Y, state, 1 + n_randint(state, 1000)); } arf_set_fmpz(x, X); arf_set_fmpz(y, Y); cmp1 = arf_cmp(x, y); cmp2 = fmpz_cmp(X, Y); cmp2 = (cmp2 > 0) - (cmp2 < 0); if (cmp1 != cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_debug(x); flint_printf("\n\n"); flint_printf("y = "); arf_debug(y); flint_printf("\n\n"); flint_printf("X = "); fmpz_print(X); flint_printf("\n\n"); flint_printf("Y = "); fmpz_print(Y); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } } arf_clear(x); arf_clear(y); fmpz_clear(X); fmpz_clear(Y); } /* compare with mpfr */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits; arf_t x, y; mpfr_t X, Y; int cmp1, cmp2; bits = 2 + n_randint(state, 200); arf_init(x); arf_init(y); mpfr_init2(X, bits); mpfr_init2(Y, bits); arf_randtest_special(x, state, bits, 10); arf_randtest_special(y, state, bits, 10); arf_get_mpfr(X, x, MPFR_RNDN); arf_get_mpfr(Y, y, MPFR_RNDN); cmp1 = arf_cmp(x, y); cmp2 = mpfr_cmp(X, Y); if (cmp1 != cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } arf_clear(x); arf_clear(y); mpfr_clear(X); mpfr_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-cmp_2exp_si.c000066400000000000000000000025721461254215100177740ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_cmp_2exp_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, e; arf_t x, y; int cmp1, cmp2; bits = 2 + n_randint(state, 1000); e = n_randtest(state); arf_init(x); arf_init(y); if (iter % 10 == 0) arf_set_ui_2exp_si(x, 1, e); else arf_randtest_special(x, state, bits, 100); arf_set_ui_2exp_si(y, 1, e); cmp1 = arf_cmp(x, y); cmp2 = arf_cmp_2exp_si(x, e); if (cmp1 != cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-cmpabs.c000066400000000000000000000060251461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2012, 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_cmpabs, state) { slong iter; /* compare with fmpz */ { arf_t x, y; fmpz_t X, Y; arf_init(x); arf_init(y); fmpz_init(X); fmpz_init(Y); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { int cmp1, cmp2; fmpz_randtest(X, state, 1 + n_randint(state, 1000)); switch (n_randint(state, 8)) { case 0: fmpz_neg(Y, X); break; case 1: fmpz_set(Y, X); break; default: fmpz_randtest(Y, state, 1 + n_randint(state, 1000)); } arf_set_fmpz(x, X); arf_set_fmpz(y, Y); cmp1 = arf_cmpabs(x, y); cmp2 = fmpz_cmpabs(X, Y); cmp2 = (cmp2 > 0) - (cmp2 < 0); if (cmp1 != cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_debug(x); flint_printf("\n\n"); flint_printf("y = "); arf_debug(y); flint_printf("\n\n"); flint_printf("X = "); fmpz_print(X); flint_printf("\n\n"); flint_printf("Y = "); fmpz_print(Y); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } } arf_clear(x); arf_clear(y); fmpz_clear(X); fmpz_clear(Y); } /* compare with mpfr */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits; arf_t x, y; mpfr_t X, Y; int cmp1, cmp2; bits = 2 + n_randint(state, 200); arf_init(x); arf_init(y); mpfr_init2(X, bits); mpfr_init2(Y, bits); arf_randtest_special(x, state, bits, 10); arf_randtest_special(y, state, bits, 10); arf_get_mpfr(X, x, MPFR_RNDN); arf_get_mpfr(Y, y, MPFR_RNDN); mpfr_abs(X, X, MPFR_RNDN); mpfr_abs(Y, Y, MPFR_RNDN); cmp1 = arf_cmpabs(x, y); cmp2 = mpfr_cmp(X, Y); if (cmp1 != cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } arf_clear(x); arf_clear(y); mpfr_clear(X); mpfr_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-cmpabs_2exp_si.c000066400000000000000000000026031461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_cmpabs_2exp_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, e; arf_t x, y; int cmp1, cmp2; bits = 2 + n_randint(state, 1000); e = n_randtest(state); arf_init(x); arf_init(y); if (iter % 10 == 0) arf_set_ui_2exp_si(x, 1, e); else arf_randtest_special(x, state, bits, 100); arf_set_ui_2exp_si(y, 1, e); cmp1 = arf_cmpabs(x, y); cmp2 = arf_cmpabs_2exp_si(x, e); if (cmp1 != cmp2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("cmp1 = %d, cmp2 = %d\n\n", cmp1, cmp2); flint_abort(); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-complex_mul.c000066400000000000000000000155571461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_complex_mul, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t e1, f1, e2, f2, a, b, c, d; slong prec, r1, r2; arf_rnd_t rnd; arf_init(a); arf_init(b); arf_init(c); arf_init(d); arf_init(e1); arf_init(f1); arf_init(e2); arf_init(f2); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(a, state, 3000, 100); arf_randtest_special(b, state, 3000, 100); arf_randtest_special(c, state, 3000, 100); arf_randtest_special(d, state, 3000, 100); prec = 2 + n_randint(state, 3000); switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) { case 0: r1 = arf_complex_mul(e1, f1, a, b, c, d, prec, rnd); r2 = arf_complex_mul_fallback(e2, f2, a, b, c, d, prec, rnd); if (!arf_equal(e1, e2) || !arf_equal(f1, f2) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_printf("d = "); arf_print(d); flint_printf("\n\n"); flint_printf("e1 = "); arf_print(e1); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("e2 = "); arf_print(e2); flint_printf("\n\n"); flint_printf("f2 = "); arf_print(f2); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: arf_set(c, a); arf_set(d, b); r1 = arf_complex_mul(e1, f1, a, b, a, b, prec, rnd); r2 = arf_complex_mul_fallback(e2, f2, a, b, c, d, prec, rnd); if (!arf_equal(e1, e2) || !arf_equal(f1, f2) || r1 != r2) { flint_printf("FAIL! (aliasing 1)\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_printf("d = "); arf_print(d); flint_printf("\n\n"); flint_printf("e1 = "); arf_print(e1); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("e2 = "); arf_print(e2); flint_printf("\n\n"); flint_printf("f2 = "); arf_print(f2); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r1 = arf_complex_mul_fallback(e1, f1, a, b, a, b, prec, rnd); r2 = arf_complex_mul(a, b, a, b, a, b, prec, rnd); if (!arf_equal(e1, a) || !arf_equal(f1, b) || r1 != r2) { flint_printf("FAIL! (aliasing 2)\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("e1 = "); arf_print(e1); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r1 = arf_complex_mul_fallback(e1, f1, a, b, c, d, prec, rnd); r2 = arf_complex_mul(a, b, a, b, c, d, prec, rnd); if (!arf_equal(e1, a) || !arf_equal(f1, b) || r1 != r2) { flint_printf("FAIL! (aliasing 3)\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_printf("d = "); arf_print(d); flint_printf("\n\n"); flint_printf("e1 = "); arf_print(e1); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r1 = arf_complex_mul_fallback(e1, f1, a, b, c, d, prec, rnd); r2 = arf_complex_mul(c, d, a, b, c, d, prec, rnd); if (!arf_equal(e1, c) || !arf_equal(f1, d) || r1 != r2) { flint_printf("FAIL! (aliasing 4)\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_printf("d = "); arf_print(d); flint_printf("\n\n"); flint_printf("e1 = "); arf_print(e1); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(a); arf_clear(b); arf_clear(c); arf_clear(d); arf_clear(e1); arf_clear(f1); arf_clear(e2); arf_clear(f2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-complex_sqr.c000066400000000000000000000072051461254215100201160ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_complex_sqr, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t e1, f1, e2, f2, a, b; slong prec, r1, r2; arf_rnd_t rnd; arf_init(a); arf_init(b); arf_init(e1); arf_init(f1); arf_init(e2); arf_init(f2); for (iter2 = 0; iter2 < 100; iter2++) { if (n_randint(state, 100) == 0) { arf_randtest_special(a, state, 12000, 3); arf_randtest_special(b, state, 12000, 3); prec = 2 + n_randint(state, 12000); } else { arf_randtest_special(a, state, 3000, 100); arf_randtest_special(b, state, 3000, 100); prec = 2 + n_randint(state, 3000); } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_complex_sqr(e1, f1, a, b, prec, rnd); r2 = arf_complex_mul_fallback(e2, f2, a, b, a, b, prec, rnd); if (!arf_equal(e1, e2) || !arf_equal(f1, f2) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("e1 = "); arf_print(e1); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("e2 = "); arf_print(e2); flint_printf("\n\n"); flint_printf("f2 = "); arf_print(f2); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r1 = arf_complex_mul_fallback(e1, f1, a, b, a, b, prec, rnd); r2 = arf_complex_sqr(a, b, a, b, prec, rnd); if (!arf_equal(e1, a) || !arf_equal(f1, b) || r1 != r2) { flint_printf("FAIL! (aliasing)\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("e1 = "); arf_print(e1); flint_printf("\n\n"); flint_printf("f1 = "); arf_print(f1); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(a); arf_clear(b); arf_clear(e1); arf_clear(f1); arf_clear(e2); arf_clear(f2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-div.c000066400000000000000000000135711461254215100163470ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" int arf_div_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { arf_t m, n; fmpz_t e, f; mpfr_t a, b, c; int inexact; if (arf_is_zero(y)) { arf_nan(z); return 0; } arf_init(m); arf_init(n); fmpz_init(e); fmpz_init(f); mpfr_init2(a, FLINT_MAX(2, arf_bits(x))); mpfr_init2(b, FLINT_MAX(2, arf_bits(y))); mpfr_init2(c, prec); arf_frexp(m, e, x); arf_frexp(n, f, y); arf_get_mpfr(a, m, MPFR_RNDD); arf_get_mpfr(b, n, MPFR_RNDD); inexact = (mpfr_div(c, a, b, arf_rnd_to_mpfr(rnd)) != 0); arf_set_mpfr(z, c); fmpz_sub(e, e, f); arf_mul_2exp_fmpz(z, z, e); arf_clear(m); arf_clear(n); fmpz_clear(e); fmpz_clear(f); mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); return inexact; } TEST_FUNCTION_START(arf_div, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); prec = 2 + n_randint(state, 2000); if (n_randint(state, 20) == 0) arf_mul(x, x, y, 2 + n_randint(state, 3000), ARF_RND_FLOOR); switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) { case 0: r1 = arf_div(z, x, y, prec, rnd); r2 = arf_div_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_div(z, x, x, prec, rnd); r2 = arf_div_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_div_naive(v, x, x, prec, rnd); r1 = arf_div(x, x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_div_naive(v, x, y, prec, rnd); r1 = arf_div(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_div_naive(v, y, x, prec, rnd); r1 = arf_div(x, y, x, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-dump_file.c000066400000000000000000000050051461254215100175220ustar00rootroot00000000000000/* Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arb.h" TEST_FUNCTION_START(arf_dump_file, state) { slong iter; /* assume tmpfile() is broken on windows */ #if !defined(_MSC_VER) && !defined(__MINGW32__) /* just test no crashing... */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; FILE* tmp; arf_init(x); arf_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); tmp = tmpfile(); arf_dump_file(tmp, x); fflush(tmp); rewind(tmp); arf_load_file(x, tmp); fclose(tmp); arf_clear(x); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z; int conversion_error; FILE* tmp; arf_init(x); arf_init(y); arf_init(z); arf_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); tmp = tmpfile(); arf_dump_file(tmp, x); fputc(' ', tmp); arf_dump_file(tmp, y); fflush(tmp); rewind(tmp); conversion_error = arf_load_file(z, tmp); if (conversion_error || !arf_equal(x, z)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 50); flint_printf("\n\n"); flint_abort(); } conversion_error = arf_load_file(z, tmp); if (conversion_error || !arf_equal(y, z)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("y = "); arf_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 50); flint_printf("\n\n"); flint_abort(); } fclose(tmp); arf_clear(x); arf_clear(y); arf_clear(z); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-dump_str.c000066400000000000000000000034011461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_dump_str, state) { slong iter; /* just test no crashing... */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; char * s; arf_init(x); arf_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); s = arf_dump_str(x); flint_free(s); arf_clear(x); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; char * s; int conversion_error; arf_init(x); arf_init(y); arf_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); s = arf_dump_str(x); conversion_error = arf_load_str(y, s); if (conversion_error || !arf_equal(x, y)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("s = %s", s); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 50); flint_printf("\n\n"); flint_abort(); } flint_free(s); arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-floor.c000066400000000000000000000042261461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_floor, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; int result; arf_init(x); arf_init(y); arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); arf_floor(y, x); result = 1; if (arf_is_int(x) || !arf_is_finite(x)) { result = arf_equal(y, x); } else if (!arf_is_int(y)) { result = 0; } else if (arf_cmp(y, x) >= 0) { result = 0; } else { arf_t s, t[3]; /* check floor(x) - x + 1 > 0 */ arf_init(s); arf_init(t[0]); arf_init(t[1]); arf_init(t[2]); arf_set(t[0], y); arf_neg(t[1], x); arf_one(t[2]); arf_sum(s, (arf_ptr) t, 3, 32, ARF_RND_DOWN); result = arf_sgn(s) > 0; arf_clear(s); arf_clear(t[0]); arf_clear(t[1]); arf_clear(t[2]); } if (!result) { flint_printf("FAIL!\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_abort(); } arf_floor(x, x); if (!arf_equal(x, y)) { flint_printf("FAIL (aliasing)!\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-fma.c000066400000000000000000000100151461254215100163160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_fma_naive(arf_t res, const arf_t x, const arf_t y, const arf_t z, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(res, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_fma, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, res1, res2; slong prec, r1, r2; arf_rnd_t rnd; int aliasing; arf_init(x); arf_init(y); arf_init(z); arf_init(res1); arf_init(res2); prec = 2 + n_randint(state, 200); arf_randtest_special(x, state, 200, 100); arf_randtest_special(y, state, 200, 100); arf_randtest_special(z, state, 200, 100); arf_randtest_special(res1, state, 200, 100); arf_randtest_special(res2, state, 200, 100); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(y)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } aliasing = n_randint(state, 7); switch (aliasing) { case 0: r1 = arf_fma(res1, x, y, z, prec, rnd); r2 = arf_fma_naive(res2, x, y, z, prec, rnd); break; case 1: arf_set(res1, z); r1 = arf_fma(res1, x, y, res1, prec, rnd); r2 = arf_fma_naive(res2, x, y, z, prec, rnd); break; case 2: arf_set(res1, x); r1 = arf_fma(res1, res1, y, z, prec, rnd); r2 = arf_fma_naive(res2, x, y, z, prec, rnd); break; case 3: arf_set(res1, y); r1 = arf_fma(res1, x, res1, z, prec, rnd); r2 = arf_fma_naive(res2, x, y, z, prec, rnd); break; case 4: r1 = arf_fma(res1, x, x, z, prec, rnd); r2 = arf_fma_naive(res2, x, x, z, prec, rnd); break; case 5: arf_set(res1, x); r1 = arf_fma(res1, res1, res1, z, prec, rnd); r2 = arf_fma_naive(res2, x, x, z, prec, rnd); break; default: arf_set(res1, x); r1 = arf_fma(res1, res1, res1, res1, prec, rnd); r2 = arf_fma_naive(res2, x, x, x, prec, rnd); break; } if (!arf_equal(res1, res2) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d, aliasing = %d\n\n", prec, rnd, aliasing); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("res1 = "); arf_print(res1); flint_printf("\n\n"); flint_printf("res2 = "); arf_print(res2); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(res1); arf_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-frexp.c000066400000000000000000000042411461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_frexp, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z; fmpz_t e, f; int ok; arf_init(x); arf_init(y); arf_init(z); fmpz_init(e); fmpz_init(f); arf_randtest_special(x, state, 200, 100); arf_randtest_special(y, state, 200, 100); fmpz_randtest(e, state, 100); fmpz_randtest(f, state, 100); arf_frexp(y, e, x); arf_mul_2exp_fmpz(z, y, e); ok = 1; if (!arf_equal(z, x)) ok = 0; if (arf_is_special(x) && !fmpz_is_zero(e)) ok = 0; if (!arf_is_special(x) && !(arf_cmpabs_2exp_si(y, 0) < 0 && arf_cmpabs_2exp_si(y, -1) >= 0)) ok = 0; if (!ok) { printf("FAIL\n"); printf("x = "); arf_print(x); printf("\n\n"); printf("y = "); arf_print(y); printf("\n\n"); printf("z = "); arf_print(z); printf("\n\n"); printf("e = "); fmpz_print(e); printf("\n\n"); printf("f = "); fmpz_print(f); printf("\n\n"); flint_abort(); } arf_frexp(x, f, x); if (!arf_equal(x, y) || !fmpz_equal(e, f)) { printf("FAIL (aliasing)\n"); printf("x = "); arf_print(x); printf("\n\n"); printf("y = "); arf_print(y); printf("\n\n"); printf("z = "); arf_print(z); printf("\n\n"); printf("e = "); fmpz_print(e); printf("\n\n"); printf("f = "); fmpz_print(f); printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); fmpz_clear(e); fmpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-get_d.c000066400000000000000000000076001461254215100166430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" TEST_FUNCTION_START(arf_get_d, state) { slong iter; /* test exact roundtrip */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z; double y; arf_rnd_t rnd; arf_init(x); arf_init(z); switch (n_randint(state, 4)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } arf_randtest_special(x, state, 53, 8); y = arf_get_d(x, rnd); arf_set_d(z, y); if (!arf_equal(x, z)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %.17g\n\n", y); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(z); } /* test rounding */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, w; arf_rnd_t rnd; double y; arf_init(x); arf_init(z); arf_init(w); arf_randtest_special(x, state, 300, 8); switch (n_randint(state, 4)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; default: rnd = ARF_RND_CEIL; break; } y = arf_get_d(x, rnd); arf_set_d(w, y); arf_set_round(z, x, 53, rnd); if (!arf_equal(w, z)) { flint_printf("FAIL:\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %.17g\n\n", y); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(z); arf_clear(w); } /* compare with mpfr */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, r1, r2; arf_rnd_t rnd; mpfr_t t; double d1, d2; arf_init(x); arf_init(r1); arf_init(r2); mpfr_init2(t, 300); arf_randtest_special(x, state, 300, 20); arf_get_mpfr(t, x, MPFR_RNDD); switch (n_randint(state, 4)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } d1 = arf_get_d(x, rnd); d2 = mpfr_get_d(t, arf_rnd_to_mpfr(rnd)); arf_set_d(r1, d1); arf_set_d(r2, d2); if (!arf_equal(r1, r2)) { flint_printf("FAIL:\n\n"); flint_printf("rnd = %i\n\n", rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("d1 = %.17g\n\n", d1); flint_printf("d2 = %.17g\n\n", d2); flint_printf("r1 = "); arf_print(r1); flint_printf("\n\n"); flint_printf("r2 = "); arf_print(r2); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(r1); arf_clear(r2); mpfr_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-get_fmpz.c000066400000000000000000000114541461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_get_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, x2; fmpz_t z, z2, e; int ret1, ret2; arf_init(x); arf_init(x2); fmpz_init(z); fmpz_init(z2); fmpz_init(e); arf_randtest(x, state, 2 + n_randint(state, 1000), 10); fmpz_randtest(z, state, 1 + n_randint(state, 1000)); fmpz_randtest(z2, state, 1 + n_randint(state, 1000)); fmpz_randtest(e, state, 1 + n_randint(state, 200)); arf_mul_2exp_fmpz(x2, x, e); ret1 = arf_get_fmpz(z, x, ARF_RND_DOWN); ret2 = arf_get_fmpz_fixed_fmpz(z2, x2, e); if (!fmpz_equal(z, z2) || (ret1 != ret2)) { flint_printf("FAIL (fixed_fmpz)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("x2 = "); arf_print(x2); flint_printf("\n\n"); flint_printf("z = "); fmpz_print(z); flint_printf("\n\n"); flint_printf("z2 = "); fmpz_print(z2); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } arf_clear(x); arf_clear(x2); fmpz_clear(z); fmpz_clear(z2); fmpz_clear(e); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, x2; fmpz_t z, z2; slong e; int ret1, ret2; arf_init(x); arf_init(x2); fmpz_init(z); fmpz_init(z2); arf_randtest(x, state, 2 + n_randint(state, 1000), 10); fmpz_randtest(z, state, 1 + n_randint(state, 1000)); fmpz_randtest(z2, state, 1 + n_randint(state, 1000)); e = n_randtest(state); arf_mul_2exp_si(x2, x, e); ret1 = arf_get_fmpz(z, x, ARF_RND_DOWN); ret2 = arf_get_fmpz_fixed_si(z2, x2, e); if (!fmpz_equal(z, z2) || (ret1 != ret2)) { flint_printf("FAIL (fixed_si)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("x2 = "); arf_print(x2); flint_printf("\n\n"); flint_printf("z = "); fmpz_print(z); flint_printf("\n\n"); flint_printf("z2 = "); fmpz_print(z2); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } arf_clear(x); arf_clear(x2); fmpz_clear(z); fmpz_clear(z2); } for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { slong bits; arf_t x; mpfr_t y; fmpz_t z, z2; mpz_t w; int ret1, ret2; bits = 2 + n_randint(state, 1000); arf_init(x); mpfr_init2(y, bits); fmpz_init(z); fmpz_init(z2); mpz_init(w); arf_randtest(x, state, bits, 10); fmpz_randtest(z, state, 1 + n_randint(state, 1000)); arf_get_mpfr(y, x, MPFR_RNDN); switch (n_randint(state, 5)) { case 0: ret1 = arf_get_fmpz(z, x, ARF_RND_FLOOR); ret2 = mpfr_get_z(w, y, MPFR_RNDD); break; case 1: ret1 = arf_get_fmpz(z, x, ARF_RND_CEIL); ret2 = mpfr_get_z(w, y, MPFR_RNDU); break; case 2: ret1 = arf_get_fmpz(z, x, ARF_RND_DOWN); ret2 = mpfr_get_z(w, y, MPFR_RNDZ); break; case 3: ret1 = arf_get_fmpz(z, x, ARF_RND_UP); ret2 = mpfr_get_z(w, y, MPFR_RNDA); break; default: ret1 = arf_get_fmpz(z, x, ARF_RND_NEAR); ret2 = mpfr_get_z(w, y, MPFR_RNDN); break; } fmpz_set_mpz(z2, w); if (!fmpz_equal(z, z2) || (ret1 != (ret2 != 0))) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); fmpz_print(z); flint_printf("\n\n"); flint_printf("z2 = "); fmpz_print(z2); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } arf_clear(x); mpfr_clear(y); fmpz_clear(z); fmpz_clear(z2); mpz_clear(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-get_mpfr.c000066400000000000000000000064501461254215100173660ustar00rootroot00000000000000/* Copyright (C) 2012, 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_get_mpfr, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits; arf_t x, z; mpfr_t y; bits = 2 + n_randint(state, 200); arf_init(x); arf_init(z); mpfr_init2(y, bits); arf_randtest_special(x, state, bits, 10); arf_get_mpfr(y, x, MPFR_RNDN); arf_set_mpfr(z, y); if (!arf_equal(x, z)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(z); mpfr_clear(y); } /* test set_mpfr out of range */ { arf_t x, z; mpfr_t y; fmpz_t e; int r; fmpz_init(e); arf_init(x); arf_init(z); mpfr_init2(y, 53); fmpz_one(e); fmpz_mul_2exp(e, e, 100); arf_set_si(x, 1); arf_mul_2exp_fmpz(x, x, e); r = arf_get_mpfr(y, x, MPFR_RNDN); arf_set_mpfr(x, y); if (!mpfr_inf_p(y) || mpfr_sgn(y) <= 0 || !mpfr_overflow_p()) { flint_printf("expected +inf with overflow\n\n"); arf_print(z); flint_printf("\n\n"); flint_printf("r = %d \n\n", r); flint_abort(); } mpfr_clear_flags(); arf_set_si(x, -1); arf_mul_2exp_fmpz(x, x, e); r = arf_get_mpfr(y, x, MPFR_RNDN); arf_set_mpfr(x, y); if (!mpfr_inf_p(y) || mpfr_sgn(y) >= 0 || !mpfr_overflow_p()) { flint_printf("expected -inf with overflow\n\n"); arf_print(z); flint_printf("\n\n"); flint_printf("r = %d \n\n", r); flint_abort(); } mpfr_clear_flags(); fmpz_neg(e, e); arf_set_si(x, 1); arf_mul_2exp_fmpz(x, x, e); r = arf_get_mpfr(y, x, MPFR_RNDN); arf_set_mpfr(x, y); if (!mpfr_zero_p(y) || mpfr_signbit(y) || !mpfr_underflow_p()) { flint_printf("expected +0 with underflow\n\n"); arf_print(z); flint_printf("\n\n"); flint_printf("r = %d \n\n", r); flint_abort(); } mpfr_clear_flags(); arf_set_si(x, -1); arf_mul_2exp_fmpz(x, x, e); r = arf_get_mpfr(y, x, MPFR_RNDN); arf_set_mpfr(x, y); if (!mpfr_zero_p(y) || !mpfr_signbit(y) || !mpfr_underflow_p()) { flint_printf("expected -0 with underflow\n\n"); arf_print(z); flint_printf("\n\n"); flint_printf("r = %d \n\n", r); flint_abort(); } mpfr_clear_flags(); arf_clear(x); arf_clear(z); mpfr_clear(y); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-get_str.c000066400000000000000000000030351461254215100172260ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" #include "arb.h" TEST_FUNCTION_START(arf_get_str, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; arb_t y; char *s1, * s2; slong d; arf_init(x); arb_init(y); arf_randtest_special(x, state, 2 + n_randint(state, 200), 2 + n_randint(state, 100)); arb_set_arf(y, x); d = 1 + n_randint(state, 200); s1 = arf_get_str(x, d); s2 = arb_get_str(y, d, ARB_STR_NO_RADIUS); if ((arf_is_pos_inf(x) && strcmp(s1, "+inf")) || (arf_is_neg_inf(x) && strcmp(s1, "-inf")) || (arf_is_nan(x) && strcmp(s1, "nan")) || (arf_is_finite(x) && strcmp(s1, s2))) { flint_printf("FAIL\n"); arf_print(x); flint_printf("\n"); arb_print(y); flint_printf("\n"); flint_printf("%s\n", s1); flint_printf("%s\n", s2); flint_abort(); } flint_free(s1); flint_free(s2); arf_clear(x); arb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-is_int_2exp_si.c000066400000000000000000000047001461254215100204750ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_is_int_2exp_si, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; fmpz_t t; slong e; int res1, res2; arf_init(x); arf_init(y); fmpz_init(t); arf_randtest_special(x, state, 2000, 100); e = n_randtest(state); arf_mul_2exp_si(y, x, e); res1 = arf_is_int(x); res2 = arf_is_int_2exp_si(y, e); if (res1 != res2) { flint_printf("FAIL! (1)\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("res1 = %d, res2 = %d\n\n", res1, res2); flint_abort(); } if (res1) { if (n_randint(state, 2)) arf_floor(y, x); else arf_ceil(y, x); if (!arf_equal(x, y) || !arf_is_finite(x)) { flint_printf("FAIL! (2)\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("res1 = %d\n\n", res1); flint_abort(); } } if (arf_is_finite(x) && !arf_is_zero(x)) { arf_bot(t, x); fmpz_neg(t, t); arf_mul_2exp_fmpz(x, x, t); res1 = arf_is_int(x); arf_mul_2exp_si(y, x, -1); res2 = arf_is_int(y); if (!arf_is_int(x) || arf_is_int(y)) { flint_printf("FAIL! (3)\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("res1 = %d, res2 = %d\n\n", res1, res2); flint_abort(); } } arf_clear(x); arf_clear(y); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-mul.c000066400000000000000000000125601461254215100163570ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" /* Defined in t-mul.c and t-mul_via_mpfr.c */ #ifndef arf_mul_naive #define arf_mul_naive arf_mul_naive /* todo: try some other code here also, e.g. fmpz roundtrip */ int arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { arf_mul(z, x, y, ARF_PREC_EXACT, rnd); return arf_set_round(z, z, prec, rnd); } #endif TEST_FUNCTION_START(arf_mul, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); prec = 2 + n_randint(state, 2000); if (n_randint(state, 50) == 0) prec = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) { case 0: r1 = arf_mul(z, x, y, prec, rnd); r2 = arf_mul_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_mul(z, x, x, prec, rnd); r2 = arf_mul_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_mul_naive(v, x, x, prec, rnd); r1 = arf_mul(x, x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_mul_naive(v, x, y, prec, rnd); r1 = arf_mul(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_mul_naive(v, x, y, prec, rnd); r1 = arf_mul(x, y, x, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-mul_fmpz.c000066400000000000000000000063261461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_mul_fmpz_naive(arf_t z, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_fmpz(t, y); r = arf_mul(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_mul_fmpz, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; fmpz_t y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); fmpz_init(y); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); fmpz_randtest(y, state, 2000); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10)) prec = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_mul_fmpz(z, x, y, prec, rnd); r2 = arf_mul_fmpz_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_mul_fmpz_naive(v, x, y, prec, rnd); r1 = arf_mul_fmpz(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-mul_si.c000066400000000000000000000062731461254215100170560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "long_extras.h" int arf_mul_si_naive(arf_t z, const arf_t x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_si(t, y); r = arf_mul(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_mul_si, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); y = z_randtest(state); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0) prec = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_mul_si(z, x, y, prec, rnd); r2 = arf_mul_si_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_mul_si_naive(v, x, y, prec, rnd); r1 = arf_mul_si(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-mul_ui.c000066400000000000000000000062741461254215100170610ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "ulong_extras.h" int arf_mul_ui_naive(arf_t z, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_ui(t, y); r = arf_mul(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_mul_ui, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; ulong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); y = n_randtest(state); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0) prec = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_mul_ui(z, x, y, prec, rnd); r2 = arf_mul_ui_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_mul_ui_naive(v, x, y, prec, rnd); r1 = arf_mul_ui(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-mul_via_mpfr.c000066400000000000000000000126701461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" /* Defined in t-mul.c and t-mul_via_mpfr.c */ #ifndef arf_mul_naive #define arf_mul_naive arf_mul_naive /* todo: try some other code here also, e.g. fmpz roundtrip */ int arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { arf_mul(z, x, y, ARF_PREC_EXACT, rnd); return arf_set_round(z, z, prec, rnd); } #endif TEST_FUNCTION_START(arf_mul_via_mpfr, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); prec = 2 + n_randint(state, 2000); if (n_randint(state, 50) == 0) prec = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) { case 0: r1 = arf_mul_via_mpfr(z, x, y, prec, rnd); r2 = arf_mul_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_mul_via_mpfr(z, x, x, prec, rnd); r2 = arf_mul_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_mul_naive(v, x, x, prec, rnd); r1 = arf_mul_via_mpfr(x, x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_mul_naive(v, x, y, prec, rnd); r1 = arf_mul_via_mpfr(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_mul_naive(v, x, y, prec, rnd); r1 = arf_mul_via_mpfr(x, y, x, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-neg_round.c000066400000000000000000000101361461254215100175370ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_neg_round, state) { slong iter; { arf_t x, y, z; arf_init(x); arf_init(y); arf_init(z); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits1, bits2; int ret1, ret2; mpfr_t g1, g2; fmpz_t e; arf_rnd_t rnd; bits1 = 1 + n_randint(state, 1000); bits2 = 2 + n_randint(state, 1000); if (n_randint(state, 100) == 0) bits2 = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } fmpz_init(e); mpfr_init2(g1, FLINT_MAX(2, bits1)); mpfr_init2(g2, FLINT_MIN(bits2, 10000)); if (n_randint(state, 100) == 0) { arf_clear(x); arf_clear(y); arf_clear(z); arf_init(x); arf_init(y); arf_init(z); } /* dirty output variables */ if (n_randint(state, 2)) { arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); } arf_randtest_special(x, state, bits1, 1 + n_randint(state, 10)); arf_get_mpfr(g1, x, MPFR_RNDD); /* exact */ /* test large exponents */ if (n_randint(state, 4) == 0) fmpz_randtest(e, state, 1 + n_randint(state, 100)); if (!arf_is_special(x)) fmpz_add(ARF_EXPREF(x), ARF_EXPREF(x), e); ret1 = arf_neg_round(y, x, bits2, rnd); ret2 = mpfr_neg(g2, g1, arf_rnd_to_mpfr(rnd)); arf_set_mpfr(z, g2); if (!arf_is_special(y)) fmpz_sub(ARF_EXPREF(y), ARF_EXPREF(y), e); if (!arf_equal(y, z) || ((ret1 == ARF_RESULT_EXACT) != (ret2 == 0))) { flint_printf("FAIL\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } if (!arf_is_special(x)) fmpz_add(ARF_EXPREF(x), ARF_EXPREF(x), e); ret1 = arf_neg_round(y, x, bits2, rnd); arf_set(z, x); ret2 = arf_neg_round(z, z, bits2, rnd); if (!arf_equal(y, z) || ret1 != ret2) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } mpfr_clear(g1); mpfr_clear(g2); fmpz_clear(e); } arf_clear(x); arf_clear(y); arf_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-root.c000066400000000000000000000072031461254215100165430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "arf.h" int arf_root_naive(arf_t z, const arf_t x, int k, slong prec, arf_rnd_t rnd) { fmpz_t t; mpfr_t u, v; int res; if ((k == 0) || (k > 1 && arf_sgn(x) < 0)) { arf_nan(z); return 0; } fmpz_init(t); if (arf_is_special(x)) fmpz_zero(t); else fmpz_fdiv_q_ui(t, ARF_EXPREF(x), k); fmpz_mul_ui(t, t, k); fmpz_neg(t, t); arf_mul_2exp_fmpz(z, x, t); mpfr_init2(u, FLINT_MAX(2, arf_bits(z))); mpfr_init2(v, prec); arf_get_mpfr(u, z, MPFR_RNDD); res = (mpfr_rootn_ui(v, u, k, arf_rnd_to_mpfr(rnd)) != 0); arf_set_mpfr(z, v); fmpz_neg(t, t); fmpz_tdiv_q_ui(t, t, k); arf_mul_2exp_fmpz(z, z, t); mpfr_clear(u); mpfr_clear(v); fmpz_clear(t); return res; } TEST_FUNCTION_START(arf_root, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong prec, r1, r2; ulong k; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 10; iter2++) { arf_randtest_special(x, state, 2000, 100); prec = 2 + n_randint(state, 2000); k = n_randint(state, 50); if (n_randint(state, 20) == 0) arf_mul(x, x, x, prec, ARF_RND_DOWN); else if (n_randint(state, 20) == 0) arf_mul(x, x, x, prec, ARF_RND_UP); switch (n_randint(state, 4)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; default: rnd = ARF_RND_CEIL; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_root(z, x, k, prec, rnd); r2 = arf_root_naive(v, x, k, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("k = %wu, prec = %wd, rnd = %d\n\n", k, prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_root_naive(v, x, k, prec, rnd); r1 = arf_root(x, x, k, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("k = %wu, prec = %wd, rnd = %d\n\n", k, prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-rsqrt.c000066400000000000000000000063341461254215100167370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" int arf_rsqrt_naive(arf_t z, const arf_t x, slong prec, arf_rnd_t rnd) { if (arf_is_special(x)) { return _arf_call_mpfr_func(z, NULL, (int (*)(void)) mpfr_rec_sqrt, x, NULL, prec, rnd); } else { fmpz_t t; int res; fmpz_init(t); fmpz_tdiv_q_2exp(t, ARF_EXPREF(x), 1); fmpz_mul_2exp(t, t, 1); fmpz_neg(t, t); arf_mul_2exp_fmpz(z, x, t); res = _arf_call_mpfr_func(z, NULL, (int (*)(void)) mpfr_rec_sqrt, z, NULL, prec, rnd); fmpz_tdiv_q_2exp(t, t, 1); arf_mul_2exp_fmpz(z, z, t); fmpz_clear(t); return res; } } TEST_FUNCTION_START(arf_rsqrt, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 4)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; default: rnd = ARF_RND_CEIL; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_rsqrt(z, x, prec, rnd); r2 = arf_rsqrt_naive(v, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_rsqrt_naive(v, x, prec, rnd); r1 = arf_rsqrt(x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_d.c000066400000000000000000000024361461254215100166610ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "double_extras.h" #include "arf.h" TEST_FUNCTION_START(arf_set_d, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { double x; arf_t y, z; mpfr_t m; arf_init(y); arf_init(z); mpfr_init2(m, 53); x = d_randtest_special(state, -1200, 1200); arf_set_d(y, x); mpfr_set_d(m, x, MPFR_RNDN); arf_set_mpfr(z, m); if (!arf_equal(y, z) || !arf_equal_d(y, x)) { flint_printf("FAIL:\n\n"); flint_printf("x = %.17g\n\n", x); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_abort(); } arf_clear(y); arf_clear(z); mpfr_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_fmpq.c000066400000000000000000000026641461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arf.h" TEST_FUNCTION_START(arf_set_fmpq, state) { slong iter; /* test exact roundtrip R -> Q -> R */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits, res; arf_t x, z; fmpq_t y; bits = 2 + n_randint(state, 200); arf_init(x); arf_init(z); fmpq_init(y); arf_randtest(x, state, bits, 10); arf_randtest(z, state, bits, 10); arf_get_fmpq(y, x); res = arf_set_fmpq(z, y, bits, ARF_RND_DOWN); if (!arf_equal(x, z) || res != 0) { flint_printf("FAIL\n\n"); flint_printf("bits: %wd\n", bits); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(z); fmpq_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_fmpz_2exp.c000066400000000000000000000030611461254215100203430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_set_fmpz_2exp, state) { slong iter; /* test exact roundtrip R -> Q -> R */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits; arf_t x, z; fmpz_t y, e; bits = 2 + n_randint(state, 200); arf_init(x); arf_init(z); fmpz_init(y); fmpz_init(e); arf_randtest(x, state, bits, 1 + n_randint(state, 100)); arf_randtest(z, state, bits, 1 + n_randint(state, 100)); arf_get_fmpz_2exp(y, e, x); arf_set_fmpz_2exp(z, y, e); if (!arf_equal(x, z)) { flint_printf("FAIL\n\n"); flint_printf("bits: %wd\n", bits); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(z); fmpz_clear(y); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_round.c000066400000000000000000000101361461254215100175610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_set_round, state) { slong iter; { arf_t x, y, z; arf_init(x); arf_init(y); arf_init(z); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits1, bits2; int ret1, ret2; mpfr_t g1, g2; fmpz_t e; arf_rnd_t rnd; bits1 = 1 + n_randint(state, 1000); bits2 = 2 + n_randint(state, 1000); if (n_randint(state, 100) == 0) bits2 = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } fmpz_init(e); mpfr_init2(g1, FLINT_MAX(2, bits1)); mpfr_init2(g2, FLINT_MIN(bits2, 10000)); if (n_randint(state, 100) == 0) { arf_clear(x); arf_clear(y); arf_clear(z); arf_init(x); arf_init(y); arf_init(z); } /* dirty output variables */ if (n_randint(state, 2)) { arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); } arf_randtest_special(x, state, bits1, 1 + n_randint(state, 10)); arf_get_mpfr(g1, x, MPFR_RNDD); /* exact */ /* test large exponents */ if (n_randint(state, 4) == 0) fmpz_randtest(e, state, 1 + n_randint(state, 100)); if (!arf_is_special(x)) fmpz_add(ARF_EXPREF(x), ARF_EXPREF(x), e); ret1 = arf_set_round(y, x, bits2, rnd); ret2 = mpfr_set(g2, g1, arf_rnd_to_mpfr(rnd)); arf_set_mpfr(z, g2); if (!arf_is_special(y)) fmpz_sub(ARF_EXPREF(y), ARF_EXPREF(y), e); if (!arf_equal(y, z) || ((ret1 == ARF_RESULT_EXACT) != (ret2 == 0))) { flint_printf("FAIL\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } if (!arf_is_special(x)) fmpz_add(ARF_EXPREF(x), ARF_EXPREF(x), e); ret1 = arf_set_round(y, x, bits2, rnd); arf_set(z, x); ret2 = arf_set_round(z, z, bits2, rnd); if (!arf_equal(y, z) || ret1 != ret2) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } mpfr_clear(g1); mpfr_clear(g2); fmpz_clear(e); } arf_clear(x); arf_clear(y); arf_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_round_fmpz.c000066400000000000000000000056541461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_set_round_fmpz, state) { slong iter; { arf_t x, y; arf_init(x); arf_init(y); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits1, bits2; int ret1, ret2; fmpz_t a; mpz_t b; mpfr_t g; arf_rnd_t rnd; bits1 = 1 + n_randint(state, 1000); bits2 = 2 + n_randint(state, 1000); if (n_randint(state, 100) == 0) bits2 = ARF_PREC_EXACT; fmpz_init(a); mpz_init(b); mpfr_init2(g, FLINT_MIN(bits2, 10000)); if (n_randint(state, 100) == 0) { arf_clear(x); arf_clear(y); arf_init(x); arf_init(y); } /* dirty output variables */ if (n_randint(state, 2)) { arf_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); } fmpz_randtest(a, state, bits1); fmpz_get_mpz(b, a); switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } ret1 = arf_set_round_fmpz(x, a, bits2, rnd); ret2 = mpfr_set_z(g, b, arf_rnd_to_mpfr(rnd)); arf_set_mpfr(y, g); arf_equal(x, y); if (!arf_equal(x, y) || ((ret1 == ARF_RESULT_EXACT) != (ret2 == 0))) { flint_printf("FAIL\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } fmpz_clear(a); mpz_clear(b); mpfr_clear(g); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_round_mpz.c000066400000000000000000000056521461254215100204560ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" TEST_FUNCTION_START(arf_set_round_mpz, state) { slong iter; { arf_t x, y; arf_init(x); arf_init(y); for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { slong bits1, bits2; int ret1, ret2; fmpz_t a; mpz_t b; mpfr_t g; arf_rnd_t rnd; bits1 = 1 + n_randint(state, 1000); bits2 = 2 + n_randint(state, 1000); if (n_randint(state, 100) == 0) bits2 = ARF_PREC_EXACT; fmpz_init(a); mpz_init(b); mpfr_init2(g, FLINT_MIN(bits2, 10000)); if (n_randint(state, 100) == 0) { arf_clear(x); arf_clear(y); arf_init(x); arf_init(y); } /* dirty output variables */ if (n_randint(state, 2)) { arf_randtest_special(x, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); } fmpz_randtest(a, state, bits1); fmpz_get_mpz(b, a); switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } ret1 = arf_set_round_mpz(x, b, bits2, rnd); ret2 = mpfr_set_z(g, b, arf_rnd_to_mpfr(rnd)); arf_set_mpfr(y, g); arf_equal(x, y); if (!arf_equal(x, y) || ((ret1 == ARF_RESULT_EXACT) != (ret2 == 0))) { flint_printf("FAIL\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } fmpz_clear(a); mpz_clear(b); mpfr_clear(g); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_round_ui.c000066400000000000000000000041621461254215100202600ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_set_round_ui, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; slong prec, fix1; int ret1, ret2; mp_limb_t t; arf_rnd_t rnd; prec = 2 + n_randint(state, 1000); arf_init(x); arf_init(y); arf_randtest_special(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arf_randtest_special(y, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); t = n_randtest(state); switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } if (t == 0) { arf_zero(x); ret1 = 0; } else { ret1 = _arf_set_round_mpn(x, &fix1, &t, 1, 0, prec, rnd); fmpz_set_si(ARF_EXPREF(x), FLINT_BITS + fix1); } ret2 = arf_set_round_ui(y, t, prec, rnd); if (!arf_equal(x, y) || (ret1 != ret2) || (ret2 == 0 && !arf_equal_ui(y, t))) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd", prec); flint_printf("\n\n"); flint_printf("t = %wu\n\n", t); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-set_round_uiui.c000066400000000000000000000046661461254215100206270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_set_round_uiui, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; slong prec, fix1, fix2; int ret1, ret2, sgnbit; mp_limb_t t[2]; arf_rnd_t rnd; prec = 2 + n_randint(state, 1000); arf_init(x); arf_init(y); arf_randtest_special(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arf_randtest_special(y, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); do { t[0] = n_randtest(state); t[1] = n_randtest(state); } while (t[0] == 0 && t[1] == 0); sgnbit = n_randint(state, 2); switch (n_randint(state, 10)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } if (t[1] != 0) { ret1 = _arf_set_round_mpn(x, &fix1, t, 2, sgnbit, prec, rnd); fmpz_set_si(ARF_EXPREF(x), 2 * FLINT_BITS + fix1); } else { ret1 = _arf_set_round_mpn(x, &fix1, t, 1, sgnbit, prec, rnd); fmpz_set_si(ARF_EXPREF(x), FLINT_BITS + fix1); } ret2 = _arf_set_round_uiui(y, &fix2, t[1], t[0], sgnbit, prec, rnd); fmpz_set_si(ARF_EXPREF(y), 2 * FLINT_BITS + fix2); if (!arf_equal(x, y) || (ret1 != ret2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd", prec); flint_printf("\n\n"); flint_printf("hi = %wu, lo = %wu\n\n", t[1], t[0]); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } arf_clear(x); arf_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sgn.c000066400000000000000000000026271461254215100163540ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_sgn, state) { slong ix; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { arf_t x; int sgn; arf_init(x); arf_randtest_special(x, state, 30, 30); sgn = arf_sgn(x); switch (sgn) { case -1: if (arf_is_neg_inf(x) || arf_cmp_si(x, 0) < 0) break; else goto fail; case 0: if (arf_is_zero(x) || arf_is_nan(x)) break; else goto fail; case 1: if (arf_is_pos_inf(x) || arf_cmp_si(x, 0) > 0) break; else goto fail; default: fail: flint_throw(FLINT_TEST_FAIL, "x = %{arf}\n" "sgn = %d\n", x, sgn); } arf_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sosq.c000066400000000000000000000127761461254215100165600ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_sosq_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul(t, x, x, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(z, y, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_add(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_sosq, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); arf_randtest_special(z, state, 2000, 100); arf_randtest_special(v, state, 2000, 100); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(y)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) { case 0: r1 = arf_sosq(z, x, y, prec, rnd); r2 = arf_sosq_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_sosq(z, x, x, prec, rnd); r2 = arf_sosq_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_sosq_naive(v, x, y, prec, rnd); r1 = arf_sosq(x, x, y, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_sosq_naive(v, x, y, prec, rnd); r1 = arf_sosq(y, x, y, prec, rnd); if (!arf_equal(v, y) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_sosq_naive(v, x, x, prec, rnd); r1 = arf_sosq(x, x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sqrt.c000066400000000000000000000066541461254215100165620ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" int arf_sqrt_naive(arf_t z, const arf_t x, slong prec, arf_rnd_t rnd) { if (arf_is_special(x)) { return _arf_call_mpfr_func(z, NULL, (int (*)(void)) mpfr_sqrt, x, NULL, prec, rnd); } else { fmpz_t t; int res; fmpz_init(t); fmpz_tdiv_q_2exp(t, ARF_EXPREF(x), 1); fmpz_mul_2exp(t, t, 1); fmpz_neg(t, t); arf_mul_2exp_fmpz(z, x, t); res = _arf_call_mpfr_func(z, NULL, (int (*)(void)) mpfr_sqrt, z, NULL, prec, rnd); fmpz_neg(t, t); fmpz_tdiv_q_2exp(t, t, 1); arf_mul_2exp_fmpz(z, z, t); fmpz_clear(t); return res; } } TEST_FUNCTION_START(arf_sqrt, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); prec = 2 + n_randint(state, 2000); if (n_randint(state, 20) == 0) arf_mul(x, x, x, prec, ARF_RND_DOWN); else if (n_randint(state, 20) == 0) arf_mul(x, x, x, prec, ARF_RND_UP); switch (n_randint(state, 4)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; default: rnd = ARF_RND_CEIL; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_sqrt(z, x, prec, rnd); r2 = arf_sqrt_naive(v, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_sqrt_naive(v, x, prec, rnd); r1 = arf_sqrt(x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sub.c000066400000000000000000000134471461254215100163600ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_sub_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { int r; arf_t t; arf_init(t); arf_neg(t, y); r = arf_add(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_sub, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; fmpz_t t; arf_init(x); arf_init(y); arf_init(z); arf_init(v); fmpz_init(t); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } rnd = ARF_RND_DOWN; if (arf_is_normal(x) && arf_is_normal(y)) { fmpz_sub(t, ARF_EXPREF(x), ARF_EXPREF(y)); /* if not too far apart, sometimes test exact addition */ if (fmpz_bits(t) < 10) { if (n_randint(state, 10) == 0) prec = ARF_PREC_EXACT; } else if (rnd == ARF_RND_NEAR) { /* large shift not supported in add_naive */ rnd = ARF_RND_DOWN; } } switch (n_randint(state, 5)) { case 0: r1 = arf_sub(z, x, y, prec, rnd); r2 = arf_sub_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_sub(z, x, x, prec, rnd); r2 = arf_sub_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_sub_naive(v, x, x, prec, rnd); r1 = arf_sub(x, x, x, prec, rnd); if (!arf_equal(v, x) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_sub_naive(v, x, y, prec, rnd); r1 = arf_sub(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_sub_naive(v, y, x, prec, rnd); r1 = arf_sub(x, y, x, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sub_fmpz.c000066400000000000000000000064301461254215100174060ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_sub_fmpz_naive(arf_t z, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_fmpz(t, y); r = arf_sub(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_sub_fmpz, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; fmpz_t y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); fmpz_init(y); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); fmpz_randtest(y, state, 2000); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_sub_fmpz(z, x, y, prec, rnd); r2 = arf_sub_fmpz_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_sub_fmpz_naive(v, x, y, prec, rnd); r1 = arf_sub_fmpz(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sub_si.c000066400000000000000000000063701461254215100170500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "long_extras.h" int arf_sub_si_naive(arf_t z, const arf_t x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_si(t, y); r = arf_sub(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_sub_si, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); y = z_randtest(state); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_sub_si(z, x, y, prec, rnd); r2 = arf_sub_si_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_sub_si_naive(v, x, y, prec, rnd); r1 = arf_sub_si(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sub_ui.c000066400000000000000000000063711461254215100170530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "ulong_extras.h" int arf_sub_ui_naive(arf_t z, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; int r; arf_init(t); arf_set_ui(t, y); r = arf_sub(z, x, t, prec, rnd); arf_clear(t); return r; } TEST_FUNCTION_START(arf_sub_ui, state) { slong iter, iter2; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; ulong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); y = n_randtest(state); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_sub_ui(z, x, y, prec, rnd); r2 = arf_sub_ui_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_sub_ui_naive(v, x, y, prec, rnd); r1 = arf_sub_ui(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); flint_printf("%wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-submul.c000066400000000000000000000127731461254215100170770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_submul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_submul, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, v; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); arf_randtest_special(y, state, 2000, 100); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(y)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) { case 0: r1 = arf_submul(z, x, y, prec, rnd); r2 = arf_submul_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 1: r1 = arf_submul(z, x, x, prec, rnd); r2 = arf_submul_naive(v, x, x, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 1)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 2: r2 = arf_submul_naive(v, v, v, prec, rnd); r1 = arf_submul(z, z, z, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing 2)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; case 3: r2 = arf_submul_naive(v, v, y, prec, rnd); r1 = arf_submul(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing 3)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_submul_naive(v, x, v, prec, rnd); r1 = arf_submul(z, x, z, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL (aliasing 4)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-submul_fmpz.c000066400000000000000000000067651461254215100201370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_submul_fmpz_naive(arf_t z, const arf_t x, const fmpz_t y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul_fmpz(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_submul_fmpz, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; fmpz_t y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); fmpz_init(y); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); fmpz_randtest(y, state, 2000); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_submul_fmpz(z, x, y, prec, rnd); r2 = arf_submul_fmpz_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_debug(z); flint_printf("\n\n"); flint_printf("v = "); arf_debug(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_submul_fmpz_naive(v, v, y, prec, rnd); r1 = arf_submul_fmpz(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); fmpz_clear(y); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-submul_si.c000066400000000000000000000066611461254215100175710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "long_extras.h" int arf_submul_si_naive(arf_t z, const arf_t x, slong y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul_si(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_submul_si, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; slong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); y = z_randtest(state); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_submul_si(z, x, y, prec, rnd); r2 = arf_submul_si_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_debug(z); flint_printf("\n\n"); flint_printf("v = "); arf_debug(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_submul_si_naive(v, v, y, prec, rnd); r1 = arf_submul_si(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = %wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-submul_ui.c000066400000000000000000000066301461254215100175670ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" int arf_submul_ui_naive(arf_t z, const arf_t x, ulong y, slong prec, arf_rnd_t rnd) { arf_t t; int inexact; arf_init(t); arf_mul_ui(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } TEST_FUNCTION_START(arf_submul_ui, state) { slong iter, iter2; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, z, v; ulong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); y = n_randtest(state); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_submul_ui(z, x, y, prec, rnd); r2 = arf_submul_ui_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %wu", y); flint_printf("\n\n"); flint_printf("z = "); arf_debug(z); flint_printf("\n\n"); flint_printf("v = "); arf_debug(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; default: r2 = arf_submul_ui_naive(v, v, y, prec, rnd); r1 = arf_submul_ui(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = %wu", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); flint_abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/test/t-sum.c000066400000000000000000000067671461254215100164020ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" TEST_FUNCTION_START(arf_sum, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { slong i, len, prec, bits, expbits; int res1, res2; arf_t s1, s2, s3, err; mag_t err_bound; arf_struct terms[20]; arf_rnd_t rnd; len = n_randint(state, 20); bits = 2 + n_randint(state, 1000); prec = 2 + n_randint(state, 1000); expbits = n_randint(state, 14); arf_init(s1); arf_init(s2); arf_init(s3); arf_init(err); mag_init(err_bound); for (i = 0; i < len; i++) { arf_init(terms + i); arf_randtest_special(terms + i, state, bits, expbits); } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } res1 = arf_sum(s1, terms, len, prec, rnd); arf_zero(s2); for (i = 0; i < len; i++) arf_add(s2, s2, terms + i, ARF_PREC_EXACT, ARF_RND_DOWN); res2 = arf_set_round(s3, s2, prec, rnd); if (!arf_equal(s1, s3) || res1 != res2) { flint_printf("FAIL (%wd)\n\n", iter); flint_printf("prec = %wd\n\n", prec); for (i = 0; i < len; i++) { flint_printf("terms[%wd] = ", i); arf_print(terms + i); flint_printf("\n\n"); } flint_printf("s1 = "); arf_print(s1); flint_printf("\n\n"); flint_printf("s2 = "); arf_print(s2); flint_printf("\n\n"); flint_printf("s3 = "); arf_print(s3); flint_printf("\n\n"); flint_printf("res1 = %d, res2 = %d\n\n", res1, res2); flint_abort(); } arf_sub(err, s1, s2, ARF_PREC_EXACT, ARF_RND_DOWN); arf_abs(err, err); if (res1) arf_mag_set_ulp(err_bound, s1, prec); else mag_zero(err_bound); if (arf_cmpabs_mag(err, err_bound) > 0) { flint_printf("FAIL (error bound)!\n"); flint_printf("prec = %wd\n\n", prec); for (i = 0; i < len; i++) { flint_printf("terms[%wd] = ", i); arf_print(terms + i); flint_printf("\n\n"); } flint_printf("s1 = "); arf_print(s1); flint_printf("\n\n"); flint_printf("s2 = "); arf_print(s2); flint_printf("\n\n"); flint_printf("s3 = "); arf_print(s3); flint_printf("\n\n"); flint_printf("error: "); arf_print(err); flint_printf("\n\n"); flint_printf("error bound: "); mag_print(err_bound); flint_printf("\n\n"); flint_printf("res1 = %d, res2 = %d\n\n", res1, res2); flint_abort(); } arf_clear(s1); arf_clear(s2); arf_clear(s3); arf_clear(err); mag_clear(err_bound); for (i = 0; i < len; i++) arf_clear(terms + i); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arf/urandom.c000066400000000000000000000014161461254215100160050ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" void arf_urandom(arf_t x, flint_rand_t state, slong bits, arf_rnd_t rnd) { slong prec = bits; fmpz_t n; fmpz_t t; prec += 128; fmpz_init(n); fmpz_one(n); fmpz_mul_2exp(n, n, (ulong) prec); fmpz_init(t); fmpz_randm(t, state, n); arf_set_round_fmpz(x, t, bits, rnd); arf_mul_2exp_si(x, x, -prec); fmpz_clear(n); fmpz_clear(t); } flint-3.1.3/src/arf_types.h000066400000000000000000000024021461254215100155650ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARF_TYPES_H #define ARF_TYPES_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Note: may also be hardcoded in a few places. */ #define ARF_NOPTR_LIMBS 2 typedef struct { mp_limb_t d[ARF_NOPTR_LIMBS]; } mantissa_noptr_struct; typedef struct { mp_size_t alloc; mp_ptr d; } mantissa_ptr_struct; typedef union { mantissa_noptr_struct noptr; mantissa_ptr_struct ptr; } mantissa_struct; typedef struct { fmpz exp; mp_size_t size; mantissa_struct d; } arf_struct; typedef arf_struct arf_t[1]; typedef arf_struct * arf_ptr; typedef const arf_struct * arf_srcptr; typedef struct { arf_struct a; arf_struct b; } arf_interval_struct; typedef arf_interval_struct arf_interval_t[1]; typedef arf_interval_struct * arf_interval_ptr; typedef const arf_interval_struct * arf_interval_srcptr; #ifdef __cplusplus } #endif #endif /* ARF_TYPES_H */ flint-3.1.3/src/arith.h000066400000000000000000000151771461254215100147150ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ARITH_H #define ARITH_H #include "fmpq_types.h" #ifdef __cplusplus extern "C" { #endif /* Various arithmetic functions **********************************************/ #define arith_primorial fmpz_primorial void _arith_harmonic_number(fmpz_t num, fmpz_t den, slong n); void arith_harmonic_number(fmpq_t x, slong n); void arith_ramanujan_tau(fmpz_t res, const fmpz_t n); void arith_ramanujan_tau_series(fmpz_poly_t res, slong n); void arith_divisors(fmpz_poly_t res, const fmpz_t n); #define arith_divisor_sigma fmpz_divisor_sigma #define arith_moebius_mu fmpz_moebius_mu #define arith_euler_phi fmpz_euler_phi /* Stirling numbers **********************************************************/ void arith_stirling_number_1u(fmpz_t s, ulong n, ulong k); void arith_stirling_number_1(fmpz_t s, ulong n, ulong k); void arith_stirling_number_2(fmpz_t s, ulong n, ulong k); void arith_stirling_number_1u_vec(fmpz * row, ulong n, slong klen); void arith_stirling_number_1_vec(fmpz * row, ulong n, slong klen); void arith_stirling_number_2_vec(fmpz * row, ulong n, slong klen); void arith_stirling_number_1u_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen); void arith_stirling_number_1_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen); void arith_stirling_number_2_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen); void arith_stirling_matrix_1u(fmpz_mat_t mat); void arith_stirling_matrix_1(fmpz_mat_t mat); void arith_stirling_matrix_2(fmpz_mat_t mat); /* Bell numbers **************************************************************/ #if FLINT64 #define BELL_NUMBER_TAB_SIZE 26 #else #define BELL_NUMBER_TAB_SIZE 16 #endif FLINT_DLL extern const mp_limb_t bell_number_tab[]; double arith_bell_number_size(ulong n); void arith_bell_number(fmpz_t b, ulong n); void arith_bell_number_dobinski(fmpz_t res, ulong n); void arith_bell_number_multi_mod(fmpz_t res, ulong n); void arith_bell_number_vec(fmpz * b, slong n); void arith_bell_number_vec_recursive(fmpz * b, slong n); void arith_bell_number_vec_multi_mod(fmpz * b, slong n); mp_limb_t arith_bell_number_nmod(ulong n, nmod_t mod); void arith_bell_number_nmod_vec(mp_ptr b, slong n, nmod_t mod); void arith_bell_number_nmod_vec_recursive(mp_ptr b, slong n, nmod_t mod); int arith_bell_number_nmod_vec_series(mp_ptr b, slong n, nmod_t mod); void arith_bell_number_nmod_vec_ogf(mp_ptr res, slong len, nmod_t mod); /* Euler numbers *************************************************************/ #if FLINT64 #define SMALL_EULER_LIMIT 25 #else #define SMALL_EULER_LIMIT 15 #endif static const mp_limb_t euler_number_small[] = { UWORD(1), UWORD(1), UWORD(5), UWORD(61), UWORD(1385), UWORD(50521), UWORD(2702765), UWORD(199360981), #if FLINT64 UWORD(19391512145), UWORD(2404879675441), UWORD(370371188237525), UWORD(69348874393137901), UWORD(15514534163557086905) #endif }; double arith_euler_number_size(ulong n); void arith_euler_number_vec(fmpz * res, slong n); void arith_euler_number(fmpz_t res, ulong n); void arith_euler_polynomial(fmpq_poly_t poly, ulong n); /* Bernoulli numbers *********************************************************/ #if FLINT64 #define BERNOULLI_SMALL_NUMER_LIMIT 35 #else #define BERNOULLI_SMALL_NUMER_LIMIT 27 #endif static const slong _bernoulli_numer_small[] = { WORD(1), WORD(1), WORD(-1), WORD(1), WORD(-1), WORD(5), WORD(-691), WORD(7), WORD(-3617), WORD(43867), WORD(-174611), WORD(854513), WORD(-236364091), WORD(8553103), #if FLINT64 WORD(-23749461029), WORD(8615841276005), WORD(-7709321041217), WORD(2577687858367) #endif }; void _arith_bernoulli_number(fmpz_t num, fmpz_t den, ulong n); void arith_bernoulli_number(fmpq_t x, ulong n); void _arith_bernoulli_number_vec(fmpz * num, fmpz * den, slong n); void arith_bernoulli_number_vec(fmpq * num, slong n); void arith_bernoulli_number_denom(fmpz_t den, ulong n); double arith_bernoulli_number_size(ulong n); void arith_bernoulli_polynomial(fmpq_poly_t poly, ulong n); void _arith_bernoulli_number_vec_multi_mod(fmpz * num, fmpz * den, slong n); void _arith_bernoulli_number_vec_recursive(fmpz * num, fmpz * den, slong n); /* Cyclotomic polynomials ****************************************************/ #define _arith_cyclotomic_polynomial _fmpz_poly_cyclotomic #define arith_cyclotomic_polynomial fmpz_poly_cyclotomic /* Hypergeometric polynomials ************************************************/ #define _arith_chebyshev_t_polynomial _fmpz_poly_chebyshev_t #define arith_chebyshev_t_polynomial fmpz_poly_chebyshev_t #define _arith_chebyshev_u_polynomial _fmpz_poly_chebyshev_u #define arith_chebyshev_u_polynomial fmpz_poly_chebyshev_u #define arith_legendre_polynomial fmpq_poly_legendre_p /* Swinnerton-Dyer polynomials ***********************************************/ #define _arith_swinnerton_dyer_polynomial _fmpz_poly_swinnerton_dyer #define arith_swinnerton_dyer_polynomial fmpz_poly_swinnerton_dyer /* Landau function ***********************************************************/ void arith_landau_function_vec(fmpz * res, slong len); /* Dedekind sums *************************************************************/ #define arith_dedekind_sum_naive fmpq_dedekind_sum_naive #define arith_dedekind_sum fmpq_dedekind_sum /* Exponential sums **********************************************************/ typedef struct { int n; int prefactor; mp_limb_t sqrt_p; mp_limb_t sqrt_q; mp_limb_signed_t cos_p[FLINT_BITS]; mp_limb_t cos_q[FLINT_BITS]; } trig_prod_struct; typedef trig_prod_struct trig_prod_t[1]; FLINT_FORCE_INLINE void trig_prod_init(trig_prod_t sum) { sum->n = 0; sum->prefactor = 1; sum->sqrt_p = 1; sum->sqrt_q = 1; } void arith_hrr_expsum_factored(trig_prod_t prod, mp_limb_t k, mp_limb_t n); /* Number of partitions ******************************************************/ FLINT_DLL extern const unsigned int partitions_lookup[128]; void arith_number_of_partitions_nmod_vec(mp_ptr res, slong len, nmod_t mod); void arith_number_of_partitions_vec(fmpz * res, slong len); void arith_number_of_partitions(fmpz_t x, ulong n); /* Number of sums of squares representations *********************************/ void arith_sum_of_squares(fmpz_t r, ulong k, const fmpz_t n); void arith_sum_of_squares_vec(fmpz * r, ulong k, slong n); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/arith/000077500000000000000000000000001461254215100145315ustar00rootroot00000000000000flint-3.1.3/src/arith/bell_number.c000066400000000000000000000045241461254215100171700ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "arith.h" #if FLINT_BITS == 64 #define MAX_N_1LIMBS 25 #define MAX_N_2LIMBS 42 #define MAX_N_3LIMBS 58 #else #define MAX_N_1LIMBS 15 #define MAX_N_2LIMBS 25 #define MAX_N_3LIMBS 34 #endif static void arith_bell_number_recursive(fmpz_t res, ulong n) { mp_limb_t t[3 * MAX_N_3LIMBS]; slong i, k; t[0] = 1; for (i = 1; i < FLINT_MIN(n, MAX_N_1LIMBS); i++) { t[i] = t[0]; for (k = i; k >= 1; k--) t[k - 1] += t[k]; } if (n <= MAX_N_1LIMBS) { fmpz_set_ui(res, t[0]); return; } for (k = i - 1; k >= 0; k--) { t[2 * k + 0] = t[k]; t[2 * k + 1] = 0; } for ( ; i < FLINT_MIN(n, MAX_N_2LIMBS); i++) { t[2 * i + 0] = t[0]; t[2 * i + 1] = t[1]; for (k = i; k >= 1; k--) add_ssaaaa(t[2 * (k - 1) + 1], t[2 * (k - 1)], t[2 * (k - 1) + 1], t[2 * (k - 1)], t[2 * k + 1], t[2 * k]); } if (n <= MAX_N_2LIMBS) { fmpz_set_uiui(res, t[1], t[0]); return; } for (k = i - 1; k >= 0; k--) { t[3 * k + 2] = 0; t[3 * k + 1] = t[2 * k + 1]; t[3 * k + 0] = t[2 * k]; } for ( ; i < n; i++) { t[3 * i + 0] = t[0]; t[3 * i + 1] = t[1]; t[3 * i + 2] = t[2]; for (k = i; k >= 1; k--) add_sssaaaaaa(t[3 * (k - 1) + 2], t[3 * (k - 1) + 1], t[3 * (k - 1)], t[3 * (k - 1) + 2], t[3 * (k - 1) + 1], t[3 * (k - 1)], t[3 * k + 2], t[3 * k + 1], t[3 * k]); } fmpz_set_ui_array(res, t, 3); } void arith_bell_number(fmpz_t res, ulong n) { if (n <= MAX_N_1LIMBS) fmpz_set_ui(res, bell_number_tab[n]); else if (n <= MAX_N_3LIMBS) arith_bell_number_recursive(res, n); else if (n <= 3400) arith_bell_number_dobinski(res, n); else arith_bell_number_multi_mod(res, n); } flint-3.1.3/src/arith/bell_number_dobinski.c000066400000000000000000000035541461254215100210540ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif void arith_bell_number_dobinski(fmpz_t res, ulong n) { fmpz_t P, Q, t; fmpz * pow; slong N, k, kodd, shift; if (n <= 1) { fmpz_one(res); return; } N = n * (1 + 1.2 / log(n)) + 2; fmpz_init(P); fmpz_init(Q); fmpz_init(t); pow = _fmpz_vec_init((N + 2) / 4); fmpz_one(P); fmpz_mul_2exp(P, P, n); fmpz_add_ui(P, P, 2); fmpz_set_ui(Q, 5); for (k = 3; k <= N; k++) { fmpz_mul_ui(P, P, k); if (k % 2 == 1) { if (2 * k <= N) { fmpz_ui_pow_ui(pow + k / 2, k, n); fmpz_add(P, P, pow + k / 2); } else { fmpz_ui_pow_ui(t, k, n); fmpz_add(P, P, t); } } else { kodd = k / 2; shift = n; while (kodd % 2 == 0) { kodd = kodd / 2; shift += n; } if (kodd == 1) fmpz_one_2exp(t, shift); else fmpz_mul_2exp(t, pow + kodd / 2, shift); fmpz_add(P, P, t); } fmpz_mul_ui(Q, Q, k); fmpz_add_ui(Q, Q, 1); } fmpz_cdiv_q(res, P, Q); _fmpz_vec_clear(pow, (N + 2) / 4); fmpz_clear(P); fmpz_clear(Q); fmpz_clear(t); } flint-3.1.3/src/arith/bell_number_multi_mod.c000066400000000000000000000067101461254215100212400ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "arith.h" static mp_limb_t arith_bell_number_nmod2(unsigned int * divtab, mp_ptr facs, mp_ptr pows, ulong n, nmod_t mod) { mp_limb_t s, t, u, v, s2, s1, s0, t1, t0; mp_limb_t qq[3]; slong i; /* Compute inverse factorials */ /* We actually compute (n! / i!) and divide out (n!)^2 at the end */ facs[n] = 1; for (i = n - 1; i >= 0; i--) facs[i] = _nmod_mul_fullword(facs[i + 1], i + 1, mod); /* Compute powers */ pows[0] = nmod_pow_ui(0, n, mod); pows[1] = nmod_pow_ui(1, n, mod); for (i = 2; i <= n; i++) { if (divtab[2 * i] == 1) pows[i] = nmod_pow_ui(i, n, mod); else pows[i] = _nmod_mul_fullword(pows[divtab[2 * i]], pows[divtab[2 * i + 1]], mod); } s2 = s1 = s0 = 0; for (t = i = 0; i <= n; i++) { if (i % 2 == 0) t = nmod_add(t, facs[i], mod); else t = nmod_sub(t, facs[i], mod); u = pows[n - i]; v = facs[n - i]; u = _nmod_mul_fullword(u, v, mod); umul_ppmm(t1, t0, u, t); add_sssaaaaaa(s2, s1, s0, s2, s1, s0, 0, t1, t0); } qq[2] = s2; qq[1] = s1; qq[0] = s0; s = mpn_mod_1(qq, 3, mod.n); /* Remove (n!)^2 */ u = nmod_inv(facs[0], mod); u = _nmod_mul_fullword(u, u, mod); s = _nmod_mul_fullword(s, u, mod); return s; } static void divisor_table(unsigned int * tab, slong len) { slong i, j; for (i = 0; i < len; i++) { tab[2 * i] = 1; tab[2 * i + 1] = i; } for (i = 2; i < len; i++) { for (j = 2; j <= i && i * j < len; j++) { tab[2 * i * j] = j; tab[2 * i * j + 1] = i; } } } void arith_bell_number_multi_mod(fmpz_t res, ulong n) { fmpz_comb_temp_t temp; fmpz_comb_t comb; nmod_t mod; mp_ptr primes, residues, t, u; slong k, num_primes; flint_bitcnt_t size, prime_bits; unsigned int * divtab; if (n <= 1) { fmpz_one(res); return; } size = arith_bell_number_size(n) + 1; prime_bits = FLINT_BITS - 1; num_primes = (size + prime_bits - 1) / prime_bits; primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); divtab = flint_malloc(2 * sizeof(unsigned int) * (n + 1)); t = flint_malloc((n + 1) * sizeof(mp_limb_t)); u = flint_malloc((n + 1) * sizeof(mp_limb_t)); divisor_table(divtab, n + 1); primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); for (k = 1; k < num_primes; k++) primes[k] = n_nextprime(primes[k-1], 0); for (k = 0; k < num_primes; k++) { nmod_init(&mod, primes[k]); residues[k] = arith_bell_number_nmod2(divtab, t, u, n, mod); } fmpz_comb_init(comb, primes, num_primes); fmpz_comb_temp_init(temp, comb); fmpz_multi_CRT_ui(res, residues, comb, temp, 0); fmpz_comb_clear(comb); fmpz_comb_temp_clear(temp); flint_free(primes); flint_free(residues); flint_free(divtab); flint_free(t); flint_free(u); } flint-3.1.3/src/arith/bell_number_nmod.c000066400000000000000000000070311461254215100202010ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "arith.h" const mp_limb_t bell_number_tab[] = { UWORD(1), UWORD(1), UWORD(2), UWORD(5), UWORD(15), UWORD(52), UWORD(203), UWORD(877), UWORD(4140), UWORD(21147), UWORD(115975), UWORD(678570), UWORD(4213597), UWORD(27644437), UWORD(190899322), UWORD(1382958545), #if FLINT64 UWORD(10480142147), UWORD(82864869804), UWORD(682076806159), UWORD(5832742205057), UWORD(51724158235372), UWORD(474869816156751), UWORD(4506715738447323), UWORD(44152005855084346), UWORD(445958869294805289), UWORD(4638590332229999353), #endif }; static const char bell_mod_2[3] = {1, 1, 0}; static const char bell_mod_3[13] = {1, 1, 2, 2, 0, 1, 2, 1, 0, 0, 1, 0, 1}; mp_limb_t arith_bell_number_nmod_fallback(ulong n, nmod_t mod) { mp_ptr bvec; mp_limb_t s; if (n > WORD_MAX / 4) { flint_throw(FLINT_ERROR, "arith_bell_number_nmod: too large n\n"); } bvec = flint_malloc(sizeof(mp_limb_t) * (n + 1)); arith_bell_number_nmod_vec(bvec, n + 1, mod); s = bvec[n]; flint_free(bvec); return s; } mp_limb_t nmod_inv_check(mp_limb_t x, nmod_t mod); mp_limb_t arith_bell_number_nmod(ulong n, nmod_t mod) { mp_limb_t s, t, u, inv_fac; mp_ptr facs, pows; slong i, j; int success; if (n < BELL_NUMBER_TAB_SIZE) return n_mod2_preinv(bell_number_tab[n], mod.n, mod.ninv); if (mod.n == 2) return bell_mod_2[n % 3]; if (mod.n == 3) return bell_mod_3[n % 13]; if (mod.n <= n) return arith_bell_number_nmod_fallback(n, mod); /* Compute inverse factorials */ /* We actually compute (n! / i!) and divide out (n!)^2 at the end */ facs = flint_malloc(sizeof(mp_limb_t) * (n + 1)); facs[n] = 1; for (i = n - 1; i >= 0; i--) facs[i] = nmod_mul(facs[i + 1], i + 1, mod); inv_fac = facs[0]; inv_fac = nmod_inv_check(inv_fac, mod); success = (inv_fac != mod.n); if (!success) { s = arith_bell_number_nmod_fallback(n, mod); } else { mp_limb_t v, s2, s1, s0, t1, t0, qq[3]; /* Compute powers */ pows = flint_calloc(n + 1, sizeof(mp_limb_t)); pows[0] = nmod_pow_ui(0, n, mod); pows[1] = nmod_pow_ui(1, n, mod); for (i = 2; i <= n; i++) { if (pows[i] == 0) pows[i] = nmod_pow_ui(i, n, mod); for (j = 2; j <= i && i * j <= n; j++) if (pows[i * j] == 0) pows[i * j] = nmod_mul(pows[i], pows[j], mod); } s2 = s1 = s0 = 0; for (t = i = 0; i <= n; i++) { if (i % 2 == 0) t = nmod_add(t, facs[i], mod); else t = nmod_sub(t, facs[i], mod); u = pows[n - i]; v = facs[n - i]; u = nmod_mul(u, v, mod); umul_ppmm(t1, t0, u, t); add_sssaaaaaa(s2, s1, s0, s2, s1, s0, 0, t1, t0); } qq[2] = s2; qq[1] = s1; qq[0] = s0; s = mpn_mod_1(qq, 3, mod.n); /* Remove (n!)^2 */ u = inv_fac; u = nmod_mul(u, u, mod); s = nmod_mul(s, u, mod); flint_free(pows); } flint_free(facs); return s; } flint-3.1.3/src/arith/bell_number_nmod_vec.c000066400000000000000000000015761461254215100210460ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "arith.h" void arith_bell_number_nmod_vec(mp_ptr b, slong len, nmod_t mod) { if (len < 300) { arith_bell_number_nmod_vec_recursive(b, len, mod); } else { if (mod.n >= len && arith_bell_number_nmod_vec_series(b, len, mod)) return; if (len < 500 + NMOD_BITS(mod) * NMOD_BITS(mod)) arith_bell_number_nmod_vec_recursive(b, len, mod); else arith_bell_number_nmod_vec_ogf(b, len, mod); } } flint-3.1.3/src/arith/bell_number_nmod_vec_ogf.c000066400000000000000000000032351461254215100216730ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "arith.h" static void bsplit_nmod(mp_ptr R, mp_ptr Q, slong a, slong b, nmod_t mod) { if (b - a == 1) { R[0] = 0; R[1] = 1; Q[0] = 1; Q[1] = nmod_neg(nmod_set_ui(a, mod), mod); } else { slong m, len1, len2; mp_ptr R1, R2, Q1, Q2; m = a + (b - a) / 2; len1 = (m - a) + 1; len2 = (b - m) + 1; R1 = _nmod_vec_init(2 * len1 + 2 * len2); Q1 = R1 + len1; R2 = Q1 + len1; Q2 = R2 + len2; bsplit_nmod(R1, Q1, a, m, mod); bsplit_nmod(R2, Q2, m, b, mod); _nmod_poly_mul(R, Q2, len2, R1, len1, mod); _nmod_vec_add(R + (m - a), R + (m - a), R2, len2, mod); _nmod_poly_mul(Q, Q2, len2, Q1, len1, mod); _nmod_vec_clear(R1); } } void arith_bell_number_nmod_vec_ogf(mp_ptr res, slong len, nmod_t mod) { mp_ptr R, Q; if (len <= 2 || mod.n == 1) { arith_bell_number_nmod_vec_recursive(res, len, mod); return; } R = _nmod_vec_init(len + 1); Q = _nmod_vec_init(len + 1); bsplit_nmod(R, Q, 1, len, mod); _nmod_poly_div_series(res, R, len, Q, len, len, mod); res[0] = 1; _nmod_vec_clear(R); _nmod_vec_clear(Q); } flint-3.1.3/src/arith/bell_number_nmod_vec_recursive.c000066400000000000000000000020661461254215100231300ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "arith.h" void arith_bell_number_nmod_vec_recursive(mp_ptr b, slong n, nmod_t mod) { if (mod.n == 1 || n == 0) { _nmod_vec_zero(b, n); return; } b[0] = 1; if (n >= 2) b[1] = 1; if (n >= 3) { slong i, k; mp_ptr t; TMP_INIT; TMP_START; n -= 1; t = TMP_ALLOC(n * sizeof(mp_limb_t)); t[0] = 1; for (i = 1; i < n; i++) { t[i] = t[0]; for (k = i; k > 0; k--) t[k - 1] = n_addmod(t[k - 1], t[k], mod.n); b[i + 1] = t[0]; } TMP_END; } } flint-3.1.3/src/arith/bell_number_nmod_vec_series.c000066400000000000000000000037331461254215100224150ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "arith.h" mp_limb_t nmod_inv_check(mp_limb_t x, nmod_t mod) { mp_limb_t r, g; g = n_gcdinv(&r, x, mod.n); if (g != 1) return mod.n; return r; } int arith_bell_number_nmod_vec_series(mp_ptr res, slong n, nmod_t mod) { mp_limb_t c; mp_ptr tmp; slong k; int success; if (n <= 0) return 1; if (mod.n == 1) return 0; tmp = flint_malloc(sizeof(mp_limb_t) * n); /* Compute inverse factorials */ c = 1; if (NMOD_BITS(mod) == FLINT_BITS) { for (k = n - 1; k > 0; k--) { tmp[k] = c; c = _nmod_mul_fullword(c, k, mod); } } else { for (k = n - 1; k > 0; k--) { tmp[k] = c; c = nmod_mul(c, k, mod); } } c = nmod_inv_check(c, mod); success = (c != mod.n); if (success) { tmp[0] = 0; _nmod_vec_scalar_mul_nmod(tmp + 1, tmp + 1, n - 1, c, mod); _nmod_poly_exp_series(res, tmp, n, n, mod); /* Multiply by factorials */ c = 1; if (NMOD_BITS(mod) == FLINT_BITS) { for (k = 1; k < n; k++) { c = _nmod_mul_fullword(c, k, mod); res[k] = _nmod_mul_fullword(res[k], c, mod); } } else { for (k = 1; k < n; k++) { c = nmod_mul(c, k, mod); res[k] = nmod_mul(res[k], c, mod); } } } flint_free(tmp); return success; } flint-3.1.3/src/arith/bell_number_size.c000066400000000000000000000015341461254215100202200ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" double arith_bell_number_size(ulong n) { double l, ll, u; if (n <= 1) return 0; /* Using de Bruijn's asymptotic expansion. Not sure if this is an upper bound for all n, but suffices at least for n < 2^64. */ l = log((double) n); ll = log(l); u = 1.0 / l; return 1.4426950408889634074 * n * (l - ll - 1.0 + ll * u + 1.0 * u + 0.5 * (ll * u) * (ll * u) + 0.25 * ll * u * u) + 2; } flint-3.1.3/src/arith/bell_number_vec.c000066400000000000000000000011041461254215100200140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arith.h" void arith_bell_number_vec(fmpz * res, slong n) { if (n < 5000) arith_bell_number_vec_recursive(res, n); else arith_bell_number_vec_multi_mod(res, n); } flint-3.1.3/src/arith/bell_number_vec_multi_mod.c000066400000000000000000000052011461254215100220670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "arith.h" #define CRT_MAX_RESOLUTION 16 void arith_bell_number_vec_multi_mod(fmpz * res, slong n) { fmpz_comb_t comb[CRT_MAX_RESOLUTION]; fmpz_comb_temp_t temp[CRT_MAX_RESOLUTION]; mp_ptr primes, residues; mp_ptr * polys; nmod_t mod; slong i, j, k, num_primes, num_primes_k, resolution; flint_bitcnt_t size, prime_bits; if (n < 1) return; resolution = FLINT_MAX(1, FLINT_MIN(CRT_MAX_RESOLUTION, n / 16)); size = arith_bell_number_size(n) + 1; prime_bits = FLINT_BITS - 1; num_primes = (size + prime_bits - 1) / prime_bits; primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); polys = flint_malloc(num_primes * sizeof(mp_ptr)); /* Compute Bell numbers mod p */ primes[0] = n_nextprime(UWORD(1)<num_primes >= num_primes_k) break; } num_primes_k = comb[i]->num_primes; for (j = 0; j < num_primes_k; j++) residues[j] = polys[j][k]; fmpz_multi_CRT_ui(res + k, residues, comb[i], temp[i], 0); } /* Cleanup */ for (k = 0; k < num_primes; k++) _nmod_vec_clear(polys[k]); for (i = 0; i < resolution; i++) { fmpz_comb_temp_clear(temp[i]); fmpz_comb_clear(comb[i]); } flint_free(primes); flint_free(residues); flint_free(polys); } flint-3.1.3/src/arith/bell_number_vec_recursive.c000066400000000000000000000017341461254215100221140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" void arith_bell_number_vec_recursive(fmpz * b, slong n) { slong i, k; fmpz * t; if (n < BELL_NUMBER_TAB_SIZE) { for (i = 0; i < n; i++) fmpz_set_ui(b + i, bell_number_tab[i]); return; } n -= 1; t = _fmpz_vec_init(n); fmpz_one(t); fmpz_one(b); fmpz_one(b + 1); for (i = 1; i < n; i++) { fmpz_set(t + i, t); for (k = i; k > 0; k--) fmpz_add(t + k - 1, t + k - 1, t + k); fmpz_set(b + i + 1, t); } _fmpz_vec_clear(t, n); } flint-3.1.3/src/arith/bernoulli_number.c000066400000000000000000000012271461254215100202420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arith.h" #include "bernoulli.h" void _arith_bernoulli_number(fmpz_t num, fmpz_t den, ulong n) { _bernoulli_fmpq_ui(num, den, n); } void arith_bernoulli_number(fmpq_t x, ulong n) { _arith_bernoulli_number(fmpq_numref(x), fmpq_denref(x), n); } flint-3.1.3/src/arith/bernoulli_number_denom.c000066400000000000000000000046511461254215100214300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "arith.h" #define BERNOULLI_DENOM_MAX_SMALL 178 #if FLINT64 #define __u32 unsigned int #else #define __u32 mp_limb_t #endif static const __u32 __bernoulli_denom_small[] = { UWORD(1), UWORD(6), UWORD(30), UWORD(42), UWORD(30), UWORD(66), UWORD(2730), UWORD(6), UWORD(510), UWORD(798), UWORD(330), UWORD(138), UWORD(2730), UWORD(6), UWORD(870), UWORD(14322), UWORD(510), UWORD(6), UWORD(1919190), UWORD(6), UWORD(13530), UWORD(1806), UWORD(690), UWORD(282), UWORD(46410), UWORD(66), UWORD(1590), UWORD(798), UWORD(870), UWORD(354), UWORD(56786730), UWORD(6), UWORD(510), UWORD(64722), UWORD(30), UWORD(4686), UWORD(140100870), UWORD(6), UWORD(30), UWORD(3318), UWORD(230010), UWORD(498), UWORD(3404310), UWORD(6), UWORD(61410), UWORD(272118), UWORD(1410), UWORD(6), UWORD(4501770), UWORD(6), UWORD(33330), UWORD(4326), UWORD(1590), UWORD(642), UWORD(209191710), UWORD(1518), UWORD(1671270), UWORD(42), UWORD(1770), UWORD(6), UWORD(2328255930), UWORD(6), UWORD(30), UWORD(4357878), UWORD(510), UWORD(8646), UWORD(4206930), UWORD(6), UWORD(4110), UWORD(274386), UWORD(679470), UWORD(6), UWORD(2381714790), UWORD(6), UWORD(4470), UWORD(2162622), UWORD(30), UWORD(138), UWORD(1794590070), UWORD(6), UWORD(230010), UWORD(130074), UWORD(2490), UWORD(1002), UWORD(3404310), UWORD(66), UWORD(5190), UWORD(2478), UWORD(1043970), UWORD(1074), }; void arith_bernoulli_number_denom(fmpz_t den, ulong n) { slong i; mp_limb_t p; const mp_limb_t * primes; if (n % 2 == 1) { fmpz_set_ui(den, 1 + (n == 1)); } else if (n <= BERNOULLI_DENOM_MAX_SMALL) { fmpz_set_ui(den, __bernoulli_denom_small[n / 2]); } else { n_prime_pi_bounds(&p, &p, n); primes = n_primes_arr_readonly(p + 2); fmpz_set_ui(den, UWORD(6)); for (i = 2; i < n; i++) { p = primes[i]; if (p - 1 > n) break; if (n % (p - 1) == 0) fmpz_mul_ui(den, den, p); } } } flint-3.1.3/src/arith/bernoulli_number_size.c000066400000000000000000000012521461254215100212720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arith.h" double arith_bernoulli_number_size(ulong n) { double x; /* |B_n| < 2 */ if (n <= 14) return 1.0; x = 2 + (n + 1) * log(n + 1) * 1.44269504088897; /* 1/log(2) */ x -= n * 4.0941911703612822; /* log2(2*pi*e) */ return x + 2; } flint-3.1.3/src/arith/bernoulli_number_vec.c000066400000000000000000000020611461254215100210740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq.h" #include "arith.h" void _arith_bernoulli_number_vec(fmpz * num, fmpz * den, slong n) { if (n < 700) _arith_bernoulli_number_vec_recursive(num, den, n); else _arith_bernoulli_number_vec_multi_mod(num, den, n); } void arith_bernoulli_number_vec(fmpq * x, slong n) { fmpz * num, * den; slong i; if (n <= 0) return; num = _fmpz_vec_init(n * 2); den = num + n; _arith_bernoulli_number_vec(num, den, n); for (i = 0; i < n; i++) { fmpz_swap(num + i, fmpq_numref(x + i)); fmpz_swap(den + i, fmpq_denref(x + i)); } _fmpz_vec_clear(num, n * 2); } flint-3.1.3/src/arith/bernoulli_number_vec_multi_mod.c000066400000000000000000000100261461254215100231450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" static void __bernoulli_number_vec_mod_p(mp_ptr res, mp_ptr tmp, const fmpz * den, slong m, nmod_t mod) { mp_limb_t fac, c, t; slong k; /* x^2/(cosh(x)-1) = \sum_{k=0}^{\infty} 2(1-2k)/(2k)! B_2k x^(2k) */ /* Divide by factorials */ fac = n_factorial_mod2_preinv(2*m, mod.n, mod.ninv); c = n_invmod(fac, mod.n); for (k = m - 1; k >= 0; k--) { tmp[k] = c; c = n_mulmod2_preinv(c, (2*k+1)*(2*k+2), mod.n, mod.ninv); } _nmod_poly_inv_series(res, tmp, m, m, mod); res[0] = UWORD(1); /* N_(2k) = -1 * D_(2k) * (2k)! / (2k-1) */ c = n_negmod(UWORD(1), mod.n); for (k = 1; k < m; k++) { t = fmpz_get_nmod(den + 2*k, mod); t = n_mulmod2_preinv(c, t, mod.n, mod.ninv); res[k] = n_mulmod2_preinv(res[k], t, mod.n, mod.ninv); c = n_mulmod2_preinv(c, 2*(k+1)*(2*k-1), mod.n, mod.ninv); } } #define CRT_MAX_RESOLUTION 16 void _arith_bernoulli_number_vec_multi_mod(fmpz * num, fmpz * den, slong n) { fmpz_comb_t comb[CRT_MAX_RESOLUTION]; fmpz_comb_temp_t temp[CRT_MAX_RESOLUTION]; mp_limb_t * primes; mp_limb_t * residues; mp_ptr * polys; mp_ptr temppoly; nmod_t mod; slong i, j, k, m, num_primes, num_primes_k, resolution; flint_bitcnt_t size, prime_bits; if (n < 1) return; for (i = 0; i < n; i++) arith_bernoulli_number_denom(den + i, i); /* Number of nonzero entries (apart from B_1) */ m = (n + 1) / 2; resolution = FLINT_MAX(1, FLINT_MIN(CRT_MAX_RESOLUTION, m / 16)); /* Note that the denominators must be accounted for */ size = arith_bernoulli_number_size(n) + _fmpz_vec_max_bits(den, n) + 2; prime_bits = FLINT_BITS - 1; num_primes = (size + prime_bits - 1) / prime_bits; primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); polys = flint_malloc(num_primes * sizeof(mp_ptr)); /* Compute Bernoulli numbers mod p */ primes[0] = n_nextprime(UWORD(1)< 1) fmpz_set_si(num + 1, WORD(-1)); for (k = 3; k < n; k += 2) fmpz_zero(num + k); /* Reconstruction */ for (k = 0; k < n; k += 2) { size = arith_bernoulli_number_size(k) + fmpz_bits(den + k) + 2; /* Use only as large a comb as needed */ num_primes_k = (size + prime_bits - 1) / prime_bits; for (i = 0; i < resolution; i++) { if (comb[i]->num_primes >= num_primes_k) break; } num_primes_k = comb[i]->num_primes; for (j = 0; j < num_primes_k; j++) residues[j] = polys[j][k / 2]; fmpz_multi_CRT_ui(num + k, residues, comb[i], temp[i], 1); } /* Cleanup */ for (k = 0; k < num_primes; k++) _nmod_vec_clear(polys[k]); _nmod_vec_clear(temppoly); for (i = 0; i < resolution; i++) { fmpz_comb_temp_clear(temp[i]); fmpz_comb_clear(comb[i]); } flint_free(primes); flint_free(residues); flint_free(polys); } flint-3.1.3/src/arith/bernoulli_number_vec_recursive.c000066400000000000000000000101671461254215100231710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "arith.h" static void __ramanujan_even_common_denom(fmpz * num, fmpz * den, slong start, slong n) { fmpz_t t, c, d, cden; slong j, k, m, mcase; int prodsize = 0; if (start >= n) return; fmpz_init(t); fmpz_init(c); fmpz_init(d); fmpz_init(cden); /* Common denominator */ arith_primorial(cden, n + 1); start += start % 2; /* Convert initial values to common denominator */ for (k = 0; k < start; k += 2) { fmpz_divexact(t, cden, den + k); fmpz_mul(num + k, num + k, t); } /* Ramanujan's recursive formula */ for (m = start; m < n; m += 2) { mcase = m % 6; fmpz_mul_ui(num + m, cden, m + UWORD(3)); fmpz_divexact_ui(num + m, num + m, UWORD(3)); if (mcase == 4) { fmpz_neg(num + m, num + m); fmpz_divexact_ui(num + m, num + m, UWORD(2)); } /* All factors are strictly smaller than m + 4; choose prodsize such that (m + 4)^prodsize fits in an slong. */ { #if FLINT64 if (m < WORD(1444)) prodsize = 6; else if (m < WORD(2097148)) prodsize = 3; else if (m < WORD(3037000495)) prodsize = 2; /* not very likely... */ else flint_throw(FLINT_ERROR, "(%s)", __func__); #else if (m < WORD(32)) prodsize = 6; else if (m < WORD(1286)) prodsize = 3; else if (m < WORD(46336)) prodsize = 2; else flint_throw(FLINT_ERROR, "(%s)", __func__); #endif } /* c = t = binomial(m+3, m) */ fmpz_set_ui(t, m + UWORD(1)); fmpz_mul_ui(t, t, m + UWORD(2)); fmpz_mul_ui(t, t, m + UWORD(3)); fmpz_divexact_ui(t, t, UWORD(6)); fmpz_set(c, t); for (j = 6; j <= m; j += 6) { slong r = m - j; /* c = binomial(m+3, m-j); */ switch (prodsize) { case 2: fmpz_mul_ui(c, c, (r+6)*(r+5)); fmpz_mul_ui(c, c, (r+4)*(r+3)); fmpz_mul_ui(c, c, (r+2)*(r+1)); fmpz_set_ui(d, (j+0)*(j+3)); fmpz_mul_ui(d, d, (j-2)*(j+2)); fmpz_mul_ui(d, d, (j-1)*(j+1)); fmpz_divexact(c, c, d); break; case 3: fmpz_mul_ui(c, c, (r+6)*(r+5)*(r+4)); fmpz_mul_ui(c, c, (r+3)*(r+2)*(r+1)); fmpz_set_ui(d, (j+0)*(j+3)*(j-2)); fmpz_mul_ui(d, d, (j+2)*(j-1)*(j+1)); fmpz_divexact(c, c, d); break; case 6: fmpz_mul_ui(c, c, (r+6)*(r+5)*(r+4)*(r+3)*(r+2)*(r+1)); fmpz_divexact_ui(c, c, (j+0)*(j+3)*(j-2)*(j+2)*(j-1)*(j+1)); break; } fmpz_submul(num + m, c, num + (m - j)); } fmpz_divexact(num + m, num + m, t); } /* Convert to separate denominators */ for (k = 0; k < n; k += 2) { arith_bernoulli_number_denom(den + k, k); fmpz_divexact(t, cden, den + k); fmpz_divexact(num + k, num + k, t); } fmpz_clear(t); fmpz_clear(c); fmpz_clear(d); fmpz_clear(cden); } void _arith_bernoulli_number_vec_recursive(fmpz * num, fmpz * den, slong n) { slong i, start; fmpz_t t; fmpz_t d; fmpz_init(t); fmpz_init(d); start = FLINT_MIN(BERNOULLI_SMALL_NUMER_LIMIT, n); /* Initial values */ for (i = 0; i < start; i += 2) _arith_bernoulli_number(num + i, den + i, i); __ramanujan_even_common_denom(num, den, start, n); /* Odd values */ for (i = 1; i < n; i += 2) _arith_bernoulli_number(num + i, den + i, i); fmpz_clear(d); fmpz_clear(t); } flint-3.1.3/src/arith/bernoulli_polynomial.c000066400000000000000000000031631461254215100211360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "arith.h" void arith_bernoulli_polynomial(fmpq_poly_t poly, ulong n) { fmpz_t t; fmpz * den; slong k; if (n == 0) { fmpq_poly_set_ui(poly, UWORD(1)); return; } fmpq_poly_fit_length(poly, n + 1); fmpz_init(t); den = _fmpz_vec_init(n + 1); _arith_bernoulli_number_vec(poly->coeffs, den, n + 1); /* Multiply the odd term by binomial(n,1) = n */ fmpz_mul_ui(poly->coeffs + 1, poly->coeffs + 1, n); /* Multiply even terms by binomial coefficients */ fmpz_one(t); for (k = 2; k <= n; k += 2) { fmpz_mul2_uiui(t, t, n-k+1, n-k+2); fmpz_divexact2_uiui(t, t, k, k-1); fmpz_mul(poly->coeffs + k, poly->coeffs + k, t); } /* Convert to common denominator */ arith_primorial(poly->den, n + 2); for (k = 0; k <= n; k++) { fmpz_mul(poly->coeffs + k, poly->coeffs+k, poly->den); fmpz_divexact(poly->coeffs + k, poly->coeffs + k, den + k); } _fmpz_poly_reverse(poly->coeffs, poly->coeffs, n + 1, n + 1); _fmpq_poly_set_length(poly, n + 1); fmpq_poly_canonicalise(poly); _fmpz_vec_clear(den, n + 1); fmpz_clear(t); } flint-3.1.3/src/arith/dedekind_cosine_sum_factored.c000066400000000000000000000161321461254215100225420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "arith.h" static const int mod4_tab[8] = { 2, 1, 3, 0, 0, 3, 1, 2 }; static const int gcd24_tab[24] = { 24, 1, 2, 3, 4, 1, 6, 1, 8, 3, 2, 1, 12, 1, 2, 3, 8, 1, 6, 1, 4, 3, 2, 1 }; static mp_limb_t n_sqrtmod_2exp(mp_limb_t a, int k) { mp_limb_t x; int i; if (a == 0 || k == 0) return 0; if (k == 1) return 1; if (k == 2) { if (a == 1) return 1; return 0; } x = 1; for (i = 3; i < k; i++) x += (a - x * x) / 2; if (k < FLINT_BITS) x &= ((UWORD(1) << k) - 1); return x; } static mp_limb_t n_sqrtmod_ppow(mp_limb_t a, mp_limb_t p, int k, mp_limb_t pk, mp_limb_t pkinv) { mp_limb_t r, t; int i; /* n_sqrtmod assumes that a is reduced */ r = n_sqrtmod(a % p, p); if (r == 0) return r; i = 1; while (i < k) { t = n_mulmod2_preinv(r, r, pk, pkinv); t = n_submod(t, a, pk); t = n_mulmod2_preinv(t, n_invmod(n_addmod(r, r, pk), pk), pk, pkinv); r = n_submod(r, t, pk); i *= 2; } return r; } void trigprod_mul_prime_power(trig_prod_t prod, mp_limb_t k, mp_limb_t n, mp_limb_t p, int exp) { mp_limb_t m, mod, inv; if (k <= 3) { if (k == 0) { prod->prefactor = 0; } else if (k == 2 && (n % 2 == 1)) { prod->prefactor *= -1; } else if (k == 3) { switch (n % 3) { case 0: prod->prefactor *= 2; prod->cos_p[prod->n] = 1; prod->cos_q[prod->n] = 18; break; case 1: prod->prefactor *= -2; prod->cos_p[prod->n] = 7; prod->cos_q[prod->n] = 18; break; case 2: prod->prefactor *= -2; prod->cos_p[prod->n] = 5; prod->cos_q[prod->n] = 18; break; } prod->n++; } return; } /* Power of 2 */ if (p == 2) { mod = 8 * k; inv = n_preinvert_limb(mod); m = n_submod(1, n_mod2_preinv(24 * n, mod, inv), mod); m = n_sqrtmod_2exp(m, exp + 3); m = n_mulmod2_preinv(m, n_invmod(3, mod), mod, inv); prod->prefactor *= n_jacobi(-1, m); if (exp % 2 == 1) prod->prefactor *= -1; prod->sqrt_p *= k; prod->cos_p[prod->n] = (mp_limb_signed_t)(k - m); prod->cos_q[prod->n] = 2 * k; prod->n++; return; } /* Power of 3 */ if (p == 3) { mod = 3 * k; inv = n_preinvert_limb(mod); m = n_submod(1, n_mod2_preinv(24 * n, mod, inv), mod); m = n_sqrtmod_ppow(m, p, exp + 1, mod, inv); m = n_mulmod2_preinv(m, n_invmod(8, mod), mod, inv); prod->prefactor *= (2 * n_jacobi_unsigned(m, 3)); if (exp % 2 == 0) prod->prefactor *= -1; prod->sqrt_p *= k; prod->sqrt_q *= 3; prod->cos_p[prod->n] = (mp_limb_signed_t)(3 * k - 8 * m); prod->cos_q[prod->n] = 6 * k; prod->n++; return; } /* Power of prime greater than 3 */ inv = n_preinvert_limb(k); m = n_submod(1, n_mod2_preinv(24 * n, k, inv), k); if (m % p == 0) { if (exp == 1) { prod->prefactor *= n_jacobi(3, k); prod->sqrt_p *= k; } else prod->prefactor = 0; return; } m = n_sqrtmod_ppow(m, p, exp, k, inv); if (m == 0) { prod->prefactor = 0; return; } prod->prefactor *= 2; prod->prefactor *= n_jacobi(3, k); prod->sqrt_p *= k; prod->cos_p[prod->n] = 4 * n_mulmod2_preinv(m, n_invmod(24 >= k ? n_mod2_preinv(24, k, inv) : 24, k), k, inv); prod->cos_q[prod->n] = k; prod->n++; } /* Solve (k2^2 * d2 * e) * n1 = (d2 * e * n + (k2^2 - 1) / d1) mod k2 TODO: test this on 32 bit */ static mp_limb_t solve_n1(mp_limb_t n, mp_limb_t k1, mp_limb_t k2, mp_limb_t d1, mp_limb_t d2, mp_limb_t e) { mp_limb_t inv, n1, u, t[2]; inv = n_preinvert_limb(k1); umul_ppmm(t[1], t[0], k2, k2); sub_ddmmss(t[1], t[0], t[1], t[0], UWORD(0), UWORD(1)); mpn_divrem_1(t, 0, t, 2, d1); n1 = n_ll_mod_preinv(t[1], t[0], k1, inv); n1 = n_mod2_preinv(n1 + d2*e*n, k1, inv); u = n_mulmod2_preinv(k2, k2, k1, inv); u = n_invmod(n_mod2_preinv(u * d2 * e, k1, inv), k1); n1 = n_mulmod2_preinv(n1, u, k1, inv); return n1; } void arith_hrr_expsum_factored(trig_prod_t prod, mp_limb_t k, mp_limb_t n) { n_factor_t fac; int i; if (k <= 1) { prod->prefactor = k; return; } n_factor_init(&fac); n_factor(&fac, k, 0); /* Repeatedly factor A_k(n) into A_k1(n1)*A_k2(n2) with k1, k2 coprime */ for (i = 0; i + 1 < fac.num && prod->prefactor != 0; i++) { mp_limb_t p, k1, k2, inv, n1, n2; p = fac.p[i]; /* k = 2 * k1 with k1 odd */ if (p == UWORD(2) && fac.exp[i] == 1) { k2 = k / 2; inv = n_preinvert_limb(k2); n2 = n_invmod(32 >= k2 ? n_mod2_preinv(32, k2, inv) : 32, k2); n2 = n_mulmod2_preinv(n2, n_mod2_preinv(8*n + 1, k2, inv), k2, inv); n1 = ((k2 % 8 == 3) || (k2 % 8 == 5)) ^ (n & 1); trigprod_mul_prime_power(prod, 2, n1, 2, 1); k = k2; n = n2; } /* k = 4 * k1 with k1 odd */ else if (p == UWORD(2) && fac.exp[i] == 2) { k2 = k / 4; inv = n_preinvert_limb(k2); n2 = n_invmod(128 >= k2 ? n_mod2_preinv(128, k2, inv) : 128, k2); n2 = n_mulmod2_preinv(n2, n_mod2_preinv(8*n + 5, k2, inv), k2, inv); n1 = (n + mod4_tab[(k2 / 2) % 8]) % 4; trigprod_mul_prime_power(prod, 4, n1, 2, 2); prod->prefactor *= -1; k = k2; n = n2; } /* k = k1 * k2 with k1 odd or divisible by 8 */ else { mp_limb_t d1, d2, e; k1 = n_pow(fac.p[i], fac.exp[i]); k2 = k / k1; d1 = gcd24_tab[k1 % 24]; d2 = gcd24_tab[k2 % 24]; e = 24 / (d1 * d2); n1 = solve_n1(n, k1, k2, d1, d2, e); n2 = solve_n1(n, k2, k1, d2, d1, e); trigprod_mul_prime_power(prod, k1, n1, fac.p[i], fac.exp[i]); k = k2; n = n2; } } if (fac.num != 0 && prod->prefactor != 0) trigprod_mul_prime_power(prod, k, n, fac.p[fac.num - 1], fac.exp[fac.num - 1]); } flint-3.1.3/src/arith/divisors.c000066400000000000000000000103641461254215100165430ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "arith.h" #define FLINT_NUM_TINY_DIVISORS FLINT_BITS const int FLINT_TINY_DIVISORS_SIZE[FLINT_NUM_TINY_DIVISORS] = { 0,1,2,2,3,2,4,2,4,3,4,2,6,2,4,4,5,2,6,2,6,4,4,2,8,3,4,4,6,2,8,2, #if FLINT64 6,4,4,4,9,2,4,4,8,2,8,2,6,6,4,2,10,3,6,4,6,2,8,4,8,4,4,2,12,2,4,6 #endif }; const ulong FLINT_TINY_DIVISORS_LOOKUP[FLINT_NUM_TINY_DIVISORS] = { UWORD(0x0),UWORD(0x2),UWORD(0x6),0xaUL,UWORD(0x16),UWORD(0x22),0x4eUL,UWORD(0x82),UWORD(0x116),0x20aUL, UWORD(0x426),UWORD(0x802),0x105eUL,UWORD(0x2002),UWORD(0x4086),0x802aUL,UWORD(0x10116),UWORD(0x20002), 0x4024eUL,UWORD(0x80002),UWORD(0x100436),0x20008aUL,UWORD(0x400806),UWORD(0x800002), 0x100115eUL,UWORD(0x2000022),UWORD(0x4002006),0x800020aUL,UWORD(0x10004096),UWORD(0x20000002), 0x4000846eUL,UWORD(0x80000002), #if FLINT64 UWORD(0x100010116),0x20000080aUL,UWORD(0x400020006),UWORD(0x8000000a2),0x100004125eUL, UWORD(0x2000000002),UWORD(0x4000080006),0x800000200aUL,UWORD(0x10000100536), UWORD(0x20000000002),0x400002040ceUL,UWORD(0x80000000002),UWORD(0x100000400816), 0x20000000822aUL,UWORD(0x400000800006),UWORD(0x800000000002),0x100000101115eUL, UWORD(0x2000000000082),UWORD(0x4000002000426),0x800000002000aUL,UWORD(0x10000004002016), UWORD(0x20000000000002),0x4000000804024eUL,UWORD(0x80000000000822), UWORD(0x100000010004196),0x20000000008000aUL,UWORD(0x400000020000006), UWORD(0x800000000000002),0x100000004010947eUL,UWORD(0x2000000000000002), UWORD(0x4000000080000006),0x800000000020028aUL #endif }; void _arith_divisors(fmpz *res, slong size, fmpz_factor_t factors) { slong i; slong *exp = flint_malloc(sizeof(slong) * factors->num); slong *exp_max = flint_malloc(sizeof(slong) * factors->num); fmpz *powers = _fmpz_vec_init(factors->num); fmpz_t d; for (i = 0; i < factors->num; i++) { exp[i] = 0; fmpz_set(powers + i, factors->p + i); exp_max[i] = factors->exp[i]; fmpz_pow_ui(powers + i, powers + i, exp_max[i]); } fmpz_init(d); fmpz_one(res); fmpz_one(d); res++; i = 0; while (1) { while (1) { if (i == factors->num) goto all_done; if (exp[i] < exp_max[i]) { exp[i]++; fmpz_mul(d, d, factors->p + i); i = 0; break; } else { exp[i] = 0; fmpz_divexact(d, d, powers+i); i += 1; } } fmpz_set(res, d); res++; } all_done: fmpz_clear(d); flint_free(exp); flint_free(exp_max); _fmpz_vec_clear(powers, factors->num); } void _arith_divisors_tiny(fmpz_poly_t res, slong n) { slong size; slong i, k; size = FLINT_TINY_DIVISORS_SIZE[n]; fmpz_poly_fit_length(res, size); i = 0; for (k = 1; k <= n; k++) { if (FLINT_TINY_DIVISORS_LOOKUP[n] & (UWORD(1) << k)) { fmpz_poly_set_coeff_si(res, i, k); i++; } } _fmpz_poly_set_length(res, size); return; } void arith_divisors(fmpz_poly_t res, const fmpz_t n) { slong i, size, m; fmpz_factor_t factors; if (!COEFF_IS_MPZ(*n)) { m = fmpz_get_si(n); if (-FLINT_NUM_TINY_DIVISORS < m && m < FLINT_NUM_TINY_DIVISORS) { _arith_divisors_tiny(res, FLINT_ABS(m)); return; } } fmpz_factor_init(factors); fmpz_factor(factors, n); /* TODO: check for overflow for huge n */ size = 1; for (i = 0; i < factors->num; i++) size *= factors->exp[i] + 1; fmpz_poly_fit_length(res, size); _arith_divisors(res->coeffs, size, factors); _fmpz_poly_set_length(res, size); _fmpz_vec_sort(res->coeffs, size); fmpz_factor_clear(factors); } flint-3.1.3/src/arith/euler_number.c000066400000000000000000000007731461254215100173700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arith.h" #include "arb.h" void arith_euler_number(fmpz_t res, ulong n) { arb_fmpz_euler_number_ui(res, n); } flint-3.1.3/src/arith/euler_number_size.c000066400000000000000000000011721461254215100204140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "arith.h" double arith_euler_number_size(ulong n) { double x; x = n + 2; x += ((n + 1) * log(n + 1) - n) * 1.44269504088897; /* 1/log(2) */ x -= 1.6514961294723*(n+1); /* log2(pi) */ return x + 2; } flint-3.1.3/src/arith/euler_number_vec.c000066400000000000000000000072731461254215100202270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "arith.h" /* Computes length-m vector containing |E_{2k}| */ static void __euler_number_vec_mod_p(mp_ptr res, mp_ptr tmp, slong m, nmod_t mod) { mp_limb_t fac, c; slong k; /* Divide by factorials */ fac = n_factorial_mod2_preinv(2*(m-1), mod.n, mod.ninv); c = n_invmod(fac, mod.n); for (k = m - 1; k >= 0; k--) { tmp[k] = c; c = n_mulmod2_preinv(c, (2*k)*(2*k-1), mod.n, mod.ninv); } _nmod_poly_inv_series(res, tmp, m, m, mod); /* Multiply by factorials */ c = UWORD(1); for (k = 0; k < m; k++) { res[k] = n_mulmod2_preinv(res[k], c, mod.n, mod.ninv); c = n_mulmod2_preinv(c, (2*k+1)*(2*k+2), mod.n, mod.ninv); c = n_negmod(c, mod.n); } } #define CRT_MAX_RESOLUTION 16 void __euler_number_vec_multi_mod(fmpz * res, slong n) { fmpz_comb_t comb[CRT_MAX_RESOLUTION]; fmpz_comb_temp_t temp[CRT_MAX_RESOLUTION]; mp_limb_t * primes; mp_limb_t * residues; mp_ptr * polys; mp_ptr temppoly; nmod_t mod; slong i, j, k, m, num_primes, num_primes_k, resolution; flint_bitcnt_t size, prime_bits; if (n < 1) return; /* Number of nonzero entries */ m = (n + 1) / 2; resolution = FLINT_MAX(1, FLINT_MIN(CRT_MAX_RESOLUTION, m / 16)); size = arith_euler_number_size(n); prime_bits = FLINT_BITS - 1; num_primes = (size + prime_bits - 1) / prime_bits; primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); polys = flint_malloc(num_primes * sizeof(mp_ptr)); /* Compute Euler numbers mod p */ primes[0] = n_nextprime(UWORD(1)<num_primes >= num_primes_k) break; } num_primes_k = comb[i]->num_primes; for (j = 0; j < num_primes_k; j++) residues[j] = polys[j][k / 2]; fmpz_multi_CRT_ui(res + k, residues, comb[i], temp[i], 0); if (k % 4) fmpz_neg(res + k, res + k); } /* Cleanup */ for (k = 0; k < num_primes; k++) _nmod_vec_clear(polys[k]); _nmod_vec_clear(temppoly); for (i = 0; i < resolution; i++) { fmpz_comb_temp_clear(temp[i]); fmpz_comb_clear(comb[i]); } flint_free(primes); flint_free(residues); flint_free(polys); } void arith_euler_number_vec(fmpz * res, slong n) { __euler_number_vec_multi_mod(res, n); } flint-3.1.3/src/arith/euler_polynomial.c000066400000000000000000000017741461254215100202650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" #include "arith.h" void arith_euler_polynomial(fmpq_poly_t poly, ulong n) { fmpz_t t; slong k; if (n == 0) { fmpq_poly_set_ui(poly, UWORD(1)); return; } arith_bernoulli_polynomial(poly, n + 1); fmpz_init(t); fmpz_set_si(t, WORD(-2)); for (k = n; k >= 0; k--) { fmpz_mul(poly->coeffs + k, poly->coeffs + k, t); fmpz_mul_ui(t, t, UWORD(2)); fmpz_sub_ui(t, t, UWORD(2)); } fmpz_zero(poly->coeffs + n + 1); fmpz_mul_ui(poly->den, poly->den, n + 1); fmpq_poly_canonicalise(poly); fmpz_clear(t); } flint-3.1.3/src/arith/harmonic_number.c000066400000000000000000000013401461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arith.h" #include "fmpq.h" void _arith_harmonic_number(fmpz_t num, fmpz_t den, slong n) { if (n <= 0) { fmpz_zero(num); fmpz_one(den); } else { _fmpq_harmonic_ui(num, den, n); } } void arith_harmonic_number(fmpq_t x, slong n) { _arith_harmonic_number(fmpq_numref(x), fmpq_denref(x), n); } flint-3.1.3/src/arith/landau_function_vec.c000066400000000000000000000025131461254215100207040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "arith.h" #ifdef __GNUC__ # define log __builtin_log # define sqrt __builtin_sqrt #else # include #endif void arith_landau_function_vec(fmpz * res, slong len) { mp_limb_t p, pmax; mp_limb_t pk, pkhi; fmpz_t a; ulong k, n; if (len < 1) return; for (k = 0; k < len; k++) fmpz_one(res + k); pmax = 1.328 * sqrt(len*log(len) + 1); fmpz_init(a); for (p = UWORD(2); p <= pmax; p = n_nextprime(p, 0)) { for (n = len - 1; n >= p; n--) { pk = p; pkhi = UWORD(0); for (k = 1; k <= len; k++) { if (pk > n || pkhi) break; fmpz_mul_ui(a, res + n - pk, pk); if (fmpz_cmp(res + n, a) < 0) fmpz_set(res + n, a); umul_ppmm(pkhi, pk, pk, p); } } } fmpz_clear(a); } flint-3.1.3/src/arith/number_of_partitions.c000066400000000000000000000010111461254215100211160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "partitions.h" /* compatibility wrapper */ void arith_number_of_partitions(fmpz_t x, ulong n) { partitions_fmpz_ui(x, n); } flint-3.1.3/src/arith/number_of_partitions_nmod_vec.c000066400000000000000000000021461461254215100230020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "arith.h" void arith_number_of_partitions_nmod_vec(mp_ptr res, slong len, nmod_t mod) { mp_ptr tmp; mp_limb_t r; slong k, n; r = mod.n - UWORD(1); if (len < 1) return; tmp = _nmod_vec_init(len); _nmod_vec_zero(tmp, len); tmp[0] = UWORD(1); for (n = k = 1; n + 4*k + 2 < len; k += 2) { tmp[n] = r; tmp[n + k] = r; tmp[n + 3*k + 1] = UWORD(1); tmp[n + 4*k + 2] = UWORD(1); n += 6*k + 5; } if (n < len) tmp[n] = r; if (n + k < len) tmp[n + k] = r; if (n + 3*k + 1 < len) tmp[n + 3*k + 1] = WORD(1); _nmod_poly_inv_series(res, tmp, len, len, mod); _nmod_vec_clear(tmp); } flint-3.1.3/src/arith/number_of_partitions_vec.c000066400000000000000000000020441461254215100217620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "arith.h" void arith_number_of_partitions_vec(fmpz * res, slong len) { fmpz * tmp; slong k, n; if (len < 1) return; tmp = _fmpz_vec_init(len); tmp[0] = WORD(1); for (n = k = 1; n + 4*k + 2 < len; k += 2) { tmp[n] = WORD(-1); tmp[n + k] = WORD(-1); tmp[n + 3*k + 1] = WORD(1); tmp[n + 4*k + 2] = WORD(1); n += 6*k + 5; } if (n < len) tmp[n] = WORD(-1); if (n + k < len) tmp[n + k] = WORD(-1); if (n + 3*k + 1 < len) tmp[n + 3*k + 1] = WORD(1); _fmpz_poly_inv_series(res, tmp, len, len); _fmpz_vec_clear(tmp, len); } flint-3.1.3/src/arith/ramanujan_tau.c000066400000000000000000000052151461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "arith.h" void arith_ramanujan_tau_series(fmpz_poly_t res, slong n) { slong j, k, jv, kv; fmpz_t tmp; fmpz_poly_fit_length(res, n); _fmpz_vec_zero(res->coeffs, n); _fmpz_poly_set_length(res, n); fmpz_init(tmp); for (j = jv = 0; jv < n; jv += ++j) { fmpz_set_ui(tmp, 2*j+1); for (k = kv = 0; jv + kv < n; kv += ++k) { if ((j+k) & 1) fmpz_submul_ui(res->coeffs + jv+kv, tmp, 2*k+1); else fmpz_addmul_ui(res->coeffs + jv+kv, tmp, 2*k+1); } } fmpz_poly_sqrlow(res, res, n-1); fmpz_poly_sqrlow(res, res, n-1); fmpz_poly_shift_left(res, res, 1); fmpz_clear(tmp); } void _arith_ramanujan_tau(fmpz_t res, fmpz_factor_t factors) { fmpz_poly_t poly; fmpz_t tau_p, p_11, next, this, prev; slong k, r; ulong max_prime; max_prime = UWORD(1); for (k = 0; k < factors->num; k++) { /* TODO: handle overflow properly */ max_prime = FLINT_MAX(max_prime, fmpz_get_ui(factors->p + k)); } fmpz_poly_init(poly); arith_ramanujan_tau_series(poly, max_prime + 1); fmpz_one(res); fmpz_init(tau_p); fmpz_init(p_11); fmpz_init(next); fmpz_init(this); fmpz_init(prev); for (k = 0; k < factors->num; k++) { ulong p = fmpz_get_ui(factors->p + k); fmpz_set(tau_p, poly->coeffs + p); fmpz_set_ui(p_11, p); fmpz_pow_ui(p_11, p_11, 11); fmpz_one(prev); fmpz_set(this, tau_p); for (r = 1; r < factors->exp[k]; r++) { fmpz_mul(next, tau_p, this); fmpz_submul(next, p_11, prev); fmpz_set(prev, this); fmpz_set(this, next); } fmpz_mul(res, res, this); } fmpz_clear(tau_p); fmpz_clear(p_11); fmpz_clear(next); fmpz_clear(this); fmpz_clear(prev); fmpz_poly_clear(poly); } void arith_ramanujan_tau(fmpz_t res, const fmpz_t n) { fmpz_factor_t factors; if (fmpz_sgn(n) <= 0) { fmpz_zero(res); return; } fmpz_factor_init(factors); fmpz_factor(factors, n); _arith_ramanujan_tau(res, factors); fmpz_factor_clear(factors); } flint-3.1.3/src/arith/stirling1.c000066400000000000000000000125021461254215100166110ustar00rootroot00000000000000/* Copyright (C) 2010, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "arith.h" /* compute single coefficient in polynomial product */ FLINT_FORCE_INLINE void _fmpz_poly_mulmid_single(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong i) { slong top1, top2; top1 = FLINT_MIN(len1 - 1, i); top2 = FLINT_MIN(len2 - 1, i); _fmpz_vec_dot_general(res, NULL, 0, poly1 + i - top2, poly2 + i - top1, 1, top1 + top2 - i + 1); } #define MAX_BASECASE 16 /* which == 1: expand (a+x)...((b-1)+x) truncated to length len which == 2: expand (1+ax)...(1+(b-1)x) truncated to length len final: only extract final coefficient */ static void stirling_1u_ogf_bsplit(fmpz * res, ulong a, ulong b, slong len, int which, int final) { ulong c, n, cbc; len = FLINT_MIN(len, b - a + 1); /* (c+x)^n has coefficients bounded by max(c,n)^n */ n = b - a; c = FLINT_MAX(b - 1, n); cbc = FLINT_BIT_COUNT(c); if (n == 1 || (len <= MAX_BASECASE && n * cbc <= FLINT_BITS)) { mp_limb_t v[MAX_BASECASE]; slong i, j; if (which == 1) { v[0] = a; v[1] = 1; /* multiply by ((a+i) + x) */ for (i = 1; i < n; i++) { if (i + 1 < len) v[i + 1] = 1; for (j = FLINT_MIN(i, len - 1); j >= 1; j--) v[j] = (a + i) * v[j] + v[j - 1]; v[0] *= (a + i); } } else { v[0] = 1; v[1] = a; /* multiply by (1 + (a+i) x) */ for (i = 1; i < n; i++) { if (i + 1 < len) v[i + 1] = v[i] * (a + i); for (j = FLINT_MIN(i, len - 1); j >= 1; j--) v[j] = v[j] + (a + i) * v[j - 1]; } } if (final) fmpz_set_ui(res, v[len - 1]); else for (i = 0; i < len; i++) fmpz_set_ui(res + i, v[i]); } else { fmpz *L, *R; slong len1, len2; slong m = a + (b - a) / 2; len1 = FLINT_MIN(m - a + 1, len); len2 = FLINT_MIN(b - m + 1, len); L = _fmpz_vec_init(len1 + len2); R = L + len1; stirling_1u_ogf_bsplit(L, a, m, len, which, 0); /* Remark: R can be computed from L using a Taylor shift. In theory, this improves the complexity from O(M(n) log n) to O(M(n)). In practice, the Taylor shift is rarely much faster than computing R from scratch, and sometimes slower, so we do not bother. */ stirling_1u_ogf_bsplit(R, m, b, len, which, 0); if (final) _fmpz_poly_mulmid_single(res, L, len1, R, len2, len - 1); else _fmpz_poly_mullow(res, R, len2, L, len1, FLINT_MIN(len, len1 + len2 - 1)); _fmpz_vec_clear(L, len1 + len2); } } static void stirling_1u_egf(fmpz_t res, ulong n, ulong k) { fmpz * num; fmpz * rnum; fmpz_t den; fmpz_t rden; slong i, len; if (k >= n || k == 0) { fmpz_set_ui(res, n == k); return; } len = n - k + 1; num = _fmpz_vec_init(len + 1); rnum = _fmpz_vec_init(len); fmpz_init(den); fmpz_init(rden); fmpz_one(den); for (i = 0; i < len; i++) fmpz_one(num + i); _fmpq_poly_integral(num, den, num, den, len + 1); for (i = 0; i < len; i++) fmpz_swap(num + i, num + i + 1); _fmpq_poly_pow_trunc(rnum, rden, num, den, len, k, len); fmpz_set_ui(num, k); fmpz_add_ui(num, num, 1); fmpz_rfac_ui(num, num, n - k); fmpz_mul(num, num, rnum + n - k); fmpz_divexact(res, num, rden); _fmpz_vec_clear(num, len + 1); _fmpz_vec_clear(rnum, len); fmpz_clear(den); fmpz_clear(rden); } void arith_stirling_number_1u(fmpz_t res, ulong n, ulong k) { if (k >= n || k == 0) { fmpz_set_ui(res, n == k); } else if (k == 1) { fmpz_fac_ui(res, n - 1); } else if (n > 140 && k > 0.87 * n) { stirling_1u_egf(res, n, k); } else { if (k < n / 2) stirling_1u_ogf_bsplit(res, 1, n, k, 1, 1); else stirling_1u_ogf_bsplit(res, 1, n, n - k + 1, 2, 1); } } void arith_stirling_number_1u_vec(fmpz * res, ulong n, slong klen) { slong k, len; if (klen <= 0) return; len = FLINT_MIN(klen - 1, n - 1); if (n >= 1 && len >= 1) stirling_1u_ogf_bsplit(res + 1, 1, n, len, 1, 0); fmpz_set_ui(res + 0, n == 0); for (k = n; k < klen; k++) fmpz_set_ui(res + k, n == k); } void arith_stirling_number_1(fmpz_t s, ulong n, ulong k) { arith_stirling_number_1u(s, n, k); if ((n + k) % 2) fmpz_neg(s, s); } void arith_stirling_number_1_vec(fmpz * row, ulong n, slong klen) { slong k; arith_stirling_number_1u_vec(row, n, klen); for (k = (n + 1) % 2; k < klen; k += 2) fmpz_neg(row + k, row + k); } flint-3.1.3/src/arith/stirling2.c000066400000000000000000000422721461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2010, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "arith.h" #ifdef __GNUC__ # define log __builtin_log # define exp __builtin_exp # define frexp __builtin_frexp #else # include #endif /* S(n,k) <= (1/2) binomial(n,k) * k^(n-k) */ static slong stirling_2_bound_2exp(ulong n, ulong k) { double bnk; int exp; slong bnk_exp, j; /* binomial coefficients */ bnk = 1.0; bnk_exp = 0; for (j = 1; j <= k; j++) { bnk = (bnk * (n + 1 - j)) / j; bnk = frexp(bnk, &exp); bnk_exp += exp; } /* (1/2) * binomial(n,k) * k^(n-k) */ /* add instead of subtract 1 to ensure upper bound in fp */ return bnk_exp + (n - k) * log(k) * 1.44269504088896 + 1; } static slong stirling_2_bound_2exp_vec(slong * bound, ulong n, slong len) { double bnk; int exp; slong bnk_exp, k, max, kmax; kmax = len - 1; bound[0] = 0; max = 0; /* binomial coefficients */ bnk = 1.0; bnk_exp = 0; for (k = 1; k <= kmax; k++) { /* binomial recurrence */ bnk = (bnk * (n + 1 - k)) / k; bnk = frexp(bnk, &exp); bnk_exp += exp; /* (1/2) * binomial(n,k) * k^(n-k) */ bound[k] = bnk_exp + (n-k) * log(k) * 1.44269504088896 + 1; max = FLINT_MAX(max, bound[k]); } return max; } #if FLINT_BITS == 32 #define MAX_N_1LIMB 16 #define MAX_N_2LIMB 26 #else #define MAX_N_1LIMB 26 #define MAX_N_2LIMB 43 #endif static void triangular_1(mp_ptr c, slong n, slong klen) { slong m, k; c[0] = 0; c[1] = 1; c[2] = 3; c[3] = 1; for (m = 4; m <= n; m++) { if (m < klen) c[m] = 1; for (k = FLINT_MIN(m, klen) - 1; k >= 2; k--) c[k] = c[k] * k + c[k - 1]; } } static void triangular_2(mp_ptr c, slong n, slong klen) { mp_limb_t hi, lo; slong m, k; triangular_1(c, MAX_N_1LIMB, klen); for (k = FLINT_MIN(MAX_N_1LIMB, klen - 1); k >= 0; k--) { c[2 * k] = c[k]; c[2 * k + 1] = 0; } for (m = MAX_N_1LIMB + 1; m <= n; m++) { if (m < klen) { c[2 * m] = 1; c[2 * m + 1] = 0; } for (k = FLINT_MIN(m, klen) - 1; k >= 2; k--) { umul_ppmm(hi, lo, c[2 * k], k); hi += c[2 * k + 1] * k; add_ssaaaa(c[2 * k + 1], c[2 * k], hi, lo, c[2 * (k - 1) + 1], c[2 * (k - 1)]); } } } void arith_stirling_number_2_vec_triangular(fmpz * row, slong n, slong klen) { mp_limb_t c[2 * MAX_N_2LIMB + 2]; slong m, k; if (klen <= 0) return; if (n >= 1) { if (n <= MAX_N_1LIMB) { triangular_1(c, n, klen); for (k = 0; k <= FLINT_MIN(klen - 1, n); k++) fmpz_set_ui(row + k, c[k]); } else { m = FLINT_MIN(n, MAX_N_2LIMB); triangular_2(c, m, klen); for (k = 0; k <= FLINT_MIN(klen - 1, m); k++) fmpz_set_uiui(row + k, c[2 * k + 1], c[2 * k]); for (m = MAX_N_2LIMB + 1 ; m <= n; m++) { if (m < klen) fmpz_one(row + m); for (k = FLINT_MIN(m, klen) - 1; k >= 2; k--) { fmpz_mul_ui(row + k, row + k, k); fmpz_add(row + k, row + k - 1, row + k); } } } } for (k = n; k < klen; k++) fmpz_set_ui(row + k, k == n); } void arith_stirling_number_2_vec_convolution(fmpz * res, ulong n, slong klen) { slong k, kodd, len; ulong e; fmpz *t, *u, *v; if (klen <= 0) return; len = FLINT_MIN(klen - 1, n - 1); t = _fmpz_vec_init(len + 1); u = _fmpz_vec_init(len); v = _fmpz_vec_init(len); if (n >= 1 && len >= 1) { fmpz_one(t + len); for (k = len - 1; k >= 0; k--) fmpz_mul_ui(t + k, t + k + 1, k + 1); for (kodd = 1; kodd <= len; kodd += 2) { fmpz_set_ui(v, kodd); fmpz_pow_ui(v, v, n); for (k = kodd, e = 0; k <= len; k *= 2, e++) { /* k^n / k! */ fmpz_mul(u + k - 1, v, t + k); fmpz_mul_2exp(u + k - 1, u + k - 1, e * n); } } for (k = 1; k < len; k += 2) fmpz_neg(t + k, t + k); _fmpz_poly_mullow(v, t, len, u, len, len); fmpz_mul(t, t, t); for (k = 0; k < len; k++) fmpz_divexact(res + k + 1, v + k, t); } fmpz_set_ui(res + 0, n == 0); for (k = n; k < klen; k++) fmpz_set_ui(res + k, n == k); _fmpz_vec_clear(t, len + 1); _fmpz_vec_clear(u, len); _fmpz_vec_clear(v, len); } static void divisor_table(unsigned int * tab, slong len) { slong i, j; for (i = 0; i < len; i++) { tab[2 * i] = 1; tab[2 * i + 1] = i; } for (i = 2; i < len; i++) { for (j = 2; j <= i && i * j < len; j++) { tab[2 * i * j] = j; tab[2 * i * j + 1] = i; } } } static void arith_stirling_number_2_nmod_vec(mp_ptr res, const unsigned int * divtab, ulong n, slong len, nmod_t mod) { mp_ptr t, u; slong i; mp_limb_t c; TMP_INIT; TMP_START; t = TMP_ALLOC(len * sizeof(mp_limb_t)); u = TMP_ALLOC(len * sizeof(mp_limb_t)); /* compute inverse factorials */ t[len - 1] = 1; for (i = len - 2; i >= 0; i--) t[i] = _nmod_mul_fullword(t[i + 1], i + 1, mod); c = nmod_inv(t[0], mod); t[0] = 1; for (i = 1; i < len; i++) t[i] = _nmod_mul_fullword(t[i], c, mod); /* compute powers */ u[0] = nmod_pow_ui(0, n, mod); u[1] = nmod_pow_ui(1, n, mod); for (i = 2; i < len; i++) { if (divtab[2 * i] == 1) u[i] = nmod_pow_ui(i, n, mod); else u[i] = _nmod_mul_fullword(u[divtab[2 * i]], u[divtab[2 * i + 1]], mod); } for (i = 1; i < len; i++) u[i] = _nmod_mul_fullword(u[i], t[i], mod); for (i = 1; i < len; i += 2) t[i] = nmod_neg(t[i], mod); _nmod_poly_mullow(res, t, len, u, len, len, mod); TMP_END; } #define CRT_MAX_RESOLUTION 16 void arith_stirling_number_2_vec_multi_mod(fmpz * res, ulong n, slong klen) { fmpz_comb_t comb[CRT_MAX_RESOLUTION]; fmpz_comb_temp_t temp[CRT_MAX_RESOLUTION]; mp_ptr primes, residues; mp_ptr * polys; nmod_t mod; slong i, j, k, len, num_primes, num_primes_k, resolution; slong need_bits, size, prime_bits; slong *bounds; unsigned int * divtab; /* per comb */ slong * local_len; slong * local_num_primes; if (klen <= 0) return; if (n <= 2) { arith_stirling_number_2_vec_triangular(res, n, klen); return; } if (klen > n + 1) { _fmpz_vec_zero(res + n + 1, klen - n - 1); klen = n + 1; } len = klen; bounds = flint_malloc(sizeof(slong) * len); need_bits = stirling_2_bound_2exp_vec(bounds, n, len); need_bits = FLINT_MAX(need_bits, 1); /* make bounds nonincreasing */ for (k = len - 2; k >= 0; k--) bounds[k] = FLINT_MAX(bounds[k], bounds[k + 1]); resolution = FLINT_MAX(1, FLINT_MIN(CRT_MAX_RESOLUTION, n / 16)); size = need_bits; prime_bits = FLINT_BITS - 1; num_primes = (size + prime_bits - 1) / prime_bits; primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); polys = flint_malloc(num_primes * sizeof(mp_ptr)); divtab = flint_malloc(2 * len * sizeof(unsigned int)); divisor_table(divtab, len); local_len = flint_malloc(resolution * sizeof(slong)); local_num_primes = flint_malloc(resolution * sizeof(slong)); primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); for (k = 1; k < num_primes; k++) primes[k] = n_nextprime(primes[k-1], 0); for (i = 0; i < resolution; i++) { local_num_primes[i] = FLINT_MAX(1, num_primes * (i + 1) / resolution); fmpz_comb_init(comb[i], primes, local_num_primes[i]); fmpz_comb_temp_init(temp[i], comb[i]); local_len[i] = len; if (i > 0) { while (local_len[i] > 0 && bounds[local_len[i] - 1] < prime_bits * local_num_primes[i - 1]) local_len[i]--; } } for (j = 0; j < num_primes; j++) { i = resolution - 1; while (i > 0 && j < local_num_primes[i - 1]) i--; polys[j] = _nmod_vec_init(local_len[i]); nmod_init(&mod, primes[j]); arith_stirling_number_2_nmod_vec(polys[j], divtab, n, local_len[i], mod); } for (k = 0; k < len; k++) { i = 0; while (i + 1 < resolution && bounds[k] >= comb[i]->num_primes * prime_bits) i++; /* Use only as large a comb as needed */ num_primes_k = comb[i]->num_primes; for (j = 0; j < num_primes_k; j++) residues[j] = polys[j][k]; fmpz_multi_CRT_ui(res + k, residues, comb[i], temp[i], 0); } /* Cleanup */ for (k = 0; k < num_primes; k++) _nmod_vec_clear(polys[k]); for (i = 0; i < resolution; i++) { fmpz_comb_temp_clear(temp[i]); fmpz_comb_clear(comb[i]); } flint_free(primes); flint_free(residues); flint_free(polys); flint_free(divtab); flint_free(bounds); flint_free(local_len); flint_free(local_num_primes); } void arith_stirling_number_2_vec(fmpz * row, ulong n, slong klen) { if (n <= 80) arith_stirling_number_2_vec_triangular(row, n, klen); else if (klen < n / 2) arith_stirling_number_2_vec_convolution(row, n, klen); else arith_stirling_number_2_vec_multi_mod(row, n, klen); } static void stirling_2_egf(fmpz_t res, ulong n, ulong k) { fmpz * num; fmpz * rnum; fmpz_t den; fmpz_t rden; slong i, len; if (k >= n || k == 0) { fmpz_set_ui(res, n == k); return; } len = n - k + 1; num = _fmpz_vec_init(len); rnum = _fmpz_vec_init(len); fmpz_init(den); fmpz_init(rden); fmpz_one(num + len - 1); for (i = len - 2; i >= 0; i--) fmpz_mul_ui(num + i, num + i + 1, i + 2); fmpz_set(den, num + 0); _fmpq_poly_pow_trunc(rnum, rden, num, den, len, k, len); fmpz_set_ui(num, k); fmpz_add_ui(num, num, 1); fmpz_rfac_ui(num, num, n - k); fmpz_mul(num, num, rnum + n - k); fmpz_divexact(res, num, rden); _fmpz_vec_clear(num, len); _fmpz_vec_clear(rnum, len); fmpz_clear(den); fmpz_clear(rden); } static void stirling_2_powsum(fmpz_t s, ulong n, ulong k) { fmpz_t t, u; fmpz *b; slong i, j, m, max_b; max_b = (k + 1) / 2; fmpz_init(t); fmpz_init(u); b = _fmpz_vec_init(max_b + 1); fmpz_one(b + 0); for (j = 1; j <= max_b; j++) { fmpz_mul_ui(b + j, b + j - 1, k + 1 - j); fmpz_divexact_ui(b + j, b + j, j); } fmpz_zero(s); for (j = 1; j <= k; j += 2) { fmpz_ui_pow_ui(u, j, n); m = j; while (1) /* Process each m = 2^p * j */ { i = (m <= max_b) ? m : k - m; if ((k + m) & 1) fmpz_submul(s, b + i, u); else fmpz_addmul(s, b + i, u); m *= 2; if (m > k) break; fmpz_mul_2exp(u, u, n); } } _fmpz_vec_clear(b, max_b + 1); fmpz_fac_ui(t, k); fmpz_divexact(s, s, t); fmpz_clear(t); fmpz_clear(u); } /* req: k >= 2 */ static mp_limb_t stirling_2_nmod(const unsigned int * divtab, ulong n, ulong k, nmod_t mod) { mp_ptr t, u; slong i, bin_len, pow_len; mp_limb_t s1, s2, bden, bd; int bound_limbs; TMP_INIT; TMP_START; pow_len = k + 1; bin_len = FLINT_MIN(pow_len, k / 2 + 1); t = TMP_ALLOC(bin_len * sizeof(mp_limb_t)); u = TMP_ALLOC(pow_len * sizeof(mp_limb_t)); /* compute binomial coefficients + denominator */ t[0] = 1; for (i = 1; i < bin_len; i++) t[i] = _nmod_mul_fullword(t[i - 1], k + 1 - i, mod); bd = t[bin_len - 1 - (k + 1) % 2]; bden = 1; for (i = bin_len - 1; i >= 0; i--) { bden = _nmod_mul_fullword(bden, i + 1, mod); t[i] = _nmod_mul_fullword(t[i], bden, mod); } /* compute powers */ u[0] = nmod_pow_ui(0, n, mod); u[1] = nmod_pow_ui(1, n, mod); for (i = 2; i < pow_len; i++) { if (divtab[2 * i] == 1) u[i] = nmod_pow_ui(i, n, mod); else u[i] = _nmod_mul_fullword(u[divtab[2 * i]], u[divtab[2 * i + 1]], mod); } for (i = 1; i < bin_len; i += 2) t[i] = nmod_neg(t[i], mod); bound_limbs = _nmod_vec_dot_bound_limbs(bin_len, mod); s1 = _nmod_vec_dot(t, u, bin_len, mod, bound_limbs); if (pow_len > bin_len) { bound_limbs = _nmod_vec_dot_bound_limbs(pow_len - bin_len, mod); s2 = _nmod_vec_dot_rev(u + bin_len, t + k - pow_len + 1, pow_len - bin_len, mod, bound_limbs); if (k % 2) s1 = nmod_sub(s1, s2, mod); else s1 = nmod_add(s1, s2, mod); } TMP_END; if (k % 2) s1 = nmod_neg(s1, mod); bden = nmod_mul(bden, bden, mod); bden = nmod_mul(bden, bd, mod); bden = nmod_inv(bden, mod); return nmod_mul(s1, bden, mod); } static void _fmpz_crt_combine(fmpz_t r1r2, fmpz_t m1m2, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2) { fmpz_invmod(m1m2, m1, m2); fmpz_mul(m1m2, m1m2, m1); fmpz_sub(r1r2, r2, r1); fmpz_mul(r1r2, r1r2, m1m2); fmpz_add(r1r2, r1r2, r1); fmpz_mul(m1m2, m1, m2); fmpz_mod(r1r2, r1r2, m1m2); } static void tree_crt(fmpz_t r, fmpz_t m, mp_srcptr residues, mp_srcptr primes, slong len) { if (len == 0) { fmpz_zero(r); fmpz_one(m); } else if (len == 1) { fmpz_set_ui(r, residues[0]); fmpz_set_ui(m, primes[0]); } else { fmpz_t r1, m1, r2, m2; fmpz_init(r1); fmpz_init(m1); fmpz_init(r2); fmpz_init(m2); tree_crt(r1, m1, residues, primes, len / 2); tree_crt(r2, m2, residues + len / 2, primes + len / 2, len - len / 2); _fmpz_crt_combine(r, m, r1, m1, r2, m2); fmpz_clear(r1); fmpz_clear(m1); fmpz_clear(r2); fmpz_clear(m2); } } static void stirling_2_multi_mod(fmpz_t res, ulong n, ulong k) { fmpz_t tmp; nmod_t mod; mp_ptr primes, residues; slong i, num_primes; flint_bitcnt_t size, prime_bits; unsigned int * divtab; size = stirling_2_bound_2exp(n, k); prime_bits = FLINT_BITS - 1; num_primes = (size + prime_bits - 1) / prime_bits; fmpz_init(tmp); primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); divtab = flint_malloc(2 * sizeof(unsigned int) * (n + 1)); divisor_table(divtab, n + 1); primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); for (i = 1; i < num_primes; i++) primes[i] = n_nextprime(primes[i - 1], 0); for (i = 0; i < num_primes; i++) { nmod_init(&mod, primes[i]); residues[i] = stirling_2_nmod(divtab, n, k, mod); } tree_crt(res, tmp, residues, primes, num_primes); flint_free(primes); flint_free(residues); flint_free(divtab); fmpz_clear(tmp); } void arith_stirling_number_2(fmpz_t res, ulong n, ulong k) { if (k >= n) { fmpz_set_ui(res, n == k); } else if (k <= 1) { fmpz_set_ui(res, k); } else if (k == n - 1) /* S(n, n-1) = binomial(n, 2) */ { fmpz_set_ui(res, n); fmpz_mul_ui(res, res, n - 1); fmpz_tdiv_q_2exp(res, res, 1); } else if (k == 2) /* S(n,2) = 2^(n-1)-1 */ { fmpz_one(res); fmpz_mul_2exp(res, res, n - 1); fmpz_sub_ui(res, res, 1); } else if (n <= MAX_N_1LIMB) { mp_limb_t c[MAX_N_2LIMB + 1]; triangular_1(c, n, k + 1); fmpz_set_ui(res, c[k]); } else if (n <= MAX_N_2LIMB) { mp_limb_t c[2 * MAX_N_2LIMB + 2]; triangular_2(c, n, k + 1); fmpz_set_uiui(res, c[2 * k + 1], c[2 * k]); } else { double low_cutoff, high_cutoff; if (n < 200) { low_cutoff = high_cutoff = 0.9; } else { if (n < 3000) low_cutoff = 0.95 * exp(-0.00022 * n); else low_cutoff = 1500 / n; low_cutoff = FLINT_MAX(low_cutoff, 0.0002); low_cutoff = FLINT_MIN(low_cutoff, 0.8); high_cutoff = 0.92 + 0.005 * log(n); high_cutoff = FLINT_MIN(high_cutoff, 0.98); } if (k <= low_cutoff * n) stirling_2_powsum(res, n, k); else if (k >= high_cutoff * n) stirling_2_egf(res, n, k); else stirling_2_multi_mod(res, n, k); } } flint-3.1.3/src/arith/stirlingmat.c000066400000000000000000000016541461254215100172400ustar00rootroot00000000000000/* Copyright (C) 2010, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "gr.h" #include "gr_mat.h" void arith_stirling_matrix_1u(fmpz_mat_t mat) { gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); GR_MUST_SUCCEED(gr_mat_stirling((gr_mat_struct *) mat, 0, ctx)); } void arith_stirling_matrix_1(fmpz_mat_t mat) { gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); GR_MUST_SUCCEED(gr_mat_stirling((gr_mat_struct *) mat, 1, ctx)); } void arith_stirling_matrix_2(fmpz_mat_t mat) { gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); GR_MUST_SUCCEED(gr_mat_stirling((gr_mat_struct *) mat, 2, ctx)); } flint-3.1.3/src/arith/sum_of_squares.c000066400000000000000000000051221461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "arith.h" static void sum_of_two_squares(fmpz_t r, const fmpz_t n) { fmpz_factor_t fac; slong i; fmpz_factor_init(fac); fmpz_factor(fac, n); fmpz_one(r); for (i = 0; i < fac->num; i++) { const int res = fmpz_fdiv_ui(fac->p + i, 4); if (res == 1) { fac->exp[i]++; fmpz_mul_ui(r, r, fac->exp[i]); } else if (res == 3) { if (fac->exp[i] % 2) { fmpz_zero(r); break; } } } fmpz_mul_ui(r, r, 4); fmpz_factor_clear(fac); } static void sum_of_four_squares(fmpz_t r, const fmpz_t n) { const flint_bitcnt_t v = fmpz_val2(n); if (v == 0) { arith_divisor_sigma(r, 1, n); fmpz_mul_ui(r, r, 8); } else { fmpz_tdiv_q_2exp(r, n, v); arith_divisor_sigma(r, 1, r); fmpz_mul_ui(r, r, 24); } } static void sum_of_squares_recursive(fmpz_t r, slong k, ulong n) { fmpz_t t, u; slong i, j; fmpz_init(t); fmpz_init(u); fmpz_zero(r); for (i = j = 0; j <= n; i++) { fmpz_set_ui(u, n - j); arith_sum_of_squares(t, k - 1, u); if (j > 0) fmpz_mul_ui(t, t, 2); fmpz_add(r, r, t); j += 2 * i + 1; } fmpz_clear(t); fmpz_clear(u); } static void sum_of_squares_series(fmpz_t r, ulong k, slong n) { fmpz * t; t = _fmpz_vec_init(n + 1); arith_sum_of_squares_vec(t, k, n + 1); fmpz_set(r, t + n); _fmpz_vec_clear(t, n + 1); } void arith_sum_of_squares(fmpz_t r, ulong k, const fmpz_t n) { if (fmpz_sgn(n) <= 0 || k == 0) fmpz_set_ui(r, fmpz_is_zero(n) != 0); else if (k == 1) fmpz_set_ui(r, 2 * (fmpz_is_square(n) != 0)); else if (k == 2) sum_of_two_squares(r, n); else if (k == 4) sum_of_four_squares(r, n); else if (k == 3 || k == 5) sum_of_squares_recursive(r, k, fmpz_get_ui(n)); else if (fmpz_fits_si(n)) sum_of_squares_series(r, k, fmpz_get_ui(n)); else { flint_throw(FLINT_ERROR, "Exception (arith_sum_of_squares). n is too large.\n"); } } flint-3.1.3/src/arith/sum_of_squares_vec.c000066400000000000000000000037111461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "arith.h" static void theta3_qexp(fmpz * r, slong n) { slong i, j; _fmpz_vec_zero(r, n); for (i = j = 0; j < n; i++) { fmpz_set_ui(r + j, i == 0 ? 1 : 2); j += 1 + 2*i; } } static void theta3_qexp_squared(fmpz * r, slong n) { slong i, j, x, y; _fmpz_vec_zero(r, n); for (x = i = 0; x < n; i++) { for (y = j = 0; x + y < n; j++) { fmpz_add_ui(r + x + y, r + x + y, (x ? 2 : 1) * (y ? 2 : 1)); y += 2 * j + 1; } x += 2 * i + 1; } } void arith_sum_of_squares_vec(fmpz * r, ulong k, slong n) { if (k == 0 || n <= 1) { _fmpz_vec_zero(r, n); if (n > 0) fmpz_set_ui(r, 1); } else if (k == 1) { theta3_qexp(r, n); } else if (k == 2) { theta3_qexp_squared(r, n); } else if (k % 2 == 0) { fmpz * t = _fmpz_vec_init(n); theta3_qexp_squared(t, n); _fmpz_poly_pow_trunc(r, t, k / 2, n); _fmpz_vec_clear(t, n); } else { fmpz *t, *u; t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); theta3_qexp_squared(t, n); if (k == 3) { theta3_qexp(u, n); _fmpz_poly_mullow(r, t, n, u, n, n); } else { _fmpz_poly_pow_trunc(u, t, (k - 1) / 2, n); theta3_qexp(t, n); _fmpz_poly_mullow(r, t, n, u, n, n); } _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); } } flint-3.1.3/src/arith/test/000077500000000000000000000000001461254215100155105ustar00rootroot00000000000000flint-3.1.3/src/arith/test/main.c000066400000000000000000000045611461254215100166060ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-bell_number.c" #include "t-bell_number_multi_mod.c" #include "t-bell_number_nmod.c" #include "t-bell_number_nmod_vec.c" #include "t-bell_number_vec.c" #include "t-bernoulli_number.c" #include "t-bernoulli_number_denom.c" #include "t-bernoulli_number_vec.c" #include "t-bernoulli_polynomial.c" #include "t-chebyshev_t_polynomial.c" #include "t-chebyshev_u_polynomial.c" #include "t-divisors.c" #include "t-euler_number_vec.c" #include "t-euler_number_zeta.c" #include "t-euler_polynomial.c" #include "t-harmonic_number.c" #include "t-landau_function_vec.c" #include "t-number_of_partitions_vec.c" #include "t-ramanujan_tau.c" #include "t-stirling.c" #include "t-sum_of_squares.c" #include "t-swinnerton_dyer_polynomial.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(arith_bell_number), TEST_FUNCTION(arith_bell_number_multi_mod), TEST_FUNCTION(arith_bell_number_nmod), TEST_FUNCTION(arith_bell_number_nmod_vec), TEST_FUNCTION(arith_bell_number_vec), TEST_FUNCTION(arith_bernoulli_number), TEST_FUNCTION(arith_bernoulli_number_denom), TEST_FUNCTION(arith_bernoulli_number_vec), TEST_FUNCTION(arith_bernoulli_polynomial), TEST_FUNCTION(arith_chebyshev_t_polynomial), TEST_FUNCTION(arith_chebyshev_u_polynomial), TEST_FUNCTION(arith_divisors), TEST_FUNCTION(arith_euler_number_vec), TEST_FUNCTION(arith_euler_number_zeta), TEST_FUNCTION(arith_euler_polynomial), TEST_FUNCTION(arith_harmonic_number), TEST_FUNCTION(arith_landau_function_vec), TEST_FUNCTION(arith_number_of_partitions_vec), TEST_FUNCTION(arith_ramanujan_tau), TEST_FUNCTION(arith_stirling), TEST_FUNCTION(arith_sum_of_squares), TEST_FUNCTION(arith_swinnerton_dyer_polynomial) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/arith/test/t-bell_number.c000066400000000000000000000076431461254215100204150ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" #define STRESS_TEST 0 #if STRESS_TEST #define MAXN 100000 #define MAXN_VEC 10000 #else #define MAXN 4000 #define MAXN_VEC 500 #endif TEST_FUNCTION_START(arith_bell_number, state) { { slong len, prev_len; fmpz * vb1, * vb2; fmpz_t b; mp_ptr vnb, vnr; slong n, iter; ulong nb; nmod_t mod; prev_len = 0; fmpz_init(b); for (n = 0; n < MAXN; n += n_randint(state, n / 4 + 2)) { #if STRESS_TEST flint_printf("%wd\n", n); #endif arith_bell_number(b, n); for (iter = 0; iter < 3 + 10 * STRESS_TEST; iter++) { nmod_init(&mod, n_randtest_not_zero(state)); nb = arith_bell_number_nmod(n, mod); if (nb != fmpz_fdiv_ui(b, mod.n)) { flint_printf("FAIL (vs nmod, n = %wd)\n", n); fflush(stdout); flint_abort(); } } } for (len = 0; len < MAXN_VEC; len = FLINT_MAX(len + 1, len * 1.25)) { vb1 = _fmpz_vec_init(len); vb2 = _fmpz_vec_init(len); vnb = _nmod_vec_init(len); vnr = _nmod_vec_init(len); arith_bell_number_vec_recursive(vb1, len); arith_bell_number_vec_multi_mod(vb2, len); if (!_fmpz_vec_equal(vb1, vb2, len)) { flint_printf("FAIL (len = %wd)\n", len); fflush(stdout); flint_abort(); } for (n = prev_len; n < len; n++) { #if STRESS_TEST flint_printf("%wd\n", n); #endif if (n < 5000) { arith_bell_number_dobinski(b, n); if (!fmpz_equal(vb1 + n, b)) { flint_printf("FAIL (dobinski, n = %wd)\n", n); fflush(stdout); flint_abort(); } } arith_bell_number_multi_mod(b, n); if (!fmpz_equal(vb1 + n, b)) { flint_printf("FAIL (multi_mod, n = %wd)\n", n); fflush(stdout); flint_abort(); } } for (iter = 0; iter < 30; iter++) { nmod_init(&mod, n_randtest_not_zero(state)); arith_bell_number_nmod_vec(vnb, len, mod); _fmpz_vec_get_nmod_vec(vnr, vb1, len, mod); if (!_nmod_vec_equal(vnr, vnb, len)) { flint_printf("FAIL (nmod_vec, len = %wd)\n", len); fflush(stdout); flint_abort(); } if (len) { n = n_randint(state, len); nb = arith_bell_number_nmod(n, mod); if (nb != fmpz_fdiv_ui(vb1 + n, mod.n)) { flint_printf("FAIL (nmod n = %wd)\n", n); fflush(stdout); flint_abort(); } } } _fmpz_vec_clear(vb1, len); _fmpz_vec_clear(vb2, len); _nmod_vec_clear(vnb); _nmod_vec_clear(vnr); prev_len = len; } fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bell_number_multi_mod.c000066400000000000000000000020221461254215100224500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "arith.h" TEST_FUNCTION_START(arith_bell_number_multi_mod, state) { slong i; for (i = 0; i < 100; i++) { slong n; fmpz_t b1, b2; fmpz_init(b1); fmpz_init(b2); n = n_randint(state, 500); arith_bell_number_dobinski(b1, n); arith_bell_number_multi_mod(b2, n); if (!fmpz_equal(b1, b2)) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(b1); fmpz_clear(b2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bell_number_nmod.c000066400000000000000000000025361461254215100214260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" #include "arith.h" TEST_FUNCTION_START(arith_bell_number_nmod, state) { slong i, j, iter; for (i = 0; i < 100 * flint_test_multiplier(); i++) { mp_ptr b; slong n; nmod_t mod; mp_limb_t p, u; n = n_randint(state, 800); if (n_randint(state, 2)) p = n_randtest_not_zero(state); else p = n_randtest_prime(state, 0); nmod_init(&mod, p); b = _nmod_vec_init(n + 1); arith_bell_number_nmod_vec(b, n + 1, mod); for (iter = 0; iter < 5; iter++) { j = n_randint(state, n + 1); u = arith_bell_number_nmod(j, mod); if (u != b[j]) { flint_printf("FAIL: p = %wu, i = %wd\n", p, j); fflush(stdout); flint_abort(); } } _nmod_vec_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bell_number_nmod_vec.c000066400000000000000000000032121461254215100222530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" #include "arith.h" TEST_FUNCTION_START(arith_bell_number_nmod_vec, state) { mp_ptr b1, b2, b3; slong n; const slong maxn = 3000; b1 = _nmod_vec_init(maxn); b2 = _nmod_vec_init(maxn); b3 = _nmod_vec_init(maxn); for (n = 0; n < maxn; n += (n < 50) ? + 1 : n/4) { nmod_t mod; mp_limb_t p; p = n_randtest_not_zero(state); nmod_init(&mod, p); arith_bell_number_nmod_vec_recursive(b1, n, mod); arith_bell_number_nmod_vec_ogf(b2, n, mod); if (!_nmod_vec_equal(b1, b2, n)) { flint_printf("FAIL:\n"); flint_printf("p = %wu\n", p); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } if (arith_bell_number_nmod_vec_series(b3, n, mod)) { if (!_nmod_vec_equal(b1, b3, n)) { flint_printf("FAIL (2):\n"); flint_printf("p = %wu\n", p); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } } } _nmod_vec_clear(b1); _nmod_vec_clear(b2); _nmod_vec_clear(b3); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bell_number_vec.c000066400000000000000000000021061461254215100212370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "arith.h" TEST_FUNCTION_START(arith_bell_number_vec, state) { fmpz * b1; fmpz * b2; slong n; const slong maxn = 1000; b1 = _fmpz_vec_init(maxn); b2 = _fmpz_vec_init(maxn); for (n = 0; n < maxn; n += (n < 50) ? + 1 : n/4) { arith_bell_number_vec_recursive(b1, n); arith_bell_number_vec_multi_mod(b2, n); if (!_fmpz_vec_equal(b1, b2, n)) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } } _fmpz_vec_clear(b1, maxn); _fmpz_vec_clear(b2, maxn); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bernoulli_number.c000066400000000000000000000045221461254215100214630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq.h" #include "arith.h" TEST_FUNCTION_START(arith_bernoulli_number, state) { fmpz * num1; fmpz * den1; fmpz_t num2; fmpz_t den2; slong n, N; N = 4000; num1 = _fmpz_vec_init(N); den1 = _fmpz_vec_init(N); fmpz_init(num2); fmpz_init(den2); _arith_bernoulli_number_vec_multi_mod(num1, den1, N); for (n = 0; n < N; n++) { _arith_bernoulli_number(num2, den2, n); if (!fmpz_equal(num1 + n, num2)) { flint_printf("FAIL: n = %wd, numerator\n", n); flint_printf("vec: "); fmpz_print(num1 + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(num2); flint_printf("\n"); fflush(stdout); flint_abort(); } if (!fmpz_equal(den1 + n, den2)) { flint_printf("FAIL: n = %wd, denominator\n", n); flint_printf("vec: "); fmpz_print(den1 + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(den2); flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check non underscore versions */ do { slong N = 100; fmpq * x; fmpq_t t; fmpq_init(t); x = flint_malloc(sizeof(fmpq) * N); for (n = 0; n < N; n++) fmpq_init(x + n); arith_bernoulli_number_vec(x, N); for (n = 0; n < N; n++) { arith_bernoulli_number(t, n); if (!fmpq_equal(x + n, t)) { flint_printf("FAIL!: n = %wd\n", n); fflush(stdout); flint_abort(); } } for (n = 0; n < N; n++) fmpq_clear(x + n); flint_free(x); fmpq_clear(t); } while (0); _fmpz_vec_clear(num1, N); _fmpz_vec_clear(den1, N); fmpz_clear(num2); fmpz_clear(den2); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bernoulli_number_denom.c000066400000000000000000000017701461254215100226470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "arith.h" TEST_FUNCTION_START(arith_bernoulli_number_denom, state) { fmpz_t s, t; slong n; fmpz_init(s); fmpz_init(t); for (n = 0; n < 1000; n++) { arith_bernoulli_number_denom(t, n); fmpz_addmul_ui(s, t, n_nth_prime(n+1)); } fmpz_set_str(t, "34549631155954474103407159", 10); if (!fmpz_equal(s, t)) { flint_printf("FAIL: Hash disagrees with known value\n"); fflush(stdout); flint_abort(); } fmpz_clear(s); fmpz_clear(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bernoulli_number_vec.c000066400000000000000000000036021461254215100223160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" TEST_FUNCTION_START(arith_bernoulli_number_vec, state) { fmpz * num1; fmpz * num2; fmpz * den1; fmpz * den2; slong i, n, N; N = 2000; num1 = _fmpz_vec_init(N); num2 = _fmpz_vec_init(N); den1 = _fmpz_vec_init(N); den2 = _fmpz_vec_init(N); for (n = 0; n < N; n += (n<100) ? 1 : n/3) { _arith_bernoulli_number_vec_recursive(num1, den1, n); _arith_bernoulli_number_vec_multi_mod(num2, den2, n); for (i = 0; i < n; i++) { if (!fmpz_equal(num1 + i, num2 + i)) { flint_printf("FAIL: n = %wd, numerator of B_%wd\n", n, i); flint_printf("recursive: "); fmpz_print(num1 + i); flint_printf("\n"); flint_printf("multi_mod: "); fmpz_print(num2 + i); flint_printf("\n"); fflush(stdout); flint_abort(); } if (!fmpz_equal(den1 + i, den2 + i)) { flint_printf("FAIL: n = %wd, denominator of B_%wd\n", n, i); flint_printf("recursive: "); fmpz_print(den1 + i); flint_printf("\n"); flint_printf("multi_mod: "); fmpz_print(den2 + i); flint_printf("\n"); fflush(stdout); flint_abort(); } } } _fmpz_vec_clear(num1, N); _fmpz_vec_clear(num2, N); _fmpz_vec_clear(den1, N); _fmpz_vec_clear(den2, N); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-bernoulli_polynomial.c000066400000000000000000000030111461254215100223460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" #include "arith.h" TEST_FUNCTION_START(arith_bernoulli_polynomial, state) { fmpq_poly_t P, Q; fmpz_t t; slong k, n; for (n = 0; n <= 100; n++) { fmpq_poly_init(P); fmpq_poly_init(Q); fmpz_init(t); for (k = 0; k <= n; k++) { arith_bernoulli_polynomial(P, k); fmpz_bin_uiui(t, n+1, k); fmpq_poly_scalar_mul_fmpz(P, P, t); fmpq_poly_add(Q, Q, P); } fmpq_poly_scalar_div_ui(Q, Q, n+1); fmpz_clear(t); fmpq_poly_zero(P); fmpq_poly_set_coeff_ui(P, n, UWORD(1)); if (!fmpq_poly_equal(P, Q)) { flint_printf("ERROR: sum up to n = %wd did not add to x^n\n", n); flint_printf("Sum: "); fmpq_poly_print_pretty(Q, "x"); flint_printf("\nExpected: "); fmpq_poly_print_pretty(P, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(P); fmpq_poly_clear(Q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-chebyshev_t_polynomial.c000066400000000000000000000027671461254215100226770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "arith.h" TEST_FUNCTION_START(arith_chebyshev_t_polynomial, state) { fmpz_poly_t T0, T1, T2, t; slong n; fmpz_poly_init(T0); fmpz_poly_init(T1); fmpz_poly_init(T2); fmpz_poly_init(t); arith_chebyshev_t_polynomial(T0, 0); arith_chebyshev_t_polynomial(T1, 1); for (n = 2; n <= 500; n++) { arith_chebyshev_t_polynomial(T2, n); /* Verify T_{n+1} = 2 x T_n - T_{n-1} */ fmpz_poly_scalar_mul_ui(t, T1, UWORD(2)); fmpz_poly_shift_left(t, t, 1); fmpz_poly_sub(t, t, T0); if (!fmpz_poly_equal(t, T2)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("t: "); fmpz_poly_print_pretty(t, "x"); flint_printf("\n"); flint_printf("T2: "); fmpz_poly_print_pretty(T2, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_swap(T0, T1); fmpz_poly_swap(T1, T2); } fmpz_poly_clear(T0); fmpz_poly_clear(T1); fmpz_poly_clear(T2); fmpz_poly_clear(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-chebyshev_u_polynomial.c000066400000000000000000000023171461254215100226670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "arith.h" TEST_FUNCTION_START(arith_chebyshev_u_polynomial, state) { fmpz_poly_t T, U; slong n; fmpz_poly_init(T); fmpz_poly_init(U); for (n = 0; n <= 500; n++) { arith_chebyshev_u_polynomial(U, n); arith_chebyshev_t_polynomial(T, n + 1); fmpz_poly_derivative(T, T); fmpz_poly_scalar_divexact_ui(T, T, n + 1); if (!fmpz_poly_equal(T, U)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("T: "); fmpz_poly_print_pretty(T, "x"); flint_printf("\n"); flint_printf("U: "); fmpz_poly_print_pretty(U, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(T); fmpz_poly_clear(U); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-divisors.c000066400000000000000000000025131461254215100177600ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "arith.h" void arith_divisors_naive(fmpz_poly_t p, slong n) { slong k; slong i = 0; n = FLINT_ABS(n); fmpz_poly_zero(p); for (k = 1; k <= n; k++) { if (n % k == 0) { fmpz_poly_set_coeff_si(p, i, k); i++; } } } TEST_FUNCTION_START(arith_divisors, state) { fmpz_t t; fmpz_poly_t a, b; slong n; fmpz_init(t); fmpz_poly_init(a); fmpz_poly_init(b); for (n = -1000; n < 1000; n++) { fmpz_set_si(t, n); arith_divisors(a, t); arith_divisors_naive(b, n); if (!fmpz_poly_equal(a, b)) { flint_printf("FAIL:\n"); flint_printf("wrong value for n=%wd\n", n); fflush(stdout); flint_abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-euler_number_vec.c000066400000000000000000000025031461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" TEST_FUNCTION_START(arith_euler_number_vec, state) { fmpz * r; fmpz_t s, t; slong k, n; for (n = 2; n <= 3000; n += (n<100) ? 2 : n/3) { n += n % 2; r = _fmpz_vec_init(n + 1); fmpz_init(s); fmpz_init(t); arith_euler_number_vec(r, n + 1); /* sum binomial(n,k) E_k = 0 */ fmpz_set_ui(t, UWORD(1)); for (k = 0; k <= n; k++) { fmpz_addmul(s, r + k, t); fmpz_mul_ui(t, t, n - k); fmpz_divexact_ui(t, t, k + 1); } if (!fmpz_is_zero(s)) { flint_printf("ERROR: sum over 0,...,n = %wd\n", n); _fmpz_vec_print(r, n + 1); fflush(stdout); flint_abort(); } fmpz_clear(s); fmpz_clear(t); _fmpz_vec_clear(r, n + 1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-euler_number_zeta.c000066400000000000000000000020731461254215100216260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" TEST_FUNCTION_START(arith_euler_number_zeta, state) { fmpz * ress; fmpz_t res; slong n, N; N = 50; ress = _fmpz_vec_init(N); arith_euler_number_vec(ress, N); for (n = 0; n < N; n++) { fmpz_init(res); arith_euler_number(res, n); if (!fmpz_equal(res, ress + n)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("Value: "); fmpz_print(res); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(res); } _fmpz_vec_clear(ress, N); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-euler_polynomial.c000066400000000000000000000031041461254215100214720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" #include "arith.h" TEST_FUNCTION_START(arith_euler_polynomial, state) { fmpq_poly_t P, Q; fmpz_t t; slong k, n; for (n = 0; n <= 100; n++) { fmpq_poly_init(P); fmpq_poly_init(Q); fmpz_init(t); for (k = 0; k < n; k++) { arith_euler_polynomial(P, k); fmpz_bin_uiui(t, n, k); fmpq_poly_scalar_mul_fmpz(P, P, t); fmpq_poly_add(Q, Q, P); } fmpq_poly_scalar_div_ui(Q, Q, 2); arith_euler_polynomial(P, n); fmpq_poly_add(Q, Q, P); fmpz_clear(t); fmpq_poly_zero(P); fmpq_poly_set_coeff_ui(P, n, UWORD(1)); if (!fmpq_poly_equal(P, Q)) { flint_printf("ERROR: sum up to n = %wd did not add to x^n\n", n); flint_printf("Sum: "); fmpq_poly_print_pretty(Q, "x"); flint_printf("\nExpected: "); fmpq_poly_print_pretty(P, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(P); fmpq_poly_clear(Q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-harmonic_number.c000066400000000000000000000064141461254215100212720ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fmpq.h" #include "arith.h" void numerical_test(fmpq_t res, slong n, double ans) { const double tol = 1e-13; double err; mpq_t tmp; mpq_init(tmp); arith_harmonic_number(res, n); fmpq_get_mpq(tmp, res); err = mpq_get_d(tmp) - ans; err = FLINT_ABS(err); if (err > tol) { flint_printf("FAIL: %wd %.16f %.16f\n", n, mpq_get_d(tmp), ans); fflush(stdout); flint_abort(); } mpq_clear(tmp); } void mpq_harmonic_balanced(mpq_t res, slong a, slong b) { slong k; mpq_t t; mpq_init(t); if (b - a < 50) { flint_mpq_set_ui(res, 0, UWORD(1)); for (k = a; k <= b; k++) { flint_mpq_set_ui(t, UWORD(1), k); mpq_add(res, res, t); } } else { mpq_harmonic_balanced(res, a, (a+b)/2); mpq_harmonic_balanced(t, (a+b)/2+1, b); mpq_add(res, res, t); } mpq_clear(t); } TEST_FUNCTION_START(arith_harmonic_number, state) { slong i; mpq_t x, y; fmpq_t t; fmpq_init(t); mpq_init(x); mpq_init(y); for (i = -2; i < 1000; i++) { mpq_harmonic_balanced(x, 1, i); arith_harmonic_number(t, i); fmpq_get_mpq(y, t); if (!mpq_equal(x, y)) { flint_printf("FAIL: %wd\n", i); fflush(stdout); flint_abort(); } } numerical_test(t, 1000, 7.4854708605503449127); numerical_test(t, 1001, 7.4864698615493459117); numerical_test(t, 1002, 7.4874678655413618797); numerical_test(t, 1003, 7.4884648745144426375); numerical_test(t, 10000, 9.7876060360443822642); numerical_test(t, 10001, 9.7877060260453821642); numerical_test(t, 10002, 9.7878060060493813643); numerical_test(t, 10003, 9.7879059760583786652); numerical_test(t, 10004, 9.7880059360743722677); numerical_test(t, 20000, 10.480728217229327573); numerical_test(t, 30000, 10.886184992119899362); numerical_test(t, 40000, 11.173862897945522882); numerical_test(t, 50000, 11.397003949278482638); numerical_test(t, 60000, 11.579323839415955783); numerical_test(t, 70000, 11.733473328773164956); numerical_test(t, 80000, 11.867003828544530692); numerical_test(t, 90000, 11.984786169759202469); numerical_test(t, 100000, 12.090146129863427947); numerical_test(t, 100001, 12.090156129763428947); numerical_test(t, 100002, 12.090166129563432947); numerical_test(t, 100003, 12.090176129263441947); numerical_test(t, 100004, 12.090186128863457946); numerical_test(t, 300000, 13.188755085205611713); numerical_test(t, 500000, 13.699580042305528322); numerical_test(t, 700000, 14.036051993212618803); numerical_test(t, 900000, 14.287366262763433338); mpq_clear(x); mpq_clear(y); fmpq_clear(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-landau_function_vec.c000066400000000000000000000026431461254215100221300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" /* Defined in t-landau_function_vec.c and t-sum_of_squares.c */ #define known known_landau_function_vec static const mp_limb_t known[] = { 1, 1, 2, 3, 4, 6, 6, 12, 15, 20, 30, 30, 60, 60, 84, 105, 140, 210, 210, 420, 420, 420, 420, 840, 840, 1260, 1260, 1540, 2310, 2520, 4620, 4620, 5460, 5460, 9240, 9240, 13860, 13860, 16380, 16380, 27720, 30030, 32760, 60060, 60060, 60060, 60060, 120120 }; TEST_FUNCTION_START(arith_landau_function_vec, state) { fmpz * res; slong k, n; n = 45; res = _fmpz_vec_init(n); arith_landau_function_vec(res, n); for (k = 0; k < n; k++) { if (fmpz_cmp_ui(res + k, known[k])) { flint_printf("FAIL:\n"); flint_printf("k = %wd, res[k] = %wd, expected: %wd\n", k, fmpz_get_si(res + k), known[k]); fflush(stdout); flint_abort(); } } _fmpz_vec_clear(res, n); TEST_FUNCTION_END(state); } #undef known flint-3.1.3/src/arith/test/t-number_of_partitions_vec.c000066400000000000000000000045111461254215100232030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" TEST_FUNCTION_START(arith_number_of_partitions_vec, state) { fmpz * p; mp_ptr pmod; slong k, n; const slong maxn = 1000; p = _fmpz_vec_init(maxn); pmod = _nmod_vec_init(maxn); for (n = 0; n < maxn; n += (n < 50) ? + 1 : n/4) { fmpz_t s, t; nmod_t mod; nmod_init(&mod, n_randtest_prime(state, 0)); arith_number_of_partitions_vec(p, n); arith_number_of_partitions_nmod_vec(pmod, n, mod); for (k = 0; k < n; k++) { if (fmpz_fdiv_ui(p + k, mod.n) != pmod[k]) { flint_printf("FAIL:\n"); flint_printf("n = %wd, k = %wd\n", n, k); fflush(stdout); flint_abort(); } } if (n > 1) { fmpz_init(s); fmpz_init(t); for (k = 1; k < n; k++) { slong j; j = n - 1 - k*(3*k - 1)/2; if (j >= 0) fmpz_set(t, p + j); else fmpz_zero(t); j = n - 1 - k*(3*k + 1)/2; if (j >= 0) fmpz_add(t, t, p + j); if (k % 2) fmpz_add(s, s, t); else fmpz_sub(s, s, t); } if (!fmpz_equal(s, p + n - 1)) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); fmpz_print(s); flint_printf("\n"); fmpz_print(p + n - 1); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(s); fmpz_clear(t); } } _fmpz_vec_clear(p, maxn); _nmod_vec_clear(pmod); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-ramanujan_tau.c000066400000000000000000000104051461254215100207420ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "arith.h" void check_value(slong n, char *ans) { fmpz_t x, y; fmpz_init(x); fmpz_init(y); fmpz_set_si(y, n); arith_ramanujan_tau(x, y); fmpz_set_str(y, ans, 10); if (!fmpz_equal(x,y)) { flint_printf("FAIL:\n"); flint_printf("tau(%wd) gave ", n); fmpz_print(x); flint_printf(", expected %s\n", ans); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); } void consistency_check(slong n) { fmpz_poly_t p; fmpz_t x, y; slong k; fmpz_poly_init(p); fmpz_init(x); fmpz_init(y); arith_ramanujan_tau_series(p, n); if (p->length != n && !(n == 1 && p->length == 0)) { flint_printf("FAIL:\n"); flint_printf("wrong length of polynomial %wd\n", n); fflush(stdout); flint_abort(); } for (k=0; k. */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "arith.h" TEST_FUNCTION_START(arith_stirling, state) { fmpz_mat_t mat, mat2, mat3; fmpz * row; fmpz_t s; slong n, k, mm, nn; const slong maxn = 40; fmpz_init(s); /* test a few large Stirling numbers */ { slong iter; fmpz_t a, b, c, d; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); for (iter = 0; iter < 50 * flint_test_multiplier(); iter++) { n = n_randint(state, 200); k = 1 + n_randint(state, 200); arith_stirling_number_1u(a, n + 1, k); arith_stirling_number_1u(b, n, k); arith_stirling_number_1u(c, n, k - 1); fmpz_set(d, c); fmpz_addmul_ui(d, b, n); if (!fmpz_equal(a, d)) { flint_printf("stirling1u"); flint_printf("n = %wd, k = %wd\n", n, k); flint_printf("a: "); fmpz_print(a); flint_printf("\n"); flint_printf("b: "); fmpz_print(b); flint_printf("\n"); flint_printf("c: "); fmpz_print(c); flint_printf("\n"); flint_printf("d: "); fmpz_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } } for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { n = n_randint(state, 1000); k = 1 + n_randint(state, 1000); arith_stirling_number_2(a, n + 1, k); arith_stirling_number_2(b, n, k); arith_stirling_number_2(c, n, k - 1); fmpz_set(d, c); fmpz_addmul_ui(d, b, k); if (!fmpz_equal(a, d)) { flint_printf("stirling2"); flint_printf("n = %wd, k = %wd\n", n, k); flint_printf("a: "); fmpz_print(a); flint_printf("\n"); flint_printf("b: "); fmpz_print(b); flint_printf("\n"); flint_printf("c: "); fmpz_print(c); flint_printf("\n"); flint_printf("d: "); fmpz_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } } for (iter = 0; iter < 50 * flint_test_multiplier(); iter++) { n = n_randint(state, 200); k = 1 + n_randint(state, 200); row = _fmpz_vec_init(k + 1); arith_stirling_number_1u_vec(row, n, k + 1); arith_stirling_number_1u(b, n, k); if (!fmpz_equal(row + k, b)) { flint_printf("stirling1u (2)"); flint_printf("n = %wd, k = %wd\n", n, k); flint_printf("a: "); fmpz_print(row + k); flint_printf("\n"); flint_printf("b: "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(row, k + 1); } for (iter = 0; iter < 50 * flint_test_multiplier(); iter++) { n = n_randint(state, 400); k = 1 + n_randint(state, 400); row = _fmpz_vec_init(k + 1); arith_stirling_number_2_vec(row, n, k + 1); arith_stirling_number_2(b, n, k); if (!fmpz_equal(row + k, b)) { flint_printf("stirling2 (2)"); flint_printf("n = %wd, k = %wd\n", n, k); flint_printf("a: "); fmpz_print(row + k); flint_printf("\n"); flint_printf("b: "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(row, k + 1); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); } for (mm = 0; mm < maxn / 2; mm++) { /* Consistency test for stirling1u */ for (nn = 0; nn < maxn; nn++) { fmpz_mat_init(mat, mm, nn); arith_stirling_matrix_1u(mat); for (n = 0; n < mm; n++) { for (k = 0; k < nn; k++) { row = _fmpz_vec_init(k); arith_stirling_number_1u_vec(row, n, k); if (!_fmpz_vec_equal(row, mat->rows[n], k)) { flint_printf("stirling1u mat != vec "); flint_printf("nn,n,k=%wd,%wd,%wd\n", nn, n, k); flint_printf("mat: "); _fmpz_vec_print(mat->rows[n], k); flint_printf("\nvec: "); _fmpz_vec_print(row, k); fflush(stdout); flint_abort(); } _fmpz_vec_clear(row, k); arith_stirling_number_1u(s, n, k); if (!fmpz_equal(mat->rows[n]+k, s)) { flint_printf("stirling1u mat != single "); flint_printf("nn,n,k=%wd,%wd,%wd\n", nn, n, k); flint_printf("mat: "); fmpz_print(mat->rows[n]+k); flint_printf("\nsingle: "); fmpz_print(s); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(mat); } /* Consistency test for stirling1 */ for (nn = 0; nn < maxn; nn++) { fmpz_mat_init(mat, mm, nn); arith_stirling_matrix_1(mat); for (n = 0; n < mm; n++) { for (k = 0; k < nn; k++) { row = _fmpz_vec_init(k); arith_stirling_number_1_vec(row, n, k); if (!_fmpz_vec_equal(row, mat->rows[n], k)) { flint_printf("stirling1 mat != vec "); flint_printf("nn,n,k=%wd,%wd,%wd\n", nn, n, k); flint_printf("mat: "); _fmpz_vec_print(mat->rows[n], k); flint_printf("\nvec: "); _fmpz_vec_print(row, k); fflush(stdout); flint_abort(); } _fmpz_vec_clear(row, k); arith_stirling_number_1(s, n, k); if (!fmpz_equal(mat->rows[n]+k, s)) { flint_printf("stirling1 mat != single "); flint_printf("nn,n,k=%wd,%wd,%wd\n", nn, n, k); flint_printf("mat: "); fmpz_print(mat->rows[n]+k); flint_printf("\nsingle: "); fmpz_print(s); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(mat); } /* Consistency test for stirling2 */ for (nn = 0; nn < maxn; nn++) { fmpz_mat_init(mat, mm, nn); arith_stirling_matrix_2(mat); for (n = 0; n < mm; n++) { for (k = 0; k < nn; k++) { row = _fmpz_vec_init(k); arith_stirling_number_2_vec(row, n, k); if (!_fmpz_vec_equal(row, mat->rows[n], k)) { flint_printf("stirling2 mat != vec "); flint_printf("nn,n,k=%wd,%wd,%wd\n", nn, n, k); flint_printf("mat: "); _fmpz_vec_print(mat->rows[n], k); flint_printf("\nvec: "); _fmpz_vec_print(row, k); fflush(stdout); flint_abort(); } _fmpz_vec_clear(row, k); arith_stirling_number_2(s, n, k); if (!fmpz_equal(mat->rows[n]+k, s)) { flint_printf("stirling2 mat != single "); flint_printf("nn,n,k=%wd,%wd,%wd\n", nn, n, k); flint_printf("mat: "); fmpz_print(mat->rows[n]+k); flint_printf("\nsingle: "); fmpz_print(s); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(mat); } } /* Matrix inverse test */ for (nn = 1; nn < 50; nn++) { fmpz_mat_init(mat, nn, nn); fmpz_mat_init(mat2, nn, nn); fmpz_mat_init(mat3, nn, nn); arith_stirling_matrix_1(mat); arith_stirling_matrix_2(mat2); fmpz_mat_mul(mat3, mat, mat2); for (n = 0; n < nn; n++) { for (k = 0; k < nn; k++) { if (fmpz_get_ui(mat3->rows[n]+k) != (n == k)) { flint_printf("not identity matrix: %wd, %wd, %wd\n", nn, n, k); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(mat); fmpz_mat_clear(mat2); fmpz_mat_clear(mat3); } fmpz_clear(s); TEST_FUNCTION_END(state); } flint-3.1.3/src/arith/test/t-sum_of_squares.c000066400000000000000000000036251461254215100211560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" #define N 10 /* Defined in t-landau_function_vec.c and t-sum_of_squares.c */ #define known known_sum_of_squares static const fmpz known[N][N] = { {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 2, 0, 0, 2, 0, 0, 0, 0, 2}, {1, 4, 4, 0, 4, 8, 0, 0, 4, 4}, {1, 6, 12, 8, 6, 24, 24, 0, 12, 30}, {1, 8, 24, 32, 24, 48, 96, 64, 24, 104}, {1, 10, 40, 80, 90, 112, 240, 320, 200, 250}, {1, 12, 60, 160, 252, 312, 544, 960, 1020, 876}, {1, 14, 84, 280, 574, 840, 1288, 2368, 3444, 3542}, {1, 16, 112, 448, 1136, 2016, 3136, 5504, 9328, 12112}, {1, 18, 144, 672, 2034, 4320, 7392, 12672, 22608, 34802} }; TEST_FUNCTION_START(arith_sum_of_squares, state) { fmpz * r; fmpz_t t; slong i, j; r = _fmpz_vec_init(N); fmpz_init(t); for (i = 0; i < N; i++) { arith_sum_of_squares_vec(r, i, N); for (j = 0; j < N; j++) { fmpz_set_ui(t, j); arith_sum_of_squares(t, i, t); if (!fmpz_equal(t, r + j) || !fmpz_equal(t, known[i] + j)) { flint_printf("FAIL:\n"); flint_printf("i, j = %wd, %wd, r[j] = %wd, r(j) = %wd, " "expected: %wd\n", i, j, fmpz_get_si(r + j), fmpz_get_si(t), known[i][j]); fflush(stdout); flint_abort(); } } } _fmpz_vec_clear(r, N); fmpz_clear(t); TEST_FUNCTION_END(state); } #undef N #undef known flint-3.1.3/src/arith/test/t-swinnerton_dyer_polynomial.c000066400000000000000000000024201461254215100236070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "arith.h" static const mp_limb_t known_values[] = { UWORD(2147483629), UWORD(1073742093), UWORD(1342248677), UWORD(3319936736), UWORD(2947821228), UWORD(1019513834), UWORD(3324951530), UWORD(1995039408), UWORD(3505683295), UWORD(3567639420), UWORD(394942914) }; TEST_FUNCTION_START(arith_swinnerton_dyer_polynomial, state) { fmpz_poly_t S; mp_limb_t r; slong n; for (n = 0; n <= 10; n++) { fmpz_poly_init(S); arith_swinnerton_dyer_polynomial(S, n); r = fmpz_poly_evaluate_mod(S, UWORD(2147483629), UWORD(4294967291)); if (r != known_values[n]) { flint_printf("ERROR: wrong evaluation of S_%wd\n", n); fflush(stdout); flint_abort(); } fmpz_poly_clear(S); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bernoulli.h000066400000000000000000000054641461254215100155770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef BERNOULLI_H #define BERNOULLI_H #include #include "arith.h" #include "arb_types.h" #ifdef __cplusplus extern "C" { #endif extern slong FLINT_TLS_PREFIX bernoulli_cache_num; extern FLINT_TLS_PREFIX fmpq * bernoulli_cache; void bernoulli_cache_compute(slong n); /* Crude bound for the bits in d(n) = denom(B_n). By von Staudt-Clausen, d(n) = prod_{p-1 | n} p <= prod_{k | n} 2k <= n^{sigma_0(n)}. We get a more accurate estimate taking the square root of this. Further, at least for sufficiently large n, sigma_0(n) < exp(1.066 log(n) / log(log(n))). */ FLINT_FORCE_INLINE slong bernoulli_denom_size(slong n) { return 0.5 * 1.4427 * log(n) * pow(n, 1.066 / log(log(n))); } FLINT_FORCE_INLINE slong bernoulli_zeta_terms(ulong s, slong prec) { slong N; N = pow(2.0, (prec + 1.0) / (s - 1.0)); N += ((N % 2) == 0); return N; } FLINT_FORCE_INLINE slong bernoulli_power_prec(slong i, ulong s1, slong wp) { slong p = wp - s1 * log(i) * 1.44269504088896341; return FLINT_MAX(p, 10); } /* we should technically add O(log(n)) guard bits, but this is unnecessary in practice since the denominator estimate is quite a bit larger than the true denominators */ FLINT_FORCE_INLINE slong bernoulli_global_prec(ulong nmax) { return arith_bernoulli_number_size(nmax) + bernoulli_denom_size(nmax); } /* avoid potential numerical problems for very small n */ #define BERNOULLI_REV_MIN 32 typedef struct { slong alloc; slong prec; slong max_power; fmpz * powers; fmpz_t pow_error; arb_t prefactor; arb_t two_pi_squared; ulong n; } bernoulli_rev_struct; typedef bernoulli_rev_struct bernoulli_rev_t[1]; void bernoulli_rev_init(bernoulli_rev_t iter, ulong nmax); void bernoulli_rev_next(fmpz_t numer, fmpz_t denom, bernoulli_rev_t iter); void bernoulli_rev_clear(bernoulli_rev_t iter); void bernoulli_fmpq_vec_no_cache(fmpq * res, ulong a, slong num); #define BERNOULLI_ENSURE_CACHED(n) \ do { \ slong __n = (n); \ if (__n >= bernoulli_cache_num) \ bernoulli_cache_compute(__n + 1); \ } while (0); \ slong bernoulli_bound_2exp_si(ulong n); ulong bernoulli_mod_p_harvey(ulong k, ulong p); void _bernoulli_fmpq_ui_multi_mod(fmpz_t num, fmpz_t den, ulong n, double alpha); void _bernoulli_fmpq_ui_zeta(fmpz_t num, fmpz_t den, ulong n); void _bernoulli_fmpq_ui(fmpz_t num, fmpz_t den, ulong n); void bernoulli_fmpq_ui(fmpq_t b, ulong n); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/bernoulli/000077500000000000000000000000001461254215100154155ustar00rootroot00000000000000flint-3.1.3/src/bernoulli/bound_2exp_si.c000066400000000000000000000063211461254215100203230ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bernoulli.h" const short bernoulli_bound_tab[256] = { 1, -2, -4, -5, -4, -3, -1, 1, 3, 6, 10, 13, 17, 21, 25, 30, 34, 39, 44, 49, 55, 60, 66, 71, 77, 83, 89, 95, 102, 108, 115, 121, 128, 135, 141, 148, 155, 162, 170, 177, 184, 192, 199, 207, 214, 222, 230, 237, 245, 253, 261, 269, 277, 285, 294, 302, 310, 318, 327, 335, 344, 352, 361, 370, 378, 387, 396, 405, 413, 422, 431, 440, 449, 458, 467, 477, 486, 495, 504, 514, 523, 532, 542, 551, 561, 570, 580, 589, 599, 608, 618, 628, 638, 647, 657, 667, 677, 687, 697, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 849, 859, 870, 880, 890, 901, 911, 922, 932, 943, 953, 964, 975, 985, 996, 1007, 1017, 1028, 1039, 1050, 1061, 1071, 1082, 1093, 1104, 1115, 1126, 1137, 1148, 1159, 1170, 1181, 1192, 1203, 1214, 1225, 1236, 1247, 1258, 1270, 1281, 1292, 1303, 1315, 1326, 1337, 1349, 1360, 1371, 1383, 1394, 1405, 1417, 1428, 1440, 1451, 1463, 1474, 1486, 1497, 1509, 1520, 1532, 1544, 1555, 1567, 1579, 1590, 1602, 1614, 1625, 1637, 1649, 1661, 1672, 1684, 1696, 1708, 1720, 1732, 1743, 1755, 1767, 1779, 1791, 1803, 1815, 1827, 1839, 1851, 1863, 1875, 1887, 1899, 1911, 1923, 1935, 1948, 1960, 1972, 1984, 1996, 2008, 2021, 2033, 2045, 2057, 2070, 2082, 2094, 2106, 2119, 2131, 2143, 2156, 2168, 2180, 2193, 2205, 2218, 2230, 2243, 2255, 2267, 2280, 2292, 2305, 2317, 2330, 2342, 2355, 2368, 2380, 2393, 2405, 2418, 2430, 2443, 2456, 2468, 2481, 2494, 2506, }; #define LOG_PREC 6 /* table of ceil(log(n,2) * M - log_prec * M) for n from M to 2M inclusive where M = 2^LOG_PREC */ const unsigned char log_tab[] = { 0, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, 54, 55, 55, 56, 57, 58, 59, 59, 60, 61, 62, 62, 63, 64, 64 }; slong bernoulli_bound_2exp_si(ulong n) { if (n % 2) { if (n == 1) return -WORD(1); else return LONG_MIN; } else if (n < 512) { return bernoulli_bound_tab[n / 2]; } else { /* |B_n| < 4 * n! / (2*pi)^n < 4 * (n+1)^(n+1) e^(-n) / (2*pi)^n */ mp_limb_t l, u, hi, lo; int b, shift; b = FLINT_BIT_COUNT(n + 1); shift = b - (LOG_PREC + 1); /* (n+1) * log_2(n+1) */ u = n + 1; l = log_tab[((u >> shift) + 1) - (1 << LOG_PREC)]; l += (LOG_PREC << LOG_PREC); umul_ppmm(hi, lo, l, u); if (hi || n > (UWORD(1) << (FLINT_BITS - 6))) { flint_throw(FLINT_ERROR, "bernoulli_bound_2exp_si: n too large\n"); } l = (lo >> LOG_PREC) + 1; l += shift * u; /* log_2(2*pi*e) > 131 / 32 */ return l + 2 - (131 * n) / 32; } } flint-3.1.3/src/bernoulli/cache_compute.c000066400000000000000000000031771461254215100203700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "bernoulli.h" FLINT_TLS_PREFIX slong bernoulli_cache_num = 0; FLINT_TLS_PREFIX fmpq * bernoulli_cache = NULL; void bernoulli_cleanup(void) { slong i; for (i = 0; i < bernoulli_cache_num; i++) fmpq_clear(bernoulli_cache + i); flint_free(bernoulli_cache); bernoulli_cache = NULL; bernoulli_cache_num = 0; } void bernoulli_cache_compute(slong n) { slong old_num = bernoulli_cache_num; if (old_num < n) { slong i, new_num; if (old_num == 0) { flint_register_cleanup_function(bernoulli_cleanup); } if (n <= 128) new_num = FLINT_MAX(old_num + 32, n); else new_num = FLINT_MAX(old_num + 128, n); bernoulli_cache = flint_realloc(bernoulli_cache, new_num * sizeof(fmpq)); for (i = old_num; i < new_num; i++) fmpq_init(bernoulli_cache + i); if (new_num <= 128) { /* todo: use recursion, but only compute new entries */ arith_bernoulli_number_vec(bernoulli_cache, new_num); } else { bernoulli_fmpq_vec_no_cache(bernoulli_cache + old_num, old_num, new_num - old_num); } bernoulli_cache_num = new_num; } } flint-3.1.3/src/bernoulli/fmpq_ui.c000066400000000000000000000016451461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "bernoulli.h" void _bernoulli_fmpq_ui(fmpz_t num, fmpz_t den, ulong n) { if (n < (ulong) bernoulli_cache_num) { fmpz_set(num, fmpq_numref(bernoulli_cache + n)); fmpz_set(den, fmpq_denref(bernoulli_cache + n)); } else if (n < 18000 || n % 2 == 1) { _bernoulli_fmpq_ui_zeta(num, den, n); } else { _bernoulli_fmpq_ui_multi_mod(num, den, n, -1.0); } } void bernoulli_fmpq_ui(fmpq_t b, ulong n) { _bernoulli_fmpq_ui(fmpq_numref(b), fmpq_denref(b), n); } flint-3.1.3/src/bernoulli/fmpq_ui_multi_mod.c000066400000000000000000000145331461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2021, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "ulong_extras.h" #include "bernoulli.h" #include "arb.h" #define TIMING 0 #define DEBUG 0 typedef struct { fmpz r; fmpz m; } crt_res_t; typedef struct { mp_srcptr residues; mp_srcptr primes; } crt_args_t; static void crt_init(crt_res_t * x, crt_args_t * args) { fmpz_init(&x->r); fmpz_init(&x->m); } static void crt_clear(crt_res_t * x, crt_args_t * args) { fmpz_clear(&x->r); fmpz_clear(&x->m); } static void _fmpz_crt_combine(fmpz_t r1r2, fmpz_t m1m2, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2) { fmpz_invmod(m1m2, m1, m2); fmpz_mul(m1m2, m1m2, m1); fmpz_sub(r1r2, r2, r1); fmpz_mul(r1r2, r1r2, m1m2); fmpz_add(r1r2, r1r2, r1); fmpz_mul(m1m2, m1, m2); fmpz_mod(r1r2, r1r2, m1m2); } static void crt_combine(crt_res_t * res, crt_res_t * left, crt_res_t * right, crt_args_t * args) { _fmpz_crt_combine(&res->r, &res->m, &left->r, &left->m, &right->r, &right->m); } static void crt_basecase(crt_res_t * res, slong a, slong b, crt_args_t * args) { if (b - a == 0) { fmpz_zero(&res->r); fmpz_one(&res->m); } else if (b - a == 1) { fmpz_set_ui(&res->r, args->residues[a]); fmpz_set_ui(&res->m, args->primes[a]); } else { crt_res_t left, right; slong m = a + (b - a) / 2; crt_init(&left, args); crt_init(&right, args); crt_basecase(&left, a, m, args); crt_basecase(&right, m, b, args); crt_combine(res, &left, &right, args); crt_clear(&left, args); crt_clear(&right, args); } } /* todo: optimize basecase and move to flint */ void _arb_tree_crt(fmpz_t r, fmpz_t m, mp_srcptr residues, mp_srcptr primes, slong len) { crt_res_t res; crt_args_t args; res.r = *r; res.m = *m; args.residues = residues; args.primes = primes; flint_parallel_binary_splitting(&res, (bsplit_basecase_func_t) crt_basecase, (bsplit_merge_func_t) crt_combine, sizeof(crt_res_t), (bsplit_init_func_t) crt_init, (bsplit_clear_func_t) crt_clear, &args, 0, len, 20, -1, 0); *r = res.r; *m = res.m; return; } typedef struct { ulong n; mp_ptr primes; mp_ptr residues; } mod_p_param_t; static void mod_p_worker(slong i, void * param) { mod_p_param_t * p = (mod_p_param_t *) param; p->residues[i] = bernoulli_mod_p_harvey(p->n, p->primes[i]); } void _bernoulli_fmpq_ui_multi_mod(fmpz_t num, fmpz_t den, ulong n, double alpha) { n_primes_t prime_iter; slong i, bits, mod_bits, zeta_bits, num_primes; ulong p; mp_ptr primes, residues; mag_t primes_product; fmpz_t M; #if TIMING double t1, t2; #endif if (n < 10 || n % 2 != 0) { _bernoulli_fmpq_ui_zeta(num, den, n); return; } if (alpha < 0) { if (n < 18000) alpha = 0.0; else if (n < 60000) alpha = 0.005 + 3.6e-6 * n; else alpha = FLINT_MIN(0.18 + 0.5e-6 * n, 0.28); } #if TIMING t1 = clock(); #endif arith_bernoulli_number_denom(den, n); bits = arith_bernoulli_number_size(n) + fmpz_bits(den) + 2; mod_bits = bits * alpha; zeta_bits = bits - mod_bits; num_primes = 0; mag_init(primes_product); mag_one(primes_product); n_primes_init(prime_iter); p = 5; n_primes_jump_after(prime_iter, 5); for ( ; mag_cmp_2exp_si(primes_product, mod_bits) < 0; p = n_primes_next(prime_iter)) { if (n % (p - 1) != 0) { mag_mul_ui_lower(primes_product, primes_product, p); num_primes++; } } #if DEBUG flint_printf("\nn = %lu, bits = %lu, num_primes = %ld\n", n, bits, num_primes); #endif primes = flint_malloc(sizeof(mp_limb_t) * num_primes); residues = flint_malloc(sizeof(mp_limb_t) * num_primes); p = 5; n_primes_jump_after(prime_iter, 5); for (i = 0; i < num_primes; p = n_primes_next(prime_iter)) { if (n % (p - 1) != 0) { primes[i] = p; i++; } } n_primes_clear(prime_iter); #if TIMING t2 = clock(); flint_printf("init time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); flint_printf("num_primes = %ld\n", num_primes); #endif { mod_p_param_t param; param.n = n; param.primes = primes; param.residues = residues; flint_parallel_do(mod_p_worker, ¶m, num_primes, 0, FLINT_PARALLEL_STRIDED /* | FLINT_PARALLEL_VERBOSE */); } #if TIMING t2 = clock(); flint_printf("mod time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); flint_printf("start CRT\n"); t1 = clock(); #endif fmpz_init(M); _arb_tree_crt(num, M, residues, primes, num_primes); fmpz_mul(num, num, den); fmpz_mod(num, num, M); if (n % 4 == 0) { fmpz_sub(num, M, num); fmpz_neg(num, num); } #if TIMING flint_printf("end CRT\n"); t2 = clock(); flint_printf("CRT time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); t1 = clock(); #endif if (zeta_bits > 0) { slong prec; arb_t b; fmpz_t t; arb_init(b); fmpz_init(t); for (prec = zeta_bits + 10; ; prec += 32) { arb_bernoulli_ui_zeta(b, n, prec); arb_mul_fmpz(b, b, den, prec); arb_sub_fmpz(b, b, num, prec); arb_div_fmpz(b, b, M, prec); if (arb_get_unique_fmpz(t, b)) { fmpz_addmul(num, t, M); break; } flint_printf("bernoulli: n = %wu, bits = %wd, mod = %wd, zeta = %wd: get_unique_fmpz failed!\n", n, bits, mod_bits, zeta_bits); } arb_clear(b); fmpz_clear(t); } #if TIMING flint_printf("end zeta\n"); t2 = clock(); flint_printf("zeta time = %f\n", (t2 - t1) / (double) CLOCKS_PER_SEC); #endif flint_free(primes); flint_free(residues); fmpz_clear(M); mag_clear(primes_product); } flint-3.1.3/src/bernoulli/fmpq_ui_zeta.c000066400000000000000000000021701461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bernoulli.h" #include "arb.h" void _bernoulli_fmpq_ui_zeta(fmpz_t num, fmpz_t den, ulong n) { slong prec; arb_t t; arith_bernoulli_number_denom(den, n); if (n % 2) { fmpz_set_si(num, -(n == 1)); return; } if (n < BERNOULLI_SMALL_NUMER_LIMIT) { fmpz_set_si(num, _bernoulli_numer_small[n / 2]); return; } arb_init(t); for (prec = arith_bernoulli_number_size(n) + fmpz_bits(den) + 2; ; prec += 20) { arb_bernoulli_ui_zeta(t, n, prec); arb_mul_fmpz(t, t, den, prec); if (arb_get_unique_fmpz(num, t)) break; flint_printf("warning: %wd insufficient precision for Bernoulli number %wu\n", prec, n); } arb_clear(t); } flint-3.1.3/src/bernoulli/fmpq_vec.c000066400000000000000000000044761461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpq.h" #include "bernoulli.h" static void bernoulli_vec_compute_one_thread(fmpq * res, slong a, slong b) { slong i; bernoulli_rev_t iter; if (b <= a) return; /* Even indices */ i = b - 1; i -= (i % 2); bernoulli_rev_init(iter, i); for ( ; i >= a; i -= 2) bernoulli_rev_next(fmpq_numref(res + i - a), fmpq_denref(res + i - a), iter); bernoulli_rev_clear(iter); /* Odd indices */ for (i = b - 1 - (b % 2); i >= a; i -= 2) { if (i == 1) fmpq_set_si(res + i - a, -1, 2); else fmpq_zero(res + i - a); } } typedef struct { fmpq * res; slong a; slong b; slong block_size; slong num_blocks; } work_chunk_t; static void worker(slong i, void * _work) { work_chunk_t work = *((work_chunk_t *) _work); slong a, b; /* reverse strided scheduling */ i = work.num_blocks - 1 - i; a = work.a + i * work.block_size; b = FLINT_MIN(a + work.block_size, work.b); bernoulli_vec_compute_one_thread(work.res + a - work.a, a, b); } void bernoulli_fmpq_vec_no_cache(fmpq * res, ulong a, slong num) { if (a > (UWORD(1) << 31) || num > 1000000000) { flint_throw(FLINT_ERROR, "bernoulli_fmpq_vec_no_cache: excessive input\n"); } if (a == 0 && num <= 128) { arith_bernoulli_number_vec(res, num); return; } if (num < 200 || flint_get_num_threads() == 1) { bernoulli_vec_compute_one_thread(res, a, a + num); } else { slong num_blocks, block_size; work_chunk_t work; block_size = FLINT_MAX((a + num) / 32, 128); num_blocks = (num + block_size - 1) / block_size; work.res = res; work.a = a; work.b = a + num; work.block_size = block_size; work.num_blocks = num_blocks; flint_parallel_do(worker, &work, num_blocks, -1, FLINT_PARALLEL_STRIDED); } } flint-3.1.3/src/bernoulli/mod_p_harvey.c000066400000000000000000000624331461254215100202450ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, David Harvey Copyright (C) 2021 Fredrik Johansson This file has been adapted from the BSD-licensed bernmm package by David Harvey (see original copyright text below). Changes in the Arb version: * Use FLINT functions instead of NTL functions. (Some helper functions have been added -- these should probably be moved to FLINT.) * C instead of C++; some renaming and reformatting for better consistency with FLINT/Arb coding conventions. Important note on performance: * The modular arithmetic in FLINT is quite a bit slower than NTL since it is designed to support full 64-bit moduli which we don't need here. This mainly affects bernoulli_sum_powg and bernsum_pow2, which fortunately don't get called often for multimodular computation. However, we'd want to re-optimize these in case they find some other use. */ /* =============================================================================== bernmm: an implementation of the algorithm described in "A multimodular algorithm for computing Bernoulli numbers", by David Harvey, 2008. version 1.1 Copyright (C) 2008, 2009, David Harvey All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================== */ #include "ulong_extras.h" #include "bernoulli.h" #ifdef __GNUC__ # define memset __builtin_memset #else # include #endif #define DEBUG 0 #define TIMING 1 /****************************************************************************** Computing the main sum (general case) ******************************************************************************/ /* todo: this should be a function in ulong_extras */ ulong _bernoulli_n_muldivrem_precomp(ulong * q, ulong a, ulong b, ulong n, double bnpre) { ulong qq, r; qq = (double) a * bnpre; r = a * b - qq * n; if ((slong) r < 0) { qq--; r += n; } if (r >= n) { qq++; r -= n; } *q = qq; return r; } /* Returns (1 - g^k) B_k / 2k mod p. PRECONDITIONS: 5 <= p < 2^FLINT_D_BITS, p prime 2 <= k <= p-3, k even pinv = n_preinvert_limb(p) g = a multiplicative generator of GF(p), in [0, p) */ static ulong bernoulli_sum_powg(ulong p, ulong pinv, ulong k, ulong g) { ulong half_gm1, sum, g_to_km1, g_to_jm1, g_to_km1_to_j, q, h; slong j; double g_pinv; g_pinv = (double) g / (double) p; half_gm1 = (g + ((g & 1) ? 0 : p) - 1) / 2; /* (g-1)/2 mod p */ g_to_km1 = n_powmod2_preinv(g, k-1, p, pinv); g_to_jm1 = 1; g_to_km1_to_j = g_to_km1; sum = 0; for (j = 1; j <= (p - 1) / 2; j++) { g_to_jm1 = _bernoulli_n_muldivrem_precomp(&q, g_to_jm1, g, p, g_pinv); h = n_submod(q, half_gm1, p); sum = n_submod(sum, n_mulmod2_preinv(h, g_to_km1_to_j, p, pinv), p); g_to_km1_to_j = n_mulmod2_preinv(g_to_km1_to_j, g_to_km1, p, pinv); } return sum; } /****************************************************************************** Computing the main sum (c = 1/2 case) ******************************************************************************/ /* The Expander class stores precomputed information for a fixed integer p, that subsequently permits fast computation of the binary expansion of s/p for any 0 < s < p. The constructor takes p and max_words as input. Must have 1 <= max_words <= MAX_INV. It computes an approximation to 1/p. The function expand(mp_ptr res, long s, long n) computes n limbs of s/p. Must have 0 < s < p and 1 <= n <= max_words. The output is written to res. The first word of output is junk. The next n words are the digits of s/p, from least to most significant. The buffer must be at least n+2 words long (even though the first and last words are never used for output). */ #define MAX_INV 256 typedef struct { /* Approximation to 1/p. We store (max_words + 1) limbs. */ mp_limb_t pinv[MAX_INV + 2]; mp_limb_t p; int max_words; } expander_t; static void expander_init(expander_t * this, ulong p, int max_words) { mp_limb_t one; FLINT_ASSERT(max_words >= 1); FLINT_ASSERT(max_words <= MAX_INV); this->max_words = max_words; this->p = p; one = 1; mpn_divrem_1(this->pinv, max_words + 1, &one, 1, p); } static void expander_expand(mp_ptr res, expander_t * this, ulong s, ulong n) { slong i; FLINT_ASSERT(s > 0 && s < this->p); FLINT_ASSERT(n >= 1); FLINT_ASSERT(n <= this->max_words); if (s == 1) { /* already have 1/p; just copy it */ for (i = 1; i <= n; i++) res[i] = this->pinv[this->max_words - n + i]; } else { mpn_mul_1(res, this->pinv + this->max_words - n, n + 1, (mp_limb_t) s); /* If the first output limb is really close to 0xFFFF..., then there's a possibility of overflow, so fall back on doing division directly. This should happen extremely rarely --- essentially never on a 64-bit system, and very occasionally on a 32-bit system. */ if (res[0] > -((mp_limb_t) s)) { mp_limb_t ss = s; mpn_divrem_1(res, n + 1, &ss, 1, this->p); } } } /* Returns (2^(-k) - 1) 2 B_k / k mod p. (Note: this is useless if 2^k = 1 mod p.) PRECONDITIONS: 5 <= p, p prime 2 <= k <= p-3, k even pinv = n_preinvert_limb(p) g = a multiplicative generator of GF(p), in [0, p) n = multiplicative n_multiplicative_order of 2 in GF(p) */ #define TABLE_LG_SIZE 8 #define TABLE_SIZE (WORD(1) << TABLE_LG_SIZE) #define TABLE_MASK (TABLE_SIZE - 1) #define NUM_TABLES (FLINT_BITS / TABLE_LG_SIZE) #if FLINT_BITS % TABLE_LG_SIZE != 0 #error Number of bits in a ulong must be divisible by TABLE_LG_SIZE #endif ulong bernsum_pow2(ulong p, ulong pinv, ulong k, ulong g, ulong n) { slong i, m; ulong g_to_km1, two_to_km1, B_to_km1, s_jump; ulong tables[NUM_TABLES][TABLE_SIZE]; ulong g_to_km1_to_i; ulong g_to_i; ulong sum; expander_t expander; slong h; ulong x; ulong weights[TABLE_SIZE]; ulong x_jump; /* In the main summation loop we accumulate data into the _tables_ array; tables[y][z] contributes to the final answer with a weight of sum(-(-1)^z[t] * (2^(k-1))^(FLINT_BITS - 1 - y * TABLE_LG_SIZE - t) : 0 <= t < TABLE_LG_SIZE), where z[t] denotes the t-th binary digit of z (LSB is t = 0). The memory footprint for _tables_ is 4KB on a 32-bit machine, or 16KB on a 64-bit machine, so should fit easily into L1 cache. */ memset(tables, 0, sizeof(ulong) * NUM_TABLES * TABLE_SIZE); m = (p-1) / n; /* take advantage of symmetry (n' and m' from the paper) */ if (n & 1) m >>= 1; else n >>= 1; /* g^(k-1) */ g_to_km1 = n_powmod2_preinv(g, k - 1, p, pinv); /* 2^(k-1) */ two_to_km1 = n_powmod2_preinv(2, k - 1, p, pinv); /* B^(k-1), where B = 2^FLINT_BITS */ B_to_km1 = n_powmod2_preinv(two_to_km1, FLINT_BITS, p, pinv); /* B^(MAX_INV) */ s_jump = n_powmod2_preinv(2, MAX_INV * FLINT_BITS, p, pinv); /* todo - help speed up modmuls mulmod_precon_t g_pinv = PrepMulModPrecon(g, p, pinv); mulmod_precon_t g_to_km1_pinv = PrepMulModPrecon(g_to_km1, p, pinv); mulmod_precon_t two_to_km1_pinv = PrepMulModPrecon(two_to_km1, p, pinv); mulmod_precon_t B_to_km1_pinv = PrepMulModPrecon(B_to_km1, p, pinv); mulmod_precon_t s_jump_pinv = PrepMulModPrecon(s_jump, p, pinv); */ g_to_km1_to_i = 1; g_to_i = 1; sum = 0; /* Precompute some of the binary expansion of 1/p; at most MAX_INV words, or possibly less if n is sufficiently small */ expander_init(&expander, p, (n >= MAX_INV * FLINT_BITS) ? MAX_INV : ((n - 1) / FLINT_BITS + 1)); /* =========== phase 1: main summation loop */ /* loop over outer sum */ for (i = 0; i < m; i++) { ulong s, x, y; slong nn; /* s keeps track of g^i*2^j mod p */ s = g_to_i; /* x keeps track of (g^i*2^j)^(k-1) mod p */ x = g_to_km1_to_i; /* loop over inner sum; break it up into chunks of length at most */ /* MAX_INV * FLINT_BITS. If n is large, this allows us to do most of */ /* the work with mpn_mul_1 instead of mpn_divrem_1, and also improves */ /* memory locality. */ for (nn = n; nn > 0; nn -= MAX_INV * FLINT_BITS) { mp_limb_t s_over_p[MAX_INV + 2]; slong bits, words; mp_ptr next; if (nn >= MAX_INV * FLINT_BITS) { /* do one chunk of length exactly MAX_INV * FLINT_BITS */ bits = MAX_INV * FLINT_BITS; words = MAX_INV; } else { /* last chunk of length less than MAX_INV * FLINT_BITS */ bits = nn; words = (nn - 1) / FLINT_BITS + 1; } /* compute some bits of the binary expansion of s/p */ expander_expand(s_over_p, &expander, s, words); next = s_over_p + words; /* loop over whole words */ for (; bits >= FLINT_BITS; bits -= FLINT_BITS, next--) { mp_limb_t y; #if NUM_TABLES != 8 && NUM_TABLES != 4 mp_ptr target; #else mp_ptr target0, target1, target2, target3, target4, target5, target6, target7; #endif y = *next; #if NUM_TABLES != 8 && NUM_TABLES != 4 /* generic version */ for (h = 0; h < NUM_TABLES; h++) { target = &(tables[h][y & TABLE_MASK]); *target = n_submod(*target, x, p); y >>= TABLE_LG_SIZE; } #else /* unrolled versions for 32-bit/64-bit machines */ target0 = &(tables[0][y & TABLE_MASK]); *target0 = n_submod(*target0, x, p); target1 = &(tables[1][(y >> TABLE_LG_SIZE) & TABLE_MASK]); *target1 = n_submod(*target1, x, p); target2 = &(tables[2][(y >> (2*TABLE_LG_SIZE)) & TABLE_MASK]); *target2 = n_submod(*target2, x, p); target3 = &(tables[3][(y >> (3*TABLE_LG_SIZE)) & TABLE_MASK]); *target3 = n_submod(*target3, x, p); #if NUM_TABLES == 8 target4 = &(tables[4][(y >> (4*TABLE_LG_SIZE)) & TABLE_MASK]); *target4 = n_submod(*target4, x, p); target5 = &(tables[5][(y >> (5*TABLE_LG_SIZE)) & TABLE_MASK]); *target5 = n_submod(*target5, x, p); target6 = &(tables[6][(y >> (6*TABLE_LG_SIZE)) & TABLE_MASK]); *target6 = n_submod(*target6, x, p); target7 = &(tables[7][(y >> (7*TABLE_LG_SIZE)) & TABLE_MASK]); *target7 = n_submod(*target7, x, p); #endif #endif x = n_mulmod2_preinv(x, B_to_km1, p, pinv); /* todo: precond */ } /* loop over remaining bits in the last word */ y = *next; for (; bits > 0; bits--) { if (y & (UWORD(1) << (FLINT_BITS - 1))) sum = n_submod(sum, x, p); else sum = n_addmod(sum, x, p); x = n_mulmod2_preinv(x, two_to_km1, p, pinv); /* todo: precond */ y <<= 1; } s = n_mulmod2_preinv(s, s_jump, p, pinv); /* todo: precond */ } /* update g^i and (g^(k-1))^i */ g_to_i = n_mulmod2_preinv(g_to_i, g, p, pinv); g_to_km1_to_i = n_mulmod2_preinv(g_to_km1_to_i, g_to_km1, p, pinv); } #if DEBUG { slong i, j; for (i = 0; i < NUM_TABLES; i++) { printf("tab[%lu] = ", i); for (j = 0; j < TABLE_SIZE; j++) printf("%lu ", tables[i][j]); printf("\n"); } } #endif /* =========== phase 2: consolidate table data */ /* compute weights[z] = sum((-1)^z[t] * (2^(k-1))^(TABLE_LG_SIZE - 1 - t) : 0 <= t < TABLE_LG_SIZE). */ weights[0] = 0; for (h = 0, x = 1; h < TABLE_LG_SIZE; h++, x = n_mulmod2_preinv(x, two_to_km1, p, pinv)) { for (i = (WORD(1) << h) - 1; i >= 0; i--) { weights[2*i+1] = n_submod(weights[i], x, p); weights[2*i] = n_addmod(weights[i], x, p); } } /* combine table data with weights */ x_jump = n_powmod2_preinv(two_to_km1, TABLE_LG_SIZE, p, pinv); for (h = NUM_TABLES - 1, x = 1; h >= 0; h--) { for (i = 0; i < TABLE_SIZE; i++) { ulong y = n_mulmod2_preinv(tables[h][i], weights[i], p, pinv); y = n_mulmod2_preinv(y, x, p, pinv); sum = n_submod(sum, y, p); } x = n_mulmod2_preinv(x_jump, x, p, pinv); } return sum; } /****************************************************************************** Computing the main sum (c = 1/2 case, with REDC arithmetic) Throughout this section F denotes 2^(FLINT_BITS / 2). ******************************************************************************/ /* Returns x/F mod n. Output is in [0, 2n), i.e. *not* reduced completely into [0, n). PRECONDITIONS: 3 <= n < F, n odd 0 <= x < nF (if n < F/2) 0 <= x < nF/2 (if n > F/2) ninv2 = -1/n mod F */ #define LOW_MASK ((UWORD(1) << (FLINT_BITS / 2)) - 1) static inline ulong RedcFast(ulong x, ulong n, ulong ninv2) { ulong y = (x * ninv2) & LOW_MASK; ulong z = x + (n * y); return z >> (FLINT_BITS / 2); } /* Same as RedcFast(), but reduces output into [0, n). */ static inline ulong Redc(ulong x, ulong n, ulong ninv2) { ulong y = RedcFast(x, n, ninv2); if (y >= n) y -= n; return y; } /* Computes -1/n mod F, in [0, F). PRECONDITIONS: 3 <= n < F, n odd */ static ulong PrepRedc(ulong n) { ulong bits; ulong ninv2 = -n; /* already correct mod 8 */ /* Newton's method for 2-adic inversion */ for (bits = 3; bits < FLINT_BITS/2; bits *= 2) ninv2 = 2*ninv2 + n * ninv2 * ninv2; return ninv2 & LOW_MASK; } /* Same as bernsum_pow2(), but uses REDC arithmetic, and various delayed reduction strategies. PRECONDITIONS: Same as bernsum_pow2(), and in addition: p < 2^(FLINT_BITS/2 - 1) (See bernsum_pow2() for code comments; we only add comments here where something is different from bernsum_pow2()) */ ulong bernsum_pow2_redc(ulong p, ulong pinv, ulong k, ulong g, ulong n) { ulong pinv2 = PrepRedc(p); ulong F = (UWORD(1) << (FLINT_BITS/2)) % p; ulong x; slong h, i, m; ulong weights[TABLE_SIZE]; ulong x_jump; ulong x_jump_redc; ulong g_to_km1; ulong two_to_km1; ulong B_to_km1; ulong s_jump; ulong g_redc; ulong g_to_km1_redc; ulong two_to_km1_redc; ulong B_to_km1_redc; ulong s_jump_redc; ulong g_to_km1_to_i; ulong g_to_i; ulong sum; ulong tables[NUM_TABLES][TABLE_SIZE]; expander_t expander; memset(tables, 0, sizeof(ulong) * NUM_TABLES * TABLE_SIZE); m = (p-1) / n; if (n & 1) m >>= 1; else n >>= 1; g_to_km1 = n_powmod2_preinv(g, k-1, p, pinv); two_to_km1 = n_powmod2_preinv(2, k-1, p, pinv); B_to_km1 = n_powmod2_preinv(two_to_km1, FLINT_BITS, p, pinv); s_jump = n_powmod2_preinv(2, MAX_INV * FLINT_BITS, p, pinv); g_redc = n_mulmod2_preinv(g, F, p, pinv); g_to_km1_redc = n_mulmod2_preinv(g_to_km1, F, p, pinv); two_to_km1_redc = n_mulmod2_preinv(two_to_km1, F, p, pinv); B_to_km1_redc = n_mulmod2_preinv(B_to_km1, F, p, pinv); s_jump_redc = n_mulmod2_preinv(s_jump, F, p, pinv); g_to_km1_to_i = 1; /* always in [0, 2p) */ g_to_i = 1; /* always in [0, 2p) */ sum = 0; #if DEBUG printf("%lu %lu %lu %lu %lu %lu %lu %lu %lu\n", F, g_to_km1, two_to_km1, B_to_km1, s_jump, g_redc, g_to_km1_redc, B_to_km1_redc, s_jump_redc); #endif expander_init(&expander, p, (n >= MAX_INV * FLINT_BITS) ? MAX_INV : ((n - 1) / FLINT_BITS + 1)); /* =========== phase 1: main summation loop */ for (i = 0; i < m; i++) { ulong s, x, y; slong nn, bits, words; mp_ptr next; s = g_to_i; /* always in [0, p) */ if (s >= p) s -= p; x = g_to_km1_to_i; /* always in [0, 2p) */ for (nn = n; nn > 0; nn -= MAX_INV * FLINT_BITS) { ulong s_over_p[MAX_INV + 2]; if (nn >= MAX_INV * FLINT_BITS) { bits = MAX_INV * FLINT_BITS; words = MAX_INV; } else { bits = nn; words = (nn - 1) / FLINT_BITS + 1; } expander_expand(s_over_p, &expander, s, words); next = s_over_p + words; for (; bits >= FLINT_BITS; bits -= FLINT_BITS, next--) { y = *next; #if DEBUG printf("i = %lu nn = %lu words = %lu bits = %lu y = %lu\n", i, nn, words, bits, y); #endif /* note: we add the values into tables *without* reduction mod p */ #if NUM_TABLES != 8 && NUM_TABLES != 4 /* generic version */ for (h = 0; h < NUM_TABLES; h++) { tables[h][y & TABLE_MASK] += x; y >>= TABLE_LG_SIZE; } #else /* unrolled versions for 32-bit/64-bit machines */ tables[0][ y & TABLE_MASK] += x; tables[1][(y >> TABLE_LG_SIZE ) & TABLE_MASK] += x; tables[2][(y >> (2*TABLE_LG_SIZE)) & TABLE_MASK] += x; tables[3][(y >> (3*TABLE_LG_SIZE)) & TABLE_MASK] += x; #if NUM_TABLES == 8 tables[4][(y >> (4*TABLE_LG_SIZE)) & TABLE_MASK] += x; tables[5][(y >> (5*TABLE_LG_SIZE)) & TABLE_MASK] += x; tables[6][(y >> (6*TABLE_LG_SIZE)) & TABLE_MASK] += x; tables[7][(y >> (7*TABLE_LG_SIZE)) & TABLE_MASK] += x; #endif #endif x = RedcFast(x * B_to_km1_redc, p, pinv2); } /* bring x into [0, p) for next loop */ if (x >= p) x -= p; y = *next; for (; bits > 0; bits--) { if (y & (UWORD(1) << (FLINT_BITS - 1))) sum = n_submod(sum, x, p); else sum = n_addmod(sum, x, p); x = Redc(x * two_to_km1_redc, p, pinv2); y <<= 1; } s = Redc(s * s_jump_redc, p, pinv2); } g_to_i = RedcFast(g_to_i * g_redc, p, pinv2); g_to_km1_to_i = RedcFast(g_to_km1_to_i * g_to_km1_redc, p, pinv2); } /* At this point, each table entry is at most p^2 (since x was always */ /* in [0, 2p), and the inner loop was called at most (p/2) / FLINT_BITS */ /* times, and 2p * p/2 / FLINT_BITS * TABLE_LG_SIZE <= p^2). */ #if DEBUG { slong i, j; for (i = 0; i < NUM_TABLES; i++) { printf("tab[%lu] = ", i); for (j = 0; j < TABLE_SIZE; j++) printf("%lu ", tables[i][j]); printf("\n"); } } #endif /* =========== phase 2: consolidate table data */ weights[0] = 0; /* we store the weights multiplied by a factor of 2^(3*FLINT_BITS/2) to */ /* compensate for the three rounds of REDC reduction in the loop below */ for (h = 0, x = n_powmod2_preinv(2, 3*FLINT_BITS/2, p, pinv); h < TABLE_LG_SIZE; h++, x = Redc(x * two_to_km1_redc, p, pinv2)) { for (i = (WORD(1) << h) - 1; i >= 0; i--) { weights[2*i+1] = n_submod(weights[i], x, p); weights[2*i] = n_addmod(weights[i], x, p); } } x_jump = n_powmod2_preinv(two_to_km1, TABLE_LG_SIZE, p, pinv); x_jump_redc = n_mulmod2_preinv(x_jump, F, p, pinv); for (h = NUM_TABLES - 1, x = 1; h >= 0; h--) { for (i = 0; i < TABLE_SIZE; i++) { ulong y; y = RedcFast(tables[h][i], p, pinv2); y = RedcFast(y * weights[i], p, pinv2); y = RedcFast(y * x, p, pinv2); sum += y; } x = Redc(x * x_jump_redc, p, pinv2); } return sum % p; } /****************************************************************************** Wrappers for bernsum_* ******************************************************************************/ /* Returns B_k/k mod p, in the range [0, p). PRECONDITIONS: 5 <= p < NTL_SP_BOUND, p prime 2 <= k <= p-3, k even pinv = PrepMulMod(p) Algorithm: uses bernoulli_sum_powg() to compute the main sum. */ ulong _bernoulli_mod_p_harvey_powg(ulong p, ulong pinv, ulong k) { ulong x, g, t, g_to_k; g = n_primitive_root_prime(p); /* compute main sum */ x = bernoulli_sum_powg(p, pinv, k, g); /* divide by (1 - g^k) and multiply by 2 */ g_to_k = n_powmod2_preinv(g, k, p, pinv); t = n_invmod(p + 1 - g_to_k, p); x = n_mulmod2_preinv(x, t, p, pinv); x = n_addmod(x, x, p); return x; } static ulong n_multiplicative_order(ulong x, ulong p, ulong pinv, n_factor_t * F) { ulong m, q, mm; slong i; /* in the loop below, m is always some multiple of the n_multiplicative_order of x */ m = p - 1; /* try to remove factors from m until we can't remove any more */ for (i = 0; i < F->num; i++) { q = F->p[i]; while (m % q == 0) { mm = m / q; if (n_powmod2_preinv(x, mm, p, pinv) != 1) break; m = mm; } } return m; } /* Returns B_k/k mod p, in the range [0, p). PRECONDITIONS: 5 <= p < NTL_SP_BOUND, p prime 2 <= k <= p-3, k even pinv = PrepMulMod(p) 2^k != 1 mod p Algorithm: uses bernsum_pow2() (or bernsum_pow2_redc() if p is small enough) to compute the main sum. */ ulong _bernoulli_mod_p_harvey_pow2(ulong p, ulong pinv, ulong k) { n_factor_t F; ulong g, n, x, t; n_factor_init(&F); n_factor(&F, p - 1, 1); g = n_primitive_root_prime_prefactor(p, &F); n = n_multiplicative_order(2, p, pinv, &F); #if DEBUG printf("g = %lu, n = %lu\n", g, n); #endif if (p < (UWORD(1) << (FLINT_BITS/2 - 1))) x = bernsum_pow2_redc(p, pinv, k, g, n); else x = bernsum_pow2(p, pinv, k, g, n); /* divide by 2*(2^(-k) - 1) */ t = n_submod(n_invmod(n_powmod2_preinv(2, k, p, pinv), p), 1, p); t = n_addmod(t, t, p); t = n_invmod(t, p); x = n_mulmod2_preinv(x, t, p, pinv); return x; } /* Returns B_k/k mod p, in the range [0, p). PRECONDITIONS: 5 <= p < NTL_SP_BOUND, p prime 2 <= k <= p-3, k even pinv = PrepMulMod(p) */ ulong _bernoulli_mod_p_harvey(ulong p, ulong pinv, ulong k) { if (n_powmod2_preinv(2, k, p, pinv) != 1) { /* 2^k != 1 mod p, so we use the faster version */ return _bernoulli_mod_p_harvey_pow2(p, pinv, k); } else { /* forced to use slower version */ return _bernoulli_mod_p_harvey_powg(p, pinv, k); } } /****************************************************************************** Main bernoulli_mod_p routine ******************************************************************************/ /* beware: opposite argument order to bernmm */ ulong bernoulli_mod_p_harvey(ulong k, ulong p) { ulong m, x, pinv; FLINT_ASSERT(k >= 0); FLINT_ASSERT(2 <= p && p < (UWORD(1) << FLINT_D_BITS)); if (k == 0) return 1; if (k == 1) { if (p == 2) return -1; return (p - 1) / 2; } if (k & 1) return 0; /* denominator of B_k is always divisible by 6 for k >= 2 */ if (p <= 3) return UWORD_MAX; /* use Kummer's congruence (k = m mod p-1 => B_k/k = B_m/m mod p) */ m = k % (p - 1); if (m == 0) return UWORD_MAX; pinv = n_preinvert_limb(p); x = _bernoulli_mod_p_harvey(p, pinv, m); /* = B_m/m mod p */ return n_mulmod2_preinv(x, k % p, p, pinv); } flint-3.1.3/src/bernoulli/rev_clear.c000066400000000000000000000013171461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "arb.h" #include "bernoulli.h" void bernoulli_rev_clear(bernoulli_rev_t iter) { if (iter->alloc != 0) { _fmpz_vec_clear(iter->powers, iter->alloc); fmpz_clear(iter->pow_error); arb_clear(iter->prefactor); arb_clear(iter->two_pi_squared); } } flint-3.1.3/src/bernoulli/rev_init.c000066400000000000000000000040551461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "arb.h" #include "bernoulli.h" void bernoulli_rev_init(bernoulli_rev_t iter, ulong nmax) { slong j; fmpz_t t; arb_t x; arf_t u; int round1, round2; slong wp; nmax -= (nmax % 2); iter->n = nmax; iter->alloc = 0; if (nmax < BERNOULLI_REV_MIN) return; iter->prec = wp = bernoulli_global_prec(nmax); iter->max_power = bernoulli_zeta_terms(nmax, iter->prec); iter->alloc = iter->max_power + 1; iter->powers = _fmpz_vec_init(iter->alloc); fmpz_init(iter->pow_error); arb_init(iter->prefactor); arb_init(iter->two_pi_squared); arb_init(x); fmpz_init(t); arf_init(u); /* precompute powers */ for (j = 3; j <= iter->max_power; j += 2) { arb_ui_pow_ui(x, j, nmax, bernoulli_power_prec(j, nmax, wp)); arb_inv(x, x, bernoulli_power_prec(j, nmax, wp)); round1 = arf_get_fmpz_fixed_si(t, arb_midref(x), -wp); fmpz_set(iter->powers + j, t); /* error: the radius, plus two roundings */ arf_set_mag(u, arb_radref(x)); round2 = arf_get_fmpz_fixed_si(t, u, -wp); fmpz_add_ui(t, t, (round1 != 0) + (round2 != 0)); if (fmpz_cmp(iter->pow_error, t) < 0) fmpz_set(iter->pow_error, t); } /* precompute (2pi)^2 and 2*(n!)/(2pi)^n */ arb_fac_ui(iter->prefactor, nmax, wp); arb_mul_2exp_si(iter->prefactor, iter->prefactor, 1); arb_const_pi(x, wp); arb_mul_2exp_si(x, x, 1); arb_mul(iter->two_pi_squared, x, x, wp); arb_pow_ui(x, iter->two_pi_squared, nmax / 2, wp); arb_div(iter->prefactor, iter->prefactor, x, wp); fmpz_clear(t); arb_clear(x); arf_clear(u); } flint-3.1.3/src/bernoulli/rev_next.c000066400000000000000000000107551461254215100174230ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "bernoulli.h" static inline void mag_ui_div(mag_t z, ulong c, const mag_t x) { mag_t t; mag_init(t); mag_set_ui(t, c); mag_div(z, t, x); mag_clear(t); } static const short small_denom[] = { 1, 6, 30, 42, 30, 66, 2730, 6, 510, 798, 330, 138, 2730, 6, 870, 14322 }; static const int small_numer[] = { 1, 1, -1, 1, -1, 5, -691, 7, -3617, 43867, -174611, 854513, -236364091, 8553103 }; static void _fmpq_bernoulli_small(fmpz_t p, fmpz_t q, ulong n) { if (n == 1) { fmpz_set_si(p, -1); fmpz_set_ui(q, 2); } else if (n % 2 == 1) { fmpz_zero(p); fmpz_one(q); } else { if (n == 28) fmpz_set_d(p, -23749461029.0); else if (n == 30) fmpz_set_d(p, 8615841276005.0); else fmpz_set_si(p, small_numer[n / 2]); fmpz_set_si(q, small_denom[n / 2]); } } void bernoulli_rev_next(fmpz_t numer, fmpz_t denom, bernoulli_rev_t iter) { ulong n; slong j, wp; fmpz_t sum; mag_t err; arb_t z, h; n = iter->n; wp = iter->prec; if (n < BERNOULLI_REV_MIN) { _fmpq_bernoulli_small(numer, denom, n); if (n != 0) iter->n -= 2; return; } fmpz_init(sum); mag_init(err); arb_init(z); arb_init(h); /* add all odd powers */ fmpz_zero(sum); for (j = iter->max_power; j >= 3; j -= 2) fmpz_add(sum, sum, iter->powers + j); arb_set_fmpz(z, sum); /* bound numerical error from the powers */ fmpz_mul_ui(sum, iter->pow_error, iter->max_power / 2); mag_set_fmpz(err, sum); mag_add(arb_radref(z), arb_radref(z), err); arb_mul_2exp_si(z, z, -wp); arb_add_ui(z, z, 1, wp); /* add truncation error: sum_{k > N} 1/k^n <= 1/N^(i-1) */ mag_set_ui_lower(err, iter->max_power); mag_pow_ui_lower(err, err, n - 1); mag_ui_div(err, 1, err); mag_add(arb_radref(z), arb_radref(z), err); /* convert zeta to Bernoulli number */ arb_div_2expm1_ui(h, z, n, wp); arb_add(z, z, h, wp); arb_mul(z, z, iter->prefactor, wp); arith_bernoulli_number_denom(denom, n); arb_mul_fmpz(z, z, denom, wp); if (n % 4 == 0) arb_neg(z, z); /* flint_printf("%wd: ", n); arb_printd(z, 5); flint_printf("\n"); */ if (!arb_get_unique_fmpz(numer, z)) { flint_printf("warning: insufficient precision for B_%wd\n", n); _bernoulli_fmpq_ui(numer, denom, n); } /* update prefactor */ if (n > 0) { arb_mul(iter->prefactor, iter->prefactor, iter->two_pi_squared, wp); arb_div_ui(iter->prefactor, iter->prefactor, n, wp); arb_div_ui(iter->prefactor, iter->prefactor, n - 1, wp); } /* update powers */ for (j = 3; j <= iter->max_power; j += 2) fmpz_mul2_uiui(iter->powers + j, iter->powers + j, j, j); /* bound error after update */ fmpz_mul2_uiui(iter->pow_error, iter->pow_error, iter->max_power, iter->max_power); /* readjust precision */ if (n % 64 == 0 && n > BERNOULLI_REV_MIN) { slong new_prec, new_max; new_prec = bernoulli_global_prec(n); new_max = bernoulli_zeta_terms(n, new_prec); if (new_prec < iter->prec && new_max <= iter->max_power) { /* change precision of the powers */ for (j = 3; j <= new_max; j += 2) fmpz_tdiv_q_2exp(iter->powers + j, iter->powers + j, iter->prec - new_prec); /* the error also changes precision */ fmpz_cdiv_q_2exp(iter->pow_error, iter->pow_error, iter->prec - new_prec); /* contribution of rounding error when changing the precision of the powers */ fmpz_add_ui(iter->pow_error, iter->pow_error, 1); /* speed improvement (could be skipped with better multiplication) */ arb_set_round(iter->two_pi_squared, iter->two_pi_squared, new_prec); iter->max_power = new_max; iter->prec = new_prec; } } iter->n -= 2; fmpz_clear(sum); mag_clear(err); arb_clear(z); arb_clear(h); } flint-3.1.3/src/bernoulli/test/000077500000000000000000000000001461254215100163745ustar00rootroot00000000000000flint-3.1.3/src/bernoulli/test/main.c000066400000000000000000000021271461254215100174660ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-bound_2exp_si.c" #include "t-fmpq_ui.c" #include "t-fmpq_ui_multi_mod.c" #include "t-fmpq_vec.c" #include "t-mod_p_harvey.c" #include "t-rev.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(bernoulli_bound_2exp_si), TEST_FUNCTION(bernoulli_fmpq_ui), TEST_FUNCTION(bernoulli_fmpq_ui_multi_mod), TEST_FUNCTION(bernoulli_fmpq_vec), TEST_FUNCTION(bernoulli_mod_p_harvey), TEST_FUNCTION(bernoulli_rev) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/bernoulli/test/t-bound_2exp_si.c000066400000000000000000000031771461254215100215510ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "arf.h" #include "bernoulli.h" double log2bern_approx(double n) { return 1 + ((n+0.5)*log(n) - n - (n-0.5)*log(2*3.14159265358979323)) * (1. / log(2)); } TEST_FUNCTION_START(bernoulli_bound_2exp_si, state) { slong i, bound; double a, b; fmpq_t q; arf_t t; fmpq_init(q); arf_init(t); for (i = 0; i < 1000; i++) { arith_bernoulli_number(q, i); bound = bernoulli_bound_2exp_si(i); arf_set_round_fmpz(t, fmpq_numref(q), 32, ARF_RND_UP); arf_div_fmpz(t, t, fmpq_denref(q), 32, ARF_RND_UP); if (arf_cmpabs_2exp_si(t, bound) > 0) { flint_printf("FAIL: %wd\n", i); arf_print(t); flint_printf("\n\n"); flint_printf("%wd\n", bound); flint_printf("\n\n"); flint_abort(); } } fmpq_clear(q); arf_clear(t); for (i = 100; i < 4000000; i += 1) { i += (i & 1); a = bernoulli_bound_2exp_si(i); b = log2bern_approx(i); if (a < b || a > 1.01 * b) { flint_printf("FAIL: %wd\n", i); flint_printf("%wd: %f %f %f\n", i, a, b, (float) a / b); flint_abort(); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/bernoulli/test/t-fmpq_ui.c000066400000000000000000000032501461254215100204410ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arf.h" #include "arith.h" #include "bernoulli.h" TEST_FUNCTION_START(bernoulli_fmpq_ui, state) { fmpz * num1; fmpz * den1; fmpz_t num2; fmpz_t den2; slong n, N; N = 4000 * FLINT_MIN(1.0, 0.1 * flint_test_multiplier()); num1 = _fmpz_vec_init(N); den1 = _fmpz_vec_init(N); fmpz_init(num2); fmpz_init(den2); _arith_bernoulli_number_vec_multi_mod(num1, den1, N); for (n = 0; n < N; n++) { _bernoulli_fmpq_ui(num2, den2, n); if (!fmpz_equal(num1 + n, num2)) { flint_printf("FAIL: n = %wd, numerator\n", n); flint_printf("vec: "); fmpz_print(num1 + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(num2); flint_printf("\n"); flint_abort(); } if (!fmpz_equal(den1 + n, den2)) { flint_printf("FAIL: n = %wd, denominator\n", n); flint_printf("vec: "); fmpz_print(den1 + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(den2); flint_printf("\n"); flint_abort(); } } _fmpz_vec_clear(num1, N); _fmpz_vec_clear(den1, N); fmpz_clear(num2); fmpz_clear(den2); TEST_FUNCTION_END(state); } flint-3.1.3/src/bernoulli/test/t-fmpq_ui_multi_mod.c000066400000000000000000000072211461254215100225140ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arf.h" #include "arith.h" #include "bernoulli.h" TEST_FUNCTION_START(bernoulli_fmpq_ui_multi_mod, state) { fmpz * num1; fmpz * den1; fmpz_t num2; fmpz_t den2; slong n, N; double alpha; N = 1500 * FLINT_MIN(1.0, 0.1 * flint_test_multiplier()); num1 = _fmpz_vec_init(N); den1 = _fmpz_vec_init(N); fmpz_init(num2); fmpz_init(den2); _arith_bernoulli_number_vec_multi_mod(num1, den1, N); for (n = 0; n < N; n++) { if (n_randint(state, 2)) alpha = -1.0; else alpha = n_randint(state, 11) / (double) 10; _bernoulli_fmpq_ui_multi_mod(num2, den2, n, alpha); if (!fmpz_equal(num1 + n, num2)) { flint_printf("FAIL: n = %wd, numerator\n", n); flint_printf("vec: "); fmpz_print(num1 + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(num2); flint_printf("\n"); flint_abort(); } if (!fmpz_equal(den1 + n, den2)) { flint_printf("FAIL: n = %wd, denominator\n", n); flint_printf("vec: "); fmpz_print(den1 + n); flint_printf("\n"); flint_printf("single: "); fmpz_print(den2); flint_printf("\n"); flint_abort(); } } { _bernoulli_fmpq_ui_multi_mod(num1, den1, 10000, 0.3); _bernoulli_fmpq_ui_multi_mod(num2, den2, 10000, 1.0); if (!fmpz_equal(num1, num2) || !fmpz_equal(den1, den2)) { flint_printf("FAIL: n = 10000\n", n); flint_printf("num1 "); fmpz_print(num1); flint_printf("\n"); flint_printf("num2 "); fmpz_print(num2); flint_printf("\n"); flint_printf("den1 "); fmpz_print(den1); flint_printf("\n"); flint_printf("den2 "); fmpz_print(den2); flint_printf("\n"); flint_abort(); } flint_set_num_threads(2); _bernoulli_fmpq_ui_multi_mod(num1, den1, 30000, -1.0); _bernoulli_fmpq_ui_multi_mod(num2, den2, 30000, 0.8); if (!fmpz_equal(num1, num2) || !fmpz_equal(den1, den2)) { flint_printf("FAIL: n = 30000\n", n); flint_printf("num1 "); fmpz_print(num1); flint_printf("\n"); flint_printf("num2 "); fmpz_print(num2); flint_printf("\n"); flint_printf("den1 "); fmpz_print(den1); flint_printf("\n"); flint_printf("den2 "); fmpz_print(den2); flint_printf("\n"); flint_abort(); } flint_set_num_threads(3); _bernoulli_fmpq_ui_multi_mod(num1, den1, 80000, -1.0); _bernoulli_fmpq_ui_multi_mod(num2, den2, 80000, 0.5); if (!fmpz_equal(num1, num2) || !fmpz_equal(den1, den2)) { flint_printf("FAIL: n = 80000\n", n); flint_printf("num1 "); fmpz_print(num1); flint_printf("\n"); flint_printf("num2 "); fmpz_print(num2); flint_printf("\n"); flint_printf("den1 "); fmpz_print(den1); flint_printf("\n"); flint_printf("den2 "); fmpz_print(den2); flint_printf("\n"); flint_abort(); } } _fmpz_vec_clear(num1, N); _fmpz_vec_clear(den1, N); fmpz_clear(num2); fmpz_clear(den2); TEST_FUNCTION_END(state); } flint-3.1.3/src/bernoulli/test/t-fmpq_vec.c000066400000000000000000000045031461254215100206030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpq.h" #include "fmpq_vec.h" #include "bernoulli.h" TEST_FUNCTION_START(bernoulli_fmpq_vec, state) { slong iter; slong n, bound; mp_limb_t p, pinv, m1, m2; nmod_poly_t A; bound = 1000 * FLINT_MIN(1.0, 0.1 * flint_test_multiplier()); p = n_nextprime(UWORD(1) << (FLINT_BITS - 1), 0); pinv = n_preinvert_limb(p); nmod_poly_init(A, p); nmod_poly_set_coeff_ui(A, 1, 1); nmod_poly_exp_series(A, A, bound); nmod_poly_shift_right(A, A, 1); nmod_poly_inv_series(A, A, bound); m1 = 1; for (n = 0; n < A->length; n++) { A->coeffs[n] = n_mulmod2_preinv(A->coeffs[n], m1, p, pinv); m1 = n_mulmod2_preinv(m1, n + 1, p, pinv); } for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { slong a, b, num; fmpq * res; slong i; b = n_randint(state, bound); a = n_randint(state, b + 1); num = b - a; flint_set_num_threads(1 + n_randint(state, 4)); res = _fmpq_vec_init(num); for (i = 0; i < num; i++) fmpq_randtest(res + i, state, 100); bernoulli_fmpq_vec_no_cache(res, a, num); for (i = 0; i < num; i++) { m1 = fmpz_fdiv_ui(fmpq_numref(res + i), p); m2 = fmpz_fdiv_ui(fmpq_denref(res + i), p); m2 = n_invmod(m2, p); m1 = n_mulmod2_preinv(m1, m2, p, pinv); m2 = nmod_poly_get_coeff_ui(A, a + i); if (m1 != m2) { flint_printf("FAIL:\n"); flint_printf("a = %wd, b = %wd, num = %wd, n = %wd\n", a, b, num, a + i); flint_printf("m1 = %wu mod %wu\n", m1, p); flint_printf("m2 = %wu mod %wu\n", m2, p); flint_abort(); } } _fmpq_vec_clear(res, num); } nmod_poly_clear(A); TEST_FUNCTION_END(state); } flint-3.1.3/src/bernoulli/test/t-mod_p_harvey.c000066400000000000000000000115401461254215100214560ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 David Harvey Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_vec.h" #include "fmpz_extras.h" #include "arith.h" #include "bernoulli.h" /* test this internal function which should really be in FLINT */ ulong _bernoulli_n_muldivrem_precomp(ulong * q, ulong a, ulong b, ulong n, double bnpre); ulong _bernoulli_mod_p_harvey_powg(ulong p, ulong pinv, ulong k); ulong _bernoulli_mod_p_harvey_pow2(ulong p, ulong pinv, ulong k); void test_bern_modp_pow2(ulong p, ulong k) { ulong x, y; ulong pinv = n_preinvert_limb(p); if (n_powmod2_preinv(2, k, p, pinv) == 1) return; x = _bernoulli_mod_p_harvey_powg(p, pinv, k); y = _bernoulli_mod_p_harvey_pow2(p, pinv, k); if (x != y) { flint_printf("FAIL\n"); flint_printf("p = %wu\n", p); flint_printf("k = %wu\n", k); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_abort(); } } TEST_FUNCTION_START(bernoulli_mod_p_harvey, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { ulong a, b, n, q1, r1, r2; mp_limb_t q2[2]; double bnpre; a = n_randtest_bits(state, FLINT_D_BITS); b = n_randtest_bits(state, FLINT_D_BITS); do { n = n_randtest_bits(state, FLINT_D_BITS); } while (n == 0); a = a % n; b = b % n; bnpre = (double) b / (double) n; r1 = _bernoulli_n_muldivrem_precomp(&q1, a, b, n, bnpre); umul_ppmm(q2[1], q2[0], a, b); r2 = mpn_divrem_1(q2, 0, q2, 2, n); if (q2[0] != q1 || r1 != r2) { flint_printf("FAIL\n"); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("n = %wu\n", n); flint_printf("q1 = %wu\n", q1); flint_printf("r1 = %wu\n", r1); flint_printf("q2 = %wu\n", q2); flint_printf("r2 = %wu\n", r2); flint_abort(); } } { slong n, N, iter; ulong x, y, z, p, pinv; fmpz * num; fmpz * den; N = 300; num = _fmpz_vec_init(N); den = _fmpz_vec_init(N); _arith_bernoulli_number_vec_recursive(num, den, N); for (n = 2; n < N; n += 2) { for (iter = 0; iter < 10 * 0.1 * flint_test_multiplier(); iter++) { if (n_randint(state, 100) == 0) { p = 1000003; } else { p = n + 2 + n_randint(state, 2 * N); p = n_nextprime(p, 1); } pinv = n_preinvert_limb(p); x = _bernoulli_mod_p_harvey_powg(p, pinv, n); y = fmpz_fdiv_ui(num + n, p); z = fmpz_fdiv_ui(den + n, p); if (y != n_mulmod2_preinv(z, n_mulmod2_preinv(x, n, p, pinv), p, pinv)) { flint_printf("FAIL\n"); flint_printf("n = %wu\n", n); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("z = %wu\n", z); flint_abort(); } } } _fmpz_vec_clear(num, N); _fmpz_vec_clear(den, N); } { ulong p, k; /* exhaustive comparison over some small p and k */ for (p = 5; p < 1000; p = n_nextprime(p, 1)) { for (k = 2; k <= p - 3; k += 2) test_bern_modp_pow2(p, k); } /* a few larger values of p */ for (p = n_nextprime(1000000, 1); p < 1000000 + 1000 * FLINT_MIN(10, 0.1 * flint_test_multiplier()); p = n_nextprime(p, 1)) { k = 2 * (n_randlimb(state) % ((p-3)/2)) + 2; test_bern_modp_pow2(p, k); } /* these are slow */ if (FLINT_BITS == 64 && 0.1 * flint_test_multiplier() >= 10) { test_bern_modp_pow2(2147483647, 10); test_bern_modp_pow2(2147483629, 10); test_bern_modp_pow2(2147483659, 10); } for (p = n_nextprime((1 << 15) - 1000, 1); p < (1 << 15); p = n_nextprime(p, 1)) { for (iter = 0; iter < 10 * 0.1 * flint_test_multiplier(); iter++) { test_bern_modp_pow2(p, 2 * (n_randlimb(state) % ((p - 3)/2)) + 2); } } } TEST_FUNCTION_END(state); } flint-3.1.3/src/bernoulli/test/t-rev.c000066400000000000000000000045001461254215100175740ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz_extras.h" #include "bernoulli.h" TEST_FUNCTION_START(bernoulli_rev, state) { slong nmax, n, bound, count; mp_limb_t p, pinv, m1, m2; nmod_poly_t A; bound = 100000 * FLINT_MIN(1.0, 0.1 * flint_test_multiplier()); p = n_nextprime(UWORD(1) << (FLINT_BITS - 1), 0); pinv = n_preinvert_limb(p); nmod_poly_init(A, p); nmod_poly_set_coeff_ui(A, 1, 1); nmod_poly_exp_series(A, A, bound); nmod_poly_shift_right(A, A, 1); nmod_poly_inv_series(A, A, bound); m1 = 1; for (n = 0; n < A->length; n++) { A->coeffs[n] = n_mulmod2_preinv(A->coeffs[n], m1, p, pinv); m1 = n_mulmod2_preinv(m1, n + 1, p, pinv); } for (nmax = 0; nmax < bound; nmax = 1.5 * nmax + 2) { fmpz_t numer, denom; bernoulli_rev_t iter; fmpz_init(numer); fmpz_init(denom); nmax += (nmax % 2); bernoulli_rev_init(iter, nmax); if (nmax < 8000) count = 4000; else count = 100; /* flint_printf("nmax = %wd, count = %wd\n", nmax, count); */ for (n = nmax; n >= 0 && count > 0; n -= 2, count--) { bernoulli_rev_next(numer, denom, iter); m1 = fmpz_fdiv_ui(numer, p); m2 = fmpz_fdiv_ui(denom, p); m2 = n_invmod(m2, p); m1 = n_mulmod2_preinv(m1, m2, p, pinv); m2 = nmod_poly_get_coeff_ui(A, n); if (m1 != m2) { flint_printf("FAIL:\n"); flint_printf("nmax = %wd, n = %wd\n", nmax, n); flint_printf("m1 = %wu mod %wu\n", m1, p); flint_printf("m2 = %wu mod %wu\n", m2, p); flint_abort(); } } bernoulli_rev_clear(iter); fmpz_clear(numer); fmpz_clear(denom); } nmod_poly_clear(A); TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat.h000066400000000000000000000066251461254215100154000ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef BOOL_MAT_H #define BOOL_MAT_H #ifdef BOOL_MAT_INLINES_C #define BOOL_MAT_INLINE #else #define BOOL_MAT_INLINE static inline #endif #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { int *entries; slong r; slong c; int **rows; } bool_mat_struct; typedef bool_mat_struct bool_mat_t[1]; #define bool_mat_nrows(mat) ((mat)->r) #define bool_mat_ncols(mat) ((mat)->c) BOOL_MAT_INLINE int bool_mat_get_entry(const bool_mat_t mat, slong i, slong j) { return mat->rows[i][j]; } BOOL_MAT_INLINE void bool_mat_set_entry(bool_mat_t mat, slong i, slong j, int value) { mat->rows[i][j] = value; } /* Memory management */ void bool_mat_init(bool_mat_t mat, slong r, slong c); void bool_mat_clear(bool_mat_t mat); BOOL_MAT_INLINE void bool_mat_swap(bool_mat_t mat1, bool_mat_t mat2) { FLINT_SWAP(bool_mat_struct, *mat1, *mat2); } /* Conversions */ void bool_mat_set(bool_mat_t dest, const bool_mat_t src); /* Random generation */ void bool_mat_randtest(bool_mat_t mat, flint_rand_t state); void bool_mat_randtest_diagonal(bool_mat_t mat, flint_rand_t state); void bool_mat_randtest_nilpotent(bool_mat_t mat, flint_rand_t state); /* I/O */ #ifdef FLINT_HAVE_FILE void bool_mat_fprint(FILE * file, const bool_mat_t mat); #endif void bool_mat_print(const bool_mat_t mat); /* Comparisons */ int bool_mat_equal(const bool_mat_t mat1, const bool_mat_t mat2); int bool_mat_any(const bool_mat_t mat); int bool_mat_all(const bool_mat_t mat); int bool_mat_is_diagonal(const bool_mat_t mat); int bool_mat_is_lower_triangular(const bool_mat_t mat); int bool_mat_is_transitive(const bool_mat_t mat); int bool_mat_is_nilpotent(const bool_mat_t mat); BOOL_MAT_INLINE int bool_mat_is_empty(const bool_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } BOOL_MAT_INLINE int bool_mat_is_square(const bool_mat_t mat) { return (mat->r == mat->c); } /* Special matrices */ void bool_mat_zero(bool_mat_t mat); void bool_mat_one(bool_mat_t mat); void bool_mat_directed_path(bool_mat_t mat); void bool_mat_directed_cycle(bool_mat_t mat); /* Transpose */ void bool_mat_transpose(bool_mat_t mat1, const bool_mat_t mat2); /* Arithmetic */ void bool_mat_complement(bool_mat_t mat1, const bool_mat_t mat2); void bool_mat_add(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2); void bool_mat_mul(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2); void bool_mat_mul_entrywise(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2); void bool_mat_pow_ui(bool_mat_t B, const bool_mat_t A, ulong exp); BOOL_MAT_INLINE void bool_mat_sqr(bool_mat_t B, const bool_mat_t A) { bool_mat_mul(B, A, A); } /* Special functions */ int bool_mat_trace(const bool_mat_t mat); slong bool_mat_nilpotency_degree(const bool_mat_t mat); void bool_mat_transitive_closure(bool_mat_t dest, const bool_mat_t src); slong bool_mat_get_strongly_connected_components(slong *partition, const bool_mat_t A); slong bool_mat_all_pairs_longest_walk(fmpz_mat_t B, const bool_mat_t A); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/bool_mat/000077500000000000000000000000001461254215100152165ustar00rootroot00000000000000flint-3.1.3/src/bool_mat/add.c000066400000000000000000000014421461254215100161130ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_add(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2) { slong i, j; if (bool_mat_is_empty(mat1)) return; for (i = 0; i < bool_mat_nrows(mat1); i++) for (j = 0; j < bool_mat_ncols(mat1); j++) bool_mat_set_entry(res, i, j, (bool_mat_get_entry(mat1, i, j) | bool_mat_get_entry(mat2, i, j))); } flint-3.1.3/src/bool_mat/all.c000066400000000000000000000012701461254215100161320ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" int bool_mat_all(const bool_mat_t mat) { slong i, j; if (bool_mat_is_empty(mat)) return 1; for (i = 0; i < bool_mat_nrows(mat); i++) for (j = 0; j < bool_mat_ncols(mat); j++) if (!bool_mat_get_entry(mat, i, j)) return 0; return 1; } flint-3.1.3/src/bool_mat/all_pairs_longest_walk.c000066400000000000000000000200331461254215100220770ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "bool_mat.h" /* * Condensation of a matrix. * This is the directed acyclic graph of strongly connected components. */ typedef struct { slong n; /* number of vertices in the original graph */ slong k; /* number of strongly connected components (sccs) */ bool_mat_t C; /* adjacency matrix of the sccs in the condensation */ slong *partition; /* maps the vertex index to the scc index */ } _condensation_struct; typedef _condensation_struct _condensation_t[1]; static void _condensation_init(_condensation_t c, const bool_mat_t A) { slong i, j, u, v; if (!bool_mat_is_square(A)) flint_throw(FLINT_ERROR, "_condensation_init: A must be square\n"); c->n = bool_mat_nrows(A); c->partition = flint_malloc(c->n * sizeof(slong)); c->k = bool_mat_get_strongly_connected_components(c->partition, A); /* * Compute the adjacency matrix of the condensation. * This should be strict lower triangular, so that visiting the * vertices in increasing order corresponds to a postorder traversal. */ bool_mat_init(c->C, c->k, c->k); bool_mat_zero(c->C); for (i = 0; i < c->n; i++) { for (j = 0; j < c->n; j++) { if (bool_mat_get_entry(A, i, j)) { u = c->partition[i]; v = c->partition[j]; if (u != v) { bool_mat_set_entry(c->C, u, v, 1); } } } } if (!bool_mat_is_lower_triangular(c->C) || bool_mat_trace(c->C)) flint_throw(FLINT_ERROR, "_condensation_init: unexpected matrix structure\n"); } static void _condensation_clear(_condensation_t c) { bool_mat_clear(c->C); flint_free(c->partition); } typedef struct { _condensation_t con; bool_mat_t T; /* transitive closure of condensation */ bool_mat_t P; /* is there a cycle in any component on a path from u to v */ fmpz_mat_t Q; /* longest path, if any, from u to v */ int *scc_has_cycle; } _connectivity_struct; typedef _connectivity_struct _connectivity_t[1]; static void _connectivity_clear(_connectivity_t c) { bool_mat_clear(c->T); bool_mat_clear(c->P); fmpz_mat_clear(c->Q); flint_free(c->scc_has_cycle); _condensation_clear(c->con); } static void _connectivity_init_scc_has_cycle(_connectivity_t c, const bool_mat_t A) { slong n, i, u; slong *scc_size; n = bool_mat_nrows(A); c->scc_has_cycle = flint_calloc(n, sizeof(int)); /* * If a vertex of the original graph has a loop, * then the strongly connected component to which it belongs has a cycle. */ for (i = 0; i < n; i++) { if (bool_mat_get_entry(A, i, i)) { u = c->con->partition[i]; c->scc_has_cycle[u] = 1; } } /* * If a strongly connected component contains more than one vertex, * then that component has a cycle. */ scc_size = flint_calloc(c->con->k, sizeof(slong)); for (i = 0; i < n; i++) { u = c->con->partition[i]; scc_size[u]++; } for (u = 0; u < c->con->k; u++) { if (scc_size[u] > 1) { c->scc_has_cycle[u] = 1; } } flint_free(scc_size); } static void _connectivity_init(_connectivity_t c, const bool_mat_t A) { slong u, v, w; slong k; slong curr, rest; /* compute the condensation */ _condensation_init(c->con, A); k = c->con->k; /* check whether each scc contains a cycle */ _connectivity_init_scc_has_cycle(c, A); /* compute the transitive closure of the condensation */ bool_mat_init(c->T, k, k); bool_mat_transitive_closure(c->T, c->con->C); /* * Is there a walk from u to v that passes through a cycle-containing scc? * Cycles in the components u and v themselves are not considered. * Remember that the condensation is a directed acyclic graph. */ bool_mat_init(c->P, k, k); bool_mat_zero(c->P); for (w = 0; w < k; w++) { if (c->scc_has_cycle[w]) { for (u = 0; u < k; u++) { for (v = 0; v < k; v++) { if (bool_mat_get_entry(c->T, u, w) && bool_mat_get_entry(c->T, w, v)) { bool_mat_set_entry(c->P, u, v, 1); } } } } } /* * What is the max length path from u to v in the condensation graph? * If u==v or if v is unreachable from u then let this be zero. * Remember that the condensation is a directed acyclic graph, * and that the components are indexed in a post-order traversal. */ fmpz_mat_init(c->Q, k, k); fmpz_mat_zero(c->Q); for (u = 0; u < k; u++) { for (w = 0; w < k; w++) { if (bool_mat_get_entry(c->con->C, u, w)) { curr = fmpz_get_si(fmpz_mat_entry(c->Q, u, w)); fmpz_set_si( fmpz_mat_entry(c->Q, u, w), FLINT_MAX(curr, 1)); for (v = 0; v < k; v++) { if (bool_mat_get_entry(c->T, w, v)) { rest = fmpz_get_si(fmpz_mat_entry(c->Q, w, v)); curr = fmpz_get_si(fmpz_mat_entry(c->Q, u, v)); fmpz_set_si( fmpz_mat_entry(c->Q, u, v), FLINT_MAX(curr, rest + 1)); } } } } } } static void _connectivity_entrywise_nilpotence_degree( fmpz_t N, _connectivity_t c, slong i, slong j) { slong u, v; u = c->con->partition[i]; v = c->con->partition[j]; if (u == v) { if (c->scc_has_cycle[u]) { fmpz_set_si(N, -1); } else { fmpz_one(N); } } else if (!bool_mat_get_entry(c->T, u, v)) { fmpz_zero(N); } else if ( c->scc_has_cycle[u] || c->scc_has_cycle[v] || bool_mat_get_entry(c->P, u, v)) { fmpz_set_si(N, -1); } else { fmpz_add_ui(N, fmpz_mat_entry(c->Q, u, v), 1); } } slong bool_mat_all_pairs_longest_walk(fmpz_mat_t B, const bool_mat_t A) { slong n; if (!bool_mat_is_square(A)) { flint_throw(FLINT_ERROR, "bool_mat_all_pairs_longest_walk: " "a square matrix is required!\n"); } if (bool_mat_is_empty(A)) return -1; n = bool_mat_nrows(A); if (n == 1) { if (bool_mat_get_entry(A, 0, 0)) { fmpz_set_si(fmpz_mat_entry(B, 0, 0), -2); return -2; } else { fmpz_set_si(fmpz_mat_entry(B, 0, 0), 0); return 0; } } else { slong i, j, result; _connectivity_t c; _connectivity_init(c, A); result = -1; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { slong x; fmpz *p = fmpz_mat_entry(B, i, j); _connectivity_entrywise_nilpotence_degree(p, c, i, j); fmpz_sub_ui(p, p, 1); if (result != -2) { x = fmpz_get_si(p); if (x == -2) { result = -2; } else { result = FLINT_MAX(result, x); } } } } _connectivity_clear(c); return result; } } flint-3.1.3/src/bool_mat/any.c000066400000000000000000000012671461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" int bool_mat_any(const bool_mat_t mat) { slong i, j; if (bool_mat_is_empty(mat)) return 0; for (i = 0; i < bool_mat_nrows(mat); i++) for (j = 0; j < bool_mat_ncols(mat); j++) if (bool_mat_get_entry(mat, i, j)) return 1; return 0; } flint-3.1.3/src/bool_mat/clear.c000066400000000000000000000010431461254215100164460ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_clear(bool_mat_t mat) { if (mat->entries != NULL) { flint_free(mat->entries); flint_free(mat->rows); } } flint-3.1.3/src/bool_mat/complement.c000066400000000000000000000013021461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_complement(bool_mat_t dest, const bool_mat_t src) { slong i, j; if (bool_mat_is_empty(src)) return; for (i = 0; i < bool_mat_nrows(src); i++) for (j = 0; j < bool_mat_ncols(src); j++) bool_mat_set_entry(dest, i, j, !bool_mat_get_entry(src, i, j)); } flint-3.1.3/src/bool_mat/directed_cycle.c000066400000000000000000000013331461254215100203240ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_directed_cycle(bool_mat_t mat) { if (!bool_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "bool_mat_directed_cycle: a square matrix is required!\n"); } if (bool_mat_is_empty(mat)) return; bool_mat_directed_path(mat); bool_mat_set_entry(mat, bool_mat_nrows(mat) - 1, 0, 1); } flint-3.1.3/src/bool_mat/directed_path.c000066400000000000000000000014141461254215100201610ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_directed_path(bool_mat_t mat) { slong i; if (!bool_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "bool_mat_directed_path: a square matrix is required!\n"); } if (bool_mat_is_empty(mat)) return; bool_mat_zero(mat); for (i = 0; i < bool_mat_nrows(mat) - 1; i++) { bool_mat_set_entry(mat, i, i+1, 1); } } flint-3.1.3/src/bool_mat/equal.c000066400000000000000000000015641461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" int bool_mat_equal(const bool_mat_t mat1, const bool_mat_t mat2) { slong i, j; if ((bool_mat_nrows(mat1) != bool_mat_nrows(mat2)) || (bool_mat_ncols(mat1) != bool_mat_ncols(mat2))) return 0; for (i = 0; i < bool_mat_nrows(mat1); i++) for (j = 0; j < bool_mat_ncols(mat1); j++) if (bool_mat_get_entry(mat1, i, j) != bool_mat_get_entry(mat2, i, j)) { return 0; } return 1; } flint-3.1.3/src/bool_mat/get_strongly_connected_components.c000066400000000000000000000107251461254215100243760ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" /* fixed-capacity stack */ typedef struct { slong *data; slong capacity; slong size; } _si_stack_struct; typedef _si_stack_struct _si_stack_t[1]; static void _si_stack_init(_si_stack_t s, slong capacity) { s->data = flint_malloc(capacity * sizeof(slong)); s->capacity = capacity; s->size = 0; } static void _si_stack_clear(_si_stack_t s) { flint_free(s->data); } static void _si_stack_push(_si_stack_t s, slong x) { if (s->size >= s->capacity) flint_throw(FLINT_ERROR, "(%s)\n", __func__); s->data[s->size++] = x; } static slong _si_stack_pop(_si_stack_t s) { slong x; if (s->size <= 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); x = s->data[s->size - 1]; s->size--; return x; } /* struct for Tarjan's strongly connected components algorithm */ typedef struct { slong *index; slong *lowlink; int *onstack; _si_stack_t S; slong nsccs; slong dim; slong idx; } _tarjan_struct; typedef _tarjan_struct _tarjan_t[1]; static const slong _tarjan_UNDEFINED = -1; static slong * _tarjan_index(_tarjan_t t, slong i) { return t->index + i; } static slong * _tarjan_lowlink(_tarjan_t t, slong i) { return t->lowlink + i; } static int _tarjan_onstack(_tarjan_t t, slong i) { return t->onstack[i]; } static void _tarjan_push(_tarjan_t t, slong v) { _si_stack_push(t->S, v); t->onstack[v] = 1; } static slong _tarjan_pop(_tarjan_t t) { slong v; v = _si_stack_pop(t->S); t->onstack[v] = 0; return v; } static slong _tarjan_next_scc(_tarjan_t t) { return t->nsccs++; } static slong _tarjan_next_idx(_tarjan_t t) { return t->idx++; } static void _tarjan_init(_tarjan_t t, slong dim) { slong i; t->index = flint_calloc(dim, sizeof(slong)); t->lowlink = flint_calloc(dim, sizeof(slong)); t->onstack = flint_calloc(dim, sizeof(int)); _si_stack_init(t->S, dim); t->dim = dim; t->nsccs = 0; t->idx = 0; for (i = 0; i < dim; i++) { t->index[i] = _tarjan_UNDEFINED; } } static void _tarjan_clear(_tarjan_t t) { flint_free(t->index); flint_free(t->lowlink); flint_free(t->onstack); _si_stack_clear(t->S); } static void _tarjan_strongconnect(slong *sccs, _tarjan_t t, const bool_mat_t A, slong v) { slong idx, w, scc; idx = _tarjan_next_idx(t); *_tarjan_index(t, v) = idx; *_tarjan_lowlink(t, v) = idx; _tarjan_push(t, v); for (w = 0; w < t->dim; w++) { if (bool_mat_get_entry(A, v, w)) { if (*_tarjan_index(t, w) == _tarjan_UNDEFINED) { _tarjan_strongconnect(sccs, t, A, w); *_tarjan_lowlink(t, v) = FLINT_MIN( *_tarjan_lowlink(t, v), *_tarjan_lowlink(t, w)); } else if (_tarjan_onstack(t, w)) { *_tarjan_lowlink(t, v) = FLINT_MIN( *_tarjan_lowlink(t, v), *_tarjan_index(t, w)); } } } if (*_tarjan_lowlink(t, v) == *_tarjan_index(t, v)) { scc = _tarjan_next_scc(t); while (w != v) { w = _tarjan_pop(t); if (sccs[w] != _tarjan_UNDEFINED) flint_throw(FLINT_ERROR, "(%s)\n", __func__); sccs[w] = scc; } } } /* following Tarjan */ slong bool_mat_get_strongly_connected_components(slong *partition, const bool_mat_t A) { slong i, n, result; _tarjan_t t; if (!bool_mat_is_square(A)) { flint_throw(FLINT_ERROR, "bool_mat_get_strongly_connected_components: " "a square matrix is required!\n"); } if (bool_mat_is_empty(A)) return 0; n = bool_mat_nrows(A); if (n == 1) { partition[0] = 0; return 1; } _tarjan_init(t, n); for (i = 0; i < n; i++) { partition[i] = _tarjan_UNDEFINED; } for (i = 0; i < n; i++) { if (*_tarjan_index(t, i) == _tarjan_UNDEFINED) { _tarjan_strongconnect(partition, t, A, i); } } result = t->nsccs; _tarjan_clear(t); return result; } flint-3.1.3/src/bool_mat/init.c000066400000000000000000000014161461254215100163270ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_init(bool_mat_t mat, slong r, slong c) { mat->entries = NULL; mat->rows = NULL; mat->r = r; mat->c = c; if (r != 0 && c != 0) { slong i; mat->entries = flint_calloc(r * c, sizeof(int)); mat->rows = flint_malloc(r * sizeof(int *)); for (i = 0; i < r; i++) mat->rows[i] = mat->entries + i * c; } } flint-3.1.3/src/bool_mat/io.c000066400000000000000000000017661461254215100160030ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "bool_mat.h" /* printing *******************************************************************/ void bool_mat_fprint(FILE * file, const bool_mat_t mat) { slong i, j; for (i = 0; i < bool_mat_nrows(mat); i++) { flint_fprintf(file, "["); for (j = 0; j < bool_mat_ncols(mat); j++) { flint_fprintf(file, "%d", bool_mat_get_entry(mat, i, j)); if (j < bool_mat_ncols(mat) - 1) flint_fprintf(file, ", "); } flint_fprintf(file, "]\n"); } } void bool_mat_print(const bool_mat_t mat) { bool_mat_fprint(stdout, mat); } flint-3.1.3/src/bool_mat/is_diagonal.c000066400000000000000000000013111461254215100176270ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" int bool_mat_is_diagonal(const bool_mat_t mat) { slong i, j; if (bool_mat_is_empty(mat)) return 1; for (i = 0; i < bool_mat_nrows(mat); i++) for (j = 0; j < bool_mat_ncols(mat); j++) if (i != j && bool_mat_get_entry(mat, i, j)) return 0; return 1; } flint-3.1.3/src/bool_mat/is_lower_triangular.c000066400000000000000000000013201461254215100214310ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" int bool_mat_is_lower_triangular(const bool_mat_t mat) { slong i, j; if (bool_mat_is_empty(mat)) return 1; for (j = 0; j < bool_mat_ncols(mat); j++) for (i = 0; i < bool_mat_nrows(mat) && i < j; i++) if (bool_mat_get_entry(mat, i, j)) return 0; return 1; } flint-3.1.3/src/bool_mat/is_nilpotent.c000066400000000000000000000037631461254215100201020ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" /* * Cycle detection, following * https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search */ typedef struct { int *u; /* 'temporary mark' */ int *v; /* 'permanent mark' */ slong size; } _cycle_detection_s; static void _cycle_detection_init(_cycle_detection_s *s, slong size) { s->size = size; s->u = flint_calloc(size, sizeof(int)); s->v = flint_calloc(size, sizeof(int)); } static void _cycle_detection_clear(_cycle_detection_s *s) { flint_free(s->u); flint_free(s->v); } static int _cycle_detection_visit(_cycle_detection_s *s, const bool_mat_t A, slong n) { if (s->u[n]) return 1; if (!s->v[n]) { slong m; s->u[n] = 1; for (m = 0; m < s->size; m++) if (bool_mat_get_entry(A, n, m)) if (_cycle_detection_visit(s, A, m)) return 1; s->v[n] = 1; s->u[n] = 0; } return 0; } int bool_mat_is_nilpotent(const bool_mat_t A) { slong n; if (!bool_mat_is_square(A)) { flint_throw(FLINT_ERROR, "bool_mat_is_nilpotent: a square matrix is required!\n"); } if (bool_mat_is_empty(A)) return 0; n = bool_mat_nrows(A); if (n == 1) { return !bool_mat_get_entry(A, 0, 0); } else { _cycle_detection_s s; slong i; int has_cycle; _cycle_detection_init(&s, n); for (has_cycle = 0, i = 0; !has_cycle && i < n; i++) if (!s.v[i]) has_cycle = _cycle_detection_visit(&s, A, i); _cycle_detection_clear(&s); return !has_cycle; } } flint-3.1.3/src/bool_mat/is_transitive.c000066400000000000000000000020071461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" int bool_mat_is_transitive(const bool_mat_t mat) { slong n, i, j, k; if (!bool_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "bool_mat_is_transitive: a square matrix is required!\n"); } if (bool_mat_is_empty(mat)) return 1; n = bool_mat_nrows(mat); for (i = 0; i < n; i++) for (j = 0; j < n; j++) for (k = 0; k < n; k++) if (bool_mat_get_entry(mat, i, j) && bool_mat_get_entry(mat, j, k) && !bool_mat_get_entry(mat, i, k)) { return 0; } return 1; } flint-3.1.3/src/bool_mat/mul.c000066400000000000000000000025371461254215100161660ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_mul(bool_mat_t C, const bool_mat_t A, const bool_mat_t B) { slong ar, ac, br, bc, i, j, k; ar = bool_mat_nrows(A); ac = bool_mat_ncols(A); br = bool_mat_nrows(B); bc = bool_mat_ncols(B); if (ac != br || ar != bool_mat_nrows(C) || bc != bool_mat_ncols(C)) { flint_throw(FLINT_ERROR, "bool_mat_mul: incompatible dimensions\n"); } if (br == 0) { bool_mat_zero(C); return; } if (A == C || B == C) { bool_mat_t T; bool_mat_init(T, ar, bc); bool_mat_mul(T, A, B); bool_mat_swap(T, C); bool_mat_clear(T); return; } for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { int any = 0; for (k = 0; k < br && !any; k++) any |= (bool_mat_get_entry(A, i, k) & bool_mat_get_entry(B, k, j)); bool_mat_set_entry(C, i, j, any); } } } flint-3.1.3/src/bool_mat/mul_entrywise.c000066400000000000000000000017101461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_mul_entrywise(bool_mat_t C, const bool_mat_t A, const bool_mat_t B) { slong i, j; if (bool_mat_nrows(A) != bool_mat_nrows(B) || bool_mat_ncols(A) != bool_mat_ncols(B)) { flint_throw(FLINT_ERROR, "bool_mat_mul_entrywise: incompatible dimensions\n"); } for (i = 0; i < bool_mat_nrows(A); i++) { for (j = 0; j < bool_mat_ncols(A); j++) { bool_mat_set_entry(C, i, j, (bool_mat_get_entry(A, i, j) & bool_mat_get_entry(B, i, j))); } } } flint-3.1.3/src/bool_mat/nilpotency_degree.c000066400000000000000000000065041461254215100210660ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "bool_mat.h" /* * Postorder traversal of a DAG follows * https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search */ typedef struct { int *u; /* 'temporary mark' */ int *v; /* 'permanent mark' */ slong *post; /* postorder nodes */ slong npost; /* number of postorder nodes so far */ slong size; } _toposort_s; static void _toposort_init(_toposort_s *s, slong size) { s->size = size; s->u = flint_calloc(size, sizeof(int)); s->v = flint_calloc(size, sizeof(int)); s->post = flint_malloc(size * sizeof(slong)); s->npost = 0; } static void _toposort_clear(_toposort_s *s) { flint_free(s->u); flint_free(s->v); flint_free(s->post); } static int _toposort_visit(_toposort_s *s, const bool_mat_t A, slong n) { if (s->u[n]) return 1; if (!s->v[n]) { slong m; s->u[n] = 1; for (m = 0; m < s->size; m++) if (bool_mat_get_entry(A, n, m)) if (_toposort_visit(s, A, m)) return 1; s->v[n] = 1; s->u[n] = 0; s->post[s->npost++] = n; } return 0; } slong bool_mat_nilpotency_degree(const bool_mat_t A) { slong n; if (!bool_mat_is_square(A)) { flint_throw(FLINT_ERROR, "bool_mat_nilpotency_degree: a square matrix is required!\n"); } if (bool_mat_is_empty(A)) return 0; n = bool_mat_nrows(A); if (n == 1) { return bool_mat_get_entry(A, 0, 0) ? -1 : 1; } else { _toposort_s s; slong i; int has_cycle; int result; _toposort_init(&s, n); for (has_cycle = 0, i = 0; !has_cycle && i < n; i++) if (!s.v[i]) has_cycle = _toposort_visit(&s, A, i); if (has_cycle) { result = -1; } else { /* Find the length of the longest path within the DAG */ /* https://stackoverflow.com/a/10737524/4072759 */ slong x, y, z; slong max_overall; fmpz_mat_t E; fmpz_mat_init(E, n, n); fmpz_mat_zero(E); max_overall = 0; for (i = n - 1; i >= 0; i--) { slong max_in = 0; y = s.post[i]; for (x = 0; x < n; x++) { max_in = FLINT_MAX(max_in, fmpz_get_si(fmpz_mat_entry(E, x, y))); } for (z = 0; z < n; z++) { if (bool_mat_get_entry(A, y, z)) { fmpz_set_si(fmpz_mat_entry(E, y, z), max_in + 1); max_overall = FLINT_MAX(max_overall, max_in + 1); } } } fmpz_mat_clear(E); result = max_overall + 1; } _toposort_clear(&s); return result; } } flint-3.1.3/src/bool_mat/one.c000066400000000000000000000011321461254215100161400ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_one(bool_mat_t mat) { slong i, j; for (i = 0; i < bool_mat_nrows(mat); i++) for (j = 0; j < bool_mat_ncols(mat); j++) bool_mat_set_entry(mat, i, j, i == j); } flint-3.1.3/src/bool_mat/pow_ui.c000066400000000000000000000030341461254215100166640ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_pow_ui(bool_mat_t B, const bool_mat_t A, ulong exp) { slong d; if (!bool_mat_is_square(A)) { flint_throw(FLINT_ERROR, "bool_mat_pow_ui: a square matrix is required!\n"); } if (bool_mat_is_empty(A)) return; d = bool_mat_nrows(A); if (exp <= 2 || d <= 1) { if (exp == 0) { bool_mat_one(B); } else if (d == 1) { bool_mat_set_entry(B, 0, 0, bool_mat_get_entry(A, 0, 0)); } else if (exp == 1) { bool_mat_set(B, A); } else if (exp == 2) { bool_mat_sqr(B, A); } } else { slong i; bool_mat_t T, U; bool_mat_init(T, d, d); bool_mat_set(T, A); bool_mat_init(U, d, d); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { bool_mat_sqr(U, T); if (exp & (WORD(1) << i)) bool_mat_mul(T, U, A); else bool_mat_swap(T, U); } bool_mat_swap(B, T); bool_mat_clear(T); bool_mat_clear(U); } } flint-3.1.3/src/bool_mat/randtest.c000066400000000000000000000045551461254215100172170ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "bool_mat.h" void bool_mat_randtest(bool_mat_t mat, flint_rand_t state) { slong i, j; mp_limb_t density; density = n_randint(state, 101); for (i = 0; i < bool_mat_nrows(mat); i++) for (j = 0; j < bool_mat_ncols(mat); j++) bool_mat_set_entry(mat, i, j, n_randint(state, 100) < density); } void bool_mat_randtest_diagonal(bool_mat_t mat, flint_rand_t state) { slong n, i; slong density; n = FLINT_MIN(bool_mat_nrows(mat), bool_mat_ncols(mat)); density = n_randint(state, 101); bool_mat_zero(mat); for (i = 0; i < n; i++) bool_mat_set_entry(mat, i, i, n_randint(state, 100) < density); } void bool_mat_randtest_nilpotent(bool_mat_t mat, flint_rand_t state) { slong n, i, j; slong density; if (!bool_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "bool_mat_randtest_nilpotent: " "a square matrix is required!\n"); } if (bool_mat_is_empty(mat)) { flint_throw(FLINT_ERROR, "bool_mat_randtest_nilpotent: " "a non-empty matrix is required!\n"); } n = bool_mat_nrows(mat); if (n == 1) { bool_mat_set_entry(mat, 0, 0, 0); return; } /* sample a strictly triangular matrix */ density = n_randint(state, 101); bool_mat_zero(mat); for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { bool_mat_set_entry(mat, i, j, n_randint(state, 100) < density); } } /* permute rows and columns */ { slong *p; bool_mat_t A; bool_mat_init(A, n, n); bool_mat_set(A, mat); p = flint_malloc(n * sizeof(slong)); _perm_randtest(p, n, state); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { bool_mat_set_entry( mat, p[i], p[j], bool_mat_get_entry(A, i, j)); } } flint_free(p); bool_mat_clear(A); } } flint-3.1.3/src/bool_mat/set.c000066400000000000000000000013111461254215100161510ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_set(bool_mat_t dest, const bool_mat_t src) { slong i, j; if (dest == src || bool_mat_is_empty(src)) return; for (i = 0; i < bool_mat_nrows(src); i++) for (j = 0; j < bool_mat_ncols(src); j++) bool_mat_set_entry(dest, i, j, bool_mat_get_entry(src, i, j)); } flint-3.1.3/src/bool_mat/test/000077500000000000000000000000001461254215100161755ustar00rootroot00000000000000flint-3.1.3/src/bool_mat/test/main.c000066400000000000000000000026011461254215100172640ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-all_pairs_longest_walk.c" #include "t-complement.c" #include "t-is_diagonal.c" #include "t-is_nilpotent.c" #include "t-is_transitive.c" #include "t-mul.c" #include "t-nilpotency_degree.c" #include "t-trace.c" #include "t-transitive_closure.c" #include "t-transpose.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(bool_mat_all_pairs_longest_walk), TEST_FUNCTION(bool_mat_complement), TEST_FUNCTION(bool_mat_is_diagonal), TEST_FUNCTION(bool_mat_is_nilpotent), TEST_FUNCTION(bool_mat_is_transitive), TEST_FUNCTION(bool_mat_mul), TEST_FUNCTION(bool_mat_nilpotency_degree), TEST_FUNCTION(bool_mat_trace), TEST_FUNCTION(bool_mat_transitive_closure), TEST_FUNCTION(bool_mat_transpose) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/bool_mat/test/t-all_pairs_longest_walk.c000066400000000000000000000235241461254215100233270ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" #include "bool_mat.h" int _is_superficially_ok_entrywise(const fmpz_mat_t A) { slong n, i, j, d; if (!fmpz_mat_is_square(A)) return 0; n = fmpz_mat_nrows(A); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d = fmpz_get_si(fmpz_mat_entry(A, i, j)); if (d < -2 || d > n-1) return 0; if (i == j && d == -1) return 0; if (i != j && d == 0) return 0; } } return 1; } /* Defined in t-all_pairs_longest_walk.c and t-transitive_closure.c */ #ifndef _bool_mat_permute #define _bool_mat_permute _bool_mat_permute /* permute rows and columns of a square matrix */ void _bool_mat_permute(bool_mat_t B, const bool_mat_t A, const slong *perm) { slong n, i, j; if ((A == B) || !bool_mat_is_square(A)) flint_abort(); /* assert */ n = bool_mat_nrows(A); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { bool_mat_set_entry( B, perm[i], perm[j], bool_mat_get_entry(A, i, j)); } } } #endif void _fmpz_mat_permute(fmpz_mat_t B, const fmpz_mat_t A, const slong *perm) { slong n, i, j; if (!fmpz_mat_is_square(A)) flint_abort(); /* assert */ if (A == B) flint_abort(); /* assert */ n = fmpz_mat_nrows(A); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { fmpz_set( fmpz_mat_entry(B, perm[i], perm[j]), fmpz_mat_entry(A, i, j)); } } } void _brute_force_all_pairs_longest_walk(fmpz_mat_t B, const bool_mat_t A) { slong i, j, n; n = bool_mat_nrows(A); /* set entries of B according to the longest observed walk */ { slong k; bool_mat_t T; bool_mat_init(T, n, n); bool_mat_one(T); fmpz_mat_zero(B); for (k = 0; k < 2*n+1; k++) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (bool_mat_get_entry(T, i, j)) { fmpz_set_si(fmpz_mat_entry(B, i, j), k); } } } bool_mat_mul(T, T, A); } bool_mat_clear(T); } /* set special values 0, -1, -2 */ { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { slong x; fmpz *p; p = fmpz_mat_entry(B, i, j); x = fmpz_get_si(p); if (x < 1) { x = (i == j) ? 0 : -1; } else if (x > n-1) { x = -2; } fmpz_set_si(p, x); } } } } TEST_FUNCTION_START(bool_mat_all_pairs_longest_walk, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, degree; bool_mat_t A; fmpz_mat_t B, C, D; m = n_randint(state, 50); bool_mat_init(A, m, m); fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, m); fmpz_mat_init(D, m, m); bool_mat_randtest(A, state); degree = bool_mat_all_pairs_longest_walk(B, A); /* entrywise reasonability */ if (!_is_superficially_ok_entrywise(B)) { flint_printf("FAIL (entrywise)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); flint_abort(); } /* nilpotency degree */ { slong nildegree = bool_mat_nilpotency_degree(A); if (nildegree != degree + 1) { flint_printf("FAIL (nilpotency degree)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); flint_printf("nildegree=%wd degree=%wd\n", nildegree, degree); flint_abort(); } } /* transitive closure */ { slong i, j; bool_mat_t U, V; bool_mat_init(U, m, m); bool_mat_transitive_closure(U, A); bool_mat_init(V, m, m); for (i = 0; i < m; i++) { for (j = 0; j < m; j++) { slong x = fmpz_get_si(fmpz_mat_entry(B, i, j)); bool_mat_set_entry(V, i, j, (x != -1 && x != 0)); } } if (!bool_mat_equal(U, V)) { flint_printf("FAIL (transitive closure)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); bool_mat_print(U); flint_printf("\n"); bool_mat_print(V); flint_printf("\n"); flint_abort(); } bool_mat_clear(U); bool_mat_clear(V); } /* test commutativity of all-pairs-longest-walk with permutation */ { bool_mat_t Ap; slong *perm; bool_mat_init(Ap, m, m); perm = flint_malloc(m * sizeof(slong)); _perm_randtest(perm, m, state); /* C is the all-pairs-longest-walk of the permutation of A */ _bool_mat_permute(Ap, A, perm); bool_mat_all_pairs_longest_walk(C, Ap); /* D is the permutation of the all-pairs-longest-walk of A */ _fmpz_mat_permute(D, B, perm); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL (permutation)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fmpz_mat_print_pretty(C); flint_printf("\n"); fmpz_mat_print_pretty(D); flint_printf("\n"); flint_abort(); } flint_free(perm); bool_mat_clear(Ap); } bool_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } /* use powering to check small random examples */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m; bool_mat_t A; fmpz_mat_t B, C; m = n_randint(state, 10); bool_mat_init(A, m, m); fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, m); bool_mat_randtest(A, state); bool_mat_all_pairs_longest_walk(B, A); _brute_force_all_pairs_longest_walk(C, A); if (!fmpz_mat_equal(B, C)) { flint_printf("FAIL (powering)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fmpz_mat_print_pretty(C); flint_printf("\n"); flint_abort(); } bool_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } /* special matrices */ { slong m; for (m = 1; m < 100; m++) { slong i, j, length; bool_mat_t A; fmpz_mat_t B; bool_mat_init(A, m, m); fmpz_mat_init(B, m, m); /* directed path */ { bool_mat_directed_path(A); length = bool_mat_all_pairs_longest_walk(B, A); if (length != m-1) { flint_printf("FAIL (directed path)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); flint_printf("m=%wd length=%wd\n", m, length); flint_abort(); } for (i = 0; i < m; i++) { for (j = 0; j < m; j++) { if (fmpz_get_si(fmpz_mat_entry(B, i, j)) != FLINT_MAX(-1, j - i)) { flint_printf("FAIL (directed path)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); flint_abort(); } } } } /* directed cycle */ { bool_mat_directed_cycle(A); length = bool_mat_all_pairs_longest_walk(B, A); if (length != -2) { flint_printf("FAIL (directed cycle)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); flint_printf("m=%wd length=%wd\n", m, length); flint_abort(); } for (i = 0; i < m; i++) { for (j = 0; j < m; j++) { if (fmpz_get_si(fmpz_mat_entry(B, i, j)) != -2) { flint_printf("FAIL (directed cycle)\n"); bool_mat_print(A); flint_printf("\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); flint_abort(); } } } } bool_mat_clear(A); fmpz_mat_clear(B); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-complement.c000066400000000000000000000057111461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_complement, state) { slong iter; /* zero matrix */ { slong m, n; for (m = 1; m < 10; m++) { for (n = 1; n < 10; n++) { bool_mat_t zero, C; bool_mat_init(zero, m, n); bool_mat_init(C, m, n); bool_mat_zero(zero); bool_mat_complement(C, zero); if (bool_mat_any(zero) || bool_mat_all(zero) || !bool_mat_any(C) || !bool_mat_all(C)) { flint_printf("FAIL (zero matrix)\n"); flint_abort(); } bool_mat_clear(zero); bool_mat_clear(C); } } } /* identity matrix */ { slong n; for (n = 2; n < 10; n++) { bool_mat_t one, C; bool_mat_init(one, n, n); bool_mat_init(C, n, n); bool_mat_one(one); bool_mat_complement(C, one); if (!bool_mat_any(one) || bool_mat_all(one) || !bool_mat_any(C) || bool_mat_all(C)) { flint_printf("FAIL (identity matrix)\n"); flint_abort(); } bool_mat_clear(one); bool_mat_clear(C); } } /* random matrices */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n; bool_mat_t A, C; m = n_randint(state, 10) + 1; n = n_randint(state, 10) + 1; bool_mat_init(A, m, n); bool_mat_init(C, m, n); bool_mat_randtest(A, state); bool_mat_randtest(C, state); bool_mat_complement(C, A); if ((bool_mat_all(A) && bool_mat_any(C)) || (bool_mat_all(C) && bool_mat_any(A))) { flint_printf("FAIL\n"); flint_abort(); } /* involution */ { bool_mat_t CC; bool_mat_init(CC, m, n); bool_mat_randtest(CC, state); bool_mat_complement(CC, C); if (!bool_mat_equal(A, CC)) { flint_printf("FAIL (involution)\n"); flint_abort(); } bool_mat_clear(CC); } /* aliasing */ bool_mat_complement(A, A); if (!bool_mat_equal(A, C)) { flint_printf("FAIL (aliasing)\n"); flint_abort(); } bool_mat_clear(A); bool_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-is_diagonal.c000066400000000000000000000051021461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_is_diagonal, state) { slong iter; /* all zero matrices are diagonal */ { slong m, n; for (m = 0; m < 10; m++) { for (n = 0; n < 10; n++) { bool_mat_t zero; bool_mat_init(zero, m, n); bool_mat_zero(zero); if (!bool_mat_is_diagonal(zero)) { flint_printf("FAIL (zero matrix)\n"); flint_abort(); } bool_mat_clear(zero); } } } /* all identity matrices are diagonal */ { slong n; for (n = 0; n < 10; n++) { bool_mat_t one; bool_mat_init(one, n, n); bool_mat_one(one); if (!bool_mat_is_diagonal(one)) { flint_printf("FAIL (identity matrix)\n"); flint_abort(); } bool_mat_clear(one); } } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n; bool_mat_t A; m = n_randint(state, 10) + 1; n = n_randint(state, 10) + 1; bool_mat_init(A, m, n); /* random diagonal */ { bool_mat_randtest_diagonal(A, state); if (!bool_mat_is_diagonal(A)) { flint_printf("FAIL (random diagonal)\n"); flint_printf("A:\n"); bool_mat_print(A); flint_printf("\n"); flint_abort(); } } /* random non-diagonal */ { slong i, j; bool_mat_randtest(A, state); i = n_randint(state, m); j = n_randint(state, n); if (i != j) { bool_mat_set_entry(A, i, j, 1); if (bool_mat_is_diagonal(A)) { flint_printf("FAIL (random non-diagonal)\n"); flint_printf("A:\n"); bool_mat_print(A); flint_printf("\n"); flint_abort(); } } } bool_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-is_nilpotent.c000066400000000000000000000040371461254215100213150ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_is_nilpotent, state) { slong iter; /* empty matrix is not nilpotent(?) */ { bool_mat_t A; bool_mat_init(A, 0, 0); if (bool_mat_is_nilpotent(A)) { flint_printf("FAIL (empty)\n"); flint_abort(); } bool_mat_clear(A); } /* detect nilpotency of matrices that are constructed to be nilpotent */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m; bool_mat_t A; m = n_randint(state, 10) + 1; bool_mat_init(A, m, m); bool_mat_randtest_nilpotent(A, state); if (!bool_mat_is_nilpotent(A)) { flint_printf("FAIL (nilpotent by construction)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n"); flint_abort(); } bool_mat_clear(A); } /* check nilpotency by computing a matrix power */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m; bool_mat_t A, B; m = n_randint(state, 10) + 1; bool_mat_init(A, m, m); bool_mat_init(B, m, m); bool_mat_randtest(A, state); bool_mat_pow_ui(B, A, m); if (bool_mat_is_nilpotent(A) != !bool_mat_any(B)) { flint_printf("FAIL (A^m)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n"); flint_printf("B = \n"); bool_mat_print(B); flint_printf("\n"); flint_abort(); } bool_mat_clear(A); bool_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-is_transitive.c000066400000000000000000000033251461254215100214700ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_is_transitive, state) { slong iter; /* special matrices */ { slong n; for (n = 0; n < 10; n++) { bool_mat_t A; bool_mat_init(A, n, n); /* identity matrices are transitive */ bool_mat_one(A); if (!bool_mat_is_transitive(A)) { flint_printf("FAIL (identity matrix)\n"); flint_abort(); } /* square zero matrices are transitive */ bool_mat_zero(A); if (!bool_mat_is_transitive(A)) { flint_printf("FAIL (zero matrix)\n"); flint_abort(); } bool_mat_clear(A); } } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong n; bool_mat_t A; n = n_randint(state, 10); bool_mat_init(A, n, n); /* all square diagonal matrices are transitive */ bool_mat_randtest_diagonal(A, state); if (!bool_mat_is_transitive(A)) { flint_printf("FAIL (diagonal)\n"); flint_printf("A:\n"); bool_mat_print(A); flint_printf("\n"); flint_abort(); } bool_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-mul.c000066400000000000000000000140201461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_mul, state) { slong iter; /* test aliasing */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n; bool_mat_t A, B, C, D; m = n_randint(state, 10); n = n_randint(state, 10); /* test aliasing with a */ { bool_mat_init(A, m, n); bool_mat_init(B, n, n); bool_mat_init(C, m, n); bool_mat_init(D, m, n); bool_mat_randtest(A, state); bool_mat_randtest(B, state); bool_mat_mul(C, A, B); bool_mat_set(D, A); bool_mat_mul(D, D, B); if (!bool_mat_equal(D, C)) { flint_printf("FAIL (aliasing 1)\n"); flint_abort(); } bool_mat_clear(A); bool_mat_clear(B); bool_mat_clear(C); bool_mat_clear(D); } /* test aliasing with b */ { bool_mat_init(A, m, m); bool_mat_init(B, m, n); bool_mat_init(C, m, n); bool_mat_init(D, m, n); bool_mat_randtest(A, state); bool_mat_randtest(B, state); bool_mat_mul(C, A, B); bool_mat_set(D, B); bool_mat_mul(D, A, D); if (!bool_mat_equal(D, C)) { flint_printf("FAIL (aliasing 2)\n"); flint_abort(); } bool_mat_clear(A); bool_mat_clear(B); bool_mat_clear(C); bool_mat_clear(D); } } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, k, l; bool_mat_t a, b, c, d, ab, ac, bd, cd, s; m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); l = n_randint(state, 10); bool_mat_init(a, m, n); bool_mat_init(b, n, k); bool_mat_init(c, n, k); bool_mat_init(d, k, l); bool_mat_randtest(a, state); bool_mat_randtest(b, state); bool_mat_randtest(c, state); bool_mat_randtest(d, state); bool_mat_init(ab, m, k); bool_mat_init(ac, m, k); bool_mat_init(bd, n, l); bool_mat_init(cd, n, l); bool_mat_init(s, n, k); bool_mat_mul(ab, a, b); bool_mat_mul(ac, a, c); bool_mat_mul(bd, b, d); bool_mat_mul(cd, c, d); bool_mat_add(s, b, c); /* check associativity of multiplication */ /* (A*B)*D = A*(B*D) */ { bool_mat_t lhs, rhs; bool_mat_init(lhs, m, l); bool_mat_init(rhs, m, l); bool_mat_mul(lhs, ab, d); bool_mat_mul(rhs, a, bd); if (!bool_mat_equal(lhs, rhs)) { flint_printf("FAIL (associativity)\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_abort(); } bool_mat_clear(lhs); bool_mat_clear(rhs); } /* check left distributivity of multiplication over addition */ /* A*(B + C) = A*B + A*C */ { bool_mat_t lhs, rhs; bool_mat_init(lhs, m, k); bool_mat_init(rhs, m, k); bool_mat_mul(lhs, a, s); bool_mat_add(rhs, ab, ac); if (!bool_mat_equal(lhs, rhs)) { flint_printf("FAIL (left distributivity)\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_abort(); } bool_mat_clear(lhs); bool_mat_clear(rhs); } /* check right distributivity of multiplication over addition */ /* (B + C)*D = B*D + C*D */ { bool_mat_t lhs, rhs; bool_mat_init(lhs, n, l); bool_mat_init(rhs, n, l); bool_mat_mul(lhs, s, d); bool_mat_add(rhs, bd, cd); if (!bool_mat_equal(lhs, rhs)) { flint_printf("FAIL (right distributivity)\n"); flint_printf("m, n, k, l = %wd, %wd, %wd, %wd\n", m, n, k, l); flint_abort(); } bool_mat_clear(lhs); bool_mat_clear(rhs); } /* check left multiplicative identity I*D = D */ { bool_mat_t one, lhs; bool_mat_init(one, k, k); bool_mat_init(lhs, k, l); bool_mat_one(one); bool_mat_mul(lhs, one, d); if (!bool_mat_equal(lhs, d)) { flint_printf("FAIL (left identity)\n"); flint_printf("k = %wd, l = %wd\n", k, l); flint_abort(); } bool_mat_clear(one); bool_mat_clear(lhs); } /* check right multiplicative identity A*I = A */ { bool_mat_t one, lhs; bool_mat_init(one, n, n); bool_mat_init(lhs, m, n); bool_mat_one(one); bool_mat_mul(lhs, a, one); if (!bool_mat_equal(lhs, a)) { flint_printf("FAIL (right identity)\n"); flint_printf("m = %wd, n = %wd\n", m, n); flint_abort(); } bool_mat_clear(one); bool_mat_clear(lhs); } bool_mat_clear(a); bool_mat_clear(b); bool_mat_clear(c); bool_mat_clear(d); bool_mat_clear(ab); bool_mat_clear(ac); bool_mat_clear(bd); bool_mat_clear(cd); bool_mat_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-nilpotency_degree.c000066400000000000000000000033361461254215100223060ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_nilpotency_degree, state) { slong iter; /* empty matrix */ { bool_mat_t A; bool_mat_init(A, 0, 0); if (bool_mat_nilpotency_degree(A) != 0) { flint_printf("FAIL (empty)\n"); flint_abort(); } bool_mat_clear(A); } /* check nilpotency degree by looking at each power of a matrix */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, i; bool_mat_t A, B; slong degree; m = n_randint(state, 10) + 1; bool_mat_init(A, m, m); bool_mat_init(B, m, m); bool_mat_randtest(A, state); bool_mat_one(B); for (degree = -1, i = 0; i < m && degree < 0; i++) { bool_mat_mul(B, B, A); if (!bool_mat_any(B)) degree = i+1; } if (bool_mat_nilpotency_degree(A) != degree) { flint_printf("FAIL (matrix powers)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n"); flint_printf("B = \n"); bool_mat_print(B); flint_printf("\n"); flint_printf("i = %wd\n", i); flint_abort(); } bool_mat_clear(A); bool_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-trace.c000066400000000000000000000112141461254215100176770ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_trace, state) { slong iter; /* trace(empty) == 0 */ { bool_mat_t A; bool_mat_init(A, 0, 0); bool_mat_one(A); if (bool_mat_trace(A) != 0) { flint_printf("FAIL (empty)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n\n"); flint_abort(); } bool_mat_clear(A); } /* trace(zero) == 0 */ { slong n; bool_mat_t A; for (n = 1; n < 10; n++) { bool_mat_init(A, n, n); bool_mat_zero(A); if (bool_mat_trace(A) != 0) { flint_printf("FAIL (zero)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n\n"); flint_abort(); } bool_mat_clear(A); } } /* trace(one) == 1 */ { slong n; bool_mat_t A; for (n = 1; n < 10; n++) { bool_mat_init(A, n, n); bool_mat_one(A); if (bool_mat_trace(A) != 1) { flint_printf("FAIL (one)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n\n"); flint_abort(); } bool_mat_clear(A); } } /* traces of random matrices with modified diagonal */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong n, i; bool_mat_t A; n = n_randint(state, 10) + 1; bool_mat_init(A, n, n); bool_mat_randtest(A, state); i = (slong) n_randint(state, n); bool_mat_set_entry(A, i, i, 1); if (bool_mat_trace(A) != 1) { flint_printf("FAIL (diagonal has a non-zero entry)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n\n"); flint_abort(); } for (i = 0; i < n; i++) { bool_mat_set_entry(A, i, i, 0); } if (bool_mat_trace(A) != 0) { flint_printf("FAIL (diagonal is zero)\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n\n"); flint_abort(); } bool_mat_clear(A); } /* trace(A + B) == trace(A) + trace(B) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong n; bool_mat_t A, B, C; n = n_randint(state, 10); bool_mat_init(A, n, n); bool_mat_init(B, n, n); bool_mat_init(C, n, n); bool_mat_randtest(A, state); bool_mat_randtest(B, state); bool_mat_add(C, A, B); if (bool_mat_trace(C) != (bool_mat_trace(A) | bool_mat_trace(B))) { flint_printf("FAIL (trace(A+B) == trace(A) | trace(B))\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n\n"); flint_printf("B = \n"); bool_mat_print(B); flint_printf("\n\n"); flint_printf("A+B = \n"); bool_mat_print(C); flint_printf("\n\n"); flint_abort(); } bool_mat_clear(A); bool_mat_clear(B); bool_mat_clear(C); } /* trace(A*B) == trace(B*A) */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong n, m; bool_mat_t A, B, AB, BA; n = n_randint(state, 10); m = n_randint(state, 10); bool_mat_init(A, n, m); bool_mat_init(B, m, n); bool_mat_init(AB, n, n); bool_mat_init(BA, m, m); bool_mat_randtest(A, state); bool_mat_randtest(B, state); bool_mat_mul(AB, A, B); bool_mat_mul(BA, B, A); if (bool_mat_trace(AB) != bool_mat_trace(BA)) { flint_printf("FAIL (trace(AB) == trace(BA))\n"); flint_printf("A = \n"); bool_mat_print(A); flint_printf("\n\n"); flint_printf("B = \n"); bool_mat_print(B); flint_printf("\n\n"); flint_printf("AB = \n"); bool_mat_print(AB); flint_printf("\n\n"); flint_printf("BA = \n"); bool_mat_print(BA); flint_printf("\n\n"); flint_abort(); } bool_mat_clear(A); bool_mat_clear(B); bool_mat_clear(AB); bool_mat_clear(BA); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-transitive_closure.c000066400000000000000000000117311461254215100225310ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" #include "perm.h" /* Defined in t-all_pairs_longest_walk.c and t-transitive_closure.c */ #ifndef _bool_mat_permute #define _bool_mat_permute _bool_mat_permute /* permute rows and columns of a square matrix */ void _bool_mat_permute(bool_mat_t B, const bool_mat_t A, const slong *perm) { slong n, i, j; if ((A == B) || !bool_mat_is_square(A)) flint_abort(); /* assert */ n = bool_mat_nrows(A); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { bool_mat_set_entry( B, perm[i], perm[j], bool_mat_get_entry(A, i, j)); } } } #endif void _bool_mat_transitive_closure_powering(bool_mat_t B, const bool_mat_t A) { slong n, k; bool_mat_t T; if ((A == B) || !bool_mat_is_square(A)) flint_abort(); /* assert */ n = bool_mat_nrows(A); bool_mat_init(T, n, n); bool_mat_one(T); bool_mat_zero(B); for (k = 0; k < n; k++) { bool_mat_mul(T, T, A); bool_mat_add(B, B, T); } bool_mat_clear(T); } TEST_FUNCTION_START(bool_mat_transitive_closure, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m; bool_mat_t A, B, C, D; m = n_randint(state, 50); bool_mat_init(A, m, m); bool_mat_init(B, m, m); bool_mat_init(C, m, m); bool_mat_init(D, m, m); bool_mat_randtest(A, state); bool_mat_randtest(B, state); bool_mat_transitive_closure(B, A); /* transitivity */ if (!bool_mat_is_transitive(B)) { flint_printf("FAIL (transitivity)\n"); bool_mat_print(A); flint_printf("\n"); bool_mat_print(B); flint_printf("\n"); flint_abort(); } /* monotonicity */ { bool_mat_complement(C, B); bool_mat_mul_entrywise(D, A, C); if (bool_mat_any(D)) { flint_printf("FAIL (monotonicity)\n"); bool_mat_print(A); flint_printf("\n"); bool_mat_print(B); flint_printf("\n"); flint_abort(); } } /* aliasing */ { bool_mat_set(C, A); bool_mat_transitive_closure(C, C); if (!bool_mat_equal(B, C)) { flint_printf("FAIL (aliasing)\n"); bool_mat_print(A); flint_printf("\n"); bool_mat_print(B); flint_printf("\n"); bool_mat_print(C); flint_printf("\n"); flint_abort(); } } /* test commutativity of permutation with transitive closure */ { slong *perm; perm = flint_malloc(m * sizeof(slong)); _perm_randtest(perm, m, state); /* C is the transitive closure of the permutation of A */ bool_mat_randtest(C, state); _bool_mat_permute(C, A, perm); bool_mat_transitive_closure(C, C); /* D is the permutation of the transitive closure of A */ bool_mat_randtest(D, state); _bool_mat_permute(D, B, perm); if (!bool_mat_equal(C, D)) { flint_printf("FAIL (commutativity with permutation)\n"); bool_mat_print(A); flint_printf("\n"); bool_mat_print(B); flint_printf("\n"); bool_mat_print(C); flint_printf("\n"); bool_mat_print(D); flint_printf("\n"); flint_abort(); } flint_free(perm); } bool_mat_clear(A); bool_mat_clear(B); bool_mat_clear(C); bool_mat_clear(D); } /* check transitive closure using brute force with smallish matrices */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m; bool_mat_t A, B, C; m = n_randint(state, 10); bool_mat_init(A, m, m); bool_mat_init(B, m, m); bool_mat_init(C, m, m); bool_mat_randtest(A, state); bool_mat_randtest(B, state); bool_mat_randtest(C, state); bool_mat_transitive_closure(B, A); _bool_mat_transitive_closure_powering(C, A); if (!bool_mat_equal(B, C)) { flint_printf("FAIL (brute force)\n"); bool_mat_print(A); flint_printf("\n"); bool_mat_print(B); flint_printf("\n"); bool_mat_print(C); flint_printf("\n"); flint_abort(); } bool_mat_clear(A); bool_mat_clear(B); bool_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/test/t-transpose.c000066400000000000000000000031601461254215100206200ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "bool_mat.h" TEST_FUNCTION_START(bool_mat_transpose, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n; bool_mat_t a, b; m = n_randint(state, 10); n = n_randint(state, 10); bool_mat_init(a, m, n); bool_mat_init(b, n, m); bool_mat_randtest(a, state); bool_mat_randtest(b, state); bool_mat_transpose(b, a); /* involution */ { bool_mat_t c; bool_mat_init(c, m, n); bool_mat_randtest(c, state); bool_mat_transpose(c, b); if (!bool_mat_equal(c, a)) { flint_printf("FAIL (involution)\n"); flint_printf("m = %wd, n = %wd\n", m, n); flint_abort(); } bool_mat_clear(c); } /* aliasing */ if (bool_mat_is_square(a)) { bool_mat_transpose(a, a); if (!bool_mat_equal(a, b)) { flint_printf("FAIL (aliasing)\n"); flint_abort(); } } bool_mat_clear(a); bool_mat_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/bool_mat/trace.c000066400000000000000000000013771461254215100164700ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" int bool_mat_trace(const bool_mat_t mat) { slong i; if (!bool_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "bool_mat_trace: a square matrix is required!\n"); } if (bool_mat_is_empty(mat)) return 0; for (i = 0; i < bool_mat_nrows(mat); i++) if (bool_mat_get_entry(mat, i, i)) return 1; return 0; } flint-3.1.3/src/bool_mat/transitive_closure.c000066400000000000000000000025471461254215100213160ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" /* Warshall's algorithm */ void bool_mat_transitive_closure(bool_mat_t dest, const bool_mat_t src) { slong k, i, j, dim; if (bool_mat_nrows(dest) != bool_mat_nrows(src) || bool_mat_ncols(dest) != bool_mat_ncols(src)) { flint_throw(FLINT_ERROR, "bool_mat_transitive_closure: incompatible dimensions\n"); } dim = bool_mat_nrows(src); if (dim != bool_mat_ncols(src)) { flint_throw(FLINT_ERROR, "bool_mat_transitive_closure: a square matrix is required!\n"); } bool_mat_set(dest, src); for (k = 0; k < dim; k++) { for (i = 0; i < dim; i++) { for (j = 0; j < dim; j++) { if (!bool_mat_get_entry(dest, i, j)) { bool_mat_set_entry(dest, i, j, ( bool_mat_get_entry(dest, i, k) & bool_mat_get_entry(dest, k, j))); } } } } } flint-3.1.3/src/bool_mat/transpose.c000066400000000000000000000025261461254215100174050ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_transpose(bool_mat_t B, const bool_mat_t A) { slong i, j; if (bool_mat_nrows(B) != bool_mat_ncols(A) || bool_mat_ncols(B) != bool_mat_nrows(A)) { flint_throw(FLINT_ERROR, "bool_mat_transpose: Incompatible dimensions.\n"); } if (bool_mat_is_empty(A)) return; if (A == B) /* In-place, guaranteed to be square */ { int tmp; for (i = 0; i < bool_mat_nrows(B) - 1; i++) { for (j = i + 1; j < bool_mat_ncols(B); j++) { tmp = bool_mat_get_entry(B, i, j); bool_mat_set_entry(B, i, j, bool_mat_get_entry(B, j, i)); bool_mat_set_entry(B, j, i, tmp); } } } else /* Not aliased; general case */ { for (i = 0; i < bool_mat_nrows(B); i++) for (j = 0; j < bool_mat_ncols(B); j++) bool_mat_set_entry(B, i, j, bool_mat_get_entry(A, j, i)); } } flint-3.1.3/src/bool_mat/zero.c000066400000000000000000000011261461254215100163410ustar00rootroot00000000000000/* Copyright (C) 2016 Arb authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "bool_mat.h" void bool_mat_zero(bool_mat_t mat) { slong i, j; for (i = 0; i < bool_mat_nrows(mat); i++) for (j = 0; j < bool_mat_ncols(mat); j++) bool_mat_set_entry(mat, i, j, 0); } flint-3.1.3/src/ca.h000066400000000000000000000534301461254215100141630ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CA_H #define CA_H #ifdef CA_INLINES_C #define CA_INLINE #else #define CA_INLINE static inline #endif #include "flint.h" #include "fmpz_mpoly_q.h" #include "nf_elem.h" #include "qqbar.h" #include "fmpz_mpoly.h" #include "fexpr.h" #ifdef __cplusplus extern "C" { #endif #define CA_INFO(ctx, args) do { if (ctx->options[CA_OPT_VERBOSE]) \ do { flint_printf("%s:%d: ", __FILE__, __LINE__); flint_printf args; } \ while (0); } while (0); /* Number object *************************************************************/ typedef union { fmpq q; /* rational number */ nf_elem_struct nf; /* algebraic number field element */ fmpz_mpoly_q_struct * mpoly_q; /* generic field element */ } ca_elem_struct; typedef struct { ulong field; ca_elem_struct elem; } ca_struct; typedef ca_struct ca_t[1]; typedef ca_struct * ca_ptr; typedef const ca_struct * ca_srcptr; #define CA_FMPQ(x) (&((x)->elem.q)) #define CA_MPOLY_Q(x) (&(((x)->elem.mpoly_q)[0])) #define CA_NF_ELEM(x) (&((x)->elem.nf)) #define CA_FMPQ_NUMREF(x) (fmpq_numref(CA_FMPQ(x))) #define CA_FMPQ_DENREF(x) (fmpq_denref(CA_FMPQ(x))) #define CA_FIELD(x, ctx) ((ca_field_ptr) ((x)->field)) #define CA_FIELD_ULONG(x) ((x)->field) /* We always allocate QQ and QQ(i) */ #define CA_IS_QQ(x, ctx) (CA_FIELD(x, ctx) == (ctx)->field_qq) #define CA_IS_QQ_I(x, ctx) (CA_FIELD(x, ctx) == (ctx)->field_qq_i) /* Use the low two bits of the field pointer to encode special values. */ /* The field pointer with the mask removed is NULL for Unknown/Undefined/Uinf, and a normal field pointer for signed infinity (encoding the sign). */ #define CA_UNKNOWN UWORD(1) #define CA_UNDEFINED UWORD(2) #define CA_INF UWORD(3) #define CA_SPECIAL (CA_UNKNOWN | CA_UNDEFINED | CA_INF) #define CA_IS_SPECIAL(x) (CA_FIELD_ULONG(x) & CA_SPECIAL) #define CA_IS_UNKNOWN(x) (CA_FIELD_ULONG(x) == CA_UNKNOWN) #define CA_IS_UNDEFINED(x) (CA_FIELD_ULONG(x) == CA_UNDEFINED) #define CA_IS_INF(x) ((CA_FIELD_ULONG(x) & CA_SPECIAL) == CA_INF) #define CA_IS_UNSIGNED_INF(x) (CA_FIELD_ULONG(x) == CA_INF) #define CA_IS_SIGNED_INF(x) (CA_IS_INF(x) && !CA_IS_UNSIGNED_INF(x)) #define CA_FIELD_UNSPECIAL(x, ctx) ((ca_field_ptr) (CA_FIELD_ULONG(x) & ~CA_SPECIAL)) /* Extension object **********************************************************/ typedef struct { qqbar_struct x; /* qqbar_t element */ nf_struct * nf; /* antic number field for fast arithmetic */ } ca_ext_qqbar; typedef struct { ca_struct * args; /* Function arguments x1, ..., xn. */ slong nargs; /* Number of function arguments n. */ acb_struct enclosure; /* Cached numerical enclosure of f(x1,...,xn) */ slong prec; /* Working precision of cached enclosure */ qqbar_struct * qqbar; /* Cached qqbar */ } ca_ext_func_data; typedef struct { calcium_func_code head; /* f = F_Pi, F_Exp, ... */ ulong hash; slong depth; union { ca_ext_qqbar qqbar; ca_ext_func_data func_data; } data; } ca_ext_struct; typedef ca_ext_struct ca_ext_t[1]; typedef ca_ext_struct * ca_ext_ptr; typedef const ca_ext_struct * ca_ext_srcptr; #define CA_EXT_HEAD(x) ((x)->head) #define CA_EXT_HASH(x) ((x)->hash) #define CA_EXT_DEPTH(x) ((x)->depth) #define CA_EXT_IS_QQBAR(x) ((x)->head == CA_QQBar) #define CA_EXT_QQBAR(_x) (&((_x)->data.qqbar.x)) #define CA_EXT_QQBAR_NF(_x) ((_x)->data.qqbar.nf) #define CA_EXT_FUNC_ARGS(x) ((x)->data.func_data.args) #define CA_EXT_FUNC_NARGS(x) ((x)->data.func_data.nargs) #define CA_EXT_FUNC_ENCLOSURE(x) (&((x)->data.func_data.enclosure)) #define CA_EXT_FUNC_PREC(x) ((x)->data.func_data.prec) typedef struct { ca_ext_struct ** items; slong length; slong alloc; slong hash_size; slong * hash_table; } ca_ext_cache_struct; typedef ca_ext_cache_struct ca_ext_cache_t[1]; /* Field object **************************************************************/ typedef struct { slong length; /* Number of generators */ ca_ext_struct ** ext; /* Generators */ fmpz_mpoly_vec_struct ideal; /* Algebraic relations for reduction */ ulong hash; } ca_field_struct; typedef ca_field_struct ca_field_t[1]; typedef ca_field_struct * ca_field_ptr; typedef const ca_field_struct * ca_field_srcptr; #define CA_FIELD_LENGTH(K) ((K)->length) #define CA_FIELD_EXT(K) ((K)->ext) #define CA_FIELD_EXT_ELEM(K, i) ((K)->ext[i]) #define CA_FIELD_HASH(K) ((K)->hash) #define CA_FIELD_IS_QQ(K) ((K)->length == 0) #define CA_FIELD_IS_NF(K) ((K)->ideal.length == -1) #define CA_FIELD_IS_GENERIC(K) (!CA_FIELD_IS_QQ(K) && !CA_FIELD_IS_NF(K)) #define CA_FIELD_NF(K) (((K)->ext[0]->data.qqbar.nf)) #define CA_FIELD_NF_QQBAR(K) (&((K)->ext[0]->data.qqbar.x)) #define CA_FIELD_IDEAL(K) (&((K)->ideal)) #define CA_FIELD_IDEAL_ELEM(K, i) fmpz_mpoly_vec_entry(CA_FIELD_IDEAL(K), i) #define CA_FIELD_IDEAL_LENGTH(K) ((K)->ideal.length) #define CA_FIELD_IDEAL_ALLOC(K) ((K)->ideal.alloc) #define CA_FIELD_IDEAL_P(K) ((K)->ideal.p) #define CA_MCTX_1(ctx) ((ctx)->mctx[0]) #define CA_FIELD_MCTX(K, ctx) ((ctx)->mctx[CA_FIELD_LENGTH(K) - 1]) typedef struct { ca_field_struct ** items; slong length; slong alloc; slong hash_size; slong * hash_table; } ca_field_cache_struct; typedef ca_field_cache_struct ca_field_cache_t[1]; /* Context object ************************************************************/ enum { CA_OPT_VERBOSE, CA_OPT_PRINT_FLAGS, CA_OPT_MPOLY_ORD, CA_OPT_PREC_LIMIT, CA_OPT_QQBAR_DEG_LIMIT, CA_OPT_LOW_PREC, CA_OPT_SMOOTH_LIMIT, CA_OPT_LLL_PREC, CA_OPT_POW_LIMIT, CA_OPT_USE_GROEBNER, CA_OPT_GROEBNER_LENGTH_LIMIT, CA_OPT_GROEBNER_POLY_LENGTH_LIMIT, CA_OPT_GROEBNER_POLY_BITS_LIMIT, CA_OPT_VIETA_LIMIT, CA_OPT_TRIG_FORM, CA_OPT_NUM_OPTIONS }; #define CA_TRIG_DIRECT 0 #define CA_TRIG_EXPONENTIAL 1 #define CA_TRIG_SINE_COSINE 2 #define CA_TRIG_TANGENT 3 typedef struct { ca_ext_cache_struct ext_cache; /* Cached extension objects */ ca_field_cache_struct field_cache; /* Cached extension fields */ ca_field_struct * field_qq; /* Quick access to QQ */ ca_field_struct * field_qq_i; /* Quick access to QQ(i) */ fmpz_mpoly_ctx_struct ** mctx; /* Cached contexts for multivariate polys */ slong mctx_len; slong * options; } ca_ctx_struct; typedef ca_ctx_struct ca_ctx_t[1]; #define CA_CTX_EXT_CACHE(ctx) (&((ctx)->ext_cache)) #define CA_CTX_FIELD_CACHE(ctx) (&((ctx)->field_cache)) #define CA_CTX_FIELD_WITH_INDEX(ctx, i) ((&((ctx)->field_cache))->items[i]) /* Context management */ void ca_ctx_init(ca_ctx_t ctx); void ca_ctx_clear(ca_ctx_t ctx); void ca_ctx_print(ca_ctx_t ctx); CA_INLINE slong ca_ctx_get_option(ca_ctx_t ctx, slong i) { return ctx->options[i]; } CA_INLINE void ca_ctx_set_option(ca_ctx_t ctx, slong i, slong value) { ctx->options[i] = value; } ca_field_ptr _ca_ctx_get_field_const(ca_ctx_t ctx, calcium_func_code func); ca_field_ptr _ca_ctx_get_field_fx(ca_ctx_t ctx, calcium_func_code func, const ca_t x); ca_field_ptr _ca_ctx_get_field_fxy(ca_ctx_t ctx, calcium_func_code func, const ca_t x, const ca_t y); /* Numbers */ void ca_init(ca_t x, ca_ctx_t ctx); void ca_clear(ca_t x, ca_ctx_t ctx); void ca_swap(ca_t x, ca_t y, ca_ctx_t ctx); void _ca_make_field_element(ca_t x, ca_field_srcptr field, ca_ctx_t ctx); CA_INLINE void _ca_make_fmpq(ca_t x, ca_ctx_t ctx) { if (!CA_IS_QQ(x, ctx)) _ca_make_field_element(x, ctx->field_qq, ctx); } CA_INLINE void _ca_function_fx(ca_t res, calcium_func_code func, const ca_t x, ca_ctx_t ctx) { ca_field_srcptr field = _ca_ctx_get_field_fx(ctx, func, x); _ca_make_field_element(res, field, ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_FIELD_MCTX(field, ctx)); } CA_INLINE void _ca_function_fxy(ca_t res, calcium_func_code func, const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_srcptr field = _ca_ctx_get_field_fxy(ctx, func, x, y); _ca_make_field_element(res, field, ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_FIELD_MCTX(field, ctx)); } void ca_set(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_transfer(ca_t res, ca_ctx_t res_ctx, const ca_t src, ca_ctx_t src_ctx); void ca_zero(ca_t x, ca_ctx_t ctx); void ca_one(ca_t x, ca_ctx_t ctx); void ca_neg_one(ca_t x, ca_ctx_t ctx); void ca_set_si(ca_t x, slong v, ca_ctx_t ctx); void ca_set_ui(ca_t x, ulong v, ca_ctx_t ctx); void ca_set_fmpz(ca_t x, const fmpz_t v, ca_ctx_t ctx); void ca_set_fmpq(ca_t x, const fmpq_t v, ca_ctx_t ctx); void ca_set_d(ca_t res, double x, ca_ctx_t ctx); void ca_set_d_d(ca_t res, double x, double y, ca_ctx_t ctx); void ca_i(ca_t x, ca_ctx_t ctx); void ca_neg_i(ca_t x, ca_ctx_t ctx); void ca_pi(ca_t res, ca_ctx_t ctx); void ca_pi_i(ca_t res, ca_ctx_t ctx); void ca_euler(ca_t res, ca_ctx_t ctx); void ca_unknown(ca_t x, ca_ctx_t ctx); void ca_undefined(ca_t x, ca_ctx_t ctx); void ca_uinf(ca_t x, ca_ctx_t ctx); void ca_pos_inf(ca_t x, ca_ctx_t ctx); void ca_neg_inf(ca_t x, ca_ctx_t ctx); void ca_pos_i_inf(ca_t x, ca_ctx_t ctx); void ca_neg_i_inf(ca_t x, ca_ctx_t ctx); void ca_set_qqbar(ca_t res, const qqbar_t x, ca_ctx_t ctx); int ca_can_evaluate_qqbar(const ca_t x, ca_ctx_t ctx); int ca_get_qqbar(qqbar_t res, const ca_t x, ca_ctx_t ctx); int ca_get_fmpq(fmpq_t res, const ca_t x, ca_ctx_t ctx); int ca_get_fmpz(fmpz_t res, const ca_t x, ca_ctx_t ctx); /* Symbolic expressions */ #define CA_FEXPR_SERIALIZATION 1 void ca_get_fexpr(fexpr_t res, const ca_t x, ulong flags, ca_ctx_t ctx); int ca_set_fexpr(ca_t res, const fexpr_t expr, ca_ctx_t ctx); /* Printing */ #define CA_PRINT_N UWORD(1) #define CA_PRINT_REPR UWORD(2) #define CA_PRINT_FIELD UWORD(4) #define CA_PRINT_DIGITS UWORD(16) #define CA_PRINT_DEFAULT (CA_PRINT_N | CA_PRINT_REPR) #define CA_PRINT_DEBUG (CA_PRINT_N | CA_PRINT_REPR | CA_PRINT_FIELD) #ifdef FLINT_HAVE_FILE void ca_fprint(FILE * fp, const ca_t x, ca_ctx_t ctx); #endif void ca_print(const ca_t x, ca_ctx_t ctx); void ca_printn(const ca_t x, slong n, ca_ctx_t ctx); char * ca_get_str(const ca_t x, ca_ctx_t ctx); /* Random generation */ void ca_randtest_same_nf(ca_t res, flint_rand_t state, const ca_t x, slong bits, slong den_bits, ca_ctx_t ctx); void ca_randtest_rational(ca_t res, flint_rand_t state, slong bits, ca_ctx_t ctx); void ca_randtest(ca_t res, flint_rand_t state, slong depth, slong bits, ca_ctx_t ctx); void ca_randtest_special(ca_t res, flint_rand_t state, slong depth, slong bits, ca_ctx_t ctx); /* Representation properties */ CA_INLINE int ca_is_special(const ca_t x, ca_ctx_t ctx) { return CA_IS_SPECIAL(x); } CA_INLINE int ca_is_unknown(const ca_t x, ca_ctx_t ctx) { return CA_IS_UNKNOWN(x); } CA_INLINE int ca_is_qq_elem(const ca_t x, ca_ctx_t ctx) { return CA_IS_QQ(x, ctx); } CA_INLINE int ca_is_qq_elem_zero(const ca_t x, ca_ctx_t ctx) { return CA_IS_QQ(x, ctx) && fmpq_is_zero(CA_FMPQ(x)); } CA_INLINE int ca_is_qq_elem_one(const ca_t x, ca_ctx_t ctx) { return CA_IS_QQ(x, ctx) && fmpq_is_one(CA_FMPQ(x)); } CA_INLINE int ca_is_qq_elem_integer(const ca_t x, ca_ctx_t ctx) { return CA_IS_QQ(x, ctx) && fmpz_is_one(CA_FMPQ_DENREF(x)); } CA_INLINE int ca_is_nf_elem(const ca_t x, ca_ctx_t ctx) { return !CA_IS_SPECIAL(x) && CA_FIELD_IS_NF(CA_FIELD(x, ctx)); } CA_INLINE int ca_is_generic_elem(const ca_t x, ca_ctx_t ctx) { return !CA_IS_SPECIAL(x) && CA_FIELD_IS_GENERIC(CA_FIELD(x, ctx)); } int ca_is_cyclotomic_nf_elem(slong * p, ulong * q, const ca_t x, ca_ctx_t ctx); /* Value predicates and comparisons */ truth_t ca_is_zero_check_fast(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_number(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_zero(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_one(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_neg_one(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_i(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_neg_i(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_algebraic(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_rational(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_integer(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_real(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_negative_real(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_imaginary(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_undefined(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_infinity(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_uinf(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_signed_inf(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_pos_inf(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_neg_inf(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_pos_i_inf(const ca_t x, ca_ctx_t ctx); truth_t ca_check_is_neg_i_inf(const ca_t x, ca_ctx_t ctx); truth_t ca_check_equal(const ca_t x, const ca_t y, ca_ctx_t ctx); truth_t ca_check_lt(const ca_t x, const ca_t y, ca_ctx_t ctx); truth_t ca_check_le(const ca_t x, const ca_t y, ca_ctx_t ctx); truth_t ca_check_gt(const ca_t x, const ca_t y, ca_ctx_t ctx); truth_t ca_check_ge(const ca_t x, const ca_t y, ca_ctx_t ctx); int ca_equal_repr(const ca_t x, const ca_t y, ca_ctx_t ctx); int ca_cmp_repr(const ca_t x, const ca_t y, ca_ctx_t ctx); ulong ca_hash_repr(const ca_t x, ca_ctx_t ctx); /* Field structure operations */ void ca_merge_fields(ca_t resx, ca_t resy, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_condense_field(ca_t res, ca_ctx_t ctx); ca_ext_ptr ca_is_gen_as_ext(const ca_t x, ca_ctx_t ctx); /* Arithmetic */ /* todo: document */ void _ca_mpoly_q_reduce_ideal(fmpz_mpoly_q_t res, ca_field_srcptr field, ca_ctx_t ctx); void _ca_mpoly_q_simplify_fraction_ideal(fmpz_mpoly_q_t res, ca_field_srcptr field, ca_ctx_t ctx); void ca_neg(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_add_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx); void ca_add_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx); void ca_add_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx); void ca_add_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx); void ca_add(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_sub_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx); void ca_sub_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx); void ca_sub_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx); void ca_sub_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx); void ca_fmpq_sub(ca_t res, const fmpq_t x, const ca_t y, ca_ctx_t ctx); void ca_fmpz_sub(ca_t res, const fmpz_t x, const ca_t y, ca_ctx_t ctx); void ca_ui_sub(ca_t res, ulong x, const ca_t y, ca_ctx_t ctx); void ca_si_sub(ca_t res, slong x, const ca_t y, ca_ctx_t ctx); void ca_sub(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_mul_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx); void ca_mul_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx); void ca_mul_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx); void ca_mul_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx); void ca_mul(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_inv(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_fmpq_div(ca_t res, const fmpq_t x, const ca_t y, ca_ctx_t ctx); void ca_fmpz_div(ca_t res, const fmpz_t x, const ca_t y, ca_ctx_t ctx); void ca_ui_div(ca_t res, ulong x, const ca_t y, ca_ctx_t ctx); void ca_si_div(ca_t res, slong x, const ca_t y, ca_ctx_t ctx); void ca_div_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx); void ca_div_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx); void ca_div_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx); void ca_div_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx); void ca_div(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_dot(ca_t res, const ca_t initial, int subtract, ca_srcptr x, slong xstep, ca_srcptr y, slong ystep, slong len, ca_ctx_t ctx); void ca_fmpz_poly_evaluate(ca_t res, const fmpz_poly_t poly, const ca_t x, ca_ctx_t ctx); void ca_fmpq_poly_evaluate(ca_t res, const fmpq_poly_t poly, const ca_t x, ca_ctx_t ctx); void ca_fmpz_mpoly_evaluate_horner(ca_t res, const fmpz_mpoly_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx); void ca_fmpz_mpoly_evaluate_iter(ca_t res, const fmpz_mpoly_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx); void ca_fmpz_mpoly_evaluate(ca_t res, const fmpz_mpoly_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx); void ca_fmpz_mpoly_q_evaluate(ca_t res, const fmpz_mpoly_q_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx); void ca_fmpz_mpoly_q_evaluate_no_division_by_zero(ca_t res, const fmpz_mpoly_q_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx); void ca_inv_no_division_by_zero(ca_t res, const ca_t x, ca_ctx_t ctx); /* Powers and roots */ CA_INLINE void ca_sqr(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_mul(res, x, x, ctx); } void ca_pow_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx); void ca_pow_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx); void ca_pow_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx); void ca_pow_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx); void ca_pow(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_pow_si_arithmetic(ca_t res, const ca_t x, slong n, ca_ctx_t ctx); void ca_sqrt_inert(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_sqrt_nofactor(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_sqrt_factor(ca_t res, const ca_t x, ulong flags, ca_ctx_t ctx); void ca_sqrt(ca_t res, const ca_t x, ca_ctx_t ctx); CA_INLINE void ca_sqrt_ui(ca_t res, ulong n, ca_ctx_t ctx) { ca_set_ui(res, n, ctx); ca_sqrt(res, res, ctx); } /* Complex parts */ void ca_conj_shallow(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_conj_deep(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_conj(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_abs(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_sgn(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_csgn(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_arg(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_re(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_im(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_floor(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_ceil(ca_t res, const ca_t x, ca_ctx_t ctx); /* Elementary functions */ void ca_exp(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_log(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_sin_cos_exponential(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx); void ca_sin_cos_direct_exp_hack(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx); void ca_sin_cos_direct(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx); void ca_sin_cos_tangent(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx); void ca_sin_cos(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx); void ca_sin(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_cos(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_tan_sine_cosine(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_tan_exponential(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_tan_direct(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_tan(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_cot(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_atan_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_atan_direct(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_atan(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_asin_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_asin_direct(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_asin(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_acos_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_acos_direct(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_acos(ca_t res, const ca_t x, ca_ctx_t ctx); /* Special functions */ void ca_erf(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_erfc(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_erfi(ca_t res, const ca_t x, ca_ctx_t ctx); void ca_gamma(ca_t res, const ca_t x, ca_ctx_t ctx); /* Numerical evaluation */ void ca_get_acb_raw(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx); void ca_get_acb(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx); void ca_get_acb_accurate_parts(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx); char * ca_get_decimal_str(const ca_t x, slong digits, ulong flags, ca_ctx_t ctx); /* Factorisation */ #define CA_FACTOR_ZZ_NONE 0 #define CA_FACTOR_ZZ_SMOOTH 2 #define CA_FACTOR_ZZ_FULL 4 #define CA_FACTOR_POLY_NONE 0 #define CA_FACTOR_POLY_CONTENT 64 #define CA_FACTOR_POLY_SQF 128 #define CA_FACTOR_POLY_FULL 256 typedef struct { ca_ptr base; ca_ptr exp; slong length; slong alloc; } ca_factor_struct; typedef ca_factor_struct ca_factor_t[1]; void ca_factor_init(ca_factor_t fac, ca_ctx_t ctx); void ca_factor_clear(ca_factor_t fac, ca_ctx_t ctx); void ca_factor_one(ca_factor_t fac, ca_ctx_t ctx); void ca_factor_print(const ca_factor_t fac, ca_ctx_t ctx); void ca_factor_insert(ca_factor_t fac, const ca_t base, const ca_t exp, ca_ctx_t ctx); void ca_factor_get_ca(ca_t res, const ca_factor_t fac, ca_ctx_t ctx); void ca_factor(ca_factor_t res, const ca_t x, ulong flags, ca_ctx_t ctx); /* Test helpers */ #define CA_TEST_PROPERTY(f, s, x, ctx, expected) \ do { \ truth_t t; \ t = f(x, ctx); \ if (t != expected) \ { \ flint_printf("FAIL\n"); \ flint_printf("%s\n\n", s); \ flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); \ flint_printf("got = "); truth_print(t); flint_printf("\n\n"); \ flint_printf("expected = "); truth_print(expected); flint_printf("\n\n"); \ flint_abort(); \ } \ } while (0) \ #ifdef __cplusplus } #endif #endif flint-3.1.3/src/ca/000077500000000000000000000000001461254215100140055ustar00rootroot00000000000000flint-3.1.3/src/ca/abs.c000066400000000000000000000023121461254215100147140ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_abs(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_INF(x)) ca_pos_inf(res, ctx); else ca_set(res, x, ctx); } else if (CA_IS_QQ(x, ctx)) { if (fmpz_sgn(fmpq_numref(CA_FMPQ(x))) >= 0) ca_set(res, x, ctx); else ca_neg(res, x, ctx); } else { qqbar_t t; qqbar_init(t); if (ca_get_qqbar(t, x, ctx)) { qqbar_abs(t, t); if (qqbar_within_limits(t, ctx->options[CA_OPT_QQBAR_DEG_LIMIT], 0)) ca_set_qqbar(res, t, ctx); else _ca_function_fx(res, CA_Abs, x, ctx); } else { _ca_function_fx(res, CA_Abs, x, ctx); } qqbar_clear(t); } } flint-3.1.3/src/ca/add.c000066400000000000000000000323401461254215100147030ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void _ca_mpoly_q_reduce_ideal(fmpz_mpoly_q_t res, ca_field_srcptr field, ca_ctx_t ctx) { slong i, n; n = CA_FIELD_IDEAL_LENGTH(field); /* todo: optimizations */ if (n > 0) { fmpz_mpoly_struct ** I; fmpz_mpoly_struct ** Q; fmpq_t scale; I = flint_malloc(sizeof(fmpz_mpoly_struct *) * n); for (i = 0; i < n; i++) I[i] = CA_FIELD_IDEAL_ELEM(field, i); Q = flint_malloc(sizeof(fmpz_mpoly_struct *) * n); for (i = 0; i < n; i++) { Q[i] = flint_malloc(sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(Q[i], CA_FIELD_MCTX(field, ctx)); } fmpq_init(scale); if (0) { fmpz_mpoly_quasidivrem_ideal(fmpq_denref(scale), Q, fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(res), I, n, CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_quasidivrem_ideal(fmpq_numref(scale), Q, fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(res), I, n, CA_FIELD_MCTX(field, ctx)); fmpq_canonicalise(scale); fmpz_mpoly_q_canonicalise(res, CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_q_mul_fmpq(res, res, scale, CA_FIELD_MCTX(field, ctx)); } else { fmpz_mpoly_t T; int changed = 0; fmpz_mpoly_init(T, CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_quasidivrem_ideal(fmpq_denref(scale), Q, T, fmpz_mpoly_q_numref(res), I, n, CA_FIELD_MCTX(field, ctx)); changed = !fmpz_mpoly_equal(T, fmpz_mpoly_q_numref(res), CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_swap(T, fmpz_mpoly_q_numref(res), CA_FIELD_MCTX(field, ctx)); /* todo: special case const den */ fmpz_mpoly_quasidivrem_ideal(fmpq_numref(scale), Q, T, fmpz_mpoly_q_denref(res), I, n, CA_FIELD_MCTX(field, ctx)); changed = changed || !fmpz_mpoly_equal(T, fmpz_mpoly_q_denref(res), CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_swap(T, fmpz_mpoly_q_denref(res), CA_FIELD_MCTX(field, ctx)); if (changed) { fmpz_mpoly_q_canonicalise(res, CA_FIELD_MCTX(field, ctx)); } if (!fmpq_is_one(scale)) { fmpq_canonicalise(scale); fmpz_mpoly_q_mul_fmpq(res, res, scale, CA_FIELD_MCTX(field, ctx)); } #if 0 if (!fmpz_mpoly_q_is_canonical(res, CA_FIELD_MCTX(field, ctx))) { flint_throw(FLINT_ERROR, "not canonical!\n"); } #endif fmpz_mpoly_clear(T, CA_FIELD_MCTX(field, ctx)); } for (i = 0; i < n; i++) { fmpz_mpoly_clear(Q[i], CA_FIELD_MCTX(field, ctx)); flint_free(Q[i]); } flint_free(Q); flint_free(I); fmpq_clear(scale); } } /* This is currently very simplistic: just try to move monomial factors in the denominator to the numerator. */ void _ca_mpoly_q_simplify_fraction_ideal(fmpz_mpoly_q_t res, ca_field_srcptr field, ca_ctx_t ctx) { slong i, ideal_len; int changed; fmpz_mpoly_ctx_struct * mctx; fmpz_mpoly_t t, u, g, q; fmpz_mpoly_q_t f; ideal_len = CA_FIELD_IDEAL_LENGTH(field); if (ideal_len == 0) return; mctx = CA_FIELD_MCTX(field, ctx); if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(res), mctx)) return; fmpz_mpoly_init(t, mctx); while (1) { changed = 0; /* todo: only need monomial content? there should be a fmpz_mpoly_monomial_content */ fmpz_mpoly_term_content(t, fmpz_mpoly_q_denref(res), mctx); if (fmpz_mpoly_is_fmpz(t, mctx)) break; fmpz_one(t->coeffs); fmpz_mpoly_init(u, mctx); fmpz_mpoly_init(g, mctx); fmpz_mpoly_init(q, mctx); fmpz_mpoly_q_init(f, mctx); for (i = 0; i < ideal_len; i++) { /* todo: error checks */ fmpz_mpoly_get_term_monomial(u, CA_FIELD_IDEAL_ELEM(field, i), 0, mctx); fmpz_mpoly_gcd(g, t, u, mctx); if (fmpz_mpoly_is_fmpz(g, mctx)) continue; _fmpz_mpoly_q_mpoly_divexact(q, u, g, mctx); fmpz_mpoly_mul(fmpz_mpoly_q_numref(f), fmpz_mpoly_q_numref(res), q, mctx); fmpz_mpoly_mul(fmpz_mpoly_q_denref(f), fmpz_mpoly_q_denref(res), q, mctx); _ca_mpoly_q_reduce_ideal(f, field, ctx); if (fmpz_mpoly_cmp(fmpz_mpoly_q_denref(f), fmpz_mpoly_q_denref(res), mctx) < 0) { changed = 1; fmpz_mpoly_q_swap(res, f, mctx); break; } } fmpz_mpoly_clear(u, mctx); fmpz_mpoly_clear(g, mctx); fmpz_mpoly_clear(q, mctx); fmpz_mpoly_q_clear(f, mctx); if (!changed) break; } fmpz_mpoly_clear(t, mctx); } void ca_add_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) { ca_field_srcptr field; if (fmpq_is_zero(y) || CA_IS_SPECIAL(x)) { ca_set(res, x, ctx); return; } if (CA_IS_QQ(x, ctx)) { _ca_make_fmpq(res, ctx); fmpq_add(CA_FMPQ(res), CA_FMPQ(x), y); } else { field = CA_FIELD(x, ctx); _ca_make_field_element(res, field, ctx); if (CA_FIELD_IS_NF(field)) nf_elem_add_fmpq(CA_NF_ELEM(res), CA_NF_ELEM(x), y, CA_FIELD_NF(field)); else fmpz_mpoly_q_add_fmpq(CA_MPOLY_Q(res), CA_MPOLY_Q(x), y, CA_FIELD_MCTX(field, ctx)); } } void ca_add_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) { fmpq_t t; *fmpq_numref(t) = *y; *fmpq_denref(t) = 1; ca_add_fmpq(res, x, t, ctx); } void ca_add_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, y); ca_add_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_add_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, y); ca_add_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_add(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_srcptr xfield, yfield, zfield; xfield = CA_FIELD(x, ctx); yfield = CA_FIELD(y, ctx); if (CA_IS_QQ(x, ctx) && (xfield == yfield)) { _ca_make_fmpq(res, ctx); fmpq_add(CA_FMPQ(res), CA_FMPQ(x), CA_FMPQ(y)); return; } if (CA_IS_QQ(y, ctx)) { if (res == y) { fmpq_t t; fmpq_init(t); fmpq_set(t, CA_FMPQ(y)); ca_add_fmpq(res, x, t, ctx); fmpq_clear(t); } else { ca_add_fmpq(res, x, CA_FMPQ(y), ctx); } return; } if (CA_IS_QQ(x, ctx)) { if (res == x) { fmpq_t t; fmpq_init(t); fmpq_set(t, CA_FMPQ(x)); ca_add_fmpq(res, y, t, ctx); fmpq_clear(t); } else { ca_add_fmpq(res, y, CA_FMPQ(x), ctx); } return; } if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { if (CA_IS_UNDEFINED(x) || CA_IS_UNDEFINED(y)) { ca_undefined(res, ctx); return; } if (CA_IS_UNKNOWN(x) || CA_IS_UNKNOWN(y)) { ca_unknown(res, ctx); return; } if (!CA_IS_SPECIAL(y)) { ca_set(res, x, ctx); return; } if (!CA_IS_SPECIAL(x)) { ca_set(res, y, ctx); return; } if (CA_IS_INF(x) && CA_IS_INF(y)) { if (CA_IS_SIGNED_INF(x) && CA_IS_SIGNED_INF(y)) { truth_t eq = ca_check_equal(x, y, ctx); if (eq == T_TRUE) /* sum of infs with same sign */ ca_set(res, x, ctx); else if (eq == T_FALSE) /* sum of infs with different sign */ ca_undefined(res, ctx); else ca_unknown(res, ctx); return; } else { ca_undefined(res, ctx); } return; } ca_unknown(res, ctx); return; } /* In-field operation. */ if (xfield == yfield) { zfield = xfield; _ca_make_field_element(res, zfield, ctx); if (CA_FIELD_IS_NF(zfield)) { nf_elem_add(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_NF_ELEM(y), CA_FIELD_NF(zfield)); } else { fmpz_mpoly_q_add(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_MPOLY_Q(y), CA_FIELD_MCTX(zfield, ctx)); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), zfield, ctx); _ca_mpoly_q_simplify_fraction_ideal(CA_MPOLY_Q(res), zfield, ctx); } ca_condense_field(res, ctx); return; } /* Coerce to a common field. */ { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_merge_fields(t, u, x, y, ctx); ca_add(res, t, u, ctx); ca_condense_field(res, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } } void ca_sub_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) { ca_field_srcptr field; if (fmpq_is_zero(y) || CA_IS_SPECIAL(x)) { ca_set(res, x, ctx); return; } if (CA_IS_QQ(x, ctx)) { _ca_make_fmpq(res, ctx); fmpq_sub(CA_FMPQ(res), CA_FMPQ(x), y); } else { field = CA_FIELD(x, ctx); _ca_make_field_element(res, field, ctx); if (CA_FIELD_IS_NF(field)) nf_elem_sub_fmpq(CA_NF_ELEM(res), CA_NF_ELEM(x), y, CA_FIELD_NF(field)); else fmpz_mpoly_q_sub_fmpq(CA_MPOLY_Q(res), CA_MPOLY_Q(x), y, CA_FIELD_MCTX(field, ctx)); } } void ca_sub(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_srcptr xfield, yfield, zfield; xfield = CA_FIELD(x, ctx); yfield = CA_FIELD(y, ctx); if (CA_IS_QQ(x, ctx) && (xfield == yfield)) { _ca_make_fmpq(res, ctx); fmpq_sub(CA_FMPQ(res), CA_FMPQ(x), CA_FMPQ(y)); return; } if (CA_IS_QQ(y, ctx)) { if (res == y) { fmpq_t t; fmpq_init(t); fmpq_set(t, CA_FMPQ(y)); ca_sub_fmpq(res, x, t, ctx); fmpq_clear(t); } else { ca_sub_fmpq(res, x, CA_FMPQ(y), ctx); } return; } if (CA_IS_QQ(x, ctx)) { if (res == x) { fmpq_t t; fmpq_init(t); fmpq_set(t, CA_FMPQ(x)); ca_sub_fmpq(res, y, t, ctx); ca_neg(res, res, ctx); fmpq_clear(t); } else { ca_sub_fmpq(res, y, CA_FMPQ(x), ctx); ca_neg(res, res, ctx); } return; } if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { ca_t t; ca_init(t, ctx); ca_neg(t, y, ctx); ca_add(res, x, t, ctx); ca_clear(t, ctx); return; } /* In-field operation. */ if (xfield == yfield) { zfield = xfield; _ca_make_field_element(res, zfield, ctx); if (CA_FIELD_IS_NF(zfield)) { nf_elem_sub(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_NF_ELEM(y), CA_FIELD_NF(zfield)); } else { fmpz_mpoly_q_sub(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_MPOLY_Q(y), CA_FIELD_MCTX(zfield, ctx)); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), zfield, ctx); _ca_mpoly_q_simplify_fraction_ideal(CA_MPOLY_Q(res), zfield, ctx); } ca_condense_field(res, ctx); return; } /* Coerce to a common field. */ { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_merge_fields(t, u, x, y, ctx); ca_sub(res, t, u, ctx); ca_condense_field(res, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } } void ca_sub_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) { fmpq_t t; *fmpq_numref(t) = *y; *fmpq_denref(t) = 1; ca_sub_fmpq(res, x, t, ctx); } void ca_sub_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, y); ca_sub_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_sub_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, y); ca_sub_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_fmpq_sub(ca_t res, const fmpq_t x, const ca_t y, ca_ctx_t ctx) { ca_sub_fmpq(res, y, x, ctx); ca_neg(res, res, ctx); } void ca_fmpz_sub(ca_t res, const fmpz_t x, const ca_t y, ca_ctx_t ctx) { fmpq_t t; *fmpq_numref(t) = *x; *fmpq_denref(t) = 1; ca_fmpq_sub(res, t, y, ctx); } void ca_ui_sub(ca_t res, ulong x, const ca_t y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, x); ca_fmpz_sub(res, t, y, ctx); fmpz_clear(t); } void ca_si_sub(ca_t res, slong x, const ca_t y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, x); ca_fmpz_sub(res, t, y, ctx); fmpz_clear(t); } flint-3.1.3/src/ca/arg.c000066400000000000000000000027431461254215100147300ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_arg(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { ca_sgn(res, x, ctx); ca_arg(res, res, ctx); } else if (CA_IS_UNKNOWN(x)) { ca_unknown(res, ctx); } else { ca_undefined(res, ctx); } } else if (CA_IS_QQ(x, ctx)) { if (fmpz_sgn(CA_FMPQ_NUMREF(x)) >= 0) { ca_zero(res, ctx); } else { ca_pi(res, ctx); ca_neg(res, res, ctx); } } else { ca_t s; qqbar_t t; slong p; ulong q; ca_init(s, ctx); qqbar_init(t); ca_sgn(s, x, ctx); if (ca_get_qqbar(t, s, ctx) && qqbar_log_pi_i(&p, &q, t)) { ca_pi(res, ctx); ca_mul_si(res, res, p, ctx); ca_div_ui(res, res, q, ctx); } else { _ca_function_fx(res, CA_Arg, x, ctx); } ca_clear(s, ctx); qqbar_clear(t); } } flint-3.1.3/src/ca/asin.c000066400000000000000000000066111461254215100151070ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_asin_special(ca_t res, const ca_t x, ca_ctx_t ctx) { if (ca_check_is_signed_inf(x, ctx) == T_TRUE) { ca_t s; ca_init(s, ctx); /* -i*csgn(i*z)*inf */ ca_i(s, ctx); ca_mul(res, x, s, ctx); ca_csgn(res, res, ctx); ca_mul(res, res, s, ctx); ca_neg(res, res, ctx); ca_pos_inf(s, ctx); ca_mul(res, res, s, ctx); ca_clear(s, ctx); return; } if (ca_check_is_uinf(x, ctx) == T_TRUE || ca_check_is_undefined(x, ctx) == T_TRUE) { ca_set(res, x, ctx); return; } ca_unknown(res, ctx); return; } static int _ca_asin_rational(ca_t res, const ca_t x, ca_ctx_t ctx) { qqbar_t v; slong p; ulong q; int success; qqbar_init(v); /* todo: rule out non-sines more quickly */ if (ca_get_qqbar(v, x, ctx) && qqbar_asin_pi(&p, &q, v)) { ca_pi(res, ctx); ca_mul_si(res, res, p, ctx); ca_div_ui(res, res, q, ctx); success = 1; } else { success = 0; } qqbar_clear(v); return success; } void ca_asin_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t, u; if (CA_IS_SPECIAL(x)) { ca_asin_special(res, x, ctx); return; } if (_ca_asin_rational(res, x, ctx)) return; /* asin(x) = -i log(ix + sqrt(1-x^2)) */ ca_init(t, ctx); ca_init(u, ctx); ca_sqr(t, x, ctx); ca_ui_sub(t, 1, t, ctx); ca_sqrt(t, t, ctx); ca_i(u, ctx); ca_mul(u, u, x, ctx); ca_add(t, t, u, ctx); ca_log(t, t, ctx); ca_i(u, ctx); ca_mul(res, t, u, ctx); ca_neg(res, res, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } void ca_asin_direct(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { ca_asin_special(res, x, ctx); return; } if (_ca_asin_rational(res, x, ctx)) return; /* todo: csgn normalization, reflection...? */ _ca_function_fx(res, CA_Asin, x, ctx); } void ca_asin(ca_t res, const ca_t x, ca_ctx_t ctx) { if (ctx->options[CA_OPT_TRIG_FORM] == CA_TRIG_EXPONENTIAL) { ca_asin_logarithm(res, x, ctx); } /* todo: else if (ctx->options[CA_OPT_TRIG_FORM] == CA_TRIG_TANGENT) { ca_asin_arctangent(res, x, ctx); } */ else { ca_asin_direct(res, x, ctx); } } void ca_acos_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_pi(t, ctx); ca_div_ui(t, t, 2, ctx); ca_asin_logarithm(res, x, ctx); ca_sub(res, t, res, ctx); ca_clear(t, ctx); } void ca_acos_direct(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_pi(t, ctx); ca_div_ui(t, t, 2, ctx); ca_asin_direct(res, x, ctx); ca_sub(res, t, res, ctx); ca_clear(t, ctx); } void ca_acos(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_pi(t, ctx); ca_div_ui(t, t, 2, ctx); ca_asin(res, x, ctx); ca_sub(res, t, res, ctx); ca_clear(t, ctx); } flint-3.1.3/src/ca/atan.c000066400000000000000000000102021461254215100150670ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_atan_special(ca_t res, const ca_t x, ca_ctx_t ctx) { if (ca_check_is_signed_inf(x, ctx) == T_TRUE) { ca_t s; ca_init(s, ctx); ca_csgn(s, x, ctx); if (ca_check_is_one(s, ctx) == T_TRUE) { ca_pi(res, ctx); ca_div_ui(res, res, 2, ctx); } else if (ca_check_is_neg_one(s, ctx) == T_TRUE) { ca_pi(res, ctx); ca_div_ui(res, res, 2, ctx); ca_neg(res, res, ctx); } else { ca_unknown(res, ctx); } ca_clear(s, ctx); return; } if (ca_check_is_uinf(x, ctx) == T_TRUE || ca_check_is_undefined(x, ctx) == T_TRUE) { ca_undefined(res, ctx); return; } ca_unknown(res, ctx); return; } static int _ca_atan_rational(ca_t res, const ca_t x, ca_ctx_t ctx) { qqbar_t v; slong p; ulong q; int success; qqbar_init(v); /* todo: rule out non-tangents more quickly */ if (ca_get_qqbar(v, x, ctx) && qqbar_atan_pi(&p, &q, v)) { ca_pi(res, ctx); ca_mul_si(res, res, p, ctx); ca_div_ui(res, res, q, ctx); success = 1; } else { success = 0; } qqbar_clear(v); return success; } void ca_atan_logarithm(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t, u, v; acb_t z; arb_t one, minus_one; if (CA_IS_SPECIAL(x)) { ca_atan_special(res, x, ctx); return; } if (_ca_atan_rational(res, x, ctx)) return; acb_init(z); arb_init(one); arb_init(minus_one); ca_init(t, ctx); ca_init(u, ctx); ca_init(v, ctx); ca_i(t, ctx); ca_mul(u, x, t, ctx); /* v = 1 + i x */ ca_add_ui(v, u, 1, ctx); /* res = 1 - i x */ ca_sub_ui(res, u, 1, ctx); ca_neg(res, res, ctx); ca_get_acb(z, x, ctx->options[CA_OPT_LOW_PREC], ctx); arb_set_si(one, 1); arb_set_si(minus_one, -1); if (arb_lt(acb_imagref(z), one)) { /* atan(x) = i/2 log((1-ix)/(1+ix)) */ ca_div(res, res, v, ctx); ca_log(res, res, ctx); ca_mul(res, res, t, ctx); ca_div_ui(res, res, 2, ctx); } else if (arb_gt(acb_imagref(z), minus_one)) { /* atan(x) = -i/2 log((1+ix)/(1-ix)) */ ca_div(res, v, res, ctx); ca_log(res, res, ctx); ca_mul(res, res, t, ctx); ca_div_ui(res, res, 2, ctx); ca_neg(res, res, ctx); } else { /* atan(x) = i/2 (log(1-ix) - log(1+ix)) */ ca_log(res, res, ctx); ca_log(v, v, ctx); ca_sub(res, res, v, ctx); ca_mul(res, res, t, ctx); ca_div_ui(res, res, 2, ctx); } ca_clear(t, ctx); ca_clear(u, ctx); ca_clear(v, ctx); acb_clear(z); arb_clear(one); arb_clear(minus_one); } void ca_atan_direct(ca_t res, const ca_t x, ca_ctx_t ctx) { truth_t pole; if (CA_IS_SPECIAL(x)) { ca_atan_special(res, x, ctx); return; } if (_ca_atan_rational(res, x, ctx)) return; pole = ca_check_is_i(x, ctx); if (pole == T_TRUE) { ca_pos_i_inf(res, ctx); return; } if (pole == T_UNKNOWN) { ca_unknown(res, ctx); return; } pole = ca_check_is_neg_i(x, ctx); if (pole == T_TRUE) { ca_neg_i_inf(res, ctx); return; } if (pole == T_UNKNOWN) { ca_unknown(res, ctx); return; } /* todo: csgn normalization, reflection...? */ _ca_function_fx(res, CA_Atan, x, ctx); } void ca_atan(ca_t res, const ca_t x, ca_ctx_t ctx) { if (ctx->options[CA_OPT_TRIG_FORM] == CA_TRIG_EXPONENTIAL) { ca_atan_logarithm(res, x, ctx); } else { ca_atan_direct(res, x, ctx); } } flint-3.1.3/src/ca/can_evaluate_qqbar.c000066400000000000000000000037241461254215100177740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" int ca_ext_can_evaluate_qqbar(const ca_ext_t x, ca_ctx_t ctx) { if (CA_EXT_IS_QQBAR(x)) return 1; if (CA_EXT_HEAD(x) == CA_Sqrt || CA_EXT_HEAD(x) == CA_Sign || CA_EXT_HEAD(x) == CA_Abs || CA_EXT_HEAD(x) == CA_Re || CA_EXT_HEAD(x) == CA_Im || CA_EXT_HEAD(x) == CA_Conjugate || CA_EXT_HEAD(x) == CA_Floor || CA_EXT_HEAD(x) == CA_Ceil) return ca_can_evaluate_qqbar(CA_EXT_FUNC_ARGS(x), ctx); if (CA_EXT_HEAD(x) == CA_Pow) return ca_can_evaluate_qqbar(CA_EXT_FUNC_ARGS(x), ctx) && CA_IS_QQ(CA_EXT_FUNC_ARGS(x) + 1, ctx); return 0; } int ca_can_evaluate_qqbar(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { return 0; } else if (CA_IS_QQ(x, ctx)) { return 1; } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { return 1; } else { slong nvars, i; int res; int * used; nvars = CA_FIELD_LENGTH(CA_FIELD(x, ctx)); used = flint_calloc(nvars, sizeof(int)); fmpz_mpoly_q_used_vars(used, CA_MPOLY_Q(x), CA_FIELD_MCTX(CA_FIELD(x, ctx), ctx)); res = 1; /* todo: exclude extension numbers that are not actually used */ for (i = 0; i < nvars; i++) { if (used[i]) { if (!ca_ext_can_evaluate_qqbar(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i), ctx)) { res = 0; break; } } } flint_free(used); return res; } } flint-3.1.3/src/ca/ceil.c000066400000000000000000000040141461254215100150640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_ceil(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_UNKNOWN(x)) ca_unknown(res, ctx); else ca_undefined(res, ctx); return; } if (CA_IS_QQ(x, ctx)) { fmpz_t t; fmpz_init(t); fmpz_cdiv_q(t, CA_FMPQ_NUMREF(x), CA_FMPQ_DENREF(x)); ca_set_fmpz(res, t, ctx); fmpz_clear(t); return; } { slong prec, prec_limit; acb_t v; mag_t m; fmpz_t n; int success = 0; acb_init(v); mag_init(m); fmpz_init(n); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && !success; prec *= 2) { ca_get_acb_raw(v, x, prec, ctx); arb_get_mag(m, acb_realref(v)); if (arb_is_finite(acb_imagref(v)) && mag_cmp_2exp_si(m, prec_limit) <= 0) { arb_ceil(acb_realref(v), acb_realref(v), prec); if (arb_get_unique_fmpz(n, acb_realref(v))) { ca_set_fmpz(res, n, ctx); success = 1; break; } } arb_get_mag_lower(m, acb_realref(v)); if (mag_cmp_2exp_si(m, prec_limit) > 0) break; } acb_clear(v); mag_clear(m); fmpz_clear(n); if (success) return; } _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Ceil, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/check_equal.c000066400000000000000000000066361461254215100164300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_equal(const ca_t x, const ca_t y, ca_ctx_t ctx) { acb_t u, v; ca_t t; truth_t res; truth_t x_alg, y_alg; slong prec; if (CA_IS_QQ(x, ctx) && CA_IS_QQ(y, ctx)) { return fmpq_equal(CA_FMPQ(x), CA_FMPQ(y)) ? T_TRUE : T_FALSE; } if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { if (CA_IS_UNKNOWN(x) || CA_IS_UNKNOWN(y)) return T_UNKNOWN; if (CA_IS_SIGNED_INF(x) && CA_IS_SIGNED_INF(y)) { ca_t xsign, ysign; *xsign = *x; *ysign = *y; xsign->field &= ~CA_SPECIAL; ysign->field &= ~CA_SPECIAL; return ca_check_equal(xsign, ysign, ctx); } if (x->field == y->field) return T_TRUE; else return T_FALSE; } if (ca_equal_repr(x, y, ctx)) return T_TRUE; /* same algebraic number field ==> sufficient to compare representation */ if (x->field == y->field && CA_FIELD_IS_NF(CA_FIELD(x, ctx))) return T_FALSE; /* Rational number field elements *should* have been demoted to QQ automatically, but let's do a comparison as a precaution. */ if (CA_FIELD_IS_NF(CA_FIELD(x, ctx)) && CA_IS_QQ(y, ctx)) return nf_elem_equal_fmpq(CA_NF_ELEM(x), CA_FMPQ(y), CA_FIELD_NF(CA_FIELD(x, ctx))) ? T_TRUE : T_FALSE; if (CA_FIELD_IS_NF(CA_FIELD(y, ctx)) && CA_IS_QQ(x, ctx)) return nf_elem_equal_fmpq(CA_NF_ELEM(y), CA_FMPQ(x), CA_FIELD_NF(CA_FIELD(y, ctx))) ? T_TRUE : T_FALSE; res = T_UNKNOWN; acb_init(u); acb_init(v); /* for (prec = 64; (prec <= ctx->options[CA_OPT_PREC_LIMIT]) && (res == T_UNKNOWN); prec *= 2) */ prec = 64; { ca_get_acb_raw(u, x, prec, ctx); ca_get_acb_raw(v, y, prec, ctx); if (!acb_overlaps(u, v)) { res = T_FALSE; } } acb_clear(u); acb_clear(v); x_alg = ca_check_is_algebraic(x, ctx); y_alg = ca_check_is_algebraic(y, ctx); if ((x_alg == T_TRUE && y_alg == T_FALSE) || (x_alg == T_FALSE && y_alg == T_TRUE)) return T_FALSE; /* todo: try qqbar computation */ /* we may want to do this selectively; in some cases cancellation in computing x-y will be helpful; in other cases, subtracting the terms will make life more difficult */ if (0 && x_alg == T_TRUE && y_alg == T_TRUE) { /* ... qqbar_t a, b; qqbar_init(a); qqbar_init(b); if (ca_get_qqbar(a, x, ctx)) { if (ca_get_qqbar(b, y, ctx)) { int eq = qqbar_equal(a, b); qqbar_clear(a); qqbar_clear(b); return eq ? T_TRUE : T_FALSE; } } qqbar_clear(a); qqbar_clear(b); */ } if (res == T_UNKNOWN) { /* check_is_zero may have additional heuristics */ ca_init(t, ctx); ca_sub(t, x, y, ctx); res = ca_check_is_zero(t, ctx); ca_clear(t, ctx); } return res; } flint-3.1.3/src/ca/check_ge.c000066400000000000000000000166421461254215100157120ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #define CMP_UNDEFINED -2 #define CMP_UNKNOWN -3 int _ca_cmp(const ca_t x, const ca_t y, ca_ctx_t ctx) { acb_t v, w; truth_t x_real, y_real; slong prec, prec_limit; int result; if (CA_IS_QQ(x, ctx) && CA_IS_QQ(y, ctx)) { result = fmpq_cmp(CA_FMPQ(x), CA_FMPQ(y)); if (result < 0) result = -1; if (result > 0) result = 1; return result; } if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { if (ca_check_is_pos_inf(x, ctx) == T_TRUE) { if (ca_check_is_pos_inf(y, ctx) == T_TRUE) return 0; if (ca_check_is_neg_inf(y, ctx) == T_TRUE) return 1; y_real = ca_check_is_real(y, ctx); if (y_real == T_TRUE) return 1; if (y_real == T_FALSE) return CMP_UNDEFINED; return CMP_UNKNOWN; } if (ca_check_is_neg_inf(x, ctx) == T_TRUE) { if (ca_check_is_neg_inf(y, ctx) == T_TRUE) return 0; if (ca_check_is_pos_inf(y, ctx) == T_TRUE) return -1; y_real = ca_check_is_real(y, ctx); if (y_real == T_TRUE) return -1; if (y_real == T_FALSE) return CMP_UNDEFINED; return CMP_UNKNOWN; } if (ca_check_is_pos_inf(y, ctx) == T_TRUE) { if (ca_check_is_pos_inf(x, ctx) == T_TRUE) return 0; if (ca_check_is_neg_inf(x, ctx) == T_TRUE) return -1; x_real = ca_check_is_real(x, ctx); if (x_real == T_TRUE) return -1; if (x_real == T_FALSE) return CMP_UNDEFINED; return CMP_UNKNOWN; } if (ca_check_is_neg_inf(y, ctx) == T_TRUE) { if (ca_check_is_neg_inf(x, ctx) == T_TRUE) return 0; if (ca_check_is_pos_inf(x, ctx) == T_TRUE) return 1; x_real = ca_check_is_real(x, ctx); if (x_real == T_TRUE) return 1; if (x_real == T_FALSE) return CMP_UNDEFINED; return CMP_UNKNOWN; } /* Not comparable */ if (ca_check_is_undefined(x, ctx) == T_TRUE || ca_check_is_undefined(y, ctx) == T_TRUE || ca_check_is_uinf(x, ctx) == T_TRUE || ca_check_is_uinf(y, ctx) == T_TRUE || (ca_check_is_signed_inf(x, ctx) == T_TRUE && ca_check_is_pos_inf(x, ctx) == T_FALSE && ca_check_is_neg_inf(x, ctx) == T_FALSE) || (ca_check_is_signed_inf(y, ctx) == T_TRUE && ca_check_is_pos_inf(y, ctx) == T_FALSE && ca_check_is_neg_inf(y, ctx) == T_FALSE) || (ca_check_is_number(x, ctx) == T_TRUE && ca_check_is_real(x, ctx) == T_FALSE) || (ca_check_is_number(y, ctx) == T_TRUE && ca_check_is_real(y, ctx) == T_FALSE)) { return CMP_UNDEFINED; } return CMP_UNKNOWN; } result = CMP_UNKNOWN; x_real = y_real = T_UNKNOWN; acb_init(v); acb_init(w); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && (result == CMP_UNKNOWN); prec *= 2) { ca_get_acb_raw(v, x, prec, ctx); ca_get_acb_raw(w, y, prec, ctx); if (arb_is_zero(acb_imagref(v))) x_real = T_TRUE; else if (!arb_contains_zero(acb_imagref(v))) x_real = T_FALSE; if (arb_is_zero(acb_imagref(w))) y_real = T_TRUE; else if (!arb_contains_zero(acb_imagref(w))) y_real = T_FALSE; if (x_real == T_FALSE || y_real == T_FALSE) { /* Not comparable */ result = CMP_UNDEFINED; break; } /* Force a verification that we have comparable numbers. */ if (x_real == T_UNKNOWN && prec == 64) x_real = ca_check_is_real(x, ctx); if (y_real == T_UNKNOWN && prec == 64) y_real = ca_check_is_real(y, ctx); if (x_real == T_FALSE || y_real == T_FALSE) { /* Not comparable */ result = CMP_UNDEFINED; break; } if (x_real == T_TRUE && y_real == T_TRUE) { if (arb_gt(acb_realref(v), acb_realref(w))) { result = 1; break; } else if (arb_lt(acb_realref(v), acb_realref(w))) { result = -1; break; } } /* try qqbar computation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { if (ca_can_evaluate_qqbar(x, ctx) && ca_can_evaluate_qqbar(y, ctx)) { qqbar_t t, u; qqbar_init(t); qqbar_init(u); if (ca_get_qqbar(t, x, ctx)) { if (!qqbar_is_real(t)) { /* Not comparable */ result = CMP_UNDEFINED; } else if (ca_get_qqbar(u, y, ctx)) { if (!qqbar_is_real(u)) { /* Not comparable */ result = CMP_UNDEFINED; } else { result = qqbar_cmp_re(t, u); if (result < 0) result = -1; if (result > 0) result = 1; } } } qqbar_clear(t); qqbar_clear(u); } } } /* Todo: subtract, compute sign? Symbolic cancellations may help. */ if (result == CMP_UNKNOWN && x_real == T_TRUE && y_real == T_TRUE) { if (ca_check_equal(x, y, ctx) == T_TRUE) result = 0; } acb_clear(v); acb_clear(w); return result; } truth_t ca_check_ge(const ca_t x, const ca_t y, ca_ctx_t ctx) { int c = _ca_cmp(x, y, ctx); if (c == CMP_UNKNOWN) return T_UNKNOWN; if (c == CMP_UNDEFINED) return T_FALSE; return (c >= 0) ? T_TRUE : T_FALSE; } truth_t ca_check_gt(const ca_t x, const ca_t y, ca_ctx_t ctx) { int c = _ca_cmp(x, y, ctx); if (c == CMP_UNKNOWN) return T_UNKNOWN; if (c == CMP_UNDEFINED) return T_FALSE; return (c > 0) ? T_TRUE : T_FALSE; } truth_t ca_check_lt(const ca_t x, const ca_t y, ca_ctx_t ctx) { int c = _ca_cmp(x, y, ctx); if (c == CMP_UNKNOWN) return T_UNKNOWN; if (c == CMP_UNDEFINED) return T_FALSE; return (c < 0) ? T_TRUE : T_FALSE; } truth_t ca_check_le(const ca_t x, const ca_t y, ca_ctx_t ctx) { int c = _ca_cmp(x, y, ctx); if (c == CMP_UNKNOWN) return T_UNKNOWN; if (c == CMP_UNDEFINED) return T_FALSE; return (c <= 0) ? T_TRUE : T_FALSE; } flint-3.1.3/src/ca/check_is_algebraic.c000066400000000000000000000027721461254215100177220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" int ca_ext_can_evaluate_qqbar(const ca_ext_t x, ca_ctx_t ctx); /* todo: move, rename */ static truth_t ca_ext_is_algebraic(const ca_ext_t x, ca_ctx_t ctx) { if (CA_EXT_IS_QQBAR(x)) return T_TRUE; if (ca_ext_can_evaluate_qqbar(x, ctx)) return T_TRUE; return T_UNKNOWN; } truth_t ca_check_is_algebraic(const ca_t x, ca_ctx_t ctx) { ca_field_srcptr field; if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } field = CA_FIELD(x, ctx); if (CA_IS_QQ(x, ctx) || CA_FIELD_IS_NF(field)) { return T_TRUE; } else { slong len, i; len = CA_FIELD_LENGTH(field); /* todo: handle simple transcendental numbers, e.g. Q(i,pi) */ /* need to verify that some generator is used in the poly */ /* for Q(a,b,pi) we don't know, because a, b could cancel out pi */ for (i = 0; i < len; i++) { if (ca_ext_is_algebraic(CA_FIELD_EXT_ELEM(field, i), ctx) != T_TRUE) return T_UNKNOWN; } return T_TRUE; } } flint-3.1.3/src/ca/check_is_i.c000066400000000000000000000021441461254215100162320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_i(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { return T_FALSE; } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n, *d; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); d = QNF_ELEM_DENREF(CA_NF_ELEM(x)); if (fmpz_is_one(d) && fmpz_is_zero(n) && fmpz_is_one(n + 1)) return T_TRUE; return T_FALSE; } else { truth_t res; ca_t t; ca_init(t, ctx); ca_i(t, ctx); res = ca_check_equal(x, t, ctx); ca_clear(t, ctx); return res; } } flint-3.1.3/src/ca/check_is_imaginary.c000066400000000000000000000047541461254215100177730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_imaginary(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { if (fmpq_is_zero(CA_FMPQ(x))) return T_TRUE; else return T_FALSE; } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); if (fmpz_is_zero(n)) return T_TRUE; return T_FALSE; } else { acb_t t; truth_t res; slong prec, prec_limit; res = T_UNKNOWN; acb_init(t); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && (res == T_UNKNOWN); prec *= 2) { ca_get_acb_raw(t, x, prec, ctx); if (arb_is_zero(acb_realref(t))) { res = T_TRUE; break; } if (!arb_contains_zero(acb_realref(t))) { res = T_FALSE; break; } /* try conjugation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { ca_t t; ca_init(t, ctx); ca_conj_deep(t, x, ctx); ca_neg(t, t, ctx); res = ca_check_equal(t, x, ctx); ca_clear(t, ctx); if (res != T_UNKNOWN) break; } /* try qqbar computation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { qqbar_t a; qqbar_init(a); if (ca_get_qqbar(a, x, ctx)) res = (qqbar_sgn_re(a) == 0) ? T_TRUE : T_FALSE; qqbar_clear(a); } } acb_clear(t); return res; } } flint-3.1.3/src/ca/check_is_infinity.c000066400000000000000000000012301461254215100176260ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_infinity(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_INF(x)) return T_TRUE; return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_integer.c000066400000000000000000000035761461254215100174510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" /* todo: fast check in number field */ truth_t ca_check_is_integer(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { if (fmpz_is_one(fmpq_denref(CA_FMPQ(x)))) return T_TRUE; else return T_FALSE; } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { return nf_elem_is_integer(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx))) ? T_TRUE : T_FALSE; } else { acb_t t; truth_t res; slong prec, prec_limit; res = T_UNKNOWN; acb_init(t); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && (res == T_UNKNOWN); prec *= 2) { ca_get_acb_raw(t, x, prec, ctx); if (!acb_contains_int(t)) { res = T_FALSE; break; } /* try qqbar computation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { qqbar_t a; qqbar_init(a); if (ca_get_qqbar(a, x, ctx)) res = qqbar_is_integer(a) ? T_TRUE : T_FALSE; qqbar_clear(a); } } acb_clear(t); return res; } } flint-3.1.3/src/ca/check_is_neg_i.c000066400000000000000000000022111461254215100170560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_neg_i(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { return T_FALSE; } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n, *d; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); d = QNF_ELEM_DENREF(CA_NF_ELEM(x)); if (fmpz_is_one(d) && fmpz_is_zero(n) && fmpz_equal_si(n + 1, -1)) return T_TRUE; return T_FALSE; } else { truth_t res; ca_t t; ca_init(t, ctx); ca_i(t, ctx); ca_neg(t, t, ctx); res = ca_check_equal(x, t, ctx); ca_clear(t, ctx); return res; } } flint-3.1.3/src/ca/check_is_neg_i_inf.c000066400000000000000000000014451461254215100177220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_neg_i_inf(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_SIGNED_INF(x)) { ca_t t; t->field = x->field & ~CA_INF; t->elem = x->elem; return ca_check_is_neg_i(t, ctx); } return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_neg_inf.c000066400000000000000000000014451461254215100174120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_neg_inf(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_SIGNED_INF(x)) { ca_t t; t->field = x->field & ~CA_INF; t->elem = x->elem; return ca_check_is_neg_one(t, ctx); } return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_neg_one.c000066400000000000000000000024051461254215100174140ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_neg_one(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { if (fmpz_is_one(fmpq_denref(CA_FMPQ(x))) && fmpz_equal_si(fmpq_numref(CA_FMPQ(x)), -1)) return T_TRUE; else return T_FALSE; } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n, *d; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); d = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); if (fmpz_is_one(d) && fmpz_equal_si(n, -1) && fmpz_is_zero(n + 1)) return T_TRUE; return T_FALSE; } else { truth_t res; ca_t t; ca_init(t, ctx); ca_set_si(t, -1, ctx); res = ca_check_equal(x, t, ctx); ca_clear(t, ctx); return res; } } flint-3.1.3/src/ca/check_is_negative_real.c000066400000000000000000000053761461254215100206210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_negative_real(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { return (fmpq_sgn(CA_FMPQ(x)) < 0) ? T_TRUE : T_FALSE; } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); if (fmpz_is_zero(n + 1)) return (fmpz_sgn(n) < 0) ? T_TRUE : T_FALSE; return T_FALSE; } else { acb_t t; truth_t res, is_real; slong prec, prec_limit; res = T_UNKNOWN; acb_init(t); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); is_real = T_UNKNOWN; for (prec = 64; (prec <= prec_limit) && (res == T_UNKNOWN); prec *= 2) { ca_get_acb_raw(t, x, prec, ctx); if (is_real == T_UNKNOWN) { if (arb_is_zero(acb_imagref(t))) is_real = T_TRUE; else if (!arb_contains_zero(acb_imagref(t))) is_real = T_FALSE; } if ((is_real == T_TRUE) && arb_is_negative(acb_realref(t))) { res = T_TRUE; break; } if ((is_real == T_FALSE) || arb_is_nonnegative(acb_realref(t))) { res = T_FALSE; break; } if (prec == 64 && is_real == T_UNKNOWN) { ca_t t; ca_init(t, ctx); ca_conj_deep(t, x, ctx); is_real = ca_check_equal(t, x, ctx); ca_clear(t, ctx); if (is_real == T_FALSE) { res = T_FALSE; break; } } /* try qqbar computation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { qqbar_t a; qqbar_init(a); if (ca_get_qqbar(a, x, ctx)) res = (qqbar_sgn_im(a) == 0 && qqbar_sgn_re(a) < 0) ? T_TRUE : T_FALSE; qqbar_clear(a); } } acb_clear(t); return res; } } flint-3.1.3/src/ca/check_is_number.c000066400000000000000000000011371461254215100172730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_number(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } return T_TRUE; } flint-3.1.3/src/ca/check_is_one.c000066400000000000000000000022711461254215100165640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_one(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { if (fmpq_is_one(CA_FMPQ(x))) return T_TRUE; else return T_FALSE; } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n, *d; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); d = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); if (fmpz_is_one(d) && fmpz_is_one(n) && fmpz_is_zero(n + 1)) return T_TRUE; return T_FALSE; } else { truth_t res; ca_t t; ca_init(t, ctx); ca_one(t, ctx); res = ca_check_equal(x, t, ctx); ca_clear(t, ctx); return res; } } flint-3.1.3/src/ca/check_is_pos_i_inf.c000066400000000000000000000014671461254215100177560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_field.h" truth_t ca_check_is_pos_i_inf(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_SIGNED_INF(x)) { ca_t t; t->field = x->field & ~CA_INF; t->elem = x->elem; return ca_check_is_i(t, ctx); } return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_pos_inf.c000066400000000000000000000014411461254215100174360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_pos_inf(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_SIGNED_INF(x)) { ca_t t; t->field = x->field & ~CA_INF; t->elem = x->elem; return ca_check_is_one(t, ctx); } return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_rational.c000066400000000000000000000034601461254215100176150ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" /* todo: fast check in number field */ truth_t ca_check_is_rational(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { return T_TRUE; } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { return nf_elem_is_rational(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx))) ? T_TRUE : T_FALSE; } else { acb_t t; truth_t res; slong prec, prec_limit; res = T_UNKNOWN; acb_init(t); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && (res == T_UNKNOWN); prec *= 2) { ca_get_acb_raw(t, x, prec, ctx); if (!arb_contains_zero(acb_imagref(t))) { res = T_FALSE; break; } /* try qqbar computation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { qqbar_t a; qqbar_init(a); if (ca_get_qqbar(a, x, ctx)) res = qqbar_is_rational(a) ? T_TRUE : T_FALSE; qqbar_clear(a); } } acb_clear(t); return res; } } flint-3.1.3/src/ca/check_is_real.c000066400000000000000000000046411461254215100167310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_real(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } else if (CA_IS_QQ(x, ctx)) { return T_TRUE; } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); if (fmpz_is_zero(n + 1)) return T_TRUE; return T_FALSE; } else /* todo: first inspect extension numbers */ { acb_t t; truth_t res; slong prec, prec_limit; res = T_UNKNOWN; acb_init(t); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && (res == T_UNKNOWN); prec *= 2) { ca_get_acb_raw(t, x, prec, ctx); if (arb_is_zero(acb_imagref(t))) { res = T_TRUE; break; } if (!arb_contains_zero(acb_imagref(t))) { res = T_FALSE; break; } /* try conjugation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { ca_t t; ca_init(t, ctx); ca_conj_deep(t, x, ctx); res = ca_check_equal(t, x, ctx); ca_clear(t, ctx); if (res != T_UNKNOWN) break; } /* try qqbar computation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { qqbar_t a; qqbar_init(a); if (ca_get_qqbar(a, x, ctx)) res = (qqbar_sgn_im(a) == 0) ? T_TRUE : T_FALSE; qqbar_clear(a); } } acb_clear(t); return res; } } flint-3.1.3/src/ca/check_is_signed_inf.c000066400000000000000000000012411461254215100201040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_signed_inf(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_SIGNED_INF(x)) return T_TRUE; return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_uinf.c000066400000000000000000000012351461254215100167430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_uinf(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_UNSIGNED_INF(x)) return T_TRUE; return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_undefined.c000066400000000000000000000012371461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t ca_check_is_undefined(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; if (CA_IS_UNDEFINED(x)) return T_TRUE; return T_FALSE; } return T_FALSE; } flint-3.1.3/src/ca/check_is_zero.c000066400000000000000000000122011461254215100167540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" truth_t _ca_check_is_zero_qqbar(const ca_t x, ca_ctx_t ctx) { qqbar_t t; truth_t res; qqbar_init(t); if (ca_get_qqbar(t, x, ctx)) res = qqbar_is_zero(t) ? T_TRUE : T_FALSE; else res = T_UNKNOWN; qqbar_clear(t); return res; } void ca_rewrite_complex_normal_form(ca_t res, const ca_t x, int deep, ca_ctx_t ctx); truth_t ca_is_zero_check_fast(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (ca_is_unknown(x, ctx)) return T_UNKNOWN; return T_FALSE; } if (CA_IS_QQ(x, ctx)) { if (fmpq_is_zero(CA_FMPQ(x))) return T_TRUE; else return T_FALSE; } if (CA_IS_QQ_I(x, ctx)) { const fmpz *n; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); if (fmpz_is_zero(n) && fmpz_is_zero(n + 1)) return T_TRUE; return T_FALSE; } if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { if (nf_elem_is_zero(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx)))) return T_TRUE; else return T_FALSE; } return T_UNKNOWN; } int _ca_generic_has_nontrivial_denominator(const ca_t x, ca_ctx_t ctx) { return !fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(CA_FIELD(x, ctx), ctx)); } truth_t ca_check_is_zero_no_factoring(const ca_t x, ca_ctx_t ctx) { acb_t v; truth_t res; slong prec, prec_limit; res = ca_is_zero_check_fast(x, ctx); if (res != T_UNKNOWN || CA_IS_SPECIAL(x)) return res; /* The denominator is irrelevant. */ /* Todo: we should probably also factor out monomials. */ if (_ca_generic_has_nontrivial_denominator(x, ctx)) { ca_t t; ca_init(t, ctx); ca_set(t, x, ctx); /* Todo: could also remove content */ fmpz_mpoly_one(fmpz_mpoly_q_denref(CA_MPOLY_Q(t)), CA_FIELD_MCTX(CA_FIELD(t, ctx), ctx)); res = ca_check_is_zero_no_factoring(t, ctx); ca_clear(t, ctx); return res; } acb_init(v); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && (res == T_UNKNOWN); prec *= 2) { ca_get_acb_raw(v, x, prec, ctx); if (!acb_contains_zero(v)) { res = T_FALSE; break; } /* try qqbar computation */ /* todo: precision to do this should depend on complexity of the polynomials, degree of the elements... */ if (prec == 64) { res = _ca_check_is_zero_qqbar(x, ctx); } } acb_clear(v); if (res == T_UNKNOWN) { ca_t tmp; ca_init(tmp, ctx); ca_rewrite_complex_normal_form(tmp, x, 1, ctx); res = ca_is_zero_check_fast(tmp, ctx); if (ctx->options[CA_OPT_VERBOSE]) { flint_printf("is_zero: complex_normal form:\n"); ca_print(x, ctx); flint_printf("\n"); ca_print(tmp, ctx); flint_printf("\n"); truth_print(res); flint_printf("\n"); } ca_clear(tmp, ctx); } return res; } truth_t ca_check_is_zero(const ca_t x, ca_ctx_t ctx) { truth_t res; res = ca_check_is_zero_no_factoring(x, ctx); if (res == T_UNKNOWN && !CA_IS_SPECIAL(x)) { ca_factor_t fac; ca_t t; truth_t factor_res; slong i, nontrivial_factors; /* the zero test will surely have succeeded over a number field */ if (!CA_FIELD_IS_GENERIC(CA_FIELD(x, ctx))) flint_throw(FLINT_ERROR, "(%s)\n", __func__); /* extract numerator */ ca_init(t, ctx); ca_set(t, x, ctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(CA_MPOLY_Q(t)), CA_FIELD_MCTX(CA_FIELD(t, ctx), ctx)); ca_factor_init(fac, ctx); ca_factor(fac, t, CA_FACTOR_ZZ_NONE | CA_FACTOR_POLY_FULL, ctx); nontrivial_factors = 0; for (i = 0; i < fac->length; i++) nontrivial_factors += !CA_IS_QQ(fac->base + i, ctx); if (nontrivial_factors >= 2) { for (i = 0; i < fac->length; i++) { factor_res = ca_check_is_zero_no_factoring(fac->base + i, ctx); if (factor_res == T_TRUE) { if (ctx->options[CA_OPT_VERBOSE]) { flint_printf("is_zero: factoring:\n"); ca_print(x, ctx); flint_printf("\n"); ca_print(fac->base + i, ctx); flint_printf("\n"); truth_print(res); flint_printf("\n"); } res = T_TRUE; break; } } } ca_clear(t, ctx); ca_factor_clear(fac, ctx); } return res; } flint-3.1.3/src/ca/clear.c000066400000000000000000000037771461254215100152550ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #define CHECK_DATA 0 void ca_clear_unchecked(ca_t x, ca_ctx_t ctx) { ca_field_srcptr field; field = (ca_field_srcptr) (x->field & ~CA_SPECIAL); if (field != NULL) { if (field == ctx->field_qq) { fmpz_clear(CA_FMPQ_NUMREF(x)); fmpz_clear(CA_FMPQ_DENREF(x)); } else if (CA_FIELD_IS_NF(field)) { nf_elem_clear(CA_NF_ELEM(x), CA_FIELD_NF(field)); } else { fmpz_mpoly_q_clear(CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx)); flint_free(x->elem.mpoly_q); } } } void ca_clear(ca_t x, ca_ctx_t ctx) { ca_field_srcptr field; field = (ca_field_srcptr) (x->field & ~CA_SPECIAL); if (field != NULL) { if (field == ctx->field_qq) { fmpz_clear(CA_FMPQ_NUMREF(x)); fmpz_clear(CA_FMPQ_DENREF(x)); } else if (CA_FIELD_IS_NF(field)) { #if CHECK_DATA if (nf_elem_is_rational(CA_NF_ELEM(x), CA_FIELD_NF(field))) { flint_throw(FLINT_ERROR, "ca_clear: nf_elem is rational:\n\nx = %s\n", ca_get_str(x, ctx)); } #endif nf_elem_clear(CA_NF_ELEM(x), CA_FIELD_NF(field)); } else { #if CHECK_DATA if (fmpz_mpoly_q_is_fmpq(CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx))) { flint_throw(FLINT_ERROR, "ca_clear: mpoly_q is rational:\n\nx = %s\n", ca_get_str(x, ctx)); } #endif fmpz_mpoly_q_clear(CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx)); flint_free(x->elem.mpoly_q); } } } flint-3.1.3/src/ca/condense_field.c000066400000000000000000000156151461254215100171220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" ca_field_ptr ca_field_cache_lookup_qqbar(ca_field_cache_t cache, const qqbar_t x, ca_ctx_t ctx); static void _fmpz_mpoly_get_fmpq_poly_var_destructive(fmpq_poly_t res, fmpz_mpoly_t F, slong i, const fmpz_mpoly_ctx_t ctx) { slong j, exp; for (j = 0; j < F->length; j++) { exp = fmpz_mpoly_get_term_var_exp_si(F, j, i, ctx); if (j == 0) { fmpq_poly_fit_length(res, exp + 1); _fmpq_poly_set_length(res, exp + 1); } fmpz_swap(res->coeffs + exp, F->coeffs + j); } } void ca_condense_field(ca_t res, ca_ctx_t ctx) { ca_field_srcptr field; if (CA_IS_QQ(res, ctx)) return; if (CA_IS_SPECIAL(res)) { if (CA_IS_SIGNED_INF(res)) { ca_t t; *t = *res; t->field &= ~CA_INF; ca_condense_field(t, ctx); t->field |= CA_INF; *res = *t; } return; } field = CA_FIELD(res, ctx); if (CA_FIELD_IS_NF(field)) { /* demote to rational number */ if (nf_elem_is_rational(CA_NF_ELEM(res), CA_FIELD_NF(field))) { fmpq_t t; fmpq_init(t); if (CA_FIELD_NF(field)->flag & NF_LINEAR) { fmpz_swap(fmpq_numref(t), LNF_ELEM_NUMREF(CA_NF_ELEM(res))); fmpz_swap(fmpq_denref(t), LNF_ELEM_DENREF(CA_NF_ELEM(res))); } else if (CA_FIELD_NF(field)->flag & NF_QUADRATIC) { fmpz_swap(fmpq_numref(t), QNF_ELEM_NUMREF(CA_NF_ELEM(res))); fmpz_swap(fmpq_denref(t), QNF_ELEM_DENREF(CA_NF_ELEM(res))); } else { if (NF_ELEM(CA_NF_ELEM(res))->length != 0) { fmpz_swap(fmpq_numref(t), NF_ELEM(CA_NF_ELEM(res))->coeffs); fmpz_swap(fmpq_denref(t), NF_ELEM(CA_NF_ELEM(res))->den); } } _ca_make_fmpq(res, ctx); fmpq_swap(CA_FMPQ(res), t); fmpq_clear(t); } } else { /* todo: demote to smaller field (in particular, single generator) */ if (fmpz_mpoly_q_is_fmpq(CA_MPOLY_Q(res), CA_FIELD_MCTX(field, ctx))) { fmpq_t t; fmpq_init(t); if (!fmpz_mpoly_q_is_zero(CA_MPOLY_Q(res), CA_FIELD_MCTX(field, ctx))) { fmpz_swap(fmpq_numref(t), fmpz_mpoly_q_numref(CA_MPOLY_Q(res))->coeffs); fmpz_swap(fmpq_denref(t), fmpz_mpoly_q_denref(CA_MPOLY_Q(res))->coeffs); } _ca_make_fmpq(res, ctx); fmpq_swap(CA_FMPQ(res), t); fmpq_clear(t); } else { slong i, nvars, count; int * used; TMP_INIT; nvars = CA_FIELD_MCTX(field, ctx)->minfo->nvars; TMP_START; used = TMP_ALLOC(sizeof(int) * nvars); fmpz_mpoly_q_used_vars(used, CA_MPOLY_Q(res), CA_FIELD_MCTX(field, ctx)); count = 0; for (i = 0; i < nvars; i++) count += used[i]; if (count == 1) { for (i = 0; i < nvars; i++) { if (used[i]) { /* Convert mpoly_q to nf elem (todo -- move to fmpz_mpoly_q module) */ if (CA_EXT_IS_QQBAR(CA_FIELD_EXT_ELEM(field, i))) { ca_field_ptr new_field; fmpq_poly_t P; const fmpz_mpoly_ctx_struct * mctx; fmpz_mpoly_q_struct * F = CA_MPOLY_Q(res); fmpq_poly_init(P); mctx = CA_FIELD_MCTX(field, ctx); new_field = ca_field_cache_lookup_qqbar(CA_CTX_FIELD_CACHE(ctx), CA_EXT_QQBAR(CA_FIELD_EXT_ELEM(field, i)), ctx); if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(F), mctx)) { _fmpz_mpoly_get_fmpq_poly_var_destructive(P, fmpz_mpoly_q_numref(F), i, mctx); fmpz_swap(P->den, fmpz_mpoly_q_denref(F)->coeffs); _ca_make_field_element(res, new_field, ctx); nf_elem_set_fmpq_poly(CA_NF_ELEM(res), P, CA_FIELD_NF(new_field)); } else if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_numref(F), mctx)) { _fmpz_mpoly_get_fmpq_poly_var_destructive(P, fmpz_mpoly_q_denref(F), i, mctx); fmpz_swap(P->den, fmpz_mpoly_q_numref(F)->coeffs); if (fmpz_sgn(P->den) < 0) { _fmpz_vec_neg(P->coeffs, P->coeffs, P->length); fmpz_neg(P->den, P->den); } _ca_make_field_element(res, new_field, ctx); nf_elem_set_fmpq_poly(CA_NF_ELEM(res), P, CA_FIELD_NF(new_field)); nf_elem_inv(CA_NF_ELEM(res), CA_NF_ELEM(res), CA_FIELD_NF(new_field)); } else { fmpq_poly_t Q; nf_elem_t t; fmpq_poly_init(Q); nf_elem_init(t, CA_FIELD_NF(new_field)); _fmpz_mpoly_get_fmpq_poly_var_destructive(P, fmpz_mpoly_q_numref(F), i, mctx); _fmpz_mpoly_get_fmpq_poly_var_destructive(Q, fmpz_mpoly_q_denref(F), i, mctx); _ca_make_field_element(res, new_field, ctx); nf_elem_set_fmpq_poly(CA_NF_ELEM(res), P, CA_FIELD_NF(new_field)); nf_elem_set_fmpq_poly(t, Q, CA_FIELD_NF(new_field)); nf_elem_div(CA_NF_ELEM(res), CA_NF_ELEM(res), t, CA_FIELD_NF(new_field)); fmpq_poly_clear(Q); nf_elem_clear(t, CA_FIELD_NF(new_field)); } fmpq_poly_clear(P); } break; } } } TMP_END; } } } flint-3.1.3/src/ca/conj.c000066400000000000000000000262061461254215100151100ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" #include "ca_vec.h" void ca_conj_shallow(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { ca_unknown(res, ctx); } else if (CA_IS_QQ(x, ctx)) { ca_set(res, x, ctx); } else if (CA_IS_QQ_I(x, ctx)) { ca_set(res, x, ctx); fmpz_neg(QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 1, QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 1); } else { _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Conjugate, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } } /* todo */ ca_field_ptr ca_ctx_get_field_qqbar(ca_ctx_t ctx, const qqbar_t x); /* Set res to the generator of Q(ext). */ void ca_set_ext(ca_t res, ca_ext_srcptr ext, ca_ctx_t ctx) { if (CA_EXT_HEAD(ext) == CA_QQBar) { ca_field_srcptr field; field = ca_ctx_get_field_qqbar(ctx, CA_EXT_QQBAR(ext)); _ca_make_field_element(res, field, ctx); nf_elem_gen(CA_NF_ELEM(res), CA_FIELD_NF(field)); } else { /* todo: direct function */ ca_field_ptr K; ca_ext_struct * X[1]; X[0] = (ca_ext_ptr) ext; K = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), X, 1, ctx); _ca_make_field_element(res, K, ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } } void ca_conj_ext(ca_t res, ca_ext_ptr ext, ca_ctx_t ctx) { slong p; ulong q; switch (CA_EXT_HEAD(ext)) { case CA_QQBar: if (qqbar_is_real(CA_EXT_QQBAR(ext))) { ca_set_ext(res, ext, ctx); } else if (qqbar_is_i(CA_EXT_QQBAR(ext))) { ca_neg_i(res, ctx); } else if (qqbar_sgn_re(CA_EXT_QQBAR(ext)) == 0) { /* Imaginary number: conjugation is negation */ ca_field_srcptr field; field = ca_ctx_get_field_qqbar(ctx, CA_EXT_QQBAR(ext)); _ca_make_field_element(res, field, ctx); nf_elem_gen(CA_NF_ELEM(res), CA_FIELD_NF(field)); nf_elem_neg(CA_NF_ELEM(res), CA_NF_ELEM(res), CA_FIELD_NF(field)); } else if (qqbar_is_root_of_unity(&p, &q, CA_EXT_QQBAR(ext))) { ca_field_srcptr field; nf_struct * nf; field = ca_ctx_get_field_qqbar(ctx, CA_EXT_QQBAR(ext)); nf = CA_FIELD_NF(field); _ca_make_field_element(res, field, ctx); nf_elem_gen(CA_NF_ELEM(res), CA_FIELD_NF(field)); nf_elem_pow(CA_NF_ELEM(res), CA_NF_ELEM(res), q - 1, nf); ca_condense_field(res, ctx); } else { qqbar_t t; qqbar_init(t); qqbar_conj(t, CA_EXT_QQBAR(ext)); ca_set_qqbar(res, t, ctx); qqbar_clear(t); } break; /* Todo: CA_Conjugate, CA_Sign, ...? */ /* Real-valued extensions */ case CA_Pi: case CA_Euler: case CA_Re: case CA_Im: case CA_Abs: case CA_Arg: case CA_Floor: case CA_Ceil: ca_set_ext(res, ext, ctx); break; /* Functions with branch cuts */ /* Todo: negate things that are pure imaginary */ /* Todo: reevaluate functions (they may want to insert new objects in the field)? */ case CA_Sqrt: case CA_Log: case CA_LogGamma: if (ca_check_is_negative_real(CA_EXT_FUNC_ARGS(ext), ctx) != T_FALSE) { ca_set_ext(res, ext, ctx); ca_conj_shallow(res, res, ctx); } else if (ca_check_is_real(CA_EXT_FUNC_ARGS(ext), ctx) == T_TRUE) { ca_set_ext(res, ext, ctx); } else { ca_t t; ca_init(t, ctx); ca_conj_deep(t, CA_EXT_FUNC_ARGS(ext), ctx); _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_EXT_HEAD(ext), t), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); ca_clear(t, ctx); } break; case CA_Pow: if (ca_check_is_negative_real(CA_EXT_FUNC_ARGS(ext) + 0, ctx) != T_FALSE) { ca_set_ext(res, ext, ctx); ca_conj_shallow(res, res, ctx); } else if (ca_check_is_real(CA_EXT_FUNC_ARGS(ext) + 0, ctx) == T_TRUE && ca_check_is_real(CA_EXT_FUNC_ARGS(ext) + 1, ctx) == T_TRUE) { ca_set_ext(res, ext, ctx); } else { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_conj_deep(t, CA_EXT_FUNC_ARGS(ext) + 0, ctx); ca_conj_deep(u, CA_EXT_FUNC_ARGS(ext) + 1, ctx); _ca_make_field_element(res, _ca_ctx_get_field_fxy(ctx, CA_Pow, t, u), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); ca_clear(t, ctx); ca_clear(u, ctx); } break; /* Meromorphic functions: conjugate argument */ /* Todo: negate things that are pure imaginary */ /* Todo: reevaluate functions (they may want to insert new objects in the field)? */ case CA_Exp: case CA_Sin: case CA_Cos: case CA_Tan: case CA_Cosh: case CA_Sinh: case CA_Tanh: case CA_Gamma: case CA_RiemannZeta: case CA_Erf: case CA_Erfc: case CA_Erfi: { if (ca_check_is_real(CA_EXT_FUNC_ARGS(ext), ctx) == T_TRUE) { ca_set_ext(res, ext, ctx); } else { ca_t t; ca_init(t, ctx); ca_conj_deep(t, CA_EXT_FUNC_ARGS(ext), ctx); _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_EXT_HEAD(ext), t), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); ca_clear(t, ctx); } } break; default: ca_set_ext(res, ext, ctx); ca_conj_shallow(res, res, ctx); } } /* Complex conjugate assuming that the generator is pure imaginary. */ void nf_elem_conj_imag(nf_elem_t a, const nf_elem_t b, const nf_t nf) { nf_elem_set(a, b, nf); if (nf->flag & NF_LINEAR) { } else if (nf->flag & NF_QUADRATIC) { fmpz_neg(QNF_ELEM_NUMREF(a) + 1, QNF_ELEM_NUMREF(a) + 1); } else { slong i; for (i = 1; i < NF_ELEM(a)->length; i += 2) fmpz_neg(NF_ELEM(a)->coeffs + i, NF_ELEM(a)->coeffs + i); } } void ca_conj_deep(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { /* todo */ ca_unknown(res, ctx); } else if (CA_IS_QQ(x, ctx)) { ca_set(res, x, ctx); } else if (CA_IS_QQ_I(x, ctx)) { ca_set(res, x, ctx); fmpz_neg(QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 1, QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 1); } else { ca_field_ptr K; slong p; ulong q; K = CA_FIELD(x, ctx); if (CA_FIELD_IS_NF(K)) { if (qqbar_is_real(CA_EXT_QQBAR(CA_FIELD_EXT_ELEM(K, 0)))) { ca_set(res, x, ctx); } else if (qqbar_sgn_re(CA_EXT_QQBAR(CA_FIELD_EXT_ELEM(K, 0))) == 0) { ca_set(res, x, ctx); nf_elem_conj_imag(CA_NF_ELEM(res), CA_NF_ELEM(res), CA_FIELD_NF(K)); } else if (ca_is_cyclotomic_nf_elem(&p, &q, x, ctx)) { nf_struct * nf; fmpq_poly_t poly; nf = CA_FIELD_NF(CA_FIELD(x, ctx)); fmpq_poly_init(poly); nf_elem_get_fmpq_poly(poly, CA_NF_ELEM(x), nf); ca_set(res, x, ctx); nf_elem_gen(CA_NF_ELEM(res), nf); nf_elem_pow(CA_NF_ELEM(res), CA_NF_ELEM(res), q - 1, nf); ca_condense_field(res, ctx); ca_fmpq_poly_evaluate(res, poly, res, ctx); fmpq_poly_clear(poly); } else { /* Todo: when to conjugate the extension number directly? We call ca_set_qqbar because it might do some rewriting that is actually desirable, e.g. standardizing in cyclotomic fields. This means that we can't safely just copy the nf_elems, because the field representation could be different. */ fmpq_poly_t poly; qqbar_t t; qqbar_init(t); fmpq_poly_init(poly); nf_elem_get_fmpq_poly(poly, CA_NF_ELEM(x), CA_FIELD_NF(K)); qqbar_conj(t, CA_EXT_QQBAR(CA_FIELD_EXT_ELEM(K, 0))); ca_set_qqbar(res, t, ctx); ca_fmpq_poly_evaluate(res, poly, res, ctx); qqbar_clear(t); fmpq_poly_clear(poly); } } else { slong nvars; int * used; slong i; ca_ptr cext; nvars = CA_FIELD_LENGTH(K); used = flint_calloc(nvars, sizeof(int)); cext = _ca_vec_init(nvars, ctx); fmpz_mpoly_q_used_vars(used, CA_MPOLY_Q(x), CA_FIELD_MCTX(K, ctx)); for (i = 0; i < nvars; i++) { if (used[i]) { ca_conj_ext(cext + i, CA_FIELD_EXT_ELEM(K, i), ctx); } } /* todo: somehow exploit the fact that the denominator is guaranteed to be nonzero, meaning that doesn't need to be checked? */ ca_fmpz_mpoly_q_evaluate(res, CA_MPOLY_Q(x), cext, CA_FIELD_MCTX(K, ctx), ctx); _ca_vec_clear(cext, nvars, ctx); flint_free(used); } } } void ca_conj(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { /* todo */ ca_unknown(res, ctx); } else if (CA_IS_QQ(x, ctx)) { ca_set(res, x, ctx); } else if (CA_IS_QQ_I(x, ctx)) { ca_set(res, x, ctx); fmpz_neg(QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 1, QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 1); } /* todo: avoid duplicate computations with is_real/is_imaginary */ else if (ca_check_is_real(x, ctx) == T_TRUE) { ca_set(res, x, ctx); } else if (ca_check_is_imaginary(x, ctx) == T_TRUE) { ca_neg(res, x, ctx); } else { ca_conj_deep(res, x, ctx); } } flint-3.1.3/src/ca/csgn.c000066400000000000000000000036551461254215100151140ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" /* todo: better impl */ /* may want to return symbolic csgn (can still bound numerically) */ void ca_csgn(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t re, im, zero; truth_t is_zero; if (CA_IS_SPECIAL(x)) { if (ca_check_is_signed_inf(x, ctx) == T_TRUE) { ca_sgn(res, x, ctx); ca_csgn(res, res, ctx); } else if (ca_check_is_uinf(x, ctx) == T_TRUE || ca_check_is_undefined(x, ctx) == T_TRUE) { ca_undefined(res, ctx); } else { ca_unknown(res, ctx); } return; } is_zero = ca_check_is_zero(x, ctx); if (is_zero == T_TRUE) { ca_zero(res, ctx); return; } if (is_zero == T_UNKNOWN) { ca_unknown(res, ctx); return; } ca_init(re, ctx); ca_init(zero, ctx); ca_re(re, x, ctx); if (ca_check_gt(re, zero, ctx) == T_TRUE) { ca_one(res, ctx); } else if (ca_check_lt(re, zero, ctx) == T_TRUE) { ca_neg_one(res, ctx); } else if (ca_check_is_zero(re, ctx) == T_TRUE) { ca_init(im, ctx); ca_im(im, x, ctx); if (ca_check_gt(im, zero, ctx) == T_TRUE) { ca_one(res, ctx); } else if (ca_check_lt(im, zero, ctx) == T_TRUE) { ca_neg_one(res, ctx); } else { ca_unknown(res, ctx); } ca_clear(im, ctx); } else { ca_unknown(res, ctx); } ca_clear(re, ctx); } flint-3.1.3/src/ca/ctx_clear.c000066400000000000000000000016551461254215100161240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" void ca_ctx_clear(ca_ctx_t ctx) { slong i; CA_INFO(ctx, ("%wd extension numbers cached at time of destruction\n", CA_CTX_EXT_CACHE(ctx)->length)); CA_INFO(ctx, ("%wd fields cached at time of destruction\n", CA_CTX_FIELD_CACHE(ctx)->length)); ca_ext_cache_clear(CA_CTX_EXT_CACHE(ctx), ctx); ca_field_cache_clear(CA_CTX_FIELD_CACHE(ctx), ctx); for (i = 0; i < ctx->mctx_len; i++) flint_free(ctx->mctx[i]); flint_free(ctx->mctx); flint_free(ctx->options); } flint-3.1.3/src/ca/ctx_get_field_const.c000066400000000000000000000015371461254215100201650ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" ca_field_ptr _ca_ctx_get_field_const(ca_ctx_t ctx, calcium_func_code func) { ca_ext_t ext; ca_ext_struct * ext_ptr[1]; ca_field_ptr field; /* todo: shallow copy */ ca_ext_init_const(ext, func, ctx); ext_ptr[0] = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), ext, ctx); field = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), ext_ptr, 1, ctx); ca_ext_clear(ext, ctx); return field; } flint-3.1.3/src/ca/ctx_get_field_fx.c000066400000000000000000000015521461254215100174510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" ca_field_ptr _ca_ctx_get_field_fx(ca_ctx_t ctx, calcium_func_code func, const ca_t x) { ca_ext_t ext; ca_ext_struct * ext_ptr[1]; ca_field_ptr field; /* todo: shallow copy */ ca_ext_init_fx(ext, func, x, ctx); ext_ptr[0] = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), ext, ctx); field = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), ext_ptr, 1, ctx); ca_ext_clear(ext, ctx); return field; } flint-3.1.3/src/ca/ctx_get_field_fxy.c000066400000000000000000000015751461254215100176470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" ca_field_ptr _ca_ctx_get_field_fxy(ca_ctx_t ctx, calcium_func_code func, const ca_t x, const ca_t y) { ca_ext_t ext; ca_ext_struct * ext_ptr[1]; ca_field_ptr field; /* todo: shallow copy */ ca_ext_init_fxy(ext, func, x, y, ctx); ext_ptr[0] = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), ext, ctx); field = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), ext_ptr, 1, ctx); ca_ext_clear(ext, ctx); return field; } flint-3.1.3/src/ca/ctx_init.c000066400000000000000000000035331461254215100157760ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" void ca_ctx_init(ca_ctx_t ctx) { qqbar_t onei; ca_ext_t ext; ca_ext_struct * ext_ptr[1]; ctx->options = flint_calloc(CA_OPT_NUM_OPTIONS, sizeof(slong)); ctx->options[CA_OPT_PREC_LIMIT] = 4096; ctx->options[CA_OPT_QQBAR_DEG_LIMIT] = 120; ctx->options[CA_OPT_LOW_PREC] = 64; ctx->options[CA_OPT_SMOOTH_LIMIT] = 32; ctx->options[CA_OPT_LLL_PREC] = 128; ctx->options[CA_OPT_POW_LIMIT] = 20; ctx->options[CA_OPT_USE_GROEBNER] = 1; ctx->options[CA_OPT_GROEBNER_LENGTH_LIMIT] = 100; ctx->options[CA_OPT_GROEBNER_POLY_LENGTH_LIMIT] = 1000; ctx->options[CA_OPT_GROEBNER_POLY_BITS_LIMIT] = 10000; ctx->options[CA_OPT_VIETA_LIMIT] = 6; ctx->options[CA_OPT_PRINT_FLAGS] = CA_PRINT_DEFAULT; ctx->options[CA_OPT_MPOLY_ORD] = ORD_LEX; ctx->options[CA_OPT_TRIG_FORM] = CA_TRIG_EXPONENTIAL; ctx->mctx = NULL; ctx->mctx_len = 0; ca_ext_cache_init(CA_CTX_EXT_CACHE(ctx), ctx); ca_field_cache_init(CA_CTX_FIELD_CACHE(ctx), ctx); /* Always create QQ */ ctx->field_qq = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), NULL, 0, ctx); /* Always create QQ(i) */ qqbar_init(onei); qqbar_i(onei); ca_ext_init_qqbar(ext, onei, ctx); ext_ptr[0] = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), ext, ctx); ctx->field_qq_i = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), ext_ptr, 1, ctx); qqbar_clear(onei); ca_ext_clear(ext, ctx); } flint-3.1.3/src/ca/div.c000066400000000000000000000121351461254215100147350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_div_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) { ca_field_srcptr field; if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { if (fmpq_is_zero(y)) ca_uinf(res, ctx); else if (fmpq_sgn(y) > 0) ca_set(res, x, ctx); else ca_neg(res, x, ctx); } else { ca_set(res, x, ctx); } return; } if (fmpq_is_zero(y)) { truth_t x_zero = ca_check_is_zero(x, ctx); if (x_zero == T_TRUE) ca_undefined(res, ctx); else if (x_zero == T_FALSE) ca_uinf(res, ctx); else ca_unknown(res, ctx); return; } if (CA_IS_QQ(x, ctx)) { _ca_make_fmpq(res, ctx); fmpq_div(CA_FMPQ(res), CA_FMPQ(x), y); return; } else { field = CA_FIELD(x, ctx); _ca_make_field_element(res, field, ctx); if (CA_FIELD_IS_NF(field)) { nf_elem_scalar_div_fmpq(CA_NF_ELEM(res), CA_NF_ELEM(x), y, CA_FIELD_NF(field)); } else { fmpz_mpoly_q_div_fmpq(CA_MPOLY_Q(res), CA_MPOLY_Q(x), y, CA_FIELD_MCTX(field, ctx)); } } } void ca_div_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) { fmpq_t t; *fmpq_numref(t) = *y; *fmpq_denref(t) = 1; ca_div_fmpq(res, x, t, ctx); } void ca_div_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, y); ca_div_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_div_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, y); ca_div_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_fmpq_div(ca_t res, const fmpq_t x, const ca_t y, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_set_fmpq(t, x, ctx); ca_div(res, t, y, ctx); ca_clear(t, ctx); } void ca_fmpz_div(ca_t res, const fmpz_t x, const ca_t y, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_set_fmpz(t, x, ctx); ca_div(res, t, y, ctx); ca_clear(t, ctx); } void ca_si_div(ca_t res, slong x, const ca_t y, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_set_si(t, x, ctx); ca_div(res, t, y, ctx); ca_clear(t, ctx); } void ca_ui_div(ca_t res, ulong x, const ca_t y, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_set_ui(t, x, ctx); ca_div(res, t, y, ctx); ca_clear(t, ctx); } void ca_div(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_srcptr xfield, yfield, zfield; truth_t x_is_zero, y_is_zero; xfield = CA_FIELD(x, ctx); yfield = CA_FIELD(y, ctx); if (CA_IS_QQ(x, ctx) && (xfield == yfield)) { if (fmpq_is_zero(CA_FMPQ(y))) { if (fmpq_is_zero(CA_FMPQ(x))) ca_undefined(res, ctx); else ca_uinf(res, ctx); } else { _ca_make_fmpq(res, ctx); fmpq_div(CA_FMPQ(res), CA_FMPQ(x), CA_FMPQ(y)); } return; } if (CA_IS_QQ(y, ctx)) { if (res == y) { fmpq_t t; fmpq_init(t); fmpq_set(t, CA_FMPQ(y)); ca_div_fmpq(res, x, t, ctx); fmpq_clear(t); } else { ca_div_fmpq(res, x, CA_FMPQ(y), ctx); } return; } if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { ca_t t; ca_init(t, ctx); ca_inv(t, y, ctx); ca_mul(res, x, t, ctx); ca_clear(t, ctx); return; } y_is_zero = ca_check_is_zero(y, ctx); if (y_is_zero == T_TRUE) { x_is_zero = ca_check_is_zero(x, ctx); if (x_is_zero == T_FALSE) ca_uinf(res, ctx); else if (x_is_zero == T_TRUE) ca_undefined(res, ctx); else ca_unknown(res, ctx); return; } else if (y_is_zero == T_UNKNOWN) { ca_unknown(res, ctx); return; } if (xfield == yfield) { zfield = xfield; _ca_make_field_element(res, zfield, ctx); if (CA_FIELD_IS_NF(zfield)) { nf_elem_div(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_NF_ELEM(y), CA_FIELD_NF(zfield)); } else { fmpz_mpoly_q_div(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_MPOLY_Q(y), CA_FIELD_MCTX(zfield, ctx)); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), zfield, ctx); _ca_mpoly_q_simplify_fraction_ideal(CA_MPOLY_Q(res), zfield, ctx); } ca_condense_field(res, ctx); return; } { ca_t t; ca_init(t, ctx); ca_inv(t, y, ctx); ca_mul(res, x, t, ctx); ca_clear(t, ctx); } } flint-3.1.3/src/ca/dot.c000066400000000000000000000023041461254215100147360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_dot(ca_t res, const ca_t initial, int subtract, ca_srcptr x, slong xstep, ca_srcptr y, slong ystep, slong len, ca_ctx_t ctx) { slong i; ca_t t; if (len <= 0) { if (initial == NULL) ca_zero(res, ctx); else ca_set(res, initial, ctx); return; } ca_init(t, ctx); if (initial == NULL) { ca_mul(res, x, y, ctx); } else { if (subtract) ca_neg(res, initial, ctx); else ca_set(res, initial, ctx); ca_mul(t, x, y, ctx); ca_add(res, res, t, ctx); } for (i = 1; i < len; i++) { ca_mul(t, x + i * xstep, y + i * ystep, ctx); ca_add(res, res, t, ctx); } if (subtract) ca_neg(res, res, ctx); ca_clear(t, ctx); } flint-3.1.3/src/ca/equal_repr.c000066400000000000000000000020431461254215100163070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" int ca_equal_repr(const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_ptr field; /* by assumption: cached field objects are unique */ if (x->field != y->field) return 0; if (CA_IS_SPECIAL(x) && !CA_IS_SIGNED_INF(x)) return x->field == y->field; field = CA_FIELD_UNSPECIAL(x, ctx); if (CA_FIELD_IS_QQ(field)) { return fmpq_equal(CA_FMPQ(x), CA_FMPQ(y)); } else if (CA_FIELD_IS_NF(field)) { return nf_elem_equal(CA_NF_ELEM(x), CA_NF_ELEM(y), CA_FIELD_NF(field)); } else { return fmpz_mpoly_q_equal(CA_MPOLY_Q(x), CA_MPOLY_Q(y), CA_FIELD_MCTX(field, ctx)); } } flint-3.1.3/src/ca/erf.c000066400000000000000000000024561461254215100147340ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_erf(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { /* todo: other signed infinities */ if (ca_check_is_pos_inf(x, ctx) == T_TRUE) ca_one(res, ctx); else if (ca_check_is_neg_inf(x, ctx) == T_TRUE) ca_neg_one(res, ctx); else if (ca_check_is_pos_i_inf(x, ctx) == T_TRUE) ca_pos_i_inf(res, ctx); else if (ca_check_is_neg_i_inf(x, ctx) == T_TRUE) ca_neg_i_inf(res, ctx); else if (ca_check_is_undefined(x, ctx) == T_TRUE || ca_check_is_uinf(x, ctx) == T_TRUE) ca_undefined(res, ctx); else ca_unknown(res, ctx); return; } if (ca_check_is_zero(x, ctx) == T_TRUE) { ca_zero(res, ctx); return; } _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Erf, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/erfc.c000066400000000000000000000024621461254215100150740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_erfc(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { /* todo: other signed infinities */ if (ca_check_is_pos_inf(x, ctx) == T_TRUE) ca_zero(res, ctx); else if (ca_check_is_neg_inf(x, ctx) == T_TRUE) ca_set_ui(res, 2, ctx); else if (ca_check_is_pos_i_inf(x, ctx) == T_TRUE) ca_neg_i_inf(res, ctx); else if (ca_check_is_neg_i_inf(x, ctx) == T_TRUE) ca_pos_i_inf(res, ctx); else if (ca_check_is_undefined(x, ctx) == T_TRUE || ca_check_is_uinf(x, ctx) == T_TRUE) ca_undefined(res, ctx); else ca_unknown(res, ctx); return; } if (ca_check_is_zero(x, ctx) == T_TRUE) { ca_one(res, ctx); return; } _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Erfc, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/erfi.c000066400000000000000000000024501461254215100150770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_erfi(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { /* todo: other signed infinities */ if (ca_check_is_pos_inf(x, ctx) == T_TRUE) ca_pos_inf(res, ctx); else if (ca_check_is_neg_inf(x, ctx) == T_TRUE) ca_neg_inf(res, ctx); else if (ca_check_is_pos_i_inf(x, ctx) == T_TRUE) ca_i(res, ctx); else if (ca_check_is_neg_i_inf(x, ctx) == T_TRUE) ca_neg_i(res, ctx); else if (ca_check_is_undefined(x, ctx) == T_TRUE || ca_check_is_uinf(x, ctx) == T_TRUE) ca_undefined(res, ctx); else ca_unknown(res, ctx); return; } if (ca_check_is_zero(x, ctx) == T_TRUE) { ca_zero(res, ctx); return; } _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Erfi, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/euler.c000066400000000000000000000011021461254215100152570ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_euler(ca_t res, ca_ctx_t ctx) { _ca_make_field_element(res, _ca_ctx_get_field_const(ctx, CA_Euler), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/exp.c000066400000000000000000000221051461254215100147450ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" int ca_as_fmpq_pi_i(fmpq_t res, const ca_t x, ca_ctx_t ctx) { ca_field_ptr K; ca_t t; int found; if (CA_IS_SPECIAL(x)) return 0; K = CA_FIELD(x, ctx); if (CA_FIELD_IS_QQ(K) || CA_FIELD_IS_NF(K)) return 0; ca_init(t, ctx); ca_pi_i(t, ctx); ca_div(t, x, t, ctx); if (CA_IS_QQ(t, ctx)) { fmpq_set(res, CA_FMPQ(t)); found = 1; } else { found = 0; } ca_clear(t, ctx); return found; } ca_ext_ptr ca_is_fmpq_times_gen_as_ext(fmpq_t c, const ca_t x, ca_ctx_t ctx) { ca_field_ptr K; if (CA_IS_SPECIAL(x)) return NULL; K = CA_FIELD(x, ctx); if (CA_FIELD_IS_QQ(K)) return NULL; /* todo */ if (CA_FIELD_IS_NF(K)) return NULL; if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx))) { if (fmpz_mpoly_length(fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx)) == 1) { fmpz_mpoly_q_t t; fmpz_t one; /* hack! */ *t = *CA_MPOLY_Q(x); *one = 1; fmpz_mpoly_q_numref(t)->coeffs = one; fmpz_mpoly_q_denref(t)->coeffs = one; if (fmpz_mpoly_is_gen(fmpz_mpoly_q_numref(t), -1, CA_FIELD_MCTX(K, ctx))) { slong i; fmpz_set(fmpq_numref(c), fmpz_mpoly_q_numref(CA_MPOLY_Q(x))->coeffs); fmpz_set(fmpq_denref(c), fmpz_mpoly_q_denref(CA_MPOLY_Q(x))->coeffs); for (i = 0; ; i++) if (fmpz_mpoly_is_gen(fmpz_mpoly_q_numref(t), i, CA_FIELD_MCTX(K, ctx))) return CA_FIELD_EXT_ELEM(K, i); } } } return NULL; } void ca_exp(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_ext_ptr ext; if (CA_IS_SPECIAL(x)) { /* todo: complex signed infinity -> 0, undefined, uinf */ if (ca_check_is_pos_inf(x, ctx) == T_TRUE) ca_pos_inf(res, ctx); else if (ca_check_is_neg_inf(x, ctx) == T_TRUE) ca_zero(res, ctx); else if (ca_check_is_undefined(x, ctx) == T_TRUE || ca_check_is_uinf(x, ctx) == T_TRUE) ca_undefined(res, ctx); else ca_unknown(res, ctx); return; } ext = ca_is_gen_as_ext(x, ctx); /* exp(log(z)) = z */ if (ext != NULL && CA_EXT_HEAD(ext) == CA_Log) { ca_set(res, CA_EXT_FUNC_ARGS(ext), ctx); return; } /* exp((p/q)*log(z)) = z^(p/q) */ /* todo: when to rewrite any exp(a*log(b)) -> b^a? */ { fmpq_t t; fmpq_init(t); ext = ca_is_fmpq_times_gen_as_ext(t, x, ctx); if (ext != NULL && CA_EXT_HEAD(ext) == CA_Log) { ca_pow_fmpq(res, CA_EXT_FUNC_ARGS(ext), t, ctx); fmpq_clear(t); return; } fmpq_clear(t); } if (ca_check_is_zero(x, ctx) == T_TRUE) { ca_one(res, ctx); return; } /* exp(p/q*pi*i) -> root of unity */ { fmpq_t t; fmpq_init(t); if (ca_as_fmpq_pi_i(t, x, ctx)) { if (fmpz_cmp_ui(fmpq_denref(t), ctx->options[CA_OPT_QQBAR_DEG_LIMIT]) <= 0) { slong p, q; qqbar_t a; q = fmpz_get_ui(fmpq_denref(t)); p = fmpz_fdiv_ui(fmpq_numref(t), 2 * q); if (q == 1) { if (p == 0) ca_one(res, ctx); else ca_neg_one(res, ctx); } else if (q == 2) { if (p == 1) ca_i(res, ctx); else ca_neg_i(res, ctx); } else { qqbar_init(a); qqbar_exp_pi_i(a, 1, q); ca_set_qqbar(res, a, ctx); ca_pow_ui(res, res, p, ctx); qqbar_clear(a); } fmpq_clear(t); return; } } fmpq_clear(t); } /* exp((p1/q1)*log(z1) + ... + S) = z1^(p1/q1) * ... * exp(S) */ { if (CA_FIELD_IS_GENERIC(CA_FIELD(x, ctx))) { fmpz_mpoly_ctx_struct * mctx; fmpz_mpoly_q_struct * rat; ca_field_ptr K; slong i, j, numer_len, field_len, ok, have_log, log_index; ulong * exp; K = CA_FIELD(x, ctx); field_len = CA_FIELD_LENGTH(K); mctx = CA_FIELD_MCTX(K, ctx); rat = CA_MPOLY_Q(x); exp = flint_malloc(field_len * sizeof(ulong)); /* todo: handle more complex cases (partial fraction decomposition?) */ if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(rat), mctx)) { numer_len = fmpz_mpoly_length(fmpz_mpoly_q_numref(rat), mctx); for (i = 0; i < numer_len; i++) { if (fmpz_mpoly_term_exp_fits_ui(fmpz_mpoly_q_numref(rat), i, mctx)) { fmpz_mpoly_get_term_exp_ui(exp, fmpz_mpoly_q_numref(rat), i, mctx); ok = 1; have_log = 0; log_index = 0; for (j = 0; j < field_len; j++) { if (exp[j] != 0 && (have_log || exp[j] > 1 || CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, j)) != CA_Log)) { ok = 0; break; } if (exp[j] == 1 && CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, j)) == CA_Log) { have_log = 1; log_index = j; continue; } } if (ok && have_log) { ca_t x_deflated, power; ca_init(x_deflated, ctx); ca_init(power, ctx); _ca_make_field_element(x_deflated, K, ctx); fmpz_mpoly_get_term(fmpz_mpoly_q_numref(CA_MPOLY_Q(x_deflated)), fmpz_mpoly_q_numref(rat), i, mctx); fmpz_mpoly_sub(fmpz_mpoly_q_numref(CA_MPOLY_Q(x_deflated)), fmpz_mpoly_q_numref(rat), fmpz_mpoly_q_numref(CA_MPOLY_Q(x_deflated)), mctx); fmpz_mpoly_set(fmpz_mpoly_q_denref(CA_MPOLY_Q(x_deflated)), fmpz_mpoly_q_denref(rat), mctx); fmpz_mpoly_q_canonicalise(CA_MPOLY_Q(x_deflated), mctx); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(x_deflated), K, ctx); ca_condense_field(x_deflated, ctx); ca_set_fmpz(power, fmpz_mpoly_q_numref(rat)->coeffs + i, ctx); ca_div_fmpz(power, power, fmpz_mpoly_q_denref(rat)->coeffs, ctx); ca_pow(power, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, log_index)), power, ctx); ca_exp(x_deflated, x_deflated, ctx); ca_mul(res, power, x_deflated, ctx); ca_clear(x_deflated, ctx); ca_clear(power, ctx); flint_free(exp); return; } } } } flint_free(exp); } } /* Could be optional: csgn normalization */ if (0) { ca_t t; ca_init(t, ctx); ca_sgn(t, x, ctx); if (ca_check_is_neg_one(t, ctx) == T_TRUE) { ca_neg(t, x, ctx); _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Exp, t), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); fmpz_mpoly_q_inv(CA_MPOLY_Q(res), CA_MPOLY_Q(res), CA_MCTX_1(ctx)); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), CA_FIELD(res, ctx), ctx); ca_condense_field(res, ctx); } else { _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Exp, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), CA_FIELD(res, ctx), ctx); ca_condense_field(res, ctx); } return; } _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Exp, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), CA_FIELD(res, ctx), ctx); ca_condense_field(res, ctx); } flint-3.1.3/src/ca/factor.c000066400000000000000000000136341461254215100154360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" #include "fmpz_mpoly_factor.h" #include "ca.h" #define HAVE_MPOLY_FAC 1 void _ca_factor_fmpz(ca_factor_t res, const fmpz_t x, int inv, ulong flags, ca_ctx_t ctx) { slong i; fmpz_factor_t fac; ca_t b, e; if (fmpz_is_one(x)) return; fmpz_factor_init(fac); if (flags & CA_FACTOR_ZZ_FULL) { fmpz_factor(fac, x); } else if (flags & CA_FACTOR_ZZ_SMOOTH) { slong smooth_limit = ctx->options[CA_OPT_SMOOTH_LIMIT]; fmpz_factor_smooth(fac, x, smooth_limit, -1); /* -1 => no primality test */ } else flint_throw(FLINT_ERROR, "(%s)\n", __func__); ca_init(b, ctx); ca_init(e, ctx); if (fac->sign != 1) { ca_set_si(b, fac->sign, ctx); ca_one(e, ctx); ca_factor_insert(res, b, e, ctx); } for (i = 0; i < fac->num; i++) { ca_set_fmpz(b, fac->p + i, ctx); ca_set_si(e, inv ? -(slong)(fac->exp[i]) : (fac->exp[i]), ctx); ca_factor_insert(res, b, e, ctx); } fmpz_factor_clear(fac); ca_clear(b, ctx); ca_clear(e, ctx); } void _ca_factor_fmpq(ca_factor_t res, const fmpq_t x, ulong flags, ca_ctx_t ctx) { if (flags & (CA_FACTOR_ZZ_SMOOTH | CA_FACTOR_ZZ_FULL)) { _ca_factor_fmpz(res, fmpq_numref(x), 0, flags, ctx); _ca_factor_fmpz(res, fmpq_denref(x), 1, flags, ctx); } else if (!fmpq_is_one(x)) { ca_t b, e; ca_init(b, ctx); ca_init(e, ctx); ca_set_fmpq(b, x, ctx); ca_one(e, ctx); ca_factor_insert(res, b, e, ctx); ca_clear(b, ctx); ca_clear(e, ctx); } } static int _ca_fmpz_mpoly_factor(fmpz_mpoly_factor_t fac, const fmpz_mpoly_t poly, int full, const fmpz_mpoly_ctx_t ctx) { if (full) return fmpz_mpoly_factor(fac, poly, ctx); else return fmpz_mpoly_factor_squarefree(fac, poly, ctx); } void ca_factor(ca_factor_t res, const ca_t x, ulong flags, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { flint_throw(FLINT_ERROR, "ca_factor: expected a non-special value\n"); } ca_factor_one(res, ctx); if (CA_IS_QQ(x, ctx)) { _ca_factor_fmpq(res, CA_FMPQ(x), flags, ctx); return; } /* todo: factoring in number fields */ if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { ca_t e; ca_init(e, ctx); ca_one(e, ctx); ca_factor_insert(res, x, e, ctx); ca_clear(e, ctx); return; } { if (flags & (CA_FACTOR_POLY_CONTENT | CA_FACTOR_POLY_SQF | CA_FACTOR_POLY_FULL)) { const fmpz_mpoly_ctx_struct * mctx; ca_t b, e; fmpq_t content; mctx = CA_FIELD_MCTX(CA_FIELD(x, ctx), ctx); fmpq_init(content); ca_init(b, ctx); ca_init(e, ctx); #if HAVE_MPOLY_FAC if (flags & (CA_FACTOR_POLY_SQF | CA_FACTOR_POLY_FULL)) { int full; slong i; fmpz_mpoly_factor_t mfac; full = (flags & CA_FACTOR_POLY_FULL) ? 1 : 0; fmpz_mpoly_factor_init(mfac, mctx); if (!_ca_fmpz_mpoly_factor(mfac, fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), full, mctx)) { flint_throw(FLINT_ERROR, "ca_factor: unable to factor numerator\n"); } for (i = 0; i < mfac->num; i++) { ca_set_fmpz(e, mfac->exp + i, ctx); _ca_make_field_element(b, CA_FIELD(x, ctx), ctx); fmpz_mpoly_swap(fmpz_mpoly_q_numref(CA_MPOLY_Q(b)), mfac->poly + i, mctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(CA_MPOLY_Q(b)), mctx); ca_factor_insert(res, b, e, ctx); } fmpz_set(fmpq_numref(content), mfac->constant); fmpz_mpoly_factor_clear(mfac, mctx); fmpz_mpoly_factor_init(mfac, mctx); if (!_ca_fmpz_mpoly_factor(mfac, fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), full, mctx)) { flint_throw(FLINT_ERROR, "ca_factor: unable to factor denominator\n"); } for (i = 0; i < mfac->num; i++) { ca_set_fmpz(e, mfac->exp + i, ctx); ca_neg(e, e, ctx); _ca_make_field_element(b, CA_FIELD(x, ctx), ctx); fmpz_mpoly_swap(fmpz_mpoly_q_numref(CA_MPOLY_Q(b)), mfac->poly + i, mctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(CA_MPOLY_Q(b)), mctx); ca_factor_insert(res, b, e, ctx); } fmpz_set(fmpq_denref(content), mfac->constant); fmpz_mpoly_factor_clear(mfac, mctx); } else #endif { fmpz_mpoly_q_content(content, CA_MPOLY_Q(x), mctx); ca_div_fmpq(b, x, content, ctx); ca_one(e, ctx); ca_factor_insert(res, b, e, ctx); } if (fmpz_sgn(fmpq_denref(content)) < 0) { fmpz_neg(fmpq_numref(content), fmpq_numref(content)); fmpz_neg(fmpq_denref(content), fmpq_denref(content)); } _ca_factor_fmpq(res, content, flags, ctx); ca_clear(b, ctx); ca_clear(e, ctx); fmpq_clear(content); } else { ca_t e; ca_init(e, ctx); ca_one(e, ctx); ca_factor_insert(res, x, e, ctx); ca_clear(e, ctx); } } } flint-3.1.3/src/ca/factor_clear.c000066400000000000000000000011461461254215100165770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_vec.h" void ca_factor_clear(ca_factor_t fac, ca_ctx_t ctx) { if (fac->alloc != 0) { _ca_vec_clear(fac->base, fac->alloc, ctx); _ca_vec_clear(fac->exp, fac->alloc, ctx); } } flint-3.1.3/src/ca/factor_get_ca.c000066400000000000000000000016501461254215100167330ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_factor_get_ca(ca_t res, const ca_factor_t fac, ca_ctx_t ctx) { slong i, len; ca_t t; len = fac->length; if (len == 0) { ca_one(res, ctx); } else if (len == 1) { ca_pow(res, fac->base, fac->exp, ctx); } else { ca_init(t, ctx); ca_pow(res, fac->base, fac->exp, ctx); for (i = 1; i < len; i++) { ca_pow(t, fac->base + i, fac->exp + i, ctx); ca_mul(res, res, t, ctx); } ca_clear(t, ctx); } } flint-3.1.3/src/ca/factor_init.c000066400000000000000000000010331461254215100164470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_factor_init(ca_factor_t fac, ca_ctx_t ctx) { fac->base = NULL; fac->exp = NULL; fac->length = 0; fac->alloc = 0; } flint-3.1.3/src/ca/factor_insert.c000066400000000000000000000024121461254215100170120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_factor_insert(ca_factor_t fac, const ca_t base, const ca_t exp, ca_ctx_t ctx) { slong i; for (i = 0; i < fac->length; i++) { if (ca_equal_repr(fac->base + i, base, ctx)) { ca_add(fac->exp, fac->exp, exp, ctx); return; } } if (fac->length == fac->alloc) { slong new_alloc; new_alloc = FLINT_MAX(1, 2 * fac->alloc); fac->base = (ca_ptr) flint_realloc(fac->base, sizeof(ca_struct) * new_alloc); fac->exp = (ca_ptr) flint_realloc(fac->exp, sizeof(ca_struct) * new_alloc); for (i = fac->alloc; i < new_alloc; i++) { ca_init(fac->base + i, ctx); ca_init(fac->exp + i, ctx); } fac->alloc = new_alloc; } ca_set(fac->base + fac->length, base, ctx); ca_set(fac->exp + fac->length, exp, ctx); fac->length++; } flint-3.1.3/src/ca/factor_one.c000066400000000000000000000011451461254215100162710ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_factor_one(ca_factor_t fac, ca_ctx_t ctx) { slong i; for (i = 0; i < fac->length; i++) { ca_zero(fac->base + i, ctx); ca_zero(fac->exp + i, ctx); } fac->length = 0; } flint-3.1.3/src/ca/floor.c000066400000000000000000000040171461254215100152740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_floor(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_UNKNOWN(x)) ca_unknown(res, ctx); else ca_undefined(res, ctx); return; } if (CA_IS_QQ(x, ctx)) { fmpz_t t; fmpz_init(t); fmpz_fdiv_q(t, CA_FMPQ_NUMREF(x), CA_FMPQ_DENREF(x)); ca_set_fmpz(res, t, ctx); fmpz_clear(t); return; } { slong prec, prec_limit; acb_t v; mag_t m; fmpz_t n; int success = 0; acb_init(v); mag_init(m); fmpz_init(n); prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, 64); for (prec = 64; (prec <= prec_limit) && !success; prec *= 2) { ca_get_acb_raw(v, x, prec, ctx); arb_get_mag(m, acb_realref(v)); if (arb_is_finite(acb_imagref(v)) && mag_cmp_2exp_si(m, prec_limit) <= 0) { arb_floor(acb_realref(v), acb_realref(v), prec); if (arb_get_unique_fmpz(n, acb_realref(v))) { ca_set_fmpz(res, n, ctx); success = 1; break; } } arb_get_mag_lower(m, acb_realref(v)); if (mag_cmp_2exp_si(m, prec_limit) > 0) break; } acb_clear(v); mag_clear(m); fmpz_clear(n); if (success) return; } _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Floor, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/fmpq_poly_evaluate.c000066400000000000000000000031321461254215100200440ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" static void _ca_set_fmpq(ca_t x, const fmpz_t p, const fmpz_t q, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpz_set(CA_FMPQ_NUMREF(x), p); fmpz_set(CA_FMPQ_DENREF(x), q); } void ca_fmpq_poly_evaluate(ca_t res, const fmpq_poly_t poly, const ca_t x, ca_ctx_t ctx) { if (fmpq_poly_is_zero(poly)) { ca_zero(res, ctx); } else if (fmpq_poly_length(poly) == 1) { _ca_set_fmpq(res, poly->coeffs + 0, poly->den, ctx); } else if (CA_IS_QQ(x, ctx)) { fmpq_t t; fmpq_init(t); fmpq_poly_evaluate_fmpq(t, poly, CA_FMPQ(x)); ca_set_fmpq(res, t, ctx); fmpq_clear(t); } /* todo: fast modular composition for number field elements */ /* else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) */ else { ca_t t; /* for aliasing */ slong i, n; ca_init(t, ctx); /* todo: rectangular splitting? */ n = fmpq_poly_degree(poly); ca_set_fmpz(t, poly->coeffs + n, ctx); for (i = n - 1; i >= 0; i--) { ca_mul(t, t, x, ctx); ca_add_fmpz(t, t, poly->coeffs + i, ctx); } ca_div_fmpz(res, t, poly->den, ctx); ca_clear(t, ctx); } } flint-3.1.3/src/ca/fmpz_mpoly_evaluate.c000066400000000000000000000261551461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" #include "ca.h" /* The conversion to Horner form can be stated as recursive. However, the call stack has depth proportial to the length of the input polynomial in the worst case. Therefore, we must convert it to an iterative algorithm. The proceedure is HornerForm(f): if f is simple to evaluate return eval(f) else choose a variable v and the smallest non zero exponent e appearing in the terms of f write f = q * v^e + r where r is independent of the variable v return HornerForm(q) * v^e + HornerForm(r) */ typedef struct { slong f; slong r; slong v_var; fmpz_t v_exp; /* will be managed as stack grows / shrinks */ int ret; } stack_entry_struct; typedef stack_entry_struct stack_entry_t[1]; /* A = A * X^pow */ /* todo: cache squares, ...? */ static void _ca_pmul(ca_t A, const ca_t X, const fmpz_t pow, ca_t T, ca_ctx_t ctx) { if (fmpz_is_one(pow)) { ca_mul(A, A, X, ctx); } else { ca_pow_fmpz(T, X, pow, ctx); ca_mul(A, A, T, ctx); } } void ca_fmpz_mpoly_evaluate_horner(ca_t A, const fmpz_mpoly_t B, ca_srcptr C, const fmpz_mpoly_ctx_t ctxB, ca_ctx_t ctx) { int ret; slong nvars = ctxB->minfo->nvars; slong i, j, k, cur, next, f, r, f_prev, r_prev, v; slong sp, rp; stack_entry_struct * stack; ca_struct * regs; ca_t temp; slong * rtypes; ulong totalcounts, maxcounts; ulong * counts; slong Blen = B->length; slong * Blist; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fmpz * Buexp; fmpz * mdegs; fmpz_t score, tz; TMP_INIT; if (Blen == 0) { ca_zero(A, ctx); return; } if (Blen == 1 && fmpz_mpoly_is_fmpz(B, ctxB)) { ca_set_fmpz(A, B->coeffs, ctx); return; } /* flint_printf("========================== HORNER %wd ==========================\n", Blen); */ FLINT_ASSERT(Blen > 0); TMP_START; fmpz_init(score); fmpz_init(tz); /* unpack B exponents */ Buexp = _fmpz_vec_init(nvars*Blen); for (i = 0; i < Blen; i++) mpoly_get_monomial_ffmpz(Buexp + nvars*i, Bexp + BN*i, Bbits, ctxB->minfo); counts = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); mdegs = _fmpz_vec_init(nvars); /* stack */ sp = -WORD(1); /* start with empty stack */ stack = (stack_entry_struct *) TMP_ALLOC(nvars*(Blen + 1)*sizeof(stack_entry_struct)); Blist = (slong *) TMP_ALLOC(Blen*sizeof(slong)); /* registers of qqbars */ rp = 0; rtypes = (slong *) TMP_ALLOC((nvars + 1)*sizeof(slong)); regs = (ca_struct *) TMP_ALLOC(nvars*sizeof(ca_struct)); for (i = 0; i < nvars; i++) ca_init(regs + i, ctx); ca_init(temp, ctx); /* polynomials will be stored as link lists */ for (i = 0; i + 1 < Blen; i++) Blist[i] = i + 1; Blist[i] = -WORD(1); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 0; (stack + sp)->f = 0; HornerForm: f = (stack + sp)->f; FLINT_ASSERT(f != -WORD(1)); /* f is not supposed to be zero */ /* obtain a count of the number of terms containing each variable */ for (i = 0; i < nvars; i++) { counts[i] = 0; fmpz_set_si(mdegs + i, -WORD(1)); } for (j = f; j != -WORD(1); j = Blist[j]) { for (i = 0; i < nvars; i++) { if (!fmpz_is_zero(Buexp + nvars*j + i )) { counts[i]++; if (fmpz_sgn(mdegs + i) < 0 || fmpz_cmp(mdegs + i, Buexp + nvars*j + i) > 0) { fmpz_set(mdegs + i, Buexp + nvars*j + i); } } } } totalcounts = 0; maxcounts = 0; v = -WORD(1); for (i = 0; i < nvars; i++) { maxcounts = FLINT_MAX(maxcounts, counts[i]); totalcounts += counts[i]; if (counts[i] != 0) v = i; } /* handle simple cases */ if (totalcounts == 0) { FLINT_ASSERT(Blist[f] == -WORD(1)); /* f should have had only one term */ rtypes[rp] = f; goto HornerFormReturn; } else if (totalcounts == 1) { FLINT_ASSERT(!fmpz_is_zero(Buexp + nvars*f + v)); /* this term should not be a scalar */ ca_pow_fmpz(regs + rp, C + v, Buexp + nvars*f + v, ctx); ca_mul_fmpz(regs + rp, regs + rp, Bcoeff + f, ctx); if (Blist[f] != -WORD(1)) /* if f has a second term */ { /* this term should be a scalar */ FLINT_ASSERT(fmpz_is_zero(Buexp + nvars*Blist[f] + v)); ca_add_fmpz(regs + rp, regs + rp, Bcoeff + Blist[f], ctx); } rtypes[rp] = -WORD(1); goto HornerFormReturn; } /* pick best power to pull out */ k = 0; if (maxcounts == 1) { fmpz_set_si(score, -WORD(1)); for (i = 0; i < nvars; i++) { if (counts[i] == 1 && (fmpz_sgn(score) < 0 || fmpz_cmp(mdegs + i, score) < 0)) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_set(score, mdegs + i); k = i; } } } else { fmpz_zero(score); for (i = 0; i < nvars; i++) { if (counts[i] > 1) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_mul_ui(tz, mdegs + i, counts[i] - 1); if (fmpz_cmp(tz, score) > 0) { fmpz_swap(score, tz); k = i; } } } } /* set variable power v */ (stack + sp)->v_var = k; fmpz_set((stack + sp)->v_exp, mdegs + k); /* scan f and split into q and v with f = q*v + r then set f = q */ r = -WORD(1); cur = f; f_prev = -WORD(1); r_prev = -WORD(1); while (cur != -WORD(1)) { next = Blist[cur]; if (fmpz_is_zero(Buexp + nvars*cur + k)) { if (f_prev == -WORD(1)) f = Blist[cur]; else Blist[f_prev] = Blist[cur]; if (r_prev == -WORD(1)) r = cur; else Blist[r_prev] = cur; Blist[cur] = -WORD(1); r_prev = cur; } else { /* mdegs[k] should be minimum non zero exponent */ fmpz_sub(Buexp + nvars*cur + k, Buexp + nvars*cur + k, mdegs + k); FLINT_ASSERT(fmpz_sgn(Buexp + nvars*cur + k) >= 0); f_prev = cur; } cur = next; } (stack + sp)->r = r; /* convert the quotient */ sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 1; (stack + sp)->f = f; goto HornerForm; HornerForm1: /* convert the remainder */ r = (stack + sp)->r; if (r != -WORD(1)) { /* remainder is non zero */ rp++; FLINT_ASSERT(0 <= rp && rp <= nvars); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 2; (stack + sp)->f = r; goto HornerForm; HornerForm2: if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] == -WORD(1)) { /* both quotient and remainder are polynomials */ _ca_pmul(regs + rp - 1, C + (stack + sp)->v_var, (stack + sp)->v_exp, temp, ctx); ca_add(temp, regs + rp - 1, regs + rp, ctx); ca_swap(temp, regs + rp - 1, ctx); } else if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] != -WORD(1)) { /* quotient is a polynomial, remainder is a scalar */ _ca_pmul(regs + rp - 1, C + (stack + sp)->v_var, (stack + sp)->v_exp, temp, ctx); ca_add_fmpz(regs + rp - 1, regs + rp - 1, Bcoeff + rtypes[rp], ctx); } else if (rtypes[rp - 1] != -WORD(1) && rtypes[rp] == -WORD(1)) { /* quotient is a scalar, remainder is a polynomial */ ca_pow_fmpz(temp, C + (stack + sp)->v_var, (stack + sp)->v_exp, ctx); ca_mul_fmpz(temp, temp, Bcoeff + rtypes[rp - 1], ctx); ca_add(regs + rp - 1, temp, regs + rp, ctx); } else { /* quotient is a scalar, remainder is a scalar */ FLINT_ASSERT(0); /* this should have been handled by simple case */ } rp--; FLINT_ASSERT(0 <= rp && rp <= nvars); } else { /* remainder is zero */ FLINT_ASSERT(rtypes[rp] == -WORD(1)); /* quotient is not a scalar */ /* quotient is a polynomial */ _ca_pmul(regs + rp, C + (stack + sp)->v_var, (stack + sp)->v_exp, temp, ctx); } rtypes[rp] = -WORD(1); HornerFormReturn: ret = (stack + sp)->ret; fmpz_clear((stack + sp)->v_exp); sp--; if (ret == 1) goto HornerForm1; if (ret == 2) goto HornerForm2; FLINT_ASSERT(rp == 0); FLINT_ASSERT(sp == -WORD(1)); if (rtypes[rp] == -WORD(1)) { ca_swap(A, regs + rp, ctx); } else { ca_set_fmpz(A, Bcoeff + rtypes[rp], ctx); } for (i = 0; i < nvars; i++) ca_clear(regs + i, ctx); ca_clear(temp, ctx); fmpz_clear(score); fmpz_clear(tz); _fmpz_vec_clear(mdegs, nvars); _fmpz_vec_clear(Buexp, nvars*Blen); TMP_END; } /* todo: accept fmpz exponents */ void ca_evaluate_fmpz_mpoly_iter(ca_t res, const fmpz_mpoly_t pol, ca_srcptr x, const fmpz_mpoly_ctx_t ctx, ca_ctx_t cactx) { slong i, j, len, nvars; ca_t s, t, u; ulong * exp; len = fmpz_mpoly_length(pol, ctx); if (len == 0) { ca_zero(res, cactx); return; } if (len == 1 && fmpz_mpoly_is_fmpz(pol, ctx)) { ca_set_fmpz(res, pol->coeffs, cactx); return; } nvars = ctx->minfo->nvars; exp = flint_malloc(sizeof(ulong) * nvars); ca_init(s, cactx); ca_init(t, cactx); ca_init(u, cactx); for (i = 0; i < len; i++) { fmpz_mpoly_get_term_exp_ui(exp, pol, i, ctx); ca_one(t, cactx); for (j = 0; j < nvars; j++) { if (exp[j] == 1) { ca_mul(t, t, x + j, cactx); } else if (exp[j] >= 2) { ca_pow_ui(u, x + j, exp[j], cactx); ca_mul(t, t, u, cactx); } } ca_mul_fmpz(t, t, pol->coeffs + i, cactx); ca_add(s, s, t, cactx); } ca_swap(res, s, cactx); flint_free(exp); ca_clear(s, cactx); ca_clear(t, cactx); ca_clear(u, cactx); } void ca_fmpz_mpoly_evaluate(ca_t res, const fmpz_mpoly_t f, ca_srcptr x, const fmpz_mpoly_ctx_t ctx, ca_ctx_t cactx) { ca_fmpz_mpoly_evaluate_horner(res, f, x, ctx, cactx); } flint-3.1.3/src/ca/fmpz_mpoly_q_evaluate.c000066400000000000000000000024141461254215100205540ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_fmpz_mpoly_q_evaluate(ca_t res, const fmpz_mpoly_q_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_fmpz_mpoly_evaluate(t, fmpz_mpoly_q_numref(f), x, mctx, ctx); ca_fmpz_mpoly_evaluate(u, fmpz_mpoly_q_denref(f), x, mctx, ctx); ca_div(res, t, u, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } void ca_fmpz_mpoly_q_evaluate_no_division_by_zero(ca_t res, const fmpz_mpoly_q_t f, ca_srcptr x, const fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_fmpz_mpoly_evaluate(t, fmpz_mpoly_q_numref(f), x, mctx, ctx); ca_fmpz_mpoly_evaluate(u, fmpz_mpoly_q_denref(f), x, mctx, ctx); /* todo: write a div function for this */ ca_inv_no_division_by_zero(u, u, ctx); ca_mul(res, t, u, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } flint-3.1.3/src/ca/fmpz_poly_evaluate.c000066400000000000000000000025511461254215100200610ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_fmpz_poly_evaluate(ca_t res, const fmpz_poly_t poly, const ca_t x, ca_ctx_t ctx) { if (fmpz_poly_is_zero(poly)) { ca_zero(res, ctx); } else if (fmpz_poly_length(poly) == 1) { ca_set_fmpz(res, poly->coeffs + 0, ctx); } else if (CA_IS_QQ(x, ctx)) { fmpq_t t; fmpq_init(t); fmpz_poly_evaluate_fmpq(t, poly, CA_FMPQ(x)); ca_set_fmpq(res, t, ctx); fmpq_clear(t); } /* todo: fast modular composition for number field elements */ /* else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) */ else { ca_t t; /* for aliasing */ slong i, n; ca_init(t, ctx); /* todo: rectangular splitting? */ n = fmpz_poly_degree(poly); ca_set_fmpz(t, poly->coeffs + n, ctx); for (i = n - 1; i >= 0; i--) { ca_mul(t, t, x, ctx); ca_add_fmpz(t, t, poly->coeffs + i, ctx); } ca_clear(t, ctx); } } flint-3.1.3/src/ca/gamma.c000066400000000000000000000106451461254215100152410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_gamma_inert(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } else { _ca_function_fx(res, CA_Gamma, x, ctx); } } void _ca_gamma_verbatim(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t y, tmp; ca_init(y, ctx); ca_init(tmp, ctx); _ca_function_fx(y, CA_Gamma, x, ctx); ca_merge_fields(tmp, res, x, y, ctx); ca_clear(y, ctx); ca_clear(tmp, ctx); } truth_t ca_re_is_positive(const ca_t x, ca_ctx_t ctx) { ca_t t, u; truth_t res; ca_init(t, ctx); ca_init(u, ctx); ca_re(t, x, ctx); res = ca_check_gt(t, u, ctx); ca_clear(t, ctx); ca_clear(u, ctx); return res; } void ca_gamma(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { /* todo: other signs */ if (ca_check_is_pos_inf(x, ctx)) { ca_pos_inf(res, ctx); } else if (ca_check_is_neg_inf(x, ctx) || ca_check_is_undefined(x, ctx) || ca_check_is_uinf(x, ctx)) { ca_undefined(res, ctx); } else if (ca_check_is_pos_i_inf(x, ctx) || ca_check_is_neg_i_inf(x, ctx)) { ca_zero(res, ctx); } else { ca_unknown(res, ctx); } } else { truth_t is_integer, is_positive; slong expand_limit; expand_limit = ctx->options[CA_OPT_PREC_LIMIT]; is_integer = ca_check_is_integer(x, ctx); if (is_integer == T_TRUE) { is_positive = ca_re_is_positive(x, ctx); if (is_positive == T_TRUE) { fmpz_t t; fmpz_init(t); if (ca_get_fmpz(t, x, ctx) && fmpz_cmp_ui(t, expand_limit) < 0) { fmpz_fac_ui(t, fmpz_get_ui(t) - 1); ca_set_fmpz(res, t, ctx); } else { /* todo: may want to use the potentially simplified x (to an integer) here... */ _ca_gamma_verbatim(res, x, ctx); } fmpz_clear(t); } else if (is_positive == T_FALSE) { ca_uinf(res, ctx); } else { ca_unknown(res, ctx); } } else if (is_integer == T_FALSE) { ca_t y; fmpz_t t, u; slong n; ca_init(y, ctx); fmpz_init(t); fmpz_init(u); ca_set_d(y, 0.5, ctx); ca_sub(y, x, y, ctx); if (ca_get_fmpz(t, y, ctx) && fmpz_cmp_si(t, expand_limit) < 0 && fmpz_cmp_si(t, -expand_limit) > 0) { n = fmpz_get_si(t); ca_pi(res, ctx); ca_sqrt(res, res, ctx); if (n != 0) { if (n >= 0) { fmpz_fac_ui(t, 2 * n); fmpz_fac_ui(u, n); fmpz_mul_2exp(u, u, 2 * n); } else { fmpz_fac_ui(t, -n); fmpz_mul_2exp(t, t, -2 * n); fmpz_fac_ui(u, -2 * n); if (n & 1) fmpz_neg(t, t); } ca_mul_fmpz(res, res, t, ctx); ca_div_fmpz(res, res, u, ctx); } } else { _ca_gamma_verbatim(res, x, ctx); } ca_clear(y, ctx); fmpz_clear(t); fmpz_clear(u); } else { is_positive = ca_re_is_positive(x, ctx); if (is_positive == T_TRUE) { _ca_gamma_verbatim(res, x, ctx); } else { ca_unknown(res, ctx); } } } } flint-3.1.3/src/ca/get_acb.c000066400000000000000000000053501461254215100155400ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_fmpz_poly.h" #include "ca.h" void ca_get_acb(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx) { slong wp, initial, maxprec, exact_check_prec; acb_indeterminate(res); initial = prec * 1.05 + 30; maxprec = FLINT_MAX(2 * initial, ctx->options[CA_OPT_PREC_LIMIT]); exact_check_prec = FLINT_MIN(maxprec, initial * 16); for (wp = initial; wp <= maxprec; wp *= 2) { ca_get_acb_raw(res, x, wp, ctx); if (acb_rel_accuracy_bits(res) >= prec) break; if (wp == exact_check_prec) { if (ca_check_is_zero(x, ctx) == T_TRUE) { acb_zero(res); break; } } } } void ca_get_acb_accurate_parts(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx) { slong wp, initial, maxprec, exact_check_prec; int re_ok, im_ok; acb_indeterminate(res); initial = prec * 1.05 + 30; maxprec = FLINT_MAX(2 * initial, ctx->options[CA_OPT_PREC_LIMIT]); exact_check_prec = FLINT_MIN(maxprec, initial * 16); for (wp = initial; wp <= maxprec; wp *= 2) { ca_get_acb_raw(res, x, wp, ctx); re_ok = arb_rel_accuracy_bits(acb_realref(res)) >= prec; im_ok = arb_rel_accuracy_bits(acb_imagref(res)) >= prec; if (re_ok && im_ok) break; if (wp == exact_check_prec) { if (acb_rel_accuracy_bits(res) < prec && ca_check_is_zero(x, ctx) == T_TRUE) { acb_zero(res); break; } if (re_ok && ca_check_is_real(x, ctx) == T_TRUE) { arb_zero(acb_imagref(res)); break; } if (im_ok && ca_check_is_imaginary(x, ctx) == T_TRUE) { arb_zero(acb_realref(res)); break; } } } } char * ca_get_decimal_str(const ca_t x, slong digits, ulong flags, ca_ctx_t ctx) { calcium_stream_t t; acb_t v; digits = FLINT_MAX(digits, 1); acb_init(v); calcium_stream_init_str(t); if (flags & 1) ca_get_acb_accurate_parts(v, x, digits * 3.333 + 1, ctx); else ca_get_acb(v, x, digits * 3.333 + 1, ctx); if (acb_is_finite(v)) calcium_write_acb(t, v, digits, ARB_STR_NO_RADIUS); else calcium_write(t, "?"); acb_clear(v); return t->s; } flint-3.1.3/src/ca/get_acb_raw.c000066400000000000000000000050531461254215100164110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_fmpz_poly.h" #include "ca.h" #include "ca_ext.h" void ca_get_acb_raw(acb_t res, const ca_t x, slong prec, ca_ctx_t ctx) { ca_field_srcptr xfield; if (CA_IS_SPECIAL(x)) { acb_indeterminate(res); return; } if (CA_IS_QQ(x, ctx)) { acb_set_fmpq(res, CA_FMPQ(x), prec); return; } if (CA_IS_QQ_I(x, ctx)) { const fmpz *n, *d; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); d = QNF_ELEM_DENREF(CA_NF_ELEM(x)); if (fmpz_is_one(d)) { arb_set_round_fmpz(acb_realref(res), n, prec); arb_set_round_fmpz(acb_imagref(res), n + 1, prec); } else { arb_fmpz_div_fmpz(acb_realref(res), n, d, prec); arb_fmpz_div_fmpz(acb_imagref(res), n + 1, d, prec); } return; } xfield = CA_FIELD(x, ctx); if (CA_FIELD_IS_NF(xfield)) { if (CA_FIELD_NF(xfield)->flag & NF_LINEAR) flint_throw(FLINT_ERROR, "(%s)\n", __func__); ca_ext_get_acb_raw(res, CA_FIELD_EXT_ELEM(xfield, 0), prec, ctx); if (CA_FIELD_NF(xfield)->flag & NF_QUADRATIC) { _arb_fmpz_poly_evaluate_acb(res, QNF_ELEM_NUMREF(CA_NF_ELEM(x)), 2, res, prec); acb_div_fmpz(res, res, QNF_ELEM_DENREF(CA_NF_ELEM(x)), prec); } else { _arb_fmpz_poly_evaluate_acb(res, NF_ELEM_NUMREF(CA_NF_ELEM(x)), NF_ELEM(CA_NF_ELEM(x))->length, res, prec); acb_div_fmpz(res, res, NF_ELEM_DENREF(CA_NF_ELEM(x)), prec); } } else { acb_ptr v; slong i, n; n = CA_FIELD_LENGTH(xfield); if (n == 1) { ca_ext_get_acb_raw(res, CA_FIELD_EXT_ELEM(xfield, 0), prec, ctx); fmpz_mpoly_q_evaluate_acb(res, CA_MPOLY_Q(x), res, prec, CA_FIELD_MCTX(xfield, ctx)); } else { v = _acb_vec_init(n); for (i = 0; i < n; i++) ca_ext_get_acb_raw(v + i, CA_FIELD_EXT_ELEM(xfield, i), prec, ctx); fmpz_mpoly_q_evaluate_acb(res, CA_MPOLY_Q(x), v, prec, CA_FIELD_MCTX(xfield, ctx)); _acb_vec_clear(v, n); } } } flint-3.1.3/src/ca/get_fexpr.c000066400000000000000000000253621461254215100161440ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #include "ca.h" #include "ca_ext.h" #include "fexpr.h" #include "fexpr_builtin.h" void _fexpr_set_fmpz_poly_decreasing(fexpr_t res, const fmpz * coeffs, slong len, const fexpr_t var) { slong i, j, num_terms; fexpr_ptr terms; fexpr_t t, u; if (len == 1) { fexpr_set_fmpz(res, coeffs); return; } num_terms = 0; for (i = 0; i < len; i++) num_terms += !fmpz_is_zero(coeffs + i); if (num_terms == 0) { fexpr_zero(res); return; } fexpr_init(t); fexpr_init(u); terms = _fexpr_vec_init(num_terms); j = 0; for (i = len - 1; i >= 0; i--) { if (!fmpz_is_zero(coeffs + i)) { if (i == 0) { fexpr_set_fmpz(terms + j, coeffs + i); } else { if (i == 1) { fexpr_set(u, var); } else { fexpr_set_ui(t, i); fexpr_pow(u, var, t); } if (fmpz_is_one(coeffs + i)) { fexpr_set(terms + j, u); } else { fexpr_set_fmpz(t, coeffs + i); fexpr_mul(terms + j, t, u); } } j++; } } if (num_terms == 1) { fexpr_swap(res, terms); } else { fexpr_set_symbol_builtin(t, FEXPR_Add); fexpr_call_vec(res, t, terms, num_terms); } _fexpr_vec_clear(terms, num_terms); fexpr_clear(t); fexpr_clear(u); } void fexpr_set_nf_elem(fexpr_t res, const nf_elem_t a, const nf_t nf, const fexpr_t var) { const fmpz * num; const fmpz * den; slong len; if (nf_elem_is_zero(a, nf)) { fexpr_zero(res); return; } if (nf->flag & NF_LINEAR) { den = LNF_ELEM_DENREF(a); num = LNF_ELEM_NUMREF(a); len = 1 - fmpz_is_zero(num); } else if (nf->flag & NF_QUADRATIC) { den = QNF_ELEM_DENREF(a); num = QNF_ELEM_NUMREF(a); len = 3; while (len != 0 && fmpz_is_zero(num + len - 1)) len--; } else { den = NF_ELEM(a)->den; num = NF_ELEM(a)->coeffs; len = NF_ELEM(a)->length; } if (fmpz_is_one(den)) { _fexpr_set_fmpz_poly_decreasing(res, num, len, var); } else { fexpr_t p, q; fexpr_init(p); fexpr_init(q); _fexpr_set_fmpz_poly_decreasing(p, num, len, var); fexpr_set_fmpz(q, den); fexpr_div(res, p, q); fexpr_clear(p); fexpr_clear(q); } } void ca_all_extensions(ca_ext_ptr ** extensions, slong * len, const ca_t x, ca_ctx_t ctx); void _ca_get_fexpr_given_ext(fexpr_t res, const ca_t x, ulong flags, ca_ext_ptr * ext, slong num_ext, const fexpr_struct * ext_vars, ca_ctx_t ctx) { ca_field_ptr K; ca_ext_ptr X; slong i, ext_pos; if (CA_IS_QQ(x, ctx)) { fexpr_set_fmpq(res, CA_FMPQ(x)); return; } if (CA_IS_UNKNOWN(x)) { fexpr_set_symbol_builtin(res, FEXPR_Unknown); return; } if (CA_IS_UNDEFINED(x)) { fexpr_set_symbol_builtin(res, FEXPR_Undefined); return; } if (CA_IS_UNSIGNED_INF(x)) { fexpr_set_symbol_builtin(res, FEXPR_UnsignedInfinity); return; } if (CA_IS_SIGNED_INF(x)) { ca_t t; fexpr_t s; ca_init(t, ctx); ca_sgn(t, x, ctx); if (CA_IS_QQ(t, ctx)) { fexpr_set_symbol_builtin(res, FEXPR_Infinity); if (!fmpq_is_one(CA_FMPQ(t))) fexpr_neg(res, res); } else { fexpr_init(s); _ca_get_fexpr_given_ext(s, t, flags, ext, num_ext, ext_vars, ctx); fexpr_set_symbol_builtin(res, FEXPR_Infinity); fexpr_call_builtin2(res, FEXPR_Mul, s, res); fexpr_clear(s); } ca_clear(t, ctx); return; } if (CA_IS_SPECIAL(x)) { flint_throw(FLINT_ERROR, "_ca_get_fexpr_given_ext: unexpected special value\n"); } K = CA_FIELD(x, ctx); if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { X = CA_FIELD_EXT_ELEM(K, 0); ext_pos = -1; for (i = 0; i < num_ext; i++) { if (ext[i] == X) { ext_pos = i; break; } } if (ext_pos == -1) { flint_throw(FLINT_ERROR, "Unable to look up ext position\n"); } fexpr_set_nf_elem(res, CA_NF_ELEM(x), CA_FIELD_NF(K), ext_vars + ext_pos); return; } else { fexpr_vec_t xvars; slong i, j, nvars; nvars = CA_FIELD_LENGTH(K); xvars->entries = flint_malloc(sizeof(fexpr_struct) * nvars); xvars->length = xvars->alloc = nvars; j = 0; for (i = 0; i < nvars; i++) { for ( ; j < num_ext; j++) { if (ext[j] == CA_FIELD_EXT_ELEM(K, i)) { xvars->entries[i] = ext_vars[j]; break; } } if (j == num_ext) { flint_throw(FLINT_ERROR, "_ca_get_fexpr_given_ext: ext not found!\n"); } } fexpr_set_fmpz_mpoly_q(res, CA_MPOLY_Q(x), xvars, CA_FIELD_MCTX(K, ctx)); flint_free(xvars->entries); return; } fexpr_set_symbol_builtin(res, FEXPR_Unknown); } #define GET_UNARY(fsymbol) \ _ca_get_fexpr_given_ext(res, CA_EXT_FUNC_ARGS(x), flags, ext, num_ext, ext_vars, ctx); \ fexpr_call_builtin1(res, fsymbol, res); \ return; \ void _ca_ext_get_fexpr_given_ext(fexpr_t res, const ca_ext_t x, ulong flags, ca_ext_ptr * ext, slong num_ext, const fexpr_struct * ext_vars, ca_ctx_t ctx) { if (CA_EXT_IS_QQBAR(x)) { if (flags & CA_FEXPR_SERIALIZATION) qqbar_get_fexpr_repr(res, CA_EXT_QQBAR(x)); else if (!qqbar_get_fexpr_formula(res, CA_EXT_QQBAR(x), QQBAR_FORMULA_GAUSSIANS | QQBAR_FORMULA_QUADRATICS)) qqbar_get_fexpr_root_nearest(res, CA_EXT_QQBAR(x)); } else { slong f, nargs; fexpr_t t, u; f = CA_EXT_HEAD(x); nargs = CA_EXT_FUNC_NARGS(x); (void) nargs; /* currently unused */ /* Todo: make a table */ switch (f) { case CA_Pi: fexpr_set_symbol_builtin(res, FEXPR_Pi); return; case CA_Euler: fexpr_set_symbol_builtin(res, FEXPR_Euler); return; case CA_Exp: GET_UNARY(FEXPR_Exp) case CA_Log: GET_UNARY(FEXPR_Log) case CA_Sin: GET_UNARY(FEXPR_Sin) case CA_Cos: GET_UNARY(FEXPR_Cos) case CA_Tan: GET_UNARY(FEXPR_Tan) case CA_Cot: GET_UNARY(FEXPR_Cot) case CA_Atan: GET_UNARY(FEXPR_Atan) case CA_Asin: GET_UNARY(FEXPR_Asin) case CA_Acos: GET_UNARY(FEXPR_Acos) case CA_Sign: GET_UNARY(FEXPR_Sign) case CA_Abs: GET_UNARY(FEXPR_Abs) case CA_Sqrt: GET_UNARY(FEXPR_Sqrt) case CA_Re: GET_UNARY(FEXPR_Re) case CA_Im: GET_UNARY(FEXPR_Im) case CA_Conjugate: GET_UNARY(FEXPR_Conjugate) case CA_Floor: GET_UNARY(FEXPR_Floor) case CA_Ceil: GET_UNARY(FEXPR_Ceil) case CA_Gamma: GET_UNARY(FEXPR_Gamma) case CA_Erf: GET_UNARY(FEXPR_Erf) case CA_Erfc: GET_UNARY(FEXPR_Erfc) case CA_Erfi: GET_UNARY(FEXPR_Erfi) case CA_Pow: fexpr_init(t); fexpr_init(u); _ca_get_fexpr_given_ext(t, CA_EXT_FUNC_ARGS(x), flags, ext, num_ext, ext_vars, ctx); _ca_get_fexpr_given_ext(u, CA_EXT_FUNC_ARGS(x) + 1, flags, ext, num_ext, ext_vars, ctx); fexpr_call_builtin2(res, FEXPR_Pow, t, u); fexpr_clear(t); fexpr_clear(u); return; } fexpr_set_symbol_builtin(res, FEXPR_Unknown); } } void _ca_default_variables(fexpr_ptr ext_vars, slong num_ext) { slong i; if (num_ext <= 26 && 0) { char tmp[20]; for (i = 0; i < num_ext; i++) { tmp[0] = 'a' + i; tmp[1] = '\0'; fexpr_set_symbol_str(ext_vars + i, tmp); } } else { char tmp[20]; for (i = 0; i < num_ext; i++) { flint_sprintf(tmp, "a_%wd", i + 1); fexpr_set_symbol_str(ext_vars + i, tmp); } } } void ca_get_fexpr(fexpr_t res, const ca_t x, ulong flags, ca_ctx_t ctx) { ca_ext_ptr * ext; slong i, num_ext; fexpr_struct * ext_vars; fexpr_struct * where_args; fexpr_t t; if (CA_IS_QQ(x, ctx)) { fexpr_set_fmpq(res, CA_FMPQ(x)); return; } if (CA_IS_UNKNOWN(x)) { fexpr_set_symbol_builtin(res, FEXPR_Unknown); return; } if (CA_IS_UNDEFINED(x)) { fexpr_set_symbol_builtin(res, FEXPR_Undefined); return; } if (CA_IS_UNSIGNED_INF(x)) { fexpr_set_symbol_builtin(res, FEXPR_UnsignedInfinity); return; } if (CA_IS_SIGNED_INF(x)) { ca_t t; ca_init(t, ctx); ca_sgn(t, x, ctx); if (CA_IS_QQ(t, ctx)) { fexpr_set_symbol_builtin(res, FEXPR_Infinity); if (!fmpq_is_one(CA_FMPQ(t))) fexpr_neg(res, res); ca_clear(t, ctx); return; } ca_clear(t, ctx); } ca_all_extensions(&ext, &num_ext, x, ctx); ext_vars = _fexpr_vec_init(num_ext); where_args = _fexpr_vec_init(num_ext + 1); fexpr_init(t); _ca_default_variables(ext_vars, num_ext); _ca_get_fexpr_given_ext(where_args + 0, x, flags, ext, num_ext, ext_vars, ctx); for (i = 0; i < num_ext; i++) { _ca_ext_get_fexpr_given_ext(t, ext[i], flags, ext, num_ext, ext_vars, ctx); fexpr_call_builtin2(where_args + i + 1, FEXPR_Def, ext_vars + i, t); } fexpr_set_symbol_builtin(t, FEXPR_Where); fexpr_call_vec(res, t, where_args, num_ext + 1); flint_free(ext); fexpr_clear(t); _fexpr_vec_clear(ext_vars, num_ext); _fexpr_vec_clear(where_args, num_ext + 1); } flint-3.1.3/src/ca/get_qqbar.c000066400000000000000000000325671461254215100161330ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" int ca_get_qqbar(qqbar_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { return 0; } else if (CA_IS_QQ(x, ctx)) { qqbar_set_fmpq(res, CA_FMPQ(x)); return 1; } else { if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { const fmpz * num; const fmpz * den; slong len; if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_LINEAR) { num = (fmpz *) LNF_ELEM_NUMREF(CA_NF_ELEM(x)); den = LNF_ELEM_DENREF(CA_NF_ELEM(x)); len = 1; } else if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_QUADRATIC) { num = (fmpz *) QNF_ELEM_NUMREF(CA_NF_ELEM(x)); den = QNF_ELEM_DENREF(CA_NF_ELEM(x)); len = 2; } else { num = (fmpz *) NF_ELEM_NUMREF(CA_NF_ELEM(x)); den = NF_ELEM_DENREF(CA_NF_ELEM(x)); len = NF_ELEM(CA_NF_ELEM(x))->length; } _qqbar_evaluate_fmpq_poly(res, num, den, len, CA_FIELD_NF_QQBAR(CA_FIELD(x, ctx))); return 1; } else { slong i, len, deg_limit, bits_limit; qqbar_ptr xs; qqbar_t y, zero; int success; int * init_mask, * used; if (!ca_can_evaluate_qqbar(x, ctx)) return 0; deg_limit = ctx->options[CA_OPT_QQBAR_DEG_LIMIT]; bits_limit = 10 * ctx->options[CA_OPT_PREC_LIMIT]; /* xxx */ len = CA_FIELD_LENGTH(CA_FIELD(x, ctx)); success = 0; xs = (qqbar_struct *) flint_malloc(sizeof(qqbar_struct) * len); init_mask = (int *) flint_calloc(sizeof(int), len); used = (int *) flint_calloc(sizeof(int), len); qqbar_init(y); qqbar_init(zero); fmpz_mpoly_q_used_vars(used, CA_MPOLY_Q(x), CA_FIELD_MCTX(CA_FIELD(x, ctx), ctx)); /* todo: allow non-qqbar extension elements to cache a qqbar value */ for (i = 0; i < len; i++) { if (!used[i]) { xs[i] = *zero; continue; } if (CA_EXT_IS_QQBAR(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i))) { xs[i] = *CA_EXT_QQBAR(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)); } else if (CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)->data.func_data.qqbar != NULL) { xs[i] = *(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)->data.func_data.qqbar); } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Sqrt) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; /* todo: maybe do a x2 bounds check */ qqbar_sqrt(xs + i, xs + i); /* todo: avoid copy here... */ CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)->data.func_data.qqbar = flint_malloc(sizeof(qqbar_struct)); qqbar_init(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)->data.func_data.qqbar); qqbar_set(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)->data.func_data.qqbar, xs + i); } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Abs) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; /* todo: bounds check */ qqbar_abs(xs + i, xs + i); } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Sign) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; /* todo: bounds check */ qqbar_sgn(xs + i, xs + i); } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Re) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; /* todo: bounds check */ qqbar_re(xs + i, xs + i); } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Im) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; /* todo: bounds check */ qqbar_im(xs + i, xs + i); } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Conjugate) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; qqbar_conj(xs + i, xs + i); } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Floor) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; { fmpz_t t; fmpz_init(t); qqbar_floor(t, xs + i); qqbar_set_fmpz(xs + i, t); fmpz_clear(t); } } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Ceil) { qqbar_init(xs + i); init_mask[i] = 1; if (!ca_get_qqbar(xs + i, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)), ctx)) goto cleanup; { fmpz_t t; fmpz_init(t); qqbar_ceil(t, xs + i); qqbar_set_fmpz(xs + i, t); fmpz_clear(t); } } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) == CA_Pow) { ca_srcptr base, exp; qqbar_init(xs + i); init_mask[i] = 1; base = CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)); exp = CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), i)) + 1; if (!CA_IS_QQ(exp, ctx)) goto cleanup; if (!ca_get_qqbar(xs + i, base, ctx)) goto cleanup; /* todo: better condition on the exponent numerator */ if (fmpz_bits(fmpq_denref(CA_FMPQ(exp))) > 20 || fmpz_bits(fmpq_numref(CA_FMPQ(exp))) > 20 || *fmpq_denref(CA_FMPQ(exp)) * qqbar_degree(xs + i) > ctx->options[CA_OPT_QQBAR_DEG_LIMIT] || (qqbar_height_bits(xs + i) + 1) * fmpz_bits(fmpq_numref(CA_FMPQ(exp))) > ctx->options[CA_OPT_PREC_LIMIT]) goto cleanup; qqbar_root_ui(xs + i, xs + i, *fmpq_denref(CA_FMPQ(exp))); if (*fmpq_numref(CA_FMPQ(exp)) >= 0) { qqbar_pow_ui(xs + i, xs + i, *fmpq_numref(CA_FMPQ(exp))); } else { qqbar_inv(xs + i, xs + i); qqbar_pow_ui(xs + i, xs + i, -*fmpq_numref(CA_FMPQ(exp))); } } } if (qqbar_evaluate_fmpz_mpoly(y, fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), xs, deg_limit, bits_limit, CA_FIELD_MCTX(CA_FIELD(x, ctx), ctx))) { if (qqbar_evaluate_fmpz_mpoly(res, fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), xs, deg_limit, bits_limit, CA_FIELD_MCTX(CA_FIELD(x, ctx), ctx))) { if (qqbar_binop_within_limits(y, res, deg_limit, bits_limit)) { qqbar_div(res, y, res); success = 1; } } } cleanup: for (i = 0; i < len; i++) { if (init_mask[i]) qqbar_clear(xs + i); } flint_free(init_mask); flint_free(used); flint_free(xs); qqbar_clear(y); qqbar_clear(zero); return success; } } } int ca_get_fmpq(fmpq_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { return 0; } else if (CA_IS_QQ(x, ctx)) { fmpq_set(res, CA_FMPQ(x)); return 1; } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { if (nf_elem_is_rational(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx)))) { const fmpz * num; const fmpz * den; slong len; if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_LINEAR) { num = (fmpz *) LNF_ELEM_NUMREF(CA_NF_ELEM(x)); den = LNF_ELEM_DENREF(CA_NF_ELEM(x)); fmpz_set(fmpq_numref(res), num); fmpz_set(fmpq_denref(res), den); } else if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_QUADRATIC) { num = (fmpz *) QNF_ELEM_NUMREF(CA_NF_ELEM(x)); den = QNF_ELEM_DENREF(CA_NF_ELEM(x)); fmpz_set(fmpq_numref(res), num); fmpz_set(fmpq_denref(res), den); } else { num = (fmpz *) NF_ELEM_NUMREF(CA_NF_ELEM(x)); den = NF_ELEM_DENREF(CA_NF_ELEM(x)); len = NF_ELEM(CA_NF_ELEM(x))->length; if (len == 0) { fmpq_zero(res); } else { fmpz_set(fmpq_numref(res), num); fmpz_set(fmpq_denref(res), den); } } return 1; } else { return 0; } } else { /* todo: exclude complex numbers, obviously irrational numbers before evaluating */ int success; qqbar_t t; qqbar_init(t); success = ca_get_qqbar(t, x, ctx); if (success && qqbar_is_rational(t)) { qqbar_get_fmpq(res, t); success = 1; } else { success = 0; } qqbar_clear(t); return success; } } int ca_get_fmpz(fmpz_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { return 0; } else if (CA_IS_QQ(x, ctx)) { if (fmpz_is_one(fmpq_denref(CA_FMPQ(x)))) { fmpz_set(res, fmpq_numref(CA_FMPQ(x))); return 1; } return 0; } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { if (nf_elem_is_integer(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx)))) { const fmpz * num; slong len; if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_LINEAR) { num = (fmpz *) LNF_ELEM_NUMREF(CA_NF_ELEM(x)); fmpz_set(res, num); } else if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_QUADRATIC) { num = (fmpz *) QNF_ELEM_NUMREF(CA_NF_ELEM(x)); fmpz_set(res, num); } else { num = (fmpz *) NF_ELEM_NUMREF(CA_NF_ELEM(x)); len = NF_ELEM(CA_NF_ELEM(x))->length; if (len == 0) fmpz_zero(res); else fmpz_set(res, num); } return 1; } else { return 0; } } else { /* todo: exclude (numerically) obvious non-integers before evaluating */ int success; qqbar_t t; qqbar_init(t); success = ca_get_qqbar(t, x, ctx); if (success && qqbar_is_integer(t)) { qqbar_get_fmpz(res, t); success = 1; } else { success = 0; } qqbar_clear(t); return success; } } flint-3.1.3/src/ca/hash_repr.c000066400000000000000000000044421461254215100161300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" ulong ca_hash_repr(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { return 123; /* not really interesting ... */ } else if (CA_IS_QQ(x, ctx)) { ulong a, b; a = calcium_fmpz_hash(CA_FMPQ_NUMREF(x)); b = calcium_fmpz_hash(CA_FMPQ_DENREF(x)); return a + 781237663 * b; } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { const fmpz * num; const fmpz * den; slong i, len; ulong hash; if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_LINEAR) { num = (fmpz *) LNF_ELEM_NUMREF(CA_NF_ELEM(x)); den = LNF_ELEM_DENREF(CA_NF_ELEM(x)); len = 1; } else if (CA_FIELD_NF(CA_FIELD(x, ctx))->flag & NF_QUADRATIC) { num = (fmpz *) QNF_ELEM_NUMREF(CA_NF_ELEM(x)); den = QNF_ELEM_DENREF(CA_NF_ELEM(x)); len = 2; } else { num = (fmpz *) NF_ELEM_NUMREF(CA_NF_ELEM(x)); den = NF_ELEM_DENREF(CA_NF_ELEM(x)); len = NF_ELEM(CA_NF_ELEM(x))->length; } hash = CA_EXT_HASH(CA_FIELD_EXT_ELEM(CA_FIELD(x, ctx), 0)); hash = 1000003 * calcium_fmpz_hash(den) + hash; for (i = 0; i < len; i++) hash = calcium_fmpz_hash(num + i) * 1000003 + hash; return hash; } else { slong i; ulong hash; const fmpz_mpoly_struct *p, *q; hash = CA_FIELD_HASH(CA_FIELD(x, ctx)); p = fmpz_mpoly_q_numref(CA_MPOLY_Q(x)); q = fmpz_mpoly_q_numref(CA_MPOLY_Q(x)); /* fixme: this only looks at coefficients -- accessing exponents is annoying */ for (i = 0; i < p->length; i++) hash = calcium_fmpz_hash(p->coeffs + i) * 1000003 + hash; for (i = 0; i < q->length; i++) hash = calcium_fmpz_hash(q->coeffs + i) * 1000003 + hash; return hash; } } flint-3.1.3/src/ca/i.c000066400000000000000000000010471461254215100144030ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_i(ca_t x, ca_ctx_t ctx) { _ca_make_field_element(x, ctx->field_qq_i, ctx); nf_elem_gen(CA_NF_ELEM(x), CA_FIELD_NF(ctx->field_qq_i)); } flint-3.1.3/src/ca/im.c000066400000000000000000000027141461254215100145620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_im(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_UNKNOWN(x)) ca_unknown(res, ctx); else ca_undefined(res, ctx); } else if (CA_IS_QQ(x, ctx)) { ca_zero(res, ctx); } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n, *d; fmpq_t t; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); d = QNF_ELEM_DENREF(CA_NF_ELEM(x)); fmpq_init(t); fmpq_set_fmpz_frac(t, n + 1, d); ca_set_fmpq(res, t, ctx); fmpq_clear(t); } else if (ca_check_is_real(x, ctx) == T_TRUE) /* todo: avoid duplicate computations with is_real/is_imaginary */ { ca_zero(res, ctx); } else if (ca_check_is_imaginary(x, ctx) == T_TRUE) { ca_t t; ca_init(t, ctx); ca_neg_i(t, ctx); ca_mul(res, x, t, ctx); ca_clear(t, ctx); } else { _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Im, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } } flint-3.1.3/src/ca/init.c000066400000000000000000000010251461254215100151120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_init(ca_t x, ca_ctx_t ctx) { x->field = (ulong) ctx->field_qq; *CA_FMPQ_NUMREF(x) = 0; *CA_FMPQ_DENREF(x) = 1; } flint-3.1.3/src/ca/inlines.c000066400000000000000000000006441461254215100156160ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define CA_INLINES_C #include "ca.h" flint-3.1.3/src/ca/inv.c000066400000000000000000000051701461254215100147500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_inv(ca_t res, const ca_t x, ca_ctx_t ctx) { truth_t is_zero; ca_field_srcptr field; if (CA_IS_QQ(x, ctx)) { if (fmpq_is_zero(CA_FMPQ(x))) { ca_uinf(res, ctx); } else { _ca_make_fmpq(res, ctx); fmpq_inv(CA_FMPQ(res), CA_FMPQ(x)); } return; } if (CA_IS_SPECIAL(x)) { if (CA_IS_INF(x)) ca_zero(res, ctx); else ca_set(res, x, ctx); return; } is_zero = ca_check_is_zero(x, ctx); if (is_zero == T_TRUE) { ca_uinf(res, ctx); return; } else if (is_zero == T_UNKNOWN) { ca_unknown(res, ctx); return; } field = CA_FIELD(x, ctx); _ca_make_field_element(res, field, ctx); if (CA_FIELD_IS_QQ(field)) /* todo: should not happen? */ { fmpq_inv(CA_FMPQ(res), CA_FMPQ(x)); } else if (CA_FIELD_IS_NF(field)) { nf_elem_inv(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_FIELD_NF(field)); } else { fmpz_mpoly_q_inv(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx)); _ca_mpoly_q_simplify_fraction_ideal(CA_MPOLY_Q(res), field, ctx); } } void ca_inv_no_division_by_zero(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_field_srcptr field; if (ca_is_zero_check_fast(x, ctx) == T_TRUE) { flint_throw(FLINT_ERROR, "ca_inv_no_division_by_zero: zero element encountered!\n"); } if (CA_IS_QQ(x, ctx)) { _ca_make_fmpq(res, ctx); fmpq_inv(CA_FMPQ(res), CA_FMPQ(x)); return; } if (CA_IS_SPECIAL(x)) { if (CA_IS_INF(x)) ca_zero(res, ctx); else ca_set(res, x, ctx); return; } field = CA_FIELD(x, ctx); _ca_make_field_element(res, field, ctx); if (CA_FIELD_IS_QQ(field)) /* todo: should not happen? */ { fmpq_inv(CA_FMPQ(res), CA_FMPQ(x)); } else if (CA_FIELD_IS_NF(field)) { nf_elem_inv(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_FIELD_NF(field)); } else { fmpz_mpoly_q_inv(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx)); _ca_mpoly_q_simplify_fraction_ideal(CA_MPOLY_Q(res), field, ctx); } } flint-3.1.3/src/ca/io.c000066400000000000000000000371631461254215100145720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ca.h" #include "ca_ext.h" #include "ca_field.h" typedef struct { ca_ext_ptr * ext; const char ** ext_vars; slong ext_len; ulong flags; slong digits; int print_where; } ca_print_info_t; void _ca_print(calcium_stream_t out, const ca_t x, ca_print_info_t * info, ca_ctx_t ctx); void _ca_ext_print(calcium_stream_t out, ca_ext_t x, const char * var, ca_print_info_t * info, ca_ctx_t ctx); void ca_write(calcium_stream_t out, const ca_t x, ca_ctx_t ctx); void _ca_all_extensions(ca_ext_ptr ** extensions, slong * length, const ca_t x, ca_ctx_t ctx); /* strings ********************************************************************/ char * ca_get_str(const ca_t x, ca_ctx_t ctx) { calcium_stream_t out; calcium_stream_init_str(out); ca_write(out, x, ctx); return out->s; } /* printing *******************************************************************/ void ca_ctx_print(ca_ctx_t ctx) { slong i; flint_printf("Calcium context with %wd cached fields:\n", CA_CTX_FIELD_CACHE(ctx)->length); for (i = 0; i < CA_CTX_FIELD_CACHE(ctx)->length; i++) { flint_printf("%wd ", i); ca_field_print(CA_CTX_FIELD_CACHE(ctx)->items[i], ctx); flint_printf("\n"); } flint_printf("\n"); } void calcium_write_fmpz(calcium_stream_t out, const fmpz_t x) { calcium_write_free(out, fmpz_get_str(NULL, 10, x)); } void qqbar_write_n(calcium_stream_t out, const qqbar_t x, slong n) { acb_t t; slong prec; n = FLINT_MAX(1, n); prec = n * 3.333 + 10; acb_init(t); qqbar_get_acb(t, x, prec); calcium_write_acb(out, t, n, ARB_STR_NO_RADIUS); acb_clear(t); } void calcium_write_nf_elem(calcium_stream_t out, const nf_elem_t a, const char * var, const nf_t nf) { const fmpz * num; const fmpz * den; slong len; if (nf_elem_is_zero(a, nf)) { calcium_write(out, "0"); return; } if (nf->flag & NF_LINEAR) { den = LNF_ELEM_DENREF(a); num = LNF_ELEM_NUMREF(a); len = 1 - fmpz_is_zero(num); } else if (nf->flag & NF_QUADRATIC) { den = QNF_ELEM_DENREF(a); num = QNF_ELEM_NUMREF(a); len = 3; while (len != 0 && fmpz_is_zero(num + len - 1)) len--; } else { den = NF_ELEM(a)->den; num = NF_ELEM(a)->coeffs; len = NF_ELEM(a)->length; } if (fmpz_is_one(den)) { calcium_write_free(out, _fmpz_poly_get_str_pretty(num, len, var)); } else { calcium_write(out, "("); calcium_write_free(out, _fmpz_poly_get_str_pretty(num, len, var)); calcium_write(out, ")/"); calcium_write_fmpz(out, den); } } void fmpz_mpoly_q_write_pretty(calcium_stream_t out, const fmpz_mpoly_q_t f, const char ** x, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(f), ctx)) { calcium_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_numref(f), x, ctx)); } else if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(f), ctx)) { calcium_write(out, "("); calcium_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_numref(f), x, ctx)); calcium_write(out, ")/"); calcium_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_denref(f), x, ctx)); } else { calcium_write(out, "("); calcium_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_numref(f), x, ctx)); calcium_write(out, ")/("); calcium_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_denref(f), x, ctx)); calcium_write(out, ")"); } } void _ca_field_print(calcium_stream_t out, const ca_field_t K, ca_print_info_t * info, ca_ctx_t ctx) { slong i, j, len, ideal_len; const char ** field_vars; calcium_write(out, "QQ"); len = CA_FIELD_LENGTH(K); if (len == 0) return; field_vars = flint_malloc(sizeof(char *) * len); for (i = 0; i < len; i++) field_vars[i] = ""; j = 0; for (i = 0; i < len; i++) { for ( ; j < info->ext_len; j++) { if (info->ext[j] == CA_FIELD_EXT_ELEM(K, i)) { field_vars[i] = info->ext_vars[j]; break; } } if (j == info->ext_len) { flint_throw(FLINT_ERROR, "_ca_field_print: ext not found!\n"); } } calcium_write(out, "("); for (i = 0; i < len; i++) { calcium_write(out, field_vars[i]); if (i < len - 1) calcium_write(out, ","); } calcium_write(out, ")"); if (CA_FIELD_IS_NF(K)) { calcium_write(out, "/<"); calcium_write_free(out, fmpz_poly_get_str_pretty(QQBAR_POLY(CA_EXT_QQBAR(CA_FIELD_EXT_ELEM(K, 0))), field_vars[0])); calcium_write(out, ">"); } else { ideal_len = CA_FIELD_IDEAL_LENGTH(K); if (ideal_len > 0) { const fmpz_mpoly_ctx_struct * mctx; mctx = CA_FIELD_MCTX(K, ctx); calcium_write(out, "/<"); for (i = 0; i < ideal_len; i++) { calcium_write_free(out, fmpz_mpoly_get_str_pretty(CA_FIELD_IDEAL_ELEM(K, i), (const char **) field_vars, mctx)); if (i < ideal_len - 1) calcium_write(out, ", "); } calcium_write(out, ">"); } } flint_free(field_vars); } void _ca_ext_print(calcium_stream_t out, ca_ext_t x, const char * var, ca_print_info_t * info, ca_ctx_t ctx) { if (x->head == CA_QQBar) { if (info->flags & CA_PRINT_N) { if (qqbar_is_i(CA_EXT_QQBAR(x))) { calcium_write(out, "I"); } else { qqbar_write_n(out, CA_EXT_QQBAR(x), info->digits); } calcium_write(out, " "); } calcium_write(out, "["); calcium_write_free(out, fmpz_poly_get_str_pretty(QQBAR_POLY(CA_EXT_QQBAR(x)), var)); calcium_write(out, "=0]"); } else { acb_t t; if (info->flags & CA_PRINT_N) { acb_init(t); ca_ext_get_acb_raw(t, x, info->digits * 3.33 + 64, ctx); calcium_write_acb(out, t, info->digits, ARB_STR_NO_RADIUS); acb_clear(t); } if (info->flags & CA_PRINT_N) calcium_write(out, " ["); calcium_write(out, calcium_func_name(CA_EXT_HEAD(x))); if (CA_EXT_FUNC_NARGS(x) != 0) { slong i; calcium_write(out, "("); for (i = 0; i < CA_EXT_FUNC_NARGS(x); i++) { _ca_print(out, CA_EXT_FUNC_ARGS(x) + i, info, ctx); if (i < CA_EXT_FUNC_NARGS(x) - 1) calcium_write(out, ", "); } calcium_write(out, ")"); } if (info->flags & CA_PRINT_N) calcium_write(out, "]"); } } void _ca_print(calcium_stream_t out, const ca_t x, ca_print_info_t * info, ca_ctx_t ctx) { ca_field_srcptr xfield; int print_where; if (CA_IS_SPECIAL(x)) { if (CA_IS_UNDEFINED(x)) { calcium_write(out, "Undefined"); } else if (CA_IS_UNKNOWN(x)) { calcium_write(out, "Unknown"); } else if (CA_IS_UNSIGNED_INF(x)) { calcium_write(out, "UnsignedInfinity"); } else if (CA_IS_SIGNED_INF(x)) { ca_t sgn; sgn->field = x->field & ~CA_SPECIAL; sgn->elem = x->elem; if (CA_IS_QQ(sgn, ctx)) { if (fmpq_sgn(CA_FMPQ(sgn)) > 0) calcium_write(out, "+Infinity"); else calcium_write(out, "-Infinity"); } else if (CA_IS_QQ_I(sgn, ctx)) { if (fmpz_sgn(QNF_ELEM_NUMREF(CA_NF_ELEM(sgn)) + 1) > 0) calcium_write(out, "+I * Infinity"); else calcium_write(out, "-I * Infinity"); } else { calcium_write(out, "Infinity * ("); _ca_print(out, sgn, info, ctx); calcium_write(out, ")"); } } return; } print_where = info->print_where; info->print_where = 0; xfield = CA_FIELD(x, ctx); if (CA_FIELD_IS_QQ(xfield) && fmpz_is_one(CA_FMPQ_DENREF(x)) && fmpz_cmp_si(CA_FMPQ_NUMREF(x), -999999) >= 0 && fmpz_cmp_si(CA_FMPQ_NUMREF(x), 999999) <= 0) { calcium_write_free(out, fmpq_get_str(NULL, 10, CA_FMPQ(x))); return; } if (info->flags & CA_PRINT_N) { acb_t t; acb_init(t); ca_get_acb_raw(t, x, info->digits * 3.33 + 64, ctx); calcium_write_acb(out, t, info->digits, ARB_STR_NO_RADIUS); acb_clear(t); } if (info->flags & CA_PRINT_REPR) { if (info->flags & CA_PRINT_N) calcium_write(out, " {"); if (CA_FIELD_IS_QQ(xfield)) { calcium_write_free(out, fmpq_get_str(NULL, 10, CA_FMPQ(x))); } else if (CA_FIELD_IS_NF(xfield)) { slong i; const char * var = NULL; for (i = 0; i < info->ext_len; i++) { if (info->ext[i] == CA_FIELD_EXT_ELEM(xfield, 0)) { var = info->ext_vars[i]; break; } } calcium_write_nf_elem(out, CA_NF_ELEM(x), var, CA_FIELD_NF(xfield)); } else { const char ** field_vars; slong i, j, len; len = CA_FIELD_LENGTH(xfield); field_vars = flint_malloc(sizeof(char *) * len); for (i = 0; i < len; i++) field_vars[i] = ""; j = 0; for (i = 0; i < len; i++) { for ( ; j < info->ext_len; j++) { if (info->ext[j] == CA_FIELD_EXT_ELEM(xfield, i)) { field_vars[i] = info->ext_vars[j]; break; } } if (j == info->ext_len) { flint_throw(FLINT_ERROR, "_ca_field_print: ext not found!\n"); } } fmpz_mpoly_q_write_pretty(out, CA_MPOLY_Q(x), (const char **) field_vars, CA_FIELD_MCTX(xfield, ctx)); flint_free(field_vars); } if (info->flags & CA_PRINT_FIELD) { calcium_write(out, " in "); _ca_field_print(out, xfield, info, ctx); } if (print_where && info->ext_len > 0) { slong i, len; len = info->ext_len; calcium_write(out, " where "); for (i = 0; i < len; i++) { calcium_write(out, info->ext_vars[i]); calcium_write(out, " = "); _ca_ext_print(out, info->ext[i], info->ext_vars[i], info, ctx); if (i != len - 1) calcium_write(out, ", "); } } if (info->flags & CA_PRINT_N) calcium_write(out, "}"); } /* todo: move... */ } /* todo: something that doesn't run in quadratic time */ void _ca_ext_insert_extension(ca_ext_ptr ** extensions, slong * length, ca_ext_t x, ca_ctx_t ctx) { slong i, j; for (i = 0; i < *length; i++) { if (extensions[0][i] == x) return; } if (*length == 0) { extensions[0] = flint_malloc(4 * sizeof(ca_ext_ptr)); extensions[0][0] = x; *length = 1; } else { if (((*length + 1) & (*length)) == 0) extensions[0] = flint_realloc(extensions[0], ((*length + 1) * 2) * sizeof(ca_ext_ptr)); for (i = 0; i < *length; i++) { if (ca_ext_cmp_repr(extensions[0][i], x, ctx) < 0) { for (j = *length - 1; j >= i; j--) extensions[0][j + 1] = extensions[0][j]; extensions[0][i] = x; break; } else if (i == *length - 1) { extensions[0][*length] = x; } } *length = *length + 1; } } void _ca_ext_all_extensions(ca_ext_ptr ** extensions, slong * length, ca_ext_t x, ca_ctx_t ctx) { slong i; _ca_ext_insert_extension(extensions, length, x, ctx); if (!CA_EXT_IS_QQBAR(x)) { for (i = 0; i < CA_EXT_FUNC_NARGS(x); i++) _ca_all_extensions(extensions, length, CA_EXT_FUNC_ARGS(x) + i, ctx); } } void _ca_all_extensions(ca_ext_ptr ** extensions, slong * length, const ca_t x, ca_ctx_t ctx) { ca_field_srcptr K; slong i; if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { ca_t sgn; sgn->field = x->field & ~CA_SPECIAL; sgn->elem = x->elem; _ca_all_extensions(extensions, length, sgn, ctx); } return; } K = CA_FIELD(x, ctx); for (i = 0; i < CA_FIELD_LENGTH(K); i++) { _ca_ext_all_extensions(extensions, length, CA_FIELD_EXT_ELEM(K, i), ctx); } } void ca_all_extensions(ca_ext_ptr ** extensions, slong * length, const ca_t x, ca_ctx_t ctx) { *extensions = NULL; *length = 0; _ca_all_extensions(extensions, length, x, ctx); } void ca_write(calcium_stream_t out, const ca_t x, ca_ctx_t ctx) { ca_print_info_t info; ca_ext_ptr * ext; slong i, len; char * all_vars; const char ** vars; ca_all_extensions(&ext, &len, x, ctx); all_vars = flint_malloc(15 * len); vars = flint_malloc(sizeof(char *) * len); for (i = 0; i < len; i++) { if (i < 26) { all_vars[15 * i] = 'a' + i; all_vars[15 * i + 1] = '\0'; } else { all_vars[15 * i] = 'a' + (i % 26); flint_sprintf(&all_vars[15 * i] + 1, "%wd", i / 26); } vars[i] = all_vars + 15 * i; } info.ext = ext; info.ext_len = len; info.ext_vars = vars; info.flags = ctx->options[CA_OPT_PRINT_FLAGS]; info.digits = ctx->options[CA_OPT_PRINT_FLAGS] / CA_PRINT_DIGITS; if (info.digits == 0) info.digits = 6; info.print_where = 1; _ca_print(out, x, &info, ctx); flint_free(all_vars); flint_free(vars); flint_free(ext); } void ca_print(const ca_t x, ca_ctx_t ctx) { #if 1 char * s = ca_get_str(x, ctx); flint_printf("%s", s); flint_free(s); #else calcium_stream_t out; calcium_stream_init_file(out, stdout); ca_write(out, x, ctx); #endif } void ca_fprint(FILE * fp, const ca_t x, ca_ctx_t ctx) { calcium_stream_t out; calcium_stream_init_file(out, fp); ca_write(out, x, ctx); } void ca_printn(const ca_t x, slong n, ca_ctx_t ctx) { ulong save_flags; save_flags = ctx->options[CA_OPT_PRINT_FLAGS]; ctx->options[CA_OPT_PRINT_FLAGS] = CA_PRINT_N | (CA_PRINT_DIGITS * n); ca_print(x, ctx); ctx->options[CA_OPT_PRINT_FLAGS] = save_flags; } void ca_factor_print(const ca_factor_t fac, ca_ctx_t ctx) { slong i; for (i = 0; i < fac->length; i++) { flint_printf("("); ca_print(fac->base + i, ctx); flint_printf(") ^ ("); ca_print(fac->exp + i, ctx); flint_printf(")\n"); } } flint-3.1.3/src/ca/is_cyclotomic_nf_elem.c000066400000000000000000000014641461254215100205030ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" int ca_is_cyclotomic_nf_elem(slong * p, ulong * q, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) return 0; if (CA_IS_QQ(x, ctx)) return 0; if (CA_IS_QQ_I(x, ctx)) { if (p != NULL) p[0] = 1; if (q != NULL) q[0] = 4; return 1; } return CA_FIELD_IS_NF(CA_FIELD(x, ctx)) && qqbar_is_root_of_unity(p, q, CA_FIELD_NF_QQBAR(CA_FIELD(x, ctx))); } flint-3.1.3/src/ca/is_gen_as_ext.c000066400000000000000000000022671461254215100167670ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" ca_ext_ptr ca_is_gen_as_ext(const ca_t x, ca_ctx_t ctx) { ca_field_ptr K; if (CA_IS_SPECIAL(x)) return NULL; K = CA_FIELD(x, ctx); if (CA_FIELD_IS_QQ(K)) return NULL; if (CA_FIELD_IS_NF(K)) { if (!nf_elem_is_gen(CA_NF_ELEM(x), CA_FIELD_NF(K))) return NULL; return CA_FIELD_EXT_ELEM(K, 0); } if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx))) { if (fmpz_mpoly_is_gen(fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), -1, CA_FIELD_MCTX(K, ctx))) { slong i; for (i = 0; ; i++) if (fmpz_mpoly_is_gen(fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), i, CA_FIELD_MCTX(K, ctx))) return CA_FIELD_EXT_ELEM(K, i); } } return NULL; } flint-3.1.3/src/ca/log.c000066400000000000000000000205131461254215100147330ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" ca_ext_ptr ca_is_gen_pow_fmpz_as_ext(fmpz_t exp, const ca_t x, ca_ctx_t ctx) { ca_field_ptr K; if (CA_IS_SPECIAL(x)) return NULL; K = CA_FIELD(x, ctx); if (CA_FIELD_IS_QQ(K)) return NULL; /* todo: detect powers of the generator in number fields */ if (CA_FIELD_IS_NF(K)) { if (!nf_elem_is_gen(CA_NF_ELEM(x), CA_FIELD_NF(K))) return NULL; fmpz_one(exp); return CA_FIELD_EXT_ELEM(K, 0); } if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx))) { if (fmpz_mpoly_length(fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx)) == 1 && fmpz_is_one(fmpz_mpoly_q_numref(CA_MPOLY_Q(x))->coeffs)) { int * used; slong i, which, num_used; used = flint_calloc(CA_FIELD_LENGTH(K), sizeof(int)); fmpz_mpoly_q_used_vars_num(used, CA_MPOLY_Q(x), CA_FIELD_MCTX(K, ctx)); which = num_used = 0; for (i = 0; i < CA_FIELD_LENGTH(K); i++) { if (used[i]) { which = i; num_used++; } } flint_free(used); if (num_used == 1) { fmpz_mpoly_total_degree_fmpz(exp, fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx)); return CA_FIELD_EXT_ELEM(K, which); } } } if (fmpz_mpoly_is_one(fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx))) { if (fmpz_mpoly_length(fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx)) == 1 && fmpz_is_one(fmpz_mpoly_q_denref(CA_MPOLY_Q(x))->coeffs)) { int * used; slong i, which, num_used; used = flint_calloc(CA_FIELD_LENGTH(K), sizeof(int)); fmpz_mpoly_q_used_vars_den(used, CA_MPOLY_Q(x), CA_FIELD_MCTX(K, ctx)); which = num_used = 0; for (i = 0; i < CA_FIELD_LENGTH(K); i++) { if (used[i]) { which = i; num_used++; } } flint_free(used); if (num_used == 1) { fmpz_mpoly_total_degree_fmpz(exp, fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), CA_FIELD_MCTX(K, ctx)); fmpz_neg(exp, exp); return CA_FIELD_EXT_ELEM(K, which); } } } return NULL; } /* log(exp(z)) -- https://fungrim.org/entry/a3a253/ */ void ca_log_exp(ca_t res, const ca_t z, ca_ctx_t ctx) { ca_t t, pi; if (CA_IS_SPECIAL(z)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); ca_init(t, ctx); ca_init(pi, ctx); ca_pi(pi, ctx); ca_im(t, z, ctx); ca_div(t, t, pi, ctx); ca_sub_ui(t, t, 1, ctx); ca_div_ui(t, t, 2, ctx); ca_ceil(t, t, ctx); if (ca_check_is_zero(t, ctx) == T_TRUE) { ca_set(res, z, ctx); } else { ca_t pi_i; ca_init(pi_i, ctx); ca_pi_i(pi_i, ctx); ca_mul(t, t, pi_i, ctx); ca_mul_ui(t, t, 2, ctx); ca_sub(res, z, t, ctx); ca_clear(pi_i, ctx); } ca_clear(t, ctx); ca_clear(pi, ctx); } /* log(z^a), assuming z != 0 */ void ca_log_pow(ca_t res, const ca_t z, const ca_t a, ca_ctx_t ctx) { ca_t t, u, pi; if (CA_IS_SPECIAL(z) || CA_IS_SPECIAL(a)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); ca_init(t, ctx); ca_init(u, ctx); ca_init(pi, ctx); ca_log(u, z, ctx); ca_mul(u, u, a, ctx); ca_pi(pi, ctx); ca_im(t, u, ctx); ca_div(t, t, pi, ctx); ca_sub_ui(t, t, 1, ctx); ca_div_ui(t, t, 2, ctx); ca_ceil(t, t, ctx); if (ca_check_is_zero(t, ctx) == T_TRUE) { ca_set(res, u, ctx); } else { ca_t pi_i; ca_init(pi_i, ctx); ca_pi_i(pi_i, ctx); ca_mul(t, t, pi_i, ctx); ca_mul_ui(t, t, 2, ctx); ca_sub(res, u, t, ctx); ca_clear(pi_i, ctx); } ca_clear(t, ctx); ca_clear(u, ctx); ca_clear(pi, ctx); } void ca_log(ca_t res, const ca_t x, ca_ctx_t ctx) { truth_t is_zero; ca_ext_ptr ext; if (CA_IS_SPECIAL(x)) { if (ca_check_is_infinity(x, ctx) == T_TRUE) ca_pos_inf(res, ctx); else if (ca_check_is_undefined(x, ctx) == T_TRUE) ca_undefined(res, ctx); else ca_unknown(res, ctx); return; } is_zero = ca_check_is_zero(x, ctx); if (is_zero == T_TRUE) { ca_neg_inf(res, ctx); return; } if (is_zero == T_UNKNOWN) { ca_unknown(res, ctx); return; } if (ca_check_is_one(x, ctx) == T_TRUE) { ca_zero(res, ctx); return; } /* log(i) and log(-i) */ if (CA_IS_QQ_I(x, ctx)) { if (ca_check_is_i(x, ctx) == T_TRUE) { ca_pi_i(res, ctx); ca_div_si(res, res, 2, ctx); return; } else if (ca_check_is_neg_i(x, ctx) == T_TRUE) { ca_pi_i(res, ctx); ca_div_si(res, res, -2, ctx); return; } } ext = ca_is_gen_as_ext(x, ctx); /* Fast detection of roots of unity. Todo: also detect roots of unity when in a number field, and in other situations. */ if (ext != NULL && CA_EXT_HEAD(ext) == CA_QQBar) { slong p; ulong q; if (qqbar_log_pi_i(&p, &q, CA_EXT_QQBAR(ext))) { ca_pi_i(res, ctx); ca_mul_si(res, res, p, ctx); ca_div_ui(res, res, q, ctx); return; } } if (ext != NULL && CA_EXT_HEAD(ext) == CA_Exp) { /* log(exp(z)) */ ca_log_exp(res, CA_EXT_FUNC_ARGS(ext), ctx); return; } if (ca_check_is_negative_real(x, ctx) == T_TRUE) { ca_t pi_i; ca_init(pi_i, ctx); ca_pi_i(pi_i, ctx); ca_neg(res, x, ctx); ca_log(res, res, ctx); ca_add(res, res, pi_i, ctx); ca_clear(pi_i, ctx); return; } if (ext != NULL && CA_EXT_HEAD(ext) == CA_Pow) { /* log(z^a) */ if (ca_check_is_zero(CA_EXT_FUNC_ARGS(ext), ctx) == T_FALSE) { ca_log_pow(res, CA_EXT_FUNC_ARGS(ext), CA_EXT_FUNC_ARGS(ext) + 1, ctx); return; } } if (ext != NULL && CA_EXT_HEAD(ext) == CA_Sqrt) { /* log(sqrt(z)) */ ca_t h; ca_init(h, ctx); ca_one(h, ctx); ca_div_ui(h, h, 2, ctx); ca_log_pow(res, CA_EXT_FUNC_ARGS(ext), h, ctx); ca_clear(h, ctx); return; } /* If x is not a generator, maybe it is a power of a generator */ { fmpz_t n; ca_t t; int success = 0; fmpz_init(n); ca_init(t, ctx); ext = ca_is_gen_pow_fmpz_as_ext(n, x, ctx); if (ext != NULL && CA_EXT_HEAD(ext) == CA_Exp) { /* log(exp(z)^n) = log(exp(n*z)) */ ca_mul_fmpz(t, CA_EXT_FUNC_ARGS(ext), n, ctx); ca_log_exp(res, t, ctx); success = 1; } if (ext != NULL && CA_EXT_HEAD(ext) == CA_Pow) { /* log((z^a)^n) = log(z^(a*n)) */ if (ca_check_is_zero(CA_EXT_FUNC_ARGS(ext), ctx) == T_FALSE) { ca_mul_fmpz(t, CA_EXT_FUNC_ARGS(ext) + 1, n, ctx); ca_log_pow(res, CA_EXT_FUNC_ARGS(ext), t, ctx); success = 1; } } if (ext != NULL && CA_EXT_HEAD(ext) == CA_Sqrt) { /* log(sqrt(z)^n) = log(z^(n/2)) */ ca_set_fmpz(t, n, ctx); ca_div_ui(t, t, 2, ctx); ca_log_pow(res, CA_EXT_FUNC_ARGS(ext), t, ctx); success = 1; } fmpz_clear(n); ca_clear(t, ctx); if (success) return; } _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Log, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/make_field_element.c000066400000000000000000000025311461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_field.h" void ca_clear_unchecked(ca_t x, ca_ctx_t ctx); /* todo: recycle storage when compatible */ void _ca_make_field_element(ca_t x, ca_field_srcptr field, ca_ctx_t ctx) { ca_field_srcptr old_field; if (field == NULL) { flint_throw(FLINT_ERROR, "NULL in _ca_make_field_element\n"); } old_field = (ca_field_srcptr) (x->field & ~CA_SPECIAL); if (old_field == field) { x->field = (ulong) field; /* unset special status */ return; } ca_clear_unchecked(x, ctx); if (field == ctx->field_qq) { *CA_FMPQ_NUMREF(x) = 0; *CA_FMPQ_DENREF(x) = 1; } else if (CA_FIELD_IS_NF(field)) { nf_elem_init(CA_NF_ELEM(x), CA_FIELD_NF(field)); } else { x->elem.mpoly_q = (fmpz_mpoly_q_struct *) flint_malloc(sizeof(fmpz_mpoly_q_struct)); fmpz_mpoly_q_init(CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx)); } x->field = (ulong) field; } flint-3.1.3/src/ca/merge_fields.c000066400000000000000000000165221461254215100166040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" #include "fmpz_mpoly.h" void _nf_elem_get_fmpz_poly_den_shallow(fmpz_poly_t pol, fmpz_t den, const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { pol->coeffs = (fmpz *) LNF_ELEM_NUMREF(a); *den = *LNF_ELEM_DENREF(a); pol->length = 1; if (fmpz_is_zero(pol->coeffs)) pol->length--; } else if (nf->flag & NF_QUADRATIC) { pol->coeffs = (fmpz *) QNF_ELEM_NUMREF(a); *den = *QNF_ELEM_DENREF(a); pol->length = 2; if (fmpz_is_zero(pol->coeffs + 1)) { pol->length--; if (fmpz_is_zero(pol->coeffs)) pol->length--; } } else { pol->coeffs = (fmpz *) NF_ELEM_NUMREF(a); pol->length = NF_ELEM(a)->length; *den = *NF_ELEM_DENREF(a); } pol->alloc = pol->length; } void ca_merge_fields(ca_t resx, ca_t resy, const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_srcptr xfield, yfield, field; ca_ext_struct ** ext; slong *xgen_map, *ygen_map; slong xlen, ylen, ext_len; slong ext_alloc; slong ix, iy; int cmp; if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { flint_throw(FLINT_ERROR, "ca_merge_fields: inputs must be field elements, not special values\n"); } xfield = CA_FIELD(x, ctx); yfield = CA_FIELD(y, ctx); if (xfield == yfield || CA_FIELD_IS_QQ(xfield) || CA_FIELD_IS_QQ(yfield)) { ca_set(resx, x, ctx); ca_set(resy, y, ctx); return; } if (x == resx || y == resy) { flint_throw(FLINT_ERROR, "ca_merge_fields: aliasing not implemented!\n"); } xlen = CA_FIELD_LENGTH(xfield); ylen = CA_FIELD_LENGTH(yfield); ext_alloc = xlen + ylen; ext = flint_malloc(ext_alloc * sizeof(ca_ext_struct *)); ext_len = 0; xgen_map = flint_malloc(xlen * sizeof(slong)); ygen_map = flint_malloc(ylen * sizeof(slong)); /* printf("merge fields of len %ld and len %ld\n", xlen, ylen); for (ix = 0; ix < xlen; ix++) { printf("x: "); ca_ext_print(CA_FIELD_EXT_ELEM(xfield, ix), ctx); printf("\n"); } for (iy = 0; iy < ylen; iy++) { printf("y: "); ca_ext_print(CA_FIELD_EXT_ELEM(yfield, iy), ctx); printf("\n"); } */ /* merge field lists */ ix = iy = 0; while (ix < xlen || iy < ylen) { if (ix < xlen && iy < ylen) { cmp = ca_ext_cmp_repr(CA_FIELD_EXT_ELEM(xfield, ix), CA_FIELD_EXT_ELEM(yfield, iy), ctx); cmp = -cmp; /* more complex first, for elimination order */ if (cmp == 0) { if (CA_FIELD_EXT_ELEM(xfield, ix) != CA_FIELD_EXT_ELEM(yfield, iy)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); ext[ext_len] = CA_FIELD_EXT_ELEM(xfield, ix); xgen_map[ix] = ext_len; ygen_map[iy] = ext_len; ix++; iy++; } else if (cmp < 0) { ext[ext_len] = CA_FIELD_EXT_ELEM(xfield, ix); xgen_map[ix] = ext_len; ix++; } else { ext[ext_len] = CA_FIELD_EXT_ELEM(yfield, iy); ygen_map[iy] = ext_len; iy++; } ext_len++; } else if (ix < xlen) { ext[ext_len] = CA_FIELD_EXT_ELEM(xfield, ix); xgen_map[ix] = ext_len; ix++; ext_len++; } else { ext[ext_len] = CA_FIELD_EXT_ELEM(yfield, iy); ygen_map[iy] = ext_len; iy++; ext_len++; } } /* printf("merged length %ld\n", ext_len); */ field = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), ext, ext_len, ctx); /* printf("MERGE FIELDS:\n"); if (CA_FIELD_LENGTH(xfield) > 100) flint_abort(); ca_field_print(xfield, ctx); printf("\n"); if (CA_FIELD_LENGTH(yfield) > 100) flint_abort(); ca_field_print(yfield, ctx); printf("\n"); if (CA_FIELD_LENGTH(field) > 100) flint_abort(); ca_field_print(field, ctx); printf("\n\n"); */ if (xfield == field) { ca_set(resx, x, ctx); } else { /* todo: allow aliasing */ _ca_make_field_element(resx, field, ctx); if (CA_FIELD_IS_NF(xfield)) { fmpz_poly_t pol; fmpz_t den; _nf_elem_get_fmpz_poly_den_shallow(pol, den, CA_NF_ELEM(x), CA_FIELD_NF(xfield)); fmpz_mpoly_set_gen_fmpz_poly(fmpz_mpoly_q_numref(CA_MPOLY_Q(resx)), xgen_map[0], pol, CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_set_fmpz(fmpz_mpoly_q_denref(CA_MPOLY_Q(resx)), den, CA_FIELD_MCTX(field, ctx)); } else { fmpz_mpoly_compose_fmpz_mpoly_gen(fmpz_mpoly_q_numref(CA_MPOLY_Q(resx)), fmpz_mpoly_q_numref(CA_MPOLY_Q(x)), xgen_map, CA_FIELD_MCTX(xfield, ctx), CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_compose_fmpz_mpoly_gen(fmpz_mpoly_q_denref(CA_MPOLY_Q(resx)), fmpz_mpoly_q_denref(CA_MPOLY_Q(x)), xgen_map, CA_FIELD_MCTX(xfield, ctx), CA_FIELD_MCTX(field, ctx)); } } if (yfield == field) { ca_set(resy, y, ctx); } else { /* todo: allow aliasing */ _ca_make_field_element(resy, field, ctx); if (CA_FIELD_IS_NF(yfield)) { fmpz_poly_t pol; fmpz_t den; _nf_elem_get_fmpz_poly_den_shallow(pol, den, CA_NF_ELEM(y), CA_FIELD_NF(yfield)); fmpz_mpoly_set_gen_fmpz_poly(fmpz_mpoly_q_numref(CA_MPOLY_Q(resy)), ygen_map[0], pol, CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_set_fmpz(fmpz_mpoly_q_denref(CA_MPOLY_Q(resy)), den, CA_FIELD_MCTX(field, ctx)); } else { fmpz_mpoly_compose_fmpz_mpoly_gen(fmpz_mpoly_q_numref(CA_MPOLY_Q(resy)), fmpz_mpoly_q_numref(CA_MPOLY_Q(y)), ygen_map, CA_FIELD_MCTX(yfield, ctx), CA_FIELD_MCTX(field, ctx)); fmpz_mpoly_compose_fmpz_mpoly_gen(fmpz_mpoly_q_denref(CA_MPOLY_Q(resy)), fmpz_mpoly_q_denref(CA_MPOLY_Q(y)), ygen_map, CA_FIELD_MCTX(yfield, ctx), CA_FIELD_MCTX(field, ctx)); } } flint_free(ext); flint_free(xgen_map); flint_free(ygen_map); } flint-3.1.3/src/ca/mul.c000066400000000000000000000140301461254215100147440ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_mul_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) { ca_field_srcptr field; if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { if (fmpq_is_zero(y)) ca_undefined(res, ctx); else if (fmpq_sgn(y) > 0) ca_set(res, x, ctx); else ca_neg(res, x, ctx); } else if (CA_IS_UNSIGNED_INF(x)) { if (fmpq_is_zero(y)) ca_undefined(res, ctx); else ca_set(res, x, ctx); } else { ca_set(res, x, ctx); } return; } if (fmpq_is_zero(y)) { ca_zero(res, ctx); return; } if (CA_IS_QQ(x, ctx)) { _ca_make_fmpq(res, ctx); fmpq_mul(CA_FMPQ(res), CA_FMPQ(x), y); } else { field = CA_FIELD(x, ctx); _ca_make_field_element(res, field, ctx); if (CA_FIELD_IS_NF(field)) { nf_elem_scalar_mul_fmpq(CA_NF_ELEM(res), CA_NF_ELEM(x), y, CA_FIELD_NF(field)); } else { fmpz_mpoly_q_mul_fmpq(CA_MPOLY_Q(res), CA_MPOLY_Q(x), y, CA_FIELD_MCTX(field, ctx)); } } } void ca_mul_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) { fmpq_t t; *fmpq_numref(t) = *y; *fmpq_denref(t) = 1; ca_mul_fmpq(res, x, t, ctx); } void ca_mul_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, y); ca_mul_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_mul_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, y); ca_mul_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_mul(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_srcptr xfield, yfield, zfield; xfield = CA_FIELD(x, ctx); yfield = CA_FIELD(y, ctx); if (CA_IS_QQ(x, ctx) && (xfield == yfield)) { _ca_make_fmpq(res, ctx); fmpq_mul(CA_FMPQ(res), CA_FMPQ(x), CA_FMPQ(y)); return; } if (CA_IS_QQ(y, ctx)) { if (res == y) { fmpq_t t; fmpq_init(t); fmpq_set(t, CA_FMPQ(y)); ca_mul_fmpq(res, x, t, ctx); fmpq_clear(t); } else { ca_mul_fmpq(res, x, CA_FMPQ(y), ctx); } return; } if (CA_IS_QQ(x, ctx)) { if (res == x) { fmpq_t t; fmpq_init(t); fmpq_set(t, CA_FMPQ(x)); ca_mul_fmpq(res, y, t, ctx); fmpq_clear(t); } else { ca_mul_fmpq(res, y, CA_FMPQ(x), ctx); } return; } if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { if (CA_IS_UNDEFINED(x) || CA_IS_UNDEFINED(y)) { ca_undefined(res, ctx); return; } if (CA_IS_UNKNOWN(x) || CA_IS_UNKNOWN(y)) { ca_unknown(res, ctx); return; } if (CA_IS_UNSIGNED_INF(x) && CA_IS_INF(y)) { ca_uinf(res, ctx); return; } if (CA_IS_UNSIGNED_INF(y) && CA_IS_INF(x)) { ca_uinf(res, ctx); return; } if (CA_IS_UNSIGNED_INF(x) && !CA_IS_SPECIAL(y)) { truth_t zero = ca_check_is_zero(y, ctx); if (zero == T_TRUE) ca_undefined(res, ctx); else if (zero == T_FALSE) ca_uinf(res, ctx); else ca_unknown(res, ctx); return; } if (CA_IS_UNSIGNED_INF(y) && !CA_IS_SPECIAL(x)) { truth_t zero = ca_check_is_zero(x, ctx); if (zero == T_TRUE) ca_undefined(res, ctx); else if (zero == T_FALSE) ca_uinf(res, ctx); else ca_unknown(res, ctx); return; } if (CA_IS_SIGNED_INF(x) || CA_IS_SIGNED_INF(y)) { ca_t t, u; truth_t xzero, yzero; xzero = ca_check_is_zero(x, ctx); yzero = ca_check_is_zero(y, ctx); if (xzero == T_TRUE || yzero == T_TRUE) { ca_undefined(res, ctx); return; } if (xzero == T_UNKNOWN || yzero == T_UNKNOWN) { ca_unknown(res, ctx); return; } ca_init(t, ctx); ca_init(u, ctx); ca_sgn(t, x, ctx); ca_sgn(u, y, ctx); ca_mul(res, t, u, ctx); if (ca_check_is_number(res, ctx) == T_TRUE) res->field |= CA_INF; ca_clear(t, ctx); ca_clear(u, ctx); return; } ca_unknown(res, ctx); return; } if (xfield == yfield) { zfield = xfield; _ca_make_field_element(res, zfield, ctx); if (CA_FIELD_IS_NF(zfield)) { nf_elem_mul(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_NF_ELEM(y), CA_FIELD_NF(zfield)); } else { fmpz_mpoly_q_mul(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_MPOLY_Q(y), CA_FIELD_MCTX(zfield, ctx)); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), zfield, ctx); _ca_mpoly_q_simplify_fraction_ideal(CA_MPOLY_Q(res), zfield, ctx); } ca_condense_field(res, ctx); return; } { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_merge_fields(t, u, x, y, ctx); ca_mul(res, t, u, ctx); ca_condense_field(res, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } } flint-3.1.3/src/ca/neg.c000066400000000000000000000024731461254215100147300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_neg(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_field_srcptr field; ulong field_flags; if (CA_IS_QQ(x, ctx)) { _ca_make_fmpq(res, ctx); fmpq_neg(CA_FMPQ(res), CA_FMPQ(x)); return; } if (CA_IS_SPECIAL(x)) { if (CA_IS_UNKNOWN(x) || CA_IS_UNDEFINED(x) || CA_IS_UNSIGNED_INF(x)) { ca_set(res, x, ctx); return; } } field_flags = x->field; _ca_make_field_element(res, (ca_field_ptr) (field_flags & ~CA_SPECIAL), ctx); field = CA_FIELD(res, ctx); res->field = field_flags; /* set special flags */ if (field == ctx->field_qq) { fmpq_neg(CA_FMPQ(res), CA_FMPQ(x)); } else if (CA_FIELD_IS_NF(field)) { nf_elem_neg(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_FIELD_NF(field)); } else { fmpz_mpoly_q_neg(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx)); } } flint-3.1.3/src/ca/neg_i.c000066400000000000000000000007411461254215100152340ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_neg_i(ca_t x, ca_ctx_t ctx) { ca_i(x, ctx); ca_neg(x, x, ctx); } flint-3.1.3/src/ca/neg_i_inf.c000066400000000000000000000007521461254215100160720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_neg_i_inf(ca_t x, ca_ctx_t ctx) { ca_neg_i(x, ctx); x->field |= CA_INF; } flint-3.1.3/src/ca/neg_inf.c000066400000000000000000000007551461254215100155650ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_neg_inf(ca_t x, ca_ctx_t ctx) { ca_set_si(x, -1, ctx); x->field |= CA_INF; } flint-3.1.3/src/ca/neg_one.c000066400000000000000000000010521461254215100155610ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_neg_one(ca_t x, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpz_one(fmpq_denref(CA_FMPQ(x))); fmpz_set_si(fmpq_numref(CA_FMPQ(x)), -1); } flint-3.1.3/src/ca/one.c000066400000000000000000000007531461254215100147370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_one(ca_t x, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpq_one(CA_FMPQ(x)); } flint-3.1.3/src/ca/pi.c000066400000000000000000000010741461254215100145630ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_pi(ca_t res, ca_ctx_t ctx) { _ca_make_field_element(res, _ca_ctx_get_field_const(ctx, CA_Pi), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } flint-3.1.3/src/ca/pi_i.c000066400000000000000000000010651461254215100150730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_pi_i(ca_t res, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_pi(res, ctx); ca_i(t, ctx); ca_mul(res, res, t, ctx); ca_clear(t, ctx); } flint-3.1.3/src/ca/pos_i_inf.c000066400000000000000000000007461461254215100161250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_pos_i_inf(ca_t x, ca_ctx_t ctx) { ca_i(x, ctx); x->field |= CA_INF; } flint-3.1.3/src/ca/pos_inf.c000066400000000000000000000007461461254215100156150ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_pos_inf(ca_t x, ca_ctx_t ctx) { ca_one(x, ctx); x->field |= CA_INF; } flint-3.1.3/src/ca/pow.c000066400000000000000000000272301461254215100147620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" slong nf_elem_bits(const nf_elem_t x, nf_t nf) { slong b, c; if (nf->flag & NF_LINEAR) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } else if (nf->flag & NF_QUADRATIC) { b = fmpz_bits(QNF_ELEM_NUMREF(x)); c = fmpz_bits(QNF_ELEM_NUMREF(x) + 1); b = FLINT_MAX(b, c); c = fmpz_bits(QNF_ELEM_DENREF(x)); b = FLINT_MAX(b, c); return b; } else { b = _fmpz_vec_max_bits(NF_ELEM_NUMREF(x), NF_ELEM(x)->length); b = FLINT_ABS(b); c = fmpz_bits(NF_ELEM_DENREF(x)); b = FLINT_MAX(b, c); return b; } } void _ca_pow_binexp(ca_t res, const ca_t x, slong n, ca_ctx_t ctx) { if (n == 0) { ca_one(res, ctx); } else if (n == 1) { ca_set(res, x, ctx); } else if (n == 2) { ca_mul(res, x, x, ctx); } else if (n < 0) { ca_inv(res, x, ctx); _ca_pow_binexp(res, res, -n, ctx); } else { /* todo: is left-to-right or right-to-left better? */ if (n % 2 == 0) { #if 0 _ca_pow_binexp(res, x, n / 2, ctx); _ca_pow_binexp(res, res, 2, ctx); #else _ca_pow_binexp(res, x, 2, ctx); _ca_pow_binexp(res, res, n / 2, ctx); #endif } else { if (res == x) { ca_t t; ca_init(t, ctx); _ca_pow_binexp(t, x, n - 1, ctx); ca_mul(res, t, x, ctx); ca_clear(t, ctx); } else { _ca_pow_binexp(res, x, n - 1, ctx); ca_mul(res, res, x, ctx); } } } } void ca_pow_si_arithmetic(ca_t res, const ca_t x, slong n, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { ca_unknown(res, ctx); } else if (n == 0) { ca_one(res, ctx); } else if (n == 1) { ca_set(res, x, ctx); } else if (n == -1) { ca_inv(res, x, ctx); } else if (n == 2) { ca_sqr(res, x, ctx); } else if (CA_IS_QQ(x, ctx)) { if (n < 0 && fmpq_is_zero(CA_FMPQ(x))) { ca_uinf(res, ctx); } else { fmpq_t t; fmpq_init(t); fmpq_pow_si(t, CA_FMPQ(x), n); ca_set_fmpq(res, t, ctx); fmpq_clear(t); } } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { ca_t t; /* Need to be sure we don't divide by zero, but more generally the base should never be a rational number here. */ if (nf_elem_is_rational(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx)))) { flint_throw(FLINT_ERROR, "ca_pow_fmpz: unexpected rational nf_elem\n"); } ca_init(t, ctx); if (n >= 0) ca_set(t, x, ctx); else { ca_inv(t, x, ctx); n = -n; } nf_elem_pow(CA_NF_ELEM(t), CA_NF_ELEM(t), n, CA_FIELD_NF(CA_FIELD(t, ctx))); ca_condense_field(t, ctx); ca_swap(res, t, ctx); ca_clear(t, ctx); } else { _ca_pow_binexp(res, x, n, ctx); } } /* (z^a)^b, assuming z != 0 */ void ca_pow_pow(ca_t res, const ca_t z, const ca_t a, const ca_t b, ca_ctx_t ctx) { ca_t t, u, pi; if (CA_IS_SPECIAL(z) || CA_IS_SPECIAL(a) || CA_IS_SPECIAL(b)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); ca_init(t, ctx); ca_init(u, ctx); ca_init(pi, ctx); ca_log(u, z, ctx); ca_mul(u, u, a, ctx); ca_pi(pi, ctx); ca_im(t, u, ctx); ca_div(t, t, pi, ctx); ca_sub_ui(t, t, 1, ctx); ca_div_ui(t, t, 2, ctx); ca_ceil(t, t, ctx); if (ca_check_is_zero(t, ctx) == T_TRUE) { ca_mul(u, a, b, ctx); ca_pow(res, z, u, ctx); } else { ca_t pi_i; ca_init(pi_i, ctx); ca_pi_i(pi_i, ctx); ca_mul(t, t, pi_i, ctx); ca_mul_ui(t, t, 2, ctx); ca_mul(t, t, b, ctx); ca_neg(t, t, ctx); ca_exp(t, t, ctx); ca_mul(u, a, b, ctx); ca_pow(res, z, u, ctx); ca_mul(res, res, t, ctx); ca_clear(pi_i, ctx); } ca_clear(t, ctx); ca_clear(u, ctx); ca_clear(pi, ctx); } /* warning: must have already checked for special values */ void _ca_pow_inert(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) { _ca_function_fxy(res, CA_Pow, x, y, ctx); _ca_mpoly_q_reduce_ideal(CA_MPOLY_Q(res), CA_FIELD(res, ctx), ctx); ca_condense_field(res, ctx); } void _ca_pow_general(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { ca_unknown(res, ctx); return; } { ca_ext_ptr ext = ca_is_gen_as_ext(x, ctx); /* (z^a)^b */ /* todo: also detect ((z^a)^n)^b, etc. */ if (ext != NULL && CA_EXT_HEAD(ext) == CA_Pow) { if (ca_check_is_zero(CA_EXT_FUNC_ARGS(ext), ctx) == T_FALSE) { ca_pow_pow(res, CA_EXT_FUNC_ARGS(ext), CA_EXT_FUNC_ARGS(ext) + 1, y, ctx); return; } } } /* todo: more simplifications */ /* inert pow must be a number -- avoid division by zero */ /* todo: more generally handle re(y) > 0 */ if (!(CA_IS_QQ(y, ctx) && fmpz_sgn(CA_FMPQ_NUMREF(y)) > 0)) { if (ca_check_is_zero(x, ctx) != T_FALSE) { /* todo: implement various cases */ ca_unknown(res, ctx); return; } } _ca_pow_inert(res, x, y, ctx); } void ca_pow_fmpz(ca_t res, const ca_t x, const fmpz_t y, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_UNSIGNED_INF(x)) { if (fmpz_sgn(y) > 0) ca_uinf(res, ctx); else if (fmpz_sgn(y) < 0) ca_zero(res, ctx); else ca_undefined(res, ctx); } else if (CA_IS_SIGNED_INF(x)) { if (fmpz_is_zero(y)) ca_undefined(res, ctx); else if (fmpz_sgn(y) < 0) ca_zero(res, ctx); else { ca_t t; ca_init(t, ctx); ca_sgn(t, x, ctx); ca_pow_fmpz(t, t, y, ctx); ca_pos_inf(res, ctx); ca_mul(res, res, t, ctx); ca_clear(t, ctx); } } else { /* unknown, undefined map to themselves */ ca_set(res, x, ctx); } return; } /* Deal with the most common cases */ if (fmpz_is_zero(y)) { ca_one(res, ctx); return; } if (fmpz_is_one(y)) { ca_set(res, x, ctx); return; } if (fmpz_equal_si(y, -1)) { ca_inv(res, x, ctx); return; } if (fmpz_equal_si(y, 2)) { ca_mul(res, x, x, ctx); return; } if (fmpz_equal_si(y, -2)) { ca_inv(res, x, ctx); ca_mul(res, res, res, ctx); return; } /* Rational base */ if (CA_IS_QQ(x, ctx)) { /* 0^y, y != 0 */ if (fmpz_is_zero(CA_FMPQ_NUMREF(x))) { if (fmpz_sgn(y) < 0) ca_uinf(res, ctx); else ca_zero(res, ctx); return; } /* 1^y or (-1)^y */ if (fmpz_is_one(CA_FMPQ_DENREF(x)) && fmpz_is_pm1(CA_FMPQ_NUMREF(x))) { if (fmpz_is_one(CA_FMPQ_NUMREF(x)) || fmpz_is_even(y)) ca_one(res, ctx); else ca_neg_one(res, ctx); return; } if (fmpz_bits(y) <= FLINT_BITS - 2) { slong xbits1, xbits2; xbits1 = fmpz_bits(CA_FMPQ_NUMREF(x)); xbits2 = fmpz_bits(CA_FMPQ_DENREF(x)); xbits1 = FLINT_MAX(xbits1, xbits2); if (xbits1 * (double) FLINT_ABS(*y) < ctx->options[CA_OPT_PREC_LIMIT]) { fmpq_t t; fmpq_init(t); fmpq_pow_si(t, CA_FMPQ(x), *y); ca_set_fmpq(res, t, ctx); fmpq_clear(t); return; } } } /* Todo: special case all roots of unity */ /* Number field base */ if (CA_FIELD_IS_NF(CA_FIELD(x, ctx)) && fmpz_bits(y) <= FLINT_BITS - 2) { slong xbits1; xbits1 = nf_elem_bits(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx))); /* Need to be sure we don't divide by zero, but more generally the base should never be a rational number here. */ if (nf_elem_is_rational(CA_NF_ELEM(x), CA_FIELD_NF(CA_FIELD(x, ctx)))) { flint_throw(FLINT_ERROR, "ca_pow_fmpz: unexpected rational nf_elem\n"); } if (xbits1 * (double) FLINT_ABS(*y) < ctx->options[CA_OPT_PREC_LIMIT]) { ca_t t; ca_init(t, ctx); if (fmpz_sgn(y) > 0) ca_set(t, x, ctx); else ca_inv(t, x, ctx); nf_elem_pow(CA_NF_ELEM(t), CA_NF_ELEM(t), FLINT_ABS(*y), CA_FIELD_NF(CA_FIELD(t, ctx))); ca_condense_field(t, ctx); ca_swap(res, t, ctx); ca_clear(t, ctx); return; } } /* todo: evaluation limits */ if (fmpz_cmp_si(y, -ctx->options[CA_OPT_POW_LIMIT]) >= 0 && fmpz_cmp_si(y, ctx->options[CA_OPT_POW_LIMIT]) <= 0) { _ca_pow_binexp(res, x, *y, ctx); return; } { ca_t t; ca_init(t, ctx); ca_set_fmpz(t, y, ctx); _ca_pow_general(res, x, t, ctx); ca_clear(t, ctx); } } void ca_pow(ca_t res, const ca_t x, const ca_t y, ca_ctx_t ctx) { if (CA_IS_QQ(y, ctx) && fmpz_is_one(CA_FMPQ_DENREF(y))) { ca_pow_fmpz(res, x, CA_FMPQ_NUMREF(y), ctx); return; } if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { ca_unknown(res, ctx); return; } if (CA_IS_QQ(y, ctx) && fmpz_equal_ui(CA_FMPQ_DENREF(y), 2)) { if (fmpz_equal_si(CA_FMPQ_NUMREF(y), 1)) { ca_sqrt(res, x, ctx); return; } else if (fmpz_equal_si(CA_FMPQ_NUMREF(y), 3)) { ca_t t; ca_init(t, ctx); ca_sqrt(t, x, ctx); ca_mul(res, t, x, ctx); ca_clear(t, ctx); return; } /* todo: evaluation limits */ else if (fmpz_cmp_si(CA_FMPQ_NUMREF(y), -ctx->options[CA_OPT_POW_LIMIT] / 2) >= 0 && fmpz_cmp_si(CA_FMPQ_NUMREF(y), ctx->options[CA_OPT_POW_LIMIT] / 2) <= 0) { ca_t t; ca_init(t, ctx); ca_sqrt(t, x, ctx); _ca_pow_binexp(res, t, *CA_FMPQ_NUMREF(y), ctx); ca_clear(t, ctx); return; } } _ca_pow_general(res, x, y, ctx); } void ca_pow_fmpq(ca_t res, const ca_t x, const fmpq_t y, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_set_fmpq(t, y, ctx); ca_pow(res, x, t, ctx); ca_clear(t, ctx); } void ca_pow_si(ca_t res, const ca_t x, slong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_si(t, y); ca_pow_fmpz(res, x, t, ctx); fmpz_clear(t); } void ca_pow_ui(ca_t res, const ca_t x, ulong y, ca_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, y); ca_pow_fmpz(res, x, t, ctx); fmpz_clear(t); } flint-3.1.3/src/ca/randtest.c000066400000000000000000000107761461254215100160100ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_randtest_same_nf(ca_t res, flint_rand_t state, const ca_t x, slong bits, slong den_bits, ca_ctx_t ctx) { if (n_randint(state, 2) || CA_IS_QQ(x, ctx)) { _ca_make_fmpq(res, ctx); fmpz_randtest(CA_FMPQ_NUMREF(res), state, bits); fmpz_randtest_not_zero(CA_FMPQ_DENREF(res), state, den_bits); fmpz_abs(CA_FMPQ_DENREF(res), CA_FMPQ_DENREF(res)); } else if (CA_FIELD_IS_NF(CA_FIELD(x, ctx))) { fmpq_poly_t p; fmpq_poly_init(p); fmpq_poly_randtest(p, state, qqbar_degree(CA_FIELD_NF_QQBAR(CA_FIELD(x, ctx))), bits); fmpz_randtest_not_zero(fmpq_poly_denref(p), state, den_bits); fmpz_abs(fmpq_poly_denref(p), fmpq_poly_denref(p)); fmpq_poly_canonicalise(p); ca_set(res, x, ctx); nf_elem_set_fmpq_poly(CA_NF_ELEM(res), p, CA_FIELD_NF(CA_FIELD(x, ctx))); ca_condense_field(res, ctx); fmpq_poly_clear(p); } else { flint_throw(FLINT_ERROR, "ca_randtest_same_nf: not implemented\n"); } } void ca_randtest_rational(ca_t res, flint_rand_t state, slong bits, ca_ctx_t ctx) { fmpq_t t; fmpq_init(t); fmpq_randtest(t, state, bits); ca_set_fmpq(res, t, ctx); fmpq_clear(t); } void ca_randtest_qqbar(ca_t res, flint_rand_t state, slong deg, slong bits, ca_ctx_t ctx) { qqbar_t q; qqbar_init(q); qqbar_randtest(q, state, deg, bits); ca_set_qqbar(res, q, ctx); qqbar_clear(q); } void ca_randtest(ca_t res, flint_rand_t state, slong len, slong bits, ca_ctx_t ctx) { if (len == 0 || n_randint(state, 2)) { switch (n_randint(state, 10)) { case 0: ca_randtest_qqbar(res, state, 2, FLINT_MAX(bits, 2), ctx); break; case 1: ca_i(res, ctx); break; case 2: ca_pi(res, ctx); break; case 3: ca_pi_i(res, ctx); break; case 4: ca_set_si(res, -6 + (slong) n_randint(state, 13), ctx); ca_sqrt(res, res, ctx); break; default: ca_randtest_rational(res, state, bits, ctx); break; } } else if (n_randint(state, 10) != 0) { ca_t t; ca_init(t, ctx); ca_randtest(t, state, len - 1, bits, ctx); ca_randtest(res, state, len - 1, bits, ctx); switch (n_randint(state, 4)) { case 0: ca_add(res, res, t, ctx); break; case 1: ca_sub(res, res, t, ctx); break; case 2: ca_mul(res, res, t, ctx); break; default: if (ca_check_is_zero(t, ctx) == T_FALSE) ca_div(res, res, t, ctx); break; } ca_clear(t, ctx); } else { ca_randtest(res, state, len - 1, bits, ctx); switch (n_randint(state, 2)) { case 0: ca_exp(res, res, ctx); break; default: if (ca_check_is_zero(res, ctx) != T_FALSE) ca_set_ui(res, 2, ctx); ca_log(res, res, ctx); break; } } } void ca_randtest_special(ca_t res, flint_rand_t state, slong len, slong bits, ca_ctx_t ctx) { if (n_randint(state, 4) == 0) { switch (n_randint(state, 7)) { case 0: ca_pos_inf(res, ctx); break; case 1: ca_neg_inf(res, ctx); break; case 2: ca_pos_i_inf(res, ctx); break; case 3: ca_neg_i_inf(res, ctx); /* todo: other signed infs? */ break; case 4: ca_uinf(res, ctx); break; case 5: ca_undefined(res, ctx); break; default: ca_unknown(res, ctx); } } else { ca_randtest(res, state, len, bits, ctx); } } flint-3.1.3/src/ca/re.c000066400000000000000000000025521461254215100145630ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_re(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_UNKNOWN(x)) ca_unknown(res, ctx); else ca_undefined(res, ctx); } else if (CA_IS_QQ(x, ctx)) { ca_set(res, x, ctx); } else if (CA_IS_QQ_I(x, ctx)) { const fmpz *n, *d; fmpq_t t; n = QNF_ELEM_NUMREF(CA_NF_ELEM(x)); d = QNF_ELEM_DENREF(CA_NF_ELEM(x)); fmpq_init(t); fmpq_set_fmpz_frac(t, n, d); ca_set_fmpq(res, t, ctx); fmpq_clear(t); } else if (ca_check_is_real(x, ctx) == T_TRUE) /* todo: avoid duplicate computations with is_real/is_imaginary */ { ca_set(res, x, ctx); } else if (ca_check_is_imaginary(x, ctx) == T_TRUE) { ca_zero(res, ctx); } else { _ca_make_field_element(res, _ca_ctx_get_field_fx(ctx, CA_Re, x), ctx); fmpz_mpoly_q_gen(CA_MPOLY_Q(res), 0, CA_MCTX_1(ctx)); } } flint-3.1.3/src/ca/rewrite_complex_normal_form.c000066400000000000000000000260571461254215100217660ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_vec.h" /* todo */ void ca_rewrite_complex_normal_form(ca_t res, const ca_t x, int deep, ca_ctx_t ctx); /* todo */ void ca_set_ext(ca_t res, ca_ext_srcptr ext, ca_ctx_t ctx); /* todo */ ulong qqbar_try_as_cyclotomic(qqbar_t zeta, fmpq_poly_t poly, const qqbar_t x); /* todo: Re, Im, Abs, Sgn ... */ void ca_rewrite_ext_complex_normal_form(ca_t res, ca_ext_ptr ext, int deep, ca_ctx_t ctx) { switch (CA_EXT_HEAD(ext)) { case CA_QQBar: if (qqbar_is_i(CA_EXT_QQBAR(ext))) { ca_set_ext(res, ext, ctx); } else if (qqbar_is_root_of_unity(NULL, NULL, CA_EXT_QQBAR(ext))) { ca_set_ext(res, ext, ctx); } else { fmpq_poly_t poly; qqbar_t zeta; ulong q; qqbar_init(zeta); fmpq_poly_init(poly); q = qqbar_try_as_cyclotomic(zeta, poly, CA_EXT_QQBAR(ext)); if (q != 0) { ca_set_qqbar(res, zeta, ctx); ca_fmpq_poly_evaluate(res, poly, res, ctx); } else { ca_set_ext(res, ext, ctx); } qqbar_clear(zeta); fmpq_poly_clear(poly); } break; case CA_Re: case CA_Im: case CA_Conjugate: case CA_Abs: case CA_Sign: case CA_Arg: { ca_t t, u; truth_t is_zero; ca_init(t, ctx); ca_init(u, ctx); if (deep) ca_rewrite_complex_normal_form(t, CA_EXT_FUNC_ARGS(ext), deep, ctx); else ca_set(t, CA_EXT_FUNC_ARGS(ext), ctx); switch (CA_EXT_HEAD(ext)) { case CA_Re: ca_conj_deep(u, t, ctx); ca_add(res, t, u, ctx); ca_div_ui(res, res, 2, ctx); break; case CA_Im: ca_conj_deep(u, t, ctx); ca_sub(res, t, u, ctx); ca_div_ui(res, res, 2, ctx); ca_neg_i(t, ctx); ca_mul(res, res, t, ctx); break; case CA_Conjugate: ca_conj_deep(res, t, ctx); break; case CA_Abs: ca_conj_deep(u, t, ctx); ca_mul(t, t, u, ctx); ca_sqrt(res, t, ctx); break; case CA_Sign: is_zero = ca_check_is_zero(t, ctx); if (is_zero == T_TRUE) { ca_zero(res, ctx); } else if (is_zero == T_FALSE) { ca_conj_deep(u, t, ctx); ca_mul(u, t, u, ctx); ca_sqrt(u, u, ctx); /* todo: division by zero is impossible; optimizations here */ ca_div(res, t, u, ctx); } else { ca_sgn(res, t, ctx); } break; case CA_Arg: is_zero = ca_check_is_zero(t, ctx); if (is_zero == T_TRUE) { ca_zero(res, ctx); } else if (is_zero == T_FALSE) { /* todo: better to create two logs? */ ca_conj_deep(u, t, ctx); ca_mul(u, t, u, ctx); ca_sqrt(u, u, ctx); ca_div(u, t, u, ctx); ca_log(u, u, ctx); ca_neg_i(t, ctx); ca_mul(res, t, u, ctx); } else { ca_arg(res, t, ctx); } break; default: flint_throw(FLINT_ERROR, "(%s)\n", __func__); } ca_clear(t, ctx); ca_clear(u, ctx); } break; /* sin(x) = (exp(ix) - 1/exp(ix))/(2i) */ /* cos(x) = (exp(ix) + 1/exp(ix))/2 */ /* tan(x) = 2i/(exp(2ix)+1) */ case CA_Sin: case CA_Cos: case CA_Tan: { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); if (deep) ca_rewrite_complex_normal_form(t, CA_EXT_FUNC_ARGS(ext), deep, ctx); else ca_set(t, CA_EXT_FUNC_ARGS(ext), ctx); if (CA_EXT_HEAD(ext) == CA_Sin) ca_sin_cos_exponential(res, NULL, t, ctx); else if (CA_EXT_HEAD(ext) == CA_Cos) ca_sin_cos_exponential(NULL, res, t, ctx); else { ca_sin_cos_exponential(t, u, t, ctx); ca_div(res, t, u, ctx); } ca_clear(t, ctx); ca_clear(u, ctx); } break; case CA_Atan: case CA_Asin: case CA_Acos: { ca_t t; ca_init(t, ctx); if (deep) ca_rewrite_complex_normal_form(t, CA_EXT_FUNC_ARGS(ext), deep, ctx); else ca_set(t, CA_EXT_FUNC_ARGS(ext), ctx); if (CA_EXT_HEAD(ext) == CA_Asin) ca_asin_logarithm(res, t, ctx); else if (CA_EXT_HEAD(ext) == CA_Acos) ca_acos_logarithm(res, t, ctx); else ca_atan_logarithm(res, t, ctx); ca_clear(t, ctx); } break; case CA_Sqrt: case CA_Exp: case CA_Log: if (deep) { ca_rewrite_complex_normal_form(res, CA_EXT_FUNC_ARGS(ext), deep, ctx); if (ca_equal_repr(res, CA_EXT_FUNC_ARGS(ext), ctx)) { ca_set_ext(res, ext, ctx); } else { switch (CA_EXT_HEAD(ext)) { case CA_Exp: ca_exp(res, res, ctx); break; case CA_Log: ca_log(res, res, ctx); break; case CA_Sqrt: ca_sqrt(res, res, ctx); break; default: flint_throw(FLINT_ERROR, "(%s)\n", __func__); } } } else { ca_set_ext(res, ext, ctx); } break; default: /* todo: deep */ ca_set_ext(res, ext, ctx); } } void ca_rewrite_complex_normal_form(ca_t res, const ca_t x, int deep, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { ca_sgn(res, x, ctx); ca_rewrite_complex_normal_form(res, res, deep, ctx); if (!ca_is_unknown(res, ctx)) res->field |= CA_INF; } else { ca_set(res, x, ctx); } } else if (CA_IS_QQ(x, ctx) || CA_IS_QQ_I(x, ctx)) { ca_set(res, x, ctx); } else { ca_field_ptr K = CA_FIELD(x, ctx); if (CA_FIELD_IS_NF(K)) { if (qqbar_is_root_of_unity(NULL, NULL, CA_FIELD_NF_QQBAR(K))) { ca_set(res, x, ctx); } else { fmpq_poly_t poly, xpoly; qqbar_t zeta; ulong q; qqbar_init(zeta); fmpq_poly_init(poly); q = qqbar_try_as_cyclotomic(zeta, poly, CA_FIELD_NF_QQBAR(K)); if (q != 0) { fmpq_poly_init(xpoly); nf_elem_get_fmpq_poly(xpoly, CA_NF_ELEM(x), CA_FIELD_NF(K)); ca_set_qqbar(res, zeta, ctx); ca_fmpq_poly_evaluate(res, poly, res, ctx); ca_fmpq_poly_evaluate(res, xpoly, res, ctx); fmpq_poly_clear(xpoly); } else { ca_set(res, x, ctx); } qqbar_clear(zeta); fmpq_poly_clear(poly); } } else if (0) { ca_set(res, x, ctx); } else { slong nvars; int * used; slong i; ca_ptr cext; nvars = CA_FIELD_LENGTH(K); used = flint_calloc(nvars, sizeof(int)); cext = _ca_vec_init(nvars, ctx); fmpz_mpoly_q_used_vars(used, CA_MPOLY_Q(x), CA_FIELD_MCTX(K, ctx)); for (i = 0; i < nvars; i++) { if (used[i]) { ca_rewrite_ext_complex_normal_form(cext + i, CA_FIELD_EXT_ELEM(K, i), deep, ctx); } } ca_fmpz_mpoly_q_evaluate_no_division_by_zero(res, CA_MPOLY_Q(x), cext, CA_FIELD_MCTX(K, ctx), ctx); _ca_vec_clear(cext, nvars, ctx); /* Root of unity hack: introduce artificial root of unity to force simplifications. This should not be necessary; cases where it helps are a sign that we are not finding all exponential relations. */ if (0 && !CA_IS_SPECIAL(res) && !CA_FIELD_IS_QQ(CA_FIELD(res, ctx)) && !CA_FIELD_IS_NF(CA_FIELD(res, ctx))) { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_pi_i(t, ctx); ca_div_ui(t, t, 12, ctx); ca_exp(t, t, ctx); ca_add(u, res, t, ctx); ca_sub(u, u, t, ctx); if (ca_cmp_repr(u, res, ctx) < 0) ca_swap(res, u, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } flint_free(used); } } } flint-3.1.3/src/ca/set.c000066400000000000000000000025631461254215100147520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_set(ca_t res, const ca_t x, ca_ctx_t ctx) { if (res != x) { ulong field_flags; ca_field_srcptr field; field_flags = x->field; field = (ca_field_srcptr) (x->field & ~CA_SPECIAL); /* for Undefined, Unknown, UnsignedInfinity */ if (field == NULL) { ca_clear(res, ctx); res->field = field_flags; return; } _ca_make_field_element(res, field, ctx); res->field = field_flags; /* set special flags */ if (field != NULL) { if (CA_FIELD_IS_QQ(field)) { fmpq_set(CA_FMPQ(res), CA_FMPQ(x)); } else if (CA_FIELD_IS_NF(field)) { nf_elem_set(CA_NF_ELEM(res), CA_NF_ELEM(x), CA_FIELD_NF(field)); } else { fmpz_mpoly_q_set(CA_MPOLY_Q(res), CA_MPOLY_Q(x), CA_FIELD_MCTX(field, ctx)); } } } } flint-3.1.3/src/ca/set_d.c000066400000000000000000000015441461254215100152530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_set_d(ca_t res, double x, ca_ctx_t ctx) { arf_t t; arf_init(t); arf_set_d(t, x); if (arf_is_finite(t)) { _ca_make_fmpq(res, ctx); arf_get_fmpq(CA_FMPQ(res), t); } else { if (arf_is_pos_inf(t)) ca_pos_inf(res, ctx); else if (arf_is_neg_inf(t)) ca_neg_inf(res, ctx); else ca_unknown(res, ctx); /* or undefined? */ } /* no need to free t */ } flint-3.1.3/src/ca/set_d_d.c000066400000000000000000000013731461254215100155560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_set_d_d(ca_t res, double x, double y, ca_ctx_t ctx) { if (y == 0.0) { ca_set_d(res, x, ctx); } else { ca_t t; ca_init(t, ctx); ca_set_d(t, y, ctx); ca_i(res, ctx); ca_mul(res, res, t, ctx); ca_set_d(t, x, ctx); ca_add(res, res, t, ctx); ca_clear(t, ctx); } } flint-3.1.3/src/ca/set_fexpr.c000066400000000000000000000214071461254215100161540ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #include "ca.h" #include "ca_ext.h" #include "ca_vec.h" #define BINARY_OP(ca_func) \ if (nargs == 2) \ { \ ca_init(t, ctx); \ fexpr_view_arg(arg, expr, 0); \ success = _ca_set_fexpr(res, inputs, outputs, arg, ctx); \ if (success) \ { \ fexpr_view_next(arg); \ success = _ca_set_fexpr(t, inputs, outputs, arg, ctx); \ if (success) \ ca_func(res, res, t, ctx); \ } \ ca_clear(t, ctx); \ return success; \ } \ return 0; \ #define UNARY_OP(ca_func) \ if (nargs == 1) \ { \ fexpr_view_arg(arg, expr, 0); \ success = _ca_set_fexpr(res, inputs, outputs, arg, ctx); \ if (success) \ ca_func(res, res, ctx); \ return success; \ } \ return 0; \ int _ca_set_fexpr(ca_t res, fexpr_vec_t inputs, ca_vec_t outputs, const fexpr_t expr, ca_ctx_t ctx) { if (fexpr_is_integer(expr)) { _ca_make_fmpq(res, ctx); fexpr_get_fmpz(CA_FMPQ_NUMREF(res), expr); fmpz_one(CA_FMPQ_DENREF(res)); return 1; } if (fexpr_is_any_builtin_symbol(expr)) { slong op = FEXPR_BUILTIN_ID(expr->data[0]); switch (op) { case FEXPR_Pi: ca_pi(res, ctx); return 1; case FEXPR_NumberI: ca_i(res, ctx); return 1; case FEXPR_NumberE: ca_one(res, ctx); ca_exp(res, res, ctx); return 1; case FEXPR_Euler: ca_euler(res, ctx); return 1; case FEXPR_GoldenRatio: ca_sqrt_ui(res, 5, ctx); ca_add_ui(res, res, 1, ctx); ca_div_ui(res, res, 2, ctx); return 1; case FEXPR_Infinity: ca_pos_inf(res, ctx); return 1; case FEXPR_UnsignedInfinity: ca_uinf(res, ctx); return 1; case FEXPR_Undefined: ca_undefined(res, ctx); return 1; case FEXPR_Unknown: ca_unknown(res, ctx); return 1; } return 0; } if (fexpr_is_symbol(expr)) { slong i, num_defs; num_defs = inputs->length; /* Treat local definitions as a stack, more recent ones overriding older ones */ for (i = num_defs - 1; i >= 0; i--) { if (fexpr_equal(expr, fexpr_vec_entry(inputs, i))) { ca_set(res, ca_vec_entry(outputs, i), ctx); return 1; } } return 0; } if (fexpr_is_any_builtin_call(expr)) { fexpr_t func, arg; slong op, i, nargs; int success; ca_t t; nargs = fexpr_nargs(expr); fexpr_view_func(func, expr); op = FEXPR_BUILTIN_ID(func->data[0]); /* Parse local definitions */ if (op == FEXPR_Where) { slong num_previous_defs; num_previous_defs = inputs->length; success = 1; /* Parse in reverse order; this assumes definitions are in the form x = f(y,z), y = g(z), z = h which is what ca_get_fexpr currently generates. Should this work in both directions (or any order)? */ for (i = nargs - 1; i >= 1; i--) { fexpr_t defn, symbol, value; fexpr_view_arg(defn, expr, i); if (!fexpr_is_builtin_call(defn, FEXPR_Def) || fexpr_nargs(defn) != 2) { success = 0; break; } fexpr_view_arg(symbol, defn, 0); fexpr_view_arg(value, defn, 1); success = _ca_set_fexpr(res, inputs, outputs, value, ctx); if (!success) break; fexpr_vec_append(inputs, symbol); ca_vec_append(outputs, res, ctx); } if (success) { fexpr_view_arg(arg, expr, 0); success = _ca_set_fexpr(res, inputs, outputs, arg, ctx); } /* We are done with the local definitions, so erase anything new. */ fexpr_vec_set_length(inputs, num_previous_defs); ca_vec_set_length(outputs, num_previous_defs, ctx); return success; } switch (op) { /* todo: generalize to non-algebraics; handle large decimals efficiently */ case FEXPR_Decimal: case FEXPR_PolynomialRootIndexed: case FEXPR_PolynomialRootNearest: case FEXPR_AlgebraicNumberSerialized: { qqbar_t a; qqbar_init(a); success = qqbar_set_fexpr(a, expr); if (success) ca_set_qqbar(res, a, ctx); qqbar_clear(a); return success; } case FEXPR_Pos: UNARY_OP(ca_set) case FEXPR_Neg: UNARY_OP(ca_neg) case FEXPR_Sub: BINARY_OP(ca_sub) case FEXPR_Div: BINARY_OP(ca_div) case FEXPR_Pow: BINARY_OP(ca_pow) case FEXPR_Sqrt: UNARY_OP(ca_sqrt) case FEXPR_Exp: UNARY_OP(ca_exp) case FEXPR_Log: UNARY_OP(ca_log) case FEXPR_Sin: UNARY_OP(ca_sin) case FEXPR_Cos: UNARY_OP(ca_cos) case FEXPR_Tan: UNARY_OP(ca_tan) case FEXPR_Cot: UNARY_OP(ca_cot) case FEXPR_Atan: UNARY_OP(ca_atan) case FEXPR_Acos: UNARY_OP(ca_acos) case FEXPR_Asin: UNARY_OP(ca_asin) case FEXPR_Sign: UNARY_OP(ca_sgn) case FEXPR_Csgn: UNARY_OP(ca_csgn) case FEXPR_Arg: UNARY_OP(ca_arg) case FEXPR_Abs: UNARY_OP(ca_abs) case FEXPR_Re: UNARY_OP(ca_re) case FEXPR_Im: UNARY_OP(ca_im) case FEXPR_Conjugate: UNARY_OP(ca_conj) case FEXPR_Floor: UNARY_OP(ca_floor) case FEXPR_Ceil: UNARY_OP(ca_ceil) case FEXPR_Gamma: UNARY_OP(ca_gamma) case FEXPR_Erf: UNARY_OP(ca_erf) case FEXPR_Erfc: UNARY_OP(ca_erfc) case FEXPR_Erfi: UNARY_OP(ca_erfi) case FEXPR_Add: if (nargs == 0) { ca_zero(res, ctx); return 1; } fexpr_view_arg(arg, expr, 0); success = _ca_set_fexpr(res, inputs, outputs, arg, ctx); if (success && nargs > 1) { /* todo: divide and conquer for large nargs? */ ca_init(t, ctx); for (i = 1; i < nargs && success; i++) { fexpr_view_next(arg); success = _ca_set_fexpr(t, inputs, outputs, arg, ctx); if (success) ca_add(res, res, t, ctx); } ca_clear(t, ctx); } return success; case FEXPR_Mul: if (nargs == 0) { ca_one(res, ctx); return 1; } fexpr_view_arg(arg, expr, 0); success = _ca_set_fexpr(res, inputs, outputs, arg, ctx); if (success && nargs > 1) { /* todo: divide and conquer for large nargs? */ ca_init(t, ctx); for (i = 1; i < nargs && success; i++) { fexpr_view_next(arg); success = _ca_set_fexpr(t, inputs, outputs, arg, ctx); if (success) ca_mul(res, res, t, ctx); } ca_clear(t, ctx); } return success; } } return 0; } int ca_set_fexpr(ca_t res, const fexpr_t expr, ca_ctx_t ctx) { int success; fexpr_vec_t inputs; ca_vec_t outputs; fexpr_vec_init(inputs, 0); ca_vec_init(outputs, 0, ctx); success = _ca_set_fexpr(res, inputs, outputs, expr, ctx); fexpr_vec_clear(inputs); ca_vec_clear(outputs, ctx); return success; } flint-3.1.3/src/ca/set_fmpq.c000066400000000000000000000010031461254215100157610ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_set_fmpq(ca_t x, const fmpq_t v, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpq_set(CA_FMPQ(x), v); } flint-3.1.3/src/ca/set_fmpz.c000066400000000000000000000010531461254215100157770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_set_fmpz(ca_t x, const fmpz_t v, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpz_set(CA_FMPQ_NUMREF(x), v); fmpz_one(CA_FMPQ_DENREF(x)); } flint-3.1.3/src/ca/set_qqbar.c000066400000000000000000000245111461254215100161350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" #include "ca.h" #include "ca_ext.h" #include "ca_field.h" #define FACTOR_SMOOTH_BOUND 32 /* Write |n| = A * B^2 */ static void _fmpz_factor_square_root(fmpz_t A, fmpz_t B, const fmpz_t n, slong smooth_bound) { fmpz_factor_t fac; fmpz_t t; slong i; fmpz_factor_init(fac); fmpz_factor_smooth(fac, n, smooth_bound, -1); /* -1 => no primality test */ fmpz_one(A); fmpz_one(B); fmpz_init(t); for (i = 0; i < fac->num; i++) { if (fac->exp[i] == 1) { fmpz_mul(A, A, fac->p + i); } else if (fac->exp[i] == 2) { fmpz_mul(B, B, fac->p + i); } else { fmpz_pow_ui(t, fac->p + i, fac->exp[i] / 2); fmpz_mul(B, B, t); if (fac->exp[i] % 2) fmpz_mul(A, A, fac->p + i); } } fmpz_factor_clear(fac); fmpz_clear(t); } ca_field_ptr ca_field_cache_lookup_qqbar(ca_field_cache_t cache, const qqbar_t x, ca_ctx_t ctx); ca_field_ptr ca_ctx_get_field_qqbar(ca_ctx_t ctx, const qqbar_t x) { ca_ext_t ext; ca_ext_struct * ext_ptr[1]; ca_field_ptr field; field = ca_field_cache_lookup_qqbar(CA_CTX_FIELD_CACHE(ctx), x, ctx); if (field == NULL) { /* todo: shallow copy */ ca_ext_init_qqbar(ext, x, ctx); ext_ptr[0] = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), ext, ctx); field = ca_field_cache_insert_ext(CA_CTX_FIELD_CACHE(ctx), ext_ptr, 1, ctx); ca_ext_clear(ext, ctx); } return field; } #if 0 /* Find if sqrt(A) is cached; otherwise create new field */ /* Todo: fast search table */ slong ca_ctx_get_quadratic_field(ca_ctx_t ctx, const fmpz_t A) { qqbar_t T; slong i; for (i = 0; i < ctx->fields_len; i++) { if (ctx->fields[i].type == CA_FIELD_TYPE_NF) { const qqbar_struct * v; v = CA_FIELD_NF_QQBAR(ctx->fields + i); if (qqbar_degree(v) == 2) { if (fmpz_is_one(QQBAR_COEFFS(v) + 2) && fmpz_is_zero(QQBAR_COEFFS(v) + 1) && (fmpz_cmpabs(QQBAR_COEFFS(v), A) == 0) && !fmpz_equal(QQBAR_COEFFS(v), A)) { if (fmpz_sgn(A) < 0) { if (qqbar_sgn_im(v) > 0) return i; } else { if (qqbar_sgn_re(v) >= 0) return i; } } } } } i = ctx->fields_len; if (i >= ctx->fields_alloc) { ctx->fields = (ca_field_struct *) flint_realloc(ctx->fields, sizeof(ca_field_struct) * 2 * ctx->fields_alloc); ctx->fields_alloc = 2 * ctx->fields_alloc; } ctx->fields_len = i + 1; qqbar_init(T); qqbar_set_fmpz(T, A); qqbar_sqrt(T, T); ca_field_init_nf(ctx->fields + i, T); qqbar_clear(T); return i; } #else ca_field_srcptr ca_ctx_get_quadratic_field(ca_ctx_t ctx, const fmpz_t A) { ca_field_srcptr res; qqbar_t x; qqbar_init(x); #if 0 qqbar_set_fmpz(x, A); qqbar_sqrt(x, x); #else fmpz_poly_fit_length(QQBAR_POLY(x), 3); _fmpz_poly_set_length(QQBAR_POLY(x), 3); fmpz_neg(QQBAR_COEFFS(x) + 0, A); fmpz_zero(QQBAR_COEFFS(x) + 1); fmpz_one(QQBAR_COEFFS(x) + 2); acb_set_fmpz(QQBAR_ENCLOSURE(x), A); acb_sqrt(QQBAR_ENCLOSURE(x), QQBAR_ENCLOSURE(x), QQBAR_DEFAULT_PREC); #endif res = ca_ctx_get_field_qqbar(ctx, x); qqbar_clear(x); return res; } #endif ca_field_srcptr ca_ctx_get_cyclotomic_field(ca_ctx_t ctx, ulong n) { ca_field_srcptr res; qqbar_t x; qqbar_init(x); qqbar_root_of_unity(x, 1, n); res = ca_ctx_get_field_qqbar(ctx, x); qqbar_clear(x); return res; } static int fmpz_discr_3(fmpz_t t, const fmpz_t D) { if (fmpz_sgn(D) < 0) return 0; if (!fmpz_divisible_si(D, 3)) return 0; fmpz_divexact_ui(t, D, 3); if (!fmpz_is_square(t)) return 0; return 1; } void ca_set_qqbar(ca_t res, const qqbar_t x, ca_ctx_t ctx) { slong d; d = qqbar_degree(x); if (d == 1) { _ca_make_fmpq(res, ctx); qqbar_get_fmpq(CA_FMPQ(res), x); } else if (d == 2) { const fmpz *a, *b, *c; fmpz_t D, t; fmpz * res_num; fmpz * res_den; a = QQBAR_COEFFS(x) + 2; b = QQBAR_COEFFS(x) + 1; c = QQBAR_COEFFS(x) + 0; /* x = (-b +/- sqrt(b^2 - 4ac))/(2a) */ fmpz_init(D); fmpz_init(t); fmpz_mul(D, a, c); fmpz_mul_2exp(D, D, 2); fmpz_submul(D, b, b); /* -D is a square <=> element of Q(i) */ if (fmpz_is_square(D)) { fmpz_sqrt(D, D); _ca_make_field_element(res, ctx->field_qq_i, ctx); res_num = QNF_ELEM_NUMREF(CA_NF_ELEM(res)); res_den = QNF_ELEM_DENREF(CA_NF_ELEM(res)); if (qqbar_sgn_im(x) > 0) fmpz_set(res_num + 1, D); else fmpz_neg(res_num + 1, D); fmpz_neg(res_num, b); fmpz_mul_2exp(res_den, a, 1); /* todo: is gcd avoidable? */ /* todo: at least use fmpz_gcd3 */ fmpz_gcd(D, res_num, res_num + 1); fmpz_gcd(D, D, res_den); if (!fmpz_is_one(D)) { fmpz_divexact(res_num, res_num, D); fmpz_divexact(res_num + 1, res_num + 1, D); fmpz_divexact(res_den, res_den, D); } } else if (fmpz_discr_3(t, D)) /* Special case for Q(zeta_3) */ { ca_field_srcptr K; fmpz_sqrt(D, t); K = ca_ctx_get_cyclotomic_field(ctx, 3); _ca_make_field_element(res, K, ctx); res_num = QNF_ELEM_NUMREF(CA_NF_ELEM(res)); res_den = QNF_ELEM_DENREF(CA_NF_ELEM(res)); if (qqbar_sgn_im(x) < 0) { fmpz_neg(D, D); } fmpz_sub(res_num, D, b); fmpz_mul_2exp(res_num + 1, D, 1); fmpz_mul_2exp(res_den, a, 1); /* todo: is gcd avoidable? */ /* todo: at least use fmpz_gcd3 */ fmpz_gcd(D, res_num, res_num + 1); fmpz_gcd(D, D, res_den); if (!fmpz_is_one(D)) { fmpz_divexact(res_num, res_num, D); fmpz_divexact(res_num + 1, res_num + 1, D); fmpz_divexact(res_den, res_den, D); } } else { fmpz_t A, B; ca_field_srcptr field; fmpz_neg(D, D); fmpz_init(A); fmpz_init(B); /* sqrt(|D|) = A * B^2 => sqrt(D) = sqrt(A) * B (D > 0) sqrt(-A) * B (D < 0) */ _fmpz_factor_square_root(A, B, D, FACTOR_SMOOTH_BOUND); if (fmpz_sgn(D) < 0) fmpz_neg(A, A); field = ca_ctx_get_quadratic_field(ctx, A); _ca_make_field_element(res, field, ctx); res_num = QNF_ELEM_NUMREF(CA_NF_ELEM(res)); res_den = QNF_ELEM_DENREF(CA_NF_ELEM(res)); /* x = (-b +/- B*sqrt(A))/(2a) */ fmpz_neg(res_num, b); fmpz_mul_2exp(res_den, a, 1); /* determine the correct sign */ { if (fmpz_sgn(D) < 0) { if (qqbar_sgn_im(x) > 0) fmpz_set(res_num + 1, B); else fmpz_neg(res_num + 1, B); } else if (fmpz_is_zero(b)) { if (qqbar_sgn_re(x) > 0) fmpz_set(res_num + 1, B); else fmpz_neg(res_num + 1, B); } else { arb_t r1, r2; slong prec; arb_init(r1); arb_init(r2); for (prec = 64; ; prec *= 2) { arb_sqrt_fmpz(r1, A, prec); arb_mul_fmpz(r1, r1, B, prec); arb_add_fmpz(r2, r1, b, prec); arb_neg(r2, r2); arb_sub_fmpz(r1, r1, b, prec); arb_div_fmpz(r1, r1, a, prec); arb_div_fmpz(r2, r2, a, prec); arb_mul_2exp_si(r1, r1, -1); arb_mul_2exp_si(r2, r2, -1); if (arb_overlaps(r1, acb_realref(QQBAR_ENCLOSURE(x))) && !arb_overlaps(r2, acb_realref(QQBAR_ENCLOSURE(x)))) { fmpz_set(res_num + 1, B); break; } if (arb_overlaps(r2, acb_realref(QQBAR_ENCLOSURE(x))) && !arb_overlaps(r1, acb_realref(QQBAR_ENCLOSURE(x)))) { fmpz_neg(res_num + 1, B); break; } } arb_clear(r1); arb_clear(r2); } } /* todo: use fmpz_gcd3 */ fmpz_gcd(D, res_num, res_num + 1); fmpz_gcd(D, D, res_den); if (!fmpz_is_one(D)) { fmpz_divexact(res_num, res_num, D); fmpz_divexact(res_num + 1, res_num + 1, D); fmpz_divexact(res_den, res_den, D); } fmpz_clear(A); fmpz_clear(B); } fmpz_clear(D); fmpz_clear(t); } else { ca_field_srcptr field; field = ca_ctx_get_field_qqbar(ctx, x); _ca_make_field_element(res, field, ctx); nf_elem_gen(CA_NF_ELEM(res), CA_FIELD_NF(field)); } } flint-3.1.3/src/ca/set_si.c000066400000000000000000000010451461254215100154370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_set_si(ca_t x, slong v, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpz_set_si(CA_FMPQ_NUMREF(x), v); fmpz_one(CA_FMPQ_DENREF(x)); } flint-3.1.3/src/ca/set_ui.c000066400000000000000000000010451461254215100154410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_set_ui(ca_t x, ulong v, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpz_set_ui(CA_FMPQ_NUMREF(x), v); fmpz_one(CA_FMPQ_DENREF(x)); } flint-3.1.3/src/ca/sgn.c000066400000000000000000000025061461254215100147430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_sgn(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { ca_set(res, x, ctx); res->field &= ~CA_INF; } else if (CA_IS_UNKNOWN(x)) { ca_unknown(res, ctx); } else { ca_undefined(res, ctx); } return; } else if (CA_IS_QQ(x, ctx)) { ca_set_si(res, fmpz_sgn(fmpq_numref(CA_FMPQ(x))), ctx); } else { qqbar_t t; qqbar_init(t); if (ca_get_qqbar(t, x, ctx)) { qqbar_sgn(t, t); if (qqbar_within_limits(t, ctx->options[CA_OPT_QQBAR_DEG_LIMIT], 0)) ca_set_qqbar(res, t, ctx); else _ca_function_fx(res, CA_Sign, x, ctx); } else { _ca_function_fx(res, CA_Sign, x, ctx); } qqbar_clear(t); } } flint-3.1.3/src/ca/sin_cos.c000066400000000000000000000243111461254215100156070ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_vec.h" void ca_sin_cos_special(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) { truth_t t1, t2; if (ca_check_is_signed_inf(x, ctx) == T_TRUE) { t1 = ca_check_is_pos_i_inf(x, ctx); if (t1 == T_TRUE) { if (res1 != NULL) ca_pos_i_inf(res1, ctx); if (res2 != NULL) ca_pos_inf(res2, ctx); return; } t2 = ca_check_is_neg_i_inf(x, ctx); if (t2 == T_TRUE) { if (res1 != NULL) ca_neg_i_inf(res1, ctx); if (res2 != NULL) ca_pos_inf(res2, ctx); return; } if (t1 == T_FALSE && t2 == T_FALSE) { if (res1 != NULL) ca_undefined(res1, ctx); if (res2 != NULL) ca_undefined(res2, ctx); return; } } if (ca_check_is_undefined(x, ctx) == T_TRUE || ca_check_is_uinf(x, ctx) == T_TRUE) { if (res1 != NULL) ca_undefined(res1, ctx); if (res2 != NULL) ca_undefined(res2, ctx); return; } if (res1 != NULL) ca_unknown(res1, ctx); if (res2 != NULL) ca_unknown(res2, ctx); } void ca_sin_cos_exponential(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) { ca_t ix, y, t; if (CA_IS_SPECIAL(x)) { ca_sin_cos_special(res1, res2, x, ctx); return; } ca_init(ix, ctx); ca_init(y, ctx); ca_init(t, ctx); ca_i(ix, ctx); ca_mul(ix, x, ix, ctx); ca_exp(y, ix, ctx); ca_inv(t, y, ctx); if (res2 != NULL) { ca_add(res2, y, t, ctx); ca_div_ui(res2, res2, 2, ctx); } if (res1 != NULL) { ca_sub(res1, y, t, ctx); ca_div_ui(res1, res1, 2, ctx); ca_neg_i(t, ctx); ca_mul(res1, res1, t, ctx); } ca_clear(ix, ctx); ca_clear(y, ctx); ca_clear(t, ctx); } void ca_sin_cos_direct(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) { ca_t t, pi; fmpq_t v; if (CA_IS_SPECIAL(x)) { ca_sin_cos_special(res1, res2, x, ctx); return; } ca_init(t, ctx); ca_init(pi, ctx); fmpq_init(v); ca_pi(pi, ctx); ca_div(t, x, pi, ctx); if (ca_get_fmpq(v, t, ctx)) { /* For now, only convert trivial values */ if (fmpz_cmp_ui(fmpq_denref(v), 6) <= 0 && !fmpz_equal_ui(fmpq_denref(v), 5)) { slong p, q; qqbar_t a; q = fmpz_get_ui(fmpq_denref(v)); p = fmpz_fdiv_ui(fmpq_numref(v), 2 * q); qqbar_init(a); if (res1 != NULL) { qqbar_sin_pi(a, p, q); ca_set_qqbar(res1, a, ctx); } if (res2 != NULL) { qqbar_cos_pi(a, p, q); ca_set_qqbar(res2, a, ctx); } qqbar_clear(a); } else { ca_mul_fmpq(t, pi, v, ctx); if (fmpq_sgn(v) > 0) { if (res1 != NULL) _ca_function_fx(res1, CA_Sin, t, ctx); if (res2 != NULL) _ca_function_fx(res2, CA_Cos, t, ctx); } else { ca_neg(t, t, ctx); if (res1 != NULL) _ca_function_fx(res1, CA_Sin, t, ctx); if (res2 != NULL) _ca_function_fx(res2, CA_Cos, t, ctx); if (res1 != NULL) ca_neg(res1, res1, ctx); } } } else { if (res1 != NULL) _ca_function_fx(res1, CA_Sin, x, ctx); if (res2 != NULL) _ca_function_fx(res2, CA_Cos, x, ctx); } ca_clear(pi, ctx); ca_clear(t, ctx); fmpq_clear(v); } #if 0 void ca_sin_cos_direct_exp_hack(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) { ca_t i, ix, exp, sin, cos, t, u; ca_init(i, ctx); ca_init(ix, ctx); ca_init(exp, ctx); ca_init(sin, ctx); ca_init(cos, ctx); ca_init(t, ctx); ca_init(u, ctx); ca_i(i, ctx); ca_mul(ix, i, x, ctx); _ca_function_fx(sin, CA_Sin, x, ctx); _ca_function_fx(cos, CA_Cos, x, ctx); _ca_function_fx(exp, CA_Exp, ix, ctx); /* todo: create field in one step! */ ca_merge_fields(t, u, sin, exp, ctx); ca_swap(sin, t, ctx); ca_merge_fields(t, u, sin, i, ctx); ca_swap(sin, t, ctx); ca_merge_fields(t, u, sin, cos, ctx); ca_swap(sin, t, ctx); ca_swap(cos, u, ctx); if (res1 != NULL) ca_swap(res1, sin, ctx); if (res2 != NULL) ca_swap(res2, cos, ctx); ca_clear(i, ctx); ca_clear(ix, ctx); ca_clear(exp, ctx); ca_clear(sin, ctx); ca_clear(cos, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } #endif void ca_sin_cos_tangent(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) { ca_t t, u, v; if (CA_IS_SPECIAL(x)) { ca_sin_cos_special(res1, res2, x, ctx); return; } ca_init(t, ctx); ca_init(u, ctx); ca_init(v, ctx); ca_div_ui(t, x, 2, ctx); ca_tan_direct(t, t, ctx); if (CA_IS_SPECIAL(t)) { ca_sin_cos_direct(res1, res2, x, ctx); } else { ca_sqr(u, t, ctx); ca_add_ui(v, u, 1, ctx); ca_inv(v, v, ctx); if (res1 != NULL) { ca_mul(res1, t, v, ctx); ca_mul_ui(res1, res1, 2, ctx); } if (res2 != NULL) { ca_ui_sub(u, 1, u, ctx); ca_mul(res2, u, v, ctx); } } ca_clear(t, ctx); ca_clear(u, ctx); ca_clear(v, ctx); } void ca_sin_cos(ca_t res1, ca_t res2, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { ca_sin_cos_special(res1, res2, x, ctx); return; } if (CA_IS_QQ(x, ctx) && fmpq_is_zero(CA_FMPQ(x))) { if (res1 != NULL) ca_zero(res1, ctx); if (res2 != NULL) ca_one(res2, ctx); return; } if (ctx->options[CA_OPT_TRIG_FORM] == CA_TRIG_EXPONENTIAL) { ca_sin_cos_exponential(res1, res2, x, ctx); return; } if (ctx->options[CA_OPT_TRIG_FORM] == CA_TRIG_TANGENT) { ca_sin_cos_tangent(res1, res2, x, ctx); return; } ca_sin_cos_direct(res1, res2, x, ctx); } void ca_sin(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_sin_cos(res, NULL, x, ctx); } void ca_cos(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_sin_cos(NULL, res, x, ctx); } void ca_tan_special(ca_t res, const ca_t x, ca_ctx_t ctx) { if (ca_check_is_signed_inf(x, ctx) == T_TRUE) { ca_t s; ca_init(s, ctx); ca_sgn(s, x, ctx); ca_im(s, s, ctx); ca_sgn(s, s, ctx); if (ca_check_is_one(s, ctx) == T_TRUE) { ca_i(res, ctx); } else if (ca_check_is_neg_one(s, ctx) == T_TRUE) { ca_neg_i(res, ctx); } else if (ca_check_is_zero(s, ctx) == T_TRUE) { ca_undefined(res, ctx); } else { ca_unknown(res, ctx); } ca_clear(s, ctx); return; } if (ca_is_unknown(res, ctx)) ca_unknown(res, ctx); else ca_undefined(res, ctx); } void ca_tan_direct(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t, u; truth_t pole; if (CA_IS_SPECIAL(x)) { ca_tan_special(res, x, ctx); return; } ca_init(t, ctx); ca_init(u, ctx); ca_pi(t, ctx); ca_div(t, x, t, ctx); if (ca_check_is_integer(t, ctx) == T_TRUE) { ca_zero(res, ctx); } else { ca_set_d(u, 0.5, ctx); ca_add(u, u, t, ctx); pole = ca_check_is_integer(u, ctx); if (pole == T_TRUE) { ca_uinf(res, ctx); } else if (pole == T_UNKNOWN) { ca_unknown(res, ctx); } else { fmpq_t v; fmpq_init(v); /* For now, only convert trivial values */ if (ca_get_fmpq(v, t, ctx) && (fmpz_equal_ui(fmpq_denref(v), 3) || fmpz_equal_ui(fmpq_denref(v), 4) || fmpz_equal_ui(fmpq_denref(v), 6) || fmpz_equal_ui(fmpq_denref(v), 8) || fmpz_equal_ui(fmpq_denref(v), 12))) { slong p, q; qqbar_t a; q = fmpz_get_ui(fmpq_denref(v)); p = fmpz_fdiv_ui(fmpq_numref(v), q); qqbar_init(a); qqbar_tan_pi(a, p, q); ca_set_qqbar(res, a, ctx); qqbar_clear(a); } else { /* todo: sign symmetry, ... */ _ca_function_fx(res, CA_Tan, x, ctx); } fmpq_clear(v); } } ca_clear(t, ctx); ca_clear(u, ctx); } void ca_tan_exponential(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { ca_tan_special(res, x, ctx); } else { ca_t s, c; ca_init(s, ctx); ca_init(c, ctx); ca_sin_cos_exponential(s, c, x, ctx); ca_div(res, s, c, ctx); ca_clear(s, ctx); ca_clear(c, ctx); return; } } void ca_tan_sine_cosine(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { ca_tan_special(res, x, ctx); } else { ca_t s, c; ca_init(s, ctx); ca_init(c, ctx); ca_sin_cos_direct(s, c, x, ctx); ca_div(res, s, c, ctx); ca_clear(s, ctx); ca_clear(c, ctx); return; } } void ca_tan(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { ca_tan_special(res, x, ctx); } else if (ctx->options[CA_OPT_TRIG_FORM] == CA_TRIG_EXPONENTIAL) { ca_tan_exponential(res, x, ctx); } else if (ctx->options[CA_OPT_TRIG_FORM] == CA_TRIG_SINE_COSINE) { ca_tan_sine_cosine(res, x, ctx); } else { ca_tan_direct(res, x, ctx); } } void ca_cot(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_tan(res, x, ctx); ca_inv(res, res, ctx); } flint-3.1.3/src/ca/sqrt.c000066400000000000000000000045721461254215100151520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_sqrt_inert(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { /* todo: could compute inert sign + sqrt for signed inf */ ca_sqrt(res, x, ctx); } else { _ca_function_fx(res, CA_Sqrt, x, ctx); } } void _ca_sqrt_nofactor(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t y, tmp; ca_init(y, ctx); ca_init(tmp, ctx); _ca_function_fx(y, CA_Sqrt, x, ctx); ca_merge_fields(tmp, res, x, y, ctx); ca_clear(y, ctx); ca_clear(tmp, ctx); } void ca_sqrt_nofactor(ca_t res, const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { ca_sgn(res, x, ctx); ca_sqrt(res, res, ctx); if (!ca_is_unknown(res, ctx)) res->field |= CA_INF; } else { ca_set(res, x, ctx); } } else { qqbar_t t; slong deg; qqbar_init(t); if (ca_get_qqbar(t, x, ctx)) { deg = qqbar_degree(t); qqbar_sqrt(t, t); /* use? qqbar_within_limits(t, ctx->options[CA_OPT_QQBAR_DEG_LIMIT], 0) */ if (qqbar_degree(t) <= FLINT_MAX(2, deg)) ca_set_qqbar(res, t, ctx); else _ca_sqrt_nofactor(res, x, ctx); } else { if (ca_check_is_negative_real(x, ctx) == T_TRUE) { ca_t i; ca_init(i, ctx); ca_i(i, ctx); ca_neg(res, x, ctx); _ca_sqrt_nofactor(res, res, ctx); ca_mul(res, res, i, ctx); ca_clear(i, ctx); } else { _ca_sqrt_nofactor(res, x, ctx); } } qqbar_clear(t); } } void ca_sqrt(ca_t res, const ca_t x, ca_ctx_t ctx) { #if 0 ca_sqrt_nofactor(res, x, ctx); #else ca_sqrt_factor(res, x, CA_FACTOR_POLY_SQF | CA_FACTOR_ZZ_SMOOTH, ctx); #endif } flint-3.1.3/src/ca/sqrt_factor.c000066400000000000000000000125341461254215100165050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_sqrt_factor(ca_t res, const ca_t x, ulong flags, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) { if (CA_IS_SIGNED_INF(x)) { ca_sgn(res, x, ctx); ca_sqrt_factor(res, res, flags, ctx); if (!ca_is_unknown(res, ctx)) res->field |= CA_INF; } else { ca_set(res, x, ctx); } } else { slong i; ca_factor_t fac; ca_t A, B, t; if (CA_IS_QQ(x, ctx)) { qqbar_t t; qqbar_init(t); qqbar_fmpq_root_ui(t, CA_FMPQ(x), 2); ca_set_qqbar(res, t, ctx); qqbar_clear(t); return; } ca_factor_init(fac, ctx); ca_init(A, ctx); ca_init(B, ctx); ca_init(t, ctx); ca_factor(fac, x, flags, ctx); ca_one(A, ctx); ca_one(B, ctx); for (i = 0; i < fac->length; i++) { if (CA_IS_QQ(fac->exp + i, ctx) && fmpz_is_one(CA_FMPQ_DENREF(fac->exp + i))) { if (!fmpz_is_zero(CA_FMPQ_DENREF(fac->exp + i))) { fmpz_t e; ca_ext_ptr ext; ext = ca_is_gen_as_ext(fac->base + i, ctx); if (ext != NULL && CA_EXT_HEAD(ext) == CA_Exp) { /* sqrt(exp(a)^n) = +/- exp(a*n/2) */ ca_mul_fmpz(t, CA_EXT_FUNC_ARGS(ext), CA_FMPQ_NUMREF(fac->exp + i), ctx); ca_div_ui(t, t, 2, ctx); ca_exp(t, t, ctx); ca_mul(A, A, t, ctx); continue; } /* todo: assert a != 0? */ if (ext != NULL && CA_EXT_HEAD(ext) == CA_Sqrt) { /* sqrt(sqrt(a)^n) = +/- a^(n/4) */ ca_set_fmpz(t, CA_FMPQ_NUMREF(fac->exp + i), ctx); ca_div_ui(t, t, 4, ctx); ca_pow(t, CA_EXT_FUNC_ARGS(ext), t, ctx); ca_mul(A, A, t, ctx); continue; } /* todo: assert a != 0? */ if (ext != NULL && CA_EXT_HEAD(ext) == CA_Pow) { /* sqrt((a^b)^n) = +/- a^(n*b/2) */ ca_mul_fmpz(t, CA_EXT_FUNC_ARGS(ext) + 1, CA_FMPQ_NUMREF(fac->exp + i), ctx); ca_div_ui(t, t, 2, ctx); ca_pow(t, CA_EXT_FUNC_ARGS(ext), t, ctx); ca_mul(A, A, t, ctx); continue; } fmpz_init(e); if (fmpz_is_odd(CA_FMPQ_NUMREF(fac->exp + i))) ca_mul(B, B, fac->base + i, ctx); fmpz_fdiv_q_2exp(e, CA_FMPQ_NUMREF(fac->exp + i), 1); ca_pow_fmpz(t, fac->base + i, e, ctx); ca_mul(A, A, t, ctx); fmpz_clear(e); } } else { ca_pow(t, fac->base + i, fac->exp + i, ctx); ca_mul(B, B, t, ctx); } } /* printf("factors:\n"); ca_factor_print(fac, ctx); printf("\n"); ca_print(A, ctx); printf("\n"); ca_print(B, ctx); printf("\n"); */ ca_sqrt_nofactor(B, B, ctx); ca_mul(A, A, B, ctx); /* check sign (todo: much improvable) */ { acb_t sA, sA2, sB; int success; slong prec, prec_limit, low_prec; low_prec = ctx->options[CA_OPT_LOW_PREC]; prec_limit = ctx->options[CA_OPT_PREC_LIMIT]; prec_limit = FLINT_MAX(prec_limit, low_prec); ca_sqrt_inert(B, x, ctx); acb_init(sA); acb_init(sA2); acb_init(sB); success = 0; for (prec = low_prec; prec <= prec_limit; prec *= 2) { ca_get_acb_raw(sA, A, prec, ctx); ca_get_acb_raw(sB, B, prec, ctx); acb_neg(sA2, sA); if (acb_overlaps(sA, sB) && !acb_overlaps(sA2, sB)) { ca_set(res, A, ctx); success = 1; break; } if (acb_overlaps(sA2, sB) && !acb_overlaps(sA, sB)) { ca_neg(res, A, ctx); success = 1; break; } } if (!success) { if (ca_check_is_zero(A, ctx) == T_TRUE) ca_zero(res, ctx); else ca_set(res, B, ctx); } acb_clear(sA); acb_clear(sA2); acb_clear(sB); } ca_factor_clear(fac, ctx); ca_clear(A, ctx); ca_clear(B, ctx); ca_clear(t, ctx); } } flint-3.1.3/src/ca/swap.c000066400000000000000000000007421461254215100151260ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_swap(ca_t x, ca_t y, ca_ctx_t ctx) { FLINT_SWAP(ca_struct, *x, *y); } flint-3.1.3/src/ca/test/000077500000000000000000000000001461254215100147645ustar00rootroot00000000000000flint-3.1.3/src/ca/test/main.c000066400000000000000000000043411461254215100160560ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-acos.c" #include "t-add.c" #include "t-asin.c" #include "t-atan.c" #include "t-conj.c" #include "t-ctx_init_clear.c" #include "t-div.c" #include "t-erf.c" #include "t-exp.c" #include "t-field_init_clear.c" #include "t-fmpz_mpoly_evaluate.c" #include "t-gamma.c" #include "t-get_fexpr.c" #include "t-get_str.c" #include "t-init_clear.c" #include "t-log.c" #include "t-log_identities.c" #include "t-mul.c" #include "t-neg.c" #include "t-pow.c" #include "t-pow_si_arithmetic.c" #include "t-properties.c" #include "t-re_im.c" #include "t-sin_cos.c" #include "t-sqrt.c" #include "t-sqrt_factor.c" #include "t-sub.c" #include "t-tan.c" #include "t-transfer.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(ca_acos), TEST_FUNCTION(ca_add), TEST_FUNCTION(ca_asin), TEST_FUNCTION(ca_atan), TEST_FUNCTION(ca_conj), TEST_FUNCTION(ca_ctx_init_clear), TEST_FUNCTION(ca_div), TEST_FUNCTION(ca_erf), TEST_FUNCTION(ca_exp), TEST_FUNCTION(ca_field_init_clear), TEST_FUNCTION(ca_fmpz_mpoly_evaluate), TEST_FUNCTION(ca_gamma), TEST_FUNCTION(ca_get_fexpr), TEST_FUNCTION(ca_get_str), TEST_FUNCTION(ca_init_clear), TEST_FUNCTION(ca_log), TEST_FUNCTION(ca_log_identities), TEST_FUNCTION(ca_mul), TEST_FUNCTION(ca_neg), TEST_FUNCTION(ca_pow), TEST_FUNCTION(ca_pow_si_arithmetic), TEST_FUNCTION(ca_properties), TEST_FUNCTION(ca_re_im), TEST_FUNCTION(ca_sin_cos), TEST_FUNCTION(ca_sqrt), TEST_FUNCTION(ca_sqrt_factor), TEST_FUNCTION(ca_sub), TEST_FUNCTION(ca_tan), TEST_FUNCTION(ca_transfer) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/ca/test/t-acos.c000066400000000000000000000044371461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_acos, state) { slong iter; { ca_ctx_t ctx; ca_ctx_init(ctx); for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { ca_t x, t1, t2, t3; if (n_randint(state, 10) == 0) { ca_ctx_clear(ctx); ca_ctx_init(ctx); } ca_init(x, ctx); ca_init(t1, ctx); ca_init(t2, ctx); ca_init(t3, ctx); ca_randtest_special(x, state, 5, 5, ctx); ca_acos_direct(t1, x, ctx); ca_acos_logarithm(t2, x, ctx); if (ca_check_equal(t1, t2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("t1 = "); ca_print(t1, ctx); flint_printf("\n\n"); flint_printf("t2 = "); ca_print(t2, ctx); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) ca_cos(t3, t2, ctx); else ca_cos(t3, t1, ctx); if (ca_check_is_infinity(t3, ctx) != T_TRUE && ca_check_is_undefined(t3, ctx) != T_TRUE) { if (ca_check_equal(t3, x, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("t2 = "); ca_print(t2, ctx); flint_printf("\n\n"); flint_printf("t3 = "); ca_print(t3, ctx); flint_printf("\n\n"); flint_abort(); } } ca_clear(x, ctx); ca_clear(t1, ctx); ca_clear(t2, ctx); ca_clear(t3, ctx); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-add.c000066400000000000000000000061321461254215100161230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_add, state) { slong iter; /* check special values */ { ca_ctx_t ctx; ca_t x, y, z; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_set_si(x, 2, ctx); ca_uinf(y, ctx); ca_add(z, x, y, ctx); if (ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: 2 + uinf\n"); flint_abort(); } ca_pos_inf(x, ctx); ca_uinf(y, ctx); ca_add(z, x, y, ctx); if (ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: +inf + uinf\n"); flint_abort(); } ca_neg_inf(x, ctx); ca_neg_inf(y, ctx); ca_add(z, x, y, ctx); if (ca_check_is_neg_inf(z, ctx) != T_TRUE) { flint_printf("FAIL: -inf + (-inf)\n"); flint_abort(); } ca_pos_inf(x, ctx); ca_neg_inf(y, ctx); ca_add(z, x, y, ctx); if (ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: +inf + (-inf)\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); /* test (x + y) + z = x + (y + z) */ ca_randtest_special(x, state, 5, 5, ctx); ca_randtest_special(y, state, 5, 5, ctx); ca_randtest_special(z, state, 5, 5, ctx); ca_randtest_special(a, state, 5, 5, ctx); ca_randtest_special(b, state, 5, 5, ctx); ca_add(a, x, y, ctx); ca_add(a, a, z, ctx); ca_add(b, y, z, ctx); ca_add(b, x, b, ctx); equal = ca_check_equal(a, b, ctx); if (equal == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-asin.c000066400000000000000000000044371461254215100163330ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_asin, state) { slong iter; { ca_ctx_t ctx; ca_ctx_init(ctx); for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { ca_t x, t1, t2, t3; if (n_randint(state, 10) == 0) { ca_ctx_clear(ctx); ca_ctx_init(ctx); } ca_init(x, ctx); ca_init(t1, ctx); ca_init(t2, ctx); ca_init(t3, ctx); ca_randtest_special(x, state, 5, 5, ctx); ca_asin_direct(t1, x, ctx); ca_asin_logarithm(t2, x, ctx); if (ca_check_equal(t1, t2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("t1 = "); ca_print(t1, ctx); flint_printf("\n\n"); flint_printf("t2 = "); ca_print(t2, ctx); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) ca_sin(t3, t2, ctx); else ca_sin(t3, t1, ctx); if (ca_check_is_infinity(t3, ctx) != T_TRUE && ca_check_is_undefined(t3, ctx) != T_TRUE) { if (ca_check_equal(t3, x, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("t2 = "); ca_print(t2, ctx); flint_printf("\n\n"); flint_printf("t3 = "); ca_print(t3, ctx); flint_printf("\n\n"); flint_abort(); } } ca_clear(x, ctx); ca_clear(t1, ctx); ca_clear(t2, ctx); ca_clear(t3, ctx); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-atan.c000066400000000000000000000044331461254215100163200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_atan, state) { slong iter; { ca_ctx_t ctx; ca_ctx_init(ctx); for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { ca_t x, t1, t2, t3; if (n_randint(state, 10) == 0) { ca_ctx_clear(ctx); ca_ctx_init(ctx); } ca_init(x, ctx); ca_init(t1, ctx); ca_init(t2, ctx); ca_init(t3, ctx); ca_randtest_special(x, state, 5, 5, ctx); ca_atan_direct(t1, x, ctx); ca_atan_logarithm(t2, x, ctx); if (ca_check_equal(t1, t2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("t1 = "); ca_print(t1, ctx); flint_printf("\n\n"); flint_printf("t2 = "); ca_print(t2, ctx); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) ca_tan(t3, t2, ctx); else ca_tan(t3, t1, ctx); if (ca_check_is_uinf(t3, ctx) != T_TRUE && ca_check_is_undefined(t3, ctx) != T_TRUE) { if (ca_check_equal(t3, x, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("t2 = "); ca_print(t2, ctx); flint_printf("\n\n"); flint_printf("t3 = "); ca_print(t3, ctx); flint_printf("\n\n"); flint_abort(); } } ca_clear(x, ctx); ca_clear(t1, ctx); ca_clear(t2, ctx); ca_clear(t3, ctx); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-conj.c000066400000000000000000000033021461254215100163200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_conj, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_randtest_special(x, state, 5, 5, ctx); switch (n_randint(state, 3)) { case 0: ca_conj(y, x, ctx); break; case 1: ca_conj_deep(y, x, ctx); break; case 2: ca_conj_shallow(y, x, ctx); break; } switch (n_randint(state, 3)) { case 0: ca_conj(z, y, ctx); break; case 1: ca_conj_deep(z, y, ctx); break; case 2: ca_conj_shallow(z, y, ctx); break; } equal = ca_check_equal(x, z, ctx); if (equal == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-ctx_init_clear.c000066400000000000000000000010731461254215100203610ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_ctx_init_clear, state) { ca_ctx_t ctx; ca_ctx_init(ctx); ca_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-div.c000066400000000000000000000131101461254215100161470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_div, state) { slong iter; /* check special values */ { ca_ctx_t ctx; ca_t x, y, z; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_set_si(x, 2, ctx); ca_uinf(y, ctx); ca_div(z, x, y, ctx); if (ca_check_is_zero(z, ctx) != T_TRUE) { flint_printf("FAIL: 2 / uinf\n"); flint_abort(); } ca_div(z, y, x, ctx); if (ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: uinf / 2\n"); flint_abort(); } ca_zero(x, ctx); ca_uinf(y, ctx); ca_div(z, x, y, ctx); if (ca_check_is_zero(z, ctx) != T_TRUE) { flint_printf("FAIL: 0 / uinf\n"); flint_abort(); } ca_div(z, y, x, ctx); if (ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: uinf / 0\n"); flint_abort(); } ca_zero(x, ctx); ca_pos_inf(y, ctx); ca_div(z, x, y, ctx); if (ca_check_is_zero(z, ctx) != T_TRUE) { flint_printf("FAIL: 0 / +inf\n"); flint_abort(); } ca_div(z, y, x, ctx); if (ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: +inf / 0\n"); flint_abort(); } ca_set_si(x, -2, ctx); ca_pos_inf(y, ctx); ca_div(z, x, y, ctx); if (ca_check_is_zero(z, ctx) != T_TRUE) { flint_printf("FAIL: -2 / +inf\n"); flint_abort(); } ca_div(z, y, x, ctx); if (ca_check_is_neg_inf(z, ctx) != T_TRUE) { flint_printf("FAIL: +inf / -2\n"); flint_abort(); } ca_pos_inf(x, ctx); ca_uinf(y, ctx); ca_div(z, x, y, ctx); if (ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: +inf / uinf\n"); flint_abort(); } ca_div(z, y, x, ctx); if (ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: uinf / +uinf\n"); flint_abort(); } ca_one(x, ctx); ca_zero(y, ctx); ca_div(z, x, y, ctx); if (ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: 1 / 0\n"); flint_abort(); } ca_zero(x, ctx); ca_zero(y, ctx); ca_div(z, x, y, ctx); if (ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: 0 / 0\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b, c; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); ca_init(c, ctx); /* test (x / y) / z = x / (y * z) */ ca_randtest_special(x, state, 5, 5, ctx); ca_randtest_special(y, state, 5, 5, ctx); ca_randtest_special(z, state, 5, 5, ctx); ca_randtest_special(a, state, 5, 5, ctx); ca_randtest_special(b, state, 5, 5, ctx); ca_div(a, x, y, ctx); ca_div(a, a, z, ctx); ca_mul(b, y, z, ctx); ca_div(b, x, b, ctx); equal = ca_check_equal(a, b, ctx); if (equal == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_abort(); } /* test (y + z) / x = y / x + z / x */ ca_add(a, y, z, ctx); ca_div(a, a, x, ctx); ca_div(b, y, x, ctx); ca_div(c, z, x, ctx); ca_add(b, b, c, ctx); equal = ca_check_equal(a, b, ctx); if (equal == T_FALSE) { if (!(ca_check_is_zero(x, ctx) == T_TRUE || ca_check_is_infinity(y, ctx) == T_TRUE || ca_check_is_infinity(z, ctx) == T_TRUE)) { flint_printf("FAIL (distributivity)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_abort(); } } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_clear(c, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-erf.c000066400000000000000000000124711461254215100161520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" void ca_randtest_zero(ca_t x, flint_rand_t state, ca_ctx_t ctx) { if (n_randint(state, 2)) { ca_zero(x, ctx); } else { ca_t t; ca_init(t, ctx); ca_sqrt_ui(x, 6, ctx); ca_mul_ui(x, x, 2, ctx); ca_add_ui(x, x, 5, ctx); ca_sqrt(x, x, ctx); ca_sqrt_ui(t, 2, ctx); ca_sub(x, x, t, ctx); ca_sqrt_ui(t, 3, ctx); ca_sub(x, x, t, ctx); ca_clear(t, ctx); } } TEST_FUNCTION_START(ca_erf, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, v, s; acb_t ax, ay, as, as2; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(v, ctx); ca_init(s, ctx); acb_init(ax); acb_init(ay); acb_init(as); acb_init(as2); ca_randtest(x, state, 3, 5, ctx); ca_randtest_zero(v, state, ctx); ca_add(y, x, v, ctx); switch (n_randint(state, 4)) { case 0: ca_neg(y, y, ctx); break; case 1: ca_i(s, ctx); ca_mul(y, y, s, ctx); break; case 2: ca_neg_i(s, ctx); ca_mul(y, y, s, ctx); break; } switch (n_randint(state, 3)) { case 0: ca_erf(x, x, ctx); break; case 1: ca_erfc(x, x, ctx); break; default: ca_erfi(x, x, ctx); break; } switch (n_randint(state, 3)) { case 0: ca_erf(y, y, ctx); break; case 1: ca_erfc(y, y, ctx); break; default: ca_erfi(y, y, ctx); break; } if (n_randint(state, 2)) ca_sqr(x, x, ctx); switch (n_randint(state, 4)) { case 0: ca_neg(x, x, ctx); break; case 1: ca_i(s, ctx); ca_mul(x, x, s, ctx); break; case 2: ca_neg_i(s, ctx); ca_mul(x, x, s, ctx); break; } if (n_randint(state, 2)) ca_sqr(y, y, ctx); switch (n_randint(state, 4)) { case 0: ca_neg(y, y, ctx); break; case 1: ca_i(s, ctx); ca_mul(y, y, s, ctx); break; case 2: ca_neg_i(s, ctx); ca_mul(y, y, s, ctx); break; } ca_add(s, x, y, ctx); ca_get_acb(ax, x, 53, ctx); ca_get_acb(ay, y, 53, ctx); ca_get_acb(as, s, 53, ctx); acb_add(as2, ax, ay, 53); if (!acb_overlaps(as, as2)) { flint_printf("FAIL\n"); flint_printf("x = "); ca_print(x, ctx); printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); printf("\n\n"); flint_printf("s = "); ca_print(s, ctx); printf("\n\n"); flint_abort(); } acb_clear(ax); acb_clear(ay); acb_clear(as); acb_clear(as2); ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(v, ctx); ca_clear(s, ctx); ca_ctx_clear(ctx); } { ca_ctx_t ctx; ca_t x, y; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); /* Erf(2*Log(Sqrt(1/2-Sqrt(2)/4))+Log(4)) - Erf(Log(2-Sqrt(2))) */ ca_sqrt_ui(x, 2, ctx); ca_div_ui(x, x, 4, ctx); ca_one(y, ctx); ca_div_ui(y, y, 2, ctx); ca_sub(x, y, x, ctx); ca_sqrt(x, x, ctx); ca_log(x, x, ctx); ca_mul_ui(x, x, 2, ctx); ca_set_ui(y, 4, ctx); ca_log(y, y, ctx); ca_add(x, y, x, ctx); ca_erf(x, x, ctx); ca_sqrt_ui(y, 2, ctx); ca_ui_sub(y, 2, y, ctx); ca_log(y, y, ctx); ca_erf(y, y, ctx); ca_sub(x, x, y, ctx); if (ca_check_is_zero(x, ctx) != T_TRUE) { flint_printf("FAIL (example 1)\n"); flint_printf("x = "); ca_print(x, ctx); printf("\n\n"); flint_abort(); } /* Erf(Sqrt(2))^2 + Erfi(Sqrt(-2))^2 */ ca_sqrt_ui(x, 2, ctx); ca_erf(x, x, ctx); ca_pow_ui(x, x, 2, ctx); ca_set_si(y, -2, ctx); ca_sqrt(y, y, ctx); ca_erfi(y, y, ctx); ca_pow_ui(y, y, 2, ctx); ca_add(x, x, y, ctx); if (ca_check_is_zero(x, ctx) != T_TRUE) { flint_printf("FAIL (example 2)\n"); flint_printf("x = "); ca_print(x, ctx); printf("\n\n"); flint_abort(); } /* Erf(Sqrt(2))^4 - Erfi(Sqrt(-2))^4 */ ca_sqrt_ui(x, 2, ctx); ca_erf(x, x, ctx); ca_pow_ui(x, x, 4, ctx); ca_set_si(y, -2, ctx); ca_sqrt(y, y, ctx); ca_erfi(y, y, ctx); ca_pow_ui(y, y, 4, ctx); ca_sub(x, x, y, ctx); if (ca_check_is_zero(x, ctx) != T_TRUE) { flint_printf("FAIL (example 3)\n"); flint_printf("x = "); ca_print(x, ctx); printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-exp.c000066400000000000000000000053471461254215100161760ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_exp, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b, c, d, e; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); ca_init(c, ctx); ca_init(d, ctx); ca_init(e, ctx); /* exp(x+y+z) = exp(x)*exp(y)*exp(z) */ ca_randtest(x, state, 5, 5, ctx); ca_randtest(y, state, 5, 5, ctx); ca_randtest(z, state, 5, 5, ctx); if (n_randint(state, 4) == 0) { if (n_randint(state, 2)) { do { ca_randtest(a, state, 5, 5, ctx); ca_log(a, a, ctx); } while (ca_check_is_number(a, ctx) != T_TRUE); ca_mul(x, x, a, ctx); } else { ca_pi_i(a, ctx); ca_mul(x, x, a, ctx); } } ca_exp(a, x, ctx); ca_exp(b, y, ctx); ca_exp(c, z, ctx); ca_add(d, x, y, ctx); ca_add(d, d, z, ctx); ca_exp(d, d, ctx); ca_mul(e, a, b, ctx); ca_mul(e, e, c, ctx); equal = ca_check_equal(d, e, ctx); if (equal == T_FALSE) { flint_printf("FAIL exp(x+y+z) = exp(x)*exp(y)*exp(z)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_printf("c = "); ca_print(c, ctx); flint_printf("\n\n"); flint_printf("d = "); ca_print(d, ctx); flint_printf("\n\n"); flint_printf("e = "); ca_print(e, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_clear(c, ctx); ca_clear(d, ctx); ca_clear(e, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-field_init_clear.c000066400000000000000000000022041461254215100206430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" #include "ca_ext.h" #include "ca_field.h" TEST_FUNCTION_START(ca_field_init_clear, state) { { ca_ctx_t ctx; ca_field_t K; ca_field_t I, Pi; qqbar_t t; qqbar_init(t); qqbar_i(t); ca_ctx_init(ctx); ca_field_init_nf(I, t, ctx); ca_field_init_const(Pi, CA_Pi, ctx); ca_field_init_multi(K, 2, ctx); /* ca_field_set_ext(K, 0, I); ca_field_set_ext(K, 1, Pi); flint_printf("\n"); ca_field_print(K); flint_printf("\n"); */ ca_field_clear(I, ctx); ca_field_clear(Pi, ctx); ca_field_clear(K, ctx); ca_ctx_clear(ctx); qqbar_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-fmpz_mpoly_evaluate.c000066400000000000000000000055061461254215100214610ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" #include "ca_vec.h" TEST_FUNCTION_START(ca_fmpz_mpoly_evaluate, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t cactx; slong i, n; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; ca_ptr x; ca_t fx, gx, hx, y; ca_ctx_init(cactx); n = 1 + n_randint(state, 5); fmpz_mpoly_ctx_init(ctx, n, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); x = _ca_vec_init(n, cactx); ca_init(fx, cactx); ca_init(gx, cactx); ca_init(hx, cactx); ca_init(y, cactx); for (i = 0; i < n; i++) ca_randtest(x + i, state, 5, 5, cactx); fmpz_mpoly_randtest_bound(f, state, 1 + n_randint(state, 30), 10, 1 + n_randint(state, 4), ctx); fmpz_mpoly_randtest_bound(g, state, 1 + n_randint(state, 30), 10, 1 + n_randint(state, 4), ctx); fmpz_mpoly_add(h, f, g, ctx); ca_fmpz_mpoly_evaluate(fx, f, x, ctx, cactx); ca_fmpz_mpoly_evaluate(gx, g, x, ctx, cactx); ca_fmpz_mpoly_evaluate(hx, h, x, ctx, cactx); ca_add(y, fx, gx, cactx); if (ca_check_equal(y, hx, cactx) == T_FALSE) { flint_printf("FAIL!\n"); flint_printf("f = "); fmpz_mpoly_print_pretty(f, NULL, ctx); flint_printf("\n\n"); flint_printf("g = "); fmpz_mpoly_print_pretty(g, NULL, ctx); flint_printf("\n\n"); flint_printf("h = "); fmpz_mpoly_print_pretty(h, NULL, ctx); flint_printf("\n\n"); for (i = 0; i < n; i++) { flint_printf("x%wd = ", i + 1); ca_print(x + i, cactx); flint_printf("\n\n"); } flint_printf("fx = "); ca_print(fx, cactx); flint_printf("\n\n"); flint_printf("gx = "); ca_print(gx, cactx); flint_printf("\n\n"); flint_printf("hx = "); ca_print(hx, cactx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, cactx); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); _ca_vec_clear(x, n, cactx); ca_clear(fx, cactx); ca_clear(gx, cactx); ca_clear(hx, cactx); ca_clear(y, cactx); ca_ctx_clear(cactx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-gamma.c000066400000000000000000000047121461254215100164570ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_gamma, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, gx, gy, gxgy; acb_t gax, gay, agx, agy, agxgy, gaxgay; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(gx, ctx); ca_init(gy, ctx); ca_init(gxgy, ctx); acb_init(gax); acb_init(gay); acb_init(agx); acb_init(agy); acb_init(agxgy); acb_init(gaxgay); ca_randtest(x, state, 3, 5, ctx); if (n_randint(state, 2)) ca_randtest(y, state, 3, 5, ctx); else ca_randtest_rational(y, state, 5, ctx); if (n_randint(state, 2)) ca_add(y, y, x, ctx); ca_gamma(gx, x, ctx); ca_gamma(gy, y, ctx); ca_add(gxgy, gx, gy, ctx); ca_get_acb(agx, gx, 53, ctx); ca_get_acb(agy, gy, 53, ctx); ca_get_acb(agxgy, gxgy, 53, ctx); ca_get_acb(gax, x, 53, ctx); acb_gamma(gax, gax, 53); ca_get_acb(gay, y, 53, ctx); acb_gamma(gay, gay, 53); acb_add(gaxgay, gax, gay, 53); if (!acb_overlaps(agx, gax) || !acb_overlaps(agy, gay) || !acb_overlaps(agxgy, gaxgay)) { flint_printf("FAIL\n"); flint_printf("x = "); ca_print(x, ctx); printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); printf("\n\n"); flint_printf("gx = "); ca_print(gx, ctx); printf("\n\n"); flint_printf("gy = "); ca_print(gy, ctx); printf("\n\n"); flint_printf("gxgy = "); ca_print(gxgy, ctx); printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(gx, ctx); ca_clear(gy, ctx); ca_clear(gxgy, ctx); acb_clear(gax); acb_clear(gay); acb_clear(agx); acb_clear(agy); acb_clear(agxgy); acb_clear(gaxgay); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-get_fexpr.c000066400000000000000000000052201461254215100173530ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_get_fexpr, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y; fexpr_t f; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); fexpr_init(f); ca_randtest_special(x, state, 5, 5, ctx); ca_get_fexpr(f, x, 0, ctx); if (!ca_set_fexpr(y, f, ctx)) { flint_printf("FAIL: unable to parse\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("f = "); fexpr_print(f); flint_printf("\n\n"); flint_abort(); } if (ca_check_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL: not equal!\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("f = "); fexpr_print(f); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_abort(); } if (ca_check_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL: not equal!\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("f = "); fexpr_print(f); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_abort(); } if (ca_check_equal(x, y, ctx) != T_TRUE && !ca_is_unknown(x, ctx)) { flint_printf("FAIL: not equal!\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("f = "); fexpr_print(f); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_abort(); } /* if (!ca_equal_repr(x, y, ctx)) { flint_printf("Warning: not equal repr!\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("f = "); fexpr_print(f); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); } */ fexpr_clear(f); ca_clear(x, ctx); ca_clear(y, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-get_str.c000066400000000000000000000017551461254215100170500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ca.h" TEST_FUNCTION_START(ca_get_str, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x; char * s; slong slen; ca_ctx_init(ctx); ca_init(x, ctx); /* just check that it doesn't crash */ ca_randtest_special(x, state, 10, 100, ctx); s = ca_get_str(x, ctx); slen = strlen(s); (void)slen; flint_free(s); ca_clear(x, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-init_clear.c000066400000000000000000000014451461254215100175060ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_init_clear, state) { { ca_ctx_t ctx; ca_t x; ca_ctx_init(ctx); ca_init(x, ctx); if (!fmpz_is_zero(CA_FMPQ_NUMREF(x))) flint_abort(); if (!fmpz_is_one(CA_FMPQ_DENREF(x))) flint_abort(); ca_clear(x, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-log.c000066400000000000000000000112201461254215100161460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_log, state) { slong iter; /* check numerical evaluation */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y; acb_t ax, ay, logax; slong prec; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); acb_init(ax); acb_init(ay); acb_init(logax); prec = 10 + n_randint(state, 100); ca_randtest(x, state, 5, 5, ctx); ca_randtest(y, state, 5, 5, ctx); if (n_randint(state, 2)) ca_exp(x, x, ctx); if (n_randint(state, 2)) ca_pow(x, x, y, ctx); ca_log(y, x, ctx); ca_get_acb(ax, x, prec, ctx); ca_get_acb(ay, y, prec, ctx); acb_log(logax, ax, prec); if (!acb_overlaps(logax, ay)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("ax = "); acb_printn(ax, 30, ARB_STR_NO_RADIUS); flint_printf("\n\n"); flint_printf("ay = "); acb_printn(ay, 30, ARB_STR_NO_RADIUS); flint_printf("\n\n"); flint_printf("logax = "); acb_printn(logax, 30, ARB_STR_NO_RADIUS); flint_printf("\n\n"); flint_abort(); } acb_clear(ax); acb_clear(ay); acb_clear(logax); ca_clear(x, ctx); ca_clear(y, ctx); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b, c, d, e, f; truth_t equal, zero; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); ca_init(c, ctx); ca_init(d, ctx); ca_init(e, ctx); ca_init(f, ctx); /* log(x * y * z) - log(x) - log(y) - log(z) */ /* testing for positive x and y here -- need better test code for complex numbers */ ca_randtest(x, state, 5, 5, ctx); ca_randtest(y, state, 5, 5, ctx); ca_randtest(z, state, 5, 5, ctx); ca_abs(x, x, ctx); ca_abs(y, y, ctx); /* Test a bug */ if (iter == 0) { ca_sqrt_ui(x, 2, ctx); ca_div_ui(x, x, 3, ctx); ca_sqrt(x, x, ctx); ca_set_ui(y, 1, ctx); ca_div_ui(y, y, 2, ctx); ca_one(z, ctx); } /* a = log(x*y*z) */ ca_mul(a, x, y, ctx); ca_mul(a, a, z, ctx); ca_log(a, a, ctx); /* b = log(x), c = log(y), d = log(z) */ ca_log(b, x, ctx); ca_log(c, y, ctx); ca_log(d, z, ctx); /* e = log(x) + log(y) + log(c) */ ca_add(e, b, c, ctx); ca_add(e, e, d, ctx); ca_sub(f, a, e, ctx); equal = ca_check_equal(a, e, ctx); if (ca_check_is_infinity(a, ctx) == T_FALSE) { zero = ca_check_is_zero(f, ctx); } else { zero = T_UNKNOWN; } if (equal == T_FALSE || zero == T_FALSE) { flint_printf("FAIL (log(x * y * z) - log(x) - log(y) - log(z) != 0)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_printf("c = "); ca_print(c, ctx); flint_printf("\n\n"); flint_printf("d = "); ca_print(d, ctx); flint_printf("\n\n"); flint_printf("e = "); ca_print(e, ctx); flint_printf("\n\n"); flint_printf("f = "); ca_print(f, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_clear(c, ctx); ca_clear(d, ctx); ca_clear(e, ctx); ca_clear(f, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-log_identities.c000066400000000000000000000122271461254215100203770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" /* atan(x) = -i/2 log((1+ix)/(1-ix)) */ /* valid for -inf < x < inf */ void simple_ca_atan(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t, u, v; ca_init(t, ctx); ca_init(u, ctx); ca_init(v, ctx); ca_i(t, ctx); ca_mul(u, x, t, ctx); /* v = 1 + i x */ ca_add_ui(v, u, 1, ctx); /* res = 1 - i x */ ca_sub_ui(res, u, 1, ctx); ca_neg(res, res, ctx); ca_div(res, v, res, ctx); ca_log(res, res, ctx); ca_mul(res, res, t, ctx); ca_div_ui(res, res, 2, ctx); ca_neg(res, res, ctx); ca_clear(t, ctx); ca_clear(u, ctx); ca_clear(v, ctx); } void simple_ca_atan_p_q(ca_t res, ulong p, ulong q, ca_ctx_t ctx) { ca_set_ui(res, p, ctx); ca_div_ui(res, res, q, ctx); simple_ca_atan(res, res, ctx); } /* valid for -1 < x < 1 */ void simple_ca_atanh(ca_t res, const ca_t x, ca_ctx_t ctx) { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_add_ui(t, x, 1, ctx); ca_sub_ui(u, x, 1, ctx); ca_neg(u, u, ctx); ca_div(res, t, u, ctx); ca_log(res, res, ctx); ca_div_ui(res, res, 2, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } void simple_ca_atanh_p_q(ca_t res, ulong p, ulong q, ca_ctx_t ctx) { ca_set_ui(res, p, ctx); ca_div_ui(res, res, q, ctx); simple_ca_atanh(res, res, ctx); } #define NUM_FORMULAS 8 slong machin_formulas[NUM_FORMULAS][4][2] = { {{1, 1}, {0, 0}, {0, 0}, {0, 0}}, {{1, 2}, {1, 3}, {0, 0}, {0, 0}}, {{2, 2}, {-1, 7}, {0, 0}, {0, 0}}, {{2, 3}, {1, 7}, {0, 0}, {0, 0}}, {{4, 5}, {-1, 239}, {0, 0}, {0, 0}}, {{1, 2}, {1, 5}, {1, 8}, {0, 0}}, {{1, 3}, {1, 4}, {1, 7}, {1, 13}}, {{12, 49}, {32, 57}, {-5, 239}, {12, 110443}}, }; #define NUM_FORMULAS2 7 slong hyperbolic_logs[NUM_FORMULAS2] = {2, 3, 5, 2, 3, 5, 7}; slong hyperbolic_machin_formulas[NUM_FORMULAS2][4][2] = { {{14, 31}, {10, 49}, {6, 161}, {0, 0}}, {{22, 31}, {16, 49}, {10, 161}, {0, 0}}, {{32, 31}, {24, 49}, {14, 161}, {0, 0}}, {{144, 251}, {54, 449}, {-38, 4801}, {62, 8749}}, {{228, 251}, {86, 449}, {-60, 4801}, {98, 8749}}, {{334, 251}, {126, 449}, {-88, 4801}, {144, 8749}}, {{404, 251}, {152, 449}, {-106, 4801}, {174, 8749}}, }; TEST_FUNCTION_START(ca_log_identities, state) { slong iter; for (iter = 0; iter < 1; iter++) { ca_ctx_t ctx; ca_t x, y, pi4; slong i, j, c, q; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(pi4, ctx); ca_pi(pi4, ctx); ca_div_ui(pi4, pi4, 4, ctx); for (i = 0; i < NUM_FORMULAS; i++) { ca_zero(x, ctx); for (j = 0; j < 4; j++) { c = machin_formulas[i][j][0]; q = machin_formulas[i][j][1]; if (c != 0) { simple_ca_atan_p_q(y, 1, q, ctx); ca_mul_si(y, y, c, ctx); ca_add(x, x, y, ctx); } } ca_sub(x, x, pi4, ctx); if (!(CA_IS_QQ(x, ctx) && fmpq_is_zero(CA_FMPQ(x)))) { flint_printf("FAIL\n\n"); for (j = 0; j < 4; j++) { c = machin_formulas[i][j][0]; q = machin_formulas[i][j][1]; flint_printf("%wd %wd ", c, q); } flint_printf("\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_abort(); } } for (i = 0; i < NUM_FORMULAS2; i++) { ca_zero(x, ctx); for (j = 0; j < 4; j++) { c = hyperbolic_machin_formulas[i][j][0]; q = hyperbolic_machin_formulas[i][j][1]; if (c != 0) { simple_ca_atanh_p_q(y, 1, q, ctx); ca_mul_si(y, y, c, ctx); ca_add(x, x, y, ctx); } } ca_set_ui(y, hyperbolic_logs[i], ctx); ca_log(y, y, ctx); ca_sub(x, x, y, ctx); if (!(CA_IS_QQ(x, ctx) && fmpq_is_zero(CA_FMPQ(x)))) { flint_printf("FAIL\n\n"); for (j = 0; j < 4; j++) { c = hyperbolic_machin_formulas[i][j][0]; q = hyperbolic_machin_formulas[i][j][1]; flint_printf("%wd %wd ", c, q); } flint_printf("\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_abort(); } } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(pi4, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-mul.c000066400000000000000000000104731461254215100161730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_mul, state) { slong iter; /* check special values */ { ca_ctx_t ctx; ca_t x, y, z; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_set_si(x, 2, ctx); ca_uinf(y, ctx); ca_mul(z, x, y, ctx); if (ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: 2 * uinf\n"); flint_abort(); } ca_zero(x, ctx); ca_uinf(y, ctx); ca_mul(z, x, y, ctx); if (ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: 0 * uinf\n"); flint_abort(); } ca_zero(x, ctx); ca_pos_inf(y, ctx); ca_mul(z, x, y, ctx); if (ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: 0 * +inf\n"); flint_abort(); } ca_set_si(x, -2, ctx); ca_pos_inf(y, ctx); ca_mul(z, x, y, ctx); if (ca_check_is_neg_inf(z, ctx) != T_TRUE) { flint_printf("FAIL: -2 * +inf\n"); flint_abort(); } ca_pos_inf(x, ctx); ca_uinf(y, ctx); ca_mul(z, x, y, ctx); if (ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: +inf * uinf\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b, c; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); ca_init(c, ctx); /* test (x * y) * z = x * (y * z) */ ca_randtest_special(x, state, 5, 5, ctx); ca_randtest_special(y, state, 5, 5, ctx); ca_randtest_special(z, state, 5, 5, ctx); ca_randtest_special(a, state, 5, 5, ctx); ca_randtest_special(b, state, 5, 5, ctx); ca_mul(a, x, y, ctx); ca_mul(a, a, z, ctx); ca_mul(b, y, z, ctx); ca_mul(b, x, b, ctx); equal = ca_check_equal(a, b, ctx); if (equal == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_abort(); } /* test x * (y + z) = x * y + x * z */ ca_add(a, y, z, ctx); ca_mul(a, x, a, ctx); ca_mul(b, x, y, ctx); ca_mul(c, x, z, ctx); ca_add(b, b, c, ctx); equal = ca_check_equal(a, b, ctx); if (equal == T_FALSE) { if (!(ca_check_is_infinity(x, ctx) == T_TRUE || ca_check_is_infinity(y, ctx) == T_TRUE || ca_check_is_infinity(z, ctx) == T_TRUE)) { flint_printf("FAIL (distributivity)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_abort(); } } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_clear(c, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-neg.c000066400000000000000000000064621461254215100161520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_neg, state) { { ca_ctx_t ctx; ca_t x, y, z; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_pos_inf(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_neg_inf(y, ctx) != T_TRUE || ca_check_is_neg_inf(z, ctx) != T_TRUE) { flint_printf("FAIL: pos_inf\n"); flint_abort(); } ca_neg_inf(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_pos_inf(y, ctx) != T_TRUE || ca_check_is_pos_inf(z, ctx) != T_TRUE) { flint_printf("FAIL: neg_inf\n"); flint_abort(); } ca_pos_i_inf(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_neg_i_inf(y, ctx) != T_TRUE || ca_check_is_neg_i_inf(z, ctx) != T_TRUE) { flint_printf("FAIL: pos_i_inf\n"); flint_abort(); } ca_undefined(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_undefined(y, ctx) != T_TRUE || ca_check_is_undefined(z, ctx) != T_TRUE) { flint_printf("FAIL: neg_i_inf\n"); flint_abort(); } ca_neg_i_inf(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_pos_i_inf(y, ctx) != T_TRUE || ca_check_is_pos_i_inf(z, ctx) != T_TRUE) { flint_printf("FAIL: neg_i_inf\n"); flint_abort(); } ca_uinf(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_uinf(y, ctx) != T_TRUE || ca_check_is_uinf(z, ctx) != T_TRUE) { flint_printf("FAIL: neg_i_inf\n"); flint_abort(); } ca_i(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_neg_i(y, ctx) != T_TRUE || ca_check_is_neg_i(z, ctx) != T_TRUE) { flint_printf("FAIL: i\n"); flint_abort(); } ca_one(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (ca_check_is_neg_one(y, ctx) != T_TRUE || ca_check_is_neg_one(z, ctx) != T_TRUE) { flint_printf("FAIL: one\n"); flint_abort(); } ca_unknown(x, ctx); ca_neg(y, x, ctx); ca_set(z, x, ctx); ca_neg(z, z, ctx); if (!ca_is_unknown(y, ctx) || !ca_is_unknown(z, ctx)) { flint_printf("FAIL: unknown\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-pow.c000066400000000000000000000103301461254215100161730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_pow, state) { slong iter; /* check numerical evaluation */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z; acb_t ax, ay, az, axy; slong prec; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); acb_init(ax); acb_init(ay); acb_init(az); acb_init(axy); prec = 10 + n_randint(state, 100); ca_randtest(x, state, 5, 5, ctx); ca_randtest(y, state, 5, 5, ctx); if (n_randint(state, 2)) ca_exp(x, x, ctx); if (n_randint(state, 2)) { ca_pow(x, x, y, ctx); ca_randtest(y, state, 5, 5, ctx); } ca_pow(z, x, y, ctx); ca_get_acb(ax, x, prec, ctx); ca_get_acb(ay, y, prec, ctx); ca_get_acb(az, z, prec, ctx); acb_pow(axy, ax, ay, prec); if (!acb_overlaps(axy, az)) { flint_printf("FAIL (overlap)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("ax = "); acb_printn(ax, 30, ARB_STR_NO_RADIUS); flint_printf("\n\n"); flint_printf("ay = "); acb_printn(ay, 30, ARB_STR_NO_RADIUS); flint_printf("\n\n"); flint_printf("az = "); acb_printn(az, 30, ARB_STR_NO_RADIUS); flint_printf("\n\n"); flint_printf("axy = "); acb_printn(axy, 30, ARB_STR_NO_RADIUS); flint_printf("\n\n"); flint_abort(); } acb_clear(ax); acb_clear(ay); acb_clear(az); acb_clear(axy); ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, a, b, xa, xb, xaxb, ab, xab; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(a, ctx); ca_init(b, ctx); ca_init(xa, ctx); ca_init(xb, ctx); ca_init(xaxb, ctx); ca_init(ab, ctx); ca_init(xab, ctx); /* otherwise this will be too slow */ ctx->options[CA_OPT_QQBAR_DEG_LIMIT] = 40; /* x^a * x^b = x^(a+b) */ do { ca_randtest(x, state, 5, 5, ctx); } while (ca_check_is_zero(x, ctx) != T_FALSE); ca_randtest(a, state, 5, 5, ctx); ca_randtest(b, state, 5, 5, ctx); ca_pow(xa, x, a, ctx); ca_pow(xb, x, b, ctx); ca_mul(xaxb, xa, xb, ctx); ca_add(ab, a, b, ctx); ca_pow(xab, x, ab, ctx); equal = ca_check_equal(xab, xaxb, ctx); if (equal == T_FALSE) { flint_printf("FAIL x^a * x^b = x^(a+b)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_printf("xa = "); ca_print(xa, ctx); flint_printf("\n\n"); flint_printf("xb = "); ca_print(xb, ctx); flint_printf("\n\n"); flint_printf("xaxb = "); ca_print(xaxb, ctx); flint_printf("\n\n"); flint_printf("ab = "); ca_print(ab, ctx); flint_printf("\n\n"); flint_printf("xab = "); ca_print(xab, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_clear(xa, ctx); ca_clear(xb, ctx); ca_clear(xaxb, ctx); ca_clear(ab, ctx); ca_clear(xab, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-pow_si_arithmetic.c000066400000000000000000000041231461254215100211020ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_pow_si_arithmetic, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, xa, xb, xaxb, xab; truth_t equal; slong a, b; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(xa, ctx); ca_init(xb, ctx); ca_init(xaxb, ctx); ca_init(xab, ctx); /* x^a * x^b = x^(a+b) */ do { ca_randtest(x, state, 5, 5, ctx); } while (ca_check_is_zero(x, ctx) != T_FALSE); a = n_randint(state, 10) - 5; b = n_randint(state, 10) - 5; ca_pow_si_arithmetic(xa, x, a, ctx); ca_pow_si_arithmetic(xb, x, b, ctx); ca_mul(xaxb, xa, xb, ctx); ca_pow_si_arithmetic(xab, x, a + b, ctx); equal = ca_check_equal(xab, xaxb, ctx); if (equal == T_FALSE) { flint_printf("FAIL x^a * x^b = x^(a+b)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("a = %wd", a); flint_printf("\n\n"); flint_printf("b = %wd", b); flint_printf("\n\n"); flint_printf("xa = "); ca_print(xa, ctx); flint_printf("\n\n"); flint_printf("xb = "); ca_print(xb, ctx); flint_printf("\n\n"); flint_printf("xaxb = "); ca_print(xaxb, ctx); flint_printf("\n\n"); flint_printf("xab = "); ca_print(xab, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(xa, ctx); ca_clear(xb, ctx); ca_clear(xaxb, ctx); ca_clear(xab, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-properties.c000066400000000000000000000615171461254215100175770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_properties, state) { { ca_ctx_t ctx; ca_t x, y; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_zero(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_one(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_set_si(x, -1, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_i(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_neg_i(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); { fmpq_t q; fmpq_init(q); fmpq_set_si(q, -2, 3); ca_set_fmpq(x, q, ctx); fmpq_clear(q); } CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_unknown(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_UNKNOWN); ca_undefined(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_uinf(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_pos_inf(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_neg_inf(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_pos_i_inf(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_FALSE); ca_neg_i_inf(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_undefined, "is_undefined", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_infinity, "is_infinity", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_uinf, "is_uinf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_signed_inf, "is_signed_inf", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_pos_inf, "is_pos_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_inf, "is_neg_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_pos_i_inf, "is_pos_i_inf", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i_inf, "is_neg_i_inf", x, ctx, T_TRUE); ca_pi(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_UNKNOWN); /* todo */ CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_UNKNOWN); /* todo */ CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); ca_pi_i(x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_UNKNOWN); /* todo */ CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_TRUE); ca_set_si(x, -400, ctx); ca_exp(x, x, ctx); ca_exp(x, x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); ca_set_si(x, -1000000, ctx); ca_exp(x, x, ctx); ca_exp(x, x, ctx); CA_TEST_PROPERTY(ca_check_is_number, "is_number", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_zero, "is_zero", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_one, "is_one", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_neg_one, "is_neg_one", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_i, "is_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_neg_i, "is_neg_i", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_algebraic, "is_algebraic", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_rational, "is_rational", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_integer, "is_integer", x, ctx, T_UNKNOWN); CA_TEST_PROPERTY(ca_check_is_real, "is_real", x, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_negative_real, "is_negative_real", x, ctx, T_FALSE); CA_TEST_PROPERTY(ca_check_is_imaginary, "is_imaginary", x, ctx, T_FALSE); ca_clear(x, ctx); ca_clear(y, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-re_im.c000066400000000000000000000053551461254215100164740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_re_im, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, rex, imx, y, absx; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(rex, ctx); ca_init(imx, ctx); ca_init(y, ctx); ca_init(absx, ctx); ca_randtest(x, state, 5, 5, ctx); ca_re(rex, x, ctx); ca_im(imx, x, ctx); /* test re(x) + im(x)*i = x */ ca_i(y, ctx); ca_mul(y, y, imx, ctx); ca_add(y, y, rex, ctx); equal = ca_check_equal(x, y, ctx); if (equal == T_FALSE) { flint_printf("FAIL (re(x) + im(x)*i != x)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("rex = "); ca_print(rex, ctx); flint_printf("\n\n"); flint_printf("imx = "); ca_print(imx, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_abort(); } CA_TEST_PROPERTY(ca_check_is_real, "is_real", rex, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", imx, ctx, T_TRUE); /* test sqrt(re(x)^2 + im(x)^2) = abs(x) */ ca_sqr(y, rex, ctx); ca_sqr(absx, imx, ctx); ca_add(y, y, absx, ctx); ca_sqrt(y, y, ctx); ca_abs(absx, x, ctx); equal = ca_check_equal(absx, y, ctx); if (equal == T_FALSE) { flint_printf("FAIL (sqrt(re(x)^2 + im(x)^2) != abs(x))\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("rex = "); ca_print(rex, ctx); flint_printf("\n\n"); flint_printf("imx = "); ca_print(imx, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("absx = "); ca_print(absx, ctx); flint_printf("\n\n"); flint_abort(); } CA_TEST_PROPERTY(ca_check_is_real, "is_real", y, ctx, T_TRUE); CA_TEST_PROPERTY(ca_check_is_real, "is_real", absx, ctx, T_TRUE); ca_clear(x, ctx); ca_clear(rex, ctx); ca_clear(imx, ctx); ca_clear(y, ctx); ca_clear(absx, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-sin_cos.c000066400000000000000000000054441461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_sin_cos, state) { slong iter; { ca_ctx_t ctx; ca_ctx_init(ctx); for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { ca_t x, s1, c1, s2, c2, s3, c3, s4, c4; if (n_randint(state, 10) == 0) { ca_ctx_clear(ctx); ca_ctx_init(ctx); } ca_init(x, ctx); ca_init(s1, ctx); ca_init(c1, ctx); ca_init(s2, ctx); ca_init(c2, ctx); ca_init(s3, ctx); ca_init(c3, ctx); ca_init(s4, ctx); ca_init(c4, ctx); ca_randtest_special(x, state, 5, 5, ctx); ca_sin_cos_direct(s1, c1, x, ctx); ca_sin_cos_exponential(s2, c2, x, ctx); ca_sin_cos_tangent(s3, c3, x, ctx); ca_sin_cos(s4, c4, x, ctx); if (ca_check_equal(s1, s2, ctx) == T_FALSE || ca_check_equal(c1, c2, ctx) == T_FALSE || ca_check_equal(s1, s3, ctx) == T_FALSE || ca_check_equal(c1, c3, ctx) == T_FALSE || ca_check_equal(s1, s4, ctx) == T_FALSE || ca_check_equal(c1, c4, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("s1 = "); ca_print(s1, ctx); flint_printf("\n\n"); flint_printf("c1 = "); ca_print(c1, ctx); flint_printf("\n\n"); flint_printf("s2 = "); ca_print(s2, ctx); flint_printf("\n\n"); flint_printf("c2 = "); ca_print(c2, ctx); flint_printf("\n\n"); flint_printf("s3 = "); ca_print(s3, ctx); flint_printf("\n\n"); flint_printf("c3 = "); ca_print(c3, ctx); flint_printf("\n\n"); flint_printf("s4 = "); ca_print(s4, ctx); flint_printf("\n\n"); flint_printf("c4 = "); ca_print(c4, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(s1, ctx); ca_clear(c1, ctx); ca_clear(s2, ctx); ca_clear(c2, ctx); ca_clear(s3, ctx); ca_clear(c3, ctx); ca_clear(s4, ctx); ca_clear(c4, ctx); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-sqrt.c000066400000000000000000000043671461254215100163740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_sqrt, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b, c, d; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); ca_init(c, ctx); ca_init(d, ctx); /* test sqrt(x)^2 = x */ ca_randtest(x, state, 5, 5, ctx); ca_randtest(y, state, 5, 5, ctx); ca_randtest(z, state, 5, 5, ctx); ca_randtest(a, state, 5, 5, ctx); ca_randtest(b, state, 5, 5, ctx); ca_mul(x, x, x, ctx); ca_mul(x, x, z, ctx); ca_sqrt(y, x, ctx); ca_mul(z, y, y, ctx); equal = ca_check_equal(x, z, ctx); if (equal == T_FALSE) { flint_printf("FAIL (sqrt(x)^2 != x)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_abort(); } ca_sqrt_inert(z, x, ctx); equal = ca_check_equal(y, z, ctx); if (equal == T_FALSE) { flint_printf("FAIL: sqrt(x) != sqrt_inert(x)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_clear(c, ctx); ca_clear(d, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-sqrt_factor.c000066400000000000000000000046271461254215100177310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_sqrt_factor, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b, c, d; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); ca_init(c, ctx); ca_init(d, ctx); /* test sqrt(x)^2 = x */ ca_randtest_special(x, state, 5, 5, ctx); ca_randtest_special(y, state, 5, 5, ctx); ca_randtest_special(z, state, 5, 5, ctx); ca_randtest_special(a, state, 5, 5, ctx); ca_randtest_special(b, state, 5, 5, ctx); ca_mul(x, x, x, ctx); ca_mul(x, x, z, ctx); /* todo: random flags */ ca_sqrt_factor(y, x, CA_FACTOR_ZZ_SMOOTH | CA_FACTOR_POLY_FULL, ctx); ca_mul(z, y, y, ctx); ca_sub(b, x, z, ctx); equal = ca_check_equal(x, z, ctx); if (equal == T_FALSE) { flint_printf("FAIL (sqrt(x)^2 != x)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_abort(); } ca_sqrt_inert(z, x, ctx); equal = ca_check_equal(y, z, ctx); if (equal == T_FALSE) { flint_printf("FAIL: sqrt(x) != sqrt_inert(x)\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_clear(c, ctx); ca_clear(d, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-sub.c000066400000000000000000000036101461254215100161620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_sub, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_t x, y, z, a, b; truth_t equal; ca_ctx_init(ctx); ca_init(x, ctx); ca_init(y, ctx); ca_init(z, ctx); ca_init(a, ctx); ca_init(b, ctx); /* test (x - y) - z = x - (y + z) */ ca_randtest_special(x, state, 5, 5, ctx); ca_randtest_special(y, state, 5, 5, ctx); ca_randtest_special(z, state, 5, 5, ctx); ca_randtest_special(a, state, 5, 5, ctx); ca_randtest_special(b, state, 5, 5, ctx); ca_sub(a, x, y, ctx); ca_sub(a, a, z, ctx); ca_add(b, y, z, ctx); ca_sub(b, x, b, ctx); equal = ca_check_equal(a, b, ctx); if (equal == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_printf("a = "); ca_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); ca_print(b, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(y, ctx); ca_clear(z, ctx); ca_clear(a, ctx); ca_clear(b, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-tan.c000066400000000000000000000040221461254215100161510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_tan, state) { slong iter; { ca_ctx_t ctx; ca_ctx_init(ctx); for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { ca_t x, t1, t2, t3, t4; if (n_randint(state, 10) == 0) { ca_ctx_clear(ctx); ca_ctx_init(ctx); } ca_init(x, ctx); ca_init(t1, ctx); ca_init(t2, ctx); ca_init(t3, ctx); ca_init(t4, ctx); ca_randtest_special(x, state, 5, 5, ctx); ca_tan_direct(t1, x, ctx); ca_tan_exponential(t2, x, ctx); ca_tan_sine_cosine(t3, x, ctx); ca_tan(t4, x, ctx); if (ca_check_equal(t1, t2, ctx) == T_FALSE || ca_check_equal(t1, t3, ctx) == T_FALSE || ca_check_equal(t1, t4, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("t1 = "); ca_print(t1, ctx); flint_printf("\n\n"); flint_printf("t2 = "); ca_print(t2, ctx); flint_printf("\n\n"); flint_printf("t3 = "); ca_print(t3, ctx); flint_printf("\n\n"); flint_printf("t4 = "); ca_print(t4, ctx); flint_printf("\n\n"); flint_abort(); } ca_clear(x, ctx); ca_clear(t1, ctx); ca_clear(t2, ctx); ca_clear(t3, ctx); ca_clear(t4, ctx); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/test/t-transfer.c000066400000000000000000000041001461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" TEST_FUNCTION_START(ca_transfer, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx, ctx2; ca_t x, y, z; slong i, reps; ca_ctx_init(ctx); ca_ctx_init(ctx2); ca_init(x, ctx); ca_init(y, ctx2); ca_init(z, ctx); reps = 1 + n_randint(state, 10); for (i = 0; i < reps; i++) { ca_randtest_special(x, state, 5, 5, ctx); ca_randtest_special(y, state, 5, 5, ctx2); ca_randtest_special(z, state, 5, 5, ctx); ca_transfer(y, ctx2, x, ctx); ca_transfer(z, ctx, y, ctx2); if (ca_check_equal(x, z, ctx) == T_FALSE) { flint_printf("FAIL: not equal!\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx2); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_abort(); } if (ca_check_equal(x, z, ctx) != T_TRUE && !ca_is_unknown(x, ctx)) { flint_printf("FAIL: not equal!\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n\n"); flint_printf("y = "); ca_print(y, ctx2); flint_printf("\n\n"); flint_printf("z = "); ca_print(z, ctx); flint_printf("\n\n"); flint_abort(); } } ca_clear(x, ctx); ca_clear(y, ctx2); ca_clear(z, ctx); ca_ctx_clear(ctx); ca_ctx_clear(ctx2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca/transfer.c000066400000000000000000000021441461254215100157760ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_transfer(ca_t res, ca_ctx_t res_ctx, const ca_t src, ca_ctx_t src_ctx) { if (res_ctx == src_ctx) { ca_set(res, src, res_ctx); } else if (CA_IS_QQ(src, src_ctx)) { _ca_make_fmpq(res, res_ctx); fmpq_set(CA_FMPQ(res), CA_FMPQ(src)); } else { fexpr_t expr; fexpr_init(expr); /* todo: optimizations, e.g. direct transfer of number field elements where permissible */ ca_get_fexpr(expr, src, CA_FEXPR_SERIALIZATION, src_ctx); if (!ca_set_fexpr(res, expr, res_ctx)) { flint_throw(FLINT_ERROR, "ca_transfer: failed to recreate from expression!\n"); } fexpr_clear(expr); } } flint-3.1.3/src/ca/uinf.c000066400000000000000000000007431461254215100151160ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_uinf(ca_t x, ca_ctx_t ctx) { ca_zero(x, ctx); x->field = CA_INF; } flint-3.1.3/src/ca/undefined.c000066400000000000000000000007561461254215100161220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_undefined(ca_t x, ca_ctx_t ctx) { ca_zero(x, ctx); x->field = CA_UNDEFINED; } flint-3.1.3/src/ca/unknown.c000066400000000000000000000007521461254215100156540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_unknown(ca_t x, ca_ctx_t ctx) { ca_zero(x, ctx); x->field = CA_UNKNOWN; } flint-3.1.3/src/ca/zero.c000066400000000000000000000007551461254215100151370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" void ca_zero(ca_t x, ca_ctx_t ctx) { _ca_make_fmpq(x, ctx); fmpq_zero(CA_FMPQ(x)); } flint-3.1.3/src/ca_ext.h000066400000000000000000000051511461254215100150400ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CA_EXT_H #define CA_EXT_H #ifdef CA_EXT_INLINES_C #define CA_EXT_INLINE #else #define CA_EXT_INLINE static inline #endif #include "ca.h" #ifdef __cplusplus extern "C" { #endif /* Types *********************************************************************/ /* note: types and macros are defined in ca.h since they are needed there */ void ca_ext_init_qqbar(ca_ext_t res, const qqbar_t x, ca_ctx_t ctx); void ca_ext_init_const(ca_ext_t res, calcium_func_code func, ca_ctx_t ctx); void ca_ext_init_fx(ca_ext_t res, calcium_func_code func, const ca_t x, ca_ctx_t ctx); void ca_ext_init_fxy(ca_ext_t res, calcium_func_code func, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_ext_init_fxn(ca_ext_t res, calcium_func_code func, ca_srcptr x, slong nargs, ca_ctx_t ctx); /* todo: this could avoid rehashing, ... */ CA_EXT_INLINE void ca_ext_init_set(ca_ext_t res, const ca_ext_t x, ca_ctx_t ctx) { if (CA_EXT_HEAD(x) == CA_QQBar) { ca_ext_init_qqbar(res, CA_EXT_QQBAR(x), ctx); } else { ca_ext_init_fxn(res, CA_EXT_HEAD(x), CA_EXT_FUNC_ARGS(x), CA_EXT_FUNC_NARGS(x), ctx); } } void ca_ext_clear(ca_ext_t res, ca_ctx_t ctx); CA_EXT_INLINE slong ca_ext_nargs(const ca_ext_t x, ca_ctx_t ctx) { if (CA_EXT_HEAD(x) == CA_QQBar) return 0; else return CA_EXT_FUNC_NARGS(x); } CA_EXT_INLINE void ca_ext_get_arg(ca_t res, const ca_ext_t x, slong i, ca_ctx_t ctx) { if (CA_EXT_HEAD(x) == CA_QQBar || i < 0 || i >= CA_EXT_FUNC_NARGS(x)) { flint_throw(FLINT_ERROR, "ca_ext_get_arg: index out of range\n"); } else { ca_set(res, CA_EXT_FUNC_ARGS(x) + i, ctx); } } CA_EXT_INLINE ulong ca_ext_hash(const ca_ext_t x, ca_ctx_t ctx) { return CA_EXT_HASH(x); } int ca_ext_equal_repr(const ca_ext_t x, const ca_ext_t y, ca_ctx_t ctx); int ca_ext_cmp_repr(const ca_ext_t x, const ca_ext_t y, ca_ctx_t ctx); void ca_ext_print(const ca_ext_t x, ca_ctx_t ctx); void ca_ext_get_acb_raw(acb_t res, ca_ext_t x, slong prec, ca_ctx_t ctx); void ca_ext_cache_init(ca_ext_cache_t cache, ca_ctx_t ctx); void ca_ext_cache_clear(ca_ext_cache_t cache, ca_ctx_t ctx); ca_ext_ptr ca_ext_cache_insert(ca_ext_cache_t cache, const ca_ext_t x, ca_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/ca_ext/000077500000000000000000000000001461254215100146655ustar00rootroot00000000000000flint-3.1.3/src/ca_ext/cache_clear.c000066400000000000000000000014501461254215100172420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" void ca_ext_cache_clear(ca_ext_cache_t cache, ca_ctx_t ctx) { slong i; /* reverse order ensures that we free f(x) before freeing any element used by x */ for (i = cache->length - 1; i >= 0; i--) ca_ext_clear(cache->items[i], ctx); for (i = 0; i < cache->alloc; i++) flint_free(cache->items[i]); flint_free(cache->items); flint_free(cache->hash_table); } flint-3.1.3/src/ca_ext/cache_init.c000066400000000000000000000014101461254215100171130ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" #define INITIAL_HASH_SIZE 16 void ca_ext_cache_init(ca_ext_cache_t cache, ca_ctx_t ctx) { slong i; cache->items = NULL; cache->length = 0; cache->alloc = 0; cache->hash_size = INITIAL_HASH_SIZE; cache->hash_table = flint_malloc(sizeof(slong) * INITIAL_HASH_SIZE); for (i = 0; i < INITIAL_HASH_SIZE; i++) cache->hash_table[i] = -1; } flint-3.1.3/src/ca_ext/cache_insert.c000066400000000000000000000046601461254215100174660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" ca_ext_ptr ca_ext_cache_insert(ca_ext_cache_t cache, const ca_ext_t x, ca_ctx_t ctx) { ulong xhash; slong i, loc; xhash = ca_ext_hash(x, ctx); /* make room for inserting entry if needed */ if (cache->length == cache->alloc) { slong new_alloc; new_alloc = FLINT_MAX(1, cache->alloc * 2); cache->items = flint_realloc(cache->items, sizeof(ca_ext_struct *) * new_alloc); for (i = cache->alloc; i < new_alloc; i++) cache->items[i] = flint_malloc(sizeof(ca_ext_struct)); cache->alloc = new_alloc; } /* rehash if needed */ if (cache->length >= 0.5 * cache->hash_size) { slong new_size, j; slong * new_table; ulong thash; new_size = cache->hash_size * 2; new_table = flint_malloc(sizeof(slong) * new_size); for (i = 0; i < new_size; i++) new_table[i] = -1; for (i = 0; i < cache->length; i++) { thash = ca_ext_hash(cache->items[i], ctx); j = thash % new_size; while (new_table[j] != -1) { j++; if (j == new_size) j = 0; } new_table[j] = i; } flint_free(cache->hash_table); cache->hash_size = new_size; cache->hash_table = new_table; } loc = xhash % ((ulong) cache->hash_size); for (i = 0; i < cache->hash_size; i++) { /* not found, so insert */ if (cache->hash_table[loc] == -1) { ca_ext_init_set(cache->items[cache->length], x, ctx); cache->hash_table[loc] = cache->length; cache->length++; return cache->items[cache->length - 1]; } /* found */ if (ca_ext_equal_repr(cache->items[cache->hash_table[loc]], x, ctx)) return cache->items[cache->hash_table[loc]]; loc++; if (loc == cache->hash_size) loc = 0; } /* cannot happen */ flint_throw(FLINT_ERROR, "(%s)\n", __func__); } flint-3.1.3/src/ca_ext/clear.c000066400000000000000000000017561461254215100161300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" #include "ca_vec.h" void ca_ext_clear(ca_ext_t res, ca_ctx_t ctx) { if (CA_EXT_HEAD(res) == CA_QQBar) { qqbar_clear(CA_EXT_QQBAR(res)); nf_clear(CA_EXT_QQBAR_NF(res)); flint_free(CA_EXT_QQBAR_NF(res)); } else { if (CA_EXT_FUNC_NARGS(res) != 0) _ca_vec_clear(CA_EXT_FUNC_ARGS(res), CA_EXT_FUNC_NARGS(res), ctx); acb_clear(CA_EXT_FUNC_ENCLOSURE(res)); if (res->data.func_data.qqbar != NULL) { qqbar_clear(res->data.func_data.qqbar); flint_free(res->data.func_data.qqbar); } } } flint-3.1.3/src/ca_ext/cmp_repr.c000066400000000000000000000046111461254215100166420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" static int _fmpz_poly_compare_abslex(const fmpz * a, const fmpz * b, slong len) { slong i; int c; for (i = len - 1; i >= 0; i--) { if (!fmpz_equal(a + i, b + i)) { c = fmpz_cmpabs(a + i, b + i); if (c != 0) return (c > 0) ? 1 : -1; return fmpz_sgn(a + i); } } return 0; } static int _qqbar_cmp_repr(const qqbar_t x1, const qqbar_t x2) { slong d1, d2; int c; d1 = qqbar_degree(x1); d2 = qqbar_degree(x2); if (d1 != d2) return (d1 < d2) ? -1 : 1; c = _fmpz_poly_compare_abslex(QQBAR_COEFFS(x1), QQBAR_COEFFS(x2), d1 + 1); if (c != 0) return c; /* todo: different sort order? */ c = qqbar_cmp_re(x1, x2); if (c != 0) return c; c = qqbar_cmp_im(x1, x2); return c; } slong ca_depth(const ca_t x, ca_ctx_t ctx); int ca_ext_cmp_repr(const ca_ext_t x, const ca_ext_t y, ca_ctx_t ctx) { calcium_func_code head1, head2; slong i, len1, len2, depth1, depth2; head1 = CA_EXT_HEAD(x); head2 = CA_EXT_HEAD(y); if (x == y) return 0; if (head1 == CA_QQBar || head2 == CA_QQBar) { if (head1 == head2) return _qqbar_cmp_repr(CA_EXT_QQBAR(x), CA_EXT_QQBAR(y)); if (head1 == CA_QQBar) return -1; else return 1; } /* Depth comparison: this is a hack to sort f(x) before x, so that lex ordering can give an elimination order. */ depth1 = CA_EXT_DEPTH(x); depth2 = CA_EXT_DEPTH(y); if (depth1 < depth2) return -1; if (depth1 > depth2) return 1; len1 = CA_EXT_FUNC_NARGS(x); len2 = CA_EXT_FUNC_NARGS(y); if (head1 != head2) return (head1 < head2) ? -1 : 1; if (len1 != len2) return (len1 < len2) ? -1 : 1; for (i = 0; i < len1; i++) { int c = ca_cmp_repr(CA_EXT_FUNC_ARGS(x) + i, CA_EXT_FUNC_ARGS(y) + i, ctx); if (c != 0) return c; } return 0; } flint-3.1.3/src/ca_ext/equal_repr.c000066400000000000000000000017061461254215100171740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" int ca_ext_equal_repr(const ca_ext_t x, const ca_ext_t y, ca_ctx_t ctx) { slong i, nargs; if (CA_EXT_HASH(x) != CA_EXT_HASH(y)) return 0; if (CA_EXT_HEAD(x) != CA_EXT_HEAD(y)) return 0; if (CA_EXT_HEAD(x) == CA_QQBar) return qqbar_equal(CA_EXT_QQBAR(x), CA_EXT_QQBAR(y)); nargs = CA_EXT_FUNC_NARGS(x); if (nargs != CA_EXT_FUNC_NARGS(y)) return 0; for (i = 0; i < nargs; i++) if (!ca_equal_repr(CA_EXT_FUNC_ARGS(x) + i, CA_EXT_FUNC_ARGS(y) + i, ctx)) return 0; return 1; } flint-3.1.3/src/ca_ext/get_acb_raw.c000066400000000000000000000103161461254215100172670ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_hypgeom.h" #include "ca_ext.h" #define ARB_CONST(f) \ f(acb_realref(res), prec); \ arb_zero(acb_imagref(res)); \ break; #define ACB_UNARY(f) \ ca_get_acb_raw(res, CA_EXT_FUNC_ARGS(x), prec, ctx); \ f(res, res, prec); \ break; #define ACB_UNARY_NOPREC(f) \ ca_get_acb_raw(res, CA_EXT_FUNC_ARGS(x), prec, ctx); \ f(res, res); \ break; #define ACB_UNARY_REAL(f) \ ca_get_acb_raw(res, CA_EXT_FUNC_ARGS(x), prec, ctx); \ f(acb_realref(res), res, prec); \ arb_zero(acb_imagref(res)); \ break; #define ACB_UNARY_REAL_NOPREC(f) \ ca_get_acb_raw(res, CA_EXT_FUNC_ARGS(x), prec, ctx); \ f(acb_realref(res), res); \ arb_zero(acb_imagref(res)); \ break; #define ACB_UNARY_REAL_REAL(f) \ ca_get_acb_raw(res, CA_EXT_FUNC_ARGS(x), prec, ctx); \ f(acb_realref(res), acb_realref(res), prec); \ arb_zero(acb_imagref(res)); \ break; #define ACB_BINARY(f) \ { \ acb_t _t; \ acb_init(_t); \ ca_get_acb_raw(res, CA_EXT_FUNC_ARGS(x), prec, ctx); \ ca_get_acb_raw(_t, CA_EXT_FUNC_ARGS(x) + 1, prec, ctx); \ f(res, res, _t, prec); \ acb_clear(_t); \ } \ break; void ca_ext_get_acb_raw(acb_t res, ca_ext_t x, slong prec, ca_ctx_t ctx) { if (CA_EXT_HEAD(x) == CA_QQBar) { qqbar_cache_enclosure(CA_EXT_QQBAR(x), prec); qqbar_get_acb(res, CA_EXT_QQBAR(x), prec); return; } if (prec <= CA_EXT_FUNC_PREC(x)) { acb_set(res, CA_EXT_FUNC_ENCLOSURE(x)); return; } switch (CA_EXT_HEAD(x)) { /* Arithmetic */ case CA_Neg: ACB_UNARY_NOPREC(acb_neg) case CA_Add: ACB_BINARY(acb_add) case CA_Sub: ACB_BINARY(acb_sub) case CA_Mul: ACB_BINARY(acb_mul) case CA_Div: ACB_BINARY(acb_div) /* Roots */ case CA_Sqrt: ACB_UNARY(acb_sqrt) /* CA_Cbrt, not implemented */ /* CA_Root, not implemented */ /* Complex parts */ case CA_Floor: ACB_UNARY_REAL_REAL(arb_floor) case CA_Ceil: ACB_UNARY_REAL_REAL(arb_ceil) case CA_Abs: ACB_UNARY_REAL(acb_abs) case CA_Sign: ACB_UNARY(acb_sgn) case CA_Re: ACB_UNARY_REAL_NOPREC(acb_get_real) case CA_Im: ACB_UNARY_REAL_NOPREC(acb_get_imag) case CA_Arg: ACB_UNARY_REAL(acb_arg) case CA_Conjugate: ACB_UNARY_NOPREC(acb_conj) /* Elementary constants */ case CA_Pi: ARB_CONST(arb_const_pi) /* Elementary functions */ case CA_Exp: ACB_UNARY(acb_exp) case CA_Log: ACB_UNARY(acb_log) case CA_Pow: ACB_BINARY(acb_pow) case CA_Cos: ACB_UNARY(acb_cos) case CA_Sin: ACB_UNARY(acb_sin) case CA_Tan: ACB_UNARY(acb_tan) case CA_Cosh: ACB_UNARY(acb_cosh) case CA_Sinh: ACB_UNARY(acb_sinh) case CA_Tanh: ACB_UNARY(acb_tanh) case CA_Atan: ACB_UNARY(acb_atan) case CA_Acos: ACB_UNARY(acb_acos) case CA_Asin: ACB_UNARY(acb_asin) case CA_Atanh: ACB_UNARY(acb_atanh) case CA_Acosh: ACB_UNARY(acb_acosh) case CA_Asinh: ACB_UNARY(acb_asinh) /* Euler's constant */ case CA_Euler: ARB_CONST(arb_const_euler) /* Gamma and related functions */ case CA_Gamma: ACB_UNARY(acb_gamma) case CA_LogGamma: ACB_UNARY(acb_lgamma) case CA_Psi: ACB_UNARY(acb_digamma) case CA_Erf: ACB_UNARY(acb_hypgeom_erf) case CA_Erfc: ACB_UNARY(acb_hypgeom_erfc) case CA_Erfi: ACB_UNARY(acb_hypgeom_erfi) case CA_RiemannZeta: ACB_UNARY(acb_zeta) case CA_HurwitzZeta: ACB_BINARY(acb_hurwitz_zeta) default: flint_throw(FLINT_ERROR, "ca_ext_get_acb_raw: unknown function\n"); } acb_set(CA_EXT_FUNC_ENCLOSURE(x), res); CA_EXT_FUNC_PREC(x) = prec; } flint-3.1.3/src/ca_ext/init.c000066400000000000000000000060211461254215100157730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" #include "ca_vec.h" static ulong hash_func(calcium_func_code func, ca_srcptr args, slong nargs, ca_ctx_t ctx) { ulong s; slong i; s = func; for (i = 0; i < nargs; i++) s = ca_hash_repr(args + i, ctx) * 1000003 + s; return s; } void ca_ext_init_qqbar(ca_ext_t res, const qqbar_t x, ca_ctx_t ctx) { fmpq_poly_t t; res->head = CA_QQBar; qqbar_init(CA_EXT_QQBAR(res)); qqbar_set(CA_EXT_QQBAR(res), x); /* qqbar_cache_enclosure(CA_EXT_QQBAR(res), 2 * QQBAR_DEFAULT_PREC); */ /* nf_init wants an fmpq_poly_t, so mock up one */ t->coeffs = QQBAR_POLY(x)->coeffs; t->den[0] = 1; t->length = QQBAR_POLY(x)->length; t->alloc = QQBAR_POLY(x)->alloc; CA_EXT_QQBAR_NF(res) = flint_malloc(sizeof(nf_struct)); nf_init(CA_EXT_QQBAR_NF(res), t); res->hash = qqbar_hash(CA_EXT_QQBAR(res)); res->depth = 0; } slong ca_depth(const ca_t x, ca_ctx_t ctx); static void _ca_ext_init_func(ca_ext_t res, ca_ctx_t ctx) { slong i, d; CA_EXT_FUNC_PREC(res) = 0; acb_init(CA_EXT_FUNC_ENCLOSURE(res)); acb_indeterminate(CA_EXT_FUNC_ENCLOSURE(res)); res->hash = hash_func(CA_EXT_HEAD(res), CA_EXT_FUNC_ARGS(res), CA_EXT_FUNC_NARGS(res), ctx); res->depth = 0; for (i = 0; i < CA_EXT_FUNC_NARGS(res); i++) { d = ca_depth(CA_EXT_FUNC_ARGS(res) + i, ctx); res->depth = FLINT_MAX(res->depth, d + 1); } res->data.func_data.qqbar = NULL; } void ca_ext_init_const(ca_ext_t res, calcium_func_code func, ca_ctx_t ctx) { res->head = func; CA_EXT_FUNC_NARGS(res) = 0; CA_EXT_FUNC_ARGS(res) = NULL; _ca_ext_init_func(res, ctx); } void ca_ext_init_fx(ca_ext_t res, calcium_func_code func, const ca_t x, ca_ctx_t ctx) { res->head = func; res->hash = 0; CA_EXT_FUNC_NARGS(res) = 1; CA_EXT_FUNC_ARGS(res) = _ca_vec_init(1, ctx); ca_set(CA_EXT_FUNC_ARGS(res), x, ctx); _ca_ext_init_func(res, ctx); } void ca_ext_init_fxy(ca_ext_t res, calcium_func_code func, const ca_t x, const ca_t y, ca_ctx_t ctx) { res->head = func; res->hash = 0; CA_EXT_FUNC_NARGS(res) = 2; CA_EXT_FUNC_ARGS(res) = _ca_vec_init(2, ctx); ca_set(CA_EXT_FUNC_ARGS(res), x, ctx); ca_set(CA_EXT_FUNC_ARGS(res) + 1, y, ctx); _ca_ext_init_func(res, ctx); } void ca_ext_init_fxn(ca_ext_t res, calcium_func_code func, ca_srcptr x, slong nargs, ca_ctx_t ctx) { res->head = func; CA_EXT_FUNC_NARGS(res) = nargs; if (nargs == 0) CA_EXT_FUNC_ARGS(res) = NULL; else CA_EXT_FUNC_ARGS(res) = _ca_vec_init(nargs, ctx); _ca_vec_set(CA_EXT_FUNC_ARGS(res), x, nargs, ctx); _ca_ext_init_func(res, ctx); } flint-3.1.3/src/ca_ext/inlines.c000066400000000000000000000006541461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define CA_EXT_INLINES_C #include "ca_ext.h" flint-3.1.3/src/ca_ext/print.c000066400000000000000000000026141461254215100161700ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" void ca_ext_print(const ca_ext_t x, ca_ctx_t ctx) { if (x->head == CA_QQBar) { flint_printf("Algebraic "); if (qqbar_is_i(CA_EXT_QQBAR(x))) flint_printf("I"); else { /* flint_printf("Algebraic [deg %wd] ", qqbar_degree(CA_EXT_QQBAR(x))); qqbar_printn(CA_EXT_QQBAR(x), 10); */ qqbar_printn(CA_EXT_QQBAR(x), 8); /* flint_printf(" ("); fmpz_poly_print_pretty(QQBAR_POLY(CA_EXT_QQBAR(x)), "a"); flint_printf("=0)"); */ } } else { flint_printf("%s", calcium_func_name(CA_EXT_HEAD(x))); if (CA_EXT_FUNC_NARGS(x) != 0) { slong i; flint_printf("("); for (i = 0; i < CA_EXT_FUNC_NARGS(x); i++) { ca_print(CA_EXT_FUNC_ARGS(x) + i, ctx); if (i < CA_EXT_FUNC_NARGS(x) - 1) flint_printf(", "); } flint_printf(")"); } } } flint-3.1.3/src/ca_ext/test/000077500000000000000000000000001461254215100156445ustar00rootroot00000000000000flint-3.1.3/src/ca_ext/test/main.c000066400000000000000000000014111461254215100167310ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-cache_insert.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(ca_ext_cache_insert) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/ca_ext/test/t-cache_insert.c000066400000000000000000000031511461254215100207000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" #include "ca_ext.h" TEST_FUNCTION_START(ca_ext_cache_insert, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_ext_t ext; ca_ext_ptr ext2; ca_ext_cache_t cache; qqbar_t x; slong i, len; ca_ctx_init(ctx); qqbar_init(x); len = n_randint(state, 1000); ca_ext_cache_init(cache, ctx); for (i = 0; i < len; i++) { qqbar_set_ui(x, n_randint(state, 100)); ca_ext_init_qqbar(ext, x, ctx); ext2 = ca_ext_cache_insert(cache, ext, ctx); if (!ca_ext_equal_repr(ext2, ext, ctx)) { flint_printf("FAIL\n\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("ext = "); ca_ext_print(ext, ctx); flint_printf("\n\n"); flint_printf("ext2 = "); ca_ext_print(ext2, ctx); flint_printf("\n\n"); flint_abort(); } ca_ext_clear(ext, ctx); } ca_ext_cache_clear(cache, ctx); ca_ctx_clear(ctx); qqbar_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_field.h000066400000000000000000000034651461254215100153310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CA_FIELD_H #define CA_FIELD_H #include "ca.h" #ifdef __cplusplus extern "C" { #endif /* Types *********************************************************************/ /* note: types and macros are defined in ca.h since they are needed there */ #define CA_FIELD_HASH_C UWORD(100003) void ca_field_init_qq(ca_field_t K, ca_ctx_t ctx); void ca_field_init_nf(ca_field_t K, const qqbar_t x, ca_ctx_t ctx); void ca_field_init_const(ca_field_t K, calcium_func_code func, ca_ctx_t ctx); void ca_field_init_fx(ca_field_t K, calcium_func_code func, const ca_t x, ca_ctx_t ctx); void ca_field_init_fxy(ca_field_t K, calcium_func_code func, const ca_t x, const ca_t y, ca_ctx_t ctx); void ca_field_init_multi(ca_field_t K, slong len, ca_ctx_t ctx); void ca_field_clear(ca_field_t K, ca_ctx_t ctx); void ca_field_set_ext(ca_field_t K, slong i, ca_ext_srcptr x, ca_ctx_t ctx); void ca_field_print(const ca_field_t K, ca_ctx_t ctx); int ca_field_cmp(const ca_field_t K1, const ca_field_t K2, ca_ctx_t ctx); void ca_field_build_ideal(ca_field_t K, ca_ctx_t ctx); void ca_field_build_ideal_erf(ca_field_t K, ca_ctx_t ctx); void ca_field_build_ideal_gamma(ca_field_t K, ca_ctx_t ctx); void ca_field_cache_init(ca_field_cache_t cache, ca_ctx_t ctx); void ca_field_cache_clear(ca_field_cache_t cache, ca_ctx_t ctx); ca_field_ptr ca_field_cache_insert_ext(ca_field_cache_t cache, ca_ext_struct ** x, slong length, ca_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/ca_field/000077500000000000000000000000001461254215100151505ustar00rootroot00000000000000flint-3.1.3/src/ca_field/build_ideal.c000066400000000000000000001012671461254215100175600ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ca.h" #include "ca_ext.h" #include "ca_field.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #include "qqbar.h" #include "fmpz_mpoly.h" #include "gr.h" slong acb_multi_lindep(fmpz_mat_t rel, acb_srcptr vec, slong len, int check, slong prec) { fmpz_mat_t A; arf_t tmpr, halfr; fmpz_lll_t ctx; fmpz_t scale_exp; int nonreal, found; slong i, row, accuracy; acb_t z2; mag_t max_size, max_rad, tmpmag; if (fmpz_mat_nrows(rel) != 0 || fmpz_mat_ncols(rel) != 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); fmpz_mat_clear(rel); for (i = 0; i < len; i++) { if (!acb_is_finite(vec + i)) { fmpz_mat_init(rel, 0, len); return 0; } } found = 0; nonreal = 0; for (i = 0; i < len; i++) if (!arb_contains_zero(acb_imagref(vec + i))) nonreal = 1; fmpz_mat_init(A, len, len + 1 + nonreal); fmpz_init(scale_exp); acb_init(z2); arf_init(tmpr); arf_init(halfr); mag_init(max_size); mag_init(max_rad); mag_init(tmpmag); arf_set_d(halfr, 0.5); for (i = 0; i < len; i++) { arf_get_mag(tmpmag, arb_midref(acb_realref(vec + i))); mag_max(max_size, max_size, tmpmag); arf_get_mag(tmpmag, arb_midref(acb_imagref(vec + i))); mag_max(max_size, max_size, tmpmag); mag_max(max_rad, max_rad, arb_radref(acb_realref(vec + i))); mag_max(max_rad, max_rad, arb_radref(acb_imagref(vec + i))); } prec = FLINT_MAX(prec, 2); if (!mag_is_zero(max_size) && !mag_is_zero(max_rad)) { accuracy = _fmpz_sub_small(MAG_EXPREF(max_size), MAG_EXPREF(max_rad)); accuracy = FLINT_MAX(accuracy, 10); prec = FLINT_MIN(prec, accuracy); } if (mag_is_zero(max_size)) { fmpz_zero(scale_exp); /* todo: quick return? */ } else { fmpz_neg(scale_exp, MAG_EXPREF(max_size)); fmpz_add_ui(scale_exp, scale_exp, prec); } /* Using 5% of the bits for checking will provide some protection against spurious relations */ fmpz_sub_ui(scale_exp, scale_exp, FLINT_MAX(10, prec * 0.05)); /* Create matrix */ for (i = 0; i < len; i++) fmpz_one(fmpz_mat_entry(A, i, i)); for (i = 0; i < len; i++) { arf_mul_2exp_fmpz(tmpr, arb_midref(acb_realref(vec + i)), scale_exp); arf_add(tmpr, tmpr, halfr, prec, ARF_RND_NEAR); arf_floor(tmpr, tmpr); arf_get_fmpz(fmpz_mat_entry(A, i, len), tmpr, ARF_RND_NEAR); if (nonreal) { arf_mul_2exp_fmpz(tmpr, arb_midref(acb_imagref(vec + i)), scale_exp); arf_add(tmpr, tmpr, halfr, prec, ARF_RND_NEAR); arf_floor(tmpr, tmpr); arf_get_fmpz(fmpz_mat_entry(A, i, len + 1), tmpr, ARF_RND_NEAR); } } /* LLL reduction */ fmpz_lll_context_init(ctx, 0.75, 0.51, 1, 0); #if 1 fmpz_lll(A, NULL, ctx); #else { fmpz_t gb; fmpz_init(gb); fmpz_one(gb); fmpz_mul_2exp(gb, gb, prec / 2); fmpz_lll_with_removal(A, NULL, gb, ctx); fmpz_clear(gb); } #endif /* Heuristic check */ for (row = 0; row < len; row++) { acb_zero(z2); for (i = 0; i < len; i++) acb_addmul_fmpz(z2, vec + i, fmpz_mat_entry(A, row, i), prec + 10); if (!_fmpz_vec_is_zero(A->rows[row], len) && acb_contains_zero(z2)) { found++; } else { _fmpz_vec_zero(A->rows[row], fmpz_mat_ncols(A)); } } fmpz_mat_init(rel, found, len); i = 0; for (row = 0; row < len; row++) { if (!_fmpz_vec_is_zero(A->rows[row], len)) { _fmpz_vec_set(rel->rows[i], A->rows[row], len); i++; } } /* todo: move outside? */ if (found > 1) { fmpz_mat_hnf(rel, rel); } fmpz_mat_clear(A); fmpz_clear(scale_exp); acb_clear(z2); arf_clear(tmpr); arf_clear(halfr); mag_clear(max_size); mag_clear(max_rad); mag_clear(tmpmag); /* fixme: bogus */ return found; } void _nf_elem_get_fmpz_poly_den_shallow(fmpz_poly_t pol, fmpz_t den, const nf_elem_t a, const nf_t nf); void _ca_field_ideal_insert_clear_mpoly(ca_field_t K, fmpz_mpoly_t poly, fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx) { if (poly->length == 0) { flint_throw(FLINT_ERROR, "ERROR: inserting the zero polynomial into ideal\n"); } if (fmpz_sgn(poly->coeffs) < 0) fmpz_mpoly_neg(poly, poly, mctx); /* todo: move!!! */ fmpz_mpoly_vec_insert_unique(CA_FIELD_IDEAL(K), poly, mctx); fmpz_mpoly_clear(poly, mctx); } int ext_as_pow_pq(slong *p, slong *q, const ca_ext_t x, ca_ctx_t ctx) { if (CA_EXT_HEAD(x) == CA_Sqrt) { *p = 1; *q = 2; return 1; } if (CA_EXT_HEAD(x) == CA_Pow && CA_IS_QQ(CA_EXT_FUNC_ARGS(x) + 1, ctx)) { fmpz pp, qq; pp = *CA_FMPQ_NUMREF(CA_EXT_FUNC_ARGS(x) + 1); qq = *CA_FMPQ_DENREF(CA_EXT_FUNC_ARGS(x) + 1); if (fmpz_bits(&pp) <= 6 && fmpz_bits(&qq) <= 6) { *p = fmpz_get_si(&pp); *q = fmpz_get_si(&qq); return 1; } } return 0; } int ca_field_prove_log_relation(ca_field_t K, const fmpz * rel, acb_srcptr z, const slong * logs, slong num_logs, slong num_logs_with_pi_i, slong prec, ca_ctx_t ctx) { ca_t prod, upow; slong j; acb_t t; mag_t tm; int success = 0; /* printf("possible log relation!\n"); for (j = 0; j < num_logs; j++) { fmpz_print(rel + j); printf(" "); acb_printn(z + j, 10, 0); printf(" "); } printf("\n"); */ acb_init(t); mag_init(tm); /* a^m * b^n = 1 => m*log(a) + n*log(b) = 2 pi i k */ /* Verify that (m*log(a) + n*log(b)) / (2 pi i) contains unique integer. */ /* It is enough to show that |... + ...| < 2^1. */ acb_zero(t); for (j = 0; j < num_logs_with_pi_i; j++) if (!fmpz_is_zero(rel + j)) acb_addmul_fmpz(t, z + j, rel + j, prec); acb_get_mag(tm, t); if (mag_cmp_2exp_si(tm, 1) < 0) { ca_init(prod, ctx); ca_init(upow, ctx); /* Check product of arguments to log. */ /* Todo: separate positive/negative exponents, thus avoiding inverses? */ /* Or: otherwise balance the product. */ ca_one(prod, ctx); for (j = 0; j < num_logs; j++) { if (!fmpz_is_zero(rel + j)) { ca_pow_fmpz(upow, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, logs[j])), rel + j, ctx); ca_mul(prod, prod, upow, ctx); } } /* printf("product: "); ca_print(prod, ctx); printf("\n\n"); */ success = (ca_check_is_one(prod, ctx) == T_TRUE); ca_clear(prod, ctx); ca_clear(upow, ctx); } if (0 && success) { printf("proved log relation!\n"); for (j = 0; j < num_logs; j++) { fmpz_print(rel + j); printf(" "); acb_printn(z + j, 10, 0); printf(" "); } printf("\n"); for (j = 0; j < num_logs; j++) { if (!fmpz_is_zero(rel + j) || 1) { fmpz_print(rel + j); flint_printf(" * log("); ca_print(CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, logs[j])), ctx); flint_printf(") "); } } flint_printf("\n"); } acb_clear(t); mag_clear(tm); return success; } slong ca_field_insert_log_relation(ca_field_t K, fmpz * rel, const slong * logs, slong index_i, slong index_pi, slong num_logs, slong num_logs_with_pi_i, ca_ctx_t ctx) { fmpz_mpoly_t poly; ulong * exp; slong which_removed; slong j, len; len = CA_FIELD_LENGTH(K); exp = flint_malloc(sizeof(ulong) * len); fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); which_removed = -1; for (j = 0; j < num_logs_with_pi_i; j++) { slong k; if (fmpz_is_zero(rel + j)) continue; if (which_removed == -1) which_removed = j; for (k = 0; k < len; k++) exp[k] = 0; /* 2 pi i */ if (j == num_logs) { exp[index_i] = 1; exp[index_pi] = 1; fmpz_mul_2exp(rel + j, rel + j, 1); } else { exp[logs[j]] = 1; } fmpz_mpoly_set_coeff_fmpz_ui(poly, rel + j, exp, CA_FIELD_MCTX(K, ctx)); } flint_free(exp); _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); return which_removed; } /* Find log relations. */ void ca_field_build_ideal_logs(ca_field_t K, ca_ctx_t ctx) { slong * logs; slong num_logs, num_logs_with_pi_i; slong prec; int have_pi, have_i, have_pi_i; slong index_pi, index_i; slong i, len; len = CA_FIELD_LENGTH(K); if (len < 2) return; num_logs = 0; logs = flint_malloc(sizeof(slong) * len); for (i = 0; i < len; i++) { if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)) == CA_Log) { logs[num_logs] = i; num_logs++; } } have_i = have_pi = 0; index_i = index_pi = -1; for (i = 0; i < len; i++) { if (CA_FIELD_EXT_ELEM(K, i) == CA_FIELD_EXT_ELEM(ctx->field_qq_i, 0)) { index_i = i; have_i = 1; break; } } for (i = 0; i < len; i++) { if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)) == CA_Pi) { index_pi = i; have_pi = 1; break; } } have_pi_i = have_pi && have_i; num_logs_with_pi_i = num_logs + have_pi_i; if (num_logs_with_pi_i >= 2) { fmpz_mat_t A; acb_ptr z; slong j, alloc; fmpz * rel; int found_relation = 0; slong which_removed = 0; slong row; prec = ctx->options[CA_OPT_LLL_PREC]; alloc = num_logs_with_pi_i; z = _acb_vec_init(alloc); for (j = 0; j < num_logs; j++) { /* todo: take advantage of cached enclosure */ ca_get_acb(z + j, CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, logs[j])), prec, ctx); acb_log(z + j, z + j, prec); } /* Add 2*pi*i as another logarithm */ if (have_pi_i) { acb_const_pi(z + num_logs, prec); acb_mul_onei(z + num_logs, z + num_logs); acb_mul_2exp_si(z + num_logs, z + num_logs, 1); } if (1) /* Find all integer relations at once. */ { fmpz_mat_init(A, 0, 0); acb_multi_lindep(A, z, num_logs_with_pi_i, 1, prec); for (row = 0; row < fmpz_mat_nrows(A); row++) { rel = A->rows[row]; if (!_fmpz_vec_is_zero(rel, num_logs_with_pi_i) && FLINT_ABS(_fmpz_vec_max_bits(rel, num_logs_with_pi_i)) <= 10) { if (ca_field_prove_log_relation(K, rel, z, logs, num_logs, num_logs_with_pi_i, prec, ctx)) { found_relation = 1; which_removed = ca_field_insert_log_relation(K, rel, logs, index_i, index_pi, num_logs, num_logs_with_pi_i, ctx); } } } fmpz_mat_clear(A); } else { rel = _fmpz_vec_init(alloc); while (num_logs_with_pi_i >= 2) { found_relation = 0; if (_qqbar_acb_lindep(rel, z, num_logs_with_pi_i, 1, prec)) { if (ca_field_prove_log_relation(K, rel, z, logs, num_logs, num_logs_with_pi_i, prec, ctx)) { found_relation = 1; which_removed = ca_field_insert_log_relation(K, rel, logs, index_i, index_pi, num_logs, num_logs_with_pi_i, ctx); } } if (!found_relation) break; for (j = which_removed; j < num_logs - 1; j++) logs[j] = logs[j + 1]; for (j = which_removed; j < num_logs_with_pi_i - 1; j++) acb_swap(z + j, z + j + 1); num_logs--; num_logs_with_pi_i--; } _fmpz_vec_clear(rel, alloc); } _acb_vec_clear(z, alloc); } flint_free(logs); } int ca_field_prove_multiplicative_relation(ca_field_t K, const fmpz * rel, acb_srcptr z, const slong * powers, slong num_powers, slong prec, ca_ctx_t ctx) { ca_t t, u; slong i; int success = 0; int all_qqbar = 1; ca_init(t, ctx); ca_init(u, ctx); if (ctx->options[CA_OPT_VERBOSE]) { flint_printf("Attempt to prove multiplicative relation:\n"); for (i = 0; i < num_powers + 1; i++) { flint_printf(" [ ^"); fmpz_print(rel + i); flint_printf("] "); if (i == num_powers) printf("(-1) "); else { ca_ext_print(CA_FIELD_EXT_ELEM(K, powers[i]), ctx); flint_printf(" "); } flint_printf("\n"); } flint_printf("\n"); } /* Special-case all qqbars; todo -- separate qqbars, exps; better algorithm */ for (i = 0; i < num_powers && all_qqbar; i++) { if (!fmpz_is_zero(rel + i)) { ca_ext_srcptr ext = CA_FIELD_EXT_ELEM(K, powers[i]); if (!CA_EXT_IS_QQBAR(ext)) all_qqbar = 0; } } if (all_qqbar) { qqbar_t a, b; qqbar_init(a); qqbar_init(b); qqbar_one(a); /* qqbar arithmetic with (bogus) limits */ gr_ctx_t QQbar; gr_ctx_init_complex_qqbar(QQbar); _gr_ctx_qqbar_set_limits(QQbar, ctx->options[CA_OPT_QQBAR_DEG_LIMIT], ctx->options[CA_OPT_PREC_LIMIT] * 10); for (i = 0; i < num_powers; i++) { if (!fmpz_is_zero(rel + i)) { ca_ext_srcptr ext = CA_FIELD_EXT_ELEM(K, powers[i]); if (gr_pow_fmpz(b, CA_EXT_QQBAR(ext), rel + i, QQbar) != GR_SUCCESS) { success = 0; goto qqbar_end; } if (gr_mul(a, a, b, QQbar) != GR_SUCCESS) { success = 0; goto qqbar_end; } } } gr_ctx_clear(QQbar); /* (-1)^ */ if (fmpz_is_odd(rel + num_powers)) qqbar_neg(a, a); success = qqbar_is_one(a); qqbar_end: /* if (!success) { printf("qqbar failed!\n"); } */ qqbar_clear(a); qqbar_clear(b); } else { /* Todo: don't duplicate these computations */ for (i = 0; i < num_powers; i++) { if (!fmpz_is_zero(rel + i)) { ca_ext_srcptr ext = CA_FIELD_EXT_ELEM(K, powers[i]); if (CA_EXT_HEAD(ext) == CA_Sqrt) { ca_log(u, CA_EXT_FUNC_ARGS(ext), ctx); ca_div_ui(u, u, 2, ctx); } else if (CA_EXT_HEAD(ext) == CA_Pow) { ca_log(u, CA_EXT_FUNC_ARGS(ext), ctx); ca_mul(u, u, CA_EXT_FUNC_ARGS(ext) + 1, ctx); } else if (CA_EXT_HEAD(ext) == CA_Exp) { ca_set(u, CA_EXT_FUNC_ARGS(ext), ctx); } else if (CA_EXT_IS_QQBAR(ext)) { ca_set_qqbar(u, CA_EXT_QQBAR(ext), ctx); ca_log(u, u, ctx); } else { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } ca_mul_fmpz(u, u, rel + i, ctx); ca_add(t, t, u, ctx); } } if (!fmpz_is_zero(rel + num_powers)) { ca_pi_i(u, ctx); ca_mul_fmpz(u, u, rel + num_powers, ctx); ca_add(t, t, u, ctx); } success = (ca_check_is_zero(t, ctx) == T_TRUE); } if (ctx->options[CA_OPT_VERBOSE]) { flint_printf(" Success = %d\n\n", success); } ca_clear(t, ctx); ca_clear(u, ctx); return success; } slong ca_field_insert_multiplicative_relation(ca_field_t K, fmpz * rel, const slong * powers, slong num_powers, ca_ctx_t ctx) { /* x^a y^b +/- z^d w^e = 0 */ fmpz_mpoly_t poly; ulong * exp1; ulong * exp2; int neg; slong len, j, which_removed; len = CA_FIELD_LENGTH(K); which_removed = -1; fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); exp1 = flint_calloc(len, sizeof(ulong)); exp2 = flint_calloc(len, sizeof(ulong)); neg = fmpz_is_odd(rel + num_powers); for (j = 0; j < num_powers; j++) { if (fmpz_is_zero(rel + j)) continue; if (which_removed == -1) which_removed = j; if (fmpz_sgn(rel + j) > 0) exp1[powers[j]] = rel[j]; else exp2[powers[j]] = -rel[j]; } /* todo: normalise sign? */ fmpz_mpoly_set_coeff_si_ui(poly, 1, exp1, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_coeff_si_ui(poly, neg ? 1 : -1, exp2, CA_FIELD_MCTX(K, ctx)); flint_free(exp1); flint_free(exp2); _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); return which_removed; } /* Find relations involving exponentials, powers and roots. */ /* Todo: more special cases (including roots of unity) */ void ca_field_build_ideal_multiplicative(ca_field_t K, ca_ctx_t ctx) { slong i, len; slong * powers; slong num_powers; slong prec; len = CA_FIELD_LENGTH(K); if (len == 0) return; num_powers = 0; powers = flint_malloc(sizeof(slong) * len); for (i = 0; i < len; i++) { if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)) == CA_Sqrt) { powers[num_powers] = i; num_powers++; } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)) == CA_Pow) { powers[num_powers] = i; num_powers++; } else if (CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)) == CA_Exp) { powers[num_powers] = i; num_powers++; } else if (CA_EXT_IS_QQBAR(CA_FIELD_EXT_ELEM(K, i))) { powers[num_powers] = i; num_powers++; } } if (num_powers >= 1) { acb_ptr z; fmpz * rel; slong alloc, j; int found_relation = 0; slong which_removed = 0; fmpz_mat_t A; slong row; prec = ctx->options[CA_OPT_LLL_PREC]; alloc = num_powers + 1; z = _acb_vec_init(alloc); for (i = 0; i < num_powers; i++) { ca_ext_srcptr ext = CA_FIELD_EXT_ELEM(K, powers[i]); if (CA_EXT_HEAD(ext) == CA_Sqrt) { ca_get_acb(z + i, CA_EXT_FUNC_ARGS(ext), prec, ctx); acb_log(z + i, z + i, prec); acb_mul_2exp_si(z + i, z + i, -1); } else if (CA_EXT_HEAD(ext) == CA_Pow) { ca_get_acb(z + i, CA_EXT_FUNC_ARGS(ext), prec, ctx); acb_log(z + i, z + i, prec); ca_get_acb(z + i + 1, CA_EXT_FUNC_ARGS(ext) + 1, prec, ctx); /* xxx */ acb_mul(z + i, z + i, z + i + 1, prec); } else if (CA_EXT_HEAD(ext) == CA_Exp) { ca_get_acb(z + i, CA_EXT_FUNC_ARGS(ext), prec, ctx); } else if (CA_EXT_IS_QQBAR(ext)) { qqbar_get_acb(z + i, CA_EXT_QQBAR(ext), prec); acb_log(z + i, z + i, prec); } else { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } } /* todo: exp(pi i) = -1 --- look for other roots of unity! */ /* todo: what else to include -- log(2), log(3), log(5) ? */ acb_const_pi(z + num_powers, prec); acb_mul_onei(z + num_powers, z + num_powers); /* todo: verify that logs are not evaluated at zero... */ if (1) /* Find all integer relations at once. */ { fmpz_mat_init(A, 0, 0); acb_multi_lindep(A, z, num_powers + 1, 1, prec); for (row = 0; row < fmpz_mat_nrows(A); row++) { rel = A->rows[row]; if (!_fmpz_vec_is_zero(rel, num_powers + 1) && FLINT_ABS(_fmpz_vec_max_bits(rel, num_powers + 1)) <= 10) { if (ca_field_prove_multiplicative_relation(K, rel, z, powers, num_powers, prec, ctx)) { ca_field_insert_multiplicative_relation(K, rel, powers, num_powers, ctx); } } } fmpz_mat_clear(A); } else { rel = _fmpz_vec_init(alloc); while (num_powers >= 1) { found_relation = 0; if (_qqbar_acb_lindep(rel, z, num_powers + 1, 1, prec) && FLINT_ABS(_fmpz_vec_max_bits(rel, num_powers + 1)) <= 10) { if (!_fmpz_vec_is_zero(rel, num_powers + 1) && FLINT_ABS(_fmpz_vec_max_bits(rel, num_powers + 1)) <= 10) { if (ca_field_prove_multiplicative_relation(K, rel, z, powers, num_powers, prec, ctx)) { ca_field_insert_multiplicative_relation(K, rel, powers, num_powers, ctx); } } } if (!found_relation) break; for (j = which_removed; j < num_powers - 1; j++) powers[j] = powers[j + 1]; for (j = which_removed; j < num_powers; j++) acb_swap(z + j, z + j + 1); num_powers--; } _fmpz_vec_clear(rel, alloc); } _acb_vec_clear(z, alloc); } flint_free(powers); } /* todo: move to utils */ void fmpz_mpoly_set_coeff_si_x(fmpz_mpoly_t poly, slong c, slong x_var, slong x_exp, const fmpz_mpoly_ctx_t ctx); void ca_field_build_ideal(ca_field_t K, ca_ctx_t ctx) { slong i, len; len = CA_FIELD_LENGTH(K); if (len <= 0) return; if (len == 1 && CA_EXT_IS_QQBAR(CA_FIELD_EXT_ELEM(K, 0))) return; /* Find direct algebraic relations. */ if (len >= 2) { slong deg, vieta_limit; vieta_limit = ctx->options[CA_OPT_VIETA_LIMIT]; for (i = 0; vieta_limit > 0 && i < len; i++) { ca_ext_struct * x = CA_FIELD_EXT_ELEM(K, i); /* If all conjugates of an algebraic number are present, add Vieta's formulas. */ if (CA_EXT_IS_QQBAR(x) && ((deg = qqbar_degree(CA_EXT_QQBAR(x))) <= vieta_limit)) { slong j, num_conjugates; num_conjugates = 0; for (j = i + 1; j < len; j++) { ca_ext_struct * y = CA_FIELD_EXT_ELEM(K, j); if (CA_EXT_IS_QQBAR(y) && fmpz_poly_equal(QQBAR_POLY(CA_EXT_QQBAR(x)), QQBAR_POLY(CA_EXT_QQBAR(y)))) num_conjugates++; else break; } if (num_conjugates + 1 == deg) { fmpz_mpoly_t r; slong k; slong * vars; ulong binom; /* an * (x1 + x2 + ... + xn) + a[n-1] = 0, etc. */ /* todo: remove coefficient GCD */ vars = flint_malloc(deg * sizeof(slong)); for (k = 0; k < deg; k++) vars[k] = i + k; binom = 1; for (k = 1; k <= deg; k++) { binom = binom * (deg - k + 1) / k; /* alternative way to define a cutoff: if (binom > (ulong) vieta_limit) break; */ fmpz_mpoly_init(r, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_symmetric_gens(r, k, vars, deg, CA_FIELD_MCTX(K, ctx)); /* todo: cancel gcd between coefficients */ fmpz_mpoly_scalar_mul_fmpz(r, r, QQBAR_COEFFS(CA_EXT_QQBAR(x)) + deg, CA_FIELD_MCTX(K, ctx)); if (k % 2 == 1) fmpz_mpoly_add_fmpz(r, r, QQBAR_COEFFS(CA_EXT_QQBAR(x)) + deg - k, CA_FIELD_MCTX(K, ctx)); else fmpz_mpoly_sub_fmpz(r, r, QQBAR_COEFFS(CA_EXT_QQBAR(x)) + deg - k, CA_FIELD_MCTX(K, ctx)); _ca_field_ideal_insert_clear_mpoly(K, r, CA_FIELD_MCTX(K, ctx), ctx); } flint_free(vars); } i += num_conjugates; } } for (i = 0; i < len; i++) { slong a, b; ca_ext_struct * x = CA_FIELD_EXT_ELEM(K, i); /* Absolute annihilating polynomial for number field */ if (CA_EXT_IS_QQBAR(x)) { fmpz_mpoly_t poly; fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_gen_fmpz_poly(poly, i, QQBAR_POLY(CA_EXT_QQBAR(x)), CA_FIELD_MCTX(K, ctx)); _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); continue; } /* x = sqrt(t) -> x^2 - t = 0 */ /* x = t^(a/b) -> x^b - t^a = 0 */ /* A relation will only be added if t can be expressed in the present field. */ if (ext_as_pow_pq(&a, &b, x, ctx)) { ca_srcptr t; ca_field_struct * L; /* Field of t */ slong L_len; slong * tgen_map; slong j, k; int success; t = CA_EXT_FUNC_ARGS(x); if (CA_IS_SPECIAL(t)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); L = CA_FIELD(t, ctx); L_len = CA_FIELD_LENGTH(L); success = 1; tgen_map = flint_malloc(L_len * sizeof(slong)); for (j = 0; j < L_len; j++) { for (k = 0; k < len; k++) { if (CA_FIELD_EXT_ELEM(L, j) == CA_FIELD_EXT_ELEM(K, k)) { tgen_map[j] = k; break; } if (k == len - 1) success = 0; } } if (success) { /* u^2 - p/q --> q u^2 - p */ /* u^b - (p/q)^a --> q^a u^b - p^a */ fmpz_mpoly_t p, q, u2; fmpz_mpoly_init(p, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_init(q, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_init(u2, CA_FIELD_MCTX(K, ctx)); if (L_len == 0) /* todo: use CA_IS_QQ when renamed */ { fmpz_mpoly_set_fmpz(p, CA_FMPQ_NUMREF(t), CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_fmpz(q, CA_FMPQ_DENREF(t), CA_FIELD_MCTX(K, ctx)); } else if (CA_FIELD_IS_NF(L)) { fmpz_poly_t pol; fmpz_t den; _nf_elem_get_fmpz_poly_den_shallow(pol, den, CA_NF_ELEM(t), CA_FIELD_NF(L)); fmpz_mpoly_set_gen_fmpz_poly(p, tgen_map[0], pol, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_fmpz(q, den, CA_FIELD_MCTX(K, ctx)); } else { fmpz_mpoly_compose_fmpz_mpoly_gen(p, fmpz_mpoly_q_numref(CA_MPOLY_Q(t)), tgen_map, CA_FIELD_MCTX(L, ctx), CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_compose_fmpz_mpoly_gen(q, fmpz_mpoly_q_denref(CA_MPOLY_Q(t)), tgen_map, CA_FIELD_MCTX(L, ctx), CA_FIELD_MCTX(K, ctx)); } fmpz_mpoly_gen(u2, i, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_pow_ui(u2, u2, b, CA_FIELD_MCTX(K, ctx)); if (a < 0) { fmpz_mpoly_swap(p, q, CA_FIELD_MCTX(K, ctx)); a = -a; } if (a != 1) fmpz_mpoly_pow_ui(q, q, a, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_mul(u2, u2, q, CA_FIELD_MCTX(K, ctx)); if (a != 1) fmpz_mpoly_pow_ui(p, p, a, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_sub(u2, u2, p, CA_FIELD_MCTX(K, ctx)); _ca_field_ideal_insert_clear_mpoly(K, u2, CA_FIELD_MCTX(K, ctx), ctx); /* u2 does not need to be cleared */ fmpz_mpoly_clear(p, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_clear(q, CA_FIELD_MCTX(K, ctx)); } flint_free(tgen_map); } } } ca_field_build_ideal_logs(K, ctx); ca_field_build_ideal_multiplicative(K, ctx); /* ca_field_build_ideal_sin_cos(K, ctx); */ ca_field_build_ideal_erf(K, ctx); ca_field_build_ideal_gamma(K, ctx); if (ctx->options[CA_OPT_USE_GROEBNER]) { slong i; int want_groebner; want_groebner = 1; for (i = 0; i < CA_FIELD_IDEAL_LENGTH(K); i++) { if (fmpz_mpoly_total_degree_si(CA_FIELD_IDEAL_ELEM(K, i), CA_FIELD_MCTX(K, ctx)) > ctx->options[CA_OPT_QQBAR_DEG_LIMIT]) { want_groebner = 0; break; } } if (want_groebner && CA_FIELD_IDEAL(K)->length > 0) { if (ctx->options[CA_OPT_VERBOSE]) { flint_printf("Attempt to compute Groebner basis for:\n "); fmpz_mpoly_vec_print(CA_FIELD_IDEAL(K), CA_FIELD_MCTX(K, ctx)); flint_printf("\n\n"); } /* Consider autoreduction as a preprocessing step. This is not necessarily a win, because the vector is usually nearly autoreduced by construction. */ if (0) { slong before, after; before = CA_FIELD_IDEAL_LENGTH(K); fmpz_mpoly_vec_autoreduction(CA_FIELD_IDEAL(K), CA_FIELD_IDEAL(K), CA_FIELD_MCTX(K, ctx)); after = CA_FIELD_IDEAL_LENGTH(K); if (before > 4) flint_printf("before, after: %wd %wd\n", before, after); } if (fmpz_mpoly_buchberger_naive_with_limits(CA_FIELD_IDEAL(K), CA_FIELD_IDEAL(K), ctx->options[CA_OPT_GROEBNER_LENGTH_LIMIT], ctx->options[CA_OPT_GROEBNER_POLY_LENGTH_LIMIT], ctx->options[CA_OPT_GROEBNER_POLY_BITS_LIMIT], CA_FIELD_MCTX(K, ctx))) { fmpz_mpoly_vec_autoreduction_groebner(CA_FIELD_IDEAL(K), CA_FIELD_IDEAL(K), CA_FIELD_MCTX(K, ctx)); if (ctx->options[CA_OPT_VERBOSE]) { flint_printf("Computed Groebner basis:\n "); fmpz_mpoly_vec_print(CA_FIELD_IDEAL(K), CA_FIELD_MCTX(K, ctx)); flint_printf("\n\n"); } } else { if (ctx->options[CA_OPT_VERBOSE]) { flint_printf("WARNING: Failed to compute a Groebner basis\n"); flint_printf("Current ideal:\n "); fmpz_mpoly_vec_print(CA_FIELD_IDEAL(K), CA_FIELD_MCTX(K, ctx)); flint_printf("\n\n"); } } } } } flint-3.1.3/src/ca_field/build_ideal_erf.c000066400000000000000000000311041461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" void _ca_field_ideal_insert_clear_mpoly(ca_field_t K, fmpz_mpoly_t poly, fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx); /* todo: optimize */ truth_t ca_check_equal_neg(const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_t t; truth_t res; ca_init(t, ctx); ca_neg(t, y, ctx); res = ca_check_equal(x, t, ctx); ca_clear(t, ctx); return res; } /* set a*x_a + b*x_b + c */ void fmpz_mpoly_set_linear_three_term_si(fmpz_mpoly_t poly, slong a, slong xa, slong b, slong xb, slong c, const fmpz_mpoly_ctx_t ctx) { ulong * exp; exp = flint_calloc(ctx->minfo->nvars, sizeof(ulong)); if (xa == xb) { flint_throw(FLINT_ERROR, "fmpz_mpoly_set_linear_three_term_si\n"); } fmpz_mpoly_set_si(poly, c, ctx); exp[xa] = 1; fmpz_mpoly_set_coeff_si_ui(poly, a, exp, ctx); exp[xa] = 0; exp[xb] = 1; fmpz_mpoly_set_coeff_si_ui(poly, b, exp, ctx); flint_free(exp); } /* set a*x_a*x_a2 + b*x_b + c */ void fmpz_mpoly_set_linear2_three_term_si(fmpz_mpoly_t poly, slong a, slong xa, slong xa2, slong b, slong xb, slong c, const fmpz_mpoly_ctx_t ctx) { ulong * exp; exp = flint_calloc(ctx->minfo->nvars, sizeof(ulong)); if (xa == xb || xa == xa2) { flint_throw(FLINT_ERROR, "fmpz_mpoly_set_linear2_three_term_si\n"); } fmpz_mpoly_set_si(poly, c, ctx); exp[xa] = 1; exp[xa2] = 1; fmpz_mpoly_set_coeff_si_ui(poly, a, exp, ctx); exp[xa] = 0; exp[xa2] = 0; exp[xb] = 1; fmpz_mpoly_set_coeff_si_ui(poly, b, exp, ctx); flint_free(exp); } /* Set the term c * x_var^x_exp */ void fmpz_mpoly_set_coeff_si_x(fmpz_mpoly_t poly, slong c, slong x_var, slong x_exp, const fmpz_mpoly_ctx_t ctx) { ulong * exp; slong i, len; TMP_INIT; len = ctx->minfo->nvars; TMP_START; exp = TMP_ALLOC(len * sizeof(ulong)); for (i = 0; i < len; i++) exp[i] = 0; exp[x_var] = x_exp; fmpz_mpoly_set_coeff_si_ui(poly, c, exp, ctx); TMP_END; } void fmpz_mpoly_set_coeff_si_xy(fmpz_mpoly_t poly, slong c, slong x_var, ulong x_exp, slong y_var, ulong y_exp, const fmpz_mpoly_ctx_t ctx) { ulong * exp; slong i, len; TMP_INIT; len = ctx->minfo->nvars; TMP_START; exp = TMP_ALLOC(len * sizeof(ulong)); for (i = 0; i < len; i++) exp[i] = 0; exp[x_var] = x_exp; exp[y_var] = y_exp; fmpz_mpoly_set_coeff_si_ui(poly, c, exp, ctx); TMP_END; } static void ideal_mixed_erfi(ca_field_t K, slong i, slong j, int have_i, slong index_i, ca_ctx_t ctx) { calcium_func_code Fi; ca_t ix; ca_ptr x, y; fmpz_mpoly_t poly; const fmpz_mpoly_ctx_struct * mctx = CA_FIELD_MCTX(K, ctx); x = CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, i)); y = CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, j)); Fi = CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)); ca_init(ix, ctx); ca_i(ix, ctx); ca_mul(ix, ix, x, ctx); if (ca_check_equal(ix, y, ctx) == T_TRUE) { if (have_i) { fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == CA_Erf) { /* erf(x) + i*erfi(i*x) */ fmpz_mpoly_set_coeff_si_x(poly, 1, i, 1, mctx); fmpz_mpoly_set_coeff_si_xy(poly, 1, j, 1, index_i, 1, mctx); } else { /* erfc(x) - i*erfi(i*x) - 1 */ fmpz_mpoly_set_si(poly, -1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, i, 1, mctx); fmpz_mpoly_set_coeff_si_xy(poly, -1, j, 1, index_i, 1, mctx); } _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } if (have_i) { fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == CA_Erf) { /* i*erf(x) - erfi(i*x) */ fmpz_mpoly_set_coeff_si_xy(poly, 1, i, 1, index_i, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, -1, j, 1, mctx); } else { /* i*erfc(x) + erfi(i*x) - i */ fmpz_mpoly_set_coeff_si_xy(poly, 1, i, 1, index_i, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, j, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, -1, index_i, 1, mctx); } _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == CA_Erf) { /* erf(x)^2 + erfi(i*x)^2 = 0 */ fmpz_mpoly_set_coeff_si_x(poly, 1, i, 2, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, j, 2, mctx); } else { /* erfc(x)^2 - 2*erfc(x) + erfi(i*x)**2 + 1 */ fmpz_mpoly_set_si(poly, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, i, 2, mctx); fmpz_mpoly_set_coeff_si_x(poly, -2, i, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, j, 2, mctx); } _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } else if (ca_check_equal_neg(ix, y, ctx) == T_TRUE) { if (have_i) { fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == CA_Erf) { /* erf(x) - i*erfi(-i*x) */ fmpz_mpoly_set_coeff_si_x(poly, 1, i, 1, mctx); fmpz_mpoly_set_coeff_si_xy(poly, -1, j, 1, index_i, 1, mctx); } else { /* erfc(x) + i*erfi(-i*x) - 1 */ fmpz_mpoly_set_si(poly, -1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, i, 1, mctx); fmpz_mpoly_set_coeff_si_xy(poly, 1, j, 1, index_i, 1, mctx); } _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } if (have_i) { fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == CA_Erf) { /* i*erf(x) + erfi(-i*x) */ fmpz_mpoly_set_coeff_si_xy(poly, 1, i, 1, index_i, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, j, 1, mctx); } else { /* i*erfc(x) - erfi(-i*x) - i */ fmpz_mpoly_set_coeff_si_xy(poly, 1, i, 1, index_i, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, -1, j, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, -1, index_i, 1, mctx); } _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == CA_Erf) { /* erf(x)^2 + erfi(-i*x)^2 = 0 */ fmpz_mpoly_set_coeff_si_x(poly, 1, i, 2, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, j, 2, mctx); } else { /* erfc(x)^2 - 2*erfc(x) + erfi(-i*x)**2 + 1 */ fmpz_mpoly_set_si(poly, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, i, 2, mctx); fmpz_mpoly_set_coeff_si_x(poly, -2, i, 1, mctx); fmpz_mpoly_set_coeff_si_x(poly, 1, j, 2, mctx); } _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } ca_clear(ix, ctx); } /* erf(x) - erf(x) = 0 erfc(x) - erfc(x) = 0 erfi(x) - erfi(x) = 0 erf(x) + erfc(x) - 1 = 0 erf(x) + erf(-x) = 0 erfc(x) + erfc(-x) - 2 = 0 erfi(x) + erfi(-x) = 0 erf(x) - erfc(-x) + 1 = 0 erfc(x) - erf(-x) - 1 = 0 erf(x) + i*erfi(i*x) = 0 erf(x) - i*erfi(-i*x) = 0 erfc(x) - i*erfi(i*x) - 1 = 0 erfc(x) + i*erfi(-i*x) - 1 = 0 */ void ca_field_build_ideal_erf(ca_field_t K, ca_ctx_t ctx) { slong i, j, len, num_erf, index_i; calcium_func_code Fi, Fj; int have_i; len = CA_FIELD_LENGTH(K); if (len < 2) return; index_i = 0; have_i = 0; num_erf = 0; for (i = 0; i < len; i++) { Fi = CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)); if (Fi == CA_Erf || Fi == CA_Erfc || Fi == CA_Erfi) { num_erf++; } else if (CA_FIELD_EXT_ELEM(K, i) == CA_FIELD_EXT_ELEM(ctx->field_qq_i, 0)) { have_i = 1; index_i = i; } } if (num_erf >= 2) { for (i = 0; i < len; i++) { Fi = CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)); if (Fi == CA_Erf || Fi == CA_Erfc || Fi == CA_Erfi) { for (j = i + 1; j < len; j++) { Fj = CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, j)); if (Fj == CA_Erf || Fj == CA_Erfc || Fj == CA_Erfi) { if ((Fj == CA_Erfi && (Fi == CA_Erf || Fi == CA_Erfc))) { ideal_mixed_erfi(K, i, j, have_i, index_i, ctx); continue; } if ((Fi == CA_Erfi && (Fj == CA_Erf || Fj == CA_Erfc))) { ideal_mixed_erfi(K, j, i, have_i, index_i, ctx); continue; } if (Fi == Fj || (Fi == CA_Erf && Fj == CA_Erfc) || (Fi == CA_Erfc && Fj == CA_Erf)) { if (ca_check_equal(CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, i)), CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, j)), ctx) == T_TRUE) { /* erf(x) - erf(x) = 0 erfc(x) - erfc(x) = 0 erfi(x) - erfi(x) = 0 erf(x) + erfc(x) - 1 = 0 */ fmpz_mpoly_t poly; fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == Fj) fmpz_mpoly_set_linear_three_term_si(poly, 1, i, -1, j, 0, CA_FIELD_MCTX(K, ctx)); else fmpz_mpoly_set_linear_three_term_si(poly, 1, i, 1, j, -1, CA_FIELD_MCTX(K, ctx)); _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } else if (ca_check_equal_neg(CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, i)), CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, j)), ctx) == T_TRUE) { /* erf(x) + erf(-x) = 0 erfc(x) + erfc(-x) - 2 = 0 erfi(x) + erfi(-x) = 0 erf(x) - erfc(-x) + 1 = 0 erfc(x) - erf(-x) - 1 = 0 */ fmpz_mpoly_t poly; fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); if (Fi == Fj) { if (Fi == CA_Erfc) fmpz_mpoly_set_linear_three_term_si(poly, 1, i, 1, j, -2, CA_FIELD_MCTX(K, ctx)); else fmpz_mpoly_set_linear_three_term_si(poly, 1, i, 1, j, 0, CA_FIELD_MCTX(K, ctx)); } else { if (Fi == CA_Erf) fmpz_mpoly_set_linear_three_term_si(poly, 1, i, -1, j, 1, CA_FIELD_MCTX(K, ctx)); else fmpz_mpoly_set_linear_three_term_si(poly, 1, i, -1, j, -1, CA_FIELD_MCTX(K, ctx)); } _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } } } } } } } } flint-3.1.3/src/ca_field/build_ideal_gamma.c000066400000000000000000000201241461254215100207120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" #include "fmpz_mpoly.h" void _ca_field_ideal_insert_clear_mpoly(ca_field_t K, fmpz_mpoly_t poly, fmpz_mpoly_ctx_t mctx, ca_ctx_t ctx); void _nf_elem_get_fmpz_poly_den_shallow(fmpz_poly_t pol, fmpz_t den, const nf_elem_t a, const nf_t nf); void fmpz_mpoly_set_coeff_si_x(fmpz_mpoly_t poly, slong c, slong x_var, slong x_exp, const fmpz_mpoly_ctx_t ctx); void ca_field_build_ideal_gamma(ca_field_t K, ca_ctx_t ctx) { calcium_func_code Fi, Fj; slong i, j, len, num_gamma; len = CA_FIELD_LENGTH(K); if (len < 2) return; num_gamma = 0; for (i = 0; i < len; i++) { Fi = CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)); if (Fi == CA_Gamma) { num_gamma++; } } if (num_gamma < 2) return; for (i = 0; i < len; i++) { Fi = CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, i)); if (Fi == CA_Gamma) { for (j = i + 1; j < len; j++) { Fj = CA_EXT_HEAD(CA_FIELD_EXT_ELEM(K, j)); if (Fj == CA_Gamma) { ca_ptr xi, xj; ca_t t, u; fmpz_t N; slong n; xi = CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, i)); xj = CA_EXT_FUNC_ARGS(CA_FIELD_EXT_ELEM(K, j)); ca_init(t, ctx); ca_init(u, ctx); fmpz_init(N); ca_sub(t, xi, xj, ctx); if (ca_get_fmpz(N, t, ctx) && fmpz_cmp_si(N, -10) >= 0 && fmpz_cmp_si(N, 10) <= 0) { n = fmpz_get_si(N); if (n == 0) { fmpz_mpoly_t poly; fmpz_mpoly_init(poly, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_coeff_si_x(poly, 1, i, 1, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_coeff_si_x(poly, -1, j, 1, CA_FIELD_MCTX(K, ctx)); _ca_field_ideal_insert_clear_mpoly(K, poly, CA_FIELD_MCTX(K, ctx), ctx); } else { ca_field_struct * L; /* Field of t */ slong L_len; slong * tgen_map; slong k, m; int success; /* gamma(x+3) = (x+2)*(x+1)*x * gamma(x) */ /* (x-1)*(x-2)*(x-3) * gamma(x-3) = gamma(x) */ if (n > 0) { ca_set(t, xj, ctx); for (k = 1; k < n; k++) { ca_add_ui(u, xj, k, ctx); ca_mul(t, t, u, ctx); } } else { ca_sub_ui(t, xj, 1, ctx); for (k = 1; k < (-n); k++) { ca_sub_ui(u, xj, k + 1, ctx); ca_mul(t, t, u, ctx); } } L = CA_FIELD(t, ctx); L_len = CA_FIELD_LENGTH(L); success = 1; tgen_map = flint_malloc(L_len * sizeof(slong)); for (m = 0; m < L_len; m++) { for (k = 0; k < len; k++) { if (CA_FIELD_EXT_ELEM(L, m) == CA_FIELD_EXT_ELEM(K, k)) { tgen_map[m] = k; break; } if (k == len - 1) success = 0; } } if (success) { fmpz_mpoly_t p, q, pxi, pxj; fmpz_mpoly_init(p, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_init(q, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_init(pxi, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_init(pxj, CA_FIELD_MCTX(K, ctx)); /* todo: factor out */ if (L_len == 0) { fmpz_mpoly_set_fmpz(p, CA_FMPQ_NUMREF(t), CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_fmpz(q, CA_FMPQ_DENREF(t), CA_FIELD_MCTX(K, ctx)); } else if (CA_FIELD_IS_NF(L)) { fmpz_poly_t pol; fmpz_t den; _nf_elem_get_fmpz_poly_den_shallow(pol, den, CA_NF_ELEM(t), CA_FIELD_NF(L)); fmpz_mpoly_set_gen_fmpz_poly(p, tgen_map[0], pol, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_set_fmpz(q, den, CA_FIELD_MCTX(K, ctx)); } else { fmpz_mpoly_compose_fmpz_mpoly_gen(p, fmpz_mpoly_q_numref(CA_MPOLY_Q(t)), tgen_map, CA_FIELD_MCTX(L, ctx), CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_compose_fmpz_mpoly_gen(q, fmpz_mpoly_q_denref(CA_MPOLY_Q(t)), tgen_map, CA_FIELD_MCTX(L, ctx), CA_FIELD_MCTX(K, ctx)); } fmpz_mpoly_gen(pxi, i, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_gen(pxj, j, CA_FIELD_MCTX(K, ctx)); if (n < 0) fmpz_mpoly_swap(p, q, CA_FIELD_MCTX(K, ctx)); /* pxi = (p/q) * pxj */ /* q * pxi - p * pxj = 0*/ fmpz_mpoly_mul(q, q, pxi, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_mul(p, p, pxj, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_sub(q, q, p, CA_FIELD_MCTX(K, ctx)); _ca_field_ideal_insert_clear_mpoly(K, q, CA_FIELD_MCTX(K, ctx), ctx); fmpz_mpoly_clear(p, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_clear(pxi, CA_FIELD_MCTX(K, ctx)); fmpz_mpoly_clear(pxj, CA_FIELD_MCTX(K, ctx)); } flint_free(tgen_map); } } ca_clear(t, ctx); ca_clear(u, ctx); fmpz_clear(N); } } } } } flint-3.1.3/src/ca_field/cache_clear.c000066400000000000000000000013151461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_field.h" void ca_field_cache_clear(ca_field_cache_t cache, ca_ctx_t ctx) { slong i; for (i = 0; i < cache->length; i++) ca_field_clear(cache->items[i], ctx); for (i = 0; i < cache->alloc; i++) flint_free(cache->items[i]); flint_free(cache->items); flint_free(cache->hash_table); } flint-3.1.3/src/ca_field/cache_init.c000066400000000000000000000014161461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_field.h" #define INITIAL_HASH_SIZE 16 void ca_field_cache_init(ca_field_cache_t cache, ca_ctx_t ctx) { slong i; cache->items = NULL; cache->length = 0; cache->alloc = 0; cache->hash_size = INITIAL_HASH_SIZE; cache->hash_table = flint_malloc(sizeof(slong) * INITIAL_HASH_SIZE); for (i = 0; i < INITIAL_HASH_SIZE; i++) cache->hash_table[i] = -1; } flint-3.1.3/src/ca_field/cache_insert.c000066400000000000000000000111431461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_ext.h" #include "ca_field.h" ca_field_ptr ca_field_cache_lookup_qqbar(ca_field_cache_t cache, const qqbar_t x, ca_ctx_t ctx) { ulong xhash; ca_field_ptr K; slong i, loc; xhash = qqbar_hash(x); loc = xhash % ((ulong) cache->hash_size); for (i = 0; i < cache->hash_size; i++) { /* not found */ if (cache->hash_table[loc] == -1) return NULL; K = cache->items[cache->hash_table[loc]]; /* found */ if (CA_FIELD_IS_NF(K) && qqbar_equal(x, CA_FIELD_NF_QQBAR(K))) return K; loc++; if (loc == cache->hash_size) loc = 0; } /* cannot happen */ flint_throw(FLINT_ERROR, "(%s)\n", __func__); } ulong _ca_field_hash(ca_ext_struct ** ext, slong len, ca_ctx_t ctx) { ulong s; slong i; s = 0; for (i = 0; i < len; i++) s = s * CA_FIELD_HASH_C + CA_EXT_HASH(ext[i]); return s; } ulong ca_field_hash(const ca_field_t K, ca_ctx_t ctx) { return _ca_field_hash(K->ext, K->length, ctx); } static int _ca_field_equal_ext(const ca_field_t K, ca_ext_struct ** x, slong len, ca_ctx_t ctx) { slong i; if (len != CA_FIELD_LENGTH(K)) return 0; for (i = 0; i < len; i++) if (CA_FIELD_EXT_ELEM(K, i) != x[i]) return 0; return 1; } void ca_field_init_set_ext(ca_field_t K, ca_ext_struct ** ext, slong len, ca_ctx_t ctx) { if (len == 0) { ca_field_init_qq(K, ctx); } else if (len == 1 && CA_EXT_IS_QQBAR(ext[0])) { CA_FIELD_LENGTH(K) = 1; CA_FIELD_EXT(K) = flint_malloc(sizeof(ca_ext_ptr)); CA_FIELD_EXT_ELEM(K, 0) = ext[0]; CA_FIELD_IDEAL_P(K) = NULL; CA_FIELD_IDEAL_LENGTH(K) = -1; CA_FIELD_IDEAL_ALLOC(K) = 0; CA_FIELD_HASH(K) = CA_EXT_HASH(ext[0]); } else { slong i; ca_field_init_multi(K, len, ctx); for (i = 0; i < len; i++) ca_field_set_ext(K, i, ext[i], ctx); } } ca_field_ptr ca_field_cache_insert_ext(ca_field_cache_t cache, ca_ext_struct ** x, slong length, ca_ctx_t ctx) { ulong xhash; slong i, loc; xhash = _ca_field_hash(x, length, ctx); /* make room for inserting entry if needed */ if (cache->length == cache->alloc) { slong new_alloc; new_alloc = FLINT_MAX(1, cache->alloc * 2); cache->items = flint_realloc(cache->items, sizeof(ca_field_struct *) * new_alloc); for (i = cache->alloc; i < new_alloc; i++) cache->items[i] = flint_malloc(sizeof(ca_field_struct)); cache->alloc = new_alloc; } /* rehash if needed */ if (cache->length >= 0.5 * cache->hash_size) { slong new_size, j; slong * new_table; ulong thash; new_size = cache->hash_size * 2; new_table = flint_malloc(sizeof(slong) * new_size); for (i = 0; i < new_size; i++) new_table[i] = -1; for (i = 0; i < cache->length; i++) { thash = ca_field_hash(cache->items[i], ctx); j = thash % new_size; while (new_table[j] != -1) { j++; if (j == new_size) j = 0; } new_table[j] = i; } flint_free(cache->hash_table); cache->hash_size = new_size; cache->hash_table = new_table; } loc = xhash % ((ulong) cache->hash_size); for (i = 0; i < cache->hash_size; i++) { /* not found, so insert */ if (cache->hash_table[loc] == -1) { ca_field_ptr res; ca_field_init_set_ext(cache->items[cache->length], x, length, ctx); cache->hash_table[loc] = cache->length; cache->length++; /* save pointer; build_ideal can resize the cache */ res = cache->items[cache->length - 1]; ca_field_build_ideal(res, ctx); return res; } /* found */ if (_ca_field_equal_ext(cache->items[cache->hash_table[loc]], x, length, ctx)) return cache->items[cache->hash_table[loc]]; loc++; if (loc == cache->hash_size) loc = 0; } /* cannot happen */ flint_throw(FLINT_ERROR, "(%s)\n", __func__); } flint-3.1.3/src/ca_field/clear.c000066400000000000000000000012671461254215100164100ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_field.h" void ca_field_clear(ca_field_t K, ca_ctx_t ctx) { slong length; length = CA_FIELD_LENGTH(K); if (length == 0) return; flint_free(CA_FIELD_EXT(K)); if (CA_FIELD_IS_NF(K)) return; fmpz_mpoly_vec_clear(CA_FIELD_IDEAL(K), CA_FIELD_MCTX(K, ctx)); } flint-3.1.3/src/ca_field/cmp.c000066400000000000000000000112641461254215100160770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" static int _fmpz_poly_compare_abslex(const fmpz * a, const fmpz * b, slong len) { slong i; int c; for (i = len - 1; i >= 0; i--) { if (!fmpz_equal(a + i, b + i)) { c = fmpz_cmpabs(a + i, b + i); if (c != 0) return c; return fmpz_sgn(a + i); } } return 0; } static int _nf_elem_cmp(const nf_elem_t x, const nf_elem_t y, const nf_t nf) { int c; if (nf->flag & NF_LINEAR) { return _fmpq_cmp(LNF_ELEM_NUMREF(x), LNF_ELEM_DENREF(x), LNF_ELEM_NUMREF(y), LNF_ELEM_DENREF(y)); } else if (nf->flag & NF_QUADRATIC) { c = _fmpz_poly_compare_abslex(QNF_ELEM_NUMREF(x), QNF_ELEM_NUMREF(y), 2); if (c != 0) return c; return fmpz_cmp(QNF_ELEM_DENREF(x), QNF_ELEM_DENREF(y)); } else { if (NF_ELEM(x)->length != NF_ELEM(y)->length) return (NF_ELEM(x)->length < NF_ELEM(y)->length) ? -1 : 1; c = _fmpz_poly_compare_abslex(NF_ELEM(x)->coeffs, NF_ELEM(y)->coeffs, NF_ELEM(x)->length); if (c != 0) return c; return fmpz_cmp(NF_ELEM_DENREF(x), NF_ELEM_DENREF(y)); } } /* todo: better algorithm extending fmpz_mpoly_cmp */ static int _fmpz_mpoly_cmp2(const fmpz_mpoly_t x, const fmpz_mpoly_t y, fmpz_mpoly_ctx_t ctx) { slong lenx, leny, nvars; mp_limb_t expx, expy; slong i, j; int c; lenx = x->length; leny = y->length; nvars = ctx->minfo->nvars; if (lenx != leny) return (lenx < leny) ? -1 : 1; for (i = 0; i < lenx; i++) { for (j = 0; j < nvars; j++) { expx = fmpz_mpoly_get_term_var_exp_ui(x, i, j, ctx); expy = fmpz_mpoly_get_term_var_exp_ui(y, i, j, ctx); if (expx != expy) return (expx < expy) ? -1 : 1; } } for (i = 0; i < lenx; i++) { c = fmpz_cmp(x->coeffs + i, y->coeffs + i); if (c != 0) return c; } return 0; } int _fmpz_mpoly_q_cmp(const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, fmpz_mpoly_ctx_t ctx) { int c; c = _fmpz_mpoly_cmp2(fmpz_mpoly_q_denref(x), fmpz_mpoly_q_denref(y), ctx); if (c != 0) return c; return _fmpz_mpoly_cmp2(fmpz_mpoly_q_numref(x), fmpz_mpoly_q_numref(y), ctx); } static inline slong si_sign(slong x) { if (x != 0) x = (x > 0) ? 1 : -1; return x; } int ca_cmp_repr(const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_field_srcptr xfield, yfield; if (CA_IS_SPECIAL(x) || CA_IS_SPECIAL(y)) { flint_throw(FLINT_ERROR, "ca_cmp_repr: not implemented for special values\n"); } xfield = CA_FIELD(x, ctx); yfield = CA_FIELD(y, ctx); if (xfield != yfield) return ca_field_cmp(xfield, yfield, ctx); if (CA_FIELD_IS_QQ(xfield)) { return si_sign(fmpq_cmp(CA_FMPQ(x), CA_FMPQ(y))); } else if (CA_FIELD_IS_NF(xfield)) { return si_sign(_nf_elem_cmp(CA_NF_ELEM(x), CA_NF_ELEM(y), CA_FIELD_NF(xfield))); } else { return si_sign(_fmpz_mpoly_q_cmp(CA_MPOLY_Q(x), CA_MPOLY_Q(y), CA_FIELD_MCTX(xfield, ctx))); } } slong ca_field_depth(const ca_field_t K, ca_ctx_t ctx); slong ca_depth(const ca_t x, ca_ctx_t ctx) { if (CA_IS_SPECIAL(x)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); return ca_field_depth(CA_FIELD(x, ctx), ctx); } static slong ca_ext_depth(const ca_ext_t x, ca_ctx_t ctx) { return CA_EXT_DEPTH(x); } slong ca_field_depth(const ca_field_t K, ca_ctx_t ctx) { if (CA_FIELD_LENGTH(K) >= 1) { slong i, depth, depth_i; depth = 0; for (i = 0; i < CA_FIELD_LENGTH(K); i++) { depth_i = ca_ext_depth(CA_FIELD_EXT_ELEM(K, i), ctx); depth = FLINT_MAX(depth, depth_i); } return depth + 1; } return 0; } /* todo: sort on depth? */ int ca_field_cmp(const ca_field_t K1, const ca_field_t K2, ca_ctx_t ctx) { slong i, len1, len2; len1 = CA_FIELD_LENGTH(K1); len2 = CA_FIELD_LENGTH(K2); if (len1 != len2) return (len1 < len2) ? -1 : 1; for (i = 0; i < len1; i++) { int c = ca_ext_cmp_repr(CA_FIELD_EXT_ELEM(K1, i), CA_FIELD_EXT_ELEM(K2, i), ctx); if (c != 0) return c; } return 0; } flint-3.1.3/src/ca_field/init.c000066400000000000000000000074351461254215100162700ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" void _ca_ctx_init_mctx(ca_ctx_t ctx, slong len) { while (ctx->mctx_len < len) { slong i, alloc; alloc = FLINT_MAX(1, 2 * ctx->mctx_len); ctx->mctx = flint_realloc(ctx->mctx, alloc * sizeof(fmpz_mpoly_ctx_struct *)); for (i = ctx->mctx_len; i < alloc; i++) { ctx->mctx[i] = flint_malloc(sizeof(fmpz_mpoly_ctx_struct)); fmpz_mpoly_ctx_init(ctx->mctx[i], i + 1, ctx->options[CA_OPT_MPOLY_ORD]); } ctx->mctx_len = alloc; } } void ca_field_init_qq(ca_field_t K, ca_ctx_t ctx) { CA_FIELD_LENGTH(K) = 0; CA_FIELD_EXT(K) = NULL; CA_FIELD_IDEAL_P(K) = NULL; CA_FIELD_IDEAL_LENGTH(K) = 0; CA_FIELD_IDEAL_ALLOC(K) = 0; CA_FIELD_HASH(K) = 0; } void ca_field_init_nf(ca_field_t K, const qqbar_t x, ca_ctx_t ctx) { ca_ext_ptr ext; ca_ext_t tmp; /* todo: avoid unnecessary work (especially the nf_t init) */ ca_ext_init_qqbar(tmp, x, ctx); ext = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), tmp, ctx); ca_ext_clear(tmp, ctx); CA_FIELD_LENGTH(K) = 1; CA_FIELD_EXT(K) = flint_malloc(sizeof(ca_ext_ptr)); CA_FIELD_EXT_ELEM(K, 0) = ext; CA_FIELD_IDEAL_P(K) = NULL; CA_FIELD_IDEAL_LENGTH(K) = -1; CA_FIELD_IDEAL_ALLOC(K) = 0; CA_FIELD_HASH(K) = CA_EXT_HASH(ext); } void ca_field_init_const(ca_field_t K, calcium_func_code func, ca_ctx_t ctx) { ca_ext_ptr ext; ca_ext_t tmp; /* todo: avoid unnecessary work */ ca_ext_init_const(tmp, func, ctx); ext = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), tmp, ctx); ca_ext_clear(tmp, ctx); CA_FIELD_LENGTH(K) = 1; CA_FIELD_EXT(K) = flint_malloc(sizeof(ca_ext_ptr)); CA_FIELD_EXT_ELEM(K, 0) = ext; CA_FIELD_IDEAL_P(K) = NULL; CA_FIELD_IDEAL_LENGTH(K) = 0; CA_FIELD_IDEAL_ALLOC(K) = 0; CA_FIELD_HASH(K) = CA_EXT_HASH(ext); _ca_ctx_init_mctx(ctx, 1); } void ca_field_init_fx(ca_field_t K, calcium_func_code func, const ca_t x, ca_ctx_t ctx) { ca_ext_ptr ext; ca_ext_t tmp; /* todo: avoid unnecessary work */ ca_ext_init_fx(tmp, func, x, ctx); ext = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), tmp, ctx); ca_ext_clear(tmp, ctx); CA_FIELD_LENGTH(K) = 1; CA_FIELD_EXT(K) = flint_malloc(sizeof(ca_ext_ptr)); CA_FIELD_EXT_ELEM(K, 0) = ext; CA_FIELD_IDEAL_P(K) = NULL; CA_FIELD_IDEAL_LENGTH(K) = 0; CA_FIELD_IDEAL_ALLOC(K) = 0; CA_FIELD_HASH(K) = CA_EXT_HASH(ext); _ca_ctx_init_mctx(ctx, 1); } void ca_field_init_fxy(ca_field_t K, calcium_func_code func, const ca_t x, const ca_t y, ca_ctx_t ctx) { ca_ext_ptr ext; ca_ext_t tmp; /* todo: avoid unnecessary work */ ca_ext_init_fxy(tmp, func, x, y, ctx); ext = ca_ext_cache_insert(CA_CTX_EXT_CACHE(ctx), tmp, ctx); ca_ext_clear(tmp, ctx); CA_FIELD_LENGTH(K) = 1; CA_FIELD_EXT(K) = flint_malloc(sizeof(ca_ext_ptr)); CA_FIELD_EXT_ELEM(K, 0) = ext; CA_FIELD_IDEAL_P(K) = NULL; CA_FIELD_IDEAL_LENGTH(K) = 0; CA_FIELD_IDEAL_ALLOC(K) = 0; CA_FIELD_HASH(K) = CA_EXT_HASH(ext); _ca_ctx_init_mctx(ctx, 2); } void ca_field_init_multi(ca_field_t K, slong len, ca_ctx_t ctx) { CA_FIELD_LENGTH(K) = len; CA_FIELD_EXT(K) = flint_malloc(len * sizeof(ca_ext_ptr)); CA_FIELD_IDEAL_P(K) = NULL; CA_FIELD_IDEAL_LENGTH(K) = 0; CA_FIELD_IDEAL_ALLOC(K) = 0; CA_FIELD_HASH(K) = 0; _ca_ctx_init_mctx(ctx, len); } flint-3.1.3/src/ca_field/print.c000066400000000000000000000026171461254215100164560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" void ca_field_print(const ca_field_t K, ca_ctx_t ctx) { slong i, len, ideal_len; flint_printf("QQ"); len = CA_FIELD_LENGTH(K); if (len == 0) return; flint_printf("("); for (i = 0; i < len; i++) { flint_printf("x%wd", i + 1); if (i < len - 1) flint_printf(", "); } flint_printf(") where {"); for (i = 0; i < len; i++) { flint_printf("x%wd = ", i + 1); ca_ext_print(CA_FIELD_EXT_ELEM(K, i), ctx); flint_printf(""); if (i < len - 1) flint_printf(", "); } flint_printf("}"); ideal_len = CA_FIELD_IDEAL_LENGTH(K); if (ideal_len > 0) { flint_printf(" with ideal {"); for (i = 0; i < ideal_len; i++) { fmpz_mpoly_print_pretty(CA_FIELD_IDEAL_ELEM(K, i), NULL, CA_FIELD_MCTX(K, ctx)); if (i < ideal_len - 1) flint_printf(", "); } flint_printf("}"); } } flint-3.1.3/src/ca_field/set_ext.c000066400000000000000000000011731461254215100167710ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca.h" #include "ca_ext.h" #include "ca_field.h" void ca_field_set_ext(ca_field_t K, slong i, ca_ext_srcptr x, ca_ctx_t ctx) { CA_FIELD_EXT_ELEM(K, i) = (ca_ext_ptr) x; CA_FIELD_HASH(K) = CA_FIELD_HASH(K) * 100003 + CA_EXT_HASH(x); } flint-3.1.3/src/ca_field/test/000077500000000000000000000000001461254215100161275ustar00rootroot00000000000000flint-3.1.3/src/ca_field/test/main.c000066400000000000000000000014131461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-cache_insert.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(ca_field_cache_insert) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/ca_field/test/t-cache_insert.c000066400000000000000000000055321461254215100211700ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca.h" #include "ca_ext.h" #include "ca_field.h" static int _ca_field_equal_ext(const ca_field_t K, ca_ext_struct ** x, slong len, ca_ctx_t ctx) { slong i; if (len != CA_FIELD_LENGTH(K)) return 0; for (i = 0; i < len; i++) if (CA_FIELD_EXT_ELEM(K, i) != x[i]) return 0; return 1; } TEST_FUNCTION_START(ca_field_cache_insert, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_ext_struct ** ext; ca_ext_struct * all_ext; ca_field_cache_t cache; ca_field_struct *K, *K2; qqbar_t x; ca_t v; slong i, j, steps, len, ext_len; ca_ctx_init(ctx); qqbar_init(x); ca_init(v, ctx); ext_len = 1 + n_randint(state, 10); steps = n_randint(state, 100); all_ext = flint_malloc(sizeof(ca_ext_struct) * ext_len); for (j = 0; j < ext_len; j++) { if (n_randint(state, 10) != 0) { ca_set_ui(v, j + 2, ctx); ca_ext_init_fx(all_ext + j, CA_RiemannZeta, v, ctx); } else { qqbar_set_ui(x, j); ca_ext_init_qqbar(all_ext + j, x, ctx); } } ca_field_cache_init(cache, ctx); for (i = 0; i < steps; i++) { len = n_randint(state, 10); ext = flint_malloc(len * sizeof(ca_ext_struct *)); for (j = 0; j < len; j++) ext[j] = all_ext + n_randint(state, ext_len); K = ca_field_cache_insert_ext(cache, ext, len, ctx); K2 = ca_field_cache_insert_ext(cache, ext, len, ctx); if (!_ca_field_equal_ext(K, ext, len, ctx) || K != K2) { flint_printf("FAIL\n\n"); flint_printf("K = "); ca_field_print(K, ctx); flint_printf("\n\n"); flint_printf("ext = \n\n"); for (j = 0; j < len; j++) { ca_ext_print(ext[j], ctx); flint_printf("\n\n"); } flint_abort(); } flint_free(ext); } for (j = 0; j < ext_len; j++) ca_ext_clear(all_ext + j, ctx); flint_free(all_ext); ca_field_cache_clear(cache, ctx); ca_clear(v, ctx); ca_ctx_clear(ctx); qqbar_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat.h000066400000000000000000000274061461254215100150300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CA_MAT_H #define CA_MAT_H #ifdef CA_MAT_INLINES_C #define CA_MAT_INLINE #else #define CA_MAT_INLINE static inline #endif #include "ca_poly.h" #ifdef __cplusplus extern "C" { #endif /* Matrix object */ typedef struct { ca_ptr entries; slong r; slong c; ca_ptr * rows; } ca_mat_struct; typedef ca_mat_struct ca_mat_t[1]; #define ca_mat_entry(mat,i,j) ((mat)->rows[i] + (j)) #define ca_mat_nrows(mat) ((mat)->r) #define ca_mat_ncols(mat) ((mat)->c) CA_MAT_INLINE ca_ptr ca_mat_entry_ptr(ca_mat_t mat, slong i, slong j) { return ca_mat_entry(mat, i, j); } /* Memory management */ void ca_mat_init(ca_mat_t mat, slong r, slong c, ca_ctx_t ctx); void ca_mat_clear(ca_mat_t mat, ca_ctx_t ctx); CA_MAT_INLINE void ca_mat_swap(ca_mat_t mat1, ca_mat_t mat2, ca_ctx_t ctx) { FLINT_SWAP(ca_mat_struct, *mat1, *mat2); } /* Window matrices */ void ca_mat_window_init(ca_mat_t window, const ca_mat_t mat, slong r1, slong c1, slong r2, slong c2, ca_ctx_t ctx); CA_MAT_INLINE void ca_mat_window_clear(ca_mat_t window, ca_ctx_t ctx) { flint_free(window->rows); } /* Shape */ CA_MAT_INLINE int ca_mat_is_empty(const ca_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } CA_MAT_INLINE int ca_mat_is_square(const ca_mat_t mat) { return (mat->r == mat->c); } /* Conversions */ void ca_mat_set(ca_mat_t dest, const ca_mat_t src, ca_ctx_t ctx); void ca_mat_set_fmpz_mat(ca_mat_t dest, const fmpz_mat_t src, ca_ctx_t ctx); void ca_mat_set_fmpq_mat(ca_mat_t dest, const fmpq_mat_t src, ca_ctx_t ctx); void ca_mat_set_ca(ca_mat_t y, const ca_t x, ca_ctx_t ctx); void ca_mat_transfer(ca_mat_t res, ca_ctx_t res_ctx, const ca_mat_t src, ca_ctx_t src_ctx); /* Random generation */ void ca_mat_randtest(ca_mat_t mat, flint_rand_t state, slong len, slong bits, ca_ctx_t ctx); void ca_mat_randtest_rational(ca_mat_t mat, flint_rand_t state, slong bits, ca_ctx_t ctx); void ca_mat_randops(ca_mat_t mat, flint_rand_t state, slong count, ca_ctx_t ctx); /* I/O */ void ca_mat_print(const ca_mat_t mat, ca_ctx_t ctx); void ca_mat_printn(const ca_mat_t mat, slong digits, ca_ctx_t ctx); /* Special matrices */ void ca_mat_zero(ca_mat_t mat, ca_ctx_t ctx); void ca_mat_one(ca_mat_t mat, ca_ctx_t ctx); void ca_mat_ones(ca_mat_t mat, ca_ctx_t ctx); void ca_mat_pascal(ca_mat_t mat, int triangular, ca_ctx_t ctx); void ca_mat_stirling(ca_mat_t mat, int kind, ca_ctx_t ctx); void ca_mat_hilbert(ca_mat_t mat, ca_ctx_t ctx); void ca_mat_dft(ca_mat_t res, int type, ca_ctx_t ctx); /* Comparisons and properties */ truth_t ca_mat_check_equal(const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); truth_t ca_mat_check_is_zero(const ca_mat_t A, ca_ctx_t ctx); truth_t ca_mat_check_is_one(const ca_mat_t A, ca_ctx_t ctx); /* Conjugate and transpose */ void ca_mat_transpose(ca_mat_t B, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_conj(ca_mat_t B, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_conj_transpose(ca_mat_t mat1, const ca_mat_t mat2, ca_ctx_t ctx); /* Arithmetic */ void ca_mat_add_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx); void ca_mat_sub_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx); void ca_mat_addmul_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx); void ca_mat_submul_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx); void ca_mat_neg(ca_mat_t dest, const ca_mat_t src, ca_ctx_t ctx); void ca_mat_add(ca_mat_t res, const ca_mat_t mat1, const ca_mat_t mat2, ca_ctx_t ctx); void ca_mat_sub(ca_mat_t res, const ca_mat_t mat1, const ca_mat_t mat2, ca_ctx_t ctx); void ca_mat_mul(ca_mat_t C, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); void ca_mat_mul_classical(ca_mat_t C, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); void ca_mat_mul_same_nf(ca_mat_t C, const ca_mat_t A, const ca_mat_t B, ca_field_t K, ca_ctx_t ctx); CA_MAT_INLINE void ca_mat_mul_si(ca_mat_t B, const ca_mat_t A, slong c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_mul_si(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_mul_fmpz(ca_mat_t B, const ca_mat_t A, const fmpz_t c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_mul_fmpz(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_mul_fmpq(ca_mat_t B, const ca_mat_t A, const fmpq_t c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_mul_fmpq(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_mul_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_mul(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_div_si(ca_mat_t B, const ca_mat_t A, slong c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_div_si(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_div_fmpz(ca_mat_t B, const ca_mat_t A, const fmpz_t c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_div_fmpz(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_div_fmpq(ca_mat_t B, const ca_mat_t A, const fmpq_t c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_div_fmpq(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_div_ca(ca_mat_t B, const ca_mat_t A, const ca_t c, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_div(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), c, ctx); } CA_MAT_INLINE void ca_mat_sqr(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) { ca_mat_mul(res, A, A, ctx); } void ca_mat_pow_ui_binexp(ca_mat_t B, const ca_mat_t A, ulong exp, ca_ctx_t ctx); /* Polynomial evaluation */ void _ca_mat_ca_poly_evaluate(ca_mat_t y, ca_srcptr poly, slong len, const ca_mat_t x, ca_ctx_t ctx); void ca_mat_ca_poly_evaluate(ca_mat_t res, const ca_poly_t f, const ca_mat_t a, ca_ctx_t ctx); /* Trace */ void ca_mat_trace(ca_t trace, const ca_mat_t mat, ca_ctx_t ctx); /* Gaussian elimination, solving and inverse */ truth_t ca_mat_find_pivot(slong * pivot_row, ca_mat_t mat, slong start_row, slong end_row, slong column, ca_ctx_t ctx); CA_MAT_INLINE void _ca_mat_swap_rows(ca_mat_t mat, slong * perm, slong r, slong s) { if (r != s) { if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(ca_ptr, mat->rows[r], mat->rows[s]); } } int ca_mat_lu_classical(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx); int ca_mat_lu_recursive(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx); int ca_mat_lu(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx); int ca_mat_fflu(slong * rank, slong * P, ca_mat_t LU, ca_t den, const ca_mat_t A, int rank_check, ca_ctx_t ctx); int ca_mat_rref_fflu(slong * rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_rref_lu(slong * rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_rref(slong * rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx); truth_t ca_mat_nonsingular_lu(slong * P, ca_mat_t LU, const ca_mat_t A, ca_ctx_t ctx); truth_t ca_mat_nonsingular_fflu(slong * P, ca_mat_t LU, ca_t den, const ca_mat_t A, ca_ctx_t ctx); truth_t ca_mat_nonsingular_solve_adjugate(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); truth_t ca_mat_nonsingular_solve_fflu(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); truth_t ca_mat_nonsingular_solve_lu(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); truth_t ca_mat_nonsingular_solve(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); truth_t ca_mat_inv(ca_mat_t X, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_solve_tril_classical(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx); void ca_mat_solve_tril_recursive(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx); void ca_mat_solve_tril(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx); void ca_mat_solve_triu_classical(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx); void ca_mat_solve_triu_recursive(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx); void ca_mat_solve_triu(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx); void ca_mat_solve_lu_precomp(ca_mat_t X, const slong * perm, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); void ca_mat_solve_fflu_precomp(ca_mat_t X, const slong * perm, const ca_mat_t A, const ca_t den, const ca_mat_t B, ca_ctx_t ctx); /* Rank and kernel */ int ca_mat_rank(slong * rank, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_right_kernel(ca_mat_t X, const ca_mat_t A, ca_ctx_t ctx); /* Determinant */ void ca_mat_det_berkowitz(ca_t det, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_det_lu(ca_t det, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_det_bareiss(ca_t det, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_det_cofactor(ca_t det, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_det(ca_t det, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_adjugate_cofactor(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_adjugate_charpoly(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_adjugate(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx); /* Characteristic polynomial */ void _ca_mat_charpoly_berkowitz(ca_ptr cp, const ca_mat_t mat, ca_ctx_t ctx); void ca_mat_charpoly_berkowitz(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx); int _ca_mat_charpoly_danilevsky(ca_ptr p, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_charpoly_danilevsky(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx); void _ca_mat_charpoly(ca_ptr cp, const ca_mat_t mat, ca_ctx_t ctx); void ca_mat_charpoly(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx); int ca_mat_companion(ca_mat_t A, const ca_poly_t poly, ca_ctx_t ctx); /* Eigenvalues and eigenvectors */ int ca_mat_eigenvalues(ca_vec_t lambda, ulong * exp, const ca_mat_t mat, ca_ctx_t ctx); /* Diagonalization */ truth_t ca_mat_diagonalization(ca_mat_t D, ca_mat_t P, const ca_mat_t A, ca_ctx_t ctx); void ca_mat_set_jordan_blocks(ca_mat_t mat, const ca_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, ca_ctx_t ctx); int ca_mat_jordan_blocks(ca_vec_t lambda, slong * num_blocks, slong * block_lambda, slong * block_size, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_jordan_transformation(ca_mat_t mat, const ca_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, const ca_mat_t A, ca_ctx_t ctx); int ca_mat_jordan_form(ca_mat_t J, ca_mat_t P, const ca_mat_t A, ca_ctx_t ctx); /* Matrix functions */ int ca_mat_exp(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx); truth_t ca_mat_log(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx); /* Internal representation */ /* todo: document, make consistent */ ca_field_ptr _ca_mat_same_field(const ca_mat_t A, ca_ctx_t ctx); ca_field_ptr _ca_mat_same_field2(const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/ca_mat/000077500000000000000000000000001461254215100146465ustar00rootroot00000000000000flint-3.1.3/src/ca_mat/add.c000066400000000000000000000013531461254215100155440ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_add(ca_mat_t res, const ca_mat_t mat1, const ca_mat_t mat2, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(mat1); i++) for (j = 0; j < ca_mat_ncols(mat1); j++) ca_add(ca_mat_entry(res, i, j), ca_mat_entry(mat1, i, j), ca_mat_entry(mat2, i, j), ctx); } flint-3.1.3/src/ca_mat/add_ca.c000066400000000000000000000020571461254215100162110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_add_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx) { slong i, j, n; if (a == y) { n = FLINT_MIN(ca_mat_nrows(a), ca_mat_ncols(a)); for (i = 0; i < n; i++) ca_add(ca_mat_entry(y, i, i), ca_mat_entry(y, i, i), x, ctx); } else { for (i = 0; i < ca_mat_nrows(a); i++) { for (j = 0; j < ca_mat_ncols(a); j++) { if (i == j) ca_add(ca_mat_entry(y, i, j), ca_mat_entry(a, i, j), x, ctx); else ca_set(ca_mat_entry(y, i, j), ca_mat_entry(a, i, j), ctx); } } } } flint-3.1.3/src/ca_mat/addmul_ca.c000066400000000000000000000014521461254215100167250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_addmul_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx) { slong i, j; ca_t t; ca_init(t, ctx); for (i = 0; i < ca_mat_nrows(a); i++) { for (j = 0; j < ca_mat_ncols(a); j++) { ca_mul(t, ca_mat_entry(a, i, j), x, ctx); ca_add(ca_mat_entry(y, i, j), ca_mat_entry(y, i, j), t, ctx); } } ca_clear(t, ctx); } flint-3.1.3/src/ca_mat/adjugate.c000066400000000000000000000011641461254215100166000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_adjugate(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx) { if (ca_mat_nrows(A) <= 5) ca_mat_adjugate_cofactor(adj, det, A, ctx); else ca_mat_adjugate_charpoly(adj, det, A, ctx); } flint-3.1.3/src/ca_mat/adjugate_charpoly.c000066400000000000000000000016631461254215100205050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_adjugate_charpoly(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx) { ca_poly_t pol; slong n; n = ca_mat_nrows(A); if (n == 0) { ca_one(det, ctx); return; } ca_poly_init(pol, ctx); ca_mat_charpoly(pol, A, ctx); ca_swap(det, ca_poly_coeff_ptr(pol, 0), ctx); ca_poly_shift_right(pol, pol, 1, ctx); ca_mat_ca_poly_evaluate(adj, pol, A, ctx); if (n % 2) ca_neg(det, det, ctx); else ca_mat_neg(adj, adj, ctx); ca_poly_clear(pol, ctx); } flint-3.1.3/src/ca_mat/adjugate_cofactor.c000066400000000000000000000051451461254215100204630ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_adjugate_cofactor(ca_mat_t adj, ca_t det, const ca_mat_t A, ca_ctx_t ctx) { ca_mat_t T; slong i, j, n, a, b; ca_t t, zero; n = ca_mat_nrows(A); if (n == 0) { ca_one(det, ctx); return; } if (n == 1) { ca_set(det, ca_mat_entry(A, 0, 0), ctx); ca_one(ca_mat_entry(adj, 0, 0), ctx); return; } if (n == 2) { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_mul(t, ca_mat_entry(A, 0, 0), ca_mat_entry(A, 1, 1), ctx); ca_mul(u, ca_mat_entry(A, 0, 1), ca_mat_entry(A, 1, 0), ctx); ca_set(ca_mat_entry(adj, 0, 0), ca_mat_entry(A, 1, 1), ctx); ca_neg(ca_mat_entry(adj, 0, 1), ca_mat_entry(A, 0, 1), ctx); ca_neg(ca_mat_entry(adj, 1, 0), ca_mat_entry(A, 1, 0), ctx); ca_set(ca_mat_entry(adj, 1, 1), ca_mat_entry(A, 0, 0), ctx); ca_sub(det, t, u, ctx); ca_clear(t, ctx); ca_clear(u, ctx); return; } if (adj == A) { ca_mat_init(T, n, n, ctx); ca_mat_adjugate_cofactor(T, det, A, ctx); ca_mat_swap(adj, T, ctx); ca_mat_clear(T, ctx); return; } ca_mat_init(T, n - 1, n - 1, ctx); ca_init(zero, ctx); ca_init(t, ctx); ca_zero(det, ctx); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { for (a = 0; a < n; a++) { for (b = 0; b < n; b++) { if (a != i && b != j) { *ca_mat_entry(T, a - (a > i), b - (b > j)) = *ca_mat_entry(A, a, b); } } } ca_mat_det(ca_mat_entry(adj, i, j), T, ctx); if ((i + j) & 1) ca_neg(ca_mat_entry(adj, i, j), ca_mat_entry(adj, i, j), ctx); if (i == 0) { ca_mul(t, ca_mat_entry(adj, i, j), ca_mat_entry(A, i, j), ctx); ca_add(det, det, t, ctx); } } } ca_mat_transpose(adj, adj, ctx); for (i = 0; i < n - 1; i++) for (j = 0; j < n - 1; j++) *ca_mat_entry(T, i, j) = *zero; ca_mat_clear(T, ctx); ca_clear(t, ctx); } flint-3.1.3/src/ca_mat/ca_poly_evaluate.c000066400000000000000000000040561461254215100203330ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "ca_mat.h" void _ca_mat_ca_poly_evaluate(ca_mat_t y, ca_srcptr poly, slong len, const ca_mat_t x, ca_ctx_t ctx) { slong i, j, m, r, n; ca_mat_struct * xs; ca_mat_t s, t; if (len == 0) { ca_mat_zero(y, ctx); return; } if (len == 1) { ca_mat_set_ca(y, poly + 0, ctx); return; } if (len == 2) { ca_mat_mul_ca(y, x, poly + 1, ctx); ca_mat_add_ca(y, y, poly + 0, ctx); return; } n = ca_mat_nrows(x); m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = flint_malloc(sizeof(ca_mat_struct) * (m + 1)); for (i = 0; i <= m; i++) { ca_mat_init(xs + i, n, n, ctx); if (i == 0) ca_mat_one(xs + i, ctx); else if (i == 1) ca_mat_set(xs + i, x, ctx); else ca_mat_mul(xs + i, xs + i - 1, x, ctx); } ca_mat_init(s, n, n, ctx); ca_mat_init(t, n, n, ctx); ca_mat_set_ca(y, poly + (r - 1) * m, ctx); for (j = 1; (r - 1) * m + j < len; j++) ca_mat_addmul_ca(y, xs + j, poly + (r - 1) * m + j, ctx); for (i = r - 2; i >= 0; i--) { ca_mat_set_ca(s, poly + i * m, ctx); for (j = 1; j < m; j++) ca_mat_addmul_ca(s, xs + j, poly + i * m + j, ctx); ca_mat_mul(y, y, xs + m, ctx); ca_mat_add(y, y, s, ctx); } for (i = 0; i <= m; i++) ca_mat_clear(xs + i, ctx); flint_free(xs); ca_mat_clear(s, ctx); ca_mat_clear(t, ctx); } void ca_mat_ca_poly_evaluate(ca_mat_t res, const ca_poly_t f, const ca_mat_t a, ca_ctx_t ctx) { _ca_mat_ca_poly_evaluate(res, f->coeffs, f->length, a, ctx); } flint-3.1.3/src/ca_mat/charpoly.c000066400000000000000000000022631461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void _ca_mat_charpoly(ca_ptr cp, const ca_mat_t mat, ca_ctx_t ctx) { if (ca_mat_nrows(mat) <= 2) { _ca_mat_charpoly_berkowitz(cp, mat, ctx); } else { /* ca_field_ptr K; K = _ca_mat_same_field(mat, ctx); if (0 && K != NULL && CA_FIELD_IS_NF(K)) { if (_ca_mat_charpoly_danilevsky(cp, mat, ctx)) return; } */ _ca_mat_charpoly_berkowitz(cp, mat, ctx); } } void ca_mat_charpoly(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx) { if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (ca_mat_charpoly). Non-square matrix.\n"); } ca_poly_fit_length(cp, mat->r + 1, ctx); _ca_poly_set_length(cp, mat->r + 1, ctx); _ca_mat_charpoly(cp->coeffs, mat, ctx); } flint-3.1.3/src/ca_mat/charpoly_berkowitz.c000066400000000000000000000025131461254215100207340ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void _ca_mat_charpoly_berkowitz(ca_ptr cp, const ca_mat_t mat, ca_ctx_t ctx) { const slong n = mat->r; if (n == 0) { ca_one(cp, ctx); } else if (n == 1) { ca_neg(cp + 0, ca_mat_entry(mat, 0, 0), ctx); ca_one(cp + 1, ctx); } else if (n == 2) { ca_mat_det_cofactor(cp, mat, ctx); ca_add(cp + 1, ca_mat_entry(mat, 0, 0), ca_mat_entry(mat, 1, 1), ctx); ca_neg(cp + 1, cp + 1, ctx); ca_one(cp + 2, ctx); } else { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(_gr_mat_charpoly_berkowitz(cp, (const gr_mat_struct *) mat, gr_ctx)); } } void ca_mat_charpoly_berkowitz(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx) { ca_poly_fit_length(cp, mat->r + 1, ctx); _ca_poly_set_length(cp, mat->r + 1, ctx); _ca_mat_charpoly_berkowitz(cp->coeffs, mat, ctx); } flint-3.1.3/src/ca_mat/charpoly_danilevsky.c000066400000000000000000000024261461254215100210700ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" int _ca_mat_charpoly_danilevsky_inplace(ca_ptr p, ca_mat_t A, ca_ctx_t ctx) { int success; gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); success = (_gr_mat_charpoly_danilevsky_inplace(p, (gr_mat_struct *) A, gr_ctx) == GR_SUCCESS); return success; } int _ca_mat_charpoly_danilevsky(ca_ptr cp, const ca_mat_t A, ca_ctx_t ctx) { ca_mat_t T; int success; ca_mat_init(T, ca_mat_nrows(A), ca_mat_nrows(A), ctx); ca_mat_set(T, A, ctx); success = _ca_mat_charpoly_danilevsky_inplace(cp, T, ctx); ca_mat_clear(T, ctx); return success; } int ca_mat_charpoly_danilevsky(ca_poly_t cp, const ca_mat_t mat, ca_ctx_t ctx) { ca_poly_fit_length(cp, mat->r + 1, ctx); _ca_poly_set_length(cp, mat->r + 1, ctx); return _ca_mat_charpoly_danilevsky(cp->coeffs, mat, ctx); } flint-3.1.3/src/ca_mat/check_equal.c000066400000000000000000000020001461254215100172460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_check_equal(const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { slong i, j; truth_t res, eq; if ((ca_mat_nrows(A) != ca_mat_nrows(B)) || (ca_mat_ncols(A) != ca_mat_ncols(B))) { return T_FALSE; } res = T_TRUE; for (i = 0; i < ca_mat_nrows(A); i++) { for (j = 0; j < ca_mat_ncols(A); j++) { eq = ca_check_equal(ca_mat_entry(A, i, j), ca_mat_entry(B, i, j), ctx); if (eq == T_FALSE) return T_FALSE; if (eq == T_UNKNOWN) res = T_UNKNOWN; } } return res; } flint-3.1.3/src/ca_mat/check_is_one.c000066400000000000000000000017061461254215100174270ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_check_is_one(const ca_mat_t A, ca_ctx_t ctx) { slong i, j; truth_t res, eq; res = T_TRUE; for (i = 0; i < ca_mat_nrows(A); i++) { for (j = 0; j < ca_mat_ncols(A); j++) { if (i == j) eq = ca_check_is_one(ca_mat_entry(A, i, j), ctx); else eq = ca_check_is_zero(ca_mat_entry(A, i, j), ctx); if (eq == T_FALSE) return T_FALSE; if (eq == T_UNKNOWN) res = T_UNKNOWN; } } return res; } flint-3.1.3/src/ca_mat/check_is_zero.c000066400000000000000000000015301461254215100176200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_check_is_zero(const ca_mat_t A, ca_ctx_t ctx) { slong i, j; truth_t res, eq; res = T_TRUE; for (i = 0; i < ca_mat_nrows(A); i++) { for (j = 0; j < ca_mat_ncols(A); j++) { eq = ca_check_is_zero(ca_mat_entry(A, i, j), ctx); if (eq == T_FALSE) return T_FALSE; if (eq == T_UNKNOWN) res = T_UNKNOWN; } } return res; } flint-3.1.3/src/ca_mat/clear.c000066400000000000000000000011121461254215100160730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_clear(ca_mat_t mat, ca_ctx_t ctx) { if (mat->entries != NULL) { _ca_vec_clear(mat->entries, mat->r * mat->c, ctx); flint_free(mat->rows); } } flint-3.1.3/src/ca_mat/companion.c000066400000000000000000000024631461254215100170020ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void _ca_mat_companion(ca_mat_t A, ca_srcptr poly, const ca_t c, ca_ctx_t ctx) { slong i, j, n; n = ca_mat_nrows(A); if (n == 0) return; for (i = 0; i < n - 1; i++) for (j = 0; j < n; j++) ca_set_ui(ca_mat_entry(A, i, j), (i + 1) == j, ctx); for (j = 0; j < n; j++) ca_mul(ca_mat_entry(A, n - 1, j), poly + j, c, ctx); } int ca_mat_companion(ca_mat_t A, const ca_poly_t poly, ca_ctx_t ctx) { ca_t c; int res; slong n = ca_mat_nrows(A); if (n != poly->length - 1 || n != ca_mat_ncols(A)) { return 0; } if (CA_IS_SPECIAL(poly->coeffs + n)) return 0; ca_init(c, ctx); ca_inv(c, poly->coeffs + n, ctx); ca_neg(c, c, ctx); if (CA_IS_SPECIAL(c)) { res = 0; } else { _ca_mat_companion(A, poly->coeffs, c, ctx); res = 1; } ca_clear(c, ctx); return res; } flint-3.1.3/src/ca_mat/conj.c000066400000000000000000000014761461254215100157530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_conj(ca_mat_t B, const ca_mat_t A, ca_ctx_t ctx) { slong i, j; if ((ca_mat_nrows(B) != ca_mat_nrows(A)) || (ca_mat_ncols(B) != ca_mat_ncols(A))) { flint_throw(FLINT_ERROR, "ca_mat_conj: incompatible dimensions.\n"); } for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) ca_conj(ca_mat_entry(B, i, j), ca_mat_entry(A, i, j), ctx); } flint-3.1.3/src/ca_mat/conj_transpose.c000066400000000000000000000010561461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_conj_transpose(ca_mat_t mat1, const ca_mat_t mat2, ca_ctx_t ctx) { ca_mat_transpose(mat1, mat2, ctx); ca_mat_conj(mat1, mat1, ctx); } flint-3.1.3/src/ca_mat/det.c000066400000000000000000000062661461254215100156000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" #include "ca_mat.h" int _ca_mat_is_fmpq(const ca_mat_t A, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) if (!CA_IS_QQ(ca_mat_entry(A, i, j), ctx)) return 0; return 1; } int _ca_mat_fmpq_is_fmpz(const ca_mat_t A, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) for (j = 0; j < ca_mat_ncols(A); j++) if (!fmpz_is_one(CA_FMPQ_DENREF(ca_mat_entry(A, i, j)))) return 0; return 1; } ca_field_ptr _ca_mat_same_field(const ca_mat_t A, ca_ctx_t ctx) { ca_field_ptr K, QQ; slong i, j; QQ = ctx->field_qq; K = QQ; for (i = 0; i < ca_mat_nrows(A); i++) { for (j = 0; j < ca_mat_ncols(A); j++) { if (CA_IS_QQ(ca_mat_entry(A, i, j), ctx)) continue; if (CA_IS_SPECIAL(ca_mat_entry(A, i, j))) return NULL; if (K == QQ) K = CA_FIELD(ca_mat_entry(A, i, j), ctx); else if (K != CA_FIELD(ca_mat_entry(A, i, j), ctx)) return NULL; } } return K; } void ca_mat_det(ca_t res, const ca_mat_t A, ca_ctx_t ctx) { slong n; n = ca_mat_nrows(A); if (n != ca_mat_ncols(A)) { flint_throw(FLINT_ERROR, "ca_mat_det: matrix must be square\n"); } if (n >= 3 && _ca_mat_is_fmpq(A, ctx)) { if (_ca_mat_fmpq_is_fmpz(A, ctx)) { fmpz_mat_t Zm; fmpz_t det; slong i, j; fmpz_init(det); fmpz_mat_init(Zm, n, n); for (i = 0; i < n; i++) for (j = 0; j < n; j++) *fmpz_mat_entry(Zm, i, j) = *CA_FMPQ_NUMREF(ca_mat_entry(A, i, j)); fmpz_mat_det(det, Zm); flint_free(Zm->rows); flint_free(Zm->entries); ca_set_fmpz(res, det, ctx); fmpz_clear(det); } else { fmpq_mat_t Qm; fmpq_t det; slong i, j; fmpq_init(det); fmpq_mat_init(Qm, n, n); for (i = 0; i < n; i++) for (j = 0; j < n; j++) *fmpq_mat_entry(Qm, i, j) = *CA_FMPQ(ca_mat_entry(A, i, j)); fmpq_mat_det(det, Qm); flint_free(Qm->rows); flint_free(Qm->entries); ca_set_fmpq(res, det, ctx); fmpq_clear(det); } return; } if (n <= 4) { ca_mat_det_cofactor(res, A, ctx); } else { ca_field_ptr K; K = _ca_mat_same_field(A, ctx); if (K != NULL && CA_FIELD_IS_NF(K)) ca_mat_det_lu(res, A, ctx); else ca_mat_det_berkowitz(res, A, ctx); } } flint-3.1.3/src/ca_mat/det_bareiss.c000066400000000000000000000017731461254215100173060ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "ca_mat.h" int ca_mat_det_bareiss(ca_t res, const ca_mat_t A, ca_ctx_t ctx) { truth_t invertible; slong * P; ca_mat_t T; slong n; n = ca_mat_nrows(A); P = _perm_init(n); ca_mat_init(T, n, n, ctx); invertible = ca_mat_nonsingular_fflu(P, T, res, A, ctx); if (invertible == T_FALSE) { ca_zero(res, ctx); } else if (invertible == T_TRUE) { if (_perm_parity(P, n)) ca_neg(res, res, ctx); } else { ca_unknown(res, ctx); } ca_mat_clear(T, ctx); _perm_clear(P); return invertible != T_UNKNOWN; } flint-3.1.3/src/ca_mat/det_berkowitz.c000066400000000000000000000013031461254215100176630ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_det_berkowitz(ca_t res, const ca_mat_t A, ca_ctx_t ctx) { ca_ptr t; t = _ca_vec_init(ca_mat_nrows(A) + 1, ctx); _ca_mat_charpoly(t, A, ctx); ca_swap(res, t, ctx); if (ca_mat_nrows(A) % 2) ca_neg(res, res, ctx); _ca_vec_clear(t, ca_mat_nrows(A) + 1, ctx); } flint-3.1.3/src/ca_mat/det_cofactor.c000066400000000000000000000012201461254215100174410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void ca_mat_det_cofactor(ca_t res, const ca_mat_t A, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_det_cofactor(res, (const gr_mat_struct *) A, gr_ctx)); } flint-3.1.3/src/ca_mat/det_lu.c000066400000000000000000000021461461254215100162710ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "ca_mat.h" int ca_mat_det_lu(ca_t res, const ca_mat_t A, ca_ctx_t ctx) { truth_t invertible; slong * P; ca_mat_t T; slong i, n; n = ca_mat_nrows(A); P = _perm_init(n); ca_mat_init(T, n, n, ctx); invertible = ca_mat_nonsingular_lu(P, T, A, ctx); if (invertible == T_FALSE) { ca_zero(res, ctx); } else if (invertible == T_TRUE) { ca_one(res, ctx); for (i = 0; i < n; i++) ca_mul(res, res, ca_mat_entry(T, i, i), ctx); if (_perm_parity(P, n)) ca_neg(res, res, ctx); } else { ca_unknown(res, ctx); } ca_mat_clear(T, ctx); _perm_clear(P); return invertible != T_UNKNOWN; } flint-3.1.3/src/ca_mat/dft.c000066400000000000000000000034741461254215100155770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_dft(ca_mat_t res, int type, ca_ctx_t ctx) { ca_ptr w; slong n, r, c, i, j; r = ca_mat_nrows(res); c = ca_mat_ncols(res); n = FLINT_MIN(r, c); if (n == 0) return; w = _ca_vec_init(2 * n, ctx); for (i = 0; i < 2 * n; i++) { if (i == 0) { ca_one(w + i, ctx); } else if (i == 1) { ca_pi_i(w + i, ctx); ca_mul_ui(w + i, w + i, 2, ctx); ca_div_si(w + i, w + i, n, ctx); ca_exp(w + i, w + i, ctx); if (type == 0 || type == 2) ca_inv(w + i, w + i, ctx); } else { ca_mul(w + i, w + i - 1, w + 1, ctx); } } for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { ca_set(ca_mat_entry(res, i, j), w + (i * j) % (2 * n), ctx); } } _ca_vec_clear(w, 2 * n, ctx); if (type == 1) { for (i = 0; i < r; i++) for (j = 0; j < c; j++) ca_div_ui(ca_mat_entry(res, i, j), ca_mat_entry(res, i, j), n, ctx); } else if (type == 2 || type == 3) { ca_t t; ca_init(t, ctx); ca_sqrt_ui(t, n, ctx); ca_inv(t, t, ctx); for (i = 0; i < r; i++) for (j = 0; j < c; j++) ca_mul(ca_mat_entry(res, i, j), ca_mat_entry(res, i, j), t, ctx); ca_clear(t, ctx); } } flint-3.1.3/src/ca_mat/diagonalization.c000066400000000000000000000044001461254215100201640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_diagonalization_precomp(ca_mat_t D, ca_mat_t P, const ca_mat_t A, const ca_vec_t eigenvalues, const ulong * am, ca_ctx_t ctx) { int success; truth_t result; ca_mat_t AIe, b; slong i, j, k, n; slong nullity, added; n = ca_mat_nrows(A); ca_mat_init(AIe, n, n, ctx); ca_mat_init(b, 0, 0, ctx); result = T_TRUE; ca_mat_zero(D, ctx); added = 0; for (i = 0; i < ca_vec_length(eigenvalues, ctx); i++) { ca_mat_set(AIe, A, ctx); for (j = 0; j < n; j++) ca_sub(ca_mat_entry(AIe, j, j), ca_mat_entry(AIe, j, j), ca_vec_entry(eigenvalues, i), ctx); success = ca_mat_right_kernel(b, AIe, ctx); if (!success) { result = T_UNKNOWN; break; } nullity = ca_mat_ncols(b); if (nullity != am[i]) { result = T_FALSE; break; } for (j = 0; j < am[i]; j++) { ca_set(ca_mat_entry(D, added + j, added + j), ca_vec_entry(eigenvalues, i), ctx); for (k = 0; k < n; k++) ca_set(ca_mat_entry(P, k, added + j), ca_mat_entry(b, k, j), ctx); } added += am[i]; } ca_mat_clear(AIe, ctx); ca_mat_clear(b, ctx); return result; } truth_t ca_mat_diagonalization(ca_mat_t D, ca_mat_t P, const ca_mat_t A, ca_ctx_t ctx) { truth_t result; ca_vec_t eigenvalues; ulong * am; slong n; if (!ca_mat_is_square(A)) return T_FALSE; n = ca_mat_nrows(A); am = flint_malloc(sizeof(ulong) * n); ca_vec_init(eigenvalues, 0, ctx); if (ca_mat_eigenvalues(eigenvalues, am, A, ctx)) { result = ca_mat_diagonalization_precomp(D, P, A, eigenvalues, am, ctx); } else { result = T_UNKNOWN; } ca_vec_clear(eigenvalues, ctx); flint_free(am); return result; } flint-3.1.3/src/ca_mat/eigenvalues.c000066400000000000000000000012631461254215100173230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" int ca_mat_eigenvalues(ca_vec_t lambda, ulong * exp, const ca_mat_t mat, ca_ctx_t ctx) { int success; ca_poly_t cp; ca_poly_init(cp, ctx); ca_mat_charpoly(cp, mat, ctx); success = ca_poly_roots(lambda, exp, cp, ctx); ca_poly_clear(cp, ctx); return success; } flint-3.1.3/src/ca_mat/exp.c000066400000000000000000000013371461254215100156120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" int ca_mat_exp(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) { gr_ctx_t cctx; int status; _gr_ctx_init_ca_from_ref(cctx, GR_CTX_CC_CA, ctx); status = gr_mat_exp((gr_mat_struct *) res, (const gr_mat_struct *) A, cctx); if (status == GR_SUCCESS) return 1; else return 0; } flint-3.1.3/src/ca_mat/fflu.c000066400000000000000000000045741461254215100157600ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" int ca_mat_fflu(slong * res_rank, slong * P, ca_mat_t LU, ca_t den, const ca_mat_t A, int rank_check, ca_ctx_t ctx) { ca_t d, e; slong i, j, k, m, n, r, rank, row, col; int success; truth_t found_pivot; if (ca_mat_is_empty(A)) { *res_rank = 0; ca_one(den, ctx); return 1; } m = ca_mat_nrows(A); n = ca_mat_ncols(A); ca_mat_set(LU, A, ctx); rank = row = col = 0; if (P != NULL) for (i = 0; i < m; i++) P[i] = i; ca_init(d, ctx); ca_init(e, ctx); success = 1; while (row < m && col < n) { found_pivot = ca_mat_find_pivot(&r, LU, row, m, col, ctx); if (found_pivot == T_UNKNOWN) { success = 0; break; } if (found_pivot == T_FALSE) { if (rank_check) { ca_zero(den, ctx); rank = 0; break; } col++; continue; } rank++; if (r != row) _ca_mat_swap_rows(LU, P, row, r); if (row > 0) ca_inv(d, den, ctx); for (j = row + 1; j < m; j++) { for (k = col + 1; k < n; k++) { ca_mul(ca_mat_entry(LU, j, k), ca_mat_entry(LU, j, k), ca_mat_entry(LU, row, col), ctx); ca_mul(e, ca_mat_entry(LU, j, col), ca_mat_entry(LU, row, k), ctx); ca_sub(ca_mat_entry(LU, j, k), ca_mat_entry(LU, j, k), e, ctx); if (row > 0) ca_mul(ca_mat_entry(LU, j, k), ca_mat_entry(LU, j, k), d, ctx); } /* todo: zero at (j, col) ? */ } ca_set(den, ca_mat_entry(LU, row, col), ctx); row++; col++; } ca_clear(d, ctx); ca_clear(e, ctx); if (success) { if (rank == 0) ca_zero(den, ctx); } if (!success) ca_unknown(den, ctx); *res_rank = rank; return success; } flint-3.1.3/src/ca_mat/find_pivot.c000066400000000000000000000055501461254215100171600ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" static truth_t ca_check_is_zero_fast(const ca_t x, ca_ctx_t ctx) { if (CA_IS_QQ(x, ctx)) { return fmpq_is_zero(CA_FMPQ(x)) ? T_TRUE : T_FALSE; } else { return T_UNKNOWN; } } static truth_t ca_check_is_zero_and_simplify(ca_t x, ca_ctx_t ctx) { truth_t res = ca_check_is_zero_fast(x, ctx); if (res == T_UNKNOWN) { res = ca_check_is_zero(x, ctx); if (res == T_TRUE) ca_zero(x, ctx); } return res; } truth_t ca_mat_find_pivot(slong * pivot_row, ca_mat_t mat, slong start_row, slong end_row, slong column, ca_ctx_t ctx) { slong best_row, i; truth_t is_zero; int unknown; if (end_row <= start_row) flint_throw(FLINT_ERROR, "(%s): end_row <= start_row\n", __func__); /* First find the simplest element that is not trivially zero. With high probability this will actually be nonzero. */ best_row = -1; for (i = start_row; i < end_row; i++) { is_zero = ca_check_is_zero_fast(ca_mat_entry(mat, i, column), ctx); if (is_zero != T_TRUE) { if (best_row == -1 || ca_cmp_repr(ca_mat_entry(mat, i, column), ca_mat_entry(mat, best_row, column), ctx) < 0) { best_row = i; } } } if (best_row != -1) { is_zero = ca_check_is_zero_and_simplify(ca_mat_entry(mat, best_row, column), ctx); if (is_zero == T_FALSE) { *pivot_row = best_row; return T_TRUE; } } /* If the above failed, go through all elements again and do more expensive checks. Todo: 1) support in-place simplifications. 2) consider sorting above and traversing all entries in order of simplicity (not just the simplest element). */ best_row = -1; unknown = 0; for (i = start_row; i < end_row; i++) { is_zero = ca_check_is_zero_and_simplify(ca_mat_entry(mat, i, column), ctx); if (is_zero == T_FALSE) { if (best_row == -1 || ca_cmp_repr(ca_mat_entry(mat, i, column), ca_mat_entry(mat, best_row, column), ctx) < 0) { best_row = i; } } if (is_zero == T_UNKNOWN) unknown = 1; } if (best_row == -1) { *pivot_row = -1; if (unknown) return T_UNKNOWN; else return T_FALSE; } else { *pivot_row = best_row; return T_TRUE; } } flint-3.1.3/src/ca_mat/get_fexpr.c000066400000000000000000000051611461254215100170000ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #include "ca.h" #include "ca_ext.h" #include "ca_mat.h" void _ca_default_variables(fexpr_ptr ext_vars, slong num_ext); void _ca_get_fexpr_given_ext(fexpr_t res, const ca_t x, ulong flags, ca_ext_ptr * ext, slong num_ext, const fexpr_struct * ext_vars, ca_ctx_t ctx); void _ca_all_extensions(ca_ext_ptr ** extensions, slong * length, const ca_t x, ca_ctx_t ctx); void _ca_ext_get_fexpr_given_ext(fexpr_t res, const ca_ext_t x, ulong flags, ca_ext_ptr * ext, slong num_ext, const fexpr_struct * ext_vars, ca_ctx_t ctx); void ca_mat_get_fexpr(fexpr_t res, const ca_mat_t A, ulong flags, ca_ctx_t ctx) { ca_ext_ptr * ext; slong r, c, i, j, num_ext; fexpr_struct * ext_vars; fexpr_struct * where_args; fexpr_struct *rows; fexpr_struct *row; fexpr_t t; ext = NULL; num_ext = 0; r = ca_mat_nrows(A); c = ca_mat_ncols(A); for (i = 0; i < r; i++) for (j = 0; j < c; j++) _ca_all_extensions(&ext, &num_ext, ca_mat_entry(A, i, j), ctx); ext_vars = _fexpr_vec_init(num_ext); fexpr_init(t); _ca_default_variables(ext_vars, num_ext); rows = _fexpr_vec_init(r); row = _fexpr_vec_init(c); for (i = 0; i < r; i++) { for (j = 0; j < c; j++) _ca_get_fexpr_given_ext(row + j, ca_mat_entry(A, i, j), flags, ext, num_ext, ext_vars, ctx); fexpr_set_symbol_builtin(t, FEXPR_Row); fexpr_call_vec(rows + i, t, row, c); } fexpr_set_symbol_builtin(t, FEXPR_Matrix); if (num_ext == 0) { fexpr_call_vec(res, t, rows, r); } else { where_args = _fexpr_vec_init(num_ext + 1); fexpr_call_vec(where_args + 0, t, rows, r); for (i = 0; i < num_ext; i++) { _ca_ext_get_fexpr_given_ext(t, ext[i], flags, ext, num_ext, ext_vars, ctx); fexpr_call_builtin2(where_args + i + 1, FEXPR_Def, ext_vars + i, t); } fexpr_set_symbol_builtin(t, FEXPR_Where); fexpr_call_vec(res, t, where_args, num_ext + 1); _fexpr_vec_clear(where_args, num_ext + 1); } _fexpr_vec_clear(rows, r); _fexpr_vec_clear(row, c); flint_free(ext); fexpr_clear(t); _fexpr_vec_clear(ext_vars, num_ext); } flint-3.1.3/src/ca_mat/hilbert.c000066400000000000000000000011561461254215100164460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void ca_mat_hilbert(ca_mat_t mat, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_hilbert((gr_mat_struct *) mat, gr_ctx)); } flint-3.1.3/src/ca_mat/init.c000066400000000000000000000014321461254215100157550ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_init(ca_mat_t mat, slong r, slong c, ca_ctx_t ctx) { if (r != 0 && c != 0) { slong i; mat->entries = _ca_vec_init(r * c, ctx); mat->rows = (ca_ptr *) flint_malloc(r * sizeof(ca_ptr)); for (i = 0; i < r; i++) mat->rows[i] = mat->entries + i * c; } else mat->entries = NULL; mat->r = r; mat->c = c; } flint-3.1.3/src/ca_mat/inlines.c000066400000000000000000000006541461254215100164600ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define CA_MAT_INLINES_C #include "ca_mat.h" flint-3.1.3/src/ca_mat/inv.c000066400000000000000000000026671461254215100156210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" static truth_t ca_mat_inv_adjugate(ca_mat_t X, const ca_mat_t A, ca_ctx_t ctx) { truth_t success; ca_t det; ca_init(det, ctx); ca_mat_adjugate(X, det, A, ctx); success = ca_check_is_zero(det, ctx); if (success == T_FALSE) { ca_mat_div_ca(X, X, det, ctx); success = T_TRUE; } else if (success == T_TRUE) success = T_FALSE; ca_clear(det, ctx); return success; } truth_t ca_mat_inv(ca_mat_t X, const ca_mat_t A, ca_ctx_t ctx) { ca_field_ptr K; slong n; truth_t success; ca_mat_t T; n = ca_mat_nrows(A); if (n == 0) return T_TRUE; if (n <= 4) return ca_mat_inv_adjugate(X, A, ctx); K = _ca_mat_same_field(A, ctx); if (K != NULL && (CA_FIELD_IS_QQ(K) || CA_FIELD_IS_NF(K))) { ca_mat_init(T, n, n, ctx); ca_mat_one(T, ctx); success = ca_mat_nonsingular_solve_lu(X, A, T, ctx); ca_mat_clear(T, ctx); return success; } else { return ca_mat_inv_adjugate(X, A, ctx); } } flint-3.1.3/src/ca_mat/jordan_blocks.c000066400000000000000000000022461461254215100176300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void ca_mat_set_jordan_blocks(ca_mat_t mat, const ca_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, ca_ctx_t ctx) { gr_ctx_t cctx; _gr_ctx_init_ca_from_ref(cctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_set_jordan_blocks((gr_mat_struct *) mat, (const gr_vec_struct *) lambda, num_blocks, block_lambda, block_size, cctx)); } int ca_mat_jordan_blocks(ca_vec_t lambda, slong * num_blocks, slong * block_lambda, slong * block_size, const ca_mat_t A, ca_ctx_t ctx) { gr_ctx_t cctx; int success; _gr_ctx_init_ca_from_ref(cctx, GR_CTX_CC_CA, ctx); success = (gr_mat_jordan_blocks((gr_vec_struct *) lambda, num_blocks, block_lambda, block_size, (const gr_mat_struct *) A, cctx) == GR_SUCCESS); return success; } flint-3.1.3/src/ca_mat/jordan_form.c000066400000000000000000000013461461254215100173160ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" int ca_mat_jordan_form(ca_mat_t J, ca_mat_t P, const ca_mat_t A, ca_ctx_t ctx) { gr_ctx_t cctx; int success; _gr_ctx_init_ca_from_ref(cctx, GR_CTX_CC_CA, ctx); success = (gr_mat_jordan_form((gr_mat_struct *) J, (gr_mat_struct *) P, (const gr_mat_struct *) A, cctx) == GR_SUCCESS); return success;} flint-3.1.3/src/ca_mat/jordan_transformation.c000066400000000000000000000015611461254215100214200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" int ca_mat_jordan_transformation(ca_mat_t mat, const ca_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, const ca_mat_t A, ca_ctx_t ctx) { gr_ctx_t cctx; int success; _gr_ctx_init_ca_from_ref(cctx, GR_CTX_CC_CA, ctx); success = (gr_mat_jordan_transformation((gr_mat_struct *) mat, (gr_vec_struct *) lambda, num_blocks, block_lambda, block_size, (const gr_mat_struct *) A, cctx) == GR_SUCCESS); return success; } flint-3.1.3/src/ca_mat/log.c000066400000000000000000000014251461254215100155750ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" truth_t ca_mat_log(ca_mat_t res, const ca_mat_t A, ca_ctx_t ctx) { gr_ctx_t cctx; int status; _gr_ctx_init_ca_from_ref(cctx, GR_CTX_CC_CA, ctx); status = gr_mat_log((gr_mat_struct *) res, (const gr_mat_struct *) A, cctx); if (status & GR_UNABLE) return T_UNKNOWN; if (status & GR_DOMAIN) return T_FALSE; return T_TRUE; } flint-3.1.3/src/ca_mat/lu.c000066400000000000000000000010751461254215100154350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" int ca_mat_lu(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx) { return ca_mat_lu_recursive(rank, P, LU, A, rank_check, ctx); } flint-3.1.3/src/ca_mat/lu_classical.c000066400000000000000000000036031461254215100174520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" int ca_mat_lu_classical(slong * res_rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx) { ca_t d, e; ca_ptr * a; slong i, j, m, n, r, rank, row, col; int success; truth_t found_pivot; if (ca_mat_is_empty(A)) { *res_rank = 0; return 1; } m = ca_mat_nrows(A); n = ca_mat_ncols(A); ca_mat_set(LU, A, ctx); a = LU->rows; rank = row = col = 0; for (i = 0; i < m; i++) P[i] = i; ca_init(d, ctx); ca_init(e, ctx); success = 1; while (row < m && col < n) { found_pivot = ca_mat_find_pivot(&r, LU, row, m, col, ctx); if (found_pivot == T_UNKNOWN) { success = 0; break; } if (found_pivot == T_FALSE) { if (rank_check) { rank = 0; break; } col++; continue; } rank++; if (r != row) _ca_mat_swap_rows(LU, P, row, r); ca_inv(d, a[row] + col, ctx); for (j = row + 1; j < m; j++) { ca_mul(e, a[j] + col, d, ctx); ca_neg(e, e, ctx); _ca_vec_scalar_addmul_ca(a[j] + col + 1, a[row] + col + 1, n - col - 1, e, ctx); ca_zero(a[j] + col, ctx); ca_neg(a[j] + rank - 1, e, ctx); } row++; col++; } ca_clear(d, ctx); ca_clear(e, ctx); *res_rank = rank; return success; } flint-3.1.3/src/ca_mat/lu_recursive.c000066400000000000000000000063121461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" static void _apply_permutation(slong * AP, ca_mat_t A, slong * P, slong n, slong offset) { if (n != 0) { ca_struct ** Atmp; slong *APtmp; slong i; Atmp = flint_malloc(sizeof(ca_mat_struct *) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } int ca_mat_lu_recursive(slong * rank, slong * P, ca_mat_t LU, const ca_mat_t A, int rank_check, ca_ctx_t ctx) { slong i, j, m, n, r1, r2, n1; ca_mat_t A0, A1, A00, A01, A10, A11; slong *P1; int success; r2 = 0; m = A->r; n = A->c; if (m < 4 || n < 4) return ca_mat_lu_classical(rank, P, LU, A, rank_check, ctx); if (LU != A) ca_mat_set(LU, A, ctx); n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; P1 = flint_malloc(sizeof(slong) * m); ca_mat_window_init(A0, LU, 0, 0, m, n1, ctx); ca_mat_window_init(A1, LU, 0, n1, m, n, ctx); success = ca_mat_lu_recursive(&r1, P1, A0, A0, rank_check, ctx); if (!success || (rank_check && (r1 != n1))) { success = 0; goto cleanup1; } if (r1 != 0) { _apply_permutation(P, LU, P1, m, 0); } ca_mat_window_init(A00, LU, 0, 0, r1, r1, ctx); ca_mat_window_init(A10, LU, r1, 0, m, r1, ctx); ca_mat_window_init(A01, LU, 0, n1, r1, n, ctx); ca_mat_window_init(A11, LU, r1, n1, m, n, ctx); if (r1 != 0) { ca_mat_t T; ca_mat_init(T, ca_mat_nrows(A10), ca_mat_ncols(A01), ctx); ca_mat_solve_tril(A01, A00, A01, 1, ctx); ca_mat_mul(T, A10, A01, ctx); ca_mat_sub(A11, A11, T, ctx); ca_mat_clear(T, ctx); } success = ca_mat_lu_recursive(&r2, P1, A11, A11, rank_check, ctx); if (!success || (rank_check && (r1 + r2 < FLINT_MIN(m, n)))) { r1 = r2 = 0; goto cleanup2; } _apply_permutation(P, LU, P1, m - r1, r1); /* Compress L */ if (r1 != n1) { for (i = 0; i < m - r1; i++) { ca_struct * row = LU->rows[r1 + i]; for (j = 0; j < FLINT_MIN(i, r2) ; j++) { ca_set(row + r1 + j, row + n1 + j, ctx); ca_zero(row + n1 + j, ctx); } } } cleanup2: ca_mat_window_clear(A00, ctx); ca_mat_window_clear(A10, ctx); ca_mat_window_clear(A01, ctx); ca_mat_window_clear(A11, ctx); cleanup1: flint_free(P1); ca_mat_window_clear(A0, ctx); ca_mat_window_clear(A1, ctx); *rank = r1 + r2; return success; } flint-3.1.3/src/ca_mat/mul.c000066400000000000000000000156341461254215100156200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" #include "ca_mat.h" int ca_mat_is_fmpq_mat(const ca_mat_t A, ca_ctx_t ctx) { slong ar, ac, i, j; ar = ca_mat_nrows(A); ac = ca_mat_ncols(A); for (i = 0; i < ar; i++) for (j = 0; j < ac; j++) if (!CA_IS_QQ(ca_mat_entry(A, i, j), ctx)) return 0; return 1; } int ca_fmpq_mat_is_fmpz_mat(const ca_mat_t A, ca_ctx_t ctx) { slong ar, ac, i, j; ar = ca_mat_nrows(A); ac = ca_mat_ncols(A); for (i = 0; i < ar; i++) for (j = 0; j < ac; j++) if (!fmpz_is_one(CA_FMPQ_DENREF(ca_mat_entry(A, i, j)))) return 0; return 1; } ca_field_ptr _ca_mat_same_field2(const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { ca_field_ptr K; ca_field_ptr QQ; slong i, j; QQ = ctx->field_qq; K = QQ; for (i = 0; i < ca_mat_nrows(A); i++) { for (j = 0; j < ca_mat_ncols(A); j++) { if (CA_IS_QQ(ca_mat_entry(A, i, j), ctx)) continue; if (CA_IS_SPECIAL(ca_mat_entry(A, i, j))) return NULL; if (K == QQ) K = CA_FIELD(ca_mat_entry(A, i, j), ctx); else if (K != CA_FIELD(ca_mat_entry(A, i, j), ctx)) return NULL; } } if (B != NULL) { for (i = 0; i < ca_mat_nrows(B); i++) { for (j = 0; j < ca_mat_ncols(B); j++) { if (CA_IS_QQ(ca_mat_entry(B, i, j), ctx)) continue; if (CA_IS_SPECIAL(ca_mat_entry(B, i, j))) return NULL; if (K == QQ) K = CA_FIELD(ca_mat_entry(B, i, j), ctx); else if (K != CA_FIELD(ca_mat_entry(B, i, j), ctx)) return NULL; } } } return K; } void ca_mat_mul(ca_mat_t C, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { slong ar, ac, br, bc, i, j; ca_field_ptr K; ar = ca_mat_nrows(A); ac = ca_mat_ncols(A); br = ca_mat_nrows(B); bc = ca_mat_ncols(B); if (ac != br || ar != ca_mat_nrows(C) || bc != ca_mat_ncols(C)) { flint_throw(FLINT_ERROR, "ca_mat_mul: incompatible dimensions\n"); } if (br == 0) { ca_mat_zero(C, ctx); return; } if (A == C || B == C) { ca_mat_t T; ca_mat_init(T, ar, bc, ctx); ca_mat_mul(T, A, B, ctx); ca_mat_swap(T, C, ctx); ca_mat_clear(T, ctx); return; } /* Multiply integer and rational matrices efficiently */ if (br >= 3 && ca_mat_is_fmpq_mat(A, ctx) && ca_mat_is_fmpq_mat(B, ctx)) { fmpq_mat_t AQ, BQ, CQ; fmpz_mat_t AZ, BZ, CZ; int Aintegral, Bintegral; Aintegral = Bintegral = 0; Aintegral = ca_fmpq_mat_is_fmpz_mat(A, ctx); Bintegral = ca_fmpq_mat_is_fmpz_mat(B, ctx); if (Aintegral) { fmpz_mat_init(AZ, ar, ac); for (i = 0; i < ar; i++) for (j = 0; j < ac; j++) *fmpz_mat_entry(AZ, i, j) = *CA_FMPQ_NUMREF(ca_mat_entry(A, i, j)); } else { fmpq_mat_init(AQ, ar, ac); for (i = 0; i < ar; i++) for (j = 0; j < ac; j++) *fmpq_mat_entry(AQ, i, j) = *CA_FMPQ(ca_mat_entry(A, i, j)); } if (Bintegral) { fmpz_mat_init(BZ, br, bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) *fmpz_mat_entry(BZ, i, j) = *CA_FMPQ_NUMREF(ca_mat_entry(B, i, j)); } else { fmpq_mat_init(BQ, br, bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) *fmpq_mat_entry(BQ, i, j) = *CA_FMPQ(ca_mat_entry(B, i, j)); } if (Aintegral && Bintegral) { fmpz_mat_init(CZ, ar, bc); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { _ca_make_fmpq(ca_mat_entry(C, i, j), ctx); fmpz_one(CA_FMPQ_DENREF(ca_mat_entry(C, i, j))); *fmpz_mat_entry(CZ, i, j) = *CA_FMPQ_NUMREF(ca_mat_entry(C, i, j)); } } } else { fmpq_mat_init(CQ, ar, bc); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { _ca_make_fmpq(ca_mat_entry(C, i, j), ctx); *fmpq_mat_entry(CQ, i, j) = *CA_FMPQ(ca_mat_entry(C, i, j)); } } } if (Aintegral && Bintegral) { fmpz_mat_mul(CZ, AZ, BZ); for (i = 0; i < ar; i++) for (j = 0; j < bc; j++) *CA_FMPQ_NUMREF(ca_mat_entry(C, i, j)) = *fmpz_mat_entry(CZ, i, j); flint_free(AZ->entries); flint_free(AZ->rows); flint_free(BZ->entries); flint_free(BZ->rows); flint_free(CZ->entries); flint_free(CZ->rows); } else { if (Bintegral) { fmpq_mat_mul_fmpz_mat(CQ, AQ, BZ); } else if (Aintegral) { fmpq_mat_mul_r_fmpz_mat(CQ, AZ, BQ); } else { fmpq_mat_mul(CQ, AQ, BQ); } for (i = 0; i < ar; i++) for (j = 0; j < bc; j++) *CA_FMPQ(ca_mat_entry(C, i, j)) = *fmpq_mat_entry(CQ, i, j); if (Aintegral) { flint_free(AZ->entries); flint_free(AZ->rows); } else { flint_free(AQ->entries); flint_free(AQ->rows); } if (Bintegral) { flint_free(BZ->entries); flint_free(BZ->rows); } else { flint_free(BQ->entries); flint_free(BQ->rows); } flint_free(CQ->entries); flint_free(CQ->rows); } return; } /* Multiply over number field */ /* Todo: probably needs some tuning for degree and bit size */ if (br >= 4 && ar >= 3 && bc >= 3) { K = _ca_mat_same_field2(A, B, ctx); if (K != NULL && CA_FIELD_IS_NF(K)) { ca_mat_mul_same_nf(C, A, B, K, ctx); return; } } ca_mat_mul_classical(C, A, B, ctx); } flint-3.1.3/src/ca_mat/mul_classical.c000066400000000000000000000030751461254215100176320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_mul_classical(ca_mat_t C, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { slong ar, ac, br, bc, i, j, k; ca_t t; ar = ca_mat_nrows(A); ac = ca_mat_ncols(A); br = ca_mat_nrows(B); bc = ca_mat_ncols(B); if (ac != br || ar != ca_mat_nrows(C) || bc != ca_mat_ncols(C)) { flint_throw(FLINT_ERROR, "ca_mat_mul_classical: incompatible dimensions\n"); } if (br == 0) { ca_mat_zero(C, ctx); return; } if (A == C || B == C) { ca_mat_t T; ca_mat_init(T, ar, bc, ctx); ca_mat_mul(T, A, B, ctx); ca_mat_swap(T, C, ctx); ca_mat_clear(T, ctx); return; } ca_init(t, ctx); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { ca_mul(ca_mat_entry(C, i, j), ca_mat_entry(A, i, 0), ca_mat_entry(B, 0, j), ctx); for (k = 1; k < br; k++) { ca_mul(t, ca_mat_entry(A, i, k), ca_mat_entry(B, k, j), ctx); ca_add(ca_mat_entry(C, i, j), ca_mat_entry(C, i, j), t, ctx); } } } ca_clear(t, ctx); } flint-3.1.3/src/ca_mat/mul_same_nf.c000066400000000000000000000165051461254215100173060ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_mat.h" #include "ca_mat.h" static const fmpz * _nf_denref(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) return LNF_ELEM_DENREF(a); else if (nf->flag & NF_QUADRATIC) return QNF_ELEM_DENREF(a); else return NF_ELEM_DENREF(a); } static void _nf_elem_get_fmpz_poly_lcm(fmpz_poly_t pol, fmpz_t t, const nf_elem_t a, const fmpz_t lcm, const nf_t nf) { fmpz_divexact(t, lcm, _nf_denref(a, nf)); if (nf->flag & NF_LINEAR) { fmpz_mul(t, t, LNF_ELEM_NUMREF(a)); fmpz_poly_set_fmpz(pol, t); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz_poly_fit_length(pol, 2); _fmpz_poly_set_length(pol, 2); _fmpz_vec_scalar_mul_fmpz(pol->coeffs, anum, 2, t); _fmpz_poly_normalise(pol); } else { fmpz_poly_fit_length(pol, NF_ELEM(a)->length); _fmpz_poly_set_length(pol, NF_ELEM(a)->length); _fmpz_vec_scalar_mul_fmpz(pol->coeffs, NF_ELEM(a)->coeffs, NF_ELEM(a)->length, t); } } static int get_lcm_rowwise(fmpz * Aden, const ca_mat_t A, ca_field_t K, slong bits_limit, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(A); i++) { fmpz_one(Aden + i); for (j = 0; j < ca_mat_ncols(A); j++) { if (CA_IS_QQ(ca_mat_entry(A, i, j), ctx)) fmpz_lcm(Aden + i, Aden + i, CA_FMPQ_DENREF(ca_mat_entry(A, i, j))); else fmpz_lcm(Aden + i, Aden + i, _nf_denref(CA_NF_ELEM(ca_mat_entry(A, i, j)), CA_FIELD_NF(K))); if (fmpz_bits(Aden + i) > bits_limit) return 0; } } return 1; } static int get_lcm_colwise(fmpz * Aden, const ca_mat_t A, ca_field_t K, slong bits_limit, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_ncols(A); i++) { fmpz_one(Aden + i); for (j = 0; j < ca_mat_nrows(A); j++) { if (CA_IS_QQ(ca_mat_entry(A, j, i), ctx)) fmpz_lcm(Aden + i, Aden + i, CA_FMPQ_DENREF(ca_mat_entry(A, j, i))); else fmpz_lcm(Aden + i, Aden + i, _nf_denref(CA_NF_ELEM(ca_mat_entry(A, j, i)), CA_FIELD_NF(K))); if (fmpz_bits(Aden + i) > bits_limit) return 0; } } return 1; } static void get_mat_rowwise(fmpz_poly_mat_t Aclear, const ca_mat_t A, const fmpz * Aden, ca_field_t K, ca_ctx_t ctx) { slong i, j; fmpz_t t; fmpz_init(t); for (i = 0; i < ca_mat_nrows(A); i++) { for (j = 0; j < ca_mat_ncols(A); j++) { if (CA_IS_QQ(ca_mat_entry(A, i, j), ctx)) { fmpz_divexact(t, Aden + i, CA_FMPQ_DENREF(ca_mat_entry(A, i, j))); fmpz_mul(t, t, CA_FMPQ_NUMREF(ca_mat_entry(A, i, j))); fmpz_poly_set_fmpz(fmpz_poly_mat_entry(Aclear, i, j), t); } else { _nf_elem_get_fmpz_poly_lcm(fmpz_poly_mat_entry(Aclear, i, j), t, CA_NF_ELEM(ca_mat_entry(A, i, j)), Aden + i, CA_FIELD_NF(K)); } } } fmpz_clear(t); } static void get_mat_colwise(fmpz_poly_mat_t Aclear, const ca_mat_t A, const fmpz * Aden, ca_field_t K, ca_ctx_t ctx) { slong i, j; fmpz_t t; fmpz_init(t); for (i = 0; i < ca_mat_ncols(A); i++) { for (j = 0; j < ca_mat_nrows(A); j++) { if (CA_IS_QQ(ca_mat_entry(A, j, i), ctx)) { fmpz_divexact(t, Aden + i, CA_FMPQ_DENREF(ca_mat_entry(A, j, i))); fmpz_mul(t, t, CA_FMPQ_NUMREF(ca_mat_entry(A, j, i))); fmpz_poly_set_fmpz(fmpz_poly_mat_entry(Aclear, j, i), t); } else { _nf_elem_get_fmpz_poly_lcm(fmpz_poly_mat_entry(Aclear, j, i), t, CA_NF_ELEM(ca_mat_entry(A, j, i)), Aden + i, CA_FIELD_NF(K)); } } } fmpz_clear(t); } void _ca_set_nf_fmpz_poly_den(ca_t res, const fmpz_poly_t poly, const fmpz_t den, ca_field_t K, ca_ctx_t ctx) { if (poly->length == 0) { ca_zero(res, ctx); } else if (poly->length == 1) { _ca_make_fmpq(res, ctx); fmpz_gcd(CA_FMPQ_DENREF(res), poly->coeffs, den); fmpz_divexact(CA_FMPQ_NUMREF(res), poly->coeffs, CA_FMPQ_DENREF(res)); fmpz_divexact(CA_FMPQ_DENREF(res), den, CA_FMPQ_DENREF(res)); } else { fmpq_poly_t T; T->coeffs = poly->coeffs; T->length = poly->length; T->alloc = poly->alloc; T->den[0] = den[0]; _ca_make_field_element(res, K, ctx); /* work around antic bug */ if (CA_FIELD_NF(K)->flag & NF_QUADRATIC) { fmpz_set(QNF_ELEM_NUMREF(CA_NF_ELEM(res)), T->coeffs); fmpz_set(QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 1, T->coeffs + 1); if (T->length == 3) fmpz_set(QNF_ELEM_NUMREF(CA_NF_ELEM(res)) + 2, T->coeffs + 2); fmpz_set(QNF_ELEM_DENREF(CA_NF_ELEM(res)), den); /* todo: canonicalise before reduction? */ } else { nf_elem_set_fmpq_poly(CA_NF_ELEM(res), T, CA_FIELD_NF(K)); } nf_elem_reduce(CA_NF_ELEM(res), CA_FIELD_NF(K)); /* antic is currently inconsistent about canonicalising in reduce() */ if (CA_FIELD_NF(K)->flag & NF_LINEAR) nf_elem_canonicalise(CA_NF_ELEM(res), CA_FIELD_NF(K)); /* may have reduced to a rational */ ca_condense_field(res, ctx); } } void ca_mat_mul_same_nf(ca_mat_t C, const ca_mat_t A, const ca_mat_t B, ca_field_t K, ca_ctx_t ctx) { fmpz_poly_mat_t ZC, ZA, ZB; fmpz * Aden, * Bden; fmpz_t den; slong Ar, Ac, Br, Bc; slong i, j; Ar = ca_mat_nrows(A); Ac = ca_mat_ncols(A); Br = ca_mat_nrows(B); Bc = ca_mat_ncols(B); if (Ar == 0 || Ac == 0 || Bc == 0) { ca_mat_zero(C, ctx); return; } if (!CA_FIELD_IS_NF(K)) { flint_throw(FLINT_ERROR, "ca_mat_mul_same_nf: expected a number field\n"); } Aden = _fmpz_vec_init(Ar); Bden = _fmpz_vec_init(Bc); if (!get_lcm_rowwise(Aden, A, K, 1000, ctx) || !get_lcm_colwise(Bden, B, K, 1000, ctx)) { _fmpz_vec_clear(Aden, Ar); _fmpz_vec_clear(Bden, Bc); ca_mat_mul_classical(C, A, B, ctx); return; } fmpz_init(den); fmpz_poly_mat_init(ZA, Ar, Ac); fmpz_poly_mat_init(ZB, Br, Bc); fmpz_poly_mat_init(ZC, Ar, Bc); get_mat_rowwise(ZA, A, Aden, K, ctx); get_mat_colwise(ZB, B, Bden, K, ctx); fmpz_poly_mat_mul(ZC, ZA, ZB); for (i = 0; i < ca_mat_nrows(C); i++) { for (j = 0; j < ca_mat_ncols(C); j++) { fmpz_mul(den, Aden + i, Bden + j); _ca_set_nf_fmpz_poly_den(ca_mat_entry(C, i, j), fmpz_poly_mat_entry(ZC, i, j), den, K, ctx); } } fmpz_poly_mat_clear(ZA); fmpz_poly_mat_clear(ZB); fmpz_poly_mat_clear(ZC); _fmpz_vec_clear(Aden, Ar); _fmpz_vec_clear(Bden, Bc); fmpz_clear(den); } flint-3.1.3/src/ca_mat/neg.c000066400000000000000000000012421461254215100155620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_neg(ca_mat_t dest, const ca_mat_t src, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(src); i++) for (j = 0; j < ca_mat_ncols(src); j++) ca_neg(ca_mat_entry(dest, i, j), ca_mat_entry(src, i, j), ctx); } flint-3.1.3/src/ca_mat/nonsingular_fflu.c000066400000000000000000000015231461254215100203660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_nonsingular_fflu(slong * P, ca_mat_t LU, ca_t den, const ca_mat_t A, ca_ctx_t ctx) { if (ca_mat_is_empty(A)) { ca_one(den, ctx); return T_TRUE; } else { int success; slong rank; success = ca_mat_fflu(&rank, P, LU, den, A, 1, ctx); if (success == 0) return T_UNKNOWN; if (rank == 0) return T_FALSE; return T_TRUE; } } flint-3.1.3/src/ca_mat/nonsingular_lu.c000066400000000000000000000014461461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_nonsingular_lu(slong * P, ca_mat_t LU, const ca_mat_t A, ca_ctx_t ctx) { if (ca_mat_is_empty(A)) { return T_TRUE; } else { int success; slong rank; success = ca_mat_lu(&rank, P, LU, A, 1, ctx); if (success == 0) return T_UNKNOWN; if (rank == 0) return T_FALSE; return T_TRUE; } } flint-3.1.3/src/ca_mat/nonsingular_solve.c000066400000000000000000000010551461254215100205620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_nonsingular_solve(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { return ca_mat_nonsingular_solve_lu(X, A, B, ctx); } flint-3.1.3/src/ca_mat/nonsingular_solve_adjugate.c000066400000000000000000000017671461254215100224400ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" truth_t ca_mat_nonsingular_solve_adjugate(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { truth_t result; ca_t det; ca_mat_t T; ca_init(det, ctx); ca_mat_init(T, ca_mat_nrows(A), ca_mat_ncols(A), ctx); ca_mat_adjugate(T, det, A, ctx); result = ca_check_is_zero(det, ctx); if (result == T_TRUE) result = T_FALSE; else if (result == T_FALSE) result = T_TRUE; if (result == T_TRUE) { ca_mat_mul(X, T, B, ctx); ca_mat_div_ca(X, X, det, ctx); } ca_mat_clear(T, ctx); ca_clear(det, ctx); return result; } flint-3.1.3/src/ca_mat/nonsingular_solve_fflu.c000066400000000000000000000020041461254215100215710ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "ca_mat.h" truth_t ca_mat_nonsingular_solve_fflu(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { truth_t result; slong n, m, *perm; ca_mat_t LU; ca_t den; n = ca_mat_nrows(A); m = ca_mat_ncols(X); if (n == 0) return T_TRUE; perm = _perm_init(n); ca_mat_init(LU, n, n, ctx); ca_init(den, ctx); result = ca_mat_nonsingular_fflu(perm, LU, den, A, ctx); if (result == T_TRUE && m != 0) ca_mat_solve_fflu_precomp(X, perm, LU, den, B, ctx); ca_mat_clear(LU, ctx); _perm_clear(perm); ca_clear(den, ctx); return result; } flint-3.1.3/src/ca_mat/nonsingular_solve_lu.c000066400000000000000000000016671461254215100212730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "ca_mat.h" truth_t ca_mat_nonsingular_solve_lu(ca_mat_t X, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { truth_t result; slong n, m, *perm; ca_mat_t LU; n = ca_mat_nrows(A); m = ca_mat_ncols(X); if (n == 0) return T_TRUE; perm = _perm_init(n); ca_mat_init(LU, n, n, ctx); result = ca_mat_nonsingular_lu(perm, LU, A, ctx); if (result == T_TRUE && m != 0) ca_mat_solve_lu_precomp(X, perm, LU, B, ctx); ca_mat_clear(LU, ctx); _perm_clear(perm); return result; } flint-3.1.3/src/ca_mat/one.c000066400000000000000000000013071461254215100155740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_one(ca_mat_t mat, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(mat); i++) for (j = 0; j < ca_mat_ncols(mat); j++) if (i == j) ca_one(ca_mat_entry(mat, i, j), ctx); else ca_zero(ca_mat_entry(mat, i, j), ctx); } flint-3.1.3/src/ca_mat/ones.c000066400000000000000000000012011461254215100157500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_ones(ca_mat_t mat, ca_ctx_t ctx) { slong R, C, i, j; R = ca_mat_nrows(mat); C = ca_mat_ncols(mat); for (i = 0; i < R; i++) for (j = 0; j < C; j++) ca_one(ca_mat_entry(mat, i, j), ctx); } flint-3.1.3/src/ca_mat/pascal.c000066400000000000000000000012101461254215100162470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void ca_mat_pascal(ca_mat_t mat, int triangular, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_pascal((gr_mat_struct *) mat, triangular, gr_ctx)); } flint-3.1.3/src/ca_mat/pow_ui_binexp.c000066400000000000000000000026721461254215100176700ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_pow_ui_binexp(ca_mat_t B, const ca_mat_t A, ulong exp, ca_ctx_t ctx) { slong d = ca_mat_nrows(A); if (exp <= 2 || d <= 1) { if (exp == 0 || d == 0) { ca_mat_one(B, ctx); } else if (d == 1) { ca_pow_ui(ca_mat_entry(B, 0, 0), ca_mat_entry(A, 0, 0), exp, ctx); } else if (exp == 1) { ca_mat_set(B, A, ctx); } else if (exp == 2) { ca_mat_sqr(B, A, ctx); } } else { ca_mat_t T, U; slong i; ca_mat_init(T, d, d, ctx); ca_mat_set(T, A, ctx); ca_mat_init(U, d, d, ctx); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { ca_mat_sqr(U, T, ctx); if (exp & (WORD(1) << i)) ca_mat_mul(T, U, A, ctx); else ca_mat_swap(T, U, ctx); } ca_mat_swap(B, T, ctx); ca_mat_clear(T, ctx); ca_mat_clear(U, ctx); } } flint-3.1.3/src/ca_mat/print.c000066400000000000000000000025631461254215100161540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_print(const ca_mat_t mat, ca_ctx_t ctx) { slong r, c; slong i, j; r = ca_mat_nrows(mat); c = ca_mat_ncols(mat); flint_printf("ca_mat of size %wd x %wd:\n", r, c); for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { flint_printf(" "); ca_print(ca_mat_entry(mat, i, j), ctx); flint_printf("\n"); } } flint_printf("\n"); } void ca_mat_printn(const ca_mat_t mat, slong digits, ca_ctx_t ctx) { slong r, c; slong i, j; r = ca_mat_nrows(mat); c = ca_mat_ncols(mat); flint_printf("["); for (i = 0; i < r; i++) { flint_printf("["); for (j = 0; j < c; j++) { ca_printn(ca_mat_entry(mat, i, j), digits, ctx); if (j < c - 1) flint_printf(", "); } if (i < r - 1) flint_printf("],\n"); else flint_printf("]"); } flint_printf("]\n"); } flint-3.1.3/src/ca_mat/randops.c000066400000000000000000000031431461254215100164610ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_randops(ca_mat_t mat, flint_rand_t state, slong count, ca_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; if (mat->r == 0 || mat->c == 0) return; for (c = 0; c < count; c++) { if (n_randint(state, 2)) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) ca_add(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); else for (k = 0; k < n; k++) ca_sub(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); } else { if ((i = n_randint(state, n)) == (j = n_randint(state, n))) continue; if (n_randint(state, 2)) for (k = 0; k < m; k++) ca_add(ca_mat_entry(mat, k, j), ca_mat_entry(mat, k, j), ca_mat_entry(mat, k, i), ctx); else for (k = 0; k < m; k++) ca_sub(ca_mat_entry(mat, k, j), ca_mat_entry(mat, k, j), ca_mat_entry(mat, k, i), ctx); } } } flint-3.1.3/src/ca_mat/randtest.c000066400000000000000000000024411461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_randtest(ca_mat_t mat, flint_rand_t state, slong length, slong bits, ca_ctx_t ctx) { slong i, j, density; density = n_randint(state, 100); for (i = 0; i < ca_mat_nrows(mat); i++) for (j = 0; j < ca_mat_ncols(mat); j++) if (n_randint(state, 100) < density) ca_randtest(ca_mat_entry(mat, i, j), state, length, bits, ctx); else ca_zero(ca_mat_entry(mat, i, j), ctx); } void ca_mat_randtest_rational(ca_mat_t mat, flint_rand_t state, slong bits, ca_ctx_t ctx) { slong i, j, density; density = n_randint(state, 100); for (i = 0; i < ca_mat_nrows(mat); i++) for (j = 0; j < ca_mat_ncols(mat); j++) if (n_randint(state, 100) < density) ca_randtest_rational(ca_mat_entry(mat, i, j), state, bits, ctx); else ca_zero(ca_mat_entry(mat, i, j), ctx); } flint-3.1.3/src/ca_mat/rank.c000066400000000000000000000015651461254215100157540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "ca_mat.h" /* todo: different algorithms... */ int ca_mat_rank(slong * rank, const ca_mat_t A, ca_ctx_t ctx) { slong n, m; slong * P; int success; ca_mat_t T; n = ca_mat_nrows(A); m = ca_mat_ncols(A); if (n == 0 || m == 0) { *rank = 0; return 1; } ca_mat_init(T, n, m, ctx); P = _perm_init(n); success = ca_mat_lu(rank, P, T, A, 0, ctx); ca_mat_clear(T, ctx); _perm_clear(P); return success; } flint-3.1.3/src/ca_mat/right_kernel.c000066400000000000000000000045521461254215100174750ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" int ca_mat_right_kernel(ca_mat_t X, const ca_mat_t A, ca_ctx_t ctx) { slong i, j, k, m, n, rank, nullity; slong *p; slong *pivots; slong *nonpivots; ca_mat_t tmp; int success; m = ca_mat_nrows(A); n = ca_mat_ncols(A); p = flint_malloc(sizeof(slong) * FLINT_MAX(m, n)); ca_mat_init(tmp, m, n, ctx); success = ca_mat_rref(&rank, tmp, A, ctx); nullity = n - rank; if (!success) goto cleanup; ca_mat_clear(X, ctx); ca_mat_init(X, n, nullity, ctx); success = 1; if (rank == 0) { for (i = 0; i < nullity; i++) ca_one(ca_mat_entry(X, i, i), ctx); } else if (nullity) { pivots = p; /* length = rank */ nonpivots = p + rank; /* length = nullity */ for (i = j = k = 0; i < rank; i++) { while (1) { /* Todo: this should not be T_UNKNOWN. Should we save the pivot data in the lu algorithm? */ truth_t is_zero = ca_check_is_zero(ca_mat_entry(tmp, i, j), ctx); if (is_zero == T_FALSE) { break; } else if (is_zero == T_TRUE) { nonpivots[k] = j; k++; j++; } else { success = 0; goto cleanup; } } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) ca_neg(ca_mat_entry(X, pivots[j], i), ca_mat_entry(tmp, j, nonpivots[i]), ctx); ca_one(ca_mat_entry(X, nonpivots[i], i), ctx); } } cleanup: flint_free(p); ca_mat_clear(tmp, ctx); return success; } flint-3.1.3/src/ca_mat/rref.c000066400000000000000000000010161461254215100157460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" int ca_mat_rref(slong * rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx) { return ca_mat_rref_lu(rank, R, A, ctx); } flint-3.1.3/src/ca_mat/rref_fflu.c000066400000000000000000000067231461254215100167740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" int ca_mat_rref_fflu(slong * res_rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx) { slong i, j, k, m, n, rank; slong *pivots, *nonpivots; ca_t den; int success; ca_init(den, ctx); success = ca_mat_fflu(&rank, NULL, R, den, A, 0, ctx); if (!success) { ca_clear(den, ctx); return 0; } m = ca_mat_nrows(R); n = ca_mat_ncols(R); /* clear bottom */ for (i = rank; i < m; i++) for (j = 0; j < n; j++) ca_zero(ca_mat_entry(R, i, j), ctx); /* Convert row echelon form to reduced row echelon form */ if (rank > 1) { ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); pivots = flint_malloc(sizeof(slong) * n); nonpivots = pivots + rank; for (i = j = k = 0; i < rank; i++) { while (1) { /* Todo: this should not be T_UNKNOWN. Should we save the pivot data in the lu algorithm? */ truth_t is_zero = ca_check_is_zero(ca_mat_entry(R, i, j), ctx); if (is_zero == T_FALSE) { break; } else if (is_zero == T_TRUE) { nonpivots[k] = j; k++; j++; } else { success = 0; goto cleanup1; } } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (k = 0; k < n - rank; k++) { for (i = rank - 2; i >= 0; i--) { ca_mul(t, den, ca_mat_entry(R, i, nonpivots[k]), ctx); for (j = i + 1; j < rank; j++) { ca_mul(u, ca_mat_entry(R, i, pivots[j]), ca_mat_entry(R, j, nonpivots[k]), ctx); ca_sub(t, t, u, ctx); } ca_div(ca_mat_entry(R, i, nonpivots[k]), t, ca_mat_entry(R, i, pivots[i]), ctx); } } /* clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { if (i == j) ca_one(ca_mat_entry(R, j, pivots[i]), ctx); else ca_zero(ca_mat_entry(R, j, pivots[i]), ctx); } } /* divide out denominator */ if (ca_check_is_one(den, ctx) != T_TRUE) for (i = 0; i < rank; i++) for (j = 0; j < n - rank; j++) ca_div(ca_mat_entry(R, i, nonpivots[j]), ca_mat_entry(R, i, nonpivots[j]), den, ctx); cleanup1: flint_free(pivots); ca_clear(t, ctx); ca_clear(u, ctx); } else if (rank == 1 && ca_check_is_one(den, ctx) != T_TRUE) { for (i = 0; i < n; i++) ca_div(ca_mat_entry(R, 0, i), ca_mat_entry(R, 0, i), den, ctx); } ca_clear(den, ctx); *res_rank = rank; return success; } flint-3.1.3/src/ca_mat/rref_lu.c000066400000000000000000000064401461254215100164540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "ca_mat.h" int ca_mat_rref_lu(slong * res_rank, ca_mat_t R, const ca_mat_t A, ca_ctx_t ctx) { slong i, j, k, n, rank; slong *pivots; slong *nonpivots; slong *P; ca_mat_t U, V; int success; if (ca_mat_check_is_zero(A, ctx) == T_TRUE) { *res_rank = 0; return 1; } /* Todo: fast path for nrows == 1 */ n = A->c; P = _perm_init(ca_mat_nrows(A)); success = ca_mat_lu(&rank, P, R, A, 0, ctx); _perm_clear(P); if (!success) return 0; if (rank == 0) { *res_rank = 0; return 1; } /* Clear L */ for (i = 0; i < A->r; i++) for (j = 0; j < FLINT_MIN(i, rank); j++) ca_zero(ca_mat_entry(R, i, j), ctx); /* We now reorder U to proper upper triangular form U | V with U full-rank triangular, set V = U^(-1) V, and then put the column back in the original order. An improvement for some matrices would be to compress V by discarding columns containing nothing but zeros. */ ca_mat_init(U, rank, rank, ctx); ca_mat_init(V, rank, n - rank, ctx); pivots = flint_malloc(sizeof(slong) * rank); nonpivots = flint_malloc(sizeof(slong) * (n - rank)); for (i = j = k = 0; i < rank; i++) { while (1) { /* Todo: this should not be T_UNKNOWN. Should we save the pivot data in the lu algorithm? */ truth_t is_zero = ca_check_is_zero(ca_mat_entry(R, i, j), ctx); if (is_zero == T_FALSE) { break; } else if (is_zero == T_TRUE) { nonpivots[k] = j; k++; j++; } else { success = 0; goto cleanup1; } } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (i = 0; i < rank; i++) for (j = 0; j <= i; j++) ca_set(ca_mat_entry(U, j, i), ca_mat_entry(R, j, pivots[i]), ctx); for (i = 0; i < n - rank; i++) for (j = 0; j < rank; j++) ca_set(ca_mat_entry(V, j, i), ca_mat_entry(R, j, nonpivots[i]), ctx); ca_mat_solve_triu(V, U, V, 0, ctx); /* Clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j <= i; j++) { if (i == j) ca_one(ca_mat_entry(R, j, pivots[i]), ctx); else ca_zero(ca_mat_entry(R, j, pivots[i]), ctx); } } /* Write back the actual content */ for (i = 0; i < n - rank; i++) for (j = 0; j < rank; j++) ca_set(ca_mat_entry(R, j, nonpivots[i]), ca_mat_entry(V, j, i), ctx); cleanup1: ca_mat_clear(U, ctx); ca_mat_clear(V, ctx); flint_free(pivots); flint_free(nonpivots); *res_rank = rank; return 1; } flint-3.1.3/src/ca_mat/set.c000066400000000000000000000013551461254215100156110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_set(ca_mat_t dest, const ca_mat_t src, ca_ctx_t ctx) { slong i, j; if (dest != src && ca_mat_ncols(src) != 0) { for (i = 0; i < ca_mat_nrows(src); i++) for (j = 0; j < ca_mat_ncols(src); j++) ca_set(ca_mat_entry(dest, i, j), ca_mat_entry(src, i, j), ctx); } } flint-3.1.3/src/ca_mat/set_ca.c000066400000000000000000000013611461254215100162510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_set_ca(ca_mat_t y, const ca_t x, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(y); i++) { for (j = 0; j < ca_mat_ncols(y); j++) { if (i == j) ca_set(ca_mat_entry(y, i, j), x, ctx); else ca_zero(ca_mat_entry(y, i, j), ctx); } } } flint-3.1.3/src/ca_mat/set_fmpq_mat.c000066400000000000000000000014111461254215100174660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" #include "ca_mat.h" void ca_mat_set_fmpq_mat(ca_mat_t dest, const fmpq_mat_t src, ca_ctx_t ctx) { slong i, j; if (ca_mat_ncols(dest) != 0) { for (i = 0; i < ca_mat_nrows(dest); i++) for (j = 0; j < ca_mat_ncols(dest); j++) ca_set_fmpq(ca_mat_entry(dest, i, j), fmpq_mat_entry(src, i, j), ctx); } } flint-3.1.3/src/ca_mat/set_fmpz_mat.c000066400000000000000000000014111461254215100174770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "ca_mat.h" void ca_mat_set_fmpz_mat(ca_mat_t dest, const fmpz_mat_t src, ca_ctx_t ctx) { slong i, j; if (ca_mat_ncols(dest) != 0) { for (i = 0; i < ca_mat_nrows(dest); i++) for (j = 0; j < ca_mat_ncols(dest); j++) ca_set_fmpz(ca_mat_entry(dest, i, j), fmpz_mat_entry(src, i, j), ctx); } } flint-3.1.3/src/ca_mat/solve_fflu_precomp.c000066400000000000000000000045341461254215100207110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_solve_fflu_precomp(ca_mat_t X, const slong * perm, const ca_mat_t A, const ca_t den, const ca_mat_t B, ca_ctx_t ctx) { ca_t t; slong i, j, k, c, n, m; n = ca_mat_nrows(X); m = ca_mat_ncols(X); if (X == B) { ca_ptr tmp = flint_malloc(sizeof(ca_struct) * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) tmp[i] = B->rows[perm[i]][c]; for (i = 0; i < n; i++) X->rows[i][c] = tmp[i]; } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { ca_set(ca_mat_entry(X, i, c), ca_mat_entry(B, perm[i], c), ctx); } } } ca_init(t, ctx); for (k = 0; k < m; k++) { /* Fraction-free forward substitution */ for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { ca_mul(ca_mat_entry(X, j, k), ca_mat_entry(X, j, k), ca_mat_entry(A, i, i), ctx); ca_mul(t, ca_mat_entry(A, j, i), ca_mat_entry(X, i, k), ctx); ca_sub(ca_mat_entry(X, j, k), ca_mat_entry(X, j, k), t, ctx); if (i > 0) ca_div(ca_mat_entry(X, j, k), ca_mat_entry(X, j, k), ca_mat_entry(A, i-1, i-1), ctx); } } /* Fraction-free back substitution */ for (i = n - 2; i >= 0; i--) { ca_mul(ca_mat_entry(X, i, k), ca_mat_entry(X, i, k), ca_mat_entry(A, n-1, n-1), ctx); for (j = i + 1; j < n; j++) { ca_mul(t, ca_mat_entry(X, j, k), ca_mat_entry(A, i, j), ctx); ca_sub(ca_mat_entry(X, i, k), ca_mat_entry(X, i, k), t, ctx); } ca_div(ca_mat_entry(X, i, k), ca_mat_entry(X, i, k), ca_mat_entry(A, i, i), ctx); } } ca_mat_div_ca(X, X, den, ctx); ca_clear(t, ctx); } flint-3.1.3/src/ca_mat/solve_lu_precomp.c000066400000000000000000000023731461254215100203740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_solve_lu_precomp(ca_mat_t X, const slong * perm, const ca_mat_t A, const ca_mat_t B, ca_ctx_t ctx) { slong i, c, n, m; n = ca_mat_nrows(X); m = ca_mat_ncols(X); if (X == B) { ca_ptr tmp = flint_malloc(sizeof(ca_struct) * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) tmp[i] = B->rows[perm[i]][c]; for (i = 0; i < n; i++) X->rows[i][c] = tmp[i]; } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { ca_set(ca_mat_entry(X, i, c), ca_mat_entry(B, perm[i], c), ctx); } } } /* todo: inline for small n? */ ca_mat_solve_tril(X, A, X, 1, ctx); ca_mat_solve_triu(X, A, X, 0, ctx); } flint-3.1.3/src/ca_mat/solve_tril.c000066400000000000000000000026401461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void ca_mat_solve_tril_classical(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_nonsingular_solve_tril_classical((gr_mat_struct *) X, (const gr_mat_struct *) L, (const gr_mat_struct *) B, unit, gr_ctx)); } void ca_mat_solve_tril_recursive(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_nonsingular_solve_tril_recursive((gr_mat_struct *) X, (const gr_mat_struct *) L, (const gr_mat_struct *) B, unit, gr_ctx)); } void ca_mat_solve_tril(ca_mat_t X, const ca_mat_t L, const ca_mat_t B, int unit, ca_ctx_t ctx) { /* todo: tune thresholds */ if (B->r < 10 || B->c < 10) ca_mat_solve_tril_classical(X, L, B, unit, ctx); else ca_mat_solve_tril_recursive(X, L, B, unit, ctx); } flint-3.1.3/src/ca_mat/solve_triu.c000066400000000000000000000026331461254215100172110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void ca_mat_solve_triu_classical(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_nonsingular_solve_triu_classical((gr_mat_struct *) X, (const gr_mat_struct *) U, (const gr_mat_struct *) B, unit, gr_ctx)); } void ca_mat_solve_triu_recursive(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_nonsingular_solve_triu_recursive((gr_mat_struct *) X, (const gr_mat_struct *) U, (const gr_mat_struct *) B, unit, gr_ctx));} void ca_mat_solve_triu(ca_mat_t X, const ca_mat_t U, const ca_mat_t B, int unit, ca_ctx_t ctx) { /* todo: tune thresholds */ if (B->r < 10 || B->c < 10) ca_mat_solve_triu_classical(X, U, B, unit, ctx); else ca_mat_solve_triu_recursive(X, U, B, unit, ctx); } flint-3.1.3/src/ca_mat/stirling.c000066400000000000000000000012001461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" #include "gr_mat.h" void ca_mat_stirling(ca_mat_t mat, int kind, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(gr_mat_stirling((gr_mat_struct *) mat, kind, gr_ctx)); } flint-3.1.3/src/ca_mat/sub.c000066400000000000000000000013531461254215100156050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_sub(ca_mat_t res, const ca_mat_t mat1, const ca_mat_t mat2, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(mat1); i++) for (j = 0; j < ca_mat_ncols(mat1); j++) ca_sub(ca_mat_entry(res, i, j), ca_mat_entry(mat1, i, j), ca_mat_entry(mat2, i, j), ctx); } flint-3.1.3/src/ca_mat/sub_ca.c000066400000000000000000000020571461254215100162520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_sub_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx) { slong i, j, n; if (a == y) { n = FLINT_MIN(ca_mat_nrows(a), ca_mat_ncols(a)); for (i = 0; i < n; i++) ca_sub(ca_mat_entry(y, i, i), ca_mat_entry(y, i, i), x, ctx); } else { for (i = 0; i < ca_mat_nrows(a); i++) { for (j = 0; j < ca_mat_ncols(a); j++) { if (i == j) ca_sub(ca_mat_entry(y, i, j), ca_mat_entry(a, i, j), x, ctx); else ca_set(ca_mat_entry(y, i, j), ca_mat_entry(a, i, j), ctx); } } } } flint-3.1.3/src/ca_mat/submul_ca.c000066400000000000000000000014521461254215100167660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_submul_ca(ca_mat_t y, const ca_mat_t a, const ca_t x, ca_ctx_t ctx) { slong i, j; ca_t t; ca_init(t, ctx); for (i = 0; i < ca_mat_nrows(a); i++) { for (j = 0; j < ca_mat_ncols(a); j++) { ca_mul(t, ca_mat_entry(a, i, j), x, ctx); ca_sub(ca_mat_entry(y, i, j), ca_mat_entry(y, i, j), t, ctx); } } ca_clear(t, ctx); } flint-3.1.3/src/ca_mat/test/000077500000000000000000000000001461254215100156255ustar00rootroot00000000000000flint-3.1.3/src/ca_mat/test/main.c000066400000000000000000000047351461254215100167260ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-adjugate.c" #include "t-ca_poly_evaluate.c" #include "t-charpoly.c" #include "t-charpoly_danilevsky.c" #include "t-companion.c" #include "t-det.c" #include "t-dft.c" #include "t-diagonalization.c" #include "t-exp.c" #include "t-inv.c" #include "t-jordan_blocks.c" #include "t-jordan_form.c" #include "t-lu.c" #include "t-lu_classical.c" #include "t-lu_recursive.c" #include "t-mul.c" #include "t-mul_same_nf.c" #include "t-nonsingular_solve_adjugate.c" #include "t-nonsingular_solve.c" #include "t-nonsingular_solve_fflu.c" #include "t-nonsingular_solve_lu.c" #include "t-rank.c" #include "t-right_kernel.c" #include "t-rref.c" #include "t-rref_fflu.c" #include "t-rref_lu.c" #include "t-solve_tril.c" #include "t-solve_triu.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(ca_mat_adjugate), TEST_FUNCTION(ca_mat_ca_poly_evaluate), TEST_FUNCTION(ca_mat_charpoly), TEST_FUNCTION(ca_mat_charpoly_danilevsky), TEST_FUNCTION(ca_mat_companion), TEST_FUNCTION(ca_mat_det), TEST_FUNCTION(ca_mat_dft), TEST_FUNCTION(ca_mat_diagonalization), TEST_FUNCTION(ca_mat_exp), TEST_FUNCTION(ca_mat_inv), TEST_FUNCTION(ca_mat_jordan_blocks), TEST_FUNCTION(ca_mat_jordan_form), TEST_FUNCTION(ca_mat_lu), TEST_FUNCTION(ca_mat_lu_classical), TEST_FUNCTION(ca_mat_lu_recursive), TEST_FUNCTION(ca_mat_mul), TEST_FUNCTION(ca_mat_mul_same_nf), TEST_FUNCTION(ca_mat_nonsingular_solve_adjugate), TEST_FUNCTION(ca_mat_nonsingular_solve), TEST_FUNCTION(ca_mat_nonsingular_solve_fflu), TEST_FUNCTION(ca_mat_nonsingular_solve_lu), TEST_FUNCTION(ca_mat_rank), TEST_FUNCTION(ca_mat_right_kernel), TEST_FUNCTION(ca_mat_rref), TEST_FUNCTION(ca_mat_rref_fflu), TEST_FUNCTION(ca_mat_rref_lu), TEST_FUNCTION(ca_mat_solve_tril), TEST_FUNCTION(ca_mat_solve_triu) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/ca_mat/test/t-adjugate.c000066400000000000000000000033561461254215100200250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_adjugate, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, C; ca_t d, e; slong n; ca_ctx_init(ctx); n = n_randint(state, 5); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_mat_init(C, n, n, ctx); ca_init(d, ctx); ca_init(e, ctx); ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_adjugate_cofactor(B, d, A, ctx); ca_mat_adjugate_charpoly(C, e, A, ctx); if (ca_mat_check_equal(B, C, ctx) == T_FALSE || ca_check_equal(d, e, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A = "), ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "), ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "), ca_mat_print(C, ctx); flint_printf("\n"); flint_printf("d = "), ca_print(d, ctx); flint_printf("\n"); flint_printf("e = "), ca_print(e, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(C, ctx); ca_clear(d, ctx); ca_clear(e, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-ca_poly_evaluate.c000066400000000000000000000046121461254215100215510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_ca_poly_evaluate, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, fA, gA, fgA, fAgA; ca_poly_t f, g, fg; slong n; n = n_randint(state, 3); ca_ctx_init(ctx); ca_mat_init(A, n, n, ctx); ca_mat_init(fA, n, n, ctx); ca_mat_init(gA, n, n, ctx); ca_mat_init(fgA, n, n, ctx); ca_mat_init(fAgA, n, n, ctx); ca_poly_init(f, ctx); ca_poly_init(g, ctx); ca_poly_init(fg, ctx); ca_mat_randtest(A, state, 1, 10, ctx); ca_mat_randtest(fA, state, 2, 10, ctx); ca_mat_randtest(gA, state, 2, 10, ctx); ca_mat_randtest(fgA, state, 2, 10, ctx); ca_poly_randtest_rational(f, state, 10, 5, ctx); ca_poly_randtest_rational(g, state, 10, 5, ctx); ca_poly_add(fg, f, g, ctx); ca_mat_ca_poly_evaluate(fA, f, A, ctx); ca_mat_set(gA, A, ctx); ca_mat_ca_poly_evaluate(gA, g, gA, ctx); ca_mat_ca_poly_evaluate(fgA, fg, A, ctx); ca_mat_add(fAgA, fA, gA, ctx); if (ca_mat_check_equal(fgA, fAgA, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "); ca_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); ca_poly_print(g, ctx); flint_printf("\n"); flint_printf("fgA = "); ca_mat_print(fgA, ctx); flint_printf("\n"); flint_printf("fAgA = "); ca_mat_print(fAgA, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(fA, ctx); ca_mat_clear(gA, ctx); ca_mat_clear(fgA, ctx); ca_mat_clear(fAgA, ctx); ca_poly_clear(f, ctx); ca_poly_clear(g, ctx); ca_poly_clear(fg, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-charpoly.c000066400000000000000000000027351461254215100200620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_charpoly, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, fA; ca_poly_t f; slong n; ca_ctx_init(ctx); n = n_randint(state, 5); ca_mat_init(A, n, n, ctx); ca_mat_init(fA, n, n, ctx); ca_poly_init(f, ctx); ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_charpoly(f, A, ctx); ca_mat_ca_poly_evaluate(fA, f, A, ctx); if (f->length != (n + 1) || ca_mat_check_is_zero(fA, ctx) != T_TRUE) { flint_printf("FAIL\n"); flint_printf("A = "), ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "), ca_poly_print(f, ctx); flint_printf("\n"); flint_printf("fA = "); ca_mat_print(fA, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(fA, ctx); ca_poly_clear(f, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-charpoly_danilevsky.c000066400000000000000000000030661461254215100223110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_charpoly_danilevsky, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, fA; ca_poly_t f; slong n; ca_ctx_init(ctx); n = n_randint(state, 10); ca_mat_init(A, n, n, ctx); ca_mat_init(fA, n, n, ctx); ca_poly_init(f, ctx); ca_mat_randtest_rational(A, state, 5, ctx); if (ca_mat_charpoly_danilevsky(f, A, ctx)) { ca_mat_ca_poly_evaluate(fA, f, A, ctx); if (f->length != (n + 1) || ca_mat_check_is_zero(fA, ctx) != T_TRUE) { flint_printf("FAIL\n"); flint_printf("A = "), ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "), ca_poly_print(f, ctx); flint_printf("\n"); flint_printf("fA = "); ca_mat_print(fA, ctx); flint_printf("\n"); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(fA, ctx); ca_poly_clear(f, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-companion.c000066400000000000000000000032451461254215100202210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_companion, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A; ca_poly_t f, g; slong n; ca_ctx_init(ctx); ca_poly_init(f, ctx); ca_poly_init(g, ctx); do { ca_poly_randtest(f, state, 1 + n_randint(state, 4), 2, 5, ctx); } while (f->length < 1); n = f->length - 1; ca_mat_init(A, n, n, ctx); ca_mat_randtest_rational(A, state, 100, ctx); if (ca_mat_companion(A, f, ctx)) { ca_mat_charpoly(g, A, ctx); ca_poly_mul_ca(g, g, f->coeffs + n, ctx); if (ca_poly_check_equal(g, f, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A = "), ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "), ca_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); ca_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } } ca_mat_clear(A, ctx); ca_poly_clear(f, ctx); ca_poly_clear(g, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-det.c000066400000000000000000000110561461254215100170110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_det, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A; ca_t detA, detB; slong n; ca_ctx_init(ctx); n = n_randint(state, 6); ca_mat_init(A, n, n, ctx); ca_init(detA, ctx); ca_init(detB, ctx); ca_mat_randtest(A, state, 3, 5, ctx); switch (n_randint(state, 5)) { case 0: ca_mat_det_berkowitz(detA, A, ctx); break; case 1: ca_mat_det_lu(detA, A, ctx); break; case 2: ca_mat_det_bareiss(detA, A, ctx); break; default: ca_mat_det(detA, A, ctx); break; } switch (n_randint(state, 5)) { case 0: ca_mat_det_berkowitz(detB, A, ctx); break; case 1: ca_mat_det_lu(detB, A, ctx); break; case 2: ca_mat_det_bareiss(detB, A, ctx); break; default: ca_mat_det(detB, A, ctx); break; } if (ca_check_equal(detA, detB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("detA = "); ca_print(detA, ctx); flint_printf("\n"); flint_printf("detB = "); ca_print(detB, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_clear(detA, ctx); ca_clear(detB, ctx); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, AB; ca_t detA, detB, detAB, detAdetB; slong n; ca_ctx_init(ctx); n = n_randint(state, 5); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_mat_init(AB, n, n, ctx); ca_init(detA, ctx); ca_init(detB, ctx); ca_init(detAB, ctx); ca_init(detAdetB, ctx); if (n_randint(state, 2)) ca_mat_randtest_rational(A, state, 100, ctx); else ca_mat_randtest(A, state, 3, 5, ctx); if (n_randint(state, 2)) ca_mat_randtest_rational(B, state, 10, ctx); else ca_mat_randtest(B, state, 3, 5, ctx); ca_mat_mul(AB, A, B, ctx); switch (n_randint(state, 5)) { case 0: ca_mat_det_berkowitz(detA, A, ctx); break; case 1: ca_mat_det_lu(detA, A, ctx); break; case 2: ca_mat_det_bareiss(detA, A, ctx); break; default: ca_mat_det(detA, A, ctx); break; } switch (n_randint(state, 5)) { case 0: ca_mat_det_berkowitz(detB, B, ctx); break; case 1: ca_mat_det_lu(detB, B, ctx); break; case 2: ca_mat_det_bareiss(detB, B, ctx); break; default: ca_mat_det(detB, B, ctx); break; } switch (n_randint(state, 5)) { case 0: ca_mat_det_berkowitz(detAB, AB, ctx); break; case 1: ca_mat_det_lu(detAB, AB, ctx); break; case 2: ca_mat_det_bareiss(detAB, AB, ctx); break; default: ca_mat_det(detAB, AB, ctx); break; } ca_mul(detAdetB, detA, detB, ctx); if (ca_check_equal(detAB, detAdetB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); ca_mat_print(AB, ctx); flint_printf("\n"); flint_printf("detA = "); ca_print(detA, ctx); flint_printf("\n"); flint_printf("detB = "); ca_print(detB, ctx); flint_printf("\n"); flint_printf("detAB = "); ca_print(detAB, ctx); flint_printf("\n"); flint_printf("detAdetB = "); ca_print(detAdetB, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(AB, ctx); ca_clear(detA, ctx); ca_clear(detB, ctx); ca_clear(detAB, ctx); ca_clear(detAdetB, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-dft.c000066400000000000000000000036711461254215100170160ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_dft, state) { slong iter; for (iter = 0; iter < 1; iter++) { ca_ctx_t ctx; ca_mat_t A, B, C; slong n; ca_ctx_init(ctx); for (n = 0; n <= 16; n++) { ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_mat_init(C, n, n, ctx); ca_mat_dft(A, 0, ctx); ca_mat_dft(B, 1, ctx); ca_mat_mul(C, A, B, ctx); if (ca_mat_check_is_one(C, ctx) != T_TRUE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_mat_print(C, ctx); flint_printf("\n"); flint_abort(); } ca_mat_dft(A, 2, ctx); ca_mat_dft(B, 3, ctx); ca_mat_mul(C, A, B, ctx); if (ca_mat_check_is_one(C, ctx) != T_TRUE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_mat_print(C, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(C, ctx); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-diagonalization.c000066400000000000000000000050521461254215100214100ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_diagonalization, state) { slong iter; /* todo: test non-diagonalizable matrices */ /* todo: test aliasing */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, P, D, Pinv, B; slong n; truth_t result; ca_ctx_init(ctx); n = n_randint(state, 4); ca_mat_init(A, n, n, ctx); ca_mat_init(P, n, n, ctx); ca_mat_init(D, n, n, ctx); ca_mat_init(Pinv, n, n, ctx); ca_mat_init(B, n, n, ctx); if (n <= 2) ca_mat_randtest(A, state, 1, 5, ctx); else ca_mat_randtest_rational(A, state, 5, ctx); ca_mat_randtest(D, state, 1, 5, ctx); ca_mat_randtest(P, state, 1, 5, ctx); result = ca_mat_diagonalization(D, P, A, ctx); if (result == T_TRUE) { result = ca_mat_inv(Pinv, P, ctx); if (result == T_FALSE) { flint_printf("FAIL (inversion of P)\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("D: "); ca_mat_print(D, ctx); flint_printf("\n"); flint_printf("P: "); ca_mat_print(P, ctx); flint_printf("\n"); flint_abort(); } if (result == T_TRUE) { ca_mat_mul(B, P, D, ctx); ca_mat_mul(B, B, Pinv, ctx); result = ca_mat_check_equal(A, B, ctx); if (result == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("D: "); ca_mat_print(D, ctx); flint_printf("\n"); flint_printf("P: "); ca_mat_print(P, ctx); flint_printf("\n"); flint_abort(); } } } ca_mat_clear(A, ctx); ca_mat_clear(D, ctx); ca_mat_clear(P, ctx); ca_mat_clear(Pinv, ctx); ca_mat_clear(B, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-exp.c000066400000000000000000000076301461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_exp, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, P, Q, C, D; ca_t d, t; slong n; int success; ca_ctx_init(ctx); n = n_randint(state, 3); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_mat_init(P, n, n, ctx); ca_mat_init(Q, n, n, ctx); ca_mat_init(C, n, n, ctx); ca_mat_init(D, n, n, ctx); ca_init(d, ctx); ca_init(t, ctx); if (n <= 2 && n_randint(state, 5) == 0) ca_mat_randtest(A, state, 1, 5, ctx); else ca_mat_randtest_rational(A, state, 5, ctx); if (n_randint(state, 2)) { success = ca_mat_exp(B, A, ctx); } else { ca_mat_set(B, A, ctx); success = ca_mat_exp(B, B, ctx); } if (success) { ca_mat_det(d, B, ctx); ca_mat_trace(t, A, ctx); ca_exp(t, t, ctx); if (ca_check_equal(d, t, ctx) == T_FALSE) { flint_printf("FAIL (trace)\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("d: "); ca_print(d, ctx); flint_printf("\n"); flint_printf("t: "); ca_print(t, ctx); flint_printf("\n"); flint_abort(); } do { ca_mat_randtest_rational(P, state, 1, ctx); } while (ca_mat_inv(Q, P, ctx) != T_TRUE); ca_mat_mul(C, P, A, ctx); ca_mat_mul(C, C, Q, ctx); success = ca_mat_exp(C, C, ctx); if (success) { ca_mat_mul(D, P, B, ctx); ca_mat_mul(D, D, Q, ctx); if (ca_mat_check_equal(C, D, ctx) == T_FALSE) { flint_printf("FAIL (similarity transform)\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C: "); ca_mat_print(C, ctx); flint_printf("\n"); flint_printf("D: "); ca_mat_print(D, ctx); flint_printf("\n"); flint_printf("P: "); ca_mat_print(P, ctx); flint_printf("\n"); flint_printf("Q: "); ca_mat_print(Q, ctx); flint_printf("\n"); flint_abort(); } } } if (ca_mat_log(B, A, ctx) == T_TRUE) { success = ca_mat_exp(C, B, ctx); if (success) { if (ca_mat_check_equal(A, C, ctx) == T_FALSE) { flint_printf("FAIL (logarithm)\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C: "); ca_mat_print(C, ctx); flint_printf("\n"); flint_abort(); } } } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(P, ctx); ca_mat_clear(Q, ctx); ca_mat_clear(C, ctx); ca_mat_clear(D, ctx); ca_clear(d, ctx); ca_clear(t, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-inv.c000066400000000000000000000042051461254215100170270ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_inv, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, C; slong n; truth_t success; ca_ctx_init(ctx); n = n_randint(state, 6); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_mat_init(C, n, n, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(A, state, 5, ctx); else ca_mat_randtest(A, state, 1, 5, ctx); success = ca_mat_inv(B, A, ctx); if (success == T_TRUE) { ca_mat_mul(C, A, B, ctx); if (ca_mat_check_is_one(C, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_mat_print(C, ctx); flint_printf("\n"); flint_abort(); } } else if (success == T_FALSE) { ca_t det; ca_init(det, ctx); ca_mat_det(det, A, ctx); if (ca_check_is_zero(det, ctx) == T_FALSE) { flint_printf("FAIL (singular)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); ca_print(det, ctx); flint_printf("\n"); flint_abort(); } ca_clear(det, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(C, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-jordan_blocks.c000066400000000000000000000171321461254215100210500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" int check_jordan_forms(ca_vec_t lambda1, slong num_blocks1, slong * block_lambda1, slong * block_size1, ca_vec_t lambda2, slong num_blocks2, slong * block_lambda2, slong * block_size2, ca_ctx_t ctx) { slong i, j; slong * used; slong found; int result; if (num_blocks1 != num_blocks2) return 0; if (ca_vec_length(lambda1, ctx) != ca_vec_length(lambda2, ctx)) return 0; /* note: not ordered for (i = 0; i < ca_vec_length(lambda1, ctx); i++) if (ca_check_equal(ca_vec_entry(lambda1, i), ca_vec_entry(lambda2, i), ctx) == T_FALSE) return 0; */ used = flint_calloc(sizeof(slong), num_blocks1); result = 1; for (i = 0; result && i < num_blocks1; i++) { found = -1; for (j = 0; found == -1 && j < num_blocks2; j++) { if (!used[j]) { if (/* block_lambda1[i] == block_lambda2[j] -- if ordered */ ca_check_equal(ca_vec_entry(lambda1, block_lambda1[i]), ca_vec_entry(lambda2, block_lambda2[j]), ctx) != T_FALSE && block_size1[i] == block_size2[j]) { found = j; used[j] = 1; } } } if (found == -1) result = 0; } flint_free(used); return result; } TEST_FUNCTION_START(ca_mat_jordan_blocks, state) { slong iter; /* Test J(A) = J(P * A * P^-1) for random rational Jordan block matrix A and random P */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, P, Q, B; slong n, i, j, num_lambda; int success1, success2; slong num_blocks1, num_blocks2, offset; ca_vec_t lambda1, lambda2; slong *block_lambda1, *block_size1, *block_lambda2, *block_size2; ca_ctx_init(ctx); num_lambda = 1 + n_randint(state, 3); ca_vec_init(lambda1, num_lambda, ctx); offset = n_randint(state, 2); for (i = 0; i < num_lambda; i++) ca_set_ui(ca_vec_entry(lambda1, i), offset + i, ctx); block_lambda1 = flint_malloc(sizeof(slong) * 4 * num_lambda); block_size1 = flint_malloc(sizeof(slong) * 4 * num_lambda); num_blocks1 = 0; n = 0; for (i = 0; i < num_lambda; i++) { slong blocks = 1 + n_randint(state, 3); for (j = 0; j < blocks; j++) { block_size1[num_blocks1] = 1 + n_randint(state, 3); block_lambda1[num_blocks1] = i; n += block_size1[num_blocks1]; num_blocks1++; } } ca_mat_init(A, n, n, ctx); ca_mat_init(P, n, n, ctx); ca_mat_init(Q, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_vec_init(lambda2, 0, ctx); block_lambda2 = flint_malloc(sizeof(slong) * n); block_size2 = flint_malloc(sizeof(slong) * n); ca_mat_set_jordan_blocks(A, lambda1, num_blocks1, block_lambda1, block_size1, ctx); do { ca_mat_randtest_rational(P, state, 1, ctx); } while (ca_mat_inv(Q, P, ctx) != T_TRUE); ca_mat_mul(B, P, A, ctx); ca_mat_mul(B, B, Q, ctx); success1 = 1; success2 = ca_mat_jordan_blocks(lambda2, &num_blocks2, block_lambda2, block_size2, B, ctx); if (success1 && success2) { if (!check_jordan_forms(lambda1, num_blocks1, block_lambda1, block_size1, lambda2, num_blocks2, block_lambda2, block_size2, ctx)) { flint_printf("FAIL (different Jordan forms)\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("lambda1: "); ca_vec_print(lambda1, ctx); printf("\n"); flint_printf("lambda2: "); ca_vec_print(lambda2, ctx); printf("\n"); flint_abort(); } } else { flint_printf("FAIL (unexpected failure to compute Jordan blocks in rational case)\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("lambda1: "); ca_vec_print(lambda1, ctx); printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(P, ctx); ca_mat_clear(Q, ctx); ca_mat_clear(B, ctx); ca_vec_clear(lambda1, ctx); ca_vec_clear(lambda2, ctx); flint_free(block_lambda1); flint_free(block_lambda2); flint_free(block_size1); flint_free(block_size2); ca_ctx_clear(ctx); } /* Test J(A) = J(P * A * P^-1) for random A, P */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, P, Q, B; slong n; int success1, success2; slong num_blocks1, num_blocks2; ca_vec_t lambda1, lambda2; slong *block_lambda1, *block_size1, *block_lambda2, *block_size2; n = n_randint(state, 6); ca_ctx_init(ctx); ca_mat_init(A, n, n, ctx); ca_mat_init(P, n, n, ctx); ca_mat_init(Q, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_vec_init(lambda1, 0, ctx); ca_vec_init(lambda2, 0, ctx); block_lambda1 = flint_malloc(sizeof(slong) * n); block_lambda2 = flint_malloc(sizeof(slong) * n); block_size1 = flint_malloc(sizeof(slong) * n); block_size2 = flint_malloc(sizeof(slong) * n); if (n <= 3 && n_randint(state, 2) == 0) ca_mat_randtest(A, state, 1, 5, ctx); else ca_mat_randtest_rational(A, state, 5, ctx); do { ca_mat_randtest_rational(P, state, 1, ctx); } while (ca_mat_inv(Q, P, ctx) != T_TRUE); ca_mat_mul(B, P, A, ctx); ca_mat_mul(B, B, Q, ctx); success1 = ca_mat_jordan_blocks(lambda1, &num_blocks1, block_lambda1, block_size1, A, ctx); success2 = success1 && ca_mat_jordan_blocks(lambda2, &num_blocks2, block_lambda2, block_size2, B, ctx); if (success1 && success2) { if (!check_jordan_forms(lambda1, num_blocks1, block_lambda1, block_size1, lambda2, num_blocks2, block_lambda2, block_size2, ctx)) { flint_printf("FAIL (different jordan forms)\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("lambda1: "); ca_vec_print(lambda1, ctx); printf("\n"); flint_printf("lambda2: "); ca_vec_print(lambda2, ctx); printf("\n"); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(P, ctx); ca_mat_clear(Q, ctx); ca_mat_clear(B, ctx); ca_vec_clear(lambda1, ctx); ca_vec_clear(lambda2, ctx); flint_free(block_lambda1); flint_free(block_lambda2); flint_free(block_size1); flint_free(block_size2); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-jordan_form.c000066400000000000000000000135061461254215100205370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_jordan_form, state) { slong iter; /* Test P J P^{-1} = A for random matrices A generated from Jordan blocks */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, P, Q, B, J; slong n, i, j, num_lambda; int success; slong num_blocks1, offset; ca_vec_t lambda1; slong *block_lambda1, *block_size1; truth_t inv; ca_ctx_init(ctx); num_lambda = 1 + n_randint(state, 3); ca_vec_init(lambda1, num_lambda, ctx); offset = n_randint(state, 2); for (i = 0; i < num_lambda; i++) ca_set_ui(ca_vec_entry(lambda1, i), offset + i, ctx); block_lambda1 = flint_malloc(sizeof(slong) * 4 * num_lambda); block_size1 = flint_malloc(sizeof(slong) * 4 * num_lambda); num_blocks1 = 0; n = 0; for (i = 0; i < num_lambda; i++) { slong blocks = 1 + n_randint(state, 3); for (j = 0; j < blocks; j++) { block_size1[num_blocks1] = 1 + n_randint(state, 3); block_lambda1[num_blocks1] = i; n += block_size1[num_blocks1]; num_blocks1++; } } ca_mat_init(A, n, n, ctx); ca_mat_init(P, n, n, ctx); ca_mat_init(Q, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_mat_init(J, n, n, ctx); ca_mat_set_jordan_blocks(A, lambda1, num_blocks1, block_lambda1, block_size1, ctx); do { ca_mat_randtest_rational(P, state, 1, ctx); } while (ca_mat_inv(Q, P, ctx) != T_TRUE); ca_mat_mul(B, P, A, ctx); ca_mat_mul(B, B, Q, ctx); ca_mat_zero(P, ctx); ca_mat_zero(Q, ctx); success = ca_mat_jordan_form(J, P, A, ctx); if (success) { inv = ca_mat_inv(Q, P, ctx); if (inv == T_FALSE) { flint_printf("FAIL (matrix not invertible)\n"); flint_printf("A: "); ca_mat_printn(A, 5, ctx); flint_printf("\n"); flint_printf("J: "); ca_mat_printn(J, 5, ctx); flint_printf("\n"); flint_printf("P: "); ca_mat_printn(P, 5, ctx); flint_printf("\n"); flint_abort(); } ca_mat_mul(B, P, J, ctx); ca_mat_mul(B, B, Q, ctx); if (ca_mat_check_equal(B, A, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A: "); ca_mat_printn(A, 5, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_printn(B, 5, ctx); flint_printf("\n"); flint_printf("J: "); ca_mat_printn(J, 5, ctx); flint_printf("\n"); flint_printf("P: "); ca_mat_printn(P, 5, ctx); flint_printf("\n"); flint_printf("Q: "); ca_mat_printn(Q, 5, ctx); flint_printf("\n"); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(P, ctx); ca_mat_clear(Q, ctx); ca_mat_clear(B, ctx); ca_mat_clear(J, ctx); ca_vec_clear(lambda1, ctx); flint_free(block_lambda1); flint_free(block_size1); ca_ctx_clear(ctx); } /* Test P J P^{-1} = A for random matrices A */ for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, J, P, Q; slong n; int success; truth_t inv; n = n_randint(state, 5); ca_ctx_init(ctx); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, n, ctx); ca_mat_init(J, n, n, ctx); ca_mat_init(P, n, n, ctx); ca_mat_init(Q, n, n, ctx); if (n <= 2 && n_randint(state, 2) == 0) ca_mat_randtest(A, state, 1, 5, ctx); else ca_mat_randtest_rational(A, state, 5, ctx); /* test aliasing */ if (n_randint(state, 2)) success = ca_mat_jordan_form(J, P, A, ctx); else { ca_mat_set(P, A, ctx); success = ca_mat_jordan_form(J, P, P, ctx); } if (success) { inv = ca_mat_inv(Q, P, ctx); if (inv == T_FALSE) { flint_printf("FAIL (matrix not invertible)\n"); flint_printf("A: "); ca_mat_printn(A, 5, ctx); flint_printf("\n"); flint_printf("J: "); ca_mat_printn(J, 5, ctx); flint_printf("\n"); flint_printf("P: "); ca_mat_printn(P, 5, ctx); flint_printf("\n"); flint_abort(); } ca_mat_mul(B, P, J, ctx); ca_mat_mul(B, B, Q, ctx); if (ca_mat_check_equal(B, A, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A: "); ca_mat_printn(A, 5, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_printn(B, 5, ctx); flint_printf("\n"); flint_printf("J: "); ca_mat_printn(J, 5, ctx); flint_printf("\n"); flint_printf("P: "); ca_mat_printn(P, 5, ctx); flint_printf("\n"); flint_printf("Q: "); ca_mat_printn(Q, 5, ctx); flint_printf("\n"); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(J, ctx); ca_mat_clear(P, ctx); ca_mat_clear(Q, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-lu.c000066400000000000000000000100531461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "ca_mat.h" /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(ca_mat_t A, slong * P) { slong i; ca_struct ** tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(ca_struct *) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, ca_mat_t LU, const ca_mat_t A, slong rank, ca_ctx_t ctx) { ca_mat_t B, L, U; slong m, n, i, j; m = A->r; n = A->c; ca_mat_init(B, m, n, ctx); ca_mat_init(L, m, m, ctx); ca_mat_init(U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (ca_check_is_zero(ca_mat_entry(LU, i, j), ctx) != T_TRUE) { flint_printf("FAIL: wrong shape!\n"); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) ca_set(ca_mat_entry(L, i, j), ca_mat_entry(LU, i, j), ctx); if (i < rank) ca_one(ca_mat_entry(L, i, i), ctx); for (j = i; j < n; j++) ca_set(ca_mat_entry(U, i, j), ca_mat_entry(LU, i, j), ctx); } ca_mat_mul(B, L, U, ctx); perm(B, P); if (ca_mat_check_equal(A, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A:\n"); ca_mat_print(A, ctx); flint_printf("LU:\n"); ca_mat_print(LU, ctx); flint_printf("B:\n"); ca_mat_print(B, ctx); flint_abort(); } ca_mat_clear(B, ctx); ca_mat_clear(L, ctx); ca_mat_clear(U, ctx); } #endif /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef ca_mat_randrank #define ca_mat_randrank ca_mat_randrank void ca_mat_randrank(ca_mat_t mat, flint_rand_t state, slong rank, slong bits, ca_ctx_t ctx) { fmpz_mat_t A; fmpz_mat_init(A, mat->r, mat->c); fmpz_mat_randrank(A, state, rank, bits); ca_mat_set_fmpz_mat(mat, A, ctx); fmpz_mat_clear(A); } #endif TEST_FUNCTION_START(ca_mat_lu, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, LU; slong m, n, r, d, rank; slong * P; int success; ca_ctx_init(ctx); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { ca_mat_init(A, m, n, ctx); ca_mat_init(LU, m, n, ctx); ca_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); ca_mat_randops(A, state, d, ctx); } P = flint_malloc(sizeof(slong) * m); success = ca_mat_lu(&rank, P, LU, A, 0, ctx); if (success) { if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); ca_mat_print(A, ctx); flint_printf("LU:"); ca_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(LU, ctx); flint_free(P); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-lu_classical.c000066400000000000000000000100771461254215100206750ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "ca_mat.h" /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(ca_mat_t A, slong * P) { slong i; ca_struct ** tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(ca_struct *) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, ca_mat_t LU, const ca_mat_t A, slong rank, ca_ctx_t ctx) { ca_mat_t B, L, U; slong m, n, i, j; m = A->r; n = A->c; ca_mat_init(B, m, n, ctx); ca_mat_init(L, m, m, ctx); ca_mat_init(U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (ca_check_is_zero(ca_mat_entry(LU, i, j), ctx) != T_TRUE) { flint_printf("FAIL: wrong shape!\n"); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) ca_set(ca_mat_entry(L, i, j), ca_mat_entry(LU, i, j), ctx); if (i < rank) ca_one(ca_mat_entry(L, i, i), ctx); for (j = i; j < n; j++) ca_set(ca_mat_entry(U, i, j), ca_mat_entry(LU, i, j), ctx); } ca_mat_mul(B, L, U, ctx); perm(B, P); if (ca_mat_check_equal(A, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A:\n"); ca_mat_print(A, ctx); flint_printf("LU:\n"); ca_mat_print(LU, ctx); flint_printf("B:\n"); ca_mat_print(B, ctx); flint_abort(); } ca_mat_clear(B, ctx); ca_mat_clear(L, ctx); ca_mat_clear(U, ctx); } #endif /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef ca_mat_randrank #define ca_mat_randrank ca_mat_randrank void ca_mat_randrank(ca_mat_t mat, flint_rand_t state, slong rank, slong bits, ca_ctx_t ctx) { fmpz_mat_t A; fmpz_mat_init(A, mat->r, mat->c); fmpz_mat_randrank(A, state, rank, bits); ca_mat_set_fmpz_mat(mat, A, ctx); fmpz_mat_clear(A); } #endif TEST_FUNCTION_START(ca_mat_lu_classical, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, LU; slong m, n, r, d, rank; slong * P; int success; ca_ctx_init(ctx); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { ca_mat_init(A, m, n, ctx); ca_mat_init(LU, m, n, ctx); ca_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); ca_mat_randops(A, state, d, ctx); } P = flint_malloc(sizeof(slong) * m); success = ca_mat_lu_classical(&rank, P, LU, A, 0, ctx); if (success) { if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); ca_mat_print(A, ctx); flint_printf("LU:"); ca_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(LU, ctx); flint_free(P); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-lu_recursive.c000066400000000000000000000100771461254215100207460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "ca_mat.h" /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(ca_mat_t A, slong * P) { slong i; ca_struct ** tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(ca_struct *) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, ca_mat_t LU, const ca_mat_t A, slong rank, ca_ctx_t ctx) { ca_mat_t B, L, U; slong m, n, i, j; m = A->r; n = A->c; ca_mat_init(B, m, n, ctx); ca_mat_init(L, m, m, ctx); ca_mat_init(U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (ca_check_is_zero(ca_mat_entry(LU, i, j), ctx) != T_TRUE) { flint_printf("FAIL: wrong shape!\n"); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) ca_set(ca_mat_entry(L, i, j), ca_mat_entry(LU, i, j), ctx); if (i < rank) ca_one(ca_mat_entry(L, i, i), ctx); for (j = i; j < n; j++) ca_set(ca_mat_entry(U, i, j), ca_mat_entry(LU, i, j), ctx); } ca_mat_mul(B, L, U, ctx); perm(B, P); if (ca_mat_check_equal(A, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A:\n"); ca_mat_print(A, ctx); flint_printf("LU:\n"); ca_mat_print(LU, ctx); flint_printf("B:\n"); ca_mat_print(B, ctx); flint_abort(); } ca_mat_clear(B, ctx); ca_mat_clear(L, ctx); ca_mat_clear(U, ctx); } #endif /* Defined in t-lu.c, t-lu_classical.c and t-lu_recursive.c */ #ifndef ca_mat_randrank #define ca_mat_randrank ca_mat_randrank void ca_mat_randrank(ca_mat_t mat, flint_rand_t state, slong rank, slong bits, ca_ctx_t ctx) { fmpz_mat_t A; fmpz_mat_init(A, mat->r, mat->c); fmpz_mat_randrank(A, state, rank, bits); ca_mat_set_fmpz_mat(mat, A, ctx); fmpz_mat_clear(A); } #endif TEST_FUNCTION_START(ca_mat_lu_recursive, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, LU; slong m, n, r, d, rank; slong * P; int success; ca_ctx_init(ctx); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { ca_mat_init(A, m, n, ctx); ca_mat_init(LU, m, n, ctx); ca_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); ca_mat_randops(A, state, d, ctx); } P = flint_malloc(sizeof(slong) * m); success = ca_mat_lu_recursive(&rank, P, LU, A, 0, ctx); if (success) { if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); ca_mat_print(A, ctx); flint_printf("LU:"); ca_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(LU, ctx); flint_free(P); } ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-mul.c000066400000000000000000000103041461254215100170250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_mul, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, C, AB, BC, X, Y; slong M, N, K, L; /* Test (A*B)*C = A*(B*C) */ M = n_randint(state, 4); N = n_randint(state, 4); K = n_randint(state, 4); L = n_randint(state, 4); ca_ctx_init(ctx); ca_mat_init(A, M, N, ctx); ca_mat_init(B, N, K, ctx); ca_mat_init(C, K, L, ctx); ca_mat_init(AB, M, K, ctx); ca_mat_init(BC, N, L, ctx); ca_mat_init(X, M, L, ctx); ca_mat_init(Y, M, L, ctx); ca_mat_randtest(A, state, 2, 10, ctx); ca_mat_randtest(B, state, 2, 10, ctx); ca_mat_randtest(C, state, 2, 10, ctx); ca_mat_randtest(AB, state, 2, 10, ctx); ca_mat_randtest(BC, state, 2, 10, ctx); ca_mat_randtest(X, state, 2, 10, ctx); ca_mat_randtest(Y, state, 2, 10, ctx); ca_mat_mul(AB, A, B, ctx); ca_mat_mul(X, AB, C, ctx); ca_mat_mul(BC, B, C, ctx); ca_mat_mul(Y, A, BC, ctx); if (ca_mat_check_equal(X, Y, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_mat_print(C, ctx); flint_printf("\n"); flint_printf("X = "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("Y = "); ca_mat_print(Y, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(C, ctx); ca_mat_clear(AB, ctx); ca_mat_clear(BC, ctx); ca_mat_clear(X, ctx); ca_mat_clear(Y, ctx); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, C, AB, BC, X, Y; slong M, N, K, L; /* Test (A*B)*C = A*(B*C), rational matrices */ M = n_randint(state, 5); N = n_randint(state, 5); K = n_randint(state, 5); L = n_randint(state, 5); ca_ctx_init(ctx); ca_mat_init(A, M, N, ctx); ca_mat_init(B, N, K, ctx); ca_mat_init(C, K, L, ctx); ca_mat_init(AB, M, K, ctx); ca_mat_init(BC, N, L, ctx); ca_mat_init(X, M, L, ctx); ca_mat_init(Y, M, L, ctx); ca_mat_randtest_rational(A, state, 200, ctx); ca_mat_randtest_rational(B, state, 200, ctx); ca_mat_randtest_rational(C, state, 200, ctx); ca_mat_randtest_rational(AB, state, 200, ctx); ca_mat_randtest_rational(BC, state, 200, ctx); ca_mat_randtest_rational(X, state, 200, ctx); ca_mat_randtest_rational(Y, state, 200, ctx); ca_mat_mul(AB, A, B, ctx); ca_mat_mul(X, AB, C, ctx); ca_mat_mul(BC, B, C, ctx); ca_mat_mul(Y, A, BC, ctx); if (ca_mat_check_equal(X, Y, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_mat_print(C, ctx); flint_printf("\n"); flint_printf("X = "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("Y = "); ca_mat_print(Y, ctx); flint_printf("\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(C, ctx); ca_mat_clear(AB, ctx); ca_mat_clear(BC, ctx); ca_mat_clear(X, ctx); ca_mat_clear(Y, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-mul_same_nf.c000066400000000000000000000057261461254215100205310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" void ca_mat_randtest_same_nf(ca_mat_t res, flint_rand_t state, const ca_t x, slong bits, slong den_bits, ca_ctx_t ctx) { slong i, j; fmpz_t t; for (i = 0; i < ca_mat_nrows(res); i++) for (j = 0; j < ca_mat_ncols(res); j++) ca_randtest_same_nf(ca_mat_entry(res, i, j), state, x, bits, 1, ctx); fmpz_init(t); fmpz_randtest_not_zero(t, state, den_bits); ca_mat_div_fmpz(res, res, t, ctx); fmpz_clear(t); } TEST_FUNCTION_START(ca_mat_mul_same_nf, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, C, D; qqbar_t t; ca_t x; slong m, n, k; ca_field_ptr K; /* Test (A*B)*C = A*(B*C) */ m = n_randint(state, 5); n = n_randint(state, 5); k = n_randint(state, 5); ca_ctx_init(ctx); qqbar_init(t); ca_init(x, ctx); do { qqbar_randtest(t, state, 8, 10); } while (qqbar_is_rational(t)); ca_set_qqbar(x, t, ctx); ca_mat_init(A, m, n, ctx); ca_mat_init(B, n, k, ctx); ca_mat_init(C, m, k, ctx); ca_mat_init(D, m, k, ctx); ca_mat_randtest_same_nf(A, state, x, 10, 10, ctx); ca_mat_randtest_same_nf(B, state, x, 10, 10, ctx); ca_mat_randtest(C, state, 1, 5, ctx); ca_mat_randtest(D, state, 1, 5, ctx); K = _ca_mat_same_field(A, ctx); if (K != NULL && CA_FIELD_IS_NF(K)) { if (n_randint(state, 2) && (m == n && n == k)) { /* test aliasing */ ca_mat_set(C, A, ctx); ca_mat_mul_same_nf(C, C, B, K, ctx); } else { ca_mat_mul_same_nf(C, A, B, K, ctx); } ca_mat_mul_classical(D, A, B, ctx); if (ca_mat_check_equal(C, D, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_mat_print(C, ctx); flint_printf("\n"); flint_printf("D = "); ca_mat_print(D, ctx); flint_printf("\n"); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(C, ctx); ca_mat_clear(D, ctx); ca_clear(x, ctx); qqbar_clear(t); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-nonsingular_solve.c000066400000000000000000000050761461254215100220110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_nonsingular_solve, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, X, B, AX; slong n, c; truth_t success; ca_ctx_init(ctx); n = n_randint(state, 6); c = n_randint(state, 6); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, c, ctx); ca_mat_init(X, n, c, ctx); ca_mat_init(AX, n, c, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(A, state, 5, ctx); else ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_randtest(X, state, 1, 5, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(B, state, 5, ctx); else ca_mat_randtest(B, state, 1, 5, ctx); success = ca_mat_nonsingular_solve(X, A, B, ctx); if (success == T_TRUE) { ca_mat_mul(AX, A, X, ctx); if (ca_mat_check_equal(AX, B, ctx) == T_FALSE) { flint_printf("FAIL (solve)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("X = "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("AX = "); ca_mat_print(AX, ctx); flint_printf("\n"); flint_abort(); } } else if (success == T_FALSE) { ca_t det; ca_init(det, ctx); ca_mat_det(det, A, ctx); if (ca_check_is_zero(det, ctx) == T_FALSE) { flint_printf("FAIL (singular)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); ca_print(det, ctx); flint_printf("\n"); flint_abort(); } ca_clear(det, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(X, ctx); ca_mat_clear(AX, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-nonsingular_solve_adjugate.c000066400000000000000000000051201461254215100236430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_nonsingular_solve_adjugate, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, X, B, AX; slong n, c; truth_t success; ca_ctx_init(ctx); n = n_randint(state, 6); c = n_randint(state, 6); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, c, ctx); ca_mat_init(X, n, c, ctx); ca_mat_init(AX, n, c, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(A, state, 5, ctx); else ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_randtest(X, state, 1, 5, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(B, state, 5, ctx); else ca_mat_randtest(B, state, 1, 5, ctx); success = ca_mat_nonsingular_solve_adjugate(X, A, B, ctx); if (success == T_TRUE) { ca_mat_mul(AX, A, X, ctx); if (ca_mat_check_equal(AX, B, ctx) == T_FALSE) { flint_printf("FAIL (solve)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("X = "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("AX = "); ca_mat_print(AX, ctx); flint_printf("\n"); flint_abort(); } } else if (success == T_FALSE) { ca_t det; ca_init(det, ctx); ca_mat_det(det, A, ctx); if (ca_check_is_zero(det, ctx) == T_FALSE) { flint_printf("FAIL (singular)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); ca_print(det, ctx); flint_printf("\n"); flint_abort(); } ca_clear(det, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(X, ctx); ca_mat_clear(AX, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-nonsingular_solve_fflu.c000066400000000000000000000051101461254215100230120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_nonsingular_solve_fflu, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, X, B, AX; slong n, c; truth_t success; ca_ctx_init(ctx); n = n_randint(state, 6); c = n_randint(state, 6); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, c, ctx); ca_mat_init(X, n, c, ctx); ca_mat_init(AX, n, c, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(A, state, 5, ctx); else ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_randtest(X, state, 1, 5, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(B, state, 5, ctx); else ca_mat_randtest(B, state, 1, 5, ctx); success = ca_mat_nonsingular_solve_fflu(X, A, B, ctx); if (success == T_TRUE) { ca_mat_mul(AX, A, X, ctx); if (ca_mat_check_equal(AX, B, ctx) == T_FALSE) { flint_printf("FAIL (solve)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("X = "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("AX = "); ca_mat_print(AX, ctx); flint_printf("\n"); flint_abort(); } } else if (success == T_FALSE) { ca_t det; ca_init(det, ctx); ca_mat_det(det, A, ctx); if (ca_check_is_zero(det, ctx) == T_FALSE) { flint_printf("FAIL (singular)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); ca_print(det, ctx); flint_printf("\n"); flint_abort(); } ca_clear(det, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(X, ctx); ca_mat_clear(AX, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-nonsingular_solve_lu.c000066400000000000000000000051041461254215100225010ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_nonsingular_solve_lu, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, X, B, AX; slong n, c; truth_t success; ca_ctx_init(ctx); n = n_randint(state, 6); c = n_randint(state, 6); ca_mat_init(A, n, n, ctx); ca_mat_init(B, n, c, ctx); ca_mat_init(X, n, c, ctx); ca_mat_init(AX, n, c, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(A, state, 5, ctx); else ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_randtest(X, state, 1, 5, ctx); if (n_randint(state, 2) || n > 3) ca_mat_randtest_rational(B, state, 5, ctx); else ca_mat_randtest(B, state, 1, 5, ctx); success = ca_mat_nonsingular_solve_lu(X, A, B, ctx); if (success == T_TRUE) { ca_mat_mul(AX, A, X, ctx); if (ca_mat_check_equal(AX, B, ctx) == T_FALSE) { flint_printf("FAIL (solve)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("X = "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("AX = "); ca_mat_print(AX, ctx); flint_printf("\n"); flint_abort(); } } else if (success == T_FALSE) { ca_t det; ca_init(det, ctx); ca_mat_det(det, A, ctx); if (ca_check_is_zero(det, ctx) == T_FALSE) { flint_printf("FAIL (singular)\n\n"); flint_printf("A = "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); ca_print(det, ctx); flint_printf("\n"); flint_abort(); } ca_clear(det, ctx); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(X, ctx); ca_mat_clear(AX, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-rank.c000066400000000000000000000032271461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_rank, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B; slong rank1, rank2, r, c; int success; ca_ctx_init(ctx); r = n_randint(state, 6); c = n_randint(state, 6); ca_mat_init(A, r, c, ctx); ca_mat_init(B, r, c, ctx); ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_set(B, A, ctx); ca_mat_randops(B, state, 1 + n_randint(state, 20), ctx); success = ca_mat_rank(&rank1, A, ctx); if (success) { success = ca_mat_rank(&rank2, B, ctx); if (success) { if (rank1 != rank2) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-right_kernel.c000066400000000000000000000053401461254215100207110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_right_kernel, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, X, AX; slong r, c, rank, nullity; int success, success2; ca_ctx_init(ctx); r = n_randint(state, 6); c = n_randint(state, 6); ca_mat_init(A, r, c, ctx); ca_mat_init(X, r, c, ctx); ca_mat_randtest(A, state, 1, 5, ctx); success = ca_mat_right_kernel(X, A, ctx); if (success) { success2 = ca_mat_rank(&rank, A, ctx); if (success2) { nullity = c - rank; if (nullity != ca_mat_ncols(X)) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("X: "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank, nullity); flint_abort(); } ca_mat_init(AX, r, nullity, ctx); ca_mat_mul(AX, A, X, ctx); if (ca_mat_check_is_zero(AX, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("X: "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("AX: "); ca_mat_print(AX, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank, nullity); flint_abort(); } success = ca_mat_rank(&nullity, X, ctx); if (!success || (nullity != ca_mat_ncols(X))) { flint_printf("FAIL (2):\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("X: "); ca_mat_print(X, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank, nullity); flint_abort(); } ca_mat_clear(AX, ctx); } } ca_mat_clear(A, ctx); ca_mat_clear(X, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-rref.c000066400000000000000000000105511461254215100171720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "ca_mat.h" /* Defined in t-rref.c, t-rref_fflu.c and t-rref_lu.c */ #ifndef ca_mat_randrowops #define ca_mat_randrowops ca_mat_randrowops void ca_mat_randrowops(ca_mat_t mat, flint_rand_t state, slong count, ca_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; if (mat->r == 0 || mat->c == 0) return; for (c = 0; c < count; c++) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) ca_add(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); else for (k = 0; k < n; k++) ca_sub(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); } } #endif TEST_FUNCTION_START(ca_mat_rref, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, R, R2; fmpq_mat_t AQ, RQ; slong rank, rankq, r, c; int success; ca_ctx_init(ctx); r = n_randint(state, 10); c = n_randint(state, 10); ca_mat_init(A, r, c, ctx); ca_mat_init(R, r, c, ctx); ca_mat_init(R2, r, c, ctx); fmpq_mat_init(AQ, r, c); fmpq_mat_init(RQ, r, c); fmpq_mat_randtest(AQ, state, 10); ca_mat_set_fmpq_mat(A, AQ, ctx); rankq = fmpq_mat_rref(RQ, AQ); if (n_randint(state, 2)) { ca_mat_set(R, A, ctx); success = ca_mat_rref(&rank, R, R, ctx); } else { success = ca_mat_rref(&rank, R, A, ctx); } if (success) { ca_mat_set_fmpq_mat(R2, RQ, ctx); if (rank != rankq || ca_mat_check_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("R: "); ca_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); ca_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank, rankq); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(R, ctx); ca_mat_clear(R2, ctx); fmpq_mat_clear(AQ); fmpq_mat_clear(RQ); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, R, R2; slong rank1, rank2, r, c; int success; ca_ctx_init(ctx); r = n_randint(state, 5); c = n_randint(state, 5); ca_mat_init(A, r, c, ctx); ca_mat_init(B, r, c, ctx); ca_mat_init(R, r, c, ctx); ca_mat_init(R2, r, c, ctx); ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_set(B, A, ctx); ca_mat_randrowops(B, state, 1 + n_randint(state, 20), ctx); success = ca_mat_rref(&rank1, R, A, ctx); if (success) { success = ca_mat_rref(&rank2, R2, B, ctx); if (success) { if (rank1 != rank2 || ca_mat_check_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("R: "); ca_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); ca_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(R, ctx); ca_mat_clear(R2, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-rref_fflu.c000066400000000000000000000106021461254215100202030ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "ca_mat.h" /* Defined in t-rref.c, t-rref_fflu.c and t-rref_lu.c */ #ifndef ca_mat_randrowops #define ca_mat_randrowops ca_mat_randrowops void ca_mat_randrowops(ca_mat_t mat, flint_rand_t state, slong count, ca_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; if (mat->r == 0 || mat->c == 0) return; for (c = 0; c < count; c++) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) ca_add(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); else for (k = 0; k < n; k++) ca_sub(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); } } #endif TEST_FUNCTION_START(ca_mat_rref_fflu, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, R, R2; fmpq_mat_t AQ, RQ; slong rank, rankq, r, c; int success; ca_ctx_init(ctx); r = n_randint(state, 10); c = n_randint(state, 10); ca_mat_init(A, r, c, ctx); ca_mat_init(R, r, c, ctx); ca_mat_init(R2, r, c, ctx); fmpq_mat_init(AQ, r, c); fmpq_mat_init(RQ, r, c); fmpq_mat_randtest(AQ, state, 10); ca_mat_set_fmpq_mat(A, AQ, ctx); rankq = fmpq_mat_rref(RQ, AQ); if (n_randint(state, 2)) { ca_mat_set(R, A, ctx); success = ca_mat_rref_fflu(&rank, R, R, ctx); } else { success = ca_mat_rref_fflu(&rank, R, A, ctx); } if (success) { ca_mat_set_fmpq_mat(R2, RQ, ctx); if (rank != rankq || ca_mat_check_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("R: "); ca_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); ca_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank, rankq); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(R, ctx); ca_mat_clear(R2, ctx); fmpq_mat_clear(AQ); fmpq_mat_clear(RQ); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, R, R2; slong rank1, rank2, r, c; int success; ca_ctx_init(ctx); r = n_randint(state, 5); c = n_randint(state, 5); ca_mat_init(A, r, c, ctx); ca_mat_init(B, r, c, ctx); ca_mat_init(R, r, c, ctx); ca_mat_init(R2, r, c, ctx); ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_set(B, A, ctx); ca_mat_randrowops(B, state, 1 + n_randint(state, 20), ctx); success = ca_mat_rref_fflu(&rank1, R, A, ctx); if (success) { success = ca_mat_rref_fflu(&rank2, R2, B, ctx); if (success) { if (rank1 != rank2 || ca_mat_check_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("R: "); ca_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); ca_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(R, ctx); ca_mat_clear(R2, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-rref_lu.c000066400000000000000000000105701461254215100176730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "ca_mat.h" /* Defined in t-rref.c, t-rref_fflu.c and t-rref_lu.c */ #ifndef ca_mat_randrowops #define ca_mat_randrowops ca_mat_randrowops void ca_mat_randrowops(ca_mat_t mat, flint_rand_t state, slong count, ca_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; if (mat->r == 0 || mat->c == 0) return; for (c = 0; c < count; c++) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) ca_add(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); else for (k = 0; k < n; k++) ca_sub(ca_mat_entry(mat, j, k), ca_mat_entry(mat, j, k), ca_mat_entry(mat, i, k), ctx); } } #endif TEST_FUNCTION_START(ca_mat_rref_lu, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, R, R2; fmpq_mat_t AQ, RQ; slong rank, rankq, r, c; int success; ca_ctx_init(ctx); r = n_randint(state, 10); c = n_randint(state, 10); ca_mat_init(A, r, c, ctx); ca_mat_init(R, r, c, ctx); ca_mat_init(R2, r, c, ctx); fmpq_mat_init(AQ, r, c); fmpq_mat_init(RQ, r, c); fmpq_mat_randtest(AQ, state, 10); ca_mat_set_fmpq_mat(A, AQ, ctx); rankq = fmpq_mat_rref(RQ, AQ); if (n_randint(state, 2)) { ca_mat_set(R, A, ctx); success = ca_mat_rref_lu(&rank, R, R, ctx); } else { success = ca_mat_rref_lu(&rank, R, A, ctx); } if (success) { ca_mat_set_fmpq_mat(R2, RQ, ctx); if (rank != rankq || ca_mat_check_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("R: "); ca_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); ca_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank, rankq); flint_abort(); } } ca_mat_clear(A, ctx); ca_mat_clear(R, ctx); ca_mat_clear(R2, ctx); fmpq_mat_clear(AQ); fmpq_mat_clear(RQ); ca_ctx_clear(ctx); } for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, B, R, R2; slong rank1, rank2, r, c; int success; ca_ctx_init(ctx); r = n_randint(state, 5); c = n_randint(state, 5); ca_mat_init(A, r, c, ctx); ca_mat_init(B, r, c, ctx); ca_mat_init(R, r, c, ctx); ca_mat_init(R2, r, c, ctx); ca_mat_randtest(A, state, 1, 5, ctx); ca_mat_set(B, A, ctx); ca_mat_randrowops(B, state, 1 + n_randint(state, 20), ctx); success = ca_mat_rref_lu(&rank1, R, A, ctx); if (success) { success = ca_mat_rref_lu(&rank2, R2, B, ctx); if (success) { if (rank1 != rank2 || ca_mat_check_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("A: "); ca_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); ca_mat_print(B, ctx); flint_printf("\n"); flint_printf("R: "); ca_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); ca_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(R, ctx); ca_mat_clear(R2, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-solve_tril.c000066400000000000000000000052211461254215100204140ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_solve_tril, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, X, B, Y; slong rows, cols, i, j; int unit; rows = n_randint(state, 15); cols = n_randint(state, 15); unit = n_randint(state, 2); ca_ctx_init(ctx); ca_mat_init(A, rows, rows, ctx); ca_mat_init(B, rows, cols, ctx); ca_mat_init(X, rows, cols, ctx); ca_mat_init(Y, rows, cols, ctx); /* todo: test number fields, etc. */ ca_mat_randtest_rational(A, state, 5, ctx); ca_mat_randtest_rational(X, state, 5, ctx); ca_mat_randtest_rational(Y, state, 5, ctx); for (i = 0; i < rows; i++) { if (unit) ca_one(ca_mat_entry(A, i, i), ctx); else ca_set_ui(ca_mat_entry(A, i, i), 1 + n_randint(state, 100), ctx); for (j = i + 1; j < rows; j++) ca_zero(ca_mat_entry(A, i, j), ctx); } ca_mat_mul(B, A, X, ctx); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) ca_set_ui(ca_mat_entry(A, i, i), 1 + n_randint(state, 100), ctx); } /* Check Y = A^(-1) * (A * X) = X */ /* Check Y = A^(-1) * (A * X) = X */ if (n_randint(state, 2)) { ca_mat_solve_tril(Y, A, B, unit, ctx); } else { ca_mat_set(Y, B, ctx); ca_mat_solve_tril(Y, A, Y, unit, ctx); } if (ca_mat_check_equal(Y, X, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A = \n"); ca_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); ca_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); ca_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("Y = \n"); ca_mat_print(Y, ctx); flint_printf("\n\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(X, ctx); ca_mat_clear(Y, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/test/t-solve_triu.c000066400000000000000000000051351461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_mat.h" TEST_FUNCTION_START(ca_mat_solve_triu, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_mat_t A, X, B, Y; slong rows, cols, i, j; int unit; rows = n_randint(state, 15); cols = n_randint(state, 15); unit = n_randint(state, 2); ca_ctx_init(ctx); ca_mat_init(A, rows, rows, ctx); ca_mat_init(B, rows, cols, ctx); ca_mat_init(X, rows, cols, ctx); ca_mat_init(Y, rows, cols, ctx); /* todo: test number fields, etc. */ ca_mat_randtest_rational(A, state, 5, ctx); ca_mat_randtest_rational(X, state, 5, ctx); ca_mat_randtest_rational(Y, state, 5, ctx); for (i = 0; i < rows; i++) { if (unit) ca_one(ca_mat_entry(A, i, i), ctx); else ca_set_ui(ca_mat_entry(A, i, i), 1 + n_randint(state, 100), ctx); for (j = 0; j < i; j++) ca_zero(ca_mat_entry(A, i, j), ctx); } ca_mat_mul(B, A, X, ctx); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) ca_set_ui(ca_mat_entry(A, i, i), 1 + n_randint(state, 100), ctx); } /* Check Y = A^(-1) * (A * X) = X */ if (n_randint(state, 2)) { ca_mat_solve_triu(Y, A, B, unit, ctx); } else { ca_mat_set(Y, B, ctx); ca_mat_solve_triu(Y, A, Y, unit, ctx); } if (ca_mat_check_equal(Y, X, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A = \n"); ca_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); ca_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); ca_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("Y = \n"); ca_mat_print(Y, ctx); flint_printf("\n\n"); flint_abort(); } ca_mat_clear(A, ctx); ca_mat_clear(B, ctx); ca_mat_clear(X, ctx); ca_mat_clear(Y, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_mat/trace.c000066400000000000000000000015431461254215100161130ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_trace(ca_t trace, const ca_mat_t mat, ca_ctx_t ctx) { slong i; if (!ca_mat_is_square(mat)) { flint_throw(FLINT_ERROR, "ca_mat_trace: a square matrix is required!\n"); } if (ca_mat_is_empty(mat)) { ca_zero(trace, ctx); return; } ca_set(trace, ca_mat_entry(mat, 0, 0), ctx); for (i = 1; i < ca_mat_nrows(mat); i++) { ca_add(trace, trace, ca_mat_entry(mat, i, i), ctx); } } flint-3.1.3/src/ca_mat/transfer.c000066400000000000000000000014551461254215100166430ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_transfer(ca_mat_t res, ca_ctx_t res_ctx, const ca_mat_t src, ca_ctx_t src_ctx) { slong i, j; if (res_ctx == src_ctx) { ca_mat_set(res, src, res_ctx); } else { for (i = 0; i < ca_mat_nrows(src); i++) for (j = 0; j < ca_mat_ncols(src); j++) ca_transfer(ca_mat_entry(res, i, j), res_ctx, ca_mat_entry(src, i, j), src_ctx); } } flint-3.1.3/src/ca_mat/transpose.c000066400000000000000000000023371461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_transpose(ca_mat_t B, const ca_mat_t A, ca_ctx_t ctx) { slong i, j; if (ca_mat_nrows(B) != ca_mat_ncols(A) || ca_mat_ncols(B) != ca_mat_nrows(A)) { flint_throw(FLINT_ERROR, "Exception (ca_mat_transpose). Incompatible dimensions.\n"); } if (ca_mat_is_empty(A)) return; if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < ca_mat_nrows(A) - 1; i++) { for (j = i + 1; j < ca_mat_ncols(A); j++) { ca_swap(ca_mat_entry(A, i, j), ca_mat_entry(A, j, i), ctx); } } } else /* Not aliased; general case */ { for (i = 0; i < ca_mat_nrows(B); i++) for (j = 0; j < ca_mat_ncols(B); j++) ca_set(ca_mat_entry(B, i, j), ca_mat_entry(A, j, i), ctx); } } flint-3.1.3/src/ca_mat/window_init.c000066400000000000000000000013761461254215100173530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_window_init(ca_mat_t window, const ca_mat_t mat, slong r1, slong c1, slong r2, slong c2, ca_ctx_t ctx) { slong i; window->entries = NULL; window->rows = flint_malloc((r2 - r1) * sizeof(ca_ptr)); for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; window->r = r2 - r1; window->c = c2 - c1; } flint-3.1.3/src/ca_mat/zero.c000066400000000000000000000011451461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_mat.h" void ca_mat_zero(ca_mat_t mat, ca_ctx_t ctx) { slong i, j; for (i = 0; i < ca_mat_nrows(mat); i++) for (j = 0; j < ca_mat_ncols(mat); j++) ca_zero(ca_mat_entry(mat, i, j), ctx); } flint-3.1.3/src/ca_poly.h000066400000000000000000000236011461254215100152230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CA_POLY_H #define CA_POLY_H #ifdef CA_POLY_INLINES_C #define CA_POLY_INLINE #else #define CA_POLY_INLINE static inline #endif #include "ca_vec.h" #ifdef __cplusplus extern "C" { #endif /* Polynomial object */ typedef struct { ca_struct * coeffs; slong alloc; slong length; } ca_poly_struct; typedef ca_poly_struct ca_poly_t[1]; /* todo: return NULL when out of bounds? */ CA_POLY_INLINE ca_ptr ca_poly_coeff_ptr(ca_poly_t poly, slong i) { return poly->coeffs + i; } /* Vectors of polynomials */ typedef struct { ca_poly_struct * entries; slong length; slong alloc; } ca_poly_vec_struct; typedef ca_poly_vec_struct ca_poly_vec_t[1]; /* Memory management */ void ca_poly_init(ca_poly_t poly, ca_ctx_t ctx); void ca_poly_init2(ca_poly_t poly, slong len, ca_ctx_t ctx); void ca_poly_clear(ca_poly_t poly, ca_ctx_t ctx); void ca_poly_fit_length(ca_poly_t poly, slong len, ca_ctx_t ctx); void _ca_poly_set_length(ca_poly_t poly, slong len, ca_ctx_t ctx); void _ca_poly_normalise(ca_poly_t poly, ca_ctx_t ctx); CA_POLY_INLINE void ca_poly_swap(ca_poly_t poly1, ca_poly_t poly2, ca_ctx_t ctx) { FLINT_SWAP(ca_poly_struct, *poly1, *poly2); } /* Assignment and simple values */ void ca_poly_set_ca(ca_poly_t poly, const ca_t x, ca_ctx_t ctx); void ca_poly_set_si(ca_poly_t poly, slong x, ca_ctx_t ctx); CA_POLY_INLINE void ca_poly_zero(ca_poly_t poly, ca_ctx_t ctx) { _ca_poly_set_length(poly, 0, ctx); } CA_POLY_INLINE void ca_poly_x(ca_poly_t poly, ca_ctx_t ctx) { ca_poly_fit_length(poly, 2, ctx); ca_zero(poly->coeffs, ctx); ca_one(poly->coeffs + 1, ctx); _ca_poly_set_length(poly, 2, ctx); } CA_POLY_INLINE void ca_poly_one(ca_poly_t poly, ca_ctx_t ctx) { ca_poly_set_si(poly, 1, ctx); } void ca_poly_set(ca_poly_t res, const ca_poly_t src, ca_ctx_t ctx); void ca_poly_set_fmpz_poly(ca_poly_t res, const fmpz_poly_t src, ca_ctx_t ctx); void ca_poly_set_fmpq_poly(ca_poly_t res, const fmpq_poly_t src, ca_ctx_t ctx); void ca_poly_transfer(ca_poly_t res, ca_ctx_t res_ctx, const ca_poly_t src, ca_ctx_t src_ctx); void ca_poly_set_coeff_ca(ca_poly_t poly, slong n, const ca_t x, ca_ctx_t ctx); /* Random generation */ void ca_poly_randtest(ca_poly_t poly, flint_rand_t state, slong len, slong depth, slong bits, ca_ctx_t ctx); void ca_poly_randtest_rational(ca_poly_t poly, flint_rand_t state, slong len, slong bits, ca_ctx_t ctx); /* Input and output */ void ca_poly_print(const ca_poly_t poly, ca_ctx_t ctx); void ca_poly_printn(const ca_poly_t poly, slong digits, ca_ctx_t ctx); /* Degree and leading coefficient */ int ca_poly_is_proper(const ca_poly_t poly, ca_ctx_t ctx); int ca_poly_make_monic(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx); void _ca_poly_reverse(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx); void ca_poly_reverse(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx); /* Comparisons */ truth_t _ca_poly_check_equal(ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx); truth_t ca_poly_check_equal(const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx); truth_t ca_poly_check_is_zero(const ca_poly_t poly, ca_ctx_t ctx); truth_t ca_poly_check_is_one(const ca_poly_t poly, ca_ctx_t ctx); /* Arithmetic */ void _ca_poly_shift_left(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx); void ca_poly_shift_left(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx); void _ca_poly_shift_right(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx); void ca_poly_shift_right(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx); void ca_poly_neg(ca_poly_t res, const ca_poly_t src, ca_ctx_t ctx); void _ca_poly_add(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx); void ca_poly_add(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx); void _ca_poly_sub(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx); void ca_poly_sub(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx); void _ca_poly_mul(ca_ptr C, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx); void ca_poly_mul(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx); CA_POLY_INLINE void ca_poly_mul_ca(ca_poly_t res, const ca_poly_t poly, const ca_t c, ca_ctx_t ctx) { ca_poly_fit_length(res, poly->length, ctx); _ca_vec_scalar_mul_ca(res->coeffs, poly->coeffs, poly->length, c, ctx); _ca_poly_set_length(res, poly->length, ctx); _ca_poly_normalise(res, ctx); } CA_POLY_INLINE void ca_poly_div_ca(ca_poly_t res, const ca_poly_t poly, const ca_t c, ca_ctx_t ctx) { ca_poly_fit_length(res, poly->length, ctx); _ca_vec_scalar_div_ca(res->coeffs, poly->coeffs, poly->length, c, ctx); _ca_poly_set_length(res, poly->length, ctx); _ca_poly_normalise(res, ctx); } /* todo: improve, document */ CA_POLY_INLINE void ca_poly_div_fmpz(ca_poly_t res, const ca_poly_t poly, const fmpz_t c, ca_ctx_t ctx) { ca_t t; ca_init(t, ctx); ca_set_fmpz(t, c, ctx); ca_poly_div_ca(res, res, t, ctx); ca_clear(t, ctx); } void _ca_poly_mullow_same_nf(ca_ptr C, ca_srcptr A, slong Alen, ca_srcptr B, slong Blen, slong len, ca_field_t K, ca_ctx_t ctx); void _ca_poly_mullow(ca_ptr C, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, slong n, ca_ctx_t ctx); void ca_poly_mullow(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, slong n, ca_ctx_t ctx); void _ca_poly_divrem_basecase(ca_ptr Q, ca_ptr R, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, const ca_t invB, ca_ctx_t ctx); int ca_poly_divrem_basecase(ca_poly_t Q, ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx); void _ca_poly_divrem(ca_ptr Q, ca_ptr R, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, const ca_t invB, ca_ctx_t ctx); int ca_poly_divrem(ca_poly_t Q, ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx); int ca_poly_div(ca_poly_t Q, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx); int ca_poly_rem(ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx); void _ca_poly_pow_ui_trunc(ca_ptr res, ca_srcptr f, slong flen, ulong exp, slong len, ca_ctx_t ctx); void ca_poly_pow_ui_trunc(ca_poly_t res, const ca_poly_t poly, ulong exp, slong len, ca_ctx_t ctx); void _ca_poly_pow_ui(ca_ptr res, ca_srcptr f, slong flen, ulong exp, ca_ctx_t ctx); void ca_poly_pow_ui(ca_poly_t res, const ca_poly_t poly, ulong exp, ca_ctx_t ctx); /* Evaluation and composition */ void _ca_poly_evaluate_horner(ca_t res, ca_srcptr f, slong len, const ca_t x, ca_ctx_t ctx); void ca_poly_evaluate_horner(ca_t res, const ca_poly_t f, const ca_t a, ca_ctx_t ctx); void _ca_poly_evaluate(ca_t res, ca_srcptr f, slong len, const ca_t x, ca_ctx_t ctx); void ca_poly_evaluate(ca_t res, const ca_poly_t f, const ca_t a, ca_ctx_t ctx); void _ca_poly_compose(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx); void ca_poly_compose(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx); /* Integral and derivative */ void _ca_poly_derivative(ca_ptr res, ca_srcptr poly, slong len, ca_ctx_t ctx); void ca_poly_derivative(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx); void _ca_poly_integral(ca_ptr res, ca_srcptr poly, slong len, ca_ctx_t ctx); void ca_poly_integral(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx); /* Greatest common divisor */ slong _ca_poly_gcd_euclidean(ca_ptr G, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx); int ca_poly_gcd_euclidean(ca_poly_t G, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx); slong _ca_poly_gcd(ca_ptr G, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx); int ca_poly_gcd(ca_poly_t G, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx); /* Power series division */ void _ca_poly_inv_series(ca_ptr res, ca_srcptr f, slong flen, slong len, ca_ctx_t ctx); void ca_poly_inv_series(ca_poly_t res, const ca_poly_t f, slong len, ca_ctx_t ctx); void _ca_poly_div_series(ca_ptr res, ca_srcptr f, slong flen, ca_srcptr g, slong glen, slong len, ca_ctx_t ctx); void ca_poly_div_series(ca_poly_t res, const ca_poly_t f, const ca_poly_t g, slong len, ca_ctx_t ctx); /* Elementary functions */ void _ca_poly_exp_series(ca_ptr res, ca_srcptr f, slong flen, slong len, ca_ctx_t ctx); void ca_poly_exp_series(ca_poly_t res, const ca_poly_t f, slong len, ca_ctx_t ctx); void _ca_poly_log_series(ca_ptr res, ca_srcptr f, slong flen, slong len, ca_ctx_t ctx); void ca_poly_log_series(ca_poly_t res, const ca_poly_t f, slong len, ca_ctx_t ctx); /* Vectors of polynomials */ ca_poly_struct * _ca_poly_vec_init(slong len, ca_ctx_t ctx); void ca_poly_vec_init(ca_poly_vec_t res, slong len, ca_ctx_t ctx); void _ca_poly_vec_fit_length(ca_poly_vec_t vec, slong len, ca_ctx_t ctx); void ca_poly_vec_set_length(ca_poly_vec_t vec, slong len, ca_ctx_t ctx); void _ca_poly_vec_clear(ca_poly_struct * v, slong len, ca_ctx_t ctx); void ca_poly_vec_clear(ca_poly_vec_t vec, ca_ctx_t ctx); void ca_poly_vec_append(ca_poly_vec_t vec, const ca_poly_t f, ca_ctx_t ctx); /* Roots and factorization */ int ca_poly_factor_squarefree(ca_t c, ca_poly_vec_t fac, ulong * exp, const ca_poly_t F, ca_ctx_t ctx); int ca_poly_squarefree_part(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx); void _ca_poly_set_roots(ca_ptr poly, ca_srcptr roots, const ulong * exp, slong len, ca_ctx_t ctx); void ca_poly_set_roots(ca_poly_t poly, ca_vec_t roots, const ulong * exp, ca_ctx_t ctx); int _ca_poly_roots(ca_ptr roots, ca_srcptr poly, slong len, ca_ctx_t ctx); int ca_poly_roots(ca_vec_t roots, ulong * exp, const ca_poly_t poly, ca_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/ca_poly/000077500000000000000000000000001461254215100150505ustar00rootroot00000000000000flint-3.1.3/src/ca_poly/add.c000066400000000000000000000022451461254215100157470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_add(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) ca_add(res + i, poly1 + i, poly2 + i, ctx); for (i = min; i < len1; i++) ca_set(res + i, poly1 + i, ctx); for (i = min; i < len2; i++) ca_set(res + i, poly2 + i, ctx); } void ca_poly_add(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) { slong max = FLINT_MAX(poly1->length, poly2->length); ca_poly_fit_length(res, max, ctx); _ca_poly_add(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _ca_poly_set_length(res, max, ctx); _ca_poly_normalise(res, ctx); } flint-3.1.3/src/ca_poly/check_equal.c000066400000000000000000000025271461254215100174660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" truth_t _ca_poly_check_equal(ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) { truth_t eq, res; slong i; res = T_TRUE; for (i = 0; i < len2; i++) { eq = ca_check_equal(poly1 + i, poly2 + i, ctx); if (eq == T_FALSE) return T_FALSE; if (eq == T_UNKNOWN) res = T_UNKNOWN; } for (i = len2; i < len1; i++) { eq = ca_check_is_zero(poly1 + i, ctx); if (eq == T_FALSE) return T_FALSE; if (eq == T_UNKNOWN) res = T_UNKNOWN; } return res; } truth_t ca_poly_check_equal(const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; if (len1 >= len2) return _ca_poly_check_equal(poly1->coeffs, len1, poly2->coeffs, len2, ctx); else return _ca_poly_check_equal(poly2->coeffs, len2, poly1->coeffs, len1, ctx); } flint-3.1.3/src/ca_poly/check_is_one.c000066400000000000000000000013021461254215100176210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" truth_t ca_poly_check_is_one(const ca_poly_t poly, ca_ctx_t ctx) { ca_t t; truth_t res; if (poly->length == 0) return T_FALSE; ca_init(t, ctx); ca_one(t, ctx); res = _ca_poly_check_equal(poly->coeffs, poly->length, t, 1, ctx); ca_clear(t, ctx); return res; } flint-3.1.3/src/ca_poly/check_is_zero.c000066400000000000000000000012561461254215100200270ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" truth_t ca_poly_check_is_zero(const ca_poly_t poly, ca_ctx_t ctx) { ca_t t; truth_t res; if (poly->length == 0) return T_TRUE; ca_init(t, ctx); res = _ca_poly_check_equal(poly->coeffs, poly->length, t, 1, ctx); ca_clear(t, ctx); return res; } flint-3.1.3/src/ca_poly/clear.c000066400000000000000000000011061461254215100163000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_clear(ca_poly_t poly, ca_ctx_t ctx) { slong i; for (i = 0; i < poly->alloc; i++) ca_clear(poly->coeffs + i, ctx); flint_free(poly->coeffs); } flint-3.1.3/src/ca_poly/compose.c000066400000000000000000000035121461254215100166620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012, 2016, 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" #include "gr_poly.h" void _ca_poly_compose(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(_gr_poly_compose(res, poly1, len1, poly2, len2, gr_ctx)); } void ca_poly_compose(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { ca_poly_zero(res, ctx); } else if (len1 == 1 || len2 == 0) { ca_poly_set_ca(res, poly1->coeffs, ctx); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { ca_poly_fit_length(res, lenr, ctx); _ca_poly_compose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); } else { ca_poly_t t; ca_poly_init2(t, lenr, ctx); _ca_poly_compose(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); ca_poly_swap(res, t, ctx); ca_poly_clear(t, ctx); } _ca_poly_set_length(res, lenr, ctx); _ca_poly_normalise(res, ctx); } } flint-3.1.3/src/ca_poly/derivative.c000066400000000000000000000016511461254215100173610ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_derivative(ca_ptr res, ca_srcptr poly, slong len, ca_ctx_t ctx) { slong i; for (i = 1; i < len; i++) ca_mul_ui(res + (i - 1), poly + i, i, ctx); } void ca_poly_derivative(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) { slong len = poly->length; if (len < 2) { ca_poly_zero(res, ctx); } else { ca_poly_fit_length(res, len - 1, ctx); _ca_poly_derivative(res->coeffs, poly->coeffs, len, ctx); _ca_poly_set_length(res, len - 1, ctx); } } flint-3.1.3/src/ca_poly/div_series.c000066400000000000000000000104751461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" ca_field_ptr _ca_vec_same_field2(ca_srcptr A, slong Alen, ca_srcptr B, slong Blen, ca_ctx_t ctx); void _ca_poly_div_series(ca_ptr Q, ca_srcptr A, slong Alen, ca_srcptr B, slong Blen, slong len, ca_ctx_t ctx) { Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); if (CA_IS_SPECIAL(A) || CA_IS_SPECIAL(B)) { if (ca_is_unknown(A, ctx) || ca_is_unknown(B, ctx)) _ca_vec_unknown(Q, len, ctx); else _ca_vec_undefined(Q, len, ctx); return; } /* todo: tuning */ /* todo: shallow copy with integers */ if (Blen >= 4 && _ca_vec_is_fmpq_vec(A, Alen, ctx) && _ca_vec_is_fmpq_vec(B, Blen, ctx) && !fmpq_is_zero(CA_FMPQ(B))) { fmpz *p, *r, *s; fmpz_t pden, rden, sden; p = _fmpz_vec_init(Alen); r = _fmpz_vec_init(Blen); s = _fmpz_vec_init(len); fmpz_init(pden); fmpz_init(rden); fmpz_init(sden); _ca_vec_fmpq_vec_get_fmpz_vec_den(p, pden, A, Alen, ctx); _ca_vec_fmpq_vec_get_fmpz_vec_den(r, rden, B, Blen, ctx); _fmpq_poly_div_series(s, sden, p, pden, Alen, r, rden, Blen, len); _ca_vec_set_fmpz_vec_div_fmpz(Q, s, sden, len, ctx); fmpz_clear(pden); fmpz_clear(rden); fmpz_clear(sden); _fmpz_vec_clear(p, Alen); _fmpz_vec_clear(r, Blen); _fmpz_vec_clear(s, len); return; } if (Blen == 1) { _ca_vec_scalar_div_ca(Q, A, Alen, B, ctx); _ca_vec_zero(Q + Alen, len - Alen, ctx); } else { int is_one; ca_field_ptr K; ca_t q; slong i; if (Blen > 8) { K = _ca_vec_same_field2(A, Alen, B, Blen, ctx); /* If we have fast multiplication and inversion */ /* Todo: also want this if inversion alone is fast and Alen is small */ if (K != NULL && CA_FIELD_IS_NF(K)) { if (len > 2 * qqbar_degree(CA_FIELD_NF_QQBAR(K))) { ca_ptr Binv; Binv = _ca_vec_init(len, ctx); _ca_poly_inv_series(Binv, B, Blen, len, ctx); _ca_poly_mullow(Q, Binv, len, A, Alen, len, ctx); _ca_vec_clear(Binv, len, ctx); return; } } } ca_init(q, ctx); ca_inv(q, B + 0, ctx); ca_mul(Q, A + 0, q, ctx); is_one = (ca_check_is_one(q, ctx) == T_TRUE); for (i = 1; i < len; i++) { ca_dot(Q + i, (i < Alen) ? A + i : NULL, 1, B + 1, 1, Q + i - 1, -1, FLINT_MIN(i, Blen - 1), ctx); if (!is_one) ca_mul(Q + i, Q + i, q, ctx); } ca_clear(q, ctx); } } void ca_poly_div_series(ca_poly_t Q, const ca_poly_t A, const ca_poly_t B, slong len, ca_ctx_t ctx) { if (len == 0) { ca_poly_zero(Q, ctx); return; } if (B->length == 0) { ca_poly_fit_length(Q, len, ctx); ca_unknown(Q->coeffs, ctx); /* todo: uinf when A != 0? */ _ca_vec_undefined(Q->coeffs + 1, len - 1, ctx); _ca_poly_set_length(Q, len, ctx); return; } if (A->length == 0) { if (ca_check_is_zero(B->coeffs, ctx) == T_FALSE) { ca_poly_zero(Q, ctx); } else { ca_poly_fit_length(Q, len, ctx); _ca_vec_unknown(Q->coeffs, len, ctx); _ca_poly_set_length(Q, len, ctx); } return; } if (Q == A || Q == B) { ca_poly_t t; ca_poly_init(t, ctx); ca_poly_div_series(t, A, B, len, ctx); ca_poly_swap(Q, t, ctx); ca_poly_clear(t, ctx); return; } ca_poly_fit_length(Q, len, ctx); _ca_poly_div_series(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, len, ctx); _ca_poly_set_length(Q, len, ctx); _ca_poly_normalise(Q, ctx); } flint-3.1.3/src/ca_poly/divrem.c000066400000000000000000000052251461254215100165060ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_divrem(ca_ptr Q, ca_ptr R, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, const ca_t invB, ca_ctx_t ctx) { _ca_poly_divrem_basecase(Q, R, A, lenA, B, lenB, invB, ctx); } int ca_poly_divrem(ca_poly_t Q, ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; ca_ptr q, r; ca_t invB; if (lenB == 0) return 0; if (lenA < lenB) { if (ca_check_is_zero(B->coeffs + lenB - 1, ctx) == T_FALSE) { ca_poly_set(R, A, ctx); ca_poly_zero(Q, ctx); return 1; } else { return 0; } } ca_init(invB, ctx); ca_inv(invB, B->coeffs + lenB - 1, ctx); if (CA_IS_SPECIAL(invB)) { ca_clear(invB, ctx); return 0; } if (Q == A || Q == B) { q = _ca_vec_init(lenQ, ctx); } else { ca_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { r = _ca_vec_init(lenA, ctx); } else { ca_poly_fit_length(R, lenA, ctx); r = R->coeffs; } _ca_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _ca_vec_clear(Q->coeffs, Q->alloc, ctx); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _ca_poly_set_length(Q, lenQ, ctx); } if (R == B) { _ca_vec_clear(R->coeffs, R->alloc, ctx); R->coeffs = r; R->alloc = lenA; R->length = lenA; } _ca_poly_set_length(R, lenB - 1, ctx); _ca_poly_normalise(R, ctx); ca_clear(invB, ctx); return 1; } int ca_poly_div(ca_poly_t Q, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) { ca_poly_t R; int success; ca_poly_init(R, ctx); success = ca_poly_divrem(Q, R, A, B, ctx); ca_poly_clear(R, ctx); return success; } int ca_poly_rem(ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) { ca_poly_t Q; int success; ca_poly_init(Q, ctx); success = ca_poly_divrem(Q, R, A, B, ctx); ca_poly_clear(Q, ctx); return success; } flint-3.1.3/src/ca_poly/divrem_basecase.c000066400000000000000000000050431461254215100203320ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_divrem_basecase(ca_ptr Q, ca_ptr R, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, const ca_t invB, ca_ctx_t ctx) { slong iQ, iR; if (R != A) _ca_vec_set(R, A, lenA, ctx); for (iQ = lenA - lenB, iR = lenA - 1; iQ >= 0; iQ--, iR--) { if (ca_check_is_zero(R + iR, ctx) == T_TRUE) { ca_zero(Q + iQ, ctx); } else { ca_mul(Q + iQ, R + iR, invB, ctx); _ca_vec_scalar_submul_ca(R + iQ, B, lenB, Q + iQ, ctx); } } } int ca_poly_divrem_basecase(ca_poly_t Q, ca_poly_t R, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; ca_ptr q, r; ca_t invB; if (lenB == 0) return 0; if (lenA < lenB) { if (ca_check_is_zero(B->coeffs + lenB - 1, ctx) == T_FALSE) { ca_poly_set(R, A, ctx); ca_poly_zero(Q, ctx); return 1; } else { return 0; } } ca_init(invB, ctx); ca_inv(invB, B->coeffs + lenB - 1, ctx); if (CA_IS_SPECIAL(invB)) { ca_clear(invB, ctx); return 0; } if (Q == A || Q == B) { q = _ca_vec_init(lenQ, ctx); } else { ca_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { r = _ca_vec_init(lenA, ctx); } else { ca_poly_fit_length(R, lenA, ctx); r = R->coeffs; } _ca_poly_divrem_basecase(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _ca_vec_clear(Q->coeffs, Q->alloc, ctx); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _ca_poly_set_length(Q, lenQ, ctx); } if (R == B) { _ca_vec_clear(R->coeffs, R->alloc, ctx); R->coeffs = r; R->alloc = lenA; R->length = lenA; } _ca_poly_set_length(R, lenB - 1, ctx); _ca_poly_normalise(R, ctx); ca_clear(invB, ctx); return 1; } flint-3.1.3/src/ca_poly/evaluate.c000066400000000000000000000013121461254215100170170ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_evaluate(ca_t res, ca_srcptr f, slong len, const ca_t x, ca_ctx_t ctx) { _ca_poly_evaluate_horner(res, f, len, x, ctx); } void ca_poly_evaluate(ca_t res, const ca_poly_t f, const ca_t a, ca_ctx_t ctx) { _ca_poly_evaluate(res, f->coeffs, f->length, a, ctx); } flint-3.1.3/src/ca_poly/evaluate_horner.c000066400000000000000000000024271461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_evaluate_horner(ca_t y, ca_srcptr f, slong len, const ca_t x, ca_ctx_t ctx) { if (len == 0) { ca_zero(y, ctx); } else if (len == 1 || ca_check_is_zero(x, ctx) == T_TRUE) { ca_set(y, f, ctx); } else if (len == 2) { ca_mul(y, x, f + 1, ctx); ca_add(y, y, f + 0, ctx); } else { slong i = len - 1; ca_t t, u; ca_init(t, ctx); ca_init(u, ctx); ca_set(u, f + i, ctx); for (i = len - 2; i >= 0; i--) { ca_mul(t, u, x, ctx); ca_add(u, f + i, t, ctx); } ca_swap(y, u, ctx); ca_clear(t, ctx); ca_clear(u, ctx); } } void ca_poly_evaluate_horner(ca_t res, const ca_poly_t f, const ca_t a, ca_ctx_t ctx) { _ca_poly_evaluate_horner(res, f->coeffs, f->length, a, ctx); } flint-3.1.3/src/ca_poly/exp_series.c000066400000000000000000000150611461254215100173650ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_vec.h" #include "ca_poly.h" ca_field_ptr _ca_vec_same_field2(ca_srcptr A, slong Alen, ca_srcptr B, slong Blen, ca_ctx_t ctx); void _ca_poly_exp_series_basecase(ca_ptr f, ca_srcptr h, slong hlen, slong len, ca_ctx_t ctx) { slong k; ca_ptr a; ca_t s, e; hlen = FLINT_MIN(hlen, len); ca_init(e, ctx); ca_exp(e, h, ctx); if (_ca_vec_is_fmpq_vec(h + 1, hlen - 1, ctx)) { fmpz *p, *r; fmpz_t pden, rden; p = _fmpz_vec_init(hlen); r = _fmpz_vec_init(len); fmpz_init(pden); fmpz_init(rden); _ca_vec_fmpq_vec_get_fmpz_vec_den(p + 1, pden, h + 1, hlen - 1, ctx); _fmpq_poly_exp_series(r, rden, p, pden, hlen, len); _ca_vec_set_fmpz_vec_div_fmpz(f, r, rden, len, ctx); fmpz_clear(pden); fmpz_clear(rden); _fmpz_vec_clear(p, hlen); _fmpz_vec_clear(r, len); } else { ca_init(s, ctx); a = _ca_vec_init(hlen, ctx); for (k = 1; k < hlen; k++) ca_mul_ui(a + k, h + k, k, ctx); ca_one(f, ctx); for (k = 1; k < len; k++) { ca_dot(s, NULL, 0, a + 1, 1, f + k - 1, -1, FLINT_MIN(k, hlen - 1), ctx); ca_div_ui(f + k, s, k, ctx); } _ca_vec_clear(a, hlen, ctx); ca_clear(s, ctx); } ca_swap(f, e, ctx); _ca_vec_scalar_mul_ca(f + 1, f + 1, len - 1, f, ctx); ca_clear(e, ctx); } /* c_k x^k -> c_k x^k / (m+k) */ static void _ca_poly_integral_offset(ca_ptr res, ca_srcptr poly, slong len, slong m, ca_ctx_t ctx) { slong k; for (k = 0; k < len; k++) ca_div_ui(res + k, poly + k, m + k, ctx); } void _ca_poly_exp_series_newton(ca_ptr f, ca_ptr g, ca_srcptr h, slong hlen, slong n, ca_ctx_t ctx) { slong a[FLINT_BITS]; slong i, m, l, r, alloc; ca_ptr t, hprime; int inverse; if (!(CA_IS_QQ(h, ctx) && fmpq_is_zero(CA_FMPQ(h)))) { hlen = FLINT_MIN(hlen, n); t = _ca_vec_init(hlen + 1, ctx); ca_exp(t + hlen, h, ctx); _ca_vec_set(t + 1, h + 1, hlen - 1, ctx); _ca_poly_exp_series_newton(f, g, t, hlen, n, ctx); _ca_vec_scalar_mul_ca(f, f, n, t + hlen, ctx); if (g != NULL) _ca_vec_scalar_div_ca(g, g, n, t + hlen, ctx); _ca_vec_clear(t, hlen + 1, ctx); return; } /* If g is provided, we compute g = exp(-h), and we can use g as scratch space. Otherwise, we still need to compute exp(-h) to length (n+1)/2 for intermediate use, and we still need n coefficients of scratch space. */ alloc = n; inverse = (g != NULL); if (!inverse) g = _ca_vec_init(n, ctx); hlen = FLINT_MIN(hlen, n); t = _ca_vec_init(n, ctx); hprime = _ca_vec_init(hlen - 1, ctx); _ca_poly_derivative(hprime, h, hlen, ctx); for (i = 1; (WORD(1) << i) < n; i++); a[i = 0] = n; while (n >= 15 || i == 0) a[++i] = (n = (n + 1) / 2); /* f := exp(h) + O(x^n), g := exp(-h) + O(x^n) */ _ca_poly_exp_series_basecase(f, h, FLINT_MIN(hlen, n), n, ctx); _ca_poly_inv_series(g, f, n, n, ctx); for (i--; i >= 0; i--) { m = n; /* previous length */ n = a[i]; /* new length */ l = FLINT_MIN(hlen, n) - 1; r = FLINT_MIN(l + m - 1, n - 1); if (l >= m) _ca_poly_mullow(t, hprime, l, f, m, r, ctx); else _ca_poly_mullow(t, f, m, hprime, l, r, ctx); _ca_poly_mullow(g + m, g, n - m, t + m - 1, r + 1 - m, n - m, ctx); _ca_poly_integral_offset(g + m, g + m, n - m, m, ctx); _ca_poly_mullow(f + m, f, n - m, g + m, n - m, n - m, ctx); /* g := exp(-h) + O(x^n); not needed if we only want exp(x) */ if (i != 0 || inverse) { _ca_poly_mullow(t, f, n, g, m, n, ctx); _ca_poly_mullow(g + m, g, m, t + m, n - m, n - m, ctx); _ca_vec_neg(g + m, g + m, n - m, ctx); } } _ca_vec_clear(hprime, hlen - 1, ctx); _ca_vec_clear(t, alloc, ctx); if (!inverse) _ca_vec_clear(g, alloc, ctx); } void _ca_poly_exp_series(ca_ptr f, ca_srcptr h, slong hlen, slong len, ca_ctx_t ctx) { hlen = FLINT_MIN(hlen, len); if (CA_IS_SPECIAL(h)) { if (ca_is_unknown(h, ctx)) _ca_vec_unknown(f, len, ctx); else _ca_vec_undefined(f, len, ctx); return; } if (hlen == 1) { ca_exp(f, h, ctx); _ca_vec_zero(f + 1, len - 1, ctx); } else if (len == 2) { ca_exp(f, h, ctx); ca_mul(f + 1, f, h + 1, ctx); /* safe since hlen >= 2 */ } else if (_ca_vec_check_is_zero(h + 1, hlen - 2, ctx) == T_TRUE) /* h = a + bx^d */ { slong i, j, d = hlen - 1; ca_t t; ca_init(t, ctx); ca_set(t, h + d, ctx); ca_exp(f, h, ctx); for (i = 1, j = d; j < len; j += d, i++) { ca_mul(f + j, f + j - d, t, ctx); ca_div_ui(f + j, f + j, i, ctx); _ca_vec_zero(f + j - d + 1, hlen - 2, ctx); } _ca_vec_zero(f + j - d + 1, len - (j - d + 1), ctx); ca_clear(t, ctx); } else { if (hlen >= 8) { ca_field_ptr K; K = _ca_vec_same_field2(h + 1, hlen - 1, NULL, 0, ctx); /* Newton iteration where we have fast multiplication */ if (K != NULL && CA_FIELD_IS_NF(K)) { if (len >= qqbar_degree(CA_FIELD_NF_QQBAR(K))) { _ca_poly_exp_series_newton(f, NULL, h, hlen, len, ctx); return; } } } _ca_poly_exp_series_basecase(f, h, hlen, len, ctx); } } void ca_poly_exp_series(ca_poly_t f, const ca_poly_t h, slong len, ca_ctx_t ctx) { slong hlen = h->length; if (len == 0) { ca_poly_zero(f, ctx); return; } if (hlen == 0) { ca_poly_one(f, ctx); return; } if (hlen == 1 && ca_check_is_number(h->coeffs, ctx) == T_TRUE) len = 1; ca_poly_fit_length(f, len, ctx); _ca_poly_exp_series(f->coeffs, h->coeffs, hlen, len, ctx); _ca_poly_set_length(f, len, ctx); _ca_poly_normalise(f, ctx); } flint-3.1.3/src/ca_poly/factor_squarefree.c000066400000000000000000000047541461254215100207260ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" int ca_poly_factor_squarefree(ca_t c, ca_poly_vec_t fac, ulong * exp, const ca_poly_t F, ca_ctx_t ctx) { ca_poly_t f, d, t1; ca_poly_t v, w, s; slong i; int success; if (F->length == 0) { ca_zero(c, ctx); ca_poly_vec_set_length(fac, 0, ctx); return 1; } if (!ca_poly_is_proper(F, ctx)) { return 0; } ca_set(c, F->coeffs + F->length - 1, ctx); if (F->length == 1) { ca_poly_vec_set_length(fac, 0, ctx); return 1; } ca_poly_init(f, ctx); ca_poly_init(d, ctx); ca_poly_init(t1, ctx); ca_poly_init(v, ctx); ca_poly_init(w, ctx); ca_poly_init(s, ctx); success = 0; ca_poly_make_monic(f, F, ctx); ca_poly_derivative(t1, f, ctx); if (!ca_poly_gcd(d, f, t1, ctx)) goto cleanup; ca_poly_vec_set_length(fac, 0, ctx); if (d->length == 1) { ca_poly_vec_append(fac, f, ctx); exp[fac->length - 1] = 1; } else { ca_poly_div(v, f, d, ctx); ca_poly_div(w, t1, d, ctx); /* invariant: v is monic, so we don't need to check if it is proper */ for (i = 1; ; i++) { ca_poly_derivative(t1, v, ctx); ca_poly_sub(s, w, t1, ctx); if (!ca_poly_is_proper(s, ctx)) goto cleanup; if (s->length == 0) { if (v->length > 1) { ca_poly_vec_append(fac, v, ctx); exp[fac->length - 1] = i; } break; } if (!ca_poly_gcd(d, v, s, ctx)) goto cleanup; ca_poly_div(v, v, d, ctx); ca_poly_div(w, s, d, ctx); if (d->length > 1) { ca_poly_vec_append(fac, d, ctx); exp[fac->length - 1] = i; } } } success = 1; cleanup: ca_poly_clear(f, ctx); ca_poly_clear(d, ctx); ca_poly_clear(t1, ctx); ca_poly_clear(v, ctx); ca_poly_clear(w, ctx); ca_poly_clear(s, ctx); return success; } flint-3.1.3/src/ca_poly/fit_length.c000066400000000000000000000014441461254215100173420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_fit_length(ca_poly_t poly, slong len, ca_ctx_t ctx) { slong i; if (len > poly->alloc) { if (len < 2 * poly->alloc) len = 2 * poly->alloc; poly->coeffs = flint_realloc(poly->coeffs, len * sizeof(ca_struct)); for (i = poly->alloc; i < len; i++) ca_init(poly->coeffs + i, ctx); poly->alloc = len; } } flint-3.1.3/src/ca_poly/gcd.c000066400000000000000000000125721461254215100157600ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_mat.h" #include "ca_poly.h" int _ca_poly_check_coprime_numerical(ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx) { acb_t D; slong degA, degB, i, j; slong prec; int result; acb_ptr TA, TB; degA = lenA - 1; degB = lenB - 1; TA = _acb_vec_init(lenA); TB = _acb_vec_init(lenA); acb_init(D); prec = ctx->options[CA_OPT_LOW_PREC]; for (i = 0; i <= degA; i++) ca_get_acb(TA + i, A + i, prec, ctx); for (i = 0; i <= degB; i++) ca_get_acb(TB + i, B + i, prec, ctx); if (_acb_vec_is_real(TA, lenA) && _acb_vec_is_real(TB, lenB)) { arb_mat_t R; arb_mat_init(R, degA + degB, degA + degB); for (i = 0; i < degB; i++) { for (j = 0; j <= degA; j++) { if (i == 0) arb_swap(acb_mat_entry(R, 0, j), acb_realref(TA + j)); else arb_set(arb_mat_entry(R, i, i + j), arb_mat_entry(R, 0, j)); } } for (i = 0; i < degA; i++) { for (j = 0; j <= degB; j++) { if (i == 0) arb_swap(arb_mat_entry(R, degB, j), acb_realref(TB + j)); else arb_set(acb_mat_entry(R, degB + i, i + j), arb_mat_entry(R, degB, j)); } } arb_mat_det(acb_realref(D), R, prec); arb_mat_clear(R); } else { acb_mat_t C; acb_mat_init(C, degA + degB, degA + degB); for (i = 0; i < degB; i++) { for (j = 0; j <= degA; j++) { if (i == 0) acb_swap(acb_mat_entry(C, 0, j), TA + j); else acb_set(acb_mat_entry(C, i, i + j), acb_mat_entry(C, 0, j)); } } for (i = 0; i < degA; i++) { for (j = 0; j <= degB; j++) { if (i == 0) acb_swap(acb_mat_entry(C, degB, j), TB + j); else acb_set(acb_mat_entry(C, degB + i, i + j), acb_mat_entry(C, degB, j)); } } acb_mat_det(D, C, prec); acb_mat_clear(C); } result = !acb_contains_zero(D); _acb_vec_clear(TA, lenA); _acb_vec_clear(TB, lenB); acb_clear(D); return result; } /* assumes lenA >= lenB >= 1, and both A and B have nonzero leading coefficient */ slong _ca_poly_gcd(ca_ptr G, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx) { if (_ca_vec_is_fmpq_vec(A, lenA, ctx) && _ca_vec_is_fmpq_vec(B, lenB, ctx)) { fmpz * zA, * zB, *zG; fmpz_t den; slong i, lenA2; fmpz_init(den); zA = _fmpz_vec_init(lenA); zB = _fmpz_vec_init(lenB); zG = _fmpz_vec_init(lenA); _ca_vec_fmpq_vec_get_fmpz_vec_den(zA, den, A, lenA, ctx); _ca_vec_fmpq_vec_get_fmpz_vec_den(zB, den, B, lenB, ctx); _fmpz_poly_gcd(zG, zA, lenA, zB, lenB); lenA2 = lenA; while (lenA2 > 1 && fmpz_is_zero(zG + lenA2 - 1)) lenA2--; for (i = 0; i < lenA2; i++) ca_set_fmpz(G + i, zG + i, ctx); _fmpz_vec_clear(zA, lenA); _fmpz_vec_clear(zB, lenB); _fmpz_vec_clear(zG, lenA); fmpz_clear(den); return lenA2; } if (_ca_poly_check_coprime_numerical(A, lenA, B, lenB, ctx)) { ca_one(G, ctx); return 1; } return _ca_poly_gcd_euclidean(G, A, lenA, B, lenB, ctx); } int ca_poly_gcd(ca_poly_t G, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenG; ca_ptr g; if (A->length == 0 && B->length == 0) { ca_poly_zero(G, ctx); return 1; } if (A->length == 0) return ca_poly_make_monic(G, B, ctx); if (B->length == 0) return ca_poly_make_monic(G, A, ctx); if (A->length < B->length) return ca_poly_gcd(G, B, A, ctx); if (ca_check_is_zero(A->coeffs + A->length - 1, ctx) != T_FALSE || ca_check_is_zero(B->coeffs + B->length - 1, ctx) != T_FALSE) { return 0; } /* lenA >= lenB >= 1 */ if (G == A || G == B) { g = _ca_vec_init(FLINT_MIN(lenA, lenB), ctx); } else { ca_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } lenG = _ca_poly_gcd(g, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _ca_vec_clear(G->coeffs, G->alloc, ctx); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _ca_poly_set_length(G, lenG, ctx); if (lenG == 0) { return 0; } else { if (G->length == 1) ca_one(G->coeffs, ctx); else ca_poly_make_monic(G, G, ctx); return 1; } } flint-3.1.3/src/ca_poly/gcd_euclidean.c000066400000000000000000000100071461254215100177600ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" #define CA_VEC_NORM(success, R, lenR, ctx) \ do { \ (success) = 1; \ while ((lenR) > 0) \ { \ truth_t is_zero; \ is_zero = ca_check_is_zero((R) + (lenR) - 1, (ctx)); \ if (is_zero == T_TRUE) \ (lenR)--; \ else if (is_zero == T_UNKNOWN) \ { \ (success) = 0; \ break; \ } \ else \ { \ break; \ } \ } \ } while (0) \ /* assumes lenA >= lenB >= 1, and both A and B have nonzero leading coefficient */ slong _ca_poly_gcd_euclidean(ca_ptr G, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx) { const slong lenW = FLINT_MAX(lenA - lenB + 1, lenB) + lenA + 2 * lenB; ca_t invR3; ca_ptr Q, R1, R2, R3, T, W; slong lenR2, lenR3; int success; if (lenB == 1) { ca_one(G, ctx); return 1; } success = 1; /* lenA >= lenB > 1 */ ca_init(invR3, ctx); W = _ca_vec_init(lenW, ctx); Q = W; R1 = W + FLINT_MAX(lenA - lenB + 1, lenB); R2 = R1 + lenA; R3 = R2 + lenB; ca_inv(invR3, B + lenB - 1, ctx); _ca_poly_divrem(Q, R1, A, lenA, B, lenB, invR3, ctx); lenR3 = lenB - 1; CA_VEC_NORM(success, R1, lenR3, ctx); if (!success) goto cleanup; if (lenR3 == 0) { ca_clear(invR3, ctx); _ca_vec_set(G, B, lenB, ctx); _ca_vec_clear(W, lenW, ctx); return lenB; } T = R3; R3 = R1; R1 = T; _ca_vec_set(R2, B, lenB, ctx); lenR2 = lenB; do { ca_inv(invR3, R3 + (lenR3 - 1), ctx); _ca_poly_divrem(Q, R1, R2, lenR2, R3, lenR3, invR3, ctx); lenR2 = lenR3--; CA_VEC_NORM(success, R1, lenR3, ctx); if (!success) goto cleanup; T = R2; R2 = R3; R3 = R1; R1 = T; } while (lenR3 > 0); _ca_vec_set(G, R2, lenR2, ctx); cleanup: _ca_vec_clear(W, lenW, ctx); ca_clear(invR3, ctx); if (success) return lenR2; else return 0; } int ca_poly_gcd_euclidean(ca_poly_t G, const ca_poly_t A, const ca_poly_t B, ca_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenG; ca_ptr g; if (A->length == 0 && B->length == 0) { ca_poly_zero(G, ctx); return 1; } if (A->length == 0) return ca_poly_make_monic(G, B, ctx); if (B->length == 0) return ca_poly_make_monic(G, A, ctx); if (A->length < B->length) return ca_poly_gcd_euclidean(G, B, A, ctx); if (ca_check_is_zero(A->coeffs + A->length - 1, ctx) != T_FALSE || ca_check_is_zero(B->coeffs + B->length - 1, ctx) != T_FALSE) { return 0; } /* lenA >= lenB >= 1 */ if (G == A || G == B) { g = _ca_vec_init(FLINT_MIN(lenA, lenB), ctx); } else { ca_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } lenG = _ca_poly_gcd_euclidean(g, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _ca_vec_clear(G->coeffs, G->alloc, ctx); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _ca_poly_set_length(G, lenG, ctx); if (lenG == 0) { return 0; } else { if (G->length == 1) ca_one(G->coeffs, ctx); else ca_poly_make_monic(G, G, ctx); return 1; } } flint-3.1.3/src/ca_poly/get_fexpr.c000066400000000000000000000047631461254215100172110ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #include "ca.h" #include "ca_ext.h" #include "ca_poly.h" void _ca_default_variables(fexpr_ptr ext_vars, slong num_ext); void _ca_get_fexpr_given_ext(fexpr_t res, const ca_t x, ulong flags, ca_ext_ptr * ext, slong num_ext, const fexpr_struct * ext_vars, ca_ctx_t ctx); void _ca_all_extensions(ca_ext_ptr ** extensions, slong * length, const ca_t x, ca_ctx_t ctx); void _ca_ext_get_fexpr_given_ext(fexpr_t res, const ca_ext_t x, ulong flags, ca_ext_ptr * ext, slong num_ext, const fexpr_struct * ext_vars, ca_ctx_t ctx); void ca_poly_get_fexpr(fexpr_t res, const ca_poly_t A, ulong flags, ca_ctx_t ctx) { ca_ext_ptr * ext; slong n, i, num_ext; fexpr_struct * ext_vars; fexpr_struct * where_args; fexpr_struct * coeffs; fexpr_t t, u; ext = NULL; num_ext = 0; n = A->length; if (n == 0) { fexpr_zero(res); return; } for (i = 0; i < n; i++) _ca_all_extensions(&ext, &num_ext, A->coeffs + i, ctx); ext_vars = _fexpr_vec_init(num_ext); fexpr_init(t); fexpr_init(u); _ca_default_variables(ext_vars, num_ext); coeffs = _fexpr_vec_init(n); for (i = 0; i < n; i++) _ca_get_fexpr_given_ext(coeffs + i, A->coeffs + i, flags, ext, num_ext, ext_vars, ctx); fexpr_set_symbol_builtin(t, FEXPR_List); fexpr_call_vec(u, t, coeffs, n); if (num_ext == 0) { fexpr_call_builtin1(res, FEXPR_Polynomial, u); } else { where_args = _fexpr_vec_init(num_ext + 1); fexpr_call_builtin1(where_args + 0, FEXPR_Polynomial, u); for (i = 0; i < num_ext; i++) { _ca_ext_get_fexpr_given_ext(t, ext[i], flags, ext, num_ext, ext_vars, ctx); fexpr_call_builtin2(where_args + i + 1, FEXPR_Def, ext_vars + i, t); } fexpr_set_symbol_builtin(t, FEXPR_Where); fexpr_call_vec(res, t, where_args, num_ext + 1); _fexpr_vec_clear(where_args, num_ext + 1); } _fexpr_vec_clear(coeffs, n); flint_free(ext); fexpr_clear(t); fexpr_clear(u); _fexpr_vec_clear(ext_vars, num_ext); } flint-3.1.3/src/ca_poly/init.c000066400000000000000000000012231461254215100161550ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_init(ca_poly_t poly, ca_ctx_t ctx) { poly->coeffs = NULL; poly->length = 0; poly->alloc = 0; } void ca_poly_init2(ca_poly_t poly, slong len, ca_ctx_t ctx) { ca_poly_init(poly, ctx); ca_poly_fit_length(poly, len, ctx); } flint-3.1.3/src/ca_poly/inlines.c000066400000000000000000000006561461254215100166640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define CA_POLY_INLINES_C #include "ca_poly.h" flint-3.1.3/src/ca_poly/integral.c000066400000000000000000000016131461254215100170220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_integral(ca_ptr res, ca_srcptr poly, slong len, ca_ctx_t ctx) { slong k = len - 1; for (k = len - 1; k > 0; k--) ca_div_ui(res + k, poly + k - 1, k, ctx); ca_zero(res, ctx); } void ca_poly_integral(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) { ca_poly_fit_length(res, poly->length + 1, ctx); _ca_poly_integral(res->coeffs, poly->coeffs, poly->length + 1, ctx); _ca_poly_set_length(res, poly->length + 1, ctx); _ca_poly_normalise(res, ctx); } flint-3.1.3/src/ca_poly/inv_series.c000066400000000000000000000103121461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "ca_poly.h" ca_field_ptr _ca_vec_same_field2(ca_srcptr A, slong Alen, ca_srcptr B, slong Blen, ca_ctx_t ctx); void _ca_poly_inv_series(ca_ptr Qinv, ca_srcptr Q, slong Qlen, slong len, ca_ctx_t ctx) { Qlen = FLINT_MIN(Qlen, len); if (CA_IS_SPECIAL(Q)) { if (ca_is_unknown(Q, ctx)) _ca_vec_unknown(Qinv, len, ctx); else _ca_vec_undefined(Qinv, len, ctx); return; } /* todo: tuning */ /* todo: shallow copy with integers */ if (Qlen >= 4 && _ca_vec_is_fmpq_vec(Q, Qlen, ctx) && !fmpq_is_zero(CA_FMPQ(Q))) { fmpz *p, *r; fmpz_t pden, rden; p = _fmpz_vec_init(Qlen); r = _fmpz_vec_init(len); fmpz_init(pden); fmpz_init(rden); _ca_vec_fmpq_vec_get_fmpz_vec_den(p, pden, Q, Qlen, ctx); _fmpq_poly_inv_series(r, rden, p, pden, Qlen, len); _ca_vec_set_fmpz_vec_div_fmpz(Qinv, r, rden, len, ctx); fmpz_clear(pden); fmpz_clear(rden); _fmpz_vec_clear(p, Qlen); _fmpz_vec_clear(r, len); return; } ca_inv(Qinv, Q, ctx); if (CA_IS_SPECIAL(Qinv)) { if (ca_is_unknown(Qinv, ctx)) _ca_vec_unknown(Qinv + 1, len - 1, ctx); else _ca_vec_undefined(Qinv + 1, len - 1, ctx); return; } if (Qlen == 1) { _ca_vec_zero(Qinv + 1, len - 1, ctx); } else if (len == 2) { ca_mul(Qinv + 1, Qinv, Qinv, ctx); ca_mul(Qinv + 1, Qinv + 1, Q + 1, ctx); ca_neg(Qinv + 1, Qinv + 1, ctx); } else { int is_one; ca_field_ptr K; slong i, blen; if (Qlen <= 8) { blen = len; } else { K = _ca_vec_same_field2(Q, Qlen, NULL, 0, ctx); /* Newton iteration where we have fast multiplication */ if (K != NULL && CA_FIELD_IS_NF(K)) { blen = 2 * qqbar_degree(CA_FIELD_NF_QQBAR(K)); blen = FLINT_MIN(blen, len); } else { blen = len; } } is_one = (ca_check_is_one(Qinv, ctx) == T_TRUE); for (i = 1; i < blen; i++) { ca_dot(Qinv + i, NULL, 1, Q + 1, 1, Qinv + i - 1, -1, FLINT_MIN(i, Qlen - 1), ctx); if (!is_one) ca_mul(Qinv + i, Qinv + i, Qinv, ctx); } if (len > blen) { slong Qnlen, Wlen, W2len; ca_ptr W; W = _ca_vec_init(len, ctx); NEWTON_INIT(blen, len) NEWTON_LOOP(m, n) Qnlen = FLINT_MIN(Qlen, n); Wlen = FLINT_MIN(Qnlen + m - 1, n); W2len = Wlen - m; _ca_poly_mullow(W, Q, Qnlen, Qinv, m, Wlen, ctx); _ca_poly_mullow(Qinv + m, Qinv, m, W + m, W2len, n - m, ctx); _ca_vec_neg(Qinv + m, Qinv + m, n - m, ctx); NEWTON_END_LOOP NEWTON_END _ca_vec_clear(W, len, ctx); } } } void ca_poly_inv_series(ca_poly_t Qinv, const ca_poly_t Q, slong len, ca_ctx_t ctx) { if (len == 0) { ca_poly_zero(Qinv, ctx); return; } if (Q->length == 0) { ca_poly_fit_length(Qinv, len, ctx); ca_uinf(Qinv->coeffs, ctx); _ca_vec_undefined(Qinv->coeffs + 1, len - 1, ctx); _ca_poly_set_length(Qinv, len, ctx); return; } if (Qinv == Q) { ca_poly_t t; ca_poly_init(t, ctx); ca_poly_inv_series(t, Q, len, ctx); ca_poly_swap(Qinv, t, ctx); ca_poly_clear(t, ctx); return; } ca_poly_fit_length(Qinv, len, ctx); _ca_poly_inv_series(Qinv->coeffs, Q->coeffs, Q->length, len, ctx); _ca_poly_set_length(Qinv, len, ctx); _ca_poly_normalise(Qinv, ctx); } flint-3.1.3/src/ca_poly/is_proper.c000066400000000000000000000013361461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" int ca_poly_is_proper(const ca_poly_t poly, ca_ctx_t ctx) { slong i, len; len = poly->length; for (i = 0; i < len; i++) if (CA_IS_SPECIAL(poly->coeffs + i)) return 0; if (len >= 1) if (ca_check_is_zero(poly->coeffs + len - 1, ctx) != T_FALSE) return 0; return 1; } flint-3.1.3/src/ca_poly/log_series.c000066400000000000000000000055741461254215100173620ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_log_series(ca_ptr res, ca_srcptr f, slong flen, slong len, ca_ctx_t ctx) { flen = FLINT_MIN(flen, len); if (CA_IS_SPECIAL(f)) { if (ca_is_unknown(f, ctx)) _ca_vec_unknown(res, len, ctx); else _ca_vec_undefined(res, len, ctx); return; } if (flen == 1) { ca_log(res, f, ctx); _ca_vec_zero(res + 1, len - 1, ctx); } else if (len == 2) { ca_div(res + 1, f + 1, f + 0, ctx); /* safe since hlen >= 2 */ ca_log(res, f, ctx); } else if (_ca_vec_check_is_zero(f + 1, flen - 2, ctx) == T_TRUE) /* f = a + bx^d */ { slong i, j, d = flen - 1; for (i = 1, j = d; j < len; j += d, i++) { if (i == 1) ca_div(res + j, f + d, f + 0, ctx); else ca_mul(res + j, res + j - d, res + d, ctx); _ca_vec_zero(res + j - d + 1, flen - 2, ctx); } _ca_vec_zero(res + j - d + 1, len - (j - d + 1), ctx); for (i = 2, j = 2 * d; j < len; j += d, i++) ca_div_si(res + j, res + j, i % 2 ? i : -i, ctx); ca_log(res, f, ctx); /* done last to allow aliasing */ } else { ca_ptr f_diff, f_inv; ca_t a; slong alloc; alloc = len + flen - 1; f_inv = _ca_vec_init(alloc, ctx); f_diff = f_inv + len; ca_init(a, ctx); ca_log(a, f, ctx); _ca_poly_derivative(f_diff, f, flen, ctx); _ca_poly_inv_series(f_inv, f, flen, len, ctx); _ca_poly_mullow(res, f_inv, len - 1, f_diff, flen - 1, len - 1, ctx); _ca_poly_integral(res, res, len, ctx); ca_swap(res, a, ctx); ca_clear(a, ctx); _ca_vec_clear(f_inv, alloc, ctx); } if (ca_check_is_number(res, ctx) != T_TRUE) { if (ca_is_unknown(res, ctx)) _ca_vec_unknown(res + 1, len - 1, ctx); else _ca_vec_undefined(res + 1, len - 1, ctx); return; } } void ca_poly_log_series(ca_poly_t res, const ca_poly_t f, slong len, ca_ctx_t ctx) { if (len == 0) { ca_poly_zero(res, ctx); return; } ca_poly_fit_length(res, len, ctx); if (f->length == 0) { ca_neg_inf(res->coeffs, ctx); _ca_vec_undefined(res->coeffs + 1, len - 1, ctx); } else { _ca_poly_log_series(res->coeffs, f->coeffs, f->length, len, ctx); } _ca_poly_set_length(res, len, ctx); _ca_poly_normalise(res, ctx); } flint-3.1.3/src/ca_poly/make_monic.c000066400000000000000000000027051461254215100173220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" int ca_poly_make_monic(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) { if (poly->length == 0) { ca_poly_zero(res, ctx); return 0; } else { if (ca_check_is_one(poly->coeffs + poly->length - 1, ctx) == T_TRUE) { ca_poly_set(res, poly, ctx); ca_one(res->coeffs + res->length - 1, ctx); return 1; } if (ca_check_is_neg_one(poly->coeffs + poly->length - 1, ctx) == T_TRUE) { ca_poly_neg(res, poly, ctx); ca_one(res->coeffs + res->length - 1, ctx); return 1; } ca_poly_set(res, poly, ctx); ca_inv(res->coeffs + res->length - 1, res->coeffs + res->length - 1, ctx); if (CA_IS_SPECIAL(res->coeffs + res->length - 1)) { return 0; } else { _ca_vec_scalar_mul_ca(res->coeffs, res->coeffs, res->length - 1, res->coeffs + res->length - 1, ctx); ca_one(res->coeffs + res->length - 1, ctx); return 1; } } } flint-3.1.3/src/ca_poly/mul.c000066400000000000000000000026361461254215100160200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_mul(ca_ptr C, ca_srcptr A, slong lenA, ca_srcptr B, slong lenB, ca_ctx_t ctx) { _ca_poly_mullow(C, A, lenA, B, lenB, lenA + lenB - 1, ctx); } void ca_poly_mul(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { ca_poly_zero(res, ctx); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { ca_poly_t temp; ca_poly_init2(temp, len_out, ctx); _ca_poly_mul(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); ca_poly_swap(res, temp, ctx); ca_poly_clear(temp, ctx); } else { ca_poly_fit_length(res, len_out, ctx); _ca_poly_mul(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); } _ca_poly_set_length(res, len_out, ctx); } flint-3.1.3/src/ca_poly/mullow.c000066400000000000000000000205101461254215100165310ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" ca_field_ptr _ca_vec_same_field2(ca_srcptr A, slong Alen, ca_srcptr B, slong Blen, ca_ctx_t ctx) { ca_field_ptr K; ca_field_ptr QQ; slong i; QQ = ctx->field_qq; K = QQ; for (i = 0; i < Alen; i++) { if (CA_IS_QQ(A + i, ctx)) continue; if (CA_IS_SPECIAL(A + i)) return NULL; if (K == QQ) K = CA_FIELD(A + i, ctx); else if (K != CA_FIELD(A + i, ctx)) return NULL; } if (B != NULL) { for (i = 0; i < Blen; i++) { if (CA_IS_QQ(B + i, ctx)) continue; if (CA_IS_SPECIAL(B + i)) return NULL; if (K == QQ) K = CA_FIELD(B + i, ctx); else if (K != CA_FIELD(B + i, ctx)) return NULL; } } return K; } static void _ca_addmul(ca_t x, ca_t tmp, const ca_t a, const ca_t b, ca_ctx_t ctx) { ca_mul(tmp, a, b, ctx); ca_add(x, x, tmp, ctx); } static void _ca_poly_sqrlow_classical(ca_ptr res, ca_srcptr poly1, slong len1, slong n, ca_ctx_t ctx) { slong i, start, stop; ca_t t; /* Basecase squaring */ ca_init(t, ctx); ca_sqr(res, poly1, ctx); ca_mul(res + 1, poly1, poly1 + 1, ctx); ca_mul_ui(res + 1, res + 1, 2, ctx); for (i = 2; i < FLINT_MIN(n, 2 * len1 - 3); i++) { start = FLINT_MAX(0, i - len1 + 1); stop = FLINT_MIN(len1 - 1, (i + 1) / 2 - 1); ca_dot(res + i, NULL, 0, poly1 + start, 1, poly1 + i - start, -1, stop - start + 1, ctx); ca_mul_ui(res + i, res + i, 2, ctx); if (i % 2 == 0 && i / 2 < len1) _ca_addmul(res + i, t, poly1 + i / 2, poly1 + i / 2, ctx); } if (len1 > 2 && n >= 2 * len1 - 2) { ca_mul(res + 2 * len1 - 3, poly1 + len1 - 1, poly1 + len1 - 2, ctx); ca_mul_ui(res + 2 * len1 - 3, res + 2 * len1 - 3, 2, ctx); } if (n >= 2 * len1 - 1) ca_sqr(res + 2 * len1 - 2, poly1 + len1 - 1, ctx); ca_clear(t, ctx); } static void _ca_poly_sqrlow_fmpqs(ca_ptr res, ca_srcptr poly1, slong len1, slong n, ca_ctx_t ctx) { fmpz *z1, *z3; fmpz_t den1; if (_ca_vec_fmpq_vec_is_fmpz_vec(poly1, len1, ctx)) { slong i; z1 = _fmpz_vec_init(len1 + n); z3 = z1 + len1; for (i = 0; i < len1; i++) z1[i] = *CA_FMPQ_NUMREF(poly1 + i); _fmpz_poly_sqrlow(z3, z1, len1, n); for (i = 0; i < n; i++) { _ca_make_fmpq(res + i, ctx); fmpz_one(CA_FMPQ_DENREF(res + i)); fmpz_clear(CA_FMPQ_NUMREF(res + i)); *CA_FMPQ_NUMREF(res + i) = z3[i]; } flint_free(z1); } else { fmpz_init(den1); z1 = _fmpz_vec_init(len1 + n); z3 = z1 + len1; _ca_vec_fmpq_vec_get_fmpz_vec_den(z1, den1, poly1, len1, ctx); fmpz_mul(den1, den1, den1); _fmpz_poly_sqrlow(z3, z1, len1, n); _ca_vec_set_fmpz_vec_div_fmpz(res, z3, den1, n, ctx); _fmpz_vec_clear(z1, len1 + n); fmpz_clear(den1); } } static void _ca_poly_mullow_fmpqs(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, slong n, ca_ctx_t ctx) { fmpz *z1, *z2, *z3; fmpz_t den1, den2; /* Todo: handle mixed cases */ if (_ca_vec_fmpq_vec_is_fmpz_vec(poly1, len1, ctx) && _ca_vec_fmpq_vec_is_fmpz_vec(poly2, len2, ctx)) { slong i; z1 = _fmpz_vec_init(len1 + len2 + n); z2 = z1 + len1; z3 = z2 + len2; for (i = 0; i < len1; i++) z1[i] = *CA_FMPQ_NUMREF(poly1 + i); for (i = 0; i < len2; i++) z2[i] = *CA_FMPQ_NUMREF(poly2 + i); if (len1 >= len2) _fmpz_poly_mullow(z3, z1, len1, z2, len2, n); else _fmpz_poly_mullow(z3, z2, len2, z1, len1, n); for (i = 0; i < n; i++) { _ca_make_fmpq(res + i, ctx); fmpz_one(CA_FMPQ_DENREF(res + i)); fmpz_clear(CA_FMPQ_NUMREF(res + i)); *CA_FMPQ_NUMREF(res + i) = z3[i]; } flint_free(z1); } else { fmpz_init(den1); fmpz_init(den2); z1 = _fmpz_vec_init(len1 + len2 + n); z2 = z1 + len1; z3 = z2 + len2; _ca_vec_fmpq_vec_get_fmpz_vec_den(z1, den1, poly1, len1, ctx); _ca_vec_fmpq_vec_get_fmpz_vec_den(z2, den2, poly2, len2, ctx); fmpz_mul(den1, den1, den2); if (len1 >= len2) _fmpz_poly_mullow(z3, z1, len1, z2, len2, n); else _fmpz_poly_mullow(z3, z2, len2, z1, len1, n); _ca_vec_set_fmpz_vec_div_fmpz(res, z3, den1, n, ctx); _fmpz_vec_clear(z1, len1 + len2 + n); fmpz_clear(den1); fmpz_clear(den2); } } void _ca_poly_mullow(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, slong n, ca_ctx_t ctx) { ca_field_ptr K; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) { ca_mul(res, poly1, poly2, ctx); return; } if (len1 == 1) { _ca_vec_scalar_mul_ca(res, poly2, n, poly1, ctx); return; } if (len2 == 1) { _ca_vec_scalar_mul_ca(res, poly1, n, poly2, ctx); return; } /* Squaring */ if (poly1 == poly2 && len1 == len2) { /* Integers and rationals. */ if (len1 >= 4 && _ca_vec_is_fmpq_vec(poly1, len1, ctx)) { _ca_poly_sqrlow_fmpqs(res, poly1, len1, n, ctx); return; } /* Square over the same number field. */ if (len1 >= 4) { K = _ca_vec_same_field2(poly1, len1, NULL, 0, ctx); if (K != NULL && CA_FIELD_IS_NF(K) && (FLINT_MIN(len1, len2) >= CA_FIELD_NF(K)->pol->length || FLINT_MIN(len1, len2) >= 10)) { _ca_poly_mullow_same_nf(res, poly1, len1, poly2, len2, n, K, ctx); return; } } _ca_poly_sqrlow_classical(res, poly1, len1, n, ctx); return; } if (len1 >= 4 && len2 >= 4 && _ca_vec_is_fmpq_vec(poly1, len1, ctx) && _ca_vec_is_fmpq_vec(poly2, len2, ctx)) { _ca_poly_mullow_fmpqs(res, poly1, len1, poly2, len2, n, ctx); return; } /* Multiply over the same number field. */ if (len1 >= 4) { K = _ca_vec_same_field2(poly1, len1, poly2, len2, ctx); if (K != NULL && CA_FIELD_IS_NF(K) && (FLINT_MIN(len1, len2) >= CA_FIELD_NF(K)->pol->length || FLINT_MIN(len1, len2) >= 10)) { _ca_poly_mullow_same_nf(res, poly1, len1, poly2, len2, n, K, ctx); return; } } /* General case */ { slong i, top1, top2; ca_mul(res, poly1, poly2, ctx); for (i = 1; i < n; i++) { top1 = FLINT_MIN(len1 - 1, i); top2 = FLINT_MIN(len2 - 1, i); ca_dot(res + i, NULL, 0, poly1 + i - top2, 1, poly2 + top2, -1, top1 + top2 - i + 1, ctx); } } } void ca_poly_mullow(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, slong n, ca_ctx_t ctx) { slong len_out; if (poly1->length == 0 || poly2->length == 0 || n == 0) { ca_poly_zero(res, ctx); return; } len_out = poly1->length + poly2->length - 1; n = FLINT_MIN(n, len_out); if (res == poly1 || res == poly2) { ca_poly_t t; ca_poly_init2(t, n, ctx); _ca_poly_mullow(t->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, ctx); ca_poly_swap(res, t, ctx); ca_poly_clear(t, ctx); } else { ca_poly_fit_length(res, n, ctx); _ca_poly_mullow(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, ctx); } _ca_poly_set_length(res, n, ctx); _ca_poly_normalise(res, ctx); } flint-3.1.3/src/ca_poly/mullow_same_nf.c000066400000000000000000000107351461254215100202310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" static const fmpz * _nf_denref(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) return LNF_ELEM_DENREF(a); else if (nf->flag & NF_QUADRATIC) return QNF_ELEM_DENREF(a); else return NF_ELEM_DENREF(a); } /* writes used coefficients; does not write padding zeros */ static void _nf_elem_get_fmpz_poly_lcm(fmpz * pol, fmpz_t t, const nf_elem_t a, const fmpz_t lcm, const nf_t nf) { fmpz_divexact(t, lcm, _nf_denref(a, nf)); if (nf->flag & NF_LINEAR) fmpz_mul(pol, t, LNF_ELEM_NUMREF(a)); else if (nf->flag & NF_QUADRATIC) _fmpz_vec_scalar_mul_fmpz(pol, QNF_ELEM_NUMREF(a), 2, t); else _fmpz_vec_scalar_mul_fmpz(pol, NF_ELEM(a)->coeffs, NF_ELEM(a)->length, t); } static int get_lcm(fmpz_t Aden, ca_srcptr A, slong Alen, ca_field_t K, slong bits_limit, ca_ctx_t ctx) { slong i; fmpz_one(Aden); for (i = 0; i < Alen; i++) { if (CA_IS_QQ(A + i, ctx)) fmpz_lcm(Aden, Aden, CA_FMPQ_DENREF(A + i)); else fmpz_lcm(Aden, Aden, _nf_denref(CA_NF_ELEM(A + i), CA_FIELD_NF(K))); if (fmpz_bits(Aden) > bits_limit) return 0; } return 1; } void _ca_set_nf_fmpz_poly_den(ca_t res, const fmpz_poly_t poly, const fmpz_t den, ca_field_t K, ca_ctx_t ctx); void _ca_poly_mullow_same_nf(ca_ptr C, ca_srcptr A, slong Alen, ca_srcptr B, slong Blen, slong len, ca_field_t K, ca_ctx_t ctx) { fmpz_t Aden, Bden; fmpz_t den, t; slong deg, m; fmpz *ZA, *ZB, *ZC; int squaring; slong i; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); if (!CA_FIELD_IS_NF(K)) { flint_throw(FLINT_ERROR, "_ca_poly_mullow_same_nf: expected a number field\n"); } squaring = (A == B) && (Alen == Blen); fmpz_init(Aden); fmpz_init(Bden); if (!get_lcm(Aden, A, Alen, K, WORD_MAX, ctx) || (!squaring && !get_lcm(Bden, B, Blen, K, WORD_MAX, ctx))) { flint_throw(FLINT_ERROR, "%s\n", __func__); /* fmpz_clear(Aden); fmpz_clear(Bden); _ca_poly_mullow_classical(C, A, Alen, B, Blen, len, ctx); return; */ } fmpz_init(den); fmpz_init(t); /* Todo: could inspect elements to get degree bounds */ deg = CA_FIELD_NF(K)->pol->length - 1; /* Packing length */ m = 2 * deg - 1; ZA = _fmpz_vec_init(Alen * m); if (squaring) ZB = ZA; else ZB = _fmpz_vec_init(Blen * m); ZC = _fmpz_vec_init(len * m); for (i = 0; i < Alen; i++) { if (CA_IS_QQ(A + i, ctx)) { fmpz_divexact(t, Aden, CA_FMPQ_DENREF(A + i)); fmpz_mul(ZA + i * m + 0, t, CA_FMPQ_NUMREF(A + i)); } else { _nf_elem_get_fmpz_poly_lcm(ZA + i * m, t, CA_NF_ELEM(A + i), Aden, CA_FIELD_NF(K)); } } if (!squaring) { for (i = 0; i < Blen; i++) { if (CA_IS_QQ(B + i, ctx)) { fmpz_divexact(t, Bden, CA_FMPQ_DENREF(B + i)); fmpz_mul(ZB + i * m + 0, t, CA_FMPQ_NUMREF(B + i)); } else { _nf_elem_get_fmpz_poly_lcm(ZB + i * m, t, CA_NF_ELEM(B + i), Bden, CA_FIELD_NF(K)); } } } if (squaring) { _fmpz_poly_sqrlow(ZC, ZA, Alen * m, len * m); fmpz_mul(den, Aden, Aden); } else { if (Alen >= Blen) _fmpz_poly_mullow(ZC, ZA, Alen * m, ZB, Blen * m, len * m); else _fmpz_poly_mullow(ZC, ZB, Blen * m, ZA, Alen * m, len * m); fmpz_mul(den, Aden, Bden); } for (i = 0; i < len; i++) { fmpz_poly_t poly; poly->coeffs = ZC + i * m; poly->length = m; while (poly->length > 0 && fmpz_is_zero(poly->coeffs + poly->length - 1)) poly->length--; _ca_set_nf_fmpz_poly_den(C + i, poly, den, K, ctx); } _fmpz_vec_clear(ZA, Alen * m); if (!squaring) _fmpz_vec_clear(ZB, Blen * m); _fmpz_vec_clear(ZC, len * m); fmpz_clear(Aden); fmpz_clear(Bden); fmpz_clear(den); fmpz_clear(t); } flint-3.1.3/src/ca_poly/neg.c000066400000000000000000000011701461254215100157640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_neg(ca_poly_t res, const ca_poly_t src, ca_ctx_t ctx) { ca_poly_fit_length(res, src->length, ctx); _ca_vec_neg(res->coeffs, src->coeffs, src->length, ctx); _ca_poly_set_length(res, src->length, ctx); } flint-3.1.3/src/ca_poly/normalise.c000066400000000000000000000012361461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_normalise(ca_poly_t poly, ca_ctx_t ctx) { slong i; i = poly->length - 1; while (i >= 0 && (ca_check_is_zero(poly->coeffs + i, ctx) == T_TRUE)) { ca_zero(poly->coeffs + i, ctx); i--; } poly->length = i + 1; } flint-3.1.3/src/ca_poly/pow_ui.c000066400000000000000000000027071461254215100165240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_pow_ui(ca_ptr res, ca_srcptr f, slong flen, ulong exp, ca_ctx_t ctx) { _ca_poly_pow_ui_trunc(res, f, flen, exp, exp * (flen - 1) + 1, ctx); } void ca_poly_pow_ui(ca_poly_t res, const ca_poly_t poly, ulong exp, ca_ctx_t ctx) { slong flen, rlen; flen = poly->length; if (exp == 0) { ca_poly_one(res, ctx); } else if (flen == 0) { ca_poly_zero(res, ctx); } else { rlen = exp * (flen - 1) + 1; if (res != poly) { ca_poly_fit_length(res, rlen, ctx); _ca_poly_pow_ui(res->coeffs, poly->coeffs, flen, exp, ctx); _ca_poly_set_length(res, rlen, ctx); _ca_poly_normalise(res, ctx); } else { ca_poly_t t; ca_poly_init2(t, rlen, ctx); _ca_poly_pow_ui(t->coeffs, poly->coeffs, flen, exp, ctx); _ca_poly_set_length(t, rlen, ctx); _ca_poly_normalise(t, ctx); ca_poly_swap(res, t, ctx); ca_poly_clear(t, ctx); } } } flint-3.1.3/src/ca_poly/pow_ui_trunc.c000066400000000000000000000037201461254215100177330ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "ca_poly.h" #include "gr_poly.h" void _ca_poly_pow_ui_trunc(ca_ptr res, ca_srcptr f, slong flen, ulong exp, slong len, ca_ctx_t ctx) { if (exp <= 2) { if (exp == 0) ca_one(res, ctx); else if (exp == 1) _ca_vec_set(res, f, len, ctx); else _ca_poly_mullow(res, f, flen, f, flen, len, ctx); } else { gr_ctx_t gr_ctx; _gr_ctx_init_ca_from_ref(gr_ctx, GR_CTX_CC_CA, ctx); GR_MUST_SUCCEED(_gr_poly_pow_series_ui_binexp(res, f, flen, exp, len, gr_ctx)); } } void ca_poly_pow_ui_trunc(ca_poly_t res, const ca_poly_t poly, ulong exp, slong len, ca_ctx_t ctx) { slong flen, rlen; flen = poly->length; if (exp == 0 && len != 0) { ca_poly_one(res, ctx); } else if (flen == 0 || len == 0) { ca_poly_zero(res, ctx); } else { rlen = poly_pow_length(flen, exp, len); if (res != poly) { ca_poly_fit_length(res, rlen, ctx); _ca_poly_pow_ui_trunc(res->coeffs, poly->coeffs, flen, exp, rlen, ctx); _ca_poly_set_length(res, rlen, ctx); _ca_poly_normalise(res, ctx); } else { ca_poly_t t; ca_poly_init2(t, rlen, ctx); _ca_poly_pow_ui_trunc(t->coeffs, poly->coeffs, flen, exp, rlen, ctx); _ca_poly_set_length(t, rlen, ctx); _ca_poly_normalise(t, ctx); ca_poly_swap(res, t, ctx); ca_poly_clear(t, ctx); } } } flint-3.1.3/src/ca_poly/print.c000066400000000000000000000020231461254215100163450ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_print(const ca_poly_t poly, ca_ctx_t ctx) { slong i, len; len = poly->length; flint_printf("ca_poly of length %wd:\n", len); for (i = 0; i < len; i++) { flint_printf(" "); ca_print(poly->coeffs + i, ctx); flint_printf("\n"); } flint_printf("\n"); } void ca_poly_printn(const ca_poly_t poly, slong digits, ca_ctx_t ctx) { slong len, i; len = poly->length; flint_printf("["); for (i = 0; i < len; i++) { ca_printn(poly->coeffs + i, digits, ctx); if (i < len - 1) flint_printf(", "); } flint_printf("]\n"); } flint-3.1.3/src/ca_poly/randtest.c000066400000000000000000000020701461254215100170370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_randtest(ca_poly_t poly, flint_rand_t state, slong len, slong depth, slong bits, ca_ctx_t ctx) { slong i; ca_poly_fit_length(poly, len, ctx); for (i = 0; i < len; i++) ca_randtest(poly->coeffs + i, state, depth, bits, ctx); _ca_poly_set_length(poly, len, ctx); _ca_poly_normalise(poly, ctx); } void ca_poly_randtest_rational(ca_poly_t poly, flint_rand_t state, slong len, slong bits, ca_ctx_t ctx) { slong i; ca_poly_fit_length(poly, len, ctx); for (i = 0; i < len; i++) ca_randtest_rational(poly->coeffs + i, state, bits, ctx); _ca_poly_set_length(poly, len, ctx); _ca_poly_normalise(poly, ctx); } flint-3.1.3/src/ca_poly/reverse.c000066400000000000000000000025351461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_reverse(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx) { if (res == poly) { slong i; for (i = 0; i < n / 2; i++) { ca_struct t = res[i]; res[i] = res[n - 1 - i]; res[n - 1 - i] = t; } for (i = 0; i < n - len; i++) ca_zero(res + i, ctx); } else { slong i; for (i = 0; i < n - len; i++) ca_zero(res + i, ctx); for (i = 0; i < len; i++) ca_set(res + (n - len) + i, poly + (len - 1) - i, ctx); } } void ca_poly_reverse(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx) { slong len = FLINT_MIN(n, poly->length); if (len == 0) { ca_poly_zero(res, ctx); return; } ca_poly_fit_length(res, n, ctx); _ca_poly_reverse(res->coeffs, poly->coeffs, len, n, ctx); _ca_poly_set_length(res, n, ctx); _ca_poly_normalise(res, ctx); } flint-3.1.3/src/ca_poly/roots.c000066400000000000000000000156461461254215100163760ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_roots_quadratic(ca_t r1, ca_t r2, const ca_t a, const ca_t b, const ca_t c, ca_ctx_t ctx) { ca_t d, t; ca_init(d, ctx); ca_init(t, ctx); ca_mul(t, a, c, ctx); ca_mul_ui(t, t, 4, ctx); ca_sqr(d, b, ctx); ca_sub(d, d, t, ctx); ca_sqrt(d, d, ctx); ca_inv(t, a, ctx); ca_div_ui(t, t, 2, ctx); ca_sub(r1, d, b, ctx); ca_add(r2, b, d, ctx); ca_neg(r2, r2, ctx); ca_mul(r1, r1, t, ctx); ca_mul(r2, r2, t, ctx); ca_clear(d, ctx); ca_clear(t, ctx); } /* exp(2 pi i * (1 / 3)) */ /* todo: make this faster to construct */ void ca_omega(ca_t res, ca_ctx_t ctx) { ca_pi_i(res, ctx); ca_mul_ui(res, res, 2, ctx); ca_div_ui(res, res, 3, ctx); ca_exp(res, res, ctx); } /* Solves a cubic equation using the cubic formula. Assumes (does not check) that a is invertible. */ int _ca_poly_roots_cubic(ca_t r1, ca_t r2, ca_t r3, const ca_t a, const ca_t b, const ca_t c, const ca_t d, ca_ctx_t ctx) { ca_t D0, D1, C, w1, w2, t; int success; ca_init(D0, ctx); ca_init(D1, ctx); ca_init(C, ctx); ca_init(w1, ctx); ca_init(w2, ctx); ca_init(t, ctx); /* D0 = b^2 - 3*a*c */ ca_sqr(D0, b, ctx); ca_mul(t, a, c, ctx); ca_mul_ui(t, t, 3, ctx); ca_sub(D0, D0, t, ctx); /* D1 = b*(2*b^2 - 9*a*c) + 27*a^2*d */ ca_sqr(D1, b, ctx); ca_mul_ui(D1, D1, 2, ctx); ca_mul(t, a, c, ctx); ca_mul_ui(t, t, 9, ctx); ca_sub(D1, D1, t, ctx); ca_mul(D1, D1, b, ctx); ca_sqr(t, a, ctx); ca_mul(t, t, d, ctx); ca_mul_ui(t, t, 27, ctx); ca_add(D1, D1, t, ctx); ca_sqr(C, D1, ctx); ca_sqr(t, D0, ctx); ca_mul(t, t, D0, ctx); ca_mul_ui(t, t, 4, ctx); ca_sub(C, C, t, ctx); ca_sqrt(C, C, ctx); /* C = (D1 + sqrt(D1^2 - 4*D0^3)) / 2 or (D1 - sqrt(D1^2 - 4*D0^3)) / 2, whichever is nonzero */ success = 1; ca_add(t, D1, C, ctx); if (ca_check_is_zero(t, ctx) == T_FALSE) { ca_swap(C, t, ctx); } else if (ca_check_is_zero(t, ctx) != T_FALSE) { ca_sub(t, D1, C, ctx); if (ca_check_is_zero(t, ctx) == T_FALSE) ca_swap(C, t, ctx); else success = 0; } if (success) { ca_div_ui(C, C, 2, ctx); /* C = C^(1/3) */ ca_set_ui(t, 1, ctx); ca_div_ui(t, t, 3, ctx); ca_pow(C, C, t, ctx); /* w1 = exp(2 pi i * (1 / 3)) */ /* w2 = exp(2 pi i * (2 / 3)) = w1^2 */ ca_omega(w1, ctx); ca_sqr(w2, w1, ctx); /* r1 = (b + C + D0 / C) / (-3*a) */ /* r2 = (b + w1*C + w2 * D0 / C) / (-3*a) */ /* r3 = (b + w2*C + w1 * D0 / C) / (-3*a) */ ca_div(r1, D0, C, ctx); ca_mul(r2, r1, w2, ctx); ca_mul(r3, r1, w1, ctx); ca_add(r1, r1, C, ctx); ca_mul(t, w1, C, ctx); ca_add(r2, r2, t, ctx); ca_mul(t, w2, C, ctx); ca_add(r3, r3, t, ctx); ca_add(r1, r1, b, ctx); ca_add(r2, r2, b, ctx); ca_add(r3, r3, b, ctx); ca_mul_si(t, a, -3, ctx); ca_inv(t, t, ctx); ca_mul(r1, r1, t, ctx); ca_mul(r2, r2, t, ctx); ca_mul(r3, r3, t, ctx); } else { ca_unknown(r1, ctx); ca_unknown(r2, ctx); ca_unknown(r3, ctx); } ca_clear(D0, ctx); ca_clear(D1, ctx); ca_clear(C, ctx); ca_clear(w1, ctx); ca_clear(w2, ctx); ca_clear(t, ctx); return success; } int _ca_poly_roots(ca_ptr roots, ca_srcptr poly, slong len, ca_ctx_t ctx) { slong deg; truth_t leading_zero; if (len == 0) return 0; deg = len - 1; leading_zero = ca_check_is_zero(poly + deg, ctx); if (leading_zero != T_FALSE) return 0; while (deg > 1 && ca_check_is_zero(poly, ctx) == T_TRUE) { ca_zero(roots, ctx); roots++; poly++; len--; deg--; } if (deg == 0) return 1; if (deg == 1) { ca_div(roots, poly, poly + 1, ctx); ca_neg(roots, roots, ctx); return 1; } if (_ca_vec_is_fmpq_vec(poly, len, ctx)) { fmpz_poly_t f; qqbar_ptr r; slong i; f->coeffs = _fmpz_vec_init(len); f->length = f->alloc = len; r = _qqbar_vec_init(len - 1); if (_ca_vec_fmpq_vec_is_fmpz_vec(poly, len, ctx)) { for (i = 0; i < len; i++) fmpz_set(f->coeffs + i, CA_FMPQ_NUMREF(poly + i)); } else { fmpz_t t; fmpz_init(t); fmpz_one(t); for (i = 0; i < len; i++) fmpz_lcm(t, t, CA_FMPQ_DENREF(poly + i)); for (i = 0; i < len; i++) { fmpz_divexact(f->coeffs + i, t, CA_FMPQ_DENREF(poly + i)); fmpz_mul(f->coeffs + i, f->coeffs + i, CA_FMPQ_NUMREF(poly + i)); } fmpz_clear(t); } qqbar_roots_fmpz_poly(r, f, 0); for (i = 0; i < deg; i++) ca_set_qqbar(roots + i, r + i, ctx); _fmpz_vec_clear(f->coeffs, len); _qqbar_vec_clear(r, len - 1); return 1; } if (deg == 2) { _ca_poly_roots_quadratic(roots, roots + 1, poly + 2, poly + 1, poly + 0, ctx); return 1; } if (deg == 3) { return _ca_poly_roots_cubic(roots, roots + 1, roots + 2, poly + 3, poly + 2, poly + 1, poly + 0, ctx); } return 0; } int ca_poly_roots(ca_vec_t roots, ulong * exp, const ca_poly_t poly, ca_ctx_t ctx) { ca_poly_vec_t fac; ca_t c; slong i, j, num_roots, factor_deg; int success; ulong * fac_exp; if (poly->length == 0) return 0; ca_poly_vec_init(fac, 0, ctx); ca_init(c, ctx); fac_exp = flint_malloc(sizeof(ulong) * poly->length); success = ca_poly_factor_squarefree(c, fac, fac_exp, poly, ctx); if (success) { num_roots = 0; for (i = 0; i < fac->length; i++) num_roots += (fac->entries + i)->length - 1; ca_vec_set_length(roots, num_roots, ctx); num_roots = 0; for (i = 0; success && i < fac->length; i++) { factor_deg = (fac->entries + i)->length - 1; success = _ca_poly_roots(roots->entries + num_roots, (fac->entries + i)->coeffs, (fac->entries + i)->length, ctx); for (j = 0; j < factor_deg; j++) exp[num_roots + j] = fac_exp[i]; num_roots += factor_deg; } } ca_poly_vec_clear(fac, ctx); ca_clear(c, ctx); flint_free(fac_exp); return success; } flint-3.1.3/src/ca_poly/set.c000066400000000000000000000011701461254215100160060ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_set(ca_poly_t res, const ca_poly_t src, ca_ctx_t ctx) { ca_poly_fit_length(res, src->length, ctx); _ca_vec_set(res->coeffs, src->coeffs, src->length, ctx); _ca_poly_set_length(res, src->length, ctx); } flint-3.1.3/src/ca_poly/set_ca.c000066400000000000000000000013021461254215100164460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_set_ca(ca_poly_t poly, const ca_t x, ca_ctx_t ctx) { if (ca_check_is_zero(x, ctx) == T_TRUE) { ca_poly_zero(poly, ctx); } else { ca_poly_fit_length(poly, 1, ctx); ca_set(poly->coeffs, x, ctx); _ca_poly_set_length(poly, 1, ctx); } } flint-3.1.3/src/ca_poly/set_coeff_ca.c000066400000000000000000000013571461254215100176220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_set_coeff_ca(ca_poly_t poly, slong n, const ca_t x, ca_ctx_t ctx) { ca_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { _ca_vec_zero(poly->coeffs + poly->length, n - poly->length, ctx); poly->length = n + 1; } ca_set(poly->coeffs + n, x, ctx); _ca_poly_normalise(poly, ctx); } flint-3.1.3/src/ca_poly/set_fmpq_poly.c000066400000000000000000000017401461254215100200770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_set_fmpq_poly(ca_poly_t res, const fmpq_poly_t src, ca_ctx_t ctx) { slong i; ca_poly_fit_length(res, src->length, ctx); if (fmpz_is_one(fmpq_poly_denref(src))) { for (i = 0; i < src->length; i++) ca_set_fmpz(res->coeffs + i, src->coeffs + i, ctx); } else { for (i = 0; i < src->length; i++) { ca_set_fmpz(res->coeffs + i, src->coeffs + i, ctx); ca_div_fmpz(res->coeffs + i, res->coeffs + i, fmpq_poly_denref(src), ctx); } } _ca_poly_set_length(res, src->length, ctx); } flint-3.1.3/src/ca_poly/set_fmpz_poly.c000066400000000000000000000012661461254215100201130ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_set_fmpz_poly(ca_poly_t res, const fmpz_poly_t src, ca_ctx_t ctx) { slong i; ca_poly_fit_length(res, src->length, ctx); for (i = 0; i < src->length; i++) ca_set_fmpz(res->coeffs + i, src->coeffs + i, ctx); _ca_poly_set_length(res, src->length, ctx); } flint-3.1.3/src/ca_poly/set_length.c000066400000000000000000000012031461254215100173440ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_set_length(ca_poly_t poly, slong len, ca_ctx_t ctx) { slong i; if (poly->length > len) { for (i = len; i < poly->length; i++) ca_zero(poly->coeffs + i, ctx); } poly->length = len; } flint-3.1.3/src/ca_poly/set_roots.c000066400000000000000000000047631461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_set_roots(ca_ptr poly, ca_srcptr xs, const ulong * exp, slong n, ca_ctx_t ctx) { if (n == 0 || (n == 1 && exp[0] == 0)) { ca_one(poly, ctx); } else if (n == 1) { if (exp[0] == 1) { ca_neg(poly, xs, ctx); ca_one(poly + 1, ctx); } else if (exp[0] == 2) { ca_sqr(poly, xs, ctx); ca_mul_si(poly + 1, xs, -2, ctx); ca_one(poly + 2, ctx); } else { slong i, e; e = exp[0]; ca_one(poly + e, ctx); for (i = e - 1; i >= 0; i--) { ca_mul(poly + i, poly + i + 1, xs, ctx); ca_mul_si(poly + i, poly + i, -(i + 1), ctx); ca_div_ui(poly + i, poly + i, e - i, ctx); } } } else if (n == 2 && exp[0] == 1 && exp[1] == 1) { ca_mul(poly, xs + 0, xs + 1, ctx); ca_add(poly + 1, xs + 0, xs + 1, ctx); ca_neg(poly + 1, poly + 1, ctx); ca_one(poly + 2, ctx); } else { slong i, m, deg_left, deg_right; ca_ptr tmp; /* todo: balance degrees */ m = (n + 1) / 2; deg_left = deg_right = 0; for (i = 0; i < m; i++) deg_left += exp[i]; for (i = m; i < n; i++) deg_right += exp[i]; tmp = _ca_vec_init(deg_left + deg_right + 2, ctx); _ca_poly_set_roots(tmp, xs, exp, m, ctx); _ca_poly_set_roots(tmp + deg_left + 1, xs + m, exp + m, n - m, ctx); _ca_poly_mul(poly, tmp, deg_left + 1, tmp + deg_left + 1, deg_right + 1, ctx); _ca_vec_clear(tmp, deg_left + deg_right + 2, ctx); } } void ca_poly_set_roots(ca_poly_t poly, ca_vec_t roots, const ulong * exp, ca_ctx_t ctx) { slong i, deg, len; len = ca_vec_length(roots, ctx); /* todo: check for overflow? */ deg = 0; for (i = 0; i < len; i++) deg += exp[i]; ca_poly_fit_length(poly, deg + 1, ctx); _ca_poly_set_roots(poly->coeffs, roots->entries, exp, len, ctx); _ca_poly_set_length(poly, deg + 1, ctx); } flint-3.1.3/src/ca_poly/set_si.c000066400000000000000000000012441461254215100165030ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_set_si(ca_poly_t poly, slong x, ca_ctx_t ctx) { if (x == 0) { ca_poly_zero(poly, ctx); } else { ca_poly_fit_length(poly, 1, ctx); ca_set_si(poly->coeffs, x, ctx); _ca_poly_set_length(poly, 1, ctx); } } flint-3.1.3/src/ca_poly/shift_left.c000066400000000000000000000024071461254215100173460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_shift_left(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx) { slong i; /* Copy in reverse to avoid writing over unshifted coefficients */ if (res != poly) { for (i = len; i--; ) ca_set(res + n + i, poly + i, ctx); } else { for (i = len; i--; ) ca_swap(res + n + i, res + i, ctx); } for (i = 0; i < n; i++) ca_zero(res + i, ctx); } void ca_poly_shift_left(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx) { if (n == 0) { ca_poly_set(res, poly, ctx); return; } if (poly->length == 0) { ca_poly_zero(res, ctx); return; } ca_poly_fit_length(res, poly->length + n, ctx); _ca_poly_shift_left(res->coeffs, poly->coeffs, poly->length, n, ctx); _ca_poly_set_length(res, poly->length + n, ctx); } flint-3.1.3/src/ca_poly/shift_right.c000066400000000000000000000023471461254215100175340ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_shift_right(ca_ptr res, ca_srcptr poly, slong len, slong n, ca_ctx_t ctx) { slong i; /* Copy in forward order to avoid writing over unshifted coefficients */ if (res != poly) { for (i = 0; i < len - n; i++) ca_set(res + i, poly + n + i, ctx); } else { for (i = 0; i < len - n; i++) ca_swap(res + i, res + n + i, ctx); } } void ca_poly_shift_right(ca_poly_t res, const ca_poly_t poly, slong n, ca_ctx_t ctx) { if (n == 0) { ca_poly_set(res, poly, ctx); return; } if (poly->length <= n) { ca_poly_zero(res, ctx); return; } ca_poly_fit_length(res, poly->length - n, ctx); _ca_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n, ctx); _ca_poly_set_length(res, poly->length - n, ctx); } flint-3.1.3/src/ca_poly/squarefree_part.c000066400000000000000000000022221461254215100204020ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" int ca_poly_squarefree_part(ca_poly_t res, const ca_poly_t poly, ca_ctx_t ctx) { ca_poly_t t; int success; if (poly->length <= 1) { ca_poly_one(res, ctx); return 1; } if (poly->length == 2) return ca_poly_make_monic(res, poly, ctx); ca_poly_init(t, ctx); ca_poly_derivative(t, poly, ctx); success = ca_poly_gcd(t, poly, t, ctx); if (success) { if (t->length == 1) /* gcd = 1 */ { success = ca_poly_make_monic(res, poly, ctx); } else { success = ca_poly_div(res, poly, t, ctx); if (success) success = ca_poly_make_monic(res, res, ctx); } } ca_poly_clear(t, ctx); return success; } flint-3.1.3/src/ca_poly/sub.c000066400000000000000000000022451461254215100160100ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_sub(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, ca_ctx_t ctx) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) ca_sub(res + i, poly1 + i, poly2 + i, ctx); for (i = min; i < len1; i++) ca_set(res + i, poly1 + i, ctx); for (i = min; i < len2; i++) ca_neg(res + i, poly2 + i, ctx); } void ca_poly_sub(ca_poly_t res, const ca_poly_t poly1, const ca_poly_t poly2, ca_ctx_t ctx) { slong max = FLINT_MAX(poly1->length, poly2->length); ca_poly_fit_length(res, max, ctx); _ca_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _ca_poly_set_length(res, max, ctx); _ca_poly_normalise(res, ctx); } flint-3.1.3/src/ca_poly/test/000077500000000000000000000000001461254215100160275ustar00rootroot00000000000000flint-3.1.3/src/ca_poly/test/main.c000066400000000000000000000031741461254215100171240ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-compose.c" #include "t-divrem.c" #include "t-div_series.c" #include "t-evaluate.c" #include "t-evaluate_horner.c" #include "t-exp_series.c" #include "t-factor_squarefree.c" #include "t-gcd.c" #include "t-gcd_euclidean.c" #include "t-inv_series.c" #include "t-log_series.c" #include "t-mul.c" #include "t-pow_ui.c" #include "t-roots.c" #include "t-squarefree_part.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(ca_poly_compose), TEST_FUNCTION(ca_poly_divrem), TEST_FUNCTION(ca_poly_div_series), TEST_FUNCTION(ca_poly_evaluate), TEST_FUNCTION(ca_poly_evaluate_horner), TEST_FUNCTION(ca_poly_exp_series), TEST_FUNCTION(ca_poly_factor_squarefree), TEST_FUNCTION(ca_poly_gcd), TEST_FUNCTION(ca_poly_gcd_euclidean), TEST_FUNCTION(ca_poly_inv_series), TEST_FUNCTION(ca_poly_log_series), TEST_FUNCTION(ca_poly_mul), TEST_FUNCTION(ca_poly_pow_ui), TEST_FUNCTION(ca_poly_roots), TEST_FUNCTION(ca_poly_squarefree_part) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/ca_poly/test/t-compose.c000066400000000000000000000043761461254215100201130ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_compose, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t F, G, FG; ca_poly_t x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ ca_ctx_init(ctx); ca_poly_init(F, ctx); ca_poly_init(G, ctx); ca_poly_init(FG, ctx); ca_poly_init(x, ctx); ca_poly_init(Fx, ctx); ca_poly_init(Gx, ctx); ca_poly_init(FxGx, ctx); ca_poly_init(FGx, ctx); ca_poly_randtest(F, state, 6, 1, 5, ctx); ca_poly_randtest(G, state, 6, 1, 5, ctx); ca_poly_randtest(x, state, 4, 1, 5, ctx); ca_poly_randtest(Fx, state, 4, 1, 5, ctx); ca_poly_add(FG, F, G, ctx); ca_poly_compose(Fx, F, x, ctx); ca_poly_set(Gx, x, ctx); /* test aliasing */ ca_poly_compose(Gx, G, Gx, ctx); ca_poly_add(FxGx, Fx, Gx, ctx); ca_poly_compose(FGx, FG, x, ctx); if (ca_poly_check_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); ca_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); ca_poly_print(x, ctx); flint_printf("\n"); flint_printf("FxGx = "); ca_poly_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); ca_poly_print(FGx, ctx); flint_printf("\n"); flint_abort(); } ca_poly_clear(F, ctx); ca_poly_clear(G, ctx); ca_poly_clear(FG, ctx); ca_poly_clear(x, ctx); ca_poly_clear(Fx, ctx); ca_poly_clear(Gx, ctx); ca_poly_clear(FxGx, ctx); ca_poly_clear(FGx, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-div_series.c000066400000000000000000000104741461254215100205760ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-mul.c */ #ifndef ca_poly_randtest_same_nf #define ca_poly_randtest_same_nf ca_poly_randtest_same_nf void ca_poly_randtest_same_nf(ca_poly_t res, flint_rand_t state, const ca_t x, slong len, slong bits, slong den_bits, ca_ctx_t ctx) { slong i; fmpz_t t; ca_poly_fit_length(res, len, ctx); for (i = 0; i < len; i++) ca_randtest_same_nf(res->coeffs + i, state, x, bits, 1, ctx); _ca_poly_set_length(res, len, ctx); _ca_poly_normalise(res, ctx); fmpz_init(t); fmpz_randtest_not_zero(t, state, den_bits); ca_poly_div_fmpz(res, res, t, ctx); fmpz_clear(t); } #endif /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-log_series.c */ #ifndef ca_poly_truncate #define ca_poly_truncate ca_poly_truncate /* todo */ void ca_poly_truncate(ca_poly_t poly, slong newlen, ca_ctx_t ctx) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) ca_zero(poly->coeffs + i, ctx); poly->length = newlen; _ca_poly_normalise(poly, ctx); } } #endif TEST_FUNCTION_START(ca_poly_div_series, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, AB, ABB, An; slong n1; /* Test (A / B) * B == A */ ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(AB, ctx); ca_poly_init(ABB, ctx); ca_poly_init(An, ctx); if (n_randint(state, 2)) { if (n_randint(state, 2)) ca_poly_randtest_rational(A, state, 10, 10, ctx); else ca_poly_randtest(A, state, 4, 2, 10, ctx); if (n_randint(state, 2)) ca_poly_randtest_rational(B, state, 10, 10, ctx); else ca_poly_randtest(B, state, 4, 2, 10, ctx); n1 = n_randint(state, 6); } else { qqbar_t t; ca_t x; qqbar_init(t); ca_init(x, ctx); qqbar_randtest(t, state, 8, 10); ca_set_qqbar(x, t, ctx); ca_poly_randtest_same_nf(A, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); ca_poly_randtest_same_nf(B, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); n1 = n_randint(state, 50); qqbar_clear(t); ca_clear(x, ctx); } ca_poly_randtest(AB, state, 4, 2, 10, ctx); if (n_randint(state, 2)) { ca_poly_set(AB, A, ctx); ca_poly_div_series(AB, AB, B, n1, ctx); } else if (n_randint(state, 2)) { ca_poly_set(AB, B, ctx); ca_poly_div_series(AB, A, AB, n1, ctx); } else { ca_poly_div_series(AB, A, B, n1, ctx); } ca_poly_mullow(ABB, AB, B, n1, ctx); ca_poly_set(An, A, ctx); ca_poly_truncate(An, n1, ctx); if (!(B->length == 0 || ca_check_is_zero(B->coeffs, ctx) != T_FALSE)) { if (ca_poly_check_equal(ABB, An, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); ca_poly_print(AB, ctx); flint_printf("\n"); flint_printf("ABB = "); ca_poly_print(ABB, ctx); flint_printf("\n"); flint_abort(); } } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(AB, ctx); ca_poly_clear(ABB, ctx); ca_poly_clear(An, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-divrem.c000066400000000000000000000053321461254215100177250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_divrem, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, Q, R, T; int success; /* Test A = Q*B + R */ ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(Q, ctx); ca_poly_init(R, ctx); ca_poly_init(T, ctx); ca_poly_randtest(A, state, 4, 2, 10, ctx); ca_poly_randtest(B, state, 4, 2, 10, ctx); ca_poly_randtest(Q, state, 4, 2, 10, ctx); ca_poly_randtest(R, state, 4, 2, 10, ctx); ca_poly_randtest(T, state, 4, 2, 10, ctx); /* test aliasing */ switch (n_randint(state, 5)) { case 0: ca_poly_set(Q, A, ctx); success = ca_poly_divrem(Q, R, Q, B, ctx); break; case 1: ca_poly_set(R, A, ctx); success = ca_poly_divrem(Q, R, R, B, ctx); break; case 2: ca_poly_set(Q, B, ctx); success = ca_poly_divrem(Q, R, A, Q, ctx); break; case 3: ca_poly_set(R, B, ctx); success = ca_poly_divrem(Q, R, A, R, ctx); break; default: success = ca_poly_divrem(Q, R, A, B, ctx); break; } if (success) { ca_poly_mul(T, Q, B, ctx); ca_poly_add(T, T, R, ctx); if (ca_poly_check_equal(A, T, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); ca_poly_print(Q, ctx); flint_printf("\n"); flint_printf("R = "); ca_poly_print(R, ctx); flint_printf("\n"); flint_printf("T = "); ca_poly_print(T, ctx); flint_printf("\n"); flint_abort(); } } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(Q, ctx); ca_poly_clear(R, ctx); ca_poly_clear(T, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-evaluate.c000066400000000000000000000042351461254215100202460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_evaluate, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t F, G, FG; ca_t x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ ca_ctx_init(ctx); ca_poly_init(F, ctx); ca_poly_init(G, ctx); ca_poly_init(FG, ctx); ca_init(x, ctx); ca_init(Fx, ctx); ca_init(Gx, ctx); ca_init(FxGx, ctx); ca_init(FGx, ctx); ca_poly_randtest(F, state, 8, 1, 5, ctx); ca_poly_randtest(G, state, 8, 1, 5, ctx); ca_randtest(x, state, 1, 5, ctx); ca_randtest(Fx, state, 1, 5, ctx); ca_poly_add(FG, F, G, ctx); ca_poly_evaluate(Fx, F, x, ctx); ca_set(Gx, x, ctx); /* test aliasing */ ca_poly_evaluate(Gx, G, Gx, ctx); ca_add(FxGx, Fx, Gx, ctx); ca_poly_evaluate(FGx, FG, x, ctx); if (ca_check_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); ca_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n"); flint_printf("FxGx = "); ca_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); ca_print(FGx, ctx); flint_printf("\n"); flint_abort(); } ca_poly_clear(F, ctx); ca_poly_clear(G, ctx); ca_poly_clear(FG, ctx); ca_clear(x, ctx); ca_clear(Fx, ctx); ca_clear(Gx, ctx); ca_clear(FxGx, ctx); ca_clear(FGx, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-evaluate_horner.c000066400000000000000000000042711461254215100216230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_evaluate_horner, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t F, G, FG; ca_t x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ ca_ctx_init(ctx); ca_poly_init(F, ctx); ca_poly_init(G, ctx); ca_poly_init(FG, ctx); ca_init(x, ctx); ca_init(Fx, ctx); ca_init(Gx, ctx); ca_init(FxGx, ctx); ca_init(FGx, ctx); ca_poly_randtest(F, state, 8, 1, 5, ctx); ca_poly_randtest(G, state, 8, 1, 5, ctx); ca_randtest(x, state, 1, 5, ctx); ca_randtest(Fx, state, 1, 5, ctx); ca_poly_add(FG, F, G, ctx); ca_poly_evaluate_horner(Fx, F, x, ctx); ca_set(Gx, x, ctx); /* test aliasing */ ca_poly_evaluate_horner(Gx, G, Gx, ctx); ca_add(FxGx, Fx, Gx, ctx); ca_poly_evaluate_horner(FGx, FG, x, ctx); if (ca_check_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); ca_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); ca_print(x, ctx); flint_printf("\n"); flint_printf("FxGx = "); ca_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); ca_print(FGx, ctx); flint_printf("\n"); flint_abort(); } ca_poly_clear(F, ctx); ca_poly_clear(G, ctx); ca_poly_clear(FG, ctx); ca_clear(x, ctx); ca_clear(Fx, ctx); ca_clear(Gx, ctx); ca_clear(FxGx, ctx); ca_clear(FGx, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-exp_series.c000066400000000000000000000103741461254215100206070ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-mul.c */ #ifndef ca_poly_randtest_same_nf #define ca_poly_randtest_same_nf ca_poly_randtest_same_nf void ca_poly_randtest_same_nf(ca_poly_t res, flint_rand_t state, const ca_t x, slong len, slong bits, slong den_bits, ca_ctx_t ctx) { slong i; fmpz_t t; ca_poly_fit_length(res, len, ctx); for (i = 0; i < len; i++) ca_randtest_same_nf(res->coeffs + i, state, x, bits, 1, ctx); _ca_poly_set_length(res, len, ctx); _ca_poly_normalise(res, ctx); fmpz_init(t); fmpz_randtest_not_zero(t, state, den_bits); ca_poly_div_fmpz(res, res, t, ctx); fmpz_clear(t); } #endif /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-log_series.c */ #ifndef ca_poly_truncate #define ca_poly_truncate ca_poly_truncate /* todo */ void ca_poly_truncate(ca_poly_t poly, slong newlen, ca_ctx_t ctx) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) ca_zero(poly->coeffs + i, ctx); poly->length = newlen; _ca_poly_normalise(poly, ctx); } } #endif TEST_FUNCTION_START(ca_poly_exp_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, AB, expA, expB, expAB, expAexpB; slong n1, n2, n3; /* Test exp(A)*exp(B) = exp(A+B) */ ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(AB, ctx); ca_poly_init(expA, ctx); ca_poly_init(expB, ctx); ca_poly_init(expAB, ctx); ca_poly_init(expAexpB, ctx); if (n_randint(state, 2)) { ca_poly_randtest(A, state, 4, 2, 10, ctx); ca_poly_randtest(B, state, 4, 2, 10, ctx); n1 = n_randint(state, 6); n2 = n_randint(state, 6); n3 = n_randint(state, 6); } else { qqbar_t t; ca_t x; qqbar_init(t); ca_init(x, ctx); qqbar_randtest(t, state, 8, 10); ca_set_qqbar(x, t, ctx); ca_poly_randtest_same_nf(A, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); ca_poly_randtest_same_nf(B, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); n1 = n_randint(state, 50); n2 = n_randint(state, 50); n3 = n_randint(state, 50); qqbar_clear(t); ca_clear(x, ctx); } ca_poly_randtest(expA, state, 4, 2, 10, ctx); ca_poly_randtest(expB, state, 4, 2, 10, ctx); ca_poly_randtest(expAB, state, 4, 2, 10, ctx); ca_poly_add(AB, A, B, ctx); ca_poly_exp_series(expA, A, n1, ctx); ca_poly_exp_series(expB, B, n2, ctx); ca_poly_exp_series(expAB, AB, n3, ctx); ca_poly_mullow(expAexpB, expA, expB, FLINT_MIN(FLINT_MIN(n1, n2), n3), ctx); ca_poly_truncate(expAB, FLINT_MIN(FLINT_MIN(n1, n2), n3), ctx); if (ca_poly_check_equal(expAB, expAexpB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("expAexpB = "); ca_poly_print(expAexpB, ctx); flint_printf("\n"); flint_printf("expAB = "); ca_poly_print(expAB, ctx); flint_printf("\n"); flint_abort(); } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(AB, ctx); ca_poly_clear(expA, ctx); ca_poly_clear(expB, ctx); ca_poly_clear(expAB, ctx); ca_poly_clear(expAexpB, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-factor_squarefree.c000066400000000000000000000102031461254215100221300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_factor_squarefree, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, C, P, Q, G1, G2, G3; ca_t c; ca_poly_vec_t F; int success; ulong ea, eb, ec, maxexp; ulong * exp; slong i, j; ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(C, ctx); ca_poly_init(G1, ctx); ca_poly_init(G2, ctx); ca_poly_init(G3, ctx); ca_poly_init(P, ctx); ca_poly_init(Q, ctx); ca_poly_vec_init(F, 0, ctx); ca_init(c, ctx); ea = 1 + n_randint(state, 2); eb = 1 + n_randint(state, 2); ec = 1 + n_randint(state, 4); do { if (n_randint(state, 2) == 0) { ca_poly_randtest(A, state, 2, 0, 3, ctx); ca_poly_randtest_rational(B, state, 2, 3, ctx); ca_poly_randtest_rational(C, state, 2, 3, ctx); } else { ca_poly_randtest_rational(A, state, 4, 3, ctx); ca_poly_randtest_rational(B, state, 4, 3, ctx); ca_poly_randtest_rational(C, state, 4, 3, ctx); } } while (A->length < 2 || B->length < 2 || C->length < 2 || !ca_poly_gcd(G1, A, B, ctx) || (ca_poly_check_is_one(G1, ctx) != T_TRUE) || !ca_poly_gcd(G2, A, C, ctx) || (ca_poly_check_is_one(G2, ctx) != T_TRUE) || !ca_poly_gcd(G3, B, C, ctx) || (ca_poly_check_is_one(G3, ctx) != T_TRUE)); ca_poly_one(P, ctx); for (i = 0; i < ea; i++) ca_poly_mul(P, P, A, ctx); for (i = 0; i < eb; i++) ca_poly_mul(P, P, B, ctx); for (i = 0; i < ec; i++) ca_poly_mul(P, P, C, ctx); exp = flint_malloc(sizeof(ulong) * P->length); success = ca_poly_factor_squarefree(c, F, exp, P, ctx); if (success) { ca_poly_one(Q, ctx); for (i = 0; i < F->length; i++) for (j = 0; j < exp[i]; j++) ca_poly_mul(Q, Q, F->entries + i, ctx); ca_poly_mul_ca(Q, Q, c, ctx); maxexp = 0; for (i = 0; i < F->length; i++) maxexp = FLINT_MAX(maxexp, exp[i]); if (ca_poly_check_equal(P, Q, ctx) == T_FALSE || maxexp < FLINT_MAX(FLINT_MAX(ea, eb), ec)) { flint_printf("FAIL (product)\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("ea = %wu\n\n", ea); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("eb = %wu\n\n", eb); flint_printf("C = "); ca_poly_print(C, ctx); flint_printf("\n"); flint_printf("ec = %wu\n\n", ec); flint_printf("P = "); ca_poly_print(P, ctx); flint_printf("\n"); flint_printf("Q = "); ca_poly_print(Q, ctx); flint_printf("\n"); for (i = 0; i < F->length; i++) { flint_printf("Multiplicity %wu: ", exp[i]); ca_poly_print(F->entries + i, ctx); } flint_abort(); } } flint_free(exp); ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(C, ctx); ca_poly_clear(G1, ctx); ca_poly_clear(G2, ctx); ca_poly_clear(G3, ctx); ca_poly_clear(P, ctx); ca_poly_clear(Q, ctx); ca_poly_vec_clear(F, ctx); ca_clear(c, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-gcd.c000066400000000000000000000105221461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_gcd, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, C, AC, BC, MC, G; int success; ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(C, ctx); ca_poly_init(AC, ctx); ca_poly_init(BC, ctx); ca_poly_init(MC, ctx); ca_poly_init(G, ctx); if (n_randint(state, 10) != 0) { do { ca_poly_randtest_rational(A, state, 4, 10, ctx); ca_poly_randtest_rational(B, state, 4, 10, ctx); success = ca_poly_gcd(G, A, B, ctx); } while (!success || ca_poly_check_is_one(G, ctx) != T_TRUE); ca_poly_randtest(C, state, 4, 2, 10, ctx); } else { do { ca_poly_randtest(A, state, 3, 2, 10, ctx); ca_poly_randtest(B, state, 3, 2, 10, ctx); success = ca_poly_gcd(G, A, B, ctx); } while (!success || ca_poly_check_is_one(G, ctx) != T_TRUE); ca_poly_randtest_rational(C, state, 3, 10, ctx); } ca_poly_mul(AC, A, C, ctx); ca_poly_mul(BC, B, C, ctx); switch (n_randint(state, 3)) { case 0: ca_poly_set(G, AC, ctx); success = ca_poly_gcd(G, G, BC, ctx); break; case 1: ca_poly_set(G, BC, ctx); success = ca_poly_gcd(G, AC, G, ctx); break; default: success = ca_poly_gcd(G, AC, BC, ctx); break; } if (success) { ca_poly_make_monic(MC, C, ctx); if (ca_poly_check_equal(MC, G, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } ca_poly_randtest(A, state, 3, 2, 10, ctx); success = ca_poly_gcd(G, A, A, ctx); if (success) { ca_poly_make_monic(B, A, ctx); if (ca_poly_check_equal(G, B, ctx) == T_FALSE) { flint_printf("FAIL (self)\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } /* compare with gcd_euclidean */ ca_poly_randtest(A, state, 3, 0, 5, ctx); ca_poly_randtest_rational(B, state, 3, 5, ctx); ca_poly_randtest_rational(C, state, 3, 5, ctx); ca_poly_mul(A, A, C, ctx); ca_poly_mul(B, B, C, ctx); if (ca_poly_gcd(G, A, B, ctx) && ca_poly_gcd_euclidean(C, A, B, ctx) && ca_poly_check_equal(G, C, ctx) == T_FALSE) { flint_printf("FAIL (2)\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_printf("C = "); ca_poly_print(C, ctx); flint_printf("\n"); flint_abort(); } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(C, ctx); ca_poly_clear(AC, ctx); ca_poly_clear(BC, ctx); ca_poly_clear(MC, ctx); ca_poly_clear(G, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-gcd_euclidean.c000066400000000000000000000071611461254215100212070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_gcd_euclidean, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, C, AC, BC, MC, G; int success; ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(C, ctx); ca_poly_init(AC, ctx); ca_poly_init(BC, ctx); ca_poly_init(MC, ctx); ca_poly_init(G, ctx); if (n_randint(state, 10) != 0) { do { ca_poly_randtest_rational(A, state, 4, 10, ctx); ca_poly_randtest_rational(B, state, 4, 10, ctx); success = ca_poly_gcd_euclidean(G, A, B, ctx); } while (!success || ca_poly_check_is_one(G, ctx) != T_TRUE); ca_poly_randtest(C, state, 4, 2, 10, ctx); } else { do { ca_poly_randtest(A, state, 3, 2, 10, ctx); ca_poly_randtest(B, state, 3, 2, 10, ctx); success = ca_poly_gcd_euclidean(G, A, B, ctx); } while (!success || ca_poly_check_is_one(G, ctx) != T_TRUE); ca_poly_randtest_rational(C, state, 3, 10, ctx); } ca_poly_mul(AC, A, C, ctx); ca_poly_mul(BC, B, C, ctx); switch (n_randint(state, 3)) { case 0: ca_poly_set(G, AC, ctx); success = ca_poly_gcd_euclidean(G, G, BC, ctx); break; case 1: ca_poly_set(G, BC, ctx); success = ca_poly_gcd_euclidean(G, AC, G, ctx); break; default: success = ca_poly_gcd_euclidean(G, AC, BC, ctx); break; } if (success) { ca_poly_make_monic(MC, C, ctx); if (ca_poly_check_equal(MC, G, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } ca_poly_randtest(A, state, 3, 2, 10, ctx); success = ca_poly_gcd_euclidean(G, A, A, ctx); if (success) { ca_poly_make_monic(B, A, ctx); if (ca_poly_check_equal(G, B, ctx) == T_FALSE) { flint_printf("FAIL (self)\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); ca_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(C, ctx); ca_poly_clear(AC, ctx); ca_poly_clear(BC, ctx); ca_poly_clear(MC, ctx); ca_poly_clear(G, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-inv_series.c000066400000000000000000000071111461254215100206020ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-mul.c */ #ifndef ca_poly_randtest_same_nf #define ca_poly_randtest_same_nf ca_poly_randtest_same_nf void ca_poly_randtest_same_nf(ca_poly_t res, flint_rand_t state, const ca_t x, slong len, slong bits, slong den_bits, ca_ctx_t ctx) { slong i; fmpz_t t; ca_poly_fit_length(res, len, ctx); for (i = 0; i < len; i++) ca_randtest_same_nf(res->coeffs + i, state, x, bits, 1, ctx); _ca_poly_set_length(res, len, ctx); _ca_poly_normalise(res, ctx); fmpz_init(t); fmpz_randtest_not_zero(t, state, den_bits); ca_poly_div_fmpz(res, res, t, ctx); fmpz_clear(t); } #endif /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-log_series.c */ #ifndef ca_poly_truncate #define ca_poly_truncate ca_poly_truncate /* todo */ void ca_poly_truncate(ca_poly_t poly, slong newlen, ca_ctx_t ctx) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) ca_zero(poly->coeffs + i, ctx); poly->length = newlen; _ca_poly_normalise(poly, ctx); } } #endif TEST_FUNCTION_START(ca_poly_inv_series, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, AB, one; slong n1; /* Test inv(A) * A == 1 */ ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(AB, ctx); ca_poly_init(one, ctx); if (n_randint(state, 2)) { ca_poly_randtest(A, state, 4, 2, 10, ctx); n1 = n_randint(state, 6); } else { qqbar_t t; ca_t x; qqbar_init(t); ca_init(x, ctx); qqbar_randtest(t, state, 8, 10); ca_set_qqbar(x, t, ctx); ca_poly_randtest_same_nf(A, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); n1 = n_randint(state, 50); qqbar_clear(t); ca_clear(x, ctx); } ca_poly_randtest(B, state, 4, 2, 10, ctx); if (n_randint(state, 2)) { ca_poly_set(B, A, ctx); ca_poly_inv_series(B, B, n1, ctx); } else { ca_poly_inv_series(B, A, n1, ctx); } ca_poly_mullow(AB, A, B, n1, ctx); ca_poly_one(one, ctx); ca_poly_truncate(one, n1, ctx); if (!(A->length == 0 || ca_check_is_zero(A->coeffs, ctx) != T_FALSE)) { if (ca_poly_check_equal(AB, one, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); ca_poly_print(AB, ctx); flint_printf("\n"); flint_abort(); } } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(AB, ctx); ca_poly_clear(one, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-log_series.c000066400000000000000000000046761461254215100206040ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-log_series.c */ #ifndef ca_poly_truncate #define ca_poly_truncate ca_poly_truncate /* todo */ void ca_poly_truncate(ca_poly_t poly, slong newlen, ca_ctx_t ctx) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) ca_zero(poly->coeffs + i, ctx); poly->length = newlen; _ca_poly_normalise(poly, ctx); } } #endif TEST_FUNCTION_START(ca_poly_log_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, C, D; slong n1; /* Test exp(log(A)) == A */ ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(C, ctx); ca_poly_init(D, ctx); ca_poly_randtest_rational(A, state, 10, 10, ctx); n1 = n_randint(state, 10); if (n_randint(state, 2)) { ca_poly_log_series(B, A, n1, ctx); } else { ca_poly_set(B, A, ctx); ca_poly_log_series(B, B, n1, ctx); } ca_poly_exp_series(C, B, n1, ctx); ca_poly_set(D, A, ctx); ca_poly_truncate(D, n1, ctx); if (!(A->length == 0 || ca_check_is_zero(A->coeffs, ctx) != T_FALSE)) { if (ca_poly_check_equal(C, D, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_poly_print(C, ctx); flint_printf("\n"); flint_printf("D = "); ca_poly_print(D, ctx); flint_printf("\n"); flint_abort(); } } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(C, ctx); ca_poly_clear(D, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-mul.c000066400000000000000000000104041461254215100172300ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" /* Defined in t-div_series.c, t-exp_series.c, t-inv_series.c, t-mul.c */ #ifndef ca_poly_randtest_same_nf #define ca_poly_randtest_same_nf ca_poly_randtest_same_nf void ca_poly_randtest_same_nf(ca_poly_t res, flint_rand_t state, const ca_t x, slong len, slong bits, slong den_bits, ca_ctx_t ctx) { slong i; fmpz_t t; ca_poly_fit_length(res, len, ctx); for (i = 0; i < len; i++) ca_randtest_same_nf(res->coeffs + i, state, x, bits, 1, ctx); _ca_poly_set_length(res, len, ctx); _ca_poly_normalise(res, ctx); fmpz_init(t); fmpz_randtest_not_zero(t, state, den_bits); ca_poly_div_fmpz(res, res, t, ctx); fmpz_clear(t); } #endif TEST_FUNCTION_START(ca_poly_mul, state) { slong iter; for (iter = 0; iter < 300 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, C, ABC, AB, AC, ABAC; /* Test A*(B+C) = A*B + A*C */ ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(C, ctx); ca_poly_init(ABC, ctx); ca_poly_init(AB, ctx); ca_poly_init(AC, ctx); ca_poly_init(ABAC, ctx); if (n_randint(state, 2)) { ca_poly_randtest(A, state, 4, 2, 10, ctx); ca_poly_randtest(B, state, 4, 2, 10, ctx); ca_poly_randtest(C, state, 4, 2, 10, ctx); } else { qqbar_t t; ca_t x; qqbar_init(t); ca_init(x, ctx); qqbar_randtest(t, state, 8, 10); ca_set_qqbar(x, t, ctx); ca_poly_randtest_same_nf(A, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); ca_poly_randtest_same_nf(B, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); ca_poly_randtest_same_nf(C, state, x, 1 + n_randint(state, 20), 2 + n_randint(state, 100), 2 + n_randint(state, 100), ctx); qqbar_clear(t); ca_clear(x, ctx); } ca_poly_randtest(ABC, state, 4, 2, 10, ctx); ca_poly_randtest(AB, state, 4, 2, 10, ctx); ca_poly_randtest(AC, state, 4, 2, 10, ctx); ca_poly_randtest(ABAC, state, 4, 2, 10, ctx); ca_poly_add(ABC, B, C, ctx); if (n_randint(state, 2)) ca_poly_mul(ABC, A, ABC, ctx); else ca_poly_mul(ABC, ABC, A, ctx); ca_poly_mul(AB, A, B, ctx); ca_poly_mul(AC, A, C, ctx); ca_poly_add(ABAC, AB, AC, ctx); if (ca_poly_check_equal(ABC, ABAC, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_poly_print(C, ctx); flint_printf("\n"); flint_printf("ABC = "); ca_poly_print(ABC, ctx); flint_printf("\n"); flint_printf("ABAC = "); ca_poly_print(ABAC, ctx); flint_printf("\n"); flint_abort(); } /* Test A^2 = A * A */ ca_poly_set(B, A, ctx); ca_poly_mul(AB, A, B, ctx); ca_poly_mul(AC, A, A, ctx); if (ca_poly_check_equal(AB, AC, ctx) == T_FALSE) { flint_printf("FAIL (squaring)\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("AB = "); ca_poly_print(AB, ctx); flint_printf("\n"); flint_printf("AC = "); ca_poly_print(AC, ctx); flint_printf("\n"); flint_abort(); } ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(C, ctx); ca_poly_clear(ABC, ctx); ca_poly_clear(AB, ctx); ca_poly_clear(AC, ctx); ca_poly_clear(ABAC, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-pow_ui.c000066400000000000000000000036551461254215100177470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_pow_ui, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, An, Am, AnAm, Anm; ulong n, m; /* Test A^n * A^m = A^(n+m) */ ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(An, ctx); ca_poly_init(Am, ctx); ca_poly_init(AnAm, ctx); ca_poly_init(Anm, ctx); ca_poly_randtest(A, state, 5, 1, 5, ctx); n = n_randint(state, 5); m = n_randint(state, 5); ca_poly_pow_ui(An, A, n, ctx); ca_poly_set(Am, A, ctx); ca_poly_pow_ui(Am, Am, m, ctx); ca_poly_mul(AnAm, An, Am, ctx); ca_poly_pow_ui(Anm, A, n + m, ctx); if (ca_poly_check_equal(AnAm, Anm, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("An = "); ca_poly_print(An, ctx); flint_printf("\n"); flint_printf("Am = "); ca_poly_print(Am, ctx); flint_printf("\n"); flint_printf("AnAm = "); ca_poly_print(AnAm, ctx); flint_printf("\n"); flint_printf("Anm = "); ca_poly_print(Anm, ctx); flint_printf("\n"); flint_abort(); } ca_poly_clear(A, ctx); ca_poly_clear(An, ctx); ca_poly_clear(Am, ctx); ca_poly_clear(AnAm, ctx); ca_poly_clear(Anm, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-roots.c000066400000000000000000000053531461254215100176100ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_roots, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_vec_t R; ca_poly_t A, B; ulong * exp; ca_ctx_init(ctx); ca_vec_init(R, 0, ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); if (n_randint(state, 10) != 0) { ca_poly_randtest(A, state, 5, 1, 10, ctx); } else { ca_poly_randtest(A, state, 3, 0, 5, ctx); ca_poly_randtest_rational(B, state, 3, 5, ctx); ca_poly_mul(A, A, B, ctx); if (n_randint(state, 2)) ca_poly_mul(A, A, B, ctx); if (n_randint(state, 2)) ca_poly_mul(A, A, B, ctx); } exp = flint_malloc(sizeof(ulong) * A->length); if (ca_poly_roots(R, exp, A, ctx)) { ca_poly_set_roots(B, R, exp, ctx); if (A->length) ca_poly_mul_ca(B, B, A->coeffs + A->length - 1, ctx); if (ca_poly_check_equal(A, B, ctx) == T_FALSE) { slong i; flint_printf("FAIL\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("R = "); ca_vec_print(R, ctx); flint_printf("\n"); for (i = 0; i < R->length; i++) flint_printf("e[%wd] = %wu\n", i, exp[i]); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_abort(); } if (0) { printf("=================================================================\n\n"); printf("EQUAL: "); truth_print(ca_poly_check_equal(A, B, ctx)); printf("\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n\n"); flint_printf("R = "); ca_vec_print(R, ctx); flint_printf("\n\n"); ca_poly_sub(B, A, B, ctx); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n\n"); } } ca_vec_clear(R, ctx); ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); flint_free(exp); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/test/t-squarefree_part.c000066400000000000000000000037151461254215100216320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ca_poly.h" TEST_FUNCTION_START(ca_poly_squarefree_part, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { ca_ctx_t ctx; ca_poly_t A, B, C; ca_t c; ca_poly_vec_t F; ulong * exp; slong i; ca_ctx_init(ctx); ca_poly_init(A, ctx); ca_poly_init(B, ctx); ca_poly_init(C, ctx); ca_poly_vec_init(F, 0, ctx); ca_init(c, ctx); ca_poly_randtest(A, state, 5, 1, 5, ctx); exp = flint_malloc(sizeof(ulong) * A->length); if (ca_poly_factor_squarefree(c, F, exp, A, ctx)) { if (ca_poly_squarefree_part(B, A, ctx)) { ca_poly_one(C, ctx); for (i = 0; i < F->length; i++) ca_poly_mul(C, C, F->entries + i, ctx); if (ca_poly_check_equal(B, C, ctx) == T_FALSE) { flint_printf("FAIL (product)\n\n"); flint_printf("A = "); ca_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); ca_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); ca_poly_print(C, ctx); flint_printf("\n"); flint_abort(); } } } flint_free(exp); ca_poly_clear(A, ctx); ca_poly_clear(B, ctx); ca_poly_clear(C, ctx); ca_poly_vec_clear(F, ctx); ca_clear(c, ctx); ca_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ca_poly/transfer.c000066400000000000000000000016151461254215100170430ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_transfer(ca_poly_t res, ca_ctx_t res_ctx, const ca_poly_t src, ca_ctx_t src_ctx) { slong i, len; if (res_ctx == src_ctx) { ca_poly_set(res, src, res_ctx); } else { len = src->length; ca_poly_fit_length(res, len, res_ctx); _ca_poly_set_length(res, len, res_ctx); for (i = 0; i < src->length; i++) ca_transfer(res->coeffs + i, res_ctx, src->coeffs + i, src_ctx); _ca_poly_normalise(res, res_ctx); } } flint-3.1.3/src/ca_poly/vec_append.c000066400000000000000000000011451461254215100173210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void ca_poly_vec_append(ca_poly_vec_t vec, const ca_poly_t f, ca_ctx_t ctx) { _ca_poly_vec_fit_length(vec, vec->length + 1, ctx); ca_poly_set(vec->entries + vec->length, f, ctx); vec->length++; } flint-3.1.3/src/ca_poly/vec_clear.c000066400000000000000000000013351461254215100171410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_vec_clear(ca_poly_struct * v, slong n, ca_ctx_t ctx) { slong i; for (i = 0; i < n; i++) ca_poly_clear(v + i, ctx); flint_free(v); } void ca_poly_vec_clear(ca_poly_vec_t vec, ca_ctx_t ctx) { if (vec->entries != NULL) { _ca_poly_vec_clear(vec->entries, vec->alloc, ctx); } } flint-3.1.3/src/ca_poly/vec_init.c000066400000000000000000000016651461254215100170240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" ca_poly_struct * _ca_poly_vec_init(slong n, ca_ctx_t ctx) { slong i; ca_poly_struct * v = (ca_poly_struct *) flint_malloc(sizeof(ca_poly_struct) * n); for (i = 0; i < n; i++) ca_poly_init(v + i, ctx); return v; } void ca_poly_vec_init(ca_poly_vec_t res, slong len, ca_ctx_t ctx) { if (len == 0) { res->entries = NULL; res->length = 0; res->alloc = 0; } else { res->entries = _ca_poly_vec_init(len, ctx); res->length = len; res->alloc = len; } } flint-3.1.3/src/ca_poly/vec_set_length.c000066400000000000000000000023321461254215100202050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_poly.h" void _ca_poly_vec_fit_length(ca_poly_vec_t vec, slong len, ca_ctx_t ctx) { if (len > vec->alloc) { slong i; if (len < 2 * vec->alloc) len = 2 * vec->alloc; vec->entries = flint_realloc(vec->entries, len * sizeof(ca_poly_struct)); for (i = vec->alloc; i < len; i++) ca_poly_init(vec->entries + i, ctx); vec->alloc = len; } } void ca_poly_vec_set_length(ca_poly_vec_t vec, slong len, ca_ctx_t ctx) { slong i; if (vec->length > len) { for (i = len; i < vec->length; i++) ca_poly_zero(vec->entries + i, ctx); } else if (vec->length < len) { _ca_poly_vec_fit_length(vec, len, ctx); for (i = vec->length; i < len; i++) ca_poly_zero(vec->entries + i, ctx); } vec->length = len; } flint-3.1.3/src/ca_vec.h000066400000000000000000000114151461254215100150150ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CA_VEC_H #define CA_VEC_H #ifdef CA_VEC_INLINES_C #define CA_VEC_INLINE #else #define CA_VEC_INLINE static inline #endif #include "ca.h" #ifdef __cplusplus extern "C" { #endif /* Vector object */ typedef struct { ca_ptr entries; slong alloc; slong length; } ca_vec_struct; typedef ca_vec_struct ca_vec_t[1]; #define ca_vec_entry(vec, i) ((vec)->entries + (i)) CA_VEC_INLINE ca_ptr ca_vec_entry_ptr(ca_vec_t vec, slong i) { return ca_vec_entry(vec, i); } /* Memory management */ ca_ptr _ca_vec_init(slong len, ca_ctx_t ctx); void ca_vec_init(ca_vec_t vec, slong len, ca_ctx_t ctx); void _ca_vec_clear(ca_ptr v, slong len, ca_ctx_t ctx); void ca_vec_clear(ca_vec_t vec, ca_ctx_t ctx); void _ca_vec_swap(ca_ptr vec1, ca_ptr vec2, slong len, ca_ctx_t ctx); CA_VEC_INLINE void ca_vec_swap(ca_vec_t vec1, ca_vec_t vec2, ca_ctx_t ctx) { FLINT_SWAP(ca_vec_struct, *vec1, *vec2); } /* Length */ CA_VEC_INLINE slong ca_vec_length(const ca_vec_t vec, ca_ctx_t ctx) { return vec->length; } void _ca_vec_fit_length(ca_vec_t vec, slong len, ca_ctx_t ctx); void ca_vec_set_length(ca_vec_t res, slong len, ca_ctx_t ctx); /* Assignment */ void _ca_vec_set(ca_ptr res, ca_srcptr src, slong len, ca_ctx_t ctx); void ca_vec_set(ca_vec_t res, const ca_vec_t src, ca_ctx_t ctx); /* Special vectors */ void _ca_vec_zero(ca_ptr res, slong len, ca_ctx_t ctx); void ca_vec_zero(ca_vec_t res, slong len, ca_ctx_t ctx); CA_VEC_INLINE void _ca_vec_unknown(ca_ptr vec, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_unknown(vec + i, ctx); } CA_VEC_INLINE void _ca_vec_undefined(ca_ptr vec, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_undefined(vec + i, ctx); } /* Input and output */ void ca_vec_print(const ca_vec_t vec, ca_ctx_t ctx); void ca_vec_printn(const ca_vec_t vec, slong digits, ca_ctx_t ctx); /* List operations */ CA_VEC_INLINE void ca_vec_append(ca_vec_t vec, const ca_t f, ca_ctx_t ctx) { _ca_vec_fit_length(vec, vec->length + 1, ctx); ca_set(vec->entries + vec->length, f, ctx); vec->length++; } /* Arithmetic */ void _ca_vec_neg(ca_ptr res, ca_srcptr src, slong len, ca_ctx_t ctx); void ca_vec_neg(ca_vec_t res, const ca_vec_t src, ca_ctx_t ctx); void _ca_vec_add(ca_ptr res, ca_srcptr vec1, ca_srcptr vec2, slong len, ca_ctx_t ctx); void _ca_vec_sub(ca_ptr res, ca_srcptr vec1, ca_srcptr vec2, slong len, ca_ctx_t ctx); void _ca_vec_scalar_mul_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx); void _ca_vec_scalar_div_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx); void _ca_vec_scalar_addmul_ca(ca_ptr res, ca_srcptr vec, slong len, const ca_t c, ca_ctx_t ctx); void _ca_vec_scalar_submul_ca(ca_ptr res, ca_srcptr vec, slong len, const ca_t c, ca_ctx_t ctx); /* Comparisons and predicates */ truth_t _ca_vec_check_is_zero(ca_srcptr vec, slong len, ca_ctx_t ctx); /* Internal representation */ CA_VEC_INLINE int _ca_vec_is_fmpq_vec(ca_srcptr vec, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) if (!CA_IS_QQ(vec + i, ctx)) return 0; return 1; } CA_VEC_INLINE int _ca_vec_fmpq_vec_is_fmpz_vec(ca_srcptr vec, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) if (!fmpz_is_one(CA_FMPQ_DENREF(vec + i))) return 0; return 1; } CA_VEC_INLINE void _ca_vec_fmpq_vec_get_fmpz_vec_den(fmpz * c, fmpz_t den, ca_srcptr vec, slong len, ca_ctx_t ctx) { slong i; fmpz_one(den); if (_ca_vec_fmpq_vec_is_fmpz_vec(vec, len, ctx)) { for (i = 0; i < len; i++) fmpz_set(c + i, CA_FMPQ_NUMREF(vec + i)); } else { for (i = 0; i < len; i++) fmpz_lcm(den, den, CA_FMPQ_DENREF(vec + i)); for (i = 0; i < len; i++) { fmpz_divexact(c + i, den, CA_FMPQ_DENREF(vec + i)); fmpz_mul(c + i, c + i, CA_FMPQ_NUMREF(vec + i)); } } } CA_VEC_INLINE void _ca_vec_set_fmpz_vec_div_fmpz(ca_ptr res, const fmpz * v, const fmpz_t den, slong len, ca_ctx_t ctx) { slong i; if (fmpz_is_one(den)) { for (i = 0; i < len; i++) ca_set_fmpz(res + i, v + i, ctx); } else { for (i = 0; i < len; i++) { ca_set_fmpz(res + i, v + i, ctx); /* todo: optimize */ ca_div_fmpz(res + i, res + i, den, ctx); } } } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/ca_vec/000077500000000000000000000000001461254215100146425ustar00rootroot00000000000000flint-3.1.3/src/ca_vec/ca_vec.c000066400000000000000000000134501461254215100162310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ca_vec.h" void _ca_vec_add(ca_ptr res, ca_srcptr vec1, ca_srcptr vec2, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_add(res + i, vec1 + i, vec2 + i, ctx); } truth_t _ca_vec_check_is_zero(ca_srcptr vec, slong len, ca_ctx_t ctx) { slong i; int have_unknown; truth_t is_zero; have_unknown = 0; for (i = 0; i < len; i++) { is_zero = ca_check_is_zero(vec + i, ctx); if (is_zero == T_FALSE) return T_FALSE; if (is_zero == T_UNKNOWN) have_unknown = 1; } if (have_unknown) return T_UNKNOWN; else return T_TRUE; } void _ca_vec_clear(ca_ptr v, slong n, ca_ctx_t ctx) { slong i; for (i = 0; i < n; i++) ca_clear(v + i, ctx); flint_free(v); } void ca_vec_clear(ca_vec_t vec, ca_ctx_t ctx) { if (vec->entries != NULL) { _ca_vec_clear(vec->entries, vec->alloc, ctx); } } ca_ptr _ca_vec_init(slong n, ca_ctx_t ctx) { slong i; ca_ptr v = (ca_ptr) flint_malloc(sizeof(ca_struct) * n); for (i = 0; i < n; i++) ca_init(v + i, ctx); return v; } void ca_vec_init(ca_vec_t res, slong len, ca_ctx_t ctx) { if (len == 0) { res->entries = NULL; res->length = 0; res->alloc = 0; } else { res->entries = _ca_vec_init(len, ctx); res->length = len; res->alloc = len; } } void _ca_vec_neg(ca_ptr res, ca_srcptr src, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_neg(res + i, src + i, ctx); } void ca_vec_neg(ca_vec_t res, const ca_vec_t src, ca_ctx_t ctx) { if (res != src) { ca_vec_set_length(res, ca_vec_length(src, ctx), ctx); _ca_vec_neg(ca_vec_entry(res, 0), ca_vec_entry(src, 0), ca_vec_length(res, ctx), ctx); } } void ca_vec_print(const ca_vec_t vec, ca_ctx_t ctx) { slong i, len; len = vec->length; flint_printf("ca_vec of length %wd:\n", len); for (i = 0; i < len; i++) { flint_printf(" "); ca_print(vec->entries + i, ctx); flint_printf("\n"); } flint_printf("\n"); } void ca_vec_printn(const ca_vec_t vec, slong digits, ca_ctx_t ctx) { slong len, i; len = vec->length; flint_printf("["); for (i = 0; i < len; i++) { ca_printn(vec->entries + i, digits, ctx); if (i < len - 1) flint_printf(", "); } flint_printf("]\n"); } void _ca_vec_scalar_addmul_ca(ca_ptr res, ca_srcptr vec, slong len, const ca_t c, ca_ctx_t ctx) { slong i; ca_t t; if (len > 0) { ca_init(t, ctx); for (i = 0; i < len; i++) { ca_mul(t, vec + i, c, ctx); ca_add(res + i, res + i, t, ctx); } ca_clear(t, ctx); } } void _ca_vec_scalar_div_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx) { slong i; if (len > 0) { ca_t t; ca_init(t, ctx); ca_inv(t, c, ctx); for (i = 0; i < len; i++) ca_mul(res + i, src + i, t, ctx); ca_clear(t, ctx); } } void _ca_vec_scalar_mul_ca(ca_ptr res, ca_srcptr src, slong len, const ca_t c, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_mul(res + i, src + i, c, ctx); } void _ca_vec_scalar_submul_ca(ca_ptr res, ca_srcptr vec, slong len, const ca_t c, ca_ctx_t ctx) { slong i; ca_t t; if (len > 0) { ca_init(t, ctx); for (i = 0; i < len; i++) { ca_mul(t, vec + i, c, ctx); ca_sub(res + i, res + i, t, ctx); } ca_clear(t, ctx); } } void _ca_vec_set(ca_ptr res, ca_srcptr src, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_set(res + i, src + i, ctx); } void ca_vec_set(ca_vec_t res, const ca_vec_t src, ca_ctx_t ctx) { if (res != src) { ca_vec_set_length(res, ca_vec_length(src, ctx), ctx); _ca_vec_set(ca_vec_entry(res, 0), ca_vec_entry(src, 0), ca_vec_length(res, ctx), ctx); } } void _ca_vec_fit_length(ca_vec_t vec, slong len, ca_ctx_t ctx) { if (len > vec->alloc) { slong i; if (len < 2 * vec->alloc) len = 2 * vec->alloc; vec->entries = flint_realloc(vec->entries, len * sizeof(ca_struct)); for (i = vec->alloc; i < len; i++) ca_init(ca_vec_entry(vec, i), ctx); vec->alloc = len; } } void ca_vec_set_length(ca_vec_t vec, slong len, ca_ctx_t ctx) { slong i; if (vec->length > len) { for (i = len; i < vec->length; i++) ca_zero(ca_vec_entry(vec, i), ctx); } else if (vec->length < len) { _ca_vec_fit_length(vec, len, ctx); for (i = vec->length; i < len; i++) ca_zero(ca_vec_entry(vec, i), ctx); } vec->length = len; } void _ca_vec_sub(ca_ptr res, ca_srcptr vec1, ca_srcptr vec2, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_sub(res + i, vec1 + i, vec2 + i, ctx); } void _ca_vec_swap(ca_ptr vec1, ca_ptr vec2, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_swap(vec1 + i, vec2 + i, ctx); } void _ca_vec_zero(ca_ptr res, slong len, ca_ctx_t ctx) { slong i; for (i = 0; i < len; i++) ca_zero(res + i, ctx); } void ca_vec_zero(ca_vec_t res, slong len, ca_ctx_t ctx) { ca_vec_set_length(res, len, ctx); _ca_vec_zero(ca_vec_entry(res, 0), ca_vec_length(res, ctx), ctx); } flint-3.1.3/src/ca_vec/inlines.c000066400000000000000000000006541461254215100164540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define CA_VEC_INLINES_C #include "ca_vec.h" flint-3.1.3/src/calcium.h000066400000000000000000000060541461254215100152150ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CALCIUM_H #define CALCIUM_H #ifdef CALCIUM_INLINES_C #define CALCIUM_INLINE #else #define CALCIUM_INLINE static inline #endif #include "fmpz.h" #include "acb_types.h" #ifdef __cplusplus extern "C" { #endif /* Input and output */ typedef struct { FLINT_FILE * fp; char * s; slong len; slong alloc; } calcium_stream_struct; typedef calcium_stream_struct calcium_stream_t[1]; #ifdef FLINT_HAVE_FILE void calcium_stream_init_file(calcium_stream_t out, FILE * fp); #endif CALCIUM_INLINE void calcium_stream_init_str(calcium_stream_t out) { out->fp = NULL; out->s = (char *) flint_malloc(16); out->s[0] = '\0'; out->len = 0; out->alloc = 16; } void calcium_write(calcium_stream_t out, const char * s); void calcium_write_si(calcium_stream_t out, slong x); void calcium_write_fmpz(calcium_stream_t out, const fmpz_t c); void calcium_write_acb(calcium_stream_t out, const acb_t z, slong digits, ulong flags); CALCIUM_INLINE void calcium_write_free(calcium_stream_t out, char * s) { calcium_write(out, s); flint_free(s); } /* Triple-valued logic */ typedef enum { T_TRUE, T_FALSE, T_UNKNOWN } truth_t; CALCIUM_INLINE void truth_print(truth_t t) { if (t == T_TRUE) flint_printf("T_TRUE"); if (t == T_FALSE) flint_printf("T_FALSE"); if (t == T_UNKNOWN) flint_printf("T_UNKNOWN"); } /* IDs for builtin mathematical functions and constants */ typedef enum { /* Special case for representing qqbar instances */ CA_QQBar, /* Arithmetic */ CA_Neg, CA_Add, CA_Sub, CA_Mul, CA_Div, /* Roots */ CA_Sqrt, CA_Cbrt, CA_Root, /* Complex parts */ CA_Floor, CA_Ceil, CA_Abs, CA_Sign, CA_Re, CA_Im, CA_Arg, CA_Conjugate, /* Elementary constants */ CA_Pi, /* Elementary functions */ CA_Sin, CA_Cos, CA_Exp, CA_Log, CA_Pow, CA_Tan, CA_Cot, CA_Cosh, CA_Sinh, CA_Tanh, CA_Coth, CA_Atan, CA_Acos, CA_Asin, CA_Acot, CA_Atanh, CA_Acosh, CA_Asinh, CA_Acoth, /* Euler's constant */ CA_Euler, /* Gamma and related functions */ CA_Gamma, CA_LogGamma, CA_Psi, CA_Erf, CA_Erfc, CA_Erfi, CA_RiemannZeta, CA_HurwitzZeta, CA_FUNC_CODE_LENGTH } calcium_func_code; const char * calcium_func_name(calcium_func_code func); /* Flint extras */ /* slower alternative: fmpz_fdiv_ui(x 1000000007) */ CALCIUM_INLINE ulong calcium_fmpz_hash(const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) return *x; else { __mpz_struct * z = COEFF_TO_PTR(*x); return (z->_mp_size > 0) ? z->_mp_d[0] : -z->_mp_d[0]; } } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/calcium/000077500000000000000000000000001461254215100150375ustar00rootroot00000000000000flint-3.1.3/src/calcium/func_name.c000066400000000000000000000043611461254215100171420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "calcium.h" const char * calcium_func_name(calcium_func_code func) { switch (func) { /* Arithmetic */ case CA_Neg: return "Neg"; case CA_Add: return "Add"; case CA_Sub: return "Sub"; case CA_Mul: return "Mul"; case CA_Div: return "Div"; /* Roots */ case CA_Sqrt: return "Sqrt"; case CA_Cbrt: return "Cbrt"; case CA_Root: return "Root"; /* Complex parts */ case CA_Floor: return "Floor"; case CA_Ceil: return "Ceil"; case CA_Abs: return "Abs"; case CA_Sign: return "Sign"; case CA_Re: return "Re"; case CA_Im: return "Im"; case CA_Arg: return "Arg"; case CA_Conjugate: return "Conjugate"; /* Elementary constants */ case CA_Pi: return "Pi"; /* Elementary functions */ case CA_Exp: return "Exp"; case CA_Log: return "Log"; case CA_Pow: return "Pow"; case CA_Cos: return "Cos"; case CA_Sin: return "Sin"; case CA_Tan: return "Tan"; case CA_Cosh: return "Cosh"; case CA_Sinh: return "Sinh"; case CA_Tanh: return "Tanh"; case CA_Atan: return "Atan"; case CA_Acos: return "Acos"; case CA_Asin: return "Asin"; case CA_Atanh: return "Atanh"; case CA_Acosh: return "Acosh"; case CA_Asinh: return "Asinh"; /* Euler's constant */ case CA_Euler: return "Euler"; /* Gamma and related functions */ case CA_Gamma: return "Gamma"; case CA_LogGamma: return "LogGamma"; case CA_Psi: return "Psi"; case CA_Erf: return "Erf"; case CA_Erfc: return "Erfc"; case CA_Erfi: return "Erfi"; case CA_RiemannZeta: return "RiemannZeta"; case CA_HurwitzZeta: return "HurwitzZeta"; default: return ""; } } flint-3.1.3/src/calcium/io.c000066400000000000000000000010341461254215100156100ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "calcium.h" void calcium_stream_init_file(calcium_stream_t out, FILE * fp) { out->fp = (FLINT_FILE *) fp; out->s = NULL; } flint-3.1.3/src/calcium/write.c000066400000000000000000000016761461254215100163470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "calcium.h" void calcium_write(calcium_stream_t out, const char * s) { if (out->fp != NULL) { flint_fprintf((FILE *) out->fp, s); } else { slong len, alloc; len = strlen(s); alloc = out->len + len + 1; if (alloc > out->alloc) { alloc = FLINT_MAX(alloc, out->alloc * 2); out->s = flint_realloc(out->s, alloc); out->alloc = alloc; } memcpy(out->s + out->len, s, len + 1); out->len += len; } } flint-3.1.3/src/calcium/write_acb.c000066400000000000000000000030121461254215100171360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "calcium.h" void calcium_write_arb(calcium_stream_t out, const arb_t x, slong digits, ulong flags) { calcium_write_free(out, arb_get_str(x, digits, flags)); } void calcium_write_acb(calcium_stream_t out, const acb_t z, slong digits, ulong flags) { if (arb_is_zero(acb_imagref(z))) { calcium_write_arb(out, acb_realref(z), digits, flags); } else if (arb_is_zero(acb_realref(z))) { calcium_write_arb(out, acb_imagref(z), digits, flags); calcium_write(out, "*I"); } else { calcium_write_arb(out, acb_realref(z), digits, flags); if ((arb_is_exact(acb_imagref(z)) || (flags & ARB_STR_NO_RADIUS)) && arf_sgn(arb_midref(acb_imagref(z))) < 0) { arb_t t; arb_init(t); arb_neg(t, acb_imagref(z)); calcium_write(out, " - "); calcium_write_arb(out, t, digits, flags); arb_clear(t); } else { calcium_write(out, " + "); calcium_write_arb(out, acb_imagref(z), digits, flags); } calcium_write(out, "*I"); } } flint-3.1.3/src/calcium/write_si.c000066400000000000000000000012541461254215100170320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "calcium.h" void calcium_write_si(calcium_stream_t out, slong x) { if (out->fp != NULL) { flint_fprintf((FILE *) out->fp, "%wd", x); } else { char tmp[22]; sprintf(tmp, WORD_FMT "d", x); calcium_write(out, tmp); } } flint-3.1.3/src/crt_helpers.h000066400000000000000000000734101461254215100161120ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef CRT_HELPERS_H #define CRT_HELPERS_H #if defined(__GNUC__) && defined(__AVX2__) # include #elif defined(_MSC_VER) && defined(__AVX2__) # include #endif #include "flint.h" #include "templates.h" #ifdef __cplusplus extern "C" { #endif #if defined(__AVX2__) FLINT_FORCE_INLINE unsigned char _addcarry_ulong(unsigned char cf, ulong x, ulong y, ulong* s) { long long unsigned int _s; cf = _addcarry_u64(cf, (long long unsigned int)(x), (long long unsigned int)(y), &_s); *s = (ulong)(_s); return cf; } FLINT_FORCE_INLINE unsigned char _subborrow_ulong(unsigned char cf, ulong x, ulong y, ulong* s) { long long unsigned int _s; cf = _subborrow_u64(cf, (long long unsigned int)(x), (long long unsigned int)(y), &_s); *s = (ulong)(_s); return cf; } #else FLINT_FORCE_INLINE unsigned char _addcarry_ulong(unsigned char cf, ulong x, ulong y, ulong* s) { #if 0 ulong cf2; *s = __builtin_addcl(x, y, cf, &cf2); return cf2; #else ulong hi, lo; add_ssaaaa(hi, lo, 0, x, 0, y); add_ssaaaa(hi, lo, hi, lo, 0, (ulong) cf); *s = lo; return hi; #endif } FLINT_FORCE_INLINE unsigned char _subborrow_ulong(unsigned char cf, ulong x, ulong y, ulong* s) { #if 0 ulong cf2; *s = __builtin_subcl(x, y, cf, &cf2); return cf2; #else ulong hi, lo; sub_ddmmss(hi, lo, 0, x, 0, y); sub_ddmmss(hi, lo, hi, lo, 0, (ulong) cf); *s = lo; return hi != 0; #endif } #endif #if 1 #if defined(__GNUC__) && defined(__AVX2__) #define add_sssssaaaaaaaaaa(s4,s3,s2,s1,s0, a4,a3,a2,a1,a0, b4,b3,b2,b1,b0) \ __asm__ ("addq %14,%q4\n\tadcq %12,%q3\n\tadcq %10,%q2\n\tadcq %8,%q1\n\tadcq %6,%q0" \ : "=r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "1" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "2" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "3" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "4" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define add_ssssssaaaaaaaaaaaa(s5,s4,s3,s2,s1,s0, a5,a4,a3,a2,a1,a0, b5,b4,b3,b2,b1,b0) \ __asm__ ("addq %17,%q5\nadcq %15,%q4\n\tadcq %13,%q3\n\tadcq %11,%q2\n\tadcq %9,%q1\n\tadcq %7,%q0" \ : "=r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a5)), "rme" ((mp_limb_t)(b5)), \ "1" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "2" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "3" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "4" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "5" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define add_sssssssaaaaaaaaaaaaaa(s6,s5,s4,s3,s2,s1,s0, a6,a5,a4,a3,a2,a1,a0, b6,b5,b4,b3,b2,b1,b0) \ __asm__ ("addq %20,%q6\nadcq %18,%q5\nadcq %16,%q4\n\tadcq %14,%q3\n\tadcq %12,%q2\n\tadcq %10,%q1\n\tadcq %8,%q0" \ : "=r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a6)), "rme" ((mp_limb_t)(b6)), \ "1" ((mp_limb_t)(a5)), "rme" ((mp_limb_t)(b5)), \ "2" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "3" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "4" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "5" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "6" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define add_ssssssssaaaaaaaaaaaaaaaa(s7,s6,s5,s4,s3,s2,s1,s0, a7,a6,a5,a4,a3,a2,a1,a0, b7,b6,b5,b4,b3,b2,b1,b0) \ __asm__ ("addq %23,%q7\nadcq %21,%q6\nadcq %19,%q5\n\tadcq %17,%q4\n\tadcq %15,%q3\n\tadcq %13,%q2\n\tadcq %11,%q1\n\tadcq %9,%q0" \ : "=r" (s7), "=&r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a7)), "rme" ((mp_limb_t)(b7)), \ "1" ((mp_limb_t)(a6)), "rme" ((mp_limb_t)(b6)), \ "2" ((mp_limb_t)(a5)), "rme" ((mp_limb_t)(b5)), \ "3" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "4" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "5" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "6" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "7" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define sub_ddddmmmmssss(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ __asm__ ("subq %11,%q3\n\tsbbq %9,%q2\n\tsbbq %7,%q1\n\tsbbq %5,%q0" \ : "=r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "1" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "2" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "3" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define sub_dddddmmmmmsssss(s4,s3,s2,s1,s0, a4,a3,a2,a1,a0, b4,b3,b2,b1,b0) \ __asm__ ("subq %14,%q4\n\tsbbq %12,%q3\n\tsbbq %10,%q2\n\tsbbq %8,%q1\n\tsbbq %6,%q0" \ : "=r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "1" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "2" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "3" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "4" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define sub_ddddddmmmmmmssssss(s5,s4,s3,s2,s1,s0, a5,a4,a3,a2,a1,a0, b5,b4,b3,b2,b1,b0) \ __asm__ ("subq %17,%q5\nsbbq %15,%q4\n\tsbbq %13,%q3\n\tsbbq %11,%q2\n\tsbbq %9,%q1\n\tsbbq %7,%q0" \ : "=r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a5)), "rme" ((mp_limb_t)(b5)), \ "1" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "2" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "3" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "4" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "5" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define sub_dddddddmmmmmmmsssssss(s6,s5,s4,s3,s2,s1,s0, a6,a5,a4,a3,a2,a1,a0, b6,b5,b4,b3,b2,b1,b0) \ __asm__ ("subq %20,%q6\nsbbq %18,%q5\nsbbq %16,%q4\n\tsbbq %14,%q3\n\tsbbq %12,%q2\n\tsbbq %10,%q1\n\tsbbq %8,%q0" \ : "=r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a6)), "rme" ((mp_limb_t)(b6)), \ "1" ((mp_limb_t)(a5)), "rme" ((mp_limb_t)(b5)), \ "2" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "3" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "4" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "5" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "6" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #define sub_ddddddddmmmmmmmmssssssss(s7,s6,s5,s4,s3,s2,s1,s0, a7,a6,a5,a4,a3,a2,a1,a0, b7,b6,b5,b4,b3,b2,b1,b0) \ __asm__ ("subq %23,%q7\nsbbq %21,%q6\nsbbq %19,%q5\n\tsbbq %17,%q4\n\tsbbq %15,%q3\n\tsbbq %13,%q2\n\tsbbq %11,%q1\n\tsbbq %9,%q0" \ : "=r" (s7), "=&r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a7)), "rme" ((mp_limb_t)(b7)), \ "1" ((mp_limb_t)(a6)), "rme" ((mp_limb_t)(b6)), \ "2" ((mp_limb_t)(a5)), "rme" ((mp_limb_t)(b5)), \ "3" ((mp_limb_t)(a4)), "rme" ((mp_limb_t)(b4)), \ "4" ((mp_limb_t)(a3)), "rme" ((mp_limb_t)(b3)), \ "5" ((mp_limb_t)(a2)), "rme" ((mp_limb_t)(b2)), \ "6" ((mp_limb_t)(a1)), "rme" ((mp_limb_t)(b1)), \ "7" ((mp_limb_t)(a0)), "rme" ((mp_limb_t)(b0))) #elif defined(__GNUC__) && defined(__ARM_NEON) #define add_sssssaaaaaaaaaa(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \ __asm__ ("adds %4,%9,%14\n\tadcs %3,%8,%13\n\tadcs %2,%7,%12\n\tadcs %1,%6,%11\n\tadc %0,%5,%10"\ : "=r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define add_ssssssaaaaaaaaaaaa(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \ __asm__ ("adds %5,%11,%17\n\tadcs %4,%10,%16\n\tadcs %3,%9,%15\n\tadcs %2,%8,%14\n\tadcs %1,%7,%13\n\tadc %0,%6,%12"\ : "=r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a5)), "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b5)), "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define add_sssssssaaaaaaaaaaaaaa(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \ __asm__ ("adds %6,%13,%20\n\tadcs %5,%12,%19\n\tadcs %4,%11,%18\n\tadcs %3,%10,%17\n\tadcs %2,%9,%16\n\tadcs %1,%8,%15\n\tadc %0,%7,%14"\ : "=r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a6)), "r" ((mp_limb_t)(a5)), "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b6)), "r" ((mp_limb_t)(b5)), "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define add_ssssssssaaaaaaaaaaaaaaaa(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \ __asm__ ("adds %7,%15,%23\n\tadcs %6,%14,%22\n\tadcs %5,%13,%21\n\tadcs %4,%12,%20\n\tadcs %3,%11,%19\n\tadcs %2,%10,%18\n\tadcs %1,%9,%17\n\tadc %0,%8,%16"\ : "=r" (s7), "=&r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a7)), "r" ((mp_limb_t)(a6)), "r" ((mp_limb_t)(a5)), "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b7)), "r" ((mp_limb_t)(b6)), "r" ((mp_limb_t)(b5)), "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define sub_ddddmmmmssss(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ __asm__ ("subs %3,%7,%11\n\tsbcs %2,%6,%10\n\tsbcs %1,%5,%9\n\tsbc %0,%4,%8"\ : "=r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define sub_dddddmmmmmsssss(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \ __asm__ ("subs %4,%9,%14\n\tsbcs %3,%8,%13\n\tsbcs %2,%7,%12\n\tsbcs %1,%6,%11\n\tsbc %0,%5,%10"\ : "=r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define sub_ddddddmmmmmmssssss(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \ __asm__ ("subs %5,%11,%17\n\tsbcs %4,%10,%16\n\tsbcs %3,%9,%15\n\tsbcs %2,%8,%14\n\tsbcs %1,%7,%13\n\tsbc %0,%6,%12"\ : "=r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a5)), "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b5)), "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define sub_dddddddmmmmmmmsssssss(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \ __asm__ ("subs %6,%13,%20\n\tsbcs %5,%12,%19\n\tsbcs %4,%11,%18\n\tsbcs %3,%10,%17\n\tsbcs %2,%9,%16\n\tsbcs %1,%8,%15\n\tsbc %0,%7,%14"\ : "=r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a6)), "r" ((mp_limb_t)(a5)), "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b6)), "r" ((mp_limb_t)(b5)), "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #define sub_ddddddddmmmmmmmmssssssss(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \ __asm__ ("subs %7,%15,%23\n\tsbcs %6,%14,%22\n\tsbcs %5,%13,%21\n\tsbcs %4,%12,%20\n\tsbcs %3,%11,%19\n\tsbcs %2,%10,%18\n\tsbcs %1,%9,%17\n\tsbc %0,%8,%16"\ : "=r" (s7), "=&r" (s6), "=&r" (s5), "=&r" (s4), "=&r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((mp_limb_t)(a7)), "r" ((mp_limb_t)(a6)), "r" ((mp_limb_t)(a5)), "r" ((mp_limb_t)(a4)), "r" ((mp_limb_t)(a3)), "r" ((mp_limb_t)(a2)), "r" ((mp_limb_t)(a1)), "r" ((mp_limb_t)(a0)), \ "r" ((mp_limb_t)(b7)), "r" ((mp_limb_t)(b6)), "r" ((mp_limb_t)(b5)), "r" ((mp_limb_t)(b4)), "r" ((mp_limb_t)(b3)), "r" ((mp_limb_t)(b2)), "r" ((mp_limb_t)(b1)), "rI" ((mp_limb_t)(b0)) \ : "cc") #elif defined(_MSC_VER) && (defined(__AVX2__) || defined(_M_ARM64)) #define add_sssssaaaaaaaaaa(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t0 = 0; \ add_ssssaaaaaaaa(__t0, s2, s1, s0, (mp_limb_t) 0, a2, a1, a0, (mp_limb_t) 0, b2, b1, b0); \ add_ssaaaa(s4, s3, a4, a3, b4, b3); \ add_ssaaaa(s4, s3, s4, s3, (mp_limb_t) 0, __t0); \ } while (0) #define add_ssssssaaaaaaaaaaaa(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t1 = 0; \ add_sssssaaaaaaaaaa(__t1, s3, s2, s1, s0, (mp_limb_t) 0, a3, a2, a1, a0, (mp_limb_t) 0, b3, b2, b1, b0);\ add_ssaaaa(s5, s4, a5, a4, b5, b4); \ add_ssaaaa(s5, s4, s5, s4, (mp_limb_t) 0, __t1); \ } while (0) #define add_sssssssaaaaaaaaaaaaaa(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t2 = 0; \ add_ssssssaaaaaaaaaaaa(__t2, s4, s3, s2, s1, s0, (mp_limb_t) 0, a4, a3, a2, a1, a0, (mp_limb_t) 0, b4, b3, b2, b1, b0); \ add_ssaaaa(s6, s5, a6, a5, b6, b5); \ add_ssaaaa(s6, s5, s6, s5, (mp_limb_t) 0, __t2); \ } while (0) #define add_ssssssssaaaaaaaaaaaaaaaa(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t3 = 0; \ add_sssssssaaaaaaaaaaaaaa(__t3, s5, s4, s3, s2, s1, s0, (mp_limb_t) 0, a5, a4, a3, a2, a1, a0, (mp_limb_t) 0, b5, b4, b3, b2, b1, b0); \ add_ssaaaa(s7, s6, a7, a6, b7, b6); \ add_ssaaaa(s7, s6, s7, s6, (mp_limb_t) 0, __t3); \ } while (0) #define sub_ddddmmmmssss(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ do { \ mp_limb_t __t1, __u1; \ sub_dddmmmsss(__t1, s1, s0, (mp_limb_t) 0, a1, a0, (mp_limb_t) 0, b1, b0); \ sub_ddmmss(__u1, s2, (mp_limb_t) 0, a2, (mp_limb_t) 0, b2); \ sub_ddmmss(s3, s2, (a3) - (b3), s2, -__u1, -__t1); \ } while (0) #define sub_dddddmmmmmsssss(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t2, __u2; \ sub_ddddmmmmssss(__t2, s2, s1, s0, (mp_limb_t) 0, a2, a1, a0, (mp_limb_t) 0, b2, b1, b0); \ sub_ddmmss(__u2, s3, (mp_limb_t) 0, a3, (mp_limb_t) 0, b3); \ sub_ddmmss(s4, s3, (a4) - (b4), s3, -__u2, -__t2); \ } while (0) #define sub_ddddddmmmmmmssssss(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t3, __u3; \ sub_dddddmmmmmsssss(__t3, s3, s2, s1, s0, (mp_limb_t) 0, a3, a2, a1, a0, (mp_limb_t) 0, b3, b2, b1, b0);\ sub_ddmmss(__u3, s4, (mp_limb_t) 0, a4, (mp_limb_t) 0, b4); \ sub_ddmmss(s5, s4, (a5) - (b5), s4, -__u3, -__t3); \ } while (0) #define sub_dddddddmmmmmmmsssssss(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t4, __u4; \ sub_ddddddmmmmmmssssss(__t4, s4, s3, s2, s1, s0, (mp_limb_t) 0, a4, a3, a2, a1, a0, (mp_limb_t) 0, b4, b3, b2, b1, b0); \ sub_ddmmss(__u4, s5, (mp_limb_t) 0, a5, (mp_limb_t) 0, b5); \ sub_ddmmss(s6, s5, (a6) - (b6), s5, -__u4, -__t4); \ } while (0) #define sub_ddddddddmmmmmmmmssssssss(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \ do { \ mp_limb_t __t5, __u5; \ sub_dddddddmmmmmmmsssssss(__t5, s5, s4, s3, s2, s1, s0, (mp_limb_t) 0, a5, a4, a3, a2, a1, a0, (mp_limb_t) 0, b5, b4, b3, b2, b1, b0); \ sub_ddmmss(__u5, s6, (mp_limb_t) 0, a6, (mp_limb_t) 0, b6); \ sub_ddmmss(s7, s6, (a7) - (b7), s6, -__u5, -__t5); \ } while (0) #else # error crt_helpers.h requires AVX2 or Neon instructions #endif FLINT_FORCE_INLINE void multi_add_0(ulong z[], const ulong a[]) { } FLINT_FORCE_INLINE void multi_add_1(ulong z[], const ulong a[]) { z[0] += a[0]; } FLINT_FORCE_INLINE void multi_add_2(ulong z[], const ulong a[]) { add_ssaaaa(z[1],z[0], z[1],z[0], a[1],a[0]); } FLINT_FORCE_INLINE void multi_add_3(ulong z[], const ulong a[]) { add_sssaaaaaa(z[2],z[1],z[0], z[2],z[1],z[0], a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_add_4(ulong z[], const ulong a[]) { add_ssssaaaaaaaa(z[3],z[2],z[1],z[0], z[3],z[2],z[1],z[0], a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_add_5(ulong z[], const ulong a[]) { add_sssssaaaaaaaaaa(z[4],z[3],z[2],z[1],z[0], z[4],z[3],z[2],z[1],z[0], a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_add_6(ulong z[], const ulong a[]) { add_ssssssaaaaaaaaaaaa(z[5],z[4],z[3],z[2],z[1],z[0], z[5],z[4],z[3],z[2],z[1],z[0], a[5],a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_add_7(ulong z[], const ulong a[]) { add_sssssssaaaaaaaaaaaaaa(z[6],z[5],z[4],z[3],z[2],z[1],z[0], z[6],z[5],z[4],z[3],z[2],z[1],z[0], a[6],a[5],a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_add_8(ulong z[], const ulong a[]) { add_ssssssssaaaaaaaaaaaaaaaa(z[7],z[6],z[5],z[4],z[3],z[2],z[1],z[0], z[7],z[6],z[5],z[4],z[3],z[2],z[1],z[0], a[7],a[6],a[5],a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_sub_0(ulong z[], const ulong a[]) { } FLINT_FORCE_INLINE void multi_sub_1(ulong z[], const ulong a[]) { z[0] -= a[0]; } FLINT_FORCE_INLINE void multi_sub_2(ulong z[], const ulong a[]) { sub_ddmmss(z[1],z[0], z[1],z[0], a[1],a[0]); } FLINT_FORCE_INLINE void multi_sub_3(ulong z[], const ulong a[]) { sub_dddmmmsss(z[2],z[1],z[0], z[2],z[1],z[0], a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_sub_4(ulong z[], const ulong a[]) { sub_ddddmmmmssss(z[3],z[2],z[1],z[0], z[3],z[2],z[1],z[0], a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_sub_5(ulong z[], const ulong a[]) { sub_dddddmmmmmsssss(z[4],z[3],z[2],z[1],z[0], z[4],z[3],z[2],z[1],z[0], a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_sub_6(ulong z[], const ulong a[]) { sub_ddddddmmmmmmssssss(z[5],z[4],z[3],z[2],z[1],z[0], z[5],z[4],z[3],z[2],z[1],z[0], a[5],a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_sub_7(ulong z[], const ulong a[]) { sub_dddddddmmmmmmmsssssss(z[6],z[5],z[4],z[3],z[2],z[1],z[0], z[6],z[5],z[4],z[3],z[2],z[1],z[0], a[6],a[5],a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_sub_8(ulong z[], const ulong a[]) { sub_ddddddddmmmmmmmmssssssss(z[7],z[6],z[5],z[4],z[3],z[2],z[1],z[0], z[7],z[6],z[5],z[4],z[3],z[2],z[1],z[0], a[7],a[6],a[5],a[4],a[3],a[2],a[1],a[0]); } FLINT_FORCE_INLINE void multi_rsub_0(ulong z[], const ulong a[]) { } FLINT_FORCE_INLINE void multi_rsub_1(ulong z[], const ulong a[]) { z[0] = a[0] - z[0]; } FLINT_FORCE_INLINE void multi_rsub_2(ulong z[], const ulong a[]) { sub_ddmmss(z[1],z[0], a[1],a[0], z[1],z[0]); } FLINT_FORCE_INLINE void multi_rsub_3(ulong z[], const ulong a[]) { sub_dddmmmsss(z[2],z[1],z[0], a[2],a[1],a[0], z[2],z[1],z[0]); } FLINT_FORCE_INLINE void multi_rsub_4(ulong z[], const ulong a[]) { sub_ddddmmmmssss(z[3],z[2],z[1],z[0], a[3],a[2],a[1],a[0], z[3],z[2],z[1],z[0]); } FLINT_FORCE_INLINE void multi_rsub_5(ulong z[], const ulong a[]) { sub_dddddmmmmmsssss(z[4],z[3],z[2],z[1],z[0], a[4],a[3],a[2],a[1],a[0], z[4],z[3],z[2],z[1],z[0]); } FLINT_FORCE_INLINE void multi_rsub_6(ulong z[], const ulong a[]) { sub_ddddddmmmmmmssssss(z[5],z[4],z[3],z[2],z[1],z[0], a[5],a[4],a[3],a[2],a[1],a[0], z[5],z[4],z[3],z[2],z[1],z[0]); } FLINT_FORCE_INLINE void multi_rsub_7(ulong z[], const ulong a[]) { sub_dddddddmmmmmmmsssssss(z[6],z[5],z[4],z[3],z[2],z[1],z[0], a[6],a[5],a[4],a[3],a[2],a[1],a[0], z[6],z[5],z[4],z[3],z[2],z[1],z[0]); } FLINT_FORCE_INLINE void multi_rsub_8(ulong z[], const ulong a[]) { sub_ddddddddmmmmmmmmssssssss(z[7],z[6],z[5],z[4],z[3],z[2],z[1],z[0], a[7],a[6],a[5],a[4],a[3],a[2],a[1],a[0], z[7],z[6],z[5],z[4],z[3],z[2],z[1],z[0]); } #else #define DEFINE_IT(n) \ FLINT_FORCE_INLINE void CAT(multi_add, n)(ulong z[], const ulong a[]) \ { \ unsigned char cf = 0; \ for (ulong i = 0; i < n; i++) \ cf = _addcarry_ulong(cf, z[i], a[i], &z[i]); \ } DEFINE_IT(0) DEFINE_IT(1) DEFINE_IT(2) DEFINE_IT(3) DEFINE_IT(4) DEFINE_IT(5) DEFINE_IT(6) DEFINE_IT(7) DEFINE_IT(8) #undef DEFINE_IT #define DEFINE_IT(n) \ FLINT_FORCE_INLINE void CAT(multi_sub, n)(ulong z[], const ulong a[]) \ { \ unsigned char cf = 0; \ for (ulong i = 0; i < n; i++) \ cf = _subborrow_ulong(cf, z[i], a[i], &z[i]); \ } DEFINE_IT(0) DEFINE_IT(1) DEFINE_IT(2) DEFINE_IT(3) DEFINE_IT(4) DEFINE_IT(5) DEFINE_IT(6) DEFINE_IT(7) #undef DEFINE_IT #endif #ifdef __GNUC__ FLINT_FORCE_INLINE void _mul(ulong* hi, ulong* lo, ulong y, ulong x) { __uint128_t p = ((__uint128_t) x) * ((__uint128_t) y); *lo = (ulong) (p); *hi = (ulong) (p >> 64); } FLINT_FORCE_INLINE void _madd(ulong* hi, ulong* lo, ulong y, ulong x) { __uint128_t p = ((__uint128_t) *lo) | (((__uint128_t) *hi) << 64); p += ((__uint128_t) x) * ((__uint128_t) y); *lo = (ulong) (p); *hi = (ulong) (p >> 64); } #else FLINT_FORCE_INLINE void _mul(ulong* hi, ulong* lo, ulong y, ulong x) { ulong r1, r0; umul_ppmm(r1, r0, x, y); *lo = r0; *hi = r1; } FLINT_FORCE_INLINE void _madd(ulong* hi, ulong* lo, ulong y, ulong x) { ulong r1, r0; umul_ppmm(r1, r0, x, y); add_ssaaaa(*hi, *lo, r1, r0, *hi, *lo); } #endif #define DEFINE_IT(n, m) \ FLINT_FORCE_INLINE void CAT3(_big_mul, n, m)(ulong r[], ulong t[], ulong C[], ulong y) \ { \ for (ulong k = 0; k < n; k += 2) \ { \ if (k + 1 < n) \ { \ FLINT_ASSERT(k < m); \ _mul(&r[k+1],&r[k+0], C[k+0], y); \ } \ else \ { \ FLINT_ASSERT(k + 1 == n); \ if (k < m) \ r[k+0] = C[k+0]*y; \ else \ r[k+0] = 0; \ } \ \ if (k + 2 < n) \ { \ FLINT_ASSERT(k + 1 < m); \ _mul(&t[k+2],&t[k+1], C[k+1], y); \ } \ else if (k + 1 < n) \ { \ if (k + 1 < m) \ t[k+1] = C[k+1]*y; \ else \ t[k+1] = 0; \ } \ } \ } \ FLINT_FORCE_INLINE void CAT3(_big_addmul, n, m)(ulong r[], ulong t[], ulong C[], ulong y) \ { \ for (ulong k = 0; k < n; k += 2) \ { \ if (k + 1 < n) \ { \ FLINT_ASSERT(k < m); \ _madd(&r[k+1],&r[k+0], C[k+0], y); \ } \ else \ { \ FLINT_ASSERT(k + 1 == n); \ if (k < m) \ r[k+0] += C[k+0]*y; \ } \ \ if (k + 2 < n) \ { \ FLINT_ASSERT(k + 1 < m); \ _madd(&t[k+2],&t[k+1], C[k+1], y); \ } \ else if (k + 1 < n) \ { \ if (k + 1 < m) \ t[k+1] += C[k+1]*y; \ } \ } \ } DEFINE_IT(1, 0) DEFINE_IT(2, 1) DEFINE_IT(3, 2) DEFINE_IT(4, 3) DEFINE_IT(4, 4) DEFINE_IT(5, 4) DEFINE_IT(6, 5) DEFINE_IT(7, 6) #undef DEFINE_IT #define DEFINE_IT(n, n_minus_1) \ FLINT_FORCE_INLINE void CAT(_reduce_big_sum, n)(ulong r[], ulong t[], const ulong* limit) \ { \ CAT(multi_add, n_minus_1)(r+1, t+1); \ check: \ for (ulong k = n; k > 1; k--) \ { \ if (FLINT_LIKELY(r[k-1] > limit[k-1])) \ goto sub; \ if (r[k-1] < limit[k-1]) \ return; \ } \ if (r[0] < limit[0]) \ return; \ sub: \ CAT(multi_sub, n)(r, limit); \ goto check; \ } DEFINE_IT(1, 0) DEFINE_IT(2, 1) DEFINE_IT(3, 2) DEFINE_IT(4, 3) DEFINE_IT(5, 4) DEFINE_IT(6, 5) DEFINE_IT(7, 6) #undef DEFINE_IT #ifdef __cplusplus } #endif #endif /* CRT_HELPERS_H */ flint-3.1.3/src/d_mat.h000066400000000000000000000043121461254215100146570ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef D_MAT_H #define D_MAT_H #ifdef D_MAT_INLINES_C #define D_MAT_INLINE #else #define D_MAT_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif typedef struct { double * entries; slong r; slong c; double ** rows; } d_mat_struct; typedef d_mat_struct d_mat_t[1]; #define d_mat_entry(mat,i,j) (*((mat)->rows[i] + (j))) D_MAT_INLINE slong d_mat_nrows(const d_mat_t mat) { return mat->r; } D_MAT_INLINE slong d_mat_ncols(const d_mat_t mat) { return mat->c; } /* Memory management ********************************************************/ void d_mat_init(d_mat_t mat, slong rows, slong cols); D_MAT_INLINE void d_mat_swap_entrywise(d_mat_t mat1, d_mat_t mat2) { slong i, j; for (i = 0; i < d_mat_nrows(mat1); i++) { double * row1 = mat1->rows[i]; double * row2 = mat2->rows[i]; for (j = 0; j < d_mat_ncols(mat1); j++) FLINT_SWAP(double, row1[j], row2[j]); } } void d_mat_set(d_mat_t mat1, const d_mat_t mat2); void d_mat_clear(d_mat_t mat); int d_mat_equal(const d_mat_t mat1, const d_mat_t mat2); int d_mat_approx_equal(const d_mat_t mat1, const d_mat_t mat2, double eps); D_MAT_INLINE int d_mat_is_square(const d_mat_t mat) { return (mat->r == mat->c); } void d_mat_zero(d_mat_t mat); /* Input and output *********************************************************/ void d_mat_print(const d_mat_t mat); /* Random matrix generation *************************************************/ void d_mat_randtest(d_mat_t mat, flint_rand_t state, slong minexp, slong maxexp); /* Transpose */ void d_mat_transpose(d_mat_t B, const d_mat_t A); /* Multiplication */ void d_mat_mul_classical(d_mat_t C, const d_mat_t A, const d_mat_t B); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/d_mat/000077500000000000000000000000001461254215100145065ustar00rootroot00000000000000flint-3.1.3/src/d_mat/approx_equal.c000066400000000000000000000015461461254215100173600ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #include "d_mat.h" int d_mat_approx_equal(const d_mat_t mat1, const d_mat_t mat2, double eps) { slong j; if (mat1->r != mat2->r || mat1->c != mat2->c) { return 0; } if (mat1->r == 0 || mat1->c == 0) return 1; for (j = 0; j < mat1->r; j++) { if (!_d_vec_approx_equal(mat1->rows[j], mat2->rows[j], mat1->c, eps)) { return 0; } } return 1; } flint-3.1.3/src/d_mat/clear.c000066400000000000000000000012411461254215100157360ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_clear(d_mat_t mat) { if (mat->entries) { flint_free(mat->entries); /* Clean up array of entries */ flint_free(mat->rows); /* Clean up row array */ } else if (mat->r != 0) flint_free(mat->rows); } flint-3.1.3/src/d_mat/equal.c000066400000000000000000000015071461254215100157640ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #include "d_mat.h" int d_mat_equal(const d_mat_t mat1, const d_mat_t mat2) { slong j; if (mat1->r != mat2->r || mat1->c != mat2->c) { return 0; } if (mat1->r == 0 || mat1->c == 0) return 1; for (j = 0; j < mat1->r; j++) { if (!_d_vec_equal(mat1->rows[j], mat2->rows[j], mat1->c)) { return 0; } } return 1; } flint-3.1.3/src/d_mat/init.c000066400000000000000000000020461461254215100156170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_init(d_mat_t mat, slong rows, slong cols) { slong i; if (rows != 0) mat->rows = (double **) flint_malloc(rows * sizeof(double *)); else mat->rows = NULL; if (rows != 0 && cols != 0) /* Allocate space for r*c small entries */ { mat->entries = (double *) flint_calloc(flint_mul_sizes(rows, cols), sizeof(double)); for (i = 0; i < rows; i++) mat->rows[i] = mat->entries + i * cols; } else { mat->entries = NULL; for (i = 0; i < rows; i++) mat->rows[i] = NULL; } mat->r = rows; mat->c = cols; } flint-3.1.3/src/d_mat/inlines.c000066400000000000000000000006711461254215100163170ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define D_MAT_INLINES_C #include "flint.h" #include "d_mat.h" flint-3.1.3/src/d_mat/mul_classical.c000066400000000000000000000033601461254215100174670ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_mul_classical(d_mat_t C, const d_mat_t A, const d_mat_t B) { slong ar, bc, br; slong jj, kk, i, j, k, blocksize; double temp; d_mat_t Bt; ar = A->r; br = B->r; bc = B->c; blocksize = 64 / sizeof(double); if (C == A || C == B) { d_mat_t t; d_mat_init(t, ar, bc); d_mat_mul_classical(t, A, B); d_mat_swap_entrywise(C, t); d_mat_clear(t); return; } if (C->r != ar || C->c != bc) { flint_throw(FLINT_ERROR, "Exception (d_mat_mul_classical). Incompatible dimensions.\n"); } if (br == 0) { d_mat_zero(C); return; } d_mat_init(Bt, bc, br); d_mat_transpose(Bt, B); d_mat_zero(C); for (jj = 0; jj < bc; jj += blocksize) { for (kk = 0; kk < br; kk += blocksize) { for (i = 0; i < ar; i++) { for (j = jj; j < FLINT_MIN(jj + blocksize, bc); j++) { temp = 0; for (k = kk; k < FLINT_MIN(kk + blocksize, br); k++) { temp += d_mat_entry(A, i, k) * d_mat_entry(Bt, j, k); } d_mat_entry(C, i, j) += temp; } } } } d_mat_clear(Bt); } flint-3.1.3/src/d_mat/print.c000066400000000000000000000014641461254215100160130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_print(const d_mat_t mat) { slong i, j; flint_printf("["); for (i = 0; i < mat->r; i++) { flint_printf("["); for (j = 0; j < mat->c; j++) { flint_printf("%E", d_mat_entry(mat, i, j)); if (j < mat->c - 1) flint_printf(" "); } flint_printf("]\n"); } flint_printf("]\n"); } flint-3.1.3/src/d_mat/randtest.c000066400000000000000000000013451461254215100165010ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_mat.h" void d_mat_randtest(d_mat_t mat, flint_rand_t state, slong minexp, slong maxexp) { slong r, c, i, j; r = mat->r; c = mat->c; for (i = 0; i < r; i++) for (j = 0; j < c; j++) d_mat_entry(mat, i, j) = d_randtest_signed(state, minexp, maxexp); } flint-3.1.3/src/d_mat/set.c000066400000000000000000000013511461254215100154450ustar00rootroot00000000000000/* Copyright (C) 2008-2009 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #include "d_mat.h" void d_mat_set(d_mat_t mat1, const d_mat_t mat2) { if (mat1 != mat2) { slong i; if (mat2->r && mat2->c) for (i = 0; i < mat2->r; i++) _d_vec_set(mat1->rows[i], mat2->rows[i], mat2->c); } } flint-3.1.3/src/d_mat/test/000077500000000000000000000000001461254215100154655ustar00rootroot00000000000000flint-3.1.3/src/d_mat/test/main.c000066400000000000000000000021401461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-entry.c" #include "t-equal.c" #include "t-init_clear.c" #include "t-is_square.c" #include "t-mul_classical.c" #include "t-transpose.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(d_mat_entry), TEST_FUNCTION(d_mat_equal), TEST_FUNCTION(d_mat_init_clear), TEST_FUNCTION(d_mat_is_square), TEST_FUNCTION(d_mat_mul_classical), TEST_FUNCTION(d_mat_transpose), TEST_FUNCTION(d_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/d_mat/test/t-entry.c000066400000000000000000000024371461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_mat.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_mat_entry, state) { int i; /* check if entries are accessed correctly by setting their values and then comparing them */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { d_mat_t A; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); d_mat_init(A, rows, cols); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) d_mat_entry(A, j, k) = 3 * j + 7 * k; for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) if (d_mat_entry(A, j, k) != 3 * j + 7 * k) TEST_FUNCTION_FAIL("get/set entry %wd, %wd\n", j, k); d_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_mat/test/t-equal.c000066400000000000000000000032601461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_mat.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_mat_equal, state) { int i; /* check A != B if A, B have different dimensions * set A = B and check A == B * compare matrices with different entries */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { d_mat_t A, B, C, D, E; slong m, n, j; m = n_randint(state, 20); n = n_randint(state, 20); d_mat_init(A, m, n); d_mat_init(B, m, n); d_mat_init(C, m, n); d_mat_init(D, m + 1, n); d_mat_init(E, m, n + 1); if (d_mat_equal(A, D) || d_mat_equal(A, E)) TEST_FUNCTION_FAIL("different dimensions should not be equal\n"); d_mat_randtest(A, state, 0, 0); d_mat_set(B, A); if (!d_mat_equal(A, B)) TEST_FUNCTION_FAIL("copied matrices should be equal\n"); if (m && n) { j = n_randint(state, m * n); A->entries[j] += 1; if (d_mat_equal(A, B)) TEST_FUNCTION_FAIL("FAIL: modified matrices should not be equal\n"); } d_mat_clear(A); d_mat_clear(B); d_mat_clear(C); d_mat_clear(D); d_mat_clear(E); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_mat/test/t-init_clear.c000066400000000000000000000017541461254215100202120ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_mat.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_mat_init_clear, state) { int i; /* check if memory management works properly */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { d_mat_t A; slong j, k; slong rows = n_randint(state, 100); slong cols = n_randint(state, 100); d_mat_init(A, rows, cols); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) d_mat_entry(A, j, k) = 0; d_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_mat/test/t-is_square.c000066400000000000000000000017201461254215100200650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_mat.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_mat_is_square, state) { int i; /* check if a non-zero value is returned for non-square matrices */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { d_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); d_mat_init(A, rows, cols); if (d_mat_is_square(A) != (rows == cols)) TEST_FUNCTION_FAIL(""); d_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_mat/test/t-mul_classical.c000066400000000000000000000035151461254215100207110ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_mat.h" #include "ulong_extras.h" #define D_MAT_MUL_CLASSICAL_EPS (1e-11) TEST_FUNCTION_START(d_mat_mul_classical, state) { d_mat_t A, B, C, D, E, F, G; slong i; /* check associative law */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n, k, l; m = n_randint(state, 50); n = n_randint(state, 50); k = n_randint(state, 50); l = n_randint(state, 50); d_mat_init(A, m, n); d_mat_init(B, n, k); d_mat_init(C, k, l); d_mat_init(D, n, l); d_mat_init(E, m, k); d_mat_init(F, m, l); d_mat_init(G, m, l); d_mat_randtest(A, state, 0, 0); d_mat_randtest(B, state, 0, 0); d_mat_randtest(C, state, 0, 0); d_mat_mul_classical(D, B, C); d_mat_mul_classical(E, A, B); d_mat_mul_classical(F, A, D); d_mat_mul_classical(G, E, C); if (!d_mat_approx_equal(F, G, D_MAT_MUL_CLASSICAL_EPS)) TEST_FUNCTION_FAIL("Results not equal\n"); if (n == k) { d_mat_mul_classical(A, A, B); if (!d_mat_equal(A, E)) TEST_FUNCTION_FAIL("Aliasing failed\n"); } d_mat_clear(A); d_mat_clear(B); d_mat_clear(C); d_mat_clear(D); d_mat_clear(E); d_mat_clear(F); d_mat_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_mat/test/t-transpose.c000066400000000000000000000033241461254215100201120ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "d_mat.h" TEST_FUNCTION_START(d_mat_transpose, state) { slong m, n, rep; /* Rectangular transpose */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { d_mat_t A, B, C; m = n_randint(state, 20); n = n_randint(state, 20); d_mat_init(A, m, n); d_mat_init(B, n, m); d_mat_init(C, m, n); d_mat_randtest(A, state, n_randint(state, 100), n_randint(state, 100)); d_mat_randtest(B, state, n_randint(state, 100), n_randint(state, 100)); d_mat_transpose(B, A); d_mat_transpose(C, B); if (!d_mat_equal(C, A)) TEST_FUNCTION_FAIL(""); d_mat_clear(A); d_mat_clear(B); d_mat_clear(C); } /* Self-transpose */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { d_mat_t A, B; m = n_randint(state, 20); d_mat_init(A, m, m); d_mat_init(B, m, m); d_mat_randtest(A, state, n_randint(state, 100), n_randint(state, 100)); d_mat_set(B, A); d_mat_transpose(B, B); d_mat_transpose(B, B); if (!d_mat_equal(B, A)) TEST_FUNCTION_FAIL(""); d_mat_clear(A); d_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_mat/test/t-zero.c000066400000000000000000000021431461254215100170510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_mat.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_mat_zero, state) { slong m, n, i, j, rep; /* check it's zero */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { d_mat_t A; m = n_randint(state, 20); n = n_randint(state, 20); d_mat_init(A, m, n); d_mat_randtest(A, state, 0, 0); d_mat_zero(A); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (d_mat_entry(A, i, j) != 0) TEST_FUNCTION_FAIL("nonzero entry\n"); } } d_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_mat/transpose.c000066400000000000000000000022551461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_transpose(d_mat_t B, const d_mat_t A) { slong ii, jj, i, j, blocksize; blocksize = 64 / sizeof(double); if (B->r != A->c || B->c != A->r) { flint_throw(FLINT_ERROR, "Exception (d_mat_transpose). Incompatible dimensions.\n"); } if (B == A) { d_mat_t t; d_mat_init(t, A->r, A->c); d_mat_transpose(t, A); d_mat_swap_entrywise(B, t); d_mat_clear(t); return; } for (ii = 0; ii < B->r; ii += blocksize) for (jj = 0; jj < B->c; jj += blocksize) for (i = ii; i < FLINT_MIN(ii + blocksize, B->r); i++) for (j = jj; j < FLINT_MIN(jj + blocksize, B->c); j++) d_mat_entry(B, i, j) = d_mat_entry(A, j, i); } flint-3.1.3/src/d_mat/zero.c000066400000000000000000000011521461254215100156300ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #include "d_mat.h" void d_mat_zero(d_mat_t mat) { slong i; if (mat->c < 1) return; for (i = 0; i < mat->r; i++) _d_vec_zero(mat->rows[i], mat->c); } flint-3.1.3/src/d_vec.h000066400000000000000000000050631461254215100146570ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef D_VEC_H #define D_VEC_H #ifdef D_VEC_INLINES_C #define D_VEC_INLINE #else #define D_VEC_INLINE static inline #endif #include "flint.h" #include "double_extras.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *******************************************************/ double * _d_vec_init(slong len); void _d_vec_clear(double * vec); /* Randomisation ***********************************************************/ void _d_vec_randtest(double * f, flint_rand_t state, slong len, slong minexp, slong maxexp); /* Assignment and basic manipulation ***************************************/ void _d_vec_set(double * vec1, const double * vec2, slong len2); void _d_vec_zero(double * vec, slong len); /* Comparison **************************************************************/ int _d_vec_equal(const double * vec1, const double * vec2, slong len); int _d_vec_approx_equal(const double * vec1, const double * vec2, slong len, double eps); int _d_vec_is_zero(const double * vec, slong len); int _d_vec_is_approx_zero(const double * vec, slong len, double eps); /* Arithmetic ****************************************************************/ void _d_vec_add(double * res, const double * vec1, const double * vec2, slong len2); void _d_vec_sub(double * res, const double * vec1, const double * vec2, slong len2); D_VEC_INLINE void _d_vec_mul_2exp(double * res, const double * x, slong len, int e) { slong i; if (e >= D_MIN_NORMAL_EXPONENT && e <= D_MAX_NORMAL_EXPONENT) { double_uint64_u u; u.i = ((int64_t) (e + D_EXPONENT_BIAS)) << D_EXPONENT_SHIFT; for (i = 0; i < len; i++) res[i] = x[i] * u.f; } else { for (i = 0; i < len; i++) res[i] = ldexp(x[i], e); } } /* Dot product and norm **************************************/ double _d_vec_dot(const double * vec1, const double * vec2, slong len2); double _d_vec_norm(const double * vec, slong len); double _d_vec_dot_heuristic(const double * vec1, const double * vec2, slong len2, double * err); double _d_vec_dot_thrice(const double * vec1, const double * vec2, slong len2, double * err); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/d_vec/000077500000000000000000000000001461254215100145025ustar00rootroot00000000000000flint-3.1.3/src/d_vec/add.c000066400000000000000000000012001461254215100153670ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" void _d_vec_add(double *res, const double *vec1, const double *vec2, slong len2) { ulong i; for (i = 0; i < len2; i++) res[i] = vec1[i] + vec2[i]; } flint-3.1.3/src/d_vec/approx_equal.c000066400000000000000000000014741461254215100173540ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif int _d_vec_approx_equal(const double *vec1, const double *vec2, slong len, double eps) { slong i; if (vec1 == vec2) return 1; for (i = 0; i < len; i++) if (fabs(vec1[i] - vec2[i]) > eps) return 0; return 1; } flint-3.1.3/src/d_vec/clear.c000066400000000000000000000007521461254215100157400ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" void _d_vec_clear(double *vec) { flint_free(vec); } flint-3.1.3/src/d_vec/dot.c000066400000000000000000000012311461254215100154310ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" double _d_vec_dot(const double *vec1, const double *vec2, slong len2) { double sum = 0; slong i; for (i = 0; i < len2; i++) sum += vec1[i] * vec2[i]; return sum; } flint-3.1.3/src/d_vec/dot_heuristic.c000066400000000000000000000021611461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" double _d_vec_dot_heuristic(const double *vec1, const double *vec2, slong len2, double *err) { double psum = 0, nsum = 0, p, n, d, t; int pexp, nexp; slong i; for (i = 0; i < len2; i++) { t = vec1[i] * vec2[i]; if (t >= 0) psum += t; else nsum += t; } nsum = -nsum; if (err != NULL) { p = frexp(psum, &pexp); n = frexp(nsum, &nexp); p = d_mul_2exp(1.0, pexp - D_BITS); n = d_mul_2exp(1.0, nexp - D_BITS); d = FLINT_MAX(p, n); *err = 2 * len2 * d; } return psum - nsum; } flint-3.1.3/src/d_vec/dot_thrice.c000066400000000000000000000041141461254215100167720ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" double _d_vec_dot_thrice(const double *vec1, const double *vec2, slong len2, double *err) { int i, j; double p, h, a1, a2, b1, b2, c, res = 0, g; double *r; ulong factor = (UWORD(1) << 27) + 1; if (len2 == 0) { *err = 0; return 0; } r = _d_vec_init(2 * len2); p = vec1[0] * vec2[0]; c = factor * vec1[0]; a1 = c - (c - vec1[0]); a2 = vec1[0] - a1; c = factor * vec2[0]; b1 = c - (c - vec2[0]); b2 = vec2[0] - b1; r[0] = a2 * b2 - (((p - a1 * b1) - a2 * b1) - a1 * b2); for (i = 1; i < len2; i++) { h = vec1[i] * vec2[i]; c = factor * vec1[i]; a1 = c - (c - vec1[i]); a2 = vec1[i] - a1; c = factor * vec2[i]; b1 = c - (c - vec2[i]); b2 = vec2[i] - b1; r[i] = a2 * b2 - (((h - a1 * b1) - a2 * b1) - a1 * b2); a1 = p; p = p + h; c = p - a1; r[len2 + i - 1] = (a1 - (p - c)) + (h - c); } r[2 * len2 - 1] = p; for (j = 1; j < 2 * len2; j++) { a1 = r[j]; r[j] = r[j] + r[j - 1]; c = r[j] - a1; r[j - 1] = (a1 - (r[j] - c)) + (r[j - 1] - c); } for (i = 0; i < 2 * len2 - 1; i++) { res = res + r[i]; } res = res + r[2 * len2 - 1]; if (err != NULL) { g = (4 * len2 - 2) * D_EPS / (1 - (4 * len2 - 2) * D_EPS); a1 = _d_vec_norm(vec1, len2); a2 = _d_vec_norm(vec2, len2); *err = (D_EPS + 2 * g * g) * fabs(res) + g * g * g * sqrt(a1) * sqrt(a2); } _d_vec_clear(r); return res; } flint-3.1.3/src/d_vec/equal.c000066400000000000000000000012371461254215100157600ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" int _d_vec_equal(const double *vec1, const double *vec2, slong len) { slong i; if (vec1 == vec2) return 1; for (i = 0; i < len; i++) if (vec1[i] != vec2[i]) return 0; return 1; } flint-3.1.3/src/d_vec/init.c000066400000000000000000000010201461254215100156020ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" double * _d_vec_init(slong len) { return (double *) flint_malloc(len * sizeof(double)); } flint-3.1.3/src/d_vec/inlines.c000066400000000000000000000006711461254215100163130ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define D_VEC_INLINES_C #include "flint.h" #include "d_vec.h" flint-3.1.3/src/d_vec/is_approx_zero.c000066400000000000000000000012751461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif int _d_vec_is_approx_zero(const double *vec, slong len, double eps) { slong i; for (i = 0; i < len; i++) if (fabs(vec[i]) > eps) return 0; return 1; } flint-3.1.3/src/d_vec/is_zero.c000066400000000000000000000011251461254215100163170ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" int _d_vec_is_zero(const double *vec, slong len) { slong i; for (i = 0; i < len; i++) if (vec[i] != 0) return 0; return 1; } flint-3.1.3/src/d_vec/norm.c000066400000000000000000000012011461254215100156130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" double _d_vec_norm(const double *vec, slong len) { double sum = 0; slong i; for (i = 0; i < len; i++) sum += vec[i] * vec[i]; return sum; } flint-3.1.3/src/d_vec/randtest.c000066400000000000000000000011751461254215100164760ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" void _d_vec_randtest(double *f, flint_rand_t state, slong len, slong minexp, slong maxexp) { slong i; for (i = 0; i < len; i++) f[i] = d_randtest_signed(state, minexp, maxexp); } flint-3.1.3/src/d_vec/set.c000066400000000000000000000012221461254215100154360ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" void _d_vec_set(double *vec1, const double *vec2, slong len2) { if (vec1 != vec2) { slong i; for (i = 0; i < len2; i++) vec1[i] = vec2[i]; } } flint-3.1.3/src/d_vec/sub.c000066400000000000000000000012001461254215100154300ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" void _d_vec_sub(double *res, const double *vec1, const double *vec2, slong len2) { ulong i; for (i = 0; i < len2; i++) res[i] = vec1[i] - vec2[i]; } flint-3.1.3/src/d_vec/test/000077500000000000000000000000001461254215100154615ustar00rootroot00000000000000flint-3.1.3/src/d_vec/test/main.c000066400000000000000000000022761461254215100165600ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-dot.c" #include "t-dot_heuristic.c" #include "t-dot_thrice.c" #include "t-init_clear.c" #include "t-norm.c" #include "t-set_equal.c" #include "t-sub.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(d_vec_add), TEST_FUNCTION(d_vec_dot), TEST_FUNCTION(d_vec_dot_heuristic), TEST_FUNCTION(d_vec_dot_thrice), TEST_FUNCTION(d_vec_init_clear), TEST_FUNCTION(d_vec_norm), TEST_FUNCTION(d_vec_set_equal), TEST_FUNCTION(d_vec_sub), TEST_FUNCTION(d_vec_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/d_vec/test/t-add.c000066400000000000000000000034041461254215100166170ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_vec_add, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a, *b, *c; slong len = n_randint(state, 100); a = _d_vec_init(len); b = _d_vec_init(len); c = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); _d_vec_add(c, a, b, len); _d_vec_add(a, a, b, len); result = (_d_vec_equal(a, c, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a, *b, *c; slong len = n_randint(state, 100); a = _d_vec_init(len); b = _d_vec_init(len); c = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); _d_vec_add(c, a, b, len); _d_vec_add(b, a, b, len); result = (_d_vec_equal(b, c, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-dot.c000066400000000000000000000026561461254215100166650ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define D_VEC_SP_EPS (1e-14) TEST_FUNCTION_START(d_vec_dot, state) { int i, result; /* check sum of scalar products of parts of vectors is equal to the scalar product of vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a, *b; double res1, res2, res3; slong len = n_randint(state, 100); if (!len) continue; a = _d_vec_init(len); b = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); res1 = _d_vec_dot(a, b, len - 1); res2 = _d_vec_dot(a + len - 1, b + len - 1, 1); res3 = _d_vec_dot(a, b, len); result = fabs(res1 + res2 - res3) < D_VEC_SP_EPS; if (!result) TEST_FUNCTION_FAIL("%g\n", fabs(res1 + res2 - res3)); _d_vec_clear(a); _d_vec_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-dot_heuristic.c000066400000000000000000000033611461254215100207360ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define D_VEC_SP_EPS (1e-14) TEST_FUNCTION_START(d_vec_dot_heuristic, state) { int i, result; /* check sum of scalar products of parts of vectors is equal to the scalar product of vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a, *b; double res1, res2, res3, err1, err2, err3; slong len = n_randint(state, 100); if (!len) continue; a = _d_vec_init(len); b = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); res1 = _d_vec_dot_heuristic(a, b, len - 1, &err1); res2 = _d_vec_dot_heuristic(a + len - 1, b + len - 1, 1, &err2); res3 = _d_vec_dot_heuristic(a, b, len, &err3); result = fabs(res1 + res2 - res3) < D_VEC_SP_EPS; if (!result) TEST_FUNCTION_FAIL( "%g\n" "%g\n" "%g\n" "%g\n" "%g\n" "%g\n" "%g\n", fabs(res1 + res2 - res3), res1, res2 , res3 , err1 , err2 , err3); _d_vec_clear(a); _d_vec_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-dot_thrice.c000066400000000000000000000033451461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define D_VEC_SP_EPS (1e-14) TEST_FUNCTION_START(d_vec_dot_thrice, state) { int i, result; /* check sum of scalar products of parts of vectors is equal to the scalar product of vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a, *b; double res1, res2, res3, err1, err2, err3; slong len = n_randint(state, 100); if (!len) continue; a = _d_vec_init(len); b = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); res1 = _d_vec_dot_thrice(a, b, len - 1, &err1); res2 = _d_vec_dot_thrice(a + len - 1, b + len - 1, 1, &err2); res3 = _d_vec_dot_thrice(a, b, len, &err3); result = fabs(res1 + res2 - res3) < D_VEC_SP_EPS; if (!result) TEST_FUNCTION_FAIL( "%g\n" "%g\n" "%g\n" "%g\n" "%g\n" "%g\n" "%g\n", fabs(res1 + res2 - res3), res1, res2 , res3 , err1 , err2 , err3); _d_vec_clear(a); _d_vec_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-init_clear.c000066400000000000000000000015611461254215100202020ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_vec_init_clear, state) { int i; /* check if memory management works properly */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a; slong j, len = n_randint(state, 100) + 1; a = _d_vec_init(len); for (j = 0; j < len; j++) a[j] = 0; _d_vec_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-norm.c000066400000000000000000000024521461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #define D_VEC_NORM_EPS (1e-14) TEST_FUNCTION_START(d_vec_norm, state) { int i, result; /* check sum of norms of parts of a vector is equal to the norm of the vector */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a; double res1, res2, res3; slong len = n_randint(state, 100); if (!len) continue; a = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); res1 = _d_vec_norm(a, len - 1); res2 = _d_vec_norm(a + len - 1, 1); res3 = _d_vec_norm(a, len); result = fabs(res1 + res2 - res3) < D_VEC_NORM_EPS; if (!result) TEST_FUNCTION_FAIL("%g\n", fabs(res1 + res2 - res3)); _d_vec_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-set_equal.c000066400000000000000000000037261461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_vec_set_equal, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a; slong len = n_randint(state, 100); a = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_set(a, a, len); result = (_d_vec_equal(a, a, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); } /* Compare copied vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a, *b; slong len = n_randint(state, 100); a = _d_vec_init(len); b = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_set(b, a, len); result = (_d_vec_equal(a, b, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); _d_vec_clear(b); } /* Compare unequal vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { double *a, *b; slong len = n_randint(state, 100) + 1; slong coeff; a = _d_vec_init(len); b = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_set(b, a, len); coeff = n_randint(state, len); b[coeff] += 1; result = (!_d_vec_equal(a, b, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); _d_vec_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-sub.c000066400000000000000000000046711461254215100166670ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "double_extras.h" #include "d_vec.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_vec_sub, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { double *a, *b, *c; slong len = n_randint(state, 20); a = _d_vec_init(len); b = _d_vec_init(len); c = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); _d_vec_sub(c, a, b, len); _d_vec_sub(a, a, b, len); result = (_d_vec_equal(a, c, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { double *a, *b, *c; slong len = n_randint(state, 20); a = _d_vec_init(len); b = _d_vec_init(len); c = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); _d_vec_sub(c, a, b, len); _d_vec_sub(b, a, b, len); result = (_d_vec_equal(b, c, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); } /* Check a + b - b = a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { double *a, *b, *c, *d; slong len = n_randint(state, 100); a = _d_vec_init(len); b = _d_vec_init(len); c = _d_vec_init(len); d = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_randtest(b, state, len, 0, 0); _d_vec_add(c, a, b, len); _d_vec_sub(d, c, b, len); result = (_d_vec_approx_equal(d, a, len, D_EPS)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); _d_vec_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/test/t-zero.c000066400000000000000000000020071461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "d_vec.h" #include "ulong_extras.h" TEST_FUNCTION_START(d_vec_zero, state) { int i; /* Check it's zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int result; double *a; slong len = n_randint(state, 100); a = _d_vec_init(len); _d_vec_randtest(a, state, len, 0, 0); _d_vec_zero(a, len); result = (_d_vec_is_zero(a, len)); if (!result) TEST_FUNCTION_FAIL(""); _d_vec_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/d_vec/zero.c000066400000000000000000000011071461254215100156240ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" void _d_vec_zero(double *vec, slong len) { slong i; for (i = 0; i < len; i++) vec[i] = 0; } flint-3.1.3/src/dirichlet.h000066400000000000000000000143711461254215100155500ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef DIRICHLET_H #define DIRICHLET_H #ifdef DIRICHLET_INLINES_C #define DIRICHLET_INLINE #else #define DIRICHLET_INLINE static inline #endif #include "nmod.h" #include "dlog.h" #ifdef __cplusplus extern "C" { #endif #define MAX_FACTORS 15 /* should this dlog pointer be in the prime or the global group? */ typedef struct { ulong p; /* underlying prime */ int e; /* exponent */ nmod_t pe; /* modulus */ nmod_t phi; /* phi(p^e) */ ulong g; /* conrey generator */ dlog_precomp_struct * dlog; /* precomputed data for discrete log mod p^e */ } dirichlet_prime_group_struct; typedef struct { ulong q; /* modulus */ ulong q_even; /* even part of modulus */ nmod_t mod; /* modulus with precomputed inverse */ ulong rad_q; /* radical = product of odd primes */ ulong phi_q; /* phi(q) = group size */ slong neven; /* number of even components (in 0,1,2)*/ slong num; /* number of prime components (even + odd) */ ulong expo; /* exponent = largest order in G */ dirichlet_prime_group_struct * P; ulong * generators; /* generators lifted mod q */ ulong * PHI; /* PHI(k) = expo / phi(k) */ } dirichlet_group_struct; typedef dirichlet_group_struct dirichlet_group_t[1]; DIRICHLET_INLINE ulong dirichlet_group_size(const dirichlet_group_t G) { return G->phi_q; } ulong dirichlet_group_num_primitive(const dirichlet_group_t G); int dirichlet_group_init(dirichlet_group_t G, ulong q); void dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h); void dirichlet_group_clear(dirichlet_group_t G); void dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num); void dirichlet_group_dlog_clear(dirichlet_group_t G); /* properties of elements without log */ ulong dirichlet_conductor_ui(const dirichlet_group_t G, ulong a); int dirichlet_parity_ui(const dirichlet_group_t G, ulong a); ulong dirichlet_order_ui(const dirichlet_group_t G, ulong a); /* characters, keep both number and log */ typedef struct { ulong n; /* number */ ulong * log; /* s.t. prod generators[k]^log[k] = number */ } dirichlet_char_struct; typedef dirichlet_char_struct dirichlet_char_t[1]; void dirichlet_char_init(dirichlet_char_t x, const dirichlet_group_t G); void dirichlet_char_clear(dirichlet_char_t x); void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t x); DIRICHLET_INLINE void dirichlet_char_set(dirichlet_char_t x, const dirichlet_group_t G, const dirichlet_char_t y) { slong k; x->n = y->n; for (k = 0; k < G->num; k++) x->log[k] = y->log[k]; } DIRICHLET_INLINE int dirichlet_char_eq(const dirichlet_char_t x, const dirichlet_char_t y) { return (x->n == y->n); } int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y); int dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x); ulong dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x); ulong dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x); void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m); DIRICHLET_INLINE ulong dirichlet_char_exp(const dirichlet_group_t G, const dirichlet_char_t x) { return x->n; } ulong _dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G); void dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j); ulong dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x); void dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G); void dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G); int dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G); int dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G); void dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n); void dirichlet_char_lower(dirichlet_char_t y, const dirichlet_group_t H, const dirichlet_char_t x, const dirichlet_group_t G); void dirichlet_char_lift(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_group_t H); #define DIRICHLET_CHI_NULL UWORD_MAX ulong dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n); ulong dirichlet_pairing_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); DIRICHLET_INLINE int dirichlet_char_is_principal(const dirichlet_group_t G, const dirichlet_char_t chi) { return (chi->n == 1); } DIRICHLET_INLINE int dirichlet_char_is_real(const dirichlet_group_t G, const dirichlet_char_t chi) { return G->q <= 4 || (nmod_mul(chi->n, chi->n, G->mod) == 1); } DIRICHLET_INLINE int dirichlet_char_is_primitive(const dirichlet_group_t G, const dirichlet_char_t chi) { return (dirichlet_conductor_char(G, chi) == G->q); } ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n); void dirichlet_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv); void dirichlet_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); void dirichlet_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); void dirichlet_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); void dirichlet_chi_vec_loop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv); void dirichlet_chi_vec_primeloop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv); void dirichlet_chi_vec_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/dirichlet/000077500000000000000000000000001461254215100153715ustar00rootroot00000000000000flint-3.1.3/src/dirichlet/char.c000066400000000000000000000011721461254215100164530ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_init(dirichlet_char_t x, const dirichlet_group_t G) { x->log = flint_malloc(G->num * sizeof(ulong)); dirichlet_char_one(x, G); } void dirichlet_char_clear(dirichlet_char_t x) { flint_free(x->log); } flint-3.1.3/src/dirichlet/char_conductor.c000066400000000000000000000020771461254215100205400ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x) { int k, f; ulong cond = 1; if (G->neven >= 1 && x->log[0] == 1) cond = 4; if (G->neven == 2 && x->log[1]) { ulong l2 = x->log[1]; f = n_remove(&l2, 2); cond = UWORD(1) << (G->P[1].e - f); } for (k = G->neven; k < G->num; k++) { if (x->log[k]) { ulong p, lp; p = G->P[k].p; lp = x->log[k]; f = n_remove(&lp, p); if (f) cond *= n_pow(p, G->P[k].e - f); else cond *= G->P[k].pe.n; } } return cond; } flint-3.1.3/src/dirichlet/char_eq_deep.c000066400000000000000000000012411461254215100201320ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y) { slong k; if (x->n != y->n) return 0; for (k = 0; k < G->num; k++) if (x->log[k] != y->log[k]) return 0; return 1; } flint-3.1.3/src/dirichlet/char_exp.c000066400000000000000000000012031461254215100173220ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong _dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G) { ulong k, n = 1; for (k = 0; k < G->num; k++) n = nmod_mul(n, nmod_pow_ui(G->generators[k], x->log[k], G->mod), G->mod); x->n = n; return n; } flint-3.1.3/src/dirichlet/char_first_primitive.c000066400000000000000000000016041461254215100217520ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G) { ulong k; if (G->q % 4 == 2) { flint_throw(FLINT_ERROR, "Exception (dirichlet_char_first_primitive). No primitive element mod %wu.\n",G->q); } x->n = 1; for (k = 0; k < G->num ; k++) { if (k == 0 && G->neven == 2) x->log[k] = 0; else { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] = 1; } } } flint-3.1.3/src/dirichlet/char_index.c000066400000000000000000000025171461254215100176460ustar00rootroot00000000000000/*============================================================================= This file is part of ARB. ARB is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ARB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ARB; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =============================================================================*/ /****************************************************************************** Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include "dirichlet.h" void dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j) { slong k; for (k = G->num - 1; k >= 0; k--) { x->log[k] = j % G->P[k].phi.n; j = j / G->P[k].phi.n; } _dirichlet_char_exp(x, G); } flint-3.1.3/src/dirichlet/char_lift.c000066400000000000000000000017021461254215100174700ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_lift(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_group_t H) { slong k, l; if (G->q % H->q != 0) { flint_throw(FLINT_ERROR, "conrey_lift: lower modulus %wu does not divide %wu\n", H->q, G->q); } for (k = 0, l = 0; k < G->num && l < H->num; k++) { if (G->P[k].p == H->P[l].p) { slong e = n_pow(G->P[k].p, G->P[k].e - H->P[l].e); y->log[k] = x->log[l] * e; l++; } } _dirichlet_char_exp(y, G); } flint-3.1.3/src/dirichlet/char_log.c000066400000000000000000000025671461254215100173250ustar00rootroot00000000000000/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" #include "dirichlet.h" /* assume m is invertible */ void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m) { slong k; /* even part */ if (G->neven >= 1) { x->log[0] = (m % 4 == 3); if (G->neven == 2) { ulong m2 = (x->log[0]) ? -m % G->q_even : m % G->q_even; if (G->P[1].dlog == NULL) x->log[1] = dlog_mod2e_1mod4(m2, G->P[1].e, nmod_inv(5, G->P[1].pe), G->P[1].pe); else x->log[1] = dlog_precomp(G->P[1].dlog, m2); } } /* odd part */ for (k = G->neven; k < G->num; k++) { dirichlet_prime_group_struct P = G->P[k]; if (P.dlog == NULL) { x->log[k] = dlog_once(m % P.pe.n, P.g, P.pe, P.phi.n); } else { x->log[k] = dlog_precomp(P.dlog, m % P.pe.n); } } /* keep value m */ x->n = m; } flint-3.1.3/src/dirichlet/char_lower.c000066400000000000000000000022331461254215100176620ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_lower(dirichlet_char_t y, const dirichlet_group_t H, const dirichlet_char_t x, const dirichlet_group_t G) { slong k, l; if (G->q % H->q != 0) { flint_throw(FLINT_ERROR, "conrey_lower: lower modulus %wu does not divide %wu\n", H->q, G->q); } for (k = 0, l = 0; k < G->num && l < H->num; k++) { ulong p = G->P[k].p; if (p == H->P[l].p) { ulong pef = n_pow(G->P[k].p, G->P[k].e - H->P[l].e); ulong a = x->log[k]; if (a % pef) { flint_throw(FLINT_ERROR, "conrey_lower: conductor does not divide lower modulus %wu", H->q); } y->log[l] = a / pef; l++; } } _dirichlet_char_exp(y, H); } flint-3.1.3/src/dirichlet/char_mul.c000066400000000000000000000012521461254215100173270ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b) { ulong k; for (k = 0; k < G->num ; k++) c->log[k] = nmod_add(a->log[k], b->log[k], G->P[k].phi); c->n = nmod_mul(a->n, b->n, G->mod); } flint-3.1.3/src/dirichlet/char_next.c000066400000000000000000000014061461254215100175110ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" int dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G) { /* update index */ int k; for (k = G->num - 1; k >= 0; k--) { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] += 1; if (x->log[k] < G->P[k].phi.n) break; x->log[k] = 0; } /* return last index modified */ return k; } flint-3.1.3/src/dirichlet/char_next_primitive.c000066400000000000000000000031661461254215100216060ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" int dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G) { /* update index avoiding multiples of p except for first component if 8|q */ slong k; /* if (G->neven == 2) { x->n = nmod_mul(x->n, G->generators[0], G->mod); x->log[0]++; if (x->log[0] == 1) return 0; x->log[0] = 0; k = 1; } */ for (k = G->num - 1; k >= 0; k--) { #if 1 x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; if (x->log[k] % G->P[k].p == 0) { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; } if (x->log[k] < G->P[k].phi.n) break; if (x->log[k] == G->P[k].phi.n) x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] = 1; #else do { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; } while (x->log[k] % G->P[k].p == 0); if (x->log[k] < G->P[k].phi) break; if (x->log[k] == G->P[k].phi) x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] = 1; #endif } /* return last index modified */ return k; } flint-3.1.3/src/dirichlet/char_one.c000066400000000000000000000010611461254215100173110ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G) { ulong k; for (k = 0; k < G->num ; k++) x->log[k] = 0; x->n = 1; } flint-3.1.3/src/dirichlet/char_order.c000066400000000000000000000011571461254215100176510ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x) { ulong k, g; g = G->expo; for (k = 0; k < G->num; k++) g = n_gcd(g, G->PHI[k] * x->log[k]); return G->expo / g; } flint-3.1.3/src/dirichlet/char_parity.c000066400000000000000000000012471461254215100200460ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" int dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x) { int k, odd = 0; for (k = 0; k < G->num; k++) { if (k == 1 && G->neven == 2) continue; if (x->log[k] % 2) odd = 1 - odd; } return odd; } flint-3.1.3/src/dirichlet/char_pow.c000066400000000000000000000012211461254215100173330ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n) { ulong k; for (k = 0; k < G->num ; k++) c->log[k] = nmod_mul(a->log[k], n, G->P[k].phi); c->n = nmod_pow_ui(a->n, n, G->mod); } flint-3.1.3/src/dirichlet/char_print.c000066400000000000000000000012611461254215100176660ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t x) { slong k; if (G->num) flint_printf("[%wu", x->log[0]); else flint_printf("["); for (k = 1; k < G->num; k++) flint_printf(", %wu", x->log[k]); flint_printf("]"); } flint-3.1.3/src/dirichlet/chi.c000066400000000000000000000014431461254215100163020ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) { if (n_gcd(G->q, n) > 1) { return DIRICHLET_CHI_NULL; } else { ulong v; dirichlet_char_t x; dirichlet_char_init(x, G); dirichlet_char_log(x, G, n); v = dirichlet_pairing_char(G, chi, x); dirichlet_char_clear(x); return v; } } flint-3.1.3/src/dirichlet/chi_vec.c000066400000000000000000000016321461254215100171370ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { if (2 * nv > G->phi_q) dirichlet_chi_vec_loop(v, G, chi, nv); else dirichlet_chi_vec_primeloop(v, G, chi, nv); } void dirichlet_chi_vec_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) { if (2 * nv > G->phi_q) dirichlet_chi_vec_loop_order(v, G, chi, order, nv); else dirichlet_chi_vec_primeloop_order(v, G, chi, order, nv); } flint-3.1.3/src/dirichlet/chi_vec_loop.c000066400000000000000000000034471461254215100201760ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" static void dirichlet_exponents_char(ulong * expo, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order) { slong k; ulong factor = G->expo / order; for (k = 0; k < G->num; k++) /* no overflow: log[k] < phi[k] and G->expo = phi[k] * PHI[k] */ expo[k] = (chi->log[k] * G->PHI[k]) / factor; } /* loop over whole group */ void dirichlet_chi_vec_loop_order(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) { int j; ulong t; slong k; ulong expo[MAX_FACTORS]; dirichlet_char_t x; nmod_t o; dirichlet_char_init(x, G); dirichlet_char_one(x, G); dirichlet_exponents_char(expo, G, chi, order); nmod_init(&o, order); for (k = 0; k < nv; k++) v[k] = DIRICHLET_CHI_NULL; t = v[1] = 0; while ( (j = dirichlet_char_next(x, G)) >= 0 ) { /* exponents were modified up to j */ for (k = G->num - 1; k >= j; k--) t = nmod_add(t, expo[k], o); if (x->n < nv) v[x->n] = t; } /* fix result outside primes */ /* dirichlet_vec_set_null(v, G, nv);*/ /* copy outside modulus */ for (k = G->q; k < nv ; k++ ) v[k] = v[k - G->q]; dirichlet_char_clear(x); } void dirichlet_chi_vec_loop(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { dirichlet_chi_vec_loop_order(v, G, chi, G->expo, nv); } flint-3.1.3/src/dirichlet/chi_vec_primeloop.c000066400000000000000000000043521461254215100212270ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" static void dirichlet_chi_vec_evenpart(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) { ulong mult = G->expo / order; if (G->neven >= 1 && chi->log[0]) { ulong x, c3 = G->PHI[0] / mult; for (x = 3; x < nv; x += 4) v[x] = c3; } if (G->neven == 2 && chi->log[1]) { ulong x, g, vx, xp, c4; nmod_t pe, o; nmod_init(&o, order); pe = G->P[1].pe; g = G->P[1].g; vx = c4 = (chi->log[1] * G->PHI[1]) / mult; for (x = g; x > 1;) { for (xp = x; xp < nv; xp += pe.n) v[xp] = nmod_add(v[xp], vx, o); for (xp = pe.n - x; xp < nv; xp += pe.n) v[xp] = nmod_add(v[xp], vx, o); x = nmod_mul(x, g, pe); vx = nmod_add(vx, c4, o); } } } /* loop over primary components */ void dirichlet_chi_vec_primeloop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) { slong k, l; ulong mult = G->expo / order; nmod_t o; nmod_init(&o, order); for (k = 0; k < nv; k++) v[k] = 0; if (G->neven) dirichlet_chi_vec_evenpart(v, G, chi, order, nv); for (l = G->neven; l < G->num; l++) { dirichlet_prime_group_struct P = G->P[l]; /* FIXME: there may be some precomputed dlog in P if needed */ if (P.dlog == NULL) dlog_vec_add(v, nv, P.g, (chi->log[l] * G->PHI[l]) / mult, P.pe, P.phi.n, o); else dlog_vec_add_precomp(v, nv, P.dlog, P.g, (chi->log[l] * G->PHI[l]) / mult, P.pe, P.phi.n, o); } dirichlet_vec_set_null(v, G, nv); } void dirichlet_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { dirichlet_chi_vec_primeloop_order(v, G, chi, G->expo, nv); } flint-3.1.3/src/dirichlet/group_clear.c000066400000000000000000000010761461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_group_clear(dirichlet_group_t G) { flint_free(G->P); flint_free(G->generators); flint_free(G->PHI); } flint-3.1.3/src/dirichlet/group_dlog_precompute.c000066400000000000000000000023011461254215100221350ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_prime_group_dlog_precompute(dirichlet_prime_group_struct * P, ulong num) { P->dlog = flint_malloc(sizeof(dlog_precomp_t)); /* even if e = 1 use modpe struct, more flexible if reused in bigger group */ dlog_precomp_modpe_init(P->dlog, P->g, P->p, P->e, P->pe.n, num); } void dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num) { slong k; for (k = 0; k < G->num; k++) { if (G->P[k].dlog == NULL) dirichlet_prime_group_dlog_precompute(&G->P[k], num); } } void dirichlet_group_dlog_clear(dirichlet_group_t G) { slong k; for (k = 0; k < G->num; k++) { if (G->P[k].dlog != NULL) { dlog_precomp_clear(G->P[k].dlog); flint_free(G->P[k].dlog); G->P[k].dlog = NULL; } } } flint-3.1.3/src/dirichlet/group_init.c000066400000000000000000000125171461254215100177220ustar00rootroot00000000000000/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" /* see https://arxiv.org/abs/2206.14193 */ static ulong primitive_root_p_and_p2(ulong p) { if (p == 40487) return 10; #if FLINT_BITS == 64 if (p == UWORD(6692367337)) return 7; if (p > UWORD(10000000000000000)) flint_throw(FLINT_ERROR, "p > 10^16 not implemented in %s\n", __func__); #endif return n_primitive_root_prime(p); } void dirichlet_prime_group_init(dirichlet_prime_group_struct * P, ulong p, int e) { P->p = p; P->e = e; if (p == 2 || p == 4) { P->p = 2; nmod_init(&P->pe, UWORD(1) << e); if (p == 2) { P->e = 2; nmod_init(&P->phi, 2); P->g = (UWORD(1) << e) - 1; } else { nmod_init(&P->phi, UWORD(1) << (e - 2)); P->g = 5; } } else { ulong pe1; pe1 = n_pow(p, e - 1); nmod_init(&P->phi, (p-1) * pe1); nmod_init(&P->pe, p * pe1); P->g = primitive_root_p_and_p2(p); } P->dlog = NULL; } static void dirichlet_group_lift_generators(dirichlet_group_t G) { slong k; dirichlet_prime_group_struct * P = G->P; G->expo = G->phi_q = 1; if (G->neven) { G->phi_q = G->q_even / 2; G->expo = P[G->neven - 1].phi.n; } for (k = G->neven; k < G->num; k++) { G->phi_q *= P[k].phi.n; G->expo *= P[k].phi.n / n_gcd(G->expo, P[k].p - 1); } for (k = 0; k < G->num; k++) { nmod_t pe; ulong qpe, v; G->PHI[k] = G->expo / G->P[k].phi.n; /* lift generators mod q */ /* u * p^e + v * q/p^e = 1 -> g mod q = 1 + (g-1) * v*(q/p^e) */ pe = G->P[k].pe; qpe = G->q / pe.n; if (G->q < G->P[k].pe.n) { flint_printf("lift generator %wu from %wu to %wu e=%wu\n", G->P[k].g, G->P[k].pe.n, G->q, G->P[k].e); } v = nmod_inv(qpe % pe.n, pe); /* v * qpe < q */ G->generators[k] = (1 + nmod_mul(G->P[k].g-1, v * qpe, G->mod)) % G->q; } } int dirichlet_group_init(dirichlet_group_t G, ulong q) { slong k; ulong e2; n_factor_t fac; G->q = q; nmod_init(&G->mod, q); e2 = n_remove(&q, 2); G->q_even = UWORD(1) << e2; /* number of components at p=2 */ G->neven = (e2 >= 3) ? 2 : (e2 == 2) ? 1 : 0; /* warning: only factor odd part */ n_factor_init(&fac); n_factor(&fac, q, 1); #if FLINT_BITS == 64 for (k = 0; k < fac.num; k++) if (fac.p[k] > UWORD(10000000000000000)) return 0; #endif G->num = fac.num + G->neven; G->P = flint_malloc(G->num * sizeof(dirichlet_prime_group_struct)); G->generators = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); /* even part */ if (G->neven >= 1) dirichlet_prime_group_init(&G->P[0], 2, e2); if (G->neven == 2) dirichlet_prime_group_init(&G->P[1], 4, e2); /* odd part */ G->rad_q = 1; for (k = G->neven; k < G->num; k++) { ulong p, e; p = fac.p[k - G->neven]; e = fac.exp[k - G->neven]; G->rad_q *= p; dirichlet_prime_group_init(&G->P[k], p, e); } dirichlet_group_lift_generators(G); return 1; } void dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h) { int s[15]; /* selected components */ slong k, j, e2; H->q = h; nmod_init(&H->mod, h); /* even components */ e2 = n_remove(&h, 2); H->q_even = UWORD(1) << e2; s[0] = s[1] = 0; j = 0; if (e2 >= 2) s[j++] = 2; if (e2 >= 3) s[j++] = e2; H->neven = j; /* odd components */ for (k = G->neven; k < G->num; k++) { ulong p = G->P[k].p; s[k] = n_remove(&h, p); if (s[k] > 0) { j++; H->rad_q *= p; } } H->num = j; H->P = flint_malloc(j * sizeof(dirichlet_prime_group_struct)); H->generators = flint_malloc(j * sizeof(ulong)); H->PHI = flint_malloc(j * sizeof(ulong)); j = 0; for (k = 0; k < H->neven; k++) { H->P[j] = G->P[k]; if (H->q_even < G->q_even) { nmod_init(&H->P[j].pe, H->q_even); H->P[j].e = s[k]; if (k == 0) H->P[j].g = H->q_even - 1; else nmod_init(&H->P[j].phi, H->q_even / 4); } j++; } for (k = G->neven; k < G->num; k++) { if (s[k]) { H->P[j] = G->P[k]; if (s[k] < G->P[k].e) { ulong pf, p = H->P[j].p; H->P[j].e = s[k]; pf = n_pow(p, s[k]); nmod_init(&H->P[j].pe, pf); nmod_init(&H->P[j].phi, (p-1) * pf / p); } j++; } } dirichlet_group_lift_generators(H); } flint-3.1.3/src/dirichlet/group_num_primitive.c000066400000000000000000000015621461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong dirichlet_group_num_primitive(const dirichlet_group_t G) { if (G->q % 4 == 2) return 0; else { slong k; ulong n = 1; /* no overflow since result < G->q */ for (k = (G->neven == 2); k < G->num; k++) { ulong p = G->P[k].p, e = G->P[k].e; if (e == 1) n *= p - 2; else n *= (p * (p - 2) + 1) * n_pow(p, e - 2); } return n; } } flint-3.1.3/src/dirichlet/index_char.c000066400000000000000000000024411461254215100176420ustar00rootroot00000000000000/*============================================================================= This file is part of ARB. ARB is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ARB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ARB; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =============================================================================*/ /****************************************************************************** Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include "dirichlet.h" ulong dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x) { slong k; ulong j = 0; for (k = 0; k < G->num; k++) j = j * G->P[k].phi.n + x->log[k]; return j; } flint-3.1.3/src/dirichlet/inlines.c000066400000000000000000000006621461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define DIRICHLET_INLINES_C #include "dirichlet.h" flint-3.1.3/src/dirichlet/pairing.c000066400000000000000000000015161461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n) { ulong x; dirichlet_char_t a, b; if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) return DIRICHLET_CHI_NULL; dirichlet_char_init(a, G); dirichlet_char_init(b, G); dirichlet_char_log(a, G, m); dirichlet_char_log(b, G, n); x = dirichlet_pairing_char(G, a, b); dirichlet_char_clear(a); dirichlet_char_clear(b); return x; } flint-3.1.3/src/dirichlet/pairing_char.c000066400000000000000000000013271461254215100201660ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong dirichlet_pairing_char(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_char_t x) { ulong v = 0, k; nmod_t order; nmod_init(&order, G->expo); for (k = 0; k < G->num; k++) v = nmod_add(v, G->PHI[k] * nmod_mul(chi->log[k], x->log[k], G->P[k].phi), order); return v; } flint-3.1.3/src/dirichlet/profile/000077500000000000000000000000001461254215100170315ustar00rootroot00000000000000flint-3.1.3/src/dirichlet/profile/p-conrey.c000066400000000000000000000106061461254215100207340ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "dirichlet.h" #include "profiler.h" #define LOG 0 #define CSV 1 #define JSON 2 typedef ulong (*do_f) (ulong q1, ulong q2); static ulong do_gcd(ulong q1, ulong q2) { ulong n, q, k; for (n = 0, q = q1; q <= q2; q++) for (k = 1; k < q; k++) n += (n_gcd(k, q) == 1); return n; } static ulong do_char(ulong q1, ulong q2) { ulong n, q; for (n = 0, q = q1; q <= q2; q++) { dirichlet_group_t G; dirichlet_char_t x; dirichlet_group_init(G, q); dirichlet_char_init(x, G); dirichlet_char_one(x, G); n++; for (; dirichlet_char_next(x, G) >= 0; n++); dirichlet_char_clear(x); dirichlet_group_clear(G); } return n; } static ulong do_gcdpluscond(ulong q1, ulong q2) { ulong n, q, k; for (n = 0, q = q1; q <= q2; q++) { dirichlet_group_t G; dirichlet_group_init(G, q); for (k = 1; k < q; k++) { /* known factors -> faster gcd */ slong i; if (G->q_even > 1 && k % 2 == 0) continue; for (i = G->neven; i < G->num; i++) if (k % G->P[i].p == 0) break; if (i == G->num) dirichlet_conductor_ui(G, k); } n += G->phi_q; dirichlet_group_clear(G); } return n; } static ulong do_charpluscond(ulong q1, ulong q2) { ulong n, q; for (n = 0, q = q1; q <= q2; q++) { dirichlet_group_t G; dirichlet_char_t x; dirichlet_group_init(G, q); dirichlet_char_init(x, G); dirichlet_char_one(x, G); n++; for (; dirichlet_char_next(x, G) >= 0; n++) dirichlet_conductor_char(G, x); dirichlet_char_clear(x); dirichlet_group_clear(G); } return n; } static ulong do_charplusorder(ulong q1, ulong q2) { ulong n, q; for (n = 0, q = q1; q <= q2; q++) { dirichlet_group_t G; dirichlet_char_t x; dirichlet_group_init(G, q); dirichlet_char_init(x, G); dirichlet_char_one(x, G); n++; for (; dirichlet_char_next(x, G) >= 0; n++) dirichlet_order_char(G, x); dirichlet_char_clear(x); dirichlet_group_clear(G); } return n; } int main(int argc, char *argv[]) { int out; int l, nf = 5; do_f func[5] = { do_gcd, do_char, do_gcdpluscond, do_charpluscond, do_charplusorder }; char * name[5] = { "gcd", "char", "gcd + cond", "char + cond", "char + order" }; int i, ni = 5; ulong qmin[5] = { 2, 1000, 10000, 100000, 1000000 }; ulong qmax[5] = { 500, 3000, 11000, 100100, 1000010 }; if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } if (out == CSV) flint_printf("# %-12s, %7s, %7s, %7s\n","name", "qmin", "qmax", "time"); for (i = 0; i < ni; i++) { if (out == LOG) { flint_printf("loop over all (Z/q)* for %wu<=q<=%wu\n", qmin[i], qmax[i]); } for (l = 0; l < nf; l++) { if (out == LOG) flint_printf("%-14s ... ",name[l]); else if (out == CSV) flint_printf("%-12s, %7d, %7d, ",name[l],qmin[i],qmax[i]); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"qmin\": %d, \"qmax\": %d, \"time\": ", name[l],qmin[i],qmax[i]); TIMEIT_ONCE_START (func[l])(qmin[i], qmax[i]); TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } } flint_cleanup(); return 0; } flint-3.1.3/src/dirichlet/test/000077500000000000000000000000001461254215100163505ustar00rootroot00000000000000flint-3.1.3/src/dirichlet/test/main.c000066400000000000000000000015641461254215100174460ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-char.c" #include "t-properties.c" #include "t-vec.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(dirichlet_char), TEST_FUNCTION(dirichlet_properties), TEST_FUNCTION(dirichlet_vec) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/dirichlet/test/t-char.c000066400000000000000000000114141461254215100176730ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "dirichlet.h" TEST_FUNCTION_START(dirichlet_char, state) { slong iter; for (iter = 0; iter < 3000 * 0.1 * flint_test_multiplier(); iter++) { dirichlet_group_t G; dirichlet_char_t x, y; ulong q, n, k, sum; slong ref; q = 1 + n_randint(state, 1000 * (1 + iter / 100)); dirichlet_group_init(G, q); dirichlet_char_init(x, G); dirichlet_char_init(y, G); /* check group size and elements */ dirichlet_char_one(x, G); sum = 1; for (n = 1; dirichlet_char_next(x, G) >= 0; n++) sum += x->n * x->n; if (FLINT_BITS == 64 || q < 1024) { /* use https://oeis.org/A053818 to check all elements * are gone through */ ref = (q % 4 == 2) ? -2 : 1; for (k = (G->neven == 2); k < G->num; k++) ref = - ref * G->P[k].p; ref = ( G->phi_q * (2 * q * q + ref) ) / 6; if (n != G->phi_q) { flint_printf("FAIL: group size\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("phi(q) = %wu\n\n", G->phi_q); flint_printf("loop index = %wu\n\n", n); flint_abort(); } if (sum != ref && q > 1) { flint_printf("FAIL: sum test\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("sum k^2 = %wu\n\n", ref); flint_printf("sum obtained = %wu\n\n", sum); flint_abort(); } } if (q % 4 != 2) { dirichlet_char_first_primitive(x, G); for (n = 1; dirichlet_char_next_primitive(x, G) >= 0; n++); ref = dirichlet_group_num_primitive(G); if (n != ref) { flint_printf("FAIL: number of primitive elements\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("# primitive = %wu\n\n", ref); flint_printf("loop index = %wu\n\n", n); flint_abort(); } /* some random elements, check log and exp */ for (n = 0; n < 30; n++) { slong k; ulong m; for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); dirichlet_char_log(x, G, m); if (m != _dirichlet_char_exp(x, G)) { flint_printf("FAIL: char log and exp\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("char = "); dirichlet_char_print(G, x); flint_printf("\n\nnumber = %wu\n\n", x->n); flint_abort(); } for (k = 0; k < G->num; k++) x->log[k] = n_randint(state, G->P[k].phi.n); m = _dirichlet_char_exp(x, G); dirichlet_char_log(y, G, m); if (!dirichlet_char_eq_deep(G, x, y)) { flint_printf("FAIL: char exp and log\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("char = "); dirichlet_char_print(G, x); flint_printf("\n\nm = %wu\n\n", m); flint_printf("log = "); dirichlet_char_print(G, y); flint_printf("\n\nnumber = %wu\n\n", y->n); flint_abort(); } dirichlet_char_next_primitive(x, G); m = x->n; if (m != _dirichlet_char_exp(x, G)) { flint_printf("FAIL: char number next primitive\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("char = "); dirichlet_char_print(G, y); flint_printf(", m = %wu\n\n", y->n); flint_printf("next primitive = "); dirichlet_char_print(G, x); flint_printf(", m = %wu\n\n", m); flint_printf("exp = %wu\n\n", x->n); flint_abort(); } } } dirichlet_char_clear(x); dirichlet_char_clear(y); dirichlet_group_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/dirichlet/test/t-properties.c000066400000000000000000000154061461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "dirichlet.h" static void check_eq(ulong p1, ulong p2, ulong q, ulong m, char * fct1, char * fct2) { if (p1 != p2) { flint_printf("FAIL:\n\n"); flint_printf("chi_%wu(%wu,.)\n\n", q, m); flint_printf("%s = %wu\n\n", fct1, p1); flint_printf("%s = %wu\n\n", fct2, p2); flint_abort(); } } static ulong random_divisor(flint_rand_t state, const dirichlet_group_t G) { ulong d; slong k; d = 1; for (k = (G->neven == 2); k < G->num; k++) d *= n_pow(G->P[k].p, n_randint(state, G->P[k].e)); return d; } TEST_FUNCTION_START(dirichlet_properties, state) { slong iter, bits; for (bits = 5; bits <= 30; bits += 5) { for (iter = 0; iter < 50; iter++) { dirichlet_group_t G; dirichlet_char_t chi, psi; ulong q, iter2; q = 2 + n_randint(state, 1 << bits); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_init(psi, G); /* check number char properties */ for (iter2 = 0; iter2 < 100; iter2++) { ulong m, n; ulong p1, p2, pairing, cm, cn, q2, q3; dirichlet_group_t G2, G3; dirichlet_char_t chi2, chi3; if (iter2 == 50) dirichlet_group_dlog_precompute(G, 5); /* one random character */ do m = n_randint(state, q); while (n_gcd(q, m) > 1); dirichlet_char_log(chi, G, m); p1 = dirichlet_order_ui(G, m); p2 = dirichlet_order_char(G, chi); check_eq(p1, p2, q, m, "order m", "order chi"); p1 = dirichlet_conductor_ui(G, m); p2 = dirichlet_conductor_char(G, chi); check_eq(p1, p2, q, m, "conductor m", "conductor chi"); p1 = dirichlet_parity_ui(G, m); p2 = dirichlet_parity_char(G, chi); check_eq(p1, p2, q, m, "parity m", "parity chi"); p1 = dirichlet_char_is_real(G, chi); p2 = (dirichlet_order_char(G, chi) <= 2); check_eq(p1, p2, q, m, "is_real", "(order <= 2)"); /* check index */ p1 = dirichlet_index_char(G, chi); dirichlet_char_index(psi, G, p1); if (!dirichlet_char_eq_deep(G, chi, psi)) { flint_printf("FAIL: index\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("chi = "); dirichlet_char_print(G, chi); flint_printf("\n\nindex(chi) = %wu\n\n", p1); flint_printf("psi(index) = %wu\n\n", psi->n); flint_printf("psi = "); dirichlet_char_print(G, psi); flint_printf("\n\n"); flint_abort(); } /* lift to higher modulus */ do { q2 = q * (1 + n_randint(state, 100)); } while (q2 % q); /* in case of overflow */ dirichlet_group_init(G2, q2); dirichlet_char_init(chi2, G2); dirichlet_char_lift(chi2, G2, chi, G); p1 = dirichlet_conductor_char(G, chi); p2 = dirichlet_conductor_char(G2, chi2); check_eq(p1, p2, q, m, "conductor chi", "conductor lift"); p1 = dirichlet_order_char(G, chi); p2 = dirichlet_order_char(G2, chi2); check_eq(p1, p2, q, m, "order chi", "order lift"); /* and lower */ dirichlet_char_lower(psi, G, chi2, G2); if (!dirichlet_char_eq_deep(G, chi, psi)) { flint_printf("FAIL: lift and lower back\n\n"); flint_printf("q = %wu\n\nchi = ", q); dirichlet_char_print(G, chi); flint_printf("\n\nq2 = %wu\n\nchi2 = ", q2); dirichlet_char_print(G2, chi2); flint_printf("\n\nq = %wu\n\npsi = ", q); dirichlet_char_print(G, psi); flint_printf("\n\n"); flint_abort(); } /* choose q3 s.t. conductor | q3 | q */ q3 = dirichlet_conductor_char(G, chi) * random_divisor(state, G); q3 = n_gcd(q, q3); /* discard if overflow */ if (q3 % p1 == 0) { dirichlet_group_init(G3, q3); dirichlet_char_init(chi3, G3); dirichlet_char_lower(chi3, G3, chi2, G2); p1 = dirichlet_conductor_char(G, chi); p2 = dirichlet_conductor_char(G3, chi3); check_eq(p1, p2, q, m, "conductor chi", "conductor lower"); p1 = dirichlet_order_char(G, chi); p2 = dirichlet_order_char(G3, chi3); check_eq(p1, p2, q, m, "order chi", "order lower"); dirichlet_char_clear(chi3); dirichlet_group_clear(G3); } dirichlet_char_clear(chi2); dirichlet_group_clear(G2); /* another random character */ do n = n_randint(state, q); while (n_gcd(q, n) > 1); dirichlet_char_log(psi, G, n); pairing = dirichlet_pairing(G, m, n); cn = dirichlet_chi(G, chi, n); cm = dirichlet_chi(G, psi, m); if (pairing != cn || pairing != cm) { flint_printf("FAIL: pairing\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("n = %wu\n\n", n); flint_printf("chi(m,n) = %wu\n\n", pairing); flint_printf("chi(m)(n) = %wu\n\n", cn); flint_printf("chi(n)(m) = %wu\n\n", cm); flint_abort(); } } dirichlet_group_dlog_clear(G); dirichlet_char_clear(chi); dirichlet_char_clear(psi); dirichlet_group_clear(G); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/dirichlet/test/t-vec.c000066400000000000000000000045231461254215100175360ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "dirichlet.h" static ulong vec_diff(ulong * v, ulong * ref, ulong nv) { ulong k; for (k = 1; k < nv; k++) if (ref[k] != v[k]) return k; return 0; } TEST_FUNCTION_START(dirichlet_vec, state) { ulong q; for (q = 2; q < 600; q ++) { dirichlet_group_t G; dirichlet_char_t chi; ulong * v1, * v2, nv, k; dirichlet_group_init(G, q); dirichlet_char_init(chi, G); nv = 100; v1 = flint_malloc(nv * sizeof(ulong)); v2 = flint_malloc(nv * sizeof(ulong)); dirichlet_char_one(chi, G); do { ulong order; dirichlet_chi_vec_loop(v1, G, chi, nv); dirichlet_chi_vec_primeloop(v2, G, chi, nv); if ((k = vec_diff(v1, v2, nv))) { flint_printf("FAIL: chi_%wu(%wu,%wu) [mod %wu]\n", q, chi->n, k, G->expo); flint_printf("vec_loop -> %wu\n", v1[k]); flint_printf("vec_primeloop -> %wu\n", v2[k]); flint_printf("pairing = %wu\n", dirichlet_pairing(G, chi->n, k)); flint_abort(); } order = dirichlet_order_char(G, chi); dirichlet_chi_vec_loop_order(v1, G, chi, order, nv); dirichlet_chi_vec_primeloop_order(v2, G, chi, order, nv); if ((k = vec_diff(v1, v2, nv))) { flint_printf("FAIL: chi_%wu(%wu,%wu) [mod %wu]\n", q, chi->n, k, order); flint_printf("vec_loop -> %wu\n", v1[k]); flint_printf("vec_primeloop -> %wu\n", v2[k]); flint_printf("pairing = %wu mod %wu\n", dirichlet_pairing(G, chi->n, k), G->expo); flint_abort(); } } while (dirichlet_char_next(chi, G) >= 0); flint_free(v1); flint_free(v2); dirichlet_group_clear(G); dirichlet_char_clear(chi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/dirichlet/ui_conductor.c000066400000000000000000000020701461254215100202310ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" ulong dirichlet_conductor_ui(const dirichlet_group_t G, ulong a) { slong k; ulong ap, cond; cond = 1; for (k = (G->neven == 2); k < G->num; k++) { ulong p; nmod_t pe; p = G->P[k].p; pe = G->P[k].pe; ap = a % pe.n; if (ap == 1) continue; if (p == 2) { cond = 4; if (a % 4 == 3) ap = pe.n - ap; } else { cond *= p; ap = nmod_pow_ui(ap, p - 1, pe); } while (ap != 1) { cond *= p; ap = nmod_pow_ui(ap, p, pe); } } return cond; } flint-3.1.3/src/dirichlet/ui_order.c000066400000000000000000000020461461254215100173470ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" /* order of an element knowing the factorization of a multiple */ ulong nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) { int k; ulong pe, ap, order = 1; for (k = 0; k < fac.num; k++) { pe = n_pow(fac.p[k], fac.exp[k]); ap = nmod_pow_ui(a, expo / pe, mod); while ( ap != 1) { ap = nmod_pow_ui(ap, fac.p[k], mod); order *= fac.p[k]; } } return order; } ulong dirichlet_order_ui(const dirichlet_group_t G, ulong a) { n_factor_t fac; n_factor_init(&fac); n_factor(&fac, G->expo, 1); return nmod_order_precomp(a, G->mod, G->expo, fac); } flint-3.1.3/src/dirichlet/ui_parity.c000066400000000000000000000011601461254215100175400ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" int dirichlet_parity_ui(const dirichlet_group_t G, ulong a) { int par; par = 0; if (G->neven && a % 4 == 3) par++; if (n_jacobi_unsigned(a, G->rad_q) == -1) par++; return par % 2; } flint-3.1.3/src/dirichlet/ui_vec_set_null.c000066400000000000000000000013551461254215100207200ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dirichlet.h" void dirichlet_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv) { slong k, l; if (G->q_even > 1) { for (k = 2; k < nv; k += 2) v[k] = -1; } for (l = G->neven; l < G->num; l++) { ulong p = G->P[l].p; for (k = p; k < nv; k += p) v[k] = DIRICHLET_CHI_NULL; } } flint-3.1.3/src/dlog.h000066400000000000000000000163401461254215100145240ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef DLOG_H #define DLOG_H #ifdef DLOG_INLINES_C #define DLOG_INLINE #else #define DLOG_INLINE static inline #endif #include "ulong_extras.h" #ifdef __cplusplus extern "C" { #endif enum { DLOG_MODPE, DLOG_CRT, DLOG_POWER, DLOG_BSGS, DLOG_TABLE, DLOG_23 }; typedef struct dlog_precomp_struct dlog_precomp_struct; typedef struct dlog_precomp_struct * dlog_precomp_ptr; /* log in (1+pZ/p^eZ), e small: use recursion formulas * could use padic log instead but exponent is small * for ulongs */ typedef struct { ulong inv1p; /* 1 / (1 + p) */ ulong invloga1; /* 1 / log(a^(p-1),1+p) */ } dlog_1modpe_struct; typedef dlog_1modpe_struct dlog_1modpe_t[1]; /* log in (Z/p^eZ)^* */ typedef struct { ulong p; ulong e; ulong pe1; /* p^(e-1) */ ulong inva; nmod_t pe; dlog_precomp_struct * modp; dlog_1modpe_t modpe; } dlog_modpe_struct; typedef dlog_modpe_struct dlog_modpe_t[1]; /* all logs precomputed in (Z/modZ)^ast */ typedef struct { ulong mod; ulong * table; } dlog_table_struct; typedef dlog_table_struct dlog_table_t[1]; /* bsgs table, already in flint */ typedef struct apow { ulong k; ulong ak; } apow_t; int apow_cmp(const apow_t * x, const apow_t * y); typedef struct { nmod_t mod; ulong m; ulong am; ulong g; apow_t * table; } dlog_bsgs_struct; typedef dlog_bsgs_struct dlog_bsgs_t[1]; /* typedef bsgs_t dlog_bsgs_t; */ /* Pollard rho */ typedef struct { ulong a; nmod_t n; nmod_t mod; int nisprime; } dlog_rho_struct; typedef dlog_rho_struct dlog_rho_t[1]; /* CRT decomposition (Pohlig-Hellman) */ typedef struct { nmod_t mod; nmod_t n; ulong num; ulong * expo; ulong * crt_coeffs; dlog_precomp_ptr pre; } dlog_crt_struct; typedef dlog_crt_struct dlog_crt_t[1]; /* dlog when generator has prime power order */ typedef struct { nmod_t mod; ulong p; ulong e; ulong * apk; dlog_precomp_struct * pre; } dlog_power_struct; typedef dlog_power_struct dlog_power_t[1]; typedef ulong dlog_order23_t[1]; /* generic decomposition */ /*typedef */ struct dlog_precomp_struct { int type; ulong cost; union { dlog_table_t table; dlog_bsgs_t bsgs; dlog_crt_t crt; dlog_power_t power; dlog_modpe_t modpe; dlog_order23_t order23; } t; }; typedef dlog_precomp_struct dlog_precomp_t[1]; void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num); void dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num); void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num); void dlog_precomp_clear(dlog_precomp_t pre); ulong dlog_precomp(const dlog_precomp_t pre, ulong b); ulong dlog_order23_init(dlog_order23_t t, ulong a); ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod); ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num); ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num); ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m); void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e, nmod_t pe); void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n); /*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ ulong dlog_once(ulong b, ulong a, const nmod_t mod, ulong n); DLOG_INLINE void dlog_order23_clear(dlog_order23_t t) { return; } DLOG_INLINE void dlog_table_clear(dlog_table_t t) { flint_free(t->table); } void dlog_crt_clear(dlog_crt_t t); DLOG_INLINE void dlog_power_clear(dlog_power_t t) { flint_free(t->apk); dlog_precomp_clear(t->pre); flint_free(t->pre); } DLOG_INLINE void dlog_modpe_clear(dlog_modpe_t t) { dlog_precomp_clear(t->modp); flint_free(t->modp); } DLOG_INLINE void dlog_bsgs_clear(dlog_bsgs_t t) { flint_free(t->table); } DLOG_INLINE void dlog_rho_clear(dlog_rho_t t) { return; } DLOG_INLINE ulong dlog_bsgs_size(ulong n, ulong num) { if (2 * num < n) return (1 + n_sqrt(n)) * (1 + n_sqrt(num)); else return n; } /*#define dlog_bsgs_clear(t) bsgs_table_clear(t)*/ ulong dlog_order23(const dlog_order23_t t, ulong b); ulong dlog_table(const dlog_table_t t, ulong b); ulong dlog_crt(const dlog_crt_t t, ulong b); ulong dlog_power(const dlog_power_t t, ulong b); ulong dlog_modpe(const dlog_modpe_t t, ulong b); ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); ulong dlog_rho(const dlog_rho_t t, ulong b); ulong dlog_1modpe_1modp(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe); ulong dlog_1modpe(const dlog_1modpe_t t, ulong b1, ulong p, ulong e, nmod_t pe); ulong dlog_mod2e_1mod4(ulong b1, ulong e, ulong inva, nmod_t pe); ulong dlog_mod2e(const dlog_modpe_t t, ulong b); /*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ #define DLOG_SMALL_LIM 50 #define DLOG_TABLE_LIM 50 #define DLOG_TABLE_P_LIM 50 #define DLOG_TABLE_MODPE_LIM 50 #define DLOG_TABLE_PE_LIM 50 #define DLOG_TABLE_N_LIM 50 #define DLOG_BSGS_LIM 500 #define DLOG_LOOP_MAX_FACTOR 6 #define DLOG_G_SMALL 0 #define DLOG_G_BIG 1 void dlog_n_factor_group(n_factor_t * fac, ulong bound); #define DLOG_NOT_FOUND UWORD_MAX #define DLOG_NONE UWORD_MAX ulong dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry); void dlog_vec_fill(ulong * v, ulong nv, ulong x); void dlog_vec_set_not_found(ulong *v, ulong nv, nmod_t mod); void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_eratos_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_eratos(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/dlog/000077500000000000000000000000001461254215100143475ustar00rootroot00000000000000flint-3.1.3/src/dlog/1modpe.c000066400000000000000000000013171461254215100157020ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_1modpe(const dlog_1modpe_t t, ulong b1, ulong p, ulong e, nmod_t pe) { if (e == 1) return 0; else { ulong logb1; logb1 = dlog_1modpe_1modp(b1, p, e, t->inv1p, pe); /* only need mod p^(e-1) */ return nmod_mul(logb1, t->invloga1, pe); } } flint-3.1.3/src/dlog/1modpe_init.c000066400000000000000000000016171461254215100167300ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e, nmod_t pe) { if (e == 1) { t->inv1p = 1; t->invloga1 = 0; } else { ulong loga1; if (a1 == 1) flint_throw(FLINT_ERROR, __func__); t->inv1p = nmod_inv(1 + p, pe); /* 1 - p + p^2 - ... */ loga1 = dlog_1modpe_1modp(a1, p, e, t->inv1p, pe); /* only need inverse mod p^(e-1) but does not hurt */ t->invloga1 = nmod_inv(loga1, pe); } } flint-3.1.3/src/dlog/1modpe_mod1p.c000066400000000000000000000017331461254215100170040ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" /* for odd prime p, assume b1 = 1 mod p */ ulong dlog_1modpe_1modp(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe) { int f; ulong x, xf, pf, pf1; pf1 = 1; pf = p; x = 0; for (f = 1; f < e; f++) { if (b1 % pf != 1) { flint_throw(FLINT_ERROR, "ERROR dlog_1modpe_1modp: %wu %% %wu != 1 mod %wu\n\n", b1, pf, pe.n); } xf = (b1 - 1) / pf; xf = (xf % p) * pf1; x += xf; b1 = nmod_mul(b1, nmod_pow_ui(inv1p, xf, pe), pe); pf1 = pf; pf *= p; } return x; } flint-3.1.3/src/dlog/bsgs.c000066400000000000000000000017501461254215100154540ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod.h" #include "dlog.h" ulong dlog_bsgs(const dlog_bsgs_t t, ulong b) { ulong i; apow_t c, * x; c.ak = b; for (i = 0; i < t->g; i++) { x = bsearch(&c, t->table, t->m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); if (x != NULL) return i * t->m + x->k; c.ak = nmod_mul(c.ak, t->am, t->mod); } flint_throw(FLINT_ERROR, "Exception (dlog_bsgs). discrete log not found.\n" " table size %wu, cosize %wu mod %wu. %wu not found (a^-m=%wu)\n", t->m, t->g, t->mod.n, b, t->am); } flint-3.1.3/src/dlog/bsgs_init.c000066400000000000000000000020451461254215100164750ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod.h" #include "dlog.h" int apow_cmp(const apow_t * x, const apow_t * y) { return (x->ak < y->ak) ? -1 : (x->ak > y->ak); } ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) { ulong k, ak; if (m >= n) m = n; t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); nmod_init(&t->mod, mod); t->m = m; t->g = n / m + 1; for (k = 0, ak = 1; k < m; k++) { t->table[k].k = k; t->table[k].ak = ak; ak = nmod_mul(ak, a, t->mod); } t->am = nmod_inv(ak, t->mod); qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); return t->g; } flint-3.1.3/src/dlog/crt.c000066400000000000000000000016031461254215100153030ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_crt(const dlog_crt_t t, ulong b) { int k; ulong r = 0; for (k = 0; k < t->num; k++) { ulong bk, rk; bk = nmod_pow_ui(b, t->expo[k], t->mod); rk = dlog_precomp(t->pre + k, bk); #if 0 flint_printf("##[crt-%d]: log(%wu)=log(%wu^%wu) = %wu [size %wu mod %wu]\n", k, bk, b, t->expo[k], rk, t->n/t->expo[k], t->mod); #endif r = nmod_add(r, nmod_mul(t->crt_coeffs[k], rk, t->n), t->n); } return r; } flint-3.1.3/src/dlog/crt_clear.c000066400000000000000000000011271461254215100164520ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_crt_clear(dlog_crt_t t) { int k; flint_free(t->expo); flint_free(t->crt_coeffs); for (k = 0; k < t->num; k++) dlog_precomp_clear(t->pre + k); flint_free(t->pre); } flint-3.1.3/src/dlog/crt_init.c000066400000000000000000000031241461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) { int k; n_factor_t fac; ulong * M, * u; ulong cost = 0; n_factor_init(&fac); n_factor(&fac, n, 1); t->num = fac.num; nmod_init(&t->mod,mod); nmod_init(&t->n, n); M = t->expo = flint_malloc(t->num * sizeof(ulong)); u = t->crt_coeffs = flint_malloc(t->num * sizeof(ulong)); t->pre = flint_malloc(t->num * sizeof(dlog_precomp_struct)); for (k = 0; k < t->num; k++) { ulong p, e, mk; p = fac.p[k]; e = fac.exp[k]; if (0 && mod % p == 0) { flint_throw(FLINT_ERROR, "dlog_crt_init: modulus must be prime to order.\n"); } mk = n_pow(p, e); M[k] = n / mk; u[k] = nmod_mul(M[k], n_invmod(M[k] % mk, mk), t->n); /* depends on the power */ #if 0 flint_printf("[sub-crt -- init for size %wu mod %wu]\n", mk, mod); #endif dlog_precomp_pe_init(t->pre + k, nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); cost += t->pre[k].cost; } #if 0 if (cost > 500) flint_printf("[crt init for size %wu mod %wu -> cost %wu]\n", n,mod,cost); #endif return cost; } flint-3.1.3/src/dlog/factor_group.c000066400000000000000000000022631461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" /* group components up to bound and return cofactor */ void dlog_n_factor_group(n_factor_t * fac, ulong bound) { int i, j, k; ulong m[FLINT_MAX_FACTORS_IN_LIMB]; ulong c = 1; i = 0; for (k = fac->num - 1; k >= 0; k--) { ulong qe = n_pow(fac->p[k], fac->exp[k]); if (qe > bound) c *= qe; else { /* try to insert somewhere in m */ for (j = 0; j < i && (m[j] * qe > bound); j++); if (j == i) m[i++] = qe; else m[j] *= qe; } } for (j = 0; j < i; j++) { fac->p[j] = m[j]; fac->exp[j] = DLOG_G_SMALL; } if (c > 1) { fac->p[i] = c; fac->exp[i] = DLOG_G_BIG; i++; } fac->num = i; } flint-3.1.3/src/dlog/mod2e.c000066400000000000000000000021441461254215100155220ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_mod2e_1mod4(ulong b1, ulong e, ulong inv5, nmod_t pe) { slong f; ulong pf1, pf, x, xf; pf1 = 1; pf = 4; x = 0; for (f = 2; f < e; f++) { if (b1 % pf != 1) { flint_throw(FLINT_ERROR, "ERROR dlog_mod2e: %wu %% %wu != 1 mod %wu\n\n", b1, pf, pe.n); } xf = (b1 - 1) / pf; xf = (f == 2) ? xf % 4 : (xf % 2) * (pf1 / 2); b1 = nmod_mul(b1, nmod_pow_ui(inv5, xf, pe), pe); x += xf; pf1 = pf; pf *= 2; } return x; } ulong dlog_mod2e(const dlog_modpe_t t, ulong b1) { if (t->e == 2) return (b1 % 4) == 3; else return dlog_mod2e_1mod4(b1, t->e, t->inva, t->pe); } flint-3.1.3/src/dlog/modpe.c000066400000000000000000000020321461254215100156140ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_modpe(const dlog_modpe_t t, ulong b) { ulong x; if (t->p == 2) return dlog_mod2e(t, b); x = dlog_precomp(t->modp, b % t->p); if (t->e > 1) { ulong b1, y; #if 0 b1 = nmod_mul(b, nmod_pow_ui(t->inva, x, t->pe), t->pe); y = dlog_1modpe(t->modpe.rec, b1, t->p, t->e, t->pe); y = y % t->pe1; x = x + (t->p - 1) * y; #else b1 = nmod_pow_ui(b, t->p - 1, t->pe); y = dlog_1modpe(t->modpe, b1, t->p, t->e, t->pe); y = y % t->pe1; x = n_submod(x, y % (t->p - 1), t->p - 1); x = y + t->pe1 * x; #endif } return x; } flint-3.1.3/src/dlog/modpe_init.c000066400000000000000000000022111461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" /* todo: recursion could be made quadratic (not very useful for ulongs) */ ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) { ulong a1; t->p = p; t->e = e; nmod_init(&t->pe, pe); t->inva = nmod_inv(a, t->pe); if (p == 2) { t->modp = NULL; t->pe1 = (e <= 2) ? 2 : pe / 4; t->modpe->inv1p = t->inva; t->modpe->invloga1 = 1; return e - 2; } else { t->modp = flint_malloc(sizeof(dlog_precomp_struct)); t->pe1 = pe / p; dlog_precomp_n_init(t->modp, a, p, p - 1, num); a1 = nmod_pow_ui(a, p - 1, t->pe); dlog_1modpe_init(t->modpe, a1, p, e, t->pe); return t->modp->cost + e; } } flint-3.1.3/src/dlog/once.c000066400000000000000000000020141461254215100154340ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) { if (b == 1) return 0; if (n < 50) { slong k; ulong ak = 1; for (k = 0; k < n; k++) { if (ak == b) return k; ak = nmod_mul(ak, a, mod); } flint_throw(FLINT_ERROR, "(dlog_once): log(%wu,%wu) mod %wu not found (size %wu)\n", b, a, mod.n, n); } else { ulong l; dlog_precomp_t pre; dlog_precomp_n_init(pre, a, mod.n, n, 1); l = dlog_precomp(pre, b); dlog_precomp_clear(pre); return l; } } flint-3.1.3/src/dlog/order23.c000066400000000000000000000007621461254215100160000ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" ulong dlog_order23(const dlog_order23_t t, ulong b) { return (b == *t) ? 1 : (b == 1) ? 0 : 2; } flint-3.1.3/src/dlog/order23_init.c000066400000000000000000000007371461254215100170250ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" ulong dlog_order23_init(dlog_order23_t t, ulong a) { * t = a; return 0; } flint-3.1.3/src/dlog/power.c000066400000000000000000000016061461254215100156520ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_power(const dlog_power_t t, ulong b) { int k; ulong x, pk[30]; /* 3^30*2+1, 2^30*3+1 are primes */ pk[0] = 1; for (k = 1; k < t->e; k++) pk[k] = pk[k-1] * t->p; x = 0; for(k = 0; k < t->e; k++) { ulong bk, xk; bk = nmod_pow_ui(b, pk[t->e-1-k], t->mod); xk = dlog_precomp(t->pre, bk); b = nmod_mul(b, nmod_pow_ui(t->apk[k], xk, t->mod), t->mod); x += xk * pk[k]; /* cannot overflow */ } return x; } flint-3.1.3/src/dlog/power_init.c000066400000000000000000000016171461254215100166770ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) { int k; nmod_init(&t->mod, mod); t->p = p; t->e = e; t->apk = flint_malloc(e * sizeof(ulong)); t->pre = flint_malloc(sizeof(dlog_precomp_struct)); t->apk[0] = nmod_inv(a, t->mod); for (k = 1; k < e; k++) t->apk[k] = nmod_pow_ui(t->apk[k-1], p, t->mod); dlog_precomp_p_init(t->pre, nmod_inv(t->apk[e-1], t->mod), mod, p, e * num); return e * t->pre->cost; } flint-3.1.3/src/dlog/precomp.c000066400000000000000000000020241461254215100161560ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" ulong dlog_precomp(const dlog_precomp_t pre, ulong b) { if (b == 1) return 0; switch (pre->type) { case DLOG_MODPE: return dlog_modpe(pre->t.modpe, b); case DLOG_CRT: return dlog_crt(pre->t.crt, b); case DLOG_POWER: return dlog_power(pre->t.power, b); case DLOG_TABLE: return dlog_table(pre->t.table, b); case DLOG_BSGS: return dlog_bsgs(pre->t.bsgs, b); case DLOG_23: return dlog_order23(pre->t.order23, b); default: flint_throw(FLINT_ERROR, "(dlog_precomp): Unknown option"); } } flint-3.1.3/src/dlog/precomp_clear.c000066400000000000000000000021701461254215100173260ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_precomp_clear(dlog_precomp_t pre) { if (pre == NULL) return; switch (pre->type) { case DLOG_MODPE: dlog_modpe_clear(pre->t.modpe); break; case DLOG_CRT: dlog_crt_clear(pre->t.crt); break; case DLOG_POWER: dlog_power_clear(pre->t.power); break; case DLOG_TABLE: dlog_table_clear(pre->t.table); break; case DLOG_BSGS: dlog_bsgs_clear(pre->t.bsgs); break; case DLOG_23: dlog_order23_clear(pre->t.order23); break; default: flint_throw(FLINT_ERROR, "dlog_precomp_clear: unknown type %d\n", pre->type); } } flint-3.1.3/src/dlog/precomp_modpe_init.c000066400000000000000000000016041461254215100203700ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" /* log mod p^e */ void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) { if (pe < DLOG_TABLE_MODPE_LIM) { dlog_precomp_small_init(pre, a, pe, pe - pe / p, num); return; } else { if (e > 1) { pre->type = DLOG_MODPE; pre->cost = dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); } else { dlog_precomp_n_init(pre, a, p, p - 1, num); } } } flint-3.1.3/src/dlog/precomp_n_init.c000066400000000000000000000022361461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" /* group of order n modulo mod, mod a prime and no information on n */ void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) { if (n % 2 && n_is_probabprime(n)) dlog_precomp_p_init(pre, a, mod, n, num); else { if (n < DLOG_TABLE_N_LIM) { dlog_precomp_small_init(pre, a, mod, n, num); } else { if (n < DLOG_BSGS_LIM) { ulong m; m = dlog_bsgs_size(n, num); pre->type = DLOG_BSGS; pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); } else { pre->type = DLOG_CRT; pre->cost = dlog_crt_init(pre->t.crt, a, mod, n, num); } } } } flint-3.1.3/src/dlog/precomp_p_init.c000066400000000000000000000014201461254215100175170ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" /* we known the order is prime */ void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) { if (p < DLOG_TABLE_P_LIM) { dlog_precomp_small_init(pre, a, mod, p, num); } else { ulong m; m = dlog_bsgs_size(p, num); pre->type = DLOG_BSGS; pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); } } flint-3.1.3/src/dlog/precomp_pe_init.c000066400000000000000000000015371461254215100176750ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) { if (pe < DLOG_TABLE_PE_LIM) { dlog_precomp_small_init(pre, a, mod, pe, num); } else { if (e == 1) { dlog_precomp_p_init(pre, a, mod, p, num); } else { pre->type = DLOG_POWER; pre->cost = dlog_power_init(pre->t.power, a, mod, p, e, num); } } } flint-3.1.3/src/dlog/precomp_small_init.c000066400000000000000000000016221461254215100203740ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) { if (n <= 3) { pre->type = DLOG_23; pre->cost = dlog_order23_init(pre->t.order23, a); } else { if (mod < DLOG_TABLE_LIM) { pre->type = DLOG_TABLE; pre->cost = dlog_table_init(pre->t.table, a, mod); } else { pre->type = DLOG_BSGS; pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, n); } } } flint-3.1.3/src/dlog/profile/000077500000000000000000000000001461254215100160075ustar00rootroot00000000000000flint-3.1.3/src/dlog/profile/p-precomp.c000066400000000000000000000100531461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "dlog.h" #include "profiler.h" #define NUMPRIMES 400 #define LOG 0 #define CSV 1 #define JSON 2 typedef void (*log_f) (ulong p, ulong a, ulong num); void flog_table(ulong p, ulong a, ulong num) { int k; dlog_table_t t; dlog_table_init(t, a, p); for (k = 1; k < num; k++) { if (k % p == 0) continue; dlog_table(t, k % p); } dlog_table_clear(t); } void flog_bsgs(ulong p, ulong a, ulong num) { int k; dlog_bsgs_t t; dlog_bsgs_init(t, a, p, p-1, dlog_bsgs_size(p, num)); for (k = 1; k < num; k++) { if (k % p == 0) continue; dlog_bsgs(t, k % p); } dlog_bsgs_clear(t); } void flog_rho(ulong p, ulong a, ulong num) { int k; dlog_rho_t t; dlog_rho_init(t, a, p, p-1); for (k = 1; k < num; k++) { if (k % p == 0) continue; dlog_rho(t, k % p); } dlog_rho_clear(t); } void flog_crt(ulong p, ulong a, ulong num) { int k; dlog_crt_t t; dlog_crt_init(t, a, p, p-1, num); for (k = 1; k < num; k++) { if (k % p == 0) continue; dlog_crt(t, k % p); } dlog_crt_clear(t); } void flog_gen(ulong p, ulong a, ulong num) { int k; dlog_precomp_t t; dlog_precomp_n_init(t, a, p, p-1, num); for (k = 1; k < num; k++) { if (k % p == 0) continue; dlog_precomp(t, k % p); } dlog_precomp_clear(t); } int main(int argc, char *argv[]) { int out = LOG; int nbits, nl = 5; int l[5] = { 1, 10, 100, 1000 , 5000}; int nf = 4; log_f func[4] = { flog_table, flog_bsgs, flog_crt, flog_gen }; char * n[4] = { "table", "bsgs", "crt", "generic" }; int np = NUMPRIMES; flint_rand_t state; if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } flint_randinit(state); for (nbits = 10; nbits <= 40; nbits += 5) { int i; ulong p[NUMPRIMES], a[NUMPRIMES]; if (nbits >= 25) np /= 2; for (i=0; i < np; i++) { p[i] = n_randprime(state, nbits, 0); a[i] = n_primitive_root_prime(p[i]); } for (i = 0; i < nl; i++) { int f; if (out == LOG) flint_printf("%d * logs mod primes of size %d.....\n", l[i], nbits); for (f = 0; f < nf; f++) { int j; /* skip useless */ if (f == 0 && nbits >= 20) continue; if (f == 1 && nbits >= 30 && l[i] > 10) continue; if (out == LOG) { flint_printf("%-20s... ",n[f]); fflush(stdout); } else if (out == CSV) flint_printf("%-8s, %2d, %4d, %3d, ",n[f],nbits,l[i],np); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nlogs\": %d, \"nprimes\": %d, \"time\": ", n[f],nbits,l[i],np); TIMEIT_ONCE_START for (j = 0; j < np; j ++) (func[f])(p[j], a[j], l[i]); TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } } } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return 0; } flint-3.1.3/src/dlog/profile/p-vec.c000066400000000000000000000070601461254215100171700ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod.h" #include "nmod_vec.h" #include "dlog.h" #include "profiler.h" #define NPRIMES 640 #define LOG 0 #define CSV 1 #define JSON 2 typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); void f_empty(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) { return; } int main(int argc, char *argv[]) { int out = LOG; int i, ni = 8; int bits[9] = { 10, 15, 20, 25, 30, 35, 40, 45, 50 }; int j, nj = 6; ulong * v; ulong nv[6] = { 50, 200, 1000, 2000, 10000, 30000 }; int k, np = NPRIMES; nmod_t * p; ulong * a; int l, nf = 5; vec_f func[5] = { f_empty, dlog_vec_loop, dlog_vec_eratos, dlog_vec_sieve, dlog_vec }; char * n[5] = { "empty", "loop", "eratos", "sieve", "default" }; flint_rand_t state; nmod_t order; nmod_init(&order, 100); p = flint_malloc(np * sizeof(nmod_t)); a = flint_malloc(np * sizeof(ulong)); flint_randinit(state); if (argc < 2) out = LOG; else if (!strcmp(argv[1], "json")) out = JSON; else if (!strcmp(argv[1], "csv")) out = CSV; else if (!strcmp(argv[1], "log")) out = LOG; else { printf("usage: %s [log|csv|json]\n", argv[0]); flint_abort(); } for (i = 0; i < ni; i++) { for (k = 0; k < np; k++) { nmod_init(&p[k], n_randprime(state, bits[i], 0)); a[k] = n_primitive_root_prime(p[k].n); } for (j = 0; j < nj; j++) { v = flint_malloc(nv[j] * sizeof(ulong)); if (out == LOG) { flint_printf("log(1..%wu) mod %d primes of size %d bits....\n", nv[j], np, bits[i]); fflush(stdout); } for (l = 0; l < nf; l++) { if (l == 1 && i > 2) continue; if (l == 2 && i > 5) continue; if (out == LOG) { flint_printf("%-20s... ",n[l]); fflush(stdout); } else if (out == CSV) { flint_printf("%-8s, %2d, %4d, %3d, ",n[l],bits[i],nv[j],np); } else if (out == JSON) { flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nv\": %d, \"nprimes\": %d, \"time\": ", n[l],bits[i],nv[j],np); } TIMEIT_ONCE_START for (k = 0; k < np; k++) { int kk; for (kk=0; kk < nv[j]; kk++) v[kk] = 0; (func[l])(v, nv[j], a[k], 1, p[k], p[k].n - 1, order); } TIMEIT_ONCE_STOP if (out == JSON) flint_printf("}\n"); else flint_printf("\n"); } flint_free(v); } np /= 2; } flint_free(p); flint_free(a); flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return 0; } flint-3.1.3/src/dlog/profile/precomp_160905.json000066400000000000000000000176251461254215100212060ustar00rootroot00000000000000{ "name": "table", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.003} { "name": "bsgs", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.002} { "name": "crt", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.001} { "name": "generic", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.001} { "name": "table", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.004} { "name": "bsgs", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.004} { "name": "crt", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.003} { "name": "generic", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.003} { "name": "table", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.004} { "name": "bsgs", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.016} { "name": "crt", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.019} { "name": "generic", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.017} { "name": "table", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.01} { "name": "bsgs", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.054} { "name": "crt", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.143} { "name": "generic", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.143} { "name": "table", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.036} { "name": "bsgs", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.147} { "name": "crt", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.692} { "name": "generic", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.694} { "name": "table", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.108} { "name": "bsgs", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.01} { "name": "crt", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.003} { "name": "generic", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.002} { "name": "table", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.108} { "name": "bsgs", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.025} { "name": "crt", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.008} { "name": "generic", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.007} { "name": "table", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.109} { "name": "bsgs", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.092} { "name": "crt", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.038} { "name": "generic", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.038} { "name": "table", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.114} { "name": "bsgs", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.321} { "name": "crt", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.275} { "name": "generic", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.273} { "name": "table", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 0.14} { "name": "bsgs", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 0.784} { "name": "crt", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 1.228} { "name": "generic", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 1.232} { "name": "bsgs", "bits": 20, "nlogs": 1, "nprimes": 400, "time": 0.069} { "name": "crt", "bits": 20, "nlogs": 1, "nprimes": 400, "time": 0.011} { "name": "generic", "bits": 20, "nlogs": 1, "nprimes": 400, "time": 0.01} { "name": "bsgs", "bits": 20, "nlogs": 10, "nprimes": 400, "time": 0.176} { "name": "crt", "bits": 20, "nlogs": 10, "nprimes": 400, "time": 0.027} { "name": "generic", "bits": 20, "nlogs": 10, "nprimes": 400, "time": 0.027} { "name": "bsgs", "bits": 20, "nlogs": 100, "nprimes": 400, "time": 0.622} { "name": "crt", "bits": 20, "nlogs": 100, "nprimes": 400, "time": 0.114} { "name": "generic", "bits": 20, "nlogs": 100, "nprimes": 400, "time": 0.114} { "name": "bsgs", "bits": 20, "nlogs": 1000, "nprimes": 400, "time": 2.166} { "name": "crt", "bits": 20, "nlogs": 1000, "nprimes": 400, "time": 0.589} { "name": "generic", "bits": 20, "nlogs": 1000, "nprimes": 400, "time": 0.591} { "name": "bsgs", "bits": 20, "nlogs": 5000, "nprimes": 400, "time": 5.333} { "name": "crt", "bits": 20, "nlogs": 5000, "nprimes": 400, "time": 2.252} { "name": "generic", "bits": 20, "nlogs": 5000, "nprimes": 400, "time": 2.238} { "name": "bsgs", "bits": 25, "nlogs": 1, "nprimes": 200, "time": 0.23} { "name": "crt", "bits": 25, "nlogs": 1, "nprimes": 200, "time": 0.025} { "name": "generic", "bits": 25, "nlogs": 1, "nprimes": 200, "time": 0.026} { "name": "bsgs", "bits": 25, "nlogs": 10, "nprimes": 200, "time": 0.585} { "name": "crt", "bits": 25, "nlogs": 10, "nprimes": 200, "time": 0.065} { "name": "generic", "bits": 25, "nlogs": 10, "nprimes": 200, "time": 0.065} { "name": "bsgs", "bits": 25, "nlogs": 100, "nprimes": 200, "time": 2.099} { "name": "crt", "bits": 25, "nlogs": 100, "nprimes": 200, "time": 0.243} { "name": "generic", "bits": 25, "nlogs": 100, "nprimes": 200, "time": 0.243} { "name": "bsgs", "bits": 25, "nlogs": 1000, "nprimes": 200, "time": 7.338} { "name": "crt", "bits": 25, "nlogs": 1000, "nprimes": 200, "time": 0.967} { "name": "generic", "bits": 25, "nlogs": 1000, "nprimes": 200, "time": 0.967} { "name": "bsgs", "bits": 25, "nlogs": 5000, "nprimes": 200, "time": 19.051} { "name": "crt", "bits": 25, "nlogs": 5000, "nprimes": 200, "time": 2.893} { "name": "generic", "bits": 25, "nlogs": 5000, "nprimes": 200, "time": 2.882} { "name": "bsgs", "bits": 30, "nlogs": 1, "nprimes": 100, "time": 0.742} { "name": "crt", "bits": 30, "nlogs": 1, "nprimes": 100, "time": 0.07} { "name": "generic", "bits": 30, "nlogs": 1, "nprimes": 100, "time": 0.071} { "name": "bsgs", "bits": 30, "nlogs": 10, "nprimes": 100, "time": 1.914} { "name": "crt", "bits": 30, "nlogs": 10, "nprimes": 100, "time": 0.178} { "name": "generic", "bits": 30, "nlogs": 10, "nprimes": 100, "time": 0.178} { "name": "crt", "bits": 30, "nlogs": 100, "nprimes": 100, "time": 0.652} { "name": "generic", "bits": 30, "nlogs": 100, "nprimes": 100, "time": 0.655} { "name": "crt", "bits": 30, "nlogs": 1000, "nprimes": 100, "time": 2.495} { "name": "generic", "bits": 30, "nlogs": 1000, "nprimes": 100, "time": 2.493} { "name": "crt", "bits": 30, "nlogs": 5000, "nprimes": 100, "time": 6.465} { "name": "generic", "bits": 30, "nlogs": 5000, "nprimes": 100, "time": 6.432} { "name": "bsgs", "bits": 35, "nlogs": 1, "nprimes": 50, "time": 2.357} { "name": "crt", "bits": 35, "nlogs": 1, "nprimes": 50, "time": 0.118} { "name": "generic", "bits": 35, "nlogs": 1, "nprimes": 50, "time": 0.118} { "name": "bsgs", "bits": 35, "nlogs": 10, "nprimes": 50, "time": 6.562} { "name": "crt", "bits": 35, "nlogs": 10, "nprimes": 50, "time": 0.307} { "name": "generic", "bits": 35, "nlogs": 10, "nprimes": 50, "time": 0.308} { "name": "crt", "bits": 35, "nlogs": 100, "nprimes": 50, "time": 1.171} { "name": "generic", "bits": 35, "nlogs": 100, "nprimes": 50, "time": 1.175} { "name": "crt", "bits": 35, "nlogs": 1000, "nprimes": 50, "time": 4.329} { "name": "generic", "bits": 35, "nlogs": 1000, "nprimes": 50, "time": 4.297} { "name": "crt", "bits": 35, "nlogs": 5000, "nprimes": 50, "time": 10.904} { "name": "generic", "bits": 35, "nlogs": 5000, "nprimes": 50, "time": 10.916} { "name": "bsgs", "bits": 40, "nlogs": 1, "nprimes": 25, "time": 7.623} { "name": "crt", "bits": 40, "nlogs": 1, "nprimes": 25, "time": 0.472} { "name": "generic", "bits": 40, "nlogs": 1, "nprimes": 25, "time": 0.463} { "name": "bsgs", "bits": 40, "nlogs": 10, "nprimes": 25, "time": 21.817} { "name": "crt", "bits": 40, "nlogs": 10, "nprimes": 25, "time": 1.395} { "name": "generic", "bits": 40, "nlogs": 10, "nprimes": 25, "time": 1.389} { "name": "crt", "bits": 40, "nlogs": 100, "nprimes": 25, "time": 5.191} { "name": "generic", "bits": 40, "nlogs": 100, "nprimes": 25, "time": 5.158} { "name": "crt", "bits": 40, "nlogs": 1000, "nprimes": 25, "time": 19.911} { "name": "generic", "bits": 40, "nlogs": 1000, "nprimes": 25, "time": 19.722} { "name": "crt", "bits": 40, "nlogs": 5000, "nprimes": 25, "time": 51.207} { "name": "generic", "bits": 40, "nlogs": 5000, "nprimes": 25, "time": 51.084} flint-3.1.3/src/dlog/profile/vec160905.json000066400000000000000000000344331461254215100201530ustar00rootroot00000000000000{ "name": "empty", "bits": 10, "nv": 50, "nprimes": 640, "time": 0} { "name": "loop", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.006} { "name": "eratos", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.007} { "name": "sieve", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.009} { "name": "default", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.01} { "name": "empty", "bits": 10, "nv": 200, "nprimes": 640, "time": 0} { "name": "loop", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.007} { "name": "eratos", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.016} { "name": "sieve", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.013} { "name": "default", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.013} { "name": "empty", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0} { "name": "loop", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.007} { "name": "eratos", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.04} { "name": "sieve", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.024} { "name": "default", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.023} { "name": "empty", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0} { "name": "loop", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.006} { "name": "eratos", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.04} { "name": "sieve", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.026} { "name": "default", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.025} { "name": "empty", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.002} { "name": "loop", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.011} { "name": "eratos", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.045} { "name": "sieve", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.05} { "name": "default", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.011} { "name": "empty", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.005} { "name": "loop", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.022} { "name": "eratos", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.055} { "name": "sieve", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.109} { "name": "default", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.022} { "name": "empty", "bits": 15, "nv": 50, "nprimes": 320, "time": 0} { "name": "loop", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.09} { "name": "eratos", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.008} { "name": "sieve", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.014} { "name": "default", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.013} { "name": "empty", "bits": 15, "nv": 200, "nprimes": 320, "time": 0} { "name": "loop", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.09} { "name": "eratos", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.018} { "name": "sieve", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.02} { "name": "default", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.02} { "name": "empty", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0} { "name": "loop", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.092} { "name": "eratos", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.05} { "name": "sieve", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.029} { "name": "default", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.03} { "name": "empty", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0} { "name": "loop", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.097} { "name": "eratos", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.085} { "name": "sieve", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.037} { "name": "default", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.039} { "name": "empty", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.001} { "name": "loop", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.126} { "name": "eratos", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.301} { "name": "sieve", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.098} { "name": "default", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.096} { "name": "empty", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.003} { "name": "loop", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.094} { "name": "eratos", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.641} { "name": "sieve", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.193} { "name": "default", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.192} { "name": "empty", "bits": 20, "nv": 50, "nprimes": 160, "time": 0} { "name": "loop", "bits": 20, "nv": 50, "nprimes": 160, "time": 1.445} { "name": "eratos", "bits": 20, "nv": 50, "nprimes": 160, "time": 0.015} { "name": "sieve", "bits": 20, "nv": 50, "nprimes": 160, "time": 0.026} { "name": "default", "bits": 20, "nv": 50, "nprimes": 160, "time": 0.027} { "name": "empty", "bits": 20, "nv": 200, "nprimes": 160, "time": 0} { "name": "loop", "bits": 20, "nv": 200, "nprimes": 160, "time": 1.445} { "name": "eratos", "bits": 20, "nv": 200, "nprimes": 160, "time": 0.03} { "name": "sieve", "bits": 20, "nv": 200, "nprimes": 160, "time": 0.034} { "name": "default", "bits": 20, "nv": 200, "nprimes": 160, "time": 0.032} { "name": "empty", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0} { "name": "loop", "bits": 20, "nv": 1000, "nprimes": 160, "time": 1.45} { "name": "eratos", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0.07} { "name": "sieve", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0.041} { "name": "default", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0.041} { "name": "empty", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0} { "name": "loop", "bits": 20, "nv": 2000, "nprimes": 160, "time": 1.454} { "name": "eratos", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0.107} { "name": "sieve", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0.048} { "name": "default", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0.047} { "name": "empty", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.001} { "name": "loop", "bits": 20, "nv": 10000, "nprimes": 160, "time": 1.465} { "name": "eratos", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.308} { "name": "sieve", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.082} { "name": "default", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.081} { "name": "empty", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.001} { "name": "loop", "bits": 20, "nv": 30000, "nprimes": 160, "time": 1.505} { "name": "eratos", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.685} { "name": "sieve", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.152} { "name": "default", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.152} { "name": "empty", "bits": 25, "nv": 50, "nprimes": 80, "time": 0} { "name": "eratos", "bits": 25, "nv": 50, "nprimes": 80, "time": 0.029} { "name": "sieve", "bits": 25, "nv": 50, "nprimes": 80, "time": 0.052} { "name": "default", "bits": 25, "nv": 50, "nprimes": 80, "time": 0.051} { "name": "empty", "bits": 25, "nv": 200, "nprimes": 80, "time": 0} { "name": "eratos", "bits": 25, "nv": 200, "nprimes": 80, "time": 0.056} { "name": "sieve", "bits": 25, "nv": 200, "nprimes": 80, "time": 0.06} { "name": "default", "bits": 25, "nv": 200, "nprimes": 80, "time": 0.06} { "name": "empty", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0} { "name": "eratos", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0.117} { "name": "sieve", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0.072} { "name": "default", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0.073} { "name": "empty", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0} { "name": "eratos", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0.168} { "name": "sieve", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0.082} { "name": "default", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0.08} { "name": "empty", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.001} { "name": "eratos", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.409} { "name": "sieve", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.092} { "name": "default", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.093} { "name": "empty", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.001} { "name": "eratos", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.8} { "name": "sieve", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.132} { "name": "default", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.132} { "name": "empty", "bits": 30, "nv": 50, "nprimes": 40, "time": 0} { "name": "eratos", "bits": 30, "nv": 50, "nprimes": 40, "time": 0.073} { "name": "sieve", "bits": 30, "nv": 50, "nprimes": 40, "time": 0.121} { "name": "default", "bits": 30, "nv": 50, "nprimes": 40, "time": 0.122} { "name": "empty", "bits": 30, "nv": 200, "nprimes": 40, "time": 0} { "name": "eratos", "bits": 30, "nv": 200, "nprimes": 40, "time": 0.138} { "name": "sieve", "bits": 30, "nv": 200, "nprimes": 40, "time": 0.136} { "name": "default", "bits": 30, "nv": 200, "nprimes": 40, "time": 0.136} { "name": "empty", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0} { "name": "eratos", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0.282} { "name": "sieve", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0.151} { "name": "default", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0.15} { "name": "empty", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0} { "name": "eratos", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0.409} { "name": "sieve", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0.166} { "name": "default", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0.162} { "name": "empty", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0} { "name": "eratos", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0.924} { "name": "sieve", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0.226} { "name": "default", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0.225} { "name": "empty", "bits": 30, "nv": 30000, "nprimes": 40, "time": 0} { "name": "eratos", "bits": 30, "nv": 30000, "nprimes": 40, "time": 1.665} { "name": "sieve", "bits": 30, "nv": 30000, "nprimes": 40, "time": 0.207} { "name": "default", "bits": 30, "nv": 30000, "nprimes": 40, "time": 0.207} { "name": "empty", "bits": 35, "nv": 50, "nprimes": 20, "time": 0} { "name": "eratos", "bits": 35, "nv": 50, "nprimes": 20, "time": 0.22} { "name": "sieve", "bits": 35, "nv": 50, "nprimes": 20, "time": 0.355} { "name": "default", "bits": 35, "nv": 50, "nprimes": 20, "time": 0.352} { "name": "empty", "bits": 35, "nv": 200, "nprimes": 20, "time": 0} { "name": "eratos", "bits": 35, "nv": 200, "nprimes": 20, "time": 0.432} { "name": "sieve", "bits": 35, "nv": 200, "nprimes": 20, "time": 0.403} { "name": "default", "bits": 35, "nv": 200, "nprimes": 20, "time": 0.407} { "name": "empty", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0} { "name": "eratos", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0.864} { "name": "sieve", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0.426} { "name": "default", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0.428} { "name": "empty", "bits": 35, "nv": 2000, "nprimes": 20, "time": 0} { "name": "eratos", "bits": 35, "nv": 2000, "nprimes": 20, "time": 1.23} { "name": "sieve", "bits": 35, "nv": 2000, "nprimes": 20, "time": 0.442} { "name": "default", "bits": 35, "nv": 2000, "nprimes": 20, "time": 0.439} { "name": "empty", "bits": 35, "nv": 10000, "nprimes": 20, "time": 0} { "name": "eratos", "bits": 35, "nv": 10000, "nprimes": 20, "time": 2.717} { "name": "sieve", "bits": 35, "nv": 10000, "nprimes": 20, "time": 0.528} { "name": "default", "bits": 35, "nv": 10000, "nprimes": 20, "time": 0.53} { "name": "empty", "bits": 35, "nv": 30000, "nprimes": 20, "time": 0} { "name": "eratos", "bits": 35, "nv": 30000, "nprimes": 20, "time": 4.735} { "name": "sieve", "bits": 35, "nv": 30000, "nprimes": 20, "time": 0.739} { "name": "default", "bits": 35, "nv": 30000, "nprimes": 20, "time": 0.74} { "name": "empty", "bits": 40, "nv": 50, "nprimes": 10, "time": 0} { "name": "sieve", "bits": 40, "nv": 50, "nprimes": 10, "time": 1.31} { "name": "default", "bits": 40, "nv": 50, "nprimes": 10, "time": 1.306} { "name": "empty", "bits": 40, "nv": 200, "nprimes": 10, "time": 0} { "name": "sieve", "bits": 40, "nv": 200, "nprimes": 10, "time": 1.537} { "name": "default", "bits": 40, "nv": 200, "nprimes": 10, "time": 1.537} { "name": "empty", "bits": 40, "nv": 1000, "nprimes": 10, "time": 0} { "name": "sieve", "bits": 40, "nv": 1000, "nprimes": 10, "time": 1.58} { "name": "default", "bits": 40, "nv": 1000, "nprimes": 10, "time": 1.574} { "name": "empty", "bits": 40, "nv": 2000, "nprimes": 10, "time": 0} { "name": "sieve", "bits": 40, "nv": 2000, "nprimes": 10, "time": 1.597} { "name": "default", "bits": 40, "nv": 2000, "nprimes": 10, "time": 1.596} { "name": "empty", "bits": 40, "nv": 10000, "nprimes": 10, "time": 0} { "name": "sieve", "bits": 40, "nv": 10000, "nprimes": 10, "time": 1.753} { "name": "default", "bits": 40, "nv": 10000, "nprimes": 10, "time": 1.748} { "name": "empty", "bits": 40, "nv": 30000, "nprimes": 10, "time": 0} { "name": "sieve", "bits": 40, "nv": 30000, "nprimes": 10, "time": 2.396} { "name": "default", "bits": 40, "nv": 30000, "nprimes": 10, "time": 2.397} { "name": "empty", "bits": 45, "nv": 50, "nprimes": 5, "time": 0} { "name": "sieve", "bits": 45, "nv": 50, "nprimes": 5, "time": 1.623} { "name": "default", "bits": 45, "nv": 50, "nprimes": 5, "time": 1.617} { "name": "empty", "bits": 45, "nv": 200, "nprimes": 5, "time": 0} { "name": "sieve", "bits": 45, "nv": 200, "nprimes": 5, "time": 2.039} { "name": "default", "bits": 45, "nv": 200, "nprimes": 5, "time": 2.072} { "name": "empty", "bits": 45, "nv": 1000, "nprimes": 5, "time": 0} { "name": "sieve", "bits": 45, "nv": 1000, "nprimes": 5, "time": 2.194} { "name": "default", "bits": 45, "nv": 1000, "nprimes": 5, "time": 2.142} { "name": "empty", "bits": 45, "nv": 2000, "nprimes": 5, "time": 0} { "name": "sieve", "bits": 45, "nv": 2000, "nprimes": 5, "time": 2.147} { "name": "default", "bits": 45, "nv": 2000, "nprimes": 5, "time": 2.182} { "name": "empty", "bits": 45, "nv": 10000, "nprimes": 5, "time": 0} { "name": "sieve", "bits": 45, "nv": 10000, "nprimes": 5, "time": 2.22} { "name": "default", "bits": 45, "nv": 10000, "nprimes": 5, "time": 2.222} { "name": "empty", "bits": 45, "nv": 30000, "nprimes": 5, "time": 0} { "name": "sieve", "bits": 45, "nv": 30000, "nprimes": 5, "time": 2.448} { "name": "default", "bits": 45, "nv": 30000, "nprimes": 5, "time": 2.445} flint-3.1.3/src/dlog/rho.c000066400000000000000000000054551461254215100153140ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" #ifdef __GNUC__ # define floor __builtin_floor #else # include #endif static ulong dlog_single(ulong b, ulong a, const nmod_t mod, ulong n) { if (n < 50) { int k; ulong ak = 1; for (k=0; k < n; k++) { if (ak == b) return k; ak = nmod_mul(ak, a, mod); } flint_throw(FLINT_ERROR, "(dlog single): log(%wu,%wu) mod %wu not found (size %wu)\n", b, a, mod.n, n); } else { dlog_rho_t t; dlog_rho_init(t, a, mod.n, n); return dlog_rho(t, b); } } /* solve log knowing equation e = f * log(b) [n] */ static ulong dlog_quotient(const dlog_rho_t t, ulong e, ulong f, ulong g, ulong b) { ulong r, b_ar, an; nmod_t n = t->n; if (g == n.n) { flint_throw(FLINT_ERROR, "(dlog quotient): trivial relation e = %wu, f = %wu mod %wu\n", e, f, n.n); } nmod_init(&n, n.n / g); e = e / g; f = f / g; r = nmod_div(e, f, n); an = nmod_pow_ui(t->a, n.n, t->mod); b_ar = nmod_div(b, nmod_pow_ui(t->a, r, t->mod), t->mod); return r + n.n * dlog_single(b_ar, an, t->mod, g); } #define RWALK 20 ulong dlog_rho(const dlog_rho_t t, ulong b) { int j, k, l; ulong m[RWALK], n[RWALK], ab[RWALK]; ulong x[2], e[2], f[2], g; flint_rand_t state; flint_randinit(state); do { for (k = 0; k < RWALK; k++) { m[k] = 1 + n_randint(state, t->n.n - 1); n[k] = 1 + n_randint(state, t->n.n - 1); ab[k] = nmod_mul(nmod_pow_ui(t->a, m[k], t->mod), nmod_pow_ui(b, n[k], t->mod), t->mod); } /* x[l] = a^e[l] * b^f[l] */ x[0] = x[1] = 1; e[0] = e[1] = 0; f[0] = f[1] = 0; do { for(j = 0; j < 3; j++) { l = (j > 0); k = floor( (double) RWALK * x[l] / t->mod.n ); x[l] = nmod_mul(x[l], ab[k], t->mod); e[l] = nmod_add(e[l], m[k], t->n); f[l] = nmod_add(f[l], n[k], t->n); } } while (x[0] != x[1]); } while (e[0] == e[1] && f[0] == f[1]); flint_randclear(state); /* e = f * log(b) */ e[0] = nmod_sub(e[0], e[1], t->n); f[0] = nmod_sub(f[1], f[0], t->n); if (!t->nisprime && (g = n_gcd(f[0], t->n.n)) > 1) return dlog_quotient(t, e[0], f[0], g, b); else return nmod_div(e[0], f[0], t->n); } flint-3.1.3/src/dlog/rho_init.c000066400000000000000000000011061461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) { t->a = a; nmod_init(&t->n, n); nmod_init(&t->mod, mod); t->nisprime = n_is_prime(n); } flint-3.1.3/src/dlog/table.c000066400000000000000000000007421461254215100156050ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" ulong dlog_table(const dlog_table_t t, ulong b) { return t->table[b % t->mod]; } flint-3.1.3/src/dlog/table_init.c000066400000000000000000000014201461254215100166220ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" /* assume mod is small so no overflow */ ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod) { int k; ulong ak; t->mod = mod; t->table = flint_malloc(mod * sizeof(ulong)); ak = 1; k = 0; /* warning: do not check a is invertible modulo mod */ do { t->table[ak] = k++; ak = (ak * a) % mod; } while (ak != 1); return 1; } flint-3.1.3/src/dlog/test/000077500000000000000000000000001461254215100153265ustar00rootroot00000000000000flint-3.1.3/src/dlog/test/main.c000066400000000000000000000015261461254215100164220ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-dlog.c" #include "t-modpe.c" #include "t-vec.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(dlog), TEST_FUNCTION(dlog_modpe), TEST_FUNCTION(dlog_vec) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/dlog/test/t-dlog.c000066400000000000000000000041241461254215100166610ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "dlog.h" TEST_FUNCTION_START(dlog, state) { slong iter; for (iter = 0; iter < 1000; iter++) { dlog_table_t table; dlog_bsgs_t bsgs; dlog_crt_t crt; dlog_precomp_t pre1, pre100; ulong p, a, k; nmod_t modp; if (iter < 10) p = n_nth_prime(iter + 2); else p = n_randprime(state, 15, 0); nmod_init(&modp, p); a = n_primitive_root_prime(p); dlog_table_init(table, a, p); dlog_bsgs_init(bsgs, a, p, p-1, dlog_bsgs_size(p, 1)); dlog_crt_init(crt, a, p, p-1, 10); dlog_precomp_n_init(pre1, a, p, p-1, 1); dlog_precomp_n_init(pre100, a, p, p-1, 100); for (k = 1; k < 100 && k < p; k++) { ulong l0, l1, l2, l3, l4, l5; l1 = dlog_table(table, k); l2 = dlog_bsgs(bsgs, k); l3 = dlog_crt(crt, k); l4 = dlog_precomp(pre1, k); l5 = dlog_precomp(pre100, k); if (iter < 50 && k <= 7) l0 = dlog_once(k, a, modp, p-1); else l0 = l1; if (l0 != l1 || l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5) { flint_printf("\n\nFAIL: log(%wu,%wu) mod %wu\n\n",k,a,p); flint_printf("once: %wu\ntable: %wu\nbsgs: %wu\ncrt: %wu\nprecomp1: %wu\nprecomp100: %wu\n\n", l0, l1, l2, l3, l4, l5); flint_abort(); } } dlog_table_clear(table); dlog_bsgs_clear(bsgs); dlog_crt_clear(crt); dlog_precomp_clear(pre1); dlog_precomp_clear(pre100); } TEST_FUNCTION_END(state); } flint-3.1.3/src/dlog/test/t-modpe.c000066400000000000000000000036171461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "dlog.h" #if FLINT_BITS == 64 #define LIM UWORD(1000000000000) #else #define LIM UWORD(1000000000) #endif TEST_FUNCTION_START(dlog_modpe, state) { slong iter; for (iter = 0; iter < 1000; iter++) { ulong p, e, pe, a; if (iter == 0) { p = 2; pe = 8; a = 5; e = 3; } else { p = pe = n_randprime(state, 10, 0); a = (p == 40487) ? 10 : n_primitive_root_prime(p); e = 1; } for (; pe < LIM; pe *= p, e++) { ulong k, phi; nmod_t mod; dlog_modpe_t modpe; nmod_init(&mod, pe); phi = (p == 2) ? pe / 4 : pe - pe / p; dlog_modpe_init(modpe, a, p, e, pe, 10); for (k = 0; k < 100 && k < p; k++) { ulong l, b, x; l = n_randint(state, phi); b = nmod_pow_ui(a, l, mod); if ((x = dlog_modpe(modpe, b)) != l) { flint_printf("FAIL modpe: %wu^%wu = %wu [%wu^%wu]\n\n", a, l, b, p, e); flint_printf("modpe returned %wu\n\n", x); flint_abort(); } } dlog_modpe_clear(modpe); /* multiplication can overflow on 32-bit */ if ((double) pe * p > LIM) break; } } TEST_FUNCTION_END(state); } flint-3.1.3/src/dlog/test/t-vec.c000066400000000000000000000053651461254215100165210ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "dlog.h" typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); void dlog_vec_trivial(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) { ulong k; dlog_precomp_t pre; dlog_precomp_n_init(pre, a, mod.n, na, 50); for (k = 1; k < nv; k++) if (n_gcd(k, mod.n) > 1) v[k] = DLOG_NOT_FOUND; else v[k] = dlog_precomp(pre, k % mod.n); dlog_precomp_clear(pre); } static ulong dlog_vec_diff(ulong * v, ulong * ref, ulong nv) { ulong k; for (k = 1; k < nv; k++) if (ref[k] != v[k]) return k; return 0; } TEST_FUNCTION_START(dlog_vec, state) { slong bits, nv, iter; int f, nf = 4; vec_f func[4] = { dlog_vec_trivial, dlog_vec_loop, dlog_vec_eratos, dlog_vec_sieve }; char * n[4] = { "trivial", "loop", "eratos", "sieve" }; for (bits = 10; bits <= FLINT_MIN(35, FLINT_BITS); bits += 5) { for (nv = 10; nv <= 10000; nv *= 10) { ulong *v, *ref; int iref; iref = (bits == 10 && nv <= 1000) ? 0 : 2; ref = flint_malloc(nv * sizeof(ulong)); v = flint_malloc(nv * sizeof(ulong)); for (iter = 0; iter < 10; iter++) { int k; ulong p, a, va, na; nmod_t mod, order; p = n_randprime(state, bits, 0); a = n_primitive_root_prime(p); nmod_init(&mod, p); va = 1; na = p - 1; nmod_init(&order, na); dlog_vec_fill(ref, nv, 0); (func[iref])(ref, nv, a, va, mod, na, order); /* compare */ for (f = iref + 1; f < nf; f++) { dlog_vec_fill(v, nv, 0); (func[f])(v, nv, a, va, mod, na, order); if ((k = dlog_vec_diff(v, ref, nv))) { flint_printf("FAIL: log(%wu,%wu) mod %wu: %s->%w != %s->%w\n", k, a, p, n[iref], ref[k], n[f], v[k]); flint_abort(); } } } flint_free(ref); flint_free(v); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/dlog/vec.c000066400000000000000000000012471461254215100152740ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { if (va == 0) return; if (na * DLOG_LOOP_MAX_FACTOR < nv) dlog_vec_loop(v, nv, a, va, mod, na, order); else dlog_vec_sieve(v, nv, a, va, mod, na, order); } flint-3.1.3/src/dlog/vec_add.c000066400000000000000000000012631461254215100161020ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_vec_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { if (va == 0) return; if (na * DLOG_LOOP_MAX_FACTOR < nv) dlog_vec_loop_add(v, nv, a, va, mod, na, order); else dlog_vec_sieve_add(v, nv, a, va, mod, na, order); } flint-3.1.3/src/dlog/vec_add_precomp.c000066400000000000000000000013341461254215100176260ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_vec_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { if (va == 0) return; if (na * DLOG_LOOP_MAX_FACTOR < nv) dlog_vec_loop_add(v, nv, a, va, mod, na, order); else dlog_vec_sieve_add_precomp(v, nv, pre, a, va, mod, na, order); } flint-3.1.3/src/dlog/vec_eratos.c000066400000000000000000000011551461254215100166470ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { dlog_vec_fill(v, nv, 0); dlog_vec_set_not_found(v, nv, mod); dlog_vec_eratos_add(v, nv, a, va, mod, na, order); } flint-3.1.3/src/dlog/vec_eratos_add.c000066400000000000000000000026131461254215100174570ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" /* assume non invertible and 1 mod n already set */ void dlog_vec_eratos_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong p, k, n; dlog_precomp_t pre; n_primes_t iter; /* discrete log on primes */ n = (nv < mod.n) ? nv : mod.n; dlog_precomp_n_init(pre, a, mod.n, na, n_prime_pi(n)); n_primes_init(iter); while ((p = n_primes_next(iter)) < n) { ulong wp, pe; if (v[p] == DLOG_NOT_FOUND) continue; /* won't be attained another time */ wp = nmod_mul(dlog_precomp(pre, p), va, order); /* FIXME: could be faster sieving m*pe? but cannot * use v[p*m]=v[p]*v[m]... */ for (pe = p; pe < n; pe *= p) for (k = pe; k < n; k += pe) if (v[k] != DLOG_NOT_FOUND) v[k] = nmod_add(v[k], wp, order); } n_primes_clear(iter); for (k = mod.n + 1; k < nv; k++) v[k] = v[k - mod.n]; dlog_precomp_clear(pre); } flint-3.1.3/src/dlog/vec_fill.c000066400000000000000000000007751461254215100163070ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_vec_fill(ulong *v, ulong nv, ulong x) { ulong k; for (k = 0; k < nv; k++) v[k] = x; } flint-3.1.3/src/dlog/vec_loop.c000066400000000000000000000015331461254215100163230ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" /* vector of log(k,a)*loga % order in Z/modZ */ void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong x, vx; dlog_vec_fill(v, nv, DLOG_NOT_FOUND); x = 1; vx = 0; do { if (x < nv) v[x] = vx; x = nmod_mul(x, a, mod); vx = nmod_add(vx, va, order); } while (x != 1); for (x = mod.n + 1; x < nv; x++) v[x] = v[x - mod.n]; } flint-3.1.3/src/dlog/vec_loop_add.c000066400000000000000000000014721461254215100171350ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" /* vector of log(k,a)*loga % order in Z/modZ */ void dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong x, xp, vx; vx = 0; for (x = a; x != 1; x = nmod_mul(x, a, mod)) { vx = nmod_add(vx, va, order); for(xp = x; xp < nv; xp+=mod.n) if (v[xp] != DLOG_NONE) v[xp] = nmod_add(v[xp], vx, order); } } flint-3.1.3/src/dlog/vec_pindex_factorgcd.c000066400000000000000000000060231461254215100206540ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" #define vbs 1 #define FACTOR_RATIO 4 static int factor_until(ulong * n, ulong nlim, const ulong * p, ulong pmax, ulong * fp, int * fe) { int i, j; for (i = 0, j = 0; *n >= nlim && p[j] < pmax; j++) { int e = n_remove(n, p[j]); if (e) { fp[i] = p[j]; fe[i] = e; i++; } } return i; } ulong dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) { int nm = 0; ulong pm, logm, pmax; ulong u[2], r[2], t; ulong up[15], rp[15]; int ue[15], re[15]; const ulong * prime; prime = n_primes_arr_readonly(p); pmax = p / FACTOR_RATIO; pm = p; logm = 0; while (nm++ < maxtry) { int i, j, iu, ir; ulong logr; pm = nmod_mul(pm, a, mod); logm = nmod_add(logm, loga, order); /* if (2 * pm > mod.n) { pm = nmod_neg(pm, mod); logm = nmod_add(logm, logm1, order); } */ /* half gcd u * pm + v * mod = r, ignore v */ u[0] = 0; r[0] = mod.n; u[1] = 1; r[1] = pm; i = 1; j = 0; /* flip flap */ while (r[i] > u[i]) { if (r[i] < nv && v[r[i]] != DLOG_NOT_FOUND && u[i] < nv && v[u[i]] != DLOG_NOT_FOUND) { /* early smooth detection: occurs for primes < 30 bits */ ulong x; /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ x = nmod_sub(v[r[i]], nmod_add(v[u[i]], logm, order), order); if (j) x = nmod_add(x, logm1, order); return x; } j = i; i = 1 - i; /* switch */ t = r[i] / r[j]; r[i] = r[i] % r[j]; u[i] = u[i] + t * u[j]; /* times (-1)^j */ }; /* try to factor both r[i] and u[i] */ iu = factor_until(&u[i], nv, prime, pmax, up, ue); if (u[i] >= nv || v[u[i]] == DLOG_NOT_FOUND) continue; ir = factor_until(&r[i], nv, prime, pmax, rp, re); if (r[i] >= nv || v[r[i]] == DLOG_NOT_FOUND) continue; /* log(u)+log(p)+log(m)=log(r) */ logm = nmod_add(logm, v[u[i]], order); logr = (j) ? logm1 : 0; logr = nmod_add(logr, v[r[i]], order); for (i=0; i < ir; i++) logr = nmod_add(logr, nmod_mul(re[i], v[rp[i]], order), order); for (i=0; i < iu; i++) logm = nmod_add(logm, nmod_mul(ue[i], v[up[i]], order), order); return nmod_sub(logr, logm, order); } return DLOG_NOT_FOUND; } flint-3.1.3/src/dlog/vec_set_not_found.c000066400000000000000000000013051461254215100202150ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" void dlog_vec_set_not_found(ulong *v, ulong nv, nmod_t mod) { n_factor_t fac; ulong i; n_factor_init(&fac); n_factor(&fac, mod.n, 1); for (i = 0; i < fac.num; i++) { ulong p, k; p = fac.p[i]; for (k = p; k < nv; k += p) v[k] = DLOG_NOT_FOUND; } } flint-3.1.3/src/dlog/vec_sieve.c000066400000000000000000000014071461254215100164650ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "dlog.h" #define vbs 0 /* TODO: tune the limit dlog -> index calculus */ void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong p1 = 50; /* FIXME: tune this limit! */ dlog_precomp_t pre; dlog_precomp_n_init(pre, a, mod.n, na, p1); dlog_vec_sieve_precomp(v, nv, pre, a, va, mod, na, order); dlog_precomp_clear(pre); } flint-3.1.3/src/dlog/vec_sieve_add.c000066400000000000000000000014421461254215100172740ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" void dlog_vec_sieve_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong * w, k; /* store size */ w = flint_malloc(nv * sizeof(ulong)); dlog_vec_sieve(w, nv, a, va, mod, na, order); /* write in v */ for (k = 0; k < nv; k++) if (v[k] != DLOG_NOT_FOUND) v[k] = nmod_add(v[k], w[k], order); flint_free(w); } flint-3.1.3/src/dlog/vec_sieve_add_precomp.c000066400000000000000000000015131461254215100210200ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" void dlog_vec_sieve_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong * w, k; /* store size */ w = flint_malloc(nv * sizeof(ulong)); dlog_vec_sieve_precomp(w, nv, pre, a, va, mod, na, order); /* write in v */ for (k = 0; k < nv; k++) if (v[k] != DLOG_NOT_FOUND) v[k] = nmod_add(v[k], w[k], order); flint_free(w); } flint-3.1.3/src/dlog/vec_sieve_precomp.c000066400000000000000000000055251461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "dlog.h" #ifdef __GNUC__ # define log __builtin_log # define pow __builtin_pow #else # include #endif #define vbs 0 /* TODO: tune the limit dlog -> index calculus */ void dlog_vec_sieve_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { #if vbs ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; #endif #if 0 ulong limcount; #endif ulong logcost; ulong k, p, pmax, logm1; n_primes_t iter; ulong X, aX, vaX; dlog_vec_fill(v, nv, DLOG_NOT_FOUND); v[1] = 0; logm1 = (na % 2) ? 0 : nmod_mul(na / 2, va, order); /* discrete log on first primes, then sieve */ pmax = (nv < mod.n) ? nv : mod.n; logcost = pre->cost; #if 0 if (logcost < 15) { /* p1 = pmax; */ limcount = mod.n; } else { limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); } #endif /* take big power of gen */ X = n_nextprime(3 * na / 2, 0) % na; aX = nmod_pow_ui(a, X, mod); vaX = nmod_mul(va, X % order.n, order); n_primes_init(iter); while ((p = n_primes_next(iter)) < pmax) { double cost; ulong m, vp; if (mod.n % p == 0) continue; /* won't be attained another time */ cost = log(mod.n)/log(p); cost = pow(cost,cost); #if vbs sievecount++; #endif /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ /* if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ if (logcost < cost || (vp = dlog_vec_pindex_factorgcd(v, nv, p, mod, aX, na, vaX, logm1, order, cost)) == DLOG_NOT_FOUND) { #if vbs if (logcost < cost) sievecount--; else missed++; logcount++; #endif vp = nmod_mul(dlog_precomp(pre, p), va, order); } for (k = p, m = 1; k < nv; k += p, m++) { if (v[m] == DLOG_NOT_FOUND) continue; #if vbs smooth++; #endif v[k] = nmod_add(v[m], vp, order); } } #if vbs if (missed) flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", smooth, limcount, mod.n, logcost, logcount, sievecount, missed); #endif n_primes_clear(iter); for (k = mod.n + 1; k < nv; k++) v[k] = v[k - mod.n]; } flint-3.1.3/src/double_extras.h000066400000000000000000000045521461254215100164410ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef DOUBLE_EXTRAS_H #define DOUBLE_EXTRAS_H #ifdef DOUBLE_EXTRAS_INLINES_C #define DOUBLE_EXTRAS_INLINE #else #define DOUBLE_EXTRAS_INLINE static inline #endif #include #include #include "flint.h" #ifdef __cplusplus extern "C" { #endif #define D_BITS 53 #define D_EPS 2.2204460492503130808e-16 #define D_INF HUGE_VAL #define D_NAN (HUGE_VAL - HUGE_VAL) double d_randtest(flint_rand_t state); double d_randtest_signed(flint_rand_t state, slong minexp, slong maxexp); double d_randtest_special(flint_rand_t state, slong minexp, slong maxexp); DOUBLE_EXTRAS_INLINE double d_polyval(const double * poly, int len, double x) { double t; int i; for (t = poly[len-1], i = len-2; i >= 0; i--) t = poly[i] + x * t; return t; } double d_lambertw(double x); DOUBLE_EXTRAS_INLINE int d_is_nan(double x) { return x != x; } double d_log2(double x); typedef union { double f; uint64_t i; } double_uint64_u; #define D_MIN_NORMAL_EXPONENT -1022 #define D_MAX_NORMAL_EXPONENT 1023 #define D_EXPONENT_BIAS 1023 #define D_EXPONENT_SHIFT 52 /* Assumes that 2^i is in the normal exponent range. */ FLINT_FORCE_INLINE double d_mul_2exp_inrange(double x, int i) { FLINT_ASSERT(i >= D_MIN_NORMAL_EXPONENT && i <= D_MAX_NORMAL_EXPONENT); double_uint64_u u; u.i = ((int64_t) (i + D_EXPONENT_BIAS)) << D_EXPONENT_SHIFT; return x * u.f; } /* Assumes that 2^i, x and x*2^i are all in the normal exponent range. */ /* In particular, also assumes x != 0. */ FLINT_FORCE_INLINE double d_mul_2exp_inrange2(double x, int i) { FLINT_ASSERT(i >= D_MIN_NORMAL_EXPONENT && i <= D_MAX_NORMAL_EXPONENT); FLINT_ASSERT(x != 0); double_uint64_u u; u.f = x; u.i += ((int64_t) i) << D_EXPONENT_SHIFT; return u.f; } FLINT_FORCE_INLINE double d_mul_2exp(double x, int i) { if (i >= D_MIN_NORMAL_EXPONENT && i <= D_MAX_NORMAL_EXPONENT) return d_mul_2exp_inrange(x, i); else return ldexp(x, i); } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/double_extras/000077500000000000000000000000001461254215100162625ustar00rootroot00000000000000flint-3.1.3/src/double_extras/inlines.c000066400000000000000000000007111461254215100200660ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define DOUBLE_EXTRAS_INLINES_C #include "flint.h" #include "double_extras.h" flint-3.1.3/src/double_extras/lambertw.c000066400000000000000000000113461461254215100202500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #define POLY(p, x) d_polyval((p), sizeof(p) / sizeof(double), (x)) static const double pol1[4] = { 0.2278634396856248853716, 0.6685854654191353381433, 0.4670475452404395343887, 0.061184972065242761167 }; static const double pol2[5] = { 0.2278636537503804204913, 0.8964421845409468074626, 1.0217927151592500702475, 0.34513102625055769873401, 0.020801230123523916719604 }; static const double pol3[6] = { 0.00005767860320327097931, 0.029896654795890461899563, 0.0378739044968912982585405, 0.00971957088414193124615358, 0.000488576886695502361566636, 1.150549466178344373015667e-6 }; static const double pol4[5] = { 0.030306172539339585635388, 0.066596680780796068408204, 0.035483738872057375987452, 0.00506436278851840340711316, 0.0001465263028844943142786722 }; static const double pol5[6] = { 0.00048233868073637531461, 0.004268700087824343609188, 0.00127714949974214706149789, 0.0000799706171559085390983949, 1.186347211803672341928371e-6, 2.943454067276155504308283e-9 }; static const double pol6[6] = { 0.00553288881087242781512, 0.0043904877060733941697614, 0.00069354549834088964895342, 0.0000288257440032545960408328, 3.01054066921000066105342e-7, 4.94316029290773314755549e-10 }; static const double pol7[4] = { -0.93011683587619427070, -2.9702322028603227386, -2.0759083419960793148, -0.042485660005713612806 }; static const double pol8[4] = { 0.93011683587619458392, 4.3654074566738568022, 6.1437079650412473506, 2.4613195056093927345 }; static const double pol9[11] = { -1.0000000000000000000, 2.3316439815971242034, -1.8121878856393634902, 1.9366311144923597554, -2.3535512018816145168, 3.0668589010506319129, -4.1753356002581771389, 5.8580237298747741488, -8.4010322175239773710, 12.250753501314460424, -18.100697012472442755 }; static const double pol10[6] = { -5.1972986075163593071, -37.478686466672907613, -96.155193004929291698, -102.23856988136744607, -37.181958033133170210, -0.48504976999675644134 }; static const double pol11[6] = { 5.1972986074950082685, 45.274634378414741754, 150.20768172029114131, 233.88699813222871981, 167.13313463159765859, 42.171248374042409414 }; /* avoid overflows in the formula when x is close to 2^EMAX */ #define RESCALE 1.1102230246251565404e-16 static double halley(double x, double w) { double t, u, v; /* exp() does not overflow, since w is an underestimate when the asymptotic series is used */ t = exp(w) * RESCALE; u = 2*w + 2; v = w*t - x * RESCALE; t = w - u*v / (u*t*(w+1) - (w+2)*v); return t; } /* this should be exactly 6627126856707895 * 2^(-54) ~= 0.36787944117144228, which is the most negative double in the domain */ #define ONE_OVER_E ldexp(6627126856707895.0, -54) /* difference from -1/e */ #define CORRECTION 4.3082397558469466e-17 double d_lambertw(double x) { double t, u, w; if (x == 0.0 || x != x || x == D_INF) return x; if (x < 0.0) { /* complex result */ if (x < -ONE_OVER_E) return D_NAN; /* close to zero */ else if (x > -1e-9) return x - x * x; /* close to the singularity at -1/e */ else if (x + ONE_OVER_E < 0.0003) return POLY(pol9, sqrt((x + ONE_OVER_E) + CORRECTION)); /* otherwise get initial value for Halley iteration */ if (x + ONE_OVER_E < 0.04) w = POLY(pol9, sqrt((x + ONE_OVER_E) + CORRECTION)); else w = x * (1.0 + x * POLY(pol10, x) / POLY(pol11, x)); } else { /* close to zero */ if (x <= 0.03125) { if (x < 1e-9) return x - x * x; else return x * (1.0 + x * POLY(pol7, x) / POLY(pol8, x)); } /* get initial value for Halley iteration */ if (x <= 1.0) w = x * POLY(pol1, x) / POLY(pol2, x); else if (x <= 6.0) w = POLY(pol3, x) / POLY(pol4, x); else if (x <= 40.0) w = POLY(pol5, x) / POLY(pol6, x); else { /* asymptotic series */ t = log(x); u = log(t); w = (2*t*t*t - 2*(1+(t-1)*t)*u + u*u)/(2*t*t); /* one extra refinement */ if (x < 1e15) w = halley(x, w); } } return halley(x, w); } flint-3.1.3/src/double_extras/log2.c000066400000000000000000000010441461254215100172700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" double d_log2(double x) { static const double l2 = 0.6931471805599453; return log(x) / l2; } flint-3.1.3/src/double_extras/randtest.c000066400000000000000000000017631461254215100202610ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "ulong_extras.h" #define EXP_MINUS_32 2.3283064365386962891e-10 #define EXP_MINUS_64 5.42101086242752217e-20 double d_randtest(flint_rand_t state) { mp_limb_t m1, m2; double t; if (FLINT_BITS == 64) { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); t = ((double) m1) * EXP_MINUS_64; } else { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); m2 = n_randtest(state); t = ((double) m1) * EXP_MINUS_32 + ((double) m2) * EXP_MINUS_64; } if (t == 1) return 0.5; else return t; } flint-3.1.3/src/double_extras/randtest_signed.c000066400000000000000000000015001461254215100215770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "ulong_extras.h" double d_randtest_signed(flint_rand_t state, slong minexp, slong maxexp) { double d, t; slong exp, kind; d = d_randtest(state); exp = minexp + n_randint(state, maxexp - minexp + 1); t = ldexp(d, exp); kind = n_randint(state, 3); if (kind == 2) return t; else if (kind == 1) return -t; else return 0; } flint-3.1.3/src/double_extras/randtest_special.c000066400000000000000000000020641461254215100217540ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "ulong_extras.h" double d_randtest_special(flint_rand_t state, slong minexp, slong maxexp) { double d, t; slong exp, kind; d = d_randtest(state); exp = minexp + n_randint(state, maxexp - minexp + 1); t = ldexp(d, exp); kind = n_randint(state, 4); if (kind == 3) return t; else if (kind == 2) return -t; else if (kind == 1) return 0; else { if (n_randint(state, 2)) return D_NAN; else { if (n_randint(state, 2)) return D_INF; else return -D_INF; } } } flint-3.1.3/src/double_extras/test/000077500000000000000000000000001461254215100172415ustar00rootroot00000000000000flint-3.1.3/src/double_extras/test/main.c000066400000000000000000000020211461254215100203240ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-is_nan.c" #include "t-lambertw.c" #include "t-log2.c" #include "t-mul_2exp.c" #include "t-randtest.c" #include "t-randtest_signed.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(d_is_nan), TEST_FUNCTION(d_lambertw), TEST_FUNCTION(d_log2), TEST_FUNCTION(d_mul_2exp), TEST_FUNCTION(d_randtest), TEST_FUNCTION(d_randtest_signed) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/double_extras/test/t-is_nan.c000066400000000000000000000021331461254215100211140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "double_extras.h" TEST_FUNCTION_START(d_is_nan, state) { double x; slong iter; /* check non-zero value returned if x == NaN */ x = D_NAN; if (!d_is_nan(x)) TEST_FUNCTION_FAIL("0 returned for %g\n", x); /* check 0 returned if x != NaN */ x = D_INF; if (d_is_nan(x)) TEST_FUNCTION_FAIL("Non-zero returned for %g\n", x); for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest_signed(state, 0, 0); if (d_is_nan(x)) TEST_FUNCTION_FAIL("Non-zero returned for %g\n", x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/double_extras/test/t-lambertw.c000066400000000000000000000067721461254215100214770ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include #include "ulong_extras.h" #include "double_extras.h" #define ONE_OVER_E ldexp(6627126856707895.0, -54) TEST_FUNCTION_START(d_lambertw, state) { double x, w, tol; slong iter, prec = 70; mpfr_t xx, ww, wnew, t, u, v, p, q, max_err; mpfr_init2(xx, prec); mpfr_init2(ww, prec); mpfr_init2(wnew, prec); mpfr_init2(t, prec); mpfr_init2(u, prec); mpfr_init2(v, prec); mpfr_init2(p, prec); mpfr_init2(q, prec); mpfr_init2(max_err, prec); mpfr_set_ui(max_err, 0, MPFR_RNDN); for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest(state); switch (n_randint(state, 3)) { /* singularity near -1/e */ case 0: x = ldexp(x, -n_randint(state, -DBL_MIN_EXP+1)); x = -ONE_OVER_E + x; tol = 50 * DBL_EPSILON; break; /* negative, not close to -1/e */ case 1: x = d_randtest(state); x = ldexp(x, -n_randint(state, -DBL_MIN_EXP+1)); x = x * -(1./4); tol = 2 * DBL_EPSILON; break; /* positive */ default: x = d_randtest(state); x = ldexp(x, (int) n_randint(state, DBL_MAX_EXP-DBL_MIN_EXP-1) + DBL_MIN_EXP); tol = 2 * DBL_EPSILON; break; } w = d_lambertw(x); mpfr_set_d(xx, x, MPFR_RNDN); mpfr_set_d(ww, w, MPFR_RNDN); /* t = exp(w) */ mpfr_exp(t, ww, MPFR_RNDN); /* u = 2*w + 2 */ mpfr_mul_ui(u, ww, 2, MPFR_RNDN); mpfr_add_ui(u, u, 2, MPFR_RNDN); /* v = w*t - x */ mpfr_mul(v, t, ww, MPFR_RNDN); mpfr_sub(v, v, xx, MPFR_RNDN); /* p = u * v */ mpfr_mul(p, u, v, MPFR_RNDN); /* q = (u*t*(w+1) - (w+2)*v) */ mpfr_mul(q, u, t, MPFR_RNDN); mpfr_add_ui(t, ww, 1, MPFR_RNDN); mpfr_mul(q, q, t, MPFR_RNDN); mpfr_add_ui(t, ww, 2, MPFR_RNDN); mpfr_mul(t, t, v, MPFR_RNDN); mpfr_sub(q, q, t, MPFR_RNDN); /* wnew = w - p / q */ mpfr_div(p, p, q, MPFR_RNDN); mpfr_sub(wnew, ww, p, MPFR_RNDN); /* relative error */ mpfr_sub(t, ww, wnew, MPFR_RNDA); mpfr_div(t, t, wnew, MPFR_RNDA); mpfr_abs(t, t, MPFR_RNDA); if (mpfr_get_d(t, MPFR_RNDA) > tol) TEST_FUNCTION_FAIL("x = %.17g, w = %.17g, error = %g\n", x, w, mpfr_get_d(t, MPFR_RNDA)); #if 0 if (mpfr_cmp(t, max_err) > 0) { flint_printf("new record: "); flint_printf("x=%.20g w=%.20g wnew=%.20g relative error: %g\n", x, w, mpfr_get_d(wnew, MPFR_RNDN), mpfr_get_d(t, MPFR_RNDN)); mpfr_set(max_err, t, MPFR_RNDN); } #endif } mpfr_clear(xx); mpfr_clear(ww); mpfr_clear(wnew); mpfr_clear(t); mpfr_clear(u); mpfr_clear(v); mpfr_clear(p); mpfr_clear(q); mpfr_clear(max_err); mpfr_free_cache(); TEST_FUNCTION_END(state); } flint-3.1.3/src/double_extras/test/t-log2.c000066400000000000000000000020371461254215100205130ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "double_extras.h" TEST_FUNCTION_START(d_log2, state) { double x, res1, res2; slong iter; /* check change of base identity */ for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest(state); res1 = d_log2(x) * log(2); res2 = log(x); if (fabs(res1 - res2) > D_EPS) TEST_FUNCTION_FAIL( "x = %.20g\n" "res1 = %.20g\n" "res2 = %.20g\n", x, res1, res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/double_extras/test/t-mul_2exp.c000066400000000000000000000054401461254215100214040ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "double_extras.h" #include "d_vec.h" static int _check_results(double res1, double res2) { if (d_is_nan(res2)) return d_is_nan(res1); else #if !defined(_MSC_VER) return res1 == res2; #else /* MSVC's ldexp doesn't give the same result as multiplying by 2^e for subnormals, so relax the test */ return (res1 == res2) || fabs(res1 - res2) < 1e-300; #endif } TEST_FUNCTION_START(d_mul_2exp, state) { double x, res1, res2; int e; slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest_special(state, -1024, 1024); e = n_randint(state, 3000) - 1500; res1 = d_mul_2exp(x, e); res2 = ldexp(x, e); if (!_check_results(res1, res2)) TEST_FUNCTION_FAIL("x = %.20g\n res1 = %.20g\n res2 = %.20g\n", x, res1, res2); } for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { do { x = d_randtest_signed(state, -256, 256); } while (x == 0.0); e = n_randint(state, 512) - 256; res1 = d_mul_2exp_inrange2(x, e); res2 = ldexp(x, e); if (!(res1 == res2)) TEST_FUNCTION_FAIL("x = %.20g\n res1 = %.20g\n res2 = %.20g\n", x, res1, res2); } for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest_special(state, -1024, 1024); e = n_randint(state, D_MAX_NORMAL_EXPONENT - D_MIN_NORMAL_EXPONENT + 1) + D_MIN_NORMAL_EXPONENT; res1 = d_mul_2exp_inrange(x, e); res2 = ldexp(x, e); if (!_check_results(res1, res2)) TEST_FUNCTION_FAIL("x = %.20g\n res1 = %.20g\n res2 = %.20g\n", x, res1, res2); } for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { double v[5] = { 0, 0, 0, 0, 0 }; double r[10] = { 0, 0, 0, 0, 0 }; slong i, n = n_randint(state, 5); for (i = 0; i < n; i++) x = d_randtest_special(state, -1024, 1024); e = n_randint(state, 3000) - 1500; _d_vec_mul_2exp(r, v, n, e); for (i = 0; i < n; i++) { res1 = r[i]; res2 = ldexp(v[i], e); if (!_check_results(res1, res2)) TEST_FUNCTION_FAIL("x = %.20g\n res1 = %.20g\n res2 = %.20g\n", x, res1, res2); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/double_extras/test/t-randtest.c000066400000000000000000000015321461254215100214730ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "double_extras.h" TEST_FUNCTION_START(d_randtest, state) { double x; slong iter; /* check that values lie in [0.5, 1) */ for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest(state); if (x < 0.5 || x >= 1) TEST_FUNCTION_FAIL("x = %.17g\n", x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/double_extras/test/t-randtest_signed.c000066400000000000000000000016441461254215100230300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "double_extras.h" TEST_FUNCTION_START(d_randtest_signed, state) { double x; slong iter; /* check that values lie in [0.5, 1) U {0} for minexp = maxexp = 0 */ for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest_signed(state, 0, 0); if ((fabs(x) < 0.5 && x != 0) || fabs(x) >= 1) TEST_FUNCTION_FAIL("x = %.17g\n", x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/double_interval.h000066400000000000000000000073571461254215100167650ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef DOUBLE_INTERVAL_H #define DOUBLE_INTERVAL_H #ifdef DOUBLE_INTERVAL_INLINES_C #define DOUBLE_INTERVAL_INLINE #else #define DOUBLE_INTERVAL_INLINE static inline #endif #include #include "double_extras.h" #include "arb_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { double a; double b; } di_t; #define DI_CHECK(__x) \ if (!(__x.a <= __x.b)) \ { \ flint_throw(FLINT_ERROR, "di_t endpoints %g, %g not ordered\n", __x.a, __x.b); \ } \ DOUBLE_INTERVAL_INLINE di_t di_interval(double a, double b) { di_t res; if (!(a <= b)) { flint_throw(FLINT_ERROR, "di_interval endpoints %g, %g not ordered\n", a, b); } res.a = a; res.b = b; return res; } DOUBLE_INTERVAL_INLINE double _di_below(double x) { double t; if (x <= 1e300) { t = x; if (t < 0.0) t = -t; t += 1e-300; return x - t * 4.440892098500626e-16; } else { if (x != x) return -D_INF; return 1e300; } } DOUBLE_INTERVAL_INLINE double _di_above(double x) { double t; if (x >= -1e300) { t = x; if (t < 0.0) t = -t; t += 1e-300; return x + t * 4.440892098500626e-16; } else { if (x != x) return D_INF; return -1e300; } } DOUBLE_INTERVAL_INLINE di_t di_neg(di_t x) { di_t res; res.a = -x.b; res.b = -x.a; return res; } DOUBLE_INTERVAL_INLINE di_t di_fast_add(di_t x, di_t y) { di_t res; res.a = _di_below(x.a + y.a); res.b = _di_above(x.b + y.b); return res; } DOUBLE_INTERVAL_INLINE di_t di_fast_sub(di_t x, di_t y) { di_t res; res.a = _di_below(x.a - y.b); res.b = _di_above(x.b - y.a); return res; } di_t di_fast_mul(di_t x, di_t y); di_t di_fast_sqr(di_t x); di_t di_fast_div(di_t x, di_t y); DOUBLE_INTERVAL_INLINE di_t di_fast_add_d(di_t x, double y) { return di_fast_add(x, di_interval(y, y)); } DOUBLE_INTERVAL_INLINE di_t di_fast_sub_d(di_t x, double y) { return di_fast_sub(x, di_interval(y, y)); } DOUBLE_INTERVAL_INLINE di_t di_fast_mul_d(di_t x, double y) { return di_fast_mul(x, di_interval(y, y)); } DOUBLE_INTERVAL_INLINE di_t di_fast_div_d(di_t x, double y) { return di_fast_div(x, di_interval(y, y)); } di_t di_fast_log_nonnegative(di_t x); DOUBLE_INTERVAL_INLINE di_t di_fast_mid(di_t x) { di_t a, b; if (x.a == -D_INF || x.b == D_INF) return di_interval(-D_INF, D_INF); a = di_interval(x.a, x.a); b = di_interval(x.b, x.b); return di_fast_mul_d(di_fast_add(a, b), 0.5); } DOUBLE_INTERVAL_INLINE double di_fast_ubound_radius(di_t x) { return _di_above((x.b - x.a) * 0.5); } DOUBLE_INTERVAL_INLINE void di_print(di_t x) { flint_printf("[%.17g, %.17g]", x.a, x.b); } di_t arb_get_di(const arb_t x); void arb_set_di(arb_t res, di_t x, slong prec); DOUBLE_INTERVAL_INLINE double d_randtest2(flint_rand_t state) { double x; x = d_randtest(state); if (n_randint(state, 2)) x = -x; return ldexp(x, n_randint(state, 2400) - 1200); } DOUBLE_INTERVAL_INLINE di_t di_randtest(flint_rand_t state) { di_t res; res.a = d_randtest2(state); res.b = d_randtest2(state); if (res.a > res.b) { double t = res.a; res.a = res.b; res.b = t; } return res; } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/double_interval/000077500000000000000000000000001461254215100166005ustar00rootroot00000000000000flint-3.1.3/src/double_interval/arb_get_di.c000066400000000000000000000015031461254215100210220ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_interval.h" #include "arb.h" di_t arb_get_di(const arb_t x) { di_t res; if (arf_is_nan(arb_midref(x))) { res.a = -D_INF; res.b = D_INF; } else { arf_t t; arf_init(t); arb_get_lbound_arf(t, x, 53); res.a = arf_get_d(t, ARF_RND_FLOOR); arb_get_ubound_arf(t, x, 53); res.b = arf_get_d(t, ARF_RND_CEIL); arf_clear(t); } return res; } flint-3.1.3/src/double_interval/arb_set_di.c000066400000000000000000000012201461254215100210320ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_interval.h" #include "arb.h" void arb_set_di(arb_t res, di_t x, slong prec) { arf_t t, u; arf_init(t); arf_init(u); arf_set_d(t, x.a); arf_set_d(u, x.b); arb_set_interval_arf(res, t, u, prec); arf_clear(t); arf_clear(u); } flint-3.1.3/src/double_interval/fast_div.c000066400000000000000000000024121461254215100205420ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_interval.h" di_t di_fast_div(di_t x, di_t y) { di_t res; if (y.a > 0) { if (x.a >= 0) { res.a = x.a / y.b; res.b = x.b / y.a; } else if (x.b <= 0) { res.a = x.a / y.a; res.b = x.b / y.b; } else { res.a = x.a / y.a; res.b = x.b / y.a; } } else if (y.b < 0) { if (x.a >= 0) { res.a = x.b / y.b; res.b = x.a / y.a; } else if (x.b <= 0) { res.a = x.b / y.a; res.b = x.a / y.b; } else { res.a = x.b / y.b; res.b = x.a / y.b; } } else { res.a = -D_INF; res.b = D_INF; } res.a = _di_below(res.a); res.b = _di_above(res.b); return res; } flint-3.1.3/src/double_interval/fast_log_nonnegative.c000066400000000000000000000013221461254215100231350ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_interval.h" #include "mag.h" double mag_d_log_lower_bound(double x); double mag_d_log_upper_bound(double x); di_t di_fast_log_nonnegative(di_t x) { di_t res; if (x.a <= 0.0) res.a = -D_INF; else res.a = mag_d_log_lower_bound(x.a); res.b = mag_d_log_upper_bound(x.b); return res; } flint-3.1.3/src/double_interval/fast_mul.c000066400000000000000000000025241461254215100205610ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_interval.h" di_t di_fast_mul(di_t x, di_t y) { di_t res; if (x.a > 0 && y.a > 0) { res.a = x.a * y.a; res.b = x.b * y.b; } else if (x.a > 0 && y.b < 0) { res.a = x.b * y.a; res.b = x.a * y.b; } else if (x.b < 0 && y.a > 0) { res.a = x.a * y.b; res.b = x.b * y.a; } else if (x.b < 0 && y.b < 0) { res.a = x.b * y.b; res.b = x.a * y.a; } else { double a, b, c, d; a = x.a * y.a; b = x.a * y.b; c = x.b * y.a; d = x.b * y.b; if (a != a || b != b || c != c || d != d) { res.a = -D_INF; res.b = D_INF; } else { res.a = FLINT_MIN(FLINT_MIN(a, b), FLINT_MIN(c, d)); res.b = FLINT_MAX(FLINT_MAX(a, b), FLINT_MAX(c, d)); } } res.a = _di_below(res.a); res.b = _di_above(res.b); return res; } flint-3.1.3/src/double_interval/fast_sqr.c000066400000000000000000000014721461254215100205720ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_interval.h" di_t di_fast_sqr(di_t x) { di_t res; if (x.a >= 0) { res.a = x.a * x.a; res.b = x.b * x.b; } else if (x.b <= 0) { res.a = x.b * x.b; res.b = x.a * x.a; } else { res.a = 0.0; res.b = FLINT_MAX(x.a * x.a, x.b * x.b); } if (res.a != 0.0) res.a = _di_below(res.a); res.b = _di_above(res.b); return res; } flint-3.1.3/src/double_interval/inlines.c000066400000000000000000000006761461254215100204160ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define DOUBLE_INTERVAL_INLINES_C #include "double_interval.h" flint-3.1.3/src/double_interval/test/000077500000000000000000000000001461254215100175575ustar00rootroot00000000000000flint-3.1.3/src/double_interval/test/main.c000066400000000000000000000015551461254215100206550ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-fast_add.c" #include "t-fast_div.c" #include "t-fast_mul.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(di_fast_add), TEST_FUNCTION(di_fast_div), TEST_FUNCTION(di_fast_mul) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/double_interval/test/t-fast_add.c000066400000000000000000000035521461254215100217360ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "double_interval.h" TEST_FUNCTION_START(di_fast_add, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { di_t x, y, z; arf_t a, b, t, za, zb; arf_init(a); arf_init(b); arf_init(t); arf_init(za); arf_init(zb); x = di_randtest(state); y = di_randtest(state); z = di_fast_add(x, y); DI_CHECK(z) arf_set_d(a, x.a); arf_set_d(t, y.a); arf_add(a, a, t, ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_d(b, x.b); arf_set_d(t, y.b); arf_add(b, b, t, ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_d(za, z.a); arf_set_d(zb, z.b); if (arf_cmp(a, za) < 0 || arf_cmp(b, zb) > 0) { flint_printf("FAIL\n"); flint_printf("x = "); di_print(x); printf("\n"); flint_printf("y = "); di_print(y); printf("\n"); flint_printf("z = "); di_print(z); printf("\n"); flint_printf("a = "); arf_printd(a, 20); printf("\n"); flint_printf("b = "); arf_printd(b, 20); printf("\n"); flint_printf("za = "); arf_printd(za, 20); printf("\n"); flint_printf("zb = "); arf_printd(zb, 20); printf("\n"); flint_abort(); } arf_clear(a); arf_clear(b); arf_clear(t); arf_clear(za); arf_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/double_interval/test/t-fast_div.c000066400000000000000000000066771461254215100220030ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "double_interval.h" /* Defined in t-fast_div.c and t-fast_mul.c */ #ifndef arf_min2 #define arf_min2 arf_min2 void arf_min2(arf_t res, const arf_t x, const arf_t y) { if (arf_is_nan(x)) arf_set(res, y); else if (arf_is_nan(y)) arf_set(res, x); else arf_min(res, x, y); } #endif /* Defined in t-fast_div.c and t-fast_mul.c */ #ifndef arf_max2 #define arf_max2 arf_max2 void arf_max2(arf_t res, const arf_t x, const arf_t y) { if (arf_is_nan(x)) arf_set(res, y); else if (arf_is_nan(y)) arf_set(res, x); else arf_max(res, x, y); } #endif TEST_FUNCTION_START(di_fast_div, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { di_t x, y, z; arf_t a, b, c, d, ra, rb, rc, rd, va, vb, za, zb; arf_init(a); arf_init(b); arf_init(c); arf_init(d); arf_init(ra); arf_init(rb); arf_init(rc); arf_init(rd); arf_init(va); arf_init(vb); arf_init(za); arf_init(zb); x = di_randtest(state); y = di_randtest(state); z = di_fast_div(x, y); DI_CHECK(z) arf_set_d(a, x.a); arf_set_d(b, x.b); arf_set_d(c, y.a); arf_set_d(d, y.b); arf_div(ra, a, c, 106, ARF_RND_DOWN); arf_div(rb, a, d, 106, ARF_RND_DOWN); arf_div(rc, b, c, 106, ARF_RND_DOWN); arf_div(rd, b, d, 106, ARF_RND_DOWN); arf_min2(va, ra, rb); arf_min2(va, va, rc); arf_min2(va, va, rd); arf_max2(vb, ra, rb); arf_max2(vb, vb, rc); arf_max2(vb, vb, rd); arf_set_d(za, z.a); arf_set_d(zb, z.b); if (arf_cmp(va, za) < 0 || arf_cmp(vb, zb) > 0) { flint_printf("FAIL\n"); flint_printf("x = "); di_print(x); printf("\n"); flint_printf("y = "); di_print(y); printf("\n"); flint_printf("z = "); di_print(z); printf("\n"); flint_printf("a = "); arf_printd(a, 20); printf("\n"); flint_printf("b = "); arf_printd(b, 20); printf("\n"); flint_printf("c = "); arf_printd(c, 20); printf("\n"); flint_printf("d = "); arf_printd(d, 20); printf("\n"); flint_printf("ra = "); arf_printd(ra, 20); printf("\n"); flint_printf("rb = "); arf_printd(rb, 20); printf("\n"); flint_printf("rc = "); arf_printd(rc, 20); printf("\n"); flint_printf("rd = "); arf_printd(rd, 20); printf("\n"); flint_printf("va = "); arf_printd(va, 20); printf("\n"); flint_printf("vb = "); arf_printd(vb, 20); printf("\n"); flint_printf("za = "); arf_printd(za, 20); printf("\n"); flint_printf("zb = "); arf_printd(zb, 20); printf("\n"); flint_abort(); } arf_clear(a); arf_clear(b); arf_clear(c); arf_clear(d); arf_clear(ra); arf_clear(rb); arf_clear(rc); arf_clear(rd); arf_clear(va); arf_clear(vb); arf_clear(za); arf_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/double_interval/test/t-fast_mul.c000066400000000000000000000073551461254215100220100ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "double_interval.h" /* Defined in t-fast_div.c and t-fast_mul.c */ #ifndef arf_min2 #define arf_min2 arf_min2 void arf_min2(arf_t res, const arf_t x, const arf_t y) { if (arf_is_nan(x)) arf_set(res, y); else if (arf_is_nan(y)) arf_set(res, x); else arf_min(res, x, y); } #endif /* Defined in t-fast_div.c and t-fast_mul.c */ #ifndef arf_max2 #define arf_max2 arf_max2 void arf_max2(arf_t res, const arf_t x, const arf_t y) { if (arf_is_nan(x)) arf_set(res, y); else if (arf_is_nan(y)) arf_set(res, x); else arf_max(res, x, y); } #endif TEST_FUNCTION_START(di_fast_mul, state) { slong iter; for (iter = 0; iter < 1000000 * 0.1 * flint_test_multiplier(); iter++) { di_t x, y, z; arf_t a, b, c, d, ra, rb, rc, rd, va, vb, za, zb; arf_init(a); arf_init(b); arf_init(c); arf_init(d); arf_init(ra); arf_init(rb); arf_init(rc); arf_init(rd); arf_init(va); arf_init(vb); arf_init(za); arf_init(zb); if (iter == 0) { x.a = 3.5835915908219665e+103; x.b = 4.0874812242073031e+295; y.a = -8.3711609938763647e+298; y.b = -3.414037107833399e+243; } else { x = di_randtest(state); y = di_randtest(state); } z = di_fast_mul(x, y); DI_CHECK(z) arf_set_d(a, x.a); arf_set_d(b, x.b); arf_set_d(c, y.a); arf_set_d(d, y.b); arf_mul(ra, a, c, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(rb, a, d, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(rc, b, c, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul(rd, b, d, ARF_PREC_EXACT, ARF_RND_DOWN); arf_min2(va, ra, rb); arf_min2(va, va, rc); arf_min2(va, va, rd); arf_max2(vb, ra, rb); arf_max2(vb, vb, rc); arf_max2(vb, vb, rd); arf_set_d(za, z.a); arf_set_d(zb, z.b); if (arf_cmp(va, za) < 0 || arf_cmp(vb, zb) > 0) { flint_printf("FAIL\n"); flint_printf("x = "); di_print(x); printf("\n"); flint_printf("y = "); di_print(y); printf("\n"); flint_printf("z = "); di_print(z); printf("\n"); flint_printf("a = "); arf_printd(a, 20); printf("\n"); flint_printf("b = "); arf_printd(b, 20); printf("\n"); flint_printf("c = "); arf_printd(c, 20); printf("\n"); flint_printf("d = "); arf_printd(d, 20); printf("\n"); flint_printf("ra = "); arf_printd(ra, 20); printf("\n"); flint_printf("rb = "); arf_printd(rb, 20); printf("\n"); flint_printf("rc = "); arf_printd(rc, 20); printf("\n"); flint_printf("rd = "); arf_printd(rd, 20); printf("\n"); flint_printf("va = "); arf_printd(va, 20); printf("\n"); flint_printf("vb = "); arf_printd(vb, 20); printf("\n"); flint_printf("za = "); arf_printd(za, 20); printf("\n"); flint_printf("zb = "); arf_printd(zb, 20); printf("\n"); flint_abort(); } arf_clear(a); arf_clear(b); arf_clear(c); arf_clear(d); arf_clear(ra); arf_clear(rb); arf_clear(rc); arf_clear(rd); arf_clear(va); arf_clear(vb); arf_clear(za); arf_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fexpr.h000066400000000000000000000373251461254215100147310ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FEXPR_H #define FEXPR_H #ifdef FEXPR_INLINES_C #define FEXPR_INLINE #else #define FEXPR_INLINE static inline #endif #ifdef __cplusplus extern "C" { #endif #include "mpoly_types.h" #include "calcium.h" #define FEXPR_TYPE_SMALL_INT UWORD(0) #define FEXPR_TYPE_SMALL_SYMBOL UWORD(1) #define FEXPR_TYPE_SMALL_STRING UWORD(2) #define FEXPR_TYPE_BIG_INT_POS UWORD(3) #define FEXPR_TYPE_BIG_INT_NEG UWORD(4) #define FEXPR_TYPE_BIG_SYMBOL UWORD(5) #define FEXPR_TYPE_BIG_STRING UWORD(6) #define FEXPR_TYPE_CALL0 UWORD(7) #define FEXPR_TYPE_CALL1 UWORD(8) #define FEXPR_TYPE_CALL2 UWORD(9) #define FEXPR_TYPE_CALL3 UWORD(10) #define FEXPR_TYPE_CALL4 UWORD(11) #define FEXPR_TYPE_CALLN UWORD(12) #define FEXPR_TYPE_BITS 4 #define FEXPR_TYPE_MASK ((UWORD(1) << FEXPR_TYPE_BITS) - 1) #define FEXPR_COEFF_MAX ((WORD(1) << (FLINT_BITS - FEXPR_TYPE_BITS - 1)) - 1) #define FEXPR_COEFF_MIN (-FEXPR_COEFF_MAX) #define FEXPR_TYPE(head) ((head) & FEXPR_TYPE_MASK) #define FEXPR_SIZE(head) ((slong) ((FEXPR_TYPE(head) <= FEXPR_TYPE_SMALL_STRING) ? 1 : (head) >> FEXPR_TYPE_BITS)) #define FEXPR_HEADER_SIZE WORD(1) #define FEXPR_SMALL_SYMBOL_LEN ((FLINT_BITS / 8) - 1) #define FEXPR_BUILTIN_ID(head) ((head) >> 16) typedef struct { ulong * data; slong alloc; } fexpr_struct; typedef fexpr_struct fexpr_t[1]; typedef fexpr_struct * fexpr_ptr; typedef const fexpr_struct * fexpr_srcptr; typedef struct { fexpr_struct * entries; slong alloc; slong length; } fexpr_vec_struct; typedef fexpr_vec_struct fexpr_vec_t[1]; #define fexpr_vec_entry(vec, i) ((vec)->entries + (i)) FEXPR_INLINE void fexpr_init(fexpr_t expr) { expr->data = (ulong *) flint_malloc(sizeof(ulong)); expr->data[0] = 0; expr->alloc = 1; } FEXPR_INLINE void fexpr_clear(fexpr_t expr) { flint_free(expr->data); } FEXPR_INLINE fexpr_ptr _fexpr_vec_init(slong len) { slong i; fexpr_ptr vec = (fexpr_ptr) flint_malloc(sizeof(fexpr_struct) * len); for (i = 0; i < len; i++) fexpr_init(vec + i); return vec; } FEXPR_INLINE void _fexpr_vec_clear(fexpr_ptr vec, slong len) { slong i; for (i = 0; i < len; i++) fexpr_clear(vec + i); flint_free(vec); } FEXPR_INLINE void fexpr_fit_size(fexpr_t expr, slong size) { if (expr->alloc < size) { size = FLINT_MAX(size, 2 * expr->alloc); expr->data = (ulong *) flint_realloc(expr->data, size * sizeof(ulong)); expr->alloc = size; } } FEXPR_INLINE slong _fexpr_size(const ulong * expr) { ulong head = expr[0]; return FEXPR_SIZE(head); } FEXPR_INLINE slong fexpr_size(const fexpr_t expr) { return _fexpr_size(expr->data); } FEXPR_INLINE void fexpr_set(fexpr_t res, const fexpr_t expr) { if (res != expr) { slong size = fexpr_size(expr); fexpr_fit_size(res, size); flint_mpn_copyi(res->data, expr->data, size); } } FEXPR_INLINE void fexpr_swap(fexpr_t a, fexpr_t b) { FLINT_SWAP(fexpr_struct, *a, *b); } FEXPR_INLINE int _mpn_equal(mp_srcptr a, mp_srcptr b, slong len) { slong i; for (i = 0; i < len; i++) if (a[i] != b[i]) return 0; return 1; } FEXPR_INLINE int fexpr_equal(const fexpr_t a, const fexpr_t b) { ulong ha, hb; slong sa, sb; ha = a->data[0]; hb = b->data[0]; if (ha != hb) return 0; sa = FEXPR_SIZE(ha); sb = FEXPR_SIZE(hb); if (sa != sb) return 0; return _mpn_equal(a->data + 1, b->data + 1, sa - 1); } /* todo: document, test */ int fexpr_equal_si(const fexpr_t expr, slong c); int fexpr_equal_ui(const fexpr_t expr, ulong c); ulong fexpr_hash(const fexpr_t expr); int fexpr_cmp_fast(const fexpr_t a, const fexpr_t b); void _fexpr_vec_sort_fast(fexpr_ptr vec, slong len); FEXPR_INLINE int _fexpr_is_integer(const ulong * expr) { ulong type = FEXPR_TYPE(expr[0]); return (type == FEXPR_TYPE_SMALL_INT) || (type == FEXPR_TYPE_BIG_INT_POS) || (type == FEXPR_TYPE_BIG_INT_NEG); } FEXPR_INLINE int fexpr_is_integer(const fexpr_t expr) { return _fexpr_is_integer(expr->data); } /* todo: document, test */ int fexpr_is_neg_integer(const fexpr_t expr); FEXPR_INLINE int _fexpr_is_symbol(const ulong * expr) { ulong type = FEXPR_TYPE(expr[0]); return (type == FEXPR_TYPE_SMALL_SYMBOL) || (type == FEXPR_TYPE_BIG_SYMBOL); } FEXPR_INLINE int fexpr_is_symbol(const fexpr_t expr) { return _fexpr_is_symbol(expr->data); } FEXPR_INLINE int _fexpr_is_string(const ulong * expr) { ulong type = FEXPR_TYPE(expr[0]); return (type == FEXPR_TYPE_SMALL_STRING) || (type == FEXPR_TYPE_BIG_STRING); } FEXPR_INLINE int fexpr_is_string(const fexpr_t expr) { return _fexpr_is_string(expr->data); } FEXPR_INLINE int _fexpr_is_atom(const ulong * expr) { return FEXPR_TYPE(expr[0]) <= FEXPR_TYPE_BIG_STRING; } FEXPR_INLINE int fexpr_is_atom(const fexpr_t expr) { return _fexpr_is_atom(expr->data); } FEXPR_INLINE void fexpr_zero(fexpr_t res) { res->data[0] = 0; } FEXPR_INLINE int fexpr_is_zero(const fexpr_t expr) { return expr->data[0] == 0; } void fexpr_set_si(fexpr_t res, slong c); void fexpr_set_ui(fexpr_t res, ulong c); void fexpr_set_fmpz(fexpr_t res, const fmpz_t c); int fexpr_get_fmpz(fmpz_t c, const fexpr_t x); void fexpr_set_fmpq(fexpr_t res, const fmpq_t x); FEXPR_INLINE void fexpr_set_symbol_builtin(fexpr_t res, slong id) { res->data[0] = FEXPR_TYPE_SMALL_SYMBOL | (id << 16); } void fexpr_set_symbol_str(fexpr_t res, const char * s); char * fexpr_get_symbol_str(const fexpr_t expr); void fexpr_set_string(fexpr_t res, const char * s); char * fexpr_get_string(const fexpr_t expr); slong fexpr_depth(const fexpr_t expr); slong fexpr_num_leaves(const fexpr_t expr); FEXPR_INLINE slong fexpr_size_bytes(const fexpr_t expr) { return fexpr_size(expr) * sizeof(ulong); } FEXPR_INLINE slong fexpr_allocated_bytes(const fexpr_t expr) { return expr->alloc * sizeof(ulong); } /* todo: document */ FEXPR_INLINE int fexpr_is_any_builtin_symbol(const fexpr_t expr) { ulong head; head = expr->data[0]; return (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_SYMBOL) && (((head >> 8) & 0xff) == 0); } /* todo: document */ FEXPR_INLINE int fexpr_is_builtin_symbol(const fexpr_t expr, slong i) { ulong head; head = expr->data[0]; return (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_SYMBOL) && (((head >> 8) & 0xff) == 0) && (FEXPR_BUILTIN_ID(head) == i); } /* todo: document, test */ int fexpr_is_builtin_call(const fexpr_t expr, slong i); int fexpr_is_any_builtin_call(const fexpr_t expr); FEXPR_INLINE slong fexpr_nargs(const fexpr_t expr) { ulong type = FEXPR_TYPE(expr->data[0]); if (FEXPR_TYPE_CALL0 <= type && type <= FEXPR_TYPE_CALL4) { return type - FEXPR_TYPE_CALL0; } else if (type == FEXPR_TYPE_CALLN) { return expr->data[1]; } else { return -1; } } void fexpr_func(fexpr_t res, const fexpr_t expr); void fexpr_view_func(fexpr_t res, const fexpr_t expr); void fexpr_arg(fexpr_t res, const fexpr_t expr, slong i); void fexpr_view_arg(fexpr_t res, const fexpr_t expr, slong i); FEXPR_INLINE void fexpr_view_next(fexpr_t view) { view->data += fexpr_size(view); } /* todo: handle aliasing! */ void fexpr_call0(fexpr_t res, const fexpr_t f); void fexpr_call1(fexpr_t res, const fexpr_t f, const fexpr_t x1); void fexpr_call2(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2); void fexpr_call3(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3); void fexpr_call4(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3, const fexpr_t x4); void fexpr_call_vec(fexpr_t res, const fexpr_t f, fexpr_srcptr args, slong len); void fexpr_call_builtin1(fexpr_t res, slong f, const fexpr_t x); void fexpr_call_builtin2(fexpr_t res, slong f, const fexpr_t x, const fexpr_t y); /* Subexpressions and replacement */ int fexpr_contains(const fexpr_t expr, const fexpr_t x); int fexpr_replace(fexpr_t res, const fexpr_t expr, const fexpr_t x, const fexpr_t y); int fexpr_replace2(fexpr_t res, const fexpr_t expr, const fexpr_t x1, const fexpr_t y1, const fexpr_t x2, const fexpr_t y2); int fexpr_replace_vec(fexpr_t res, const fexpr_t expr, const fexpr_vec_t xs, const fexpr_vec_t ys); /* Input/output */ void fexpr_write(calcium_stream_t stream, const fexpr_t expr); void fexpr_print(const fexpr_t expr); char * fexpr_get_str(const fexpr_t expr); /* LaTeX output */ #define FEXPR_LATEX_SMALL 1 #define FEXPR_LATEX_LOGIC 2 void fexpr_write_latex(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_print_latex(const fexpr_t expr, ulong flags); char * fexpr_get_str_latex(const fexpr_t expr, ulong flags); void fexpr_write_latex_call(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_subscript(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_subscript_call(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_infix(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_mul(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_div(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_neg_pos(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_add(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_sub(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_pow(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_exp(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_factorial(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_integral(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_sum_product(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_divsum(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_limit(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_logic(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_collection(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_matrix(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_simple(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_simple2(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_simple2_small(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_alg_structure(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_setop(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_cases(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_where(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_show_form(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_range(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_decimal(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_call1_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_call2_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_sub1_call1_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_sub1_call2_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_misc_special(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_write_latex_residue(calcium_stream_t out, const fexpr_t expr, ulong flags); void fexpr_set_arf(fexpr_t res, const arf_t x); void fexpr_set_d(fexpr_t res, double x); void fexpr_set_re_im_d(fexpr_t res, double x, double y); void fexpr_neg(fexpr_t res, const fexpr_t a); void fexpr_add(fexpr_t res, const fexpr_t a, const fexpr_t b); void fexpr_sub(fexpr_t res, const fexpr_t a, const fexpr_t b); void fexpr_mul(fexpr_t res, const fexpr_t a, const fexpr_t b); void fexpr_div(fexpr_t res, const fexpr_t a, const fexpr_t b); void fexpr_pow(fexpr_t res, const fexpr_t a, const fexpr_t b); int fexpr_is_arithmetic_operation(const fexpr_t expr); void fexpr_arithmetic_nodes(fexpr_vec_t nodes, const fexpr_t expr); int fexpr_get_fmpz_mpoly_q(fmpz_mpoly_q_t res, const fexpr_t expr, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx); void fexpr_set_fmpz_mpoly(fexpr_t res, const fmpz_mpoly_t poly, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx); void fexpr_set_fmpz_mpoly_q(fexpr_t res, const fmpz_mpoly_q_t frac, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx); int fexpr_expanded_normal_form(fexpr_t res, const fexpr_t expr, ulong flags); /* Vectors */ FEXPR_INLINE void fexpr_vec_init(fexpr_vec_t vec, slong len) { if (len == 0) { vec->entries = NULL; vec->length = 0; vec->alloc = 0; } else { slong i; vec->entries = (fexpr_ptr) flint_malloc(sizeof(fexpr_struct) * len); for (i = 0; i < len; i++) fexpr_init(vec->entries + i); vec->length = vec->alloc = len; } } FEXPR_INLINE void fexpr_vec_print(const fexpr_vec_t F) { slong i; flint_printf("["); for (i = 0; i < F->length; i++) { fexpr_print(F->entries + i); if (i < F->length - 1) flint_printf(", "); } flint_printf("]"); } FEXPR_INLINE void fexpr_vec_swap(fexpr_vec_t x, fexpr_vec_t y) { fexpr_vec_t tmp; *tmp = *x; *x = *y; *y = *tmp; } FEXPR_INLINE void fexpr_vec_fit_length(fexpr_vec_t vec, slong len) { if (len > vec->alloc) { slong i; if (len < 2 * vec->alloc) len = 2 * vec->alloc; vec->entries = (fexpr_struct *) flint_realloc(vec->entries, len * sizeof(fexpr_struct)); for (i = vec->alloc; i < len; i++) fexpr_init(vec->entries + i); vec->alloc = len; } } FEXPR_INLINE void fexpr_vec_clear(fexpr_vec_t vec) { slong i; for (i = 0; i < vec->alloc; i++) fexpr_clear(vec->entries + i); flint_free(vec->entries); } FEXPR_INLINE void fexpr_vec_set(fexpr_vec_t dest, const fexpr_vec_t src) { if (dest != src) { slong i; fexpr_vec_fit_length(dest, src->length); for (i = 0; i < src->length; i++) fexpr_set(dest->entries + i, src->entries + i); dest->length = src->length; } } FEXPR_INLINE void fexpr_vec_append(fexpr_vec_t vec, const fexpr_t f) { fexpr_vec_fit_length(vec, vec->length + 1); fexpr_set(vec->entries + vec->length, f); vec->length++; } FEXPR_INLINE slong fexpr_vec_insert_unique(fexpr_vec_t vec, const fexpr_t f) { slong i; for (i = 0; i < vec->length; i++) { if (fexpr_equal(vec->entries + i, f)) return i; } fexpr_vec_append(vec, f); return vec->length - 1; } FEXPR_INLINE void fexpr_vec_set_length(fexpr_vec_t vec, slong len) { slong i; if (len > vec->length) { fexpr_vec_fit_length(vec, len); for (i = vec->length; i < len; i++) fexpr_zero(vec->entries + i); } else if (len < vec->length) { for (i = len; i < vec->length; i++) fexpr_zero(vec->entries + i); } vec->length = len; } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fexpr/000077500000000000000000000000001461254215100145465ustar00rootroot00000000000000flint-3.1.3/src/fexpr/arg.c000066400000000000000000000042311461254215100154630ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" /* todo: bounds checking? */ void fexpr_arg(fexpr_t res, const fexpr_t expr, slong i) { const ulong * data; slong j, size; ulong type = FEXPR_TYPE(expr->data[0]); if (FEXPR_TYPE_CALL0 <= type && type <= FEXPR_TYPE_CALL4) { data = expr->data + FEXPR_HEADER_SIZE; data += FEXPR_SIZE(data[0]); /* skip f */ for (j = 0; j < i; j++) data += FEXPR_SIZE(data[0]); /* jump ahead */ size = FEXPR_SIZE(data[0]); fexpr_fit_size(res, size); flint_mpn_copyi(res->data, data, size); } else if (type == FEXPR_TYPE_CALLN) { data = expr->data + expr->data[3 + i / 4]; for (j = 0; j < i % 4; j++) data += FEXPR_SIZE(data[0]); size = FEXPR_SIZE(data[0]); fexpr_fit_size(res, size); flint_mpn_copyi(res->data, data, size); } else { flint_throw(FLINT_ERROR, "fexpr_arg: a non-atomic expression is required\n"); } } void fexpr_view_arg(fexpr_t res, const fexpr_t expr, slong i) { const ulong * data; slong j; ulong type = FEXPR_TYPE(expr->data[0]); if (FEXPR_TYPE_CALL0 <= type && type <= FEXPR_TYPE_CALL4) { data = expr->data + FEXPR_HEADER_SIZE; data += FEXPR_SIZE(data[0]); /* skip f */ for (j = 0; j < i; j++) data += FEXPR_SIZE(data[0]); /* jump ahead */ res->data = (ulong *) data; res->alloc = 0; } else if (type == FEXPR_TYPE_CALLN) { data = expr->data + expr->data[3 + i / 4]; for (j = 0; j < i % 4; j++) data += FEXPR_SIZE(data[0]); res->data = (ulong *) data; res->alloc = 0; } else { flint_throw(FLINT_ERROR, "fexpr_view_arg: a non-atomic expression is required\n"); } } flint-3.1.3/src/fexpr/arithmetic.c000066400000000000000000000021051461254215100170410ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" void fexpr_neg(fexpr_t res, const fexpr_t a) { fexpr_call_builtin1(res, FEXPR_Neg, a); } void fexpr_add(fexpr_t res, const fexpr_t a, const fexpr_t b) { fexpr_call_builtin2(res, FEXPR_Add, a, b); } void fexpr_sub(fexpr_t res, const fexpr_t a, const fexpr_t b) { fexpr_call_builtin2(res, FEXPR_Sub, a, b); } void fexpr_mul(fexpr_t res, const fexpr_t a, const fexpr_t b) { fexpr_call_builtin2(res, FEXPR_Mul, a, b); } void fexpr_div(fexpr_t res, const fexpr_t a, const fexpr_t b) { fexpr_call_builtin2(res, FEXPR_Div, a, b); } void fexpr_pow(fexpr_t res, const fexpr_t a, const fexpr_t b) { fexpr_call_builtin2(res, FEXPR_Pow, a, b); } flint-3.1.3/src/fexpr/arithmetic_nodes.c000066400000000000000000000024731461254215100202410ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" static void traverse(fexpr_vec_t nodes, const fexpr_t expr) { slong i, nargs; fexpr_t view; if (fexpr_is_integer(expr)) return; if (fexpr_is_arithmetic_operation(expr)) { nargs = fexpr_nargs(expr); fexpr_view_arg(view, expr, 0); for (i = 0; i < nargs; i++) { traverse(nodes, view); fexpr_view_next(view); } return; } if (fexpr_is_builtin_call(expr, FEXPR_Pow) && (fexpr_nargs(expr) == 2)) { fexpr_t base, exp; fexpr_view_arg(base, expr, 0); fexpr_view_arg(exp, expr, 1); if (fexpr_is_integer(exp)) { traverse(nodes, base); return; } } fexpr_vec_insert_unique(nodes, expr); } void fexpr_arithmetic_nodes(fexpr_vec_t nodes, const fexpr_t expr) { fexpr_vec_set_length(nodes, 0); traverse(nodes, expr); } flint-3.1.3/src/fexpr/call0.c000066400000000000000000000013741461254215100157120ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_call0(fexpr_t res, const fexpr_t f) { slong res_size, f_size; mp_ptr out; f_size = fexpr_size(f); res_size = FEXPR_HEADER_SIZE + f_size; fexpr_fit_size(res, res_size); out = res->data; out[0] = FEXPR_TYPE_CALL0 | (res_size << FEXPR_TYPE_BITS); out += FEXPR_HEADER_SIZE; flint_mpn_copyi(out, f->data, f_size); } flint-3.1.3/src/fexpr/call1.c000066400000000000000000000023641461254215100157130ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_call1(fexpr_t res, const fexpr_t f, const fexpr_t x1) { slong res_size, f_size, x1_size; mp_ptr out; f_size = fexpr_size(f); x1_size = fexpr_size(x1); res_size = FEXPR_HEADER_SIZE + f_size + x1_size; fexpr_fit_size(res, res_size); out = res->data; out[0] = FEXPR_TYPE_CALL1 | (res_size << FEXPR_TYPE_BITS); out += FEXPR_HEADER_SIZE; flint_mpn_copyi(out, f->data, f_size); out += f_size; flint_mpn_copyi(out, x1->data, x1_size); } void fexpr_call_builtin1(fexpr_t res, slong f, const fexpr_t x) { fexpr_t t; ulong d; t->data = &d; t->alloc = 1; fexpr_set_symbol_builtin(t, f); if (res == x) { fexpr_t u; fexpr_init(u); fexpr_call1(u, t, x); fexpr_swap(res, u); fexpr_clear(u); } else { fexpr_call1(res, t, x); } } flint-3.1.3/src/fexpr/call2.c000066400000000000000000000026271461254215100157160ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_call2(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2) { slong res_size, f_size, x1_size, x2_size; mp_ptr out; f_size = fexpr_size(f); x1_size = fexpr_size(x1); x2_size = fexpr_size(x2); res_size = FEXPR_HEADER_SIZE + f_size + x1_size + x2_size; fexpr_fit_size(res, res_size); out = res->data; out[0] = FEXPR_TYPE_CALL2 | (res_size << FEXPR_TYPE_BITS); out += FEXPR_HEADER_SIZE; flint_mpn_copyi(out, f->data, f_size); out += f_size; flint_mpn_copyi(out, x1->data, x1_size); out += x1_size; flint_mpn_copyi(out, x2->data, x2_size); } void fexpr_call_builtin2(fexpr_t res, slong f, const fexpr_t x, const fexpr_t y) { fexpr_t t; ulong d; t->data = &d; t->alloc = 1; fexpr_set_symbol_builtin(t, f); if (res == x || res == y) { fexpr_t u; fexpr_init(u); fexpr_call2(u, t, x, y); fexpr_swap(res, u); fexpr_clear(u); } else { fexpr_call2(res, t, x, y); } } flint-3.1.3/src/fexpr/call3.c000066400000000000000000000021731461254215100157130ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_call3(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3) { slong res_size, f_size, x1_size, x2_size, x3_size; mp_ptr out; f_size = fexpr_size(f); x1_size = fexpr_size(x1); x2_size = fexpr_size(x2); x3_size = fexpr_size(x3); res_size = FEXPR_HEADER_SIZE + f_size + x1_size + x2_size + x3_size; fexpr_fit_size(res, res_size); out = res->data; out[0] = FEXPR_TYPE_CALL3 | (res_size << FEXPR_TYPE_BITS); out += FEXPR_HEADER_SIZE; flint_mpn_copyi(out, f->data, f_size); out += f_size; flint_mpn_copyi(out, x1->data, x1_size); out += x1_size; flint_mpn_copyi(out, x2->data, x2_size); out += x2_size; flint_mpn_copyi(out, x3->data, x3_size); } flint-3.1.3/src/fexpr/call4.c000066400000000000000000000023731461254215100157160ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_call4(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3, const fexpr_t x4) { slong res_size, f_size, x1_size, x2_size, x3_size, x4_size; mp_ptr out; f_size = fexpr_size(f); x1_size = fexpr_size(x1); x2_size = fexpr_size(x2); x3_size = fexpr_size(x3); x4_size = fexpr_size(x4); res_size = FEXPR_HEADER_SIZE + f_size + x1_size + x2_size + x3_size + x4_size; fexpr_fit_size(res, res_size); out = res->data; out[0] = FEXPR_TYPE_CALL4 | (res_size << FEXPR_TYPE_BITS); out += FEXPR_HEADER_SIZE; flint_mpn_copyi(out, f->data, f_size); out += f_size; flint_mpn_copyi(out, x1->data, x1_size); out += x1_size; flint_mpn_copyi(out, x2->data, x2_size); out += x2_size; flint_mpn_copyi(out, x3->data, x3_size); out += x3_size; flint_mpn_copyi(out, x4->data, x4_size); } flint-3.1.3/src/fexpr/call_vec.c000066400000000000000000000036241461254215100164670ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_call_vec(fexpr_t res, const fexpr_t f, fexpr_srcptr args, slong len) { if (len == 0) { fexpr_call0(res, f); } else if (len == 1) { fexpr_call1(res, f, args); } else if (len == 2) { fexpr_call2(res, f, args, args + 1); } else if (len == 3) { fexpr_call3(res, f, args, args + 1, args + 2); } else if (len == 4) { fexpr_call4(res, f, args, args + 1, args + 2, args + 3); } else { slong i, f_size, args_size, index_size, size, pos, arg_size; mp_ptr out; f_size = fexpr_size(f); args_size = 0; for (i = 0; i < len; i++) args_size += fexpr_size(args + i); /* write index: data[1] = nargs data[2] = position of f data[3], data[4], ..., positions of every 1/4 args for random access */ index_size = 2 + (len + 4 - 1) / 4; size = 1 + index_size + f_size + args_size; fexpr_fit_size(res, size); out = res->data; out[0] = FEXPR_TYPE_CALLN | (size << FEXPR_TYPE_BITS); out[1] = len; pos = 1 + index_size; out[2] = pos; flint_mpn_copyi(out + pos, f->data, f_size); pos += f_size; for (i = 0; i < len; i++) { if (i % 4 == 0) out[3 + i / 4] = pos; arg_size = fexpr_size(args + i); flint_mpn_copyi(out + pos, args[i].data, arg_size); pos += arg_size; } } } flint-3.1.3/src/fexpr/cmp_fast.c000066400000000000000000000015371461254215100165140ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" int fexpr_cmp_fast(const fexpr_t a, const fexpr_t b) { ulong ha, hb; slong sa, sb; slong i; ha = a->data[0]; hb = b->data[0]; if (ha != hb) return (ha > hb) ? 1 : -1; sa = FEXPR_SIZE(ha); sb = FEXPR_SIZE(hb); if (sa != sb) return 0; for (i = 1; i < sa; i++) { ha = a->data[i]; hb = b->data[i]; if (ha != hb) return (ha > hb) ? 1 : -1; } return 0; } flint-3.1.3/src/fexpr/contains.c000066400000000000000000000021511461254215100165270ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" int fexpr_contains(const fexpr_t expr, const fexpr_t x) { fexpr_t func, arg; slong expr_size, x_size, i, nargs; expr_size = fexpr_size(expr); x_size = fexpr_size(x); if (expr_size < x_size) return 0; if (expr_size == x_size) return _mpn_equal(expr->data, x->data, x_size); nargs = fexpr_nargs(expr); if (nargs < 0) return 0; fexpr_view_func(func, expr); if (fexpr_contains(func, x)) return 1; if (nargs <= 0) return 0; fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { if (fexpr_contains(arg, x)) return 1; if (i < nargs - 1) fexpr_view_next(arg); } return 0; } flint-3.1.3/src/fexpr/depth.c000066400000000000000000000016161461254215100160220ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" slong fexpr_depth(const fexpr_t expr) { if (fexpr_is_atom(expr)) { return 1; } else { fexpr_t func, arg; slong i, depth, d, nargs; fexpr_view_func(func, expr); depth = fexpr_depth(func); nargs = fexpr_nargs(expr); *arg = *func; for (i = 0; i < nargs; i++) { fexpr_view_next(arg); d = fexpr_depth(arg); depth = FLINT_MAX(depth, d); } return depth + 1; } } flint-3.1.3/src/fexpr/equal_si.c000066400000000000000000000014631461254215100165200ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" int fexpr_equal_si(const fexpr_t expr, slong c) { if (c >= FEXPR_COEFF_MIN && c <= FEXPR_COEFF_MAX) return expr->data[0] == (c << FEXPR_TYPE_BITS); else if (c > 0) return (expr->data[0] == (FEXPR_TYPE_BIG_INT_POS | (2 << FEXPR_TYPE_BITS)) && expr->data[1] == c); else return (expr->data[0] == (FEXPR_TYPE_BIG_INT_NEG | (2 << FEXPR_TYPE_BITS)) && expr->data[1] == (-(ulong) c)); } flint-3.1.3/src/fexpr/equal_ui.c000066400000000000000000000012451461254215100165200ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" int fexpr_equal_ui(const fexpr_t expr, ulong c) { if (c <= FEXPR_COEFF_MAX) return expr->data[0] == (c << FEXPR_TYPE_BITS); else return (expr->data[0] == (FEXPR_TYPE_BIG_INT_POS | (2 << FEXPR_TYPE_BITS)) && expr->data[1] == c); } flint-3.1.3/src/fexpr/expanded_normal_form.c000066400000000000000000000022321461254215100210740ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" #include "fexpr.h" int fexpr_expanded_normal_form(fexpr_t res, const fexpr_t expr, ulong flags) { fexpr_vec_t args; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t frac; int success; fexpr_vec_init(args, 0); fexpr_arithmetic_nodes(args, expr); _fexpr_vec_sort_fast(args->entries, args->length); /* todo: when length == 0, use fmpq arithmetic instead */ fmpz_mpoly_ctx_init(ctx, FLINT_MAX(args->length, 1), ORD_LEX); fmpz_mpoly_q_init(frac, ctx); success = fexpr_get_fmpz_mpoly_q(frac, expr, args, ctx); if (success) fexpr_set_fmpz_mpoly_q(res, frac, args, ctx); else fexpr_set(res, expr); fmpz_mpoly_q_clear(frac, ctx); fmpz_mpoly_ctx_clear(ctx); fexpr_vec_clear(args); return success; } flint-3.1.3/src/fexpr/func.c000066400000000000000000000027111461254215100156460ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_func(fexpr_t res, const fexpr_t expr) { ulong type = FEXPR_TYPE(expr->data[0]); slong size; const ulong * data; if (FEXPR_TYPE_CALL0 <= type && type <= FEXPR_TYPE_CALL4) { data = expr->data + FEXPR_HEADER_SIZE; } else if (type == FEXPR_TYPE_CALLN) { data = expr->data + expr->data[2]; } else { flint_throw(FLINT_ERROR, "fexpr_func: a non-atomic expression is required\n"); } size = FEXPR_SIZE(data[0]); fexpr_fit_size(res, size); flint_mpn_copyi(res->data, data, size); } void fexpr_view_func(fexpr_t res, const fexpr_t expr) { ulong type = FEXPR_TYPE(expr->data[0]); const ulong * data; if (FEXPR_TYPE_CALL0 <= type && type <= FEXPR_TYPE_CALL4) { data = expr->data + FEXPR_HEADER_SIZE; } else if (type == FEXPR_TYPE_CALLN) { data = expr->data + expr->data[2]; } else { flint_throw(FLINT_ERROR, "fexpr_view_func: a non-atomic expression is required\n"); } res->data = (ulong *) data; res->alloc = 0; } flint-3.1.3/src/fexpr/get_fmpz.c000066400000000000000000000024151461254215100165270ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_extras.h" #include "fexpr.h" int fexpr_get_fmpz(fmpz_t c, const fexpr_t x) { ulong head = x->data[0]; if (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_INT) { _fmpz_demote(c); *c = ((slong) head) >> FEXPR_TYPE_BITS; } else { slong nlimbs; int negative; nlimbs = FEXPR_SIZE(head) - 1; if (FEXPR_TYPE(head) == FEXPR_TYPE_BIG_INT_POS) { negative = 0; } else if (FEXPR_TYPE(head) == FEXPR_TYPE_BIG_INT_NEG) { negative = 1; } else { return 0; } if (nlimbs == 1 && x->data[1] <= COEFF_MAX) { _fmpz_demote(c); *c = negative ? (-(slong) x->data[1]) : x->data[1]; } else { fmpz_set_mpn_large(c, x->data + 1, nlimbs, negative); } } return 1; } flint-3.1.3/src/fexpr/get_fmpz_mpoly_q.c000066400000000000000000000101141461254215100202620ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" #include "fexpr.h" #include "fexpr_builtin.h" int fexpr_get_fmpz_mpoly_q(fmpz_mpoly_q_t res, const fexpr_t expr, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx) { if (fexpr_is_integer(expr)) { fmpz_t c; fmpz_init(c); fexpr_get_fmpz(c, expr); fmpz_mpoly_q_set_fmpz(res, c, ctx); fmpz_clear(c); return 1; } else { slong i, nargs; ulong op_head; fexpr_t func, arg; int success; if (fexpr_is_arithmetic_operation(expr)) { fmpz_mpoly_q_t A, B; nargs = fexpr_nargs(expr); if (nargs == 0) { /* not implemented */ return 0; } success = 1; fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fexpr_view_func(func, expr); op_head = func->data[0]; fexpr_view_arg(arg, expr, 0); success = fexpr_get_fmpz_mpoly_q(res, arg, vars, ctx); if (!success) goto cleanup1; /* todo: verify nargs == 1 */ if (op_head == FEXPR_SYMBOL_Neg) { fmpz_mpoly_q_neg(res, res, ctx); goto cleanup1; } for (i = 1; i < nargs; i++) { fexpr_view_next(arg); success = fexpr_get_fmpz_mpoly_q(A, arg, vars, ctx); if (!success) goto cleanup1; if (op_head == FEXPR_SYMBOL_Add) fmpz_mpoly_q_add(B, res, A, ctx); else if (op_head == FEXPR_SYMBOL_Sub) fmpz_mpoly_q_sub(B, res, A, ctx); else if (op_head == FEXPR_SYMBOL_Mul) fmpz_mpoly_q_mul(B, res, A, ctx); else if (op_head == FEXPR_SYMBOL_Div) { /* formal division by zero */ if (fmpz_mpoly_q_is_zero(A, ctx)) success = 0; else fmpz_mpoly_q_div(B, res, A, ctx); } fmpz_mpoly_q_swap(res, B, ctx); } cleanup1: fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); return success; } if (fexpr_is_builtin_call(expr, FEXPR_Pow) && (fexpr_nargs(expr) == 2)) { fexpr_t base, exp; int success; fexpr_view_arg(base, expr, 0); fexpr_view_arg(exp, expr, 1); if (fexpr_is_integer(exp)) { fmpz_t c; success = fexpr_get_fmpz_mpoly_q(res, base, vars, ctx); if (!success) return 0; fmpz_init(c); fexpr_get_fmpz(c, exp); if (fmpz_sgn(c) < 0) { if (fmpz_mpoly_q_is_zero(res, ctx)) { success = 0; goto cleanup2; } fmpz_neg(c, c); fmpz_mpoly_q_inv(res, res, ctx); } success = (fmpz_mpoly_pow_fmpz(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(res), c, ctx) && fmpz_mpoly_pow_fmpz(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(res), c, ctx)); cleanup2: fmpz_clear(c); return success; } } for (i = 0; i < vars->length; i++) { if (fexpr_equal(expr, fexpr_vec_entry(vars, i))) { fmpz_mpoly_q_gen(res, i, ctx); return 1; } } return 0; } } flint-3.1.3/src/fexpr/get_string.c000066400000000000000000000024751461254215100170670ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy # define strlen __builtin_strlen #else # include #endif char * fexpr_get_string(const fexpr_t expr) { char * res; slong i, len; ulong head = expr->data[0]; if (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_STRING) { res = flint_malloc(FEXPR_SMALL_SYMBOL_LEN + 1); res[FEXPR_SMALL_SYMBOL_LEN] = '\0'; for (i = 0; i < FEXPR_SMALL_SYMBOL_LEN; i++) { res[i] = (head >> ((i + 1) * 8)); if (res[i] == '\0') break; } } else if (FEXPR_TYPE(head) == FEXPR_TYPE_BIG_STRING) { len = strlen((const char *) (expr->data + 1)); res = flint_malloc(len + 1); memcpy(res, (const char *) (expr->data + 1), len + 1); } else { flint_throw(FLINT_ERROR, "fexpr_get_string: a string is required\n"); } return res; } flint-3.1.3/src/fexpr/get_symbol_str.c000066400000000000000000000031261461254215100177500ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy # define strlen __builtin_strlen #else # include #endif char * fexpr_get_symbol_str(const fexpr_t expr) { char * res; slong i, len; ulong head = expr->data[0]; if (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_SYMBOL) { if (((head >> 8) & 0xff) == 0) { i = head >> 16; len = strlen(fexpr_builtin_table[i].string); res = flint_malloc(len + 1); memcpy(res, fexpr_builtin_table[i].string, len + 1); return res; } res = flint_malloc(FEXPR_SMALL_SYMBOL_LEN + 1); res[FEXPR_SMALL_SYMBOL_LEN] = '\0'; for (i = 0; i < FEXPR_SMALL_SYMBOL_LEN; i++) { res[i] = (head >> ((i + 1) * 8)); if (res[i] == '\0') break; } } else if (FEXPR_TYPE(head) == FEXPR_TYPE_BIG_SYMBOL) { len = strlen((const char *) (expr->data + 1)); res = flint_malloc(len + 1); memcpy(res, (const char *) (expr->data + 1), len + 1); } else { flint_throw(FLINT_ERROR, "fexpr_get_symbol_str: a symbol is required\n"); } return res; } flint-3.1.3/src/fexpr/hash.c000066400000000000000000000012051461254215100156330ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" ulong fexpr_hash(const fexpr_t expr) { ulong head, hash; slong i, size; hash = head = expr->data[0]; size = FEXPR_SIZE(head); for (i = 1; i < size; i++) hash = expr->data[i] * 1000003 + hash; return hash; } flint-3.1.3/src/fexpr/inlines.c000066400000000000000000000006521461254215100163560ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FEXPR_INLINES_C #include "fexpr.h" flint-3.1.3/src/fexpr/is_any_builtin_call.c000066400000000000000000000011341461254215100207140ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" int fexpr_is_any_builtin_call(const fexpr_t expr) { fexpr_t func; if (fexpr_is_atom(expr)) return 0; fexpr_view_func(func, expr); return fexpr_is_any_builtin_symbol(func); } flint-3.1.3/src/fexpr/is_arithmetic_operation.c000066400000000000000000000022451461254215100216210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #define FEXPR_IS_ARITHMETIC_OP(h) \ ((h) == FEXPR_SYMBOL_Add || (h) == FEXPR_SYMBOL_Sub || \ (h) == FEXPR_SYMBOL_Mul || (h) == FEXPR_SYMBOL_Div || \ (h) == FEXPR_SYMBOL_Neg || (h) == FEXPR_SYMBOL_Pos) int fexpr_is_arithmetic_operation(const fexpr_t expr) { ulong head; fexpr_t func; head = expr->data[0]; switch (FEXPR_TYPE(head)) { case FEXPR_TYPE_CALL0: case FEXPR_TYPE_CALL1: case FEXPR_TYPE_CALL2: case FEXPR_TYPE_CALL3: case FEXPR_TYPE_CALL4: return FEXPR_IS_ARITHMETIC_OP(expr->data[1]); case FEXPR_TYPE_CALLN: fexpr_view_func(func, expr); return FEXPR_IS_ARITHMETIC_OP(func->data[0]); default: return 0; } } flint-3.1.3/src/fexpr/is_builtin_call.c000066400000000000000000000011401461254215100200420ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" int fexpr_is_builtin_call(const fexpr_t expr, slong i) { fexpr_t func; if (fexpr_is_atom(expr)) return 0; fexpr_view_func(func, expr); return fexpr_is_builtin_symbol(func, i); } flint-3.1.3/src/fexpr/is_neg_integer.c000066400000000000000000000012451461254215100176750ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" int fexpr_is_neg_integer(const fexpr_t expr) { ulong head = expr->data[0]; if (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_INT) return (((slong) head) >> FEXPR_TYPE_BITS) < 0; if (FEXPR_TYPE(head) == FEXPR_TYPE_BIG_INT_NEG) return 1; return 0; } flint-3.1.3/src/fexpr/num_leaves.c000066400000000000000000000015661461254215100170600ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" slong fexpr_num_leaves(const fexpr_t expr) { if (fexpr_is_atom(expr)) { return 1; } else { fexpr_t func, arg; slong i, leaves, nargs; fexpr_view_func(func, expr); leaves = fexpr_num_leaves(func); nargs = fexpr_nargs(expr); *arg = *func; for (i = 0; i < nargs; i++) { fexpr_view_next(arg); leaves += fexpr_num_leaves(arg); } return leaves; } } flint-3.1.3/src/fexpr/numerical_enclosure.c000066400000000000000000000334651461254215100207630ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_hypgeom.h" #include "acb_modular.h" #include "acb_dirichlet.h" #include "fexpr.h" #include "fexpr_builtin.h" void _acb_root(acb_t res, const acb_t x, const acb_t y, slong prec) { if (acb_is_int(y) && arf_sgn(arb_midref(acb_realref(y))) > 0 && arf_cmpabs_ui(arb_midref(acb_realref(y)), 1000) <= 0) { acb_root_ui(res, x, arf_get_si(arb_midref(acb_realref(y)), ARF_RND_DOWN), prec); } else { acb_t e; acb_init(e); acb_inv(e, y, prec); acb_pow(res, x, e, prec); acb_clear(e); } } #define REQUIRE_NARGS(n) if (nargs != n) { success = 0; break; } #define ACB_FUNCTION_1(acb_func) \ REQUIRE_NARGS(1) \ success = fexpr_get_acb_raw(res, arg, prec); \ acb_func(res, res, prec); \ break; #define ACB_FUNCTION_1_ANALYTIC_FLAG(acb_func) \ REQUIRE_NARGS(1) \ success = fexpr_get_acb_raw(res, arg, prec); \ acb_func(res, res, 0, prec); \ break; #define ACB_FUNCTION_2(acb_func) \ REQUIRE_NARGS(2) \ success = fexpr_get_acb_raw(res, arg, prec); \ if (success) \ { \ acb_init(t); \ fexpr_view_next(arg); \ success = fexpr_get_acb_raw(t, arg, prec); \ if (success) \ acb_func(res, res, t, prec); \ acb_clear(t); \ } \ break; int fexpr_get_acb_raw(acb_t res, const fexpr_t expr, slong prec) { if (fexpr_is_integer(expr)) { fmpz_t c; fmpz_init(c); fexpr_get_fmpz(c, expr); acb_set_round_fmpz(res, c, prec); fmpz_clear(c); return 1; } else if (fexpr_is_atom(expr)) { ulong op; if (!fexpr_is_any_builtin_symbol(expr)) { acb_indeterminate(res); return 0; } /* todo: clean up these cases */ op = FEXPR_BUILTIN_ID(expr->data[0]); if (op == FEXPR_Pi) { acb_const_pi(res, prec); return 1; } if (op == FEXPR_NumberI) { acb_onei(res); return 1; } if (op == FEXPR_NumberE) { arb_const_e(acb_realref(res), prec); arb_zero(acb_imagref(res)); return 1; } if (op == FEXPR_Euler) { arb_const_euler(acb_realref(res), prec); arb_zero(acb_imagref(res)); return 1; } if (op == FEXPR_CatalanConstant) { arb_const_catalan(acb_realref(res), prec); arb_zero(acb_imagref(res)); return 1; } if (op == FEXPR_GoldenRatio) { arb_sqrt_ui(acb_realref(res), 5, prec); arb_add_ui(acb_realref(res), acb_realref(res), 1, prec); arb_mul_2exp_si(acb_realref(res), acb_realref(res), -1); arb_zero(acb_imagref(res)); return 1; } acb_indeterminate(res); return 0; } else { slong nargs; fmpz_t n, m; acb_t t, u, v, w; fexpr_t func; fexpr_t arg; fexpr_builtin_symbol op; slong i; int success = 0; nargs = fexpr_nargs(expr); fexpr_view_func(func, expr); if (!fexpr_is_any_builtin_symbol(func)) { acb_indeterminate(res); return 0; } if (nargs > 0) fexpr_view_arg(arg, expr, 0); op = FEXPR_BUILTIN_ID(func->data[0]); switch (op) { case FEXPR_Abs: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); acb_abs(acb_realref(res), res, prec); arb_zero(acb_imagref(res)); break; case FEXPR_Acos: ACB_FUNCTION_1(acb_acos) case FEXPR_Acosh: ACB_FUNCTION_1(acb_acosh) case FEXPR_Add: if (nargs == 0) { acb_zero(res); } else if (nargs == 1) { success = fexpr_get_acb_raw(res, arg, prec); } else { acb_init(t); success = fexpr_get_acb_raw(res, arg, prec); for (i = 1; success && i < nargs; i++) { fexpr_view_next(arg); success = fexpr_get_acb_raw(t, arg, prec); acb_add(res, res, t, prec); } acb_clear(t); } break; case FEXPR_AiryAi: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); acb_hypgeom_airy(res, NULL, NULL, NULL, res, prec); break; case FEXPR_AiryBi: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); acb_hypgeom_airy(NULL, res, NULL, NULL, res, prec); break; case FEXPR_Arg: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); acb_arg(acb_realref(res), res, prec); arb_zero(acb_imagref(res)); break; case FEXPR_Asin: ACB_FUNCTION_1(acb_asin) case FEXPR_Asinh: ACB_FUNCTION_1(acb_asinh) case FEXPR_Atan: ACB_FUNCTION_1(acb_atan) case FEXPR_Atanh: ACB_FUNCTION_1(acb_atanh) case FEXPR_BesselI: ACB_FUNCTION_2(acb_hypgeom_bessel_i) case FEXPR_BesselJ: ACB_FUNCTION_2(acb_hypgeom_bessel_j) case FEXPR_BesselK: ACB_FUNCTION_2(acb_hypgeom_bessel_k) case FEXPR_BesselY: ACB_FUNCTION_2(acb_hypgeom_bessel_y) case FEXPR_Ceil: ACB_FUNCTION_1_ANALYTIC_FLAG(acb_real_ceil) case FEXPR_Conjugate: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); acb_conj(res, res); break; case FEXPR_Cos: ACB_FUNCTION_1(acb_cos) case FEXPR_Cosh: ACB_FUNCTION_1(acb_cosh) case FEXPR_DedekindEta: ACB_FUNCTION_1(acb_modular_eta) case FEXPR_Div: ACB_FUNCTION_2(acb_div) case FEXPR_Erf: ACB_FUNCTION_1(acb_hypgeom_erf) case FEXPR_Erfc: ACB_FUNCTION_1(acb_hypgeom_erfc) case FEXPR_Erfi: ACB_FUNCTION_1(acb_hypgeom_erfi) case FEXPR_Exp: ACB_FUNCTION_1(acb_exp) case FEXPR_Floor: ACB_FUNCTION_1_ANALYTIC_FLAG(acb_real_floor) case FEXPR_Gamma: ACB_FUNCTION_1(acb_gamma) case FEXPR_HurwitzZeta: ACB_FUNCTION_2(acb_hurwitz_zeta) case FEXPR_Im: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); arb_swap(acb_realref(res), acb_imagref(res)); arb_zero(acb_imagref(res)); break; case FEXPR_JacobiTheta: REQUIRE_NARGS(3) { fmpz_init(n); success = fexpr_get_fmpz(n, arg); if (success) success = (*n == 1 || *n == 2 || *n == 3 || *n == 4); if (success) { fexpr_view_next(arg); success = fexpr_get_acb_raw(res, arg, prec); if (success) { acb_init(t); fexpr_view_next(arg); success = fexpr_get_acb_raw(t, arg, prec); if (success) { acb_init(u); acb_init(v); acb_init(w); if (*n == 1) acb_modular_theta(res, t, u, v, res, t, prec); else if (*n == 2) acb_modular_theta(t, res, u, v, res, t, prec); else if (*n == 3) acb_modular_theta(t, u, res, v, res, t, prec); else acb_modular_theta(t, u, v, res, res, t, prec); acb_clear(u); acb_clear(v); acb_clear(w); } acb_clear(t); } } fmpz_clear(n); } break; case FEXPR_LambertW: if (nargs == 1) { fmpz_init(n); success = fexpr_get_acb_raw(res, arg, prec); if (success) acb_lambertw(res, res, n, 0, prec); fmpz_clear(n); } else if (nargs == 2) { fmpz_init(n); success = fexpr_get_fmpz(n, arg); if (success) { fexpr_view_next(arg); success = fexpr_get_acb_raw(res, arg, prec); if (success) acb_lambertw(res, res, n, 0, prec); } fmpz_clear(n); } break; case FEXPR_Log: ACB_FUNCTION_1(acb_log) case FEXPR_LogGamma: ACB_FUNCTION_1(acb_lgamma) case FEXPR_Mul: if (nargs == 0) { acb_one(res); } else if (nargs == 1) { success = fexpr_get_acb_raw(res, arg, prec); } else { acb_init(t); success = fexpr_get_acb_raw(res, arg, prec); for (i = 1; success && i < nargs; i++) { fexpr_view_next(arg); success = fexpr_get_acb_raw(t, arg, prec); acb_mul(res, res, t, prec); } acb_clear(t); } break; case FEXPR_Neg: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); acb_neg(res, res); break; case FEXPR_Pos: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); break; case FEXPR_Pow: ACB_FUNCTION_2(acb_pow) /* todo: acb_polygamma */ case FEXPR_DigammaFunction: ACB_FUNCTION_1(acb_digamma) case FEXPR_Re: REQUIRE_NARGS(1) success = fexpr_get_acb_raw(res, arg, prec); arb_zero(acb_imagref(res)); break; case FEXPR_RiemannZeta: ACB_FUNCTION_1(acb_zeta) case FEXPR_Root: ACB_FUNCTION_2(_acb_root) case FEXPR_RootOfUnity: if (nargs == 1 || nargs == 2) { fmpq_t q; fmpz_init(n); fmpz_init(m); fmpz_one(m); success = fexpr_get_fmpz(n, arg); success = success && (fmpz_sgn(n) >= 1); if (success && nargs == 2) { fexpr_view_next(arg); success = fexpr_get_fmpz(m, arg); } if (success) { fmpz_mul_2exp(m, m, 1); *fmpq_denref(q) = *n; *fmpq_numref(q) = *m; arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), q, prec); } } break; case FEXPR_Sign: ACB_FUNCTION_1(acb_sgn) case FEXPR_Sin: ACB_FUNCTION_1(acb_sin) case FEXPR_Sinh: ACB_FUNCTION_1(acb_sinh) case FEXPR_Sqrt: ACB_FUNCTION_1(acb_sqrt) case FEXPR_Sub: if (nargs == 0) { acb_zero(res); } else if (nargs == 1) { success = fexpr_get_acb_raw(res, arg, prec); } else { acb_init(t); success = fexpr_get_acb_raw(res, arg, prec); for (i = 1; success && i < nargs; i++) { fexpr_view_next(arg); success = fexpr_get_acb_raw(t, arg, prec); acb_sub(res, res, t, prec); } acb_clear(t); } break; case FEXPR_Tan: ACB_FUNCTION_1(acb_tan) case FEXPR_Tanh: ACB_FUNCTION_1(acb_tanh) default: success = 0; } if (!success || !acb_is_finite(res)) { success = 0; acb_indeterminate(res); } return success; } } int fexpr_get_acb_with_accuracy(acb_t res, const fexpr_t expr, slong prec, ulong flags) { slong wp, initial, maxprec; int success = 0; initial = prec * 1.05 + 20; maxprec = FLINT_MAX(4096, 4 * initial); for (wp = initial; wp < maxprec; wp *= 2) { success = fexpr_get_acb_raw(res, expr, wp); if (acb_rel_accuracy_bits(res) >= prec) break; } return success; } char * fexpr_get_decimal_str(const fexpr_t expr, slong digits, ulong flags) { calcium_stream_t t; acb_t v; digits = FLINT_MAX(digits, 1); acb_init(v); calcium_stream_init_str(t); if (fexpr_get_acb_with_accuracy(v, expr, digits * 3.333 + 1, 0)) calcium_write_acb(t, v, digits, ARB_STR_NO_RADIUS); else calcium_write(t, "?"); acb_clear(v); return t->s; } /* todo: implement void fexpr_set_acb(fexpr_t res, const acb_t x); */ flint-3.1.3/src/fexpr/print.c000066400000000000000000000106371461254215100160550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fexpr.h" #include "fexpr_builtin.h" void fexpr_write(calcium_stream_t stream, const fexpr_t expr) { ulong type = FEXPR_TYPE(expr->data[0]); switch (type) { case FEXPR_TYPE_SMALL_INT: { slong c = ((slong) (expr->data[0])) >> FEXPR_TYPE_BITS; calcium_write_si(stream, c); } break; case FEXPR_TYPE_SMALL_SYMBOL: { slong i; if (((expr->data[0] >> 8) & 0xff) == 0) { calcium_write(stream, fexpr_builtin_table[expr->data[0] >> 16].string); } else { char tmp[FEXPR_SMALL_SYMBOL_LEN + 1]; tmp[FEXPR_SMALL_SYMBOL_LEN] = '\0'; for (i = 0; i < FEXPR_SMALL_SYMBOL_LEN; i++) { char c = expr->data[0] >> ((i + 1) * 8); tmp[i] = c; if (c == '\0') break; } calcium_write(stream, tmp); } } break; case FEXPR_TYPE_BIG_SYMBOL: { calcium_write(stream, (const char *) (expr->data + 1)); } break; case FEXPR_TYPE_SMALL_STRING: { slong i; char tmp[FEXPR_SMALL_SYMBOL_LEN + 3]; /* todo: escape string */ tmp[FEXPR_SMALL_SYMBOL_LEN] = '\0'; for (i = 0; i < FEXPR_SMALL_SYMBOL_LEN; i++) { char c = expr->data[0] >> ((i + 1) * 8); tmp[i] = c; if (c == '\0') break; } calcium_write(stream, "\""); calcium_write(stream, tmp); calcium_write(stream, "\""); } break; case FEXPR_TYPE_BIG_STRING: { calcium_write(stream, "\""); /* todo: escape string */ calcium_write(stream, (const char *) (expr->data + 1)); calcium_write(stream, "\""); } break; case FEXPR_TYPE_BIG_INT_NEG: case FEXPR_TYPE_BIG_INT_POS: /* todo: print without copying */ { fmpz_t c; fmpz_init(c); fexpr_get_fmpz(c, expr); calcium_write_fmpz(stream, c); fmpz_clear(c); } break; case FEXPR_TYPE_CALL0: case FEXPR_TYPE_CALL1: case FEXPR_TYPE_CALL2: case FEXPR_TYPE_CALL3: case FEXPR_TYPE_CALL4: case FEXPR_TYPE_CALLN: { fexpr_t t; ulong * ptr; slong i, num; if (type == FEXPR_TYPE_CALLN) { num = expr->data[1]; ptr = expr->data + expr->data[2]; } else { ptr = expr->data + FEXPR_HEADER_SIZE; num = type - FEXPR_TYPE_CALL0; } t->data = ptr; t->alloc = 1; fexpr_write(stream, t); t->data += fexpr_size(t); calcium_write(stream, "("); for (i = 0; i < num; i++) { fexpr_write(stream, t); t->data += fexpr_size(t); if (i < num - 1) calcium_write(stream, ", "); } calcium_write(stream, ")"); } break; default: calcium_write(stream, "?UNKNOWN?"); } } void fexpr_print(const fexpr_t expr) { calcium_stream_t t; calcium_stream_init_file(t, stdout); fexpr_write(t, expr); } char * fexpr_get_str(const fexpr_t expr) { calcium_stream_t t; calcium_stream_init_str(t); fexpr_write(t, expr); return t->s; } flint-3.1.3/src/fexpr/replace.c000066400000000000000000000112701461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" /* Sets res_view to a view of expr replaced by {xs, ys, len} and returns whether any replacement has been made. If no replacement has been made, res_view will refer to the data of expr, with an alloc field of 0. If expr as a whole has been replaced with some entry in ys, res_view will refer to the data of that value in ys, also with an alloc field of 0. Otherwise, expr will be initialized to a new expression, with a nonzero alloc field. */ int _fexpr_replace_vec(fexpr_t res_view, const fexpr_t expr, fexpr_srcptr xs, fexpr_srcptr ys, slong len) { slong i, nargs; fexpr_t func, new_func, arg; fexpr_struct tmp_args[4]; fexpr_ptr args; int changed; for (i = 0; i < len; i++) { if (fexpr_equal(expr, xs + i)) { res_view->data = ys[i].data; res_view->alloc = 0; return 1; } } if (fexpr_is_atom(expr)) { res_view->data = expr->data; res_view->alloc = 0; return 0; } nargs = fexpr_nargs(expr); fexpr_view_func(func, expr); changed = _fexpr_replace_vec(new_func, func, xs, ys, len); if (nargs >= 5) args = flint_malloc(sizeof(fexpr_struct) * nargs); else args = tmp_args; if (nargs >= 1) { fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { changed |= _fexpr_replace_vec(args + i, arg, xs, ys, len); if (i < nargs - 1) fexpr_view_next(arg); } } if (changed) { fexpr_init(res_view); fexpr_call_vec(res_view, new_func, args, nargs); if (new_func->alloc != 0) flint_free(new_func->data); for (i = 0; i < nargs; i++) { if (args[i].alloc != 0) flint_free(args[i].data); } } else { res_view->data = expr->data; res_view->alloc = 0; } if (nargs >= 5) flint_free(args); return changed; } int fexpr_replace_vec(fexpr_t res, const fexpr_t expr, const fexpr_vec_t xs, const fexpr_vec_t ys) { int changed; slong num_rules; fexpr_t res_view; num_rules = xs->length; if (num_rules != ys->length) { flint_throw(FLINT_ERROR, "fexpr_replace_vec: vectors don't match\n"); } if (num_rules == 0) { fexpr_set(res, expr); return 0; } changed = _fexpr_replace_vec(res_view, expr, xs->entries, ys->entries, num_rules); if (changed) { if (res_view->alloc != 0) { /* We have new data */ fexpr_swap(res, res_view); fexpr_clear(res_view); } else { /* Must be a view of some ys; we assume that res is not aliased with any entry in ys. */ fexpr_set(res, res_view); } } else { fexpr_set(res, expr); } return changed; } int fexpr_replace(fexpr_t res, const fexpr_t expr, const fexpr_t x, const fexpr_t y) { int changed; fexpr_t res_view; changed = _fexpr_replace_vec(res_view, expr, x, y, 1); if (changed) { if (res_view->alloc != 0) { /* We have new data */ fexpr_swap(res, res_view); fexpr_clear(res_view); } else { /* Must be a view of some ys; we assume that res is not aliased with any entry in ys. */ fexpr_set(res, res_view); } } else { fexpr_set(res, expr); } return changed; } int fexpr_replace2(fexpr_t res, const fexpr_t expr, const fexpr_t x1, const fexpr_t y1, const fexpr_t x2, const fexpr_t y2) { int changed; fexpr_t res_view; fexpr_struct tmp[4]; tmp[0] = *x1; tmp[1] = *x2; tmp[2] = *y1; tmp[3] = *y2; changed = _fexpr_replace_vec(res_view, expr, tmp, tmp + 2, 2); if (changed) { if (res_view->alloc != 0) { /* We have new data */ fexpr_swap(res, res_view); fexpr_clear(res_view); } else { /* Must be a view of some ys; we assume that res is not aliased with any entry in ys. */ fexpr_set(res, res_view); } } else { fexpr_set(res, expr); } return changed; } flint-3.1.3/src/fexpr/set_arf.c000066400000000000000000000043101461254215100163330ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "fexpr.h" #include "fexpr_builtin.h" void fexpr_set_arf(fexpr_t res, const arf_t x) { if (arf_is_zero(x)) { fexpr_zero(res); } else if (arf_is_pos_inf(x)) { fexpr_set_symbol_builtin(res, FEXPR_Infinity); } else if (arf_is_neg_inf(x)) { fexpr_set_symbol_builtin(res, FEXPR_Infinity); fexpr_neg(res, res); } else if (arf_is_nan(x)) { fexpr_set_symbol_builtin(res, FEXPR_Undefined); } else { fmpz_t m, e; fmpz_init(m); fmpz_init(e); arf_get_fmpz_2exp(m, e, x); if (0 <= *e && *e <= 20) { fmpz_mul_2exp(m, m, *e); fexpr_set_fmpz(res, m); } else if (-8 <= *e && *e < 0) { fmpq_t t; *fmpq_numref(t) = *m; *fmpq_denref(t) = (1 << (-*e)); fexpr_set_fmpq(res, t); } else if (fmpz_is_pm1(m)) { fexpr_t base, exp; fexpr_init(base); fexpr_init(exp); fexpr_set_si(base, 2); fexpr_set_fmpz(exp, e); fexpr_pow(res, base, exp); if (!fmpz_is_one(m)) fexpr_neg(res, res); fexpr_clear(base); fexpr_clear(exp); } else { fexpr_t mantissa, base, exp; fexpr_init(mantissa); fexpr_init(base); fexpr_init(exp); fexpr_set_si(base, 2); fexpr_set_fmpz(exp, e); fexpr_pow(res, base, exp); fexpr_set_fmpz(mantissa, m); fexpr_mul(base, mantissa, res); fexpr_swap(res, base); fexpr_clear(mantissa); fexpr_clear(base); fexpr_clear(exp); } fmpz_clear(m); fmpz_clear(e); } } flint-3.1.3/src/fexpr/set_d.c000066400000000000000000000032101461254215100160040ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "fexpr.h" #include "fexpr_builtin.h" void fexpr_set_d(fexpr_t res, double x) { arf_t t; arf_init(t); arf_set_d(t, x); /* no need to free */ fexpr_set_arf(res, t); } void fexpr_set_re_im_d(fexpr_t res, double x, double y) { if (y == 0.0) { fexpr_set_d(res, x); } else if (x == 0.0) { if (y == 1.0) { fexpr_set_symbol_builtin(res, FEXPR_NumberI); } else if (y == -1.0) { fexpr_set_symbol_builtin(res, FEXPR_NumberI); fexpr_neg(res, res); } else { fexpr_t im, t; fexpr_init(im); fexpr_init(t); fexpr_set_d(im, y); fexpr_set_symbol_builtin(t, FEXPR_NumberI); fexpr_mul(res, im, t); fexpr_clear(im); fexpr_clear(t); } } else { fexpr_t re, im, t; fexpr_init(re); fexpr_init(im); fexpr_init(t); fexpr_set_d(re, x); fexpr_set_d(im, y); fexpr_set_symbol_builtin(t, FEXPR_NumberI); fexpr_mul(res, im, t); fexpr_swap(t, res); fexpr_add(res, re, t); fexpr_clear(re); fexpr_clear(im); fexpr_clear(t); } } flint-3.1.3/src/fexpr/set_fmpq.c000066400000000000000000000026271461254215100165370ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fexpr.h" #include "fexpr_builtin.h" void fexpr_set_fmpq(fexpr_t res, const fmpq_t x) { if (fmpz_is_one(fmpq_denref(x))) { fexpr_set_fmpz(res, fmpq_numref(x)); } else { slong p, q; p = *fmpq_numref(x); q = *fmpq_denref(x); if (p >= FEXPR_COEFF_MIN && p <= FEXPR_COEFF_MAX && q >= FEXPR_COEFF_MIN && q <= FEXPR_COEFF_MAX) { fexpr_fit_size(res, 4); res->data[0] = FEXPR_TYPE_CALL2 | (4 << FEXPR_TYPE_BITS); res->data[1] = FEXPR_SYMBOL_Div; res->data[2] = p << FEXPR_TYPE_BITS; res->data[3] = q << FEXPR_TYPE_BITS; } else /* todo: copy directly without temporaries */ { fexpr_t a, b; fexpr_init(a); fexpr_init(b); fexpr_set_fmpz(a, fmpq_numref(x)); fexpr_set_fmpz(b, fmpq_denref(x)); fexpr_div(res, a, b); fexpr_clear(a); fexpr_clear(b); } } } flint-3.1.3/src/fexpr/set_fmpz.c000066400000000000000000000015661461254215100165510ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_set_fmpz(fexpr_t res, const fmpz_t c) { if (!COEFF_IS_MPZ(*c)) { fexpr_set_si(res, *c); } else { slong nlimbs; __mpz_struct * z = COEFF_TO_PTR(*c); nlimbs = FLINT_ABS(z->_mp_size); fexpr_fit_size(res, 1 + nlimbs); res->data[0] = ((z->_mp_size > 0) ? FEXPR_TYPE_BIG_INT_POS : FEXPR_TYPE_BIG_INT_NEG) | ((1 + nlimbs) << FEXPR_TYPE_BITS); flint_mpn_copyi(res->data + 1, z->_mp_d, nlimbs); } } flint-3.1.3/src/fexpr/set_fmpz_mpoly.c000066400000000000000000000061451461254215100177670ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #include "fexpr.h" /* Sets *res* to an expression for the multivariate polynomial *poly* using the expressions in *vars* as variables. If *vars* is *NULL*, the symbols *x1*, *x2*, ..., *xn* are used. */ void fexpr_set_fmpz_mpoly(fexpr_t res, const fmpz_mpoly_t poly, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx) { slong len, nvars, i, j, factors_len; fexpr_ptr terms; fexpr_ptr factors; fexpr_t op, t; ulong * exp; nvars = ctx->minfo->nvars; len = poly->length; if (len == 0) { fexpr_zero(res); return; } if (fmpz_mpoly_is_fmpz(poly, ctx)) { fexpr_set_fmpz(res, poly->coeffs); return; } if (vars == NULL) { fexpr_vec_t v; fexpr_vec_init(v, nvars); /* FIXME */ for (i = 0; i < nvars; i++) { fexpr_vec_entry(v, i)->data[0] = FEXPR_TYPE_SMALL_SYMBOL | ('x' << 8) | (('1' + i) << 16); } fexpr_set_fmpz_mpoly(res, poly, v, ctx); fexpr_vec_clear(v); return; } exp = flint_malloc(sizeof(ulong) * nvars); len = poly->length; fexpr_init(t); fexpr_init(op); factors = _fexpr_vec_init(nvars + 1); /* todo: just allocate one array */ terms = _fexpr_vec_init(len); fexpr_set_symbol_str(op, "Mul"); for (i = 0; i < len; i++) { int constant_term; fmpz_mpoly_get_term_exp_ui(exp, poly, i, ctx); factors_len = 0; constant_term = (i == len - 1); for (j = 0; constant_term && j < nvars; j++) if (exp[j] != 0) constant_term = 0; if (!fmpz_is_one(poly->coeffs + i) || constant_term) { fexpr_set_fmpz(factors, poly->coeffs + i); factors_len = 1; } for (j = 0; j < nvars; j++) { if (exp[j] != 0) { if (exp[j] == 1) { fexpr_set(factors + factors_len, fexpr_vec_entry(vars, j)); } else { fexpr_set_ui(t, exp[j]); fexpr_pow(factors + factors_len, fexpr_vec_entry(vars, j), t); } factors_len++; } } if (factors_len == 1) fexpr_set(terms + i, factors); else { fexpr_call_vec(terms + i, op, factors, factors_len); } } if (len == 1) { fexpr_swap(res, terms); } else { fexpr_set_symbol_str(op, "Add"); fexpr_call_vec(res, op, terms, len); } flint_free(exp); _fexpr_vec_clear(factors, nvars + 1); _fexpr_vec_clear(terms, len); fexpr_clear(op); fexpr_clear(t); } flint-3.1.3/src/fexpr/set_fmpz_mpoly_q.c000066400000000000000000000017621461254215100203070ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" #include "fexpr.h" void fexpr_set_fmpz_mpoly_q(fexpr_t res, const fmpz_mpoly_q_t frac, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(frac), ctx)) { fexpr_set_fmpz_mpoly(res, fmpz_mpoly_q_numref(frac), vars, ctx); } else { fexpr_t p, q; fexpr_init(p); fexpr_init(q); fexpr_set_fmpz_mpoly(p, fmpz_mpoly_q_numref(frac), vars, ctx); fexpr_set_fmpz_mpoly(q, fmpz_mpoly_q_denref(frac), vars, ctx); fexpr_div(res, p, q); fexpr_clear(p); fexpr_clear(q); } } flint-3.1.3/src/fexpr/set_si.c000066400000000000000000000013731461254215100162040ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_set_si(fexpr_t res, slong c) { if (c >= FEXPR_COEFF_MIN && c <= FEXPR_COEFF_MAX) { res->data[0] = (c << FEXPR_TYPE_BITS); } else { fexpr_fit_size(res, 2); res->data[0] = ((c > 0) ? FEXPR_TYPE_BIG_INT_POS : FEXPR_TYPE_BIG_INT_NEG) | (2 << FEXPR_TYPE_BITS); res->data[1] = (c > 0) ? c : -c; } } flint-3.1.3/src/fexpr/set_string.c000066400000000000000000000023651461254215100171010ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy # define strlen __builtin_strlen #else # include #endif void fexpr_set_string(fexpr_t res, const char * s) { slong i, len; len = strlen(s); if (len <= FEXPR_SMALL_SYMBOL_LEN) { ulong data; data = FEXPR_TYPE_SMALL_STRING; for (i = 0; i < len; i++) data |= (((ulong) s[i]) << ((i + 1) * 8)); res->data[0] = data; } else { slong data_size; data_size = len + 1; data_size = (data_size + sizeof(ulong) - 1) / sizeof(ulong); fexpr_fit_size(res, data_size + 1); res->data[0] = FEXPR_TYPE_BIG_STRING | ((data_size + 1) << FEXPR_TYPE_BITS); res->data[data_size] = 0; /* zero pad for consistency */ memcpy((char *) (res->data + 1), s, len + 1); } } flint-3.1.3/src/fexpr/set_symbol_str.c000066400000000000000000000026261461254215100177700ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy # define strlen __builtin_strlen #else # include #endif void fexpr_set_symbol_str(fexpr_t res, const char * s) { slong i, len; i = fexpr_builtin_lookup(s); if (i != -1) { res->data[0] = FEXPR_TYPE_SMALL_SYMBOL | (i << 16); return; } len = strlen(s); if (len <= FEXPR_SMALL_SYMBOL_LEN) { slong i; ulong data; data = FEXPR_TYPE_SMALL_SYMBOL; for (i = 0; i < len; i++) data |= (((ulong) s[i]) << ((i + 1) * 8)); res->data[0] = data; } else { slong data_size; data_size = len + 1; data_size = (data_size + sizeof(ulong) - 1) / sizeof(ulong); fexpr_fit_size(res, data_size + 1); res->data[0] = FEXPR_TYPE_BIG_SYMBOL | ((data_size + 1) << FEXPR_TYPE_BITS); res->data[data_size] = 0; /* zero pad for consistency */ memcpy((char *) (res->data + 1), s, len + 1); } } flint-3.1.3/src/fexpr/set_ui.c000066400000000000000000000012571461254215100162070ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" void fexpr_set_ui(fexpr_t res, ulong c) { if (c <= FEXPR_COEFF_MAX) { res->data[0] = (c << FEXPR_TYPE_BITS); } else { fexpr_fit_size(res, 2); res->data[0] = FEXPR_TYPE_BIG_INT_POS | (2 << FEXPR_TYPE_BITS); res->data[1] = c; } } flint-3.1.3/src/fexpr/test/000077500000000000000000000000001461254215100155255ustar00rootroot00000000000000flint-3.1.3/src/fexpr/test/main.c000066400000000000000000000017601461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-builtins.c" #include "t-call_vec.c" #include "t-replace.c" #include "t-set_fmpz.c" #include "t-write_latex.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fexpr_builtins), TEST_FUNCTION(fexpr_call_vec), TEST_FUNCTION(fexpr_replace), TEST_FUNCTION(fexpr_set_fmpz), TEST_FUNCTION(fexpr_write_latex) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fexpr/test/t-builtins.c000066400000000000000000000033771461254215100177750ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "calcium.h" #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define strcmp __builtin_strcmp #else # include #endif TEST_FUNCTION_START(fexpr_builtins, state) { { slong i, j; for (i = 0; i < FEXPR_BUILTIN_LENGTH; i++) { if (fexpr_builtin_table[i].symbol != i) { flint_printf("FAIL (missing)\n"); flint_printf("%s\n", fexpr_builtin_name(i)); flint_abort(); } if (i < FEXPR_BUILTIN_LENGTH - 1 && strcmp(fexpr_builtin_name(i), fexpr_builtin_name(i + 1)) >= 0) { flint_printf("FAIL (order)\n"); flint_printf("%s\n", fexpr_builtin_name(i)); flint_printf("%s\n", fexpr_builtin_name(i + 1)); flint_abort(); } j = fexpr_builtin_lookup(fexpr_builtin_name(i)); if (i != j) { flint_printf("FAIL (lookup)\n"); flint_printf("%s\n", fexpr_builtin_name(i)); flint_abort(); } } } if (fexpr_builtin_lookup("") != -1 || fexpr_builtin_lookup("FooBarBaz") != -1 || fexpr_builtin_lookup("ZZZZZZZ") != -1) { flint_printf("FAIL (lookup)\n"); flint_abort(); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fexpr/test/t-call_vec.c000066400000000000000000000043101461254215100177000ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "calcium.h" #include "fexpr.h" TEST_FUNCTION_START(fexpr_call_vec, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fexpr_t f, f2, f3, g, v, a; fexpr_ptr args; fmpz_t c; slong i, len; len = n_randint(state, 20); fmpz_init(c); fexpr_init(f); fexpr_init(f2); fexpr_init(g); fexpr_init(a); args = _fexpr_vec_init(len); if (n_randint(state, 2)) fexpr_set_symbol_str(f, "Foo"); else fexpr_set_symbol_str(f, "FooVeryLongSymbolName"); for (i = 0; i < len; i++) { fmpz_randtest(c, state, 200); fexpr_set_fmpz(args + i, c); } fexpr_call_vec(g, f, args, len); for (i = 0; i < len; i++) { fexpr_func(f2, g); fexpr_view_func(f3, g); fexpr_arg(a, g, i); fexpr_view_arg(v, g, i); if (fexpr_nargs(g) != len || !fexpr_equal(f, f2) || !fexpr_equal(f, f3) || !fexpr_equal(a, args + i) || !fexpr_equal(v, args + i)) { flint_printf("FAIL\n\n"); flint_printf("len = %wd\n", len); flint_printf("g = "); fexpr_print(g); printf("\n"); flint_printf("arg = "); fexpr_print(args + i); printf("\n"); flint_printf("a = "); fexpr_print(a); printf("\n"); flint_printf("v = "); fexpr_print(v); printf("\n"); flint_printf("f2 = "); fexpr_print(f2); printf("\n"); flint_abort(); } } fexpr_clear(f); fexpr_clear(f2); fexpr_clear(g); fexpr_clear(a); _fexpr_vec_clear(args, len); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fexpr/test/t-replace.c000066400000000000000000000142651461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "calcium.h" #include "fexpr.h" #include "fexpr_builtin.h" void fexpr_randtest_atom1(fexpr_t expr, flint_rand_t state) { if (n_randint(state, 2)) { if (n_randint(state, 10) == 5) fexpr_set_si(expr, (slong) n_randtest(state)); else fexpr_set_si(expr, ((slong) n_randint(state, 3)) - 1); } else { if (n_randint(state, 2)) fexpr_set_symbol_builtin(expr, FEXPR_alpha); else fexpr_set_symbol_builtin(expr, FEXPR_beta); } } void fexpr_randtest1(fexpr_t expr, flint_rand_t state, slong max_leaves, slong max_depth) { if (max_leaves <= 1 || max_depth <= 1 || n_randint(state, 10) == 0) { fexpr_randtest_atom1(expr, state); } else { slong i, nargs; fexpr_t f; fexpr_ptr args; fexpr_init(f); fexpr_randtest1(f, state, max_leaves / 4, max_depth - 1); max_leaves -= fexpr_num_leaves(f); nargs = n_randint(state, 1 + FLINT_MIN(5, max_leaves / max_depth)); args = _fexpr_vec_init(nargs); for (i = 0; i < nargs; i++) { fexpr_randtest1(args + i, state, max_leaves, max_depth - 1); max_leaves -= fexpr_num_leaves(args + i); } fexpr_call_vec(expr, f, args, nargs); _fexpr_vec_clear(args, nargs); fexpr_clear(f); } } int fexpr_replace_vec_naive(fexpr_t res, const fexpr_t expr, const fexpr_vec_t xs, const fexpr_vec_t ys) { slong i, num_rules; num_rules = xs->length; if (num_rules != ys->length) { flint_printf("fexpr_replace_vec: vectors don't match\n"); flint_abort(); } for (i = 0; i < num_rules; i++) { if (fexpr_equal(expr, xs->entries + i)) { fexpr_set(res, ys->entries + i); return 1; } } if (fexpr_is_atom(expr)) { fexpr_set(res, expr); return 0; } else { fexpr_ptr args; fexpr_t func, view; slong nargs; int changed; nargs = fexpr_nargs(expr); args = NULL; fexpr_init(func); fexpr_view_func(view, expr); changed = fexpr_replace_vec_naive(func, view, xs, ys); if (nargs >= 1) { args = _fexpr_vec_init(nargs); fexpr_view_arg(view, expr, 0); for (i = 0; i < nargs; i++) { changed |= fexpr_replace_vec_naive(args + i, view, xs, ys); if (i < nargs - 1) fexpr_view_next(view); } fexpr_call_vec(res, func, args, nargs); _fexpr_vec_clear(args, nargs); } else { fexpr_call0(res, func); } fexpr_clear(func); return changed; } } TEST_FUNCTION_START(fexpr_replace, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fexpr_t expr, res1, res2, res3; fexpr_vec_t xs, ys; slong i, len; int changed1, changed2, changed3; fexpr_init(expr); fexpr_init(res1); fexpr_init(res2); fexpr_init(res3); fexpr_randtest1(expr, state, 1 + n_randint(state, 100), 2 + n_randint(state, 10)); fexpr_randtest1(res1, state, 5, 2 + n_randint(state, 5)); fexpr_randtest1(res2, state, 5, 2 + n_randint(state, 5)); len = n_randint(state, 4); fexpr_vec_init(xs, len); fexpr_vec_init(ys, len); for (i = 0; i < len; i++) { fexpr_randtest1(xs->entries + i, state, 1 + n_randint(state, 3), 1 + n_randint(state, 2)); fexpr_randtest1(ys->entries + i, state, 1 + n_randint(state, 10), 2 + n_randint(state, 5)); } if (xs->length == 1 && n_randint(state, 2)) { changed1 = fexpr_replace(res1, expr, xs->entries, ys->entries); /* also test contains() */ if (n_randint(state, 2)) changed1 = fexpr_contains(expr, xs->entries); } else changed1 = fexpr_replace_vec(res1, expr, xs, ys); fexpr_set(res2, expr); if (xs->length == 1 && n_randint(state, 2)) changed2 = fexpr_replace(res2, res2, xs->entries, ys->entries); else changed2 = fexpr_replace_vec(res2, res2, xs, ys); changed3 = fexpr_replace_vec_naive(res3, expr, xs, ys); if ((changed1 != changed3) || !fexpr_equal(res1, res3)) { flint_printf("FAIL\n"); flint_printf("expr = "); fexpr_print(expr); flint_printf("\n\n"); flint_printf("xs = "); fexpr_vec_print(xs); flint_printf("\n\n"); flint_printf("ys = "); fexpr_vec_print(ys); flint_printf("\n\n"); flint_printf("res1 = "); fexpr_print(res1); flint_printf("\n\n"); flint_printf("res3 = "); fexpr_print(res3); flint_printf("\n\n"); flint_printf("changed1 = %d, changed3 = %d\n\n", changed1, changed3); flint_abort(); } if ((changed1 != changed2) || !fexpr_equal(res1, res2)) { flint_printf("FAIL (aliasing)\n"); flint_printf("expr = "); fexpr_print(expr); flint_printf("\n\n"); flint_printf("xs = "); fexpr_vec_print(xs); flint_printf("\n\n"); flint_printf("ys = "); fexpr_vec_print(ys); flint_printf("\n\n"); flint_printf("res1 = "); fexpr_print(res1); flint_printf("\n\n"); flint_printf("res2 = "); fexpr_print(res2); flint_printf("\n\n"); flint_printf("changed1 = %d, changed2 = %d\n\n", changed1, changed2); flint_abort(); } fexpr_vec_clear(xs); fexpr_vec_clear(ys); fexpr_clear(expr); fexpr_clear(res1); fexpr_clear(res2); fexpr_clear(res3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fexpr/test/t-set_fmpz.c000066400000000000000000000024601461254215100177630ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "calcium.h" #include "fexpr.h" TEST_FUNCTION_START(fexpr_set_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, b; fexpr_t x; slong i; fmpz_init(a); fmpz_init(b); fexpr_init(x); for (i = 0; i < 5; i++) { fmpz_randtest(a, state, 300); fexpr_set_fmpz(x, a); fexpr_get_fmpz(b, x); if (!fmpz_equal(a, b)) { flint_printf("FAIL\n\n"); flint_printf("a = "); fmpz_print(a); printf("\n"); flint_printf("b = "); fmpz_print(b); printf("\n"); flint_printf("x = "); fexpr_print(x); printf("\n"); flint_abort(); } } fmpz_clear(a); fmpz_clear(b); fexpr_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fexpr/test/t-write_latex.c000066400000000000000000000067441461254215100204740ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "calcium.h" #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define strlen __builtin_strlen #else # include #endif void fexpr_randtest_atom(fexpr_t expr, flint_rand_t state) { if (n_randint(state, 2)) { fexpr_set_si(expr, (slong) n_randtest(state)); } else if (n_randint(state, 2)) { switch (n_randint(state, 10)) { case 0: fexpr_set_symbol_builtin(expr, FEXPR_For); break; case 1: fexpr_set_symbol_builtin(expr, FEXPR_Where); break; case 2: fexpr_set_symbol_builtin(expr, FEXPR_Def); break; case 3: fexpr_set_symbol_builtin(expr, FEXPR_Neg); break; case 4: fexpr_set_symbol_builtin(expr, FEXPR_Pos); break; case 5: fexpr_set_symbol_builtin(expr, FEXPR_Add); break; case 6: fexpr_set_symbol_builtin(expr, FEXPR_Sub); break; case 7: fexpr_set_symbol_builtin(expr, FEXPR_Mul); break; case 8: fexpr_set_symbol_builtin(expr, FEXPR_Div); break; default: fexpr_set_symbol_builtin(expr, FEXPR_Pow); break; } } else { fexpr_set_symbol_builtin(expr, n_randint(state, FEXPR_BUILTIN_LENGTH)); } } /* todo: doesn't actually respect max_leaves */ void fexpr_randtest_gibberish(fexpr_t expr, flint_rand_t state, slong max_leaves, slong max_depth) { if (max_leaves <= 1 || max_depth <= 1 || n_randint(state, 10) == 0) { fexpr_randtest_atom(expr, state); } else { slong i, nargs; fexpr_t f; fexpr_ptr args; fexpr_init(f); if (n_randint(state, 10) != 0) { fexpr_set_symbol_builtin(f, n_randint(state, FEXPR_BUILTIN_LENGTH)); } else { fexpr_randtest_gibberish(f, state, max_leaves / 4, max_depth - 1); max_leaves -= fexpr_num_leaves(f); } nargs = n_randint(state, 1 + FLINT_MIN(5, max_leaves / max_depth)); args = _fexpr_vec_init(nargs); for (i = 0; i < nargs; i++) { fexpr_randtest_gibberish(args + i, state, max_leaves, max_depth - 1); max_leaves -= fexpr_num_leaves(args + i); } fexpr_call_vec(expr, f, args, nargs); _fexpr_vec_clear(args, nargs); fexpr_clear(f); } } TEST_FUNCTION_START(fexpr_write_latex, state) { slong iter; /* Generate gibberish and just check that we get valid strings */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fexpr_t expr; char * s; ulong flags; slong len; fexpr_init(expr); fexpr_randtest_gibberish(expr, state, 2 + n_randint(state, 30), 2 + n_randint(state, 5)); flags = 0; if (n_randint(state, 2)) flags |= FEXPR_LATEX_SMALL; if (n_randint(state, 2)) flags |= FEXPR_LATEX_LOGIC; /* fexpr_print(expr); printf("\n\n"); */ s = fexpr_get_str_latex(expr, flags); len = strlen(s); (void)len; flint_free(s); fexpr_clear(expr); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fexpr/vec_sort_fast.c000066400000000000000000000010741461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fexpr.h" void _fexpr_vec_sort_fast(fexpr_ptr vec, slong len) { qsort(vec, len, sizeof(fexpr_struct), (int(*)(const void*,const void*)) fexpr_cmp_fast); } flint-3.1.3/src/fexpr/write_latex.c000066400000000000000000003225331461254215100172510ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy # define strcmp __builtin_strcmp # define strlen __builtin_strlen #else # include #endif void fexpr_write_latex_symbol(int * subscript, calcium_stream_t out, const fexpr_t expr, ulong flags); int _fexpr_is_symbol_with_trailing_underscore(const fexpr_t expr); const char * fexpr_get_symbol_str_pointer(char * tmp, const fexpr_t expr) { slong i; ulong head = expr->data[0]; if (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_SYMBOL) { if (((head >> 8) & 0xff) == 0) { i = head >> 16; return fexpr_builtin_table[i].string; } tmp[FEXPR_SMALL_SYMBOL_LEN] = '\0'; for (i = 0; i < FEXPR_SMALL_SYMBOL_LEN; i++) { tmp[i] = (head >> ((i + 1) * 8)); if (tmp[i] == '\0') break; } return tmp; } else if (FEXPR_TYPE(head) == FEXPR_TYPE_BIG_SYMBOL) { return (const char *) (expr->data + 1); } else { flint_throw(FLINT_ERROR, "fexpr_get_symbol_str_pointer: a symbol is required\n"); } } int _fexpr_is_symbol_with_trailing_underscore(const fexpr_t expr) { const char *s; char tmp[FEXPR_SMALL_SYMBOL_LEN + 1]; slong len; if (!fexpr_is_symbol(expr)) return 0; s = fexpr_get_symbol_str_pointer(tmp, expr); len = strlen(s); return (len > 1 && s[len - 1] == '_'); } int _fexpr_is_symbol_with_internal_underscore(const fexpr_t expr) { const char *s; char tmp[FEXPR_SMALL_SYMBOL_LEN + 1]; slong i, len; if (!fexpr_is_symbol(expr)) return 0; s = fexpr_get_symbol_str_pointer(tmp, expr); len = strlen(s); if (len >= 3) { for (i = 1; i < len - 1; i++) if (s[i] == '_') return i; } return 0; } /* static int fexpr_view_call0(fexpr_t func, const fexpr_t expr) { slong nargs; nargs = fexpr_nargs(expr); if (nargs != 0) return 0; fexpr_view_func(func, expr); return 1; } */ static int fexpr_view_call1(fexpr_t func, fexpr_t x1, const fexpr_t expr) { slong nargs; nargs = fexpr_nargs(expr); if (nargs != 1) return 0; fexpr_view_func(func, expr); *x1 = *func; fexpr_view_next(x1); return 1; } /* static int fexpr_view_call2(fexpr_t func, fexpr_t x1, fexpr_t x2, const fexpr_t expr) { slong nargs; nargs = fexpr_nargs(expr); if (nargs != 2) return 0; fexpr_view_func(func, expr); *x1 = *func; fexpr_view_next(x1); *x2 = *x1; fexpr_view_next(x2); return 1; } */ static int fexpr_view_call3(fexpr_t func, fexpr_t x1, fexpr_t x2, fexpr_t x3, const fexpr_t expr) { slong nargs; nargs = fexpr_nargs(expr); if (nargs != 3) return 0; fexpr_view_func(func, expr); *x1 = *func; fexpr_view_next(x1); *x2 = *x1; fexpr_view_next(x2); *x3 = *x2; fexpr_view_next(x3); return 1; } /* static int fexpr_view_call4(fexpr_t func, fexpr_t x1, fexpr_t x2, fexpr_t x3, fexpr_t x4, const fexpr_t expr) { slong nargs; nargs = fexpr_nargs(expr); if (nargs != 4) return 0; fexpr_view_func(func, expr); *x1 = *func; fexpr_view_next(x1); *x2 = *x1; fexpr_view_next(x2); *x3 = *x2; fexpr_view_next(x3); *x4 = *x3; fexpr_view_next(x4); return 1; } */ static int fexpr_need_parens_in_mul(const fexpr_t expr, slong arg_index) { if (fexpr_is_atom(expr)) { if (arg_index == 0) return 0; return fexpr_is_neg_integer(expr); } else { fexpr_t func; fexpr_view_func(func, expr); if (fexpr_is_builtin_symbol(func, FEXPR_Add)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Sub)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Neg)) return (arg_index != 0); if (fexpr_is_builtin_symbol(func, FEXPR_Pos)) return (arg_index != 0); return 0; } } /* todo */ static int fexpr_need_cdot_before_factor(const fexpr_t expr) { if (fexpr_is_integer(expr)) return 1; if (fexpr_is_builtin_symbol(expr, FEXPR_Infinity) || fexpr_is_builtin_symbol(expr, FEXPR_UnsignedInfinity)) return 1; if (fexpr_is_builtin_call(expr, FEXPR_Mul) && fexpr_nargs(expr) >= 1) { fexpr_t first; fexpr_view_arg(first, expr, 0); return fexpr_need_cdot_before_factor(first); } if (fexpr_is_builtin_call(expr, FEXPR_Neg) || fexpr_is_builtin_call(expr, FEXPR_Pos)) return 1; if (fexpr_is_builtin_call(expr, FEXPR_Pow) && fexpr_nargs(expr) == 2) { fexpr_t first; fexpr_view_arg(first, expr, 0); if (fexpr_is_integer(first)) return 1; } return 0; } void fexpr_write_latex_mul(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; slong i, len; int need_parens; len = fexpr_nargs(expr); if (len == 0) { calcium_write(out, "(1)"); return; } fexpr_view_arg(arg, expr, 0); for (i = 0; i < len; i++) { /* 1 * x * y or -1 * x * y -> x * y, - x * y */ if (i == 0 && len >= 2 && fexpr_is_integer(arg) && (fexpr_equal_si(arg, 1) || fexpr_equal_si(arg, -1))) { if (fexpr_equal_si(arg, -1)) calcium_write(out, "-"); fexpr_view_next(arg); if (fexpr_need_cdot_before_factor(arg)) calcium_write(out, "1 \\cdot "); else calcium_write(out, " "); } else { need_parens = fexpr_need_parens_in_mul(arg, i); if (need_parens) calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); if (need_parens) calcium_write(out, "\\right)"); if (i < len - 1) { fexpr_view_next(arg); if (fexpr_need_cdot_before_factor(arg)) calcium_write(out, " \\cdot "); else calcium_write(out, " "); } } } } static int fexpr_need_parens_in_numerator(const fexpr_t expr) { if (fexpr_is_atom(expr)) { return 0; } else { fexpr_t func; fexpr_view_func(func, expr); if (fexpr_is_builtin_symbol(func, FEXPR_Add)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Sub)) return 1; return 0; } } static int fexpr_need_parens_in_denominator(const fexpr_t expr) { if (fexpr_is_atom(expr)) { return 0; } else { fexpr_t func; fexpr_view_func(func, expr); if (fexpr_is_builtin_symbol(func, FEXPR_Add)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Sub)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Mul)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Div)) return 1; return 0; } } static int fexpr_can_extract_leading_sign(const fexpr_t expr) { if (fexpr_is_atom(expr)) { return fexpr_is_neg_integer(expr); } else { fexpr_t func; fexpr_view_func(func, expr); if (fexpr_is_builtin_symbol(func, FEXPR_Neg)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Pos)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Mul) && fexpr_nargs(expr) >= 1) { fexpr_view_next(func); return fexpr_can_extract_leading_sign(func); } return 0; } } void fexpr_write_latex_div(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t num, den; /* Expect exactly 2 arguments */ if (fexpr_nargs(expr) != 2) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(num, expr, 0); fexpr_view_arg(den, expr, 1); if (flags & FEXPR_LATEX_SMALL) { int pnum, pden; pnum = fexpr_need_parens_in_numerator(num); pden = fexpr_need_parens_in_denominator(den); if (pnum) calcium_write(out, "\\left("); fexpr_write_latex(out, num, flags); if (pnum) calcium_write(out, "\\right)"); calcium_write(out, " / "); if (pden) calcium_write(out, "\\left("); fexpr_write_latex(out, den, flags); if (pden) calcium_write(out, "\\right)"); } else { if (fexpr_can_extract_leading_sign(num)) { char * s = fexpr_get_str_latex(num, flags); if (s[0] == '+' || s[0] == '-') { char tmp[2]; tmp[0] = s[0]; tmp[1] = '\0'; calcium_write(out, tmp); calcium_write(out, "\\frac{"); calcium_write(out, s + 1); calcium_write(out, "}{"); fexpr_write_latex(out, den, flags); calcium_write(out, "}"); } else { calcium_write(out, "\\frac{"); fexpr_write_latex(out, num, flags); calcium_write(out, "}{"); fexpr_write_latex(out, den, flags); calcium_write(out, "}"); } flint_free(s); } else { calcium_write(out, "\\frac{"); fexpr_write_latex(out, num, flags); calcium_write(out, "}{"); fexpr_write_latex(out, den, flags); calcium_write(out, "}"); } } } void fexpr_write_latex_neg_pos(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; /* Expect exactly 1 argument */ if (fexpr_nargs(expr) != 1) { fexpr_write_latex_call(out, expr, flags); return; } if (fexpr_is_builtin_call(expr, FEXPR_Pos)) calcium_write(out, "+"); else calcium_write(out, "-"); fexpr_view_arg(arg, expr, 0); if (fexpr_is_builtin_call(arg, FEXPR_Neg) || fexpr_is_builtin_call(arg, FEXPR_Pos) || fexpr_is_builtin_call(arg, FEXPR_Add) || fexpr_is_builtin_call(arg, FEXPR_Sub) || fexpr_is_neg_integer(arg)) { calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex(out, arg, flags); } } static int fexpr_need_parens_in_add(const fexpr_t expr) { if (fexpr_is_atom(expr)) { return 0; } else { fexpr_t func; fexpr_view_func(func, expr); if (fexpr_is_builtin_symbol(func, FEXPR_Sub)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Neg)) return 1; return 0; } } void fexpr_write_latex_add(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; slong i, len; len = fexpr_nargs(expr); if (len == 0) { calcium_write(out, "(0)"); return; } fexpr_view_arg(arg, expr, 0); for (i = 0; i < len; i++) { if (i == 0) { fexpr_write_latex(out, arg, flags); } else { int need_parens = fexpr_need_parens_in_add(arg); if (need_parens) { calcium_write(out, " + \\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } else { char * s = fexpr_get_str_latex(arg, flags); if (s[0] == '+' || s[0] == '-') { calcium_write(out, s); } else { calcium_write(out, " + "); calcium_write(out, s); } flint_free(s); } } fexpr_view_next(arg); } } static int fexpr_need_parens_in_sub(const fexpr_t expr) { if (fexpr_is_atom(expr)) { return fexpr_is_neg_integer(expr); } else { fexpr_t func; fexpr_view_func(func, expr); if (fexpr_is_builtin_symbol(func, FEXPR_Add)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Sub)) return 1; if (fexpr_is_builtin_symbol(func, FEXPR_Neg)) return 1; if ((fexpr_is_builtin_symbol(func, FEXPR_Mul) || fexpr_is_builtin_symbol(func, FEXPR_Div)) && fexpr_nargs(expr) >= 1) { fexpr_t arg; fexpr_view_arg(arg, expr, 0); return fexpr_can_extract_leading_sign(arg); } return 0; } } void fexpr_write_latex_sub(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; slong i, len; len = fexpr_nargs(expr); if (len == 0) { calcium_write(out, "(0)"); return; } fexpr_view_arg(arg, expr, 0); for (i = 0; i < len; i++) { if (i == 0) { fexpr_write_latex(out, arg, flags); } else { int need_parens = fexpr_need_parens_in_sub(arg); if (need_parens) { calcium_write(out, " - \\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } else { calcium_write(out, " - "); fexpr_write_latex(out, arg, flags); } } fexpr_view_next(arg); } } static int fexpr_power_base_is_safe(const fexpr_t base) { if (fexpr_is_atom(base)) { if (fexpr_is_neg_integer(base)) return 0; return 1; } else { slong id; fexpr_t func; if (fexpr_is_any_builtin_call(base)) { fexpr_view_func(func, base); id = FEXPR_BUILTIN_ID(func->data[0]); if (id == FEXPR_Abs) return 1; if (id == FEXPR_Binomial) return 1; if (id == FEXPR_Matrix) return 1; if (id == FEXPR_Matrix2x2) return 1; if (id == FEXPR_Parentheses) return 1; if (id == FEXPR_Brackets) return 1; if (id == FEXPR_Braces) return 1; if (id == FEXPR_AngleBrackets) return 1; } return 0; } } void _fexpr_write_latex_pow(calcium_stream_t out, const fexpr_t base, const fexpr_t expo, ulong flags) { if (fexpr_is_any_builtin_call(base) && fexpr_nargs(base) == 1) { fexpr_t func, arg; fexpr_view_func(func, base); /* (f(x))^n written as f^n(x) for some standard functions */ switch (FEXPR_BUILTIN_ID(func->data[0])) { case FEXPR_Sin: case FEXPR_Cos: case FEXPR_Tan: case FEXPR_Cot: case FEXPR_Sec: case FEXPR_Csc: case FEXPR_Sinh: case FEXPR_Cosh: case FEXPR_Tanh: case FEXPR_Coth: case FEXPR_Sech: case FEXPR_Csch: case FEXPR_Log: case FEXPR_Sinc: case FEXPR_DedekindEta: fexpr_write_latex(out, func, flags); calcium_write(out, "^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); fexpr_view_arg(arg, base, 0); calcium_write(out, "}\\!\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); return; default: break; } } /* todo: generalize */ if ((fexpr_is_builtin_call(base, FEXPR_JacobiTheta) || fexpr_is_builtin_call(base, FEXPR_JacobiThetaQ)) && fexpr_nargs(base) == 3) { fexpr_t func, x, y, z; fexpr_view_func(func, base); fexpr_view_arg(x, base, 0); fexpr_view_arg(y, base, 1); fexpr_view_arg(z, base, 2); calcium_write(out, "\\theta_{"); fexpr_write_latex(out, x, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}\\!\\left("); fexpr_write_latex(out, y, flags); calcium_write(out, ", "); fexpr_write_latex(out, z, flags); calcium_write(out, "\\right)"); return; } if (fexpr_is_symbol(base)) { slong underscore_pos; char * s; /* Need to change {x_3}^{y} -> x^{y}_{3} for correct rendering */ underscore_pos = _fexpr_is_symbol_with_internal_underscore(base); if (underscore_pos > 0) { char *sym, *sub; s = fexpr_get_symbol_str(base); s[underscore_pos] = '\0'; sym = s; sub = s + underscore_pos + 1; if (underscore_pos == 1) { calcium_write(out, sym); } else { calcium_write(out, "\\operatorname{"); calcium_write(out, sym); calcium_write(out, "}"); } calcium_write(out, "^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}_{"); calcium_write(out, sub); calcium_write(out, "}"); return; } } if (fexpr_is_any_builtin_call(base)) { slong id; fexpr_t func, x, y; fexpr_view_func(func, base); id = FEXPR_BUILTIN_ID(func->data[0]); if (fexpr_builtin_table[id].latex_writer == fexpr_write_latex_subscript && fexpr_nargs(base) == 1) { fexpr_view_arg(x, base, 0); fexpr_write_latex(out, func, flags); calcium_write(out, "_{"); fexpr_write_latex(out, x, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); return; } if (fexpr_builtin_table[id].latex_writer == fexpr_write_latex_subscript_call && fexpr_nargs(base) == 2) { fexpr_view_arg(x, base, 0); fexpr_view_arg(y, base, 1); fexpr_write_latex(out, func, flags); calcium_write(out, "_{"); fexpr_write_latex(out, x, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}\\!\\left("); fexpr_write_latex(out, y, flags); calcium_write(out, "\\right)"); return; } } if (fexpr_is_builtin_call(base, FEXPR_Subscript) && fexpr_nargs(base) == 2) { fexpr_t func, x; fexpr_view_arg(func, base, 0); fexpr_view_arg(x, base, 1); calcium_write(out, "{"); fexpr_write_latex(out, func, flags); calcium_write(out, "}_{"); fexpr_write_latex(out, x, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); return; } if (fexpr_nargs(base) == 1) { fexpr_t func, x; int subscript; fexpr_view_func(func, base); if (_fexpr_is_symbol_with_trailing_underscore(func)) { fexpr_view_arg(x, base, 0); fexpr_write_latex_symbol(&subscript, out, func, flags); calcium_write(out, "_{"); fexpr_write_latex(out, x, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); return; } } if (fexpr_power_base_is_safe(base)) { calcium_write(out, "{"); fexpr_write_latex(out, base, flags); calcium_write(out, "}^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } else { calcium_write(out, "{\\left("); fexpr_write_latex(out, base, flags); calcium_write(out, "\\right)}^{"); fexpr_write_latex(out, expo, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } } void fexpr_write_latex_pow(calcium_stream_t out, const fexpr_t expr, ulong flags) { if (fexpr_nargs(expr) == 2) { fexpr_t base, expo; fexpr_view_arg(base, expr, 0); fexpr_view_arg(expo, expr, 1); _fexpr_write_latex_pow(out, base, expo, flags); } else { fexpr_write_latex_call(out, expr, flags); } } static int fexpr_show_exp_as_power(const fexpr_t expr) { fexpr_t func, arg; slong i, nargs; if (fexpr_is_atom(expr)) return 1; fexpr_view_func(func, expr); /* todo: more systematic solution */ if (fexpr_is_builtin_symbol(func, FEXPR_Pos) || fexpr_is_builtin_symbol(func, FEXPR_Neg) || fexpr_is_builtin_symbol(func, FEXPR_Add) || fexpr_is_builtin_symbol(func, FEXPR_Sub) || fexpr_is_builtin_symbol(func, FEXPR_Mul) || fexpr_is_builtin_symbol(func, FEXPR_Div) || fexpr_is_builtin_symbol(func, FEXPR_Pow) || fexpr_is_builtin_symbol(func, FEXPR_Abs) || fexpr_is_builtin_symbol(func, FEXPR_RealAbs) || fexpr_is_builtin_symbol(func, FEXPR_Sqrt) || fexpr_is_builtin_symbol(func, FEXPR_Re) || fexpr_is_builtin_symbol(func, FEXPR_Im) || fexpr_is_builtin_symbol(func, FEXPR_Log)) { nargs = fexpr_nargs(expr); if (fexpr_is_builtin_symbol(func, FEXPR_Div) && nargs == 2) { fexpr_view_arg(arg, expr, 1); if (!fexpr_is_atom(arg)) return 0; } fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { if (!fexpr_show_exp_as_power(arg)) return 0; fexpr_view_next(arg); } return 1; } return 0; } void fexpr_write_latex_exp(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; slong nargs; nargs = fexpr_nargs(expr); if (nargs == 1) { fexpr_view_arg(arg, expr, 0); if (fexpr_show_exp_as_power(arg)) { calcium_write(out, "e^{"); fexpr_write_latex(out, arg, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } else { calcium_write(out, "\\exp\\!\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } return; } fexpr_write_latex_call(out, expr, flags); } void fexpr_write_latex_factorial(calcium_stream_t out, const fexpr_t expr, ulong flags) { if (fexpr_nargs(expr) == 1) { fexpr_t func, arg; fexpr_view_func(func, expr); fexpr_view_arg(arg, expr, 0); if (fexpr_is_symbol(arg) || (fexpr_is_integer(arg) && !fexpr_is_neg_integer(arg))) { fexpr_write_latex(out, arg, flags); } else { calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } if (fexpr_is_builtin_symbol(func, FEXPR_DoubleFactorial)) calcium_write(out, "!!"); else calcium_write(out, "!"); } else { fexpr_write_latex_call(out, expr, flags); } } void fexpr_write_latex_sum_product(calcium_stream_t out, const fexpr_t expr, ulong flags) { slong nargs, forexpr_nargs; fexpr_t f, forexpr, var, low, high, domain, predicate; int have_predicate = 0; int have_domain = 0; int have_low_high = 0; int need_parens; nargs = fexpr_nargs(expr); if (nargs != 2 && nargs != 3) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(f, expr, 0); fexpr_view_arg(forexpr, expr, 1); if (nargs == 3) { fexpr_view_arg(predicate, expr, 2); have_predicate = 1; } forexpr_nargs = fexpr_nargs(forexpr); if (forexpr_nargs != 2 && forexpr_nargs != 3) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(var, forexpr, 0); if (forexpr_nargs == 2) { fexpr_view_arg(domain, forexpr, 1); have_domain = 1; } else { fexpr_view_arg(low, forexpr, 1); fexpr_view_arg(high, forexpr, 2); have_low_high = 1; } if (fexpr_is_builtin_call(expr, FEXPR_Sum)) calcium_write(out, "\\sum"); else calcium_write(out, "\\prod"); if (have_domain) { if (have_predicate) { calcium_write(out, "_{\\textstyle{"); fexpr_write_latex(out, var, flags); calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags); calcium_write(out, " \\atop "); fexpr_write_latex(out, predicate, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}}"); } else { calcium_write(out, "_{"); fexpr_write_latex(out, var, flags); calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } } else if (have_low_high) { if (have_predicate) { calcium_write(out, "_{\\textstyle{"); fexpr_write_latex(out, var, flags); calcium_write(out, "="); fexpr_write_latex(out, low, flags | FEXPR_LATEX_SMALL); calcium_write(out, " \\atop "); fexpr_write_latex(out, predicate, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}}^{"); fexpr_write_latex(out, high, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } else { calcium_write(out, "_{"); fexpr_write_latex(out, var, flags); calcium_write(out, "="); fexpr_write_latex(out, low, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}^{"); fexpr_write_latex(out, high, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } } calcium_write(out, " "); need_parens = fexpr_is_builtin_call(f, FEXPR_Add) || fexpr_is_builtin_call(f, FEXPR_Sub); if (need_parens) calcium_write(out, "\\left("); fexpr_write_latex(out, f, flags); if (need_parens) calcium_write(out, "\\right)"); } void fexpr_write_latex_divsum(calcium_stream_t out, const fexpr_t expr, ulong flags) { slong nargs, forexpr_nargs; fexpr_t f, forexpr, var, high, predicate; slong expected_forargs; int have_predicate = 0; int need_parens; nargs = fexpr_nargs(expr); if (nargs != 2 && nargs != 3) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(f, expr, 0); fexpr_view_arg(forexpr, expr, 1); if (nargs == 3) { fexpr_view_arg(predicate, expr, 2); have_predicate = 1; } forexpr_nargs = fexpr_nargs(forexpr); if (fexpr_is_builtin_call(expr, FEXPR_DivisorSum) || fexpr_is_builtin_call(expr, FEXPR_DivisorProduct)) expected_forargs = 2; else expected_forargs = 1; if (forexpr_nargs != expected_forargs) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(var, forexpr, 0); if (forexpr_nargs == 2) fexpr_view_arg(high, forexpr, 1); if (fexpr_is_builtin_call(expr, FEXPR_DivisorSum) || fexpr_is_builtin_call(expr, FEXPR_PrimeSum)) calcium_write(out, "\\sum_{"); else calcium_write(out, "\\prod_{"); if (fexpr_is_builtin_call(expr, FEXPR_DivisorSum) || fexpr_is_builtin_call(expr, FEXPR_DivisorProduct)) { fexpr_write_latex(out, var, flags | FEXPR_LATEX_SMALL); calcium_write(out, " \\mid "); fexpr_write_latex(out, high, flags | FEXPR_LATEX_SMALL); if (have_predicate) { calcium_write(out, ",\\, "); fexpr_write_latex(out, predicate, flags | FEXPR_LATEX_SMALL); } } else { if (have_predicate) fexpr_write_latex(out, predicate, flags | FEXPR_LATEX_SMALL); else fexpr_write_latex(out, var, flags | FEXPR_LATEX_SMALL); } calcium_write(out, "} "); need_parens = fexpr_is_builtin_call(f, FEXPR_Add) || fexpr_is_builtin_call(f, FEXPR_Sub); if (need_parens) calcium_write(out, "\\left("); fexpr_write_latex(out, f, flags); if (need_parens) calcium_write(out, "\\right)"); } void fexpr_write_latex_integral(calcium_stream_t out, const fexpr_t expr, ulong flags) { if (fexpr_nargs(expr) == 2) { fexpr_t f, iter, var, low, high, domain; int need_parens; fexpr_view_arg(f, expr, 0); fexpr_view_arg(iter, expr, 1); need_parens = fexpr_is_builtin_call(f, FEXPR_Add) || fexpr_is_builtin_call(f, FEXPR_Sub); if (fexpr_is_builtin_call(iter, FEXPR_For)) { if (fexpr_nargs(iter) == 2) { fexpr_view_arg(var, iter, 0); fexpr_view_arg(domain, iter, 1); calcium_write(out, "\\int_{"); fexpr_write_latex(out, var, flags | FEXPR_LATEX_SMALL); calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags | FEXPR_LATEX_SMALL); calcium_write(out, "} "); if (need_parens) calcium_write(out, "\\left("); fexpr_write_latex(out, f, flags); if (need_parens) calcium_write(out, "\\right)"); calcium_write(out, " \\, d"); fexpr_write_latex(out, var, flags); return; } if (fexpr_nargs(iter) == 3) { fexpr_view_arg(var, iter, 0); fexpr_view_arg(low, iter, 1); fexpr_view_arg(high, iter, 2); calcium_write(out, "\\int_{"); fexpr_write_latex(out, low, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}^{"); fexpr_write_latex(out, high, flags | FEXPR_LATEX_SMALL); calcium_write(out, "} "); if (need_parens) calcium_write(out, "\\left("); fexpr_write_latex(out, f, flags); if (need_parens) calcium_write(out, "\\right)"); calcium_write(out, " \\, d"); fexpr_write_latex(out, var, flags); return; } } } fexpr_write_latex_call(out, expr, flags); } void fexpr_write_latex_limit(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t op, formula, forexpr, var, point, predicate; slong nargs, id; int have_predicate = 0; int parens; nargs = fexpr_nargs(expr); if (nargs != 2 && nargs != 3) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_func(op, expr); fexpr_view_arg(formula, expr, 0); fexpr_view_arg(forexpr, expr, 1); if (fexpr_nargs(forexpr) != 2) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(var, forexpr, 0); fexpr_view_arg(point, forexpr, 1); if (nargs == 3) { fexpr_view_arg(predicate, expr, 2); have_predicate = 1; } id = FEXPR_BUILTIN_ID(op->data[0]); if (id == FEXPR_SequenceLimitInferior) calcium_write(out, "\\liminf_{"); else if (id == FEXPR_SequenceLimitSuperior) calcium_write(out, "\\limsup_{"); else calcium_write(out, "\\lim_{"); fexpr_write_latex(out, var, flags); calcium_write(out, " \\to "); if (id == FEXPR_LeftLimit || id == FEXPR_RightLimit) calcium_write(out, "{"); fexpr_write_latex(out, point, flags | FEXPR_LATEX_SMALL); if (id == FEXPR_LeftLimit) calcium_write(out, "}^{-}"); if (id == FEXPR_RightLimit) calcium_write(out, "}^{+}"); if (have_predicate) { calcium_write(out, ",\\,"); fexpr_write_latex(out, predicate, flags | FEXPR_LATEX_SMALL); } calcium_write(out, "} "); parens = (fexpr_is_builtin_call(formula, FEXPR_Add) || fexpr_is_builtin_call(formula, FEXPR_Sub)); if (parens) calcium_write(out, "\\left["); fexpr_write_latex(out, formula, flags); if (parens) calcium_write(out, "\\right]"); } void fexpr_write_latex_residue(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t op, formula, forexpr, var, point; slong nargs, id; int parens; nargs = fexpr_nargs(expr); if (nargs != 2) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_func(op, expr); fexpr_view_arg(formula, expr, 0); fexpr_view_arg(forexpr, expr, 1); if (fexpr_nargs(forexpr) != 2) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(var, forexpr, 0); fexpr_view_arg(point, forexpr, 1); id = FEXPR_BUILTIN_ID(op->data[0]); if (id == FEXPR_ComplexZeroMultiplicity) calcium_write(out, "\\mathop{\\operatorname{ord}}\\limits_{"); else calcium_write(out, "\\mathop{\\operatorname{res}}\\limits_{"); fexpr_write_latex(out, var, flags); calcium_write(out, "="); fexpr_write_latex(out, point, flags); calcium_write(out, "} "); parens = (fexpr_is_builtin_call(formula, FEXPR_Add) || fexpr_is_builtin_call(formula, FEXPR_Sub)); if (parens) calcium_write(out, "\\left["); fexpr_write_latex(out, formula, flags); if (parens) calcium_write(out, "\\right]"); } void _fexpr_write_latex_derivative(calcium_stream_t out, const fexpr_t f, const fexpr_t subscript, const fexpr_t order, ulong flags) { if (fexpr_equal_ui(order, 1)) { fexpr_write_latex(out, f, flags); calcium_write(out, "'"); } else if (fexpr_equal_ui(order, 2)) { fexpr_write_latex(out, f, flags); calcium_write(out, "''"); } else if (fexpr_equal_ui(order, 3)) { fexpr_write_latex(out, f, flags); calcium_write(out, "'''"); } else { calcium_write(out, "{"); fexpr_write_latex(out, f, flags); calcium_write(out, "}^{("); fexpr_write_latex(out, order, flags); calcium_write(out, ")}"); } if (subscript != NULL) { calcium_write(out, "_{"); fexpr_write_latex(out, subscript, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } } void fexpr_write_latex_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t formula, forexpr, var, point, order; slong nargs, forexpr_nargs; int parens; ulong tmp; nargs = fexpr_nargs(expr); if (nargs != 2) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(formula, expr, 0); fexpr_view_arg(forexpr, expr, 1); forexpr_nargs = fexpr_nargs(forexpr); if (forexpr_nargs != 2 && forexpr_nargs != 3) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(var, forexpr, 0); fexpr_view_arg(point, forexpr, 1); if (forexpr_nargs == 3) { fexpr_view_arg(order, forexpr, 2); } else { order->data = &tmp; order->alloc = 1; fexpr_set_ui(order, 1); } /* d/dx f(x) -> f'(x) */ if (fexpr_nargs(formula) == 1) { fexpr_t f, x; fexpr_view_func(f, formula); fexpr_view_arg(x, formula, 0); if (fexpr_equal(x, var) && fexpr_is_symbol(f) && !fexpr_is_builtin_symbol(f, FEXPR_Exp) && !fexpr_is_builtin_symbol(f, FEXPR_Sqrt)) { _fexpr_write_latex_derivative(out, f, NULL, order, flags); calcium_write(out, "\\!\\left("); fexpr_write_latex(out, point, flags); calcium_write(out, "\\right)"); return; } } /* d/dx f_n(x) -> f'_n(x) */ if (fexpr_nargs(formula) == 2) { fexpr_t f, n, x; slong id; fexpr_view_func(f, formula); fexpr_view_arg(n, formula, 0); fexpr_view_arg(x, formula, 1); if (fexpr_equal(x, var) && fexpr_is_any_builtin_symbol(f)) { id = FEXPR_BUILTIN_ID(f->data[0]); if (fexpr_builtin_table[id].latex_writer == fexpr_write_latex_subscript_call) { _fexpr_write_latex_derivative(out, f, n, order, flags); calcium_write(out, "\\!\\left("); fexpr_write_latex(out, point, flags); calcium_write(out, "\\right)"); return; } } } if (!fexpr_equal(var, point)) calcium_write(out, "\\left["); if (fexpr_equal_ui(order, 1)) { calcium_write(out, "\\frac{d}{d "); fexpr_write_latex(out, var, flags); calcium_write(out, "}\\, "); } else { calcium_write(out, "\\frac{d^{"); fexpr_write_latex(out, order, flags); calcium_write(out, "}}{{d "); fexpr_write_latex(out, var, flags); calcium_write(out, "}^{"); fexpr_write_latex(out, order, flags); calcium_write(out, "}}\\, "); } parens = (fexpr_is_builtin_call(formula, FEXPR_Add) || fexpr_is_builtin_call(formula, FEXPR_Sub)); if (parens) calcium_write(out, "\\left["); fexpr_write_latex(out, formula, flags); if (parens) calcium_write(out, "\\right]"); if (!fexpr_equal(var, point)) { calcium_write(out, " \\right]_{"); fexpr_write_latex(out, var, flags); calcium_write(out, " = "); fexpr_write_latex(out, point, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } } void fexpr_write_latex_setop(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t op, formula, forexpr, var, domain, predicate; const char * ops; slong nargs, id; int have_predicate = 0, have_domain = 0; int parens; nargs = fexpr_nargs(expr); fexpr_view_func(op, expr); id = FEXPR_BUILTIN_ID(op->data[0]); switch (id) { case FEXPR_Minimum: ops = "\\min"; break; case FEXPR_Maximum: ops = "\\max"; break; case FEXPR_ArgMin: ops = "\\operatorname{arg\\,min}"; break; case FEXPR_ArgMax: ops = "\\operatorname{arg\\,max}"; break; case FEXPR_ArgMinUnique: ops = "\\operatorname{arg\\,min*}"; break; case FEXPR_ArgMaxUnique: ops = "\\operatorname{arg\\,max*}"; break; case FEXPR_Infimum: ops = "\\operatorname{inf}"; break; case FEXPR_Supremum: ops = "\\operatorname{sup}"; break; case FEXPR_Zeros: ops = "\\operatorname{zeros}"; break; case FEXPR_UniqueZero: ops = "\\operatorname{zero*}"; break; case FEXPR_Solutions: ops = "\\operatorname{solutions}"; break; case FEXPR_UniqueSolution: ops = "\\operatorname{solution*}"; break; case FEXPR_Poles: ops = "\\operatorname{poles}"; break; default: ops = ""; } if (nargs == 1) { fexpr_t arg; fexpr_view_arg(arg, expr, 0); calcium_write(out, ops); if (fexpr_is_builtin_call(arg, FEXPR_Set)) { calcium_write(out, " "); fexpr_write_latex(out, arg, flags); } else { calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } return; } if (nargs != 2 && nargs != 3) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(formula, expr, 0); fexpr_view_arg(forexpr, expr, 1); if (fexpr_nargs(forexpr) != 1 && fexpr_nargs(forexpr) != 2) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_arg(var, forexpr, 0); if (fexpr_nargs(forexpr) == 1) { have_domain = 0; } else { fexpr_view_arg(domain, forexpr, 1); have_domain = 1; } if (nargs == 3) { fexpr_view_arg(predicate, expr, 2); have_predicate = 1; } calcium_write(out, "\\mathop{"); calcium_write(out, ops); calcium_write(out, "\\,}\\limits_{"); if (have_domain) { fexpr_write_latex(out, var, flags | FEXPR_LATEX_SMALL); calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags | FEXPR_LATEX_SMALL); } if (have_predicate) { if (have_domain) calcium_write(out, ",\\,"); fexpr_write_latex(out, predicate, flags | FEXPR_LATEX_SMALL); } calcium_write(out, "} "); parens = (fexpr_is_builtin_call(formula, FEXPR_Add) || fexpr_is_builtin_call(formula, FEXPR_Sub) || fexpr_is_builtin_call(formula, FEXPR_Neg) || fexpr_is_builtin_call(formula, FEXPR_Sum) || fexpr_is_builtin_call(formula, FEXPR_Product) || fexpr_is_builtin_call(formula, FEXPR_Integral)); if (parens) calcium_write(out, "\\left["); fexpr_write_latex(out, formula, flags); if (parens) calcium_write(out, "\\right]"); } void fexpr_write_latex_logic(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; slong i, nargs; nargs = fexpr_nargs(expr); if (fexpr_is_builtin_call(expr, FEXPR_Not) && nargs == 1) { fexpr_view_arg(arg, expr, 0); if (flags & FEXPR_LATEX_LOGIC) calcium_write(out, "\\neg "); else calcium_write(out, "\\operatorname{not} "); if (fexpr_is_atom(arg)) { fexpr_write_latex(out, arg, flags); } else { if (!(flags & FEXPR_LATEX_LOGIC)) calcium_write(out, "\\,"); calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } return; } if (fexpr_is_builtin_call(expr, FEXPR_Or) && nargs >= 1) { fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { if (fexpr_is_builtin_call(arg, FEXPR_And) || fexpr_is_builtin_call(arg, FEXPR_Or) || fexpr_is_builtin_call(arg, FEXPR_Not)) { calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex(out, arg, flags); } if (i < nargs - 1) { if (flags & FEXPR_LATEX_LOGIC) calcium_write(out, " \\,\\lor\\, "); else calcium_write(out, " \\;\\mathbin{\\operatorname{or}}\\; "); fexpr_view_next(arg); } } return; } if (fexpr_is_builtin_call(expr, FEXPR_And) && nargs >= 1) { fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { if (fexpr_is_builtin_call(arg, FEXPR_And) || fexpr_is_builtin_call(arg, FEXPR_Or) || fexpr_is_builtin_call(arg, FEXPR_All) || fexpr_is_builtin_call(arg, FEXPR_Exists)) { calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex(out, arg, flags); } if (i < nargs - 1) { if (flags & FEXPR_LATEX_LOGIC) calcium_write(out, " \\,\\land\\, "); else if (flags & FEXPR_LATEX_SMALL) /* see see ff190c */ calcium_write(out, " ,\\, "); else calcium_write(out, " \\;\\mathbin{\\operatorname{and}}\\; "); fexpr_view_next(arg); } } return; } if (fexpr_is_builtin_call(expr, FEXPR_Implies) && nargs == 2) { fexpr_t arg1, arg2; fexpr_view_arg(arg1, expr, 0); fexpr_view_arg(arg2, expr, 1); if (!(fexpr_is_atom(arg1) || fexpr_is_builtin_call(arg1, FEXPR_Element))) { calcium_write(out, "\\left("); fexpr_write_latex(out, arg1, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex(out, arg1, flags); } calcium_write(out, " \\;\\implies\\; "); if (!(fexpr_is_atom(arg2) || fexpr_is_builtin_call(arg2, FEXPR_Element))) { calcium_write(out, "\\left("); fexpr_write_latex(out, arg2, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex(out, arg2, flags); } return; } if (fexpr_is_builtin_call(expr, FEXPR_Equivalent) && nargs >= 1) { fexpr_view_func(arg, expr); for (i = 0; i < nargs; i++) { fexpr_view_next(arg); if (!fexpr_is_atom(arg)) calcium_write(out, "\\left("); fexpr_write_latex(out, arg, flags); if (!fexpr_is_atom(arg)) calcium_write(out, "\\right)"); if (i < nargs - 1) { calcium_write(out, " \\iff "); } } return; } if ((fexpr_is_builtin_call(expr, FEXPR_All) || fexpr_is_builtin_call(expr, FEXPR_Exists)) && (nargs == 2 || nargs == 3)) { fexpr_t func, forarg, var, domain, condition; fexpr_view_arg(func, expr, 0); fexpr_view_arg(forarg, expr, 1); if (nargs == 3) fexpr_view_arg(condition, expr, 2); if (fexpr_nargs(forarg) == 1 || fexpr_nargs(forarg) == 2) { int have_domain = (fexpr_nargs(forarg) == 2); fexpr_view_arg(var, forarg, 0); if (have_domain) fexpr_view_arg(domain, forarg, 1); if (flags & FEXPR_LATEX_LOGIC) { if (fexpr_is_builtin_call(expr, FEXPR_All)) calcium_write(out, "\\forall "); else calcium_write(out, "\\exists "); fexpr_write_latex(out, var, flags); if (have_domain) { calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags); } if (nargs == 3) { calcium_write(out, ", \\,"); fexpr_write_latex(out, condition, flags); } calcium_write(out, " : \\, "); fexpr_write_latex(out, func, flags); } else { fexpr_write_latex(out, func, flags); if (fexpr_is_builtin_call(expr, FEXPR_All)) calcium_write(out, " \\;\\text{ for all } "); else calcium_write(out, " \\;\\text{ for some } "); fexpr_write_latex(out, var, flags); if (have_domain) { calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags); } if (nargs == 3) { calcium_write(out, " \\text{ with } "); fexpr_write_latex(out, condition, flags); } } return; } } if (fexpr_is_builtin_call(expr, FEXPR_Logic) && nargs == 1) { fexpr_t arg; fexpr_view_arg(arg, expr, 0); fexpr_write_latex(out, arg, flags | FEXPR_LATEX_LOGIC); return; } /* todo: move this */ if (fexpr_is_builtin_call(expr, FEXPR_CongruentMod) && nargs == 3) { fexpr_t arg; fexpr_view_arg(arg, expr, 0); fexpr_write_latex(out, arg, flags); calcium_write(out, " \\equiv "); fexpr_view_next(arg); fexpr_write_latex(out, arg, flags); calcium_write(out, " \\pmod {"); fexpr_view_next(arg); fexpr_write_latex(out, arg, flags); calcium_write(out, " }"); return; } fexpr_write_latex_call(out, expr, flags); } void fexpr_write_latex_cases(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg, value, condition; slong i, nargs; calcium_write(out, "\\begin{cases} "); nargs = fexpr_nargs(expr); fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { if (fexpr_nargs(arg) != 2) continue; fexpr_view_arg(value, arg, 0); fexpr_view_arg(condition, arg, 1); fexpr_write_latex(out, value, flags /* | FEXPR_LATEX_SMALL */); calcium_write(out, ", & "); if (fexpr_is_builtin_symbol(condition, FEXPR_Otherwise)) calcium_write(out, "\\text{otherwise}"); else fexpr_write_latex(out, condition, flags /* | FEXPR_LATEX_SMALL */); calcium_write(out, "\\\\"); if (i < nargs - 1) fexpr_view_next(arg); } calcium_write(out, " \\end{cases}"); } void fexpr_write_latex_simple(calcium_stream_t out, const fexpr_t expr, ulong flags) { slong i; const char * a; const char * b; fexpr_t func, arg; if (fexpr_nargs(expr) != 1 || !fexpr_is_any_builtin_call(expr)) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_func(func, expr); fexpr_view_arg(arg, expr, 0); i = FEXPR_BUILTIN_ID(func->data[0]); switch (i) { case FEXPR_Sqrt: a = "\\sqrt{"; b = "}"; break; case FEXPR_Conjugate: a = "\\overline{"; b = "}"; break; case FEXPR_Cardinality: case FEXPR_Length: a = "\\# "; b = ""; break; case FEXPR_Abs: case FEXPR_RealAbs: a = "\\left|"; b = "\\right|"; break; case FEXPR_Floor: a = "\\left\\lfloor "; b = " \\right\\rfloor"; break; case FEXPR_Ceil: a = "\\left\\lceil "; b = "\\right\\rceil"; break; case FEXPR_Parentheses: a = "\\left("; b = "\\right)"; break; case FEXPR_Brackets: a = "\\left["; b = "\\right]"; break; case FEXPR_Braces: a = "\\left\\{"; b = "\\right\\}"; break; case FEXPR_AngleBrackets: a = "\\left\\langle "; b = "\\right\\rangle"; break; case FEXPR_IsEven: a = ""; b = " \\text{ even}"; break; case FEXPR_IsOdd: a = ""; b = " \\text{ odd}"; break; case FEXPR_IsPrime: a = ""; b = " \\text{ prime}"; break; case FEXPR_Enclosure: a = "\\left(\\in "; b = " \\right)"; break; case FEXPR_Guess: a = "\\left(?\\; "; b = " \\right)"; break; case FEXPR_Approximation: a = "\\left(\\approx "; b = " \\right)"; break; default: fexpr_write_latex_call(out, expr, flags); return; } calcium_write(out, a); fexpr_write_latex(out, arg, flags); calcium_write(out, b); } void _fexpr_write_latex_simple2(calcium_stream_t out, const fexpr_t expr, ulong flags) { slong i; const char * a; const char * b; const char * c; fexpr_t func, arg1, arg2; if (fexpr_nargs(expr) != 2 || !fexpr_is_any_builtin_call(expr)) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_func(func, expr); fexpr_view_arg(arg1, expr, 0); fexpr_view_arg(arg2, expr, 1); i = FEXPR_BUILTIN_ID(func->data[0]); switch (i) { case FEXPR_RisingFactorial: a = "\\left("; b = "\\right)_{"; c = "}"; break; case FEXPR_FallingFactorial: a = "\\left("; b = "\\right)^{\\underline{"; c = "}}"; break; case FEXPR_Binomial: a = "{"; b = " \\choose "; c = "}"; break; case FEXPR_StirlingCycle: a = "\\left[{"; b = " \\atop "; c = "}\\right]"; break; case FEXPR_StirlingS1: a = "s\\!\\left("; b = ", "; c = "\\right)"; break; case FEXPR_StirlingS2: a = "\\left\\{{"; b = " \\atop "; c = "}\\right\\}"; break; case FEXPR_LegendreSymbol: case FEXPR_JacobiSymbol: case FEXPR_KroneckerSymbol: a = "\\left(\\frac{"; b = "}{"; c = "}\\right)"; break; case FEXPR_Interval: a = "\\left["; b = ", "; c = "\\right]"; break; case FEXPR_OpenInterval: a = "\\left("; b = ", "; c = "\\right)"; break; case FEXPR_ClosedOpenInterval: a = "\\left["; b = ", "; c = "\\right)"; break; case FEXPR_OpenClosedInterval: a = "\\left("; b = ", "; c = "\\right]"; break; case FEXPR_RealBall: a = "\\left["; b = " \\pm "; c = "\\right]"; break; case FEXPR_OpenRealBall: a = "\\left("; b = " \\pm "; c = "\\right)"; break; case FEXPR_KroneckerDelta: a = "\\delta_{("; b = ","; c = ")}"; break; case FEXPR_Subscript: case FEXPR_Item: a = "{"; b = "}_{"; c = "}"; break; default: fexpr_write_latex_call(out, expr, flags); return; } calcium_write(out, a); fexpr_write_latex(out, arg1, flags); calcium_write(out, b); fexpr_write_latex(out, arg2, flags); calcium_write(out, c); } void fexpr_write_latex_simple2(calcium_stream_t out, const fexpr_t expr, ulong flags) { _fexpr_write_latex_simple2(out, expr, flags); } void fexpr_write_latex_simple2_small(calcium_stream_t out, const fexpr_t expr, ulong flags) { _fexpr_write_latex_simple2(out, expr, flags | FEXPR_LATEX_SMALL); } void fexpr_write_latex_collection(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; slong nargs; nargs = fexpr_nargs(expr); /* Set comprehension */ if (fexpr_is_builtin_call(expr, FEXPR_Set) && (nargs == 2 || nargs == 3)) { slong for_nargs; fexpr_view_arg(arg, expr, 1); for_nargs = fexpr_nargs(arg); if (fexpr_is_builtin_call(arg, FEXPR_For) && (for_nargs == 2 || for_nargs == 1)) { fexpr_t func, var, domain, predicate; fexpr_view_arg(func, expr, 0); fexpr_view_arg(var, arg, 0); if (for_nargs == 2) fexpr_view_arg(domain, arg, 1); calcium_write(out, "\\left\\{ "); fexpr_write_latex(out, func, flags); if (for_nargs == 2 || nargs == 3) calcium_write(out, " : "); if (for_nargs == 2) { fexpr_write_latex(out, var, flags); calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags); } if (nargs == 3) { fexpr_view_arg(predicate, expr, 2); if (for_nargs == 2) calcium_write(out, "\\,\\mathbin{\\operatorname{and}}\\, "); fexpr_write_latex(out, predicate, flags); } calcium_write(out, " \\right\\}"); return; } } if (fexpr_is_builtin_call(expr, FEXPR_Set)) calcium_write(out, "\\left\\{"); else if (fexpr_is_builtin_call(expr, FEXPR_Tuple)) calcium_write(out, "\\left("); else if (fexpr_is_builtin_call(expr, FEXPR_List)) calcium_write(out, "\\left["); else if (fexpr_is_builtin_call(expr, FEXPR_Lattice)) calcium_write(out, "\\Lambda_{("); { fexpr_t func, var, a, b; slong for_nargs; if (nargs == 2) { fexpr_view_arg(arg, expr, 1); for_nargs = fexpr_nargs(arg); } /* {f(n) for n=a..b} -- todo: special cases for infinity, explicit integer a and b */ if (nargs == 2 && fexpr_is_builtin_call(arg, FEXPR_For) && for_nargs == 3) { fexpr_t first, second, last, t, a1; fmpz_t n; fexpr_view_arg(func, expr, 0); fexpr_view_arg(var, arg, 0); fexpr_view_arg(a, arg, 1); fexpr_view_arg(b, arg, 2); fexpr_init(first); fexpr_init(second); fexpr_init(last); fexpr_init(a1); fexpr_init(t); fmpz_init(n); if (fexpr_is_integer(a)) { fexpr_get_fmpz(n, a); fmpz_add_ui(n, n, 1); fexpr_set_fmpz(a1, n); } else { fexpr_set_ui(t, 1); fexpr_add(a1, a, t); } fexpr_replace(first, func, var, a); fexpr_replace(second, func, var, a1); fexpr_replace(last, func, var, b); fexpr_write_latex(out, first, flags); calcium_write(out, ", "); fexpr_write_latex(out, second, flags); calcium_write(out, ", \\ldots, "); fexpr_write_latex(out, last, flags); fexpr_clear(first); fexpr_clear(second); fexpr_clear(last); fexpr_clear(a1); fexpr_clear(t); fmpz_clear(n); } else if (nargs >= 1) { slong i; fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { fexpr_write_latex(out, arg, flags); if (i < nargs - 1) { calcium_write(out, ", "); fexpr_view_next(arg); } } } } if (fexpr_is_builtin_call(expr, FEXPR_Set)) calcium_write(out, "\\right\\}"); else if (fexpr_is_builtin_call(expr, FEXPR_Tuple)) calcium_write(out, "\\right)"); else if (fexpr_is_builtin_call(expr, FEXPR_List)) calcium_write(out, "\\right]"); else if (fexpr_is_builtin_call(expr, FEXPR_Lattice)) calcium_write(out, ")}"); } void fexpr_write_latex_range(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t a, b; if (fexpr_is_builtin_call(expr, FEXPR_IntegersGreaterEqual) && fexpr_nargs(expr) == 1) { fexpr_view_arg(a, expr, 0); calcium_write(out, "\\mathbb{Z}_{\\ge "); fexpr_write_latex(out, a, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); return; } if (fexpr_is_builtin_call(expr, FEXPR_IntegersLessEqual) && fexpr_nargs(expr) == 1) { fexpr_view_arg(a, expr, 0); if (fexpr_is_integer(a)) { fmpz_t n; fmpz_init(n); fexpr_get_fmpz(n, a); calcium_write(out, "\\{"); calcium_write_fmpz(out, n); calcium_write(out, ", "); fmpz_sub_ui(n, n, 1); calcium_write_fmpz(out, n); calcium_write(out, ", \\ldots\\}"); fmpz_clear(n); } else { calcium_write(out, "\\mathbb{Z}_{\\le "); fexpr_write_latex(out, a, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } return; } if (fexpr_is_builtin_call(expr, FEXPR_Range) && fexpr_nargs(expr) == 2) { fexpr_view_arg(a, expr, 0); fexpr_view_arg(b, expr, 1); if (fexpr_is_integer(a)) { fmpz_t n; fmpz_init(n); fexpr_get_fmpz(n, a); calcium_write(out, "\\{"); calcium_write_fmpz(out, n); calcium_write(out, ", "); fmpz_add_ui(n, n, 1); calcium_write_fmpz(out, n); calcium_write(out, ", \\ldots, "); fexpr_write_latex(out, b, flags); calcium_write(out, "\\}"); fmpz_clear(n); } else { calcium_write(out, "\\{"); fexpr_write_latex(out, a, flags); calcium_write(out, ", "); fexpr_write_latex(out, a, flags); calcium_write(out, " + 1, \\ldots, "); fexpr_write_latex(out, b, flags); calcium_write(out, "\\}"); } return; } fexpr_write_latex_call(out, expr, flags); } void fexpr_write_latex_matrix(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg, row, elem; slong i, j, nargs, nrows, ncols; nargs = fexpr_nargs(expr); if (fexpr_is_builtin_call(expr, FEXPR_RowMatrix) || fexpr_is_builtin_call(expr, FEXPR_ColumnMatrix)) { int isrow = fexpr_is_builtin_call(expr, FEXPR_RowMatrix); calcium_write(out, "\\displaystyle{\\begin{pmatrix}"); if (nargs > 0) { fexpr_view_arg(elem, expr, 0); for (i = 0; i < nargs; i++) { fexpr_write_latex(out, elem, flags); if (i < nargs - 1) { if (isrow) calcium_write(out, " & "); else calcium_write(out, " \\\\ "); fexpr_view_next(elem); } } } calcium_write(out, "\\end{pmatrix}}"); return; } if (fexpr_is_builtin_call(expr, FEXPR_DiagonalMatrix)) { calcium_write(out, "\\displaystyle{\\begin{pmatrix}"); if (nargs > 0) { fexpr_view_arg(elem, expr, 0); for (i = 0; i < nargs; i++) { for (j = 0; j < i; j++) calcium_write(out, " & "); fexpr_write_latex(out, elem, flags); for (j = i + 1; j < nargs; j++) calcium_write(out, " & "); if (i < nargs - 1) { calcium_write(out, " \\\\ "); fexpr_view_next(elem); } } } calcium_write(out, "\\end{pmatrix}}"); return; } if (fexpr_is_builtin_call(expr, FEXPR_Matrix2x2) && nargs == 4) { calcium_write(out, "\\displaystyle{\\begin{pmatrix}"); fexpr_view_arg(elem, expr, 0); fexpr_write_latex(out, elem, flags); calcium_write(out, " & "); fexpr_view_next(elem); fexpr_write_latex(out, elem, flags); calcium_write(out, " \\\\ "); fexpr_view_next(elem); fexpr_write_latex(out, elem, flags); calcium_write(out, " & "); fexpr_view_next(elem); fexpr_write_latex(out, elem, flags); calcium_write(out, "\\end{pmatrix}}"); return; } if (fexpr_is_builtin_call(expr, FEXPR_Matrix) && nargs == 3) { fexpr_t for1, for2, f1, f2, i, a, b, j, c, d; fexpr_view_arg(for1, expr, 1); fexpr_view_arg(for2, expr, 2); if (fexpr_view_call3(f1, i, a, b, for1) && fexpr_view_call3(f2, j, c, d, for2) && fexpr_is_builtin_symbol(f1, FEXPR_For) && fexpr_is_builtin_symbol(f2, FEXPR_For)) { fexpr_t a1, c1, x; fmpz_t n; fmpz_init(n); fexpr_init(a1); fexpr_init(c1); fexpr_init(x); fexpr_view_arg(arg, expr, 0); /* a1 = a + 1 */ if (fexpr_is_integer(a)) { fexpr_get_fmpz(n, a); fmpz_add_ui(n, n, 1); fexpr_set_fmpz(a1, n); } else { fexpr_set_ui(x, 1); fexpr_add(a1, a, x); } /* c1 = c + 1 */ if (fexpr_is_integer(c)) { fexpr_get_fmpz(n, c); fmpz_add_ui(n, n, 1); fexpr_set_fmpz(c1, n); } else { fexpr_set_ui(x, 1); fexpr_add(c1, c, x); } calcium_write(out, "\\displaystyle{\\begin{pmatrix} "); fexpr_replace2(x, arg, i, a, j, c); fexpr_write_latex(out, x, flags); calcium_write(out, " & "); fexpr_replace2(x, arg, i, a, j, c1); fexpr_write_latex(out, x, flags); calcium_write(out, " & \\cdots & "); fexpr_replace2(x, arg, i, a, j, d); fexpr_write_latex(out, x, flags); calcium_write(out, " \\\\ "); fexpr_replace2(x, arg, i, a1, j, c); fexpr_write_latex(out, x, flags); calcium_write(out, " & "); fexpr_replace2(x, arg, i, a1, j, c1); fexpr_write_latex(out, x, flags); calcium_write(out, " & \\cdots & "); fexpr_replace2(x, arg, i, a1, j, d); fexpr_write_latex(out, x, flags); calcium_write(out, " \\\\ "); calcium_write(out, "\\vdots & \\vdots & \\ddots & \\vdots \\\\ "); fexpr_replace2(x, arg, i, b, j, c); fexpr_write_latex(out, x, flags); calcium_write(out, " & "); fexpr_replace2(x, arg, i, b, j, c1); fexpr_write_latex(out, x, flags); calcium_write(out, " & \\cdots & "); fexpr_replace2(x, arg, i, b, j, d); fexpr_write_latex(out, x, flags); calcium_write(out, " \\end{pmatrix}}"); fmpz_clear(n); fexpr_clear(a1); fexpr_clear(c1); fexpr_clear(x); return; } } if (fexpr_is_builtin_call(expr, FEXPR_Matrix) && nargs >= 1) { fexpr_view_arg(arg, expr, 0); /* Todo: handle columns too */ if (fexpr_is_builtin_call(arg, FEXPR_Row)) { nrows = fexpr_nargs(expr); calcium_write(out, "\\displaystyle{\\begin{pmatrix}"); fexpr_view_arg(row, expr, 0); for (i = 0; i < nrows; i++) { ncols = fexpr_nargs(row); if (ncols >= 0) { fexpr_view_arg(elem, row, 0); for (j = 0; j < ncols; j++) { fexpr_write_latex(out, elem, flags); if (j < ncols - 1) { calcium_write(out, " & "); fexpr_view_next(elem); } } } if (i < nrows - 1) { calcium_write(out, " \\\\"); fexpr_view_next(row); } } calcium_write(out, "\\end{pmatrix}}"); return; } } if (nargs == 1) { fexpr_view_arg(arg, expr, 0); if (fexpr_is_builtin_call(arg, FEXPR_Tuple) || fexpr_is_builtin_call(arg, FEXPR_List)) { nrows = fexpr_nargs(arg); calcium_write(out, "\\displaystyle{\\begin{pmatrix}"); fexpr_view_arg(row, arg, 0); for (i = 0; i < nrows; i++) { ncols = fexpr_nargs(row); if (ncols >= 0) { fexpr_view_arg(elem, row, 0); for (j = 0; j < ncols; j++) { fexpr_write_latex(out, elem, flags); if (j < ncols - 1) { calcium_write(out, " & "); fexpr_view_next(elem); } } } if (i < nrows - 1) { calcium_write(out, " \\\\"); fexpr_view_next(row); } } calcium_write(out, "\\end{pmatrix}}"); return; } } fexpr_write_latex_call(out, expr, flags); } void fexpr_write_latex_decimal(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t arg; char * s; slong i, len; if (fexpr_nargs(expr) == 1) { fexpr_view_arg(arg, expr, 0); if (fexpr_is_string(arg)) { s = fexpr_get_string(arg); len = strlen(s); for (i = 0; i < len; i++) { if (s[i] == 'e' || s[i] == 'E') { s[i] = '\0'; calcium_write(out, s); calcium_write(out, " \\cdot 10^{"); calcium_write(out, s + i + 1); calcium_write(out, "}"); flint_free(s); return; } } calcium_write(out, s); flint_free(s); return; } } fexpr_write_latex_call(out, expr, flags); } /* Write (x) */ void _fexpr_write_latex_call1(calcium_stream_t out, const fexpr_t x, ulong flags) { if (fexpr_is_atom(x)) { calcium_write(out, "("); fexpr_write_latex(out, x, flags); calcium_write(out, ")"); } else { calcium_write(out, "\\!\\left("); fexpr_write_latex(out, x, flags); calcium_write(out, "\\right)"); } } static void _write_poly(calcium_stream_t out, const fexpr_t pol, ulong flags) { fexpr_t c; slong i, d; d = fexpr_nargs(pol) - 1; if (d < 0) { calcium_write(out, "0"); return; } for (i = d; i >= 0; i--) { fexpr_view_arg(c, pol, i); if (fexpr_equal_si(c, 0)) continue; if (fexpr_equal_si(c, 1)) { if (i == 0) calcium_write(out, "+1"); else if (i != d) calcium_write(out, "+"); } else if (fexpr_equal_si(c, -1)) { if (i == 0) calcium_write(out, "-1"); else calcium_write(out, "-"); } else { if (fexpr_need_parens_in_mul(c, 0)) { if (i != d) calcium_write(out, "+ "); calcium_write(out, "\\left("); fexpr_write_latex(out, c, flags); calcium_write(out, "\\right)"); } else { if (fexpr_is_integer(c)) { if (!(fexpr_can_extract_leading_sign(c) || i == d)) calcium_write(out, "+"); fexpr_write_latex(out, c, flags); } else { char * s = fexpr_get_str_latex(c, flags); if (s[0] == '+' || s[0] == '-') { calcium_write(out, s); } else { if (i != d) calcium_write(out, " + "); calcium_write(out, s); } flint_free(s); } } } if (i == 1) { calcium_write(out, " x"); } else if (i >= 2) { calcium_write(out, " x^{"); calcium_write_si(out, i); calcium_write(out, "}"); } } } void fexpr_write_latex_misc_special(calcium_stream_t out, const fexpr_t expr, ulong flags) { if (fexpr_is_builtin_call(expr, FEXPR_Polynomial) && fexpr_nargs(expr) == 1) { fexpr_t pol; fexpr_view_arg(pol, expr, 0); _write_poly(out, pol, flags); return; } if (fexpr_is_builtin_call(expr, FEXPR_PolynomialRootNearest) && fexpr_nargs(expr) == 2) { fexpr_t pol, point; fexpr_view_arg(pol, expr, 0); fexpr_view_arg(point, expr, 1); /* calcium_write(out, "\\left(x \\approx "); fexpr_write_latex(out, point, flags); calcium_write(out, ", \\,"); _write_poly(out, pol, flags); calcium_write(out, "= 0\\right)"); return; */ calcium_write(out, "\\left(\\text{Root }\\, "); calcium_write(out, "x \\approx {"); fexpr_write_latex(out, point, flags); calcium_write(out, "} \\;\\text{ of } \\;{"); _write_poly(out, pol, flags); calcium_write(out, "}\\right)"); return; } if (fexpr_is_builtin_call(expr, FEXPR_PolynomialRootIndexed) && fexpr_nargs(expr) == 2) { fexpr_t pol, point; fexpr_view_arg(pol, expr, 0); fexpr_view_arg(point, expr, 1); calcium_write(out, "\\left(\\text{Root \\#}"); fexpr_write_latex(out, point, flags); calcium_write(out, " \\text{ of }\\, {"); _write_poly(out, pol, flags); calcium_write(out, "}\\right)"); return; } /* if (fexpr_is_builtin_call(expr, FEXPR_AlgebraicNumberSerialized) && fexpr_nargs(expr) == 2) { fexpr_t pol, index; fexpr_view_arg(pol, expr, 0); fexpr_view_arg(index, expr, 1); calcium_write(out, "\\left(\\text{Algebraic } "); fexpr_write_latex(out, pol, flags); calcium_write(out, "_{"); fexpr_write_latex(out, index, flags); calcium_write(out, "}\\right)"); return; } */ if (fexpr_is_builtin_call(expr, FEXPR_Call) && fexpr_nargs(expr) == 2) { fexpr_t f, x; fexpr_view_arg(f, expr, 0); fexpr_view_arg(x, expr, 1); fexpr_write_latex(out, f, flags); _fexpr_write_latex_call1(out, x, flags); return; } if (fexpr_is_builtin_call(expr, FEXPR_CallIndeterminate) && fexpr_nargs(expr) == 3) { fexpr_t f, x, v; fexpr_view_arg(f, expr, 0); fexpr_view_arg(x, expr, 1); fexpr_view_arg(v, expr, 2); fexpr_write_latex(out, f, flags); _fexpr_write_latex_call1(out, v, flags); return; } if (fexpr_is_builtin_call(expr, FEXPR_IndefiniteIntegralEqual) && fexpr_nargs(expr) == 3) { fexpr_t fx, gx, x; fexpr_view_arg(fx, expr, 0); fexpr_view_arg(gx, expr, 1); fexpr_view_arg(x, expr, 2); calcium_write(out, "\\int "); fexpr_write_latex(out, fx, flags); calcium_write(out, " \\, d"); fexpr_write_latex(out, x, flags); calcium_write(out, " = "); fexpr_write_latex(out, gx, flags); calcium_write(out, " + \\mathcal{C}"); return; } if (fexpr_is_builtin_call(expr, FEXPR_CurvePath) && fexpr_nargs(expr) == 2) { fexpr_t f, forexpr, x, a, b; slong forexpr_nargs; fexpr_view_arg(f, expr, 0); fexpr_view_arg(forexpr, expr, 1); forexpr_nargs = fexpr_nargs(forexpr); if (forexpr_nargs == 3) { fexpr_view_arg(x, forexpr, 0); fexpr_view_arg(a, forexpr, 1); fexpr_view_arg(b, forexpr, 2); calcium_write(out, "\\left("); fexpr_write_latex(out, f, flags); calcium_write(out, ",\\, "); fexpr_write_latex(out, x, flags); calcium_write(out, " : "); fexpr_write_latex(out, a, flags); calcium_write(out, " \\rightsquigarrow "); fexpr_write_latex(out, b, flags); calcium_write(out, "\\right)"); return; } } if (fexpr_is_builtin_call(expr, FEXPR_AnalyticContinuation) && fexpr_nargs(expr) == 2) { fexpr_t f, forexpr, x, a, b; slong forexpr_nargs; fexpr_view_arg(f, expr, 0); fexpr_view_arg(forexpr, expr, 1); forexpr_nargs = fexpr_nargs(forexpr); if (forexpr_nargs == 2) { fexpr_view_arg(x, forexpr, 0); fexpr_view_arg(a, forexpr, 1); calcium_write(out, "\\mathop{\\text{Continuation}}\\limits_{\\displaystyle{"); fexpr_write_latex(out, x, flags); calcium_write(out, ": "); fexpr_write_latex(out, a, flags); calcium_write(out, "}} \\, "); fexpr_write_latex(out, f, flags); return; } if (forexpr_nargs == 3) { fexpr_view_arg(x, forexpr, 0); fexpr_view_arg(a, forexpr, 1); fexpr_view_arg(b, forexpr, 2); calcium_write(out, "\\mathop{\\text{Continuation}}\\limits_{\\displaystyle{"); fexpr_write_latex(out, x, flags); calcium_write(out, ": "); fexpr_write_latex(out, a, flags); calcium_write(out, " \\rightsquigarrow "); fexpr_write_latex(out, b, flags); calcium_write(out, "}} \\, "); fexpr_write_latex(out, f, flags); return; } } if (fexpr_is_builtin_call(expr, FEXPR_QSeriesCoefficient) && fexpr_nargs(expr) == 5) { fexpr_t f, tau, q, n, qdef; int parens; fexpr_view_arg(f, expr, 0); fexpr_view_arg(tau, expr, 1); fexpr_view_arg(q, expr, 2); fexpr_view_arg(n, expr, 3); fexpr_view_arg(qdef, expr, 4); parens = fexpr_is_builtin_call(f, FEXPR_Add) || fexpr_is_builtin_call(f, FEXPR_Sub); calcium_write(out, "[{"); fexpr_write_latex(out, q, flags); calcium_write(out, "}^{"); fexpr_write_latex(out, n, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}] "); if (parens) calcium_write(out, "\\left("); fexpr_write_latex(out, f, flags); if (parens) calcium_write(out, "\\right)"); calcium_write(out, " \\; \\left("); fexpr_write_latex(out, qdef, flags); calcium_write(out, "\\right)"); return; } if (fexpr_is_builtin_call(expr, FEXPR_EqualQSeriesEllipsis) && fexpr_nargs(expr) == 5) { fexpr_t f, tau, q, ser, qdef; fexpr_view_arg(f, expr, 0); fexpr_view_arg(tau, expr, 1); fexpr_view_arg(q, expr, 2); fexpr_view_arg(ser, expr, 3); fexpr_view_arg(qdef, expr, 4); fexpr_write_latex(out, f, flags); calcium_write(out, " = "); fexpr_write_latex(out, ser, flags | FEXPR_LATEX_SMALL); calcium_write(out, " + \\ldots \\; \\text{ where } "); fexpr_write_latex(out, qdef, flags); return; } if (fexpr_is_builtin_call(expr, FEXPR_Coefficient) && fexpr_nargs(expr) == 3) { fexpr_t f, x, n; int parens; fexpr_view_arg(f, expr, 0); fexpr_view_arg(x, expr, 1); fexpr_view_arg(n, expr, 2); parens = fexpr_is_builtin_call(f, FEXPR_Add) || fexpr_is_builtin_call(f, FEXPR_Sub); calcium_write(out, "[{"); fexpr_write_latex(out, x, flags); calcium_write(out, "}^{"); fexpr_write_latex(out, n, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}] "); if (parens) calcium_write(out, "\\left("); fexpr_write_latex(out, f, flags); if (parens) calcium_write(out, "\\right)"); return; } if (fexpr_is_builtin_call(expr, FEXPR_DiscreteLog) && fexpr_nargs(expr) == 3) { fexpr_t n, b, q; fexpr_view_arg(n, expr, 0); fexpr_view_arg(b, expr, 1); fexpr_view_arg(q, expr, 2); calcium_write(out, "(\\epsilon : {"); /* todo: may need parentheses */ fexpr_write_latex(out, b, flags); calcium_write(out, "}^{\\epsilon} \\equiv "); fexpr_write_latex(out, n, flags); calcium_write(out, " \\text{ mod }"); fexpr_write_latex(out, q, flags); calcium_write(out, ")"); return; } if (fexpr_is_builtin_call(expr, FEXPR_AsymptoticTo) && fexpr_nargs(expr) == 4) { fexpr_t a, b, c, d; fexpr_view_arg(a, expr, 0); fexpr_view_arg(b, expr, 1); fexpr_view_arg(c, expr, 2); fexpr_view_arg(d, expr, 3); fexpr_write_latex(out, a, flags); calcium_write(out, " \\sim "); fexpr_write_latex(out, b, flags); calcium_write(out, ", \\; "); fexpr_write_latex(out, c, flags); calcium_write(out, " \\to "); fexpr_write_latex(out, d, flags); return; } if ((fexpr_is_builtin_call(expr, FEXPR_CoulombF) || fexpr_is_builtin_call(expr, FEXPR_CoulombG)) && fexpr_nargs(expr) == 3) { fexpr_t l, eta, z; fexpr_view_arg(l, expr, 0); fexpr_view_arg(eta, expr, 1); fexpr_view_arg(z, expr, 2); if (fexpr_is_builtin_call(expr, FEXPR_CoulombF)) calcium_write(out, "F_{"); else calcium_write(out, "G_{"); fexpr_write_latex(out, l, flags | FEXPR_LATEX_SMALL); calcium_write(out, ","); fexpr_write_latex(out, eta, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); _fexpr_write_latex_call1(out, z, flags); return; } if (fexpr_is_builtin_call(expr, FEXPR_CoulombH) && fexpr_nargs(expr) == 4) { fexpr_t omega, l, eta, z; fexpr_view_arg(omega, expr, 0); fexpr_view_arg(l, expr, 1); fexpr_view_arg(eta, expr, 2); fexpr_view_arg(z, expr, 3); calcium_write(out, "H^{"); if (fexpr_equal_si(omega, +1)) calcium_write(out, "+"); else if (fexpr_equal_si(omega, -1)) calcium_write(out, "-"); else fexpr_write_latex(out, omega, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}_{"); fexpr_write_latex(out, l, flags | FEXPR_LATEX_SMALL); calcium_write(out, ","); fexpr_write_latex(out, eta, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); _fexpr_write_latex_call1(out, z, flags); return; } if (fexpr_is_builtin_call(expr, FEXPR_Repeat) && fexpr_nargs(expr) >= 2) { slong i, n; fexpr_t x; n = fexpr_nargs(expr) - 1; calcium_write(out, "\\underbrace{"); for (i = 0; i < n; i++) { fexpr_view_arg(x, expr, i); fexpr_write_latex(out, x, flags); if (i < n - 1) calcium_write(out, ", "); } calcium_write(out, ", \\ldots, "); for (i = 0; i < n; i++) { fexpr_view_arg(x, expr, i); fexpr_write_latex(out, x, flags); if (i < n - 1) calcium_write(out, ", "); } calcium_write(out, "}_{"); if (n > 1) { calcium_write(out, "\\left("); for (i = 0; i < n; i++) { fexpr_view_arg(x, expr, i); fexpr_write_latex(out, x, flags); if (i < n - 1) calcium_write(out, ", "); } calcium_write(out, "\\right) \\; "); } fexpr_view_arg(x, expr, n); fexpr_write_latex(out, x, flags); calcium_write(out, " \\text{ times}}"); return; } if (fexpr_is_builtin_call(expr, FEXPR_Matrices)) { fexpr_t R, n, m; if (fexpr_nargs(expr) == 2 || fexpr_nargs(expr) == 3) { fexpr_view_arg(R, expr, 0); fexpr_view_arg(n, expr, 1); calcium_write(out, "\\operatorname{M}_{"); fexpr_write_latex(out, n, flags); if (fexpr_nargs(expr) == 3) { calcium_write(out, " \\times "); fexpr_view_arg(m, expr, 2); fexpr_write_latex(out, m, flags | FEXPR_LATEX_SMALL); } calcium_write(out, "}"); _fexpr_write_latex_call1(out, R, flags); return; } } if (fexpr_is_builtin_call(expr, FEXPR_DirichletCharacter)) { fexpr_t a, b, n; if (fexpr_nargs(expr) == 2 || fexpr_nargs(expr) == 3) { fexpr_view_arg(a, expr, 0); fexpr_view_arg(b, expr, 1); calcium_write(out, "\\chi_{"); fexpr_write_latex(out, a, flags | FEXPR_LATEX_SMALL); calcium_write(out, " \\, . \\, "); fexpr_write_latex(out, b, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); if (fexpr_nargs(expr) == 3) { fexpr_view_arg(n, expr, 2); _fexpr_write_latex_call1(out, n, flags); } return; } } if (fexpr_is_builtin_call(expr, FEXPR_LambertW)) { fexpr_t f, x, n, r; if (fexpr_nargs(expr) == 1) { fexpr_view_arg(n, expr, 0); calcium_write(out, "W"); _fexpr_write_latex_call1(out, n, flags); return; } if (fexpr_nargs(expr) == 2) { fexpr_view_arg(x, expr, 0); fexpr_view_arg(n, expr, 1); calcium_write(out, "W_{"); fexpr_write_latex(out, n, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); _fexpr_write_latex_call1(out, x, flags); return; } if (fexpr_nargs(expr) == 3) { fexpr_view_func(f, expr); fexpr_view_arg(x, expr, 0); fexpr_view_arg(n, expr, 1); fexpr_view_arg(r, expr, 2); _fexpr_write_latex_derivative(out, f, NULL, r, flags); calcium_write(out, "_{"); fexpr_write_latex(out, n, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); _fexpr_write_latex_call1(out, x, flags); return; } } if (fexpr_is_builtin_call(expr, FEXPR_SloaneA) && fexpr_nargs(expr) == 2) { fexpr_t x, n; fexpr_view_arg(x, expr, 0); fexpr_view_arg(n, expr, 1); calcium_write(out, "\\text{"); if (fexpr_is_integer(x)) { fmpz_t t; fmpz_init(t); fexpr_get_fmpz(t, x); if (fmpz_cmp_ui(t, 10) < 0) calcium_write(out, "A00000"); else if (fmpz_cmp_ui(t, 100) < 0) calcium_write(out, "A0000"); else if (fmpz_cmp_ui(t, 1000) < 0) calcium_write(out, "A000"); else if (fmpz_cmp_ui(t, 10000) < 0) calcium_write(out, "A00"); else if (fmpz_cmp_ui(t, 100000) < 0) calcium_write(out, "A0"); else calcium_write(out, "A"); calcium_write_fmpz(out, t); fmpz_clear(t); } else if (fexpr_is_string(x)) { char * s = fexpr_get_string(x); if (s[0] != 'A') calcium_write(out, "A"); calcium_write_free(out, s); } else { calcium_write(out, "A00000"); fexpr_write_latex(out, x, flags); } calcium_write(out, "}\\!\\left("); fexpr_write_latex(out, n, flags); calcium_write(out, "\\right)"); return; } if (fexpr_is_builtin_call(expr, FEXPR_EqualAndElement)) { fexpr_t a, b, c; if (fexpr_nargs(expr) == 3) { fexpr_view_arg(a, expr, 0); fexpr_view_arg(b, expr, 1); fexpr_view_arg(c, expr, 2); fexpr_write_latex(out, a, flags); calcium_write(out, " = "); fexpr_write_latex(out, b, flags); calcium_write(out, " \\in "); fexpr_write_latex(out, c, flags); return; } } if (fexpr_is_builtin_call(expr, FEXPR_EqualNearestDecimal)) { fexpr_t a, b, c; if (fexpr_nargs(expr) == 3) { fexpr_view_arg(a, expr, 0); fexpr_view_arg(b, expr, 1); fexpr_view_arg(c, expr, 2); fexpr_write_latex(out, a, flags); calcium_write(out, " = "); fexpr_write_latex(out, b, flags); calcium_write(out, " \\;\\, {\\scriptstyle (\\text{nearest } "); fexpr_write_latex(out, c, flags); calcium_write(out, " \\text{ digits})}"); return; } } if (fexpr_is_builtin_call(expr, FEXPR_IsHolomorphicOn) || fexpr_is_builtin_call(expr, FEXPR_IsMeromorphicOn)) { if (fexpr_nargs(expr) == 2) { fexpr_t func, forexpr; fexpr_view_arg(func, expr, 0); fexpr_view_arg(forexpr, expr, 1); if (fexpr_nargs(forexpr) == 2) { fexpr_t var, domain; fexpr_view_arg(var, forexpr, 0); fexpr_view_arg(domain, forexpr, 1); fexpr_write_latex(out, func, flags); if (fexpr_is_builtin_call(expr, FEXPR_IsHolomorphicOn)) calcium_write(out, " \\text{ is holomorphic on } "); else calcium_write(out, " \\text{ is meromorphic on } "); fexpr_write_latex(out, var, flags); calcium_write(out, " \\in "); fexpr_write_latex(out, domain, flags); return; } } } fexpr_write_latex_call(out, expr, flags); } void fexpr_write_latex_show_form(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t f, arg; if (fexpr_view_call1(f, arg, expr) && fexpr_is_builtin_symbol(f, FEXPR_ShowExpandedNormalForm)) { fexpr_t v; fexpr_init(v); fexpr_expanded_normal_form(v, arg, 0); fexpr_write_latex(out, v, flags); fexpr_clear(v); return; } fexpr_write_latex_call(out, expr, flags); } void fexpr_write_latex_alg_structure(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t func, arg; const char *a; const char *b; slong i, nargs; nargs = fexpr_nargs(expr); if (nargs <= 1) { fexpr_write_latex_call(out, expr, flags); return; } fexpr_view_func(func, expr); fexpr_view_arg(arg, expr, 0); i = FEXPR_BUILTIN_ID(func->data[0]); switch (i) { case FEXPR_Polynomials: a = "["; b = "]"; break; case FEXPR_PolynomialFractions: a = "("; b = ")"; break; case FEXPR_FormalPowerSeries: a = "[["; b = "]]"; break; case FEXPR_FormalLaurentSeries: a = "(\\!("; b = ")\\!)"; break; case FEXPR_FormalPuiseuxSeries: a = "\\!\\left\\langle\\!\\left\\langle "; b = " \\right\\rangle\\!\\right\\rangle"; break; default: fexpr_write_latex_call(out, expr, flags); return; } fexpr_write_latex(out, arg, flags); calcium_write(out, a); if (nargs >= 1) { slong i; fexpr_view_next(arg); if (fexpr_is_builtin_call(arg, FEXPR_Tuple)) { nargs = fexpr_nargs(arg); fexpr_view_arg(arg, arg, 0); } else { nargs--; } for (i = 0; i < nargs; i++) { fexpr_write_latex(out, arg, flags); if (i < nargs - 1) { calcium_write(out, ", "); fexpr_view_next(arg); } } } calcium_write(out, b); } void fexpr_write_latex_where(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t f, arg, x, val; slong i, nargs; nargs = fexpr_nargs(expr); if (nargs > 0) { fexpr_view_arg(f, expr, 0); fexpr_write_latex(out, f, flags); } if (nargs > 1) { calcium_write(out, "\\; \\text{ where } "); fexpr_view_arg(arg, expr, 1); for (i = 1; i < nargs; i++) { if (fexpr_nargs(arg) == 2) { fexpr_view_arg(x, arg, 0); fexpr_view_arg(val, arg, 1); fexpr_write_latex(out, x, flags); calcium_write(out, " = "); fexpr_write_latex(out, val, flags); if (i < nargs - 1) { calcium_write(out, ",\\;"); fexpr_view_next(arg); } } } } } static int _fexpr_all_arguments_small(const fexpr_t expr) { fexpr_t arg; slong i, nargs; nargs = fexpr_nargs(expr); fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { if (!fexpr_is_atom(arg)) return 0; fexpr_view_next(arg); } return 1; } void fexpr_write_latex_symbol(int * subscript, calcium_stream_t out, const fexpr_t expr, ulong flags) { if (fexpr_is_any_builtin_symbol(expr)) { slong i; i = FEXPR_BUILTIN_ID(expr->data[0]); if (strcmp(fexpr_builtin_table[i].latex_string, "")) { calcium_write(out, fexpr_builtin_table[i].latex_string); } else { calcium_write(out, "\\operatorname{"); calcium_write(out, fexpr_builtin_table[i].string); calcium_write(out, "}"); } *subscript = 0; } else if (fexpr_is_symbol(expr)) { const char *s; char tmp[FEXPR_SMALL_SYMBOL_LEN + 1]; slong i, len; s = fexpr_get_symbol_str_pointer(tmp, expr); len = strlen(s); if (len > 1 && s[len - 1] == '_') { char * tmp2; tmp2 = flint_malloc(len); memcpy(tmp2, tmp, len - 1); tmp2[len - 1] = '\0'; calcium_write(out, tmp2); *subscript = 1; flint_free(tmp2); } else if (len == 1) { calcium_write(out, s); *subscript = 0; } else { /* Look for internal underscore */ slong pos = 0; for (i = 1; i < len - 1; i++) { if (s[i] == '_') { pos = i; break; } } if (pos == 0) { calcium_write(out, "\\operatorname{"); calcium_write(out, s); calcium_write(out, "}"); *subscript = 0; } else { char * tmp2; tmp2 = flint_malloc(len); memcpy(tmp2, tmp, pos); tmp2[pos] = '\0'; if (pos == 1) { calcium_write(out, tmp2); } else { calcium_write(out, "\\operatorname{"); calcium_write(out, tmp2); calcium_write(out, "}"); } calcium_write(out, "_{"); calcium_write(out, s + pos + 1); calcium_write(out, "}"); flint_free(tmp2); *subscript = 0; } } } else { if (fexpr_is_builtin_call(expr, FEXPR_Add) || fexpr_is_builtin_call(expr, FEXPR_Sub) || fexpr_is_builtin_call(expr, FEXPR_Mul) || fexpr_is_builtin_call(expr, FEXPR_Div) || fexpr_is_builtin_call(expr, FEXPR_Neg) || fexpr_is_builtin_call(expr, FEXPR_Pos)) { calcium_write(out, "\\left("); fexpr_write_latex(out, expr, flags); calcium_write(out, "\\right)"); *subscript = 0; } else { fexpr_write_latex(out, expr, flags); *subscript = 0; } } } void fexpr_write_latex_call(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t view; slong i, nargs; int small, subscript; nargs = fexpr_nargs(expr); fexpr_view_func(view, expr); fexpr_write_latex_symbol(&subscript, out, view, flags); if (subscript) { calcium_write(out, "_{"); for (i = 0; i < nargs; i++) { fexpr_view_next(view); fexpr_write_latex(out, view, flags | FEXPR_LATEX_SMALL); if (i < nargs - 1) calcium_write(out, ", "); } calcium_write(out, "}"); } else { fexpr_view_next(view); /* Function of matrix already has parentheses */ if (nargs == 1) { if (fexpr_is_builtin_call(view, FEXPR_Matrix) || fexpr_is_builtin_call(view, FEXPR_Matrix2x2)) { calcium_write(out, " "); fexpr_write_latex(out, view, flags); return; } } small = _fexpr_all_arguments_small(expr); if (small) calcium_write(out, "("); else calcium_write(out, "\\!\\left("); for (i = 0; i < nargs; i++) { fexpr_write_latex(out, view, flags); if (i < nargs - 1) { calcium_write(out, ", "); fexpr_view_next(view); } } if (small) calcium_write(out, ")"); else calcium_write(out, "\\right)"); } } void fexpr_write_latex_subscript_call(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t view; slong i, nargs; int subscript; nargs = fexpr_nargs(expr); fexpr_view_func(view, expr); fexpr_write_latex_symbol(&subscript, out, view, flags); if (nargs >= 1) { calcium_write(out, "_{"); fexpr_view_next(view); fexpr_write_latex(out, view, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); } if (nargs >= 2) { calcium_write(out, "\\!\\left("); for (i = 1; i < nargs; i++) { fexpr_view_next(view); fexpr_write_latex(out, view, flags); if (i < nargs - 1) calcium_write(out, ", "); } calcium_write(out, "\\right)"); } } void fexpr_write_latex_subscript(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t view; slong i, nargs; int subscript; nargs = fexpr_nargs(expr); fexpr_view_func(view, expr); fexpr_write_latex_symbol(&subscript, out, view, flags); calcium_write(out, "_{"); for (i = 0; i < nargs; i++) { fexpr_view_next(view); fexpr_write_latex(out, view, flags | FEXPR_LATEX_SMALL); if (i < nargs - 1) calcium_write(out, ", "); } calcium_write(out, "}"); } /* f(x) */ /* f(x,n) -> nth derivative */ void fexpr_write_latex_call1_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t func, x, order; slong nargs; nargs = fexpr_nargs(expr); if (nargs == 2) { fexpr_view_func(func, expr); fexpr_view_arg(x, expr, 0); fexpr_view_arg(order, expr, 1); _fexpr_write_latex_derivative(out, func, NULL, order, flags); calcium_write(out, "\\!\\left("); fexpr_write_latex(out, x, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex_call(out, expr, flags); } } /* f(x,y) */ /* f(x,y,n) -> nth derivative */ void fexpr_write_latex_call2_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t func, x, y, order; slong nargs; nargs = fexpr_nargs(expr); if (nargs == 3) { fexpr_view_func(func, expr); fexpr_view_arg(x, expr, 0); fexpr_view_arg(y, expr, 1); fexpr_view_arg(order, expr, 2); _fexpr_write_latex_derivative(out, func, NULL, order, flags); calcium_write(out, "\\!\\left("); fexpr_write_latex(out, x, flags); calcium_write(out, ", "); fexpr_write_latex(out, y, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex_call(out, expr, flags); } } /* f_x(y) */ /* f_x(y,n) -> nth derivative */ void fexpr_write_latex_sub1_call1_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t func, x, y, order; slong nargs; nargs = fexpr_nargs(expr); if (nargs == 3) { fexpr_view_func(func, expr); fexpr_view_arg(x, expr, 0); fexpr_view_arg(y, expr, 1); fexpr_view_arg(order, expr, 2); _fexpr_write_latex_derivative(out, func, NULL, order, flags); calcium_write(out, "_{"); fexpr_write_latex(out, x, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); calcium_write(out, "\\!\\left("); fexpr_write_latex(out, y, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex_subscript_call(out, expr, flags); } } /* f_x(y,z) */ /* f_x(y,z,n) -> nth derivative */ void fexpr_write_latex_sub1_call2_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t func, x, y, z, order; slong nargs; nargs = fexpr_nargs(expr); if (nargs == 4) { fexpr_view_func(func, expr); fexpr_view_arg(x, expr, 0); fexpr_view_arg(y, expr, 1); fexpr_view_arg(z, expr, 2); fexpr_view_arg(order, expr, 3); _fexpr_write_latex_derivative(out, func, NULL, order, flags); calcium_write(out, "_{"); fexpr_write_latex(out, x, flags | FEXPR_LATEX_SMALL); calcium_write(out, "}"); calcium_write(out, "\\!\\left("); fexpr_write_latex(out, y, flags); calcium_write(out, ", "); fexpr_write_latex(out, z, flags); calcium_write(out, "\\right)"); } else { fexpr_write_latex_subscript_call(out, expr, flags); } } void fexpr_write_latex_infix(calcium_stream_t out, const fexpr_t expr, ulong flags) { fexpr_t func, arg; slong i, nargs; nargs = fexpr_nargs(expr); fexpr_view_func(func, expr); fexpr_view_func(arg, expr); for (i = 0; i < nargs; i++) { fexpr_view_next(arg); if (fexpr_is_builtin_call(arg, FEXPR_Step) && fexpr_nargs(arg) == 2) { fexpr_t x, forexpr, n, a, b, na, na1, nb; fmpz_t t; fexpr_view_arg(x, arg, 0); fexpr_view_arg(forexpr, arg, 1); if (fexpr_nargs(forexpr) == 3) { fexpr_view_arg(n, forexpr, 0); fexpr_view_arg(a, forexpr, 1); fexpr_view_arg(b, forexpr, 2); fexpr_init(na); fexpr_init(na1); fexpr_init(nb); fmpz_init(t); fexpr_replace(na, x, n, a); if (fexpr_is_integer(a)) { fexpr_get_fmpz(t, a); fmpz_add_ui(t, t, 1); fexpr_set_fmpz(na1, t); fexpr_swap(nb, na1); fexpr_replace(na1, x, n, nb); } else { fexpr_set_ui(nb, 1); fexpr_add(na1, a, nb); fexpr_swap(nb, na1); fexpr_replace(na1, x, n, nb); } fexpr_replace(nb, x, n, b); fexpr_write_latex(out, na, flags); calcium_write(out, " "); fexpr_write_latex(out, func, flags); calcium_write(out, " "); fexpr_write_latex(out, na1, flags); calcium_write(out, " "); fexpr_write_latex(out, func, flags); calcium_write(out, " \\ldots "); fexpr_write_latex(out, func, flags); calcium_write(out, " "); fexpr_write_latex(out, nb, flags); fexpr_clear(na); fexpr_clear(na1); fexpr_clear(nb); fmpz_clear(t); } else { fexpr_write_latex(out, arg, flags); } } else { fexpr_write_latex(out, arg, flags); } if (i < nargs - 1) { calcium_write(out, " "); fexpr_write_latex(out, func, flags); calcium_write(out, " "); } } } void fexpr_write_latex(calcium_stream_t out, const fexpr_t expr, ulong flags) { if (fexpr_is_atom(expr)) { if (fexpr_is_integer(expr)) { fexpr_write(out, expr); } else if (fexpr_is_string(expr)) { char * s; /* todo: escape strings */ s = fexpr_get_string(expr); calcium_write(out, "\\text{``"); calcium_write(out, s); calcium_write(out, "''}"); flint_free(s); } else { int subscript; fexpr_write_latex_symbol(&subscript, out, expr, flags); } } else { fexpr_t func; slong i; fexpr_view_func(func, expr); if (fexpr_is_any_builtin_symbol(func)) { i = FEXPR_BUILTIN_ID(func->data[0]); if (fexpr_builtin_table[i].latex_writer != NULL) { (fexpr_builtin_table[i].latex_writer)(out, expr, flags); return; } } fexpr_write_latex_call(out, expr, flags); } } void fexpr_print_latex(const fexpr_t expr, ulong flags) { calcium_stream_t t; calcium_stream_init_file(t, stdout); fexpr_write_latex(t, expr, flags); } char * fexpr_get_str_latex(const fexpr_t expr, ulong flags) { calcium_stream_t t; calcium_stream_init_str(t); fexpr_write_latex(t, expr, flags); return t->s; } flint-3.1.3/src/fexpr_builtin.h000066400000000000000000000301501461254215100164440ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FEXPR_BUILTIN_H #define FEXPR_BUILTIN_H #ifdef FEXPR_BUILTIN_INLINES_C #define FEXPR_BUILTIN_INLINE #else #define FEXPR_BUILTIN_INLINE static inline #endif #ifdef __cplusplus extern "C" { #endif #include "fexpr.h" /* Builtin symbols */ /* Must be listed in alphabetical order with corresponding entry in fexpr_builtin_table (the alphabetical order is just so that we can do binary search on the strings). */ typedef enum { FEXPR_AGM, FEXPR_AGMSequence, FEXPR_Abs, FEXPR_Acos, FEXPR_Acosh, FEXPR_Acot, FEXPR_Acoth, FEXPR_Acsc, FEXPR_Acsch, FEXPR_Add, FEXPR_AiryAi, FEXPR_AiryAiZero, FEXPR_AiryBi, FEXPR_AiryBiZero, FEXPR_AlgebraicNumberSerialized, FEXPR_AlgebraicNumbers, FEXPR_All, FEXPR_AnalyticContinuation, FEXPR_And, FEXPR_AngleBrackets, FEXPR_Approximation, FEXPR_Arg, FEXPR_ArgMax, FEXPR_ArgMaxUnique, FEXPR_ArgMin, FEXPR_ArgMinUnique, FEXPR_Asec, FEXPR_Asech, FEXPR_Asin, FEXPR_Asinh, FEXPR_AsymptoticTo, FEXPR_Atan, FEXPR_Atan2, FEXPR_Atanh, FEXPR_BarnesG, FEXPR_BellNumber, FEXPR_BernoulliB, FEXPR_BernoulliPolynomial, FEXPR_BernsteinEllipse, FEXPR_BesselI, FEXPR_BesselJ, FEXPR_BesselJZero, FEXPR_BesselK, FEXPR_BesselY, FEXPR_BesselYZero, FEXPR_BetaFunction, FEXPR_Binomial, FEXPR_Braces, FEXPR_Brackets, FEXPR_CC, FEXPR_Call, FEXPR_CallIndeterminate, FEXPR_Cardinality, FEXPR_CarlsonHypergeometricR, FEXPR_CarlsonHypergeometricT, FEXPR_CarlsonRC, FEXPR_CarlsonRD, FEXPR_CarlsonRF, FEXPR_CarlsonRG, FEXPR_CarlsonRJ, FEXPR_CartesianPower, FEXPR_CartesianProduct, FEXPR_Case, FEXPR_Cases, FEXPR_CatalanConstant, FEXPR_Ceil, FEXPR_Characteristic, FEXPR_ChebyshevT, FEXPR_ChebyshevU, FEXPR_ClosedComplexDisk, FEXPR_ClosedOpenInterval, FEXPR_Coefficient, FEXPR_Column, FEXPR_ColumnMatrix, FEXPR_CommutativeRings, FEXPR_ComplexBranchDerivative, FEXPR_ComplexDerivative, FEXPR_ComplexInfinities, FEXPR_ComplexLimit, FEXPR_ComplexSignedInfinities, FEXPR_ComplexSingularityClosure, FEXPR_ComplexZeroMultiplicity, FEXPR_Concatenation, FEXPR_CongruentMod, FEXPR_Conjugate, FEXPR_ConreyGenerator, FEXPR_Cos, FEXPR_CosIntegral, FEXPR_Cosh, FEXPR_CoshIntegral, FEXPR_Cot, FEXPR_Coth, FEXPR_CoulombC, FEXPR_CoulombF, FEXPR_CoulombG, FEXPR_CoulombH, FEXPR_CoulombSigma, FEXPR_Csc, FEXPR_Csch, FEXPR_Csgn, FEXPR_CurvePath, FEXPR_Cyclotomic, FEXPR_Decimal, FEXPR_DedekindEta, FEXPR_DedekindEtaEpsilon, FEXPR_DedekindSum, FEXPR_Def, FEXPR_Delta, FEXPR_Delta_, FEXPR_Derivative, FEXPR_Det, FEXPR_DiagonalMatrix, FEXPR_DigammaFunction, FEXPR_DigammaFunctionZero, FEXPR_DirichletCharacter, FEXPR_DirichletGroup, FEXPR_DirichletL, FEXPR_DirichletLZero, FEXPR_DirichletLambda, FEXPR_DiscreteLog, FEXPR_Div, FEXPR_Divides, FEXPR_DivisorProduct, FEXPR_DivisorSigma, FEXPR_DivisorSum, FEXPR_DoubleFactorial, FEXPR_EisensteinE, FEXPR_EisensteinG, FEXPR_Element, FEXPR_Ellipsis, FEXPR_EllipticE, FEXPR_EllipticK, FEXPR_EllipticPi, FEXPR_EllipticRootE, FEXPR_Enclosure, FEXPR_Equal, FEXPR_EqualAndElement, FEXPR_EqualNearestDecimal, FEXPR_EqualQSeriesEllipsis, FEXPR_Equivalent, FEXPR_Erf, FEXPR_Erfc, FEXPR_Erfi, FEXPR_Euler, FEXPR_EulerE, FEXPR_EulerPhi, FEXPR_EulerPolynomial, FEXPR_EulerQSeries, FEXPR_Exists, FEXPR_Exp, FEXPR_ExpIntegralE, FEXPR_ExpIntegralEi, FEXPR_ExtendedRealNumbers, FEXPR_Factorial, FEXPR_FallingFactorial, FEXPR_False, FEXPR_Fibonacci, FEXPR_Fields, FEXPR_FiniteField, FEXPR_Floor, FEXPR_For, FEXPR_FormalLaurentSeries, FEXPR_FormalPowerSeries, FEXPR_FormalPuiseuxSeries, FEXPR_FresnelC, FEXPR_FresnelS, FEXPR_Fun, FEXPR_GCD, FEXPR_Gamma, FEXPR_GaussLegendreWeight, FEXPR_GaussSum, FEXPR_GegenbauerC, FEXPR_GeneralLinearGroup, FEXPR_GeneralizedBernoulliB, FEXPR_GeneralizedRiemannHypothesis, FEXPR_GlaisherConstant, FEXPR_GoldenRatio, FEXPR_Greater, FEXPR_GreaterEqual, FEXPR_GreekGamma, FEXPR_GreekGamma_, FEXPR_GreekPi, FEXPR_GreekPi_, FEXPR_Guess, FEXPR_HankelH1, FEXPR_HankelH2, FEXPR_HarmonicNumber, FEXPR_HermiteH, FEXPR_HilbertClassPolynomial, FEXPR_HilbertMatrix, FEXPR_HurwitzZeta, FEXPR_Hypergeometric0F1, FEXPR_Hypergeometric0F1Regularized, FEXPR_Hypergeometric1F1, FEXPR_Hypergeometric1F1Regularized, FEXPR_Hypergeometric1F2, FEXPR_Hypergeometric1F2Regularized, FEXPR_Hypergeometric2F0, FEXPR_Hypergeometric2F1, FEXPR_Hypergeometric2F1Regularized, FEXPR_Hypergeometric2F2, FEXPR_Hypergeometric2F2Regularized, FEXPR_Hypergeometric3F2, FEXPR_Hypergeometric3F2Regularized, FEXPR_HypergeometricU, FEXPR_HypergeometricUStar, FEXPR_HypergeometricUStarRemainder, FEXPR_IdentityMatrix, FEXPR_Im, FEXPR_Implies, FEXPR_IncompleteBeta, FEXPR_IncompleteBetaRegularized, FEXPR_IncompleteEllipticE, FEXPR_IncompleteEllipticF, FEXPR_IncompleteEllipticPi, FEXPR_IndefiniteIntegralEqual, FEXPR_Infimum, FEXPR_Infinity, FEXPR_IntegersGreaterEqual, FEXPR_IntegersLessEqual, FEXPR_Integral, FEXPR_Intersection, FEXPR_Interval, FEXPR_IsEven, FEXPR_IsHolomorphicOn, FEXPR_IsMeromorphicOn, FEXPR_IsOdd, FEXPR_IsPrime, FEXPR_Item, FEXPR_JacobiP, FEXPR_JacobiSymbol, FEXPR_JacobiTheta, FEXPR_JacobiThetaEpsilon, FEXPR_JacobiThetaPermutation, FEXPR_JacobiThetaQ, FEXPR_KeiperLiLambda, FEXPR_KhinchinConstant, FEXPR_KroneckerDelta, FEXPR_KroneckerSymbol, FEXPR_LCM, FEXPR_LaguerreL, FEXPR_LambertW, FEXPR_Lamda, FEXPR_Lamda_, FEXPR_LandauG, FEXPR_Lattice, FEXPR_LeftLimit, FEXPR_LegendreP, FEXPR_LegendrePolynomialZero, FEXPR_LegendreSymbol, FEXPR_Length, FEXPR_LerchPhi, FEXPR_Less, FEXPR_LessEqual, FEXPR_Limit, FEXPR_LiouvilleLambda, FEXPR_List, FEXPR_Log, FEXPR_LogBarnesG, FEXPR_LogBarnesGRemainder, FEXPR_LogGamma, FEXPR_LogIntegral, FEXPR_Logic, FEXPR_LowerGamma, FEXPR_Matrices, FEXPR_Matrix, FEXPR_Matrix2x2, FEXPR_Max, FEXPR_Maximum, FEXPR_MeromorphicDerivative, FEXPR_MeromorphicLimit, FEXPR_Min, FEXPR_Minimum, FEXPR_Mod, FEXPR_ModularGroupAction, FEXPR_ModularGroupFundamentalDomain, FEXPR_ModularJ, FEXPR_ModularLambda, FEXPR_ModularLambdaFundamentalDomain, FEXPR_MoebiusMu, FEXPR_Mul, FEXPR_MultiZetaValue, FEXPR_NN, FEXPR_Neg, FEXPR_Not, FEXPR_NotElement, FEXPR_NotEqual, FEXPR_NumberE, FEXPR_NumberI, FEXPR_Omega, FEXPR_Omega_, FEXPR_One, FEXPR_OpenClosedInterval, FEXPR_OpenComplexDisk, FEXPR_OpenInterval, FEXPR_OpenRealBall, FEXPR_Or, FEXPR_Otherwise, FEXPR_PSL2Z, FEXPR_Parentheses, FEXPR_PartitionsP, FEXPR_Path, FEXPR_Phi, FEXPR_Phi_, FEXPR_Pi, FEXPR_Pol, FEXPR_Poles, FEXPR_PolyLog, FEXPR_Polynomial, FEXPR_PolynomialDegree, FEXPR_PolynomialFractions, FEXPR_PolynomialRootIndexed, FEXPR_PolynomialRootNearest, FEXPR_Polynomials, FEXPR_Pos, FEXPR_Pow, FEXPR_Prime, FEXPR_PrimePi, FEXPR_PrimeProduct, FEXPR_PrimeSum, FEXPR_Primes, FEXPR_PrimitiveDirichletCharacters, FEXPR_PrimitiveReducedPositiveIntegralBinaryQuadraticForms, FEXPR_Product, FEXPR_ProjectiveComplexNumbers, FEXPR_ProjectiveRealNumbers, FEXPR_Psi, FEXPR_Psi_, FEXPR_QQ, FEXPR_QSeriesCoefficient, FEXPR_QuotientRing, FEXPR_RR, FEXPR_Range, FEXPR_Re, FEXPR_RealAbs, FEXPR_RealAlgebraicNumbers, FEXPR_RealBall, FEXPR_RealDerivative, FEXPR_RealInfinities, FEXPR_RealLimit, FEXPR_RealSignedInfinities, FEXPR_RealSingularityClosure, FEXPR_Repeat, FEXPR_Residue, FEXPR_RiemannHypothesis, FEXPR_RiemannXi, FEXPR_RiemannZeta, FEXPR_RiemannZetaZero, FEXPR_RightLimit, FEXPR_Rings, FEXPR_RisingFactorial, FEXPR_Root, FEXPR_RootOfUnity, FEXPR_Row, FEXPR_RowMatrix, FEXPR_SL2Z, FEXPR_Same, FEXPR_Sec, FEXPR_Sech, FEXPR_SequenceLimit, FEXPR_SequenceLimitInferior, FEXPR_SequenceLimitSuperior, FEXPR_Ser, FEXPR_Set, FEXPR_SetMinus, FEXPR_Sets, FEXPR_ShowExpandedNormalForm, FEXPR_Sigma, FEXPR_Sigma_, FEXPR_Sign, FEXPR_SignExtendedComplexNumbers, FEXPR_Sin, FEXPR_SinIntegral, FEXPR_Sinc, FEXPR_SingularValues, FEXPR_Sinh, FEXPR_SinhIntegral, FEXPR_SloaneA, FEXPR_Solutions, FEXPR_SpecialLinearGroup, FEXPR_Spectrum, FEXPR_SphericalHarmonicY, FEXPR_Sqrt, FEXPR_SquaresR, FEXPR_Step, FEXPR_StieltjesGamma, FEXPR_StirlingCycle, FEXPR_StirlingS1, FEXPR_StirlingS2, FEXPR_StirlingSeriesRemainder, FEXPR_Sub, FEXPR_Subscript, FEXPR_Subset, FEXPR_SubsetEqual, FEXPR_Subsets, FEXPR_Sum, FEXPR_Supremum, FEXPR_SymmetricPolynomial, FEXPR_Tan, FEXPR_Tanh, FEXPR_Theta, FEXPR_Theta_, FEXPR_True, FEXPR_Tuple, FEXPR_Tuples, FEXPR_Undefined, FEXPR_Union, FEXPR_UniqueSolution, FEXPR_UniqueZero, FEXPR_UnitCircle, FEXPR_Unknown, FEXPR_UnsignedInfinity, FEXPR_UpperGamma, FEXPR_UpperHalfPlane, FEXPR_WeierstrassP, FEXPR_WeierstrassSigma, FEXPR_WeierstrassZeta, FEXPR_Where, FEXPR_XGCD, FEXPR_XX, FEXPR_Xi, FEXPR_Xi_, FEXPR_ZZ, FEXPR_Zero, FEXPR_ZeroMatrix, FEXPR_Zeros, FEXPR_alpha, FEXPR_alpha_, FEXPR_beta, FEXPR_beta_, FEXPR_chi, FEXPR_chi_, FEXPR_delta, FEXPR_delta_, FEXPR_ell, FEXPR_ell_, FEXPR_epsilon, FEXPR_epsilon_, FEXPR_eta, FEXPR_eta_, FEXPR_gamma, FEXPR_gamma_, FEXPR_iota, FEXPR_iota_, FEXPR_kappa, FEXPR_kappa_, FEXPR_lamda, FEXPR_lamda_, FEXPR_mu, FEXPR_mu_, FEXPR_nu, FEXPR_nu_, FEXPR_omega, FEXPR_omega_, FEXPR_phi, FEXPR_phi_, FEXPR_pi, FEXPR_pi_, FEXPR_rho, FEXPR_rho_, FEXPR_sigma, FEXPR_sigma_, FEXPR_tau, FEXPR_tau_, FEXPR_theta, FEXPR_theta_, FEXPR_varphi, FEXPR_varphi_, FEXPR_vartheta, FEXPR_vartheta_, FEXPR_xi, FEXPR_xi_, FEXPR_zeta, FEXPR_zeta_, FEXPR_BUILTIN_LENGTH } fexpr_builtin_symbol; typedef void (*_fexpr_latex_writer)(calcium_stream_t, const fexpr_t, ulong); typedef struct { fexpr_builtin_symbol symbol; const char * string; const char * latex_string; _fexpr_latex_writer latex_writer; } fexpr_symbol_info; FLINT_DLL extern const fexpr_symbol_info fexpr_builtin_table[FEXPR_BUILTIN_LENGTH]; #define FEXPR_SYMBOL_Pos (FEXPR_TYPE_SMALL_SYMBOL | (FEXPR_Pos << 16)) #define FEXPR_SYMBOL_Neg (FEXPR_TYPE_SMALL_SYMBOL | (FEXPR_Neg << 16)) #define FEXPR_SYMBOL_Add (FEXPR_TYPE_SMALL_SYMBOL | (FEXPR_Add << 16)) #define FEXPR_SYMBOL_Sub (FEXPR_TYPE_SMALL_SYMBOL | (FEXPR_Sub << 16)) #define FEXPR_SYMBOL_Mul (FEXPR_TYPE_SMALL_SYMBOL | (FEXPR_Mul << 16)) #define FEXPR_SYMBOL_Div (FEXPR_TYPE_SMALL_SYMBOL | (FEXPR_Div << 16)) #define FEXPR_SYMBOL_Pow (FEXPR_TYPE_SMALL_SYMBOL | (FEXPR_Pow << 16)) slong fexpr_builtin_lookup(const char * s); FEXPR_BUILTIN_INLINE const char * fexpr_builtin_name(slong n) { return fexpr_builtin_table[n].string; } FEXPR_BUILTIN_INLINE slong fexpr_builtin_length(void) { return FEXPR_BUILTIN_LENGTH; } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fexpr_builtin/000077500000000000000000000000001461254215100162745ustar00rootroot00000000000000flint-3.1.3/src/fexpr_builtin/inlines.c000066400000000000000000000006721461254215100201060ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FEXPR_BUILTIN_INLINES_C #include "fexpr_builtin.h" flint-3.1.3/src/fexpr_builtin/lookup.c000066400000000000000000000016161461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define strcmp __builtin_strcmp #else # include #endif slong fexpr_builtin_lookup(const char * s) { slong a, mid, b; int cmp; a = 0; b = FEXPR_BUILTIN_LENGTH - 1; while (a <= b) { mid = (a + b) / 2; cmp = strcmp(fexpr_builtin_table[mid].string, s); if (cmp == 0) return mid; else if (cmp > 0) b = mid - 1; else a = mid + 1; } return -1; } flint-3.1.3/src/fexpr_builtin/table.c000066400000000000000000001016611461254215100175340ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" const fexpr_symbol_info fexpr_builtin_table[FEXPR_BUILTIN_LENGTH] = { { FEXPR_AGM, "AGM", "\\operatorname{agm}", NULL, }, { FEXPR_AGMSequence, "AGMSequence", "\\operatorname{agm}", fexpr_write_latex_subscript_call, }, { FEXPR_Abs, "Abs", "", fexpr_write_latex_simple, }, { FEXPR_Acos, "Acos", "\\operatorname{acos}", NULL, }, { FEXPR_Acosh, "Acosh", "\\operatorname{acosh}", NULL, }, { FEXPR_Acot, "Acot", "\\operatorname{acot}", NULL, }, { FEXPR_Acoth, "Acoth", "\\operatorname{acoth}", NULL, }, { FEXPR_Acsc, "Acsc", "\\operatorname{acsc}", NULL, }, { FEXPR_Acsch, "Acsch", "\\operatorname{acsch}", NULL, }, { FEXPR_Add, "Add", "", fexpr_write_latex_add, }, { FEXPR_AiryAi, "AiryAi", "\\operatorname{Ai}", fexpr_write_latex_call1_optional_derivative, }, { FEXPR_AiryAiZero, "AiryAiZero", "a", fexpr_write_latex_subscript, }, { FEXPR_AiryBi, "AiryBi", "\\operatorname{Bi}", fexpr_write_latex_call1_optional_derivative, }, { FEXPR_AiryBiZero, "AiryBiZero", "b", fexpr_write_latex_subscript, }, { FEXPR_AlgebraicNumberSerialized, "AlgebraicNumberSerialized", "", fexpr_write_latex_misc_special, }, { FEXPR_AlgebraicNumbers, "AlgebraicNumbers", "\\overline{\\mathbb{Q}}", NULL, }, { FEXPR_All, "All", "", fexpr_write_latex_logic, }, { FEXPR_AnalyticContinuation, "AnalyticContinuation", "", fexpr_write_latex_misc_special, }, { FEXPR_And, "And", "", fexpr_write_latex_logic, }, { FEXPR_AngleBrackets, "AngleBrackets", "", fexpr_write_latex_simple, }, { FEXPR_Approximation, "Approximation", "", fexpr_write_latex_simple }, { FEXPR_Arg, "Arg", "\\arg", NULL, }, { FEXPR_ArgMax, "ArgMax", "", fexpr_write_latex_setop, }, { FEXPR_ArgMaxUnique, "ArgMaxUnique", "", fexpr_write_latex_setop, }, { FEXPR_ArgMin, "ArgMin", "", fexpr_write_latex_setop, }, { FEXPR_ArgMinUnique, "ArgMinUnique", "", fexpr_write_latex_setop, }, { FEXPR_Asec, "Asec", "\\operatorname{asec}", NULL, }, { FEXPR_Asech, "Asech", "\\operatorname{asech}", NULL, }, { FEXPR_Asin, "Asin", "\\operatorname{asin}", NULL, }, { FEXPR_Asinh, "Asinh", "\\operatorname{asinh}", NULL, }, { FEXPR_AsymptoticTo, "AsymptoticTo", "", fexpr_write_latex_misc_special, }, { FEXPR_Atan, "Atan", "\\operatorname{atan}", NULL, }, { FEXPR_Atan2, "Atan2", "\\operatorname{atan2}", NULL, }, { FEXPR_Atanh, "Atanh", "\\operatorname{atanh}", NULL, }, { FEXPR_BarnesG, "BarnesG", "G", NULL, }, { FEXPR_BellNumber, "BellNumber", "\\operatorname{B}", fexpr_write_latex_subscript, }, { FEXPR_BernoulliB, "BernoulliB", "B", fexpr_write_latex_subscript, }, { FEXPR_BernoulliPolynomial, "BernoulliPolynomial", "B", fexpr_write_latex_subscript_call, }, { FEXPR_BernsteinEllipse, "BernsteinEllipse", "\\mathcal{E}", fexpr_write_latex_subscript, }, { FEXPR_BesselI, "BesselI", "I", fexpr_write_latex_sub1_call1_optional_derivative, }, { FEXPR_BesselJ, "BesselJ", "J", fexpr_write_latex_sub1_call1_optional_derivative, }, { FEXPR_BesselJZero, "BesselJZero", "j", fexpr_write_latex_subscript, }, { FEXPR_BesselK, "BesselK", "K", fexpr_write_latex_sub1_call1_optional_derivative, }, { FEXPR_BesselY, "BesselY", "Y", fexpr_write_latex_sub1_call1_optional_derivative, }, { FEXPR_BesselYZero, "BesselYZero", "y", fexpr_write_latex_subscript, }, { FEXPR_BetaFunction, "BetaFunction", "\\mathrm{B}", NULL, }, { FEXPR_Binomial, "Binomial", "", fexpr_write_latex_simple2, }, { FEXPR_Braces, "Braces", "", fexpr_write_latex_simple, }, { FEXPR_Brackets, "Brackets", "", fexpr_write_latex_simple, }, { FEXPR_CC, "CC", "\\mathbb{C}", NULL, }, { FEXPR_Call, "Call", "", fexpr_write_latex_misc_special, }, { FEXPR_CallIndeterminate, "CallIndeterminate", "", fexpr_write_latex_misc_special, }, { FEXPR_Cardinality, "Cardinality", "", fexpr_write_latex_simple, }, { FEXPR_CarlsonHypergeometricR, "CarlsonHypergeometricR", "R", fexpr_write_latex_subscript_call, }, { FEXPR_CarlsonHypergeometricT, "CarlsonHypergeometricT", "T", fexpr_write_latex_subscript_call, }, { FEXPR_CarlsonRC, "CarlsonRC", "R_C", NULL, }, { FEXPR_CarlsonRD, "CarlsonRD", "R_D", NULL, }, { FEXPR_CarlsonRF, "CarlsonRF", "R_F", NULL, }, { FEXPR_CarlsonRG, "CarlsonRG", "R_G", NULL, }, { FEXPR_CarlsonRJ, "CarlsonRJ", "R_J", NULL, }, { FEXPR_CartesianPower, "CartesianPower", "", fexpr_write_latex_pow, }, { FEXPR_CartesianProduct, "CartesianProduct", "\\times", fexpr_write_latex_infix, }, { FEXPR_Case, "Case", "", NULL, }, { FEXPR_Cases, "Cases", "", fexpr_write_latex_cases, }, { FEXPR_CatalanConstant, "CatalanConstant", "G", NULL, }, { FEXPR_Ceil, "Ceil", "", fexpr_write_latex_simple, }, { FEXPR_Characteristic, "Characteristic", "\\operatorname{char}", NULL, }, { FEXPR_ChebyshevT, "ChebyshevT", "T", fexpr_write_latex_subscript_call, }, { FEXPR_ChebyshevU, "ChebyshevU", "U", fexpr_write_latex_subscript_call, }, { FEXPR_ClosedComplexDisk, "ClosedComplexDisk", "\\overline{D}", NULL, }, { FEXPR_ClosedOpenInterval, "ClosedOpenInterval", "", fexpr_write_latex_simple2_small, }, { FEXPR_Coefficient, "Coefficient", "", fexpr_write_latex_misc_special, }, { FEXPR_Column, "Column", "", NULL, }, { FEXPR_ColumnMatrix, "ColumnMatrix", "", fexpr_write_latex_matrix, }, { FEXPR_CommutativeRings, "CommutativeRings", "", NULL, }, { FEXPR_ComplexBranchDerivative, "ComplexBranchDerivative", "", fexpr_write_latex_derivative, }, { FEXPR_ComplexDerivative, "ComplexDerivative", "", fexpr_write_latex_derivative, }, { FEXPR_ComplexInfinities, "ComplexInfinities", "\\{\\hat{\\infty}, [e^{i \\theta}] \\infty\\}", NULL, }, { FEXPR_ComplexLimit, "ComplexLimit", "", fexpr_write_latex_limit, }, { FEXPR_ComplexSignedInfinities, "ComplexSignedInfinities", "\\{[e^{i \\theta}] \\infty\\}", NULL, }, { FEXPR_ComplexSingularityClosure, "ComplexSingularityClosure", "\\overline{\\mathbb{C}}_{\\text{Sing}}", NULL, }, { FEXPR_ComplexZeroMultiplicity, "ComplexZeroMultiplicity", "", fexpr_write_latex_residue, }, { FEXPR_Concatenation, "Concatenation", " \\,^\\frown ", fexpr_write_latex_infix, }, { FEXPR_CongruentMod, "CongruentMod", "", fexpr_write_latex_logic, }, { FEXPR_Conjugate, "Conjugate", "", fexpr_write_latex_simple, }, { FEXPR_ConreyGenerator, "ConreyGenerator", "g", fexpr_write_latex_subscript, }, { FEXPR_Cos, "Cos", "\\cos", NULL, }, { FEXPR_CosIntegral, "CosIntegral", "\\operatorname{Ci}", NULL, }, { FEXPR_Cosh, "Cosh", "\\cosh", NULL, }, { FEXPR_CoshIntegral, "CoshIntegral", "\\operatorname{Chi}", NULL, }, { FEXPR_Cot, "Cot", "\\cot", NULL, }, { FEXPR_Coth, "Coth", "\\coth", NULL, }, { FEXPR_CoulombC, "CoulombC", "C", fexpr_write_latex_subscript_call, }, { FEXPR_CoulombF, "CoulombF", "", fexpr_write_latex_misc_special, }, { FEXPR_CoulombG, "CoulombG", "", fexpr_write_latex_misc_special, }, { FEXPR_CoulombH, "CoulombH", "", fexpr_write_latex_misc_special, }, { FEXPR_CoulombSigma, "CoulombSigma", "\\sigma", fexpr_write_latex_subscript_call, }, { FEXPR_Csc, "Csc", "\\csc", NULL, }, { FEXPR_Csch, "Csch", "\\operatorname{csch}", NULL, }, { FEXPR_Csgn, "Csgn", "\\operatorname{csgn}", NULL, }, { FEXPR_CurvePath, "CurvePath", "", fexpr_write_latex_misc_special, }, { FEXPR_Cyclotomic, "Cyclotomic", "\\Phi", fexpr_write_latex_subscript_call, }, { FEXPR_Decimal, "Decimal", "", fexpr_write_latex_decimal, }, { FEXPR_DedekindEta, "DedekindEta", "\\eta", NULL, }, { FEXPR_DedekindEtaEpsilon, "DedekindEtaEpsilon", "\\varepsilon", NULL, }, { FEXPR_DedekindSum, "DedekindSum", "s", NULL, }, { FEXPR_Def, "Def", "", NULL, }, { FEXPR_Delta, "Delta", "\\Delta", NULL }, { FEXPR_Delta_, "Delta_", "\\Delta", fexpr_write_latex_subscript }, { FEXPR_Derivative, "Derivative", "", fexpr_write_latex_derivative, }, { FEXPR_Det, "Det", "\\operatorname{det}", NULL, }, { FEXPR_DiagonalMatrix, "DiagonalMatrix", "", fexpr_write_latex_matrix, }, { FEXPR_DigammaFunction, "DigammaFunction", "\\psi", fexpr_write_latex_call1_optional_derivative, }, { FEXPR_DigammaFunctionZero, "DigammaFunctionZero", "x", fexpr_write_latex_subscript, }, { FEXPR_DirichletCharacter, "DirichletCharacter", "", fexpr_write_latex_misc_special, }, { FEXPR_DirichletGroup, "DirichletGroup", "G", fexpr_write_latex_subscript, }, { FEXPR_DirichletL, "DirichletL", "L", NULL, }, { FEXPR_DirichletLZero, "DirichletLZero", "\\rho", fexpr_write_latex_subscript, }, { FEXPR_DirichletLambda, "DirichletLambda", "\\Lambda", NULL, }, { FEXPR_DiscreteLog, "DiscreteLog", "", fexpr_write_latex_misc_special, }, { FEXPR_Div, "Div", "", fexpr_write_latex_div, }, { FEXPR_Divides, "Divides", "\\mid", fexpr_write_latex_infix, }, { FEXPR_DivisorProduct, "DivisorProduct", "", fexpr_write_latex_divsum, }, { FEXPR_DivisorSigma, "DivisorSigma", "\\sigma", fexpr_write_latex_subscript_call, }, { FEXPR_DivisorSum, "DivisorSum", "", fexpr_write_latex_divsum, }, { FEXPR_DoubleFactorial, "DoubleFactorial", "", fexpr_write_latex_factorial, }, { FEXPR_EisensteinE, "EisensteinE", "E", fexpr_write_latex_subscript_call, }, { FEXPR_EisensteinG, "EisensteinG", "G", fexpr_write_latex_subscript_call, }, { FEXPR_Element, "Element", "\\in", fexpr_write_latex_infix, }, { FEXPR_Ellipsis, "Ellipsis", "\\ldots", NULL, }, { FEXPR_EllipticE, "EllipticE", "E", NULL, }, { FEXPR_EllipticK, "EllipticK", "K", NULL, }, { FEXPR_EllipticPi, "EllipticPi", "\\Pi", NULL, }, { FEXPR_EllipticRootE, "EllipticRootE", "e", fexpr_write_latex_subscript_call, }, { FEXPR_Enclosure, "Enclosure", "", fexpr_write_latex_simple }, { FEXPR_Equal, "Equal", "=", fexpr_write_latex_infix, }, { FEXPR_EqualAndElement, "EqualAndElement", "", fexpr_write_latex_misc_special, }, { FEXPR_EqualNearestDecimal, "EqualNearestDecimal", "", fexpr_write_latex_misc_special, }, { FEXPR_EqualQSeriesEllipsis, "EqualQSeriesEllipsis", "", fexpr_write_latex_misc_special, }, { FEXPR_Equivalent, "Equivalent", "", fexpr_write_latex_logic, }, { FEXPR_Erf, "Erf", "\\operatorname{erf}", NULL, }, { FEXPR_Erfc, "Erfc", "\\operatorname{erfc}", NULL, }, { FEXPR_Erfi, "Erfi", "\\operatorname{erfi}", NULL, }, { FEXPR_Euler, "Euler", "\\gamma", NULL, }, { FEXPR_EulerE, "EulerE", "E", fexpr_write_latex_subscript, }, { FEXPR_EulerPhi, "EulerPhi", "\\varphi", NULL, }, { FEXPR_EulerPolynomial, "EulerPolynomial", "E", fexpr_write_latex_subscript_call, }, { FEXPR_EulerQSeries, "EulerQSeries", "\\phi", NULL, }, { FEXPR_Exists, "Exists", "", fexpr_write_latex_logic, }, { FEXPR_Exp, "Exp", "\\exp", fexpr_write_latex_exp, }, { FEXPR_ExpIntegralE, "ExpIntegralE", "E", fexpr_write_latex_subscript_call, }, { FEXPR_ExpIntegralEi, "ExpIntegralEi", "\\operatorname{Ei}", NULL, }, { FEXPR_ExtendedRealNumbers, "ExtendedRealNumbers", "\\overline{\\mathbb{R}}", NULL, }, { FEXPR_Factorial, "Factorial", "", fexpr_write_latex_factorial, }, { FEXPR_FallingFactorial, "FallingFactorial", "", fexpr_write_latex_simple2, }, { FEXPR_False, "False", "\\operatorname{False}", NULL, }, { FEXPR_Fibonacci, "Fibonacci", "F", fexpr_write_latex_subscript, }, { FEXPR_Fields, "Fields", "", NULL, }, { FEXPR_FiniteField, "FiniteField", "", NULL, }, { FEXPR_Floor, "Floor", "", fexpr_write_latex_simple, }, { FEXPR_For, "For", "", NULL, }, { FEXPR_FormalLaurentSeries, "FormalLaurentSeries", "", fexpr_write_latex_alg_structure, }, { FEXPR_FormalPowerSeries, "FormalPowerSeries", "", fexpr_write_latex_alg_structure, }, { FEXPR_FormalPuiseuxSeries, "FormalPuiseuxSeries", "", fexpr_write_latex_alg_structure, }, { FEXPR_FresnelC, "FresnelC", "C", NULL, }, { FEXPR_FresnelS, "FresnelS", "S", NULL, }, { FEXPR_Fun, "Fun", "\\mapsto", fexpr_write_latex_infix, }, { FEXPR_GCD, "GCD", "\\gcd", NULL, }, { FEXPR_Gamma, "Gamma", "\\Gamma", NULL, }, { FEXPR_GaussLegendreWeight, "GaussLegendreWeight", "w", fexpr_write_latex_subscript, }, { FEXPR_GaussSum, "GaussSum", "G", fexpr_write_latex_subscript_call, }, { FEXPR_GegenbauerC, "GegenbauerC", "", NULL, }, { FEXPR_GeneralLinearGroup, "GeneralLinearGroup", "\\operatorname{GL}", fexpr_write_latex_subscript_call, }, { FEXPR_GeneralizedBernoulliB, "GeneralizedBernoulliB", "B", fexpr_write_latex_subscript, }, { FEXPR_GeneralizedRiemannHypothesis, "GeneralizedRiemannHypothesis", "\\operatorname{GRH}", NULL, }, { FEXPR_GlaisherConstant, "GlaisherConstant", "A", NULL, }, { FEXPR_GoldenRatio, "GoldenRatio", "\\varphi", NULL, }, { FEXPR_Greater, "Greater", ">", fexpr_write_latex_infix, }, { FEXPR_GreaterEqual, "GreaterEqual", "\\ge", fexpr_write_latex_infix, }, { FEXPR_GreekGamma, "GreekGamma", "\\Gamma", NULL }, { FEXPR_GreekGamma_, "GreekGamma_", "\\Gamma", fexpr_write_latex_subscript }, { FEXPR_GreekPi, "GreekPi", "\\Pi", NULL }, { FEXPR_GreekPi_, "GreekPi_", "\\Pi", fexpr_write_latex_subscript }, { FEXPR_Guess, "Guess", "", fexpr_write_latex_simple }, { FEXPR_HankelH1, "HankelH1", "H^{(1)}", fexpr_write_latex_subscript_call, }, { FEXPR_HankelH2, "HankelH2", "H^{(2)}", fexpr_write_latex_subscript_call, }, { FEXPR_HarmonicNumber, "HarmonicNumber", "H", fexpr_write_latex_subscript, }, { FEXPR_HermiteH, "HermiteH", "H", fexpr_write_latex_subscript_call, }, { FEXPR_HilbertClassPolynomial, "HilbertClassPolynomial", "H", fexpr_write_latex_subscript_call, }, { FEXPR_HilbertMatrix, "HilbertMatrix", "H", fexpr_write_latex_subscript, }, { FEXPR_HurwitzZeta, "HurwitzZeta", "\\zeta", fexpr_write_latex_call2_optional_derivative, }, { FEXPR_Hypergeometric0F1, "Hypergeometric0F1", "\\,{}_0F_1", NULL, }, { FEXPR_Hypergeometric0F1Regularized, "Hypergeometric0F1Regularized", "\\,{}_0{\\textbf F}_1", NULL, }, { FEXPR_Hypergeometric1F1, "Hypergeometric1F1", "\\,{}_1F_1", NULL, }, { FEXPR_Hypergeometric1F1Regularized, "Hypergeometric1F1Regularized", "\\,{}_1{\\textbf F}_1", NULL, }, { FEXPR_Hypergeometric1F2, "Hypergeometric1F2", "\\,{}_1F_2", NULL, }, { FEXPR_Hypergeometric1F2Regularized, "Hypergeometric1F2Regularized", "\\,{}_1{\\textbf F}_2", NULL, }, { FEXPR_Hypergeometric2F0, "Hypergeometric2F0", "\\,{}_2F_0", NULL, }, { FEXPR_Hypergeometric2F1, "Hypergeometric2F1", "\\,{}_2F_1", NULL, }, { FEXPR_Hypergeometric2F1Regularized, "Hypergeometric2F1Regularized", "\\,{}_2{\\textbf F}_1", NULL, }, { FEXPR_Hypergeometric2F2, "Hypergeometric2F2", "\\,{}_2F_2", NULL, }, { FEXPR_Hypergeometric2F2Regularized, "Hypergeometric2F2Regularized", "\\,{}_2{\\textbf F}_2", NULL, }, { FEXPR_Hypergeometric3F2, "Hypergeometric3F2", "\\,{}_3F_2", NULL, }, { FEXPR_Hypergeometric3F2Regularized, "Hypergeometric3F2Regularized", "\\,{}_3{\\textbf F}_2", NULL, }, { FEXPR_HypergeometricU, "HypergeometricU", "U", NULL, }, { FEXPR_HypergeometricUStar, "HypergeometricUStar", "U^{*}", NULL, }, { FEXPR_HypergeometricUStarRemainder, "HypergeometricUStarRemainder", "R", fexpr_write_latex_subscript_call, }, { FEXPR_IdentityMatrix, "IdentityMatrix", "I", fexpr_write_latex_subscript, }, { FEXPR_Im, "Im", "\\operatorname{Im}", NULL, }, { FEXPR_Implies, "Implies", "", fexpr_write_latex_logic, }, { FEXPR_IncompleteBeta, "IncompleteBeta", "\\mathrm{B}", fexpr_write_latex_subscript_call, }, { FEXPR_IncompleteBetaRegularized, "IncompleteBetaRegularized", "I", fexpr_write_latex_subscript_call, }, { FEXPR_IncompleteEllipticE, "IncompleteEllipticE", "E", NULL, }, { FEXPR_IncompleteEllipticF, "IncompleteEllipticF", "F", NULL, }, { FEXPR_IncompleteEllipticPi, "IncompleteEllipticPi", "\\Pi", NULL, }, { FEXPR_IndefiniteIntegralEqual, "IndefiniteIntegralEqual", "", fexpr_write_latex_misc_special, }, { FEXPR_Infimum, "Infimum", "", fexpr_write_latex_setop, }, { FEXPR_Infinity, "Infinity", "\\infty", NULL, }, { FEXPR_IntegersGreaterEqual, "IntegersGreaterEqual", "", fexpr_write_latex_range, }, { FEXPR_IntegersLessEqual, "IntegersLessEqual", "", fexpr_write_latex_range, }, { FEXPR_Integral, "Integral", "", fexpr_write_latex_integral, }, { FEXPR_Intersection, "Intersection", "\\cap", fexpr_write_latex_infix, }, { FEXPR_Interval, "Interval", "", fexpr_write_latex_simple2_small, }, { FEXPR_IsEven, "IsEven", "", fexpr_write_latex_simple, }, { FEXPR_IsHolomorphicOn, "IsHolomorphicOn", "", fexpr_write_latex_misc_special, }, { FEXPR_IsMeromorphicOn, "IsMeromorphicOn", "", fexpr_write_latex_misc_special, }, { FEXPR_IsOdd, "IsOdd", "", fexpr_write_latex_simple, }, { FEXPR_IsPrime, "IsPrime", "", fexpr_write_latex_simple, }, { FEXPR_Item, "Item", "", fexpr_write_latex_simple2, }, { FEXPR_JacobiP, "JacobiP", "", NULL, }, { FEXPR_JacobiSymbol, "JacobiSymbol", "", fexpr_write_latex_simple2, }, { FEXPR_JacobiTheta, "JacobiTheta", "\\theta", fexpr_write_latex_sub1_call2_optional_derivative, }, { FEXPR_JacobiThetaEpsilon, "JacobiThetaEpsilon", "\\varepsilon", fexpr_write_latex_subscript_call, }, { FEXPR_JacobiThetaPermutation, "JacobiThetaPermutation", "S", fexpr_write_latex_subscript_call, }, { FEXPR_JacobiThetaQ, "JacobiThetaQ", "\\theta", fexpr_write_latex_sub1_call2_optional_derivative, }, { FEXPR_KeiperLiLambda, "KeiperLiLambda", "\\lambda", fexpr_write_latex_subscript, }, { FEXPR_KhinchinConstant, "KhinchinConstant", "K", NULL, }, { FEXPR_KroneckerDelta, "KroneckerDelta", "", fexpr_write_latex_simple2_small, }, { FEXPR_KroneckerSymbol, "KroneckerSymbol", "", fexpr_write_latex_simple2, }, { FEXPR_LCM, "LCM", "\\operatorname{lcm}", NULL, }, { FEXPR_LaguerreL, "LaguerreL", "", NULL, }, { FEXPR_LambertW, "LambertW", "W", fexpr_write_latex_misc_special, }, { FEXPR_Lamda, "Lamda", "\\Lambda", NULL }, { FEXPR_Lamda_, "Lamda_", "\\Lambda", fexpr_write_latex_subscript }, { FEXPR_LandauG, "LandauG", "g", NULL, }, { FEXPR_Lattice, "Lattice", "", fexpr_write_latex_collection }, { FEXPR_LeftLimit, "LeftLimit", "", fexpr_write_latex_limit, }, { FEXPR_LegendreP, "LegendreP", "P", fexpr_write_latex_subscript_call, }, { FEXPR_LegendrePolynomialZero, "LegendrePolynomialZero", "x", fexpr_write_latex_subscript, }, { FEXPR_LegendreSymbol, "LegendreSymbol", "", fexpr_write_latex_simple2, }, { FEXPR_Length, "Length", "", fexpr_write_latex_simple, }, { FEXPR_LerchPhi, "LerchPhi", "\\Phi", NULL, }, { FEXPR_Less, "Less", "<", fexpr_write_latex_infix, }, { FEXPR_LessEqual, "LessEqual", "\\le", fexpr_write_latex_infix, }, { FEXPR_Limit, "Limit", "", fexpr_write_latex_limit, }, { FEXPR_LiouvilleLambda, "LiouvilleLambda", "\\lambda", NULL, }, { FEXPR_List, "List", "", fexpr_write_latex_collection, }, { FEXPR_Log, "Log", "\\log", NULL, }, { FEXPR_LogBarnesG, "LogBarnesG", "\\log G", NULL, }, { FEXPR_LogBarnesGRemainder, "LogBarnesGRemainder", "R", fexpr_write_latex_subscript_call, }, { FEXPR_LogGamma, "LogGamma", "\\log \\Gamma", NULL, }, { FEXPR_LogIntegral, "LogIntegral", "\\operatorname{li}", NULL, }, { FEXPR_Logic, "Logic", "", fexpr_write_latex_logic }, { FEXPR_LowerGamma, "LowerGamma", "\\gamma", NULL, }, { FEXPR_Matrices, "Matrices", "", fexpr_write_latex_misc_special, }, { FEXPR_Matrix, "Matrix", "", fexpr_write_latex_matrix, }, { FEXPR_Matrix2x2, "Matrix2x2", "", fexpr_write_latex_matrix, }, { FEXPR_Max, "Max", "\\max", NULL, }, { FEXPR_Maximum, "Maximum", "", fexpr_write_latex_setop, }, { FEXPR_MeromorphicDerivative, "MeromorphicDerivative", "", fexpr_write_latex_derivative, }, { FEXPR_MeromorphicLimit, "MeromorphicLimit", "", fexpr_write_latex_limit, }, { FEXPR_Min, "Min", "\\min", NULL, }, { FEXPR_Minimum, "Minimum", "", fexpr_write_latex_setop, }, { FEXPR_Mod, "Mod", "\\bmod", fexpr_write_latex_infix, }, { FEXPR_ModularGroupAction, "ModularGroupAction", "\\circ", fexpr_write_latex_infix, }, { FEXPR_ModularGroupFundamentalDomain, "ModularGroupFundamentalDomain", "\\mathcal{F}", NULL, }, { FEXPR_ModularJ, "ModularJ", "j", NULL, }, { FEXPR_ModularLambda, "ModularLambda", "\\lambda", NULL, }, { FEXPR_ModularLambdaFundamentalDomain, "ModularLambdaFundamentalDomain", "\\mathcal{F}_{\\lambda}", NULL, }, { FEXPR_MoebiusMu, "MoebiusMu", "\\mu", NULL, }, { FEXPR_Mul, "Mul", "", fexpr_write_latex_mul, }, { FEXPR_MultiZetaValue, "MultiZetaValue", "\\zeta", NULL, }, { FEXPR_NN, "NN", "\\mathbb{N}", NULL, }, { FEXPR_Neg, "Neg", "", fexpr_write_latex_neg_pos, }, { FEXPR_Not, "Not", "", fexpr_write_latex_logic, }, { FEXPR_NotElement, "NotElement", "\\notin", fexpr_write_latex_infix, }, { FEXPR_NotEqual, "NotEqual", "\\ne", fexpr_write_latex_infix, }, { FEXPR_NumberE, "NumberE", "e", NULL, }, { FEXPR_NumberI, "NumberI", "i", NULL, }, { FEXPR_Omega, "Omega", "\\Omega", NULL }, { FEXPR_Omega_, "Omega_", "\\Omega", fexpr_write_latex_subscript }, { FEXPR_One, "One", "1", fexpr_write_latex_subscript, }, { FEXPR_OpenClosedInterval, "OpenClosedInterval", "", fexpr_write_latex_simple2_small, }, { FEXPR_OpenComplexDisk, "OpenComplexDisk", "D", NULL, }, { FEXPR_OpenInterval, "OpenInterval", "", fexpr_write_latex_simple2_small, }, { FEXPR_OpenRealBall, "OpenRealBall", "", fexpr_write_latex_simple2_small, }, { FEXPR_Or, "Or", "", fexpr_write_latex_logic, }, { FEXPR_Otherwise, "Otherwise", "", NULL, }, { FEXPR_PSL2Z, "PSL2Z", "\\operatorname{PSL}_2(\\mathbb{Z})", NULL, }, { FEXPR_Parentheses, "Parentheses", "", fexpr_write_latex_simple, }, { FEXPR_PartitionsP, "PartitionsP", "p", NULL, }, { FEXPR_Path, "Path", "\\rightsquigarrow", fexpr_write_latex_infix, }, { FEXPR_Phi, "Phi", "\\Phi", NULL }, { FEXPR_Phi_, "Phi_", "\\Phi", fexpr_write_latex_subscript }, { FEXPR_Pi, "Pi", "\\pi", NULL, }, { FEXPR_Pol, "Pol", "", NULL, }, { FEXPR_Poles, "Poles", "", fexpr_write_latex_setop, }, { FEXPR_PolyLog, "PolyLog", "\\operatorname{Li}", fexpr_write_latex_subscript_call, }, { FEXPR_Polynomial, "Polynomial", "", fexpr_write_latex_misc_special, }, { FEXPR_PolynomialDegree, "PolynomialDegree", "\\deg", NULL, }, { FEXPR_PolynomialFractions, "PolynomialFractions", "", fexpr_write_latex_alg_structure, }, { FEXPR_PolynomialRootIndexed, "PolynomialRootIndexed", "", fexpr_write_latex_misc_special, }, { FEXPR_PolynomialRootNearest, "PolynomialRootNearest", "", fexpr_write_latex_misc_special, }, { FEXPR_Polynomials, "Polynomials", "", fexpr_write_latex_alg_structure, }, { FEXPR_Pos, "Pos", "", fexpr_write_latex_neg_pos, }, { FEXPR_Pow, "Pow", "", fexpr_write_latex_pow, }, { FEXPR_Prime, "Prime", "p", fexpr_write_latex_subscript, }, { FEXPR_PrimePi, "PrimePi", "\\pi", NULL, }, { FEXPR_PrimeProduct, "PrimeProduct", "", fexpr_write_latex_divsum, }, { FEXPR_PrimeSum, "PrimeSum", "", fexpr_write_latex_divsum, }, { FEXPR_Primes, "Primes", "\\mathbb{P}", NULL, }, { FEXPR_PrimitiveDirichletCharacters, "PrimitiveDirichletCharacters", "G^{\\text{Primitive}}", fexpr_write_latex_subscript, }, { FEXPR_PrimitiveReducedPositiveIntegralBinaryQuadraticForms, "PrimitiveReducedPositiveIntegralBinaryQuadraticForms", "\\mathcal{Q}^{*}", fexpr_write_latex_subscript_call, }, { FEXPR_Product, "Product", "", fexpr_write_latex_sum_product, }, { FEXPR_ProjectiveComplexNumbers, "ProjectiveComplexNumbers", "\\hat{\\mathbb{C}}_{\\infty}", NULL, }, { FEXPR_ProjectiveRealNumbers, "ProjectiveRealNumbers", "\\hat{\\mathbb{R}}_{\\infty}", NULL, }, { FEXPR_Psi, "Psi", "\\Psi", NULL }, { FEXPR_Psi_, "Psi_", "\\Psi", fexpr_write_latex_subscript }, { FEXPR_QQ, "QQ", "\\mathbb{Q}", NULL, }, { FEXPR_QSeriesCoefficient, "QSeriesCoefficient", "", fexpr_write_latex_misc_special, }, { FEXPR_QuotientRing, "QuotientRing", "", NULL, }, { FEXPR_RR, "RR", "\\mathbb{R}", NULL, }, { FEXPR_Range, "Range", "", fexpr_write_latex_range, }, { FEXPR_Re, "Re", "\\operatorname{Re}", NULL, }, { FEXPR_RealAbs, "RealAbs", "", fexpr_write_latex_simple, }, { FEXPR_RealAlgebraicNumbers, "RealAlgebraicNumbers", "\\overline{\\mathbb{Q}}_{\\mathbb{R}}", NULL, }, { FEXPR_RealBall, "RealBall", "", fexpr_write_latex_simple2_small, }, { FEXPR_RealDerivative, "RealDerivative", "", fexpr_write_latex_derivative, }, { FEXPR_RealInfinities, "RealInfinities", "\\{\\hat{\\infty}, \\pm \\infty\\}", NULL, }, { FEXPR_RealLimit, "RealLimit", "", fexpr_write_latex_limit, }, { FEXPR_RealSignedInfinities, "RealSignedInfinities", "\\{\\pm \\infty\\}", NULL, }, { FEXPR_RealSingularityClosure, "RealSingularityClosure", "\\overline{\\mathbb{R}}_{\\text{Sing}}", NULL, }, { FEXPR_Repeat, "Repeat", "", fexpr_write_latex_misc_special, }, { FEXPR_Residue, "Residue", "", fexpr_write_latex_residue, }, { FEXPR_RiemannHypothesis, "RiemannHypothesis", "\\operatorname{RH}", NULL, }, { FEXPR_RiemannXi, "RiemannXi", "\\xi", NULL, }, { FEXPR_RiemannZeta, "RiemannZeta", "\\zeta", fexpr_write_latex_call1_optional_derivative, }, { FEXPR_RiemannZetaZero, "RiemannZetaZero", "\\rho", fexpr_write_latex_subscript, }, { FEXPR_RightLimit, "RightLimit", "", fexpr_write_latex_limit, }, { FEXPR_Rings, "Rings", "", NULL, }, { FEXPR_RisingFactorial, "RisingFactorial", "", fexpr_write_latex_simple2, }, { FEXPR_Root, "Root", "", NULL, }, { FEXPR_RootOfUnity, "RootOfUnity", "\\zeta", fexpr_write_latex_subscript, }, { FEXPR_Row, "Row", "", NULL, }, { FEXPR_RowMatrix, "RowMatrix", "", fexpr_write_latex_matrix, }, { FEXPR_SL2Z, "SL2Z", "\\operatorname{SL}_2(\\mathbb{Z})", NULL, }, { FEXPR_Same, "Same", "=", fexpr_write_latex_infix, }, { FEXPR_Sec, "Sec", "\\sec", NULL, }, { FEXPR_Sech, "Sech", "\\operatorname{sech}", NULL, }, { FEXPR_SequenceLimit, "SequenceLimit", "", fexpr_write_latex_limit, }, { FEXPR_SequenceLimitInferior, "SequenceLimitInferior", "", fexpr_write_latex_limit, }, { FEXPR_SequenceLimitSuperior, "SequenceLimitSuperior", "", fexpr_write_latex_limit, }, { FEXPR_Ser, "Ser", "", NULL, }, { FEXPR_Set, "Set", "", fexpr_write_latex_collection, }, { FEXPR_SetMinus, "SetMinus", "\\setminus", fexpr_write_latex_infix, }, { FEXPR_Sets, "Sets", "", NULL, }, { FEXPR_ShowExpandedNormalForm, "ShowExpandedNormalForm", "", fexpr_write_latex_show_form, }, { FEXPR_Sigma, "Sigma", "\\Sigma", NULL }, { FEXPR_Sigma_, "Sigma_", "\\Sigma", fexpr_write_latex_subscript }, { FEXPR_Sign, "Sign", "\\operatorname{sgn}", NULL, }, { FEXPR_SignExtendedComplexNumbers, "SignExtendedComplexNumbers", "\\overline{\\mathbb{C}}_{[e^{i \\theta}] \\infty}", NULL, }, { FEXPR_Sin, "Sin", "\\sin", NULL, }, { FEXPR_SinIntegral, "SinIntegral", "\\operatorname{Si}", NULL, }, { FEXPR_Sinc, "Sinc", "\\operatorname{sinc}", NULL, }, { FEXPR_SingularValues, "SingularValues", "\\sigma", NULL, }, { FEXPR_Sinh, "Sinh", "\\sinh", NULL, }, { FEXPR_SinhIntegral, "SinhIntegral", "\\operatorname{Shi}", NULL, }, { FEXPR_SloaneA, "SloaneA", "", fexpr_write_latex_misc_special, }, { FEXPR_Solutions, "Solutions", "", fexpr_write_latex_setop, }, { FEXPR_SpecialLinearGroup, "SpecialLinearGroup", "\\operatorname{SL}", fexpr_write_latex_subscript_call, }, { FEXPR_Spectrum, "Spectrum", "\\operatorname{spec}", NULL, }, { FEXPR_SphericalHarmonicY, "SphericalHarmonicY", "", NULL, }, { FEXPR_Sqrt, "Sqrt", "", fexpr_write_latex_simple, }, { FEXPR_SquaresR, "SquaresR", "r", fexpr_write_latex_subscript_call, }, { FEXPR_Step, "Step", "", fexpr_write_latex_collection, }, { FEXPR_StieltjesGamma, "StieltjesGamma", "\\gamma", fexpr_write_latex_subscript_call, }, { FEXPR_StirlingCycle, "StirlingCycle", "", fexpr_write_latex_simple2, }, { FEXPR_StirlingS1, "StirlingS1", "", fexpr_write_latex_simple2, }, { FEXPR_StirlingS2, "StirlingS2", "", fexpr_write_latex_simple2, }, { FEXPR_StirlingSeriesRemainder, "StirlingSeriesRemainder", "R", fexpr_write_latex_subscript_call, }, { FEXPR_Sub, "Sub", "", fexpr_write_latex_sub, }, { FEXPR_Subscript, "Subscript", "", fexpr_write_latex_simple2, }, { FEXPR_Subset, "Subset", "\\subset", fexpr_write_latex_infix, }, { FEXPR_SubsetEqual, "SubsetEqual", "\\subseteq", fexpr_write_latex_infix, }, { FEXPR_Subsets, "Subsets", "\\mathscr{P}", NULL, }, { FEXPR_Sum, "Sum", "", fexpr_write_latex_sum_product, }, { FEXPR_Supremum, "Supremum", "", fexpr_write_latex_setop, }, { FEXPR_SymmetricPolynomial, "SymmetricPolynomial", "e", fexpr_write_latex_subscript_call, }, { FEXPR_Tan, "Tan", "\\tan", NULL, }, { FEXPR_Tanh, "Tanh", "\\tanh", NULL, }, { FEXPR_Theta, "Theta", "\\Theta", NULL }, { FEXPR_Theta_, "Theta_", "\\Theta", fexpr_write_latex_subscript }, { FEXPR_True, "True", "\\operatorname{True}", NULL, }, { FEXPR_Tuple, "Tuple", "", fexpr_write_latex_collection, }, { FEXPR_Tuples, "Tuples", "", NULL, }, { FEXPR_Undefined, "Undefined", "\\mathfrak{u}", NULL, }, { FEXPR_Union, "Union", "\\cup", fexpr_write_latex_infix, }, { FEXPR_UniqueSolution, "UniqueSolution", "", fexpr_write_latex_setop, }, { FEXPR_UniqueZero, "UniqueZero", "", fexpr_write_latex_setop, }, { FEXPR_UnitCircle, "UnitCircle", "\\mathbb{T}", NULL, }, { FEXPR_Unknown, "Unknown", "\\operatorname{Unknown}", NULL, }, { FEXPR_UnsignedInfinity, "UnsignedInfinity", "\\hat{\\infty}", NULL, }, { FEXPR_UpperGamma, "UpperGamma", "\\Gamma", NULL, }, { FEXPR_UpperHalfPlane, "UpperHalfPlane", "\\mathbb{H}", NULL, }, { FEXPR_WeierstrassP, "WeierstrassP", "\\wp", NULL, }, { FEXPR_WeierstrassSigma, "WeierstrassSigma", "\\sigma", NULL, }, { FEXPR_WeierstrassZeta, "WeierstrassZeta", "\\zeta", NULL, }, { FEXPR_Where, "Where", "", fexpr_write_latex_where, }, { FEXPR_XGCD, "XGCD", "\\operatorname{xgcd}", NULL, }, { FEXPR_XX, "XX", "\\text{x}", fexpr_write_latex_subscript, }, { FEXPR_Xi, "Xi", "\\Xi", NULL }, { FEXPR_Xi_, "Xi_", "\\Xi", fexpr_write_latex_subscript }, { FEXPR_ZZ, "ZZ", "\\mathbb{Z}", NULL, }, { FEXPR_Zero, "Zero", "0", fexpr_write_latex_subscript, }, { FEXPR_ZeroMatrix, "ZeroMatrix", "0", fexpr_write_latex_subscript, }, { FEXPR_Zeros, "Zeros", "", fexpr_write_latex_setop, }, { FEXPR_alpha, "alpha", "\\alpha", NULL }, { FEXPR_alpha_, "alpha_", "\\alpha", fexpr_write_latex_subscript }, { FEXPR_beta, "beta", "\\beta", NULL }, { FEXPR_beta_, "beta_", "\\beta", fexpr_write_latex_subscript }, { FEXPR_chi, "chi", "\\chi", NULL }, { FEXPR_chi_, "chi_", "\\chi", fexpr_write_latex_subscript }, { FEXPR_delta, "delta", "\\delta", NULL }, { FEXPR_delta_, "delta_", "\\delta", fexpr_write_latex_subscript }, { FEXPR_ell, "ell", "\\ell", NULL }, { FEXPR_ell_, "ell_", "\\ell", fexpr_write_latex_subscript }, { FEXPR_epsilon, "epsilon", "\\varepsilon", NULL }, { FEXPR_epsilon_, "epsilon_", "\\varepsilon", fexpr_write_latex_subscript }, { FEXPR_eta, "eta", "\\eta", NULL }, { FEXPR_eta_, "eta_", "\\eta", fexpr_write_latex_subscript }, { FEXPR_gamma, "gamma", "\\gamma", NULL }, { FEXPR_gamma_, "gamma_", "\\gamma", fexpr_write_latex_subscript }, { FEXPR_iota, "iota", "\\iota", NULL }, { FEXPR_iota_, "iota_", "\\iota", fexpr_write_latex_subscript }, { FEXPR_kappa, "kappa", "\\kappa", NULL }, { FEXPR_kappa_, "kappa_", "\\kappa", fexpr_write_latex_subscript }, { FEXPR_lamda, "lamda", "\\lambda", NULL }, { FEXPR_lamda_, "lamda_", "\\lambda", fexpr_write_latex_subscript }, { FEXPR_mu, "mu", "\\mu", NULL }, { FEXPR_mu_, "mu_", "\\mu", fexpr_write_latex_subscript }, { FEXPR_nu, "nu", "\\nu", NULL }, { FEXPR_nu_, "nu_", "\\nu", fexpr_write_latex_subscript }, { FEXPR_omega, "omega", "\\omega", NULL }, { FEXPR_omega_, "omega_", "\\omega", fexpr_write_latex_subscript }, { FEXPR_phi, "phi", "\\phi", NULL }, { FEXPR_phi_, "phi_", "\\phi", fexpr_write_latex_subscript }, { FEXPR_pi, "pi", "\\pi", NULL }, { FEXPR_pi_, "pi_", "\\pi", fexpr_write_latex_subscript }, { FEXPR_rho, "rho", "\\rho", NULL }, { FEXPR_rho_, "rho_", "\\rho", fexpr_write_latex_subscript }, { FEXPR_sigma, "sigma", "\\sigma", NULL }, { FEXPR_sigma_, "sigma_", "\\sigma", fexpr_write_latex_subscript }, { FEXPR_tau, "tau", "\\tau", NULL }, { FEXPR_tau_, "tau_", "\\tau", fexpr_write_latex_subscript }, { FEXPR_theta, "theta", "\\theta", NULL }, { FEXPR_theta_, "theta_", "\\theta", fexpr_write_latex_subscript }, { FEXPR_varphi, "varphi", "\\varphi", NULL }, { FEXPR_varphi_, "varphi_", "\\varphi", fexpr_write_latex_subscript }, { FEXPR_vartheta, "vartheta", "\\vartheta", NULL }, { FEXPR_vartheta_, "vartheta_", "\\vartheta", fexpr_write_latex_subscript }, { FEXPR_xi, "xi", "\\xi", NULL }, { FEXPR_xi_, "xi_", "\\xi", fexpr_write_latex_subscript }, { FEXPR_zeta, "zeta", "\\zeta", NULL }, { FEXPR_zeta_, "zeta_", "\\zeta", fexpr_write_latex_subscript }, }; flint-3.1.3/src/fft.h000066400000000000000000000226671461254215100143670ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FFT_H #define FFT_H #ifdef FFT_INLINES_C #define FFT_INLINE #else #define FFT_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* defined in mpn_extras.h */ mp_limb_t flint_mpn_sumdiff_n(mp_ptr s, mp_ptr d, mp_srcptr x, mp_srcptr y, mp_size_t n); #define fft_sumdiff(t, u, r, s, n) \ (n == 0 ? 0 : flint_mpn_sumdiff_n(t, u, r, s, n)) #define SWAP_PTRS(xx, yy) FLINT_SWAP(mp_ptr, xx, yy) /* used for generating random values mod p in test code */ /* NOTE: One needs to include mpn_extras.h for this macro. */ #define random_fermat(nn, state, limbs) \ do { \ if (n_randint(state, 10) == 0) { \ flint_mpn_zero(nn, limbs); \ nn[limbs] = 1; \ } else { \ if (n_randint(state, 2) == 0) \ flint_mpn_rrandom(nn, state->gmp_state, limbs); \ else \ flint_mpn_urandomb(nn, state->gmp_state, limbs*FLINT_BITS); \ nn[limbs] = n_randint(state, 1024); \ } \ if (n_randint(state, 2)) \ nn[limbs] = -nn[limbs]; \ } while (0) FFT_INLINE void mpn_addmod_2expp1_1(mp_limb_t * r, mp_size_t limbs, mp_limb_signed_t c) { mp_limb_t sum = r[0] + c; /* check if adding c would cause a carry to propagate */ if ((mp_limb_signed_t)(sum ^ r[0]) >= 0) r[0] = sum; else { if (c >= 0) mpn_add_1(r, r, limbs + 1, c); else mpn_sub_1(r, r, limbs + 1, -c); } } void fft_combine_limbs(mp_limb_t * res, mp_limb_t ** poly, slong length, mp_size_t coeff_limbs, mp_size_t output_limbs, mp_size_t total_limbs); void fft_combine_bits(mp_limb_t * res, mp_limb_t ** poly, slong length, flint_bitcnt_t bits, mp_size_t output_limbs, mp_size_t total_limbs); mp_size_t fft_split_limbs(mp_limb_t ** poly, mp_srcptr limbs, mp_size_t total_limbs, mp_size_t coeff_limbs, mp_size_t output_limbs); mp_size_t fft_split_bits(mp_limb_t ** poly, mp_srcptr limbs, mp_size_t total_limbs, flint_bitcnt_t bits, mp_size_t output_limbs); void fermat_to_mpz(mpz_t m, mp_limb_t * i, mp_size_t limbs); void mpn_normmod_2expp1(mp_limb_t * t, mp_size_t limbs); void butterfly_lshB(mp_limb_t * t, mp_limb_t * u, mp_limb_t * i1, mp_limb_t * i2, mp_size_t limbs, mp_size_t x, mp_size_t y); void butterfly_rshB(mp_limb_t * t, mp_limb_t * u, mp_limb_t * i1, mp_limb_t * i2, mp_size_t limbs, mp_size_t x, mp_size_t y); void mpn_negmod_2expp1(mp_limb_t* z, const mp_limb_t* a, mp_size_t limbs); void mpn_mul_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d); void mpn_div_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d); void fft_adjust(mp_limb_t * r, mp_limb_t * i1, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w); void fft_butterfly(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w); void ifft_butterfly(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w); void fft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2); void fft_truncate1(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc); void fft_truncate(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc); void ifft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2); void ifft_truncate1(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc); void ifft_truncate(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc); void fft_butterfly_sqrt2(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp); void ifft_butterfly_sqrt2(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp); void fft_adjust_sqrt2(mp_limb_t * r, mp_limb_t * i1, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp); void fft_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t trunc); void ifft_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t trunc); void mul_truncate_sqrt2(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2, flint_bitcnt_t depth, flint_bitcnt_t w); void fft_butterfly_twiddle(mp_limb_t * u, mp_limb_t * v, mp_limb_t * s, mp_limb_t * t, mp_size_t limbs, flint_bitcnt_t b1, flint_bitcnt_t b2); void ifft_butterfly_twiddle(mp_limb_t * u, mp_limb_t * v, mp_limb_t * s, mp_limb_t * t, mp_size_t limbs, flint_bitcnt_t b1, flint_bitcnt_t b2); void fft_radix2_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs); void ifft_radix2_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs); void fft_truncate1_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs, mp_size_t trunc); void ifft_truncate1_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs, mp_size_t trunc); void fft_mfa_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc); void ifft_mfa_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc); void mul_mfa_truncate_sqrt2(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2, flint_bitcnt_t depth, flint_bitcnt_t w); void fft_mfa_truncate_sqrt2_outer(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc); void fft_mfa_truncate_sqrt2_inner(mp_limb_t ** ii, mp_limb_t ** jj, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc, mp_limb_t ** tt); void ifft_mfa_truncate_sqrt2_outer(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc); void fft_negacyclic(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp); void ifft_negacyclic(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp); void fft_naive_convolution_1(mp_limb_t * r, mp_limb_t * ii, mp_limb_t * jj, mp_size_t m); void _fft_mulmod_2expp1(mp_limb_t * r1, mp_limb_t * i1, mp_limb_t * i2, mp_size_t r_limbs, flint_bitcnt_t depth, flint_bitcnt_t w); slong fft_adjust_limbs(mp_size_t limbs); void fft_mulmod_2expp1(mp_limb_t * r, mp_limb_t * i1, mp_limb_t * i2, mp_size_t n, mp_size_t w, mp_limb_t * tt); void flint_mpn_mul_fft_main(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2); void fft_convolution_basic(mp_limb_t ** ii, mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1, mp_limb_t ** tt); void fft_convolution(mp_limb_t ** ii, mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1, mp_limb_t ** tt); /***** FFT Precaching *****/ void fft_precache(mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1); void fft_convolution_precache(mp_limb_t ** ii, mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1, mp_limb_t ** tt); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fft/000077500000000000000000000000001461254215100142015ustar00rootroot00000000000000flint-3.1.3/src/fft/README000066400000000000000000000312761461254215100150720ustar00rootroot00000000000000FFT Integer Multiplication code =============================== License: BSD NOTE: The following note is no longer applicable. (Note the FLINT library of which this is a part is overall LGPL v2.1+ and the latest version of GMP on which this currently depends is LGPL v3+. But the files in this implementation of the FFT are individually licensed BSD.) Introduction ------------ Many bignum libraries and programming languages do not contain fast code for multiplication of huge integers. It is important to have this when computing millions of digits of Pi, multiplying polynomials using Kronecker segmentation (or the Schoenhage-Strassen technique using an FFT directly) and a variety of other problems. Here we introduce fast FFT code for multiplication of huge integers. Currently the code depends on GMP, however, any sufficiently well developed bignum library should have equivalent primitives for bignums. (There is also a dependence on the flint function n_revbin, which is found in the ulong_extras directory of flint -- I hereby license it under the BSD license as per the remainder of the FFT implementation.) To use the FFT for multiplying large integers, one needs to use the function flint_mpn_mul_fft_main as documented in the doc directory. This relies on tuning values supplied in fft_tuning.h in the top level source directory. Features: -------- * Cache friendly up to huge transforms (integers of billions of bits) * Truncated -- no uglytwit performance jumps at power of 2 lengths and no problem with unbalanced multiplications * Extremely fast * Easy to tune * Truncated FFT/IFFT functions can be used for polynomial multiplication Performance Data ---------------- Here are timings for multiplication of two integers of the given number of bits, comparing MPIR 2.4.0, this code and GMP 5.0.2 respectively. The timings are for varying numbers of iterations as specified. The timings were done on a 2.2GHz AMD K10-2 Mangy Cours machine. The tuning values used are specified in the final two columns. The first part of the table uses mul_truncate_sqrt2, the second half uses mul_mfa_truncate_sqrt2. bits iters mpir this gmp n w 195840 1000 1.149s 1.105s 0.997s 7 16 261120 1000 1.483s 1.415s 1.396s 7 16 391296 100 0.261s 0.248s 0.282s 8 8 521728 100 0.344s 0.315s 0.411s 8 8 782592 100 0.577s 0.539s 0.628s 9 4 1043456 100 0.706s 0.688s 0.848s 9 4 1569024 100 1.229s 1.153s 1.317s 9 8 2092032 100 1.543s 1.440s 2.765s 9 8 3127296 10 0.283s 0.266s 0.408s 11 1 4169728 10 0.357s 0.335s 0.543s 11 1 6273024 10 0.621s 0.597s 0.843s 11 2 8364032 10 0.831s 0.742s 1.156s 11 2 12539904 10 1.441s 1.394s 1.798s 12 1 16719872 1 0.230s 0.205s 0.288s 12 1 25122816 1 0.379s 0.336s 0.434s 12 2 33497088 1 0.524s 0.428s 0.646s 12 2 50245632 1 0.833s 0.693s 1.035s 13 1 66994176 1 1.596s 0.896s 1.358s 13 1 100577280 1 1.906s 1.552s 2.177s 13 2 134103040 1 2.784s 2.076s 2.984s 13 2 201129984 1 3.971s 3.158s 4.536s 14 1 268173312 1 5.146s 4.137s 5.781s 14 1 402456576 1 7.548s 6.443s 9.867s 14 2 536608768 1 9.841s 8.365s 12.71s 14 2 804913152 1 15.48s 13.29s 20.06s 15 1 1073217536 1 21.17s 17.16s 27.19s 15 1 1610219520 1 31.64s 28.60s 43.37s 15 2 2146959360 1 43.25s 37.02s 57.66s 15 2 3220340736 1 70.14s 58.09s 92.94s 16 1 4293787648 1 96.00s 74.26s 146.1s 16 1 6441566208 1 150.2s 131.1s 217.5s 16 2 8588754944 1 208.4s 175.0s 312.8s 16 2 12883132416 1 327.4s 278.6s 447.7s 17 1 17177509888 1 485.0s 360.ss 614.2s 17 1 Additional tuning ----------------- Technically one should tune the values that appear in fft_tuning.h. The mulmod_2expp1 tuning array indices correspond to (n, w) pairs starting at n = 12, w = 1. The values in the array should be nonnegative and less than 6. The length of the array is given by FFT_N_NUM. The cutoff FFT_MULMOD_2EXPP1_CUTOFF should also be tuned. It must be bigger than 128. The function that these values tunes is in the file mulmod_2expp1.c. See the corresponding test function for an example of how to call it. The fft tuning array indices correspond to (n, w) pairs starting at n = 6, w = 1. The values in the array should be nonnegative and less than 6. The function that is tuned is in the file mpn_mul_fft_main.c. See the corresponding test function for an example of how to call it. The function implementation itself is the best reference for which inputs will use which table entries. Strategy -------- Let's suppose we wish to compute a convolution of length 2n where n is a power of 2. We do this with a standard Fermat transform with coefficients mod p = 2^wn + 1. Note 2^w is a 2n-th root of unity. We assume wn is divisible by GMP_LIMB_BITS (either 32 or 64). In practice n is always divisible by this constant. Write l = wn/GMP_LIMB_BITS. Each coeff is stored in a block of l+1 limbs in twos complement form. We accumulate carries in the top limb meaning reduction mod p does not need to be done after an addition or subtraction. Coefficients are also accessed via one level of indirection so that coefficients can be swapped by swapping pointers. A couple of extra temporary coefficients are allocated for operations which cannot be done entirely in-place. 1. Efficient butterflies The FFT butterfly step is: [a{i}, b{i}] => [a{i}+b{i}, z^i*(a{i}-b{i})] We use sumdiff to simultaneously perform the addition and subtraction. The multiplication by z^i is a shift by iw bits which we decompose into a shift by b bits and x limbs. The output is written in a location with an offset of x limbs. To handle the wraparound we split the operation into two parts. Finally we shift by the remaining b bits. An additional negation needs to occur when i >= n as nw = -1 mod p. The IFFT butterfly is: [a{i}, b{i}] => [a{i}+z^-i*b{i}, a{i}-z^-i*b{i}] We first decompose iw into b bits and x limbs. We perform the bit shift first, in-place. Then we use sumdiff, this time reading at an offset of x limbs, splitting the operation into two parts as before. 2. Cache locality We use the Matrix Fourier Algorithm. To perform an FFT of length m = RC we: * Split the coefficients into R rows of C columns * Perform a length R FFT on each column, i.e. with an input stride of C * Multiply each coefficient by z^{r*c} where z = exp(2*Pi*I/m), note z corresponds to a shift of w bits * Perform a length C FFT on each row, i.e. with an input stride of 1 * Transpose the matrix of coefficients To perform an IFFT we complete the steps in reverse, using IFFT's instead of FFT's. We set R, C to be both around sqrt(m) to minimise the maximum size of FFT which is in cache at any one time. When the FFT is followed by the IFFT as in the convolution we do not perform the transposes of the matrix coefficients as they cancel each other out. We do not perform the twiddles by z^{rc} in a separate pass over the data. We combine them with the length R FFT's and IFFT's. They are combined with the butterflies at the very bottom level of the FFT's and IFFT's. They essentially cost nothing as they just increase the bit shifts already being performed. The algorithm expects the FFT's to output their coefficients in reverse binary order, thus we have to revbin the coefficient order after the column FFTs and before the column IFFTs. 3. Truncation When performing a convolution where we know that many of the output coefficients will be zero (this happens when multiplying integers that are not of an optimal split-into-a-nice-power-of-two length) we can use Van der Hoeven's truncated FFT. There are two cases: a) less than or equal to half of the FFT output coeffs are non-zero and b) more than half the coefficients are non-zero: a) A 0 0 0 b) A A A 0 In the first case, the first layer of the FFT would do nothing. As we only care about the left half, we recurse on only the left half A 0, ignoring the remaining zeros. In the second case we compute the first layer of the FFT. We then do an ordinary FFT on the left half and recurse with a truncated FFT on the right half. Of course we need to be careful in that the first layer of the FFT will have replaced our zeroes with non-zero coefficients, so we don't recurse to the above two cases. We start instead with an FFT with non-zero coefficients (labelled B). A B B B or A A A B But the cases can be dealt with in a similar way to the cases where there are zeros. The saving comes in that we repeatedly ignore coefficients on the right hand side when they are all past the truncation point. The IFFT is slightly more involved. We know that we are going to *end up with* zeroes on the right hand side. We start with the results of the pointwise mults, though we do not perform all the pointwise mults. If we are going to end up with c zeroes, we do not perform the last c pointwise mults. So we want our IFFT to get to A A A 0 starting from P P P ? Again there are two cases, depending on how many zeros we will end up with: a) A 0 0 0 b) A A A 0 In case (a) , by working backwards from what we know we will get, the next to last level must be A/2 0 (A/2)~ 0 where ~ is the opposite of the twiddle that will be applied by the IFFT butterfly. But I can compute the LHS, A/2 0, simply by recursing on the truncated IFFT. Then it is just a matter of multiplying by 2 to get A 0 which is what I was after. In case (b) an ordinary IFFT can compute the left hand of the penultimate layer, as we have all the necessary pointwise mults for that. A A A 0 B B ? ? The right hand side we compute by recursing on the truncated IFFT. But we don't know what the final question mark is. To get it we have to reverse the steps of the IFFT to find it. As we have the second B we can compute the second A simply by performing some IFFT butterflies. Now we can compute the second ? by reversing the IFFT butterflies. So we are left with: A A' A 0' B' B' ? C' where I wrote a dash on the coefficients we actually now know. Now we can recurse using the truncated IFFT on the right hand side. Although the coefficients C' are not zero, the principles are the same and we split into two cases as above. This allows us to get the question mark, yielding: A A' A 0' B' B' C' C' and clearly now we can compute the A's we don't know from the known coefficients. To combine the MFA with truncation we simply truncate at one level of the MFA, i.e. set the truncation length to be a multiple of the length of the inner FFT's. When we are at the lower levels computing row FFT's we don't compute those which lie past the truncation point. We need to take care to perform the right pointwise mults because we do not transpose the matrix or output coefficients in revbin order. 4. Negacyclic convolution The pointwise multiplications mod p are sometimes large enough to make use of an FFT. For this purpose we use a negacyclic convolution which naturally performs integer multiplication mod p. If we do this naively we break up into coefficients whose sizes are multiples of half the negacyclic FFT lengths. This becomes inefficient. In order to get around this we must perform two multiplications, one via a negacyclic FFT with big coefficients and one naively with very small coefficients and CRT them together. This gives more flexibility in the size of coefficients we use in the negacyclic FFT allowing the large pointwise multication mod p to be done efficiently (not implemented yet). 5. Sqrt 2 trick In the ring Z/pZ where p = 2^S + 1 the value 2^(2S/4)-2^(S/4) is a square root of 2. This allows us to perform a convolution of twice the length without twice the cost. To perform the operations we need to be able to perform twiddles by powers of sqrt2. These are decomposed and the operations are combined as much as possible with the multiplications by powers of 2. Acknowledgements ---------------- "Matters Computational: ideas, algorithms and source code", by Jorg Arndt, see https://www.jjj.de/fxt/fxtbook.pdf "Primes numbers: a computational perspective", by Richard Crandall and Carl Pomerance, 2nd ed., 2005, Springer. "A GMP-based implementation of Schonhage-Strassen's Large Integer Multiplication Algorithm" by Pierrick Gaudry, Alexander Kruppa and Paul Zimmermann, ISAAC 2007 proceedings, pp 167-174. See http://www.loria.fr/~gaudry/publis/issac07.pdf "Multidigit multiplication for mathematicians" by Dan Bernstein (to appear). see https://cr.yp.to/papers/m3.pdf "A cache-friendly truncated FFT" by David Harvey, Theor. Comput. Sci. 410 (2009), 2649.2658. See http://web.maths.unsw.edu.au/~davidharvey/papers/cache-trunc-fft/ "The truncated Fourier transform and applications" by Joris van der Hoeven, J. Gutierrez, editor, Proc. ISSAC 2004, pages 290.296, Univ. of Cantabria, Santander, Spain, July 4.7 2004. flint-3.1.3/src/fft/adjust.c000066400000000000000000000017121461254215100156400ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void fft_adjust(mp_limb_t * r, mp_limb_t * i1, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w) { flint_bitcnt_t b1; mp_limb_t cy; mp_size_t x; b1 = i*w; x = b1/FLINT_BITS; b1 = b1%FLINT_BITS; if (x) { flint_mpn_copyi(r + x, i1, limbs - x); r[limbs] = 0; cy = mpn_neg(r, i1 + limbs - x, x); mpn_addmod_2expp1_1(r + x, limbs - x, -i1[limbs]); mpn_sub_1(r + x, r + x, limbs - x + 1, cy); mpn_mul_2expmod_2expp1(r, r, limbs, b1); } else mpn_mul_2expmod_2expp1(r, i1, limbs, b1); } flint-3.1.3/src/fft/adjust_sqrt2.c000066400000000000000000000033441461254215100167760ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void fft_adjust_sqrt2(mp_limb_t * r, mp_limb_t * i1, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp) { flint_bitcnt_t wn = limbs*FLINT_BITS; mp_limb_t cy; mp_size_t j = i/2, k = w/2; mp_size_t y; flint_bitcnt_t b1; int negate = 0; b1 = j + wn/4 + i*k; if (b1 >= wn) { negate = 1; b1 -= wn; } y = b1/FLINT_BITS; b1 = b1%FLINT_BITS; /* multiply by 2^{j + wn/4 + i*k} */ if (y) { flint_mpn_copyi(temp + y, i1, limbs - y); cy = mpn_neg(temp, i1 + limbs - y, y); temp[limbs] = 0; mpn_addmod_2expp1_1(temp + y, limbs - y, -i1[limbs]); mpn_sub_1(temp + y, temp + y, limbs - y + 1, cy); mpn_mul_2expmod_2expp1(r, temp, limbs, b1); } else mpn_mul_2expmod_2expp1(r, i1, limbs, b1); /* multiply by 2^{wn/2} */ y = limbs/2; cy = 0; flint_mpn_copyi(temp + y, r, limbs - y); temp[limbs] = 0; if (y) cy = mpn_neg(temp, r + limbs - y, y); mpn_addmod_2expp1_1(temp + y, limbs - y, -r[limbs]); mpn_sub_1(temp + y, temp + y, limbs - y + 1, cy); /* shift by an additional half limb (rare) */ if (limbs & 1) mpn_mul_2expmod_2expp1(temp, temp, limbs, FLINT_BITS/2); /* subtract */ if (negate) mpn_sub_n(r, r, temp, limbs + 1); else mpn_sub_n(r, temp, r, limbs + 1); } flint-3.1.3/src/fft/butterfly_lshB.c000066400000000000000000000067471461254215100173530ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void butterfly_lshB(mp_limb_t * t, mp_limb_t * u, mp_limb_t * i1, mp_limb_t * i2, mp_size_t limbs, mp_size_t x, mp_size_t y) { mp_limb_t cy, cy1, cy2; if (x == 0) { if (y == 0) cy = fft_sumdiff(t + x, u + y, i1, i2, limbs + 1); else { cy = fft_sumdiff(t, u + y, i1, i2, limbs - y); u[limbs] = -(cy&1); cy1 = cy>>1; cy = fft_sumdiff(t + limbs - y, u, i2 + limbs - y, i1 + limbs - y, y); t[limbs] = cy>>1; mpn_add_1(t + limbs - y, t + limbs - y, y + 1, cy1); cy1 = -(cy&1) + (i2[limbs] - i1[limbs]); mpn_addmod_2expp1_1(u + y, limbs - y, cy1); cy1 = -(i1[limbs] + i2[limbs]); mpn_addmod_2expp1_1(t, limbs, cy1); } } else if (y == 0) { cy = fft_sumdiff(t + x, u, i1, i2, limbs - x); t[limbs] = cy>>1; cy1 = cy&1; cy = fft_sumdiff(t, u + limbs - x, i1 + limbs - x, i2 + limbs - x, x); cy2 = mpn_neg(t, t, x); u[limbs] = -(cy&1); mpn_sub_1(u + limbs - x, u + limbs - x, x + 1, cy1); cy1 = -(cy>>1) - cy2; cy1 -= (i1[limbs] + i2[limbs]); mpn_addmod_2expp1_1(t + x, limbs - x, cy1); cy1 = (i2[limbs] - i1[limbs]); mpn_addmod_2expp1_1(u, limbs, cy1); } else if (x > y) { cy = fft_sumdiff(t + x, u + y, i1, i2, limbs - x); t[limbs] = cy>>1; cy1 = cy&1; cy = fft_sumdiff(t, u + y + limbs - x, i1 + limbs - x, i2 + limbs - x, x - y); cy2 = mpn_neg(t, t, x - y); u[limbs] = -(cy&1); mpn_sub_1(u + y + limbs - x, u + y + limbs - x, x - y + 1, cy1); cy1 = (cy>>1) + cy2; cy = fft_sumdiff(t + x - y, u, i2 + limbs - y, i1 + limbs - y, y); cy2 = mpn_neg(t + x - y, t + x - y, y); cy1 = -(cy>>1) - mpn_sub_1(t + x - y, t + x - y, y, cy1) - cy2; cy1 -= (i1[limbs] + i2[limbs]); mpn_addmod_2expp1_1(t + x, limbs - x, cy1); cy1 = -(cy&1) + (i2[limbs] - i1[limbs]); mpn_addmod_2expp1_1(u + y, limbs - y, cy1); } else if (x < y) { cy = fft_sumdiff(t + x, u + y, i1, i2, limbs - y); u[limbs] = -(cy&1); cy1 = cy>>1; cy = fft_sumdiff(t + x + limbs - y, u, i2 + limbs - y, i1 + limbs - y, y - x); t[limbs] = cy>>1; mpn_add_1(t + x + limbs - y, t + x + limbs - y, y - x + 1, cy1); cy1 = cy&1; cy = fft_sumdiff(t, u + y - x, i2 + limbs - x, i1 + limbs - x, x); cy1 = -(cy&1) - mpn_sub_1(u + y - x, u + y - x, x, cy1); cy1 += (i2[limbs] - i1[limbs]); mpn_addmod_2expp1_1(u + y, limbs - y, cy1); cy2 = mpn_neg(t, t, x); cy1 = -(cy>>1) - (i1[limbs] + i2[limbs]) - cy2; mpn_addmod_2expp1_1(t + x, limbs - x, cy1); } else /* x == y */ { cy = fft_sumdiff(t + x, u + x, i1, i2, limbs - x); t[limbs] = cy>>1; u[limbs] = -(cy&1); cy = fft_sumdiff(t, u, i2 + limbs - x, i1 + limbs - x, x); cy2 = mpn_neg(t, t, x); cy1 = -(cy>>1) - (i1[limbs] + i2[limbs]) - cy2; mpn_addmod_2expp1_1(t + x, limbs - x, cy1); cy1 = -(cy&1) + i2[limbs] - i1[limbs]; mpn_addmod_2expp1_1(u + x, limbs - x, cy1); } } flint-3.1.3/src/fft/butterfly_rshB.c000066400000000000000000000064741461254215100173560ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void butterfly_rshB(mp_limb_t * t, mp_limb_t * u, mp_limb_t * i1, mp_limb_t * i2, mp_size_t limbs, mp_size_t x, mp_size_t y) { mp_limb_t cy, cy1, cy2, cy3; if (x == 0) { if (y == 0) { cy = fft_sumdiff(t, u, i1, i2, limbs + 1); } else /* y != 0 */ { cy = fft_sumdiff(t, u, i1, i2 + y, limbs - y); cy1 = (cy>>1); cy2 = -(cy&1); cy = fft_sumdiff(u + limbs - y, t + limbs - y, i1 + limbs - y, i2, y); u[limbs] = (cy>>1) + i1[limbs]; t[limbs] = i1[limbs] - (cy&1); mpn_addmod_2expp1_1(t + limbs - y, y, cy1 + i2[limbs]); mpn_addmod_2expp1_1(u + limbs - y, y, cy2 - i2[limbs]); } } else if (y == 0) /* x != 0 */ { cy = fft_sumdiff(t, u, i1 + x, i2, limbs - x); cy1 = (cy>>1); cy2 = -(cy&1); cy3 = mpn_neg(i1, i1, x); cy = fft_sumdiff(t + limbs - x, u + limbs - x, i1, i2 + limbs - x, x); u[limbs] = -cy3 - (cy&1) - i2[limbs]; t[limbs] = -cy3 + i2[limbs] + (cy>>1); mpn_addmod_2expp1_1(t + limbs - x, x, cy1 + i1[limbs]); mpn_addmod_2expp1_1(u + limbs - x, x, cy2 + i1[limbs]); } else if (x == y) { cy = fft_sumdiff(t, u, i1 + x, i2 + x, limbs - x); cy1 = (cy>>1); cy2 = -(cy&1); cy = fft_sumdiff(t + limbs - x, u + limbs - x, i2, i1, x); cy3 = mpn_neg(t + limbs - x, t + limbs - x, x); u[limbs] = -(cy&1); t[limbs] = -(cy>>1) - cy3; mpn_addmod_2expp1_1(t + limbs - x, x, cy1 + i1[limbs] + i2[limbs]); mpn_addmod_2expp1_1(u + limbs - x, x, cy2 + i1[limbs] - i2[limbs]); } else if (x > y) { cy = fft_sumdiff(t + limbs - y, u + limbs - y, i2, i1 + x - y, y); cy3 = mpn_neg(t + limbs - y, t + limbs - y, y); t[limbs] = -(cy>>1) - cy3; u[limbs] = -(cy&1); cy3 = mpn_neg(i1, i1, x - y); cy = fft_sumdiff(t + limbs - x, u + limbs - x, i1, i2 + limbs - x + y, x - y); mpn_addmod_2expp1_1(t + limbs - y, y, (cy>>1) + i2[limbs] - cy3); mpn_addmod_2expp1_1(u + limbs - y, y, -(cy&1) - i2[limbs] - cy3); cy = fft_sumdiff(t, u, i1 + x, i2 + y, limbs - x); mpn_addmod_2expp1_1(t + limbs - x, x, (cy>>1) + i1[limbs]); mpn_addmod_2expp1_1(u + limbs - x, x, -(cy&1) + i1[limbs]); } else /* x < y */ { cy = fft_sumdiff(t + limbs - x, u + limbs - x, i2 + y - x, i1, x); cy3 = mpn_neg(t + limbs - x, t + limbs - x, x); t[limbs] = -(cy>>1) - cy3; u[limbs] = -(cy&1); cy3 = mpn_neg(i2, i2, y - x); cy = fft_sumdiff(t + limbs - y, u + limbs - y, i1 + limbs - y + x, i2, y - x); mpn_addmod_2expp1_1(t + limbs - x, x, (cy>>1) + i1[limbs] - cy3); mpn_addmod_2expp1_1(u + limbs - x, x, -(cy&1) + i1[limbs] + cy3); cy = fft_sumdiff(t, u, i1 + x, i2 + y, limbs - y); mpn_addmod_2expp1_1(t + limbs - y, y, (cy>>1) + i2[limbs]); mpn_addmod_2expp1_1(u + limbs - y, y, -(cy&1) - i2[limbs]); } } flint-3.1.3/src/fft/combine_bits.c000066400000000000000000000050631461254215100170060ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void fft_combine_limbs(mp_limb_t * res, mp_limb_t ** poly, slong length, mp_size_t coeff_limbs, mp_size_t output_limbs, mp_size_t total_limbs) { mp_size_t skip, i; for (skip = 0, i = 0; i < length && skip + output_limbs + 1 <= total_limbs; i++, skip += coeff_limbs) mpn_add(res + skip, res + skip, output_limbs + 1, poly[i], output_limbs); while ((skip < total_limbs) && (i < length)) { mpn_add(res + skip, res + skip, total_limbs - skip, poly[i], FLINT_MIN(total_limbs - skip, output_limbs)); i++; skip += coeff_limbs; } } void fft_combine_bits(mp_limb_t * res, mp_limb_t ** poly, slong length, flint_bitcnt_t bits, mp_size_t output_limbs, mp_size_t total_limbs) { flint_bitcnt_t shift_bits, top_bits = ((FLINT_BITS - 1) & bits); mp_size_t coeff_limbs, i; mp_limb_t * temp, * limb_ptr, * end; if (top_bits == 0) { fft_combine_limbs(res, poly, length, bits/FLINT_BITS, output_limbs, total_limbs); return; } coeff_limbs = (bits/FLINT_BITS) + 1; temp = flint_malloc((output_limbs + 1)*sizeof(mp_limb_t)); shift_bits = 0; limb_ptr = res; end = res + total_limbs; for (i = 0; i < length && limb_ptr + output_limbs + 1 < end; i++) { if (shift_bits) { mpn_lshift(temp, poly[i], output_limbs + 1, shift_bits); mpn_add_n(limb_ptr, limb_ptr, temp, output_limbs + 1); } else mpn_add(limb_ptr, limb_ptr, output_limbs + 1, poly[i], output_limbs); shift_bits += top_bits; limb_ptr += (coeff_limbs - 1); if (shift_bits >= FLINT_BITS) { limb_ptr++; shift_bits -= FLINT_BITS; } } while (limb_ptr < end && i < length) { if (shift_bits) { mpn_lshift(temp, poly[i], output_limbs + 1, shift_bits); mpn_add_n(limb_ptr, limb_ptr, temp, end - limb_ptr); } else mpn_add_n(limb_ptr, limb_ptr, poly[i], end - limb_ptr); shift_bits += top_bits; limb_ptr += (coeff_limbs - 1); if (shift_bits >= FLINT_BITS) { limb_ptr++; shift_bits -= FLINT_BITS; } i++; } flint_free(temp); } flint-3.1.3/src/fft/convolution.c000066400000000000000000000074421461254215100167330ustar00rootroot00000000000000/* Copyright (C) 2008-2011, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fft.h" void fft_convolution(mp_limb_t ** ii, mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1, mp_limb_t ** tt) { slong n = (WORD(1)<. */ #include "ulong_extras.h" #include "fft.h" void fft_precache(mp_limb_t ** jj, slong depth, slong limbs, slong trunc, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** s1) { slong n = (WORD(1)<. */ #include "flint.h" #include "fft.h" /* WARNING: relies on GCC's handling of >> as arithmetic shift right */ void mpn_div_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d) { mp_limb_t lo; mp_limb_t * ptr; mp_limb_signed_t hi; if (d == 0) { if (t != i1) flint_mpn_copyi(t, i1, limbs + 1); } else { hi = i1[limbs]; lo = mpn_rshift(t, i1, limbs + 1, d); t[limbs] = (hi >> d); ptr = t + limbs - 1; sub_ddmmss(ptr[1], ptr[0], ptr[1], ptr[0], (mp_limb_t) 0, lo); } } flint-3.1.3/src/fft/fermat_to_mpz.c000066400000000000000000000016761461254215100172250ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void fermat_to_mpz(mpz_t m, mp_limb_t * i, mp_size_t limbs) { mp_limb_signed_t hi; mpz_realloc(m, limbs + 1); flint_mpn_copyi(m->_mp_d, i, limbs + 1); hi = i[limbs]; if (hi < WORD(0)) { mpn_neg(m->_mp_d, m->_mp_d, limbs + 1); m->_mp_size = limbs + 1; while ((m->_mp_size) && (!m->_mp_d[m->_mp_size - 1])) m->_mp_size--; m->_mp_size = -m->_mp_size; } else { m->_mp_size = limbs + 1; while ((m->_mp_size) && (!m->_mp_d[m->_mp_size - 1])) m->_mp_size--; } } flint-3.1.3/src/fft/fft_mfa_truncate_sqrt2.c000066400000000000000000000302031461254215100210050ustar00rootroot00000000000000/* Copyright (C) 2009, 2011, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fft.h" void fft_butterfly_twiddle(mp_limb_t * u, mp_limb_t * v, mp_limb_t * s, mp_limb_t * t, mp_size_t limbs, flint_bitcnt_t b1, flint_bitcnt_t b2) { mp_limb_t nw = limbs*FLINT_BITS; mp_size_t x, y; int negate1 = 0; int negate2 = 0; if (b1 >= nw) { negate2 = 1; b1 -= nw; } x = b1/FLINT_BITS; b1 = b1%FLINT_BITS; if (b2 >= nw) { negate1 = 1; b2 -= nw; } y = b2/FLINT_BITS; b2 = b2%FLINT_BITS; butterfly_lshB(u, v, s, t, limbs, x, y); mpn_mul_2expmod_2expp1(u, u, limbs, b1); if (negate2) mpn_neg(u, u, limbs + 1); mpn_mul_2expmod_2expp1(v, v, limbs, b2); if (negate1) mpn_neg(v, v, limbs + 1); } void fft_radix2_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (n == 1) { mp_size_t tw1 = r*c; mp_size_t tw2 = tw1 + rs*c; fft_butterfly_twiddle(*t1, *t2, ii[0], ii[is], limbs, tw1*ws, tw2*ws); SWAP_PTRS(ii[0], *t1); SWAP_PTRS(ii[is], *t2); return; } for (i = 0; i < n; i++) { fft_butterfly(*t1, *t2, ii[i*is], ii[(n+i)*is], i, limbs, w); SWAP_PTRS(ii[i*is], *t1); SWAP_PTRS(ii[(n+i)*is], *t2); } fft_radix2_twiddle(ii, is, n/2, 2*w, t1, t2, ws, r, c, 2*rs); fft_radix2_twiddle(ii+n*is, is, n/2, 2*w, t1, t2, ws, r + rs, c, 2*rs); } void fft_truncate1_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (trunc == 2*n) fft_radix2_twiddle(ii, is, n, w, t1, t2, ws, r, c, rs); else if (trunc <= n) { for (i = 0; i < n; i++) mpn_add_n(ii[i*is], ii[i*is], ii[(i+n)*is], limbs + 1); fft_truncate1_twiddle(ii, is, n/2, 2*w, t1, t2, ws, r, c, 2*rs, trunc); } else { for (i = 0; i < n; i++) { fft_butterfly(*t1, *t2, ii[i*is], ii[(n+i)*is], i, limbs, w); SWAP_PTRS(ii[i*is], *t1); SWAP_PTRS(ii[(n+i)*is], *t2); } fft_radix2_twiddle(ii, is, n/2, 2*w, t1, t2, ws, r, c, 2*rs); fft_truncate1_twiddle(ii + n*is, is, n/2, 2*w, t1, t2, ws, r + rs, c, 2*rs, trunc - n); } } void fft_mfa_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) { mp_size_t i, j, s; mp_size_t n2 = (2*n)/n1; mp_size_t trunc2 = (trunc - 2*n)/n1; mp_size_t limbs = (n*w)/FLINT_BITS; flint_bitcnt_t depth = 0; flint_bitcnt_t depth2 = 0; while ((UWORD(1)< w bits */ fft_radix2_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1); for (j = 0; j < n2; j++) { mp_size_t s = n_revbin(j, depth); if (j < s) SWAP_PTRS(ii[i+j*n1], ii[i+s*n1]); } } /* FFTs on rows */ for (i = 0; i < n2; i++) { fft_radix2(ii + i*n1, n1/2, w*n2, t1, t2); for (j = 0; j < n1; j++) { mp_size_t t = n_revbin(j, depth2); if (j < t) SWAP_PTRS(ii[i*n1+j], ii[i*n1+t]); } } /* second half matrix fourier FFT : n2 rows, n1 cols */ ii += 2*n; /* FFTs on columns */ for (i = 0; i < n1; i++) { /* FFT of length n2 on column i, applying z^{r*i} for rows going up in steps of 1 starting at row 0, where z => w bits */ fft_truncate1_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1, trunc2); for (j = 0; j < n2; j++) { mp_size_t s = n_revbin(j, depth); if (j < s) SWAP_PTRS(ii[i+j*n1], ii[i+s*n1]); } } /* FFTs on relevant rows */ for (s = 0; s < trunc2; s++) { i = n_revbin(s, depth); fft_radix2(ii + i*n1, n1/2, w*n2, t1, t2); for (j = 0; j < n1; j++) { mp_size_t t = n_revbin(j, depth2); if (j < t) SWAP_PTRS(ii[i*n1+j], ii[i*n1+t]); } } } typedef struct { volatile mp_size_t * i; mp_size_t n1; mp_size_t n2; mp_size_t n; mp_size_t trunc; mp_size_t limbs; flint_bitcnt_t depth; flint_bitcnt_t w; mp_limb_t ** ii; mp_limb_t ** t1; mp_limb_t ** t2; mp_limb_t * temp; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } fft_outer_arg_t; void _fft_outer1_worker(void * arg_ptr) { fft_outer_arg_t arg = *((fft_outer_arg_t *) arg_ptr); mp_size_t n1 = arg.n1; mp_size_t n2 = arg.n2; mp_size_t n = arg.n; mp_size_t trunc = arg.trunc; mp_size_t limbs = arg.limbs; flint_bitcnt_t depth = arg.depth; flint_bitcnt_t w = arg.w; mp_limb_t ** ii = arg.ii; mp_limb_t ** t1 = arg.t1; mp_limb_t ** t2 = arg.t2; mp_limb_t * temp = arg.temp; mp_size_t i, j, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; end = *arg.i = FLINT_MIN(i + 16, n1); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= n1) return; for ( ; i < end; i++) { /* relevant part of first layer of full sqrt2 FFT */ if (w & 1) { for (j = i; j < trunc - 2*n; j+=n1) { if (j & 1) fft_butterfly_sqrt2(*t1, *t2, ii[j], ii[2*n+j], j, limbs, w, temp); else fft_butterfly(*t1, *t2, ii[j], ii[2*n+j], j/2, limbs, w); SWAP_PTRS(ii[j], *t1); SWAP_PTRS(ii[2*n+j], *t2); } for ( ; j < 2*n; j+=n1) { if (i & 1) fft_adjust_sqrt2(ii[j + 2*n], ii[j], j, limbs, w, temp); else fft_adjust(ii[j + 2*n], ii[j], j/2, limbs, w); } } else { for (j = i; j < trunc - 2*n; j+=n1) { fft_butterfly(*t1, *t2, ii[j], ii[2*n+j], j, limbs, w/2); SWAP_PTRS(ii[j], *t1); SWAP_PTRS(ii[2*n+j], *t2); } for ( ; j < 2*n; j+=n1) fft_adjust(ii[j + 2*n], ii[j], j, limbs, w/2); } /* FFT of length n2 on column i, applying z^{r*i} for rows going up in steps of 1 starting at row 0, where z => w bits */ fft_radix2_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1); for (j = 0; j < n2; j++) { mp_size_t s = n_revbin(j, depth); if (j < s) SWAP_PTRS(ii[i + j*n1], ii[i + s*n1]); } } } } void _fft_outer2_worker(void * arg_ptr) { fft_outer_arg_t arg = *((fft_outer_arg_t *) arg_ptr); mp_size_t n1 = arg.n1; mp_size_t n2 = arg.n2; mp_size_t trunc2 = arg.trunc; flint_bitcnt_t depth = arg.depth; flint_bitcnt_t w = arg.w; mp_limb_t ** ii = arg.ii; mp_limb_t ** t1 = arg.t1; mp_limb_t ** t2 = arg.t2; mp_size_t i, j, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; end = *arg.i = FLINT_MIN(i + 16, n1); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= n1) return; for ( ; i < end; i++) { /* FFT of length n2 on column i, applying z^{r*i} for rows going up in steps of 1 starting at row 0, where z => w bits */ fft_truncate1_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1, trunc2); for (j = 0; j < n2; j++) { mp_size_t s = n_revbin(j, depth); if (j < s) SWAP_PTRS(ii[i+j*n1], ii[i+s*n1]); } } } } void fft_mfa_truncate_sqrt2_outer(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) { mp_size_t i, shared_i = 0; mp_size_t n2 = (2*n)/n1; mp_size_t trunc2 = (trunc - 2*n)/n1; mp_size_t limbs = (n*w)/FLINT_BITS; flint_bitcnt_t depth = 0; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong num_threads; thread_pool_handle * threads; fft_outer_arg_t * args; while ((UWORD(1)<. */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fft.h" typedef struct { volatile mp_size_t * i; mp_size_t n1; mp_size_t n2; mp_size_t n; mp_size_t trunc; mp_size_t limbs; flint_bitcnt_t depth; flint_bitcnt_t w; mp_limb_t ** ii; mp_limb_t ** jj; mp_limb_t ** t1; mp_limb_t ** t2; mp_limb_t * tt; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } fft_inner_arg_t; void _fft_inner1_worker(void * arg_ptr) { fft_inner_arg_t arg = *((fft_inner_arg_t *) arg_ptr); mp_size_t n1 = arg.n1; mp_size_t n2 = arg.n2; mp_size_t n = arg.n; mp_size_t trunc = arg.trunc; mp_size_t limbs = arg.limbs; flint_bitcnt_t depth = arg.depth; flint_bitcnt_t w = arg.w; mp_limb_t ** ii = arg.ii; mp_limb_t ** jj = arg.jj; mp_limb_t ** t1 = arg.t1; mp_limb_t ** t2 = arg.t2; mp_limb_t * tt = arg.tt; mp_size_t i, j, s, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif s = *arg.i; end = *arg.i = FLINT_MIN(s + 16, trunc); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (s >= trunc) return; for ( ; s < end; s++) { i = n_revbin(s, depth); fft_radix2(ii + i*n1, n1/2, w*n2, t1, t2); if (ii != jj) fft_radix2(jj + i*n1, n1/2, w*n2, t1, t2); for (j = 0; j < n1; j++) { mp_size_t t = i*n1 + j; mpn_normmod_2expp1(ii[t], limbs); if (ii != jj) mpn_normmod_2expp1(jj[t], limbs); fft_mulmod_2expp1(ii[t], ii[t], jj[t], n, w, tt); } ifft_radix2(ii + i*n1, n1/2, w*n2, t1, t2); } } } void _fft_inner2_worker(void * arg_ptr) { fft_inner_arg_t arg = *((fft_inner_arg_t *) arg_ptr); mp_size_t n1 = arg.n1; mp_size_t n2 = arg.n2; mp_size_t n = arg.n; mp_size_t limbs = arg.limbs; flint_bitcnt_t w = arg.w; mp_limb_t ** ii = arg.ii; mp_limb_t ** jj = arg.jj; mp_limb_t ** t1 = arg.t1; mp_limb_t ** t2 = arg.t2; mp_limb_t * tt = arg.tt; mp_size_t i, j, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; end = *arg.i = FLINT_MIN(i + 16, n2); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= n2) return; for ( ; i < end; i++) { fft_radix2(ii + i*n1, n1/2, w*n2, t1, t2); if (ii != jj) fft_radix2(jj + i*n1, n1/2, w*n2, t1, t2); for (j = 0; j < n1; j++) { mp_size_t t = i*n1 + j; mpn_normmod_2expp1(ii[t], limbs); if (ii != jj) mpn_normmod_2expp1(jj[t], limbs); fft_mulmod_2expp1(ii[t], ii[t], jj[t], n, w, tt); } ifft_radix2(ii + i*n1, n1/2, w*n2, t1, t2); } } } void fft_mfa_truncate_sqrt2_inner(mp_limb_t ** ii, mp_limb_t ** jj, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc, mp_limb_t ** tt) { mp_size_t i, shared_i = 0; mp_size_t n2 = (2*n)/n1; mp_size_t trunc2 = (trunc - 2*n)/n1; mp_size_t limbs = (n*w)/FLINT_BITS; flint_bitcnt_t depth = 0; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong num_threads; thread_pool_handle * threads; fft_inner_arg_t * args; while ((UWORD(1)<. */ #include "flint.h" #include "fft.h" void fft_negacyclic(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; /* first apply twiddle factors corresponding to shifts of w*i/2 bits */ if (w & 1) { for (i = 0; i < n; i++) { fft_adjust(*t1, ii[i], i/2, limbs, w); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], (n+i)/2, limbs, w); SWAP_PTRS(ii[n+i], *t2); fft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); i++; fft_adjust_sqrt2(*t1, ii[i], i, limbs, w, *temp); SWAP_PTRS(ii[i], *t1); fft_adjust_sqrt2(*t2, ii[n+i], n+i, limbs, w, *temp); SWAP_PTRS(ii[n+i], *t2); fft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } } else { for (i = 0; i < n; i++) { fft_adjust(*t1, ii[i], i, limbs, w/2); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], n+i, limbs, w/2); SWAP_PTRS(ii[n+i], *t2); fft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } } fft_radix2(ii, n/2, 2*w, t1, t2); fft_radix2(ii+n, n/2, 2*w, t1, t2); } flint-3.1.3/src/fft/fft_radix2.c000066400000000000000000000024631461254215100164020ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void fft_butterfly(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w) { mp_size_t y; flint_bitcnt_t b1; b1 = i*w; y = b1/FLINT_BITS; b1 = b1%FLINT_BITS; butterfly_lshB(s, t, i1, i2, limbs, 0, y); mpn_mul_2expmod_2expp1(t, t, limbs, b1); } void fft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2) { mp_size_t i; mp_size_t limbs = (w*n)/GMP_LIMB_BITS; if (n == 1) { fft_butterfly(*t1, *t2, ii[0], ii[1], 0, limbs, w); SWAP_PTRS(ii[0], *t1); SWAP_PTRS(ii[1], *t2); return; } for (i = 0; i < n; i++) { fft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } fft_radix2(ii, n/2, 2*w, t1, t2); fft_radix2(ii + n, n/2, 2*w, t1, t2); } flint-3.1.3/src/fft/fft_truncate.c000066400000000000000000000035621461254215100170370ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void fft_truncate1(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (trunc == 2*n) fft_radix2(ii, n, w, t1, t2); else if (trunc <= n) { for (i = 0; i < n; i++) mpn_add_n(ii[i], ii[i], ii[i+n], limbs + 1); fft_truncate1(ii, n/2, 2*w, t1, t2, trunc); } else { for (i = 0; i < n; i++) { fft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } fft_radix2(ii, n/2, 2*w, t1, t2); fft_truncate1(ii+n, n/2, 2*w, t1, t2, trunc - n); } } void fft_truncate(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (trunc == 2*n) fft_radix2(ii, n, w, t1, t2); else if (trunc <= n) fft_truncate(ii, n/2, 2*w, t1, t2, trunc); else { for (i = 0; i < trunc - n; i++) { fft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } for ( ; i < n; i++) fft_adjust(ii[i+n], ii[i], i, limbs, w); fft_radix2(ii, n/2, 2*w, t1, t2); fft_truncate1(ii+n, n/2, 2*w, t1, t2, trunc - n); } } flint-3.1.3/src/fft/fft_truncate_sqrt2.c000066400000000000000000000047241461254215100201730ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void fft_butterfly_sqrt2(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp) { flint_bitcnt_t wn = limbs*FLINT_BITS; mp_limb_t cy = 0; mp_size_t j = i/2, k = w/2; mp_size_t y; flint_bitcnt_t b1; int negate = 0; b1 = j + wn/4 + i*k; if (b1 >= wn) { negate = 1; b1 -= wn; } y = b1/FLINT_BITS; b1 = b1%FLINT_BITS; /* sumdiff and multiply by 2^{j + wn/4 + i*k} */ butterfly_lshB(s, t, i1, i2, limbs, 0, y); mpn_mul_2expmod_2expp1(t, t, limbs, b1); /* multiply by 2^{wn/2} */ y = limbs/2; flint_mpn_copyi(temp + y, t, limbs - y); temp[limbs] = 0; if (y) cy = mpn_neg(temp, t + limbs - y, y); mpn_addmod_2expp1_1(temp + y, limbs - y, -t[limbs]); mpn_sub_1(temp + y, temp + y, limbs - y + 1, cy); /* shift by an additional half limb (rare) */ if (limbs & 1) mpn_mul_2expmod_2expp1(temp, temp, limbs, FLINT_BITS/2); /* subtract */ if (negate) mpn_sub_n(t, t, temp, limbs + 1); else mpn_sub_n(t, temp, t, limbs + 1); } void fft_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/GMP_LIMB_BITS; if ((w & 1) == 0) { fft_truncate(ii, 2*n, w/2, t1, t2, trunc); return; } for (i = 0; i < trunc - 2*n; i++) { fft_butterfly(*t1, *t2, ii[i], ii[2*n+i], i/2, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[i+2*n], *t2); i++; fft_butterfly_sqrt2(*t1, *t2, ii[i], ii[2*n+i], i, limbs, w, *temp); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[2*n+i], *t2); } for (i = trunc - 2*n; i < 2*n; i++) { fft_adjust(ii[i+2*n], ii[i], i/2, limbs, w); i++; fft_adjust_sqrt2(ii[i+2*n], ii[i], i, limbs, w, *temp); } fft_radix2(ii, n, w, t1, t2); fft_truncate1(ii + 2*n, n, w, t1, t2, trunc - 2*n); } flint-3.1.3/src/fft/ifft_mfa_truncate_sqrt2.c000066400000000000000000000334201461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2009, 2011, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fft.h" void ifft_butterfly_twiddle(mp_limb_t * u, mp_limb_t * v, mp_limb_t * s, mp_limb_t * t, mp_size_t limbs, flint_bitcnt_t b1, flint_bitcnt_t b2) { mp_limb_t nw = limbs*FLINT_BITS; mp_size_t x, y; int negate1 = 0; int negate2 = 0; if (b1 >= nw) { negate1 = 1; b1 -= nw; } x = b1/FLINT_BITS; b1 = b1%FLINT_BITS; if (b2 >= nw) { negate2 = 1; b2 -= nw; } y = b2/FLINT_BITS; b2 = b2%FLINT_BITS; if (negate1) mpn_neg(s, s, limbs + 1); mpn_div_2expmod_2expp1(s, s, limbs, b1); if (negate2) mpn_neg(t, t, limbs + 1); mpn_div_2expmod_2expp1(t, t, limbs, b2); butterfly_rshB(u, v, s, t, limbs, x, y); } void ifft_radix2_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (n == 1) { mp_size_t tw1, tw2; tw1 = r*c; tw2 = tw1 + rs*c; ifft_butterfly_twiddle(*t1, *t2, ii[0], ii[is], limbs, tw1*ws, tw2*ws); SWAP_PTRS(ii[0], *t1); SWAP_PTRS(ii[is], *t2); return; } ifft_radix2_twiddle(ii, is, n/2, 2*w, t1, t2, ws, r, c, 2*rs); ifft_radix2_twiddle(ii+n*is, is, n/2, 2*w, t1, t2, ws, r + rs, c, 2*rs); for (i = 0; i < n; i++) { ifft_butterfly(*t1, *t2, ii[i*is], ii[(n+i)*is], i, limbs, w); SWAP_PTRS(ii[i*is], *t1); SWAP_PTRS(ii[(n+i)*is], *t2); } } void ifft_truncate1_twiddle(mp_limb_t ** ii, mp_size_t is, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t ws, mp_size_t r, mp_size_t c, mp_size_t rs, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (trunc == 2*n) ifft_radix2_twiddle(ii, is, n, w, t1, t2, ws, r, c, rs); else if (trunc <= n) { for (i = trunc; i < n; i++) { mpn_add_n(ii[i*is], ii[i*is], ii[(i+n)*is], limbs + 1); mpn_div_2expmod_2expp1(ii[i*is], ii[i*is], limbs, 1); } ifft_truncate1_twiddle(ii, is, n/2, 2*w, t1, t2, ws, r, c, 2*rs, trunc); for (i = 0; i < trunc; i++) { #if HAVE_ADDSUB_N mpn_addsub_n(ii[i*is], ii[i*is], ii[i*is], ii[(n+i)*is], limbs + 1); #else mpn_add_n(ii[i*is], ii[i*is], ii[i*is], limbs + 1); mpn_sub_n(ii[i*is], ii[i*is], ii[(n+i)*is], limbs + 1); #endif } } else { ifft_radix2_twiddle(ii, is, n/2, 2*w, t1, t2, ws, r, c, 2*rs); for (i = trunc - n; i < n; i++) { mpn_sub_n(ii[(i+n)*is], ii[i*is], ii[(i+n)*is], limbs + 1); fft_adjust(*t1, ii[(i+n)*is], i, limbs, w); mpn_add_n(ii[i*is], ii[i*is], ii[(i+n)*is], limbs + 1); SWAP_PTRS(ii[(i+n)*is], *t1); } ifft_truncate1_twiddle(ii + n*is, is, n/2, 2*w, t1, t2, ws, r + rs, c, 2*rs, trunc - n); for (i = 0; i < trunc - n; i++) { ifft_butterfly(*t1, *t2, ii[i*is], ii[(n+i)*is], i, limbs, w); SWAP_PTRS(ii[i*is], *t1); SWAP_PTRS(ii[(n+i)*is], *t2); } } } void ifft_mfa_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) { mp_size_t i, j, s; mp_size_t n2 = (2*n)/n1; mp_size_t trunc2 = (trunc - 2*n)/n1; flint_bitcnt_t depth = 0; flint_bitcnt_t depth2 = 0; flint_bitcnt_t limbs = (w*n)/FLINT_BITS; while ((UWORD(1)< w bits */ ifft_radix2_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1); } /* second half IFFT : n2 rows, n1 cols */ ii += 2*n; /* row IFFTs */ for (s = 0; s < trunc2; s++) { i = n_revbin(s, depth); for (j = 0; j < n1; j++) { mp_size_t t = n_revbin(j, depth2); if (j < t) SWAP_PTRS(ii[i*n1 + j], ii[i*n1 + t]); } ifft_radix2(ii + i*n1, n1/2, w*n2, t1, t2); } /* column IFFTs with relevant sqrt2 layer butterflies combined */ for (i = 0; i < n1; i++) { for (j = 0; j < trunc2; j++) { mp_size_t s = n_revbin(j, depth); if (j < s) SWAP_PTRS(ii[i+j*n1], ii[i+s*n1]); } for ( ; j < n2; j++) { mp_size_t u = i + j*n1; if (w & 1) { if (i & 1) fft_adjust_sqrt2(ii[i + j*n1], ii[u - 2*n], u, limbs, w, *temp); else fft_adjust(ii[i + j*n1], ii[u - 2*n], u/2, limbs, w); } else fft_adjust(ii[i + j*n1], ii[u - 2*n], u, limbs, w/2); } /* IFFT of length n2 on column i, applying z^{r*i} for rows going up in steps of 1 starting at row 0, where z => w bits */ ifft_truncate1_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1, trunc2); /* relevant components of final sqrt2 layer of IFFT */ if (w & 1) { for (j = i; j < trunc - 2*n; j+=n1) { if (j & 1) ifft_butterfly_sqrt2(*t1, *t2, ii[j - 2*n], ii[j], j, limbs, w, *temp); else ifft_butterfly(*t1, *t2, ii[j - 2*n], ii[j], j/2, limbs, w); SWAP_PTRS(ii[j-2*n], *t1); SWAP_PTRS(ii[j], *t2); } } else { for (j = i; j < trunc - 2*n; j+=n1) { ifft_butterfly(*t1, *t2, ii[j - 2*n], ii[j], j, limbs, w/2); SWAP_PTRS(ii[j-2*n], *t1); SWAP_PTRS(ii[j], *t2); } } for (j = trunc + i - 2*n; j < 2*n; j+=n1) mpn_add_n(ii[j - 2*n], ii[j - 2*n], ii[j - 2*n], limbs + 1); } } typedef struct { volatile mp_size_t * i; mp_size_t n1; mp_size_t n2; mp_size_t n; mp_size_t trunc; mp_size_t trunc2; mp_size_t limbs; flint_bitcnt_t depth; flint_bitcnt_t depth2; flint_bitcnt_t w; mp_limb_t ** ii; mp_limb_t ** t1; mp_limb_t ** t2; mp_limb_t * temp; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } ifft_outer_arg_t; void _ifft_outer1_worker(void * arg_ptr) { ifft_outer_arg_t arg = *((ifft_outer_arg_t *) arg_ptr); mp_size_t n1 = arg.n1; mp_size_t n2 = arg.n2; flint_bitcnt_t depth = arg.depth; flint_bitcnt_t w = arg.w; mp_limb_t ** ii = arg.ii; mp_limb_t ** t1 = arg.t1; mp_limb_t ** t2 = arg.t2; mp_size_t i, j, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; end = *arg.i = FLINT_MIN(i + 16, n1); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= n1) return; for ( ; i < end; i++) { for (j = 0; j < n2; j++) { mp_size_t s = n_revbin(j, depth); if (j < s) SWAP_PTRS(ii[i + j*n1], ii[i + s*n1]); } /* IFFT of length n2 on column i, applying z^{r*i} for rows going up in steps of 1 starting at row 0, where z => w bits */ ifft_radix2_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1); } } } void _ifft_outer2_worker(void * arg_ptr) { ifft_outer_arg_t arg = *((ifft_outer_arg_t *) arg_ptr); mp_size_t n1 = arg.n1; mp_size_t n2 = arg.n2; mp_size_t n = arg.n; mp_size_t trunc = arg.trunc; mp_size_t trunc2 = arg.trunc2; mp_size_t limbs = arg.limbs; flint_bitcnt_t depth = arg.depth; flint_bitcnt_t depth2 = arg.depth2; flint_bitcnt_t w = arg.w; mp_limb_t ** ii = arg.ii; mp_limb_t ** t1 = arg.t1; mp_limb_t ** t2 = arg.t2; mp_limb_t * temp = arg.temp; mp_size_t i, j, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; end = *arg.i = FLINT_MIN(i + 16, n1); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= n1) return; for ( ; i < end; i++) { for (j = 0; j < trunc2; j++) { mp_size_t s = n_revbin(j, depth); if (j < s) SWAP_PTRS(ii[i + j*n1], ii[i + s*n1]); } for ( ; j < n2; j++) { mp_size_t u = i + j*n1; if (w & 1) { if (i & 1) fft_adjust_sqrt2(ii[i + j*n1], ii[u - 2*n], u, limbs, w, temp); else fft_adjust(ii[i + j*n1], ii[u - 2*n], u/2, limbs, w); } else fft_adjust(ii[i + j*n1], ii[u - 2*n], u, limbs, w/2); } /* IFFT of length n2 on column i, applying z^{r*i} for rows going up in steps of 1 starting at row 0, where z => w bits */ ifft_truncate1_twiddle(ii + i, n1, n2/2, w*n1, t1, t2, w, 0, i, 1, trunc2); /* relevant components of final sqrt2 layer of IFFT */ if (w & 1) { for (j = i; j < trunc - 2*n; j+=n1) { if (j & 1) ifft_butterfly_sqrt2(*t1, *t2, ii[j - 2*n], ii[j], j, limbs, w, temp); else ifft_butterfly(*t1, *t2, ii[j - 2*n], ii[j], j/2, limbs, w); SWAP_PTRS(ii[j - 2*n], *t1); SWAP_PTRS(ii[j], *t2); } } else { for (j = i; j < trunc - 2*n; j+=n1) { ifft_butterfly(*t1, *t2, ii[j - 2*n], ii[j], j, limbs, w/2); SWAP_PTRS(ii[j - 2*n], *t1); SWAP_PTRS(ii[j], *t2); } } for (j = trunc + i - 2*n; j < 2*n; j+=n1) mpn_add_n(ii[j - 2*n], ii[j - 2*n], ii[j - 2*n], limbs + 1); for (j = 0; j < trunc2; j++) { mp_size_t t = j*n1 + i; mpn_div_2expmod_2expp1(ii[t], ii[t], limbs, depth + depth2 + 1); mpn_normmod_2expp1(ii[t], limbs); } for (j = 0; j < n2; j++) { mp_size_t t = j*n1 + i - 2*n; mpn_div_2expmod_2expp1(ii[t], ii[t], limbs, depth + depth2 + 1); mpn_normmod_2expp1(ii[t], limbs); } } } } void ifft_mfa_truncate_sqrt2_outer(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t n1, mp_size_t trunc) { mp_size_t i, shared_i = 0; mp_size_t n2 = (2*n)/n1; mp_size_t trunc2 = (trunc - 2*n)/n1; flint_bitcnt_t depth = 0; flint_bitcnt_t depth2 = 0; flint_bitcnt_t limbs = (w*n)/FLINT_BITS; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong num_threads; thread_pool_handle * threads; ifft_outer_arg_t * args; while ((UWORD(1)<. */ #include "flint.h" #include "fft.h" void ifft_negacyclic(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; ifft_radix2(ii, n/2, 2*w, t1, t2); ifft_radix2(ii+n, n/2, 2*w, t1, t2); if (w & 1) { for (i = 0; i < n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); fft_adjust(*t1, ii[i], n - i/2, limbs, w); mpn_neg(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], n - (n+i)/2, limbs, w); mpn_neg(*t2, *t2, limbs + 1); SWAP_PTRS(ii[n+i], *t2); i++; ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); fft_adjust_sqrt2(*t1, ii[i], 2*n-i, limbs, w, *temp); mpn_neg(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust_sqrt2(*t2, ii[n+i], n-i, limbs, w, *temp); mpn_neg(*t2, *t2, limbs + 1); SWAP_PTRS(ii[n+i], *t2); } } else { for (i = 0; i < n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); fft_adjust(*t1, ii[i], 2*n-i, limbs, w/2); mpn_neg(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], n-i, limbs, w/2); mpn_neg(*t2, *t2, limbs + 1); SWAP_PTRS(ii[n+i], *t2); } } } flint-3.1.3/src/fft/ifft_radix2.c000066400000000000000000000025001461254215100165430ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void ifft_butterfly(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w) { mp_size_t y; flint_bitcnt_t b1; b1 = i*w; y = b1/FLINT_BITS; b1 = b1%FLINT_BITS; mpn_div_2expmod_2expp1(i2, i2, limbs, b1); butterfly_rshB(s, t, i1, i2, limbs, 0, y); } void ifft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (n == 1) { ifft_butterfly(*t1, *t2, ii[0], ii[1], 0, limbs, w); SWAP_PTRS(ii[0], *t1); SWAP_PTRS(ii[1], *t2); return; } ifft_radix2(ii, n/2, 2*w, t1, t2); ifft_radix2(ii+n, n/2, 2*w, t1, t2); for (i = 0; i < n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } } flint-3.1.3/src/fft/ifft_truncate.c000066400000000000000000000053101461254215100172010ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void ifft_truncate1(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if (trunc == 2*n) ifft_radix2(ii, n, w, t1, t2); else if (trunc <= n) { for (i = trunc; i < n; i++) { mpn_add_n(ii[i], ii[i], ii[i+n], limbs + 1); mpn_div_2expmod_2expp1(ii[i], ii[i], limbs, 1); } ifft_truncate1(ii, n/2, 2*w, t1, t2, trunc); for (i = 0; i < trunc; i++) { #if HAVE_ADDSUB_N mpn_addsub_n(ii[i], ii[i], ii[i], ii[n+i], limbs + 1); #else mpn_add_n(ii[i], ii[i], ii[i], limbs + 1); mpn_sub_n(ii[i], ii[i], ii[n+i], limbs + 1); #endif } } else { ifft_radix2(ii, n/2, 2*w, t1, t2); for (i = trunc - n; i < n; i++) { mpn_sub_n(ii[i+n], ii[i], ii[i+n], limbs + 1); fft_adjust(*t1, ii[i+n], i, limbs, w); mpn_add_n(ii[i], ii[i], ii[i+n], limbs + 1); SWAP_PTRS(ii[i+n], *t1); } ifft_truncate1(ii+n, n/2, 2*w, t1, t2, trunc - n); for (i = 0; i < trunc - n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } } } void ifft_truncate(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/GMP_LIMB_BITS; if (trunc == 2*n) ifft_radix2(ii, n, w, t1, t2); else if (trunc <= n) { ifft_truncate(ii, n/2, 2*w, t1, t2, trunc); for (i = 0; i < trunc; i++) mpn_add_n(ii[i], ii[i], ii[i], limbs + 1); } else { ifft_radix2(ii, n/2, 2*w, t1, t2); for (i = trunc - n; i < n; i++) fft_adjust(ii[i+n], ii[i], i, limbs, w); ifft_truncate1(ii+n, n/2, 2*w, t1, t2, trunc - n); for (i = 0; i < trunc - n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } for (i = trunc - n; i < n; i++) mpn_add_n(ii[i], ii[i], ii[i], limbs + 1); } } flint-3.1.3/src/fft/ifft_truncate_sqrt2.c000066400000000000000000000051731461254215100203430ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void ifft_butterfly_sqrt2(mp_limb_t * s, mp_limb_t * t, mp_limb_t * i1, mp_limb_t * i2, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w, mp_limb_t * temp) { flint_bitcnt_t wn = limbs*FLINT_BITS; mp_limb_t cy = 0; mp_size_t j = i/2, k = w/2; mp_size_t y2, y; mp_size_t b1; int negate = 1; b1 = wn - j - i*k - 1 + wn/4; if (b1 >= wn) { negate = 0; b1 -= wn; } y2 = b1/GMP_LIMB_BITS; b1 = b1%GMP_LIMB_BITS; /* multiply by small part of 2^{2*wn - j - ik - 1 + wn/4} */ if (b1) mpn_mul_2expmod_2expp1(i2, i2, limbs, b1); /* multiply by 2^{wn/2} */ y = limbs/2; flint_mpn_copyi(temp + y, i2, limbs - y); temp[limbs] = 0; if (y) cy = mpn_neg(temp, i2 + limbs - y, y); mpn_addmod_2expp1_1(temp + y, limbs - y, -i2[limbs]); mpn_sub_1(temp + y, temp + y, limbs - y + 1, cy); /* shift by an additional half limb (rare) */ if (limbs & 1) mpn_mul_2expmod_2expp1(temp, temp, limbs, FLINT_BITS/2); /* subtract and negate... */ if (negate) mpn_sub_n(i2, temp, i2, limbs + 1); else mpn_sub_n(i2, i2, temp, limbs + 1); /* ...negate and shift **left** by y2 limbs (i.e. shift right by (size - y2) limbs) and sumdiff */ butterfly_rshB(s, t, i1, i2, limbs, 0, limbs - y2); } void ifft_truncate_sqrt2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp, mp_size_t trunc) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; if ((w & 1) == 0) { ifft_truncate(ii, 2*n, w/2, t1, t2, trunc); return; } ifft_radix2(ii, n, w, t1, t2); for (i = trunc - 2*n; i < 2*n; i++) { fft_adjust(ii[i+2*n], ii[i], i/2, limbs, w); i++; fft_adjust_sqrt2(ii[i+2*n], ii[i], i, limbs, w, *temp); } ifft_truncate1(ii + 2*n, n, w, t1, t2, trunc - 2*n); for (i = 0; i < trunc - 2*n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[2*n+i], i/2, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[2*n+i], *t2); i++; ifft_butterfly_sqrt2(*t1, *t2, ii[i], ii[2*n+i], i, limbs, w, *temp); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[2*n+i], *t2); } for (i = trunc - 2*n; i < 2*n; i++) mpn_add_n(ii[i], ii[i], ii[i], limbs + 1); } flint-3.1.3/src/fft/inlines.c000066400000000000000000000006651461254215100160150ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FFT_INLINES_C #include "flint.h" #include "fft.h" flint-3.1.3/src/fft/mul_2expmod_2expp1.c000066400000000000000000000017041461254215100200010ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" /* WARNING: relies on GCC's handling of >> as arithmetic shift right */ void mpn_mul_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d) { mp_limb_signed_t hi1, hi2; if (d == 0) { if (t != i1) flint_mpn_copyi(t, i1, limbs + 1); } else { hi1 = ((mp_limb_signed_t) i1[limbs] >> (GMP_LIMB_BITS - d)); mpn_lshift(t, i1, limbs + 1, d); hi2 = t[limbs]; t[limbs] = 0; mpn_sub_1(t, t, limbs + 1, hi2); mpn_addmod_2expp1_1(t + 1, limbs - 1, -hi1); } } flint-3.1.3/src/fft/mul_fft_main.c000066400000000000000000000040521461254215100170060ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" #include "ulong_extras.h" #include "fft_tuning.h" static int fft_tuning_table[5][2] = FFT_TAB; void flint_mpn_mul_fft_main(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2) { mp_size_t off, depth = 6; mp_size_t w = 1; mp_size_t n = ((mp_size_t) 1 << depth); flint_bitcnt_t bits = (n*w - (depth+1))/2; flint_bitcnt_t bits1 = n1*FLINT_BITS; flint_bitcnt_t bits2 = n2*FLINT_BITS; mp_size_t j1 = (bits1 - 1)/bits + 1; mp_size_t j2 = (bits2 - 1)/bits + 1; FLINT_ASSERT(n1 > 0); FLINT_ASSERT(n2 > 0); FLINT_ASSERT(j1 + j2 - 1 > 2*n); while (j1 + j2 - 1 > 4*n) /* find initial n, w */ { if (w == 1) w = 2; else { depth++; w = 1; n *= 2; } bits = (n*w - (depth+1))/2; j1 = (bits1 - 1)/bits + 1; j2 = (bits2 - 1)/bits + 1; } if (depth < 11) { mp_size_t wadj = 1; off = fft_tuning_table[depth - 6][w - 1]; /* adjust n and w */ depth -= off; n = ((mp_size_t) 1 << depth); w *= ((mp_size_t) 1 << (2*off)); if (depth < 6) wadj = ((mp_size_t) 1 << (6 - depth)); if (w > wadj) { do { /* see if a smaller w will work */ w -= wadj; bits = (n*w - (depth+1))/2; j1 = (bits1 - 1)/bits + 1; j2 = (bits2 - 1)/bits + 1; } while (j1 + j2 - 1 <= 4*n && w > wadj); w += wadj; } mul_truncate_sqrt2(r1, i1, n1, i2, n2, depth, w); } else { if (j1 + j2 - 1 <= 3*n) { depth--; w *= 3; } mul_mfa_truncate_sqrt2(r1, i1, n1, i2, n2, depth, w); } } flint-3.1.3/src/fft/mul_mfa_truncate_sqrt2.c000066400000000000000000000054341461254215100210330ustar00rootroot00000000000000/* Copyright (C) 2009, 2011, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" #include "ulong_extras.h" void mul_mfa_truncate_sqrt2(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2, flint_bitcnt_t depth, flint_bitcnt_t w) { mp_size_t n = (UWORD(1)<. */ #include "flint.h" #include "fft.h" #include "mpn_extras.h" void mul_truncate_sqrt2(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2, flint_bitcnt_t depth, flint_bitcnt_t w) { mp_size_t n = (UWORD(1)<. */ #include "flint.h" #include "fft.h" #include "ulong_extras.h" #include "fft_tuning.h" #include "mpn_extras.h" static mp_size_t mulmod_2expp1_table_n[FFT_N_NUM] = MULMOD_TAB; void fft_naive_convolution_1(mp_limb_t * r, mp_limb_t * ii, mp_limb_t * jj, mp_size_t m) { mp_size_t i, j; for (i = 0; i < m; i++) r[i] = ii[0]*jj[i]; for (i = 1; i < m; i++) { for (j = 0; j < m - i; j++) r[i+j] += ii[i]*jj[j]; for ( ; j < m; j++) r[i+j-m] -=ii[i]*jj[j]; } } void _fft_mulmod_2expp1(mp_limb_t * r1, mp_limb_t * i1, mp_limb_t * i2, mp_size_t r_limbs, flint_bitcnt_t depth, flint_bitcnt_t w) { mp_size_t n = (UWORD(1)<. */ #include "flint.h" #include "fft.h" /* negation mod 2^(FLINT_BITS*limbs) + 1 assuming normalized input */ void mpn_negmod_2expp1(mp_limb_t* z, const mp_limb_t* a, mp_size_t limbs) { if (a[limbs] != 0) { FLINT_ASSERT(a[limbs] == 1); z[0] = 1; flint_mpn_zero(z + 1, limbs); } else { mpn_com(z, a, limbs); z[limbs] = mpn_add_1(z, z, limbs, 2); if (z[limbs] != 0) { if (z[0] != 0) { FLINT_ASSERT(z[0] == 1); z[0] = 0; z[limbs] = 0; } } } } flint-3.1.3/src/fft/normmod_2expp1.c000066400000000000000000000016461461254215100172260ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fft.h" void mpn_normmod_2expp1(mp_limb_t * t, mp_size_t limbs) { mp_limb_signed_t hi = t[limbs]; if (hi) { t[limbs] = 0; mpn_addmod_2expp1_1(t, limbs, -hi); /* hi will now be in [-1,1] */ if ((hi = t[limbs])) { t[limbs] = 0; mpn_addmod_2expp1_1(t, limbs, -hi); if (t[limbs] == ~(mp_limb_signed_t) 0) /* if we now have -1 (very unlikely) */ { t[limbs] = 0; mpn_addmod_2expp1_1(t, limbs, 1); } } } } flint-3.1.3/src/fft/profile/000077500000000000000000000000001461254215100156415ustar00rootroot00000000000000flint-3.1.3/src/fft/profile/p-mul_fft_main.c000066400000000000000000000031071461254215100207030ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" #include "profiler.h" int main(void) { mp_ptr r, x, y; mp_size_t n; slong i, nt; double t, FLINT_SET_BUT_UNUSED(_); flint_printf(" n mpn_mul 1 thread 2 threads 4 threads 8 threads\n"); for (n = 1000; n <= 10000000; n *= 1.025) { r = flint_malloc(2 * n * sizeof(mp_limb_t)); x = flint_malloc(n * sizeof(mp_limb_t)); y = flint_malloc(n * sizeof(mp_limb_t)); for (i = 0; i < n; i++) { x[i] = UWORD_MAX - i - 1; y[i] = UWORD_MAX - i - 2; } flint_printf("%10wd", n); fflush(stdout); TIMEIT_START mpn_mul(r, x, n, y, n); TIMEIT_STOP_VALUES(_, t) flint_printf("%12g", t); fflush(stdout); for (nt = 1; nt <= 8; nt *= 2) { flint_set_num_threads(nt); TIMEIT_START flint_mpn_mul_fft_main(r, x, n, y, n); TIMEIT_STOP_VALUES(_, t) flint_printf("%12g", t); fflush(stdout); } flint_printf("\n"); flint_free(r); flint_free(x); flint_free(y); } return 0; } flint-3.1.3/src/fft/profile/p-mul_mfa_truncate_sqrt2.c000066400000000000000000000031711461254215100227240ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; mp_size_t iters; double truncation; FLINT_TEST_INIT(state); flint_printf("mul_mfa_truncate_sqrt2...."); fflush(stdout); _flint_rand_init_gmp(state); depth = 13; w = 2; iters = 1; truncation = 0.5; { mp_size_t n = (UWORD(1)<gmp_state, int_limbs*FLINT_BITS); flint_mpn_urandomb(i2, state->gmp_state, int_limbs*FLINT_BITS); for (j = 0; j < iters; j++) mul_mfa_truncate_sqrt2(r1, i1, int_limbs, i2, int_limbs, depth, w); /* mpn_mul(r2, i1, int_limbs, i2, int_limbs); */ flint_free(i1); } flint_randclear(state); flint_printf("done\n"); return 0; } flint-3.1.3/src/fft/profile/p-mul_truncate_sqrt2.c000066400000000000000000000031561461254215100221040ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; mp_size_t iters; double truncation; FLINT_TEST_INIT(state); flint_printf("mul_truncate_sqrt2...."); fflush(stdout); _flint_rand_init_gmp(state); depth = 13; w = 1; iters = 1; truncation = 1.0; { mp_size_t n = (UWORD(1)<gmp_state, int_limbs*FLINT_BITS); flint_mpn_urandomb(i2, state->gmp_state, int_limbs*FLINT_BITS); /* mpn_mul(r2, i1, int_limbs, i2, int_limbs); */ for (j = 0; j < iters; j++) mul_truncate_sqrt2(r1, i1, int_limbs, i2, int_limbs, depth, w); flint_free(i1); } flint_randclear(state); flint_printf("done\n"); return 0; } flint-3.1.3/src/fft/split_bits.c000066400000000000000000000167141461254215100165320ustar00rootroot00000000000000/* Copyright (C) 2009, 2011, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fft.h" typedef struct { volatile mp_size_t * i; slong num; mp_size_t coeff_limbs; mp_size_t output_limbs; mp_srcptr limbs; mp_limb_t ** poly; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } split_limbs_arg_t; void _split_limbs_worker(void * arg_ptr) { split_limbs_arg_t arg = *((split_limbs_arg_t *) arg_ptr); slong num = arg.num; mp_size_t skip; mp_size_t coeff_limbs = arg.coeff_limbs; mp_size_t output_limbs = arg.output_limbs; mp_srcptr limbs = arg.limbs; mp_limb_t ** poly = arg.poly; mp_size_t i, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; end = *arg.i = FLINT_MIN(i + 16, num); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= num) return; for ( ; i < end; i++) { skip = i*coeff_limbs; flint_mpn_zero(poly[i], output_limbs + 1); flint_mpn_copyi(poly[i], limbs + skip, coeff_limbs); } } } mp_size_t fft_split_limbs(mp_limb_t ** poly, mp_srcptr limbs, mp_size_t total_limbs, mp_size_t coeff_limbs, mp_size_t output_limbs) { mp_size_t i, shared_i = 0, skip, length = (total_limbs - 1)/coeff_limbs + 1; mp_size_t num = total_limbs/coeff_limbs; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong num_threads; thread_pool_handle * threads; split_limbs_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif num_threads = flint_request_threads(&threads, FLINT_MIN(flint_get_num_threads(), (num + 15)/16)); args = (split_limbs_arg_t *) flint_malloc(sizeof(split_limbs_arg_t)*(num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].i = &shared_i; args[i].num = num; args[i].coeff_limbs = coeff_limbs; args[i].output_limbs = output_limbs; args[i].limbs = limbs; args[i].poly = poly; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif } for (i = 0; i < num_threads; i++) thread_pool_wake(global_thread_pool, threads[i], 0, _split_limbs_worker, &args[i]); _split_limbs_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) thread_pool_wait(global_thread_pool, threads[i]); flint_give_back_threads(threads, num_threads); flint_free(args); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif i = num; skip = i*coeff_limbs; if (i < length) flint_mpn_zero(poly[i], output_limbs + 1); if (total_limbs > skip) flint_mpn_copyi(poly[i], limbs + skip, total_limbs - skip); return length; } typedef struct { volatile mp_size_t * i; slong length; mp_size_t coeff_limbs; mp_size_t output_limbs; mp_srcptr limbs; flint_bitcnt_t top_bits; mp_limb_t mask; mp_limb_t ** poly; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } split_bits_arg_t; void _split_bits_worker(void * arg_ptr) { split_bits_arg_t arg = *((split_bits_arg_t *) arg_ptr); slong length = arg.length; mp_size_t coeff_limbs = arg.coeff_limbs; mp_size_t output_limbs = arg.output_limbs; mp_srcptr limbs = arg.limbs; flint_bitcnt_t top_bits = arg.top_bits; mp_limb_t mask = arg.mask; mp_limb_t ** poly = arg.poly; flint_bitcnt_t shift_bits; mp_srcptr limb_ptr; mp_size_t i, end; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; end = *arg.i = FLINT_MIN(i + 16, length - 1); #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= length - 1) return; for ( ; i < end; i++) { flint_mpn_zero(poly[i], output_limbs + 1); limb_ptr = limbs + i*(coeff_limbs - 1) + (i*top_bits)/FLINT_BITS; shift_bits = (i*top_bits) % FLINT_BITS; if (!shift_bits) { flint_mpn_copyi(poly[i], limb_ptr, coeff_limbs); poly[i][coeff_limbs - 1] &= mask; limb_ptr += (coeff_limbs - 1); shift_bits += top_bits; } else { mpn_rshift(poly[i], limb_ptr, coeff_limbs, shift_bits); limb_ptr += (coeff_limbs - 1); shift_bits += top_bits; if (shift_bits >= FLINT_BITS) { limb_ptr++; poly[i][coeff_limbs - 1] += (limb_ptr[0] << (FLINT_BITS - (shift_bits - top_bits))); shift_bits -= FLINT_BITS; } poly[i][coeff_limbs - 1] &= mask; } } } } mp_size_t fft_split_bits(mp_limb_t ** poly, mp_srcptr limbs, mp_size_t total_limbs, flint_bitcnt_t bits, mp_size_t output_limbs) { mp_size_t i, shared_i = 0, coeff_limbs, limbs_left; mp_size_t length = (FLINT_BITS*total_limbs - 1)/bits + 1; flint_bitcnt_t shift_bits, top_bits = ((FLINT_BITS - 1) & bits); mp_srcptr limb_ptr; mp_limb_t mask; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong num_threads; thread_pool_handle * threads; split_bits_arg_t * args; if (top_bits == 0) return fft_split_limbs(poly, limbs, total_limbs, bits/FLINT_BITS, output_limbs); coeff_limbs = (bits/FLINT_BITS) + 1; mask = (WORD(1)<. */ #include #include /* Include functions *********************************************************/ #include "t-adjust.c" #include "t-adjust_sqrt2.c" #include "t-butterfly.c" #include "t-butterfly_lshB.c" #include "t-butterfly_rshB.c" #include "t-butterfly_sqrt2.c" #include "t-butterfly_twiddle.c" #include "t-convolution.c" #include "t-convolution_precache.c" #include "t-div_2expmod_2expp1.c" #include "t-fft_ifft_mfa_truncate_sqrt2.c" #include "t-fft_ifft_negacyclic.c" #include "t-fft_ifft_radix2.c" #include "t-fft_ifft_truncate.c" #include "t-fft_ifft_truncate_sqrt2.c" #include "t-mul_2expmod_2expp1.c" #include "t-mul_fft_main.c" #include "t-mul_mfa_truncate_sqrt2.c" #include "t-mulmod_2expp1.c" #include "t-mul_truncate_sqrt2.c" #include "t-negmod_2expp1.c" #include "t-normmod_2expp1.c" #include "t-split_combine_bits.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fft_adjust), TEST_FUNCTION(fft_adjust_sqrt2), TEST_FUNCTION(fft_ifft_butterfly), TEST_FUNCTION(butterfly_lshB), TEST_FUNCTION(butterfly_rshB), TEST_FUNCTION(fft_ifft_butterfly_sqrt2), TEST_FUNCTION(fft_ifft_butterfly_twiddle), TEST_FUNCTION(fft_convolution), TEST_FUNCTION(fft_convolution_precache), TEST_FUNCTION(mpn_div_2expmod_2expp1), TEST_FUNCTION(fft_ifft_mfa_truncate_sqrt2), TEST_FUNCTION(fft_ifft_negacyclic), TEST_FUNCTION(fft_ifft_radix2), TEST_FUNCTION(fft_ifft_truncate), TEST_FUNCTION(fft_ifft_truncate_sqrt2), TEST_FUNCTION(mpn_mul_2expmod_2expp1), TEST_FUNCTION(flint_mpn_mul_fft_main), TEST_FUNCTION(mul_mfa_truncate_sqrt2), TEST_FUNCTION(fft_mulmod_2expp1), TEST_FUNCTION(mul_truncate_sqrt2), TEST_FUNCTION(mpn_negmod_2expp1), TEST_FUNCTION(mpn_normmod_2expp1), TEST_FUNCTION(fft_split_combine_bits) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fft/test/t-adjust.c000066400000000000000000000057371461254215100170730ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif void ref_adjust(mpz_t r, mpz_t i1, mpz_t p, mp_size_t i, mp_size_t w) { mpz_mul_2exp(r, i1, w*i); mpz_mod(r, r, p); } TEST_FUNCTION_START(fft_adjust, state) { mp_size_t c, bits, j, k, n, w, limbs; mpz_t p, m2a, m2b, mn1; mp_limb_t * nn1, * r1; _flint_rand_init_gmp(state); mpz_init(p); mpz_init(m2a); mpz_init(m2b); mpz_init(mn1); for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 0; c < n; c++) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; set_p(p, n, w); nn1 = flint_malloc((limbs+1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs+1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); fermat_to_mpz(mn1, nn1, limbs); ref_adjust(m2a, mn1, p, c, w); fft_adjust(r1, nn1, c, limbs, w); fermat_to_mpz(m2b, r1, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); if (mpz_cmp(m2a, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("adjust error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, c = %wd\n", n, w, c); gmp_printf("want %Zx\n\n", m2a); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(nn1); flint_free(r1); } } } } mpz_clear(p); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-adjust_sqrt2.c000066400000000000000000000064571461254215100202260ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif void ref_adjust_sqrt2(mpz_t r, mpz_t i1, mpz_t p, mp_size_t i, mp_size_t limbs, mp_size_t w) { mpz_mul_2exp(r, i1, (w/2)*i + i/2); if (i & 1) { mpz_mul_2exp(i1, r, 3*limbs*FLINT_BITS/4); mpz_mul_2exp(r, r, limbs*FLINT_BITS/4); mpz_sub(r, i1, r); } mpz_mod(r, r, p); } TEST_FUNCTION_START(fft_adjust_sqrt2, state) { mp_size_t c, bits, j, k, n, w, limbs; mpz_t p, m2a, m2b, mn1; mp_limb_t * nn1, * r1, * temp; _flint_rand_init_gmp(state); mpz_init(p); mpz_init(m2a); mpz_init(m2b); mpz_init(mn1); for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 1; c < 2*n; c+=2) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; set_p(p, n, w); nn1 = flint_malloc((limbs+1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs+1)*sizeof(mp_limb_t)); temp = flint_malloc((limbs+1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); fermat_to_mpz(mn1, nn1, limbs); ref_adjust_sqrt2(m2a, mn1, p, c, limbs, w); fft_adjust_sqrt2(r1, nn1, c, limbs, w, temp); fermat_to_mpz(m2b, r1, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); if (mpz_cmp(m2a, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("adjust_sqrt2 error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, c = %wd\n", n, w, c); gmp_printf("want %Zx\n\n", m2a); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(temp); flint_free(nn1); flint_free(r1); } } } } mpz_clear(p); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-butterfly.c000066400000000000000000000157641461254215100176220ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif void ref_fft_butterfly(mpz_t s, mpz_t t, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t i, mp_size_t w) { mpz_add(s, i1, i2); mpz_sub(t, i1, i2); mpz_mul_2exp(t, t, i*w); mpz_mod(s, s, p); mpz_mod(t, t, p); } void ref_ifft_butterfly(mpz_t s, mpz_t t, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t i, mp_size_t n, mp_size_t w) { mpz_mul_2exp(i2, i2, 2*n*w - i*w); mpz_add(s, i1, i2); mpz_sub(t, i1, i2); mpz_mod(s, s, p); mpz_mod(t, t, p); } TEST_FUNCTION_START(fft_ifft_butterfly, state) { mp_size_t c, bits, j, k, n, w, limbs; mpz_t p, ma, mb, m2a, m2b, mn1, mn2; mp_limb_t * nn1, * nn2, * r1, * r2; _flint_rand_init_gmp(state); mpz_init(p); mpz_init(ma); mpz_init(mb); mpz_init(m2a); mpz_init(m2b); mpz_init(mn1); mpz_init(mn2); for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 0; c < n; c++) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); fft_butterfly(r1, r2, nn1, nn2, c, limbs, w); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_fft_butterfly(ma, mb, mn1, mn2, p, c, w); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("fft_butterfly error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("fft_butterfly error b\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 0; c < n; c++) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); ifft_butterfly(r1, r2, nn1, nn2, c, limbs, w); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_ifft_butterfly(ma, mb, mn1, mn2, p, c, n, w); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("ifft_butterfly error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("ifft_butterfly error b\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } mpz_clear(p); mpz_clear(ma); mpz_clear(mb); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); mpz_clear(mn2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-butterfly_lshB.c000066400000000000000000000107131461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif void ref_butterfly_lshB(mpz_t t, mpz_t u, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t x, mp_size_t y) { mpz_add(t, i1, i2); mpz_sub(u, i1, i2); mpz_mul_2exp(t, t, x*GMP_LIMB_BITS); mpz_mul_2exp(u, u, y*GMP_LIMB_BITS); mpz_mod(t, t, p); mpz_mod(u, u, p); } TEST_FUNCTION_START(butterfly_lshB, state) { mp_size_t c, bits, j, k, x, y, n, w, limbs; mpz_t p, ma, mb, m2a, m2b, mn1, mn2; mp_limb_t * nn1, * nn2, * r1, * r2; _flint_rand_init_gmp(state); mpz_init(p); mpz_init(ma); mpz_init(mb); mpz_init(m2a); mpz_init(m2b); mpz_init(mn1); mpz_init(mn2); for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 0; c < limbs; c++) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; x = n_randint(state, limbs); y = n_randint(state, limbs); nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); flint_mpn_rrandom(nn1, state->gmp_state, limbs); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); butterfly_lshB(r1, r2, nn1, nn2, limbs, x, y); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_butterfly_lshB(ma, mb, mn1, mn2, p, x, y); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("butterfly_lshB error a\n"); flint_printf("x = %wd, y = %wd, limbs = %wd\n", x, y, limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("butterfly_lshB error b\n"); flint_printf("x = %wd, y = %wd, limbs = %wd\n", x, y, limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } mpz_clear(p); mpz_clear(ma); mpz_clear(mb); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); mpz_clear(mn2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-butterfly_rshB.c000066400000000000000000000114071461254215100205660ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif void ref_butterfly_rshB(mpz_t t, mpz_t u, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t x, mp_size_t y) { mpz_t mult1, mult2; mpz_init(mult1); mpz_init(mult2); flint_mpz_set_ui(mult1, 1); mpz_mul_2exp(mult1, mult1, x*FLINT_BITS); mpz_invert(mult1, mult1, p); flint_mpz_set_ui(mult2, 1); mpz_mul_2exp(mult2, mult2, y*FLINT_BITS); mpz_invert(mult2, mult2, p); mpz_mul(mult1, mult1, i1); mpz_mul(mult2, mult2, i2); mpz_add(t, mult1, mult2); mpz_sub(u, mult1, mult2); mpz_mod(t, t, p); mpz_mod(u, u, p); mpz_clear(mult1); mpz_clear(mult2); } TEST_FUNCTION_START(butterfly_rshB, state) { mp_size_t c, bits, j, k, x, y, n, w, limbs; mpz_t p, ma, mb, m2a, m2b, mn1, mn2; mp_limb_t * nn1, * nn2, * r1, * r2; _flint_rand_init_gmp(state); mpz_init(p); mpz_init(ma); mpz_init(mb); mpz_init(m2a); mpz_init(m2b); mpz_init(mn1); mpz_init(mn2); for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 0; c < limbs; c++) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; x = n_randint(state, limbs); y = n_randint(state, limbs); nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); flint_mpn_rrandom(nn1, state->gmp_state, limbs); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); butterfly_rshB(r1, r2, nn1, nn2, limbs, x, y); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_butterfly_rshB(ma, mb, mn1, mn2, p, x, y); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("butterfly_rshB error a\n"); flint_printf("x = %wd, y = %wd, limbs = %wd\n", x, y, limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("butterfly_rshB error b\n"); flint_printf("x = %wd, y = %wd, limbs = %wd\n", x, y, limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } mpz_clear(p); mpz_clear(ma); mpz_clear(mb); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); mpz_clear(mn2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-butterfly_sqrt2.c000066400000000000000000000173301461254215100207440ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif void ref_fft_butterfly_sqrt2(mpz_t s, mpz_t t, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t i, mp_size_t limbs, mp_size_t w) { mpz_sub(t, i1, i2); mpz_mul_2exp(t, t, i*(w/2) + i/2); mpz_mul_2exp(s, t, 3*limbs*FLINT_BITS/4); mpz_mul_2exp(t, t, limbs*FLINT_BITS/4); mpz_sub(t, s, t); mpz_add(s, i1, i2); mpz_mod(s, s, p); mpz_mod(t, t, p); } void ref_ifft_butterfly_sqrt2(mpz_t s, mpz_t t, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t i, mp_size_t n, mp_size_t limbs, mp_size_t w) { mpz_mul_2exp(s, i2, 2*n*w - i*(w/2) - 1 - i/2); mpz_mul_2exp(t, s, 3*limbs*FLINT_BITS/4); mpz_mul_2exp(s, s, limbs*FLINT_BITS/4); mpz_sub(i2, t, s); mpz_add(s, i1, i2); mpz_sub(t, i1, i2); mpz_mod(s, s, p); mpz_mod(t, t, p); } TEST_FUNCTION_START(fft_ifft_butterfly_sqrt2, state) { mp_size_t c, bits, j, k, n, w, limbs; mpz_t p, ma, mb, m2a, m2b, mn1, mn2; mp_limb_t * nn1, * nn2, * r1, * r2, * temp; _flint_rand_init_gmp(state); mpz_init(p); mpz_init(ma); mpz_init(mb); mpz_init(m2a); mpz_init(m2b); mpz_init(mn1); mpz_init(mn2); for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; if ((w & 1) == 0) continue; /* w must be odd here */ limbs = (n*w)/FLINT_BITS; for (c = 1; c < 2*n; c+=2) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); temp = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); fft_butterfly_sqrt2(r1, r2, nn1, nn2, c, limbs, w, temp); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_fft_butterfly_sqrt2(ma, mb, mn1, mn2, p, c, limbs, w); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("fft_butterfly_sqrt2 error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("fft_butterfly_sqrt2 error b\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(temp); flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; if ((w & 1) == 0) continue; /* w must be odd here */ limbs = (n*w)/FLINT_BITS; for (c = 1; c < 2*n; c+=2) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); temp = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); ifft_butterfly_sqrt2(r1, r2, nn1, nn2, c, limbs, w, temp); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_ifft_butterfly_sqrt2(ma, mb, mn1, mn2, p, c, n, limbs, w); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("ifft_butterfly_sqrt2 error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("ifft_butterfly_sqrt2 error b\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(temp); flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } mpz_clear(p); mpz_clear(ma); mpz_clear(mb); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); mpz_clear(mn2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-butterfly_twiddle.c000066400000000000000000000166341461254215100213330ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif void ref_fft_butterfly_twiddle(mpz_t s, mpz_t t, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t i, mp_size_t w, flint_bitcnt_t b1, flint_bitcnt_t b2) { mpz_add(s, i1, i2); mpz_sub(t, i1, i2); mpz_mul_2exp(s, s, b1); mpz_mul_2exp(t, t, b2); mpz_mod(s, s, p); mpz_mod(t, t, p); } void ref_ifft_butterfly_twiddle(mpz_t s, mpz_t t, mpz_t i1, mpz_t i2, mpz_t p, mp_size_t i, mp_size_t n, mp_size_t w, flint_bitcnt_t b1, flint_bitcnt_t b2) { mpz_mul_2exp(i1, i1, 2*n*w - b1); mpz_mul_2exp(i2, i2, 2*n*w - b2); mpz_add(s, i1, i2); mpz_sub(t, i1, i2); mpz_mod(s, s, p); mpz_mod(t, t, p); } TEST_FUNCTION_START(fft_ifft_butterfly_twiddle, state) { mp_size_t c, bits, j, k, n, w, limbs; mpz_t p, ma, mb, m2a, m2b, mn1, mn2; mp_limb_t * nn1, * nn2, * r1, * r2; flint_bitcnt_t b1, b2; _flint_rand_init_gmp(state); mpz_init(p); mpz_init(ma); mpz_init(mb); mpz_init(m2a); mpz_init(m2b); mpz_init(mn1); mpz_init(mn2); for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 0; c < n; c++) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; b1 = n_randint(state, n*w); b2 = n_randint(state, n*w); nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); fft_butterfly_twiddle(r1, r2, nn1, nn2, limbs, b1, b2); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_fft_butterfly_twiddle(ma, mb, mn1, mn2, p, c, w, b1, b2); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("fft_butterfly_twiddle error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("fft_butterfly_twiddle error b\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } for (bits = FLINT_BITS; bits < 20*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 10; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/FLINT_BITS; for (c = 0; c < n; c++) { if (n_randint(state, 100) > 2.0 + flint_test_multiplier() * 10) continue; b1 = n_randint(state, n*w); b2 = n_randint(state, n*w); nn1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); nn2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r1 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r2 = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn1, state, limbs); random_fermat(nn2, state, limbs); fermat_to_mpz(mn1, nn1, limbs); fermat_to_mpz(mn2, nn2, limbs); set_p(p, n, w); ifft_butterfly_twiddle(r1, r2, nn1, nn2, limbs, b1, b2); fermat_to_mpz(m2a, r1, limbs); fermat_to_mpz(m2b, r2, limbs); mpz_mod(m2a, m2a, p); mpz_mod(m2b, m2b, p); ref_ifft_butterfly_twiddle(ma, mb, mn1, mn2, p, c, n, w, b1, b2); if (mpz_cmp(ma, m2a) != 0) { flint_printf("FAIL:\n"); flint_printf("ifft_butterfly_twiddle error a\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", ma); gmp_printf("got %Zx\n", m2a); fflush(stdout); flint_abort(); } if (mpz_cmp(mb, m2b) != 0) { flint_printf("FAIL:\n"); flint_printf("ifft_butterfly_twiddle error b\n"); flint_printf("limbs = %wd\n", limbs); flint_printf("n = %wd, w = %wd, k = %wd, c = %wd\n", n, w, k, c); gmp_printf("want %Zx\n\n", mb); gmp_printf("got %Zx\n", m2b); fflush(stdout); flint_abort(); } flint_free(nn1); flint_free(nn2); flint_free(r1); flint_free(r2); } } } } mpz_clear(p); mpz_clear(ma); mpz_clear(mb); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); mpz_clear(mn2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-convolution.c000066400000000000000000000067661461254215100201630ustar00rootroot00000000000000/* Copyright (C) 2009, 2011, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_convolution, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 13 : (flint_test_multiplier() > 1) ? 12 : 11; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_convolution_precache, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 13 : (flint_test_multiplier() > 1) ? 12 : 11; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif TEST_FUNCTION_START(mpn_div_2expmod_2expp1, state) { flint_bitcnt_t bits; mp_size_t j, k, n, w, limbs, d; mp_limb_t * nn, * r; mpz_t p, m1, m2, mn1, mn2; _flint_rand_init_gmp(state); mpz_init(m1); mpz_init(m2); mpz_init(mn1); mpz_init(mn2); mpz_init(p); /* normalisation mod p = 2^wn + 1 where B divides nw and n is a power of 2 */ for (bits = FLINT_BITS; bits < 16*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 32; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { for (d = 0; d < FLINT_BITS; d++) { n = bits/k; w = j*k; limbs = (n*w)/GMP_LIMB_BITS; nn = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn, state, limbs); fermat_to_mpz(mn1, nn, limbs); set_p(p, n, w); mpn_div_2expmod_2expp1(r, nn, limbs, d); fermat_to_mpz(m2, r, limbs); mpz_mod(m2, m2, p); mpz_mod(m1, mn1, p); mpz_mul_2exp(m2, m2, d); mpz_mod(m2, m2, p); if (mpz_cmp(m1, m2) != 0) { flint_printf("FAIL:\n"); flint_printf("mpn_div_2expmod_2expp1 error\n"); gmp_printf("want %Zx\n\n", m1); gmp_printf("got %Zx\n", m2); fflush(stdout); flint_abort(); } flint_free(nn); flint_free(r); } } } } mpz_clear(mn2); mpz_clear(mn1); mpz_clear(m2); mpz_clear(m1); mpz_clear(p); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-fft_ifft_mfa_truncate_sqrt2.c000066400000000000000000000052661461254215100232500ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_ifft_mfa_truncate_sqrt2, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 13 : (flint_test_multiplier() > 1) ? 12 : 11; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_ifft_negacyclic, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 12 : (flint_test_multiplier() > 1) ? 11 : 10; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_ifft_radix2, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 12 : (flint_test_multiplier() > 1) ? 11 : 10; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_ifft_truncate, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 12 : (flint_test_multiplier() > 1) ? 11 : 10; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_ifft_truncate_sqrt2, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 12 : (flint_test_multiplier() > 1) ? 11 : 10; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif TEST_FUNCTION_START(mpn_mul_2expmod_2expp1, state) { flint_bitcnt_t bits; mp_size_t j, k, n, w, limbs, d; mp_limb_t * nn, * r; mpz_t p, m1, m2, mn1, mn2; _flint_rand_init_gmp(state); mpz_init(m1); mpz_init(m2); mpz_init(mn1); mpz_init(mn2); mpz_init(p); /* normalisation mod p = 2^wn + 1 where B divides nw and n is a power of 2 */ for (bits = FLINT_BITS; bits < 16*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 32; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { for (d = 0; d < FLINT_BITS; d++) { n = bits/k; w = j*k; limbs = (n*w)/GMP_LIMB_BITS; nn = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); r = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn, state, limbs); fermat_to_mpz(mn1, nn, limbs); set_p(p, n, w); mpn_mul_2expmod_2expp1(r, nn, limbs, d); fermat_to_mpz(m2, r, limbs); mpz_mod(m2, m2, p); mpz_mod(m1, mn1, p); mpz_mul_2exp(m1, m1, d); mpz_mod(m1, m1, p); if (mpz_cmp(m1, m2) != 0) { flint_printf("FAIL:\n"); flint_printf("mpn_mul_2expmod_2expp1 error\n"); gmp_printf("want %Zx\n\n", m1); gmp_printf("got %Zx\n", m2); fflush(stdout); flint_abort(); } flint_free(nn); flint_free(r); } } } } mpz_clear(mn2); mpz_clear(mn1); mpz_clear(m2); mpz_clear(m1); mpz_clear(p); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-mul_fft_main.c000066400000000000000000000052541461254215100202330ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(flint_mpn_mul_fft_main, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 12 : (flint_test_multiplier() > 1) ? 11 : 10; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 3 - (depth >= 12); w++) { int iter = 1 + 200*(depth <= 8) + 80*(depth <= 9) + 10*(depth <= 10), i; for (i = 0; i < iter; i++) { mp_size_t n = (UWORD(1)<= b2 */ { mp_size_t t = n1; flint_bitcnt_t tb = b1; n1 = n2; b1 = b2; n2 = t; b2 = tb; } i1 = flint_malloc(3*(n1 + n2)*sizeof(mp_limb_t)); i2 = i1 + n1; r1 = i2 + n2; r2 = r1 + n1 + n2; flint_mpn_urandomb(i1, state->gmp_state, b1); flint_mpn_urandomb(i2, state->gmp_state, b2); mpn_mul(r2, i1, n1, i2, n2); flint_mpn_mul_fft_main(r1, i1, n1, i2, n2); for (j = 0; j < n1 + n2; j++) { if (r1[j] != r2[j]) { flint_printf("error in limb %wd, %wx != %wx\n", j, r1[j], r2[j]); fflush(stdout); flint_abort(); } } flint_free(i1); } } } flint_set_num_threads(1); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-mul_mfa_truncate_sqrt2.c000066400000000000000000000060551461254215100222530ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(mul_mfa_truncate_sqrt2, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() >= 10) ? 13 : (flint_test_multiplier() >= 1) ? 12 : 11; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 3 - (depth >= 12); w++) { mp_size_t n = (UWORD(1)<= 12); w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(mul_truncate_sqrt2, state) { flint_bitcnt_t depth, w, maxdepth; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 12 : (flint_test_multiplier() > 1) ? 11 : 10; for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_mulmod_2expp1, state) { flint_bitcnt_t depth, w, maxdepth; int iters; _flint_rand_init_gmp(state); maxdepth = (flint_test_multiplier() > 10) ? 18 : 15; for (iters = 0; iters < 100; iters++) { for (depth = 6; depth <= maxdepth; depth++) { for (w = 1; w <= 2; w++) { mp_size_t n = (UWORD(1)<. */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif TEST_FUNCTION_START(mpn_negmod_2expp1, state) { flint_bitcnt_t bits; mp_size_t j, k, n, w, limbs; mp_limb_t * a, * z; mpz_t p, z1, z2; _flint_rand_init_gmp(state); mpz_init(z1); mpz_init(z2); mpz_init(p); /* normalisation mod p = 2^wn + 1 where B divides nw and n is a power of 2 */ for (bits = FLINT_BITS; bits < 16*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 32; j++) { for (k = 1; k <= FLINT_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/GMP_LIMB_BITS; set_p(p, n, w); a = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); z = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(a, state, limbs); mpn_normmod_2expp1(a, limbs); mpn_negmod_2expp1(z, a, limbs); fermat_to_mpz(z1, a, limbs); mpz_neg(z1, z1); mpz_mod(z1, z1, p); fermat_to_mpz(z2, z, limbs); if (mpz_cmp(z1, z2) != 0) { flint_printf("FAIL:\n"); flint_printf("mpn_negmod_2expp1 error\n"); gmp_printf("want %Zx\n\n", z1); gmp_printf("got %Zx\n", z2); fflush(stdout); flint_abort(); } flint_free(a); flint_free(z); } } } mpz_clear(p); mpz_clear(z2); mpz_clear(z1); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-normmod_2expp1.c000066400000000000000000000044721461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" #include "fft.h" /* Defined in t-adjust.c, t-adjust_sqrt2.c, t-butterfly.c, t-butterfly_lshB.c, * t-butterfly_rshB.c, t-butterfly_sqrt2.c, t-butterfly_twiddle.c, * t-div_2expmod_2expp1.c, t-mul_2expmod_2expp1.c, t-negmod_2expp1.c, * t-normmod_2expp1.c */ #ifndef set_p #define set_p set_p /* set p = 2^wn + 1 */ void set_p(mpz_t p, mp_size_t n, flint_bitcnt_t w) { flint_mpz_set_ui(p, 1); mpz_mul_2exp(p, p, n*w); flint_mpz_add_ui(p, p, 1); } #endif TEST_FUNCTION_START(mpn_normmod_2expp1, state) { flint_bitcnt_t bits; mp_size_t j, k, n, w, limbs; mp_limb_t * nn; mpz_t p, m1, m2; _flint_rand_init_gmp(state); mpz_init(m1); mpz_init(m2); mpz_init(p); /* normalisation mod p = 2^wn + 1 where B divides nw and n is a power of 2 */ for (bits = FLINT_BITS; bits < 32*FLINT_BITS; bits += FLINT_BITS) { for (j = 1; j < 32; j++) { for (k = 1; k <= GMP_NUMB_BITS; k <<= 1) { n = bits/k; w = j*k; limbs = (n*w)/GMP_LIMB_BITS; nn = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); random_fermat(nn, state, limbs); fermat_to_mpz(m1, nn, limbs); set_p(p, n, w); mpn_normmod_2expp1(nn, limbs); fermat_to_mpz(m2, nn, limbs); mpz_mod(m1, m1, p); if (mpz_cmp(m1, m2) != 0) { flint_printf("FAIL:\n"); flint_printf("mpn_normmod_2expp1 error\n"); gmp_printf("want %Zx\n\n", m1); gmp_printf("got %Zx\n", m2); fflush(stdout); flint_abort(); } flint_free(nn); } } } mpz_clear(m2); mpz_clear(m1); mpz_clear(p); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/test/t-split_combine_bits.c000066400000000000000000000035411461254215100214400ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft.h" TEST_FUNCTION_START(fft_split_combine_bits, state) { int i; mp_size_t j; _flint_rand_init_gmp(state); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_size_t total_limbs = n_randint(state, 1000) + 1; mp_limb_t * in = flint_malloc(total_limbs*sizeof(mp_limb_t)); mp_limb_t * out = flint_calloc(total_limbs, sizeof(mp_limb_t)); flint_bitcnt_t bits = n_randint(state, 200) + 1; mp_size_t limbs = (2*bits - 1)/FLINT_BITS + 1; slong length = (total_limbs*FLINT_BITS - 1)/bits + 1; mp_limb_t ** poly; poly = flint_malloc(length*sizeof(mp_limb_t *)); for (j = 0; j < length; j++) poly[j] = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); flint_mpn_urandomb(in, state->gmp_state, total_limbs*FLINT_BITS); fft_split_bits(poly, in, total_limbs, bits, limbs); fft_combine_bits(out, poly, length, bits, limbs, total_limbs); for (j = 0; j < total_limbs; j++) { if (in[j] != out[j]) { flint_printf("FAIL:\n"); flint_printf("Error in limb %wd, %wu != %wu\n", j, in[j], out[j]); fflush(stdout); flint_abort(); } } flint_free(in); flint_free(out); for (j = 0; j < length; j++) flint_free(poly[j]); flint_free(poly); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fft/tune/000077500000000000000000000000001461254215100151545ustar00rootroot00000000000000flint-3.1.3/src/fft/tune/tune-fft.c000066400000000000000000000122161461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" #include "mpn_extras.h" int main(void) { flint_bitcnt_t depth, w, depth1, w1; clock_t start, end; double elapsed; double best = 0.0; mp_size_t best_off, off, best_d, best_w; FLINT_TEST_INIT(state); flint_printf("/* fft_tuning.h -- autogenerated by tune-fft */\n\n"); flint_printf("#ifndef FFT_TUNING_H\n"); flint_printf("#define FFT_TUNING_H\n\n"); flint_printf("#include \"gmp.h\"\n\n"); flint_printf("#define FFT_TAB \\\n"); fflush(stdout); _flint_rand_init_gmp(state); flint_printf(" { "); fflush(stdout); for (depth = 6; depth <= 10; depth++) { flint_printf("{ "); fflush(stdout); for (w = 1; w <= 2; w++) { int iters = 100*((mp_size_t) 1 << (3*(10 - depth)/2)), i; mp_size_t n = (UWORD(1)<gmp_state, b1); flint_mpn_urandomb(i2, state->gmp_state, b2); best_off = -1; for (off = 0; off <= 4; off++) { start = clock(); for (i = 0; i < iters; i++) mul_truncate_sqrt2(r1, i1, n1, i2, n2, depth - off, w*((mp_size_t)1 << (off*2))); end = clock(); elapsed = ((double) (end - start)) / CLOCKS_PER_SEC; if (elapsed < best || best_off == -1) { best_off = off; best = elapsed; } } flint_printf("%wd", best_off); if (w != 2) flint_printf(","); flint_printf(" "); fflush(stdout); flint_free(i1); } flint_printf("}"); if (depth != 10) flint_printf(","); flint_printf(" "); fflush(stdout); } flint_printf("}\n\n"); best_d = 12; best_w = 1; best_off = -1; flint_printf("#define MULMOD_TAB \\\n"); fflush(stdout); flint_printf(" { "); fflush(stdout); for (depth = 12; best_off != 1 ; depth++) { for (w = 1; w <= 2; w++) { int iters, i; mp_size_t n = (UWORD(1)<gmp_state, int_limbs*FLINT_BITS); flint_mpn_urandomb(i2, state->gmp_state, int_limbs*FLINT_BITS); i1[int_limbs] = 0; i2[int_limbs] = 0; depth1 = FLINT_CLOG2(bits); depth1 = depth1/2; w1 = bits/(UWORD(1)<<(2*depth1)); best_off = -1; for (off = 0; off <= 4; off++) { start = clock(); for (i = 0; i < iters; i++) _fft_mulmod_2expp1(r1, i1, i2, int_limbs, depth1 - off, w1*((mp_size_t)1 << (off*2))); end = clock(); elapsed = ((double) (end - start)) / CLOCKS_PER_SEC; if (best_off == -1 || elapsed < best) { best_off = off; best = elapsed; } } start = clock(); for (i = 0; i < iters; i++) flint_mpn_mulmod_2expp1_basecase(r1, i1, i2, 0, bits, tt); end = clock(); elapsed = ((double) (end - start)) / CLOCKS_PER_SEC; if (elapsed < best) { best_d = depth + (w == 2); best_w = w + 1 - 2*(w == 2); } flint_printf("%wd", best_off); if (w != 2) flint_printf(", "); fflush(stdout); flint_free(i1); } flint_printf(", "); fflush(stdout); } flint_printf("1 }\n\n"); flint_printf("#define FFT_N_NUM %wd\n\n", 2*(depth - 12) + 1); flint_printf("#define FFT_MULMOD_2EXPP1_CUTOFF %wd\n\n", ((mp_limb_t) 1 << best_d)*best_w/(2*FLINT_BITS)); flint_randclear(state); flint_printf("#endif\n"); return 0; } flint-3.1.3/src/fft_small.h000066400000000000000000000344331461254215100155510ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FFT_SMALL_H #define FFT_SMALL_H #include "machine_vectors.h" #define LG_BLK_SZ 8 #define BLK_SZ 256 #define BLK_SHIFT 10 #ifdef __cplusplus extern "C" { #endif /* Check that a modulus n satisfies the assumptions for mulmod documented in machine_vectors.h */ int fft_small_mulmod_satisfies_bounds(ulong n); FLINT_FORCE_INLINE ulong n_pow2(int k) { return UWORD(1) << k; } FLINT_FORCE_INLINE ulong n_min(ulong a, ulong b) { return FLINT_MIN(a, b); } FLINT_FORCE_INLINE ulong n_max(ulong a, ulong b) { return FLINT_MAX(a, b); } FLINT_FORCE_INLINE ulong n_cdiv(ulong a, ulong b) { /* not technically correct because the addition can overflow */ return (a + b - 1)/b; } FLINT_FORCE_INLINE ulong n_round_up(ulong a, ulong b) { return n_cdiv(a, b)*b; } FLINT_FORCE_INLINE ulong n_round_down(ulong a, ulong b) { return a/b*b; } /* 0 -> 0, 1 -> 1, [2,3] -> 3, [4,7] -> 7, [8,15] -> 15, ... */ FLINT_FORCE_INLINE ulong n_next_pow2m1(ulong a) { a |= a >> 1; a |= a >> 2; a |= a >> 4; a |= a >> 8; a |= a >> 16; #if FLINT64 a |= a >> 32; #endif return a; } FLINT_FORCE_INLINE ulong n_leading_zeros(ulong x) { return x == 0 ? FLINT_BITS : flint_clz(x); } FLINT_FORCE_INLINE ulong n_trailing_zeros(ulong x) { return x == 0 ? FLINT_BITS : flint_ctz(x); } /* nbits is a mess without assuming x != 0: on x86 we want 64 - LZCNT on arm we want 64 - CLZ the problem is gcc decided that __builtin_clz is undefined on zero input even though both instructions LZCNT and CLZ are defined assuming x != 0: on x86 we want BSR + 1 */ FLINT_FORCE_INLINE ulong n_nbits(ulong x) { if (x == 0) return 0; return FLINT_BITS - flint_clz(x); } FLINT_FORCE_INLINE ulong n_nbits_nz(ulong x) { FLINT_ASSERT(x != 0); return (flint_clz(x)^(FLINT_BITS-1)) + 1; } FLINT_FORCE_INLINE ulong n_clog2(ulong x) { return (x <= 2) ? (x == 2) : FLINT_BITS - flint_clz(x - 1); } FLINT_FORCE_INLINE ulong n_flog2(ulong x) { return (x <= 2) ? (x == 2) : FLINT_BITS - flint_clz(x); } FLINT_FORCE_INLINE slong z_min(slong a, slong b) {return FLINT_MIN(a, b);} FLINT_FORCE_INLINE slong z_max(slong a, slong b) {return FLINT_MAX(a, b);} int fft_small_mulmod_satisfies_bounds(ulong n); /* The twiddle factors are split across FLINT_BITS tables: [0] = {e(1)} original index 0 [1] = {e(1/4)} original index 1 [2] = {e(1/8), e(3/8)} original index 2,3 [3] = {e(1/16), e(5/16), e(3/16), e(7/16)} original index 4,5,6,7 ... The unallocated ones start out as NULL, and once they are filled in, they never have to move. This simplifies thread safe enlargement but complicates random access into the original table. If j is the index into the original table, the new indices are [j_bits][j_r] where j_bits = nbits(j), j_r = j - 2^(j_bits-1) with the special case j_bits = j_r = 0 for j = 0. The first SD_FFT_CTX_INIT_DEPTH tables are stored consecutively to ease the lookup of small indices, which must currently be at least 4. */ /* for the fft look up of powers of w */ #define SET_J_BITS_AND_J_R(j_bits, j_r, j) \ do { \ if (j == 0) \ { \ j_bits = 0; \ j_r = 0; \ } \ else \ { \ j_bits = n_nbits_nz(j); \ j_r = j - n_pow2(j_bits - 1); \ } \ } while (0) /* for the ifft look up of powers of w^-1: the remainder has to be flipped */ #define SET_J_BITS_AND_J_MR(j_bits, j_mr, j) \ do { \ if (j == 0) \ { \ j_bits = 0; \ j_mr = 0; \ } \ else \ { \ j_bits = n_nbits_nz(j); \ j_mr = n_pow2(j_bits) - 1 - j; \ } \ } while (0) #define SD_FFT_CTX_INIT_DEPTH 12 /* This context is the one expected to sit in a global position */ typedef struct { double p; double pinv; nmod_t mod; ulong primitive_root; ulong blk_sz; volatile ulong w2tab_depth; double* w2tab[FLINT_BITS]; } sd_fft_ctx_struct; typedef sd_fft_ctx_struct sd_fft_ctx_t[1]; /* The local context is expected to be copied and passed to the calculations. */ typedef struct { double* data; double p; double pinv; const double* w2tab[50]; } sd_fft_lctx_struct; typedef sd_fft_lctx_struct sd_fft_lctx_t[1]; /* Points are blocked into blocks of size BLK_SZ. The blocks are mapped into memory with some extra padding for potential cache issues. The 4* keeps things aligned for 4-wide vectors. If this alignment is broken, the load and stores in the fft (unspecified vec4d_load) need to support unaligned addresses. */ FLINT_FORCE_INLINE ulong sd_fft_ctx_blk_offset(ulong I) { return (I << LG_BLK_SZ) + 4*(I >> (BLK_SHIFT+2)); } FLINT_FORCE_INLINE ulong sd_fft_ctx_data_size(ulong depth) { FLINT_ASSERT(depth >= LG_BLK_SZ); return sd_fft_ctx_blk_offset(n_pow2(depth - LG_BLK_SZ)); } FLINT_FORCE_INLINE double* sd_fft_ctx_blk_index(double* d, ulong I) { return d + sd_fft_ctx_blk_offset(I); } FLINT_FORCE_INLINE double* sd_fft_lctx_blk_index(const sd_fft_lctx_t Q, ulong I) { return Q->data + sd_fft_ctx_blk_offset(I); } FLINT_FORCE_INLINE void sd_fft_ctx_set_index(double* d, ulong i, double x) { sd_fft_ctx_blk_index(d, i/BLK_SZ)[i%BLK_SZ] = x; } FLINT_FORCE_INLINE double sd_fft_ctx_get_index(double* d, ulong i) { return sd_fft_ctx_blk_index(d, i/BLK_SZ)[i%BLK_SZ]; } /* slightly-worse-than-bit-reversed order of sd_{i}fft_basecase_4 */ FLINT_FORCE_INLINE double sd_fft_ctx_get_fft_index(double* d, ulong i) { ulong j = i&(BLK_SZ-16); FLINT_ASSERT(BLK_SZ >= 16); j |= (i&3)<<2; j |= ((i>>2)&3); return sd_fft_ctx_blk_index(d, i/BLK_SZ)[j]; } /* sd_fft.c */ void sd_fft_trunc(const sd_fft_lctx_t Q, ulong I, ulong S, ulong k, ulong j, ulong itrunc, ulong otrunc); /* sd_ifft.c */ void sd_ifft_trunc(const sd_fft_lctx_t Q, ulong I, ulong S, ulong k, ulong j, ulong z, ulong n, int f); /* sd_fft_ctx.c */ void sd_fft_ctx_clear(sd_fft_ctx_t Q); void sd_fft_ctx_init_prime(sd_fft_ctx_t Q, ulong pp); void sd_fft_ctx_fit_depth(sd_fft_ctx_t Q, ulong k); /* TODO: these should probably increment/decrement a ref count */ FLINT_FORCE_INLINE void sd_fft_lctx_init(sd_fft_lctx_t L, sd_fft_ctx_t Q, ulong depth) { L->p = Q->p; L->pinv = Q->pinv; sd_fft_ctx_fit_depth(Q, depth); for (int i = 0; i < 50; i++) L->w2tab[i] = Q->w2tab[i]; } FLINT_FORCE_INLINE void sd_fft_lctx_clear(sd_fft_lctx_t LQ, sd_fft_ctx_t Q) { } void sd_fft_lctx_point_mul(const sd_fft_lctx_t Q, double* a, const double* b, ulong m_, ulong depth); void sd_fft_lctx_point_sqr(const sd_fft_lctx_t Q, double* a, ulong m_, ulong depth); FLINT_FORCE_INLINE void sd_fft_lctx_fft_trunc(sd_fft_lctx_t Q, double* d, ulong depth, ulong itrunc, ulong otrunc) { FLINT_ASSERT(depth >= LG_BLK_SZ); FLINT_ASSERT(itrunc % BLK_SZ == 0); FLINT_ASSERT(otrunc % BLK_SZ == 0); FLINT_ASSERT(Q->w2tab[depth - 1] != NULL); Q->data = d; sd_fft_trunc(Q, 0, 1, depth - LG_BLK_SZ, 0, itrunc/BLK_SZ, otrunc/BLK_SZ); } FLINT_FORCE_INLINE void sd_fft_lctx_ifft_trunc(sd_fft_lctx_t Q, double* d, ulong depth, ulong trunc) { FLINT_ASSERT(depth >= LG_BLK_SZ); FLINT_ASSERT(trunc % BLK_SZ == 0); FLINT_ASSERT(Q->w2tab[depth - 1] != NULL); Q->data = d; sd_ifft_trunc(Q, 0, 1, depth - LG_BLK_SZ, 0, trunc/BLK_SZ, trunc/BLK_SZ, 0); } FLINT_FORCE_INLINE void sd_fft_ctx_fft_trunc(sd_fft_ctx_t Q, double* d, ulong depth, ulong itrunc, ulong otrunc) { sd_fft_lctx_t QL; sd_fft_lctx_init(QL, Q, depth); sd_fft_lctx_fft_trunc(QL, d, depth, itrunc, otrunc); } FLINT_FORCE_INLINE void sd_fft_ctx_ifft_trunc(sd_fft_ctx_t Q, double* d, ulong depth, ulong trunc) { sd_fft_lctx_t QL; sd_fft_lctx_init(QL, Q, depth); sd_fft_lctx_ifft_trunc(QL, d, depth, trunc); } /* The bit reversed table is w = {e(0), e(1/2), e(1/4), e(3/4), e(1/8), e(5/8), e(3/8), e(7/8), ...} Only the terms of even index are explicitly stored, and they are split among several tables. */ /* look up w[2*j] */ FLINT_FORCE_INLINE double sd_fft_lctx_w2(const sd_fft_lctx_t Q, ulong j) { ulong j_bits, j_r; SET_J_BITS_AND_J_R(j_bits, j_r, j); return Q->w2tab[j_bits][j_r]; } /* look up -w[2*j]^-1 */ FLINT_FORCE_INLINE double sd_fft_lctx_w2inv(const sd_fft_lctx_t Q, ulong j) { ulong j_bits, j_mr; SET_J_BITS_AND_J_MR(j_bits, j_mr, j); if (j == 0) return -1.0; else return Q->w2tab[j_bits][j_mr]; } /* look up w[jj] */ FLINT_FORCE_INLINE double sd_fft_ctx_w(const sd_fft_ctx_t Q, ulong jj) { ulong j = jj/2, j_bits, j_r; SET_J_BITS_AND_J_R(j_bits, j_r, j); return (jj&1) ? -Q->w2tab[j_bits][j_r] : Q->w2tab[j_bits][j_r]; } typedef struct { ulong prime; ulong coeff_len; ulong nprimes; ulong* data; } crt_data_struct; typedef crt_data_struct crt_data_t[1]; void crt_data_init(crt_data_t C, ulong prime, ulong coeff_len, ulong nprimes); void crt_data_clear(crt_data_t C); /* return mpn of length C->coeff_len */ FLINT_FORCE_INLINE ulong* crt_data_co_prime(const crt_data_t C, ulong i) { FLINT_ASSERT(i < C->nprimes); return C->data + i*C->coeff_len; } FLINT_FORCE_INLINE ulong* _crt_data_co_prime(const crt_data_t C, ulong i, ulong n) { FLINT_ASSERT(i < C->nprimes); FLINT_ASSERT(n == C->coeff_len); return C->data + i*n; } /* return mpn of length C->coeff_len */ FLINT_FORCE_INLINE ulong* crt_data_prod_primes(const crt_data_t C) { return C->data + C->nprimes*C->coeff_len; } /* the reduction of co_prime mod the i^th prime */ FLINT_FORCE_INLINE ulong* crt_data_co_prime_red(const crt_data_t C, ulong i) { FLINT_ASSERT(i < C->nprimes); return C->data + C->nprimes*C->coeff_len + C->coeff_len + i; } typedef void (*to_ffts_func)( sd_fft_ctx_struct* Qffts, double* d, ulong dstride, const ulong* a_, ulong an_, ulong atrunc, const vec4d* two_pow, ulong start_easy, ulong stop_easy, ulong start_hard, ulong stop_hard); typedef struct { ulong np; ulong bits; ulong bn_bound; to_ffts_func to_ffts; } profile_entry_struct; typedef profile_entry_struct profile_entry_t[1]; #define MPN_CTX_NCRTS 8 #define MAX_NPROFILES 20 #define VEC_SZ 4 /* The tables for powers of two each have this fixed length. This has to go up linearly with the max number of primes MPN_CTX_NCRTS involved in chinese remaindering. This length is checked with asserts in the code. */ #define MPN_CTX_TWO_POWER_TAB_SIZE 256 typedef struct { sd_fft_ctx_struct ffts[MPN_CTX_NCRTS]; crt_data_struct crts[MPN_CTX_NCRTS]; /* For each table of tables of powers of two, the whole collection is held in one big buffer and the table is an array of pointer into it. */ vec4d* vec_two_pow_tab[(MPN_CTX_NCRTS + VEC_SZ - 1)/VEC_SZ]; vec4d* vec_two_pow_buffer; double* slow_two_pow_tab[MPN_CTX_NCRTS]; double* slow_two_pow_buffer; profile_entry_struct profiles[MAX_NPROFILES]; ulong profiles_size; void* buffer; ulong buffer_alloc; } mpn_ctx_struct; typedef mpn_ctx_struct mpn_ctx_t[1]; void _convert_block(ulong* Xs, sd_fft_ctx_struct* Rffts, double* d, ulong dstride, ulong np, ulong I); ulong flint_mpn_nbits(const ulong* a, ulong an); int flint_mpn_cmp_ui_2exp(const ulong* a, ulong an, ulong b, ulong e); unsigned char flint_mpn_add_inplace_c(ulong* z, ulong zn, ulong* a, ulong an, unsigned char cf); void mpn_ctx_init(mpn_ctx_t R, ulong p); void mpn_ctx_clear(mpn_ctx_t R); void* mpn_ctx_fit_buffer(mpn_ctx_t R, ulong n); void mpn_ctx_mpn_mul(mpn_ctx_t R, ulong* z, const ulong* a, ulong an, const ulong* b, ulong bn); void _nmod_poly_mul_mid_mpn_ctx( ulong* z, ulong zl, ulong zh, const ulong* a, ulong an, const ulong* b, ulong bn, nmod_t mod, mpn_ctx_t R); void _nmod_poly_divrem_mpn_ctx( ulong* q, ulong* r, const ulong* a, ulong an, const ulong* b, ulong bn, nmod_t mod, mpn_ctx_t R); void _nmod_poly_mul_mid_classical( ulong* z, slong zl, slong zh, const ulong* a, slong an, const ulong* b, slong bn, nmod_t mod); void _nmod_poly_mul_mid( ulong* z, slong zl, slong zh, const ulong* a, slong an, const ulong* b, slong bn, nmod_t mod); typedef struct { ulong depth; ulong N; ulong offset; ulong np; ulong stride; ulong bn; ulong btrunc; double* bbuf; } mul_precomp_struct; void _mul_precomp_init( mul_precomp_struct* M, const ulong * b, ulong bn, ulong btrunc, ulong depth, nmod_t mod, mpn_ctx_t R); FLINT_FORCE_INLINE void _mul_precomp_clear(mul_precomp_struct* M) { flint_aligned_free(M->bbuf); } int _nmod_poly_mul_mid_precomp( ulong* z, ulong zl, ulong zh, const ulong* a, ulong an, mul_precomp_struct* M, nmod_t mod, mpn_ctx_t R); typedef struct { mul_precomp_struct quo_maker[1]; mul_precomp_struct rem_maker[1]; } nmod_poly_divrem_precomp_struct; FLINT_FORCE_INLINE void _nmod_poly_divrem_precomp_clear(nmod_poly_divrem_precomp_struct* M) { _mul_precomp_clear(M->quo_maker); _mul_precomp_clear(M->rem_maker); } void _nmod_poly_divrem_precomp_init( nmod_poly_divrem_precomp_struct* M, const ulong* b, ulong bn, ulong Bn, nmod_t mod, mpn_ctx_t R); int _nmod_poly_divrem_precomp( ulong* q, ulong* r, const ulong* a, ulong an, nmod_poly_divrem_precomp_struct* M, nmod_t mod, mpn_ctx_t R); mpn_ctx_struct * get_default_mpn_ctx(void); void mpn_mul_default_mpn_ctx(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2); void _nmod_poly_mul_mid_default_mpn_ctx(mp_ptr res, slong zl, slong zh, mp_srcptr a, slong an, mp_srcptr b, slong bn, nmod_t mod); int _fmpz_poly_mul_mid_mpn_ctx( fmpz * z, ulong zl, ulong zh, const fmpz * a, ulong an, const fmpz * b, ulong bn, mpn_ctx_t R); int _fmpz_poly_mul_mid_default_mpn_ctx( fmpz * z, slong zl, slong zh, const fmpz * a, slong an, const fmpz * b, slong bn); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fft_small/000077500000000000000000000000001461254215100153715ustar00rootroot00000000000000flint-3.1.3/src/fft_small/default_ctx.c000066400000000000000000000031001461254215100200310ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fft_small.h" FLINT_TLS_PREFIX mpn_ctx_t default_mpn_ctx; FLINT_TLS_PREFIX int default_mpn_ctx_initialized = 0; #define DEFAULT_PRIME UWORD(0x0003f00000000001) void mpn_ctx_cleanup(void) { if (default_mpn_ctx_initialized) { default_mpn_ctx_initialized = 0; mpn_ctx_clear(default_mpn_ctx); } } mpn_ctx_struct * get_default_mpn_ctx(void) { if (!default_mpn_ctx_initialized) { mpn_ctx_init(default_mpn_ctx, DEFAULT_PRIME); flint_register_cleanup_function(mpn_ctx_cleanup); default_mpn_ctx_initialized = 1; } return default_mpn_ctx; } void mpn_mul_default_mpn_ctx(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2) { mpn_ctx_mpn_mul(get_default_mpn_ctx(), r1, i1, n1, i2, n2); } void _nmod_poly_mul_mid_default_mpn_ctx(mp_ptr res, slong zl, slong zh, mp_srcptr a, slong an, mp_srcptr b, slong bn, nmod_t mod) { _nmod_poly_mul_mid_mpn_ctx(res, zl, zh, a, an, b, bn, mod, get_default_mpn_ctx()); } int _fmpz_poly_mul_mid_default_mpn_ctx(fmpz * res, slong zl, slong zh, const fmpz * a, slong an, const fmpz * b, slong bn) { return _fmpz_poly_mul_mid_mpn_ctx(res, zl, zh, a, an, b, bn, get_default_mpn_ctx()); } flint-3.1.3/src/fft_small/doc/000077500000000000000000000000001461254215100161365ustar00rootroot00000000000000flint-3.1.3/src/fft_small/doc/fft.jl000066400000000000000000000162051461254215100172500ustar00rootroot00000000000000# This file contains an illustration of David Harvey's truncated fft fitted # with reduced twiddle factor loads. It also contains ifft_trunc_formula which # prints formulas that are needed in the inverse truncated transform. using Nemo L = 2 Qw,w = PolynomialRing(QQ, "x") K,w = NumberField(w^(2^(L-1))+1, "w") R,X = PolynomialRing(K, vcat([Symbol(:x,i) for i in 0:2^L-1])) function revbits(a::Int, l::Int) @assert 0 <= a < 2^l return evalpoly(2, reverse(digits(a, base=2, pad=l))) end # on input: # x is assumed to have length at least 2^k # x[1+itrunc] ... x[1+2^k-1] are not read and assumed to be zero # on output (checked by an assert): # x[1+otrunc] ... x[1+2^k-1] are not defined # x[1+i] is evalpoly(w^revbits(j*2^k+i,L), x[1:itrunc]) # all accesses to x are offset in the real x by I and strided by S function tfft!(x::Vector, I::Int, S::Int, k::Int, j::Int, itrunc::Int, otrunc::Int) @assert k >= 0 @assert 0 <= itrunc <= 2^k @assert 0 <= otrunc <= 2^k if otrunc < 1 return elseif itrunc < 1 for i in 0:otrunc-1 x[1+I+S*i] = zero(R) end return end # for answer check inx = elem_type(R)[x[1+I+S*i] for i in 0:itrunc-1] if k < 1 return elseif k == 1 ww = w^revbits(2*j+0,L) x0 = 0 < itrunc ? x[1+I+0*S] : zero(R) x1 = 1 < itrunc ? x[1+I+1*S] : zero(R) x[1+I+0*S] = 0 < otrunc ? x0 + ww*x1 : zero(R) x[1+I+1*S] = 1 < otrunc ? x0 - ww*x1 : zero(R) else # any k1 + k2 = k with k1, k2 >= 1 will do k1 = fld(k, 2) k2 = k - k1 n1, n2 = divrem(otrunc, 2^k2) z1, z2 = divrem(itrunc, 2^k2) n1p = n1 + (n2 != 0) z2p = min(2^k2, itrunc) # columns !!! j is not changing in this loop !!! for a in 0:z2p-1 tfft!(x, I + a*S, S*2^k2, k1, j, z1 + (a < z2), n1p) end # rows for b in 0:n1-1 tfft!(x, I + S*b*2^k2, S, k2, j*2^k1 + b, z2p, 2^k2) end if n2 > 0 tfft!(x, I + S*n1*2^k2, S, k2, j*2^k1 + n1, z2p, n2) end end # check answer for i in 0:otrunc-1 if x[1+I+S*i] != evalpoly(R(w^revbits(j*2^k+i,L)), inx) error("error at i = $i with k = $k") end end end #= L = 2^k suppose a[z] = ... = a[L-1] = 0 n <= z 1 <= n + f <= L IFFT(L, zeta, z, n, f; ah[0], ..., ah[n-1], L*a[n], ..., L*a[z-1]) returns with (L*a[0], ..., L*a[n-1]) if f = 0 (L*a[0], ..., L*a[n-1], ah[n]) if f = 1 ifft_trunc_formula generates the input -> output map as a n+f by z matrix. Special case for L = 2: Harvey !!! Here !!! ah[0] = a[0] + a[1] ah[0] = a[0] + w*a[1] ah[1] = zeta*(a[0] - a[1]) ah[1] = a[0] - w*a[1] if n = 2, 2*a[0] = ah[0] + zeta^-1*ah[1] 2*a[0] = ah[0] + ah[1] 2*a[1] = ah[0] - zeta^-1*ah[1] 2*a[1] = (ah[0] - ah[1])*w^-1 if n = 1, f = 1, z = 2 ah[0], 2*a[1] 2*a[0] = 2*ah[0] - 2*a[1] 2*a[0] = 2*ah[0] - w*2*a[1] ah[1] = zeta*(ah[0] - 2*a[1]) ah[1] = ah[0] - w*2*a[1] if n = 1, f = 1, z = 1 2*a[0] = 2*ah[0] ah[1] = zeta*(ah[0]) if n = 0, f = 1, z = 2 ah[0] = (2*a[0] + 2*a[1])/2 if n = 0, f = 1, z = 1 ah[0] = (2*a[0])/2 =# function itfft!(x::Vector, I::Int, S::Int, k::Int, j::Int, z::Int, n::Int, f::Bool) @assert n <= z @assert 1 <= z <= 2^k @assert 1 <= n + f <= 2^k if k < 1 return elseif k == 1 ww = w^revbits(2*j+0,L) if n == 2 u = x[1+I+0*S] v = x[1+I+1*S] x[1+I+0*S] = u + v x[1+I+1*S] = (u - v)*ww^-1 elseif n == 1 u = x[1+I+0*S] v = z == 2 ? x[1+I+1*S] : zero(R) x[1+I+0*S] = 2*u - ww*v if f x[1+I+1*S] = u - ww*v end elseif n == 0 u = x[1+I+0*S] v = z == 2 ? x[1+I+1*S] : zero(R) x[1+I+0*S] = (u + ww*v)*inv(K(2)) else error("case n=$n, f=$f, z=$z not implemented") end else # any k1 + k2 = k with k1, k2 >= 1 will do k1 = fld(k, 2) k2 = k - k1 n1, n2 = divrem(n, 2^k2) z1, z2 = divrem(z, 2^k2) fp = n2 + f > 0 z2p = min(2^k2, z) m = min(n2, z2); mp = max(n2, z2) # complete rows for b in 0:n1-1 itfft!(x, I + S*b*2^k2, S, k2, j*2^k1 + b, 2^k2, 2^k2, false) end # rightmost columns !!! j is not changing in this loop !!! for a in n2:z2p-1 itfft!(x, I + S*a, S*2^k2, k1, j, z1 + (a < mp), n1, fp) end # last partial row if fp itfft!(x, I + S*n1*2^k2, S, k2, j*2^k1 + n1, z2p, n2, f) end # leftmost columns !!! j is not changing in this loop !!! for a in 0:n2-1 itfft!(x, I + S*a, S*2^k2, k1, j, z1 + (a < m), n1 + 1, false) end end end println("-------- fft ----------") for itrunc in 1:2^L @show itrunc for otrunc in 1:2^L x = copy(X) tfft!(x, 0, 1, L, 0, itrunc, otrunc) for i in 0:otrunc-1 @assert x[1+i] == evalpoly(R(w^revbits(i,L)), X[1:itrunc]) end end end println("-------- ifft ---------") for trunc in 1:2^L @show trunc x = copy(X) tfft!(x, 0, 1, L, 0, trunc, trunc) itfft!(x, 0, 1, L, 0, trunc, trunc, false) #show(stdout, "text/plain", x); println(); for i in 0:trunc-1 @assert x[1+i] == 2^L*X[1+i] end end function ifft_trunc_formula(k::Int, n::Int, z::Int, f::Bool) @assert n <= z @assert 1 <= z <= 2^k @assert 1 <= n + f <= 2^k l = 2^k local Qr,r = PolynomialRing(QQ, "r") local K,r = NumberField(r^(2^(k-1)) + 1, "r") local Rwr,w = PolynomialRing(K, "w") r = Rwr(r) local F = FractionField(Rwr) r = F(r) w = F(w) M = zero_matrix(F, l, l) for i in 0:n-1, j in 0:l-1 M[1+i,1+j] = (r^revbits(i,k)*w)^j end for i in n:l-1 M[1+i,1+i] = l end N = zero_matrix(F, n+f, l) for i in 0:n-1 N[1+i,1+i] = l end if f for j in 0:l-1 N[1+n,1+j] = (r^revbits(n,k)*w)^j end end println("\nk = $k, n = $n, z = $z, f = $f") show(stdout, "text/plain", (N*inv(M))[:, 1:z]) println() nothing end println("\n-------- radix 2 --------------------") ifft_trunc_formula(1, 2,2,false) ifft_trunc_formula(1, 1,2,true) ifft_trunc_formula(1, 1,2,false) ifft_trunc_formula(1, 1,1,true) ifft_trunc_formula(1, 1,1,false) println("\n-------- radix 4 (r^2 = -1) ---------") ifft_trunc_formula(2, 4,4,false) ifft_trunc_formula(2, 1,1,false) ifft_trunc_formula(2, 1,1,true) ifft_trunc_formula(2, 2,4,false) ifft_trunc_formula(2, 2,2,false) ifft_trunc_formula(2, 3,3,false) ifft_trunc_formula(2, 3,3,true) ifft_trunc_formula(2, 2,2,true) ifft_trunc_formula(2, 1,4,false) ifft_trunc_formula(2, 3,4,false) ifft_trunc_formula(2, 0,4,true) ifft_trunc_formula(2, 2,4,true) ifft_trunc_formula(2, 3,4,true) ifft_trunc_formula(2, 1,4,true) nothing flint-3.1.3/src/fft_small/fmpz_poly_mul.c000066400000000000000000000430141461254215100204330ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "crt_helpers.h" #include "fft_small.h" static void _mod( double* abuf, ulong atrunc, const fmpz * a, ulong an, slong abits, const sd_fft_ctx_struct* fft) { double* aI; ulong i, j; nmod_t mod = fft->mod; ulong p = mod.n; if (atrunc < an) { flint_throw(FLINT_ERROR, "fft _mod: atrunc < an not handled\n"); } if (FLINT_ABS(abits) < FLINT_BIT_COUNT(p)) { if (abits >= 0) { for (i = 0; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { vec8n t = vec8n_load_unaligned((ulong *) (a + i + j)); FLINT_ASSERT(i+j < atrunc); vec8d_store_aligned(aI + j, vec8n_convert_limited_vec8d(t)); } } aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = a[i + j]; } else { for (i = 0; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { ulong aa[8]; /* todo: vectorize */ aa[0] = a[i + j + 0] >= 0 ? a[i + j + 0] : a[i + j + 0] + p; aa[1] = a[i + j + 1] >= 0 ? a[i + j + 1] : a[i + j + 1] + p; aa[2] = a[i + j + 2] >= 0 ? a[i + j + 2] : a[i + j + 2] + p; aa[3] = a[i + j + 3] >= 0 ? a[i + j + 3] : a[i + j + 3] + p; aa[4] = a[i + j + 4] >= 0 ? a[i + j + 4] : a[i + j + 4] + p; aa[5] = a[i + j + 5] >= 0 ? a[i + j + 5] : a[i + j + 5] + p; aa[6] = a[i + j + 6] >= 0 ? a[i + j + 6] : a[i + j + 6] + p; aa[7] = a[i + j + 7] >= 0 ? a[i + j + 7] : a[i + j + 7] + p; vec8n t = vec8n_load_unaligned(aa); FLINT_ASSERT(i+j < atrunc); vec8d_store_aligned(aI + j, vec8n_convert_limited_vec8d(t)); } } aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = a[i + j] >= 0 ? a[i + j] : a[i + j] + p; } } else if (FLINT_ABS(abits) <= SMALL_FMPZ_BITCOUNT_MAX) { if (abits >= 0) { for (i = 0; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { ulong aa[8]; FLINT_ASSERT(i+j < atrunc); /* todo: vectorize */ aa[0] = nmod_set_ui(a[i + j + 0], mod); aa[1] = nmod_set_ui(a[i + j + 1], mod); aa[2] = nmod_set_ui(a[i + j + 2], mod); aa[3] = nmod_set_ui(a[i + j + 3], mod); aa[4] = nmod_set_ui(a[i + j + 4], mod); aa[5] = nmod_set_ui(a[i + j + 5], mod); aa[6] = nmod_set_ui(a[i + j + 6], mod); aa[7] = nmod_set_ui(a[i + j + 7], mod); vec8n t = vec8n_load_unaligned(aa); vec8d_store_aligned(aI + j, vec8n_convert_limited_vec8d(t)); } } aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = nmod_set_ui(a[i + j], mod); } else { for (i = 0; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { ulong aa[8]; FLINT_ASSERT(i+j < atrunc); /* todo: vectorize */ aa[0] = nmod_set_si(a[i + j + 0], mod); aa[1] = nmod_set_si(a[i + j + 1], mod); aa[2] = nmod_set_si(a[i + j + 2], mod); aa[3] = nmod_set_si(a[i + j + 3], mod); aa[4] = nmod_set_si(a[i + j + 4], mod); aa[5] = nmod_set_si(a[i + j + 5], mod); aa[6] = nmod_set_si(a[i + j + 6], mod); aa[7] = nmod_set_si(a[i + j + 7], mod); vec8n t = vec8n_load_unaligned(aa); vec8d_store_aligned(aI + j, vec8n_convert_limited_vec8d(t)); } } aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = nmod_set_si(a[i + j], mod); } } else { for (i = 0; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { ulong aa[8]; FLINT_ASSERT(i+j < atrunc); /* todo: vectorize? */ aa[0] = fmpz_get_nmod(&a[i + j + 0], mod); aa[1] = fmpz_get_nmod(&a[i + j + 1], mod); aa[2] = fmpz_get_nmod(&a[i + j + 2], mod); aa[3] = fmpz_get_nmod(&a[i + j + 3], mod); aa[4] = fmpz_get_nmod(&a[i + j + 4], mod); aa[5] = fmpz_get_nmod(&a[i + j + 5], mod); aa[6] = fmpz_get_nmod(&a[i + j + 6], mod); aa[7] = fmpz_get_nmod(&a[i + j + 7], mod); vec8n t = vec8n_load_unaligned(aa); vec8d_store_aligned(aI + j, vec8n_convert_limited_vec8d(t)); } } aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = (double) fmpz_get_nmod(&a[i + j], mod); } for (i = an; i < atrunc; i++) sd_fft_ctx_set_index(abuf, i, 0); } void fmpz_neg_ui_array(fmpz_t out, const ulong * in, slong in_len) { slong size = in_len; FLINT_ASSERT(in_len > 0); /* find end of zero extension */ while (size > WORD(1) && in[size - 1] == UWORD(0)) size--; /* copy limbs */ if (size == WORD(1)) { fmpz_neg_ui(out, in[0]); } else { __mpz_struct * mpz = _fmpz_promote(out); if (mpz->_mp_alloc < size) mpz_realloc2(mpz, FLINT_BITS * size); mpz->_mp_size = -size; flint_mpn_copyi(mpz->_mp_d, in, size); } } #define DEFINE_IT(NP, N, M) \ static void CAT(_crt, NP)( \ fmpz * z, ulong zl, ulong zi_start, ulong zi_stop, \ sd_fft_ctx_struct* Rffts, double* d, ulong dstride, \ crt_data_struct* Rcrts) \ { \ ulong np = NP; \ ulong n = N; \ ulong m = M; \ \ FLINT_ASSERT(n == Rcrts[np-1].coeff_len); \ FLINT_ASSERT(1 <= N && N <= 7); \ \ if (n == m + 1) \ { \ for (ulong l = 0; l < np; l++) { \ FLINT_ASSERT(crt_data_co_prime(Rcrts + np - 1, l)[m] == 0); \ } \ } \ else \ { \ FLINT_ASSERT(n == m); \ } \ \ ulong Mhalf[N]; \ mpn_rshift(Mhalf, crt_data_prod_primes(Rcrts + np - 1), N, 1); \ \ ulong Xs[BLK_SZ*NP]; \ \ for (ulong i = n_round_down(zi_start, BLK_SZ); i < zi_stop; i += BLK_SZ) \ { \ _convert_block(Xs, Rffts, d, dstride, np, i/BLK_SZ); \ \ ulong jstart = (i < zi_start) ? zi_start - i : 0; \ ulong jstop = FLINT_MIN(BLK_SZ, zi_stop - i); \ for (ulong j = jstart; j < jstop; j += 1) \ { \ ulong r[N]; \ ulong t[N]; \ ulong l = 0; \ \ CAT3(_big_mul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ for (l++; l < np; l++) \ CAT3(_big_addmul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ \ CAT(_reduce_big_sum, N)(r, t, crt_data_prod_primes(Rcrts + np - 1)); \ \ if (mpn_cmp(r, Mhalf, N) > 0) \ { \ multi_rsub_ ## N(r, crt_data_prod_primes(Rcrts + np - 1)); \ fmpz_neg_ui_array(&z[i+j-zl], r, N); \ } \ else \ fmpz_set_ui_array(&z[i+j-zl], r, N); \ } \ } \ } DEFINE_IT(2, 2, 1) /* 100 bits */ DEFINE_IT(3, 3, 2) /* 150 bits */ DEFINE_IT(4, 4, 3) /* 200 bits */ DEFINE_IT(5, 4, 4) /* 250 bits */ DEFINE_IT(6, 5, 4) /* 300 bits */ DEFINE_IT(7, 6, 5) /* 350 bits */ DEFINE_IT(8, 7, 6) /* 400 bits */ #undef DEFINE_IT /* 50 bits */ static void _crt_1( fmpz * z, ulong zl, ulong zi_start, ulong zi_stop, sd_fft_ctx_struct* Rffts, double* d, ulong dstride, crt_data_struct* Rcrts) { ulong i, j, jstart, jstop; ulong Xs[BLK_SZ*1]; ulong p = Rffts[0].mod.n; for (i = n_round_down(zi_start, BLK_SZ); i < zi_stop; i += BLK_SZ) { _convert_block(Xs, Rffts, d, dstride, 1, i/BLK_SZ); jstart = (i < zi_start) ? zi_start - i : 0; jstop = FLINT_MIN(BLK_SZ, zi_stop - i); for (j = jstart; j < jstop; j += 1) { if (COEFF_IS_MPZ(z[i+j-zl])) _fmpz_clear_mpz(z[i+j-zl]); z[i+j-zl] = (Xs[j] <= p / 2) ? Xs[j] : Xs[j] - p; } } } typedef struct { ulong np; ulong start_pi; ulong stop_pi; ulong offset; double* abuf; double* bbuf; ulong depth; ulong stride; ulong atrunc; ulong btrunc; ulong ztrunc; const fmpz * a; ulong an; slong abits; const fmpz * b; ulong bn; slong bbits; sd_fft_ctx_struct* ffts; crt_data_struct* crts; ulong ioff; int squaring; int want_worker; } s1worker_struct; static void extra_func(void* varg) { s1worker_struct* X = (s1worker_struct*) varg; sd_fft_lctx_t Q; sd_fft_lctx_init(Q, X->ffts + X->ioff, X->depth); _mod(X->bbuf, X->btrunc, X->b, X->bn, X->bbits, X->ffts + X->ioff); sd_fft_lctx_fft_trunc(Q, X->bbuf, X->depth, X->btrunc, X->ztrunc); sd_fft_lctx_clear(Q, X->ffts + X->ioff); } static void s1worker_func(void* varg) { s1worker_struct* X = (s1worker_struct*) varg; sd_fft_lctx_t Q; ulong i, m; thread_pool_handle* handles = NULL; slong nworkers = 0; if (X->want_worker) nworkers = flint_request_threads(&handles, 2); for (i = X->start_pi; i < X->stop_pi; i++) { ulong ioff = i + X->offset; double* abuf = X->abuf + X->stride*i; double* bbuf = X->bbuf; sd_fft_lctx_init(Q, X->ffts + ioff, X->depth); if (!X->squaring) { if (nworkers > 0) { X->ioff = ioff; thread_pool_wake(global_thread_pool, handles[0], 0, extra_func, X); } else { _mod(bbuf, X->btrunc, X->b, X->bn, X->bbits, X->ffts + ioff); sd_fft_lctx_fft_trunc(Q, bbuf, X->depth, X->btrunc, X->ztrunc); } } _mod(abuf, X->atrunc, X->a, X->an, X->abits, X->ffts + ioff); sd_fft_lctx_fft_trunc(Q, abuf, X->depth, X->atrunc, X->ztrunc); if (!X->squaring) { if (nworkers > 0) thread_pool_wait(global_thread_pool, handles[0]); } ulong cop = X->np == 1 ? 1 : *crt_data_co_prime_red(X->crts + X->np - 1, ioff); NMOD_RED2(m, cop >> (FLINT_BITS - X->depth), cop << X->depth, X->ffts[ioff].mod); m = nmod_inv(m, X->ffts[ioff].mod); if (X->squaring) sd_fft_lctx_point_sqr(Q, abuf, m, X->depth); else sd_fft_lctx_point_mul(Q, abuf, bbuf, m, X->depth); sd_fft_lctx_ifft_trunc(Q, abuf, X->depth, X->ztrunc); sd_fft_lctx_clear(Q, X->ffts + ioff); } flint_give_back_threads(handles, nworkers); } typedef struct { fmpz * z; ulong zl; ulong start_zi; ulong stop_zi; double* buf; ulong offset; ulong stride; sd_fft_ctx_struct* ffts; crt_data_struct* crts; nmod_t mod; void (*f)( fmpz * z, ulong zl, ulong zi_start, ulong zi_stop, sd_fft_ctx_struct* Rffts, double* d, ulong dstride, crt_data_struct* Rcrts); } s2worker_struct; static void s2worker_func(void* varg) { s2worker_struct* X = (s2worker_struct*) varg; X->f(X->z, X->zl, X->start_zi, X->stop_zi, X->ffts + X->offset, X->buf, X->stride, X->crts + X->offset); } int _fmpz_poly_mul_mid_mpn_ctx( fmpz * z, ulong zl, ulong zh, const fmpz * a, ulong an, const fmpz * b, ulong bn, mpn_ctx_t R) { ulong modbits; ulong offset = 0; ulong zn = an + bn - 1; ulong atrunc, btrunc, ztrunc; ulong i, np, depth, stride; double* buf; int squaring; slong bits1, bits2; int sign; FLINT_ASSERT(an > 0); FLINT_ASSERT(bn > 0); if (zl >= zh) return 1; if (zh > zn) { if (zl >= zn) { _fmpz_vec_zero(z, zh - zl); return 1; } _fmpz_vec_zero(z + zn - zl, zh - zn); zh = zn; } squaring = (a == b) && (an == bn); bits1 = _fmpz_vec_max_bits(a, an); if (squaring) bits2 = bits1; else bits2 = _fmpz_vec_max_bits(b, bn); sign = (bits1 < 0) || (bits2 < 0); (void) sign; /* should be +sign instead of +1, but currently the CRT code doesn't distinguish between the signed and unsigned cases */ modbits = FLINT_ABS(bits1) + FLINT_ABS(bits2) + 1; FLINT_ASSERT(zl < zh); FLINT_ASSERT(zh <= zn); /* need prod_of_primes >= blen * 2^modbits */ for (np = 1; ; np++) { if (np > MPN_CTX_NCRTS) return 0; if (flint_mpn_cmp_ui_2exp(crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, bn, modbits) >= 0) { break; } } FLINT_ASSERT(0 <= flint_mpn_cmp_ui_2exp( crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, bn, modbits)); atrunc = n_round_up(an, BLK_SZ); btrunc = n_round_up(bn, BLK_SZ); ztrunc = n_round_up(zn, BLK_SZ); /* if there is a power of two 2^d between zh and zn with good wrap around i.e. max(an, bn, zh) <= 2^d <= zn with zn - 2^d <= zl then use d as the depth, otherwise the usual with no wrap around */ depth = n_flog2(zn); i = n_pow2(depth); if (atrunc <= i && btrunc <= i && zh <= i && i <= zn && zn <= zl + i) { ztrunc = i; } else { depth = n_max(LG_BLK_SZ, n_clog2(ztrunc)); } stride = n_round_up(sd_fft_ctx_data_size(depth), 128); ulong want_threads; if ((np >= 2 && bn >= 1000) || (np >= 4 && bn >= 300)) want_threads = np; else want_threads = 1; thread_pool_handle* handles; slong nworkers = flint_request_threads(&handles, want_threads); ulong nthreads = nworkers + 1; buf = (double*) mpn_ctx_fit_buffer(R, (np+nthreads)*stride*sizeof(double)); s1worker_struct s1args[8]; FLINT_ASSERT(nthreads <= 8); for (i = 0; i < nthreads; i++) { s1worker_struct* X = s1args + i; X->np = np; X->start_pi = (i+0)*np/nthreads; X->stop_pi = (i+1)*np/nthreads; X->offset = offset; X->abuf = buf; X->bbuf = buf + (np+i)*stride; X->depth = depth; X->stride = stride; X->atrunc = atrunc; X->btrunc = btrunc; X->ztrunc = ztrunc; X->a = a; X->an = an; X->abits = bits1; X->b = b; X->bn = bn; X->bbits = bits2; X->ffts = R->ffts; X->crts = R->crts; X->squaring = squaring; X->want_worker = !squaring && ((np == 1 && bn > 5000) || (np >= 2 && bn >= 1000)); } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s1worker_func, s1args + i); s1worker_func(s1args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); if (zn > 50000 || (np >= 2 && zn > 20000) || (np >= 4 && zn > 800)) { flint_give_back_threads(handles, nworkers); nworkers = flint_request_threads(&handles, 8); nthreads = nworkers + 1; } s2worker_struct s2args[8]; FLINT_ASSERT(nthreads <= 8); ulong o = zl; for (i = 0; i < nthreads; i++) { s2worker_struct* X = s2args + i; X->z = z; X->zl = zl; X->start_zi = o; ulong newo = n_round_down(zl + (i+1)*(zh-zl)/nthreads, BLK_SZ); o = i+1 < nthreads ? FLINT_MAX(o, newo) : zh; X->stop_zi = o; X->buf = buf; X->offset = offset; X->stride = stride; X->ffts = R->ffts; X->crts = R->crts; X->f = np == 1 ? _crt_1 : np == 2 ? _crt_2 : np == 3 ? _crt_3 : np == 4 ? _crt_4 : np == 5 ? _crt_5 : np == 6 ? _crt_6 : np == 7 ? _crt_7 : _crt_8; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s2worker_func, s2args + i); s2worker_func(s2args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); flint_give_back_threads(handles, nworkers); return 1; } flint-3.1.3/src/fft_small/mpn_helpers.c000066400000000000000000000065001461254215100200520ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fft_small.h" #include "crt_helpers.h" /* transpose a block */ void _convert_block( ulong* Xs, sd_fft_ctx_struct* Rffts, double* d, ulong dstride, ulong np, ulong I) { for (ulong l = 0; l < np; l++) { vec4d p = vec4d_set_d(Rffts[l].p); vec4d pinv = vec4d_set_d(Rffts[l].pinv); double* x = sd_fft_ctx_blk_index(d + l*dstride, I); ulong j = 0; do { vec4d x0, x1, x2, x3; vec4n y0, y1, y2, y3; x0 = vec4d_load(x + j + 0*VEC_SZ); x1 = vec4d_load(x + j + 1*VEC_SZ); x2 = vec4d_load(x + j + 2*VEC_SZ); x3 = vec4d_load(x + j + 3*VEC_SZ); x0 = vec4d_reduce_to_0n(x0, p, pinv); x1 = vec4d_reduce_to_0n(x1, p, pinv); x2 = vec4d_reduce_to_0n(x2, p, pinv); x3 = vec4d_reduce_to_0n(x3, p, pinv); y0 = vec4d_convert_limited_vec4n(x0); y1 = vec4d_convert_limited_vec4n(x1); y2 = vec4d_convert_limited_vec4n(x2); y3 = vec4d_convert_limited_vec4n(x3); vec4n_store_unaligned(Xs + l*BLK_SZ + j + 0*VEC_SZ, y0); vec4n_store_unaligned(Xs + l*BLK_SZ + j + 1*VEC_SZ, y1); vec4n_store_unaligned(Xs + l*BLK_SZ + j + 2*VEC_SZ, y2); vec4n_store_unaligned(Xs + l*BLK_SZ + j + 3*VEC_SZ, y3); } while (j += 4*VEC_SZ, j < BLK_SZ); FLINT_ASSERT(j == BLK_SZ); } } ulong flint_mpn_nbits(const ulong* a, ulong an) { while (an > 0 && a[an-1] == 0) an--; if (an == 0) return 0; return FLINT_BITS*(an - 1) + n_nbits(a[an-1]); } /* cmp(a, b*2^e), a does not have to be normalized */ int flint_mpn_cmp_ui_2exp(const ulong* a, ulong an, ulong b, ulong e) { ulong q = e/FLINT_BITS; ulong r = e%FLINT_BITS; ulong x, b0, b1; while (an > 0 && a[an-1] == 0) an--; if (an == 0) return b != 0; // b*2^e = (b*2^r )*2^(64*q) // = (b0 + b1*2^64)*2^(64*q) if (r == 0) { b0 = b; b1 = 0; } else { b0 = b << r; b1 = b >> (FLINT_BITS - r); } // check words [q+2,infty) // then check words [q+1, 64*q+128) against b1 // then check words [q, q+1) against b0 // then check words [0, q) if (an > q + 2) return 1; x = (q+1 < an) ? a[q+1] : 0; if (x != b1) return x > b1 ? 1 : -1; x = (q < an) ? a[q] : 0; if (x != b0) return x > b0 ? 1 : -1; q = n_min(q, an); while (q > 0) { q--; if (a[q] != 0) return 1; } return 0; } unsigned char flint_mpn_add_inplace_c(ulong* z, ulong zn, ulong* a, ulong an, unsigned char cf) { FLINT_ASSERT(zn >= an); FLINT_ASSERT(an > 0); ulong i = 0; do { cf = _addcarry_ulong(cf, z[i], a[i], &z[i]); } while (i++, i < an); while (i < zn && cf != 0) { cf = _addcarry_ulong(cf, z[i], 0, &z[i]); i++; } return cf; } flint-3.1.3/src/fft_small/mpn_mul.c000066400000000000000000001432551461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "crt_helpers.h" #include "fft_small.h" void crt_data_init(crt_data_t C, ulong prime, ulong coeff_len, ulong nprimes) { C->prime = prime; C->coeff_len = coeff_len; C->nprimes = nprimes; C->data = FLINT_ARRAY_ALLOC(nprimes*coeff_len + coeff_len + nprimes, ulong); } void crt_data_clear(crt_data_t C) { flint_free(C->data); } /* need ceil(64*bn/bits) <= prod_primes/2^(2*bits) i.e. (64*bn+bits-1)/bits <= prod_primes/2^(2*bits) 64*bn <= bits*prod_primes/2^(2*bits) - (bits-1) */ static ulong crt_data_find_bn_bound(const crt_data_t C, ulong bits) { ulong bound = 0; ulong q = (2*bits)/FLINT_BITS; ulong r = (2*bits)%FLINT_BITS; ulong n = C->coeff_len; ulong i; ulong* x; TMP_INIT; TMP_START; x = TMP_ARRAY_ALLOC(n+1, ulong); x[n] = mpn_mul_1(x, crt_data_prod_primes(C), n, bits); if (q < n+1) { if (r > 0) mpn_rshift(x + q, x + q, n + 1 - q, r); if (!mpn_sub_1(x + q, x + q, n + 1 - q, bits - 1)) { mpn_rshift(x + q, x + q, n + 1 - q, 6); bound = (x + q)[0]; for (i = q + 1; i < n + 1; i++) if (x[i] != 0) bound = -UWORD(1); } } TMP_END; return bound; } /* need ceil(64*bn/bits) <= prod_primes/2^(2*bits) first try bits = (nbits(prod_primes) - nbits(bn))/2 then adjust also require bits > 64 for some applications below */ static ulong crt_data_find_bits(const crt_data_t C, ulong bn) { ulong p_nbits = flint_mpn_nbits(crt_data_prod_primes(C), C->coeff_len); ulong bits = n_max(66, (p_nbits - n_nbits(bn))/2); if (bn > crt_data_find_bn_bound(C, bits)) { do { bits -= 1; } while (bits > 65 && bn > crt_data_find_bn_bound(C, bits)); } else { while (bn <= crt_data_find_bn_bound(C, bits + 1)) { bits += 1; } } FLINT_ASSERT(bits > 64 && bn <= crt_data_find_bn_bound(C, bn)); return bits; } #define aindex(i) (a[i]) #if 0 void slow_mpn_to_fft_easy( sd_fft_lctx_t Q, double* z, const uint32_t* a, ulong iq_stop_easy, ulong bits, const double* two_pow) { vec8d p = vec8d_set_d(Q->p); vec8d pinv = vec8d_set_d(Q->pinv); ulong s = BLK_SZ/8/32*bits; FLINT_ASSERT(64 < bits); __m256i tab[256]; for (ulong iq = 0; iq < iq_stop_easy; iq++) { double* zI = sd_fft_ctx_blk_index(z, iq); const uint32_t* aa = a + iq*(BLK_SZ/32)*bits; ulong k = 0; /* transposing this block all at once first is faster than gathering it in the loop */ #if 1 do { __m256i A, B, C, D, E, F, G, H, X0, X1, Y0, Y1, Z0, Z1, W0, W1, P, Q, R, S, T, U, V, W; A = _mm256_loadu_si256((const __m256i*) (aa + k + 0*s)); B = _mm256_loadu_si256((const __m256i*) (aa + k + 1*s)); C = _mm256_loadu_si256((const __m256i*) (aa + k + 2*s)); D = _mm256_loadu_si256((const __m256i*) (aa + k + 3*s)); E = _mm256_loadu_si256((const __m256i*) (aa + k + 4*s)); F = _mm256_loadu_si256((const __m256i*) (aa + k + 5*s)); G = _mm256_loadu_si256((const __m256i*) (aa + k + 6*s)); H = _mm256_loadu_si256((const __m256i*) (aa + k + 7*s)); X0 = _mm256_unpacklo_epi32(A, B); // a0 b0 | a1 b1 | a4 b4 | a5 b5 Y0 = _mm256_unpacklo_epi32(C, D); // c0 d0 | c1 d1 | c4 d4 | c5 d5 Z0 = _mm256_unpacklo_epi32(E, F); // e0 f0 | e1 f1 | e4 f4 | e5 f5 W0 = _mm256_unpacklo_epi32(G, H); // g0 h0 | g1 h1 | g4 h4 | g5 h5 X1 = _mm256_unpackhi_epi32(A, B); // a2 b2 | a3 b3 | a6 b6 | a7 b7 Y1 = _mm256_unpackhi_epi32(C, D); // c2 d2 | c3 d3 | c6 d6 | c7 d7 Z1 = _mm256_unpackhi_epi32(E, F); // e2 f2 | e3 f3 | e6 f6 | e7 f7 W1 = _mm256_unpackhi_epi32(G, H); // g2 h2 | g3 h3 | g6 h6 | g7 h7 P = _mm256_unpacklo_epi64(X0, Y0); // a0 b0 | c0 d0 | a4 b4 | c4 d4 Q = _mm256_unpackhi_epi64(X0, Y0); // a1 b1 | c1 d1 | a5 b5 | c5 d5 R = _mm256_unpacklo_epi64(Z0, W0); // e0 f0 | g0 h0 | e4 f4 | g4 h4 S = _mm256_unpackhi_epi64(Z0, W0); // e1 f1 | g1 h1 | e5 f5 | g5 h5 T = _mm256_unpacklo_epi64(X1, Y1); // a2 b2 | c2 d2 | a6 b6 | c6 d6 U = _mm256_unpackhi_epi64(X1, Y1); // a3 b3 | c3 d3 | a7 b7 | c7 d7 V = _mm256_unpacklo_epi64(Z1, W1); // e2 f2 | g2 h2 | e6 f6 | g6 h6 W = _mm256_unpackhi_epi64(Z1, W1); // e3 f3 | g3 h3 | e7 f7 | g7 h7 tab[k+0] = _mm256_permute2x128_si256(P, R, 0 + 16*2); tab[k+4] = _mm256_permute2x128_si256(P, R, 1 + 16*3); tab[k+1] = _mm256_permute2x128_si256(Q, S, 0 + 16*2); tab[k+5] = _mm256_permute2x128_si256(Q, S, 1 + 16*3); tab[k+2] = _mm256_permute2x128_si256(T, V, 0 + 16*2); tab[k+6] = _mm256_permute2x128_si256(T, V, 1 + 16*3); tab[k+3] = _mm256_permute2x128_si256(U, W, 0 + 16*2); tab[k+7] = _mm256_permute2x128_si256(U, W, 1 + 16*3); } while (k += 8, k + 8 <= s); #endif while (k < s) { tab[k] = _mm256_set_epi32(aa[k + 7*s], aa[k + 6*s], aa[k + 5*s], aa[k + 4*s], aa[k + 3*s], aa[k + 2*s], aa[k + 1*s], aa[k + 0*s]); k++; } for (ulong ir = 0; ir < BLK_SZ/8; ir++) { ulong k = (ir*bits)/32; ulong j = (ir*bits)%32; __m256i AK = tab[k];/*_mm256_i32gather_epi32((const int*)aa+k, index, 4);*/ __m256i AKJ = _mm256_srl_epi32(AK, _mm_set_epi32(0,0,0,j)); vec8d ak = _vec8i32_convert_vec8d(AKJ); vec8d X = ak; k++; j = 32 - j; do { AK = tab[k];/*_mm256_i32gather_epi32((const int*)aa+k, index, 4);*/ AKJ = AK; ak = _vec8i32_convert_vec8d(AKJ); X = vec8d_add(X, vec8d_mulmod(ak, vec8d_set_d(two_pow[j]), p, pinv)); k++; j += 32; } while (j + 32 <= bits); if ((bits-j) != 0) { AK = tab[k];/*_mm256_i32gather_epi32((const int*)aa+k, index, 4);*/ AKJ = _mm256_sll_epi32(AK, _mm_set_epi32(0,0,0,32-(bits-j))); ak = _vec8i32_convert_vec8d(AKJ); X = vec8d_add(X, vec8d_mulmod(ak, vec8d_set_d(two_pow[bits - 32]), p, pinv)); k++; } X = vec8d_reduce_to_pm1n(X, p, pinv); /* _vec8i32_convert_vec8d make the Xs slightly out of order */ zI[ir+0*BLK_SZ/8] = X.e1[0]; zI[ir+1*BLK_SZ/8] = X.e1[1]; zI[ir+4*BLK_SZ/8] = X.e1[2]; zI[ir+5*BLK_SZ/8] = X.e1[3]; zI[ir+2*BLK_SZ/8] = X.e2[0]; zI[ir+3*BLK_SZ/8] = X.e2[1]; zI[ir+6*BLK_SZ/8] = X.e2[2]; zI[ir+7*BLK_SZ/8] = X.e2[3]; } } } #else void slow_mpn_to_fft_easy( sd_fft_lctx_t Q, double* z, const uint32_t* a, ulong iq_stop_easy, ulong bits, const double* two_pow) { vec8d p = vec8d_set_d(Q->p); vec8d pinv = vec8d_set_d(Q->pinv); for (ulong iq = 0; iq < iq_stop_easy; iq++) { double* zI = sd_fft_ctx_blk_index(z, iq); for (ulong ir = 0; ir < BLK_SZ/8; ir++) { ulong k = iq*(BLK_SZ/32)*bits + (ir*bits)/32; ulong j = (ir*bits)%32; vec8d ak = vec8d_set_d8(aindex(k+0*BLK_SZ/8/32*bits) >> j, aindex(k+1*BLK_SZ/8/32*bits) >> j, aindex(k+2*BLK_SZ/8/32*bits) >> j, aindex(k+3*BLK_SZ/8/32*bits) >> j, aindex(k+4*BLK_SZ/8/32*bits) >> j, aindex(k+5*BLK_SZ/8/32*bits) >> j, aindex(k+6*BLK_SZ/8/32*bits) >> j, aindex(k+7*BLK_SZ/8/32*bits) >> j); vec8d X = ak; k++; j = 32 - j; while (j + 32 <= bits) { ak = vec8d_set_d8(aindex(k+0*BLK_SZ/8/32*bits), aindex(k+1*BLK_SZ/8/32*bits), aindex(k+2*BLK_SZ/8/32*bits), aindex(k+3*BLK_SZ/8/32*bits), aindex(k+4*BLK_SZ/8/32*bits), aindex(k+5*BLK_SZ/8/32*bits), aindex(k+6*BLK_SZ/8/32*bits), aindex(k+7*BLK_SZ/8/32*bits)); X = vec8d_add(X, vec8d_mulmod(ak, vec8d_set_d(two_pow[j]), p, pinv)); k++; j += 32; } if ((bits-j) != 0) { ak = vec8d_set_d8(aindex(k+0*BLK_SZ/8/32*bits) << (32-(bits-j)), aindex(k+1*BLK_SZ/8/32*bits) << (32-(bits-j)), aindex(k+2*BLK_SZ/8/32*bits) << (32-(bits-j)), aindex(k+3*BLK_SZ/8/32*bits) << (32-(bits-j)), aindex(k+4*BLK_SZ/8/32*bits) << (32-(bits-j)), aindex(k+5*BLK_SZ/8/32*bits) << (32-(bits-j)), aindex(k+6*BLK_SZ/8/32*bits) << (32-(bits-j)), aindex(k+7*BLK_SZ/8/32*bits) << (32-(bits-j))); X = vec8d_add(X, vec8d_mulmod(ak, vec8d_set_d(two_pow[bits-32]), p, pinv)); } X = vec8d_reduce_to_pm1n(X, p, pinv); zI[ir+0*BLK_SZ/8] = vec8d_get_index(X, 0); zI[ir+1*BLK_SZ/8] = vec8d_get_index(X, 1); zI[ir+2*BLK_SZ/8] = vec8d_get_index(X, 2); zI[ir+3*BLK_SZ/8] = vec8d_get_index(X, 3); zI[ir+4*BLK_SZ/8] = vec8d_get_index(X, 4); zI[ir+5*BLK_SZ/8] = vec8d_get_index(X, 5); zI[ir+6*BLK_SZ/8] = vec8d_get_index(X, 6); zI[ir+7*BLK_SZ/8] = vec8d_get_index(X, 7); } } } #endif #undef aindex void slow_mpn_to_fft( sd_fft_lctx_t Q, double* z, ulong ztrunc, const ulong* a_, ulong an_, ulong bits, const double* two_pow) { const uint32_t* a = (const uint32_t*)(a_); ulong an = 2*an_; ulong iq, i_stop_easy, iq_stop_easy; /* the highest index read from two_pow is bits - 32 */ FLINT_ASSERT(bits - 32 < MPN_CTX_TWO_POWER_TAB_SIZE); /* if i*bits + 32 < 32*an, then the index into a is always in bounds */ i_stop_easy = n_min(ztrunc, (32*an - 33)/bits); iq_stop_easy = i_stop_easy/BLK_SZ; slow_mpn_to_fft_easy(Q, z, a, iq_stop_easy, bits, two_pow); /* now the hard ones */ { vec1d p = vec1d_set_d(Q->p); vec1d pinv = vec1d_set_d(Q->pinv); #define aindex(i) (((i) < an) ? a[i] : (uint32_t)(0)) for (iq = iq_stop_easy; iq < ztrunc/BLK_SZ; iq++) { double* zI = sd_fft_ctx_blk_index(z, iq); for (ulong ir = 0; ir < BLK_SZ; ir++) { ulong k = ((iq*BLK_SZ+ir)*bits)/32; ulong j = ((iq*BLK_SZ+ir)*bits)%32; vec1d ak = vec1d_set_d(aindex(k) >> j); vec1d X = ak; k++; j = 32 - j; while (j + 32 <= bits) { ak = vec1d_set_d(aindex(k)); X = vec1d_add(X, vec1d_mulmod(ak, two_pow[j], p, pinv)); k++; j += 32; } if ((bits-j) != 0) { ak = vec1d_set_d(aindex(k) << (32-(bits-j))); X = vec1d_add(X, vec1d_mulmod(ak, two_pow[bits-32], p, pinv)); } X = vec1d_reduce_to_pm1n(X, p, pinv); zI[ir] = X; } } #undef aindex } } #define aindex(i) (((i) < an) ? a[i] : (uint32_t)(0)) #define N_CDIV(a, b) (((a) + (b) - 1) / (b)) #define DEFINE_IT(NP) \ FLINT_STATIC_NOINLINE void CAT(mpn_to_ffts_hard, NP)( \ sd_fft_ctx_struct* Rffts, double* d, ulong dstride, \ const uint32_t* a, ulong an, ulong atrunc, \ const vec4d* two_pow, \ ulong start_hard, ulong stop_hard, \ ulong bits) \ { \ ulong np = NP; \ ulong nvs = N_CDIV(NP, VEC_SZ); \ vec4d X[N_CDIV(NP, VEC_SZ)]; \ vec4d P[N_CDIV(NP, VEC_SZ)]; \ vec4d PINV[N_CDIV(NP, VEC_SZ)]; \ \ for (ulong l = 0; l < nvs; l++) \ { \ P[l] = vec4d_set_d4(Rffts[4*l+0].p, Rffts[4*l+1].p, Rffts[4*l+2].p, Rffts[4*l+3].p); \ PINV[l] = vec4d_set_d4(Rffts[4*l+0].pinv, Rffts[4*l+1].pinv, Rffts[4*l+2].pinv, Rffts[4*l+3].pinv); \ } \ \ for (ulong i = start_hard; i < stop_hard; i++) \ { \ ulong k = (i*bits)/32; \ ulong j = (i*bits)%32; \ \ vec4d ak = vec4d_set_d((double)(aindex(k) >> j)); \ for (ulong l = 0; l < nvs; l++) \ X[l] = ak; \ k++; \ j = 32 - j; \ while (j + 32 <= bits) \ { \ ak = vec4d_set_d((double)(aindex(k))); \ for (ulong l = 0; l < nvs; l++) \ X[l] = vec4d_add(X[l], vec4d_mulmod(ak, two_pow[j*nvs+l], P[l], PINV[l])); \ k++; \ j += 32; \ } \ \ if ((bits-j) != 0) \ { \ ak = vec4d_set_d((double)(aindex(k) << (32-(bits-j)))); \ for (ulong l = 0; l < nvs; l++) \ X[l] = vec4d_add(X[l], vec4d_mulmod(ak, two_pow[(bits-32)*nvs+l], P[l], PINV[l])); \ } \ \ for (ulong l = 0; l < nvs; l++) \ X[l] = vec4d_reduce_to_pm1n(X[l], P[l], PINV[l]); \ \ for (ulong l = 0; l < np; l++) \ sd_fft_ctx_set_index(d + l*dstride, i, vec4d_get_index(X[l/VEC_SZ], l%VEC_SZ)); \ } \ \ for (ulong l = 0; l < np; l++) \ for (ulong i = stop_hard; i < atrunc; i++) \ sd_fft_ctx_set_index(d + l*dstride, i, 0.0); \ } DEFINE_IT(4) DEFINE_IT(5) DEFINE_IT(6) DEFINE_IT(7) DEFINE_IT(8) #undef DEFINE_IT #undef aindex #undef N_CDIV #define CODE(ir) \ { \ ulong k = ((i+ir)*bits)/32; \ ulong j = (( ir)*bits)%32; \ \ vec4d ak = vec4d_set_d((double)(a[k] >> j)); \ for (ulong l = 0; l < nvs; l++) \ X[l] = ak; \ k++; \ j = 32 - j; \ while (j + 32 <= bits) \ { \ ak = vec4d_set_d((double)(a[k])); \ for (ulong l = 0; l < nvs; l++) \ X[l] = vec4d_add(X[l], vec4d_mulmod(ak, two_pow[j*nvs+l], P[l], PINV[l])); \ k++; \ j += 32; \ } \ \ if ((bits-j) != 0) \ { \ ak = vec4d_set_d((double)(a[k] << (32-(bits-j)))); \ for (ulong l = 0; l < nvs; l++) \ X[l] = vec4d_add(X[l], vec4d_mulmod(ak, two_pow[(bits-32)*nvs+l], P[l], PINV[l])); \ } \ \ for (ulong l = 0; l < nvs; l++) \ X[l] = vec4d_reduce_to_pm1n(X[l], P[l], PINV[l]); \ \ for (ulong l = 0; l < np; l++) \ sd_fft_ctx_set_index(d + l*dstride, i+ir, vec4d_get_index(X[l/VEC_SZ], l%VEC_SZ)); \ } #define N_CDIV(a, b) (((a) + (b) - 1) / (b)) /* The the l^th fft ctx Rffts[l] is expected to have data at d + l*dstride */ #define DEFINE_IT(NP, BITS) \ static void CAT3(mpn_to_ffts, NP, BITS)( \ sd_fft_ctx_struct* Rffts, double* d, ulong dstride, \ const ulong* a_, ulong an_, ulong atrunc, \ const vec4d* two_pow, \ ulong start_easy, ulong stop_easy, \ ulong start_hard, ulong stop_hard) \ { \ ulong np = NP; \ ulong bits = BITS; \ ulong nvs = N_CDIV(NP, VEC_SZ); \ \ FLINT_ASSERT(bits >= FLINT_BITS); \ FLINT_ASSERT(bits - 32 < MPN_CTX_TWO_POWER_TAB_SIZE); \ \ const uint32_t* a = (const uint32_t*)(a_); \ ulong an = 2*an_; \ \ vec4d X[N_CDIV(NP, VEC_SZ)]; \ vec4d P[N_CDIV(NP, VEC_SZ)]; \ vec4d PINV[N_CDIV(NP, VEC_SZ)]; \ \ for (ulong l = 0; l < nvs; l++) \ { \ P[l] = vec4d_set_d4(Rffts[4*l+0].p, Rffts[4*l+1].p, Rffts[4*l+2].p, Rffts[4*l+3].p); \ PINV[l] = vec4d_set_d4(Rffts[4*l+0].pinv, Rffts[4*l+1].pinv, Rffts[4*l+2].pinv, Rffts[4*l+3].pinv); \ } \ \ if ((bits % 8) == 0) \ { \ FLINT_ASSERT(start_easy % 4 == 0); \ FLINT_ASSERT(stop_easy % 4 == 0); \ for (ulong i = start_easy ; i < stop_easy; i += 4) \ { \ CODE(0);CODE(1);CODE(2);CODE(3); \ } \ } \ else if ((bits % 4) == 0) \ { \ FLINT_ASSERT(start_easy % 8 == 0); \ FLINT_ASSERT(stop_easy % 8 == 0); \ for (ulong i = start_easy ; i < stop_easy; i += 8) \ { \ CODE(0);CODE(1);CODE(2);CODE(3); \ CODE(4);CODE(5);CODE(6);CODE(7); \ } \ } \ else if ((bits % 2) == 0) \ { \ FLINT_ASSERT(start_easy % 16 == 0); \ FLINT_ASSERT(stop_easy % 16 == 0); \ for (ulong i = start_easy ; i < stop_easy; i += 16) \ { \ CODE(0);CODE(1);CODE(2);CODE(3); \ CODE(4);CODE(5);CODE(6);CODE(7); \ CODE(8);CODE(9);CODE(10);CODE(11); \ CODE(12);CODE(13);CODE(14);CODE(15); \ } \ } \ else \ { \ FLINT_ASSERT(0); \ } \ \ CAT(mpn_to_ffts_hard, NP)(Rffts, d, dstride, a, an, atrunc, two_pow, \ start_hard, stop_hard, bits); \ } DEFINE_IT(4, 84) DEFINE_IT(4, 88) DEFINE_IT(4, 92) DEFINE_IT(5,112) DEFINE_IT(5,116) DEFINE_IT(5,120) DEFINE_IT(6,136) DEFINE_IT(6,140) DEFINE_IT(6,144) DEFINE_IT(7,160) DEFINE_IT(7,164) DEFINE_IT(7,168) DEFINE_IT(8,184) DEFINE_IT(8,188) DEFINE_IT(8,192) #undef DEFINE_IT #undef CODE #undef aindex #undef N_CDIV #define DEFINE_IT(n, n_plus_1) \ FLINT_FORCE_INLINE void CAT(_add_to_answer_easy, n)(ulong z[], ulong r[], ulong zn, ulong toff, ulong tshift) \ { \ FLINT_ASSERT(zn > toff); \ if (tshift == 0) \ { \ CAT(multi_add, n)(z + toff, r); \ } \ else \ { \ r[n] = r[n-1] >> (64-tshift); \ for (ulong k = n; k >= 2; k--) \ r[k-1] = (r[k-1] << (tshift)) | (r[k-2] >> (64-tshift)); \ r[0] = r[0] << (tshift); \ CAT(multi_add, n_plus_1)(z + toff, r); \ } \ } \ FLINT_FORCE_INLINE void CAT(_add_to_answer_hard, n)(ulong z[], ulong r[], ulong zn, ulong toff, ulong tshift) \ { \ FLINT_ASSERT(zn > toff); \ if (tshift == 0) \ { \ if (zn - toff >= n) \ { \ CAT(multi_add, n)(z + toff, r); \ return; \ } \ } \ else \ { \ r[n] = r[n-1] >> (64-tshift); \ for (ulong k = n; k >= 2; k--) \ r[k-1] = (r[k-1] << (tshift)) | (r[k-2] >> (64-tshift)); \ r[0] = r[0] << (tshift); \ if (zn - toff > n) \ { \ CAT(multi_add, n_plus_1)(z + toff, r); \ return; \ } \ } \ FLINT_ASSERT(zn - toff <= n); \ mpn_add_n(z + toff, z + toff, r, zn - toff); \ } DEFINE_IT(4, 5) DEFINE_IT(5, 6) DEFINE_IT(6, 7) DEFINE_IT(7, 8) #undef DEFINE_IT typedef void (*from_ffts_func)( ulong* z, ulong zn, ulong zlen, sd_fft_ctx_struct* Rffts, double* d, ulong dstride, crt_data_struct* Rcrts, ulong bits, ulong start_easy, ulong stop_easy, ulong* overhang); /* The "n" here is the limb count Rcrts[np-1].coeff_len, which is big enough to hold (product of primes)*(number of primes), so it can hold the intermediate dot products f[0]*x[0] + ... + f[np-1]*x[np-1]. The x[i] are single limb and the f[i] are of length "m". The number of primes is "np". The coefficient of X^i, 0 <= i < zlen needs to be reconstructed and added to the answer mpn (z, zn). This involves the limbs z[floor(i*bits/64)] ... z[floor(i*bits/64)+n] so is easy if floor(i*bits/64)+n < zn. The the l^th fft ctx Rffts[l] is expected to have data at d + l*dstride if overhang = NULL handle output coefficients from [start_easy, zlen) end_easy is still expected to be valid if overhang != NULL overhang has space for n words handle output coefficients from [start_easy, end_easy) where start_easy and stop_easy are divisible by BLK_SZ write to output words [start_easy*bits/64, stop_easy*bits/64) [overhang+0, overhang+n) */ #define DEFINE_IT(NP, N, M) \ static void CAT(_mpn_from_ffts, NP)( \ ulong* z, ulong zn, ulong zlen, \ sd_fft_ctx_struct* Rffts, double* d, ulong dstride, \ crt_data_struct* Rcrts, \ ulong bits, \ ulong start_easy, ulong stop_easy, \ ulong* overhang) \ { \ ulong np = NP; \ ulong n = N; \ ulong m = M; \ ulong zn_start = start_easy*bits/64; \ ulong zn_stop = (overhang == NULL) ? zn : stop_easy*bits/64; \ \ FLINT_ASSERT(n == Rcrts[np-1].coeff_len); \ FLINT_ASSERT(start_easy <= stop_easy); \ \ if (n == m + 1) \ { \ for (ulong l = 0; l < np; l++) { \ FLINT_ASSERT(crt_data_co_prime(Rcrts + np - 1, l)[m] == 0); \ } \ } \ else \ { \ FLINT_ASSERT(n == m); \ } \ \ memset(z + zn_start, 0, (zn_stop - zn_start)*sizeof(ulong)); \ \ ulong Xs[BLK_SZ*NP]; \ \ if (overhang != NULL) \ { \ for (ulong i = 0; i < n; i++) \ overhang[i] = 0; \ if (start_easy >= stop_easy) \ return; \ stop_easy -= BLK_SZ; \ } \ \ for (ulong i = start_easy; i < stop_easy; i += BLK_SZ) \ { \ _convert_block(Xs, Rffts, d, dstride, np, i/BLK_SZ); \ \ for (ulong j = 0; j < BLK_SZ; j += 1) \ { \ ulong r[N + 1]; \ ulong t[N + 1]; \ ulong l = 0; \ \ CAT3(_big_mul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ for (l++; l < np; l++) \ CAT3(_big_addmul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ \ CAT(_reduce_big_sum, N)(r, t, crt_data_prod_primes(Rcrts + np - 1)); \ \ ulong toff = ((i+j)*bits)/FLINT_BITS; \ ulong tshift = ((i+j)*bits)%FLINT_BITS; \ \ FLINT_ASSERT(zn_stop > n + toff); \ \ CAT(_add_to_answer_easy, N)(z, r, zn_stop, toff, tshift); \ } \ } \ \ if (overhang != NULL) \ { \ ulong i = stop_easy; \ _convert_block(Xs, Rffts, d, dstride, np, i/BLK_SZ); \ \ for (ulong j = 0; j < BLK_SZ; j += 1) \ { \ ulong r[N + 1]; \ ulong t[N + 1]; \ ulong l = 0; \ \ CAT3(_big_mul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ for (l++; l < np; l++) \ CAT3(_big_addmul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ \ CAT(_reduce_big_sum, N)(r, t, crt_data_prod_primes(Rcrts + np - 1)); \ \ ulong toff = ((i+j)*bits)/FLINT_BITS; \ ulong tshift = ((i+j)*bits)%FLINT_BITS; \ \ if (n + toff < zn_stop) \ { \ CAT(_add_to_answer_easy, N)(z, r, zn_stop, toff, tshift); \ } \ else \ { \ if (tshift == 0) \ { \ r[n] = 0; \ } \ else \ { \ r[n] = r[n-1] >> (64-tshift); \ for (ulong k = n; k >= 2; k--) \ r[k-1] = (r[k-1] << (tshift)) | (r[k-2] >> (64-tshift)); \ r[0] = r[0] << (tshift); \ } \ /* add zn_stop - toff words to the answer */ \ /* and n + 1 + toff - zn_stop words to the overhang */ \ unsigned char cf = 0; \ ulong k = 0; \ for (; k < zn_stop - toff; k++) \ cf = _addcarry_ulong(cf, z[toff + k], r[k], &z[toff + k]); \ for (; k <= n; k++) \ cf = _addcarry_ulong(cf, overhang[k-(zn_stop-toff)], r[k], &overhang[k-(zn_stop-toff)]); \ } \ } \ } \ else \ { \ for (ulong i = stop_easy; i < zlen; i++) \ { \ ulong r[N + 1]; \ ulong t[N + 1]; \ ulong l = 0; \ double xx = sd_fft_ctx_get_index(d + l*dstride, i); \ ulong x = vec1d_reduce_to_0n(xx, Rffts[l].p, Rffts[l].pinv); \ \ CAT3(_big_mul, N, M)(r, t, crt_data_co_prime(Rcrts + np - 1, l), x); \ for (l++; l < np; l++) \ { \ xx = sd_fft_ctx_get_index(d + l*dstride, i); \ x = vec1d_reduce_to_0n(xx, Rffts[l].p, Rffts[l].pinv); \ CAT3(_big_addmul, N, M)(r, t, crt_data_co_prime(Rcrts + np - 1, l), x); \ } \ \ CAT(_reduce_big_sum, N)(r, t, crt_data_prod_primes(Rcrts + np - 1)); \ \ ulong toff = (i*bits)/FLINT_BITS; \ ulong tshift = (i*bits)%FLINT_BITS; \ \ if (toff >= zn) \ break; \ \ CAT(_add_to_answer_hard, N)(z, r, zn, toff, tshift); \ } \ } \ } DEFINE_IT(4, 4, 3) DEFINE_IT(5, 4, 4) DEFINE_IT(6, 5, 4) DEFINE_IT(7, 6, 5) DEFINE_IT(8, 7, 6) #undef DEFINE_IT ulong next_fft_number(ulong p) { ulong bits, l, q; bits = n_nbits(p); l = n_trailing_zeros(p - 1); q = p - (UWORD(2) << l); if (bits < 15) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (n_nbits(q) == bits) return q; if (l < 5) return n_pow2(bits - 2) + 1; return n_pow2(bits) - n_pow2(l - 1) + 1; } /* fill x[i] = 2^i mod p for 0 <= i < len */ static void fill_slow_two_pow_tab(double* x, ulong len, double p, double pinv) { double t = 1; x[0] = t; for (ulong i = 1; i < len; i++) { double q = vec1d_round(vec1d_mul(t, 2*pinv)); t = vec1d_fnmadd(q, p, vec1d_add(t, t)); x[i] = t; } } /* fill in d[i*nvs + k/VEC_SZ][k%VEC_SZ] = 2^i mod Rffts[k].p for 0 <= k < VEC_SZ*nvs and 0 <= i < len. */ static void fill_vec_two_pow_tab( vec4d* x, sd_fft_ctx_struct* Rffts, ulong len, ulong nvs) { ulong i, l; vec4d* ps; ps = (vec4d*) flint_aligned_alloc(32, 2*nvs*sizeof(vec4d)); for (l = 0; l < nvs; l++) { /* just p */ ps[2*l+0] = vec4d_set_d4(Rffts[4*l+0].p, Rffts[4*l+1].p, Rffts[4*l+2].p, Rffts[4*l+3].p); /* 2/p */ ps[2*l+1] = vec4d_set_d4(Rffts[4*l+0].pinv, Rffts[4*l+1].pinv, Rffts[4*l+2].pinv, Rffts[4*l+3].pinv); ps[2*l+1] = vec4d_add(ps[2*l+1], ps[2*l+1]); } for (l = 0; l < nvs; l++) x[0*nvs + l] = vec4d_one(); for (i = 1; i < len; i++) for (l = 0; l < nvs; l++) { vec4d t = x[(i-1)*nvs+l]; vec4d p = ps[2*l+0]; vec4d two_over_p = ps[2*l+1]; vec4d q = vec4d_round(vec4d_mul(t, two_over_p)); x[i*nvs+l] = vec4d_fnmadd(q, p, vec4d_add(t, t)); } flint_aligned_free(ps); } void mpn_ctx_init(mpn_ctx_t R, ulong p) { slong i; R->buffer = NULL; R->buffer_alloc = 0; for (i = 0; i < MPN_CTX_NCRTS; i++) { if (i > 0) p = next_fft_number(p); while (!n_is_prime(p)) p = next_fft_number(p); /* ffts */ sd_fft_ctx_init_prime(R->ffts + i, p); /* crts */ if (i == 0) { crt_data_init(R->crts + 0, p, 1, 1); *crt_data_co_prime_red(R->crts + 0, 0) = 1; crt_data_co_prime(R->crts + 0, 0)[0] = 1; crt_data_prod_primes(R->crts + 0)[0] = p; } else { ulong pi; ulong len = R->crts[i - 1].coeff_len; ulong* t, * tt; t = FLINT_ARRAY_ALLOC(2*(len + 2), ulong); tt = t + (len + 2); t[len + 1] = 0; t[len] = mpn_mul_1(t, crt_data_prod_primes(R->crts + i - 1), len, p); /* leave enough room for (product of primes)*(number of primes) */ len += 2; mpn_mul_1(tt, t, len, i + 1); while (tt[len - 1] == 0) len--; crt_data_init(R->crts + i, p, len, i + 1); /* set product of primes */ flint_mpn_copyi(crt_data_prod_primes(R->crts + i), t, len); /* set cofactors */ for (pi = 0; pi < i + 1; pi++) { ulong* cofac = crt_data_co_prime(R->crts + i, pi); mpn_divexact_1(cofac, t, len, R->crts[pi].prime); *crt_data_co_prime_red(R->crts + i, pi) = mpn_mod_1(cofac, len, R->crts[pi].prime); } flint_free(t); } } /* powers of two for slow mod */ { ulong len = MPN_CTX_TWO_POWER_TAB_SIZE; double* x = FLINT_ARRAY_ALLOC(len*MPN_CTX_NCRTS, double); R->slow_two_pow_buffer = x; for (i = 0; i < MPN_CTX_NCRTS; i++) { R->slow_two_pow_tab[i] = x; fill_slow_two_pow_tab(x, len, R->ffts[i].p, R->ffts[i].pinv); x += len; } } /* powers of two for fast mod */ { ulong len = MPN_CTX_TWO_POWER_TAB_SIZE; ulong max_nvs = n_cdiv(MPN_CTX_NCRTS, VEC_SZ); vec4d* x = (vec4d*) flint_aligned_alloc(32, max_nvs*(max_nvs + 1)/2*len*sizeof(vec4d)); R->vec_two_pow_buffer = x; for (ulong nvs = 1; nvs <= max_nvs; nvs++) { R->vec_two_pow_tab[nvs - 1] = x; fill_vec_two_pow_tab(x, R->ffts, len, nvs); x += nvs*len; } } R->profiles_size = 0; /*flint_printf("\n");*/ #define PUSH_PROFILE(np_, bits_, n, m) \ i = R->profiles_size; \ R->profiles[i].np = np_; \ R->profiles[i].bits = bits_; \ R->profiles[i].bn_bound = crt_data_find_bn_bound(R->crts + np_ - 1, bits_); \ R->profiles[i].to_ffts = CAT3(mpn_to_ffts, np_, bits_); \ /*flint_printf("profile np = %wu, bits = %3wu, bn <= 0x%16wx\n", R->profiles[i].np, R->profiles[i].bits, R->profiles[i].bn_bound);*/ \ R->profiles_size = i + 1; PUSH_PROFILE(4, 84, 4,3); PUSH_PROFILE(4, 88, 4,3); PUSH_PROFILE(4, 92, 4,3); PUSH_PROFILE(5,112, 4,4); PUSH_PROFILE(5,116, 4,4); PUSH_PROFILE(5,120, 4,4); PUSH_PROFILE(6,136, 5,4); PUSH_PROFILE(6,140, 5,4); PUSH_PROFILE(6,144, 5,4); PUSH_PROFILE(7,160, 6,5); PUSH_PROFILE(7,164, 6,5); PUSH_PROFILE(7,168, 6,5); PUSH_PROFILE(8,184, 7,6); PUSH_PROFILE(8,188, 7,6); PUSH_PROFILE(8,192, 7,6); FLINT_ASSERT(R->profiles_size <= MAX_NPROFILES); } #define VEC_SZ 4 void mpn_ctx_clear(mpn_ctx_t R) { slong i; for (i = 0; i < MPN_CTX_NCRTS; i++) { sd_fft_ctx_clear(R->ffts + i); crt_data_clear(R->crts + i); } flint_free(R->slow_two_pow_buffer); flint_aligned_free(R->vec_two_pow_buffer); flint_aligned_free(R->buffer); } typedef struct { thread_pool_handle* handles; slong nhandles; ulong nthreads; ulong np; ulong bits; to_ffts_func to_ffts; } profile_entry; static void mpn_ctx_best_profile( const mpn_ctx_t R, profile_entry* P, ulong an, ulong bn) { ulong i = 0; ulong best_i = 0; double best_score = 100000000.0*(an + bn); ulong thread_limit = 8; ulong zn = an + bn; if (zn < 2048) thread_limit = 1; else if (zn < 4096) thread_limit = 4; else if (zn < 8192) thread_limit = 5; else if (zn < 16384) thread_limit = 6; else if (zn < 32768) thread_limit = 7; P->nhandles = flint_request_threads(&P->handles, thread_limit); P->nthreads = 1 + P->nhandles; /* The first profile is supposed to have the biggest bn_bound. If the given bn is too large, we must fill in P->to_ffts = NULL because we don't have a fast mod function. We can also fill in P->to_ffts = NULL any time to not use the fast mod function and use the slow generic one instead. */ if (FLINT_UNLIKELY(bn > R->profiles[i].bn_bound)) { P->np = n_max(n_min(P->nthreads, 8), 4); P->bits = crt_data_find_bits(R->crts + P->np - 1, bn); P->to_ffts = NULL; return; } got_one: /* maximize R->profiles[i].bits */ FLINT_ASSERT(i < R->profiles_size); FLINT_ASSERT(bn <= R->profiles[i].bn_bound); while (i+1 < R->profiles_size && bn <= R->profiles[i+1].bn_bound && R->profiles[i+1].np == R->profiles[i].np) { i++; } ulong np = R->profiles[i].np; if (np % P->nthreads != 0) goto find_next; ulong bits = R->profiles[i].bits; ulong alen = n_cdiv(64*an, bits); ulong blen = n_cdiv(64*bn, bits); ulong zlen = alen + blen - 1; ulong ztrunc = n_round_up(zlen, BLK_SZ); ulong depth = n_max(LG_BLK_SZ, n_clog2(ztrunc)); double ratio = (double)(ztrunc)/(double)(n_pow2(depth)); double score = (1-0.25*ratio)*(1.0/1000000); score *= np*depth; score *= ztrunc; if (score < best_score) { best_i = i; best_score = score; } find_next: do { i++; if (i >= R->profiles_size) { P->np = R->profiles[best_i].np; P->bits = R->profiles[best_i].bits; P->to_ffts = R->profiles[best_i].to_ffts; return; } } while (bn > R->profiles[i].bn_bound); goto got_one; } void* mpn_ctx_fit_buffer(mpn_ctx_t R, ulong n) { if (n > R->buffer_alloc) { flint_aligned_free(R->buffer); n = n_round_up(n_max(n, R->buffer_alloc*17/16), 4096); R->buffer = flint_aligned_alloc(4096, n); R->buffer_alloc = n; } return R->buffer; } /* pointwise mul of a with b and m */ void sd_fft_lctx_point_mul( const sd_fft_lctx_t Q, double* a, const double* b, ulong m_, ulong depth) { vec8d m = vec8d_set_d(vec1d_reduce_0n_to_pmhn((slong)m_, Q->p)); vec8d n = vec8d_set_d(Q->p); vec8d ninv = vec8d_set_d(Q->pinv); FLINT_ASSERT(depth >= LG_BLK_SZ); for (ulong I = 0; I < n_pow2(depth - LG_BLK_SZ); I++) { double* ax = a + sd_fft_ctx_blk_offset(I); const double* bx = b + sd_fft_ctx_blk_offset(I); ulong j = 0; do { vec8d x0, x1, b0, b1; x0 = vec8d_load(ax+j+0); x1 = vec8d_load(ax+j+8); b0 = vec8d_load(bx+j+0); b1 = vec8d_load(bx+j+8); x0 = vec8d_mulmod(x0, m, n, ninv); x1 = vec8d_mulmod(x1, m, n, ninv); x0 = vec8d_mulmod(x0, b0, n, ninv); x1 = vec8d_mulmod(x1, b1, n, ninv); vec8d_store(ax+j+0, x0); vec8d_store(ax+j+8, x1); } while (j += 16, j < BLK_SZ); } } void sd_fft_lctx_point_sqr( const sd_fft_lctx_t Q, double* a, ulong m_, ulong depth) { vec8d m = vec8d_set_d(vec1d_reduce_0n_to_pmhn((slong)m_, Q->p)); vec8d n = vec8d_set_d(Q->p); vec8d ninv = vec8d_set_d(Q->pinv); FLINT_ASSERT(depth >= LG_BLK_SZ); for (ulong I = 0; I < n_pow2(depth - LG_BLK_SZ); I++) { double* ax = a + sd_fft_ctx_blk_offset(I); ulong j = 0; do { vec8d x0, x1; x0 = vec8d_load(ax+j+0); x1 = vec8d_load(ax+j+8); x0 = vec8d_mulmod(x0, x0, n, ninv); x1 = vec8d_mulmod(x1, x1, n, ninv); x0 = vec8d_mulmod(x0, m, n, ninv); x1 = vec8d_mulmod(x1, m, n, ninv); vec8d_store(ax+j+0, x0); vec8d_store(ax+j+8, x1); } while (j += 16, j < BLK_SZ); } } typedef struct { to_ffts_func to_ffts; sd_fft_ctx_struct* ffts; ulong stride; const vec4d* two_pow_tab; double* abuf; const ulong* a; ulong an; ulong atrunc; ulong a_start_easy; ulong a_stop_easy; ulong a_start_hard; ulong a_stop_hard; double* bbuf; const ulong* b; ulong bn; ulong btrunc; ulong b_start_easy; ulong b_stop_easy; ulong b_start_hard; ulong b_stop_hard; int squaring; } mod_worker_struct; void mod_worker_func(void* varg) { mod_worker_struct* X = (mod_worker_struct*) varg; X->to_ffts(X->ffts, X->abuf, X->stride, X->a, X->an, X->atrunc, X->two_pow_tab, X->a_start_easy, X->a_stop_easy, X->a_start_hard, X->a_stop_hard); if (!X->squaring) { X->to_ffts(X->ffts, X->bbuf, X->stride, X->b, X->bn, X->btrunc, X->two_pow_tab, X->b_start_easy, X->b_stop_easy, X->b_start_hard, X->b_stop_hard); } } typedef struct fft_worker_struct { sd_fft_ctx_struct* fctx; ulong cop; ulong depth; ulong ztrunc; double* abuf; ulong atrunc; double* bbuf; ulong btrunc; struct fft_worker_struct* next; int squaring; } fft_worker_struct; void fft_worker_func(void* varg) { fft_worker_struct* X = (fft_worker_struct*) varg; sd_fft_lctx_t Q; ulong m; do { sd_fft_lctx_init(Q, X->fctx, X->depth); if (!X->squaring) sd_fft_lctx_fft_trunc(Q, X->bbuf, X->depth, X->btrunc, X->ztrunc); sd_fft_lctx_fft_trunc(Q, X->abuf, X->depth, X->atrunc, X->ztrunc); NMOD_RED2(m, X->cop >> (64 - X->depth), X->cop << X->depth, X->fctx->mod); m = nmod_inv(m, X->fctx->mod); if (X->squaring) sd_fft_lctx_point_sqr(Q, X->abuf, m, X->depth); else sd_fft_lctx_point_mul(Q, X->abuf, X->bbuf, m, X->depth); sd_fft_lctx_ifft_trunc(Q, X->abuf, X->depth, X->ztrunc); sd_fft_lctx_clear(Q, X->fctx); } while (X = X->next, X != NULL); } typedef struct mod_fft_worker_struct { ulong bits; sd_fft_ctx_struct* fctx; const double* two_pow_tab; ulong cop; ulong depth; ulong ztrunc; const ulong* a; ulong an; double* abuf; ulong atrunc; const ulong* b; ulong bn; double* bbuf; ulong btrunc; struct mod_fft_worker_struct* next; int squaring; } mod_fft_worker_struct; void mod_fft_worker_func(void* varg) { mod_fft_worker_struct* X = (mod_fft_worker_struct*) varg; sd_fft_lctx_t Q; ulong m; do { sd_fft_lctx_init(Q, X->fctx, X->depth); if (!X->squaring) { slow_mpn_to_fft(Q, X->bbuf, X->btrunc, X->b, X->bn, X->bits, X->two_pow_tab); sd_fft_lctx_fft_trunc(Q, X->bbuf, X->depth, X->btrunc, X->ztrunc); } slow_mpn_to_fft(Q, X->abuf, X->atrunc, X->a, X->an, X->bits, X->two_pow_tab); sd_fft_lctx_fft_trunc(Q, X->abuf, X->depth, X->atrunc, X->ztrunc); NMOD_RED2(m, X->cop >> (64 - X->depth), X->cop << X->depth, X->fctx->mod); m = nmod_inv(m, X->fctx->mod); if (X->squaring) sd_fft_lctx_point_sqr(Q, X->abuf, m, X->depth); else sd_fft_lctx_point_mul(Q, X->abuf, X->bbuf, m, X->depth); sd_fft_lctx_ifft_trunc(Q, X->abuf, X->depth, X->ztrunc); sd_fft_lctx_clear(Q, X->fctx); } while (X = X->next, X != NULL); } typedef struct { from_ffts_func from_ffts; ulong* z; ulong zn; ulong zlen; sd_fft_ctx_struct* fctxs; double* abuf; ulong stride; crt_data_struct* crts; ulong bits; ulong start_easy; ulong stop_easy; ulong* overhang; ulong overhang_buffer[MPN_CTX_NCRTS]; } crt_worker_struct; void crt_worker_func(void* varg) { crt_worker_struct* X = (crt_worker_struct*) varg; X->from_ffts(X->z, X->zn, X->zlen, X->fctxs, X->abuf, X->stride, X->crts, X->bits, X->start_easy, X->stop_easy, X->overhang); } void mpn_ctx_mpn_mul(mpn_ctx_t R, ulong* z, const ulong* a, ulong an, const ulong* b, ulong bn) { ulong zn, alen, blen, zlen, atrunc, btrunc, ztrunc, depth, stride; double* abuf; profile_entry P; ulong sz; void* worker_struct_buffer; int squaring; mpn_ctx_best_profile(R, &P, an, bn); sz = sizeof(mod_worker_struct)*P.nthreads; sz = n_max(sz, sizeof(fft_worker_struct)*P.np); sz = n_max(sz, sizeof(mod_fft_worker_struct)*P.np); sz = n_max(sz, sizeof(crt_worker_struct)*P.nthreads); worker_struct_buffer = flint_malloc(sz); squaring = (a == b) && (an == bn); zn = an + bn; alen = n_cdiv(FLINT_BITS*an, P.bits); blen = n_cdiv(FLINT_BITS*bn, P.bits); zlen = alen + blen - 1; atrunc = n_round_up(alen, BLK_SZ); btrunc = n_round_up(blen, BLK_SZ); ztrunc = n_round_up(zlen, BLK_SZ); depth = n_max(LG_BLK_SZ, n_clog2(ztrunc)); stride = n_round_up(sd_fft_ctx_data_size(depth), 128); FLINT_ASSERT(an > 0); FLINT_ASSERT(bn > 0); FLINT_ASSERT(0 <= flint_mpn_cmp_ui_2exp( crt_data_prod_primes(R->crts + P.np - 1), R->crts[P.np - 1].coeff_len, blen, 2*P.bits)); #define TIME_THIS 0 #if TIME_THIS timeit_t timer, timer_overall; flint_printf("------------ zn = %wu, nthreads = %wu np = %wu, bits = %wu, -------------\n", zn, nthreads, np, bits); #endif #if TIME_THIS timeit_start(timer_overall); #endif if (P.to_ffts != NULL) { ulong bits = P.bits; mod_worker_struct* wm; fft_worker_struct* wf; /* if i*bits + 32 < 64*an, then the index into a is always in bounds */ ulong a_stop_easy = n_min(atrunc, (64*an - 33)/bits); /* if i*bits >= 64*an, then the index into a is always out of bounds */ ulong a_stop_hard = n_min(atrunc, (64*an + bits - 1)/bits); /* ditto */ ulong b_stop_easy = n_min(btrunc, (64*bn - 33)/bits); ulong b_stop_hard = n_min(btrunc, (64*bn + bits - 1)/bits); ulong rounding = (bits%8 == 0) ? 4 : (bits%4 == 0) ? 8 : 16; ulong nthreads = P.nthreads; double* bbuf; abuf = (double*) mpn_ctx_fit_buffer(R, 2*P.np*stride*sizeof(double)); bbuf = abuf + P.np*stride; #if TIME_THIS timeit_start(timer); #endif /* some fixups for loop unrollings: round down the easy stops */ FLINT_ASSERT(bits%2 == 0); a_stop_easy &= -rounding; b_stop_easy &= -rounding; wm = (mod_worker_struct*) worker_struct_buffer; for (ulong i = 0; i < nthreads; i++) { mod_worker_struct* X = wm + i; X->to_ffts = P.to_ffts; X->ffts = R->ffts; X->stride = stride; X->two_pow_tab = R->vec_two_pow_tab[n_cdiv(P.np, VEC_SZ) - 1]; X->abuf = abuf; X->a = a; X->an = an, X->atrunc = atrunc; X->bbuf = bbuf; X->b = b; X->bn = bn, X->btrunc = btrunc; X->a_start_easy = n_round_up((i+0)*a_stop_easy/nthreads, rounding); X->a_stop_easy = n_round_up((i+1)*a_stop_easy/nthreads, rounding); X->b_start_easy = n_round_up((i+0)*b_stop_easy/nthreads, rounding); X->b_stop_easy = n_round_up((i+1)*b_stop_easy/nthreads, rounding); /* only the last thread i = nthreads - 1 does the hard ends */ X->a_start_hard = (i + 1 == nthreads) ? a_stop_easy : atrunc; X->a_stop_hard = (i + 1 == nthreads) ? a_stop_hard : atrunc; X->b_start_hard = (i + 1 == nthreads) ? b_stop_easy : btrunc; X->b_stop_hard = (i + 1 == nthreads) ? b_stop_hard : btrunc; X->squaring = squaring; } for (slong i = P.nhandles; i > 0; i--) thread_pool_wake(global_thread_pool, P.handles[i - 1], 0, mod_worker_func, wm + i); mod_worker_func(wm + 0); for (slong i = P.nhandles; i > 0; i--) thread_pool_wait(global_thread_pool, P.handles[i - 1]); #if TIME_THIS timeit_stop(timer); if (timer->wall > 50) flint_printf(" mod: %wd\n", timer->wall); #endif #if TIME_THIS timeit_start(timer); #endif /* current scheduling: np = 5, nthreads = 3: thread0: p0, p3 thread1: p1, p4 thread2: p2 np = 3, nthreads = 5: thread0: p0 thread1: p1 thread2: p2 thread3: - thread4: - */ wf = (fft_worker_struct*) worker_struct_buffer; for (ulong l = 0; l < P.np; l++) { fft_worker_struct* X = wf + l; X->fctx = R->ffts + l; X->cop = *crt_data_co_prime_red(R->crts + P.np - 1, l); X->depth = depth; X->ztrunc = ztrunc; X->abuf = abuf + l*stride; X->atrunc = atrunc; X->bbuf = bbuf + l*stride; X->btrunc = btrunc; X->next = (l + nthreads < P.np) ? X + nthreads : NULL; X->squaring = squaring; } for (ulong i = n_min(P.nhandles, P.np - 1); i > 0; i--) thread_pool_wake(global_thread_pool, P.handles[i - 1], 0, fft_worker_func, wf + i); fft_worker_func(wf + 0); for (ulong i = n_min(P.nhandles, P.np - 1); i > 0; i--) thread_pool_wait(global_thread_pool, P.handles[i - 1]); #if TIME_THIS timeit_stop(timer); if (timer->wall > 50) flint_printf(" fft: %wd\n", timer->wall); #endif } else { mod_fft_worker_struct* w = (mod_fft_worker_struct*) worker_struct_buffer; ulong bits = P.bits; ulong np = P.np; ulong nthreads = P.nthreads; double* bbuf; abuf = (double*) mpn_ctx_fit_buffer(R, (np+nthreads)*stride*sizeof(double)); bbuf = abuf + np*stride; #if TIME_THIS timeit_start(timer); #endif for (ulong l = 0; l < np; l++) { mod_fft_worker_struct* X = w + l; X->bits = bits; X->fctx = R->ffts + l; X->cop = *crt_data_co_prime_red(R->crts + np - 1, l); X->depth = depth; X->ztrunc = ztrunc; X->a = a; X->an = an; X->abuf = abuf + l*stride; X->atrunc = atrunc; X->b = b; X->bn = bn; X->bbuf = bbuf + (l%nthreads)*stride; X->btrunc = btrunc; X->two_pow_tab = R->slow_two_pow_tab[l]; X->next = (l + nthreads < np) ? X + nthreads : NULL; X->squaring = squaring; } for (ulong i = n_min(P.nhandles, P.np - 1); i > 0; i--) thread_pool_wake(global_thread_pool, P.handles[i - 1], 0, mod_fft_worker_func, w + i); mod_fft_worker_func(w + 0); for (ulong i = n_min(P.nhandles, P.np - 1); i > 0; i--) thread_pool_wait(global_thread_pool, P.handles[i - 1]); #if TIME_THIS timeit_stop(timer); if (timer->wall > 50) flint_printf("mod+fft: %wd\n", timer->wall); #endif } #if TIME_THIS timeit_start(timer); #endif { ulong n = R->crts[P.np-1].coeff_len; crt_worker_struct* w = (crt_worker_struct*) worker_struct_buffer; ulong nthreads = P.nthreads; ulong end_easy = (zn >= n+1 ? zn - (n+1) : UWORD(0))*64/P.bits; /* this is how must space was statically allocated in each struct */ FLINT_ASSERT(n <= MPN_CTX_NCRTS); end_easy &= -BLK_SZ; FLINT_ASSERT(4 <= P.np && P.np <= 8); static from_ffts_func tab[8-4+1] = {_mpn_from_ffts_4, _mpn_from_ffts_5, _mpn_from_ffts_6, _mpn_from_ffts_7, _mpn_from_ffts_8}; for (ulong l = 0; l < nthreads; l++) { crt_worker_struct* X = w + l; X->from_ffts = tab[P.np - 4]; X->z = z; X->zn = zn; X->zlen = zlen; X->fctxs = R->ffts; X->abuf = abuf; X->stride = stride; X->crts = R->crts; X->bits = P.bits; X->start_easy = n_round_up((l+0)*end_easy/nthreads, BLK_SZ); X->stop_easy = n_round_up((l+1)*end_easy/nthreads, BLK_SZ); X->overhang = (l + 1 == nthreads) ? NULL : X->overhang_buffer; } for (slong i = P.nhandles; i > 0; i--) thread_pool_wake(global_thread_pool, P.handles[i - 1], 0, crt_worker_func, w + i); crt_worker_func(w + 0); for (slong i = P.nhandles; i > 0; i--) thread_pool_wait(global_thread_pool, P.handles[i - 1]); unsigned char cf = 0; for (ulong i = 1; i <= P.nhandles; i++) { ulong start = w[i].start_easy*P.bits/64; if (i == P.nhandles) { cf = flint_mpn_add_inplace_c(z + start, zn - start, w[i - 1].overhang_buffer, n, cf); } else { ulong stop = w[i].stop_easy*P.bits/64; if (stop > start) { cf = flint_mpn_add_inplace_c(z + start, stop - start, w[i - 1].overhang_buffer, n, cf); } else { for (ulong k = 0; k < n; k++) { FLINT_ASSERT(w[i].overhang_buffer[k] == 0); w[i].overhang_buffer[k] = w[i - 1].overhang_buffer[k]; } } } } } #if TIME_THIS timeit_stop(timer); if (timer->wall > 50) flint_printf(" crt: %wd\n", timer->wall); timeit_stop(timer_overall); if (timer_overall->wall > 50) flint_printf(" +: %wd\n", timer_overall->wall); #endif #undef TIME_THIS flint_free(worker_struct_buffer); flint_give_back_threads(P.handles, P.nhandles); } flint-3.1.3/src/fft_small/mulmod_statisfies_bounds.c000066400000000000000000000176431461254215100226550ustar00rootroot00000000000000#include #include "double_extras.h" #include "fft_small.h" /* For arithmetic mod n, the product a*b is represented exactly as the usual double-double format h + l where h and l are prec-bit floating point numbers. a*b will be roughly the size of n^2, but since one or both of a or b may not be reduced modulo n, it is common for the product a*b to be a reasonable multiple of n^2. Since this is calculated as h = mul(a, b) l = fmsub(a, b, h), if we have |a*b| < 2^e <= 2^(2*prec), then |l| <= 2^(e - prec - 1). First, ninv is an floating approximation of 1/n with some error epsilon ninv := 1/n + epsilon. Next, we would like to approximate the true quotient a*b/n as q = round_int(h*ninv), so that h + l can be reduced mod n. Since h*ninv = (a*b - l)*(1/n + epsilon) = a*b/n + a*b*epsilon - l*ninv, we have (with |h*ninv - q| <= q_error) (*) |a*b/n - q| <= |a*b*epsilon| + 2^(e - prec - 1)*ninv + q_error. When the quantity on the rhs is <= k, we can guarantee that |h + l - q*n| <= k*n, while h + l - q*n can be calculated exactly as add(l, fnmadd(q, n, h)). *** q_error *** when mul(h, ninv) does rounding B bits after the units place, the additional rounding done by round(mul(h, ninv)) can introduce an error as large as q_error = 1/2 + 1/2^(B+1) For example, suppose h*ninv = XXXXXX1.0100001.... mul(h, ninv) = XXXXXX1.1 rounded to 1 bit to the right of the dot Now mul(h,ninv) rounds up although h*ninv rounds down. The difference between the final rounded integer and the original h*ninv is at most 1/2 + 1/4 = 3/4 We can get the optimal q_error = 1/2 by calculating round_int(h*ninv) as sub(fmadd(h, ninv, r), r) with r = 3*2^(prec - 2) However, this requires |h*innv| < 2^(prec - 2), which is not always true. Furthermore, round(mul(.,.)) is fast on AMD :) Illustration of the truth of 1/2 + 1/2^(B+1): suppose mul(h, ninv) rounds to B=2 bits after the dot (XXXX means some non-zero bits): h*ninv mul(h*ninv) round(mul(h*ninv)) bound on |h*ninv - round(mul(h*ninv))| 0.000 0.00 0. 0 0.000XXXX 0.00 0. 1/8 0.001 0.00 0. 1/8 0.001XXXX 0.01 0. 2/8 0.010 0.01 0. 2/8 0.010XXXX 0.01 0. 3/8 0.011 0.10 0. or 1. 3/8 or 5/8 0.011XXXX 0.10 0. or 1. 4/8 or 5/8 0.100 0.10 0. or 1. 4/8 0.100XXXX 0.10 0. or 1. 5/8 or 4/8 0.101 0.10 0. or 1. 5/8 or 3/8 0.101XXXX 0.11 1. 3/8 0.110 0.11 1. 2/8 0.110XXXX 0.11 1. 2/8 0.111 1.00 1. 1/8 0.111XXXX 1.00 1. 1/8 We see q_error = 5/8 = 1/2 + 1/2^(B+1) */ /* Analysis for 2^(prec - 4) < n < 2^(prec - 3) (aka 50 bit primes) ---------------------------------------------------------------- In this case we have |epsilon| < 2^(3 - 2*prec) and ninv < 2^(4 - prec). For |a*b| < 2*n^2, we can take e = 2*prec - 5. Then, |h*ninv| < 2^(prec-2) and mul(h, ninv) does rounding at least two bits to the right of the dot. Then, we make take q_error = 1/2 + 2^-3: |a*b*epsilon| + 2^(e - prec - 1)*ninv + 1/2+2^-3 < 2^-2 + 2^-2 + 1/2 + 2^-3 = 1+1/8 Similarly for |a*b| < 4*n^2, we can take e = 2*prec - 4 and q_error = 1/2 + 2^-2: |a*b*epsilon| + 2^(e - prec - 1)*ninv + 1/2+2^-2 < 2^-1 + 2^-1 + 1/2 + 2^-2 = 3/2+1/4 Therefore, Products in the range (-2*n^2, 2*n^2) are reduced to the range (-9/8*n, 9/8*n). Products in the range (-4*n^2, 4*n^2) are reduced to the range (-7/4*n, 7/4*n). These pessimistic bounds are not good enough. For specific values of n, epsilon can be much smaller, and it not very restrictive to assume what mulmod needs: (1) Products in the range (-2*n^2, 2*n^2) are reduced to the range (-1*n, 1*n). (2) Products in the range (-4*n^2, 4*n^2) are reduced to the range (-3/2*n, 3/2*n). */ /* define e as |a*b| < 2^e bound = |a*b*(ninv-1/n)| + 2^(e - prec - 1)*ninv + q_error want bound < 1 for |a*b| < 2*n^2 where q_error = 1/2 + 2^-3 want bound < 1.5 for |a*b| < 4*n^2 where q_error = 1/2 + 2^-2 */ int fft_small_mulmod_satisfies_bounds(ulong nn) { double n = nn; double ninv = 1.0/n; double t1 = fabs(fma(n, ninv, -1.0)); /* epsilon ~= t1/n good enough */ double limit2, limit4; int B, ok, n1bits, n2bits; ulong n2hi, n2lo; n1bits = n_nbits(nn); umul_ppmm(n2hi, n2lo, nn, nn); if (n2hi != 0) n2bits = FLINT_BITS + n_nbits(n2hi); else n2bits = n_nbits(n2lo); /* for |a*b| < 2*n^2*/ /* |h*n_inv| < 2*n, so rounding in mul(h, ninv) at least B bits after the .*/ B = D_BITS - n1bits - 1; if (B < 2) return 0; limit2 = 2*n*t1 + ldexp(ninv, 1+n2bits-D_BITS-1) + 0.5 + ldexp(1.0, -(B+1)); /* for |a*b| < 4*n^2*/ B -= 1; limit4 = 4*n*t1 + ldexp(ninv, 2+n2bits-D_BITS-1) + 0.5 + ldexp(1.0, -(B+1)); /* fudge the limits 1 and 3/2 because the above is double arithmetic */ ok = (limit2 < 0.99) && (limit4 < 1.49); return ok; } /* assuming satisfies_bounds(n): (1) Products in the range (-2*n^2, 2*n^2) are reduced to the range (-1*n, 1*n). (2) Products in the range (-4*n^2, 4*n^2) are reduced to the range (-3/2*n, 3/2*n). Analysis of the forward butterfiles for 50 bit primes ----------------------------------------------------- b0 = 1*a0 + w^2*a2 + w*(a1 + w^2*a3) b1 = 1*a0 + w^2*a2 - w*(a1 + w^2*a3) b2 = 1*a0 - w^2*a2 + i*w*(a1 - w^2*a3) b3 = 1*a0 - w^2*a2 - i*w*(a1 - w^2*a3) Each of w^2, w, and i*w is in (-n/2, n/2). As part of this operation, the multiplication 1*a0 reduces a0 to the range (-n, n) and the other multiplications use the above. In practice, a0 does not get large even without this reduction, but this is needed to prove things stay bounded. The following claim is trivial from (1): (*) If the ai in (-3*n, 3*n), then the bi are also in (-3*n, 3*n). Analysis of the truncated forward butterfiles for 50 bit primes --------------------------------------------------------------- Trivial because some of the ai are just 0. Analysis of the pointwise muls ------------------------------ The output of one fft in the range (-3*n, 3*n) is multiplied with a multiplier (2^-depth) in the range (-n/2, n/2). This produces a product x in the range (-n, n). Then, x is multiplied by the output of another fft in the range (-3*n, 3*n). Thus, (*) The outputs of the pointwise muls are in the range (-3/2*n, 3/2*n). Analysis of the reverse butterflies for 50 bit primes ----------------------------------------------------- 4a0 = 1*( (b0 + b1) + (b2 + b3)) 4a2 = w^-2*( (b0 + b1) - (b2 + b3)) 4a1 = w^-1*(b0 - b1) - i*w^-1*(b2 - b3) 4a3 = w^-2*(w^-1*(b0 - b1) + i*w^-1*(b2 - b3)) As before, each of w^-2, w^-1, and i*w^-1 is in (-n/2, n/2). As part of this operation, 1*(b0 + b1 + b2 + b3) reduces 4a0 to the range (-n, n), and the other multiplications are as before. The following claim is trivial from (1) and (2): (*) If the bi are in (-2*n, 2*n), then the 4ai are also in (-2*n, 2*n). The bound n < 2^50 guarantees that |(b0 + b1) +- (b2 + b3)| < 2^53 so that no bits are lost. Analysis of the truncated reverse butterflies for 50 bit primes --------------------------------------------------------------- *** TODO *** A bit tedious because there are so many formulas, but we just need make sure that output is in the range (-2*n, 2*n) if input is. */ flint-3.1.3/src/fft_small/nmod_poly_mul.c000066400000000000000000001121411461254215100204120ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "crt_helpers.h" #include "fft_small.h" static void _mod_red( double* abuf, ulong atrunc, const ulong* a, ulong an, const sd_fft_ctx_struct* fft, nmod_t mod) { double* aI; ulong i, j; FLINT_ASSERT(atrunc < an); FLINT_ASSERT(atrunc%BLK_SZ == 0); #if 1 ulong tt = an%atrunc; #define UNROLL 8 for (i = 0; i < atrunc; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); vec8n nn = vec8n_set_n(mod.n); vec8d n = vec8d_set_d(fft->p); vec8d ninv = vec8d_set_d(fft->pinv); for (j = 0; j < BLK_SZ; j += UNROLL) { if (i+j+UNROLL <= tt || i+j >= tt) { ulong k = i+j; FLINT_ASSERT(k+UNROLL-1 < an); vec8n t = vec8n_load_unaligned(a + k); if (mod.norm == 0) for (k += atrunc; k < an; k += atrunc) t = vec8n_addmod(t, vec8n_load_unaligned(a + k), nn); else for (k += atrunc; k < an; k += atrunc) t = vec8n_addmod_limited(t, vec8n_load_unaligned(a + k), nn); vec8d tlo = vec8n_convert_limited_vec8d(vec8n_bit_and(t, vec8n_set_n(n_pow2(32)-1))); vec8d thi = vec8n_convert_limited_vec8d(vec8n_bit_shift_right_32(t)); vec8d_store_aligned(aI + j, vec8d_add(tlo, vec8d_mulmod(thi, vec8d_set_d(n_pow2(32)), n, ninv))); } else { for (ulong l = 0; l < UNROLL; l++) { ulong k = i+j+l; ulong c = a[k]; for (k += atrunc; k < an; k += atrunc) c = nmod_add(c, a[k], mod); aI[j+l] = (slong)(nmod_set_ui(c, fft->mod)); } } } } #else // wrong way!! if (modn <= fft->mod.n) { /* first pass fill in */ for (i = 0; i < atrunc; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { vec8n t = vec8n_load_unaligned(a + i + j); vec8d_store_aligned(aI + j, vec8n_convert_limited_vec8d(t)); } } vec8d n = vec8d_set_d(fft->p); /* second pass add to existing */ for (i = atrunc; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, (i%atrunc)/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { vec8n t = vec8n_load_unaligned(a + i + j); vec8d s = vec8n_convert_limited_vec8d(t); s = vec8d_add(s, vec8d_load_aligned(aI + j)); s = vec8d_reduce_2n_to_n(s, n); vec8d_store_aligned(aI + j, s); } } aI = sd_fft_ctx_blk_index(abuf, (i%atrunc)/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = vec1d_reduce_2n_to_n(aI[j] + (slong)a[i + j], fft->p); } else { vec8d n = vec8d_set_d(fft->p); vec8d ninv = vec8d_set_d(fft->pinv); for (i = 0; i < atrunc; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { vec8n t = vec8n_load_unaligned(a + i + j); vec8d tlo = vec8n_convert_limited_vec8d(vec8n_bit_and(t, vec8n_set_n(n_pow2(32)-1))); vec8d thi = vec8n_convert_limited_vec8d(vec8n_bit_shift_right_32(t)); vec8d_store_aligned(aI + j, vec8d_add(tlo, vec8d_mulmod(thi, vec8d_set_d(n_pow2(32)), n, ninv))); } } for (i = atrunc; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, (i%atrunc)/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { vec8n t = vec8n_load_unaligned(a + i + j); vec8d tlo = vec8n_convert_limited_vec8d(vec8n_bit_and(t, vec8n_set_n(n_pow2(32)-1))); vec8d thi = vec8n_convert_limited_vec8d(vec8n_bit_shift_right_32(t)); vec8d s = vec8d_add(tlo, vec8d_mulmod(thi, vec8d_set_d(n_pow2(32)), n, ninv)); s = vec8d_add(s, vec8d_load_aligned(aI + j)); s = vec8d_reduce_2n_to_n(s, n); vec8d_store_aligned(aI + j, s); } } aI = sd_fft_ctx_blk_index(abuf, (i%atrunc)/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = vec1d_reduce_2n_to_n(aI[j] + (slong)nmod_set_ui(a[i+j], fft->mod), fft->p); } #endif } static void _mod( double* abuf, ulong atrunc, const ulong* a, ulong an, const sd_fft_ctx_struct* fft, nmod_t mod) { double* aI; ulong i, j; if (atrunc < an) { _mod_red(abuf, atrunc, a, an, fft, mod); return; } if (mod.n <= fft->mod.n) { for (i = 0; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < BLK_SZ; j += 8) { vec8n t = vec8n_load_unaligned(a + i + j); FLINT_ASSERT(i+j < atrunc); vec8d_store_aligned(aI + j, vec8n_convert_limited_vec8d(t)); } } aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = (slong)a[i + j]; } else { vec8d n = vec8d_set_d(fft->p); vec8d ninv = vec8d_set_d(fft->pinv); for (i = 0; i + BLK_SZ <= an; i += BLK_SZ) { aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); #if 1 for (j = 0; j < BLK_SZ; j += 8) { vec8n t = vec8n_load_unaligned(a + i + j); vec8d tlo = vec8n_convert_limited_vec8d(vec8n_bit_and(t, vec8n_set_n(n_pow2(32)-1))); vec8d thi = vec8n_convert_limited_vec8d(vec8n_bit_shift_right_32(t)); vec8d_store_aligned(aI + j, vec8d_add(tlo, vec8d_mulmod(thi, vec8d_set_d(n_pow2(32)), n, ninv))); } #else for (j = 0; j < BLK_SZ; j += 1) { aI[j] = (slong)nmod_set_ui(a[i+j], fft->mod); } #endif } aI = sd_fft_ctx_blk_index(abuf, i/BLK_SZ); for (j = 0; j < an - i; j++) aI[j] = (slong)nmod_set_ui(a[i+j], fft->mod); } for (i = an; i < atrunc; i++) sd_fft_ctx_set_index(abuf, i, 0); } #define DEFINE_IT(NP, N, M) \ static void CAT(_crt, NP)( \ ulong* z, ulong zl, ulong zi_start, ulong zi_stop, \ sd_fft_ctx_struct* Rffts, double* d, ulong dstride, \ crt_data_struct* Rcrts, \ nmod_t mod) \ { \ ulong np = NP; \ ulong n = N; \ ulong m = M; \ \ FLINT_ASSERT(n == Rcrts[np-1].coeff_len); \ FLINT_ASSERT(1 <= N && N <= 3); \ \ if (n == m + 1) \ { \ for (ulong l = 0; l < np; l++) { \ FLINT_ASSERT(crt_data_co_prime(Rcrts + np - 1, l)[m] == 0); \ } \ } \ else \ { \ FLINT_ASSERT(n == m); \ } \ \ ulong Xs[BLK_SZ*NP]; \ \ for (ulong i = n_round_down(zi_start, BLK_SZ); i < zi_stop; i += BLK_SZ) \ { \ _convert_block(Xs, Rffts, d, dstride, np, i/BLK_SZ); \ \ ulong jstart = (i < zi_start) ? zi_start - i : 0; \ ulong jstop = FLINT_MIN(BLK_SZ, zi_stop - i); \ for (ulong j = jstart; j < jstop; j += 1) \ { \ ulong r[N]; \ ulong t[N]; \ ulong l = 0; \ \ CAT3(_big_mul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ for (l++; l < np; l++) \ CAT3(_big_addmul, N, M)(r, t, _crt_data_co_prime(Rcrts + np - 1, l, n), Xs[l*BLK_SZ + j]); \ \ CAT(_reduce_big_sum, N)(r, t, crt_data_prod_primes(Rcrts + np - 1)); \ \ if (N == 1) \ { \ NMOD_RED(z[i+j-zl], r[0], mod); \ } \ else if (N == 2) \ { \ NMOD2_RED2(z[i+j-zl], r[1], r[0], mod); \ } \ else \ { \ FLINT_ASSERT(N < 4 || r[3] == 0); \ NMOD_RED3(z[i+j-zl], r[2], r[1], r[0], mod); \ } \ } \ } \ } DEFINE_IT(2, 2, 1) DEFINE_IT(3, 3, 2) DEFINE_IT(4, 4, 3) #undef DEFINE_IT static void _crt_1( ulong* z, ulong zl, ulong zi_start, ulong zi_stop, sd_fft_ctx_struct* Rffts, double* d, ulong dstride, crt_data_struct* Rcrts, nmod_t mod) { ulong i, j, jstart, jstop; ulong Xs[BLK_SZ*1]; if (mod.n == Rffts[0].mod.n) { for (i = n_round_down(zi_start, BLK_SZ); i < zi_stop; i += BLK_SZ) { _convert_block(Xs, Rffts, d, dstride, 1, i/BLK_SZ); jstart = (i < zi_start) ? zi_start - i : 0; \ jstop = FLINT_MIN(BLK_SZ, zi_stop - i); for (j = jstart; j < jstop; j += 1) { z[i+j-zl] = Xs[j]; } } } else { for (i = n_round_down(zi_start, BLK_SZ); i < zi_stop; i += BLK_SZ) { _convert_block(Xs, Rffts, d, dstride, 1, i/BLK_SZ); jstart = (i < zi_start) ? zi_start - i : 0; \ jstop = FLINT_MIN(BLK_SZ, zi_stop - i); for (j = jstart; j < jstop; j += 1) { NMOD_RED(z[i+j-zl], Xs[j], mod); } } } } typedef struct { ulong np; ulong start_pi; ulong stop_pi; ulong offset; double* abuf; double* bbuf; ulong depth; ulong stride; ulong atrunc; ulong btrunc; ulong ztrunc; const ulong* a; ulong an; const ulong* b; ulong bn; sd_fft_ctx_struct* ffts; crt_data_struct* crts; nmod_t mod; ulong ioff; int squaring; } s1worker_struct; static void extra_func(void* varg) { s1worker_struct* X = (s1worker_struct*) varg; sd_fft_lctx_t Q; sd_fft_lctx_init(Q, X->ffts + X->ioff, X->depth); _mod(X->bbuf, X->btrunc, X->b, X->bn, X->ffts + X->ioff, X->mod); sd_fft_lctx_fft_trunc(Q, X->bbuf, X->depth, X->btrunc, X->ztrunc); sd_fft_lctx_clear(Q, X->ffts + X->ioff); } void s1worker_func(void* varg) { s1worker_struct* X = (s1worker_struct*) varg; sd_fft_lctx_t Q; ulong i, m; thread_pool_handle* handles = NULL; slong nworkers = 0; if (X->bn > 5000 && !X->squaring) nworkers = flint_request_threads(&handles, 2); for (i = X->start_pi; i < X->stop_pi; i++) { ulong ioff = i + X->offset; double* abuf = X->abuf + X->stride*i; double* bbuf = X->bbuf; sd_fft_lctx_init(Q, X->ffts + ioff, X->depth); if (!X->squaring) { if (nworkers > 0) { X->ioff = ioff; thread_pool_wake(global_thread_pool, handles[0], 0, extra_func, X); } else { _mod(bbuf, X->btrunc, X->b, X->bn, X->ffts + ioff, X->mod); sd_fft_lctx_fft_trunc(Q, bbuf, X->depth, X->btrunc, X->ztrunc); } } _mod(abuf, X->atrunc, X->a, X->an, X->ffts + ioff, X->mod); sd_fft_lctx_fft_trunc(Q, abuf, X->depth, X->atrunc, X->ztrunc); if (!X->squaring) { if (nworkers > 0) thread_pool_wait(global_thread_pool, handles[0]); } ulong cop = X->np == 1 ? 1 : *crt_data_co_prime_red(X->crts + X->np - 1, ioff); NMOD_RED2(m, cop >> (FLINT_BITS - X->depth), cop << X->depth, X->ffts[ioff].mod); m = nmod_inv(m, X->ffts[ioff].mod); if (X->squaring) sd_fft_lctx_point_sqr(Q, abuf, m, X->depth); else sd_fft_lctx_point_mul(Q, abuf, bbuf, m, X->depth); sd_fft_lctx_ifft_trunc(Q, abuf, X->depth, X->ztrunc); sd_fft_lctx_clear(Q, X->ffts + ioff); } flint_give_back_threads(handles, nworkers); } typedef struct { ulong* z; ulong zl; ulong start_zi; ulong stop_zi; double* buf; ulong offset; ulong stride; sd_fft_ctx_struct* ffts; crt_data_struct* crts; nmod_t mod; void (*f)( ulong* z, ulong zl, ulong zi_start, ulong zi_stop, sd_fft_ctx_struct* Rffts, double* d, ulong dstride, crt_data_struct* Rcrts, nmod_t mod); } s2worker_struct; void s2worker_func(void* varg) { s2worker_struct* X = (s2worker_struct*) varg; X->f(X->z, X->zl, X->start_zi, X->stop_zi, X->ffts + X->offset, X->buf, X->stride, X->crts + X->offset, X->mod); } void _nmod_poly_mul_mid_mpn_ctx( ulong* z, ulong zl, ulong zh, const ulong* a, ulong an, const ulong* b, ulong bn, nmod_t mod, mpn_ctx_t R) { ulong modbits = FLINT_BITS - mod.norm; ulong offset = 0; ulong zn = an + bn - 1; ulong atrunc, btrunc, ztrunc; ulong i, np, depth, stride; double* buf; int squaring; FLINT_ASSERT(an > 0); FLINT_ASSERT(bn > 0); if (zl >= zh) return; if (zh > zn) { if (zl >= zn) { flint_mpn_zero(z, zh - zl); return; } flint_mpn_zero(z + zn - zl, zh - zn); zh = zn; } squaring = (a == b) && (an == bn); FLINT_ASSERT(zl < zh); FLINT_ASSERT(zh <= zn); /* first see if mod.n is on of R->ffts[i].mod.n */ if (modbits == 50) { for (i = 0; i < MPN_CTX_NCRTS; i++) { if (mod.n == R->ffts[i].mod.n) { offset = i; np = 1; goto got_np_and_offset; } } } /* need prod_of_primes >= blen * 4^modbits */ for (np = 1; np < 4; np++) { if (flint_mpn_cmp_ui_2exp(crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, bn, 2*modbits) >= 0) { break; } } FLINT_ASSERT(0 <= flint_mpn_cmp_ui_2exp( crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, bn, 2*modbits)); got_np_and_offset: atrunc = n_round_up(an, BLK_SZ); btrunc = n_round_up(bn, BLK_SZ); ztrunc = n_round_up(zn, BLK_SZ); /* if there is a power of two 2^d between zh and zn with good wrap around i.e. max(an, bn, zh) <= 2^d <= zn with zn - 2^d <= zl then use d as the depth, otherwise the usual with no wrap around */ depth = n_flog2(zn); i = n_pow2(depth); if (atrunc <= i && btrunc <= i && zh <= i && i <= zn && zn <= zl + i) { ztrunc = i; } else { depth = n_max(LG_BLK_SZ, n_clog2(ztrunc)); } stride = n_round_up(sd_fft_ctx_data_size(depth), 128); ulong want_threads; if (bn < 1500) want_threads = 1; else want_threads = np; thread_pool_handle* handles; slong nworkers = flint_request_threads(&handles, want_threads); ulong nthreads = nworkers + 1; buf = (double*) mpn_ctx_fit_buffer(R, (np+nthreads)*stride*sizeof(double)); s1worker_struct s1args[4]; for (i = 0; i < nthreads; i++) { s1worker_struct* X = s1args + i; X->np = np; X->start_pi = (i+0)*np/nthreads; X->stop_pi = (i+1)*np/nthreads; X->offset = offset; X->abuf = buf; X->bbuf = buf + (np+i)*stride; X->depth = depth; X->stride = stride; X->atrunc = atrunc; X->btrunc = btrunc; X->ztrunc = ztrunc; X->a = a; X->an = an; X->b = b; X->bn = bn; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; X->squaring = squaring; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s1worker_func, s1args + i); s1worker_func(s1args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); if (np*zn > 10000) { flint_give_back_threads(handles, nworkers); nworkers = flint_request_threads(&handles, 8); nthreads = nworkers + 1; } s2worker_struct s2args[8]; ulong o = zl; for (i = 0; i < nthreads; i++) { s2worker_struct* X = s2args + i; X->z = z; X->zl = zl; X->start_zi = o; ulong newo = n_round_down(zl + (i+1)*(zh-zl)/nthreads, BLK_SZ); o = i+1 < nthreads ? FLINT_MAX(o, newo) : zh; X->stop_zi = o; X->buf = buf; X->offset = offset; X->stride = stride; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; X->f = np == 1 ? _crt_1 : np == 2 ? _crt_2 : np == 3 ? _crt_3 : _crt_4; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s2worker_func, s2args + i); s2worker_func(s2args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); flint_give_back_threads(handles, nworkers); } void _nmod_poly_mul_mod_xpnm1_naive( ulong* z, ulong zn, const ulong* a, ulong an, const ulong* b, ulong bn, ulong lgN, nmod_t mod, mpn_ctx_t R) { ulong N = n_pow2(lgN); FLINT_ASSERT(zn <= N); ulong* t = FLINT_ARRAY_ALLOC(an + bn - 1, ulong); if (an >= bn) _nmod_poly_mul(t, a, an, b, bn, mod); else _nmod_poly_mul(t, b, bn, a, an, mod); for (ulong i = 0; i < zn; i++) { ulong c = 0; for (ulong j = i; j < an + bn - 1; j += N) c = nmod_add(c, t[j], mod); z[i] = c; } flint_free(t); } void _nmod_poly_mul_mod_xpnm1( ulong* z, ulong ztrunc, const ulong* a, ulong an, const ulong* b, ulong bn, ulong depth, nmod_t mod, mpn_ctx_t R) { ulong N = n_pow2(depth); ulong modbits = FLINT_BITS - mod.norm; ulong offset = 0; ulong i, np, stride; double* buf; FLINT_ASSERT(an > 0); FLINT_ASSERT(bn > 0); FLINT_ASSERT(ztrunc <= N); /* first see if mod.n is on of R->ffts[i].mod.n */ if (modbits == 50) { for (i = 0; i < MPN_CTX_NCRTS; i++) { if (mod.n == R->ffts[i].mod.n) { offset = i; np = 1; goto got_np_and_offset; } } } /* need prod_of_primes >= N * 4^modbits */ for (np = 1; np < 4; np++) { if (flint_mpn_cmp_ui_2exp(crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, N, 2*modbits) >= 0) { break; } } FLINT_ASSERT(0 <= flint_mpn_cmp_ui_2exp( crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, N, 2*modbits)); got_np_and_offset: stride = n_round_up(sd_fft_ctx_data_size(depth), 128); ulong want_threads; if (bn < 1500) want_threads = 1; else want_threads = np; thread_pool_handle* handles; slong nworkers = flint_request_threads(&handles, want_threads); ulong nthreads = nworkers + 1; buf = (double*) mpn_ctx_fit_buffer(R, (np+nthreads)*stride*sizeof(double)); s1worker_struct s1args[4]; for (i = 0; i < nthreads; i++) { s1worker_struct* X = s1args + i; X->np = np; X->start_pi = (i+0)*np/nthreads; X->stop_pi = (i+1)*np/nthreads; X->offset = offset; X->abuf = buf; X->bbuf = buf + (np+i)*stride; X->depth = depth; X->stride = stride; X->atrunc = N; X->btrunc = N; X->ztrunc = N; X->a = a; X->an = an; X->b = b; X->bn = bn; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; X->squaring = 0; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s1worker_func, s1args + i); s1worker_func(s1args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); s2worker_struct s2args[8]; ulong zl = 0; ulong zh = ztrunc; ulong o = zl; for (i = 0; i < nthreads; i++) { s2worker_struct* X = s2args + i; X->z = z; X->zl = zl; X->start_zi = o; ulong newo = n_round_down(zl + (i+1)*(zh-zl)/nthreads, BLK_SZ); o = i+1 < nthreads ? FLINT_MAX(o, newo) : zh; X->stop_zi = o; X->buf = buf; X->offset = offset; X->stride = stride; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; X->f = np == 1 ? _crt_1 : np == 2 ? _crt_2 : np == 3 ? _crt_3 : _crt_4; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s2worker_func, s2args + i); s2worker_func(s2args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); flint_give_back_threads(handles, nworkers); } typedef struct { ulong np; ulong start_pi; ulong stop_pi; ulong offset; double* abuf; double* bbuf; ulong depth; ulong stride; ulong atrunc; ulong ztrunc; const ulong* a; ulong an; sd_fft_ctx_struct* ffts; crt_data_struct* crts; nmod_t mod; } s1pworker_struct; void s1pworker_func(void* varg) { s1pworker_struct* X = (s1pworker_struct*) varg; sd_fft_lctx_t Q; ulong i, m; for (i = X->start_pi; i < X->stop_pi; i++) { ulong ioff = i + X->offset; double* abuf = X->abuf + X->stride*i; sd_fft_lctx_init(Q, X->ffts + ioff, X->depth); _mod(abuf, X->atrunc, X->a, X->an, X->ffts + ioff, X->mod); sd_fft_lctx_fft_trunc(Q, abuf, X->depth, X->atrunc, X->ztrunc); ulong cop = X->np == 1 ? 1 : *crt_data_co_prime_red(X->crts + X->np - 1, ioff); NMOD_RED2(m, cop >> (FLINT_BITS - X->depth), cop << X->depth, X->ffts[ioff].mod); m = nmod_inv(m, X->ffts[ioff].mod); sd_fft_lctx_point_mul(Q, abuf, X->bbuf + X->stride*i, m, X->depth); sd_fft_lctx_ifft_trunc(Q, abuf, X->depth, X->ztrunc); sd_fft_lctx_clear(Q, X->ffts + ioff); } } void _mul_precomp_init( mul_precomp_struct* M, const ulong * b, ulong bn, ulong btrunc, ulong depth, nmod_t mod, mpn_ctx_t R) { ulong N = n_pow2(depth); ulong modbits = FLINT_BITS - mod.norm; ulong offset = 0; ulong i, np, stride; sd_fft_lctx_t Q; btrunc = n_round_up(btrunc, BLK_SZ); FLINT_ASSERT(bn > 0); /* first see if mod.n is on of R->ffts[i].mod.n */ if (modbits == 50) { for (i = 0; i < MPN_CTX_NCRTS; i++) { if (mod.n == R->ffts[i].mod.n) { offset = i; np = 1; goto got_np_and_offset; } } } /* need prod_of_primes >= N * 4^modbits */ for (np = 1; np < 4; np++) { if (flint_mpn_cmp_ui_2exp(crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, N, 2*modbits) >= 0) { break; } } FLINT_ASSERT(0 <= flint_mpn_cmp_ui_2exp( crt_data_prod_primes(R->crts + np - 1), R->crts[np - 1].coeff_len, N, 2*modbits)); got_np_and_offset: stride = n_round_up(sd_fft_ctx_data_size(depth), 128); M->depth = depth; M->N = N; M->offset = offset; M->np = np; M->stride = stride; M->bn = bn; M->btrunc = btrunc; M->bbuf = flint_aligned_alloc(4096, n_round_up(np*stride*sizeof(double), 4096)); for (i = 0; i < np; i++) { ulong ioff = i + offset; double* bbuf = M->bbuf + stride*i; sd_fft_lctx_init(Q, R->ffts + ioff, depth); _mod(bbuf, N, b, bn, R->ffts + ioff, mod); sd_fft_lctx_fft_trunc(Q, bbuf, depth, N, N); sd_fft_lctx_clear(Q, R->ffts + ioff); } } int _nmod_poly_mul_mid_precomp( ulong* z, ulong zl, ulong zh, const ulong* a, ulong an, mul_precomp_struct* M, nmod_t mod, mpn_ctx_t R) { ulong bn = M->bn; ulong zn = an + bn - 1; ulong atrunc, ztrunc; ulong depth = M->depth; ulong N = n_pow2(depth); ulong i, np = M->np; double* buf; FLINT_ASSERT(an > 0); FLINT_ASSERT(bn > 0); FLINT_ASSERT(M->btrunc <= N); if (zl >= zh) return 1; if (zh > zn) { if (zl >= zn) { flint_mpn_zero(z, zh - zl); return 1; } flint_mpn_zero(z + zn - zl, zh - zn); zh = zn; } FLINT_ASSERT(zl < zh); FLINT_ASSERT(zh <= zn); atrunc = n_round_up(an, BLK_SZ); ztrunc = n_round_up(zn, BLK_SZ); if (atrunc <= N && zh <= N && N <= zn && zn <= zl + N) { ztrunc = N; } else if (ztrunc <= N) { } else { return 0; } ulong want_threads; /* todo: even with np == 1, we may want threads for the conversion to fft */ if (bn < 1500) want_threads = 1; else want_threads = np; thread_pool_handle* handles; slong nworkers = flint_request_threads(&handles, want_threads); ulong nthreads = nworkers + 1; buf = (double*) mpn_ctx_fit_buffer(R, np*M->stride*sizeof(double)); s1pworker_struct s1pargs[4]; for (i = 0; i < nthreads; i++) { s1pworker_struct* X = s1pargs + i; X->np = np; X->start_pi = (i+0)*np/nthreads; X->stop_pi = (i+1)*np/nthreads; X->offset = M->offset; X->abuf = buf; X->bbuf = M->bbuf; X->depth = depth; X->stride = M->stride; X->atrunc = atrunc; X->ztrunc = ztrunc; X->a = a; X->an = an; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s1pworker_func, s1pargs + i); s1pworker_func(s1pargs + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); s2worker_struct s2args[8]; ulong o = zl; for (i = 0; i < nthreads; i++) { s2worker_struct* X = s2args + i; X->z = z; X->zl = zl; X->start_zi = o; ulong newo = n_round_down(zl + (i+1)*(zh-zl)/nthreads, BLK_SZ); o = i+1 < nthreads ? FLINT_MAX(o, newo) : zh; X->stop_zi = o; X->buf = buf; X->offset = M->offset; X->stride = M->stride; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; X->f = np == 1 ? _crt_1 : np == 2 ? _crt_2 : np == 3 ? _crt_3 : _crt_4; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s2worker_func, s2args + i); s2worker_func(s2args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); flint_give_back_threads(handles, nworkers); return 1; } void _nmod_poly_mul_mod_xpnm1_precomp( ulong* z, ulong ztrunc, const ulong* a, ulong an, mul_precomp_struct* M, nmod_t mod, mpn_ctx_t R) { ulong depth = M->depth; ulong i, np = M->np; double* buf; FLINT_ASSERT(an > 0); ulong want_threads; if (an < 1500) want_threads = 1; else want_threads = np; thread_pool_handle* handles; slong nworkers = flint_request_threads(&handles, want_threads); ulong nthreads = nworkers + 1; buf = (double*) mpn_ctx_fit_buffer(R, np*M->stride*sizeof(double)); s1pworker_struct s1pargs[4]; for (i = 0; i < nthreads; i++) { s1pworker_struct* X = s1pargs + i; X->np = np; X->start_pi = (i+0)*np/nthreads; X->stop_pi = (i+1)*np/nthreads; X->offset = M->offset; X->abuf = buf; X->bbuf = M->bbuf; X->depth = depth; X->stride = M->stride; X->atrunc = M->btrunc; X->ztrunc = M->btrunc; X->a = a; X->an = an; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s1pworker_func, s1pargs + i); s1pworker_func(s1pargs + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); s2worker_struct s2args[8]; ulong zl = 0; ulong zh = ztrunc; ulong o = zl; for (i = 0; i < nthreads; i++) { s2worker_struct* X = s2args + i; X->z = z; X->zl = zl; X->start_zi = o; ulong newo = n_round_down(zl + (i+1)*(zh-zl)/nthreads, BLK_SZ); o = i+1 < nthreads ? FLINT_MAX(o, newo) : zh; X->stop_zi = o; X->buf = buf; X->offset = M->offset; X->stride = M->stride; X->ffts = R->ffts; X->crts = R->crts; X->mod = mod; X->f = np == 1 ? _crt_1 : np == 2 ? _crt_2 : np == 3 ? _crt_3 : _crt_4; } for (i = nworkers; i > 0; i--) thread_pool_wake(global_thread_pool, handles[i - 1], 0, s2worker_func, s2args + i); s2worker_func(s2args + 0); for (i = nworkers; i > 0; i--) thread_pool_wait(global_thread_pool, handles[i - 1]); flint_give_back_threads(handles, nworkers); } /* z -= a mod x^N-1, write coeffs [0,ztrunc) */ void _nmod_poly_sub_mod_xpNm1( ulong* z, ulong ztrunc, const ulong* a, ulong an, ulong N, nmod_t mod) { FLINT_ASSERT(ztrunc <= an); FLINT_ASSERT(ztrunc <= N); for (ulong i = 0; i < ztrunc; i++) { ulong k = i; ulong c = nmod_sub(a[k], z[i], mod); for (k += N; k < an; k += N) c = nmod_add(c, a[k], mod); z[i] = c; } } /* for divrem(a, b) an = length(a) bn = length(b) qn = length(q) = an - bn + 1 choose a precision Bn of B(x) = B[0] + ... + B[Bn-1]*x^(Bn-1) with rev(B) = rev(b)^-1 mod x^Bn = B[Bn-1] + B[Bn-2]*x + ... + B[0]*x^(Bn-1) then (a[an-1] + a[an-2]*x + ... + a[an-qn]*x^(qn-1)) * (B[Bn-1] + B[Bn-2]*x + ... + B[0]*x^(Bn-1)) = q[qn-1] + q[qn-2]*x + ... + q[0]*x^(qn-1) mod x^qn therefore need Bn >= qn, or, the same thing, Bn >= an - bn + 1 in terms of non-reversed polys, _mul_mid(q, an+Bn-1-qn, an+Bn-1, a, an, B, Bn) or, the same thing, _mul_mid(q, Bn-1, Bn-1+qn, a+an-qn, qn, B, Bn) will calculate q. Then, find r via r = a - b*q mod x^N-1 where N >= bn - 1 */ void _nmod_poly_divrem_mpn_ctx( ulong* q, ulong* r, const ulong* a, ulong an, const ulong* b, ulong bn, nmod_t mod, mpn_ctx_t R) { ulong qn = an - bn + 1; FLINT_ASSERT(an >= bn); FLINT_ASSERT(bn > 1); FLINT_ASSERT(qn > 0); /* choose precision */ ulong Bn = qn; ulong lgN = n_max(LG_BLK_SZ, n_clog2(bn-1)); ulong N = n_pow2(lgN); ulong* B = FLINT_ARRAY_ALLOC(Bn, ulong); ulong* t = FLINT_ARRAY_ALLOC(FLINT_MAX(N, bn), ulong); _nmod_poly_reverse(t, b, bn, bn); _nmod_poly_inv_series(B, t, bn, Bn, mod); _nmod_poly_reverse(B, B, Bn, Bn); _nmod_poly_mul_mid_mpn_ctx(q, Bn-1, Bn-1+qn, a+an-qn, qn, B, Bn, mod, R); _nmod_poly_mul_mod_xpnm1(r, bn-1, q, qn, b, bn, lgN, mod, R); _nmod_poly_sub_mod_xpNm1(r, bn-1, a, an, N, mod); flint_free(B); flint_free(t); } void _nmod_poly_divrem_precomp_init( nmod_poly_divrem_precomp_struct* M, const ulong* b, ulong bn, ulong Bn, nmod_t mod, mpn_ctx_t R) { ulong* B = FLINT_ARRAY_ALLOC(Bn, ulong); ulong* t = FLINT_ARRAY_ALLOC(bn, ulong); _nmod_poly_reverse(t, b, bn, bn); _nmod_poly_inv_series(B, t, bn, Bn, mod); _nmod_poly_reverse(B, B, Bn, Bn); _mul_precomp_init(M->quo_maker, B, Bn, Bn, n_max(LG_BLK_SZ, n_clog2(2*Bn-1)), mod, R); ulong lgN = n_max(LG_BLK_SZ, n_clog2(bn-1)); ulong N = n_pow2(lgN); _mul_precomp_init(M->rem_maker, b, bn, N, lgN, mod, R); flint_free(B); flint_free(t); } int _nmod_poly_divrem_precomp( ulong* q, ulong* r, const ulong* a, ulong an, nmod_poly_divrem_precomp_struct* M, nmod_t mod, mpn_ctx_t R) { ulong Bn = M->quo_maker->bn; ulong bn = M->rem_maker->bn; ulong qn = an-bn+1; FLINT_ASSERT(an >= bn); FLINT_ASSERT(bn > 1); FLINT_ASSERT(qn > 0); if (!_nmod_poly_mul_mid_precomp(q, Bn-1, Bn-1+qn, a+an-qn, qn, M->quo_maker, mod, R)) return 0; _nmod_poly_mul_mod_xpnm1_precomp(r, bn-1, q, qn, M->rem_maker, mod, R); _nmod_poly_sub_mod_xpNm1(r, bn-1, a, an, M->rem_maker->N, mod); return 1; } /* definition of _mul_mid(z, zl, zh, a, an, b, bn) h [sum z[i]*x^i] := sum z[i]*x^(i-l) i l l<=i= zh) return; if (an < bn) { FLINT_SWAP(const ulong *, a, b); FLINT_SWAP(ulong, an, bn); } if (zl > bn - 1) { if (an > zl - (bn - 1)) { an -= zl - (bn - 1); a += zl - (bn - 1); zh -= zl - (bn - 1); zl -= zl - (bn - 1); _nmod_poly_mul_mid(z, zl, zh, a, an, b, bn, mod); } else { flint_mpn_zero(z, zh - zl); } return; } if (zh < an) { an = zh; _nmod_poly_mul_mid(z, zl, zh, a, an, b, bn, mod); return; } FLINT_ASSERT(zl < bn && bn <= an && an <= zh); if (an >= 2*bn) { _nmod_poly_mul_mid_unbalanced(z, zl, zh, a, an, b, bn, mod); return; } if (zl < an + bn + 1) { if (zh > 0) { /* middle product or three pieces +----------------+ | |\ | | 1 | \| | |3 | |-------------+--| |\ 2 | +----------------+ */ } else if (0) { /* two pieces +----------------+ | |\ | | | \| | 1 |2 | | | | | | | +-------------+--+ */ } else { /* two pieces +----------------+ | \ | | \ | |------------ \ | | \ | | \| +----------------+ */ } } else { if (zh > 0) { /* two pieces +----------------+ | | | | | | |1| 2 | | | | |\| | +----------------+ */ } } _nmod_poly_mul_mid_classical(z, zl, zh, a, an, b, bn, mod); return; } flint-3.1.3/src/fft_small/profile/000077500000000000000000000000001461254215100170315ustar00rootroot00000000000000flint-3.1.3/src/fft_small/profile/p-fft_small_vs_gmp.c000066400000000000000000000040741461254215100227610ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #if FLINT_HAVE_FFT_SMALL #include "fft_small.h" #include "profiler.h" #define N_MIN_MUL 1500 #define N_MAX_MUL 1600 #define N_MIN_SQR 2900 #define N_MAX_SQR 3200 int main(void) { mp_ptr x, y, r, s; slong n; x = flint_malloc(sizeof(mp_limb_t) * FLINT_MAX(N_MAX_MUL, N_MAX_SQR)); y = flint_malloc(sizeof(mp_limb_t) * FLINT_MAX(N_MAX_MUL, N_MAX_SQR)); r = flint_malloc(2 * sizeof(mp_limb_t) * FLINT_MAX(N_MAX_MUL, N_MAX_SQR)); s = flint_malloc(2 * sizeof(mp_limb_t) * FLINT_MAX(N_MAX_MUL, N_MAX_SQR)); mpn_random2(x, FLINT_MAX(N_MAX_MUL, N_MAX_SQR)); mpn_random2(y, FLINT_MAX(N_MAX_MUL, N_MAX_SQR)); flint_printf("mpn_mul_n vs fft_small\n\n"); for (n = N_MIN_MUL; n <= N_MAX_MUL; n += 5) { double t1, t2, FLINT_SET_BUT_UNUSED(__); flint_printf("n = %4wd: ", n); TIMEIT_START mpn_mul_n(r, x, y, n); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START mpn_mul_default_mpn_ctx(s, x, n, y, n); TIMEIT_STOP_VALUES(__, t2) flint_printf("%.2f\n", t1 / t2); } flint_printf("mpn_sqr vs fft_small\n\n"); for (n = N_MIN_SQR; n <= N_MAX_SQR; n += 10) { double t1, t2, FLINT_SET_BUT_UNUSED(__); flint_printf("n = %4wd: ", n); TIMEIT_START mpn_sqr(r, x, n); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START mpn_mul_default_mpn_ctx(s, x, n, x, n); TIMEIT_STOP_VALUES(__, t2) flint_printf("%.2f\n", t1 / t2); } flint_free(x); flint_free(y); flint_free(r); flint_free(s); flint_cleanup_master(); return 0; } #else int main(void) { return 0; } #endif flint-3.1.3/src/fft_small/profile/p-mul.c000066400000000000000000000215651461254215100202400ustar00rootroot00000000000000#include "ulong_extras.h" #include "fft_small.h" #include "profiler.h" void flint_print_d_fixed(double x, ulong l) { ulong i; TMP_INIT; TMP_START; char* s = TMP_ARRAY_ALLOC(l + 1, char); for (i = 0; i < l; i++) s[i] = ' '; s[l] = 0; ulong y = fabs(rint(x)); while (l > 0) { s[--l] = '0' + (y%10); y = y/10; if (y == 0) break; } printf("%s", s); TMP_END; } void flint_print_d_fixed_dot(double x, ulong l, ulong r) { ulong i; TMP_INIT; TMP_START; char* s = TMP_ARRAY_ALLOC(l + r + 2, char); for (i = 0; i < l + r + 1; i++) s[i] = ' '; s[l + r + 1] = 0; s[l] = '.'; ulong y = fabs(rint(x*n_pow(10, r))); while (r > 0) { --r; s[l+1+r] = '0' + (y%10); y = y/10; } while (l > 0) { --l; s[l] = '0' + (y%10); y = y/10; if (y == 0) break; } printf("%s", s); TMP_END; } void profile_mul( mpn_ctx_t Q, int min_lg_bit_size, int max_lg_bit_size, int for_latex, int with_precomp) { timeit_t timer; int first = 1; min_lg_bit_size = FLINT_MAX(min_lg_bit_size, 12); for (int lg_bit_size = min_lg_bit_size; lg_bit_size < max_lg_bit_size; lg_bit_size++) { ulong max_len = n_pow2(1+lg_bit_size-6); ulong* data = FLINT_ARRAY_ALLOC(max_len*2, ulong); for (ulong i = 0; i < max_len; i++) data[i] = -(ulong)(1+i); double total_precomp = 0; double max_precomp = 0; ulong nprecomp_samples = 0; for (int ci = 0; ci < 10; ci++) { ulong cn = max_len/2*pow(2.0, ci*1.0/10); ulong cbits = cn*64; double lgcbits = log2(cbits); ulong nsamples = 0; double total_time = 0; double max_time = 0; double min_time = 1.0e100; for (ulong an = (cn+1)/2; an <= 3*cn/4; an += 1+an/12) /* usually 1+an/12 */ { ulong bn = cn - an; if (!(bn <= an && an < cn)) continue; nsamples++; ulong* a = data; ulong* b = data + an; ulong* c = data + max_len; double precomp = 0; if (with_precomp) { timeit_start_us(timer); mpn_ctx_mpn_mul(Q, c, a, an, b, bn); timeit_stop_us(timer); precomp = (double)timer->wall; nprecomp_samples++; } ulong nreps = 1 + 30000000/(cn*n_clog2(cn)); timeit_start_us(timer); for (ulong rep = 0; rep < nreps; rep++) mpn_ctx_mpn_mul(Q, c, a, an, b, bn); timeit_stop_us(timer); double time = ((double)timer->wall)/nreps; precomp -= time; precomp = precomp*1e5/(lgcbits*cbits); max_precomp = FLINT_MAX(max_precomp, precomp); total_precomp += precomp; time = time*1e5/(lgcbits*cbits); total_time += time; min_time = FLINT_MIN(min_time, time); max_time = FLINT_MAX(max_time, time); } if (nsamples < 1) continue; if (for_latex) { if (!first) flint_printf(","); flint_printf("(%f,%f),", lgcbits, min_time); flint_printf("(%f,%f),", lgcbits, total_time/nsamples); flint_printf("(%f,%f)", lgcbits, max_time); } else { flint_print_d_fixed_dot(lgcbits, 2, 2); flint_printf(":"); flint_print_d_fixed_dot(total_time/nsamples, 3, 3); flint_print_d_fixed_dot(min_time, 3, 3); flint_print_d_fixed_dot(max_time, 3, 3); flint_printf("\n"); } fflush(stdout); first = 0; } if (!for_latex && nprecomp_samples > 0) { flint_printf("precomp: avg %f, max %f\n", total_precomp/nprecomp_samples, max_precomp); } flint_free(data); } } void profile_mul_gmp( int min_lg_bit_size, int max_lg_bit_size, int for_latex, int with_precomp) { timeit_t timer; int first = 1; min_lg_bit_size = FLINT_MAX(min_lg_bit_size, 12); for (int lg_bit_size = min_lg_bit_size; lg_bit_size < max_lg_bit_size; lg_bit_size++) { ulong max_len = n_pow2(1+lg_bit_size-6); ulong* data = FLINT_ARRAY_ALLOC(max_len*2, ulong); for (ulong i = 0; i < max_len; i++) data[i] = -(ulong)(1+i); double total_precomp = 0; double max_precomp = 0; ulong nprecomp_samples = 0; for (int ci = 0; ci < 10; ci++) { ulong cn = max_len/2*pow(2.0, ci*1.0/10); ulong cbits = cn*64; double lgcbits = log2(cbits); ulong nsamples = 0; double total_time = 0; double max_time = 0; double min_time = 1.0e100; for (ulong an = (cn+1)/2; an <= 3*cn/4; an += 1+an/12) { ulong bn = cn - an; if (!(bn <= an && an < cn)) continue; nsamples++; ulong* a = data; ulong* b = data + an; ulong* c = data + max_len; double precomp = 0; if (with_precomp) { timeit_start(timer); mpn_mul(c, a, an, b, bn); timeit_stop(timer); precomp = (double)timer->wall; nprecomp_samples++; } ulong nreps = 1 + 20000000/(cn*n_clog2(cn)); timeit_start(timer); for (ulong rep = 0; rep < nreps; rep++) mpn_mul(c, a, an, b, bn); timeit_stop(timer); precomp -= ((double)timer->wall)/nreps; max_precomp = FLINT_MAX(max_precomp, precomp*1e8/(lgcbits*cbits)); total_precomp += precomp*1e8/(lgcbits*cbits); double time = ((double)timer->wall)*1e8/(lgcbits*cbits*nreps); total_time += time; min_time = FLINT_MIN(min_time, time); max_time = FLINT_MAX(max_time, time); } if (nsamples < 1) continue; if (for_latex) { if (!first) flint_printf(","); flint_printf("(%f,%f),", lgcbits, min_time); flint_printf("(%f,%f),", lgcbits, total_time/nsamples); flint_printf("(%f,%f)", lgcbits, max_time); } else { flint_print_d_fixed_dot(lgcbits, 2, 2); flint_printf(":"); flint_print_d_fixed_dot(total_time/nsamples, 3, 3); flint_print_d_fixed_dot(min_time, 3, 3); flint_print_d_fixed_dot(max_time, 3, 3); flint_printf("\n"); } fflush(stdout); first = 0; } if (!for_latex && nprecomp_samples > 0) { flint_printf("precomp: %f, %f\n", total_precomp/nprecomp_samples, max_precomp); } flint_free(data); } } /* some notes on precomp: (1) the global twiddle factors need to be precomputed (2) when the big buffer for temp space needs to be reallocated, the accesses to the new space all incur page faults. These occur out of order in the beginning of the calculation and contribute noticably to the run time. Therefore, there is a penalty for the first run of a computation of a certain size. If the data comes out like 24.00: 2.856 2.831 2.980 24.10: 2.827 2.769 2.885 24.20: 2.984 2.948 3.055 24.30: 2.939 2.889 3.038 24.40: 3.062 3.055 3.101 24.50: 3.049 2.982 3.097 24.60: 3.082 3.037 3.144 24.70: 3.053 2.971 3.169 24.80: 2.999 2.899 3.083 24.90: 2.979 2.950 2.993 precomp: avg 0.073270, max 0.852562 this means that the penalty on average was 0.073270/3 = 2.5% and at most 0.85/3 = 28.3% */ int main(void) { mpn_ctx_t R; #if 0 int cpu_affinities[32]; for (int i = 0; i < 32; i++) cpu_affinities[i] = i; #endif mpn_ctx_init(R, UWORD(0x0003f00000000001)); /* the majority of the precomp is reallocating the temp buffer (2) */ // mpn_ctx_fit_buffer(R, 1610620928); flint_printf(" --- fft_small 1 thread --- \n"); flint_set_num_threads(1); profile_mul(R, 20, 26, 0, 1); #if 0 flint_printf(" --- fft_small 8 threads --- \n"); flint_set_num_threads(8); profile_mul(R, 20, 28, 1, 1); mpn_ctx_clear(R); #endif #if 0 flint_printf(" --- gmp --- \n"); profile_mul_gmp(12, 31, 1, 1); #endif mpn_ctx_clear(R); return 0; } flint-3.1.3/src/fft_small/profile/p-nmod_poly_divrem.c000066400000000000000000000250451461254215100230060ustar00rootroot00000000000000#include "nmod.h" #include "nmod_poly.h" #include "fft_small.h" #include "profiler.h" /* speed up of 2n-3 by n division with divisor precomp: ---> log2(n) | | nbits(mod.n) with ** denoting a special fft prime v 1 thread: 9.0 9.6 10.1 10.7 11.3 11.9 12.5 13.1 13.6 14.2 14.8 15.4 16.0 16.6 17.2 17.7 18.3 18.9 19.5 **: 15.3 15.1 14.9 20.3 19.9 28.3 24.5 19.0 25.0 25.5 30.2 28.7 29.9 31.2 28.6 32.7 28.9 36.0 29.9 2: 1.0 1.0 1.0 1.5 1.5 1.9 2.1 2.1 2.6 2.9 3.6 3.3 4.1 4.2 3.8 4.3 3.6 5.1 5.5 4: 1.2 1.4 1.4 1.8 2.0 2.7 2.6 2.7 3.7 3.8 4.4 4.3 5.4 4.3 3.9 4.8 5.0 5.9 6.1 6: 1.6 1.8 1.8 2.4 2.4 3.1 3.3 3.1 4.4 4.2 5.2 4.7 5.8 5.5 5.0 6.8 5.3 6.6 6.1 8: 2.0 2.0 2.0 2.8 2.9 3.9 3.9 3.8 5.2 5.0 6.2 5.3 7.4 6.8 5.6 6.1 6.1 8.7 7.4 10: 2.4 2.4 2.5 3.3 3.3 4.4 4.6 4.7 5.9 5.9 6.6 6.6 7.9 6.9 6.2 8.6 8.4 9.5 7.6 12: 2.9 2.7 2.9 3.9 3.9 5.1 5.3 5.3 6.5 6.0 7.7 7.4 9.4 6.7 6.4 9.4 8.3 10.5 8.0 14: 3.2 3.4 3.3 4.5 4.5 6.4 6.2 5.7 7.4 6.8 8.4 7.3 9.5 9.4 8.5 9.7 7.8 10.7 11.1 16: 3.8 3.5 3.6 4.9 5.1 6.6 6.2 6.7 8.3 7.5 9.5 9.2 11.7 6.1 3.6 4.9 5.3 6.0 5.3 18: 4.2 4.0 4.1 5.6 5.5 7.8 4.4 3.3 4.2 3.5 4.3 4.7 5.3 4.9 3.6 5.4 5.3 6.0 5.6 20: 2.5 2.0 2.1 2.7 2.8 3.7 3.7 3.6 4.7 4.3 5.1 4.4 5.4 5.0 5.2 6.8 6.0 6.0 6.3 22: 2.1 2.2 2.3 2.9 3.2 4.2 4.0 3.8 4.7 4.4 5.7 5.3 5.2 5.0 5.2 6.3 6.1 6.0 6.9 24: 2.3 2.4 2.5 3.3 3.5 4.4 4.5 4.2 5.5 4.7 5.7 5.3 6.9 6.9 5.6 6.9 6.2 7.3 8.0 26: 2.5 2.6 2.8 3.6 3.6 4.7 4.9 4.7 5.5 6.0 5.9 5.5 7.5 7.0 5.8 6.9 6.1 8.5 7.8 28: 3.0 3.0 3.1 4.1 4.2 5.3 5.3 4.8 6.1 5.6 7.2 6.8 7.8 6.6 6.7 6.6 6.5 9.4 8.6 30: 3.2 3.3 3.3 4.4 4.5 5.7 6.0 5.3 6.1 5.7 7.9 6.8 8.0 6.8 6.4 9.4 7.8 10.0 8.1 32: 3.6 3.6 3.6 4.7 4.7 6.2 5.9 5.7 6.3 6.4 7.8 7.1 8.9 6.8 6.4 9.3 7.8 9.9 8.8 34: 3.7 3.9 3.8 5.0 5.0 6.8 6.6 6.0 7.3 6.9 7.8 7.1 9.1 9.2 8.9 10.7 7.8 10.5 8.8 36: 3.8 4.1 4.1 5.4 5.5 7.3 6.6 6.0 7.5 7.2 8.1 7.2 9.0 9.9 8.5 10.5 7.6 11.1 11.0 38: 4.1 4.4 4.2 5.8 5.7 7.6 7.4 6.8 8.2 7.3 9.7 7.1 8.7 9.8 8.6 10.0 7.7 11.4 11.0 40: 4.4 4.7 4.5 6.1 6.2 8.1 7.5 6.8 8.4 7.4 9.4 9.3 11.2 10.3 8.4 11.0 6.1 9.1 6.8 42: 4.5 5.0 4.6 6.5 6.3 8.5 7.9 7.0 8.6 5.5 6.8 6.0 7.1 6.1 5.5 6.8 7.1 8.7 7.9 44: 4.9 5.2 3.8 4.9 4.2 5.4 5.2 4.4 5.7 4.8 5.8 6.1 7.0 6.4 5.1 7.0 7.2 8.7 8.0 46: 3.4 3.5 3.4 4.4 4.4 5.7 5.3 4.8 5.8 5.7 7.3 6.4 7.0 8.0 5.2 7.2 7.7 9.0 8.1 48: 3.6 3.6 3.5 4.7 4.5 6.3 5.3 4.8 6.1 5.8 7.2 6.7 7.2 7.6 7.3 8.6 8.2 9.3 8.6 50: 3.7 3.7 3.7 4.8 4.9 6.4 6.0 4.7 6.0 6.2 7.2 6.9 7.1 7.3 7.3 8.5 7.8 9.4 8.9 52: 3.7 3.7 3.8 4.8 5.1 6.2 6.1 5.0 6.4 6.1 7.5 7.0 7.1 7.7 7.7 8.6 8.0 8.8 9.2 54: 3.7 3.9 4.0 5.1 5.3 6.7 6.4 5.7 7.1 6.3 7.5 7.0 7.0 7.2 7.7 8.7 9.0 8.8 9.5 56: 3.9 4.0 4.1 5.3 5.4 6.7 6.4 5.8 7.1 6.2 7.5 7.0 9.7 9.9 8.0 8.8 9.0 8.9 9.6 58: 4.0 4.2 4.3 5.6 5.5 6.7 6.4 5.8 7.2 6.3 7.4 7.0 10.0 10.1 8.2 8.9 9.0 10.6 11.1 60: 4.3 4.3 4.6 5.7 5.8 7.3 7.0 6.4 8.0 7.6 7.5 7.1 10.4 9.5 8.8 8.7 9.5 11.7 11.0 62: 4.5 4.6 4.8 6.0 6.1 7.8 7.3 6.6 8.2 7.5 7.6 7.3 10.4 9.8 9.0 8.8 9.1 11.8 10.8 64: 4.7 4.8 5.0 6.4 6.4 8.0 7.3 6.5 7.8 7.6 9.9 9.2 10.6 9.2 8.9 8.7 10.1 12.4 12.0 8 threads: 9.0 9.6 10.1 10.7 11.3 11.9 12.5 13.1 13.6 14.2 14.8 15.4 16.0 16.6 17.2 17.7 18.3 18.9 19.5 **: 15.4 16.1 14.9 20.2 20.1 26.4 25.8 19.0 26.4 25.5 29.6 26.8 30.1 29.3 30.2 32.8 28.8 37.1 29.9 2: 1.0 1.1 1.1 1.5 1.5 1.9 2.0 2.1 2.8 3.0 3.5 3.3 4.4 4.0 4.0 4.5 3.6 4.9 5.8 4: 1.4 1.4 1.3 1.8 2.0 2.7 2.6 2.6 3.4 3.7 4.4 4.2 5.3 4.6 3.9 4.8 5.2 6.2 5.9 6: 1.6 1.7 1.7 2.3 2.3 3.1 3.4 3.1 4.4 4.4 5.5 4.7 5.5 5.5 5.2 6.8 5.2 6.6 6.3 8: 2.0 2.1 2.1 2.7 2.8 4.0 3.9 3.6 5.2 4.7 5.8 5.6 7.5 7.1 5.6 6.1 6.2 8.7 7.4 10: 2.4 2.5 2.5 3.3 3.3 4.4 4.7 4.7 5.6 5.9 6.2 6.6 7.4 6.9 6.3 8.5 8.5 9.5 7.6 12: 2.8 2.9 2.7 3.8 3.9 5.1 5.3 5.3 6.4 5.8 7.6 7.5 8.8 6.9 6.4 9.0 8.2 10.4 7.6 14: 3.2 3.3 3.2 4.5 4.5 6.0 6.1 6.0 7.1 7.3 7.9 7.3 9.5 8.9 8.6 9.7 7.8 10.8 11.1 16: 3.6 3.8 3.5 4.9 5.1 6.6 6.6 6.4 8.2 7.5 9.6 9.3 11.7 9.7 6.7 9.0 9.7 10.6 9.2 18: 4.2 4.0 4.1 5.6 5.8 7.4 5.5 6.0 7.4 6.6 8.0 9.0 10.2 9.1 6.8 9.8 9.4 10.2 9.5 20: 1.9 1.9 2.5 3.4 4.1 5.7 6.4 6.3 8.4 7.9 9.6 8.5 10.2 9.7 9.5 12.5 10.8 10.6 10.6 22: 1.4 2.1 2.8 3.9 4.7 6.5 7.0 7.0 8.4 8.2 10.7 10.1 9.9 9.4 9.4 11.4 11.1 10.6 11.8 24: 1.5 2.3 3.0 4.2 5.3 6.8 7.7 7.7 9.9 8.9 10.4 10.1 13.5 12.8 10.3 13.0 11.0 12.9 13.8 26: 1.6 2.5 3.3 4.6 5.5 7.2 8.5 8.3 10.1 11.2 10.6 10.5 14.2 13.2 10.7 12.5 10.8 15.1 13.2 28: 1.9 2.9 3.8 5.4 6.1 8.2 9.2 8.7 11.0 10.5 13.0 12.8 15.3 12.3 12.5 11.8 11.2 17.1 14.3 30: 2.1 3.1 4.0 5.7 6.7 9.2 10.2 9.6 11.0 10.7 14.4 13.0 15.3 12.4 12.1 17.7 13.6 17.4 14.1 32: 2.3 3.4 4.3 5.9 6.9 9.5 10.2 10.2 11.8 11.6 14.2 13.6 16.9 12.4 12.1 16.7 13.8 17.5 14.6 34: 2.5 3.6 4.6 6.5 7.4 10.3 11.1 10.8 13.4 12.8 15.2 13.4 16.1 16.8 16.0 19.2 13.9 18.8 15.1 36: 2.5 3.9 4.9 6.8 8.0 11.4 11.1 10.8 13.5 13.6 15.4 14.1 17.1 18.5 15.0 19.5 14.2 19.5 19.0 38: 2.7 4.1 5.1 7.4 8.3 11.9 12.7 12.3 14.2 13.6 18.0 13.7 16.3 18.7 15.7 18.4 14.3 19.7 19.1 40: 2.8 4.4 5.5 8.1 9.4 12.6 12.9 12.2 15.4 13.8 17.0 17.7 22.1 18.9 15.8 20.1 12.3 18.9 14.9 42: 3.0 4.6 5.8 8.1 9.6 12.7 13.5 12.6 14.9 12.4 15.8 16.1 19.1 16.5 13.7 16.5 16.4 20.2 16.5 44: 3.1 4.9 5.8 7.8 9.3 12.1 12.8 11.7 15.6 14.0 15.8 17.2 18.8 16.5 12.9 17.7 16.0 20.1 16.8 46: 3.4 4.3 5.8 8.3 9.6 12.6 12.8 12.8 15.8 15.8 20.4 17.8 18.9 21.4 12.5 17.2 17.4 20.7 17.1 48: 3.6 4.5 6.1 8.4 10.0 14.0 12.8 12.9 15.5 16.4 20.4 18.9 18.9 21.0 19.0 20.6 18.7 21.4 18.0 50: 3.8 4.6 6.4 9.2 10.9 14.5 14.7 12.4 15.5 17.0 19.7 19.4 19.1 19.6 18.2 21.7 17.3 21.8 19.4 52: 4.0 4.7 6.4 9.3 11.5 14.0 15.1 13.7 17.6 17.3 20.7 19.9 18.3 21.2 19.9 21.0 17.4 20.4 20.4 54: 4.0 5.0 6.8 10.0 11.6 15.2 15.9 14.9 19.2 17.0 20.9 19.1 19.3 19.8 19.4 22.2 20.0 20.4 20.1 56: 4.3 5.0 7.1 10.2 12.0 14.8 15.4 15.6 18.4 17.4 20.7 19.1 26.5 27.0 20.1 21.5 19.4 20.5 20.3 58: 4.3 5.4 7.7 10.6 12.2 14.7 15.9 15.8 19.1 17.1 21.6 20.1 26.8 27.2 20.1 22.6 20.6 24.6 23.8 60: 4.5 5.5 7.9 10.9 13.3 16.3 17.3 16.8 20.9 19.8 20.3 20.1 27.6 25.5 22.7 22.0 21.0 26.9 23.3 62: 4.7 5.7 8.0 11.3 13.4 17.5 18.1 18.0 21.3 20.7 21.5 20.3 27.6 26.1 22.8 21.1 20.5 26.9 22.9 64: 4.9 5.9 8.5 11.8 14.3 17.8 18.1 17.4 20.2 20.8 28.1 25.9 28.5 24.5 21.9 21.2 22.6 29.2 25.8 */ int main(void) { flint_bitcnt_t nbits; mpn_ctx_t R; nmod_t mod; flint_rand_t state; timeit_t timer; double time1, time2; ulong * a, * b, * q1, * q2, * r1, * r2; ulong an, bn, n, i, nreps; ulong nmax = 1000000; flint_randinit(state); mpn_ctx_init(R, UWORD(0x0003f00000000001)); flint_set_num_threads(8); flint_printf(" "); for (n = 500; n < nmax; n += 1 + n/2) flint_printf("%5.1f", log2(n)); flint_printf("\n"); for (nbits = 0; nbits <= FLINT_BITS; nbits += 2) { if (nbits == 0) { nmod_init(&mod, R->ffts[1].mod.n); flint_printf("**:"); } else { nmod_init(&mod, n_randbits(state, nbits)); flint_printf("%2wu:", nbits); } a = FLINT_ARRAY_ALLOC(2*nmax, ulong); b = FLINT_ARRAY_ALLOC(nmax, ulong); q1 = FLINT_ARRAY_ALLOC(nmax, ulong); q2 = FLINT_ARRAY_ALLOC(nmax, ulong); r1 = FLINT_ARRAY_ALLOC(nmax, ulong); r2 = FLINT_ARRAY_ALLOC(nmax, ulong); for (n = 500; n < nmax; n += 1 + n/2) { an = 2*n-3; bn = n; nreps = 1 + 10000000/(n*n_nbits(n)); for (i = 0; i < an; i++) a[i] = n_randint(state, mod.n); for (i = 0; i < bn; i++) b[i] = n_randint(state, mod.n); while (n_gcd(b[bn-1], mod.n) != 1) b[bn-1] = n_randint(state, mod.n); #if 1 { ulong* B = FLINT_ARRAY_ALLOC(n-2, ulong); _nmod_poly_reverse(b, b, bn, bn); _nmod_poly_inv_series(B, b, bn, n-2, mod); _nmod_poly_reverse(b, b, bn, bn); timeit_start(timer); for (i = 0; i < nreps; i++) _nmod_poly_divrem_newton_n_preinv(q1, r1, a, an, b, bn, B, n-2, mod); timeit_stop(timer); time1 = timer->wall*1e6/(nreps*log2(n)*n); flint_free(B); } { nmod_poly_divrem_precomp_struct M[1]; _nmod_poly_divrem_precomp_init(M, b, bn, n-2, mod, R); timeit_start(timer); for (i = 0; i < nreps; i++) _nmod_poly_divrem_precomp(q2, r2, a, an, M, mod, R); timeit_stop(timer); time2 = timer->wall*1e6/(nreps*log2(n)*n); _nmod_poly_divrem_precomp_clear(M); } #else timeit_start(timer); for (i = 0; i < nreps; i++) _nmod_poly_divrem(q1, r1, a, an, b, bn, mod); timeit_stop(timer); time1 = timer->wall*1e6/(nreps*log2(n)*n); timeit_start(timer); for (i = 0; i < nreps; i++) _nmod_poly_divrem_mpn_ctx(q2, r2, a, an, b, bn, mod, R); timeit_stop(timer); time2 = timer->wall*1e6/(nreps*log2(n)*n); #endif flint_printf("%5.1f", /*time2*/time1/time2); fflush(stdout); for (i = 0; i < an-bn+1; i++) { if (q1[i] != q2[i]) { flint_printf("error at index %wu\n", i); flint_printf("mod: %wu\n", mod.n); flint_abort(); } } for (i = 0; i < bn-1; i++) { if (r1[i] != r2[i]) { flint_printf("error at index %wu\n", i); flint_printf("mod: %wu\n", mod.n); flint_abort(); } } } flint_printf("\n"); flint_free(a); flint_free(b); flint_free(q1); flint_free(q2); flint_free(r1); flint_free(r2); } mpn_ctx_clear(R); flint_randclear(state); return 0; } flint-3.1.3/src/fft_small/profile/p-nmod_poly_mul.c000066400000000000000000000264411461254215100223160ustar00rootroot00000000000000#include "nmod.h" #include "nmod_poly.h" #include "fft_small.h" #include "profiler.h" /* speed up over _nmod_poly_mul: ---> log2(degree of product) | | nbits(mod.n) with ** denoting a special fft prime v 1 thread: 9.0 9.6 10.1 10.7 11.3 11.9 12.5 13.1 13.6 14.2 14.8 15.4 16.0 16.6 17.2 17.7 18.3 18.9 19.5 20.1 20.7 21.3 21.8 22.4 23.0 **: 4.8 5.3 5.3 6.7 7.7 8.8 9.4 9.3 11.2 10.1 14.1 13.8 13.6 13.9 14.7 15.7 14.1 14.2 14.7 14.6 16.0 14.1 16.9 14.1 11.9 2: 0.5 0.5 0.5 0.6 0.7 0.8 0.9 1.0 1.2 1.4 1.5 1.6 1.8 2.1 2.2 2.5 2.2 2.4 2.4 2.2 2.5 2.1 3.2 3.3 2.8 4: 0.6 0.6 0.6 0.7 0.9 1.1 1.1 1.1 1.5 1.6 1.9 2.0 2.4 2.5 2.2 2.9 2.8 3.1 2.9 2.3 2.7 3.1 3.2 3.4 3.9 6: 0.7 0.8 0.7 0.9 1.0 1.2 1.3 1.3 1.7 1.9 2.3 2.4 2.9 3.3 2.7 3.0 3.2 3.1 2.9 3.0 3.3 3.5 4.6 4.3 4.3 8: 0.8 0.8 0.9 1.1 1.3 1.5 1.4 1.4 1.9 2.2 2.6 2.8 3.5 3.9 3.0 3.5 3.2 3.9 3.6 3.4 3.3 3.5 5.2 4.3 5.0 10: 0.9 1.0 1.0 1.3 1.4 1.7 1.6 1.8 2.2 2.7 3.0 3.4 3.4 3.5 3.7 4.0 3.9 3.9 3.7 3.5 4.4 4.6 5.0 4.4 5.0 12: 1.0 1.2 1.2 1.4 1.6 2.0 1.8 2.1 2.5 2.7 3.4 3.4 4.4 3.7 3.7 4.4 4.1 5.0 4.3 3.6 4.5 4.6 4.9 6.0 6.2 14: 1.2 1.3 1.3 1.6 1.7 2.1 2.1 2.3 2.6 3.4 3.8 4.3 4.8 4.3 4.1 5.0 4.3 4.7 4.8 4.5 4.9 4.4 5.4 6.2 6.4 16: 1.3 1.4 1.4 1.7 1.9 2.2 2.4 2.5 3.1 3.7 4.3 4.7 5.9 4.8 4.3 5.0 5.2 6.0 2.3 2.1 2.6 2.2 2.5 3.3 2.6 18: 1.4 1.7 1.6 2.0 2.2 2.6 2.5 2.7 3.6 4.0 4.5 2.3 2.4 2.3 2.1 2.4 2.6 2.7 2.6 2.0 2.6 2.9 3.1 3.6 3.2 20: 1.5 1.8 1.7 2.1 2.4 1.2 1.2 1.4 1.6 2.1 2.3 2.5 2.6 2.5 2.5 2.7 2.4 2.6 2.6 2.9 3.3 3.3 3.1 3.5 3.7 22: 0.7 0.8 0.8 1.0 1.1 1.2 1.4 1.5 1.8 2.3 2.2 2.8 2.6 2.6 2.5 2.9 3.1 2.6 2.6 2.9 3.1 3.4 3.3 4.0 3.9 24: 0.8 0.8 0.9 1.1 1.2 1.4 1.5 1.6 1.9 2.3 2.7 2.6 3.0 3.0 2.9 3.0 2.9 3.5 3.4 3.2 3.5 3.6 4.4 4.5 4.4 26: 0.8 0.9 0.9 1.2 1.3 1.4 1.5 1.7 2.2 2.6 3.1 2.9 3.2 3.1 2.9 3.1 3.0 3.5 3.4 3.2 3.3 3.6 4.5 4.4 4.5 28: 0.9 1.1 1.1 1.3 1.5 1.7 1.9 2.0 2.5 2.7 3.3 3.5 3.4 3.2 3.3 3.8 3.7 3.9 3.4 3.7 3.5 4.4 4.9 4.8 5.0 30: 1.0 1.2 1.1 1.5 1.6 1.9 2.1 2.3 2.6 3.1 3.5 3.5 3.5 3.5 3.3 4.0 3.7 3.9 3.4 3.8 4.6 4.5 5.2 4.9 5.3 32: 1.1 1.2 1.2 1.5 1.7 2.1 2.0 2.1 2.6 2.8 3.3 3.5 3.9 3.4 3.4 4.3 3.9 4.3 3.4 3.7 4.6 4.5 4.9 5.0 5.1 34: 1.1 1.3 1.3 1.6 1.8 2.2 2.3 2.2 2.9 3.3 4.0 3.7 4.1 4.1 3.9 4.1 3.8 4.3 3.9 3.7 4.6 4.6 5.7 4.6 5.2 36: 1.2 1.4 1.4 1.8 1.8 2.2 2.5 2.5 3.1 3.6 4.2 3.8 4.2 4.2 4.0 4.1 3.8 4.3 5.0 4.6 5.3 4.6 5.6 5.9 6.0 38: 1.3 1.4 1.4 1.8 1.9 2.5 2.6 2.4 3.4 3.7 4.4 4.0 4.2 4.3 4.3 5.1 3.9 4.3 4.8 4.6 5.5 4.5 6.1 6.0 6.0 40: 1.3 1.5 1.6 1.9 2.2 2.5 2.6 2.8 3.5 3.8 4.5 4.3 4.8 4.6 4.3 4.8 4.5 5.1 4.9 4.8 3.5 2.9 4.0 4.0 3.6 42: 1.3 1.6 1.6 2.0 2.4 2.4 2.6 3.2 3.9 4.3 5.1 4.6 4.7 2.9 2.7 3.0 3.1 3.5 3.2 3.2 3.6 4.1 4.6 4.5 4.2 44: 1.4 1.6 1.7 2.1 2.4 2.6 1.9 2.0 2.3 2.5 3.2 3.0 3.1 3.0 2.7 3.0 3.2 3.5 3.3 3.0 3.5 4.0 4.7 4.6 4.5 46: 1.0 1.1 1.1 1.4 1.6 1.9 2.1 1.9 2.4 2.6 2.9 3.1 3.1 3.3 2.8 3.2 3.4 3.4 4.0 3.0 3.5 4.0 4.5 4.5 4.5 48: 1.1 1.2 1.2 1.4 1.6 2.0 2.1 2.0 2.5 3.1 3.1 3.0 3.4 3.3 3.6 3.8 3.6 3.4 3.8 3.0 3.7 4.5 4.9 5.1 4.4 50: 1.1 1.2 1.2 1.5 1.8 2.2 2.0 2.1 2.8 3.1 3.3 3.3 3.3 3.4 3.6 3.8 3.4 3.5 3.9 4.2 4.4 4.5 4.8 5.0 4.4 52: 1.1 1.2 1.2 1.5 1.8 2.0 2.3 2.5 2.7 3.6 3.3 3.4 3.3 3.3 3.5 3.8 3.5 3.4 3.7 4.5 4.5 4.6 4.9 5.0 5.0 54: 1.1 1.3 1.3 1.6 1.8 2.0 2.1 2.5 3.0 3.5 3.5 3.5 3.5 3.6 3.6 3.8 3.8 3.4 4.0 4.6 4.5 4.5 5.0 5.2 5.1 56: 1.2 1.3 1.4 1.6 2.0 2.1 2.2 2.6 2.8 3.6 3.5 3.6 3.9 3.9 3.6 3.9 3.8 4.1 3.8 4.2 4.7 5.4 5.1 5.5 5.5 58: 1.2 1.3 1.3 1.8 1.9 2.2 2.5 2.6 3.2 4.0 3.6 3.7 4.0 4.0 3.8 3.9 3.9 5.1 5.2 4.9 4.7 5.4 4.8 5.3 5.5 60: 1.1 1.4 1.4 1.7 2.0 2.4 2.9 3.0 3.2 3.8 3.9 3.8 4.2 4.2 3.7 3.9 3.9 4.9 4.9 4.9 4.6 5.3 6.0 6.2 5.9 62: 1.3 1.5 1.6 2.0 2.3 2.6 2.8 2.9 3.7 4.0 3.9 4.1 4.2 4.6 4.5 3.9 3.9 5.0 4.7 5.0 4.7 5.3 6.1 6.1 5.9 64: 1.4 1.6 1.6 2.0 2.2 2.8 2.9 3.0 3.5 3.7 4.1 4.3 4.5 4.4 4.6 4.0 4.0 4.9 5.1 5.1 4.7 5.8 6.3 6.1 6.2 8 threads: 9.0 9.6 10.1 10.7 11.3 11.9 12.5 13.1 13.6 14.2 14.8 15.4 16.0 16.6 17.2 17.7 18.3 18.9 19.5 20.1 20.7 21.3 21.8 22.4 23.0 **: 4.9 5.3 5.3 6.7 7.6 8.7 9.5 9.3 8.5 8.6 14.9 14.3 16.1 18.3 19.3 21.7 20.0 20.2 19.8 19.7 21.1 19.1 22.9 20.3 16.6 2: 0.5 0.5 0.5 0.6 0.7 0.8 0.9 1.0 1.0 1.6 1.7 1.8 2.4 2.9 3.3 3.9 3.5 3.7 3.5 3.0 3.6 2.9 4.6 4.7 4.0 4: 0.6 0.6 0.6 0.7 0.9 1.1 1.2 1.1 1.3 1.8 2.2 2.4 3.1 3.5 3.3 4.3 4.2 4.7 4.2 3.2 3.7 4.4 4.6 5.0 5.5 6: 0.7 0.8 0.7 0.9 1.0 1.2 1.3 1.3 1.5 1.9 2.6 3.0 3.6 4.4 4.0 4.7 4.7 4.8 4.2 4.2 4.7 5.0 6.5 6.3 6.3 8: 0.8 0.8 0.9 1.1 1.3 1.5 1.5 1.5 1.6 1.8 3.0 3.3 4.4 5.3 4.4 5.1 4.9 5.8 5.2 4.8 4.5 4.9 7.4 6.1 7.3 10: 0.9 1.1 1.0 1.3 1.4 1.6 1.6 1.8 1.8 2.7 3.4 4.0 4.3 4.7 5.4 6.2 5.7 6.1 5.4 4.9 6.2 6.7 7.0 6.2 7.2 12: 1.0 1.2 1.2 1.4 1.6 2.0 1.8 2.1 2.1 2.8 3.8 3.7 5.6 5.2 5.3 6.7 6.3 7.6 6.2 5.0 6.5 6.5 7.0 8.4 8.6 14: 1.2 1.3 1.3 1.6 1.8 2.1 2.1 2.2 2.3 3.4 4.1 4.9 6.1 5.9 6.1 7.6 6.5 7.3 6.9 6.3 6.9 6.2 7.7 8.7 9.0 16: 1.3 1.4 1.4 1.7 1.9 2.3 2.5 2.5 2.7 4.3 4.7 5.3 7.5 6.7 6.2 7.5 7.8 9.3 4.5 3.8 5.1 4.2 4.9 6.2 4.9 18: 1.4 1.6 1.6 2.0 2.2 2.6 2.5 2.6 3.0 4.4 5.1 4.4 4.6 4.7 4.3 5.2 5.2 5.2 5.0 3.9 5.0 5.5 6.2 7.1 6.1 20: 1.5 1.8 1.8 2.1 2.3 1.9 1.8 1.8 2.8 3.5 4.0 4.8 5.1 5.2 5.1 5.8 4.8 5.2 5.0 5.4 6.4 6.2 6.2 6.8 7.2 22: 0.5 0.7 0.9 1.3 1.6 1.9 2.1 2.0 3.0 3.6 3.8 5.0 5.1 5.3 5.2 5.9 6.0 5.2 5.0 5.5 6.2 6.5 6.5 7.6 7.4 24: 0.5 0.8 1.1 1.4 1.7 2.2 2.2 2.2 3.2 3.7 4.6 4.7 5.9 6.1 5.9 6.2 6.0 6.7 6.6 5.8 6.8 6.8 8.6 8.8 8.4 26: 0.5 0.8 1.1 1.5 1.8 2.3 2.2 2.2 3.9 4.3 5.1 5.4 6.3 6.4 6.0 6.3 5.9 7.0 6.6 5.8 6.4 6.8 8.8 8.4 8.5 28: 0.5 1.0 1.3 1.7 2.1 2.6 3.0 2.5 4.3 4.5 5.6 6.5 6.5 6.3 6.8 7.9 7.3 7.5 6.5 7.0 6.7 8.2 9.6 9.3 9.4 30: 0.6 1.0 1.3 1.9 2.3 3.1 3.1 3.0 4.5 4.9 5.9 6.3 6.8 7.0 6.9 8.3 7.3 7.6 6.7 7.1 8.9 8.5 10.2 9.5 10.0 32: 0.7 1.1 1.5 2.0 2.4 3.3 3.1 2.7 4.6 4.7 5.8 6.4 7.8 7.1 7.2 9.0 7.6 8.3 6.7 6.8 8.8 8.6 9.7 9.6 9.7 34: 0.7 1.2 1.5 2.1 2.6 3.5 3.5 2.8 5.2 5.3 6.9 6.7 8.0 8.3 8.1 8.5 7.6 8.3 7.6 6.7 8.8 8.6 11.1 9.0 9.9 36: 0.8 1.2 1.6 2.3 2.6 3.5 3.8 3.2 5.3 5.7 7.5 6.6 8.5 8.6 8.2 8.6 7.7 8.4 9.5 8.4 10.1 8.6 11.1 11.4 11.4 38: 0.8 1.3 1.7 2.4 2.8 4.0 3.7 3.1 6.2 5.8 7.5 7.6 8.2 8.5 8.7 10.3 7.9 8.3 9.2 8.7 10.6 8.5 12.2 11.7 11.5 40: 0.8 1.4 1.8 2.5 3.1 4.0 4.0 3.6 5.9 6.2 7.7 8.0 9.3 9.3 8.7 9.9 9.0 10.1 9.5 8.8 8.5 6.7 9.8 9.1 8.4 42: 0.9 1.5 1.9 2.6 3.4 3.9 4.0 4.1 6.6 7.1 9.1 8.2 9.4 8.7 7.8 8.4 7.9 9.0 7.7 7.2 8.6 9.4 11.1 10.5 9.9 44: 0.9 1.5 2.0 2.8 3.5 4.2 4.5 3.9 5.4 6.2 8.6 8.5 9.0 9.1 7.7 8.6 8.1 8.8 8.0 6.7 8.5 9.3 11.5 10.6 10.5 46: 1.0 1.3 1.7 2.6 3.6 4.1 4.7 3.9 6.0 6.5 7.6 8.5 9.0 9.9 8.2 8.7 8.3 8.6 9.6 6.8 8.6 9.2 11.1 10.6 10.5 48: 1.0 1.4 1.8 2.7 3.4 4.3 4.7 3.9 6.1 7.9 8.2 8.7 9.9 10.1 10.2 10.2 9.0 8.6 9.1 6.8 9.0 10.4 12.0 12.0 10.2 50: 1.1 1.5 1.9 2.9 3.8 4.8 4.3 4.1 6.4 8.0 8.7 9.4 9.9 10.4 10.2 10.5 8.6 8.6 9.4 9.5 10.7 10.4 11.6 12.0 10.1 52: 1.1 1.4 2.0 3.0 3.9 4.4 5.1 5.1 5.9 9.2 8.7 9.5 9.7 10.3 10.2 10.4 8.8 8.6 9.1 10.3 11.0 10.5 12.0 11.9 11.8 54: 1.2 1.6 2.1 3.2 4.1 4.4 4.9 4.9 6.5 9.0 9.3 10.1 10.3 10.9 10.3 10.5 9.5 8.5 9.7 10.6 10.9 10.5 12.1 12.4 11.8 56: 1.2 1.6 2.3 3.2 4.4 4.5 5.0 5.2 6.8 9.2 9.5 10.1 11.4 12.3 10.4 10.8 9.6 10.1 9.1 9.5 11.3 12.4 12.4 12.8 12.5 58: 1.3 1.6 2.1 3.4 4.3 4.8 5.5 5.9 8.1 10.4 9.3 10.6 11.7 11.9 10.6 11.0 9.7 12.9 12.5 11.1 11.3 12.6 11.8 12.5 12.7 60: 1.2 1.7 2.3 3.4 4.4 5.4 6.1 6.1 7.4 9.6 10.4 10.7 12.3 12.7 10.6 11.1 9.9 12.3 11.6 11.2 11.1 12.1 14.7 14.5 13.7 62: 1.4 1.9 2.6 3.9 5.0 5.7 6.4 5.9 8.5 10.3 10.3 11.3 12.2 13.5 12.6 10.7 9.6 12.5 11.4 11.5 11.0 12.4 15.0 14.5 13.5 64: 1.4 1.8 2.5 4.0 4.9 6.0 6.8 6.1 8.0 9.5 10.6 12.0 12.9 12.8 13.0 11.3 9.6 12.6 12.3 11.4 11.5 13.4 15.3 14.4 14.3 */ int main(void) { flint_bitcnt_t nbits; mpn_ctx_t R; nmod_t mod; flint_rand_t state; timeit_t timer; double time1, time2; ulong * a, * b, * c, * d; ulong an, bn, zn, i, nreps; ulong zn_max = 10000000; flint_randinit(state); mpn_ctx_init(R, UWORD(0x0003f00000000001)); //flint_set_num_threads(8); flint_printf(" "); for (zn = 500; zn < zn_max; zn += 1 + zn/2) flint_printf("%5.1f", log2(zn)); flint_printf("\n"); for (nbits = 0; nbits <= FLINT_BITS; nbits += 2) { if (nbits == 0) { nmod_init(&mod, R->ffts[1].mod.n); flint_printf("**:"); } else { nmod_init(&mod, n_randbits(state, nbits)); flint_printf("%2wu:", nbits); } a = FLINT_ARRAY_ALLOC(zn_max, ulong); b = FLINT_ARRAY_ALLOC(zn_max, ulong); c = FLINT_ARRAY_ALLOC(zn_max, ulong); d = FLINT_ARRAY_ALLOC(zn_max, ulong); for (zn = 500; zn < zn_max; zn += 1 + zn/2) { an = zn/2 + n_randint(state, 1 + zn/4); bn = 1 + zn - an; if (an < bn) FLINT_SWAP(ulong, an, bn); nreps = 1 + 100000000/(zn*n_nbits(zn)); for (i = 0; i < an; i++) a[i] = n_randint(state, mod.n); for (i = 0; i < bn; i++) b[i] = n_randint(state, mod.n); timeit_start(timer); for (i = 0; i < nreps; i++) _nmod_poly_mul(c, a, an, b, bn, mod); timeit_stop(timer); time1 = timer->wall*1e6/(nreps*log2(zn)*zn); timeit_start(timer); for (i = 0; i < nreps; i++) _nmod_poly_mul_mid_mpn_ctx(d, 0, an+bn-1, a, an, b, bn, mod, R); timeit_stop(timer); time2 = timer->wall*1e6/(nreps*log2(zn)*zn); flint_printf("%5.1f", /*time2*/time1/time2); fflush(stdout); for (i = 0; i < zn; i++) { if (c[i] != d[i]) { flint_printf("error at index %wu\n", i); flint_printf("mod: %wu\n", mod.n); flint_printf("zn: %wu, an: %wu, bn: %wu\n", zn, an, bn); flint_abort(); } } } flint_printf("\n"); flint_free(a); flint_free(b); flint_free(c); flint_free(d); } mpn_ctx_clear(R); flint_randclear(state); return 0; } flint-3.1.3/src/fft_small/profile/p-sd_fft.c000066400000000000000000000062351461254215100207050ustar00rootroot00000000000000#include "ulong_extras.h" #include "fft_small.h" #include "profiler.h" void flint_print_d_fixed(double x, ulong l) { ulong i; TMP_INIT; TMP_START; char* s = TMP_ARRAY_ALLOC(l + 1, char); for (i = 0; i < l; i++) s[i] = ' '; s[l] = 0; ulong y = fabs(rint(x)); while (l > 0) { s[--l] = '0' + (y%10); y = y/10; if (y == 0) break; } printf("%s", s); TMP_END; } void flint_print_d_fixed_dot(double x, ulong l, ulong r) { ulong i; TMP_INIT; TMP_START; char* s = TMP_ARRAY_ALLOC(l + r + 2, char); for (i = 0; i < l + r + 1; i++) s[i] = ' '; s[l + r + 1] = 0; s[l] = '.'; ulong y = fabs(rint(x*n_pow(10, r))); while (r > 0) { --r; s[l+1+r] = '0' + (y%10); y = y/10; } while (l > 0) { --l; s[l] = '0' + (y%10); y = y/10; if (y == 0) break; } printf("%s", s); TMP_END; } void record_time( int first, double len, double t1, double t2) { t1 *= 1e6; t2 *= 1e6; double depth = log2(len); flint_printf(first ? "depth" : " "); flint_print_d_fixed_dot(depth, 3,1); flint_printf(":"); flint_print_d_fixed_dot(5*len*depth/t1, 4,2); flint_print_d_fixed_dot(5*len*depth/t2, 4,2); flint_printf("\n"); } #define EXP_FAC 16 void profile_v2_fft(sd_fft_ctx_t Q, ulong minL, ulong maxL) { timeit_t timer; minL = n_max(minL, 10); maxL = n_max(maxL, minL + 1); timeit_start(timer); sd_fft_ctx_fit_depth(Q, maxL); timeit_stop(timer); flint_printf("depth %wu setup: %wd ms\n", maxL, timer->wall); minL = n_max(minL, n_clog2(Q->blk_sz) + 1); for (ulong L = minL+1; L <= maxL; L++) { double fft_time, ifft_time; ulong sz = sd_fft_ctx_data_size(L)*sizeof(double); double* data = flint_aligned_alloc(4096, n_round_up(sz, 4096)); // do 1/2*2^L < otrunc <= 2^L ulong otrunc = n_pow2(L-1); while (otrunc < n_pow2(L)) { otrunc = n_round_up(1+1+(EXP_FAC+1)*otrunc/EXP_FAC, Q->blk_sz); otrunc = n_min(otrunc, n_pow2(L)); ulong itrunc = n_round_up(otrunc/2, Q->blk_sz); for (ulong i = 0; i < n_pow2(L); i++) sd_fft_ctx_set_index(data, i, 0); ulong nreps = 1 + 300000000/(otrunc*n_clog2(otrunc)); timeit_start(timer); for (ulong i = 0; i < nreps; i++) sd_fft_ctx_fft_trunc(Q, data, L, itrunc, otrunc); timeit_stop(timer); fft_time = timer->wall; timeit_start(timer); for (ulong i = 0; i < nreps; i++) sd_fft_ctx_ifft_trunc(Q, data, L, otrunc); timeit_stop(timer); ifft_time = timer->wall; record_time(otrunc == n_pow2(L), otrunc, fft_time/nreps, ifft_time/nreps); } flint_free(data); } } int main(void) { sd_fft_ctx_t Q; sd_fft_ctx_init_prime(Q, UWORD(0x0003f00000000001)); flint_printf("--- v2 fft/ifft gflops ---\n"); profile_v2_fft(Q, 10, 20); sd_fft_ctx_clear(Q); return 0; } flint-3.1.3/src/fft_small/sd_fft.c000066400000000000000000000604331461254215100170100ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fft_small.h" /* N is supposed to be a good fit for the number of points to process per loop in the radix 4 butterflies. 16x 4-wide AVX registers => N = 8 32x 2-wide NEON registers => N = 8 32x 8-wide AVX512 registers => N = ? */ #define N 8 #define VECND vec8d #define VECNOP(op) vec8d_##op /********************* forward butterfly ************************************** b0 = a0 + w*a1 b1 = a0 - w*a1 */ #define RADIX_2_FORWARD_PARAM_J_IS_Z(V, Q) \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); #define RADIX_2_FORWARD_MOTH_J_IS_Z(V, X0, X1) \ { \ V x0, x1; \ x0 = V##_load(X0); \ x0 = V##_reduce_to_pm1n(x0, n, ninv); \ x1 = V##_load(X1); \ x1 = V##_reduce_to_pm1n(x1, n, ninv); \ V##_store(X0, V##_add(x0, x1)); \ V##_store(X1, V##_sub(x0, x1)); \ } #define RADIX_2_FORWARD_PARAM_J_IS_NZ(V, Q, j_r, j_bits) \ V w = V##_set_d(Q->w2tab[j_bits][j_r]); \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); #define RADIX_2_FORWARD_MOTH_J_IS_NZ(V, X0, X1) \ { \ V x0, x1; \ x0 = V##_load(X0); \ x0 = V##_reduce_to_pm1n(x0, n, ninv); \ x1 = V##_load(X1); \ x1 = V##_mulmod(x1, w, n, ninv); \ V##_store(X0, V##_add(x0, x1)); \ V##_store(X1, V##_sub(x0, x1)); \ } /* for when the V arguments above needs "evaluation" */ #define _RADIX_2_FORWARD_PARAM_J_IS_Z(...) RADIX_2_FORWARD_PARAM_J_IS_Z(__VA_ARGS__) #define _RADIX_2_FORWARD_MOTH_J_IS_Z(...) RADIX_2_FORWARD_MOTH_J_IS_Z(__VA_ARGS__) #define _RADIX_2_FORWARD_PARAM_J_IS_NZ(...) RADIX_2_FORWARD_PARAM_J_IS_NZ(__VA_ARGS__) #define _RADIX_2_FORWARD_MOTH_J_IS_NZ(...) RADIX_2_FORWARD_MOTH_J_IS_NZ(__VA_ARGS__) /**************** forward butterfly with truncation **************************/ #define RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_Z(V, X0, X1) \ { \ V x0, x1; \ x0 = V##_load(X0); \ x0 = V##_reduce_to_pm1n(x0, n, ninv); \ x1 = V##_load(X1); \ x1 = V##_reduce_to_pm1n(x1, n, ninv); \ V##_store(X0, V##_add(x0, x1)); \ } #define RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_NZ(V, X0, X1) \ { \ V x0, x1; \ x0 = V##_load(X0); \ x0 = V##_reduce_to_pm1n(x0, n, ninv); \ x1 = V##_load(X1); \ x1 = V##_mulmod(x1, w, n, ninv); \ V##_store(X0, V##_add(x0, x1)); \ } #define _RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_Z(...) RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_Z(__VA_ARGS__) #define _RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_NZ(...) RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_NZ(__VA_ARGS__) /********************* forward butterfly ************************************** b0 = a0 + w^2*a2 + w*(a1 + w^2*a3) b1 = a0 + w^2*a2 - w*(a1 + w^2*a3) b2 = a0 - w^2*a2 + i*w*(a1 - w^2*a3) b3 = a0 - w^2*a2 - i*w*(a1 - w^2*a3) */ #define RADIX_4_FORWARD_PARAM_J_IS_Z(V, Q) \ V iw = V##_set_d(Q->w2tab[1][0]); \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); #define RADIX_4_FORWARD_MOTH_J_IS_Z(V, X0, X1, X2, X3) \ { \ V x0, x1, x2, x3, y0, y1, y2, y3; \ x0 = V##_load(X0); \ x0 = V##_reduce_to_pm1n(x0, n, ninv); \ x1 = V##_load(X1); \ x2 = V##_load(X2); \ x3 = V##_load(X3); \ x2 = V##_reduce_to_pm1n(x2, n, ninv); \ x3 = V##_reduce_to_pm1n(x3, n, ninv); \ y0 = V##_add(x0, x2); \ y1 = V##_add(x1, x3); \ y2 = V##_sub(x0, x2); \ y3 = V##_sub(x1, x3); \ y1 = V##_reduce_to_pm1n(y1, n, ninv); \ y3 = V##_mulmod(y3, iw, n, ninv); \ x0 = V##_add(y0, y1); \ x1 = V##_sub(y0, y1); \ x2 = V##_add(y2, y3); \ x3 = V##_sub(y2, y3); \ V##_store(X0, x0); \ V##_store(X1, x1); \ V##_store(X2, x2); \ V##_store(X3, x3); \ } #define RADIX_4_FORWARD_PARAM_J_IS_NZ(V, Q, j_r, j_bits) \ FLINT_ASSERT(j_bits > 0); \ V w = V##_set_d(Q->w2tab[1+j_bits][2*j_r]); \ V w2 = V##_set_d(Q->w2tab[0+j_bits][j_r]); \ V iw = V##_set_d(Q->w2tab[1+j_bits][2*j_r+1]); \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); #define RADIX_4_FORWARD_MOTH_J_IS_NZ(V, X0, X1, X2, X3) \ { \ V x0, x1, x2, x3, y0, y1, y2, y3; \ x0 = V##_load(X0); \ x0 = V##_reduce_to_pm1n(x0, n, ninv); \ x1 = V##_load(X1); \ x2 = V##_load(X2); \ x3 = V##_load(X3); \ x2 = V##_mulmod(x2, w2, n, ninv); \ x3 = V##_mulmod(x3, w2, n, ninv); \ y0 = V##_add(x0, x2); \ y1 = V##_add(x1, x3); \ y2 = V##_sub(x0, x2); \ y3 = V##_sub(x1, x3); \ y1 = V##_mulmod(y1, w, n, ninv); \ y3 = V##_mulmod(y3, iw, n, ninv); \ x0 = V##_add(y0, y1); \ x1 = V##_sub(y0, y1); \ x2 = V##_add(y2, y3); \ x3 = V##_sub(y2, y3); \ V##_store(X0, x0); \ V##_store(X1, x1); \ V##_store(X2, x2); \ V##_store(X3, x3); \ } #define _RADIX_4_FORWARD_PARAM_J_IS_Z(...) RADIX_4_FORWARD_PARAM_J_IS_Z(__VA_ARGS__) #define _RADIX_4_FORWARD_MOTH_J_IS_Z(...) RADIX_4_FORWARD_MOTH_J_IS_Z(__VA_ARGS__) #define _RADIX_4_FORWARD_PARAM_J_IS_NZ(...) RADIX_4_FORWARD_PARAM_J_IS_NZ(__VA_ARGS__) #define _RADIX_4_FORWARD_MOTH_J_IS_NZ(...) RADIX_4_FORWARD_MOTH_J_IS_NZ(__VA_ARGS__) /**************** basecase transform of size BLK_SZ **************************/ /* The basecases below 4 are disabled because the fft is expected to be produced in the slightly-worse-than-bit-reversed order of basecase_4. */ #define DEFINE_IT(j_is_0) \ FLINT_FORCE_INLINE void CAT(sd_fft_basecase_4, j_is_0)( \ const sd_fft_lctx_t Q, \ double* X, \ ulong j_r, \ ulong j_bits) \ { \ vec4d n = vec4d_set_d(Q->p); \ vec4d ninv = vec4d_set_d(Q->pinv); \ vec4d w, w2, iw; \ vec4d x0, x1, x2, x3, y0, y1, y2, y3, u, v; \ \ /* will abuse the fact that Q->w2tab[0] points to consecutive entries */ \ FLINT_ASSERT(SD_FFT_CTX_INIT_DEPTH >= 4); \ \ x0 = vec4d_load(X+0); \ x0 = vec4d_reduce_to_pm1n(x0, n, ninv); \ x1 = vec4d_load(X+4); \ x2 = vec4d_load(X+8); \ x3 = vec4d_load(X+12); \ \ if (j_is_0) \ { \ iw = vec4d_set_d(Q->w2tab[0][1]); \ \ x2 = vec4d_reduce_to_pm1n(x2, n, ninv); \ x3 = vec4d_reduce_to_pm1n(x3, n, ninv); \ y0 = vec4d_add(x0, x2); \ y1 = vec4d_add(x1, x3); \ y2 = vec4d_sub(x0, x2); \ y3 = vec4d_sub(x1, x3); \ y1 = vec4d_reduce_to_pm1n(y1, n, ninv); \ y3 = vec4d_mulmod(y3, iw, n, ninv); \ x0 = vec4d_add(y0, y1); \ x1 = vec4d_sub(y0, y1); \ x2 = vec4d_add(y2, y3); \ x3 = vec4d_sub(y2, y3); \ } \ else \ { \ w = vec4d_set_d(Q->w2tab[1+j_bits][2*j_r]); \ w2 = vec4d_set_d(Q->w2tab[0+j_bits][j_r]); \ iw = vec4d_set_d(Q->w2tab[1+j_bits][2*j_r+1]); \ \ x2 = vec4d_mulmod(x2, w2, n, ninv); \ x3 = vec4d_mulmod(x3, w2, n, ninv); \ y0 = vec4d_add(x0, x2); \ y1 = vec4d_add(x1, x3); \ y2 = vec4d_sub(x0, x2); \ y3 = vec4d_sub(x1, x3); \ y1 = vec4d_mulmod(y1, w, n, ninv); \ y3 = vec4d_mulmod(y3, iw, n, ninv); \ x0 = vec4d_add(y0, y1); \ x1 = vec4d_sub(y0, y1); \ x2 = vec4d_add(y2, y3); \ x3 = vec4d_sub(y2, y3); \ } \ \ if (j_is_0) \ { \ u = vec4d_load_aligned(Q->w2tab[0] + 0); \ v = vec4d_load_aligned(Q->w2tab[0] + 4); \ w2 = u; \ } \ else \ { \ u = vec4d_load_aligned(Q->w2tab[3+j_bits] + 8*j_r + 0); \ v = vec4d_load_aligned(Q->w2tab[3+j_bits] + 8*j_r + 4); \ w2 = vec4d_load_aligned(Q->w2tab[2+j_bits] + 4*j_r + 0); \ } \ w = vec4d_unpack_lo_permute_0_2_1_3(u, v); \ iw = vec4d_unpack_hi_permute_0_2_1_3(u, v); \ \ VEC4D_TRANSPOSE(x0, x1, x2, x3, x0, x1, x2, x3); \ \ x0 = vec4d_reduce_to_pm1n(x0, n, ninv); \ x2 = vec4d_mulmod(x2, w2, n, ninv); \ x3 = vec4d_mulmod(x3, w2, n, ninv); \ y0 = vec4d_add(x0, x2); \ y1 = vec4d_add(x1, x3); \ y2 = vec4d_sub(x0, x2); \ y3 = vec4d_sub(x1, x3); \ y1 = vec4d_mulmod(y1, w, n, ninv); \ y3 = vec4d_mulmod(y3, iw, n, ninv); \ x0 = vec4d_add(y0, y1); \ x1 = vec4d_sub(y0, y1); \ x2 = vec4d_add(y2, y3); \ x3 = vec4d_sub(y2, y3); \ \ /* another VEC4D_TRANSPOSE here would put the output in bit-reversed */ \ /* but this slow down is not necessary */ \ \ vec4d_store(X+0, x0); \ vec4d_store(X+4, x1); \ vec4d_store(X+8, x2); \ vec4d_store(X+12, x3); \ } DEFINE_IT(0) DEFINE_IT(1) #undef DEFINE_IT /* use with n = m-2 and m >= 6 */ #define EXTEND_BASECASE(n, m) \ static void CAT3(sd_fft_basecase, m, 1)(const sd_fft_lctx_t Q, double* X, ulong j_r, ulong j_bits) \ { \ ulong l = n_pow2(m - 2); \ _RADIX_4_FORWARD_PARAM_J_IS_Z(VECND, Q) \ ulong i = 0; do { \ _RADIX_4_FORWARD_MOTH_J_IS_Z(VECND, X+0*l+i, X+1*l+i, X+2*l+i, X+3*l+i) \ } while (i += N, i < l); \ CAT3(sd_fft_basecase, n, 1)(Q, X+0*l, 0, 0); \ CAT3(sd_fft_basecase, n, 0)(Q, X+1*l, 0, 1); \ CAT3(sd_fft_basecase, n, 0)(Q, X+2*l, 0, 2); \ CAT3(sd_fft_basecase, n, 0)(Q, X+3*l, 1, 2); \ } \ static void CAT3(sd_fft_basecase, m, 0)(const sd_fft_lctx_t Q, double* X, ulong j_r, ulong j_bits) \ { \ ulong l = n_pow2(m - 2); \ _RADIX_4_FORWARD_PARAM_J_IS_NZ(VECND, Q, j_r, j_bits) \ ulong i = 0; do { \ _RADIX_4_FORWARD_MOTH_J_IS_NZ(VECND, X+0*l+i, X+1*l+i, X+2*l+i, X+3*l+i) \ } while (i += N, i < l); \ CAT3(sd_fft_basecase, n, 0)(Q, X+0*l, 4*j_r+0, j_bits+2); \ CAT3(sd_fft_basecase, n, 0)(Q, X+1*l, 4*j_r+1, j_bits+2); \ CAT3(sd_fft_basecase, n, 0)(Q, X+2*l, 4*j_r+2, j_bits+2); \ CAT3(sd_fft_basecase, n, 0)(Q, X+3*l, 4*j_r+3, j_bits+2); \ } EXTEND_BASECASE(4, 6) EXTEND_BASECASE(6, 8) #undef EXTEND_BASECASE /* parameter 1: j can be zero */ static void sd_fft_base_1(const sd_fft_lctx_t Q, ulong I, ulong j) { ulong j_bits, j_r; double* x = sd_fft_lctx_blk_index(Q, I); FLINT_ASSERT(8 == LG_BLK_SZ); FLINT_ASSERT(256 == BLK_SZ); SET_J_BITS_AND_J_R(j_bits, j_r, j); if (FLINT_UNLIKELY(j == 0)) sd_fft_basecase_8_1(Q, x, j_r, j_bits); else sd_fft_basecase_8_0(Q, x, j_r, j_bits); } /* parameter 0: j cannot be zero */ static void sd_fft_base_0(const sd_fft_lctx_t Q, ulong I, ulong j) { ulong j_bits, j_r; double* x = sd_fft_lctx_blk_index(Q, I); FLINT_ASSERT(j != 0); FLINT_ASSERT(8 == LG_BLK_SZ); FLINT_ASSERT(256 == BLK_SZ); SET_J_BITS_AND_J_R(j_bits, j_r, j); sd_fft_basecase_8_0(Q, x, j_r, j_bits); } /**************** forward butterfly with truncation **************************/ /* third parameter is j == 0 */ #define DEFINE_IT(itrunc, otrunc) \ static void CAT4(sd_fft_moth_trunc_block, itrunc, otrunc, 1)( \ const sd_fft_lctx_t Q, \ ulong j_r, ulong j_bits, \ double* X0, double* X1, double* X2, double* X3) \ { \ _RADIX_4_FORWARD_PARAM_J_IS_Z(VECND, Q); \ ulong i = 0; do { \ VECND x0, x1, x2, x3, y0, y1, y2, y3; \ x0 = x1 = x2 = x3 = VECNOP(zero)(); \ if (0 < itrunc) x0 = VECNOP(load)(X0+i); \ if (0 < itrunc) x0 = VECNOP(reduce_to_pm1n)(x0, n, ninv); \ if (1 < itrunc) x1 = VECNOP(load)(X1+i); \ if (2 < itrunc) x2 = VECNOP(load)(X2+i); \ if (2 < itrunc) x2 = VECNOP(reduce_to_pm1n)(x2, n, ninv); \ if (3 < itrunc) x3 = VECNOP(load)(X3+i); \ if (3 < itrunc) x3 = VECNOP(reduce_to_pm1n)(x3, n, ninv); \ y0 = (2 < itrunc) ? VECNOP(add)(x0, x2) : x0; \ y1 = (3 < itrunc) ? VECNOP(add)(x1, x3) : x1; \ y2 = (2 < itrunc) ? VECNOP(sub)(x0, x2) : x0; \ y3 = (3 < itrunc) ? VECNOP(sub)(x1, x3) : x1; \ y1 = VECNOP(reduce_to_pm1n)(y1, n, ninv); \ y3 = VECNOP(mulmod)(y3, iw, n, ninv); \ x0 = VECNOP(add)(y0, y1); \ x1 = VECNOP(sub)(y0, y1); \ x2 = VECNOP(add)(y2, y3); \ x3 = VECNOP(sub)(y2, y3); \ if (0 < otrunc) VECNOP(store)(X0+i, x0); \ if (1 < otrunc) VECNOP(store)(X1+i, x1); \ if (2 < otrunc) VECNOP(store)(X2+i, x2); \ if (3 < otrunc) VECNOP(store)(X3+i, x3); \ } while (i += N, i < BLK_SZ); \ FLINT_ASSERT(i == BLK_SZ); \ } \ static void CAT4(sd_fft_moth_trunc_block, itrunc, otrunc, 0)( \ const sd_fft_lctx_t Q, \ ulong j_r, ulong j_bits, \ double* X0, double* X1, double* X2, double* X3) \ { \ _RADIX_4_FORWARD_PARAM_J_IS_NZ(VECND, Q, j_r, j_bits); \ ulong i = 0; do { \ VECND x0, x1, x2, x3, y0, y1, y2, y3; \ x0 = x1 = x2 = x3 = VECNOP(zero)(); \ if (0 < itrunc) x0 = VECNOP(load)(X0+i); \ if (0 < itrunc) x0 = VECNOP(reduce_to_pm1n)(x0, n, ninv); \ if (1 < itrunc) x1 = VECNOP(load)(X1+i); \ if (2 < itrunc) x2 = VECNOP(load)(X2+i); \ if (2 < itrunc) x2 = VECNOP(mulmod)(x2, w2, n, ninv); \ if (3 < itrunc) x3 = VECNOP(load)(X3+i); \ if (3 < itrunc) x3 = VECNOP(mulmod)(x3, w2, n, ninv); \ y0 = (2 < itrunc) ? VECNOP(add)(x0, x2) : x0; \ y1 = (3 < itrunc) ? VECNOP(add)(x1, x3) : x1; \ y2 = (2 < itrunc) ? VECNOP(sub)(x0, x2) : x0; \ y3 = (3 < itrunc) ? VECNOP(sub)(x1, x3) : x1; \ y1 = VECNOP(mulmod)(y1, w, n, ninv); \ y3 = VECNOP(mulmod)(y3, iw, n, ninv); \ x0 = VECNOP(add)(y0, y1); \ x1 = VECNOP(sub)(y0, y1); \ x2 = VECNOP(add)(y2, y3); \ x3 = VECNOP(sub)(y2, y3); \ if (0 < otrunc) VECNOP(store)(X0+i, x0); \ if (1 < otrunc) VECNOP(store)(X1+i, x1); \ if (2 < otrunc) VECNOP(store)(X2+i, x2); \ if (3 < otrunc) VECNOP(store)(X3+i, x3); \ } while (i += N, i < BLK_SZ); \ FLINT_ASSERT(i == BLK_SZ); \ } DEFINE_IT(2, 1) DEFINE_IT(2, 2) DEFINE_IT(2, 3) DEFINE_IT(2, 4) DEFINE_IT(3, 1) DEFINE_IT(3, 2) DEFINE_IT(3, 3) DEFINE_IT(3, 4) DEFINE_IT(4, 1) DEFINE_IT(4, 2) DEFINE_IT(4, 3) DEFINE_IT(4, 4) #undef DEFINE_IT /************************ the recursive stuff ********************************/ void sd_fft_main_block( const sd_fft_lctx_t Q, ulong I, /* starting index */ ulong S, /* stride */ ulong k, /* BLK_SZ transforms each of length 2^k */ ulong j) { ulong j_bits, j_r; if (k > 4) { ulong k1 = k/2; ulong k2 = k - k1; ulong l2 = n_pow2(k2); ulong a = 0; do { sd_fft_main_block(Q, I + a*S, S<= 2) { ulong k1 = 2; ulong k2 = k - k1; ulong l2 = n_pow2(k2); /* column ffts */ if (FLINT_UNLIKELY(j_bits == 0)) { _RADIX_4_FORWARD_PARAM_J_IS_Z(VECND, Q) ulong a = 0; do { double* X0 = sd_fft_lctx_blk_index(Q, I+a*S + (S< 2) { ulong k1 = k/2; ulong k2 = k - k1; /* column ffts */ ulong l2 = n_pow2(k2); ulong a = 0; do { sd_fft_main_block(Q, I + a*S, S< 2) { ulong k1 = k/2; ulong k2 = k - k1; ulong l2 = n_pow2(k2); ulong n1 = otrunc >> k2; ulong n2 = otrunc & (l2 - 1); ulong z1 = itrunc >> k2; ulong z2 = itrunc & (l2 - 1); ulong n1p = n1 + (n2 != 0); ulong z2p = n_min(l2, itrunc); /* columns */ for (ulong a = 0; a < z2p; a++) sd_fft_trunc_block(Q, I + a*S, S << k2, k1, j, z1 + (a < z2), n1p); /* full rows */ for (ulong b = 0; b < n1; b++) sd_fft_trunc_block(Q, I + b*(S << k2), S, k2, (j << k1) + b, z2p, l2); /* last partial row */ if (n2 > 0) sd_fft_trunc_block(Q, I + n1*(S << k2), S, k2, (j << k1) + n1, z2p, n2); return; } SET_J_BITS_AND_J_R(j_bits, j_r, j); if (k == 2) { #define IT(ii, oo) CAT4(sd_fft_moth_trunc_block, ii, oo, 0), \ CAT4(sd_fft_moth_trunc_block, ii, oo, 1) #define LOOKUP_IT(ii, oo, j_is_zero) tab[(j_is_zero) + 2*((oo)-1 + 4*((ii)-2))] static void (*tab[3*4*2])(const sd_fft_lctx_t, ulong, ulong, double*, double*, double*, double*) = {IT(2,1), IT(2,2), IT(2,3), IT(2,4), IT(3,1), IT(3,2), IT(3,3), IT(3,4), IT(4,1), IT(4,2), IT(4,3), IT(4,4)}; LOOKUP_IT(itrunc, otrunc, j == 0)(Q, j_r, j_bits, sd_fft_lctx_blk_index(Q, I + S*0), sd_fft_lctx_blk_index(Q, I + S*1), sd_fft_lctx_blk_index(Q, I + S*2), sd_fft_lctx_blk_index(Q, I + S*3)); #undef LOOKUP_IT #undef IT } else if (k == 1) { double* X0 = sd_fft_lctx_blk_index(Q, I + S*0); double* X1 = sd_fft_lctx_blk_index(Q, I + S*1); FLINT_ASSERT(itrunc == 2); FLINT_ASSERT(otrunc == 1); if (FLINT_UNLIKELY(j_bits == 0)) { _RADIX_2_FORWARD_PARAM_J_IS_Z(VECND, Q) ulong i = 0; do { _RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_Z(VECND, X0 + i, X1 + i); } while (i += N, i < BLK_SZ); } else { _RADIX_2_FORWARD_PARAM_J_IS_NZ(VECND, Q, j_r, j_bits) ulong i = 0; do { _RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_NZ(VECND, X0 + i, X1 + i); } while (i += N, i < BLK_SZ); } } } void sd_fft_trunc( const sd_fft_lctx_t Q, ulong I, /* starting index */ ulong S, /* stride */ ulong k, /* transform length BLK_SZ*2^k */ ulong j, ulong itrunc, /* actual trunc is BLK_SZ*itrunc */ ulong otrunc) /* actual trunc is BLK_SZ*otrunc */ { if (otrunc < 1) return; if (itrunc < 1) { for (ulong a = 0; a < otrunc; a++) { double* X0 = sd_fft_lctx_blk_index(Q, I + S*a); VECND z = VECNOP(zero)(); ulong i = 0; do { VECNOP(store)(X0 + i, z); } while (i += N, i < BLK_SZ); } return; } if (k > 2) { ulong k1 = k/2; ulong k2 = k - k1; ulong l2 = n_pow2(k2); ulong n1 = otrunc >> k2; ulong n2 = otrunc & (l2 - 1); ulong z1 = itrunc >> k2; ulong z2 = itrunc & (l2 - 1); ulong n1p = n1 + (n2 != 0); ulong z2p = n_min(l2, itrunc); /* columns */ for (ulong a = 0; a < z2p; a++) sd_fft_trunc_block(Q, I + a*S, S << k2, k1, j, z1 + (a < z2), n1p); /* full rows */ for (ulong b = 0; b < n1; b++) sd_fft_trunc(Q, I + b*(S << k2), S, k2, (j << k1) + b, z2p, l2); /* last partial row */ if (n2 > 0) sd_fft_trunc(Q, I + n1*(S << k2), S, k2, (j << k1) + n1, z2p, n2); return; } if (k == 2) { sd_fft_trunc_block(Q, I, S, 2, j, itrunc, otrunc); sd_fft_base_1(Q, I + S*0, 4*j + 0); if (otrunc > 1) sd_fft_base_0(Q, I + S*1, 4*j + 1); if (otrunc > 2) sd_fft_base_0(Q, I + S*2, 4*j + 2); if (otrunc > 3) sd_fft_base_0(Q, I + S*3, 4*j + 3); } else if (k == 1) { sd_fft_trunc_block(Q, I, S, 1, j, itrunc, otrunc); sd_fft_base_1(Q, I + S*0, 2*j + 0); if (otrunc > 1) sd_fft_base_0(Q, I + S*1, 2*j + 1); } else { sd_fft_base_1(Q, I, j); } } #undef RADIX_2_FORWARD_PARAM_J_IS_Z #undef RADIX_2_FORWARD_MOTH_J_IS_Z #undef RADIX_2_FORWARD_PARAM_J_IS_NZ #undef RADIX_2_FORWARD_MOTH_J_IS_NZ #undef RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_Z #undef RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_NZ #undef RADIX_4_FORWARD_PARAM_J_IS_Z #undef RADIX_4_FORWARD_MOTH_J_IS_Z #undef RADIX_4_FORWARD_PARAM_J_IS_NZ #undef RADIX_4_FORWARD_MOTH_J_IS_NZ #undef _RADIX_2_FORWARD_PARAM_J_IS_Z #undef _RADIX_2_FORWARD_MOTH_J_IS_Z #undef _RADIX_2_FORWARD_PARAM_J_IS_NZ #undef _RADIX_2_FORWARD_MOTH_J_IS_NZ #undef _RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_Z #undef _RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_NZ #undef _RADIX_4_FORWARD_PARAM_J_IS_Z #undef _RADIX_4_FORWARD_MOTH_J_IS_Z #undef _RADIX_4_FORWARD_PARAM_J_IS_NZ #undef _RADIX_4_FORWARD_MOTH_J_IS_NZ #undef N #undef VECND #undef VECNOP flint-3.1.3/src/fft_small/sd_fft_ctx.c000066400000000000000000000103771461254215100176700ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fft_small.h" #include "nmod.h" void sd_fft_ctx_clear(sd_fft_ctx_t Q) { ulong k; flint_aligned_free(Q->w2tab[0]); for (k = SD_FFT_CTX_INIT_DEPTH; k < FLINT_BITS; k++) flint_aligned_free(Q->w2tab[k]); } void sd_fft_ctx_init_prime(sd_fft_ctx_t Q, ulong pp) { ulong N, i, k, l; double * t; double n, ninv; if (!fft_small_mulmod_satisfies_bounds(pp)) flint_throw(FLINT_ERROR, "FFT prime %wu does not satisfy bounds for arithmetic", pp); Q->blk_sz = BLK_SZ; Q->p = pp; Q->pinv = 1.0/Q->p; nmod_init(&Q->mod, pp); Q->primitive_root = n_primitive_root_prime(pp); n = Q->p; ninv = Q->pinv; /* fill wtab to a depth of SD_FFT_CTX_INIT_DEPTH: 2^(SD_FFT_CTX_INIT_DEPTH-1) entries: 1, e(1/4), e(1/8), e(3/8), ... Q->w2tab[j] is itself a table of length 2^(j-1) containing 2^(j+1) st roots of unity. */ N = n_pow2(SD_FFT_CTX_INIT_DEPTH - 1); t = (double*) flint_aligned_alloc(4096, n_round_up(N*sizeof(double), 4096)); Q->w2tab[0] = t; t[0] = 1; for (k = 1, l = 1; k < SD_FFT_CTX_INIT_DEPTH; k++, l *= 2) { ulong ww = nmod_pow_ui(Q->primitive_root, (Q->mod.n - 1)>>(k + 1), Q->mod); double w = vec1d_set_d(vec1d_reduce_0n_to_pmhn(ww, n)); double* curr = t + l; Q->w2tab[k] = curr; i = 0; do { vec1d x = vec1d_load(t + i); x = vec1d_mulmod(x, w, n, ninv); x = vec1d_reduce_pm1n_to_pmhn(x, n); vec1d_store(curr + i, x); } while (i += 1, i < l); } Q->w2tab_depth = k; /* the rest of the tables are uninitialized */ for ( ; k < FLINT_BITS; k++) Q->w2tab[k] = NULL; #if FLINT_WANT_ASSERT for (k = 1; k < SD_FFT_CTX_INIT_DEPTH; k++) { ulong ww = nmod_pow_ui(Q->primitive_root, (Q->mod.n - 1)>>(k + 1), Q->mod); for (i = 0; i < n_pow2(k-1); i++) { ulong www = nmod_pow_ui(ww, n_revbin(i+n_pow2(k-1), k), Q->mod); FLINT_ASSERT(Q->w2tab[k][i] == vec1d_reduce_0n_to_pmhn(www, n)); } } #endif } void sd_fft_ctx_fit_depth(sd_fft_ctx_t Q, ulong depth) { ulong k = Q->w2tab_depth; while (k < depth) { ulong i, j, l, off; ulong ww = nmod_pow_ui(Q->primitive_root, (Q->mod.n - 1)>>(k + 1), Q->mod); vec8d w = vec8d_set_d(vec1d_reduce_0n_to_pmhn(ww, Q->p)); vec8d n = vec8d_set_d(Q->p); vec8d ninv = vec8d_set_d(Q->pinv); ulong N = n_pow2(k - 1); double* curr = (double*) flint_aligned_alloc(4096, n_round_up(N*sizeof(double), 4096)); double* t = Q->w2tab[0]; Q->w2tab[k] = curr; /* The first few tables are stored consecutively, so vec16 is ok. */ off = 0; l = n_pow2(SD_FFT_CTX_INIT_DEPTH - 1); for (j = SD_FFT_CTX_INIT_DEPTH - 1; j < k; j++) { i = 0; do { vec8d x0 = vec8d_load_aligned(t + i + 0); vec8d x1 = vec8d_load_aligned(t + i + 8); x0 = vec8d_mulmod(x0, w, n, ninv); x1 = vec8d_mulmod(x1, w, n, ninv); x0 = vec8d_reduce_pm1n_to_pmhn(x0, n); x1 = vec8d_reduce_pm1n_to_pmhn(x1, n); vec8d_store_aligned(curr + off + i + 0, x0); vec8d_store_aligned(curr + off + i + 8, x1); } while (i += 16, i < l); FLINT_ASSERT(i == l); t = Q->w2tab[j + 1]; l += off; off = l; } #if FLINT_WANT_ASSERT { ulong ww = nmod_pow_ui(Q->primitive_root, (Q->mod.n - 1)>>(k + 1), Q->mod); for (i = 0; i < n_pow2(k-1); i++) { ulong www = nmod_pow_ui(ww, n_revbin(i+n_pow2(k-1), k), Q->mod); FLINT_ASSERT(Q->w2tab[k][i] == vec1d_reduce_0n_to_pmhn(www, Q->p)); } } #endif k++; Q->w2tab_depth = k; } } flint-3.1.3/src/fft_small/sd_ifft.c000066400000000000000000001247451461254215100171700ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fft_small.h" /* N is supposed to be a good fit for the number of points to process per loop in the radix 4 inverse butterflies. M is supposed to be <= N and is used for truncation formulas that have a larger register pressure. */ #define N 8 #define VECND vec8d #define VECNOP(op) vec8d_##op #define M 4 #define VECMD vec4d #define VECMOP(op) vec4d_##op /************************** inverse butterfly ********************************* 2*a0 = (b0 + b1) 2*a1 = w^-1*(b0 - b1) W := -w^-1 */ #define RADIX_2_REVERSE_PARAM_J_IS_Z(V, Q) \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); #define RADIX_2_REVERSE_MOTH_J_IS_Z(V, X0, X1) \ { \ V x0, x1, y0, y1; \ x0 = V##_load(X0); \ x1 = V##_load(X1); \ y0 = V##_add(x0, x1); \ y1 = V##_sub(x0, x1); \ y0 = V##_reduce_to_pm1n(y0, n, ninv); \ y1 = V##_reduce_to_pm1n(y1, n, ninv); \ V##_store(X0, y0); \ V##_store(X1, y1); \ } #define RADIX_2_REVERSE_PARAM_J_IS_NZ(V, Q, j_mr, j_bits) \ V W = V##_set_d(Q->w2tab[j_bits][j_mr]); \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); #define RADIX_2_REVERSE_MOTH_J_IS_NZ(V, X0, X1) \ { \ V x0, x1, y0, y1; \ x0 = V##_load(X0); \ x1 = V##_load(X1); \ y0 = V##_add(x0, x1); \ y1 = V##_sub(x1, x0); \ y0 = V##_reduce_to_pm1n(y0, n, ninv); \ y1 = V##_mulmod(y1, W, n, ninv); \ V##_store(X0, y0); \ V##_store(X1, y1); \ } #define _RADIX_2_REVERSE_PARAM_J_IS_Z(...) RADIX_2_REVERSE_PARAM_J_IS_Z(__VA_ARGS__) #define _RADIX_2_REVERSE_MOTH_J_IS_Z(...) RADIX_2_REVERSE_MOTH_J_IS_Z(__VA_ARGS__) #define _RADIX_2_REVERSE_PARAM_J_IS_NZ(...) RADIX_2_REVERSE_PARAM_J_IS_NZ(__VA_ARGS__) #define _RADIX_2_REVERSE_MOTH_J_IS_NZ(...) RADIX_2_REVERSE_MOTH_J_IS_NZ(__VA_ARGS__) /****************** inverse butterfly with truncation ************************/ /* the legal functions must be implemented */ #define DEFINE_IT(nn, zz, ff) \ static void CAT4(radix_2_moth_inv_trunc_block, nn, zz, ff)( \ const sd_fft_lctx_t Q, \ ulong j, \ double* X0, double* X1) \ { \ int l = 2; \ flint_printf("function l = %d, n = %d, z = %d, f = %d", l, nn, zz, ff); \ if (1 <= zz && zz <= 2 && nn <= zz && 1 <= nn+ff && nn+ff <= l) \ flint_throw(FLINT_ERROR, " is not implemented\n"); \ else \ flint_throw(FLINT_ERROR, " does not exist and should not be called\n"); \ } DEFINE_IT(0,1,0) DEFINE_IT(0,2,0) DEFINE_IT(2,1,0) DEFINE_IT(2,1,1) DEFINE_IT(2,2,0) DEFINE_IT(2,2,1) #undef DEFINE_IT /* {x0, x1} = {2*x0 - w*x1, x0 - w*x1} */ static void radix_2_moth_inv_trunc_block_1_2_1( const sd_fft_lctx_t Q, ulong j, double* X0, double* X1) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND w = VECNOP(set_d)(sd_fft_lctx_w2(Q, j)); VECND c = VECNOP(set_d)(2); ulong i = 0; do { VECND a, b, u, v; a = VECNOP(load)(X0 + i); b = VECNOP(load)(X1 + i); b = VECNOP(nmulmod)(b, w, n, ninv); u = VECNOP(fmadd)(c, a, b); v = VECNOP(add)(a, b); u = VECNOP(reduce_to_pm1n)(u, n, ninv); v = VECNOP(reduce_to_pm1n)(v, n, ninv); VECNOP(store)(X0 + i, u); VECNOP(store)(X1 + i, v); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* {x0} = {2*x0 - w*x1} */ static void radix_2_moth_inv_trunc_block_1_2_0( const sd_fft_lctx_t Q, ulong j, double* X0, double* X1) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND w = VECNOP(set_d)(sd_fft_lctx_w2(Q, j)); VECND c = VECNOP(set_d)(2); ulong i = 0; do { VECND a, b, u; a = VECNOP(load)(X0 + i); b = VECNOP(load)(X1 + i); b = VECNOP(mulmod)(b, w, n, ninv); u = VECNOP(fmsub)(c, a, b); u = VECNOP(reduce_to_pm1n)(u, n, ninv); VECNOP(store)(X0 + i, u); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* {x0, x1} = {2*x0, x0} */ static void radix_2_moth_inv_trunc_block_1_1_1( const sd_fft_lctx_t Q, ulong j, double* X0, double* X1) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); ulong i = 0; do { VECND a, u; a = VECNOP(load)(X0 + i); u = VECNOP(add)(a, a); u = VECNOP(reduce_to_pm1n)(u, n, ninv); VECNOP(store)(X0 + i, u); VECNOP(store)(X1 + i, a); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* {x0} = {2*x0} */ static void radix_2_moth_inv_trunc_block_1_1_0( const sd_fft_lctx_t Q, ulong j, double* X0, double* X1) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); ulong i = 0; do { VECND a; a = VECNOP(load)(X0 + i); a = VECNOP(add)(a, a); a = VECNOP(reduce_to_pm1n)(a, n, ninv); VECNOP(store)(X0 + i, a); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* {x0} = {(x0 + w*x1)/2} */ static void radix_2_moth_inv_trunc_block_0_2_1( const sd_fft_lctx_t Q, ulong j, double* X0, double* X1) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND w = VECNOP(set_d)(sd_fft_lctx_w2(Q, j)); VECND c = VECNOP(set_d)(vec1d_fnmadd(0.5, Q->p, 0.5)); ulong i = 0; do { VECND a, b; a = VECNOP(load)(X0 + i); b = VECNOP(load)(X1 + i); b = VECNOP(mulmod)(b, w, n, ninv); a = VECNOP(add)(a, b); a = VECNOP(mulmod)(a, c, n, ninv); VECNOP(store)(X0 + i, a); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* {x0} = {(x0)/2} */ static void radix_2_moth_inv_trunc_block_0_1_1( const sd_fft_lctx_t Q, ulong j, double* X0, double* X1) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND c = VECNOP(set_d)(vec1d_fnmadd(0.5, Q->p, 0.5)); ulong i = 0; do { VECND a; a = VECNOP(load)(X0 + i); a = VECNOP(mulmod)(a, c, n, ninv); VECNOP(store)(X0 + i, a); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /************************* inverse butterfly ********************************** 4*a0 = (b0 + b1) + (b2 + b3) 4*a1 = w^-1*(b0 - b1) - i*w^-1*(b2 - b3) 4*a2 = w^-2*( (b0 + b1) - (b2 + b3)) 4*a3 = w^-2*(w^-1*(b0 - b1) + i*w^-1*(b2 - b3)) W := -w^-1 W2 := -w^-2 IW := i*w^-1 */ #define RADIX_4_REVERSE_PARAM_J_IS_Z(V, Q) \ V IW = V##_set_d(Q->w2tab[0][1]); \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); \ #define RADIX_4_REVERSE_MOTH_J_IS_Z(V, X0, X1, X2, X3) \ { \ V x0, x1, x2, x3, y0, y1, y2, y3; \ x0 = V##_load(X0); \ x1 = V##_load(X1); \ x2 = V##_load(X2); \ x3 = V##_load(X3); \ y0 = V##_add(x0, x1); \ y1 = V##_add(x2, x3); \ y2 = V##_sub(x0, x1); \ y3 = V##_sub(x2, x3); \ y0 = V##_reduce_to_pm1n(y0, n, ninv); \ y1 = V##_reduce_to_pm1n(y1, n, ninv); \ y2 = V##_reduce_to_pm1n(y2, n, ninv); \ y3 = V##_mulmod(y3, IW, n, ninv); \ V##_store(X0, V##_add(y0, y1)); \ V##_store(X2, V##_sub(y0, y1)); \ V##_store(X1, V##_sub(y2, y3)); \ V##_store(X3, V##_add(y2, y3)); \ } #define RADIX_4_REVERSE_PARAM_J_IS_NZ(V, Q, j_mr, j_bits) \ V W = V##_set_d(Q->w2tab[1+j_bits][2*j_mr+1]); \ V W2 = V##_set_d(Q->w2tab[0+j_bits][j_mr]); \ V IW = V##_set_d(Q->w2tab[1+j_bits][2*j_mr+0]); \ V n = V##_set_d(Q->p); \ V ninv = V##_set_d(Q->pinv); \ #define RADIX_4_REVERSE_MOTH_J_IS_NZ(V, X0, X1, X2, X3) \ { \ V x0, x1, x2, x3, y0, y1, y2, y3; \ x0 = V##_load(X0); \ x1 = V##_load(X1); \ x2 = V##_load(X2); \ x3 = V##_load(X3); \ y0 = V##_add(x0, x1); \ y1 = V##_add(x2, x3); \ y2 = V##_sub(x0, x1); \ y3 = V##_sub(x3, x2); \ y2 = V##_mulmod(y2, W, n, ninv); \ y3 = V##_mulmod(y3, IW, n, ninv); \ x0 = V##_add(y0, y1); \ x1 = V##_sub(y3, y2); \ V##_store(X1, x1); \ x2 = V##_sub(y1, y0); \ x3 = V##_add(y3, y2); \ x0 = V##_reduce_to_pm1n(x0, n, ninv); \ x2 = V##_mulmod(x2, W2, n, ninv); \ x3 = V##_mulmod(x3, W2, n, ninv); \ V##_store(X0, x0); \ V##_store(X2, x2); \ V##_store(X3, x3); \ } #define _RADIX_4_REVERSE_PARAM_J_IS_Z(...) RADIX_4_REVERSE_PARAM_J_IS_Z(__VA_ARGS__) #define _RADIX_4_REVERSE_MOTH_J_IS_Z(...) RADIX_4_REVERSE_MOTH_J_IS_Z(__VA_ARGS__) #define _RADIX_4_REVERSE_PARAM_J_IS_NZ(...) RADIX_4_REVERSE_PARAM_J_IS_NZ(__VA_ARGS__) #define _RADIX_4_REVERSE_MOTH_J_IS_NZ(...) RADIX_4_REVERSE_MOTH_J_IS_NZ(__VA_ARGS__) /************ basecase inverse transform of size BLK_SZ **********************/ /* The basecases below 4 are disabled because the ifft expects input in slightly-worse-than-bit-reversed order as in basecase_4. */ #define DEFINE_IT(j_is_0) \ FLINT_FORCE_INLINE void sd_ifft_basecase_4_##j_is_0(\ const sd_fft_lctx_t Q, double* X, ulong j_mr, ulong j_bits) \ { \ vec4d n = vec4d_set_d(Q->p); \ vec4d ninv = vec4d_set_d(Q->pinv); \ vec4d W, W2, IW, u, v; \ vec4d x0, x1, x2, x3, y0, y1, y2, y3; \ \ x0 = vec4d_load(X + 0); \ x1 = vec4d_load(X + 4); \ x2 = vec4d_load(X + 8); \ x3 = vec4d_load(X + 12); \ \ if (j_is_0) \ { \ W = vec4d_set_d4(-Q->w2tab[0][0], Q->w2tab[0][3], Q->w2tab[0][7], Q->w2tab[0][5]); \ IW = vec4d_set_d4( Q->w2tab[0][1], Q->w2tab[0][2], Q->w2tab[0][6], Q->w2tab[0][4]); \ W2 = vec4d_set_d4(-Q->w2tab[0][0], Q->w2tab[0][1], Q->w2tab[0][3], Q->w2tab[0][2]); \ } \ else \ { \ W2 = vec4d_load_aligned(Q->w2tab[2+j_bits] + 4*j_mr); /* a b c d */ \ W2 = vec4d_permute_3_2_1_0(W2); /* d c b a */ \ u = vec4d_load_aligned(Q->w2tab[3+j_bits] + 8*j_mr+0); /* 0 1 2 3 */ \ v = vec4d_load_aligned(Q->w2tab[3+j_bits] + 8*j_mr+4); /* 4 5 6 7 */ \ W = vec4d_unpackhi_permute_3_1_2_0(u, v); /* 7 5 3 1 */ \ IW = vec4d_unpacklo_permute_3_1_2_0(u, v); /* 6 4 2 0 */ \ } \ \ y0 = vec4d_add(x0, x1); \ y1 = vec4d_add(x2, x3); \ y2 = vec4d_sub(x0, x1); \ y3 = vec4d_sub(x3, x2); \ y2 = vec4d_mulmod(y2, W, n, ninv); \ y3 = vec4d_mulmod(y3, IW, n, ninv); \ x0 = vec4d_add(y0, y1); \ x1 = vec4d_sub(y3, y2); \ x2 = vec4d_sub(y1, y0); \ x3 = vec4d_add(y3, y2); \ x0 = vec4d_reduce_to_pm1n(x0, n, ninv); \ x2 = vec4d_mulmod(x2, W2, n, ninv); \ x3 = vec4d_mulmod(x3, W2, n, ninv); \ \ VEC4D_TRANSPOSE(x0, x1, x2, x3, x0, x1, x2, x3); \ \ if (j_is_0) \ { \ IW = vec4d_set_d(Q->w2tab[0][1]); \ y0 = vec4d_add(x0, x1); \ y1 = vec4d_add(x2, x3); \ y2 = vec4d_sub(x0, x1); \ y3 = vec4d_sub(x2, x3); \ y0 = vec4d_reduce_to_pm1n(y0, n, ninv); \ y1 = vec4d_reduce_to_pm1n(y1, n, ninv); \ y2 = vec4d_reduce_to_pm1n(y2, n, ninv); \ y3 = vec4d_mulmod(y3, IW, n, ninv); \ vec4d_store(X+0, vec4d_add(y0, y1)); \ vec4d_store(X+8, vec4d_sub(y0, y1)); \ vec4d_store(X+4, vec4d_sub(y2, y3)); \ vec4d_store(X+12, vec4d_add(y2, y3)); \ } \ else \ { \ W = vec4d_set_d(Q->w2tab[1+j_bits][2*j_mr+1]); \ IW = vec4d_set_d(Q->w2tab[1+j_bits][2*j_mr+0]); \ W2 = vec4d_set_d(Q->w2tab[0+j_bits][j_mr]); \ y0 = vec4d_add(x0, x1); \ y1 = vec4d_add(x2, x3); \ y2 = vec4d_sub(x0, x1); \ y3 = vec4d_sub(x3, x2); \ y2 = vec4d_mulmod(y2, W, n, ninv); \ y3 = vec4d_mulmod(y3, IW, n, ninv); \ x0 = vec4d_add(y0, y1); \ x1 = vec4d_sub(y3, y2); \ x2 = vec4d_sub(y1, y0); \ x3 = vec4d_add(y3, y2); \ x0 = vec4d_reduce_to_pm1n(x0, n, ninv); \ x2 = vec4d_mulmod(x2, W2, n, ninv); \ x3 = vec4d_mulmod(x3, W2, n, ninv); \ vec4d_store(X+0, x0); \ vec4d_store(X+4, x1); \ vec4d_store(X+8, x2); \ vec4d_store(X+12, x3); \ } \ } DEFINE_IT(0) DEFINE_IT(1) #undef DEFINE_IT /* use with n = m-2 and m >= 6 */ #define EXTEND_BASECASE(n, m) \ void CAT3(sd_ifft_basecase, m, 1)(const sd_fft_lctx_t Q, double* X, ulong j_mr, ulong j_bits) \ { \ ulong l = n_pow2(m - 2); \ FLINT_ASSERT(j_bits == 0); \ CAT3(sd_ifft_basecase, n, 1)(Q, X+0*l, 0, 0); \ CAT3(sd_ifft_basecase, n, 0)(Q, X+1*l, 0, 1); \ CAT3(sd_ifft_basecase, n, 0)(Q, X+2*l, 1, 2); \ CAT3(sd_ifft_basecase, n, 0)(Q, X+3*l, 0, 2); \ { \ _RADIX_4_REVERSE_PARAM_J_IS_Z(VECND, Q) \ ulong i = 0; do { \ _RADIX_4_REVERSE_MOTH_J_IS_Z(VECND, X+0*l+i, X+1*l+i, X+2*l+i, X+3*l+i) \ } while (i += N, i < l); \ FLINT_ASSERT(i == l); \ } \ } \ void CAT3(sd_ifft_basecase, m, 0)(const sd_fft_lctx_t Q, double* X, ulong j_mr, ulong j_bits) \ { \ ulong l = n_pow2(m - 2); \ FLINT_ASSERT(j_bits != 0); \ CAT3(sd_ifft_basecase, n, 0)(Q, X+0*l, 4*j_mr+3, 2+j_bits); \ CAT3(sd_ifft_basecase, n, 0)(Q, X+1*l, 4*j_mr+2, 2+j_bits); \ CAT3(sd_ifft_basecase, n, 0)(Q, X+2*l, 4*j_mr+1, 2+j_bits); \ CAT3(sd_ifft_basecase, n, 0)(Q, X+3*l, 4*j_mr+0, 2+j_bits); \ { \ _RADIX_4_REVERSE_PARAM_J_IS_NZ(VECND, Q, j_mr, j_bits) \ ulong i = 0; do { \ _RADIX_4_REVERSE_MOTH_J_IS_NZ(VECND, X+0*l+i, X+1*l+i, X+2*l+i, X+3*l+i) \ } while (i += N, i < l); \ FLINT_ASSERT(i == l); \ } \ } EXTEND_BASECASE(4, 6) EXTEND_BASECASE(6, 8) #undef EXTEND_BASECASE /* parameter 1: j can be zero */ void sd_ifft_base_1(const sd_fft_lctx_t Q, ulong I, ulong j) { ulong j_bits, j_mr; double* x = sd_fft_lctx_blk_index(Q, I); SET_J_BITS_AND_J_MR(j_bits, j_mr, j); if (j == 0) sd_ifft_basecase_8_1(Q, x, j_mr, j_bits); else sd_ifft_basecase_8_0(Q, x, j_mr, j_bits); } /* parameter 0: j cannot be zero */ void sd_ifft_base_0(const sd_fft_lctx_t Q, ulong I, ulong j) { ulong j_bits, j_mr; double* x = sd_fft_lctx_blk_index(Q, I); FLINT_ASSERT(j != 0); SET_J_BITS_AND_J_MR(j_bits, j_mr, j); sd_ifft_basecase_8_0(Q, x, j_mr, j_bits); } /***************** inverse butterfy with truncation **************************/ /* the legal function are opt-in, and illegal/unimplemented are NULL */ #define radix_4_moth_inv_trunc_block_0_1_0 NULL #define radix_4_moth_inv_trunc_block_0_1_1 NULL #define radix_4_moth_inv_trunc_block_0_2_0 NULL #define radix_4_moth_inv_trunc_block_0_2_1 NULL #define radix_4_moth_inv_trunc_block_0_3_0 NULL #define radix_4_moth_inv_trunc_block_0_3_1 NULL #define radix_4_moth_inv_trunc_block_0_4_0 NULL #define radix_4_moth_inv_trunc_block_1_2_0 NULL #define radix_4_moth_inv_trunc_block_1_2_1 NULL #define radix_4_moth_inv_trunc_block_1_3_0 NULL #define radix_4_moth_inv_trunc_block_1_3_1 NULL #define radix_4_moth_inv_trunc_block_2_1_0 NULL #define radix_4_moth_inv_trunc_block_2_1_1 NULL #define radix_4_moth_inv_trunc_block_2_3_0 NULL #define radix_4_moth_inv_trunc_block_2_3_1 NULL #define radix_4_moth_inv_trunc_block_3_1_0 NULL #define radix_4_moth_inv_trunc_block_3_1_1 NULL #define radix_4_moth_inv_trunc_block_3_2_0 NULL #define radix_4_moth_inv_trunc_block_3_2_1 NULL #define radix_4_moth_inv_trunc_block_4_1_0 NULL #define radix_4_moth_inv_trunc_block_4_1_1 NULL #define radix_4_moth_inv_trunc_block_4_2_0 NULL #define radix_4_moth_inv_trunc_block_4_2_1 NULL #define radix_4_moth_inv_trunc_block_4_3_0 NULL #define radix_4_moth_inv_trunc_block_4_3_1 NULL #define radix_4_moth_inv_trunc_block_4_4_0 NULL #define radix_4_moth_inv_trunc_block_4_4_1 NULL /* k = 2, n = 3, z = 4, f = true [ -r + 1 r + 1 2 r*w^3] [ 2//w -2//w 0 -w^2] [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2 -r*w] [ -r r 1 r*w^3] */ static void radix_4_moth_inv_trunc_block_3_4_1( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; ulong j_r = j & (n_pow2(j_bits)/2 - 1); VECMD n = VECMOP(set_d)(Q->p); VECMD ninv = VECMOP(set_d)(Q->pinv); double W = FLINT_UNLIKELY(j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; double W2 = FLINT_UNLIKELY(j == 0) ? -1.0 : Q->w2tab[0+j_bits][j_mr]; double twoW = vec1d_reduce_pm1n_to_pmhn(-2*W, Q->p); VECMD f0 = VECMOP(set_d)(Q->w2tab[0][1]); /* r */ VECMD f1 = VECMOP(set_d)(twoW); /* 2*w^-1 */ VECMD f2 = VECMOP(set_d)(2); VECMD f3 = VECMOP(set_d)(W2); /* -w^-2 */ double rw = FLINT_UNLIKELY(j == 0) ? Q->w2tab[0][1] : Q->w2tab[1+j_bits][2*j_r+1]; VECMD fr = VECMOP(set_d)(rw); /* r*w */ VECMD fq = VECMOP(set_d)(Q->w2tab[0+j_bits][j_r]); /* w^2 */ VECMD fp_ = VECMOP(mulmod)(fr, fq, n, ninv); VECMD fp = VECMOP(reduce_pm1n_to_pmhn)(fp_, n); /* r*w^3 */ ulong i = 0; do { VECMD a, b, c, d, u, v, p, q, r; a = VECMOP(load)(X0+i); b = VECMOP(load)(X1+i); c = VECMOP(load)(X2+i); d = VECMOP(load)(X3+i); u = VECMOP(add)(a, b); v = VECMOP(sub)(a, b); p = VECMOP(mulmod)(d, fp, n, ninv); q = VECMOP(mulmod)(d, fq, n, ninv); r = VECMOP(mulmod)(d, fr, n, ninv); c = VECMOP(reduce_to_pm1n)(c, n, ninv); u = VECMOP(reduce_to_pm1n)(u, n, ninv); b = VECMOP(mulmod)(v, f1, n, ninv); v = VECMOP(mulmod)(v, f0, n, ninv); d = VECMOP(sub)(c, v); c = VECMOP(fmsub)(f2, c, v); a = VECMOP(add)(c, u); c = VECMOP(sub)(c, u); c = VECMOP(mulmod)(c, f3, n, ninv); VECMOP(store)(X0+i, VECMOP(add)(a, p)); VECMOP(store)(X1+i, VECMOP(sub)(b, q)); VECMOP(store)(X2+i, VECMOP(sub)(c, r)); VECMOP(store)(X3+i, VECMOP(add)(d, p)); } while (i += M, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 3, z = 4, f = false [ -r + 1 r + 1 2 r*w^3] [ 2//w -2//w 0 -w^2] [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2 -r*w] */ static void radix_4_moth_inv_trunc_block_3_4_0( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; ulong j_r = j & (n_pow2(j_bits)/2 - 1); VECMD n = VECMOP(set_d)(Q->p); VECMD ninv = VECMOP(set_d)(Q->pinv); double W = FLINT_UNLIKELY(j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; double W2 = FLINT_UNLIKELY(j == 0) ? -1.0 : Q->w2tab[0+j_bits][j_mr]; double twoW = vec1d_reduce_pm1n_to_pmhn(-2*W, Q->p); VECMD f0 = VECMOP(set_d)(Q->w2tab[0][1]); /* r */ VECMD f1 = VECMOP(set_d)(twoW); /* 2*w^-1 */ VECMD f2 = VECMOP(set_d)(2); VECMD f3 = VECMOP(set_d)(W2); /* -w^-2 */ double rw = FLINT_UNLIKELY(j == 0) ? Q->w2tab[0][1] : Q->w2tab[1+j_bits][2*j_r+1]; VECMD fr = VECMOP(set_d)(rw); /* r*w */ VECMD fq = VECMOP(set_d)(Q->w2tab[0+j_bits][j_r]); /* w^2 */ VECMD fp_ = VECMOP(mulmod)(fr, fq, n, ninv); VECMD fp = VECMOP(reduce_pm1n_to_pmhn)(fp_, n); /* r*w^3 */ ulong i = 0; do { VECMD a, b, c, d, u, v, p, q, r; a = VECMOP(load)(X0+i); b = VECMOP(load)(X1+i); c = VECMOP(load)(X2+i); d = VECMOP(load)(X3+i); u = VECMOP(add)(a, b); v = VECMOP(sub)(a, b); p = VECMOP(mulmod)(d, fp, n, ninv); q = VECMOP(mulmod)(d, fq, n, ninv); r = VECMOP(mulmod)(d, fr, n, ninv); c = VECMOP(reduce_to_pm1n)(c, n, ninv); u = VECMOP(reduce_to_pm1n)(u, n, ninv); b = VECMOP(mulmod)(v, f1, n, ninv); v = VECMOP(mulmod)(v, f0, n, ninv); c = VECMOP(fmsub)(f2, c, v); a = VECMOP(add)(c, u); c = VECMOP(sub)(c, u); c = VECMOP(mulmod)(c, f3, n, ninv); a = VECMOP(add)(a, p); b = VECMOP(sub)(b, q); c = VECMOP(sub)(c, r); VECMOP(store)(X0+i, a); VECMOP(store)(X1+i, b); VECMOP(store)(X2+i, c); } while (i += M, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 3, z = 3, f = true [ -r + 1 r + 1 2] [ 2//w -2//w 0] [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2] [ -r r 1] {x0, x1, x3, x4} = { -r*(x0 - x1) + (x0 + x1) + 2*x2, 2*w^-1* (x0 - x1), -w^-2*(-r*(x0 - x1) - (x0 + x1) + 2*x2), -r*(x0 - x1) + x2 } */ static void radix_4_moth_inv_trunc_block_3_3_1( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); double W = (j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; double W2 = (j == 0) ? -1.0 : Q->w2tab[0+j_bits][j_mr]; double twoW = vec1d_reduce_pm1n_to_pmhn(-2*W, Q->p); VECND f0 = VECNOP(set_d)(Q->w2tab[0][1]); /* r */ VECND f1 = VECNOP(set_d)(twoW); /* 2*w^-1 */ VECND f2 = VECNOP(set_d)(2); VECND f3 = VECNOP(set_d)(W2); /* -w^-2 */ ulong i = 0; do { VECND a, b, c, u, v; a = VECNOP(load)(X0+i); b = VECNOP(load)(X1+i); c = VECNOP(load)(X2+i); v = VECNOP(sub)(a, b); VECNOP(store)(X1+i, VECNOP(mulmod)(v, f1, n, ninv)); c = VECNOP(reduce_to_pm1n)(c, n, ninv); v = VECNOP(mulmod)(v, f0, n, ninv); VECNOP(store)(X3+i, VECNOP(sub)(c, v)); u = VECNOP(reduce_to_pm1n)(VECNOP(add)(a, b), n, ninv); c = VECNOP(fnmadd)(f2, c, v); a = VECNOP(sub)(u, c); c = VECNOP(add)(u, c); c = VECNOP(nmulmod)(c, f3, n, ninv); VECNOP(store)(X0+i, a); VECNOP(store)(X2+i, c); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 3, z = 3, f = false [ -r + 1 r + 1 2] [ 2//w -2//w 0] [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2] {x0, x1, x3} = { -r*(x0 - x1) + (x0 + x1) + 2*x2, 2*w^-1*(x0 - x1), -w^-2*(-r*(x0 - x1) - (x0 + x1) + 2*x2)} = { 2*x2 - r*v + u, 2*w^-1*v, -w^-2*(2*x2 - r*v - u)} */ static void radix_4_moth_inv_trunc_block_3_3_0( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); double W = (j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; double W2 = (j == 0) ? -1.0 : Q->w2tab[0+j_bits][j_mr]; double twoW = vec1d_reduce_pm1n_to_pmhn(-2*W, Q->p); VECND f0 = VECNOP(set_d)(Q->w2tab[0][1]); /* r */ VECND f1 = VECNOP(set_d)(twoW); /* 2*w^-1 */ VECND f2 = VECNOP(set_d)(2); VECND f3 = VECNOP(set_d)(W2); /* -w^-2 */ ulong i = 0; do { VECND a, b, c, u, v; a = VECNOP(load)(X0+i); b = VECNOP(load)(X1+i); c = VECNOP(load)(X2+i); v = VECNOP(sub)(a, b); VECNOP(store)(X1+i, VECNOP(mulmod)(v, f1, n, ninv)); c = VECNOP(reduce_to_pm1n)(c, n, ninv); v = VECNOP(mulmod)(v, f0, n, ninv); u = VECNOP(add)(a, b); u = VECNOP(reduce_to_pm1n)(u, n, ninv); c = VECNOP(fnmadd)(f2, c, v); a = VECNOP(sub)(u, c); c = VECNOP(add)(u, c); c = VECNOP(nmulmod)(c, f3, n, ninv); VECNOP(store)(X0+i, a); VECNOP(store)(X2+i, c); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 2, z = 4, f = true [ 2 2 -w^2 0] [ 2//w -2//w 0 -w^2] [1//2*r + 1//2 -1//2*r + 1//2 -1//2*w^2 -1//2*r*w^3] */ static void radix_4_moth_inv_trunc_block_2_4_1( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; ulong j_r = j & (n_pow2(j_bits)/2 - 1); VECMD n = VECMOP(set_d)(Q->p); VECMD ninv = VECMOP(set_d)(Q->pinv); double W = FLINT_UNLIKELY(j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; double rw = FLINT_UNLIKELY(j == 0) ? Q->w2tab[0][1] : Q->w2tab[1+j_bits][2*j_r+1]; double w = Q->w2tab[j_bits][j_r]; double twoW = vec1d_reduce_pm1n_to_pmhn(-2*W, Q->p); double rw3 = vec1d_mulmod(w, rw, Q->p, Q->pinv); VECMD f0 = VECMOP(set_d)(2); VECMD f1 = VECMOP(set_d)(twoW); /* 2*w^-1 */ VECMD f2 = VECMOP(set_d)(vec1d_fnmadd(0.5, Q->p, 0.5)); /* 1/2 */ VECMD f3 = VECMOP(set_d)(Q->w2tab[0][1]); /* r */ VECMD f4 = VECMOP(set_d)(w); /* w^2 */ VECMD f5 = VECMOP(set_d)(vec1d_reduce_pm1n_to_pmhn(rw3, Q->p)); /* r*w^3 */ ulong i = 0; do { VECMD a, b, u, v, s, t, g, h, p, q, r; u = VECMOP(load)(X0+i); v = VECMOP(load)(X1+i); a = VECMOP(load)(X2+i); b = VECMOP(load)(X3+i); p = VECMOP(mulmod)(a, f4, n, ninv); q = VECMOP(mulmod)(b, f4, n, ninv); r = VECMOP(mulmod)(b, f5, n, ninv); s = VECMOP(add)(u, v); s = VECMOP(reduce_to_pm1n)(s, n, ninv); t = VECMOP(sub)(u, v); g = VECMOP(mulmod)(s, f0, n, ninv); h = VECMOP(mulmod)(t, f1, n, ninv); t = VECMOP(mulmod)(t, f3, n, ninv); VECMOP(store)(X0+i, VECMOP(sub)(g, p)); VECMOP(store)(X1+i, VECMOP(sub)(h, q)); u = VECMOP(add)(s, t); v = VECMOP(add)(p, r); u = VECMOP(sub)(u, v); u = VECMOP(mulmod)(u, f2, n, ninv); VECMOP(store)(X2+i, u); } while (i += M, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 2, z = 4, f = false [ 2 2 -w^2 0] [2//w -2//w 0 -w^2] */ static void radix_4_moth_inv_trunc_block_2_4_0( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; ulong j_r = j & (n_pow2(j_bits)/2 - 1); VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); double wi = FLINT_UNLIKELY(j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; VECND w2 = VECNOP(set_d)(Q->w2tab[j_bits][j_r]); VECND twowi = VECNOP(set_d)(vec1d_reduce_pm1n_to_pmhn(-2*wi, Q->p)); ulong i = 0; do { VECND a, b, c, d, u, v; a = VECNOP(load)(X0+i); b = VECNOP(load)(X1+i); c = VECNOP(load)(X2+i); d = VECNOP(load)(X3+i); c = VECNOP(mulmod)(c, w2, n, ninv); d = VECNOP(mulmod)(d, w2, n, ninv); u = VECNOP(add)(a, b); v = VECNOP(sub)(a, b); u = VECNOP(add)(u, u); u = VECNOP(reduce_to_pm1n)(u, n, ninv); v = VECNOP(mulmod)(v, twowi, n, ninv); u = VECNOP(sub)(u, c); v = VECNOP(sub)(v, d); VECNOP(store)(X0+i, u); VECNOP(store)(X1+i, v); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 2, z = 2, f = true [ 2 2] [ 2//w -2//w] [1//2*r + 1//2 -1//2*r + 1//2] {x0, x1, x2} = {2*(x0 + x1), 2*w^-1*(x0 - x1), (x0+x1)/2 + (x0-x1)*i/2} */ static void radix_4_moth_inv_trunc_block_2_2_1( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); double W = (j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; VECND c1 = VECNOP(set_d)(vec1d_reduce_pm1n_to_pmhn(-2*W, Q->p)); /* 2/w */ VECND c2 = VECNOP(set_d)(vec1d_fnmadd(0.5, Q->p, 0.5)); /* 1/2 */ VECND c3 = VECNOP(set_d)(Q->w2tab[1][0]); /* r */ ulong i = 0; do { VECND u, v, s, t; u = VECNOP(load)(X0+i); v = VECNOP(load)(X1+i); s = VECNOP(add)(u, v); t = VECNOP(sub)(u, v); u = VECNOP(add)(s, s); u = VECNOP(reduce_to_pm1n)(u, n, ninv); v = VECNOP(mulmod)(t, c1, n, ninv); t = VECNOP(mulmod)(t, c3, n, ninv); s = VECNOP(add)(s, t); s = VECNOP(mulmod)(s, c2, n, ninv); VECNOP(store)(X0+i, u); VECNOP(store)(X1+i, v); VECNOP(store)(X2+i, s); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 2, z = 2, f = 0 {x0, x1} = {2*(x0 + x1), 2*w^-1*(x0 - x1)} */ static void radix_4_moth_inv_trunc_block_2_2_0( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_mr = n_pow2(j_bits) - 1 - j; VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); double W = (j == 0) ? -1.0 : Q->w2tab[1+j_bits][2*j_mr+1]; VECND c0 = VECNOP(set_d)(2); VECND c1 = VECNOP(set_d)(vec1d_reduce_pm1n_to_pmhn(-2*W, Q->p)); ulong i = 0; do { VECND u, v, s, t; u = VECNOP(load)(X0+i); v = VECNOP(load)(X1+i); s = VECNOP(add)(u, v); t = VECNOP(sub)(u, v); u = VECNOP(mulmod)(s, c0, n, ninv); v = VECNOP(mulmod)(t, c1, n, ninv); VECNOP(store)(X0+i, u); VECNOP(store)(X1+i, v); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 1, z = 4, f = true [4 -w -w^2 -w^3] [1 -1//2*w 0 -1//2*w^3] */ static void radix_4_moth_inv_trunc_block_1_4_1( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_r = j & (n_pow2(j_bits)/2 - 1); double W2 = Q->w2tab[j_bits][j_r]; double W = FLINT_UNLIKELY(j == 0) ? 1.0 : Q->w2tab[1+j_bits][2*j_r]; VECMD n = VECMOP(set_d)(Q->p); VECMD ninv = VECMOP(set_d)(Q->pinv); VECMD f2 = VECMOP(set_d)(2); VECMD w2 = VECMOP(set_d)(W2); double ha = vec1d_fnmadd(0.5, Q->p, 0.5); double haW = vec1d_mulmod(W, ha, Q->p, Q->pinv); VECMD wo2 = VECMOP(set_d)(vec1d_reduce_pm1n_to_pmhn(haW, Q->p)); ulong i = 0; do { VECMD a, b, c, d, u; a = VECMOP(load)(X0+i); a = VECMOP(reduce_to_pm1n)(a, n, ninv); b = VECMOP(load)(X1+i); c = VECMOP(load)(X2+i); d = VECMOP(load)(X3+i); c = VECMOP(nmulmod)(c, w2, n, ninv); d = VECMOP(mulmod)(d, w2, n, ninv); b = VECMOP(add)(b, d); b = VECMOP(mulmod)(b, wo2, n, ninv); u = VECMOP(fnmadd)(f2, a, b); b = VECMOP(sub)(a, b); a = VECMOP(reduce_to_pm1n)(VECMOP(add)(u, u), n, ninv); a = VECMOP(sub)(c, a); VECMOP(store)(X0+i, a); VECMOP(store)(X1+i, b); } while (i += M, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 1, z = 4, f = false [4 -w -w^2 -w^3] */ static void radix_4_moth_inv_trunc_block_1_4_0( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_r = j & (n_pow2(j_bits)/2 - 1); VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND f1 = VECNOP(set_d)(4.0); VECND w2 = VECNOP(set_d)(Q->w2tab[0+j_bits][j_r]); VECND w = VECNOP(set_d)(FLINT_UNLIKELY(j == 0) ? 1.0 : Q->w2tab[1+j_bits][2*j_r]); ulong i = 0; do { VECND a, b, c, d; a = VECNOP(load)(X0+i); b = VECNOP(load)(X1+i); c = VECNOP(load)(X2+i); d = VECNOP(load)(X3+i); a = VECNOP(mul)(a, f1); d = VECNOP(mulmod)(d, w, n, ninv); a = VECNOP(reduce_to_pm1n)(a, n, ninv); b = VECNOP(mulmod)(b, w, n, ninv); a = VECNOP(sub)(a, b); c = VECNOP(add)(c, d); c = VECNOP(mulmod)(c, w2, n, ninv); a = VECNOP(sub)(a, c); VECNOP(store)(X0+i, a); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 1, z = 1, f = true [4] [1] */ static void radix_4_moth_inv_trunc_block_1_1_1( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND f = VECNOP(set_d)(4.0); ulong i = 0; do { VECND a, b; a = VECNOP(load)(X0+i); b = VECNOP(mul)(f, a); VECNOP(store)(X0+i, VECNOP(reduce_to_pm1n)(b, n, ninv)); VECNOP(store)(X1+i, VECNOP(reduce_to_pm1n)(a, n, ninv)); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 1, z = 1, f = false [4] */ static void radix_4_moth_inv_trunc_block_1_1_0( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND f = VECNOP(set_d)(4.0); ulong i = 0; do { VECND a, b; a = VECNOP(load)(X0+i); b = VECNOP(mul)(f, a); VECNOP(store)(X0+i, VECNOP(reduce_to_pm1n)(b, n, ninv)); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /* k = 2, n = 0, z = 4, f = true [1//4 1//4*w 1//4*w^2 1//4*w^3] */ static void radix_4_moth_inv_trunc_block_0_4_1( const sd_fft_lctx_t Q, ulong j, ulong j_bits, double* X0, double* X1, double* X2, double* X3) { ulong j_r = j & (n_pow2(j_bits)/2 - 1); VECND n = VECNOP(set_d)(Q->p); VECND ninv = VECNOP(set_d)(Q->pinv); VECND one4th = VECNOP(set_d)(vec1d_fnmadd(0.25, Q->p, 0.25)); VECND w2 = VECNOP(set_d)(Q->w2tab[j_bits][j_r]); VECND w = VECNOP(set_d)(FLINT_UNLIKELY(j == 0) ? 1.0 : Q->w2tab[1+j_bits][2*j_r]); ulong i = 0; do { VECND a, b, c, d; a = VECNOP(load)(X0+i); b = VECNOP(load)(X1+i); c = VECNOP(load)(X2+i); d = VECNOP(load)(X3+i); b = VECNOP(mulmod)(b, w, n, ninv); d = VECNOP(mulmod)(d, w, n, ninv); a = VECNOP(add)(a, b); c = VECNOP(add)(c, d); c = VECNOP(mulmod)(c, w2, n, ninv); a = VECNOP(add)(a, c); VECNOP(store)(X0+i, VECNOP(mulmod)(a, one4th, n, ninv)); } while (i += N, i < BLK_SZ); FLINT_ASSERT(i == BLK_SZ); } /************************ the recursive stuff ********************************/ void sd_ifft_main_block( const sd_fft_lctx_t Q, ulong I, /* starting index */ ulong S, /* stride */ ulong k, /* BLK_SZ transforms each of length 2^k */ ulong j) { ulong j_bits, j_mr; if (k > 2) { ulong k1 = k/2; ulong k2 = k - k1; /* row ffts */ ulong l1 = n_pow2(k1); ulong b = 0; do { sd_ifft_main_block(Q, I + (b< 2) { ulong k1 = k/2; ulong k2 = k - k1; ulong l1 = n_pow2(k1); ulong b = 0; do { sd_ifft_main(Q, I + b*(S< 1) { ulong k1 = k/2; ulong k2 = k - k1; ulong l2 = n_pow2(k2); ulong n1 = n >> k2; ulong n2 = n & (l2 - 1); ulong z1 = z >> k2; ulong z2 = z & (l2 - 1); int fp = n2 + f > 0; ulong z2p = n_min(l2, z); ulong m = n_min(n2, z2); ulong mp = n_max(n2, z2); /* complete rows */ for (ulong b = 0; b < n1; b++) sd_ifft_main_block(Q, I + b*(S << k2), S, k2, (j << k1) + b); /* rightmost columns */ for (ulong a = n2; a < z2p; a++) sd_ifft_trunc_block(Q, I + a*S, S << k2, k1, j, z1 + (a < mp), n1, fp); /* last partial row */ if (fp) sd_ifft_trunc_block(Q, I + n1*(S << k2), S, k2, (j << k1) + n1, z2p, n2, f); /* leftmost columns */ for (ulong a = 0; a < n2; a++) sd_ifft_trunc_block(Q, I + a*S, S << k2, k1, j, z1 + (a < m), n1 + 1, 0); return; } if (k == 1) { #define IT(nn, zz, ff) CAT4(radix_2_moth_inv_trunc_block, nn, zz, ff) #define LOOKUP_IT(nn, zz, ff) tab[(ulong)(ff) + 2*((zz)-1 + 2*(nn))] static void (*tab[3*2*2*2])(const sd_fft_lctx_t, ulong, double*, double*) = {IT(0,1,0),IT(0,1,1), IT(0,2,0),IT(0,2,1), IT(1,1,0),IT(1,1,1), IT(1,2,0),IT(1,2,1), IT(2,1,0),IT(2,1,1), IT(2,2,0),IT(2,2,1)}; LOOKUP_IT(n, z, f)(Q, j, sd_fft_lctx_blk_index(Q, I + S*0), sd_fft_lctx_blk_index(Q, I + S*1)); return; #undef LOOKUP_IT #undef IT } } void sd_ifft_trunc( const sd_fft_lctx_t Q, ulong I, // starting index ulong S, // stride ulong k, // transform length 2^(k + LG_BLK_SZ) ulong j, ulong z, // actual trunc is z*BLK_SZ ulong n, // actual trunc is n*BLK_SZ int f) { FLINT_ASSERT(f == 0 || f == 1); FLINT_ASSERT(n <= z); FLINT_ASSERT(1 <= BLK_SZ*z && BLK_SZ*z <= n_pow2(k+LG_BLK_SZ)); FLINT_ASSERT(1 <= BLK_SZ*n+f && BLK_SZ*n+f <= n_pow2(k+LG_BLK_SZ)); if (k > 2) { ulong k1 = k/2; ulong k2 = k - k1; ulong l2 = n_pow2(k2); ulong n1 = n >> k2; ulong n2 = n & (l2 - 1); ulong z1 = z >> k2; ulong z2 = z & (l2 - 1); int fp = n2 + f > 0; ulong z2p = n_min(l2, z); ulong m = n_min(n2, z2); ulong mp = n_max(n2, z2); /* complete rows */ for (ulong b = 0; b < n1; b++) sd_ifft_main(Q, I + b*(S << k2), S, k2, (j << k1) + b); /* rightmost columns */ for (ulong a = n2; a < z2p; a++) sd_ifft_trunc_block(Q, I + a*S, S << k2, k1, j, z1 + (a < mp), n1, fp); /* last partial row */ if (fp) sd_ifft_trunc(Q, I + n1*(S << k2), S, k2, (j << k1) + n1, z2p, n2, f); /* leftmost columns */ for (ulong a = 0; a < n2; a++) sd_ifft_trunc_block(Q, I + a*S, S << k2, k1, j, z1 + (a < m), n1 + 1, 0); return; } if (k == 2) { sd_ifft_base_1(Q, I + S*0, 4*j+0); if (n > 1) sd_ifft_base_0(Q, I + S*1, 4*j+1); if (n > 2) sd_ifft_base_0(Q, I + S*2, 4*j+2); if (n > 3) sd_ifft_base_0(Q, I + S*3, 4*j+3); sd_ifft_trunc_block(Q, I, S, 2, j, z, n, f); if (f) sd_ifft_trunc(Q, I + S*n, S, 0, 4*j+n, 1, 0, f); } else if (k == 1) { sd_ifft_base_1(Q, I + S*0, 2*j+0); if (n > 1) sd_ifft_base_0(Q, I + S*1, 2*j+1); sd_ifft_trunc_block(Q, I, S, 1, j, z, n, f); if (f) sd_ifft_trunc(Q, I + S*n, S, 0, 2*j+n, 1, 0, f); } else { FLINT_ASSERT(!f); sd_ifft_base_1(Q, I, j); } } flint-3.1.3/src/fft_small/test/000077500000000000000000000000001461254215100163505ustar00rootroot00000000000000flint-3.1.3/src/fft_small/test/main.c000066400000000000000000000021401461254215100174350ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-fmpz_poly_mul.c" #include "t-mpn_add_inplace_c.c" #include "t-mul.c" #include "t-nmod_poly_divrem.c" #include "t-nmod_poly_mul.c" #include "t-sd_fft.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(_fmpz_poly_mul_mid_mpn_ctx), TEST_FUNCTION(flint_mpn_add_inplace_c), TEST_FUNCTION(mpn_ctx_mpn_mul), TEST_FUNCTION(_nmod_poly_divrem_mpn_ctx), TEST_FUNCTION(_nmod_poly_mul_mid_mpn_ctx), TEST_FUNCTION(sd_fft) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fft_small/test/t-fmpz_poly_mul.c000066400000000000000000000101721461254215100216520ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fft_small.h" TEST_FUNCTION_START(_fmpz_poly_mul_mid_mpn_ctx, state) { mpn_ctx_t R; mpn_ctx_init(R, UWORD(0x0003f00000000001)); { fmpz * a, * c, * d; ulong an, zn, zl, zh, sz, i, reps, abits; for (reps = 0; reps < 1000 * flint_test_multiplier(); reps++) { flint_set_num_threads(1 + n_randint(state, 10)); abits = 1 + n_randint(state, 250); an = 1 + n_randint(state, 5000); an = 1 + n_randint(state, 1 + an); zn = an + an - 1; zl = n_randint(state, zn+10); zh = n_randint(state, zn+20); sz = FLINT_MAX(zl, zh); sz = FLINT_MAX(sz, zn); a = _fmpz_vec_init(an); c = _fmpz_vec_init(sz); d = _fmpz_vec_init(sz); if (n_randint(state, 2)) _fmpz_vec_randtest_unsigned(a, state, an, abits); else _fmpz_vec_randtest(a, state, an, abits); if (_fmpz_poly_mul_mid_mpn_ctx(d, zl, zh, a, an, a, an, R)) { _fmpz_poly_mul_KS(c, a, an, a, an); for (i = zl; i < zh; i++) { if (!fmpz_equal(c + i, d + i-zl)) { flint_printf("(squaring) mulmid error at index %wu\n", i); flint_printf("abits=%wu\n", abits); flint_printf("zl=%wu, zh=%wu, an=%wu\n", zl, zh, an); flint_abort(); } } } _fmpz_vec_clear(a, an); _fmpz_vec_clear(c, sz); _fmpz_vec_clear(d, sz); } } { fmpz * a, * b, * c, * d; ulong an, bn, zn, zl, zh, sz, i, reps, abits, bbits; for (reps = 0; reps < 1000 * flint_test_multiplier(); reps++) { flint_set_num_threads(1 + n_randint(state, 10)); abits = 1 + n_randint(state, 250); bbits = 1 + n_randint(state, 250); an = 1 + n_randint(state, 5000); an = 1 + n_randint(state, 1 + an); bn = 1 + n_randint(state, an); zn = an + bn - 1; zl = n_randint(state, zn+10); zh = n_randint(state, zn+20); sz = FLINT_MAX(zl, zh); sz = FLINT_MAX(sz, zn); a = _fmpz_vec_init(an); b = _fmpz_vec_init(bn); c = _fmpz_vec_init(sz); d = _fmpz_vec_init(sz); if (n_randint(state, 2)) _fmpz_vec_randtest_unsigned(a, state, an, abits); else _fmpz_vec_randtest(a, state, an, abits); if (n_randint(state, 2)) _fmpz_vec_randtest_unsigned(b, state, bn, bbits); else _fmpz_vec_randtest(b, state, bn, bbits); _fmpz_vec_randtest(d, state, sz, bbits); if (_fmpz_poly_mul_mid_mpn_ctx(d, zl, zh, a, an, b, bn, R)) { _fmpz_poly_mul_KS(c, a, an, b, bn); for (i = zl; i < zh; i++) { if (!fmpz_equal(c + i, d + i-zl)) { flint_printf("mulmid error at index %wu\n", i); flint_printf("abits=%wu, bbits=%wu\n", abits, bbits); flint_printf("zl=%wu, zh=%wu, an=%wu, bn=%wu\n", zl, zh, an, bn); flint_abort(); } } } _fmpz_vec_clear(a, an); _fmpz_vec_clear(b, bn); _fmpz_vec_clear(c, sz); _fmpz_vec_clear(d, sz); } } mpn_ctx_clear(R); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft_small/test/t-mpn_add_inplace_c.c000066400000000000000000000046271461254215100223650ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "fft_small.h" #include "crt_helpers.h" #define TEST_ADD(n) \ flint_mpn_copyi(a, d, n); \ mpn_add_n(c, a, b, n); \ multi_add_ ## n(a, b); \ if (mpn_cmp(a, c, n) != 0) \ { \ flint_printf("FAIL: add_%i\n", n); \ flint_abort(); \ } #define TEST_SUB(n) \ flint_mpn_copyi(a, d, n); \ mpn_sub_n(c, a, b, n); \ multi_sub_ ## n(a, b); \ if (mpn_cmp(a, c, n) != 0) \ { \ flint_printf("FAIL: sub_%i\n", n); \ flint_abort(); \ } TEST_FUNCTION_START(flint_mpn_add_inplace_c, state) { slong iter; _flint_rand_init_gmp(state); for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { mp_limb_t a[10], b[10], c[10]; mp_size_t an, bn; unsigned char cf, c1, c2; bn = 1 + n_randint(state, 4); an = bn + n_randint(state, 4); flint_mpn_rrandom(a, state->gmp_state, an); flint_mpn_rrandom(b, state->gmp_state, bn); flint_mpn_copyi(c, a, an); cf = n_randint(state, 2); c1 = flint_mpn_add_inplace_c(a, an, b, bn, cf); c2 = mpn_add(c, c, an, b, bn); c2 += mpn_add_1(c, c, an, cf); if (c1 != c2 || mpn_cmp(a, c, an) != 0) { flint_printf("FAIL\n"); flint_abort(); } } for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { mp_limb_t a[8], b[8], c[8], d[8]; flint_mpn_rrandom(a, state->gmp_state, 8); flint_mpn_rrandom(b, state->gmp_state, 8); flint_mpn_copyi(c, a, 8); flint_mpn_copyi(d, a, 8); TEST_ADD(1) TEST_ADD(2) TEST_ADD(3) TEST_ADD(4) TEST_ADD(5) TEST_ADD(6) TEST_ADD(7) TEST_ADD(8) TEST_SUB(1) TEST_SUB(2) TEST_SUB(3) TEST_SUB(4) TEST_SUB(5) TEST_SUB(6) TEST_SUB(7) TEST_SUB(8) } TEST_FUNCTION_END(state); } flint-3.1.3/src/fft_small/test/t-mul.c000066400000000000000000000047261461254215100175630ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fft_small.h" #include "machine_vectors.h" void test_mul(mpn_ctx_t R, ulong maxsize, ulong nreps, flint_rand_t state) { ulong * a, * b, * c, *d; a = FLINT_ARRAY_ALLOC(maxsize, ulong); b = FLINT_ARRAY_ALLOC(maxsize, ulong); c = FLINT_ARRAY_ALLOC(maxsize, ulong); d = FLINT_ARRAY_ALLOC(maxsize, ulong); for (ulong rep = 0; rep < nreps; rep++) { ulong an = 2 + n_randint(state, maxsize - 4); ulong bn = 1 + n_randint(state, n_min(an, maxsize - an)); for (ulong i = 0; i < maxsize; i++) { a[i] = n_randlimb(state); b[i] = n_randlimb(state); c[i] = n_randlimb(state); d[i] = n_randlimb(state); } mpn_ctx_mpn_mul(R, d, a, an, b, bn); mpn_mul(c, a, an, b, bn); for (ulong i = 0; i < an + bn; i++) { if (c[i] != d[i]) { flint_printf("\nFAILED\n"); flint_printf("an = %wu, bn = %wu\n", an, bn); flint_printf("limb[%wu] = 0x%wx should be 0x%wx\n", i, d[i], c[i]); fflush(stdout); flint_abort(); } } mpn_ctx_mpn_mul(R, d, b, bn, b, bn); mpn_sqr(c, b, bn); for (ulong i = 0; i < 2 * bn; i++) { if (c[i] != d[i]) { flint_printf("\nFAILED (squaring)\n"); flint_printf("bn = %wu\n", bn); flint_printf("limb[%wu] = 0x%wx should be 0x%wx\n", i, d[i], c[i]); fflush(stdout); flint_abort(); } } flint_set_num_threads(1 + n_randint(state, 10)); } flint_free(a); flint_free(b); flint_free(c); flint_free(d); } TEST_FUNCTION_START(mpn_ctx_mpn_mul, state) { { mpn_ctx_t R; mpn_ctx_init(R, UWORD(0x0003f00000000001)); test_mul(R, 10000, 1000 * flint_test_multiplier(), state); test_mul(R, 50000, 100 * flint_test_multiplier(), state); mpn_ctx_clear(R); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fft_small/test/t-nmod_poly_divrem.c000066400000000000000000000064661461254215100223370ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" #include "fft_small.h" TEST_FUNCTION_START(_nmod_poly_divrem_mpn_ctx, state) { flint_bitcnt_t nbits; mpn_ctx_t R; nmod_t mod; mpn_ctx_init(R, UWORD(0x0003f00000000001)); { ulong * a, * b, * q1, * q2, * q3, * r1, * r2, * r3; ulong an, bn, qn, i, reps; nmod_poly_divrem_precomp_struct M[1]; for (reps = 0; reps < 1000 * flint_test_multiplier(); reps++) { flint_set_num_threads(1 + n_randint(state, 10)); /* 2 <= nbits <= FLINT_BITS */ nbits = 2 + n_randint(state, FLINT_BITS - 1); nmod_init(&mod, n_randbits(state, nbits)); bn = 2 + n_randint(state, 5000); qn = 1 + n_randint(state, 5000); an = bn + qn - 1; a = FLINT_ARRAY_ALLOC(an, ulong); b = FLINT_ARRAY_ALLOC(bn, ulong); q1 = FLINT_ARRAY_ALLOC(qn, ulong); q2 = FLINT_ARRAY_ALLOC(qn, ulong); q3 = FLINT_ARRAY_ALLOC(qn, ulong); r1 = FLINT_ARRAY_ALLOC(bn, ulong); r2 = FLINT_ARRAY_ALLOC(bn, ulong); r3 = FLINT_ARRAY_ALLOC(bn, ulong); for (i = 0; i < an; i++) a[i] = n_randint(state, mod.n); for (i = 0; i < bn; i++) b[i] = n_randint(state, mod.n); while (n_gcd(b[bn-1], mod.n) != 1) b[bn-1] = n_randint(state, mod.n); _nmod_poly_divrem(q1, r1, a, an, b, bn, mod); _nmod_poly_divrem_mpn_ctx(q2, r2, a, an, b, bn, mod, R); ulong prec = qn + n_randint(state, 200); _nmod_poly_divrem_precomp_init(M, b, bn, prec, mod, R); _nmod_poly_divrem_precomp(q3, r3, a, an, M, mod, R); _nmod_poly_divrem_precomp_clear(M); for (i = qn; i > 0; i--) { if (q1[i-1] != q2[i-1] || q1[i-1] != q3[i-1]) { flint_printf("quotient error at index %wu\n", i-1); flint_printf("qn=%wu, an=%wu, bn=%wu\n", qn, an, bn); flint_printf("mod: %wu\n", mod.n); flint_abort(); } } for (i = bn-1; i > 0; i--) { if (r1[i-1] != r2[i-1] || r1[i-1] != r3[i-1]) { flint_printf("remainder error at index %wu\n", i-1); flint_printf("r1[i]=%wu, r2[i]=%wu, bn=%wu\n", r1[i-1], r2[i-1]); flint_printf("qn=%wu, an=%wu, bn=%wu\n", qn, an, bn); flint_printf("mod: %wu\n", mod.n); flint_abort(); } } flint_free(a); flint_free(b); flint_free(q1); flint_free(q2); flint_free(r1); flint_free(r2); } } mpn_ctx_clear(R); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft_small/test/t-nmod_poly_mul.c000066400000000000000000000125171461254215100216400ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" #include "fft_small.h" TEST_FUNCTION_START(_nmod_poly_mul_mid_mpn_ctx, state) { flint_bitcnt_t nbits; mpn_ctx_t R; nmod_t mod; mpn_ctx_init(R, UWORD(0x0003f00000000001)); /* (slow) test bug where 3 instead of 4 primes were used */ #if 0 { ulong * a, *b, * c, * d; ulong an, zn, zl, zh, sz, i; nbits = FLINT_BITS; { nmod_init(&mod, UWORD(18446744073709551557)); an = 25000000; zn = an + an - 1; zl = n_randint(state, zn+10); zh = n_randint(state, zn+20); sz = FLINT_MAX(zl, zh); sz = FLINT_MAX(sz, zn); a = FLINT_ARRAY_ALLOC(an, ulong); b = FLINT_ARRAY_ALLOC(an, ulong); c = FLINT_ARRAY_ALLOC(sz, ulong); d = FLINT_ARRAY_ALLOC(sz, ulong); for (i = 0; i < an; i++) b[i] = a[i] = n_randint(state, mod.n); flint_mpn_zero(c, sz); _nmod_poly_mul_KS(c, a, an, a, an, 0, mod); _nmod_poly_mul_mid_mpn_ctx(d, zl, zh, a, an, b, an, mod, R); for (i = zl; i < zh; i++) { if (c[i] != d[i-zl]) { flint_printf("(huge) mulmid error at index %wu\n", i); flint_printf("zl=%wu, zh=%wu, an=%wu\n", zl, zh, an); flint_printf("mod: %wu\n", mod.n); flint_abort(); } } flint_free(a); flint_free(b); flint_free(c); flint_free(d); } } #endif /* Check squaring */ { ulong * a, *b, * c, * d; ulong an, zn, zl, zh, sz, i, reps; for (reps = 0; reps < 1000 * flint_test_multiplier(); reps++) { flint_set_num_threads(1 + n_randint(state, 10)); /* 1 <= nbits <= FLINT_BITS */ nbits = 1 + n_randint(state, FLINT_BITS); nmod_init(&mod, n_randbits(state, nbits)); an = 1 + n_randint(state, 7000); zn = an + an - 1; zl = n_randint(state, zn+10); zh = n_randint(state, zn+20); sz = FLINT_MAX(zl, zh); sz = FLINT_MAX(sz, zn); a = FLINT_ARRAY_ALLOC(an, ulong); b = FLINT_ARRAY_ALLOC(an, ulong); c = FLINT_ARRAY_ALLOC(sz, ulong); d = FLINT_ARRAY_ALLOC(sz, ulong); for (i = 0; i < an; i++) b[i] = a[i] = n_randint(state, mod.n); flint_mpn_zero(c, sz); _nmod_poly_mul_KS(c, a, an, a, an, 0, mod); _nmod_poly_mul_mid_mpn_ctx(d, zl, zh, a, an, b, an, mod, R); for (i = zl; i < zh; i++) { if (c[i] != d[i-zl]) { flint_printf("(squaring) mulmid error at index %wu\n", i); flint_printf("zl=%wu, zh=%wu, an=%wu\n", zl, zh, an); flint_printf("mod: %wu\n", mod.n); flint_abort(); } } flint_free(a); flint_free(b); flint_free(c); flint_free(d); } } /* Check multiplication */ { ulong * a, * b, * c, * d; ulong an, bn, zn, zl, zh, sz, i, reps; for (reps = 0; reps < 1000 * flint_test_multiplier(); reps++) { flint_set_num_threads(1 + n_randint(state, 10)); /* 1 <= nbits <= FLINT_BITS */ nbits = 1 + n_randint(state, FLINT_BITS); nmod_init(&mod, n_randbits(state, nbits)); an = 1 + n_randint(state, 7000); bn = 1 + n_randint(state, an); zn = an + bn - 1; zl = n_randint(state, zn+10); zh = n_randint(state, zn+20); sz = FLINT_MAX(zl, zh); sz = FLINT_MAX(sz, zn); a = FLINT_ARRAY_ALLOC(an, ulong); b = FLINT_ARRAY_ALLOC(bn, ulong); c = FLINT_ARRAY_ALLOC(sz, ulong); d = FLINT_ARRAY_ALLOC(sz, ulong); for (i = 0; i < an; i++) a[i] = n_randint(state, mod.n); for (i = 0; i < bn; i++) b[i] = n_randint(state, mod.n); flint_mpn_zero(c, sz); _nmod_poly_mul_KS(c, a, an, b, bn, 0, mod); _nmod_poly_mul_mid_mpn_ctx(d, zl, zh, a, an, b, bn, mod, R); for (i = zl; i < zh; i++) { if (c[i] != d[i-zl]) { flint_printf("mulmid error at index %wu\n", i); flint_printf("zl=%wu, zh=%wu, an=%wu, bn=%wu\n", zl, zh, an, bn); flint_printf("mod: %wu\n", mod.n); flint_abort(); } } flint_free(a); flint_free(b); flint_free(c); flint_free(d); } } mpn_ctx_clear(R); TEST_FUNCTION_END(state); } flint-3.1.3/src/fft_small/test/t-sd_fft.c000066400000000000000000000071611461254215100202270ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "ulong_extras.h" #include "fft_small.h" #include "machine_vectors.h" vec1d vec1d_eval_poly_mod(const vec1d* a, ulong an, const vec1d b, const vec1d n, const vec1d ninv) { vec1d x = a[--an]; while (an > 0) x = vec1d_add(a[--an], vec1d_mulmod(x, b, n, ninv)); return vec1d_reduce_to_pm1n(x, n, ninv); } void test_v2_fft(sd_fft_ctx_t Q, ulong minL, ulong maxL, ulong ireps, flint_rand_t state) { ulong irepmul = 10; minL = n_max(minL, LG_BLK_SZ); for (ulong L = minL; L <= maxL; L++) { ulong i; ulong Xn = n_pow2(L); double* X = FLINT_ARRAY_ALLOC(Xn, double); double* data = (double*) flint_aligned_alloc(32, sd_fft_ctx_data_size(L)*sizeof(double)); ulong nreps = ireps + irepmul*L; for (ulong rep = 0; rep < nreps; rep++) { // randomize input data for (i = 0; i < Xn; i++) X[i] = i + 1; // output of fft_trunc is supposed to be eval_poly ulong itrunc = n_round_up(1 + n_randint(state, Xn), Q->blk_sz); ulong otrunc = n_round_up(1 + n_randint(state, Xn) , Q->blk_sz); for (i = 0; i < itrunc; i++) sd_fft_ctx_set_index(data, i, X[i]); sd_fft_ctx_fft_trunc(Q, data, L, itrunc, otrunc); for (int check_reps = 0; check_reps < 3; check_reps++) { i = n_randint(state, otrunc); double point = sd_fft_ctx_w(Q, i); double y = vec1d_eval_poly_mod(X, itrunc, point, Q->p, Q->pinv); if (!vec1d_same_mod(y, sd_fft_ctx_get_fft_index(data, i), Q->p, Q->pinv)) { flint_printf("FAIL: fft error at index %wu\nitrunc: %wu\n" "otrunc: %wu\n", i, itrunc, otrunc); fflush(stdout); flint_abort(); } } /* output of ifft_trunc is supposed to be 2^L*input */ ulong trunc = n_round_up(1 + n_randint(state, Xn), Q->blk_sz); for (i = 0; i < trunc; i++) sd_fft_ctx_set_index( data, i, X[i]); sd_fft_ctx_fft_trunc(Q, data, L, trunc, trunc); sd_fft_ctx_ifft_trunc(Q, data, L, trunc); for (int check_reps = 0; check_reps < 3; check_reps++) { i = n_randint(state, trunc); double m = vec1d_reduce_0n_to_pmhn(nmod_pow_ui(2, L, Q->mod), Q->p); double y = vec1d_mulmod(X[i], m, Q->p, Q->pinv); if (!vec1d_same_mod(y, sd_fft_ctx_get_index(data, i), Q->p, Q->pinv)) { flint_printf("FAIL: ifft error at index %wu\n" "trunc: %wu\ndepth: %wu\n", i, trunc, L); fflush(stdout); flint_abort(); } } } flint_aligned_free(data); flint_free(X); } } TEST_FUNCTION_START(sd_fft, state) { { sd_fft_ctx_t Q; sd_fft_ctx_init_prime(Q, UWORD(0x0003f00000000001)); test_v2_fft(Q, 10, 19, 20, state); sd_fft_ctx_clear(Q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fft_tuning32.in000066400000000000000000000005061461254215100162630ustar00rootroot00000000000000/* fft_tuning.h -- autogenerated by tune-fft */ #ifndef FFT_TUNING_H #define FFT_TUNING_H #include "gmp.h" #define FFT_TAB \ { { 3, 3 }, { 3, 2 }, { 2, 1 }, { 2, 1 }, { 0, 0 } } #define MULMOD_TAB \ { 4, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 2, 2, 1, 1 } #define FFT_N_NUM 15 #define FFT_MULMOD_2EXPP1_CUTOFF 256 #endif flint-3.1.3/src/fft_tuning64.in000066400000000000000000000005221461254215100162660ustar00rootroot00000000000000/* fft_tuning.h -- autogenerated by tune-fft */ #ifndef FFT_TUNING_H #define FFT_TUNING_H #include "gmp.h" #define FFT_TAB \ { { 4, 4 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, { 2, 1 } } #define MULMOD_TAB \ { 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1 } #define FFT_N_NUM 19 #define FFT_MULMOD_2EXPP1_CUTOFF 128 #endif flint-3.1.3/src/flint-config.h.in000066400000000000000000000026101461254215100165560ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Define if system is big endian. */ #undef FLINT_BIG_ENDIAN /* Define if system is strongly ordered */ #undef FLINT_KNOW_STRONG_ORDER /* Define to set threshold for when to use fft_small module */ #undef FLINT_FFT_SMALL_THRESHOLD /* Define if system has the ADX instruction set */ #undef FLINT_HAVE_ADX /* Define if system has AVX2 */ #undef FLINT_HAVE_AVX2 /* Define if system has AVX512 */ #undef FLINT_HAVE_AVX512 /* Define to use the fft_small module */ #undef FLINT_HAVE_FFT_SMALL /* Define to enable reentrant. */ #undef FLINT_REENTRANT /* Define to enable BLAS. */ #undef FLINT_USES_BLAS /* Define if system has cpu_set_t */ #undef FLINT_USES_CPUSET /* Define to enable the Boehm-Demers-Weise garbage collector. */ #undef FLINT_USES_GC /* Define to enable the use of pthread. */ #undef FLINT_USES_PTHREAD /* Define to enable thread-local storage. */ #undef FLINT_USES_TLS /* Define to enable use of asserts. */ #undef FLINT_WANT_ASSERT /* Define to enable use of GMP internals. */ #undef FLINT_WANT_GMP_INTERNALS flint-3.1.3/src/flint.h.in000066400000000000000000000335511461254215100153230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FLINT_H #define FLINT_H #ifndef FLINT_NOSTDIO # include #endif #ifndef FLINT_NOSTDARG # include #endif #if defined(__CYGWIN__) # include #endif #include #include #ifdef BUILDING_FLINT # include "config.h" #else # include "flint-config.h" #endif #if FLINT_USES_GC # include "gc.h" #endif #if FLINT_WANT_ASSERT # include #endif #ifndef FLINT_DLL # define FLINT_DLL #endif #ifndef alloca # ifdef __GNUC__ # define alloca __builtin_alloca # else # ifdef _MSC_VER # include # define alloca _alloca # else # include /* We assume then that you have alloca.h */ # endif # endif #endif #ifdef va_start # define FLINT_HAVE_VA_LIST #endif #if defined(FILE) || defined(_FILE_DEFINED) || defined(__DEFINED_FILE) \ || defined(H_STDIO) || defined(_H_STDIO) || defined(_STDIO_H) \ || defined(_STDIO_H_) || defined(__STDIO_H) || defined(__STDIO_H__) \ || defined(__STDIO__) # define FLINT_HAVE_FILE #endif #ifdef FLINT_INLINES_C # define FLINT_INLINE #else # define FLINT_INLINE static inline #endif #ifdef __cplusplus extern "C" { #endif /* FLINT version number */ #define __FLINT_VERSION @FLINT_MAJOR@ #define __FLINT_VERSION_MINOR @FLINT_MINOR@ #define __FLINT_VERSION_PATCHLEVEL @FLINT_PATCH@ #define FLINT_VERSION "@FLINT_VERSION_FULL@" #define __FLINT_RELEASE_NUM(a,b,c) ((a)*10000 + (b)*100 + (c)) #define __FLINT_RELEASE __FLINT_RELEASE_NUM(__FLINT_VERSION, __FLINT_VERSION_MINOR, __FLINT_VERSION_PATCHLEVEL) FLINT_DLL extern char flint_version[]; struct __FLINT_FILE; typedef struct __FLINT_FILE FLINT_FILE; #define ulong mp_limb_t #define slong mp_limb_signed_t #define flint_bitcnt_t ulong #if FLINT_WANT_ASSERT # define FLINT_ASSERT(param) assert(param) #else # define FLINT_ASSERT(param) #endif #if defined(__GNUC__) # define FLINT_FORCE_INLINE static __attribute__((always_inline)) inline # define FLINT_STATIC_NOINLINE static __attribute__((noinline)) # define FLINT_UNUSED(x) UNUSED_ ## x __attribute__((unused)) # define FLINT_SET_BUT_UNUSED(x) x __attribute__((unused)) # define FLINT_CONST __attribute__ ((const)) # define FLINT_WARN_UNUSED __attribute__((warn_unused_result)) # define FLINT_UNLIKELY(x) __builtin_expect((x),0) # define FLINT_LIKELY(x) __builtin_expect((x),1) # define FLINT_PUSH_OPTIONS _Pragma("GCC push_options") # define FLINT_POP_OPTIONS _Pragma("GCC pop_options") # define FLINT_OPTIMIZE_NESTED_3(part) _Pragma(#part) # define FLINT_OPTIMIZE_NESTED_2(part) FLINT_OPTIMIZE_NESTED_3(GCC optimize part) # define FLINT_OPTIMIZE_NESTED_1(part) FLINT_OPTIMIZE_NESTED_2(#part) # define FLINT_OPTIMIZE(x) FLINT_OPTIMIZE_NESTED_1(x) # define FLINT_CONSTANT_P __builtin_constant_p # define FLINT_UNREACHABLE __builtin_unreachable() #else # define __attribute__(x) # if defined(_MSC_VER) # define FLINT_FORCE_INLINE static __forceinline # define FLINT_UNREACHABLE __assume(0) # else # define FLINT_FORCE_INLINE static inline # define FLINT_UNREACHABLE # endif # define FLINT_STATIC_NOINLINE static # define FLINT_UNUSED(x) x # define FLINT_SET_BUT_UNUSED(x) x # define FLINT_WARN_UNUSED # define FLINT_CONST # define FLINT_UNLIKELY(x) (x) # define FLINT_LIKELY(x) (x) # define FLINT_PUSH_OPTIONS # define FLINT_POP_OPTIONS # define FLINT_OPTIMIZE(x) # define FLINT_CONSTANT_P(x) 0 #endif #if defined(__cplusplus) # define FLINT_NORETURN [[noreturn]] #elif __STDC_VERSION__ < 202300L # define FLINT_NORETURN _Noreturn #else # define FLINT_NORETURN noreturn #endif #if FLINT_USES_TLS # if __STDC_VERSION__ < 202300L && !defined(__cplusplus) # define FLINT_TLS_PREFIX _Thread_local # else # define FLINT_TLS_PREFIX thread_local # endif #else # define FLINT_TLS_PREFIX #endif #if defined(_LONG_LONG_LIMB) # define _WORD_FMT "ll" # define WORD_FMT "%ll" # define WORD_WIDTH_FMT "%*ll" # define WORD(xx) (xx##LL) # define UWORD(xx) (xx##ULL) # ifndef FLINT_NO_WORDMAC # define UWORD_MAX ULLONG_MAX # define UWORD_MIN ULLONG_MIN # define WORD_MAX LLONG_MAX # define WORD_MIN LLONG_MIN # endif #else # define _WORD_FMT "l" # define WORD_FMT "%l" # define WORD_WIDTH_FMT "%*l" # define WORD(xx) (xx##L) # define UWORD(xx) (xx##UL) # ifndef FLINT_NO_WORDMAC # define UWORD_MAX ULONG_MAX # define UWORD_MIN ULONG_MIN # define WORD_MAX LONG_MAX # define WORD_MIN LONG_MIN # endif #endif #if GMP_LIMB_BITS == 64 # define FLINT_BITS 64 # define FLINT_D_BITS 53 # define FLINT64 1 #else # define FLINT_BITS 32 # define FLINT_D_BITS 31 #endif #include "longlong.h" /* memory ********************************************************************/ void * flint_malloc(size_t size); void * flint_realloc(void * ptr, size_t size); void * flint_calloc(size_t num, size_t size); void flint_free(void * ptr); void * flint_aligned_alloc(size_t alignment, size_t size); void flint_aligned_free(void * ptr); typedef void (*flint_cleanup_function_t)(void); void flint_register_cleanup_function(flint_cleanup_function_t cleanup_function); void flint_cleanup(void); void flint_cleanup_master(void); void __flint_set_all_memory_functions( void * (* alloc_func)(size_t), void * (* calloc_func)(size_t, size_t), void * (* realloc_func)(void *, size_t), void (* free_func)(void *), void * (* aligned_alloc_func)(size_t, size_t), void (* aligned_free_func)(void *)); void __flint_get_all_memory_functions( void * (** alloc_func)(size_t), void * (** calloc_func)(size_t, size_t), void * (** realloc_func)(void *, size_t), void (** free_func)(void *), void * (** aligned_alloc_func)(size_t, size_t), void (** aligned_free_func)(void *)); void __flint_set_memory_functions( void * (* alloc_func)(size_t), void * (* calloc_func)(size_t, size_t), void * (* realloc_func)(void *, size_t), void (* free_func)(void *)); void __flint_get_memory_functions( void * (** alloc_func)(size_t), void * (** calloc_func)(size_t, size_t), void * (** realloc_func)(void *, size_t), void (** free_func)(void *)); FLINT_NORETURN void flint_abort(void); void flint_set_abort(void (*func)(void)); /* threads *******************************************************************/ int flint_get_num_threads(void); void flint_set_num_threads(int num_threads); void _flint_set_num_workers(int num_workers); int flint_set_num_workers(int num_workers); void flint_reset_num_workers(int max_workers); int flint_set_thread_affinity(int * cpus, slong length); int flint_restore_thread_affinity(void); typedef int thread_pool_handle; /* randomization and test utilities ******************************************/ FLINT_CONST double flint_test_multiplier(void); typedef struct { gmp_randstate_t gmp_state; int gmp_init; mp_limb_t __randval; mp_limb_t __randval2; } flint_rand_s; typedef flint_rand_s flint_rand_t[1]; FLINT_INLINE void flint_randinit(flint_rand_t state) { state->gmp_init = 0; #if FLINT64 state->__randval = UWORD(13845646450878251009); state->__randval2 = UWORD(13142370077570254774); #else state->__randval = UWORD(4187301858); state->__randval2 = UWORD(3721271368); #endif } FLINT_INLINE void flint_randseed(flint_rand_t state, ulong seed1, ulong seed2) { state->__randval = seed1; state->__randval2 = seed2; } FLINT_INLINE void flint_get_randseed(ulong * seed1, ulong * seed2, flint_rand_t state) { *seed1 = state->__randval; *seed2 = state->__randval2; } FLINT_INLINE void _flint_rand_init_gmp(flint_rand_t state) { if (!state->gmp_init) { gmp_randinit_default(state->gmp_state); state->gmp_init = 1; } } FLINT_INLINE void flint_randclear(flint_rand_t state) { if (state->gmp_init) gmp_randclear(state->gmp_state); } FLINT_INLINE flint_rand_s * flint_rand_alloc(void) { return (flint_rand_s *) flint_malloc(sizeof(flint_rand_s)); } FLINT_INLINE void flint_rand_free(flint_rand_s * state) { flint_free(state); } /* defined in ulong_extras, but used throughout the test code */ ulong n_randint(flint_rand_t, ulong); ulong n_randtest(flint_rand_t); ulong n_randtest_not_zero(flint_rand_t); #if FLINT_USES_GC #define FLINT_GC_INIT() GC_init() #else #define FLINT_GC_INIT() #endif #define FLINT_TEST_INIT(xxx) \ flint_rand_t xxx; \ FLINT_GC_INIT(); \ flint_randinit(xxx) #define FLINT_TEST_CLEANUP(xxx) \ flint_randclear(xxx); \ flint_cleanup_master(); /* comparison macros *********************************************************/ #define FLINT_MAX(x, y) ((x) > (y) ? (x) : (y)) #define FLINT_MIN(x, y) ((x) > (y) ? (y) : (x)) #define FLINT_ABS(x) ((slong)(x) < 0 ? (-(x)) : (x)) #define FLINT_SIGN_EXT(x) (-(ulong)((slong)(x) < 0)) #define FLINT_SGN(x) ((0 < (slong)(x)) - ((slong)(x) < 0)) #define FLINT_SWAP(T, x, y) do { T _swap_t = (x); (x) = (y); (y) = _swap_t; } while(0) #define r_shift(in, shift) \ ((shift == FLINT_BITS) ? WORD(0) : ((in) >> (shift))) #define l_shift(in, shift) \ ((shift == FLINT_BITS) ? WORD(0) : ((in) << (shift))) /* Beware when using the unsigned return value in signed arithmetic */ static inline mp_limb_t FLINT_BIT_COUNT(mp_limb_t x) { mp_limb_t zeros = FLINT_BITS; if (x) zeros = flint_clz(x); return FLINT_BITS - zeros; } #define FLINT_FLOG2(k) (FLINT_BIT_COUNT(k) - 1) #define FLINT_CLOG2(k) FLINT_BIT_COUNT((k) - 1) /* mpn macros ****************************************************************/ #define flint_mpn_zero(xxx, nnn) \ do \ { \ slong ixxx; \ for (ixxx = 0; ixxx < (nnn); ixxx++) \ (xxx)[ixxx] = UWORD(0); \ } while (0) #define flint_mpn_copyi(xxx, yyy, nnn) \ do { \ slong ixxx; \ for (ixxx = 0; ixxx < (nnn); ixxx++) \ (xxx)[ixxx] = (yyy)[ixxx]; \ } while (0) #define flint_mpn_copyd(xxx, yyy, nnn) \ do { \ slong ixxx; \ for (ixxx = nnn - 1; ixxx >= 0; ixxx--) \ (xxx)[ixxx] = (yyy)[ixxx]; \ } while (0) #define flint_mpn_store(xxx, nnn, yyy) \ do \ { \ slong ixxx; \ for (ixxx = 0; ixxx < nnn; ixxx++) \ (xxx)[ixxx] = yyy; \ } while (0) /* allocation macros *********************************************************/ #define FLINT_ARRAY_ALLOC(n, T) (T *) flint_malloc((n)*sizeof(T)) #define FLINT_ARRAY_REALLOC(p, n, T) (T *) flint_realloc(p, (n)*sizeof(T)) #define TMP_INIT \ typedef struct __tmp_struct { \ void * block; \ struct __tmp_struct * next; \ } __tmp_t; \ __tmp_t * __tmp_root; \ __tmp_t * __tpx #define TMP_START \ __tmp_root = NULL #ifdef FLINT_WANT_ASSERT #define TMP_ALLOC(size) \ (__tpx = (__tmp_t *) alloca(sizeof(__tmp_t)), \ __tpx->next = __tmp_root, \ __tmp_root = __tpx, \ __tpx->block = flint_malloc(size)) #else #define TMP_ALLOC(size) \ (((size) > 8192) ? \ (__tpx = (__tmp_t *) alloca(sizeof(__tmp_t)), \ __tpx->next = __tmp_root, \ __tmp_root = __tpx, \ __tpx->block = flint_malloc(size)) : \ alloca(size)) #endif #define TMP_ARRAY_ALLOC(n, T) (T *) TMP_ALLOC((n)*sizeof(T)) #define TMP_END \ while (__tmp_root) { \ flint_free(__tmp_root->block); \ __tmp_root = __tmp_root->next; \ } /* I/O ***********************************************************************/ int parse_fmt(int * floating, const char * fmt); int flint_printf(const char * str, ...); int flint_sprintf(char * s, const char * str, ...); int flint_scanf(const char * str, ...); int flint_sscanf(const char * s, const char * str, ...); #ifdef FLINT_HAVE_VA_LIST int flint_vprintf(const char * str, va_list ap); #endif #ifdef FLINT_HAVE_FILE int flint_fprintf(FILE * f, const char * str, ...); int flint_fscanf(FILE * f, const char * str, ...); #endif #if defined(FLINT_HAVE_VA_LIST) && defined(FLINT_HAVE_FILE) int flint_vfprintf(FILE * f, const char * str, va_list ap); #endif /* exceptions ****************************************************************/ typedef enum { FLINT_ERROR, /* general error */ FLINT_OVERFLOW, /* overflow */ FLINT_IMPINV, /* impossible inverse */ FLINT_DOMERR, /* domain error */ FLINT_DIVZERO, /* divide by zero */ FLINT_EXPOF, /* exponent overflow */ FLINT_INEXACT, /* inexact error */ FLINT_TEST_FAIL /* test fail */ } flint_err_t; FLINT_NORETURN void flint_throw(flint_err_t exc, const char * msg, ...); /* checked multiplication ****************************************************/ FLINT_INLINE slong flint_mul_sizes(slong x, slong y) { ulong hi, lo; umul_ppmm(hi, lo, (ulong) x, (ulong) y); if (hi != 0 || lo > WORD_MAX) flint_throw(FLINT_OVERFLOW, "Overflow creating size %wd x %wd object.\n", x, y); return lo; } /* FLINT generic type definitions ********************************************/ typedef struct { mp_limb_t n; mp_limb_t ninv; flint_bitcnt_t norm; } nmod_t; typedef slong fmpz; typedef fmpz fmpz_t[1]; typedef struct { fmpz num; fmpz den; } fmpq; typedef fmpq fmpq_t[1]; #define fmpq_numref(__x) (&(__x)->num) #define fmpq_denref(__y) (&(__y)->den) /* fmpz macros ***************************************************************/ /* The largest bit count for an fmpz to be small */ #define SMALL_FMPZ_BITCOUNT_MAX (FLINT_BITS - 2) /* Minimum and maximum value for a small fmpz */ #define COEFF_MIN (-((WORD(1) << SMALL_FMPZ_BITCOUNT_MAX) - WORD(1))) #define COEFF_MAX ((WORD(1) << SMALL_FMPZ_BITCOUNT_MAX) - WORD(1)) /* Conversions between mpz_ptr and fmpz_t */ #define PTR_TO_COEFF(x) (((ulong) (x) >> 2) | (WORD(1) << (FLINT_BITS - 2))) #define COEFF_TO_PTR(x) ((mpz_ptr) (((ulong)x) << 2)) #define COEFF_IS_MPZ(x) (((x) >> SMALL_FMPZ_BITCOUNT_MAX) == WORD(1)) #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpq.h000066400000000000000000000326501461254215100145440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_H #define FMPQ_H #ifdef FMPQ_INLINES_C #define FMPQ_INLINE #else #define FMPQ_INLINE static inline #endif #include "fmpz.h" #ifdef __cplusplus extern "C" { #endif #define FMPQ_RECONSTRUCT_HGCD_CUTOFF 500 FMPQ_INLINE void fmpq_init(fmpq_t x) { x->num = WORD(0); x->den = WORD(1); } FMPQ_INLINE void fmpq_clear(fmpq_t x) { fmpz_clear(fmpq_numref(x)); fmpz_clear(fmpq_denref(x)); } FMPQ_INLINE void fmpq_zero(fmpq_t res) { fmpz_zero(fmpq_numref(res)); fmpz_one(fmpq_denref(res)); } FMPQ_INLINE void fmpq_one(fmpq_t res) { fmpz_one(fmpq_numref(res)); fmpz_one(fmpq_denref(res)); } FMPQ_INLINE int fmpq_equal(const fmpq_t x, const fmpq_t y) { return fmpz_equal(fmpq_numref(x), fmpq_numref(y)) && fmpz_equal(fmpq_denref(x), fmpq_denref(y)); } FMPQ_INLINE int fmpq_sgn(const fmpq_t x) { return fmpz_sgn(fmpq_numref(x)); } FMPQ_INLINE int fmpq_is_zero(const fmpq_t x) { return fmpz_is_zero(fmpq_numref(x)); } FMPQ_INLINE int fmpq_is_one(const fmpq_t x) { return fmpz_is_one(fmpq_numref(x)) && fmpz_is_one(fmpq_denref(x)); } FMPQ_INLINE int fmpq_is_pm1(const fmpq_t x) { return fmpz_is_pm1(fmpq_numref(x)) && fmpz_is_one(fmpq_denref(x)); } FMPQ_INLINE void fmpq_set(fmpq_t dest, const fmpq_t src) { fmpz_set(fmpq_numref(dest), fmpq_numref(src)); fmpz_set(fmpq_denref(dest), fmpq_denref(src)); } FMPQ_INLINE void fmpq_swap(fmpq_t op1, fmpq_t op2) { FLINT_SWAP(fmpq, *op1, *op2); } FMPQ_INLINE void fmpq_neg(fmpq_t dest, const fmpq_t src) { fmpz_neg(fmpq_numref(dest), fmpq_numref(src)); fmpz_set(fmpq_denref(dest), fmpq_denref(src)); } FMPQ_INLINE void fmpq_abs(fmpq_t dest, const fmpq_t src) { fmpz_abs(fmpq_numref(dest), fmpq_numref(src)); fmpz_set(fmpq_denref(dest), fmpq_denref(src)); } int _fmpq_cmp(const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s); int fmpq_cmp(const fmpq_t x, const fmpq_t y); int _fmpq_cmp_fmpz(const fmpz_t p, const fmpz_t q, const fmpz_t r); int fmpq_cmp_fmpz(const fmpq_t x, const fmpz_t y); int _fmpq_cmp_ui(const fmpz_t p, const fmpz_t q, ulong c); int fmpq_cmp_ui(const fmpq_t x, ulong c); int _fmpq_cmp_si(const fmpz_t p, const fmpz_t q, slong c); int fmpq_cmp_si(const fmpq_t x, slong c); void _fmpq_canonicalise(fmpz_t num, fmpz_t den); void fmpq_canonicalise(fmpq_t res); int _fmpq_is_canonical(const fmpz_t num, const fmpz_t den); int fmpq_is_canonical(const fmpq_t x); void _fmpq_set_ui(fmpz_t rnum, fmpz_t rden, ulong p, ulong q); void fmpq_set_ui(fmpq_t res, ulong p, ulong q); void _fmpq_set_si(fmpz_t rnum, fmpz_t rden, slong p, ulong q); void fmpq_set_si(fmpq_t res, slong p, ulong q); FMPQ_INLINE int fmpq_equal_ui(fmpq_t q, ulong n) { return fmpz_equal_ui(fmpq_numref(q), n) && q->den == WORD(1); } FMPQ_INLINE int fmpq_equal_si(fmpq_t q, slong n) { return fmpz_equal_si(fmpq_numref(q), n) && q->den == WORD(1); } FMPQ_INLINE void fmpq_set_fmpz(fmpq_t q, const fmpz_t n) { fmpz_set(fmpq_numref(q), n); fmpz_one(fmpq_denref(q)); } void fmpq_set_fmpz_frac(fmpq_t res, const fmpz_t p, const fmpz_t q); int fmpq_set_str(fmpq_t res, const char * str, int base); FMPQ_INLINE void fmpq_set_mpq(fmpq_t dest, const mpq_t src) { fmpz_set_mpz(fmpq_numref(dest), mpq_numref(src)); fmpz_set_mpz(fmpq_denref(dest), mpq_denref(src)); } FMPQ_INLINE void fmpq_get_mpq(mpq_t dest, const fmpq_t src) { fmpz_get_mpz(mpq_numref(dest), fmpq_numref(src)); fmpz_get_mpz(mpq_denref(dest), fmpq_denref(src)); } double fmpq_get_d(const fmpq_t a); #ifdef __MPFR_H int fmpq_get_mpfr(mpfr_t r, const fmpq_t x, mpfr_rnd_t rnd); #endif void fmpq_get_mpz_frac(mpz_t a, mpz_t b, fmpq_t c); void flint_mpq_init_set_readonly(mpq_t z, const fmpq_t f); void flint_mpq_clear_readonly(mpq_t z); void fmpq_init_set_readonly(fmpq_t f, const mpq_t z); void fmpq_clear_readonly(fmpq_t f); char * _fmpq_get_str(char * str, int b, const fmpz_t num, const fmpz_t den); char * fmpq_get_str(char * str, int b, const fmpq_t x); #ifdef FLINT_HAVE_FILE int _fmpq_fprint(FILE * file, const fmpz_t num, const fmpz_t den); int fmpq_fprint(FILE * file, const fmpq_t x); #endif int _fmpq_print(const fmpz_t num, const fmpz_t den); int fmpq_print(const fmpq_t x); void _fmpq_randtest(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits); void fmpq_randtest(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits); void fmpq_randtest_not_zero(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits); void _fmpq_randbits(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits); void fmpq_randbits(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits); void _fmpq_add_small(fmpz_t rnum, fmpz_t rden, slong p1, ulong q1, slong p2, ulong q2); void _fmpq_mul_small(fmpz_t rnum, fmpz_t rden, slong p1, ulong q1, slong p2, ulong q2); void _fmpq_add(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den); void fmpq_add(fmpq_t res, const fmpq_t op1, const fmpq_t op2); void _fmpq_add_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r); void fmpq_add_si(fmpq_t res, const fmpq_t op1, slong c); void _fmpq_add_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r); void fmpq_add_ui(fmpq_t res, const fmpq_t op1, ulong c); void _fmpq_add_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r); void fmpq_add_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c); void _fmpq_sub(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den); void fmpq_sub(fmpq_t res, const fmpq_t op1, const fmpq_t op2); void _fmpq_sub_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r); void fmpq_sub_si(fmpq_t res, const fmpq_t op1, slong c); void _fmpq_sub_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r); void fmpq_sub_ui(fmpq_t res, const fmpq_t op1, ulong c); void _fmpq_sub_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r); void fmpq_sub_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c); void _fmpq_mul_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r); void fmpq_mul_si(fmpq_t res, const fmpq_t op1, slong c); void _fmpq_mul_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r); void fmpq_mul_ui(fmpq_t res, const fmpq_t op1, ulong c); void _fmpq_mul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den); void fmpq_mul(fmpq_t res, const fmpq_t op1, const fmpq_t op2); void fmpq_mul_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x); void _fmpq_pow_si(fmpz_t rnum, fmpz_t rden, const fmpz_t opnum, const fmpz_t opden, slong e); void fmpq_pow_si(fmpq_t rop, const fmpq_t op, slong e); int fmpq_pow_fmpz(fmpq_t a, const fmpq_t b, const fmpz_t e); void _fmpq_addmul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den); void fmpq_addmul(fmpq_t res, const fmpq_t op1, const fmpq_t op2); void _fmpq_submul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den); void fmpq_submul(fmpq_t res, const fmpq_t op1, const fmpq_t op2); void fmpq_inv(fmpq_t dest, const fmpq_t src); void _fmpq_div(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den); void fmpq_div(fmpq_t res, const fmpq_t op1, const fmpq_t op2); void fmpq_div_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x); void fmpq_mul_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp); void fmpq_div_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp); int _fmpq_mod_fmpz(fmpz_t res, const fmpz_t num, const fmpz_t den, const fmpz_t mod); int fmpq_mod_fmpz(fmpz_t res, const fmpq_t x, const fmpz_t mod); void _fmpq_gcd(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s); void fmpq_gcd(fmpq_t res, const fmpq_t op1, const fmpq_t op2); void _fmpq_gcd_cofactors(fmpz_t ng, fmpz_t dg, fmpz_t A, fmpz_t B, const fmpz_t na, const fmpz_t da, const fmpz_t nb, const fmpz_t db); void fmpq_gcd_cofactors(fmpq_t g, fmpz_t A, fmpz_t B, const fmpq_t a, const fmpq_t b); int _fmpq_reconstruct_fmpz(fmpz_t num, fmpz_t den, const fmpz_t a, const fmpz_t m); int fmpq_reconstruct_fmpz(fmpq_t res, const fmpz_t a, const fmpz_t m); int _fmpq_reconstruct_fmpz_2_naive(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D); int _fmpq_reconstruct_fmpz_2(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D); int fmpq_reconstruct_fmpz_2(fmpq_t res, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D); flint_bitcnt_t fmpq_height_bits(const fmpq_t x); void fmpq_height(fmpz_t height, const fmpq_t x); void _fmpq_next_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); void fmpq_next_calkin_wilf(fmpq_t res, const fmpq_t x); void _fmpq_next_signed_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); void fmpq_next_signed_calkin_wilf(fmpq_t res, const fmpq_t x); void _fmpq_next_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); void fmpq_next_minimal(fmpq_t res, const fmpq_t x); void _fmpq_next_signed_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); void fmpq_next_signed_minimal(fmpq_t res, const fmpq_t x); void fmpq_farey_neighbors(fmpq_t left, fmpq_t right, const fmpq_t mid, const fmpz_t Q); void _fmpq_simplest_between(fmpz_t mid_num, fmpz_t mid_den, const fmpz_t l_num, const fmpz_t l_den, const fmpz_t r_num, const fmpz_t r_den); void fmpq_simplest_between(fmpq_t mid, const fmpq_t l, const fmpq_t r); slong fmpq_get_cfrac_naive(fmpz * c, fmpq_t rem, const fmpq_t x, slong n); slong fmpq_get_cfrac(fmpz * c, fmpq_t rem, const fmpq_t x, slong n); void fmpq_set_cfrac(fmpq_t x, const fmpz * c, slong n); slong fmpq_cfrac_bound(const fmpq_t x); void fmpq_dedekind_sum_naive(fmpq_t s, const fmpz_t h, const fmpz_t k); void fmpq_dedekind_sum(fmpq_t s, const fmpz_t h, const fmpz_t k); void _fmpq_harmonic_ui(fmpz_t num, fmpz_t den, ulong n); void fmpq_harmonic_ui(fmpq_t x, ulong n); /*********************** 2x2 integer matrix **********************************/ typedef struct { fmpz_t _11, _12, _21, _22; int det; /* 0,1,or,-1: 0 -> don't know, 1 -> 1, -1 -> -1 */ } _fmpz_mat22_struct; typedef _fmpz_mat22_struct _fmpz_mat22_t[1]; typedef struct { mp_limb_t _11, _12, _21, _22; int det; /* ditto */ } _ui_mat22_struct; typedef _ui_mat22_struct _ui_mat22_t[1]; void _fmpz_mat22_init(_fmpz_mat22_t M); void _fmpz_mat22_clear(_fmpz_mat22_t M); void _fmpz_mat22_one(_fmpz_mat22_t M); int _fmpz_mat22_is_one(_fmpz_mat22_t M); flint_bitcnt_t _fmpz_mat22_bits(const _fmpz_mat22_t N); void _fmpz_mat22_rmul(_fmpz_mat22_t M, const _fmpz_mat22_t N); void _fmpz_mat22_addmul_inv_vec(fmpz_t ya, fmpz_t yb, _fmpz_mat22_t N, fmpz_t xa, fmpz_t xb); void _fmpz_mat22_addmul_inv_mat(fmpz_t A11, fmpz_t A12, fmpz_t A21, fmpz_t A22, _fmpz_mat22_t M, fmpz_t B11, fmpz_t B12, fmpz_t B21, fmpz_t B22); void _fmpz_mat22_rmul_ui(_fmpz_mat22_t M, const _ui_mat22_t N); void _fmpz_mat22_rmul_inv_ui(_fmpz_mat22_t M, const _ui_mat22_t N); void _fmpz_mat22_rmul_elem(_fmpz_mat22_t M, const fmpz_t q); void _fmpz_mat22_rmul_inv_elem(_fmpz_mat22_t M, const fmpz_t q); void _fmpz_mat22_lmul_elem(_fmpz_mat22_t M, const fmpz_t q); /******** resizable integer vector specific to cfrac functionality ***********/ typedef struct { fmpz * array; slong length; slong alloc; slong limit; fmpz_t alt_sum; int want_alt_sum; } _fmpq_cfrac_list_struct; typedef _fmpq_cfrac_list_struct _fmpq_cfrac_list_t[1]; void _fmpq_cfrac_list_init(_fmpq_cfrac_list_t v); void _fmpq_cfrac_list_clear(_fmpq_cfrac_list_t v); void _fmpq_cfrac_list_fit_length(_fmpq_cfrac_list_t v, slong len); void _fmpq_cfrac_list_push_back(_fmpq_cfrac_list_t v, const fmpz_t a); void _fmpq_cfrac_list_push_back_zero(_fmpq_cfrac_list_t v); void _fmpq_cfrac_list_append_ui(_fmpq_cfrac_list_t v, const ulong * a, slong n); /*************** ball for closed interval [left, right] **********************/ typedef struct { fmpz_t left_num, left_den, right_num, right_den; int exact; } _fmpq_ball_struct; typedef _fmpq_ball_struct _fmpq_ball_t[1]; void _fmpq_ball_init(_fmpq_ball_t x); void _fmpq_ball_clear(_fmpq_ball_t x); FLINT_FORCE_INLINE void _fmpq_ball_swap(_fmpq_ball_t x, _fmpq_ball_t y) { FLINT_SWAP(_fmpq_ball_struct, *x, *y); } int _fmpq_ball_gt_one(const _fmpq_ball_t x); void _fmpq_hgcd(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, fmpz_t x_num, fmpz_t x_den); void _fmpq_ball_get_cfrac(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, int needM, _fmpq_ball_t x); /* Inlines *******************************************************************/ void fmpq_numerator(fmpz_t n, const fmpq_t q); void fmpq_denominator(fmpz_t n, const fmpq_t q); fmpz * fmpq_numerator_ptr(fmpq_t q); fmpz * fmpq_denominator_ptr(fmpq_t q); int fmpq_equal_fmpz(fmpq_t q, fmpz_t n); #define fmpq_init_set_mpz_frac_readonly _Pragma("GCC error \"'fmpq_init_set_mpz_frac_readonly' is deprecated.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpq/000077500000000000000000000000001461254215100143655ustar00rootroot00000000000000flint-3.1.3/src/fmpq/add.c000066400000000000000000000235561461254215100152740ustar00rootroot00000000000000/* Copyright (C) 2011, 2020 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" void _fmpq_add_small(fmpz_t rnum, fmpz_t rden, slong p1, ulong q1, slong p2, ulong q2) { ulong pp, qq, rr, ss; mp_limb_t hi, lo; int s1, s2; if (q1 == q2) { p1 += p2; if (q1 != 1) { ulong g = n_gcd(FLINT_ABS(p1), q1); if (g != 1) { p1 /= (slong) g; q1 /= g; } } fmpz_set_si(rnum, p1); _fmpz_demote(rden); *rden = q1; return; } if (p1 == 0) { _fmpz_demote(rnum); _fmpz_demote(rden); *rnum = p2; *rden = q2; return; } if (p2 == 0) { _fmpz_demote(rnum); _fmpz_demote(rden); *rnum = p1; *rden = q1; return; } qq = q1; ss = q2; if (p1 >= 0) { s1 = 0; pp = p1; } else { s1 = 1; pp = -p1; } if (p2 >= 0) { s2 = 0; rr = p2; } else { s2 = 1; rr = -p2; } if (ss == 1) { umul_ppmm(hi, lo, rr, qq); if (s1 == s2) { add_ssaaaa(hi, lo, hi, lo, 0, pp); } else { if (hi || (lo >= pp)) { sub_ddmmss(hi, lo, hi, lo, 0, pp); s1 = s2; } else { hi = 0; lo = pp - lo; } } _fmpz_demote(rden); *rden = qq; } else if (qq == 1) { umul_ppmm(hi, lo, pp, ss); if (s1 == s2) { add_ssaaaa(hi, lo, hi, lo, 0, rr); } else { if (hi || (lo >= rr)) { sub_ddmmss(hi, lo, hi, lo, 0, rr); } else { hi = 0; lo = rr - lo; s1 = s2; } } _fmpz_demote(rden); *rden = ss; } else { ulong g, h, a, b, t, u, v, denhi, denlo; g = n_gcd(qq, ss); if (g == 1) { umul_ppmm(hi, lo, pp, ss); umul_ppmm(t, u, qq, rr); if (s1 == s2) { add_ssaaaa(hi, lo, hi, lo, t, u); } else { if (hi > t || (hi == t && lo >= u)) { sub_ddmmss(hi, lo, hi, lo, t, u); } else { sub_ddmmss(hi, lo, t, u, hi, lo); s1 = s2; } } umul_ppmm(denhi, denlo, qq, ss); } else { a = qq / g; b = ss / g; umul_ppmm(hi, lo, pp, b); umul_ppmm(t, u, rr, a); if (s1 == s2) { add_ssaaaa(hi, lo, hi, lo, t, u); } else { if (hi > t || (hi == t && lo >= u)) { sub_ddmmss(hi, lo, hi, lo, t, u); } else { sub_ddmmss(hi, lo, t, u, hi, lo); s1 = s2; } } if (hi == 0) { h = n_gcd(lo, g); } else { udiv_qrnnd(t, h, hi % g, lo, g); h = n_gcd(h, g); } if (h != 1) { if (hi == 0) { lo /= h; } else { t = hi / h; u = hi - t * h; udiv_qrnnd(v, u, u, lo, h); hi = t; lo = v; } qq /= h; } umul_ppmm(denhi, denlo, qq, b); } fmpz_set_uiui(rden, denhi, denlo); } if (s1) fmpz_neg_uiui(rnum, hi, lo); else fmpz_set_uiui(rnum, hi, lo); } void _fmpq_add(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s) { fmpz_t g, a, b, t, u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && !COEFF_IS_MPZ(*r) && !COEFF_IS_MPZ(*s)) { _fmpq_add_small(rnum, rden, *p, *q, *r, *s); return; } /* Same denominator */ if (fmpz_equal(q, s)) { fmpz_add(rnum, p, r); /* Both are integers */ if (fmpz_is_one(q)) { fmpz_set(rden, q); } else { fmpz_init(g); fmpz_gcd(g, rnum, q); if (fmpz_is_one(g)) { fmpz_set(rden, q); } else { fmpz_divexact(rnum, rnum, g); fmpz_divexact(rden, q, g); } fmpz_clear(g); } return; } /* p/q is an integer */ if (fmpz_is_one(q)) { fmpz_init(t); fmpz_mul(t, p, s); fmpz_add(rnum, t, r); fmpz_set(rden, s); fmpz_clear(t); return; } /* r/s is an integer */ if (fmpz_is_one(s)) { fmpz_init(t); fmpz_mul(t, r, q); fmpz_add(rnum, t, p); fmpz_set(rden, q); fmpz_clear(t); return; } /* We want to compute p/q + r/s where the inputs are already in canonical form. If q and s are coprime, then (p*s + q*r, q*s) is in canonical form. Otherwise, let g = gcd(q, s) with q = g*a, s = g*b. Then the sum is given by ((p*b + r*a) / (a*b)) / g. As above, (p*b + r*a) / (a*b) is in canonical form, and g has no common factor with a*b. Thus we only need to reduce (p*b + r*a, g). If the gcd is 1, the reduced denominator is g*a*b = q*b. */ fmpz_init(g); fmpz_gcd(g, q, s); if (fmpz_is_one(g)) { fmpz_init(t); fmpz_init(u); fmpz_mul(t, p, s); fmpz_mul(u, q, r); fmpz_add(rnum, t, u); fmpz_mul(rden, q, s); fmpz_clear(t); fmpz_clear(u); } else { fmpz_init(a); fmpz_init(b); fmpz_init(t); fmpz_init(u); fmpz_divexact(a, q, g); fmpz_divexact(b, s, g); fmpz_mul(t, p, b); fmpz_mul(u, r, a); fmpz_add(rnum, t, u); fmpz_gcd(t, rnum, g); if (fmpz_is_one(t)) { fmpz_mul(rden, q, b); } else { fmpz_divexact(rnum, rnum, t); fmpz_divexact(g, q, t); fmpz_mul(rden, g, b); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(t); fmpz_clear(u); } fmpz_clear(g); } void fmpq_add(fmpq_t res, const fmpq_t op1, const fmpq_t op2) { _fmpq_add(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } void _fmpq_add_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r) { fmpz_t u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && !COEFF_IS_MPZ(*r)) { _fmpq_add_small(rnum, rden, *p, *q, *r, 1); return; } /* both are integers */ if (fmpz_is_one(q)) { fmpz_add(rnum, p, r); fmpz_set(rden, q); return; } /* We want to compute p/q + r/1 where the inputs are already in canonical form. Note (p + q*r, q) is in canonical form. */ fmpz_init(u); fmpz_mul(u, q, r); fmpz_add(rnum, p, u); fmpz_set(rden, q); fmpz_clear(u); } void fmpq_add_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c) { _fmpq_add_fmpz(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } void _fmpq_add_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r) { fmpz_t u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && r >= COEFF_MIN && r <= COEFF_MAX) { _fmpq_add_small(rnum, rden, *p, *q, r, 1); return; } /* both are integers */ if (fmpz_is_one(q)) { if (r >= 0) fmpz_add_ui(rnum, p, r); else fmpz_sub_ui(rnum, p, -r); fmpz_set(rden, q); return; } /* We want to compute p/q + r/1 where the inputs are already in canonical form. Note (p + q*r, q) is in canonical form. */ fmpz_init(u); fmpz_mul_si(u, q, r); fmpz_add(rnum, p, u); fmpz_set(rden, q); fmpz_clear(u); } void fmpq_add_si(fmpq_t res, const fmpq_t op1, slong c) { _fmpq_add_si(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } void _fmpq_add_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r) { fmpz_t u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && r <= COEFF_MAX) { _fmpq_add_small(rnum, rden, *p, *q, r, 1); return; } /* both are integers */ if (fmpz_is_one(q)) { fmpz_add_ui(rnum, p, r); fmpz_set(rden, q); return; } /* We want to compute p/q + r/1 where the inputs are already in canonical form. Note (p + q*r, q) is in canonical form. */ fmpz_init(u); fmpz_mul_ui(u, q, r); fmpz_add(rnum, p, u); fmpz_set(rden, q); fmpz_clear(u); } void fmpq_add_ui(fmpq_t res, const fmpq_t op1, ulong c) { _fmpq_add_ui(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } flint-3.1.3/src/fmpq/addmul.c000066400000000000000000000017101461254215100157760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_addmul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) { fmpz_t u, v; fmpz_init(u); fmpz_init(v); _fmpq_mul(u, v, op1num, op1den, op2num, op2den); _fmpq_add(rnum, rden, rnum, rden, u, v); fmpz_clear(u); fmpz_clear(v); } void fmpq_addmul(fmpq_t res, const fmpq_t op1, const fmpq_t op2) { _fmpq_addmul(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } flint-3.1.3/src/fmpq/ball.c000066400000000000000000000013351461254215100154450ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_ball_init(_fmpq_ball_t x) { fmpz_init(x->left_num); fmpz_init(x->left_den); fmpz_init(x->right_num); fmpz_init(x->right_den); x->exact = 0; } void _fmpq_ball_clear(_fmpq_ball_t x) { fmpz_clear(x->left_num); fmpz_clear(x->left_den); fmpz_clear(x->right_num); fmpz_clear(x->right_den); } flint-3.1.3/src/fmpq/canonicalise.c000066400000000000000000000017021461254215100171610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_canonicalise(fmpz_t num, fmpz_t den) { fmpz_t u; if (fmpz_is_one(den)) return; if (fmpz_is_zero(num)) { fmpz_one(den); return; } fmpz_init(u); fmpz_gcd(u, num, den); if (!fmpz_is_one(u)) { fmpz_divexact(num, num, u); fmpz_divexact(den, den, u); } fmpz_clear(u); if (fmpz_sgn(den) < 0) { fmpz_neg(num, num); fmpz_neg(den, den); } } void fmpq_canonicalise(fmpq_t res) { _fmpq_canonicalise(fmpq_numref(res), fmpq_denref(res)); } flint-3.1.3/src/fmpq/cfrac_bound.c000066400000000000000000000011541461254215100167770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #define ONE_OVER_LOG2_PHI (1.44042009041255648 + 1e-13) slong fmpq_cfrac_bound(const fmpq_t x) { if (fmpz_is_one(fmpq_denref(x))) return 1; return fmpz_bits(fmpq_denref(x)) * ONE_OVER_LOG2_PHI + 2; } flint-3.1.3/src/fmpq/clear_readonly.c000066400000000000000000000010141461254215100175100ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_clear_readonly(fmpq_t f) { fmpz_clear_readonly(fmpq_numref(f)); fmpz_clear_readonly(fmpq_denref(f)); } flint-3.1.3/src/fmpq/cmp.c000066400000000000000000000113071461254215100153120ustar00rootroot00000000000000/* Copyright (C) 2012, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" int _fmpq_cmp(const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s) { int s1, s2, res; flint_bitcnt_t bp, bq, br, bs; fmpz_t t, u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && !COEFF_IS_MPZ(*r) && !COEFF_IS_MPZ(*s)) { ulong a1, a0, b1, b0; smul_ppmm(a1, a0, *p, *s); smul_ppmm(b1, b0, *q, *r); sub_ddmmss(a1, a0, a1, a0, b1, b0); if ((slong) a1 < 0) return -1; if ((slong) a1 > 0) return 1; return a0 != 0; } if (fmpz_equal(q, s)) return fmpz_cmp(p, r); s1 = fmpz_sgn(p); s2 = fmpz_sgn(r); if (s1 != s2) return s1 < s2 ? -1 : 1; /* NOTE: If `p' and `r' was zero, then we stepped into the first * if-statement. Else, if `p' or `r' was zero, then s1 != s2. Hence, at this * stage `p' and `r' has to be non-zero. */ bp = fmpz_bits(p); bq = fmpz_bits(q); br = fmpz_bits(r); bs = fmpz_bits(s); if (bp + bs + 1 < br + bq) return -s1; if (bp + bs > br + bq + 1) return s1; if (fmpz_is_one(q)) { fmpz_init(t); fmpz_mul(t, p, s); res = fmpz_cmp(t, r); fmpz_clear(t); } else if (fmpz_is_one(s)) { fmpz_init(u); fmpz_mul(u, q, r); res = fmpz_cmp(p, u); fmpz_clear(u); } else { fmpz_init(t); fmpz_init(u); fmpz_mul(t, p, s); fmpz_mul(u, q, r); res = fmpz_cmp(t, u); fmpz_clear(t); fmpz_clear(u); } return res; } int fmpq_cmp(const fmpq_t x, const fmpq_t y) { return _fmpq_cmp(fmpq_numref(x), fmpq_denref(x), fmpq_numref(y), fmpq_denref(y)); } int _fmpq_cmp_fmpz(const fmpz_t p, const fmpz_t q, const fmpz_t r) { fmpz one = 1; return _fmpq_cmp(p, q, r, &one); } int fmpq_cmp_fmpz(const fmpq_t x, const fmpz_t y) { return _fmpq_cmp_fmpz(fmpq_numref(x), fmpq_denref(x), y); } int _fmpq_cmp_si(const fmpz_t p, const fmpz_t q, slong c) { int s1, s2, res; flint_bitcnt_t bp, bq, bc; slong d; fmpz_t u; if (fmpz_is_one(q)) return fmpz_cmp_si(p, c); if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q)) { ulong a1, a0, b1, b0; a0 = *p; a1 = FLINT_SIGN_EXT(a0); smul_ppmm(b1, b0, *q, c); sub_ddmmss(a1, a0, a1, a0, b1, b0); if ((slong) a1 < 0) return -1; if ((slong) a1 > 0) return 1; return a0 != 0; } s1 = fmpz_sgn(p); s2 = c > 0 ? 1 : (c < 0 ? -1 : 0); if (s1 != s2) return s1 < s2 ? -1 : 1; if (s1 == 0) return 0; bp = fmpz_bits(p); bq = fmpz_bits(q); d = -c; if (c != d) /* check for SLONG_MIN */ { d = c < 0 ? -c : c; bc = FLINT_BIT_COUNT(d); if (bp + 2 < bc + bq) return -s1; if (bp > bc + bq) return s1; } fmpz_init(u); fmpz_mul_si(u, q, c); res = fmpz_cmp(p, u); fmpz_clear(u); return res; } int fmpq_cmp_si(const fmpq_t x, slong c) { return _fmpq_cmp_si(fmpq_numref(x), fmpq_denref(x), c); } int _fmpq_cmp_ui(const fmpz_t p, const fmpz_t q, ulong c) { int s1, s2, res; flint_bitcnt_t bp, bq, bc; fmpz_t u; if (fmpz_is_one(q)) return fmpz_cmp_ui(p, c); if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && c <= WORD_MAX) { ulong a1, a0, b1, b0; a0 = *p; a1 = FLINT_SIGN_EXT(a0); smul_ppmm(b1, b0, *q, c); sub_ddmmss(a1, a0, a1, a0, b1, b0); if ((slong) a1 < 0) return -1; if ((slong) a1 > 0) return 1; return a0 != 0; } s1 = fmpz_sgn(p); s2 = (c > 0); if (s1 != s2) return s1 < s2 ? -1 : 1; /* NOTE: If `p' and `r' was zero, then we stepped into the first * if-statement. Else, if `p' or `r' was zero, then s1 != s2. Hence, at this * stage `p' and `r' has to be non-zero. */ bp = fmpz_bits(p); bq = fmpz_bits(q); bc = FLINT_BIT_COUNT(c); if (bp + 2 < bc + bq) return -s1; if (bp > bc + bq) return s1; fmpz_init(u); fmpz_mul_ui(u, q, c); res = fmpz_cmp(p, u); fmpz_clear(u); return res; } int fmpq_cmp_ui(const fmpq_t x, ulong c) { return _fmpq_cmp_ui(fmpq_numref(x), fmpq_denref(x), c); } flint-3.1.3/src/fmpq/dedekind_sum.c000066400000000000000000000117611461254215100171720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_dedekind_sum_naive(fmpq_t s, const fmpz_t h, const fmpz_t k) { fmpz_t i, j, q1, q2, r2; if (fmpz_is_zero(k)) { fmpq_zero(s); return; } fmpz_init(i); fmpz_init(j); fmpz_init(q1); fmpz_init(q2); fmpz_init(r2); fmpz_zero(fmpq_numref(s)); for (fmpz_one(i); fmpz_cmp(i, k) < 0; fmpz_add_ui(i, i, 1)) { fmpz_fdiv_q(q1, i, k); fmpz_mul(j, h, i); fmpz_fdiv_qr(q2, r2, j, k); if (fmpz_is_zero(r2)) continue; fmpz_mul(q1, q1, k); fmpz_sub(q1, i, q1); fmpz_mul_ui(q1, q1, 2); fmpz_sub(q1, q1, k); fmpz_mul(q2, q2, k); fmpz_sub(q2, j, q2); fmpz_mul_ui(q2, q2, 2); fmpz_sub(q2, q2, k); fmpz_addmul(fmpq_numref(s), q1, q2); } fmpz_mul(fmpq_denref(s), k, k); fmpz_mul_ui(fmpq_denref(s), fmpq_denref(s), 4); fmpq_canonicalise(s); fmpz_clear(i); fmpz_clear(j); fmpz_clear(q1); fmpz_clear(q2); fmpz_clear(r2); } #define _UI_MAT22_RMUL_ELEM(m11, m12, m21, m22, q) \ do { \ mp_limb_t __t1 = m12 + q*m11; \ mp_limb_t __t2 = m22 + q*m21; \ m12 = m11; \ m22 = m21; \ m11 = __t1; \ m21 = __t2; \ } while (0) void fmpq_dedekind_sum(fmpq_t sum, const fmpz_t h, const fmpz_t k) { if (fmpz_cmp_ui(k, 2) <= 0 || fmpz_is_zero(h)) { fmpq_zero(sum); return; } else if (fmpz_fits_si(k)) { /* since the alternating sum of quotients s1 - s2 + - ... + sn - 3, n odd s1 - s2 + - ... - sn, n even is < k in absolute value, we have a version for machine k */ ulong a = fmpz_get_ui(k); ulong b = fmpz_fdiv_ui(h, a); ulong m11 = 1, m12 = 0, m21 = 0, m22 = 1; ulong sum_hi, sum_lo, t = 0, q, r; while (b != 0) { udiv_qrnnd(q, r, 0, a, b); a = b; b = r; t += q; _UI_MAT22_RMUL_ELEM(m11, m12, m21, m22, q); if (b == 0) { /* break with det -1 */ t -= 3; smul_ppmm(sum_hi, sum_lo, t, m11); add_ssaaaa(sum_hi, sum_lo, sum_hi, sum_lo, 0, m21 + m12); goto set_sum; } udiv_qrnnd(q, r, 0, a, b); a = b; b = r; t -= q; _UI_MAT22_RMUL_ELEM(m11, m12, m21, m22, q); } /* break with det +1 */ smul_ppmm(sum_hi, sum_lo, t, m11); t = m21 - m12; add_ssaaaa(sum_hi, sum_lo, sum_hi, sum_lo, FLINT_SIGN_EXT(t), t); set_sum: fmpz_set_signed_uiui(fmpq_numref(sum), sum_hi, sum_lo); fmpz_set_ui(fmpq_denref(sum), m11); } else { _fmpq_cfrac_list_t s; _fmpz_mat22_t M; _fmpq_ball_t x; _fmpq_cfrac_list_init(s); s->length = -1; s->want_alt_sum = 1; _fmpz_mat22_init(M); _fmpz_mat22_one(M); _fmpq_ball_init(x); x->exact = 1; fmpz_set(x->left_num, k); fmpz_fdiv_r(x->left_den, h, k); if (!fmpz_is_zero(x->left_den)) { _fmpq_ball_get_cfrac(s, M, 1, x); /* exactly one extra iteration needed if get_cfrac is working */ FLINT_ASSERT(fmpz_divisible(x->left_num, x->left_den)); do { fmpz_fdiv_qr(x->right_num, x->left_num, x->left_num, x->left_den); _fmpz_mat22_rmul_elem(M, x->right_num); _fmpq_cfrac_list_push_back(s, x->right_num); fmpz_swap(x->left_num, x->left_den); } while (!fmpz_is_zero(x->left_den)); } FLINT_ASSERT(!fmpz_is_zero(M->_11)); FLINT_ASSERT(s->want_alt_sum == M->det); if (M->det == 1) { fmpz_sub(fmpq_numref(sum), M->_21, M->_12); } else { FLINT_ASSERT(M->det == -1); fmpz_sub_ui(s->alt_sum, s->alt_sum, 3); fmpz_add(fmpq_numref(sum), M->_21, M->_12); } fmpz_swap(fmpq_denref(sum), M->_11); fmpz_addmul(fmpq_numref(sum), s->alt_sum, fmpq_denref(sum)); _fmpq_ball_clear(x); _fmpq_cfrac_list_clear(s); _fmpz_mat22_clear(M); } fmpz_mul_ui(fmpq_denref(sum), fmpq_denref(sum), 12); fmpq_canonicalise(sum); /* extra gcd seems to be unavoidable */ } flint-3.1.3/src/fmpq/div.c000066400000000000000000000046171461254215100153230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_div(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) { fmpz_t t, u; if (!COEFF_IS_MPZ(*op1num) && !COEFF_IS_MPZ(*op1den) && !COEFF_IS_MPZ(*op2num) && !COEFF_IS_MPZ(*op2den)) { if (*op2num > 0) _fmpq_mul_small(rnum, rden, *op1num, *op1den, *op2den, *op2num); else _fmpq_mul_small(rnum, rden, *op1num, *op1den, -(*op2den), -(*op2num)); return; } fmpz_init(t); fmpz_init(u); fmpz_set(t, op2den); fmpz_set(u, op2num); _fmpq_mul(rnum, rden, op1num, op1den, t, u); fmpz_clear(t); fmpz_clear(u); if (fmpz_sgn(rden) < 0) { fmpz_neg(rnum, rnum); fmpz_neg(rden, rden); } } void fmpq_div(fmpq_t res, const fmpq_t op1, const fmpq_t op2) { if (fmpq_is_zero(op2)) { flint_throw(FLINT_ERROR, "Exception (fmpq_div). Division by zero.\n"); } _fmpq_div(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } void fmpq_div_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x) { fmpz_t y; if (fmpz_is_zero(x)) { flint_throw(FLINT_ERROR, "Exception (fmpq_div_fmpz). Division by zero.\n"); } if (!COEFF_IS_MPZ(*fmpq_numref(op)) && !COEFF_IS_MPZ(*fmpq_denref(op)) && !COEFF_IS_MPZ(*x)) { if (*x >= 0) _fmpq_mul_small(fmpq_numref(res), fmpq_denref(res), *fmpq_numref(op), *fmpq_denref(op), 1, *x); else _fmpq_mul_small(fmpq_numref(res), fmpq_denref(res), *fmpq_numref(op), *fmpq_denref(op), -WORD(1), -(*x)); return; } *y = 1; _fmpq_mul(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op), fmpq_denref(op), y, x); if (fmpz_sgn(fmpq_denref(res)) < 0) { fmpz_neg(fmpq_numref(res), fmpq_numref(res)); fmpz_neg(fmpq_denref(res), fmpq_denref(res)); } } flint-3.1.3/src/fmpq/div_2exp.c000066400000000000000000000017011461254215100162500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_div_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp) { if (fmpq_is_zero(x) || exp == 0) { fmpq_set(res, x); } else { flint_bitcnt_t v = fmpz_val2(fmpq_numref(x)); if (exp <= v) { fmpz_fdiv_q_2exp(fmpq_numref(res), fmpq_numref(x), exp); fmpz_set(fmpq_denref(res), fmpq_denref(x)); } else { fmpz_fdiv_q_2exp(fmpq_numref(res), fmpq_numref(x), v); fmpz_mul_2exp(fmpq_denref(res), fmpq_denref(x), exp - v); } } } flint-3.1.3/src/fmpq/farey_neighbors.c000066400000000000000000000042011461254215100176740ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" /* Find the fractions directly below and above a1/q1 in the Farey sequence of order Q: a0 a1 a2 ---- < ---- < ---- q0 q1 q2 The index v satisfies Q + q0 q2 + q0 a2 + a0 v = floor(--------) = --------- = --------- q1 q1 a1 */ void fmpq_farey_neighbors(fmpq_t left, fmpq_t right, const fmpq_t mid_, const fmpz_t Q_) { fmpz_t Q, t; fmpq_t mid; /* find left denominator */ if (fmpz_sgn(fmpq_denref(mid_)) <= 0 || fmpz_cmp(fmpq_denref(mid_), Q_) > 0 || !fmpz_invmod(fmpq_denref(left), fmpq_numref(mid_), fmpq_denref(mid_))) flint_throw(FLINT_ERROR, "(%s): bad input\n", __func__); /* simple handling of aliasing */ fmpz_init_set(fmpq_numref(mid), fmpq_numref(mid_)); fmpz_init_set(fmpq_denref(mid), fmpq_denref(mid_)); fmpz_init_set(Q, Q_); fmpz_init(t); fmpz_sub(t, Q, fmpq_denref(left)); fmpz_mod(t, t, fmpq_denref(mid)); fmpz_sub(fmpq_denref(left), Q, t); /* find left numerator */ fmpz_mul(t, fmpq_numref(mid), fmpq_denref(left)); fmpz_sub_ui(t, t, 1); fmpz_divexact(fmpq_numref(left), t, fmpq_denref(mid)); /* find index t */ fmpz_add(t, Q, fmpq_denref(left)); fmpz_fdiv_q(t, t, fmpq_denref(mid)); /* find right denominator */ fmpz_mul(fmpq_denref(mid), fmpq_denref(mid), t); fmpz_sub(fmpq_denref(right), fmpq_denref(mid), fmpq_denref(left)); /* find right numerator */ fmpz_mul(fmpq_numref(mid), fmpq_numref(mid), t); fmpz_sub(fmpq_numref(right), fmpq_numref(mid), fmpq_numref(left)); fmpz_clear(fmpq_numref(mid)); fmpz_clear(fmpq_denref(mid)); fmpz_clear(Q); fmpz_clear(t); } flint-3.1.3/src/fmpq/fmpz_vector.c000066400000000000000000000071621461254215100170750ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" /* after initialization one may: (1) set length to < 0: terms should not be stored, or (2) set want_alt_sum to +-1: terms should be add/sub to alt_sum, or (3) set limit to anything >= 0: stop generating terms after limit (4) set length to < 0 and set want_alt_sum to +-1: combination of (1) and (2) different combinations of these settings may or may not work */ void _fmpq_cfrac_list_init(_fmpq_cfrac_list_t v) { v->array = NULL; v->length = 0; v->alloc = 0; v->limit = WORD_MAX; v->want_alt_sum = 0; fmpz_init(v->alt_sum); } void _fmpq_cfrac_list_clear(_fmpq_cfrac_list_t v) { slong i; for (i = 0; i < v->alloc; i++) fmpz_clear(v->array + i); if (v->array) flint_free(v->array); fmpz_clear(v->alt_sum); } void _fmpq_cfrac_list_fit_length(_fmpq_cfrac_list_t v, slong len) { if (len <= v->alloc) return; if (v->alloc > 0) { len = FLINT_MAX(len, v->alloc + v->alloc/2); v->array = (fmpz *) flint_realloc(v->array, len * sizeof(fmpz)); FLINT_ASSERT(len > v->alloc); flint_mpn_zero((mp_ptr) (v->array + v->alloc), len - v->alloc); } else { v->array = (fmpz *) flint_calloc(len, sizeof(fmpz)); } v->alloc = len; } void _fmpq_cfrac_list_push_back(_fmpq_cfrac_list_t v, const fmpz_t a) { if (v->want_alt_sum) { v->want_alt_sum *= -1; if (v->want_alt_sum > 0) fmpz_sub(v->alt_sum, v->alt_sum, a); else fmpz_add(v->alt_sum, v->alt_sum, a); } if (v->length < 0) return; _fmpq_cfrac_list_fit_length(v, v->length + 1); fmpz_set(v->array + v->length, a); v->length++; FLINT_ASSERT(v->length <= v->limit); } void _fmpq_cfrac_list_push_back_zero(_fmpq_cfrac_list_t v) { v->want_alt_sum *= -1; if (v->length < 0) return; _fmpq_cfrac_list_fit_length(v, v->length + 1); fmpz_zero(v->array + v->length); v->length++; FLINT_ASSERT(v->length <= v->limit); } void _fmpq_cfrac_list_append_ui(_fmpq_cfrac_list_t v, const ulong * a, slong n) { slong i; if (v->want_alt_sum) { ulong hi = 0, lo = 0; for (i = 0; i + 2 <= n; i += 2) { add_ssaaaa(hi,lo, hi,lo, 0,a[i]); sub_ddmmss(hi,lo, hi,lo, 0,a[i + 1]); } if (i < n) { add_ssaaaa(hi,lo, hi,lo, 0,a[i]); } if (v->want_alt_sum < 0) { hi = -hi - (lo != 0); lo = -lo; } if (i < n) { v->want_alt_sum *= -1; } if (hi == 0) { fmpz_add_ui(v->alt_sum, v->alt_sum, lo); } else if (lo != 0 && hi == -UWORD(1)) { fmpz_sub_ui(v->alt_sum, v->alt_sum, -lo); } else { fmpz_t t; fmpz_init(t); fmpz_set_signed_uiui(t, hi, lo); fmpz_add(v->alt_sum, v->alt_sum, t); fmpz_clear(t); } } if (v->length < 0) return; _fmpq_cfrac_list_fit_length(v, v->length + n); for (i = 0; i < n; i++) fmpz_set_ui(v->array + v->length + i, a[i]); v->length += n; FLINT_ASSERT(v->length <= v->limit); } flint-3.1.3/src/fmpq/gcd.c000066400000000000000000000016451461254215100152740ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_gcd(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); fmpz_mul(a, p, s); fmpz_mul(b, q, r); fmpz_gcd(rnum, a, b); fmpz_mul(rden, q, s); _fmpq_canonicalise(rnum, rden); fmpz_clear(a); fmpz_clear(b); } void fmpq_gcd(fmpq_t res, const fmpq_t op1, const fmpq_t op2) { _fmpq_gcd(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } flint-3.1.3/src/fmpq/gcd_cofactors.c000066400000000000000000000041671461254215100173410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_gcd_cofactors( fmpz_t ng_, fmpz_t dg_, fmpz_t abar, fmpz_t bbar, const fmpz_t na, const fmpz_t da, const fmpz_t nb, const fmpz_t db) { fmpz_t ng, dg, nabar, dabar, nbbar, dbbar; #if FLINT_WANT_ASSERT fmpq_t cqt_g; int input_is_canonical = _fmpq_is_canonical(na, da) && _fmpq_is_canonical(nb, db); #endif fmpz_init(ng); fmpz_gcd(ng, na, nb); if (fmpz_is_zero(ng)) { fmpz_zero(ng_); fmpz_one(dg_); fmpz_zero(abar); fmpz_zero(bbar); fmpz_clear(ng); return; } #if FLINT_WANT_ASSERT fmpq_init(cqt_g); _fmpq_gcd(fmpq_numref(cqt_g), fmpq_denref(cqt_g), na, da, nb, db); #endif fmpz_init(dg); fmpz_init(nabar); fmpz_init(dabar); fmpz_init(nbbar); fmpz_init(dbbar); fmpz_divexact(nabar, na, ng); fmpz_divexact(nbbar, nb, ng); fmpz_gcd(dg, da, db); fmpz_divexact(dabar, da, dg); fmpz_divexact(dbbar, db, dg); fmpz_mul(abar, nabar, dbbar); fmpz_mul(bbar, dabar, nbbar); fmpz_mul(dg_, da, dbbar); fmpz_swap(ng_, ng); #if FLINT_WANT_ASSERT if (input_is_canonical) { FLINT_ASSERT(fmpz_equal(fmpq_numref(cqt_g), ng_)); FLINT_ASSERT(fmpz_equal(fmpq_denref(cqt_g), dg_)); fmpz_gcd(ng, abar, bbar); FLINT_ASSERT(fmpz_is_one(ng)); } fmpq_clear(cqt_g); #endif fmpz_clear(ng); fmpz_clear(dg); fmpz_clear(nabar); fmpz_clear(dabar); fmpz_clear(nbbar); fmpz_clear(dbbar); } void fmpq_gcd_cofactors(fmpq_t g, fmpz_t A, fmpz_t B, const fmpq_t a, const fmpq_t b) { _fmpq_gcd_cofactors(fmpq_numref(g), fmpq_denref(g), A, B, fmpq_numref(a), fmpq_denref(a), fmpq_numref(b), fmpq_denref(b)); } flint-3.1.3/src/fmpq/get_cfrac.c000066400000000000000000000067541461254215100164620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copywrite (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" slong fmpq_get_cfrac(fmpz * c, fmpq_t rem, const fmpq_t f, slong limit) { slong i; int cmp, num_sign, den_sign; _fmpq_ball_t x; _fmpq_cfrac_list_t s; _fmpz_mat22_t M; #if FLINT_WANT_ASSERT int input_is_canonical; #endif num_sign = fmpz_sgn(fmpq_denref(f)); den_sign = fmpz_sgn(fmpq_denref(f)); if (limit <= 0 || den_sign == 0) { if (num_sign < 0) { fmpz_neg(fmpq_numref(rem), fmpq_numref(f)); fmpz_neg(fmpq_denref(rem), fmpq_denref(f)); } else { fmpz_set(fmpq_numref(rem), fmpq_numref(f)); fmpz_set(fmpq_denref(rem), fmpq_denref(f)); } fmpz_swap(fmpq_numref(rem), fmpq_denref(rem)); return 0; } #if FLINT_WANT_ASSERT input_is_canonical = fmpq_is_canonical(f); #endif _fmpz_mat22_init(M); _fmpz_mat22_one(M); _fmpq_ball_init(x); if (den_sign > 0) { fmpz_set(x->left_num, fmpq_numref(f)); fmpz_set(x->left_den, fmpq_denref(f)); } else { fmpz_neg(x->left_num, fmpq_numref(f)); fmpz_neg(x->left_den, fmpq_denref(f)); } x->exact = 1; _fmpq_cfrac_list_init(s); s->limit = limit; cmp = fmpz_cmp(x->left_num, x->left_den); if (cmp > 0) { /* 1 < x */ _fmpq_ball_get_cfrac(s, M, 0, x); } else { /* x <= 1 */ _fmpq_cfrac_list_push_back_zero(s); if (cmp >= 0 || fmpz_sgn(x->left_num) < 0) { /* x == 1 or x < 0 */ fmpz_fdiv_qr(s->array + 0, x->left_num, x->left_num, x->left_den); } fmpz_swap(x->left_num, x->left_den); if (!fmpz_is_zero(x->left_den)) _fmpq_ball_get_cfrac(s, M, 0, x); } FLINT_ASSERT(fmpz_is_zero(x->left_den) || _fmpq_ball_gt_one(x)); FLINT_ASSERT(x->exact); while (s->length < s->limit && !fmpz_is_zero(x->left_den)) { _fmpq_cfrac_list_push_back_zero(s); fmpz_fdiv_qr(s->array + s->length - 1, x->left_num, x->left_num, x->left_den); fmpz_swap(x->left_num, x->left_den); } /* write remainder */ FLINT_ASSERT(!fmpz_is_zero(x->left_num)); fmpz_swap(fmpq_numref(rem), x->left_den); fmpz_swap(fmpq_denref(rem), x->left_num); FLINT_ASSERT(!input_is_canonical || fmpq_is_canonical(rem)); /* write terms */ FLINT_ASSERT(s->length <= limit); for (i = 0; i < s->length; i++) fmpz_swap(c + i, s->array + i); _fmpz_mat22_clear(M); _fmpq_ball_clear(x); _fmpq_cfrac_list_clear(s); return i; } slong fmpq_get_cfrac_naive(fmpz * c, fmpq_t rem, const fmpq_t x, slong n) { fmpz_t p, q; slong i; fmpz_init(p); fmpz_init(q); fmpz_set(p, fmpq_numref(x)); fmpz_set(q, fmpq_denref(x)); for (i = 0; i < n && !fmpz_is_zero(q); i++) { fmpz_fdiv_qr(c + i, p, p, q); fmpz_swap(p, q); } fmpz_set(fmpq_numref(rem), q); fmpz_set(fmpq_denref(rem), p); fmpq_canonicalise(rem); fmpz_clear(p); fmpz_clear(q); return i; } flint-3.1.3/src/fmpq/get_cfrac_helpers.c000066400000000000000000000755041461254215100202030ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "fmpq.h" #include "fmpz_poly.h" /* enable for debug printing of various types */ #if 0 static void _fmpz_mat22_print(const _fmpz_mat22_t M) { printf("Matrix[\n "); fmpz_print(M->_11); printf(",\n "); fmpz_print(M->_12); printf(",\n "); fmpz_print(M->_21); printf(",\n "); fmpz_print(M->_22); printf("]\n"); } static void _ui_mat22_print(const _ui_mat22_t M) { flint_printf("Matrix[{{%wu, %wu}, {%wu, %wu}}]", M->_11, M->_12, M->_21, M->_22); } static void _fmpq_ball_print(const _fmpq_ball_t x) { if (x->exact) printf("ExactBall["); else printf("Ball["); fmpz_print(x->left_num); flint_printf("/"); fmpz_print(x->left_den); flint_printf(", "); fmpz_print(x->right_num); flint_printf("/"); fmpz_print(x->right_den); flint_printf("]"); } #endif #if FLINT_WANT_ASSERT static int _fmpq_ball_is_ordered(const _fmpq_ball_t x) { return x->exact || _fmpq_cmp(x->left_num, x->left_den, x->right_num, x->right_den) <= 0; } /* y = m^-1(x) */ static void _fmpq_ball_apply_mat22_inv( _fmpq_ball_t y, const _fmpz_mat22_t M, const _fmpq_ball_t x) { y->exact = x->exact; if (M->det == 1) { if (!x->exact) { fmpz_mul(y->right_num, x->right_num, M->_22); fmpz_submul(y->right_num, x->right_den, M->_12); fmpz_mul(y->right_den, x->right_den, M->_11); fmpz_submul(y->right_den, x->right_num, M->_21); } fmpz_mul(y->left_num, x->left_num, M->_22); fmpz_submul(y->left_num, x->left_den, M->_12); fmpz_mul(y->left_den, x->left_den, M->_11); fmpz_submul(y->left_den, x->left_num, M->_21); } else { FLINT_ASSERT(M->det == -1); /* det = -1 swaps the endpoints */ if (x->exact) { fmpz_mul(y->left_num, x->left_den, M->_12); fmpz_submul(y->left_num, x->left_num, M->_22); fmpz_mul(y->left_den, x->left_num, M->_21); fmpz_submul(y->left_den, x->left_den, M->_11); } else { fmpz_mul(y->right_num, x->left_den, M->_12); fmpz_submul(y->right_num, x->left_num, M->_22); fmpz_mul(y->right_den, x->left_num, M->_21); fmpz_submul(y->right_den, x->left_den, M->_11); fmpz_mul(y->left_num, x->right_den, M->_12); fmpz_submul(y->left_num, x->right_num, M->_22); fmpz_mul(y->left_den, x->right_num, M->_21); fmpz_submul(y->left_den, x->right_den, M->_11); } } } static int _fmpq_ball_equal(const _fmpq_ball_t x, _fmpq_ball_t y) { if (x->exact != y->exact) return 0; if (!fmpz_equal(x->left_num, y->left_num) || !fmpz_equal(x->left_den, y->left_den)) return 0; if (x->exact) return 1; if (!fmpz_equal(x->right_num, y->right_num) || !fmpz_equal(x->right_den, y->right_den)) return 0; return 1; } #endif /* y = [q 1; 1 0]^-1(x), also takes the left remainder */ static void _fmpq_ball_apply_mat22_inv_elem2( _fmpq_ball_t y, const fmpz_t q, fmpz_t r, const _fmpq_ball_t x) { y->exact = x->exact; if (x->exact) { fmpz_set(y->left_num, x->left_den); fmpz_swap(y->left_den, r); } else { fmpz_set(y->right_num, x->left_den); fmpz_swap(y->right_den, r); fmpz_set(y->left_num, x->right_den); fmpz_set(y->left_den, x->right_num); fmpz_submul(y->left_den, x->right_den, q); } } /* is x canonical and bounded away from 1, i.e. 1 < x ? */ int _fmpq_ball_gt_one(const _fmpq_ball_t x) { if (fmpz_sgn(x->left_num) <= 0) return 0; if (fmpz_sgn(x->left_den) <= 0) return 0; if (fmpz_cmp(x->left_den, x->left_num) >= 0) return 0; if (x->exact) return 1; if (fmpz_sgn(x->right_num) <= 0) return 0; if (fmpz_sgn(x->right_den) <= 0) return 0; if (fmpz_cmp(x->right_den, x->right_num) >= 0) return 0; return 1; } #define CFRAC_NEED_MATRIX 1 #define CFRAC_NEED_HGCD 2 /********************* hgcd ******************* for a > b > 0, the hgcd returns terms for the open interval (a/(b+1), (a+1)/b) M is the product of the quotients {{q,1},{1,0}} if xa/xb = M(ya/yb), then det +1: M^-1 = {{m22, -m12}, {-m21, m11}} xa xa+1 ya-m12 ya+m22 (----, ----) = M((------, ------)) xb+1 xb yb+m11 yb-m21 det -1: M^-1 = {{-m22, m12}, {m21, -m11}} xa xa+1 ya-m22 ya+m12 (----, ----) = M((------, ------)) xb+1 xb yb+m21 yb-m11 we say that ya/yb is ok w.r.t. M if the above intervals are > 1, i.e. det +1: yb > m21, and ya - yb >= m11 + m12 det -1: yb > m11, and ya - yb >= m21 + m22 */ static int _hgcd_ok(const _fmpz_mat22_t M, const fmpz_t a, const fmpz_t b) { int r = 1; fmpz_t t1, t2; fmpz_init(t1); fmpz_init(t2); FLINT_ASSERT(fmpz_sgn(M->_11) >= 0); FLINT_ASSERT(fmpz_sgn(M->_12) >= 0); FLINT_ASSERT(fmpz_sgn(M->_21) >= 0); FLINT_ASSERT(fmpz_sgn(M->_22) >= 0); r = r && (fmpz_cmp(a, b) > 0); r = r && (fmpz_sgn(b) > 0); if (M->det == 1) { r = r && (fmpz_cmp(a, M->_12) > 0); r = r && (fmpz_cmp(b, M->_21) > 0); fmpz_add(t2, M->_11, M->_12); } else { FLINT_ASSERT(M->det == -1); r = r && (fmpz_cmp(a, M->_22) > 0); r = r && (fmpz_cmp(b, M->_11) > 0); fmpz_add(t2, M->_21, M->_22); } fmpz_sub(t1, a, b); r = r && (fmpz_cmp(t1, t2) >= 0); fmpz_clear(t1); fmpz_clear(t2); return r; } static flint_bitcnt_t _hgcd_split( fmpz_t xa, fmpz_t xb, const fmpz_t ya, const fmpz_t yb, const _fmpz_mat22_t M, flint_bitcnt_t shift) { flint_bitcnt_t r = 0; fmpz_t ta, tb; FLINT_ASSERT(_hgcd_ok(M, ya, yb)); fmpz_init(ta); fmpz_init(tb); if (M->det == 1) { fmpz_sub(xa, ya, M->_12); fmpz_sub(xb, yb, M->_21); fmpz_add(ta, ya, M->_22); fmpz_add(tb, yb, M->_11); } else { FLINT_ASSERT(M->det == -1); fmpz_sub(xa, ya, M->_22); fmpz_sub(xb, yb, M->_11); fmpz_add(ta, ya, M->_12); fmpz_add(tb, yb, M->_21); } FLINT_ASSERT(fmpz_sgn(xa) > 0); FLINT_ASSERT(fmpz_sgn(xb) > 0); FLINT_ASSERT(fmpz_cmp(ta, xa) >= 0); FLINT_ASSERT(fmpz_cmp(tb, xb) >= 0); fmpz_fdiv_q_2exp(xa, xa, shift); fmpz_fdiv_q_2exp(ta, ta, shift); fmpz_fdiv_q_2exp(xb, xb, shift); fmpz_fdiv_q_2exp(tb, tb, shift); if (fmpz_sgn(xb) <= 0 || fmpz_cmp(xa, xb) <= 0) goto cleanup; while (!fmpz_equal(xa, ta) || !fmpz_equal(xb, tb)) { shift++; fmpz_fdiv_q_2exp(xa, xa, 1); fmpz_fdiv_q_2exp(ta, ta, 1); fmpz_fdiv_q_2exp(xb, xb, 1); fmpz_fdiv_q_2exp(tb, tb, 1); if (fmpz_sgn(xb) <= 0 || fmpz_cmp(xa, xb) <= 0) goto cleanup; } r = shift; cleanup: fmpz_clear(ta); fmpz_clear(tb); return r; } /* hgcd for two-limb input s should have at least 2*FLINT_BITS entries allocated */ static slong _uiui_hgcd( mp_limb_t * s, mp_limb_t A1, mp_limb_t A0, mp_limb_t B1, mp_limb_t B0, _ui_mat22_t M) { slong written = 0; mp_limb_t d0, d1; mp_limb_t t0, t1, t2, r0, r1; int det = 1; mp_limb_t m11 = 1; mp_limb_t m12 = 0; mp_limb_t m21 = 0; mp_limb_t m22 = 1; mp_limb_t a1 = A1; mp_limb_t a0 = A0; mp_limb_t b1 = B1; mp_limb_t b0 = B0; mp_limb_t q; FLINT_ASSERT(a1 != 0); FLINT_ASSERT(b1 < a1 || (b1 == a1 && b0 <= a0)); if (b1 == 0 || !(b1 < a1 || (b1 == a1 && b0 < a0))) goto done; while (1) { eudiv_qrrnndd(q, r1, r0, a1, a0, b1, b0, hgcd_); t1 = m12 + q*m11; t2 = m22 + q*m21; if (r1 == 0) break; a0 = b0; a1 = b1; b0 = r0; b1 = r1; m12 = m11; m22 = m21; m11 = t1; m21 = t2; det *= -1; s[written] = q; written++; FLINT_ASSERT(written <= 2*FLINT_BITS); } FLINT_ASSERT(a1 != 0); FLINT_ASSERT(b1 <= a1); FLINT_ASSERT(b1 < a1 || (b1 == a1 && b0 < a0)); sub_ddmmss(d1,d0, a1,a0, b1,b0); if (det == 1) { if (b1 == 0 && b0 <= m21) goto fix; add_ssaaaa(t1,t0, 0,m11, 0,m12); } else { if (b1 == 0 && b0 <= m11) goto fix; add_ssaaaa(t1,t0, 0,m21, 0,m22); } if (d1 < t1 || (d1 == t1 && d0 < t0)) goto fix; fixed: #if FLINT_WANT_ASSERT /* should be ok */ sub_ddmmss(d1,d0, a1,a0, b1,b0); if (det == 1) { FLINT_ASSERT(!(b1 == 0 && b0 <= m21)); add_ssaaaa(t1,t0, 0,m11, 0,m12); } else { FLINT_ASSERT(!(b1 == 0 && b0 <= m11)); add_ssaaaa(t1,t0, 0,m21, 0,m22); } FLINT_ASSERT(!(d1 < t1 || (d1 == t1 && d0 < t0))); /* should have {A, B} == {{m11, m12}, {m21, m22}} . {a, b} */ umul_ppmm(t1,t0, a0, m11); t1 += a1*m11; umul_ppmm(d1,d0, b0, m12); d1 += b1*m12; add_sssaaaaaa(t2,t1,t0, 0,t1,t0, 0,d1,d0); FLINT_ASSERT(t0 == A0 && t1 == A1 && t2 == 0); umul_ppmm(t1,t0, a0, m21); t1 += a1*m21; umul_ppmm(d1,d0, b0, m22); d1 += b1*m22; add_sssaaaaaa(t2,t1,t0, 0,t1,t0, 0,d1,d0); FLINT_ASSERT(t0 == B0 && t1 == B1 && t2 == 0); /* should have det = Det[{{m11, m12}, {m21, m22}}] */ umul_ppmm(t1,t0, m11, m22); umul_ppmm(d1,d0, m12, m21); sub_ddmmss(t1,t0, t1,t0, d1,d0); FLINT_ASSERT(t1 == FLINT_SIGN_EXT(t0)); FLINT_ASSERT(t0 == det); #endif done: M->_11 = m11; M->_12 = m12; M->_21 = m21; M->_22 = m22; M->det = det; return written; fix: written--; FLINT_ASSERT(written >= 0); q = s[written]; t1 = m11 - q*m12; t2 = m21 - q*m22; m11 = m12; m21 = m22; m12 = t1; m22 = t2; det *= -1; #if FLINT_WANT_ASSERT umul_ppmm(t1,t0, a0, q); t1 += a1*q; add_ssaaaa(t1,t0, t1,t0, b1,b0); b0 = a0; b1 = a1; a0 = t0; a1 = t1; #endif goto fixed; } static void _lehmer_exact(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, int flags, fmpz_t xa, fmpz_t xb, fmpz_t ya, fmpz_t yb) { mp_limb_t s_temp[2*FLINT_BITS]; slong written; unsigned int x_lzcnt; mpz_ptr xn, xd, yn, yd; mp_size_t xn_len, xd_len, yn_len, yd_len; mp_ptr xn_ptr, xd_ptr, yn_ptr, yd_ptr; _ui_mat22_t m; mp_limb_t A0, A1, B0, B1; mp_size_t n; if (!COEFF_IS_MPZ(*xa) || !COEFF_IS_MPZ(*xb)) return; xn = COEFF_TO_PTR(*xa); xd = COEFF_TO_PTR(*xb); yn = _fmpz_promote(ya); yd = _fmpz_promote(yb); /* fit everything to xn_len */ n = xn->_mp_size; FLINT_MPZ_REALLOC(xd, n); FLINT_MPZ_REALLOC(yn, n); FLINT_MPZ_REALLOC(yd, n); again: xn_len = xn->_mp_size; xd_len = xd->_mp_size; xn_ptr = xn->_mp_d; xd_ptr = xd->_mp_d; yn_ptr = yn->_mp_d; yd_ptr = yd->_mp_d; /* supposed xn > xd > 0 */ FLINT_ASSERT(xn_len >= xd_len); FLINT_ASSERT(xd_len > 0); FLINT_ASSERT(xn_ptr[xn_len - 1] != 0); FLINT_ASSERT(xd_ptr[xd_len - 1] != 0); n = xn_len; if (n < 3) goto cleanup; if ((flags & CFRAC_NEED_HGCD) && xd_len <= 3 + _fmpz_mat22_bits(M)/FLINT_BITS) { goto cleanup; } if (n != xd_len && n != xd_len + 1) goto cleanup; if (n == xd_len + 1) xd_ptr[n - 1] = 0; x_lzcnt = flint_clz(xn_ptr[n - 1]); A1 = MPN_LEFT_SHIFT_HI(xn_ptr[n - 1], xn_ptr[n - 2], x_lzcnt); A0 = MPN_LEFT_SHIFT_HI(xn_ptr[n - 2], xn_ptr[n - 3], x_lzcnt); B1 = MPN_LEFT_SHIFT_HI(xd_ptr[n - 1], xd_ptr[n - 2], x_lzcnt); B0 = MPN_LEFT_SHIFT_HI(xd_ptr[n - 2], xd_ptr[n - 3], x_lzcnt); written = _uiui_hgcd(s_temp, A1, A0, B1, B0, m); if (written <= 0 || s->length + written > s->limit) goto cleanup; if (m->det == 1) { yn_len = flint_mpn_fmms1(yn_ptr, m->_22, xn_ptr, m->_12, xd_ptr, n); if (yn_len <= 0) goto cleanup; yd_len = flint_mpn_fmms1(yd_ptr, m->_11, xd_ptr, m->_21, xn_ptr, n); if (yd_len <= 0) goto cleanup; } else { yn_len = flint_mpn_fmms1(yn_ptr, m->_12, xd_ptr, m->_22, xn_ptr, n); if (yn_len <= 0) goto cleanup; yd_len = flint_mpn_fmms1(yd_ptr, m->_21, xn_ptr, m->_11, xd_ptr, n); if (yd_len <= 0) goto cleanup; } if (flags & CFRAC_NEED_HGCD) { /* over-strict but fast _hcgd_ok(M, yn, yd) */ mp_size_t j; FLINT_ASSERT(yn_len >= yd_len); _fmpz_mat22_rmul_ui(M, m); for (j = 2 + _fmpz_mat22_bits(M)/FLINT_BITS; j < yn_len; j++) { mp_limb_t aa = yn_ptr[j]; mp_limb_t bb = j < yd_len ? yd_ptr[j] : 0; if (aa > bb && aa - bb > 1) goto its_ok; } _fmpz_mat22_rmul_inv_ui(M, m); goto cleanup; } if (flags & CFRAC_NEED_MATRIX) _fmpz_mat22_rmul_ui(M, m); its_ok: yn->_mp_size = yn_len; yd->_mp_size = yd_len; _fmpq_cfrac_list_append_ui(s, s_temp, written); FLINT_SWAP(mpz_ptr, xn, yn); FLINT_SWAP(mpz_ptr, xd, yd); goto again; cleanup: /* xn/xd are valid; make yn/yd valid */ yn->_mp_size = 0; yd->_mp_size = 0; *xa = PTR_TO_COEFF(xn); *xb = PTR_TO_COEFF(xd); *ya = PTR_TO_COEFF(yn); *yb = PTR_TO_COEFF(yd); _fmpz_demote_val(yb); _fmpz_demote_val(ya); _fmpz_demote_val(xb); _fmpz_demote_val(xa); return; } static void _lehmer_inexact(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, int needM, _fmpq_ball_t x, _fmpq_ball_t y) { mp_limb_t s_temp[2*FLINT_BITS]; slong written; unsigned int x_lzcnt; mpz_ptr xln, xld, xrn, xrd; mpz_ptr yln, yld, yrn, yrd; mp_size_t xln_len, xld_len, xrn_len, xrd_len; mp_size_t yln_len, yld_len, yrn_len, yrd_len; mp_ptr xln_ptr, xld_ptr, xrn_ptr, xrd_ptr; mp_ptr yln_ptr, yld_ptr, yrn_ptr, yrd_ptr; _ui_mat22_t m; mp_limb_t A0, A1, B0, B1; mp_size_t n, nl, nr; if (!COEFF_IS_MPZ(*x->left_num) || !COEFF_IS_MPZ(*x->left_den) || !COEFF_IS_MPZ(*x->right_num) || !COEFF_IS_MPZ(*x->right_den)) { return; } xln = COEFF_TO_PTR(*x->left_num); xld = COEFF_TO_PTR(*x->left_den); xrn = COEFF_TO_PTR(*x->right_num); xrd = COEFF_TO_PTR(*x->right_den); yln = _fmpz_promote(y->left_num); yld = _fmpz_promote(y->left_den); yrn = _fmpz_promote(y->right_num); yrd = _fmpz_promote(y->right_den); /* fit everything to max(xln_len) */ nl = xln->_mp_size; nr = xrn->_mp_size; n = FLINT_MAX(nl, nr); FLINT_MPZ_REALLOC(xln, n); FLINT_MPZ_REALLOC(xld, n); FLINT_MPZ_REALLOC(yln, n); FLINT_MPZ_REALLOC(yld, n); FLINT_MPZ_REALLOC(xrn, n); FLINT_MPZ_REALLOC(xrd, n); FLINT_MPZ_REALLOC(yrn, n); FLINT_MPZ_REALLOC(yrd, n); again: xln_len = xln->_mp_size; xld_len = xld->_mp_size; xrn_len = xrn->_mp_size; xrd_len = xrd->_mp_size; xln_ptr = xln->_mp_d; xld_ptr = xld->_mp_d; xrn_ptr = xrn->_mp_d; xrd_ptr = xrd->_mp_d; yln_ptr = yln->_mp_d; yld_ptr = yld->_mp_d; yrn_ptr = yrn->_mp_d; yrd_ptr = yrd->_mp_d; /* supposed xln > xld > 0 */ FLINT_ASSERT(xln_len >= xld_len); FLINT_ASSERT(xld_len > 0); /* supposed xrn > xrd > 0 */ FLINT_ASSERT(xrn_len >= xrd_len); FLINT_ASSERT(xrd_len > 0); FLINT_ASSERT(xln_ptr[xln_len - 1] != 0); FLINT_ASSERT(xld_ptr[xld_len - 1] != 0); FLINT_ASSERT(xrn_ptr[xrn_len - 1] != 0); FLINT_ASSERT(xrd_ptr[xrd_len - 1] != 0); nl = xln_len; nr = xrn_len; if (nl < 3 || nr < 3) goto cleanup; if (nl != xld_len && nl != xld_len + 1) goto cleanup; if (nl == xld_len + 1) xld_ptr[nl - 1] = 0; if (nr != xrd_len && nr != xrd_len + 1) goto cleanup; if (nr == xrd_len + 1) xrd_ptr[nr - 1] = 0; x_lzcnt = flint_clz(xln_ptr[nl - 1]); A1 = MPN_LEFT_SHIFT_HI(xln_ptr[nl - 1], xln_ptr[nl - 2], x_lzcnt); A0 = MPN_LEFT_SHIFT_HI(xln_ptr[nl - 2], xln_ptr[nl - 3], x_lzcnt); B1 = MPN_LEFT_SHIFT_HI(xld_ptr[nl - 1], xld_ptr[nl - 2], x_lzcnt); B0 = MPN_LEFT_SHIFT_HI(xld_ptr[nl - 2], xld_ptr[nl - 3], x_lzcnt); written = _uiui_hgcd(s_temp, A1, A0, B1, B0, m); if (written <= 0 || s->length + written > s->limit) goto cleanup; if (m->det == 1) { yln_len = flint_mpn_fmms1(yln_ptr, m->_22, xln_ptr, m->_12, xld_ptr, nl); if (yln_len <= 0) goto cleanup; yld_len = flint_mpn_fmms1(yld_ptr, m->_11, xld_ptr, m->_21, xln_ptr, nl); if (yld_len <= 0) goto cleanup; yrn_len = flint_mpn_fmms1(yrn_ptr, m->_22, xrn_ptr, m->_12, xrd_ptr, nr); if (yrn_len <= 0) goto cleanup; yrd_len = flint_mpn_fmms1(yrd_ptr, m->_11, xrd_ptr, m->_21, xrn_ptr, nr); if (yrd_len <= 0) goto cleanup; } else { yrn_len = flint_mpn_fmms1(yrn_ptr, m->_12, xld_ptr, m->_22, xln_ptr, nl); if (yrn_len <= 0) goto cleanup; yrd_len = flint_mpn_fmms1(yrd_ptr, m->_21, xln_ptr, m->_11, xld_ptr, nl); if (yrd_len <= 0) goto cleanup; yln_len = flint_mpn_fmms1(yln_ptr, m->_12, xrd_ptr, m->_22, xrn_ptr, nr); if (yln_len <= 0) goto cleanup; yld_len = flint_mpn_fmms1(yld_ptr, m->_21, xrn_ptr, m->_11, xrd_ptr, nr); if (yld_len <= 0) goto cleanup; } /* check yl > 1 */ if (yln_len <= yld_len) { if (yln_len != yld_len) goto cleanup; if (mpn_cmp(yln_ptr, yld_ptr, yln_len) <= 0) goto cleanup; } yln->_mp_size = yln_len; yld->_mp_size = yld_len; yrn->_mp_size = yrn_len; yrd->_mp_size = yrd_len; if (needM) _fmpz_mat22_rmul_ui(M, m); /* already checked that s will fit new terms */ _fmpq_cfrac_list_append_ui(s, s_temp, written); FLINT_SWAP(mpz_ptr, xln, yln); FLINT_SWAP(mpz_ptr, xld, yld); FLINT_SWAP(mpz_ptr, xrn, yrn); FLINT_SWAP(mpz_ptr, xrd, yrd); goto again; cleanup: /* x is valid; make y valid */ yln->_mp_size = 0; yld->_mp_size = 0; yrn->_mp_size = 0; yrd->_mp_size = 0; *x->left_num = PTR_TO_COEFF(xln); *x->left_den = PTR_TO_COEFF(xld); *x->right_num = PTR_TO_COEFF(xrn); *x->right_den = PTR_TO_COEFF(xrd); *y->left_num = PTR_TO_COEFF(yln); *y->left_den = PTR_TO_COEFF(yld); *y->right_num = PTR_TO_COEFF(yrn); *y->right_den = PTR_TO_COEFF(yrd); _fmpz_demote_val(y->left_num); _fmpz_demote_val(y->left_den); _fmpz_demote_val(y->right_num); _fmpz_demote_val(y->right_den); _fmpz_demote_val(x->left_num); _fmpz_demote_val(x->left_den); _fmpz_demote_val(x->right_num); _fmpz_demote_val(x->right_den); return; } static void _hgcd_step( _fmpz_mat22_t M, fmpz_t xa, fmpz_t xb, flint_bitcnt_t shift, _fmpz_mat22_t N, fmpz_t ya, fmpz_t yb) { fmpz_fdiv_r_2exp(xa, xa, shift); fmpz_fdiv_r_2exp(xb, xb, shift); if (M->det == 1) { fmpz_sub(xa, xa, M->_12); fmpz_sub(xb, xb, M->_21); fmpz_fdiv_r_2exp(xa, xa, shift); fmpz_fdiv_r_2exp(xb, xb, shift); fmpz_add(xa, xa, M->_12); fmpz_add(xb, xb, M->_21); } else { FLINT_ASSERT(M->det == -1); fmpz_sub(xa, xa, M->_22); fmpz_sub(xb, xb, M->_11); fmpz_fdiv_r_2exp(xa, xa, shift); fmpz_fdiv_r_2exp(xb, xb, shift); fmpz_add(xa, xa, M->_22); fmpz_add(xb, xb, M->_11); } fmpz_mul_2exp(ya, ya, shift); fmpz_mul_2exp(yb, yb, shift); _fmpz_mat22_addmul_inv_vec(ya, yb, N, xa, xb); fmpz_swap(xa, ya); fmpz_swap(xb, yb); _fmpz_mat22_rmul(M, N); } /* Supposing a > b > 0, generate terms valid for all real numbers in the open interval M^-1(a/(b+1), (a+1)/b). a/b = [[q1 1][1 0]] * ... * [[qn 1][1 0]](a'/b') The qi are written to s, and M is multiplied on the right. This is an in-place operation, so (M, xa/xb) is the input ball M^-1(a/(b+1), (a+1)/b) and output ball M^-1(a'/(b'+1), (a'+1)/b'). */ void _fmpq_hgcd(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, fmpz_t xa, fmpz_t xb) { flint_bitcnt_t k, km, shift; fmpz_t ya, yb; _fmpz_mat22_t N; #if FLINT_WANT_ASSERT fmpz_t xa_org, xb_org; fmpz_init_set(xa_org, xa); fmpz_init_set(xb_org, xb); #endif fmpz_init(ya); fmpz_init(yb); _fmpz_mat22_init(N); again: FLINT_ASSERT(_hgcd_ok(M, xa, xb)); if (s->length >= s->limit) goto cleanup; k = fmpz_bits(xa); km = _fmpz_mat22_bits(M); FLINT_ASSERT(k >= km); k -= km; if (k > 500*FLINT_BITS) goto split; if (k > 4*FLINT_BITS) goto lehmer; gauss: FLINT_ASSERT(s->length <= s->limit); FLINT_ASSERT(_hgcd_ok(M, xa, xb)); if (s->length >= s->limit) goto cleanup; fmpz_fdiv_qr(ya, yb, xa, xb); _fmpz_mat22_rmul_elem(M, ya); if (!_hgcd_ok(M, xb, yb)) { _fmpz_mat22_rmul_inv_elem(M, ya); goto cleanup; } fmpz_swap(xa, xb); fmpz_swap(xb, yb); _fmpq_cfrac_list_push_back(s, ya); goto again; lehmer: FLINT_ASSERT(s->length < s->limit); FLINT_ASSERT(_hgcd_ok(M, xa, xb)); _lehmer_exact(s, M, CFRAC_NEED_MATRIX | CFRAC_NEED_HGCD, xa, xb, ya, yb); goto gauss; split: shift = _hgcd_split(ya, yb, xa, xb, M, km + k/2); if (shift == 0) goto gauss; _fmpz_mat22_one(N); _fmpq_hgcd(s, N, ya, yb); if (_fmpz_mat22_is_one(N)) goto gauss; _hgcd_step(M, xa, xb, shift, N, ya, yb); FLINT_ASSERT(_hgcd_ok(M, xa, xb)); km = _fmpz_mat22_bits(M); shift = _hgcd_split(ya, yb, xa, xb, M, km + 1); if (shift == 0) goto gauss; _fmpz_mat22_one(N); _fmpq_hgcd(s, N, ya, yb); if (_fmpz_mat22_is_one(N)) goto gauss; _hgcd_step(M, xa, xb, shift, N, ya, yb); FLINT_ASSERT(_hgcd_ok(M, xa, xb)); goto again; cleanup: #if FLINT_WANT_ASSERT FLINT_ASSERT(_hgcd_ok(M, xa, xb)); fmpz_mul(ya, M->_11, xa); fmpz_addmul(ya, M->_12, xb); fmpz_mul(yb, M->_21, xa); fmpz_addmul(yb, M->_22, xb); FLINT_ASSERT(fmpz_equal(xa_org, ya)); FLINT_ASSERT(fmpz_equal(xb_org, yb)); fmpz_clear(xa_org); fmpz_clear(xb_org); #endif fmpz_clear(ya); fmpz_clear(yb); _fmpz_mat22_clear(N); FLINT_ASSERT(s->length <= s->limit); FLINT_ASSERT(_hgcd_ok(M, xa, xb)); FLINT_ASSERT(M->det == 1 || M->det == -1); return; } /* given a >= b > 0, return the smallest k with floor(a/2^k) = floor(b/2^k) */ static flint_bitcnt_t _fmpz_tail_bits(const fmpz_t a, const fmpz_t b) { flint_bitcnt_t k, j, max; max = k = fmpz_bits(a); FLINT_ASSERT(max >= fmpz_bits(b)); for (j = 0; j < max; j++) if (fmpz_tstbit(a, j) != fmpz_tstbit(b, j)) k = j + 1; return k; } /* generate terms valid for every number in the closed ball x > 1 */ void _fmpq_ball_get_cfrac(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, int needM, _fmpq_ball_t x) { flint_bitcnt_t k; fmpz_t q, r; _fmpq_ball_t y; _fmpz_mat22_t N; #if FLINT_WANT_ASSERT _fmpq_ball_t xorg; _fmpq_ball_init(xorg); xorg->exact = x->exact; fmpz_set(xorg->left_num, x->left_num); fmpz_set(xorg->left_den, x->left_den); fmpz_set(xorg->right_num, x->right_num); fmpz_set(xorg->right_den, x->right_den); #endif fmpz_init(q); fmpz_init(r); _fmpq_ball_init(y); _fmpz_mat22_init(N); _fmpz_mat22_one(M); if (!x->exact) { if (fmpz_equal(x->left_num, x->right_num)) { k = _fmpz_tail_bits(x->left_den, x->right_den); goto chop; } if (fmpz_equal(x->left_den, x->right_den)) { k = _fmpz_tail_bits(x->right_num, x->left_num); goto chop; } } again: FLINT_ASSERT(s->length <= s->limit); FLINT_ASSERT(_fmpq_ball_is_ordered(x)); FLINT_ASSERT(_fmpq_ball_gt_one(x)); FLINT_ASSERT(M->det == 1 || M->det == -1); if (s->length >= s->limit) goto cleanup; k = fmpz_bits(x->left_num); if (k > 500*FLINT_BITS) goto split; if (k > 4*FLINT_BITS) goto lehmer; gauss: FLINT_ASSERT(s->length <= s->limit); FLINT_ASSERT(_fmpq_ball_is_ordered(x)); FLINT_ASSERT(_fmpq_ball_gt_one(x)); FLINT_ASSERT(M->det == 1 || M->det == -1); if (s->length >= s->limit) goto cleanup; fmpz_fdiv_qr(q, r, x->left_num, x->left_den); _fmpq_ball_apply_mat22_inv_elem2(y, q, r, x); if (!_fmpq_ball_gt_one(y)) goto cleanup; _fmpq_ball_swap(x, y); if (needM) _fmpz_mat22_rmul_elem(M, q); _fmpq_cfrac_list_push_back(s, q); goto again; lehmer: FLINT_ASSERT(s->length < s->limit); FLINT_ASSERT(_fmpq_ball_is_ordered(x)); FLINT_ASSERT(_fmpq_ball_gt_one(x)); FLINT_ASSERT(M->det == 1 || M->det == -1); _fmpz_mat22_one(N); if (x->exact) { _lehmer_exact(s, N, needM ? CFRAC_NEED_MATRIX : 0, x->left_num, x->left_den, y->left_num, y->left_den); } else { _lehmer_inexact(s, N, needM, x, y); } if (needM && !_fmpz_mat22_is_one(N)) _fmpz_mat22_rmul(M, N); goto gauss; split: FLINT_ASSERT(s->length < s->limit); FLINT_ASSERT(_fmpq_ball_is_ordered(x)); FLINT_ASSERT(_fmpq_ball_gt_one(x)); FLINT_ASSERT(M->det == 1 || M->det == -1); k = k/2; if (x->exact) { /* get a ball y containing x */ fmpz_fdiv_q_2exp(y->left_num, x->left_num, k); fmpz_fdiv_q_2exp(y->left_den, x->left_den, k); if (fmpz_sgn(y->left_den) <= 0 || fmpz_cmp(y->left_num, y->left_den) <= 0) goto gauss; _fmpz_mat22_one(N); _fmpq_hgcd(s, N, y->left_num, y->left_den); if (_fmpz_mat22_is_one(N)) goto gauss; /* optimized form of _fmpq_ball_apply_mat22_inv(y, N, x) _fmpq_ball_swap(x, y) */ fmpz_fdiv_r_2exp(q, x->left_num, k); fmpz_fdiv_r_2exp(r, x->left_den, k); fmpz_mul_2exp(x->left_num, y->left_num, k); fmpz_mul_2exp(x->left_den, y->left_den, k); _fmpz_mat22_addmul_inv_vec(x->left_num, x->left_den, N, q, r); } else { /* get a ball y containing x */ fmpz_fdiv_q_2exp(y->left_num, x->left_num, k); fmpz_fdiv_q_2exp(y->left_den, x->left_den, k); fmpz_add_ui(y->left_den, y->left_den, 1); fmpz_fdiv_q_2exp(y->right_num, x->right_num, k); fmpz_fdiv_q_2exp(y->right_den, x->right_den, k); fmpz_add_ui(y->right_num, y->right_num, 1); y->exact = 0; if (!_fmpq_ball_gt_one(y)) goto gauss; _fmpq_ball_get_cfrac(s, N, 1, y); if (_fmpz_mat22_is_one(N)) goto gauss; /* optimized form of _fmpq_ball_apply_mat22_inv(y, N, x) _fmpq_ball_swap(x, y) */ fmpz_one(r); fmpz_mul_2exp(r, r, k); fmpz_fdiv_r_2exp(q, x->left_den, k); fmpz_sub(x->left_den, q, r); fmpz_fdiv_r_2exp(x->left_num, x->left_num, k); fmpz_fdiv_r_2exp(q, x->right_num, k); fmpz_sub(x->right_num, q, r); fmpz_fdiv_r_2exp(x->right_den, x->right_den, k); fmpz_mul_2exp(y->left_num, y->left_num, k); fmpz_mul_2exp(y->left_den, y->left_den, k); fmpz_mul_2exp(y->right_num, y->right_num, k); fmpz_mul_2exp(y->right_den, y->right_den, k); if (N->det == -1) { fmpz_swap(x->right_num, x->left_num); fmpz_swap(x->right_den, x->left_den); } _fmpz_mat22_addmul_inv_mat(y->left_num, y->right_num, y->left_den, y->right_den, N, x->left_num, x->right_num, x->left_den, x->right_den); fmpz_swap(x->left_num, y->left_num); fmpz_swap(x->left_den, y->left_den); fmpz_swap(x->right_num, y->right_num); fmpz_swap(x->right_den, y->right_den); } FLINT_ASSERT(_fmpq_ball_gt_one(x)); if (!needM) goto again; _fmpz_mat22_rmul(M, N); _fmpq_ball_get_cfrac(s, N, 1, x); _fmpz_mat22_rmul(M, N); goto cleanup; chop: FLINT_ASSERT(s->length <= s->limit); FLINT_ASSERT(_fmpq_ball_is_ordered(x)); FLINT_ASSERT(_fmpq_ball_gt_one(x)); FLINT_ASSERT(_fmpz_mat22_is_one(M)); fmpz_fdiv_q_2exp(q, x->left_num, k); fmpz_fdiv_q_2exp(r, x->left_den, k); if (fmpz_sgn(r) <= 0 || fmpz_cmp(q, r) <= 0) goto again; _fmpz_mat22_one(M); _fmpq_hgcd(s, M, q, r); if (_fmpz_mat22_is_one(M)) goto again; fmpz_fdiv_r_2exp(y->left_num, x->left_num, k); fmpz_fdiv_r_2exp(y->left_den, x->left_den, k); fmpz_fdiv_r_2exp(y->right_num, x->right_num, k); fmpz_fdiv_r_2exp(y->right_den, x->right_den, k); fmpz_mul_2exp(x->left_num, q, k); fmpz_mul_2exp(x->left_den, r, k); fmpz_mul_2exp(x->right_num, q, k); fmpz_mul_2exp(x->right_den, r, k); if (M->det == 1) { fmpz_addmul(x->left_num, M->_22, y->left_num); fmpz_submul(x->left_num, M->_12, y->left_den); fmpz_addmul(x->left_den, M->_11, y->left_den); fmpz_submul(x->left_den, M->_21, y->left_num); fmpz_addmul(x->right_num, M->_22, y->right_num); fmpz_submul(x->right_num, M->_12, y->right_den); fmpz_addmul(x->right_den, M->_11, y->right_den); fmpz_submul(x->right_den, M->_21, y->right_num); } else { FLINT_ASSERT(M->det == -1); fmpz_addmul(x->left_num, M->_12, y->right_den); fmpz_submul(x->left_num, M->_22, y->right_num); fmpz_addmul(x->left_den, M->_21, y->right_num); fmpz_submul(x->left_den, M->_11, y->right_den); fmpz_addmul(x->right_num, M->_12, y->left_den); fmpz_submul(x->right_num, M->_22, y->left_num); fmpz_addmul(x->right_den, M->_21, y->left_num); fmpz_submul(x->right_den, M->_11, y->left_den); } goto gauss; cleanup: #if FLINT_WANT_ASSERT FLINT_ASSERT(!needM || (_fmpq_ball_apply_mat22_inv(y, M, xorg), _fmpq_ball_equal(y, x))); _fmpq_ball_clear(xorg); #endif fmpz_clear(q); fmpz_clear(r); _fmpq_ball_clear(y); _fmpz_mat22_clear(N); FLINT_ASSERT(s->length <= s->limit); FLINT_ASSERT(_fmpq_ball_gt_one(x)); FLINT_ASSERT(M->det == 1 || M->det == -1); return; } flint-3.1.3/src/fmpq/get_d.c000066400000000000000000000010741461254215100156150ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" double fmpq_get_d(const fmpq_t a) { double d; mpq_t z; flint_mpq_init_set_readonly(z, a); d = mpq_get_d(z); flint_mpq_clear_readonly(z); return d; } flint-3.1.3/src/fmpq/get_mpfr.c000066400000000000000000000021441461254215100163350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpfr.h" #include "fmpq.h" int fmpq_get_mpfr(mpfr_t r, const fmpq_t x, mpfr_rnd_t rnd) { __mpq_struct mpq; fmpz p, q; mp_limb_t pp, qq; p = *fmpq_numref(x); q = *fmpq_denref(x); if (p == 0) return mpfr_set_ui(r, 0, rnd); if (COEFF_IS_MPZ(p)) mpq._mp_num = *COEFF_TO_PTR(p); else { pp = FLINT_ABS(p); mpq._mp_num._mp_alloc = 1; mpq._mp_num._mp_size = (p < 0) ? -1 : 1; mpq._mp_num._mp_d = &pp; } if (COEFF_IS_MPZ(q)) mpq._mp_den = *COEFF_TO_PTR(q); else { qq = q; mpq._mp_den._mp_alloc = 1; mpq._mp_den._mp_size = 1; mpq._mp_den._mp_d = &qq; } return mpfr_set_q(r, &mpq, rnd); } flint-3.1.3/src/fmpq/get_mpz_frac.c000066400000000000000000000010361461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq.h" void fmpq_get_mpz_frac(mpz_t a, mpz_t b, fmpq_t c) { fmpz_get_mpz(a, fmpq_numref(c)); fmpz_get_mpz(b, fmpq_denref(c)); } flint-3.1.3/src/fmpq/get_str.c000066400000000000000000000021011461254215100161720ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" char * _fmpq_get_str(char * str, int b, const fmpz_t num, const fmpz_t den) { char *s; if (str == NULL) { str = flint_malloc(fmpz_sizeinbase(num, b) + fmpz_sizeinbase(den, b) + 3); if (str == NULL) { flint_throw(FLINT_ERROR, "Exception (_fmpq_get_str). Not enough memory.\n"); } } fmpz_get_str(str, b, num); if (!fmpz_is_one(den)) { s = str; while (*s != '\0') s++; *s = '/'; s++; fmpz_get_str(s, b, den); } return str; } char * fmpq_get_str(char * str, int b, const fmpq_t f) { return _fmpq_get_str(str, b, fmpq_numref(f), fmpq_denref(f)); } flint-3.1.3/src/fmpq/harmonic_ui.c000066400000000000000000000154511461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2011, 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #if FLINT_BITS == 64 #define FMPQ_HARMONIC_UI_TAB_SIZE 47 #else #define FMPQ_HARMONIC_UI_TAB_SIZE 25 #endif static const mp_limb_t fmpq_harmonic_ui_tab_num[] = { 0, 1, 3, 11, 25, 137, 49, 363, 761, 7129, 7381, 83711, 86021, 1145993, 1171733, 1195757, 2436559, 42142223, 14274301, 275295799, 55835135, 18858053, 19093197, 444316699, 1347822955, #if FLINT64 UWORD(34052522467), UWORD(34395742267), UWORD(312536252003), UWORD(315404588903), UWORD(9227046511387), UWORD(9304682830147), UWORD(290774257297357), UWORD(586061125622639), UWORD(53676090078349), UWORD(54062195834749), UWORD(54437269998109), UWORD(54801925434709), UWORD(2040798836801833), UWORD(2053580969474233), UWORD(2066035355155033), UWORD(2078178381193813), UWORD(85691034670497533), UWORD(12309312989335019), UWORD(532145396070491417), UWORD(5884182435213075787), UWORD(5914085889685464427), UWORD(5943339269060627227), #endif }; const mp_limb_t fmpq_harmonic_ui_tab_den[] = { 1, 1, 2, 6, 12, 60, 20, 140, 280, 2520, 2520, 27720, 27720, 360360, 360360, 360360, 720720, 12252240, 4084080, 77597520, 15519504, 5173168, 5173168, 118982864, 356948592, #if FLINT64 UWORD(8923714800), UWORD(8923714800), UWORD(80313433200), UWORD(80313433200), UWORD(2329089562800), UWORD(2329089562800), UWORD(72201776446800), UWORD(144403552893600), UWORD(13127595717600), UWORD(13127595717600), UWORD(13127595717600), UWORD(13127595717600), UWORD(485721041551200), UWORD(485721041551200), UWORD(485721041551200), UWORD(485721041551200), UWORD(19914562703599200), UWORD(2844937529085600), UWORD(122332313750680800), UWORD(1345655451257488800), UWORD(1345655451257488800), UWORD(1345655451257488800), #endif }; /* The basic approach to compute H(n) quickly is to use a balanced sum. To save some more time, we note that we only have to sum over the odd terms since H(n) = H(floor(n/2))/2 + H_odd(n). Recursive application of this formula results in a geometric series for the weight of each odd term 1/k: n/2 < k <= n : weight 1 n/4 < k <= n/2 : weight 3/2 n/8 < k <= n/4 : weight 7/4 n/16 < k <= n/8 : weight 15/8 ... n/2^d < k <= n/2^(d-1) : weight (2^d-1)/2^(d-1) Although not necessary, the implementation is simplified by always splitting the interval exactly in half, since we then just have to increment d on every subinterval that starts with a = 1. Below a threshold, we fall back to direct summation of the odd fractions. As a final optimization, we accumulate word-size partial sums in single limbs in the basecase summation. A basic Python implementation: def harmonic_odd_direct(a, b, n, d): t, v = 0, 1 if a == 1: for k in range(b-1-(b%2), 0, -2): while k <= (n >> d): d += 1 r = 2**(d-1)*k t, v = ((2**d-1)*v + r*t), r*v return t, v else: a += (a % 2 == 0) for k in range(a, b, 2): t, v = (v+k*t), k*v return (2**d - 1) * t, 2**(d-1) * v def harmonic_odd_balanced(a, b, n, d): if b - a < 50: return harmonic_odd_direct(a, b, n, d) m = (a+b) // 2 t, v = harmonic_odd_balanced(a, m, n, d + (a==1)) u, w = harmonic_odd_balanced(m, b, n, d) return (t*w + u*v), v*w def harmonic(n): return harmonic_odd_balanced(1, n+1, n, 1) */ static void harmonic_odd_direct(fmpz_t P, fmpz_t Q, ulong a, ulong b, ulong n, int d) { mp_limb_t p, q, r, s, t, u, v, w = 0; slong k; fmpz_zero(P); fmpz_one(Q); p = 0; q = 1; if (a == 1) { for (k = b - 1 - (b % 2); k > 0; k -= 2) { while (k <= (n >> d)) d++; r = (UWORD(1) << d) - UWORD(1); s = ((mp_limb_t) k) << (d-1); umul_ppmm(t, u, p, s); umul_ppmm(v, w, q, r); if (t == 0 && v == 0) { add_ssaaaa(t, u, t, u, v, w); if (t == 0) umul_ppmm(v, w, q, s); } if (t == 0 && v == 0) { p = u; q = w; } else { fmpz_mul_ui(P, P, q); fmpz_addmul_ui(P, Q, p); fmpz_mul_ui(Q, Q, q); p = r; q = s; } } if (p != 0) { fmpz_mul_ui(P, P, q); fmpz_addmul_ui(P, Q, p); fmpz_mul_ui(Q, Q, q); } } else { a += (a % 2 == 0); for (k = a; k < b; k += 2) { umul_ppmm(t, u, p, k); v = 0; if (t == 0) { add_ssaaaa(t, u, t, u, 0, q); if (t == 0) umul_ppmm(v, w, q, k); } if (t == 0 && v == 0) { p = u; q = w; } else { fmpz_mul_ui(P, P, q); fmpz_addmul_ui(P, Q, p); fmpz_mul_ui(Q, Q, q); p = 1; q = k; } } if (p != 0) { fmpz_mul_ui(P, P, q); fmpz_addmul_ui(P, Q, p); fmpz_mul_ui(Q, Q, q); } fmpz_mul_ui(P, P, (UWORD(1) << d) - UWORD(1)); fmpz_mul_ui(Q, Q, UWORD(1) << (d - 1)); } } static void harmonic_odd_balanced(fmpz_t P, fmpz_t Q, ulong a, ulong b, ulong n, int d) { if (b - a < 50) { harmonic_odd_direct(P, Q, a, b, n, d); } else { ulong m; fmpz_t R, S; fmpz_init(R); fmpz_init(S); m = a + (b - a) / 2; harmonic_odd_balanced(P, Q, a, m, n, d + (a==1)); harmonic_odd_balanced(R, S, m, b, n, d); fmpz_mul(P, P, S); fmpz_addmul(P, Q, R); fmpz_mul(Q, Q, S); fmpz_clear(R); fmpz_clear(S); } } void _fmpq_harmonic_ui(fmpz_t num, fmpz_t den, ulong n) { if (n < FMPQ_HARMONIC_UI_TAB_SIZE) { fmpz_set_ui(num, fmpq_harmonic_ui_tab_num[n]); fmpz_set_ui(den, fmpq_harmonic_ui_tab_den[n]); } else { /* overflow */ if ((slong) n < 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); harmonic_odd_balanced(num, den, 1, n + 1, n, 1); _fmpq_canonicalise(num, den); } } void fmpq_harmonic_ui(fmpq_t x, ulong n) { _fmpq_harmonic_ui(fmpq_numref(x), fmpq_denref(x), n); } flint-3.1.3/src/fmpq/height.c000066400000000000000000000011341461254215100160000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_height(fmpz_t height, const fmpq_t x) { if (fmpz_cmpabs(fmpq_numref(x), fmpq_denref(x)) < 0) fmpz_abs(height, fmpq_denref(x)); else fmpz_abs(height, fmpq_numref(x)); } flint-3.1.3/src/fmpq/height_bits.c000066400000000000000000000011031461254215100170150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" flint_bitcnt_t fmpq_height_bits(const fmpq_t x) { flint_bitcnt_t a, b; a = fmpz_bits(fmpq_numref(x)); b = fmpz_bits(fmpq_denref(x)); return FLINT_MAX(a, b); } flint-3.1.3/src/fmpq/init_set_readonly.c000066400000000000000000000011021461254215100202360ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_init_set_readonly(fmpq_t f, const mpq_t z) { fmpz_init_set_readonly(fmpq_numref(f), mpq_numref(z)); fmpz_init_set_readonly(fmpq_denref(f), mpq_denref(z)); } flint-3.1.3/src/fmpq/inlines.c000066400000000000000000000015761461254215100162030ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPQ_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpq.h" void fmpq_numerator(fmpz_t n, const fmpq_t q) { fmpz_set(n, fmpq_numref(q)); } void fmpq_denominator(fmpz_t n, const fmpq_t q) { fmpz_set(n, fmpq_denref(q)); } fmpz * fmpq_numerator_ptr(fmpq_t q) { return fmpq_numref(q); } fmpz * fmpq_denominator_ptr(fmpq_t q) { return fmpq_denref(q); } int fmpq_equal_fmpz(fmpq_t q, fmpz_t n) { return fmpz_equal(fmpq_numref(q), n) && q->den == WORD(1); } flint-3.1.3/src/fmpq/inv.c000066400000000000000000000013311461254215100153230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_inv(fmpq_t dest, const fmpq_t src) { fmpz tmp; if (dest != src) { fmpq_set(dest, src); } tmp = dest->num; dest->num = dest->den; dest->den = tmp; if (fmpz_sgn(&dest->den) < 0) { fmpz_neg(&dest->den, &dest->den); fmpz_neg(&dest->num, &dest->num); } } flint-3.1.3/src/fmpq/io.c000066400000000000000000000031211461254215100151350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" /* printing *******************************************************************/ /* Recall the return value conventions for fputc (of type int) ``If there are no errors, the same character that has been written is returned. If an error occurs, EOF is returned and the error indicator is set'' where the EOF macro expands to a negative int, and flint_fprintf (of type int) ``On success, the total number of characters written is returned. On failure, a negative number is returned.'' */ int _fmpq_fprint(FILE * file, const fmpz_t num, const fmpz_t den) { if (fmpz_is_one(den)) { return fmpz_fprint(file, num); } else { int r; r = fmpz_fprint(file, num); if (r > 0) { r = fputc('/', file); if (r > 0) r = fmpz_fprint(file, den); } return r; } } int fmpq_fprint(FILE * file, const fmpq_t x) { return _fmpq_fprint(file, &x->num, &x->den); } int _fmpq_print(const fmpz_t num, const fmpz_t den) { return _fmpq_fprint(stdout, num, den); } int fmpq_print(const fmpq_t x) { return fmpq_fprint(stdout, x); } flint-3.1.3/src/fmpq/is_canonical.c000066400000000000000000000015111461254215100171510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" int _fmpq_is_canonical(const fmpz_t num, const fmpz_t den) { fmpz_t u; int result; if (fmpz_is_one(den)) return 1; if (fmpz_sgn(den) <= 0) return 0; if (fmpz_is_zero(num)) return fmpz_is_one(den); fmpz_init(u); fmpz_gcd(u, num, den); result = fmpz_is_one(u); fmpz_clear(u); return result; } int fmpq_is_canonical(const fmpq_t x) { return _fmpq_is_canonical(fmpq_numref(x), fmpq_denref(x)); } flint-3.1.3/src/fmpq/mat22.c000066400000000000000000000120771461254215100154650ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_mat.h" void _fmpz_mat22_init(_fmpz_mat22_t M) { fmpz_init(M->_11); fmpz_init(M->_12); fmpz_init(M->_21); fmpz_init(M->_22); M->det = 0; } void _fmpz_mat22_clear(_fmpz_mat22_t M) { fmpz_clear(M->_11); fmpz_clear(M->_12); fmpz_clear(M->_21); fmpz_clear(M->_22); } void _fmpz_mat22_one(_fmpz_mat22_t M) { fmpz_one(M->_11); fmpz_zero(M->_12); fmpz_zero(M->_21); fmpz_one(M->_22); M->det = 1; } int _fmpz_mat22_is_one(_fmpz_mat22_t M) { return fmpz_is_one(M->_11) && fmpz_is_zero(M->_12) && fmpz_is_zero(M->_21) && fmpz_is_one(M->_22); } flint_bitcnt_t _fmpz_mat22_bits(const _fmpz_mat22_t N) { flint_bitcnt_t b = fmpz_bits(N->_11); flint_bitcnt_t b1 = fmpz_bits(N->_12); flint_bitcnt_t b2 = fmpz_bits(N->_21); flint_bitcnt_t b3 = fmpz_bits(N->_22); b = FLINT_MAX(b, b1); b = FLINT_MAX(b, b2); b = FLINT_MAX(b, b3); return b; } /* M = M.N */ void _fmpz_mat22_rmul(_fmpz_mat22_t M, const _fmpz_mat22_t N) { fmpz_t a, b, c, d; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_mul(a, M->_11, N->_11); fmpz_addmul(a, M->_12, N->_21); fmpz_mul(b, M->_11, N->_12); fmpz_addmul(b, M->_12, N->_22); fmpz_mul(c, M->_21, N->_11); fmpz_addmul(c, M->_22, N->_21); fmpz_mul(d, M->_21, N->_12); fmpz_addmul(d, M->_22, N->_22); fmpz_swap(M->_11, a); fmpz_swap(M->_12, b); fmpz_swap(M->_21, c); fmpz_swap(M->_22, d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); M->det *= N->det; } /* (ya, yb) += N^-1*(xa, xb). xa and xb may be clobbered */ void _fmpz_mat22_addmul_inv_vec(fmpz_t ya, fmpz_t yb, _fmpz_mat22_t N, fmpz_t xa, fmpz_t xb) { if (N->det == 1) { fmpz_addmul(ya, N->_22, xa); fmpz_submul(ya, N->_12, xb); fmpz_addmul(yb, N->_11, xb); fmpz_submul(yb, N->_21, xa); } else { FLINT_ASSERT(N->det == -1); fmpz_addmul(ya, N->_12, xb); fmpz_submul(ya, N->_22, xa); fmpz_addmul(yb, N->_21, xa); fmpz_submul(yb, N->_11, xb); } } /* A += N^-1*B */ void _fmpz_mat22_addmul_inv_mat(fmpz_t A11, fmpz_t A12, fmpz_t A21, fmpz_t A22, _fmpz_mat22_t N, fmpz_t B11, fmpz_t B12, fmpz_t B21, fmpz_t B22) { _fmpz_mat22_addmul_inv_vec(A11, A21, N, B11, B21); _fmpz_mat22_addmul_inv_vec(A12, A22, N, B12, B22); } /* M = M*N */ void _fmpz_mat22_rmul_ui(_fmpz_mat22_t M, const _ui_mat22_t N) { fmpz_t a; fmpz_init(a); fmpz_mul_ui(a, M->_11, N->_11); fmpz_addmul_ui(a, M->_12, N->_21); fmpz_mul_ui(M->_12, M->_12, N->_22); fmpz_addmul_ui(M->_12, M->_11, N->_12); fmpz_swap(M->_11, a); fmpz_mul_ui(a, M->_21, N->_11); fmpz_addmul_ui(a, M->_22, N->_21); fmpz_mul_ui(M->_22, M->_22, N->_22); fmpz_addmul_ui(M->_22, M->_21, N->_12); fmpz_swap(M->_21, a); M->det *= N->det; fmpz_clear(a); } /* M = M*N^-1 */ void _fmpz_mat22_rmul_inv_ui(_fmpz_mat22_t M, const _ui_mat22_t N) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); if (N->det == 1) { fmpz_mul_ui(a, M->_11, N->_22); fmpz_submul_ui(a, M->_12, N->_21); fmpz_mul_ui(b, M->_12, N->_11); fmpz_submul_ui(b, M->_11, N->_12); fmpz_swap(M->_11, a); fmpz_swap(M->_12, b); fmpz_mul_ui(a, M->_21, N->_22); fmpz_submul_ui(a, M->_22, N->_21); fmpz_mul_ui(b, M->_22, N->_11); fmpz_submul_ui(b, M->_21, N->_12); } else { FLINT_ASSERT(N->det == -1); fmpz_mul_ui(a, M->_12, N->_21); fmpz_submul_ui(a, M->_11, N->_22); fmpz_mul_ui(b, M->_11, N->_12); fmpz_submul_ui(b, M->_12, N->_11); fmpz_swap(M->_11, a); fmpz_swap(M->_12, b); fmpz_mul_ui(a, M->_22, N->_21); fmpz_submul_ui(a, M->_21, N->_22); fmpz_mul_ui(b, M->_21, N->_12); fmpz_submul_ui(b, M->_22, N->_11); } fmpz_swap(M->_21, a); fmpz_swap(M->_22, b); M->det *= N->det; fmpz_clear(a); fmpz_clear(b); } /* M = M*[q 1; 1 0] */ void _fmpz_mat22_rmul_elem(_fmpz_mat22_t M, const fmpz_t q) { fmpz_addmul(M->_12, M->_11, q); fmpz_addmul(M->_22, M->_21, q); fmpz_swap(M->_11, M->_12); fmpz_swap(M->_21, M->_22); M->det *= -1; } /* M = M*[q 1; 1 0]^-1 = M*[0 1; 1 -q] */ void _fmpz_mat22_rmul_inv_elem(_fmpz_mat22_t M, const fmpz_t q) { fmpz_submul(M->_11, M->_12, q); fmpz_submul(M->_21, M->_22, q); fmpz_swap(M->_11, M->_12); fmpz_swap(M->_21, M->_22); M->det *= -1; } /* M = [q 1; 1 0]*M */ void _fmpz_mat22_lmul_elem(_fmpz_mat22_t M, const fmpz_t q) { fmpz_addmul(M->_21, M->_11, q); fmpz_addmul(M->_22, M->_12, q); fmpz_swap(M->_11, M->_21); fmpz_swap(M->_12, M->_22); M->det *= -1; } flint-3.1.3/src/fmpq/mod_fmpz.c000066400000000000000000000014661461254215100163530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" int _fmpq_mod_fmpz(fmpz_t res, const fmpz_t num, const fmpz_t den, const fmpz_t mod) { int result; fmpz_t tmp; fmpz_init(tmp); result = fmpz_invmod(tmp, den, mod); fmpz_mul(tmp, tmp, num); fmpz_mod(res, tmp, mod); fmpz_clear(tmp); return result; } int fmpq_mod_fmpz(fmpz_t res, const fmpq_t x, const fmpz_t mod) { return _fmpq_mod_fmpz(res, fmpq_numref(x), fmpq_denref(x), mod); } flint-3.1.3/src/fmpq/mpq_clear_readonly.c000066400000000000000000000010301461254215100203630ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void flint_mpq_clear_readonly(mpq_t z) { flint_mpz_clear_readonly(mpq_numref(z)); flint_mpz_clear_readonly(mpq_denref(z)); } flint-3.1.3/src/fmpq/mpq_init_set_readonly.c000066400000000000000000000011211461254215100211140ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void flint_mpq_init_set_readonly(mpq_t z, const fmpq_t f) { flint_mpz_init_set_readonly(mpq_numref(z), fmpq_numref(f)); flint_mpz_init_set_readonly(mpq_denref(z), fmpq_denref(f)); } flint-3.1.3/src/fmpq/mul.c000066400000000000000000000144601461254215100153330ustar00rootroot00000000000000/* Copyright (C) 2011, 2020 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpq.h" static ulong _fmpz_gcd_ui(const fmpz_t g, ulong h) { if (!COEFF_IS_MPZ(*g)) return n_gcd(FLINT_ABS(*g), h); else return n_gcd(flint_mpz_fdiv_ui(COEFF_TO_PTR(*g), h), h); } void _fmpq_mul_small(fmpz_t rnum, fmpz_t rden, slong op1num, ulong op1den, slong op2num, ulong op2den) { mp_limb_t hi, lo, denhi, denlo; int neg; if (op1num == 0 || op2num == 0) { fmpz_zero(rnum); fmpz_one(rden); return; } neg = 0; if (op1num < 0) { op1num = -op1num; neg = 1; } if (op2num < 0) { op2num = -op2num; neg = !neg; } if (op1den == op2den) { umul_ppmm(hi, lo, op1num, op2num); umul_ppmm(denhi, denlo, op1den, op2den); } else if (op1den == 1) { ulong t, x; t = n_gcd(op1num, op2den); x = op1num / t; t = op2den / t; umul_ppmm(hi, lo, x, op2num); umul_ppmm(denhi, denlo, op1den, t); } else if (op2den == 1) { ulong t, x; t = n_gcd(op2num, op1den); x = op2num / t; t = op1den / t; umul_ppmm(hi, lo, x, op1num); umul_ppmm(denhi, denlo, op2den, t); } else { ulong t, u, x, y; t = n_gcd(op1num, op2den); u = n_gcd(op1den, op2num); x = op1num / t; y = op2num / u; umul_ppmm(hi, lo, x, y); x = op1den / u; y = op2den / t; umul_ppmm(denhi, denlo, x, y); } if (neg) fmpz_neg_uiui(rnum, hi, lo); else fmpz_set_uiui(rnum, hi, lo); fmpz_set_uiui(rden, denhi, denlo); } void _fmpq_mul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) { if (!COEFF_IS_MPZ(*op1num) && !COEFF_IS_MPZ(*op1den) && !COEFF_IS_MPZ(*op2num) && !COEFF_IS_MPZ(*op2den)) { _fmpq_mul_small(rnum, rden, *op1num, *op1den, *op2num, *op2den); return; } /* Common special cases: squaring, same denominator (e.g. both integers) */ if (((op1num == op2num) && (op1den == op2den)) || fmpz_equal(op1den, op2den)) { fmpz_mul(rnum, op1num, op2num); fmpz_mul(rden, op1den, op2den); } /* Exactly one argument is an integer */ else if (fmpz_is_one(op1den)) { fmpz_t t, x; fmpz_init(t); fmpz_init(x); fmpz_gcd(t, op1num, op2den); fmpz_divexact(x, op1num, t); fmpz_mul(rnum, x, op2num); fmpz_divexact(t, op2den, t); fmpz_mul(rden, op1den, t); fmpz_clear(t); fmpz_clear(x); } else if (fmpz_is_one(op2den)) { fmpz_t t, x; fmpz_init(t); fmpz_init(x); fmpz_gcd(t, op2num, op1den); fmpz_divexact(x, op2num, t); fmpz_mul(rnum, x, op1num); fmpz_divexact(t, op1den, t); fmpz_mul(rden, op2den, t); fmpz_clear(t); fmpz_clear(x); } else { fmpz_t t, u, x, y; fmpz_init(t); fmpz_init(u); fmpz_init(x); fmpz_init(y); fmpz_gcd(t, op1num, op2den); fmpz_gcd(u, op1den, op2num); fmpz_divexact(x, op1num, t); fmpz_divexact(y, op2num, u); fmpz_mul(rnum, x, y); fmpz_divexact(x, op1den, u); fmpz_divexact(y, op2den, t); fmpz_mul(rden, x, y); fmpz_clear(t); fmpz_clear(u); fmpz_clear(x); fmpz_clear(y); } } void fmpq_mul(fmpq_t res, const fmpq_t op1, const fmpq_t op2) { _fmpq_mul(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } void fmpq_mul_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x) { fmpz_t y; *y = 1; _fmpq_mul(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op), fmpq_denref(op), x, y); } void _fmpq_mul_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r) { if (r == 0 || fmpz_is_zero(p)) { fmpz_zero(rnum); fmpz_one(rden); } else if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && r <= COEFF_MAX) { _fmpq_mul_small(rnum, rden, *p, *q, r, 1); } else if (r == 1) { fmpz_set(rnum, p); fmpz_set(rden, q); } else { ulong g = _fmpz_gcd_ui(q, r); if (g == 1) { fmpz_set(rden, q); fmpz_mul_ui(rnum, p, r); } else { fmpz_mul_ui(rnum, p, r / g); fmpz_divexact_ui(rden, q, g); } } } void fmpq_mul_ui(fmpq_t res, const fmpq_t op1, ulong c) { _fmpq_mul_ui(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } void _fmpq_mul_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r) { if (r == 0 || fmpz_is_zero(p)) { fmpz_zero(rnum); fmpz_one(rden); } else if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && r >= COEFF_MIN && r <= COEFF_MAX) { _fmpq_mul_small(rnum, rden, *p, *q, r, 1); } else if (r == 1) { fmpz_set(rnum, p); fmpz_set(rden, q); } else if (r == -WORD(1)) { fmpz_neg(rnum, p); fmpz_set(rden, q); } else { ulong a, g; a = FLINT_ABS(r); g = _fmpz_gcd_ui(q, a); if (g == 1) { fmpz_set(rden, q); fmpz_mul_si(rnum, p, r); } else { /* not using fmpz_mul_si(...) because of the special case g = -WORD_MIN */ fmpz_mul_ui(rnum, p, a / g); if (r < 0) fmpz_neg(rnum, rnum); fmpz_divexact_ui(rden, q, g); } } } void fmpq_mul_si(fmpq_t res, const fmpq_t op1, slong c) { _fmpq_mul_si(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } flint-3.1.3/src/fmpq/mul_2exp.c000066400000000000000000000017011461254215100162630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_mul_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp) { if (fmpq_is_zero(x) || exp == 0) { fmpq_set(res, x); } else { flint_bitcnt_t v = fmpz_val2(fmpq_denref(x)); if (exp <= v) { fmpz_set(fmpq_numref(res), fmpq_numref(x)); fmpz_fdiv_q_2exp(fmpq_denref(res), fmpq_denref(x), exp); } else { fmpz_mul_2exp(fmpq_numref(res), fmpq_numref(x), exp - v); fmpz_fdiv_q_2exp(fmpq_denref(res), fmpq_denref(x), v); } } } flint-3.1.3/src/fmpq/next_calkin_wilf.c000066400000000000000000000023621461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_next_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) { fmpz n, d; n = *num; d = *den; if (!COEFF_IS_MPZ(n) && !COEFF_IS_MPZ(d)) { /* This does not overflow, as the larger part at most doubles */ fmpz_set_ui(rnum, d); fmpz_set_ui(rden, d*(n / d) + d - (n % d)); } else { fmpz_t q, r, t; fmpz_init(q); fmpz_init(r); fmpz_init(t); fmpz_fdiv_qr(q, r, num, den); fmpz_set(rnum, den); fmpz_mul(t, q, den); fmpz_add(rden, t, den); fmpz_sub(rden, rden, r); fmpz_clear(q); fmpz_clear(r); fmpz_clear(t); } } void fmpq_next_calkin_wilf(fmpq_t res, const fmpq_t x) { _fmpq_next_calkin_wilf(fmpq_numref(res), fmpq_denref(res), fmpq_numref(x), fmpq_denref(x)); } flint-3.1.3/src/fmpq/next_minimal.c000066400000000000000000000035411461254215100172200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" void _fmpq_next_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) { fmpz p, q; p = *num; q = *den; if (!COEFF_IS_MPZ(p) && !COEFF_IS_MPZ(q)) { if (p < q && p) { fmpz_set_ui(rnum, q); fmpz_set_ui(rden, p); return; } while (q < p) { q++; if (n_gcd(p, q) == 1) { fmpz_set_ui(rnum, q); fmpz_set_ui(rden, p); return; } } fmpz_one(rnum); fmpz_set_ui(rden, p + 1); } else { fmpz_t t; if (fmpz_cmp(num, den) < 0) { fmpz_set(rnum, num); fmpz_set(rden, den); fmpz_swap(rnum, rden); return; } fmpz_init(t); fmpz_set(rnum, num); fmpz_set(rden, den); while (fmpz_cmp(rden, rnum) < 0) { fmpz_add_ui(rden, rden, 1); fmpz_gcd(t, rden, rnum); if (fmpz_is_one(t)) { fmpz_swap(rnum, rden); fmpz_clear(t); return; } } fmpz_add_ui(rden, rden, 1); fmpz_one(rnum); fmpz_clear(t); } } void fmpq_next_minimal(fmpq_t res, const fmpq_t x) { _fmpq_next_minimal(fmpq_numref(res), fmpq_denref(res), fmpq_numref(x), fmpq_denref(x)); } flint-3.1.3/src/fmpq/next_signed_calkin_wilf.c000066400000000000000000000015671461254215100214130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_next_signed_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) { if (fmpz_sgn(num) > 0) { fmpz_neg(rnum, num); fmpz_set(rden, den); } else { fmpz_neg(rnum, num); _fmpq_next_calkin_wilf(rnum, rden, rnum, den); } } void fmpq_next_signed_calkin_wilf(fmpq_t res, const fmpq_t x) { _fmpq_next_signed_calkin_wilf(fmpq_numref(res), fmpq_denref(res), fmpq_numref(x), fmpq_denref(x)); } flint-3.1.3/src/fmpq/next_signed_minimal.c000066400000000000000000000015471461254215100205550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_next_signed_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den) { if (fmpz_sgn(num) > 0) { fmpz_neg(rnum, num); fmpz_set(rden, den); } else { fmpz_neg(rnum, num); _fmpq_next_minimal(rnum, rden, rnum, den); } } void fmpq_next_signed_minimal(fmpq_t res, const fmpq_t x) { _fmpq_next_signed_minimal(fmpq_numref(res), fmpq_denref(res), fmpq_numref(x), fmpq_denref(x)); } flint-3.1.3/src/fmpq/pow_fmpz.c000066400000000000000000000021661461254215100163770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" int fmpq_pow_fmpz(fmpq_t a, const fmpq_t b, const fmpz_t e) { int e_sgn; if (fmpq_is_zero(b)) { e_sgn = fmpz_sgn(e); if (e_sgn < 0) flint_throw(FLINT_ERROR, "Division by zero in fmpq_pow_fmpz"); fmpz_set_si(fmpq_numref(a), e_sgn == 0 ? 1 : 0); fmpz_one(fmpq_denref(a)); return 1; } else if (fmpz_is_one(fmpq_denref(b)) && fmpz_is_pm1(fmpq_numref(b))) { fmpz_set_si(fmpq_numref(a), fmpz_is_one(fmpq_numref(b)) || fmpz_is_even(e) ? 1 : -1); fmpz_one(fmpq_denref(a)); return 1; } else { if (!fmpz_fits_si(e)) return 0; fmpq_pow_si(a, b, fmpz_get_si(e)); return 1; } } flint-3.1.3/src/fmpq/pow_si.c000066400000000000000000000026141461254215100160340ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_pow_si(fmpz_t rnum, fmpz_t rden, const fmpz_t opnum, const fmpz_t opden, slong e) { if (e >= 0) { fmpz_pow_ui(rnum, opnum, e); fmpz_pow_ui(rden, opden, e); } else { if (rnum == opnum) { fmpz t; fmpz_pow_ui(rnum, opnum, -e); fmpz_pow_ui(rden, opden, -e); t = *rnum; *rnum = *rden; *rden = t; } else { fmpz_pow_ui(rden, opnum, -e); fmpz_pow_ui(rnum, opden, -e); } if (fmpz_sgn(rden) < 0) { fmpz_neg(rnum, rnum); fmpz_neg(rden, rden); } } } void fmpq_pow_si(fmpq_t rop, const fmpq_t op, slong e) { if (e < 0 && fmpz_is_zero(fmpq_numref(op))) { flint_throw(FLINT_ERROR, "Exception (fmpq_pow_si). Division by zero.\n"); } _fmpq_pow_si(fmpq_numref(rop), fmpq_denref(rop), fmpq_numref(op), fmpq_denref(op), e); } flint-3.1.3/src/fmpq/profile/000077500000000000000000000000001461254215100160255ustar00rootroot00000000000000flint-3.1.3/src/fmpq/profile/p-get_cfrac.c000066400000000000000000000063211461254215100203450ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq.h" #include "profiler.h" int main(void) { int i; flint_printf("\n"); fflush(stdout); for (i = 0; i <= 24; i++) { fmpq_t x, r, l, m; fmpz *c1, *c2; slong n1, /*n2, */bound; slong gcd_time; timeit_t timer; slong expected_length; fmpq_init(x); fmpq_init(r); fmpq_init(l); fmpq_init(m); fmpz_fib_ui(fmpq_numref(x), (1 << i) + 1); fmpz_fib_ui(fmpq_denref(x), (1 << i)); flint_printf("\n--- fib(1+2^%wd)/fib(2^%wd) (numerator bits = %wu) ---\n", i, i, fmpz_bits(fmpq_numref(x))); expected_length = FLINT_MAX(1, (1 << i) - 1); timeit_start(timer); fmpq_canonicalise(x); timeit_stop(timer); gcd_time = timer->wall; flint_printf("gcd: %wd\n", timer->wall); gcd_time = FLINT_MAX(1, gcd_time); bound = fmpq_cfrac_bound(x); if (bound < expected_length) { flint_printf("FAIL0: bound = %wd, expected = %wd\n", bound, expected_length); flint_abort(); } c1 = _fmpz_vec_init(bound); c2 = _fmpz_vec_init(bound); timeit_start(timer); n1 = fmpq_get_cfrac(c1, r, x, bound); timeit_stop(timer); if (!fmpq_is_zero(r) || n1 != expected_length) { flint_printf("FAIL1: n1 = %wd, expected = %wd\n", n1, expected_length); flint_abort(); } flint_printf("new: %wd (new/gcd: %f)\n", timer->wall, (double)(timer->wall)/(double)(gcd_time)); fmpz_fib_ui(fmpq_numref(r), (1 << i) + 1); fmpz_fib_ui(fmpq_denref(r), (1 << i)); fmpz_fib_ui(fmpq_numref(l), (1 << i) + 2); fmpz_fib_ui(fmpq_denref(l), (1 << i) + 1); if (i == 0) fmpq_swap(l, r); timeit_start(timer); _fmpq_simplest_between(fmpq_numref(m), fmpq_denref(m), fmpq_numref(l), fmpq_denref(l), fmpq_numref(r), fmpq_denref(r)); timeit_stop(timer); if (!fmpq_equal(m, x)) { flint_printf("FAIL: between\n"); flint_abort(); } flint_printf("bet: %wd (bet/gcd: %f)\n", timer->wall, (double)(timer->wall)/(double)(gcd_time)); #if 0 timeit_start(timer); n2 = fmpq_get_cfrac_naive(c2, r, x, bound); timeit_stop(timer); if (!fmpq_is_zero(r) || n2 != expected_length) { flint_printf("FAIL2: n2 = %wd, expected = %wd\n", n2, expected_length); flint_abort(); } flint_printf("old: %wd\n", timer->wall); #endif _fmpz_vec_clear(c1, bound); _fmpz_vec_clear(c2, bound); fmpq_clear(x); fmpq_clear(r); fmpq_clear(l); fmpq_clear(m); } flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpq/profile/p-reconstruct_fmpz_2.c000066400000000000000000000117511461254215100222630ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" #include "profiler.h" double profile_it( flint_rand_t state, slong reps, flint_bitcnt_t Nbits, flint_bitcnt_t Dbits, flint_bitcnt_t mbits, int print_it) { slong i, j, k; fmpq_t x, y; fmpz_t N, D, m, r; timeit_t timer; double new_time, old_time; slong outer_reps = 9; fmpq_init(x); fmpq_init(y); fmpz_init(N); fmpz_init(D); fmpz_init(m); fmpz_init(r); new_time = 0; old_time = 0; k = n_randint(state, 2); for (j = 0; j < outer_reps; j++) { fmpq_zero(y); fmpz_randbits(N, state, Nbits); fmpz_randbits(D, state, Dbits); fmpz_randbits(m, state, mbits); fmpz_abs(N, N); fmpz_abs(D, D); fmpz_abs(m, m); fmpz_mul_ui(r, N, 2); fmpz_randm(fmpq_numref(x), state, r); fmpz_sub(fmpq_numref(x), fmpq_numref(x), N); fmpz_randm(fmpq_denref(x), state, D); fmpz_add_ui(fmpq_denref(x), fmpq_denref(x), 1); fmpq_canonicalise(x); fmpz_addmul(m, r, D); do fmpz_add_ui(m, m, 1); while (!fmpq_mod_fmpz(r, x, m)); if ((j + k) & 1) { timeit_start(timer); for (i = 0; i < reps; i++) _fmpq_reconstruct_fmpz_2(fmpq_numref(y), fmpq_denref(y), r, m, N, D); timeit_stop(timer); new_time += timer->wall; } else { timeit_start(timer); for (i = 0; i < reps; i++) _fmpq_reconstruct_fmpz_2_naive(fmpq_numref(y), fmpq_denref(y), r, m, N, D); timeit_stop(timer); old_time += timer->wall; } if (!fmpq_equal(y, x)) { flint_printf("problem %wd\n", (j + k) & 1); printf("x: "); fmpq_print(x); printf("\n"); printf("y: "); fmpq_print(y); printf("\n"); flint_abort(); } } new_time = new_time / reps / outer_reps; old_time = old_time / reps / outer_reps; if (print_it) flint_printf("bits (%wu, %wu, %wu): new %f ms , old %f ms | old/new: %f\n", Nbits, Dbits, mbits, new_time, old_time, old_time/new_time); fmpq_clear(x); fmpq_clear(y); fmpz_clear(N); fmpz_clear(D); fmpz_clear(m); fmpz_clear(r); return old_time/new_time; } int main(void) { double total; slong i, j, count; flint_rand_t state; flint_printf("\n"); fflush(stdout); flint_randinit(state); printf("---- balanced ----\n"); for (j = 1; j <= 10; j++) { total = 0; count = 0; i = (j < 2) ? 10 : FLINT_BITS*(j - 1) + 1; for (; i <= FLINT_BITS*j; i += 1) { total += profile_it(state, 200000/i, i/2, i/2, i, 0); count++; } flint_printf("size %wd average speedup ratio: %f\n", j, total/count); } profile_it(state, 100, 500, 500, 1000,1); profile_it(state, 100, 500, 500, 1000,1); profile_it(state, 80, 1000, 1000, 2000,1); profile_it(state, 80, 1000, 1000, 2000,1); profile_it(state, 50, 2000, 2000, 4000,1); profile_it(state, 50, 2000, 2000, 4000,1); profile_it(state, 10, 10000, 10000, 20000,1); profile_it(state, 10, 10000, 10000, 20000,1); profile_it(state, 8, 20000, 20000, 40000,1); profile_it(state, 8, 20000, 20000, 40000,1); profile_it(state, 6, 40000, 40000, 80000,1); profile_it(state, 6, 40000, 40000, 80000,1); profile_it(state, 4, 80000, 80000, 160000,1); profile_it(state, 1, 160000, 160000, 320000,1); printf("---- imbalanced ----\n"); profile_it(state, 500, 50, 30, 80,1); profile_it(state, 500, 30, 50, 80,1); profile_it(state, 200, 50,100,150,1); profile_it(state, 200, 100, 50,150,1); profile_it(state, 100, 100,200,300,1); profile_it(state, 100, 200,100,300,1); profile_it(state, 100, 200,400,600,1); profile_it(state, 100, 400,200,600,1); profile_it(state, 100, 400,800,1200,1); profile_it(state, 100, 800,400,1200,1); profile_it(state, 100, 1000,2000,3000,1); profile_it(state, 100, 2000,1000,3000,1); profile_it(state, 80, 2000,4000,6000,1); profile_it(state, 80, 4000,2000,6000,1); profile_it(state, 30, 4000,8000,12000,1); profile_it(state, 30, 8000,4000,12000,1); profile_it(state, 10, 10000,20000,30000,1); profile_it(state, 10, 20000,10000,30000,1); profile_it(state, 4, 20000,40000,60000,1); profile_it(state, 4, 40000,20000,60000,1); flint_randclear(state); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpq/randbits.c000066400000000000000000000014311461254215100163360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_randbits(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits) { fmpz_randbits(num, state, bits); do { fmpz_randbits(den, state, bits); } while (fmpz_is_zero(den)); _fmpq_canonicalise(num, den); } void fmpq_randbits(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits) { _fmpq_randbits(fmpq_numref(res), fmpq_denref(res), state, bits); } flint-3.1.3/src/fmpq/randtest.c000066400000000000000000000031671461254215100163640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" void _fmpq_randtest(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits) { mp_limb_t x = n_randlimb(state); fmpz_randtest(num, state, bits); if (bits == 1) { fmpz_one(den); return; } fmpz_randtest_not_zero(den, state, bits); switch (x % 16) { case 0: fmpz_set_si(num, 1); break; case 1: fmpz_set_si(num, -1); break; case 2: fmpz_set_si(num, 2); break; case 3: fmpz_set_si(num, -2); break; } switch ((x / 16) % 16) { case 0: fmpz_set_si(den, 1); break; case 2: fmpz_set_si(den, 2); break; } _fmpq_canonicalise(num, den); } void fmpq_randtest(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits) { _fmpq_randtest(fmpq_numref(res), fmpq_denref(res), state, bits); } void fmpq_randtest_not_zero(fmpq_t f, flint_rand_t state, flint_bitcnt_t bits) { if (bits == 0) { flint_throw(FLINT_ERROR, "Exception (fmpq_randtest_not_zero). bits == 0.\n"); } do { fmpq_randtest(f, state, bits); } while (fmpq_is_zero(f)); } flint-3.1.3/src/fmpq/reconstruct_fmpz.c000066400000000000000000000016401461254215100201410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" int _fmpq_reconstruct_fmpz(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m) { fmpz_t N; int result; fmpz_init(N); fmpz_fdiv_q_2exp(N, m, 1); if (fmpz_is_even(m)) fmpz_sub_ui(N, N, 1); fmpz_sqrt(N, N); result = _fmpq_reconstruct_fmpz_2(n, d, a, m, N, N); fmpz_clear(N); return result; } int fmpq_reconstruct_fmpz(fmpq_t res, const fmpz_t a, const fmpz_t m) { return _fmpq_reconstruct_fmpz(fmpq_numref(res), fmpq_denref(res), a, m); } flint-3.1.3/src/fmpq/reconstruct_fmpz_2.c000066400000000000000000000617721461254215100203760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "fmpq.h" #define FMPQ_RECONSTRUCT_ARRAY_LIMIT 12 /* hgcd for two-limb input, individual quotients not written */ static slong _hgcd_uiui_no_write( mp_limb_t A1, mp_limb_t A0, mp_limb_t B1, mp_limb_t B0, _ui_mat22_t M) { slong written = 0; /* number of quotients generated */ mp_limb_t last_written = 0; mp_limb_t d0, d1, t0, t1, t2, r0, r1; int det = 1; mp_limb_t m11 = 1; mp_limb_t m12 = 0; mp_limb_t m21 = 0; mp_limb_t m22 = 1; mp_limb_t a1 = A1; mp_limb_t a0 = A0; mp_limb_t b1 = B1; mp_limb_t b0 = B0; mp_limb_t q; FLINT_ASSERT(a1 != 0); FLINT_ASSERT(b1 < a1 || (b1 == a1 && b0 <= a0)); if (b1 == 0 || !(b1 < a1 || (b1 == a1 && b0 < a0))) goto done; while (1) { eudiv_qrrnndd(q, r1, r0, a1, a0, b1, b0, tmp1_); t1 = m12 + q*m11; t2 = m22 + q*m21; if (r1 == 0) break; a0 = b0; a1 = b1; b0 = r0; b1 = r1; m12 = m11; m22 = m21; m11 = t1; m21 = t2; det *= -1; last_written = q; written++; } FLINT_ASSERT(a1 != 0); FLINT_ASSERT(b1 <= a1); FLINT_ASSERT(b1 < a1 || (b1 == a1 && b0 < a0)); sub_ddmmss(d1,d0, a1,a0, b1,b0); if (det > 0) { if (b1 == 0 && b0 <= m21) goto fix; add_ssaaaa(t1,t0, 0,m11, 0,m12); } else { if (b1 == 0 && b0 <= m11) goto fix; add_ssaaaa(t1,t0, 0,m21, 0,m22); } if (d1 < t1 || (d1 == t1 && d0 < t0)) goto fix; fixed: #if FLINT_WANT_ASSERT /* should be ok */ sub_ddmmss(d1,d0, a1,a0, b1,b0); if (det > 0) { FLINT_ASSERT(!(b1 == 0 && b0 <= m21)); add_ssaaaa(t1,t0, 0,m11, 0,m12); } else { FLINT_ASSERT(!(b1 == 0 && b0 <= m11)); add_ssaaaa(t1,t0, 0,m21, 0,m22); } FLINT_ASSERT(!(d1 < t1 || (d1 == t1 && d0 < t0))); /* should have {A, B} == {{m11, m12}, {m21, m22}} . {a, b} */ umul_ppmm(t1,t0, a0, m11); t1 += a1*m11; umul_ppmm(d1,d0, b0, m12); d1 += b1*m12; add_sssaaaaaa(t2,t1,t0, 0,t1,t0, 0,d1,d0); FLINT_ASSERT(t0 == A0 && t1 == A1 && t2 == 0); umul_ppmm(t1,t0, a0, m21); t1 += a1*m21; umul_ppmm(d1,d0, b0, m22); d1 += b1*m22; add_sssaaaaaa(t2,t1,t0, 0,t1,t0, 0,d1,d0); FLINT_ASSERT(t0 == B0 && t1 == B1 && t2 == 0); /* should have det = Det[{{m11, m12}, {m21, m22}}] */ umul_ppmm(t1,t0, m11, m22); umul_ppmm(d1,d0, m12, m21); sub_ddmmss(t1,t0, t1,t0, d1,d0); FLINT_ASSERT(t1 == FLINT_SIGN_EXT(t0)); FLINT_ASSERT(t0 == det); #endif done: M->_11 = m11; M->_12 = m12; M->_21 = m21; M->_22 = m22; M->det = det; return written; fix: written--; FLINT_ASSERT(written >= 0); FLINT_ASSERT(last_written != 0); q = last_written; t1 = m11 - q*m12; t2 = m21 - q*m22; m11 = m12; m21 = m22; m12 = t1; m22 = t2; det *= -1; #if FLINT_WANT_ASSERT umul_ppmm(t1,t0, a0, q); t1 += a1*q; add_ssaaaa(t1,t0, t1,t0, b1,b0); b0 = a0; b1 = a1; a0 = t0; a1 = t1; #endif goto fixed; } /* u is odd */ static int coprime_ui(mp_limb_t u, mp_limb_t v) { FLINT_ASSERT(u > 0); FLINT_ASSERT(v > 0); while ((v & 1) == 0) {v = v/2;} again: FLINT_ASSERT(u & 1); FLINT_ASSERT(v & 1); if (u > v) { u -= v; do { u = u >> 1; } while ((u & 1) == 0); goto again; } else if (u < v) { v -= u; do { v = v >> 1; } while ((v & 1) == 0); goto again; } else { return u == 1; } } /* u is odd */ static int coprime_uiui(mp_limb_t u1, mp_limb_t u0, mp_limb_t v1, mp_limb_t v0) { FLINT_ASSERT(u1 > 0 || u0 > 0); FLINT_ASSERT(v1 > 0 || v0 > 0); while ((v0 & 1) == 0) { v0 = MPN_RIGHT_SHIFT_LOW(v1, v0, 1); v1 = v1 >> 1; } again: FLINT_ASSERT(u0 & 1); FLINT_ASSERT(v0 & 1); if (u1 > v1) { sub_ddmmss(u1, u0, u1, u0, v1, v0); do { u0 = MPN_RIGHT_SHIFT_LOW(u1, u0, 1); u1 = u1 >> 1; } while ((u0 & 1) == 0); goto again; } else if (v1 > u1) { sub_ddmmss(v1, v0, v1, v0, u1, u0); do { v0 = MPN_RIGHT_SHIFT_LOW(v1, v0, 1); v1 = v1 >> 1; } while ((v0 & 1) == 0); goto again; } else if (u0 > v0) { return coprime_ui(v0, u0 - v0); } else if (v0 > u0) { return coprime_ui(u0, v0 - u0); } else { return u1 == 0 && u0 == 1; } } int _fmpq_reconstruct_fmpz_2_ui(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t NN, const fmpz_t DD) { mp_limb_t Q, R, A, B, N; mp_limb_t m11 = 1, m12 = 0, t; int mdet = 1; FLINT_ASSERT(fmpz_size(m) == 1); A = fmpz_get_ui(m); B = fmpz_get_ui(a); N = fmpz_get_ui(NN); gauss: FLINT_ASSERT(A > B && B > N); eudiv_qrnd(Q, R, A, B, tmp_); mdet *= -1; t = m12 + m11*Q; m12 = m11; m11 = t; A = B; B = R; if (B > N) goto gauss; FLINT_ASSERT(A > N && N >= B); if (fmpz_cmp_ui(DD, m11) < 0) return 0; if (mdet > 0) fmpz_set_ui(n, B); else fmpz_neg_ui(n, B); fmpz_set_ui(d, m11); FLINT_ASSERT(m11 != 0); if (B == 0) return m11 == 1; if (B & 1) return coprime_ui(B, m11); else if (m11 & 1) return coprime_ui(m11, B); else return 0; } int _fmpq_reconstruct_fmpz_2_uiui(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t NN, const fmpz_t DD) { mp_limb_t extra; mp_limb_t Q1, Q0, R1, R0, A1, A0, B1, B0, N1, N0, D1, D0; mp_limb_t m11[2] = {1, 0}, m12[2] = {0, 0}, t[2]; int mdet = 1; FLINT_ASSERT(fmpz_size(m) == 2); fmpz_get_uiui(&A1, &A0, m); fmpz_get_uiui(&B1, &B0, a); fmpz_get_uiui(&N1, &N0, NN); fmpz_get_uiui(&D1, &D0, DD); gauss: FLINT_ASSERT(A1 > B1 || (A1 == B1 && A0 > B0)); FLINT_ASSERT(B1 > N1 || (B1 == N1 && B0 > N0)); if (A1 != 0 && B1 != 0) { eudiv_qrrnndd(Q0, R1, R0, A1, A0, B1, B0, tmp1_); extra = 0; } else if (A1 == 0 && B1 == 0) { eudiv_qrnd(Q0, R0, A0, B0, tmp2_); R1 = 0; extra = 0; } else { eudiv_qqrnnd(Q1, Q0, R0, A1, A0, B0, tmp3_); R1 = 0; extra = m11[0]*Q1; } umul_ppmm(t[1], t[0], m11[0], Q0); add_ssaaaa(t[1], t[0], t[1], t[0], m12[1], m12[0]); t[1] += m11[1]*Q0 + extra; mdet *= -1; m12[1] = m11[1]; m12[0] = m11[0]; m11[1] = t[1]; m11[0] = t[0]; A1 = B1; A0 = B0; B1 = R1; B0 = R0; if (B1 > N1 || (B1 == N1 && B0 > N0)) goto gauss; if (D1 < m11[1] || (D1 == m11[1] && D0 < m11[0])) return 0; if (mdet > 0) fmpz_set_uiui(n, B1, B0); else fmpz_neg_uiui(n, B1, B0); fmpz_set_uiui(d, m11[1], m11[0]); if (B1 == 0 && B0 == 0) return m11[1] == 0 && m11[0] == 1; if (m11[0] & 1) return coprime_uiui(m11[1], m11[0], B1, B0); else if (B0 & 1) return coprime_uiui(B1, B0, m11[1], m11[0]); else return 0; } int _fmpq_reconstruct_fmpz_2_ui_array(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D) { mp_limb_t ex0, ex1, ex2, ex3, A1, A0, B1, B0; unsigned int n_lzcnt, a_lzcnt; _ui_mat22_t h; slong written; const mp_limb_t * n_ptr, * d_ptr; slong n_len, d_len; mp_limb_t A[FMPQ_RECONSTRUCT_ARRAY_LIMIT + 1]; mp_limb_t B[FMPQ_RECONSTRUCT_ARRAY_LIMIT + 1]; mp_limb_t Q[FMPQ_RECONSTRUCT_ARRAY_LIMIT + 1]; mp_limb_t R[FMPQ_RECONSTRUCT_ARRAY_LIMIT + 1]; mp_limb_t m11[FMPQ_RECONSTRUCT_ARRAY_LIMIT + 2]; mp_limb_t m12[FMPQ_RECONSTRUCT_ARRAY_LIMIT + 2]; slong Alen, Blen, Qlen, Rlen, m_len; int mdet = 1; FLINT_ASSERT(fmpz_size(m) <= FMPQ_RECONSTRUCT_ARRAY_LIMIT); fmpz_get_ui_array(A, FMPQ_RECONSTRUCT_ARRAY_LIMIT, m); Alen = FMPQ_RECONSTRUCT_ARRAY_LIMIT; MPN_NORM(A, Alen); fmpz_get_ui_array(B, FMPQ_RECONSTRUCT_ARRAY_LIMIT, a); Blen = FMPQ_RECONSTRUCT_ARRAY_LIMIT; MPN_NORM(B, Blen); if (COEFF_IS_MPZ(*N)) { n_ptr = COEFF_TO_PTR(*N)->_mp_d; n_len = COEFF_TO_PTR(*N)->_mp_size; } else { n_ptr = (mp_srcptr) N; /* haha, dirty but works */ n_len = 1; } if (COEFF_IS_MPZ(*D)) { d_ptr = COEFF_TO_PTR(*D)->_mp_d; d_len = COEFF_TO_PTR(*D)->_mp_size; } else { d_ptr = (mp_srcptr) D; /* haha, dirty but works */ d_len = 1; } /* m12 is supposed to be zero-extended to the length of m11 (= m_len) */ flint_mpn_zero(m11, FMPQ_RECONSTRUCT_ARRAY_LIMIT); flint_mpn_zero(m12, FMPQ_RECONSTRUCT_ARRAY_LIMIT); /* m11 = 1, m12 = 0 */ m_len = 1; m11[0] = 1; FLINT_ASSERT(n_len > 0); FLINT_ASSERT(d_len > 0); FLINT_ASSERT(n_ptr[n_len - 1] != 0); n_lzcnt = flint_clz(n_ptr[n_len - 1]); again: FLINT_ASSERT(Alen > 0 && A[Alen - 1] > 0); FLINT_ASSERT(Blen > 0 && B[Blen - 1] > 0); FLINT_ASSERT(Alen > Blen || (Alen == Blen && mpn_cmp(A, B, Blen) > 0)); FLINT_ASSERT(Blen > n_len || (Blen == n_len && mpn_cmp(B, n_ptr, n_len) > 0)); FLINT_ASSERT(m_len > 0 && m11[m_len - 1] > 0); FLINT_ASSERT(mpn_cmp(m11, m12, m_len) >= 0); if (Alen < 3 || Blen <= n_len) { /* too small or too close to the end */ goto gauss; } a_lzcnt = flint_clz(A[Alen - 1]); if (Alen - 1 > Blen) { /* large quotient */ goto gauss; } if (Alen - 1 == n_len && n_lzcnt < a_lzcnt) { /* too small or too close to the end */ goto gauss; } FLINT_ASSERT(Alen == Blen || Alen - 1 == Blen); /* zero-extend B to length of A in the case Alen - 1 == Blen */ B[Blen] = 0; A1 = MPN_LEFT_SHIFT_HI(A[Alen - 1], A[Alen - 2], a_lzcnt); A0 = MPN_LEFT_SHIFT_HI(A[Alen - 2], A[Alen - 3], a_lzcnt); B1 = MPN_LEFT_SHIFT_HI(B[Alen - 1], B[Alen - 2], a_lzcnt); B0 = MPN_LEFT_SHIFT_HI(B[Alen - 2], B[Alen - 3], a_lzcnt); written = _hgcd_uiui_no_write(A1, A0, B1, B0, h); if (written <= 0) { /* difficult quotient */ goto gauss; } /* (Q, R) will be the new values for (A, B) */ if (h->det == 1) { Qlen = flint_mpn_fmms1(Q, h->_22, A, h->_12, B, Alen); Rlen = flint_mpn_fmms1(R, h->_11, B, h->_21, A, Alen); } else { Qlen = flint_mpn_fmms1(Q, h->_12, B, h->_22, A, Alen); Rlen = flint_mpn_fmms1(R, h->_21, A, h->_11, B, Alen); } FLINT_ASSERT(Qlen >= Rlen && Rlen >= 0); FLINT_ASSERT(Qlen > Rlen || Rlen == 0 || mpn_cmp(Q, R, Rlen) > 0); if (Qlen < n_len || (Qlen == n_len && mpn_cmp(Q, n_ptr, n_len) <= 0)) { /* overshot with too many quotients. rare (impossible?) due to above lzcnt restriction. can trigger by using n_lzcnt + 1 < a_lzcnt. */ goto gauss; } /* copy (Q, R) to (A, B) */ Alen = Qlen; Blen = Rlen; flint_mpn_copyi(A, Q, FMPQ_RECONSTRUCT_ARRAY_LIMIT); flint_mpn_copyi(B, R, FMPQ_RECONSTRUCT_ARRAY_LIMIT); /* multiply first row of m by h, use R for temp */ mdet *= h->det; ex0 = mpn_mul_1(R, m11, m_len, h->_11); ex1 = mpn_addmul_1(R, m12, m_len, h->_21); ex2 = mpn_mul_1(m12, m12, m_len, h->_22); ex3 = mpn_addmul_1(m12, m11, m_len, h->_12); add_ssaaaa(m12[m_len + 1], m12[m_len], 0, ex2, 0, ex3); flint_mpn_copyi(m11, R, m_len); add_ssaaaa(m11[m_len + 1], m11[m_len], 0, ex0, 0, ex1); m_len += (m11[m_len + 1] != 0) ? 2 : (m11[m_len] != 0); /* so A > N. see if further A > N >= B */ if (Blen < n_len || (Blen == n_len && mpn_cmp(B, n_ptr, n_len) <= 0)) { /* got lucky. can happen */ goto done; } goto again; gauss: FLINT_ASSERT(Alen > 0 && A[Alen - 1] > 0); FLINT_ASSERT(Blen > 0 && B[Blen - 1] > 0); FLINT_ASSERT(Alen > Blen || (Alen == Blen && mpn_cmp(A, B, Blen) > 0)); FLINT_ASSERT(Blen > n_len || (Blen == n_len && mpn_cmp(B, n_ptr, n_len) > 0)); FLINT_ASSERT(m_len > 0 && m11[m_len - 1] > 0); FLINT_ASSERT(mpn_cmp(m11, m12, m_len) >= 0); /* (A, B) = (B, A mod B) */ mpn_tdiv_qr(Q, R, 0, A, Alen, B, Blen); Qlen = Alen - Blen + 1; MPN_NORM(Q, Qlen); Rlen = Blen; MPN_NORM(R, Rlen); Alen = Blen; Blen = Rlen; flint_mpn_copyi(A, B, FMPQ_RECONSTRUCT_ARRAY_LIMIT); flint_mpn_copyi(B, R, FMPQ_RECONSTRUCT_ARRAY_LIMIT); /* (m11, m12) = (m12 + Q*m11, m11), use R for temp */ mdet *= -1; ex0 = (Qlen > m_len) ? flint_mpn_mul(R, Q, Qlen, m11, m_len) : flint_mpn_mul(R, m11, m_len, Q, Qlen); m_len = Qlen + m_len - (ex0 == 0); ex0 = mpn_add_n(R, R, m12, m_len); R[m_len] = ex0; m_len += ex0; flint_mpn_copyi(m12, m11, m_len); flint_mpn_copyi(m11, R, m_len); /* see if further A > N >= B */ if (Blen > n_len || (Blen == n_len && mpn_cmp(B, n_ptr, n_len) > 0)) goto again; done: FLINT_ASSERT(Alen > n_len || (Alen == n_len && mpn_cmp(A, n_ptr, n_len) > 0)); FLINT_ASSERT(n_len > Blen || (n_len == Blen && mpn_cmp(n_ptr, B, Blen) >= 0)); if (d_len < m_len || (d_len == m_len && mpn_cmp(d_ptr, m11, m_len) < 0)) return 0; fmpz_set_ui_array(d, m11, m_len); if (Blen > 0) { fmpz_set_ui_array(n, B, Blen); if (mdet < 0) fmpz_neg(n, n); } else { fmpz_zero(n); } FLINT_ASSERT(m_len > 0); if (Blen == 0) return m_len == 1 && m11[0] == 1; if (((m11[0] | B[0]) & 1) == 0) return 0; /* gcd is even */ if (m_len >= Blen) { if (mpn_gcd(R, m11, m_len, B, Blen) != 1) return 0; } else { if (mpn_gcd(R, B, Blen, m11, m_len) != 1) return 0; } return R[0] == 1; } /* A, B, and N come in with A > B > N > 0. Work on A/B and accumulate any quotients into M. The second row of M is ignored. S and T are temp working space. return -1: no need to use _lehmer again; leave with A > B > N > 0 return 0: good idea to use _lehmer again; leave with A > B > N > 0 return 1: done; leave with A > N >= B */ static int _lehmer(_fmpz_mat22_t M, fmpz_t A, fmpz_t B, const fmpz_t N, fmpz_t S, fmpz_t T) { int ret; slong written; mp_srcptr n_ptr; mpz_ptr a, b, s, t; mp_ptr a_ptr, b_ptr, s_ptr, t_ptr; mp_size_t a_len, b_len, n_len, s_len, t_len; _ui_mat22_t h; mp_limb_t A0, A1, B0, B1; unsigned int n_lzcnt, a_lzcnt; if (!COEFF_IS_MPZ(*A) || !COEFF_IS_MPZ(*B)) { /* don't come back */ return -1; } a = COEFF_TO_PTR(*A); b = COEFF_TO_PTR(*B); if (COEFF_IS_MPZ(*N)) { n_ptr = COEFF_TO_PTR(*N)->_mp_d; n_len = COEFF_TO_PTR(*N)->_mp_size; } else { n_ptr = (mp_srcptr) N; /* haha, dirty but works */ n_len = 1; } FLINT_ASSERT(n_ptr[n_len - 1] != 0); n_lzcnt = flint_clz(n_ptr[n_len - 1]); if (a->_mp_size < 3 || b->_mp_size <= n_len) { /* don't come back */ return -1; } s = _fmpz_promote(S); t = _fmpz_promote(T); /* fit everything to length a->_mp_size */ a_len = a->_mp_size; FLINT_MPZ_REALLOC(b, a_len); FLINT_MPZ_REALLOC(s, a_len); FLINT_MPZ_REALLOC(t, a_len); again: a_ptr = a->_mp_d; b_ptr = b->_mp_d; s_ptr = s->_mp_d; t_ptr = t->_mp_d; a_len = a->_mp_size; b_len = b->_mp_size; /* supposed a > b > n > 0 */ FLINT_ASSERT(a_len >= b_len); FLINT_ASSERT(b_len >= n_len); FLINT_ASSERT(n_len > 0); FLINT_ASSERT(a_ptr[a_len - 1] != 0); FLINT_ASSERT(b_ptr[b_len - 1] != 0); FLINT_ASSERT(n_ptr[n_len - 1] != 0); if (a_len < 3 || b_len <= n_len) { /* too small or too close to the end */ ret = -1; goto cleanup; } if (a_len - 1 > b_len) { /* large quotient */ ret = 0; goto cleanup; } FLINT_ASSERT(a_ptr[a_len - 1] != 0); a_lzcnt = flint_clz(a_ptr[a_len - 1]); if (a_len - 1 == n_len && n_lzcnt < a_lzcnt) { /* too small or too close to the end */ ret = -1; goto cleanup; } FLINT_ASSERT(a_len == b_len || a_len - 1 == b_len); if (a_len - 1 == b_len) b_ptr[a_len - 1] = 0; A1 = MPN_LEFT_SHIFT_HI(a_ptr[a_len - 1], a_ptr[a_len - 2], a_lzcnt); A0 = MPN_LEFT_SHIFT_HI(a_ptr[a_len - 2], a_ptr[a_len - 3], a_lzcnt); B1 = MPN_LEFT_SHIFT_HI(b_ptr[a_len - 1], b_ptr[a_len - 2], a_lzcnt); B0 = MPN_LEFT_SHIFT_HI(b_ptr[a_len - 2], b_ptr[a_len - 3], a_lzcnt); written = _hgcd_uiui_no_write(A1, A0, B1, B0, h); if (written <= 0) { /* difficult quotient */ ret = 0; goto cleanup; } if (h->det == 1) { s_len = flint_mpn_fmms1(s_ptr, h->_22, a_ptr, h->_12, b_ptr, a_len); t_len = flint_mpn_fmms1(t_ptr, h->_11, b_ptr, h->_21, a_ptr, a_len); } else { FLINT_ASSERT(h->det == -1); s_len = flint_mpn_fmms1(s_ptr, h->_12, b_ptr, h->_22, a_ptr, a_len); t_len = flint_mpn_fmms1(t_ptr, h->_21, a_ptr, h->_11, b_ptr, a_len); } /* s > t >= 0 */ FLINT_ASSERT(s_len >= t_len && t_len >= 0); FLINT_ASSERT(s_len > t_len || t_len == 0 || mpn_cmp(s_ptr, t_ptr, t_len) > 0); if (s_len < n_len || (s_len == n_len && mpn_cmp(s_ptr, n_ptr, n_len) <= 0)) { /* overshot with too many quotients */ ret = 0; goto cleanup; } /* multiply first row of M by h, using second row as temp space */ fmpz_mul_ui(M->_21, M->_11, h->_11); fmpz_addmul_ui(M->_21, M->_12, h->_21); fmpz_mul_ui(M->_12, M->_12, h->_22); fmpz_addmul_ui(M->_12, M->_11, h->_12); fmpz_swap(M->_11, M->_21); M->det *= h->det; /* a = s; b = t */ s->_mp_size = s_len; t->_mp_size = t_len; FLINT_SWAP(mpz_ptr, a, s); FLINT_SWAP(mpz_ptr, b, t); /* so a > n. see if further a > n >= b. */ if (t_len < n_len || (t_len == n_len && mpn_cmp(t_ptr, n_ptr, n_len) <= 0)) { /* lucky finish */ ret = 1; goto cleanup; } goto again; cleanup: /* a/b are valid; make s/t valid */ s->_mp_size = 0; t->_mp_size = 0; *A = PTR_TO_COEFF(a); *B = PTR_TO_COEFF(b); *S = PTR_TO_COEFF(s); *T = PTR_TO_COEFF(t); _fmpz_demote_val(A); _fmpz_demote_val(B); _fmpz_demote_val(S); _fmpz_demote_val(T); return ret; } /* return 0: not done, output still satisfies A > B > N return 1: we are done with A > N >= B (rare) */ static int _split(_fmpz_mat22_t M, fmpz_t A, fmpz_t B, const fmpz_t N) { int ret; _fmpq_cfrac_list_t v; _fmpz_mat22_t H; fmpz_t As, Bs, Q, R; slong a, b, n = fmpz_size(N); slong s; /* shift amount in words */ fmpz_init(As); fmpz_init(Bs); fmpz_init(Q); fmpz_init(R); _fmpz_mat22_init(H); _fmpq_cfrac_list_init(v); again: FLINT_ASSERT(fmpz_cmp(A, B) > 0 && fmpz_cmp(B, N) > 0); a = fmpz_size(A); b = fmpz_size(B); if (b - n < FMPQ_RECONSTRUCT_HGCD_CUTOFF) { /* relatively few remaining quotients */ ret = 0; goto cleanup; } s = 1 + FLINT_MAX(0, 2*n - a); if (s >= b) { gauss: /* we hit a hard quotient */ fmpz_fdiv_qr(Q, A, A, B); fmpz_addmul(M->_12, M->_11, Q); fmpz_swap(M->_11, M->_12); M->det *= -1; fmpz_swap(A, B); if (fmpz_cmp(B, N) > 0) goto again; ret = 1; goto cleanup; } fmpz_fdiv_q_2exp(As, A, FLINT_BITS*s); fmpz_fdiv_q_2exp(Bs, B, FLINT_BITS*s); if (fmpz_cmp(As, Bs) <= 0) goto gauss; _fmpz_mat22_one(H); v->length = 0; _fmpq_hgcd(v, H, As, Bs); if (_fmpz_mat22_is_one(H)) goto gauss; fmpz_fdiv_r_2exp(Q, A, FLINT_BITS*s); fmpz_fdiv_r_2exp(R, B, FLINT_BITS*s); fmpz_mul_2exp(A, As, FLINT_BITS*s); fmpz_mul_2exp(B, Bs, FLINT_BITS*s); if (H->det == 1) { fmpz_addmul(A, Q, H->_22); fmpz_submul(A, R, H->_12); fmpz_addmul(B, R, H->_11); fmpz_submul(B, Q, H->_21); } else { fmpz_addmul(A, R, H->_12); fmpz_submul(A, Q, H->_22); fmpz_addmul(B, Q, H->_21); fmpz_submul(B, R, H->_11); } /* multiply first row of M by H, using second row as temp space */ fmpz_mul(M->_21, M->_11, H->_11); fmpz_addmul(M->_21, M->_12, H->_21); fmpz_mul(M->_12, M->_12, H->_22); fmpz_addmul(M->_12, M->_11, H->_12); fmpz_swap(M->_11, M->_21); M->det *= H->det; while (fmpz_cmp(A, N) <= 0) { /* unlikely (impossible?) with above choice of s. pop a quotient */ FLINT_ASSERT(v->length > 0); v->length--; fmpz_addmul(B, A, v->array + v->length); fmpz_swap(A, B); fmpz_submul(M->_11, M->_12, v->array + v->length); fmpz_swap(M->_11, M->_12); M->det *= -1; } /* should have used at least one quotient! */ FLINT_ASSERT(v->length > 0); if (fmpz_cmp(B, N) > 0) goto again; ret = 1; cleanup: fmpz_clear(As); fmpz_clear(Bs); fmpz_clear(Q); fmpz_clear(R); _fmpz_mat22_clear(H); _fmpq_cfrac_list_clear(v); return ret; } int _fmpq_reconstruct_fmpz_2(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D) { int ret, success; mp_size_t Asize, Nsize; fmpz_t Q, R, A, B; _fmpz_mat22_t M; /* only need first row of matrix M */ #if FLINT_WANT_ASSERT int cqt_success; fmpz_t cqt_n, cqt_d; /* check answer against correct naive version */ fmpz_init(cqt_n); fmpz_init(cqt_d); cqt_success = _fmpq_reconstruct_fmpz_2_naive(cqt_n, cqt_d, a, m, N, D); #endif /* Quickly identify small integers */ if (fmpz_cmp(a, N) <= 0) { fmpz_set(n, a); fmpz_one(d); success = 1; goto cleanup_assert; } fmpz_sub(n, a, m); if (fmpz_cmpabs(n, N) <= 0) { fmpz_one(d); success = 1; goto cleanup_assert; } Asize = fmpz_size(m); Nsize = fmpz_size(N); /* it is better to avoid the fmpz overhead & allocation at small sizes */ if (Asize <= FMPQ_RECONSTRUCT_ARRAY_LIMIT) { if (Asize < 2) success = _fmpq_reconstruct_fmpz_2_ui(n, d, a, m, N, D); else if (Asize == 2) success = _fmpq_reconstruct_fmpz_2_uiui(n, d, a, m, N, D); else success = _fmpq_reconstruct_fmpz_2_ui_array(n, d, a, m, N, D); goto cleanup_assert; } _fmpz_mat22_init(M); _fmpz_mat22_one(M); fmpz_init_set(A, m); fmpz_init_set(B, a); fmpz_init(Q); fmpz_init(R); /* We have A > B > N > 0; accumulate quotients into M until A > N >= B */ FLINT_ASSERT(fmpz_cmp(A, B) > 0 && fmpz_cmp(B, N) > 0 && fmpz_sgn(N) > 0); if (Asize - Nsize < 3) goto gauss; if (Asize - Nsize < FMPQ_RECONSTRUCT_HGCD_CUTOFF) goto lehmer; if (_split(M, A, B, N)) goto write_answer; lehmer: FLINT_ASSERT(fmpz_cmp(A, B) > 0 && fmpz_cmp(B, N) > 0); ret = _lehmer(M, A, B, N, Q, R); if (ret < 0) goto gauss; else if (ret > 0) goto write_answer; fmpz_fdiv_qr(Q, A, A, B); fmpz_addmul(M->_12, M->_11, Q); fmpz_swap(M->_11, M->_12); M->det *= -1; fmpz_swap(A, B); if (fmpz_cmp(B, N) > 0) goto lehmer; goto write_answer; gauss: FLINT_ASSERT(fmpz_cmp(A, B) > 0 && fmpz_cmp(B, N) > 0); fmpz_fdiv_qr(Q, A, A, B); fmpz_addmul(M->_12, M->_11, Q); fmpz_swap(M->_11, M->_12); M->det *= -1; fmpz_swap(A, B); if (fmpz_cmp(B, N) > 0) goto gauss; write_answer: FLINT_ASSERT(fmpz_cmp(A, N) > 0 && fmpz_cmp(N, B) >= 0); fmpz_swap(n, B); fmpz_swap(d, M->_11); if (M->det != 1) { FLINT_ASSERT(M->det == -1); fmpz_neg(n, n); } success = 0; FLINT_ASSERT(fmpz_sgn(d) > 0); if (fmpz_cmp(d, D) <= 0) { fmpz_gcd(R, n, d); success = fmpz_is_one(R); } fmpz_clear(Q); fmpz_clear(R); fmpz_clear(A); fmpz_clear(B); _fmpz_mat22_clear(M); cleanup_assert: #if FLINT_WANT_ASSERT FLINT_ASSERT(success == cqt_success); if (success) { FLINT_ASSERT(fmpz_equal(n, cqt_n)); FLINT_ASSERT(fmpz_equal(d, cqt_d)); } fmpz_clear(cqt_n); fmpz_clear(cqt_d); #endif return success; } int fmpq_reconstruct_fmpz_2(fmpq_t res, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D) { return _fmpq_reconstruct_fmpz_2(fmpq_numref(res), fmpq_denref(res), a, m, N, D); } flint-3.1.3/src/fmpq/reconstruct_fmpz_2_naive.c000066400000000000000000000030501461254215100215410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #define ROT(u,v,t) \ do { fmpz _t = *u; *u = *v; *v = *t; *t = _t; } while (0); int _fmpq_reconstruct_fmpz_2_naive(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D) { fmpz_t q, r, s, t; int success = 0; /* Quickly identify small integers */ if (fmpz_cmp(a, N) <= 0) { fmpz_set(n, a); fmpz_one(d); return 1; } fmpz_sub(n, a, m); if (fmpz_cmpabs(n, N) <= 0) { fmpz_one(d); return 1; } fmpz_init(q); fmpz_init(r); fmpz_init(s); fmpz_init(t); fmpz_set(r, m); fmpz_zero(s); fmpz_set(n, a); fmpz_one(d); while (fmpz_cmpabs(n, N) > 0) { fmpz_fdiv_q(q, r, n); fmpz_mul(t, q, n); fmpz_sub(t, r, t); ROT(r, n, t); fmpz_mul(t, q, d); fmpz_sub(t, s, t); ROT(s, d, t); } if (fmpz_sgn(d) < 0) { fmpz_neg(n, n); fmpz_neg(d, d); } if (fmpz_cmp(d, D) <= 0) { fmpz_gcd(t, n, d); success = fmpz_is_one(t); } fmpz_clear(q); fmpz_clear(r); fmpz_clear(s); fmpz_clear(t); return success; } flint-3.1.3/src/fmpq/set_cfrac.c000066400000000000000000000022451461254215100164650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_set_cfrac_divconquer(_fmpz_mat22_t M, const fmpz * c, slong n) { _fmpz_mat22_one(M); if (n < 32) { slong i; for (i = 0; i < n; i++) _fmpz_mat22_rmul_elem(M, c + i); } else { slong m = n / 2; _fmpz_mat22_t N; _fmpz_mat22_init(N); _fmpq_set_cfrac_divconquer(M, c, m); _fmpq_set_cfrac_divconquer(N, c + m, n - m); _fmpz_mat22_rmul(M, N); _fmpz_mat22_clear(N); } } void fmpq_set_cfrac(fmpq_t x, const fmpz * c, slong n) { _fmpz_mat22_t M; _fmpz_mat22_init(M); _fmpq_set_cfrac_divconquer(M, c, n); fmpz_swap(fmpq_numref(x), M->_11); fmpz_swap(fmpq_denref(x), M->_21); _fmpz_mat22_clear(M); FLINT_ASSERT(n <= 0 || fmpq_is_canonical(x)); } flint-3.1.3/src/fmpq/set_fmpz_frac.c000066400000000000000000000026051461254215100173560ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_set_fmpz_frac(fmpq_t res, const fmpz_t p, const fmpz_t q) { if (fmpz_is_zero(p)) { fmpq_zero(res); } else if (fmpz_is_pm1(q) || fmpz_is_pm1(p)) { if (fmpz_sgn(q) < 0) { fmpz_neg(fmpq_numref(res), p); fmpz_neg(fmpq_denref(res), q); } else { fmpz_set(fmpq_numref(res), p); fmpz_set(fmpq_denref(res), q); } } else { fmpz_t t; fmpz_init(t); fmpz_gcd(t, p, q); if (fmpz_is_one(t)) { fmpz_set(fmpq_numref(res), p); fmpz_set(fmpq_denref(res), q); } else { fmpz_divexact(fmpq_numref(res), p, t); fmpz_divexact(fmpq_denref(res), q, t); } if (fmpz_sgn(fmpq_denref(res)) < 0) { fmpz_neg(fmpq_numref(res), fmpq_numref(res)); fmpz_neg(fmpq_denref(res), fmpq_denref(res)); } fmpz_clear(t); } } flint-3.1.3/src/fmpq/set_si.c000066400000000000000000000017361461254215100160260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" void _fmpq_set_si(fmpz_t rnum, fmpz_t rden, slong p, ulong q) { if (q == 1 || p == 0) { fmpz_set_si(rnum, p); fmpz_one(rden); } else { ulong r = n_gcd(p < 0 ? (-(ulong) p) : (ulong) p, q); if (p < 0) { fmpz_set_ui(rnum, (-(ulong) p) / r); fmpz_neg(rnum, rnum); } else fmpz_set_si(rnum, p / r); fmpz_set_ui(rden, q / r); } } void fmpq_set_si(fmpq_t res, slong p, ulong q) { _fmpq_set_si(fmpq_numref(res), fmpq_denref(res), p, q); } flint-3.1.3/src/fmpq/set_str.c000066400000000000000000000012061461254215100162130ustar00rootroot00000000000000/* Copyright (C) 2018 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" int fmpq_set_str(fmpq_t x, const char *str, int base) { int ans; mpq_t copy; mpq_init(copy); ans = mpq_set_str(copy, (char *) str, base); if (ans == 0) fmpq_set_mpq(x, copy); mpq_clear(copy); return ans; } flint-3.1.3/src/fmpq/set_ui.c000066400000000000000000000015271461254215100160260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" void _fmpq_set_ui(fmpz_t rnum, fmpz_t rden, ulong p, ulong q) { if (q == 1 || p == 0) { fmpz_set_ui(rnum, p); fmpz_one(rden); } else { ulong r = n_gcd(p, q); fmpz_set_ui(rnum, p / r); fmpz_set_ui(rden, q / r); } } void fmpq_set_ui(fmpq_t res, ulong p, ulong q) { _fmpq_set_ui(fmpq_numref(res), fmpq_denref(res), p, q); } flint-3.1.3/src/fmpq/simplest_between.c000066400000000000000000000062451461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_simplest_between(fmpz_t mid_num, fmpz_t mid_den, const fmpz_t l_num, const fmpz_t l_den, const fmpz_t r_num, const fmpz_t r_den) { fmpz_t q, r; _fmpq_cfrac_list_t s; _fmpz_mat22_t M; _fmpq_ball_t x; FLINT_ASSERT(fmpz_sgn(l_den) > 0); FLINT_ASSERT(fmpz_sgn(r_den) > 0); FLINT_ASSERT(_fmpq_cmp(l_num, l_den, r_num, r_den) <= 0); fmpz_init(q); fmpz_init(r); _fmpq_cfrac_list_init(s); s->length = -1; /* no write */ _fmpz_mat22_init(M); _fmpz_mat22_one(M); _fmpq_ball_init(x); fmpz_set(x->left_num, l_num); fmpz_set(x->left_den, l_den); fmpz_set(x->right_num, r_num); fmpz_set(x->right_den, r_den); x->exact = 0; if (fmpz_cmp(x->left_num, x->left_den) > 0) { /* 1 < x */ _fmpq_ball_get_cfrac(s, M, 1, x); } else if (fmpz_sgn(x->left_num) > 0 && fmpz_cmp(x->right_num, x->right_den) < 0) { /* 0 < x < 1 */ fmpz_swap(x->left_den, x->right_num); fmpz_swap(x->left_num, x->right_den); _fmpq_ball_get_cfrac(s, M, 1, x); fmpz_zero(q); _fmpz_mat22_lmul_elem(M, q); } else { _fmpq_ball_t y; _fmpq_ball_init(y); y->exact = 0; fmpz_fdiv_qr(q, r, x->left_num, x->left_den); fmpz_set(y->right_num, x->left_den); fmpz_swap(y->right_den, r); fmpz_set(y->left_num, x->right_den); fmpz_set(y->left_den, x->right_num); fmpz_submul(y->left_den, x->right_den, q); if (_fmpq_ball_gt_one(y)) { _fmpq_ball_swap(x, y); _fmpq_ball_get_cfrac(s, M, 1, x); _fmpz_mat22_lmul_elem(M, q); } _fmpq_ball_clear(y); } fmpz_cdiv_q(q, x->left_num, x->left_den); FLINT_ASSERT(_fmpq_cmp_fmpz(x->right_num, x->right_den, q) >= 0); FLINT_ASSERT(M->det == 1 || M->det == -1); fmpz_swap(mid_num, M->_12); fmpz_addmul(mid_num, M->_11, q); fmpz_swap(mid_den, M->_22); fmpz_addmul(mid_den, M->_21, q); fmpz_clear(q); fmpz_clear(r); _fmpq_cfrac_list_clear(s); _fmpq_ball_clear(x); _fmpz_mat22_clear(M); FLINT_ASSERT(_fmpq_is_canonical(mid_num, mid_den)); return; } void fmpq_simplest_between(fmpq_t mid, const fmpq_t l, const fmpq_t r) { if (fmpq_cmp(l, r) <= 0) { _fmpq_simplest_between(fmpq_numref(mid), fmpq_denref(mid), fmpq_numref(l), fmpq_denref(l), fmpq_numref(r), fmpq_denref(r)); } else { _fmpq_simplest_between(fmpq_numref(mid), fmpq_denref(mid), fmpq_numref(r), fmpq_denref(r), fmpq_numref(l), fmpq_denref(l)); } } flint-3.1.3/src/fmpq/sub.c000066400000000000000000000125471461254215100153330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_sub(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s) { fmpz_t g, a, b, t, u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && !COEFF_IS_MPZ(*r) && !COEFF_IS_MPZ(*s)) { _fmpq_add_small(rnum, rden, *p, *q, -(*r), *s); return; } /* Same denominator */ if (fmpz_equal(q, s)) { fmpz_sub(rnum, p, r); /* Both are integers */ if (fmpz_is_one(q)) { fmpz_set(rden, q); } else { fmpz_init(g); fmpz_gcd(g, rnum, q); if (fmpz_is_one(g)) { fmpz_set(rden, q); } else { fmpz_divexact(rnum, rnum, g); fmpz_divexact(rden, q, g); } fmpz_clear(g); } return; } /* p/q is an integer */ if (fmpz_is_one(q)) { fmpz_init(t); fmpz_mul(t, p, s); fmpz_sub(rnum, t, r); fmpz_set(rden, s); fmpz_clear(t); return; } /* r/s is an integer */ if (fmpz_is_one(s)) { fmpz_init(t); fmpz_mul(t, r, q); fmpz_sub(rnum, p, t); fmpz_set(rden, q); fmpz_clear(t); return; } fmpz_init(g); fmpz_gcd(g, q, s); if (fmpz_is_one(g)) { fmpz_init(t); fmpz_init(u); fmpz_mul(t, p, s); fmpz_mul(u, q, r); fmpz_sub(rnum, t, u); fmpz_mul(rden, q, s); fmpz_clear(t); fmpz_clear(u); } else { fmpz_init(a); fmpz_init(b); fmpz_init(t); fmpz_init(u); fmpz_divexact(a, q, g); fmpz_divexact(b, s, g); fmpz_mul(t, p, b); fmpz_mul(u, r, a); fmpz_sub(rnum, t, u); fmpz_gcd(t, rnum, g); if (fmpz_is_one(t)) { fmpz_mul(rden, q, b); } else { fmpz_divexact(rnum, rnum, t); fmpz_divexact(g, q, t); fmpz_mul(rden, g, b); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(t); fmpz_clear(u); } fmpz_clear(g); } void fmpq_sub(fmpq_t res, const fmpq_t op1, const fmpq_t op2) { _fmpq_sub(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } void _fmpq_sub_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r) { fmpz_t u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && !COEFF_IS_MPZ(*r)) { _fmpq_add_small(rnum, rden, *p, *q, -(*r), 1); return; } /* both are integers */ if (fmpz_is_one(q)) { fmpz_sub(rnum, p, r); fmpz_set(rden, q); return; } /* We want to compute p/q - r/1 where the inputs are already in canonical form. Note (p - q*r, q) is in canonical form. */ fmpz_init(u); fmpz_mul(u, q, r); fmpz_sub(rnum, p, u); fmpz_set(rden, q); fmpz_clear(u); } void fmpq_sub_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c) { _fmpq_sub_fmpz(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } void _fmpq_sub_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r) { fmpz_t u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && r >= COEFF_MIN && r <= COEFF_MAX) { _fmpq_add_small(rnum, rden, *p, *q, -r, 1); return; } /* both are integers */ if (fmpz_is_one(q)) { if (r >= 0) fmpz_sub_ui(rnum, p, r); else fmpz_add_ui(rnum, p, -r); fmpz_set(rden, q); return; } /* We want to compute p/q - r/1 where the inputs are already in canonical form. Note (p - q*r, q) is in canonical form. */ fmpz_init(u); fmpz_mul_si(u, q, r); fmpz_sub(rnum, p, u); fmpz_set(rden, q); fmpz_clear(u); } void fmpq_sub_si(fmpq_t res, const fmpq_t op1, slong c) { _fmpq_sub_si(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } void _fmpq_sub_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r) { fmpz_t u; if (!COEFF_IS_MPZ(*p) && !COEFF_IS_MPZ(*q) && r <= COEFF_MAX) { _fmpq_add_small(rnum, rden, *p, *q, -(slong) r, 1); return; } /* both are integers */ if (fmpz_is_one(q)) { fmpz_sub_ui(rnum, p, r); fmpz_set(rden, q); return; } /* We want to compute p/q - r/1 where the inputs are already in canonical form. Note (p - q*r, q) is in canonical form. */ fmpz_init(u); fmpz_mul_ui(u, q, r); fmpz_sub(rnum, p, u); fmpz_set(rden, q); fmpz_clear(u); } void fmpq_sub_ui(fmpq_t res, const fmpq_t op1, ulong c) { _fmpq_sub_ui(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), c); } flint-3.1.3/src/fmpq/submul.c000066400000000000000000000017101461254215100160370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void _fmpq_submul(fmpz_t rnum, fmpz_t rden, const fmpz_t op1num, const fmpz_t op1den, const fmpz_t op2num, const fmpz_t op2den) { fmpz_t u, v; fmpz_init(u); fmpz_init(v); _fmpq_mul(u, v, op1num, op1den, op2num, op2den); _fmpq_sub(rnum, rden, rnum, rden, u, v); fmpz_clear(u); fmpz_clear(v); } void fmpq_submul(fmpq_t res, const fmpq_t op1, const fmpq_t op2) { _fmpq_submul(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } flint-3.1.3/src/fmpq/test/000077500000000000000000000000001461254215100153445ustar00rootroot00000000000000flint-3.1.3/src/fmpq/test/main.c000066400000000000000000000067501461254215100164440ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* For t-get_mpfr.c */ #include #include /* Include functions *********************************************************/ #include "t-abs.c" #include "t-add.c" #include "t-add_fmpz.c" #include "t-addmul.c" #include "t-add_si.c" #include "t-add_ui.c" #include "t-canonicalise.c" #include "t-cfrac_bound.c" #include "t-cmp.c" #include "t-dedekind_sum.c" #include "t-div_2exp.c" #include "t-div.c" #include "t-div_fmpz.c" #include "t-equal_si_ui.c" #include "t-farey_neighbors.c" #include "t-gcd_cofactors.c" #include "t-get_cfrac.c" #include "t-get_d.c" #include "t-get_mpfr.c" #include "t-get_set_str.c" #include "t-harmonic_ui.c" #include "t-height.c" #include "t-init_set_readonly.c" #include "t-inv.c" #include "t-mpq_init_set_readonly.c" #include "t-mul_2exp.c" #include "t-mul.c" #include "t-mul_fmpz.c" #include "t-mul_si.c" #include "t-mul_ui.c" #include "t-next_calkin_wilf.c" #include "t-next_minimal.c" #include "t-one.c" #include "t-pow_si.c" #include "t-randtest.c" #include "t-reconstruct_fmpz_2.c" #include "t-reconstruct_fmpz.c" #include "t-set_cfrac.c" #include "t-set_fmpz_frac.c" #include "t-set_si.c" #include "t-set_ui.c" #include "t-simplest_between.c" #include "t-sub.c" #include "t-sub_fmpz.c" #include "t-submul.c" #include "t-sub_si.c" #include "t-sub_ui.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpq_abs), TEST_FUNCTION(fmpq_add), TEST_FUNCTION(fmpq_add_fmpz), TEST_FUNCTION(fmpq_addmul), TEST_FUNCTION(fmpq_add_si), TEST_FUNCTION(fmpq_add_ui), TEST_FUNCTION(fmpq_canonicalise), TEST_FUNCTION(fmpq_cfrac_bound), TEST_FUNCTION(fmpq_cmp), TEST_FUNCTION(fmpq_dedekind_sum), TEST_FUNCTION(fmpq_div_2exp), TEST_FUNCTION(fmpq_div), TEST_FUNCTION(fmpq_div_fmpz), TEST_FUNCTION(fmpq_equal_si_ui), TEST_FUNCTION(fmpq_farey_neighbors), TEST_FUNCTION(fmpq_gcd_cofactors), TEST_FUNCTION(fmpq_get_cfrac), TEST_FUNCTION(fmpq_get_d), TEST_FUNCTION(fmpq_get_mpfr), TEST_FUNCTION(fmpq_get_set_str), TEST_FUNCTION(fmpq_harmonic_ui), TEST_FUNCTION(fmpq_height), TEST_FUNCTION(fmpq_init_set_readonly), TEST_FUNCTION(fmpq_inv), TEST_FUNCTION(fmpq_mpq_init_set_readonly), TEST_FUNCTION(fmpq_mul_2exp), TEST_FUNCTION(fmpq_mul), TEST_FUNCTION(fmpq_mul_fmpz), TEST_FUNCTION(fmpq_mul_si), TEST_FUNCTION(fmpq_mul_ui), TEST_FUNCTION(fmpq_next_calkin_wilf), TEST_FUNCTION(fmpq_next_minimal), TEST_FUNCTION(fmpq_one), TEST_FUNCTION(fmpq_pow_si), TEST_FUNCTION(fmpq_randtest), TEST_FUNCTION(fmpq_reconstruct_fmpz_2), TEST_FUNCTION(fmpq_reconstruct_fmpz), TEST_FUNCTION(fmpq_set_cfrac), TEST_FUNCTION(fmpq_set_fmpz_frac), TEST_FUNCTION(fmpq_set_si), TEST_FUNCTION(fmpq_set_ui), TEST_FUNCTION(fmpq_simplest_between), TEST_FUNCTION(fmpq_sub), TEST_FUNCTION(fmpq_sub_fmpz), TEST_FUNCTION(fmpq_submul), TEST_FUNCTION(fmpq_sub_si), TEST_FUNCTION(fmpq_sub_ui) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpq/test/t-abs.c000066400000000000000000000026121461254215100165170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Tom Bachmann (adapt for fmpq) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_abs, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a, b; mpq_t c, d; fmpq_init(a); fmpq_init(b); mpq_init(c); mpq_init(d); fmpq_randtest(a, state, 200); fmpq_get_mpq(c, a); if (n_randint(state, 2)) /* test aliasing */ { fmpq_set(b, a); fmpq_abs(b, b); } else { fmpq_abs(b, a); } mpq_abs(c, c); fmpq_get_mpq(d, b); result = (mpq_cmp(c, d) == 0) && fmpq_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Qd, d = %Qd\n", c, d); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); mpq_clear(c); mpq_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-add.c000066400000000000000000000035511461254215100165050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_add, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a, b, c; mpq_t d, e, f, g; int aliasing; fmpq_init(a); fmpq_init(b); fmpq_init(c); mpq_init(d); mpq_init(e); mpq_init(f); mpq_init(g); fmpq_randtest(a, state, 200); fmpq_randtest(b, state, 200); fmpq_get_mpq(d, a); fmpq_get_mpq(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpq_add(c, a, b); } else if (aliasing == 1) { fmpq_set(a, b); mpq_set(d, e); fmpq_add(c, a, a); } else if (aliasing == 2) { fmpq_set(c, a); fmpq_add(c, c, b); } else { fmpq_set(c, b); fmpq_add(c, a, c); } mpq_add(f, d, e); fmpq_get_mpq(g, c); result = (mpq_cmp(f, g) == 0) && fmpq_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Qd, e = %Qd, f = %Qd, g = %Qd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); mpq_clear(d); mpq_clear(e); mpq_clear(f); mpq_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-add_fmpz.c000066400000000000000000000040121461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_add_fmpz, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a; fmpz_t b; fmpq_t c, d, e, f; int aliasing; fmpq_init(a); fmpz_init(b); fmpq_init(c); fmpq_init(d); fmpq_init(e); fmpq_init(f); fmpq_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpq_set(d, a); fmpq_set_fmpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpq_add_fmpz(c, a, b); } else if (aliasing == 1) { fmpq_set_fmpz(e, fmpq_numref(a)); fmpq_add_fmpz(c, a, fmpq_numref(a)); } else if (aliasing == 2) { fmpq_set(c, a); fmpq_add_fmpz(c, c, b); } else { fmpq_set_fmpz(c, b); fmpq_add_fmpz(c, a, fmpq_numref(c)); } fmpq_add(f, d, e); result = (fmpq_cmp(f, c) == 0) && fmpq_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); printf("c = "); fmpq_print(c); printf(", d = "); fmpq_print(d); printf(", e = "); fmpq_print(e); printf(", f = "); fmpq_print(f); printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpz_clear(b); fmpq_clear(c); fmpq_clear(d); fmpq_clear(e); fmpq_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-add_si.c000066400000000000000000000032761461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_add_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a; slong b; fmpq_t c, d, e, f; int aliasing; fmpq_init(a); fmpq_init(c); fmpq_init(d); fmpq_init(e); fmpq_init(f); fmpq_randtest(a, state, 200); b = z_randtest(state); fmpq_set(d, a); fmpq_set_si(e, b, 1); aliasing = n_randint(state, 2); if (aliasing == 0) { fmpq_add_si(c, a, b); } else { fmpq_set(c, a); fmpq_add_si(c, c, b); } fmpq_add(f, d, e); result = (fmpq_cmp(f, c) == 0) && fmpq_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); printf("c = "); fmpq_print(c); printf(", d = "); fmpq_print(d); printf(", e = "); fmpq_print(e); printf(", f = "); fmpq_print(f); printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(c); fmpq_clear(d); fmpq_clear(e); fmpq_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-add_ui.c000066400000000000000000000032531461254215100172010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_add_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a; ulong b; fmpq_t c, d, e, f; int aliasing; fmpq_init(a); fmpq_init(c); fmpq_init(d); fmpq_init(e); fmpq_init(f); fmpq_randtest(a, state, 200); b = n_randtest(state); fmpq_set(d, a); fmpq_set_ui(e, b, 1); aliasing = n_randint(state, 2); if (aliasing == 0) { fmpq_add_ui(c, a, b); } else { fmpq_set(c, a); fmpq_add_ui(c, c, b); } fmpq_add(f, d, e); result = (fmpq_cmp(f, c) == 0) && fmpq_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); printf("c = "); fmpq_print(c); printf(", d = "); fmpq_print(d); printf(", e = "); fmpq_print(e); printf(", f = "); fmpq_print(f); printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(c); fmpq_clear(d); fmpq_clear(e); fmpq_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-addmul.c000066400000000000000000000043121461254215100172170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" void mpq_addmul(mpq_t x, mpq_t y, mpq_t z) { mpq_t t; mpq_init(t); mpq_mul(t, y, z); mpq_add(x, x, t); mpq_clear(t); } TEST_FUNCTION_START(fmpq_addmul, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a, b, c; mpq_t d, e, f, g; int aliasing; fmpq_init(a); fmpq_init(b); fmpq_init(c); mpq_init(d); mpq_init(e); mpq_init(f); mpq_init(g); fmpq_randtest(a, state, 200); fmpq_randtest(b, state, 200); fmpq_randtest(c, state, 200); if (n_randint(state, 10) == 0) fmpq_submul(c, a, b); fmpq_get_mpq(d, a); fmpq_get_mpq(e, b); fmpq_get_mpq(f, c); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpq_addmul(c, a, b); } else if (aliasing == 1) { fmpq_set(a, b); mpq_set(d, e); fmpq_addmul(c, a, a); } else if (aliasing == 2) { fmpq_set(c, a); mpq_set(f, d); fmpq_addmul(c, c, b); } else { fmpq_set(c, b); mpq_set(f, e); fmpq_addmul(c, a, c); } mpq_addmul(f, d, e); fmpq_get_mpq(g, c); result = (mpq_cmp(f, g) == 0) && fmpq_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Qd, e = %Qd, f = %Qd, g = %Qd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); mpq_clear(d); mpq_clear(e); mpq_clear(f); mpq_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-canonicalise.c000066400000000000000000000044521461254215100204060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_canonicalise, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t x; fmpz_t mult; fmpq_init(x); fmpq_randtest(x, state, 200); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: expected fmpq_randtest output to be canonical\n"); fmpq_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_init(mult); fmpz_randtest_not_zero(mult, state, 200); fmpz_add_ui(mult, mult, UWORD(1)); fmpz_mul(&x->num, &x->num, mult); fmpz_mul(&x->den, &x->den, mult); if (fmpq_is_canonical(x)) { flint_printf("FAIL: expected fmpq_is_canonical to detect common factor\n"); fmpq_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_canonicalise(x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical after calling fmpq_canonicalise\n"); fmpq_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_neg(&x->den, &x->den); if (fmpq_is_canonical(x)) { flint_printf("FAIL: negative denominator reported as being canonical\n"); fmpq_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_canonicalise(x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical after calling fmpq_canonicalise\n"); fmpq_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(mult); fmpq_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-cfrac_bound.c000066400000000000000000000027161461254215100202240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_vec.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_cfrac_bound, state) { int i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t x, r; fmpz * c; slong n, bound; fmpq_init(x); fmpq_init(r); /* Test worst case (quotient of Fibonacci numbers) */ if (n_randint(state, 50) == 1) { slong v = 1 + n_randint(state, 1000); fmpz_fib_ui(fmpq_numref(x), v + 1); fmpz_fib_ui(fmpq_denref(x), v); } else { fmpq_randtest(x, state, 1 + n_randint(state, 1000)); } bound = fmpq_cfrac_bound(x); c = _fmpz_vec_init(bound + 10); n = fmpq_get_cfrac(c, r, x, bound); if (n > bound) { flint_printf("FAIL: length=%wd > bound=%wd\n", n, bound); fflush(stdout); flint_abort(); } _fmpz_vec_clear(c, bound + 10); fmpq_clear(x); fmpq_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-cmp.c000066400000000000000000000043631461254215100165360ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_cmp, state) { int i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t x, y; mpq_t X, Y; int c1, c2; int type; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); type = n_randint(state, 4); switch (type) { case 0: fmpq_randtest(y, state, 200); c1 = fmpq_cmp(x, y); break; case 1: fmpz_randtest(fmpq_denref(y), state, 200); c1 = fmpq_cmp_fmpz(x, fmpq_numref(y)); break; case 2: { slong ys = z_randtest(state); c1 = fmpq_cmp_si(x, ys); fmpz_set_si(fmpq_numref(y), ys); break; } case 3: { ulong ys = n_randtest(state); c1 = fmpq_cmp_ui(x, ys); fmpz_set_ui(fmpq_numref(y), ys); break; } default: FLINT_UNREACHABLE; } fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); c2 = mpq_cmp(X, Y); if (FLINT_SGN(c1) != FLINT_SGN(c2)) { flint_throw(FLINT_TEST_FAIL, "x = %{fmpq}\n" "y = %{fmpq}\n" "%s(x, y) = %d\n" "cmp(X, Y) = %d\n", x, y, type == 0 ? "cmp" : type == 1 ? "cmp_fmpz" : type == 2 ? "cmp_si" : "cmp_ui", c1, c2); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-dedekind_sum.c000066400000000000000000000176021461254215100204120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" /* The results in the following random test cases were computed with the naive implementation. Doing a live comparison with large values against the naive implementation would take too much time. */ static const slong testdata[][4] = { /* h, k, p/q */ {WORD(20816815), WORD(29229), WORD(-10669), WORD(87687)}, {WORD(-481962612), WORD(709105), WORD(-910639), WORD(141821)}, {WORD(-70965), WORD(3384), WORD(1785), WORD(752)}, {WORD(1899905), WORD(6657), WORD(-43795), WORD(5706)}, {WORD(-1893), WORD(511167), WORD(-3411568), WORD(170389)}, {WORD(1417295), WORD(10180), WORD(3543), WORD(4072)}, {WORD(-1149), WORD(9350), WORD(6971), WORD(9350)}, {WORD(-15520), WORD(22977640), WORD(-70331425), WORD(574441)}, {WORD(3339), WORD(9873153), WORD(270746882), WORD(1097017)}, {WORD(470645896), WORD(71754), WORD(-21713), WORD(107631)}, {WORD(1153), WORD(1332403), WORD(258755243), WORD(2664806)}, {WORD(-501576), WORD(292801), WORD(269095), WORD(292801)}, {WORD(1861), WORD(34440), WORD(-723059), WORD(206640)}, {WORD(-4278761), WORD(239321), WORD(791947), WORD(239321)}, {WORD(9414763), WORD(30776409), WORD(-93285463), WORD(92329227)}, {WORD(4872687), WORD(2199), WORD(146), WORD(733)}, {WORD(-22349505), WORD(60581653), WORD(27694241), WORD(60581653)}, {WORD(85739724), WORD(9289), WORD(961), WORD(2654)}, {WORD(-5616), WORD(124023), WORD(-31447), WORD(41341)}, {WORD(99382204), WORD(1378843), WORD(-2537405), WORD(2757686)}, {WORD(1903), WORD(15842), WORD(102), WORD(89)}, {WORD(-907226), WORD(5818), WORD(5608), WORD(2909)}, {WORD(-948920), WORD(4768), WORD(-4815), WORD(1192)}, {WORD(-352220914), WORD(15390287), WORD(-171358081), WORD(30780574)}, {WORD(-159206), WORD(3028284), WORD(12921745), WORD(4542426)}, {WORD(61951448), WORD(1624), WORD(-341), WORD(406)}, {WORD(-49167), WORD(2092), WORD(-32915), WORD(4184)}, {WORD(-20878222), WORD(586303210), WORD(-530581301), WORD(293151605)}, {WORD(-1435637), WORD(3483), WORD(-4787), WORD(20898)}, {WORD(-1129797), WORD(171620), WORD(238211), WORD(68648)}, {WORD(-177095), WORD(2914), WORD(1132), WORD(1457)}, {WORD(-343227551), WORD(1509), WORD(-3289), WORD(4527)}, {WORD(57497376), WORD(1351), WORD(373), WORD(2702)}, {WORD(3350543), WORD(5771893), WORD(-51196457), WORD(5771893)}, {WORD(-44408), WORD(1670), WORD(367), WORD(1670)}, {WORD(-4139), WORD(59959), WORD(-286689), WORD(119918)}, {WORD(7397588), WORD(16695), WORD(-41627), WORD(20034)}, {WORD(-78900791), WORD(10792), WORD(-30905), WORD(21584)}, {WORD(-1204294), WORD(10134), WORD(-8945), WORD(30402)}, {WORD(27649424), WORD(57014291), WORD(731583513), WORD(114028582)}, {WORD(3275043), WORD(436410815), WORD(2018428417), WORD(174564326)}, #if FLINT64 /* skip on 32 bit only because of the literals */ {WORD(61247), WORD(81381215), WORD(3622491319), WORD(32552486)}, {WORD(-52118), WORD(125095621), WORD(-24931204413), WORD(125095621)}, {WORD(201446493), WORD(951783261), WORD(2467429915), WORD(634522174)}, {WORD(176112), WORD(72187934), WORD(2692844825), WORD(72187934)}, {WORD(1272), WORD(8722219), WORD(9972821075), WORD(17444438)}, #endif {0, 0, 0, 0} }; TEST_FUNCTION_START(fmpq_dedekind_sum, state) { fmpz_t hh, kk; fmpq_t s1, s2; slong i, h, k; fmpz_init(hh); fmpz_init(kk); fmpq_init(s1); fmpq_init(s2); for (k = -40; k < 40; k++) { for (h = -40; h < 40; h++) { fmpz_set_si(hh, h); fmpz_set_si(kk, k); fmpq_dedekind_sum(s1, hh, kk); fmpq_dedekind_sum_naive(s2, hh, kk); if (!fmpq_equal(s1, s2)) { flint_printf("FAIL:\n"); flint_printf("s(%wd,%wd)\n", h, k); flint_printf("s1: "); fmpq_print(s1); flint_printf("\n"); flint_printf("s2: "); fmpq_print(s2); flint_printf("\n"); fflush(stdout); flint_abort(); } } } /* Test large values, 10-30 bits */ for (i = 0; testdata[i][0] != 0; i++) { h = testdata[i][0]; k = testdata[i][1]; fmpz_set_si(hh, h); fmpz_set_si(kk, k); fmpq_dedekind_sum(s1, hh, kk); fmpz_set_si(fmpq_numref(s2), testdata[i][2]); fmpz_set_si(fmpq_denref(s2), testdata[i][3]); if (!fmpq_equal(s1, s2)) { flint_printf("FAIL:\n"); flint_printf("s(%wd,%wd)\n", h, k); flint_printf("s1: "); fmpq_print(s1); flint_printf("\n"); flint_printf("s2: "); fmpq_print(s2); flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check a large value computed with Pari */ fmpz_set_ui(hh, 1); fmpz_mul_2exp(hh, hh, 1000); fmpz_add_ui(hh, hh, 1); fmpz_set_ui(kk, 1); fmpz_mul_2exp(kk, kk, 1001); fmpz_add_ui(kk, kk, 1); fmpq_dedekind_sum(s1, hh, kk); if ((fmpz_fdiv_ui(fmpq_numref(s1), 1000000000) != 906445312) || (fmpz_fdiv_ui(fmpq_denref(s1), 1000000000) != 8416259)) { flint_printf("Wrong large value:\n"); fmpq_print(s1); flint_printf("\n"); fflush(stdout); flint_abort(); } /* check reciprocity law 12*b*c(S(b,c) + S(c,b)) = (b - c)^2 - b*c + 1 */ for (i = 0; i < 500*flint_test_multiplier(); i++) { fmpq_t x, r1, r2; fmpz_t b1, c1, b2, c2, t, s; fmpq_init(x); fmpq_init(r1); fmpq_init(r2); fmpz_init(b1); fmpz_init(c1); fmpz_init(b2); fmpz_init(c2); fmpz_init(t); fmpz_init(s); if (i % 2) { fmpq_randtest_not_zero(x, state, 2000); fmpq_abs(x, x); } else { fmpz * v; h = 1 + n_randint(state, 100); v = _fmpz_vec_init(h); for (k = 0; k < h; k++) { fmpz_randtest_unsigned(v + k, state, 3*FLINT_BITS); fmpz_add_ui(v + k, v + k, 1); } fmpq_set_cfrac(x, v, h); _fmpz_vec_clear(v, h); } /* inflate one input */ fmpz_randtest_unsigned(t, state, 100); fmpz_add_ui(t, t, 1); fmpz_mul(b1, fmpq_numref(x), t); fmpz_mul(c1, fmpq_denref(x), t); /* inflate the reciprocal input */ fmpz_randtest_unsigned(t, state, 100); fmpz_add_ui(t, t, 1); fmpz_mul(b2, fmpq_denref(x), t); fmpz_mul(c2, fmpq_numref(x), t); /* rhs */ fmpz_mul(t, fmpq_numref(x), fmpq_denref(x)); fmpz_sub(s, fmpq_numref(x), fmpq_denref(x)); fmpz_mul(s, s, s); fmpz_sub(s, s, t); fmpz_add_ui(s, s, 1); /* lhs */ fmpq_dedekind_sum(r1, b1, c1); fmpq_dedekind_sum(r2, b2, c2); fmpq_add(r1, r1, r2); fmpz_mul_ui(t, t, 12); fmpq_mul_fmpz(r1, r1, t); if (!fmpz_is_one(fmpq_denref(r1)) || !fmpz_equal(fmpq_numref(r1), s)) { flint_printf("FAIL:\n"); flint_printf("check reciprocity law i = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(r1); fmpq_clear(r2); fmpz_clear(b1); fmpz_clear(c1); fmpz_clear(b2); fmpz_clear(c2); fmpz_clear(t); fmpz_clear(s); } fmpz_clear(hh); fmpz_clear(kk); fmpq_clear(s1); fmpq_clear(s2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-div.c000066400000000000000000000036071461254215100165410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_div, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a, b, c; mpq_t d, e, f, g; int aliasing; fmpq_init(a); fmpq_init(b); fmpq_init(c); mpq_init(d); mpq_init(e); mpq_init(f); mpq_init(g); fmpq_randtest(a, state, 200); do {fmpq_randtest(b, state, 200);} while (fmpq_is_zero(b)); fmpq_get_mpq(d, a); fmpq_get_mpq(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpq_div(c, a, b); } else if (aliasing == 1) { fmpq_set(a, b); mpq_set(d, e); fmpq_div(c, a, a); } else if (aliasing == 2) { fmpq_set(c, a); fmpq_div(c, c, b); } else { fmpq_set(c, b); fmpq_div(c, a, c); } mpq_div(f, d, e); fmpq_get_mpq(g, c); result = (mpq_cmp(f, g) == 0) && fmpq_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Qd, e = %Qd, f = %Qd, g = %Qd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); mpq_clear(d); mpq_clear(e); mpq_clear(f); mpq_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-div_2exp.c000066400000000000000000000036661461254215100175040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_div_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a, b; mpq_t c, d, e; flint_bitcnt_t exp; int aliasing; fmpq_init(a); fmpq_init(b); mpq_init(c); mpq_init(d); mpq_init(e); fmpq_randtest(a, state, 200); switch (n_randint(state, 5)) { case 0: fmpz_mul_2exp(fmpq_numref(a), fmpq_numref(a), n_randint(state, 200)); fmpq_canonicalise(a); break; case 1: fmpz_mul_2exp(fmpq_denref(a), fmpq_denref(a), n_randint(state, 200)); fmpq_canonicalise(a); break; } fmpq_get_mpq(c, a); exp = n_randint(state, 200); aliasing = n_randint(state, 2); if (aliasing == 0) { fmpq_div_2exp(b, a, exp); } else { fmpq_set(b, a); fmpq_div_2exp(b, b, exp); } mpq_div_2exp(d, c, exp); fmpq_get_mpq(e, b); result = (mpq_cmp(d, e) == 0) && fmpq_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Qd, d = %Qd, e = %Qd, exp = %Md\n", c, d, e, exp); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); mpq_clear(c); mpq_clear(d); mpq_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-div_fmpz.c000066400000000000000000000043161461254215100175730ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_div_fmpz, state) { int i, result; /* Aliasing x = x/z */ for (i = 0; i < 10000; i++) { fmpq_t x, y; fmpz_t z; fmpq_init(x); fmpq_init(y); fmpz_init(z); fmpq_randtest(x, state, 200); while (fmpz_is_zero(z)) fmpz_randtest(z, state, 200); fmpq_div_fmpz(y, x, z); fmpq_div_fmpz(x, x, z); result = (fmpq_is_canonical(x) && fmpq_is_canonical(y) && fmpq_equal(x, y)); if (!result) { flint_printf("FAIL (alias):\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); flint_printf("z = "), fmpz_print(z), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(z); } /* Compare with fmpq_div */ for (i = 0; i < 10000; i++) { fmpq_t x, y, z; fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpq_randtest(x, state, 200); while (fmpq_is_zero(z)) fmpz_randtest(fmpq_numref(z), state, 200); fmpq_div_fmpz(y, x, fmpq_numref(z)); fmpq_div(x, x, z); result = (fmpq_is_canonical(x) && fmpq_is_canonical(y) && fmpq_equal(x, y)); if (!result) { flint_printf("FAIL (cmp):\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-equal_si_ui.c000066400000000000000000000057411461254215100202570ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_equal_si_ui, state) { int i; int res; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_t x; slong y_si = 0; /* Silence warnings about maybe uninitialized */ ulong y_ui = 0; int type; fmpq_init(x); type = n_randint(state, 4); if (type == 0) { /* Let x be proper rational, y is slong */ do { fmpq_randtest(x, state, 200); } while (x->den == WORD(1)); y_si = z_randtest(state); /* Then x != y */ res = (fmpq_equal_si(x, y_si) == 0); } else if (type == 1) { /* Let x be integer, y is slong */ fmpz_one(fmpq_denref(x)); y_si = z_randtest(state); if (n_randint(state, 2)) { /* Random numerator */ fmpz_randtest(fmpq_numref(x), state, 200); res = (fmpq_equal_si(x, y_si) == fmpz_equal_si(fmpq_numref(x), y_si)); } else { /* Numerator of x equals to y */ fmpz_set_si(fmpq_numref(x), y_si); res = (fmpq_equal_si(x, y_si) == 1); } } else if (type == 2) { /* Let x be proper rational, y is ulong */ do { fmpq_randtest(x, state, 200); } while (x->den == WORD(1)); y_ui = n_randtest(state); /* Then x != y */ res = (fmpq_equal_ui(x, y_ui) == 0); } else { /* Let x be integer, y is ulong */ fmpz_one(fmpq_denref(x)); y_ui = n_randtest(state); if (n_randint(state, 2)) { /* Random numerator */ fmpz_randtest(fmpq_numref(x), state, 200); res = (fmpq_equal_ui(x, y_ui) == fmpz_equal_ui(fmpq_numref(x), y_ui)); } else { /* Numerator of x equals to y */ fmpz_set_ui(fmpq_numref(x), y_ui); res = (fmpq_equal_ui(x, y_ui) == 1); } } if (!res) { flint_printf("FAIL\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ntype = %d", type); if (type <= 1) flint_printf("y_si = %wd\n", y_si); else flint_printf("y_ui = %wu\n", y_ui); fflush(stdout); flint_abort(); } fmpq_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-farey_neighbors.c000066400000000000000000000044521461254215100211240ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_farey_neighbors, state) { slong i, q, steps; /* walk from -2 to 2 with a known number of steps */ for (q = 1; q <= 4 * flint_test_multiplier(); q++) { fmpq_t s, t, cur, left, right; fmpz_t Q; fmpq_init(s); fmpq_init(t); fmpq_init(cur); fmpq_init(left); fmpq_init(right); steps = 0; for (i = 1; i <= q; i++) steps += 4*n_euler_phi(i); fmpz_init_set_ui(Q, q); fmpq_set_si(cur, -2, 1); for (i = 0; i < steps; i++) { fmpq_farey_neighbors(left, right, cur, Q); fmpq_sub(t, cur, left); fmpz_one(fmpq_numref(s)); fmpz_mul(fmpq_denref(s), fmpq_denref(left), fmpq_denref(cur)); if (!fmpq_equal(s, t)) { flint_printf("FAIL:\n"); flint_printf("check left neighbor i = %wd, q = %wd\n", i, q); fflush(stdout); flint_abort(); } fmpq_sub(t, right, cur); fmpz_one(fmpq_numref(s)); fmpz_mul(fmpq_denref(s), fmpq_denref(right), fmpq_denref(cur)); if (!fmpq_equal(s, t)) { flint_printf("FAIL:\n"); flint_printf("check right neighbor i = %wd, q = %wd\n", i, q); fflush(stdout); flint_abort(); } fmpq_swap(cur, right); } fmpq_set_si(right, 2, 1); if (!fmpq_equal(cur, right)) { flint_printf("FAIL:\n"); flint_printf("check end q = %wd\n", q); fflush(stdout); flint_abort(); } fmpz_clear(Q); fmpq_clear(s); fmpq_clear(t); fmpq_clear(cur); fmpq_clear(left); fmpq_clear(right); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-gcd_cofactors.c000066400000000000000000000045351461254215100205600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_gcd_cofactors, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t g, a, b, g1, t1, t2; fmpz_t abar, bbar, abar1, bbar1; fmpq_init(g); fmpq_init(a); fmpq_init(b); fmpq_init(g1); fmpq_init(t1); fmpq_init(t2); fmpz_init(abar); fmpz_init(bbar); fmpz_init(abar1); fmpz_init(bbar1); fmpq_randtest(g, state, 200); fmpq_randtest(a, state, 200); fmpq_randtest(b, state, 200); fmpq_gcd_cofactors(g, abar, bbar, a, b); fmpq_gcd(g1, a, b); if (!fmpq_equal(g, g1)) { flint_printf("FAIL: check gcd\n"); fflush(stdout); flint_abort(); } fmpq_mul_fmpz(t1, g, abar); fmpq_mul_fmpz(t2, g, bbar); if (!fmpq_equal(t1, a) || !fmpq_equal(t2, b)) { flint_printf("FAIL: check cofactors\n"); fflush(stdout); flint_abort(); } fmpq_set(t1, a); fmpq_gcd_cofactors(t1, abar1, bbar1, t1, b); if (!fmpq_equal(t1, g) || !fmpz_equal(abar1, abar) ||!fmpz_equal(bbar1, bbar)) { flint_printf("FAIL: check aliasing first argument\n"); fflush(stdout); flint_abort(); } fmpq_set(t1, b); fmpq_gcd_cofactors(t1, abar1, bbar1, a, t1); if (!fmpq_equal(t1, g) || !fmpz_equal(abar1, abar) ||!fmpz_equal(bbar1, bbar)) { flint_printf("FAIL: check aliasing second argument\n"); fflush(stdout); flint_abort(); } fmpq_clear(g); fmpq_clear(a); fmpq_clear(b); fmpq_clear(g1); fmpq_clear(t1); fmpq_clear(t2); fmpz_clear(abar); fmpz_clear(bbar); fmpz_clear(abar1); fmpz_clear(bbar1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-get_cfrac.c000066400000000000000000000046121461254215100176710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_get_cfrac, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t x, r; fmpz *c1, *c2; slong k, n1, n2, bound; fmpq_init(x); fmpq_init(r); if (i % 2) { fmpq_randtest(x, state, 1 + n_randint(state, 1000)); bound = fmpq_cfrac_bound(x); c1 = _fmpz_vec_init(bound); } else { bound = 1 + n_randint(state, 100); c1 = _fmpz_vec_init(bound); fmpz_randtest(c1 + 0, state, 2*FLINT_BITS); for (k = 1; k < bound; k++) { fmpz_randtest_unsigned(c1 + k, state, 3*FLINT_BITS); fmpz_add_ui(c1 + k, c1 + k, 1); } fmpq_set_cfrac(x, c1, bound); } c2 = _fmpz_vec_init(bound); n1 = fmpq_get_cfrac(c1, r, x, bound); if (!fmpq_is_zero(r)) { flint_printf("FAIL: expected zero remainder\n"); fflush(stdout); flint_abort(); } /* Test chaining */ n2 = 0; while (1) { n2 += fmpq_get_cfrac(c2 + n2, x, x, n_randint(state, 10)); if (fmpq_is_zero(x)) break; fmpq_inv(x, x); } if (n1 != n2) { flint_printf("FAIL: i = %wd, n1 = %wd, n2 = %wd\n", i, n1, n2); fflush(stdout); flint_abort(); } if (!_fmpz_vec_equal(c1, c2, n1)) { flint_printf("FAIL: i = %wd, vectors not equal\n", i); _fmpz_vec_print(c1, n1); flint_printf("\n"); _fmpz_vec_print(c2, n2); flint_printf("\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(c1, bound); _fmpz_vec_clear(c2, bound); fmpq_clear(x); fmpq_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-get_d.c000066400000000000000000000032421461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_get_d, state) { const flint_bitcnt_t bound = 1000; slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { flint_bitcnt_t num_bits, den_bits; int sgn, result; double d; fmpq_t a; fmpq_init(a); fmpq_randtest(a, state, 9999); num_bits = fmpz_bits(fmpq_numref(a)); den_bits = fmpz_bits(fmpq_denref(a)); if ( (num_bits >= den_bits && num_bits - den_bits < bound) || (den_bits >= num_bits && den_bits - num_bits < bound)) { /* the exponent range is such that d should be finite */ d = fmpq_get_d(a); sgn = fmpq_sgn(a); result = (sgn == 0) ? (d == 0) : (sgn < 0) ? (d < 0) : (d > 0); if (!result) { flint_printf("FAIL:\ncheck sign of result matches\n"); flint_printf("a = "); fmpq_print(a); flint_printf("\n"); flint_printf("num_bits = %wu\n", num_bits); flint_printf("den_bits = %wu\n", den_bits); flint_printf("d = %f\n", d); fflush(stdout); flint_abort(); } } fmpq_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-get_mpfr.c000066400000000000000000000035031461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include #include "fmpq.h" TEST_FUNCTION_START(fmpq_get_mpfr, state) { int i; for (i = 0; i < 10000; i++) { fmpq_t x; mpq_t y; mpfr_t f1, f2; int r1, r2; mpfr_rnd_t rnd; fmpq_init(x); mpq_init(y); mpfr_init2(f1, 2 + n_randint(state, 1000)); mpfr_init2(f2, mpfr_get_prec(f1)); fmpq_randtest(x, state, 2 + n_randint(state, 1000)); fmpq_get_mpq(y, x); switch (n_randint(state, 5)) { case 0: rnd = MPFR_RNDZ; break; case 1: rnd = MPFR_RNDD; break; case 2: rnd = MPFR_RNDU; break; case 3: rnd = MPFR_RNDA; break; default: rnd = MPFR_RNDN; break; } r1 = fmpq_get_mpfr(f1, x, rnd); r2 = mpfr_set_q(f2, y, rnd); if (r1 != r2 || !mpfr_equal_p(f1, f2)) { flint_printf("FAIL\n"); fmpq_print(x); flint_printf("\n"); flint_printf("r1 = %d, r2 = %d\n", r1, r2); flint_printf("\nf1: \n"); mpfr_out_str(stdout, 10, 0, f1, MPFR_RNDN); flint_printf("\n\nf1: \n"); mpfr_out_str(stdout, 10, 0, f2, MPFR_RNDN); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); mpq_clear(y); mpfr_clear(f1); mpfr_clear(f2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-get_set_str.c000066400000000000000000000043041461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2018 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "fmpq.h" void check_invalid(char * s, int b) { fmpq_t r; int err; fmpq_init(r); err = fmpq_set_str(r, s, b); if (!err) { printf("Got no error with s='%s'\n", s); printf("r = "); fmpq_print(r); printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(r); } TEST_FUNCTION_START(fmpq_get_set_str, state) { int i; check_invalid("x5/3", 6); check_invalid("5x/3", 6); check_invalid("5/x3", 6); check_invalid("5/3x", 6); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t a, a2; mpq_t b; int ans, base; char *str1, *str2; fmpq_init(a); fmpq_init(a2); mpq_init(b); fmpq_randtest(a, state, 200); base = (int) (n_randint(state, 31) + 2); fmpq_get_mpq(b, a); str1 = fmpq_get_str(NULL, base, a); str2 = mpq_get_str(NULL, base, b); if (strcmp(str1, str2)) { flint_printf("FAIL:\n"); gmp_printf("b = %Qd\n", b); flint_printf("base = %d\n", base); flint_printf("str1 = %s\n, str2 = %s\n", str1, str2); fflush(stdout); flint_abort(); } ans = fmpq_set_str(a2, str1, base); if (ans || !fmpq_equal(a, a2)) { flint_printf("FAIL:\n"); flint_printf("str1 = %s\n", str1); flint_printf("base = %d\n", base); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } flint_free(str1); flint_free(str2); fmpq_clear(a); fmpq_clear(a2); mpq_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-harmonic_ui.c000066400000000000000000000054221461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2010-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" void numerical_test(fmpq_t res, slong n, double ans) { const double tol = 1e-13; double val, err; fmpq_harmonic_ui(res, n); val = fmpq_get_d(res); err = FLINT_ABS(val - ans); if (err > tol) { flint_printf("FAIL: %wd %.16f %.16f\n", n, val, ans); fflush(stdout); flint_abort(); } } TEST_FUNCTION_START(fmpq_harmonic_ui, state) { ulong i; fmpq_t s, t, u; fmpq_init(s); fmpq_init(t); fmpq_init(u); for (i = 0; i < 1000; i++) { if (i > 0) { fmpq_set_si(u, 1, i); fmpq_add(s, s, u); } fmpq_harmonic_ui(t, i); if (!fmpq_equal(t, s)) { flint_printf("FAIL: %wd\n", i); fflush(stdout); flint_abort(); } } numerical_test(t, 1000, 7.4854708605503449127); numerical_test(t, 1001, 7.4864698615493459117); numerical_test(t, 1002, 7.4874678655413618797); numerical_test(t, 1003, 7.4884648745144426375); numerical_test(t, 10000, 9.7876060360443822642); numerical_test(t, 10001, 9.7877060260453821642); numerical_test(t, 10002, 9.7878060060493813643); numerical_test(t, 10003, 9.7879059760583786652); numerical_test(t, 10004, 9.7880059360743722677); numerical_test(t, 100000, 12.090146129863427947); if (flint_test_multiplier() > 10) { numerical_test(t, 20000, 10.480728217229327573); numerical_test(t, 30000, 10.886184992119899362); numerical_test(t, 40000, 11.173862897945522882); numerical_test(t, 50000, 11.397003949278482638); numerical_test(t, 60000, 11.579323839415955783); numerical_test(t, 70000, 11.733473328773164956); numerical_test(t, 80000, 11.867003828544530692); numerical_test(t, 90000, 11.984786169759202469); numerical_test(t, 100001, 12.090156129763428947); numerical_test(t, 100002, 12.090166129563432947); numerical_test(t, 100003, 12.090176129263441947); numerical_test(t, 100004, 12.090186128863457946); numerical_test(t, 300000, 13.188755085205611713); numerical_test(t, 500000, 13.699580042305528322); numerical_test(t, 700000, 14.036051993212618803); numerical_test(t, 900000, 14.287366262763433338); } fmpq_clear(s); fmpq_clear(t); fmpq_clear(u); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-height.c000066400000000000000000000020521461254215100172200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_height, state) { int i; for (i = 0; i < 10000; i++) { fmpq_t x; fmpz_t h; flint_bitcnt_t b; fmpz_init(h); fmpq_init(x); fmpq_randtest(x, state, 200); fmpq_height(h, x); b = fmpq_height_bits(x); if (fmpz_bits(h) != b) { flint_printf("FAIL!\n"); flint_printf("x: "); fmpq_print(x); flint_printf("\nh: "); fmpz_print(h); flint_printf("\nb: %wd\n", b); } fmpq_clear(x); fmpz_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-init_set_readonly.c000066400000000000000000000042401461254215100214640ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_init_set_readonly, state) { int i; /* Create some small fmpq rationals, clear the mpq_t */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t f; mpq_t z; fmpq_init(f); fmpq_randtest(f, state, SMALL_FMPZ_BITCOUNT_MAX); mpq_init(z); fmpq_get_mpq(z, f); { fmpq_t g; fmpq_init_set_readonly(g, z); fmpq_clear_readonly(g); } mpq_clear(z); } /* Create some small fmpq ratioals, do *not* clear the mpq_t */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t f; mpq_t z; fmpq_init(f); fmpq_randtest(f, state, SMALL_FMPZ_BITCOUNT_MAX); mpq_init(z); fmpq_get_mpq(z, f); { fmpq_t g; fmpq_init_set_readonly(g, z); } mpq_clear(z); } /* Create some more fmpq rationals */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t f; mpq_t z; fmpq_init(f); fmpq_randtest(f, state, 2 * FLINT_BITS); mpq_init(z); fmpq_get_mpq(z, f); { fmpq_t g, h; fmpq_init_set_readonly(g, z); fmpq_init(h); fmpq_set_mpq(h, z); if (!fmpq_equal(g, h)) { flint_printf("FAIL:\n\n"); flint_printf("g = "), fmpq_print(g), flint_printf("\n"); flint_printf("h = "), fmpq_print(h), flint_printf("\n"); gmp_printf("z = %Qd\n", z); } fmpq_clear_readonly(g); fmpq_clear(h); } fmpq_clear(f); mpq_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-inv.c000066400000000000000000000057211461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_inv, state) { int i; /* x = y * z */ for (i = 0; i < 10000; i++) { fmpq_t x, y, z; mpq_t X, Y, Z, YY, ZZ; fmpq_init(x); fmpq_init(y); fmpq_init(z); mpq_init(X); mpq_init(Y); mpq_init(Z); mpq_init(YY); mpq_init(ZZ); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); do { fmpq_randtest(z, state, 200); } while (fmpq_is_zero(z)); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_get_mpq(Z, z); fmpq_inv(y, z); fmpq_inv(x, y); if (!fmpq_equal(x, z)) { flint_printf("FAIL: applying inv twice did not give back the input!\n"); fflush(stdout); flint_abort(); } if (!fmpq_is_canonical(y) || !fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_inv(Y, Z); mpq_inv(X, Z); fmpq_get_mpq(YY, y); fmpq_get_mpq(ZZ, z); if (!mpq_equal(Y, YY) || !mpq_equal(Z, ZZ)) { flint_printf("FAIL: fmpq_inv != mpq_inv\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); fmpq_print(z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); mpq_clear(X); mpq_clear(Y); mpq_clear(Z); mpq_clear(YY); mpq_clear(ZZ); } /* Check aliasing */ for (i = 0; i < 10000; i++) { fmpq_t x; mpq_t X, Y; fmpq_init(x); mpq_init(X); mpq_init(Y); do { fmpq_randtest(x, state, 200); } while (fmpq_is_zero(x)); fmpq_get_mpq(X, x); fmpq_inv(x, x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_inv(X, X); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_mul(x,x,y) != mpq_mul(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); mpq_clear(X); mpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-mpq_init_set_readonly.c000066400000000000000000000035221461254215100223430ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_mpq_init_set_readonly, state) { int i; /* Create some small fmpq rationals, clear the mpq_t */ for (i = 0; i < 100000; i++) { fmpq_t f; mpq_t z; fmpq_init(f); fmpq_randtest(f, state, SMALL_FMPZ_BITCOUNT_MAX); flint_mpq_init_set_readonly(z, f); flint_mpq_clear_readonly(z); } /* Create some large fmpq rationals, do not clear the mpq_t */ for (i = 0; i < 100000; i++) { fmpq_t f; mpq_t z; fmpq_init(f); fmpq_randtest(f, state, 2 * FLINT_BITS); if (COEFF_IS_MPZ(*fmpq_numref(f)) && COEFF_IS_MPZ(*(fmpq_denref(f)))) { flint_mpq_init_set_readonly(z, f); } fmpq_clear(f); } /* Create some more fmpq rationals */ for (i = 0; i < 100000; i++) { fmpq_t f, g; mpq_t z; fmpq_init(f); fmpq_init(g); fmpq_randtest(f, state, 2 * FLINT_BITS); flint_mpq_init_set_readonly(z, f); fmpq_set_mpq(g, z); if (!fmpq_equal(f, g)) { flint_printf("FAIL:\n\n"); flint_printf("f = "), fmpq_print(f), flint_printf("\n"); flint_printf("g = "), fmpq_print(g), flint_printf("\n"); gmp_printf("z = %Qd\n", z); } flint_mpq_clear_readonly(z); fmpq_clear(f); fmpq_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-mul.c000066400000000000000000000072451461254215100165560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_mul, state) { int i; /* x = y * z */ for (i = 0; i < 10000; i++) { fmpq_t x, y, z; mpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpq_init(z); mpq_init(X); mpq_init(Y); mpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_randtest(z, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_get_mpq(Z, z); fmpq_mul(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_mul(X, Y, Z); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_mul(x,y,z) != mpq_mul(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); fmpq_print(z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); mpq_clear(X); mpq_clear(Y); mpq_clear(Z); } /* x = x * y */ for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_mul(x, x, y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_mul(X, X, Y); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_mul(x,x,y) != mpq_mul(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } /* x = y * x */ for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_mul(x, y, x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_mul(X, Y, X); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_mul(x,y,x) != mpq_mul(X,Y,X)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-mul_2exp.c000066400000000000000000000065141461254215100175120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_mul_2exp, state) { int i; /* x = y * 2^exp */ for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; flint_bitcnt_t c; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); if (n_randint(state, 5) == 0) fmpz_mul_2exp(fmpq_numref(y), fmpq_numref(y), n_randint(state, 200)); else if (n_randint(state, 5) == 0) fmpz_mul_2exp(fmpq_denref(y), fmpq_denref(y), n_randint(state, 200)); fmpq_canonicalise(y); c = n_randint(state, 200); fmpq_mul_2exp(x, y, c); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nc = %wu\n", c); fflush(stdout); flint_abort(); } fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); mpq_mul_2exp(X, Y, c); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_mul_2exp(x,y,c) != mpq_mul_2exp(X,Y,c)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } /* y = y * 2^exp */ for (i = 0; i < 10000; i++) { fmpq_t x, y; flint_bitcnt_t c; fmpq_init(x); fmpq_init(y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); if (n_randint(state, 5) == 0) fmpz_mul_2exp(fmpq_numref(y), fmpq_numref(y), n_randint(state, 200)); else if (n_randint(state, 5) == 0) fmpz_mul_2exp(fmpq_denref(y), fmpq_denref(y), n_randint(state, 200)); fmpq_canonicalise(y); c = n_randint(state, 200); fmpq_mul_2exp(x, y, c); fmpq_mul_2exp(y, y, c); if (!fmpq_is_canonical(y)) { flint_printf("FAIL: result not canonical!\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nc = %wu\n", c); fflush(stdout); flint_abort(); } if (!fmpq_equal(x, y)) { flint_printf("FAIL: fmpq_mul_2exp(x,y,c) != fmpq_mul_2exp(y,y,c)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nc = %wu\n", c); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-mul_fmpz.c000066400000000000000000000042061461254215100176040ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_mul_fmpz, state) { int i, result; /* Aliasing x = x*z */ for (i = 0; i < 10000; i++) { fmpq_t x, y; fmpz_t z; fmpq_init(x); fmpq_init(y); fmpz_init(z); fmpq_randtest(x, state, 200); fmpz_randtest(z, state, 200); fmpq_mul_fmpz(y, x, z); fmpq_mul_fmpz(x, x, z); result = (fmpq_is_canonical(x) && fmpq_is_canonical(y) && fmpq_equal(x, y)); if (!result) { flint_printf("FAIL (alias):\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); flint_printf("z = "), fmpz_print(z), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(z); } /* Compare with fmpq_mul */ for (i = 0; i < 10000; i++) { fmpq_t x, y, z; fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpq_randtest(x, state, 200); fmpz_randtest(fmpq_numref(z), state, 200); fmpq_mul_fmpz(y, x, fmpq_numref(z)); fmpq_mul(x, x, z); result = (fmpq_is_canonical(x) && fmpq_is_canonical(y) && fmpq_equal(x, y)); if (!result) { flint_printf("FAIL (cmp):\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-mul_si.c000066400000000000000000000052311461254215100172420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_mul_si, state) { int i; /* x = y + z */ for (i = 0; i < 10000; i++) { fmpq_t x, y; slong z; fmpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpq_init(X); fmpq_init(Y); fmpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); z = z_randtest(state); fmpq_set(X, x); fmpq_set(Y, y); fmpq_set_si(Z, z, 1); fmpq_mul_si(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } fmpq_mul(X, Y, Z); if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,y,z) != mpq_add(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); flint_printf("%wd", z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(X); fmpq_clear(Y); fmpq_clear(Z); } /* x = x + y */ for (i = 0; i < 10000; i++) { fmpq_t x; slong y; fmpq_t X, Y; fmpq_init(x); fmpq_init(X); fmpq_init(Y); fmpq_randtest(x, state, 200); y = z_randtest(state); fmpq_set(X, x); fmpq_set_si(Y, y, 1); fmpq_mul_si(x, x, y); fmpq_mul(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_mul(x,x,y) != mpq_mul(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); flint_printf("%wd", y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-mul_ui.c000066400000000000000000000051721461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_mul_ui, state) { int i; /* x = y + z */ for (i = 0; i < 10000; i++) { fmpq_t x, y; ulong z; fmpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpq_init(X); fmpq_init(Y); fmpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); z = n_randtest(state); fmpq_set(X, x); fmpq_set(Y, y); fmpq_set_ui(Z, z, 1); fmpq_mul_ui(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } fmpq_mul(X, Y, Z); if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,y,z) != mpq_add(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); flint_printf("%wd", z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(X); fmpq_clear(Y); fmpq_clear(Z); } /* x = x + y */ for (i = 0; i < 10000; i++) { fmpq_t x; ulong y; fmpq_t X, Y; fmpq_init(x); fmpq_init(X); fmpq_init(Y); fmpq_randtest(x, state, 200); y = n_randtest(state); fmpq_set(X, x); fmpq_set_ui(Y, y, 1); fmpq_mul_ui(x, x, y); fmpq_mul(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_mul(x,x,y) != mpq_mul(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); flint_printf("%wd", y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-next_calkin_wilf.c000066400000000000000000000047211461254215100212750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_next_calkin_wilf, state) { slong i; fmpq_t r, ans; fmpq_init(r); fmpq_init(ans); fmpq_set_si(r, 0, 1); fmpq_set_si(ans, 43, 205); for (i = 0; i < 10000; i++) fmpq_next_calkin_wilf(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: enum from 0\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_set_si(r, 0, 1); fmpq_set_si(ans, -43, 162); for (i = 0; i < 10000; i++) fmpq_next_signed_calkin_wilf(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: signed enum from 0\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_set_str(fmpq_numref(r), "18446744073709551615", 10); fmpz_set_str(fmpq_denref(r), "18446744073709551616", 10); fmpz_set_str(fmpq_numref(ans), "498062089990157893394", 10); fmpz_set_str(fmpq_denref(ans), "700976274800962961073", 10); for (i = 0; i < 1000; i++) fmpq_next_calkin_wilf(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: enum from 2^64\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_set_str(fmpq_numref(r), "18446744073709551615", 10); fmpz_set_str(fmpq_denref(r), "18446744073709551616", 10); fmpz_set_str(fmpq_numref(ans), "295147905179352825731", 10); fmpz_set_str(fmpq_denref(ans), "498062089990157893421", 10); for (i = 0; i < 1000; i++) fmpq_next_signed_calkin_wilf(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: signed enum from 2^64\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(r); fmpq_clear(ans); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-next_minimal.c000066400000000000000000000046311461254215100204410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_next_minimal, state) { slong i; fmpq_t r, ans; fmpq_init(r); fmpq_init(ans); fmpq_set_si(r, 0, 1); fmpq_set_si(ans, 85, 128); for (i = 0; i < 10000; i++) fmpq_next_minimal(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: enum from 0\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_set_si(r, 0, 1); fmpq_set_si(ans, -25, 91); for (i = 0; i < 10000; i++) fmpq_next_signed_minimal(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: signed enum from 0\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_set_str(fmpq_numref(r), "36893488147419102231", 10); fmpz_set_str(fmpq_denref(r), "36893488147419103232", 10); fmpz_set_str(fmpq_numref(ans), "7484", 10); fmpz_set_str(fmpq_denref(ans), "36893488147419103233", 10); for (i = 0; i < 10000; i++) fmpq_next_minimal(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: enum from 2^65\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_set_str(fmpq_numref(r), "36893488147419102231", 10); fmpz_set_str(fmpq_denref(r), "36893488147419103232", 10); fmpz_set_str(fmpq_numref(ans), "3326", 10); fmpz_set_str(fmpq_denref(ans), "36893488147419103233", 10); for (i = 0; i < 10000; i++) fmpq_next_signed_minimal(r, r); if (!fmpq_equal(r, ans)) { flint_printf("FAIL: signed enum from 2^65\n"); fmpq_print(r); flint_printf("\n"); fmpq_print(ans); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(r); fmpq_clear(ans); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-one.c000066400000000000000000000034641461254215100165410ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_one, state) { int i, result; /* x == 1 * x */ for (i = 0; i < 10000; i++) { fmpq_t x, y, z; fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpq_randtest(x, state, 200); fmpq_one(y); fmpq_mul(z, y, x); result = fmpq_is_canonical(z) && fmpq_equal(x, z); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* x/x == 1 */ for (i = 0; i < 10000; i++) { fmpq_t x, y; fmpq_init(x); fmpq_init(y); while (fmpq_is_zero(x)) fmpq_randtest(x, state, 200); fmpq_div(y, x, x); result = fmpq_is_canonical(y) && fmpq_is_one(y); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-pow_si.c000066400000000000000000000046721461254215100172620ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_pow_si, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 100000; i++) { fmpq_t a, b, c; slong e; fmpq_init(a); fmpq_init(b); fmpq_init(c); fmpq_randtest(a, state, 100); fmpq_set(b, a); e = z_randint(state, 20); if (fmpq_is_zero(b) && e < 0) e = -e; fmpq_pow_si(c, b, e); fmpq_pow_si(b, b, e); result = fmpq_equal(b, c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpq_print(c), flint_printf("\n\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); } /* Compare with repeated multiplication */ for (i = 0; i < 10000; i++) { fmpq_t a, b, c; slong j, e; fmpq_init(a); fmpq_init(b); fmpq_init(c); fmpq_randtest(a, state, 50); e = z_randint(state, 20); if (fmpq_is_zero(a) && e < 0) e = -e; fmpq_pow_si(b, a, e); fmpq_one(c); for (j = 0; j < FLINT_ABS(e); j++) fmpq_mul(c, c, a); if (e < 0) fmpq_inv(c, c); result = fmpq_equal(b, c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpq_print(c), flint_printf("\n\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-randtest.c000066400000000000000000000017671461254215100176100ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_randtest, state) { int i; for (i = 0; i < 10000; i++) { fmpq_t x; slong bits; fmpq_init(x); bits = 1 + n_randint(state, 100); fmpq_randtest(x, state, bits); if (!fmpq_is_canonical(x) || fmpz_bits(fmpq_numref(x)) > bits || fmpz_bits(fmpq_denref(x)) > bits) { flint_printf("FAIL\n"); flint_printf("x: "); fmpq_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-reconstruct_fmpz.c000066400000000000000000000036261461254215100213670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_reconstruct_fmpz, state) { int i; for (i = 0; i < 1000*flint_test_multiplier(); i++) { int result; fmpq_t x, y; fmpz_t mod; fmpz_t res; mpz_t tmp; fmpq_init(x); fmpq_init(y); fmpz_init(mod); fmpz_init(res); mpz_init(tmp); fmpq_randtest(x, state, 1000); /* Modulus m > 2*max(|n|,d)^2 */ if (fmpz_cmpabs(&x->num, &x->den) >= 0) fmpz_mul(mod, &x->num, &x->num); else fmpz_mul(mod, &x->den, &x->den); fmpz_mul_2exp(mod, mod, 1); do fmpz_add_ui(mod, mod, 1); while (!fmpq_mod_fmpz(res, x, mod)); result = fmpq_reconstruct_fmpz(y, res, mod); if (!result || !fmpq_equal(x, y)) { flint_printf("FAIL: reconstruction failed\n"); flint_printf("input = "); fmpq_print(x); flint_printf("\nmodulus = "); fmpz_print(mod); flint_printf("\nresidue = "); fmpz_print(res); flint_printf("\nreconstructed = "); fmpq_print(y); flint_printf("\nfmpq_reconstruct_fmpz return value = %d", result); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(mod); fmpz_clear(res); mpz_clear(tmp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-reconstruct_fmpz_2.c000066400000000000000000000116311461254215100216030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_reconstruct_fmpz_2, state) { int i; /* check successful reconstructions */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int success; fmpq_t x, y; fmpz_t mod, res, N, D, t; fmpq_init(x); fmpq_init(y); fmpz_init(mod); fmpz_init(res); fmpz_init(N); fmpz_init(D); fmpz_init(t); if (i % 2) { fmpq_randtest(x, state, 1 + n_randint(state, 5000)); } else { slong k, bound; fmpz * c1; bound = 1 + n_randint(state, 100); c1 = _fmpz_vec_init(bound); fmpz_randtest(c1 + 0, state, 2*FLINT_BITS); for (k = 1; k < bound; k++) { fmpz_randtest_unsigned(c1 + k, state, 3*FLINT_BITS); fmpz_add_ui(c1 + k, c1 + k, 1); } fmpq_set_cfrac(x, c1, bound); _fmpz_vec_clear(c1, bound); } fmpz_abs(N, fmpq_numref(x)); fmpz_set(D, fmpq_denref(x)); /* Randomly generate larger bounds */ if (n_randint(state, 2)) { fmpz_randtest_not_zero(t, state, 2000); fmpz_abs(t, t); fmpz_mul(N, N, t); } if (n_randint(state, 2)) { fmpz_randtest_not_zero(t, state, 2000); fmpz_abs(t, t); fmpz_mul(D, D, t); } if (n_randint(state, 10)) { fmpz_mul(mod, N, D); fmpz_mul_ui(mod, mod, 2); } else { fmpz_randbits(mod, state, FLINT_BITS * FMPQ_RECONSTRUCT_HGCD_CUTOFF + fmpz_bits(N) + n_randint(state, 10)); fmpz_abs(mod, mod); } do fmpz_add_ui(mod, mod, 1); while (!fmpq_mod_fmpz(res, x, mod)); success = fmpq_reconstruct_fmpz_2(y, res, mod, N, D); if (!success || !fmpq_equal(x, y)) flint_throw(FLINT_TEST_FAIL, "success = %d\n" "x = %{fmpq}\n" "N = %{fmpz}\n" "D = %{fmpz}\n" "mod = %{fmpz}\n" "res = %{fmpz}\n" "y = %{fmpq}\n", success, x, N, D, mod, res, y); fmpq_clear(x); fmpq_clear(y); fmpz_clear(mod); fmpz_clear(res); fmpz_clear(N); fmpz_clear(D); fmpz_clear(t); } /* check random reconstructions */ for (i = 0; i < 1000*flint_test_multiplier(); i++) { int success1, success2; fmpq_t x, y; fmpz_t mod, res, N, D, t; fmpq_init(x); fmpq_init(y); fmpz_init(mod); fmpz_init(res); fmpz_init(N); fmpz_init(D); fmpz_init(t); if (i % 2) { fmpz_randtest_not_zero(mod, state, 5000); fmpz_randtest_not_zero(res, state, 5000); } else { slong k, bound; fmpz * c1; bound = 2 + n_randint(state, 100); c1 = _fmpz_vec_init(bound); fmpz_zero(c1 + 0); for (k = 1; k < bound; k++) { fmpz_randtest_unsigned(c1 + k, state, 2*FLINT_BITS); fmpz_add_ui(c1 + k, c1 + k, 1); } fmpq_set_cfrac(x, c1, bound); _fmpz_vec_clear(c1, bound); fmpz_swap(res, fmpq_numref(x)); fmpz_swap(mod, fmpq_denref(x)); } if (fmpz_cmp_ui(mod, 3) < 0) fmpz_set_ui(mod, 3); fmpz_mod(res, res, mod); fmpz_sub_ui(t, mod, 1); fmpz_fdiv_q_ui(t, t, 2); fmpz_randtest_mod(N, state, t); fmpz_add_ui(N, N, 1); fmpz_fdiv_q(D, t, N); fmpz_randtest_mod(D, state, D); fmpz_add_ui(D, D, 1); success1 = _fmpq_reconstruct_fmpz_2(fmpq_numref(x), fmpq_denref(x), res, mod, N, D); success2 = _fmpq_reconstruct_fmpz_2_naive(fmpq_numref(y), fmpq_denref(y), res, mod, N, D); if (success1 != success2 || (success1 && !fmpq_equal(x, y))) flint_throw(FLINT_TEST_FAIL, "check match with naive: i = %wd\n", i); fmpq_clear(x); fmpq_clear(y); fmpz_clear(mod); fmpz_clear(res); fmpz_clear(N); fmpz_clear(D); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-set_cfrac.c000066400000000000000000000025731461254215100177110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_set_cfrac, state) { int i; for (i = 0; i < 10000; i++) { fmpq_t x, y, r; fmpz * c; slong n, bound; fmpq_init(x); fmpq_init(y); fmpq_init(r); fmpq_randtest(x, state, 1 + n_randint(state, 1000)); bound = fmpq_cfrac_bound(x); c = _fmpz_vec_init(bound); n = fmpq_get_cfrac(c, r, x, bound); fmpq_set_cfrac(y, c, n); if (!fmpq_equal(x, y)) { flint_printf("FAIL: x != y\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n"); flint_printf("c = "); _fmpz_vec_print(c, n); flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(c, bound); fmpq_clear(x); fmpq_clear(y); fmpq_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-set_fmpz_frac.c000066400000000000000000000027071461254215100206010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_set_fmpz_frac, state) { int i; for (i = 0; i < 10000; i++) { fmpq_t x, y; fmpz_t p, q; fmpq_init(x); fmpq_init(y); fmpz_init(p); fmpz_init(q); fmpz_randtest(p, state, 100); fmpz_randtest_not_zero(q, state, 100); fmpq_set_fmpz_frac(x, p, q); fmpz_set(fmpq_numref(y), p); fmpz_set(fmpq_denref(y), q); fmpq_canonicalise(y); if (!fmpq_is_canonical(x) || !fmpq_equal(x, y)) { flint_printf("FAIL"); flint_printf("p: "); fmpz_print(p); flint_printf("\n"); flint_printf("q: "); fmpz_print(q); flint_printf("\n"); flint_printf("x: "); fmpq_print(x); flint_printf("\n"); flint_printf("y: "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(p); fmpz_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-set_si.c000066400000000000000000000026651461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_set_si, state) { int i; for (i = 0; i < 10000; i++) { fmpq_t x, y; fmpz_t p, q; slong P, Q; fmpq_init(x); fmpq_init(y); fmpz_init(p); fmpz_init(q); P = z_randtest(state); Q = n_randtest_not_zero(state); fmpz_set_si(p, P); fmpz_set_ui(q, Q); fmpq_set_fmpz_frac(x, p, q); fmpq_set_si(y, P, Q); if (!fmpq_is_canonical(y) || !fmpq_equal(x, y)) { flint_printf("FAIL"); flint_printf("p: "); fmpz_print(p); flint_printf("\n"); flint_printf("q: "); fmpz_print(q); flint_printf("\n"); flint_printf("x: "); fmpq_print(x); flint_printf("\n"); flint_printf("y: "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(p); fmpz_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-set_ui.c000066400000000000000000000027001461254215100172400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_set_ui, state) { int i; for (i = 0; i < 10000; i++) { fmpq_t x, y; fmpz_t p, q; ulong P, Q; fmpq_init(x); fmpq_init(y); fmpz_init(p); fmpz_init(q); P = n_randtest(state); Q = n_randtest_not_zero(state); fmpz_set_ui(p, P); fmpz_set_ui(q, Q); fmpq_set_fmpz_frac(x, p, q); fmpq_set_ui(y, P, Q); if (!fmpq_is_canonical(y) || !fmpq_equal(x, y)) { flint_printf("FAIL"); flint_printf("p: "); fmpz_print(p); flint_printf("\n"); flint_printf("q: "); fmpz_print(q); flint_printf("\n"); flint_printf("x: "); fmpq_print(x); flint_printf("\n"); flint_printf("y: "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(p); fmpz_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-simplest_between.c000066400000000000000000000077471461254215100213410ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_simplest_between, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_t m2, m1, m, l, r, l1, r1; fmpq_init(m2); fmpq_init(m1); fmpq_init(m); fmpq_init(l); fmpq_init(r); fmpq_init(l1); fmpq_init(r1); fmpq_randtest(l, state, 1 + n_randint(state, 1000)); fmpq_randtest(r, state, 1 + n_randint(state, 1000)); fmpz_one(fmpq_numref(m)); fmpz_randtest_not_zero(fmpq_denref(m), state, 1 + n_randint(state, 1000)); fmpz_abs(fmpq_denref(m), fmpq_denref(m)); fmpq_mul(l, l, m); fmpq_mul(r, r, m); if (i % 2) { fmpq_randtest(m2, state, 1 + n_randint(state, 1000)); } else { slong k, bound; fmpz * c1; bound = 1 + n_randint(state, 100); c1 = _fmpz_vec_init(bound); fmpz_randtest(c1 + 0, state, 2*FLINT_BITS); for (k = 1; k < bound; k++) { fmpz_randtest_unsigned(c1 + k, state, 3*FLINT_BITS); fmpz_add_ui(c1 + k, c1 + k, 1); } fmpq_set_cfrac(m2, c1, bound); _fmpz_vec_clear(c1, bound); } fmpq_add(l, l, m2); fmpq_add(r, r, m2); fmpq_simplest_between(m, l, r); if (fmpq_cmp(l, r) > 0) fmpq_swap(l, r); if (!(fmpq_cmp(l, m) <= 0 && fmpq_cmp(m, r) <= 0)) { printf("FAIL\n"); flint_printf("Check answer is between, i = %wd\n", i); fflush(stdout); flint_abort(); } if ( fmpz_cmp(fmpq_denref(m), fmpq_denref(l)) > 0 || fmpz_cmp(fmpq_denref(m), fmpq_denref(r)) > 0) { printf("FAIL\n"); flint_printf("Check denominator, i = %wd\n", i); fflush(stdout); flint_abort(); } if (fmpz_cmp_ui(fmpq_denref(m), 1) > 0) { fmpq_farey_neighbors(l1, r1, m, fmpq_denref(m)); if (fmpq_cmp(l1, l) >= 0 || fmpq_cmp(r1, r) <= 0) { printf("FAIL\n"); flint_printf("Check answer is simplest, i = %wd\n", i); fflush(stdout); flint_abort(); } } else if (fmpz_is_one(fmpq_denref(m))) { fmpz_cdiv_q(fmpq_numref(m1), fmpq_numref(l), fmpq_denref(l)); if (!fmpz_equal(fmpq_numref(m1), fmpq_numref(m))) { printf("FAIL\n"); flint_printf("Check int answer is simplest, i = %wd\n", i); fflush(stdout); flint_abort(); } } else { printf("FAIL\n"); flint_printf("Check return has positive denominator, i = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_simplest_between(m1, l, m); if (!fmpq_equal(m1, m)) { printf("FAIL\n"); flint_printf("Check m left, i = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_simplest_between(m1, r, m); if (!fmpq_equal(m1, m)) { printf("FAIL\n"); flint_printf("Check m right, i = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_clear(m2); fmpq_clear(m1); fmpq_clear(m); fmpq_clear(l); fmpq_clear(r); fmpq_clear(l1); fmpq_clear(r1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-sub.c000066400000000000000000000072451461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_sub, state) { int i; /* x = y - z */ for (i = 0; i < 10000; i++) { fmpq_t x, y, z; mpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpq_init(z); mpq_init(X); mpq_init(Y); mpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_randtest(z, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_get_mpq(Z, z); fmpq_sub(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_sub(X, Y, Z); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_sub(x,y,z) != mpq_sub(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); fmpq_print(z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); mpq_clear(X); mpq_clear(Y); mpq_clear(Z); } /* x = x - y */ for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_sub(x, x, y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_sub(X, X, Y); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_sub(x,x,y) != mpq_sub(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } /* x = y - x */ for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_sub(x, y, x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_sub(X, Y, X); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_sub(x,y,x) != mpq_sub(X,Y,X)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-sub_fmpz.c000066400000000000000000000056021461254215100176010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_sub_fmpz, state) { int i; /* x = y + z */ for (i = 0; i < 10000; i++) { fmpq_t x, y; fmpz_t z, one; fmpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpz_init(z); fmpz_init_set_ui(one, 1); fmpq_init(X); fmpq_init(Y); fmpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpz_randtest(z, state, 200); fmpq_set(X, x); fmpq_set(Y, y); fmpq_set_fmpz_frac(Z, z, one); fmpq_sub_fmpz(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } fmpq_sub(X, Y, Z); if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,y,z) != mpq_add(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); fmpz_print(z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(z); fmpz_clear(one); fmpq_clear(X); fmpq_clear(Y); fmpq_clear(Z); } /* x = x + y */ for (i = 0; i < 10000; i++) { fmpq_t x; fmpz_t y, one; fmpq_t X, Y; fmpq_init(x); fmpz_init(y); fmpz_init(one); fmpq_init(X); fmpq_init(Y); fmpq_randtest(x, state, 200); fmpz_randtest(y, state, 200); fmpz_init_set_ui(one, 1); fmpq_set(X, x); fmpq_set_fmpz_frac(Y, y, one); fmpq_sub_fmpz(x, x, y); fmpq_sub(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,x,y) != mpq_add(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpz_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpz_clear(y); fmpz_clear(one); fmpq_clear(X); fmpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-sub_si.c000066400000000000000000000052231461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_sub_si, state) { int i; /* x = y + z */ for (i = 0; i < 10000; i++) { fmpq_t x, y; slong z; fmpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpq_init(X); fmpq_init(Y); fmpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); z = z_randtest(state); fmpq_set(X, x); fmpq_set(Y, y); fmpq_set_si(Z, z, 1); fmpq_sub_si(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } fmpq_sub(X, Y, Z); if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,y,z) != mpq_add(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); flint_printf("%wd", z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(X); fmpq_clear(Y); fmpq_clear(Z); } /* x = x + y */ for (i = 0; i < 10000; i++) { fmpq_t x; slong y; fmpq_t X, Y; fmpq_init(x); fmpq_init(X); fmpq_init(Y); fmpq_randtest(x, state, 200); y = z_randtest(state); fmpq_set(X, x); fmpq_set_si(Y, y, 1); fmpq_sub_si(x, x, y); fmpq_sub(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,x,y) != mpq_add(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); flint_printf("%wd", y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-sub_ui.c000066400000000000000000000052321461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq.h" TEST_FUNCTION_START(fmpq_sub_ui, state) { int i; /* x = y + z */ for (i = 0; i < 10000; i++) { fmpq_t x, y; ulong z; fmpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpq_init(X); fmpq_init(Y); fmpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); z = n_randtest(state); fmpq_set(X, x); fmpq_set(Y, y); fmpq_set_ui(Z, z, 1); fmpq_sub_ui(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } fmpq_sub(X, Y, Z); if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,y,z) != mpq_add(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); flint_printf("%wd", z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(X); fmpq_clear(Y); fmpq_clear(Z); } /* x = x + y */ for (i = 0; i < 10000; i++) { fmpq_t x; ulong y; fmpq_t X, Y; fmpq_init(x); fmpq_init(X); fmpq_init(Y); fmpq_randtest(x, state, 200); y = n_randtest(state); fmpq_set(X, x); fmpq_set_ui(Y, y, 1); fmpq_sub_ui(x, x, y); fmpq_sub(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } if (!fmpq_equal(X, x)) { flint_printf("FAIL: fmpq_add(x,x,y) != mpq_add(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); flint_printf("%wd", y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq/test/t-submul.c000066400000000000000000000075331461254215100172700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" void mpq_submul(mpq_t x, mpq_t y, mpq_t z) { mpq_t t; mpq_init(t); mpq_mul(t, y, z); mpq_sub(x, x, t); mpq_clear(t); } TEST_FUNCTION_START(fmpq_submul, state) { int i; /* x -= y * z */ for (i = 0; i < 10000; i++) { fmpq_t x, y, z; mpq_t X, Y, Z; fmpq_init(x); fmpq_init(y); fmpq_init(z); mpq_init(X); mpq_init(Y); mpq_init(Z); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_randtest(z, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_get_mpq(Z, z); fmpq_submul(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_submul(X, Y, Z); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_submul(x,y,z) != mpq_submul(X,Y,Z)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nz = "); fmpq_print(z); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); mpq_clear(X); mpq_clear(Y); mpq_clear(Z); } /* x -= x * y */ for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_submul(x, x, y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_submul(X, X, Y); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_submul(x,x,y) != mpq_submul(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } /* x -= y * x */ for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_submul(x, y, x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fflush(stdout); flint_abort(); } mpq_submul(X, Y, X); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_submul(x,y,x) != mpq_submul(X,Y,X)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat.h000066400000000000000000000233071461254215100154040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_MAT_H #define FMPQ_MAT_H #ifdef FMPQ_MAT_INLINES_C #define FMPQ_MAT_INLINE #else #define FMPQ_MAT_INLINE static inline #endif #include "fmpq_types.h" #ifdef __cplusplus extern "C" { #endif FMPQ_MAT_INLINE fmpq * fmpq_mat_entry(const fmpq_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } FMPQ_MAT_INLINE fmpz * fmpq_mat_entry_num(const fmpq_mat_t mat, slong i, slong j) { return (fmpz *)(&((*fmpq_mat_entry(mat, i, j)).num)); } FMPQ_MAT_INLINE fmpz * fmpq_mat_entry_den(const fmpq_mat_t mat, slong i, slong j) { return (fmpz *)(&((*fmpq_mat_entry(mat, i, j)).den)); } FMPQ_MAT_INLINE slong fmpq_mat_nrows(const fmpq_mat_t mat) { return mat->r; } FMPQ_MAT_INLINE slong fmpq_mat_ncols(const fmpq_mat_t mat) { return mat->c; } void fmpq_mat_init(fmpq_mat_t mat, slong rows, slong cols); void fmpq_mat_init_set(fmpq_mat_t mat1, const fmpq_mat_t mat2); void fmpq_mat_clear(fmpq_mat_t mat); FMPQ_MAT_INLINE void fmpq_mat_swap(fmpq_mat_t mat1, fmpq_mat_t mat2) { FLINT_SWAP(fmpq_mat_struct, *mat1, *mat2); } void fmpq_mat_swap_entrywise(fmpq_mat_t mat1, fmpq_mat_t mat2); /* Windows and concatenation */ void fmpq_mat_window_init(fmpq_mat_t window, const fmpq_mat_t mat, slong r1, slong c1, slong r2, slong c2); void fmpq_mat_window_clear(fmpq_mat_t window); void fmpq_mat_concat_horizontal(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2); void fmpq_mat_concat_vertical(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2); /* Input and output */ void fmpq_mat_print(const fmpq_mat_t mat); /* Random matrix generation **************************************************/ void fmpq_mat_randbits(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); void fmpq_mat_randtest(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); /* Special matrices **********************************************************/ void fmpq_mat_hilbert_matrix(fmpq_mat_t mat); /* Basic assignment **********************************************************/ void fmpq_mat_set(fmpq_mat_t dest, const fmpq_mat_t src); void fmpq_mat_zero(fmpq_mat_t mat); void fmpq_mat_one(fmpq_mat_t mat); void fmpq_mat_transpose(fmpq_mat_t rop, const fmpq_mat_t op); /* Addition, scalar multiplication ******************************************/ void fmpq_mat_add(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2); void fmpq_mat_sub(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2); void fmpq_mat_neg(fmpq_mat_t rop, const fmpq_mat_t op); void fmpq_mat_scalar_mul_fmpq(fmpq_mat_t rop, const fmpq_mat_t op, const fmpq_t x); void fmpq_mat_scalar_mul_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x); void fmpq_mat_scalar_div_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x); /* Basic comparison and properties *******************************************/ int fmpq_mat_equal(const fmpq_mat_t mat1, const fmpq_mat_t mat2); int fmpq_mat_is_integral(const fmpq_mat_t mat); int fmpq_mat_is_zero(const fmpq_mat_t mat); int fmpq_mat_is_one(const fmpq_mat_t mat); FMPQ_MAT_INLINE int fmpq_mat_is_empty(const fmpq_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } FMPQ_MAT_INLINE int fmpq_mat_is_square(const fmpq_mat_t mat) { return (mat->r == mat->c); } /* Integer matrix conversion *************************************************/ int fmpq_mat_get_fmpz_mat(fmpz_mat_t dest, const fmpq_mat_t mat); void fmpq_mat_get_fmpz_mat_entrywise(fmpz_mat_t num, fmpz_mat_t den, const fmpq_mat_t mat); void fmpq_mat_get_fmpz_mat_matwise(fmpz_mat_t num, fmpz_t den, const fmpq_mat_t mat); void fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat); void fmpq_mat_get_fmpz_mat_colwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat); void fmpq_mat_get_fmpz_mat_rowwise_2(fmpz_mat_t num, fmpz_mat_t num2, fmpz * den, const fmpq_mat_t mat, const fmpq_mat_t mat2); void fmpq_mat_get_fmpz_mat_mod_fmpz(fmpz_mat_t dest, const fmpq_mat_t mat, const fmpz_t mod); void fmpq_mat_set_fmpz_mat(fmpq_mat_t dest, const fmpz_mat_t src); void fmpq_mat_set_fmpz_mat_div_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t div); int fmpq_mat_set_fmpz_mat_mod_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t mod); /* Matrix multiplication *****************************************************/ void fmpq_mat_mul_direct(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); void fmpq_mat_mul_cleared(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); void fmpq_mat_mul(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); void fmpq_mat_mul_fmpz_mat(fmpq_mat_t C, const fmpq_mat_t A, const fmpz_mat_t B); void fmpq_mat_mul_r_fmpz_mat(fmpq_mat_t C, const fmpz_mat_t A, const fmpq_mat_t B); void fmpq_mat_mul_fmpq_vec(fmpq * c, const fmpq_mat_t A, const fmpq * b, slong blen); void fmpq_mat_mul_fmpz_vec(fmpq* c, const fmpq_mat_t A, const fmpz * b, slong blen); void fmpq_mat_mul_fmpq_vec_ptr(fmpq * const * c, const fmpq_mat_t A, const fmpq * const * b, slong blen); void fmpq_mat_mul_fmpz_vec_ptr(fmpq * const * c, const fmpq_mat_t A, const fmpz * const * b, slong blen); void fmpq_mat_fmpq_vec_mul(fmpq* c, const fmpq* a, slong alen, const fmpq_mat_t B); void fmpq_mat_fmpz_vec_mul(fmpq * c, const fmpz * a, slong alen, const fmpq_mat_t B); void fmpq_mat_fmpq_vec_mul_ptr(fmpq * const * c, const fmpq * const * a, slong alen, const fmpq_mat_t B); void fmpq_mat_fmpz_vec_mul_ptr(fmpq * const * c, const fmpz * const * a, slong alen, const fmpq_mat_t B); /* Kronecker product *********************************************************/ void fmpq_mat_kronecker_product(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); /* Permutations **************************************************************/ void fmpq_mat_swap_rows(fmpq_mat_t mat, slong * perm, slong r, slong s); void fmpq_mat_swap_cols(fmpq_mat_t mat, slong * perm, slong r, slong s); void fmpq_mat_invert_rows(fmpq_mat_t mat, slong * perm); void fmpq_mat_invert_cols(fmpq_mat_t mat, slong * perm); /* Trace *********************************************************************/ void fmpq_mat_trace(fmpq_t trace, const fmpq_mat_t mat); /* Determinant ***************************************************************/ void fmpq_mat_det(fmpq_t det, const fmpq_mat_t mat); /* Nonsingular solving *******************************************************/ int fmpq_mat_solve_fmpz_mat_fraction_free(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); int fmpq_mat_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); int fmpq_mat_solve_fmpz_mat_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); int fmpq_mat_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); int fmpq_mat_solve_fmpz_mat_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); int fmpq_mat_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); int fmpq_mat_can_solve_fmpz_mat_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); int fmpq_mat_can_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); int fmpq_mat_can_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); int fmpq_mat_can_solve_fmpz_mat_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); int fmpq_mat_can_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); int fmpq_mat_solve_fmpz_mat(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); int fmpq_mat_solve(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); int fmpq_mat_can_solve(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); /* Inverse *******************************************************************/ int fmpq_mat_inv(fmpq_mat_t B, const fmpq_mat_t A); /* Echelon form **************************************************************/ int fmpq_mat_pivot(slong * perm, fmpq_mat_t mat, slong r, slong c); slong fmpq_mat_rref_classical(fmpq_mat_t B, const fmpq_mat_t A); slong fmpq_mat_rref_fraction_free(fmpq_mat_t B, const fmpq_mat_t A); slong fmpq_mat_rref(fmpq_mat_t B, const fmpq_mat_t A); /* Gram-Schmidt Orthogonalisation *******************************************/ void fmpq_mat_gso(fmpq_mat_t B, const fmpq_mat_t A); /* Characteristic polynomial *************************************************/ void fmpq_mat_similarity(fmpq_mat_t A, slong r, fmpq_t d); /* Characteristic polynomial *************************************************/ void _fmpq_mat_charpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat); void fmpq_mat_charpoly(fmpq_poly_t pol, const fmpq_mat_t mat); /* Minimal polynomial ********************************************************/ slong _fmpq_mat_minpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat); void fmpq_mat_minpoly(fmpq_poly_t pol, const fmpq_mat_t mat); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpq_mat/000077500000000000000000000000001461254215100152265ustar00rootroot00000000000000flint-3.1.3/src/fmpq_mat/add.c000066400000000000000000000013221461254215100161200ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_add(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2) { slong i, j; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_add(fmpq_mat_entry(mat, i, j), fmpq_mat_entry(mat1, i, j), fmpq_mat_entry(mat2, i, j)); } flint-3.1.3/src/fmpq_mat/can_solve.c000066400000000000000000000012231461254215100173410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" int fmpq_mat_can_solve(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { if (fmpq_mat_nrows(A) <= 15) return fmpq_mat_can_solve_fraction_free(X, A, B); else return fmpq_mat_can_solve_multi_mod(X, A, B); } flint-3.1.3/src/fmpq_mat/can_solve_dixon.c000066400000000000000000000074461461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2022 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" /* Algorithm developed with Claus Fieker */ int _fmpq_mat_check_solution_fmpz_mat(const fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); int fmpq_mat_can_solve_fmpz_mat_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { mp_limb_t p; fmpz_t tested; nmod_mat_t Ap, LU; int result = 0, success = 0; slong * perm, * pivots; slong i, j, k, col, rank; fmpz_mat_t Arank, Brank; fmpq_mat_t Xrank; fmpz_t det_bound; p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; fmpz_init(det_bound); fmpz_init(tested); fmpz_one(tested); nmod_mat_init(Ap, A->r, A->c, p); nmod_mat_init(LU, A->r, A->c, p); perm = flint_malloc(sizeof(slong)*A->r); pivots = flint_malloc(sizeof(slong)*A->c); /* only first rank entries are meaningful */ fmpz_mat_det_bound(det_bound, A); while (1) { p = n_nextprime(p, 0); nmod_mat_set_mod(Ap, p); nmod_mat_set_mod(LU, p); fmpz_mat_get_nmod_mat(Ap, A); nmod_mat_set(LU, Ap); for (i = 0; i < A->r; i++) perm[i] = i; rank = nmod_mat_lu(perm, LU, 0); col = 0; for (i = 0; i < rank; i++) { while (nmod_mat_entry(LU, i, col) == 0) col++; pivots[i] = col; col++; } fmpz_mat_init(Arank, rank, rank); fmpz_mat_init(Brank, rank, B->c); fmpq_mat_init(Xrank, rank, B->c); for (i = 0; i < rank; i++) { k = 0; for (j = 0; j < A->c; j++) { if (k < rank && j == pivots[k]) { fmpz_set(fmpz_mat_entry(Arank, i, k), fmpz_mat_entry(A, perm[i], j)); k++; } } for (j = 0; j < B->c; j++) fmpz_set(fmpz_mat_entry(Brank, i, j), fmpz_mat_entry(B, perm[i], j)); } success = fmpq_mat_solve_fmpz_mat_dixon(Xrank, Arank, Brank); if (success) { fmpq_mat_zero(X); for (i = 0; i < rank; i++) { for (j = 0; j < B->c; j++) fmpq_set(fmpq_mat_entry(X, pivots[i], j), fmpq_mat_entry(Xrank, i, j)); } result = _fmpq_mat_check_solution_fmpz_mat(X, A, B); } fmpz_mat_clear(Arank); fmpz_mat_clear(Brank); fmpq_mat_clear(Xrank); if (result) break; fmpz_mul_ui(tested, tested, p); if (fmpz_cmp(tested, det_bound) > 0) break; } fmpz_clear(det_bound); nmod_mat_clear(Ap); nmod_mat_clear(LU); fmpz_clear(tested); flint_free(perm); flint_free(pivots); return result; } int fmpq_mat_can_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { fmpz_mat_t Anum; fmpz_mat_t Bnum; int success; if (A->r == 0 || B->c == 0) { fmpq_mat_zero(X); return 1; } if (A->c == 0) { fmpq_mat_zero(X); return fmpq_mat_is_zero(B); } fmpz_mat_init(Anum, A->r, A->c); fmpz_mat_init(Bnum, B->r, B->c); fmpq_mat_get_fmpz_mat_rowwise_2(Anum, Bnum, NULL, A, B); success = fmpq_mat_can_solve_fmpz_mat_dixon(X, Anum, Bnum); fmpz_mat_clear(Anum); fmpz_mat_clear(Bnum); return success; } flint-3.1.3/src/fmpq_mat/can_solve_fraction_free.c000066400000000000000000000027711461254215100222400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2022 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" int fmpq_mat_can_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { fmpz_mat_t Anum; fmpz_mat_t Bnum; fmpz_mat_t Xnum; fmpz_t den; int success; if (A->r != B->r || A->c != X->r || X->c != B->c) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_can_solve_fraction_free). Incompatible matrix dimensions.\n"); } if (A->r == 0) { fmpq_mat_zero(X); return 1; } if (A->c == 0) { fmpq_mat_zero(X); return fmpq_mat_is_zero(B); } fmpz_mat_init(Anum, A->r, A->c); fmpz_mat_init(Bnum, B->r, B->c); fmpz_mat_init(Xnum, A->c, B->c); fmpz_init(den); fmpq_mat_get_fmpz_mat_rowwise_2(Anum, Bnum, NULL, A, B); success = fmpz_mat_can_solve_fflu(Xnum, den, Anum, Bnum); if (success) fmpq_mat_set_fmpz_mat_div_fmpz(X, Xnum, den); fmpz_mat_clear(Anum); fmpz_mat_clear(Bnum); fmpz_mat_clear(Xnum); fmpz_clear(den); return success; } flint-3.1.3/src/fmpq_mat/can_solve_multi_mod.c000066400000000000000000000165231461254215100214230ustar00rootroot00000000000000/* Copyright (C) 2019, 2020 William Hart Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq_mat.h" static int _fmpq_mat_check_solution_fmpz_mat(const fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { slong i, j; fmpz_mat_t Xclear, AXclear; fmpz_t t; fmpz * Xden; int ok; Xden = _fmpz_vec_init(X->c); fmpz_mat_init(Xclear, X->r, X->c); fmpz_mat_init(AXclear, A->r, X->c); fmpz_init(t); fmpq_mat_get_fmpz_mat_colwise(Xclear, Xden, X); fmpz_mat_mul(AXclear, A, Xclear); ok = 1; for (i = 0; i < B->r && ok; i++) { for (j = 0; j < B->c && ok; j++) { /* AXclear[i,j] / Xden[j] = B[i,j] */ fmpz_mul(t, fmpz_mat_entry(B, i, j), Xden + j); if (!fmpz_equal(t, fmpz_mat_entry(AXclear, i, j))) ok = 0; } } _fmpz_vec_clear(Xden, X->c); fmpz_mat_clear(Xclear); fmpz_mat_clear(AXclear); fmpz_clear(t); return ok; } static int _permpiv_cmp(slong * perm, slong * prm, slong * pivots, slong * piv, slong n) { slong i; for (i = 0; i < n; i++) { if ((perm[i] < prm[i] && pivots[i] <= piv[i]) || (perm[i] == prm[i] && pivots[i] < piv[i] && pivots[i] != -WORD(1))) return 1; /* earlier pivots/row swaps */ else if (perm[i] > prm[i] || pivots[i] > piv[i]) return -1; /* later pivots/row swaps */ } return 0; /* perms/pivots are the same */ } static void _permpiv_copy(slong * perm, slong * prm, slong * pivots, slong * piv, slong n) { slong i; for (i = 0; i < n; i++) { prm[i] = perm[i]; piv[i] = pivots[i]; } } int _fmpq_mat_can_solve_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B, const fmpz_t D) { fmpz_t pprod, badprod; fmpz_mat_t x; fmpq_mat_t AX; nmod_mat_t Xmod, Amod, Bmod; slong i, n, nexti, rank, rnk; slong * prm, * perm, * piv, * pivots; int stabilised; /* has CRT stabilised */ int res = 1, pcmp, firstp = 1; mp_limb_t p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; n = A->r; fmpz_init(pprod); fmpz_init(badprod); fmpz_one(badprod); perm = (slong *) flint_malloc(n*sizeof(slong)); /* current row perm */ prm = (slong *) flint_malloc(n*sizeof(slong)); /* best row perm */ pivots = (slong *) flint_malloc(n*sizeof(slong)); /* current pivot cols */ piv = (slong *) flint_malloc(n*sizeof(slong)); /* best pivot cols */ for (i = 0; i < n; i++) { perm[i] = i; prm[i] = 0; piv[i] = -WORD(1); pivots[i] = -WORD(1); } rnk = -WORD(1); nmod_mat_init(Amod, A->r, A->c, 1); nmod_mat_init(Bmod, B->r, B->c, 1); nmod_mat_init(Xmod, X->r, X->c, 1); fmpq_mat_init(AX, B->r, B->c); fmpz_mat_init(x, X->r, X->c); fmpz_set_ui(pprod, 1); i = 0; /* working with i primes */ nexti = 1; /* when to do next termination test */ while (1) { stabilised = i == nexti; if (stabilised) /* set next termination test iteration */ nexti = (slong)(i*1.4) + 1; /* full matrix stabilisation check */ if (stabilised) { stabilised = fmpq_mat_set_fmpz_mat_mod_fmpz(X, x, pprod); if (stabilised) { if (_fmpq_mat_check_solution_fmpz_mat(X, A, B)) goto multi_mod_done; } } i++; while (1) { p = n_nextprime(p, 1); nmod_mat_set_mod(Xmod, p); nmod_mat_set_mod(Amod, p); nmod_mat_set_mod(Bmod, p); fmpz_mat_get_nmod_mat(Amod, A); fmpz_mat_get_nmod_mat(Bmod, B); if (!nmod_mat_can_solve_inner(&rank, perm, pivots, Xmod, Amod, Bmod)) { fmpz_mul_ui(badprod, badprod, p); if (fmpz_cmp(badprod, D) > 0) { res = 0; fmpq_mat_zero(X); goto multi_mod_done; } else continue; } pcmp = _permpiv_cmp(perm, prm, pivots, piv, n); if (rank != rnk || pcmp != 0) /* structure not the same as last solve */ { if (rank < rnk) /* rank too low : reject */ continue; else if (rank > rnk) /* rank increased : restart */ { _permpiv_copy(perm, prm, pivots, piv, n); rnk = rank; firstp = 0; fmpz_set_ui(pprod, p); fmpz_mat_set_nmod_mat(x, Xmod); continue; } else if (firstp || pcmp > 0) /* earlier pivots/row swaps : restart */ { _permpiv_copy(perm, prm, pivots, piv, n); firstp = 0; fmpz_set_ui(pprod, p); fmpz_mat_set_nmod_mat(x, Xmod); continue; } else /* worse pivots/row swaps : reject */ continue; } else break; /* everything the same : accept */ } fmpz_mat_CRT_ui(x, x, pprod, Xmod, 0); fmpz_mul_ui(pprod, pprod, p); } fmpq_mat_set_fmpz_mat_mod_fmpz(X, x, pprod); multi_mod_done: nmod_mat_clear(Xmod); nmod_mat_clear(Bmod); nmod_mat_clear(Amod); fmpz_clear(pprod); fmpz_clear(badprod); fmpq_mat_clear(AX); fmpz_mat_clear(x); flint_free(piv); flint_free(pivots); flint_free(perm); flint_free(prm); return res; } int fmpq_mat_can_solve_fmpz_mat_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { fmpz_t D; int res; if (A->r != B->r || A->c != X->r || X->c != B->c) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_can_solve_fmpz_mat_multi_mod). Incompatible matrix dimensions.\n"); } if (A->r == 0) { fmpq_mat_zero(X); return 1; } if (A->c == 0) { fmpq_mat_zero(X); return fmpz_mat_is_zero(B); } fmpz_init(D); fmpz_mat_det_bound_nonzero(D, A); res = _fmpq_mat_can_solve_multi_mod(X, A, B, D); fmpz_clear(D); return res; } int fmpq_mat_can_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { fmpz_mat_t Anum; fmpz_mat_t Bnum; int success; if (A->r != B->r || A->c != X->r || X->c != B->c) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_can_solve_multi_mod). Incompatible matrix dimensions.\n"); } if (A->r == 0) { fmpq_mat_zero(X); return 1; } if (A->c == 0) { fmpq_mat_zero(X); return fmpq_mat_is_zero(B); } fmpz_mat_init(Anum, A->r, A->c); fmpz_mat_init(Bnum, B->r, B->c); fmpq_mat_get_fmpz_mat_rowwise_2(Anum, Bnum, NULL, A, B); success = fmpq_mat_can_solve_fmpz_mat_multi_mod(X, Anum, Bnum); fmpz_mat_clear(Anum); fmpz_mat_clear(Bnum); return success; } flint-3.1.3/src/fmpq_mat/charpoly.c000066400000000000000000000027711461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" #include "fmpq_mat.h" void _fmpq_mat_charpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat) { fmpz_t p; fmpz_mat_t zmat; slong n = mat->r, i; if (n == 0) { fmpz_one(coeffs + 0); fmpz_one(den); return; } fmpz_init(p); fmpz_mat_init(zmat, mat->r, mat->c); fmpq_mat_get_fmpz_mat_matwise(zmat, p, mat); _fmpz_mat_charpoly(coeffs, zmat); if (n > 1) { fmpz_mul(coeffs + 1, coeffs + 1, p); fmpz_mul(den, p, p); } else fmpz_set(den, p); for (i = 2; i < n; i++) { fmpz_mul(coeffs + i, coeffs + i, den); fmpz_mul(den, den, p); } fmpz_mul(coeffs + n, coeffs + n, den); fmpz_mat_clear(zmat); fmpz_clear(p); } void fmpq_mat_charpoly(fmpq_poly_t pol, const fmpq_mat_t mat) { slong n = mat->r; if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_charpoly). Non-square matrix.\n"); } fmpq_poly_fit_length(pol, n + 1); _fmpq_poly_set_length(pol, n + 1); _fmpq_mat_charpoly(pol->coeffs, pol->den, mat); fmpq_poly_canonicalise(pol); } flint-3.1.3/src/fmpq_mat/clear.c000066400000000000000000000013231461254215100164570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_clear(fmpq_mat_t mat) { if (mat->entries) { slong i; for (i = 0; i < mat->r * mat->c; i++) fmpq_clear(mat->entries + i); flint_free(mat->entries); flint_free(mat->rows); } else if (mat->r != 0) flint_free(mat->rows); } flint-3.1.3/src/fmpq_mat/concat_horizontal.c000066400000000000000000000017271461254215100211210ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_concat_horizontal(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { fmpq_set(fmpq_mat_entry(res, i, j), fmpq_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { fmpq_set(fmpq_mat_entry(res, i, j + c1), fmpq_mat_entry(mat2, i, j)); } } } flint-3.1.3/src/fmpq_mat/concat_vertical.c000066400000000000000000000017251461254215100205370ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_concat_vertical(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { fmpq_set(fmpq_mat_entry(res, i, j), fmpq_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { fmpq_set(fmpq_mat_entry(res, i + r1, j), fmpq_mat_entry(mat2, i, j)); } } } flint-3.1.3/src/fmpq_mat/det.c000066400000000000000000000027021461254215100161470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_det(fmpq_t det, const fmpq_mat_t mat) { slong n = mat->r; if (n == 0) { fmpq_set_si(det, WORD(1), WORD(1)); return; } else if (n == 1) { fmpq_set(det, fmpq_mat_entry(mat, 0, 0)); } else if (n == 2) { fmpq_t t; fmpq_init(t); fmpq_mul(t, fmpq_mat_entry(mat, 0, 0), fmpq_mat_entry(mat, 1, 1)); fmpq_submul(t, fmpq_mat_entry(mat, 0, 1), fmpq_mat_entry(mat, 1, 0)); fmpq_set(det, t); fmpq_clear(t); } else { fmpz_mat_t num; fmpz * den; slong i; fmpz_mat_init(num, mat->r, mat->c); den = _fmpz_vec_init(mat->r); fmpq_mat_get_fmpz_mat_rowwise(num, den, mat); fmpz_mat_det(&det->num, num); fmpz_one(&det->den); for (i = 0; i < mat->r; i++) fmpz_mul(&det->den, &det->den, den + i); fmpq_canonicalise(det); fmpz_mat_clear(num); _fmpz_vec_clear(den, mat->r); } } flint-3.1.3/src/fmpq_mat/equal.c000066400000000000000000000015051461254215100165020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" int fmpq_mat_equal(const fmpq_mat_t mat1, const fmpq_mat_t mat2) { slong i, j; if (mat1->r != mat2->r || mat1->c != mat2->c) return 0; for (i = 0; i < mat1->r; i++) { for (j = 0; j < mat1->c; j++) { if (!fmpq_equal(fmpq_mat_entry(mat1, i, j), fmpq_mat_entry(mat2, i, j))) return 0; } } return 1; } flint-3.1.3/src/fmpq_mat/fmpq_vec_mul.c000066400000000000000000000040221461254215100200450ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" void fmpq_mat_fmpq_vec_mul( fmpq* c, const fmpq* a, slong alen, const fmpq_mat_t B) { fmpz den[1], * num; slong i, len = FLINT_MIN(B->r, alen); TMP_INIT; if (len < 1) { for (i = 0; i < B->c; i++) fmpq_zero(c + i); return; } TMP_START; fmpz_init(den); num = TMP_ARRAY_ALLOC(len, fmpz); for (i = 0; i < len; i++) fmpz_init(num + i); _fmpq_vec_get_fmpz_vec_fmpz(num, den, a, len); fmpq_mat_fmpz_vec_mul(c, num, len, B); for (i = 0; i < B->c; i++) fmpq_div_fmpz(c + i, c + i, den); fmpz_clear(den); for (i = 0; i < len; i++) fmpz_clear(num + i); TMP_END; } void fmpq_mat_fmpq_vec_mul_ptr( fmpq * const * c, const fmpq * const * a, slong alen, const fmpq_mat_t B) { fmpz den[1], * num, ** num_ptrs; fmpq * ta; slong i, len = FLINT_MIN(B->r, alen); TMP_INIT; if (len < 1) { for (i = 0; i < B->c; i++) fmpq_zero(c[i]); return; } TMP_START; fmpz_init(den); num = TMP_ARRAY_ALLOC(len, fmpz); num_ptrs = TMP_ARRAY_ALLOC(len, fmpz*); ta = TMP_ARRAY_ALLOC(len, fmpq); for (i = 0; i < len; i++) { fmpz_init(num + i); num_ptrs[i] = num + i; ta[i] = *a[i]; } _fmpq_vec_get_fmpz_vec_fmpz(num, den, ta, len); fmpq_mat_fmpz_vec_mul_ptr(c, (const fmpz * const *)num_ptrs, len, B); for (i = 0; i < B->c; i++) fmpq_div_fmpz(c[i], c[i], den); fmpz_clear(den); for (i = 0; i < len; i++) fmpz_clear(num + i); TMP_END; } flint-3.1.3/src/fmpq_mat/fmpz_vec_mul.c000066400000000000000000000031031461254215100200550ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_fmpz_vec_mul( fmpq * c, const fmpz * a, slong alen, const fmpq_mat_t B) { fmpq_t t; slong i, j; slong len = FLINT_MIN(B->r, alen); if (len < 1) { for (i = 0; i < B->c; i++) fmpq_zero(c + i); return; } fmpq_init(t); for (i = 0; i < B->c; i++) { fmpq_mul_fmpz(c + i, fmpq_mat_entry(B, 0, i), a + 0); for (j = 1; j < len; j++) { fmpq_mul_fmpz(t, fmpq_mat_entry(B, j, i), a + j); fmpq_add(c + i, c + i, t); } } fmpq_clear(t); } void fmpq_mat_fmpz_vec_mul_ptr( fmpq * const * c, const fmpz * const * a, slong alen, const fmpq_mat_t B) { fmpq_t t; slong i, j; slong len = FLINT_MIN(B->r, alen); if (len < 1) { for (i = 0; i < B->c; i++) fmpq_zero(c[i]); return; } fmpq_init(t); for (i = 0; i < B->c; i++) { fmpq_mul_fmpz(c[i], fmpq_mat_entry(B, 0, i), a[0]); for (j = 1; j < len; j++) { fmpq_mul_fmpz(t, fmpq_mat_entry(B, j, i), a[j]); fmpq_add(c[i], c[i], t); } } fmpq_clear(t); } flint-3.1.3/src/fmpq_mat/get_fmpz_mat.c000066400000000000000000000015351461254215100200520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" int fmpq_mat_get_fmpz_mat(fmpz_mat_t dest, const fmpq_mat_t mat) { slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (fmpz_is_one(fmpq_mat_entry_den(mat, i, j))) fmpz_set(fmpz_mat_entry(dest, i, j), fmpq_mat_entry_num(mat, i, j)); else return 0; } } return 1; } flint-3.1.3/src/fmpq_mat/get_fmpz_mat_colwise.c000066400000000000000000000030051461254215100215710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" void fmpq_mat_get_fmpz_mat_colwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat) { fmpz_t t, lcm; slong i, j; if (fmpq_mat_is_empty(mat)) return; fmpz_init(t); fmpz_init(lcm); for (j = 0; j < mat->c; j++) { /* Compute common denominator of column */ fmpz_set(lcm, fmpq_mat_entry_den(mat, 0, j)); for (i = 1; i < mat->r; i++) fmpz_lcm(lcm, lcm, fmpq_mat_entry_den(mat, i, j)); if (den != NULL) fmpz_set(den + j, lcm); /* Rescale numerators in column */ if (fmpz_is_one(lcm)) { for (i = 0; i < mat->r; i++) fmpz_set(fmpz_mat_entry(num, i, j), fmpq_mat_entry_num(mat, i, j)); } else { for (i = 0; i < mat->r; i++) { fmpz_divexact(t, lcm, fmpq_mat_entry_den(mat, i, j)); fmpz_mul(fmpz_mat_entry(num, i, j), fmpq_mat_entry_num(mat, i, j), t); } } } fmpz_clear(t); fmpz_clear(lcm); } flint-3.1.3/src/fmpq_mat/get_fmpz_mat_entrywise.c000066400000000000000000000015401461254215100221570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" void fmpq_mat_get_fmpz_mat_entrywise(fmpz_mat_t num, fmpz_mat_t den, const fmpq_mat_t mat) { slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { fmpz_set(fmpz_mat_entry(num, i, j), fmpq_mat_entry_num(mat, i, j)); fmpz_set(fmpz_mat_entry(den, i, j), fmpq_mat_entry_den(mat, i, j)); } } } flint-3.1.3/src/fmpq_mat/get_fmpz_mat_matwise.c000066400000000000000000000027351461254215100216060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" void fmpq_mat_get_fmpz_mat_matwise(fmpz_mat_t num, fmpz_t den, const fmpq_mat_t mat) { fmpz_t t, lcm; slong i, j; if (fmpq_mat_is_empty(mat)) { fmpz_one(den); return; } fmpz_init(t); fmpz_init(lcm); fmpz_one(lcm); /* Compute common denominator of matrix */ for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpz_lcm(lcm, lcm, fmpq_mat_entry_den(mat, i, j)); fmpz_set(den, lcm); for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { /* Rescale numerators */ if (fmpz_is_one(lcm)) { fmpz_set(fmpz_mat_entry(num, i, j), fmpq_mat_entry_num(mat, i, j)); } else { fmpz_divexact(t, lcm, fmpq_mat_entry_den(mat, i, j)); fmpz_mul(fmpz_mat_entry(num, i, j), fmpq_mat_entry_num(mat, i, j), t); } } } fmpz_clear(t); fmpz_clear(lcm); } flint-3.1.3/src/fmpq_mat/get_fmpz_mat_mod_fmpz.c000066400000000000000000000016001461254215100217360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" /* TODO: we may want to clear denominators to avoid expensive invmods */ void fmpq_mat_get_fmpz_mat_mod_fmpz(fmpz_mat_t dest, const fmpq_mat_t mat, const fmpz_t mod) { slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { fmpq_mod_fmpz(fmpz_mat_entry(dest, i, j), fmpq_mat_entry(mat, i, j), mod); } } } flint-3.1.3/src/fmpq_mat/get_fmpz_mat_rowwise.c000066400000000000000000000044751461254215100216370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" void _fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_struct ** num, fmpz * den, const fmpq_mat_struct ** mat, slong n) { fmpz_t t, lcm; slong i, j, k; if (fmpq_mat_is_empty(mat[0])) return; fmpz_init(t); fmpz_init(lcm); for (i = 0; i < mat[0]->r; i++) { /* Compute common denominator of row */ fmpz_set(lcm, fmpq_mat_entry_den(mat[0], i, 0)); for (k = 0; k < n; k++) for (j = (k == 0); j < mat[k]->c; j++) fmpz_lcm(lcm, lcm, fmpq_mat_entry_den(mat[k], i, j)); if (den != NULL) fmpz_set(den + i, lcm); for (k = 0; k < n; k++) { /* Rescale numerators in row */ if (fmpz_is_one(lcm)) { for (j = 0; j < mat[k]->c; j++) fmpz_set(fmpz_mat_entry(num[k], i, j), fmpq_mat_entry_num(mat[k], i, j)); } else { for (j = 0; j < mat[k]->c; j++) { fmpz_divexact(t, lcm, fmpq_mat_entry_den(mat[k], i, j)); fmpz_mul(fmpz_mat_entry(num[k], i, j), fmpq_mat_entry_num(mat[k], i, j), t); } } } } fmpz_clear(t); fmpz_clear(lcm); } void fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat) { _fmpq_mat_get_fmpz_mat_rowwise(&num, den, &mat, 1); } void fmpq_mat_get_fmpz_mat_rowwise_2(fmpz_mat_t num, fmpz_mat_t num2, fmpz * den, const fmpq_mat_t mat, const fmpq_mat_t mat2) { fmpz_mat_struct * nums[2]; fmpq_mat_struct * mats[2]; nums[0] = num; nums[1] = num2; mats[0] = (fmpq_mat_struct *) mat; mats[1] = (fmpq_mat_struct *) mat2; _fmpq_mat_get_fmpz_mat_rowwise(nums, den, (const fmpq_mat_struct **) mats, 2); } flint-3.1.3/src/fmpq_mat/gso.c000066400000000000000000000040311461254215100161600ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_gso(fmpq_mat_t B, const fmpq_mat_t A) { slong i, j, k; fmpq_t num, den, mu; if (B->r != A->r || B->c != A->c) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_gso). Incompatible dimensions.\n"); } if (B == A) { fmpq_mat_t t; fmpq_mat_init(t, B->r, B->c); fmpq_mat_gso(t, A); fmpq_mat_swap_entrywise(B, t); fmpq_mat_clear(t); return; } if (A->r == 0) { return; } fmpq_init(num); fmpq_init(den); fmpq_init(mu); for (i = 0; i < A->c; i++) { for (j = 0; j < A->r; j++) { fmpq_set(fmpq_mat_entry(B, j, i), fmpq_mat_entry(A, j, i)); } for (j = 0; j < i; j++) { fmpq_mul(num, fmpq_mat_entry(A, 0, i), fmpq_mat_entry(B, 0, j)); for (k = 1; k < A->r; k++) { fmpq_addmul(num, fmpq_mat_entry(A, k, i), fmpq_mat_entry(B, k, j)); } fmpq_mul(den, fmpq_mat_entry(B, 0, j), fmpq_mat_entry(B, 0, j)); for (k = 1; k < A->r; k++) { fmpq_addmul(den, fmpq_mat_entry(B, k, j), fmpq_mat_entry(B, k, j)); } if (!fmpq_is_zero(den)) { fmpq_div(mu, num, den); for (k = 0; k < A->r; k++) { fmpq_submul(fmpq_mat_entry(B, k, i), mu, fmpq_mat_entry(B, k, j)); } } } } fmpq_clear(num); fmpq_clear(den); fmpq_clear(mu); } flint-3.1.3/src/fmpq_mat/hilbert_matrix.c000066400000000000000000000011621461254215100204070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_hilbert_matrix(fmpq_mat_t mat) { slong i, j; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_set_si(fmpq_mat_entry(mat, i, j), 1, i + j + 1); } flint-3.1.3/src/fmpq_mat/init.c000066400000000000000000000022431461254215100163360ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" void fmpq_mat_init(fmpq_mat_t mat, slong rows, slong cols) { slong i; if (rows != 0) mat->rows = (fmpq **) flint_malloc(rows * sizeof(fmpq *)); else mat->rows = NULL; if (rows != 0 && cols != 0) { mat->entries = (fmpq *) flint_calloc(flint_mul_sizes(rows, cols), sizeof(fmpq)); /* Set denominators */ for (i = 0; i < rows * cols; i++) mat->entries[i].den = WORD(1); for (i = 0; i < rows; i++) mat->rows[i] = mat->entries + i * cols; } else { mat->entries = NULL; if (rows != 0) { for (i = 0; i < rows; i++) mat->rows[i] = NULL; } } mat->r = rows; mat->c = cols; } flint-3.1.3/src/fmpq_mat/init_set.c000066400000000000000000000010771461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" void fmpq_mat_init_set(fmpq_mat_t mat, const fmpq_mat_t src) { fmpq_mat_init(mat, src->r, src->c); fmpq_mat_set(mat, src); } flint-3.1.3/src/fmpq_mat/inlines.c000066400000000000000000000006541461254215100170400ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPQ_MAT_INLINES_C #include "fmpq_mat.h" flint-3.1.3/src/fmpq_mat/inv.c000066400000000000000000000045531461254215100161750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" int fmpq_mat_inv(fmpq_mat_t B, const fmpq_mat_t A) { slong n = A->r; if (n == 0) { return 1; } else if (n == 1) { if (fmpq_is_zero(fmpq_mat_entry(A, 0, 0))) return 0; fmpq_inv(fmpq_mat_entry(B, 0, 0), fmpq_mat_entry(A, 0, 0)); return 1; } else if (n == 2) { fmpq_t d; int success; fmpq_init(d); fmpq_mul(d, fmpq_mat_entry(A, 0, 0), fmpq_mat_entry(A, 1, 1)); fmpq_submul(d, fmpq_mat_entry(A, 0, 1), fmpq_mat_entry(A, 1, 0)); success = !fmpq_is_zero(d); if (success) { fmpq_t t00, t01, t10, t11; fmpq_inv(d, d); fmpq_init(t00); fmpq_init(t01); fmpq_init(t10); fmpq_init(t11); fmpq_mul(t00, fmpq_mat_entry(A, 1, 1), d); fmpq_mul(t01, fmpq_mat_entry(A, 0, 1), d); fmpq_mul(t10, fmpq_mat_entry(A, 1, 0), d); fmpq_mul(t11, fmpq_mat_entry(A, 0, 0), d); fmpq_set(fmpq_mat_entry(B, 0, 0), t00); fmpq_neg(fmpq_mat_entry(B, 0, 1), t01); fmpq_neg(fmpq_mat_entry(B, 1, 0), t10); fmpq_set(fmpq_mat_entry(B, 1, 1), t11); fmpq_clear(t00); fmpq_clear(t01); fmpq_clear(t10); fmpq_clear(t11); } fmpq_clear(d); return success; } else { fmpz_mat_t Aclear, I; fmpz * den; slong i; int success; fmpz_mat_init(Aclear, n, n); fmpz_mat_init(I, n, n); den = _fmpz_vec_init(n); fmpq_mat_get_fmpz_mat_rowwise(Aclear, den, A); for (i = 0; i < n; i++) fmpz_set(fmpz_mat_entry(I, i, i), den + i); success = fmpq_mat_solve_fmpz_mat(B, Aclear, I); fmpz_mat_clear(Aclear); fmpz_mat_clear(I); _fmpz_vec_clear(den, A->r); return success; } } flint-3.1.3/src/fmpq_mat/invert.c000066400000000000000000000020371461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_invert_rows(fmpq_mat_t mat, slong * perm) { slong i; for (i = 0; i < mat->r/2; i++) fmpq_mat_swap_rows(mat, perm, i, mat->r - i - 1); } void fmpq_mat_invert_cols(fmpq_mat_t mat, slong * perm) { if (!fmpq_mat_is_empty(mat)) { slong t, i; slong c = mat->c; slong k = mat->c/2; if (perm != NULL) for (i = 0; i < k; i++) FLINT_SWAP(slong, perm[i], perm[c - i - 1]); for (t = 0; t < mat->r; t++) for (i = 0; i < k; i++) fmpq_swap(fmpq_mat_entry(mat, t, i), fmpq_mat_entry(mat, t, c - i - 1)); } } flint-3.1.3/src/fmpq_mat/io.c000066400000000000000000000016501461254215100160030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" /* printing *******************************************************************/ void fmpq_mat_print(const fmpq_mat_t mat) { slong i, j; flint_printf("<%wd x %wd matrix over Q>\n", mat->r, mat->c); for (i = 0; i < mat->r; i++) { flint_printf("["); for (j = 0; j < mat->c; j++) { fmpq_print(fmpq_mat_entry(mat, i, j)); if (j + 1 < mat->c) flint_printf(", "); } flint_printf("]\n"); } flint_printf("\n"); } flint-3.1.3/src/fmpq_mat/is_integral.c000066400000000000000000000012701461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_mat.h" int fmpq_mat_is_integral(const fmpq_mat_t mat) { slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (!fmpz_is_one(fmpq_mat_entry_den(mat, i, j))) return 0; } } return 1; } flint-3.1.3/src/fmpq_mat/is_one.c000066400000000000000000000014621461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" int fmpq_mat_is_one(const fmpq_mat_t mat) { slong i, j; if (mat->r == 0 || mat->c == 0) return 1; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (fmpq_cmp_ui(fmpq_mat_entry(mat, i, j), i == j) != 0) { return 0; } } } return 1; } flint-3.1.3/src/fmpq_mat/is_zero.c000066400000000000000000000012611461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" int fmpq_mat_is_zero(const fmpq_mat_t mat) { slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (!fmpq_is_zero(fmpq_mat_entry(mat, i, j))) return 0; } } return 1; } flint-3.1.3/src/fmpq_mat/kronecker_product.c000066400000000000000000000017451461254215100211240ustar00rootroot00000000000000/* Copyright (C) 2018 Martin Raum This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_kronecker_product(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) { slong i, j, k, l; slong ir, jc; fmpq * Aentry; for (i = 0, ir = 0; i < A->r; i++, ir += B->r) { for (j = 0, jc = 0; j < A->c; j++, jc += B->c) { Aentry = fmpq_mat_entry(A, i, j); for (k = 0; k < B->r; k++) { for (l = 0; l < B->c; l++) { fmpq_mul(fmpq_mat_entry(C, ir + k, jc + l), Aentry, fmpq_mat_entry(B, k, l)); } } } } } flint-3.1.3/src/fmpq_mat/minpoly.c000066400000000000000000000030571461254215100170660ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" #include "fmpq_mat.h" slong _fmpq_mat_minpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat) { fmpz_t p; fmpz_mat_t zmat; slong n = mat->r, len, i; if (n == 0) { fmpz_one(coeffs + 0); fmpz_one(den); return 1; } fmpz_init(p); fmpz_mat_init(zmat, mat->r, mat->c); fmpq_mat_get_fmpz_mat_matwise(zmat, p, mat); len = _fmpz_mat_minpoly(coeffs, zmat); if (len > 2) { fmpz_mul(coeffs + 1, coeffs + 1, p); fmpz_mul(den, p, p); } else fmpz_set(den, p); for (i = 2; i < len - 1; i++) { fmpz_mul(coeffs + i, coeffs + i, den); fmpz_mul(den, den, p); } fmpz_mul(coeffs + len - 1, coeffs + len - 1, den); fmpz_mat_clear(zmat); fmpz_clear(p); return len; } void fmpq_mat_minpoly(fmpq_poly_t pol, const fmpq_mat_t mat) { slong n = mat->r, len; if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_minpoly). Non-square matrix.\n"); } fmpq_poly_fit_length(pol, n + 1); len = _fmpq_mat_minpoly(pol->coeffs, pol->den, mat); _fmpq_poly_set_length(pol, len); fmpq_poly_canonicalise(pol); } flint-3.1.3/src/fmpq_mat/mul.c000066400000000000000000000011031461254215100161620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" void fmpq_mat_mul(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) { /* This is faster except maybe for 1x1 or 2x2 matrices */ fmpq_mat_mul_cleared(C, A, B); } flint-3.1.3/src/fmpq_mat/mul_cleared.c000066400000000000000000000027131461254215100176510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_mul_cleared(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) { slong i, j; fmpz_mat_t Aclear; fmpz_mat_t Bclear; fmpz_mat_t Cclear; fmpz * Aden; fmpz * Bden; fmpz_mat_init(Aclear, A->r, A->c); fmpz_mat_init(Bclear, B->r, B->c); fmpz_mat_init(Cclear, A->r, B->c); Aden = _fmpz_vec_init(A->r); Bden = _fmpz_vec_init(B->c); fmpq_mat_get_fmpz_mat_rowwise(Aclear, Aden, A); fmpq_mat_get_fmpz_mat_colwise(Bclear, Bden, B); fmpz_mat_mul(Cclear, Aclear, Bclear); for (i = 0; i < C->r; i++) { for (j = 0; j < C->c; j++) { fmpz_set(fmpq_mat_entry_num(C, i, j), fmpz_mat_entry(Cclear, i, j)); fmpz_mul(fmpq_mat_entry_den(C, i, j), Aden + i, Bden + j); fmpq_canonicalise(fmpq_mat_entry(C, i, j)); } } fmpz_mat_clear(Aclear); fmpz_mat_clear(Bclear); fmpz_mat_clear(Cclear); _fmpz_vec_clear(Aden, A->r); _fmpz_vec_clear(Bden, B->c); } flint-3.1.3/src/fmpq_mat/mul_direct.c000066400000000000000000000022631461254215100175240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_mul_direct(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B) { slong i, j, k; if (A == C || B == C) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_mul_direct). Aliasing not implemented.\n"); } if (A->c == 0) { fmpq_mat_zero(C); return; } for (i = 0; i < A->r; i++) { for (j = 0; j < B->c; j++) { fmpq_mul(fmpq_mat_entry(C, i, j), fmpq_mat_entry(A, i, 0), fmpq_mat_entry(B, 0, j)); for (k = 1; k < A->c; k++) { fmpq_addmul(fmpq_mat_entry(C, i, j), fmpq_mat_entry(A, i, k), fmpq_mat_entry(B, k, j)); } } } } flint-3.1.3/src/fmpq_mat/mul_fmpq_vec.c000066400000000000000000000040161461254215100200500ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" void fmpq_mat_mul_fmpq_vec( fmpq * c, const fmpq_mat_t A, const fmpq * b, slong blen) { fmpz den[1], * num; slong i, len = FLINT_MIN(A->c, blen); TMP_INIT; if (A->r < 1 || len < 1) { for (i = 0; i < A->r; i++) fmpq_zero(c + i); return; } TMP_START; fmpz_init(den); num = TMP_ARRAY_ALLOC(len, fmpz); for (i = 0; i < len; i++) fmpz_init(num + i); _fmpq_vec_get_fmpz_vec_fmpz(num, den, b, len); fmpq_mat_mul_fmpz_vec(c, A, num, len); for (i = 0; i < A->r; i++) fmpq_div_fmpz(c + i, c + i, den); fmpz_clear(den); for (i = 0; i < len; i++) fmpz_clear(num + i); TMP_END; } void fmpq_mat_mul_fmpq_vec_ptr( fmpq * const * c, const fmpq_mat_t A, const fmpq * const * b, slong blen) { fmpz den[1], * num, ** num_ptrs; fmpq * tb; slong i, len = FLINT_MIN(A->c, blen); TMP_INIT; if (len < 1) { for (i = 0; i < A->r; i++) fmpq_zero(c[i]); return; } TMP_START; fmpz_init(den); num = TMP_ARRAY_ALLOC(len, fmpz); num_ptrs = TMP_ARRAY_ALLOC(len, fmpz*); tb = TMP_ARRAY_ALLOC(len, fmpq); for (i = 0; i < len; i++) { fmpz_init(num + i); num_ptrs[i] = num + i; tb[i] = *b[i]; } _fmpq_vec_get_fmpz_vec_fmpz(num, den, tb, len); fmpq_mat_mul_fmpz_vec_ptr(c, A, (const fmpz * const *)num_ptrs, len); for (i = 0; i < A->r; i++) fmpq_div_fmpz(c[i], c[i], den); fmpz_clear(den); for (i = 0; i < len; i++) fmpz_clear(num + i); TMP_END; } flint-3.1.3/src/fmpq_mat/mul_fmpz_mat.c000066400000000000000000000023111461254215100200610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_mul_fmpz_mat(fmpq_mat_t C, const fmpq_mat_t A, const fmpz_mat_t B) { slong i, j; fmpz_mat_t Aclear; fmpz_mat_t Cclear; fmpz * Aden; fmpz_mat_init(Aclear, A->r, A->c); fmpz_mat_init(Cclear, A->r, B->c); Aden = _fmpz_vec_init(A->r); fmpq_mat_get_fmpz_mat_rowwise(Aclear, Aden, A); fmpz_mat_mul(Cclear, Aclear, B); for (i = 0; i < C->r; i++) { for (j = 0; j < C->c; j++) { fmpz_set(fmpq_mat_entry_num(C, i, j), fmpz_mat_entry(Cclear, i, j)); fmpz_set(fmpq_mat_entry_den(C, i, j), Aden + i); fmpq_canonicalise(fmpq_mat_entry(C, i, j)); } } fmpz_mat_clear(Aclear); fmpz_mat_clear(Cclear); _fmpz_vec_clear(Aden, A->r); } flint-3.1.3/src/fmpq_mat/mul_fmpz_vec.c000066400000000000000000000031111461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_mul_fmpz_vec( fmpq* c, const fmpq_mat_t A, const fmpz * b, slong blen) { fmpq_t t; slong i, j; slong len = FLINT_MIN(A->c, blen); if (len < 1) { for (i = 0; i < A->r; i++) fmpq_zero(c + i); return; } fmpq_init(t); for (i = 0; i < A->r; i++) { const fmpq* Ai = A->rows[i]; fmpq_mul_fmpz(c + i, Ai + 0, b + 0); for (j = 1; j < len; j++) { fmpq_mul_fmpz(t, Ai + j, b + j); fmpq_add(c + i, c + i, t); } } fmpq_clear(t); } void fmpq_mat_mul_fmpz_vec_ptr( fmpq * const * c, const fmpq_mat_t A, const fmpz * const * b, slong blen) { fmpq_t t; slong i, j; slong len = FLINT_MIN(A->c, blen); if (len < 1) { for (i = 0; i < A->r; i++) fmpq_zero(c[i]); return; } fmpq_init(t); for (i = 0; i < A->r; i++) { const fmpq* Ai = A->rows[i]; fmpq_mul_fmpz(c[i], Ai + 0, b[0]); for (j = 1; j < len; j++) { fmpq_mul_fmpz(t, Ai + j, b[j]); fmpq_add(c[i], c[i], t); } } fmpq_clear(t); } flint-3.1.3/src/fmpq_mat/mul_r_fmpz_mat.c000066400000000000000000000023131461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_mul_r_fmpz_mat(fmpq_mat_t C, const fmpz_mat_t A, const fmpq_mat_t B) { slong i, j; fmpz_mat_t Bclear; fmpz_mat_t Cclear; fmpz * Bden; fmpz_mat_init(Bclear, B->r, B->c); fmpz_mat_init(Cclear, A->r, B->c); Bden = _fmpz_vec_init(B->c); fmpq_mat_get_fmpz_mat_colwise(Bclear, Bden, B); fmpz_mat_mul(Cclear, A, Bclear); for (i = 0; i < C->r; i++) { for (j = 0; j < C->c; j++) { fmpz_set(fmpq_mat_entry_num(C, i, j), fmpz_mat_entry(Cclear, i, j)); fmpz_set(fmpq_mat_entry_den(C, i, j), Bden + j); fmpq_canonicalise(fmpq_mat_entry(C, i, j)); } } fmpz_mat_clear(Bclear); fmpz_mat_clear(Cclear); _fmpz_vec_clear(Bden, B->c); } flint-3.1.3/src/fmpq_mat/neg.c000066400000000000000000000012311461254215100161400ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_neg(fmpq_mat_t rop, const fmpq_mat_t op) { slong i, j; for (i = 0; i < op->r; i++) for (j = 0; j < op->c; j++) fmpq_neg(fmpq_mat_entry(rop, i, j), fmpq_mat_entry(op, i, j)); } flint-3.1.3/src/fmpq_mat/one.c000066400000000000000000000013171461254215100161550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_one(fmpq_mat_t mat) { slong i, j, min; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_zero(fmpq_mat_entry(mat, i, j)); min = FLINT_MIN(mat->r, mat->c); for (i = 0; i < min; i++) fmpq_one(fmpq_mat_entry(mat, i, i)); } flint-3.1.3/src/fmpq_mat/pivot.c000066400000000000000000000017501461254215100165360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" int fmpq_mat_pivot(slong * perm, fmpq_mat_t mat, slong r, slong c) { slong t, j; fmpq * u; if (!fmpq_is_zero(fmpq_mat_entry(mat, r, c))) return 1; for (j = r + 1; j < mat->r; j++) { if (!fmpq_is_zero(fmpq_mat_entry(mat, j, c))) { if (perm) { t = perm[j]; perm[j] = perm[r]; perm[r] = t; } u = mat->rows[j]; mat->rows[j] = mat->rows[r]; mat->rows[r] = u; return -1; } } return 0; } flint-3.1.3/src/fmpq_mat/randbits.c000066400000000000000000000012241461254215100171770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_randbits(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong i, j; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_randbits(fmpq_mat_entry(mat,i,j), state, bits); } flint-3.1.3/src/fmpq_mat/randtest.c000066400000000000000000000012241461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_randtest(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong i, j; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_randtest(fmpq_mat_entry(mat,i,j), state, bits); } flint-3.1.3/src/fmpq_mat/rref.c000066400000000000000000000011311461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" slong fmpq_mat_rref(fmpq_mat_t B, const fmpq_mat_t A) { if (A->r <= 2 || A->c <= 2) return fmpq_mat_rref_classical(B, A); else return fmpq_mat_rref_fraction_free(B, A); } flint-3.1.3/src/fmpq_mat/rref_classical.c000066400000000000000000000034731461254215100203550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" slong fmpq_mat_rref_classical(fmpq_mat_t B, const fmpq_mat_t A) { slong m, n, i, j, pivot_row, pivot_col, rank; m = A->r; n = A->c; if (m == 0 || n == 0) return 0; if (A != B) fmpq_mat_set(B, A); rank = 0; pivot_row = 0; pivot_col = 0; while (pivot_row < m && pivot_col < n) { if (!fmpq_mat_pivot(NULL, B, pivot_row, pivot_col)) { pivot_col++; continue; } rank++; /* Scale row to have 1 as leading entry */ for (j = pivot_col + 1; j < n; j++) { fmpq_div(fmpq_mat_entry(B, pivot_row, j), fmpq_mat_entry(B, pivot_row, j), fmpq_mat_entry(B, pivot_row, pivot_col)); } /* Eliminate rows above and below */ for (i = 0; i < m; i++) { if (i == pivot_row || fmpq_is_zero(fmpq_mat_entry(B, i, pivot_col))) continue; for (j = pivot_col + 1; j < n; j++) fmpq_submul(fmpq_mat_entry(B, i, j), fmpq_mat_entry(B, pivot_row, j), fmpq_mat_entry(B, i, pivot_col)); } /* Clear pivot column */ for (i = 0; i < m; i++) fmpq_set_si(fmpq_mat_entry(B, i, pivot_col), i == pivot_row, 1); pivot_row++; pivot_col++; } return rank; } flint-3.1.3/src/fmpq_mat/rref_fraction_free.c000066400000000000000000000017011461254215100212150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" slong fmpq_mat_rref_fraction_free(fmpq_mat_t B, const fmpq_mat_t A) { fmpz_mat_t Aclear; fmpz_t den; slong rank; if (fmpq_mat_is_empty(A)) return 0; fmpz_mat_init(Aclear, A->r, A->c); fmpq_mat_get_fmpz_mat_rowwise(Aclear, NULL, A); fmpz_init(den); rank = fmpz_mat_rref(Aclear, den, Aclear); if (rank == 0) fmpq_mat_zero(B); else fmpq_mat_set_fmpz_mat_div_fmpz(B, Aclear, den); fmpz_mat_clear(Aclear); fmpz_clear(den); return rank; } flint-3.1.3/src/fmpq_mat/scalar_div_fmpz.c000066400000000000000000000013401461254215100205330ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_scalar_div_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x) { slong i, j; for (i = 0; i < op->r; i++) for (j = 0; j < op->c; j++) fmpq_div_fmpz(fmpq_mat_entry(rop, i, j), fmpq_mat_entry(op, i, j), x); } flint-3.1.3/src/fmpq_mat/scalar_mul_fmpq.c000066400000000000000000000013501461254215100205360ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz, 2018 Martin Raum This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_scalar_mul_fmpq(fmpq_mat_t rop, const fmpq_mat_t op, const fmpq_t x) { slong i, j; for (i = 0; i < op->r; i++) for (j = 0; j < op->c; j++) fmpq_mul(fmpq_mat_entry(rop, i, j), fmpq_mat_entry(op, i, j), x); } flint-3.1.3/src/fmpq_mat/scalar_mul_fmpz.c000066400000000000000000000013401461254215100205460ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_scalar_mul_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x) { slong i, j; for (i = 0; i < op->r; i++) for (j = 0; j < op->c; j++) fmpq_mul_fmpz(fmpq_mat_entry(rop, i, j), fmpq_mat_entry(op, i, j), x); } flint-3.1.3/src/fmpq_mat/set.c000066400000000000000000000012051461254215100161630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_set(fmpq_mat_t dest, const fmpq_mat_t src) { slong i, j; for (i = 0; i < src->r; i++) for (j = 0; j < src->c; j++) fmpq_set(fmpq_mat_entry(dest,i,j), fmpq_mat_entry(src,i,j)); } flint-3.1.3/src/fmpq_mat/set_fmpz_mat.c000066400000000000000000000014021461254215100200570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" void fmpq_mat_set_fmpz_mat(fmpq_mat_t dest, const fmpz_mat_t src) { slong i, j; for (i = 0; i < src->r; i++) { for (j = 0; j < src->c; j++) { fmpz_set(fmpq_mat_entry_num(dest, i, j), fmpz_mat_entry(src, i, j)); fmpz_one(fmpq_mat_entry_den(dest, i, j)); } } } flint-3.1.3/src/fmpq_mat/set_fmpz_mat_div_fmpz.c000066400000000000000000000027421461254215100217650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_set_fmpz_mat_div_fmpz(fmpq_mat_t X, const fmpz_mat_t Xnum, const fmpz_t den) { slong i, j; if (fmpz_is_one(den)) { fmpq_mat_set_fmpz_mat(X, Xnum); } else if (*den == WORD(-1)) { fmpz_t t; fmpz_init(t); fmpz_set(t, den); for (i = 0; i < Xnum->r; i++) { for (j = 0; j < Xnum->c; j++) { fmpz_neg(fmpq_mat_entry_num(X, i, j), fmpz_mat_entry(Xnum, i, j)); fmpz_one(fmpq_mat_entry_den(X, i, j)); } } fmpz_clear(t); } else { for (i = 0; i < Xnum->r; i++) { for (j = 0; j < Xnum->c; j++) { fmpz_set(fmpq_mat_entry_num(X, i, j), fmpz_mat_entry(Xnum, i, j)); fmpz_set(fmpq_mat_entry_den(X, i, j), den); fmpq_canonicalise(fmpq_mat_entry(X, i, j)); } } } } flint-3.1.3/src/fmpq_mat/set_fmpz_mat_mod_fmpz.c000066400000000000000000000030331461254215100217540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" int fmpq_mat_set_fmpz_mat_mod_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t mod) { fmpz_t num, den, t, u, d; slong i, j; int success = 1; fmpz_init(num); fmpz_init(den); fmpz_init(d); fmpz_init(t); fmpz_init(u); fmpz_one(d); for (i = 0; i < Xmod->r; i++) { for (j = 0; j < Xmod->c; j++) { /* TODO: handle various special cases efficiently; zeros, small integers, etc. */ fmpz_mul(t, d, fmpz_mat_entry(Xmod, i, j)); fmpz_fdiv_qr(u, t, t, mod); success = _fmpq_reconstruct_fmpz(num, den, t, mod); if (!success) goto cleanup; fmpz_mul(den, den, d); fmpz_set(d, den); fmpz_set(fmpq_mat_entry_num(X, i, j), num); fmpz_set(fmpq_mat_entry_den(X, i, j), den); fmpq_canonicalise(fmpq_mat_entry(X, i, j)); } } cleanup: fmpz_clear(num); fmpz_clear(den); fmpz_clear(d); fmpz_clear(t); fmpz_clear(u); return success; } flint-3.1.3/src/fmpq_mat/similarity.c000066400000000000000000000017741461254215100175710ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_similarity(fmpq_mat_t A, slong r, fmpq_t d) { slong n = A->r, i, j; for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) fmpq_addmul(fmpq_mat_entry(A, i, j), fmpq_mat_entry(A, i, r), d); for (j = r + 1; j < n; j++) fmpq_addmul(fmpq_mat_entry(A, i, j), fmpq_mat_entry(A, i, r), d); } for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) fmpq_submul(fmpq_mat_entry(A, r, i), fmpq_mat_entry(A, j, i), d); for (j = r + 1; j < n; j++) fmpq_submul(fmpq_mat_entry(A, r, i), fmpq_mat_entry(A, j, i), d); } } flint-3.1.3/src/fmpq_mat/solve.c000066400000000000000000000020571461254215100165260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" int fmpq_mat_solve_fmpz_mat(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { if (fmpz_mat_nrows(A) <= 15) return fmpq_mat_solve_fmpz_mat_fraction_free(X, A, B); else if (fmpz_mat_ncols(B) == 1) return fmpq_mat_solve_fmpz_mat_dixon(X, A, B); else return fmpq_mat_solve_fmpz_mat_multi_mod(X, A, B); } int fmpq_mat_solve(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { if (fmpq_mat_nrows(A) <= 15) return fmpq_mat_solve_fraction_free(X, A, B); else if (fmpq_mat_ncols(B) == 1) return fmpq_mat_solve_dixon(X, A, B); else return fmpq_mat_solve_multi_mod(X, A, B); } flint-3.1.3/src/fmpq_mat/solve_dixon.c000066400000000000000000000126441461254215100177320ustar00rootroot00000000000000/* Copyright (C) 2019 William Hart Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" #define USE_SLOW_MULTIPLICATION 1 int _fmpq_mat_check_solution_fmpz_mat(const fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpq_mat_solve_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B, const nmod_mat_t Ainv, mp_limb_t p, const fmpz_t N, const fmpz_t D) { fmpz_t bound, ppow; fmpz_mat_t x, y, d, Ay; fmpz_t prod; mp_limb_t * crt_primes; nmod_mat_t * A_mod; nmod_mat_t Ay_mod, d_mod, y_mod; slong i, j, n, nexti, cols, num_primes; int stabilised; /* has lifting stabilised */ n = A->r; cols = B->c; fmpz_init(bound); fmpz_init(ppow); fmpz_init(prod); fmpz_mat_init(x, n, cols); fmpz_mat_init(y, n, cols); fmpz_mat_init(Ay, n, cols); fmpz_mat_init_set(d, B); /* Compute bound for the needed modulus. TODO: if one of N and D is much smaller than the other, we could use a tighter bound (i.e. 2ND). This would require the ability to forward N and D to the rational reconstruction routine. */ if (fmpz_cmpabs(N, D) < 0) fmpz_mul(bound, D, D); else fmpz_mul(bound, N, N); fmpz_mul_ui(bound, bound, UWORD(2)); /* signs */ crt_primes = fmpz_mat_dixon_get_crt_primes(&num_primes, A, p); A_mod = (nmod_mat_t *) flint_malloc(sizeof(nmod_mat_t) * num_primes); for (j = 0; j < num_primes; j++) { nmod_mat_init(A_mod[j], n, n, crt_primes[j]); fmpz_mat_get_nmod_mat(A_mod[j], A); } nmod_mat_init(Ay_mod, n, cols, UWORD(1)); nmod_mat_init(d_mod, n, cols, p); nmod_mat_init(y_mod, n, cols, p); fmpz_one(ppow); i = 1; /* working with p^i */ nexti = 1; /* iteration of next termination test */ while (fmpz_cmp(ppow, bound) <= 0) { /* y = A^(-1) * d (mod p) */ fmpz_mat_get_nmod_mat(d_mod, d); nmod_mat_mul(y_mod, Ainv, d_mod); /* x = x + y * p^i [= A^(-1) * b mod p^(i+1)] */ fmpz_mat_scalar_addmul_nmod_mat_fmpz(x, y_mod, ppow); /* ppow = p^(i+1) */ fmpz_mul_ui(ppow, ppow, p); if (fmpz_cmp(ppow, bound) > 0) break; stabilised = i == nexti; if (stabilised) nexti = (slong)(i*1.4) + 1; /* set iteration of next test */ /* full matrix stabilisation check */ if (stabilised) { stabilised = fmpq_mat_set_fmpz_mat_mod_fmpz(X, x, ppow); if (stabilised) { if (_fmpq_mat_check_solution_fmpz_mat(X, A, B)) goto dixon_done; } } i++; /* d = (d - Ay) / p */ #if USE_SLOW_MULTIPLICATION fmpz_mat_set_nmod_mat_unsigned(y, y_mod); fmpz_mat_mul(Ay, A, y); #else for (j = 0; j < num_primes; j++) { nmod_mat_set_mod(y_mod, crt_primes[j]); nmod_mat_set_mod(Ay_mod, crt_primes[j]); nmod_mat_mul(Ay_mod, A_mod[j], y_mod); if (j == 0) { fmpz_mat_set_nmod_mat(Ay, Ay_mod); fmpz_set_ui(prod, crt_primes[0]); } else { fmpz_mat_CRT_ui(Ay, Ay, prod, Ay_mod, 1); fmpz_mul_ui(prod, prod, crt_primes[j]); } } #endif nmod_mat_set_mod(y_mod, p); fmpz_mat_sub(d, d, Ay); fmpz_mat_scalar_divexact_ui(d, d, p); } fmpq_mat_set_fmpz_mat_mod_fmpz(X, x, ppow); dixon_done: nmod_mat_clear(y_mod); nmod_mat_clear(d_mod); nmod_mat_clear(Ay_mod); for (j = 0; j < num_primes; j++) nmod_mat_clear(A_mod[j]); flint_free(A_mod); flint_free(crt_primes); fmpz_clear(bound); fmpz_clear(ppow); fmpz_clear(prod); fmpz_mat_clear(d); fmpz_mat_clear(x); fmpz_mat_clear(y); fmpz_mat_clear(Ay); } int fmpq_mat_solve_fmpz_mat_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { nmod_mat_t Ainv; fmpz_t N, D; mp_limb_t p; if (!fmpz_mat_is_square(A)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_solve_fmpz_mat_dixon). Non-square system matrix.\n"); } if (fmpz_mat_is_empty(A) || fmpz_mat_is_empty(B)) return 1; fmpz_init(N); fmpz_init(D); fmpz_mat_solve_bound(N, D, A, B); nmod_mat_init(Ainv, A->r, A->r, 1); p = fmpz_mat_find_good_prime_and_invert(Ainv, A, D); if (p != 0) _fmpq_mat_solve_dixon(X, A, B, Ainv, p, N, D); nmod_mat_clear(Ainv); fmpz_clear(N); fmpz_clear(D); return p != 0; } int fmpq_mat_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { fmpz_mat_t Anum; fmpz_mat_t Bnum; int success; fmpz_mat_init(Anum, A->r, A->c); fmpz_mat_init(Bnum, B->r, B->c); fmpq_mat_get_fmpz_mat_rowwise_2(Anum, Bnum, NULL, A, B); success = fmpq_mat_solve_fmpz_mat_dixon(X, Anum, Bnum); fmpz_mat_clear(Anum); fmpz_mat_clear(Bnum); return success; } flint-3.1.3/src/fmpq_mat/solve_fraction_free.c000066400000000000000000000034151461254215100214130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" int fmpq_mat_solve_fmpz_mat_fraction_free(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { fmpz_mat_t Xnum; fmpz_t den; int success; fmpz_mat_init(Xnum, B->r, B->c); fmpz_init(den); /* call solve instead of solve_fflu explicitly because we also want to use cramer where applicable */ success = fmpz_mat_solve(Xnum, den, A, B); if (success) fmpq_mat_set_fmpz_mat_div_fmpz(X, Xnum, den); fmpz_mat_clear(Xnum); fmpz_clear(den); return success; } int fmpq_mat_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { fmpz_mat_t Anum; fmpz_mat_t Bnum; fmpz_mat_t Xnum; fmpz_t den; int success; fmpz_mat_init(Anum, A->r, A->c); fmpz_mat_init(Bnum, B->r, B->c); fmpz_mat_init(Xnum, B->r, B->c); fmpz_init(den); fmpq_mat_get_fmpz_mat_rowwise_2(Anum, Bnum, NULL, A, B); /* call solve instead of solve_fflu explicitly because we also want to use cramer where applicable */ success = fmpz_mat_solve(Xnum, den, Anum, Bnum); if (success) fmpq_mat_set_fmpz_mat_div_fmpz(X, Xnum, den); fmpz_mat_clear(Anum); fmpz_mat_clear(Bnum); fmpz_mat_clear(Xnum); fmpz_clear(den); return success; } flint-3.1.3/src/fmpq_mat/solve_multi_mod.c000066400000000000000000000120361461254215100205750ustar00rootroot00000000000000/* Copyright (C) 2019 William Hart Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq_mat.h" mp_limb_t fmpz_mat_find_good_prime_and_solve(nmod_mat_t Xmod, nmod_mat_t Amod, nmod_mat_t Bmod, const fmpz_mat_t A, const fmpz_mat_t B, const fmpz_t det_bound); int _fmpq_mat_check_solution_fmpz_mat(const fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { slong i, j; fmpz_mat_t Xclear, AXclear; fmpz_t t; fmpz * Xden; int ok; Xden = _fmpz_vec_init(X->c); fmpz_mat_init(Xclear, X->r, X->c); fmpz_mat_init(AXclear, B->r, B->c); fmpz_init(t); fmpq_mat_get_fmpz_mat_colwise(Xclear, Xden, X); fmpz_mat_mul(AXclear, A, Xclear); ok = 1; for (i = 0; i < B->r && ok; i++) { for (j = 0; j < B->c && ok; j++) { /* AXclear[i,j] / Xden[j] = B[i,j] */ fmpz_mul(t, fmpz_mat_entry(B, i, j), Xden + j); if (!fmpz_equal(t, fmpz_mat_entry(AXclear, i, j))) ok = 0; } } _fmpz_vec_clear(Xden, X->c); fmpz_mat_clear(Xclear); fmpz_mat_clear(AXclear); fmpz_clear(t); return ok; } void _fmpq_mat_solve_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B, nmod_mat_t Xmod, nmod_mat_t Amod, nmod_mat_t Bmod, mp_limb_t p, const fmpz_t N, const fmpz_t D) { fmpz_t bound, pprod; fmpz_mat_t x; fmpq_mat_t AX; slong i, n, nexti, cols; int stabilised; /* has CRT stabilised */ n = A->r; cols = B->c; fmpz_init(bound); fmpz_init(pprod); fmpq_mat_init(AX, B->r, B->c); fmpz_mat_init(x, n, cols); /* Compute bound for the needed modulus. TODO: if one of N and D is much smaller than the other, we could use a tighter bound (i.e. 2ND). This would require the ability to forward N and D to the CRT routine. */ if (fmpz_cmpabs(N, D) < 0) fmpz_mul(bound, D, D); else fmpz_mul(bound, N, N); fmpz_mul_ui(bound, bound, UWORD(2)); /* signs */ fmpz_set_ui(pprod, p); fmpz_mat_set_nmod_mat(x, Xmod); i = 1; /* working with i primes */ nexti = 1; /* when to do next termination test */ while (fmpz_cmp(pprod, bound) <= 0) { stabilised = i == nexti; if (stabilised) /* set next termination test iteration */ nexti = (slong)(i*1.4) + 1; /* full matrix stabilisation check */ if (stabilised) { stabilised = fmpq_mat_set_fmpz_mat_mod_fmpz(X, x, pprod); if (stabilised) { if (_fmpq_mat_check_solution_fmpz_mat(X, A, B)) goto multi_mod_done; } } i++; while (1) { p = n_nextprime(p, 1); nmod_mat_set_mod(Xmod, p); nmod_mat_set_mod(Amod, p); nmod_mat_set_mod(Bmod, p); fmpz_mat_get_nmod_mat(Amod, A); fmpz_mat_get_nmod_mat(Bmod, B); if (nmod_mat_solve(Xmod, Amod, Bmod)) break; } fmpz_mat_CRT_ui(x, x, pprod, Xmod, 0); fmpz_mul_ui(pprod, pprod, p); } fmpq_mat_set_fmpz_mat_mod_fmpz(X, x, pprod); multi_mod_done: fmpz_clear(bound); fmpz_clear(pprod); fmpq_mat_clear(AX); fmpz_mat_clear(x); } int fmpq_mat_solve_fmpz_mat_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B) { nmod_mat_t Xmod, Amod, Bmod; fmpz_t N, D; mp_limb_t p; if (!fmpz_mat_is_square(A)) { flint_throw(FLINT_ERROR, "Exception (fmpq_mat_solve_fmpz_mat_multi_mod). Non-square system matrix.\n"); } if (fmpz_mat_is_empty(A) || fmpz_mat_is_empty(B)) return 1; fmpz_init(N); fmpz_init(D); fmpz_mat_solve_bound(N, D, A, B); nmod_mat_init(Amod, A->r, A->c, 1); nmod_mat_init(Bmod, B->r, B->c, 1); nmod_mat_init(Xmod, B->r, B->c, 1); p = fmpz_mat_find_good_prime_and_solve(Xmod, Amod, Bmod, A, B, D); if (p != 0) _fmpq_mat_solve_multi_mod(X, A, B, Xmod, Amod, Bmod, p, N, D); nmod_mat_clear(Xmod); nmod_mat_clear(Bmod); nmod_mat_clear(Amod); fmpz_clear(N); fmpz_clear(D); return p != 0; } int fmpq_mat_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B) { fmpz_mat_t Anum; fmpz_mat_t Bnum; int success; fmpz_mat_init(Anum, A->r, A->c); fmpz_mat_init(Bnum, B->r, B->c); fmpq_mat_get_fmpz_mat_rowwise_2(Anum, Bnum, NULL, A, B); success = fmpq_mat_solve_fmpz_mat_multi_mod(X, Anum, Bnum); fmpz_mat_clear(Anum); fmpz_mat_clear(Bnum); return success; } flint-3.1.3/src/fmpq_mat/sub.c000066400000000000000000000013221461254215100161610ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_sub(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2) { slong i, j; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_sub(fmpq_mat_entry(mat, i, j), fmpq_mat_entry(mat1, i, j), fmpq_mat_entry(mat2, i, j)); } flint-3.1.3/src/fmpq_mat/swap.c000066400000000000000000000024351461254215100163500ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_swap_entrywise(fmpq_mat_t mat1, fmpq_mat_t mat2) { slong i, j; for (i = 0; i < fmpq_mat_nrows(mat1); i++) for (j = 0; j < fmpq_mat_ncols(mat1); j++) fmpq_swap(fmpq_mat_entry(mat2, i, j), fmpq_mat_entry(mat1, i, j)); } void fmpq_mat_swap_cols(fmpq_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !fmpq_mat_is_empty(mat)) { slong i; if (perm) FLINT_SWAP(slong, perm[r], perm[s]); for (i = 0; i < mat->r; i++) fmpq_swap(fmpq_mat_entry(mat, i, r), fmpq_mat_entry(mat, i, s)); } } void fmpq_mat_swap_rows(fmpq_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !fmpq_mat_is_empty(mat)) { if (perm) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(fmpq *, mat->rows[r], mat->rows[s]); } } flint-3.1.3/src/fmpq_mat/test/000077500000000000000000000000001461254215100162055ustar00rootroot00000000000000flint-3.1.3/src/fmpq_mat/test/main.c000066400000000000000000000066171461254215100173070ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-can_solve.c" #include "t-can_solve_dixon.c" #include "t-can_solve_fraction_free.c" #include "t-can_solve_multi_mod.c" #include "t-charpoly.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-det.c" #include "t-fmpq_vec_mul.c" #include "t-fmpz_vec_mul.c" #include "t-gso.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-invert_rows_cols.c" #include "t-is_integral.c" #include "t-is_one.c" #include "t-kronecker_product.c" #include "t-minpoly.c" #include "t-mul.c" #include "t-mul_fmpq_vec.c" #include "t-mul_fmpz_vec.c" #include "t-neg.c" #include "t-one.c" #include "t-rref.c" #include "t-scalar_div_fmpz.c" #include "t-scalar_mul_fmpq.c" #include "t-scalar_mul_fmpz.c" #include "t-solve.c" #include "t-solve_dixon.c" #include "t-solve_fmpz_mat.c" #include "t-solve_fmpz_mat_dixon.c" #include "t-solve_fmpz_mat_fraction_free.c" #include "t-solve_fmpz_mat_multi_mod.c" #include "t-solve_fraction_free.c" #include "t-solve_multi_mod.c" #include "t-sub.c" #include "t-trace.c" #include "t-transpose.c" #include "t-window_init_clear.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpq_mat_add), TEST_FUNCTION(fmpq_mat_can_solve), TEST_FUNCTION(fmpq_mat_can_solve_dixon), TEST_FUNCTION(fmpq_mat_can_solve_fraction_free), TEST_FUNCTION(fmpq_mat_can_solve_multi_mod), TEST_FUNCTION(fmpq_mat_charpoly), TEST_FUNCTION(fmpq_mat_concat_horizontal), TEST_FUNCTION(fmpq_mat_concat_vertical), TEST_FUNCTION(fmpq_mat_det), TEST_FUNCTION(fmpq_mat_fmpq_vec_mul), TEST_FUNCTION(fmpq_mat_fmpz_vec_mul), TEST_FUNCTION(fmpq_mat_gso), TEST_FUNCTION(fmpq_mat_init_clear), TEST_FUNCTION(fmpq_mat_inv), TEST_FUNCTION(fmpq_mat_invert_rows_cols), TEST_FUNCTION(fmpq_mat_is_integral), TEST_FUNCTION(fmpq_mat_is_one), TEST_FUNCTION(fmpq_mat_kronecker_product), TEST_FUNCTION(fmpq_mat_minpoly), TEST_FUNCTION(fmpq_mat_mul), TEST_FUNCTION(fmpq_mat_mul_fmpq_vec), TEST_FUNCTION(fmpq_mat_mul_fmpz_vec), TEST_FUNCTION(fmpq_mat_neg), TEST_FUNCTION(fmpq_mat_one), TEST_FUNCTION(fmpq_mat_rref), TEST_FUNCTION(fmpq_mat_scalar_div_fmpz), TEST_FUNCTION(fmpq_mat_scalar_mul_fmpq), TEST_FUNCTION(fmpq_mat_scalar_mul_fmpz), TEST_FUNCTION(fmpq_mat_solve), TEST_FUNCTION(fmpq_mat_solve_dixon), TEST_FUNCTION(fmpq_mat_solve_fmpz_mat), TEST_FUNCTION(fmpq_mat_solve_fmpz_mat_dixon), TEST_FUNCTION(fmpq_mat_solve_fmpz_mat_fraction_free), TEST_FUNCTION(fmpq_mat_solve_fmpz_mat_multi_mod), TEST_FUNCTION(fmpq_mat_solve_fraction_free), TEST_FUNCTION(fmpq_mat_solve_multi_mod), TEST_FUNCTION(fmpq_mat_sub), TEST_FUNCTION(fmpq_mat_trace), TEST_FUNCTION(fmpq_mat_transpose), TEST_FUNCTION(fmpq_mat_window_init_clear) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpq_mat/test/t-add.c000066400000000000000000000067741461254215100173600ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_add, state) { int i, result; /* Aliasing, B = B + C */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_randtest(B, state, bits); fmpq_mat_randtest(C, state, bits); fmpq_mat_add(A, B, C); fmpq_mat_add(B, B, C); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL (B = B + C):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } /* Aliasing, C = B + C */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_randtest(B, state, bits); fmpq_mat_randtest(C, state, bits); fmpq_mat_add(A, B, C); fmpq_mat_add(C, B, C); result = fmpq_mat_equal(A, C); if (!result) { flint_printf("FAIL (C = B + C):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } /* A + B == B + A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C, D; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_init(D, m, n); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpq_mat_add(C, A, B); fmpq_mat_add(D, B, A); result = fmpq_mat_equal(C, D); if (!result) { flint_printf("FAIL (A + B == B + A):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); flint_printf("D:\n"); fmpq_mat_print(D); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-can_solve.c000066400000000000000000000073601461254215100205710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_can_solve, state) { int i; /* Solve random systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*n*k + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_can_solve(X, A, B); fmpq_mat_mul(AX, A, X); if (success && !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Solve random soluble systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(X, state, bits); fmpq_mat_mul(B, A, X); success = fmpq_mat_can_solve(X, A, B); fmpq_mat_mul(AX, A, X); if (!success || !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-can_solve_dixon.c000066400000000000000000000074021461254215100217670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2022 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_can_solve_dixon, state) { int i; /* Solve random systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*n*k + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_can_solve_dixon(X, A, B); fmpq_mat_mul(AX, A, X); if (success && !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Solve random soluble systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 300); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(X, state, bits); fmpq_mat_mul(B, A, X); success = fmpq_mat_can_solve_dixon(X, A, B); fmpq_mat_mul(AX, A, X); if (!success || !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-can_solve_fraction_free.c000066400000000000000000000074321461254215100234570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_can_solve_fraction_free, state) { int i; /* Solve random systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*n*k + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_can_solve_fraction_free(X, A, B); fmpq_mat_mul(AX, A, X); if (success && !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Solve random soluble systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(X, state, bits); fmpq_mat_mul(B, A, X); success = fmpq_mat_can_solve_fraction_free(X, A, B); fmpq_mat_mul(AX, A, X); if (!success || !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-can_solve_multi_mod.c000066400000000000000000000074161461254215100226440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_can_solve_multi_mod, state) { int i; /* Solve random systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*n*k + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_can_solve_multi_mod(X, A, B); fmpq_mat_mul(AX, A, X); if (success && !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Solve random soluble systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpz_mat_t M; fmpz_t den; int success; slong n, m, k, bits; n = n_randint(state, 10); m = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpq_mat_init(A, n, k); fmpq_mat_init(B, n, m); fmpq_mat_init(X, k, m); fmpq_mat_init(AX, n, m); fmpz_mat_init(M, n, k); fmpz_mat_randrank(M, state, n_randint(state, FLINT_MIN(n, k) + 1), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_randtest(X, state, bits); fmpq_mat_mul(B, A, X); success = fmpq_mat_can_solve_multi_mod(X, A, B); fmpq_mat_mul(AX, A, X); if (!success || !fmpq_mat_equal(AX, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-charpoly.c000066400000000000000000000035071461254215100204400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_charpoly, state) { slong m, n, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpq_mat_t A, B, C, D; fmpq_poly_t f, g; m = n_randint(state, 4); n = m; fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, m); fmpq_mat_init(D, n, n); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_mat_randtest(A, state, 10); fmpq_mat_randtest(B, state, 10); fmpq_mat_mul(C, A, B); fmpq_mat_mul(D, B, A); fmpq_mat_charpoly(f, C); fmpq_mat_charpoly(g, D); if (!fmpq_poly_equal(f, g)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), fmpq_mat_print(A), flint_printf("\n"); flint_printf("Matrix B:\n"), fmpq_mat_print(B), flint_printf("\n"); flint_printf("cp(AB) = "), fmpq_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(BA) = "), fmpq_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); fmpq_poly_clear(f); fmpq_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-concat_horizontal.c000066400000000000000000000031371461254215100223360ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_concat_horizontal, state) { fmpq_mat_t A, B, C; fmpq_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong c1, c2, r1; c1 = n_randint(state, 50); c2 = n_randint(state, 50); r1 = n_randint(state, 50); fmpq_mat_init(A, r1, c1); fmpq_mat_init(B, r1, c2); fmpq_mat_init(C, r1, (c1 + c2)); fmpq_mat_randtest(A, state, n_randint(state, 200) + 1); fmpq_mat_randtest(B, state, n_randint(state, 200) + 1); fmpq_mat_randtest(C, state, n_randint(state, 200) + 1); fmpq_mat_concat_horizontal(C, A, B); fmpq_mat_window_init(window1, C, 0, 0, r1, c1); fmpq_mat_window_init(window2, C, 0, c1, r1, (c1 + c2)); if (!(fmpq_mat_equal(window1, A) && fmpq_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_window_clear(window1); fmpq_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-concat_vertical.c000066400000000000000000000031331461254215100217520ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_concat_vertical, state) { fmpq_mat_t A, B, C; fmpq_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong r1, r2, c1; r1 = n_randint(state, 50); r2 = n_randint(state, 50); c1 = n_randint(state, 50); fmpq_mat_init(A, r1, c1); fmpq_mat_init(B, r2, c1); fmpq_mat_init(C, (r1 + r2), c1); fmpq_mat_randtest(A, state, n_randint(state, 200) + 1); fmpq_mat_randtest(B, state, n_randint(state, 200) + 1); fmpq_mat_randtest(C, state, n_randint(state, 200) + 1); fmpq_mat_concat_vertical(C, A, B); fmpq_mat_window_init(window1, C, 0, 0, r1, c1); fmpq_mat_window_init(window2, C, r1, 0, (r1 + r2), c1); if (!(fmpq_mat_equal(window1, A) && fmpq_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_window_clear(window1); fmpq_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-det.c000066400000000000000000000035561461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_det, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; fmpq_t a, b, ab, c; slong n, bits; n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); fmpq_mat_init(C, n, n); fmpq_init(a); fmpq_init(b); fmpq_init(ab); fmpq_init(c); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpq_mat_mul(C, A, B); fmpq_mat_det(a, A); fmpq_mat_det(b, B); fmpq_mat_det(c, C); fmpq_mul(ab, a, b); if (!fmpq_equal(ab, c)) { flint_printf("FAIL!\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); flint_printf("\ndet(A):\n"); fmpq_print(a); flint_printf("\ndet(B):\n"); fmpq_print(b); flint_printf("\ndet(C):\n"); fmpq_print(c); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); fmpq_clear(ab); fmpq_clear(c); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-fmpq_vec_mul.c000066400000000000000000000052611461254215100212730ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_fmpq_vec_mul, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; fmpq * a; fmpq * c; fmpq ** aa; fmpq ** cc; slong j, m, n, alen; m = n_randint(state, 40); n = n_randint(state, 40); alen = n_randint(state, 40); fmpq_mat_init(C, 1, n); fmpq_mat_init(A, 1, m); fmpq_mat_init(B, m, n); c = _fmpq_vec_init(n); a = _fmpq_vec_init(alen); fmpq_mat_randtest(B, state, n_randint(state, 200) + 1); _fmpq_vec_randtest(c, state, n, n_randint(state, 200) + 1); _fmpq_vec_randtest(a, state, alen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(n, fmpq*); for (j = 0; j < n; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpq); fmpq_init(cc[j]); fmpq_set(cc[j], c + j); } aa = FLINT_ARRAY_ALLOC(alen, fmpq*); for (j = 0; j < alen; j++) { aa[j] = FLINT_ARRAY_ALLOC(1, fmpq); fmpq_init(aa[j]); fmpq_set(aa[j], a + j); } fmpq_mat_fmpq_vec_mul(c, a, alen, B); fmpq_mat_fmpq_vec_mul_ptr(cc, (const fmpq * const *)aa, alen, B); /* supposed to match mul of the chopped or zero-extended a */ for (j = 0; j < m && j < alen; j++) fmpq_set(fmpq_mat_entry(A, 0, j), a + j); fmpq_mat_mul(C, A, B); for (j = 0; j < n; j++) { if (!fmpq_equal(fmpq_mat_entry(C, 0, j), c + j) || !fmpq_equal(fmpq_mat_entry(C, 0, j), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); _fmpq_vec_clear(c, n); _fmpq_vec_clear(a, alen); for (j = 0; j < n; j++) { fmpq_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < alen; j++) { fmpq_clear(aa[j]); flint_free(aa[j]); } flint_free(aa); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-fmpz_vec_mul.c000066400000000000000000000052631461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_fmpz_vec_mul, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; fmpz * a; fmpq * c; fmpz ** aa; fmpq ** cc; slong j, m, n, alen; m = n_randint(state, 40); n = n_randint(state, 40); alen = n_randint(state, 40); fmpq_mat_init(C, 1, n); fmpq_mat_init(A, 1, m); fmpq_mat_init(B, m, n); c = _fmpq_vec_init(n); a = _fmpz_vec_init(alen); fmpq_mat_randtest(B, state, n_randint(state, 200) + 1); _fmpq_vec_randtest(c, state, n, n_randint(state, 200) + 1); _fmpz_vec_randtest(a, state, alen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(n, fmpq*); for (j = 0; j < n; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpq); fmpq_init(cc[j]); fmpq_set(cc[j], c + j); } aa = FLINT_ARRAY_ALLOC(alen, fmpz*); for (j = 0; j < alen; j++) { aa[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(aa[j], a + j); } fmpq_mat_fmpz_vec_mul(c, a, alen, B); fmpq_mat_fmpz_vec_mul_ptr(cc, (const fmpz * const *)aa, alen, B); /* supposed to match mul of the chopped or zero-extended a */ for (j = 0; j < m && j < alen; j++) fmpq_set_fmpz(fmpq_mat_entry(A, 0, j), a + j); fmpq_mat_mul(C, A, B); for (j = 0; j < n; j++) { if (!fmpq_equal(fmpq_mat_entry(C, 0, j), c + j) || !fmpq_equal(fmpq_mat_entry(C, 0, j), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); _fmpq_vec_clear(c, n); _fmpz_vec_clear(a, alen); for (j = 0; j < n; j++) { fmpq_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < alen; j++) { fmpz_clear(aa[j]); flint_free(aa[j]); } flint_free(aa); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-gso.c000066400000000000000000000041041461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_gso, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; fmpq_t dot; int j, k; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, m); fmpq_mat_init(C, n, m); fmpq_mat_randtest(A, state, bits); fmpq_mat_transpose(B, A); fmpq_mat_rref(B, B); fmpq_mat_gso(A, A); fmpq_mat_transpose(C, A); fmpq_init(dot); for (j = 0; j < n; j++) { for (k = j + 1; k < n; k++) { if (m) { _fmpq_vec_dot(dot, C->rows[j], C->rows[k], m); if (!fmpq_is_zero(dot)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpq_mat_print(A); fflush(stdout); flint_abort(); } } } } fmpq_mat_rref(C, C); result = fmpq_mat_equal(B, C); if (!result) { flint_printf("FAIL:\n"); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_clear(dot); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-init_clear.c000066400000000000000000000017161461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mat_t a; slong j, k; slong rows = n_randint(state, 100); slong cols = n_randint(state, 100); fmpq_mat_init(a, rows, cols); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) fmpq_zero(fmpq_mat_entry(a, j, k)); fmpq_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-inv.c000066400000000000000000000077131461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_inv, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; fmpq_t d; int success1, success2; slong n, bits; n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); fmpq_mat_init(C, n, n); fmpq_init(d); /* XXX: replace with a randtest function */ { slong k; for (k = 0; (k < 100) && fmpq_is_zero(d); k++) { fmpq_mat_randtest(A, state, bits); fmpq_mat_det(d, A); } if (fmpq_is_zero(d)) { fmpq_mat_one(A); } } fmpq_clear(d); success1 = fmpq_mat_inv(B, A); success2 = fmpq_mat_inv(C, B); if (!fmpq_mat_equal(A, C) || !success1 || !success2) { flint_printf("FAIL!\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } /* Test aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mat_t A, B; fmpq_t d; int success1, success2; slong n, bits; n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); fmpq_init(d); /* XXX: replace with a randtest function */ do { fmpq_mat_randtest(A, state, bits); fmpq_mat_det(d, A); } while (fmpq_is_zero(d)); fmpq_clear(d); success1 = fmpq_mat_inv(B, A); success2 = fmpq_mat_inv(A, A); if (!fmpq_mat_equal(A, B) || !success1 || !success2) { flint_printf("FAIL!\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); } /* Test singular matrices */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong n, r, b, d; fmpq_mat_t A, B; fmpz_mat_t M; fmpz_t den; int success; n = n_randint(state, 10); fmpz_init(den); for (r = 0; r < n; r++) { b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*n*n + 1); fmpz_mat_init(M, n, n); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); fmpz_mat_randrank(M, state, r, b); if (i % 2 == 0) fmpz_mat_randops(M, state, d); fmpz_randtest_not_zero(den, state, b); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); success = fmpq_mat_inv(B, A); if (success) { flint_printf("FAIL:\n"); flint_printf("matrix reported as invertible:\n"); fmpq_mat_print(A); fflush(stdout); flint_abort(); } fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); } fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-invert_rows_cols.c000066400000000000000000000030731461254215100222160ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_invert_rows_cols, state) { slong n, rep; /* Rectangular inversion of rows and cols */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { slong i, j; fmpq_mat_t A, B; n = n_randint(state, 10); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); fmpq_mat_randtest(A, state, 1+n_randint(state, 3)); fmpq_mat_set(B, A); fmpq_mat_invert_rows(A, NULL); fmpq_mat_invert_cols(A, NULL); for (i = 0; i < A->r; i++) { for (j =0; j < A->c; j++) { if (fmpq_cmp(fmpq_mat_entry(B, i, j), fmpq_mat_entry(A, A->r - i - 1, A->c - j - 1)) != 0) { flint_printf("FAIL: B != A\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); fflush(stdout); flint_abort(); } } } fmpq_mat_clear(A); fmpq_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-is_integral.c000066400000000000000000000027171461254215100211210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_is_integral, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A; fmpz_mat_t B; slong n, m; m = n_randint(state, 10); n = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_randtest(B, state, 10); fmpq_mat_set_fmpz_mat(A, B); if (!fmpq_mat_is_integral(A)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } if (m && n) { slong i, j; i = n_randint(state, m); j = n_randint(state, n); fmpq_set_si(fmpq_mat_entry(A, i, j), 1, 2); if (fmpq_mat_is_integral(A)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } } fmpq_mat_clear(A); fmpz_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-is_one.c000066400000000000000000000023231461254215100200660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_is_one, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpq_mat_init(A, rows, cols); fmpq_mat_one(A); if (!fmpq_mat_is_one(A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } if (rows && cols) { fmpq_mat_randbits(A, state, 100); if (fmpq_mat_is_one(A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } fmpq_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-kronecker_product.c000066400000000000000000000042631461254215100223420ustar00rootroot00000000000000/* Copyright (C) 2018 Martin Raum This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_kronecker_product, state) { int r, result; fmpq_mat_t A, B, C; fmpq_mat_t window1, window2; slong m, n, k, l, i, j; slong bits; for (r = 0; r < 100 * flint_test_multiplier(); r++) { m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); l = n_randint(state, 10); if ( m && n ) { i = n_randint(state, m); j = n_randint(state, n); } fmpq_mat_init(A, m, n); fmpq_mat_init(B, k, l); fmpq_mat_init(C, m*k, n*l); bits = 1 + n_randint(state, 100); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpq_mat_kronecker_product(C, A, B); if ( m && n ) { fmpq_mat_window_init(window1, C, 0, 0, k, l); fmpq_mat_window_init(window2, C, i*k, j*l, (i+1)*k, (j+1)*l); fmpq_mat_scalar_mul_fmpq(window1, window1, fmpq_mat_entry(A, i, j)); fmpq_mat_scalar_mul_fmpq(window2, window2, fmpq_mat_entry(A, 0, 0)); result = fmpq_mat_equal(window1, window2); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); flint_printf("i,j: %d,%d\n", i, j); fflush(stdout); flint_abort(); } fmpq_mat_window_clear(window1); fmpq_mat_window_clear(window2); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-minpoly.c000066400000000000000000000065331461254215100203100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_minpoly, state) { slong m, n, rep, i, j; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpq_mat_t A; fmpq_poly_t f, g, q, r; m = n_randint(state, 4); n = m; fmpq_mat_init(A, m, n); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(q); fmpq_poly_init(r); fmpq_mat_randtest(A, state, 10); fmpq_mat_charpoly(f, A); fmpq_mat_minpoly(g, A); fmpq_poly_divrem(q, r, f, g); if (!fmpq_poly_is_zero(r)) { flint_printf("FAIL: minpoly(A) doesn't divide charpoly(A).\n"); flint_printf("Matrix A:\n"), fmpq_mat_print(A), flint_printf("\n"); flint_printf("cp(A) = "), fmpq_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("mp(A) = "), fmpq_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(q); fmpq_poly_clear(r); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpq_mat_t A, B; fmpq_poly_t f, g; fmpq_t d; m = n_randint(state, 4); n = m; fmpq_init(d); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_mat_randtest(A, state, 10); for (i = 0; i < n/2; i++) { for (j = 0; j < n/2; j++) { fmpq_zero(fmpq_mat_entry(A, i, j + n/2)); fmpq_zero(fmpq_mat_entry(A, i + n/2, j)); } } for (i = 0; i < n/2; i++) { for (j = 0; j < n/2; j++) { fmpq_set(fmpq_mat_entry(A, i + n/2, j + n/2), fmpq_mat_entry(A, i, j)); } } fmpq_mat_set(B, A); fmpq_mat_minpoly(g, A); for (i = 0; i < n; i++) { fmpq_set_si(d, n_randint(state, 6) - 3, 1); fmpq_mat_similarity(B, n_randint(state, n), d); } fmpq_mat_minpoly(f, B); if (!fmpq_poly_equal(f, g)) { flint_printf("FAIL: minpoly(P^{-1}AP) != minpoly(A).\n"); flint_printf("Matrix A:\n"), fmpq_mat_print(A), flint_printf("\n"); flint_printf("Matrix P^{-1}AP:\n"), fmpq_mat_print(B), flint_printf("\n"); flint_printf("mp(P^{-1}AP) = "), fmpq_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("mp(A) = "), fmpq_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_clear(d); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_poly_clear(f); fmpq_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-mul.c000066400000000000000000000047071461254215100174170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_mul, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C, D; slong m, n, k, bits; m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, k); fmpq_mat_init(B, k, n); fmpq_mat_init(C, m, n); fmpq_mat_init(D, m, n); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpq_mat_randtest(C, state, bits); /* noise in output */ fmpq_mat_mul_direct(C, A, B); fmpq_mat_mul_cleared(D, A, B); result = fmpq_mat_equal(C, D); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); flint_printf("D:\n"); fmpq_mat_print(D); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); } /* Test aliasing with windows */ { fmpq_mat_t A, B, A_window; fmpq_mat_init(A, 2, 2); fmpq_mat_init(B, 2, 2); fmpq_mat_window_init(A_window, A, 0, 0, 2, 2); fmpq_mat_one(A); fmpq_mat_one(B); fmpq_set_ui(fmpq_mat_entry(B, 0, 1), 1, 1); fmpq_set_ui(fmpq_mat_entry(B, 1, 0), 1, 1); fmpq_mat_mul(A_window, B, A_window); if (!fmpq_mat_equal(A, B)) { flint_printf("FAIL: window aliasing failed\n"); fmpq_mat_print(A); flint_printf("\n\n"); fmpq_mat_print(B); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_mat_window_clear(A_window); fmpq_mat_clear(A); fmpq_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-mul_fmpq_vec.c000066400000000000000000000052611461254215100212730ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_mul_fmpq_vec, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; fmpq * b; fmpq * c; fmpq ** bb; fmpq ** cc; slong j, m, n, blen; m = n_randint(state, 40); n = n_randint(state, 40); blen = n_randint(state, 40); fmpq_mat_init(C, m, 1); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, 1); c = _fmpq_vec_init(m); b = _fmpq_vec_init(blen); fmpq_mat_randtest(A, state, n_randint(state, 200) + 1); _fmpq_vec_randtest(c, state, m, n_randint(state, 200) + 1); _fmpq_vec_randtest(b, state, blen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(m, fmpq*); for (j = 0; j < m; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpq); fmpq_init(cc[j]); fmpq_set(cc[j], c + j); } bb = FLINT_ARRAY_ALLOC(blen, fmpq*); for (j = 0; j < blen; j++) { bb[j] = FLINT_ARRAY_ALLOC(1, fmpq); fmpq_init(bb[j]); fmpq_set(bb[j], b + j); } fmpq_mat_mul_fmpq_vec(c, A, b, blen); fmpq_mat_mul_fmpq_vec_ptr(cc, A, (const fmpq * const *)bb, blen); /* supposed to match mul of the chopped or zero-extended b */ for (j = 0; j < n && j < blen; j++) fmpq_set(fmpq_mat_entry(B, j, 0), b + j); fmpq_mat_mul(C, A, B); for (j = 0; j < m; j++) { if (!fmpq_equal(fmpq_mat_entry(C, j, 0), c + j) || !fmpq_equal(fmpq_mat_entry(C, j, 0), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); _fmpq_vec_clear(c, m); _fmpq_vec_clear(b, blen); for (j = 0; j < m; j++) { fmpq_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < blen; j++) { fmpq_clear(bb[j]); flint_free(bb[j]); } flint_free(bb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-mul_fmpz_vec.c000066400000000000000000000052631461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_mul_fmpz_vec, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; fmpz * b; fmpq * c; fmpz ** bb; fmpq ** cc; slong j, m, n, blen; m = n_randint(state, 40); n = n_randint(state, 40); blen = n_randint(state, 40); fmpq_mat_init(C, m, 1); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, 1); c = _fmpq_vec_init(m); b = _fmpz_vec_init(blen); fmpq_mat_randtest(A, state, n_randint(state, 200) + 1); _fmpq_vec_randtest(c, state, m, n_randint(state, 200) + 1); _fmpz_vec_randtest(b, state, blen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(m, fmpq*); for (j = 0; j < m; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpq); fmpq_init(cc[j]); fmpq_set(cc[j], c + j); } bb = FLINT_ARRAY_ALLOC(blen, fmpz*); for (j = 0; j < blen; j++) { bb[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(bb[j], b + j); } fmpq_mat_mul_fmpz_vec(c, A, b, blen); fmpq_mat_mul_fmpz_vec_ptr(cc, A, (const fmpz * const *)bb, blen); /* supposed to match mul of the chopped or zero-extended b */ for (j = 0; j < n && j < blen; j++) fmpq_set_fmpz(fmpq_mat_entry(B, j, 0), b + j); fmpq_mat_mul(C, A, B); for (j = 0; j < m; j++) { if (!fmpq_equal(fmpq_mat_entry(C, j, 0), c + j) || !fmpq_equal(fmpq_mat_entry(C, j, 0), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); _fmpq_vec_clear(c, m); _fmpz_vec_clear(b, blen); for (j = 0; j < m; j++) { fmpq_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < blen; j++) { fmpz_clear(bb[j]); flint_free(bb[j]); } flint_free(bb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-neg.c000066400000000000000000000040401461254215100173610ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_neg, state) { int i, result; /* Aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_randtest(B, state, bits); fmpq_mat_neg(A, B); fmpq_mat_neg(B, B); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); } /* --A == A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_randtest(B, state, bits); fmpq_mat_neg(A, B); fmpq_mat_neg(A, A); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-one.c000066400000000000000000000030631461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_one, state) { int i, result; /* 1 * A == A * 1 == A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C, I; slong n, bits; n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, n); fmpq_mat_init(C, n, n); fmpq_mat_init(I, n, n); fmpq_mat_randtest(A, state, bits); fmpq_mat_one(I); fmpq_mat_mul(B, I, A); fmpq_mat_mul(C, A, I); result = fmpq_mat_equal(A, B) && fmpq_mat_equal(A, C); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); flint_printf("I:\n"); fmpq_mat_print(I); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(I); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-rref.c000066400000000000000000000051431461254215100175530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_rref, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong m, n, r, rank, b, d; fmpq_mat_t A, B, C; fmpz_mat_t M; fmpz_t den; m = n_randint(state, 10); n = n_randint(state, 10); fmpz_init(den); for (r = 0; r <= FLINT_MIN(m,n); r++) { b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_init(M, m, n); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpz_mat_randrank(M, state, r, b); if (i % 2 == 0) fmpz_mat_randops(M, state, d); fmpz_randtest_not_zero(den, state, b); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); rank = fmpq_mat_rref_classical(B, A); if (r != rank) { flint_printf("FAIL:\n"); flint_printf("fmpq_mat_rref_classical: wrong rank!\n"); fmpq_mat_print(A); flint_printf("\nrank: %wd computed: %wd\n", r, rank); fflush(stdout); flint_abort(); } rank = fmpq_mat_rref_fraction_free(C, A); if (r != rank) { flint_printf("FAIL:\n"); flint_printf("fmpq_mat_rref_fraction_free: wrong rank!\n"); fflush(stdout); flint_abort(); } if (!fmpq_mat_equal(B, C)) { flint_printf("FAIL:\n"); flint_printf("different results!\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("\nB:\n"); fmpq_mat_print(B); flint_printf("\nC:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-scalar_div_fmpz.c000066400000000000000000000051151461254215100217570ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_scalar_div_fmpz, state) { int i, result; /* Aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B; fmpz_t x; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpz_init(x); fmpq_mat_randtest(B, state, bits); fmpz_randtest_not_zero(x, state, bits); fmpq_mat_scalar_div_fmpz(A, B, x); fmpq_mat_scalar_div_fmpz(B, B, x); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"), fmpq_mat_print(A); flint_printf("B:\n"), fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpz_clear(x); } /* (A + B) / x == A / x + B / x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C, D; fmpz_t x; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_init(D, m, n); fmpz_init(x); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpz_randtest_not_zero(x, state, bits); fmpq_mat_scalar_div_fmpz(C, A, x); fmpq_mat_scalar_div_fmpz(D, B, x); fmpq_mat_add(D, C, D); fmpq_mat_add(C, A, B); fmpq_mat_scalar_div_fmpz(C, C, x); result = fmpq_mat_equal(C, D); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"), fmpq_mat_print(A); flint_printf("B:\n"), fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-scalar_mul_fmpq.c000066400000000000000000000051361461254215100217640ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2018 Martin Raum This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_scalar_mul_fmpq, state) { int i, result; /* Aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B; fmpq_t x; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_init(x); fmpq_mat_randtest(B, state, bits); fmpq_randtest(x, state, bits); fmpq_mat_scalar_mul_fmpq(A, B, x); fmpq_mat_scalar_mul_fmpq(B, B, x); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"), fmpq_mat_print(A); flint_printf("B:\n"), fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_clear(x); } /* (A + B) * x == A * x + B * x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C, D; fmpq_t x; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_init(D, m, n); fmpq_init(x); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpq_randtest(x, state, bits); fmpq_mat_scalar_mul_fmpq(C, A, x); fmpq_mat_scalar_mul_fmpq(D, B, x); fmpq_mat_add(D, C, D); fmpq_mat_add(C, A, B); fmpq_mat_scalar_mul_fmpq(C, C, x); result = fmpq_mat_equal(C, D); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"), fmpq_mat_print(A); flint_printf("B:\n"), fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); fmpq_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000050731461254215100217750ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_scalar_mul_fmpz, state) { int i, result; /* Aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B; fmpz_t x; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpz_init(x); fmpq_mat_randtest(B, state, bits); fmpz_randtest(x, state, bits); fmpq_mat_scalar_mul_fmpz(A, B, x); fmpq_mat_scalar_mul_fmpz(B, B, x); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"), fmpq_mat_print(A); flint_printf("B:\n"), fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpz_clear(x); } /* (A + B) * x == A * x + B * x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C, D; fmpz_t x; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_init(D, m, n); fmpz_init(x); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpz_randtest(x, state, bits); fmpq_mat_scalar_mul_fmpz(C, A, x); fmpq_mat_scalar_mul_fmpz(D, B, x); fmpq_mat_add(D, C, D); fmpq_mat_add(C, A, B); fmpq_mat_scalar_mul_fmpz(C, C, x); result = fmpq_mat_equal(C, D); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"), fmpq_mat_print(A); flint_printf("B:\n"), fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve.c000066400000000000000000000070201461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve, state) { int i; /* Solve nonsingular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpq_t d; int success; slong n, m, bits; if (n_randint(state, 2)) { n = n_randint(state, 30); m = n_randint(state, 30); bits = 1 + n_randint(state, 10); } else { n = n_randint(state, 10); m = n_randint(state, 10); bits = 1 + n_randint(state, 100); } fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpq_init(d); /* XXX: replace with a randtest function */ do { fmpq_mat_randtest(A, state, bits); fmpq_mat_det(d, A); } while (fmpq_is_zero(d)); fmpq_clear(d); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_solve(X, A, B); fmpq_mat_mul(AX, A, X); if (!fmpq_mat_equal(AX, B) || !success) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X; fmpz_mat_t M; fmpz_t den; slong n, m, bits; int success; if (n_randint(state, 2)) { n = 1 + n_randint(state, 40); m = 1 + n_randint(state, 40); bits = 1 + n_randint(state, 10); } else { n = 1 + n_randint(state, 10); m = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); } fmpz_init(den); fmpz_mat_init(M, n, n); fmpz_mat_randrank(M, state, n_randint(state, n), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_init(A, n, n); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_init(B, n, m); fmpq_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpq_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve_dixon.c000066400000000000000000000061441461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve_dixon, state) { int i; /* Solve nonsingular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpq_t d; int success; slong n, m, bits; n = n_randint(state, 10); m = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpq_init(d); /* XXX: replace with a randtest function */ do { fmpq_mat_randtest(A, state, bits); fmpq_mat_det(d, A); } while (fmpq_is_zero(d)); fmpq_clear(d); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_solve_dixon(X, A, B); fmpq_mat_mul(AX, A, X); if (!fmpq_mat_equal(AX, B) || !success) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X; fmpz_mat_t M; fmpz_t den; slong n, m, bits; int success; n = 1 + n_randint(state, 10); m = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpz_mat_init(M, n, n); fmpz_mat_randrank(M, state, n_randint(state, n), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_init(A, n, n); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_init(B, n, m); fmpq_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve_dixon(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpq_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve_fmpz_mat.c000066400000000000000000000057071461254215100216500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve_fmpz_mat, state) { int i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X, AX; fmpz_mat_t A, B, AX_Z; fmpz_t d; int success; slong n, m, bits; n = n_randint(state, 40); m = n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_init(B, n, m); fmpz_mat_init(AX_Z, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpz_init(d); /* XXX: replace with a randtest function */ do { fmpz_mat_randtest(A, state, bits); fmpz_mat_det(d, A); } while (fmpz_is_zero(d)); fmpz_clear(d); fmpz_mat_randtest(B, state, bits); success = fmpq_mat_solve_fmpz_mat(X, A, B); fmpq_mat_mul_r_fmpz_mat(AX, A, X); if (!success || !fmpq_mat_get_fmpz_mat(AX_Z, AX) || !fmpz_mat_equal(AX_Z, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpz_mat_print(A); flint_printf("B:\n"); fmpz_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(AX_Z); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X; fmpz_mat_t A, B; slong n, m, bits; int success; n = 1 + n_randint(state, 40); m = 1 + n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_randrank(A, state, n_randint(state, n), bits); fmpz_mat_init(B, n, m); fmpz_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve_fmpz_mat(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpz_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve_fmpz_mat_dixon.c000066400000000000000000000057311461254215100230460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve_fmpz_mat_dixon, state) { int i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X, AX; fmpz_mat_t A, B, AX_Z; fmpz_t d; int success; slong n, m, bits; n = n_randint(state, 40); m = n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_init(B, n, m); fmpz_mat_init(AX_Z, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpz_init(d); /* XXX: replace with a randtest function */ do { fmpz_mat_randtest(A, state, bits); fmpz_mat_det(d, A); } while (fmpz_is_zero(d)); fmpz_clear(d); fmpz_mat_randtest(B, state, bits); success = fmpq_mat_solve_fmpz_mat_dixon(X, A, B); fmpq_mat_mul_r_fmpz_mat(AX, A, X); if (!success || !fmpq_mat_get_fmpz_mat(AX_Z, AX) || !fmpz_mat_equal(AX_Z, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpz_mat_print(A); flint_printf("B:\n"); fmpz_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(AX_Z); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X; fmpz_mat_t A, B; slong n, m, bits; int success; n = 1 + n_randint(state, 40); m = 1 + n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_randrank(A, state, n_randint(state, n), bits); fmpz_mat_init(B, n, m); fmpz_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve_fmpz_mat_dixon(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpz_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve_fmpz_mat_fraction_free.c000066400000000000000000000057611461254215100245360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve_fmpz_mat_fraction_free, state) { int i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X, AX; fmpz_mat_t A, B, AX_Z; fmpz_t d; int success; slong n, m, bits; n = n_randint(state, 40); m = n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_init(B, n, m); fmpz_mat_init(AX_Z, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpz_init(d); /* XXX: replace with a randtest function */ do { fmpz_mat_randtest(A, state, bits); fmpz_mat_det(d, A); } while (fmpz_is_zero(d)); fmpz_clear(d); fmpz_mat_randtest(B, state, bits); success = fmpq_mat_solve_fmpz_mat_fraction_free(X, A, B); fmpq_mat_mul_r_fmpz_mat(AX, A, X); if (!success || !fmpq_mat_get_fmpz_mat(AX_Z, AX) || !fmpz_mat_equal(AX_Z, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpz_mat_print(A); flint_printf("B:\n"); fmpz_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(AX_Z); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X; fmpz_mat_t A, B; slong n, m, bits; int success; n = 1 + n_randint(state, 40); m = 1 + n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_randrank(A, state, n_randint(state, n), bits); fmpz_mat_init(B, n, m); fmpz_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve_fmpz_mat_fraction_free(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpz_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve_fmpz_mat_multi_mod.c000066400000000000000000000057451461254215100237230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve_fmpz_mat_multi_mod, state) { int i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X, AX; fmpz_mat_t A, B, AX_Z; fmpz_t d; int success; slong n, m, bits; n = n_randint(state, 40); m = n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_init(B, n, m); fmpz_mat_init(AX_Z, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpz_init(d); /* XXX: replace with a randtest function */ do { fmpz_mat_randtest(A, state, bits); fmpz_mat_det(d, A); } while (fmpz_is_zero(d)); fmpz_clear(d); fmpz_mat_randtest(B, state, bits); success = fmpq_mat_solve_fmpz_mat_multi_mod(X, A, B); fmpq_mat_mul_r_fmpz_mat(AX, A, X); if (!success || !fmpq_mat_get_fmpz_mat(AX_Z, AX) || !fmpz_mat_equal(AX_Z, B)) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpz_mat_print(A); flint_printf("B:\n"); fmpz_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(AX_Z); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mat_t X; fmpz_mat_t A, B; slong n, m, bits; int success; n = 1 + n_randint(state, 40); m = 1 + n_randint(state, 40); bits = 1 + n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_randrank(A, state, n_randint(state, n), bits); fmpz_mat_init(B, n, m); fmpz_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve_fmpz_mat_multi_mod(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpz_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve_fraction_free.c000066400000000000000000000061311461254215100226310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve_fraction_free, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpq_t d; int success; slong n, m, bits; n = n_randint(state, 10); m = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpq_init(d); /* XXX: replace with a randtest function */ do { fmpq_mat_randtest(A, state, bits); fmpq_mat_det(d, A); } while (fmpq_is_zero(d)); fmpq_clear(d); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_solve_fraction_free(X, A, B); fmpq_mat_mul(AX, A, X); if (!fmpq_mat_equal(AX, B) || !success) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X; fmpz_mat_t M; fmpz_t den; slong n, m, bits; int success; n = 1 + n_randint(state, 10); m = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpz_mat_init(M, n, n); fmpz_mat_randrank(M, state, n_randint(state, n), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_init(A, n, n); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_init(B, n, m); fmpq_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve_fraction_free(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpq_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-solve_multi_mod.c000066400000000000000000000061601461254215100220160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_solve_multi_mod, state) { int i; /* Solve nonsingular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X, AX; fmpq_t d; int success; slong n, m, bits; n = n_randint(state, 10); m = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, n, n); fmpq_mat_init(B, n, m); fmpq_mat_init(X, n, m); fmpq_mat_init(AX, n, m); fmpq_init(d); /* XXX: replace with a randtest function */ do { fmpq_mat_randtest(A, state, bits); fmpq_mat_det(d, A); } while (fmpq_is_zero(d)); fmpq_clear(d); fmpq_mat_randtest(B, state, bits); success = fmpq_mat_solve_multi_mod(X, A, B); fmpq_mat_mul(AX, A, X); if (!fmpq_mat_equal(AX, B) || !success) { flint_printf("FAIL!\n"); flint_printf("success: %d\n", success); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("X:\n"); fmpq_mat_print(X); flint_printf("AX:\n"); fmpq_mat_print(AX); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } /* Check singular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, X; fmpz_mat_t M; fmpz_t den; slong n, m, bits; int success; n = 1 + n_randint(state, 10); m = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_init(den); fmpz_mat_init(M, n, n); fmpz_mat_randrank(M, state, n_randint(state, n), bits); if (i % 2) fmpz_mat_randops(M, state, n_randint(state, 2*m*n + 1)); fmpz_randtest_not_zero(den, state, bits); fmpq_mat_init(A, n, n); fmpq_mat_set_fmpz_mat_div_fmpz(A, M, den); fmpq_mat_init(B, n, m); fmpq_mat_randtest(B, state, bits); fmpq_mat_init(X, n, m); success = fmpq_mat_solve_multi_mod(X, A, B); if (success != 0) { flint_printf("FAIL!\n"); flint_printf("Expected success = 0\n"); fmpq_mat_print(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-sub.c000066400000000000000000000070331461254215100174060ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_sub, state) { int i, result; /* Aliasing, B = B - C */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_randtest(B, state, bits); fmpq_mat_randtest(C, state, bits); fmpq_mat_sub(A, B, C); fmpq_mat_sub(B, B, C); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL (B = B - C):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } /* Aliasing, C = B - C */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_randtest(B, state, bits); fmpq_mat_randtest(C, state, bits); fmpq_mat_sub(A, B, C); fmpq_mat_sub(C, B, C); result = fmpq_mat_equal(A, C); if (!result) { flint_printf("FAIL (C = B - C):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } /* A - B == -(B - A) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C, D; slong m, n, bits; m = n_randint(state, 10); n = n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_init(D, m, n); fmpq_mat_randtest(A, state, bits); fmpq_mat_randtest(B, state, bits); fmpq_mat_sub(C, A, B); fmpq_mat_sub(D, B, A); fmpq_mat_neg(D, D); result = fmpq_mat_equal(C, D); if (!result) { flint_printf("FAIL (A + B == B + A):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); flint_printf("D:\n"); fmpq_mat_print(D); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-trace.c000066400000000000000000000036001461254215100177070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_trace, state) { slong i; /* Test trace(AB) = trace(BA) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, AB, BA; fmpq_t trab, trba; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, n, m); fmpq_mat_init(AB, m, m); fmpq_mat_init(BA, n, n); fmpq_init(trab); fmpq_init(trba); fmpq_mat_randtest(A, state, 1 + n_randint(state, 100)); fmpq_mat_randtest(B, state, 1 + n_randint(state, 100)); fmpq_mat_mul(AB, A, B); fmpq_mat_mul(BA, B, A); fmpq_mat_trace(trab, AB); fmpq_mat_trace(trba, BA); if (!fmpq_equal(trab, trba)) { flint_printf("FAIL:\n"); fmpq_mat_print(A), flint_printf("\n"); fmpq_mat_print(B), flint_printf("\n"); fmpq_mat_print(AB), flint_printf("\n"); fmpq_mat_print(BA), flint_printf("\n"); flint_printf("tr(AB): "), fmpq_print(trab), flint_printf("\n"); flint_printf("tr(BA): "), fmpq_print(trba), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(AB); fmpq_mat_clear(BA); fmpq_clear(trab); fmpq_clear(trba); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-transpose.c000066400000000000000000000043331461254215100206330ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_transpose, state) { int i, result; /* Aliasing, B = B^t */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B, C; slong m, n, bits; m = n_randint(state, 10); n = m; bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); fmpq_mat_randtest(A, state, bits); fmpq_mat_set(B, A); fmpq_mat_transpose(C, B); fmpq_mat_transpose(B, B); result = fmpq_mat_equal(B, C); if (!result) { flint_printf("FAIL (B = B^t):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); flint_printf("C:\n"); fmpq_mat_print(C); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } /* ((B^t)^t) == B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mat_t A, B; slong m, n, bits; m = n_randint(state, 10); n = m; bits = 1 + n_randint(state, 100); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_randtest(A, state, bits); fmpq_mat_transpose(B, A); fmpq_mat_transpose(B, B); result = fmpq_mat_equal(A, B); if (!result) { flint_printf("FAIL ((B^t)^t == B):\n"); flint_printf("A:\n"); fmpq_mat_print(A); flint_printf("B:\n"); fmpq_mat_print(B); fflush(stdout); flint_abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/test/t-window_init_clear.c000066400000000000000000000026521461254215100223170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_mat.h" TEST_FUNCTION_START(fmpq_mat_window_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mat_t a, w; slong j, k, r1, r2, c1, c2; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpq_mat_init(a, rows, cols); fmpq_mat_randtest(a, state, n_randint(state, 200) + 1); r2 = n_randint(state, rows + 1); c2 = n_randint(state, cols + 1); if (r2) r1 = n_randint(state, r2); else r1 = 0; if (c2) c1 = n_randint(state, c2); else c1 = 0; fmpq_mat_window_init(w, a, r1, c1, r2, c2); for (j = 0; j < r2 - r1; j++) for (k = 0; k < c2 - c1; k++) fmpq_zero(fmpq_mat_entry(w, j, k)); fmpq_mat_window_clear(w); fmpq_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mat/trace.c000066400000000000000000000013351461254215100164720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_trace(fmpq_t trace, const fmpq_mat_t mat) { slong i, n = fmpq_mat_nrows(mat); if (n == 0) fmpq_zero(trace); else { fmpq_set(trace, fmpq_mat_entry(mat, 0, 0)); for (i = 1; i < n; i++) fmpq_add(trace, trace, fmpq_mat_entry(mat, i, i)); } } flint-3.1.3/src/fmpq_mat/transpose.c000066400000000000000000000016311461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_transpose(fmpq_mat_t rop, const fmpq_mat_t op) { slong i, j; if (rop == op) { for (i = 0; i < rop->r; i++) for (j = 0; j < i; j++) fmpq_swap(fmpq_mat_entry(rop, i, j), fmpq_mat_entry(rop, j, i)); } else { for (i = 0; i < rop->r; i++) for (j = 0; j < rop->c; j++) fmpq_set(fmpq_mat_entry(rop, i, j), fmpq_mat_entry(op, j, i)); } } flint-3.1.3/src/fmpq_mat/window_clear.c000066400000000000000000000010021461254215100200400ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" void fmpq_mat_window_clear(fmpq_mat_t window) { if (window->r != 0) flint_free(window->rows); } flint-3.1.3/src/fmpq_mat/window_init.c000066400000000000000000000017211461254215100177250ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" void fmpq_mat_window_init(fmpq_mat_t window, const fmpq_mat_t mat, slong r1, slong c1, slong r2, slong c2) { slong i; window->entries = NULL; if (r2 > r1) window->rows = (fmpq **) flint_malloc((r2 - r1) * sizeof(fmpq *)); else window->rows = NULL; if (mat->c > 0) { for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; } else { for (i = 0; i < r2 - r1; i++) window->rows[i] = NULL; } window->r = r2 - r1; window->c = c2 - c1; } flint-3.1.3/src/fmpq_mat/zero.c000066400000000000000000000011301461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" void fmpq_mat_zero(fmpq_mat_t mat) { slong i, j; for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) fmpq_zero(fmpq_mat_entry(mat, i, j)); } flint-3.1.3/src/fmpq_mpoly.h000066400000000000000000000725621461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_MPOLY_H #define FMPQ_MPOLY_H #ifdef FMPQ_MPOLY_INLINES_C #define FMPQ_MPOLY_INLINE #else #define FMPQ_MPOLY_INLINE static inline #endif #include "fmpq_types.h" #include "fmpq.h" #include "fmpz_mpoly.h" #ifdef __cplusplus extern "C" { #endif /* Context object ************************************************************/ FMPQ_MPOLY_INLINE void fmpq_mpoly_ctx_init(fmpq_mpoly_ctx_t ctx, slong nvars, const ordering_t ord) { fmpz_mpoly_ctx_init(ctx->zctx, nvars, ord); } FMPQ_MPOLY_INLINE void fmpq_mpoly_ctx_init_rand(fmpq_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars) { fmpz_mpoly_ctx_init_rand(ctx->zctx, state, max_nvars); } FMPQ_MPOLY_INLINE void fmpq_mpoly_ctx_clear(fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_ctx_clear(ctx->zctx); } FMPQ_MPOLY_INLINE slong fmpq_mpoly_ctx_nvars(const fmpq_mpoly_ctx_t ctx) { return ctx->zctx->minfo->nvars; } FMPQ_MPOLY_INLINE ordering_t fmpq_mpoly_ctx_ord(const fmpq_mpoly_ctx_t ctx) { return ctx->zctx->minfo->ord; } /* Polynomials over Q ********************************************************/ FMPQ_MPOLY_INLINE fmpq * fmpq_mpoly_content_ref(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return A->content; } FMPQ_MPOLY_INLINE fmpz_mpoly_struct * fmpq_mpoly_zpoly_ref(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return A->zpoly; } FMPQ_MPOLY_INLINE fmpz * fmpq_mpoly_zpoly_term_coeff_ref(fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT(i < A->zpoly->length); return A->zpoly->coeffs + i; } /* Internal type definitions *************************************************/ /* fmpq_mpoly_univar_t sparse univariates with multivariate coefficients */ typedef struct { fmpq_mpoly_struct * coeffs; /* multivariate coefficients */ fmpz * exps; slong alloc; slong length; } fmpq_mpoly_univar_struct; typedef fmpq_mpoly_univar_struct fmpq_mpoly_univar_t[1]; /* Memory management ********************************************************/ FMPQ_MPOLY_INLINE void fmpq_mpoly_init(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpq_init(A->content); fmpz_mpoly_init(A->zpoly, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_init2(fmpq_mpoly_t A, slong alloc, const fmpq_mpoly_ctx_t ctx) { fmpq_init(A->content); fmpz_mpoly_init2(A->zpoly, alloc, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_init3(fmpq_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpq_mpoly_ctx_t ctx) { fmpq_init(A->content); fmpz_mpoly_init3(A->zpoly, alloc, bits, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_realloc(fmpq_mpoly_t A, slong alloc, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_realloc(A->zpoly, alloc, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_fit_length(fmpq_mpoly_t A, slong len, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_fit_length(A->zpoly, len, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_clear(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_clear(A->zpoly, ctx->zctx); fmpq_clear(A->content); } FMPQ_MPOLY_INLINE void fmpq_mpoly_fit_bits(fmpq_mpoly_t A, flint_bitcnt_t bits, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_fit_bits(A->zpoly, bits, ctx->zctx); } /* Input/output **************************************************************/ int fmpq_mpoly_set_str_pretty(fmpq_mpoly_t A, const char * str, const char ** x, const fmpq_mpoly_ctx_t ctx); char * fmpq_mpoly_get_str_pretty(const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx); #ifdef FLINT_HAVE_FILE int fmpq_mpoly_fprint_pretty(FILE * file, const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx); #endif int fmpq_mpoly_print_pretty(const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx); /* Basic manipulation *******************************************************/ FMPQ_MPOLY_INLINE void fmpq_mpoly_gen(fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) { fmpq_one(A->content); fmpz_mpoly_gen(A->zpoly, var, ctx->zctx); } FMPQ_MPOLY_INLINE int fmpq_mpoly_is_gen(const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) { return fmpq_is_one(A->content) && fmpz_mpoly_is_gen(A->zpoly, var, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_set(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { fmpq_set(A->content, B->content); fmpz_mpoly_set(A->zpoly, B->zpoly, ctx->zctx); } FMPQ_MPOLY_INLINE int fmpq_mpoly_equal(const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { return fmpq_equal(A->content, B->content) && fmpz_mpoly_equal(A->zpoly, B->zpoly, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_swap(fmpq_mpoly_t A, fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { FLINT_SWAP(fmpq_mpoly_struct, *A, *B); } /* Constants *****************************************************************/ FMPQ_MPOLY_INLINE int fmpq_mpoly_is_fmpq(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return fmpz_mpoly_is_fmpz(A->zpoly, ctx->zctx); } void fmpq_mpoly_get_fmpq(fmpq_t c, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_fmpq(fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_fmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_ui(fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_si(fmpq_mpoly_t A, slong c, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE void fmpq_mpoly_zero(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpq_zero(A->content); fmpz_mpoly_zero(A->zpoly, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_one(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpq_one(A->content); fmpz_mpoly_one(A->zpoly, ctx->zctx); } int fmpq_mpoly_equal_fmpq(const fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_equal_fmpz(const fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_equal_ui(const fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_equal_si(const fmpq_mpoly_t A, slong c, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE int fmpq_mpoly_is_zero(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return A->zpoly->length == WORD(0); } FMPQ_MPOLY_INLINE int fmpq_mpoly_is_one(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return fmpq_is_one(A->content) && fmpz_mpoly_is_one(A->zpoly, ctx->zctx); } /* Degrees *******************************************************************/ int fmpq_mpoly_degrees_fit_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_degrees_fmpz(fmpz ** degs, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_degrees_si(slong * degs, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_degree_fmpz(fmpz_t deg, const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx); slong fmpq_mpoly_degree_si(const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_total_degree_fits_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_total_degree_fmpz(fmpz_t tdeg, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); slong fmpq_mpoly_total_degree_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE void fmpq_mpoly_used_vars(int * used, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_used_vars(used, A->zpoly, ctx->zctx); } /* Coefficients **************************************************************/ FMPQ_MPOLY_INLINE void fmpq_mpoly_get_denominator(fmpz_t d, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_set(d, fmpq_denref(A->content)); } int fmpq_mpoly_is_monic(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_coeff_fmpq_monomial(fmpq_t c, const fmpq_mpoly_t A, const fmpq_mpoly_t M, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_coeff_fmpq_monomial(fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_t M, const fmpq_mpoly_ctx_t ctx); void _fmpq_mpoly_set_coeff_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_coeff_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_coeff_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); void _fmpq_mpoly_get_coeff_fmpq_fmpz(fmpq_t c, const fmpq_mpoly_t A, const fmpz * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_coeff_fmpq_fmpz(fmpq_t c, const fmpq_mpoly_t A, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_coeff_fmpq_ui(fmpq_t c, const fmpq_mpoly_t A, const ulong * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_coeff_vars_ui(fmpq_mpoly_t C, const fmpq_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpq_mpoly_ctx_t ctx); /* conversion ****************************************************************/ int fmpq_mpoly_is_fmpq_poly(const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_get_fmpq_poly(fmpq_poly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_fmpq_poly(fmpq_mpoly_t A, const fmpq_poly_t B, slong var, const fmpq_mpoly_ctx_t ctx); /* comparison ****************************************************************/ int fmpq_mpoly_cmp(const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); /* container operations ******************************************************/ int fmpq_mpoly_is_canonical(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE slong fmpq_mpoly_length(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return A->zpoly->length; } FMPQ_MPOLY_INLINE void fmpq_mpoly_resize(fmpq_mpoly_t A, slong new_length, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_resize(A->zpoly, new_length, ctx->zctx); } void fmpq_mpoly_get_term_coeff_fmpq(fmpq_t c, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_set_term_coeff_fmpq(fmpq_mpoly_t A, slong i, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_term_exp_fits_ui(const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_term_exp_fits_si(const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_term_exp_fmpz(fmpz ** exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_term_exp_ui(ulong * exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_term_exp_si(slong * exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); ulong fmpq_mpoly_get_term_var_exp_ui(const fmpq_mpoly_t A, slong i, slong var, const fmpq_mpoly_ctx_t ctx); slong fmpq_mpoly_get_term_var_exp_si(const fmpq_mpoly_t A, slong i, slong var, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE void fmpq_mpoly_set_term_exp_fmpz(fmpq_mpoly_t A, slong i, fmpz * const * exps, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_set_term_exp_fmpz(A->zpoly, i, exps, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_set_term_exp_ui(fmpq_mpoly_t A, slong i, const ulong * exps, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_set_term_exp_ui(A->zpoly, i, exps, ctx->zctx); } void fmpq_mpoly_get_term(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_get_term_monomial(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_fmpq_ffmpz(fmpq_mpoly_t A, const fmpq_t c, const fmpz *exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, fmpz *const *exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_fmpz_ffmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpz *exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, ulong c, fmpz *const *exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_ui_ffmpz(fmpq_mpoly_t A, ulong c, const fmpz *exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, slong c, fmpz *const *exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_si_ffmpz(fmpq_mpoly_t A, slong c, const fmpz *exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_fmpz_ui(fmpq_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_ui_ui(fmpq_mpoly_t A, ulong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_si_ui(fmpq_mpoly_t A, slong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_reduce(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_reduce_easy(fmpq_mpoly_t A, slong easy_length, const fmpq_mpoly_ctx_t); FMPQ_MPOLY_INLINE void fmpq_mpoly_sort_terms(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_sort_terms(A->zpoly, ctx->zctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_combine_like_terms(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_combine_like_terms(A->zpoly, ctx->zctx); fmpq_mpoly_reduce(A, ctx); } void fmpq_mpoly_reverse(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_assert_canonical(const fmpq_mpoly_t poly, const fmpq_mpoly_ctx_t ctx); void _fmpq_mpoly_push_rescale(fmpq_mpoly_t A, fmpq_t C, const fmpq_mpoly_ctx_t ctx); /* Random generation *********************************************************/ FMPQ_MPOLY_INLINE void fmpq_mpoly_randtest_bounds(fmpq_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, ulong * exp_bounds, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_randtest_bounds(A->zpoly, state, length, coeff_bits, exp_bounds, ctx->zctx); fmpq_randtest_not_zero(A->content, state, coeff_bits + 1); fmpq_mpoly_reduce(A, ctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_randtest_bound(fmpq_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, ulong exp_bound, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_randtest_bound(A->zpoly, state, length, coeff_bits, exp_bound, ctx->zctx); fmpq_randtest_not_zero(A->content, state, coeff_bits + 1); fmpq_mpoly_reduce(A, ctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_randtest_bits(fmpq_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, flint_bitcnt_t exp_bits, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_randtest_bits(A->zpoly, state, length, coeff_bits, exp_bits, ctx->zctx); fmpq_randtest_not_zero(A->content, state, coeff_bits + 1); fmpq_mpoly_reduce(A, ctx); } /* Basic arithmetic **********************************************************/ void fmpq_mpoly_add_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_add_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_add_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_add_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_sub_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_sub_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_sub_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_sub_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_add(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_sub(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx); /* Scalar operations *********************************************************/ FMPQ_MPOLY_INLINE void fmpq_mpoly_neg(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { fmpq_neg(A->content, B->content); fmpz_mpoly_set(A->zpoly, B->zpoly, ctx->zctx); } void fmpq_mpoly_scalar_mul_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_scalar_mul_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_scalar_mul_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_scalar_mul_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_scalar_div_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_scalar_div_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_scalar_div_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_scalar_div_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_make_monic(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); void _fmpq_mpoly_make_monic_inplace(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); /* Differentiation/Integration ***********************************************/ void fmpq_mpoly_derivative(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_integral(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ int _fmpq_mpoly_rescale(fmpq_t Acontent, fmpz * Acoeff, const fmpq_mpoly_t B, const fmpq * scales, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_evaluate_all_fmpq(fmpq_t ev, const fmpq_mpoly_t A, fmpq * const * vals, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_evaluate_one_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_t val, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_compose_fmpq_poly(fmpq_poly_t A, const fmpq_mpoly_t B, fmpq_poly_struct * const * C, const fmpq_mpoly_ctx_t ctxB); int fmpq_mpoly_compose_fmpq_mpoly(fmpq_mpoly_t A, const fmpq_mpoly_t B, fmpq_mpoly_struct * const * C, const fmpq_mpoly_ctx_t ctxB, const fmpq_mpoly_ctx_t ctxAC); void fmpq_mpoly_compose_fmpq_mpoly_gen(fmpq_mpoly_t A, const fmpq_mpoly_t B, const slong * c, const fmpq_mpoly_ctx_t ctxB, const fmpq_mpoly_ctx_t ctxAC); /* Multiplication ************************************************************/ void fmpq_mpoly_mul(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx); /* Powering ******************************************************************/ int fmpq_mpoly_pow_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t k, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_pow_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong k, const fmpq_mpoly_ctx_t ctx); /* Division ******************************************************************/ int fmpq_mpoly_divides(fmpq_mpoly_t poly1, const fmpq_mpoly_t poly2, const fmpq_mpoly_t poly3, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_div(fmpq_mpoly_t q, const fmpq_mpoly_t poly2, const fmpq_mpoly_t poly3, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_divrem(fmpq_mpoly_t q, fmpq_mpoly_t r, const fmpq_mpoly_t poly2, const fmpq_mpoly_t poly3, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_divrem_ideal(fmpq_mpoly_struct ** q, fmpq_mpoly_t r, const fmpq_mpoly_t poly2, fmpq_mpoly_struct * const * poly3, slong len, const fmpq_mpoly_ctx_t ctx); /* Square root ***************************************************************/ int fmpq_mpoly_sqrt(fmpq_mpoly_t Q, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE int fmpq_mpoly_is_square(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return fmpz_is_square(fmpq_numref(A->content)) && fmpz_is_square(fmpq_denref(A->content)) && fmpz_mpoly_is_square(A->zpoly, ctx->zctx); } /* GCD ***********************************************************************/ FMPQ_MPOLY_INLINE void fmpq_mpoly_content(fmpq_t g, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpq_abs(g, A->content); } void fmpq_mpoly_term_content(fmpq_mpoly_t M, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_content_vars(fmpq_mpoly_t g, const fmpq_mpoly_t A, slong * vars, slong vars_length, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_gcd(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_inflate(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_gcd_cofactors(fmpq_mpoly_t G, fmpq_mpoly_t Abar, fmpq_mpoly_t Bbar, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_gcd_hensel(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_gcd_brown(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_gcd_subresultant(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_gcd_zippel(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_gcd_zippel2(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_resultant(fmpq_mpoly_t R, const fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_discriminant(fmpq_mpoly_t R, const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx); /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ void mpoly_void_ring_init_fmpq_mpoly_ctx(mpoly_void_ring_t R, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_repack_bits(fmpq_mpoly_t A, const fmpq_mpoly_t B, flint_bitcnt_t Abits, const fmpq_mpoly_ctx_t ctx); /* Univariates ***************************************************************/ void fmpq_mpoly_univar_init(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_univar_clear(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_univar_fit_length(fmpq_mpoly_univar_t A, slong length, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_univar_print_pretty(const fmpq_mpoly_univar_t A, const char ** x, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_univar_assert_canonical(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_to_univar(fmpq_mpoly_univar_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_from_univar_bits(fmpq_mpoly_t A, flint_bitcnt_t Abits, const fmpq_mpoly_univar_t B, slong var, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_from_univar(fmpq_mpoly_t A, const fmpq_mpoly_univar_t B, slong var, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE void fmpq_mpoly_univar_swap(fmpq_mpoly_univar_t A, fmpq_mpoly_univar_t B, const fmpq_mpoly_ctx_t ctx) { FLINT_SWAP(fmpq_mpoly_univar_struct, *A, *B); } FMPQ_MPOLY_INLINE int fmpq_mpoly_univar_degree_fits_si(const fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) { return A->length == 0 || fmpz_fits_si(A->exps + 0); } FMPQ_MPOLY_INLINE slong fmpq_mpoly_univar_length(const fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) { return A->length; } FMPQ_MPOLY_INLINE slong fmpq_mpoly_univar_get_term_exp_si(fmpq_mpoly_univar_t A, slong i, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); return fmpz_get_si(A->exps + i); } FMPQ_MPOLY_INLINE void fmpq_mpoly_univar_get_term_coeff(fmpq_mpoly_t c, const fmpq_mpoly_univar_t A, slong i, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fmpq_mpoly_set(c, A->coeffs + i, ctx); } FMPQ_MPOLY_INLINE void fmpq_mpoly_univar_swap_term_coeff(fmpq_mpoly_t c, fmpq_mpoly_univar_t A, slong i, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fmpq_mpoly_swap(c, A->coeffs + i, ctx); } /****************************************************************************** Internal consistency checks ******************************************************************************/ void fmpq_mpoly_remainder_test(const fmpq_mpoly_t r, const fmpq_mpoly_t g, const fmpq_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpq_mpoly/000077500000000000000000000000001461254215100156055ustar00rootroot00000000000000flint-3.1.3/src/fmpq_mpoly/add.c000066400000000000000000000021251461254215100165010ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_add(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx) { fmpz_t t1, t2; slong easy_length = B->zpoly->length + C->zpoly->length; if (fmpq_mpoly_is_zero(B, ctx)) { fmpq_mpoly_set(A, C, ctx); return; } if (fmpq_mpoly_is_zero(C, ctx)) { fmpq_mpoly_set(A, B, ctx); return; } fmpz_init(t1); fmpz_init(t2); fmpq_gcd_cofactors(A->content, t1, t2, B->content, C->content); fmpz_mpoly_scalar_fmma(A->zpoly, B->zpoly, t1, C->zpoly, t2, ctx->zctx); fmpz_clear(t1); fmpz_clear(t2); fmpq_mpoly_reduce_easy(A, easy_length, ctx); } flint-3.1.3/src/fmpq_mpoly/add_fmpq.c000066400000000000000000000037011461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_add_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) { fmpz_t t1, t2; slong easy_length = B->zpoly->length + 1; if (fmpq_is_zero(c)) { fmpq_mpoly_set(A, B, ctx); return; } else if (fmpq_mpoly_is_zero(B, ctx)) { fmpq_mpoly_set_fmpq(A, c, ctx); return; } fmpz_init(t1); fmpz_init(t2); fmpq_gcd_cofactors(A->content, t1, t2, B->content, c); fmpz_mpoly_scalar_mul_fmpz(A->zpoly, B->zpoly, t1, ctx->zctx); fmpz_mpoly_add_fmpz(A->zpoly, A->zpoly, t2, ctx->zctx); fmpz_clear(t1); fmpz_clear(t2); fmpq_mpoly_reduce_easy(A, easy_length, ctx); } void fmpq_mpoly_add_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) { fmpq_t t; *fmpq_numref(t) = *c; *fmpq_denref(t) = 1; fmpq_mpoly_add_fmpq(A, B, t, ctx); } void fmpq_mpoly_add_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) { fmpq_t t; fmpz_init_set_ui(fmpq_numref(t), c); *fmpq_denref(t) = 1; fmpq_mpoly_add_fmpq(A, B, t, ctx); fmpz_clear(fmpq_numref(t)); } void fmpq_mpoly_add_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) { fmpq_t t; fmpz_init_set_si(fmpq_numref(t), c); *fmpq_denref(t) = 1; fmpq_mpoly_add_fmpq(A, B, t, ctx); fmpz_clear(fmpq_numref(t)); } flint-3.1.3/src/fmpq_mpoly/cmp.c000066400000000000000000000027061461254215100165350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" int fmpq_mpoly_cmp(const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { int cmp; slong i; slong length = A->zpoly->length; fmpz * Acoeffs = A->zpoly->coeffs; fmpz * Bcoeffs = B->zpoly->coeffs; if (A->zpoly->length != B->zpoly->length) return A->zpoly->length < B->zpoly->length ? -1 : 1; if (length <= 0) return 0; cmp = mpoly_monomials_cmp(A->zpoly->exps, A->zpoly->bits, B->zpoly->exps, B->zpoly->bits, length, ctx->zctx->minfo); if (cmp != 0) return cmp; cmp = fmpz_cmp(fmpq_denref(A->content), fmpq_denref(B->content)); if (cmp != 0) return cmp; cmp = fmpz_cmp(fmpq_numref(A->content), fmpq_numref(B->content)); if (cmp != 0) return cmp; for (i = 0; i < length; i++) { cmp = fmpz_cmp(Acoeffs + i, Bcoeffs + i); if (cmp != 0) return cmp; } return 0; } flint-3.1.3/src/fmpq_mpoly/compose_fmpq_mpoly.c000066400000000000000000000037141461254215100216660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_mpoly.h" int fmpq_mpoly_compose_fmpq_mpoly(fmpq_mpoly_t A, const fmpq_mpoly_t B, fmpq_mpoly_struct * const * C, const fmpq_mpoly_ctx_t ctxB, const fmpq_mpoly_ctx_t ctxAC) { int success = 0; slong i; fmpq * scales; fmpz_mpoly_struct ** Czpoly; fmpz_mpoly_t newB; slong nvarsB = ctxB->zctx->minfo->nvars; TMP_INIT; if (fmpq_mpoly_is_zero(B, ctxB)) { fmpq_mpoly_zero(A, ctxAC); return 1; } TMP_START; Czpoly = (fmpz_mpoly_struct **) TMP_ALLOC(nvarsB*sizeof(fmpz_mpoly_struct *)); /* scale B by the contents of the polynomials in C We are only borrowing B to feed it to fmpz_mpoly_compose. There might be zero coeffs in newBcoeffs, but fmpz_mpoly_compose should have no problem with zero coeffs. */ scales = (fmpq *) TMP_ALLOC(nvarsB*sizeof(fmpq)); for (i = 0; i < nvarsB; i++) { Czpoly[i] = C[i]->zpoly; /* we are only borrowing the content of each of the C[i] */ *(scales + i) = *C[i]->content; } *newB = *B->zpoly; newB->coeffs = _fmpz_vec_init(B->zpoly->length); if (!_fmpq_mpoly_rescale(A->content, newB->coeffs, B, scales, ctxB)) goto cleanup; if (!fmpz_mpoly_compose_fmpz_mpoly(A->zpoly, newB, Czpoly, ctxB->zctx, ctxAC->zctx)) goto cleanup; fmpq_mpoly_reduce(A, ctxAC); success = 1; cleanup: TMP_END; _fmpz_vec_clear(newB->coeffs, B->zpoly->length); return success; } flint-3.1.3/src/fmpq_mpoly/compose_fmpq_mpoly_gen.c000066400000000000000000000016111461254215100225110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" /* evaluate B(x_1,...,x_n) at x_i = y_c[i], y_j are vars of ctxAC */ void fmpq_mpoly_compose_fmpq_mpoly_gen(fmpq_mpoly_t A, const fmpq_mpoly_t B, const slong * c, const fmpq_mpoly_ctx_t ctxB, const fmpq_mpoly_ctx_t ctxAC) { fmpq_set(A->content, B->content); fmpz_mpoly_compose_fmpz_mpoly_gen(A->zpoly, B->zpoly, c, ctxB->zctx, ctxAC->zctx); fmpq_mpoly_reduce(A, ctxAC); return; } flint-3.1.3/src/fmpq_mpoly/compose_fmpq_poly.c000066400000000000000000000047421461254215100215130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "fmpq_mpoly.h" int fmpq_mpoly_compose_fmpq_poly(fmpq_poly_t A, const fmpq_mpoly_t B, fmpq_poly_struct * const * C, const fmpq_mpoly_ctx_t ctxB) { int success = 0; slong i; fmpq * scales; fmpz_poly_struct ** Czpoly; fmpz_mpoly_t newB; fmpq_t Acontent; fmpz_poly_t Azpoly; slong nvarsB = ctxB->zctx->minfo->nvars; TMP_INIT; if (B->zpoly->length == 0) { fmpq_poly_zero(A); return 1; } TMP_START; fmpq_init(Acontent); fmpz_poly_init(Azpoly); Czpoly = (fmpz_poly_struct **) TMP_ALLOC(nvarsB*sizeof(fmpz_poly_struct *)); /* scale B by the contents of the polynomials in C We are only borrowing B to feed it to fmpz_mpoly_compose. */ scales = (fmpq *) TMP_ALLOC(nvarsB*sizeof(fmpq)); for (i = 0; i < nvarsB; i++) { /* since the fmpq_poly_t does not have a fmpz_poly_t in it, we have to manually copy the relevant struct members */ Czpoly[i] = (fmpz_poly_struct *) flint_malloc(sizeof(fmpz_poly_struct)); Czpoly[i]->coeffs = C[i]->coeffs; Czpoly[i]->alloc = C[i]->alloc; Czpoly[i]->length = C[i]->length; /* and manually set the scales */ fmpz_init_set_ui(fmpq_numref(scales + i), UWORD(1)); fmpz_init_set(fmpq_denref(scales + i), C[i]->den); } *newB = *B->zpoly; newB->coeffs = _fmpz_vec_init(B->zpoly->length); if (!_fmpq_mpoly_rescale(Acontent, newB->coeffs, B, scales, ctxB)) goto cleanup; if (!fmpz_mpoly_compose_fmpz_poly(Azpoly, newB, Czpoly, ctxB->zctx)) goto cleanup; fmpq_poly_set_fmpz_poly(A, Azpoly); fmpq_poly_scalar_mul_fmpq(A, A, Acontent); success = 1; cleanup: _fmpz_vec_clear(newB->coeffs, B->zpoly->length); for (i = 0; i < nvarsB; i++) { flint_free(Czpoly[i]); fmpq_clear(scales + i); } fmpq_clear(Acontent); fmpz_poly_clear(Azpoly); TMP_END; return success; } flint-3.1.3/src/fmpq_mpoly/content_vars.c000066400000000000000000000016141461254215100204600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_content_vars( fmpq_mpoly_t g, const fmpq_mpoly_t A, slong * vars, slong num_vars, const fmpq_mpoly_ctx_t ctx) { int success; success = fmpz_mpoly_content_vars(g->zpoly, A->zpoly, vars, num_vars, ctx->zctx); if (!success) return 0; if (g->zpoly->length > 0) { fmpz_one(fmpq_numref(g->content)); fmpz_set(fmpq_denref(g->content), g->zpoly->coeffs + 0); } else { fmpq_zero(g->content); } return 1; } flint-3.1.3/src/fmpq_mpoly/degrees.c000066400000000000000000000054071461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" int fmpq_mpoly_degrees_fit_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return A->zpoly->bits <= FLINT_BITS ? 1 : mpoly_degrees_fit_si(A->zpoly->exps, A->zpoly->length, A->zpoly->bits, ctx->zctx->minfo); } void fmpq_mpoly_degrees_fmpz(fmpz ** degs, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { mpoly_degrees_pfmpz(degs, A->zpoly->exps, A->zpoly->length, A->zpoly->bits, ctx->zctx->minfo); } void fmpq_mpoly_degrees_si(slong * degs, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { mpoly_degrees_si(degs, A->zpoly->exps, A->zpoly->length, A->zpoly->bits, ctx->zctx->minfo); } void fmpq_mpoly_degree_fmpz(fmpz_t deg, const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) { mpoly_degree_fmpz(deg, A->zpoly->exps, A->zpoly->length, A->zpoly->bits, var, ctx->zctx->minfo); } slong fmpq_mpoly_degree_si(const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) { return mpoly_degree_si(A->zpoly->exps, A->zpoly->length, A->zpoly->bits, var, ctx->zctx->minfo); } int fmpq_mpoly_total_degree_fits_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return mpoly_total_degree_fits_si(A->zpoly->exps, A->zpoly->length, A->zpoly->bits, ctx->zctx->minfo); } void fmpq_mpoly_total_degree_fmpz(fmpz_t tdeg, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { mpoly_total_degree_fmpz(tdeg, A->zpoly->exps, A->zpoly->length, A->zpoly->bits, ctx->zctx->minfo); } slong fmpq_mpoly_total_degree_si(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { return mpoly_total_degree_si(A->zpoly->exps, A->zpoly->length, A->zpoly->bits, ctx->zctx->minfo); } flint-3.1.3/src/fmpq_mpoly/derivative.c000066400000000000000000000013121461254215100201100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_derivative(fmpq_mpoly_t poly1, const fmpq_mpoly_t poly2, slong var, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_derivative(poly1->zpoly, poly2->zpoly, var, ctx->zctx); fmpq_set(poly1->content, poly2->content); fmpq_mpoly_reduce(poly1, ctx); } flint-3.1.3/src/fmpq_mpoly/discriminant.c000066400000000000000000000022111461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_discriminant(fmpq_mpoly_t R, const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) { int success; fmpz_mpoly_univar_t Ax; fmpz_mpoly_univar_init(Ax, ctx->zctx); fmpz_mpoly_to_univar(Ax, A->zpoly, var, ctx->zctx); success = fmpz_mpoly_univar_discriminant(R->zpoly, Ax, ctx->zctx); if (success && Ax->length > 0) { fmpz_t t; fmpz_init(t); fmpz_mul_ui(t, Ax->exps + 0, 2); fmpz_sub_ui(t, t, 2); success = fmpq_pow_fmpz(R->content, A->content, t); fmpz_clear(t); } else { fmpq_zero(R->content); } fmpq_mpoly_reduce(R, ctx); fmpz_mpoly_univar_clear(Ax, ctx->zctx); return success; } flint-3.1.3/src/fmpq_mpoly/div.c000066400000000000000000000020421461254215100165310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_div(fmpq_mpoly_t Q, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { fmpz_t scale; if (fmpq_mpoly_is_zero(B, ctx)) { flint_throw(FLINT_DIVZERO, "Divide by zero in fmpq_mpoly_div"); } if (fmpq_mpoly_is_zero(A, ctx)) { fmpq_mpoly_zero(Q, ctx); return; } fmpz_init(scale); fmpz_mpoly_quasidiv(scale, Q->zpoly, A->zpoly, B->zpoly, ctx->zctx); fmpq_div(Q->content, A->content, B->content); fmpq_div_fmpz(Q->content, Q->content, scale); fmpz_clear(scale); fmpq_mpoly_reduce(Q, ctx); } flint-3.1.3/src/fmpq_mpoly/divides.c000066400000000000000000000020161461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" /* return 1 if quotient is exact */ int fmpq_mpoly_divides(fmpq_mpoly_t Q, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { int res; if (fmpq_mpoly_is_zero(B, ctx)) { flint_throw(FLINT_DIVZERO, "Divide by zero in fmpq_mpoly_divides"); } if (fmpq_mpoly_is_zero(A, ctx)) { fmpq_mpoly_zero(Q, ctx); return 1; } res = fmpz_mpoly_divides(Q->zpoly, A->zpoly, B->zpoly, ctx->zctx); if (!res) { fmpq_mpoly_zero(Q, ctx); return 0; } fmpq_div(Q->content, A->content, B->content); return 1; } flint-3.1.3/src/fmpq_mpoly/divrem.c000066400000000000000000000024161461254215100172420ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_divrem(fmpq_mpoly_t Q, fmpq_mpoly_t R, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { fmpz_t scale; fmpq_t t; if (fmpq_mpoly_is_zero(B, ctx)) { flint_throw(FLINT_DIVZERO, "Divide by zero in fmpq_mpoly_divrem"); } if (fmpq_mpoly_is_zero(A, ctx)) { fmpq_mpoly_zero(Q, ctx); fmpq_mpoly_zero(R, ctx); return; } fmpz_init(scale); fmpz_mpoly_quasidivrem(scale, Q->zpoly, R->zpoly, A->zpoly, B->zpoly, ctx->zctx); fmpq_init(t); fmpq_div_fmpz(t, A->content, scale); fmpq_div(Q->content, t, B->content); fmpq_swap(t, R->content); fmpq_clear(t); fmpz_clear(scale); fmpq_mpoly_reduce(Q, ctx); fmpq_mpoly_reduce(R, ctx); } flint-3.1.3/src/fmpq_mpoly/divrem_ideal.c000066400000000000000000000037701461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" /* Assumes divisor polys don't alias any output polys */ void fmpq_mpoly_divrem_ideal(fmpq_mpoly_struct ** Q, fmpq_mpoly_t R, const fmpq_mpoly_t A, fmpq_mpoly_struct * const * B, slong len, const fmpq_mpoly_ctx_t ctx) { slong i; fmpz_t scale; fmpq_t t; fmpz_mpoly_struct ** Qarr, ** Barr; TMP_INIT; /* check none of the divisor polynomials is zero */ for (i = 0; i < len; i++) { if (fmpq_mpoly_is_zero(B[i], ctx)) { flint_throw(FLINT_DIVZERO, "Divide by zero in fmpq_mpoly_divrem_ideal"); } } /* dividend is zero, write out quotients and remainder */ if (fmpq_mpoly_is_zero(A, ctx)) { for (i = 0; i < len; i++) fmpq_mpoly_zero(Q[i], ctx); fmpq_mpoly_zero(R, ctx); return; } TMP_START; Qarr = (fmpz_mpoly_struct **) TMP_ALLOC(len*sizeof(fmpz_mpoly_struct *)); Barr = (fmpz_mpoly_struct **) TMP_ALLOC(len*sizeof(fmpz_mpoly_struct *)); for (i = 0; i < len; i++) { Qarr[i] = Q[i]->zpoly; Barr[i] = B[i]->zpoly; } fmpz_init(scale); fmpz_mpoly_quasidivrem_ideal_heap(scale, Qarr, R->zpoly, A->zpoly, Barr, len, ctx->zctx); fmpq_init(t); fmpq_div_fmpz(t, A->content, scale); for (i = 0; i < len; i++) fmpq_div(Q[i]->content, t, B[i]->content); fmpq_swap(t, R->content); fmpq_clear(t); fmpz_clear(scale); for (i = 0; i < len; i++) fmpq_mpoly_reduce(Q[i], ctx); fmpq_mpoly_reduce(R, ctx); TMP_END; } flint-3.1.3/src/fmpq_mpoly/equal_fmpq.c000066400000000000000000000013611461254215100201040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_equal_fmpq(const fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) { if (fmpq_mpoly_is_zero(A, ctx)) { return fmpq_is_zero(c); } else { return fmpq_equal(A->content, c) && fmpz_mpoly_is_one(A->zpoly, ctx->zctx); } } flint-3.1.3/src/fmpq_mpoly/equal_fmpz.c000066400000000000000000000031431461254215100201150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_equal_fmpz(const fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) { if (fmpq_mpoly_is_zero(A, ctx)) { return fmpz_is_zero(c); } else { return fmpz_is_one(fmpq_denref(A->content)) && fmpz_equal(fmpq_numref(A->content), c) && fmpz_mpoly_is_one(A->zpoly, ctx->zctx); } } int fmpq_mpoly_equal_ui(const fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx) { if (fmpq_mpoly_is_zero(A, ctx)) { return c == UWORD(0); } else { return fmpz_is_one(fmpq_denref(A->content)) && fmpz_equal_ui(fmpq_numref(A->content), c) && fmpz_mpoly_is_one(A->zpoly, ctx->zctx); } } int fmpq_mpoly_equal_si(const fmpq_mpoly_t A, slong c, const fmpq_mpoly_ctx_t ctx) { if (fmpq_mpoly_is_zero(A, ctx)) { return c == WORD(0); } else { return fmpz_is_one(fmpq_denref(A->content)) && fmpz_equal_si(fmpq_numref(A->content), c) && fmpz_mpoly_is_one(A->zpoly, ctx->zctx); } } flint-3.1.3/src/fmpq_mpoly/evaluate_all.c000066400000000000000000000133161461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpq_mpoly.h" static int _fmpz_mpoly_evaluate_all_tree_fmpq_sp(fmpq_t ev, const fmpz_mpoly_t poly, fmpq * const * vals, const fmpz_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t bits = poly->bits; slong i, j, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, shift, off; slong p_len = poly->length; const fmpz * p_coeff = poly->coeffs; const ulong * p_exp = poly->exps; slong * degrees; slong * offs; ulong * masks; fmpq * powers; fmpq_t t; TMP_INIT; FLINT_ASSERT(p_len > 0); TMP_START; degrees = TMP_ARRAY_ALLOC(nvars, slong); fmpz_mpoly_degrees_si(degrees, poly, ctx); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_fmpz_pow_ui_is_not_feasible(fmpq_height_bits(vals[i]), degrees[i])) { success = 0; goto cleanup_degrees; } entries += FLINT_BIT_COUNT(degrees[i]); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fmpq); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the non-main variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = FLINT_BIT_COUNT(degrees[i]); mpoly_gen_offset_shift_sp(&off, &shift, i, bits, ctx->minfo); for (j = 0; j < varibits; j++) { offs[k] = off; masks[k] = UWORD(1) << (shift + j); fmpq_init(powers + k); if (j == 0) fmpq_set(powers + k, vals[i]); else fmpq_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fmpq_zero(ev); fmpq_init(t); for (i = 0; i < p_len; i++) { fmpz_set(fmpq_numref(t), p_coeff + i); fmpz_one(fmpq_denref(t)); for (k = 0; k < k_len; k++) { if ((p_exp[N*i + offs[k]] & masks[k]) != WORD(0)) fmpq_mul(t, t, powers + k); } fmpq_add(ev, ev, t); } fmpq_clear(t); for (k = 0; k < k_len; k++) fmpq_clear(powers + k); cleanup_degrees: TMP_END; return success; } static int _fmpz_mpoly_evaluate_all_fmpq_mp(fmpq_t ev, const fmpz_mpoly_t poly, fmpq * const * vals, const fmpz_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t bits = poly->bits; slong i, j, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, off; slong p_len = poly->length; const fmpz * p_coeff = poly->coeffs; ulong * p_exp = poly->exps; slong * degrees; slong * offs; ulong * masks; fmpq * powers; fmpq_t t; TMP_INIT; FLINT_ASSERT(p_len > 0); TMP_START; degrees = _fmpz_vec_init(nvars); mpoly_degrees_ffmpz(degrees, p_exp, p_len, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_fmpz_pow_fmpz_is_not_feasible(fmpq_height_bits(vals[i]), degrees + i)) { success = 0; goto cleanup_degrees; } entries += fmpz_bits(degrees + i); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fmpq); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the non-main variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = fmpz_bits(degrees + i); off = mpoly_gen_offset_mp(i, bits, ctx->minfo); for (j = 0; j < varibits; j++) { offs[k] = off + (j / FLINT_BITS); masks[k] = UWORD(1) << (j % FLINT_BITS); fmpq_init(powers + k); if (j == 0) fmpq_set(powers + k, vals[i]); else fmpq_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fmpq_zero(ev); fmpq_init(t); for (i = 0; i < p_len; i++) { fmpz_set(fmpq_numref(t), p_coeff + i); fmpz_one(fmpq_denref(t)); for (k = 0; k < k_len; k++) { if ((p_exp[N*i + offs[k]] & masks[k]) != WORD(0)) fmpq_mul(t, t, powers + k); } fmpq_add(ev, ev, t); } fmpq_clear(t); for (k = 0; k < k_len; k++) fmpq_clear(powers + k); cleanup_degrees: _fmpz_vec_clear(degrees, nvars); TMP_END; return success; } /* evaluate A(xbar) at xbar = vals */ int fmpq_mpoly_evaluate_all_fmpq(fmpq_t ev, const fmpq_mpoly_t A, fmpq * const * vals, const fmpq_mpoly_ctx_t ctx) { int success; fmpq_t t; if (fmpq_mpoly_is_zero(A, ctx)) { fmpq_zero(ev); return 1; } fmpq_init(t); if (A->zpoly->bits <= FLINT_BITS) { success = _fmpz_mpoly_evaluate_all_tree_fmpq_sp(t, A->zpoly, vals, ctx->zctx); } else { success = _fmpz_mpoly_evaluate_all_fmpq_mp(t, A->zpoly, vals, ctx->zctx); } if (success) fmpq_mul(ev, t, A->content); fmpq_clear(t); return success; } flint-3.1.3/src/fmpq_mpoly/evaluate_one.c000066400000000000000000000176431461254215100204330ustar00rootroot00000000000000/* Copyright (C) 2018, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" /* exponents of B are not multiprecision */ static int _fmpq_mpoly_evaluate_one_fmpq_sp( fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, fmpz_pow_cache_t num_cache, fmpz_pow_cache_t den_cache, ulong deg, const fmpq_mpoly_ctx_t ctx) { int success = 1; slong i, N, off, shift; ulong * cmpmask, * one; slong Blen = B->zpoly->length; const fmpz * Bcoeffs = B->zpoly->coeffs; const ulong * Bexps = B->zpoly->exps; flint_bitcnt_t bits = B->zpoly->bits; slong Alen; fmpz * Acoeffs; ulong * Aexps; ulong mask, k; int need_sort = 0, cmp; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); TMP_START; if (A != B) fmpz_mpoly_fit_length_reset_bits(A->zpoly, Blen, bits, ctx->zctx); Acoeffs = A->zpoly->coeffs; Aexps = A->zpoly->exps; mask = (-UWORD(1)) >> (FLINT_BITS - bits); N = mpoly_words_per_exp_sp(bits, ctx->zctx->minfo); cmpmask = TMP_ARRAY_ALLOC(2*N, ulong); one = cmpmask + N; mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->zctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->zctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; success = fmpz_pow_cache_mulpow_ui(Acoeffs + Alen, Bcoeffs + i, k, num_cache) && fmpz_pow_cache_mulpow_ui(Acoeffs + Alen, Acoeffs + Alen, deg - k, den_cache); if (!success) break; if (fmpz_is_zero(Acoeffs + Alen)) continue; mpoly_monomial_msub(Aexps + N*Alen, Bexps + N*i, k, one, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fmpz_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen); Alen -= fmpz_is_zero(Acoeffs + Alen - 1); } /* from the fmpz_add: at most two junk coeffs past length */ for (i = Alen; i < Alen + 2 && i < A->zpoly->alloc; i++) _fmpz_demote(Acoeffs + i); _fmpz_mpoly_set_length(A->zpoly, Alen, ctx->zctx); TMP_END; if (success) { fmpz_set(fmpq_numref(A->content), fmpq_numref(B->content)); success = fmpz_pow_cache_mulpow_ui(fmpq_denref(A->content), fmpq_denref(B->content), deg, den_cache); fmpq_canonicalise(A->content); } else { fmpq_zero(A->content); } if (need_sort) { fmpz_mpoly_sort_terms(A->zpoly, ctx->zctx); fmpz_mpoly_combine_like_terms(A->zpoly, ctx->zctx); } fmpq_mpoly_reduce(A, ctx); FLINT_ASSERT(fmpq_mpoly_is_canonical(A, ctx)); return success; } /* exponents of B are multiprecision */ static int _fmpq_mpoly_evaluate_one_fmpq_mp( fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, fmpz_pow_cache_t num_cache, fmpz_pow_cache_t den_cache, const fmpz_t deg, const fmpq_mpoly_ctx_t ctx) { int success = 1; slong i, N, off; ulong * cmpmask, * one, * tmp; slong Blen = B->zpoly->length; const fmpz * Bcoeffs = B->zpoly->coeffs; const ulong * Bexps = B->zpoly->exps; flint_bitcnt_t bits = B->zpoly->bits; slong Alen; fmpz * Acoeffs; ulong * Aexps; fmpz_t k, degmk; int need_sort = 0, cmp; TMP_INIT; FLINT_ASSERT((bits % FLINT_BITS) == 0); TMP_START; fmpz_init(k); fmpz_init(degmk); if (A != B) fmpz_mpoly_fit_length_reset_bits(A->zpoly, Blen, bits, ctx->zctx); Acoeffs = A->zpoly->coeffs; Aexps = A->zpoly->exps; N = mpoly_words_per_exp(bits, ctx->zctx->minfo); one = (ulong *) TMP_ALLOC(3*N*sizeof(ulong)); cmpmask = one + N; tmp = cmpmask + N; off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->zctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->zctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexps + N*i + off, bits/FLINT_BITS); fmpz_sub(degmk, deg, k); success = fmpz_pow_cache_mulpow_fmpz(Acoeffs + Alen, Bcoeffs + i, k, num_cache) && fmpz_pow_cache_mulpow_fmpz(Acoeffs + Alen, Acoeffs + Alen, degmk, den_cache); if (!success) break; if (fmpz_is_zero(Acoeffs + Alen)) continue; mpoly_monomial_mul_fmpz(tmp, one, N, k); mpoly_monomial_sub_mp(Aexps + N*Alen, Bexps + N*i, tmp, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fmpz_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen); Alen -= fmpz_is_zero(Acoeffs + Alen - 1); } /* from the fmpz_add: at most two junk coeffs past length */ for (i = Alen; i < Alen + 2 && i < A->zpoly->alloc; i++) _fmpz_demote(Acoeffs + i); _fmpz_mpoly_set_length(A->zpoly, Alen, ctx->zctx); fmpz_clear(k); fmpz_clear(degmk); TMP_END; if (success) { fmpz_set(fmpq_numref(A->content), fmpq_numref(B->content)); success = fmpz_pow_cache_mulpow_fmpz(fmpq_denref(A->content), fmpq_denref(B->content), deg, den_cache); fmpq_canonicalise(A->content); } else { fmpq_zero(A->content); } if (need_sort) { fmpz_mpoly_sort_terms(A->zpoly, ctx->zctx); fmpz_mpoly_combine_like_terms(A->zpoly, ctx->zctx); } fmpq_mpoly_reduce(A, ctx); FLINT_ASSERT(fmpq_mpoly_is_canonical(A, ctx)); return success; } int fmpq_mpoly_evaluate_one_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_t val, const fmpq_mpoly_ctx_t ctx) { flint_bitcnt_t height; fmpz_pow_cache_t num_cache, den_cache; int success; if (B->zpoly->length == 0) { fmpq_mpoly_zero(A, ctx); return 1; } if (A == B) { int success; fmpq_mpoly_t T; fmpq_mpoly_init(T, ctx); success = fmpq_mpoly_evaluate_one_fmpq(T, B, var, val, ctx); fmpq_mpoly_swap(A, T, ctx); fmpq_mpoly_clear(T, ctx); return success; } fmpz_pow_cache_init(num_cache, fmpq_numref(val)); fmpz_pow_cache_init(den_cache, fmpq_denref(val)); height = fmpq_height_bits(val); if (B->zpoly->bits <= FLINT_BITS) { ulong deg = fmpq_mpoly_degree_si(B, var, ctx); success = (!_fmpz_pow_ui_is_not_feasible(height, deg)) && _fmpq_mpoly_evaluate_one_fmpq_sp(A, B, var, num_cache, den_cache, deg, ctx); } else { fmpz_t deg; fmpz_init(deg); fmpq_mpoly_degree_fmpz(deg, B, var, ctx); success = (!_fmpz_pow_fmpz_is_not_feasible(height, deg)) && _fmpq_mpoly_evaluate_one_fmpq_mp(A, B, var, num_cache, den_cache, deg, ctx); fmpz_clear(deg); } fmpz_pow_cache_clear(num_cache); fmpz_pow_cache_clear(den_cache); return success; } flint-3.1.3/src/fmpq_mpoly/gcd.c000066400000000000000000000030131461254215100165030ustar00rootroot00000000000000/* Copyright (C) 2018,2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" static void _make_monic(fmpq_mpoly_t G) { if (G->zpoly->length > 0) { fmpz_one(fmpq_numref(G->content)); fmpz_set(fmpq_denref(G->content), G->zpoly->coeffs + 0); } else { fmpq_zero(G->content); } } #define FMPQ_MPOLY_GCD_EXT(ext) \ int fmpq_mpoly_##ext(fmpq_mpoly_t G, const fmpq_mpoly_t A, \ const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) \ { \ int success; \ success = fmpz_mpoly_##ext(G->zpoly, A->zpoly, B->zpoly, ctx->zctx); \ if (success) \ _make_monic(G); \ return success; \ } FMPQ_MPOLY_GCD_EXT(gcd) FMPQ_MPOLY_GCD_EXT(gcd_brown) FMPQ_MPOLY_GCD_EXT(gcd_hensel) FMPQ_MPOLY_GCD_EXT(gcd_subresultant) FMPQ_MPOLY_GCD_EXT(gcd_zippel) FMPQ_MPOLY_GCD_EXT(gcd_zippel2) flint-3.1.3/src/fmpq_mpoly/gcd_cofactors.c000066400000000000000000000025421461254215100205540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_gcd_cofactors(fmpq_mpoly_t G, fmpq_mpoly_t Abar, fmpq_mpoly_t Bbar, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { fmpq_t cAbar, cBbar; int success; success = fmpz_mpoly_gcd_cofactors(G->zpoly, Abar->zpoly, Bbar->zpoly, A->zpoly, B->zpoly, ctx->zctx); if (!success) return 0; fmpq_init(cAbar); fmpq_init(cBbar); if (G->zpoly->length > 0) { fmpq_mul_fmpz(cAbar, A->content, G->zpoly->coeffs + 0); fmpq_mul_fmpz(cBbar, B->content, G->zpoly->coeffs + 0); fmpz_set(fmpq_denref(G->content), G->zpoly->coeffs + 0); fmpz_one(fmpq_numref(G->content)); } else { fmpq_zero(G->content); } fmpq_swap(Abar->content, cAbar); fmpq_swap(Bbar->content, cBbar); fmpq_clear(cAbar); fmpq_clear(cBbar); return 1; } flint-3.1.3/src/fmpq_mpoly/get_coeff_fmpq_fmpz.c000066400000000000000000000041001461254215100217440ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void _fmpq_mpoly_get_coeff_fmpq_fmpz(fmpq_t c, const fmpq_mpoly_t qpoly, const fmpz * exp, const fmpq_mpoly_ctx_t qctx) { slong N, index, exp_bits; ulong * cmpmask, * packed_exp; int exists; const fmpz_mpoly_struct * poly = qpoly->zpoly; const fmpz_mpoly_ctx_struct * ctx = qctx->zctx; TMP_INIT; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); if (exp_bits > poly->bits) /* exponent too large to be poly exponent */ { fmpq_zero(c); return; } TMP_START; N = mpoly_words_per_exp(poly->bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, poly->bits, ctx->minfo); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, poly->bits, ctx->minfo); exists = mpoly_monomial_exists(&index, poly->exps, packed_exp, poly->length, N, cmpmask); if (!exists) { fmpq_zero(c); } else { fmpq_mul_fmpz(c, qpoly->content, poly->coeffs + index); } TMP_END; } void fmpq_mpoly_get_coeff_fmpq_fmpz(fmpq_t c, const fmpq_mpoly_t poly, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { slong i, nvars = ctx->zctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_init(newexp + i); fmpz_set(newexp + i, exp[i]); } _fmpq_mpoly_get_coeff_fmpq_fmpz(c, poly, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fmpq_mpoly/get_coeff_fmpq_monomial.c000066400000000000000000000014131461254215100226070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_get_coeff_fmpq_monomial(fmpq_t c, const fmpq_mpoly_t poly1, const fmpq_mpoly_t poly2, const fmpq_mpoly_ctx_t ctx) { fmpz_one(fmpq_denref(c)); fmpz_mpoly_get_coeff_fmpz_monomial(fmpq_numref(c), poly1->zpoly, poly2->zpoly, ctx->zctx); fmpq_mul(c, c, poly1->content); } flint-3.1.3/src/fmpq_mpoly/get_coeff_fmpq_ui.c000066400000000000000000000016331461254215100214150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_get_coeff_fmpq_ui(fmpq_t c, const fmpq_mpoly_t poly, const ulong * exp, const fmpq_mpoly_ctx_t ctx) { slong i, nvars = ctx->zctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); _fmpq_mpoly_get_coeff_fmpq_fmpz(c, poly, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fmpq_mpoly/get_coeff_vars_ui.c000066400000000000000000000014331461254215100214230ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_get_coeff_vars_ui(fmpq_mpoly_t C, const fmpq_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_get_coeff_vars_ui(C->zpoly, A->zpoly, vars, exps, length, ctx->zctx); fmpq_set(C->content, A->content); fmpq_mpoly_reduce(C, ctx); } flint-3.1.3/src/fmpq_mpoly/get_fmpq.c000066400000000000000000000013631461254215100175560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_get_fmpq(fmpq_t c, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { /* the easiest way to throw is to call fmpz_mpoly_get_fmpz */ fmpz_one(fmpq_denref(c)); fmpz_mpoly_get_fmpz(fmpq_numref(c), A->zpoly, ctx->zctx); /* either 0 or 1 */ fmpq_mul(c, c, A->content); } flint-3.1.3/src/fmpq_mpoly/get_set_is_fmpq_poly.c000066400000000000000000000031341461254215100221650ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpq_poly.h" #include "mpoly.h" #include "fmpq_mpoly.h" int fmpq_mpoly_is_fmpq_poly( const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx) { return fmpz_mpoly_is_fmpz_poly(A->zpoly, var, ctx->zctx); } int fmpq_mpoly_get_fmpq_poly( fmpq_poly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx) { int success; fmpz_poly_t a; fmpz_poly_init(a); success = fmpz_mpoly_get_fmpz_poly(a, B->zpoly, var, ctx->zctx); if (success) { fmpq_poly_set_fmpz_poly(A, a); fmpq_poly_scalar_mul_fmpq(A, A, B->content); } fmpz_poly_clear(a); return success; } void fmpq_mpoly_set_fmpq_poly( fmpq_mpoly_t A, const fmpq_poly_t B, slong v, const fmpq_mpoly_ctx_t ctx) { flint_bitcnt_t bits; if (B->length < 1) { fmpq_mpoly_zero(A, ctx); return; } bits = mpoly_gen_pow_exp_bits_required(v, B->length - 1, ctx->zctx->minfo); bits = mpoly_fix_bits(bits, ctx->zctx->minfo); _fmpz_mpoly_set_fmpz_poly(A->zpoly, bits, B->coeffs, B->length, v, ctx->zctx); fmpz_one(fmpq_numref(A->content)); fmpz_set(fmpq_denref(A->content), B->den); fmpq_mpoly_reduce(A, ctx); } flint-3.1.3/src/fmpq_mpoly/get_str_pretty.c000066400000000000000000000067051461254215100210370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" #define ALLOC_PER_VAR ((FLINT_BITS+4)/3) char * fmpq_mpoly_get_str_pretty(const fmpq_mpoly_t A, const char ** x_in, const fmpq_mpoly_ctx_t qctx) { fmpq_t c; slong i, j, N, bound, off; fmpz * exponents; const fmpz_mpoly_struct * poly = A->zpoly; const mpoly_ctx_struct * mctx = qctx->zctx->minfo; char ** x = (char **) x_in, *xtmp; slong len = A->zpoly->length; flint_bitcnt_t bits = A->zpoly->bits; char * str; TMP_INIT; if (poly->length == 0) { str = (char *) flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } N = mpoly_words_per_exp(poly->bits, mctx); TMP_START; fmpq_init(c); if (x == NULL) { xtmp = (char *) TMP_ALLOC(mctx->nvars * ALLOC_PER_VAR * sizeof(char)); x = (char **) TMP_ALLOC(mctx->nvars*sizeof(char *)); for (i = 0; i < mctx->nvars; i++) { x[i] = xtmp + i * ALLOC_PER_VAR; flint_sprintf(x[i], "x%wd", i + 1); } } bound = 1; for (i = 0; i < len; i++) { fmpq_mul_fmpz(c, A->content, poly->coeffs + i); bound += fmpz_sizeinbase(fmpq_numref(c), 10); bound += fmpz_sizeinbase(fmpq_denref(c), 10); bound += 4; } exponents = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(ulong)); for (i = 0; i < mctx->nvars; i++) fmpz_init(exponents + i); mpoly_degrees_ffmpz((fmpz *) exponents, poly->exps, len, bits, mctx); for (i = 0; i < mctx->nvars; i++) bound += (fmpz_sizeinbase(exponents + i, 10) + strlen(x[i]) + 3)*len; str = flint_malloc(bound); off = 0; for (i = 0; i < len; i++) { int first = 1; fmpq_mul_fmpz(c, A->content, poly->coeffs + i); off += flint_sprintf(str + off, "%s", (fmpq_sgn(c) >= 0) ? (i > 0 ? " + " : "") : (i > 0 ? " - " : "-") ); fmpq_abs(c, c); if (!fmpq_is_one(c)) { first = 0; fmpq_get_str(str + off, 10, c); while (str[off]) off++; } mpoly_get_monomial_ffmpz(exponents, poly->exps + N*i, bits, mctx); for (j = 0; j < mctx->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, UWORD(1)); if (cmp < 0) continue; if (!first) str[off++] = '*'; off += flint_sprintf(str + off, "%s", x[j]); if (cmp > 0) { str[off++] = '^'; if (!COEFF_IS_MPZ(exponents[j])) off += flint_sprintf(str + off, "%wd", exponents[j]); else off += gmp_sprintf(str + off, "%Zd", COEFF_TO_PTR(exponents[j])); } first = 0; } if (first) str[off++] = '1'; } fmpq_clear(c); for (i = 0; i < mctx->nvars; i++) fmpz_clear(exponents + i); TMP_END; str[off] = '\0'; return str; } flint-3.1.3/src/fmpq_mpoly/get_term.c000066400000000000000000000022351461254215100175610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void fmpq_mpoly_get_term(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t bits = A->zpoly->bits; if ((ulong) i >= (ulong) A->zpoly->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpq_mpoly_get_term"); } fmpz_mpoly_fit_length(M->zpoly, WORD(1), ctx->zctx); fmpz_mpoly_fit_bits(M->zpoly, bits, ctx->zctx); M->zpoly->bits = bits; N = mpoly_words_per_exp(bits, ctx->zctx->minfo); mpoly_monomial_set(M->zpoly->exps + N*0, A->zpoly->exps + N*i, N); fmpq_mul_fmpz(M->content, A->content, A->zpoly->coeffs + i); fmpz_one(M->zpoly->coeffs + 0); _fmpz_mpoly_set_length(M->zpoly, 1, ctx->zctx); } flint-3.1.3/src/fmpq_mpoly/get_term_coeff_fmpq.c000066400000000000000000000013771461254215100217540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_get_term_coeff_fmpq(fmpq_t c, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) fmpq_mpoly_length(A, ctx)) { flint_throw(FLINT_ERROR, "index out of range in fmpq_mpoly_get_coeff_fmpq"); } fmpq_mul_fmpz(c, A->content, A->zpoly->coeffs + i); } flint-3.1.3/src/fmpq_mpoly/get_term_exp_fmpz.c000066400000000000000000000017231461254215100214720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void fmpq_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->zpoly->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term_exp_fmpz"); } N = mpoly_words_per_exp(A->zpoly->bits, ctx->zctx->minfo); mpoly_get_monomial_pfmpz(exp, A->zpoly->exps + N*i, A->zpoly->bits, ctx->zctx->minfo); } flint-3.1.3/src/fmpq_mpoly/get_term_exp_si.c000066400000000000000000000017161461254215100211330ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void fmpq_mpoly_get_term_exp_si(slong * exp, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->zpoly->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpq_mpoly_get_term_exp_si"); } N = mpoly_words_per_exp(A->zpoly->bits, ctx->zctx->minfo); mpoly_get_monomial_si(exp, A->zpoly->exps + N*i, A->zpoly->bits, ctx->zctx->minfo); } flint-3.1.3/src/fmpq_mpoly/get_term_exp_ui.c000066400000000000000000000017161461254215100211350ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void fmpq_mpoly_get_term_exp_ui(ulong * exp, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->zpoly->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpq_mpoly_get_term_exp_ui"); } N = mpoly_words_per_exp(A->zpoly->bits, ctx->zctx->minfo); mpoly_get_monomial_ui(exp, A->zpoly->exps + N*i, A->zpoly->bits, ctx->zctx->minfo); } flint-3.1.3/src/fmpq_mpoly/get_term_monomial.c000066400000000000000000000022101461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void fmpq_mpoly_get_term_monomial(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t bits = A->zpoly->bits; if ((ulong) i >= (ulong) A->zpoly->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpq_mpoly_get_term_monomial"); } fmpz_mpoly_fit_length(M->zpoly, WORD(1), ctx->zctx); fmpz_mpoly_fit_bits(M->zpoly, bits, ctx->zctx); M->zpoly->bits = bits; N = mpoly_words_per_exp(bits, ctx->zctx->minfo); mpoly_monomial_set(M->zpoly->exps + N*0, A->zpoly->exps + N*i, N); fmpz_one(M->zpoly->coeffs + 0); _fmpz_mpoly_set_length(M->zpoly, 1, ctx->zctx); fmpq_one(M->content); } flint-3.1.3/src/fmpq_mpoly/get_term_var_exp_si.c000066400000000000000000000017161461254215100220030ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" slong fmpq_mpoly_get_term_var_exp_si(const fmpq_mpoly_t A, slong i, slong var, const fmpq_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->zpoly->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpq_mpoly_get_term_var_exp_si"); } N = mpoly_words_per_exp(A->zpoly->bits, ctx->zctx->minfo); return mpoly_get_monomial_var_exp_si(A->zpoly->exps + N*i, var, A->zpoly->bits, ctx->zctx->minfo); } flint-3.1.3/src/fmpq_mpoly/get_term_var_exp_ui.c000066400000000000000000000017161461254215100220050ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" ulong fmpq_mpoly_get_term_var_exp_ui(const fmpq_mpoly_t A, slong i, slong var, const fmpq_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->zpoly->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpq_mpoly_get_term_var_exp_ui"); } N = mpoly_words_per_exp(A->zpoly->bits, ctx->zctx->minfo); return mpoly_get_monomial_var_exp_ui(A->zpoly->exps + N*i, var, A->zpoly->bits, ctx->zctx->minfo); } flint-3.1.3/src/fmpq_mpoly/inflate.c000066400000000000000000000012621461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_inflate(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_inflate(A->zpoly, A->zpoly, shift, stride, ctx->zctx); fmpq_set(A->content, B->content); fmpq_mpoly_reduce(A, ctx); } flint-3.1.3/src/fmpq_mpoly/inlines.c000066400000000000000000000006621461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPQ_MPOLY_INLINES_C #include "fmpq_mpoly.h" flint-3.1.3/src/fmpq_mpoly/integral.c000066400000000000000000000014051461254215100175560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_integral(fmpq_mpoly_t poly1, const fmpq_mpoly_t poly2, slong var, const fmpq_mpoly_ctx_t ctx) { fmpz_t s; fmpz_init(s); fmpz_mpoly_integral(poly1->zpoly, s, poly2->zpoly, var, ctx->zctx); fmpq_div_fmpz(poly1->content, poly2->content, s); fmpq_mpoly_reduce(poly1, ctx); fmpz_clear(s); } flint-3.1.3/src/fmpq_mpoly/io.c000066400000000000000000000061771461254215100163730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "mpoly.h" #include "fmpq_mpoly.h" /* printing *******************************************************************/ int fmpq_mpoly_fprint_pretty(FILE * file, const fmpq_mpoly_t A, const char ** x_in, const fmpq_mpoly_ctx_t qctx) { int r = 0; fmpq_t c; slong i, j, N; fmpz * exponents; const fmpz_mpoly_struct * poly = A->zpoly; const mpoly_ctx_struct * mctx = qctx->zctx->minfo; char ** x = (char **) x_in; TMP_INIT; TMP_START; fmpq_init(c); N = mpoly_words_per_exp(poly->bits, mctx); exponents = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(exponents + i); r = 0; if (poly->length == 0) { r = fputc('0', file); goto cleanup; } if (x == NULL) { x = (char **) TMP_ALLOC(mctx->nvars*sizeof(char *)); for (i = 0; i < mctx->nvars; i++) { x[i] = (char *) TMP_ALLOC(22*sizeof(char)); flint_sprintf(x[i], "x%wd", i + 1); } } for (i = 0; i < poly->length; i++) { int first = 1; fmpq_mul_fmpz(c, A->content, poly->coeffs + i); r = flint_fprintf(file, (fmpq_sgn(c) >= 0) ? (i > 0 ? " + " : "") : (i > 0 ? " - " : "-") ); fmpq_abs(c, c); if (!fmpq_is_one(c)) { first = 0; fmpq_fprint(file, c); } mpoly_get_monomial_ffmpz(exponents, poly->exps + N*i, poly->bits, mctx); for (j = 0; j < mctx->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, UWORD(1)); if (cmp < 0) continue; if (!first) { r = fputc('*', file); } r = flint_fprintf(file, "%s", x[j]); if (cmp > 0) { r = fputc('^', file); r = fmpz_fprint(file, exponents + j); } first = 0; } if (first) { r = flint_fprintf(file, "1"); } } cleanup: for (i = 0; i < mctx->nvars; i++) fmpz_clear(exponents + i); fmpq_clear(c); TMP_END; return r; } int fmpq_mpoly_print_pretty(const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx) { return fmpq_mpoly_fprint_pretty(stdout, A, x, ctx); } /* debugging ******************************************************************/ /* test that r is a valid remainder upon division by g over Q this means that no term of r is divisible by lt(g) */ void fmpq_mpoly_remainder_test(const fmpq_mpoly_t r, const fmpq_mpoly_t g, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_remainder_strongtest(r->zpoly, g->zpoly, ctx->zctx); } flint-3.1.3/src/fmpq_mpoly/is_canonical.c000066400000000000000000000037031461254215100203760ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_mpoly.h" int fmpq_mpoly_is_canonical(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_t g; int ret; if (!fmpq_is_canonical(A->content)) return 0; if (!fmpz_mpoly_is_canonical(A->zpoly, ctx->zctx)) return 0; if (fmpq_is_zero(A->content)) return A->zpoly->length == 0; if (A->zpoly->length == 0) return !!fmpq_is_zero(A->content); if (fmpz_sgn(A->zpoly->coeffs + 0) <= 0) return 0; fmpz_init(g); _fmpz_vec_content(g, A->zpoly->coeffs, A->zpoly->length); ret = fmpz_is_one(g); fmpz_clear(g); return ret; } void fmpq_mpoly_assert_canonical(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_t g; if (!fmpq_is_canonical(A->content)) flint_throw(FLINT_ERROR, "Polynomial content is not canonical"); fmpz_mpoly_assert_canonical(A->zpoly, ctx->zctx); if (fmpq_is_zero(A->content)) { if (A->zpoly->length != 0) flint_throw(FLINT_ERROR, "Polynomial content is zero but zpoly is not"); return; } if (A->zpoly->length == 0) { if (!fmpq_is_zero(A->content)) flint_throw(FLINT_ERROR, "Polynomial zpoly is zero but content is not"); return; } if (fmpz_sgn(A->zpoly->coeffs + 0) <= 0) flint_throw(FLINT_ERROR, "Polynomial zpoly has negative leading coefficient"); fmpz_init(g); _fmpz_vec_content(g, A->zpoly->coeffs, A->zpoly->length); if (!fmpz_is_one(g)) flint_throw(FLINT_ERROR, "Polynomial zpoly has content"); fmpz_clear(g); } flint-3.1.3/src/fmpq_mpoly/is_monic.c000066400000000000000000000015511461254215100175530ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_is_monic(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { int res; fmpz_t t; if (A->zpoly->length < 1) return 0; if (fmpz_is_one(fmpq_numref(A->content)) && fmpz_equal(fmpq_denref(A->content), A->zpoly->coeffs + 0)) { return 1; } fmpz_init(t); fmpz_mul(t, fmpq_numref(A->content), A->zpoly->coeffs + 0); res = fmpz_equal(t, fmpq_denref(A->content)); fmpz_clear(t); return res; } flint-3.1.3/src/fmpq_mpoly/make_monic.c000066400000000000000000000022361461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_make_monic(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx) { if (B->zpoly->length == 0) { flint_throw(FLINT_ERROR, "Zero polynomial in fmpq_mpoly_make_monic"); } fmpz_one(fmpq_numref(A->content)); fmpz_set(fmpq_denref(A->content), B->zpoly->coeffs + 0); if (A != B) { fmpz_mpoly_set(A->zpoly, B->zpoly, ctx->zctx); } } /* this version must ignore A->content */ void _fmpq_mpoly_make_monic_inplace(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT(A->zpoly->length > 0); FLINT_ASSERT(fmpz_sgn(A->zpoly->coeffs + 0) > 0); fmpz_one(fmpq_numref(A->content)); fmpz_set(fmpq_denref(A->content), A->zpoly->coeffs + 0); } flint-3.1.3/src/fmpq_mpoly/mul.c000066400000000000000000000014231461254215100165460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_mul(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx) { if (fmpq_mpoly_is_zero(B, ctx) || fmpq_mpoly_is_zero(C, ctx)) { fmpq_mpoly_zero(A, ctx); return; } fmpq_mul(A->content, B->content, C->content); fmpz_mpoly_mul(A->zpoly, B->zpoly, C->zpoly, ctx->zctx); } flint-3.1.3/src/fmpq_mpoly/pow_fmpz.c000066400000000000000000000013261461254215100176140ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_pow_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t k, const fmpq_mpoly_ctx_t ctx) { int success; success = fmpq_pow_fmpz(A->content, B->content, k); success = success && fmpz_mpoly_pow_fmpz(A->zpoly, B->zpoly, k, ctx->zctx); return success; } flint-3.1.3/src/fmpq_mpoly/pow_ui.c000066400000000000000000000024041461254215100172530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_pow_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong k, const fmpq_mpoly_ctx_t ctx) { slong success; /* we have to work around the fact that there is no fmpq_pow_ui */ if (k <= WORD_MAX) { fmpq_pow_si(A->content, B->content, k); success = 1; } else if (fmpq_is_zero(B->content)) { fmpq_mpoly_zero(A, ctx); return 1; } else { if (!fmpq_is_pm1(B->content)) { success = 0; } else { fmpz_set_si(fmpq_numref(A->content), (k % UWORD(2)) == 0 || fmpq_is_one(B->content) ? 1 : -1); fmpz_one(fmpq_denref(A->content)); success = 1; } } success = success && fmpz_mpoly_pow_ui(A->zpoly, B->zpoly, k, ctx->zctx); return success; } flint-3.1.3/src/fmpq_mpoly/push_term_fmpq_fmpz.c000066400000000000000000000074351461254215100220470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_push_term_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set(fmpq_numref(C), fmpq_numref(c)); fmpz_init_set(fmpq_denref(C), fmpq_denref(c)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_pfmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_fmpq_ffmpz(fmpq_mpoly_t A, const fmpq_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set(fmpq_numref(C), fmpq_numref(c)); fmpz_init_set(fmpq_denref(C), fmpq_denref(c)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_pfmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_fmpz_ffmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpz *exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, ulong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set_ui(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_pfmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_ui_ffmpz(fmpq_mpoly_t A, ulong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set_ui(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, slong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set_si(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_pfmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_si_ffmpz(fmpq_mpoly_t A, slong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set_si(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } flint-3.1.3/src/fmpq_mpoly/push_term_fmpq_ui.c000066400000000000000000000056031461254215100215030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_mpoly.h" void _fmpq_mpoly_push_rescale(fmpq_mpoly_t A, fmpq_t C, const fmpq_mpoly_ctx_t ctx) { fmpz_mpoly_struct * Z = A->zpoly; if (!fmpz_is_one(fmpq_numref(A->content))) { _fmpz_vec_scalar_mul_fmpz(Z->coeffs, Z->coeffs, Z->length, fmpq_numref(A->content)); fmpz_one(fmpq_numref(A->content)); } fmpq_mul_fmpz(C, C, fmpq_denref(A->content)); if (!fmpz_is_one(fmpq_denref(C))) { _fmpz_vec_scalar_mul_fmpz(Z->coeffs, Z->coeffs, Z->length, fmpq_denref(C)); fmpz_mul(fmpq_denref(A->content), fmpq_denref(A->content), fmpq_denref(C)); } } void fmpq_mpoly_push_term_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set(fmpq_numref(C), fmpq_numref(c)); fmpz_init_set(fmpq_denref(C), fmpq_denref(c)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ui(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_fmpz_ui(fmpq_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ui(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_ui_ui(fmpq_mpoly_t A, ulong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set_ui(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ui(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } void fmpq_mpoly_push_term_si_ui(fmpq_mpoly_t A, slong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) { fmpq_t C; fmpz_init_set_si(fmpq_numref(C), c); fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); _fmpq_mpoly_push_rescale(A, C, ctx); _fmpz_mpoly_push_exp_ui(A->zpoly, exp, ctx->zctx); fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } flint-3.1.3/src/fmpq_mpoly/reduce.c000066400000000000000000000032441461254215100172230ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_mpoly.h" /* We are supposed to produce a canonical A assuming that A->zpoly is itself canonical. The code should not break if A->zpoly is not canonical. */ void fmpq_mpoly_reduce(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_t g; if (A->zpoly->length < 1) { fmpq_zero(A->content); return; } else if (fmpq_is_zero(A->content)) { fmpz_mpoly_zero(A->zpoly, ctx->zctx); return; } /* A is nonzero at this point (assuming A->zpoly is canonical) */ fmpz_init(g); _fmpz_vec_content(g, A->zpoly->coeffs, A->zpoly->length); if (fmpz_sgn(A->zpoly->coeffs + 0) < 0) fmpz_neg(g, g); if (fmpz_is_zero(g)) { /* bail if A->zpoly has only zeros stored (A->zpoly not canonical) */ fmpq_one(A->content); } else if (fmpz_is_pm1(g)) { if (!fmpz_is_one(g)) { fmpq_neg(A->content, A->content); _fmpz_vec_neg(A->zpoly->coeffs, A->zpoly->coeffs, A->zpoly->length); } } else { fmpq_mul_fmpz(A->content, A->content, g); _fmpz_vec_scalar_divexact_fmpz(A->zpoly->coeffs, A->zpoly->coeffs, A->zpoly->length, g); } fmpz_clear(g); } flint-3.1.3/src/fmpq_mpoly/reduce_easy.c000066400000000000000000000020061461254215100202370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_mpoly.h" /* don't do too much work if length(A) matches easy_length */ void fmpq_mpoly_reduce_easy( fmpq_mpoly_t A, slong easy_length, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT(easy_length > 0); FLINT_ASSERT(A->zpoly->length <= easy_length); if (A->zpoly->length != easy_length) { fmpq_mpoly_reduce(A, ctx); } else if (fmpz_sgn(A->zpoly->coeffs + 0) < 0) { fmpz_neg(fmpq_numref(A->content), fmpq_numref(A->content)); _fmpz_vec_neg(A->zpoly->coeffs, A->zpoly->coeffs, A->zpoly->length); } FLINT_ASSERT(fmpq_mpoly_is_canonical(A, ctx)); } flint-3.1.3/src/fmpq_mpoly/repack_bits.c000066400000000000000000000013501461254215100202360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_repack_bits(fmpq_mpoly_t A, const fmpq_mpoly_t B, flint_bitcnt_t Abits, const fmpq_mpoly_ctx_t ctx) { int success; success = fmpz_mpoly_repack_bits(A->zpoly, B->zpoly, Abits, ctx->zctx); if (success) { fmpq_set(A->content, B->content); } return success; } flint-3.1.3/src/fmpq_mpoly/rescale.c000066400000000000000000000151141461254215100173710ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpq_mpoly.h" static void _fmpz_binpow_fmpz(fmpz_t a, const fmpz * p, const fmpz_t e) { ulong i; flint_bitcnt_t bits = fmpz_bits(e); fmpz_one(a); for (i = 0; i < bits; i++) { if (fmpz_tstbit(e, i)) { fmpz_mul(a, a, p + 2*i); } } } /* scales+0 scales+n-1 -------- e1 en \ (a1 ) (an ) \ c * (-- * x1) * ... * (-- * x_n) / (b1 ) (bn ) / -------- c, e let fi and di be the min and max exponents of xi rewrite as integer polynomial -------- \ e1-f1 d1-e1 en-f1 dn-en e1 en \ c * a1 * b1 * ... * an * bn * x1 * ... * xn / / -------- c, e times f1 fn a1 an ---- * ... * ---- d1 dn b1 bn */ int _fmpq_mpoly_rescale(fmpq_t Acontent, fmpz * Acoeff, const fmpq_mpoly_t B, const fmpq * scales, const fmpq_mpoly_ctx_t ctx) { int success = 1; slong i, j, v; slong nvars, N; slong Blen; fmpz * Bcoeff; ulong * Bexp; fmpz * Buexp; flint_bitcnt_t Bbits, tbits; fmpz * emin; fmpz * emax; fmpz ** powertable; fmpz * lastexp; fmpz * lastpow; fmpz_t t, s, u; fmpq_t q; TMP_INIT; TMP_START; fmpz_init(t); fmpz_init(s); fmpz_init(u); fmpq_init(q); nvars = ctx->zctx->minfo->nvars; Blen = B->zpoly->length; Bcoeff = B->zpoly->coeffs; Bexp = B->zpoly->exps; Bbits = B->zpoly->bits; FLINT_ASSERT(Blen > 0); N = mpoly_words_per_exp(Bbits, ctx->zctx->minfo); Buexp = _fmpz_vec_init(nvars*Blen); i = 0; mpoly_get_monomial_ffmpz(Buexp + nvars*i, Bexp + N*i, Bbits, ctx->zctx->minfo); emin = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); emax = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (v = 0; v < nvars; v++) { fmpz_init_set(emin + v, Buexp + nvars*i + v); fmpz_init_set(emax + v, Buexp + nvars*i + v); } for (i = 1; i < Blen; i++) { mpoly_get_monomial_ffmpz(Buexp + nvars*i, Bexp + N*i, Bbits, ctx->zctx->minfo); for (v = 0; v < nvars; v++) { if (fmpz_cmp(emin + v, Buexp + nvars*i + v) > 0) fmpz_set(emin + v, Buexp + nvars*i + v); if (fmpz_cmp(emax + v, Buexp + nvars*i + v) < 0) fmpz_set(emax + v, Buexp + nvars*i + v); } } /* check that the powers in the powertable loop do not get too big */ for (v = 0; v < nvars; v++) { if (_fmpz_pow_fmpz_is_not_feasible(fmpq_height_bits(scales + v), emax + v)) { success = 0; goto cleanup_exp_bounds; } } powertable = (fmpz **) TMP_ALLOC(nvars*sizeof(fmpz *)); for (v = 0; v < nvars; v++) { fmpz * row; tbits = fmpz_bits(emax + v); tbits = FLINT_MAX(UWORD(1), tbits); row = (fmpz *) flint_malloc(2*tbits*sizeof(fmpz)); powertable[v] = row; j = 0; fmpz_init_set(row + 2*j + 0, fmpq_numref(scales + v)); fmpz_init_set(row + 2*j + 1, fmpq_denref(scales + v)); for (j = 1; j < tbits; j++) { fmpz_init(row + 2*j + 0); fmpz_init(row + 2*j + 1); fmpz_mul(row + 2*j + 0, row + 2*j - 2, row + 2*j - 2); fmpz_mul(row + 2*j + 1, row + 2*j - 1, row + 2*j - 1); } } lastexp = (fmpz *) TMP_ALLOC(2*nvars*sizeof(fmpz)); lastpow = (fmpz *) TMP_ALLOC(2*nvars*sizeof(fmpz)); for (v = 0; v < nvars; v++) { fmpz_init_set_ui(lastexp + 2*v + 0, 0); fmpz_init_set_ui(lastpow + 2*v + 0, 1); fmpz_init_set_ui(lastexp + 2*v + 1, 0); fmpz_init_set_ui(lastpow + 2*v + 1, 1); } fmpq_set(Acontent, B->content); for (v = 0; v < nvars; v++) { _fmpz_binpow_fmpz(fmpq_numref(q), powertable[v] + 0, emin + v); _fmpz_binpow_fmpz(fmpq_denref(q), powertable[v] + 1, emax + v); fmpq_mul(Acontent, Acontent, q); } for (i = 0; i < Blen; i++) { fmpz_set(Acoeff + i, Bcoeff + i); for (v = 0; v < nvars; v++) { /* power numerator of vth scale */ fmpz_sub(t, Buexp + nvars*i + v, emin + v); FLINT_ASSERT(fmpz_sgn(t) >= 0); fmpz_sub(s, t, lastexp + 2*v + 0); if (fmpz_sgn(s) >= 0) { _fmpz_binpow_fmpz(u, powertable[v] + 0, s); fmpz_mul(lastpow + 2*v + 0, lastpow + 2*v + 0, u); } else { _fmpz_binpow_fmpz(lastpow + 2*v + 0, powertable[v] + 0, t); } fmpz_swap(lastexp + 2*v + 0, t); fmpz_mul(Acoeff + i, Acoeff + i, lastpow + 2*v + 0); /* power denominator of vth scale */ fmpz_sub(t, emax + v, Buexp + nvars*i + v); FLINT_ASSERT(fmpz_sgn(t) >= 0); fmpz_sub(s, t, lastexp + 2*v + 1); if (fmpz_sgn(s) >= 0) { _fmpz_binpow_fmpz(u, powertable[v] + 1, s); fmpz_mul(lastpow + 2*v + 1, lastpow + 2*v + 1, u); } else { _fmpz_binpow_fmpz(lastpow + 2*v + 1, powertable[v] + 1, t); } fmpz_swap(lastexp + 2*v + 1, t); fmpz_mul(Acoeff + i, Acoeff + i, lastpow + 2*v + 1); } } /* clean up */ for (v = 0; v < nvars; v++) { fmpz_clear(lastexp + 2*v + 0); fmpz_clear(lastpow + 2*v + 0); fmpz_clear(lastexp + 2*v + 1); fmpz_clear(lastpow + 2*v + 1); } for (v = 0; v < nvars; v++) { tbits = fmpz_bits(emax + v); tbits = FLINT_MAX(UWORD(1), tbits); for (j = 0; j < tbits; j++) { fmpz_clear(powertable[v] + 2*j + 0); fmpz_clear(powertable[v] + 2*j + 1); } flint_free(powertable[v]); } cleanup_exp_bounds: for (v = 0; v < nvars; v++) { fmpz_clear(emin + v); fmpz_clear(emax + v); } _fmpz_vec_clear(Buexp, nvars*Blen); fmpz_clear(t); fmpz_clear(s); fmpz_clear(u); fmpq_clear(q); TMP_END; return success; } flint-3.1.3/src/fmpq_mpoly/resultant.c000066400000000000000000000025641461254215100200010ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_resultant(fmpq_mpoly_t R, const fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx) { int success; fmpz_mpoly_univar_t Ax, Bx; fmpz_mpoly_univar_init(Ax, ctx->zctx); fmpz_mpoly_univar_init(Bx, ctx->zctx); fmpz_mpoly_to_univar(Ax, A->zpoly, var, ctx->zctx); fmpz_mpoly_to_univar(Bx, B->zpoly, var, ctx->zctx); success = fmpz_mpoly_univar_resultant(R->zpoly, Ax, Bx, ctx->zctx); if (success && Ax->length > 0 && Bx->length > 0) { fmpq_t t; fmpq_init(t); success = fmpq_pow_fmpz(t, A->content, Bx->exps + 0) && fmpq_pow_fmpz(R->content, B->content, Ax->exps + 0); if (success) fmpq_mul(R->content, R->content, t); fmpq_clear(t); } else { fmpq_zero(R->content); } fmpq_mpoly_reduce(R, ctx); fmpz_mpoly_univar_clear(Ax, ctx->zctx); fmpz_mpoly_univar_clear(Bx, ctx->zctx); return success; } flint-3.1.3/src/fmpq_mpoly/scalar_div_fmpq.c000066400000000000000000000011651461254215100211060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_scalar_div_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) { fmpq_div(A->content, B->content, c); fmpz_mpoly_set(A->zpoly, B->zpoly, ctx->zctx); } flint-3.1.3/src/fmpq_mpoly/scalar_div_fmpz.c000066400000000000000000000021431461254215100211140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_scalar_div_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) { fmpq_div_fmpz(A->content, B->content, c); fmpz_mpoly_set(A->zpoly, B->zpoly, ctx->zctx); } void fmpq_mpoly_scalar_div_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init_set_ui(C, c); fmpq_mpoly_scalar_div_fmpz(A, B, C, ctx); fmpz_clear(C); } void fmpq_mpoly_scalar_div_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init(C); fmpz_set_si(C, c); fmpq_mpoly_scalar_div_fmpz(A, B, C, ctx); fmpz_clear(C); } flint-3.1.3/src/fmpq_mpoly/scalar_mul_fmpq.c000066400000000000000000000013521461254215100211170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_scalar_mul_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) { fmpq_mul(A->content, B->content, c); if (fmpq_is_zero(A->content)) { fmpz_mpoly_zero(A->zpoly, ctx->zctx); } else { fmpz_mpoly_set(A->zpoly, B->zpoly, ctx->zctx); } } flint-3.1.3/src/fmpq_mpoly/scalar_mul_fmpz.c000066400000000000000000000023301461254215100211250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_scalar_mul_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) { fmpq_mul_fmpz(A->content, B->content, c); if (fmpq_is_zero(A->content)) { fmpz_mpoly_zero(A->zpoly, ctx->zctx); } else { fmpz_mpoly_set(A->zpoly, B->zpoly, ctx->zctx); } } void fmpq_mpoly_scalar_mul_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init_set_ui(C, c); fmpq_mpoly_scalar_mul_fmpz(A, B, C, ctx); fmpz_clear(C); } void fmpq_mpoly_scalar_mul_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init(C); fmpz_set_si(C, c); fmpq_mpoly_scalar_mul_fmpz(A, B, C, ctx); fmpz_clear(C); } flint-3.1.3/src/fmpq_mpoly/set_coeff_fmpq_fmpz.c000066400000000000000000000075441461254215100217770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void _fmpq_mpoly_set_coeff_fmpq_fmpz(fmpq_mpoly_t qpoly, const fmpq_t c, const fmpz * exp, const fmpq_mpoly_ctx_t qctx) { flint_bitcnt_t exp_bits; slong i, N, index; ulong * cmpmask; ulong * packed_exp; int exists; fmpz_mpoly_struct * poly = qpoly->zpoly; const fmpz_mpoly_ctx_struct * ctx = qctx->zctx; TMP_INIT; TMP_START; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_bits(poly, exp_bits, ctx); N = mpoly_words_per_exp(poly->bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, poly->bits, ctx->minfo); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, poly->bits, ctx->minfo); exists = mpoly_monomial_exists(&index, poly->exps, packed_exp, poly->length, N, cmpmask); if (!exists) { if (!fmpq_is_zero(c)) /* make new term only if coeff is nonzero*/ { fmpz_mpoly_fit_length(poly, poly->length + 1, ctx); if (poly->length > 0) { fmpz_t prod; fmpz_init(prod); fmpz_mul(prod, fmpq_numref(qpoly->content), fmpq_denref(c)); fmpz_mpoly_scalar_mul_fmpz(poly, poly, prod, ctx); for (i = poly->length; i >= index + 1; i--) { fmpz_set(poly->coeffs + i, poly->coeffs + i - 1); mpoly_monomial_set(poly->exps + N*i, poly->exps + N*(i - 1), N); } fmpz_mul(poly->coeffs + index, fmpq_denref(qpoly->content), fmpq_numref(c)); fmpq_div_fmpz(qpoly->content, qpoly->content, prod); fmpz_clear(prod); } else { index = 0; fmpz_one(poly->coeffs + index); fmpq_set(qpoly->content, c); } mpoly_monomial_set(poly->exps + N*index, packed_exp, N); poly->length++; /* safe because length is increasing */ } } else if (fmpq_is_zero(c)) /* zero coeff, remove term */ { for (i = index; i < poly->length - 1; i++) { fmpz_set(poly->coeffs + i, poly->coeffs + i + 1); mpoly_monomial_set(poly->exps + N*i, poly->exps + N*(i + 1), N); } _fmpz_mpoly_set_length(poly, poly->length - 1, ctx); } else /* term with that monomial exists, coeff is nonzero */ { fmpz_t prod; fmpz_init(prod); fmpz_mul(prod, fmpq_numref(qpoly->content), fmpq_denref(c)); fmpz_mpoly_scalar_mul_fmpz(poly, poly, prod, ctx); fmpz_mul(poly->coeffs + index, fmpq_denref(qpoly->content), fmpq_numref(c)); fmpq_div_fmpz(qpoly->content, qpoly->content, prod); fmpz_clear(prod); } fmpq_mpoly_reduce(qpoly, qctx); TMP_END; } void fmpq_mpoly_set_coeff_fmpq_fmpz(fmpq_mpoly_t poly, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { slong i, nvars = ctx->zctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_init(newexp + i); fmpz_set(newexp + i, exp[i]); } _fmpq_mpoly_set_coeff_fmpq_fmpz(poly, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fmpq_mpoly/set_coeff_fmpq_monomial.c000066400000000000000000000023171461254215100226270ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" void fmpq_mpoly_set_coeff_fmpq_monomial(fmpq_mpoly_t poly1, const fmpq_t c, const fmpq_mpoly_t poly2, const fmpq_mpoly_ctx_t ctx) { slong i, nvars = ctx->zctx->minfo->nvars; fmpz * texps; TMP_INIT; if (poly2->zpoly->length != WORD(1)) { flint_throw(FLINT_ERROR, "poly2 not monomial in fmpz_mpoly_set_coeff_fmpz_monomial"); } TMP_START; texps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init(texps + i); mpoly_get_monomial_ffmpz(texps, poly2->zpoly->exps + 0, poly2->zpoly->bits, ctx->zctx->minfo); _fmpq_mpoly_set_coeff_fmpq_fmpz(poly1, c, texps, ctx); for (i = 0; i < nvars; i++) fmpz_clear(texps + i); TMP_END; return; } flint-3.1.3/src/fmpq_mpoly/set_coeff_fmpq_ui.c000066400000000000000000000016141461254215100214300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_set_coeff_fmpq_ui(fmpq_mpoly_t poly, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) { slong i, nvars = ctx->zctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); _fmpq_mpoly_set_coeff_fmpq_fmpz(poly, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fmpq_mpoly/set_fmpq.c000066400000000000000000000013051461254215100175660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_set_fmpq(fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) { fmpq_set(A->content, c); if (fmpq_is_zero(c)) { fmpz_mpoly_zero(A->zpoly, ctx->zctx); } else { fmpz_mpoly_one(A->zpoly, ctx->zctx); } } flint-3.1.3/src/fmpq_mpoly/set_fmpz.c000066400000000000000000000025501461254215100176020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_set_fmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) { fmpz_set(fmpq_numref(A->content), c); fmpz_one(fmpq_denref(A->content)); if (fmpz_is_zero(c)) { fmpz_mpoly_zero(A->zpoly, ctx->zctx); } else { fmpz_mpoly_one(A->zpoly, ctx->zctx); } } void fmpq_mpoly_set_ui(fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx) { fmpz_set_ui(fmpq_numref(A->content), c); fmpz_one(fmpq_denref(A->content)); if (c == UWORD(0)) { fmpz_mpoly_zero(A->zpoly, ctx->zctx); } else { fmpz_mpoly_one(A->zpoly, ctx->zctx); } } void fmpq_mpoly_set_si(fmpq_mpoly_t A, slong c, const fmpq_mpoly_ctx_t ctx) { fmpz_set_si(fmpq_numref(A->content), c); fmpz_one(fmpq_denref(A->content)); if (c == WORD(0)) { fmpz_mpoly_zero(A->zpoly, ctx->zctx); } else { fmpz_mpoly_one(A->zpoly, ctx->zctx); } } flint-3.1.3/src/fmpq_mpoly/set_str_pretty.c000066400000000000000000000023771461254215100210540ustar00rootroot00000000000000/* Copyright (C) 2019-2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" int fmpq_mpoly_set_str_pretty(fmpq_mpoly_t poly, const char * str, const char** x, const fmpq_mpoly_ctx_t ctx) { int ret; slong i; fmpq_mpoly_t val; mpoly_parse_t E; char dummy[FLINT_BITS/2]; mpoly_void_ring_init_fmpq_mpoly_ctx(E->R, ctx); mpoly_parse_init(E); fmpq_mpoly_init(val, ctx); for (i = 0; i < ctx->zctx->minfo->nvars; i++) { fmpq_mpoly_gen(val, i, ctx); if (x == NULL) { flint_sprintf(dummy, "x%wd", i + 1); mpoly_parse_add_terminal(E, dummy, (const void *)val); } else { mpoly_parse_add_terminal(E, x[i], (const void *)val); } } fmpq_mpoly_clear(val, ctx); ret = mpoly_parse_parse(E, poly, str, strlen(str)); mpoly_parse_clear(E); return ret; } flint-3.1.3/src/fmpq_mpoly/set_term_coeff_fmpq.c000066400000000000000000000041001461254215100217530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_mpoly.h" void fmpq_mpoly_set_term_coeff_fmpq(fmpq_mpoly_t A, slong i, const fmpq_t x, const fmpq_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) fmpq_mpoly_length(A, ctx)) { flint_throw(FLINT_ERROR, "index out of range in fmpq_mpoly_set_term_coeff_fmpq"); } if (fmpq_is_zero(x)) { /* we can easily get a zero coeff by zeroing the coeff of the zpoly */ fmpz_mpoly_set_term_coeff_fmpz(A->zpoly, i, fmpq_numref(x), ctx->zctx); } else if (fmpq_is_zero(A->content)) { /* if the A->content is zero, set the nth coeff to 1 set all other coeffs to 0 set the content to x */ fmpz_t t; fmpz_init_set_ui(t, UWORD(1)); fmpq_set(A->content, x); _fmpz_vec_zero(A->zpoly->coeffs, A->zpoly->length); fmpz_mpoly_set_term_coeff_fmpz(A->zpoly, i, t, ctx->zctx); fmpz_clear(t); } else { /* if A->content != 0 and x != 0, compute nun/den = x / A->content scale zpoly by den divide A->content by den set the nth coeff of zpoly to num */ fmpq_t t; fmpq_init(t); fmpq_div(t, x, A->content); if (!fmpz_is_one(fmpq_denref(t))) { fmpq_div_fmpz(A->content, A->content, fmpq_denref(t)); _fmpz_vec_scalar_mul_fmpz(A->zpoly->coeffs, A->zpoly->coeffs, A->zpoly->length, fmpq_denref(t)); } fmpz_mpoly_set_term_coeff_fmpz(A->zpoly, i, fmpq_numref(t), ctx->zctx); fmpq_clear(t); } } flint-3.1.3/src/fmpq_mpoly/sqrt.c000066400000000000000000000020471461254215100167450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int fmpq_mpoly_sqrt(fmpq_mpoly_t Q, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_t r; fmpz_init(r); if (fmpz_sgn(fmpq_numref(A->content)) < 0) goto fail; fmpz_sqrtrem(fmpq_numref(Q->content), r, fmpq_numref(A->content)); if (!fmpz_is_zero(r)) goto fail; fmpz_sqrtrem(fmpq_denref(Q->content), r, fmpq_denref(A->content)); if (!fmpz_is_zero(r)) goto fail; if (!fmpz_mpoly_sqrt(Q->zpoly, A->zpoly, ctx->zctx)) goto fail; fmpz_clear(r); return 1; fail: fmpq_mpoly_zero(Q, ctx); fmpz_clear(r); return 0; } flint-3.1.3/src/fmpq_mpoly/sub.c000066400000000000000000000021541461254215100165440ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_sub(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx) { fmpz_t t1, t2; slong easy_length = B->zpoly->length + C->zpoly->length; if (fmpq_mpoly_is_zero(B, ctx)) { fmpq_mpoly_neg(A, C, ctx); return; } if (fmpq_mpoly_is_zero(C, ctx)) { fmpq_mpoly_set(A, B, ctx); return; } fmpz_init(t1); fmpz_init(t2); fmpq_gcd_cofactors(A->content, t1, t2, B->content, C->content); fmpz_neg(t2, t2); fmpz_mpoly_scalar_fmma(A->zpoly, B->zpoly, t1, C->zpoly, t2, ctx->zctx); fmpz_clear(t1); fmpz_clear(t2); fmpq_mpoly_reduce_easy(A, easy_length, ctx); } flint-3.1.3/src/fmpq_mpoly/sub_fmpq.c000066400000000000000000000037441461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_sub_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) { fmpz_t t1, t2; slong easy_length = B->zpoly->length + 1; if (fmpq_is_zero(c)) { fmpq_mpoly_set(A, B, ctx); return; } else if (fmpq_mpoly_is_zero(B, ctx)) { fmpq_mpoly_set_fmpq(A, c, ctx); fmpq_mpoly_neg(A, A, ctx); return; } fmpz_init(t1); fmpz_init(t2); fmpq_gcd_cofactors(A->content, t1, t2, B->content, c); fmpz_mpoly_scalar_mul_fmpz(A->zpoly, B->zpoly, t1, ctx->zctx); fmpz_mpoly_sub_fmpz(A->zpoly, A->zpoly, t2, ctx->zctx); fmpz_clear(t1); fmpz_clear(t2); fmpq_mpoly_reduce_easy(A, easy_length, ctx); } void fmpq_mpoly_sub_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx) { fmpq_t t; *fmpq_numref(t) = *c; *fmpq_denref(t) = 1; fmpq_mpoly_sub_fmpq(A, B, t, ctx); } void fmpq_mpoly_sub_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx) { fmpq_t t; fmpz_init_set_ui(fmpq_numref(t), c); *fmpq_denref(t) = 1; fmpq_mpoly_sub_fmpq(A, B, t, ctx); fmpz_clear(fmpq_numref(t)); } void fmpq_mpoly_sub_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx) { fmpq_t t; fmpz_init_set_si(fmpq_numref(t), c); *fmpq_denref(t) = 1; fmpq_mpoly_sub_fmpq(A, B, t, ctx); fmpz_clear(fmpq_numref(t)); } flint-3.1.3/src/fmpq_mpoly/term_content.c000066400000000000000000000013671461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" void fmpq_mpoly_term_content(fmpq_mpoly_t M, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { if (fmpq_mpoly_is_zero(A, ctx)) { fmpq_mpoly_zero(M, ctx); return; } fmpz_mpoly_term_content(M->zpoly, A->zpoly, ctx->zctx); _fmpq_mpoly_make_monic_inplace(M, ctx); } flint-3.1.3/src/fmpq_mpoly/term_exp_fits.c000066400000000000000000000017571461254215100206330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpq_mpoly.h" int fmpq_mpoly_term_exp_fits_ui(const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { return A->zpoly->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_ui(A->zpoly->exps, A->zpoly->bits, i, ctx->zctx->minfo); } int fmpq_mpoly_term_exp_fits_si(const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx) { return A->zpoly->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_si(A->zpoly->exps, A->zpoly->bits, i, ctx->zctx->minfo); } flint-3.1.3/src/fmpq_mpoly/test/000077500000000000000000000000001461254215100165645ustar00rootroot00000000000000flint-3.1.3/src/fmpq_mpoly/test/main.c000066400000000000000000000105011461254215100176510ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-add_sub_fmpq.c" #include "t-add_sub_fmpz.c" #include "t-cmp.c" #include "t-compose_fmpq_mpoly.c" #include "t-compose_fmpq_poly.c" #include "t-content.c" #include "t-content_vars.c" #include "t-degree.c" #include "t-degrees_term_exp_fits_ui_si.c" #include "t-derivative_integral.c" #include "t-div.c" #include "t-divides.c" #include "t-divrem.c" #include "t-divrem_ideal.c" #include "t-equal_is_fmpq.c" #include "t-evaluate.c" #include "t-gcd_brown.c" #include "t-gcd.c" #include "t-gcd_cofactors.c" #include "t-gcd_hensel.c" #include "t-gcd_subresultant.c" #include "t-gcd_zippel2.c" #include "t-gcd_zippel.c" #include "t-gen.c" #include "t-get_coeff_vars_ui.c" #include "t-get_set_coeff_fmpq_fmpz.c" #include "t-get_set_coeff_fmpq_monomial.c" #include "t-get_set_coeff_fmpq_ui.c" #include "t-get_set_is_fmpq.c" #include "t-get_set_str_pretty.c" #include "t-get_set_term_coeff_fmpq.c" #include "t-get_set_term_exp_fmpz.c" #include "t-get_set_term_exp_si.c" #include "t-get_set_term_exp_ui.c" #include "t-get_term.c" #include "t-get_term_monomial.c" #include "t-mul.c" #include "t-pow_fmpz.c" #include "t-pow_ui.c" #include "t-push_term_fmpq_fmpz.c" #include "t-push_term_fmpq_ui.c" #include "t-resultant_discriminant.c" #include "t-scalar_mul_div_fmpq.c" #include "t-scalar_mul_div_fmpz.c" #include "t-scalar_mul_fmpq.c" #include "t-sqrt.c" #include "t-term_content.c" #include "t-total_degree.c" #include "t-univar.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpq_mpoly_add_sub), TEST_FUNCTION(fmpq_mpoly_add_sub_fmpq), TEST_FUNCTION(fmpq_mpoly_add_sub_fmpz), TEST_FUNCTION(fmpq_mpoly_cmp), TEST_FUNCTION(fmpq_mpoly_compose_fmpq_mpoly), TEST_FUNCTION(fmpq_mpoly_compose_fmpq_poly), TEST_FUNCTION(fmpq_mpoly_content), TEST_FUNCTION(fmpq_mpoly_content_vars), TEST_FUNCTION(fmpq_mpoly_degree), TEST_FUNCTION(fmpq_mpoly_degrees_term_exp_fits_ui_si), TEST_FUNCTION(fmpq_mpoly_derivative_integral), TEST_FUNCTION(fmpq_mpoly_div), TEST_FUNCTION(fmpq_mpoly_divides), TEST_FUNCTION(fmpq_mpoly_divrem), TEST_FUNCTION(fmpq_mpoly_divrem_ideal), TEST_FUNCTION(fmpq_mpoly_equal_is_fmpq), TEST_FUNCTION(fmpq_mpoly_evaluate), TEST_FUNCTION(fmpq_mpoly_gcd_brown), TEST_FUNCTION(fmpq_mpoly_gcd), TEST_FUNCTION(fmpq_mpoly_gcd_cofactors), TEST_FUNCTION(fmpq_mpoly_gcd_hensel), TEST_FUNCTION(fmpq_mpoly_gcd_subresultant), TEST_FUNCTION(fmpq_mpoly_gcd_zippel2), TEST_FUNCTION(fmpq_mpoly_gcd_zippel), TEST_FUNCTION(fmpq_mpoly_gen), TEST_FUNCTION(fmpq_mpoly_get_coeff_vars_ui), TEST_FUNCTION(fmpq_mpoly_get_set_coeff_fmpq_fmpz), TEST_FUNCTION(fmpq_mpoly_get_set_coeff_fmpq_monomial), TEST_FUNCTION(fmpq_mpoly_get_set_coeff_fmpq_ui), TEST_FUNCTION(fmpq_mpoly_get_set_is_fmpq), TEST_FUNCTION(fmpq_mpoly_get_set_str_pretty), TEST_FUNCTION(fmpq_mpoly_get_set_term_coeff_fmpq), TEST_FUNCTION(fmpq_mpoly_get_set_term_exp_fmpz), TEST_FUNCTION(fmpq_mpoly_get_set_term_exp_si), TEST_FUNCTION(fmpq_mpoly_get_set_term_exp_ui), TEST_FUNCTION(fmpq_mpoly_get_term), TEST_FUNCTION(fmpq_mpoly_get_term_monomial), TEST_FUNCTION(fmpq_mpoly_mul), TEST_FUNCTION(fmpq_mpoly_pow_fmpz), TEST_FUNCTION(fmpq_mpoly_pow_ui), TEST_FUNCTION(fmpq_mpoly_push_term_fmpq_fmpz), TEST_FUNCTION(fmpq_mpoly_push_term_fmpq_ui), TEST_FUNCTION(fmpq_mpoly_resultant_discriminant), TEST_FUNCTION(fmpq_mpoly_scalar_mul_div_fmpq), TEST_FUNCTION(fmpq_mpoly_scalar_mul_div_fmpz), TEST_FUNCTION(fmpq_mpoly_scalar_mul_fmpq), TEST_FUNCTION(fmpq_mpoly_sqrt), TEST_FUNCTION(fmpq_mpoly_term_content), TEST_FUNCTION(fmpq_mpoly_total_degree), TEST_FUNCTION(fmpq_mpoly_univar) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpq_mpoly/test/t-add_sub.c000066400000000000000000000321321461254215100205730ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_add_sub, state) { int i, j, result; /* Check (f + g) - g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_add(h, g, f, ctx); fmpq_mpoly_sub(k, h, g, ctx); result = fmpq_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + g) - g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check f + g = g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_add(h, f, g, ctx); fmpq_mpoly_add(k, g, f, ctx); result = fmpq_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + g = g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check f - g = -g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_sub(h, f, g, ctx); fmpq_mpoly_neg(k, g, ctx); fmpq_mpoly_add(k, k, f, ctx); result = fmpq_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f - g = -g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check f + (g + h) = (f + g) + h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k1, ctx); fmpq_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k1, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k2, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_add(k1, f, g, ctx); fmpq_mpoly_add(k1, k1, h, ctx); fmpq_mpoly_add(k2, g, h, ctx); fmpq_mpoly_add(k2, k2, f, ctx); result = fmpq_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + (g + h) = (f + g) + h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k1, ctx); fmpq_mpoly_clear(k2, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check f - (g + h) = (f - g) - h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k1, ctx); fmpq_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k1, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k2, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_add(k1, g, h, ctx); fmpq_mpoly_sub(k1, f, k1, ctx); fmpq_mpoly_sub(k2, f, g, ctx); fmpq_mpoly_sub(k2, k2, h, ctx); result = fmpq_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f - (g + h) = (f - g) - h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k1, ctx); fmpq_mpoly_clear(k2, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); if ((j % 2) == 0) { fmpq_mpoly_add(h, g, f, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_add(f, g, f, ctx); fmpq_mpoly_assert_canonical(f, ctx); } else { fmpq_mpoly_sub(h, g, f, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_sub(f, g, f, ctx); fmpq_mpoly_assert_canonical(f, ctx); } result = fmpq_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); if ((j % 2) == 0) { fmpq_mpoly_add(h, g, f, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_add(g, g, f, ctx); fmpq_mpoly_assert_canonical(f, ctx); } else { fmpq_mpoly_sub(h, g, f, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_sub(g, g, f, ctx); fmpq_mpoly_assert_canonical(f, ctx); } result = fmpq_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); if ((j % 2) == 0) { fmpq_mpoly_add(h, f, f, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_add(f, f, f, ctx); fmpq_mpoly_assert_canonical(f, ctx); } else { fmpq_mpoly_sub(h, f, f, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_sub(f, f, f, ctx); fmpq_mpoly_assert_canonical(f, ctx); } result = fmpq_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing both args\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-add_sub_fmpq.c000066400000000000000000000073661461254215100216310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_add_sub_fmpq, state) { slong i, j; /* Check (f + a) - a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpq_t c; slong len, coeff_bits, exp_bits; fmpq_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_randtest(c, state, n_randint(state, 200) + 1); fmpq_mpoly_add_fmpq(g, f, c, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_sub_fmpq(h, g, c, ctx); fmpq_mpoly_assert_canonical(h, ctx); if (!fmpq_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check (f + a) - a = f\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_randtest(c, state, n_randint(state, 200) + 1); fmpq_mpoly_sub_fmpq(g, f, c, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_add_fmpq(h, g, c, ctx); fmpq_mpoly_assert_canonical(h, ctx); if (!fmpq_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check (f - a) + a = f\n"); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g; fmpq_t c; slong len, coeff_bits, exp_bits; fmpq_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_set(g, f, ctx); fmpq_randtest(c, state, n_randint(state, 200) + 1); fmpq_mpoly_add_fmpq(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); fmpq_mpoly_sub_fmpq(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); if (!fmpq_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check aliasing\n"); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-add_sub_fmpz.c000066400000000000000000000063331461254215100216330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_add_sub_fmpz, state) { int i, j, result; /* Check (f + a) - a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpq_mpoly_add_fmpz(g, f, c, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_sub_fmpz(h, g, c, ctx); fmpq_mpoly_assert_canonical(h, ctx); result = fmpq_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + a) - a = f, i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpz_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_set(g, f, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpq_mpoly_add_fmpz(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); fmpq_mpoly_sub_fmpz(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); result = fmpq_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-cmp.c000066400000000000000000000137201461254215100177530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_cmp, state) { int result; slong i, j1, j2; /* check polynomial terms are in order */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, mf, mg; slong len; flint_bitcnt_t coeff_bits, exp_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(mf, ctx); fmpq_mpoly_init(mg, ctx); len = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits = n_randint(state, exp_bits) + 2; coeff_bits = n_randint(state, 100) + 1; fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_repack_bits(g, f, f->zpoly->bits + n_randint(state, FLINT_BITS), ctx); fmpq_mpoly_assert_canonical(f, ctx); fmpq_mpoly_assert_canonical(g, ctx); for (j1 = 0; j1 < f->zpoly->length; j1++) for (j2 = 0; j2 < g->zpoly->length; j2++) { fmpq_mpoly_get_term_monomial(mf, f, j1, ctx); fmpq_mpoly_get_term_monomial(mg, g, j2, ctx); result = fmpq_mpoly_cmp(mf, mg, ctx); result = (result == 0 && j1 == j2) || (result == +1 && j1 < j2) || (result == -1 && j1 > j2); if (!result) { flint_printf("FAIL\n" "check polynomial terms are in order\n" "i = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(mf, ctx); fmpq_mpoly_clear(mg, ctx); fmpq_mpoly_ctx_clear(ctx); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, c, aa, bb, cc; int a_a, a_b, a_c, a_aa, a_bb, a_cc; int b_a, b_b, b_c, b_aa, b_bb, b_cc; int c_a, c_b, c_c, c_aa, c_bb, c_cc; flint_bitcnt_t newbits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(c, ctx); fmpq_mpoly_init(aa, ctx); fmpq_mpoly_init(bb, ctx); fmpq_mpoly_init(cc, ctx); fmpq_mpoly_randtest_bits(a, state, n_randint(state, 100) + 1, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fmpq_mpoly_randtest_bits(b, state, n_randint(state, 100) + 1, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fmpq_mpoly_randtest_bits(c, state, n_randint(state, 100) + 1, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); newbits = a->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(aa, a, newbits, ctx); newbits = b->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(bb, b, newbits, ctx); newbits = c->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(cc, c, newbits, ctx); a_a = fmpq_mpoly_cmp(a, a, ctx); a_b = fmpq_mpoly_cmp(a, b, ctx); a_c = fmpq_mpoly_cmp(a, c, ctx); a_aa = fmpq_mpoly_cmp(a, aa, ctx); a_bb = fmpq_mpoly_cmp(a, bb, ctx); a_cc = fmpq_mpoly_cmp(a, cc, ctx); b_a = fmpq_mpoly_cmp(b, a, ctx); b_b = fmpq_mpoly_cmp(b, b, ctx); b_c = fmpq_mpoly_cmp(b, c, ctx); b_aa = fmpq_mpoly_cmp(b, aa, ctx); b_bb = fmpq_mpoly_cmp(b, bb, ctx); b_cc = fmpq_mpoly_cmp(b, cc, ctx); c_a = fmpq_mpoly_cmp(c, a, ctx); c_b = fmpq_mpoly_cmp(c, b, ctx); c_c = fmpq_mpoly_cmp(c, c, ctx); c_aa = fmpq_mpoly_cmp(c, aa, ctx); c_bb = fmpq_mpoly_cmp(c, bb, ctx); c_cc = fmpq_mpoly_cmp(c, cc, ctx); if (a_a != 0 || a_aa != 0 || b_b != 0 || b_bb != 0 || c_c != 0 || c_cc != 0) { flint_printf("FAIL\n" "check polynomial compares equal to itself\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if (a_b != a_bb || a_c != a_cc || b_a != b_aa || b_c != b_cc || c_a != c_aa || c_b != c_bb) { flint_printf("FAIL\n" "check polynomial comparison with differing bits\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if ((a_b*b_c == 0 && a_c != a_b + b_c) || (a_b*b_c > 0 && a_c != a_b)) { flint_printf("FAIL\n" "check transitivity\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(c, ctx); fmpq_mpoly_clear(aa, ctx); fmpq_mpoly_clear(bb, ctx); fmpq_mpoly_clear(cc, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-compose_fmpq_mpoly.c000066400000000000000000000251651461254215100231120ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_compose_fmpq_mpoly, state) { slong i, j, v; { fmpq_mpoly_t A, A1, A2, B; fmpq_mpoly_struct * Cp[3]; fmpq_mpoly_struct C[3]; fmpq_mpoly_ctx_t ctxAC, ctxB; fmpq_mpoly_ctx_init(ctxB, 3, ORD_LEX); fmpq_mpoly_ctx_init(ctxAC, 2, ORD_LEX); fmpq_mpoly_init(B, ctxB); fmpq_mpoly_init(A, ctxAC); fmpq_mpoly_init(A1, ctxAC); fmpq_mpoly_init(A2, ctxAC); for (i = 0; i < 3; i++) { Cp[i] = C + i; fmpq_mpoly_init(C + i, ctxAC); } fmpq_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB); fmpq_mpoly_set_str_pretty(C + 0, "x1 + x2", NULL, ctxAC); fmpq_mpoly_set_str_pretty(C + 1, "x1 - x2", NULL, ctxAC); fmpq_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (fmpq_mpoly_compose_fmpq_mpoly(A, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(C + 0, "x1", NULL, ctxAC); fmpq_mpoly_set_str_pretty(C + 1, "2*x2", NULL, ctxAC); fmpq_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (fmpq_mpoly_compose_fmpq_mpoly(A, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 2\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(C + 0, "2*x1", NULL, ctxAC); fmpq_mpoly_set_str_pretty(C + 1, "x2", NULL, ctxAC); fmpq_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (!fmpq_mpoly_compose_fmpq_mpoly(A, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check example 3\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(B, ctxB); fmpq_mpoly_clear(A, ctxAC); fmpq_mpoly_clear(A1, ctxAC); fmpq_mpoly_clear(A2, ctxAC); for (i = 0; i < 3; i++) fmpq_mpoly_clear(C + i, ctxAC); fmpq_mpoly_ctx_clear(ctxB); fmpq_mpoly_ctx_clear(ctxAC); } /* check composition with generators */ for (i = 0; i < 50*flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctxB, ctxAC; fmpq_mpoly_t B, A, A1; fmpq_mpoly_struct ** C; slong * c; slong nvarsB, nvarsAC; slong len; flint_bitcnt_t exp_bits, coeff_bits; fmpq_mpoly_ctx_init_rand(ctxB, state, 20); fmpq_mpoly_ctx_init_rand(ctxAC, state, 20); nvarsB = ctxB->zctx->minfo->nvars; nvarsAC = ctxAC->zctx->minfo->nvars; fmpq_mpoly_init(B, ctxB); fmpq_mpoly_init(A, ctxAC); fmpq_mpoly_init(A1, ctxAC); c = (slong *) flint_malloc(nvarsB*sizeof(slong)); C = (fmpq_mpoly_struct **) flint_malloc(nvarsB * sizeof(fmpq_mpoly_struct *)); for (v = 0; v < nvarsB; v++) { C[v] = (fmpq_mpoly_struct *) flint_malloc(sizeof(fmpq_mpoly_struct)); fmpq_mpoly_init(C[v], ctxAC); } for (j = 0; j < 4; j++) { len = n_randint(state, 200); exp_bits = n_randint(state, 100) + 1; coeff_bits = n_randint(state, 100) + 1; for (v = 0; v < nvarsB; v++) { c[v] = n_randint(state, nvarsAC + 2) - 2; if (c[v] >= 0) fmpq_mpoly_gen(C[v], c[v], ctxAC); else fmpq_mpoly_zero(C[v], ctxAC); } fmpq_mpoly_randtest_bits(B, state, len, coeff_bits, exp_bits, ctxB); fmpq_mpoly_compose_fmpq_mpoly_gen(A, B, c, ctxB, ctxAC); if (!fmpq_mpoly_compose_fmpq_mpoly(A1, B, C, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition success with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal(A, A1, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(A, ctxAC); fmpq_mpoly_assert_canonical(A1, ctxAC); } for (v = 0; v < nvarsB; v++) { fmpq_mpoly_clear(C[v], ctxAC); flint_free(C[v]); } flint_free(C); flint_free(c); fmpq_mpoly_clear(B, ctxB); fmpq_mpoly_clear(A, ctxAC); fmpq_mpoly_clear(A1, ctxAC); fmpq_mpoly_ctx_clear(ctxB); fmpq_mpoly_ctx_clear(ctxAC); } /* Check composition with identity */ for (i = 0; i < 50*flint_test_multiplier(); i++) { slong nvars, len1; flint_bitcnt_t exp_bits, coeff_bits; fmpq_mpoly_struct ** vals1; fmpq_mpoly_t f, g; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->zctx->minfo->nvars; vals1 = (fmpq_mpoly_struct **) flint_malloc(nvars*sizeof(fmpq_mpoly_struct *)); for (v = 0; v < nvars; v++) { vals1[v] = (fmpq_mpoly_struct *) flint_malloc(sizeof(fmpq_mpoly_struct)); fmpq_mpoly_init(vals1[v], ctx); fmpq_mpoly_gen(vals1[v], v, ctx); } fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); len1 = n_randint(state, 200); exp_bits = n_randint(state, 100) + 1; coeff_bits = n_randint(state, 100) + 1; fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx); if (!fmpq_mpoly_compose_fmpq_mpoly(g, f, vals1, ctx, ctx)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check composition with identity\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(f, ctx); for (v = 0; v < nvars; v++) { fmpq_mpoly_clear(vals1[v], ctx); flint_free(vals1[v]); } flint_free(vals1); } /* Check composition and evalall commute */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx1, ctx2; fmpq_mpoly_t f, g; fmpq_mpoly_struct ** vals1; fmpq_t fe, ge; fmpq ** vals2, ** vals3; slong nvars1, nvars2; slong len1, len2; slong exp_bound1, exp_bound2; slong coeff_bits; fmpq_mpoly_ctx_init_rand(ctx1, state, 10); fmpq_mpoly_ctx_init_rand(ctx2, state, 10); nvars1 = ctx1->zctx->minfo->nvars; nvars2 = ctx2->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx1); fmpq_mpoly_init(g, ctx2); fmpq_init(fe); fmpq_init(ge); len1 = n_randint(state, 70/FLINT_MAX(WORD(1), nvars1) + 1); len2 = n_randint(state, 25/FLINT_MAX(WORD(1), nvars2) + 1); exp_bound1 = n_randint(state, 15/FLINT_MAX(WORD(1), nvars1) + 2) + 1; exp_bound2 = n_randint(state, 15/FLINT_MAX(WORD(1), nvars2) + 2) + 1; coeff_bits = n_randint(state, 10); vals1 = (fmpq_mpoly_struct **) flint_malloc(nvars1 * sizeof(fmpq_mpoly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpq_mpoly_struct *) flint_malloc( sizeof(fmpq_mpoly_struct)); fmpq_mpoly_init(vals1[v], ctx2); fmpq_mpoly_randtest_bound(vals1[v], state, len2, coeff_bits, exp_bound2, ctx2); } vals2 = (fmpq **) flint_malloc(nvars2*sizeof(fmpq*)); for (v = 0; v < nvars2; v++) { vals2[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals2[v]); fmpq_randbits(vals2[v], state, 4); } vals3 = (fmpq **) flint_malloc(nvars1*sizeof(fmpq*)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals3[v]); if (!fmpq_mpoly_evaluate_all_fmpq(vals3[v], vals1[v], vals2, ctx2)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } } fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx1); if (!fmpq_mpoly_compose_fmpq_mpoly(g, f, vals1, ctx1, ctx2)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(g, ctx2); if (!fmpq_mpoly_evaluate_all_fmpq(fe, f, vals3, ctx1) || !fmpq_mpoly_evaluate_all_fmpq(ge, g, vals2, ctx2)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } if (!fmpq_equal(fe, ge)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } for (v = 0; v < nvars1; v++) { fmpq_mpoly_clear(vals1[v], ctx2); flint_free(vals1[v]); } flint_free(vals1); for (v = 0; v < nvars2; v++) { fmpq_clear(vals2[v]); flint_free(vals2[v]); } flint_free(vals2); for (v = 0; v < nvars1; v++) { fmpq_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); fmpq_mpoly_clear(f, ctx1); fmpq_mpoly_clear(g, ctx2); fmpq_clear(fe); fmpq_clear(ge); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-compose_fmpq_poly.c000066400000000000000000000213761461254215100227350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_compose_fmpq_poly, state) { slong i, v; /* Check composition and evalall commute */ for (i = 0; i < 50*flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx1; fmpq_mpoly_t f; fmpq_poly_t g; fmpq_poly_struct ** vals1; fmpq_t fe, ge; fmpq_t vals2; fmpq ** vals3; slong nvars1; slong len1, len2; slong exp_bound1; flint_bitcnt_t coeff_bits, coeff_bits2; fmpq_mpoly_ctx_init_rand(ctx1, state, 10); nvars1 = ctx1->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx1); fmpq_poly_init(g); fmpq_init(fe); fmpq_init(ge); len1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars1) + 1); len2 = n_randint(state, 40); exp_bound1 = n_randint(state, 100/FLINT_MAX(WORD(1), nvars1) + 2) + 1; coeff_bits = n_randint(state, 100) + 1; coeff_bits2 = n_randint(state, 15) + 1; fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx1); vals1 = (fmpq_poly_struct **) flint_malloc(nvars1 * sizeof(fmpq_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpq_poly_struct *) flint_malloc( sizeof(fmpq_poly_struct)); fmpq_poly_init(vals1[v]); fmpq_poly_randtest(vals1[v], state, len2, coeff_bits2); } fmpq_init(vals2); fmpq_randbits(vals2, state, 10); vals3 = (fmpq **) flint_malloc(nvars1*sizeof(fmpq *)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals3[v]); fmpq_poly_evaluate_fmpq(vals3[v], vals1[v], vals2); } if (fmpq_mpoly_total_degree_si(f, ctx1) < 50) { if (!fmpq_mpoly_compose_fmpq_poly(g, f, vals1, ctx1) || !fmpq_mpoly_evaluate_all_fmpq(fe, f, vals3, ctx1)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpq_poly_evaluate_fmpq(ge, g, vals2); if (!fmpq_equal(fe, ge)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars1; v++) { fmpq_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); fmpq_clear(vals2); for (v = 0; v < nvars1; v++) { fmpq_poly_clear(vals1[v]); flint_free(vals1[v]); } flint_free(vals1); fmpq_clear(fe); fmpq_clear(ge); fmpq_mpoly_clear(f, ctx1); fmpq_poly_clear(g); fmpq_mpoly_ctx_clear(ctx1); } /* Check composition with constants matches evalall */ for (i = 0; i < 50*flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx1; fmpq_mpoly_t f; fmpq_poly_t g; fmpq_poly_struct ** vals1; fmpq_t fe; fmpq ** vals3; slong nvars1; slong len1; slong exp_bound1; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx1, state, 10); nvars1 = ctx1->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx1); fmpq_poly_init(g); fmpq_init(fe); len1 = n_randint(state, 50); exp_bound1 = n_randint(state, 200/FLINT_MAX(WORD(1), nvars1) + 2) + 1; coeff_bits = n_randint(state, 100) + 1; fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx1); vals3 = (fmpq **) flint_malloc(nvars1*sizeof(fmpq *)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals3[v]); fmpq_randtest(vals3[v], state, 20); } vals1 = (fmpq_poly_struct **) flint_malloc(nvars1 * sizeof(fmpq_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpq_poly_struct *) flint_malloc( sizeof(fmpq_poly_struct)); fmpq_poly_init(vals1[v]); fmpq_poly_set_fmpq(vals1[v], vals3[v]); } if (fmpq_mpoly_total_degree_si(f, ctx1) < 50) { fmpq_poly_t t; if (!fmpq_mpoly_compose_fmpq_poly(g, f, vals1, ctx1) || !fmpq_mpoly_evaluate_all_fmpq(fe, f, vals3, ctx1)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpq_poly_init(t); fmpq_poly_set_fmpq(t, fe); if (!fmpq_poly_equal(g, t)) { printf("FAIL\n"); flint_printf("Check composition with constants matches evalall\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpq_poly_clear(t); } for (v = 0; v < nvars1; v++) { fmpq_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); for (v = 0; v < nvars1; v++) { fmpq_poly_clear(vals1[v]); flint_free(vals1[v]); } flint_free(vals1); fmpq_clear(fe); fmpq_mpoly_clear(f, ctx1); fmpq_poly_clear(g); fmpq_mpoly_ctx_clear(ctx1); } /* Check multiprecision composition with constants matches evalall */ for (i = 0; i < 50*flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx1; fmpq_mpoly_t f; fmpq_poly_t g; fmpq_poly_struct ** vals1; fmpq_t fe; fmpq ** vals3; slong nvars1; slong len1; flint_bitcnt_t exp_bits; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx1, state, 10); nvars1 = ctx1->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx1); fmpq_poly_init(g); fmpq_init(fe); len1 = n_randint(state, 50); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 100) + 1; fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx1); vals3 = (fmpq **) flint_malloc(nvars1*sizeof(fmpq *)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals3[v]); fmpq_set_si(vals3[v], n_randint(state, UWORD(3)) - WORD(1), UWORD(1)); } vals1 = (fmpq_poly_struct **) flint_malloc(nvars1 * sizeof(fmpq_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpq_poly_struct *) flint_malloc( sizeof(fmpq_poly_struct)); fmpq_poly_init(vals1[v]); fmpq_poly_set_fmpq(vals1[v], vals3[v]); } { fmpq_poly_t t; if (!fmpq_mpoly_compose_fmpq_poly(g, f, vals1, ctx1) || !fmpq_mpoly_evaluate_all_fmpq(fe, f, vals3, ctx1)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpq_poly_init(t); fmpq_poly_set_fmpq(t, fe); if (!fmpq_poly_equal(g, t)) { printf("FAIL\n"); flint_printf("Check multiprecision composition with constants matches evalall\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpq_poly_clear(t); } for (v = 0; v < nvars1; v++) { fmpq_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); for (v = 0; v < nvars1; v++) { fmpq_poly_clear(vals1[v]); flint_free(vals1[v]); } flint_free(vals1); fmpq_clear(fe); fmpq_mpoly_clear(f, ctx1); fmpq_poly_clear(g); fmpq_mpoly_ctx_clear(ctx1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-content.c000066400000000000000000000034611461254215100206470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_content, state) { slong i, j, k; /* Check content is gcd of coefficients */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; fmpq_t g1, g2, t; slong len; flint_bitcnt_t coeff_bits, exp_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_init(g1); fmpq_init(g2); fmpq_init(t); len = n_randint(state, 50); exp_bits = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_zero(g1); for (k = 0; k < fmpq_mpoly_length(f, ctx); k++) { fmpq_mpoly_get_term_coeff_fmpq(t, f, k, ctx); fmpq_gcd(g1, g1, t); } fmpq_mpoly_content(g2, f, ctx); if (!fmpq_equal(g1, g2)) { printf("FAIL\n"); flint_printf("Check content\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpq_clear(g1); fmpq_clear(g2); fmpq_clear(t); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-content_vars.c000066400000000000000000000077401461254215100217060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_content_vars, state) { slong i, j; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, t; slong nvars, num_vars, len; ulong * exp_bounds; slong * vars; fmpq_mpoly_ctx_init_rand(ctx, state, 20); nvars = ctx->zctx->minfo->nvars; if (nvars < 1) { fmpq_mpoly_ctx_clear(ctx); continue; } fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(t, ctx); exp_bounds = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (j = 0; j < nvars; j++) exp_bounds[j] = 1 + n_randint(state, 5); len = n_randint(state, 20); fmpq_mpoly_randtest_bounds(f, state, len, 200, exp_bounds, ctx); vars = (slong *) flint_malloc(nvars*sizeof(slong)); for (j = 0; j < nvars; j++) vars[j] = j; for (j = 0; j < 2*nvars; j++) { slong k1 = n_randint(state, nvars); slong k2 = n_randint(state, nvars); FLINT_SWAP(slong, vars[k1], vars[k2]); } num_vars = 1 + n_randint(state, nvars); for (j = 0; j < num_vars; j++) exp_bounds[vars[j]] = 1; len = n_randint(state, 10); fmpq_mpoly_randtest_bounds(t, state, len, 200, exp_bounds, ctx); fmpq_mpoly_mul(f, f, t, ctx); fmpq_mpoly_repack_bits(f, f, f->zpoly->bits + n_randint(state, FLINT_BITS), ctx); if (!fmpq_mpoly_content_vars(g, f, vars, num_vars, ctx)) { flint_printf("FAIL: check content could be computed\n"); fflush(stdout); flint_abort(); } if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(f, ctx)) { flint_printf("FAIL: check zero content\n"); fflush(stdout); flint_abort(); } } else { for (j = 0; j < num_vars; j++) { if (fmpq_mpoly_degree_si(g, vars[j], ctx) != 0) { flint_printf("FAIL: content depends on a bad variable\n"); fflush(stdout); flint_abort(); } } if (!fmpq_mpoly_divides(t, f, g, ctx)) { flint_printf("FAIL: check content divides\n"); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_content_vars(t, t, vars, num_vars, ctx)) { flint_printf("FAIL: check cofactor content could be computed\n"); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_one(t, ctx)) { flint_printf("FAIL: check cofactor content is one\n"); fflush(stdout); flint_abort(); } } if (!fmpq_mpoly_content_vars(f, f, vars, num_vars, ctx)) { flint_printf("FAIL: check aliased content could be computed\n"); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check aliasing\n"); fflush(stdout); flint_abort(); } flint_free(exp_bounds); flint_free(vars); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-degree.c000066400000000000000000000100421461254215100204210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_degree, state) { int i, j; /* Check degree does not go up under addition */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 4); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_add(h, f, g, ctx); fmpq_mpoly_degree_fmpz(hdeg, h, j, ctx); fmpq_mpoly_degree_fmpz(fdeg, f, j, ctx); fmpq_mpoly_degree_fmpz(gdeg, g, j, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check degree adds under multiplication */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { int ok; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 4); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_degree_fmpz(hdeg, h, j, ctx); fmpq_mpoly_degree_fmpz(fdeg, f, j, ctx); fmpq_mpoly_degree_fmpz(gdeg, g, j, ctx); if (fmpq_mpoly_is_zero(g, ctx) || fmpq_mpoly_is_zero(f, ctx)) { ok = (fmpz_cmp_si(hdeg, -WORD(1)) == 0); } else { fmpz_sub(hdeg, hdeg, fdeg); ok = (fmpz_cmp(hdeg, gdeg) == 0); } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-degrees_term_exp_fits_ui_si.c000066400000000000000000000212571461254215100247360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpq_mpoly_degrees_term_exp_fits_ui_si, state) { slong i, j, k; int result; /* basic corner cases */ { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; const char * vars[] = {"x","y","z"}; fmpq_mpoly_ctx_init(ctx, 3, ORD_DEGLEX); fmpq_mpoly_init(f, ctx); if (FLINT_BITS == 64) { fmpq_mpoly_set_str_pretty(f, "x^9223372036854775807", vars, ctx); if (!fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 1\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "(x*y)^9223372036854775807", vars, ctx); if (!fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 2\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^9223372036854775808", vars, ctx); if (fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 3\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "(x*y)^9223372036854775808", vars, ctx); if (fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 4\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^18446744073709551615", vars, ctx); if (!fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 1\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "(x*y)^18446744073709551615", vars, ctx); if (!fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 2\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^18446744073709551616", vars, ctx); if (fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 3\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "(x*y)^18446744073709551616", vars, ctx); if (fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 4\n"); fflush(stdout); flint_abort(); } } else if (FLINT_BITS == 32) { fmpq_mpoly_set_str_pretty(f, "x^2147483647", vars, ctx); if (!fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 1\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^2147483647*y^2147483647", vars, ctx); if (!fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 2\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^2147483648", vars, ctx); if (fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 3\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^2147483648*y^2147483648", vars, ctx); if (fmpq_mpoly_term_exp_fits_si(f, 0, ctx) || fmpq_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 4\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^4294967295", vars, ctx); if (!fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 1\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^4294967295*y^4294967295", vars, ctx); if (!fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 2\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^4294967296", vars, ctx); if (fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 3\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_set_str_pretty(f, "x^4294967296*y^4294967296", vars, ctx); if (fmpq_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 4\n"); fflush(stdout); flint_abort(); } } else { printf("FAIL\nFLINT_BITS is not 64 or 32\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check fit */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; fmpz ** exp, ** deg; slong len; flint_bitcnt_t coeff_bits, exp_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); exp = (fmpz **) flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz *)); deg = (fmpz **) flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz *)); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); deg[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_init(deg[k]); fmpz_set_si(deg[k], -WORD(1)); } len = n_randint(state, 100); exp_bits = n_randint(state, FLINT_BITS + 10) + 1; coeff_bits = n_randint(state, 30); fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < fmpq_mpoly_length(f, ctx); j++) { fmpq_mpoly_get_term_exp_fmpz(exp, f, j, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) if (fmpz_cmp(deg[k], exp[k]) < 0) fmpz_set(deg[k], exp[k]); result = 1; for (k = 0; k < ctx->zctx->minfo->nvars; k++) result = result && fmpz_fits_si(exp[k]); if (result != fmpq_mpoly_term_exp_fits_si(f, j, ctx)) { flint_printf("FAIL\nCheck monomial_fit_si\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } result = 1; for (k = 0; k < ctx->zctx->minfo->nvars; k++) result = result && fmpz_abs_fits_ui(exp[k]); if (result != fmpq_mpoly_term_exp_fits_ui(f, j, ctx)) { flint_printf("FAIL\nCheck monomial_fit_ui\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } result = 1; fmpq_mpoly_degrees_fmpz(exp, f, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { if (!fmpz_equal(exp[k], deg[k])) { flint_printf("FAIL\nCheck degree computation\ni = %wd\n", i); fflush(stdout); flint_abort(); } result = result && fmpz_fits_si(exp[k]); } if (result != fmpq_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nCheck degrees_fit_si\ni = %wd\n", i); fflush(stdout); flint_abort(); } for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_clear(deg[k]); flint_free(deg[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(deg); flint_free(exp); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-derivative_integral.c000066400000000000000000000200351461254215100232200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_derivative_integral, state) { int i, j, result; /* Check d(f*g) = df*g + f*dg */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, fp, gp, hp, t1, t2; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(fp, ctx); fmpq_mpoly_init(gp, ctx); fmpq_mpoly_init(hp, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(hp, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(fp, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(gp, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); idx = n_randint(state, nvars); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_derivative(hp, h, idx, ctx); fmpq_mpoly_assert_canonical(hp, ctx); fmpq_mpoly_derivative(fp, f, idx, ctx); fmpq_mpoly_assert_canonical(fp, ctx); fmpq_mpoly_derivative(gp, g, idx, ctx); fmpq_mpoly_assert_canonical(gp, ctx); fmpq_mpoly_mul(t1, f, gp, ctx); fmpq_mpoly_assert_canonical(t1, ctx); fmpq_mpoly_mul(t2, g, fp, ctx); fmpq_mpoly_assert_canonical(t2, ctx); fmpq_mpoly_add(t1, t1, t2, ctx); fmpq_mpoly_assert_canonical(t1, ctx); result = fmpq_mpoly_equal(hp, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(fp, ctx); fmpq_mpoly_clear(gp, ctx); fmpq_mpoly_clear(hp, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); } /* Check d(f*g) = df*g + f*dg with aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, fp, gp, t1, t2; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(fp, ctx); fmpq_mpoly_init(gp, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(fp, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(gp, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); idx = n_randint(state, nvars); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_derivative(h, h, idx, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_set(fp, f, ctx); fmpq_mpoly_derivative(fp, fp, idx, ctx); fmpq_mpoly_assert_canonical(fp, ctx); fmpq_mpoly_set(gp, g, ctx); fmpq_mpoly_derivative(gp, gp, idx, ctx); fmpq_mpoly_assert_canonical(gp, ctx); fmpq_mpoly_mul(t1, f, gp, ctx); fmpq_mpoly_assert_canonical(t1, ctx); fmpq_mpoly_mul(t2, g, fp, ctx); fmpq_mpoly_assert_canonical(t2, ctx); fmpq_mpoly_add(t1, t1, t2, ctx); fmpq_mpoly_assert_canonical(t1, ctx); result = fmpq_mpoly_equal(h, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg with aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(fp, ctx); fmpq_mpoly_clear(gp, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); } /* Check d(int(f)) = f with aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, f1; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(f1, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(f1, state, len1, coeff_bits, exp_bits1, ctx); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); idx = n_randint(state, nvars); fmpq_mpoly_set(g, f, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_integral(f1, f, idx, ctx); fmpq_mpoly_assert_canonical(f1, ctx); fmpq_mpoly_integral(f, f, idx, ctx); fmpq_mpoly_assert_canonical(f, ctx); result = fmpq_mpoly_equal(f, f1, ctx); fmpq_mpoly_derivative(f, f, idx, ctx); fmpq_mpoly_assert_canonical(f, ctx); result = result && fmpq_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(int(f)) = f with aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(f1, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-div.c000066400000000000000000000312241461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_div, state) { slong i, j, tmul = 10; { fmpq_mpoly_t f, g, p, q; fmpq_mpoly_ctx_t ctx; const char * vars[] = {"x", "y", "z", "t", "u"}; fmpq_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(p, ctx); fmpq_mpoly_init(q, ctx); fmpq_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)^6", vars, ctx); fmpq_mpoly_set_str_pretty(g, "(1+u+t+2*z^2+3*y^3+5*x^5)^6", vars, ctx); fmpq_mpoly_mul(p, f, g, ctx); fmpq_mpoly_assert_canonical(p, ctx); fmpq_mpoly_div(q, p, g, ctx); fmpq_mpoly_assert_canonical(q, ctx); if (!fmpq_mpoly_equal(q, f, ctx)) { printf("FAIL\n"); flint_printf("Check example\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(p, ctx); fmpq_mpoly_clear(q, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check f*g/g = f */ for (i = 0; i < 10 * tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_div(k, h, g, ctx); fmpq_mpoly_assert_canonical(k, ctx); if (!fmpq_mpoly_equal(k, f, ctx)) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni=%wd j=%wd\n",i,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check output agrees with divrem for random polys */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong nvars; fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 70); max_bound = 1 + 400/FLINT_MAX(WORD(1), nvars)/FLINT_MAX(WORD(1), nvars); exp_bound = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_randtest_bounds(k, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_inflate(f, f, shifts, strides, ctx); fmpq_mpoly_inflate(g, g, shifts, strides, ctx); fmpq_mpoly_divrem(h, r, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_div(k, f, g, ctx); fmpq_mpoly_assert_canonical(k, ctx); if (!fmpq_mpoly_equal(k, h, ctx)) { printf("FAIL\n"); flint_printf("Check output agrees with divrem\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (j = 0; j < nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_clear(r, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong nvars; fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 70); max_bound = 1 + 400/FLINT_MAX(WORD(1), nvars)/FLINT_MAX(WORD(1), nvars); exp_bound = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_inflate(f, f, shifts, strides, ctx); fmpq_mpoly_inflate(g, g, shifts, strides, ctx); fmpq_mpoly_divrem(h, r, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_div(f, f, g, ctx); fmpq_mpoly_assert_canonical(f, ctx); if (!fmpq_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (j = 0; j < nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(r, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong nvars; fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 70); max_bound = 1 + 400/FLINT_MAX(WORD(1), nvars)/FLINT_MAX(WORD(1), nvars); exp_bound = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_inflate(f, f, shifts, strides, ctx); fmpq_mpoly_inflate(g, g, shifts, strides, ctx); fmpq_mpoly_divrem(h, r, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_div(f, f, g, ctx); fmpq_mpoly_assert_canonical(f, ctx); if (!fmpq_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (j = 0; j < nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(r, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-divides.c000066400000000000000000000310021461254215100206140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_divides, state) { int i, j, result, ok1, ok2; /* Check f*g/g = f */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); ok1 = fmpq_mpoly_divides(k, h, g, ctx); fmpq_mpoly_assert_canonical(k, ctx); result = (ok1 && fmpq_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check random polys don't divide */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2, maxbits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; maxbits = 10/FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)) + 2; exp_bits = n_randint(state, maxbits) + 1; exp_bits1 = n_randint(state, maxbits) + 1; exp_bits2 = n_randint(state, maxbits) + 1; exp_bound = n_randbits(state, exp_bits); exp_bound1 = n_randbits(state, exp_bits1); exp_bound2 = n_randbits(state, exp_bits2); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpq_mpoly_divides(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); if (ok1) { fmpq_mpoly_mul(k, h, g, ctx); fmpq_mpoly_assert_canonical(k, ctx); } result = (ok1 == 0 || fmpq_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check random polys don't divide\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing first argument, exact division */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); ok1 = fmpq_mpoly_divides(k, h, g, ctx); fmpq_mpoly_assert_canonical(k, ctx); ok2 = fmpq_mpoly_divides(h, h, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); result = (ok1 == 1 && ok2 == 1 && fmpq_mpoly_equal(h, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument, exact division\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing, first argument, random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2, maxbits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; maxbits = 10/FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)) + 2; exp_bits = n_randint(state, maxbits) + 1; exp_bits1 = n_randint(state, maxbits) + 1; exp_bits2 = n_randint(state, maxbits) + 1; exp_bound = n_randbits(state, exp_bits); exp_bound1 = n_randbits(state, exp_bits1); exp_bound2 = n_randbits(state, exp_bits2); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpq_mpoly_divides(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); ok2 = fmpq_mpoly_divides(f, f, g, ctx); fmpq_mpoly_assert_canonical(f, ctx); result = ((ok1 == ok2) && (ok1 == 0 || fmpq_mpoly_equal(f, h, ctx))); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing, first argument, random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing second argument, exact division */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); ok1 = fmpq_mpoly_divides(k, h, g, ctx); fmpq_mpoly_assert_canonical(k, ctx); ok2 = fmpq_mpoly_divides(g, h, g, ctx); fmpq_mpoly_assert_canonical(g, ctx); result = (ok1 == 1 && ok2 == 1 && fmpq_mpoly_equal(g, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument, exact division\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing, second argument, random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2, maxbits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; maxbits = 10/FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)) + 2; exp_bits = n_randint(state, maxbits) + 1; exp_bits1 = n_randint(state, maxbits) + 1; exp_bits2 = n_randint(state, maxbits) + 1; exp_bound = n_randbits(state, exp_bits); exp_bound1 = n_randbits(state, exp_bits1); exp_bound2 = n_randbits(state, exp_bits2); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpq_mpoly_divides(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); ok2 = fmpq_mpoly_divides(g, f, g, ctx); fmpq_mpoly_assert_canonical(g, ctx); result = ((ok1 == ok2) && (ok1 == 0 || fmpq_mpoly_equal(g, h, ctx))); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing, second argument, random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-divrem.c000066400000000000000000000316431461254215100204660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_divrem, state) { int i, j, result; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k, r; slong len, len1, len2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(r, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_divrem(k, r, h, g, ctx); fmpq_mpoly_assert_canonical(k, ctx); fmpq_mpoly_assert_canonical(r, ctx); result = fmpq_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_clear(r, ctx); } /* Check f = g*q + r for random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)); exp_bound = n_randint(state, 25/n + 1) + 2; exp_bound1 = n_randint(state, 35/n + 1) + 4; exp_bound2 = n_randint(state, 30/n + 1) + 2; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_divrem(h, r, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_assert_canonical(r, ctx); fmpq_mpoly_remainder_test(r, g, ctx); fmpq_mpoly_mul(k, h, g, ctx); fmpq_mpoly_add(k, k, r, ctx); fmpq_mpoly_assert_canonical(k, ctx); result = fmpq_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_clear(r, ctx); } /* Check f = g*q + r for random polys, alias quotient and numerator */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)); exp_bound = n_randint(state, 35/n + 1) + 2; exp_bound1 = n_randint(state, 35/n + 1) + 4; exp_bound2 = n_randint(state, 30/n + 1) + 2; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_set(h, f, ctx); fmpq_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_divrem(h, r, h, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_assert_canonical(r, ctx); fmpq_mpoly_remainder_test(r, g, ctx); fmpq_mpoly_mul(k, h, g, ctx); fmpq_mpoly_add(k, k, r, ctx); fmpq_mpoly_assert_canonical(k, ctx); result = fmpq_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys, alias quotient and numerator\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_clear(r, ctx); } /* Check f = g*q + r for random polys, alias quotient and denominator */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)); exp_bound = n_randint(state, 25/n + 1) + 2; exp_bound1 = n_randint(state, 35/n + 1) + 4; exp_bound2 = n_randint(state, 30/n + 1) + 2; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_set(h, g, ctx); fmpq_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_divrem(h, r, f, h, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_assert_canonical(r, ctx); fmpq_mpoly_remainder_test(r, g, ctx); fmpq_mpoly_mul(k, h, g, ctx); fmpq_mpoly_add(k, k, r, ctx); fmpq_mpoly_assert_canonical(k, ctx); result = fmpq_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys, alias quotient and numerator\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_clear(r, ctx); } /* Check f = g*q + r for random polys, alias remainder and denominator */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)); exp_bound = n_randint(state, 25/n + 1) + 2; exp_bound1 = n_randint(state, 35/n + 1) + 4; exp_bound2 = n_randint(state, 30/n + 1) + 2; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_set(r, g, ctx); fmpq_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_divrem(h, r, f, r, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_assert_canonical(r, ctx); fmpq_mpoly_remainder_test(r, g, ctx); fmpq_mpoly_mul(k, h, g, ctx); fmpq_mpoly_add(k, k, r, ctx); fmpq_mpoly_assert_canonical(k, ctx); result = fmpq_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys, alias quotient and numerator\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_clear(r, ctx); } /* Check f = g*q + r for random polys, alias remainder and numerator */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)); exp_bound = n_randint(state, 25/n + 1) + 2; exp_bound1 = n_randint(state, 35/n + 1) + 4; exp_bound2 = n_randint(state, 30/n + 1) + 2; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(g, ctx)); fmpq_mpoly_set(r, f, ctx); fmpq_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_divrem(h, r, r, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_assert_canonical(r, ctx); fmpq_mpoly_remainder_test(r, g, ctx); fmpq_mpoly_mul(k, h, g, ctx); fmpq_mpoly_add(k, k, r, ctx); fmpq_mpoly_assert_canonical(k, ctx); result = fmpq_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys, alias quotient and numerator\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_clear(r, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-divrem_ideal.c000066400000000000000000000167771461254215100216370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_divrem_ideal, state) { int i, j, w, result; /* Check s*f = g1*q1 + ... + gn*qn + r for random polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, r, k1, k2; fmpq_mpoly_struct * g, * q; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; fmpq_mpoly_struct * qarr[5], * darr[5]; fmpz * shifts, * strides; num = n_randint(state, 5) + 1; g = (fmpq_mpoly_struct *) flint_malloc(num*sizeof(fmpq_mpoly_struct)); q = (fmpq_mpoly_struct *) flint_malloc(num*sizeof(fmpq_mpoly_struct)); fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = fmpq_mpoly_ctx_nvars(ctx); for (w = 0; w < num; w++) { fmpq_mpoly_init(g + w, ctx); darr[w] = g + w; fmpq_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(k1, ctx); fmpq_mpoly_init(k2, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 12); len2 = n_randint(state, 8) + 1; exp_bound = n_randint(state, 10/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound1 = n_randint(state, 25/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound2 = n_randint(state, 20/FLINT_MAX(WORD(1), nvars) + 1) + 1; coeff_bits = n_randint(state, 40); shifts = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) { fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpq_mpoly_inflate(f, f, shifts, strides, ctx); fmpq_mpoly_assert_canonical(f, ctx); for (w = 0; w < num; w++) { do { fmpq_mpoly_randtest_bound(darr[w], state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(darr[w], ctx)); fmpq_mpoly_inflate(darr[w], darr[w], shifts, strides, ctx); fmpq_mpoly_assert_canonical(darr[w], ctx); fmpq_mpoly_randtest_bound(qarr[w], state, len, coeff_bits, exp_bound, ctx); } fmpq_mpoly_randtest_bound(k1, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_randtest_bound(k2, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_divrem_ideal(qarr, r, f, darr, num, ctx); fmpq_mpoly_assert_canonical(r, ctx); fmpq_mpoly_set(k2, r, ctx); for (w = 0; w < num; w++) { fmpq_mpoly_assert_canonical(qarr[w], ctx); fmpq_mpoly_remainder_test(r, darr[w], ctx); fmpq_mpoly_mul(k1, qarr[w], darr[w], ctx); fmpq_mpoly_add(k2, k2, k1, ctx); } result = fmpq_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check s*f = g1*q1 + ... + gn*qn + r\ni=%wd j=%wd\n",i,j); fflush(stdout); flint_abort(); } } for (j = 0; j < nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); for (w = 0; w < num; w++) fmpq_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpq_mpoly_clear(darr[w], ctx); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(k1, ctx); fmpq_mpoly_clear(k2, ctx); fmpq_mpoly_clear(r, ctx); flint_free(g); flint_free(q); } /* Check aliasing of remainder */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, r, k1, k2; fmpq_mpoly_struct * g, * q; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; fmpq_mpoly_struct * qarr[5], * darr[5]; num = n_randint(state, 5) + 1; g = (fmpq_mpoly_struct *) flint_malloc(num*sizeof(fmpq_mpoly_struct)); q = (fmpq_mpoly_struct *) flint_malloc(num*sizeof(fmpq_mpoly_struct)); fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = fmpq_mpoly_ctx_nvars(ctx); for (w = 0; w < num; w++) { fmpq_mpoly_init(g + w, ctx); darr[w] = g + w; fmpq_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(k1, ctx); fmpq_mpoly_init(k2, ctx); fmpq_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 12); len2 = n_randint(state, 8) + 1; exp_bound = n_randint(state, 10/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound1 = n_randint(state, 25/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound2 = n_randint(state, 20/FLINT_MAX(WORD(1), nvars) + 1) + 1; coeff_bits = n_randint(state, 40); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); for (w = 0; w < num; w++) { do { fmpq_mpoly_randtest_bound(darr[w], state, len2, coeff_bits + 1, exp_bound2, ctx); } while (fmpq_mpoly_is_zero(darr[w], ctx)); fmpq_mpoly_randtest_bound(qarr[w], state, len, coeff_bits, exp_bound, ctx); } fmpq_mpoly_randtest_bound(k1, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_randtest_bound(k2, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_set(r, f, ctx); fmpq_mpoly_divrem_ideal(qarr, r, r, darr, num, ctx); fmpq_mpoly_assert_canonical(r, ctx); fmpq_mpoly_set(k2, r, ctx); for (w = 0; w < num; w++) { fmpq_mpoly_assert_canonical(qarr[w], ctx); fmpq_mpoly_remainder_test(r, darr[w], ctx); fmpq_mpoly_mul(k1, qarr[w], darr[w], ctx); fmpq_mpoly_add(k2, k2, k1, ctx); } result = fmpq_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder\ni=%wd j=%wd\n",i,j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) fmpq_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpq_mpoly_clear(darr[w], ctx); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(k1, ctx); fmpq_mpoly_clear(k2, ctx); fmpq_mpoly_clear(r, ctx); flint_free(g); flint_free(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-equal_is_fmpq.c000066400000000000000000000214241461254215100220210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_equal_is_fmpq, state) { int result; { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpq_t q, r; fmpz_t a, b; const char * vars[] = {"x","y","z"}; fmpq_mpoly_ctx_init(ctx, 3, ORD_DEGLEX); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_init(q); fmpq_init(r); fmpz_init(a); fmpz_init(b); result = 1; fmpq_mpoly_set_str_pretty(f, "0", vars, ctx); fmpq_set_si(q, WORD(0), WORD(1)); result = result && fmpq_mpoly_equal_fmpq(f, q, ctx); fmpz_set_si(a, WORD(0)); result = result && fmpq_mpoly_equal_fmpz(f, a, ctx); result = result && fmpq_mpoly_equal_ui(f, UWORD(0), ctx); result = result && fmpq_mpoly_equal_si(f, WORD(0), ctx); result = result && fmpq_mpoly_is_fmpq(f, ctx); fmpq_mpoly_get_fmpq(r, f, ctx); result = result && fmpq_is_zero(r); result = result && !fmpq_mpoly_is_gen(f, WORD(0), ctx); result = result && !fmpq_mpoly_is_gen(f, -WORD(1), ctx); result = result && (fmpq_mpoly_length(f, ctx) == WORD(0)); if (!result) { printf("FAIL\n"); flint_printf("test 1\n"); fflush(stdout); flint_abort(); } result = 1; fmpq_mpoly_set_str_pretty(f, "1", vars, ctx); fmpq_set_si(q, WORD(1), WORD(1)); result = result && fmpq_mpoly_equal_fmpq(f, q, ctx); fmpz_set_si(a, WORD(1)); result = result && fmpq_mpoly_equal_fmpz(f, a, ctx); result = result && fmpq_mpoly_equal_ui(f, UWORD(1), ctx); result = result && fmpq_mpoly_equal_si(f, WORD(1), ctx); result = result && fmpq_mpoly_is_fmpq(f, ctx); fmpq_mpoly_get_fmpq(r, f, ctx); result = result && fmpq_is_one(r); fmpq_mpoly_get_coeff_fmpq_monomial(r, f, f, ctx); result = result && fmpq_is_one(r); result = result && !fmpq_mpoly_is_gen(f, WORD(0), ctx); result = result && !fmpq_mpoly_is_gen(f, -WORD(1), ctx); result = result && (fmpq_mpoly_length(f, ctx) == WORD(1)); if (!result) { printf("FAIL\n"); flint_printf("test 2\n"); fflush(stdout); flint_abort(); } result = 1; fmpq_mpoly_set_str_pretty(f, "2/3", vars, ctx); fmpq_set_si(q, WORD(2), WORD(3)); result = result && fmpq_mpoly_equal_fmpq(f, q, ctx); fmpz_set_si(a, WORD(2)); result = result && !fmpq_mpoly_equal_fmpz(f, a, ctx); result = result && !fmpq_mpoly_equal_ui(f, UWORD(2), ctx); result = result && !fmpq_mpoly_equal_si(f, WORD(2), ctx); result = result && fmpq_mpoly_is_fmpq(f, ctx); fmpq_mpoly_get_fmpq(r, f, ctx); result = result && fmpq_equal(r, q); result = result && !fmpq_mpoly_is_gen(f, WORD(0), ctx); result = result && !fmpq_mpoly_is_gen(f, -WORD(1), ctx); result = result && (fmpq_mpoly_length(f, ctx) == WORD(1)); if (!result) { printf("FAIL\n"); flint_printf("test 3\n"); fflush(stdout); flint_abort(); } result = 1; fmpq_mpoly_set_str_pretty(f, "x", vars, ctx); fmpq_set_si(q, WORD(1), WORD(1)); result = result && !fmpq_mpoly_equal_fmpq(f, q, ctx); fmpz_set_si(a, WORD(1)); result = result && !fmpq_mpoly_equal_fmpz(f, a, ctx); result = result && !fmpq_mpoly_equal_ui(f, UWORD(1), ctx); result = result && !fmpq_mpoly_equal_si(f, WORD(1), ctx); result = result && !fmpq_mpoly_is_fmpq(f, ctx); result = result && fmpq_mpoly_is_gen(f, WORD(0), ctx); result = result && fmpq_mpoly_is_gen(f, -WORD(1), ctx); result = result && (fmpq_mpoly_length(f, ctx) == WORD(1)); if (!result) { printf("FAIL\n"); flint_printf("test 4\n"); fflush(stdout); flint_abort(); } result = 1; fmpq_mpoly_set_str_pretty(f, "2/3*x*z", vars, ctx); fmpq_mpoly_set_str_pretty(g, "2*x*z", vars, ctx); fmpq_mpoly_set_str_pretty(h, "2*x*z*y^2", vars, ctx); fmpq_set_si(q, WORD(2), WORD(3)); result = result && !fmpq_mpoly_equal_fmpq(f, q, ctx); fmpq_mpoly_get_denominator(a, f, ctx); result = result && fmpz_equal_si(a, WORD(3)); fmpq_mpoly_get_denominator(a, g, ctx); result = result && fmpz_equal_si(a, WORD(1)); fmpz_set_si(a, WORD(1)); result = result && !fmpq_mpoly_equal_fmpz(f, a, ctx); result = result && !fmpq_mpoly_equal_ui(f, UWORD(1), ctx); result = result && !fmpq_mpoly_equal_si(f, WORD(1), ctx); result = result && !fmpq_mpoly_is_gen(f, WORD(0), ctx); result = result && !fmpq_mpoly_is_gen(f, -WORD(1), ctx); result = result && (fmpq_mpoly_length(f, ctx) == WORD(1)); fmpq_mpoly_get_coeff_fmpq_monomial(r, f, g, ctx); result = result && fmpq_equal(r, q); fmpq_mpoly_get_coeff_fmpq_monomial(r, f, h, ctx); result = result && fmpq_is_zero(r); if (!result) { printf("FAIL\n"); flint_printf("test 5\n"); fflush(stdout); flint_abort(); } result = 1; fmpq_mpoly_set_str_pretty(f, "2/3*x*z+3/5*x^999999999999999999999*y*z", vars, ctx); fmpq_mpoly_set_str_pretty(g, "-x*z", vars, ctx); fmpq_mpoly_set_str_pretty(h, "x^999999999999999999999*y*z", vars, ctx); fmpq_set_si(q, WORD(2), WORD(3)); result = result && !fmpq_mpoly_equal_fmpq(f, q, ctx); fmpq_mpoly_get_denominator(a, f, ctx); result = result && fmpz_equal_si(a, WORD(15)); fmpq_mpoly_get_denominator(a, g, ctx); result = result && fmpz_equal_si(a, WORD(1)); fmpz_set_si(a, WORD(1)); result = result && !fmpq_mpoly_equal_fmpz(f, a, ctx); result = result && !fmpq_mpoly_equal_ui(f, UWORD(1), ctx); result = result && !fmpq_mpoly_equal_si(f, WORD(1), ctx); result = result && !fmpq_mpoly_is_gen(f, WORD(0), ctx); result = result && !fmpq_mpoly_is_gen(f, -WORD(1), ctx); result = result && (fmpq_mpoly_length(f, ctx) != WORD(1)); fmpq_mpoly_get_coeff_fmpq_monomial(r, f, g, ctx); fmpq_set_si(q, WORD(2), WORD(3)); result = result && fmpq_equal(r, q); fmpq_mpoly_get_coeff_fmpq_monomial(r, f, h, ctx); fmpq_set_si(q, WORD(3), WORD(5)); result = result && fmpq_equal(r, q); result = result && fmpq_mpoly_divides(g, h, g, ctx); fmpq_mpoly_get_coeff_fmpq_monomial(r, f, g, ctx); result = result && fmpq_is_zero(r); if (!result) { printf("FAIL\n"); flint_printf("test 6\n"); fflush(stdout); flint_abort(); } result = 1; fmpq_mpoly_set_str_pretty(f, "0", vars, ctx); fmpq_mpoly_set_str_pretty(g, "2*x^2", vars, ctx); fmpq_set_si(q, WORD(2), WORD(3)); fmpq_mpoly_set_coeff_fmpq_monomial(f, q, g, ctx); fmpq_mpoly_set_str_pretty(g, "2*y^3", vars, ctx); fmpq_set_si(q, WORD(3), WORD(5)); fmpq_mpoly_set_coeff_fmpq_monomial(f, q, g, ctx); fmpq_mpoly_set_str_pretty(g, "2*z", vars, ctx); fmpq_set_si(q, WORD(7), WORD(1)); fmpq_mpoly_set_coeff_fmpq_monomial(f, q, g, ctx); fmpq_mpoly_set_str_pretty(g, "2*y^3", vars, ctx); fmpq_set_si(q, -WORD(3), WORD(5)); fmpq_mpoly_set_coeff_fmpq_monomial(f, q, g, ctx); fmpq_mpoly_set_str_pretty(g, "-2", vars, ctx); fmpq_set_si(q, -WORD(6), WORD(11)); fmpq_mpoly_set_coeff_fmpq_monomial(f, q, g, ctx); fmpq_mpoly_set_str_pretty(h, "2/3*x^2 - 3/5*y^3 + 7*z - 6/11", vars, ctx); result = fmpq_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("test 7\n"); fflush(stdout); flint_abort(); } fmpz_clear(b); fmpz_clear(a); fmpq_clear(r); fmpq_clear(q); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-evaluate.c000066400000000000000000000200101461254215100207700ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_evaluate, state) { slong i, j, v; /* Check repeated evalone matches evalall */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; fmpq_t fe; fmpq ** vals; slong * perm; slong nvars; slong len1, exp_bound1; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx); fmpq_init(fe); perm = (slong *) flint_malloc(nvars*sizeof(slong)); len1 = n_randint(state, 50); exp_bound1 = n_randint(state, 10) + 1; coeff_bits = n_randint(state, 100) + 1; vals = (fmpq **) flint_malloc(nvars*sizeof(fmpq*)); for (v = 0; v < nvars; v++) { vals[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals[v]); fmpq_randtest(vals[v], state, 10); perm[v] = v; } for (j = 0; j < 2*nvars; j++) { slong a, b, c; a = n_randint(state, nvars); b = n_randint(state, nvars); c = perm[a]; perm[a] = perm[b]; perm[b] = c; } for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); if (!fmpq_mpoly_evaluate_all_fmpq(fe, f, vals, ctx)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } for (v = 0; v < nvars; v++) { if (!fmpq_mpoly_evaluate_one_fmpq(f, f, perm[v], vals[perm[v]], ctx)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(f, ctx); } if (!fmpq_mpoly_equal_fmpq(f, fe, ctx)) { printf("FAIL\n"); flint_printf("Check repeated evalone matches evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpq_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpq_mpoly_clear(f, ctx); fmpq_clear(fe); flint_free(perm); } /* Check multiprecision repeated evalone matches evalall */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; fmpq_t fe; fmpq ** vals; slong * perm; slong nvars; slong len1; flint_bitcnt_t exp_bits, coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx); fmpq_init(fe); perm = (slong *) flint_malloc(nvars*sizeof(slong)); len1 = n_randint(state, 50); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200) + 1; vals = (fmpq **) flint_malloc(nvars*sizeof(fmpq*)); for (v = 0; v < nvars; v++) { /* only evaluate at 0, 1, or -1 */ vals[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals[v]); fmpq_set_si(vals[v], n_randint(state, UWORD(3)) - WORD(1), UWORD(1)); perm[v] = v; } for (j = 0; j < 2*nvars; j++) { slong a, b, c; a = n_randint(state, nvars); b = n_randint(state, nvars); c = perm[a]; perm[a] = perm[b]; perm[b] = c; } for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx); if (!fmpq_mpoly_evaluate_all_fmpq(fe, f, vals, ctx)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } for (v = 0; v < nvars; v++) { if (!fmpq_mpoly_evaluate_one_fmpq(f, f, perm[v], vals[perm[v]], ctx)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(f, ctx); } if (!fmpq_mpoly_equal_fmpq(f, fe, ctx)) { printf("FAIL\n"); flint_printf("Check multiprecision repeated evalone matches evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpq_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpq_mpoly_clear(f, ctx); fmpq_clear(fe); flint_free(perm); } /* Check addition commutes with evalall */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, fg; fmpq_t fe, ge, fge, t; fmpq ** vals; slong nvars, len1, len2, exp_bound1, exp_bound2; flint_bitcnt_t coeff_bits; slong n; fmpq_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->zctx->minfo->nvars; fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(fg, ctx); fmpq_init(fe); fmpq_init(ge); fmpq_init(fge); fmpq_init(t); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), nvars); exp_bound1 = n_randint(state, 2000/n/n) + 1; exp_bound2 = n_randint(state, 2000/n/n) + 1; coeff_bits = n_randint(state, 100); vals = (fmpq **) flint_malloc(nvars*sizeof(fmpq*)); for (v = 0; v < nvars; v++) { vals[v] = (fmpq *) flint_malloc(sizeof(fmpq)); fmpq_init(vals[v]); fmpq_randbits(vals[v], state, 10); } for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpq_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpq_mpoly_add(fg, f, g, ctx); if (!fmpq_mpoly_evaluate_all_fmpq(fe, f, vals, ctx) || !fmpq_mpoly_evaluate_all_fmpq(ge, g, vals, ctx) || !fmpq_mpoly_evaluate_all_fmpq(fge, fg, vals, ctx)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpq_add(t, fe, ge); if (!fmpq_equal(t, fge)) { printf("FAIL\n"); flint_printf("Check addition commutes with evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpq_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(fg, ctx); fmpq_clear(fe); fmpq_clear(ge); fmpq_clear(fge); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-gcd.c000066400000000000000000000621101461254215100177260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd void gcd_check( fmpq_mpoly_t g, fmpq_mpoly_t a, fmpq_mpoly_t b, const fmpq_mpoly_t gdiv, fmpq_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpq_mpoly_t ca, cb, cg; fmpq_mpoly_init(ca, ctx); fmpq_mpoly_init(cb, ctx); fmpq_mpoly_init(cg, ctx); res = fmpq_mpoly_gcd(g, a, b, ctx); fmpq_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_zero(gdiv, ctx)) { if (!fmpq_mpoly_divides(ca, g, gdiv, ctx)) { printf("FAIL\n"); flint_printf("Check divisor of gcd\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(a, ctx) || !fmpq_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpq_mpoly_is_monic(g, ctx)) { printf("FAIL\n"); flint_printf("Check gcd is monic\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if ((i + j % 11) == 0) { fmpq_mpoly_set(cg, b, ctx); fmpq_mpoly_gcd(cg, cg, a, ctx); if (!fmpq_mpoly_equal(cg, g, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing 1\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if ((i + j % 9) == 0) { fmpq_mpoly_set(cg, b, ctx); fmpq_mpoly_gcd(cg, a, cg, ctx); if (!fmpq_mpoly_equal(cg, g, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing 2\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } res = 1; res = res && fmpq_mpoly_divides(ca, a, g, ctx); res = res && fmpq_mpoly_divides(cb, b, g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check divisibility\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpq_mpoly_gcd(cg, ca, cb, ctx); fmpq_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpq_mpoly_gcd, state) { const slong max_threads = 5; slong i, j, k, tmul = 5; { int success; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t g, a, b; const char * vars[] = {"x" ,"y", "z", "t"}; fmpq_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_set_str_pretty(a, "x^3 + 1", vars, ctx); fmpq_mpoly_set_str_pretty(b, "x^9999999999999999999999 + x^3333333333333333333333 + x", vars, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); success = fmpq_mpoly_gcd(g, a, b, ctx); if (success) { printf("FAIL\n"); flint_printf("Check non-example\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_ctx_clear(ctx); } /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bits(t, state, 1, coeff_bits + 1, exp_bits, ctx); } while (t->zpoly->length != 1); fmpq_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(b, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "monomial"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t1, t2; slong len, len1; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bits(t1, state, 1, coeff_bits + 1, exp_bits1, ctx); } while (t1->zpoly->length != 1); do { fmpq_mpoly_randtest_bits(t2, state, 1, coeff_bits + 1, exp_bits2, ctx); } while (t2->zpoly->length != 1); fmpq_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(b, a, t1, ctx); fmpq_mpoly_mul(t2, a, t2, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, t2, b, a, ctx, i, j, "monomial cofactors"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); fmpq_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t c; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(c); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(t1, state, len1, coeff_bits + 1, exp_bound1, ctx); fmpq_mpoly_randtest_bound(t2, state, len2, coeff_bits + 1, exp_bound2, ctx); fmpq_mpoly_mul(b, t1, t2, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpq_mpoly_scalar_mul_fmpz(a, t2, c, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpq_mpoly_scalar_mul_fmpz(b, b, c, ctx); fmpq_mpoly_randtest_bound(g, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); if ((j%2) == 0) fmpq_mpoly_swap(a, b, ctx); gcd_check(g, a, b, t2, ctx, i, j, "one input divides the other"); } fmpz_clear(c); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); fmpq_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 30/(2*ctx->zctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "sparse inputs"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t coeff_bits, newbits; slong len, len1, len2; slong degbound; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 30/(2*ctx->zctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(b, b, newbits, ctx); } fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "sparse input with repacking"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 30/(2*ctx->zctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpq_mpoly_inflate(a, a, shifts1, strides, ctx); fmpq_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpq_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpq_mpoly_ctx_init_rand(ctx, state, 4); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); } bits4 = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); coeff_bits2 = n_randint(state, 200); coeff_bits3 = n_randint(state, 200); coeff_bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpq_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "dense input"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t newbits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpq_mpoly_ctx_init_rand(ctx, state, 4); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); } bits4 = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); coeff_bits2 = n_randint(state, 200); coeff_bits3 = n_randint(state, 200); coeff_bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpq_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(b, b, newbits, ctx); } fmpq_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "dense input with repacking"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpq_mpoly_ctx_init_rand(ctx, state, 4); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->zctx->minfo->nvars); } bits4 = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); coeff_bits2 = n_randint(state, 200); coeff_bits3 = n_randint(state, 200); coeff_bits4 = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpq_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpq_mpoly_inflate(a, a, shifts1, strides, ctx); fmpq_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpq_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpq_mpoly/test/t-gcd_brown.c000066400000000000000000000120271461254215100211370ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_brown void gcd_check( fmpq_mpoly_t g, fmpq_mpoly_t a, fmpq_mpoly_t b, fmpq_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpq_mpoly_t ca, cb, cg; fmpq_mpoly_init(ca, ctx); fmpq_mpoly_init(cb, ctx); fmpq_mpoly_init(cg, ctx); res = fmpq_mpoly_gcd_brown(g, a, b, ctx); fmpq_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(a, ctx) || !fmpq_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpq_mpoly_is_monic(g, ctx)) { printf("FAIL\n"); flint_printf("Check gcd has positive lc\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpq_mpoly_divides(ca, a, g, ctx); res = res && fmpq_mpoly_divides(cb, b, g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check divisibility\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpq_mpoly_gcd_brown(cg, ca, cb, ctx); fmpq_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpq_mpoly_gcd_brown, state) { slong tmul = 10; slong i, j; { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t g, a, b; const char * vars[] = {"x", "y", "z"}; fmpq_mpoly_ctx_init(ctx, 3, ORD_LEX); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_set_str_pretty(a, "(x+y+z^2)*(x-y^9+z^3)", vars, ctx); fmpq_mpoly_set_str_pretty(b, "(x+y+z^2)*(x^9+y+z^2)", vars, ctx); gcd_check(g, a, b, ctx, 0, 0, "example"); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; slong n; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); len = n_randint(state, 40) + 1; len1 = n_randint(state, 60); len2 = n_randint(state, 60); n = FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)); degbound = 1 + 50/n/n; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(g, state, len, coeff_bits + 1, degbound, ctx); if (fmpq_mpoly_is_zero(g, ctx)) fmpq_mpoly_one(g, ctx); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, g, ctx); fmpq_mpoly_mul(b, b, g, ctx); fmpq_mpoly_scalar_mul_ui(a, a, n_randint(state, 10) + 1, ctx); fmpq_mpoly_scalar_mul_ui(b, b, n_randint(state, 10) + 1, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, ctx, i, j, "random dense"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpq_mpoly/test/t-gcd_cofactors.c000066400000000000000000001010711461254215100217710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_cofactors void gcd_check( fmpq_mpoly_t g, fmpq_mpoly_t abar, fmpq_mpoly_t bbar, fmpq_mpoly_t a, fmpq_mpoly_t b, const fmpq_mpoly_t gdiv, fmpq_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpq_mpoly_t ca, cb, cg, u, v, w; fmpq_mpoly_init(ca, ctx); fmpq_mpoly_init(cb, ctx); fmpq_mpoly_init(cg, ctx); fmpq_mpoly_init(u, ctx); fmpq_mpoly_init(v, ctx); fmpq_mpoly_init(w, ctx); res = fmpq_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_assert_canonical(abar, ctx); fmpq_mpoly_assert_canonical(bbar, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_zero(gdiv, ctx)) { if (!fmpq_mpoly_divides(ca, g, gdiv, ctx)) { printf("FAIL\n"); flint_printf("Check divisor of gcd\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } fmpq_mpoly_mul(ca, g, abar, ctx); fmpq_mpoly_mul(cb, g, bbar, ctx); if (!fmpq_mpoly_equal(ca, a, ctx) || !fmpq_mpoly_equal(cb, b, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(a, ctx) || !fmpq_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpq_mpoly_is_monic(g, ctx)) { printf("FAIL\n"); flint_printf("Check gcd is monic\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(u, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, a, u, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(v, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, a, v, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(w, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, a, w, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(u, a, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, u, b, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(v, a, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, v, b, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(w, a, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, w, b, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(u, a, ctx); fmpq_mpoly_set(v, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, u, v, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(v, a, ctx); fmpq_mpoly_set(u, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, v, u, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(u, a, ctx); fmpq_mpoly_set(w, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, u, w, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(w, a, ctx); fmpq_mpoly_set(u, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, w, u, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(v, a, ctx); fmpq_mpoly_set(w, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, v, w, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_set(w, a, ctx); fmpq_mpoly_set(v, b, ctx); fmpq_mpoly_gcd_cofactors(u, v, w, w, v, ctx); fmpq_mpoly_assert_canonical(u, ctx); fmpq_mpoly_assert_canonical(v, ctx); fmpq_mpoly_assert_canonical(w, ctx); if (!fmpq_mpoly_equal(g, u, ctx) || !fmpq_mpoly_equal(abar, v, ctx) || !fmpq_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpq_mpoly_gcd_cofactors(cg, ca, cb, abar, bbar, ctx); fmpq_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal(ca, abar, ctx) || !fmpq_mpoly_equal(cb, bbar, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors of cofactors\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpq_mpoly_gcd_cofactors(cg, abar, bbar, abar, bbar, ctx); fmpq_mpoly_assert_canonical(cg, ctx); if (!fmpq_mpoly_equal(ca, abar, ctx) || !fmpq_mpoly_equal(cb, bbar, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors of cofactors with aliasing\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); fmpq_mpoly_clear(u, ctx); fmpq_mpoly_clear(v, ctx); fmpq_mpoly_clear(w, ctx); } TEST_FUNCTION_START(fmpq_mpoly_gcd_cofactors, state) { const slong max_threads = 5; slong i, j, k, tmul = 3; { int success; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t g, abar, bbar, a, b; const char * vars[] = {"x" ,"y", "z", "t"}; fmpq_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_set_str_pretty(a, "x^3 + 1", vars, ctx); fmpq_mpoly_set_str_pretty(b, "x^9999999999999999999999 + x^3333333333333333333333 + x", vars, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); success = fmpq_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); if (success) { printf("FAIL\n"); flint_printf("Check non-example\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_ctx_clear(ctx); } /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bits(t, state, 1, coeff_bits + 1, exp_bits, ctx); } while (t->zpoly->length != 1); fmpq_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(b, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "monomial"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bits(t1, state, 1, coeff_bits + 1, exp_bits1, ctx); } while (t1->zpoly->length != 1); do { fmpq_mpoly_randtest_bits(t2, state, 1, coeff_bits + 1, exp_bits2, ctx); } while (t2->zpoly->length != 1); fmpq_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(b, a, t1, ctx); fmpq_mpoly_mul(t2, a, t2, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, t2, b, a, ctx, i, j, "monomial cofactors"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); fmpq_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t c; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(c); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(t1, state, len1, coeff_bits + 1, exp_bound1, ctx); fmpq_mpoly_randtest_bound(t2, state, len2, coeff_bits + 1, exp_bound2, ctx); fmpq_mpoly_mul(b, t1, t2, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpq_mpoly_scalar_mul_fmpz(a, t2, c, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpq_mpoly_scalar_mul_fmpz(b, b, c, ctx); fmpq_mpoly_randtest_bound(g, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); if ((j%2) == 0) fmpq_mpoly_swap(a, b, ctx); gcd_check(g, abar, bbar, a, b, t2, ctx, i, j, "one input divides the other"); } fmpz_clear(c); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); fmpq_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 10) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->zctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse inputs"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t coeff_bits, newbits; slong len, len1, len2; slong degbound; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 10) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->zctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(b, b, newbits, ctx); } fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with repacking"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t; flint_bitcnt_t coeff_bits; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 10) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->zctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpq_mpoly_inflate(a, a, shifts1, strides, ctx); fmpq_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpq_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpq_mpoly_ctx_init_rand(ctx, state, 4); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); } bits4 = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); coeff_bits2 = n_randint(state, 100); coeff_bits3 = n_randint(state, 100); coeff_bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpq_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpq_mpoly_ctx_init_rand(ctx, state, 4); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); } bits4 = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); coeff_bits2 = n_randint(state, 100); coeff_bits3 = n_randint(state, 100); coeff_bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpq_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->zpoly->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->zctx->minfo); fmpq_mpoly_repack_bits(b, b, newbits, ctx); } fmpq_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with repacking"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpq_mpoly_ctx_init_rand(ctx, state, 4); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(abar, ctx); fmpq_mpoly_init(bbar, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->zctx->minfo->nvars); } bits4 = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); coeff_bits2 = n_randint(state, 100); coeff_bits3 = n_randint(state, 100); coeff_bits4 = n_randint(state, 100); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpq_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->zpoly->length == 0); fmpq_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpq_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpq_mpoly_inflate(a, a, shifts1, strides, ctx); fmpq_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpq_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(abar, ctx); fmpq_mpoly_clear(bbar, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpq_mpoly/test/t-gcd_hensel.c000066400000000000000000000132021461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_hensel void gcd_check( fmpq_mpoly_t g, fmpq_mpoly_t a, fmpq_mpoly_t b, fmpq_mpoly_t t, fmpq_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpq_mpoly_t ca, cb, cg; fmpq_mpoly_init(ca, ctx); fmpq_mpoly_init(cb, ctx); fmpq_mpoly_init(cg, ctx); if (!fmpq_mpoly_gcd_hensel(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(g, ctx); if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(a, ctx) || !fmpq_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpq_mpoly_is_monic(g, ctx)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_zero(t, ctx) && !fmpq_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_divides(ca, a, g, ctx) || !fmpq_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_gcd_hensel(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(cg, ctx); if (!fmpq_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpq_mpoly_gcd_hensel, state) { slong i, j, tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t1, t2, t3; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 5); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); fmpq_mpoly_init(t3, ctx); degbound = 42/(2*fmpq_mpoly_ctx_nvars(ctx) - 1); degbounds = FLINT_ARRAY_ALLOC(fmpq_mpoly_ctx_nvars(ctx), ulong); degbounds1 = FLINT_ARRAY_ALLOC(fmpq_mpoly_ctx_nvars(ctx), ulong); degbounds2 = FLINT_ARRAY_ALLOC(fmpq_mpoly_ctx_nvars(ctx), ulong); for (j = 0; j < fmpq_mpoly_ctx_nvars(ctx); j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 6; j++) { len = n_randint(state, 10) + 1; len1 = n_randint(state, 10); len2 = n_randint(state, 15); coeff_bits = n_randint(state, 200) + 10; fmpq_mpoly_randtest_bounds(t1, state, coeff_bits, len, degbounds, ctx); coeff_bits = n_randint(state, 200) + 10; fmpq_mpoly_randtest_bounds(t2, state, coeff_bits, len1, degbounds1, ctx); coeff_bits = n_randint(state, 200) + 10; fmpq_mpoly_randtest_bounds(t3, state, coeff_bits, len2, degbounds2, ctx); switch (n_randint(state, 4)) { case 3: fmpq_mpoly_mul(t3, t1, t2, ctx); break; case 2: fmpq_mpoly_mul(t3, t3, t1, ctx); break; case 1: fmpq_mpoly_mul(t3, t3, t2, ctx); break; default: break; } fmpq_mpoly_mul(a, t1, t3, ctx); fmpq_mpoly_mul(b, t2, t3, ctx); coeff_bits = n_randint(state, 300) + 10; fmpq_mpoly_randtest_bits(g, state, coeff_bits, len, FLINT_BITS, ctx); if (fmpq_mpoly_length(a, ctx) < 4000 && fmpq_mpoly_length(b, ctx) < 4000) gcd_check(g, a, b, t3, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); fmpq_mpoly_clear(t3, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpq_mpoly/test/t-gcd_subresultant.c000066400000000000000000000130351461254215100225430ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_subresultant void gcd_check( fmpq_mpoly_t g, fmpq_mpoly_t a, fmpq_mpoly_t b, fmpq_mpoly_t t, fmpq_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpq_mpoly_t ca, cb, cg; fmpq_mpoly_init(ca, ctx); fmpq_mpoly_init(cb, ctx); fmpq_mpoly_init(cg, ctx); if (!fmpq_mpoly_gcd_subresultant(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(g, ctx); if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(a, ctx) || !fmpq_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpq_mpoly_is_monic(g, ctx)) { flint_printf("FAIL: check gcd is unit normal\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_zero(t, ctx) && !fmpq_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_divides(ca, a, g, ctx) || !fmpq_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_gcd_subresultant(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpq_mpoly_assert_canonical(cg, ctx); if (!fmpq_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpq_mpoly_gcd_subresultant, state) { slong i, j; slong tmul = 5; { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t g, a, b, t; const char * vars[] = {"x", "y", "z", "t"}; fmpq_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(t, ctx); fmpq_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpq_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpq_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, 0, 0, "example"); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 3); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 1 + 10/FLINT_MAX(WORD(1), fmpq_mpoly_ctx_nvars(ctx)); for (j = 0; j < 4; j++) { coeff_bits = 1 + n_randint(state, 80); fmpq_mpoly_randtest_bound(t, state, len, coeff_bits, degbound, ctx); if (fmpq_mpoly_is_zero(t, ctx)) fmpq_mpoly_one(t, ctx); coeff_bits = 1 + n_randint(state, 80); fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); coeff_bits = 1 + n_randint(state, 80); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); coeff_bits = 1 + n_randint(state, 80); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random small"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpq_mpoly/test/t-gcd_zippel.c000066400000000000000000000104571461254215100213200ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_gcd_zippel, state) { slong i, j; slong tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, ca, cb, cg, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; ulong degbound; ulong * degbounds; int res; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(ca, ctx); fmpq_mpoly_init(cb, ctx); fmpq_mpoly_init(cg, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 15); len2 = n_randint(state, 15); degbound = 100/(2*fmpq_mpoly_ctx_nvars(ctx) - 1); degbounds = FLINT_ARRAY_ALLOC(fmpq_mpoly_ctx_nvars(ctx), ulong); for (j = 0; j < fmpq_mpoly_ctx_nvars(ctx); j++) degbounds[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bounds(t, state, len, coeff_bits + 1, degbounds, ctx); if (fmpq_mpoly_is_zero(g, ctx)) fmpq_mpoly_one(g, ctx); fmpq_mpoly_randtest_bounds(a, state, len1, coeff_bits, degbounds, ctx); fmpq_mpoly_randtest_bounds(b, state, len2, coeff_bits, degbounds, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); res = fmpq_mpoly_gcd_zippel(g, a, b, ctx); fmpq_mpoly_assert_canonical(g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check that gcd could be computed\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(a, ctx) || !fmpq_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } continue; } if (!fmpq_mpoly_is_monic(g, ctx)) { printf("FAIL\n"); flint_printf("Check gcd has positive lc\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } res = 1; res = res && fmpq_mpoly_divides(ca, a, g, ctx); res = res && fmpq_mpoly_divides(cb, b, g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check divisibility\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } res = fmpq_mpoly_gcd_zippel(cg, ca, cb, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check that cofactor gcd could be computed\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal_ui(cg, UWORD(1), ctx)) { printf("FAIL\n"); flint_printf("Check cofactors are relatively prime\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(degbounds); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-gcd_zippel2.c000066400000000000000000000134701461254215100214000ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_zippel2 void gcd_check( fmpq_mpoly_t g, fmpq_mpoly_t a, fmpq_mpoly_t b, const fmpq_mpoly_t gdiv, fmpq_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpq_mpoly_t ca, cb, cg; fmpq_mpoly_init(ca, ctx); fmpq_mpoly_init(cb, ctx); fmpq_mpoly_init(cg, ctx); res = fmpq_mpoly_gcd_zippel2(g, a, b, ctx); fmpq_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_zero(gdiv, ctx)) { if (!fmpq_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(a, ctx) || !fmpq_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpq_mpoly_is_monic(g, ctx)) { flint_printf("FAIL: Check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpq_mpoly_divides(ca, a, g, ctx); res = res && fmpq_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpq_mpoly_gcd_zippel2(cg, ca, cb, ctx); fmpq_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpq_mpoly_gcd_zippel2, state) { slong i, j, tmul = 10; { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t g, a, b, t; const char* vars[] = {"y", "t", "x", "z"}; fmpq_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); fmpq_mpoly_set_str_pretty(t, "x+y+z+t", vars, ctx); fmpq_mpoly_set_str_pretty(a, "x^2+y^2+z^2+t^2", vars, ctx); fmpq_mpoly_set_str_pretty(b, "x^3+y^3+z^3+t^3", vars, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 0, "example"); fmpq_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpq_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpq_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 0, "example"); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(t, ctx); len = n_randint(state, 35) + 1; len1 = n_randint(state, 35) + 1; len2 = n_randint(state, 35) + 1; degbound = 2 + 100/(2*fmpq_mpoly_ctx_nvars(ctx) - 1); coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpq_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); if (fmpq_mpoly_is_zero(t, ctx)) fmpq_mpoly_one(t, ctx); fmpq_mpoly_mul(a, a, t, ctx); fmpq_mpoly_mul(b, b, t, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse"); } fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpq_mpoly/test/t-gen.c000066400000000000000000000046711461254215100177520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_gen, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f1, f2; slong len, coeff_bits, exp_bits, k1, k2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); if (ctx->zctx->minfo->nvars < 1) { fmpq_mpoly_ctx_clear(ctx); continue; } fmpq_mpoly_init(f1, ctx); fmpq_mpoly_init(f2, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(f1, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(f2, state, len, coeff_bits, exp_bits, ctx); k1 = n_randint(state, ctx->zctx->minfo->nvars); k2 = n_randint(state, ctx->zctx->minfo->nvars); fmpq_mpoly_gen(f1, k1, ctx); fmpq_mpoly_assert_canonical(f1, ctx); fmpq_mpoly_gen(f2, k2, ctx); fmpq_mpoly_assert_canonical(f2, ctx); result = 1; result = result && fmpq_mpoly_is_gen(f1, k1, ctx); result = result && fmpq_mpoly_is_gen(f1, -WORD(1), ctx); result = result && fmpq_mpoly_is_gen(f2, k2, ctx); result = result && fmpq_mpoly_is_gen(f2, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check one generator\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_mul(f1, f1, f2, ctx); result = 1; result = result && !fmpq_mpoly_is_gen(f1, k1, ctx); result = result && !fmpq_mpoly_is_gen(f1, k2, ctx); result = result && !fmpq_mpoly_is_gen(f1, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check product of two generators\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f1, ctx); fmpq_mpoly_clear(f2, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000122651461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_coeff_vars_ui, state) { slong i, j1, j2; /* check simple example */ { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g; /* get the coefficient of y^1*x^2*/ slong varl[2] = {1, 0}; ulong expl[2] = {1, 2}; const char * vars[] = {"x", "y", "z", "w"}; fmpq_mpoly_ctx_init(ctx, 4, ORD_DEGREVLEX); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_set_str_pretty(f, "x^2*y*(z+w)+x+y+x*y^2+z^2+w^2", vars, ctx); fmpq_mpoly_set_str_pretty(g, "z+w", vars, ctx); fmpq_mpoly_get_coeff_vars_ui(f, f, varl, expl, 2, ctx); if (!fmpq_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\ncheck simple example\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_ctx_clear(ctx); } /* check 1 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, m; slong nvars, len; ulong exp_bound; flint_bitcnt_t coeff_bits; slong vars[1]; ulong exps[1]; slong var1; nvars = 1 + n_randint(state, 20); fmpq_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 100); fmpq_mpoly_randtest_bound(f, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_repack_bits(f, f, f->zpoly->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars); fmpq_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { vars[0] = var1; exps[0] = j1; fmpq_mpoly_get_coeff_vars_ui(g, f, vars, exps, 1, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_gen(m, var1, ctx); fmpq_mpoly_pow_ui(m, m, j1, ctx); fmpq_mpoly_mul(g, g, m, ctx); fmpq_mpoly_add(h, h, g, ctx); } if (!fmpq_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n" "check 1 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(m, ctx); fmpq_mpoly_ctx_clear(ctx); } /* check 2 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, m; slong nvars, len; ulong exp_bound; flint_bitcnt_t coeff_bits; slong vars[2]; ulong exps[2]; slong var1, var2; nvars = 2 + n_randint(state, 20); fmpq_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 12) + 1; coeff_bits = n_randint(state, 100); fmpq_mpoly_randtest_bound(f, state, len, coeff_bits, exp_bound, ctx); fmpq_mpoly_repack_bits(f, f, f->zpoly->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars - 1); var2 = 1 + var1 + n_randint(state, nvars - 1 - var1); fmpq_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { for (j2 = 0; j2 < exp_bound; j2++) { vars[0] = var1; exps[0] = j1; vars[1] = var2; exps[1] = j2; fmpq_mpoly_get_coeff_vars_ui(g, f, vars, exps, 2, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_gen(m, var1, ctx); fmpq_mpoly_pow_ui(m, m, j1, ctx); fmpq_mpoly_mul(g, g, m, ctx); fmpq_mpoly_gen(m, var2, ctx); fmpq_mpoly_pow_ui(m, m, j2, ctx); fmpq_mpoly_mul(g, g, m, ctx); fmpq_mpoly_add(h, h, g, ctx); } } if (!fmpq_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n" "check 2 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(m, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_coeff_fmpq_fmpz.c000066400000000000000000000041731461254215100240510ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_coeff_fmpq_fmpz, state) { int i, j, k, result; /* Check _fmpq_fmpz */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; flint_bitcnt_t coeff_bits, exp_bits; slong len; fmpq_t c, d; fmpq_init(c); fmpq_init(d); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); len = n_randint(state, 100); coeff_bits = n_randint(state, 200); exp_bits = n_randint(state, 200) + 2; fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 10; j++) { fmpz * exp = (fmpz *) flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz)); fmpq_randtest(c, state, 200); for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpz_init(exp + k); fmpz_randtest_unsigned(exp + k, state, 200); } _fmpq_mpoly_set_coeff_fmpq_fmpz(f, c, exp, ctx); fmpq_mpoly_assert_canonical(f, ctx); _fmpq_mpoly_get_coeff_fmpq_fmpz(d, f, exp, ctx); result = fmpq_equal(c, d); if (!result) { printf("FAIL\n"); flint_printf("Check _fmpq_fmpz\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } for (k = 0; k < ctx->zctx->minfo->nvars; k++) fmpz_clear(exp + k); flint_free(exp); } fmpq_mpoly_clear(f, ctx); fmpq_clear(c); fmpq_clear(d); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_coeff_fmpq_monomial.c000066400000000000000000000073341461254215100247120ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_coeff_fmpq_monomial, state) { slong i, j, k; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, m; fmpz ** exp; fmpq_t cm, ce, q; slong nvars, len; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(m, ctx); fmpq_init(cm); fmpq_init(ce); fmpq_init(q); fmpq_one(q); /* anything nonzero is ok */ nvars = fmpq_mpoly_ctx_nvars(ctx); len = n_randint(state, 100); exp_bits = n_randint(state, FLINT_BITS + 10) + 1; exp_bits1 = n_randint(state, 200); exp_bits2 = n_randint(state, 200); coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); /* check a random monomial - this also randomizes m->bits */ exp = (fmpz **) flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz *)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_randtest_unsigned(exp[k], state, exp_bits1); } fmpq_mpoly_zero(m, ctx); fmpq_mpoly_set_coeff_fmpq_fmpz(m, q, exp, ctx); fmpq_mpoly_get_coeff_fmpq_monomial(cm, f, m, ctx); fmpq_mpoly_get_coeff_fmpq_fmpz(ce, f, exp, ctx); if (!fmpq_equal(cm, ce)) { flint_printf("FAIL\ncheck a random monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } /* check all monomials in f */ for (j = 0; j < fmpq_mpoly_length(f, ctx); j++) { fmpq_mpoly_get_term_exp_fmpz(exp, f, j, ctx); fmpq_mpoly_zero(m, ctx); fmpq_mpoly_set_coeff_fmpq_fmpz(m, q, exp, ctx); fmpq_mpoly_get_coeff_fmpq_monomial(cm, f, m, ctx); fmpq_mpoly_get_coeff_fmpq_fmpz(ce, f, exp, ctx); if (!fmpq_equal(cm, ce)) { flint_printf("FAIL\ncheck all monomials in f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } /* set random coeff and check */ for (j = 0; j < 10; j++) { for (k = 0; k < nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits2); } fmpq_randtest(cm, state, coeff_bits + 1); fmpq_mpoly_zero(m, ctx); fmpq_mpoly_set_coeff_fmpq_fmpz(m, q, exp, ctx); fmpq_mpoly_set_coeff_fmpq_monomial(f, cm, m, ctx); fmpq_mpoly_get_coeff_fmpq_monomial(ce, f, m, ctx); if (!fmpq_equal(cm, ce)) { flint_printf("FAIL\nset random coeff and check\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < nvars; k++) { fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp); fmpq_clear(q); fmpq_clear(cm); fmpq_clear(ce); fmpq_mpoly_clear(m, ctx); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_coeff_fmpq_ui.c000066400000000000000000000037001461254215100235050ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_coeff_fmpq_ui, state) { int i, j, k, result; /* Check _fmpq_ui */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; flint_bitcnt_t coeff_bits, exp_bits; slong len; fmpq_t c, d; fmpq_init(c); fmpq_init(d); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); len = n_randint(state, 100); coeff_bits = n_randint(state, 200); exp_bits = n_randint(state, 200) + 2; fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 10; j++) { ulong * exp = (ulong *) flint_malloc(ctx->zctx->minfo->nvars*sizeof(ulong)); fmpq_randtest(c, state, 200); for (k = 0; k < ctx->zctx->minfo->nvars; k++) exp[k] = n_randtest(state); fmpq_mpoly_set_coeff_fmpq_ui(f, c, exp, ctx); fmpq_mpoly_assert_canonical(f, ctx); fmpq_mpoly_get_coeff_fmpq_ui(d, f, exp, ctx); result = fmpq_equal(c, d); if (!result) { printf("FAIL\n"); flint_printf("Check _fmpq_ui\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } flint_free(exp); } fmpq_mpoly_clear(f, ctx); fmpq_clear(c); fmpq_clear(d); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_is_fmpq.c000066400000000000000000000041451461254215100223450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_is_fmpq, state) { slong i; /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; fmpq_t c, d; slong len; flint_bitcnt_t coeff_bits, exp_bits; fmpq_init(c); fmpq_init(d); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); len = n_randint(state, 10); exp_bits = n_randint(state, 200); coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); if (fmpq_mpoly_is_fmpq(f, ctx)) { fmpq_mpoly_get_fmpq(c, f, ctx); if (!fmpq_mpoly_equal_fmpq(f, c, ctx)) { printf("FAIL\n"); flint_printf("Check is_fmpq and get_fmpq catch constants\ni = %wd\n", i); fflush(stdout); flint_abort(); } } fmpq_randtest(c, state, n_randint(state, 200) + 1); fmpq_mpoly_set_fmpq(f, c, ctx); if (!fmpq_mpoly_is_fmpq(f, ctx)) { printf("FAIL\n"); flint_printf("Check set_fmpq makes is_fmpq true\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_get_fmpq(d, f, ctx); if (!fmpq_equal(c, d)) { printf("FAIL\n"); flint_printf("Check get_fmpq matches set_fmpq true\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_clear(c); fmpq_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_str_pretty.c000066400000000000000000000034411461254215100231240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_str_pretty, state) { slong i; { slong len1, exp_bits, coeff_bits; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, f1; char * str; const char * vars[] = {"x","xy","y","yx","z","zz"}; for (i = 0; i < 1 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_init_rand(ctx, state, 6); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(f1, ctx); for (len1 = 3; len1 < 1000; len1 += len1/2) { coeff_bits = 100; exp_bits = 100; fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx); fmpq_mpoly_assert_canonical(f, ctx); str = fmpq_mpoly_get_str_pretty(f, vars, ctx); fmpq_mpoly_set_str_pretty(f1, str, vars, ctx); fmpq_mpoly_assert_canonical(f1, ctx); flint_free(str); if (!fmpq_mpoly_equal(f, f1, ctx)) { flint_printf("FAIL\n"); flint_printf("check that parsing inverts printing\ni = %wd, len1 = %wd\n", i ,len1); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(f1, ctx); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_term_coeff_fmpq.c000066400000000000000000000042171461254215100240430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_term_coeff_fmpq, state) { slong i, j; /* check get and set match */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; fmpq_t c, d; slong len, coeff_bits, exp_bits, index; fmpq_init(c); fmpq_init(d); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); do { len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); } while (fmpq_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { fmpq_randtest(c, state, n_randint(state, 100) + 1); index = n_randint(state, fmpq_mpoly_length(f, ctx)); fmpq_mpoly_set_term_coeff_fmpq(f, index, c, ctx); fmpq_mpoly_get_term_coeff_fmpq(d, f, index, ctx); if (!fmpq_equal(c, d)) { printf("FAIL\n"); flint_printf("check get and set match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpq_mul_fmpz(c, fmpq_mpoly_content_ref(f, ctx), fmpq_mpoly_zpoly_term_coeff_ref(f, index, ctx)); if (!fmpq_equal(c, d)) { printf("FAIL\n"); flint_printf("check reference match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_clear(c); fmpq_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000056401461254215100235670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_term_exp_fmpz, state) { slong i, j, k; int result; /* check get and set match */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; slong len, nvars, index; flint_bitcnt_t coeff_bits, exp_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); nvars = fmpq_mpoly_ctx_nvars(ctx); do { len = n_randint(state, 50); exp_bits = n_randint(state, 100) + 1; coeff_bits = n_randint(state, 100); fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); } while (fmpq_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { fmpz ** exp1 = (fmpz **) flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz*)); fmpz ** exp2 = (fmpz **) flint_malloc(ctx->zctx->minfo->nvars*sizeof(fmpz*)); for (k = 0; k < nvars; k++) { exp1[k] = (fmpz *) flint_malloc(sizeof(fmpz)); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp1[k]); fmpz_init(exp2[k]); fmpz_randtest_unsigned(exp1[k], state, 200); } index = n_randint(state, fmpq_mpoly_length(f, ctx)); fmpq_mpoly_set_term_exp_fmpz(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->zpoly->exps, f->zpoly->length, f->zpoly->bits, ctx->zctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->zpoly->exps, f->zpoly->length, f->zpoly->bits, ctx->zctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpq_mpoly_get_term_exp_fmpz(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && fmpz_equal(exp1[k], exp2[k]); fmpz_clear(exp1[k]); fmpz_clear(exp2[k]); flint_free(exp1[k]); flint_free(exp2[k]); } if (!result) { flint_printf("FAIL\ncheck get and set match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpq_mpoly_clear(f, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000054501461254215100232250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_term_exp_si, state) { slong i, j, k; int result; /* check get and set match */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; slong len, nvars, index; flint_bitcnt_t coeff_bits, exp_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); nvars = fmpq_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 100) + 1; do { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); } while (fmpq_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { slong * exp1 = (slong *) flint_malloc(ctx->zctx->minfo->nvars*sizeof(slong)); slong * exp2 = (slong *) flint_malloc(ctx->zctx->minfo->nvars*sizeof(slong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS - 1) + 1; exp1[k] = n_randbits(state, bits); exp1[k] = FLINT_ABS(exp1[k]); } index = n_randint(state, fmpq_mpoly_length(f, ctx)); fmpq_mpoly_set_term_exp_ui(f, index, (ulong *) exp1, ctx); if (!mpoly_monomials_valid_test(f->zpoly->exps, f->zpoly->length, f->zpoly->bits, ctx->zctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->zpoly->exps, f->zpoly->length, f->zpoly->bits, ctx->zctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpq_mpoly_get_term_exp_si(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fmpq_mpoly_get_term_var_exp_si(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck get and set match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000053551461254215100232330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_set_term_exp_ui, state) { slong i, j, k; int result; /* check get and set match */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f; slong len, nvars, index; flint_bitcnt_t coeff_bits, exp_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); nvars = fmpq_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100) + 1; do { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); } while (fmpq_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { ulong * exp1 = (ulong *) flint_malloc(ctx->zctx->minfo->nvars*sizeof(ulong)); ulong * exp2 = (ulong *) flint_malloc(ctx->zctx->minfo->nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, fmpq_mpoly_length(f, ctx)); fmpq_mpoly_set_term_exp_ui(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->zpoly->exps, f->zpoly->length, f->zpoly->bits, ctx->zctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->zpoly->exps, f->zpoly->length, f->zpoly->bits, ctx->zctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpq_mpoly_get_term_exp_ui(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fmpq_mpoly_get_term_var_exp_ui(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck get and set match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_term.c000066400000000000000000000040621461254215100210010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_term, state) { int i, j; /* Check a polynomial is the sum of its terms */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len3, coeff_bits, exp_bits3, ctx); fmpq_mpoly_zero(h, ctx); for (j = fmpq_mpoly_length(f, ctx) - 1; j >= 0; j--) { fmpq_mpoly_get_term(g, f, j, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_add(h, h, g, ctx); } if (!fmpq_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\nCheck a polynomial is the sum of its terms\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-get_term_monomial.c000066400000000000000000000046721461254215100227030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_get_term_monomial, state) { int i, j; /* Check getting a coeff by its monomial */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_t c, d; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; flint_bitcnt_t coeff_bits; slong len1, len2, len3; fmpq_init(c); fmpq_init(d); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len3, coeff_bits, exp_bits3, ctx); fmpq_mpoly_repack_bits(h, f, f->zpoly->bits + n_randint(state, FLINT_BITS), ctx); for (j = fmpq_mpoly_length(f, ctx) - 1; j >= 0; j--) { fmpq_mpoly_get_term_monomial(g, f, j, ctx); fmpq_mpoly_repack_bits(g, g, g->zpoly->bits + n_randint(state, FLINT_BITS), ctx); fmpq_mpoly_get_term_coeff_fmpq(d, f, j, ctx); fmpq_mpoly_get_coeff_fmpq_monomial(c, h, g, ctx); if (!fmpq_equal(c, d)) { flint_printf("FAIL\nCheck getting a coeff by its monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } } fmpq_clear(c); fmpq_clear(d); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-mul.c000066400000000000000000000137641461254215100200010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_mul, state) { int i, j, result; /* Check f*(g + h) = f*g + f*h */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k1, ctx); fmpq_mpoly_init(k2, ctx); fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); fmpq_mpoly_randtest_bits(k1, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k2, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_add(t1, g, h, ctx); fmpq_mpoly_assert_canonical(t1, ctx); fmpq_mpoly_mul(k1, f, t1, ctx); fmpq_mpoly_assert_canonical(k1, ctx); fmpq_mpoly_mul(t1, f, g, ctx); fmpq_mpoly_assert_canonical(t1, ctx); fmpq_mpoly_mul(t2, f, h, ctx); fmpq_mpoly_assert_canonical(t2, ctx); fmpq_mpoly_add(k2, t1, t2, ctx); fmpq_mpoly_assert_canonical(k2, ctx); result = fmpq_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*(g + h) = f*g + f*h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k1, ctx); fmpq_mpoly_clear(k2, ctx); fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_mul(f, f, g, ctx); fmpq_mpoly_assert_canonical(f, ctx); result = fmpq_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_mul(g, f, g, ctx); fmpq_mpoly_assert_canonical(g, ctx); result = fmpq_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-pow_fmpz.c000066400000000000000000000042171461254215100210360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_pow_fmpz, state) { int i, j, k, result; /* Check against rmul */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len1, len2; fmpz_t power; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpz_init(power); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len2, coeff_bits, exp_bits2, ctx); fmpz_set_si(power, j); fmpq_mpoly_pow_fmpz(h, f, power, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_one(g, ctx); for (k = 0; k < j; k++) fmpq_mpoly_mul(g, g, f, ctx); result = fmpq_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check against rmul\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_clear(power); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-pow_ui.c000066400000000000000000000100441461254215100204720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_pow_ui, state) { int i, j, k, result; /* Check against rmul */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len1, len2; fmpz_t power; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpz_init(power); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_pow_ui(h, f, j, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_one(g, ctx); for (k = 0; k < j; k++) fmpq_mpoly_mul(g, g, f, ctx); result = fmpq_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check against rmul\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_clear(power); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check monomials against pow_fmpz */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len2; fmpz_t power; flint_bitcnt_t coeff_bits, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpz_init(power); len2 = n_randint(state, 10); exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { /* make sure power is random ui */ fmpz_set_ui(power, n_randlimb(state)); /* set f to a random monomial */ fmpq_mpoly_one(f, ctx); if (n_randint(state, 2)) { fmpq_mpoly_neg(f, f, ctx); } for (k = 0; k < ctx->zctx->minfo->nvars; k++) { fmpq_mpoly_gen(h, n_randint(state, ctx->zctx->minfo->nvars), ctx); fmpq_mpoly_mul(f, f, h, ctx); } fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_randtest_bits(h, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_pow_ui(g, f, fmpz_get_ui(power), ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_pow_fmpz(h, f, power, ctx); fmpq_mpoly_assert_canonical(h, ctx); result = fmpq_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check monomials against pow_fmpz\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_clear(power); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-push_term_fmpq_fmpz.c000066400000000000000000000111211461254215100232520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_push_term_fmpq_fmpz, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f1, f2, f3, m; flint_bitcnt_t coeff_bits, exp_bits; fmpz **exp, **exp2, *exp3; slong len, nvars; fmpq_t c, c2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f1, ctx); fmpq_mpoly_init(f2, ctx); fmpq_mpoly_init(f3, ctx); fmpq_mpoly_init(m, ctx); fmpq_init(c); fmpq_init(c2); nvars = fmpq_mpoly_ctx_nvars(ctx); exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); fmpz_init(exp3 + k); } len = n_randint(state, 20); coeff_bits = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200); fmpq_mpoly_zero(f1, ctx); fmpq_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fmpq_randtest(c, state, coeff_bits + 1); for (k = 0; k < nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits); fmpz_set(exp3 + k, exp[k]); } /* add it to f1 */ fmpq_mpoly_zero(m, ctx); fmpq_mpoly_set_coeff_fmpq_fmpz(m, c, exp, ctx); fmpq_mpoly_add(f1, f1, m, ctx); fmpq_mpoly_assert_canonical(f1, ctx); /* push it back on f2 */ if (fmpz_is_one(fmpq_denref(c))) fmpq_mpoly_push_term_fmpz_fmpz(f2, fmpq_numref(c), exp, ctx); else fmpq_mpoly_push_term_fmpq_fmpz(f2, c, exp, ctx); fmpq_mpoly_push_term_fmpq_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ fmpq_mpoly_get_term_coeff_fmpq(c2, f2, fmpq_mpoly_length(f2, ctx) - 1, ctx); fmpq_mpoly_get_term_exp_fmpz(exp2, f2, fmpq_mpoly_length(f2, ctx) - 1, ctx); if (!fmpq_equal(c, c2)) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (!fmpz_equal(exp[k], exp2[k])) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpq_mpoly_sort_terms(f2, ctx); fmpq_mpoly_combine_like_terms(f2, ctx); fmpq_mpoly_assert_canonical(f2, ctx); fmpq_mpoly_sort_terms(f3, ctx); fmpq_mpoly_combine_like_terms(f3, ctx); fmpq_mpoly_assert_canonical(f3, ctx); if (!fmpq_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushed polynomial matches add\ni = %wd\n",i); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check pushed ffmpz polynomial matches add\ni = %wd\n",i); fflush(stdout); flint_abort(); } fmpq_clear(c2); fmpq_clear(c); fmpq_mpoly_clear(f1, ctx); fmpq_mpoly_clear(f2, ctx); fmpq_mpoly_clear(f3, ctx); fmpq_mpoly_clear(m, ctx); fmpq_mpoly_ctx_clear(ctx); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); fmpz_clear(exp3 + k); } flint_free(exp3); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-push_term_fmpq_ui.c000066400000000000000000000066641461254215100227330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_push_term_fmpq_ui, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f1, f2, m; flint_bitcnt_t coeff_bits, exp_bits; ulong * exp, * exp2; slong len, nvars; fmpq_t c, c2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f1, ctx); fmpq_mpoly_init(f2, ctx); fmpq_mpoly_init(m, ctx); fmpq_init(c); fmpq_init(c2); nvars = fmpq_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 20); coeff_bits = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200); fmpq_mpoly_zero(f1, ctx); fmpq_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fmpq_randtest(c, state, coeff_bits + 1); for (k = 0; k < nvars; k++) exp[k] = n_randint(state, exp_bits); /* add it to f1 */ fmpq_mpoly_zero(m, ctx); fmpq_mpoly_set_coeff_fmpq_ui(m, c, exp, ctx); fmpq_mpoly_add(f1, f1, m, ctx); fmpq_mpoly_assert_canonical(f1, ctx); /* push it back on f2 */ if (fmpz_is_one(fmpq_denref(c))) fmpq_mpoly_push_term_fmpz_ui(f2, fmpq_numref(c), exp, ctx); else fmpq_mpoly_push_term_fmpq_ui(f2, c, exp, ctx); /* make sure last term matches */ fmpq_mpoly_get_term_coeff_fmpq(c2, f2, fmpq_mpoly_length(f2, ctx) - 1, ctx); fmpq_mpoly_get_term_exp_ui(exp2, f2, fmpq_mpoly_length(f2, ctx) - 1, ctx); if (!fmpq_equal(c, c2)) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (exp[k] != exp2[k]) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpq_mpoly_sort_terms(f2, ctx); fmpq_mpoly_combine_like_terms(f2, ctx); fmpq_mpoly_assert_canonical(f2, ctx); if (!fmpq_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushed polynomial matches add\ni=%wd\n",i,j); fflush(stdout); flint_abort(); } fmpq_clear(c2); fmpq_clear(c); fmpq_mpoly_clear(f1, ctx); fmpq_mpoly_clear(f2, ctx); fmpq_mpoly_clear(m, ctx); fmpq_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-resultant_discriminant.c000066400000000000000000000203241461254215100237570ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_resultant_discriminant, state) { slong i, j; /* Check quadratic polynomial */ { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, d, d1; const char * vars[] = {"x","a","b","c"}; fmpq_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(d, ctx); fmpq_mpoly_init(d1, ctx); fmpq_mpoly_set_str_pretty(f, "a^10/3*x^2 + b^100*x + c^100000000000000000000", vars, ctx); fmpq_mpoly_set_str_pretty(d1, "b^200 - 4/3*a^10*c^100000000000000000000", vars, ctx); if (!fmpq_mpoly_discriminant(d, f, 0, ctx)) { flint_printf("FAIL: could not compute quadratic discriminant\n"); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(d, ctx); fmpq_mpoly_clear(d1, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check univariate resultant */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, r; fmpq_poly_t au, bu; fmpq_t ru; slong len1, len2, exp_bound1, exp_bound2; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init(ctx, 1, mpoly_ordering_randtest(state)); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(r, ctx); fmpq_poly_init(au); fmpq_poly_init(bu); fmpq_init(ru); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 50) + 1; exp_bound2 = n_randint(state, 50) + 1; coeff_bits = n_randint(state, 100) + 1; fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, exp_bound1, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, exp_bound2, ctx); fmpq_mpoly_get_fmpq_poly(au, a, 0, ctx); fmpq_mpoly_get_fmpq_poly(bu, b, 0, ctx); fmpq_poly_resultant(ru, au, bu); if (!fmpq_mpoly_resultant(r, a, b, 0, ctx) || !fmpq_mpoly_equal_fmpq(r, ru, ctx)) { flint_printf("FAIL: Check univariate resultant \n"); flint_printf("i: %wd\n",i); fflush(stdout); flint_abort(); } fmpq_clear(ru); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(r, ctx); fmpq_poly_clear(au); fmpq_poly_clear(bu); fmpq_mpoly_ctx_clear(ctx); } /* Check res(a*b,c) = res(a,c)*res(b,c) */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, c, ab, ra, rb, rab, p; slong len1, len2, len3, exp_bound1, exp_bound2, exp_bound3; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 3); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(c, ctx); fmpq_mpoly_init(ab, ctx); fmpq_mpoly_init(ra, ctx); fmpq_mpoly_init(rb, ctx); fmpq_mpoly_init(rab, ctx); fmpq_mpoly_init(p, ctx); len1 = n_randint(state, 12); len2 = n_randint(state, 12); len3 = n_randint(state, 12); exp_bound1 = n_randint(state, 5) + 1; exp_bound2 = n_randint(state, 5) + 1; exp_bound3 = n_randint(state, 5) + 1; coeff_bits = n_randint(state, 100) + 1; fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, exp_bound1, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, exp_bound2, ctx); fmpq_mpoly_randtest_bound(c, state, len3, coeff_bits, exp_bound3, ctx); for (j = 0; j < fmpq_mpoly_ctx_nvars(ctx); j++) { fmpq_mpoly_mul(ab, a, b, ctx); if (!fmpq_mpoly_resultant(ra, a, c, j, ctx)) continue; fmpq_mpoly_assert_canonical(ra, ctx); if (!fmpq_mpoly_resultant(rb, b, c, j, ctx)) continue; fmpq_mpoly_assert_canonical(rb, ctx); if (!fmpq_mpoly_resultant(rab, ab, c, j, ctx)) continue; fmpq_mpoly_assert_canonical(rab, ctx); fmpq_mpoly_mul(p, ra, rb, ctx); if (!fmpq_mpoly_equal(p,rab,ctx)) { flint_printf("FAIL: Check res(a*b,c) = res(a,c)*res(b,c)\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(c, ctx); fmpq_mpoly_clear(ab, ctx); fmpq_mpoly_clear(ra, ctx); fmpq_mpoly_clear(rb, ctx); fmpq_mpoly_clear(rab, ctx); fmpq_mpoly_clear(p, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2 */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, b, ab, r, da, db, dab, p; slong len1, len2, exp_bound1, exp_bound2; flint_bitcnt_t coeff_bits; fmpq_mpoly_ctx_init_rand(ctx, state, 3); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(b, ctx); fmpq_mpoly_init(ab, ctx); fmpq_mpoly_init(da, ctx); fmpq_mpoly_init(db, ctx); fmpq_mpoly_init(dab, ctx); fmpq_mpoly_init(r, ctx); fmpq_mpoly_init(p, ctx); len1 = n_randint(state, 12); len2 = n_randint(state, 12); exp_bound1 = n_randint(state, 4) + 1; exp_bound2 = n_randint(state, 4) + 1; coeff_bits = n_randint(state, 80) + 1; fmpq_mpoly_randtest_bound(a, state, len1, coeff_bits, exp_bound1, ctx); fmpq_mpoly_randtest_bound(b, state, len2, coeff_bits, exp_bound2, ctx); for (j = 0; j < fmpq_mpoly_ctx_nvars(ctx); j++) { if (fmpq_mpoly_degree_si(a, j, ctx) < 1) continue; if (fmpq_mpoly_degree_si(b, j, ctx) < 1) continue; fmpq_mpoly_mul(ab, a, b, ctx); if (!fmpq_mpoly_resultant(r, a, b, j, ctx)) continue; if (!fmpq_mpoly_discriminant(da, a, j, ctx)) continue; if (!fmpq_mpoly_discriminant(db, b, j, ctx)) continue; if (!fmpq_mpoly_discriminant(dab, ab, j, ctx)) continue; fmpq_mpoly_mul(p, da, db, ctx); fmpq_mpoly_mul(p, p, r, ctx); fmpq_mpoly_mul(p, p, r, ctx); if (!fmpq_mpoly_equal(dab, p, ctx)) { flint_printf("FAIL: Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2\n"); flint_printf("a: "); fmpq_mpoly_print_pretty(a, NULL, ctx); flint_printf("\n"); flint_printf("b: "); fmpq_mpoly_print_pretty(b, NULL, ctx); flint_printf("\n"); flint_printf("disc(a*b): "); fmpq_mpoly_print_pretty(dab, NULL, ctx); flint_printf("\n"); flint_printf("disc(a): "); fmpq_mpoly_print_pretty(da, NULL, ctx); flint_printf("\n"); flint_printf("disc(b): "); fmpq_mpoly_print_pretty(db, NULL, ctx); flint_printf("\n"); flint_printf("res(a, b): "); fmpq_mpoly_print_pretty(r, NULL, ctx); flint_printf("\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(a, ctx); fmpq_mpoly_clear(b, ctx); fmpq_mpoly_clear(ab, ctx); fmpq_mpoly_clear(da, ctx); fmpq_mpoly_clear(db, ctx); fmpq_mpoly_clear(dab, ctx); fmpq_mpoly_clear(r, ctx); fmpq_mpoly_clear(p, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-scalar_mul_div_fmpq.c000066400000000000000000000066261461254215100232120ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpq_mpoly_scalar_mul_div_fmpq, state) { int i, j, result; /* Check (f * a) / a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpq_t c; slong len, coeff_bits, exp_bits; fmpq_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_randtest(c, state, n_randint(state, 200) + 1); if (fmpq_is_zero(c)) continue; fmpq_mpoly_scalar_mul_fmpq(g, f, c, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_scalar_div_fmpq(h, g, c, ctx); fmpq_mpoly_assert_canonical(h, ctx); result = fmpq_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f * a) / a = f, i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g; fmpq_t c; slong len, coeff_bits, exp_bits; fmpq_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_set(g, f, ctx); fmpq_randtest(c, state, n_randint(state, 200) + 1); if (fmpq_is_zero(c)) continue; fmpq_mpoly_scalar_mul_fmpq(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); fmpq_mpoly_scalar_div_fmpq(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); result = fmpq_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-scalar_mul_div_fmpz.c000066400000000000000000000065641461254215100232240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_scalar_mul_div_fmpz, state) { int i, j, result; /* Check (f * a) / a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); if (fmpz_is_zero(c)) continue; fmpq_mpoly_scalar_mul_fmpz(g, f, c, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_scalar_div_fmpz(h, g, c, ctx); fmpq_mpoly_assert_canonical(h, ctx); result = fmpq_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f * a) / a = f, i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpz_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_set(g, f, ctx); fmpz_randtest(c, state, n_randint(state, 200)); if (fmpz_is_zero(c)) continue; fmpq_mpoly_scalar_mul_fmpz(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); fmpq_mpoly_scalar_div_fmpz(f, f, c, ctx); fmpq_mpoly_assert_canonical(f, ctx); result = fmpq_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-scalar_mul_fmpq.c000066400000000000000000000076531461254215100223510ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_scalar_mul_fmpq, state) { int i, j, result; /* Check (f*a)*b = f*(a*b) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h, k; fmpq_t a, b, c; slong len, coeff_bits, exp_bits; fmpq_init(a); fmpq_init(b); fmpq_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpq_randtest(a, state, coeff_bits + 1); fmpq_randtest(b, state, coeff_bits + 1); fmpq_mul(c, a, b); fmpq_mpoly_scalar_mul_fmpq(g, f, a, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_scalar_mul_fmpq(h, g, b, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_scalar_mul_fmpq(k, f, c, ctx); fmpq_mpoly_assert_canonical(k, ctx); result = fmpq_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b)\ni=%wd j=%wd\n",i,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_clear(k, ctx); fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpq_t c; slong len, coeff_bits, exp_bits; fmpq_init(c); fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_randtest(c, state, coeff_bits + 1); fmpq_mpoly_set(g, f, ctx); fmpq_mpoly_assert_canonical(g, ctx); fmpq_mpoly_scalar_mul_fmpq(h, f, c, ctx); fmpq_mpoly_assert_canonical(h, ctx); fmpq_mpoly_scalar_mul_fmpq(g, g, c, ctx); fmpq_mpoly_assert_canonical(g, ctx); result = fmpq_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni=%wd j=%wd\n",i,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-sqrt.c000066400000000000000000000132001461254215100201560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_sqrt, state) { slong i, j, tmul = 10; /* Check sqrt(f^2) = +-f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; flint_bitcnt_t coeff_bits, coeff_bits1; int sqr; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits1, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(g, f, f, ctx); fmpq_mpoly_assert_canonical(g, ctx); sqr = fmpq_mpoly_sqrt(h, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); if (!sqr) { flint_printf("FAIL: Check sqrt(f^2) returns 1\n"); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_equal(h, f, ctx) && !(fmpq_mpoly_neg(h, h, ctx), fmpq_mpoly_equal(h, f, ctx))) { flint_printf("FAIL: Check sqrt(f^2) = +-f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check sqrt(random) */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; flint_bitcnt_t coeff_bits, coeff_bits1; int sqr; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 100); coeff_bits1 = n_randint(state, 100) + 1; for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits1, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); sqr = fmpq_mpoly_sqrt(g, f, ctx); fmpq_mpoly_assert_canonical(g, ctx); if (sqr) { fmpq_mpoly_mul(g, g, g, ctx); if (!fmpq_mpoly_equal(g, f, ctx)) { flint_printf("FAIL: Check sqrt(random)\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } else if (!fmpq_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check aliasing of square root with input */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; flint_bitcnt_t coeff_bits, coeff_bits1; int sqr1, sqr2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits1, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpq_mpoly_mul(g, f, f, ctx); fmpq_mpoly_assert_canonical(g, ctx); sqr1 = fmpq_mpoly_sqrt(h, g, ctx); fmpq_mpoly_assert_canonical(h, ctx); sqr2 = fmpq_mpoly_sqrt(g, g, ctx); fmpq_mpoly_assert_canonical(g, ctx); if (sqr1 != sqr2 || !fmpq_mpoly_equal(g, h, ctx)) { printf("FAIL: Check aliasing\n"); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-term_content.c000066400000000000000000000074541461254215100217040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_term_content, state) { int i, j, result; /* Check division by content leaves trivial content */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 20); fmpq_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 10; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_term_content(f, g, ctx); if (fmpq_mpoly_is_zero(g, ctx)) { result = fmpq_mpoly_is_zero(f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check zero\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } else { result = fmpq_mpoly_length(f, ctx) == 1; if (!result) { printf("FAIL\n"); flint_printf("Check content is monomial\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } result = fmpq_is_one(f->content) && fmpz_is_one(f->zpoly->coeffs + 0); if (!result) { printf("FAIL\n"); flint_printf("Check content is monic\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } result = fmpq_mpoly_divides(k, g, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check content divides\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fmpq_mpoly_term_content(k, k, ctx); result = fmpq_mpoly_is_one(k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check quotient is primitive\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_term_content(g, g, ctx); result = fmpq_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing \ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-total_degree.c000066400000000000000000000117341461254215100216350ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" /* foolproof way to check totdeg_check is correct */ void _check_total_degree(const fmpz_t totdeg_check, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { fmpz_t totdeg; fmpz_init(totdeg); mpoly_total_degree_fmpz_ref(totdeg, A->zpoly->exps, A->zpoly->length, A->zpoly->bits, ctx->zctx->minfo); if (!fmpz_equal(totdeg_check, totdeg)) flint_throw(FLINT_ERROR, "Total degree is wrong"); fmpz_clear(totdeg); } TEST_FUNCTION_START(fmpq_mpoly_total_degree, state) { int i, j; /* Check total_degree does not go up under addition */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_add(h, f, g, ctx); fmpq_mpoly_total_degree_fmpz(hdeg, h, ctx); fmpq_mpoly_total_degree_fmpz(fdeg, f, ctx); fmpq_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } /* Check total_degree adds under multiplication */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { int ok; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_mul(h, f, g, ctx); fmpq_mpoly_total_degree_fmpz(hdeg, h, ctx); fmpq_mpoly_total_degree_fmpz(fdeg, f, ctx); fmpq_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if (fmpq_mpoly_is_zero(f, ctx) || fmpq_mpoly_is_zero(g, ctx)) { ok = fmpz_equal_si(hdeg, -WORD(1)) && (fmpz_equal_si(fdeg, -WORD(1)) || fmpz_equal_si(gdeg, -WORD(1))); } else { fmpz_add(gdeg, gdeg, fdeg); ok = fmpz_equal(hdeg, gdeg); } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/test/t-univar.c000066400000000000000000000066451461254215100205100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly.h" TEST_FUNCTION_START(fmpq_mpoly_univar, state) { slong i, j, k; /* Check mpoly -> mpoly_univar -> mpoly */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t f, g, h; fmpq_mpoly_univar_t fx, gx; slong len1, len2, n; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2, bits; fmpq_mpoly_ctx_init_rand(ctx, state, 20); fmpq_mpoly_init(f, ctx); fmpq_mpoly_init(g, ctx); fmpq_mpoly_init(h, ctx); fmpq_mpoly_univar_init(fx, ctx); fmpq_mpoly_univar_init(gx, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 3*FLINT_BITS) + 1; exp_bits2 = n_randint(state, 3*FLINT_BITS) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < ctx->zctx->minfo->nvars; j++) { fmpq_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpq_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpq_mpoly_to_univar(fx, f, j, ctx); fmpq_mpoly_univar_assert_canonical(fx, ctx); fmpq_mpoly_from_univar(g, fx, j, ctx); fmpq_mpoly_assert_canonical(g, ctx); if (!fmpq_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check mpoly -> mpoly_univar -> mpoly\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } bits = mpoly_fix_bits(f->zpoly->bits + n_randint(state, FLINT_BITS), ctx->zctx->minfo); fmpq_mpoly_from_univar_bits(h, bits, fx, j, ctx); fmpq_mpoly_assert_canonical(h, ctx); if (h->zpoly->bits != bits || !fmpq_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check mpoly -> mpoly_univar -> mpoly with bits\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } if (!fmpq_mpoly_univar_degree_fits_si(fx, ctx)) continue; n = fmpq_mpoly_univar_length(fx, ctx); fmpq_mpoly_univar_fit_length(gx, n, ctx); gx->length = n; for (k = 0; k < n; k++) { fmpq_mpoly_univar_swap_term_coeff(gx->coeffs + k, fx, k, ctx); fmpz_set_si(gx->exps + k, fmpq_mpoly_univar_get_term_exp_si(fx, k, ctx)); } fmpq_mpoly_from_univar(g, gx, j, ctx); if (!fmpq_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check construction\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_univar_clear(gx, ctx); fmpq_mpoly_univar_clear(fx, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_mpoly/univar.c000066400000000000000000000261421461254215100172620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpq_mpoly.h" void fmpq_mpoly_univar_init(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; } void fmpq_mpoly_univar_clear(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) { fmpq_mpoly_clear(A->coeffs + i, ctx); fmpz_clear(A->exps + i); } if (A->coeffs) flint_free(A->coeffs); if (A->exps) flint_free(A->exps); } void fmpq_mpoly_univar_fit_length(fmpq_mpoly_univar_t A, slong length, const fmpq_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { if (old_alloc == 0) { A->exps = (fmpz *) flint_malloc(new_alloc*sizeof(fmpz)); A->coeffs = (fmpq_mpoly_struct *) flint_malloc( new_alloc*sizeof(fmpq_mpoly_struct)); } else { A->exps = (fmpz *) flint_realloc(A->exps, new_alloc*sizeof(fmpz)); A->coeffs = (fmpq_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fmpq_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) { fmpz_init(A->exps + i); fmpq_mpoly_init(A->coeffs + i, ctx); } A->alloc = new_alloc; } } void fmpq_mpoly_univar_assert_canonical(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx) { slong i; for (i = 0; i + 1 < A->length; i++) { if (fmpz_cmp(A->exps + i, A->exps + i + 1) <= 0 || fmpz_sgn(A->exps + i) < 0 || fmpz_sgn(A->exps + i + 1) < 0) { flint_throw(FLINT_ERROR, "Univariate polynomial exponents out of order"); } } for (i = 0; i < A->length; i++) fmpq_mpoly_assert_canonical(A->coeffs + i, ctx); } void fmpq_mpoly_univar_print_pretty(const fmpq_mpoly_univar_t A, const char ** x, const fmpq_mpoly_ctx_t ctx) { slong i; if (A->length == 0) flint_printf("0"); for (i = 0; i < A->length; i++) { if (i != 0) flint_printf("+"); flint_printf("("); fmpq_mpoly_print_pretty(A->coeffs + i,x,ctx); flint_printf(")*X^"); fmpz_print(A->exps + i); } } void fmpq_mpoly_to_univar(fmpq_mpoly_univar_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx) { slong i; fmpz_mpoly_univar_t Z; fmpz_mpoly_univar_init(Z, ctx->zctx); fmpz_mpoly_to_univar(Z, B->zpoly, var, ctx->zctx); fmpq_mpoly_univar_fit_length(A, Z->length, ctx); A->length = Z->length; for (i = Z->length - 1; i >= 0; i--) { fmpz_swap(A->exps + i, Z->exps + i); fmpz_mpoly_swap(A->coeffs[i].zpoly, Z->coeffs + i, ctx->zctx); fmpq_set(A->coeffs[i].content, B->content); fmpq_mpoly_reduce(A->coeffs + i, ctx); } fmpz_mpoly_univar_clear(Z, ctx->zctx); } /* Currently this function does not work if the coefficients depend on "var". The assertion x->next == NULL would need to be replaced by a loop. Other asserts would need to be removed as well. */ void fmpq_mpoly_from_univar_bits(fmpq_mpoly_t A, flint_bitcnt_t Abits, const fmpq_mpoly_univar_t B, slong var, const fmpq_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->zctx->minfo); slong i; slong next_loc, heap_len = 1; ulong * cmpmask; slong total_len; mpoly_heap_s * heap; slong Alen; ulong ** Btexp; fmpz * Bscales; fmpz_t t; ulong * exp; ulong * one; mpoly_heap_t * chain, * x; TMP_INIT; if (B->length == 0) { fmpz_mpoly_fit_bits(A->zpoly, Abits, ctx->zctx); A->zpoly->bits = Abits; _fmpz_mpoly_set_length(A->zpoly, 0, ctx->zctx); fmpq_zero(A->content); return; } TMP_START; /* pack everything into Abits */ one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); Btexp = (ulong **) TMP_ALLOC(B->length*sizeof(ulong*)); Bscales = (fmpz *) TMP_ALLOC(B->length*sizeof(ulong*)); total_len = 0; fmpq_zero(A->content); for (i = 0; i < B->length; i++) { fmpz_mpoly_struct * Bi; fmpz_init(Bscales + i); fmpq_gcd(A->content, A->content, B->coeffs[i].content); Bi = B->coeffs[i].zpoly; total_len += Bi->length; Btexp[i] = Bi->exps; if (Abits != Bi->bits) { Btexp[i] = (ulong *) flint_malloc(N*Bi->length*sizeof(ulong)); if (!mpoly_repack_monomials(Btexp[i], Abits, Bi->exps, Bi->bits, Bi->length, ctx->zctx->minfo)) { FLINT_ASSERT(0 && "repack does not fit"); } } } fmpz_init(t); if (!fmpq_is_zero(A->content)) { for (i = 0; i < B->length; i++) { _fmpq_div(Bscales + i, t, fmpq_numref(B->coeffs[i].content), fmpq_denref(B->coeffs[i].content), fmpq_numref(A->content), fmpq_denref(A->content)); FLINT_ASSERT(fmpz_is_one(t)); } } fmpz_clear(t); fmpz_mpoly_fit_length(A->zpoly, total_len, ctx->zctx); fmpz_mpoly_fit_bits(A->zpoly, Abits, ctx->zctx); A->zpoly->bits = Abits; next_loc = B->length + 2; heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); exp = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->zctx->minfo); Alen = 0; if (Abits <= FLINT_BITS) { mpoly_gen_monomial_sp(one, var, Abits, ctx->zctx->minfo); for (i = 0; i < B->length; i++) { FLINT_ASSERT(fmpz_fits_si(B->exps + i)); x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + i), one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->zpoly->alloc); mpoly_monomial_set(A->zpoly->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fmpz_mul(A->zpoly->coeffs + Alen, Bscales + x->i, (B->coeffs + x->i)->zpoly->coeffs + x->j); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->zpoly->length) { FLINT_ASSERT(fmpz_fits_si(B->exps + x->i)); x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + x->i), one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } else { mpoly_gen_monomial_offset_mp(one, var, Abits, ctx->zctx->minfo); for (i = 0; i < B->length; i++) { x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + i, one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->zpoly->alloc); mpoly_monomial_set(A->zpoly->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fmpz_mul(A->zpoly->coeffs + Alen, Bscales + x->i, (B->coeffs + x->i)->zpoly->coeffs + x->j); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->zpoly->length) { x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + x->i, one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } for (i = 0; i < B->length; i++) { fmpz_clear(Bscales + i); if (Btexp[i] != (B->coeffs + i)->zpoly->exps) flint_free(Btexp[i]); } TMP_END; _fmpz_mpoly_set_length(A->zpoly, Alen, ctx->zctx); fmpq_mpoly_reduce(A, ctx); } void fmpq_mpoly_from_univar(fmpq_mpoly_t A, const fmpq_mpoly_univar_t B, slong var, const fmpq_mpoly_ctx_t ctx) { slong n = ctx->zctx->minfo->nfields; flint_bitcnt_t bits; slong i; fmpz * gen_fields, * tmp_fields, * max_fields; TMP_INIT; if (B->length == 0) { fmpq_mpoly_zero(A, ctx); return; } TMP_START; /* find bits required to represent result */ gen_fields = (fmpz *) TMP_ALLOC(ctx->zctx->minfo->nfields*sizeof(fmpz)); tmp_fields = (fmpz *) TMP_ALLOC(ctx->zctx->minfo->nfields*sizeof(fmpz)); max_fields = (fmpz *) TMP_ALLOC(ctx->zctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->zctx->minfo->nfields; i++) { fmpz_init(gen_fields + i); fmpz_init(tmp_fields + i); fmpz_init(max_fields + i); } mpoly_gen_fields_fmpz(gen_fields, var, ctx->zctx->minfo); for (i = 0; i < B->length; i++) { fmpz_mpoly_struct * Bi = B->coeffs[i].zpoly; mpoly_max_fields_fmpz(tmp_fields, Bi->exps, Bi->length, Bi->bits, ctx->zctx->minfo); _fmpz_vec_scalar_addmul_fmpz(tmp_fields, gen_fields, n, B->exps + i); _fmpz_vec_max_inplace(max_fields, tmp_fields, n); } bits = _fmpz_vec_max_bits(max_fields, n); bits = FLINT_MAX(MPOLY_MIN_BITS, bits + 1); bits = mpoly_fix_bits(bits, ctx->zctx->minfo); for (i = 0; i < ctx->zctx->minfo->nfields; i++) { fmpz_clear(gen_fields + i); fmpz_clear(tmp_fields + i); fmpz_clear(max_fields + i); } TMP_END; fmpq_mpoly_from_univar_bits(A, bits, B, var, ctx); } flint-3.1.3/src/fmpq_mpoly/void_ring.c000066400000000000000000000071651461254215100177420ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" static void fmpq_mpoly_void_init(void * a, const void * ctx) { fmpq_mpoly_init(a, ctx); } static void fmpq_mpoly_void_clear(void * a, const void * ctx) { fmpq_mpoly_clear(a, ctx); } static int fmpq_mpoly_void_is_zero(const void * a, const void * ctx) { return fmpq_mpoly_is_zero(a, ctx); } static void fmpq_mpoly_void_zero(void * a, const void * ctx) { fmpq_mpoly_zero(a, ctx); } static void fmpq_mpoly_void_one(void * a, const void * ctx) { fmpq_mpoly_one(a, ctx); } static void fmpq_mpoly_void_set(void * a, const void * b, const void * ctx) { fmpq_mpoly_set(a, b, ctx); } static void fmpq_mpoly_void_set_fmpz(void * a, const fmpz_t b, const void * ctx) { fmpq_mpoly_set_fmpz(a, b, ctx); } static void fmpq_mpoly_void_swap(void * a, void * b, const void * ctx) { fmpq_mpoly_swap(a, b, ctx); } static void fmpq_mpoly_void_neg(void * a, const void * b, const void * ctx) { fmpq_mpoly_neg(a, b, ctx); } static void fmpq_mpoly_void_add(void * a, const void * b, const void * c, const void * ctx) { fmpq_mpoly_add(a, b, c, ctx); } static void fmpq_mpoly_void_sub(void * a, const void * b, const void * c, const void * ctx) { fmpq_mpoly_sub(a, b, c, ctx); } static void fmpq_mpoly_void_mul(void * a, const void * b, const void * c, const void * ctx) { fmpq_mpoly_mul(a, b, c, ctx); } static void fmpq_mpoly_void_mul_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { fmpq_mpoly_scalar_mul_fmpz(a, b, c, ctx); } static void fmpq_mpoly_void_divexact(void * a, const void * b, const void * c, const void * ctx) { if (!fmpq_mpoly_divides(a, b, c, ctx)) flint_throw(FLINT_ERROR, "fmpq_mpoly_void_divexact: nonexact"); } static int fmpq_mpoly_void_divides(void * a, const void * b, const void * c, const void * ctx) { return fmpq_mpoly_divides(a, b, c, ctx); } static int fmpq_mpoly_void_pow_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { return fmpq_mpoly_pow_fmpz(a, b, c, ctx); } static slong fmpq_mpoly_void_length(const void * a, const void * ctx) { return fmpq_mpoly_length(a, ctx); } void mpoly_void_ring_init_fmpq_mpoly_ctx( mpoly_void_ring_t R, const fmpq_mpoly_ctx_t ctx) { R->elem_size = sizeof(fmpq_mpoly_struct); R->ctx = ctx; R->init = fmpq_mpoly_void_init; R->clear = fmpq_mpoly_void_clear; R->is_zero = fmpq_mpoly_void_is_zero; R->zero = fmpq_mpoly_void_zero; R->one = fmpq_mpoly_void_one; R->set = fmpq_mpoly_void_set; R->set_fmpz = fmpq_mpoly_void_set_fmpz; R->swap = fmpq_mpoly_void_swap; R->neg = fmpq_mpoly_void_neg; R->add = fmpq_mpoly_void_add; R->sub = fmpq_mpoly_void_sub; R->mul = fmpq_mpoly_void_mul; R->mul_fmpz = fmpq_mpoly_void_mul_fmpz; R->divexact = fmpq_mpoly_void_divexact; R->divides = fmpq_mpoly_void_divides; R->pow_fmpz = fmpq_mpoly_void_pow_fmpz; R->length = fmpq_mpoly_void_length; } flint-3.1.3/src/fmpq_mpoly_factor.h000066400000000000000000000063761461254215100173300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_MPOLY_FACTOR_H #define FMPQ_MPOLY_FACTOR_H #ifdef FMPQ_MPOLY_FACTOR_INLINES_C #define FMPQ_MPOLY_FACTOR_INLINE #else #define FMPQ_MPOLY_FACTOR_INLINE static inline #endif #include "fmpq_mpoly.h" #ifdef __cplusplus extern "C" { #endif void fmpq_mpoly_factor_init(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_factor_realloc(fmpq_mpoly_factor_t f, slong alloc, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_factor_fit_length(fmpq_mpoly_factor_t f, slong len, const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_factor_clear(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_FACTOR_INLINE slong fmpq_mpoly_factor_length(const fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { return f->num; } FMPQ_MPOLY_FACTOR_INLINE void fmpq_mpoly_factor_get_constant_fmpq(fmpq_t c, const fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { fmpq_set(c, f->constant); } FMPQ_MPOLY_FACTOR_INLINE void fmpq_mpoly_factor_get_base(fmpq_mpoly_t p, const fmpq_mpoly_factor_t f, slong i, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fmpq_mpoly_set(p, f->poly + i, ctx); } FMPQ_MPOLY_FACTOR_INLINE void fmpq_mpoly_factor_swap_base(fmpq_mpoly_t p, fmpq_mpoly_factor_t f, slong i, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fmpq_mpoly_swap(p, f->poly + i, ctx); } FMPQ_MPOLY_FACTOR_INLINE slong fmpq_mpoly_factor_get_exp_si(fmpq_mpoly_factor_t f, slong i, const fmpq_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); return fmpz_get_si(f->exp + i); } void fmpq_mpoly_factor_sort(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_factor_make_monic(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_factor_make_integral(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_factor_squarefree(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_factor(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); void _fmpq_mpoly_factor_swap_fmpz_mpoly_factor(fmpq_mpoly_factor_t f, fmpz_mpoly_factor_t g, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); int fmpq_mpoly_factor_expand(fmpq_mpoly_t A, const fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpq_mpoly_factor/000077500000000000000000000000001461254215100171435ustar00rootroot00000000000000flint-3.1.3/src/fmpq_mpoly_factor/clear.c000066400000000000000000000014021461254215100203720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly_factor.h" void fmpq_mpoly_factor_clear(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { if (f->alloc > 0) { slong i; for (i = 0; i < f->alloc; i++) { fmpq_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } flint_free(f->poly); flint_free(f->exp); } fmpq_clear(f->constant); } flint-3.1.3/src/fmpq_mpoly_factor/expand.c000066400000000000000000000021071461254215100205660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly_factor.h" int fmpq_mpoly_factor_expand( fmpq_mpoly_t A, const fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { int success = 1; slong i; fmpq_mpoly_t t1, t2; fmpq_mpoly_init(t1, ctx); fmpq_mpoly_init(t2, ctx); fmpq_mpoly_set_fmpq(A, f->constant, ctx); for (i = 0; i < f->num; i++) { if (fmpz_sgn(f->exp + i) < 0 || !fmpq_mpoly_pow_fmpz(t1, f->poly + i, f->exp + i, ctx)) { success = 0; goto cleanup; } fmpq_mpoly_mul(t2, A, t1, ctx); fmpq_mpoly_swap(A, t2, ctx); } cleanup: fmpq_mpoly_clear(t1, ctx); fmpq_mpoly_clear(t2, ctx); return success; } flint-3.1.3/src/fmpq_mpoly_factor/factor.c000066400000000000000000000015411461254215100205660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "fmpq_mpoly_factor.h" int fmpq_mpoly_factor(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { int success; fmpz_mpoly_factor_t zf; fmpz_mpoly_factor_init(zf, ctx->zctx); success = fmpz_mpoly_factor(zf, A->zpoly, ctx->zctx); _fmpq_mpoly_factor_swap_fmpz_mpoly_factor(f, zf, A->content, ctx); fmpz_mpoly_factor_clear(zf, ctx->zctx); return success; } flint-3.1.3/src/fmpq_mpoly_factor/factor_make_integral.c000066400000000000000000000017151461254215100234530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly_factor.h" int fmpq_mpoly_factor_make_integral(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { int success = 1; slong i; fmpq_t t; fmpq_init(t); for (i = 0; i < f->num; i++) { success = !fmpq_is_zero(f->poly[i].content) && fmpq_pow_fmpz(t, f->poly[i].content, f->exp + i); if (!success) goto cleanup; fmpq_mul(f->constant, f->constant, t); fmpq_one(f->poly[i].content); } cleanup: fmpq_clear(t); return success; } flint-3.1.3/src/fmpq_mpoly_factor/factor_make_monic.c000066400000000000000000000023271461254215100227530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly_factor.h" int fmpq_mpoly_factor_make_monic(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { int success = 1; slong i; fmpq_t t; fmpq_init(t); for (i = 0; i < f->num; i++) { if (fmpq_is_zero(f->poly[i].content) || f->poly[i].zpoly->length < 1) { success = 0; goto cleanup; } fmpq_div_fmpz(t, f->poly[i].content, f->poly[i].zpoly->coeffs + 0); if (!fmpq_pow_fmpz(t, t, f->exp + i)) { success = 0; goto cleanup; } fmpq_div(f->constant, f->constant, t); fmpz_one(fmpq_numref(f->poly[i].content)); fmpz_set(fmpq_denref(f->poly[i].content), f->poly[i].zpoly->coeffs + 0); } cleanup: fmpq_clear(t); return success; } flint-3.1.3/src/fmpq_mpoly_factor/factor_squarefree.c000066400000000000000000000015671461254215100230200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "fmpq_mpoly_factor.h" int fmpq_mpoly_factor_squarefree(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx) { int success; fmpz_mpoly_factor_t zf; fmpz_mpoly_factor_init(zf, ctx->zctx); success = fmpz_mpoly_factor_squarefree(zf, A->zpoly, ctx->zctx); _fmpq_mpoly_factor_swap_fmpz_mpoly_factor(f, zf, A->content, ctx); fmpz_mpoly_factor_clear(zf, ctx->zctx); return success; } flint-3.1.3/src/fmpq_mpoly_factor/fit_length.c000066400000000000000000000012751461254215100214370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly_factor.h" void fmpq_mpoly_factor_fit_length(fmpq_mpoly_factor_t f, slong len, const fmpq_mpoly_ctx_t ctx) { if (len > f->alloc) { len = FLINT_MAX(len, f->alloc + f->alloc/2); fmpq_mpoly_factor_realloc(f, len, ctx); } } flint-3.1.3/src/fmpq_mpoly_factor/init.c000066400000000000000000000011621461254215100202520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly_factor.h" void fmpq_mpoly_factor_init(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { fmpq_init(f->constant); fmpq_one(f->constant); f->poly = NULL; f->exp = NULL; f->num = 0; f->alloc = 0; } flint-3.1.3/src/fmpq_mpoly_factor/inlines.c000066400000000000000000000007551461254215100207570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPQ_MPOLY_FACTOR_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fmpq_mpoly_factor.h" flint-3.1.3/src/fmpq_mpoly_factor/realloc.c000066400000000000000000000036451461254215100207400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly_factor.h" void fmpq_mpoly_factor_realloc(fmpq_mpoly_factor_t f, slong alloc, const fmpq_mpoly_ctx_t ctx) { slong i; if (alloc <= 0) { fmpq_mpoly_factor_clear(f, ctx); fmpq_mpoly_factor_init(f, ctx); return; } if (f->alloc > 0) { if (f->alloc > alloc) { for (i = alloc; i < f->alloc; i++) { fmpq_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fmpq_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fmpq_mpoly_struct)); } else if (f->alloc < alloc) { f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fmpq_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fmpq_mpoly_struct)); for (i = f->alloc; i < alloc; i++) { fmpq_mpoly_init(f->poly + i, ctx); fmpz_init(f->exp + i); } } } else { f->exp = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); f->poly = (fmpq_mpoly_struct *) flint_malloc(alloc * sizeof(fmpq_mpoly_struct)); for (i = 0; i < alloc; i++) fmpq_mpoly_init(f->poly + i, ctx); } f->alloc = alloc; } flint-3.1.3/src/fmpq_mpoly_factor/sort.c000066400000000000000000000034431461254215100203020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly_factor.h" typedef struct { slong idx; fmpz exp; const fmpq_mpoly_struct * polys; const fmpq_mpoly_ctx_struct * ctx; } sort_struct; static int _sort(const void * a_, const void * b_) { int cmp; const sort_struct * a = (const sort_struct *) a_; const sort_struct * b = (const sort_struct *) b_; const fmpq_mpoly_struct * apoly = a->polys + a->idx; const fmpq_mpoly_struct * bpoly = b->polys + b->idx; cmp = fmpz_cmp(&a->exp, &b->exp); if (cmp != 0) return cmp; return fmpq_mpoly_cmp(apoly, bpoly, a->ctx); } void fmpq_mpoly_factor_sort( fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx) { slong i; sort_struct * data; fmpq_mpoly_struct * fc; if (f->num < 1) return; data = (sort_struct *) flint_malloc(f->num*sizeof(sort_struct)); for (i = 0; i < f->num; i++) { data[i].idx = i; data[i].exp = f->exp[i]; data[i].polys = f->poly; data[i].ctx = ctx; } qsort(data, f->num, sizeof(sort_struct), _sort); /* we will not permute in place */ fc = (fmpq_mpoly_struct *) flint_malloc(f->num*sizeof(fmpq_mpoly_struct)); memcpy(fc, f->poly, f->num*sizeof(fmpq_mpoly_struct)); for (i = 0; i < f->num; i++) { f->exp[i] = data[i].exp; f->poly[i] = fc[data[i].idx]; } flint_free(fc); flint_free(data); } flint-3.1.3/src/fmpq_mpoly_factor/swap_fmpz_mpoly_factor.c000066400000000000000000000017231461254215100240760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "fmpq_mpoly_factor.h" /* f = g*c, clobber g */ void _fmpq_mpoly_factor_swap_fmpz_mpoly_factor( fmpq_mpoly_factor_t f, fmpz_mpoly_factor_t g, const fmpq_t c, const fmpq_mpoly_ctx_t ctx) { slong i; fmpq_mpoly_factor_fit_length(f, g->num, ctx); for (i = 0; i < g->num; i++) { fmpz_swap(f->exp + i, g->exp + i); fmpq_one(f->poly[i].content); fmpz_mpoly_swap(f->poly[i].zpoly, g->poly + i, ctx->zctx); fmpq_mpoly_reduce(f->poly + i, ctx); /* just in case */ } f->num = g->num; fmpq_mul_fmpz(f->constant, c, g->constant); } flint-3.1.3/src/fmpq_mpoly_factor/test/000077500000000000000000000000001461254215100201225ustar00rootroot00000000000000flint-3.1.3/src/fmpq_mpoly_factor/test/main.c000066400000000000000000000014011461254215100212060ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpq_mpoly_factor) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpq_mpoly_factor/test/t-factor.c000066400000000000000000000110741461254215100220100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mpoly_factor.h" void check_omega(slong lower, slong upper, const fmpq_mpoly_t p, const fmpq_mpoly_ctx_t ctx) { slong i; fmpq_t t; fmpq_mpoly_t q; fmpq_mpoly_factor_t g, h; fmpz_t omega; fmpq_init(t); fmpz_init(omega); fmpq_mpoly_factor_init(g, ctx); fmpq_mpoly_factor_init(h, ctx); fmpq_mpoly_init(q, ctx); if (!fmpq_mpoly_factor(g, p, ctx)) { flint_printf("check factorization could be computed\n"); fflush(stdout); flint_abort(); } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("factorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_factor_expand(q, g, ctx); if (!fmpq_mpoly_equal(q, p, ctx)) { flint_printf("factorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { fmpq_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpq_mpoly_factor_make_monic(g, ctx); for (i = 0; i < g->num; i++) { if (fmpq_mpoly_length(g->poly + i, ctx) < 1 || (fmpq_mpoly_get_term_coeff_fmpq(t, g->poly + i, 0, ctx), !fmpq_is_one(t))) { flint_printf("monic factorization is not monic\n"); fflush(stdout); flint_abort(); } } fmpq_mpoly_factor_expand(q, g, ctx); if (!fmpq_mpoly_equal(q, p, ctx)) { flint_printf("monic factorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_factor_make_integral(g, ctx); for (i = 0; i < g->num; i++) { if (fmpq_mpoly_length(g->poly + i, ctx) < 1 || (fmpq_mpoly_content(t, g->poly + i, ctx), !fmpq_is_one(t)) || (fmpq_mpoly_get_term_coeff_fmpq(t, g->poly + i, 0, ctx), fmpq_sgn(t) <= 0)) { flint_printf("integral factorization is not integral\n"); fflush(stdout); flint_abort(); } } fmpq_mpoly_factor_expand(q, g, ctx); if (!fmpq_mpoly_equal(q, p, ctx)) { flint_printf("integral factorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } fmpq_mpoly_clear(q, ctx); fmpq_mpoly_factor_clear(g, ctx); fmpq_mpoly_factor_clear(h, ctx); fmpz_clear(omega); fmpq_clear(t); } TEST_FUNCTION_START(fmpq_mpoly_factor, state) { slong i, j, tmul = 25; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpq_mpoly_ctx_t ctx; fmpq_mpoly_t a, t; flint_bitcnt_t coeff_bits; slong n, nfacs, len; ulong expbound, powbound, pow; fmpq_mpoly_ctx_init_rand(ctx, state, 8); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->zctx->minfo->nvars); nfacs = 1 + (5 + n_randint(state, 5))/n; expbound = 3 + 40/nfacs/n; powbound = 1 + n_randint(state, 3); lower = 0; fmpq_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { do { len = 1 + n_randint(state, 7); coeff_bits = 10 + n_randint(state, 200)/nfacs; fmpq_mpoly_randtest_bound(t, state, len, coeff_bits, expbound, ctx); } while (fmpq_mpoly_length(t, ctx) < 1); pow = 1 + n_randint(state, powbound); if (!fmpq_mpoly_is_fmpq(t, ctx)) lower += pow; fmpq_mpoly_pow_ui(t, t, pow, ctx); fmpq_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx); fmpq_mpoly_clear(t, ctx); fmpq_mpoly_clear(a, ctx); fmpq_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly.h000066400000000000000000000752411461254215100156120ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_POLY_H #define FMPQ_POLY_H #ifdef FMPQ_POLY_INLINES_C #define FMPQ_POLY_INLINE #else #define FMPQ_POLY_INLINE static inline #endif #include "fmpq_types.h" #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions ********************************************************/ typedef struct { fmpq_poly_struct * powers; slong len; } fmpq_poly_powers_precomp_struct; typedef fmpq_poly_powers_precomp_struct fmpq_poly_powers_precomp_t[1]; #define WEAK_CANONICALISE_CUTOFF 25600 /* Memory management *******************************************************/ void fmpq_poly_init(fmpq_poly_t poly); void fmpq_poly_init2(fmpq_poly_t poly, slong alloc); void fmpq_poly_realloc(fmpq_poly_t poly, slong alloc); void fmpq_poly_fit_length(fmpq_poly_t poly, slong len); void _fmpq_poly_set_length(fmpq_poly_t poly, slong len); void fmpq_poly_clear(fmpq_poly_t poly); void _fmpq_poly_normalise(fmpq_poly_t poly); /* Accessing numerator and denominator *************************************/ #define fmpq_poly_numref(poly) ((poly)->coeffs) #define fmpq_poly_denref(poly) ((poly)->den) void fmpq_poly_get_numerator(fmpz_poly_t res, const fmpq_poly_t poly); void fmpq_poly_get_denominator(fmpz_t den, const fmpq_poly_t poly); /* Canonicalisation *************************************/ void _fmpq_poly_canonicalise(fmpz * rpoly, fmpz_t den, slong len); void fmpq_poly_canonicalise(fmpq_poly_t poly); int _fmpq_poly_is_canonical(const fmpz * poly, const fmpz_t den, slong len); int fmpq_poly_is_canonical(const fmpq_poly_t poly); /* Polynomial parameters ***************************************************/ FMPQ_POLY_INLINE slong fmpq_poly_degree(const fmpq_poly_t poly) { return poly->length - 1; } FMPQ_POLY_INLINE slong fmpq_poly_length(const fmpq_poly_t poly) { return poly->length; } /* Randomisation ***********************************************************/ void fmpq_poly_randtest(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits_in); void fmpq_poly_randtest_unsigned(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits_in); void fmpq_poly_randtest_not_zero(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits_in); /* Assignment and basic manipulation ***************************************/ void fmpq_poly_set(fmpq_poly_t poly1, const fmpq_poly_t poly2); void fmpq_poly_set_si(fmpq_poly_t poly, slong x); void fmpq_poly_set_ui(fmpq_poly_t poly, ulong x); void fmpq_poly_set_fmpz(fmpq_poly_t poly, const fmpz_t x); void fmpq_poly_set_fmpq(fmpq_poly_t poly, const fmpq_t x); void fmpq_poly_set_fmpz_poly(fmpq_poly_t rop, const fmpz_poly_t op); void _fmpq_poly_get_nmod_poly(nmod_poly_t rop, const fmpq_poly_t op); void fmpq_poly_get_nmod_poly_den(nmod_poly_t rop, const fmpq_poly_t op, int den); void fmpq_poly_get_nmod_poly(nmod_poly_t rop, const fmpq_poly_t op); void fmpq_poly_set_nmod_poly(fmpq_poly_t rop, const nmod_poly_t op); int _fmpq_poly_set_str(fmpz * poly, fmpz_t den, const char * str, slong len); int fmpq_poly_set_str(fmpq_poly_t poly, const char * str); char * fmpq_poly_get_str(const fmpq_poly_t poly); char * fmpq_poly_get_str_pretty(const fmpq_poly_t poly, const char * var); char * _fmpq_poly_get_str_pretty(const fmpz *poly, const fmpz_t den, slong len, const char *var); void fmpq_poly_zero(fmpq_poly_t poly); void fmpq_poly_one(fmpq_poly_t poly); void fmpq_poly_neg(fmpq_poly_t poly1, const fmpq_poly_t poly2); void fmpq_poly_inv(fmpq_poly_t poly1, const fmpq_poly_t poly2); void fmpq_poly_swap(fmpq_poly_t poly1, fmpq_poly_t poly2); void fmpq_poly_truncate(fmpq_poly_t poly, slong n); void fmpq_poly_set_trunc(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void fmpq_poly_get_slice(fmpq_poly_t rop, const fmpq_poly_t op, slong i, slong j); void fmpq_poly_reverse(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Getting and setting coefficients ****************************************/ void fmpq_poly_get_coeff_fmpz(fmpz_t x, const fmpq_poly_t poly, slong n); void fmpq_poly_get_coeff_fmpq(fmpq_t x, const fmpq_poly_t poly, slong n); void fmpq_poly_set_coeff_si(fmpq_poly_t poly, slong n, slong x); void fmpq_poly_set_coeff_ui(fmpq_poly_t poly, slong n, ulong x); void fmpq_poly_set_coeff_fmpz(fmpq_poly_t poly, slong n, const fmpz_t x); void fmpq_poly_set_coeff_fmpq(fmpq_poly_t poly, slong n, const fmpq_t x); /* Comparison **************************************************************/ int fmpq_poly_equal(const fmpq_poly_t poly1, const fmpq_poly_t poly2); int _fmpq_poly_cmp(const fmpz * lpoly, const fmpz_t lden, const fmpz * rpoly, const fmpz_t rden, slong len); int fmpq_poly_cmp(const fmpq_poly_t left, const fmpq_poly_t right); int _fmpq_poly_equal_trunc(const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n); int fmpq_poly_equal_trunc(const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); FMPQ_POLY_INLINE int fmpq_poly_is_zero(const fmpq_poly_t poly) { return poly->length == WORD(0); } int fmpq_poly_is_one(const fmpq_poly_t poly); FMPQ_POLY_INLINE int fmpq_poly_is_gen(const fmpq_poly_t op) { return (op->length) == 2 && (*(op->coeffs + 1) == WORD(1)) && (*(op->coeffs + 0) == WORD(0)) && (*(op->den) == WORD(1)); } /* Addition and subtraction ************************************************/ void _fmpq_poly_add(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2); void fmpq_poly_add(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); void _fmpq_poly_add_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, int can); void fmpq_poly_add_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can); void fmpq_poly_add_si(fmpq_poly_t res, const fmpq_poly_t poly, slong c); void fmpq_poly_add_fmpz(fmpq_poly_t res, const fmpq_poly_t poly, const fmpz_t c); void fmpq_poly_add_fmpq(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t c); void _fmpq_poly_add_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n); void fmpq_poly_add_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); void _fmpq_poly_add_series_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n, int can); void fmpq_poly_add_series_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n, int can); void _fmpq_poly_sub(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2); void fmpq_poly_sub(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); void fmpq_poly_sub_si(fmpq_poly_t res, const fmpq_poly_t poly, slong c); void fmpq_poly_si_sub(fmpq_poly_t res, slong c, const fmpq_poly_t poly); void fmpq_poly_sub_fmpz(fmpq_poly_t res, const fmpq_poly_t poly, const fmpz_t c); void fmpq_poly_fmpz_sub(fmpq_poly_t res, const fmpz_t c, const fmpq_poly_t poly); void fmpq_poly_sub_fmpq(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t c); void fmpq_poly_fmpq_sub(fmpq_poly_t res, const fmpq_t c, const fmpq_poly_t poly); void _fmpq_poly_sub_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, int can); void fmpq_poly_sub_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can); void _fmpq_poly_sub_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n); void fmpq_poly_sub_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); void _fmpq_poly_sub_series_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n, int can); void fmpq_poly_sub_series_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n, int can); /* Scalar multiplication and division **************************************/ void _fmpq_poly_scalar_mul_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c); void _fmpq_poly_scalar_mul_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c); void _fmpq_poly_scalar_mul_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c); void _fmpq_poly_scalar_mul_fmpq(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t r, const fmpz_t s); void fmpq_poly_scalar_mul_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c); void fmpq_poly_scalar_mul_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c); void fmpq_poly_scalar_mul_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c); void fmpq_poly_scalar_mul_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c); void _fmpq_poly_scalar_div_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c); void _fmpq_poly_scalar_div_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c); void _fmpq_poly_scalar_div_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c); void _fmpq_poly_scalar_div_fmpq(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t r, const fmpz_t s); void fmpq_poly_scalar_div_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c); void fmpq_poly_scalar_div_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c); void fmpq_poly_scalar_div_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c); void fmpq_poly_scalar_div_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c); /* Multiplication **********************************************************/ void _fmpq_poly_mul(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2); void fmpq_poly_mul(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); void _fmpq_poly_mullow(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n); void fmpq_poly_mullow(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); FMPQ_POLY_INLINE void fmpq_poly_addmul(fmpq_poly_t rop, const fmpq_poly_t op1, const fmpq_poly_t op2) { fmpq_poly_t t; fmpq_poly_init(t); fmpq_poly_mul(t, op1, op2); fmpq_poly_add(rop, rop, t); fmpq_poly_clear(t); } FMPQ_POLY_INLINE void fmpq_poly_submul(fmpq_poly_t rop, const fmpq_poly_t op1, const fmpq_poly_t op2) { fmpq_poly_t t; fmpq_poly_init(t); fmpq_poly_mul(t, op1, op2); fmpq_poly_sub(rop, rop, t); fmpq_poly_clear(t); } /* Powering ****************************************************************/ void _fmpq_poly_pow(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong e); void fmpq_poly_pow(fmpq_poly_t rpoly, const fmpq_poly_t poly, ulong e); void _fmpq_poly_pow_trunc(fmpz * res, fmpz_t resden, const fmpz * f, const fmpz_t fden, slong flen, ulong exp, slong len); void fmpq_poly_pow_trunc(fmpq_poly_t res, const fmpq_poly_t poly, ulong exp, slong len); /* Shifting ****************************************************************/ void fmpq_poly_shift_left(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void fmpq_poly_shift_right(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Euclidean division ******************************************************/ #ifdef FMPZ_H void _fmpq_poly_divrem(fmpz * Q, fmpz_t q, fmpz * R, fmpz_t r, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv); void _fmpq_poly_div(fmpz * Q, fmpz_t q, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv); void _fmpq_poly_rem(fmpz * R, fmpz_t r, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv); #endif void fmpq_poly_divrem(fmpq_poly_t Q, fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2); void fmpq_poly_div(fmpq_poly_t Q, const fmpq_poly_t poly1, const fmpq_poly_t poly2); void fmpq_poly_rem(fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2); /* Precomputed inverse *****************************************************/ fmpq_poly_struct * _fmpq_poly_powers_precompute(const fmpz * B, const fmpz_t denB, slong len); void fmpq_poly_powers_precompute(fmpq_poly_powers_precomp_t pinv, fmpq_poly_t poly); void _fmpq_poly_powers_clear(fmpq_poly_struct * powers, slong len); void fmpq_poly_powers_clear(fmpq_poly_powers_precomp_t pinv); void _fmpq_poly_rem_powers_precomp(fmpz * A, fmpz_t denA, slong m, const fmpz * B, const fmpz_t denB, slong n, fmpq_poly_struct * const powers); void fmpq_poly_rem_powers_precomp(fmpq_poly_t R, const fmpq_poly_t A, const fmpq_poly_t B, const fmpq_poly_powers_precomp_t B_inv); /* Divisibility testing ******************************************************/ int _fmpq_poly_divides(fmpz * qpoly, fmpz_t qden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2); int fmpq_poly_divides(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2); slong fmpq_poly_remove(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2); /* Power series division ***************************************************/ void _fmpq_poly_inv_series_newton(fmpz * Qinv, fmpz_t Qinvden, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n); void fmpq_poly_inv_series_newton(fmpq_poly_t Qinv, const fmpq_poly_t Q, slong n); FMPQ_POLY_INLINE void _fmpq_poly_inv_series(fmpz * Qinv, fmpz_t Qinvden, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n) { _fmpq_poly_inv_series_newton(Qinv, Qinvden, Q, Qden, Qlen, n); } FMPQ_POLY_INLINE void fmpq_poly_inv_series(fmpq_poly_t Qinv, const fmpq_poly_t Q, slong n) { fmpq_poly_inv_series_newton(Qinv, Q, n); } void _fmpq_poly_div_series(fmpz * Q, fmpz_t denQ, const fmpz * A, const fmpz_t denA, slong lenA, const fmpz * B, const fmpz_t denB, slong lenB, slong n); void fmpq_poly_div_series(fmpq_poly_t Q, const fmpq_poly_t A, const fmpq_poly_t B, slong n); /* Greatest common divisor **************************************************/ void _fmpq_poly_gcd(fmpz *G, fmpz_t denG, const fmpz *A, slong lenA, const fmpz *B, slong lenB); void fmpq_poly_gcd(fmpq_poly_t G, const fmpq_poly_t A, const fmpq_poly_t B); void _fmpq_poly_xgcd(fmpz *G, fmpz_t denG, fmpz *S, fmpz_t denS, fmpz *T, fmpz_t denT, const fmpz *A, const fmpz_t denA, slong lenA, const fmpz *B, const fmpz_t denB, slong lenB); void fmpq_poly_xgcd(fmpq_poly_t G, fmpq_poly_t S, fmpq_poly_t T, const fmpq_poly_t A, const fmpq_poly_t B); void _fmpq_poly_lcm(fmpz *G, fmpz_t denG, const fmpz *A, slong lenA, const fmpz *B, slong lenB); void fmpq_poly_lcm(fmpq_poly_t L, const fmpq_poly_t A, const fmpq_poly_t B); void _fmpq_poly_resultant(fmpz_t rnum, fmpz_t rden, const fmpz *poly1, const fmpz_t den1, slong len1, const fmpz *poly2, const fmpz_t den2, slong len2); void fmpq_poly_resultant(fmpq_t r, const fmpq_poly_t f, const fmpq_poly_t g); void _fmpq_poly_resultant_div(fmpz_t rnum, fmpz_t rden, const fmpz *poly1, const fmpz_t den1, slong len1, const fmpz *poly2, const fmpz_t den2, slong len2, const fmpz_t divisor, slong nbits); void fmpq_poly_resultant_div(fmpq_t r, const fmpq_poly_t f, const fmpq_poly_t g, const fmpz_t divisor, slong nbits); /* Derivative and integral *************************************************/ void _fmpq_poly_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); void fmpq_poly_derivative(fmpq_poly_t res, const fmpq_poly_t poly); void _fmpq_poly_nth_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, ulong n, slong len); void fmpq_poly_nth_derivative(fmpq_poly_t res, const fmpq_poly_t poly, ulong n); void _fmpq_poly_integral(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); void fmpq_poly_integral(fmpq_poly_t res, const fmpq_poly_t poly); /* Square roots ************************************************************/ void _fmpq_poly_invsqrt_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong n); void fmpq_poly_invsqrt_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_sqrt_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong n); void fmpq_poly_sqrt_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Power sums ****************************************************************/ void _fmpq_poly_power_sums(fmpz * res, fmpz_t rden, const fmpz * poly, slong len, slong n); void fmpq_poly_power_sums(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, const fmpz_t den, slong len); void fmpq_poly_power_sums_to_fmpz_poly(fmpz_poly_t res, const fmpq_poly_t Q); void fmpq_poly_power_sums_to_poly(fmpq_poly_t res, const fmpq_poly_t Q); /* Transcendental functions ************************************************/ void _fmpq_poly_log_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n); void fmpq_poly_log_series(fmpq_poly_t res, const fmpq_poly_t f, slong n); void _fmpq_poly_exp_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_exp_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_exp_expinv_series(fmpz * g, fmpz_t gden, fmpz * r, fmpz_t rden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_exp_expinv_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n); void _fmpq_poly_atan_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_atan_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_atanh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_atanh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_asin_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_asin_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_asinh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_asinh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_tan_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_tan_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_sin_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_sin_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_cos_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_cos_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_sin_cos_series(fmpz * s, fmpz_t sden, fmpz * c, fmpz_t cden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_sin_cos_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n); void _fmpq_poly_sinh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_sinh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_cosh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_cosh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_sinh_cosh_series(fmpz * s, fmpz_t sden, fmpz * c, fmpz_t cden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_sinh_cosh_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n); void _fmpq_poly_tanh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); void fmpq_poly_tanh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Orthogonal polynomials ***************************************************/ void _fmpq_poly_legendre_p(fmpz * coeffs, fmpz_t den, ulong n); void fmpq_poly_legendre_p(fmpq_poly_t poly, ulong n); void _fmpq_poly_laguerre_l(fmpz * coeffs, fmpz_t den, ulong n); void fmpq_poly_laguerre_l(fmpq_poly_t poly, ulong n); void _fmpq_poly_gegenbauer_c(fmpz * coeffs, fmpz_t den, ulong n, const fmpq_t a); void fmpq_poly_gegenbauer_c(fmpq_poly_t poly, ulong n, const fmpq_t a); /* Evaluation **************************************************************/ void _fmpq_poly_evaluate_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t a); void fmpq_poly_evaluate_fmpz(fmpq_t res, const fmpq_poly_t poly, const fmpz_t a); void _fmpq_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t anum, const fmpz_t aden); void fmpq_poly_evaluate_fmpq(fmpq_t res, const fmpq_poly_t poly, const fmpq_t a); /* Interpolation ************************************************************/ void _fmpq_poly_interpolate_fmpz_vec(fmpz * poly, fmpz_t den, const fmpz * xs, const fmpz * ys, slong n); void fmpq_poly_interpolate_fmpz_vec(fmpq_poly_t poly, const fmpz * xs, const fmpz * ys, slong n); /* Composition *************************************************************/ void _fmpq_poly_compose(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2); void fmpq_poly_compose(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); void _fmpq_poly_rescale(fmpz * res, fmpz_t denr, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t xnum, const fmpz_t xden); void fmpq_poly_rescale(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t x); /* Power series composition ************************************************/ void _fmpq_poly_compose_series_horner(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n); void fmpq_poly_compose_series_horner(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); void _fmpq_poly_compose_series_brent_kung(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n); void fmpq_poly_compose_series_brent_kung(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); void _fmpq_poly_compose_series(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n); void fmpq_poly_compose_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); /* Power series reversion ************************************************/ void _fmpq_poly_revert_series_lagrange(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); void fmpq_poly_revert_series_lagrange(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_revert_series_lagrange_fast(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); void fmpq_poly_revert_series_lagrange_fast(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_revert_series_newton(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); void fmpq_poly_revert_series_newton(fmpq_poly_t res, const fmpq_poly_t poly, slong n); void _fmpq_poly_revert_series(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); void fmpq_poly_revert_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Gaussian content ********************************************************/ void _fmpq_poly_content(fmpq_t res, const fmpz * poly, const fmpz_t den, slong len); void fmpq_poly_content(fmpq_t res, const fmpq_poly_t poly); void _fmpq_poly_primitive_part(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); void fmpq_poly_primitive_part(fmpq_poly_t res, const fmpq_poly_t poly); int _fmpq_poly_is_monic(const fmpz * poly, const fmpz_t den, slong len); int fmpq_poly_is_monic(const fmpq_poly_t poly); void _fmpq_poly_make_monic(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); void fmpq_poly_make_monic(fmpq_poly_t res, const fmpq_poly_t poly); /* Square-free *************************************************************/ int fmpq_poly_is_squarefree(const fmpq_poly_t poly); /* Input and output *********************************************************/ #ifdef FLINT_HAVE_FILE int _fmpq_poly_fprint(FILE * file, const fmpz * poly, const fmpz_t den, slong len); int fmpq_poly_fprint(FILE * file, const fmpq_poly_t poly); int _fmpq_poly_fprint_pretty(FILE * file, const fmpz * poly, const fmpz_t den, slong len, const char * x); int fmpq_poly_fprint_pretty(FILE * file, const fmpq_poly_t poly, const char * var); int fmpq_poly_fread(FILE * file, fmpq_poly_t poly); #endif int _fmpq_poly_print(const fmpz * poly, const fmpz_t den, slong len); int fmpq_poly_print(const fmpq_poly_t poly); int _fmpq_poly_print_pretty(const fmpz *poly, const fmpz_t den, slong len, const char * x); int fmpq_poly_print_pretty(const fmpq_poly_t poly, const char * var); int fmpq_poly_read(fmpq_poly_t poly); int fmpq_poly_debug(const fmpq_poly_t poly); /* Declare dead functions ****************************************************/ #define fmpq_poly_set_mpz _Pragma("GCC error \"'fmpq_poly_set_mpz' is deprecated. Use 'fmpq_poly_set_fmpz' instead.\"") #define fmpq_poly_set_mpq _Pragma("GCC error \"'fmpq_poly_set_mpq' is deprecated. Use 'fmpq_poly_set_fmpq' instead.\"") #define _fmpq_poly_set_array_mpq _Pragma("GCC error \"'_fmpq_poly_set_array_mpq' is deprecated. Use 'fmpq_poly_set' instead.\"") #define fmpq_poly_set_array_mpq _Pragma("GCC error \"'fmpq_poly_set_array_mpq' is deprecated. Use 'fmpq_poly_set' instead.\"") #define fmpq_poly_get_coeff_mpq _Pragma("GCC error \"'fmpq_poly_get_coeff_mpq' is deprecated. Use 'fmpq_poly_get_coeff_fmpq' instead.\"") #define fmpq_poly_set_coeff_mpz _Pragma("GCC error \"'fmpq_poly_set_coeff_mpz' is deprecated. Use 'fmpq_poly_set_coeff_fmpz' instead.\"") #define fmpq_poly_set_coeff_mpq _Pragma("GCC error \"'fmpq_poly_set_coeff_mpq' is deprecated. Use 'fmpq_poly_set_coeff_fmpq' instead.\"") #define fmpq_poly_scalar_mul_mpz _Pragma("GCC error \"'fmpq_poly_scalar_mul_mpz' is deprecated. Use 'fmpq_poly_scalar_mul_fmpz' instead.\"") #define fmpq_poly_scalar_mul_mpq _Pragma("GCC error \"'fmpq_poly_scalar_mul_mpq' is deprecated. Use 'fmpq_poly_scalar_mul_fmpq' instead.\"") #define fmpq_poly_scalar_div_mpz _Pragma("GCC error \"'fmpq_poly_scalar_div_mpz' is deprecated. Use 'fmpq_poly_scalar_div_fmpz' instead.\"") #define fmpq_poly_scalar_div_mpq _Pragma("GCC error \"'fmpq_poly_scalar_div_mpq' is deprecated. Use 'fmpq_poly_scalar_div_fmpq' instead.\"") #define fmpq_poly_evaluate_mpz _Pragma("GCC error \"'fmpq_poly_evaluate_mpz' is deprecated. Use 'fmpq_poly_evaluate_fmpz' instead.\"") #define fmpq_poly_evaluate_mpq _Pragma("GCC error \"'fmpq_poly_evaluate_mpq' is deprecated. Use 'fmpq_poly_evaluate_fmpq' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpq_poly/000077500000000000000000000000001461254215100154305ustar00rootroot00000000000000flint-3.1.3/src/fmpq_poly/add.c000066400000000000000000000140271461254215100163300ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_add_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, int can) { slong max = FLINT_MAX(len1, len2); slong min = FLINT_MIN(len1, len2); fmpz_t d; if (fmpz_equal(den1, den2)) { _fmpz_poly_add(rpoly, poly1, len1, poly2, len2); if (fmpz_is_one(den1) || !can) fmpz_set(rden, den1); else { fmpz_init(d); _fmpz_vec_content_chained(d, rpoly, max, den1); if (fmpz_is_one(d)) fmpz_set(rden, den1); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d); fmpz_divexact(rden, den1, d); } fmpz_clear(d); } return; } fmpz_init(d); fmpz_one(d); if (!fmpz_is_one(den1) && !fmpz_is_one(den2)) fmpz_gcd(d, den1, den2); if (fmpz_is_one(d)) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den2); _fmpz_vec_scalar_addmul_fmpz(rpoly, poly2, min, den1); if (len1 < len2) _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den1); fmpz_mul(rden, den1, den2); } else { fmpz_t den11; fmpz_t den22; fmpz_init(den11); fmpz_init(den22); fmpz_divexact(den11, den1, d); fmpz_divexact(den22, den2, d); _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den22); _fmpz_vec_scalar_addmul_fmpz(rpoly, poly2, len2, den11); if (len1 < len2) _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den11); if (_fmpz_vec_is_zero(rpoly, max)) fmpz_one(rden); else { if (can) { fmpz_t e; fmpz_init(e); _fmpz_vec_content_chained(e, rpoly, max, d); if (fmpz_is_one(e)) fmpz_mul(rden, den1, den22); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e); fmpz_divexact(den11, den1, e); fmpz_mul(rden, den11, den22); } fmpz_clear(e); } else fmpz_mul(rden, den1, den22); } fmpz_clear(den11); fmpz_clear(den22); } fmpz_clear(d); } void _fmpq_poly_add(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) { _fmpq_poly_add_can(rpoly, rden, poly1, den1, len1, poly2, den2, len2, 1); } void fmpq_poly_add_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can) { slong len1 = poly1->length, len2, max; if (poly1 == poly2) /* Set res = 2 * poly1 */ { fmpq_poly_fit_length(res, len1); _fmpq_poly_set_length(res, len1); if (fmpz_is_even(poly1->den)) { _fmpz_vec_set(res->coeffs, poly1->coeffs, len1); fmpz_fdiv_q_2exp(res->den, poly1->den, 1); } else { _fmpz_vec_scalar_mul_2exp(res->coeffs, poly1->coeffs, len1, 1); fmpz_set(res->den, poly1->den); } return; } len2 = poly2->length; max = FLINT_MAX(len1, len2); fmpq_poly_fit_length(res, max); if (res != poly2) _fmpq_poly_add_can(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, can); else _fmpq_poly_add_can(res->coeffs, res->den, poly2->coeffs, poly2->den, len2, poly1->coeffs, poly1->den, len1, can); _fmpq_poly_set_length(res, max); _fmpq_poly_normalise(res); } void fmpq_poly_add(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { fmpq_poly_add_can(res, poly1, poly2, 1); } void fmpq_poly_add_si(fmpq_poly_t res, const fmpq_poly_t poly, slong c) { if (c == 0) { fmpq_poly_set(res, poly); } else if (poly->length == 0) { fmpq_poly_set_si(res, c); } else { fmpz_t p, q; fmpz_init_set_si(p, c); *q = 1; fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_add(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, p, q, 1); _fmpq_poly_normalise(res); fmpz_clear(p); } } void fmpq_poly_add_fmpz(fmpq_poly_t res, const fmpq_poly_t poly, const fmpz_t c) { if (fmpz_is_zero(c)) { fmpq_poly_set(res, poly); } else if (poly->length == 0) { fmpq_poly_set_fmpz(res, c); } else { fmpz_t q; *q = 1; fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_add(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, c, q, 1); _fmpq_poly_normalise(res); } } void fmpq_poly_add_fmpq(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t c) { if (fmpq_is_zero(c)) { fmpq_poly_set(res, poly); } else if (poly->length == 0) { fmpq_poly_set_fmpq(res, c); } else { fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_add(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, fmpq_numref(c), fmpq_denref(c), 1); _fmpq_poly_normalise(res); } } flint-3.1.3/src/fmpq_poly/add_series.c000066400000000000000000000152371461254215100177060ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_add_series_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n, int can) { int trunc = 0; slong max, min; fmpz_t d; if (n < len1) { len1 = n; trunc = 1; } if (n < len2) { len2 = n; trunc = 1; } max = FLINT_MAX(len1, len2); min = FLINT_MIN(len1, len2); if (fmpz_equal(den1, den2)) { _fmpz_poly_add(rpoly, poly1, len1, poly2, len2); if (fmpz_is_one(den1) || !can) fmpz_set(rden, den1); else { fmpz_init(d); _fmpz_vec_content_chained(d, rpoly, max, den1); if (fmpz_is_one(d)) fmpz_set(rden, den1); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d); fmpz_divexact(rden, den1, d); } fmpz_clear(d); } return; } fmpz_init(d); fmpz_one(d); if (!fmpz_is_one(den1) && !fmpz_is_one(den2)) fmpz_gcd(d, den1, den2); if (fmpz_is_one(d)) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den2); _fmpz_vec_scalar_addmul_fmpz(rpoly, poly2, min, den1); if (len1 < len2) _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den1); fmpz_mul(rden, den1, den2); /* may not be canonical if actual truncation happened */ if (can && trunc) { if (_fmpz_vec_is_zero(rpoly, max)) fmpz_one(rden); else { _fmpz_vec_content_chained(d, rpoly, max, rden); if (!fmpz_is_one(d)) { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d); fmpz_divexact(rden, rden, d); } } } } else { fmpz_t den11; fmpz_t den22; fmpz_init(den11); fmpz_init(den22); fmpz_divexact(den11, den1, d); fmpz_divexact(den22, den2, d); _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den22); _fmpz_vec_scalar_addmul_fmpz(rpoly, poly2, len2, den11); if (len1 < len2) _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den11); if (_fmpz_vec_is_zero(rpoly, max)) fmpz_one(rden); else { if (can) { fmpz_t e; fmpz_init(e); _fmpz_vec_content(e, rpoly, max); if (fmpz_is_one(e)) fmpz_mul(rden, den1, den22); else { if (trunc) /* there may be extra common factors if truncation occurred */ { fmpz_mul(rden, den1, den22); fmpz_gcd(e, e, rden); if (!fmpz_is_one(e)) { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e); fmpz_divexact(rden, rden, e); } } else { fmpz_gcd(e, e, d); if (fmpz_is_one(e)) fmpz_mul(rden, den1, den22); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e); fmpz_divexact(den11, den1, e); fmpz_mul(rden, den11, den22); } } } fmpz_clear(e); } else fmpz_mul(rden, den1, den22); } fmpz_clear(den11); fmpz_clear(den22); } fmpz_clear(d); } void _fmpq_poly_add_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) { _fmpq_poly_add_series_can(rpoly, rden, poly1, den1, len1, poly2, den2, len2, n, 1); } void fmpq_poly_add_series_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n, int can) { slong len1 = poly1->length, len2, max; if (n < 0) n = 0; if (poly1 == poly2) /* Set res = 2 * poly1 */ { len1 = FLINT_MIN(len1, n); fmpq_poly_fit_length(res, len1); _fmpq_poly_set_length(res, len1); if (fmpz_is_even(poly1->den)) { _fmpz_vec_set(res->coeffs, poly1->coeffs, len1); fmpz_fdiv_q_2exp(res->den, poly1->den, 1); } else { _fmpz_vec_scalar_mul_2exp(res->coeffs, poly1->coeffs, len1, 1); fmpz_set(res->den, poly1->den); } /* may not be canonical if actual truncation happened */ if (len1 < poly1->length) { if (can) { fmpz_t e; fmpz_init(e); _fmpz_vec_content(e, res->coeffs, len1); if (!fmpz_is_one(e)) fmpz_gcd(e, e, res->den); if (!fmpz_is_one(e)) { _fmpz_vec_scalar_divexact_fmpz(res->coeffs, res->coeffs, len1, e); fmpz_divexact(res->den, res->den, e); } fmpz_clear(e); } _fmpq_poly_normalise(res); } return; } len2 = poly2->length; max = FLINT_MAX(len1, len2); max = FLINT_MIN(max, n); fmpq_poly_fit_length(res, max); if (res != poly2) _fmpq_poly_add_series_can(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, n, can); else _fmpq_poly_add_series_can(res->coeffs, res->den, poly2->coeffs, poly2->den, len2, poly1->coeffs, poly1->den, len1, n, can); _fmpq_poly_set_length(res, max); _fmpq_poly_normalise(res); } void fmpq_poly_add_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) { fmpq_poly_add_series_can(res, poly1, poly2, n, 1); } flint-3.1.3/src/fmpq_poly/asin_series.c000066400000000000000000000044661461254215100201120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_asin_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; slong h2len; hlen = FLINT_MIN(hlen, n); h2len = FLINT_MIN(2 * hlen - 1, n); if (hlen == 1) { _fmpz_vec_zero(g, n); fmpz_one(gden); return; } t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* asin(h(x)) = integral(h'(x)/sqrt(1-h(x)^2)) */ _fmpq_poly_mullow(u, uden, h, hden, hlen, h, hden, hlen, h2len); _fmpq_poly_canonicalise(u, uden, h2len); _fmpz_vec_neg(u, u, h2len); fmpz_set(u, uden); /* u += 1 */ _fmpq_poly_invsqrt_series(t, tden, u, uden, h2len, n); _fmpq_poly_derivative(u, uden, h, hden, hlen); _fmpq_poly_mullow(g, gden, t, tden, n, u, uden, hlen - 1, n); _fmpq_poly_canonicalise(g, gden, n - 1); _fmpq_poly_integral(g, gden, g, gden, n); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void fmpq_poly_asin_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_asin_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_asin_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_asin_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/asinh_series.c000066400000000000000000000044341461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_asinh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; slong h2len; hlen = FLINT_MIN(hlen, n); h2len = FLINT_MIN(2 * hlen - 1, n); if (hlen == 1) { _fmpz_vec_zero(g, n); fmpz_one(gden); return; } t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* asinh(h(x)) = integral(h'(x)/sqrt(1+h(x)^2)) */ _fmpq_poly_mullow(u, uden, h, hden, hlen, h, hden, hlen, h2len); _fmpq_poly_canonicalise(u, uden, h2len); fmpz_set(u, uden); /* u += 1 */ _fmpq_poly_invsqrt_series(t, tden, u, uden, h2len, n); _fmpq_poly_derivative(u, uden, h, hden, hlen); _fmpq_poly_mullow(g, gden, t, tden, n, u, uden, hlen - 1, n); _fmpq_poly_canonicalise(g, gden, n - 1); _fmpq_poly_integral(g, gden, g, gden, n); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void fmpq_poly_asinh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_asinh_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_asinh_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_asinh_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/atan_series.c000066400000000000000000000043371461254215100201000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_atan_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; slong h2len; hlen = FLINT_MIN(hlen, n); h2len = FLINT_MIN(2 * hlen - 1, n); if (hlen == 1) { _fmpz_vec_zero(g, n); fmpz_one(gden); return; } t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* atan(h(x)) = integral(h'(x)/(1+h(x)^2)) */ _fmpq_poly_mullow(u, uden, h, hden, hlen, h, hden, hlen, h2len); _fmpq_poly_canonicalise(u, uden, h2len); fmpz_set(u, uden); /* u += 1 */ _fmpq_poly_derivative(t, tden, h, hden, hlen); _fmpq_poly_div_series(g, gden, t, tden, hlen - 1, u, uden, h2len, n); _fmpq_poly_canonicalise(g, gden, n - 1); _fmpq_poly_integral(g, gden, g, gden, n); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void fmpq_poly_atan_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_atan_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_atan_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_atan_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/atanh_series.c000066400000000000000000000044051461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_atanh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; slong h2len; hlen = FLINT_MIN(hlen, n); h2len = FLINT_MIN(2 * hlen - 1, n); if (hlen == 1) { _fmpz_vec_zero(g, n); fmpz_one(gden); return; } t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* atanh(h(x)) = integral(h'(x)/(1-h(x)^2)) */ _fmpq_poly_mullow(u, uden, h, hden, hlen, h, hden, hlen, h2len); _fmpq_poly_canonicalise(u, uden, h2len); _fmpz_vec_neg(u, u, h2len); fmpz_set(u, uden); /* u += 1 */ _fmpq_poly_derivative(t, tden, h, hden, hlen); _fmpq_poly_div_series(g, gden, t, tden, hlen - 1, u, uden, h2len, n); _fmpq_poly_canonicalise(g, gden, n - 1); _fmpq_poly_integral(g, gden, g, gden, n); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void fmpq_poly_atanh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_atanh_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_atanh_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_atanh_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/canonicalise.c000066400000000000000000000023251461254215100202260ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_canonicalise(fmpz * poly, fmpz_t den, slong len) { if (*den == WORD(1)) return; if (*den == WORD(-1)) { _fmpz_vec_neg(poly, poly, len); fmpz_one(den); } else if (len == 0) { fmpz_one(den); } else { fmpz_t gcd; fmpz_init(gcd); _fmpz_vec_content_chained(gcd, poly, len, den); if (fmpz_sgn(den) < 0) fmpz_neg(gcd, gcd); if (!fmpz_is_one(gcd)) { _fmpz_vec_scalar_divexact_fmpz(poly, poly, len, gcd); fmpz_divexact(den, den, gcd); } fmpz_clear(gcd); } } void fmpq_poly_canonicalise(fmpq_poly_t poly) { _fmpq_poly_normalise(poly); _fmpq_poly_canonicalise(poly->coeffs, poly->den, poly->length); } flint-3.1.3/src/fmpq_poly/clear.c000066400000000000000000000012771461254215100166710ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_clear(fmpq_poly_t poly) { if (poly->coeffs) { slong i; for (i = 0; i < poly->alloc; i++) _fmpz_demote(poly->coeffs + i); flint_free(poly->coeffs); } fmpz_clear(poly->den); } flint-3.1.3/src/fmpq_poly/cmp.c000066400000000000000000000044061461254215100163570ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" int _fmpq_poly_cmp(const fmpz * lpoly, const fmpz_t lden, const fmpz * rpoly, const fmpz_t rden, slong len) { int ans; slong i = len - 1; fmpz_t lcoeff, rcoeff; if (fmpz_equal(lden, rden)) { while (i && fmpz_equal(lpoly + i, rpoly + i)) i--; ans = fmpz_cmp(lpoly + i, rpoly + i); } else if (*lden == WORD(1)) /* Here rden exceeds 1 */ { fmpz_init(lcoeff); fmpz_mul(lcoeff, lpoly + i, rden); while (i && fmpz_equal(lcoeff, rpoly + i)) fmpz_mul(lcoeff, lpoly + (--i), rden); ans = fmpz_cmp(lcoeff, rpoly + i); fmpz_clear(lcoeff); } else if (*rden == WORD(1)) /* Here lden exceeds 1 */ { fmpz_init(rcoeff); fmpz_mul(rcoeff, rpoly + i, lden); while (i && fmpz_equal(rcoeff, lpoly + i)) fmpz_mul(rcoeff, rpoly + (--i), lden); ans = fmpz_cmp(lpoly + i, rcoeff); fmpz_clear(rcoeff); } else /* Here both lden, rden exceed 1 */ { fmpz_init(lcoeff); fmpz_init(rcoeff); fmpz_mul(lcoeff, lpoly + i, rden); fmpz_mul(rcoeff, rpoly + i, lden); while (i && fmpz_equal(lcoeff, rcoeff)) { i--; fmpz_mul(lcoeff, lpoly + i, rden); fmpz_mul(rcoeff, rpoly + i, lden); } ans = fmpz_cmp(lcoeff, rcoeff); fmpz_clear(lcoeff); fmpz_clear(rcoeff); } return ans; } int fmpq_poly_cmp(const fmpq_poly_t left, const fmpq_poly_t right) { slong len1, len2; if (left == right) return 0; len1 = left->length; len2 = right->length; if (len1 < len2) return -1; else if (len1 > len2) return 1; else if (len1 == 0) return 0; else return _fmpq_poly_cmp(left->coeffs, left->den, right->coeffs, right->den, len1); } flint-3.1.3/src/fmpq_poly/comparisons.c000066400000000000000000000010461461254215100201320ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" int fmpq_poly_is_one(const fmpq_poly_t poly) { return (poly->length == WORD(1)) && (fmpz_equal(poly->coeffs, poly->den)); } flint-3.1.3/src/fmpq_poly/compose.c000066400000000000000000000055601461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_compose(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) { if (*den2 == WORD(1)) { _fmpz_poly_compose(res, poly1, len1, poly2, len2); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, (len1 - WORD(1)) * (len2 - WORD(1)) + WORD(1)); } else { fmpz_t one; fmpz * v = _fmpz_vec_init(len1); fmpz_init(one); fmpz_one(one); _fmpq_poly_rescale(v, den, poly1, den1, len1, one, den2); _fmpz_poly_compose(res, v, len1, poly2, len2); _fmpq_poly_canonicalise(res, den, (len1 - WORD(1)) * (len2 - WORD(1)) + WORD(1)); fmpz_clear(one); _fmpz_vec_clear(v, len1); } } void fmpq_poly_compose(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; slong lenr; if (len1 == WORD(0)) { fmpq_poly_zero(res); return; } if (len1 == WORD(1) || len2 == WORD(0)) { fmpq_poly_fit_length(res, 1); fmpz_set(res->coeffs, poly1->coeffs); fmpz_set(res->den, poly1->den); { fmpz_t d; fmpz_init(d); fmpz_gcd(d, res->coeffs, res->den); if (*d != WORD(1)) { fmpz_divexact(res->coeffs, res->coeffs, d); fmpz_divexact(res->den, res->den, d); } fmpz_clear(d); } _fmpq_poly_set_length(res, 1); _fmpq_poly_normalise(res); return; } lenr = (len1 - WORD(1)) * (len2 - WORD(1)) + WORD(1); if ((res != poly1) && (res != poly2)) { fmpq_poly_fit_length(res, lenr); _fmpq_poly_compose(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2); _fmpq_poly_set_length(res, lenr); _fmpq_poly_normalise(res); } else { fmpq_poly_t t; fmpq_poly_init2(t, lenr); _fmpq_poly_compose(t->coeffs, t->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2); _fmpq_poly_set_length(t, lenr); _fmpq_poly_normalise(t); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } } flint-3.1.3/src/fmpq_poly/compose_series.c000066400000000000000000000054671461254215100206270ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_compose_series(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) { if (len1 <= 20) _fmpq_poly_compose_series_horner(res, den, poly1, den1, len1, poly2, den2, len2, n); else _fmpq_poly_compose_series_brent_kung(res, den, poly1, den1, len1, poly2, den2, len2, n); } void fmpq_poly_compose_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !fmpz_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "(fmpq_poly_compose_series): Inner polynomial \n" "must have zero constant term.\n"); } if (len1 == 0 || n == 0) { fmpq_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { fmpq_poly_fit_length(res, 1); fmpz_set(res->coeffs, poly1->coeffs); fmpz_set(res->den, poly1->den); { fmpz_t d; fmpz_init(d); fmpz_gcd(d, res->coeffs, res->den); if (!fmpz_is_one(d)) { fmpz_divexact(res->coeffs, res->coeffs, d); fmpz_divexact(res->den, res->den, d); } fmpz_clear(d); } _fmpq_poly_set_length(res, 1); _fmpq_poly_normalise(res); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { fmpq_poly_fit_length(res, lenr); _fmpq_poly_compose_series(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, lenr); _fmpq_poly_set_length(res, lenr); _fmpq_poly_normalise(res); } else { fmpq_poly_t t; fmpq_poly_init2(t, lenr); _fmpq_poly_compose_series(t->coeffs, t->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, lenr); _fmpq_poly_set_length(t, lenr); _fmpq_poly_normalise(t); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } } flint-3.1.3/src/fmpq_poly/compose_series_brent_kung.c000066400000000000000000000134461461254215100230410ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_mat.h" #include "fmpq_poly.h" static void _fmpq_mat_get_row(fmpz * rnum, fmpz_t den, fmpq_mat_t A, slong i) { slong j; fmpz_t t; fmpz_init(t); fmpz_one(den); for (j = 0; j < fmpq_mat_ncols(A); j++) fmpz_lcm(den, den, fmpq_mat_entry_den(A, i, j)); for (j = 0; j < fmpq_mat_ncols(A); j++) { fmpz_divexact(t, den, fmpq_mat_entry_den(A, i, j)); fmpz_mul(rnum + j, fmpq_mat_entry_num(A, i, j), t); } fmpz_clear(t); } void _fmpq_poly_compose_series_brent_kung(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) { fmpq_mat_t A, B, C; fmpz_t tden, uden, hden; fmpz *t, *u, *h, *swap; slong i, j, m; if (fmpz_is_one(den2)) { _fmpz_poly_compose_series(res, poly1, len1, poly2, len2, n); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, n); return; } if (n == 1) { fmpz_set(res, poly1); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, 1); return; } m = n_sqrt(n) + 1; fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, m); fmpq_mat_init(C, m, n); fmpz_init(tden); fmpz_init(uden); fmpz_init(hden); h = _fmpz_vec_init(n); t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1; i++) { fmpz_set(fmpq_mat_entry_num(B, i / m, i % m), poly1 + i); fmpz_set(fmpq_mat_entry_den(B, i / m, i % m), den1); fmpq_canonicalise(fmpq_mat_entry(B, i / m, i % m)); } /* Set rows of A to powers of poly2 */ fmpq_set_si(fmpq_mat_entry(A, 0, 0), WORD(1), WORD(1)); for (i = 0; i < len2; i++) { fmpz_set(fmpq_mat_entry_num(A, 1, i), poly2 + i); fmpz_set(fmpq_mat_entry_den(A, 1, i), den2); fmpq_canonicalise(fmpq_mat_entry(A, 1, i)); } _fmpz_vec_set(h, poly2, len2); fmpz_set(hden, den2); for (i = 2; i < m; i++) { _fmpq_poly_mullow(t, tden, h, hden, n, poly2, den2, len2, n); _fmpq_poly_canonicalise(t, tden, n); for (j = 0; j < n; j++) { fmpz_set(fmpq_mat_entry_num(A, i, j), t + j); fmpz_set(fmpq_mat_entry_den(A, i, j), tden); fmpq_canonicalise(fmpq_mat_entry(A, i, j)); } swap = t; t = h; h = swap; fmpz_swap(hden, tden); } /* Compute h = poly2 ^ m */ _fmpq_poly_mullow(t, tden, h, hden, n, poly2, den2, len2, n); _fmpq_poly_canonicalise(t, tden, n); swap = t; t = h; h = swap; fmpz_swap(hden, tden); /* Matrix multiply */ fmpq_mat_mul(C, B, A); fmpq_mat_clear(A); fmpq_mat_clear(B); /* Evaluate block composition using the Horner scheme */ _fmpq_mat_get_row(res, den, C, m - 1); for (i = m - 2; i >= 0; i--) { _fmpq_poly_mullow(t, tden, res, den, n, h, hden, n, n); /* we could canonicalise t here, but it does not seem to make much of a difference */ _fmpq_mat_get_row(u, uden, C, i); _fmpq_poly_add(res, den, t, tden, n, u, uden, n); } _fmpq_poly_canonicalise(res, den, n); fmpq_mat_clear(C); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); _fmpz_vec_clear(h, n); fmpz_clear(tden); fmpz_clear(uden); fmpz_clear(hden); } void fmpq_poly_compose_series_brent_kung(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !fmpz_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "(fmpq_poly_compose_series_brent_kung): Inner polynomial must have zero constant term.\n"); } if (len1 == 0 || n == 0) { fmpq_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { fmpq_poly_fit_length(res, 1); fmpz_set(res->coeffs, poly1->coeffs); fmpz_set(res->den, poly1->den); { fmpz_t d; fmpz_init(d); fmpz_gcd(d, res->coeffs, res->den); if (!fmpz_is_one(d)) { fmpz_divexact(res->coeffs, res->coeffs, d); fmpz_divexact(res->den, res->den, d); } fmpz_clear(d); } _fmpq_poly_set_length(res, 1); _fmpq_poly_normalise(res); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { fmpq_poly_fit_length(res, lenr); _fmpq_poly_compose_series_brent_kung(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, lenr); _fmpq_poly_set_length(res, lenr); _fmpq_poly_normalise(res); } else { fmpq_poly_t t; fmpq_poly_init2(t, lenr); _fmpq_poly_compose_series_brent_kung(t->coeffs, t->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, lenr); _fmpq_poly_set_length(t, lenr); _fmpq_poly_normalise(t); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } } flint-3.1.3/src/fmpq_poly/compose_series_horner.c000066400000000000000000000100661461254215100221730ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_compose_series_horner(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) { if (fmpz_is_one(den2)) { _fmpz_poly_compose_series(res, poly1, len1, poly2, len2, n); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, n); } else if (n == 1) { fmpz_set(res, poly1); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, 1); } else { slong i = len1 - 1; slong lenr; fmpz_t tden; fmpz * t = _fmpz_vec_init(n); fmpz_init(tden); _fmpz_vec_zero(res, n); lenr = len2; _fmpq_poly_scalar_mul_fmpz(res, den, poly2, den2, len2, poly1 + i); _fmpq_poly_scalar_div_fmpz(res, den, res, den, len2, den1); i--; _fmpq_poly_add(res, den, res, den, len2, poly1 + i, den1, 1); _fmpq_poly_canonicalise(res, den, lenr); while (i > 0) { i--; if (lenr + len2 - 1 < n) { _fmpq_poly_mul(t, tden, res, den, lenr, poly2, den2, len2); lenr = lenr + len2 - 1; } else { _fmpq_poly_mullow(t, tden, res, den, lenr, poly2, den2, len2, n); lenr = n; } _fmpq_poly_canonicalise(t, tden, lenr); _fmpq_poly_add(res, den, t, tden, lenr, poly1 + i, den1, 1); } _fmpq_poly_canonicalise(res, den, n); _fmpz_vec_clear(t, n); fmpz_clear(tden); } } void fmpq_poly_compose_series_horner(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !fmpz_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "(fmpq_poly_compose_series_horner): " "Inner polynomial must have zero constant term.\n"); } if (len1 == 0 || n == 0) { fmpq_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { fmpq_poly_fit_length(res, 1); fmpz_set(res->coeffs, poly1->coeffs); fmpz_set(res->den, poly1->den); { fmpz_t d; fmpz_init(d); fmpz_gcd(d, res->coeffs, res->den); if (!fmpz_is_one(d)) { fmpz_divexact(res->coeffs, res->coeffs, d); fmpz_divexact(res->den, res->den, d); } fmpz_clear(d); } _fmpq_poly_set_length(res, 1); _fmpq_poly_normalise(res); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { fmpq_poly_fit_length(res, lenr); _fmpq_poly_compose_series_horner(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, lenr); _fmpq_poly_set_length(res, lenr); _fmpq_poly_normalise(res); } else { fmpq_poly_t t; fmpq_poly_init2(t, lenr); _fmpq_poly_compose_series_horner(t->coeffs, t->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, lenr); _fmpq_poly_set_length(t, lenr); _fmpq_poly_normalise(t); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } } flint-3.1.3/src/fmpq_poly/content.c000066400000000000000000000014171461254215100172510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_content(fmpq_t res, const fmpz * poly, const fmpz_t den, slong len) { _fmpz_poly_content(fmpq_numref(res), poly, len); fmpz_set(fmpq_denref(res), den); } void fmpq_poly_content(fmpq_t res, const fmpq_poly_t poly) { _fmpq_poly_content(res, poly->coeffs, poly->den, poly->length); } flint-3.1.3/src/fmpq_poly/cos_series.c000066400000000000000000000053671461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2011, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_sin_cos_series_basecase_can(fmpz * S, fmpz_t Sden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n, int can); void _fmpq_poly_cos_series_basecase(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * tmp; if (hlen == 1 || n == 1) { fmpz_one(g); _fmpz_vec_zero(g + 1, n - 1); fmpz_one(gden); return; } tmp = _fmpz_vec_init(n + 1); _fmpq_poly_sin_cos_series_basecase_can(tmp, tmp + 1, g, gden, h, hden, hlen, n, 2); _fmpz_vec_clear(tmp, n + 1); } void _fmpq_poly_cos_series_tangent(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2) */ fmpz_mul_ui(uden, hden, 2); _fmpq_poly_tan_series(t, tden, h, uden, hlen, n); _fmpq_poly_mullow(u, uden, t, tden, n, t, tden, n, n); _fmpq_poly_canonicalise(u, uden, n); _fmpz_vec_neg(t, u, n); fmpz_set(tden, uden); fmpz_set(t, tden); fmpz_set(u, uden); _fmpq_poly_div_series(g, gden, t, tden, n, u, uden, n, n); _fmpq_poly_canonicalise(g, gden, n); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void _fmpq_poly_cos_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { if (hlen < 20 || n < 20) _fmpq_poly_cos_series_basecase(g, gden, h, hden, hlen, n); else _fmpq_poly_cos_series_tangent(g, gden, h, hden, hlen, n); } void fmpq_poly_cos_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_zero(res); return; } if (poly->length == 0 || n == 1) { fmpq_poly_one(res); return; } if (!fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_cos_series). Constant term != 0.\n"); } fmpq_poly_fit_length(res, n); _fmpq_poly_cos_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/cosh_series.c000066400000000000000000000027531461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_cosh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz_t tden; t = _fmpz_vec_init(n); fmpz_init(tden); /* cosh(x) = (exp(x)+exp(-x))/2 */ _fmpq_poly_exp_expinv_series(g, gden, t, tden, h, hden, hlen, n); _fmpq_poly_add(g, gden, g, gden, n, t, tden, n); _fmpq_poly_scalar_div_ui(g, gden, g, gden, n, 2); _fmpz_vec_clear(t, n); fmpz_clear(tden); } void fmpq_poly_cosh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_zero(res); return; } if (poly->length == 0 || n == 1) { fmpq_poly_one(res); return; } if (!fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_cosh_series). Constant term != 0.\n"); } fmpq_poly_fit_length(res, n); _fmpq_poly_cosh_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/derivative.c000066400000000000000000000020741461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2021 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) { _fmpz_poly_derivative(rpoly, poly, len); fmpz_set(rden, den); _fmpq_poly_canonicalise(rpoly, rden, len - 1); } void fmpq_poly_derivative(fmpq_poly_t res, const fmpq_poly_t poly) { slong len = poly->length; if (len < 2) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, len - 1); _fmpq_poly_derivative(res->coeffs, res->den, poly->coeffs, poly->den, len); _fmpq_poly_set_length(res, len - 1); } flint-3.1.3/src/fmpq_poly/div.c000066400000000000000000000055711461254215100163660ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_div(fmpz * Q, fmpz_t q, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv) { slong lenQ = lenA - lenB + 1; ulong d; const fmpz * lead = B + (lenB - 1); if (lenB == 1) { _fmpq_poly_scalar_div_fmpq(Q, q, A, a, lenA, B, b); return; } /* From pseudo division over Z we have lead^d * A = Q * B + R and thus {A, a} = {b * Q, a * lead^d} * {B, b} + {R, a * lead^d}. */ _fmpz_poly_pseudo_div(Q, &d, A, lenA, B, lenB, inv); /* 1. lead^d == +-1. {Q, q} = {b Q, a} up to sign */ if (d == UWORD(0) || *lead == WORD(1) || *lead == WORD(-1)) { fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, a); if (*lead == WORD(-1) && d % UWORD(2)) _fmpz_vec_neg(Q, Q, lenQ); } /* 2. lead^d != +-1. {Q, q} = {b Q, a lead^d} */ else { /* TODO: Improve this. Clearly we do not need to compute den = a lead^d in many cases, but can determine the GCD from lead alone already. */ fmpz_t den; fmpz_init(den); fmpz_pow_ui(den, lead, d); fmpz_mul(den, a, den); fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, den); fmpz_clear(den); } } void fmpq_poly_div(fmpq_poly_t Q, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { slong lenA, lenB, lenQ; if (fmpq_poly_is_zero(poly2)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_div). Division by zero.\n"); } if (poly1->length < poly2->length) { fmpq_poly_zero(Q); return; } /* Deal with aliasing */ if (Q == poly1 || Q == poly2) { fmpq_poly_t tempQ; fmpq_poly_init(tempQ); fmpq_poly_div(tempQ, poly1, poly2); fmpq_poly_swap(Q, tempQ); fmpq_poly_clear(tempQ); return; } lenA = poly1->length; lenB = poly2->length; lenQ = lenA - lenB + 1; fmpq_poly_fit_length(Q, lenQ); _fmpq_poly_div(Q->coeffs, Q->den, poly1->coeffs, poly1->den, poly1->length, poly2->coeffs, poly2->den, poly2->length, NULL); _fmpq_poly_set_length(Q, lenQ); } flint-3.1.3/src/fmpq_poly/div_series.c000066400000000000000000000032251461254215100177320ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_div_series(fmpz * Q, fmpz_t Qden, const fmpz * A, const fmpz_t Aden, slong Alen, const fmpz * B, const fmpz_t Bden, slong Blen, slong n) { fmpz * C; fmpz_t Cden; C = _fmpz_vec_init(n); fmpz_init(Cden); _fmpq_poly_inv_series(C, Cden, B, Bden, Blen, n); _fmpq_poly_mullow(Q, Qden, A, Aden, Alen, C, Cden, n, n); _fmpz_vec_clear(C, n); fmpz_clear(Cden); } void fmpq_poly_div_series(fmpq_poly_t Q, const fmpq_poly_t A, const fmpq_poly_t B, slong n) { if (A->length == 0) { fmpq_poly_zero(Q); return; } if (B->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_div_series). Division by zero.\n"); } if (Q == A || Q == B) { fmpq_poly_t t; fmpq_poly_init2(t, n); fmpq_poly_div_series(t, A, B, n); fmpq_poly_swap(Q, t); fmpq_poly_clear(t); return; } fmpq_poly_fit_length(Q, n); _fmpq_poly_div_series(Q->coeffs, Q->den, A->coeffs, A->den, A->length, B->coeffs, B->den, B->length, n); _fmpq_poly_set_length(Q, n); fmpq_poly_canonicalise(Q); } flint-3.1.3/src/fmpq_poly/divides.c000066400000000000000000000055301461254215100172260ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" int _fmpq_poly_divides(fmpz * qpoly, fmpz_t qden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) { fmpz_t c1, c2, n; fmpz * poly2_pp, * poly1_pp; int divides; fmpz_init(c1); fmpz_init(c2); _fmpz_poly_content(c1, poly1, len1); _fmpz_poly_content(c2, poly2, len2); if (!fmpz_is_one(c1)) { poly1_pp = _fmpz_vec_init(len1); _fmpz_vec_scalar_divexact_fmpz(poly1_pp, poly1, len1, c1); } else poly1_pp = (fmpz *) poly1; if (!fmpz_is_one(c2)) { poly2_pp = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(poly2_pp, poly2, len2, c2); } else poly2_pp = (fmpz *) poly2; divides = _fmpz_poly_divides(qpoly, poly1_pp, len1, poly2_pp, len2); if (divides) { fmpz_init(n); _fmpq_mul(n, qden, c1, den1, den2, c2); _fmpz_vec_scalar_mul_fmpz(qpoly, qpoly, len1 - len2 + 1, n); fmpz_clear(n); } else fmpz_set_ui(qden, 1); if (!fmpz_is_one(c1)) _fmpz_vec_clear(poly1_pp, len1); if (!fmpz_is_one(c2)) _fmpz_vec_clear(poly2_pp, len2); fmpz_clear(c1); fmpz_clear(c2); return divides; } int fmpq_poly_divides(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { fmpz * qpoly; fmpz_t qden; slong len1, len2; int divides; len1 = poly1->length; len2 = poly2->length; if (len2 == 0) { if (len1 == 0) { fmpq_poly_zero(q); return 1; } else return 0; } if (fmpq_poly_is_zero(poly1)) { fmpq_poly_zero(q); return 1; } if (len2 > len1) return 0; fmpq_poly_fit_length(q, len1 - len2 + 1); if (q == poly1 || q == poly2) { qpoly = _fmpz_vec_init(len1 - len2 + 1); fmpz_init(qden); divides = _fmpq_poly_divides(qpoly, qden, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2); _fmpz_vec_set(q->coeffs, qpoly, len1 - len2 + 1); fmpz_set(q->den, qden); fmpz_clear(qden); _fmpz_vec_clear(qpoly, len1 - len2 + 1); } else divides = _fmpq_poly_divides(q->coeffs, q->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2); _fmpq_poly_set_length(q, len1 - len2 + 1); _fmpq_poly_normalise(q); return divides; } flint-3.1.3/src/fmpq_poly/divrem.c000066400000000000000000000107531461254215100170700ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_divrem(fmpz * Q, fmpz_t q, fmpz * R, fmpz_t r, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv) { slong lenQ = lenA - lenB + 1; slong lenR = lenB - 1; ulong d; const fmpz * lead = B + (lenB - 1); if (lenB == 1) { _fmpq_poly_scalar_div_fmpq(Q, q, A, a, lenA, B, b); fmpz_one(r); return; } /* From pseudo division over Z we have lead^d * A = Q * B + R and thus {A, a} = {b * Q, a * lead^d} * {B, b} + {R, a * lead^d}. */ _fmpz_poly_pseudo_divrem(Q, R, &d, A, lenA, B, lenB, inv); /* Determine the actual length of R */ for ( ; lenR != 0 && fmpz_is_zero(R + (lenR - 1)); lenR--) ; /* 1. lead^d == +-1. {Q, q} = {b Q, a}, {R, r} = {R, a} up to sign */ if (d == UWORD(0) || *lead == WORD(1) || *lead == WORD(-1)) { fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, a); fmpz_one(r); if (lenR > 0) _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, a); if (*lead == WORD(-1) && d % UWORD(2)) { _fmpz_vec_neg(Q, Q, lenQ); _fmpz_vec_neg(R, R, lenR); } } /* 2. lead^d != +-1. {Q, q} = {b Q, a lead^d}, {R, r} = {R, a lead^d} */ else { /* TODO: Improve this. Clearly we do not need to compute den = a lead^d in many cases, but can determine the GCD from lead alone already. */ fmpz_t den; fmpz_init(den); fmpz_pow_ui(den, lead, d); fmpz_mul(den, a, den); fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, den); fmpz_one(r); if (lenR > 0) _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, den); fmpz_clear(den); } } void fmpq_poly_divrem(fmpq_poly_t Q, fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { slong lenA, lenB, lenQ, lenR; if (fmpq_poly_is_zero(poly2)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_divrem). Division by zero.\n"); } if (Q == R) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_divrem). Output arguments aliased.\n"); } /* Deal with the various other cases of aliasing. */ if (R == poly1 || R == poly2) { if (Q == poly1 || Q == poly2) { fmpq_poly_t tempQ, tempR; fmpq_poly_init(tempQ); fmpq_poly_init(tempR); fmpq_poly_divrem(tempQ, tempR, poly1, poly2); fmpq_poly_swap(Q, tempQ); fmpq_poly_swap(R, tempR); fmpq_poly_clear(tempQ); fmpq_poly_clear(tempR); return; } else { fmpq_poly_t tempR; fmpq_poly_init(tempR); fmpq_poly_divrem(Q, tempR, poly1, poly2); fmpq_poly_swap(R, tempR); fmpq_poly_clear(tempR); return; } } else { if (Q == poly1 || Q == poly2) { fmpq_poly_t tempQ; fmpq_poly_init(tempQ); fmpq_poly_divrem(tempQ, R, poly1, poly2); fmpq_poly_swap(Q, tempQ); fmpq_poly_clear(tempQ); return; } } if (poly1->length < poly2->length) { fmpq_poly_set(R, poly1); fmpq_poly_zero(Q); return; } lenA = poly1->length; lenB = poly2->length; lenQ = lenA - lenB + 1; lenR = lenB - 1; fmpq_poly_fit_length(Q, lenQ); fmpq_poly_fit_length(R, lenA); /* XXX: Need at least that much space */ _fmpq_poly_divrem(Q->coeffs, Q->den, R->coeffs, R->den, poly1->coeffs, poly1->den, poly1->length, poly2->coeffs, poly2->den, poly2->length, NULL); _fmpq_poly_set_length(Q, lenQ); _fmpq_poly_set_length(R, lenR); _fmpq_poly_normalise(R); } flint-3.1.3/src/fmpq_poly/equal.c000066400000000000000000000012611461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" int fmpq_poly_equal(const fmpq_poly_t poly1, const fmpq_poly_t poly2) { return (poly1->length == poly2->length) && (fmpz_equal(poly1->den, poly2->den)) && (_fmpz_vec_equal(poly1->coeffs, poly2->coeffs, poly1->length)); } flint-3.1.3/src/fmpq_poly/equal_trunc.c000066400000000000000000000042421461254215100201200ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" int _fmpq_poly_equal_trunc(const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) { int res = 1; slong i; if (n < 0) n = 0; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (len1 > len2) { for (i = len2; i < len1; i++) { if (!fmpz_is_zero(poly1 + i)) return 0; } len1 = len2; } else if (len2 > len1) { for (i = len1; i < len2; i++) { if (!fmpz_is_zero(poly2 + i)) return 0; } } if (fmpz_equal(den1, den2)) return (_fmpz_vec_equal(poly1, poly2, len1)); else { fmpz_t p1, p2, d, d1, d2; fmpz_init(d); fmpz_init(p1); fmpz_init(p2); fmpz_init(d1); fmpz_init(d2); fmpz_gcd(d, den1, den2); if (!fmpz_is_one(d)) { fmpz_divexact(d1, den1, d); fmpz_divexact(d2, den2, d); } else { fmpz_set(d1, den1); fmpz_set(d2, den2); } for (i = 0; i < len1; i++) { fmpz_mul(p1, poly1 + i, d2); fmpz_mul(p2, poly2 + i, d1); if (!fmpz_equal(p1, p2)) { res = 0; break; } } fmpz_clear(d1); fmpz_clear(d2); fmpz_clear(p1); fmpz_clear(p2); fmpz_clear(d); } return res; } int fmpq_poly_equal_trunc(const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) { return _fmpq_poly_equal_trunc(poly1->coeffs, poly1->den, poly1->length, poly2->coeffs, poly2->den, poly2->length, n); } flint-3.1.3/src/fmpq_poly/evaluate.c000066400000000000000000000040651461254215100174070ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t anum, const fmpz_t aden) { fmpz_t d; _fmpz_poly_evaluate_fmpq(rnum, rden, poly, len, anum, aden); fmpz_mul(rden, rden, den); fmpz_init(d); fmpz_gcd(d, rnum, rden); if (!fmpz_is_one(d)) { fmpz_divexact(rnum, rnum, d); fmpz_divexact(rden, rden, d); } fmpz_clear(d); } void fmpq_poly_evaluate_fmpq(fmpq_t res, const fmpq_poly_t poly, const fmpq_t a) { if (res != a) { _fmpq_poly_evaluate_fmpq(fmpq_numref(res), fmpq_denref(res), poly->coeffs, poly->den, poly->length, fmpq_numref(a), fmpq_denref(a)); } else { fmpq_t t; fmpq_init(t); fmpq_set(t, a); fmpq_poly_evaluate_fmpq(res, poly, t); fmpq_clear(t); } } void _fmpq_poly_evaluate_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t a) { fmpz_t d; _fmpz_poly_evaluate_horner_fmpz(rnum, poly, len, a); fmpz_init(d); fmpz_gcd(d, rnum, den); if (*d != WORD(1)) { fmpz_divexact(rnum, rnum, d); fmpz_divexact(rden, den, d); } else { fmpz_set(rden, den); } fmpz_clear(d); } void fmpq_poly_evaluate_fmpz(fmpq_t res, const fmpq_poly_t poly, const fmpz_t a) { _fmpq_poly_evaluate_fmpz(fmpq_numref(res), fmpq_denref(res), poly->coeffs, poly->den, poly->length, a); } flint-3.1.3/src/fmpq_poly/exp_series.c000066400000000000000000000344041461254215100177470ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011, 2014, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" static ulong _fmpz_gcd_big_small(const fmpz_t g, ulong h) { __mpz_struct * z = COEFF_TO_PTR(*g); return n_gcd(mpn_mod_1(z->_mp_d, FLINT_ABS(z->_mp_size), h), h); } static ulong _fmpz_gcd_small(const fmpz_t g, ulong h) { if (!COEFF_IS_MPZ(*g)) return n_gcd(FLINT_ABS(*g), h); else return _fmpz_gcd_big_small(g, h); } /* Basecase algorithm, given a precomputed derivative of of the input series (Alen still refers to the length of the original series). */ void _fmpq_poly_exp_series_basecase_deriv(fmpz * B, fmpz_t Bden, const fmpz * Aprime, const fmpz_t Aden, slong Alen, slong n) { fmpz_t t, u; slong k; Alen = FLINT_MIN(Alen, n); fmpz_init(t); fmpz_init(u); fmpz_fac_ui(t, n - 1); fmpz_pow_ui(u, Aden, n - 1); fmpz_mul(Bden, t, u); fmpz_set(B, Bden); for (k = 1; k < n; k++) { slong l = FLINT_MIN(Alen - 1, k); _fmpz_vec_dot_general(t, NULL, 0, Aprime, B + k - l, 1, l); fmpz_mul_ui(u, Aden, k); fmpz_divexact(B + k, t, u); } _fmpq_poly_canonicalise(B, Bden, n); fmpz_clear(t); fmpz_clear(u); } /* Basecase algorithm; supports aliasing and guarantees canonical output. */ void _fmpq_poly_exp_series_basecase(fmpz * B, fmpz_t Bden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n) { fmpz * Aprime; fmpz_t Aden2; Alen = FLINT_MIN(Alen, n); Aprime = _fmpz_vec_init(Alen - 1); fmpz_init(Aden2); /* There is probably not much content, so avoid the overhead of canonicalising. */ if (Alen <= 6) { _fmpz_poly_derivative(Aprime, A, Alen); fmpz_set(Aden2, Aden); } else { _fmpq_poly_derivative(Aprime, Aden2, A, Aden, Alen); } _fmpq_poly_exp_series_basecase_deriv(B, Bden, Aprime, Aden2, Alen, n); _fmpz_vec_clear(Aprime, Alen - 1); fmpz_clear(Aden2); } /* c_k x^k -> c_k x^k / (m+k) */ void _fmpq_poly_integral_offset(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong m) { slong k; ulong v, c, d; mp_ptr divisors; fmpz_t t, u; TMP_INIT; TMP_START; divisors = TMP_ALLOC(sizeof(ulong) * len); fmpz_init(t); fmpz_one(t); for (k = len - 1; k >= 0; k--) { if (fmpz_is_zero(poly + k)) { fmpz_zero(rpoly + k); } else { c = _fmpz_gcd_small(poly + k, k + m); if (c == k + m) { fmpz_divexact_ui(rpoly + k, poly + k, k + m); divisors[k] = 1; } else { if (c == 1) { fmpz_set(rpoly + k, poly + k); divisors[k] = k + m; } else { fmpz_divexact_ui(rpoly + k, poly + k, c); divisors[k] = (k + m) / c; } c = divisors[k]; d = _fmpz_gcd_small(t, c); if (d != c) fmpz_mul_ui(t, t, c / d); } } } fmpz_mul(rden, den, t); if (!fmpz_is_one(t)) { if (!COEFF_IS_MPZ(*t)) { v = *t; for (k = len - 1; k >= 0; k--) { if (!fmpz_is_zero(rpoly + k) && v != divisors[k]) fmpz_mul_ui(rpoly + k, rpoly + k, divisors[k] == 1 ? v : v / divisors[k]); } } else { fmpz_init(u); for (k = len - 1; k >= 0; k--) { if (!fmpz_is_zero(rpoly + k)) { if (divisors[k] == 1) { fmpz_mul(rpoly + k, rpoly + k, t); } else { fmpz_divexact_ui(u, t, divisors[k]); fmpz_mul(rpoly + k, rpoly + k, u); } } } fmpz_clear(u); } } fmpz_clear(t); TMP_END; } static void MULLOW(fmpz * z, fmpz_t zden, const fmpz * x, const fmpz_t xden, slong xn, const fmpz * y, const fmpz_t yden, slong yn, slong n) { if (xn + yn - 1 < n) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (xn >= yn) _fmpz_poly_mullow(z, x, xn, y, yn, n); else _fmpz_poly_mullow(z, y, yn, x, xn, n); fmpz_mul(zden, xden, yden); } /* Assuming that the low m coefficients of poly have denominator den in canonical form and that the high n - m coefficients have denominator high_den in canonical form, combine the high and lower parts and put the polynomial in canonical form {poly, den, n}. */ static void CONCATENATE(fmpz * poly, fmpz_t den, const fmpz_t high_den, slong m, slong n) { fmpz_t gcd, d1, d2; fmpz_init(gcd); fmpz_init(d1); fmpz_init(d2); fmpz_gcd(gcd, den, high_den); fmpz_divexact(d1, high_den, gcd); fmpz_divexact(d2, den, gcd); _fmpz_vec_scalar_mul_fmpz(poly, poly, m, d1); _fmpz_vec_scalar_mul_fmpz(poly + m, poly + m, n - m, d2); fmpz_mul(den, d2, high_den); fmpz_clear(gcd); fmpz_clear(d1); fmpz_clear(d2); } /* Newton iteration. If g == NULL, computes {f, fden, n} = exp({h, hden, hlen}). If g != NULL, simultaneously computes {g, gden, n} = exp(-{h, hden, hlen}). Allows aliasing between (f, fden) and (h, hden) but not with (g, gden). */ void _fmpq_poly_exp_series_newton(fmpz * f, fmpz_t fden, fmpz * g, fmpz * gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { slong a[FLINT_BITS]; slong original_n, i, m, l, r, cutoff; fmpz * t, * hprime; fmpz_t tden, hprimeden, uden, d, hdenin; int inverse; /* If g is provided, we compute g = exp(-h), and we can use g as scratch space. Otherwise, we still need to compute exp(-h) to length (n+1)/2 for intermediate use, and we still need n coefficients of scratch space. */ original_n = n; inverse = (g != NULL); if (!inverse) { g = _fmpz_vec_init(n + 1); gden = g + n; } hlen = FLINT_MIN(hlen, n); t = _fmpz_vec_init(n); hprime = _fmpz_vec_init(hlen - 1); fmpz_init(tden); fmpz_init(hprimeden); fmpz_init(uden); fmpz_init(d); fmpz_init(hdenin); /* Precompute h' which is needed throughout. We will not canonicalise immediately; we want the truncated series to have minimal content in each step of the Newton iteration, so we canonicalise gradually. */ fmpz_set(hdenin, hden); fmpz_set(hprimeden, hden); _fmpz_poly_derivative(hprime, h, hlen); cutoff = 20 + 1000 / n_sqrt(fmpz_bits(hden)); for (i = 1; (WORD(1) << i) < n; i++); a[i = 0] = n; while (n >= cutoff || i == 0) a[++i] = (n = (n + 1) / 2); /* Canonicalise h' for first step. */ _fmpq_poly_canonicalise(hprime, hprimeden, FLINT_MIN(n, hlen) - 1); /* Initial approximation f := exp(h) + O(x^n) using basecase algorithm. */ _fmpq_poly_exp_series_basecase_deriv(f, fden, hprime, hprimeden, hlen, n); /* Initial approximation of inverse g := exp(-h) + O(x^n) */ _fmpq_poly_inv_series(g, gden, f, fden, n, n); for (i--; i >= 0; i--) { m = n; /* previous length */ n = a[i]; /* new length */ l = FLINT_MIN(hlen, n) - 1; r = FLINT_MIN(l + m - 1, n - 1); /* Extend h' */ if (l > m - 1) { fmpz_set(uden, hdenin); _fmpq_poly_canonicalise(hprime + m - 1, uden, l - m + 1); CONCATENATE(hprime, hprimeden, uden, m - 1, l); } MULLOW(t, tden, hprime, hprimeden, l, f, fden, m, r); _fmpq_poly_canonicalise(t + m - 1, tden, r + 1 - m); MULLOW(g + m, uden, g, gden, n - m, t + m - 1, tden, r + 1 - m, n - m); _fmpq_poly_canonicalise(g + m, uden, n - m); _fmpq_poly_integral_offset(g + m, uden, g + m, uden, n - m, m); MULLOW(f + m, uden, f, fden, n - m, g + m, uden, n - m, n - m); /* Assuming that the low part is canonicalised on input, we just need to canonicalise the high part. */ _fmpq_poly_canonicalise(f + m, uden, n - m); CONCATENATE(f, fden, uden, m, n); /* g := exp(-h) + O(x^n); not needed if we only want exp(x) */ if (i != 0 || inverse) { MULLOW(t, tden, f, fden, n, g, gden, m, n); _fmpq_poly_canonicalise(t + m, tden, n - m); MULLOW(g + m, uden, g, gden, m, t + m, tden, n - m, n - m); /* Assuming that the low part is canonicalised on input, we just need to canonicalise the high part. */ _fmpq_poly_canonicalise(g + m, uden, n - m); CONCATENATE(g, gden, uden, m, n); _fmpz_vec_neg(g + m, g + m, n - m); } } _fmpz_vec_clear(hprime, hlen - 1); _fmpz_vec_clear(t, original_n); fmpz_clear(tden); fmpz_clear(hprimeden); fmpz_clear(uden); fmpz_clear(d); fmpz_clear(hdenin); if (!inverse) _fmpz_vec_clear(g, original_n + 1); } void _fmpq_poly_exp_series(fmpz * B, fmpz_t Bden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n) { Alen = FLINT_MIN(Alen, n); if (Alen == 1) { fmpz_one(B); fmpz_one(Bden); _fmpz_vec_zero(B + 1, n - 1); return; } /* A is a monomial (p/q) * x^d */ if (_fmpz_vec_is_zero(A + 1, Alen - 2)) { fmpz * R; ulong v; slong i, d, m; d = Alen - 1; /* Degree of input monomial. */ m = (n - 1) / d; /* m*d is highest degree in output. */ R = _fmpz_vec_init(m + 1); /* A[d]/Aden could be non-canonical due to truncation */ fmpz_gcd(R, A + d, Aden); fmpz_divexact(B + d, A + d, R); fmpz_divexact(R, Aden, R); /* store q in R[0] */ fmpz_set(R + 1, R); fmpz_set(Bden, R); for (i = 2; i <= m; i++) { /* Computing (p/q)^i / i! from the previous term, we only need to remove the gcd between the numerator and i. */ fmpz_mul(B + i * d, B + (i - 1) * d, B + d); fmpz_mul(Bden, Bden, R); v = _fmpz_gcd_small(B + i * d, i); fmpz_divexact_ui(B + i * d, B + i * d, v); fmpz_mul_ui(Bden, Bden, i / v); fmpz_mul_ui(R + i, R, i / v); } /* Put all terms on the same denominator as the last term. */ for (i = m - 1; i > 0; i--) { fmpz_mul(B + i * d, B + i * d, R + m); fmpz_mul(R + m, R + m, R + i); } /* Constant term = 1. */ fmpz_set(B, Bden); for (i = 0; d != 1 && i < n; i++) if (i % d != 0) fmpz_zero(B + i); _fmpz_vec_clear(R, m + 1); return; } if (Alen <= 12 || n <= 10 + 1000 / n_sqrt(fmpz_bits(Aden))) { _fmpq_poly_exp_series_basecase(B, Bden, A, Aden, Alen, n); } else { _fmpq_poly_exp_series_newton(B, Bden, NULL, NULL, A, Aden, Alen, n); } } void _fmpq_poly_exp_expinv_series(fmpz * B, fmpz_t Bden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n) { Alen = FLINT_MIN(Alen, n); if (Alen == 1) { fmpz_one(B); fmpz_one(Bden); fmpz_one(C); fmpz_one(Cden); _fmpz_vec_zero(B + 1, n - 1); _fmpz_vec_zero(C + 1, n - 1); return; } if (_fmpz_vec_is_zero(A + 1, Alen - 2)) { slong i; _fmpq_poly_exp_series(B, Bden, A, Aden, Alen, n); _fmpz_vec_set(C, B, n); for (i = Alen - 1; i < n; i += 2 * (Alen - 1)) fmpz_neg(C + i, C + i); fmpz_set(Cden, Bden); return; } /* todo: tweak tuning for this function */ if (Alen <= 12 || n <= 10 + 1000 / n_sqrt(fmpz_bits(Aden))) { _fmpq_poly_exp_series_basecase(B, Bden, A, Aden, Alen, n); _fmpq_poly_inv_series(C, Cden, B, Bden, n, n); } else { fmpz * tmp; if (A == C || Aden == Cden) { tmp = _fmpz_vec_init(n + 1); _fmpq_poly_exp_series_newton(B, Bden, tmp, tmp + n, A, Aden, Alen, n); _fmpz_vec_swap(C, tmp, n); fmpz_swap(Cden, tmp + n); _fmpz_vec_clear(tmp, n); } else { _fmpq_poly_exp_series_newton(B, Bden, C, Cden, A, Aden, Alen, n); } } } void fmpq_poly_exp_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_zero(res); return; } if (poly->length == 0 || n == 1) { fmpq_poly_one(res); return; } if (!fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_exp_series). Constant term != 0.\n"); } fmpq_poly_fit_length(res, n); _fmpq_poly_exp_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } void fmpq_poly_exp_expinv_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_zero(res1); fmpq_poly_zero(res2); return; } if (poly->length == 0 || n == 1) { fmpq_poly_one(res1); fmpq_poly_one(res2); return; } if (!fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_exp_expinv_series). Constant term != 0.\n"); } fmpq_poly_fit_length(res1, n); fmpq_poly_fit_length(res2, n); _fmpq_poly_exp_expinv_series(res1->coeffs, res1->den, res2->coeffs, res2->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res1, n); _fmpq_poly_set_length(res2, n); _fmpq_poly_normalise(res1); _fmpq_poly_normalise(res2); } flint-3.1.3/src/fmpq_poly/fit_length.c000066400000000000000000000013151461254215100177170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" void fmpq_poly_fit_length(fmpq_poly_t poly, slong len) { if (len > poly->alloc) { /* At least double the number of allocated coefficients */ if (len < 2 * poly->alloc) len = 2 * poly->alloc; fmpq_poly_realloc(poly, len); } } flint-3.1.3/src/fmpq_poly/gcd.c000066400000000000000000000064741461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_gcd(fmpz *G, fmpz_t denG, const fmpz *A, slong lenA, const fmpz *B, slong lenB) { if (lenA == 1) /* lenA == lenB == 1 */ { fmpz_one(G); fmpz_one(denG); } else { fmpz *primA, *primB; fmpz_t s, t; slong lenG; fmpz_init(s); fmpz_init(t); _fmpz_vec_content(s, A, lenA); _fmpz_vec_content(t, B, lenB); /* Set primA, primB to the primitive multiples of A, B */ if (fmpz_is_one(s)) { if (fmpz_is_one(t)) { primA = (fmpz *) A; primB = (fmpz *) B; } else { primA = (fmpz *) A; primB = _fmpz_vec_init(lenB); _fmpz_vec_scalar_divexact_fmpz(primB, B, lenB, t); } } else { if (fmpz_is_one(t)) { primA = _fmpz_vec_init(lenA); primB = (fmpz *) B; _fmpz_vec_scalar_divexact_fmpz(primA, A, lenA, s); } else { primA = _fmpz_vec_init(lenA + lenB); primB = primA + lenA; _fmpz_vec_scalar_divexact_fmpz(primA, A, lenA, s); _fmpz_vec_scalar_divexact_fmpz(primB, B, lenB, t); } } _fmpz_poly_gcd(G, primA, lenA, primB, lenB); for (lenG = lenB - 1; !G[lenG]; lenG--) ; lenG++; fmpz_set(denG, G + (lenG - 1)); if (A != primA) _fmpz_vec_clear(primA, lenA + (B != primB) * lenB); else if (B != primB) _fmpz_vec_clear(primB, lenB); fmpz_clear(s); fmpz_clear(t); } } void fmpq_poly_gcd(fmpq_poly_t G, const fmpq_poly_t A, const fmpq_poly_t B) { if (A->length < B->length) { fmpq_poly_gcd(G, B, A); } else { slong lenA = A->length, lenB = B->length; if (lenA == 0) /* lenA = lenB = 0 */ { fmpq_poly_zero(G); } else if (lenB == 0) /* lenA > lenB = 0 */ { fmpq_poly_make_monic(G, A); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { fmpq_poly_t t; fmpq_poly_init2(t, lenB); _fmpq_poly_gcd(t->coeffs, t->den, A->coeffs, A->length, B->coeffs, B->length); fmpq_poly_swap(t, G); fmpq_poly_clear(t); } else { fmpq_poly_fit_length(G, lenB); _fmpq_poly_gcd(G->coeffs, G->den, A->coeffs, A->length, B->coeffs, B->length); } _fmpq_poly_set_length(G, lenB); _fmpq_poly_normalise(G); } } } flint-3.1.3/src/fmpq_poly/gegenbauer_c.c000066400000000000000000000043651461254215100202120ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_gegenbauer_c(fmpz * coeffs, fmpz_t den, ulong n, const fmpq_t a) { fmpz_t t, p, nu, de; ulong k; slong kk; if (n == 0) { fmpz_one(coeffs); fmpz_one(den); return; } if (n == 1) { fmpz_zero(coeffs); if (fmpz_is_even(fmpq_denref(a))) { fmpz_tdiv_q_2exp(den, fmpq_denref(a), 1); fmpz_set(coeffs + 1, fmpq_numref(a)); } else { fmpz_set(den, fmpq_denref(a)); fmpz_mul_2exp(coeffs + 1, fmpq_numref(a), 1); } return; } fmpz_init(t); fmpz_init(p); fmpz_init(nu); fmpz_init(de); fmpz_set(nu, fmpq_numref(a)); fmpz_set(de, fmpq_denref(a)); fmpz_pow_ui(den, de, n); fmpz_fac_ui(t, n); fmpz_mul(den, den, t); fmpz_fac_ui(p, n/2); fmpz_divexact(p, t, p); if (n%2) fmpz_mul_2exp(p, p, 1); if (n&2) fmpz_neg(p, p); for (k = 0; k < n-n/2; k++) { fmpz_mul(p, p, nu); fmpz_add(nu, nu, de); } fmpz_pow_ui(t, de, n/2); fmpz_mul(p, p, t); fmpz_zero(coeffs); fmpz_set(coeffs + (n%2), p); for (kk = n/2 - 1; kk >= 0; --kk) { fmpz_mul(p, p, nu); fmpz_mul_ui(p, p, 4*(kk+1)); fmpz_divexact(p, p, de); fmpz_divexact2_uiui(p, p, n-2*kk-1, n-2*kk); fmpz_neg(p, p); fmpz_set(coeffs + n - 2*kk, p); fmpz_zero(coeffs + n - 2*kk - 1); fmpz_add(nu, nu, de); } fmpz_clear(t); fmpz_clear(p); fmpz_clear(nu); fmpz_clear(de); } void fmpq_poly_gegenbauer_c(fmpq_poly_t poly, ulong n, const fmpq_t a) { fmpq_poly_fit_length(poly, n + 1); _fmpq_poly_gegenbauer_c(poly->coeffs, poly->den, n, a); _fmpq_poly_set_length(poly, n + 1); _fmpq_poly_normalise(poly); fmpq_poly_canonicalise(poly); } flint-3.1.3/src/fmpq_poly/get_coeff.c000066400000000000000000000017451461254215100175240ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_poly.h" void fmpq_poly_get_coeff_fmpq(fmpq_t x, const fmpq_poly_t poly, slong n) { if (n >= poly->length) /* Coefficient is beyond the end of poly */ { fmpq_zero(x); return; } fmpz_set(fmpq_numref(x), poly->coeffs + n); fmpz_set(fmpq_denref(x), poly->den); fmpq_canonicalise(x); } void fmpq_poly_get_coeff_fmpz(fmpz_t x, const fmpq_poly_t poly, slong n) { if (n >= poly->length) /* Coefficient is beyond the end of poly */ fmpz_zero(x); else fmpz_set(x, poly->coeffs + n); } flint-3.1.3/src/fmpq_poly/get_nmod_poly.c000066400000000000000000000024131461254215100204330ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_get_nmod_poly(nmod_poly_t rop, const fmpq_poly_t op) { slong len = op->length; if (len == 0) { nmod_poly_zero(rop); } else { nmod_poly_fit_length(rop, len); _fmpz_vec_get_nmod_vec(rop->coeffs, op->coeffs, len, rop->mod); _nmod_poly_set_length(rop, len); _nmod_poly_normalise(rop); } } void fmpq_poly_get_nmod_poly_den(nmod_poly_t rop, const fmpq_poly_t op, int den) { _fmpq_poly_get_nmod_poly(rop, op); if (den) { if (!fmpz_is_one(op->den)) { nmod_poly_scalar_mul_nmod(rop, rop, n_invmod(fmpz_get_nmod(op->den, rop->mod), rop->mod.n)); } } } void fmpq_poly_get_nmod_poly(nmod_poly_t rop, const fmpq_poly_t op) { fmpq_poly_get_nmod_poly_den(rop, op, 1); } flint-3.1.3/src/fmpq_poly/get_numerator_denominator.c000066400000000000000000000014461461254215100230530ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void fmpq_poly_get_numerator(fmpz_poly_t res, const fmpq_poly_t poly) { fmpz_poly_fit_length(res, poly->length); _fmpz_vec_set(res->coeffs, poly->coeffs, poly->length); _fmpz_poly_set_length(res, poly->length); } void fmpq_poly_get_denominator(fmpz_t den, const fmpq_poly_t poly) { fmpz_set(den, fmpq_poly_denref(poly)); } flint-3.1.3/src/fmpq_poly/get_slice.c000066400000000000000000000022731461254215100175360ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_get_slice(fmpq_poly_t rop, const fmpq_poly_t op, slong i, slong j) { i = FLINT_MAX(i, 0); j = FLINT_MIN(j, op->length); if (i < j) { slong k; if (rop == op) { for (k = 0; k < i; k++) fmpz_zero(rop->coeffs + k); for (k = j; k < rop->length; k++) fmpz_zero(rop->coeffs + k); fmpq_poly_canonicalise(rop); } else { fmpq_poly_fit_length(rop, j); _fmpq_poly_set_length(rop, j); _fmpz_vec_set(rop->coeffs + i, op->coeffs + i, j - i); fmpz_set(rop->den, op->den); fmpq_poly_canonicalise(rop); } } else { fmpq_poly_zero(rop); } } flint-3.1.3/src/fmpq_poly/get_str.c000066400000000000000000000154131461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "gmpcompat.h" #include "fmpz.h" #include "fmpq_poly.h" char * fmpq_poly_get_str(const fmpq_poly_t poly) { slong i; size_t j; size_t len; /* Upper bound on the length */ size_t denlen; /* Size of the denominator in base 10 */ mpz_t z; mpq_t q; char * str; if (poly->length == 0) { str = (char *) flint_malloc(2 * sizeof(char)); str[0] = '0'; str[1] = '\0'; return str; } mpz_init(z); if (*poly->den == WORD(1)) { denlen = 0; } else { fmpz_get_mpz(z, poly->den); denlen = mpz_sizeinbase(z, 10); } len = (size_t) ceil(log10((double) (poly->length + 1))) + (size_t) 2; for (i = 0; i < poly->length; i++) { fmpz_get_mpz(z, poly->coeffs + i); len += mpz_sizeinbase(z, 10) + (size_t) 1; if (mpz_sgn(z)) len += denlen + (size_t) 2; } mpq_init(q); str = (char *) flint_malloc(len * sizeof(char)); j = flint_sprintf(str, "%wd", poly->length); str[j++] = ' '; for (i = 0; i < poly->length; i++) { str[j++] = ' '; fmpz_get_mpz(mpq_numref(q), poly->coeffs + i); fmpz_get_mpz(mpq_denref(q), poly->den); mpq_canonicalize(q); mpq_get_str(str + j, 10, q); j += strlen(str + j); } mpq_clear(q); mpz_clear(z); return str; } char * _fmpq_poly_get_str_pretty(const fmpz *poly, const fmpz_t den, slong len, const char *var) { slong i; size_t j; size_t size; /* Upper bound on the length */ size_t densize; /* Size of the denominator in base 10 */ size_t varsize; /* Length of the variable name */ mpz_t z; /* op->den (if this is not 1) */ mpq_t q; char *str; if (len == 0) /* Zero polynomial */ { str = flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } if (len == 1) /* Constant polynomials */ { mpq_init(q); fmpz_get_mpz(mpq_numref(q), poly); fmpz_get_mpz(mpq_denref(q), den); mpq_canonicalize(q); str = flint_malloc(mpz_sizeinbase (mpq_numref(q), 10) + mpz_sizeinbase (mpq_denref(q), 10) + 3); str = mpq_get_str(str, 10, q); mpq_clear(q); return str; } if (len == 2) /* Linear polynomials */ { mpq_t a0, a1; size_t size0, size1; mpq_init(a0); mpq_init(a1); fmpz_get_mpz(mpq_numref(a0), poly); fmpz_get_mpz(mpq_denref(a0), den); mpq_canonicalize(a0); fmpz_get_mpz(mpq_numref(a1), poly + 1); fmpz_get_mpz(mpq_denref(a1), den); mpq_canonicalize(a1); size0 = mpz_sizeinbase(mpq_numref(a0), 10) + mpz_sizeinbase(mpq_denref(a0), 10) + 2; size1 = mpz_sizeinbase(mpq_numref(a1), 10) + mpz_sizeinbase(mpq_denref(a1), 10) + 2; size = size0 + 1 + strlen(var) + 1 + size1 + 1; str = flint_malloc(size); if (flint_mpq_cmp_si(a1, 1, 1) == 0) { if (mpq_sgn(a0) == 0) gmp_sprintf(str, "%s", var); else if (mpq_sgn(a0) > 0) gmp_sprintf(str, "%s+%Qd", var, a0); else /* mpq_sgn(a0) < 0 */ gmp_sprintf(str, "%s%Qd", var, a0); } else if (flint_mpq_cmp_si(a1, -1, 1) == 0) { if (mpq_sgn(a0) == 0) gmp_sprintf(str, "-%s", var); else if (mpq_sgn(a0) > 0) gmp_sprintf(str, "-%s+%Qd", var, a0); else /* mpq_sgn(a0) < 0 */ gmp_sprintf(str, "-%s%Qd", var, a0); } else { if (mpq_sgn(a0) == 0) gmp_sprintf(str, "%Qd*%s", a1, var); else if (mpq_sgn(a0) > 0) gmp_sprintf(str, "%Qd*%s+%Qd", a1, var, a0); else /* mpq_sgn(a0) < 0 */ gmp_sprintf(str, "%Qd*%s%Qd", a1, var, a0); } mpq_clear(a0); mpq_clear(a1); return str; } varsize = strlen(var); /* Copy the denominator into an mpz_t */ mpz_init(z); if (*den == WORD(1)) { densize = 0; } else { fmpz_get_mpz(z, den); densize = mpz_sizeinbase(z, 10); } /* Estimate the length */ size = 0; for (i = 0; i < len; i++) { fmpz_get_mpz(z, poly + i); size += mpz_sizeinbase(z, 10) + 1; /* Numerator + sign */ if (mpz_sgn(z) != 0) size += 1 + densize; /* Denominator and / */ size += 3; /* Operator and ws */ size += 1 + varsize + 1; /* *, x and ^ */ size += (size_t) ceil(log10((double) (i + 1))); /* Exponent */ } mpq_init(q); str = flint_malloc(size); j = 0; /* Print the leading term */ fmpz_get_mpz(mpq_numref(q), poly + (len - 1)); fmpz_get_mpz(mpq_denref(q), den); mpq_canonicalize(q); if (flint_mpq_cmp_si(q, 1, 1) != 0) { if (flint_mpq_cmp_si(q, -1, 1) == 0) str[j++] = '-'; else { mpq_get_str(str, 10, q); j += strlen(str + j); str[j++] = '*'; } } j += flint_sprintf(str + j, "%s", var); str[j++] = '^'; j += flint_sprintf(str + j, "%wd", len - 1); i = len - 1; while (i) { i--; if (fmpz_is_zero(poly + i)) continue; fmpz_get_mpz(mpq_numref(q), poly + i); fmpz_get_mpz(mpq_denref(q), den); mpq_canonicalize(q); str[j++] = ' '; if (mpq_sgn(q) < 0) { mpq_abs(q, q); str[j++] = '-'; } else str[j++] = '+'; str[j++] = ' '; mpq_get_str(str + j, 10, q); j += strlen(str + j); if (i > 0) { str[j++] = '*'; j += flint_sprintf(str + j, "%s", var); if (i > 1) { str[j++] = '^'; j += flint_sprintf(str + j, "%wd", i); } } } mpq_clear(q); mpz_clear(z); return str; } char * fmpq_poly_get_str_pretty(const fmpq_poly_t poly, const char * var) { return _fmpq_poly_get_str_pretty(poly->coeffs, poly->den, poly->length, var); } flint-3.1.3/src/fmpq_poly/init.c000066400000000000000000000016151461254215100165420ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_init(fmpq_poly_t poly) { poly->coeffs = NULL; fmpz_init(poly->den); fmpz_one(poly->den); poly->alloc = 0; poly->length = 0; } void fmpq_poly_init2(fmpq_poly_t poly, slong alloc) { /* Allocate space for alloc small coeffs */ poly->coeffs = (alloc ? (fmpz *) flint_calloc(alloc, sizeof(fmpz)) : NULL); fmpz_init(poly->den); fmpz_one(poly->den); poly->alloc = alloc; poly->length = 0; } flint-3.1.3/src/fmpq_poly/inlines.c000066400000000000000000000006561461254215100172440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPQ_POLY_INLINES_C #include "fmpq_poly.h" flint-3.1.3/src/fmpq_poly/integral.c000066400000000000000000000067411461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpq_poly.h" static ulong _fmpz_gcd_big_small(const fmpz_t g, ulong h) { __mpz_struct * z = COEFF_TO_PTR(*g); return n_gcd(mpn_mod_1(z->_mp_d, FLINT_ABS(z->_mp_size), h), h); } static ulong _fmpz_gcd_small(const fmpz_t g, ulong h) { if (!COEFF_IS_MPZ(*g)) return n_gcd(FLINT_ABS(*g), h); else return _fmpz_gcd_big_small(g, h); } void _fmpq_poly_integral(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) { slong k; ulong v, c, d; mp_ptr divisors; fmpz_t t, u; TMP_INIT; if (len <= 2) { if (len == 2) fmpz_set(rpoly + 1, poly); fmpz_zero(rpoly); fmpz_set(rden, den); return; } TMP_START; divisors = TMP_ALLOC(sizeof(ulong) * len); fmpz_init(t); fmpz_one(t); for (k = len - 1; k >= 2; k--) { if (fmpz_is_zero(poly + k - 1)) { fmpz_zero(rpoly + k); } else { c = _fmpz_gcd_small(poly + k - 1, k); if (c == k) { fmpz_divexact_ui(rpoly + k, poly + k - 1, k); divisors[k] = 1; } else { if (c == 1) { fmpz_set(rpoly + k, poly + k - 1); divisors[k] = k; } else { fmpz_divexact_ui(rpoly + k, poly + k - 1, c); divisors[k] = k / c; } c = divisors[k]; d = _fmpz_gcd_small(t, c); if (d != c) fmpz_mul_ui(t, t, c / d); } } } fmpz_mul(rden, den, t); if (!fmpz_is_one(t)) { if (!COEFF_IS_MPZ(*t)) { v = *t; for (k = len - 1; k >= 2; k--) { if (!fmpz_is_zero(rpoly + k) && v != divisors[k]) fmpz_mul_ui(rpoly + k, rpoly + k, divisors[k] == 1 ? v : v / divisors[k]); } } else { fmpz_init(u); for (k = len - 1; k >= 2; k--) { if (!fmpz_is_zero(rpoly + k)) { if (divisors[k] == 1) { fmpz_mul(rpoly + k, rpoly + k, t); } else { fmpz_divexact_ui(u, t, divisors[k]); fmpz_mul(rpoly + k, rpoly + k, u); } } } fmpz_clear(u); } } fmpz_mul(rpoly + 1, poly + 0, t); fmpz_zero(rpoly); fmpz_clear(t); TMP_END; } void fmpq_poly_integral(fmpq_poly_t res, const fmpq_poly_t poly) { slong len = poly->length; if (len == 0) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, len + 1); _fmpq_poly_integral(res->coeffs, res->den, poly->coeffs, poly->den, len + 1); _fmpq_poly_set_length(res, len + 1); } flint-3.1.3/src/fmpq_poly/interpolate_fmpz_vec.c000066400000000000000000000045451461254215100220230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_interpolate_fmpz_vec(fmpz * poly, fmpz_t den, const fmpz * xs, const fmpz * ys, slong n) { fmpz *P, *Q, *w; fmpz_t t; slong i, j; /* Constant */ if (n == 1) { fmpz_set(poly, ys); fmpz_one(den); return; } /* Linear */ if (n == 2) { fmpz_sub(den, xs, xs + 1); fmpz_sub(poly + 1, ys, ys + 1); fmpz_mul(poly, xs, ys + 1); fmpz_submul(poly, xs + 1, ys); return; } fmpz_init(t); P = _fmpz_vec_init(n + 1); Q = _fmpz_vec_init(n); w = _fmpz_vec_init(n); /* P = (x-x[0])*(x-x[1])*...*(x-x[n-1]) */ _fmpz_poly_product_roots_fmpz_vec(P, xs, n); /* Weights */ for (i = 0; i < n; i++) { fmpz_one(w + i); for (j = 0; j < n; j++) { if (i != j) { fmpz_sub(t, xs + i, xs + j); fmpz_mul(w + i, w + i, t); } } } _fmpz_vec_zero(poly, n); _fmpz_vec_lcm(den, w, n); for (i = 0; i < n; i++) { /* Q = P / (x - x[i]) */ _fmpz_poly_div_root(Q, P, n + 1, xs + i); /* result += Q * weight(i) */ fmpz_divexact(t, den, w + i); fmpz_mul(t, t, ys + i); _fmpz_vec_scalar_addmul_fmpz(poly, Q, n, t); } _fmpz_vec_clear(P, n + 1); _fmpz_vec_clear(Q, n); _fmpz_vec_clear(w, n); fmpz_clear(t); } void fmpq_poly_interpolate_fmpz_vec(fmpq_poly_t poly, const fmpz * xs, const fmpz * ys, slong n) { if (n == 0) { fmpq_poly_zero(poly); } else if (n == 1) { fmpq_poly_set_fmpz(poly, ys); } else { fmpq_poly_fit_length(poly, n); _fmpq_poly_interpolate_fmpz_vec(poly->coeffs, poly->den, xs, ys, n); _fmpq_poly_set_length(poly, n); fmpq_poly_canonicalise(poly); } } flint-3.1.3/src/fmpq_poly/inv.c000066400000000000000000000023471461254215100163760ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_inv(fmpq_poly_t poly1, const fmpq_poly_t poly2) { if (poly2->length != 1) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_inv). poly2 is not invertible.\n"); } if (poly1 == poly2) { fmpz_swap(poly1->coeffs, poly1->den); if (fmpz_sgn(poly1->den) < 0) { fmpz_neg(poly1->coeffs, poly1->coeffs); fmpz_neg(poly1->den, poly1->den); } } else { fmpq_poly_fit_length(poly1, 1); if (fmpz_sgn(poly2->coeffs) > 0) { fmpz_set(poly1->coeffs, poly2->den); fmpz_set(poly1->den, poly2->coeffs); } else { fmpz_neg(poly1->coeffs, poly2->den); fmpz_neg(poly1->den, poly2->coeffs); } _fmpq_poly_set_length(poly1, 1); } } flint-3.1.3/src/fmpq_poly/inv_series_newton.c000066400000000000000000000103271461254215100213370ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" /* Newton iteration macros */ #define FLINT_NEWTON_INIT(from, to) \ { \ slong __steps[FLINT_BITS], __i, __from, __to; \ __steps[__i = 0] = __to = (to); \ __from = (from); \ while (__to > __from) \ __steps[++__i] = (__to = (__to + 1) / 2); \ #define FLINT_NEWTON_BASECASE(bc_to) { slong bc_to = __to; #define FLINT_NEWTON_END_BASECASE } #define FLINT_NEWTON_LOOP(step_from, step_to) \ { \ for (__i--; __i >= 0; __i--) \ { \ slong step_from = __steps[__i+1]; \ slong step_to = __steps[__i]; \ #define FLINT_NEWTON_END_LOOP }} #define FLINT_NEWTON_END } #define FMPQ_POLY_INV_NEWTON_CUTOFF 24 /* Requires 2*min(Qlen,n) + n - 1 < 3n coefficients of scratch space in W */ static void _fmpq_poly_inv_series_basecase_rev(fmpz * Qinv, fmpz_t Qinvden, fmpz * W, fmpz_t Wden, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n) { slong Wlen; fmpz *Qrev; Qlen = FLINT_MIN(Qlen, n); Wlen = n + Qlen - 1; Qrev = W + Wlen; _fmpz_poly_reverse(Qrev, Q, Qlen, Qlen); _fmpz_vec_zero(W, Wlen - 1); fmpz_one(W + Wlen - 1); fmpz_one(Wden); _fmpq_poly_div(Qinv, Qinvden, W, Wden, Wlen, Qrev, Qden, Qlen, NULL); _fmpq_poly_canonicalise(Qinv, Qinvden, n); _fmpz_poly_reverse(Qinv, Qinv, n, n); } #define MULLOW(z, x, xn, y, yn, nn) \ if ((xn) >= (yn)) \ _fmpz_poly_mullow(z, x, xn, y, yn, nn); \ else \ _fmpz_poly_mullow(z, y, yn, x, xn, nn); \ void _fmpq_poly_inv_series_newton(fmpz * Qinv, fmpz_t Qinvden, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n) { if (fmpz_is_pm1(Q) && fmpz_is_one(Qden)) { _fmpz_poly_inv_series(Qinv, Q, Qlen, n); fmpz_one(Qinvden); return; } Qlen = FLINT_MIN(Qlen, n); if (Qlen == 1) { fmpz_set(Qinv, Qden); fmpz_set(Qinvden, Q); _fmpq_canonicalise(Qinv, Qinvden); _fmpz_vec_zero(Qinv + 1, n - 1); } else { slong alloc, Qnlen, Wlen, W2len; fmpz * W; fmpz_t Wden; alloc = FLINT_MAX(n, 3 * FMPQ_POLY_INV_NEWTON_CUTOFF); W = _fmpz_vec_init(alloc); fmpz_init(Wden); FLINT_NEWTON_INIT(FMPQ_POLY_INV_NEWTON_CUTOFF, n) FLINT_NEWTON_BASECASE(n) _fmpq_poly_inv_series_basecase_rev(Qinv, Qinvden, W, Wden, Q, Qden, Qlen, n); FLINT_NEWTON_END_BASECASE FLINT_NEWTON_LOOP(m, n) Qnlen = FLINT_MIN(Qlen, n); Wlen = FLINT_MIN(Qnlen + m - 1, n); W2len = Wlen - m; MULLOW(W, Q, Qnlen, Qinv, m, Wlen); fmpz_mul(Wden, Qden, Qinvden); MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m); fmpz_mul(Qinvden, Qinvden, Wden); _fmpz_vec_scalar_mul_fmpz(Qinv, Qinv, m, Wden); _fmpz_vec_neg(Qinv + m, Qinv + m, n - m); _fmpq_poly_canonicalise(Qinv, Qinvden, n); FLINT_NEWTON_END_LOOP FLINT_NEWTON_END _fmpz_vec_clear(W, alloc); fmpz_clear(Wden); } } void fmpq_poly_inv_series_newton(fmpq_poly_t Qinv, const fmpq_poly_t Q, slong n) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_inv_series_newton). Division by zero.\n"); } if (Qinv != Q) { fmpq_poly_fit_length(Qinv, n); _fmpq_poly_inv_series_newton(Qinv->coeffs, Qinv->den, Q->coeffs, Q->den, Qlen, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_inv_series_newton(t->coeffs, t->den, Q->coeffs, Q->den, Qlen, n); fmpq_poly_swap(Qinv, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(Qinv, n); _fmpq_poly_normalise(Qinv); } flint-3.1.3/src/fmpq_poly/invsqrt_series.c000066400000000000000000000045371461254215100206650ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_invsqrt_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong n) { slong m; fmpz * t, * u; fmpz_t tden, uden; if (n == 1) { fmpz_one(rpoly); fmpz_one(rden); return; } m = (n + 1) / 2; _fmpq_poly_invsqrt_series(rpoly, rden, poly, den, len, m); fmpz_init(tden); fmpz_init(uden); t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); _fmpz_vec_zero(rpoly + m, n - m); _fmpq_poly_mul(t, tden, rpoly, rden, m, rpoly, rden, m); if (2*m - 1 < n) fmpz_zero(t + n - 1); _fmpq_poly_mullow(u, uden, t, tden, n, rpoly, rden, n, n); _fmpq_poly_mullow(t, tden, u, uden, n, poly, den, len, n); _fmpz_vec_neg(t + m, t + m, n - m); _fmpz_vec_zero(t, m); fmpz_mul_ui(tden, tden, UWORD(2)); _fmpq_poly_canonicalise(t, tden, n); _fmpq_poly_add(rpoly, rden, rpoly, rden, m, t, tden, n); fmpz_clear(tden); fmpz_clear(uden); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); } void fmpq_poly_invsqrt_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length < 1 || !fmpz_equal(poly->coeffs, poly->den)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_invsqrt_series). Constant term != 1.\n"); } if (n < 1) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_invsqrt_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_invsqrt_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); fmpq_poly_canonicalise(res); /* XXX: necessary? */ } flint-3.1.3/src/fmpq_poly/io.c000066400000000000000000000212311461254215100162020ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gmpcompat.h" #include "fmpq.h" #include "fmpq_poly.h" /* printing *******************************************************************/ /* Recall the return value conventions for fputc (of type int) ``If there are no errors, the same character that has been written is returned. If an error occurs, EOF is returned and the error indicator is set'' where the EOF macro expands to a negative int, and flint_fprintf (of type int) ``On success, the total number of characters written is returned. On failure, a negative number is returned.'' */ /* TODO: Remove me! */ static void ___fmpq_poly_set_array_mpq(fmpz * poly, fmpz_t den, const mpq_t * a, slong n) { slong i; mpz_t d, t; flint_mpz_init_set_ui(d, 1); mpz_init(t); for (i = 0; i < n; i++) { mpz_lcm(d, d, mpq_denref(a[i])); } for (i = 0; i < n; i++) { __mpz_struct *ptr = _fmpz_promote(poly + i); mpz_divexact(t, d, mpq_denref(a[i])); mpz_mul(ptr, mpq_numref(a[i]), t); _fmpz_demote_val(poly + i); } fmpz_set_mpz(den, d); mpz_clear(d); mpz_clear(t); } /* TODO: Remove me! */ static void __fmpq_poly_set_array_mpq(fmpq_poly_t poly, const mpq_t * a, slong n) { if (n == 0) { fmpq_poly_zero(poly); } else { fmpq_poly_fit_length(poly, n); ___fmpq_poly_set_array_mpq(poly->coeffs, poly->den, a, n); _fmpq_poly_set_length(poly, n); _fmpq_poly_normalise(poly); } } int _fmpq_poly_fprint(FILE * file, const fmpz * poly, const fmpz_t den, slong len) { int r; slong i; fmpz_t n, d, g; fmpz_init(n); fmpz_init(d); fmpz_init(g); r = flint_fprintf(file, "%wd", len); if ((len > 0) && (r > 0)) { r = fputc(' ', file); for (i = 0; (i < len) && (r > 0); i++) { r = fputc(' ', file); if (r > 0) { fmpz_gcd(g, poly + i, den); fmpz_divexact(n, poly + i, g); fmpz_divexact(d, den, g); if (*d == WORD(1)) r = fmpz_fprint(file, n); else { r = fmpz_fprint(file, n); if (r > 0) r = fputc('/', file); if (r > 0) r = fmpz_fprint(file, d); } } } } fmpz_clear(n); fmpz_clear(d); fmpz_clear(g); return r; } /* Macro wrapping _fmpq_fprint(file, x, y), ensuring that the printed rational is in lowest terms. Assumes that y > 0. */ #define __fmpq_fprint(x,y) \ do { \ fmpz_gcd(g, x, y); \ if (fmpz_is_one(g)) \ { \ _fmpq_fprint(file, x, y); \ } \ else \ { \ fmpz_divexact(n, x, g); \ fmpz_divexact(d, y, g); \ _fmpq_fprint(file, n, d); \ } \ } while (0) /* checks if x/y == 1, where (x, y) need not be in lowest terms */ #define __fmpq_is_one(x,y) fmpz_equal((x), (y)) /* checks if x/y == +/- 1, where (x, y) need not be in lowest terms */ #define __fmpq_is_pm1(x,y) (fmpz_cmpabs((x),(y)) == 0) int _fmpq_poly_fprint_pretty(FILE * file, const fmpz *poly, const fmpz_t den, slong len, const char * x) { fmpz_t n, d, g; fmpz_init(n); fmpz_init(d); fmpz_init(g); if (len == 0) { fputc('0', file); } else if (len == 1) { _fmpq_fprint(file, poly + 0, den); } else if (len == 2) { if (__fmpq_is_one(poly + 1, den)) { flint_fprintf(file, "%s", x); } else if (__fmpq_is_pm1(poly + 1, den)) { flint_fprintf(file, "-%s", x); } else { __fmpq_fprint(poly + 1, den); flint_fprintf(file, "*%s", x); } if (fmpz_sgn(poly + 0) > 0) { flint_fprintf(file, "+"); __fmpq_fprint(poly + 0, den); } else if (fmpz_sgn(poly + 0) < 0) { __fmpq_fprint(poly + 0, den); } } else /* len >= 3 */ { slong i = len - 1; /* i >= 2 */ { if (__fmpq_is_one(poly + i, den)) flint_fprintf(file, "%s^%wd", x, i); else if (__fmpq_is_pm1(poly + i, den)) flint_fprintf(file, "-%s^%wd", x, i); else { __fmpq_fprint(poly + i, den); flint_fprintf(file, "*%s^%wd", x, i); } --i; } for (; i > 1; --i) { if (poly[i] == 0) continue; if (__fmpq_is_one(poly + i, den)) flint_fprintf(file, "+%s^%wd", x, i); else if (__fmpq_is_pm1(poly + i, den)) flint_fprintf(file, "-%s^%wd", x, i); else { if (fmpz_sgn(poly + i) > 0) { fputc('+', file); } __fmpq_fprint(poly + i, den); flint_fprintf(file, "*%s^%wd", x, i); } } if (poly[1]) { if (__fmpq_is_one(poly + 1, den)) { fputc('+', file); fputs(x, file); } else if (__fmpq_is_pm1(poly + 1, den)) { fputc('-', file); fputs(x, file); } else { if (fmpz_sgn(poly + 1) > 0) { fputc('+', file); } __fmpq_fprint(poly + 1, den); fputc('*', file); fputs(x, file); } } if (*(poly)) { if (fmpz_sgn(poly) > 0) { fputc('+', file); } __fmpq_fprint(poly + 0, den); } } fmpz_clear(n); fmpz_clear(d); fmpz_clear(g); return 1; } #undef __fmpq_fprint int fmpq_poly_fprint(FILE * file, const fmpq_poly_t poly) { return _fmpq_poly_fprint(file, poly->coeffs, poly->den, poly->length); } int fmpq_poly_fprint_pretty(FILE * file, const fmpq_poly_t poly, const char * var) { return _fmpq_poly_fprint_pretty(file, poly->coeffs, poly->den, poly->length, var); } int _fmpq_poly_print(const fmpz * poly, const fmpz_t den, slong len) { return _fmpq_poly_fprint(stdout, poly, den, len); } int fmpq_poly_print(const fmpq_poly_t poly) { return fmpq_poly_fprint(stdout, poly); } int _fmpq_poly_print_pretty(const fmpz *poly, const fmpz_t den, slong len, const char * x) { return _fmpq_poly_fprint_pretty(stdout, poly, den, len, x); } int fmpq_poly_print_pretty(const fmpq_poly_t poly, const char * var) { return fmpq_poly_fprint_pretty(stdout, poly, var); } /* reading ********************************************************************/ int fmpq_poly_fread(FILE * file, fmpq_poly_t poly) { int r; slong i, len; mpz_t t; mpq_t *a; mpz_init(t); r = mpz_inp_str(t, file, 10); if (r == 0) { mpz_clear(t); return 0; } if (!mpz_fits_slong_p(t)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_fread). Length does not fit into a slong.\n"); } len = flint_mpz_get_si(t); mpz_clear(t); a = flint_malloc(len * sizeof(mpq_t)); for (i = 0; i < len; i++) mpq_init(a[i]); for (i = 0; (i < len) && r; i++) r = mpq_inp_str(a[i], file, 10); if (r > 0) __fmpq_poly_set_array_mpq(poly, (const mpq_t *) a, len); for (i = 0; i < len; i++) mpq_clear(a[i]); flint_free(a); return r; } int fmpq_poly_read(fmpq_poly_t poly) { return fmpq_poly_fread(stdin, poly); } /* debugging ******************************************************************/ int fmpq_poly_debug(const fmpq_poly_t poly) { slong i; flint_printf("{alloc: %wd, length: %wd, coeffs:", poly->alloc, poly->length); for (i = 0; i < poly->alloc; i++) { flint_printf(" "); fmpz_print(poly->coeffs + i); } flint_printf(", den: "); fmpz_print(poly->den); flint_printf("}"); return 1; } flint-3.1.3/src/fmpq_poly/is_canonical.c000066400000000000000000000020471461254215100202210ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" int _fmpq_poly_is_canonical(const fmpz * poly, const fmpz_t den, slong len) { if (len) { int ans; fmpz_t c; if (fmpz_is_zero(poly + len - 1)) return 0; if (fmpz_sgn(den) < 0) return 0; fmpz_init(c); _fmpz_poly_content(c, poly, len); fmpz_gcd(c, c, den); ans = (*c == WORD(1)); fmpz_clear(c); return ans; } else { return (*den == WORD(1)); } } int fmpq_poly_is_canonical(const fmpq_poly_t poly) { return _fmpq_poly_is_canonical(poly->coeffs, poly->den, poly->length); } flint-3.1.3/src/fmpq_poly/is_monic.c000066400000000000000000000012541461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" int _fmpq_poly_is_monic(const fmpz * poly, const fmpz_t den, slong len) { return (len > 0) && fmpz_equal(poly + (len - 1), den); } int fmpq_poly_is_monic(const fmpq_poly_t poly) { return _fmpq_poly_is_monic(poly->coeffs, poly->den, poly->length); } flint-3.1.3/src/fmpq_poly/is_squarefree.c000066400000000000000000000010501461254215100204250ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpq_poly.h" int fmpq_poly_is_squarefree(const fmpq_poly_t poly) { return _fmpz_poly_is_squarefree(poly->coeffs, poly->length); } flint-3.1.3/src/fmpq_poly/laguerre_l.c000066400000000000000000000024271461254215100177220ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void _fmpq_poly_laguerre_l(fmpz * coeffs, fmpz_t den, ulong n) { fmpz_t c; ulong k; if (n == 0) { fmpz_one(coeffs); fmpz_one(den); return; } if (n == 1) { fmpz_one(coeffs); fmpz_one(coeffs + 1); fmpz_neg(coeffs + 1, coeffs + 1); fmpz_one(den); return; } fmpz_init(c); fmpz_one(c); if (n%2 == 1) fmpz_neg(c, c); fmpz_set(coeffs + n, c); for (k = 0; k < n; k++) { fmpz_mul2_uiui(c, c, n-k, n-k); fmpz_divexact_ui(c, c, k+1); fmpz_neg(c, c); fmpz_set(coeffs + n - k - 1, c); } fmpz_set(den, coeffs); fmpz_clear(c); } void fmpq_poly_laguerre_l(fmpq_poly_t poly, ulong n) { fmpq_poly_fit_length(poly, n + 1); _fmpq_poly_laguerre_l(poly->coeffs, poly->den, n); _fmpq_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpq_poly/lcm.c000066400000000000000000000063631461254215100163570ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_lcm(fmpz *L, fmpz_t denL, const fmpz *A, slong lenA, const fmpz *B, slong lenB) { if (lenA == 1) /* lenA == lenB == 1 */ { fmpz_one(L); fmpz_one(denL); } else { fmpz *copyA, *copyB; fmpz_t s, t; slong lenL; fmpz_init(s); fmpz_init(t); _fmpz_vec_content(s, A, lenA); _fmpz_vec_content(t, B, lenB); if (fmpz_is_one(s)) { if (fmpz_is_one(t)) { copyA = (fmpz *) A; copyB = (fmpz *) B; } else { copyA = (fmpz *) A; copyB = _fmpz_vec_init(lenB); _fmpz_vec_scalar_divexact_fmpz(copyB, B, lenB, t); } } else { if (fmpz_is_one(s)) { copyA = _fmpz_vec_init(lenA); copyB = (fmpz *) B; _fmpz_vec_scalar_divexact_fmpz(copyA, A, lenA, s); } else { copyA = _fmpz_vec_init(lenA + lenB); copyB = copyA + lenA; _fmpz_vec_scalar_divexact_fmpz(copyA, A, lenA, s); _fmpz_vec_scalar_divexact_fmpz(copyB, B, lenB, t); } } _fmpz_poly_lcm(L, copyA, lenA, copyB, lenB); for (lenL = lenA + lenB - 2; !L[lenL]; lenL--) ; lenL++; fmpz_set(denL, L + (lenL - 1)); if (A != copyA) _fmpz_vec_clear(copyA, lenA + (B != copyB) * lenB); else if (B != copyB) _fmpz_vec_clear(copyB, lenB); fmpz_clear(s); fmpz_clear(t); } } void fmpq_poly_lcm(fmpq_poly_t L, const fmpq_poly_t A, const fmpq_poly_t B) { slong lenA = A->length, lenB = B->length, lenL = lenA + lenB - 1; if (lenA == 0 || lenB == 0) { fmpq_poly_zero(L); return; } if (L == A || L == B) { fmpq_poly_t t; fmpq_poly_init2(t, lenL); if (lenA >= lenB) _fmpq_poly_lcm(t->coeffs, t->den, A->coeffs, A->length, B->coeffs, B->length); else _fmpq_poly_lcm(t->coeffs, t->den, B->coeffs, B->length, A->coeffs, A->length); fmpq_poly_swap(t, L); fmpq_poly_clear(t); } else { fmpq_poly_fit_length(L, lenL); if (lenA >= lenB) _fmpq_poly_lcm(L->coeffs, L->den, A->coeffs, A->length, B->coeffs, B->length); else _fmpq_poly_lcm(L->coeffs, L->den, B->coeffs, B->length, A->coeffs, A->length); } _fmpq_poly_set_length(L, lenL); _fmpq_poly_normalise(L); } flint-3.1.3/src/fmpq_poly/legendre_p.c000066400000000000000000000032641461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" static inline void __legendre_denom(fmpz_t den, ulong n) { ulong d, k; d = k = n >> 1; while (k) { k >>= 1; d += k; } fmpz_one(den); fmpz_mul_2exp(den, den, d); } void _fmpq_poly_legendre_p(fmpz * coeffs, fmpz_t den, ulong n) { fmpz * r; int odd; slong k; ulong L; if (n == 0) { fmpz_one(coeffs); fmpz_one(den); return; } if (n == 1) { fmpz_zero(coeffs); fmpz_one(coeffs + 1); fmpz_one(den); return; } L = n / 2; odd = n % 2; r = coeffs + odd; __legendre_denom(den, n); fmpz_bin_uiui(r, n, L); fmpz_mul(r, r, den); if (odd) fmpz_mul_ui(r, r, L + 1); fmpz_fdiv_q_2exp(r, r, 2*L); if (L % 2) fmpz_neg(r, r); for (k = 1; k <= L; k++) { fmpz_mul2_uiui(r + 2, r, L + 1 - k, 2*k + 2*L - 1 + 2*odd); fmpz_divexact2_uiui(r + 2, r + 2, k, 2*k - 1 + 2*odd); fmpz_neg(r + 2, r + 2); r += 2; } for (k = 1 - odd; k < n; k += 2) fmpz_zero(coeffs + k); } void fmpq_poly_legendre_p(fmpq_poly_t poly, ulong n) { fmpq_poly_fit_length(poly, n + 1); _fmpq_poly_legendre_p(poly->coeffs, poly->den, n); _fmpq_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpq_poly/log_series.c000066400000000000000000000034051461254215100177310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_log_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n) { fmpz * f_diff; fmpz * f_inv; fmpz_t f_diff_den; fmpz_t f_inv_den; flen = FLINT_MIN(flen, n); f_diff = _fmpz_vec_init(flen - 1); f_inv = _fmpz_vec_init(n); fmpz_init(f_diff_den); fmpz_init(f_inv_den); _fmpq_poly_derivative(f_diff, f_diff_den, f, fden, flen); _fmpq_poly_inv_series(f_inv, f_inv_den, f, fden, flen, n); _fmpq_poly_mullow(g, gden, f_inv, f_inv_den, n - 1, f_diff, f_diff_den, flen - 1, n - 1); _fmpq_poly_canonicalise(g, gden, n - 1); _fmpq_poly_integral(g, gden, g, gden, n); _fmpz_vec_clear(f_diff, flen - 1); _fmpz_vec_clear(f_inv, n); fmpz_clear(f_diff_den); fmpz_clear(f_inv_den); } void fmpq_poly_log_series(fmpq_poly_t res, const fmpq_poly_t f, slong n) { slong flen = f->length; if (flen < 1 || !fmpz_equal(f->coeffs, f->den)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_log_series). Constant term != 1.\n"); } if (flen == 1 || n < 2) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, n); _fmpq_poly_log_series(res->coeffs, res->den, f->coeffs, f->den, f->length, n); _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/make_monic.c000066400000000000000000000017451461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_make_monic(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) { _fmpz_poly_primitive_part(rpoly, poly, len); fmpz_set(rden, rpoly + (len - 1)); } void fmpq_poly_make_monic(fmpq_poly_t res, const fmpq_poly_t poly) { slong len = poly->length; if (len == 0) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, len); _fmpq_poly_set_length(res, len); _fmpq_poly_make_monic(res->coeffs, res->den, poly->coeffs, poly->den, len); } flint-3.1.3/src/fmpq_poly/mul.c000066400000000000000000000053051461254215100163740ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_mul(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) { fmpz_t gcd1; /* GCD( poly1, den2 ) */ fmpz_t gcd2; /* GCD( poly2, den1 ) */ if (poly1 == poly2 && len1 == len2) { _fmpz_poly_sqr(rpoly, poly1, len1); fmpz_mul(rden, den1, den2); return; } fmpz_init(gcd1); fmpz_init(gcd2); fmpz_one(gcd1); fmpz_one(gcd2); if (!fmpz_is_one(den2)) _fmpz_vec_content_chained(gcd1, poly1, len1, den2); if (!fmpz_is_one(den1)) _fmpz_vec_content_chained(gcd2, poly2, len2, den1); /* TODO: If gcd1 and gcd2 are very large compared to the degrees of poly1 and poly2, we might want to create copies of the polynomials and divide out the common factors *before* the multiplication. */ _fmpz_poly_mul(rpoly, poly1, len1, poly2, len2); fmpz_mul(rden, den1, den2); if (!fmpz_is_one(gcd1) || !fmpz_is_one(gcd2)) { fmpz_t g; fmpz_init(g); fmpz_mul(g, gcd1, gcd2); _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, len1 + len2 - 1, g); fmpz_divexact(rden, rden, g); fmpz_clear(g); } fmpz_clear(gcd1); fmpz_clear(gcd2); } void fmpq_poly_mul(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { slong len; if (poly1->length == 0 || poly2->length == 0) { fmpq_poly_zero(res); return; } len = poly1->length + poly2->length - 1; if (res == poly2 || res == poly1) { fmpq_poly_t t; fmpq_poly_init2(t, len); fmpq_poly_mul(t, poly1, poly2); fmpq_poly_swap(res, t); fmpq_poly_clear(t); return; } fmpq_poly_fit_length(res, len); if (poly1->length >= poly2->length) _fmpq_poly_mul(res->coeffs, res->den, poly1->coeffs, poly1->den, poly1->length, poly2->coeffs, poly2->den, poly2->length); else _fmpq_poly_mul(res->coeffs, res->den, poly2->coeffs, poly2->den, poly2->length, poly1->coeffs, poly1->den, poly1->length); _fmpq_poly_set_length(res, len); } flint-3.1.3/src/fmpq_poly/mullow.c000066400000000000000000000034351461254215100171200ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_mullow(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) { _fmpz_poly_mullow(rpoly, poly1, len1, poly2, len2, n); fmpz_mul(rden, den1, den2); } void fmpq_poly_mullow(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) { const slong len1 = poly1->length; const slong len2 = poly2->length; slong lenr; if (len1 == 0 || len2 == 0 || n == 0) { fmpq_poly_zero(res); return; } if (res == poly1 || res == poly2) { fmpq_poly_t t; fmpq_poly_init2(t, n); fmpq_poly_mullow(t, poly1, poly2, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); return; } lenr = len1 + len2 - 1; if (n > lenr) n = lenr; fmpq_poly_fit_length(res, n); if (len1 >= len2) _fmpq_poly_mullow(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, n); else _fmpq_poly_mullow(res->coeffs, res->den, poly2->coeffs, poly2->den, len2, poly1->coeffs, poly1->den, len1, n); _fmpq_poly_set_length(res, n); fmpq_poly_canonicalise(res); } flint-3.1.3/src/fmpq_poly/neg.c000066400000000000000000000015271461254215100163520ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_neg(fmpq_poly_t poly1, const fmpq_poly_t poly2) { if (poly1 == poly2) { _fmpz_vec_neg(poly1->coeffs, poly2->coeffs, poly2->length); } else { fmpq_poly_fit_length(poly1, poly2->length); _fmpz_vec_neg(poly1->coeffs, poly2->coeffs, poly2->length); _fmpq_poly_set_length(poly1, poly2->length); fmpz_set(poly1->den, poly2->den); } } flint-3.1.3/src/fmpq_poly/normalise.c000066400000000000000000000011271461254215100175660ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" void _fmpq_poly_normalise(fmpq_poly_t poly) { slong i; for (i = poly->length - 1; (i >= 0) && !poly->coeffs[i]; i--) ; poly->length = i + 1; } flint-3.1.3/src/fmpq_poly/nth_derivative.c000066400000000000000000000023601461254215100206100ustar00rootroot00000000000000/* Copyright (C) 2021 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_nth_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, ulong n, slong len) { _fmpz_poly_nth_derivative(rpoly, poly, n, len); fmpz_set(rden, den); _fmpq_poly_canonicalise(rpoly, rden, len - n); } void fmpq_poly_nth_derivative(fmpq_poly_t res, const fmpq_poly_t poly, ulong n) { slong len = poly->length; if (len <= n) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, len - n); if (n == 0) { fmpq_poly_set(res, poly); } else if (n == 1) { _fmpq_poly_derivative(res->coeffs, res->den, poly->coeffs, poly->den, len); } else { _fmpq_poly_nth_derivative(res->coeffs, res->den, poly->coeffs, poly->den, n, len); } _fmpq_poly_set_length(res, len - n); } flint-3.1.3/src/fmpq_poly/one.c000066400000000000000000000011421461254215100163530ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void fmpq_poly_one(fmpq_poly_t poly) { fmpq_poly_fit_length(poly, 1); _fmpq_poly_set_length(poly, 1); fmpz_one(poly->coeffs); fmpz_one(poly->den); } flint-3.1.3/src/fmpq_poly/pow.c000066400000000000000000000026071461254215100164060ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_pow(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong e) { _fmpz_poly_pow(rpoly, poly, len, e); fmpz_pow_ui(rden, den, e); } void fmpq_poly_pow(fmpq_poly_t res, const fmpq_poly_t poly, ulong e) { slong len = poly->length, rlen; if (e == 0) { fmpq_poly_set_ui(res, 1); return; } if (len == 0) { fmpq_poly_zero(res); return; } rlen = (slong) e * (len - WORD(1)) + WORD(1); if (res != poly) { fmpq_poly_fit_length(res, rlen); _fmpq_poly_pow(res->coeffs, res->den, poly->coeffs, poly->den, len, e); _fmpq_poly_set_length(res, rlen); } else { fmpq_poly_t t; fmpq_poly_init2(t, rlen); _fmpq_poly_pow(t->coeffs, t->den, poly->coeffs, poly->den, len, e); _fmpq_poly_set_length(t, rlen); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } } flint-3.1.3/src/fmpq_poly/pow_trunc.c000066400000000000000000000113321461254215100176140ustar00rootroot00000000000000/* Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" /* counts zero bits in the binary representation of e */ static int n_zerobits(mp_limb_t e) { int zeros = 0; while (e > 1) { zeros += !(e & 1); e >>= 1; } return zeros; } static slong poly_pow_length(slong poly_len, ulong exp, slong trunc) { mp_limb_t hi, lo; umul_ppmm(hi, lo, poly_len - 1, exp); add_ssaaaa(hi, lo, hi, lo, 0, 1); if (hi != 0 || lo > (mp_limb_t) WORD_MAX) return trunc; return FLINT_MIN((slong) lo, trunc); } #define MUL(z, zden, zlen, x, xden, xlen, y, yden, ylen, trunc, prec) \ do { \ slong slen = FLINT_MIN(xlen + ylen - 1, trunc); \ if (xlen >= ylen) \ _fmpz_poly_mullow(z, x, xlen, y, ylen, slen); \ else \ _fmpz_poly_mullow(z, y, ylen, x, xlen, slen); \ zlen = slen; \ fmpz_mul(zden, xden, yden); \ _fmpq_poly_canonicalise(z, zden, zlen); \ } while (0) void _fmpq_poly_pow_trunc(fmpz * res, fmpz_t resden, const fmpz * f, const fmpz_t fden, slong flen, ulong exp, slong len) { fmpz * v, * R, * S, * T, * Rden, * Sden; fmpz_t vden; slong rlen; ulong bit; if (exp <= 1) { if (exp == 0) { fmpz_one(res); fmpz_one(resden); } else if (exp == 1) { _fmpz_vec_set(res, f, len); fmpz_set(resden, fden); _fmpq_poly_canonicalise(res, resden, len); } return; } /* (f * x^r)^m = x^(rm) * f^m */ while (flen > 1 && fmpz_is_zero(f)) { if (((ulong) len) > exp) { _fmpz_vec_zero(res, exp); len -= exp; res += exp; } else { _fmpz_vec_zero(res, len); fmpz_one(resden); return; } f++; flen--; } if (exp == 2) { _fmpq_poly_mullow(res, resden, f, fden, flen, f, fden, flen, len); _fmpq_poly_canonicalise(res, resden, len); return; } if (flen == 1) { fmpz_set(res, f); fmpz_set(resden, fden); _fmpq_canonicalise(res, resden); fmpz_pow_ui(res, res, exp); fmpz_pow_ui(resden, resden, exp); return; } v = _fmpz_vec_init(len); fmpz_init(vden); bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2); if (n_zerobits(exp) % 2) { R = res; Rden = resden; S = v; Sden = vden; } else { R = v; Rden = vden; S = res; Sden = resden; } MUL(R, Rden, rlen, f, fden, flen, f, fden, flen, len, prec); if (bit & exp) { MUL(S, Sden, rlen, R, Rden, rlen, f, fden, flen, len, prec); T = R; R = S; S = T; T = Rden; Rden = Sden; Sden = T; } while (bit >>= 1) { if (bit & exp) { MUL(S, Sden, rlen, R, Rden, rlen, R, Rden, rlen, len, prec); MUL(R, Rden, rlen, S, Sden, rlen, f, fden, flen, len, prec); } else { MUL(S, Sden, rlen, R, Rden, rlen, R, Rden, rlen, len, prec); T = R; R = S; S = T; T = Rden; Rden = Sden; Sden = T; } } _fmpz_vec_clear(v, len); fmpz_clear(vden); } void fmpq_poly_pow_trunc(fmpq_poly_t res, const fmpq_poly_t poly, ulong exp, slong len) { slong flen, rlen; flen = poly->length; if (exp == 0 && len != 0) { fmpq_poly_one(res); } else if (flen == 0 || len == 0) { fmpq_poly_zero(res); } else { rlen = poly_pow_length(flen, exp, len); if (res != poly) { fmpq_poly_fit_length(res, rlen); _fmpq_poly_pow_trunc(res->coeffs, res->den, poly->coeffs, poly->den, flen, exp, rlen); _fmpq_poly_set_length(res, rlen); _fmpq_poly_normalise(res); } else { fmpq_poly_t t; fmpq_poly_init2(t, rlen); _fmpq_poly_pow_trunc(t->coeffs, t->den, poly->coeffs, poly->den, flen, exp, rlen); _fmpq_poly_set_length(t, rlen); _fmpq_poly_normalise(t); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } } } flint-3.1.3/src/fmpq_poly/power_sums.c000066400000000000000000000067351461254215100200120ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_power_sums(fmpz * res, fmpz_t rden, const fmpz * poly, slong len, slong n) { if (fmpz_is_one(poly + len - 1)) { /* monic polynomial */ _fmpz_poly_power_sums_naive(res, poly, len, n); fmpz_one(rden); } else if (len == 2) { /* degree 1 */ fmpz_t a; slong i; fmpz_init(a); fmpz_set(a, poly + 1); fmpz_set(rden, poly); if (fmpz_sgn(a) < 0) fmpz_neg(a, a); else fmpz_neg(rden, rden); fmpz_one(res); for (i = 1; i < n; i++) fmpz_mul(res + i, res + i - 1, rden); fmpz_one(rden); for (i = n - 2; i >= 0; i--) { fmpz_mul(rden, rden, a); fmpz_mul(res + i, res + i, rden); } fmpz_set(res, rden); fmpz_clear(a); } else { /* general case */ slong i, k; fmpz_one(rden); for (k = 1; k < FLINT_MIN(n, len); k++) { fmpz_mul_si(res + k, poly + len - 1 - k, -k); fmpz_mul(res + k, res + k, rden); _fmpz_vec_scalar_mul_fmpz(res + 1, res + 1, k - 2, poly + len - 1); _fmpz_vec_dot_general(res + k, res + k, 1, poly + len - 1 - k + 1, res + 1, 0, k - 1); fmpz_mul(rden, rden, poly + len - 1); } for (k = len; k < n; k++) { _fmpz_vec_scalar_mul_fmpz(res + k - len + 1, res + k - len + 1, len - 2, poly + len - 1); _fmpz_vec_dot_general(res + k, NULL, 1, poly, res + k - len + 1, 0, len - 1); } _fmpz_vec_scalar_mul_fmpz(res + n - len + 1, res + n - len + 1, len - 2, poly + len - 1); fmpz_one(rden); for (i = n - len; i > 0; i--) { fmpz_mul(rden, rden, poly + len - 1); fmpz_mul(res + i, res + i, rden); } fmpz_pow_ui(rden, poly + len - 1, n - 1); fmpz_mul_ui(res, rden, len - 1); } } void fmpq_poly_power_sums(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length == 0) { flint_throw(FLINT_ERROR, "(fmpq_poly_power_sums_naive): Zero polynomial.\n"); } else if (n <= 0 || poly->length == 1) { fmpq_poly_zero(res); return; } else if (n == 1) { fmpq_poly_fit_length(res, 1); fmpz_set_ui(res->coeffs, fmpq_poly_degree(poly)); fmpz_one(res->den); _fmpq_poly_set_length(res, 1); return; } else if (poly == res) { fmpq_poly_t t; fmpq_poly_init(t); fmpq_poly_fit_length(t, n); _fmpq_poly_power_sums(t->coeffs, t->den, poly->coeffs, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } else { fmpq_poly_fit_length(res, n); _fmpq_poly_power_sums(res->coeffs, res->den, poly->coeffs, poly->length, n); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); fmpq_poly_canonicalise(res); } flint-3.1.3/src/fmpq_poly/power_sums_to_poly.c000066400000000000000000000063571461254215100215570ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, const fmpz_t den, slong len) { slong i, k; fmpz_t f; slong d; ulong a; fmpz_init(f); fmpz_divexact(f, poly, den); d = fmpz_get_ui(f); fmpz_one(f); for (k = 1; k <= d; k++) { if (k < len) { fmpz_mul(res + d - k, poly + k, f); _fmpz_vec_dot_general(res + d - k, res + d - k, 0, res + d - k + 1, poly + 1, 0, k - 1); } else { _fmpz_vec_dot_general(res + d - k, NULL, 0, res + d - k + 1, poly + 1, 0, len - 1); } a = n_gcd(FLINT_ABS(fmpz_fdiv_ui(res + d - k, k)), k); fmpz_divexact_ui(res + d - k, res + d - k, a); if (a != k) { a = k / a; for (i = d - k + 1; i < d; i++) fmpz_mul_ui(res + i, res + i, a); fmpz_mul_ui(f, f, a); } fmpz_neg(res + d - k, res + d - k); fmpz_mul(f, f, den); for (i = d - k + 1; i < d; i++) fmpz_mul(res + i, res + i, den); } fmpz_swap(res + d, f); fmpz_clear(f); } void fmpq_poly_power_sums_to_fmpz_poly(fmpz_poly_t res, const fmpq_poly_t Q) { if (Q->length == 0) fmpz_poly_one(res); else { fmpz_t fd; slong d; fmpz_init(fd); fmpz_divexact(fd, Q->coeffs, Q->den); d = fmpz_get_ui(fd); fmpz_clear(fd); fmpz_poly_fit_length(res, d + 1); _fmpq_poly_power_sums_to_poly(res->coeffs, Q->coeffs, Q->den, Q->length); _fmpz_poly_set_length(res, d + 1); _fmpz_poly_normalise(res); _fmpz_poly_primitive_part(res->coeffs, res->coeffs, d + 1); } } void fmpq_poly_power_sums_to_poly(fmpq_poly_t res, const fmpq_poly_t Q) { if (Q->length == 0) fmpq_poly_one(res); else { fmpz_t fd; slong d; fmpz_init(fd); fmpz_divexact(fd, Q->coeffs, Q->den); d = fmpz_get_ui(fd); fmpz_clear(fd); if (res == Q) { fmpq_poly_t t; fmpq_poly_init(t); fmpq_poly_fit_length(res, d + 1); _fmpq_poly_power_sums_to_poly(t->coeffs, Q->coeffs, Q->den, Q->length); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } else { fmpq_poly_fit_length(res, d + 1); _fmpq_poly_power_sums_to_poly(res->coeffs, Q->coeffs, Q->den, Q->length); } _fmpq_poly_set_length(res, d + 1); _fmpq_poly_normalise(res); _fmpq_poly_make_monic(res->coeffs, res->den, res->coeffs, res->den, res->length); } } flint-3.1.3/src/fmpq_poly/powers_clear.c000066400000000000000000000012721461254215100202630ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" void _fmpq_poly_powers_clear(fmpq_poly_struct * powers, slong len) { slong i; for (i = 0; i < 2*len - 1; i++) fmpq_poly_clear(powers + i); flint_free(powers); } void fmpq_poly_powers_clear(fmpq_poly_powers_precomp_t pinv) { _fmpq_poly_powers_clear(pinv->powers, pinv->len); } flint-3.1.3/src/fmpq_poly/powers_precompute.c000066400000000000000000000037121461254215100213610ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" fmpq_poly_struct * _fmpq_poly_powers_precompute(const fmpz * B, const fmpz_t denB, slong len) { slong i; fmpq_poly_struct * powers = flint_malloc(sizeof(fmpq_poly_struct)*(2*len - 1)); fmpq_poly_t pow, p; fmpq_poly_init2(pow, len); fmpq_poly_one(pow); fmpq_poly_init2(p, len - 1); for (i = 0; i < 2*len - 1; i++) { fmpq_poly_init(powers + i); if (pow->length == len) /* reduce pow mod B */ { fmpz_mul(fmpq_poly_denref(p), B + len - 1, fmpq_poly_denref(pow)); _fmpz_vec_scalar_mul_fmpz(fmpq_poly_numref(p), B, len - 1, fmpq_poly_numref(pow) + len - 1); _fmpq_poly_set_length(p, len - 1); _fmpq_poly_normalise(p); fmpq_poly_canonicalise(p); fmpq_poly_sub(pow, pow, p); _fmpq_poly_set_length(pow, len - 1); _fmpq_poly_normalise(pow); fmpq_poly_canonicalise(pow); } fmpq_poly_set(powers + i, pow); fmpq_poly_shift_left(pow, pow, 1); } fmpq_poly_clear(pow); fmpq_poly_clear(p); return powers; } void fmpq_poly_powers_precompute(fmpq_poly_powers_precomp_t pinv, fmpq_poly_t poly) { if (poly->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_powers_precompute). Division by zero.\n"); } pinv->powers = _fmpq_poly_powers_precompute(fmpq_poly_numref(poly), fmpq_poly_denref(poly), poly->length); pinv->len = poly->length; } flint-3.1.3/src/fmpq_poly/primitive_part.c000066400000000000000000000020401461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_primitive_part(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) { _fmpz_poly_primitive_part(rpoly, poly, len); fmpz_one(rden); } void fmpq_poly_primitive_part(fmpq_poly_t res, const fmpq_poly_t poly) { const slong len = poly->length; if (len == 0) { fmpq_poly_zero(res); } else { fmpq_poly_fit_length(res, len); _fmpq_poly_set_length(res, len); _fmpq_poly_primitive_part(res->coeffs, res->den, poly->coeffs, poly->den, len); } } flint-3.1.3/src/fmpq_poly/randtest.c000066400000000000000000000051641461254215100174260ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_randtest(fmpq_poly_t poly, flint_rand_t state, slong len, flint_bitcnt_t bits) { ulong m; m = n_randlimb(state); fmpq_poly_fit_length(poly, len); _fmpq_poly_set_length(poly, len); if (m & UWORD(1)) { _fmpz_vec_randtest(poly->coeffs, state, len, bits); } else { fmpz_t x; fmpz_init(x); fmpz_randtest(x, state, bits / 2); _fmpz_vec_randtest(poly->coeffs, state, len, (bits + 1) / 2); _fmpz_vec_scalar_mul_fmpz(poly->coeffs, poly->coeffs, len, x); fmpz_clear(x); } if (m & UWORD(2)) { fmpz_randtest_not_zero(poly->den, state, FLINT_MAX(bits, 1)); fmpz_abs(poly->den, poly->den); fmpq_poly_canonicalise(poly); } else { fmpz_one(poly->den); _fmpq_poly_normalise(poly); } } void fmpq_poly_randtest_unsigned(fmpq_poly_t poly, flint_rand_t state, slong len, flint_bitcnt_t bits) { ulong m; m = n_randlimb(state); fmpq_poly_fit_length(poly, len); _fmpq_poly_set_length(poly, len); if (m & UWORD(1)) { _fmpz_vec_randtest_unsigned(poly->coeffs, state, len, bits); } else { fmpz_t x; fmpz_init(x); fmpz_randtest_unsigned(x, state, bits / 2); _fmpz_vec_randtest_unsigned(poly->coeffs, state, len, (bits + 1) / 2); _fmpz_vec_scalar_mul_fmpz(poly->coeffs, poly->coeffs, len, x); fmpz_clear(x); } if (m & UWORD(2)) { fmpz_randtest_not_zero(poly->den, state, FLINT_MAX(bits, 1)); fmpz_abs(poly->den, poly->den); fmpq_poly_canonicalise(poly); } else { fmpz_one(poly->den); _fmpq_poly_normalise(poly); } } void fmpq_poly_randtest_not_zero(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) { if ((bits == 0) | (len == 0)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_randtest_not_zeo). bits == 0.\n"); } fmpq_poly_randtest(f, state, len, bits); if (f->length == 0) fmpq_poly_set_ui(f, 1); } flint-3.1.3/src/fmpq_poly/realloc.c000066400000000000000000000025111461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_realloc(fmpq_poly_t poly, slong alloc) { if (alloc == 0) /* Clear up, reinitialise */ { fmpq_poly_clear(poly); fmpq_poly_init(poly); return; } if (poly->alloc) /* Realloc */ { if (poly->length > alloc) /* Reduce the size */ { slong i; for (i = alloc; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); poly->length = alloc; _fmpq_poly_normalise(poly); } poly->coeffs = (fmpz *) flint_realloc(poly->coeffs, alloc * sizeof(fmpz)); if (poly->alloc < alloc) { flint_mpn_zero((mp_ptr) (poly->coeffs + poly->alloc), alloc - poly->alloc); } } else /* Nothing allocated, do it now */ { poly->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); } poly->alloc = alloc; } flint-3.1.3/src/fmpq_poly/rem.c000066400000000000000000000056631461254215100163710ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_rem(fmpz * R, fmpz_t r, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv) { slong lenR; ulong d; const fmpz * lead = B + (lenB - 1); if (lenB == 1) { fmpz_one(r); return; } /* From pseudo division over Z we have lead^d * A = Q * B + R and thus {A, a} = {b * Q, a * lead^d} * {B, b} + {R, a * lead^d}. */ _fmpz_poly_pseudo_rem(R, &d, A, lenA, B, lenB, inv); /* Determine the actual length of R */ for (lenR = lenB - 2; lenR >= 0 && !R[lenR]; lenR--) ; lenR++; /* 1. lead^d == +-1. {R, r} = {R, a} up to sign */ if (d == UWORD(0) || *lead == WORD(1) || *lead == WORD(-1)) { fmpz_one(r); if (lenR > 0) _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, a); if (*lead == WORD(-1) && d % UWORD(2)) _fmpz_vec_neg(R, R, lenR); } /* 2. lead^d != +-1. {R, r} = {R, a lead^d} */ else { /* TODO: Improve this. Clearly we do not need to compute den = a lead^d in many cases, but can determine the GCD from lead alone already. */ fmpz_t den; fmpz_init(den); fmpz_pow_ui(den, lead, d); fmpz_mul(den, a, den); fmpz_one(r); if (lenR > 0) _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, den); fmpz_clear(den); } } void fmpq_poly_rem(fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { slong lenA, lenB, lenR; if (fmpq_poly_is_zero(poly2)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_rem). Division by zero.\n"); } if (poly1->length < poly2->length) { fmpq_poly_set(R, poly1); return; } /* Deal with aliasing */ if (R == poly1 || R == poly2) { fmpq_poly_t tempR; fmpq_poly_init(tempR); fmpq_poly_rem(tempR, poly1, poly2); fmpq_poly_swap(R, tempR); fmpq_poly_clear(tempR); return; } lenA = poly1->length; lenB = poly2->length; lenR = lenB - 1; fmpq_poly_fit_length(R, lenA); /* XXX: Need at least that much space */ _fmpq_poly_rem(R->coeffs, R->den, poly1->coeffs, poly1->den, poly1->length, poly2->coeffs, poly2->den, poly2->length, NULL); _fmpq_poly_set_length(R, lenR); _fmpq_poly_normalise(R); } flint-3.1.3/src/fmpq_poly/rem_powers_precomp.c000066400000000000000000000051161461254215100215060ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_rem_powers_precomp(fmpz * A, fmpz_t denA, slong m, const fmpz * B, const fmpz_t denB, slong n, fmpq_poly_struct * const powers) { slong i; fmpq_poly_t prod; fmpz_t den; if (m >= 2*n) /* TODO: make this case use the precomputed squares */ { fmpz * R = _fmpz_vec_init(m); fmpz_init(den); _fmpz_vec_set(R, A, m); fmpz_set(den, denA); _fmpq_poly_rem(A, denA, R, den, m, B, denB, n, NULL); _fmpz_vec_clear(R, m); fmpz_clear(den); return; } if (m < n) return; fmpz_init(den); fmpq_poly_init2(prod, n - 1); fmpz_set(den, denA); for (i = n - 1; i < m; i++) { _fmpz_vec_scalar_mul_fmpz(fmpq_poly_numref(prod), fmpq_poly_numref(powers + i), powers[i].length, A + i); fmpz_mul(fmpq_poly_denref(prod), fmpq_poly_denref(powers + i), den); _fmpq_poly_add_can(A, denA, A, denA, n - 1, fmpq_poly_numref(prod), fmpq_poly_denref(prod), powers[i].length, 0); } fmpq_poly_clear(prod); fmpz_clear(den); } void fmpq_poly_rem_powers_precomp(fmpq_poly_t R, const fmpq_poly_t A, const fmpq_poly_t B, const fmpq_poly_powers_precomp_t B_inv) { fmpq_poly_t tR; fmpz * r, * d; slong len1 = A->length, len2 = B->length; if (len1 < len2) { fmpq_poly_set(R, A); return; } if (R == B) { fmpq_poly_init2(tR, len1); r = fmpq_poly_numref(tR); d = fmpq_poly_denref(tR); } else { fmpq_poly_fit_length(R, len1); r = fmpq_poly_numref(R); d = fmpq_poly_denref(R); } if (R == B || R != A) { _fmpz_vec_set(r, fmpq_poly_numref(A), len1); fmpz_set(d, fmpq_poly_denref(A)); } _fmpq_poly_rem_powers_precomp(r, d, len1, fmpq_poly_numref(B), fmpq_poly_denref(B), len2, B_inv->powers); if (R == B) { _fmpq_poly_set_length(tR, len2 - 1); fmpq_poly_swap(tR, R); fmpq_poly_clear(tR); } else _fmpq_poly_set_length(R, len2 - 1); _fmpq_poly_normalise(R); } flint-3.1.3/src/fmpq_poly/remove.c000066400000000000000000000050321461254215100170710ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_poly.h" slong fmpq_poly_remove(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { fmpq_poly_t p1, p2, qpoly, pow; fmpq_t c1, c2; fmpz_t p1sum, p2sum, qsum; slong i, len1, len2; len1 = poly1->length; len2 = poly2->length; if (len2 == 0) { flint_throw(FLINT_ERROR, "(fmpq_poly_remove): Division by zero.\n"); } if (len2 == 1) { flint_throw(FLINT_ERROR, "(fmpq_poly_remove): Divisor must not be a unit.\n"); } if (len2 > len1) { fmpq_poly_set(q, poly1); return 0; } fmpq_poly_init(qpoly); fmpq_poly_init(p1); fmpq_poly_init(p2); fmpq_poly_init(pow); fmpq_init(c1); fmpq_init(c2); fmpq_poly_content(c1, poly1); fmpq_poly_content(c2, poly2); fmpq_poly_scalar_div_fmpq(p1, poly1, c1); fmpq_poly_scalar_div_fmpq(p2, poly2, c2); fmpz_init(p1sum); fmpz_init(p2sum); fmpz_init(qsum); for (i = 0; i < poly1->length; i++) fmpz_add(p1sum, p1sum, p1->coeffs + i); for (i = 0; i < poly2->length; i++) fmpz_add(p2sum, p2sum, p2->coeffs + i); fmpz_abs(p1sum, p1sum); fmpz_abs(p2sum, p2sum); if (fmpz_is_zero(p2sum)) { if (!fmpz_is_zero(p1sum)) { fmpq_poly_set(q, poly1); i = 0; goto cleanup; } else i = (p1->length - 1)/(p2->length - 1); } else if (fmpz_is_zero(p1sum) || fmpz_is_one(p2sum)) i = (p1->length - 1)/(p2->length - 1); else i = fmpz_remove(qsum, p1sum, p2sum); fmpq_poly_pow(pow, p2, i); while (i > 0 && !fmpq_poly_divides(qpoly, p1, pow)) { fmpq_poly_div(pow, pow, p2); i--; } if (i == 0) fmpq_poly_set(q, poly1); else { fmpq_pow_si(c2, c2, i); fmpq_div(c1, c1, c2); fmpq_poly_scalar_mul_fmpq(q, qpoly, c1); } cleanup: fmpz_clear(qsum); fmpz_clear(p1sum); fmpz_clear(p2sum); fmpq_clear(c2); fmpq_clear(c1); fmpq_poly_clear(pow); fmpq_poly_clear(p2); fmpq_poly_clear(p1); fmpq_poly_clear(qpoly); return i; } flint-3.1.3/src/fmpq_poly/rescale.c000066400000000000000000000034761461254215100172240ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_rescale(fmpz * res, fmpz_t denr, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t xnum, const fmpz_t xden) { if (len < WORD(2)) { if (res != poly) { _fmpz_vec_set(res, poly, len); fmpz_set(denr, den); } } else { slong i; fmpz_t t; fmpz_init(t); fmpz_one(t); fmpz_set(res, poly); for (i = WORD(1); i < len; i++) { fmpz_mul(t, t, xnum); fmpz_mul(res + i, poly + i, t); } fmpz_one(t); for (i = len - WORD(2); i >= WORD(0); i--) { fmpz_mul(t, t, xden); fmpz_mul(res + i, res + i, t); } fmpz_mul(denr, den, t); fmpz_clear(t); _fmpq_poly_canonicalise(res, denr, len); } } void fmpq_poly_rescale(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t x) { if (fmpq_is_zero(x)) { fmpq_poly_zero(res); } else if (poly->length < WORD(2)) { fmpq_poly_set(res, poly); } else { fmpq_poly_fit_length(res, poly->length); _fmpq_poly_rescale(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, fmpq_numref(x), fmpq_denref(x)); _fmpq_poly_set_length(res, poly->length); } } flint-3.1.3/src/fmpq_poly/resultant.c000066400000000000000000000112751461254215100176230ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_resultant(fmpz_t rnum, fmpz_t rden, const fmpz *poly1, const fmpz_t den1, slong len1, const fmpz *poly2, const fmpz_t den2, slong len2) { if (len2 == 1) { if (len1 == 1) { fmpz_one(rnum); fmpz_one(rden); } else if (len1 == 2) { fmpz_set(rnum, poly2); fmpz_set(rden, den2); } else { fmpz_pow_ui(rnum, poly2, len1 - 1); if (fmpz_is_one(den2)) { fmpz_one(rden); } else { fmpz_pow_ui(rden, den2, len1 - 1); } } } else /* len1 >= len2 >= 2 */ { fmpz_t c1, c2; fmpz *prim1, *prim2, *g; slong lenG = len2; ulong p; nmod_t mod; mp_ptr pp1, pp2, gp; fmpz_init(c1); fmpz_init(c2); _fmpz_vec_content(c1, poly1, len1); _fmpz_vec_content(c2, poly2, len2); prim1 = _fmpz_vec_init(len1); prim2 = _fmpz_vec_init(len2); g = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(prim1, poly1, len1, c1); _fmpz_vec_scalar_divexact_fmpz(prim2, poly2, len2, c2); /* first check GCD mod a prime */ #if FLINT64 p = UWORD(1152921504606846869); #else p = UWORD(1073741789); #endif /* ensure p doesn't divide the leading coeffs */ while (fmpz_fdiv_ui(prim1 + len1 - 1, p) == 0 || fmpz_fdiv_ui(prim2 + len2 - 1, p) == 0) p = n_nextprime(p, 1); nmod_init(&mod, p); pp1 = _nmod_vec_init(len1); pp2 = _nmod_vec_init(len2); gp = _nmod_vec_init(len2); _fmpz_vec_get_nmod_vec(pp1, prim1, len1, mod); _fmpz_vec_get_nmod_vec(pp2, prim2, len2, mod); lenG = _nmod_poly_gcd(gp, pp1, len1, pp2, len2, mod); if (lenG > 1) /* inconclusive, p could be a bad prime, so check over Z */ { _fmpz_poly_gcd(g, prim1, len1, prim2, len2); FMPZ_VEC_NORM(g, lenG); } if (lenG > 1) { fmpz_zero(rnum); fmpz_one(rden); } else /* prim1, prim2 are coprime */ { fmpz_t t; fmpz_init(t); _fmpz_poly_resultant(rnum, prim1, len1, prim2, len2); if (!fmpz_is_one(c1)) { fmpz_pow_ui(t, c1, len2 - 1); fmpz_mul(rnum, rnum, t); } if (!fmpz_is_one(c2)) { fmpz_pow_ui(t, c2, len1 - 1); fmpz_mul(rnum, rnum, t); } if (fmpz_is_one(den1)) { if (fmpz_is_one(den2)) fmpz_one(rden); else fmpz_pow_ui(rden, den2, len1 - 1); } else { if (fmpz_is_one(den2)) fmpz_pow_ui(rden, den1, len2 - 1); else { fmpz_pow_ui(rden, den1, len2 - 1); fmpz_pow_ui(t, den2, len1 - 1); fmpz_mul(rden, rden, t); } } _fmpq_canonicalise(rnum, rden); fmpz_clear(t); } _nmod_vec_clear(pp1); _nmod_vec_clear(pp2); _nmod_vec_clear(gp); fmpz_clear(c1); fmpz_clear(c2); _fmpz_vec_clear(prim1, len1); _fmpz_vec_clear(prim2, len2); _fmpz_vec_clear(g, len2); } } void fmpq_poly_resultant(fmpq_t r, const fmpq_poly_t f, const fmpq_poly_t g) { const slong len1 = f->length; const slong len2 = g->length; if (len1 == 0 || len2 == 0) { fmpq_zero(r); } else { if (len1 >= len2) { _fmpq_poly_resultant(fmpq_numref(r), fmpq_denref(r), f->coeffs, f->den, len1, g->coeffs, g->den, len2); } else { _fmpq_poly_resultant(fmpq_numref(r), fmpq_denref(r), g->coeffs, g->den, len2, f->coeffs, f->den, len1); if (((len1 | len2) & WORD(1)) == WORD(0)) fmpq_neg(r, r); } } } flint-3.1.3/src/fmpq_poly/resultant_modular_div.c000066400000000000000000000111571461254215100222070ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2015 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_resultant_div(fmpz_t rnum, fmpz_t rden, const fmpz *poly1, const fmpz_t den1, slong len1, const fmpz *poly2, const fmpz_t den2, slong len2, const fmpz_t divisor, slong nbits) { fmpz_t div, l; if (fmpz_is_zero(divisor)) { fmpz_zero(rnum); fmpz_one(rden); return; } if (len2 == 1) { if (len1 == 1) { fmpz_one(rnum); fmpz_one(rden); } else if (len1 == 2) { fmpz_set(rnum, poly2); fmpz_set(rden, den2); } else { fmpz_pow_ui(rnum, poly2, len1 - 1); if (fmpz_is_one(den2)) { fmpz_one(rden); } else { fmpz_pow_ui(rden, den2, len1 - 1); } } fmpz_divexact(rnum, rnum, divisor); } else /* len1 >= len2 >= 2 */ { fmpz_t c1, c2, t, la, lb; fmpz *prim1, *prim2; fmpz_init(c1); fmpz_init(c2); _fmpz_vec_content(c1, poly1, len1); _fmpz_vec_content(c2, poly2, len2); prim1 = _fmpz_vec_init(len1); prim2 = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(prim1, poly1, len1, c1); _fmpz_vec_scalar_divexact_fmpz(prim2, poly2, len2, c2); fmpz_init(l); if (!fmpz_is_one(c1)) { fmpz_pow_ui(l, c1, len2 - 1); fmpz_init(div); fmpz_init(la); fmpz_gcd(div, l, divisor); /* div = gcd(c1^(len2-1), divisor) */ fmpz_divexact(la, l, div); /* la = c1^(len2 -1)/gcd */ fmpz_divexact(div, divisor, div); /*div /= gcd */ nbits = nbits - fmpz_bits(la) + 1; } else { fmpz_init_set(div, divisor); } if (!fmpz_is_one(c2)) { fmpz_init(lb); fmpz_pow_ui(lb, c2, len1 - 1); fmpz_gcd(l, lb, div); fmpz_divexact(lb, lb, l); fmpz_divexact(div, div, l); nbits = nbits - fmpz_bits(lb) + 1; } _fmpz_poly_resultant_modular_div(rnum, prim1, len1, prim2, len2, div, nbits); fmpz_init(t); if (!fmpz_is_one(c1)) { fmpz_mul(rnum, rnum, la); fmpz_clear(la); } if (!fmpz_is_one(c2)) { fmpz_mul(rnum, rnum, lb); fmpz_clear(lb); } if (fmpz_is_one(den1)) { if (fmpz_is_one(den2)) fmpz_one(rden); else fmpz_pow_ui(rden, den2, len1 - 1); } else { if (fmpz_is_one(den2)) fmpz_pow_ui(rden, den1, len2 - 1); else { fmpz_pow_ui(rden, den1, len2 - 1); fmpz_pow_ui(t, den2, len1 - 1); fmpz_mul(rden, rden, t); } } _fmpq_canonicalise(rnum, rden); fmpz_clear(t); fmpz_clear(c1); fmpz_clear(c2); fmpz_clear(div); fmpz_clear(l); _fmpz_vec_clear(prim1, len1); _fmpz_vec_clear(prim2, len2); } } void fmpq_poly_resultant_div(fmpq_t r, const fmpq_poly_t f, const fmpq_poly_t g, const fmpz_t divisor, slong nbits) { const slong len1 = f->length; const slong len2 = g->length; if (len1 == 0 || len2 == 0 || fmpz_is_zero(divisor)) { fmpq_zero(r); } else { if (len1 >= len2) { _fmpq_poly_resultant_div(fmpq_numref(r), fmpq_denref(r), f->coeffs, f->den, len1, g->coeffs, g->den, len2, divisor, nbits); } else { _fmpq_poly_resultant_div(fmpq_numref(r), fmpq_denref(r), g->coeffs, g->den, len2, f->coeffs, f->den, len1, divisor, nbits); if (((len1 | len2) & WORD(1)) == WORD(0)) fmpq_neg(r, r); } } } flint-3.1.3/src/fmpq_poly/reverse.c000066400000000000000000000015141461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void fmpq_poly_reverse(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { slong len = FLINT_MIN(n, poly->length); if (len == 0) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, n); _fmpz_poly_reverse(res->coeffs, poly->coeffs, len, n); fmpz_set(res->den, poly->den); _fmpq_poly_set_length(res, n); fmpq_poly_canonicalise(res); } flint-3.1.3/src/fmpq_poly/revert_series.c000066400000000000000000000034071461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_revert_series(fmpz * Qinv, fmpz_t den, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n) { if (fmpz_is_one(Qden) && (n > 1) && fmpz_is_pm1(Q + 1)) { _fmpz_poly_revert_series(Qinv, Q, Qlen, n); fmpz_one(den); return; } _fmpq_poly_revert_series_lagrange_fast(Qinv, den, Q, Qden, Qlen, n); } void fmpq_poly_revert_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length < 2 || !fmpz_is_zero(poly->coeffs) || fmpz_is_zero(poly->coeffs + 1)) { flint_throw(FLINT_ERROR, "(fmpq_poly_revert_series): " "Input must have zero constant term and nonzero coefficient of x^1.\n"); } if (n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_revert_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_revert_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/revert_series_lagrange.c000066400000000000000000000070011461254215100223130ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" static void _set_vec(fmpz * rnum, fmpz_t den, const fmpz * xnum, const fmpz * xden, slong len) { slong j; fmpz_t t; fmpz_init(t); fmpz_one(den); for (j = 0; j < len; j++) fmpz_lcm(den, den, xden + j); for (j = 0; j < len; j++) { fmpz_divexact(t, den, xden + j); fmpz_mul(rnum + j, xnum + j, t); } fmpz_clear(t); } void _fmpq_poly_revert_series_lagrange(fmpz * Qinv, fmpz_t den, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n) { slong i; fmpz *R, *S, *T, *dens, *tmp; fmpz_t Rden, Sden, Tden; Qlen = FLINT_MIN(Qlen, n); if (Qlen <= 2) { fmpz_zero(Qinv); if (Qlen == 2) { fmpz_set(Qinv + 1, Qden); fmpz_set(den, Q + 1); _fmpq_poly_canonicalise(Qinv, den, 2); } _fmpz_vec_zero(Qinv + 2, n - 2); } else { dens = _fmpz_vec_init(n); R = _fmpz_vec_init(n - 1); S = _fmpz_vec_init(n - 1); T = _fmpz_vec_init(n - 1); fmpz_init(Rden); fmpz_init(Sden); fmpz_init(Tden); fmpz_zero(Qinv); fmpz_one(dens); fmpz_set(Qinv + 1, Qden); fmpz_set(dens + 1, Q + 1); _fmpq_poly_inv_series(R, Rden, Q + 1, Qden, Qlen - 1, n - 1); _fmpq_poly_canonicalise(R, Rden, n - 1); _fmpz_vec_set(S, R, n - 1); fmpz_set(Sden, Rden); for (i = 2; i < n; i++) { _fmpq_poly_mullow(T, Tden, S, Sden, n - 1, R, Rden, n - 1, n - 1); _fmpq_poly_canonicalise(T, Tden, n - 1); fmpz_set(Qinv + i, T + i - 1); fmpz_mul_ui(dens + i, Tden, i); tmp = S; S = T; T = tmp; fmpz_swap(Sden, Tden); } _set_vec(Qinv, den, Qinv, dens, n); _fmpq_poly_canonicalise(Qinv, den, n); _fmpz_vec_clear(R, n - 1); _fmpz_vec_clear(S, n - 1); _fmpz_vec_clear(T, n - 1); _fmpz_vec_clear(dens, n); fmpz_clear(Rden); fmpz_clear(Sden); fmpz_clear(Tden); } } void fmpq_poly_revert_series_lagrange(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length < 2 || !fmpz_is_zero(poly->coeffs) || fmpz_is_zero(poly->coeffs + 1)) { flint_throw(FLINT_ERROR, "(fmpq_poly_revert_series_lagrange): " "Input must have zero constant term and nonzero coefficient of x^1.\n"); } if (n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_revert_series_lagrange(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_revert_series_lagrange(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/revert_series_lagrange_fast.c000066400000000000000000000102571461254215100233370ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" /* pointer to (x/Q)^i */ #define Ri(ii) (R + (n-1)*((ii)-1)) #define Rdeni(ii) (Rden + ii - 1) static void _set_vec(fmpz * rnum, fmpz_t den, const fmpz * xnum, const fmpz * xden, slong len) { slong j; fmpz_t t; fmpz_init(t); fmpz_one(den); for (j = 0; j < len; j++) fmpz_lcm(den, den, xden + j); for (j = 0; j < len; j++) { fmpz_divexact(t, den, xden + j); fmpz_mul(rnum + j, xnum + j, t); } fmpz_clear(t); } void _fmpq_poly_revert_series_lagrange_fast(fmpz * Qinv, fmpz_t den, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n) { slong i, j, m; fmpz *R, *Rden, *S, *T, *dens, *tmp; fmpz_t Sden, Tden; if (Qlen <= 2) { fmpz_zero(Qinv); if (Qlen == 2) { fmpz_set(Qinv + 1, Qden); fmpz_set(den, Q + 1); _fmpq_poly_canonicalise(Qinv, den, 2); } _fmpz_vec_zero(Qinv + 2, n - 2); return; } m = n_sqrt(n); dens = _fmpz_vec_init(n); R = _fmpz_vec_init((n - 1) * m); S = _fmpz_vec_init(n - 1); T = _fmpz_vec_init(n - 1); Rden = _fmpz_vec_init(m); fmpz_init(Sden); fmpz_init(Tden); fmpz_zero(Qinv); fmpz_one(dens); _fmpq_poly_inv_series(Ri(1), Rdeni(1), Q + 1, Qden, Qlen - 1, n - 1); _fmpq_poly_canonicalise(Ri(1), Rdeni(1), n - 1); for (i = 2; i <= m; i++) { _fmpq_poly_mullow(Ri(i), Rdeni(i), Ri(i-1), Rdeni(i-1), n - 1, Ri(1), Rdeni(1), n - 1, n - 1); _fmpq_poly_canonicalise(Ri(i), Rdeni(i), n - 1); } for (i = 1; i < m; i++) { fmpz_set(Qinv + i, Ri(i) + i - 1); fmpz_mul_ui(dens + i, Rdeni(i), i); } _fmpz_vec_set(S, Ri(m), n - 1); fmpz_set(Sden, Rdeni(m)); for (i = m; i < n; i += m) { fmpz_set(Qinv + i, S + i - 1); fmpz_mul_ui(dens + i, Sden, i); for (j = 1; j < m && i + j < n; j++) { _fmpz_vec_dot_general(Qinv + i + j, NULL, 0, S, Ri(j), 1, i + j); fmpz_mul(dens + i + j, Sden, Rdeni(j)); fmpz_mul_ui(dens + i + j, dens + i + j, i + j); } if (i + 1 < n) { _fmpq_poly_mullow(T, Tden, S, Sden, n - 1, Ri(m), Rdeni(m), n - 1, n - 1); _fmpq_poly_canonicalise(T, Tden, n - 1); fmpz_swap(Tden, Sden); tmp = S; S = T; T = tmp; } } _set_vec(Qinv, den, Qinv, dens, n); _fmpq_poly_canonicalise(Qinv, den, n); _fmpz_vec_clear(dens, n); _fmpz_vec_clear(R, (n - 1) * m); _fmpz_vec_clear(S, n - 1); _fmpz_vec_clear(T, n - 1); _fmpz_vec_clear(Rden, m); fmpz_clear(Sden); fmpz_clear(Tden); } void fmpq_poly_revert_series_lagrange_fast(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length < 2 || !fmpz_is_zero(poly->coeffs) || fmpz_is_zero(poly->coeffs + 1)) { flint_throw(FLINT_ERROR, "(fmpq_poly_revert_series_lagrange_fast): Input must " "have zero constant term and nonzero coefficient of x^1.\n"); } if (n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_revert_series_lagrange_fast(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_revert_series_lagrange_fast(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/revert_series_newton.c000066400000000000000000000074511461254215100220560ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" /* Newton iteration macros */ #define FLINT_NEWTON_INIT(from, to) \ { \ slong __steps[FLINT_BITS], __i, __from, __to; \ __steps[__i = 0] = __to = (to); \ __from = (from); \ while (__to > __from) \ __steps[++__i] = (__to = (__to + 1) / 2); \ #define FLINT_NEWTON_BASECASE(bc_to) { slong bc_to = __to; #define FLINT_NEWTON_END_BASECASE } #define FLINT_NEWTON_LOOP(step_from, step_to) \ { \ for (__i--; __i >= 0; __i--) \ { \ slong step_from = __steps[__i+1]; \ slong step_to = __steps[__i]; \ #define FLINT_NEWTON_END_LOOP }} #define FLINT_NEWTON_END } #define FLINT_REVERSE_NEWTON_CUTOFF 4 void _fmpq_poly_revert_series_newton(fmpz * Qinv, fmpz_t den, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n) { Qlen = FLINT_MIN(Qlen, n); if (Qlen <= 2) { fmpz_zero(Qinv); if (Qlen == 2) { fmpz_set(Qinv + 1, Qden); fmpz_set(den, Q + 1); _fmpq_poly_canonicalise(Qinv, den, 2); } _fmpz_vec_zero(Qinv + 2, n - 2); } else { fmpz *T, *U, *V; fmpz_t Tden, Uden, Vden; T = _fmpz_vec_init(n); U = _fmpz_vec_init(n); V = _fmpz_vec_init(n); fmpz_init(Tden); fmpz_init(Uden); fmpz_init(Vden); FLINT_NEWTON_INIT(FLINT_REVERSE_NEWTON_CUTOFF, n) FLINT_NEWTON_BASECASE(k) _fmpq_poly_revert_series_lagrange(Qinv, den, Q, Qden, Qlen, k); _fmpz_vec_zero(Qinv + k, n - k); FLINT_NEWTON_END_BASECASE FLINT_NEWTON_LOOP(k0, k) _fmpq_poly_compose_series(T, Tden, Q, Qden, FLINT_MIN(Qlen, k), Qinv, den, k0, k); _fmpq_poly_derivative(U, Uden, T, Tden, k); fmpz_zero(U + k - 1); fmpz_zero(T + 1); _fmpq_poly_div_series(V, Vden, T, Tden, k, U, Uden, k, k); _fmpq_poly_canonicalise(V, Vden, k); _fmpq_poly_derivative(T, Tden, Qinv, den, k); _fmpq_poly_mullow(U, Uden, V, Vden, k, T, Tden, k, k); _fmpq_poly_sub(Qinv, den, Qinv, den, k, U, Uden, k); FLINT_NEWTON_END_LOOP FLINT_NEWTON_END _fmpq_poly_canonicalise(Qinv, den, n); _fmpz_vec_clear(T, n); _fmpz_vec_clear(U, n); _fmpz_vec_clear(V, n); fmpz_clear(Tden); fmpz_clear(Uden); fmpz_clear(Vden); } } void fmpq_poly_revert_series_newton(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length < 2 || !fmpz_is_zero(poly->coeffs) || fmpz_is_zero(poly->coeffs + 1)) { flint_throw(FLINT_ERROR, "(fmpq_poly_revert_series_newton): " "Input must have zero constant term and nonzero coefficient of x^1.\n"); } if (n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_revert_series_newton(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_revert_series_newton(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/scalar.c000066400000000000000000000314341461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_scalar_div_fmpq(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t r, const fmpz_t s) { fmpz_t gcd1; /* GCD( poly, r ) */ fmpz_t gcd2; /* GCD( s, den ) */ fmpz_init(gcd1); fmpz_init(gcd2); fmpz_one(gcd1); fmpz_one(gcd2); if (!fmpz_is_one(r)) _fmpz_vec_content_chained(gcd1, poly, len, r); if (!fmpz_is_one(den) && !fmpz_is_one(s)) fmpz_gcd(gcd2, s, den); if (fmpz_is_one(gcd1)) { if (fmpz_is_one(gcd2)) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, s); fmpz_mul(rden, den, r); } else { fmpz_t s2; fmpz_init(s2); fmpz_divexact(s2, s, gcd2); _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, s2); fmpz_divexact(rden, den, gcd2); fmpz_mul(rden, rden, r); fmpz_clear(s2); } } else { fmpz_t r2; fmpz_init(r2); fmpz_divexact(r2, r, gcd1); if (fmpz_is_one(gcd2)) { _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1); _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, s); fmpz_mul(rden, den, r2); } else { fmpz_t s2; fmpz_init(s2); fmpz_divexact(s2, s, gcd2); _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1); _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, s2); fmpz_divexact(rden, den, gcd2); fmpz_mul(rden, rden, r2); fmpz_clear(s2); } fmpz_clear(r2); } if (_fmpz_vec_is_zero(rpoly, len)) fmpz_one(rden); if (fmpz_sgn(rden) < 0) { _fmpz_vec_neg(rpoly, rpoly, len); fmpz_neg(rden, rden); } fmpz_clear(gcd1); fmpz_clear(gcd2); } void fmpq_poly_scalar_div_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c) { if (fmpq_is_zero(c)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_scalar_div_fmpq). Division by zero.\n"); } if (fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); } else { fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_div_fmpq(rop->coeffs, rop->den, op->coeffs, op->den, op->length, fmpq_numref(c), fmpq_denref(c)); } } void _fmpq_poly_scalar_div_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c) { if (fmpz_is_one(c)) { if (rpoly != poly) { _fmpz_vec_set(rpoly, poly, len); fmpz_set(rden, den); } } else if (*c == WORD(-1)) { _fmpz_vec_neg(rpoly, poly, len); fmpz_set(rden, den); } else { fmpz_t d; fmpz_init(d); _fmpz_vec_content_chained(d, poly, len, c); if (fmpz_sgn(c) < 0) fmpz_neg(d, d); _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, d); fmpz_divexact(d, c, d); fmpz_mul(rden, den, d); fmpz_clear(d); } } void fmpq_poly_scalar_div_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c) { if (*c == WORD(0)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_scalar_div_fmpz). Division by zero.\n"); } if (fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); return; } fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_div_fmpz(rop->coeffs, rop->den, op->coeffs, op->den, op->length, c); } void _fmpq_poly_scalar_div_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c) { if (c == 1) { if (rpoly != poly) { _fmpz_vec_set(rpoly, poly, len); fmpz_set(rden, den); } } else if (c == -1) { _fmpz_vec_neg(rpoly, poly, len); fmpz_set(rden, den); } else { fmpz_t d, f; fmpz_init(d); fmpz_init(f); fmpz_set_si(f, c); _fmpz_vec_content_chained(d, poly, len, f); if (c > 0) { _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, d); fmpz_mul_si(rden, den, c / fmpz_get_si(d)); } else { ulong q = (- (ulong) c) / fmpz_get_ui(d); fmpz_neg(d, d); _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, d); fmpz_mul_ui(rden, den, q); } fmpz_clear(d); fmpz_clear(f); } } void fmpq_poly_scalar_div_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c) { if (c == WORD(0)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_scalar_div_si). Division by zero.\n"); } if (fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); return; } fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_div_si(rop->coeffs, rop->den, op->coeffs, op->den, op->length, c); } void _fmpq_poly_scalar_div_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c) { if (c == UWORD(1)) { if (rpoly != poly) _fmpz_vec_set(rpoly, poly, len); fmpz_set(rden, den); } else { fmpz_t d, fc; ulong ud; fmpz_init(d); fmpz_init(fc); fmpz_set_ui(fc, c); _fmpz_vec_content_chained(d, poly, len, fc); ud = fmpz_get_ui(d); /* gcd of d and c fits into a ulong */ _fmpz_vec_scalar_divexact_ui(rpoly, poly, len, ud); fmpz_mul_ui(rden, den, c / ud); fmpz_clear(d); fmpz_clear(fc); } } void fmpq_poly_scalar_div_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c) { if (c == UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_scalar_div_ui). Division by zero.\n"); } if (fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); return; } fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_div_ui(rop->coeffs, rop->den, op->coeffs, op->den, op->length, c); } void _fmpq_poly_scalar_mul_fmpq(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t r, const fmpz_t s) { fmpz_t gcd1; /* GCD( poly, s ) */ fmpz_t gcd2; /* GCD( r, den ) */ if (fmpz_is_zero(r)) { _fmpz_vec_zero(rpoly, len); fmpz_one(rden); return; } fmpz_init(gcd1); fmpz_init(gcd2); fmpz_one(gcd1); fmpz_one(gcd2); if (!fmpz_is_one(s)) _fmpz_vec_content_chained(gcd1, poly, len, s); if (!fmpz_is_one(den) && !fmpz_is_one(r)) fmpz_gcd(gcd2, r, den); if (fmpz_is_one(gcd1)) { if (fmpz_is_one(gcd2)) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, r); fmpz_mul(rden, den, s); } else { fmpz_t r2; fmpz_init(r2); fmpz_divexact(r2, r, gcd2); _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, r2); fmpz_divexact(rden, den, gcd2); fmpz_mul(rden, rden, s); fmpz_clear(r2); } } else { fmpz_t s2; fmpz_init(s2); fmpz_divexact(s2, s, gcd1); if (fmpz_is_one(gcd2)) { _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1); _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, r); fmpz_mul(rden, den, s2); } else { fmpz_t r2; fmpz_init(r2); fmpz_divexact(r2, r, gcd2); _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1); _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, r2); fmpz_divexact(rden, den, gcd2); fmpz_mul(rden, rden, s2); fmpz_clear(r2); } fmpz_clear(s2); } fmpz_clear(gcd1); fmpz_clear(gcd2); } void fmpq_poly_scalar_mul_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c) { if (fmpz_is_one(fmpq_denref(c))) { fmpq_poly_scalar_mul_fmpz(rop, op, fmpq_numref(c)); } else if (fmpq_is_zero(c) || fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); } else { fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_mul_fmpq(rop->coeffs, rop->den, op->coeffs, op->den, op->length, fmpq_numref(c), fmpq_denref(c)); } } void _fmpq_poly_scalar_mul_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c) { fmpz_t gcd; /* GCD( den, c ) */ if (fmpz_is_zero(c)) { _fmpz_vec_zero(rpoly, len); fmpz_one(rden); return; } fmpz_init(gcd); fmpz_one(gcd); if (!fmpz_is_one(c)) fmpz_gcd(gcd, c, den); if (fmpz_is_one(gcd)) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, c); fmpz_set(rden, den); } else { fmpz_t c2; fmpz_init(c2); fmpz_divexact(c2, c, gcd); _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, c2); fmpz_divexact(rden, den, gcd); fmpz_clear(c2); } fmpz_clear(gcd); } void fmpq_poly_scalar_mul_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c) { if (fmpz_is_zero(c) || fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); return; } fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_mul_fmpz(rop->coeffs, rop->den, op->coeffs, op->den, op->length, c); } void _fmpq_poly_scalar_mul_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c) { fmpz_t gcd; /* GCD( den, c ) */ if (c == 0) { _fmpz_vec_zero(rpoly, len); fmpz_one(rden); return; } fmpz_init(gcd); fmpz_set_si(gcd, c); fmpz_gcd(gcd, gcd, den); if (fmpz_is_one(gcd)) { _fmpz_vec_scalar_mul_si(rpoly, poly, len, c); fmpz_set(rden, den); } else { if (c > WORD_MIN || fmpz_cmp_ui(gcd, - (ulong) WORD_MIN)) { slong g = fmpz_get_si(gcd); _fmpz_vec_scalar_mul_si(rpoly, poly, len, c / g); fmpz_divexact_si(rden, den, g); } else { _fmpz_vec_neg(rpoly, poly, len); fmpz_divexact_ui(rden, den, - (ulong) WORD_MIN); } } fmpz_clear(gcd); } void fmpq_poly_scalar_mul_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c) { if (c == 0 || fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); return; } fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_mul_si(rop->coeffs, rop->den, op->coeffs, op->den, op->length, c); } void _fmpq_poly_scalar_mul_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c) { fmpz_t gcd; /* GCD( den, c ) */ if (c == 0) { _fmpz_vec_zero(rpoly, len); fmpz_one(rden); return; } fmpz_init(gcd); fmpz_set_ui(gcd, c); fmpz_gcd(gcd, gcd, den); if (fmpz_is_one(gcd)) { _fmpz_vec_scalar_mul_ui(rpoly, poly, len, c); fmpz_set(rden, den); } else { ulong gcd2 = fmpz_get_ui(gcd); ulong c2 = c / gcd2; _fmpz_vec_scalar_mul_ui(rpoly, poly, len, c2); fmpz_fdiv_q_ui(rden, den, gcd2); } fmpz_clear(gcd); } void fmpq_poly_scalar_mul_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c) { if (c == 0 || fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); return; } fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_mul_ui(rop->coeffs, rop->den, op->coeffs, op->den, op->length, c); } flint-3.1.3/src/fmpq_poly/set.c000066400000000000000000000050541461254215100163730ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void fmpq_poly_set(fmpq_poly_t poly1, const fmpq_poly_t poly2) { if (poly1 != poly2) { slong i, len = poly2->length; fmpq_poly_fit_length(poly1, len); for (i = 0; i < len; i++) fmpz_set(poly1->coeffs + i, poly2->coeffs + i); _fmpq_poly_set_length(poly1, len); fmpz_set(poly1->den, poly2->den); } } void fmpq_poly_set_fmpq(fmpq_poly_t poly, const fmpq_t x) { fmpq_poly_fit_length(poly, 1); fmpz_set(poly->coeffs, fmpq_numref(x)); fmpz_set(poly->den, fmpq_denref(x)); _fmpq_poly_set_length(poly, 1); _fmpq_poly_normalise(poly); } void fmpq_poly_set_fmpz(fmpq_poly_t poly, const fmpz_t x) { fmpq_poly_fit_length(poly, 1); fmpz_set(poly->coeffs, x); fmpz_one(poly->den); _fmpq_poly_set_length(poly, 1); _fmpq_poly_normalise(poly); } void fmpq_poly_set_fmpz_poly(fmpq_poly_t rop, const fmpz_poly_t op) { if (fmpz_poly_is_zero(op)) { fmpq_poly_zero(rop); } else { fmpq_poly_fit_length(rop, fmpz_poly_length(op)); _fmpq_poly_set_length(rop, fmpz_poly_length(op)); _fmpz_vec_set(rop->coeffs, op->coeffs, rop->length); fmpz_one(rop->den); } } void fmpq_poly_set_nmod_poly(fmpq_poly_t rop, const nmod_poly_t op) { slong len = op->length; if (len == 0) { fmpq_poly_zero(rop); } else { slong i; fmpz_one(rop->den); fmpq_poly_fit_length(rop, len); for (i = 0; i < len; i++) fmpz_set_ui_smod(rop->coeffs + i, op->coeffs[i], op->mod.n); _fmpq_poly_set_length(rop, len); } } void fmpq_poly_set_si(fmpq_poly_t poly, slong x) { fmpq_poly_fit_length(poly, 1); fmpz_set_si(poly->coeffs, x); fmpz_one(poly->den); _fmpq_poly_set_length(poly, 1); _fmpq_poly_normalise(poly); } void fmpq_poly_set_ui(fmpq_poly_t poly, ulong x) { fmpq_poly_fit_length(poly, 1); fmpz_set_ui(poly->coeffs, x); fmpz_one(poly->den); _fmpq_poly_set_length(poly, 1); _fmpq_poly_normalise(poly); } flint-3.1.3/src/fmpq_poly/set_coeff.c000066400000000000000000000103421461254215100175310ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" void fmpq_poly_set_coeff_fmpq(fmpq_poly_t poly, slong n, const fmpq_t x) { slong len = poly->length; const int replace = (n < len && !fmpz_is_zero(poly->coeffs + n)); if (!replace && fmpq_is_zero(x)) return; if (n + 1 > len) { fmpq_poly_fit_length(poly, n + 1); _fmpq_poly_set_length(poly, n + 1); flint_mpn_zero((mp_ptr) poly->coeffs + len, (n + 1) - len); len = n + 1; } if (replace) { fmpz_t c; fmpz_init(c); fmpz_zero(poly->coeffs + n); _fmpz_poly_content(c, poly->coeffs, len); _fmpz_vec_scalar_mul_fmpz(poly->coeffs, poly->coeffs, len, fmpq_denref(x)); fmpz_mul(c, c, fmpq_denref(x)); fmpz_mul(poly->coeffs + n, fmpq_numref(x), poly->den); fmpz_gcd(c, c, poly->coeffs + n); fmpz_mul(poly->den, poly->den, fmpq_denref(x)); if (!fmpz_is_one(c)) fmpz_gcd(c, c, poly->den); if (!fmpz_is_one(c)) { _fmpz_vec_scalar_divexact_fmpz(poly->coeffs, poly->coeffs, len, c); fmpz_divexact(poly->den, poly->den, c); } _fmpq_poly_normalise(poly); fmpz_clear(c); } else { fmpz_t d, t; fmpz_init(d); fmpz_init(t); fmpz_gcd(d, poly->den, fmpq_denref(x)); fmpz_divexact(t, fmpq_denref(x), d); _fmpz_vec_scalar_mul_fmpz(poly->coeffs, poly->coeffs, len, t); fmpz_set(poly->coeffs + n, fmpq_numref(x)); fmpz_mul(poly->coeffs + n, poly->coeffs + n, poly->den); fmpz_divexact(poly->coeffs + n, poly->coeffs + n, d); fmpz_mul(poly->den, poly->den, t); fmpz_clear(d); fmpz_clear(t); } } void fmpq_poly_set_coeff_fmpz(fmpq_poly_t poly, slong n, const fmpz_t x) { slong len = poly->length; const int replace = (n < len && !fmpz_is_zero(poly->coeffs + n)); if (!replace && fmpz_is_zero(x)) return; if (n + 1 > len) { fmpq_poly_fit_length(poly, n + 1); _fmpq_poly_set_length(poly, n + 1); flint_mpn_zero((mp_ptr) poly->coeffs + len, (n + 1) - len); } if (*poly->den == WORD(1)) { fmpz_set(poly->coeffs + n, x); if (replace) _fmpq_poly_normalise(poly); } else { fmpz_mul(poly->coeffs + n, poly->den, x); if (replace) fmpq_poly_canonicalise(poly); } } void fmpq_poly_set_coeff_si(fmpq_poly_t poly, slong n, slong x) { slong len = poly->length; const int replace = (n < len && !fmpz_is_zero(poly->coeffs + n)); if (!replace && (x == WORD(0))) return; if (n + 1 > len) { fmpq_poly_fit_length(poly, n + 1); _fmpq_poly_set_length(poly, n + 1); flint_mpn_zero((mp_ptr) poly->coeffs + len, (n + 1) - len); } if (*poly->den == WORD(1)) { fmpz_set_si(poly->coeffs + n, x); if (replace) _fmpq_poly_normalise(poly); } else { fmpz_mul_si(poly->coeffs + n, poly->den, x); if (replace) fmpq_poly_canonicalise(poly); } } void fmpq_poly_set_coeff_ui(fmpq_poly_t poly, slong n, ulong x) { slong len = poly->length; const int replace = (n < len && !fmpz_is_zero(poly->coeffs + n)); if (!replace && (x == UWORD(0))) return; if (n + 1 > len) { fmpq_poly_fit_length(poly, n + 1); _fmpq_poly_set_length(poly, n + 1); flint_mpn_zero((mp_ptr) poly->coeffs + len, (n + 1) - len); } if (*poly->den == WORD(1)) { fmpz_set_ui(poly->coeffs + n, x); if (replace) _fmpq_poly_normalise(poly); } else { fmpz_mul_ui(poly->coeffs + n, poly->den, x); if (replace) fmpq_poly_canonicalise(poly); } } flint-3.1.3/src/fmpq_poly/set_length.c000066400000000000000000000012001461254215100177210ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void _fmpq_poly_set_length(fmpq_poly_t poly, slong len) { slong i; for (i = len; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); poly->length = len; } flint-3.1.3/src/fmpq_poly/set_str.c000066400000000000000000000067621461254215100172720ustar00rootroot00000000000000/* Copyright (C) 2018 Vincent Delecroix Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" /* TODO: Remove me */ static void __fmpq_poly_set_array_mpq(fmpz * poly, fmpz_t den, const mpq_t * a, slong n) { slong i; mpz_t d, t; flint_mpz_init_set_ui(d, 1); mpz_init(t); for (i = 0; i < n; i++) { mpz_lcm(d, d, mpq_denref(a[i])); } for (i = 0; i < n; i++) { __mpz_struct *ptr = _fmpz_promote(poly + i); mpz_divexact(t, d, mpq_denref(a[i])); mpz_mul(ptr, mpq_numref(a[i]), t); _fmpz_demote_val(poly + i); } fmpz_set_mpz(den, d); mpz_clear(d); mpz_clear(t); } int _fmpq_poly_set_str(fmpz * poly, fmpz_t den, const char * str, slong len) { char * w; slong i; mpq_t * a; if (!len) return *str == '\0'; if (*str == '\0') return -1; /* Find maximal gap between spaces and allocate w */ { const char * s = str; slong max; for (max = 0; *s != '\0';) { slong cur; for (s++, cur = 1; *s != ' ' && *s != '\0'; s++, cur++) ; if (max < cur) max = cur; } w = (char *) flint_malloc((max + 1) * sizeof(char)); } a = (mpq_t *) flint_malloc(len * sizeof(mpq_t)); str--; for (i = 0; i < len; i++) { char * v; int ans; for (str++, v = w; *str != ' ' && *str != '\0';) *v++ = *str++; *v = '\0'; mpq_init(a[i]); ans = mpq_set_str(a[i], w, 10); /* If the format is not correct, clear up and return -1 */ if (ans || (i + 1 < len && *str == '\0')) { int j; for (j = 0; j <= i; j++) mpq_clear(a[j]); flint_free(a); flint_free(w); return -1; } } __fmpq_poly_set_array_mpq(poly, den, (const mpq_t *) a, len); for (i = 0; i < len; i++) mpq_clear(a[i]); flint_free(a); flint_free(w); if (*str != '\0') return -1; else return 0; } int fmpq_poly_set_str(fmpq_poly_t poly, const char * str) { int ans; slong len; char * endptr; /* Get the length (a positive integer) */ if (*str < 48 || *str > 57) { fmpq_poly_zero(poly); return -1; } errno = 0; len = strtol(str, &endptr, 10); if (errno || len < 0 || (len > 0 && *endptr == '\0')) { fmpq_poly_zero(poly); return -1; } if (len == 0) { fmpq_poly_zero(poly); if (*(str+1) != '\0') return -1; return 0; } /* Check that we have two spaces after the length */ endptr++; if (*endptr != ' ') { fmpq_poly_zero(poly); return -1; } endptr++; /* Now get the coefficients */ fmpq_poly_fit_length(poly, len); ans = _fmpq_poly_set_str(poly->coeffs, poly->den, endptr, len); if (ans) { fmpq_poly_zero(poly); return -1; } _fmpq_poly_set_length(poly, len); _fmpq_poly_normalise(poly); return 0; } flint-3.1.3/src/fmpq_poly/set_trunc.c000066400000000000000000000017261461254215100176100ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_set_trunc(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly == res) { fmpq_poly_truncate(res, n); } else { slong rlen; rlen = FLINT_MIN(n, poly->length); while (rlen > 0 && fmpz_is_zero(poly->coeffs + rlen - 1)) rlen--; fmpq_poly_fit_length(res, rlen); _fmpz_vec_set(res->coeffs, poly->coeffs, rlen); fmpz_set(res->den, poly->den); _fmpq_poly_set_length(res, rlen); fmpq_poly_canonicalise(res); } } flint-3.1.3/src/fmpq_poly/shift_left.c000066400000000000000000000016031461254215100177230ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void fmpq_poly_shift_left(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_set(res, poly); return; } if (poly->length == 0) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, poly->length + n); _fmpz_poly_shift_left(res->coeffs, poly->coeffs, poly->length, n); fmpz_set(res->den, poly->den); _fmpq_poly_set_length(res, poly->length + n); } flint-3.1.3/src/fmpq_poly/shift_right.c000066400000000000000000000016461461254215100201150ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void fmpq_poly_shift_right(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_set(res, poly); return; } if (poly->length <= n) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, poly->length - n); _fmpz_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n); fmpz_set(res->den, poly->den); _fmpq_poly_set_length(res, poly->length - n); fmpq_poly_canonicalise(res); } flint-3.1.3/src/fmpq_poly/sin_cos_series.c000066400000000000000000000112251461254215100206040ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_sin_cos_series_basecase_can(fmpz * S, fmpz_t Sden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n, int can) { fmpz_t t, u, v; slong j, k; Alen = FLINT_MIN(Alen, n); if (Alen == 1 || n == 1) { fmpz_zero(S); fmpz_one(C); _fmpz_vec_zero(S + 1, n - 1); _fmpz_vec_zero(C + 1, n - 1); fmpz_one(Sden); fmpz_one(Cden); return; } /* support aliasing */ if (A == S || A == C) { fmpz * tmp = _fmpz_vec_init(Alen + 1); _fmpz_vec_set(tmp, A, Alen); fmpz_set(tmp + Alen, Aden); _fmpq_poly_sin_cos_series_basecase_can(S, Sden, C, Cden, tmp, tmp + Alen, Alen, n, can); _fmpz_vec_clear(tmp, Alen + 1); return; } fmpz_init(t); fmpz_init(u); fmpz_init(v); fmpz_fac_ui(t, n - 1); fmpz_pow_ui(v, Aden, n - 1); fmpz_mul(Sden, t, v); fmpz_set(C, Sden); fmpz_set(Cden, Sden); fmpz_zero(S); for (k = 1; k < n; k++) { fmpz_zero(t); fmpz_zero(u); /* todo: precompute A[j] * j, use dot products */ for (j = 1; j < FLINT_MIN(Alen, k + 1); j++) { fmpz_mul_ui(v, A + j, j); fmpz_submul(t, v, S + k - j); fmpz_addmul(u, v, C + k - j); } fmpz_mul_ui(v, Aden, k); fmpz_divexact(C + k, t, v); fmpz_divexact(S + k, u, v); } if (can & 1) _fmpq_poly_canonicalise(S, Sden, n); if (can & 2) _fmpq_poly_canonicalise(C, Cden, n); fmpz_clear(t); fmpz_clear(u); fmpz_clear(v); } void _fmpq_poly_sin_cos_series_basecase(fmpz * S, fmpz_t Sden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n) { _fmpq_poly_sin_cos_series_basecase_can(S, Sden, C, Cden, A, Aden, Alen, n, 3); } void _fmpq_poly_sin_cos_series_tangent(fmpz * S, fmpz_t Sden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; Alen = FLINT_MIN(Alen, n); t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* sin(x) = 2*tan(x/2)/(1+tan(x/2)^2) */ /* cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2) */ /* t = tan(x/2), u = 1+tan(x/2)^2 */ fmpz_mul_ui(uden, Aden, 2); _fmpq_poly_tan_series(t, tden, A, uden, Alen, n); _fmpq_poly_mullow(u, uden, t, tden, n, t, tden, n, n); fmpz_set(u, uden); _fmpq_poly_canonicalise(u, uden, n); /* C = 1/(1+tan(x/2))^2 */ _fmpq_poly_inv_series(C, Cden, u, uden, n, n); /* S = sin(x)/2 */ _fmpq_poly_mullow(S, Sden, t, tden, n, C, Cden, n, n); _fmpq_poly_canonicalise(S, Sden, n); /* u = sin(x)/2 * tan(x/2) */ /* C = C - u */ _fmpq_poly_mullow(u, uden, S, Sden, n, t, tden, n, n); _fmpq_poly_canonicalise(u, uden, n); _fmpq_poly_sub(C, Cden, C, Cden, n, u, uden, n); /* S = sin(x) */ _fmpq_poly_scalar_mul_ui(S, Sden, S, Sden, n, 2); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void _fmpq_poly_sin_cos_series(fmpz * S, fmpz_t Sden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n) { if (Alen < 20 || n < 20) _fmpq_poly_sin_cos_series_basecase(S, Sden, C, Cden, A, Aden, Alen, n); else _fmpq_poly_sin_cos_series_tangent(S, Sden, C, Cden, A, Aden, Alen, n); } void fmpq_poly_sin_cos_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_zero(res1); fmpq_poly_zero(res2); return; } if (fmpq_poly_is_zero(poly) || n == 1) { fmpq_poly_zero(res1); fmpq_poly_one(res2); return; } if (!fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_sin_cos_series). Constant term != 0.\n"); } fmpq_poly_fit_length(res1, n); fmpq_poly_fit_length(res2, n); _fmpq_poly_sin_cos_series(res1->coeffs, res1->den, res2->coeffs, res2->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res1, n); _fmpq_poly_normalise(res1); _fmpq_poly_set_length(res2, n); _fmpq_poly_normalise(res2); } flint-3.1.3/src/fmpq_poly/sin_series.c000066400000000000000000000052431461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2011, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_sin_cos_series_basecase_can(fmpz * S, fmpz_t Sden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n, int can); void _fmpq_poly_sin_series_basecase(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * tmp; if (hlen == 1 || n == 1) { fmpz_zero(g); _fmpz_vec_zero(g + 1, n - 1); fmpz_one(gden); return; } tmp = _fmpz_vec_init(n + 1); _fmpq_poly_sin_cos_series_basecase_can(g, gden, tmp, tmp + 1, h, hden, hlen, n, 1); _fmpz_vec_clear(tmp, n + 1); } void _fmpq_poly_sin_series_tangent(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* sin(x) = 2*tan(x/2)/(1+tan(x/2)^2) */ fmpz_mul_ui(uden, hden, 2); _fmpq_poly_tan_series(t, tden, h, uden, hlen, n); _fmpq_poly_mullow(u, uden, t, tden, n, t, tden, n, n); fmpz_set(u, uden); _fmpq_poly_canonicalise(u, uden, n); _fmpq_poly_div_series(g, gden, t, tden, n, u, uden, n, n); _fmpq_poly_canonicalise(g, gden, n); _fmpq_poly_scalar_mul_ui(g, gden, g, gden, n, 2); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void _fmpq_poly_sin_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { if (hlen < 20 || n < 20) _fmpq_poly_sin_series_basecase(g, gden, h, hden, hlen, n); else _fmpq_poly_sin_series_tangent(g, gden, h, hden, hlen, n); } void fmpq_poly_sin_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_sin_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, n); _fmpq_poly_sin_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/sinh_cosh_series.c000066400000000000000000000035411461254215100211260ustar00rootroot00000000000000/* Copyright (C) 2016, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_sinh_cosh_series(fmpz * S, fmpz_t Sden, fmpz * C, fmpz_t Cden, const fmpz * A, const fmpz_t Aden, slong Alen, slong n) { fmpz * t; fmpz_t tden; t = _fmpz_vec_init(n); fmpz_init(tden); /* sinh(x) = (exp(x)-exp(-x))/2 */ /* cosh(x) = (exp(x)+exp(-x))/2 = sinh(x) + exp(-x) */ _fmpq_poly_exp_expinv_series(S, Sden, t, tden, A, Aden, Alen, n); _fmpq_poly_sub(S, Sden, S, Sden, n, t, tden, n); _fmpq_poly_scalar_div_ui(S, Sden, S, Sden, n, 2); _fmpq_poly_add(C, Cden, S, Sden, n, t, tden, n); _fmpz_vec_clear(t, n); fmpz_clear(tden); } void fmpq_poly_sinh_cosh_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n) { if (n == 0) { fmpq_poly_zero(res1); fmpq_poly_zero(res2); return; } if (fmpq_poly_is_zero(poly) || n == 1) { fmpq_poly_zero(res1); fmpq_poly_one(res2); return; } if (!fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_sinh_cosh_series). Constant term != 0.\n"); } fmpq_poly_fit_length(res1, n); fmpq_poly_fit_length(res2, n); _fmpq_poly_sinh_cosh_series(res1->coeffs, res1->den, res2->coeffs, res2->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res1, n); _fmpq_poly_normalise(res1); _fmpq_poly_set_length(res2, n); _fmpq_poly_normalise(res2); } flint-3.1.3/src/fmpq_poly/sinh_series.c000066400000000000000000000026671461254215100201220ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_sinh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz_t tden; t = _fmpz_vec_init(n); fmpz_init(tden); /* sinh(x) = (exp(x)-exp(-x))/2 */ _fmpq_poly_exp_expinv_series(g, gden, t, tden, h, hden, hlen, n); _fmpq_poly_sub(g, gden, g, gden, n, t, tden, n); _fmpq_poly_scalar_div_ui(g, gden, g, gden, n, 2); _fmpz_vec_clear(t, n); fmpz_clear(tden); } void fmpq_poly_sinh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_sinh_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } fmpq_poly_fit_length(res, n); _fmpq_poly_sinh_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/sqrt_series.c000066400000000000000000000032721461254215100201430ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_sqrt_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong n) { fmpz * t; fmpz_t tden; t = _fmpz_vec_init(n); fmpz_init(tden); _fmpq_poly_invsqrt_series(t, tden, poly, den, len, n); _fmpq_poly_mullow(rpoly, rden, t, tden, n, poly, den, len, n); _fmpz_vec_clear(t, n); fmpz_clear(tden); } void fmpq_poly_sqrt_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length < 1 || !fmpz_equal(poly->coeffs, poly->den)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_sqrt_series). Constant term != 1.\n"); } if (n < 1) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_sqrt_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_sqrt_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); fmpq_poly_canonicalise(res); } flint-3.1.3/src/fmpq_poly/sub.c000066400000000000000000000174451461254215100164000ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" void _fmpq_poly_sub_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, int can) { slong max = FLINT_MAX(len1, len2); slong min = FLINT_MIN(len1, len2); fmpz_t d; if (fmpz_equal(den1, den2)) { _fmpz_poly_sub(rpoly, poly1, len1, poly2, len2); if (fmpz_is_one(den1) || !can) fmpz_set(rden, den1); else if (can) { fmpz_init(d); _fmpz_vec_content_chained(d, rpoly, max, den1); if (fmpz_is_one(d)) fmpz_set(rden, den1); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d); fmpz_divexact(rden, den1, d); } fmpz_clear(d); } return; } fmpz_init(d); fmpz_one(d); if (!fmpz_is_one(den1) && !fmpz_is_one(den2)) fmpz_gcd(d, den1, den2); if (fmpz_is_one(d)) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den2); _fmpz_vec_scalar_submul_fmpz(rpoly, poly2, min, den1); if (len1 < len2) { _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den1); _fmpz_vec_neg(rpoly + min, rpoly + min, max - min); } fmpz_mul(rden, den1, den2); } else { fmpz_t den11; fmpz_t den22; fmpz_init(den11); fmpz_init(den22); fmpz_divexact(den11, den1, d); fmpz_divexact(den22, den2, d); _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den22); _fmpz_vec_scalar_submul_fmpz(rpoly, poly2, len2, den11); if (len1 < len2) { _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den11); _fmpz_vec_neg(rpoly + min, rpoly + min, max - min); } if (_fmpz_vec_is_zero(rpoly, max)) fmpz_one(rden); else { if (can) { fmpz_t e; fmpz_init(e); _fmpz_vec_content_chained(e, rpoly, max, d); if (fmpz_is_one(e)) fmpz_mul(rden, den1, den22); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e); fmpz_divexact(den11, den1, e); fmpz_mul(rden, den11, den22); } fmpz_clear(e); } else fmpz_mul(rden, den1, den22); } fmpz_clear(den11); fmpz_clear(den22); } fmpz_clear(d); } void _fmpq_poly_sub(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) { _fmpq_poly_sub_can(rpoly, rden, poly1, den1, len1, poly2, den2, len2, 1); } void fmpq_poly_sub_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can) { slong len1, len2, max; if (poly1 == poly2) { fmpq_poly_zero(res); return; } len1 = poly1->length; len2 = poly2->length; max = FLINT_MAX(poly1->length, poly2->length); fmpq_poly_fit_length(res, max); if (res != poly2) _fmpq_poly_sub_can(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, can); else { _fmpq_poly_sub_can(res->coeffs, res->den, poly2->coeffs, poly2->den, len2, poly1->coeffs, poly1->den, len1, can); _fmpz_vec_neg(res->coeffs, res->coeffs, max); } _fmpq_poly_set_length(res, max); _fmpq_poly_normalise(res); } void fmpq_poly_sub(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { fmpq_poly_sub_can(res, poly1, poly2, 1); } void fmpq_poly_sub_si(fmpq_poly_t res, const fmpq_poly_t poly, slong c) { if (c == 0) { fmpq_poly_set(res, poly); } else if (poly->length == 0) { fmpq_poly_set_si(res, c); fmpz_neg(res->coeffs + 0, res->coeffs + 0); } else { fmpz_t p, q; fmpz_init_set_si(p, c); *q = 1; fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_sub(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, p, q, 1); _fmpq_poly_normalise(res); fmpz_clear(p); } } void fmpq_poly_si_sub(fmpq_poly_t res, slong c, const fmpq_poly_t poly) { if (c == 0) { fmpq_poly_neg(res, poly); } else if (poly->length == 0) { fmpq_poly_set_si(res, c); } else { fmpz_t p, q; fmpz_init_set_si(p, c); *q = 1; fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_sub(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, p, q, 1); _fmpq_poly_normalise(res); _fmpz_vec_neg(res->coeffs, res->coeffs, res->length); fmpz_clear(p); } } void fmpq_poly_sub_fmpz(fmpq_poly_t res, const fmpq_poly_t poly, const fmpz_t c) { if (fmpz_is_zero(c)) { fmpq_poly_set(res, poly); } else if (poly->length == 0) { fmpq_poly_set_fmpz(res, c); fmpz_neg(res->coeffs + 0, res->coeffs + 0); } else { fmpz_t q; *q = 1; fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_sub(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, c, q, 1); _fmpq_poly_normalise(res); } } void fmpq_poly_fmpz_sub(fmpq_poly_t res, const fmpz_t c, const fmpq_poly_t poly) { if (fmpz_is_zero(c)) { fmpq_poly_neg(res, poly); } else if (poly->length == 0) { fmpq_poly_set_fmpz(res, c); } else { fmpz_t q; *q = 1; fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_sub(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, c, q, 1); _fmpq_poly_normalise(res); _fmpz_vec_neg(res->coeffs, res->coeffs, res->length); } } void fmpq_poly_sub_fmpq(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t c) { if (fmpq_is_zero(c)) { fmpq_poly_set(res, poly); } else if (poly->length == 0) { fmpq_poly_set_fmpq(res, c); fmpz_neg(res->coeffs + 0, res->coeffs + 0); } else { fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_sub(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, fmpq_numref(c), fmpq_denref(c), 1); _fmpq_poly_normalise(res); } } void fmpq_poly_fmpq_sub(fmpq_poly_t res, const fmpq_t c, const fmpq_poly_t poly) { if (fmpq_is_zero(c)) { fmpq_poly_neg(res, poly); } else if (poly->length == 0) { fmpq_poly_set_fmpq(res, c); } else { fmpq_poly_fit_length(res, poly->length); _fmpq_poly_set_length(res, poly->length); _fmpq_poly_sub(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, fmpq_numref(c), fmpq_denref(c), 1); _fmpq_poly_normalise(res); _fmpz_vec_neg(res->coeffs, res->coeffs, res->length); } } flint-3.1.3/src/fmpq_poly/sub_series.c000066400000000000000000000135231461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_sub_series_can(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n, int can) { int trunc = 0; slong max, min; fmpz_t d; if (n < len1) { len1 = n; trunc = 1; } if (n < len2) { len2 = n; trunc = 1; } max = FLINT_MAX(len1, len2); min = FLINT_MIN(len1, len2); if (fmpz_equal(den1, den2)) { _fmpz_poly_sub(rpoly, poly1, len1, poly2, len2); if (fmpz_is_one(den1) || !can) fmpz_set(rden, den1); else { fmpz_init(d); _fmpz_vec_content_chained(d, rpoly, max, den1); if (fmpz_is_one(d)) fmpz_set(rden, den1); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d); fmpz_divexact(rden, den1, d); } fmpz_clear(d); } return; } fmpz_init(d); fmpz_one(d); if (!fmpz_is_one(den1) && !fmpz_is_one(den2)) fmpz_gcd(d, den1, den2); if (fmpz_is_one(d)) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den2); _fmpz_vec_scalar_submul_fmpz(rpoly, poly2, min, den1); if (len1 < len2) { _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den1); _fmpz_vec_neg(rpoly + min, rpoly + min, max - min); } fmpz_mul(rden, den1, den2); /* may not be canonical if actual truncation happened */ if (can && trunc) { if (_fmpz_vec_is_zero(rpoly, max)) fmpz_one(rden); else { _fmpz_vec_content_chained(d, rpoly, max, rden); if (!fmpz_is_one(d)) { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d); fmpz_divexact(rden, rden, d); } } } } else { fmpz_t den11; fmpz_t den22; fmpz_init(den11); fmpz_init(den22); fmpz_divexact(den11, den1, d); fmpz_divexact(den22, den2, d); _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den22); _fmpz_vec_scalar_submul_fmpz(rpoly, poly2, len2, den11); if (len1 < len2) { _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den11); _fmpz_vec_neg(rpoly + min, rpoly + min, max - min); } if (_fmpz_vec_is_zero(rpoly, max)) fmpz_one(rden); else { if (can) { fmpz_t e; fmpz_init(e); _fmpz_vec_content(e, rpoly, max); if (fmpz_is_one(e)) fmpz_mul(rden, den1, den22); else { if (trunc) /* there may be extra common factors if truncation occurred */ { fmpz_mul(rden, den1, den22); fmpz_gcd(e, e, rden); if (!fmpz_is_one(e)) { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e); fmpz_divexact(rden, rden, e); } } else { fmpz_gcd(e, e, d); if (fmpz_is_one(e)) fmpz_mul(rden, den1, den22); else { _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e); fmpz_divexact(den11, den1, e); fmpz_mul(rden, den11, den22); } } } fmpz_clear(e); } else fmpz_mul(rden, den1, den22); } fmpz_clear(den11); fmpz_clear(den22); } fmpz_clear(d); } void _fmpq_poly_sub_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2, slong n) { _fmpq_poly_sub_series_can(rpoly, rden, poly1, den1, len1, poly2, den2, len2, n, 1); } void fmpq_poly_sub_series_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n, int can) { slong len1 = poly1->length, len2, max; if (n < 0) n = 0; if (poly1 == poly2 || n == 0) { fmpq_poly_zero(res); return; } len2 = poly2->length; max = FLINT_MAX(len1, len2); max = FLINT_MIN(max, n); fmpq_poly_fit_length(res, max); if (res != poly2) _fmpq_poly_sub_series_can(res->coeffs, res->den, poly1->coeffs, poly1->den, len1, poly2->coeffs, poly2->den, len2, n, can); else { _fmpq_poly_sub_series_can(res->coeffs, res->den, poly2->coeffs, poly2->den, len2, poly1->coeffs, poly1->den, len1, n, can); _fmpz_vec_neg(res->coeffs, res->coeffs, max); } _fmpq_poly_set_length(res, max); _fmpq_poly_normalise(res); } void fmpq_poly_sub_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n) { fmpq_poly_sub_series_can(res, poly1, poly2, n, 1); } flint-3.1.3/src/fmpq_poly/swap.c000066400000000000000000000010761461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_swap(fmpq_poly_t poly1, fmpq_poly_t poly2) { FLINT_SWAP(fmpq_poly_struct, *poly1, *poly2); } flint-3.1.3/src/fmpq_poly/tan_series.c000066400000000000000000000053711461254215100177360ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_tan_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { slong m; fmpz * t, * u, * v; fmpz_t tden, uden, vden; hlen = FLINT_MIN(hlen, n); if (hlen == 1) { fmpz_zero(g); fmpz_one(gden); _fmpz_vec_zero(g + hlen, n - hlen); return; } if (n <= 3) { fmpz_zero(g); if (n >= 2) fmpz_set(g + 1, h + 1); if (hlen == 3) fmpz_set(g + 2, h + 2); else if (n == 3) fmpz_zero(g + 2); fmpz_set(gden, hden); _fmpq_poly_canonicalise(g, gden, n); return; } m = (n + 1) / 2; _fmpq_poly_tan_series(g, gden, h, hden, hlen, m); _fmpz_vec_zero(g + m, n - m); t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); v = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); fmpz_init(vden); _fmpq_poly_mul(u, uden, g, gden, m, g, gden, m); fmpz_set(u, uden); /* u += 1 */ if (2*m - 1 < n) fmpz_zero(u + n - 1); _fmpq_poly_atan_series(t, tden, g, gden, n, n); _fmpq_poly_sub(t, tden, t, tden, n, h, hden, hlen); _fmpq_poly_mullow(v + m, vden, u, uden, n, t + m, tden, n - m, n - m); _fmpq_poly_sub(g, gden, g, gden, m, v, vden, n); _fmpq_poly_canonicalise(g, gden, n); fmpz_clear(tden); fmpz_clear(uden); fmpz_clear(vden); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); _fmpz_vec_clear(v, n); } void fmpq_poly_tan_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_tan_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_tan_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_tan_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/tanh_series.c000066400000000000000000000041021461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void _fmpq_poly_tanh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n) { fmpz * t; fmpz * u; fmpz_t tden; fmpz_t uden; hlen = FLINT_MIN(hlen, n); t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); /* tanh(x) = (exp(2x)-1)/(exp(2x)+1) */ _fmpq_poly_scalar_mul_ui(t, tden, h, hden, hlen, UWORD(2)); _fmpq_poly_exp_series(u, uden, t, tden, hlen, n); _fmpz_vec_set(t, u, n); fmpz_set(tden, uden); fmpz_zero(t); /* t[0] = 0 */ fmpz_mul_ui(u, uden, UWORD(2)); /* u[0] = 2 */ _fmpq_poly_div_series(g, gden, t, tden, n, u, uden, n, n); _fmpq_poly_canonicalise(g, gden, n); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); fmpz_clear(tden); fmpz_clear(uden); } void fmpq_poly_tanh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n) { if (poly->length && !fmpz_is_zero(poly->coeffs)) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_tanh_series). Constant term != 0.\n"); } if (poly->length == 0 || n < 2) { fmpq_poly_zero(res); return; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_tanh_series(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_tanh_series(t->coeffs, t->den, poly->coeffs, poly->den, poly->length, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); } flint-3.1.3/src/fmpq_poly/test/000077500000000000000000000000001461254215100164075ustar00rootroot00000000000000flint-3.1.3/src/fmpq_poly/test/main.c000066400000000000000000000157361461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Try to get fdopen declared for fmpq_poly_[print/read] */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_series.c" #include "t-add_sub_fmpq.c" #include "t-add_sub_fmpz.c" #include "t-add_sub_si.c" #include "t-asinh_series.c" #include "t-asin_series.c" #include "t-atanh_series.c" #include "t-atan_series.c" #include "t-cmp.c" #include "t-compose.c" #include "t-compose_series_brent_kung.c" #include "t-compose_series.c" #include "t-compose_series_horner.c" #include "t-content.c" #include "t-cosh_series.c" #include "t-cos_series.c" #include "t-derivative.c" #include "t-div.c" #include "t-divides.c" #include "t-divrem.c" #include "t-div_series.c" #include "t-equal_trunc.c" #include "t-evaluate_fmpq.c" #include "t-evaluate_fmpz.c" #include "t-exp_expinv_series.c" #include "t-exp_series.c" #include "t-gcd.c" #include "t-gegenbauer_c.c" #include "t-get_nmod_poly.c" #include "t-get_set_coeff_fmpq.c" #include "t-get_set_coeff_fmpz.c" #include "t-get_set_coeff_si.c" #include "t-get_set_coeff_ui.c" #include "t-get_set_str.c" #include "t-get_slice.c" #include "t-init_realloc_clear.c" #include "t-integral.c" #include "t-interpolate_fmpz_vec.c" #include "t-inv.c" #include "t-inv_series_newton.c" #include "t-invsqrt_series.c" #include "t-is_squarefree.c" #include "t-laguerre_l.c" #include "t-lcm.c" #include "t-legendre_p.c" #include "t-log_series.c" #include "t-make_monic.c" #include "t-mul.c" #include "t-mullow.c" #include "t-neg.c" #include "t-nth_derivative.c" #include "t-pow.c" #include "t-power_sums.c" #include "t-pow_trunc.c" #include "t-primitive_part.c" #include "t-print_read.c" #include "t-rem.c" #include "t-remove.c" #include "t-rem_powers_precomp.c" #include "t-rescale.c" #include "t-resultant.c" #include "t-resultant_div.c" #include "t-reverse.c" #include "t-revert_series.c" #include "t-revert_series_lagrange.c" #include "t-revert_series_lagrange_fast.c" #include "t-revert_series_newton.c" #include "t-scalar_div_fmpq.c" #include "t-scalar_div_fmpz.c" #include "t-scalar_div_si.c" #include "t-scalar_div_ui.c" #include "t-scalar_mul_fmpq.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_si.c" #include "t-scalar_mul_ui.c" #include "t-set_equal.c" #include "t-set_trunc.c" #include "t-shift_left_right.c" #include "t-sin_cos_series.c" #include "t-sinh_cosh_series.c" #include "t-sinh_series.c" #include "t-sin_series.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-swap.c" #include "t-tanh_series.c" #include "t-tan_series.c" #include "t-xgcd.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpq_poly_add), TEST_FUNCTION(fmpq_poly_add_series), TEST_FUNCTION(fmpq_poly_add_sub_fmpq), TEST_FUNCTION(fmpq_poly_add_sub_fmpz), TEST_FUNCTION(fmpq_poly_add_sub_si), TEST_FUNCTION(fmpq_poly_asinh_series), TEST_FUNCTION(fmpq_poly_asin_series), TEST_FUNCTION(fmpq_poly_atanh_series), TEST_FUNCTION(fmpq_poly_atan_series), TEST_FUNCTION(fmpq_poly_cmp), TEST_FUNCTION(fmpq_poly_compose), TEST_FUNCTION(fmpq_poly_compose_series_brent_kung), TEST_FUNCTION(fmpq_poly_compose_series), TEST_FUNCTION(fmpq_poly_compose_series_horner), TEST_FUNCTION(fmpq_poly_content), TEST_FUNCTION(fmpq_poly_cosh_series), TEST_FUNCTION(fmpq_poly_cos_series), TEST_FUNCTION(fmpq_poly_derivative), TEST_FUNCTION(fmpq_poly_div), TEST_FUNCTION(fmpq_poly_divides), TEST_FUNCTION(fmpq_poly_divrem), TEST_FUNCTION(fmpq_poly_div_series), TEST_FUNCTION(fmpq_poly_equal_trunc), TEST_FUNCTION(fmpq_poly_evaluate_fmpq), TEST_FUNCTION(fmpq_poly_evaluate_fmpz), TEST_FUNCTION(fmpq_poly_exp_expinv_series), TEST_FUNCTION(fmpq_poly_exp_series), TEST_FUNCTION(fmpq_poly_gcd), TEST_FUNCTION(fmpq_poly_gegenbauer_c), TEST_FUNCTION(fmpq_poly_get_nmod_poly), TEST_FUNCTION(fmpq_poly_get_set_coeff_fmpq), TEST_FUNCTION(fmpq_poly_get_set_coeff_fmpz), TEST_FUNCTION(fmpq_poly_get_set_coeff_si), TEST_FUNCTION(fmpq_poly_get_set_coeff_ui), TEST_FUNCTION(fmpq_poly_get_set_str), TEST_FUNCTION(fmpq_poly_get_slice), TEST_FUNCTION(fmpq_poly_init_realloc_clear), TEST_FUNCTION(fmpq_poly_integral), TEST_FUNCTION(fmpq_poly_interpolate_fmpz_vec), TEST_FUNCTION(fmpq_poly_inv), TEST_FUNCTION(fmpq_poly_inv_series_newton), TEST_FUNCTION(fmpq_poly_invsqrt_series), TEST_FUNCTION(fmpq_poly_is_squarefree), TEST_FUNCTION(fmpq_poly_laguerre_l), TEST_FUNCTION(fmpq_poly_lcm), TEST_FUNCTION(fmpq_poly_legendre_p), TEST_FUNCTION(fmpq_poly_log_series), TEST_FUNCTION(fmpq_poly_make_monic), TEST_FUNCTION(fmpq_poly_mul), TEST_FUNCTION(fmpq_poly_mullow), TEST_FUNCTION(fmpq_poly_neg), TEST_FUNCTION(fmpq_poly_nth_derivative), TEST_FUNCTION(fmpq_poly_pow), TEST_FUNCTION(fmpq_poly_power_sums), TEST_FUNCTION(fmpq_poly_pow_trunc), TEST_FUNCTION(fmpq_poly_primitive_part), TEST_FUNCTION(fmpq_poly_print_read), TEST_FUNCTION(fmpq_poly_rem), TEST_FUNCTION(fmpq_poly_remove), TEST_FUNCTION(fmpq_poly_rem_powers_precomp), TEST_FUNCTION(fmpq_poly_rescale), TEST_FUNCTION(fmpq_poly_resultant), TEST_FUNCTION(fmpq_poly_resultant_div), TEST_FUNCTION(fmpq_poly_reverse), TEST_FUNCTION(fmpq_poly_revert_series), TEST_FUNCTION(fmpq_poly_revert_series_lagrange), TEST_FUNCTION(fmpq_poly_revert_series_lagrange_fast), TEST_FUNCTION(fmpq_poly_revert_series_newton), TEST_FUNCTION(fmpq_poly_scalar_div_fmpq), TEST_FUNCTION(fmpq_poly_scalar_div_fmpz), TEST_FUNCTION(fmpq_poly_scalar_div_si), TEST_FUNCTION(fmpq_poly_scalar_div_ui), TEST_FUNCTION(fmpq_poly_scalar_mul_fmpq), TEST_FUNCTION(fmpq_poly_scalar_mul_fmpz), TEST_FUNCTION(fmpq_poly_scalar_mul_si), TEST_FUNCTION(fmpq_poly_scalar_mul_ui), TEST_FUNCTION(fmpq_poly_set_equal), TEST_FUNCTION(fmpq_poly_set_trunc), TEST_FUNCTION(fmpq_poly_shift_left_right), TEST_FUNCTION(fmpq_poly_sin_cos_series), TEST_FUNCTION(fmpq_poly_sinh_cosh_series), TEST_FUNCTION(fmpq_poly_sinh_series), TEST_FUNCTION(fmpq_poly_sin_series), TEST_FUNCTION(fmpq_poly_sqrt_series), TEST_FUNCTION(fmpq_poly_sub), TEST_FUNCTION(fmpq_poly_sub_series), TEST_FUNCTION(fmpq_poly_swap), TEST_FUNCTION(fmpq_poly_tanh_series), TEST_FUNCTION(fmpq_poly_tan_series), TEST_FUNCTION(fmpq_poly_xgcd), TEST_FUNCTION(fmpq_poly_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpq_poly/test/t-add.c000066400000000000000000000075421461254215100175540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_add, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_add(c, a, b); fmpq_poly_add(a, a, b); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_add(c, a, b); fmpq_poly_add(b, a, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check (a + b) + c = (b + c) + a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, d, e; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_init(e); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_randtest(c, state, n_randint(state, 100), 200); fmpq_poly_add(d, a, b); fmpq_poly_add(d, d, c); fmpq_poly_add(e, b, c); fmpq_poly_add(e, e, a); cflags |= fmpq_poly_is_canonical(d) ? 0 : 1; cflags |= fmpq_poly_is_canonical(e) ? 0 : 2; result = (fmpq_poly_equal(d, e) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fmpq_poly_debug(e), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); fmpq_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-add_series.c000066400000000000000000000077771461254215100211400ustar00rootroot00000000000000/* Copyright (C) 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_add_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 200); fmpq_poly_add_series(c, a, b, n); fmpq_poly_add_series(a, a, b, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 200); fmpq_poly_add_series(c, a, b, n); fmpq_poly_add_series(b, a, b, n); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check truncate(a + b, n) = addseries(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, d, e; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(d); fmpq_poly_init(e); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 200); fmpq_poly_add_series(d, a, b, n); fmpq_poly_add(e, a, b); fmpq_poly_truncate(e, n); cflags |= fmpq_poly_is_canonical(d) ? 0 : 1; cflags |= fmpq_poly_is_canonical(e) ? 0 : 2; result = (fmpq_poly_equal(d, e) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fmpq_poly_debug(e), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-add_sub_fmpq.c000066400000000000000000000045371461254215100214510ustar00rootroot00000000000000/* Copyright (C) 2020 Vincent Delecroix Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_add_sub_fmpq, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, s, t; fmpq_t c; int op, alias; fmpq_poly_init(a); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_init(c); fmpq_poly_randtest(a, state, 1 + n_randint(state, 4), 1 + n_randint(state, 200)); fmpq_poly_randtest(s, state, 4, 200); fmpq_poly_randtest(t, state, 4, 200); fmpq_randtest(c, state, 1 + n_randint(state, 200)); op = n_randint(state, 3); alias = n_randint(state, 3); fmpq_poly_set_fmpq(s, c); if (op == 0) fmpq_poly_add(s, a, s); else if (op == 1) fmpq_poly_sub(s, a, s); else fmpq_poly_sub(s, s, a); if (alias) { if (op == 0) fmpq_poly_add_fmpq(t, a, c); else if (op == 1) fmpq_poly_sub_fmpq(t, a, c); else fmpq_poly_fmpq_sub(t, c, a); } else { fmpq_poly_set(t, a); if (op == 0) fmpq_poly_add_fmpq(t, t, c); else if (op == 1) fmpq_poly_sub_fmpq(t, t, c); else fmpq_poly_fmpq_sub(t, c, t); } if (!fmpq_poly_equal(s, t)) { printf("FAIL (op = %d, alias = %d):\n", op, alias); printf("a = "); fmpq_poly_print(a); printf("\n"); printf("s = "); fmpq_poly_print(s); printf("\n"); printf("t = "); fmpq_poly_print(t); printf("\n"); printf("c = "); fmpq_print(c); printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpq_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-add_sub_fmpz.c000066400000000000000000000045371461254215100214620ustar00rootroot00000000000000/* Copyright (C) 2020 Vincent Delecroix Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_add_sub_fmpz, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, s, t; fmpz_t c; int op, alias; fmpq_poly_init(a); fmpq_poly_init(s); fmpq_poly_init(t); fmpz_init(c); fmpq_poly_randtest(a, state, 1 + n_randint(state, 4), 1 + n_randint(state, 200)); fmpq_poly_randtest(s, state, 4, 200); fmpq_poly_randtest(t, state, 4, 200); fmpz_randtest(c, state, 1 + n_randint(state, 200)); op = n_randint(state, 3); alias = n_randint(state, 3); fmpq_poly_set_fmpz(s, c); if (op == 0) fmpq_poly_add(s, a, s); else if (op == 1) fmpq_poly_sub(s, a, s); else fmpq_poly_sub(s, s, a); if (alias) { if (op == 0) fmpq_poly_add_fmpz(t, a, c); else if (op == 1) fmpq_poly_sub_fmpz(t, a, c); else fmpq_poly_fmpz_sub(t, c, a); } else { fmpq_poly_set(t, a); if (op == 0) fmpq_poly_add_fmpz(t, t, c); else if (op == 1) fmpq_poly_sub_fmpz(t, t, c); else fmpq_poly_fmpz_sub(t, c, t); } if (!fmpq_poly_equal(s, t)) { printf("FAIL (op = %d, alias = %d):\n", op, alias); printf("a = "); fmpq_poly_print(a); printf("\n"); printf("s = "); fmpq_poly_print(s); printf("\n"); printf("t = "); fmpq_poly_print(t); printf("\n"); printf("c = "); fmpz_print(c); printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-add_sub_si.c000066400000000000000000000043751461254215100211210ustar00rootroot00000000000000/* Copyright (C) 2020 Vincent Delecroix Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_add_sub_si, state) { int i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_poly_t a, s, t; slong c; int op, alias; fmpq_poly_init(a); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_randtest(a, state, 1 + n_randint(state, 4), 1 + n_randint(state, 200)); fmpq_poly_randtest(s, state, 4, 200); fmpq_poly_randtest(t, state, 4, 200); c = n_randtest(state); op = n_randint(state, 3); alias = n_randint(state, 3); fmpq_poly_set_si(s, c); if (op == 0) fmpq_poly_add(s, a, s); else if (op == 1) fmpq_poly_sub(s, a, s); else fmpq_poly_sub(s, s, a); if (alias) { if (op == 0) fmpq_poly_add_si(t, a, c); else if (op == 1) fmpq_poly_sub_si(t, a, c); else fmpq_poly_si_sub(t, c, a); } else { fmpq_poly_set(t, a); if (op == 0) fmpq_poly_add_si(t, t, c); else if (op == 1) fmpq_poly_sub_si(t, t, c); else fmpq_poly_si_sub(t, c, t); } if (!fmpq_poly_equal(s, t)) { printf("FAIL (op = %d, alias = %d):\n", op, alias); printf("a = "); fmpq_poly_print(a); printf("\n"); printf("s = "); fmpq_poly_print(s); printf("\n"); printf("t = "); fmpq_poly_print(t); printf("\n"); printf("c = "); flint_printf("%wd", c); printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(s); fmpq_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-asin_series.c000066400000000000000000000061331461254215100213230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_asin_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_asin_series(b, a, n); fmpq_poly_asin_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check asin(A) = atan(A/sqrt(1-A^2)) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t A, B, asinA, atanB; slong n = n_randint(state, 80) + 1; fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(asinA); fmpq_poly_init(atanB); fmpq_poly_randtest_not_zero(A, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); fmpq_poly_mullow(B, A, A, n); fmpq_poly_neg(B, B); fmpq_poly_set_coeff_ui(B, 0, UWORD(1)); fmpq_poly_invsqrt_series(B, B, n); fmpq_poly_mullow(B, A, B, n); fmpq_poly_asin_series(asinA, A, n); fmpq_poly_atan_series(atanB, B, n); cflags |= fmpq_poly_is_canonical(asinA) ? 0 : 1; cflags |= fmpq_poly_is_canonical(atanB) ? 0 : 2; result = (fmpq_poly_equal(asinA, atanB) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), fmpq_poly_debug(A), flint_printf("\n\n"); flint_printf("B = "), fmpq_poly_debug(B), flint_printf("\n\n"); flint_printf("asin(A) = "), fmpq_poly_debug(asinA), flint_printf("\n\n"); flint_printf("atan(B) = "), fmpq_poly_debug(atanB), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(asinA); fmpq_poly_clear(atanB); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-asinh_series.c000066400000000000000000000061251461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_asinh_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_asinh_series(b, a, n); fmpq_poly_asinh_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check asinh(A) = atanh(A/sqrt(1+A^2)) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t A, B, asinhA, atanhB; slong n = n_randint(state, 80) + 1; fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(asinhA); fmpq_poly_init(atanhB); fmpq_poly_randtest_not_zero(A, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); fmpq_poly_mullow(B, A, A, n); fmpq_poly_set_coeff_ui(B, 0, UWORD(1)); fmpq_poly_invsqrt_series(B, B, n); fmpq_poly_mullow(B, A, B, n); fmpq_poly_asinh_series(asinhA, A, n); fmpq_poly_atanh_series(atanhB, B, n); cflags |= fmpq_poly_is_canonical(asinhA) ? 0 : 1; cflags |= fmpq_poly_is_canonical(atanhB) ? 0 : 2; result = (fmpq_poly_equal(asinhA, atanhB) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), fmpq_poly_debug(A), flint_printf("\n\n"); flint_printf("B = "), fmpq_poly_debug(B), flint_printf("\n\n"); flint_printf("asinh(A) = "), fmpq_poly_debug(asinhA), flint_printf("\n\n"); flint_printf("atanh(B) = "), fmpq_poly_debug(atanhB), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(asinhA); fmpq_poly_clear(atanhB); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-atan_series.c000066400000000000000000000064001461254215100213110ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_atan_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_atan_series(b, a, n); fmpq_poly_atan_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check 2*atan(A) = atan(2*A/(1-A^2)) */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpq_poly_t A, B, atanA, atanB; slong n = n_randint(state, 80) + 1; fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(atanA); fmpq_poly_init(atanB); fmpq_poly_randtest_not_zero(A, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); fmpq_poly_randtest_not_zero(B, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(B, 0, UWORD(0)); fmpq_poly_mullow(B, A, A, n); fmpq_poly_neg(B, B); fmpq_poly_set_coeff_ui(B, 0, UWORD(1)); fmpq_poly_div_series(B, A, B, n); fmpq_poly_add(B, B, B); fmpq_poly_atan_series(atanA, A, n); fmpq_poly_atan_series(atanB, B, n); fmpq_poly_add(atanA, atanA, atanA); cflags |= fmpq_poly_is_canonical(atanA) ? 0 : 1; cflags |= fmpq_poly_is_canonical(atanB) ? 0 : 2; result = (fmpq_poly_equal(atanA, atanB) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), fmpq_poly_debug(A), flint_printf("\n\n"); flint_printf("B = "), fmpq_poly_debug(B), flint_printf("\n\n"); flint_printf("2*atan(A) = "), fmpq_poly_debug(atanA), flint_printf("\n\n"); flint_printf("atan(B) = "), fmpq_poly_debug(atanB), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(atanA); fmpq_poly_clear(atanB); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-atanh_series.c000066400000000000000000000063751461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_atanh_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_atanh_series(b, a, n); fmpq_poly_atanh_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check 2*atanh(A) = atanh(2*A/(1+A^2)) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t A, B, atanhA, atanhB; slong n = n_randint(state, 80) + 1; fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(atanhA); fmpq_poly_init(atanhB); fmpq_poly_randtest_not_zero(A, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); fmpq_poly_randtest_not_zero(B, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(B, 0, UWORD(0)); fmpq_poly_mullow(B, A, A, n); fmpq_poly_set_coeff_ui(B, 0, UWORD(1)); fmpq_poly_div_series(B, A, B, n); fmpq_poly_add(B, B, B); fmpq_poly_atanh_series(atanhA, A, n); fmpq_poly_atanh_series(atanhB, B, n); fmpq_poly_add(atanhA, atanhA, atanhA); cflags |= fmpq_poly_is_canonical(atanhA) ? 0 : 1; cflags |= fmpq_poly_is_canonical(atanhB) ? 0 : 2; result = (fmpq_poly_equal(atanhA, atanhB) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), fmpq_poly_debug(A), flint_printf("\n\n"); flint_printf("B = "), fmpq_poly_debug(B), flint_printf("\n\n"); flint_printf("2*atanh(A) = "), fmpq_poly_debug(atanhA), flint_printf("\n\n"); flint_printf("atanh(B) = "), fmpq_poly_debug(atanhB), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(atanhA); fmpq_poly_clear(atanhB); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-cmp.c000066400000000000000000000054031461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_cmp, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f; fmpq_poly_init(f); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); result = (fmpq_poly_cmp(f, f) == 0); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); } /* Check transitivity, i.e. f <= g <= h implies f <= h, that is NOT (f <= g <= h) OR f <= h */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); fmpq_poly_randtest(g, state, n_randint(state, 100), 200); fmpq_poly_randtest(h, state, n_randint(state, 100), 200); result = !(fmpq_poly_cmp(f, g) <= 0) || !(fmpq_poly_cmp(g, h) <= 0) || (fmpq_poly_cmp(f, h) <= 0); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n"); fmpq_poly_debug(g), flint_printf("\n"); fmpq_poly_debug(h), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Check that <, ==, or > */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); fmpq_poly_randtest(g, state, n_randint(state, 100), 200); result = (fmpq_poly_cmp(f, g) < 0) || (fmpq_poly_equal(f, g)) || (fmpq_poly_cmp(f, g) > 0); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n"); fmpq_poly_debug(g), flint_printf("\n"); flint_printf("cmp(f,g) = %d\n", fmpq_poly_cmp(f, g)); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-compose.c000066400000000000000000000100241461254215100204560ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_compose, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 50), 100); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_compose(f, g, h); fmpq_poly_compose(g, g, h); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; cflags |= fmpq_poly_is_canonical(g) ? 0 : 2; result = (fmpq_poly_equal(f, g) && !cflags); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 50), 100); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_compose(f, g, h); fmpq_poly_compose(h, g, h); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; cflags |= fmpq_poly_is_canonical(h) ? 0 : 2; result = (fmpq_poly_equal(f, h) && !cflags); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fmpq_poly_debug(h), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Compare with the naive method for g(h(t)) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h, s, t, u; fmpq_t c; slong k; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_init(u); fmpq_init(c); fmpq_poly_randtest(g, state, n_randint(state, 20), 65); fmpq_poly_randtest(h, state, n_randint(state, 20), 65); fmpq_poly_zero(s); fmpq_poly_set_ui(t, UWORD(1)); for (k = WORD(0); k < g->length; k++) { fmpq_poly_get_coeff_fmpq(c, g, k); fmpq_poly_scalar_mul_fmpq(u, t, c); fmpq_poly_add(s, s, u); fmpq_poly_mul(t, t, h); } fmpq_poly_compose(f, g, h); result = (fmpq_poly_equal(f, s)); if (!result) { flint_printf("FAIL (compare with naive):\n"); flint_printf("g = "), fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("h = "), fmpq_poly_debug(h), flint_printf("\n\n"); flint_printf("f = "), fmpq_poly_debug(f), flint_printf("\n\n"); flint_printf("s = "), fmpq_poly_debug(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpq_poly_clear(u); fmpq_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-compose_series.c000066400000000000000000000072401461254215100220360ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_compose_series, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose_series(f, g, h, n); fmpq_poly_compose_series(g, g, h, n); result = (fmpq_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose_series(f, g, h, n); fmpq_poly_compose_series(h, g, h, n); result = (fmpq_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Compare with compose */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h, s, t; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose(s, g, h); fmpq_poly_truncate(s, n); fmpq_poly_compose_series(f, g, h, n); result = (fmpq_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("n = %wd\n", n); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpq_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpq_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(s); fmpq_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-compose_series_brent_kung.c000066400000000000000000000073421461254215100242570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_compose_series_brent_kung, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose_series_brent_kung(f, g, h, n); fmpq_poly_compose_series_brent_kung(g, g, h, n); result = (fmpq_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose_series_brent_kung(f, g, h, n); fmpq_poly_compose_series_brent_kung(h, g, h, n); result = (fmpq_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Compare with compose */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h, s, t; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose(s, g, h); fmpq_poly_truncate(s, n); fmpq_poly_compose_series_brent_kung(f, g, h, n); result = (fmpq_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("n = %wd\n", n); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpq_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpq_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(s); fmpq_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-compose_series_horner.c000066400000000000000000000073121461254215100234130ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_compose_series_horner, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose_series_horner(f, g, h, n); fmpq_poly_compose_series_horner(g, g, h, n); result = (fmpq_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose_series_horner(f, g, h, n); fmpq_poly_compose_series_horner(h, g, h, n); result = (fmpq_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Compare with compose */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h, s, t; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_randtest(g, state, n_randint(state, 40), 80); fmpq_poly_randtest(h, state, n_randint(state, 20), 50); fmpq_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpq_poly_compose(s, g, h); fmpq_poly_truncate(s, n); fmpq_poly_compose_series_horner(f, g, h, n); result = (fmpq_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("n = %wd\n", n); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpq_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpq_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(s); fmpq_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-content.c000066400000000000000000000032751461254215100204750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_content, state) { int i, result; /* Check that content(a f) = abs(a) content(f) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_t a, b, c; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_init(a); fmpq_init(b); fmpq_init(c); fmpq_poly_randtest_not_zero(f, state, n_randint(state, 100) + 1, 100); fmpq_randtest_not_zero(a, state, 100); fmpq_poly_scalar_mul_fmpq(g, f, a); fmpq_poly_content(b, g); fmpq_poly_content(c, f); fmpq_mul(c, a, c); fmpq_abs(c, c); result = (fmpq_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fmpq_print(a), flint_printf("\n\n"); fmpq_print(b), flint_printf("\n\n"); fmpq_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-cos_series.c000066400000000000000000000061151461254215100211550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_cos_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_cos_series(b, a, n); fmpq_poly_cos_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check 1-cos(A)^2 = sin(A)^2 */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t A, cosA, sinA, B, C, one; slong n = n_randint(state, 80) + 1; fmpq_poly_init(A); fmpq_poly_init(cosA); fmpq_poly_init(sinA); fmpq_poly_init(B); fmpq_poly_init(C); fmpq_poly_init(one); fmpq_poly_randtest_not_zero(A, state, n_randint(state, 60) + 1, 80); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); fmpq_poly_cos_series(cosA, A, n); fmpq_poly_sin_series(sinA, A, n); fmpq_poly_mullow(B, cosA, cosA, n); fmpq_poly_set_coeff_ui(one, 0, UWORD(1)); fmpq_poly_sub(B, one, B); fmpq_poly_mullow(C, sinA, sinA, n); cflags |= fmpq_poly_is_canonical(cosA) ? 0 : 1; cflags |= fmpq_poly_is_canonical(sinA) ? 0 : 2; result = (fmpq_poly_equal(B, C) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), fmpq_poly_debug(A), flint_printf("\n\n"); flint_printf("cos(A) = "), fmpq_poly_debug(cosA), flint_printf("\n\n"); flint_printf("sin(A) = "), fmpq_poly_debug(sinA), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(cosA); fmpq_poly_clear(sinA); fmpq_poly_clear(B); fmpq_poly_clear(C); fmpq_poly_clear(one); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-cosh_series.c000066400000000000000000000061461461254215100213310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_cosh_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_cosh_series(b, a, n); fmpq_poly_cosh_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check cosh(A)^2-1 = sinh(A)^2 */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t A, coshA, sinhA, B, C, one; slong n = n_randint(state, 80) + 1; fmpq_poly_init(A); fmpq_poly_init(coshA); fmpq_poly_init(sinhA); fmpq_poly_init(B); fmpq_poly_init(C); fmpq_poly_init(one); fmpq_poly_randtest_not_zero(A, state, n_randint(state, 60) + 1, 80); fmpq_poly_set_coeff_ui(A, 0, UWORD(0)); fmpq_poly_cosh_series(coshA, A, n); fmpq_poly_sinh_series(sinhA, A, n); fmpq_poly_mullow(B, coshA, coshA, n); fmpq_poly_set_coeff_ui(one, 0, UWORD(1)); fmpq_poly_sub(B, B, one); fmpq_poly_mullow(C, sinhA, sinhA, n); cflags |= fmpq_poly_is_canonical(coshA) ? 0 : 1; cflags |= fmpq_poly_is_canonical(sinhA) ? 0 : 2; result = (fmpq_poly_equal(B, C) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), fmpq_poly_debug(A), flint_printf("\n\n"); flint_printf("cosh(A) = "), fmpq_poly_debug(coshA), flint_printf("\n\n"); flint_printf("sinh(A) = "), fmpq_poly_debug(sinhA), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(coshA); fmpq_poly_clear(sinhA); fmpq_poly_clear(B); fmpq_poly_clear(C); fmpq_poly_clear(one); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-derivative.c000066400000000000000000000066671461254215100211750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_derivative, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_derivative(b, a); fmpq_poly_derivative(a, a); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check constants have derivative zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 2), 200); fmpq_poly_derivative(b, a); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; result = fmpq_poly_is_zero(b) && !cflags; if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check (f g)' = f' g + f g' */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, d, lhs, rhs; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_mul(lhs, a, b); fmpq_poly_derivative(lhs, lhs); fmpq_poly_derivative(c, a); fmpq_poly_derivative(d, b); fmpq_poly_mul(c, c, b); fmpq_poly_mul(d, a, d); fmpq_poly_add(rhs, c, d); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = fmpq_poly_equal(lhs, rhs) && !cflags; if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-div.c000066400000000000000000000100401461254215100175710ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_div, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of q and a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_div(q, a, b); fmpq_poly_div(a, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(a) ? 0 : 2; result = (fmpq_poly_equal(q, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); } /* Check aliasing of q and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_div(q, a, b); fmpq_poly_div(b, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(q, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); } /* Compare with divrem */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q, q2, r; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_init(q2); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_divrem(q, r, a, b); fmpq_poly_div(q2, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(q2) ? 0 : 2; result = (fmpq_poly_equal(q, q2) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("q2 = "), fmpq_poly_debug(q2), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(q2); fmpq_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-div_series.c000066400000000000000000000104601461254215100211510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_div_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing q and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_randtest(a, state, n_randint(state, 50) + 1, 80); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 80); fmpq_poly_set_coeff_ui(b, 0, 1); fmpq_poly_div_series(q, a, b, n); fmpq_poly_div_series(a, a, b, n); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(a) ? 0 : 2; result = (fmpq_poly_equal(q, a)) && !cflags; if (!result) { flint_printf("FAIL (alias q and a):\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); } /* Check aliasing q and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_randtest(a, state, n_randint(state, 50) + 1, 80); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 80); fmpq_poly_set_coeff_ui(b, 0, 1); fmpq_poly_div_series(q, a, b, n); fmpq_poly_div_series(b, a, b, n); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(q, b)) && !cflags; if (!result) { flint_printf("FAIL (alias q and b):\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); } /* Check that Q * B == A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, p, q; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(p); fmpq_poly_init(q); fmpq_poly_randtest(a, state, n_randint(state, 50) + 1, 80); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 80); fmpq_poly_set_coeff_ui(b, 0, 1); fmpq_poly_div_series(q, a, b, n); fmpq_poly_mullow(p, q, b, n); fmpq_poly_truncate(a, n); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(p) ? 0 : 2; cflags |= fmpq_poly_is_canonical(a) ? 0 : 4; result = (fmpq_poly_equal(p, a)) && !cflags; if (!result) { flint_printf("FAIL (check Q * B = A):\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("p = "), fmpq_poly_debug(p), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(p); fmpq_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-divides.c000066400000000000000000000106341461254215100204470ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_divides, state) { int i, result, d1, d2; ulong cflags = UWORD(0); /* Check aliasing of q and a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); if (n_randint(state, 2)) fmpq_poly_mul(a, a, b); d1 = fmpq_poly_divides(q, a, b); d2 = fmpq_poly_divides(a, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(a) ? 0 : 2; result = (d1 == d2 && (d1 == 0 || fmpq_poly_equal(q, a)) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu, d1 = %d, d2 = %d\n\n", cflags, d1, d2); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); } /* Check aliasing of q and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); if (n_randint(state, 2)) fmpq_poly_mul(a, a, b); d1 = fmpq_poly_divides(q, a, b); d2 = fmpq_poly_divides(b, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (d1 == d2 && (d1 == 0 || fmpq_poly_equal(q, b)) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu, d1 = %d, d2 = %d\n\n", cflags, d1, d2); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); } /* Compare with divrem */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q, q2, r; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_init(q2); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); if (n_randint(state, 2)) fmpq_poly_mul(a, a, b); fmpq_poly_divrem(q, r, a, b); d1 = fmpq_poly_divides(q2, a, b); d2 = fmpq_poly_is_zero(r); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(q2) ? 0 : 2; result = (d1 == d2 && (d1 == 0 || fmpq_poly_equal(q, q2)) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("q2 = "), fmpq_poly_debug(q2), flint_printf("\n\n"); flint_printf("cflags = %wu, d1 = %d, d2 = %d\n\n", cflags, d1, d2); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(q2); fmpq_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-divrem.c000066400000000000000000000115701461254215100203060ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_divrem, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of {q,r} and {a,b} */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t A, B; fmpq_poly_t a, b, q, r; fmpq_poly_init(A); fmpq_poly_init(B); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_init(r); fmpq_poly_randtest(A, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(B, state, n_randint(state, 50) + 1, 200); fmpq_poly_set(a, A); fmpq_poly_set(b, B); fmpq_poly_divrem(q, r, a, b); fmpq_poly_divrem(a, b, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(a) ? 0 : 2; result = (fmpq_poly_equal(q, a)) && (fmpq_poly_equal(r, b)) && !cflags; if (!result) { flint_printf("FAIL (aliasing {q,r} and {a,b}):\n\n"); flint_printf("A = "), fmpq_poly_debug(A), flint_printf("\n\n"); flint_printf("B = "), fmpq_poly_debug(B), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(r); } /* Check aliasing of {q,r} and {b,a} */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q, r; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_divrem(q, r, a, b); fmpq_poly_divrem(b, a, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(q, b)) && (fmpq_poly_equal(r, a)) && !cflags; if (!result) { flint_printf("FAIL (aliasing of {q,r} and {b,a}):\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(r); } /* check a = q b + r */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q, r, rhs; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_init(r); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_divrem(q, r, a, b); fmpq_poly_mul(rhs, q, b); fmpq_poly_add(rhs, rhs, r); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = fmpq_poly_equal(a, rhs) && !cflags; if (!result) { flint_printf("FAIL (a == q b + r):\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("q b + r = "), fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(r); fmpq_poly_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-equal_trunc.c000066400000000000000000000062141461254215100213410ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_equal_trunc, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_t c; slong n, j; fmpq_init(c); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); for (j = 0; j < n; j++) { fmpq_poly_get_coeff_fmpq(c, a, j); fmpq_poly_set_coeff_fmpq(b, j, c); } result = (fmpq_poly_equal_trunc(a, b, n)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", a->alloc, a->length); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", b->alloc, b->length); flint_printf("equal(a, b) = %d\n", result); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpq_clear(c); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* unequal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_t c; slong n, m, j; fmpq_init(c); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100) + 1; for (j = 0; j < n; j++) { fmpq_poly_get_coeff_fmpq(c, a, j); fmpq_poly_set_coeff_fmpq(b, j, c); } m = n_randint(state, n); fmpq_poly_get_coeff_fmpq(c, a, m); fmpq_add_si(c, c, 1); fmpq_poly_set_coeff_fmpq(b, m, c); result = (!fmpq_poly_equal_trunc(a, b, n)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", a->alloc, a->length); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", b->alloc, b->length); flint_printf("equal(a, b) = %d\n", result); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } fmpq_clear(c); fmpq_poly_clear(a); fmpq_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-evaluate_fmpq.c000066400000000000000000000102121461254215100216410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_evaluate_fmpq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y; fmpq_poly_t f; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_poly_init(f); fmpq_poly_randtest(f, state, n_randint(state, 80), 100); fmpz_randtest(a, state, 80); fmpz_randtest_not_zero(b, state, 80); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), a); fmpq_canonicalise(x); fmpq_poly_evaluate_fmpq(y, f, x); fmpq_poly_evaluate_fmpq(x, f, x); result = (fmpq_equal(x, y)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_poly_clear(f); } /* Check that (f+g)(a) = f(a) + g(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpq_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 80), 100); fmpq_poly_randtest(g, state, n_randint(state, 80), 100); fmpz_randtest(a, state, 80); fmpz_randtest_not_zero(b, state, 80); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), a); fmpq_canonicalise(x); fmpq_poly_evaluate_fmpq(y, f, x); fmpq_poly_evaluate_fmpq(z, g, x); fmpq_add(y, y, z); fmpq_poly_add(f, f, g); fmpq_poly_evaluate_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpq_poly_clear(f); fmpq_poly_clear(g); } /* Check that (f*g)(a) = f(a) * g(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpq_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 50), 80); fmpq_poly_randtest(g, state, n_randint(state, 50), 80); fmpz_randtest(a, state, 80); fmpz_randtest_not_zero(b, state, 80); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), a); fmpq_canonicalise(x); fmpq_poly_evaluate_fmpq(y, f, x); fmpq_poly_evaluate_fmpq(z, g, x); fmpq_mul(y, y, z); fmpq_poly_mul(f, f, g); fmpq_poly_evaluate_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpq_poly_clear(f); fmpq_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-evaluate_fmpz.c000066400000000000000000000057161461254215100216670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_evaluate_fmpz, state) { int i, result; /* Check that (f+g)(a) = f(a) + g(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a; fmpq_poly_t f, g, h; fmpq_t x, y; fmpq_init(x); fmpq_init(y); fmpz_init(a); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); fmpq_poly_randtest(g, state, n_randint(state, 100), 200); fmpz_randtest(a, state, n_randint(state, 100)); fmpq_poly_evaluate_fmpz(x, f, a); fmpq_poly_evaluate_fmpz(y, g, a); fmpq_add(x, x, y); fmpq_poly_add(h, f, g); fmpq_poly_evaluate_fmpz(y, h, a); result = (fmpq_equal(x, y)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpq_poly_debug(f), flint_printf("\n"); flint_printf("g = "), fmpq_poly_debug(g), flint_printf("\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("f(a) + g(a) = "), fmpq_print(x), flint_printf("\n\n"); flint_printf("(f + g)(a) = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(a); fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } /* Check that (f*g)(a) = f(a) * g(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a; fmpq_poly_t f, g; fmpq_t x, y; fmpq_init(x); fmpq_init(y); fmpz_init(a); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); fmpq_poly_randtest(g, state, n_randint(state, 100), 200); fmpz_randtest(a, state, n_randint(state, 100)); fmpq_poly_evaluate_fmpz(x, f, a); fmpq_poly_evaluate_fmpz(y, g, a); fmpq_mul(x, x, y); fmpq_poly_mul(f, f, g); fmpq_poly_evaluate_fmpz(y, f, a); result = (fmpq_equal(x, y)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(a); fmpq_poly_clear(f); fmpq_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-exp_expinv_series.c000066400000000000000000000035501461254215100225560ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_exp_expinv_series, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, d; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 10); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); if (n_randint(state, 2)) { fmpq_poly_set(c, a); fmpq_poly_exp_expinv_series(b, c, c, n); } else if (n_randint(state, 2)) { fmpq_poly_set(b, a); fmpq_poly_exp_expinv_series(b, c, b, n); } else { fmpq_poly_exp_expinv_series(b, c, a, n); } fmpq_poly_mullow(d, b, c, n); if (!fmpq_poly_is_one(d) || !fmpq_poly_is_canonical(b) || !fmpq_poly_is_canonical(c)) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-exp_series.c000066400000000000000000000121661461254215100211700ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_exp_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_exp_series(b, a, n); fmpq_poly_exp_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check exp(a+b) = exp(a) * exp(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, ab, expa, expb, expab, expa_expb; slong n = n_randint(state, 20) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(ab); fmpq_poly_init(expa); fmpq_poly_init(expb); fmpq_poly_init(expab); fmpq_poly_init(expa_expb); fmpq_poly_randtest(a, state, n_randint(state, 20) + 1, 1 + n_randint(state, 80)); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_randtest(b, state, n_randint(state, 20) + 1, 1 + n_randint(state, 80)); fmpq_poly_set_coeff_ui(b, 0, UWORD(0)); fmpq_poly_add(ab, a, b); fmpq_poly_exp_series(expab, ab, n); fmpq_poly_exp_series(expa, a, n); fmpq_poly_exp_series(expb, b, n); fmpq_poly_mullow(expa_expb, expa, expb, n); cflags |= fmpq_poly_is_canonical(expa) ? 0 : 1; cflags |= fmpq_poly_is_canonical(expb) ? 0 : 2; cflags |= fmpq_poly_is_canonical(expab) ? 0 : 4; result = (fmpq_poly_equal(expab, expa_expb) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("exp(a) = "), fmpq_poly_debug(expa), flint_printf("\n\n"); flint_printf("exp(b) = "), fmpq_poly_debug(expb), flint_printf("\n\n"); flint_printf("exp(ab) = "), fmpq_poly_debug(expab), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(ab); fmpq_poly_clear(expa); fmpq_poly_clear(expb); fmpq_poly_clear(expab); fmpq_poly_clear(expa_expb); } /* Compare with nmod_poly_exp */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, expa; nmod_poly_t pa, pexpa, pexpa2; ulong p; slong n = n_randint(state, 200) + 1; fmpq_poly_init(a); fmpq_poly_init(expa); p = n_nextprime((UWORD(1) << (FLINT_BITS - 1)) + 1000, 0); nmod_poly_init(pa, p); nmod_poly_init(pexpa, p); nmod_poly_init(pexpa2, p); fmpq_poly_randtest(a, state, n_randint(state, 200) + 1, 1 + n_randint(state, 200)); fmpz_randtest_not_zero(fmpq_poly_denref(a), state, 1 + n_randint(state, 200)); fmpq_poly_canonicalise(a); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_get_nmod_poly(pa, a); nmod_poly_exp_series(pexpa, pa, n); if (n_randint(state, 2)) { fmpq_poly_exp_series(expa, a, n); } else { fmpq_poly_set(expa, a); fmpq_poly_exp_series(expa, expa, n); } fmpq_poly_get_nmod_poly(pexpa2, expa); if (!fmpq_poly_is_canonical(expa) || !nmod_poly_equal(pexpa, pexpa2)) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("exp(a) = "), fmpq_poly_debug(expa), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(expa); nmod_poly_clear(pa); nmod_poly_clear(pexpa); nmod_poly_clear(pexpa2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-gcd.c000066400000000000000000000167361461254215100175660ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_gcd, state) { int cflags = 0, i, result; /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_gcd(c, a, b); fmpq_poly_gcd(a, a, b); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL (aliasing a, c):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_gcd(c, a, b); fmpq_poly_gcd(b, a, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL (aliasing b, c):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Generic case when a, b are most likely co-prime ***********************/ /* Verify commutativity and that c is monic */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_gcd(c, a, b); fmpq_poly_gcd(a, b, a); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags && (fmpq_poly_is_zero(c) || fmpq_poly_is_monic(c))); if (!result) { flint_printf("FAIL (commutativity #1):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Verify that GCD(a, b) divides a, b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, r1, r2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(r1); fmpq_poly_init(r2); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_gcd(c, a, b); if (!fmpq_poly_is_zero(c)) { fmpq_poly_rem(r1, a, c); fmpq_poly_rem(r2, b, c); } result = fmpq_poly_is_zero(r1) && fmpq_poly_is_zero(r2); if (!result) { flint_printf("FAIL (division #1):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(r1); fmpq_poly_clear(r2); } /* Case when a, b are not co-prime ***************************************/ /* Verify commutativity and that c is monic */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, t; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(t); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_randtest(t, state, n_randint(state, 50), 20); fmpq_poly_mul(a, a, t); fmpq_poly_mul(b, b, t); fmpq_poly_gcd(c, a, b); fmpq_poly_gcd(a, b, a); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags && (fmpq_poly_is_zero(c) || fmpq_poly_is_monic(c))); if (!result) { flint_printf("FAIL (commutativity #2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(t); } /* Verify that GCD(a, b) divides a, b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, r1, r2, t; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(r1); fmpq_poly_init(r2); fmpq_poly_init(t); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_randtest(t, state, n_randint(state, 50), 20); fmpq_poly_mul(a, a, t); fmpq_poly_mul(b, b, t); fmpq_poly_gcd(c, a, b); if (!fmpq_poly_is_zero(c)) { fmpq_poly_rem(r1, a, c); fmpq_poly_rem(r2, b, c); } result = fmpq_poly_is_zero(r1) && fmpq_poly_is_zero(r2); if (!result) { flint_printf("FAIL (division #2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(r1); fmpq_poly_clear(r2); fmpq_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-gegenbauer_c.c000066400000000000000000000051331461254215100214240ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_poly.h" #define NRATS 20 TEST_FUNCTION_START(fmpq_poly_gegenbauer_c, state) { fmpq_poly_t T0, T1, T2, t, tt; fmpq_t a, rat; fmpq *rats; slong n, d; flint_rand_t rand_state; fmpq_poly_init(T0); fmpq_poly_init(T1); fmpq_poly_init(T2); fmpq_poly_init(t); fmpq_poly_init(tt); fmpq_init(a); fmpq_init(rat); rats = _fmpq_vec_init(NRATS); fmpq_set_si(rats, 0, 1); for (d = 1; d < 16; d++) fmpq_set_si(rats + d, 1, d); flint_randinit(rand_state); for (d = 16; d < NRATS; d++) fmpq_randtest_not_zero(rats + d, rand_state, 32); flint_randclear(rand_state); for (d = 0; d < NRATS; d++) { fmpq_set(a, rats + d); fmpq_poly_gegenbauer_c(T0, 0, a); fmpq_poly_gegenbauer_c(T1, 1, a); for (n = 1; n <= 20; n++) { fmpq_poly_gegenbauer_c(T2, n+1, a); fmpq_poly_set(t, T1); /* Verify (n+1)C^a_{n+1} = 2x(n+a) C^a_n - (n+2a-1)C^a_{n-1} */ fmpq_poly_shift_left(t, t, 1); fmpq_set(rat, a); fmpq_add_si(rat, rat, n); fmpq_mul_2exp(rat, rat, 1); fmpq_poly_scalar_mul_fmpq(t, t, rat); fmpq_set(rat, a); fmpq_mul_2exp(rat, rat, 1); fmpq_add_si(rat, rat, n-1); fmpq_poly_scalar_mul_fmpq(tt, T0, rat); fmpq_poly_sub(t, t, tt); fmpq_poly_scalar_mul_si(tt, T2, n+1); if (!fmpq_poly_equal(t, tt)) { flint_printf("\nFAIL: n = %wd, a = ", n); fmpq_print(a); flint_printf("\n"); flint_printf("t: "); fmpq_poly_print_pretty(t, "x"); flint_printf("\n"); flint_printf("tt: "); fmpq_poly_print_pretty(tt, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_swap(T0, T1); fmpq_poly_swap(T1, T2); } } fmpq_poly_clear(T0); fmpq_poly_clear(T1); fmpq_poly_clear(T2); fmpq_poly_clear(t); fmpq_poly_clear(tt); _fmpq_vec_clear(rats, NRATS); fmpq_clear(a); fmpq_clear(rat); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-get_nmod_poly.c000066400000000000000000000045241461254215100216600ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_get_nmod_poly, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t A; nmod_poly_t M, M2; slong length; mp_limb_t mod; length = n_randint(state, 50); mod = n_randtest_prime(state, 0); nmod_poly_init(M, mod); nmod_poly_init(M2, mod); fmpq_poly_init(A); nmod_poly_randtest(M, state, length); fmpq_poly_set_nmod_poly(A, M); fmpq_poly_scalar_mul_ui(A, A, UWORD(2)); nmod_poly_add(M, M, M); fmpq_poly_get_nmod_poly(M2, A); if (!nmod_poly_equal(M, M2)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); nmod_poly_clear(M); nmod_poly_clear(M2); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t A; nmod_poly_t M, M2; slong length; mp_limb_t mod; ulong lead; length = n_randint(state, 50); while (length == WORD(0)) length = n_randint(state, 50); mod = n_randtest_prime(state, 0); nmod_poly_init(M, mod); nmod_poly_init(M2, mod); fmpq_poly_init(A); nmod_poly_randtest(M, state, length); while (nmod_poly_is_zero(M)) nmod_poly_randtest(M, state, length); lead = nmod_poly_get_coeff_ui(M, M->length - 1); fmpq_poly_set_nmod_poly(A, M); nmod_poly_make_monic(M, M); fmpq_poly_scalar_div_ui(A, A, lead); fmpq_poly_get_nmod_poly(M2, A); if (!nmod_poly_equal(M, M2)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(A); nmod_poly_clear(M); nmod_poly_clear(M2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-get_set_coeff_fmpq.c000066400000000000000000000035411461254215100226360ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_get_set_coeff_fmpq, state) { int i, j, result; ulong cflags = UWORD(0); for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a; fmpq_t x, y; slong coeff, len; fmpq_poly_init(a); fmpq_init(x); fmpq_init(y); len = (slong) (n_randint(state, 100) + 1); for (j = 0; j < 50; j++) { fmpq_randtest(x, state, 200); coeff = (slong) n_randint(state, len); fmpq_poly_set_coeff_fmpq(a, coeff, x); fmpq_poly_get_coeff_fmpq(y, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (fmpq_equal(x, y) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("coeff = %wd\n\n", coeff); flint_printf("len = %wd\n\n", len); flint_printf("cflags = %wu\n\n", cflags); flint_printf("x = "), fmpq_print(x), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpq_clear(x); fmpq_clear(y); fmpq_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-get_set_coeff_fmpz.c000066400000000000000000000040541461254215100226470ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_get_set_coeff_fmpz, state) { int i, j, result; ulong cflags = UWORD(0); fmpq_t n1, n2; fmpq_init(n1); fmpq_init(n2); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a; fmpz_t x1, x2; slong coeff, len; fmpq_poly_init(a); fmpz_init(x1); fmpz_init(x2); len = (slong) (n_randint(state, 100) + 1); for (j = 0; j < 100; j++) { fmpz_randtest(x1, state, 200); fmpz_set(fmpq_numref(n1), x1); fmpz_set_si(fmpq_denref(n1), 1); coeff = (slong) n_randint(state, len); fmpq_poly_set_coeff_fmpz(a, coeff, x1); fmpq_poly_get_coeff_fmpq(n2, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (fmpq_equal(n1, n2) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("coeff = %wd\n\n", coeff); flint_printf("len = %wd\n\n", len); flint_printf("cflags = %wu\n\n", cflags); flint_printf("n1 = "); fmpq_print(n1); flint_printf("\n\n"); flint_printf("n2 = "); fmpq_print(n2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(x1); fmpz_clear(x2); fmpq_poly_clear(a); } fmpq_clear(n1); fmpq_clear(n2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-get_set_coeff_si.c000066400000000000000000000036411461254215100223070ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_get_set_coeff_si, state) { int i, j, result; ulong cflags = UWORD(0); slong n; fmpq_t n_fmpq; fmpq_init(n_fmpq); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a; slong coeff, len; fmpq_poly_init(a); len = (slong) n_randint(state, 100) + 1; for (j = 0; j < 1000; j++) { n = z_randtest(state); coeff = n_randint(state, len); fmpq_poly_set_coeff_si(a, coeff, n); fmpq_poly_get_coeff_fmpq(n_fmpq, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (fmpz_cmp_ui(fmpq_denref(n_fmpq), 1) == 0 && fmpz_cmp_si(fmpq_numref(n_fmpq), n) == 0 && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n"); flint_printf("len = %wd\n", len); flint_printf("coeff = %wd\n", coeff); flint_printf("cflags = %wu\n", cflags); flint_printf("n = %wd\n", n); flint_printf("n_fmpq = "); fmpq_print(n_fmpq); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpq_poly_clear(a); } fmpq_clear(n_fmpq); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-get_set_coeff_ui.c000066400000000000000000000036721461254215100223150ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_get_set_coeff_ui, state) { int i, j, result; ulong cflags = UWORD(0); ulong n; fmpq_t n_fmpq; fmpq_init(n_fmpq); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a; slong coeff, len; fmpq_poly_init(a); len = (slong) (n_randint(state, 100) + 1); fmpq_poly_randtest(a, state, len, 100); for (j = 0; j < 1000; j++) { n = n_randtest(state); coeff = n_randint(state, len); fmpq_poly_set_coeff_ui(a, coeff, n); fmpq_poly_get_coeff_fmpq(n_fmpq, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (fmpz_cmp_ui(fmpq_denref(n_fmpq), 1) == 0 && fmpz_cmp_ui(fmpq_numref(n_fmpq), n) == 0 && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n"); flint_printf("len = %wd\n", len); flint_printf("coeff = %wd\n", coeff); flint_printf("cflags = %wu\n", cflags); flint_printf("n = %wu\n", n); flint_printf("n_fmpq = "); fmpq_print(n_fmpq); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpq_poly_clear(a); } fmpq_clear(n_fmpq); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-get_set_str.c000066400000000000000000000047111461254215100213410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2018 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" void check_invalid(char * s) { fmpq_poly_t p; int err; fmpq_poly_init(p); err = fmpq_poly_set_str(p, s); if (!err) { printf("Got no error with s='%s'\n", s); printf("p = "); fmpq_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(p); } TEST_FUNCTION_START(fmpq_poly_get_set_str, state) { int i, result; ulong cflags = UWORD(0); /* badly formatted input */ check_invalid(""); check_invalid("1"); check_invalid("x"); check_invalid("-"); check_invalid("-1"); check_invalid("-1 0"); check_invalid("2 X1 0"); check_invalid("3 X-2 0 1"); check_invalid("2 -1 0 1Y"); check_invalid("2 -1 0 1"); check_invalid("3 -1 0 1 "); check_invalid("3 -1 0 1 "); check_invalid("3 -1 0 1"); check_invalid("3 -1 0 1"); /* wrong length */ check_invalid("0 0"); check_invalid("2 -1 0 1"); check_invalid("4 0 0"); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int ans; char * str; fmpq_poly_t f, g; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); str = fmpq_poly_get_str(f); ans = fmpq_poly_set_str(g, str); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; result = (ans == 0 && fmpq_poly_equal(f, g) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpq_poly_debug(f), flint_printf("\n\n"); flint_printf("g = "), fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("str = %s\n\n", str); flint_printf("ans = %d\n\n", ans); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); flint_free(str); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-get_slice.c000066400000000000000000000074611461254215100207620ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_get_slice, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong j1, j2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_set(b, a); j1 = n_randint(state, 100); j2 = n_randint(state, 100); fmpq_poly_get_slice(c, b, j1, j2); fmpq_poly_get_slice(b, b, j1, j2); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check slice with i >= j is zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong j1, j2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); j2 = n_randint(state, 60); j1 = j2 + n_randint(state, 60); fmpq_poly_get_slice(b, a, j1, j2); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; result = (fmpq_poly_is_zero(b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check transitivity when j1 <= k1 <= k2 <= j2 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, d; slong j1, j2, k1, k2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); j1 = n_randint(state, 20); k1 = j1 + n_randint(state, 20); k2 = k1 + n_randint(state, 20); j2 = k2 + n_randint(state, 20); fmpq_poly_get_slice(b, a, j1, j2); fmpq_poly_get_slice(c, b, k1, k2); fmpq_poly_get_slice(d, a, k1, k2); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; cflags |= fmpq_poly_is_canonical(d) ? 0 : 4; result = (fmpq_poly_equal(c, d) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-init_realloc_clear.c000066400000000000000000000022431461254215100226270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_init_realloc_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a; fmpq_poly_init2(a, n_randint(state, 100)); fmpq_poly_clear(a); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a; fmpq_poly_init2(a, n_randint(state, 100)); fmpq_poly_realloc(a, n_randint(state, 100)); fmpq_poly_clear(a); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a; fmpq_poly_init(a); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-integral.c000066400000000000000000000033271461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_integral, state) { int i, result; ulong cflags = UWORD(0); /* Check inverse of fmpq_poly_derivative */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 1 + n_randint(state, 200)); if (n_randint(state, 2)) { fmpq_poly_integral(b, a); } else /* Check aliasing */ { fmpq_poly_set(b, a); fmpq_poly_integral(b, b); } fmpq_poly_derivative(c, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = fmpq_poly_equal(a, c) && !cflags; if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-interpolate_fmpz_vec.c000066400000000000000000000035271461254215100232420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_interpolate_fmpz_vec, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t P; fmpz *x, *y, *z; fmpq_t q; slong j, n, bits; n = n_randint(state, 50); bits = n_randint(state, 100); x = _fmpz_vec_init(n); y = _fmpz_vec_init(n); z = _fmpz_vec_init(n); fmpq_poly_init(P); for (j = 0; j < n; j++) fmpz_set_si(x + j, -n/2 + j); _fmpz_vec_randtest(y, state, n, bits); fmpq_poly_interpolate_fmpz_vec(P, x, y, n); fmpq_init(q); for (j = 0; j < n; j++) { fmpq_poly_evaluate_fmpz(q, P, x + j); fmpz_set(z + j, fmpq_numref(q)); if (!fmpz_equal(z + j, y + j) || !fmpz_is_one(fmpq_denref(q))) { flint_printf("FAIL:\n"); flint_printf("x:\n"); _fmpz_vec_print(x, n); flint_printf("\n\n"); flint_printf("y:\n"); _fmpz_vec_print(y, n); flint_printf("\n\n"); flint_printf("P:\n"); fmpq_poly_print(P), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpq_clear(q); fmpq_poly_clear(P); _fmpz_vec_clear(x, n); _fmpz_vec_clear(y, n); _fmpz_vec_clear(z, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-inv.c000066400000000000000000000027141461254215100176140ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_inv, state) { int i, result; ulong cflags = UWORD(0); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest_not_zero(a, state, 1, 200); fmpq_poly_inv(b, a); fmpq_poly_inv(c, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-inv_series_newton.c000066400000000000000000000055671461254215100225710ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_inv_series_newton, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpz_randtest_not_zero(a->coeffs, state, 50); fmpq_poly_canonicalise(a); fmpq_poly_inv_series_newton(b, a, n); fmpq_poly_inv_series_newton(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check Q^{-1} * Q is congruent 1 mod t^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, one; slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(one); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 80) + 1, 80); fmpz_randtest_not_zero(a->coeffs, state, 80); fmpq_poly_canonicalise(a); fmpq_poly_one(one); fmpq_poly_inv_series_newton(b, a, n); fmpq_poly_mul(c, a, b); fmpq_poly_truncate(c, n); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(c, one) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("c = "), fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(one); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-invsqrt_series.c000066400000000000000000000053421461254215100221000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_invsqrt_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(1)); fmpq_poly_canonicalise(a); fmpq_poly_invsqrt_series(b, a, n); fmpq_poly_invsqrt_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check 1/((1/sqrt(a))^2) = a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(a, 0, UWORD(1)); fmpq_poly_invsqrt_series(b, a, n); fmpq_poly_mullow(c, b, b, n); fmpq_poly_inv_series(c, c, n); fmpq_poly_truncate(a, n); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; result = (fmpq_poly_equal(c, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("c = "), fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-is_squarefree.c000066400000000000000000000055201461254215100216530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_is_squarefree, state) { int i, result; /* Check that polynomials of degree <= 1 are square-free */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t f; fmpq_poly_init(f); fmpq_poly_randtest(f, state, n_randint(state, 2), 100); result = (fmpq_poly_is_squarefree(f)); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); } /* Check that a^2 f is not square-free */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, f; fmpq_poly_init(a); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1, 40); if (a->length < 2) { fmpq_poly_clear(a); continue; } fmpq_poly_init(f); fmpq_poly_randtest_not_zero(f, state, n_randint(state, 20) + 1, 40); fmpq_poly_mul(a, a, a); fmpq_poly_mul(f, a, f); result = (!fmpq_poly_is_squarefree(f)); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(f); } /* Check that f + N*(x^M + 1) is square-free, for N >> f, M > deg(f) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, f; fmpz_t N; fmpq_poly_init(a); fmpq_poly_set_coeff_si(a, 0, WORD(1)); fmpq_poly_set_coeff_si(a, n_randint(state, 20), WORD(1)); if (a->length < 2) { fmpq_poly_clear(a); continue; } fmpq_poly_init(f); fmpq_poly_randtest(f, state, a->length - 2, 40); fmpz_init_set_ui(N, UWORD(1)); fmpz_mul_2exp(N, N, 45 + a->length); fmpq_poly_scalar_mul_fmpz(a, a, N); fmpq_poly_add(f, a, f); result = fmpq_poly_is_squarefree(f); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(f); fmpz_clear(N); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-laguerre_l.c000066400000000000000000000032271461254215100211410ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_laguerre_l, state) { fmpq_poly_t T0, T1, T2, t, tt; slong n; fmpq_poly_init(T0); fmpq_poly_init(T1); fmpq_poly_init(T2); fmpq_poly_init(t); fmpq_poly_init(tt); fmpq_poly_laguerre_l(T0, 0); fmpq_poly_laguerre_l(T1, 1); for (n = 1; n <= 500; n++) { fmpq_poly_laguerre_l(T2, n+1); fmpq_poly_set(t, T1); /* Verify (n+1)P_{n+1} = (2n+1-x) P_n - nP_{n-1} */ fmpq_poly_shift_left(tt, t, 1); fmpq_poly_scalar_mul_ui(t, t, 2*n+1); fmpq_poly_sub(t, t, tt); fmpq_poly_scalar_mul_ui(tt, T0, n); fmpq_poly_sub(t, t, tt); fmpq_poly_scalar_mul_ui(tt, T2, n+1); if (!fmpq_poly_equal(t, tt)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("t: "); fmpq_poly_print_pretty(t, "x"); flint_printf("\n"); flint_printf("tt: "); fmpq_poly_print_pretty(tt, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_swap(T0, T1); fmpq_poly_swap(T1, T2); } fmpq_poly_clear(T0); fmpq_poly_clear(T1); fmpq_poly_clear(T2); fmpq_poly_clear(t); fmpq_poly_clear(tt); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-lcm.c000066400000000000000000000164221461254215100175740ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_lcm, state) { int cflags = 0, i, result; /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_lcm(c, a, b); fmpq_poly_lcm(a, a, b); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_lcm(c, a, b); fmpq_poly_lcm(b, a, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Generic case when a, b are most likely co-prime ***********************/ /* Verify commutativity and that c is monic */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_lcm(c, a, b); fmpq_poly_lcm(a, b, a); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags && (fmpq_poly_is_zero(c) || fmpq_poly_is_monic(c))); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Verify that LCM(a, b) GCD(a, b) == a b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lcm, gcd; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lcm); fmpq_poly_init(gcd); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_lcm(lcm, a, b); fmpq_poly_gcd(gcd, a, b); fmpq_poly_mul(lcm, lcm, gcd); fmpq_poly_mul(a, a, b); fmpq_poly_make_monic(a, a); result = fmpq_poly_equal(lcm, a); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(lcm), flint_printf("\n\n"); fmpq_poly_debug(gcd), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lcm); fmpq_poly_clear(gcd); } /* Case when a, b are not co-prime ***************************************/ /* Verify commutativity and that c is monic */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, t; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(t); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_randtest(t, state, n_randint(state, 50), 20); fmpq_poly_mul(a, a, t); fmpq_poly_mul(b, b, t); fmpq_poly_lcm(c, a, b); fmpq_poly_lcm(a, b, a); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags && (fmpq_poly_is_zero(c) || fmpq_poly_is_monic(c))); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(t); } /* Verify that LCM(a, b) GCD(a, b) == a b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lcm, gcd, t; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lcm); fmpq_poly_init(gcd); fmpq_poly_init(t); fmpq_poly_randtest(a, state, n_randint(state, 100), 100); fmpq_poly_randtest(b, state, n_randint(state, 100), 100); fmpq_poly_randtest(t, state, n_randint(state, 50), 20); fmpq_poly_mul(a, a, t); fmpq_poly_mul(b, b, t); fmpq_poly_lcm(lcm, a, b); fmpq_poly_gcd(gcd, a, b); fmpq_poly_mul(lcm, lcm, gcd); fmpq_poly_mul(a, a, b); fmpq_poly_make_monic(a, a); result = fmpq_poly_equal(lcm, a); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(lcm), flint_printf("\n\n"); fmpq_poly_debug(gcd), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lcm); fmpq_poly_clear(gcd); fmpq_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-legendre_p.c000066400000000000000000000030361461254215100211220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_legendre_p, state) { fmpq_poly_t Pn, Pn1, Pn2, R; slong n; fmpq_poly_init(Pn); fmpq_poly_init(Pn1); fmpq_poly_init(Pn2); fmpq_poly_init(R); fmpq_poly_set_ui(Pn, UWORD(1)); fmpq_poly_set_coeff_ui(Pn1, 1, UWORD(1)); for (n = 0; n <= 500; n++) { fmpq_poly_legendre_p(R, n); if (!fmpq_poly_equal(Pn, R)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("Direct: "); fmpq_poly_print_pretty(R, "x"); flint_printf("\n"); flint_printf("Recur.: "); fmpq_poly_print_pretty(Pn, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_shift_left(Pn2, Pn1, 1); fmpq_poly_scalar_mul_ui(Pn2, Pn2, 2*n + 3); fmpq_poly_scalar_mul_si(Pn, Pn, -(n+1)); fmpq_poly_add(Pn2, Pn2, Pn); fmpq_poly_scalar_div_ui(Pn2, Pn2, n+2); fmpq_poly_swap(Pn, Pn1); fmpq_poly_swap(Pn1, Pn2); } fmpq_poly_clear(Pn); fmpq_poly_clear(Pn1); fmpq_poly_clear(Pn2); fmpq_poly_clear(R); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-log_series.c000066400000000000000000000067501461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_log_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(1)); fmpq_poly_canonicalise(a); fmpq_poly_log_series(b, a, n); fmpq_poly_log_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check log(a*b) = log(a) + log(b) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, ab, loga, logb, logab, loga_logb; slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(ab); fmpq_poly_init(loga); fmpq_poly_init(logb); fmpq_poly_init(logab); fmpq_poly_init(loga_logb); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(a, 0, UWORD(1)); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(b, 0, UWORD(1)); fmpq_poly_mullow(ab, a, b, n); fmpq_poly_log_series(logab, ab, n); fmpq_poly_log_series(loga, a, n); fmpq_poly_log_series(logb, b, n); fmpq_poly_add(loga_logb, loga, logb); cflags |= fmpq_poly_is_canonical(loga) ? 0 : 1; cflags |= fmpq_poly_is_canonical(logb) ? 0 : 2; cflags |= fmpq_poly_is_canonical(logab) ? 0 : 4; result = (fmpq_poly_equal(logab, loga_logb) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("log(a) = "), fmpq_poly_debug(loga), flint_printf("\n\n"); flint_printf("log(b) = "), fmpq_poly_debug(logb), flint_printf("\n\n"); flint_printf("log(ab) = "), fmpq_poly_debug(logab), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(ab); fmpq_poly_clear(loga); fmpq_poly_clear(logb); fmpq_poly_clear(logab); fmpq_poly_clear(loga_logb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-make_monic.c000066400000000000000000000040761461254215100211250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_make_monic, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); fmpq_poly_make_monic(g, f); fmpq_poly_make_monic(f, f); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; cflags |= fmpq_poly_is_canonical(g) ? 0 : 2; result = (fmpq_poly_equal(f, g) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); } /* Check that the result of "monic" has "is_monic" return 1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f; fmpq_poly_init(f); fmpq_poly_randtest_not_zero(f, state, n_randint(state, 100) + 1, 200); fmpq_poly_make_monic(f, f); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; result = (fmpq_poly_is_monic(f) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-mul.c000066400000000000000000000072451461254215100176210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_mul, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(b, state, n_randint(state, 50), 500); fmpq_poly_randtest(c, state, n_randint(state, 50), 500); fmpq_poly_mul(a, b, c); fmpq_poly_mul(b, b, c); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(b, state, n_randint(state, 50), 500); fmpq_poly_randtest(c, state, n_randint(state, 50), 500); fmpq_poly_mul(a, b, c); fmpq_poly_mul(c, b, c); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a1, a2, b, c, d; fmpq_poly_init(a1); fmpq_poly_init(a2); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_randtest(b, state, n_randint(state, 100), 500); fmpq_poly_randtest(c, state, n_randint(state, 100), 500); fmpq_poly_randtest(d, state, n_randint(state, 100), 500); fmpq_poly_mul(a1, b, c); fmpq_poly_mul(a2, b, d); fmpq_poly_add(a1, a1, a2); fmpq_poly_add(c, c, d); fmpq_poly_mul(a2, b, c); cflags |= fmpq_poly_is_canonical(a1) ? 0 : 1; cflags |= fmpq_poly_is_canonical(a2) ? 0 : 2; result = (fmpq_poly_equal(a1, a2) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a1), flint_printf("\n\n"); fmpq_poly_debug(a2), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a1); fmpq_poly_clear(a2); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-mullow.c000066400000000000000000000031001461254215100203250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_mullow, state) { int i, result; ulong cflags = UWORD(0); /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong trunc; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); trunc = n_randint(state, 50); fmpq_poly_randtest(b, state, trunc, 200); fmpq_poly_randtest(c, state, trunc, 200); fmpq_poly_mullow(a, b, c, trunc); fmpq_poly_mul(b, b, c); fmpq_poly_truncate(b, trunc); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-neg.c000066400000000000000000000027271461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_neg, state) { int i, result; ulong cflags = UWORD(0); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_neg(b, a); fmpq_poly_neg(c, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-nth_derivative.c000066400000000000000000000042101461254215100220240ustar00rootroot00000000000000/* Copyright (C) 2021 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_nth_derivative, state) { ulong nth, cflags = UWORD(0); int i, j, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); nth = n_randint(state, 100); fmpq_poly_nth_derivative(b, a, nth); fmpq_poly_nth_derivative(a, a, nth); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check if derivative is correct */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); nth = n_randint(state, 100); fmpq_poly_nth_derivative(b, a, nth); for (j = 0; j < nth; j ++) { fmpq_poly_derivative(a, a); } result = (fmpq_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_print(a), flint_printf("\n\n"); fmpq_poly_print(b), flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-pow.c000066400000000000000000000054111461254215100176220ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_pow, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; ulong exp; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(b, state, n_randint(state, 10), 100); exp = (ulong) n_randtest(state) % UWORD(20); fmpq_poly_pow(a, b, exp); fmpq_poly_pow(b, b, exp); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Compare with repeated multiplications by the base */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; ulong exp; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(b, state, n_randint(state, 10), 100); exp = (ulong) n_randtest(state) % UWORD(20); fmpq_poly_pow(a, b, exp); if (exp == 0) { fmpq_poly_set_ui(c, 1); } else { ulong j; fmpq_poly_set(c, b); for (j = 1; j < exp; j++) fmpq_poly_mul(c, c, b); } cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("c = "), fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-pow_trunc.c000066400000000000000000000061311461254215100210350ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2019 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_pow_trunc, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; ulong exp; slong len; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(b, state, n_randint(state, 10), 100); exp = (ulong) n_randtest(state) % UWORD(20); len = n_randtest(state) % 20; fmpq_poly_pow_trunc(a, b, exp, len); fmpq_poly_pow_trunc(b, b, exp, len); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu, len = %wd\n", exp, len); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Compare with repeated multiplications by the base */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; ulong exp; slong len; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(b, state, n_randint(state, 10), 100); fmpq_poly_randtest(c, state, n_randint(state, 10), 100); exp = (ulong) n_randtest(state) % UWORD(20); len = n_randtest(state) % 20; fmpq_poly_pow_trunc(a, b, exp, len); if (exp == 0) { fmpq_poly_set_ui(c, 1); } else { ulong j; fmpq_poly_set(c, b); for (j = 1; j < exp; j++) fmpq_poly_mullow(c, c, b, len); } fmpq_poly_truncate(c, len); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu, len = %wd\n", exp, len); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("c = "), fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-power_sums.c000066400000000000000000000142671461254215100212310ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpz_poly.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_power_sums, state) { int i, j, k, l, den, result; fmpz_t il, jl, kl, dl; fmpq_t tot; fmpq_t tmp; fmpq_poly_t a, b, c, d; fmpz_poly_t az, bz; /* Check that it is valid in degree 3 with rational roots, ie */ /* for polynomials of the form (dx-i)(dx-j)(dx-k) */ for (den = 1; den < 6; den++) for (i = -4; i < 4; i++) for (j = i; j < 4; j++) for (k = j; k < 4; k++) { fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_set_coeff_si(a, 0, -i * j * k); fmpq_poly_set_coeff_si(a, 1, den * (i * j + i * k + j * k)); fmpq_poly_set_coeff_si(a, 2, den * den * (-i - j - k)); fmpq_poly_set_coeff_si(a, 3, den * den * den); fmpq_poly_power_sums(b, a, 20); fmpz_init(il); fmpz_init(jl); fmpz_init(kl); fmpz_init(dl); fmpq_init(tot); fmpq_init(tmp); fmpz_one(il); fmpz_one(jl); fmpz_one(kl); fmpz_one(dl); for (l = 0; l < FLINT_MIN(20, fmpq_poly_length(b)); l++) { fmpq_zero(tot); fmpq_add_fmpz(tot, tot, il); fmpq_add_fmpz(tot, tot, jl); fmpq_add_fmpz(tot, tot, kl); fmpq_div_fmpz(tot, tot, dl); fmpq_poly_get_coeff_fmpq(tmp, b, l); result = fmpq_equal(tmp, tot); if (!result) { flint_printf("FAIL: power sums rational root\n"); flint_printf("%d %d %d %d %d\n", i, j, k, den, l); fflush(stdout); flint_abort(); } fmpz_mul_si(il, il, i); fmpz_mul_si(jl, jl, j); fmpz_mul_si(kl, kl, k); fmpz_mul_si(dl, dl, den); } fmpq_poly_power_sums(b, a, 4); fmpq_poly_power_sums_to_poly(c, b); fmpq_poly_make_monic(a, a); result = fmpq_poly_equal(a, c); if (!result) { flint_printf("FAIL: power sums to poly\n"); fmpq_poly_print(a), flint_printf("\n\n"); fmpq_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(il); fmpz_clear(jl); fmpz_clear(kl); fmpq_clear(tot); fmpq_clear(tmp); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check that going back and forth between the power sums representation gives the identity */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_init(az); fmpz_poly_init(bz); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpz_poly_randtest_not_zero(az, state, 1 + n_randint(state, 15), 30); fmpq_poly_set_fmpz_poly(a, az); fmpq_poly_power_sums(b, a, 20); fmpq_poly_power_sums_to_fmpz_poly(bz, b); fmpq_poly_power_sums_to_poly(c, b); fmpq_poly_make_monic(a, a); _fmpz_poly_primitive_part(az->coeffs, az->coeffs, az->length); result = fmpq_poly_equal(a, c) && fmpz_poly_equal(bz, az); if (!result) { flint_printf("FAIL: power sums - power sums to poly\n"); fmpz_poly_print(az), flint_printf("\n\n"); fmpz_poly_print(bz), flint_printf("\n\n"); fmpq_poly_print(a), flint_printf("\n\n"); fmpq_poly_print(b), flint_printf("\n\n"); fmpq_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpz_poly_clear(az); fmpz_poly_clear(bz); } /* Check that the product of polynomials correspond to the sum of Power sums series */ /* (and aliasing of fmpq_poly_power_sums) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_randtest_not_zero(a, state, 1 + n_randint(state, 10), 30); fmpq_poly_randtest_not_zero(b, state, 1 + n_randint(state, 10), 30); fmpq_poly_mul(c, a, b); fmpq_poly_power_sums(c, c, 20); fmpq_poly_power_sums(a, a, 20); fmpq_poly_power_sums(b, b, 20); fmpq_poly_add(d, a, b); result = fmpq_poly_equal(c, d); if (!result) { flint_printf ("FAIL: PowerSums(p1 p2) = PowerSums(p1) + PowerSums(p2)\n"); fmpq_poly_print(a), flint_printf("\n"); fmpq_poly_print(b), flint_printf("\n"); fmpq_poly_print(c), flint_printf("\n"); fmpq_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-primitive_part.c000066400000000000000000000054011461254215100220520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_primitive_part, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_t x; fmpq_init(x); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); fmpq_randtest(x, state, 100); fmpq_poly_scalar_mul_fmpq(f, f, x); fmpq_poly_primitive_part(g, f); fmpq_poly_primitive_part(f, f); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; cflags |= fmpq_poly_is_canonical(g) ? 0 : 2; result = (fmpq_poly_equal(f, g) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_poly_clear(f); fmpq_poly_clear(g); } /* Check that content(f) primitive_part(f) = +- f */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_t x, y; fmpq_init(x); fmpq_init(y); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 200); fmpq_randtest(x, state, 100); fmpq_poly_scalar_mul_fmpq(f, f, x); fmpq_poly_content(y, f); fmpq_poly_primitive_part(g, f); fmpq_poly_scalar_mul_fmpq(g, g, y); if (!fmpq_poly_is_zero(f) && fmpz_sgn(f->coeffs + (f->length - 1)) < 0) fmpq_poly_neg(g, g); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; cflags |= fmpq_poly_is_canonical(g) ? 0 : 2; result = (fmpq_poly_equal(f, g) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_poly_clear(f); fmpq_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-print_read.c000066400000000000000000000152231461254215100211460ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) # include # include # include #endif #include "test_helpers.h" #include "fmpq_poly.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) TEST_FUNCTION_START(fmpq_poly_print_read, state) { int i, j, n = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; fflush(stdout); /* Ensure buffer does not flow into child process */ /* Randomise n polynomials, write to and read from a pipe */ { fmpq_poly_t *a; a = flint_malloc(n * sizeof(fmpq_poly_t)); for (i = 0; i < n; i++) { fmpq_poly_init(a[i]); fmpq_poly_randtest(a[i], state, 100, 100); } if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } for (j = 0; j < n; j++) { r = fmpq_poly_fprint(out, a[j]); if ((j < n - 1) && (r > 0)) r = flint_fprintf(out, "\n"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } } fclose(out); for (i = 0; i < n; ++i) fmpq_poly_clear(a[i]); flint_free(a); exit(0); } else /* Parent process */ { int r; fmpq_poly_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpq_poly_init(t); i = 0; while (!feof(in)) { r = fmpq_poly_fread(in, t); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Read error.\n"); fflush(stdout); flint_abort(); } result = fmpq_poly_equal(t, a[i]); if (!result) { flint_printf("FAIL:\n"); flint_printf("a[i] = "), fmpq_poly_debug(a[i]), flint_printf("\n"); flint_printf("t = "), fmpq_poly_debug(t), flint_printf("\n"); fflush(stdout); flint_abort(); } ++i; } fmpq_poly_clear(t); fclose(in); waitpid(childpid, NULL, 0); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); fflush(stdout); flint_abort(); } for (i = 0; i < n; i++) fmpq_poly_clear(a[i]); flint_free(a); } /* Write bad data to a pipe and read it */ { char str[5] = {'b', 'l', 'a', 'h', '\0'}; if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } fclose(out); exit(0); } else /* Parent process */ { int r; fmpq_poly_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpq_poly_init(t); i = 0; while (!feof(in)) { r = fmpq_poly_fread(in, t); if (r > 0) { flint_printf("FAIL:\n"); flint_printf("r = %d\n", r); fflush(stdout); flint_abort(); } ++i; } fmpq_poly_clear(t); fclose(in); waitpid(childpid, NULL, 0); } /* For {'b','l','a','h','\0'} we expect 5 reads */ if (i != 5) { flint_printf("FAIL:\n"); flint_printf("Carried out %d reads, but \"%s\" has only 4 characters.\n", i, str); fflush(stdout); flint_abort(); } } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(fmpq_poly_print_read, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/fmpq_poly/test/t-rem.c000066400000000000000000000100401461254215100175720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_rem, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of r and a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, r; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_rem(r, a, b); fmpq_poly_rem(a, a, b); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(r) ? 0 : 2; result = (fmpq_poly_equal(r, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(r); } /* Check aliasing of r and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, r; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_rem(r, a, b); fmpq_poly_rem(b, a, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(r) ? 0 : 2; result = (fmpq_poly_equal(r, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(r); } /* Compare with divrem */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q, r, r2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_init(r); fmpq_poly_init(r2); fmpq_poly_randtest(a, state, n_randint(state, 50), 200); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 200); fmpq_poly_divrem(q, r, a, b); fmpq_poly_rem(r2, a, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(r2) ? 0 : 2; result = (fmpq_poly_equal(r, r2) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("r2 = "), fmpq_poly_debug(r2), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(r); fmpq_poly_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-rem_powers_precomp.c000066400000000000000000000103251461254215100227240ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_rem_powers_precomp, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of q and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, r; fmpq_poly_powers_precomp_t binv; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 100); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpq_poly_powers_precompute(binv, b); fmpq_poly_rem_powers_precomp(r, a, b, binv); fmpq_poly_rem_powers_precomp(a, a, b, binv); result = (fmpq_poly_equal(r, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_powers_clear(binv); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(r); } /* Check aliasing of q and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, r; fmpq_poly_powers_precomp_t binv; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 100); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpq_poly_powers_precompute(binv, b); fmpq_poly_rem_powers_precomp(r, a, b, binv); fmpq_poly_rem_powers_precomp(b, a, b, binv); result = (fmpq_poly_equal(r, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_powers_clear(binv); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(r); } /* Compare with divrem */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, q, r2, r; fmpq_poly_powers_precomp_t binv; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(q); fmpq_poly_init(r2); fmpq_poly_init(r); fmpq_poly_randtest(a, state, n_randint(state, 50), 100); fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpq_poly_powers_precompute(binv, b); fmpq_poly_divrem(q, r, a, b); fmpq_poly_rem_powers_precomp(r2, a, b, binv); fmpq_poly_canonicalise(r2); result = (fmpq_poly_equal(r, r2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("r = "), fmpq_poly_debug(r), flint_printf("\n\n"); flint_printf("r2 = "), fmpq_poly_debug(r2), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_powers_clear(binv); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(r2); fmpq_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-remove.c000066400000000000000000000117351461254215100203200ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_remove, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of q and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, p, q; slong e1, e2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(p); fmpq_poly_init(q); e1 = n_randint(state, 5); do { fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); } while (b->length < 2); do { fmpq_poly_randtest(a, state, n_randint(state, 50), 100); fmpq_poly_gcd(q, a, b); } while (!fmpq_poly_is_one(q)); fmpq_poly_pow(p, b, e1); fmpq_poly_mul(p, p, a); e1 = fmpq_poly_remove(q, p, b); e2 = fmpq_poly_remove(p, p, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(p) ? 0 : 2; result = (e1 == e2 && fmpq_poly_equal(q, p) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("p = "), fmpq_poly_debug(p), flint_printf("\n\n"); flint_printf("cflags = %wu, e1 = %wd, e2 = %wd\n\n", cflags, e1, e2); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(p); fmpq_poly_clear(q); } /* Check aliasing of q and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, p, q; slong e1, e2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(p); fmpq_poly_init(q); e1 = n_randint(state, 5); do { fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); } while (b->length < 2); do { fmpq_poly_randtest(a, state, n_randint(state, 50), 100); fmpq_poly_gcd(q, a, b); } while (!fmpq_poly_is_one(q)); fmpq_poly_pow(p, b, e1); fmpq_poly_mul(p, p, a); e1 = fmpq_poly_remove(q, p, b); e2 = fmpq_poly_remove(b, p, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (e1 == e2 && fmpq_poly_equal(q, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("p = "), fmpq_poly_debug(p), flint_printf("\n\n"); flint_printf("cflags = %wu, e1 = %wd, e2 = %wd\n\n", cflags, e1, e2); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(p); fmpq_poly_clear(q); } /* Compare with construction */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, p, q; slong e1, e2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(p); fmpq_poly_init(q); e1 = n_randint(state, 5); do { fmpq_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); } while (b->length < 2); do { fmpq_poly_randtest(a, state, n_randint(state, 50), 100); fmpq_poly_gcd(q, a, b); } while (!fmpq_poly_is_one(q)); fmpq_poly_pow(p, b, e1); fmpq_poly_mul(p, p, a); e2 = fmpq_poly_remove(q, p, b); cflags |= fmpq_poly_is_canonical(q) ? 0 : 1; result = (e1 == e2 && fmpq_poly_equal(q, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("q = "), fmpq_poly_debug(q), flint_printf("\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("p = "), fmpq_poly_debug(p), flint_printf("\n\n"); flint_printf("cflags = %wu, e1 = %wd, e2 = %wd\n\n", cflags, e1, e2); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(p); fmpq_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-rescale.c000066400000000000000000000050331461254215100204330ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_rescale, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_t a; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 100); fmpq_init(a); fmpq_randtest(a, state, 100); fmpq_poly_rescale(g, f, a); fmpq_poly_rescale(f, f, a); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; cflags |= fmpq_poly_is_canonical(g) ? 0 : 2; result = (fmpq_poly_equal(f, g) && !cflags); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(a); } /* Check that rescaling by a and then by 1/a is the identity */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_t a; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, 100), 100); fmpq_init(a); fmpq_randtest_not_zero(a, state, 100); fmpq_poly_rescale(g, f, a); fmpq_inv(a, a); fmpq_poly_rescale(g, g, a); cflags |= fmpq_poly_is_canonical(f) ? 0 : 1; cflags |= fmpq_poly_is_canonical(g) ? 0 : 2; result = (fmpq_poly_equal(f, g) && !cflags); if (!result) { flint_printf("FAIL (composition of a and 1/a):\n"); fmpq_poly_debug(f), flint_printf("\n\n"); fmpq_poly_debug(g), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-resultant.c000066400000000000000000000132571461254215100210450ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Woverlength-strings" #endif TEST_FUNCTION_START(fmpq_poly_resultant, state) { int i, result; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; fmpq_t x, y; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_init(x); fmpq_init(y); fmpq_poly_randtest(f, state, n_randint(state, 60), 60); fmpq_poly_randtest(g, state, n_randint(state, 60), 60); fmpq_poly_resultant(x, f, g); fmpq_poly_resultant(y, g, f); if ((fmpq_poly_degree(f) * fmpq_poly_degree(g)) % 2) fmpq_neg(y, y); result = fmpq_equal(x, y); if (!result) { flint_printf("FAIL (res(f,g) == (-1)^(m * n) res(g, f)):\n"); flint_printf("f = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(x); fmpq_clear(y); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; fmpq_t x, y, z; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpq_poly_randtest(f, state, n_randint(state, 60), 60); fmpq_poly_randtest(g, state, n_randint(state, 60), 60); fmpq_poly_randtest(h, state, n_randint(state, 60), 60); fmpq_poly_resultant(y, f, g); fmpq_poly_resultant(z, h, g); fmpq_mul(y, y, z); fmpq_poly_mul(f, f, h); fmpq_poly_resultant(x, f, g); result = fmpq_equal(x, y); if (!result) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); flint_printf("f = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpq_poly_print(h), flint_printf("\n\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } /* fredrik's test case */ { fmpq_poly_t f, g; fmpq_t x, y; int result; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_init(x); fmpq_init(y); fmpq_poly_set_str(f, "49 16702090503 -23810415210 7561766512 801950253" " 56796743 40735271 -15934 820601 -2712604160 -1577466 0 0 -7967 0" " 0 0 -14491973 0 6566138489 -55769 0 130523361 4071137 15934" " -501921 -59067338 63860755253 23924901 -15934 -262911 -7967" " -4389817 0 185876611072 58470888545 130523361 -63736 -130618965" " -39835 0 7967 0 55769 -7967 103571 111298990 47802 -3808226" " -3800259"); fmpq_poly_set_str(g, "59 -458395/219902324736 151585/4581298432" " 112595/219902324736 -2016245/54975581184 0 35/73300774912 0" " -234880919/219902324736 7/219902324736 -7/1278501888" " -6055/109951162368 7/27487790592 -504623/73300774912" " 53673977/219902324736 0 611667/73300774912 -497/13743895296" " 0 -6265/219902324736 2446675/73300774912 2345/219902324736" " -371/73300774912 -427/6871947648 -3758096377/219902324736" " 20595995/109951162368 -256459/73300774912 0 33690223/73300774912" " -229369/219902324736 93205/219902324736 -7/107374182" " -133/219902324736 -665/13743895296 -146503/219902324736 0" " 7/219902324736 66633/73300774912 -855190385/219902324736" " 229355/219902324736 0 161/219902324736 887299/219902324736" " -427/7582838784 -611667/18325193728 -7/5114007552 833/54975581184" " -7/109951162368 -5402264413/219902324736 7/5114007552 35/9162596864" " 1133545/219902324736 -151319/73300774912 0 7/219902324736" " 7/54975581184 0 -10367/109951162368 7/54975581184 -161/109951162368"); fmpq_poly_resultant(x, f, g); fmpq_poly_resultant(y, g, f); if ((fmpq_poly_degree(f) * fmpq_poly_degree(g)) % 2) fmpq_neg(y, y); result = fmpq_equal(x, y); if (!result) { flint_printf("FAIL (res(f,g) == (-1)^(m * n) res(g, f)):\n"); flint_printf("x = "), fmpq_print(x), flint_printf("\n\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(x); fmpq_clear(y); } TEST_FUNCTION_END(state); } #ifdef __GNUC__ # pragma GCC diagnostic pop #endif flint-3.1.3/src/fmpq_poly/test/t-resultant_div.c000066400000000000000000000106741461254215100217070ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Woverlength-strings" #endif TEST_FUNCTION_START(fmpq_poly_resultant_div, state) { int i, result; for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h, p; fmpq_t x, y, z, zz; fmpz_t den; slong nbits; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(p); fmpq_poly_init(h); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpq_init(zz); fmpz_init(den); fmpq_poly_randtest(f, state, n_randint(state, 50), 100); fmpq_poly_randtest(g, state, n_randint(state, 50), 100); fmpq_poly_randtest(h, state, n_randint(state, 50), 100); fmpz_set(den, fmpq_poly_denref(f)); fmpq_poly_scalar_mul_fmpz(f, f, den); fmpz_set(den, fmpq_poly_denref(g)); fmpq_poly_scalar_mul_fmpz(g, g, den); fmpz_set(den, fmpq_poly_denref(h)); fmpq_poly_scalar_mul_fmpz(h, h, den); fmpq_poly_mul(p, f, g); fmpq_poly_resultant(x, f, h); if (!fmpz_is_one(fmpq_denref(x))) { flint_printf("FAIL resultant not integral\n"); flint_printf("f = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_resultant(y, g, h); if (!fmpz_is_one(fmpq_denref(y))) { flint_printf("FAIL resultant not integral\n"); flint_printf("h = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("z = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_resultant(z, p, h); if (!fmpz_is_one(fmpq_denref(z))) { flint_printf("FAIL resultant not integral\n"); flint_printf("p = "), fmpq_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpq_poly_print(g), flint_printf("\n\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (fmpq_is_zero(z)) { fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(p); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpq_clear(zz); fmpz_clear(den); continue; } nbits = (slong)fmpz_bits(fmpq_numref(y)) + 1; fmpq_poly_resultant_div(z, p, h, fmpq_numref(x), nbits); fmpq_poly_resultant(zz, p, h); result = fmpq_equal(z, y); if (!result) { flint_printf("FAIL (res(p, g)/div == res(p, g)/div:\n"); flint_printf("p = "), fmpq_poly_print_pretty(p, "x"), flint_printf("\n\n"); flint_printf("h = "), fmpq_poly_print_pretty(h, "x"), flint_printf("\n\n"); flint_printf("res(p, h) = "), fmpq_print(zz), flint_printf("\n\n"); flint_printf("res(p, h) = "), fmpq_print(x), flint_printf(" * "), fmpq_print(y), flint_printf("\n\n"); flint_printf("supplied divisor = "), fmpq_print(x), flint_printf("\n\n"); flint_printf("nbits = %wu\n\n", nbits); flint_printf("divisor found = "), fmpq_print(z), flint_printf("\n\n"); flint_printf("correct result = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(p); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpq_clear(zz); fmpz_clear(den); } TEST_FUNCTION_END(state); } #ifdef __GNUC__ # pragma GCC diagnostic pop #endif flint-3.1.3/src/fmpq_poly/test/t-reverse.c000066400000000000000000000046761461254215100205040ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_reverse, state) { int i, result; /* Aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 150); fmpq_poly_reverse(a, b, n); fmpq_poly_reverse(b, b, n); result = (fmpq_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); flint_printf("a = "), fmpq_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Correctness (?) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong j, len, n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 150); len = FLINT_MIN(n, b->length); if (len) { fmpq_poly_fit_length(a, n); for (j = 0; j < len; j++) fmpz_set(a->coeffs + (n - len) + j, b->coeffs + (len - 1 - j)); fmpz_set(a->den, b->den); _fmpq_poly_set_length(a, n); fmpq_poly_canonicalise(a); } fmpq_poly_reverse(b, b, n); result = (fmpq_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); flint_printf("a = "), fmpq_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-revert_series.c000066400000000000000000000053721461254215100217040ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_revert_series, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; slong n; fmpq_poly_init(f); fmpq_poly_init(g); do { fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series(f, g, n); fmpq_poly_revert_series(g, g, n); result = (fmpq_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); } /* Check f(f^(-1)) = id */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); do { if (n_randint(state, 20) == 0) fmpq_poly_randtest(g, state, n_randint(state, 50), 1); else fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series(f, g, n); fmpq_poly_compose_series(h, g, f, n); result = ((n <= 1 && fmpq_poly_is_zero(h)) || (h->length == 2 && fmpz_is_zero(h->coeffs + 0) && fmpz_is_one(h->coeffs + 1))); if (!result) { flint_printf("FAIL (comparison):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fmpq_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-revert_series_lagrange.c000066400000000000000000000054361461254215100235450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_revert_series_lagrange, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; slong n; fmpq_poly_init(f); fmpq_poly_init(g); do { fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series_lagrange(f, g, n); fmpq_poly_revert_series_lagrange(g, g, n); result = (fmpq_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); } /* Check f(f^(-1)) = id */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); do { if (n_randint(state, 20) == 0) fmpq_poly_randtest(g, state, n_randint(state, 50), 1); else fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series_lagrange(f, g, n); fmpq_poly_compose_series(h, g, f, n); result = ((n <= 1 && fmpq_poly_is_zero(h)) || (h->length == 2 && fmpz_is_zero(h->coeffs + 0) && fmpz_is_one(h->coeffs + 1))); if (!result) { flint_printf("FAIL (comparison):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fmpq_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-revert_series_lagrange_fast.c000066400000000000000000000054621461254215100245610ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_revert_series_lagrange_fast, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; slong n; fmpq_poly_init(f); fmpq_poly_init(g); do { fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series_lagrange_fast(f, g, n); fmpq_poly_revert_series_lagrange_fast(g, g, n); result = (fmpq_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); } /* Check f(f^(-1)) = id */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); do { if (n_randint(state, 20) == 0) fmpq_poly_randtest(g, state, n_randint(state, 50), 1); else fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series_lagrange_fast(f, g, n); fmpq_poly_compose_series(h, g, f, n); result = ((n <= 1 && fmpq_poly_is_zero(h)) || (h->length == 2 && fmpz_is_zero(h->coeffs + 0) && fmpz_is_one(h->coeffs + 1))); if (!result) { flint_printf("FAIL (comparison):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fmpq_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-revert_series_newton.c000066400000000000000000000054261461254215100232760ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_revert_series_newton, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g; slong n; fmpq_poly_init(f); fmpq_poly_init(g); do { fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series_newton(f, g, n); fmpq_poly_revert_series_newton(g, g, n); result = (fmpq_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); } /* Check f(f^(-1)) = id */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, h; slong n; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); do { if (n_randint(state, 20) == 0) fmpq_poly_randtest(g, state, n_randint(state, 50), 1); else fmpq_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); } while (fmpq_poly_length(g) < 2 || fmpz_is_zero(g->coeffs + 1)); fmpq_poly_set_coeff_ui(g, 0, 0); n = n_randint(state, 50); fmpq_poly_revert_series_newton(f, g, n); fmpq_poly_compose_series(h, g, f, n); result = ((n <= 1 && fmpq_poly_is_zero(h)) || (h->length == 2 && fmpz_is_zero(h->coeffs + 0) && fmpz_is_one(h->coeffs + 1))); if (!result) { flint_printf("FAIL (comparison):\n"); fmpq_poly_print(f), flint_printf("\n\n"); fmpq_poly_print(g), flint_printf("\n\n"); fmpq_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_div_fmpq.c000066400000000000000000000107771461254215100221620ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_div_fmpq, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_t z; fmpq_init(z); fmpq_randtest_not_zero(z, state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_fmpq(b, a, z); fmpq_poly_scalar_div_fmpq(a, a, z); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL (aliasing):\n\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_print(z), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check that (a / n1) / n2 == a / (n1 * n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, lhs, rhs; fmpq_t z1, z2, z; fmpq_init(z1); fmpq_init(z2); fmpq_init(z); fmpq_randtest_not_zero(z1, state, 100); fmpq_randtest_not_zero(z2, state, 100); fmpq_mul(z, z1, z2); fmpq_poly_init(a); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_fmpq(lhs, a, z1); fmpq_poly_scalar_div_fmpq(lhs, lhs, z2); fmpq_poly_scalar_div_fmpq(rhs, a, z); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL (a / n1 / n2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_print(z1), flint_printf("\n\n"); fmpq_print(z2), flint_printf("\n\n"); fmpq_print(z), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(z1); fmpq_clear(z2); fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } /* Check that (a + b) / n == a/n + b/n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; fmpq_t z; fmpq_init(z); fmpq_randtest_not_zero(z, state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_fmpq(lhs, a, z); fmpq_poly_scalar_div_fmpq(rhs, b, z); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_div_fmpq(lhs, lhs, z); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL ((a + b) / n):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_print(z), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_div_fmpz.c000066400000000000000000000133251461254215100221630ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_div_fmpz, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpz_t n; fmpz_init(n); fmpz_randtest_not_zero(n, state, 200); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_fmpz(b, a, n); fmpq_poly_scalar_div_fmpz(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fmpz_print(n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Compare with fmpq_poly_scalar_mul_si */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpz_t n1; slong n; n = z_randtest_not_zero(state); fmpz_init(n1); fmpz_set_si(n1, n); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_fmpz(b, a, n1); fmpq_poly_scalar_div_si(c, a, n); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL (comparison with _si):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpz_print(n1), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpz_clear(n1); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check that (a / n1) / n2 == a / (n1 * n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, lhs, rhs; fmpz_t n1, n2, n; fmpz_init(n1); fmpz_init(n2); fmpz_init(n); fmpz_randtest_not_zero(n1, state, 100); fmpz_randtest_not_zero(n2, state, 100); fmpz_mul(n, n1, n2); fmpq_poly_init(a); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_fmpz(lhs, a, n1); fmpq_poly_scalar_div_fmpz(lhs, lhs, n2); fmpq_poly_scalar_div_fmpz(rhs, a, n); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL (a / n1 / n2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpz_print(n1), flint_printf("\n\n"); fmpz_print(n2), flint_printf("\n\n"); fmpz_print(n), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpz_clear(n1); fmpz_clear(n2); fmpz_clear(n); fmpq_poly_clear(a); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } /* Check that (a + b) / n == a/n + b/n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; fmpz_t n; fmpz_init(n); fmpz_randtest_not_zero(n, state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_fmpz(lhs, a, n); fmpq_poly_scalar_div_fmpz(rhs, b, n); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_div_fmpz(lhs, lhs, n); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL ((a + b) / n):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpz_print(n), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_div_si.c000066400000000000000000000075551461254215100216320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_div_si, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); n = z_randtest_not_zero(state); fmpq_poly_scalar_div_si(b, a, n); fmpq_poly_scalar_div_si(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Compare with fmpq_poly_scalar_div_ui */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; ulong n; n = n_randtest_not_zero(state); if (n > WORD_MAX) n >>= 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_ui(b, a, n); fmpq_poly_scalar_div_si(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check (a / n1) / n2 == a / (n1 * n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n1, n2; ulong m; while ((n1 = (slong) n_randbits(state, FLINT_BITS / 2)) == 0) ; while ((n2 = (slong) n_randbits(state, FLINT_BITS / 2 - 1)) == 0) ; m = n_randlimb(state); if (m & UWORD(1)) n1 = -n1; if (m & UWORD(2)) n2 = -n2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_si(b, a, n1); fmpq_poly_scalar_div_si(c, b, n2); fmpq_poly_scalar_div_si(b, a, n1 * n2); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("n1 = %wu, n2 = %wu:\n\n", n1, n2); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_div_ui.c000066400000000000000000000054151461254215100216250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_div_ui, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; ulong n = n_randtest_not_zero(state); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_ui(b, a, n); fmpq_poly_scalar_div_ui(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check (a / n1) / n2 = a / (n1 * n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; ulong n1 = n_randbits(state, FLINT_BITS / 2); ulong n2 = n_randbits(state, FLINT_BITS / 2); if (n1 == UWORD(0)) n1 = UWORD(1); if (n2 == UWORD(0)) n2 = UWORD(1); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_ui(b, a, n1); fmpq_poly_scalar_div_ui(c, b, n2); fmpq_poly_scalar_div_ui(b, a, n1 * n2); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf(" n1 = %wu, n2 = %wu:\n\n", n1, n2); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_mul_fmpq.c000066400000000000000000000112511461254215100221610ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_mul_fmpq, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_t z; fmpq_init(z); fmpq_randtest(z, state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_mul_fmpq(b, a, z); fmpq_poly_scalar_mul_fmpq(a, a, z); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n\n"); gmp_printf("z = %Qd\n\n", z); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check that (a * n1) * n2 == a * (n1 * n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, lhs, rhs; fmpq_t z1, z2, z; fmpq_init(z1); fmpq_init(z2); fmpq_init(z); fmpq_randtest(z1, state, 100); fmpq_randtest(z2, state, 100); fmpq_mul(z, z1, z2); fmpq_poly_init(a); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_mul_fmpq(lhs, a, z1); fmpq_poly_scalar_mul_fmpq(lhs, lhs, z2); fmpq_poly_scalar_mul_fmpq(rhs, a, z); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL (a * n1 * n2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("z1 = "), fmpq_print(z1), flint_printf("\n\n"); flint_printf("z2 = "), fmpq_print(z2), flint_printf("\n\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(z1); fmpq_clear(z2); fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } /* Check that (a + b) * n == a*n + b*n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; fmpq_t z; fmpq_init(z); fmpq_randtest(z, state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_scalar_mul_fmpq(lhs, a, z); fmpq_poly_scalar_mul_fmpq(rhs, b, z); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_mul_fmpq(lhs, lhs, z); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL ((a + b) / n):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_mul_fmpz.c000066400000000000000000000076371461254215100222070ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_mul_fmpz, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpz_t n; fmpz_init(n); fmpz_randtest(n, state, 200); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_fmpz(b, a, n); fmpq_poly_scalar_mul_fmpz(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check that n (a + b) == na + nb */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; fmpz_t n; fmpz_init(n); fmpz_randtest(n, state, 200); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_randtest(b, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_fmpz(lhs, a, n); fmpq_poly_scalar_mul_fmpz(rhs, b, n); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_mul_fmpz(lhs, lhs, n); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } /* Compare with fmpq_poly_scalar_mul_si */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpz_t n1; slong n; n = z_randtest(state); fmpz_init(n1); fmpz_set_si(n1, n); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_fmpz(b, a, n1); fmpq_poly_scalar_mul_si(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpz_clear(n1); fmpq_poly_clear(a); fmpq_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_mul_si.c000066400000000000000000000074621461254215100216420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_mul_si, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = z_randtest(state); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_si(b, a, n); fmpq_poly_scalar_mul_si(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Compare with fmpq_poly_scalar_mul_ui */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; ulong n = n_randbits(state, FLINT_BITS - 1); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_ui(b, a, n); fmpq_poly_scalar_mul_si(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check n2 * (n1 a) == (n1*n2) a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n1, n2; ulong m; n1 = (slong) n_randbits(state, FLINT_BITS / 2); n2 = (slong) n_randbits(state, FLINT_BITS / 2 - 1); m = n_randlimb(state); if (m & UWORD(1)) n1 = -n1; if (m & UWORD(2)) n2 = -n2; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_si(b, a, n1); fmpq_poly_scalar_mul_si(c, b, n2); fmpq_poly_scalar_mul_si(b, a, n1 * n2); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu:\n\n", n1, n2); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-scalar_mul_ui.c000066400000000000000000000101201461254215100216250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_scalar_mul_ui, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; ulong n = n_randtest(state); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_ui(b, a, n); fmpq_poly_scalar_mul_ui(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check that (a + b) * n == a * n + b * n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; ulong n = n_randtest(state); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_randtest(b, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_ui(lhs, a, n); fmpq_poly_scalar_mul_ui(rhs, b, n); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_mul_ui(lhs, lhs, n); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("%li\n\n", n); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } /* Check (a * n1) * n2 = a * (n1 * n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; ulong n1 = n_randbits(state, FLINT_BITS / 2); ulong n2 = n_randbits(state, FLINT_BITS / 2); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); fmpq_poly_scalar_mul_ui(b, a, n1); fmpq_poly_scalar_mul_ui(c, b, n2); fmpq_poly_scalar_mul_ui(b, a, n1 * n2); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu:\n\n", n1, n2); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-set_equal.c000066400000000000000000000054471461254215100210100ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_set_equal, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_set(b, a); result = (fmpq_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", a->alloc, a->length); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", b->alloc, b->length); flint_printf("equal(a, b) = %d\n", result); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong coeff = (slong) n_randint(state, 100); fmpq_t x1, x2; fmpz_t x1fmpz; fmpq_init(x1); fmpq_init(x2); fmpz_init(x1fmpz); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_set(b, a); fmpq_poly_get_coeff_fmpq(x2, b, coeff); do { fmpz_randtest(x1fmpz, state, 200); fmpz_set(fmpq_numref(x1), x1fmpz); fmpz_set_si(fmpq_denref(x1), 1); } while (fmpq_equal(x1, x2)); fmpq_poly_set_coeff_fmpq(b, coeff, x1); result = (!fmpq_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", a->alloc, a->length); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("alloc = %wd\nlength = %wd\n\n", b->alloc, b->length); flint_printf("!equal(a, b) = %d\n", result); fflush(stdout); flint_abort(); } fmpq_clear(x1); fmpq_clear(x2); fmpz_clear(x1fmpz); fmpq_poly_clear(a); fmpq_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-set_trunc.c000066400000000000000000000033371461254215100210300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_set_trunc, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 50); fmpq_poly_set_trunc(b, a, n); fmpq_poly_set(c, a); fmpq_poly_truncate(c, n); result = (fmpq_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_print(a), flint_printf("\n\n"); fmpq_poly_print(b), flint_printf("\n\n"); fmpq_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_set_trunc(a, a, n); result = (fmpq_poly_equal(a, c)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpq_poly_print(a), flint_printf("\n\n"); fmpq_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-shift_left_right.c000066400000000000000000000067051461254215100223500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_shift_left_right, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and b for left shift */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong shift = (slong) n_randint(state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_shift_left(b, a, shift); fmpq_poly_shift_left(a, a, shift); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check aliasing of a and b for right shift */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong shift; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 100) + 1, 200); shift = (slong) n_randint(state, a->length); fmpq_poly_shift_right(b, a, shift); fmpq_poly_shift_right(a, a, shift); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check shift left then right does nothing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong shift = (slong) n_randint(state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_shift_left(b, a, shift); fmpq_poly_shift_right(c, b, shift); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(c, a) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-sin_cos_series.c000066400000000000000000000072721461254215100220330ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_sin_cos_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing (sin) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, d; int which; slong n = n_randint(state, 50) + 1; which = n_randint(state, 2); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_randtest(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, 0); if (which) { fmpq_poly_sin_cos_series(c, b, a, n); fmpq_poly_sin_cos_series(d, a, a, n); } else { fmpq_poly_sin_cos_series(b, c, a, n); fmpq_poly_sin_cos_series(a, d, a, n); } cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; cflags |= fmpq_poly_is_canonical(c) ? 0 : 4; cflags |= fmpq_poly_is_canonical(d) ? 0 : 8; result = (fmpq_poly_equal(a, b) && fmpq_poly_equal(c, d) && !cflags); if (!result) { flint_printf("FAIL (aliasing %d):\n", which); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } /* Compare with sin and cos */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, sina1, cosa1, sina2, cosa2; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(sina1); fmpq_poly_init(sina2); fmpq_poly_init(cosa1); fmpq_poly_init(cosa2); fmpq_poly_randtest(a, state, n_randint(state, 60) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, 0); fmpq_poly_sin_cos_series(sina1, cosa1, a, n); fmpq_poly_sin_series(sina2, a, n); fmpq_poly_cos_series(cosa2, a, n); cflags |= fmpq_poly_is_canonical(sina1) ? 0 : 1; cflags |= fmpq_poly_is_canonical(cosa1) ? 0 : 2; result = (fmpq_poly_equal(sina1, sina2) && fmpq_poly_equal(cosa1, cosa2) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("sin(a) = "), fmpq_poly_debug(sina1), flint_printf("\n\n"); flint_printf("cos(a) = "), fmpq_poly_debug(cosa1), flint_printf("\n\n"); flint_printf("sin(a) = "), fmpq_poly_debug(sina2), flint_printf("\n\n"); flint_printf("cos(a) = "), fmpq_poly_debug(cosa2), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sina1); fmpq_poly_clear(sina2); fmpq_poly_clear(cosa1); fmpq_poly_clear(cosa2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-sin_series.c000066400000000000000000000054631461254215100211670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_sin_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_sin_series(b, a, n); fmpq_poly_sin_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check asin(sin(a)) = a */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, sina, asinsina; slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(sina); fmpq_poly_init(asinsina); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 60) + 1, 80); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_sin_series(sina, a, n); fmpq_poly_asin_series(asinsina, sina, n); fmpq_poly_truncate(a, n); cflags |= fmpq_poly_is_canonical(sina) ? 0 : 1; cflags |= fmpq_poly_is_canonical(asinsina) ? 0 : 2; result = (fmpq_poly_equal(asinsina, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("sin(a) = "), fmpq_poly_debug(sina), flint_printf("\n\n"); flint_printf("asin(sin(a)) = "), fmpq_poly_debug(asinsina), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sina); fmpq_poly_clear(asinsina); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-sinh_cosh_series.c000066400000000000000000000073431461254215100223520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_sinh_cosh_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, d; int which; slong n = n_randint(state, 50) + 1; which = n_randint(state, 2); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_randtest(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, 0); if (which) { fmpq_poly_sinh_cosh_series(c, b, a, n); fmpq_poly_sinh_cosh_series(d, a, a, n); } else { fmpq_poly_sinh_cosh_series(b, c, a, n); fmpq_poly_sinh_cosh_series(a, d, a, n); } cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; cflags |= fmpq_poly_is_canonical(c) ? 0 : 4; cflags |= fmpq_poly_is_canonical(d) ? 0 : 8; result = (fmpq_poly_equal(a, b) && fmpq_poly_equal(c, d) && !cflags); if (!result) { flint_printf("FAIL (aliasinhg %d):\n", which); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } /* Compare with sinh and cosh */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, sinha1, cosha1, sinha2, cosha2; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(sinha1); fmpq_poly_init(sinha2); fmpq_poly_init(cosha1); fmpq_poly_init(cosha2); fmpq_poly_randtest(a, state, n_randint(state, 60) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, 0); fmpq_poly_sinh_cosh_series(sinha1, cosha1, a, n); fmpq_poly_sinh_series(sinha2, a, n); fmpq_poly_cosh_series(cosha2, a, n); cflags |= fmpq_poly_is_canonical(sinha1) ? 0 : 1; cflags |= fmpq_poly_is_canonical(cosha1) ? 0 : 2; result = (fmpq_poly_equal(sinha1, sinha2) && fmpq_poly_equal(cosha1, cosha2) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("sinh(a) = "), fmpq_poly_debug(sinha1), flint_printf("\n\n"); flint_printf("cosh(a) = "), fmpq_poly_debug(cosha1), flint_printf("\n\n"); flint_printf("sinh(a) = "), fmpq_poly_debug(sinha2), flint_printf("\n\n"); flint_printf("cosh(a) = "), fmpq_poly_debug(cosha2), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sinha1); fmpq_poly_clear(sinha2); fmpq_poly_clear(cosha1); fmpq_poly_clear(cosha2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-sinh_series.c000066400000000000000000000055221461254215100213330ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_sinh_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_sinh_series(b, a, n); fmpq_poly_sinh_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check asinh(sinh(a)) = a */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, sinha, asinhsinha; slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(sinha); fmpq_poly_init(asinhsinha); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 60) + 1, 80); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_sinh_series(sinha, a, n); fmpq_poly_asinh_series(asinhsinha, sinha, n); fmpq_poly_truncate(a, n); cflags |= fmpq_poly_is_canonical(sinha) ? 0 : 1; cflags |= fmpq_poly_is_canonical(asinhsinha) ? 0 : 2; result = (fmpq_poly_equal(asinhsinha, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("sinh(a) = "), fmpq_poly_debug(sinha), flint_printf("\n\n"); flint_printf("asinh(sinh(a)) = "), fmpq_poly_debug(asinhsinha), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sinha); fmpq_poly_clear(asinhsinha); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-sqrt_series.c000066400000000000000000000052471461254215100213670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_sqrt_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(1)); fmpq_poly_canonicalise(a); fmpq_poly_sqrt_series(b, a, n); fmpq_poly_sqrt_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check sqrt(a)^2 = a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 80) + 1, 80); fmpq_poly_set_coeff_ui(a, 0, UWORD(1)); fmpq_poly_sqrt_series(b, a, n); fmpq_poly_mullow(c, b, b, n); fmpq_poly_truncate(a, n); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; result = (fmpq_poly_equal(c, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("c = "), fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-sub.c000066400000000000000000000072651461254215100176170ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_sub, state) { int i, result; ulong cflags = UWORD(0); /* Check a - b = a + neg(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c, d; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_init(d); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_sub(c, a, b); fmpq_poly_neg(b, b); fmpq_poly_add(d, a, b); cflags |= fmpq_poly_is_canonical(c) ? 0 : 1; cflags |= fmpq_poly_is_canonical(d) ? 0 : 2; result = (fmpq_poly_equal(c, d) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_sub(c, a, b); fmpq_poly_sub(a, a, b); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_sub(c, a, b); fmpq_poly_sub(b, a, b); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-sub_series.c000066400000000000000000000100171461254215100211560ustar00rootroot00000000000000/* Copyright (C) 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_sub_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 200); fmpq_poly_sub_series(c, a, b, n); fmpq_poly_sub_series(a, a, b, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(a, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 200); fmpq_poly_sub_series(c, a, b, n); fmpq_poly_sub_series(b, a, b, n); cflags |= fmpq_poly_is_canonical(b) ? 0 : 1; cflags |= fmpq_poly_is_canonical(c) ? 0 : 2; result = (fmpq_poly_equal(b, c) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } /* Check truncate(a + b, n) = addseries(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, d, e; slong n; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(d); fmpq_poly_init(e); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 200); fmpq_poly_sub_series(d, a, b, n); fmpq_poly_sub(e, a, b); fmpq_poly_truncate(e, n); cflags |= fmpq_poly_is_canonical(d) ? 0 : 1; cflags |= fmpq_poly_is_canonical(e) ? 0 : 2; result = (fmpq_poly_equal(d, e) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fmpq_poly_debug(e), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-swap.c000066400000000000000000000025231461254215100177700ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_swap, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(c); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_set(c, b); fmpq_poly_swap(a, b); result = (fmpq_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-tan_series.c000066400000000000000000000055231461254215100211550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_tan_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_tan_series(b, a, n); fmpq_poly_tan_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check atan(tan(a)) = a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, tana, atantana; /* but what is an atantana? */ slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(tana); fmpq_poly_init(atantana); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 60) + 1, 80); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_tan_series(tana, a, n); fmpq_poly_atan_series(atantana, tana, n); fmpq_poly_truncate(a, n); cflags |= fmpq_poly_is_canonical(tana) ? 0 : 1; cflags |= fmpq_poly_is_canonical(atantana) ? 0 : 2; result = (fmpq_poly_equal(atantana, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("tan(a) = "), fmpq_poly_debug(tana), flint_printf("\n\n"); flint_printf("atan(tan(a)) = "), fmpq_poly_debug(atantana), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(tana); fmpq_poly_clear(atantana); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-tanh_series.c000066400000000000000000000055221461254215100213240ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_tanh_series, state) { int i, result; ulong cflags = UWORD(0); /* Check aliasing of a and c */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; slong n = n_randint(state, 50) + 1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 50) + 1, 50); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_canonicalise(a); fmpq_poly_tanh_series(b, a, n); fmpq_poly_tanh_series(a, a, n); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check atanh(tanh(a)) = a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a, tanha, atanhtanha; slong n = n_randint(state, 80) + 1; fmpq_poly_init(a); fmpq_poly_init(tanha); fmpq_poly_init(atanhtanha); fmpq_poly_randtest_not_zero(a, state, n_randint(state, 60) + 1, 80); fmpq_poly_set_coeff_ui(a, 0, UWORD(0)); fmpq_poly_tanh_series(tanha, a, n); fmpq_poly_atanh_series(atanhtanha, tanha, n); fmpq_poly_truncate(a, n); cflags |= fmpq_poly_is_canonical(tanha) ? 0 : 1; cflags |= fmpq_poly_is_canonical(atanhtanha) ? 0 : 2; result = (fmpq_poly_equal(atanhtanha, a) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("tanh(a) = "), fmpq_poly_debug(tanha), flint_printf("\n\n"); flint_printf("atanh(tanh(a)) = "), fmpq_poly_debug(atanhtanha), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(tanha); fmpq_poly_clear(atanhtanha); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-xgcd.c000066400000000000000000000173671461254215100177570ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_xgcd, state) { int cflags = 0, i, result; /* Generic case, where a and b are coprime *******************************/ /* Verify d == s a + t b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, d, e, f, s, t; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(d); fmpq_poly_init(e); fmpq_poly_init(f); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_randtest(a, state, n_randint(state, 60), 80); fmpq_poly_randtest(b, state, n_randint(state, 60), 80); fmpq_poly_xgcd(d, s, t, a, b); fmpq_poly_mul(e, s, a); fmpq_poly_mul(f, t, b); fmpq_poly_add(e, e, f); cflags |= fmpq_poly_is_canonical(d) ? 0 : 1; cflags |= fmpq_poly_is_canonical(s) ? 0 : 2; cflags |= fmpq_poly_is_canonical(t) ? 0 : 4; result = (fmpq_poly_equal(d, e) && !cflags); if (!result) { flint_printf("FAIL (correctness #1):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fmpq_poly_debug(s), flint_printf("\n\n"); fmpq_poly_debug(t), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(e); fmpq_poly_clear(f); fmpq_poly_clear(s); fmpq_poly_clear(t); } /* Verify consistency with GCD */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, d, s, t; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(d); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_randtest(a, state, n_randint(state, 60), 80); fmpq_poly_randtest(b, state, n_randint(state, 60), 80); fmpq_poly_xgcd(d, s, t, a, b); fmpq_poly_gcd(a, a, b); cflags |= fmpq_poly_is_canonical(d) ? 0 : 1; cflags |= fmpq_poly_is_canonical(s) ? 0 : 2; cflags |= fmpq_poly_is_canonical(t) ? 0 : 4; result = (fmpq_poly_equal(d, a) && !cflags); if (!result) { flint_printf("FAIL (GCD #1):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fmpq_poly_debug(s), flint_printf("\n\n"); fmpq_poly_debug(t), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(s); fmpq_poly_clear(t); } /* Generic case when a, b are most likely co-prime ***********************/ /* Verify d == s a + t b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, d, s, t, z; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(d); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_init(z); fmpq_poly_randtest(a, state, n_randint(state, 60), 80); fmpq_poly_randtest(b, state, n_randint(state, 60), 80); fmpq_poly_randtest(z, state, n_randint(state, 20), 20); fmpq_poly_mul(a, a, z); fmpq_poly_mul(b, b, z); fmpq_poly_xgcd(d, s, t, a, b); fmpq_poly_mul(a, s, a); fmpq_poly_mul(b, t, b); fmpq_poly_add(a, a, b); cflags |= fmpq_poly_is_canonical(d) ? 0 : 1; cflags |= fmpq_poly_is_canonical(s) ? 0 : 2; cflags |= fmpq_poly_is_canonical(t) ? 0 : 4; result = (fmpq_poly_equal(d, a) && !cflags); if (!result) { flint_printf("FAIL (correctness #2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fmpq_poly_debug(s), flint_printf("\n\n"); fmpq_poly_debug(t), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpq_poly_clear(z); } /* Verify consistency with GCD */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, d, s, t, z; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(d); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_init(z); fmpq_poly_randtest(a, state, n_randint(state, 60), 80); fmpq_poly_randtest(b, state, n_randint(state, 60), 80); fmpq_poly_randtest(z, state, n_randint(state, 20), 20); fmpq_poly_mul(a, a, z); fmpq_poly_mul(b, b, z); fmpq_poly_xgcd(d, s, t, a, b); fmpq_poly_gcd(a, a, b); cflags |= fmpq_poly_is_canonical(d) ? 0 : 1; cflags |= fmpq_poly_is_canonical(s) ? 0 : 2; cflags |= fmpq_poly_is_canonical(t) ? 0 : 4; result = (fmpq_poly_equal(d, a) && !cflags); if (!result) { flint_printf("FAIL (GCD #2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); fmpq_poly_debug(d), flint_printf("\n\n"); fmpq_poly_debug(s), flint_printf("\n\n"); fmpq_poly_debug(t), flint_printf("\n\n"); flint_printf("cflags = %d\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpq_poly_clear(z); } /* regression test, see #1014 */ { fmpq_poly_t a, b, d, s, t, z, z1; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(d); fmpq_poly_init(s); fmpq_poly_init(t); fmpq_poly_init(z); fmpq_poly_init(z1); fmpq_poly_one(a); fmpq_poly_one(b); fmpq_poly_shift_left(a, a, 400); fmpq_poly_shift_left(b, b, 400); fmpq_poly_sub_si(a, a, 1); fmpq_poly_add_si(b, b, 1); fmpq_poly_xgcd(d, s, t, a, b); fmpq_poly_mul(z, s, a); fmpq_poly_mul(z1, t, b); fmpq_poly_add(z, z, z1); if (!fmpq_poly_equal(z, d)) { flint_printf("FAIL:\n"); flint_printf("a: "); fmpq_poly_print_pretty(a, "x"), flint_printf("\n\n"); flint_printf("b: "); fmpq_poly_print_pretty(b, "x"), flint_printf("\n\n"); flint_printf("d: "); fmpq_poly_print_pretty(d, "x"), flint_printf("\n\n"); flint_printf("s: "); fmpq_poly_print_pretty(s, "x"), flint_printf("\n\n"); flint_printf("t: "); fmpq_poly_print_pretty(t, "x"), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpq_poly_clear(z); fmpq_poly_clear(z1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/test/t-zero.c000066400000000000000000000025001461254215100177700ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" TEST_FUNCTION_START(fmpq_poly_zero, state) { int i, result; ulong cflags = UWORD(0); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_zero(a); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); fflush(stdout); flint_abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_poly/truncate.c000066400000000000000000000012531461254215100174220ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_truncate(fmpq_poly_t poly, slong n) { if (poly->length > n) { slong i; for (i = n; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); poly->length = n; fmpq_poly_canonicalise(poly); } } flint-3.1.3/src/fmpq_poly/xgcd.c000066400000000000000000000142101461254215100165170ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" void _fmpq_poly_xgcd(fmpz *G, fmpz_t denG, fmpz *S, fmpz_t denS, fmpz *T, fmpz_t denT, const fmpz *A, const fmpz_t denA, slong lenA, const fmpz *B, const fmpz_t denB, slong lenB) { int alloc = 0; fmpz *primA, *primB, *C, *D; fmpz_t cA, cB; slong lenG, lenC, lenD; fmpz_init(cA); fmpz_init(cB); _fmpz_vec_content(cA, A, lenA); _fmpz_vec_content(cB, B, lenB); if (fmpz_is_one(cA)) { if (fmpz_is_one(cB)) { primA = (fmpz *) A; primB = (fmpz *) B; } else { alloc |= 1; primA = (fmpz *) A; primB = _fmpz_vec_init(lenB); _fmpz_vec_scalar_divexact_fmpz(primB, B, lenB, cB); } } else { if (fmpz_is_one(cB)) { alloc |= 2; primA = _fmpz_vec_init(lenA); primB = (fmpz *) B; _fmpz_vec_scalar_divexact_fmpz(primA, A, lenA, cA); } else { alloc |= 3; primA = _fmpz_vec_init(lenA + lenB); primB = primA + lenA; _fmpz_vec_scalar_divexact_fmpz(primA, A, lenA, cA); _fmpz_vec_scalar_divexact_fmpz(primB, B, lenB, cB); } } _fmpz_poly_gcd(G, primA, lenA, primB, lenB); for (lenG = lenB - 1; !G[lenG]; lenG--) ; lenG++; if (lenG > 1) { alloc |= 4; lenC = lenA - lenG + 1; lenD = lenB - lenG + 1; C = _fmpz_vec_init(lenC + lenD); D = C + lenC; _fmpz_poly_divexact(C, primA, lenA, G, lenG); _fmpz_poly_divexact(D, primB, lenB, G, lenG); } else { lenC = lenA; lenD = lenB; C = primA; D = primB; } _fmpz_poly_xgcd(denG, S, T, C, lenC, D, lenD); if (!fmpz_is_one(denA)) _fmpz_vec_scalar_mul_fmpz(S, S, lenD, denA); fmpz_mul(cA, cA, denG); fmpz_mul(denS, cA, G + (lenG - 1)); if (!fmpz_is_one(denB)) _fmpz_vec_scalar_mul_fmpz(T, T, lenC, denB); fmpz_mul(cB, cB, denG); fmpz_mul(denT, cB, G + (lenG - 1)); _fmpz_vec_zero(S + lenD, lenB - lenD); _fmpz_vec_zero(T + lenC, lenA - lenC); _fmpq_poly_canonicalise(S, denS, lenD); _fmpq_poly_canonicalise(T, denT, lenC); fmpz_set(denG, G + (lenG - 1)); if ((alloc & 3) == 1) _fmpz_vec_clear(primB, lenB); else if ((alloc & 3) == 2) _fmpz_vec_clear(primA, lenA); else if ((alloc & 3) == 3) _fmpz_vec_clear(primA, lenA + lenB); if ((alloc & 4)) _fmpz_vec_clear(C, lenC + lenD); fmpz_clear(cA); fmpz_clear(cB); } void fmpq_poly_xgcd(fmpq_poly_t G, fmpq_poly_t S, fmpq_poly_t T, const fmpq_poly_t A, const fmpq_poly_t B) { if (G == S || G == T || S == T) { flint_throw(FLINT_ERROR, "Exception (fmpq_poly_xgcd). Output arguments aliased.\n"); } if (A->length < B->length) { fmpq_poly_xgcd(G, T, S, B, A); } else { slong lenA = A->length, lenB = B->length, lenG = lenB; if (lenA == 0) /* lenA = lenB = 0 */ { fmpq_poly_zero(G); fmpq_poly_zero(S); fmpq_poly_zero(T); } else if (lenB == 0) /* lenA > lenB = 0 */ { fmpq_poly_make_monic(G, A); fmpq_poly_zero(T); fmpq_poly_fit_length(S, 1); _fmpq_poly_set_length(S, 1); if (fmpz_sgn(A->coeffs + (lenA - 1)) > 0) { fmpz_set(S->coeffs, A->den); fmpz_set(S->den, A->coeffs + (lenA - 1)); } else { fmpz_neg(S->coeffs, A->den); fmpz_neg(S->den, A->coeffs + (lenA - 1)); } fmpq_poly_canonicalise(S); } else if (lenB == 1) /* lenA >= lenB = 1 */ { fmpq_poly_set_ui(G, 1); fmpq_poly_zero(S); fmpq_poly_fit_length(T, 1); _fmpq_poly_set_length(T, 1); if (fmpz_sgn(B->coeffs) > 0) { fmpz_set(T->coeffs, B->den); fmpz_set(T->den, B->coeffs); } else { fmpz_neg(T->coeffs, B->den); fmpz_neg(T->den, B->coeffs); } } else /* lenA >= lenB >= 2 */ { /* Aliasing */ if (G == A || G == B) { fmpq_poly_t tG; fmpq_poly_init2(tG, lenG); fmpq_poly_xgcd(tG, S, T, A, B); fmpq_poly_swap(tG, G); fmpq_poly_clear(tG); } else if (S == A || S == B) { fmpq_poly_t tS; fmpq_poly_init2(tS, lenB); fmpq_poly_xgcd(G, tS, T, A, B); fmpq_poly_swap(tS, S); fmpq_poly_clear(tS); } else if (T == A || T == B) { fmpq_poly_t tT; fmpq_poly_init2(tT, lenA); fmpq_poly_xgcd(G, S, tT, A, B); fmpq_poly_swap(tT, T); fmpq_poly_clear(tT); } else /* no aliasing */ { fmpq_poly_fit_length(G, lenG); fmpq_poly_fit_length(S, lenB); fmpq_poly_fit_length(T, lenA); _fmpq_poly_xgcd(G->coeffs, G->den, S->coeffs, S->den, T->coeffs, T->den, A->coeffs, A->den, lenA, B->coeffs, B->den, lenB); _fmpq_poly_set_length(G, lenG); _fmpq_poly_set_length(S, lenB); _fmpq_poly_set_length(T, lenA); _fmpq_poly_normalise(G); _fmpq_poly_normalise(S); _fmpq_poly_normalise(T); } } } } flint-3.1.3/src/fmpq_poly/zero.c000066400000000000000000000010651461254215100165550ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_zero(fmpq_poly_t poly) { _fmpq_poly_set_length(poly, 0); fmpz_one(poly->den); } flint-3.1.3/src/fmpq_types.h000066400000000000000000000030601461254215100157610ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_TYPES_H #define FMPQ_TYPES_H #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpq * entries; slong r; slong c; fmpq ** rows; } fmpq_mat_struct; typedef fmpq_mat_struct fmpq_mat_t[1]; typedef struct { fmpz * coeffs; slong alloc; slong length; fmpz_t den; } fmpq_poly_struct; typedef fmpq_poly_struct fmpq_poly_t[1]; /* A polynomial f is represented as content * zpoly, where zpoly should have positive leading coefficient and trivial content. If f is zero, then the representation should have content = 0 and zpoly = 0 */ typedef struct { /* non zero case: | zero case: */ fmpq_t content; /* positive or negative content | zero */ fmpz_mpoly_t zpoly; /* contentless poly, lc is positive | zero */ } fmpq_mpoly_struct; typedef fmpq_mpoly_struct fmpq_mpoly_t[1]; typedef struct { fmpq_t constant; fmpq_mpoly_struct * poly; fmpz * exp; slong num; slong alloc; } fmpq_mpoly_factor_struct; typedef fmpq_mpoly_factor_struct fmpq_mpoly_factor_t[1]; #ifdef __cplusplus } #endif #endif /* FMPQ_TYPES_H */ flint-3.1.3/src/fmpq_vec.h000066400000000000000000000037521461254215100154020ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_VEC_H #define FMPQ_VEC_H #ifdef FMPQ_VEC_INLINES_C #define FMPQ_VEC_INLINE #else #define FMPQ_VEC_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *******************************************************/ fmpq * _fmpq_vec_init(slong len); void _fmpq_vec_clear(fmpq * vec, slong len); /* Randomisation ***********************************************************/ void _fmpq_vec_randtest(fmpq * f, flint_rand_t state, slong len, flint_bitcnt_t bits); void _fmpq_vec_randtest_uniq_sorted(fmpq * vec, flint_rand_t state, slong len, flint_bitcnt_t bits); /* Sorting ******************************************************************/ void _fmpq_vec_sort(fmpq * vec, slong len); /* Conversions *************************************************************/ void _fmpq_vec_set_fmpz_vec(fmpq * res, const fmpz * vec, slong len); void _fmpq_vec_get_fmpz_vec_fmpz(fmpz* num, fmpz_t den, const fmpq * a, slong len); void _fmpq_vec_get_fmpz_vec_fmpz(fmpz* num, fmpz_t den, const fmpq * a, slong len); /* Dot product **************************************************/ void _fmpq_vec_dot(fmpq_t res, const fmpq * vec1, const fmpq * vec2, slong len); /* Input and output ********************************************************/ #ifdef FLINT_HAVE_FILE int _fmpq_vec_fprint(FILE * file, const fmpq * vec, slong len); #endif int _fmpq_vec_print(const fmpq * vec, slong len); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpq_vec/000077500000000000000000000000001461254215100152225ustar00rootroot00000000000000flint-3.1.3/src/fmpq_vec/clear.c000066400000000000000000000010051461254215100164500ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_vec.h" void _fmpq_vec_clear(fmpq * vec, slong len) { _fmpz_vec_clear((fmpz *) vec, 2 * len); } flint-3.1.3/src/fmpq_vec/dot.c000066400000000000000000000012041461254215100161510ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpq.h" #include "fmpq_vec.h" void _fmpq_vec_dot(fmpq_t res, const fmpq * vec1, const fmpq * vec2, slong len) { slong i; fmpq_zero(res); for (i = 0; i < len; i++) { fmpq_addmul(res, vec1 + i, vec2 + i); } } flint-3.1.3/src/fmpq_vec/get_fmpz_vec_fmpz.c000066400000000000000000000022451461254215100210750ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_vec.h" void _fmpq_vec_get_fmpz_vec_fmpz(fmpz* num, fmpz_t den, const fmpq * a, slong len) { slong i; if (len < 1) { fmpz_one(den); return; } else if (len == 1) { fmpz_set(num + 0, fmpq_numref(a + 0)); fmpz_set(den, fmpq_denref(a + 0)); return; } fmpz_lcm(den, fmpq_denref(a + 0), fmpq_denref(a + 1)); for (i = 2; i < len; i++) fmpz_lcm(den, den, fmpq_denref(a + i)); if (fmpz_is_one(den)) { for (i = 0; i < len; i++) fmpz_set(num + i, fmpq_numref(a + i)); } else { for (i = 0; i < len; i++) { fmpz_divexact(num + i, den, fmpq_denref(a + i)); fmpz_mul(num + i, num + i, fmpq_numref(a + i)); } } } flint-3.1.3/src/fmpq_vec/init.c000066400000000000000000000013021461254215100163250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpq.h" #include "fmpq_vec.h" fmpq * _fmpq_vec_init(slong len) { fmpq * v = (fmpq *) flint_malloc(sizeof(fmpq) * len); slong i; for (i = 0; i < len; i++) fmpq_init(v + i); return v; } flint-3.1.3/src/fmpq_vec/io.c000066400000000000000000000017661461254215100160070ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "fmpq_vec.h" /* printing *******************************************************************/ int _fmpq_vec_fprint(FILE * file, const fmpq * vec, slong len) { int r; slong i; r = flint_fprintf(file, "%wd", len); if ((len > 0) && (r > 0)) { r = fputc(' ', file); for (i = 0; (i < len) && (r > 0); i++) { r = fputc(' ', file); if (r > 0) r = fmpq_fprint(file, vec + i); } } return r; } int _fmpq_vec_print(const fmpq * vec, slong len) { return _fmpq_vec_fprint(stdout, vec, len); } flint-3.1.3/src/fmpq_vec/randtest.c000066400000000000000000000017251461254215100172170ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpq.h" #include "fmpq_vec.h" void _fmpq_vec_randtest(fmpq * f, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong i, sparseness; if (n_randint(state, 2)) { for (i = 0; i < len; i++) fmpq_randtest(f + i, state, bits); } else { sparseness = 1 + n_randint(state, FLINT_MAX(2, len)); for (i = 0; i < len; i++) { if (n_randint(state, sparseness)) fmpq_zero(f + i); else fmpq_randtest(f + i, state, bits); } } } flint-3.1.3/src/fmpq_vec/randtest_uniq_sorted.c000066400000000000000000000021711461254215100216270ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" #include "fmpq_vec.h" void _fmpq_vec_randtest_uniq_sorted(fmpq * vec, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong i; int do_again; /* if 2^bits < len we are too likely to have collision */ if (4 * n_sizeinbase(len, 2) > bits) flint_throw(FLINT_ERROR, "bits too small in %s\n", __func__); _fmpq_vec_randtest(vec, state, len, bits); if (len <= 1) return; do { do_again = 0; _fmpq_vec_sort(vec, len); for (i = 0; i < len - 1; i++) { if (fmpq_equal(vec + i, vec + i + 1)) { fmpq_randtest(vec + i, state, bits); do_again = 1; } } } while (do_again); } flint-3.1.3/src/fmpq_vec/set_fmpz_vec.c000066400000000000000000000011511461254215100200500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_vec.h" void _fmpq_vec_set_fmpz_vec(fmpq * res, const fmpz * vec, slong len) { slong i; for (i = 0; i < len; i++) fmpq_set_fmpz(res + i, vec + i); } flint-3.1.3/src/fmpq_vec/sort.c000066400000000000000000000011411461254215100163520ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "fmpq_vec.h" typedef int(*__compar_fn_t) (const void *, const void *); void _fmpq_vec_sort(fmpq * vec, slong len) { qsort(vec, len, sizeof(fmpq), (__compar_fn_t) fmpq_cmp); } flint-3.1.3/src/fmpq_vec/test/000077500000000000000000000000001461254215100162015ustar00rootroot00000000000000flint-3.1.3/src/fmpq_vec/test/main.c000066400000000000000000000016351461254215100172760ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-dot.c" #include "t-get_set_fmpz_vec.c" #include "t-randtest_uniq_sorted.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpq_vec_dot), TEST_FUNCTION(fmpq_vec_get_set_fmpz_vec), TEST_FUNCTION(fmpq_vec_randtest_uniq_sorted) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpq_vec/test/t-dot.c000066400000000000000000000024361461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" TEST_FUNCTION_START(fmpq_vec_dot, state) { int i, result; /* Check commutative law */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq *a, *b; fmpq_t res1, res2; slong len = n_randint(state, 100); a = _fmpq_vec_init(len); b = _fmpq_vec_init(len); _fmpq_vec_randtest(a, state, len, 200); _fmpq_vec_randtest(b, state, len, 200); fmpq_init(res1); fmpq_init(res2); _fmpq_vec_dot(res1, a, b, len); _fmpq_vec_dot(res2, b, a, len); result = fmpq_equal(res1, res2); if (!result) { flint_printf("FAIL:\n"); fflush(stdout); flint_abort(); } _fmpq_vec_clear(a, len); _fmpq_vec_clear(b, len); fmpq_clear(res1); fmpq_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_vec/test/t-get_set_fmpz_vec.c000066400000000000000000000030541461254215100221330ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_vec.h" TEST_FUNCTION_START(fmpq_vec_get_set_fmpz_vec, state) { int iter; for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong i, n; fmpq * a, * b; fmpz * c; fmpz_t d; n = n_randint(state, 20); a = _fmpq_vec_init(n); b = _fmpq_vec_init(n); c = _fmpz_vec_init(n); fmpz_init(d); _fmpq_vec_randtest(a, state, n, 1 + n_randint(state, 200)); _fmpq_vec_randtest(b, state, n, 1 + n_randint(state, 200)); _fmpz_vec_randtest(c, state, n, 1 + n_randint(state, 200)); _fmpq_vec_get_fmpz_vec_fmpz(c, d, a, n); _fmpq_vec_set_fmpz_vec(b, c, n); for (i = 0; i < n; i++) { fmpq_div_fmpz(b + i, b + i, d); if (!fmpq_equal(b + i, a + i)) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } _fmpq_vec_clear(a, n); _fmpq_vec_clear(b, n); _fmpz_vec_clear(c, n); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpq_vec/test/t-randtest_uniq_sorted.c000066400000000000000000000040341461254215100230470ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpq_vec.h" TEST_FUNCTION_START(fmpq_vec_randtest_uniq_sorted, state) { int iter; for (iter = 0; iter < 500 * flint_test_multiplier(); iter++) { slong i; slong n; flint_bitcnt_t bits; fmpq * vec; n = n_randint(state, 20); vec = _fmpq_vec_init(n); bits = 21 + n_randint(state, 200); _fmpq_vec_randtest_uniq_sorted(vec, state, n, bits); /* check bit size */ for (i = 0; i < n; i++) { if ((fmpz_bits(fmpq_numref(vec + i)) > bits) || (fmpz_bits(fmpq_denref(vec + i)) > bits)) { printf("ERROR\n"); flint_printf("num size: %wu\n", fmpz_bits(fmpq_numref(vec + i))); flint_printf("den size: %wu\n", fmpz_bits(fmpq_denref(vec + i))); flint_printf("bits : %wu\n", bits); fflush(stdout); flint_abort(); } } /* check uniqueness and ordering */ for (i = 0; i < n-1; i++) { if (fmpq_cmp(vec + i + 1, vec + i) <= 0) { printf("ERROR:\n"); flint_printf("n = %wu\n", n); flint_printf("bits = %wu\n", bits); flint_printf("got vec[%wd] = ", i); fmpq_print(vec + i); flint_printf(" and vec[%wd] = ", i+1); fmpq_print(vec + i + 1); printf("\n"); fflush(stdout); flint_abort(); } } _fmpq_vec_clear(vec, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz.h000066400000000000000000000614521461254215100145570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_H #define FMPZ_H #ifdef FMPZ_INLINES_C #define FMPZ_INLINE #else #define FMPZ_INLINE static inline #endif #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *********************************************************/ mpz_ptr _fmpz_new_mpz(void); void _fmpz_clear_mpz(fmpz f); void _fmpz_cleanup_mpz_content(void); void _fmpz_cleanup(void); mpz_ptr _fmpz_promote(fmpz_t f); mpz_ptr _fmpz_promote_val(fmpz_t f); FMPZ_INLINE void _fmpz_demote(fmpz_t f) { if (COEFF_IS_MPZ(*f)) { _fmpz_clear_mpz(*f); (*f) = WORD(0); } } void _fmpz_demote_val(fmpz_t f); FMPZ_INLINE void fmpz_init(fmpz_t f) { *f = WORD(0); } FMPZ_INLINE void fmpz_clear(fmpz_t f) { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); } void fmpz_init2(fmpz_t f, ulong limbs); void _fmpz_promote_set_ui(fmpz_t f, ulong v); void _fmpz_promote_set_si(fmpz_t f, slong v); void _fmpz_promote_neg_ui(fmpz_t f, ulong v); void _fmpz_init_promote_set_ui(fmpz_t f, ulong v); void _fmpz_init_promote_set_si(fmpz_t f, slong v); FMPZ_INLINE void fmpz_init_set(fmpz_t f, const fmpz_t g) { if (!COEFF_IS_MPZ(*g)) { *f = *g; } else { mpz_ptr ptr; ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(ptr); mpz_set(ptr, COEFF_TO_PTR(*g)); } } FMPZ_INLINE void fmpz_init_set_ui(fmpz_t f, ulong g) { if (g <= COEFF_MAX) *f = g; else _fmpz_init_promote_set_ui(f, g); } FMPZ_INLINE void fmpz_init_set_si(fmpz_t f, slong g) { if (COEFF_MIN <= g && g <= COEFF_MAX) *f = g; else _fmpz_init_promote_set_si(f, g); } void _fmpz_init_readonly_mpz(fmpz_t f, const mpz_t z); void flint_mpz_init_set_readonly(mpz_t z, const fmpz_t f); void fmpz_init_set_readonly(fmpz_t f, const mpz_t z); void flint_mpz_clear_readonly(mpz_t z); void _fmpz_clear_readonly_mpz(mpz_t); void fmpz_clear_readonly(fmpz_t f); int _fmpz_is_canonical(const fmpz_t x); /* Randomisation *************************************************************/ void fmpz_randbits(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); void fmpz_randm(fmpz_t f, flint_rand_t state, const fmpz_t m); void fmpz_randtest(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); void fmpz_randtest_unsigned(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); void fmpz_randtest_not_zero(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); void fmpz_randtest_mod(fmpz_t f, flint_rand_t state, const fmpz_t m); void fmpz_randtest_mod_signed(fmpz_t f, flint_rand_t state, const fmpz_t m); void fmpz_randprime(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits, int proved); /* Assignments and conversions ***********************************************/ FMPZ_INLINE void fmpz_zero(fmpz_t f) { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); *f = WORD(0); } FMPZ_INLINE void fmpz_one(fmpz_t f) { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); *f = WORD(1); } void fmpz_set(fmpz_t f, const fmpz_t g); FMPZ_INLINE void fmpz_swap(fmpz_t f, fmpz_t g) { FLINT_SWAP(fmpz, *f, *g); } slong fmpz_get_si(const fmpz_t f); ulong fmpz_get_ui(const fmpz_t f); FMPZ_INLINE void fmpz_set_si(fmpz_t f, slong val) { if (val >= COEFF_MIN && val <= COEFF_MAX) { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); *f = val; } else _fmpz_promote_set_si(f, val); } FMPZ_INLINE void fmpz_set_ui(fmpz_t f, ulong val) { if (val <= COEFF_MAX) { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); *f = val; } else _fmpz_promote_set_ui(f, val); } FMPZ_INLINE void fmpz_neg_ui(fmpz_t f, ulong val) { if (val <= COEFF_MAX) { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); *f = -(slong) val; } else _fmpz_promote_neg_ui(f, val); } FMPZ_INLINE void fmpz_get_uiui(mp_limb_t * hi, mp_limb_t * low, const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) { *low = *f; *hi = 0; } else { __mpz_struct * mpz = COEFF_TO_PTR(*f); *low = mpz->_mp_d[0]; *hi = mpz->_mp_size == 2 ? mpz->_mp_d[1] : 0; } } FMPZ_INLINE void fmpz_set_uiui(fmpz_t f, mp_limb_t hi, mp_limb_t lo) { if (hi == 0) { fmpz_set_ui(f, lo); } else { __mpz_struct *z = _fmpz_promote(f); if (z->_mp_alloc < 2) mpz_realloc2(z, 2 * FLINT_BITS); z->_mp_d[0] = lo; z->_mp_d[1] = hi; z->_mp_size = 2; } } FMPZ_INLINE void fmpz_neg_uiui(fmpz_t f, mp_limb_t hi, mp_limb_t lo) { if (hi == 0) { fmpz_neg_ui(f, lo); } else { __mpz_struct *z = _fmpz_promote(f); if (z->_mp_alloc < 2) mpz_realloc2(z, 2 * FLINT_BITS); z->_mp_d[0] = lo; z->_mp_d[1] = hi; z->_mp_size = -2; } } void fmpz_get_signed_uiui(ulong * hi, ulong * lo, const fmpz_t x); FMPZ_INLINE void fmpz_set_signed_uiui(fmpz_t r, ulong hi, ulong lo) { if (((slong) hi) < 0) { hi = -hi - (lo != 0); lo = -lo; fmpz_neg_uiui(r, hi, lo); } else { fmpz_set_uiui(r, hi, lo); } } void fmpz_set_signed_uiuiui(fmpz_t r, ulong hi, ulong mid, ulong lo); void fmpz_get_ui_array(ulong * out, slong n, const fmpz_t in); void fmpz_set_ui_array(fmpz_t out, const ulong * in, slong n); void fmpz_get_signed_ui_array(ulong * out, slong n, const fmpz_t in); void fmpz_set_signed_ui_array(fmpz_t out, const ulong * in, slong n); void fmpz_get_mpz(mpz_t x, const fmpz_t f); void fmpz_set_mpz(fmpz_t f, const mpz_t x); mp_limb_t fmpz_get_nmod(const fmpz_t f, nmod_t mod); double fmpz_get_d(const fmpz_t f); void fmpz_set_d(fmpz_t f, double c); void fmpz_get_mpf(mpf_t x, const fmpz_t f); void fmpz_set_mpf(fmpz_t f, const mpf_t x); #ifdef __MPFR_H void fmpz_get_mpfr(mpfr_t x, const fmpz_t f, mpfr_rnd_t rnd); #endif int fmpz_get_mpn(mp_ptr * n, fmpz_t n_in); /* Comparisons ***************************************************************/ FMPZ_INLINE int fmpz_is_zero(const fmpz_t f) { return (*f == 0); } FMPZ_INLINE int fmpz_is_one(const fmpz_t f) { return (*f == 1); } FMPZ_INLINE int fmpz_is_pm1(const fmpz_t f) { return (*f == 1 || *f == -1); } int fmpz_equal(const fmpz_t f, const fmpz_t g); int fmpz_equal_si(const fmpz_t f, slong g); int fmpz_equal_ui(const fmpz_t f, ulong g); int fmpz_cmp(const fmpz_t f, const fmpz_t g); int fmpz_cmp_ui(const fmpz_t f, ulong g); int fmpz_cmp_si(const fmpz_t f, slong g); int fmpz_cmpabs(const fmpz_t f, const fmpz_t g); int fmpz_cmp2abs(const fmpz_t f, const fmpz_t g); /* Basic properties and manipulation *****************************************/ FMPZ_INLINE int fmpz_is_even(const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) return !((*f) & WORD(1)); else return mpz_even_p(COEFF_TO_PTR(*f)); } FMPZ_INLINE int fmpz_is_odd(const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) return ((*f) & WORD(1)); else return mpz_odd_p(COEFF_TO_PTR(*f)); } int fmpz_sgn(const fmpz_t f); int fmpz_abs_fits_ui(const fmpz_t f); int fmpz_fits_si(const fmpz_t f); size_t fmpz_sizeinbase(const fmpz_t f, int b); mp_size_t fmpz_size(const fmpz_t f); flint_bitcnt_t fmpz_bits(const fmpz_t f); flint_bitcnt_t fmpz_val2(const fmpz_t x); int fmpz_is_square(const fmpz_t f); int fmpz_is_perfect_power(fmpz_t root, const fmpz_t f); mp_limb_t fmpz_abs_ubound_ui_2exp(slong * exp, const fmpz_t x, int bits); mp_limb_t fmpz_abs_lbound_ui_2exp(slong * exp, const fmpz_t x, int bits); /* I/O ***********************************************************************/ int fmpz_read(fmpz_t f); int fmpz_print(const fmpz_t x); int fmpz_set_str(fmpz_t f, const char * str, int b); char * fmpz_get_str(char * str, int b, const fmpz_t f); #ifdef FLINT_HAVE_FILE int fmpz_fread(FILE * file, fmpz_t f); int fmpz_fprint(FILE * file, const fmpz_t x); size_t fmpz_inp_raw(fmpz_t x, FILE * fin); size_t fmpz_out_raw(FILE * fout, const fmpz_t x); #endif /* Basic arithmetic **********************************************************/ void fmpz_add(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_add_ui(fmpz_t f, const fmpz_t g, ulong x); void fmpz_sub(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_sub_ui(fmpz_t f, const fmpz_t g, ulong x); FMPZ_INLINE void fmpz_add_si(fmpz_t f, const fmpz_t g, slong x) { if (x >= 0) fmpz_add_ui(f, g, (ulong) x); else fmpz_sub_ui(f, g, (ulong) -x); } FMPZ_INLINE void fmpz_sub_si(fmpz_t f, const fmpz_t g, slong x) { if (x >= 0) fmpz_sub_ui(f, g, (ulong) x); else fmpz_add_ui(f, g, (ulong) -x); } void fmpz_abs(fmpz_t f1, const fmpz_t f2); void fmpz_neg(fmpz_t f1, const fmpz_t f2); void fmpz_mul_ui(fmpz_t f, const fmpz_t g, ulong x); void fmpz_mul_si(fmpz_t f, const fmpz_t g, slong x); void fmpz_mul(fmpz_t f, const fmpz_t g, const fmpz_t h); FMPZ_INLINE void fmpz_mul2_uiui(fmpz_t f, const fmpz_t g, ulong h1, ulong h2) { mp_limb_t hi, lo; umul_ppmm(hi, lo, h1, h2); if (!hi) { fmpz_mul_ui(f, g, lo); } else { fmpz_mul_ui(f, g, h1); fmpz_mul_ui(f, f, h2); } } void fmpz_mul_2exp(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_one_2exp(fmpz_t f, ulong exp); void fmpz_addmul(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_addmul_si(fmpz_t f, const fmpz_t g, slong x); void fmpz_addmul_ui(fmpz_t f, const fmpz_t g, ulong x); void fmpz_submul(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_submul_si(fmpz_t f, const fmpz_t g, slong x); void fmpz_submul_ui(fmpz_t f, const fmpz_t g, ulong x); void fmpz_fmma(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d); void fmpz_fmms(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d); void fmpz_pow_ui(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_ui_pow_ui(fmpz_t x, ulong b, ulong e); int fmpz_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t e); void fmpz_sqrt(fmpz_t f, const fmpz_t g); void fmpz_sqrtrem(fmpz_t f, fmpz_t r, const fmpz_t g); int fmpz_root(fmpz_t r, const fmpz_t f, slong n); int fmpz_divisible(const fmpz_t f, const fmpz_t g); int fmpz_divisible_ui(const fmpz_t f, ulong g); FMPZ_INLINE int fmpz_divisible_si(const fmpz_t f, slong g) { return fmpz_divisible_ui(f, FLINT_ABS(g)); } int fmpz_divides(fmpz_t q, const fmpz_t g, const fmpz_t h); void fmpz_divexact(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_divexact_ui(fmpz_t f, const fmpz_t g, ulong h); void fmpz_divexact_si(fmpz_t f, const fmpz_t g, slong h); FMPZ_INLINE void fmpz_divexact2_uiui(fmpz_t f, const fmpz_t g, ulong h1, ulong h2) { mp_limb_t hi, lo; umul_ppmm(hi, lo, h1, h2); if (!hi) { fmpz_divexact_ui(f, g, lo); } else { fmpz_divexact_ui(f, g, h1); fmpz_divexact_ui(f, f, h2); } } void fmpz_cdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h); void fmpz_fdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h); void fmpz_tdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h); void fmpz_ndiv_qr(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b); void fmpz_cdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_fdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_tdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_cdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_fdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_tdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp); ulong fmpz_cdiv_ui(const fmpz_t g, ulong h); ulong fmpz_fdiv_ui(const fmpz_t g, ulong h); ulong fmpz_tdiv_ui(const fmpz_t g, ulong h); void fmpz_cdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_tdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_fdiv_r(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_cdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h); void fmpz_fdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h); void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h); void fmpz_cdiv_q_si(fmpz_t f, const fmpz_t g, slong h); void fmpz_fdiv_q_si(fmpz_t f, const fmpz_t g, slong h); void fmpz_tdiv_q_si(fmpz_t f, const fmpz_t g, slong h); void fmpz_mul_tdiv_q_2exp(fmpz_t f, const fmpz_t g, const fmpz_t h, ulong exp); void fmpz_mul_si_tdiv_q_2exp(fmpz_t f, const fmpz_t g, slong x, ulong exp); double fmpz_dlog(const fmpz_t x); slong fmpz_clog(const fmpz_t x, const fmpz_t b); slong fmpz_flog(const fmpz_t x, const fmpz_t b); slong fmpz_clog_ui(const fmpz_t x, ulong b); slong fmpz_flog_ui(const fmpz_t x, ulong b); double fmpz_get_d_2exp(slong * exp, const fmpz_t f); void fmpz_set_d_2exp(fmpz_t f, double m, slong exp); #ifdef FLINT_HAVE_FFT_SMALL #define MPZ_WANT_FLINT_DIVISION(a, b) (mpz_size(b) >= 1250 && mpz_size(a) - mpz_size(b) >= 1250) #else #define MPZ_WANT_FLINT_DIVISION(a, b) 0 #endif void _fmpz_tdiv_q_newton(fmpz_t q, const fmpz_t a, const fmpz_t b); void _fmpz_fdiv_q_newton(fmpz_t q, const fmpz_t a, const fmpz_t b); void _fmpz_cdiv_q_newton(fmpz_t q, const fmpz_t a, const fmpz_t b); void _fmpz_tdiv_qr_newton(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b); void _fmpz_fdiv_qr_newton(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b); void _fmpz_cdiv_qr_newton(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b); void _fmpz_tdiv_r_newton(fmpz_t r, const fmpz_t a, const fmpz_t b); void _fmpz_fdiv_r_newton(fmpz_t r, const fmpz_t a, const fmpz_t b); void _fmpz_cdiv_r_newton(fmpz_t r, const fmpz_t a, const fmpz_t b); void _fmpz_mod_newton(fmpz_t r, const fmpz_t a, const fmpz_t b); void _fmpz_divexact_newton(fmpz_t q, const fmpz_t a, const fmpz_t b); /* Bitwise operations ********************************************************/ void fmpz_setbit(fmpz_t f, ulong i); void fmpz_clrbit(fmpz_t f, ulong i); int fmpz_tstbit(const fmpz_t f, ulong i); void fmpz_complement(fmpz_t r, const fmpz_t f); void fmpz_combit(fmpz_t f, ulong i); void fmpz_and(fmpz_t r, const fmpz_t a, const fmpz_t b); void fmpz_or(fmpz_t r, const fmpz_t a, const fmpz_t b); void fmpz_xor(fmpz_t r, const fmpz_t a, const fmpz_t b); flint_bitcnt_t fmpz_popcnt(const fmpz_t c); /* Bit packing ***************************************************************/ int fmpz_bit_pack(mp_ptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits, const fmpz_t coeff, int negate, int borrow); int fmpz_bit_unpack(fmpz_t coeff, mp_srcptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits, int negate, int borrow); void fmpz_bit_unpack_unsigned(fmpz_t coeff, mp_srcptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits); /* Modular arithmetic ********************************************************/ FMPZ_INLINE ulong fmpz_mod_ui(fmpz_t f, const fmpz_t g, ulong h) { h = fmpz_fdiv_ui(g, h); fmpz_set_ui(f, h); return h; } FMPZ_INLINE void fmpz_set_ui_smod(fmpz_t f, mp_limb_t x, mp_limb_t m) { if (x <= m / 2) fmpz_set_ui(f, x); else fmpz_set_si(f, x - m); } void fmpz_mod(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_smod(fmpz_t f, const fmpz_t g, const fmpz_t h); void _fmpz_smod(fmpz_t r, const fmpz_t a, const fmpz_t m, int sign, fmpz_t t); FMPZ_INLINE void fmpz_negmod(fmpz_t r, const fmpz_t a, const fmpz_t mod) { if (fmpz_is_zero(a)) fmpz_zero(r); else fmpz_sub(r, mod, a); } int fmpz_invmod(fmpz_t f, const fmpz_t g, const fmpz_t h); int fmpz_sqrtmod(fmpz_t b, const fmpz_t a, const fmpz_t p); void fmpz_powm_ui(fmpz_t f, const fmpz_t g, ulong exp, const fmpz_t m); void fmpz_powm(fmpz_t f, const fmpz_t g, const fmpz_t e, const fmpz_t m); void fmpz_divides_mod_list(fmpz_t xstart, fmpz_t xstride, fmpz_t xlength, const fmpz_t a, const fmpz_t b, const fmpz_t n); slong _fmpz_remove(fmpz_t x, const fmpz_t f, double finv); slong fmpz_remove(fmpz_t rop, const fmpz_t op, const fmpz_t f); /* GCD and LCM ***************************************************************/ void fmpz_gcd(fmpz_t f, const fmpz_t g, const fmpz_t h); void fmpz_gcd_ui(fmpz_t res, const fmpz_t a, ulong b); void fmpz_gcd3(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c); void fmpz_gcdinv(fmpz_t d, fmpz_t a, const fmpz_t f, const fmpz_t g); void fmpz_xgcd(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g); void fmpz_xgcd_canonical_bezout(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g); void fmpz_xgcd_partial(fmpz_t co2, fmpz_t co1, fmpz_t r2, fmpz_t r1, const fmpz_t L); void fmpz_lcm(fmpz_t f, const fmpz_t g, const fmpz_t h); /* preinvn *******************************************************************/ void fmpz_fdiv_qr_preinvn(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h, const fmpz_preinvn_t inv); void fmpz_fdiv_r_preinvn(fmpz_t f, const fmpz_t g, const fmpz_t h, const fmpz_preinvn_t inv); void fmpz_preinvn_init(fmpz_preinvn_t inv, const fmpz_t f); void fmpz_preinvn_clear(fmpz_preinvn_t inv); /* Combinatorics functions ***************************************************/ void fmpz_fac_ui(fmpz_t f, ulong n); void fmpz_bin_uiui(fmpz_t res, ulong n, ulong k); void _fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong a, ulong b); void fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong n); void fmpz_rfac_uiui(fmpz_t r, ulong x, ulong n); /* Number theoretic functions ************************************************/ int fmpz_jacobi(const fmpz_t a, const fmpz_t p); int fmpz_kronecker(const fmpz_t a, const fmpz_t n); void fmpz_fib_ui(fmpz_t f, ulong n); /* crt ***********************************************************************/ void _fmpz_CRT_ui_precomp(fmpz_t out, const fmpz_t r1, const fmpz_t m1, ulong r2, ulong m2, mp_limb_t m2inv, const fmpz_t m1m2, mp_limb_t c, int sign); void fmpz_CRT_ui(fmpz_t out, const fmpz_t r1, const fmpz_t m1, ulong r2, ulong m2, int sign); void fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2, int sign); /* multi CRT *****************************************************************/ typedef struct { slong a_idx; /* index of A */ slong b_idx; /* index of B */ slong c_idx; /* index of C */ fmpz_t b_modulus; fmpz_t c_modulus; } _fmpz_multi_CRT_instr; typedef struct { _fmpz_multi_CRT_instr * prog; /* straight line program */ fmpz * moduli, * fracmoduli; fmpz_t final_modulus; slong moduli_count; flint_bitcnt_t min_modulus_bits; slong length; /* length of prog */ slong alloc; /* alloc of prog */ slong localsize; /* length of outputs required in fmpz_multi_CRT_run */ slong temp1loc, temp2loc, temp3loc, temp4loc; int good; /* the moduli are good for CRT, essentially relatively prime */ } fmpz_multi_CRT_struct; typedef fmpz_multi_CRT_struct fmpz_multi_CRT_t[1]; void fmpz_multi_CRT_init(fmpz_multi_CRT_t CRT); void fmpz_multi_CRT_clear(fmpz_multi_CRT_t P); void _fmpz_multi_CRT_precomp(fmpz * outputs, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign); void fmpz_multi_CRT_precomp(fmpz_t output, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign); int fmpz_multi_CRT_precompute(fmpz_multi_CRT_t CRT, const fmpz * moduli, slong len); int fmpz_multi_CRT(fmpz_t output, const fmpz * moduli, const fmpz * values, slong len, int sign); /* multi mod *****************************************************************/ typedef struct { slong in_idx; slong out_idx; fmpz_t modulus; } _fmpz_multi_mod_instr; typedef struct { _fmpz_multi_mod_instr * prog; /* straight line program */ fmpz * moduli; slong moduli_count; flint_bitcnt_t min_modulus_bits; slong length; /* length of prog */ slong alloc; /* alloc of prog */ slong localsize; /* length of tmp required in _fmpz_multi_mod_precomp */ slong temp1loc; int good; /* the moduli are good for MOD, none are zero */ } fmpz_multi_mod_struct; typedef fmpz_multi_mod_struct fmpz_multi_mod_t[1]; void fmpz_multi_mod_init(fmpz_multi_mod_t P); void fmpz_multi_mod_clear(fmpz_multi_mod_t P); int fmpz_multi_mod_precompute(fmpz_multi_mod_t P, const fmpz * f, slong r); void _fmpz_multi_mod_precomp(fmpz * outputs, const fmpz_multi_mod_t P, const fmpz_t input, int sign, fmpz * tmp); void fmpz_multi_mod_precomp(fmpz * outputs, const fmpz_multi_mod_t P, const fmpz_t input, int sign); /* multi mod/multi CRT ui ****************************************************/ typedef struct { nmod_t mod; mp_limb_t i0, i1, i2; } crt_lut_entry; typedef struct { nmod_t mod; nmod_t mod0, mod1, mod2; } mod_lut_entry; typedef struct { fmpz_multi_CRT_t crt_P; fmpz_multi_mod_t mod_P; mp_limb_t * packed_multipliers; slong * step; slong * crt_offsets; slong crt_offsets_alloc; slong * mod_offsets; slong mod_offsets_alloc; crt_lut_entry * crt_lu; slong crt_lu_alloc; slong crt_klen; mod_lut_entry * mod_lu; slong mod_lu_alloc; slong mod_klen; slong num_primes; } fmpz_comb_struct; typedef fmpz_comb_struct fmpz_comb_t[1]; typedef struct { slong Alen, Tlen; fmpz * A, * T; } fmpz_comb_temp_struct; typedef fmpz_comb_temp_struct fmpz_comb_temp_t[1]; void fmpz_comb_temp_init(fmpz_comb_temp_t CT, const fmpz_comb_t C); void fmpz_comb_temp_clear(fmpz_comb_temp_t CT); void fmpz_comb_init(fmpz_comb_t C, mp_srcptr primes, slong num_primes); void fmpz_comb_clear(fmpz_comb_t C); void fmpz_multi_mod_ui(mp_limb_t * out, const fmpz_t in, const fmpz_comb_t C, fmpz_comb_temp_t CT); void fmpz_multi_CRT_ui(fmpz_t output, mp_srcptr residues, const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign); /*****************************************************************************/ void fmpz_lucas_chain(fmpz_t Vm, fmpz_t Vm1, const fmpz_t A, const fmpz_t m, const fmpz_t n); void fmpz_lucas_chain_full(fmpz_t Vm, fmpz_t Vm1, const fmpz_t A, const fmpz_t B, const fmpz_t m, const fmpz_t n); void fmpz_lucas_chain_double(fmpz_t U2m, fmpz_t U2m1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t A, const fmpz_t B, const fmpz_t n); void fmpz_lucas_chain_add(fmpz_t Umn, fmpz_t Umn1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t Un, const fmpz_t Un1, const fmpz_t A, const fmpz_t B, const fmpz_t n); void fmpz_lucas_chain_mul(fmpz_t Ukm, fmpz_t Ukm1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t A, const fmpz_t B, const fmpz_t k, const fmpz_t n); void fmpz_lucas_chain_VtoU(fmpz_t Um, fmpz_t Um1, const fmpz_t Vm, const fmpz_t Vm1, const fmpz_t A, const fmpz_t B, const fmpz_t Dinv, const fmpz_t n); int fmpz_is_probabprime_lucas(const fmpz_t n); int fmpz_is_probabprime_BPSW(const fmpz_t n); int fmpz_is_probabprime(const fmpz_t p); int fmpz_is_strong_probabprime(const fmpz_t n, const fmpz_t a); int fmpz_is_prime_pseudosquare(const fmpz_t n); int fmpz_is_prime_pocklington(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pm1, slong num_pm1); int fmpz_is_prime_morrison(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pm1, slong num_pm1); int fmpz_is_prime(const fmpz_t p); void fmpz_nextprime(fmpz_t res, const fmpz_t n, int proved); void _fmpz_nm1_trial_factors(const fmpz_t n, mp_ptr pm1, slong * num_pm1, ulong limit); void _fmpz_np1_trial_factors(const fmpz_t n, mp_ptr pp1, slong * num_pp1, ulong limit); int fmpz_divisor_in_residue_class_lenstra(fmpz_t fac, const fmpz_t n, const fmpz_t r, const fmpz_t s); /* Primorial *****************************************************************/ void fmpz_primorial(fmpz_t res, ulong n); /* Multiplicative functions **************************************************/ void fmpz_euler_phi(fmpz_t res, const fmpz_t n); int fmpz_moebius_mu(const fmpz_t n); void fmpz_divisor_sigma(fmpz_t res, ulong k, const fmpz_t n); /* Declare dead functions ****************************************************/ #define __new_fmpz _Pragma("GCC error \"'__new_fmpz' is deprecated.\"") #define __free_fmpz _Pragma("GCC error \"'__free_fmpz' is deprecated.\"") #define __fmpz_lt _Pragma("GCC error \"'__fmpz_lt' is deprecated.\"") #define __fmpz_gt _Pragma("GCC error \"'__fmpz_gt' is deprecated.\"") #define __fmpz_lte _Pragma("GCC error \"'__fmpz_lte' is deprecated.\"") #define __fmpz_gte _Pragma("GCC error \"'__fmpz_gte' is deprecated.\"") #define __fmpz_neq _Pragma("GCC error \"'__fmpz_neq' is deprecated.\"") #define __fmpz_init _Pragma("GCC error \"'__fmpz_init' is deprecated. Use 'fmpz_init' instead.\"") #define __fmpz_init_set _Pragma("GCC error \"'__fmpz_init_set' is deprecated. Use 'fmpz_init_set' instead.\"") #define __fmpz_init_set_ui _Pragma("GCC error \"'__fmpz_init_set_ui' is deprecated. Use 'fmpz_init_set_ui' instead.\"") #define __fmpz_clear _Pragma("GCC error \"'__fmpz_clear' is deprecated. Use 'fmpz_clear' instead.\"") #define __fmpz_set_si _Pragma("GCC error \"'__fmpz_set_si' is deprecated. Use 'fmpz_set_si' instead.\"") #define __fmpz_set_ui _Pragma("GCC error \"'__fmpz_set_ui' is deprecated. Use 'fmpz_set_ui' instead.\"") #define __fmpz_eq _Pragma("GCC error \"'__fmpz_eq' is deprecated. Use 'fmpz_equal' instead.\"") #define __fmpz_neg _Pragma("GCC error \"'__fmpz_neg' is deprecated. Use 'fmpz_neg' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz/000077500000000000000000000000001461254215100143765ustar00rootroot00000000000000flint-3.1.3/src/fmpz/CRT.c000066400000000000000000000057671461254215100152110ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" void _fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2, const fmpz_t m1m2, fmpz_t c, int sign) { fmpz_t r1normal, tmp, r1mod, s; fmpz_init(tmp); fmpz_init(r1mod); fmpz_init(s); /* FIXME: assume r1 moved to [0, m1); add tests for this */ if (fmpz_sgn(r1) < 0) { fmpz_init(r1normal); fmpz_add(r1normal, r1, m1); } else { *r1normal = *r1; } fmpz_mod(r1mod, r1normal, m2); fmpz_sub(s, r2, r1mod); if (fmpz_sgn(s) < 0) fmpz_add(s, s, m2); fmpz_mul(s, s, c); fmpz_mod(s, s, m2); fmpz_mul(tmp, m1, s); fmpz_add(tmp, tmp, r1normal); if (fmpz_sgn(r1) < 0) fmpz_clear(r1normal); if (sign) { fmpz_sub(out, tmp, m1m2); if (fmpz_cmpabs(tmp, out) <= 0) fmpz_set(out, tmp); } else { fmpz_set(out, tmp); } fmpz_clear(tmp); fmpz_clear(r1mod); fmpz_clear(s); } void fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2, int sign) { fmpz_t m1m2, c; fmpz_init(c); fmpz_mod(c, m1, m2); if (!fmpz_invmod(c, c, m2)) { flint_throw(FLINT_ERROR, "Exception (fmpz_CRT). m1 not invertible modulo m2.\n"); } fmpz_init(m1m2); fmpz_mul(m1m2, m1, m2); _fmpz_CRT(out, r1, m1, r2, m2, m1m2, c, sign); fmpz_clear(m1m2); fmpz_clear(c); } void _fmpz_CRT_ui_precomp(fmpz_t out, const fmpz_t r1, const fmpz_t m1, ulong r2, ulong m2, mp_limb_t m2inv, const fmpz_t m1m2, mp_limb_t c, int sign) { mp_limb_t r1mod, s; fmpz_t tmp; nmod_t mod; fmpz_init(tmp); if (fmpz_sgn(r1) < 0) fmpz_add(tmp, r1, m1); else fmpz_set(tmp, r1); mod.n = m2; mod.ninv = m2inv; mod.norm = flint_clz(m2); r1mod = fmpz_get_nmod(tmp, mod); s = n_submod(r2, r1mod, m2); s = n_mulmod2_preinv(s, c, m2, m2inv); fmpz_addmul_ui(tmp, m1, s); if (sign) { fmpz_sub(out, tmp, m1m2); if (fmpz_cmpabs(tmp, out) <= 0) fmpz_swap(out, tmp); } else { fmpz_swap(out, tmp); } fmpz_clear(tmp); } void fmpz_CRT_ui(fmpz_t out, const fmpz_t r1, const fmpz_t m1, ulong r2, ulong m2, int sign) { mp_limb_t c; fmpz_t m1m2; c = fmpz_fdiv_ui(m1, m2); c = n_invmod(c, m2); fmpz_init(m1m2); fmpz_mul_ui(m1m2, m1, m2); _fmpz_CRT_ui_precomp(out, r1, m1, r2, m2, n_preinvert_limb(m2), m1m2, c, sign); fmpz_clear(m1m2); } flint-3.1.3/src/fmpz/abs.c000066400000000000000000000015741461254215100153160ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_abs(fmpz_t f1, const fmpz_t f2) { if (!COEFF_IS_MPZ(*f2)) /* coeff is small */ { fmpz t = FLINT_ABS(*f2); /* Need to save value in case of aliasing */ _fmpz_demote(f1); *f1 = t; } else /* coeff is large */ { /* No need to retain value in promotion, as if aliased, both already large */ __mpz_struct * mf1 = _fmpz_promote(f1); mpz_abs(mf1, COEFF_TO_PTR(*f2)); } } flint-3.1.3/src/fmpz/abs_fits_ui.c000066400000000000000000000011071461254215100170300ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_abs_fits_ui(const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) return 1; return FLINT_ABS(COEFF_TO_PTR(*f)->_mp_size) <= 1; } flint-3.1.3/src/fmpz/abs_lbound_ui_2exp.c000066400000000000000000000032131461254215100203040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" mp_limb_t fmpz_abs_lbound_ui_2exp(slong * exp, const fmpz_t x, int bits) { mp_limb_t m; slong shift, e, size; fmpz c = *x; if (!COEFF_IS_MPZ(c)) { m = FLINT_ABS(c); e = 0; } else { __mpz_struct * z = COEFF_TO_PTR(c); size = z->_mp_size; size = FLINT_ABS(size); e = (size - 1) * FLINT_BITS; if (size == 1) { m = z->_mp_d[0]; } else /* there are two or more limbs */ { /* top limb (which must be nonzero) */ m = z->_mp_d[size - 1]; shift = flint_clz(m); shift = FLINT_BITS - shift - bits; e += shift; if (shift >= 0) { m >>= shift; } else { /* read a second limb to get an accurate value */ mp_limb_t m2 = z->_mp_d[size - 2]; m = (m << (-shift)) | (m2 >> (FLINT_BITS + shift)); } *exp = e; return m; } } shift = flint_clz(m); e += FLINT_BITS - shift - bits; if (e >= 0) m >>= e; else m <<= (-e); *exp = e; return m; } flint-3.1.3/src/fmpz/abs_ubound_ui_2exp.c000066400000000000000000000042601461254215100203200ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" mp_limb_t fmpz_abs_ubound_ui_2exp(slong * exp, const fmpz_t x, int bits) { mp_limb_t m; slong shift, e, size; fmpz c = *x; if (!COEFF_IS_MPZ(c)) { m = FLINT_ABS(c); e = 0; } else { /* mpz */ __mpz_struct * z = COEFF_TO_PTR(c); size = z->_mp_size; size = FLINT_ABS(size); e = (size - 1) * FLINT_BITS; if (size == 1) { m = z->_mp_d[0]; } else /* there are two or more limbs */ { /* top limb (which must be nonzero) */ m = z->_mp_d[size - 1]; shift = flint_clz(m); shift = FLINT_BITS - shift - bits; e += shift; if (shift >= 0) { /* round up */ m = (m >> shift) + 1; } else { /* read a second limb to get an accurate value */ mp_limb_t m2 = z->_mp_d[size - 2]; m = (m << (-shift)) | (m2 >> (FLINT_BITS + shift)); /* round up */ m++; } /* adding 1 caused overflow to the next power of two */ if ((m & (m - UWORD(1))) == UWORD(0)) { m = UWORD(1) << (bits - 1); e++; } *exp = e; return m; } } /* single limb, adjust */ shift = flint_clz(m); e = FLINT_BITS - shift - bits; if (e >= 0) { m = (m >> e) + 1; /* overflowed to next power of two */ if ((m & (m - 1)) == UWORD(0)) { m = UWORD(1) << (bits - 1); e++; } } else { m <<= (-e); } *exp = e; return m; } flint-3.1.3/src/fmpz/add.c000066400000000000000000000035161461254215100152770ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_add(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* both inputs are small */ { fmpz_set_si(f, c1 + c2); } else /* g is small, h is large */ { __mpz_struct * mpz3 = _fmpz_promote(f); /* g is saved and h is large */ __mpz_struct * mpz2 = COEFF_TO_PTR(c2); if (c1 < WORD(0)) flint_mpz_sub_ui(mpz3, mpz2, -c1); else flint_mpz_add_ui(mpz3, mpz2, c1); _fmpz_demote_val(f); /* may have cancelled */ } } else { if (!COEFF_IS_MPZ(c2)) /* g is large, h is small */ { __mpz_struct * mpz3 = _fmpz_promote(f); /* h is saved and g is large */ __mpz_struct * mpz1 = COEFF_TO_PTR(c1); if (c2 < WORD(0)) flint_mpz_sub_ui(mpz3, mpz1, -c2); else flint_mpz_add_ui(mpz3, mpz1, c2); _fmpz_demote_val(f); /* may have cancelled */ } else /* g and h are large */ { __mpz_struct * mpz3 = _fmpz_promote(f); /* aliasing means f is already large */ __mpz_struct * mpz1 = COEFF_TO_PTR(c1); __mpz_struct * mpz2 = COEFF_TO_PTR(c2); mpz_add(mpz3, mpz1, mpz2); _fmpz_demote_val(f); /* may have cancelled */ } } } flint-3.1.3/src/fmpz/addmul.c000066400000000000000000000154611461254215100160170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2021 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "ulong_extras.h" #include "fmpz.h" #define MPZ_FIT_SIZE(z, nlimbs) \ do { \ if (z->_mp_alloc < nlimbs) \ _mpz_realloc(z, nlimbs); \ } while (0) /* Will not get called with x or y small. */ void _flint_mpz_addmul_large(mpz_ptr z, mpz_srcptr x, mpz_srcptr y, int negate) { mp_size_t xn, yn, tn, zn, zn_signed, zn_new, x_sgn, y_sgn, sgn, alloc; mp_srcptr xd, yd; mp_ptr zd; mp_ptr td; mp_limb_t top; TMP_INIT; xn = x->_mp_size; yn = y->_mp_size; x_sgn = xn; y_sgn = yn; xn = FLINT_ABS(xn); yn = FLINT_ABS(yn); if (xn < yn) { mpz_srcptr t; mp_size_t tn; t = x; x = y; y = t; tn = xn; xn = yn; yn = tn; tn = x_sgn; x_sgn = y_sgn; y_sgn = tn; } if (negate) y_sgn = -y_sgn; xd = x->_mp_d; yd = y->_mp_d; /* todo: could inline code for (zn <= 5) + (xn <= 2) x (yn <= 2) */ if (yn == 1) { if (y_sgn >= 0) flint_mpz_addmul_ui(z, x, yd[0]); else flint_mpz_submul_ui(z, x, yd[0]); return; } sgn = x_sgn ^ y_sgn; zn_signed = z->_mp_size; zn = FLINT_ABS(zn_signed); sgn ^= zn_signed; tn = xn + yn; /* Currently unreachable because fmpz_addmul and fmpz_submul both handle z == 0 specially. */ #if 1 FLINT_ASSERT(zn != 0); #else if (zn == 0) { /* Cannot have aliasing here, because x and y are not small and therefore not 0. We can therefore resize z or write to zd without invalidating the inputs. */ FLINT_ASSERT(xn >= 2 || xd[0] > COEFF_MAX); FLINT_ASSERT(yn >= 2 || yd[0] > COEFF_MAX); MPZ_FIT_SIZE(z, tn + 1); zd = z->_mp_d; zn = tn; if (x == y) { flint_mpn_sqr(zd, xd, xn); top = zd[zn - 1]; } else { top = flint_mpn_mul(zd, xd, xn, yd, yn); } zn -= (top == 0); z->_mp_size = (sgn >= 0) ? zn : -zn; return; } #endif TMP_START; td = TMP_ALLOC(tn * sizeof(mp_limb_t)); if (x == y) { flint_mpn_sqr(td, xd, xn); top = td[tn - 1]; } else { top = flint_mpn_mul(td, xd, xn, yd, yn); } tn -= (top == 0); alloc = FLINT_MAX(tn, zn) + 1; MPZ_FIT_SIZE(z, alloc); zd = z->_mp_d; if (sgn >= 0) { if (zn >= tn) { top = mpn_add(zd, zd, zn, td, tn); zn_new = zn; } else { top = mpn_add(zd, td, tn, zd, zn); zn_new = tn; } zd[zn_new] = top; zn_new += (top != 0); } else { if (zn > tn || (zn == tn && mpn_cmp(zd, td, zn) >= 0)) { mpn_sub(zd, zd, zn, td, tn); zn_new = zn; } else { mpn_sub(zd, td, tn, zd, zn); zn_new = tn; zn_signed = -zn_signed; } while (zn_new >= 1 && zd[zn_new - 1] == 0) zn_new--; } z->_mp_size = (zn_signed >= 0) ? zn_new : -zn_new; TMP_END; } void fmpz_addmul(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1, c2, c3; __mpz_struct * mf; c1 = *g; c2 = *h; c3 = *f; /* todo: are the zero checks worth it for small input? */ if (c1 == 0 || c2 == 0) return; if (c3 == 0) { fmpz_mul(f, g, h); return; } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* both are small */ { ulong p1, p0; smul_ppmm(p1, p0, c1, c2); if (!COEFF_IS_MPZ(c3)) { ulong F1 = FLINT_SIGN_EXT(c3); add_ssaaaa(p1, p0, p1, p0, F1, c3); fmpz_set_signed_uiui(f, p1, p0); } else { mpz_ptr pF = COEFF_TO_PTR(c3); flint_mpz_add_signed_uiui(pF, pF, p1, p0); _fmpz_demote_val(f); /* cancellation may have occurred */ } } else { fmpz_addmul_si(f, h, c1); } } else if (!COEFF_IS_MPZ(c2)) /* h is small */ { fmpz_addmul_si(f, g, c2); } else { mf = _fmpz_promote_val(f); _flint_mpz_addmul_large(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2), 0); _fmpz_demote_val(f); /* cancellation may have occurred */ } } void fmpz_addmul_si(fmpz_t f, const fmpz_t g, slong x) { fmpz F, G; G = *g; if (x == 0 || G == 0) return; F = *f; if (F == 0) { fmpz_mul_si(f, g, x); return; } if (!COEFF_IS_MPZ(G)) { ulong p1, p0; smul_ppmm(p1, p0, G, x); if (!COEFF_IS_MPZ(F)) { ulong F1 = FLINT_SIGN_EXT(F); add_ssaaaa(p1, p0, p1, p0, F1, F); fmpz_set_signed_uiui(f, p1, p0); } else { mpz_ptr pF = COEFF_TO_PTR(F); flint_mpz_add_signed_uiui(pF, pF, p1, p0); _fmpz_demote_val(f); } } else { mpz_ptr pG = COEFF_TO_PTR(G); mpz_ptr pF = _fmpz_promote_val(f); if (x < 0) flint_mpz_submul_ui(pF, pG, -x); else flint_mpz_addmul_ui(pF, pG, x); _fmpz_demote_val(f); } } void fmpz_addmul_ui(fmpz_t f, const fmpz_t g, ulong x) { fmpz F, G; G = *g; if (x == 0 || G == 0) return; F = *f; if (F == 0) { fmpz_mul_ui(f, g, x); return; } if (!COEFF_IS_MPZ(G)) { ulong p1, p0; if (x <= WORD_MAX) { smul_ppmm(p1, p0, G, x); } else { umul_ppmm(p1, p0, FLINT_ABS(G), x); if (G < 0) { p1 = -p1 - (p0 != 0); p0 = -p0; } } if (!COEFF_IS_MPZ(F)) { ulong F1 = FLINT_SIGN_EXT(F); add_ssaaaa(p1, p0, p1, p0, F1, F); fmpz_set_signed_uiui(f, p1, p0); } else { mpz_ptr pF = COEFF_TO_PTR(F); flint_mpz_add_signed_uiui(pF, pF, p1, p0); _fmpz_demote_val(f); } } else { mpz_ptr pG = COEFF_TO_PTR(G); mpz_ptr pF = _fmpz_promote_val(f); flint_mpz_addmul_ui(pF, pG, x); _fmpz_demote_val(f); } } flint-3.1.3/src/fmpz/aors_ui.c000066400000000000000000000136631461254215100162140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2022 Albin Ahlbäck Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "fmpz.h" #define VARIANT 1 void fmpz_add_ui(fmpz_t res, const fmpz_t x, ulong y) { if (!COEFF_IS_MPZ(*x)) { slong a = *x; if (y <= COEFF_MAX) /* likely case */ { #if VARIANT slong b = a + y; if (b <= COEFF_MAX) { if (COEFF_IS_MPZ(*res)) _fmpz_clear_mpz(*res); *res = b; } else { __mpz_struct * mpz_res = _fmpz_promote(res); flint_mpz_set_si(mpz_res, b); } #else fmpz_set_si(res, a + (slong) y); #endif } else { if (a < 0) /* opposite signs, and y > |a|, so no borrow */ fmpz_set_ui(res, y + a); else fmpz_set_uiui(res, ((ulong) a + y) < y, (ulong) a + y); } } else { mpz_ptr rp; mpz_srcptr xp; mp_ptr rd; mp_srcptr xd; mp_size_t xn_signed, xn; mp_limb_t cy; xp = COEFF_TO_PTR(*x); xn_signed = xp->_mp_size; xn = FLINT_ABS(xn_signed); if (COEFF_IS_MPZ(*res)) rp = COEFF_TO_PTR(*res); else rp = _fmpz_promote_val(res); if (rp->_mp_alloc < xn + 1) _mpz_realloc(rp, xn + 1); rd = rp->_mp_d; xd = xp->_mp_d; if (xn_signed >= 0) /* positive + nonnegative */ { rd[xn] = cy = mpn_add_1(rd, xd, xn, y); rp->_mp_size = xn + (cy != 0); } else if (xn >= 2) /* negative + nonnegative; result cannot be 0 */ { mpn_sub_1(rd, xd, xn, y); xn -= (rd[xn - 1] == 0); rp->_mp_size = -xn; if (xn == 1 && rd[0] <= COEFF_MAX) /* possible demotion */ { cy = rd[0]; _fmpz_clear_mpz(*res); *res = -(slong) cy; } } else { /* 1 limb, different signs; possible sign change and possible demotion */ ulong a = xd[0]; if (y >= a) { if (y - a <= COEFF_MAX) { _fmpz_clear_mpz(*res); *res = y - a; } else { rd[0] = y - a; rp->_mp_size = 1; } } else { if (a - y <= COEFF_MAX) { _fmpz_clear_mpz(*res); *res = -(slong) (a - y); } else { rd[0] = a - y; rp->_mp_size = -1; } } } } } void fmpz_sub_ui(fmpz_t res, const fmpz_t x, ulong y) { if (!COEFF_IS_MPZ(*x)) { slong a = *x; if (y <= COEFF_MAX) { #if VARIANT slong b = a - y; if (b >= COEFF_MIN) { if (COEFF_IS_MPZ(*res)) _fmpz_clear_mpz(*res); *res = b; } else { __mpz_struct * mpz_res = _fmpz_promote(res); flint_mpz_set_si(mpz_res, b); } #else fmpz_set_si(res, a - (slong) y); #endif } else { if (a > 0) /* opposite signs, and y > |a|, so no borrow */ fmpz_neg_ui(res, y - a); else fmpz_neg_uiui(res, ((ulong) (-a) + y) < y, (ulong) (-a) + y); } } else { mpz_ptr rp; mpz_srcptr xp; mp_ptr rd; mp_srcptr xd; mp_size_t xn_signed, xn; mp_limb_t cy; xp = COEFF_TO_PTR(*x); xn_signed = xp->_mp_size; xn = FLINT_ABS(xn_signed); if (COEFF_IS_MPZ(*res)) rp = COEFF_TO_PTR(*res); else rp = _fmpz_promote_val(res); if (rp->_mp_alloc < xn + 1) _mpz_realloc(rp, xn + 1); rd = rp->_mp_d; xd = xp->_mp_d; if (xn_signed <= 0) /* positive + nonnegative */ { rd[xn] = cy = mpn_add_1(rd, xd, xn, y); rp->_mp_size = -(xn + (cy != 0)); } else if (xn >= 2) /* negative + nonnegative; result cannot be 0 */ { mpn_sub_1(rd, xd, xn, y); xn -= (rd[xn - 1] == 0); rp->_mp_size = xn; if (xn == 1 && rd[0] <= COEFF_MAX) /* possible demotion */ { cy = rd[0]; _fmpz_clear_mpz(*res); *res = (slong) cy; } } else { /* 1 limb, different signs; possible sign change and possible demotion */ ulong a = xd[0]; if (y >= a) { if (y - a <= COEFF_MAX) { _fmpz_clear_mpz(*res); *res = -(slong) (y - a); } else { rd[0] = y - a; rp->_mp_size = -1; } } else { if (a - y <= COEFF_MAX) { _fmpz_clear_mpz(*res); *res = a - y; } else { rd[0] = a - y; rp->_mp_size = 1; } } } } } flint-3.1.3/src/fmpz/bin_uiui.c000066400000000000000000000012241461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" /* TODO: speedup for small n,k */ void fmpz_bin_uiui(fmpz_t res, ulong n, ulong k) { __mpz_struct * t = _fmpz_promote(res); flint_mpz_bin_uiui(t, n, k); _fmpz_demote_val(res); } flint-3.1.3/src/fmpz/bit_pack.c000066400000000000000000000115141461254215100163200ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" int fmpz_bit_pack(mp_ptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits, const fmpz_t coeff, int negate, int borrow) { mp_limb_t save = arr[0]; fmpz c = *coeff; int sign = fmpz_sgn(coeff); mp_limb_t cy; ulong limbs = (shift + bits) / FLINT_BITS; ulong rem_bits = (shift + bits) % FLINT_BITS; mp_limb_t mask; ulong size; if (sign == 0) /* special case, deal with zero (store -borrow) */ { if (borrow) { /* store -1 shifted and add save back in */ arr[0] = ((~(mp_limb_t) 0) << shift) + save; /* com remaining limbs */ if (limbs > 1) flint_mpn_store(arr + 1, limbs - 1, ~(mp_limb_t) 0); /* com remaining bits */ if (limbs) { if (rem_bits) arr[limbs] = (((mp_limb_t) 1) << rem_bits) - (mp_limb_t) 1; } else { /* mask off final limb */ mask = (((mp_limb_t) 1) << rem_bits) - (mp_limb_t) 1; arr[limbs] &= mask; } } return borrow; } /* Let |c| = b. If c is -ve and negate == 0 or c is positive and negate is 1 we want -b - borrow. If c is +ve and negate is 0 or c is negative and negate == 1, we want b - borrow. */ if ((sign ^ negate) < 0) /* -b - borrow = com(b) + 1 - borrow */ { if (!COEFF_IS_MPZ(c)) { /* compute d = -b - borrow */ mp_limb_t d = (c < WORD(0) ? c - borrow : -c - borrow); /* store d << shift and add save back into place */ arr[0] = (d << shift) + save; /* store carry from d<> (FLINT_BITS - shift)) + ((~(mp_limb_t) 0) << shift); else arr[1] = ~(mp_limb_t) 0; } size = 2; } else { __mpz_struct * ptr = COEFF_TO_PTR(c); size = FLINT_ABS(ptr->_mp_size); /* complement coefficient into arr */ mpn_com(arr, ptr->_mp_d, size); /* deal with +1 - borrow */ if (!borrow) mpn_add_1(arr, arr, size, 1); /* cannot be a carry, else we com'd 0 */ /* shift into place */ if (shift) { cy = mpn_lshift(arr, arr, size, shift); if (limbs + (rem_bits != 0) > size) arr[size++] = ((~(mp_limb_t) 0) << shift) + cy; } /* add back in saved bits from start of field */ arr[0] += save; } if (limbs >= size) { /* com any additional limbs */ if (limbs > size) flint_mpn_store(arr + size, limbs - size, ~(mp_limb_t) 0); /* com remaining bits */ if (rem_bits) arr[limbs] = (((mp_limb_t) 1) << rem_bits) - (mp_limb_t) 1; } else { /* mask off final limb */ mask = (((mp_limb_t) 1) << rem_bits) - (mp_limb_t) 1; arr[limbs] &= mask; } return 1; } else /* b - borrow */ { if (!COEFF_IS_MPZ(c)) { /* compute d = b - borrow */ mp_limb_t d = (c < WORD(0) ? -c - borrow : c - borrow); /* store d< 1) { if (shift) arr[1] = (d >> (FLINT_BITS - shift)); } } else { __mpz_struct *ptr = COEFF_TO_PTR(c); size = FLINT_ABS(ptr->_mp_size); /* shift into place */ if (shift) { cy = mpn_lshift(arr, ptr->_mp_d, size, shift); if (cy) arr[size++] = cy; } else flint_mpn_copyi(arr, ptr->_mp_d, size); /* deal with - borrow */ if (borrow) mpn_sub_1(arr, arr, size, ((mp_limb_t) 1) << shift); /* add back in saved bits from start of field */ arr[0] += save; } return 0; } } flint-3.1.3/src/fmpz/bit_unpack.c000066400000000000000000000131441461254215100166640ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" int fmpz_bit_unpack(fmpz_t coeff, mp_srcptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits, int negate, int borrow) { mp_limb_t mask, sign; ulong limbs = (shift + bits) / FLINT_BITS; ulong rem_bits = (shift + bits) % FLINT_BITS; /* determine if field is positive or negative */ if (rem_bits) sign = ((((mp_limb_t) 1) << (rem_bits - 1)) & arr[limbs]); else sign = ((((mp_limb_t) 1) << (FLINT_BITS - 1)) & arr[limbs - 1]); if (bits <= SMALL_FMPZ_BITCOUNT_MAX) /* fits into a small coeff */ { _fmpz_demote(coeff); /* mask for the given number of bits */ mask = (((mp_limb_t) 1) << bits) - (mp_limb_t) 1; if (limbs + (rem_bits != 0) > 1) /* field crosses a limb boundary */ (*coeff) = ((arr[0] >> shift) + (arr[1] << (FLINT_BITS - shift))) & mask; else /* field is in first limb only, mask it */ (*coeff) = (arr[0] >> shift) & mask; /* sign extend */ if (sign) (*coeff) += ((~(mp_limb_t) 0) << bits); /* determine whether we need to return a borrow */ sign = (*coeff < (mp_limb_signed_t) 0 ? (mp_limb_t) 1 : (mp_limb_t) 0); /* deal with borrow */ if (borrow) { (*coeff)++; if ((*coeff) > COEFF_MAX) { fmpz v = *coeff; *coeff = 0; fmpz_set_ui(coeff, v); } } /* negate the coeff if necessary */ if (negate) fmpz_neg(coeff, coeff); return (sign != (mp_limb_t) 0); } else /* large coefficient */ { __mpz_struct * mcoeff; mp_limb_t * p; ulong l, b; mcoeff = _fmpz_promote(coeff); /* the number of limbs to hold the bitfield _including_ b extra bits */ l = (bits - 1) / FLINT_BITS + 1; b = bits % FLINT_BITS; /* allocate space for l limbs only */ mpz_realloc(mcoeff, l); p = mcoeff->_mp_d; /* shift in l limbs */ if (shift) mpn_rshift(p, arr, l, shift); else flint_mpn_copyi(p, arr, l); /* shift in any rem_bits that weren't already shifted */ if (limbs + (rem_bits != 0) > l) p[l - 1] += (arr[limbs] << (FLINT_BITS - shift)); /* mask off the last limb, if not full */ if (b) { mask = (((mp_limb_t) 1) << b) - (mp_limb_t) 1; p[l - 1] &= mask; } if (sign != (mp_limb_t) 0) { /* sign extend */ if (b) p[l - 1] += ((~(mp_limb_t) 0) << b); /* negate */ mpn_com(p, p, l); if (!borrow) mpn_add_1(p, p, l, 1); /* normalise */ while (l && (p[l - 1] == (mp_limb_t) 0)) l--; mcoeff->_mp_size = -l; sign = 1; } else { /* deal with borrow */ if (borrow) mpn_add_1(p, p, l, 1); /* normalise */ while (l && (p[l - 1] == (mp_limb_t) 0)) l--; mcoeff->_mp_size = l; sign = 0; } /* negate if required */ if (negate) mpz_neg(mcoeff, mcoeff); /* coeff may fit in a small */ _fmpz_demote_val(coeff); return sign; } } void fmpz_bit_unpack_unsigned(fmpz_t coeff, mp_srcptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits) { ulong limbs = (shift + bits) / FLINT_BITS; ulong rem_bits = (shift + bits) % FLINT_BITS; mp_limb_t mask; if (bits <= SMALL_FMPZ_BITCOUNT_MAX) /* fits into a small coeff */ { _fmpz_demote(coeff); /* mask for the given number of bits */ mask = (((mp_limb_t) 1) << bits) - (mp_limb_t) 1; if (limbs + (rem_bits != 0) > 1) /* field crosses a limb boundary */ (*coeff) = ((arr[0] >> shift) + (arr[1] << (FLINT_BITS - shift))) & mask; else /* field is in first limb only, mask it */ (*coeff) = (arr[0] >> shift) & mask; } else /* large coefficient */ { __mpz_struct * mcoeff; mp_limb_t * p; ulong l, b; mcoeff = _fmpz_promote(coeff); /* the number of limbs to hold the bitfield _including_ b extra bits */ l = (bits - 1) / FLINT_BITS + 1; b = bits % FLINT_BITS; /* allocate space for l limbs only */ mpz_realloc(mcoeff, l); p = mcoeff->_mp_d; /* shift in l limbs */ if (shift) mpn_rshift(p, arr, l, shift); else flint_mpn_copyi(p, arr, l); /* shift in any rem_bits that weren't already shifted */ if (limbs + (rem_bits != 0) > l) p[l - 1] += (arr[limbs] << (FLINT_BITS - shift)); /* mask off the last limb, if not full */ if (b) { mask = (((mp_limb_t) 1) << b) - (mp_limb_t) 1; p[l - 1] &= mask; } /* normalise */ while (l && (p[l - 1] == (mp_limb_t) 0)) l--; mcoeff->_mp_size = l; /* coeff may fit in a small */ _fmpz_demote_val(coeff); } } flint-3.1.3/src/fmpz/bits.c000066400000000000000000000011551461254215100155050ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" flint_bitcnt_t fmpz_bits(const fmpz_t f) { fmpz d = *f; if (!COEFF_IS_MPZ(d)) return FLINT_BIT_COUNT(FLINT_ABS(d)); else return mpz_sizeinbase(COEFF_TO_PTR(d), 2); } flint-3.1.3/src/fmpz/cdiv.c000066400000000000000000000212441461254215100154720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" void fmpz_cdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) { fmpz d = *g; if (!COEFF_IS_MPZ(d)) /* g is small */ { fmpz_set_si(f, -((-d) >> FLINT_MIN(exp, SMALL_FMPZ_BITCOUNT_MAX))); } else /*g is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ mpz_cdiv_q_2exp(mf, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } void fmpz_cdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_cdiv_q). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if (r && ((c2 ^ r) > WORD(0))) /* r != 0, c2 and r same sign */ ++q; fmpz_set_si(f, q); } else /* h is large and g is small */ { if ((c1 < WORD(0) && fmpz_sgn(h) < 0) || (c1 > WORD(0) && fmpz_sgn(h) > 0)) /* signs are the same */ fmpz_one(f); /* quotient is positive, round up to one */ else fmpz_zero(f); /* quotient is zero, or negative, round up to zero */ } } else /* g is large */ { __mpz_struct * mf; if (!COEFF_IS_MPZ(c2)) /* h is small */ { mf = _fmpz_promote(f); if (c2 > 0) /* h > 0 */ { flint_mpz_cdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_fdiv_q_ui(mf, COEFF_TO_PTR(c1), -c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_cdiv_q_newton(f, g, h); } else { mf = _fmpz_promote(f); mpz_cdiv_q(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ } } } } void fmpz_cdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_cdiv_q). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ /* rounding of division is undefined, but it should satisfy: */ FLINT_ASSERT(FLINT_ABS(r) < FLINT_ABS(c2)); if ((c2 > WORD(0) && r > WORD(0)) || (c2 < WORD(0) && r < WORD(0))) { q += 1; /* q cannot overflow as remainder implies |c2| != 1 */ r -= c2; } fmpz_set_si(f, q); fmpz_set_si(s, r); } else /* h is large and g is small */ { int sgn_h = fmpz_sgn(h); if ((c1 < WORD(0) && sgn_h < 0) || (c1 > WORD(0) && sgn_h > 0)) /* signs are the same */ { fmpz_sub(s, g, h); fmpz_one(f); /* quotient > 0, round up to 1 */ } else { fmpz_set_si(s, c1); fmpz_zero(f); /* quotient <= 0, round up to 0 */ } } } else /* g is large */ { __mpz_struct * mf, * ms; if (!COEFF_IS_MPZ(c2)) /* h is small */ { _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ ms = _fmpz_promote(s); mf = COEFF_TO_PTR(*f); if (c2 > 0) /* h > 0 */ { flint_mpz_cdiv_qr_ui(mf, ms, COEFF_TO_PTR(c1), c2); } else { flint_mpz_fdiv_qr_ui(mf, ms, COEFF_TO_PTR(c1), -c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_cdiv_qr_newton(f, s, g, h); } else { _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ ms = _fmpz_promote(s); mf = COEFF_TO_PTR(*f); mpz_cdiv_qr(mf, ms, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } } } } void fmpz_cdiv_q_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; slong c2 = h; if (h == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_cdiv_q_si). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if (r && ((c1 ^ c2) > WORD(0))) ++q; fmpz_set_si(f, q); } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); if (c2 > 0) { flint_mpz_cdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_fdiv_q_ui(mf, COEFF_TO_PTR(c1), -(ulong) c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ } } void fmpz_cdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; ulong c2 = h; if (h == 0) { flint_throw(FLINT_ERROR, "Exception: division by zero in fmpz_cdiv_q_ui\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 > 0) { ulong q = c1 / c2; ulong r = c1 - c2 * q; if (r) ++q; fmpz_set_ui(f, q); } else { fmpz_set_si(f, - (((ulong) -c1) / c2)); } } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); flint_mpz_cdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } } void fmpz_cdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp) { fmpz d = *g; if (!COEFF_IS_MPZ(d)) /* g is small */ { if (d <= 0) { d = -d; fmpz_neg_ui(f, exp < (SMALL_FMPZ_BITCOUNT_MAX) ? d & ((WORD(1) << exp) - 1) : d); } else { if (exp <= SMALL_FMPZ_BITCOUNT_MAX) { fmpz_neg_ui(f, (-d) & ((WORD(1) << exp) - 1)); } else { __mpz_struct * mf = _fmpz_promote(f); flint_mpz_set_ui(mf, 1); mpz_mul_2exp(mf, mf, exp); flint_mpz_sub_ui(mf, mf, d); mpz_neg(mf, mf); } } } else /*g is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ mpz_cdiv_r_2exp(mf, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } ulong fmpz_cdiv_ui(const fmpz_t g, ulong h) { fmpz c1 = *g; ulong r; if (h == UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_cdiv_ui). Division by 0.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 >= WORD(1)) r = h - 1 - ((c1 - WORD(1)) % h); else r = (-c1) % h; return r; } else /* g is large */ { return flint_mpz_cdiv_ui(COEFF_TO_PTR(c1), h); } } flint-3.1.3/src/fmpz/clear_readonly.c000066400000000000000000000011541461254215100175260ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" void fmpz_clear_readonly(fmpz_t f) { if (COEFF_IS_MPZ(*f)) { __mpz_struct *ptr = COEFF_TO_PTR(*f); mpz_init(ptr); _fmpz_clear_mpz(*f); *f = WORD(0); } } flint-3.1.3/src/fmpz/clog.c000066400000000000000000000042631461254215100154730ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "ulong_extras.h" slong fmpz_clog(const fmpz_t n, const fmpz_t b) { fmpz_t t; int sign; slong r; if (fmpz_is_one(n)) return 0; if (!COEFF_IS_MPZ(*b)) return fmpz_clog_ui(n, *b); if (fmpz_cmp(n, b) <= 0) return 1; r = fmpz_dlog(n) / fmpz_dlog(b); fmpz_init(t); fmpz_pow_ui(t, b, r); sign = fmpz_cmp(t, n); /* Adjust down */ if (sign > 0) { while (sign > 0) { fmpz_divexact(t, t, b); sign = fmpz_cmp(t, n); r--; } r += (sign != 0); } /* Adjust up */ else if (sign < 0) { while (sign < 0) { fmpz_mul(t, t, b); sign = fmpz_cmp(t, n); r++; } } fmpz_clear(t); return r; } slong fmpz_clog_ui(const fmpz_t n, ulong b) { fmpz_t t; int sign; slong r; if (fmpz_is_one(n)) return 0; if (b == 2) { fmpz_init(t); fmpz_sub_ui(t, n, 1); r = fmpz_bits(t); fmpz_clear(t); return r; } if (!COEFF_IS_MPZ(*n)) return n_clog(*n, b); if (fmpz_cmp_ui(n, b) <= 0) return 1; r = fmpz_dlog(n) / log(b); fmpz_init(t); fmpz_set_ui(t, b); fmpz_pow_ui(t, t, r); sign = fmpz_cmp(t, n); /* Adjust down */ if (sign > 0) { while (sign > 0) { fmpz_divexact_ui(t, t, b); sign = fmpz_cmp(t, n); r--; } r += (sign != 0); } /* Adjust up */ else if (sign < 0) { while (sign < 0) { fmpz_mul_ui(t, t, b); sign = fmpz_cmp(t, n); r++; } } fmpz_clear(t); return r; } flint-3.1.3/src/fmpz/cmp.c000066400000000000000000000076571461254215100153400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "fmpz.h" static int flint_mpn_cmp2abs(mp_srcptr x, slong xn, mp_srcptr a, slong an) { mp_limb_t xhi, ahi; FLINT_ASSERT(an >= 0); FLINT_ASSERT(xn >= 0); FLINT_ASSERT(xn == 0 || x[xn - 1] != 0); FLINT_ASSERT(an == 0 || a[an - 1] != 0); if (an > xn) return -1; if (an + 1 < xn) return 1; xhi = an == xn ? 0 : x[an]; ahi = 0; while (an > 0) { ahi = MPN_LEFT_SHIFT_HI(ahi, a[an - 1], 1); if (xhi != ahi) return xhi > ahi ? 1 : -1; ahi = a[an - 1]; xhi = x[an - 1]; an--; } ahi = MPN_LEFT_SHIFT_HI(ahi, UWORD(0), 1); if (xhi != ahi) return xhi > ahi ? 1 : -1; return 0; } /* compare |a| and 2|b| */ int fmpz_cmp2abs(const fmpz_t a, const fmpz_t b) { if (!COEFF_IS_MPZ(*b)) { mp_limb_t ub = FLINT_ABS(*b); if (!COEFF_IS_MPZ(*a)) { mp_limb_t ua = FLINT_ABS(*a); return ua < 2*ub ? -1 : ua > 2*ub ? 1 : 0; } else { return flint_mpn_cmp2abs(COEFF_TO_PTR(*a)->_mp_d, FLINT_ABS(COEFF_TO_PTR(*a)->_mp_size), &ub, ub != 0); } } else { if (!COEFF_IS_MPZ(*a)) { return -1; } else { return flint_mpn_cmp2abs(COEFF_TO_PTR(*a)->_mp_d, FLINT_ABS(COEFF_TO_PTR(*a)->_mp_size), COEFF_TO_PTR(*b)->_mp_d, FLINT_ABS(COEFF_TO_PTR(*b)->_mp_size)); } } } int fmpz_cmpabs(const fmpz_t f, const fmpz_t g) { if (f == g) return 0; /* aliased inputs */ if (!COEFF_IS_MPZ(*f)) { if (!COEFF_IS_MPZ(*g)) { mp_limb_t uf = FLINT_ABS(*f); mp_limb_t ug = FLINT_ABS(*g); return (uf < ug ? -1 : (uf > ug)); } else return -1; } else { if (!COEFF_IS_MPZ(*g)) return 1; /* f is large, so if g isn't... */ else return mpz_cmpabs(COEFF_TO_PTR(*f), COEFF_TO_PTR(*g)); } } int fmpz_cmp(const fmpz_t f, const fmpz_t g) { int sign; if (f == g) return 0; /* aliased inputs */ if (!COEFF_IS_MPZ(*f)) { if (!COEFF_IS_MPZ(*g)) { return (*f < *g ? -1 : *f > *g); } else /* f is small, g is large */ { sign = mpz_sgn(COEFF_TO_PTR(*g)); return (*f >= 0 && sign < 0) ? 1 : -sign; } } else { if (!COEFF_IS_MPZ(*g)) /* f is large, and g is small */ { sign = mpz_sgn(COEFF_TO_PTR(*f)); return (*g >= 0 && sign < 0) ? -1 : sign; } else return mpz_cmp(COEFF_TO_PTR(*f), COEFF_TO_PTR(*g)); } } int fmpz_cmp_si(const fmpz_t f, slong g) { fmpz c = *f; if (!COEFF_IS_MPZ(c)) /* f is small */ return c < g ? -1 : c > g; else /* f is large */ return flint_mpz_cmp_si(COEFF_TO_PTR(c), g); } int fmpz_cmp_ui(const fmpz_t f, ulong g) { fmpz c = *f; if (!COEFF_IS_MPZ(c)) /* f is small */ { if (c < WORD(0) || g > COEFF_MAX) return -1; else return c < (slong) g ? -1 : c > (slong) g; } else /* f is large */ return flint_mpz_cmp_ui(COEFF_TO_PTR(c), g); } flint-3.1.3/src/fmpz/comb_clear.c000066400000000000000000000016411461254215100166320ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" void fmpz_comb_temp_clear(fmpz_comb_temp_t CT) { _fmpz_vec_clear(CT->A, CT->Alen); _fmpz_vec_clear(CT->T, CT->Tlen); } void fmpz_comb_clear(fmpz_comb_t C) { flint_free(C->step); flint_free(C->packed_multipliers); flint_free(C->crt_lu); flint_free(C->mod_lu); flint_free(C->crt_offsets); flint_free(C->mod_offsets); fmpz_multi_CRT_clear(C->crt_P); fmpz_multi_mod_clear(C->mod_P); } flint-3.1.3/src/fmpz/comb_init.c000066400000000000000000000254571461254215100165220ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* The better mpn_addmul_1 is, the larger FMPZ_CRT_UI_CUTOFF can be. */ #define FMPZ_CRT_UI_CUTOFF 50 /* The better fmpz_get_nmod (mpn_mod_1) is, the larger FMPZ_MOD_UI_CUTOFF can be. Very poor implementations of mpn_mod_1 can have 10, and anything up to 100 is reasonable. ]*/ #define FMPZ_MOD_UI_CUTOFF 75 /* minimal number of basecase chunks in which to partition */ #define FMPZ_CRT_UI_MULTIPLE_CUTOFF 4 #define FMPZ_MOD_UI_MULTIPLE_CUTOFF 4 void fmpz_comb_temp_init(fmpz_comb_temp_t CT, const fmpz_comb_t C) { CT->Alen = FLINT_MAX(C->crt_klen, C->mod_klen); CT->Tlen = FLINT_MAX(C->crt_P->localsize, C->mod_P->localsize); CT->A = _fmpz_vec_init(CT->Alen); CT->T = _fmpz_vec_init(CT->Tlen); } void fmpz_comb_init(fmpz_comb_t C, mp_srcptr m, slong len) { int success; slong l, i, j, k, s; ulong tt, mm, mt; fmpz_poly_t M, Mm; /* only used for resizable fmpz array convenience */ if (len < 1) flint_throw(FLINT_ERROR, "fmpz_comb_init: len should be positive"); fmpz_poly_init(Mm); fmpz_poly_init(M); fmpz_multi_CRT_init(C->crt_P); C->packed_multipliers = NULL; C->step = NULL; C->crt_lu = NULL; C->crt_lu_alloc = 0; C->crt_offsets = NULL; C->crt_offsets_alloc = 0; fmpz_multi_mod_init(C->mod_P); C->mod_lu = NULL; C->mod_lu_alloc = 0; C->mod_offsets = NULL; C->mod_offsets_alloc = 0; C->num_primes = len; /* set up crt */ for (l = 0, i = 0, k = 0; l < len; k++) { if (k + 1 >= C->crt_offsets_alloc) { C->crt_offsets_alloc = FLINT_MAX(k + 1, C->crt_offsets_alloc*3/2); C->crt_offsets = FLINT_ARRAY_REALLOC(C->crt_offsets, C->crt_offsets_alloc, slong); } fmpz_poly_fit_length(M, k + 1); fmpz_one(M->coeffs + k); for (j = i; l < len && fmpz_size(M->coeffs + k) <= FMPZ_CRT_UI_CUTOFF; j++) { if (j + 1 >= C->crt_lu_alloc) { C->crt_lu_alloc = FLINT_MAX(j + 1, C->crt_lu_alloc*3/2); C->crt_lu = FLINT_ARRAY_REALLOC(C->crt_lu, C->crt_lu_alloc, crt_lut_entry); } C->crt_lu[j].i0 = 0; C->crt_lu[j].i1 = 0; C->crt_lu[j].i2 = 0; mm = m[l]; if (l + 1 < len && !n_mul_checked(&mt, mm, m[l+1])) { mm = mt; if (l + 2 < len && !n_mul_checked(&mt, mm, m[l+2])) { mm = mt; success = (1 == n_gcdinv(&C->crt_lu[j].i0, m[l+1]*m[l+2] % m[l+0], m[l+0])) && (1 == n_gcdinv(&C->crt_lu[j].i1, m[l+0]*m[l+2] % m[l+1], m[l+1])) && (1 == n_gcdinv(&C->crt_lu[j].i2, m[l+0]*m[l+1] % m[l+2], m[l+2])); if (!success) goto bad_moduli; C->crt_lu[j].i0 *= m[l+1]*m[l+2]; C->crt_lu[j].i1 *= m[l+0]*m[l+2]; C->crt_lu[j].i2 *= m[l+0]*m[l+1]; l += 3; } else { success = (1 == n_gcdinv(&C->crt_lu[j].i0, m[l+1] % m[l+0], m[l+0])) && (1 == n_gcdinv(&C->crt_lu[j].i1, m[l+0] % m[l+1], m[l+1])); if (!success) goto bad_moduli; C->crt_lu[j].i0 *= m[l+1]; C->crt_lu[j].i1 *= m[l+0]; l += 2; } } else { C->crt_lu[j].i0 = 1; l += 1; } nmod_init(&C->crt_lu[j].mod, mm); fmpz_mul_ui(M->coeffs + k, M->coeffs + k, C->crt_lu[j].mod.n); } C->crt_offsets[k] = j; fmpz_poly_fit_length(Mm, j); for ( ; i < j; i++) { fmpz_divexact_ui(Mm->coeffs + i, M->coeffs + k, C->crt_lu[i].mod.n); tt = fmpz_get_nmod(Mm->coeffs + i, C->crt_lu[i].mod); success = (1 == n_gcdinv(&tt, tt, C->crt_lu[i].mod.n)); if (!success) goto bad_moduli; C->crt_lu[i].i0 = nmod_mul(tt, C->crt_lu[i].i0, C->crt_lu[i].mod); C->crt_lu[i].i1 = nmod_mul(tt, C->crt_lu[i].i1, C->crt_lu[i].mod); C->crt_lu[i].i2 = nmod_mul(tt, C->crt_lu[i].i2, C->crt_lu[i].mod); } } /* avoid small last chunk and have at least FMPZ_CRT_UI_MULTIPLE_CUTOFF chunks or one big chunk */ while (k > 1 && (k < FMPZ_CRT_UI_MULTIPLE_CUTOFF || fmpz_size(M->coeffs + k - 1) <= FMPZ_CRT_UI_CUTOFF*3/4)) { k--; for (i = (k >= 2) ? C->crt_offsets[k - 2] : 0; i < C->crt_offsets[k]; i++) { int last = (i >= C->crt_offsets[k - 1]); fmpz_mul(Mm->coeffs + i, Mm->coeffs + i, M->coeffs + k - last); tt = fmpz_get_nmod(M->coeffs + k - last, C->crt_lu[i].mod); success = (1 == n_gcdinv(&tt, tt, C->crt_lu[i].mod.n)); if (!success) goto bad_moduli; C->crt_lu[i].i0 = nmod_mul(tt, C->crt_lu[i].i0, C->crt_lu[i].mod); C->crt_lu[i].i1 = nmod_mul(tt, C->crt_lu[i].i1, C->crt_lu[i].mod); C->crt_lu[i].i2 = nmod_mul(tt, C->crt_lu[i].i2, C->crt_lu[i].mod); } C->crt_offsets[k - 1] = C->crt_offsets[k]; fmpz_mul(M->coeffs + k - 1, M->coeffs + k - 1, M->coeffs + k); } C->crt_klen = k; success = fmpz_multi_CRT_precompute(C->crt_P, M->coeffs, C->crt_klen); if (!success) goto bad_moduli; C->step = FLINT_ARRAY_ALLOC(C->crt_klen, slong); l = 0; for (k = 0, i = 0; k < C->crt_klen; k++) { int all_large = 1; s = 1; for (j = i; j < C->crt_offsets[k]; j++) { if (C->crt_lu[j].i1 != 0 || C->crt_lu[j].i2 != 0) all_large = 0; FLINT_ASSERT(fmpz_cmp(Mm->coeffs + j, M->coeffs + k) <= 0); s = FLINT_MAX(s, fmpz_size(Mm->coeffs + j)); } if (all_large) { s = 1; for (j = i; j < C->crt_offsets[k]; j++) { FLINT_ASSERT(C->crt_lu[i].i1 == 0 && C->crt_lu[i].i2 == 0); fmpz_mul_ui(Mm->coeffs + j, Mm->coeffs + j, C->crt_lu[j].i0); s = FLINT_MAX(s, fmpz_size(Mm->coeffs + j)); } C->step[k] = -s - 1; } else { C->step[k] = s; } for ( ; i < C->crt_offsets[k]; i++) { l += s; } } C->packed_multipliers = FLINT_ARRAY_ALLOC(l, mp_limb_t); l = 0; for (k = 0, i = 0; k < C->crt_klen; k++) { s = C->step[k]; if (s < 0) s = -s - 1; for ( ; i < C->crt_offsets[k]; i++) { fmpz_get_ui_array(C->packed_multipliers + l, s, Mm->coeffs + i); l += s; } } /* set up mod */ for (l = 0, i = 0, k = 0; l < len; k++) { if (k + 1 >= C->mod_offsets_alloc) { C->mod_offsets_alloc = FLINT_MAX(k + 1, C->mod_offsets_alloc*3/2); C->mod_offsets = FLINT_ARRAY_REALLOC(C->mod_offsets, C->mod_offsets_alloc, slong); } fmpz_poly_fit_length(M, k + 1); fmpz_one(M->coeffs + k); for (j = i; l < len && fmpz_size(M->coeffs + k) <= FMPZ_MOD_UI_CUTOFF; j++) { if (j + 1 >= C->mod_lu_alloc) { C->mod_lu_alloc = FLINT_MAX(j + 1, C->mod_lu_alloc*3/2); C->mod_lu = FLINT_ARRAY_REALLOC(C->mod_lu, C->mod_lu_alloc, mod_lut_entry); } C->mod_lu[j].mod0.n = 0; C->mod_lu[j].mod1.n = 0; C->mod_lu[j].mod2.n = 0; mm = m[l]; if (l + 1 < len && !n_mul_checked(&mt, mm, m[l+1])) { mm = mt; if (l + 2 < len && !n_mul_checked(&mt, mm, m[l+2])) { mm = mt; success = (m[l+0] != 0) && (m[l+1] != 0) && (m[l+2] != 0); if (!success) goto zero_moduli; nmod_init(&C->mod_lu[j].mod0, m[l+0]); nmod_init(&C->mod_lu[j].mod1, m[l+1]); nmod_init(&C->mod_lu[j].mod2, m[l+2]); l += 3; } else { success = (m[l+0] != 0) && (m[l+1] != 0); if (!success) goto zero_moduli; nmod_init(&C->mod_lu[j].mod0, m[l+0]); nmod_init(&C->mod_lu[j].mod1, m[l+1]); l += 2; } } else { success = (m[l+0] != 0); if (!success) goto zero_moduli; nmod_init(&C->mod_lu[j].mod0, m[l+0]); l += 1; } nmod_init(&C->mod_lu[j].mod, mm); fmpz_mul_ui(M->coeffs + k, M->coeffs + k, C->mod_lu[j].mod.n); } C->mod_offsets[k] = j; i = j; } /* avoid small last chunk and have at least FMPZ_MOD_UI_MULTIPLE_CUTOFF chunks or one big chunk */ while (k > 1 && (k < FMPZ_MOD_UI_MULTIPLE_CUTOFF || fmpz_size(M->coeffs + k - 1) < FMPZ_MOD_UI_CUTOFF*3/4)) { k--; C->mod_offsets[k - 1] = C->mod_offsets[k]; fmpz_mul(M->coeffs + k - 1, M->coeffs + k - 1, M->coeffs + k); } C->mod_klen = k; success = fmpz_multi_mod_precompute(C->mod_P, M->coeffs, C->mod_klen); if (!success) goto zero_moduli; fmpz_poly_clear(M); fmpz_poly_clear(Mm); return; bad_moduli: flint_throw(FLINT_ERROR, "fmpz_comb_init: moduli are not pairwise prime"); zero_moduli: flint_throw(FLINT_ERROR, "fmpz_comb_init: moduli are not nonzero"); } flint-3.1.3/src/fmpz/div_newton.c000066400000000000000000000166021461254215100167230ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" /* The underlying approximate division is implemented in arb/div.c. One day this should have mpn code. */ void _arb_fmpz_divapprox_newton(fmpz_t res, const fmpz_t x, const fmpz_t y, slong exp); #if 1 #define TEST_PERTURBATION #elif 0 #define TEST_PERTURBATION fmpz_add_ui(q, q, 1); #else #define TEST_PERTURBATION fmpz_sub_ui(q, q, 1); #endif static void fmpz_addmul_sgn(fmpz_t res, const fmpz_t a, const fmpz_t b, int sgn) { if (sgn == 1) fmpz_add(res, a, b); else fmpz_sub(res, a, b); } static ulong _fmpz_can_round(const fmpz_t x) { fmpz f = *x; ulong c; if (!COEFF_IS_MPZ(f)) c = FLINT_ABS(f); else c = COEFF_TO_PTR(f)->_mp_d[0]; return c > 2 && c < UWORD_MAX - 2; } static void _fmpz_tdiv_qr_correction(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { while (fmpz_sgn(r) < 0) { fmpz_addmul_sgn(r, r, b, fmpz_sgn(b)); fmpz_sub_si(q, q, fmpz_sgn(b)); } while (fmpz_cmpabs(r, b) >= 0) { fmpz_addmul_sgn(r, r, b, -fmpz_sgn(b)); fmpz_add_si(q, q, fmpz_sgn(b)); } if (!fmpz_is_zero(r) && fmpz_sgn(a) < 0) { fmpz_add_si(q, q, fmpz_sgn(b)); fmpz_addmul_sgn(r, r, b, -fmpz_sgn(b)); } } static void _fmpz_fdiv_qr_correction(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { while (fmpz_sgn(r) < 0) { fmpz_addmul_sgn(r, r, b, fmpz_sgn(b)); fmpz_sub_si(q, q, fmpz_sgn(b)); } while (fmpz_cmpabs(r, b) >= 0) { fmpz_addmul_sgn(r, r, b, -fmpz_sgn(b)); fmpz_add_si(q, q, fmpz_sgn(b)); } if (!fmpz_is_zero(r) && fmpz_sgn(b) != fmpz_sgn(r)) { fmpz_addmul_sgn(r, r, b, -fmpz_sgn(b)); fmpz_add_si(q, q, fmpz_sgn(b)); } } static void _fmpz_cdiv_qr_correction(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { while (fmpz_sgn(r) > 0) { fmpz_addmul_sgn(r, r, b, -fmpz_sgn(b)); fmpz_add_si(q, q, fmpz_sgn(b)); } while (fmpz_sgn(r) < 0 && fmpz_cmpabs(r, b) >= 0) { fmpz_addmul_sgn(r, r, b, fmpz_sgn(b)); fmpz_sub_si(q, q, fmpz_sgn(b)); } if (!fmpz_is_zero(r) && fmpz_sgn(b) < 0) { fmpz_add_ui(q, q, 1); fmpz_sub(r, r, b); } } void _fmpz_tdiv_q_newton(fmpz_t q, const fmpz_t a, const fmpz_t b) { if (q == a || q == b) { fmpz_t t; fmpz_init(t); _fmpz_tdiv_q_newton(t, a, b); fmpz_swap(q, t); fmpz_clear(t); return; } _arb_fmpz_divapprox_newton(q, a, b, FLINT_BITS); TEST_PERTURBATION if (_fmpz_can_round(q)) { fmpz_tdiv_q_2exp(q, q, FLINT_BITS); } else { fmpz_t r; fmpz_init(r); fmpz_tdiv_q_2exp(q, q, FLINT_BITS); fmpz_mul(r, q, b); fmpz_sub(r, a, r); _fmpz_tdiv_qr_correction(q, r, a, b); fmpz_clear(r); } } void _fmpz_fdiv_q_newton(fmpz_t q, const fmpz_t a, const fmpz_t b) { if (q == a || q == b) { fmpz_t t; fmpz_init(t); _fmpz_fdiv_q_newton(t, a, b); fmpz_swap(q, t); fmpz_clear(t); return; } _arb_fmpz_divapprox_newton(q, a, b, FLINT_BITS); TEST_PERTURBATION if (_fmpz_can_round(q)) { fmpz_fdiv_q_2exp(q, q, FLINT_BITS); } else { fmpz_t r; fmpz_init(r); fmpz_fdiv_q_2exp(q, q, FLINT_BITS); fmpz_mul(r, q, b); fmpz_sub(r, a, r); _fmpz_fdiv_qr_correction(q, r, a, b); fmpz_clear(r); } } void _fmpz_cdiv_q_newton(fmpz_t q, const fmpz_t a, const fmpz_t b) { if (q == a || q == b) { fmpz_t t; fmpz_init(t); _fmpz_cdiv_q_newton(t, a, b); fmpz_swap(q, t); fmpz_clear(t); return; } _arb_fmpz_divapprox_newton(q, a, b, FLINT_BITS); TEST_PERTURBATION if (_fmpz_can_round(q)) { fmpz_cdiv_q_2exp(q, q, FLINT_BITS); } else { fmpz_t r; fmpz_init(r); fmpz_cdiv_q_2exp(q, q, FLINT_BITS); fmpz_mul(r, q, b); fmpz_sub(r, a, r); _fmpz_cdiv_qr_correction(q, r, a, b); fmpz_clear(r); } } void _fmpz_fdiv_qr_newton(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { if (q == NULL || q == a || q == b) { fmpz_t t; fmpz_init(t); _fmpz_fdiv_qr_newton(t, r, a, b); if (q != NULL) fmpz_swap(q, t); fmpz_clear(t); return; } if (r == a || r == b) { fmpz_t t; fmpz_init(t); _fmpz_fdiv_qr_newton(q, t, a, b); fmpz_swap(r, t); fmpz_clear(t); return; } _arb_fmpz_divapprox_newton(q, a, b, 0); TEST_PERTURBATION fmpz_mul(r, q, b); fmpz_sub(r, a, r); _fmpz_fdiv_qr_correction(q, r, a, b); } void _fmpz_cdiv_qr_newton(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { if (q == NULL || q == a || q == b) { fmpz_t t; fmpz_init(t); _fmpz_cdiv_qr_newton(t, r, a, b); if (q != NULL) fmpz_swap(q, t); fmpz_clear(t); return; } if (r == a || r == b) { fmpz_t t; fmpz_init(t); _fmpz_cdiv_qr_newton(q, t, a, b); fmpz_swap(r, t); fmpz_clear(t); return; } _arb_fmpz_divapprox_newton(q, a, b, 0); TEST_PERTURBATION fmpz_mul(r, q, b); fmpz_sub(r, a, r); _fmpz_cdiv_qr_correction(q, r, a, b); } void _fmpz_tdiv_qr_newton(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { if (q == NULL || q == a || q == b) { fmpz_t t; fmpz_init(t); _fmpz_tdiv_qr_newton(t, r, a, b); if (q != NULL) fmpz_swap(q, t); fmpz_clear(t); return; } if (r == a || r == b) { fmpz_t t; fmpz_init(t); _fmpz_tdiv_qr_newton(q, t, a, b); fmpz_swap(r, t); fmpz_clear(t); return; } _arb_fmpz_divapprox_newton(q, a, b, 0); TEST_PERTURBATION fmpz_mul(r, q, b); fmpz_sub(r, a, r); _fmpz_tdiv_qr_correction(q, r, a, b); } void _fmpz_tdiv_r_newton(fmpz_t r, const fmpz_t a, const fmpz_t b) { _fmpz_tdiv_qr_newton(NULL, r, a, b); } void _fmpz_fdiv_r_newton(fmpz_t r, const fmpz_t a, const fmpz_t b) { _fmpz_fdiv_qr_newton(NULL, r, a, b); } void _fmpz_cdiv_r_newton(fmpz_t r, const fmpz_t a, const fmpz_t b) { _fmpz_cdiv_qr_newton(NULL, r, a, b); } void _fmpz_mod_newton(fmpz_t r, const fmpz_t a, const fmpz_t b) { fmpz_t q; fmpz_init(q); if (r == a || r == b) { fmpz_t t; fmpz_init(t); _fmpz_mod_newton(t, a, b); fmpz_swap(r, t); fmpz_clear(t); return; } _arb_fmpz_divapprox_newton(q, a, b, 0); TEST_PERTURBATION fmpz_mul(r, q, b); fmpz_sub(r, a, r); if (fmpz_sgn(b) > 0) _fmpz_fdiv_qr_correction(q, r, a, b); else _fmpz_cdiv_qr_correction(q, r, a, b); fmpz_clear(q); } void _fmpz_divexact_newton(fmpz_t q, const fmpz_t a, const fmpz_t b) { _arb_fmpz_divapprox_newton(q, a, b, 0); } flint-3.1.3/src/fmpz/divexact.c000066400000000000000000000057561461254215100163660ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" void fmpz_divexact(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_divexact). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small, h must be also or division isn't exact */ { fmpz_set_si(f, c1 / c2); } else /* g is large */ { __mpz_struct * mf; if (!COEFF_IS_MPZ(c2)) /* h is small */ { mf = _fmpz_promote(f); if (c2 > 0) /* h > 0 */ { flint_mpz_divexact_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_divexact_ui(mf, COEFF_TO_PTR(c1), -c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_divexact_newton(f, g, h); } else { mf = _fmpz_promote(f); mpz_divexact(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ } } } } void fmpz_divexact_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; if (h == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_divexact_si). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_set_si(f, c1 / h); } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); if (h > 0) { flint_mpz_divexact_ui(mf, COEFF_TO_PTR(c1), h); _fmpz_demote_val(f); /* division by h may result in small value */ } else { flint_mpz_divexact_ui(mf, COEFF_TO_PTR(c1), -h); _fmpz_demote_val(f); /* division by h may result in small value */ fmpz_neg(f, f); } } } void fmpz_divexact_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; if (h == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_divexact_ui). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_set_si(f, c1 / (slong) h); } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); flint_mpz_divexact_ui(mf, COEFF_TO_PTR(c1), h); _fmpz_demote_val(f); /* division by h may result in small value */ } } flint-3.1.3/src/fmpz/divides.c000066400000000000000000000043341461254215100161750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_divides(fmpz_t q, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; int res, negate = 0; if (fmpz_is_zero(h)) { res = fmpz_is_zero(g); fmpz_zero(q); return res; } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { mp_limb_t qz; if (c1 < 0) { c1 = -c1; negate ^= 1; } if (c2 < 0) { c2 = -c2; negate ^= 1; } res = n_divides(&qz, c1, c2); fmpz_set_ui(q, qz); if (negate) fmpz_neg(q, q); return res; } else /* h is large and g is small */ { res = fmpz_is_zero(g); fmpz_zero(q); return res; } } else /* g is large */ { __mpz_struct * mq; if (!COEFF_IS_MPZ(c2)) /* h is small */ { mp_limb_t r; mq = _fmpz_promote(q); if (c2 < 0) { c2 = -c2; negate ^= 1; } r = flint_mpz_tdiv_q_ui(mq, COEFF_TO_PTR(c1), c2); res = (r == 0); if (negate) mpz_neg(mq, mq); if (!res) mpz_set_ui(mq, 0); _fmpz_demote_val(q); } else /* both are large */ { fmpz_t r; fmpz_init(r); fmpz_tdiv_qr(q, r, g, h); res = fmpz_is_zero(r); if (!res) fmpz_zero(q); fmpz_clear(r); } return res; } } flint-3.1.3/src/fmpz/divides_mod_list.c000066400000000000000000000026341461254215100200700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" /* The solutions for x in a*x + b*y = c && 0 <= x < b will be precisely {xstart + xstride*i | 0 <= i < xlength } */ void fmpz_divides_mod_list(fmpz_t xstart, fmpz_t xstride, fmpz_t xlength, const fmpz_t c, const fmpz_t a, const fmpz_t b) { fmpz_t d, x, q, r, bbar; fmpz_init(d); fmpz_init(x); fmpz_init(q); fmpz_init(r); fmpz_init(bbar); FLINT_ASSERT(fmpz_sgn(b) > 0); fmpz_mod(r, a, b); fmpz_gcdinv(d, x, r, b); fmpz_fdiv_qr(q, r, c, d); if (fmpz_is_zero(r)) { fmpz_divexact(bbar, b, d); fmpz_mul(x, x, q); fmpz_fdiv_q(r, x, bbar); fmpz_submul(x, bbar, r); fmpz_swap(xlength, d); fmpz_swap(xstride, bbar); fmpz_swap(xstart, x); } else { fmpz_zero(xstart); fmpz_zero(xstride); fmpz_zero(xlength); } fmpz_clear(d); fmpz_clear(x); fmpz_clear(q); fmpz_clear(r); fmpz_clear(bbar); } flint-3.1.3/src/fmpz/divisible.c000066400000000000000000000024601461254215100165160ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2022, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" int fmpz_divisible_ui(const fmpz_t f, ulong g) { if (*f == WORD(0)) return 1; if (!COEFF_IS_MPZ(*f)) { ulong fa = FLINT_ABS(*f); return !(fa % g); } else return flint_mpz_divisible_ui_p(COEFF_TO_PTR(*f), g); } int fmpz_divisible(const fmpz_t x, const fmpz_t p) { fmpz y = *x; fmpz q = *p; if (y == WORD(0)) return 1; if (q == WORD(0)) return 0; if (!COEFF_IS_MPZ(y)) { if (!COEFF_IS_MPZ(q)) { return !(y % q); } else { return 0; } } else { if (!COEFF_IS_MPZ(q)) { return flint_mpz_divisible_ui_p(COEFF_TO_PTR(y), FLINT_ABS(q)); } else { return mpz_divisible_p(COEFF_TO_PTR(y), COEFF_TO_PTR(q)); } } } flint-3.1.3/src/fmpz/divisor_in_residue_class_lenstra.c000066400000000000000000000124001461254215100233410ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" int fmpz_divisor_in_residue_class_lenstra(fmpz_t fac, const fmpz_t n, const fmpz_t r, const fmpz_t s) { fmpz_t r1, r2, a0, a1, b0, b1, c0, c1, q, d, d1, s1, s2, ns2; slong i; int res = 0; fmpz_init(r1); fmpz_init(r2); fmpz_init(a0); fmpz_init(a1); fmpz_init(b0); fmpz_init(b1); fmpz_init(c0); fmpz_init(c1); fmpz_init(q); fmpz_init(d); fmpz_init(d1); fmpz_init(s1); fmpz_init(s2); fmpz_init(ns2); /* ns2 = n/s^2 */ fmpz_mul(ns2, s, s); fmpz_tdiv_q(ns2, n, ns2); /* initialise */ fmpz_invmod(r1, r, s); /* r1 = r^-1 mod s */ fmpz_mul(r2, r1, n); fmpz_mod(r2, r2, s); /* r2 = r1*n mod s */ fmpz_set(a0, s); /* a0 = s */ fmpz_mul(a1, r1, r2); /* a1 = r1*r2 mod s */ fmpz_mod(a1, a1, s); if (fmpz_is_zero(a1)) fmpz_add(a1, a1, s); /* 0 < a1 <= s */ fmpz_zero(b0); fmpz_one(b1); fmpz_zero(c0); fmpz_mul(c1, r, r2); /* c1 = (n - r*r2)/s * r1 mod s */ fmpz_sub(c1, n, c1); fmpz_divexact(c1, c1, s); fmpz_mul(c1, c1, r1); fmpz_mod(c1, c1, s); /* deal with a0, b0, c0 */ if (!fmpz_is_one(r) && !fmpz_equal(n, r) && fmpz_divisible(n, r)) { fmpz_set(fac, r); res = 1; goto cleanup; } for (i = 1; ; i++) { if ((i & 1) == 0) { fmpz_mod(s1, c1, s); fmpz_neg(s2, s); } else { fmpz_mul(s2, a1, b1); /* s2 = a1*b1 */ fmpz_add(s1, s2, ns2); /* s1 = a1*b1 + n/s^2 */ fmpz_mod(q, s1, s); /* s1 largest integer < a1*b1 + n/s^2 congruent to c1 mod s */ if (fmpz_cmp(q, c1) < 0) fmpz_sub(s1, s1, s); fmpz_sub(s1, s1, q); fmpz_add(s1, s1, c1); fmpz_add(s2, s2, s2); /* s2 = 2*a1*b1 - 1 */ fmpz_sub_ui(s2, s2, 1); } while (fmpz_cmp(s1, s2) > 0) /* for each value s1 in range */ { fmpz_mul(d, s, s1); /* d = (s1*s + a1*r + b1*r2)^2 - 4*a1*b1*n */ fmpz_addmul(d, a1, r); fmpz_addmul(d, b1, r2); fmpz_set(d1, d); /* d1 = s1*s + a1*r + b1*r2 */ fmpz_mul(d, d, d); fmpz_mul(q, a1, b1); fmpz_mul(q, q, n); fmpz_submul_ui(d, q, 4); if (fmpz_is_square(d)) /* divisor exists, roots are (d1 +/- sqrt(d))/2 */ { fmpz_sqrt(d, d); fmpz_add(d, d, d1); fmpz_tdiv_q_2exp(d, d, 1); if (fmpz_is_zero(a1)) { fmpz_tdiv_q(fac, s1, b1); /* y*b1 = s1 */ fmpz_mul(fac, fac, s); /* check if ys + r2 is factor */ fmpz_add(fac, fac, r2); fmpz_abs(fac, fac); if (!fmpz_is_zero(fac) && !fmpz_is_one(fac) && !fmpz_equal(fac, n) && fmpz_divisible(n, fac)) { res = 1; break; } } else if (fmpz_is_zero(b1)) { fmpz_tdiv_q(fac, s1, a1); /* x*a1 = s1 */ fmpz_mul(fac, fac, s); /* check if xs + r is factor */ fmpz_add(fac, fac, r); fmpz_abs(fac, fac); if (!fmpz_is_zero(fac) && !fmpz_is_one(fac) && !fmpz_equal(fac, n) && fmpz_divisible(n, fac)) { res = 1; break; } } else { /* either d/a1 or d/b1 is a divisor of n */ fmpz_tdiv_q(fac, d, a1); fmpz_abs(fac, fac); if (!fmpz_is_zero(fac) && !fmpz_is_one(fac) && !fmpz_equal(fac, n) && fmpz_divisible(n, fac)) { res = 1; break; } fmpz_tdiv_q(fac, d, b1); fmpz_abs(fac, fac); if (!fmpz_is_zero(fac) && !fmpz_is_one(fac) && !fmpz_equal(fac, n) && fmpz_divisible(n, fac)) { res = 1; break; } } } fmpz_sub(s1, s1, s); } if (fmpz_is_zero(a1) || res == 1) /* Euclidean chain has terminated */ break; /* Euclidean chain: a1, a0 = a0 - q*a1, a1, where 0 <= a1 < a0 for i even and 0 < a1 <= a0 for i odd */ fmpz_tdiv_qr(q, a0, a0, a1); if ((i & 1) == 0 && fmpz_is_zero(a0)) { fmpz_sub_ui(q, q, 1); fmpz_add(a0, a0, a1); } fmpz_swap(a0, a1); /* b1, b0 = b0 - q*b1, b1 */ fmpz_submul(b0, q, b1); fmpz_swap(b0, b1); /* c1, c0 = c0 - q*c1, c1 mod s */ fmpz_submul(c0, q, c1); fmpz_mod(c0, c0, s); fmpz_swap(c0, c1); } cleanup: fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(a0); fmpz_clear(a1); fmpz_clear(b0); fmpz_clear(b1); fmpz_clear(c0); fmpz_clear(c1); fmpz_clear(q); fmpz_clear(d); fmpz_clear(d1); fmpz_clear(s1); fmpz_clear(s2); fmpz_clear(ns2); return res; } flint-3.1.3/src/fmpz/divisor_sigma.c000066400000000000000000000027561461254215100174130ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" void fmpz_factor_divisor_sigma(fmpz_t res, ulong k, const fmpz_factor_t fac) { slong i; fmpz_one(res); if (fac->num == 0) return; if (k == 0) { for (i = 0; i < fac->num; i++) fmpz_mul_ui(res, res, fac->exp[i] + 1); } else { fmpz * p; fmpz_t r; p = _fmpz_vec_init(fac->num); fmpz_init(r); for (i = 0; i < fac->num; i++) { fmpz_pow_ui(p + i, fac->p + i, k); fmpz_pow_ui(r, p + i, fac->exp[i] + 1); fmpz_sub_ui(r, r, 1); fmpz_sub_ui(p + i, p + i, 1); fmpz_divexact(p + i, r, p + i); } _fmpz_vec_prod(res, p, fac->num); _fmpz_vec_clear(p, fac->num); fmpz_clear(r); } } void fmpz_divisor_sigma(fmpz_t res, ulong k, const fmpz_t n) { fmpz_factor_t fac; if (fmpz_is_zero(n)) { fmpz_zero(res); return; } fmpz_factor_init(fac); fmpz_factor(fac, n); fmpz_factor_divisor_sigma(res, k, fac); fmpz_factor_clear(fac); } flint-3.1.3/src/fmpz/dlog.c000066400000000000000000000012471461254215100154730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" double fmpz_dlog(const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) { return log(*x); } else { double s; long e; s = mpz_get_d_2exp(&e, COEFF_TO_PTR(*x)); return log(s) + e * 0.69314718055994530942; } } flint-3.1.3/src/fmpz/equal.c000066400000000000000000000022341461254215100156520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" int fmpz_equal(const fmpz_t f, const fmpz_t g) { if (f == g) return 1; /* aliased inputs */ if (!COEFF_IS_MPZ(*f)) return (*f == *g); /* if f is large it can't be equal to g */ else if (!COEFF_IS_MPZ(*g)) return 0; /* f is large, so if g isn't... */ else return (mpz_cmp(COEFF_TO_PTR(*f), COEFF_TO_PTR(*g)) == 0); } int fmpz_equal_si(const fmpz_t f, slong g) { fmpz c = *f; return !COEFF_IS_MPZ(c) ? (c == g) : !flint_mpz_cmp_si(COEFF_TO_PTR(c), g); } int fmpz_equal_ui(const fmpz_t f, ulong g) { fmpz c = *f; return !COEFF_IS_MPZ(c) ? ((c >= 0) & (c == g)) : !flint_mpz_cmp_ui(COEFF_TO_PTR(c), g); } flint-3.1.3/src/fmpz/euler_phi.c000066400000000000000000000023461461254215100165230ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" void fmpz_factor_euler_phi(fmpz_t res, const fmpz_factor_t fac) { fmpz_t t; slong i; fmpz_init(t); fmpz_one(res); for (i = 0; i < fac->num; i++) { fmpz_sub_ui(t, fac->p + i, 1); fmpz_mul(res, res, t); if (fac->exp[i] != 1) { fmpz_pow_ui(t, fac->p + i, fac->exp[i] - 1); fmpz_mul(res, res, t); } } fmpz_clear(t); } void fmpz_euler_phi(fmpz_t res, const fmpz_t n) { fmpz_factor_t fac; if (fmpz_sgn(n) <= 0) { fmpz_zero(res); return; } if (fmpz_abs_fits_ui(n)) { fmpz_set_ui(res, n_euler_phi(fmpz_get_ui(n))); return; } fmpz_factor_init(fac); fmpz_factor(fac, n); fmpz_factor_euler_phi(res, fac); fmpz_factor_clear(fac); } flint-3.1.3/src/fmpz/fac_ui.c000066400000000000000000000022441461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" #if FLINT64 #define FLINT_NUM_TINY_FACTORIALS 21 #else #define FLINT_NUM_TINY_FACTORIALS 13 #endif const mp_limb_t flint_tiny_factorials[] = { UWORD(1), UWORD(1), UWORD(2), UWORD(6), UWORD(24), UWORD(120), UWORD(720), UWORD(5040), UWORD(40320), UWORD(362880), UWORD(3628800), UWORD(39916800), UWORD(479001600), #if FLINT64 UWORD(6227020800), UWORD(87178291200), UWORD(1307674368000), UWORD(20922789888000), UWORD(355687428096000), UWORD(6402373705728000), UWORD(121645100408832000), UWORD(2432902008176640000), #endif }; void fmpz_fac_ui(fmpz_t f, ulong n) { if (n < FLINT_NUM_TINY_FACTORIALS) fmpz_set_ui(f, flint_tiny_factorials[n]); else flint_mpz_fac_ui(_fmpz_promote(f), n); } flint-3.1.3/src/fmpz/fdiv.c000066400000000000000000000372161461254215100155030ustar00rootroot00000000000000/* Copyright 1991, 1993-1996, 2000, 2001, 2005 Free Software Foundation, Inc. Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "fmpz.h" void fmpz_fdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) { fmpz d = *g; if (!COEFF_IS_MPZ(d)) /* g is small */ { fmpz_set_si(f, d>>FLINT_MIN(exp, SMALL_FMPZ_BITCOUNT_MAX)); } else /*g is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ mpz_fdiv_q_2exp(mf, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_fdiv_q). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if (r && (c2 ^ r) < WORD(0)) --q; fmpz_set_si(f, q); } else /* h is large and g is small */ { if ((c1 > WORD(0) && fmpz_sgn(h) < 0) || (c1 < WORD(0) && fmpz_sgn(h) > 0)) /* signs are the same */ fmpz_set_si(f, WORD(-1)); /* quotient is negative, round down to minus one */ else fmpz_zero(f); } } else /* g is large */ { __mpz_struct * mf; if (!COEFF_IS_MPZ(c2)) /* h is small */ { mf = _fmpz_promote(f); if (c2 > 0) /* h > 0 */ { flint_mpz_fdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_q_ui(mf, COEFF_TO_PTR(c1), -c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_fdiv_q_newton(f, g, h); } else { mf = _fmpz_promote(f); mpz_fdiv_q(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ } } } } void fmpz_fdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_fdiv_q). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if ((c2 > WORD(0) && r < WORD(0)) || (c2 < WORD(0) && r > WORD(0))) { q--; /* q cannot overflow as remainder implies |c2| != 1 */ r += c2; } fmpz_set_si(f, q); fmpz_set_si(s, r); } else /* h is large and g is small */ { if (c1 == WORD(0)) { fmpz_set_ui(f, WORD(0)); /* g is zero */ fmpz_set_si(s, c1); } else if ((c1 < WORD(0) && fmpz_sgn(h) < 0) || (c1 > WORD(0) && fmpz_sgn(h) > 0)) /* signs are the same */ { fmpz_zero(f); /* quotient is positive, round down to zero */ fmpz_set_si(s, c1); } else { fmpz_add(s, g, h); fmpz_set_si(f, WORD(-1)); /* quotient is negative, round down to minus one */ } } } else /* g is large */ { __mpz_struct * mf, * ms; if (!COEFF_IS_MPZ(c2)) /* h is small */ { _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ ms = _fmpz_promote(s); mf = COEFF_TO_PTR(*f); if (c2 > 0) /* h > 0 */ { flint_mpz_fdiv_qr_ui(mf, ms, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_qr_ui(mf, ms, COEFF_TO_PTR(c1), -c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_fdiv_qr_newton(f, s, g, h); } else { _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ ms = _fmpz_promote(s); mf = COEFF_TO_PTR(*f); mpz_fdiv_qr(mf, ms, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } } } } /* these functions were adapted from similar functions in an old version of GMP */ void _mpz_tdiv_qr_preinvn(mpz_ptr q, mpz_ptr r, mpz_srcptr a, mpz_srcptr d, const fmpz_preinvn_t inv) { slong size1 = a->_mp_size, size2 = d->_mp_size; ulong usize1 = FLINT_ABS(size1); ulong usize2 = FLINT_ABS(size2); ulong qsize = usize1 - usize2 + 1; int nm = (inv->norm != 0); TMP_INIT; mp_ptr qp, rp, ap, dp, tp, sp; if (r->_mp_alloc < usize1 + nm) mpz_realloc2(r, (usize1 + nm)*FLINT_BITS); if (usize1 < usize2) /* special case preinv code can't deal with */ { mpz_set(r, a); /* remainder equals numerator */ q->_mp_size = 0; /* quotient is zero */ return; } if (q->_mp_alloc < qsize + nm) mpz_realloc2(q, (qsize + nm)*FLINT_BITS); dp = d->_mp_d; ap = a->_mp_d; qp = q->_mp_d; rp = r->_mp_d; TMP_START; if ((r == d || q == d) && !nm) /* we have alias with d */ { tp = TMP_ALLOC(usize2*FLINT_BITS); mpn_copyi(tp, dp, usize2); dp = tp; } if (r == a || q == a) /* we have alias with a */ { tp = TMP_ALLOC(usize1*FLINT_BITS); mpn_copyi(tp, ap, usize1); ap = tp; } /* TODO: speedup mpir's mullow and mulhigh and use in flint_mpn_divrem_preinvn so we can remove this first case here */ if (usize2 == 2 || (usize2 > 15 && usize2 < 120)) mpn_tdiv_qr(qp, rp, 0, ap, usize1, dp, usize2); else { if (nm) { tp = TMP_ALLOC(usize2*FLINT_BITS); mpn_lshift(tp, dp, usize2, inv->norm); dp = tp; rp[usize1] = mpn_lshift(rp, ap, usize1, inv->norm); if (rp[usize1] != 0) usize1++, qsize++; sp = rp; } else sp = ap; qp[qsize - 1] = flint_mpn_divrem_preinvn(qp, rp, sp, usize1, dp, usize2, inv->dinv); if (nm) mpn_rshift(rp, rp, usize2, inv->norm); } qsize -= (qp[qsize - 1] == 0); MPN_NORM(rp, usize2); q->_mp_size = ((size1 ^ size2) < 0 ? -qsize : qsize); r->_mp_size = (size1 < 0 ? -usize2 : usize2); TMP_END; } void _mpz_fdiv_qr_preinvn(mpz_ptr q, mpz_ptr r, mpz_srcptr a, mpz_srcptr d, const fmpz_preinvn_t inv) { slong size1 = a->_mp_size; slong size2 = d->_mp_size; ulong usize2 = FLINT_ABS(size2); mpz_t t; TMP_INIT; TMP_START; if (q == d || r == d) /* we need d later, so make sure it doesn't alias */ { t->_mp_d = TMP_ALLOC(usize2*FLINT_BITS); t->_mp_size = d->_mp_size; t->_mp_alloc = d->_mp_alloc; mpn_copyi(t->_mp_d, d->_mp_d, usize2); d = t; } _mpz_tdiv_qr_preinvn(q, r, a, d, inv); if ((size1 ^ size2) < 0 && r->_mp_size != 0) { flint_mpz_sub_ui(q, q, 1); mpz_add(r, r, d); } TMP_END; } void fmpz_fdiv_qr_preinvn(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h, const fmpz_preinvn_t inv) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_fdiv_q). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ fmpz_fdiv_qr(f, s, g, h); else /* h is large and g is small */ { if (c1 == WORD(0)) { fmpz_set_ui(f, WORD(0)); /* g is zero */ fmpz_set_si(s, c1); } else if ((c1 < WORD(0) && fmpz_sgn(h) < 0) || (c1 > WORD(0) && fmpz_sgn(h) > 0)) /* signs are the same */ { fmpz_zero(f); /* quotient is positive, round down to zero */ fmpz_set_si(s, c1); } else { fmpz_add(s, g, h); fmpz_set_si(f, WORD(-1)); /* quotient is negative, round down to minus one */ } } } else /* g is large */ { __mpz_struct * mf, * ms; if (!COEFF_IS_MPZ(c2)) /* h is small */ fmpz_fdiv_qr(f, s, g, h); else { _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ ms = _fmpz_promote(s); mf = COEFF_TO_PTR(*f); _mpz_fdiv_qr_preinvn(mf, ms, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2), inv); _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } } } /* todo: avoid the temporary variable */ void fmpz_fdiv_r_preinvn(fmpz_t f, const fmpz_t g, const fmpz_t h, const fmpz_preinvn_t inv) { fmpz_t q; fmpz_init(q); fmpz_fdiv_qr_preinvn(q, f, g, h, inv); fmpz_clear(q); } void fmpz_fdiv_q_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; slong c2 = h; if (h == 0) { flint_throw(FLINT_ERROR, "Exception (fmpq_fdiv_q_si). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if (r && ((c1 ^ c2) < 0)) --q; fmpz_set_si(f, q); } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); if (c2 > 0) { flint_mpz_fdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_q_ui(mf, COEFF_TO_PTR(c1), -(ulong) c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ } } void fmpz_fdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; ulong c2 = h; if (h == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_fdiv_q_ui). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 > 0) { fmpz_set_ui(f, c1 / c2); } else { ulong q = ((ulong) -c1) / c2; ulong r = ((ulong) -c1) - c2 * q; if (r) ++q; fmpz_set_si(f, - (slong) q); } } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); flint_mpz_fdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } } void fmpz_fdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp) { fmpz d = *g; if (!COEFF_IS_MPZ(d)) /* g is small */ { if (d >= 0) { fmpz_set_ui(f, exp < (SMALL_FMPZ_BITCOUNT_MAX) ? d & ((WORD(1) << exp) - 1) : d); } else { if (exp <= SMALL_FMPZ_BITCOUNT_MAX) { fmpz_set_ui(f, d & ((WORD(1) << exp) - 1)); } else { __mpz_struct * mf = _fmpz_promote(f); flint_mpz_set_ui(mf, 1); mpz_mul_2exp(mf, mf, exp); flint_mpz_sub_ui(mf, mf, -d); } } } else /*g is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ mpz_fdiv_r_2exp(mf, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } void fmpz_fdiv_r(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_fdiv_r). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if ((c2 > WORD(0) && r < WORD(0)) || (c2 < WORD(0) && r > WORD(0))) r += c2; fmpz_set_si(f, r); } else /* h is large and g is small */ { if (c1 == WORD(0)) { fmpz_set_si(f, c1); } else if ((c1 < WORD(0) && fmpz_sgn(h) < 0) || (c1 > WORD(0) && fmpz_sgn(h) > 0)) /* signs are the same */ { fmpz_set_si(f, c1); } else { fmpz_add(f, g, h); } } } else /* g is large */ { __mpz_struct * mf; if (!COEFF_IS_MPZ(c2)) /* h is small */ { /* todo: should not create an mpz */ mf = _fmpz_promote(f); if (c2 > 0) /* h > 0 */ { flint_mpz_fdiv_r_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_r_ui(mf, COEFF_TO_PTR(c1), -c2); } _fmpz_demote_val(f); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_fdiv_r_newton(f, g, h); } else { mf = _fmpz_promote(f); mpz_fdiv_r(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ } } } } ulong fmpz_fdiv_ui(const fmpz_t g, ulong h) { fmpz c1 = *g; ulong r; if (h == UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_fdiv_ui). Division by 0.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 < WORD(0)) { r = h - (-c1 % h); /* C doesn't correctly handle negative mods */ if (r == h) r = 0; } else r = c1 % h; return r; } else /* g is large */ { return flint_mpz_fdiv_ui(COEFF_TO_PTR(c1), h); } } flint-3.1.3/src/fmpz/fib_ui.c000066400000000000000000000053561461254215100160100ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" #if FLINT64 #define NUM_SMALL_FIB 94 #define NUM_SMALL_FIB2 184 #else #define NUM_SMALL_FIB 48 #define NUM_SMALL_FIB2 92 #endif static const mp_limb_t small_fib[NUM_SMALL_FIB] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, UWORD(2971215073), #if FLINT64 UWORD(4807526976), UWORD(7778742049), UWORD(12586269025), UWORD(20365011074), UWORD(32951280099), UWORD(53316291173), UWORD(86267571272), UWORD(139583862445), UWORD(225851433717), UWORD(365435296162), UWORD(591286729879), UWORD(956722026041), 1548008755920, UWORD(2504730781961), UWORD(4052739537881), UWORD(6557470319842), 10610209857723, UWORD(17167680177565), UWORD(27777890035288), UWORD(44945570212853), 72723460248141, UWORD(117669030460994), UWORD(190392490709135), UWORD(308061521170129), 498454011879264, UWORD(806515533049393), UWORD(1304969544928657), UWORD(2111485077978050), UWORD(3416454622906707), UWORD(5527939700884757), UWORD(8944394323791464), UWORD(14472334024676221), UWORD(23416728348467685), UWORD(37889062373143906), UWORD(61305790721611591), UWORD(99194853094755497), UWORD(160500643816367088), UWORD(259695496911122585), UWORD(420196140727489673), UWORD(679891637638612258), UWORD(1100087778366101931), UWORD(1779979416004714189), UWORD(2880067194370816120), UWORD(4660046610375530309), UWORD(7540113804746346429), UWORD(12200160415121876738) #endif }; void fmpz_fib_ui(fmpz_t f, ulong n) { if (n < NUM_SMALL_FIB) { fmpz_set_ui(f, small_fib[n]); } else if (n < NUM_SMALL_FIB2) { mp_limb_t hi, lo, a, b; a = small_fib[n / 2]; b = small_fib[n / 2 - 1]; if (n & 1) { umul_ppmm(hi, lo, 2 * a + b, 2 * a - b); if ((n / 2) % 2 == 0) lo += 2; else lo -= 2; } else { umul_ppmm(hi, lo, a, a + 2 * b); } fmpz_set_uiui(f, hi, lo); } else { flint_mpz_fib_ui(_fmpz_promote(f), n); } } flint-3.1.3/src/fmpz/fits_si.c000066400000000000000000000043421461254215100162050ustar00rootroot00000000000000/* int mpz_fits_X_p (mpz_t z) -- test whether z fits signed type X. Copyright 1997, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "flint.h" #include "gmpcompat.h" #include "fmpz.h" #if defined(_WIN64) || defined(__mips64) #define FLINT_UI_MAX ((mp_limb_t)(~(mp_limb_t)0)) #define FLINT_UI_HIBIT (FLINT_UI_MAX ^ (FLINT_UI_MAX >> 1)) #define FLINT_SI_MAX ((mp_limb_signed_t)(FLINT_UI_MAX ^ FLINT_UI_HIBIT)) #define FLINT_SI_MIN ((mp_limb_signed_t)FLINT_UI_HIBIT) int flint_mpz_fits_si_p(mpz_srcptr z) { mp_size_t n = z->_mp_size; mp_ptr p = z->_mp_d; mp_limb_t limb = p[0]; if (n == 0) return 1; if (n == 1) return limb <= FLINT_SI_MAX; if (n == -1) return limb <= (mp_limb_t) FLINT_SI_MIN; return 0; } #endif /* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ int fmpz_fits_si(const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) { return 1; } else { #if defined(_WIN64) || defined(__mips64) return flint_mpz_fits_si_p(COEFF_TO_PTR(*f)); #else return mpz_fits_slong_p(COEFF_TO_PTR(*f)); #endif } } flint-3.1.3/src/fmpz/flog.c000066400000000000000000000042611461254215100154740ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "fmpz.h" slong fmpz_flog(const fmpz_t n, const fmpz_t b) { fmpz_t t; int sign; slong r; if (fmpz_is_one(n)) return 0; if (!COEFF_IS_MPZ(*b)) return fmpz_flog_ui(n, *b); sign = fmpz_cmp(n, b); if (sign <= 0) return (sign == 0) ? 1 : 0; r = fmpz_dlog(n) / fmpz_dlog(b); fmpz_init(t); fmpz_pow_ui(t, b, r); sign = fmpz_cmp(t, n); /* Adjust down */ if (sign > 0) { while (sign > 0) { fmpz_divexact(t, t, b); sign = fmpz_cmp(t, n); r--; } } /* Adjust up */ else if (sign < 0) { while (1) { fmpz_mul(t, t, b); if (fmpz_cmp(t, n) <= 0) r++; else break; } } fmpz_clear(t); return r; } slong fmpz_flog_ui(const fmpz_t n, ulong b) { fmpz_t t; int sign; slong r; if (fmpz_is_one(n)) return 0; if (b == 2) return fmpz_bits(n) - 1; if (!COEFF_IS_MPZ(*n)) return n_flog(*n, b); sign = fmpz_cmp_ui(n, b); if (sign <= 0) return (sign == 0) ? 1 : 0; r = fmpz_dlog(n) / log(b); fmpz_init(t); fmpz_set_ui(t, b); fmpz_pow_ui(t, t, r); sign = fmpz_cmp(t, n); /* Adjust down */ if (sign > 0) { while (sign > 0) { fmpz_divexact_ui(t, t, b); sign = fmpz_cmp(t, n); r--; } } /* Adjust up */ else if (sign < 0) { while (1) { fmpz_mul_ui(t, t, b); if (fmpz_cmp(t, n) <= 0) r++; else break; } } fmpz_clear(t); return r; } flint-3.1.3/src/fmpz/fmma.c000066400000000000000000000027321461254215100154660ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" void fmpz_fmma(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d) { fmpz s, t, u, v; s = *a; t = *b; u = *c; v = *d; if (!COEFF_IS_MPZ(s) && !COEFF_IS_MPZ(t) && !COEFF_IS_MPZ(u) && !COEFF_IS_MPZ(v)) { mp_limb_t sh, sl, th, tl; smul_ppmm(sh, sl, s, t); smul_ppmm(th, tl, u, v); add_ssaaaa(sh, sl, sh, sl, th, tl); fmpz_set_signed_uiui(f, sh, sl); return; } if (s == 0 || t == 0) { fmpz_mul(f, c, d); return; } if (u == 0 || v == 0) { fmpz_mul(f, a, b); return; } if (f == c || f == d) { if (f == a || f == b) { fmpz_t t; fmpz_init(t); fmpz_mul(t, a, b); fmpz_addmul(t, c, d); fmpz_swap(t, f); fmpz_clear(t); } else { fmpz_mul(f, c, d); fmpz_addmul(f, a, b); } } else { fmpz_mul(f, a, b); fmpz_addmul(f, c, d); } } flint-3.1.3/src/fmpz/fmms.c000066400000000000000000000030161461254215100155040ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" void fmpz_fmms(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d) { fmpz s, t, u, v; s = *a; t = *b; u = *c; v = *d; if (!COEFF_IS_MPZ(s) && !COEFF_IS_MPZ(t) && !COEFF_IS_MPZ(u) && !COEFF_IS_MPZ(v)) { mp_limb_t sh, sl, th, tl; smul_ppmm(sh, sl, s, t); smul_ppmm(th, tl, u, v); sub_ddmmss(sh, sl, sh, sl, th, tl); fmpz_set_signed_uiui(f, sh, sl); return; } if (s == 0 || t == 0) { fmpz_mul(f, c, d); fmpz_neg(f, f); return; } if (u == 0 || v == 0) { fmpz_mul(f, a, b); return; } if (f == c || f == d) { if (f == a || f == b) { fmpz_t t; fmpz_init(t); fmpz_mul(t, a, b); fmpz_submul(t, c, d); fmpz_swap(t, f); fmpz_clear(t); } else { fmpz_mul(f, c, d); fmpz_submul(f, a, b); fmpz_neg(f, f); } } else { fmpz_mul(f, a, b); fmpz_submul(f, c, d); } } flint-3.1.3/src/fmpz/gcd.c000066400000000000000000000142551461254215100153060ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2021 Fredrik Johansson Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" void fmpz_gcd(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (!COEFF_IS_MPZ(c1)) /* g is small */ { ulong u1; if (c1 == 0) { fmpz_abs(f, h); return; } u1 = FLINT_ABS(c1); if (!COEFF_IS_MPZ(c2)) /* and h is also small */ { ulong u2; if (c2 == 0) { fmpz_abs(f, g); return; } u2 = FLINT_ABS(c2); fmpz_set_ui(f, mpn_gcd_1((mp_srcptr) &u2, (mp_size_t) 1, u1)); } else /* but h is large */ { __mpz_struct * mpzc2 = COEFF_TO_PTR(c2); mp_size_t size = mpzc2->_mp_size; /* The sign is stored in the size of an mpz, and gcd_1 only takes * positive integers. */ fmpz_set_ui(f, mpn_gcd_1(mpzc2->_mp_d, FLINT_ABS(size), u1)); } } else /* g is large */ { if (!COEFF_IS_MPZ(c2)) /* but h is small */ { ulong u2; __mpz_struct * mpzc1; mp_size_t size; if (c2 == 0) { fmpz_abs(f, g); return; } u2 = FLINT_ABS(c2); mpzc1 = COEFF_TO_PTR(c1); size = mpzc1->_mp_size; fmpz_set_ui(f, mpn_gcd_1(mpzc1->_mp_d, FLINT_ABS(size), u2)); } else { /* TODO: Change to mpn_gcd in order to save some calculations that * have already been already made. */ __mpz_struct * mf = _fmpz_promote(f); mpz_gcd(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); } } } void fmpz_gcd_ui(fmpz_t res, const fmpz_t a, ulong b) { if (b == 0) fmpz_abs(res, a); else if (!COEFF_IS_MPZ(*a)) { if (*a != 0) { _fmpz_demote(res); *res = mpn_gcd_1(&b, 1, FLINT_ABS(*a)); } else fmpz_set_ui(res, b); } else { __mpz_struct * ma = COEFF_TO_PTR(*a); fmpz_set_ui(res, mpn_gcd_1(ma->_mp_d, FLINT_ABS(ma->_mp_size), b)); } } /* Assumes that c fits in fmpz */ static void _fmpz_gcd3_small(fmpz_t res, const fmpz_t a, const fmpz_t b, ulong c) { if (c <= 1) { if (c == 1) fmpz_one(res); else fmpz_gcd(res, a, b); } else { if (!COEFF_IS_MPZ(*a)) { if (*a != 0) c = mpn_gcd_1(&c, 1, FLINT_ABS(*a)); if (c != 1) { if (!COEFF_IS_MPZ(*b)) { if (*b != 0) c = mpn_gcd_1(&c, 1, FLINT_ABS(*b)); } else { __mpz_struct * mb = COEFF_TO_PTR(*b); c = mpn_gcd_1(mb->_mp_d, FLINT_ABS(mb->_mp_size), c); } } } else { __mpz_struct * ma = COEFF_TO_PTR(*a); if (!COEFF_IS_MPZ(*b)) { if (*b != 0) c = mpn_gcd_1(&c, 1, FLINT_ABS(*b)); if (c != 1) c = mpn_gcd_1(ma->_mp_d, FLINT_ABS(ma->_mp_size), c); } else { c = mpn_gcd_1(ma->_mp_d, FLINT_ABS(ma->_mp_size), c); if (c != 1) { ma = COEFF_TO_PTR(*b); c = mpn_gcd_1(ma->_mp_d, FLINT_ABS(ma->_mp_size), c); } } } if (COEFF_IS_MPZ(*res)) _fmpz_demote(res); *res = c; } } void fmpz_gcd3(fmpz_t res, const fmpz_t a, const fmpz_t b, const fmpz_t c) { if (!COEFF_IS_MPZ(*a)) { _fmpz_gcd3_small(res, b, c, FLINT_ABS(*a)); } else if (!COEFF_IS_MPZ(*b)) { _fmpz_gcd3_small(res, a, c, FLINT_ABS(*b)); } else if (!COEFF_IS_MPZ(*c)) { _fmpz_gcd3_small(res, a, b, FLINT_ABS(*c)); } else { /* Three-way mpz_gcd. */ __mpz_struct *rp, *ap, *bp, *cp, *tp; mp_size_t an, bn, cn, mn; /* If res is small, it cannot be aliased with a, b, c, so promoting is fine. */ rp = _fmpz_promote(res); ap = COEFF_TO_PTR(*a); bp = COEFF_TO_PTR(*b); cp = COEFF_TO_PTR(*c); an = FLINT_ABS(ap->_mp_size); bn = FLINT_ABS(bp->_mp_size); cn = FLINT_ABS(cp->_mp_size); /* Select c to be the largest operand; we do the smaller gcd first. */ mn = FLINT_MAX(FLINT_MAX(an, bn), cn); tp = cp; if (mn != cn) { if (mn == an) { cp = ap; ap = tp; } else { cp = bp; bp = tp; } cn = mn; } /* Handle aliasing */ if (rp == cp) { mpz_t t; TMP_INIT; TMP_START; /* It would be more efficient to allocate temporary space for gcd(a, b), but we can't be sure that mpz_gcd never attempts to reallocate the output. */ t->_mp_d = TMP_ALLOC(sizeof(mp_limb_t) * cn); t->_mp_size = t->_mp_alloc = cn; flint_mpn_copyi(t->_mp_d, cp->_mp_d, cn); mpz_gcd(rp, ap, bp); if (mpz_cmpabs_ui(rp, 1) != 0) mpz_gcd(rp, rp, t); TMP_END; } else { mpz_gcd(rp, ap, bp); if (mpz_cmpabs_ui(rp, 1) != 0) mpz_gcd(rp, rp, cp); } /* The result may be small */ _fmpz_demote_val(res); } } flint-3.1.3/src/fmpz/gcdinv.c000066400000000000000000000033331461254215100160160ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_gcdinv(fmpz_t d, fmpz_t a, const fmpz_t f, const fmpz_t g) { FLINT_ASSERT(fmpz_cmp(f, g) < 0); if (fmpz_is_zero(f)) { fmpz_set(d, g); fmpz_set_ui(a, 0); return; } if (!COEFF_IS_MPZ(*g)) /* g is small, hence f is small */ { fmpz ff, gg; ff = *f; gg = *g; _fmpz_demote(d); _fmpz_demote(a); *d = n_gcdinv((mp_limb_t *) a, ff, gg); } else /* g is large */ { mpz_t atemp, dtemp; mpz_init(atemp); mpz_init(dtemp); _fmpz_promote_val(d); _fmpz_promote_val(a); if (!COEFF_IS_MPZ(*f)) /* f is small */ { mpz_t fptr; fptr->_mp_alloc = 1; fptr->_mp_size = 1; fptr->_mp_d = (mp_limb_t *) f; mpz_gcdext(dtemp, atemp, NULL, fptr, COEFF_TO_PTR(*g)); } else /* f is large */ { mpz_gcdext(dtemp, atemp, NULL, COEFF_TO_PTR(*f), COEFF_TO_PTR(*g)); } if (mpz_cmp_ui(atemp, 0) < 0) mpz_add(atemp, atemp, COEFF_TO_PTR(*g)); mpz_swap(COEFF_TO_PTR(*d), dtemp); mpz_swap(COEFF_TO_PTR(*a), atemp); mpz_clear(atemp); mpz_clear(dtemp); _fmpz_demote_val(d); _fmpz_demote_val(a); } } flint-3.1.3/src/fmpz/get.c000066400000000000000000000136771461254215100153370ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2009 Andy Novocin Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid Copyright (C) 2015 Kushagra Singh Copyright (C) 2018, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #if defined(_WIN64) || defined(__mips64) # include /* to enable mpfr_set_sj in mpfr.h */ #endif #include #include "mpn_extras.h" #include "gmpcompat.h" #include "nmod.h" #include "fmpz.h" double fmpz_get_d_2exp(slong * exp, const fmpz_t f) { fmpz d = *f; if (!COEFF_IS_MPZ(d)) { ulong d_abs; if (d == WORD(0)) { (*exp) = WORD(0); return 0.0; } d_abs = FLINT_ABS(d); *exp = FLINT_BIT_COUNT(d_abs); if (d < WORD(0)) return flint_mpn_get_d((mp_limb_t *) &d_abs, WORD(1), WORD(-1), -*exp); else return flint_mpn_get_d((mp_limb_t *) &d, WORD(1), WORD(1), -*exp); } else { long exp2; double m = mpz_get_d_2exp(&exp2, COEFF_TO_PTR(d)); *exp = exp2; return m; } } #if FLINT64 /* 2^53 */ #define DOUBLE_MAX WORD(9007199254740992) #define DOUBLE_MIN WORD(-9007199254740992) #else #define DOUBLE_MAX COEFF_MAX #define DOUBLE_MIN COEFF_MIN #endif double fmpz_get_d(const fmpz_t f) { fmpz c = *f; if (c >= DOUBLE_MIN && c <= DOUBLE_MAX) { return (double) c; } else if (!COEFF_IS_MPZ(c)) { mp_limb_t d; if (c > 0) { d = c; return flint_mpn_get_d(&d, 1, 1, 0); } else { d = -c; return flint_mpn_get_d(&d, 1, -1, 0); } } else return mpz_get_d(COEFF_TO_PTR(c)); } void fmpz_get_mpf(mpf_t x, const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) flint_mpf_set_si(x, *f); /* set x to small value */ else mpf_set_z(x, COEFF_TO_PTR(*f)); /* set x to large value */ } void fmpz_get_mpfr(mpfr_t x, const fmpz_t f, mpfr_rnd_t rnd) { if (!COEFF_IS_MPZ(*f)) #if defined(_WIN64) || defined(__mips64) mpfr_set_sj(x, *f, rnd); #else mpfr_set_si(x, *f, rnd); /* set x to small value */ #endif else mpfr_set_z(x, COEFF_TO_PTR(*f), rnd); /* set x to large value */ } int fmpz_get_mpn(mp_ptr *n, fmpz_t n_in) { mp_limb_t n_size; mp_ptr temp; n_size = fmpz_size(n_in); *n = flint_malloc(n_size * sizeof(mp_limb_t)); if (n_size <= 1) { (*n)[0] = fmpz_get_ui(n_in); return 1; } else { temp = COEFF_TO_PTR(*n_in)->_mp_d; flint_mpn_copyi(*n, temp, n_size); return n_size; } } void fmpz_get_mpz(mpz_t x, const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) flint_mpz_set_si(x, *f); /* set x to small value */ else mpz_set(x, COEFF_TO_PTR(*f)); /* set x to large value */ } mp_limb_t fmpz_get_nmod(const fmpz_t aa, nmod_t mod) { fmpz A = *aa; mp_limb_t r, SA, UA; if (!COEFF_IS_MPZ(A)) { SA = FLINT_SIGN_EXT(A); UA = FLINT_ABS(A); NMOD_RED(r, UA, mod); } else { mpz_srcptr a = COEFF_TO_PTR(A); mp_srcptr ad = a->_mp_d; slong an = a->_mp_size; if (an < 0) { SA = -UWORD(1); an = -an; } else { SA = 0; } if (an < 5) { r = 0; while (an > 0) { NMOD_RED2(r, r, ad[an - 1], mod); an--; } } else { r = mpn_mod_1(ad, an, mod.n); } } return (SA == 0 || r == 0) ? r : (mod.n - r); } slong fmpz_get_si(const fmpz_t f) { return (!COEFF_IS_MPZ(*f) ? *f : flint_mpz_get_si(COEFF_TO_PTR(*f))); } void fmpz_get_signed_ui_array(mp_limb_t * r, slong n, const fmpz_t x) { int neg; slong i, sz; FLINT_ASSERT(n > 0); if (!COEFF_IS_MPZ(*x)) { neg = *x < 0; r[0] = FLINT_ABS(*x); i = 1; } else { __mpz_struct * p = COEFF_TO_PTR(*x); neg = p->_mp_size < 0; sz = FLINT_ABS(p->_mp_size); for (i = 0; i < n && i < sz; i++) r[i] = p->_mp_d[i]; } for ( ; i < n; i++) r[i] = 0; if (neg) mpn_neg(r, r, n); } void fmpz_get_signed_uiui(mp_limb_t * hi, mp_limb_t * lo, const fmpz_t x) { ulong r0, r1, s; if (!COEFF_IS_MPZ(*x)) { r0 = *x; r1 = FLINT_SIGN_EXT(r0); } else { __mpz_struct * p = COEFF_TO_PTR(*x); s = -(ulong)(p->_mp_size < 0); r0 = p->_mp_d[0]; if (p->_mp_size > 1 || p->_mp_size < -1) r1 = p->_mp_d[1]; else r1 = 0; sub_ddmmss(r1, r0, r1^s, r0^s, s, s); } *lo = r0; *hi = r1; } /* Assuming that "in" is non negative and has a limb count <= out_len, write the limbs to "out" and zero extend to "out_len" limbs. */ void fmpz_get_ui_array(ulong * out, slong out_len, const fmpz_t in) { slong size = 0; FLINT_ASSERT(out_len > 0); /* copy limbs */ if (fmpz_abs_fits_ui(in)) { *out++ = fmpz_get_ui(in); size++; } else { __mpz_struct * mpz = COEFF_TO_PTR(*in); FLINT_ASSERT(mpz->_mp_size <= out_len); while (size < mpz->_mp_size) *out++ = mpz->_mp_d[size++]; } /* zero extend to out_len */ while (size++ < out_len) *out++ = UWORD(0); } ulong fmpz_get_ui(const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) /*value is small */ return (*f < WORD(0) ? -*f : *f); else /* value is large */ return flint_mpz_get_ui(COEFF_TO_PTR(*f)); } flint-3.1.3/src/fmpz/get_str.c000066400000000000000000000214441461254215100162160ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "thread_pool.h" #include "thread_support.h" #include "string.h" /* Notes: * Right now the purpose of the recursive fmpz code is just to have something that takes advantage of the small FFT and is multithreaded for huge (million-digit) operands. * This code should be rewritten mpn style with an efficient mpn basecase. GMP handles the basecase just fine, of course, but it's wasteful to let GMP recompute the powers on each basecase call. (There are also some tricks that GMP doesn't use.) * Incidentally, because fmpzs are normalized, this code performs better when the input has long strings of 0s. (Fun exercise: make it equally fast for long strings of 9s too.) * Other potential improvements: cache transforms, trim the low zeros in 10^N when dividing. * It is mildly annoying that the output is big endian, as we have to shift the string when fmpz_sizeinbase is too big. This shift can avoided if we always compute the high part first, but that gets tricker when we want multithreading. * This is currently base 10 only. Trivial to generalize, but who cares about other bases? */ /* Falling back to GMP. */ #define STR_BASECASE_CUTOFF_BITS 30000 /* We compute inverses of 10^N to speed up divisions, but it is pointless to do so near the root of the tree where each power is used only a couple of times. */ #define PREINV_DEPTH 3 typedef struct { char * s; slong num_digits; fmpz * f; const slong * exps; slong cur_depth; slong depth; const fmpz * pows; const fmpz_preinvn_struct * preinv; } worker_args_struct; static void _fmpz_get_str_recursive(char * s, slong num_digits, const fmpz_t f, const slong * exps, slong cur_depth, slong depth, const fmpz * pows, const fmpz_preinvn_struct * preinv); static void worker(void * arg) { worker_args_struct * X = (worker_args_struct * ) arg; _fmpz_get_str_recursive(X->s, X->num_digits, X->f, X->exps, X->cur_depth, X->depth, X->pows, X->preinv); fmpz_clear(X->f); } static void _fmpz_get_str_recursive(char * s, slong num_digits, const fmpz_t f, const slong * exps, slong cur_depth, slong depth, const fmpz * pows, const fmpz_preinvn_struct * preinv) { if (cur_depth >= depth || fmpz_bits(f) < STR_BASECASE_CUTOFF_BITS) { char * tmp; slong n; tmp = fmpz_get_str(NULL, 10, f); n = strlen(tmp); memcpy(s + num_digits - n, tmp, n); flint_free(tmp); } else { fmpz_t q, r; slong num_right = exps[cur_depth]; slong nworkers, nthreads, nworkers_save; int want_workers; thread_pool_handle * threads; worker_args_struct high_digits[1], low_digits[1]; fmpz_init(q); fmpz_init(r); if (cur_depth >= PREINV_DEPTH) fmpz_fdiv_qr_preinvn(q, r, f, pows + cur_depth, preinv + cur_depth); else fmpz_fdiv_qr(q, r, f, pows + cur_depth); low_digits->s = s + num_digits - num_right; low_digits->num_digits = num_right; low_digits->f = r; low_digits->exps = exps; low_digits->cur_depth = cur_depth + 1; low_digits->depth = depth; low_digits->pows = pows; low_digits->preinv = preinv; high_digits->s = s; high_digits->num_digits = num_digits - num_right; high_digits->f = q; high_digits->exps = exps; high_digits->cur_depth = cur_depth + 1; high_digits->depth = depth; high_digits->pows = pows; high_digits->preinv = preinv; nthreads = flint_get_num_threads(); /* Prefer to let the multithreaded multiplication do its things near the root. */ want_workers = nthreads >= 2 && (num_right <= 100000000 || cur_depth >= 2); nworkers = flint_request_threads(&threads, want_workers ? 2 : 1); if (nworkers == 1) { nworkers_save = flint_set_num_workers(nthreads - nthreads / 2 - 1); thread_pool_wake(global_thread_pool, threads[0], nthreads / 2 - 1, worker, low_digits); worker(high_digits); flint_reset_num_workers(nworkers_save); thread_pool_wait(global_thread_pool, threads[0]); } else { worker(low_digits); worker(high_digits); } flint_give_back_threads(threads, nworkers); } } char * fmpz_get_str_bsplit_threaded(char * s, const fmpz_t f) { slong n, k, depth, leading_zeros; slong exps[FLINT_BITS]; fmpz * pows; fmpz_preinvn_struct * preinv; if (!COEFF_IS_MPZ(*f)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (s == NULL) s = flint_malloc(mpz_sizeinbase(COEFF_TO_PTR(*f), 10) + 2); if (fmpz_sgn(f) < 0) { /* make a shallow mpz copy */ fmpz_t g; mpz_t u; *u = *COEFF_TO_PTR(*f); *g = PTR_TO_COEFF(u); u->_mp_size = -u->_mp_size; s[0] = '-'; fmpz_get_str_bsplit_threaded(s + 1, g); return s; } n = fmpz_sizeinbase(f, 10); exps[0] = (n + 1) / 2; depth = 1; while (exps[depth - 1] > 2 * 0.301 * STR_BASECASE_CUTOFF_BITS) { exps[depth] = (exps[depth - 1] + 1) / 2; depth++; } pows = _fmpz_vec_init(depth); preinv = flint_malloc(sizeof(fmpz_preinvn_struct) * depth); fmpz_ui_pow_ui(pows + depth - 1, 5, exps[depth - 1]); for (k = depth - 2; k >= 0; k--) { fmpz_mul(pows + k, pows + k + 1, pows + k + 1); if (exps[k] != 2 * exps[k + 1]) fmpz_divexact_ui(pows + k, pows + k, 5); } for (k = 0; k < depth; k++) fmpz_mul_2exp(pows + k, pows + k, exps[k]); for (k = depth - 1; k >= PREINV_DEPTH; k--) fmpz_preinvn_init(preinv + k, pows + k); memset(s, '0', n); _fmpz_get_str_recursive(s, n, f, exps, 0, depth, pows, preinv); leading_zeros = 0; while (s[leading_zeros] == '0') leading_zeros++; if (leading_zeros != 0) { n -= leading_zeros; for (k = 0; k < n; k++) s[k] = s[k + leading_zeros]; } s[n] = '\0'; for (k = depth - 1; k >= PREINV_DEPTH; k--) fmpz_preinvn_clear(preinv + k); _fmpz_vec_clear(pows, depth); flint_free(preinv); return s; } char * fmpz_get_str(char * str, int b, const fmpz_t f) { FLINT_ASSERT(b >= 2 && b <= 62); if (!COEFF_IS_MPZ(*f)) { fmpz c; mp_limb_t d; c = *f; d = FLINT_ABS(c); /* Need a special case for zero, which may as well handle single digits. */ if (d < FLINT_MIN(b, 10)) { if (str == NULL) str = flint_malloc(3); str[0] = '-'; str[0 + (c < 0)] = d + '0'; str[1 + (c < 0)] = '\0'; } else if (b == 10) { unsigned char tmp[FLINT_BITS + 3]; slong i, len; /* The compiler might generate faster code for 32-bit divisions */ unsigned int dl; len = 0; #if FLINT_BITS == 64 while (d >= (UWORD(1) << 32)) { tmp[len] = d % 10; d /= 10; len++; } #endif dl = d; while (dl != 0) { tmp[len] = dl % 10; dl /= 10; len++; } if (str == NULL) str = flint_malloc(len + 2); str[0] = '-'; for (i = 0; i < len; i++) str[i + (c < 0)] = tmp[len - 1 - i] + '0'; str[len + (c < 0)] = '\0'; return str; } else { mpz_t z; z->_mp_d = &d; z->_mp_alloc = 1; z->_mp_size = (c > 1) ? 1 : -1; if (str == NULL) str = flint_malloc(mpz_sizeinbase(z, b) + 2); str = mpz_get_str(str, b, z); } } else { if (str == NULL) str = flint_malloc(mpz_sizeinbase(COEFF_TO_PTR(*f), b) + 2); #ifdef FLINT_HAVE_FFT_SMALL if (b == 10 && mpz_size(COEFF_TO_PTR(*f)) > 15000) { fmpz_get_str_bsplit_threaded(str, f); } else #endif { str = mpz_get_str(str, b, COEFF_TO_PTR(*f)); } } return str; } flint-3.1.3/src/fmpz/init2.c000066400000000000000000000012321461254215100155650ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_init2(fmpz_t f, ulong limbs) { if (limbs) { __mpz_struct * mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); _mpz_realloc(mf, limbs); } else { (*f) = WORD(0); } } flint-3.1.3/src/fmpz/init_set_readonly.c000066400000000000000000000014301461254215100202530ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" void fmpz_init_set_readonly(fmpz_t f, const mpz_t z) { if (z->_mp_size == 1 && z->_mp_d[0] <= COEFF_MAX) { *f = z->_mp_d[0]; } else if (z->_mp_size == -1 && z->_mp_d[0] <= COEFF_MAX) { *f = -(z->_mp_d[0]); } else if (z->_mp_size) { _fmpz_init_readonly_mpz(f, z); } else { *f = WORD(0); } } flint-3.1.3/src/fmpz/inlines.c000066400000000000000000000021351461254215100162040ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_INLINES_C #include "gmpcompat.h" #include "fmpz.h" void _fmpz_promote_set_ui(fmpz_t f, ulong v) { __mpz_struct * z = _fmpz_promote(f); flint_mpz_set_ui(z, v); } void _fmpz_promote_neg_ui(fmpz_t f, ulong v) { __mpz_struct * z = _fmpz_promote(f); flint_mpz_set_ui(z, v); mpz_neg(z, z); } void _fmpz_promote_set_si(fmpz_t f, slong v) { __mpz_struct * z = _fmpz_promote(f); flint_mpz_set_si(z, v); } void _fmpz_init_promote_set_ui(fmpz_t f, ulong v) { __mpz_struct * z = _fmpz_new_mpz(); *f = PTR_TO_COEFF(z); flint_mpz_set_ui(z, v); } void _fmpz_init_promote_set_si(fmpz_t f, slong v) { __mpz_struct * z = _fmpz_new_mpz(); *f = PTR_TO_COEFF(z); flint_mpz_set_si(z, v); } flint-3.1.3/src/fmpz/invmod.c000066400000000000000000000057751461254215100160540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" ulong z_gcdinv(ulong * inv, slong a, ulong b) { ulong g, ua = FLINT_ABS(a); if (ua >= b) ua %= b; g = n_gcdinv(inv, ua, b); if (a < WORD(0)) *inv = n_submod(UWORD(0), *inv, b); return g; } int fmpz_invmod(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; int val; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_invmod). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { ulong inv, gcd; if (c2 < WORD(0)) c2 = -c2; if (c2 == WORD(1)) { fmpz_zero(f); return 1; /* special case not handled by n_invmod */ } gcd = z_gcdinv(&inv, c1, c2); return (gcd == UWORD(1) ? fmpz_set_si(f, inv), 1 : 0); } else /* h is large and g is small */ { __mpz_struct temp; /* put g into a temporary mpz_t */ __mpz_struct * mf; if (c1 < WORD(0)) { c1 = -c1; temp._mp_d = (mp_limb_t *) & c1; temp._mp_size = -1; } else if (c1 == WORD(0)) temp._mp_size = 0; else { temp._mp_d = (mp_limb_t *) & c1; temp._mp_size = 1; } mf = _fmpz_promote(f); val = mpz_invert(mf, &temp, COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* inverse mod h may result in small value */ return val; } } else /* g is large */ { if (!COEFF_IS_MPZ(c2)) /* h is small */ { ulong gcd, inv, r; if (c2 < WORD(0)) c2 = -c2; if (c2 == WORD(1)) { fmpz_zero(f); return 1; /* special case not handled by z_gcd_invert */ } /* reduce g mod h first */ r = flint_mpz_fdiv_ui(COEFF_TO_PTR(c1), c2); gcd = z_gcdinv(&inv, r, c2); return (gcd == UWORD(1) ? fmpz_set_si(f, inv), 1 : 0); } else /* both are large */ { __mpz_struct * mf = _fmpz_promote(f); val = mpz_invert(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* reduction mod h may result in small value */ return val; } } } flint-3.1.3/src/fmpz/io.c000066400000000000000000000031571461254215100151570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Qingwen GUAN This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" /* printing *******************************************************************/ int fmpz_fprint(FILE * file, const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) return fprintf(file, WORD_FMT "d", *x); else return (int) mpz_out_str(file, 10, COEFF_TO_PTR(*x)); } int fmpz_print(const fmpz_t x) { return fmpz_fprint(stdout, x); } /* reading ********************************************************************/ int fmpz_fread(FILE * file, fmpz_t f) { mpz_t t; size_t r; mpz_init(t); r = mpz_inp_str(t, file, 10); fmpz_set_mpz(f, t); mpz_clear(t); return (r > 0) ? 1 : 0; } int fmpz_read(fmpz_t f) { return fmpz_fread(stdout, f); } /* file I/O ********************************************************************/ size_t fmpz_inp_raw(fmpz_t x, FILE * fin) { mpz_t v; size_t size; mpz_init( v ); size = mpz_inp_raw( v, fin ); fmpz_set_mpz( x, v ); mpz_clear( v ); return size; } size_t fmpz_out_raw(FILE * fout, const fmpz_t x) { mpz_t v; size_t size; mpz_init( v ); fmpz_get_mpz( v, x ); size = mpz_out_raw( fout, v ); mpz_clear( v ); return size; } flint-3.1.3/src/fmpz/is_canonical.c000066400000000000000000000013271461254215100171670ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" int _fmpz_is_canonical(const fmpz_t x) { __mpz_struct * z; mp_size_t n; if (!COEFF_IS_MPZ(*x)) return 1; z = COEFF_TO_PTR(*x); n = FLINT_ABS(z->_mp_size); if (n == 0) return 0; if (n == 1) return z->_mp_d[0] > (mp_limb_t) COEFF_MAX; return z->_mp_d[n - 1] != 0; } flint-3.1.3/src/fmpz/is_perfect_power.c000066400000000000000000000161241461254215100201050ustar00rootroot00000000000000/* mpz_perfect_power_p(arg) -- Return non-zero if ARG is a perfect power, zero otherwise. Copyright 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc. Copyright 2008 Jason Moxham Copyright 2017 William Hart This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* We are to determine if c is a perfect power, c = a ^ b. Assume c is divisible by 2^n and that codd = c/2^n is odd. Assume a is divisible by 2^m and that aodd = a/2^m is odd. It is always true that m divides n. * If n is prime, either 1) a is 2*aodd and b = n or 2) a = c and b = 1. So for n prime, we readily have a solution. * If n is factorable into the non-trivial factors p1,p2,... Since m divides n, m has a subset of n's factors and b = n / m. */ /* This is a naive approach to recognizing perfect powers. Many things can be improved. In particular, we should use p-adic arithmetic for computing possible roots. */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" static const unsigned short primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,107,109,113,127,131, 137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223, 227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311, 313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409, 419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503, 509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613, 617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719, 727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827, 829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941, 947,953,967,971,977,983,991,997,0 }; #define SMALLEST_OMITTED_PRIME 1009 int fmpz_is_perfect_power(fmpz_t root, const fmpz_t f) { ulong prime, n, n2, rem; mpz_t u2, q; int exact, exp2, sgn = fmpz_sgn(f); slong i, uns, usize = fmpz_size(f); __mpz_struct * u, * r; if (usize == 0) { fmpz_zero(root); return 2; /* consider 0 a perfect square */ } if (usize == 1) { ulong r = 0; ulong r2; ulong n = fmpz_get_ui(f); int exp = n_is_perfect_power(&r, n); /* get highest exponent */ while (r > 1 && (exp2 = n_is_perfect_power(&r2, r)) != 0) { exp *= exp2; r = r2; } if (exp == 0) return 0; else if (sgn < 0 && (exp & 1) == 0) { while ((exp & 1) == 0) { r = r*r; exp >>= 1; } if (exp == 1 && n != 1) return 0; else { fmpz_set_si(root, -r); return exp; } } else { fmpz_set_ui(root, r); if (sgn < 0) fmpz_neg(root, root); return exp; } } u = COEFF_TO_PTR(*f); usize = u->_mp_size; n2 = mpz_scan1(u, 0); if (n2 == 1) return 0; /* 2 divides exactly once */ if (n2 > 1 && (n2 & (n2 - 1)) == 0 && usize < 0) return 0; /* 2 has power of two multiplicity with negative u */ uns = FLINT_ABS(usize) - n2/FLINT_BITS; mpz_init2(q, FLINT_BITS*uns); mpz_init2(u2, FLINT_BITS*uns); mpz_tdiv_q_2exp(u2, u, n2); if (n_is_prime(n2)) goto n2prime; for (i = 1; primes[i] != 0; i++) { prime = primes[i]; if (mpz_divisible_ui_p(u2, prime)) /* divisible by this prime? */ { rem = mpz_tdiv_q_ui(q, u2, prime*prime); if (rem != 0) { mpz_clear(q); mpz_clear(u2); return 0; /* prime divides exactly once, reject */ } mpz_swap(q, u2); for (n = 2; ; ) { rem = mpz_tdiv_q_ui(q, u2, prime); if (rem != 0) break; mpz_swap (q, u2); n++; } if ((n & (n - 1)) == 0 && usize < 0) { mpz_clear(q); mpz_clear(u2); return 0; /* power of two multiplicity with negative U, reject */ } n2 = n_gcd(n2, n); if (n2 == 1) { mpz_clear(q); mpz_clear(u2); return 0; /* we have multiplicity 1 of some factor */ } if (mpz_cmpabs_ui(u2, 1) == 0) { mpz_clear(q); mpz_clear(u2); if (usize < 0) { if ((n2 & (n2 - 1)) == 0) return 0; /* factoring completed; not consistent power */ while ((n2 & 1) == 0) n2 >>= 1; } r = _fmpz_promote(root); mpz_root(r, u, n2); _fmpz_demote_val(root); return n2; /* factoring completed; consistent power */ } /* as soon as n2 becomes a prime number, stop factoring either we have u=x^n2 or u is not a perfect power */ if (n_is_prime(n2)) goto n2prime; } } if (n2 == 0) { /* we found no factors above; have to check all values of n */ ulong nth; for (nth = usize < 0 ? 3 : 2; ; nth++) { if (!n_is_prime(nth)) continue; exact = mpz_root(q, u2, nth); if (exact) { r = _fmpz_promote(root); mpz_set(r, q); _fmpz_demote_val(root); mpz_clear(q); mpz_clear(u2); return nth; } if (mpz_cmpabs_ui(q, SMALLEST_OMITTED_PRIME) < 0) { mpz_clear(q); mpz_clear(u2); return 0; } } } else { ulong nth; /* we found some factors above and we just need to consider values of n that divide n2 */ for (nth = usize < 0 ? 3 : 2; nth <= n2; nth++) { if (!n_is_prime(nth)) continue; if (n2 % nth != 0) continue; exact = mpz_root(q, u, nth); if (exact) { r = _fmpz_promote(root); mpz_set(r, q); _fmpz_demote_val(root); mpz_clear(q); mpz_clear(u2); return nth; } if (mpz_cmpabs_ui(q, SMALLEST_OMITTED_PRIME) < 0) { mpz_clear(q); mpz_clear(u2); return 0; } } mpz_clear(q); mpz_clear(u2); return 0; } n2prime: if (n2 == 2 && usize < 0) { mpz_clear(q); mpz_clear(u2); return 0; } exact = mpz_root(q, u, n2); if (exact) { r = _fmpz_promote(root); mpz_set(r, q); _fmpz_demote_val(root); mpz_clear(q); mpz_clear(u2); return n2; } else { mpz_clear(q); mpz_clear(u2); return 0; } } flint-3.1.3/src/fmpz/is_prime.c000066400000000000000000000226321461254215100163560ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "fmpz.h" #include "aprcl.h" int _fmpz_is_prime(const fmpz_t n, int proved) { double logd; ulong p, ppi, limit; ulong * pp1, * pm1; slong i, l, num, num_pp1, num_pm1; const ulong * primes; const double * pinv; fmpz_t F1, Fsqr, Fcub, R, t; int res = -1; if (!COEFF_IS_MPZ(*n)) { slong v = *n; if (v <= 1) return 0; /* Note: we want n_is_prime rather than n_is_probabprime even when proved == 0, because ns_is_prime handles general input faster. */ return n_is_prime(v); } else { __mpz_struct * z; mp_ptr d; slong size, bits, trial_primes; z = COEFF_TO_PTR(*n); size = z->_mp_size; d = z->_mp_d; if (size < 0) return 0; if (size == 1) return n_is_prime(d[0]); /* As above */ if (d[0] % 2 == 0) return 0; bits = size * FLINT_BITS + FLINT_BIT_COUNT(d[size-1]); trial_primes = bits; if (flint_mpn_factor_trial(d, size, 1, trial_primes)) return 0; } /* todo: use fmpz_is_perfect_power? */ if (fmpz_is_square(n)) return 0; if (!proved) return fmpz_is_probabprime_BPSW(n); /* Fast deterministic Miller-Rabin test up to about 81 bits. This choice of bases certifies primality for n < 3317044064679887385961981; see https://doi.org/10.1090/mcom/3134 */ fmpz_init(t); fmpz_tdiv_q_2exp(t, n, 64); if (fmpz_cmp_ui(t, 179817) < 0) { static const char bases[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 0 }; for (i = 0; bases[i] != 0; i++) { fmpz_set_ui(t, bases[i]); if (!fmpz_is_strong_probabprime(n, t)) return 0; /* no need to clear t since it is small */ } return 1; } /* Do a single base-2 test to rule out most composites */ fmpz_set_ui(t, 2); if (!fmpz_is_strong_probabprime(n, t)) return 0; fmpz_clear(t); logd = fmpz_dlog(n); limit = (ulong) (logd*logd*logd/100.0) + 20; fmpz_init(F1); fmpz_init(R); fmpz_init(Fsqr); fmpz_init(Fcub); for (l = 0; l < 4 && res == -1; l++, limit *= 10) { num_pm1 = num_pp1 = 0; /* number of primes multiplied that will fit in a word */ num = FLINT_BITS/FLINT_BIT_COUNT(limit); /* compute remainders of n mod p for primes p up to limit (approx.) */ n_prime_pi_bounds(&ppi, &ppi, limit); /* precompute primes */ primes = n_primes_arr_readonly(ppi + FLINT_BITS); pinv = n_prime_inverses_arr_readonly(ppi + FLINT_BITS); pm1 = _nmod_vec_init(2 + (ulong) logd); /* space for primes dividing n - 1 */ pp1 = _nmod_vec_init(2 + (ulong) logd); /* space for primes dividing n + 1 */ while (primes[0] < limit) { /* multiply batch of primes */ p = primes[0]; for (i = 1; i < num; i++) p *= primes[i]; /* multi-modular reduction */ p = fmpz_tdiv_ui(n, p); /* check for factors */ for (i = 0; i < num; i++) { ulong r = n_mod2_precomp(p, primes[i], pinv[i]); if (r == 1) /* n - 1 = 0 mod p */ pm1[num_pm1++] = primes[i]; if (r == primes[i] - 1) /* n + 1 = 0 mod p */ pp1[num_pp1++] = primes[i]; } /* get next batch of primes */ primes += num; pinv += num; } /* p - 1 test */ res = fmpz_is_prime_pocklington(F1, R, n, pm1, num_pm1); if (res == 1) { fmpz_mul(Fsqr, F1, F1); if (fmpz_cmp(Fsqr, n) < 0) { fmpz_mul(Fcub, Fsqr, F1); if (fmpz_cmp(Fcub, n) >= 0) /* Brillhart, Lehmer, Selfridge test */ { fmpz_t n1, c2, c1; fmpz_init(n1); fmpz_init(c2); fmpz_init(c1); fmpz_sub_ui(n1, n, 1); /* n is 1 mod F1 */ fmpz_tdiv_q(n1, n1, F1); fmpz_tdiv_qr(c2, c1, n1, F1); /* Let n = c2*F^2 + c1*F + 1 */ fmpz_mul(c1, c1, c1); /* check if c1^2 - 4*c2 is a square */ fmpz_submul_ui(c1, c2, 4); if (fmpz_is_square(c1)) res = 0; /* else n is prime (res == 1) */ fmpz_clear(n1); fmpz_clear(c2); fmpz_clear(c1); } else /* p + 1 test */ { fmpz_t F2, Fm1; fmpz_init(F2); fmpz_init(Fm1); res = fmpz_is_prime_morrison(F2, R, n, pp1, num_pp1); if (res == 1) { fmpz_sub_ui(Fm1, F2, 1); /* need F2 - 1 > sqrt(n) */ fmpz_mul(Fsqr, Fm1, Fm1); if (fmpz_cmp(Fsqr, n) <= 0) { fmpz_mul(Fcub, Fsqr, Fm1); if (fmpz_cmp(Fcub, n) > 0) /* Improved n + 1 test */ { fmpz_t r1, r0, b, r, t; fmpz_init(r1); fmpz_init(r0); fmpz_init(b); fmpz_init(r); fmpz_init(t); fmpz_tdiv_qr(r1, r0, R, F2); /* R = r1*F2 + r0 */ /* check if x^2 + r0*x - r1 has positive integral root */ fmpz_mul(t, r0, r0); /* b = sqrt(r0^2 - 4(-r1)) */ fmpz_addmul_ui(t, r1, 4); fmpz_sqrtrem(b, r, t); if (fmpz_is_zero(r) && fmpz_cmp(b, r0) > 0) /* if so, composite */ res = 0; /* check if x^2 + (r0 - F2)*x - r1 - 1 has positive integral root */ fmpz_sub(r0, r0, F2); fmpz_add_ui(r1, r1, 1); fmpz_mul(t, r0, r0); /* b = sqrt((r0 - F2)^2 - 4(-r1 - 1)) */ fmpz_addmul_ui(t, r1, 4); fmpz_sqrtrem(b, r, t); if (fmpz_is_zero(r) && fmpz_cmp(b, r0) > 0) /* if so, composite */ res = 0; fmpz_clear(t); fmpz_clear(b); fmpz_clear(r); fmpz_clear(r1); fmpz_clear(r0); } else /* Brillhart, Lehmer, Selfridge combined p-1, p+1 test */ { fmpz_t F, nmodF; fmpz_init(F); fmpz_mul(F, F1, F2); /* F = lcm(F1, F2), F1 | n - 1, F2 | n + 1 */ if (fmpz_is_even(F1) && fmpz_is_even(F2)) fmpz_tdiv_q_2exp(F, F, 1); fmpz_mul(Fsqr, F, F); if (fmpz_cmp(Fsqr, n) > 0) /* lcm(F1, F2) > sqrt(n) */ { fmpz_init(nmodF); fmpz_mod(nmodF, n, F); /* check n mod F not factor of n */ if (!fmpz_equal(nmodF, n) && !fmpz_is_one(nmodF) && fmpz_divisible(n, nmodF)) res = 0; fmpz_clear(nmodF); } else { fmpz_t d; fmpz_init(d); fmpz_mul(Fcub, Fsqr, F); if (fmpz_cmp(Fcub, n) > 0) /* Lenstra's divisors in residue class */ { fmpz_t r; fmpz_init(r); fmpz_set_ui(r, 1); if (fmpz_divisor_in_residue_class_lenstra(d, n, r, F)) res = 0; fmpz_mod(r, n, F); if (fmpz_divisor_in_residue_class_lenstra(d, n, r, F)) res = 0; fmpz_clear(r); } else /* apr-cl primality test */ { res = aprcl_is_prime(n); } fmpz_clear(d); } fmpz_clear(F); } } /* else n is prime, i.e. res = 1 */ } fmpz_clear(F2); fmpz_clear(Fm1); } } } _nmod_vec_clear(pm1); _nmod_vec_clear(pp1); } /* aprcl_is_prime() actually throws, but it does not hurt to have this fallback here */ if (res < 0) { flint_throw(FLINT_ERROR, "Failed to prove %s prime or composite\n", fmpz_get_str(NULL, 10, n)); } fmpz_clear(F1); fmpz_clear(R); fmpz_clear(Fsqr); fmpz_clear(Fcub); return res; } int fmpz_is_probabprime(const fmpz_t n) { return _fmpz_is_prime(n, 0); } int fmpz_is_prime(const fmpz_t n) { return _fmpz_is_prime(n, 1); } flint-3.1.3/src/fmpz/is_prime_morrison.c000066400000000000000000000117541461254215100203110ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" void _fmpz_np1_trial_factors(const fmpz_t n, mp_ptr pp1, slong * num_pp1, ulong limit) { slong i, num; ulong ppi, p; const ulong * primes; const double * pinv; *num_pp1 = 0; /* number of primes multiplied that will fit in a word */ num = FLINT_BITS/FLINT_BIT_COUNT(limit); /* compute remainders of n mod p for primes p up to limit (approx.) */ n_prime_pi_bounds(&ppi, &ppi, limit); /* precompute primes */ primes = n_primes_arr_readonly(ppi + FLINT_BITS); pinv = n_prime_inverses_arr_readonly(ppi + FLINT_BITS); while (primes[0] < limit) { /* multiply batch of primes */ p = primes[0]; for (i = 1; i < num; i++) p *= primes[i]; /* multi-modular reduction */ p = fmpz_tdiv_ui(n, p); /* check for factors */ for (i = 0; i < num; i++) { ulong r = n_mod2_precomp(p, primes[i], pinv[i]); if (r == primes[i] - 1) /* n + 1 = 0 mod p */ pp1[(*num_pp1)++] = primes[i]; } /* get next batch of primes */ primes += num; pinv += num; } } int fmpz_is_prime_morrison(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pp1, slong num_pp1) { slong i, d, bits; mp_limb_t a, b; fmpz_t g, q, r, ex, c, D, Dinv, A, B, Ukm, Ukm1, Um, Um1, Vm, Vm1, p; fmpz_factor_t fac; int res = 0, fac_found; fmpz_init(D); fmpz_init(Dinv); fmpz_init(A); fmpz_init(B); fmpz_init(p); fmpz_init(q); fmpz_init(r); fmpz_init(g); fmpz_init(c); fmpz_init(ex); fmpz_init(Um); fmpz_init(Um1); fmpz_init(Ukm); fmpz_init(Ukm1); fmpz_init(Vm); fmpz_init(Vm1); fmpz_factor_init(fac); fmpz_add_ui(R, n, 1); /* start with n + 1 */ bits = fmpz_bits(R); for (i = 0; i < num_pp1; i++) { fmpz_set_ui(p, pp1[i]); d = fmpz_remove(R, R, p); _fmpz_factor_append_ui(fac, pp1[i], d); } srand(time(NULL)); if (!fmpz_is_probabprime_BPSW(R)) { if (bits > 150 && (fac_found = fmpz_factor_pp1(p, R, bits + 1000, bits/20 + 1000, rand()%100 + 3) && fmpz_is_prime(p))) { d = fmpz_remove(R, R, p); _fmpz_factor_append(fac, p, d); if (fmpz_is_probabprime_BPSW(R)) /* fast test first */ { if (fmpz_is_prime(R) == 1) { _fmpz_factor_append(fac, R, 1); fmpz_set_ui(R, 1); } } } } else { if (fmpz_is_prime(R) == 1) { _fmpz_factor_append(fac, R, 1); fmpz_set_ui(R, 1); } } /* compute product F of found primes */ fmpz_set_ui(F, 1); for (i = 0; i < fac->num; i++) { if (fac->exp[i] == 1) fmpz_mul(F, F, fac->p + i); else { fmpz_pow_ui(ex, fac->p + i, fac->exp[i]); fmpz_mul(F, F, ex); } } /* Want D = A^2 - 4B where A = a, B = b, such that (D/n) = -1 */ for (b = 1; ; b++) { fmpz_set_ui(B, b); fmpz_gcd(g, B, n); if (fmpz_equal(g, n)) /* need gcd(n, b) = 1 */ continue; if (!fmpz_is_one(g)) /* found a factor of n */ { res = 0; goto cleanup; } a = 2; do { a++; fmpz_set_ui(A, a); fmpz_mul_ui(D, A, a); fmpz_sub_ui(D, D, 4*b); } while (fmpz_jacobi(D, n) != -1); fmpz_invmod(Dinv, D, n); /* compute U((n+1)/F) mod n */ fmpz_lucas_chain_full(Vm, Vm1, A, B, R, n); fmpz_lucas_chain_VtoU(Um, Um1, Vm, Vm1, A, B, Dinv, n); /* check U(n+1) = 0 mod n */ fmpz_lucas_chain_mul(Ukm, Ukm1, Um, Um1, A, B, F, n); if (!fmpz_is_zero(Ukm)) { res = 0; goto cleanup; } fmpz_set_ui(c, 1); /* find values U((n+1)/q) for each prime q dividing F */ for (i = 0; i < fac->num; i++) { fmpz_tdiv_q(ex, F, fac->p + i); fmpz_lucas_chain_mul(Ukm, Ukm1, Um, Um1, A, B, ex, n); if (!fmpz_is_zero(Ukm)) { fmpz_mul(c, c, Ukm); fmpz_mod(c, c, n); } else break; } if (i == fac->num) /* found valid base a */ break; } /* check for factors of n */ fmpz_gcd(g, n, c); res = fmpz_is_one(g); cleanup: fmpz_factor_clear(fac); fmpz_clear(D); fmpz_clear(Dinv); fmpz_clear(A); fmpz_clear(B); fmpz_clear(c); fmpz_clear(ex); fmpz_clear(p); fmpz_clear(q); fmpz_clear(r); fmpz_clear(g); fmpz_clear(Um); fmpz_clear(Um1); fmpz_clear(Ukm); fmpz_clear(Ukm1); fmpz_clear(Vm); fmpz_clear(Vm1); return res; } flint-3.1.3/src/fmpz/is_prime_pocklington.c000066400000000000000000000102441461254215100207610ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" void _fmpz_nm1_trial_factors(const fmpz_t n, mp_ptr pm1, slong * num_pm1, ulong limit) { slong i, num; ulong ppi, p; const ulong * primes; const double * pinv; *num_pm1 = 0; /* number of primes multiplied that will fit in a word */ num = FLINT_BITS/FLINT_BIT_COUNT(limit); /* compute remainders of n mod p for primes p up to limit (approx.) */ n_prime_pi_bounds(&ppi, &ppi, limit); /* precompute primes */ primes = n_primes_arr_readonly(ppi + FLINT_BITS); pinv = n_prime_inverses_arr_readonly(ppi + FLINT_BITS); while (primes[0] < limit) { /* multiply batch of primes */ p = primes[0]; for (i = 1; i < num; i++) p *= primes[i]; /* multi-modular reduction */ p = fmpz_tdiv_ui(n, p); /* check for factors */ for (i = 0; i < num; i++) { ulong r = n_mod2_precomp(p, primes[i], pinv[i]); if (r == 1) /* n - 1 = 0 mod p */ pm1[(*num_pm1)++] = primes[i]; } /* get next batch of primes */ primes += num; pinv += num; } } int fmpz_is_prime_pocklington(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pm1, slong num_pm1) { slong i, d, bits; ulong a; fmpz_t g, q, r, pow, pow2, ex, c, p; fmpz_factor_t fac; int res = 0, fac_found; fmpz_init(p); fmpz_init(q); fmpz_init(r); fmpz_init(g); fmpz_init(pow); fmpz_init(pow2); fmpz_init(c); fmpz_init(ex); fmpz_factor_init(fac); fmpz_sub_ui(R, n, 1); /* start with n - 1 */ bits = fmpz_bits(R); for (i = 0; i < num_pm1; i++) { fmpz_set_ui(p, pm1[i]); d = fmpz_remove(R, R, p); _fmpz_factor_append_ui(fac, pm1[i], d); } srand(time(NULL)); if (!fmpz_is_probabprime_BPSW(R)) { if (bits > 150 && (fac_found = fmpz_factor_pp1(p, R, bits + 1000, bits/20 + 1000, rand()%100 + 3) && fmpz_is_prime(p))) { d = fmpz_remove(R, R, p); _fmpz_factor_append(fac, p, d); if (fmpz_is_probabprime_BPSW(R)) /* fast test first */ { if (fmpz_is_prime(R) == 1) { _fmpz_factor_append(fac, R, 1); fmpz_set_ui(R, 1); } } } } else { if (fmpz_is_prime(R) == 1) { _fmpz_factor_append(fac, R, 1); fmpz_set_ui(R, 1); } } /* compute product F of found primes */ fmpz_set_ui(F, 1); for (i = 0; i < fac->num; i++) { if (fac->exp[i] == 1) fmpz_mul(F, F, fac->p + i); else { fmpz_pow_ui(pow, fac->p + i, fac->exp[i]); fmpz_mul(F, F, pow); } } for (a = 2; ; a++) { /* compute a^((n-1)/F) mod n */ fmpz_set_ui(pow, a); fmpz_powm(pow, pow, R, n); /* check a^(n-1) = 1 mod n */ fmpz_powm(pow2, pow, F, n); if (!fmpz_is_one(pow2)) { res = 0; goto cleanup; } fmpz_set_ui(c, 1); /* find values a^((n-1)/q) - 1 for each prime q dividing F */ for (i = 0; i < fac->num; i++) { fmpz_tdiv_q(ex, F, fac->p + i); fmpz_powm(pow2, pow, ex, n); fmpz_sub_ui(pow2, pow2, 1); if (fmpz_sgn(pow2) < 0) fmpz_add(pow2, pow2, n); if (!fmpz_is_zero(pow2)) { fmpz_mul(c, c, pow2); fmpz_mod(c, c, n); } else break; } if (i == fac->num) /* found valid base a */ break; } /* check for factors of n */ fmpz_gcd(g, n, c); res = fmpz_is_one(g); cleanup: fmpz_factor_clear(fac); fmpz_clear(pow); fmpz_clear(pow2); fmpz_clear(c); fmpz_clear(ex); fmpz_clear(p); fmpz_clear(q); fmpz_clear(r); fmpz_clear(g); return res; } flint-3.1.3/src/fmpz/is_prime_pseudosquare.c000066400000000000000000000203301461254215100211470ustar00rootroot00000000000000/* Copyright (C) 2009, 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #ifndef FLINT64 mp_limb_t flint_fmpz_pseudosquares[][3] = { { 17, 0, 0 }, { 73, 0, 0 }, { 241, 0, 0 }, { 1009, 0, 0 }, { 2641, 0, 0 }, { 8089, 0, 0 }, { 18001, 0, 0 }, { 53881, 0, 0 }, { 87481, 0, 0 }, { 117049, 0, 0 }, { 515761, 0, 0 }, { 1083289, 0, 0 }, { 3206641, 0, 0 }, { 3818929, 0, 0 }, { 9257329, 0, 0 }, { 22000801, 0, 0 }, { 48473881, 0, 0 }, { 48473881, 0, 0 }, { 175244281, 0, 0 }, { 427733329, 0, 0 }, { 427733329, 0, 0 }, { 898716289u, 0, 0 }, { 2805544681u, 0, 0 }, { 2805544681u, 0, 0 }, { 2805544681u, 0, 0 }, { 1720328849u, 2u, 0 }, { 2141495009u, 5u, 0 }, { 3553231785u, 19u, 0 }, { 3553231785u, 19u, 0 }, { 2991566689u, 45u, 0 }, { 2991566689u, 45u, 0 }, { 2804689073u, 668u, 0 }, { 2804689073u, 668u, 0 }, { 2804689073u, 668u, 0 }, { 46910577u, 6112u, 0 }, { 46910577u, 6112u, 0 }, { 1079027281u, 26178u, 0 }, { 1079027281u, 26178u, 0 }, { 1079027281u, 26178u, 0 }, { 3590018425u, 41661u, 0 }, { 3590018425u, 41661u, 0 }, { 2746102297u, 162087u, 0 }, { 2746102297u, 162087u, 0 }, { 1936779721u, 664710u, 0 }, { 1070451441u, 1501768u, 0 }, { 1070451441u, 1501768u, 0 }, { 2061289617u, 2710474u, 0 }, { 2061289617u, 2710474u, 0 }, { 4235760785u, 44382509u, 0 }, { 2312776601u, 45783875u, 0 }, { 2678348049u, 165920782u, 0 }, { 3315991761u, 413007985u, 0 }, { 1567179849u, 541956877u, 0 }, { 2273104657u, 1486621767u, 0 }, { 3796117489u, 1867116582u, 0 }, { 2425538377u, 2374430322u, 0 }, { 2425538377u, 2374430322u, 0 }, { 2425538377u, 2374430322u, 0 }, { 3763487577u, 3377920039u, 3u }, { 2972093785u, 1402148275u, 11u }, { 2785759393u, 3968325740u, 28u }, { 551239041u, 3335735663u, 50u }, { 551239041u, 3335735663u, 50u }, { 732515297u, 554264481u, 116u }, { 732515297u, 554264481u, 116u }, { 732515297u, 554264481u, 116u }, { 2681625681u, 3960593856u, 739u }, { 2546105329u, 1679561907u, 1875u }, { 533319201u, 2248012685u, 5393u }, { 533319201u, 2248012685u, 5393u }, { 996692113u, 2949507147u, 16011u }, { 996692113u, 2949507147u, 16011u }, { 2616068761u, 328479117u, 198156u }, { 1411295841u, 761797252u, 229581u } }; #else mp_limb_t flint_fmpz_pseudosquares[][2] = { { 17, 0 }, { 73, 0 }, { 241, 0 }, { 1009, 0 }, { 2641, 0 }, { 8089, 0 }, { 18001, 0 }, { 53881, 0 }, { 87481, 0 }, { 117049, 0 }, { 515761, 0 }, { 1083289, 0 }, { 3206641, 0 }, { 3818929, 0 }, { 9257329, 0 }, { 22000801, 0 }, { 48473881, 0 }, { 48473881, 0 }, { 175244281, 0 }, { 427733329, 0 }, { 427733329, 0 }, { 898716289u, 0 }, { 2805544681u, 0 }, { 2805544681u, 0 }, { 2805544681u, 0 }, { 10310263441u, 0 }, { 23616331489u, 0 }, { 85157610409u, 0 }, { 85157610409u, 0 }, { 196265095009u, 0 }, { 196265095009u, 0 }, { 2871842842801u, 0 }, { 2871842842801u, 0 }, { 2871842842801u, 0 }, { 26250887023729u, 0 }, { 26250887023729u, 0 }, { 112434732901969u, 0 }, { 112434732901969u, 0 }, { 112434732901969u, 0 }, { 178936222537081u, 0 }, { 178936222537081u, 0 }, { 696161110209049u, 0 }, { 696161110209049u, 0 }, { 2854909648103881u, 0 }, { 6450045516630769u, 0 }, { 6450045516630769u, 0 }, { 11641399247947921u, 0 }, { 11641399247947921u, 0 }, { 190621428905186449u, 0 }, { 196640248121928601u, 0 }, { 712624335095093521u, 0 }, { 1773855791877850321u, 0 }, { 2327687064124474441u, 0 }, { 6384991873059836689u, 0 }, { 8019204661305419761u, 0 }, { 10198100582046287689u, 0 }, { 10198100582046287689u, 0 }, { 10198100582046287689u, 0 }, { 14508056099771532121u, 3u }, { 6022180988239908185u, 11u }, { 17043829275960758433u, 28u }, { 14326875581237116289u, 50u }, { 14326875581237116289u, 50u }, { 2380547819961928673u, 116u }, { 2380547819961928673u, 116u }, { 2380547819961928673u, 116u }, { 17010621086940159057u, 739u }, { 7213663464718498801u, 1875u }, { 9655140963601468961u, 5393u }, { 9655140963601468961u, 5393u }, { 12668036736679956625u, 16011u }, { 12668036736679956625u, 16011u }, { 1410807067550026393u, 198156u }, { 3271894284933966433u, 229581u } }; #endif #define FLINT_NUM_FMPZ_PSEUDOSQUARES 74 void fmpz_set_pseudosquare(fmpz_t f, unsigned int i) { #ifndef FLINT64 if (i < 25) fmpz_set_ui(f, flint_fmpz_pseudosquares[i][0]); else if (i < 58) { fmpz_set_ui(f, flint_fmpz_pseudosquares[i][1]); fmpz_mul_2exp(f, f, 32); fmpz_add_ui(f, f, flint_fmpz_pseudosquares[i][0]); } else if (i < FLINT_NUM_FMPZ_PSEUDOSQUARES) { fmpz_set_ui(f, flint_fmpz_pseudosquares[i][2]); fmpz_mul_2exp(f, f, 32); fmpz_add_ui(f, f, flint_fmpz_pseudosquares[i][1]); fmpz_mul_2exp(f, f, 32); fmpz_add_ui(f, f, flint_fmpz_pseudosquares[i][1]); } #else if (i < 58) fmpz_set_ui(f, flint_fmpz_pseudosquares[i][0]); else if (i < FLINT_NUM_FMPZ_PSEUDOSQUARES) { fmpz_set_ui(f, flint_fmpz_pseudosquares[i][1]); fmpz_mul_2exp(f, f, 64); fmpz_add_ui(f, f, flint_fmpz_pseudosquares[i][0]); } #endif else { flint_throw(FLINT_ERROR, "Exception (fmpz_set_pseudosquare). Index too large.\n"); } } int fmpz_is_prime_pseudosquare(const fmpz_t n) { unsigned int i, j, m1; mp_limb_t p, B, mod8; fmpz_t NB, f, exp, mod, nm1; int ret; const mp_limb_t * primes; if (fmpz_sgn(n) <= 0) return 0; if (fmpz_size(n) == 1) return n_is_prime_pseudosquare(fmpz_get_ui(n)); primes = n_primes_arr_readonly(FLINT_PSEUDOSQUARES_CUTOFF + 1); for (i = 0; i < FLINT_PSEUDOSQUARES_CUTOFF; i++) { p = primes[i]; if (fmpz_fdiv_ui(n, p) == 0) return 0; } fmpz_init(NB); fmpz_init(f); fmpz_init(exp); fmpz_init(mod); fmpz_init(nm1); B = primes[FLINT_PSEUDOSQUARES_CUTOFF]; fmpz_sub_ui(nm1, n, 1); fmpz_fdiv_q_ui(NB, nm1, B); fmpz_add_ui(NB, NB, 1); m1 = 0; for (i = 0; i < FLINT_NUM_FMPZ_PSEUDOSQUARES; i++) { fmpz_set_pseudosquare(f, i); if (fmpz_cmp(f, NB) > 0) break; } if (i == FLINT_NUM_FMPZ_PSEUDOSQUARES) { ret = -1; goto cleanup; } fmpz_fdiv_q_2exp(exp, nm1, 1); for (j = 0; j <= i; j++) { fmpz_set_ui(mod, primes[j]); fmpz_powm(mod, mod, exp, n); if (!fmpz_is_one(mod) && fmpz_cmp(mod, nm1) != 0) { ret = 0; goto cleanup; } if (fmpz_cmp(mod, nm1) == 0) m1 = 1; } mod8 = fmpz_fdiv_ui(n, 8); if ((mod8 == 3) || (mod8 == 7)) { ret = 1; goto cleanup; } if (mod8 == 5) { fmpz_set_ui(mod, 2); fmpz_powm(mod, mod, exp, n); if (fmpz_cmp(mod, nm1) == 0) { ret = 1; goto cleanup; } flint_throw(FLINT_ERROR, "%s is a probable prime, but not prime, please report!!\n", fmpz_get_str(NULL, 10, n)); } else { if (m1) { ret = 1; goto cleanup; } for (j = i + 1; j < FLINT_NUM_FMPZ_PSEUDOSQUARES + 1; j++) { fmpz_set_ui(mod, primes[j]); fmpz_powm(mod, mod, exp, n); if (fmpz_cmp(mod, nm1) == 0) { ret = 1; goto cleanup; } if (!fmpz_is_one(mod)) { flint_throw(FLINT_ERROR, "%s is a probable prime, but not prime, please report!!\n", fmpz_get_str(NULL, 10, n)); } } flint_throw(FLINT_ERROR, "%s is a probable prime, but not prime, please report!!\n", fmpz_get_str(NULL, 10, n)); } cleanup: fmpz_clear(NB); fmpz_clear(f); fmpz_clear(exp); fmpz_clear(mod); fmpz_clear(nm1); return ret; } flint-3.1.3/src/fmpz/is_probabprime_BPSW.c000066400000000000000000000013361461254215100203750ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" int fmpz_is_probabprime_BPSW(const fmpz_t n) { fmpz_t b; int res = 1; fmpz_init_set_ui(b, 2); if (!fmpz_is_strong_probabprime(n, b) || !fmpz_is_probabprime_lucas(n)) res = 0; fmpz_clear(b); return res; } flint-3.1.3/src/fmpz/is_probabprime_lucas.c000066400000000000000000000037641461254215100207400ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" int fmpz_is_probabprime_lucas(const fmpz_t n) { fmpz_t A, Q, D, t, m, Vm, Vm1; int res = 0; if (fmpz_cmp_ui(n, 1) <= 0) return 0; if (fmpz_is_even(n)) return fmpz_cmp_ui(n, 2) == 0; /* ensure 2, n coprime */ if (fmpz_is_square(n)) return 0; fmpz_init(A); fmpz_init(Q); fmpz_init(D); fmpz_init(t); fmpz_init(m); fmpz_init(Vm); fmpz_init(Vm1); fmpz_set_si(D, WORD(-3)); /* -3 becomes 5 after first iteration */ do { /* check D = 5, -7, 9, -11 such that (D/n) = -1 */ do { if (fmpz_sgn(D) > 0) fmpz_add_ui(D, D, 2); else fmpz_sub_ui(D, D, 2); fmpz_neg(D, D); } while (fmpz_jacobi(D, n) != -1); /* this ensures D, n coprime */ fmpz_sub_ui(t, D, 1); fmpz_neg(t, t); fmpz_tdiv_q_2exp(Q, t, 2); fmpz_gcd(t, Q, n); /* require Q, n coprime */ } while (fmpz_equal(t, n)); if (fmpz_is_one(t)) /* check no factor found */ { fmpz_invmod(A, Q, n); /* A = P^2Q^-1 - 2 mod n, where P = 1 */ fmpz_sub_ui(A, A, 2); if (fmpz_sgn(A) < 0) fmpz_add(A, A, n); fmpz_add_ui(m, n, 1); /* m = (n - jacobi(D/n))/2 = (n + 1)/2 */ fmpz_tdiv_q_2exp(m, m, 1); fmpz_lucas_chain(Vm, Vm1, A, m, n); fmpz_mul(Vm, Vm, A); fmpz_submul_ui(Vm, Vm1, 2); res = fmpz_divisible(Vm, n); } fmpz_clear(A); fmpz_clear(Q); fmpz_clear(D); fmpz_clear(t); fmpz_clear(m); fmpz_clear(Vm); fmpz_clear(Vm1); return res; } flint-3.1.3/src/fmpz/is_square.c000066400000000000000000000012561461254215100165410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_is_square(const fmpz_t x) { fmpz c = *x; if (!COEFF_IS_MPZ(c)) { if (c <= 1) return (c >= 0); return n_is_square(c); } else return mpz_perfect_square_p(COEFF_TO_PTR(c)); } flint-3.1.3/src/fmpz/is_strong_probabprime.c000066400000000000000000000025751461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" int fmpz_is_strong_probabprime(const fmpz_t n, const fmpz_t base) { fmpz_t a, nm1, t, y; int res = 0; if (fmpz_cmp_ui(n, 1) <= 0) return 0; fmpz_init(a); fmpz_init(t); fmpz_init(nm1); fmpz_sub_ui(nm1, n, 1); if (fmpz_cmp(base, n) >= 0) fmpz_mod(a, base, n); else fmpz_set(a, base); if (fmpz_is_one(a) || fmpz_equal(a, nm1) || fmpz_is_zero(a)) res = 1; else { slong s = 0; fmpz_init(y); s = fmpz_val2(nm1); fmpz_tdiv_q_2exp(t, nm1, s); fmpz_powm(y, a, t, n); if (fmpz_is_one(y)) res = 1; else { for (s--; s > 0 && !fmpz_equal(y, nm1); s--) { fmpz_mul(t, y, y); fmpz_mod(y, t, n); } res = fmpz_equal(y, nm1); } fmpz_clear(y); } fmpz_clear(nm1); fmpz_clear(a); fmpz_clear(t); return res; } flint-3.1.3/src/fmpz/jacobi.c000066400000000000000000000017701461254215100157760ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_jacobi(const fmpz_t a, const fmpz_t p) { fmpz c = *p; fmpz d = *a; mpz_t t, u; int r; if (!COEFF_IS_MPZ(c) && !COEFF_IS_MPZ(d)) return n_jacobi(d, c); if (COEFF_IS_MPZ(c) && COEFF_IS_MPZ(d)) return mpz_jacobi(COEFF_TO_PTR(d), COEFF_TO_PTR(c)); if (d == 0) return 0; /* a is zero and p is large */ flint_mpz_init_set_readonly(t, a); flint_mpz_init_set_readonly(u, p); r = mpz_jacobi(t, u); flint_mpz_clear_readonly(t); flint_mpz_clear_readonly(u); return r; } flint-3.1.3/src/fmpz/kronecker.c000066400000000000000000000017131461254215100165270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "long_extras.h" #include "fmpz.h" int fmpz_kronecker(const fmpz_t a, const fmpz_t n) { fmpz A = *a; fmpz N = *n; mpz_t aa, nn; int r; if (!COEFF_IS_MPZ(A) && !COEFF_IS_MPZ(N)) return z_kronecker(A, N); if (COEFF_IS_MPZ(A) && COEFF_IS_MPZ(N)) return mpz_kronecker(COEFF_TO_PTR(A), COEFF_TO_PTR(N)); flint_mpz_init_set_readonly(aa, a); flint_mpz_init_set_readonly(nn, n); r = mpz_kronecker(aa, nn); flint_mpz_clear_readonly(aa); flint_mpz_clear_readonly(nn); return r; } flint-3.1.3/src/fmpz/lcm.c000066400000000000000000000015541461254215100153220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" void fmpz_lcm(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz_t t; if (fmpz_is_zero(g) || fmpz_is_zero(h)) { fmpz_zero(f); return; } if (fmpz_is_pm1(g)) { fmpz_abs(f, h); return; } if (fmpz_is_pm1(h)) { fmpz_abs(f, g); return; } fmpz_init(t); fmpz_gcd(t, g, h); fmpz_divexact(t, g, t); fmpz_mul(f, t, h); fmpz_abs(f, f); fmpz_clear(t); } flint-3.1.3/src/fmpz/link/000077500000000000000000000000001461254215100153335ustar00rootroot00000000000000flint-3.1.3/src/fmpz/link/fmpz_gc.c000066400000000000000000000103661461254215100171320ustar00rootroot00000000000000/* Copyright (C) 2009, 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" #if FLINT_USES_PTHREAD #include static pthread_once_t fmpz_initialised = PTHREAD_ONCE_INIT; pthread_mutex_t fmpz_lock; #endif /* Always free larger mpz's to avoid wasting too much heap space */ #define FLINT_MPZ_MAX_CACHE_LIMBS 64 /* The number of new mpz's allocated at a time */ #define MPZ_BLOCK 64 /* there's no point using TLS here as GC doesn't support it */ __mpz_struct ** mpz_free_arr = NULL; __mpz_struct ** mpz_arr = NULL; ulong mpz_num = 0; ulong mpz_alloc = 0; ulong mpz_free_num = 0; ulong mpz_free_alloc = 0; #if FLINT_USES_PTHREAD void fmpz_lock_init() { pthread_mutex_init(&fmpz_lock, NULL); } #endif __mpz_struct * _fmpz_new_mpz(void) { __mpz_struct * z = NULL; #if FLINT_USES_PTHREAD pthread_once(&fmpz_initialised, fmpz_lock_init); pthread_mutex_lock(&fmpz_lock); #endif if (mpz_free_num != 0) z = mpz_free_arr[--mpz_free_num]; else { z = flint_malloc(sizeof(__mpz_struct)); if (mpz_num == mpz_alloc) /* store pointer to prevent gc cleanup */ { mpz_alloc = FLINT_MAX(64, mpz_alloc * 2); mpz_arr = flint_realloc(mpz_arr, mpz_alloc * sizeof(__mpz_struct *)); } mpz_arr[mpz_num++] = z; mpz_init(z); } #if FLINT_USES_PTHREAD pthread_mutex_unlock(&fmpz_lock); #endif return z; } void _fmpz_clear_mpz(fmpz f) { __mpz_struct * ptr = COEFF_TO_PTR(f); if (ptr->_mp_alloc > FLINT_MPZ_MAX_CACHE_LIMBS) mpz_realloc2(ptr, 1); #if FLINT_USES_PTHREAD pthread_mutex_lock(&fmpz_lock); #endif if (mpz_free_num == mpz_free_alloc) { mpz_free_alloc = FLINT_MAX(64, mpz_free_alloc * 2); mpz_free_arr = flint_realloc(mpz_free_arr, mpz_free_alloc * sizeof(__mpz_struct *)); } mpz_free_arr[mpz_free_num++] = ptr; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&fmpz_lock); #endif } void _fmpz_cleanup_mpz_content(void) { ulong i; for (i = 0; i < mpz_free_num; i++) { mpz_clear(mpz_free_arr[i]); flint_free(mpz_free_arr[i]); } /* TODO: remove selected mpz's from mpz_arr too and compact */ mpz_free_num = mpz_free_alloc = 0; } void _fmpz_cleanup(void) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&fmpz_lock); #endif _fmpz_cleanup_mpz_content(); flint_free(mpz_free_arr); mpz_free_arr = NULL; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&fmpz_lock); #endif } __mpz_struct * _fmpz_promote(fmpz_t f) { if (!COEFF_IS_MPZ(*f)) /* f is small so promote it first */ { __mpz_struct * mf = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mf); return mf; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(*f); } __mpz_struct * _fmpz_promote_val(fmpz_t f) { fmpz c = (*f); if (!COEFF_IS_MPZ(c)) /* f is small so promote it */ { __mpz_struct * mf = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mf); flint_mpz_set_si(mf, c); return mf; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(c); } void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mf = COEFF_TO_PTR(*f); int size = mf->_mp_size; if (size == 1 || size == -1) { ulong uval = mf->_mp_d[0]; if (uval <= (ulong) COEFF_MAX) { _fmpz_clear_mpz(*f); *f = size * (fmpz) uval; } } else if (size == 0) /* value is 0 */ { _fmpz_clear_mpz(*f); *f = 0; } /* don't do anything if value has to be multi precision */ } void _fmpz_init_readonly_mpz(fmpz_t f, const mpz_t z) { __mpz_struct *ptr; *f = WORD(0); ptr = _fmpz_promote(f); mpz_clear(ptr); *ptr = *z; } void _fmpz_clear_readonly_mpz(mpz_t z) { if (((z->_mp_size == 1 || z->_mp_size == -1) && (z->_mp_d[0] <= COEFF_MAX)) || (z->_mp_size == 0)) { mpz_clear(z); } } flint-3.1.3/src/fmpz/link/fmpz_reentrant.c000066400000000000000000000043671461254215100205470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" __mpz_struct * _fmpz_new_mpz(void) { __mpz_struct * mf = (__mpz_struct *) flint_malloc(sizeof(__mpz_struct)); mpz_init2(mf, 2*FLINT_BITS); return mf; } void _fmpz_clear_mpz(fmpz f) { mpz_clear(COEFF_TO_PTR(f)); flint_free(COEFF_TO_PTR(f)); } void _fmpz_cleanup_mpz_content(void) { } void _fmpz_cleanup(void) { } __mpz_struct * _fmpz_promote(fmpz_t f) { if (!COEFF_IS_MPZ(*f)) /* f is small so promote it first */ { __mpz_struct * mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); return mf; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(*f); } __mpz_struct * _fmpz_promote_val(fmpz_t f) { fmpz c = *f; if (!COEFF_IS_MPZ(c)) /* f is small so promote it */ { __mpz_struct * mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); flint_mpz_set_si(mf, c); return mf; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(*f); } void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mf = COEFF_TO_PTR(*f); int size = mf->_mp_size; if (!(((unsigned int) size + 1U) & ~2U)) /* size +-1 */ { ulong uval = mf->_mp_d[0]; if (uval <= (ulong) COEFF_MAX) { _fmpz_clear_mpz(*f); *f = size * (fmpz) uval; } } else if (size == 0) /* value is 0 */ { _fmpz_clear_mpz(*f); *f = 0; } /* don't do anything if value has to be multi precision */ } void _fmpz_init_readonly_mpz(fmpz_t f, const mpz_t z) { __mpz_struct * mf = (__mpz_struct *) flint_malloc(sizeof(__mpz_struct)); *f = PTR_TO_COEFF(mf); *mf = *z; } void _fmpz_clear_readonly_mpz(mpz_t z) { if (((z->_mp_size == 1 || z->_mp_size == -1) && (z->_mp_d[0] <= COEFF_MAX)) || (z->_mp_size == 0)) { mpz_clear(z); } } flint-3.1.3/src/fmpz/link/fmpz_single.c000066400000000000000000000161431461254215100200210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __unix__ # include /* sysconf */ #endif #if defined(_WIN32) || defined(WIN32) # include /* GetSystemInfo */ #endif #include "gmpcompat.h" #include "fmpz.h" #if FLINT_USES_PTHREAD # include # include #endif #if FLINT_USES_PTHREAD typedef struct { _Atomic(int) count; pthread_t thread; void * address; } fmpz_block_header_s; #else typedef struct { int count; void * address; } fmpz_block_header_s; #endif /* Always free larger mpz's to avoid wasting too much heap space */ #define FLINT_MPZ_MAX_CACHE_LIMBS 64 #define PAGES_PER_BLOCK 16 /* The number of new mpz's allocated at a time */ #define MPZ_BLOCK 64 FLINT_TLS_PREFIX __mpz_struct ** mpz_free_arr = NULL; FLINT_TLS_PREFIX ulong mpz_free_num = 0; FLINT_TLS_PREFIX ulong mpz_free_alloc = 0; static slong flint_page_size; static slong flint_mpz_structs_per_block; static slong flint_page_mask; slong flint_get_page_size(void) { #if defined(__unix__) return sysconf(_SC_PAGESIZE); #elif defined(_WIN32) || defined(WIN32) SYSTEM_INFO si; GetSystemInfo(&si); return si.dwPageSize; #else return 4096; #endif } static inline void * flint_align_ptr(void * ptr, slong size) { slong mask = ~(size - 1); return (void *)((mask & (slong) ptr) + size); } __mpz_struct * _fmpz_new_mpz(void) { if (mpz_free_num == 0) /* allocate more mpz's */ { void * aligned_ptr, * ptr; slong i, j, num, block_size, skip; flint_page_size = flint_get_page_size(); block_size = PAGES_PER_BLOCK*flint_page_size; flint_page_mask = ~(flint_page_size - 1); /* get new block */ ptr = flint_malloc(block_size + flint_page_size); /* align to page boundary */ aligned_ptr = flint_align_ptr(ptr, flint_page_size); /* set free count to zero and determine if this is the main thread */ ((fmpz_block_header_s *) ptr)->count = 0; #if FLINT_USES_PTHREAD ((fmpz_block_header_s *) ptr)->thread = pthread_self(); #endif /* how many __mpz_structs worth are dedicated to header, per page */ skip = (sizeof(fmpz_block_header_s) - 1)/sizeof(__mpz_struct) + 1; /* total number of number of __mpz_structs worth per page */ num = flint_page_size/sizeof(__mpz_struct); flint_mpz_structs_per_block = PAGES_PER_BLOCK*(num - skip); for (i = 0; i < PAGES_PER_BLOCK; i++) { __mpz_struct * page_ptr = (__mpz_struct *)((slong) aligned_ptr + i*flint_page_size); /* set pointer in each page to start of entire block */ ((fmpz_block_header_s *) page_ptr)->address = ptr; for (j = skip; j < num; j++) { mpz_init2(page_ptr + j, 2*FLINT_BITS); /* Cannot be lifted from loop due to possibility of gc calling _fmpz_clear_mpz during call to mpz_init_2 */ if (mpz_free_num >= mpz_free_alloc) { mpz_free_alloc = FLINT_MAX(mpz_free_num + 1, mpz_free_alloc * 2); mpz_free_arr = flint_realloc(mpz_free_arr, mpz_free_alloc * sizeof(__mpz_struct *)); } mpz_free_arr[mpz_free_num++] = page_ptr + j; } } } return mpz_free_arr[--mpz_free_num]; } void _fmpz_clear_mpz(fmpz f) { __mpz_struct * ptr = COEFF_TO_PTR(f); /* check free count for block is zero, else this mpz came from a thread */ fmpz_block_header_s * header_ptr = (fmpz_block_header_s *)((slong) ptr & flint_page_mask); header_ptr = (fmpz_block_header_s *) header_ptr->address; /* clean up if this is left over from another thread */ #if FLINT_USES_PTHREAD if (header_ptr->count != 0 || !pthread_equal(header_ptr->thread, pthread_self())) #else if (header_ptr->count != 0) #endif { int new_count; mpz_clear(ptr); #if FLINT_USES_PTHREAD new_count = atomic_fetch_add(&(header_ptr->count), 1) + 1; #else new_count = ++header_ptr->count; #endif if (new_count == flint_mpz_structs_per_block) flint_free(header_ptr); } else { if (ptr->_mp_alloc > FLINT_MPZ_MAX_CACHE_LIMBS) mpz_realloc2(ptr, 2*FLINT_BITS); if (mpz_free_num == mpz_free_alloc) { mpz_free_alloc = FLINT_MAX(64, mpz_free_alloc * 2); mpz_free_arr = flint_realloc(mpz_free_arr, mpz_free_alloc * sizeof(__mpz_struct *)); } mpz_free_arr[mpz_free_num++] = ptr; } } void _fmpz_cleanup_mpz_content(void) { ulong i; for (i = 0; i < mpz_free_num; i++) { int new_count; fmpz_block_header_s * ptr; mpz_clear(mpz_free_arr[i]); /* update count of cleared mpz's for block */ ptr = (fmpz_block_header_s *)((slong) mpz_free_arr[i] & ~(flint_page_size - 1)); ptr = (fmpz_block_header_s *) ptr->address; #if FLINT_USES_PTHREAD new_count = atomic_fetch_add(&(ptr->count), 1) + 1; #else new_count = ++ptr->count; #endif if (new_count == flint_mpz_structs_per_block) flint_free(ptr); } mpz_free_num = mpz_free_alloc = 0; } void _fmpz_cleanup(void) { _fmpz_cleanup_mpz_content(); flint_free(mpz_free_arr); mpz_free_arr = NULL; } __mpz_struct * _fmpz_promote(fmpz_t f) { if (!COEFF_IS_MPZ(*f)) /* f is small so promote it first */ { __mpz_struct * mf = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mf); return mf; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(*f); } __mpz_struct * _fmpz_promote_val(fmpz_t f) { fmpz c = (*f); if (!COEFF_IS_MPZ(c)) /* f is small so promote it */ { __mpz_struct * mf = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mf); flint_mpz_set_si(mf, c); return mf; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(c); } void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mf = COEFF_TO_PTR(*f); int size = mf->_mp_size; if (size == 1 || size == -1) { ulong uval = mf->_mp_d[0]; if (uval <= (ulong) COEFF_MAX) { _fmpz_clear_mpz(*f); *f = size * (fmpz) uval; } } else if (size == 0) /* value is 0 */ { _fmpz_clear_mpz(*f); *f = 0; } /* don't do anything if value has to be multi precision */ } void _fmpz_init_readonly_mpz(fmpz_t f, const mpz_t z) { __mpz_struct *ptr; *f = WORD(0); ptr = _fmpz_promote(f); mpz_clear(ptr); *ptr = *z; } void _fmpz_clear_readonly_mpz(mpz_t z) { if (((z->_mp_size == 1 || z->_mp_size == -1) && (z->_mp_d[0] <= COEFF_MAX)) || (z->_mp_size == 0)) { mpz_clear(z); } } flint-3.1.3/src/fmpz/logic.c000066400000000000000000000141471461254215100156460ustar00rootroot00000000000000/* Copyright (C) 2012 Thomas M. DuBuisson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" void fmpz_and(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1,c2; c1 = *g; c2 = *h; if(!COEFF_IS_MPZ(c1)) { if(!COEFF_IS_MPZ(c2)) /* both inputs are small */ { fmpz_set_si(f, c1 & c2); } else /* g is small, h is large */ { mpz_t tmp; __mpz_struct *mpz3 = _fmpz_promote(f); flint_mpz_init_set_si(tmp, c1); mpz_and(mpz3, COEFF_TO_PTR(c2), tmp); _fmpz_demote_val(f); mpz_clear(tmp); } } else { if(!COEFF_IS_MPZ(c2)) /* g is large, h is small */ { mpz_t tmp; __mpz_struct *mpz3 = _fmpz_promote(f); flint_mpz_init_set_si(tmp, c2); mpz_and(mpz3, COEFF_TO_PTR(c1), tmp); _fmpz_demote_val(f); mpz_clear(tmp); } else /* g and h are large */ { __mpz_struct * mpz3 = _fmpz_promote(f); __mpz_struct * mpz1 = COEFF_TO_PTR(c1); __mpz_struct * mpz2 = COEFF_TO_PTR(c2); mpz_and(mpz3, mpz1, mpz2); _fmpz_demote_val(f); } } } void fmpz_complement(fmpz_t r, const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) /* f is small */ { slong res = ~(*f); fmpz_set_si(r, res); } else /* f is big */ { if(r != f) { /* not aliased */ __mpz_struct *ptr, *ptr2; ptr = _fmpz_promote(r); ptr2 = COEFF_TO_PTR(*f); mpz_com(ptr, ptr2); _fmpz_demote_val(r); } else { /* alaised */ fmpz_t tmp; __mpz_struct *ptr, *ptr2; fmpz_init(tmp); ptr = _fmpz_promote(tmp); ptr2 = COEFF_TO_PTR(*f); mpz_com(ptr, ptr2); _fmpz_demote_val(tmp); fmpz_set(r,tmp); fmpz_clear(tmp); } } } void fmpz_or(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1,c2; c1 = *g; c2 = *h; if(!COEFF_IS_MPZ(c1)) { if(!COEFF_IS_MPZ(c2)) /* both inputs are small */ { fmpz_set_si(f, c1 | c2); } else /* g is small, h is large */ { mpz_t tmp; __mpz_struct * mpz3 = _fmpz_promote(f); flint_mpz_init_set_si(tmp,c1); mpz_ior(mpz3, COEFF_TO_PTR(c2), tmp); _fmpz_demote_val(f); mpz_clear(tmp); } } else { if(!COEFF_IS_MPZ(c2)) /* g is large, h is small */ { mpz_t tmp; __mpz_struct *mpz3 = _fmpz_promote(f); flint_mpz_init_set_si(tmp,c2); mpz_ior(mpz3, COEFF_TO_PTR(c1), tmp); _fmpz_demote_val(f); mpz_clear(tmp); } else /* g and h are large */ { __mpz_struct * mpz3 = _fmpz_promote(f); __mpz_struct * mpz1 = COEFF_TO_PTR(c1); __mpz_struct * mpz2 = COEFF_TO_PTR(c2); mpz_ior(mpz3, mpz1, mpz2); _fmpz_demote_val(f); } } } void fmpz_xor(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1,c2; c1 = *g; c2 = *h; if(!COEFF_IS_MPZ(c1)) { if(!COEFF_IS_MPZ(c2)) /* both inputs are small */ { fmpz_set_si(f, c1 ^ c2); } else /* g is small, h is large */ { mpz_t tmp; __mpz_struct * mpz3 = _fmpz_promote(f); flint_mpz_init_set_si(tmp, c1); mpz_xor(mpz3, COEFF_TO_PTR(c2), tmp); _fmpz_demote_val(f); mpz_clear(tmp); } } else { if(!COEFF_IS_MPZ(c2)) /* g is large, h is small */ { mpz_t tmp; __mpz_struct *mpz3 = _fmpz_promote(f); flint_mpz_init_set_si(tmp, c2); mpz_xor(mpz3, COEFF_TO_PTR(c1), tmp); _fmpz_demote_val(f); mpz_clear(tmp); } else /* g and h are large */ { __mpz_struct * mpz3 = _fmpz_promote(f); __mpz_struct * mpz1 = COEFF_TO_PTR(c1); __mpz_struct * mpz2 = COEFF_TO_PTR(c2); mpz_xor(mpz3, mpz1, mpz2); _fmpz_demote_val(f); } } } void fmpz_clrbit(fmpz_t f, ulong i) { if (!COEFF_IS_MPZ(*f)) { if (i < SMALL_FMPZ_BITCOUNT_MAX) { *f &= ~(WORD(1) << i); } /* i >= FLINT_BITS --> nop */ } else { __mpz_struct *ptr = COEFF_TO_PTR(*f); mpz_clrbit(ptr, i); _fmpz_demote_val(f); } } void fmpz_combit(fmpz_t f, ulong i) { if (!COEFF_IS_MPZ(*f)) { if (i < SMALL_FMPZ_BITCOUNT_MAX) { *f ^= (WORD(1) << i); } else /* i >= FLINT_BITS */ { __mpz_struct *ptr = _fmpz_promote_val(f); mpz_combit(ptr, i); _fmpz_demote_val(f); } } else { __mpz_struct *ptr = COEFF_TO_PTR(*f); mpz_combit(ptr, i); _fmpz_demote_val(f); } } flint_bitcnt_t fmpz_popcnt(const fmpz_t c) { mp_limb_t d; fmpz c1 = *c; if (!COEFF_IS_MPZ(c1)) { if (c1 < 0) return 0; d = c1; return mpn_popcount(&d, 1); } else { __mpz_struct *t = COEFF_TO_PTR(c1); if (mpz_sgn(t) < 0) return 0; else return mpz_popcount(t); } } flint-3.1.3/src/fmpz/lucas_chain.c000066400000000000000000000122731461254215100170200ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" void fmpz_lucas_chain(fmpz_t Vm, fmpz_t Vm1, const fmpz_t A, const fmpz_t m, const fmpz_t n) { fmpz_t t; slong i, B = fmpz_sizeinbase(m, 2); fmpz_init(t); fmpz_set_ui(Vm, 2); fmpz_set(Vm1, A); for (i = B - 1; i >= 0; i--) { if (fmpz_tstbit(m, i)) /* 1 in binary repn */ { fmpz_mul(t, Vm, Vm1); fmpz_sub(t, t, A); fmpz_mod(Vm, t, n); fmpz_mul(t, Vm1, Vm1); fmpz_sub_ui(t, t, 2); fmpz_mod(Vm1, t, n); } else /* 0 in binary repn */ { fmpz_mul(t, Vm, Vm1); fmpz_sub(t, t, A); fmpz_mod(Vm1, t, n); fmpz_mul(t, Vm, Vm); fmpz_sub_ui(t, t, 2); fmpz_mod(Vm, t, n); } } fmpz_clear(t); } void fmpz_lucas_chain_full(fmpz_t Vm, fmpz_t Vm1, const fmpz_t A, const fmpz_t B, const fmpz_t m, const fmpz_t n) { fmpz_t t, Q; slong i, bits = fmpz_sizeinbase(m, 2); fmpz_init(t); fmpz_init(Q); fmpz_set_ui(Q, 1); fmpz_set_ui(Vm, 2); fmpz_set(Vm1, A); for (i = bits - 1; i >= 0; i--) { if (fmpz_tstbit(m, i)) /* 1 in binary repn */ { fmpz_mul(t, Vm1, Vm); fmpz_submul(t, Q, A); fmpz_mod(Vm, t, n); fmpz_mul(Vm1, Vm1, Vm1); fmpz_mul_ui(t, Q, 2); fmpz_mul(t, t, B); fmpz_sub(Vm1, Vm1, t); fmpz_mod(Vm1, Vm1, n); fmpz_mul(Q, Q, Q); fmpz_mul(Q, Q, B); fmpz_mod(Q, Q, n); } else /* 0 in binary repn */ { fmpz_mul(t, Vm, Vm1); fmpz_submul(t, Q, A); fmpz_mod(Vm1, t, n); fmpz_mul(t, Vm, Vm); fmpz_submul_ui(t, Q, 2); fmpz_mod(Vm, t, n); fmpz_mul(Q, Q, Q); fmpz_mod(Q, Q, n); } } fmpz_clear(Q); fmpz_clear(t); } /* Compute U_{2m}, U_{2m + 1} given U_m, U_{m + 1} */ void fmpz_lucas_chain_double(fmpz_t U2m, fmpz_t U2m1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t A, const fmpz_t B, const fmpz_t n) { fmpz_t t, t2; fmpz_init(t); fmpz_init(t2); fmpz_mul_2exp(t, Um1, 1); /* U_m(2U_{m+1) - AU_m) */ fmpz_submul(t, Um, A); fmpz_mul(t, t, Um); fmpz_mul(U2m1, Um1, Um1); /* U_{m+1}^2 - BU_m^2 */ fmpz_mul(t2, Um, Um); fmpz_submul(U2m1, t2, B); fmpz_mod(U2m1, U2m1, n); fmpz_mod(U2m, t, n); fmpz_clear(t); fmpz_clear(t2); } /* Compute U_{m + n}, U_{m + n + 1} given U_m, U_{m + 1} and U_n, U_{n + 1} */ void fmpz_lucas_chain_add(fmpz_t Umn, fmpz_t Umn1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t Un, const fmpz_t Un1, const fmpz_t A, const fmpz_t B, const fmpz_t n) { fmpz_t t, t2; fmpz_init(t); fmpz_init(t2); fmpz_mul(t, Un, A); /* U_nU_{m + 1} - BU_m(AU_n - U_{n + 1})/B */ fmpz_sub(t, Un1, t); fmpz_mul(t, t, Um); fmpz_addmul(t, Un, Um1); fmpz_mul(Umn1, Un1, Um1); /* U_{n + 1}U_{m + 1} - BU_mU_n */ fmpz_mul(t2, Um, Un); fmpz_submul(Umn1, t2, B); fmpz_mod(Umn1, Umn1, n); fmpz_mod(Umn, t, n); fmpz_clear(t); fmpz_clear(t2); } /* Compute U_{km}, U_{km + 1} from U_m, U_{m + 1}, k > 0 */ void fmpz_lucas_chain_mul(fmpz_t Ukm, fmpz_t Ukm1, const fmpz_t Um, const fmpz_t Um1, const fmpz_t A, const fmpz_t B, const fmpz_t k, const fmpz_t n) { slong i = 0, b = fmpz_sizeinbase(k, 2); fmpz_t t, t1; fmpz_init(t); fmpz_init(t1); fmpz_set(Ukm, Um); fmpz_set(Ukm1, Um1); while (!fmpz_tstbit(k, i)) { fmpz_lucas_chain_double(Ukm, Ukm1, Ukm, Ukm1, A, B, n); i++; } i++; if (i < b) { fmpz_set(t, Ukm); fmpz_set(t1, Ukm1); } while (i < b) { fmpz_lucas_chain_double(t, t1, t, t1, A, B, n); if (fmpz_tstbit(k, i)) fmpz_lucas_chain_add(Ukm, Ukm1, Ukm, Ukm1, t, t1, A, B, n); i++; } fmpz_clear(t); fmpz_clear(t1); } /* Compute U_m, U_{m + 1} from V_m, V_{m + 1} */ void fmpz_lucas_chain_VtoU(fmpz_t Um, fmpz_t Um1, const fmpz_t Vm, const fmpz_t Vm1, const fmpz_t A, const fmpz_t B, const fmpz_t Dinv, const fmpz_t n) { fmpz_t t; fmpz_init(t); fmpz_mul_2exp(t, Vm1, 1); /* (2V_{m + 1} - AV_m) / D */ fmpz_submul(t, Vm, A); fmpz_mul(t, t, Dinv); fmpz_set(Um1, Vm); fmpz_mod(Um, t, n); fmpz_addmul(Um1, Um, A); /* (V_m + AU_m) / 2 */ if (!fmpz_is_even(Um1)) fmpz_add(Um1, Um1, n); fmpz_tdiv_q_2exp(Um1, Um1, 1); fmpz_mod(Um1, Um1, n); fmpz_clear(t); } flint-3.1.3/src/fmpz/mod.c000066400000000000000000000041051461254215100153210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_mod(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { slong r; if (c2 < WORD(0)) c2 = -c2; if (c1 < WORD(0)) { r = c2 - (-c1 % c2); /* C doesn't correctly handle negative mods */ if (r == c2) r = 0; } else r = c1 % c2; fmpz_set_si(f, r); } else /* h is large and g is small */ { if (c1 < WORD(0)) { fmpz_abs(f, h); fmpz_sub_ui(f, f, -c1); } else fmpz_set_ui(f, c1); } } else /* g is large */ { if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 < WORD(0)) fmpz_set_si(f, flint_mpz_fdiv_ui(COEFF_TO_PTR(c1), -c2)); else fmpz_set_ui(f, flint_mpz_fdiv_ui(COEFF_TO_PTR(c1), c2)); } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_mod_newton(f, g, h); } else { __mpz_struct * mf = _fmpz_promote(f); mpz_mod(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* reduction mod h may result in small value */ } } } } flint-3.1.3/src/fmpz/moebius_mu.c000066400000000000000000000016451461254215100167140ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" int fmpz_factor_moebius_mu(const fmpz_factor_t fac) { slong i; for (i = 0; i < fac->num; i++) if (fac->exp[i] != 1) return 0; return (fac->num % 2) ? -1 : 1; } int fmpz_moebius_mu(const fmpz_t n) { fmpz_factor_t fac; int mu; if (fmpz_abs_fits_ui(n)) return n_moebius_mu(fmpz_get_ui(n)); fmpz_factor_init(fac); fmpz_factor(fac, n); mu = fmpz_factor_moebius_mu(fac); fmpz_factor_clear(fac); return mu; } flint-3.1.3/src/fmpz/mpz_readonly.c000066400000000000000000000012661461254215100172520ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" void flint_mpz_clear_readonly(mpz_t z) { _fmpz_clear_readonly_mpz(z); } void flint_mpz_init_set_readonly(mpz_t z, const fmpz_t f) { if (COEFF_IS_MPZ(*f)) { *z = *COEFF_TO_PTR(*f); } else { flint_mpz_init_set_si(z, *f); } } flint-3.1.3/src/fmpz/mul.c000066400000000000000000000141501461254215100153400ustar00rootroot00000000000000/* Copyright (C) 2009, 2020 William Hart Copyright (C) 2021 Albin Ahlbäck Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "fmpz.h" /* This can only be called from fmpz_mul, and assumes x and y are not small. */ static void flint_mpz_mul(mpz_ptr z, mpz_srcptr x, mpz_srcptr y) { mp_size_t xn, yn, zn, sgn; mp_srcptr xd, yd; mp_ptr zd; mp_limb_t top; TMP_INIT; xn = x->_mp_size; yn = y->_mp_size; sgn = xn ^ yn; xn = FLINT_ABS(xn); yn = FLINT_ABS(yn); if (xn < yn) { mpz_srcptr t; mp_size_t tn; t = x; x = y; y = t; tn = xn; xn = yn; yn = tn; } zn = xn + yn; if (z->_mp_alloc < zn) _mpz_realloc(z, zn); zd = z->_mp_d; /* Important: read after possibly resizing z, so that the pointers are valid in case of aliasing. */ xd = x->_mp_d; yd = y->_mp_d; if (xn == yn) { if (xn == 2) { mp_limb_t r3, r2, r1, r0; FLINT_MPN_MUL_2X2(r3, r2, r1, r0, xd[1], xd[0], yd[1], yd[0]); zd[0] = r0; zd[1] = r1; zd[2] = r2; zd[3] = r3; zn -= (r3 == 0); z->_mp_size = (sgn >= 0) ? zn : -zn; return; } if (xn == 1) { mp_limb_t hi, lo; umul_ppmm(hi, lo, xd[0], yd[0]); zd[0] = lo; zd[1] = hi; /* The result cannot be 1 limb, because that would require a coefficient smaller than COEFF_MAX. */ FLINT_ASSERT(hi != 0); z->_mp_size = (sgn >= 0) ? 2 : -2; return; } } /* Unlikely case since operands up to FLINT_BITS-2 bits get caught in the fmpz fast path, but we should still optimize for this, especially since we don't need to handle aliasing. */ if (yn == 1) { if (xn == 2) { mp_limb_t r2, r1, r0; FLINT_MPN_MUL_2X1(r2, r1, r0, xd[1], xd[0], yd[0]); zd[0] = r0; zd[1] = r1; zd[2] = top = r2; } else { top = zd[xn] = mpn_mul_1(zd, xd, xn, yd[0]); } zn -= (top == 0); z->_mp_size = (sgn >= 0) ? zn : -zn; return; } TMP_START; /* In case of aliasing, we need to copy the input so that we do not overwrite it during the multiplication. */ if (zd == xd) { mp_ptr tmp = TMP_ALLOC(xn * sizeof(mp_limb_t)); flint_mpn_copyi(tmp, xd, xn); xd = tmp; } else if (zd == yd) { mp_ptr tmp = TMP_ALLOC(yn * sizeof(mp_limb_t)); flint_mpn_copyi(tmp, yd, yn); yd = tmp; } if (x == y) { flint_mpn_sqr(zd, xd, xn); top = zd[zn - 1]; } else { top = flint_mpn_mul(zd, xd, xn, yd, yn); } zn -= (top == 0); z->_mp_size = (sgn >= 0) ? zn : -zn; TMP_END; } void fmpz_mul(fmpz_t f, const fmpz_t g, const fmpz_t h) { __mpz_struct * mf; fmpz c1 = *g; fmpz c2 = *h; if (!COEFF_IS_MPZ(c1)) { if (!COEFF_IS_MPZ(c2)) { ulong th, tl; smul_ppmm(th, tl, c1, c2); fmpz_set_signed_uiui(f, th, tl); return; } else if (c1 != 0) { mf = _fmpz_promote(f); flint_mpz_mul_si(mf, COEFF_TO_PTR(c2), c1); return; } } if (!COEFF_IS_MPZ(*f)) { if (c1 == 0 || c2 == 0) { *f = 0; return; } mf = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mf); } else { if (c1 == 0 || c2 == 0) { _fmpz_clear_mpz(*f); *f = 0; return; } mf = COEFF_TO_PTR(*f); } if (!COEFF_IS_MPZ(c2)) flint_mpz_mul_si(mf, COEFF_TO_PTR(c1), c2); else flint_mpz_mul(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } void fmpz_mul_si(fmpz_t f, const fmpz_t g, slong x) { fmpz c2 = *g; if (!COEFF_IS_MPZ(c2)) /* c2 is small */ { mp_limb_t th, tl; /* limb by limb multiply (assembly for most CPU's) */ smul_ppmm(th, tl, c2, x); fmpz_set_signed_uiui(f, th, tl); } else /* c2 is large */ { __mpz_struct * mf; if (!COEFF_IS_MPZ(*f)) { if (x == 0) { *f = 0; return; } mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); } else { if (x == 0) { _fmpz_clear_mpz(*f); *f = 0; return; } mf = COEFF_TO_PTR(*f); } flint_mpz_mul_si(mf, COEFF_TO_PTR(c2), x); } } void fmpz_mul_ui(fmpz_t f, const fmpz_t g, ulong x) { fmpz c2 = *g; if (!COEFF_IS_MPZ(c2)) /* c2 is small */ { mp_limb_t th, tl; mp_limb_t uc2 = FLINT_ABS(c2); /* unsigned limb by limb multiply (assembly for most CPU's) */ umul_ppmm(th, tl, uc2, x); if (c2 >= 0) fmpz_set_uiui(f, th, tl); else fmpz_neg_uiui(f, th, tl); } else /* c2 is large */ { __mpz_struct * mf; if (!COEFF_IS_MPZ(*f)) { if (x == 0) { *f = 0; return; } mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); } else { if (x == 0) { _fmpz_clear_mpz(*f); *f = 0; return; } mf = COEFF_TO_PTR(*f); } flint_mpz_mul_ui(mf, COEFF_TO_PTR(c2), x); } } flint-3.1.3/src/fmpz/mul_2exp.c000066400000000000000000000046721461254215100163060ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2022 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include void fmpz_mul_2exp(fmpz_t f, const fmpz_t g, ulong exp) { slong c1 = *g; ulong c1abs, c1bits; __mpz_struct * mf; if (c1 == 0) { fmpz_zero(f); return; } c1abs = FLINT_ABS(c1); c1bits = FLINT_BIT_COUNT(c1abs); if (c1bits + exp <= SMALL_FMPZ_BITCOUNT_MAX) /* Result fits inside a small fmpz */ { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); *f = c1 << exp; } else if (c1bits <= SMALL_FMPZ_BITCOUNT_MAX) /* g is small */ { ulong expred = exp % FLINT_BITS; int alloc = 1 + exp / FLINT_BITS + ((c1bits + expred) > FLINT_BITS); mp_limb_t * limbs; /* Ensure enough limbs are allocated for f */ if (!COEFF_IS_MPZ(*f)) { /* TODO: Initialize the new mpz with alloc limbs instead of * reallocating them. */ mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); _mpz_realloc(mf, alloc); } else { mf = COEFF_TO_PTR(*f); if (mf->_mp_alloc < alloc) _mpz_realloc(mf, alloc); } limbs = mf->_mp_d; mf->_mp_size = (c1 > 0) ? alloc : -alloc; memset(limbs, 0, sizeof(mp_limb_t) * alloc); if (c1bits + expred <= FLINT_BITS) { limbs[alloc - 1] = c1abs << expred; } else { limbs[alloc - 1] = c1abs >> (FLINT_BITS - expred); limbs[alloc - 2] = c1abs << expred; } } else /* g is large */ { __mpz_struct * mg = COEFF_TO_PTR(c1); if (!COEFF_IS_MPZ(*f)) { /* TODO: Initialize the new mpz with alloc limbs instead of * reallocating them. */ mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); _mpz_realloc(mf, FLINT_ABS(mg->_mp_size) + exp / FLINT_BITS + 1); } else mf = COEFF_TO_PTR(*f); mpz_mul_2exp(mf, mg, exp); } } flint-3.1.3/src/fmpz/mul_si_tdiv_q_2exp.c000066400000000000000000000040661461254215100203440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_mul_si_tdiv_q_2exp(fmpz_t f, const fmpz_t g, slong x, ulong exp) { fmpz c2 = *g; if (x == 0) { fmpz_zero(f); return; } else if (!COEFF_IS_MPZ(c2)) /* c2 is small */ { mp_limb_t prod[2]; mp_limb_t uc2; mp_limb_t ux; if (exp >= 2 * FLINT_BITS) { fmpz_zero(f); return; } uc2 = FLINT_ABS(c2); ux = FLINT_ABS(x); umul_ppmm(prod[1], prod[0], uc2, ux); if (exp >= FLINT_BITS) { fmpz_set_ui(f, prod[1] >> (exp - FLINT_BITS)); if ((c2 ^ x) < WORD(0)) fmpz_neg(f, f); return; } if (exp != 0) { prod[0] = (prod[1] << (FLINT_BITS - exp)) | (prod[0] >> exp); prod[1] >>= exp; } if (!prod[1]) { fmpz_set_ui(f, prod[0]); if ((c2 ^ x) < WORD(0)) fmpz_neg(f, f); return; } else /* result takes two limbs */ { __mpz_struct * mf = _fmpz_promote(f); /* two limbs, least significant first, native endian, no nails, stored in prod */ mpz_import(mf, 2, -1, sizeof(mp_limb_t), 0, 0, prod); if ((c2 ^ x) < WORD(0)) mpz_neg(mf, mf); } } else /* c2 is large */ { __mpz_struct * mf = _fmpz_promote(f); /* ok without val as if aliased both are large */ flint_mpz_mul_si(mf, COEFF_TO_PTR(c2), x); mpz_tdiv_q_2exp(mf, mf, exp); _fmpz_demote_val(f); /* value may be small */ } } flint-3.1.3/src/fmpz/mul_tdiv_q_2exp.c000066400000000000000000000025061461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_mul_tdiv_q_2exp(fmpz_t f, const fmpz_t g, const fmpz_t h, ulong exp) { fmpz c1, c2; __mpz_struct * mf; c1 = *g; if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_mul_si_tdiv_q_2exp(f, h, c1, exp); return; } c2 = *h; /* save h in case it is aliased with f */ if (c2 == WORD(0)) /* special case, h = 0 */ { fmpz_zero(f); return; } mf = _fmpz_promote(f); /* h is saved, g is already large */ if (!COEFF_IS_MPZ(c2)) /* g is large, h is small */ flint_mpz_mul_si(mf, COEFF_TO_PTR(c1), c2); else /* c1 and c2 are large */ mpz_mul(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); mpz_tdiv_q_2exp(mf, mf, exp); _fmpz_demote_val(f); /* division may make value small */ } flint-3.1.3/src/fmpz/multi_CRT.c000066400000000000000000000316771461254215100164220ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "nmod.h" #include "fmpz.h" void fmpz_multi_CRT_init(fmpz_multi_CRT_t P) { P->prog = NULL; P->moduli = NULL; P->fracmoduli = NULL; P->alloc = 0; P->length = 0; P->localsize = 1; P->temp1loc = 0; P->temp2loc = 0; P->temp3loc = 0; P->temp4loc = 0; P->good = 0; fmpz_init(P->final_modulus); } void fmpz_multi_CRT_clear(fmpz_multi_CRT_t P) { slong i; for (i = 0; i < P->alloc; i++) { fmpz_clear(P->prog[i].b_modulus); fmpz_clear(P->prog[i].c_modulus); fmpz_clear(P->moduli + i); fmpz_clear(P->fracmoduli + i); } flint_free(P->prog); flint_free(P->moduli); flint_free(P->fracmoduli); fmpz_clear(P->final_modulus); } int fmpz_multi_CRT( fmpz_t output, const fmpz * moduli, const fmpz * values, slong len, int sign) { int success; slong i; fmpz_multi_CRT_t P; fmpz * out; TMP_INIT; FLINT_ASSERT(len > 0); TMP_START; fmpz_multi_CRT_init(P); success = fmpz_multi_CRT_precompute(P, moduli, len); out = TMP_ARRAY_ALLOC(P->localsize, fmpz); for (i = 0; i < P->localsize; i++) fmpz_init(out + i); fmpz_swap(out + 0, output); _fmpz_multi_CRT_precomp(out, P, values, sign); fmpz_swap(out + 0, output); for (i = 0; i < P->localsize; i++) fmpz_clear(out + i); fmpz_multi_CRT_clear(P); TMP_END; return success; } void _fmpz_multi_CRT_precomp( fmpz * outputs, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign) { slong i, a, b, c; slong len = P->length; const fmpz * m = P->moduli; const fmpz * mf = P->fracmoduli; fmpz * A, * B, * C, * t1, * t2, * t3, * t4; t1 = outputs + P->temp1loc; t2 = outputs + P->temp2loc; t3 = outputs + P->temp3loc; t4 = outputs + P->temp4loc; FLINT_ASSERT(len < 1 || P->good); if (len > 0) { for (i = P->moduli_count - 1; i > 0; i--) { if (!fmpz_equal(inputs + 0, inputs + i)) goto doit; } } _fmpz_smod(outputs + 0, inputs + 0, P->final_modulus, sign, t4); return; doit: for (i = 0; i < len; i++) { a = P->prog[i].a_idx; b = P->prog[i].b_idx; c = P->prog[i].c_idx; A = outputs + a; B = outputs + b; C = outputs + c; if (b < 0) { b = -b - 1; B = t1; fmpz_mul(t3, inputs + b, mf + b); _fmpz_smod(B, t3, m + b, sign, t4); } if (c < 0) { c = -c - 1; C = t2; fmpz_mul(t3, inputs + c, mf + c); _fmpz_smod(C, t3, m + c, sign, t4); } /* A = B*c_m + C*b_m */ fmpz_mul(A, B, P->prog[i].c_modulus); fmpz_mul(t3, C, P->prog[i].b_modulus); fmpz_add(A, A, t3); } _fmpz_smod(outputs + 0, A, P->final_modulus, sign, t4); } void fmpz_multi_CRT_precomp( fmpz_t output, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign) { slong i; fmpz * out; TMP_INIT; TMP_START; out = TMP_ARRAY_ALLOC(P->localsize, fmpz); for (i = 0; i < P->localsize; i++) fmpz_init(out + i); fmpz_swap(out + 0, output); _fmpz_multi_CRT_precomp(out, P, inputs, sign); fmpz_swap(out + 0, output); for (i = 0; i < P->localsize; i++) fmpz_clear(out + i); TMP_END; } static void _fmpz_multi_CRT_fit_length(fmpz_multi_CRT_t P, slong k) { slong i; k = FLINT_MAX(WORD(1), k); for (i = k; i < P->alloc; i++) { fmpz_clear(P->prog[i].b_modulus); fmpz_clear(P->prog[i].c_modulus); fmpz_clear(P->moduli + i); fmpz_clear(P->fracmoduli + i); } P->prog = FLINT_ARRAY_REALLOC(P->prog, k, _fmpz_multi_CRT_instr); P->moduli = FLINT_ARRAY_REALLOC(P->moduli, k, fmpz); P->fracmoduli = FLINT_ARRAY_REALLOC(P->fracmoduli, k, fmpz); for (i = P->alloc; i < k; i++) { fmpz_init(P->prog[i].b_modulus); fmpz_init(P->prog[i].c_modulus); fmpz_init(P->moduli + i); fmpz_init(P->fracmoduli + i); } P->alloc = k; } static int _fill_pfrac( slong * link, fmpz * v, fmpz * w, slong j, const fmpz_t A, fmpz_t g, /* temps */ fmpz_t s, fmpz_t t) { while (j >= 0) { int cmp = fmpz_cmp(v + j, v + j + 1); /* A/(v[j]*v[j+1]) = w[j]/v[j] + w[j+1]/v[j+1] mod 1 */ if (fmpz_is_zero(v + j) || fmpz_is_zero(v + j + 1) || fmpz_is_one(v + j) || fmpz_is_one(v + j + 1) || cmp == 0) { return 0; } /* fmpz_gcdinv requires x < y AND we hit the smaller branch first */ if (cmp > 0) { fmpz_swap(v + j, v + j + 1); FLINT_SWAP(slong, link[j], link[j + 1]); } fmpz_gcdinv(g, s, v + j + 0, v + j + 1); if (!fmpz_is_one(g)) return 0; fmpz_mul(w + j + 1, A, s); fmpz_mod(w + j + 1, w + j + 1, v + j + 1 ); /* w[j] = (A - v[j] w[1 + j])/v[1 + j] */ fmpz_mul(w + j + 0, v + j + 0, w + j + 1); fmpz_sub(t, A, w + j + 0); fmpz_fdiv_qr(w + j + 0, g, t, v + j + 1); FLINT_ASSERT(fmpz_is_zero(g) && "division should be exact"); fmpz_mod(w + j + 0, w + j + 0, v + j + 0); if (!_fill_pfrac(link, v, w, link[j + 0], w + j + 0, g, s, t)) return 0; A = w + j + 1; j = link[j + 1]; } return 1; } static void _fill_prog( fmpz_multi_CRT_t P, slong * link, fmpz * v, fmpz * w, slong j, slong ret_idx) { slong i, b_idx, c_idx; slong next_ret_idx = ret_idx; FLINT_ASSERT(j >= 0); if (link[j] >= 0) { b_idx = ++next_ret_idx; _fill_prog(P, link, v, w, link[j], b_idx); } else { b_idx = -1 - link[j]; FLINT_ASSERT(b_idx < P->alloc); fmpz_set(P->moduli + b_idx, v + j); fmpz_set(P->fracmoduli + b_idx, w + j); b_idx = -1 - b_idx; } if (link[j + 1] >= 0) { c_idx = ++next_ret_idx; _fill_prog(P, link, v, w, link[j + 1], c_idx); } else { c_idx = -1 - link[j + 1]; FLINT_ASSERT(c_idx < P->alloc); fmpz_set(P->moduli + c_idx, v + j + 1); fmpz_set(P->fracmoduli + c_idx, w + j + 1); c_idx = -1 - c_idx; } i = P->length; FLINT_ASSERT(i < P->alloc); P->prog[i].a_idx = ret_idx; P->prog[i].b_idx = b_idx; P->prog[i].c_idx = c_idx; fmpz_set(P->prog[i].b_modulus, v + j); fmpz_set(P->prog[i].c_modulus, v + j + 1); P->length = i + 1; P->localsize = FLINT_MAX(P->localsize, 1 + next_ret_idx); } int fmpz_multi_CRT_precompute( fmpz_multi_CRT_t P, const fmpz * f, slong r) { slong i, j; slong * link; fmpz * v; fmpz * w; fmpz_t one, g, s, t; FLINT_ASSERT(r > 0); _fmpz_multi_CRT_fit_length(P, r); P->length = 0; P->localsize = 1; P->moduli_count = r; P->min_modulus_bits = fmpz_bits(f + 0); if (r < 2) { P->good = !fmpz_is_zero(f + 0); if (P->good) { fmpz_abs(P->final_modulus, f + 0); fmpz_abs(P->moduli + 0, f + 0); fmpz_one(P->fracmoduli + 0); } goto done; } fmpz_init(one); fmpz_init(g); fmpz_init(s); fmpz_init(t); link = FLINT_ARRAY_ALLOC(2*r - 2, slong); v = FLINT_ARRAY_ALLOC(2*(2*r - 2), fmpz); w = v + 2*r - 2; for (i = 0; i < 2*(2*r - 2); i++) fmpz_init(v + i); for (i = 0; i < r; i++) { flint_bitcnt_t this_bits = fmpz_bits(f + i); P->min_modulus_bits = FLINT_MIN(P->min_modulus_bits, this_bits); fmpz_abs(v + i, f + i); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp; const fmpz * mind; minp = j; mind = v + j; for (s = j + 1; s < i; s++) { if (fmpz_cmp(v + s, mind) < 0) { mind = v + s; minp = s; } } fmpz_swap(v + j, v + minp); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = v + j + 1; for (s = j + 2; s < i; s++) { if (fmpz_cmp(v + s, mind) < 0) { mind = v + s; minp = s; } } fmpz_swap(v + j + 1, v + minp); FLINT_SWAP(slong, link[j + 1], link[minp]); fmpz_mul(v + i, v + j, v + j + 1); link[i] = j; } fmpz_mul(P->final_modulus, v + 2*r - 4, v + 2*r - 3); fmpz_one(one); P->good = _fill_pfrac(link, v, w, 2*r - 4, one, g, s, t); if (P->good) _fill_prog(P, link, v, w, 2*r - 4, 0); fmpz_clear(one); fmpz_clear(g); fmpz_clear(s); fmpz_clear(t); for (i = 0; i < 2*(2*r - 2); i++) fmpz_clear(v + i); flint_free(link); flint_free(v); done: P->temp1loc = P->localsize++; P->temp2loc = P->localsize++; P->temp3loc = P->localsize++; P->temp4loc = P->localsize++; if (!P->good) { fmpz_one(P->final_modulus); P->length = 0; } return P->good; } #define MAC(h, l, a, b) \ do { \ mp_limb_t p1, p0; \ umul_ppmm(p1, p0, a, b); \ add_ssaaaa(h, l, h, l, p1, p0); \ } while (0) void fmpz_multi_CRT_ui( fmpz_t b, mp_srcptr in, const fmpz_comb_t C, fmpz_comb_temp_t CT, int sign) { slong i, j, k, l, s; slong klen = C->crt_klen; slong * step = C->step; crt_lut_entry * lu = C->crt_lu; fmpz * T = CT->T; fmpz * A = CT->A; slong * offsets = C->crt_offsets; const mp_limb_t * md = C->packed_multipliers; mpz_ptr az; mp_limb_t * ad; mp_limb_t hi, lo, t; for (k = 0, i = 0, l = 0; k < klen; k++) { s = step[k]; j = offsets[k]; az = _fmpz_promote(A + k); if (s < 0) { /* every low level combination in this chunk has 1 prime and md already has lu[i].i0 pre-multiplied in. */ s = -s - 1; ad = FLINT_MPZ_REALLOC(az, s + 2); flint_mpn_zero(ad, s + 2); hi = lo = 0; for ( ; i < j; md += s, l++, i++) { FLINT_ASSERT(lu[i].i0 != 0); FLINT_ASSERT(lu[i].i1 == 0); FLINT_ASSERT(lu[i].i2 == 0); t = mpn_addmul_1(ad, md, s, in[l*1]); add_ssaaaa(hi, lo, hi, lo, UWORD(0), t); } ad[s] = lo; ad[s + 1] = hi; } else { ad = FLINT_MPZ_REALLOC(az, s + 2); flint_mpn_zero(ad, s + 2); for ( ; i < j; md += s, i++) { /* low level combination: 1, 2, or 3 small primes */ FLINT_ASSERT(l + 1 <= C->num_primes); umul_ppmm(hi, lo, in[l*1], lu[i].i0); l++; if (lu[i].i2 != 0) { FLINT_ASSERT(l + 2 <= C->num_primes); MAC(hi, lo, in[l*1], lu[i].i1); l++; MAC(hi, lo, in[l*1], lu[i].i2); l++; /* We have lu[i].mod.n = p0*p1*p2, and each lu[i].i{0|1|2} is strictly less than p1*p2*p3, and the inputs are reduced mod pi. Therefore, the sum is at most (p0*p1*p2-1)*(p0-1+p1-1+p2-1). Since p0*p1*p2 fits into a word, the sum fits into two words and the hi word is less than p0*p1*p2. */ } else if (lu[i].i1 != 0) { FLINT_ASSERT(l + 1 <= C->num_primes); MAC(hi, lo, in[l*1], lu[i].i1); l++; /* Ditto for two */ } FLINT_ASSERT(hi < lu[i].mod.n); NMOD_RED2(t, hi, lo, lu[i].mod); /* mid level combination: depends on FMPZ_CRT_UI_CUTOFF */ hi = mpn_addmul_1(ad, md, s, t); add_ssaaaa(ad[s + 1], ad[s], ad[s + 1], ad[s], UWORD(0), hi); } } s += 2; MPN_NORM(ad, s); az->_mp_size = s; _fmpz_demote_val(A + k); _fmpz_smod(A + k, A + k, C->crt_P->moduli + k, sign, T + 0); } FLINT_ASSERT(l == C->num_primes); /* high level combination */ fmpz_swap(T + 0, b); _fmpz_multi_CRT_precomp(T, C->crt_P, A, sign); fmpz_swap(T + 0, b); } flint-3.1.3/src/fmpz/multi_mod.c000066400000000000000000000212111461254215100165300ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" void fmpz_multi_mod_init(fmpz_multi_mod_t P) { P->prog = NULL; P->moduli = NULL; P->alloc = 0; P->length = 0; P->localsize = 1; P->temp1loc = 0; P->good = 0; } void fmpz_multi_mod_clear(fmpz_multi_mod_t P) { slong i; for (i = 0; i < P->alloc; i++) { fmpz_clear(P->prog[i].modulus); fmpz_clear(P->moduli + i); } flint_free(P->prog); flint_free(P->moduli); } void _fmpz_multi_mod_precomp( fmpz * outputs, const fmpz_multi_mod_t P, const fmpz_t input, int sign, fmpz * T) { slong i, a, b; slong len = P->length; _fmpz_multi_mod_instr * instr = P->prog; fmpz * t1 = T + P->temp1loc; unsigned char * org; TMP_INIT; TMP_START; /* Efficiently propagate small inputs without copying: ord[i] = 1 means T[i] should be read from input */ org = TMP_ARRAY_ALLOC(P->localsize, unsigned char); #if FLINT_WANT_ASSERT for (i = 0; i < P->localsize; i++) org[i] = 2; #endif for (i = 0; i < len; i++) { a = P->prog[i].in_idx; b = P->prog[i].out_idx; FLINT_ASSERT(a < 1 || org[a] < 2); if (a > 0 && org[a] == 0) { /* read input from T[a] */ if (b < 0) { _fmpz_smod(outputs - b - 1, T + a, instr[i].modulus, sign, t1); } else { org[b] = 0; fmpz_tdiv_qr(t1, T + b, T + a, instr[i].modulus); } } else { /* read input from input */ if (b < 0) { _fmpz_smod(outputs - b - 1, input, instr[i].modulus, sign, t1); } else if (fmpz_cmpabs(instr[i].modulus, input) > 0) { org[b] = 1; } else { org[b] = 0; fmpz_tdiv_qr(t1, T + b, input, instr[i].modulus); } } } TMP_END; } void fmpz_multi_mod_precomp( fmpz * outputs, const fmpz_multi_mod_t P, const fmpz_t input, int sign) { slong i; fmpz * tmp; TMP_INIT; TMP_START; tmp = TMP_ARRAY_ALLOC(P->localsize, fmpz); for (i = 0; i < P->localsize; i++) fmpz_init(tmp + i); _fmpz_multi_mod_precomp(outputs, P, input, sign, tmp); for (i = 0; i < P->localsize; i++) fmpz_clear(tmp + i); TMP_END; } static void _fmpz_multi_mod_fit_length(fmpz_multi_mod_t P, slong k) { slong i; k = FLINT_MAX(WORD(1), k); for (i = k; i < P->alloc; i++) { fmpz_clear(P->prog[i].modulus); fmpz_clear(P->moduli + i); } P->prog = FLINT_ARRAY_REALLOC(P->prog, k, _fmpz_multi_mod_instr); P->moduli = FLINT_ARRAY_REALLOC(P->moduli, k, fmpz); for (i = P->alloc; i < k; i++) { fmpz_init(P->prog[i].modulus); fmpz_init(P->moduli + i); } P->alloc = k; } static int _fill_sort(slong * link, fmpz * v, slong j) { while (j >= 0) { int cmp = fmpz_cmp(v + j, v + j + 1); if (fmpz_is_zero(v + j) || fmpz_is_zero(v + j + 1)) return 0; /* hit the smaller branch first */ if (cmp > 0) { fmpz_swap(v + j, v + j + 1); FLINT_SWAP(slong, link[j], link[j + 1]); } if (!_fill_sort(link, v, link[j + 0])) return 0; j = link[j + 1]; } return 1; } static void _fill_prog( fmpz_multi_mod_t P, slong * link, fmpz * v, slong j, slong a_idx) { slong i, b_idx, c_idx; FLINT_ASSERT(j >= 0); if (link[j] >= 0) { b_idx = a_idx + 1; } else { b_idx = -1 - link[j]; FLINT_ASSERT(b_idx < P->alloc); fmpz_set(P->moduli + b_idx, v + j); b_idx = -1 - b_idx; } if (link[j + 1] >= 0) { c_idx = a_idx + 1; } else { c_idx = -1 - link[j + 1]; FLINT_ASSERT(c_idx < P->alloc); fmpz_set(P->moduli + c_idx, v + j + 1); c_idx = -1 - c_idx; } i = P->length; FLINT_ASSERT(i < P->alloc); P->prog[i].in_idx = a_idx; P->prog[i].out_idx = b_idx; fmpz_set(P->prog[i].modulus, v + j); P->length = i + 1; if (link[j + 0] >= 0) _fill_prog(P, link, v, link[j + 0], b_idx); i = P->length; FLINT_ASSERT(i < P->alloc); P->prog[i].in_idx = a_idx; P->prog[i].out_idx = c_idx; fmpz_set(P->prog[i].modulus, v + j + 1); P->length = i + 1; if (link[j + 1] >= 0) _fill_prog(P, link, v, link[j + 1], c_idx); P->localsize = FLINT_MAX(P->localsize, a_idx + 1); } int fmpz_multi_mod_precompute( fmpz_multi_mod_t P, const fmpz * f, slong r) { slong i, j; slong * link; fmpz * v; FLINT_ASSERT(r > 0); _fmpz_multi_mod_fit_length(P, 2*r); P->length = 0; P->localsize = 1; P->moduli_count = r; P->min_modulus_bits = fmpz_bits(f + 0); if (r < 2) { P->good = !fmpz_is_zero(f + 0); if (P->good) { fmpz_abs(P->moduli + 0, f + 0); P->prog[0].in_idx = 0; P->prog[0].out_idx = -1; fmpz_set(P->prog[0].modulus, P->moduli + 0); P->length = 1; } goto done; } link = FLINT_ARRAY_ALLOC(2*r - 2, slong); v = _fmpz_vec_init(2*r - 2); for (i = 0; i < r; i++) { flint_bitcnt_t this_bits = fmpz_bits(f + i); P->min_modulus_bits = FLINT_MIN(P->min_modulus_bits, this_bits); fmpz_abs(v + i, f + i); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp; const fmpz * mind; minp = j; mind = v + j; for (s = j + 1; s < i; s++) { if (fmpz_cmp(v + s, mind) < 0) { mind = v + s; minp = s; } } fmpz_swap(v + j, v + minp); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = v + j + 1; for (s = j + 2; s < i; s++) { if (fmpz_cmp(v + s, mind) < 0) { mind = v + s; minp = s; } } fmpz_swap(v + j + 1, v + minp); FLINT_SWAP(slong, link[j + 1], link[minp]); fmpz_mul(v + i, v + j, v + j + 1); link[i] = j; } P->good = _fill_sort(link, v, 2*r - 4); if (P->good) _fill_prog(P, link, v, 2*r - 4, 0); flint_free(link); _fmpz_vec_clear(v, 2*r - 2); done: P->temp1loc = P->localsize++; if (!P->good) { P->length = 0; } return P->good; } void fmpz_multi_mod_ui( mp_limb_t * out, const fmpz_t input, const fmpz_comb_t C, fmpz_comb_temp_t CT) { slong i, k, l; slong stride = 1; fmpz * A = CT->A; mod_lut_entry * lu; slong * offsets; slong klen = C->mod_klen; fmpz_t ttt; /* high level split */ if (klen == 1) { *ttt = A[0]; A[0] = *input; } else { _fmpz_multi_mod_precomp(A, C->mod_P, input, -1, CT->T); } offsets = C->mod_offsets; lu = C->mod_lu; for (k = 0, i = 0, l = 0; k < klen; k++) { slong j = offsets[k]; for ( ; i < j; i++) { /* mid level split: depends on FMPZ_MOD_UI_CUTOFF */ mp_limb_t t = fmpz_get_nmod(A + k, lu[i].mod); /* low level split: 1, 2, or 3 small primes */ if (lu[i].mod2.n != 0) { FLINT_ASSERT(l + 3 <= C->num_primes); NMOD_RED(out[l*stride], t, lu[i].mod0); l++; NMOD_RED(out[l*stride], t, lu[i].mod1); l++; NMOD_RED(out[l*stride], t, lu[i].mod2); l++; } else if (lu[i].mod1.n != 0) { FLINT_ASSERT(l + 2 <= C->num_primes); NMOD_RED(out[l*stride], t, lu[i].mod0); l++; NMOD_RED(out[l*stride], t, lu[i].mod1); l++; } else { FLINT_ASSERT(l + 1 <= C->num_primes); out[l*stride] = t; l++; } } } FLINT_ASSERT(l == C->num_primes); if (klen == 1) A[0] = *ttt; } flint-3.1.3/src/fmpz/ndiv_qr.c000066400000000000000000000047221461254215100162110ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" /* b aliases neither q nor r */ static void _fmpz_ndiv_qr(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { int c, rbsgn; fmpz_tdiv_qr(q, r, a, b); c = fmpz_cmp2abs(b, r); if (c > 0) return; rbsgn = fmpz_sgn(r)*fmpz_sgn(b); if (c < 0) { if (rbsgn < 0) { fmpz_sub_ui(q, q, 1); fmpz_add(r, r, b); } else { fmpz_add_ui(q, q, 1); fmpz_sub(r, r, b); } } else { int qsgn = fmpz_sgn(q); if (rbsgn < 0 && qsgn > 0) { fmpz_sub_ui(q, q, 1); fmpz_add(r, r, b); } else if (rbsgn > 0 && qsgn < 0) { fmpz_add_ui(q, q, 1); fmpz_sub(r, r, b); } } } void fmpz_ndiv_qr(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) { slong A = *a; slong B = *b; if (fmpz_is_zero(b)) { flint_throw(FLINT_ERROR, "Exception: division by zero in fmpz_ndiv_qr\n"); } if (!COEFF_IS_MPZ(A) && !COEFF_IS_MPZ(B)) { slong lquo, lrem; _fmpz_demote(q); _fmpz_demote(r); if (FLINT_ABS(*b) == 1) /* avoid overflow in case */ { /* a = 2^(SMALL_FMPZ_BITCOUNT_MAX) */ fmpz_set_si(q, A * FLINT_SGN(B)); fmpz_zero(r); return; } *q = A / B; *r = A - B * *q; lquo = *q + FLINT_SGN(A) * FLINT_SGN(B); lrem = A - B * lquo; if (FLINT_ABS(lrem) < FLINT_ABS(*r)) { *q = lquo; *r = lrem; } } else { if (b == q) { fmpz_t t; fmpz_init(t); _fmpz_ndiv_qr(t, r, a, b); fmpz_swap(q, t); fmpz_clear(t); } else if (b == r) { fmpz_t t; fmpz_init(t); _fmpz_ndiv_qr(q, t, a, b); fmpz_swap(r, t); fmpz_clear(t); } else { _fmpz_ndiv_qr(q, r, a, b); } } } flint-3.1.3/src/fmpz/neg.c000066400000000000000000000015761461254215100153240ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" void fmpz_neg(fmpz_t f1, const fmpz_t f2) { if (!COEFF_IS_MPZ(*f2)) /* coeff is small */ { fmpz t = -*f2; /* Need to save value in case of aliasing */ _fmpz_demote(f1); *f1 = t; } else /* coeff is large */ { /* No need to retain value in promotion, as if aliased, both already large */ __mpz_struct *mpz_res = _fmpz_promote(f1); mpz_neg(mpz_res, COEFF_TO_PTR(*f2)); } } flint-3.1.3/src/fmpz/nextprime.c000066400000000000000000000034151461254215100165600ustar00rootroot00000000000000/* Authored 2015 by Daniel S. Roche; US Government work in the public domain. This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "fmpz.h" #include "ulong_extras.h" void fmpz_nextprime(fmpz_t res, const fmpz_t n, int proved) { if (fmpz_sgn(n) <= 0) { fmpz_set_ui(res, UWORD(2)); return; } else if (COEFF_IS_MPZ(*n)) { /* n is big */ __mpz_struct *res_mpz = _fmpz_promote(res); mpz_nextprime(res_mpz, COEFF_TO_PTR(*n)); } else if (FLINT_BIT_COUNT(*n) < SMALL_FMPZ_BITCOUNT_MAX) { /* n and res will both be small */ _fmpz_demote(res); *res = n_nextprime(*n, proved); return; } else if (res != n) { /* n is small, but res might not be */ mpz_t temp_n; __mpz_struct *res_mpz = _fmpz_promote(res); flint_mpz_init_set_ui(temp_n, *n); mpz_nextprime(res_mpz, temp_n); _fmpz_demote_val(res); mpz_clear(temp_n); } else { /* same as above case, but need to handle aliasing here. */ __mpz_struct *res_mpz = _fmpz_promote_val(res); mpz_nextprime(res_mpz, res_mpz); _fmpz_demote_val(res); } if (proved) { if (!fmpz_is_prime(res)) { /* Keep searching. No big penalty for recursion here because this * will almost never happen. */ fmpz_nextprime(res, res, proved); } } } flint-3.1.3/src/fmpz/one_2exp.c000066400000000000000000000013211461254215100162560ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_one_2exp(fmpz_t x, ulong e) { if (e <= FLINT_BITS - 3) { fmpz_set_ui(x, UWORD(1) << e); } else { __mpz_struct * z = _fmpz_promote(x); flint_mpz_set_ui(z, 1); mpz_mul_2exp(z, z, e); } } flint-3.1.3/src/fmpz/pow.c000066400000000000000000000053411461254215100153520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2018 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_pow_ui(fmpz_t f, const fmpz_t g, ulong exp) { fmpz c1; if (exp == WORD(0)) { fmpz_one(f); return; } c1 = *g; if (!COEFF_IS_MPZ(c1)) /* g is small */ { ulong u1 = FLINT_ABS(c1); ulong bits = FLINT_BIT_COUNT(u1); if (u1 <= UWORD(1)) { fmpz_set_ui(f, u1); } else if (exp * bits <= SMALL_FMPZ_BITCOUNT_MAX) { fmpz_set_ui(f, n_pow(u1, exp)); } else { __mpz_struct * mf = _fmpz_promote_val(f); flint_mpz_set_ui(mf, u1); flint_mpz_pow_ui(mf, mf, exp); _fmpz_demote_val(f); /* may actually fit into a small after all */ } if ((c1 < WORD(0)) && (exp & 1)) /* sign is -ve if exp odd and g -ve */ fmpz_neg(f, f); } else { __mpz_struct * mf = _fmpz_promote_val(f); flint_mpz_pow_ui(mf, COEFF_TO_PTR(c1), exp); /* no need to demote as it can't get smaller */ } } int fmpz_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t e) { int e_sgn = fmpz_sgn(e); if (e_sgn < 0) { flint_throw(FLINT_ERROR, "Negative exponent in fmpz_pow_fmpz"); } else if (e_sgn == 0) { fmpz_one(a); } else if (fmpz_is_zero(b)) { fmpz_zero(a); } else if (fmpz_is_pm1(b)) { fmpz_set_si(a, fmpz_is_one(b) || fmpz_is_even(e) ? 1 : -1); } else { if (!fmpz_fits_si(e)) return 0; fmpz_pow_ui(a, b, fmpz_get_si(e)); } return 1; } void fmpz_ui_pow_ui(fmpz_t x, ulong b, ulong e) { if (e <= 1) { fmpz_set_ui(x, e == 0 ? 1 : b); } else if (e == 2) { mp_limb_t t[2]; umul_ppmm(t[1], t[0], b, b); fmpz_set_uiui(x, t[1], t[0]); } else if (b <= 1) { fmpz_set_ui(x, b); } else { ulong bits = FLINT_BIT_COUNT(b); if (e * bits <= FLINT_BITS) { fmpz_set_ui(x, n_pow(b, e)); } else { __mpz_struct * z = _fmpz_promote(x); flint_mpz_set_ui(z, b); flint_mpz_pow_ui(z, z, e); _fmpz_demote_val(x); } } } flint-3.1.3/src/fmpz/powm.c000066400000000000000000000162621461254215100155330ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" #include "gr.h" #include "gr_generic.h" /* assumes e is large */ static void _fmpz_powm(fmpz_t res, const fmpz_t x, const fmpz_t e, const fmpz_t m) { if (!COEFF_IS_MPZ(*m)) /* m is small */ { /* todo: make n_powmod2_fmpz_preinv faster than mpz_powm and use here */ ulong c1, c2; mpz_t zx, zm; __mpz_struct * zres; c2 = *m; c1 = fmpz_fdiv_ui(x, c2); zx->_mp_d = &c1; zx->_mp_size = (c1 != 0); zx->_mp_alloc = 1; zm->_mp_d = &c2; zm->_mp_size = 1; zm->_mp_alloc = 1; zres = _fmpz_promote(res); mpz_powm(zres, zx, COEFF_TO_PTR(*e), zm); _fmpz_demote_val(res); } else if (fmpz_is_zero(x) || fmpz_is_one(x)) { fmpz_set(res, x); } #ifdef FLINT_HAVE_FFT_SMALL else if (fmpz_bits(m) >= 70000) { gr_ctx_t gctx; fmpz_t t; gr_ctx_init_fmpz_mod(gctx, m); fmpz_init(t); /* fmpz_mod input must be reduced */ GR_MUST_SUCCEED(gr_set_fmpz(t, x, gctx)); if (!COEFF_IS_MPZ(*x)) GR_MUST_SUCCEED(gr_generic_pow_fmpz_binexp(res, t, e, gctx)); else GR_MUST_SUCCEED(gr_generic_pow_fmpz_sliding(res, t, e, gctx)); fmpz_clear(t); gr_ctx_clear(gctx); } #endif else { if (!COEFF_IS_MPZ(*x)) /* x is small */ { mpz_t zx; __mpz_struct * zres; ulong c1; c1 = FLINT_ABS(*x); zx->_mp_d = &c1; zx->_mp_size = (*x == 0) ? 0 : ((*x > 0) ? 1 : -1); zx->_mp_alloc = 1; zres = _fmpz_promote(res); mpz_powm(zres, zx, COEFF_TO_PTR(*e), COEFF_TO_PTR(*m)); _fmpz_demote_val(res); } else /* x is large */ { __mpz_struct * zres = _fmpz_promote(res); mpz_powm(zres, COEFF_TO_PTR(*x), COEFF_TO_PTR(*e), COEFF_TO_PTR(*m)); _fmpz_demote_val(res); } } } void fmpz_powm(fmpz_t f, const fmpz_t g, const fmpz_t e, const fmpz_t m) { if (fmpz_sgn(m) <= 0) { flint_throw(FLINT_ERROR, "Exception in fmpz_powm: " "Modulus is less than 1.\n"); } else if (!COEFF_IS_MPZ(*e)) /* e is small */ { if (*e >= 0) { fmpz_powm_ui(f, g, *e, m); } else { fmpz_t g_inv; fmpz_init(g_inv); if (!fmpz_invmod(g_inv, g, m)) { fmpz_clear(g_inv); flint_throw(FLINT_ERROR, "Exception in fmpz_powm: " "Base is not invertible.\n"); } else { fmpz_powm_ui(f, g_inv, -*e, m); fmpz_clear(g_inv); } } } else /* e is large */ { _fmpz_powm(f, g, e, m); } } /* assumes m is large */ static void _fmpz_powm_ui(fmpz_t res, const fmpz_t x, ulong e, const fmpz_t m) { if (e == 1) { fmpz_mod(res, x, m); } /* don't bother handling aliasing for the extremely unusual case where res == m */ else if (e == 2 && res != m) { fmpz_mul(res, x, x); fmpz_mod(res, res, m); } else if (e == 3 && res != m) { if (res == x) { fmpz_t t; fmpz_init(t); fmpz_mul(t, x, x); fmpz_mod(t, t, m); fmpz_mul(t, t, x); fmpz_mod(res, t, m); fmpz_clear(t); } else { fmpz_mul(res, x, x); fmpz_mod(res, res, m); fmpz_mul(res, res, x); fmpz_mod(res, res, m); } } else if (e == 4 && res != m) { fmpz_mul(res, x, x); fmpz_mod(res, res, m); fmpz_mul(res, res, res); fmpz_mod(res, res, m); } else if (fmpz_is_zero(x) || fmpz_is_one(x)) { fmpz_set(res, x); } #ifdef FLINT_HAVE_FFT_SMALL else if (fmpz_bits(m) >= 70000) { gr_ctx_t gctx; fmpz_t t; gr_ctx_init_fmpz_mod(gctx, m); fmpz_init(t); /* fmpz_mod input must be reduced */ GR_MUST_SUCCEED(gr_set_fmpz(t, x, gctx)); if (!COEFF_IS_MPZ(*x) || FLINT_BIT_COUNT(e) < 20) GR_MUST_SUCCEED(gr_generic_pow_ui_binexp(res, t, e, gctx)); else GR_MUST_SUCCEED(gr_generic_pow_ui_sliding(res, t, e, gctx)); fmpz_clear(t); gr_ctx_clear(gctx); } #endif else { if (!COEFF_IS_MPZ(*x)) /* x is small */ { mpz_t zx; __mpz_struct * zres; ulong c1; c1 = FLINT_ABS(*x); zx->_mp_d = &c1; zx->_mp_size = (*x == 0) ? 0 : ((*x > 0) ? 1 : -1); zx->_mp_alloc = 1; zres = _fmpz_promote(res); flint_mpz_powm_ui(zres, zx, e, COEFF_TO_PTR(*m)); _fmpz_demote_val(res); } else /* x is large */ { __mpz_struct * zres = _fmpz_promote(res); flint_mpz_powm_ui(zres, COEFF_TO_PTR(*x), e, COEFF_TO_PTR(*m)); _fmpz_demote_val(res); } } } void fmpz_powm_ui(fmpz_t f, const fmpz_t g, ulong e, const fmpz_t m) { if (fmpz_sgn(m) <= 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_powm_ui). Modulus is less than 1.\n"); } if (fmpz_is_one(m)) { fmpz_zero(f); } else if (e == 0) { fmpz_one(f); } else /* e != 0, m > 0 */ { fmpz g2 = *g; fmpz m2 = *m; if (!COEFF_IS_MPZ(m2)) /* m is small */ { if (!COEFF_IS_MPZ(g2)) /* g is small */ { mp_limb_t minv = n_preinvert_limb(m2); _fmpz_demote(f); if (g2 >= 0) { g2 = n_mod2_preinv(g2, m2, minv); *f = n_powmod2_ui_preinv(g2, e, m2, minv); } else { g2 = n_mod2_preinv(-g2, m2, minv); *f = n_powmod2_ui_preinv(g2, e, m2, minv); if ((e & UWORD(1))) *f = n_negmod(*f, m2); } } else /* g is large */ { ulong c3; mpz_t m3; __mpz_struct *ptr = _fmpz_promote(f); c3 = m2; m3->_mp_d = &c3; m3->_mp_size = 1; m3->_mp_alloc = 1; flint_mpz_powm_ui(ptr, COEFF_TO_PTR(g2), e, m3); _fmpz_demote_val(f); } } else /* m is large */ { _fmpz_powm_ui(f, g, e, m); } } } flint-3.1.3/src/fmpz/powmod2_fmpz_preinv.c000066400000000000000000000024171461254215100205540ustar00rootroot00000000000000/* Copyright (C) 2018, Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" ulong n_powmod2_fmpz_preinv(ulong a, const fmpz_t exp, ulong n, ulong ninv) { flint_bitcnt_t i, bits; ulong x, norm; FLINT_ASSERT(n != 0); FLINT_ASSERT(a < n); FLINT_ASSERT(fmpz_sgn(exp) >= 0); if (fmpz_is_zero(exp)) { /* anything modulo 1 is 0 */ return n == 1 ? 0 : 1; } if (a == 0) return 0; norm = flint_clz(n); a <<= norm; n <<= norm; bits = fmpz_bits(exp); i = 0; while (i < bits && fmpz_tstbit(exp, i) == 0) { a = n_mulmod_preinv(a, a, n, ninv, norm); i++; } x = a; i++; while (i < bits) { a = n_mulmod_preinv(a, a, n, ninv, norm); if (fmpz_tstbit(exp, i) != 0) { x = n_mulmod_preinv(x, a, n, ninv, norm); } i++; } return x >> norm; } flint-3.1.3/src/fmpz/preinvn.c000066400000000000000000000027051461254215100162270ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz.h" void fmpz_preinvn_init(fmpz_preinvn_t inv, const fmpz_t f) { fmpz c = *f; flint_bitcnt_t norm; mp_ptr t; if (c == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_preinvn_init). Division by zero.\n"); } else if (!COEFF_IS_MPZ(c)) /* c is small */ { inv->dinv = flint_malloc(sizeof(mp_limb_t)); if (c < 0) c = -c; norm = flint_clz(c); if (norm) c <<= norm; flint_mpn_preinvn(inv->dinv, (mp_ptr) &c, 1); inv->n = 1; } else /* c is big */ { __mpz_struct * mc = COEFF_TO_PTR(c); slong size = FLINT_ABS(mc->_mp_size); inv->dinv = flint_malloc(size*sizeof(mp_limb_t)); norm = flint_clz(mc->_mp_d[size - 1]); if (norm) { t = flint_malloc(size*sizeof(mp_limb_t)); mpn_lshift(t, mc->_mp_d, size, norm); } else t = mc->_mp_d; flint_mpn_preinvn(inv->dinv, t, size); inv->n = size; if (norm) flint_free(t); } inv->norm = norm; } void fmpz_preinvn_clear(fmpz_preinvn_t inv) { flint_free(inv->dinv); } flint-3.1.3/src/fmpz/primorial.c000066400000000000000000000073521461254215100165470ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpn_extras.h" #include "ulong_extras.h" #if FLINT64 #define LARGEST_ULONG_PRIMORIAL 52 #else #define LARGEST_ULONG_PRIMORIAL 28 #endif /* Only those with odd index */ const ulong ULONG_PRIMORIALS[] = { UWORD(6), UWORD(30), UWORD(210), UWORD(210), UWORD(2310), UWORD(30030), UWORD(30030), UWORD(510510), UWORD(9699690), UWORD(9699690), UWORD(223092870), UWORD(223092870), UWORD(223092870), #if FLINT64 UWORD(6469693230), UWORD(200560490130), UWORD(200560490130), UWORD(200560490130), UWORD(7420738134810), UWORD(7420738134810), UWORD(304250263527210), UWORD(13082761331670030), UWORD(13082761331670030), UWORD(614889782588491410), UWORD(614889782588491410), UWORD(614889782588491410) #endif }; #define PROD_LIMBS_DIRECT_CUTOFF 50 mp_size_t mpn_prod_limbs_direct(mp_limb_t * result, const mp_limb_t * factors, mp_size_t n) { mp_size_t k, len; mp_limb_t top; if (n < 1) { result[0] = UWORD(1); return 1; } result[0] = factors[0]; len = 1; for (k=1; k_mp_d, primes, pi, bits); mres->_mp_size = len; } flint-3.1.3/src/fmpz/profile/000077500000000000000000000000001461254215100160365ustar00rootroot00000000000000flint-3.1.3/src/fmpz/profile/p-addmul.c000066400000000000000000000060211461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "fmpz_vec.h" #include "gmpcompat.h" #define ntests 30 void fmpz_addmul_old(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1, c2; __mpz_struct * mf; c1 = *g; if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 < WORD(0)) fmpz_submul_ui(f, h, -c1); else fmpz_addmul_ui(f, h, c1); return; } c2 = *h; if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 < WORD(0)) fmpz_submul_ui(f, g, -c2); else fmpz_addmul_ui(f, g, c2); return; } /* both g and h are large */ mf = _fmpz_promote_val(f); mpz_addmul(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* cancellation may have occurred */ } void sample_new(void * arg, ulong count) { fmpz *res, *a, *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = _fmpz_vec_init(ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(b + jx, state, bits); fmpz_randtest(res + jx, state, bits); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_addmul(res + jx, a + jx, b + jx); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); _fmpz_vec_clear(b, ntests); flint_randclear(state); } void sample_old(void * arg, ulong count) { fmpz *res, *a, *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = _fmpz_vec_init(ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(b + jx, state, bits); fmpz_randtest(res + jx, state, bits); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_addmul_old(res + jx, a + jx, b + jx); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); _fmpz_vec_clear(b, ntests); flint_randclear(state); } slong sizes[] = { 10, 30, 60, 62, 64, 66, 80, 128, 160, 256, 512, 1024, 4096, 0 }; int main(void) { double minnew, maxnew, minold, maxold; int i, bits; for (i = 0; (bits = sizes[i]) != 0; i++) { prof_repeat(&minnew, &maxnew, sample_new, &bits); prof_repeat(&minold, &maxold, sample_old, &bits); flint_printf("%d bits: min %.2fx, max %.2fx\n", bits, minold / minnew, maxold / maxnew); } return 0; } flint-3.1.3/src/fmpz/profile/p-aors_ui.c000066400000000000000000000401721461254215100201040ustar00rootroot00000000000000/* Copyright (C) 2022 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "fmpz_vec.h" #include "gmpcompat.h" #define ntests 30 #define OLD_ALBIN 1 #if OLD_ALBIN static void _fmpz_add_mpn_1(fmpz_t f, const mp_limb_t * glimbs, mp_size_t gsz, mp_limb_t x); static void _fmpz_sub_mpn_1(fmpz_t f, const mp_limb_t * glimbs, mp_size_t gsz, mp_limb_t x); void fmpz_add_ui_old(fmpz_t f, const fmpz_t g, ulong x) { __mpz_struct * mf; slong g1 = *g; slong f1 = *f; if (!COEFF_IS_MPZ(g1)) /* g is small */ { mp_size_t sz = 2; if (g1 >= 0) { { /* add with jump if carry */ ulong tmp = g1; g1 += x; if (((ulong) g1) < tmp) goto carry; } if (((ulong) g1) <= COEFF_MAX) { if (COEFF_IS_MPZ(f1)) _fmpz_clear_mpz(f1); *f = g1; return; } nocarry: sz = 1; /* No carry, but result does not fit in small fmpz */ carry: if (COEFF_IS_MPZ(f1)) mf = COEFF_TO_PTR(f1); else { mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); } mf->_mp_size = sz; mf->_mp_d[0] = g1; mf->_mp_d[1] = 1; /* Set carry (not used if sz = 1) */ } else /* g < 0 */ { g1 += x; if (((slong) x) >= 0 && g1 <= COEFF_MAX) { /* If x > 0 does not have its top bit set * and COEFF_MIN <= g < 0, we can interpret x + g as a slong. * So if the result in g1 is smaller than COEFF_MAX, it is a * small fmpz. */ if (COEFF_IS_MPZ(f1)) _fmpz_clear_mpz(f1); *f = g1; return; } else { /* 1) If top bit is set in x, the result is going to be positive * but will be larger than COEFF_MAX since * * x + g >= (2^63) - (2^62 - 1) = 2^62 + 1. * * However, it will be contained in one limb since g < 0. * * 2) If top bit is not set, then result is larger than * COEFF_MAX, and so it cannot be a small fmpz. However, it * must fit in one limb since * * x + g <= (2^63 - 1) + (-1) = 2^63 - 2, * * which is contained in one limb. */ goto nocarry; } } } else { __mpz_struct * mg = COEFF_TO_PTR(g1); mp_size_t gsz = mg->_mp_size; mp_limb_t * glimbs = mg->_mp_d; if (gsz > 0) _fmpz_add_mpn_1(f, glimbs, gsz, x); else _fmpz_sub_mpn_1(f, glimbs, gsz, x); } } /* "Add" two number with same sign. Decide sign from g. */ static void _fmpz_add_mpn_1(fmpz_t f, const mp_limb_t * glimbs, mp_size_t gsz, mp_limb_t x) { __mpz_struct * mf; mp_limb_t * flimbs; mp_size_t gabssz = FLINT_ABS(gsz); /* Promote f as it is guaranteed to be large */ if (COEFF_IS_MPZ(*f)) mf = COEFF_TO_PTR(*f); else { mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); } flimbs = mf->_mp_d; if (mf->_mp_alloc < (gabssz + 1)) /* Ensure result fits */ { mp_limb_t * tmp = flimbs; flimbs = _mpz_realloc(mf, gabssz + 1); /* If f and g are aliased, then we need to change glimbs as well. */ if (tmp == glimbs) glimbs = flimbs; } /* Use GMP to calculate result */ flimbs[gabssz] = mpn_add_1(flimbs, glimbs, gabssz, x); /* flimbs[gabssz] is the carry from mpn_add_1, * and so gabssz + flimbs[gabssz] is valid to determine the size of f */ mf->_mp_size = gabssz + flimbs[gabssz]; if (gsz < 0) { /* g and x has same sign. If g is negative, we negate the result */ mf->_mp_size = -mf->_mp_size; } } /* Subtract two limbs (they have different sign) and decide the sign via g. */ static void _fmpz_sub_mpn_1(fmpz_t f, const mp_limb_t * glimbs, mp_size_t gsz, mp_limb_t x) { __mpz_struct * mf; mp_limb_t * flimbs; mp_size_t gabssz = FLINT_ABS(gsz); /* If size of g is 1, we have a higher probability of the result being * small. */ if (gabssz == 1) { if (x <= glimbs[0]) /* Result is zero or has the same sign as g */ { x = glimbs[0] - x; L1: if (x <= COEFF_MAX) /* Fits in small fmpz */ { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); *f = (gsz > 0) ? x : -x; /* With consideration of sign */ } else /* Does not fit in small fmpz */ { if (COEFF_IS_MPZ(*f)) mf = COEFF_TO_PTR(*f); else { mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); } mf->_mp_d[0] = x; mf->_mp_size = gsz; /* Sign of f is the same as for g */ } } else /* |x| > |g|, which implies f has opposite sign of g */ { /* Set x to the absolute value of |g - x|. By switching sign of * gsz, we can reuse the code above. */ x -= glimbs[0]; gsz = -gsz; goto L1; } return; } /* As g has more than one limb, it is a very high probability that result * does not fit inside small fmpz. */ if (COEFF_IS_MPZ(*f)) mf = COEFF_TO_PTR(*f); else { mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); } flimbs = mf->_mp_d; if (gabssz == 2) { /* Special case. Can result in a small fmpz, but as |g| > |x| the sign * cannot change. */ sub_ddmmss(flimbs[1], flimbs[0], glimbs[1], glimbs[0], 0, x); if (flimbs[1] != 0) { /* Most likely: upper limb not zero, so we just have set the sign * of f to g's. */ mf->_mp_size = gsz; } else if (flimbs[0] > COEFF_MAX) { /* Still very likely: Upper limb is zero but lower limb does not * fit inside a small fmpz. Sign is the same as for g, but the * absolute value of the size is one. */ mf->_mp_size = (gsz > 0) ? 1 : -1; } else { /* Upper limb is zero and lower limb fits inside a small fmpz. * Therefore we set f to +/- flimbs[0] and clear the mpz associated * to f. */ slong tmp = flimbs[0]; /* We will clear this mpz, so save first. */ _fmpz_clear_mpz(*f); *f = (gsz > 0) ? tmp : -tmp; } } else { /* As the absolute value of g's size is larger than 2, the result won't * fit inside a small fmpz. */ if (mf->_mp_alloc < gabssz) /* Ensure result fits */ { /* The allocation size of g is always larger than the absolute value * of g. Therefore, if f's allocation size is smaller than g's * size, they cannot be aliased. */ flimbs = _mpz_realloc(mf, gabssz); } mpn_sub_1(flimbs, glimbs, gabssz, x); /* Subtract via GMP */ /* If last limb is zero, we have to set f's absolute size to one less * than g's. */ mf->_mp_size = gabssz - (flimbs[gabssz - 1] == 0); if (gsz < 0) /* If g is negative, then f is negative as well. */ mf->_mp_size = -mf->_mp_size; } } void fmpz_sub_ui_old(fmpz_t f, const fmpz_t g, ulong x) { __mpz_struct * mf; slong g1 = *g; slong f1 = *f; if (!COEFF_IS_MPZ(g1)) /* g is small */ { mp_size_t sz = -2; if (g1 <= 0) { /* "add" with jump if carry */ g1 = x - g1; /* g1 = x + |g| */ if (((ulong) g1) < x) goto carry; if (((ulong) g1) <= COEFF_MAX) { if (COEFF_IS_MPZ(f1)) _fmpz_clear_mpz(f1); *f = -g1; return; } nocarry: sz = -1; /* No carry, but result is not a small fmpz */ carry: if (COEFF_IS_MPZ(f1)) mf = COEFF_TO_PTR(f1); else { mf = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mf); } mf->_mp_size = sz; mf->_mp_d[0] = g1; mf->_mp_d[1] = 1; /* Set carry (not used if sz = -1) */ } else { g1 = x - g1; /* -(g - x) */ if (((slong) x) >= 0 && g1 <= COEFF_MAX) { /* If x > 0 does not have its top bit set * and 0 < g <= COEFF_MAX, we can interpret x - g as a slong. * So if the result in g1 is smaller than COEFF_MAX, it is a * small fmpz. */ if (COEFF_IS_MPZ(f1)) _fmpz_clear_mpz(f1); *f = -g1; /* g - x = -(x - g) */ return; } else { /* 1) If top bit is set in x, the result is going to be negative * but will be larger than COEFF_MAX since * * x - g >= 2^63 - (2^62 - 1) = 2^62 + 1. * * However, it will be contained in one limb since g > 0. * * 2) If top bit is not set, then result is smaller than * COEFF_MIN, and so it cannot be a small fmpz. However, it * must fit in one limb since * * x - g <= (2^63 - 1) - 1 = 2^63 - 2, * * which is contained in one limb. */ goto nocarry; } } } else { __mpz_struct * mg = COEFF_TO_PTR(g1); mp_size_t gsz = mg->_mp_size; mp_limb_t * glimbs = mg->_mp_d; if (gsz > 0) _fmpz_sub_mpn_1(f, glimbs, gsz, x); else _fmpz_add_mpn_1(f, glimbs, gsz, x); } } #else void fmpz_add_ui_old(fmpz_t f, const fmpz_t g, ulong x) { fmpz c = *g; if (!COEFF_IS_MPZ(c)) /* g is small */ { mp_limb_t sum[2]; if (c >= WORD(0)) /* both operands non-negative */ { add_ssaaaa(sum[1], sum[0], 0, c, 0, x); fmpz_set_uiui(f, sum[1], sum[0]); } else /* coeff is negative, x positive */ { if (-c > x) fmpz_set_si(f, x + c); /* can't overflow as g is small and x smaller */ else fmpz_set_ui(f, x + c); /* won't be negative and has to be less than x */ } } else { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ __mpz_struct * mc = COEFF_TO_PTR(c); flint_mpz_add_ui(mf, mc, x); _fmpz_demote_val(f); /* cancellation may have occurred */ } } void fmpz_sub_ui_old(fmpz_t f, const fmpz_t g, ulong x) { fmpz c = *g; if (!COEFF_IS_MPZ(c)) /* coeff is small */ { mp_limb_t sum[2]; if (c < WORD(0)) /* g negative, x positive, so difference is negative */ { add_ssaaaa(sum[1], sum[0], 0, -c, 0, x); fmpz_neg_uiui(f, sum[1], sum[0]); } else /* coeff is non-negative, x non-negative */ { if (x < c) fmpz_set_ui(f, c - x); /* won't be negative and is smaller than c */ else fmpz_neg_ui(f, x - c); /* positive or zero */ } } else { __mpz_struct * mc, * mf; mf = _fmpz_promote(f); /* g is already large */ mc = COEFF_TO_PTR(c); flint_mpz_sub_ui(mf, mc, x); _fmpz_demote_val(f); /* cancellation may have occurred */ } } #endif void sample_add_new(void * arg, ulong count) { fmpz *res, *a; ulong *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = flint_malloc(sizeof(mp_limb_t) * ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(res + jx, state, bits); b[jx] = n_randtest(state); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_add_ui(res + jx, a + jx, b[jx]); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); flint_free(b); flint_randclear(state); } void sample_add_old(void * arg, ulong count) { fmpz *res, *a; ulong *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = flint_malloc(sizeof(mp_limb_t) * ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(res + jx, state, bits); b[jx] = n_randtest(state); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_add_ui_old(res + jx, a + jx, b[jx]); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); flint_free(b); flint_randclear(state); } void sample_sub_new(void * arg, ulong count) { fmpz *res, *a; ulong *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = flint_malloc(sizeof(mp_limb_t) * ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(res + jx, state, bits); b[jx] = n_randtest(state); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_sub_ui(res + jx, a + jx, b[jx]); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); flint_free(b); flint_randclear(state); } void sample_sub_old(void * arg, ulong count) { fmpz *res, *a; ulong *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = flint_malloc(sizeof(mp_limb_t) * ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(res + jx, state, bits); b[jx] = n_randtest(state); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_sub_ui_old(res + jx, a + jx, b[jx]); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); flint_free(b); flint_randclear(state); } slong sizes[] = { 10, 30, 60, 62, 64, 66, 80, 128, 160, 256, 512, 1024, 4096, 0 }; int main(void) { double minnew, maxnew, minold, maxold; int i, bits; flint_printf("ADD\n"); for (i = 0; (bits = sizes[i]) != 0; i++) { prof_repeat(&minnew, &maxnew, sample_add_new, &bits); prof_repeat(&minold, &maxold, sample_add_old, &bits); flint_printf("%d bits: min %.2fx, max %.2fx\n", bits, minold / minnew, maxold / maxnew); } flint_printf("\nSUB\n"); for (i = 0; (bits = sizes[i]) != 0; i++) { prof_repeat(&minnew, &maxnew, sample_sub_new, &bits); prof_repeat(&minold, &maxold, sample_sub_old, &bits); flint_printf("%d bits: min %.2fx, max %.2fx\n", bits, minold / minnew, maxold / maxnew); } return 0; } flint-3.1.3/src/fmpz/profile/p-crt.c000066400000000000000000000104351461254215100172320ustar00rootroot00000000000000#include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" void _fmpz_crt_combine(fmpz_t r1r2, fmpz_t m1m2, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2) { fmpz_invmod(m1m2, m1, m2); fmpz_mul(m1m2, m1m2, m1); fmpz_sub(r1r2, r2, r1); fmpz_mul(r1r2, r1r2, m1m2); fmpz_add(r1r2, r1r2, r1); fmpz_mul(m1m2, m1, m2); fmpz_mod(r1r2, r1r2, m1m2); } void _fmpz_crt_combine_uiui(fmpz_t r1r2, fmpz_t m1m2, ulong r1, ulong m1, ulong r2, ulong m2) { mp_limb_t M[2]; /* M = m1 * m2 c = invmod(m1, m2) * m1 r1r2 = ((r2 - r1) * c + r1) mod M m1m2 = M */ /* M = m1 * m2 */ umul_ppmm(M[1], M[0], m1, m2); if (M[1] == 0) { mp_limb_t c, v; c = n_invmod(m1, m2) * m1; if (r2 >= r1) v = n_mulmod2(r2 - r1, c, M[0]); else v = n_mulmod2(n_negmod(r1 - r2, M[0]), c, M[0]); v = n_addmod(v, r1, M[0]); fmpz_set_ui(r1r2, v); fmpz_set_ui(m1m2, M[0]); } else { mp_limb_t c[2], t[4], q[3], r[3]; umul_ppmm(c[1], c[0], n_invmod(m1, m2), m1); if (r2 >= r1) { t[2] = mpn_mul_1(t, c, 2, r2 - r1); mpn_add_1(t, t, 3, r1); mpn_tdiv_qr(q, r, 0, t, 3, M, 2); } else { sub_ddmmss(r[1], r[0], M[1], M[0], 0, r1 - r2); mpn_mul_n(t, c, r, 2); mpn_add_1(t, t, 4, r1); mpn_tdiv_qr(q, r, 0, t, 4, M, 2); } fmpz_set_uiui(r1r2, r[1], r[0]); fmpz_set_uiui(m1m2, M[1], M[0]); } } void tree_crt(fmpz_t r, fmpz_t m, mp_srcptr residues, mp_srcptr primes, slong len) { if (len == 0) { fmpz_zero(r); fmpz_one(m); } else if (len == 1) { fmpz_set_ui(r, residues[0]); fmpz_set_ui(m, primes[0]); } else if (len == 2) { _fmpz_crt_combine_uiui(r, m, residues[0], primes[0], residues[1], primes[1]); } else { fmpz_t r1, m1, r2, m2; fmpz_init(r1); fmpz_init(m1); fmpz_init(r2); fmpz_init(m2); tree_crt(r1, m1, residues, primes, len / 2); tree_crt(r2, m2, residues + len / 2, primes + len / 2, len - len / 2); _fmpz_crt_combine(r, m, r1, m1, r2, m2); fmpz_clear(r1); fmpz_clear(m1); fmpz_clear(r2); fmpz_clear(m2); } } void fmpz_print1(const fmpz_t n) { /* printf("%lu", fmpz_fdiv_ui(n, 1000000000)); printf("\n"); */ } void benchmark(slong num_primes, slong prime_bits) { flint_rand_t state; fmpz_comb_temp_t temp; fmpz_comb_t comb; mp_ptr primes, residues; fmpz_t res; slong k; flint_randinit(state); primes = flint_malloc(num_primes * sizeof(mp_limb_t)); residues = flint_malloc(num_primes * sizeof(mp_limb_t)); fmpz_init(res); primes[0] = n_nextprime(UWORD(1) << (prime_bits - 1), 0); for (k = 1; k < num_primes; k++) primes[k] = n_nextprime(primes[k-1], 0); for (k = 0; k < num_primes; k++) residues[k] = n_randint(state, primes[k]); printf("simple tree: "); TIMEIT_START fmpz_t tmp; fmpz_init(tmp); tree_crt(res, tmp, residues, primes, num_primes); fmpz_clear(tmp); TIMEIT_STOP fmpz_print1(res); printf("multi CRT: "); TIMEIT_START fmpz_comb_init(comb, primes, num_primes); fmpz_comb_temp_init(temp, comb); fmpz_multi_CRT_ui(res, residues, comb, temp, 0); fmpz_comb_clear(comb); fmpz_comb_temp_clear(temp); TIMEIT_STOP fmpz_print1(res); printf("multi precomp: "); fmpz_comb_init(comb, primes, num_primes); fmpz_comb_temp_init(temp, comb); TIMEIT_START fmpz_multi_CRT_ui(res, residues, comb, temp, 0); TIMEIT_STOP fmpz_comb_clear(comb); fmpz_comb_temp_clear(temp); fmpz_print1(res); flint_free(primes); flint_free(residues); fmpz_clear(res); } int main(void) { slong len, bits; bits = 5; for (len = 1; len <= 4000; len = FLINT_MAX(len * 1.5, len + 1)) { printf("bits = %ld, len = %ld\n", bits, len); benchmark(len, bits); } bits = 64; for (len = 1; len <= 4000; len = FLINT_MAX(len * 1.5, len + 1)) { printf("bits = %ld, len = %ld\n", bits, len); benchmark(len, bits); } return 0; } flint-3.1.3/src/fmpz/profile/p-div_qr.c000066400000000000000000000135071461254215100177310ustar00rootroot00000000000000/* Copyright 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "profiler.h" void sample_ndiv_qr(void * arg, ulong count) { fmpz_t q, r, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(q); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, FLINT_BITS); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); if (n_randint(state, 2)) fmpz_neg(a, a); if (n_randint(state, 2)) fmpz_neg(b, b); if (fmpz_is_zero(b)) fmpz_one(b); fmpz_ndiv_qr(q, r, a, b); } prof_stop(); fmpz_clear(q); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_fdiv_qr(void * arg, ulong count) { fmpz_t q, r, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(q); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, FLINT_BITS); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); if (n_randint(state, 2)) fmpz_neg(a, a); if (n_randint(state, 2)) fmpz_neg(b, b); if (fmpz_is_zero(b)) fmpz_one(b); fmpz_fdiv_qr(q, r, a, b); } prof_stop(); fmpz_clear(q); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_cdiv_qr(void * arg, ulong count) { fmpz_t q, r, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(q); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, FLINT_BITS); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); if (n_randint(state, 2)) fmpz_neg(a, a); if (n_randint(state, 2)) fmpz_neg(b, b); if (fmpz_is_zero(b)) fmpz_one(b); fmpz_cdiv_qr(q, r, a, b); } prof_stop(); fmpz_clear(q); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_tdiv_qr(void * arg, ulong count) { fmpz_t q, r, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(q); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, FLINT_BITS); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); if (n_randint(state, 2)) fmpz_neg(a, a); if (n_randint(state, 2)) fmpz_neg(b, b); if (fmpz_is_zero(b)) fmpz_one(b); fmpz_tdiv_qr(q, r, a, b); } prof_stop(); fmpz_clear(q); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } int main(void) { double min, max; prof_repeat(&min, &max, sample_ndiv_qr, NULL); flint_printf("fmpz_ndiv_qr:\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_fdiv_qr, NULL); flint_printf("fmpz_fdiv_qr:\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_cdiv_qr, NULL); flint_printf("fmpz_cdiv_qr:\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_tdiv_qr, NULL); flint_printf("fmpz_tdiv_qr:\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); { flint_bitcnt_t abits, bbits; fmpz * as, * bs; fmpz_t q, r; slong i, len = 2000000; flint_rand_t state; timeit_t timer; flint_randinit(state); as = _fmpz_vec_init(len); bs = _fmpz_vec_init(len); fmpz_init(q); fmpz_init(r); for (bbits = 10; bbits <= 300; bbits += bbits/4) { flint_printf("%4wu: ", bbits); for (abits = 10; abits <= 300; abits += abits/4) { for (i = 0; i < len; i++) { fmpz_randbits(as + i, state, abits); fmpz_randbits(bs + i, state, bbits); } timeit_start(timer); for (i = 0; i < len; i++) fmpz_ndiv_qr(q, r, as + i, bs + i); timeit_stop(timer); flint_printf(" %4wd", timer->wall); fflush(stdout); } flint_printf("\n"); } fmpz_clear(q); fmpz_clear(r); _fmpz_vec_clear(as, len); _fmpz_vec_clear(bs, len); flint_randclear(state); } return 0; } flint-3.1.3/src/fmpz/profile/p-fdiv_qr_preinvn.c000066400000000000000000000044511461254215100216360ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" typedef struct { slong limbs; int algo; } info_t; void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong limbs = info->limbs, i, j; int algo = info->algo; int scale = 200; fmpz_t a, b, c, r; fmpz_preinvn_t inv; FLINT_TEST_INIT(state); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(r); for (i = 0; i < count; i++) { fmpz_randbits(a, state, (2*limbs - 1)*FLINT_BITS); fmpz_randbits(b, state, limbs*FLINT_BITS); fmpz_preinvn_init(inv, b); prof_start(); if (algo == 1) { for (j = 0; j < scale; j++) { fmpz_fdiv_qr_preinvn(c, r, a, b, inv); } } else { for (j = 0; j < scale; j++) { fmpz_fdiv_qr(c, r, a, b); } } prof_stop(); } fmpz_preinvn_clear(inv); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(r); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("1: With precomputed inverse\n"); printf("2: Without precomputed inverse\n\n"); for (k = 1; k <= 10000; k = (slong) ceil(1.1*k)) { info.limbs = k; info.algo = 1; scale = 200; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("1: limbs %wd, min %.3g ms, max %.3g ms\n", info.limbs, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); info.algo = 2; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("2: limbs %wd, min %.3g ms, max %.3g ms\n\n", info.limbs, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); } return 0; } flint-3.1.3/src/fmpz/profile/p-fmma.c000066400000000000000000000143211461254215100173600ustar00rootroot00000000000000/* Copyright 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "profiler.h" void fmpz_fmma_old(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d) { fmpz s, t, u, v; s = *a; t = *b; u = *c; v = *d; if (s == 0 || t == 0) { fmpz_mul(f, c, d); return; } if (u == 0 || v == 0) { fmpz_mul(f, a, b); return; } if (!COEFF_IS_MPZ(s) && !COEFF_IS_MPZ(t) && !COEFF_IS_MPZ(u) && !COEFF_IS_MPZ(v)) { mp_limb_t sh, sl, th, tl; smul_ppmm(sh, sl, s, t); smul_ppmm(th, tl, u, v); add_ssaaaa(sh, sl, sh, sl, th, tl); fmpz_set_signed_uiui(f, sh, sl); return; } if (f == c || f == d) { if (f == a || f == b) { fmpz_t t; fmpz_init(t); fmpz_mul(t, a, b); fmpz_addmul(t, c, d); fmpz_swap(t, f); fmpz_clear(t); } else { fmpz_mul(f, c, d); fmpz_addmul(f, a, b); } } else { fmpz_mul(f, a, b); fmpz_addmul(f, c, d); } } void sample_small(void * arg, ulong count) { fmpz_t r, a, b, c, d; int ix; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); prof_start(); for (ix = 0; ix < 1000000 * count; ix++) { fmpz_set_ui(a, n_randint(state, COEFF_MAX)); fmpz_set_ui(b, n_randint(state, COEFF_MAX)); fmpz_set_ui(c, n_randint(state, COEFF_MAX)); fmpz_set_ui(d, n_randint(state, COEFF_MAX)); fmpz_fmma(r, a, b, c, d); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); flint_randclear(state); } void sample_small_old(void * arg, ulong count) { fmpz_t r, a, b, c, d; int ix; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); prof_start(); for (ix = 0; ix < 1000000 * count; ix++) { fmpz_set_ui(a, n_randint(state, COEFF_MAX)); fmpz_set_ui(b, n_randint(state, COEFF_MAX)); fmpz_set_ui(c, n_randint(state, COEFF_MAX)); fmpz_set_ui(d, n_randint(state, COEFF_MAX)); fmpz_fmma_old(r, a, b, c, d); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); flint_randclear(state); } void sample_small_zeros(void * arg, ulong count) { fmpz_t r, a, b, c, d; int ix; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_zero(c); prof_start(); for (ix = 0; ix < 1000000 * count; ix++) { fmpz_set_ui(a, n_randint(state, COEFF_MAX)); fmpz_set_ui(b, n_randint(state, COEFF_MAX)); fmpz_set_ui(d, n_randint(state, COEFF_MAX)); fmpz_fmma(r, a, b, c, d); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); flint_randclear(state); } void sample_small_zeros_old(void * arg, ulong count) { fmpz_t r, a, b, c, d; int ix; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_zero(c); prof_start(); for (ix = 0; ix < 1000000 * count; ix++) { fmpz_set_ui(a, n_randint(state, COEFF_MAX)); fmpz_set_ui(b, n_randint(state, COEFF_MAX)); fmpz_set_ui(d, n_randint(state, COEFF_MAX)); fmpz_fmma_old(r, a, b, c, d); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); flint_randclear(state); } void sample_big_zeros(void * arg, ulong count) { fmpz_t r, a, b, c, d; int ix; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_zero(c); prof_start(); for (ix = 0; ix < 1000000 * count; ix++) { fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 100); fmpz_randtest(d, state, 100); fmpz_fmma(r, a, b, c, d); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); flint_randclear(state); } void sample_big_zeros_old(void * arg, ulong count) { fmpz_t r, a, b, c, d; int ix; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_zero(c); prof_start(); for (ix = 0; ix < 1000000 * count; ix++) { fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 100); fmpz_randtest(d, state, 100); fmpz_fmma_old(r, a, b, c, d); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); flint_randclear(state); } int main(void) { double minnew, maxnew, minold, maxold; prof_repeat(&minnew, &maxnew, sample_small, NULL); prof_repeat(&minold, &maxold, sample_small_old, NULL); flint_printf("fmpz_fmma with small numbers:\n" " min %.3fx speedup, max %.3fx speedup\n", minold / minnew, maxold / maxnew); prof_repeat(&minnew, &maxnew, sample_small_zeros, NULL); prof_repeat(&minold, &maxold, sample_small_zeros_old, NULL); flint_printf("fmpz_fmma with one zero and small entries:\n" " min %.3fx speedup, max %.3fx speedup\n", minold / minnew, maxold / maxnew); prof_repeat(&minnew, &maxnew, sample_big_zeros, NULL); prof_repeat(&minold, &maxold, sample_big_zeros_old, NULL); flint_printf("fmpz_fmma with one zero and big entries:\n" " min %.3fx speedup, max %.3fx speedup\n", minold / minnew, maxold / maxnew); return 0; } flint-3.1.3/src/fmpz/profile/p-gcd.c000066400000000000000000000062721461254215100172030ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "profiler.h" typedef struct { slong bits; } info_t; ulong z_gcd_old(slong a, slong b) { ulong ua = FLINT_ABS(a); ulong ub = FLINT_ABS(b); return n_gcd(ua, ub); } void fmpz_gcd_old(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(g)) { fmpz_abs(f, h); return; } if (fmpz_is_zero(h)) { fmpz_abs(f, g); return; } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz_set_si(f, z_gcd_old(c1, c2)); } else /* h is large, but g is small */ { fmpz c2d = fmpz_fdiv_ui(h, FLINT_ABS(c1)); fmpz_set_si(f, z_gcd_old(c1, c2d)); } } else { if (!COEFF_IS_MPZ(c2)) /* h is small, but g is large */ { fmpz c1d = fmpz_fdiv_ui(g, FLINT_ABS(c2)); fmpz_set_si(f, z_gcd_old(c2, c1d)); } else /* g and h are both large */ { __mpz_struct *z = _fmpz_promote(f); /* aliasing fine as g, h already large */ mpz_gcd(z, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* gcd may be small */ } } } void sample_new(void * arg, ulong count) { fmpz_t r, a, b; int ix; info_t * info = (info_t *) arg; slong bits = info->bits; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); prof_start(); for (ix = 0; ix < 1000 * count; ix++) { fmpz_randtest(a, state, bits); fmpz_randtest(b, state, bits); fmpz_gcd(r, a, b); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); flint_randclear(state); } void sample_old(void * arg, ulong count) { fmpz_t r, a, b; int ix; info_t * info = (info_t *) arg; slong bits = info->bits; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); prof_start(); for (ix = 0; ix < 1000 * count; ix++) { fmpz_randtest(a, state, bits); fmpz_randtest(b, state, bits); fmpz_gcd_old(r, a, b); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); flint_randclear(state); } int main(void) { double minnew, maxnew, minold, maxold; int bits; info_t as; for (bits = 5; bits <= 150; bits += 5) { as.bits = bits; prof_repeat(&minnew, &maxnew, sample_new, &as); prof_repeat(&minold, &maxold, sample_old, &as); flint_printf("%3d bits: (min) %.2fx speedup (max) %.2fx speedup\n", bits, minold / minnew, maxold / maxnew); } return 0; } flint-3.1.3/src/fmpz/profile/p-gcd3.c000066400000000000000000000120321461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" typedef struct { slong bits; } info_t; static ulong _fmpz_gcd_big_small_old(const fmpz_t g, ulong h) { __mpz_struct * z = COEFF_TO_PTR(*g); return n_gcd(mpn_mod_1(z->_mp_d, FLINT_ABS(z->_mp_size), h), h); } static ulong _fmpz_gcd_small_old(const fmpz_t g, ulong h) { if (!COEFF_IS_MPZ(*g)) return n_gcd(FLINT_ABS(*g), h); else return _fmpz_gcd_big_small_old(g, h); } static void fmpz_gcd3_small_old(fmpz_t res, const fmpz_t a, const fmpz_t b, ulong c) { if (c <= 1) { if (c == 1) fmpz_one(res); else fmpz_gcd(res, a, b); } else { if (!COEFF_IS_MPZ(*a)) { c = n_gcd(FLINT_ABS(*a), c); if (c != 1) c = _fmpz_gcd_small_old(b, c); } else { c = _fmpz_gcd_small_old(b, c); if (c != 1) c = _fmpz_gcd_big_small_old(a, c); } fmpz_set_ui(res, c); } } void fmpz_gcd3_old(fmpz_t res, const fmpz_t a, const fmpz_t b, const fmpz_t c) { if (!COEFF_IS_MPZ(*a)) { fmpz_gcd3_small_old(res, b, c, FLINT_ABS(*a)); } else if (!COEFF_IS_MPZ(*b)) { fmpz_gcd3_small_old(res, a, c, FLINT_ABS(*b)); } else if (!COEFF_IS_MPZ(*c)) { fmpz_gcd3_small_old(res, a, b, FLINT_ABS(*c)); } else { /* Three-way mpz_gcd. */ __mpz_struct *rp, *ap, *bp, *cp, *tp; mp_size_t an, bn, cn, mn; /* If res is small, it cannot be aliased with a, b, c, so promoting is fine. */ rp = _fmpz_promote(res); ap = COEFF_TO_PTR(*a); bp = COEFF_TO_PTR(*b); cp = COEFF_TO_PTR(*c); an = FLINT_ABS(ap->_mp_size); bn = FLINT_ABS(bp->_mp_size); cn = FLINT_ABS(cp->_mp_size); /* Select c to be the largest operand; we do the smaller gcd first. */ mn = FLINT_MAX(FLINT_MAX(an, bn), cn); tp = cp; if (mn != cn) { if (mn == an) { cp = ap; ap = tp; } else { cp = bp; bp = tp; } cn = mn; } /* Handle aliasing */ if (rp == cp) { mpz_t t; TMP_INIT; TMP_START; /* It would be more efficient to allocate temporary space for gcd(a, b), but we can't be sure that mpz_gcd never attempts to reallocate the output. */ t->_mp_d = TMP_ALLOC(sizeof(mp_limb_t) * cn); t->_mp_size = t->_mp_alloc = cn; flint_mpn_copyi(t->_mp_d, cp->_mp_d, cn); mpz_gcd(rp, ap, bp); if (mpz_cmpabs_ui(rp, 1) != 0) mpz_gcd(rp, rp, t); TMP_END; } else { mpz_gcd(rp, ap, bp); if (mpz_cmpabs_ui(rp, 1) != 0) mpz_gcd(rp, rp, cp); } /* The result may be small */ _fmpz_demote_val(res); } } void sample_new(void * arg, ulong count) { fmpz_t r, a, b, c; int ix; info_t * info = (info_t *) arg; slong bits = info->bits; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); prof_start(); for (ix = 0; ix < 1000 * count; ix++) { fmpz_randtest(a, state, bits); fmpz_randtest(b, state, bits); fmpz_randtest(c, state, bits); fmpz_gcd3(r, a, b, c); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); flint_randclear(state); } void sample_old(void * arg, ulong count) { fmpz_t r, a, b, c; int ix; info_t * info = (info_t *) arg; slong bits = info->bits; FLINT_TEST_INIT(state); fmpz_init(r); fmpz_init(a); fmpz_init(b); fmpz_init(c); prof_start(); for (ix = 0; ix < 1000 * count; ix++) { fmpz_randtest(a, state, bits); fmpz_randtest(b, state, bits); fmpz_randtest(c, state, bits); fmpz_gcd3_old(r, a, b, c); } prof_stop(); fmpz_clear(r); fmpz_clear(a); fmpz_clear(b); flint_randclear(state); } int main(void) { double minnew, maxnew, minold, maxold; int bits; info_t as; for (bits = 1; bits <= 200; bits += 3) { as.bits = bits; prof_repeat(&minnew, &maxnew, sample_new, &as); prof_repeat(&minold, &maxold, sample_old, &as); flint_printf("%3d bits: (min) %.2fx speedup (max) %.2fx speedup\n", bits, minold / minnew, maxold / maxnew); } return 0; } flint-3.1.3/src/fmpz/profile/p-is_prime_bench.c000066400000000000000000000022371461254215100214110ustar00rootroot00000000000000/* Copyright 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz.h" #include "fmpz_factor.h" #include "ulong_extras.h" slong bits[] = { 1, 64, 128, 256, 512, 1024 }; slong reps[] = { 10000000, 10000000, 30000, 3000, 3000, 1500 }; int main(void) { slong i, b, count; fmpz_t n; flint_set_num_threads(8); fmpz_init(n); for (b = 0; b < 6; b++) { count = 0; flint_printf("%wd x %wd bits: ", reps[b], bits[b]); fmpz_one(n); fmpz_mul_2exp(n, n, bits[b] - 1); TIMEIT_ONCE_START for (i = 0; i < reps[b]; i++) { fmpz_add_ui(n, n, 1); count += fmpz_is_prime(n); } flint_printf("%wd found ", count); TIMEIT_ONCE_STOP } fmpz_clear(n); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz/profile/p-is_probabprime_bench.c000066400000000000000000000022531461254215100225750ustar00rootroot00000000000000/* Copyright 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz.h" #include "fmpz_factor.h" #include "ulong_extras.h" slong bits[] = { 1, 64, 128, 256, 1024, 4096 }; slong reps[] = { 10000000, 10000000, 1000000, 100000, 10000, 1000 }; int main(void) { slong i, b, count; fmpz_t n; flint_set_num_threads(8); fmpz_init(n); for (b = 0; b < 6; b++) { count = 0; flint_printf("%wd x %wd bits: ", reps[b], bits[b]); fmpz_one(n); fmpz_mul_2exp(n, n, bits[b] - 1); TIMEIT_ONCE_START for (i = 0; i < reps[b]; i++) { fmpz_add_ui(n, n, 1); count += fmpz_is_probabprime(n); } flint_printf("%wd found ", count); TIMEIT_ONCE_STOP } fmpz_clear(n); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz/profile/p-mul.c000066400000000000000000000061761461254215100172460ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "fmpz_vec.h" #include "gmpcompat.h" #define ntests 30 void fmpz_mul_old(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1, c2; __mpz_struct *z; c1 = *g; if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_mul_si(f, h, c1); return; } c2 = *h; /* save h in case it is aliased with f */ if (c2 == WORD(0)) /* special case, h = 0 */ { fmpz_zero(f); return; } z = _fmpz_promote(f); /* h is saved, g is already large */ if (!COEFF_IS_MPZ(c2)) /* g is large, h is small */ flint_mpz_mul_si(z, COEFF_TO_PTR(c1), c2); else /* c1 and c2 are large */ mpz_mul(z, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } void sample_new(void * arg, ulong count) { fmpz *res, *a, *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = _fmpz_vec_init(ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(b + jx, state, bits); fmpz_randtest(res + jx, state, bits); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_mul(res + jx, a + jx, b + jx); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); _fmpz_vec_clear(b, ntests); flint_randclear(state); } void sample_old(void * arg, ulong count) { fmpz *res, *a, *b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); res = _fmpz_vec_init(ntests); a = _fmpz_vec_init(ntests); b = _fmpz_vec_init(ntests); for (ix = 0; ix < 10 * count; ix++) { for (jx = 0; jx < ntests; jx++) { fmpz_randtest(a + jx, state, bits); fmpz_randtest(b + jx, state, bits); fmpz_randtest(res + jx, state, bits); } prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_mul_old(res + jx, a + jx, b + jx); prof_stop(); } _fmpz_vec_clear(res, ntests); _fmpz_vec_clear(a, ntests); _fmpz_vec_clear(b, ntests); flint_randclear(state); } slong sizes[] = { 10, 30, 60, 62, 64, 66, 80, 128, 160, 256, 512, 1024, 4096, 0 }; int main(void) { double minnew, maxnew, minold, maxold; int i, bits; for (i = 0; (bits = sizes[i]) != 0; i++) { prof_repeat(&minnew, &maxnew, sample_new, &bits); prof_repeat(&minold, &maxold, sample_old, &bits); flint_printf("%d bits: min %.2fx, max %.2fx\n", bits, minold / minnew, maxold / maxnew); } return 0; } flint-3.1.3/src/fmpz/profile/p-mul_2exp.c000066400000000000000000000052061461254215100201750ustar00rootroot00000000000000/* Copyright (C) 2022 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "gmpcompat.h" #define ntests 1000 void fmpz_mul_2exp_old(fmpz_t f, const fmpz_t g, ulong exp) { fmpz d = *g; if (!COEFF_IS_MPZ(d)) /* g is small */ { ulong dabs = FLINT_ABS(d); ulong bits = FLINT_BIT_COUNT(dabs); if (bits == 0) { fmpz_set_si(f, 0); } else if (bits + exp <= SMALL_FMPZ_BITCOUNT_MAX) /* result will fit in small */ { fmpz_set_si(f, d << exp); } else /* result is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is saved */ flint_mpz_set_si(mf, d); mpz_mul_2exp(mf, mf, exp); } } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ mpz_mul_2exp(mf, COEFF_TO_PTR(d), exp); } } void sample_new(void * arg, ulong count) { fmpz_t res, a; ulong ix, jx, b; int bits = *((int *) arg); FLINT_TEST_INIT(state); fmpz_init(res); fmpz_init(a); for (ix = 0; ix < count; ix++) { fmpz_randtest(a, state, bits); b = n_randint(state, 200); prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_mul_2exp(res, a, b); prof_stop(); } flint_randclear(state); fmpz_clear(res); fmpz_clear(a); } void sample_old(void * arg, ulong count) { fmpz_t res, a; ulong ix, jx, b; int bits = *((int *) arg); FLINT_TEST_INIT(state); fmpz_init(res); fmpz_init(a); for (ix = 0; ix < count; ix++) { fmpz_randtest(a, state, bits); b = n_randint(state, 200); prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_mul_2exp_old(res, a, b); prof_stop(); } flint_randclear(state); fmpz_clear(res); fmpz_clear(a); } int main(void) { double minnew, maxnew, minold, maxold; int bits; for (bits = 5; bits <= 150; bits += 5) { prof_repeat(&minnew, &maxnew, sample_new, &bits); prof_repeat(&minold, &maxold, sample_old, &bits); flint_printf("%d bits: min %.2fx, max %.2fx\n", bits, minold / minnew, maxold / maxnew); } return 0; } flint-3.1.3/src/fmpz/profile/p-mul_ui.c000066400000000000000000000050551461254215100177360ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "ulong_extras.h" #define ntests 2000 void fmpz_mul_ui_old(fmpz_t f, const fmpz_t g, ulong x) { fmpz c2 = *g; if (!COEFF_IS_MPZ(c2)) /* c2 is small */ { mp_limb_t th, tl; mp_limb_t uc2 = FLINT_ABS(c2); /* unsigned limb by limb multiply (assembly for most CPU's) */ umul_ppmm(th, tl, uc2, x); if (c2 >= 0) fmpz_set_uiui(f, th, tl); else fmpz_neg_uiui(f, th, tl); } else /* c2 is large */ { if (x == 0) fmpz_zero(f); else { /* Promote without val as if aliased both are large */ __mpz_struct *z = _fmpz_promote(f); mpz_mul_ui(z, COEFF_TO_PTR(c2), x); } } } void sample_new(void * arg, ulong count) { fmpz_t res, a; ulong b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); fmpz_init(res); fmpz_init(a); for (ix = 0; ix < count; ix++) { fmpz_randtest(a, state, bits + 20); b = n_randbits(state, bits); prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_mul_ui(res, a, b); prof_stop(); } flint_randclear(state); fmpz_clear(res); fmpz_clear(a); } void sample_old(void * arg, ulong count) { fmpz_t res, a; ulong b; ulong ix, jx; int bits = *((int *) arg); FLINT_TEST_INIT(state); fmpz_init(res); fmpz_init(a); for (ix = 0; ix < count; ix++) { fmpz_randtest(a, state, bits + 20); b = n_randbits(state, bits); prof_start(); for (jx = 0; jx < ntests; jx++) fmpz_mul_ui_old(res, a, b); prof_stop(); } flint_randclear(state); fmpz_clear(res); fmpz_clear(a); } int main(void) { double minnew, maxnew, minold, maxold; int bits; for (bits = 1; bits <= 64; bits += 3) { prof_repeat(&minnew, &maxnew, sample_new, &bits); prof_repeat(&minold, &maxold, sample_old, &bits); flint_printf("%d bits: min %.2fx, max %.2fx\n", bits, minold / minnew, maxold / maxnew); } return 0; } flint-3.1.3/src/fmpz/profile/p-xgcd.c000066400000000000000000000143641461254215100173740ustar00rootroot00000000000000/* Copyright 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "profiler.h" void sample_xgcd_small(void * arg, ulong count) { fmpz_t d, x, y, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(d); fmpz_init(x); fmpz_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, SMALL_FMPZ_BITCOUNT_MAX); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); fmpz_xgcd(d, x, y, a, b); } prof_stop(); fmpz_clear(d); fmpz_clear(x); fmpz_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_xgcd_mixed(void * arg, ulong count) { fmpz_t d, x, y, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(d); fmpz_init(x); fmpz_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, FLINT_BITS); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); fmpz_xgcd(d, x, y, a, b); } prof_stop(); fmpz_clear(d); fmpz_clear(x); fmpz_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_xgcd_big(void * arg, ulong count) { fmpz_t d, x, y, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(d); fmpz_init(x); fmpz_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, 512); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); fmpz_xgcd(d, x, y, a, b); } prof_stop(); fmpz_clear(d); fmpz_clear(x); fmpz_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_xgcd_canonical_bezout_small(void * arg, ulong count) { fmpz_t d, x, y, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(d); fmpz_init(x); fmpz_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, SMALL_FMPZ_BITCOUNT_MAX); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); fmpz_xgcd_canonical_bezout(d, x, y, a, b); } prof_stop(); fmpz_clear(d); fmpz_clear(x); fmpz_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_xgcd_canonical_bezout_mixed(void * arg, ulong count) { fmpz_t d, x, y, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(d); fmpz_init(x); fmpz_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, FLINT_BITS); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); fmpz_xgcd_canonical_bezout(d, x, y, a, b); } prof_stop(); fmpz_clear(d); fmpz_clear(x); fmpz_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } void sample_xgcd_canonical_bezout_big(void * arg, ulong count) { fmpz_t d, x, y, a, b; fmpz_t nmax; int ix; FLINT_TEST_INIT(state); fmpz_init(d); fmpz_init(x); fmpz_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(nmax); fmpz_set_d_2exp(nmax, 1.0, 512); prof_start(); for (ix = 0; ix < count; ix++) { fmpz_randm(a, state, nmax); fmpz_randm(b, state, nmax); fmpz_xgcd_canonical_bezout(d, x, y, a, b); } prof_stop(); fmpz_clear(d); fmpz_clear(x); fmpz_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nmax); flint_randclear(state); } int main(void) { double min, max; prof_repeat(&min, &max, sample_xgcd_small, NULL); flint_printf("fmpz_xgcd (small size):\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_xgcd_mixed, NULL); flint_printf("fmpz_xgcd (mixed size):\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_xgcd_big, NULL); flint_printf("fmpz_xgcd (big size):\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_xgcd_canonical_bezout_small, NULL); flint_printf("fmpz_xgcd_canonical_bezout (small size):\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_xgcd_canonical_bezout_mixed, NULL); flint_printf("fmpz_xgcd_canonical_bezout (mixed size):\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); prof_repeat(&min, &max, sample_xgcd_canonical_bezout_big, NULL); flint_printf("fmpz_xgcd_canonical_bezout (big size):\n" " min time is %.3f cycles\n" " max time is %.3f cycles\n\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); return 0; } flint-3.1.3/src/fmpz/rand.c000066400000000000000000000106371461254215100154750ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Authored 2015 by Daniel S. Roche; US Government work in the public domain. This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" void fmpz_randbits(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) { if (bits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_demote(f); *f = n_randbits(state, bits); if (n_randint(state, 2)) *f = -*f; } else { __mpz_struct *mf = _fmpz_promote(f); _flint_rand_init_gmp(state); mpz_urandomb(mf, state->gmp_state, bits); mpz_setbit(mf, bits - 1); if (n_randint(state, 2)) mpz_neg(mf, mf); _fmpz_demote_val(f); } } void fmpz_randm(fmpz_t f, flint_rand_t state, const fmpz_t m) { flint_bitcnt_t bits = fmpz_bits(m); int sgn = fmpz_sgn(m); if (bits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_demote(f); *f = (sgn >= 0) ? n_randint(state, *m) : - n_randint(state, -(*m)); } else { __mpz_struct * mf = _fmpz_promote(f); _flint_rand_init_gmp(state); mpz_urandomm(mf, state->gmp_state, COEFF_TO_PTR(*m)); if (sgn < 0) mpz_neg(mf, mf); _fmpz_demote_val(f); } } void fmpz_randprime(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits, int proved) { if (bits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_demote(f); *f = n_randprime(state, bits, proved); } else { /* Here I would like to just call * fmpz_randbits(f, state, bits); * but it has different semantics from n_randbits, * and in particular may return integers with fewer bits. */ __mpz_struct * mf = _fmpz_promote(f); _flint_rand_init_gmp(state); do { mpz_urandomb(mf, state->gmp_state, bits - 1); mpz_setbit(mf, bits - 1); fmpz_nextprime(f, f, proved); } while (fmpz_bits(f) != bits); } } void fmpz_randtest(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) { ulong m; fmpz_randtest_unsigned(f, state, bits); m = n_randlimb(state); if (m & UWORD(1)) fmpz_neg(f, f); } void fmpz_randtest_unsigned(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) { ulong m; m = n_randlimb(state); bits = n_randint(state, bits + 1); if (bits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_demote(f); if (m & UWORD(3)) *f = n_randtest_bits(state, bits); else { m >>= 2; if (bits == 0) *f = 0; else if (bits < SMALL_FMPZ_BITCOUNT_MAX) *f = m & UWORD(1); else *f = COEFF_MAX; } } else { __mpz_struct * mf = _fmpz_promote(f); _flint_rand_init_gmp(state); mpz_rrandomb(mf, state->gmp_state, bits); _fmpz_demote_val(f); } } void fmpz_randtest_not_zero(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) { if (bits == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_randtest_not_zero). bits == 0.\n"); } fmpz_randtest(f, state, bits); if (fmpz_is_zero(f)) fmpz_one(f); } void fmpz_randtest_mod(fmpz_t f, flint_rand_t state, const fmpz_t m) { fmpz_t t; fmpz_init(t); fmpz_randtest_unsigned(t, state, fmpz_bits(m) + 2); fmpz_mod(t, t, m); if (n_randlimb(state) & UWORD(1)) { fmpz_sub(t, m, t); fmpz_sub_ui(t, t, UWORD(1)); } fmpz_set(f, t); fmpz_clear(t); } void fmpz_randtest_mod_signed(fmpz_t f, flint_rand_t state, const fmpz_t m) { /* Randomly generate m/2 when included in the range */ if ((n_randlimb(state) % 32 == 1) && (fmpz_fdiv_ui(m, 2) == 0)) { fmpz_fdiv_q_ui(f, m, UWORD(2)); } else { fmpz_t t; fmpz_init(t); fmpz_tdiv_q_ui(t, m, UWORD(2)); fmpz_randtest_mod(t, state, t); if (n_randlimb(state) & UWORD(1)) { fmpz_neg(t, t); } fmpz_set(f, t); fmpz_clear(t); } } flint-3.1.3/src/fmpz/remove.c000066400000000000000000000056651461254215100160530ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "fmpz.h" #include "ulong_extras.h" slong _fmpz_remove(fmpz_t x, const fmpz_t f, double finv) { fmpz y = *x; fmpz q = *f; if (!COEFF_IS_MPZ(y)) /* x is small */ { if (!COEFF_IS_MPZ(q)) /* f is small */ { if (y > 0) { return n_remove2_precomp((mp_limb_t *) x, q, finv); } else { ulong z = - (ulong) y; slong e = n_remove2_precomp(&z, q, finv); if (e > 0) { *x = - (slong) z; } return e; } } else /* f is large */ { return 0; } } else /* x is large */ { __mpz_struct *z = COEFF_TO_PTR(y); if (!COEFF_IS_MPZ(q)) /* f is small */ { if (!flint_mpz_divisible_ui_p(z, q)) { return 0; } else { flint_mpz_divexact_ui(z, z, q); if (!flint_mpz_divisible_ui_p(z, q)) { _fmpz_demote_val(x); return 1; } else { mpz_t r; slong e; flint_mpz_divexact_ui(z, z, q); flint_mpz_init_set_ui(r, q); e = 2 + mpz_remove(z, z, r); mpz_clear(r); _fmpz_demote_val(x); return e; } } } else /* f is large */ { __mpz_struct *r = COEFF_TO_PTR(q); if (!mpz_divisible_p(z, r)) { return 0; } else { slong e; mpz_divexact(z, z, r); e = 1 + mpz_remove(z, z, r); _fmpz_demote_val(x); return e; } } } } slong fmpz_remove(fmpz_t rop, const fmpz_t op, const fmpz_t f) { double finv; if ((fmpz_sgn(f) <= 0) || fmpz_is_one(f)) { flint_throw(FLINT_ERROR, "Exception (fmpz_remove). factor f <= 1.\n"); } if (rop == f) { slong ans; fmpz_t t; fmpz_init(t); ans = fmpz_remove(t, op, f); fmpz_swap(rop, t); fmpz_clear(t); return ans; } finv = (!COEFF_IS_MPZ((*f))) ? n_precompute_inverse(*f) : 0; fmpz_set(rop, op); return _fmpz_remove(rop, f, finv); } flint-3.1.3/src/fmpz/rfac.c000066400000000000000000000055031461254215100154600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" static inline ulong rfac(ulong x, ulong b) { ulong i, c = x; for (i = 1; i < b; i++) c *= x + i; return c; } /* Assumes x positive, b > a. b must also be small enough to avoid integer overflow, which is no problem if the result is to fit in memory. */ void _fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong a, ulong b) { if (b - a == 1) { fmpz_add_ui(r, x, a); } else if ((*x <= COEFF_MAX) && (b - a < 60)) { ulong step, bits, factors_per_limb; ulong y = *x; /* Bound size of largest factor */ bits = FLINT_BIT_COUNT(y + a + b - 1); /* The result fits in a single limb */ if ((b - a) * bits < FLINT_BITS) step = factors_per_limb = b - a; else { factors_per_limb = FLINT_BITS / bits; step = FLINT_MIN(b - a, factors_per_limb); } fmpz_set_ui(r, rfac(y + a, step)); a += step; while (a < b) { step = FLINT_MIN(b - a, factors_per_limb); fmpz_mul_ui(r, r, rfac(y + a, step)); a += step; } } else { fmpz_t t, u; ulong m = (a + b) / 2; fmpz_init(t); fmpz_init(u); _fmpz_rfac_ui(t, x, a, m); _fmpz_rfac_ui(u, x, m, b); fmpz_mul(r, t, u); fmpz_clear(t); fmpz_clear(u); } } void fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong n) { if (n == 0) { fmpz_one(r); } else if (n == 1) { fmpz_set(r, x); } else if (fmpz_is_zero(x)) { fmpz_zero(r); } else if (fmpz_sgn(x) < 0) { fmpz_t t; fmpz_init(t); fmpz_add_ui(t, x, n - 1); if (fmpz_sgn(t) >= 0) { fmpz_zero(r); } else { fmpz_neg(t, t); fmpz_rfac_ui(r, t, n); if (n % 2 == 1) fmpz_neg(r, r); } fmpz_clear(t); } else { _fmpz_rfac_ui(r, x, 0, n); } } void fmpz_rfac_uiui(fmpz_t r, ulong x, ulong n) { if (n == 0) { fmpz_one(r); } else if (n == 1) { fmpz_set_ui(r, x); } else if (x == 0) { fmpz_zero(r); } else if (x <= COEFF_MAX) { _fmpz_rfac_ui(r, (fmpz *) &x, 0, n); } else { fmpz_t tmp; fmpz_init_set_ui(tmp, x); fmpz_rfac_ui(r, tmp, n); fmpz_clear(tmp); } } flint-3.1.3/src/fmpz/root.c000066400000000000000000000037611461254215100155340ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_root(fmpz_t r, const fmpz_t f, slong n) { fmpz c = *f; if (n <= 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_root). Unable to take %wd-th root.\n", n); } if (n == 1) { fmpz_set(r, f); return 1; } if (!COEFF_IS_MPZ(c)) /* f is small */ { mp_limb_t rem, root; int sgn = c < 0; if (n == 2) { if (sgn) { flint_throw(FLINT_ERROR, "Exception (fmpz_root). Unable to take square root of negative value.\n"); } root = n_sqrtrem(&rem, c); fmpz_set_ui(r, root); return rem == 0; } else if (n == 3) { if (sgn) c = -c; root = n_cbrtrem(&rem, c); fmpz_set_si(r, sgn ? -root : root); return rem == 0; } else /* n > 3 */ { if (sgn) { if ((n & 1) == 0) /* even root */ { flint_throw(FLINT_ERROR, "Exception (fmpz_root). Unable to take %wd-th root of negative value.\n", n); } else /* odd */ c = -c; } root = n_rootrem(&rem, c, n); fmpz_set_si(r, sgn ? -root : root); return rem == 0; } } else /* f is large */ { __mpz_struct * mpz2 = COEFF_TO_PTR(c); __mpz_struct * mpz1 = _fmpz_promote(r); int exact = mpz_root(mpz1, mpz2, n); _fmpz_demote_val(r); /* root may be small */ return exact; } } flint-3.1.3/src/fmpz/set.c000066400000000000000000000124501461254215100153370ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart Copyright (C) 2011, 2017 Fredrik Johansson Copyright (C) 2014 Abhinav Baid Copyright (C) 2018, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "double_extras.h" #include "gmpcompat.h" #include "fmpz.h" void fmpz_set(fmpz_t f, const fmpz_t g) { if (f == g) return; /* aliased inputs */ if (!COEFF_IS_MPZ(*g)) /* g is small */ { _fmpz_demote(f); *f = *g; } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); mpz_set(mf, COEFF_TO_PTR(*g)); } } #if FLINT64 /* 2^53 */ #define DOUBLE_MAX 9007199254740992.0 #define DOUBLE_MIN -9007199254740992.0 #else #define DOUBLE_MAX COEFF_MAX #define DOUBLE_MIN COEFF_MIN #endif void fmpz_set_d(fmpz_t f, double c) { if (c >= DOUBLE_MIN && c <= DOUBLE_MAX) { _fmpz_demote(f); /* guaranteed to fit, since c gets truncated */ *f = (slong) c; } else { __mpz_struct * z = _fmpz_promote(f); mpz_set_d(z, c); _fmpz_demote_val(f); } } void fmpz_set_d_2exp(fmpz_t f, double m, slong exp) { int exp2; m = frexp(m, &exp2); exp += exp2; if (exp >= 53) { fmpz_set_d(f, m * ldexp(1.0, 53)); fmpz_mul_2exp(f, f, exp - 53); } else if (exp < 0) fmpz_set_ui(f, 0); else fmpz_set_d(f, d_mul_2exp_inrange(m, exp)); } void fmpz_set_mpf(fmpz_t f, const mpf_t x) { int check; check = flint_mpf_fits_slong_p(x); if (check) { slong cx = flint_mpf_get_si(x); fmpz_set_si(f, cx); } else { __mpz_struct *z = _fmpz_promote(f); mpz_set_f(z, x); } } void fmpz_set_mpz(fmpz_t f, const mpz_t x) { int size = (slong) x->_mp_size; if (size == 0) /* x is zero */ { fmpz_zero(f); } else if (size == 1) /* x is positive and 1 limb */ { fmpz_set_ui(f, flint_mpz_get_ui(x)); } else if (size == -1) /* x is negative and 1 limb */ { ulong uval = flint_mpz_get_ui(x); if (uval <= COEFF_MAX) /* x is small */ { _fmpz_demote(f); *f = -uval; } else /* x is large but one limb */ { __mpz_struct * mf = _fmpz_promote(f); flint_mpz_set_ui(mf, uval); mpz_neg(mf, mf); } } else /* x is more than one limb */ { __mpz_struct * mf = _fmpz_promote(f); mpz_set(mf, x); } } /* Given an array of limbs "c" representing a integer mod 2^(FLINT_BITS*n), set "f" to the symmetric remainder with the halfway point 2^(FLINT_BITS*n/2) mapping to -2^(FLINT_BITS*n/2) */ void fmpz_set_signed_ui_array(fmpz_t f, const ulong * c, slong n) { ulong csign; FLINT_ASSERT(n > 0); csign = FLINT_SIGN_EXT(c[n - 1]); while (n > 0 && c[n - 1] == csign) n--; if (n < 2) { if (csign == 0) fmpz_set_ui(f, c[0]); else if (c[0] != 0) fmpz_neg_ui(f, -c[0]); else fmpz_neg_uiui(f, 1, 0); } else { __mpz_struct * z = _fmpz_promote(f); mp_limb_t * zd = FLINT_MPZ_REALLOC(z, n); if (csign == 0) { flint_mpn_copyi(zd, c, n); z->_mp_size = n; } else { if (mpn_neg(zd, c, n)) { FLINT_ASSERT(zd[n - 1] != 0); z->_mp_size = -n; } else { zd = FLINT_MPZ_REALLOC(z, n + 1); zd[n] = 1; z->_mp_size = -(n + 1); } } } } void fmpz_set_signed_uiuiui(fmpz_t r, ulong hi, ulong mid, ulong lo) { int negate = 0; if ((slong) hi < 0) { hi = -hi - ((lo != 0) || (mid != 0)); mid = -mid - (lo != 0); lo = -lo; negate = 1; } if (hi == 0) { if (negate) fmpz_neg_uiui(r, mid, lo); else fmpz_set_uiui(r, mid, lo); } else { __mpz_struct * z = _fmpz_promote(r); if (z->_mp_alloc < 3) mpz_realloc2(z, 3 * FLINT_BITS); z->_mp_d[0] = lo; z->_mp_d[1] = mid; z->_mp_d[2] = hi; z->_mp_size = negate ? -3 : 3; } } /* Given an array of limbs "in" representing a non negative integer, set "out" to this integer. */ void fmpz_set_ui_array(fmpz_t out, const ulong * in, slong in_len) { slong size = in_len; FLINT_ASSERT(in_len > 0); /* find end of zero extension */ while (size > WORD(1) && in[size - 1] == UWORD(0)) size--; /* copy limbs */ if (size == WORD(1)) { fmpz_set_ui(out, in[0]); } else { __mpz_struct * mpz = _fmpz_promote(out); if (mpz->_mp_alloc < size) mpz_realloc2(mpz, FLINT_BITS * size); mpz->_mp_size = size; flint_mpn_copyi(mpz->_mp_d, in, size); } } flint-3.1.3/src/fmpz/set_str.c000066400000000000000000000147121461254215100162320ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fmpz_vec.h" #include "thread_support.h" #include "thread_pool.h" #include "profiler.h" #define BASECASE_CUTOFF 24000 /* lower bounds */ #if FLINT_BITS == 64 #define DIGITS_PER_LIMB 19 #else #define DIGITS_PER_LIMB 9 #endif /* todo: the binary splitting code is almost the same as that for get_str and could be reused */ typedef struct { fmpz * res; const char * s; slong slen; const slong * exps; slong cur_depth; slong depth; const fmpz * pows; const fmpz_preinvn_struct * preinv; } worker_args_struct; static void _fmpz_get_str_recursive(fmpz_t res, const char * s, slong slen, const slong * exps, slong cur_depth, slong depth, const fmpz * pows); static void worker(void * arg) { worker_args_struct * X = (worker_args_struct * ) arg; _fmpz_get_str_recursive(X->res, X->s, X->slen, X->exps, X->cur_depth, X->depth, X->pows); } static void _fmpz_set_str_basecase(fmpz_t res, const char * s, slong slen) { mp_ptr tmp; unsigned char * stmp; mp_size_t n; slong i; TMP_INIT; TMP_START; stmp = TMP_ALLOC(sizeof(char) * slen); tmp = TMP_ALLOC(sizeof(mp_limb_t) * (slen / DIGITS_PER_LIMB + 2)); for (i = 0; i < slen; i++) stmp[i] = s[i] - '0'; n = mpn_set_str(tmp, stmp, slen, 10); if (n == 0) fmpz_zero(res); else fmpz_set_ui_array(res, tmp, n); TMP_END; } static void _fmpz_get_str_recursive(fmpz_t res, const char * s, slong slen, const slong * exps, slong cur_depth, slong depth, const fmpz * pows) { if (cur_depth >= depth || slen < BASECASE_CUTOFF) { _fmpz_set_str_basecase(res, s, slen); } else { fmpz_t q, r; slong num_right = exps[cur_depth]; slong nworkers, nthreads, nworkers_save; int want_workers; thread_pool_handle * threads; worker_args_struct high_digits[1], low_digits[1]; fmpz_init(q); fmpz_init(r); /* _fmpz_get_str_recursive(r, s + slen - num_right, num_right, exps, cur_depth + 1, depth, pows); _fmpz_get_str_recursive(q, s, slen - num_right, exps, cur_depth + 1, depth, pows); fmpz_mul(res, q, pows + cur_depth); fmpz_mul_2exp(res, res, exps[cur_depth]); fmpz_add(res, res, r); */ low_digits->res = r; low_digits->s = s + slen - num_right; low_digits->slen = num_right; low_digits->exps = exps; low_digits->cur_depth = cur_depth + 1; low_digits->depth = depth; low_digits->pows = pows; high_digits->res = q; high_digits->s = s; high_digits->slen = slen - num_right; high_digits->exps = exps; high_digits->cur_depth = cur_depth + 1; high_digits->depth = depth; high_digits->pows = pows; nthreads = flint_get_num_threads(); /* Prefer to let the multithreaded multiplication do its things near the root. */ want_workers = nthreads >= 2 && (num_right <= 100000000 || cur_depth >= 2); nworkers = flint_request_threads(&threads, want_workers ? 2 : 1); if (nworkers == 1) { nworkers_save = flint_set_num_workers(nthreads - nthreads / 2 - 1); thread_pool_wake(global_thread_pool, threads[0], nthreads / 2 - 1, worker, low_digits); worker(high_digits); flint_reset_num_workers(nworkers_save); thread_pool_wait(global_thread_pool, threads[0]); } else { worker(low_digits); worker(high_digits); } flint_give_back_threads(threads, nworkers); fmpz_mul(res, q, pows + cur_depth); fmpz_mul_2exp(res, res, exps[cur_depth]); fmpz_add(res, res, r); fmpz_clear(q); fmpz_clear(r); } } void fmpz_set_str_bsplit_threaded(fmpz_t res, const char * s, slong slen) { slong k, depth; slong exps[FLINT_BITS]; fmpz * pows; exps[0] = (slen + 1) / 2; depth = 1; while (exps[depth - 1] > BASECASE_CUTOFF / DIGITS_PER_LIMB) { exps[depth] = (exps[depth - 1] + 1) / 2; depth++; } pows = _fmpz_vec_init(depth); fmpz_ui_pow_ui(pows + depth - 1, 5, exps[depth - 1]); for (k = depth - 2; k >= 0; k--) { fmpz_mul(pows + k, pows + k + 1, pows + k + 1); if (exps[k] != 2 * exps[k + 1]) fmpz_divexact_ui(pows + k, pows + k, 5); } _fmpz_get_str_recursive(res, s, slen, exps, 0, depth, pows); _fmpz_vec_clear(pows, depth); } static int fmpz_set_str_fallback(fmpz_t res, const char * str, int b, int neg) { int err; __mpz_struct * z = _fmpz_promote(res); err = mpz_set_str(z, str, b); if (neg) mpz_neg(z, z); _fmpz_demote_val(res); return err; } int fmpz_set_str(fmpz_t res, const char * str, int base) { slong slen, i; int neg = 0; /* Let GMP handle unusual bases. */ if (base != 10) return fmpz_set_str_fallback(res, str, base, 0); /* Allow leading whitespace. */ while (isspace(str[0])) str++; if (str[0] == '-') { str++; neg = 1; } slen = strlen(str); /* Allow trailing whitespace. */ while (slen > 0 && isspace(str[slen - 1])) slen--; if (slen == 0) return -1; for (i = 0; i < slen; i++) { /* The string is either invalid or has interior whitespace, which GMP allows. Either way, let GMP handle it. */ if (((unsigned int) (str[i] - '0')) > 9) return fmpz_set_str_fallback(res, str, base, neg); } if (slen <= DIGITS_PER_LIMB) { ulong c = str[0] - '0'; for (i = 1; i < slen; i++) c = c * 10 + (ulong) (str[i] - '0'); if (neg) fmpz_neg_ui(res, c); else fmpz_set_ui(res, c); } else { if (slen < BASECASE_CUTOFF) _fmpz_set_str_basecase(res, str, slen); else fmpz_set_str_bsplit_threaded(res, str, slen); if (neg) fmpz_neg(res, res); } return 0; } flint-3.1.3/src/fmpz/setbit.c000066400000000000000000000015741461254215100160430ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" void fmpz_setbit(fmpz_t f, ulong i) { if (!COEFF_IS_MPZ(*f)) { if (i < SMALL_FMPZ_BITCOUNT_MAX) { *f |= (WORD(1) << i); } else /* i >= SMALL_FMPZ_BITCOUNT_MAX */ { __mpz_struct *ptr = _fmpz_promote_val(f); mpz_setbit(ptr, i); _fmpz_demote_val(f); } } else { __mpz_struct *ptr = COEFF_TO_PTR(*f); mpz_setbit(ptr, i); _fmpz_demote_val(f); } } flint-3.1.3/src/fmpz/sgn.c000066400000000000000000000012321461254215100153270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_sgn(const fmpz_t f) { fmpz d = *f; if (d == 0) return 0; if (!COEFF_IS_MPZ(d)) /* c1 is small */ return (d > WORD(0) ? 1 : -1); else return mpz_sgn(COEFF_TO_PTR(d)); } flint-3.1.3/src/fmpz/size.c000066400000000000000000000011651461254215100155170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" mp_size_t fmpz_size(const fmpz_t f) { fmpz d = *f; if (d == 0) return 0; if (!COEFF_IS_MPZ(d)) return 1; else return mpz_size(COEFF_TO_PTR(d)); } flint-3.1.3/src/fmpz/sizeinbase.c000066400000000000000000000012021461254215100166710ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "long_extras.h" size_t fmpz_sizeinbase(const fmpz_t f, int b) { fmpz d = *f; if (!COEFF_IS_MPZ(d)) return z_sizeinbase(d, b); else return mpz_sizeinbase(COEFF_TO_PTR(d), b); } flint-3.1.3/src/fmpz/smod.c000066400000000000000000000043541461254215100155120ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2014 Abhinav Baid Copyright (C) 2021 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" /* r = a mod m with various options for the range of r */ void _fmpz_smod( fmpz_t r, const fmpz_t a, const fmpz_t m, int sign, /* -1: |r| < |m| & sgn(r) = sgn(a) or r == 0 0: |r| < |m| & sgn(r) = sgn(m) or r == 0 1: -|m| < 2r <= |m| */ fmpz_t t) /* temp not aliased with anything else */ { if (sign < 0) { if (fmpz_cmpabs(m, a) > 0) fmpz_set(r, a); else fmpz_tdiv_qr(t, r, a, m); } else if (sign > 0) { int cmp = fmpz_cmp2abs(m, a); if (cmp >= 0) { if (cmp == 0) fmpz_abs(r, a); else fmpz_set(r, a); } else if (m != r) { fmpz_fdiv_qr(t, r, a, m); /* r is zero or has same sign as m */ cmp = fmpz_cmp2abs(m, r); if (cmp == 0) fmpz_abs(r, r); else if (cmp < 0) fmpz_sub(r, r, m); } else { fmpz_set(t, m); fmpz_fdiv_r(r, a, t); cmp = fmpz_cmp2abs(t, r); if (cmp == 0) fmpz_abs(r, r); else if (cmp < 0) fmpz_sub(r, r, t); } } else { fmpz_fdiv_qr(t, r, a, m); } } void fmpz_smod(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c2 = *h; if (!COEFF_IS_MPZ(c2)) /* h is small */ { ulong tmp; tmp = FLINT_ABS(c2); fmpz_mod(f, g, h); if (fmpz_cmp_ui(f, tmp / 2) > 0) { fmpz_sub_ui(f, f, tmp); } } else /* h is large */ { fmpz_t tmp; fmpz_init(tmp); _fmpz_smod(f, g, h, 1, tmp); fmpz_clear(tmp); } } flint-3.1.3/src/fmpz/sqrt.c000066400000000000000000000014471461254215100155410ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_sqrt(fmpz_t f, const fmpz_t g) { if (fmpz_sgn(g) < 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_sqrt). g is negative.\n"); } if (!COEFF_IS_MPZ(*g)) fmpz_set_ui(f, n_sqrt(*g)); else { __mpz_struct * mf = _fmpz_promote(f); mpz_sqrt(mf, COEFF_TO_PTR(*g)); _fmpz_demote_val(f); } } flint-3.1.3/src/fmpz/sqrtmod.c000066400000000000000000000103201461254215100162270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "fmpz.h" #include "ulong_extras.h" /* Assumes that p is an odd prime, and that 0 <= a < p. Returns 1 if a is a quadratic residue and 0 otherwise. Does not support aliasing. */ static int _fmpz_sqrtmod(mpz_t rop, const mpz_t a, const mpz_t p) { slong i, r, m, iter; mpz_t p1, k, exp, b, g, bpow, gpow; if (mpz_jacobi(a, p) == -1) return 0; if (flint_mpz_congruent_ui_p(p, 3, 4)) { mpz_init(exp); flint_mpz_add_ui(exp, p, 1); mpz_tdiv_q_2exp(exp, exp, 2); mpz_powm(rop, a, exp, p); mpz_clear(exp); return 1; } if (flint_mpz_congruent_ui_p(p, 5, 8)) { mpz_init(exp); mpz_init(g); mpz_init(k); flint_mpz_add_ui(exp, p, 3); mpz_tdiv_q_2exp(exp, exp, 3); mpz_powm(rop, a, exp, p); mpz_set_ui(k, 2); mpz_powm(g, rop, k, p); if (mpz_cmp(g, a) == 0) { mpz_clear(exp); mpz_clear(g); mpz_clear(k); return 1; } flint_mpz_sub_ui(exp, p, 1); mpz_tdiv_q_2exp(exp, exp, 2); mpz_powm(g, k, exp, p); mpz_mul(rop, rop, g); mpz_mod(rop, rop, p); mpz_clear(exp); mpz_clear(g); mpz_clear(k); return 1; } mpz_init(p1); mpz_init(k); mpz_init(exp); mpz_init(b); mpz_init(g); mpz_init(bpow); mpz_init(gpow); r = 0; flint_mpz_sub_ui(p1, p, 1); do { mpz_tdiv_q_2exp(p1, p1, 1); r++; } while (mpz_even_p(p1)); mpz_powm(b, a, p1, p); for (flint_mpz_set_ui(k, 3); ; flint_mpz_add_ui(k, k, 2)) /* 2 is a quadratic residue mod p = 8k + 1 */ { if (mpz_jacobi(k, p) == -1) break; } mpz_powm(g, k, p1, p); flint_mpz_add_ui(exp, p1, 1); mpz_tdiv_q_2exp(exp, exp, 1); mpz_powm(rop, a, exp, p); iter = r - 1; /* maximum number of iterations if p is prime */ while (flint_mpz_cmp_ui(b, 1)) { mpz_set(bpow, b); m = 0; do { mpz_mul(bpow, bpow, bpow); mpz_mod(bpow, bpow, p); m++; } while (m < r && flint_mpz_cmp_ui(bpow, 1)); mpz_set(gpow, g); for (i = 1; i < r - m; i++) { mpz_mul(gpow, gpow, gpow); mpz_mod(gpow, gpow, p); } mpz_mul(rop, rop, gpow); mpz_mod(rop, rop, p); mpz_mul(g, gpow, gpow); mpz_mod(g, g, p); mpz_mul(b, b, g); mpz_mod(b, b, p); r = m; if (iter-- == 0) /* too many iterations, p is not prime */ { mpz_set_ui(rop, 0); break; } } mpz_clear(p1); mpz_clear(k); mpz_clear(exp); mpz_clear(b); mpz_clear(g); mpz_clear(bpow); mpz_clear(gpow); return mpz_sgn(rop) ? 1 : 0; } int fmpz_sqrtmod(fmpz_t b, const fmpz_t a, const fmpz_t p) { if (b == a || b == p) { int ans; fmpz_t t; fmpz_init(t); ans = fmpz_sqrtmod(t, a, p); fmpz_swap(b, t); fmpz_clear(t); return ans; } fmpz_mod(b, a, p); if (fmpz_cmp_ui(b, 1) <= 0) { return 1; } if (!COEFF_IS_MPZ(*p)) /* p, and b are small */ { mp_limb_t ans; ans = n_sqrtmod(*b, *p); if (ans) fmpz_set_ui(b, ans); return ans != 0; } else /* p is large */ { int ans; mpz_t t; __mpz_struct *bptr; if (fmpz_is_even(p)) return 0; if (fmpz_is_square(p)) return 0; bptr = _fmpz_promote_val(b); mpz_init(t); ans = _fmpz_sqrtmod(t, bptr, COEFF_TO_PTR(*p)); mpz_swap(bptr, t); mpz_clear(t); _fmpz_demote_val(b); return ans; } } flint-3.1.3/src/fmpz/sqrtrem.c000066400000000000000000000021351461254215100162400ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_sqrtrem(fmpz_t f, fmpz_t r, const fmpz_t g) { if (fmpz_sgn(g) < 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_sqrtrem). g is negative.\n"); } if (!COEFF_IS_MPZ(*g)) { if (COEFF_IS_MPZ(*r)) _fmpz_clear_mpz(*r); fmpz_set_ui(f, n_sqrtrem((mp_limb_t *) r, *g)); } else { __mpz_struct * r_mpz_ptr, * f_mpz_ptr; _fmpz_promote(f); /* must not hang on to pointer whilst promoting */ r_mpz_ptr = _fmpz_promote(r); f_mpz_ptr = COEFF_TO_PTR(*f); mpz_sqrtrem(f_mpz_ptr, r_mpz_ptr, COEFF_TO_PTR(*g)); _fmpz_demote_val(f); _fmpz_demote_val(r); } } flint-3.1.3/src/fmpz/sub.c000066400000000000000000000037761461254215100153500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_sub(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* both inputs are small */ { fmpz_set_si(f, c1 - c2); } else /* g is small, h is large */ { __mpz_struct *mpz3 = _fmpz_promote(f); /* g is saved and h is large */ __mpz_struct *mpz2 = COEFF_TO_PTR(c2); if (c1 < WORD(0)) { flint_mpz_add_ui(mpz3, mpz2, -c1); mpz_neg(mpz3, mpz3); } else flint_mpz_ui_sub(mpz3, c1, mpz2); _fmpz_demote_val(f); /* may have cancelled */ } } else { if (!COEFF_IS_MPZ(c2)) /* g is large, h is small */ { __mpz_struct *mpz3 = _fmpz_promote(f); /* h is saved and g is large */ __mpz_struct *mpz1 = COEFF_TO_PTR(c1); if (c2 < WORD(0)) flint_mpz_add_ui(mpz3, mpz1, -c2); else flint_mpz_sub_ui(mpz3, mpz1, c2); _fmpz_demote_val(f); /* may have cancelled */ } else /* g and h are large */ { __mpz_struct *mpz3 = _fmpz_promote(f); /* aliasing means f is already large */ __mpz_struct *mpz1 = COEFF_TO_PTR(c1); __mpz_struct *mpz2 = COEFF_TO_PTR(c2); mpz_sub(mpz3, mpz1, mpz2); _fmpz_demote_val(f); /* may have cancelled */ } } } flint-3.1.3/src/fmpz/submul.c000066400000000000000000000077211461254215100160600ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2021 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" /* defined in addmul.c */ void _flint_mpz_addmul_large(mpz_ptr z, mpz_srcptr x, mpz_srcptr y, int negate); void fmpz_submul(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1, c2, c3; __mpz_struct * mf; c1 = *g; c2 = *h; c3 = *f; /* todo: are the zero checks worth it for small input? */ if (c1 == 0 || c2 == 0) return; if (c3 == 0) { fmpz_mul(f, g, h); fmpz_neg(f, f); return; } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* both are small */ { ulong p1, p0; smul_ppmm(p1, p0, -c1, c2); if (!COEFF_IS_MPZ(c3)) { ulong F1 = FLINT_SIGN_EXT(c3); add_ssaaaa(p1, p0, p1, p0, F1, c3); fmpz_set_signed_uiui(f, p1, p0); } else { mpz_ptr pF = COEFF_TO_PTR(c3); flint_mpz_add_signed_uiui(pF, pF, p1, p0); _fmpz_demote_val(f); /* cancellation may have occurred */ } } else { fmpz_addmul_si(f, h, -c1); } } else if (!COEFF_IS_MPZ(c2)) /* h is small */ { fmpz_addmul_si(f, g, -c2); } else { mf = _fmpz_promote_val(f); _flint_mpz_addmul_large(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2), 1); _fmpz_demote_val(f); /* cancellation may have occurred */ } } void fmpz_submul_si(fmpz_t f, const fmpz_t g, slong x) { fmpz F, G; G = *g; if (x == 0 || G == 0) return; F = *f; if (F == 0) { fmpz_mul_si(f, g, x); fmpz_neg(f, f); return; } if (!COEFF_IS_MPZ(G)) { ulong p1, p0; smul_ppmm(p1, p0, G, x); if (!COEFF_IS_MPZ(F)) { ulong F1 = FLINT_SIGN_EXT(F); sub_ddmmss(p1, p0, F1, F, p1, p0); fmpz_set_signed_uiui(f, p1, p0); } else { mpz_ptr pF = COEFF_TO_PTR(F); sub_ddmmss(p1, p0, UWORD(0), UWORD(0), p1, p0); flint_mpz_add_signed_uiui(pF, pF, p1, p0); _fmpz_demote_val(f); } } else { mpz_ptr pG = COEFF_TO_PTR(G); mpz_ptr pF = _fmpz_promote_val(f); if (x < 0) flint_mpz_addmul_ui(pF, pG, -x); else flint_mpz_submul_ui(pF, pG, x); _fmpz_demote_val(f); } } void fmpz_submul_ui(fmpz_t f, const fmpz_t g, ulong x) { fmpz F, G; G = *g; if (x == 0 || G == 0) return; F = *f; if (F == 0) { fmpz_mul_ui(f, g, x); fmpz_neg(f, f); return; } if (!COEFF_IS_MPZ(G)) { ulong p1, p0; if (x <= WORD_MAX) { smul_ppmm(p1, p0, -G, x); } else { umul_ppmm(p1, p0, FLINT_ABS(G), x); if (G > 0) { p1 = -p1 - (p0 != 0); p0 = -p0; } } if (!COEFF_IS_MPZ(F)) { ulong F1 = FLINT_SIGN_EXT(F); add_ssaaaa(p1, p0, p1, p0, F1, F); fmpz_set_signed_uiui(f, p1, p0); } else { mpz_ptr pF = COEFF_TO_PTR(F); flint_mpz_add_signed_uiui(pF, pF, p1, p0); _fmpz_demote_val(f); } } else { mpz_ptr pG = COEFF_TO_PTR(G); mpz_ptr pF = _fmpz_promote_val(f); flint_mpz_submul_ui(pF, pG, x); _fmpz_demote_val(f); } } flint-3.1.3/src/fmpz/tdiv.c000066400000000000000000000162361461254215100155200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz.h" void fmpz_tdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) { fmpz d = *g; if (!COEFF_IS_MPZ(d)) /* g is small */ { if (d >= 0) d = d >> FLINT_MIN(exp, SMALL_FMPZ_BITCOUNT_MAX); else d = -((-d) >> FLINT_MIN(exp, SMALL_FMPZ_BITCOUNT_MAX)); fmpz_set_si(f, d); } else /*g is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ mpz_tdiv_q_2exp(mf, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } void fmpz_tdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception (fmpz_tdiv_q). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ fmpz_set_si(f, c1 / c2); else /* h is large */ fmpz_zero(f); } else /* g is large */ { __mpz_struct * mf; if (!COEFF_IS_MPZ(c2)) /* h is small */ { mf = _fmpz_promote(f); if (c2 > 0) /* h > 0 */ { flint_mpz_tdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_tdiv_q_ui(mf, COEFF_TO_PTR(c1), -c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_tdiv_q_newton(f, g, h); } else { mf = _fmpz_promote(f); mpz_tdiv_q(mf, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ } } } } void fmpz_tdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_throw(FLINT_ERROR, "Exception: division by zero in fmpz_tdiv_qr\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ fmpz_set_si(f, q); fmpz_set_si(s, r); } else /* h is large and g is small */ { fmpz_set_ui(f, WORD(0)); /* g is zero */ fmpz_set_si(s, c1); } } else /* g is large */ { __mpz_struct * mf, * ms; if (!COEFF_IS_MPZ(c2)) /* h is small */ { _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ ms = _fmpz_promote(s); mf = COEFF_TO_PTR(*f); if (c2 > 0) /* h > 0 */ { flint_mpz_tdiv_qr_ui(mf, ms, COEFF_TO_PTR(c1), c2); } else { flint_mpz_tdiv_qr_ui(mf, ms, COEFF_TO_PTR(c1), -c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } else /* both are large */ { if (MPZ_WANT_FLINT_DIVISION(COEFF_TO_PTR(c1), COEFF_TO_PTR(c2))) { _fmpz_tdiv_qr_newton(f, s, g, h); } else { _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ ms = _fmpz_promote(s); mf = COEFF_TO_PTR(*f); mpz_tdiv_qr(mf, ms, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } } } } void fmpz_tdiv_q_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; slong c2 = h; if (h == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_tdiv_q_si). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_set_si(f, c1 / c2); } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); if (c2 > 0) { flint_mpz_tdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); } else { flint_mpz_tdiv_q_ui(mf, COEFF_TO_PTR(c1), -(ulong) c2); mpz_neg(mf, mf); } _fmpz_demote_val(f); /* division by h may result in small value */ } } void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; ulong c2 = h; if (h == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_tdiv_q_ui). Division by zero.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 > 0) { fmpz_set_ui(f, c1 / c2); } else { ulong q = ((ulong) -c1) / c2; fmpz_set_si(f, - (slong) q); } } else /* g is large */ { __mpz_struct * mf = _fmpz_promote(f); flint_mpz_tdiv_q_ui(mf, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } } void fmpz_tdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp) { fmpz d = *g; if (!COEFF_IS_MPZ(d)) /* g is small */ { if (d >= 0) { fmpz_set_ui(f, exp < (SMALL_FMPZ_BITCOUNT_MAX) ? d & ((WORD(1) << exp) - 1) : d); } else { d = -d; fmpz_neg_ui(f, exp < (SMALL_FMPZ_BITCOUNT_MAX) ? d & ((WORD(1) << exp) - 1) : d); } } else /*g is large */ { __mpz_struct * mf = _fmpz_promote(f); /* g is already large */ mpz_tdiv_r_2exp(mf, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } ulong fmpz_tdiv_ui(const fmpz_t g, ulong h) { fmpz c1 = *g; if (h == UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_tdiv_ui). Division by 0.\n"); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { /* We need the absolute value of the remainder and C 90 guarantees truncation towards zero. */ if (c1 < WORD(0)) return -c1 % h; else return c1 % h; } else /* g is large */ { return flint_mpz_tdiv_ui(COEFF_TO_PTR(c1), h); } } flint-3.1.3/src/fmpz/test/000077500000000000000000000000001461254215100153555ustar00rootroot00000000000000flint-3.1.3/src/fmpz/test/main.c000066400000000000000000000246271461254215100164600ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Try to get fdopen declared for fmpz_[print/read] */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #include #include #include #include /* Include functions *********************************************************/ #include "t-abs.c" #include "t-abs_fits_ui.c" #include "t-abs_lbound_ui_2exp.c" #include "t-abs_ubound_ui_2exp.c" #include "t-add.c" #include "t-addmul.c" #include "t-addmul_si.c" #include "t-addmul_ui.c" #include "t-and.c" #include "t-aors_ui.c" #include "t-bin_uiui.c" #include "t-bit_pack.c" #include "t-bits.c" #include "t-cdiv_q_2exp.c" #include "t-cdiv_q.c" #include "t-cdiv_qr.c" #include "t-cdiv_q_si.c" #include "t-cdiv_q_ui.c" #include "t-cdiv_r_2exp.c" #include "t-cdiv_ui.c" #include "t-clog.c" #include "t-clog_ui.c" #include "t-cmp2abs.c" #include "t-cmpabs.c" #include "t-cmp.c" #include "t-cmp_si.c" #include "t-cmp_ui.c" #include "t-comb_init_clear.c" #include "t-combit.c" #include "t-complement.c" #include "t-crt.c" #include "t-crt_ui.c" #include "t-divexact2_uiui.c" #include "t-divexact.c" #include "t-divexact_si.c" #include "t-divexact_ui.c" #include "t-divides.c" #include "t-divides_mod_list.c" #include "t-divisible.c" #include "t-divisible_si.c" #include "t-divisor_in_residue_class_lenstra.c" #include "t-divisor_sigma.c" #include "t-div_newton.c" #include "t-dlog.c" #include "t-equal.c" #include "t-equal_si.c" #include "t-equal_ui.c" #include "t-euler_phi.c" #include "t-fac_ui.c" #include "t-fdiv_q_2exp.c" #include "t-fdiv_q.c" #include "t-fdiv_qr.c" #include "t-fdiv_qr_preinvn.c" #include "t-fdiv_q_si.c" #include "t-fdiv_q_ui.c" #include "t-fdiv_r_2exp.c" #include "t-fdiv_r.c" #include "t-fdiv_ui.c" #include "t-fib_ui.c" #include "t-fits_si.c" #include "t-flog.c" #include "t-flog_ui.c" #include "t-fmma.c" #include "t-fmms.c" #include "t-fmpz.c" #include "t-fmpz_cleanup.c" #include "t-fmpz_stress.c" #include "t-gcd3.c" #include "t-gcd.c" #include "t-gcdinv.c" #include "t-gcd_ui.c" #include "t-get_d_2exp.c" #include "t-get_d.c" #include "t-get_mpf.c" #include "t-get_mpfr.c" #include "t-get_mpn.c" #include "t-get_mpz.c" #include "t-get_nmod.c" #include "t-get_set_ui_array.c" #include "t-get_si.c" #include "t-get_str.c" #include "t-get_ui.c" #include "t-init2.c" #include "t-init_set.c" #include "t-init_set_readonly.c" #include "t-init_set_ui.c" #include "t-invmod.c" #include "t-is_even.c" #include "t-is_perfect_power.c" #include "t-is_prime.c" #include "t-is_prime_morrison.c" #include "t-is_prime_pocklington.c" #include "t-is_prime_pseudosquare.c" #include "t-is_probabprime_BPSW.c" #include "t-is_probabprime_lucas.c" #include "t-is_square.c" #include "t-is_strong_probabprime.c" #include "t-jacobi.c" #include "t-kronecker.c" #include "t-lcm.c" #include "t-mod.c" #include "t-mod_ui.c" #include "t-moebius_mu.c" #include "t-mpz_init_set_readonly.c" #include "t-mul_2exp.c" #include "t-mul2_uiui.c" #include "t-mul.c" #include "t-mul_si.c" #include "t-mul_si_tdiv_q_2exp.c" #include "t-mul_tdiv_q_2exp.c" #include "t-multi_CRT_multi_mod.c" #include "t-multi_CRT_ui.c" #include "t-mul_ui.c" #include "t-ndiv_qr.c" #include "t-neg.c" #include "t-neg_ui.c" #include "t-neg_uiui.c" #include "t-nextprime.c" #include "t-or.c" #include "t-out_inp_raw.c" #include "t-popcnt.c" #include "t-powm.c" #include "t-powm_ui.c" #include "t-pow_ui.c" #include "t-primorial.c" #include "t-print_read.c" #include "t-randprime.c" #include "t-remove.c" #include "t-rfac_ui.c" #include "t-rfac_uiui.c" #include "t-root.c" #include "t-setbit.c" #include "t-set.c" #include "t-set_d_2exp.c" #include "t-set_signed_ui_array.c" #include "t-set_signed_uiui.c" #include "t-set_signed_uiuiui.c" #include "t-set_str.c" #include "t-set_ui_smod.c" #include "t-set_uiui.c" #include "t-sgn.c" #include "t-size.c" #include "t-sizeinbase.c" #include "t-smod.c" #include "t-sqrt.c" #include "t-sqrtmod.c" #include "t-sqrtrem.c" #include "t-sub.c" #include "t-submul.c" #include "t-submul_si.c" #include "t-submul_ui.c" #include "t-swap.c" #include "t-tdiv_q_2exp.c" #include "t-tdiv_q.c" #include "t-tdiv_qr.c" #include "t-tdiv_q_si.c" #include "t-tdiv_q_ui.c" #include "t-tdiv_r_2exp.c" #include "t-tdiv_ui.c" #include "t-tstbit.c" #include "t-val2.c" #include "t-xgcd.c" #include "t-xgcd_canonical_bezout.c" #include "t-xgcd_partial.c" #include "t-xor.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_abs), TEST_FUNCTION(fmpz_abs_fits_ui), TEST_FUNCTION(fmpz_abs_lbound_ui_2exp), TEST_FUNCTION(fmpz_abs_ubound_ui_2exp), TEST_FUNCTION(fmpz_add), TEST_FUNCTION(fmpz_addmul), TEST_FUNCTION(fmpz_addmul_si), TEST_FUNCTION(fmpz_addmul_ui), TEST_FUNCTION(fmpz_and), TEST_FUNCTION(fmpz_aors_ui), TEST_FUNCTION(fmpz_bin_uiui), TEST_FUNCTION(fmpz_bit_pack), TEST_FUNCTION(fmpz_bits), TEST_FUNCTION(fmpz_cdiv_q_2exp), TEST_FUNCTION(fmpz_cdiv_q), TEST_FUNCTION(fmpz_cdiv_qr), TEST_FUNCTION(fmpz_cdiv_q_si), TEST_FUNCTION(fmpz_cdiv_q_ui), TEST_FUNCTION(fmpz_cdiv_r_2exp), TEST_FUNCTION(fmpz_cdiv_ui), TEST_FUNCTION(fmpz_clog), TEST_FUNCTION(fmpz_clog_ui), TEST_FUNCTION(fmpz_cmp2abs), TEST_FUNCTION(fmpz_cmpabs), TEST_FUNCTION(fmpz_cmp), TEST_FUNCTION(fmpz_cmp_si), TEST_FUNCTION(fmpz_cmp_ui), TEST_FUNCTION(fmpz_comb_init_clear), TEST_FUNCTION(fmpz_combit), TEST_FUNCTION(fmpz_complement), TEST_FUNCTION(fmpz_CRT), TEST_FUNCTION(fmpz_CRT_ui), TEST_FUNCTION(fmpz_divexact2_uiui), TEST_FUNCTION(fmpz_divexact), TEST_FUNCTION(fmpz_divexact_si), TEST_FUNCTION(fmpz_divexact_ui), TEST_FUNCTION(fmpz_divides), TEST_FUNCTION(fmpz_divides_mod_list), TEST_FUNCTION(fmpz_divisible), TEST_FUNCTION(fmpz_divisible_si), TEST_FUNCTION(fmpz_divisor_in_residue_class_lenstra), TEST_FUNCTION(fmpz_divisor_sigma), TEST_FUNCTION(fmpz_div_newton), TEST_FUNCTION(fmpz_dlog), TEST_FUNCTION(fmpz_equal), TEST_FUNCTION(fmpz_equal_si), TEST_FUNCTION(fmpz_equal_ui), TEST_FUNCTION(fmpz_euler_phi), TEST_FUNCTION(fmpz_fac_ui), TEST_FUNCTION(fmpz_fdiv_q_2exp), TEST_FUNCTION(fmpz_fdiv_q), TEST_FUNCTION(fmpz_fdiv_qr), TEST_FUNCTION(fmpz_fdiv_qr_preinvn), TEST_FUNCTION(fmpz_fdiv_q_si), TEST_FUNCTION(fmpz_fdiv_q_ui), TEST_FUNCTION(fmpz_fdiv_r_2exp), TEST_FUNCTION(fmpz_fdiv_r), TEST_FUNCTION(fmpz_fdiv_ui), TEST_FUNCTION(fmpz_fib_ui), TEST_FUNCTION(fmpz_fits_si), TEST_FUNCTION(fmpz_flog), TEST_FUNCTION(fmpz_flog_ui), TEST_FUNCTION(fmpz_fmma), TEST_FUNCTION(fmpz_fmms), TEST_FUNCTION(fmpz_fmpz), TEST_FUNCTION(fmpz_cleanup), TEST_FUNCTION(fmpz_stress), TEST_FUNCTION(fmpz_gcd3), TEST_FUNCTION(fmpz_gcd), TEST_FUNCTION(fmpz_gcdinv), TEST_FUNCTION(fmpz_gcd_ui), TEST_FUNCTION(fmpz_get_d_2exp), TEST_FUNCTION(fmpz_get_d), TEST_FUNCTION(fmpz_get_mpf), TEST_FUNCTION(fmpz_get_mpfr), TEST_FUNCTION(fmpz_get_mpn), TEST_FUNCTION(fmpz_get_mpz), TEST_FUNCTION(fmpz_get_nmod), TEST_FUNCTION(fmpz_get_set_ui_array), TEST_FUNCTION(fmpz_get_si), TEST_FUNCTION(fmpz_get_str), TEST_FUNCTION(fmpz_get_ui), TEST_FUNCTION(fmpz_init2), TEST_FUNCTION(fmpz_init_set), TEST_FUNCTION(fmpz_init_set_readonly), TEST_FUNCTION(fmpz_init_set_ui), TEST_FUNCTION(fmpz_invmod), TEST_FUNCTION(fmpz_is_even), TEST_FUNCTION(fmpz_is_perfect_power), TEST_FUNCTION(fmpz_is_prime), TEST_FUNCTION(fmpz_is_prime_morrison), TEST_FUNCTION(fmpz_is_prime_pocklington), TEST_FUNCTION(fmpz_is_prime_pseudosquare), TEST_FUNCTION(fmpz_is_probabprime_BPSW), TEST_FUNCTION(fmpz_is_probabprime_lucas), TEST_FUNCTION(fmpz_is_square), TEST_FUNCTION(fmpz_is_strong_probabprime), TEST_FUNCTION(fmpz_jacobi), TEST_FUNCTION(fmpz_kronecker), TEST_FUNCTION(fmpz_lcm), TEST_FUNCTION(fmpz_mod), TEST_FUNCTION(fmpz_mod_ui), TEST_FUNCTION(fmpz_moebius_mu), TEST_FUNCTION(fmpz_mpz_init_set_readonly), TEST_FUNCTION(fmpz_mul_2exp), TEST_FUNCTION(fmpz_mul2_uiui), TEST_FUNCTION(fmpz_mul), TEST_FUNCTION(fmpz_mul_si), TEST_FUNCTION(fmpz_mul_si_tdiv_q_2exp), TEST_FUNCTION(fmpz_mul_tdiv_q_2exp), TEST_FUNCTION(fmpz_multi_CRT_multi_mod), TEST_FUNCTION(fmpz_multi_CRT_ui), TEST_FUNCTION(fmpz_mul_ui), TEST_FUNCTION(fmpz_ndiv_qr), TEST_FUNCTION(fmpz_neg), TEST_FUNCTION(fmpz_neg_ui), TEST_FUNCTION(fmpz_neg_uiui), TEST_FUNCTION(fmpz_nextprime), TEST_FUNCTION(fmpz_or), TEST_FUNCTION(fmpz_out_inp_raw), TEST_FUNCTION(fmpz_popcnt), TEST_FUNCTION(fmpz_powm), TEST_FUNCTION(fmpz_powm_ui), TEST_FUNCTION(fmpz_pow_ui), TEST_FUNCTION(fmpz_primorial), TEST_FUNCTION(fmpz_print_read), TEST_FUNCTION(fmpz_randprime), TEST_FUNCTION(fmpz_remove), TEST_FUNCTION(fmpz_rfac_ui), TEST_FUNCTION(fmpz_rfac_uiui), TEST_FUNCTION(fmpz_root), TEST_FUNCTION(fmpz_setbit), TEST_FUNCTION(fmpz_set), TEST_FUNCTION(fmpz_set_d_2exp), TEST_FUNCTION(fmpz_set_signed_ui_array), TEST_FUNCTION(fmpz_set_signed_uiui), TEST_FUNCTION(fmpz_set_signed_uiuiui), TEST_FUNCTION(fmpz_set_str), TEST_FUNCTION(fmpz_set_ui_smod), TEST_FUNCTION(fmpz_set_uiui), TEST_FUNCTION(fmpz_sgn), TEST_FUNCTION(fmpz_size), TEST_FUNCTION(fmpz_sizeinbase), TEST_FUNCTION(fmpz_smod), TEST_FUNCTION(fmpz_sqrt), TEST_FUNCTION(fmpz_sqrtmod), TEST_FUNCTION(fmpz_sqrtrem), TEST_FUNCTION(fmpz_sub), TEST_FUNCTION(fmpz_submul), TEST_FUNCTION(fmpz_submul_si), TEST_FUNCTION(fmpz_submul_ui), TEST_FUNCTION(fmpz_swap), TEST_FUNCTION(fmpz_tdiv_q_2exp), TEST_FUNCTION(fmpz_tdiv_q), TEST_FUNCTION(fmpz_tdiv_qr), TEST_FUNCTION(fmpz_tdiv_q_si), TEST_FUNCTION(fmpz_tdiv_q_ui), TEST_FUNCTION(fmpz_tdiv_r_2exp), TEST_FUNCTION(fmpz_tdiv_ui), TEST_FUNCTION(fmpz_tstbit), TEST_FUNCTION(fmpz_val2), TEST_FUNCTION(fmpz_xgcd), TEST_FUNCTION(fmpz_xgcd_canonical_bezout), TEST_FUNCTION(fmpz_xgcd_partial), TEST_FUNCTION(fmpz_xor) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz/test/t-abs.c000066400000000000000000000025601461254215100165320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_abs, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_get_mpz(c, a); if (n_randint(state, 2)) /* test aliasing */ { fmpz_set(b, a); fmpz_abs(b, b); } else { fmpz_abs(b, a); } mpz_abs(c, c); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-abs_fits_ui.c000066400000000000000000000033061461254215100202530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #ifndef check #define check check /* Defined in t-abs_fits_ui.c, t-fits_si.c and t-moebius_mu.c */ static void check(fmpz_t input, int output, int expected) { if (output != expected) { printf("FAIL:\n\n" "input = "), fmpz_print(input), printf("\n" "output = %d, expected = %d\n", output, expected); fflush(stdout); flint_abort(); } } #endif TEST_FUNCTION_START(fmpz_abs_fits_ui, state) { slong i; fmpz_t x; fmpz_init(x); fmpz_set_si(x, COEFF_MIN); check(x, fmpz_abs_fits_ui(x), 1); fmpz_set_si(x, COEFF_MAX); check(x, fmpz_abs_fits_ui(x), 1); fmpz_set_ui(x, UWORD_MAX); check(x, fmpz_abs_fits_ui(x), 1); fmpz_set_ui(x, UWORD_MAX); fmpz_neg(x, x); check(x, fmpz_abs_fits_ui(x), 1); fmpz_set_ui(x, UWORD_MAX); fmpz_add_ui(x, x, UWORD(1)); check(x, fmpz_abs_fits_ui(x), 0); fmpz_neg(x, x); check(x, fmpz_abs_fits_ui(x), 0); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_set_ui(x, UWORD(1)); fmpz_mul_2exp(x, x, i); check(x, fmpz_abs_fits_ui(x), i < FLINT_BITS); fmpz_neg(x, x); check(x, fmpz_abs_fits_ui(x), i < FLINT_BITS); } fmpz_clear(x); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-abs_lbound_ui_2exp.c000066400000000000000000000035741461254215100215360ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" static mp_limb_t refimpl(slong * exp, const fmpz_t x, int bits) { fmpz_t t; slong xbits; mp_limb_t m; xbits = fmpz_bits(x); fmpz_init(t); fmpz_abs(t, x); if (xbits >= bits) fmpz_tdiv_q_2exp(t, t, xbits - bits); else fmpz_mul_2exp(t, t, bits - xbits); m = fmpz_get_ui(t); fmpz_clear(t); *exp = xbits - bits; return m; } TEST_FUNCTION_START(fmpz_abs_lbound_ui_2exp, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_t x; slong bits; slong exp, yexp; mp_limb_t yman, man; fmpz_init(x); fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 400)); bits = 1 + n_randint(state, FLINT_BITS - 1); yman = refimpl(&yexp, x, bits); man = fmpz_abs_lbound_ui_2exp(&exp, x, bits); if (FLINT_BIT_COUNT(man) != bits || (man != yman) || (exp != yexp)) { flint_printf("FAIL\n"); flint_printf("bits = %wd, count = %u\n\n", bits, FLINT_BIT_COUNT(man)); flint_printf("x = "); fmpz_print(x); flint_printf("\n\n"); flint_printf("bits(x) = %wd\n\n", fmpz_bits(x)); flint_printf("man = %wu, exp = %wd\n", man, exp); flint_printf("yman = %wu, yexp = %wd\n", yman, yexp); fflush(stdout); flint_abort(); } fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-abs_ubound_ui_2exp.c000066400000000000000000000062401461254215100215400ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_abs_ubound_ui_2exp, state) { slong iter; int result; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_t x, y; slong bits, yexp; slong exp; mp_limb_t man; fmpz_init(x); fmpz_init(y); fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 400)); bits = 1 + n_randint(state, FLINT_BITS - 1); /* compute an exactly rounded mantissa */ fmpz_abs(y, x); if (fmpz_is_zero(y)) { yexp = 0; } else { yexp = fmpz_bits(y) - bits; if (yexp >= 0) { fmpz_cdiv_q_2exp(y, y, yexp); if (fmpz_bits(y) == bits + 1) { fmpz_tdiv_q_2exp(y, y, 1); yexp--; } } else { fmpz_mul_2exp(y, y, -yexp); } } man = fmpz_abs_ubound_ui_2exp(&exp, x, bits); if (FLINT_BIT_COUNT(man) != bits) { flint_printf("wrong number of bits!\n"); flint_printf("bits = %wd, count = %u\n\n", bits, FLINT_BIT_COUNT(man)); flint_printf("x = "); fmpz_print(x); flint_printf("\n\n"); flint_printf("bits(x) = %wd\n\n", fmpz_bits(x)); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); flint_printf("yexp = %wd\n\n", yexp); flint_printf("man = %wu, exp = %wd\n", man, exp); fflush(stdout); flint_abort(); } /* ok if equal */ result = (fmpz_cmp_ui(y, man) == 0); /* ok if mantissa is 1 larger */ if (!result) { result = ((exp == yexp) && (fmpz_cmp_ui(y, man - 1) == 0)); } /* ok if the exact mantissa is 2^r-1 and overflow to 2^r happened */ if (!result) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, man); fmpz_mul_ui(t, t, 2); fmpz_sub_ui(t, t, 1); result = (exp == yexp + 1) && fmpz_equal(t, y); fmpz_clear(t); } if (!result) { flint_printf("different from exact ceiling division\n"); flint_printf("bits = %wd\n\n", bits); flint_printf("x = "); fmpz_print(x); flint_printf("\n\n"); flint_printf("bits(x) = %wd\n\n", fmpz_bits(x)); flint_printf("y = "); fmpz_print(y); flint_printf(", yexp = %wd\n\n", yexp); flint_printf("man = %wu, exp = %wd\n", man, exp); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-add.c000066400000000000000000000035771461254215100165260ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_add, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_add(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_add(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_add(c, c, b); } else { fmpz_set(c, b); fmpz_add(c, a, c); } mpz_add(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-addmul.c000066400000000000000000000041241461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_addmul, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_randtest(c, state, 200); if (n_randint(state, 10) == 0) fmpz_submul(c, a, b); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); fmpz_get_mpz(f, c); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_addmul(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_addmul(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); mpz_set(f, d); fmpz_addmul(c, c, b); } else { fmpz_set(c, b); mpz_set(f, e); fmpz_addmul(c, a, c); } mpz_addmul(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-addmul_si.c000066400000000000000000000033011461254215100177200ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "long_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_addmul_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, xx; slong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); x = z_randtest(state); if (n_randint(state, 2)) { fmpz_addmul_si(b, a, x); } else /* test aliasing */ { fmpz_set(b, a); mpz_set(e, d); fmpz_addmul_si(b, b, x); } flint_mpz_init_set_si(xx, x); mpz_addmul(e, d, xx); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, xx = %Zd\n", d, e, f, xx); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(xx); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-addmul_ui.c000066400000000000000000000045441461254215100177340ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_addmul_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); x = n_randtest(state); if (n_randint(state, 2)) { fmpz_addmul_ui(b, a, x); } else /* test aliasing */ { fmpz_set(b, a); mpz_set(e, d); fmpz_addmul_ui(b, b, x); } flint_mpz_addmul_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t d, e; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randtest(state); fmpz_addmul_ui(a, a, x); flint_mpz_addmul_ui(d, d, x); fmpz_get_mpz(e, a); result = (mpz_cmp(d, e) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, x = %Mu\n", d, e, x); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-and.c000066400000000000000000000036231461254215100165300ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_and, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_and(c, a, b); } else if (aliasing == 1) { fmpz_set(c, a); fmpz_and(c, c, b); } else if (aliasing == 2) { fmpz_set(c, b); fmpz_and(c, a, c); } else if (aliasing == 3) { fmpz_set(c, a); fmpz_and(c, a, a); mpz_set(e, d); } mpz_and(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-aors_ui.c000066400000000000000000000051131461254215100174230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_aors_ui, state) { int i, result; for (i = 0; i < 20000 * flint_test_multiplier(); i++) { fmpz_t f, g, tst; mpz_t mf, mg; ulong x; int type; fmpz_init(f); fmpz_init(g); fmpz_init(tst); mpz_init(mf); mpz_init(mg); type = n_randint(state, 5); if (type < 4) { fmpz_randtest(g, state, 200); x = n_randtest(state); } else { fmpz_randbits(g, state, FLINT_BITS + 1); x = n_randbits(state, FLINT_BITS); } fmpz_get_mpz(mg, g); switch (type) { /* Add */ case 0: fmpz_add_ui(f, g, x); break; /* Add, aliased */ case 1: fmpz_set(f, g); fmpz_add_ui(f, f, x); break; /* Sub */ case 2: fmpz_sub_ui(f, g, x); break; /* Sub, aliased */ case 3: fmpz_set(f, g); fmpz_sub_ui(f, f, x); break; /* size(g) = 2 but f may be small */ case 4: if (fmpz_sgn(g) < 0) fmpz_add_ui(f, g, x); else fmpz_sub_ui(f, g, x); break; default: FLINT_UNREACHABLE; } if (type < 2 || (type == 4 && fmpz_sgn(g) < 0)) flint_mpz_add_ui(mf, mg, x); else flint_mpz_sub_ui(mf, mg, x); fmpz_set_mpz(tst, mf); result = fmpz_equal(f, tst) && _fmpz_is_canonical(f); if (!result) flint_throw(FLINT_TEST_FAIL, "f = %{fmpz}\n" "g = %{fmpz}\n" "x = %wu\n\n" "Correct result via GMP: %{fmpz}\n", f, g, x, tst); fmpz_clear(f); fmpz_clear(g); fmpz_clear(tst); mpz_clear(mf); mpz_clear(mg); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-bin_uiui.c000066400000000000000000000022321461254215100175640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_bin_uiui, state) { slong i; ulong n, k; fmpz_t x, y; mpz_t z; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_init(x); fmpz_init(y); mpz_init(z); n = n_randint(state, 1000); k = n_randint(state, 1000); fmpz_bin_uiui(x, n, k); flint_mpz_bin_uiui(z, n, k); fmpz_set_mpz(y, z); if (!fmpz_equal(x, y) || !_fmpz_is_canonical(x)) { flint_printf("FAIL: n,k = %wu,%wu\n", n, k); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-bit_pack.c000066400000000000000000000047551461254215100175510ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_bit_pack, state) { int i, result; for (i = 0; i < 50000 * flint_test_multiplier(); i++) { fmpz_t a, b; flint_bitcnt_t bits = n_randint(state, 300) + 1; ulong space = (300 - 1) / FLINT_BITS + 2; /* 2 to accommodate shift */ mp_ptr arr = (mp_ptr) flint_calloc(space, sizeof(mp_limb_t)); flint_bitcnt_t shift = n_randint(state, FLINT_BITS); int negate = (int) -n_randint(state, 2); fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, bits - 1); /* need one bit for sign */ arr[0] = n_randbits(state, shift); fmpz_bit_pack(arr, shift, bits, a, negate, 0); fmpz_bit_unpack(b, arr, shift, bits, negate, 0); result = (fmpz_cmp(a, b) == 0); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n"); fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(arr); fmpz_clear(a); fmpz_clear(b); } for (i = 0; i < 50000 * flint_test_multiplier(); i++) { fmpz_t a, b; flint_bitcnt_t bits = n_randint(state, 300) + 1; ulong space = (300 - 1) / FLINT_BITS + 2; /* 2 to accommodate shift */ mp_ptr arr = (mp_ptr) flint_calloc(space, sizeof(mp_limb_t)); flint_bitcnt_t shift = n_randint(state, FLINT_BITS); fmpz_init(a); fmpz_init(b); fmpz_randtest_unsigned(a, state, bits); arr[0] = n_randbits(state, shift); fmpz_bit_pack(arr, shift, bits, a, 0, 0); fmpz_bit_unpack_unsigned(b, arr, shift, bits); result = (fmpz_cmp(a, b) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n"); fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(arr); fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-bits.c000066400000000000000000000021521461254215100167230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_bits, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; flint_bitcnt_t r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); fmpz_get_mpz(b, a); r1 = fmpz_bits(a); r2 = mpz_sizeinbase(b, 2); result = (r1 == r2) || ((r1 == 0) && (r2 == 1)); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cdiv_q.c000066400000000000000000000037041461254215100172330ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cdiv_q, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_cdiv_q(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_cdiv_q(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_cdiv_q(c, c, b); } else { fmpz_set(c, b); fmpz_cdiv_q(c, a, c); } mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cdiv_q_2exp.c000066400000000000000000000030271461254215100201670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cdiv_q_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_cdiv_q_2exp(b, a, x); } else /* test aliasing */ { fmpz_set(b, a); fmpz_cdiv_q_2exp(b, b, x); } mpz_cdiv_q_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cdiv_q_si.c000066400000000000000000000031751461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_cdiv_q_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong b; fmpz_t a, c; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); b = z_randtest_not_zero(state); fmpz_get_mpz(d, a); flint_mpz_set_si(e, b); if (n_randint(state, 2)) { fmpz_cdiv_q_si(c, a, b); } else /* test aliasing */ { fmpz_set(c, a); fmpz_cdiv_q_si(c, c, b); } mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cdiv_q_ui.c000066400000000000000000000031761461254215100177330ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cdiv_q_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b; fmpz_t a, c; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); b = n_randtest_not_zero(state); fmpz_get_mpz(d, a); flint_mpz_set_ui(e, b); if (n_randint(state, 2)) { fmpz_cdiv_q_ui(c, a, b); } else /* test aliasing */ { fmpz_set(c, a); fmpz_cdiv_q_ui(c, c, b); } mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cdiv_qr.c000066400000000000000000000044331461254215100174150ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cdiv_qr, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(r); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); mpz_init(h); mpz_init(s); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 5); if (aliasing == 0) { fmpz_cdiv_qr(c, r, a, b); } else if (aliasing == 1) { fmpz_set(c, a); fmpz_cdiv_qr(c, r, c, b); } else if (aliasing == 2) { fmpz_set(c, b); fmpz_cdiv_qr(c, r, a, c); } else if (aliasing == 3) { fmpz_set(r, a); fmpz_cdiv_qr(c, r, r, b); } else { fmpz_set(r, b); fmpz_cdiv_qr(c, r, a, r); } mpz_cdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, r); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0) && _fmpz_is_canonical(c) && _fmpz_is_canonical(r); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(r); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); mpz_clear(h); mpz_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cdiv_r_2exp.c000066400000000000000000000030071461254215100201660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cdiv_r_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_cdiv_r_2exp(b, a, x); } else { fmpz_set(b, a); fmpz_cdiv_r_2exp(b, b, x); } mpz_cdiv_r_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL 1:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cdiv_ui.c000066400000000000000000000023451461254215100174100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cdiv_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; ulong x, r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); fmpz_get_mpz(b, a); x = n_randtest_not_zero(state); r1 = fmpz_cdiv_ui(a, x); r2 = flint_mpz_cdiv_ui(b, x); result = (r1 == r2) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("b = %Zd, x = %wu, r1 = %wu, r2 = %wu\n", b, x, r1, r2); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-clog.c000066400000000000000000000060271461254215100167130ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_clog, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; slong l; fmpz_init(a); while (fmpz_cmp_ui(a, 2) < 0) fmpz_randtest(a, state, 200); l = fmpz_clog(a, a); result = (l == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("l = %wd\n", l); fflush(stdout); flint_abort(); } fmpz_clear(a); } /* Check correctness */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, x, y; slong k; fmpz_init(a); fmpz_init(b); fmpz_init(x); fmpz_init(y); while (fmpz_cmp_ui(a, 1) < 0) fmpz_randtest(a, state, 200); while (fmpz_cmp_ui(b, 2) < 0) fmpz_randtest(b, state, 200); k = fmpz_clog(a, b); /* p^{k-1} < a <= p^k*/ if (k > 0) fmpz_pow_ui(x, b, k - 1); else fmpz_zero(x); fmpz_pow_ui(y, b, k); result = (fmpz_cmp(x, a) < 0 && fmpz_cmp(a, y) <= 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("y = "), fmpz_print(y), flint_printf("\n"); flint_printf("k = %wd\n", k); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(x); fmpz_clear(y); } /* Check correctness: exact powers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; slong k, l; fmpz_init(a); fmpz_init(b); while (fmpz_cmp_ui(b, 2) < 0) fmpz_randtest(b, state, 200); l = n_randint(state, 20); fmpz_pow_ui(a, b, l); k = fmpz_clog(a, b); result = (k == l); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("k = %wd\n", k); flint_printf("l = %wd\n", l); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-clog_ui.c000066400000000000000000000047721461254215100174150ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_clog_ui, state) { int i, result; /* Check correctness */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, x, y; slong k; fmpz_init(a); fmpz_init(b); fmpz_init(x); fmpz_init(y); while (fmpz_cmp_ui(a, 1) < 0) fmpz_randtest(a, state, 200); while (fmpz_cmp_ui(b, 2) < 0) fmpz_set_ui(b, n_randtest(state)); k = fmpz_clog_ui(a, fmpz_get_ui(b)); if (k > 0) fmpz_pow_ui(x, b, k - 1); else fmpz_zero(x); fmpz_pow_ui(y, b, k); result = (fmpz_cmp(x, a) < 0 && fmpz_cmp(a, y) <= 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("y = "), fmpz_print(y), flint_printf("\n"); flint_printf("k = %wd\n", k); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(x); fmpz_clear(y); } /* Check correctness: exact powers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; slong k, l; fmpz_init(a); fmpz_init(b); while (fmpz_cmp_ui(b, 2) < 0) fmpz_set_ui(b, n_randtest(state)); l = n_randint(state, 20); fmpz_pow_ui(a, b, l); k = fmpz_clog_ui(a, fmpz_get_ui(b)); result = (k == l); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("k = %wd\n", k); flint_printf("l = %wd\n", l); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cmp.c000066400000000000000000000035441461254215100165470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cmp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, 200); fmpz_set(b, a); result = (fmpz_cmp(a, b)); if (result != 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; int r1, r2; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(c, a); fmpz_get_mpz(d, b); r1 = fmpz_cmp(a, b); r2 = mpz_cmp(c, d); result = ((r1 == 0 && r2 == 0) || (r1 > 0 && r2 > 0) || (r1 < 0 && r2 < 0)); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cmp2abs.c000066400000000000000000000024301461254215100173100ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" int sign(int a) { return a > 0 ? 1 : a < 0 ? -1 : 0; } TEST_FUNCTION_START(fmpz_cmp2abs, state) { slong i; for (i = 0; i < 200000 * flint_test_multiplier(); i++) { fmpz_t a, b, b2; fmpz_init(a); fmpz_init(b); fmpz_init(b2); fmpz_randtest(a, state, 400); fmpz_randtest(b, state, 400); fmpz_addmul_ui(a, b, 2); fmpz_mul_ui(b2, b, 2); if (sign(fmpz_cmp2abs(a, b)) != sign(fmpz_cmpabs(a, b2))) { flint_printf("FAIL i = %wd\n", i); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(b2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cmp_si.c000066400000000000000000000027751461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cmp_si, state) { int i, result; /* Compare with fmpz_cmp */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; slong n; int lhs, rhs; fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, 200); n = z_randtest(state); fmpz_set_si(b, n); lhs = fmpz_cmp(a, b); rhs = fmpz_cmp_si(a, n); result = (lhs < 0) ? (rhs < 0) : ((lhs > 0) ? (rhs > 0) : (rhs == 0)); if (result == 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("n = %wd\n", n); flint_printf("cmp(a, b) = %d\n", fmpz_cmp(a, b)); flint_printf("cmp_si(a, n) = %d\n", fmpz_cmp_si(a, n)); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cmp_ui.c000066400000000000000000000027251461254215100172440ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cmp_ui, state) { int i, result; /* Compare with fmpz_cmp */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; ulong n; int lhs, rhs; fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, 200); n = n_randtest(state); fmpz_set_ui(b, n); lhs = fmpz_cmp(a, b); rhs = fmpz_cmp_ui(a, n); result = (lhs < 0) ? (rhs < 0) : ((lhs > 0) ? (rhs > 0) : (rhs == 0)); if (result == 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("n = %wu\n", n); flint_printf("cmp(a, b) = %d\n", fmpz_cmp(a, b)); flint_printf("cmp_ui(a, n) = %d\n", fmpz_cmp_ui(a, n)); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-cmpabs.c000066400000000000000000000035571461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_cmpabs, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, 200); fmpz_set(b, a); result = (fmpz_cmpabs(a, b)); if (result != 0) { flint_printf("FAIL\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; int r1, r2; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(c, a); fmpz_get_mpz(d, b); r1 = fmpz_cmpabs(a, b); r2 = mpz_cmpabs(c, d); result = ((r1 == 0 && r2 == 0) || (r1 > 0 && r2 > 0) || (r1 < 0 && r2 < 0)); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-comb_init_clear.c000066400000000000000000000023111461254215100210700ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_comb_init_clear, state) { slong i, j; mp_limb_t n; slong num_primes; mp_limb_t * primes; mp_limb_t p; fmpz_comb_t comb; for (i = 0; i < 100 * flint_test_multiplier(); i++) { n = n_randint(state, 10); num_primes = (WORD(1) << n); primes = (mp_limb_t *) flint_malloc(num_primes * sizeof(mp_limb_t)); p = n_nextprime((UWORD(1) << (FLINT_BITS-1)) - WORD(10000000), 0); for (j = 0; j < num_primes; j++) { primes[j] = p; p = n_nextprime(p, 0); } fmpz_comb_init(comb, primes, num_primes); fmpz_comb_clear(comb); flint_free(primes); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-combit.c000066400000000000000000000025701461254215100172430ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_combit, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong j; fmpz_t a; mpz_t b, c; fmpz_init(a); mpz_init(b); mpz_init(c); fmpz_randtest(a, state, 2 * FLINT_BITS); fmpz_get_mpz(b, a); j = n_randint(state, 3 * FLINT_BITS); fmpz_combit(a, j); mpz_combit(b, j); fmpz_get_mpz(c, a); result = (mpz_cmp(b, c) == 0) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); gmp_printf("b = %Zd\n", b); flint_printf("j = %wd\n", j); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(c); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-complement.c000066400000000000000000000025761461254215100201370ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_complement, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_get_mpz(c, a); if (n_randint(state, 2)) { fmpz_complement(b, a); } else { fmpz_set(b, a); fmpz_complement(b, b); } mpz_com(c, c); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL (no alias):\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-crt.c000066400000000000000000000053121461254215100165530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_CRT, state) { slong i, j; int sign; fmpz_t input; fmpz_t result; fmpz_t r1; fmpz_t m1; fmpz_t mprod; fmpz_t r2, m2; fmpz_init(input); fmpz_init(result); fmpz_init(r1); fmpz_init(m1); fmpz_init(r2); fmpz_init(m2); fmpz_init(mprod); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong nprimes; fmpz_set_ui(m2, n_randtest_prime(state, 0)); nprimes = 1 + n_randint(state, 4); fmpz_set_ui(m1, UWORD(1)); for (j = 0; j < nprimes; ) { ulong t = n_randtest_prime(state, 0); if (t != fmpz_get_ui(m2)) { fmpz_mul_ui(m1, m1, t); j++; } } fmpz_mul(mprod, m1, m2); sign = n_randint(state, 2); if (sign) fmpz_randtest_mod_signed(input, state, mprod); else fmpz_randtest_mod(input, state, mprod); fmpz_mod(r1, input, m1); fmpz_mod(r2, input, m2); if (sign && n_randint(state, 2)) { /* If sign is set, fmpz_CRT allows -m_{1} <= r < m_{1}. Set r < 0.*/ fmpz_sub(r1, r1, m1); } fmpz_CRT(result, r1, m1, r2, m2, sign); if (!fmpz_equal(result, input) || !_fmpz_is_canonical(result)) { flint_printf("FAIL:\n"); flint_printf("m1: "); fmpz_print(m1); flint_printf("\n"); flint_printf("m2: "); fmpz_print(m2); flint_printf("\n"); flint_printf("m1*m2: "); fmpz_print(mprod); flint_printf("\n"); flint_printf("input: "); fmpz_print(input); flint_printf("\n"); flint_printf("r1: "); fmpz_print(r1); flint_printf("\n"); flint_printf("r2: "); fmpz_print(r2); flint_printf("\n"); flint_printf("result: "); fmpz_print(result); flint_printf("\n"); flint_printf("%wd Equalness: %d\n", i, fmpz_equal(result, input)); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_clear(input); fmpz_clear(result); fmpz_clear(r1); fmpz_clear(m1); fmpz_clear(r2); fmpz_clear(m2); fmpz_clear(mprod); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-crt_ui.c000066400000000000000000000045451461254215100172570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_CRT_ui, state) { slong i, j; int sign; fmpz_t input; fmpz_t result; fmpz_t r1; fmpz_t m1; fmpz_t mprod; ulong r2, m2; fmpz_init(input); fmpz_init(result); fmpz_init(r1); fmpz_init(m1); fmpz_init(mprod); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong nprimes; m2 = n_randtest_prime(state, 0); nprimes = 1 + n_randint(state, 4); fmpz_set_ui(m1, UWORD(1)); for (j = 0; j < nprimes; ) { ulong t = n_randtest_prime(state, 0); if (t != m2) { fmpz_mul_ui(m1, m1, t); j++; } } fmpz_mul_ui(mprod, m1, m2); sign = n_randint(state, 2); if (sign) fmpz_randtest_mod_signed(input, state, mprod); else fmpz_randtest_mod(input, state, mprod); fmpz_mod(r1, input, m1); r2 = fmpz_fdiv_ui(input, m2); fmpz_CRT_ui(result, r1, m1, r2, m2, sign); if (!fmpz_equal(result, input) || !_fmpz_is_canonical(result)) { flint_printf("FAIL:\n"); flint_printf("m1: "); fmpz_print(m1); flint_printf("\n"); flint_printf("m2: %wu\n", m2); flint_printf("m1*m2: "); fmpz_print(mprod); flint_printf("\n"); flint_printf("input: "); fmpz_print(input); flint_printf("\n"); flint_printf("r1: "); fmpz_print(r1); flint_printf("\n"); flint_printf("r2: %wu\n", r2); flint_printf("result: "); fmpz_print(result); flint_printf("\n"); flint_printf("%wd Equalness: %d\n", i, fmpz_equal(result, input)); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_clear(input); fmpz_clear(result); fmpz_clear(r1); fmpz_clear(m1); fmpz_clear(mprod); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-div_newton.c000066400000000000000000000123131461254215100201360ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" void test_div_q(void (*my_f)(fmpz_t, const fmpz_t, const fmpz_t), void (*reference_f)(fmpz_t, const fmpz_t, const fmpz_t), flint_rand_t state, const char * descr) { fmpz_t a, b, q, q2; int aliasing; slong bits; fmpz_init(a); fmpz_init(b); fmpz_init(q); fmpz_init(q2); if (n_randint(state, 100) == 0) bits = 100000; else bits = 200; if (reference_f == fmpz_divexact) { fmpz_randtest(a, state, bits); fmpz_randtest_not_zero(b, state, bits); fmpz_mul(a, a, b); } else { fmpz_randtest(a, state, bits); fmpz_randtest_not_zero(b, state, bits); if (n_randint(state, 4) == 0) { fmpz_mul(a, a, b); fmpz_add_si(a, a, (slong) n_randint(state, 5) - 2); } } aliasing = n_randint(state, 3); if (aliasing == 0) { my_f(q, a, b); } else if (aliasing == 1) { fmpz_set(q, a); my_f(q, q, b); } else { fmpz_set(q, b); my_f(q, a, q); } reference_f(q2, a, b); if (!fmpz_equal(q, q2) || !_fmpz_is_canonical(q)) { flint_printf("FAIL: %s\n", descr); flint_printf("aliasing = %d\n", aliasing); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n"); flint_printf("q2 = "); fmpz_print(q2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(q); fmpz_clear(q2); } void test_div_qr(void (*my_f)(fmpz_t, fmpz_t, const fmpz_t, const fmpz_t), void (*reference_f)(fmpz_t, fmpz_t, const fmpz_t, const fmpz_t), flint_rand_t state, const char * descr) { fmpz_t a, b, q, r, q2, r2; int aliasing; slong bits; fmpz_init(a); fmpz_init(b); fmpz_init(q); fmpz_init(r); fmpz_init(q2); fmpz_init(r2); if (n_randint(state, 100) == 0) bits = 100000; else bits = 200; fmpz_randtest(a, state, bits); fmpz_randtest_not_zero(b, state, bits); if (n_randint(state, 4) == 0) { fmpz_mul(a, a, b); fmpz_add_si(a, a, (slong) n_randint(state, 5) - 2); } aliasing = n_randint(state, 5); if (aliasing == 0) { my_f(q, r, a, b); } else if (aliasing == 1) { fmpz_set(q, a); my_f(q, r, q, b); } else if (aliasing == 2) { fmpz_set(q, b); my_f(q, r, a, q); } else if (aliasing == 3) { fmpz_set(r, a); my_f(q, r, r, b); } else { fmpz_set(r, b); my_f(q, r, a, r); } reference_f(q2, r2, a, b); if (!fmpz_equal(q, q2) || !fmpz_equal(r, r2) || !_fmpz_is_canonical(q) || !_fmpz_is_canonical(r)) { flint_printf("FAIL: %s\n", descr); flint_printf("aliasing = %d\n", aliasing); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n"); flint_printf("r = "); fmpz_print(r); flint_printf("\n"); flint_printf("q2 = "); fmpz_print(q2); flint_printf("\n"); flint_printf("r2 = "); fmpz_print(r2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(q); fmpz_clear(r); fmpz_clear(q2); fmpz_clear(r2); } /* these currently don't exist in flint */ void fmpz_tdiv_r(fmpz_t r, const fmpz_t a, const fmpz_t b) { fmpz_t t; fmpz_init(t); fmpz_tdiv_qr(t, r, a, b); fmpz_clear(t); } void fmpz_cdiv_r(fmpz_t r, const fmpz_t a, const fmpz_t b) { fmpz_t t; fmpz_init(t); fmpz_cdiv_qr(t, r, a, b); fmpz_clear(t); } TEST_FUNCTION_START(fmpz_div_newton, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { test_div_q(_fmpz_tdiv_q_newton, fmpz_tdiv_q, state, "tdiv_q"); test_div_q(_fmpz_fdiv_q_newton, fmpz_fdiv_q, state, "fdiv_q"); test_div_q(_fmpz_cdiv_q_newton, fmpz_cdiv_q, state, "cdiv_q"); test_div_q(_fmpz_tdiv_r_newton, fmpz_tdiv_r, state, "tdiv_r"); test_div_q(_fmpz_fdiv_r_newton, fmpz_fdiv_r, state, "fdiv_r"); test_div_q(_fmpz_cdiv_r_newton, fmpz_cdiv_r, state, "cdiv_r"); test_div_q(_fmpz_mod_newton, fmpz_mod, state, "mod"); test_div_qr(_fmpz_tdiv_qr_newton, fmpz_tdiv_qr, state, "tdiv_qr"); test_div_qr(_fmpz_fdiv_qr_newton, fmpz_fdiv_qr, state, "fdiv_qr"); test_div_qr(_fmpz_cdiv_qr_newton, fmpz_cdiv_qr, state, "cdiv_qr"); test_div_q(_fmpz_divexact_newton, fmpz_divexact, state, "divexact"); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divexact.c000066400000000000000000000037041461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_divexact, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_mul(c, a, b); fmpz_get_mpz(d, b); fmpz_get_mpz(e, c); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_divexact(a, c, b); } else if (aliasing == 1) { fmpz_set(c, b); mpz_set(e, d); fmpz_divexact(a, c, c); } else if (aliasing == 2) { fmpz_set(a, c); fmpz_divexact(a, a, b); } else { fmpz_set(a, b); fmpz_divexact(a, c, a); } mpz_divexact(f, e, d); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL %d:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divexact2_uiui.c000066400000000000000000000034571461254215100207170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_divexact2_uiui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t e, f, g; ulong n, m; fmpz_init(a); fmpz_init(c); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); n = n_randtest_not_zero(state); m = n_randtest_not_zero(state); fmpz_mul_ui(c, a, n); fmpz_mul_ui(c, c, m); fmpz_get_mpz(e, c); if (n_randint(state, 2)) { fmpz_divexact2_uiui(a, c, n, m); } else { fmpz_set(a, c); fmpz_divexact2_uiui(a, a, n, m); } flint_mpz_divexact_ui(f, e, n); flint_mpz_divexact_ui(f, f, m); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); gmp_printf("n = %Mu, m = %Mu, e = %Zd, f = %Zd, g = %Zd\n", n, m, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divexact_si.c000066400000000000000000000032411461254215100202640ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_divexact_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t e, f, g; slong n; fmpz_init(a); fmpz_init(c); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); n = z_randtest_not_zero(state); fmpz_mul_si(c, a, n); fmpz_get_mpz(e, c); if (n_randint(state, 2)) { fmpz_divexact_si(a, c, n); } else { fmpz_set(a, c); fmpz_divexact_si(a, a, n); } flint_mpz_divexact_ui(f, e, FLINT_ABS(n)); if (n < 0) mpz_neg(f, f); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); gmp_printf("n = %Md, e = %Zd, f = %Zd, g = %Zd\n", n, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divexact_ui.c000066400000000000000000000031511461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_divexact_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t e, f, g; ulong n; fmpz_init(a); fmpz_init(c); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); n = n_randtest_not_zero(state); fmpz_mul_ui(c, a, n); fmpz_get_mpz(e, c); if (n_randint(state, 2)) { fmpz_divexact_ui(a, c, n); } else { fmpz_set(a, c); fmpz_divexact_ui(a, a, n); } flint_mpz_divexact_ui(f, e, n); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL1\n"); gmp_printf("n = %Mu, e = %Zd, f = %Zd, g = %Zd\n", n, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divides.c000066400000000000000000000060771461254215100174230ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_divides, state) { int i, result; /* Random values */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, q, p; int divides; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(p); fmpz_init(q); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); aliasing = n_randint(state, 4); if (aliasing == 0) { divides = fmpz_divides(q, b, a); } else if (aliasing == 1) { fmpz_set(b, a); divides = fmpz_divides(q, b, b); } else if (aliasing == 2) { fmpz_set(q, b); divides = fmpz_divides(q, q, a); } else { fmpz_set(q, a); divides = fmpz_divides(q, b, q); } fmpz_mul(p, a, q); result = ((divides && fmpz_equal(p, b)) || (!divides && fmpz_is_zero(q) && !fmpz_equal(p, b))); result = result && _fmpz_is_canonical(q); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("p = "); fmpz_print(p); flint_printf("\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(p); fmpz_clear(q); } /* Random b multiple of a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, q, p; int divides; fmpz_init(a); fmpz_init(b); fmpz_init(p); fmpz_init(q); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_mul(b, a, b); divides = fmpz_divides(q, b, a); fmpz_mul(p, a, q); result = (divides && fmpz_equal(p, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("p = "); fmpz_print(p); flint_printf("\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(p); fmpz_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divides_mod_list.c000066400000000000000000000111461461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_divides_mod_list, state) { slong i, j; int result1, result2; for (i = 0; i < 2000 * flint_test_multiplier(); i++) { fmpz_t xstart, xstride, xlength; fmpz_t a, b, n; fmpz_t q, r, x; fmpz_init(xstart); fmpz_init(xstride); fmpz_init(xlength); fmpz_init(a); fmpz_init(b); fmpz_init(n); fmpz_init(q); fmpz_init(r); fmpz_init(x); fmpz_randtest(xstart, state, 100); fmpz_randtest(xstride, state, 100); fmpz_randtest(xlength, state, 100); fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 100); fmpz_randtest_unsigned(n, state, 100); fmpz_add_ui(n, n, 1); fmpz_divides_mod_list(xstart, xstride, xlength, a, b, n); if (fmpz_sgn(xlength) > 0) { if (fmpz_sgn(xstride) <= 0) { flint_printf("FAIL:\ncheck xstride > 0\n"); fflush(stdout); flint_abort(); } if (fmpz_cmp(xstart, xstride) >= 0) { flint_printf("FAIL:\ncheck xstart < xstride\n"); fflush(stdout); flint_abort(); } for (j = 0; j < 200; j++) { fmpz_randm(x, state, n); fmpz_mul(r, x, b); fmpz_sub(r, r, a); result1 = fmpz_divisible(r, n); fmpz_sub(r, x, xstart); fmpz_fdiv_qr(q, r, r, xstride); result2 = fmpz_is_zero(r) && fmpz_sgn(q) >= 0 && fmpz_cmp(q, xlength) < 0; if (result1 != result2) { flint_printf("FAIL:\ncheck "); fmpz_print(a); flint_printf("/"); fmpz_print(b); flint_printf(" = "); fmpz_print(x); flint_printf(" mod "); fmpz_print(n); fflush(stdout); flint_abort(); } } } else { for (j = 0; j < 200; j++) { fmpz_randm(x, state, n); fmpz_mul(r, x, b); fmpz_sub(r, r, a); result1 = fmpz_divisible(r, n); if (result1) { flint_printf("FAIL:\ncheck "); fmpz_print(a); flint_printf("/"); fmpz_print(b); flint_printf(" = "); fmpz_print(x); flint_printf(" mod "); fmpz_print(n); fflush(stdout); flint_abort(); } } } fmpz_set(q, a); fmpz_set(r, b); fmpz_set(x, n); fmpz_divides_mod_list(q, r, x, q, r, x); if (!fmpz_equal(q, xstart) || !fmpz_equal(r, xstride) || !fmpz_equal(x, xlength)) { flint_printf("FAIL:\ncheck aliasing 1\n"); fflush(stdout); flint_abort(); } fmpz_set(x, a); fmpz_set(r, b); fmpz_set(q, n); fmpz_divides_mod_list(q, r, x, x, r, q); if (!fmpz_equal(q, xstart) || !fmpz_equal(r, xstride) || !fmpz_equal(x, xlength)) { flint_printf("FAIL:\ncheck aliasing 2\n"); fflush(stdout); flint_abort(); } fmpz_set(r, a); fmpz_set(x, b); fmpz_set(q, n); fmpz_divides_mod_list(q, r, x, r, x, q); if (!fmpz_equal(q, xstart) || !fmpz_equal(r, xstride) || !fmpz_equal(x, xlength)) { flint_printf("FAIL:\ncheck aliasing 3\n"); fflush(stdout); flint_abort(); } fmpz_clear(xstart); fmpz_clear(xstride); fmpz_clear(xlength); fmpz_clear(a); fmpz_clear(b); fmpz_clear(n); fmpz_clear(q); fmpz_clear(r); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divisible.c000066400000000000000000000050231461254215100177340ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_divisible, state) { int i, result; /* Compare with GMP: random */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; int e, f; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(c, a); fmpz_get_mpz(d, b); e = fmpz_divisible(b, a); f = mpz_divisible_p(d, c); result = (e == f); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } /* Compare with GMP: b a multiple of a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; int e, f; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_mul(b, a, b); fmpz_get_mpz(c, a); fmpz_get_mpz(d, b); e = fmpz_divisible(b, a); f = mpz_divisible_p(d, c); result = (e == f && e == 1); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a; int b; fmpz_init(a); fmpz_randtest(a, state, 200); b = fmpz_divisible(a, a); result = (b == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a); fflush(stdout); flint_abort(); } fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divisible_si.c000066400000000000000000000040441461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2022 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "gmpcompat.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_divisible_si, state) { int i, result; /* Compare with GMP: random */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong a; fmpz_t b; mpz_t d; int e, f; fmpz_init(b); mpz_init(d); a = z_randtest_not_zero(state); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, b); e = fmpz_divisible_si(b, a); f = flint_mpz_divisible_ui_p(d, FLINT_ABS(a)); result = (e == f); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wd, b = ", a), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(b); mpz_clear(d); } /* Compare with GMP: b a multiple of a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong a; fmpz_t b; mpz_t d; int e, f; fmpz_init(b); mpz_init(d); a = z_randtest_not_zero(state); fmpz_randtest(b, state, 200); fmpz_mul_si(b, b, a); fmpz_get_mpz(d, b); e = fmpz_divisible_si(b, a); f = flint_mpz_divisible_ui_p(d, FLINT_ABS(a)); result = (e == f && e == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wd, b = ", a), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(b); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divisor_in_residue_class_lenstra.c000066400000000000000000000065121461254215100245700ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_divisor_in_residue_class_lenstra, state) { int i, result; /* test factors of composites are found */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p, a, r, s, d, g; int res; fmpz_init(p); fmpz_init(a); fmpz_init(d); fmpz_init(r); fmpz_init(s); fmpz_init(g); do { do { fmpz_randbits(p, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(p, 2) < 0); do { fmpz_randbits(a, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(a, 2) < 0); fmpz_mul(p, p, a); fmpz_root(s, p, 3); /* cube root of p */ fmpz_randbits(r, state, (2*fmpz_bits(p))/3); fmpz_abs(r, r); fmpz_mul(s, s, r); /* s now between cube root and p */ fmpz_mod(r, a, s); fmpz_gcd(g, r, s); } while (!fmpz_is_one(g)); result = ((res = fmpz_divisor_in_residue_class_lenstra(d, p, r, s)) && !fmpz_is_one(d) && !fmpz_equal(d, p) && fmpz_divisible(p, d)); if (!result) { flint_printf("FAIL:\n"); printf("%d\n", res); fmpz_print(p); printf("\n"); fmpz_print(r); printf("\n"); fmpz_print(s); printf("\n"); fmpz_print(a); printf("\n"); fmpz_print(d); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(a); fmpz_clear(r); fmpz_clear(s); fmpz_clear(g); fmpz_clear(d); } /* test factors of primes are not found */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p, r, s, d, g; int res; fmpz_init(p); fmpz_init(d); fmpz_init(r); fmpz_init(s); fmpz_init(g); do { do { fmpz_randbits(p, state, n_randint(state, 100) + 2); } while (!fmpz_is_probabprime_BPSW(p)); fmpz_root(s, p, 3); /* cube root of p */ fmpz_randbits(r, state, (2*fmpz_bits(p))/3); fmpz_abs(r, r); fmpz_mul(s, s, r); /* s now between cube root and p */ fmpz_randm(r, state, s); fmpz_gcd(g, r, s); } while (!fmpz_is_one(g) || fmpz_is_one(s)); result = (!(res = fmpz_divisor_in_residue_class_lenstra(d, p, r, s))); if (!result) { flint_printf("FAIL:\n"); printf("%d\n", res); fmpz_print(p); printf("\n"); fmpz_print(r); printf("\n"); fmpz_print(s); printf("\n"); fmpz_print(d); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(r); fmpz_clear(s); fmpz_clear(g); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-divisor_sigma.c000066400000000000000000000031261461254215100206230ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz.h" #include "fmpz.h" #include "ulong_extras.h" #include "arith.h" void fmpz_sigma_naive(fmpz_t x, ulong k, ulong n) { slong i = 0; fmpz_t t; fmpz_poly_t p; fmpz_init(t); fmpz_poly_init(p); fmpz_set_ui(t, n); arith_divisors(p, t); fmpz_zero(x); for (i = 0; i < p->length; i++) { fmpz_poly_get_coeff_fmpz(t, p, i); fmpz_pow_ui(t, t, k); fmpz_add(x, x, t); } fmpz_clear(t); fmpz_poly_clear(p); } TEST_FUNCTION_START(fmpz_divisor_sigma, state) { fmpz_t m, a, b; slong n, k; fmpz_init(a); fmpz_init(b); fmpz_init(m); for (n = 0; n < 5000; n++) { for (k = 0; k < 10; k++) { fmpz_set_ui(m, n); fmpz_divisor_sigma(a, k, m); fmpz_sigma_naive(b, k, n); if (!fmpz_equal(a, b) || !_fmpz_is_canonical(a)) { flint_printf("FAIL:\n"); flint_printf("wrong value for n=%wd, k=%wd\n", n, k); fflush(stdout); flint_abort(); } } } fmpz_clear(a); fmpz_clear(b); fmpz_clear(m); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-dlog.c000066400000000000000000000026561461254215100167200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_dlog, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t x; mpz_t z; mpfr_t r; double y, w; fmpz_init(x); mpz_init(z); mpfr_init2(r, 53); fmpz_randtest_not_zero(x, state, 10000); fmpz_abs(x, x); y = fmpz_dlog(x); fmpz_get_mpz(z, x); mpfr_set_z(r, z, MPFR_RNDN); mpfr_log(r, r, MPFR_RNDN); w = mpfr_get_d(r, MPFR_RNDN); result = (FLINT_ABS(y - w) <= w * 1e-13); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("y = %.20g\n", y); flint_printf("w = %.20g\n", w); fflush(stdout); flint_abort(); } fmpz_clear(x); mpz_clear(z); mpfr_clear(r); } mpfr_free_cache(); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-equal.c000066400000000000000000000033531461254215100170750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_equal, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, 200); fmpz_set(b, a); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(c, a); fmpz_get_mpz(d, b); result = (fmpz_equal(a, b) == (mpz_cmp(c, d) == 0)); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-equal_si.c000066400000000000000000000046121461254215100175670ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_equal_si, state) { int i, result; /* Compare with fmpz_equal, random values */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; slong n; int lhs, rhs; fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, 200); n = z_randtest(state); fmpz_set_si(b, n); lhs = fmpz_equal(a, b); rhs = fmpz_equal_si(a, n); result = (lhs == rhs); if (result == 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("n = %wd\n", n); flint_printf("equal(a, b) = %d\n", fmpz_equal(a, b)); flint_printf("equal_si(a, n) = %d\n", fmpz_equal_si(a, n)); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } /* Compare with fmpz_equal, equal values */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; slong n; int lhs, rhs; fmpz_init(a); fmpz_init(b); n = z_randtest(state); fmpz_set_si(a, n); fmpz_set_si(b, n); lhs = fmpz_equal(a, b); rhs = fmpz_equal_si(a, n); result = (lhs == rhs) && (lhs == 1); if (result == 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("n = %wd\n", n); flint_printf("equal(a, b) = %d\n", fmpz_equal(a, b)); flint_printf("equal_si(a, n) = %d\n", fmpz_equal_si(a, n)); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-equal_ui.c000066400000000000000000000045421461254215100175730ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_equal_ui, state) { int i, result; /* Compare with fmpz_equal, random values */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; ulong n; int lhs, rhs; fmpz_init(a); fmpz_init(b); fmpz_randtest(a, state, 200); n = n_randtest(state); fmpz_set_ui(b, n); lhs = fmpz_equal(a, b); rhs = fmpz_equal_ui(a, n); result = (lhs == rhs); if (result == 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("n = %wu\n", n); flint_printf("equal(a, b) = %d\n", fmpz_equal(a, b)); flint_printf("equal_ui(a, n) = %d\n", fmpz_equal_ui(a, n)); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } /* Compare with fmpz_equal, equal values */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; ulong n; int lhs, rhs; fmpz_init(a); fmpz_init(b); n = n_randtest(state); fmpz_set_ui(a, n); fmpz_set_ui(b, n); lhs = fmpz_equal(a, b); rhs = fmpz_equal_ui(a, n); result = (lhs == rhs) && (lhs == 1); if (result == 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("n = %wu\n", n); flint_printf("equal(a, b) = %d\n", fmpz_equal(a, b)); flint_printf("equal_ui(a, n) = %d\n", fmpz_equal_ui(a, n)); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-euler_phi.c000066400000000000000000000046621461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_euler_phi, state) { slong i; ulong n; fmpz_t x, y, z; fmpz_init(x); fmpz_init(y); fmpz_init(z); for (i = 0; i < 100; i++) { fmpz_set_ui(x, i); fmpz_euler_phi(y, x); fmpz_euler_phi(x, x); fmpz_set_ui(z, n_euler_phi(i)); if (!fmpz_equal(x, y) || !fmpz_equal(x, z)) { flint_printf("FAIL: %wd\n", i); fflush(stdout); flint_abort(); } } /* Aliasing test */ for (i = 0; i < 1000; i++) { fmpz_randtest(x, state, FLINT_BITS); fmpz_randtest(y, state, 5); fmpz_pow_ui(y, y, n_randtest(state) % 100); fmpz_mul(x, x, y); fmpz_set(z, x); fmpz_euler_phi(y, x); fmpz_euler_phi(x, x); if (!fmpz_equal(x, y)) { flint_printf("FAIL: "); fmpz_print(z); flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Power of a single prime, phi(p^n) = (p-1) * p^(n-1) */ for (i = 0; i < 100; i++) { n = (n_randtest(state) % 100) + 1; fmpz_set_ui(x, n_nth_prime(i+1)); fmpz_pow_ui(x, x, n); fmpz_euler_phi(x, x); fmpz_set_ui(y, n_nth_prime(i+1)); fmpz_pow_ui(y, y, n-1); fmpz_mul_ui(y, y, n_nth_prime(i+1)-1); if (!fmpz_equal(x, y) || !_fmpz_is_canonical(x)) { flint_printf("FAIL: %wu ^ %wu\n", n_nth_prime(i+1), n); } } /* Something nontrivial */ fmpz_set_str(x, "10426024348053113487152988625265848110501553295256578345594388516660144", 10); fmpz_set_str(y, "2265085829098571747262267425315881590169106756213617459200000000000000", 10); fmpz_euler_phi(x, x); if (!fmpz_equal(x, y) || !_fmpz_is_canonical(x)) { flint_printf("FAIL: special test value\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fac_ui.c000066400000000000000000000023561461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fac_ui, state) { slong i, n; fmpz_t x; fmpz_t y; fmpz_init(x); fmpz_init(y); /* Twice to check demotion */ for (n = 0; n < 2; n++) { fmpz_set_ui(y, UWORD(1)); for (i = 0; i < 100; i++) { fmpz_fac_ui(x, i); fmpz_mul_ui(y, y, FLINT_MAX(1, i)); if (!fmpz_equal(x, y) || !_fmpz_is_canonical(x)) { flint_printf("FAIL: %wd\n", i); fmpz_print(x); flint_printf("\n"); fmpz_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } } } fmpz_clear(x); fmpz_clear(y); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_q.c000066400000000000000000000037041461254215100172360ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_q, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_fdiv_q(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_fdiv_q(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_fdiv_q(c, c, b); } else { fmpz_set(c, b); fmpz_fdiv_q(c, a, c); } mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_q_2exp.c000066400000000000000000000030271461254215100201720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_q_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_fdiv_q_2exp(b, a, x); } else /* test aliasing */ { fmpz_set(b, a); fmpz_fdiv_q_2exp(b, b, x); } mpz_fdiv_q_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_q_si.c000066400000000000000000000031751461254215100177330ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_fdiv_q_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong b; fmpz_t a, c; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); b = z_randtest_not_zero(state); fmpz_get_mpz(d, a); flint_mpz_set_si(e, b); if (n_randint(state, 2)) { fmpz_fdiv_q_si(c, a, b); } else /* test aliasing */ { fmpz_set(c, a); fmpz_fdiv_q_si(c, c, b); } mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_q_ui.c000066400000000000000000000031761461254215100177360ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_q_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b; fmpz_t a, c; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); b = n_randtest_not_zero(state); fmpz_get_mpz(d, a); flint_mpz_set_ui(e, b); if (n_randint(state, 2)) { fmpz_fdiv_q_ui(c, a, b); } else /* test aliasing */ { fmpz_set(c, a); fmpz_fdiv_q_ui(c, c, b); } mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_qr.c000066400000000000000000000044331461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_qr, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(r); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); mpz_init(h); mpz_init(s); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 5); if (aliasing == 0) { fmpz_fdiv_qr(c, r, a, b); } else if (aliasing == 1) { fmpz_set(c, a); fmpz_fdiv_qr(c, r, c, b); } else if (aliasing == 2) { fmpz_set(c, b); fmpz_fdiv_qr(c, r, a, c); } else if (aliasing == 3) { fmpz_set(r, a); fmpz_fdiv_qr(c, r, r, b); } else { fmpz_set(r, b); fmpz_fdiv_qr(c, r, a, r); } mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, r); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0) && _fmpz_is_canonical(c) && _fmpz_is_canonical(r); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(r); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); mpz_clear(h); mpz_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_qr_preinvn.c000066400000000000000000000046231461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_qr_preinvn, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; fmpz_preinvn_t inv; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(r); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); mpz_init(h); mpz_init(s); fmpz_randtest(a, state, 400); fmpz_randtest_not_zero(b, state, 400); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); fmpz_preinvn_init(inv, b); aliasing = n_randint(state, 5); if (aliasing == 0) { fmpz_fdiv_qr_preinvn(c, r, a, b, inv); } else if (aliasing == 1) { fmpz_set(c, a); fmpz_fdiv_qr_preinvn(c, r, c, b, inv); } else if (aliasing == 2) { fmpz_set(c, b); fmpz_fdiv_qr_preinvn(c, r, a, c, inv); } else if (aliasing == 3) { fmpz_set(r, a); fmpz_fdiv_qr_preinvn(c, r, r, b, inv); } else { fmpz_set(r, b); fmpz_fdiv_qr_preinvn(c, r, a, r, inv); } mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, r); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); fflush(stdout); flint_abort(); } fmpz_preinvn_clear(inv); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(r); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); mpz_clear(h); mpz_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_r.c000066400000000000000000000037041461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_r, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_fdiv_r(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_fdiv_r(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_fdiv_r(c, c, b); } else { fmpz_set(c, b); fmpz_fdiv_r(c, a, c); } mpz_fdiv_r(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_r_2exp.c000066400000000000000000000030071461254215100201710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_r_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_fdiv_r_2exp(b, a, x); } else { fmpz_set(b, a); fmpz_fdiv_r_2exp(b, b, x); } mpz_fdiv_r_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL 1:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fdiv_ui.c000066400000000000000000000023451461254215100174130ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fdiv_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; ulong x, r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); fmpz_get_mpz(b, a); x = n_randtest_not_zero(state); r1 = fmpz_fdiv_ui(a, x); r2 = flint_mpz_fdiv_ui(b, x); result = (r1 == r2) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("b = %Zd, x = %wu, r1 = %wu, r2 = %wu\n", b, x, r1, r2); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fib_ui.c000066400000000000000000000026051461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fib_ui, state) { slong i, n; fmpz_t x, y, z, w; fmpz_init(x); fmpz_init(y); fmpz_init(z); fmpz_init(w); /* Twice to check demotion */ for (n = 0; n < 2; n++) { for (i = 0; i < 200; i++) { fmpz_fib_ui(x, i); fmpz_fib_ui(y, i+1); fmpz_fib_ui(z, i+2); fmpz_add(w, x, y); if (!fmpz_equal(w, z) || !_fmpz_is_canonical(x)) { flint_printf("FAIL: %wd\n", i); fmpz_print(x); flint_printf("\n"); fmpz_print(y); flint_printf("\n"); fmpz_print(z); flint_printf("\n"); fflush(stdout); flint_abort(); } } } fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); fmpz_clear(w); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fits_si.c000066400000000000000000000035431461254215100174270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #ifndef check #define check check /* Defined in t-abs_fits_ui.c, t-fits_si.c and t-moebius_mu.c */ static void check(fmpz_t input, int output, int expected) { if (output != expected) { printf("FAIL:\n\n" "input = "), fmpz_print(input), printf("\n" "output = %d, expected = %d\n", output, expected); fflush(stdout); flint_abort(); } } #endif TEST_FUNCTION_START(fmpz_fits_si, state) { slong i; fmpz_t x; fmpz_init(x); fmpz_set_si(x, COEFF_MIN); check(x, fmpz_fits_si(x), 1); fmpz_set_si(x, COEFF_MAX); check(x, fmpz_fits_si(x), 1); fmpz_set_si(x, WORD_MAX); check(x, fmpz_fits_si(x), 1); fmpz_set_si(x, WORD_MIN); check(x, fmpz_fits_si(x), 1); fmpz_set_ui(x, UWORD_MAX); check(x, fmpz_fits_si(x), 0); fmpz_set_ui(x, UWORD_MAX); fmpz_neg(x, x); check(x, fmpz_fits_si(x), 0); fmpz_set_si(x, WORD_MAX); fmpz_add_ui(x, x, 1); check(x, fmpz_fits_si(x), 0); fmpz_set_si(x, WORD_MIN); fmpz_sub_ui(x, x, 1); check(x, fmpz_fits_si(x), 0); for (i = 0; i < 1000; i++) { fmpz_set_ui(x, 1); fmpz_mul_2exp(x, x, i); check(x, fmpz_fits_si(x), i < FLINT_BITS - 1); fmpz_neg(x, x); check(x, fmpz_fits_si(x), i < FLINT_BITS); /* WORD_MIN fits */ } fmpz_clear(x); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-flog.c000066400000000000000000000057001461254215100167130ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_flog, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; slong l; fmpz_init(a); while (fmpz_cmp_ui(a, 2) < 0) fmpz_randtest(a, state, 200); l = fmpz_flog(a, a); result = (l == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("l = %wd\n", l); fflush(stdout); flint_abort(); } fmpz_clear(a); } /* Check correctness */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, x, y; slong k; fmpz_init(a); fmpz_init(b); fmpz_init(x); fmpz_init(y); while (fmpz_cmp_ui(a, 1) < 0) fmpz_randtest(a, state, 200); while (fmpz_cmp_ui(b, 2) < 0) fmpz_randtest(b, state, 200); k = fmpz_flog(a, b); fmpz_pow_ui(x, b, k); fmpz_pow_ui(y, b, k + 1); result = (fmpz_cmp(x, a) <= 0 && fmpz_cmp(a, y) < 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("y = "), fmpz_print(y), flint_printf("\n"); flint_printf("k = %wd\n", k); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(x); fmpz_clear(y); } /* Check correctness: exact powers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; slong k, l; fmpz_init(a); fmpz_init(b); while (fmpz_cmp_ui(b, 2) < 0) fmpz_randtest(b, state, 200); l = n_randint(state, 20); fmpz_pow_ui(a, b, l); k = fmpz_flog(a, b); result = (k == l); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("k = %wd\n", k); flint_printf("l = %wd\n", l); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-flog_ui.c000066400000000000000000000046741461254215100174210ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_flog_ui, state) { int i, result; /* Check correctness */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, x, y; slong k; fmpz_init(a); fmpz_init(b); fmpz_init(x); fmpz_init(y); while (fmpz_cmp_ui(a, 1) < 0) fmpz_randtest(a, state, 200); while (fmpz_cmp_ui(b, 2) < 0) fmpz_set_ui(b, n_randtest(state)); k = fmpz_flog_ui(a, fmpz_get_ui(b)); fmpz_pow_ui(x, b, k); fmpz_pow_ui(y, b, k + 1); result = (fmpz_cmp(x, a) <= 0 && fmpz_cmp(a, y) < 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("y = "), fmpz_print(y), flint_printf("\n"); flint_printf("k = %wd\n", k); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(x); fmpz_clear(y); } /* Check correctness: exact powers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; slong k, l; fmpz_init(a); fmpz_init(b); while (fmpz_cmp_ui(b, 2) < 0) fmpz_set_ui(b, n_randtest(state)); l = n_randint(state, 20); fmpz_pow_ui(a, b, l); k = fmpz_flog_ui(a, fmpz_get_ui(b)); result = (k == l); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("k = %wd\n", k); flint_printf("l = %wd\n", l); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fmma.c000066400000000000000000000040251461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fmma, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d, f, g; fmpz *aptr, *bptr, *cptr, *dptr; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(f); fmpz_init(g); fmpz_randtest(f, state, 200); fmpz_randtest(g, state, 200); if (n_randint(state, 2)) { fmpz_randtest(a, state, 200); aptr = a; } else { fmpz_set(a, f); aptr = f; } if (n_randint(state, 2)) { fmpz_randtest(b, state, 200); bptr = b; } else { fmpz_set(b, f); bptr = f; } if (n_randint(state, 2)) { fmpz_randtest(c, state, 200); cptr = c; } else { fmpz_set(c, f); cptr = f; } if (n_randint(state, 2)) { fmpz_randtest(d, state, 200); dptr = d; } else { fmpz_set(d, f); dptr = f; } fmpz_fmma(f, aptr, bptr, cptr, dptr); fmpz_mul(g, a, b); fmpz_addmul(g, c, d); if (!fmpz_equal(f, g) || !_fmpz_is_canonical(f)) { flint_printf("FAIL:\n"); fmpz_print(a); flint_printf("\n"); fmpz_print(b); flint_printf("\n"); fmpz_print(c); flint_printf("\n"); fmpz_print(d); flint_printf("\n"); fmpz_print(f); flint_printf("\n"); fmpz_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(f); fmpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fmms.c000066400000000000000000000040251461254215100167250ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fmms, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d, f, g; fmpz *aptr, *bptr, *cptr, *dptr; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(f); fmpz_init(g); fmpz_randtest(f, state, 200); fmpz_randtest(g, state, 200); if (n_randint(state, 2)) { fmpz_randtest(a, state, 200); aptr = a; } else { fmpz_set(a, f); aptr = f; } if (n_randint(state, 2)) { fmpz_randtest(b, state, 200); bptr = b; } else { fmpz_set(b, f); bptr = f; } if (n_randint(state, 2)) { fmpz_randtest(c, state, 200); cptr = c; } else { fmpz_set(c, f); cptr = f; } if (n_randint(state, 2)) { fmpz_randtest(d, state, 200); dptr = d; } else { fmpz_set(d, f); dptr = f; } fmpz_fmms(f, aptr, bptr, cptr, dptr); fmpz_mul(g, a, b); fmpz_submul(g, c, d); if (!fmpz_equal(f, g) || !_fmpz_is_canonical(f)) { flint_printf("FAIL:\n"); fmpz_print(a); flint_printf("\n"); fmpz_print(b); flint_printf("\n"); fmpz_print(c); flint_printf("\n"); fmpz_print(d); flint_printf("\n"); fmpz_print(f); flint_printf("\n"); fmpz_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(f); fmpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fmpz.c000066400000000000000000000016741461254215100167460ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_fmpz, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; *a = WORD(0); fmpz_randtest(a, state, SMALL_FMPZ_BITCOUNT_MAX); *b = *a; _fmpz_promote_val(a); _fmpz_demote_val(a); result = (*b == *a); if (!result) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fmpz_cleanup.c000066400000000000000000000025651461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_cleanup, state) { slong iter; for (iter = 0; iter < 300 * flint_test_multiplier(); iter++) { slong i, n; fmpz *A, *B; n = n_randint(state, 100); A = _fmpz_vec_init(n); B = _fmpz_vec_init(n); for (i = 0; i < n; i++) { fmpz_randtest(A + i, state, 1 + n_randint(state, 1000)); fmpz_randtest(B + i, state, 1 + n_randint(state, 1000)); } for (i = 0; i < n; i++) { fmpz_addmul(A + n_randint(state, n), A + n_randint(state, n), B + n_randint(state, n)); fmpz_addmul(B + n_randint(state, n), A + n_randint(state, n), B + n_randint(state, n)); if (n_randint(state, 10) == 0) { } } _fmpz_vec_clear(A, n); _fmpz_vec_clear(B, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-fmpz_stress.c000066400000000000000000000110761461254215100203460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_vec.h" typedef struct { slong idx; slong num; slong len; fmpz * vec; } worker_arg_struct; void worker1(void * varg) { worker_arg_struct * arg = (worker_arg_struct *) varg; slong idx = arg->idx; slong num = arg->num; slong len = arg->len; fmpz * vec = arg->vec; slong i; slong start = (idx + 0)*len/num; slong stop = (idx + 1)*len/num; for (i = start; i < stop; i++) { fmpz_set_ui(vec + i, i); fmpz_mul_2exp(vec + i, vec + i, 100); } } void worker2(void * varg) { worker_arg_struct * arg = (worker_arg_struct *) varg; slong idx = arg->idx; slong num = arg->num; slong len = arg->len; fmpz * vec = arg->vec; slong i; for (i = idx + num; i < len; i += num) { fmpz_add(vec + idx, vec + idx, vec + i); fmpz_zero(vec + i); } } void worker3(void * varg) { worker_arg_struct * arg = (worker_arg_struct *) varg; slong idx = arg->idx; slong num = arg->num; slong len = arg->len; fmpz * vec = arg->vec; slong i; for (i = idx + num; i < len; i += num) { fmpz_set_ui(vec + i, i); fmpz_mul_2exp(vec + i, vec + i, 110); } } TEST_FUNCTION_START(fmpz_stress, state) { slong i, j, k; slong max_num_threads = 5; thread_pool_handle * handles; slong num_handles; worker_arg_struct * wargs; wargs = (worker_arg_struct *) flint_malloc(max_num_threads* sizeof(worker_arg_struct)); /* checking parallel clearing of fmpz's allocated from the same thread */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong n; fmpz * v; fmpz_t total, check; fmpz_init(total); fmpz_init(check); n = n_randint(state, 10000) + 10000; v = _fmpz_vec_init(n); for (j = 0; j < 4; j++) { flint_set_num_threads(n_randint(state, max_num_threads) + 1); num_handles = flint_request_threads(&handles, max_num_threads); for (k = 0; k <= num_handles; k++) { wargs[k].idx = k; wargs[k].num = num_handles + 1; wargs[k].len = n; wargs[k].vec = v; } /* fill v with blocks of large fmpz's from the same thread */ for (k = 0; k < num_handles; k++) thread_pool_wake(global_thread_pool, handles[k], 0, worker1, &wargs[k]); worker1(&wargs[num_handles]); for (k = 0; k < num_handles; k++) thread_pool_wait(global_thread_pool, handles[k]); /* rip up the blocks in succession, zeroing as we go */ for (k = 0; k < num_handles; k++) thread_pool_wake(global_thread_pool, handles[k], 0, worker2, &wargs[k]); worker2(&wargs[num_handles]); for (k = 0; k < num_handles; k++) thread_pool_wait(global_thread_pool, handles[k]); fmpz_zero(total); for (k = 0; k <= num_handles; k++) fmpz_add(total, total, v + k); /* put large fmpz's back in succession */ for (k = 0; k < num_handles; k++) thread_pool_wake(global_thread_pool, handles[k], 0, worker3, &wargs[k]); worker3(&wargs[num_handles]); for (k = 0; k < num_handles; k++) thread_pool_wait(global_thread_pool, handles[k]); flint_give_back_threads(handles, num_handles); fmpz_set_ui(check, n); fmpz_mul_ui(check, check, n - 1); fmpz_mul_2exp(check, check, 99); if (!fmpz_equal(total, check) || !_fmpz_is_canonical(total)) { flint_printf("FAIL:\n"); flint_printf("total: "); fmpz_print(total); flint_printf("\n"); flint_printf("check: "); fmpz_print(check); flint_printf("\n"); fflush(stdout); flint_abort(); } } _fmpz_vec_clear(v, n); fmpz_clear(total); fmpz_clear(check); } flint_free(wargs); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-gcd.c000066400000000000000000000037531461254215100165270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_gcd, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_randtest(c, state, 200); fmpz_mul(a, a, c); fmpz_mul(b, b, c); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_gcd(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_gcd(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_gcd(c, c, b); } else { fmpz_set(c, b); fmpz_gcd(c, a, c); } mpz_gcd(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-gcd3.c000066400000000000000000000040301461254215100165770ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_gcd3, state) { slong i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d, e; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(e); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_randtest(c, state, 200); fmpz_randtest(d, state, 200); fmpz_randtest(e, state, 200); fmpz_mul(a, a, d); fmpz_mul(b, b, d); fmpz_mul(c, c, d); fmpz_gcd(d, a, b); fmpz_gcd(d, d, c); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_gcd3(e, a, b, c); } else if (aliasing == 1) { fmpz_set(e, a); fmpz_gcd3(e, e, b, c); } else if (aliasing == 2) { fmpz_set(e, b); fmpz_gcd3(e, a, e, c); } else { fmpz_set(e, c); fmpz_gcd3(e, a, b, e); } if (!fmpz_equal(d, e)) { flint_printf("FAIL:\n"); flint_printf("aliasing = %d\n", aliasing); fmpz_print(a); printf("\n"); fmpz_print(b); printf("\n"); fmpz_print(c); printf("\n"); fmpz_print(d); printf("\n"); fmpz_print(e); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-gcd_ui.c000066400000000000000000000031101461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_gcd_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t r1, r2, a, fb; ulong b; fmpz_init(r1); fmpz_init(r2); fmpz_init(a); fmpz_init(fb); fmpz_randtest(a, state, 200); b = n_randtest(state); fmpz_set_ui(fb, b); fmpz_gcd(r1, a, fb); if (n_randint(state, 2)) { fmpz_gcd_ui(r2, a, b); } else { fmpz_set(r2, a); fmpz_gcd_ui(r2, r2, b); } result = (fmpz_cmp(r1, r2) == 0) && _fmpz_is_canonical(r2); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\nb = %wu", b); flint_printf("\nr1 = "); fmpz_print(r1); flint_printf("\nr2 = "); fmpz_print(r2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(a); fmpz_clear(fb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-gcdinv.c000066400000000000000000000046121461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_gcdinv, state) { int i, result; /* Test a f == d mod g (specifically d > 1) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, f, g, t, x; int aliasing = n_randint(state, 5); fmpz_init(d); fmpz_init(a); fmpz_init(f); fmpz_init(g); fmpz_init(t); fmpz_init(x); fmpz_randtest_unsigned(g, state, 200); fmpz_add_ui(g, g, 1); fmpz_randm(f, state, g); fmpz_randtest_unsigned(x, state, 100); fmpz_add_ui(x, x, 1); fmpz_mul(f, f, x); fmpz_mul(g, g, x); if (aliasing == 0) { fmpz_gcdinv(d, a, f, g); } else if (aliasing == 1) { fmpz_set(d, f); fmpz_gcdinv(d, a, d, g); } else if (aliasing == 2) { fmpz_set(a, g); fmpz_gcdinv(d, a, f, a); } else if (aliasing == 3) { fmpz_set(a, f); fmpz_gcdinv(d, a, a, g); } else { fmpz_set(d, g); fmpz_gcdinv(d, a, f, d); } fmpz_mul(t, a, f); fmpz_mod(t, t, g); result = ((fmpz_equal(t, d) || fmpz_is_zero(f)) && fmpz_cmp_ui(a, 0) >= 0 && fmpz_cmp(a, g) < 0) && _fmpz_is_canonical(d) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("d = "), fmpz_print(d), flint_printf("\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("t = "), fmpz_print(t), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(f); fmpz_clear(g); fmpz_clear(t); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_d.c000066400000000000000000000033471461254215100170530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_d, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t x, y; mpz_t z; double a, b; fmpz_init(x); fmpz_init(y); mpz_init(z); fmpz_randtest(x, state, 200); fmpz_get_mpz(z, x); a = fmpz_get_d(x); b = mpz_get_d(z); result = (a == b); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("a = %f\n", a); flint_printf("b = %f\n", b); fflush(stdout); flint_abort(); } a = a * (n_randtest(state) / (double) n_randtest_not_zero(state)); fmpz_set_d(x, a); mpz_set_d(z, a); fmpz_set_mpz(y, z); result = fmpz_equal(x, y); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("y = "), fmpz_print(y), flint_printf("\n"); flint_printf("a = %f\n", a); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_d_2exp.c000066400000000000000000000023031461254215100200000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2009 Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_d_2exp, state) { int i, result; double output; slong exp; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a; fmpz_init(a); fmpz_randtest(a, state, 200); output = fmpz_get_d_2exp(&exp, a); result = (fmpz_bits(a) == exp); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("output = %f\n", output); flint_printf("exp = %wd, bits = %wu\n", exp, fmpz_bits(a)); fflush(stdout); flint_abort(); } fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_mpf.c000066400000000000000000000041221461254215100174020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_mpf, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t x, y; mpz_t z; mpf_t a, b, tmp; fmpz_init(x); fmpz_init(y); mpz_init(z); mpf_inits(a, b, tmp, NULL); fmpz_randtest(x, state, 200); fmpz_get_mpz(z, x); fmpz_get_mpf(a, x); mpf_set_z(b, z); result = (mpf_cmp(a, b) == 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("a = "), mpf_out_str(stdout, 10, 0, a), flint_printf("\n"); flint_printf("b = "), mpf_out_str(stdout, 10, 0, b), flint_printf("\n"); fflush(stdout); flint_abort(); } mpf_set_d(tmp, (n_randtest(state) / (double) n_randtest_not_zero(state))); mpf_mul(a, a, tmp); fmpz_set_mpf(x, a); mpz_set_f(z, a); fmpz_set_mpz(y, z); result = fmpz_equal(x, y); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("y = "), fmpz_print(y), flint_printf("\n"); flint_printf("a = "), mpf_out_str(stdout, 10, 0, a), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); mpf_clears(a, b, tmp, NULL); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_mpfr.c000066400000000000000000000030571461254215100175720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_mpfr, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t x, y; mpz_t z; mpfr_t a, b; fmpz_init(x); fmpz_init(y); mpz_init(z); mpfr_inits(a, b, NULL); fmpz_randtest(x, state, 200); fmpz_get_mpz(z, x); fmpz_get_mpfr(a, x, MPFR_RNDN); mpfr_set_z(b, z, MPFR_RNDN); result = (mpfr_equal_p(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("a = "), mpfr_out_str(stdout, 10, 0, a, MPFR_RNDN), flint_printf("\n"); flint_printf("b = "), mpfr_out_str(stdout, 10, 0, b, MPFR_RNDN), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); mpfr_clears(a, b, NULL); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_mpn.c000066400000000000000000000051711461254215100174170ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_mpn, state) { fmpz_t a, b, mmin; int i, j, k; mp_ptr mpna; fmpz_init(a); fmpz_init(b); fmpz_init(mmin); for (i = 0; i < 100; i++) { fmpz_set_ui(mmin, 1); fmpz_mul_2exp(mmin, mmin, i * FLINT_BITS); for (j = 0; j < 100; j++) { fmpz_set_ui(b, 0); k = n_randint(state, FLINT_BITS); k += 1; /* 1 <= k <= FLINT_BITS */ k += (i * FLINT_BITS); /* 2^(i*FLINT_BITS) + 1 <= k <= 2^((i + 1)*FLINT_BITS) */ fmpz_randtest_unsigned(a, state, k); fmpz_add(a, a, mmin); k = fmpz_get_mpn(&mpna, a); while (k != 0) { fmpz_add_ui(b, b, mpna[k - 1]); if (k > 1) fmpz_mul_2exp(b, b, FLINT_BITS); k--; } if (fmpz_cmp(a, b)) { printf("conversion failed.\nn : "); fmpz_print(a); printf("\nconverted value : "); fmpz_print(b); printf("\n"); fflush(stdout); flint_abort(); } flint_free(mpna); } } /* regression test */ { #if FLINT_BITS == 32 slong ksave; ulong limb0, limb1; fmpz_set_ui(a, 524287); fmpz_mul_2exp(a, a, FLINT_BITS); fmpz_add_ui(a, a, 4294443520); fmpz_zero(b); k = fmpz_get_mpn(&mpna, a); ksave = k; limb0 = mpna[0]; limb1 = mpna[1]; while (k != 0) { fmpz_add_ui(b, b, mpna[k - 1]); if (k > 1) fmpz_mul_2exp(b, b, FLINT_BITS); k--; } if (fmpz_cmp(a, b)) { flint_printf("limb0 = %wu, limb1 = %wu, k = %wd\n", limb0, limb1, k); printf("conversion failed.\nn : "); fmpz_print(a); printf("\nconverted value : "); fmpz_print(b); printf("\n"); fflush(stdout); flint_abort(); } flint_free(mpna); #endif } fmpz_clear(a); fmpz_clear(b); fmpz_clear(mmin); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_mpz.c000066400000000000000000000024431461254215100174320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_mpz, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b, c; flint_bitcnt_t bits; mpz_init(b); mpz_init(c); bits = n_randint(state, 200) + 1; _flint_rand_init_gmp(state); mpz_rrandomb(b, state->gmp_state, bits); if (n_randint(state, 2)) mpz_neg(b, b); fmpz_init(a); fmpz_set_mpz(a, b); fmpz_get_mpz(c, a); result = (mpz_cmp(b, c) == 0) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd, c = %Zd\n", b, c); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); mpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_nmod.c000066400000000000000000000024201461254215100175540ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_nmod, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; ulong x, r1, r2; nmod_t mod; fmpz_init(a); fmpz_randtest(a, state, 1000); x = n_randtest_not_zero(state); nmod_init(&mod, x); r1 = fmpz_fdiv_ui(a, x); r2 = fmpz_get_nmod(a, mod); result = (r1 == r2); if (!result) { flint_printf("FAIL: i = %wd\n", i); flint_printf("a: "); fmpz_print(a); flint_printf("\n"); flint_printf("x : %wu\n", x); flint_printf("r1: %wu\n", r1); flint_printf("r2: %wu\n", r2); fflush(stdout); flint_abort(); } fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_set_ui_array.c000066400000000000000000000037761461254215100213240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_set_ui_array, state) { int i; slong max_limbs = 100; ulong * limbs; limbs = (ulong *) flint_malloc(max_limbs*sizeof(ulong)); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong j; slong limb_count1, limb_count2, limb_count3; fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); limb_count1 = n_randint(state, max_limbs) + 1; limb_count2 = n_randint(state, 2*max_limbs); limb_count3 = n_randint(state, 2*max_limbs); fmpz_randtest(a, state, limb_count1*FLINT_BITS); fmpz_abs(a, a); fmpz_randtest(b, state, limb_count2*FLINT_BITS); fmpz_randtest(c, state, limb_count3*FLINT_BITS); fmpz_get_ui_array(limbs, limb_count1, a); fmpz_set_ui_array(b, limbs, limb_count1); fmpz_zero(c); for (j = limb_count1 - 1; j >= 0; j--) { fmpz_mul_2exp(c, c, FLINT_BITS); fmpz_add_ui(c, c, limbs[j]); } if (!fmpz_equal(a, b) || !_fmpz_is_canonical(b)) { flint_printf("FAIL:\n"); flint_printf("Check get and set are inverse\n"); fflush(stdout); flint_abort(); } if (!fmpz_equal(a, c)) { flint_printf("FAIL:\n"); flint_printf("Check limbs are accurate\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } flint_free(limbs); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_si.c000066400000000000000000000034471461254215100172440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_get_si, state) { int i, result; fmpz_t x; fmpz_init(x); fmpz_set_si(x, COEFF_MIN); if (COEFF_IS_MPZ(*x) || fmpz_get_si(x) != COEFF_MIN) { flint_printf("FAIL: COEFF_MIN"); fflush(stdout); flint_abort(); } fmpz_set_si(x, COEFF_MAX); if (COEFF_IS_MPZ(*x) || fmpz_get_si(x) != COEFF_MAX) { flint_printf("FAIL: COEFF_MIN"); fflush(stdout); flint_abort(); } fmpz_set_si(x, WORD_MIN); if (!COEFF_IS_MPZ(*x) || fmpz_get_si(x) != WORD_MIN) { flint_printf("FAIL: WORD_MIN"); fflush(stdout); flint_abort(); } fmpz_set_si(x, WORD_MIN); if (!COEFF_IS_MPZ(*x) || fmpz_get_si(x) != WORD_MIN) { flint_printf("FAIL: WORD_MAX"); fflush(stdout); flint_abort(); } fmpz_clear(x); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; slong b, c; b = z_randtest(state); fmpz_init(a); fmpz_set_si(a, b); c = fmpz_get_si(a); result = (b == c) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); flint_printf("b = %wd, c = %wd\n", b, c); fflush(stdout); flint_abort(); } fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_str.c000066400000000000000000000046341461254215100174400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" char * fmpz_get_str_bsplit_threaded(char * s, const fmpz_t f); TEST_FUNCTION_START(fmpz_get_str, state) { int i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; int base; char *str1, *str2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); base = (int) (n_randint(state, 61) + 2); fmpz_get_mpz(b, a); str1 = fmpz_get_str(NULL, base, a); str2 = mpz_get_str(NULL, base, b); if (strcmp(str1, str2)) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); flint_printf("base = %d\n", base); flint_printf("str1 = %s\n, str2 = %s\n", str1, str2); fflush(stdout); flint_abort(); } flint_free(str1); flint_free(str2); fmpz_clear(a); mpz_clear(b); } for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; int base; char *str1, *str2; flint_set_num_threads(1 + n_randint(state, 5)); fmpz_init(a); mpz_init(b); fmpz_randbits(a, state, 1000000 + n_randint(state, 1000000)); base = 10; fmpz_get_mpz(b, a); if (n_randint(state, 2)) str1 = fmpz_get_str(NULL, base, a); else str1 = fmpz_get_str_bsplit_threaded(NULL, a); str2 = mpz_get_str(NULL, base, b); if (strcmp(str1, str2)) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); flint_printf("base = %d\n", base); flint_printf("str1 = %s\n, str2 = %s\n", str1, str2); fflush(stdout); flint_abort(); } flint_free(str1); flint_free(str2); fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-get_ui.c000066400000000000000000000020041461254215100172320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_get_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; ulong b, c; b = n_randtest(state); fmpz_init(a); fmpz_set_ui(a, b); c = fmpz_get_ui(a); result = (b == c) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); flint_printf("b = %wd, c = %wd\n", b, c); fflush(stdout); flint_abort(); } fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-init2.c000066400000000000000000000016631461254215100170150ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_init2, state) { int i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; fmpz_init2(a, n_randint(state, 100)); fmpz_clear(a); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; fmpz_init(a); fmpz_randtest(a, state, SMALL_FMPZ_BITCOUNT_MAX); _fmpz_promote_val(a); _fmpz_demote_val(a); fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-init_set.c000066400000000000000000000033361461254215100176050ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_init_set, state) { int i, result; /* Small integers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_init(a); fmpz_randtest(a, state, SMALL_FMPZ_BITCOUNT_MAX); fmpz_init_set(b, a); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } /* Large integers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_init(a); fmpz_randtest(a, state, 2 * FLINT_BITS); fmpz_init_set(b, a); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-init_set_readonly.c000066400000000000000000000042121461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_init_set_readonly, state) { int i; /* Create some small fmpz integers, clear the mpz_t */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t z; *f = z_randint(state, COEFF_MAX + 1); mpz_init(z); fmpz_get_mpz(z, f); { fmpz_t g; fmpz_init_set_readonly(g, z); fmpz_clear_readonly(g); } mpz_clear(z); } /* Create some small fmpz integers, do *not* clear the mpz_t */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t z; *f = z_randint(state, COEFF_MAX + 1); mpz_init(z); fmpz_get_mpz(z, f); { fmpz_t g; fmpz_init_set_readonly(g, z); } mpz_clear(z); } /* Create some more fmpz integers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t z; fmpz_init(f); fmpz_randtest(f, state, 2 * FLINT_BITS); mpz_init(z); fmpz_get_mpz(z, f); { fmpz_t g, h; fmpz_init_set_readonly(g, z); fmpz_init(h); fmpz_set_mpz(h, z); if (!fmpz_equal(g, h) || !_fmpz_is_canonical(h)) { flint_printf("FAIL:\n\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("h = "), fmpz_print(h), flint_printf("\n"); gmp_printf("z = %Zd\n", z); } fmpz_clear_readonly(g); fmpz_clear(h); } fmpz_clear(f); mpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-init_set_ui.c000066400000000000000000000022441461254215100202770ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_init_set_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; ulong x = n_randtest(state); fmpz_init(a); fmpz_set_ui(a, x); fmpz_init_set_ui(b, x); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("x = %wu\n", x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-invmod.c000066400000000000000000000045001461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" /* Use the definition of GMP versions >= 6.0 */ int mpz_invert2(mpz_t a, const mpz_t b, const mpz_t c) { if (mpz_cmpabs_ui(c, 1) == 0) { mpz_set_ui(a, 0); return 1; } else return mpz_invert(a, b, c); } TEST_FUNCTION_START(fmpz_invmod, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int r1, r2; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { r1 = fmpz_invmod(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); r1 = fmpz_invmod(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); r1 = fmpz_invmod(c, c, b); } else { fmpz_set(c, b); r1 = fmpz_invmod(c, a, c); } r2 = mpz_invert2(f, d, e); fmpz_get_mpz(g, c); result = (r1 != 0 && r2 != 0 && (mpz_cmp(f, g) == 0)) || (r1 == 0 && r2 == 0); result = result && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, r1 = %d, r2 = %d\n", d, e, f, g, r1, r2); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_even.c000066400000000000000000000032021461254215100174070ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_even, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t g; fmpz_init(f); mpz_init(g); fmpz_randtest(f, state, 100); fmpz_get_mpz(g, f); result = (fmpz_is_even(f) == mpz_even_p(g)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); gmp_printf("g = %Zd\n", g); fflush(stdout); flint_abort(); } fmpz_clear(f); mpz_clear(g); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t g; fmpz_init(f); mpz_init(g); fmpz_randtest(f, state, 100); fmpz_get_mpz(g, f); result = (fmpz_is_odd(f) == mpz_odd_p(g)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); gmp_printf("g = %Zd\n", g); fflush(stdout); flint_abort(); } fmpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_perfect_power.c000066400000000000000000000067131461254215100213300ustar00rootroot00000000000000/* Copyright (C) 2009, 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_perfect_power, state) { int i, result; ulong bits, exp; fmpz_t root, d, n, n2, pow; fmpz_init(d); fmpz_init(n); fmpz_init(n2); fmpz_init(pow); fmpz_init(root); for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that perfect powers pass the test */ { bits = n_randint(state, 80) + 2; exp = n_randint(state, 10) + 2; fmpz_randtest(d, state, bits); fmpz_pow_ui(n, d, exp); result = fmpz_is_perfect_power(root, n); if (result == 0) { flint_printf("FAIL:\n"); fmpz_print(n); flint_printf(" is declared not a perfect power\n"); fflush(stdout); flint_abort(); } fmpz_pow_ui(pow, root, result); if (!fmpz_equal(pow, n)) { flint_printf("FAIL:\n"); fmpz_print(root); flint_printf("^%d != ", result); fmpz_print(n); fflush(stdout); flint_abort(); } } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that non perfect powers fail */ { mpz_t d_m; mpz_init(d_m); do { bits = n_randint(state, 1000) + 1; fmpz_randtest(n, state, bits); fmpz_get_mpz(d_m, n); } while (mpz_perfect_power_p(d_m)); result = !fmpz_is_perfect_power(root, n); if (!result) { flint_printf("FAIL:\n"); fmpz_print(n); flint_printf(" is declared a perfect power\n"); fflush(stdout); flint_abort(); } mpz_clear(d_m); } for (i = 0; i < 100 * flint_test_multiplier(); i++) /* aliasing test, perfect powers */ { bits = n_randint(state, 80) + 2; exp = n_randint(state, 10) + 2; fmpz_randtest(d, state, bits); fmpz_pow_ui(n, d, exp); fmpz_set(n2, n); result = fmpz_is_perfect_power(n, n); if (result == 0) { flint_printf("FAIL:\n"); fmpz_print(n2); flint_printf(" is declared not a perfect power\n"); fflush(stdout); flint_abort(); } fmpz_pow_ui(pow, n, result); if (!fmpz_equal(pow, n2)) { flint_printf("FAIL:\n"); fmpz_print(n); flint_printf("^%d != ", result); fmpz_print(n2); fflush(stdout); flint_abort(); } } for (i = 0; i < 100 * flint_test_multiplier(); i++) /* aliasing test, non perfect powers */ { mpz_t d_m; mpz_init(d_m); do { bits = n_randint(state, 1000) + 1; fmpz_randtest(n, state, bits); fmpz_get_mpz(d_m, n); } while (mpz_perfect_power_p(d_m)); result = !fmpz_is_perfect_power(n, n); if (!result) { flint_printf("FAIL:\n"); fmpz_print(n2); flint_printf(" is declared a perfect power\n"); fflush(stdout); flint_abort(); } mpz_clear(d_m); } fmpz_clear(n); fmpz_clear(n2); fmpz_clear(d); fmpz_clear(pow); fmpz_clear(root); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_prime.c000066400000000000000000000072511461254215100175760ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" /* Composite strong pseudoprimes from https://oeis.org/A014233 and https://doi.org/10.1090/mcom/3134 */ static const char * composites_is_prime[] = { "2047", "1373653", "25326001", "3215031751", "2152302898747", "3474749660383", "341550071728321", "230245660726188031", "3825123056546413051", "7395010240794120709381", "164280218643672633986221", "318665857834031151167461", "360681321802296925566181", "552727880697763694556181", "667636712015520329618581", "2995741773170734841812261", "3317044064679887385961981", "3404730287403079539471001", NULL, }; TEST_FUNCTION_START(fmpz_is_prime, state) { int i, result, r1; /* test table of composites */ for (i = 0; composites_is_prime[i] != NULL; i++) { fmpz_t n; fmpz_init(n); fmpz_set_str(n, composites_is_prime[i], 10); r1 = fmpz_is_prime(n); if (r1 != 0) { flint_printf("FAIL:\n"); fmpz_print(n); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); } /* test primes always pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, F; fmpz_init(p); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 160) + 2); fmpz_abs(p, p); } while (!fmpz_is_probabprime(p)); r1 = fmpz_is_prime(p); result = (r1 == 1 || r1 == -1); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(F); } /* test composites never pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, a, F; fmpz_init(p); fmpz_init(a); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 80) + 2); } while (fmpz_cmp_ui(p, 2) < 0); do { fmpz_randbits(a, state, n_randint(state, 80) + 2); } while (fmpz_cmp_ui(a, 2) < 0); fmpz_mul(p, p, a); r1 = fmpz_is_prime(p); result = (r1 == 0 || r1 == -1); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(a); fmpz_clear(F); } /* test issue 345 */ { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, 13567); fmpz_pow_ui(t, t, 145); if (fmpz_is_prime(t) != 0) { flint_printf("FAIL:\n"); fmpz_print(t); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(t); } /* regression test */ { fmpz_t p; fmpz_init_set_ui(p, 13567); fmpz_pow_ui(p, p, 145); result = fmpz_is_prime(p); if (result) { printf("FAIL\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_prime_morrison.c000066400000000000000000000030111461254215100215140ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "nmod_vec.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_prime_morrison, state) { int i, result; for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_t p, F, R; mp_ptr pp1; slong num_pp1; double logd; ulong limit; fmpz_init(p); fmpz_init(F); fmpz_init(R); do { fmpz_randbits(p, state, n_randint(state, 330) + 2); fmpz_abs(p, p); } while (!fmpz_is_probabprime(p) || fmpz_cmp_ui(p, 2) == 0); logd = log(fmpz_get_d(p)); limit = (ulong) (logd*logd*logd/10.0) + 2; pp1 = _nmod_vec_init((ulong) logd + 2); _fmpz_np1_trial_factors(p, pp1, &num_pp1, limit); result = fmpz_is_prime_morrison(F, R, p, pp1, num_pp1); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } _nmod_vec_clear(pp1); fmpz_clear(p); fmpz_clear(F); fmpz_clear(R); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_prime_pocklington.c000066400000000000000000000030171461254215100222010ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "nmod_vec.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_prime_pocklington, state) { int i, result; for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_t p, F, R; mp_ptr pm1; slong num_pm1; ulong limit; double logd; fmpz_init(p); fmpz_init(F); fmpz_init(R); do { fmpz_randbits(p, state, n_randint(state, 330) + 2); fmpz_abs(p, p); } while (!fmpz_is_probabprime(p) || fmpz_cmp_ui(p, 2) == 0); logd = log(fmpz_get_d(p)); limit = (ulong) (logd*logd*logd/10.0) + 2; pm1 = _nmod_vec_init((ulong) logd + 2); _fmpz_nm1_trial_factors(p, pm1, &num_pm1, limit); result = fmpz_is_prime_pocklington(F, R, p, pm1, num_pm1); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } _nmod_vec_clear(pm1); fmpz_clear(p); fmpz_clear(F); fmpz_clear(R); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_prime_pseudosquare.c000066400000000000000000000021301461254215100223650ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_prime_pseudosquare, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { fmpz_t p; int r1, r2; fmpz_init(p); fmpz_randtest_unsigned(p, state, n_randint(state, 94) + 1); r1 = fmpz_is_probabprime(p); r2 = fmpz_is_prime_pseudosquare(p); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); flint_printf("r1 = %d, r2 = %d\n", r1, r2); fflush(stdout); flint_abort(); } fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_probabprime_BPSW.c000066400000000000000000000035761461254215100216250ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_probabprime_BPSW, state) { int i, result; /* test primes always pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, F; fmpz_init(p); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 330) + 2); fmpz_abs(p, p); } while (!fmpz_is_probabprime(p) || fmpz_cmp_ui(p, 2) == 0); result = fmpz_is_probabprime_BPSW(p); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(F); } /* test composites never pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, a, F; fmpz_init(p); fmpz_init(a); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(p, 2) < 0); do { fmpz_randbits(a, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(a, 2) < 0); fmpz_mul(p, p, a); result = !fmpz_is_probabprime_BPSW(p); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(a); fmpz_clear(F); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_probabprime_lucas.c000066400000000000000000000036711461254215100221550ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_probabprime_lucas, state) { int i, result, count = 0; /* test primes always pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, F; fmpz_init(p); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 330) + 2); fmpz_abs(p, p); } while (!fmpz_is_probabprime(p) || fmpz_cmp_ui(p, 2) == 0); result = fmpz_is_probabprime_lucas(p); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(F); } /* test composites rarely pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, a, F; fmpz_init(p); fmpz_init(a); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(p, 2) < 0); do { fmpz_randbits(a, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(a, 2) < 0); fmpz_mul(p, p, a); if (fmpz_is_probabprime_lucas(p)) count++; fmpz_clear(p); fmpz_clear(a); fmpz_clear(F); } result = (count < flint_test_multiplier()); if (!result) { flint_printf("FAIL:\n"); flint_printf("count = %ld\n", count); fflush(stdout); flint_abort(); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_square.c000066400000000000000000000022271461254215100177600ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_is_square, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; int r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); if (n_randint(state, 2) == 0) fmpz_mul(a, a, a); fmpz_get_mpz(b, a); r1 = fmpz_is_square(a); r2 = mpz_perfect_square_p(b); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-is_strong_probabprime.c000066400000000000000000000100321461254215100223470ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" /* Composite strong pseudoprimes from https://oeis.org/A014233 */ static const char * composites_is_strong_probabprime[] = { "2047", "1373653", "25326001", "3215031751", "2152302898747", "3474749660383", "341550071728321", "341550071728321", "3825123056546413051", "3825123056546413051", "3825123056546413051", "318665857834031151167461", "3317044064679887385961981", NULL, }; TEST_FUNCTION_START(fmpz_is_strong_probabprime, state) { int i, result, count = 0; /* test table */ { for (i = 0; composites_is_strong_probabprime[i] != NULL; i++) { int j; fmpz_t n, a; fmpz_init(n); fmpz_init(a); fmpz_set_str(n, composites_is_strong_probabprime[i], 10); for (j = 0; j <= i; j++) { fmpz_set_ui(a, n_nth_prime(j + 1)); if (!fmpz_is_strong_probabprime(n, a)) { flint_printf("FAIL (composite expected to pass test):\n"); fmpz_print(n); printf("\n"); fmpz_print(a); printf("\n"); fflush(stdout); flint_abort(); } } fmpz_set_ui(a, n_nth_prime(i + 2 + (i == 6) + 2*(i==8) + (i==9)) /* because of repeated entries */ ); if (fmpz_is_strong_probabprime(n, a)) { flint_printf("FAIL (composite expected to fail test):\n"); fmpz_print(n); printf("\n"); fmpz_print(a); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_clear(a); } } /* test primes always pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, b, F; fmpz_init(p); fmpz_init(b); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 330) + 2); fmpz_abs(p, p); } while (!fmpz_is_probabprime(p) || fmpz_cmp_ui(p, 2) == 0); do { fmpz_randbits(b, state, n_randint(state, 100) + 1); fmpz_abs(b, b); } while (fmpz_is_zero(b) || fmpz_is_one(b)); result = fmpz_is_strong_probabprime(p, b); if (!result) { flint_printf("FAIL:\n"); fmpz_print(p); printf("\n"); fmpz_print(b); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_clear(b); fmpz_clear(F); } /* test composites rarely pass */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, a, b, F; fmpz_init(p); fmpz_init(a); fmpz_init(b); fmpz_init(F); do { fmpz_randbits(p, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(p, 2) < 0); do { fmpz_randbits(a, state, n_randint(state, 100) + 2); } while (fmpz_cmp_ui(a, 2) < 0); do { fmpz_randbits(b, state, n_randint(state, 100) + 1); fmpz_abs(b, b); } while (fmpz_cmp_ui(b, 2) < 0); fmpz_mul(p, p, a); if (fmpz_is_strong_probabprime(p, b)) count++; fmpz_clear(p); fmpz_clear(a); fmpz_clear(b); fmpz_clear(F); } result = (count < flint_test_multiplier()); if (!result) { flint_printf("FAIL:\n"); flint_printf("count = %ld\n", count); fflush(stdout); flint_abort(); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-jacobi.c000066400000000000000000000024611461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_jacobi, state) { slong i, j; for (i = 0; i < 3000 * flint_test_multiplier(); i++) { fmpz_t a, n; mpz_t aa, nn; fmpz_init(a); fmpz_init(n); mpz_init(aa); mpz_init(nn); for (j = 0; j < 100; j++) { fmpz_randtest(a, state, 150); fmpz_randtest_unsigned(n, state, 150); fmpz_setbit(n, 0); fmpz_get_mpz(aa, a); fmpz_get_mpz(nn, n); if (mpz_jacobi(aa, nn) != fmpz_jacobi(a, n)) { flint_printf("FAIL:\n"); gmp_printf("a = %Zd, n = %Zd\n", aa, nn); fflush(stdout); flint_abort(); } } fmpz_clear(a); fmpz_clear(n); mpz_clear(aa); mpz_clear(nn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-kronecker.c000066400000000000000000000024211461254215100177440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_kronecker, state) { slong i, j; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, n; mpz_t aa, nn; fmpz_init(a); fmpz_init(n); mpz_init(aa); mpz_init(nn); for (j = 0; j < 100; j++) { fmpz_randtest(a, state, 150); fmpz_randtest(n, state, 150); fmpz_get_mpz(aa, a); fmpz_get_mpz(nn, n); if (mpz_kronecker(aa, nn) != fmpz_kronecker(a, n)) { flint_printf("FAIL:\n"); gmp_printf("a = %Zd, n = %Zd\n", aa, nn); fflush(stdout); flint_abort(); } } fmpz_clear(a); fmpz_clear(n); mpz_clear(aa); mpz_clear(nn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-lcm.c000066400000000000000000000037531461254215100165450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_lcm, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_randtest(c, state, 200); fmpz_mul(a, a, c); fmpz_mul(b, b, c); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_lcm(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_lcm(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_lcm(c, c, b); } else { fmpz_set(c, b); fmpz_lcm(c, a, c); } mpz_lcm(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mod.c000066400000000000000000000036621461254215100165500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mod, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_mod(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_mod(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_mod(c, c, b); } else { fmpz_set(c, b); fmpz_mod(c, a, c); } mpz_mod(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mod_ui.c000066400000000000000000000031671461254215100172450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mod_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x, r1, r2; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randtest_not_zero(state); if (n_randint(state, 2)) { r1 = fmpz_mod_ui(b, a, x); } else { fmpz_set(b, a); r1 = fmpz_mod_ui(b, b, x); } r2 = flint_mpz_fdiv_r_ui(e, d, x); fmpz_get_mpz(f, b); result = ((mpz_cmp(e, f) == 0) && (r1 == r2)) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, x = %wu, r1 = %wu, r2 = %wu\n", d, e, f, x, r1, r2); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-moebius_mu.c000066400000000000000000000034401461254215100201270ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" #ifndef check #define check check /* Defined in t-abs_fits_ui.c, t-fits_si.c and t-moebius_mu.c */ static void check(fmpz_t input, int output, int expected) { if (output != expected) { printf("FAIL:\n\n" "input = "), fmpz_print(input), printf("\n" "output = %d, expected = %d\n", output, expected); fflush(stdout); flint_abort(); } } #endif TEST_FUNCTION_START(fmpz_moebius_mu, state) { fmpz_t x; ulong p; slong i, j, k, l; fmpz_init(x); for (i = -1000; i < 1000; i++) { fmpz_set_si(x, i); check(x, fmpz_moebius_mu(x), n_moebius_mu(FLINT_ABS(i))); } for (i = 0; i < 1000; i++) { fmpz_set_ui(x, 1); /* Product of some primes */ k = n_randtest(state) % 10; l = n_randtest(state) % 10; for (j = 0; j < k; j++) { l += (n_randtest(state) % 10) + 1; fmpz_mul_ui(x, x, n_nth_prime(l+1)); } check(x, fmpz_moebius_mu(x), (k % 2 ? -1 : 1)); fmpz_neg(x, x); check(x, fmpz_moebius_mu(x), (k % 2 ? -1 : 1)); fmpz_abs(x, x); /* No longer square-free */ p = n_nth_prime(n_randtest(state) % 100 + 1); fmpz_mul_ui(x, x, p*p); check(x, fmpz_moebius_mu(x), 0); } fmpz_clear(x); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mpz_init_set_readonly.c000066400000000000000000000035621461254215100223710ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "long_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mpz_init_set_readonly, state) { int i; /* Create some small fmpz integers, clear the mpz_t */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t z; *f = z_randint(state, COEFF_MAX + 1); flint_mpz_init_set_readonly(z, f); flint_mpz_clear_readonly(z); } /* Create some large fmpz integers, do not clear the mpz_t */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t z; fmpz_init(f); fmpz_randtest(f, state, 2 * FLINT_BITS); if (COEFF_IS_MPZ(*f)) { flint_mpz_init_set_readonly(z, f); } fmpz_clear(f); } /* Create some more fmpz integers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f, g; mpz_t z; fmpz_init(f); fmpz_init(g); fmpz_randtest(f, state, 2 * FLINT_BITS); flint_mpz_init_set_readonly(z, f); fmpz_set_mpz(g, z); if (!fmpz_equal(f, g)) { flint_printf("FAIL:\n\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); gmp_printf("z = %Zd\n", z); } flint_mpz_clear_readonly(z); fmpz_clear(f); fmpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mul.c000066400000000000000000000035771461254215100165730ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mul, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_mul(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_mul(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_mul(c, c, b); } else { fmpz_set(c, b); fmpz_mul(c, a, c); } mpz_mul(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mul2_uiui.c000066400000000000000000000032371461254215100177010ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mul2_uiui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x, y; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randtest(state); y = n_randtest(state); if (n_randint(state, 2)) { fmpz_mul2_uiui(b, a, x, y); } else { fmpz_set(b, a); fmpz_mul2_uiui(b, b, x, y); } flint_mpz_mul_ui(e, d, x); flint_mpz_mul_ui(e, e, y); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu, y = %Mu\n", d, e, f, x, y); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mul_2exp.c000066400000000000000000000027701461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mul_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_mul_2exp(b, a, x); } else { fmpz_set(b, a); fmpz_mul_2exp(b, b, x); } mpz_mul_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mul_si.c000066400000000000000000000030051461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_mul_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; slong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = z_randtest(state); if (n_randint(state, 2)) { fmpz_mul_si(b, a, x); } else { fmpz_set(b, a); fmpz_mul_si(b, b, x); } flint_mpz_mul_si(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Md\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mul_si_tdiv_q_2exp.c000066400000000000000000000033301461254215100215550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_mul_si_tdiv_q_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; slong x; ulong exp; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = z_randtest(state); exp = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_mul_si_tdiv_q_2exp(b, a, x, exp); } else { fmpz_set(b, a); fmpz_mul_si_tdiv_q_2exp(b, b, x, exp); } flint_mpz_mul_si(e, d, x); mpz_tdiv_q_2exp(e, e, exp); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Md, exp = %Mu\n", d, e, f, x, exp); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mul_tdiv_q_2exp.c000066400000000000000000000041641461254215100210700ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mul_tdiv_q_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; ulong exp; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); exp = n_randint(state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_mul_tdiv_q_2exp(c, a, b, exp); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_mul_tdiv_q_2exp(c, a, a, exp); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_mul_tdiv_q_2exp(c, c, b, exp); } else { fmpz_set(c, b); fmpz_mul_tdiv_q_2exp(c, a, c, exp); } mpz_mul(f, d, e); mpz_tdiv_q_2exp(f, f, exp); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd, exp = %Mu\n", d, e, f, g, exp); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-mul_ui.c000066400000000000000000000030061461254215100172530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_mul_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randtest(state); if (n_randint(state, 2)) { fmpz_mul_ui(b, a, x); } else { fmpz_set(b, a); fmpz_mul_ui(b, b, x); } flint_mpz_mul_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-multi_CRT_multi_mod.c000066400000000000000000000241751461254215100217060ustar00rootroot00000000000000/* Copyright (C) 2019-2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_multi_CRT_multi_mod, state) { slong i, j, k; /* test internal interface */ { fmpz_multi_CRT_t P; fmpz * moduli, * inputs, * outputs; slong moduli_count = 1000; moduli = _fmpz_vec_init(moduli_count); inputs = _fmpz_vec_init(moduli_count); outputs = _fmpz_vec_init(moduli_count); for (k = 0; k < moduli_count; k++) { fmpz_set_ui(moduli + k, n_nth_prime(k + 2)); fmpz_sub_ui(inputs + k, moduli + k, 1); } fmpz_multi_CRT_init(P); if (!fmpz_multi_CRT_precompute(P, moduli, moduli_count)) { flint_printf("FAIL: Check internal interface precompute\n"); fflush(stdout); flint_abort(); } FLINT_ASSERT(P->localsize <= moduli_count); for (k = 0; k < 1; k++) { _fmpz_multi_CRT_precomp(outputs, P, inputs, 1); } _fmpz_vec_clear(moduli, moduli_count); _fmpz_vec_clear(inputs, moduli_count); _fmpz_vec_clear(outputs, moduli_count); fmpz_multi_CRT_clear(P); } for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_multi_CRT_t P; fmpz_multi_mod_t M; fmpz_t t, p; slong moduli_count; flint_bitcnt_t moduli_bits; fmpz * moduli, * inputs, * values; fmpz_t output; fmpz_init(t); fmpz_init(p); fmpz_init(output); fmpz_multi_CRT_init(P); fmpz_multi_mod_init(M); for (j = 0; j < 5; j++) { moduli_count = n_randint(state, 40) + 1; moduli = _fmpz_vec_init(moduli_count); inputs = _fmpz_vec_init(moduli_count); values = _fmpz_vec_init(moduli_count); for (k = 0; k < moduli_count; k++) { moduli_bits = n_randint(state, 150) + 1; fmpz_init(moduli + k); fmpz_init(inputs + k); fmpz_randtest_unsigned(moduli + k, state, moduli_bits); fmpz_randtest(inputs + k, state, moduli_bits); if (n_randint(state, 2)) fmpz_nextprime(moduli + k, moduli + k, 1); } if (fmpz_multi_CRT_precompute(P, moduli, moduli_count)) { int sign = 1; if (!fmpz_multi_mod_precompute(M, moduli, moduli_count)) { flint_printf("FAIL: Check multi mod precompute\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_multi_CRT_precomp(output, P, inputs, sign); fmpz_multi_mod_precomp(values, M, output, sign); fmpz_one(p); for (k = 0; k < moduli_count; k++) { fmpz_mul(p, p, moduli + k); fmpz_sub(t, output, inputs + k); if (!fmpz_divisible(t, moduli + k)) { flint_printf("FAIL: Check output remainder\n"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } fmpz_sub(t, inputs + k, values + k); if (!fmpz_divisible(t, moduli + k)) { flint_printf("FAIL: Check multi mod\n"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } if (sign ? (fmpz_cmp2abs(moduli + k, values + k) < 0) : (fmpz_cmp(values + k, moduli + k) >= 0 || fmpz_sgn(values + k) < 0)) { flint_printf("FAIL: Check mod output size\n"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } if (sign ? (fmpz_cmp2abs(p, output) < 0) : (fmpz_cmp(output, p) >= 0 || fmpz_sgn(output) < 0)) { flint_printf("FAIL: Check CRT output size\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_abs(p, p); fmpz_add(p, p, p); fmpz_add_ui(p, p, 3); fmpz_randtest_mod_signed(output, state, p); fmpz_multi_mod_precomp(values, M, output, sign); fmpz_one(p); for (k = 0; k < moduli_count; k++) { fmpz_sub(t, output, values + k); if (!fmpz_divisible(t, moduli + k)) { flint_printf("FAIL: Check multi mod 2\n"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } } else { /* check if it was ok to fail on these moduli */ int ok = 0; fmpz_one(p); for (k = 0; !ok && k < moduli_count; k++) { fmpz_mul(p, p, moduli + k); ok |= (fmpz_is_zero(moduli + k) || fmpz_is_pm1(moduli + k)); } for (k = 0; !ok && k < moduli_count; k++) { fmpz_divexact(t, p, moduli + k); fmpz_gcd(t, t, moduli + k); ok |= (fmpz_cmp_ui(t, 1) > 0); } if (!ok) { flint_printf("FAIL: Check flat CRT failure\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } _fmpz_vec_clear(moduli, moduli_count); _fmpz_vec_clear(inputs, moduli_count); _fmpz_vec_clear(values, moduli_count); } fmpz_clear(t); fmpz_clear(p); fmpz_clear(output); fmpz_multi_CRT_clear(P); fmpz_multi_mod_clear(M); } /* test lazy interface */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_t t, p; slong moduli_count; flint_bitcnt_t moduli_bits; fmpz * moduli, * inputs; fmpz_t output; fmpz_init(t); fmpz_init(p); fmpz_init(output); for (j = 0; j < 4; j++) { moduli_bits = n_randint(state, 100) + 1; moduli_count = n_randint(state, 50) + 1; moduli = (fmpz *) flint_malloc(moduli_count*sizeof(fmpz)); inputs = (fmpz *) flint_malloc(moduli_count*sizeof(fmpz)); for (k = 0; k < moduli_count; k++) { fmpz_init(moduli + k); fmpz_init(inputs + k); fmpz_randtest_unsigned(moduli + k, state, moduli_bits); fmpz_randtest(inputs + k, state, moduli_bits); } if (fmpz_multi_CRT(output, moduli, inputs, moduli_count, 1)) { fmpz_one(p); for (k = 0; k < moduli_count; k++) { fmpz_mul(p, p, moduli + k); fmpz_sub(t, output, inputs + k); if (!fmpz_divisible(t, moduli + k)) { printf("FAIL\n"); flint_printf("Check remainder lazy " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } fmpz_add(output, output, output); if (fmpz_cmpabs(output, p) > 0) { printf("FAIL\n"); flint_printf("Check output size lazy " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } else { /* check if it was ok to fail on these moduli */ int ok = 0; fmpz_one(p); for (k = 0; !ok && k < moduli_count; k++) { fmpz_mul(p, p, moduli + k); if (fmpz_is_zero(moduli + k) || fmpz_is_pm1(moduli + k)) { ok = 1; } } for (k = 0; !ok && k < moduli_count; k++) { fmpz_divexact(t, p, moduli + k); fmpz_gcd(t, t, moduli + k); if (fmpz_cmp_ui(t, 1) > 0) { ok = 1; } } if (!ok) { printf("FAIL\n"); flint_printf("Check lazy CRT failure i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < moduli_count; k++) { fmpz_clear(moduli + k); fmpz_clear(inputs + k); } flint_free(moduli); flint_free(inputs); } fmpz_clear(t); fmpz_clear(p); fmpz_clear(output); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-multi_CRT_ui.c000066400000000000000000000065251461254215100203310ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_multi_CRT_ui, state) { fmpz_t input, temp, prod; mp_limb_t * output; slong i, j, k; flint_bitcnt_t bits1, bits2, bits; mp_limb_t * primes; fmpz * primes2; slong num_primes; fmpz_comb_t comb; fmpz_comb_temp_t comb_temp; for (i = 0; i < 100 * flint_test_multiplier(); i++) { int sign = n_randint(state, 2); num_primes = 1 + n_randint(state, 400); fmpz_init(temp); fmpz_init(input); fmpz_init(prod); output = FLINT_ARRAY_ALLOC(num_primes, mp_limb_t); primes = FLINT_ARRAY_ALLOC(num_primes, mp_limb_t); primes2 = _fmpz_vec_init(num_primes); try_again: bits1 = n_randint(state, FLINT_BITS*3/4) + FLINT_BITS/4; bits2 = n_randint(state, FLINT_BITS*3/4) + FLINT_BITS/4; if (bits1 > bits2) FLINT_SWAP(ulong, bits1, bits2); fmpz_one(prod); for (j = 0; j < num_primes; j++) { bits = bits1 + n_randint(state, bits2 - bits1 + 1); primes[j] = n_randbits(state, bits); primes[j] = n_nextprime(primes[j], 1); fmpz_mul_ui(prod, prod, primes[j]); fmpz_set_ui(primes2 + j, primes[j]); } _fmpz_vec_sort(primes2, num_primes); for (j = 1; j < num_primes; j++) if (fmpz_equal(primes2 + j, primes2 + j - 1)) goto try_again; fmpz_randtest(input, state, n_randint(state, 300) + 1); fmpz_comb_init(comb, primes, num_primes); fmpz_comb_temp_init(comb_temp, comb); fmpz_multi_mod_ui(output, input, comb, comb_temp); fmpz_multi_CRT_ui(temp, output, comb, comb_temp, sign); fmpz_comb_temp_clear(comb_temp); fmpz_comb_clear(comb); if (sign ? fmpz_cmp2abs(prod, temp) < 0 : (fmpz_sgn(temp) < 0 || fmpz_cmp(prod, temp) <= 0)) { flint_printf("FAIL: check crt output range\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_sub(temp, temp, input); if (!fmpz_divisible(temp, prod)) { flint_printf("FAIL: check crt modulo product of primes\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } for (k = 0; k < num_primes; k++) { if (output[k] != fmpz_fdiv_ui(input, primes[k])) { flint_printf("FAIL: check multi_mod_ui output"); flint_printf("i = %wd, k = %wd\n", i, k); fflush(stdout); flint_abort(); } } fmpz_clear(temp); fmpz_clear(input); fmpz_clear(prod); flint_free(output); flint_free(primes); _fmpz_vec_clear(primes2, num_primes); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-ndiv_qr.c000066400000000000000000000115071461254215100174300ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_ndiv_qr, state) { slong i; int result; /* Check that a = b * nquo + nrem, and that nrem is smallest */ for (i = 0; i < 30000 * flint_test_multiplier(); i++) { fmpz_t tmp; fmpz_t a, b; fmpz_t A, B; fmpz_t nquo, nrem; fmpz_t fquo, frem; fmpz_t cquo, crem; fmpz_init(tmp); fmpz_init(a); fmpz_init(b); fmpz_init(A); fmpz_init(B); fmpz_init(nquo); fmpz_init(nrem); fmpz_init(fquo); fmpz_init(frem); fmpz_init(cquo); fmpz_init(crem); fmpz_randbits(a, state, n_randint(state, 200)); fmpz_randbits(b, state, 1 + n_randint(state, 200)); fmpz_ndiv_qr(nquo, nrem, a, b); { fmpz_set(A, a); fmpz_set(B, b); fmpz_ndiv_qr(A, B, A, B); if (!fmpz_equal(A, nquo) || !fmpz_equal(B, nrem)) { flint_printf("FAIL: check (A, B, A, B) aliasing\n"); fflush(stdout); flint_abort(); } fmpz_set(A, a); fmpz_set(B, b); fmpz_ndiv_qr(B, A, A, B); if (!fmpz_equal(B, nquo) || !fmpz_equal(A, nrem)) { flint_printf("FAIL: check (B, A, A, B) aliasing\n"); fflush(stdout); flint_abort(); } } fmpz_fdiv_qr(fquo, frem, a, b); fmpz_cdiv_qr(cquo, crem, a, b); fmpz_set(tmp, nrem); fmpz_addmul(tmp, b, nquo); result = ( fmpz_cmp(tmp, a) == 0 && fmpz_cmpabs(nrem, frem) <= 0 && fmpz_cmpabs(nrem, crem) <= 0) && _fmpz_is_canonical(nquo) && _fmpz_is_canonical(nrem); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("q = "); fmpz_print(nquo); flint_printf("\n"); flint_printf("r = "); fmpz_print(nrem); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(tmp); fmpz_clear(a); fmpz_clear(b); fmpz_clear(A); fmpz_clear(B); fmpz_clear(nquo); fmpz_clear(nrem); fmpz_clear(fquo); fmpz_clear(frem); fmpz_clear(cquo); fmpz_clear(crem); } /* Check that it rounds towards zero for ties */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t max; fmpz_t tmp; fmpz_t a, b; fmpz_t nquo, nrem; fmpz_t tquo, trem; ulong multiplier; fmpz_init(max); fmpz_init(tmp); fmpz_init(a); fmpz_init(b); fmpz_init(nquo); fmpz_init(nrem); fmpz_init(tquo); fmpz_init(trem); fmpz_set_d_2exp(max, 1.0, 2*FLINT_BITS); fmpz_randm(a, state, max); fmpz_set(b, a); /* a -> odd * a, b -> 2 * b */ /* Thus a // b = odd // 2 and q should have to round down */ multiplier = n_randint(state, 50); multiplier += (multiplier % 2 == 0); fmpz_mul_ui(a, a, multiplier); fmpz_mul_ui(b, b, 2); if (n_randint(state, 2)) fmpz_neg(a, a); if (n_randint(state, 2)) fmpz_neg(b, b); if (fmpz_is_zero(b)) fmpz_one(b); fmpz_ndiv_qr(nquo, nrem, a, b); fmpz_tdiv_qr(tquo, trem, a, b); fmpz_set(tmp, nrem); fmpz_addmul(tmp, b, nquo); result = ( fmpz_cmp(tmp, a) == 0 && fmpz_cmp(nquo, tquo) == 0 && fmpz_cmp(nrem, trem) == 0) && _fmpz_is_canonical(nquo) && _fmpz_is_canonical(nrem); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("q = "); fmpz_print(nquo); flint_printf("\n"); flint_printf("r = "); fmpz_print(nrem); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(max); fmpz_clear(tmp); fmpz_clear(a); fmpz_clear(b); fmpz_clear(nquo); fmpz_clear(nrem); fmpz_clear(tquo); fmpz_clear(trem); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-neg.c000066400000000000000000000025361461254215100165410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_neg, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_get_mpz(c, a); if (n_randint(state, 2)) { fmpz_neg(b, a); } else { fmpz_set(b, a); fmpz_neg(b, b); } mpz_neg(c, c); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-neg_ui.c000066400000000000000000000023161461254215100172320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_neg_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; ulong c; c = n_randtest(state); fmpz_init(a); fmpz_init(b); fmpz_set_ui(a, c); fmpz_neg(a, a); fmpz_neg_ui(b, c); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); flint_printf("c = %wu\n", c); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-neg_uiui.c000066400000000000000000000025641461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_neg_uiui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; ulong hi, lo; hi = n_randtest(state); lo = n_randtest(state); fmpz_init(a); fmpz_init(b); fmpz_set_ui(a, hi); fmpz_mul_2exp(a, a, FLINT_BITS); fmpz_add_ui(a, a, lo); fmpz_neg(a, a); fmpz_neg_uiui(b, hi, lo); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); flint_printf("hi = %wu\n", hi); flint_printf("lo = %wu\n", lo); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-nextprime.c000066400000000000000000000050551461254215100200020ustar00rootroot00000000000000/* Authored 2015 by Daniel S. Roche; US Government work in the public domain. This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" const char * const manual_tests[] = { /* anything <= 1 should produce 2 */ "1", "2", "0", "2", "-13842090335966649306", "2", "-819856806963901485525117166411138935256434837055304839519773", "2", /* some small checks */ "2", "3", "3", "5", "4", "5", /* around the 32-bit boundary */ "2147483630", "2147483647", "2147483648", "2147483659", "4294967279", "4294967291", "4294967296", "4294967311", /* around the 64-bit boundary */ "9223372036854775643", "9223372036854775783", "9223372036854775808", "9223372036854775837", "18446744073709551533", "18446744073709551557", "18446744073709551616", "18446744073709551629", "\0" }; TEST_FUNCTION_START(fmpz_nextprime, state) { int i; for (i=0; manual_tests[i][0]; i += 2) { fmpz_t start, expected, actual; fmpz_init(start); fmpz_init(expected); fmpz_init(actual); fmpz_set_str(start, manual_tests[i], 10); fmpz_nextprime(actual, start, 0); fmpz_set_str(expected, manual_tests[i+1], 10); if (!fmpz_equal(actual, expected) || !_fmpz_is_canonical(actual)) { flint_printf("FAIL:\n"); fmpz_print(start); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(start); fmpz_clear(expected); fmpz_clear(actual); } for (i=0; i < 100 * flint_test_multiplier(); ++i) { fmpz_t start, res, iter; fmpz_init(start); fmpz_init(res); fmpz_init(iter); fmpz_randtest_unsigned(start, state, 160); fmpz_nextprime(res, start, 0); fmpz_set(iter, start); do fmpz_add_ui(iter, iter, UWORD(1)); while (!fmpz_is_probabprime(iter)); if (!fmpz_equal(res, iter) || !_fmpz_is_canonical(res)) { flint_printf("FAIL:\n"); fmpz_print(start); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(start); fmpz_clear(res); fmpz_clear(iter); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-or.c000066400000000000000000000036161461254215100164100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_or, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_or(c, a, b); } else if (aliasing == 1) { fmpz_set(c, a); fmpz_or(c, c, b); } else if (aliasing == 2) { fmpz_set(c, b); fmpz_or(c, a, c); } else if (aliasing == 3) { fmpz_set(c, a); fmpz_or(c, a, a); mpz_set(e, d); } mpz_ior(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-out_inp_raw.c000066400000000000000000000075431461254215100203210ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Qingwen GUAN This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) # include # include # include #endif #include "test_helpers.h" #include "fmpz.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) TEST_FUNCTION_START(fmpz_out_inp_raw, state) { int i, j, n = 10000, result; FILE *in, *out; int fd[2]; pid_t childpid; fflush(stdout); /* Ensure buffer does not flow into child process */ /* Randomise n integers, write to and read from a pipe */ { fmpz *a; a = flint_calloc(n, sizeof(fmpz)); for (i = 0; i < n; i++) fmpz_randtest(a + i, state, 200); if (pipe(fd)) { printf("FAIL:\n"); printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { printf("FAIL:\n"); printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { size_t r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { printf("FAIL:\n"); printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } for (j = 0; j < n; j++) { r = fmpz_out_raw(out, a + j); if (r <= 0) { printf("FAIL:\n"); printf("Write error.\n"); fflush(stdout); flint_abort(); } } fclose(out); for (i = 0; i < n; ++i) fmpz_clear(a + i); flint_free(a); exit(0); } else /* Parent process */ { size_t r; fmpz_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { printf("FAIL:\n"); printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_init(t); i = 0; while ( (r = fmpz_inp_raw(t, in)) != 0 ) { result = fmpz_equal(t, a + i) && _fmpz_is_canonical(t); if (!result) { printf("FAIL:\n"); printf("a[i] = "), fmpz_print(a + i), printf("\n"); printf("t = "), fmpz_print(t), printf("\n"); fflush(stdout); flint_abort(); } ++i; } fmpz_clear(t); fclose(in); waitpid(childpid, NULL, 0); } if (i != n) { printf("FAIL:\n"); printf("Only %d out of %d objects were processed.\n", i, n); fflush(stdout); flint_abort(); } for (i = 0; i < n; i++) fmpz_clear(a + i); flint_free(a); } /* Write bad data to a pipe and read it */ /* Not necessary */ TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(fmpz_out_inp_raw, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/fmpz/test/t-popcnt.c000066400000000000000000000024241461254215100172670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_popcnt, state) { int i, result; flint_bitcnt_t r1, r2; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 2 * FLINT_BITS); fmpz_get_mpz(b, a); r1 = fmpz_popcnt(a); r2 = mpz_popcount(b); result = r1 == r2; if (!result && fmpz_cmp_si(a,0) >= 0) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); gmp_printf("b = %Zd\n", b); flint_printf("r1 = %wu r2 = %wu\n", r1, r2); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-pow_ui.c000066400000000000000000000030111461254215100172570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_pow_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 20); if (n_randint(state, 2)) { fmpz_pow_ui(b, a, x); } else { fmpz_set(b, a); fmpz_pow_ui(b, b, x); } flint_mpz_pow_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-powm.c000066400000000000000000000045711461254215100167530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_powm, state) { int i, result; /* Compare with GMP */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, m; fmpz_t x; mpz_t y; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(x); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(m); mpz_init(y); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); fmpz_get_mpz(d, a); fmpz_get_mpz(m, c); fmpz_randtest_unsigned(x, state, 20); fmpz_get_mpz(y, x); aliasing = n_randint(state, 5); if (aliasing == 0) { fmpz_powm(b, a, x, c); } else if (aliasing == 1) { fmpz_set(b, a); fmpz_powm(b, a, x, c); } else if (aliasing == 2) { fmpz_set(b, c); fmpz_powm(b, a, x, b); } else if (aliasing == 3) { fmpz_set(a, c); mpz_set(d, m); fmpz_powm(b, a, x, a); } else { fmpz_set(b, c); mpz_set(d, m); fmpz_powm(b, b, x, b); } mpz_powm(e, d, y, m); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL (cmp f with GMP e := d^y mod m):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, y = %Zd, m = %Zd\n", d, e, f, y, m); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(x); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(m); mpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-powm_ui.c000066400000000000000000000042231461254215100174420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_powm_ui, state) { int i, result; /* Compare with GMP */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, m; ulong x; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(m); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); fmpz_get_mpz(d, a); fmpz_get_mpz(m, c); x = n_randtest(state); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_powm_ui(b, a, x, c); } else if (aliasing == 1) { fmpz_set(b, a); fmpz_powm_ui(b, b, x, c); } else if (aliasing == 2) { fmpz_set(a, c); mpz_set(d, m); fmpz_powm_ui(b, a, x, a); } else if (aliasing == 3) { fmpz_set(b, c); mpz_set(d, m); fmpz_powm_ui(b, b, x, b); } flint_mpz_powm_ui(e, d, x, m); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu, m = %Zd\n", d, e, f, x, m); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-primorial.c000066400000000000000000000021111461254215100177530ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_primorial, state) { ulong k; fmpz_t x; fmpz_t y; fmpz_init(x); fmpz_init(y); fmpz_set_ui(y, 1); for (k = 0; k < 2000; k++) { fmpz_primorial(x, k); if (n_is_prime(k)) fmpz_mul_ui(y, y, k); if (!fmpz_equal(x, y) || !_fmpz_is_canonical(x)) { flint_printf("FAIL:\n"); flint_printf("primorial of %wu disagrees with direct product\n", k); fmpz_print(x); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_clear(x); fmpz_clear(y); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-print_read.c000066400000000000000000000150461461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) # include # include # include #endif #include "test_helpers.h" #include "fmpz.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) TEST_FUNCTION_START(fmpz_print_read, state) { int i, j, n = 10000, result; FILE *in, *out; int fd[2]; pid_t childpid; fflush(stdout); /* Ensure buffer does not flow into child process */ /* Randomise n integers, write to and read from a pipe */ { fmpz *a; a = flint_calloc(n, sizeof(fmpz)); for (i = 0; i < n; i++) fmpz_randtest(a + i, state, 200); if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } for (j = 0; j < n; j++) { r = fmpz_fprint(out, a + j); if ((j < n - 1) && (r > 0)) r = flint_fprintf(out, "\n"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } } fclose(out); for (i = 0; i < n; ++i) fmpz_clear(a + i); flint_free(a); exit(0); } else /* Parent process */ { int r; fmpz_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_init(t); i = 0; while (!feof(in)) { r = fmpz_fread(in, t); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Read error.\n"); fflush(stdout); flint_abort(); } result = fmpz_equal(t, a + i) && _fmpz_is_canonical(t); if (!result) { flint_printf("FAIL:\n"); flint_printf("a[i] = "), fmpz_print(a + i), flint_printf("\n"); flint_printf("t = "), fmpz_print(t), flint_printf("\n"); fflush(stdout); flint_abort(); } ++i; } fmpz_clear(t); fclose(in); waitpid(childpid, NULL, 0); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); fflush(stdout); flint_abort(); } for (i = 0; i < n; i++) fmpz_clear(a + i); flint_free(a); } /* Write bad data to a pipe and read it */ { char str[5] = {'b', 'l', 'a', 'h', '\0'}; if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } fclose(out); exit(0); } else /* Parent process */ { int r; fmpz_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_init(t); i = 0; while (!feof(in)) { r = fmpz_fread(in, t); if (r > 0 || !_fmpz_is_canonical(t)) { flint_printf("FAIL:\n"); flint_printf("r = %d\n", r); fflush(stdout); flint_abort(); } ++i; } fmpz_clear(t); fclose(in); waitpid(childpid, NULL, 0); } /* For {'b','l','a','h','\0'} we expect 5 reads */ if (i != 5) { flint_printf("FAIL:\n"); flint_printf("Carried out %d reads, but \"%s\" has only 4 characters.\n", i, str); fflush(stdout); flint_abort(); } } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(fmpz_print_read, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/fmpz/test/t-randprime.c000066400000000000000000000053361461254215100177520ustar00rootroot00000000000000/* Authored 2015 by Daniel S. Roche; US Government work in the public domain. This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_randprime, state) { int i; flint_bitcnt_t bits; for (bits=2; bits < 36; ++bits) { for (i=0; i < 1 * flint_test_multiplier(); ++i) { fmpz_t p; fmpz_init(p); fmpz_randprime(p, state, bits, 1); if (fmpz_bits(p) != bits || !_fmpz_is_canonical(p)) { flint_printf("FAIL: not %wu bits\n", bits); fmpz_print(p); flint_printf("\n"); fflush(stdout); flint_abort(); } if (fmpz_is_prime(p) != 1) { flint_printf("FAIL: not prime, %wu bits\n", bits); fmpz_print(p); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); } } for (; bits < 130; ++bits) { /* at this point, the chances of a collision are less than * one in a billion. So it should never happen. */ for (i=0; i < 1 + flint_test_multiplier()/5; ++i) { int j; fmpz p[2]; fmpz_init(p+0); fmpz_init(p+1); for (j=0; j<2; ++j) { fmpz_randprime(p+j, state, bits, 0); if (fmpz_bits(p+j) != bits || !_fmpz_is_canonical(p+j)) { flint_printf("FAIL: not %wu bits\n", bits); fmpz_print(p+j); flint_printf("\n"); fflush(stdout); flint_abort(); } if (fmpz_is_prime(p+j) == 0) { flint_printf("FAIL: not prime, %wu bits\n", bits); fmpz_print(p+j); flint_printf("\n"); fflush(stdout); flint_abort(); } } if (fmpz_equal(p+0, p+1)) { flint_printf("FAIL: returned a duplicate\n"); fmpz_print(p+0); flint_printf("\n"); fmpz_print(p+1); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p+0); fmpz_clear(p+1); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-remove.c000066400000000000000000000065441461254215100172700ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_remove, state) { int i, result; /* Compare with GMP, random input */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; slong x, y; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); do { fmpz_randtest_not_zero(b, state, 200); fmpz_abs(b, b); } while (fmpz_is_one(b)); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { x = fmpz_remove(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); x = fmpz_remove(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); x = fmpz_remove(c, c, b); } else { fmpz_set(c, b); x = fmpz_remove(c, a, c); } y = mpz_remove(f, d, e); fmpz_get_mpz(g, c); result = ((x == y) && (mpz_cmp(f, g) == 0)) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Compare with GMP, random input but ensure that factors exist */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, pow; mpz_t d, e, f, g; slong x, y; ulong n; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(pow); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); do { fmpz_randtest_not_zero(b, state, 200); fmpz_abs(b, b); } while (fmpz_is_one(b)); n = n_randint(state, 10); fmpz_pow_ui(pow, b, n); fmpz_mul(a, a, pow); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); x = fmpz_remove(c, a, b); y = mpz_remove(f, d, e); fmpz_get_mpz(g, c); result = ((x == y) && (x >= n) && (mpz_cmp(f, g) == 0)); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(pow); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-rfac_ui.c000066400000000000000000000040631461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_rfac_ui, state) { int i, result; /* Check rf(x,a) * rf(x+a,b) = rf(x,a+b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t x, xa, r1, r2, r1r2, r3; ulong a, b; fmpz_init(x); fmpz_init(xa); fmpz_init(r1); fmpz_init(r2); fmpz_init(r1r2); fmpz_init(r3); fmpz_randtest(x, state, 1 + n_randint(state, 200)); a = n_randint(state, 100); b = n_randint(state, 100); fmpz_add_ui(xa, x, a); if (n_randint(state, 2)) { fmpz_rfac_ui(r1, x, a); } else /* test aliasing */ { fmpz_set(r1, x); fmpz_rfac_ui(r1, r1, a); } fmpz_rfac_ui(r2, xa, b); fmpz_rfac_ui(r3, x, a+b); fmpz_mul(r1r2, r1, r2); result = fmpz_equal(r1r2, r3) && _fmpz_is_canonical(r1) && _fmpz_is_canonical(r2) && _fmpz_is_canonical(r3); if (!result) { flint_printf("FAIL\n\n"); flint_printf("x: "); fmpz_print(x); flint_printf("\n\n"); flint_printf("a = %wu, b = %wu\n\n", a, b); flint_printf("rf(x,a): "); fmpz_print(r1); flint_printf("\n\n"); flint_printf("rf(x+a,b): "); fmpz_print(r2); flint_printf("\n\n"); flint_printf("rf(x,a+b): "); fmpz_print(r3); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(xa); fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(r1r2); fmpz_clear(r3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-rfac_uiui.c000066400000000000000000000035451461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_rfac_uiui, state) { int i, result; /* Check rf(x,a) * rf(x+a,b) = rf(x,a+b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t xa, r1, r2, r1r2, r3; mp_limb_t x; ulong a, b; fmpz_init(xa); fmpz_init(r1); fmpz_init(r2); fmpz_init(r1r2); fmpz_init(r3); x = n_randlimb(state); a = n_randint(state, 100); b = n_randint(state, 100); fmpz_set_ui(xa, x); fmpz_add_ui(xa, xa, a); fmpz_rfac_uiui(r1, x, a); fmpz_rfac_ui(r2, xa, b); fmpz_rfac_uiui(r3, x, a+b); fmpz_mul(r1r2, r1, r2); result = fmpz_equal(r1r2, r3) && _fmpz_is_canonical(r1) && _fmpz_is_canonical(r2) && _fmpz_is_canonical(r3); if (!result) { flint_printf("FAIL\n\n"); flint_printf("x: %wu", x); flint_printf("\n\n"); flint_printf("a = %wu, b = %wu\n\n", a, b); flint_printf("rf(x,a): "); fmpz_print(r1); flint_printf("\n\n"); flint_printf("rf(x+a,b): "); fmpz_print(r2); flint_printf("\n\n"); flint_printf("rf(x,a+b): "); fmpz_print(r3); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(xa); fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(r1r2); fmpz_clear(r3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-root.c000066400000000000000000000071271461254215100167540ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_root, state) { int i, result, exact; /* Comparison with mpz routines */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f, g; mpz_t mf, mf2, mg; slong n; fmpz_init(f); fmpz_init(g); mpz_init(mf); mpz_init(mf2); mpz_init(mg); n = n_randint(state, 20) + 1; fmpz_randtest(g, state, 200); if ((n & 1) == 0) fmpz_abs(g, g); fmpz_get_mpz(mg, g); if (n_randint(state, 2)) { fmpz_root(f, g, n); } else /* test aliasing */ { fmpz_set(f, g); fmpz_root(f, f, n); } mpz_root(mf, mg, n); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf2, mf) == 0) && _fmpz_is_canonical(f); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd, mg = %Zd, root = %Md\n", mf, mf2, mg, n); fflush(stdout); flint_abort(); } fmpz_clear(f); fmpz_clear(g); mpz_clear(mf); mpz_clear(mf2); mpz_clear(mg); } /* Exact powers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f, g, pow; slong n; fmpz_init(f); fmpz_init(g); fmpz_init(pow); n = n_randint(state, 20) + 1; fmpz_randtest(g, state, 200); if ((n & 1) == 0) fmpz_abs(g, g); fmpz_pow_ui(pow, g, n); exact = fmpz_root(f, pow, n); result = (exact && fmpz_equal(f, g)); if (!result) { flint_printf("FAIL:\n"); flint_printf("g = "); fmpz_print(g); flint_printf("\n"); flint_printf("f = "); fmpz_print(f); flint_printf("\n"); flint_printf("exact = %d, n = %wu\n", exact, n); fflush(stdout); flint_abort(); } fmpz_clear(f); fmpz_clear(g); fmpz_clear(pow); } /* Not exact powers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f, g, pow; slong n; fmpz_init(f); fmpz_init(g); fmpz_init(pow); n = n_randint(state, 20) + 2; while (fmpz_cmp_ui(g, 2) < 0) fmpz_randtest_unsigned(g, state, 200); while (fmpz_is_zero(f)) fmpz_randm(f, state, g); fmpz_pow_ui(pow, g, n); fmpz_add(pow, pow, f); if ((n & 1) != 0 && n_randint(state, 2) == 0) { fmpz_neg(g, g); fmpz_neg(pow, pow); } exact = fmpz_root(f, pow, n); result = (!exact && fmpz_equal(f, g)); if (!result) { flint_printf("FAIL:\n"); flint_printf("g = "); fmpz_print(g); flint_printf("\n"); flint_printf("f = "); fmpz_print(f); flint_printf("\n"); flint_printf("exact = %d, n = %wu\n", exact, n); fflush(stdout); flint_abort(); } fmpz_clear(f); fmpz_clear(g); fmpz_clear(pow); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set.c000066400000000000000000000025471461254215100165650ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; flint_bitcnt_t bits; mpz_init(c); mpz_init(d); bits = n_randint(state, 200) + 1; _flint_rand_init_gmp(state); mpz_rrandomb(c, state->gmp_state, bits); if (n_randint(state, 2)) mpz_neg(c, c); fmpz_init(a); fmpz_init(b); fmpz_set_mpz(a, c); fmpz_set(b, a); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set_d_2exp.c000066400000000000000000000025001461254215100200130ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2009 Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set_d_2exp, state) { int i, result; double d, d2; slong exp, exp2; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a; fmpz_init(a); fmpz_randtest(a, state, 200); d = fmpz_get_d_2exp(&exp, a); fmpz_set_d_2exp(a, d, exp); d2 = fmpz_get_d_2exp(&exp2, a); result = (d2 == d && exp == exp2) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("d = %f, d2 = %f\n", d, d2); flint_printf("exp = %wd, exp2 = %wd, bits = %wu\n", exp, exp2, fmpz_bits(a)); fflush(stdout); flint_abort(); } fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set_signed_ui_array.c000066400000000000000000000040001461254215100217730ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set_signed_ui_array, state) { int i; slong max_limbs = 20; ulong * limbs; fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); limbs = (ulong *) flint_malloc(max_limbs*sizeof(ulong)); for (i = 0; i < 100000 * flint_test_multiplier(); i++) { slong j, n; n = n_randint(state, max_limbs) + 1; for (j = 0; j < n; j++) { limbs[j] = n_randlimb(state); if (n_randint(state, 10) == 0) limbs[j] = 0; if (n_randint(state, 10) == 0) limbs[j] = -UWORD(1); } fmpz_set_ui_array(a, limbs, n); fmpz_set_signed_ui_array(b, limbs, n); fmpz_sub(a, a, b); fmpz_one(c); fmpz_mul_2exp(c, c, n*FLINT_BITS); if (!fmpz_divisible(a, c) || !_fmpz_is_canonical(b)) { flint_printf("FAIL: check answer mod 2^(n*FLINT_BITS)\n"); fflush(stdout); flint_abort(); } fmpz_one(c); fmpz_mul_2exp(c, c, n*FLINT_BITS - 1); if (fmpz_cmp(b, c) >= 0) { flint_printf("FAIL: check answer < 2^(n*FLINT_BITS - 1)\n"); fflush(stdout); flint_abort(); } fmpz_neg(c, c); if (fmpz_cmp(b, c) < 0) { flint_printf("FAIL: check answer >= -2^(n*FLINT_BITS - 1)\n"); fflush(stdout); flint_abort(); } } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); flint_free(limbs); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set_signed_uiui.c000066400000000000000000000030721461254215100211430ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set_signed_uiui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; ulong hi, lo; hi = n_randtest(state); lo = n_randtest(state); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_set_ui(a, hi); fmpz_mul_2exp(a, a, FLINT_BITS); fmpz_add_ui(a, a, lo); if (((slong) hi) < 0) { fmpz_one(c); fmpz_mul_2exp(c, c, 2 * FLINT_BITS); fmpz_sub(a, a, c); } fmpz_set_signed_uiui(b, hi, lo); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); flint_printf("hi = %wu\n", hi); flint_printf("lo = %wu\n", lo); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set_signed_uiuiui.c000066400000000000000000000033401461254215100214770ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set_signed_uiuiui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; ulong hi, mid, lo; hi = n_randtest(state); mid = n_randtest(state); lo = n_randtest(state); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_set_ui(a, hi); fmpz_mul_2exp(a, a, FLINT_BITS); fmpz_add_ui(a, a, mid); fmpz_mul_2exp(a, a, FLINT_BITS); fmpz_add_ui(a, a, lo); if (((slong) hi) < 0) { fmpz_one(c); fmpz_mul_2exp(c, c, 3 * FLINT_BITS); fmpz_sub(a, a, c); } fmpz_set_signed_uiuiui(b, hi, mid, lo); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); flint_printf("hi = %wu\n", hi); flint_printf("mid = %wu\n", mid); flint_printf("lo = %wu\n", lo); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set_str.c000066400000000000000000000062511461254215100174510ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set_str, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t b; char * str; int ret1, ret2; int base; slong i; fmpz_init(a); fmpz_init(c); mpz_init(b); base = n_randint(state, 20); if (base == 1) base = 10; fmpz_randtest(a, state, 100); str = fmpz_get_str(NULL, base ? base : 10, a); /* test inner whitespace */ i = n_randint(state, strlen(str)); /* work around GMP bug: "- 123" is not accepted */ if (n_randint(state, 10) == 0 && i != 0 && str[i - 1] != '-') str[i] = ' '; /* test error handling */ if (n_randint(state, 10) == 0) str[n_randint(state, strlen(str))] = '?'; if (n_randint(state, 100) == 0) str[0] = '\0'; fmpz_zero(a); ret1 = fmpz_set_str(a, str, base); ret2 = mpz_set_str(b, str, base); fmpz_set_mpz(c, b); if (ret1 != ret2 || (ret1 == 0 && !fmpz_equal(a, c)) || !_fmpz_is_canonical(a)) { flint_printf("FAIL:\n"); flint_printf("base = %d\n", base); flint_printf("str = %s\n", str); flint_printf("ret1 = %d, ret2 = %d\n", ret1, ret2); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(str); fmpz_clear(a); fmpz_clear(c); mpz_clear(b); } /* test binary splitting code */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t b; char * str; slong i, n; int ret1, ret2; flint_set_num_threads(1 + n_randint(state, 5)); fmpz_init(a); fmpz_init(c); mpz_init(b); n = 20000 + n_randint(state, 100000); str = flint_malloc(n + 1); for (i = 0; i < n; i++) str[i] = n_randint(state, 10) + '0'; str[n] = '\0'; ret1 = fmpz_set_str(a, str, 10); ret2 = mpz_set_str(b, str, 10); fmpz_set_mpz(c, b); if (ret1 != ret2 || !fmpz_equal(a, c) || !_fmpz_is_canonical(a)) { flint_printf("FAIL:\n"); flint_printf("str = %s\n", str); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(str); fmpz_clear(a); fmpz_clear(c); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set_ui_smod.c000066400000000000000000000025601461254215100202770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set_ui_smod, state) { int i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, mz; mp_limb_t m, r; fmpz_init(a); fmpz_init(b); fmpz_init(mz); do { m = n_randtest(state); } while (m < 2); fmpz_set_ui(mz, m); fmpz_randtest_mod_signed(a, state, mz); r = fmpz_fdiv_ui(a, m); fmpz_set_ui_smod(b, r, m); if (!fmpz_equal(a, b) || !_fmpz_is_canonical(b)) { flint_printf("FAIL:\n"); flint_printf("a: "); fmpz_print(a); flint_printf("\n"); flint_printf("m: %wu\n", m); flint_printf("r: %wu\n", m); flint_printf("b: "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(mz); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-set_uiui.c000066400000000000000000000025341461254215100176140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_set_uiui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; ulong hi, lo; hi = n_randtest(state); lo = n_randtest(state); fmpz_init(a); fmpz_init(b); fmpz_set_ui(a, hi); fmpz_mul_2exp(a, a, FLINT_BITS); fmpz_add_ui(a, a, lo); fmpz_set_uiui(b, hi, lo); result = fmpz_equal(a, b) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); flint_printf("hi = %wu\n", hi); flint_printf("lo = %wu\n", lo); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-setbit.c000066400000000000000000000031121461254215100172510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_setbit, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong j; fmpz_t a, b, c; mpz_t z; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(z); fmpz_randtest(a, state, 2 * FLINT_BITS); fmpz_set(b, a); fmpz_get_mpz(z, b); j = n_randint(state, 3 * FLINT_BITS); fmpz_setbit(b, j); mpz_setbit(z, j); fmpz_set_mpz(c, z); result = (fmpz_equal(b, c)) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); gmp_printf("z = %Zd\n", z); flint_printf("j = %wd\n", j); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-sgn.c000066400000000000000000000020771461254215100165570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_sgn, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; mp_size_t r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); fmpz_get_mpz(b, a); r1 = fmpz_sgn(a); r2 = mpz_sgn(b); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-size.c000066400000000000000000000021021461254215100167270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_size, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; mp_size_t r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); fmpz_get_mpz(b, a); r1 = fmpz_size(a); r2 = mpz_size(b); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-sizeinbase.c000066400000000000000000000025461461254215100201250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_sizeinbase, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; int base; size_t r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); base = (int) (n_randint(state, 61) + 2); fmpz_get_mpz(b, a); r1 = fmpz_sizeinbase(a, base); r2 = mpz_sizeinbase(b, base); result = (r1 == r2 || r1 + 1 == r2); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); flint_printf("base = %d\n", base); flint_printf("r1 = %wu\n, r2 = %wu\n", (ulong) r1, (ulong) r2); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-smod.c000066400000000000000000000057751461254215100167420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_smod, state) { int i; for (i = 0; i < 20000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d, e; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(e); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); if (n_randint(state, 10) == 0) { fmpz_fdiv_q_ui(a, b, 2); if (n_randint(state, 2)) fmpz_add(a, b, b); if (n_randint(state, 2)) fmpz_sub(a, b, b); if (n_randint(state, 2)) fmpz_add(a, b, b); } aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_smod(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); fmpz_smod(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_smod(c, c, b); } else { fmpz_set(c, b); fmpz_smod(c, a, c); } fmpz_sub(d, a, c); fmpz_mod(d, d, b); if (!fmpz_is_zero(d) || !_fmpz_is_canonical(c)) { flint_printf("FAIL: check b|(smod(a,b) - a)\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("smod(a,b) = "), fmpz_print(c), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_abs(e, b); fmpz_mul_2exp(d, c, 1); if (fmpz_cmp(d, e) > 0) { flint_printf("FAIL: check 2*smod(a,b) <= |b|\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("smod(a,b) = "), fmpz_print(c), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_neg(e, e); if (fmpz_cmp(e, d) >= 0) { flint_printf("FAIL: check -|b| < 2*smod(a,b)\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("smod(a,b) = "), fmpz_print(c), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-sqrt.c000066400000000000000000000031151461254215100167530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_sqrt, state) { int i, result; /* Comparison with mpz routines */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f, g; mpz_t mf, mf2, mg; fmpz_init(f); fmpz_init(g); mpz_init(mf); mpz_init(mf2); mpz_init(mg); fmpz_randtest(g, state, 200); fmpz_abs(g, g); fmpz_get_mpz(mg, g); if (n_randint(state, 2)) { fmpz_sqrt(f, g); } else /* test aliasing */ { fmpz_set(f, g); fmpz_sqrt(f, f); } fmpz_sqrt(f, g); mpz_sqrt(mf, mg); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf2, mf) == 0) && _fmpz_is_canonical(f); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd, mg = %Zd\n", mf, mf2, mg); fflush(stdout); flint_abort(); } fmpz_clear(f); fmpz_clear(g); mpz_clear(mf); mpz_clear(mf2); mpz_clear(mg); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-sqrtmod.c000066400000000000000000000062751461254215100174650ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_sqrtmod, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) /* Test random integers */ { int ans; fmpz_t a, b, c, p; mp_limb_t prime; prime = n_randint(state, UWORD(1) << (FLINT_BITS - 1)); prime = n_nextprime(prime, 1); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(p); fmpz_set_ui(p, prime); fmpz_randm(a, state, p); ans = fmpz_sqrtmod(b, a, p); fmpz_mul(c, b, b); fmpz_mod(c, c, p); result = (ans == 0 || fmpz_equal(a, c)) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL (random):\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(p); } for (i = 0; i < 100 * flint_test_multiplier(); i++) /* Test random squares */ { int ans; fmpz_t a, b, c, d, p; mp_limb_t prime; prime = n_randint(state, UWORD(1) << (FLINT_BITS - 1)); prime = n_nextprime(prime, 1); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(p); fmpz_set_ui(p, prime); do fmpz_randm(b, state, p); while (fmpz_is_zero(b)); fmpz_mul(a, b, b); fmpz_mod(a, a, p); /* check a special case */ if (i == 0) { fmpz_set_str(p, "15951355998396157", 10); fmpz_set_str(a, "7009303413761286", 10); } ans = fmpz_sqrtmod(c, a, p); fmpz_mul(d, c, c); fmpz_mod(d, d, p); result = (ans && fmpz_equal(a, d)) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL (squares):\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("a (= b^2) = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c (= sqrt(a) = "), fmpz_print(c), flint_printf("\n"); flint_printf("d (= c^2) = "), fmpz_print(d), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-sqrtrem.c000066400000000000000000000036011461254215100174570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_sqrtrem, state) { int i, result; /* Comparison with mpz routines */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f, r, g; mpz_t mf, mf2, mr, mg; int aliasing; fmpz_init(f); fmpz_init(r); fmpz_init(g); mpz_init(mf); mpz_init(mf2); mpz_init(mr); mpz_init(mg); fmpz_randtest(g, state, 200); fmpz_abs(g, g); fmpz_get_mpz(mg, g); aliasing = n_randint(state, 3); if (aliasing == 0) { fmpz_sqrtrem(f, r, g); } else if (aliasing == 1) { fmpz_set(f, g); fmpz_sqrtrem(f, r, f); } else { fmpz_set(r, g); fmpz_sqrtrem(f, r, r); } mpz_sqrtrem(mf, mr, mg); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf2, mf) == 0) && _fmpz_is_canonical(f) && _fmpz_is_canonical(r); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd, mr = %Zd, mg = %Zd\n", mf, mf2, mr, mg); fflush(stdout); flint_abort(); } fmpz_clear(f); fmpz_clear(r); fmpz_clear(g); mpz_clear(mf); mpz_clear(mf2); mpz_clear(mr); mpz_clear(mg); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-sub.c000066400000000000000000000035771461254215100165670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_sub, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_sub(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_sub(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_sub(c, c, b); } else { fmpz_set(c, b); fmpz_sub(c, a, c); } mpz_sub(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-submul.c000066400000000000000000000041231461254215100172710ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_submul, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_randtest(c, state, 200); if (n_randint(state, 10) == 0) fmpz_addmul(c, a, b); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); fmpz_get_mpz(f, c); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_submul(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_submul(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); mpz_set(f, d); fmpz_submul(c, c, b); } else { fmpz_set(c, b); mpz_set(f, e); fmpz_submul(c, a, c); } mpz_submul(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-submul_si.c000066400000000000000000000033021461254215100177620ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "long_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_submul_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, xx; slong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); x = z_randtest(state); if (n_randint(state, 2)) { fmpz_submul_si(b, a, x); } else /* test aliasing */ { fmpz_set(b, a); mpz_set(e, d); fmpz_submul_si(b, b, x); } flint_mpz_init_set_si(xx, x); mpz_submul(e, d, xx); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, xx = %Zd\n", d, e, f, xx); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(xx); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-submul_ui.c000066400000000000000000000032051461254215100177660ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_submul_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); x = n_randtest(state); if (n_randint(state, 2)) { fmpz_submul_ui(b, a, x); } else /* test aliasing */ { fmpz_set(b, a); mpz_set(e, d); fmpz_submul_ui(b, b, x); } flint_mpz_submul_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-swap.c000066400000000000000000000023651461254215100167420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_swap, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t c, d; fmpz_init(a); fmpz_init(b); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(c, a); fmpz_swap(a, b); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0) && _fmpz_is_canonical(a) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tdiv_q.c000066400000000000000000000037041461254215100172540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_tdiv_q, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_tdiv_q(c, a, b); } else if (aliasing == 1) { fmpz_set(a, b); mpz_set(d, e); fmpz_tdiv_q(c, a, a); } else if (aliasing == 2) { fmpz_set(c, a); fmpz_tdiv_q(c, c, b); } else { fmpz_set(c, b); fmpz_tdiv_q(c, a, c); } mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tdiv_q_2exp.c000066400000000000000000000030271461254215100202100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_tdiv_q_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_tdiv_q_2exp(b, a, x); } else /* test aliasing */ { fmpz_set(b, a); fmpz_tdiv_q_2exp(b, b, x); } mpz_tdiv_q_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tdiv_q_si.c000066400000000000000000000031751461254215100177510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "long_extras.h" TEST_FUNCTION_START(fmpz_tdiv_q_si, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong b; fmpz_t a, c; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); b = z_randtest_not_zero(state); fmpz_get_mpz(d, a); flint_mpz_set_si(e, b); if (n_randint(state, 2)) { fmpz_tdiv_q_si(c, a, b); } else /* test aliasing */ { fmpz_set(c, a); fmpz_tdiv_q_si(c, c, b); } mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tdiv_q_ui.c000066400000000000000000000031761461254215100177540ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_tdiv_q_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b; fmpz_t a, c; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); b = n_randtest_not_zero(state); fmpz_get_mpz(d, a); flint_mpz_set_ui(e, b); if (n_randint(state, 2)) { fmpz_tdiv_q_ui(c, a, b); } else /* test aliasing */ { fmpz_set(c, a); fmpz_tdiv_q_ui(c, c, b); } mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tdiv_qr.c000066400000000000000000000044331461254215100174360ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_tdiv_qr, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(r); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); mpz_init(h); mpz_init(s); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 5); if (aliasing == 0) { fmpz_tdiv_qr(c, r, a, b); } else if (aliasing == 1) { fmpz_set(c, a); fmpz_tdiv_qr(c, r, c, b); } else if (aliasing == 2) { fmpz_set(c, b); fmpz_tdiv_qr(c, r, a, c); } else if (aliasing == 3) { fmpz_set(r, a); fmpz_tdiv_qr(c, r, r, b); } else { fmpz_set(r, b); fmpz_tdiv_qr(c, r, a, r); } mpz_tdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, r); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0) && _fmpz_is_canonical(c) && _fmpz_is_canonical(r); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(r); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); mpz_clear(h); mpz_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tdiv_r_2exp.c000066400000000000000000000030071461254215100202070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_tdiv_r_2exp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; ulong x; fmpz_init(a); fmpz_init(b); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); if (n_randint(state, 2)) { fmpz_tdiv_r_2exp(b, a, x); } else { fmpz_set(b, a); fmpz_tdiv_r_2exp(b, b, x); } mpz_tdiv_r_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL 1:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tdiv_ui.c000066400000000000000000000023451461254215100174310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_tdiv_ui, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; ulong x, r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); fmpz_get_mpz(b, a); x = n_randtest_not_zero(state); r1 = fmpz_tdiv_ui(a, x); r2 = flint_mpz_tdiv_ui(b, x); result = (r1 == r2) && _fmpz_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("b = %Zd, x = %wu, r1 = %wu, r2 = %wu\n", b, x, r1, r2); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-tstbit.c000066400000000000000000000023251461254215100172750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_tstbit, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { int k, l; ulong j; fmpz_t a; mpz_t b; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 2 * FLINT_BITS); fmpz_get_mpz(b, a); j = n_randint(state, 3 * FLINT_BITS); k = fmpz_tstbit(a, j); l = mpz_tstbit(b, j); result = (k == l); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd, j = %Mu k = %d, l = %d\n", b, j, k, l); fflush(stdout); flint_abort(); } fmpz_clear(a); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-val2.c000066400000000000000000000025071461254215100166320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_val2, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t x; slong v1, v2; fmpz_init(x); /* Test special case */ if (n_randint(state, 1000) == 0) { fmpz_zero(x); v1 = 0; } else { do { fmpz_randtest(x, state, 1000); } while (fmpz_is_even(x)); v1 = n_randint(state, 1000); fmpz_mul_2exp(x, x, v1); } v2 = fmpz_val2(x); result = ((v1 == v2) == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("v1 = %wd v2 = %wd\n", v1, v2); fflush(stdout); flint_abort(); } fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-xgcd.c000066400000000000000000000057531461254215100167210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_xgcd, state) { int i, result; /* Test a f + b g == d and d >= 0 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, b, f, g, t1, t2; int aliasing; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(f); fmpz_init(g); fmpz_init(t1); fmpz_init(t2); fmpz_randtest_unsigned(g, state, 200); fmpz_add_ui(g, g, 1); fmpz_randm(f, state, g); if (n_randint(state, 2)) fmpz_neg(g, g); if (n_randint(state, 2)) fmpz_neg(f, f); aliasing = n_randint(state, 5); if (aliasing == 0) { fmpz_xgcd(d, a, b, f, g); } else if (aliasing == 1) { /* Test aliasing of d and f, a and g */ fmpz_set(d, f); fmpz_set(a, g); fmpz_xgcd(d, a, b, d, a); } else if (aliasing == 2) { /* Test aliasing of a and f, d and g */ fmpz_set(a, f); fmpz_set(d, g); fmpz_xgcd(d, a, b, a, d); } else if (aliasing == 3) { /* Test aliasing of d and f, b and g */ fmpz_set(d, f); fmpz_set(b, g); fmpz_xgcd(d, a, b, d, b); } else { /* Test aliasing of b and f, d and g */ fmpz_set(b, f); fmpz_set(d, g); fmpz_xgcd(d, a, b, b, d); } fmpz_mul(t1, a, f); fmpz_mul(t2, b, g); fmpz_add(t1, t1, t2); result = fmpz_equal(t1, d) && fmpz_sgn(d) >= 0 && _fmpz_is_canonical(d) && _fmpz_is_canonical(a) && _fmpz_is_canonical(b); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("aliasing = %d\n", aliasing); flint_printf("d = "), fmpz_print(d), flint_printf("\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("t1 = "), fmpz_print(t1), flint_printf("\n"); flint_printf("t2 = "), fmpz_print(t2), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(f); fmpz_clear(g); fmpz_clear(t1); fmpz_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-xgcd_canonical_bezout.c000066400000000000000000000300441461254215100223070ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_xgcd_canonical_bezout, state) { int ix, result; fmpz_t maxval; fmpz_t nd, na, nb, nf, ng; fmpz_init(maxval); /* For uniformly random distributions, * about half the numbers should be represented as slongs */ fmpz_set_d_2exp(maxval, 1.0, FLINT_BITS - 1); fmpz_init(nd); fmpz_init(na); fmpz_init(nb); fmpz_init(nf); fmpz_init(ng); /* Check that xgcd(0, 0) = (0, 0, 0) */ if (1) { fmpz_zero(nf); fmpz_zero(ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_is_zero(nd) && fmpz_is_zero(na) && fmpz_is_zero(nb) && fmpz_is_zero(nf) && fmpz_is_zero(ng)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(0, 0) is not equal to (0, 0, 0):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check that xgcd(±g, g) = (|g|, 0, sgn(g)) */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fmpz_randm(ng, state, maxval); if (n_randint(state, 2)) fmpz_neg(ng, ng); fmpz_set(nf, ng); if (n_randint(state, 2)) fmpz_neg(nf, nf); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_cmp_si(nd, 0) >= 0 && fmpz_cmpabs(nd, ng) == 0 && fmpz_is_zero(na) && fmpz_equal_si(nb, fmpz_sgn(ng))); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(+/-g, g) is not equal to (|g|, 0, sgn(g)):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check that xgcd(f, 0) = (|f|, sgn(f), 0) */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fmpz_randm(nf, state, maxval); if (n_randint(state, 2)) fmpz_neg(nf, nf); fmpz_zero(ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_cmp_si(nd, 0) >= 0 && fmpz_cmpabs(nd, nf) == 0 && fmpz_equal_si(na, fmpz_sgn(nf)) && fmpz_is_zero(nb)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(f, 0) is not equal to (|f|, sgn(f), 0):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check that xgcd(0, g) = (|g|, 0, sgn(g)) */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fmpz_zero(nf); fmpz_randm(ng, state, maxval); if (n_randint(state, 2)) fmpz_neg(ng, ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_cmp_si(nd, 0) >= 0 && fmpz_cmpabs(nd, ng) == 0 && fmpz_is_zero(na) && fmpz_equal_si(nb, fmpz_sgn(ng))); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(0, g) is not equal to (|g|, 0, sgn(g)):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check that xgcd(f, ±1) = (1, 0, ±1) */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fmpz_randm(nf, state, maxval); if (n_randint(state, 2)) fmpz_neg(nf, nf); fmpz_one(ng); if (n_randint(state, 2)) fmpz_neg(ng, ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_is_one(nd) && fmpz_is_zero(na) && fmpz_equal_si(nb, fmpz_sgn(ng))); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(f, +/-1) is not equal to (1, 0, +/-1):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check that xgcd(±1, g) = (1, ±1, 0) when g is not 0 or ±1 */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fmpz_one(nf); if (n_randint(state, 2)) fmpz_neg(nf, nf); fmpz_randm(ng, state, maxval); if (n_randint(state, 2)) fmpz_neg(ng, ng); if (fmpz_is_zero(ng) || fmpz_is_pm1(ng)) fmpz_set_si(ng, 3); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_is_one(nd) && fmpz_equal_si(na, fmpz_sgn(nf)) && fmpz_is_zero(nb)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(+/-1, g) is not equal to (1, +/-1, 0):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } } /* Check that xgcd(±2d, g) = (d, X, sgn(g)) */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fmpz_t dsave; flint_bitcnt_t div2; fmpz_randm(nd, state, maxval); fmpz_init_set(dsave, nd); fmpz_mul_si(nf, nd, 2); if (n_randint(state, 2)) fmpz_neg(nf, nf); fmpz_randm(ng, state, maxval); div2 = fmpz_val2(ng); fmpz_tdiv_q_2exp(ng, ng, div2); /* we still want gcd(2d, g) = d */ fmpz_mul(ng, ng, nd); if (n_randint(state, 2)) fmpz_neg(ng, ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_equal(nd, dsave) && fmpz_equal_si(nb, fmpz_sgn(ng))); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(+/-2 d, g) is not equal to (d, X, sgn(g)):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(dsave); } /* Check that xgcd(f, ±2d) = (d, sgn(f), X) */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fmpz_t dsave; flint_bitcnt_t div2; fmpz_randm(nd, state, maxval); fmpz_init_set(dsave, nd); fmpz_mul_si(ng, nd, 2); if (n_randint(state, 2)) fmpz_neg(ng, ng); fmpz_randm(nf, state, maxval); div2 = fmpz_val2(nf); fmpz_tdiv_q_2exp(nf, nf, div2); /* we still want gcd(2d, f) = d */ fmpz_mul(nf, nf, nd); if (n_randint(state, 2)) fmpz_neg(nf, nf); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); result = (fmpz_equal(nd, dsave) && fmpz_equal_si(na, fmpz_sgn(nf))); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("xgcd(f, +/-2 d) is not equal to (d, sgn(f), X):\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(dsave); } /* For the other cases, check that * a f + b g = d, * |a| < |g / (2 d)|, * |b| < |f / (2 d)|. */ for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { fmpz_t tmp; int aliasing; fmpz_init(tmp); fmpz_randm(nf, state, maxval); fmpz_randm(ng, state, maxval); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); aliasing = n_randint(state, 5); if (aliasing == 0) { fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); } else if (aliasing == 1) { /* Test aliasing of d and f, a and g */ fmpz_set(nd, nf); fmpz_set(na, ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nd, na); } else if (aliasing == 2) { /* Test aliasing of a and f, d and g */ fmpz_set(na, nf); fmpz_set(nd, ng); fmpz_xgcd_canonical_bezout(nd, na, nb, na, nd); } else if (aliasing == 3) { /* Test aliasing of d and f, b and g */ fmpz_set(nd, nf); fmpz_set(nb, ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nd, nb); } else { /* Test aliasing of b and f, d and g */ fmpz_set(nb, nf); fmpz_set(nd, ng); fmpz_xgcd_canonical_bezout(nd, na, nb, nb, nd); } fmpz_mul(tmp, na, nf); fmpz_addmul(tmp, nb, ng); fmpz_mul_si(na, na, 2); fmpz_mul(na, na, nd); fmpz_mul_si(nb, nb, 2); fmpz_mul(nb, nb, nd); result = (fmpz_equal(tmp, nd) && fmpz_cmpabs(na, ng) < 0 && fmpz_cmpabs(nb, nf) < 0) && _fmpz_is_canonical(nd) && _fmpz_is_canonical(na) && _fmpz_is_canonical(nb); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("d = "), fmpz_print(nd), flint_printf("\n"); flint_printf("a = "), fmpz_print(na), flint_printf("\n"); flint_printf("b = "), fmpz_print(nb), flint_printf("\n"); flint_printf("f = "), fmpz_print(nf), flint_printf("\n"); flint_printf("g = "), fmpz_print(ng), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(tmp); } fmpz_clear(maxval); fmpz_clear(nd); fmpz_clear(na); fmpz_clear(nb); fmpz_clear(nf); fmpz_clear(ng); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-xgcd_partial.c000066400000000000000000000037761461254215100204400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_xgcd_partial, state) { int i, result; /* Test co2*r1 - co1*r2 = r2_orig */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t co1, co2, f, g, t1, t2, L; fmpz_init(co1); fmpz_init(co2); fmpz_init(f); fmpz_init(g); fmpz_init(L); fmpz_init(t1); fmpz_init(t2); fmpz_randtest_unsigned(g, state, 200); fmpz_add_ui(g, g, 1); fmpz_randm(f, state, g); fmpz_randtest_unsigned(L, state, 200); fmpz_set(t2, g); fmpz_abs(t2, t2); fmpz_xgcd_partial(co2, co1, g, f, L); fmpz_mul(t1, co2, f); fmpz_submul(t1, co1, g); fmpz_abs(t1, t1); result = fmpz_equal(t1, t2); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("co1 = "), fmpz_print(co1), flint_printf("\n"); flint_printf("co2 = "), fmpz_print(co2), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("L = "), fmpz_print(L), flint_printf("\n"); flint_printf("t1 = "), fmpz_print(t1), flint_printf("\n"); flint_printf("t2 = "), fmpz_print(t2), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(co1); fmpz_clear(co2); fmpz_clear(f); fmpz_clear(g); fmpz_clear(L); fmpz_clear(t1); fmpz_clear(t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/test/t-xor.c000066400000000000000000000036231461254215100165760ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(fmpz_xor, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int aliasing; fmpz_init(a); fmpz_init(b); fmpz_init(c); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); aliasing = n_randint(state, 4); if (aliasing == 0) { fmpz_xor(c, a, b); } else if (aliasing == 1) { fmpz_set(c, a); fmpz_xor(c, c, b); } else if (aliasing == 2) { fmpz_set(c, b); fmpz_xor(c, a, c); } else if (aliasing == 3) { fmpz_set(c, a); fmpz_xor(c, a, a); mpz_set(e, d); } mpz_xor(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0) && _fmpz_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz/tstbit.c000066400000000000000000000013361461254215100160560ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" int fmpz_tstbit(const fmpz_t f, ulong i) { if (!COEFF_IS_MPZ(*f)) { if (i < FLINT_BITS) { return ((WORD(1) << i) & *f) != 0; } else /* i >= FLINT_BITS */ { return *f < 0; } } else { return mpz_tstbit(COEFF_TO_PTR(*f), i); } } flint-3.1.3/src/fmpz/val2.c000066400000000000000000000016341461254215100154120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" flint_bitcnt_t fmpz_val2(const fmpz_t x) { fmpz c = *x; flint_bitcnt_t t; if (!COEFF_IS_MPZ(c)) { if (c == 0) t = 0; else t = flint_ctz(FLINT_ABS(c)); } else { mp_limb_t *d = (COEFF_TO_PTR(c))->_mp_d; flint_bitcnt_t u; t = 0; while (*d == 0) { d++; t += FLINT_BITS; } u = flint_ctz(*d); t += u; } return t; } flint-3.1.3/src/fmpz/xgcd.c000066400000000000000000000107351461254215100154750ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" void fmpz_xgcd(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g) { fmpz_t t1, t2; fmpz *f1, *g1; if (fmpz_is_zero(f)) { int sign = fmpz_sgn(g); fmpz_abs(d, g); fmpz_set_ui(a, 0); if (sign == 0) fmpz_set_ui(b, 0); else if (sign > 0) fmpz_set_ui(b, 1); else fmpz_set_si(b, -1); } else if (fmpz_cmpabs(f, g) == 0) { if (fmpz_sgn(f) > 0) { fmpz_set(d, f); fmpz_set_ui(a, 1); } else { fmpz_neg(d, f); fmpz_set_si(a, -1); } fmpz_set_si(b, 0); } else { int sign1 = fmpz_sgn(f); int sign2 = fmpz_sgn(g); fmpz_init(t1); fmpz_init(t2); /* support aliasing */ if (d == f || a == f || sign1 < 0) { f1 = t1; if (sign1 < 0) fmpz_neg(f1, f); else fmpz_set(f1, f); } else f1 = (fmpz *) f; if (d == g || a == g || sign2 < 0) { g1 = t2; if (sign2 < 0) fmpz_neg(g1, g); else fmpz_set(g1, g); } else g1 = (fmpz *) g; if (fmpz_cmp(f1, g1) < 0) { fmpz_gcdinv(d, a, f1, g1); fmpz_mul(t1, a, f1); fmpz_sub(t1, d, t1); fmpz_divexact(b, t1, g1); } else /* g < f */ { fmpz_gcdinv(d, b, g1, f1); fmpz_mul(t2, b, g1); fmpz_sub(t2, d, t2); fmpz_divexact(a, t2, f1); } if (sign1 < 0) fmpz_neg(a, a); if (sign2 < 0) fmpz_neg(b, b); fmpz_clear(t1); fmpz_clear(t2); } } void fmpz_xgcd_canonical_bezout(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g) { /* check aliasing */ if (d == f || a == f || b == f || d == g || a == g || b == g) { fmpz_t d2, a2, b2; fmpz_init(d2); fmpz_init(a2); fmpz_init(b2); fmpz_xgcd_canonical_bezout(d2, a2, b2, f, g); fmpz_swap(d, d2); fmpz_swap(a, a2); fmpz_swap(b, b2); fmpz_clear(d2); fmpz_clear(a2); fmpz_clear(b2); return; } if (!COEFF_IS_MPZ(*f) && !COEFF_IS_MPZ(*g)) /* both are small */ { ulong fn = FLINT_ABS(*f); ulong gn = FLINT_ABS(*g); _fmpz_demote(d); _fmpz_demote(a); _fmpz_demote(b); if (fn == 0 || gn == 0) { /* xgcd(0, g) = (|g|, 0, sgn(g)) */ /* xgcd(f, 0) = (|f|, sgn(f), 0) */ *d = (slong) gn + (slong) (fn != gn) * fn; *a = (gn == 0) * FLINT_SGN(*f); *b = FLINT_SGN(*g); return; } *d = mpn_gcdext_1(a, b, fn, gn); *a *= FLINT_SGN(*f); *b *= FLINT_SGN(*g); return; } else if (!COEFF_IS_MPZ(*f)) /* only f is small */ { mpz_t mf; ulong tf = FLINT_ABS(*f); mf->_mp_d = (mp_limb_t *) &tf; mf->_mp_size = fmpz_sgn(f); _fmpz_promote(d); _fmpz_promote(a); _fmpz_promote(b); mpz_gcdext(COEFF_TO_PTR(*d), COEFF_TO_PTR(*a), COEFF_TO_PTR(*b), mf, COEFF_TO_PTR(*g)); } else if (!COEFF_IS_MPZ(*g)) /* only g is small */ { mpz_t mg; ulong tg = FLINT_ABS(*g); mg->_mp_d = (mp_limb_t *) &tg; mg->_mp_size = fmpz_sgn(g); _fmpz_promote(d); _fmpz_promote(a); _fmpz_promote(b); mpz_gcdext(COEFF_TO_PTR(*d), COEFF_TO_PTR(*a), COEFF_TO_PTR(*b), COEFF_TO_PTR(*f), mg); } else /* both are big */ { _fmpz_promote(d); _fmpz_promote(a); _fmpz_promote(b); mpz_gcdext(COEFF_TO_PTR(*d), COEFF_TO_PTR(*a), COEFF_TO_PTR(*b), COEFF_TO_PTR(*f), COEFF_TO_PTR(*g)); } _fmpz_demote_val(d); _fmpz_demote_val(a); _fmpz_demote_val(b); } flint-3.1.3/src/fmpz/xgcd_partial.c000066400000000000000000000053551461254215100172130ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_xgcd_partial(fmpz_t co2, fmpz_t co1, fmpz_t r2, fmpz_t r1, const fmpz_t L) { fmpz_t q, r; slong aa2, aa1, bb2, bb1, rr1, rr2, qq, bb, t1, t2, t3, i; slong bits, bits1, bits2; fmpz_init(q); fmpz_init(r); fmpz_zero(co2); fmpz_set_si(co1, -1); while (!fmpz_is_zero(r1) && fmpz_cmp(r1, L) > 0) { bits2 = fmpz_bits(r2); bits1 = fmpz_bits(r1); bits = FLINT_MAX(bits2, bits1) - FLINT_BITS + 1; if (bits < 0) bits = 0; fmpz_tdiv_q_2exp(r, r2, bits); rr2 = fmpz_get_ui(r); fmpz_tdiv_q_2exp(r, r1, bits); rr1 = fmpz_get_ui(r); fmpz_tdiv_q_2exp(r, L, bits); bb = fmpz_get_ui(r); aa2 = 0; aa1 = 1; bb2 = 1; bb1 = 0; for (i = 0; rr1 != 0 && rr1 > bb; i++) { qq = rr2 / rr1; t1 = rr2 - qq*rr1; t2 = aa2 - qq*aa1; t3 = bb2 - qq*bb1; if (i & 1) { if (t1 < -t3 || rr1 - t1 < t2 - aa1) break; } else { if (t1 < -t2 || rr1 - t1 < t3 - bb1) break; } rr2 = rr1; rr1 = t1; aa2 = aa1; aa1 = t2; bb2 = bb1; bb1 = t3; } if (i == 0) { fmpz_fdiv_qr(q, r2, r2, r1); fmpz_swap(r2, r1); fmpz_submul(co2, co1, q); fmpz_swap(co2, co1); } else { fmpz_mul_si(r, r2, bb2); if (aa2 >= 0) fmpz_addmul_ui(r, r1, aa2); else fmpz_submul_ui(r, r1, -aa2); fmpz_mul_si(r1, r1, aa1); if (bb1 >= 0) fmpz_addmul_ui(r1, r2, bb1); else fmpz_submul_ui(r1, r2, -bb1); fmpz_set(r2, r); fmpz_mul_si(r, co2, bb2); if (aa2 >= 0) fmpz_addmul_ui(r, co1, aa2); else fmpz_submul_ui(r, co1, -aa2); fmpz_mul_si(co1, co1, aa1); if (bb1 >= 0) fmpz_addmul_ui(co1, co2, bb1); else fmpz_submul_ui(co1, co2, -bb1); fmpz_set(co2, r); if (fmpz_sgn(r1) < 0) { fmpz_neg(co1, co1); fmpz_neg(r1, r1); } if (fmpz_sgn(r2) < 0) { fmpz_neg(co2, co2); fmpz_neg(r2, r2); } } } if (fmpz_sgn(r2) < 0) { fmpz_neg(co2, co2); fmpz_neg(co1, co1); fmpz_neg(r2, r2); } fmpz_clear(q); fmpz_clear(r); } flint-3.1.3/src/fmpz_extras.h000066400000000000000000000102441461254215100161360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_EXTRAS_H #define FMPZ_EXTRAS_H #include "fmpz.h" #ifdef __cplusplus extern "C" { #endif static inline void fmpz_add_inline(fmpz_t z, const fmpz_t x, const fmpz_t y) { fmpz f, g; f = *x; g = *y; if (!COEFF_IS_MPZ(f) && !COEFF_IS_MPZ(g)) fmpz_set_si(z, f + g); else fmpz_add(z, x, y); } static inline void fmpz_add_si_inline(fmpz_t z, const fmpz_t x, slong y) { fmpz f; f = *x; if (!COEFF_IS_MPZ(f) && (COEFF_MIN <= y && y <= COEFF_MAX)) fmpz_set_si(z, f + y); else fmpz_add_si(z, x, y); } static inline void fmpz_sub_si_inline(fmpz_t z, const fmpz_t x, slong y) { fmpz f; f = *x; if (!COEFF_IS_MPZ(f) && (COEFF_MIN <= y && y <= COEFF_MAX)) fmpz_set_si(z, f - y); else fmpz_sub_si(z, x, y); } static inline void fmpz_add_ui_inline(fmpz_t z, const fmpz_t x, ulong y) { fmpz f = *x; if (!COEFF_IS_MPZ(f) && y <= COEFF_MAX) fmpz_set_si(z, f + y); else fmpz_add_ui(z, x, y); } static inline void fmpz_add2_fmpz_si_inline(fmpz_t z, const fmpz_t x, const fmpz_t y, slong c) { fmpz f, g, h; f = *x; g = *y; if (!COEFF_IS_MPZ(f) && !COEFF_IS_MPZ(g)) { h = f + g; if ((COEFF_MIN <= h && h <= COEFF_MAX) && (COEFF_MIN <= c && c <= COEFF_MAX)) { fmpz_set_si(z, h + c); return; } } fmpz_add(z, x, y); fmpz_add_si(z, z, c); } static inline void fmpz_set_mpn_large(fmpz_t z, mp_srcptr src, mp_size_t n, int negative) { __mpz_struct * zz; zz = _fmpz_promote(z); if (zz->_mp_alloc < n) mpz_realloc2(zz, n * FLINT_BITS); flint_mpn_copyi(zz->_mp_d, src, n); zz->_mp_size = negative ? -n : n; } static inline void fmpz_adiv_q_2exp(fmpz_t z, const fmpz_t x, flint_bitcnt_t exp) { int sign = fmpz_sgn(x); if (sign > 0) fmpz_cdiv_q_2exp(z, x, exp); else fmpz_fdiv_q_2exp(z, x, exp); } static inline void _fmpz_set_si_small(fmpz_t x, slong v) { fmpz_clear(x); *x = v; } slong _fmpz_sub_small_large(const fmpz_t x, const fmpz_t y); static inline slong _fmpz_sub_small(const fmpz_t x, const fmpz_t y) { if (!COEFF_IS_MPZ(*x) && !COEFF_IS_MPZ(*y)) { return (*x) - (*y); } else { return _fmpz_sub_small_large(x, y); } } static inline mp_size_t _fmpz_size(const fmpz_t f) { fmpz d = *f; if (!COEFF_IS_MPZ(d)) return 1; else return mpz_size(COEFF_TO_PTR(d)); } static inline void fmpz_ui_mul_ui(fmpz_t r, ulong a, ulong b) { if (a < (UWORD(1) << (FLINT_BITS / 2)) && b < (UWORD(1) << (FLINT_BITS / 2))) { fmpz_set_ui(r, a * b); } else { fmpz_set_ui(r, a); fmpz_mul_ui(r, r, b); } } static inline void fmpz_max(fmpz_t z, const fmpz_t x, const fmpz_t y) { if (fmpz_cmp(x, y) >= 0) fmpz_set(z, x); else fmpz_set(z, y); } static inline void fmpz_min(fmpz_t z, const fmpz_t x, const fmpz_t y) { if (fmpz_cmp(x, y) < 0) fmpz_set(z, x); else fmpz_set(z, y); } #define FMPZ_GET_MPN_READONLY(zsign, zn, zptr, ztmp, zv) \ if (!COEFF_IS_MPZ(zv)) \ { \ (zsign) = (zv) < 0; \ (ztmp) = FLINT_ABS(zv); \ (zptr) = &(ztmp); \ (zn) = 1; \ } \ else \ { \ __mpz_struct * ___zz = COEFF_TO_PTR(zv); \ (zptr) = ___zz->_mp_d; \ (zn) = ___zz->_mp_size; \ (zsign) = (zn) < 0; \ (zn) = FLINT_ABS(zn); \ } void fmpz_lshift_mpn(fmpz_t z, mp_srcptr d, mp_size_t dn, int sgnbit, flint_bitcnt_t shift); static inline slong fmpz_allocated_bytes(const fmpz_t x) { if (COEFF_IS_MPZ(*x)) return sizeof(__mpz_struct) + COEFF_TO_PTR(*x)->_mp_alloc * sizeof(mp_limb_t); else return 0; } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_extras/000077500000000000000000000000001461254215100157645ustar00rootroot00000000000000flint-3.1.3/src/fmpz_extras/lshift_mpn.c000066400000000000000000000022571461254215100203010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_extras.h" void fmpz_lshift_mpn(fmpz_t z, mp_srcptr d, mp_size_t dn, int sgnbit, flint_bitcnt_t shift) { __mpz_struct * zmpz; mp_ptr zp; mp_size_t zn, shift_limbs; flint_bitcnt_t shift_bits; zmpz = _fmpz_promote(z); shift_limbs = shift / FLINT_BITS; shift_bits = shift % FLINT_BITS; zn = dn + shift_limbs + (shift_bits != 0); if (zmpz->_mp_alloc < zn) mpz_realloc2(zmpz, zn * FLINT_BITS); zp = zmpz->_mp_d; flint_mpn_zero(zp, shift_limbs); if (shift_bits == 0) { flint_mpn_copyi(zp + shift_limbs, d, dn); } else { zp[zn - 1] = mpn_lshift(zp + shift_limbs, d, dn, shift_bits); while (zp[zn - 1] == 0) zn--; } zmpz->_mp_size = sgnbit ? -(slong) zn : zn; _fmpz_demote_val(z); } flint-3.1.3/src/fmpz_extras/sub_small_large.c000066400000000000000000000013501461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_extras.h" slong _fmpz_sub_small_large(const fmpz_t x, const fmpz_t y) { fmpz_t t; fmpz_init(t); fmpz_sub(t, x, y); if (!COEFF_IS_MPZ(*t)) { /* no need to free t */ return *t; } else { int sign = fmpz_sgn(t); fmpz_clear(t); return (sign > 0) ? WORD_MAX : -WORD_MAX; } } flint-3.1.3/src/fmpz_extras/test/000077500000000000000000000000001461254215100167435ustar00rootroot00000000000000flint-3.1.3/src/fmpz_extras/test/main.c000066400000000000000000000021351461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add2_fmpz_si_inline.c" #include "t-add_inline.c" #include "t-add_si_inline.c" #include "t-add_ui_inline.c" #include "t-lshift_mpn.c" #include "t-sub_si_inline.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_add2_fmpz_si_inline), TEST_FUNCTION(fmpz_add_inline), TEST_FUNCTION(fmpz_add_si_inline), TEST_FUNCTION(fmpz_add_ui_inline), TEST_FUNCTION(fmpz_lshift_mpn), TEST_FUNCTION(fmpz_sub_si_inline) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_extras/test/t-add2_fmpz_si_inline.c000066400000000000000000000065711461254215100232600ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_extras.h" TEST_FUNCTION_START(fmpz_add2_fmpz_si_inline, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, b, c, d; slong e; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_randtest(a, state, 1 + n_randint(state, 200)); fmpz_randtest(b, state, 1 + n_randint(state, 200)); fmpz_randtest(c, state, 1 + n_randint(state, 200)); fmpz_randtest(d, state, 1 + n_randint(state, 200)); e = n_randtest(state); fmpz_add(c, a, b); fmpz_add_si(c, c, e); fmpz_add2_fmpz_si_inline(d, a, b, e); if (!fmpz_equal(c, d)) { flint_printf("FAIL\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_printf("%wd\n\n", e); flint_abort(); } fmpz_add2_fmpz_si_inline(a, a, b, e); if (!fmpz_equal(c, a)) { flint_printf("FAIL (aliasing 1)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_printf("%wd\n\n", e); flint_abort(); } fmpz_randtest(a, state, 1 + n_randint(state, 200)); fmpz_add(c, a, b); fmpz_add_si(c, c, e); fmpz_add2_fmpz_si_inline(b, a, b, e); if (!fmpz_equal(c, b)) { flint_printf("FAIL (aliasing 2)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_printf("%wd\n\n", e); flint_abort(); } fmpz_add(d, a, a); fmpz_add_si(d, d, e); fmpz_add2_fmpz_si_inline(c, a, a, e); if (!fmpz_equal(c, d)) { flint_printf("FAIL (aliasing 3)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_printf("%wd\n\n", e); flint_abort(); } fmpz_add(d, a, a); fmpz_add_si(d, d, e); fmpz_add2_fmpz_si_inline(a, a, a, e); if (!fmpz_equal(d, a)) { flint_printf("FAIL (aliasing 4)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_printf("%wd\n\n", e); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_extras/test/t-add_inline.c000066400000000000000000000057041461254215100214440ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_extras.h" TEST_FUNCTION_START(fmpz_add_inline, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, b, c, d; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_randtest(a, state, 1 + n_randint(state, 200)); fmpz_randtest(b, state, 1 + n_randint(state, 200)); fmpz_randtest(c, state, 1 + n_randint(state, 200)); fmpz_randtest(d, state, 1 + n_randint(state, 200)); fmpz_add(c, a, b); fmpz_add_inline(d, a, b); if (!fmpz_equal(c, d)) { flint_printf("FAIL\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_add_inline(a, a, b); if (!fmpz_equal(c, a)) { flint_printf("FAIL (aliasing 1)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_randtest(a, state, 1 + n_randint(state, 200)); fmpz_add(c, a, b); fmpz_add_inline(b, a, b); if (!fmpz_equal(c, b)) { flint_printf("FAIL (aliasing 2)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_add(d, a, a); fmpz_add_inline(c, a, a); if (!fmpz_equal(c, d)) { flint_printf("FAIL (aliasing 3)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_add(d, a, a); fmpz_add_inline(a, a, a); if (!fmpz_equal(d, a)) { flint_printf("FAIL (aliasing 4)\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_extras/test/t-add_si_inline.c000066400000000000000000000033461461254215100221370ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_extras.h" TEST_FUNCTION_START(fmpz_add_si_inline, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, c, d; slong b; fmpz_init(a); fmpz_init(c); fmpz_init(d); fmpz_randtest(a, state, 1 + n_randint(state, 200)); fmpz_randtest(c, state, 1 + n_randint(state, 200)); fmpz_randtest(d, state, 1 + n_randint(state, 200)); b = n_randtest(state); fmpz_add_si(c, a, b); fmpz_add_si_inline(d, a, b); if (!fmpz_equal(c, d)) { flint_printf("FAIL\n"); fmpz_print(a); flint_printf("\n\n"); flint_printf("%wd", b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_add_si_inline(a, a, b); if (!fmpz_equal(c, a)) { flint_printf("FAIL (aliasing)\n"); fmpz_print(a); flint_printf("\n\n"); flint_printf("%wd", b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_extras/test/t-add_ui_inline.c000066400000000000000000000033461461254215100221410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_extras.h" TEST_FUNCTION_START(fmpz_add_ui_inline, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, c, d; ulong b; fmpz_init(a); fmpz_init(c); fmpz_init(d); fmpz_randtest(a, state, 1 + n_randint(state, 200)); fmpz_randtest(c, state, 1 + n_randint(state, 200)); fmpz_randtest(d, state, 1 + n_randint(state, 200)); b = n_randtest(state); fmpz_add_ui(c, a, b); fmpz_add_ui_inline(d, a, b); if (!fmpz_equal(c, d)) { flint_printf("FAIL\n"); fmpz_print(a); flint_printf("\n\n"); flint_printf("%wu", b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_add_ui_inline(a, a, b); if (!fmpz_equal(c, a)) { flint_printf("FAIL (aliasing)\n"); fmpz_print(a); flint_printf("\n\n"); flint_printf("%wu", b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_extras/test/t-lshift_mpn.c000066400000000000000000000027561461254215100215250ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_extras.h" TEST_FUNCTION_START(fmpz_lshift_mpn, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, b, c; ulong e; mp_limb_t atmp; mp_ptr aptr; mp_size_t an; int asgnbit; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_randtest_not_zero(a, state, 1 + n_randint(state, 2000)); fmpz_randtest(b, state, 1 + n_randint(state, 2000)); fmpz_randtest(c, state, 1 + n_randint(state, 2000)); e = n_randint(state, 1000); FMPZ_GET_MPN_READONLY(asgnbit, an, aptr, atmp, *a) fmpz_lshift_mpn(b, aptr, an, asgnbit, e); fmpz_mul_2exp(c, a, e); if (!fmpz_equal(b, c)) { flint_printf("FAIL\n"); fmpz_print(a); flint_printf("\n\n"); fmpz_print(b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_extras/test/t-sub_si_inline.c000066400000000000000000000033461461254215100222000ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_extras.h" TEST_FUNCTION_START(fmpz_sub_si_inline, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_t a, c, d; slong b; fmpz_init(a); fmpz_init(c); fmpz_init(d); fmpz_randtest(a, state, 1 + n_randint(state, 200)); fmpz_randtest(c, state, 1 + n_randint(state, 200)); fmpz_randtest(d, state, 1 + n_randint(state, 200)); b = n_randtest(state); fmpz_sub_si(c, a, b); fmpz_sub_si_inline(d, a, b); if (!fmpz_equal(c, d)) { flint_printf("FAIL\n"); fmpz_print(a); flint_printf("\n\n"); flint_printf("%wd", b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_sub_si_inline(a, a, b); if (!fmpz_equal(c, a)) { flint_printf("FAIL (aliasing)\n"); fmpz_print(a); flint_printf("\n\n"); flint_printf("%wd", b); flint_printf("\n\n"); fmpz_print(c); flint_printf("\n\n"); fmpz_print(d); flint_printf("\n\n"); flint_abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_factor.h000066400000000000000000000117311461254215100161100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_FACTOR_H #define FMPZ_FACTOR_H #ifdef FMPZ_FACTOR_INLINES_C #define FMPZ_FACTOR_INLINE #else #define FMPZ_FACTOR_INLINE static inline \ error fmpz_factor/inline.c currently does not exist as no function has been inlined #endif #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif /* Utility functions *********************************************************/ void fmpz_factor_init(fmpz_factor_t factor); void fmpz_factor_clear(fmpz_factor_t factor); void _fmpz_factor_fit_length(fmpz_factor_t factor, slong len); void _fmpz_factor_set_length(fmpz_factor_t factor, slong newlen); void _fmpz_factor_append(fmpz_factor_t factor, const fmpz_t p, ulong exp); void _fmpz_factor_append_ui(fmpz_factor_t factor, mp_limb_t p, ulong exp); void _fmpz_factor_concat(fmpz_factor_t factor1, fmpz_factor_t factor2, ulong exp); /* I/O ***********************************************************************/ #ifdef FLINT_HAVE_FILE int fmpz_factor_fprint(FILE * fs, const fmpz_factor_t factor); #endif int fmpz_factor_print(const fmpz_factor_t factor); /* Factoring *****************************************************************/ void _fmpz_factor_extend_factor_ui(fmpz_factor_t factor, mp_limb_t n); int fmpz_factor_trial_range(fmpz_factor_t factor, const fmpz_t n, ulong start, ulong num_primes); int fmpz_factor_trial(fmpz_factor_t factor, const fmpz_t n, slong num_primes); void fmpz_factor_no_trial(fmpz_factor_t factor, const fmpz_t n); void fmpz_factor_si(fmpz_factor_t factor, slong n); void fmpz_factor(fmpz_factor_t factor, const fmpz_t n); int fmpz_factor_smooth(fmpz_factor_t factor, const fmpz_t n, slong bits, int proved); int fmpz_factor_pp1(fmpz_t factor, const fmpz_t n, ulong B1, ulong B2_sqrt, ulong c); void fmpz_factor_refine(fmpz_factor_t res, const fmpz_factor_t f); void flint_mpn_sqr_and_add_a(mp_ptr y, mp_ptr a, mp_ptr n, mp_limb_t n_size, mp_ptr ninv, mp_limb_t normbits); int flint_mpn_factor_pollard_brent_single(mp_ptr factor, mp_ptr n, mp_ptr ninv, mp_ptr a, mp_ptr y, mp_limb_t n_size, mp_limb_t normbits, mp_limb_t max_iters); int fmpz_factor_pollard_brent_single(fmpz_t p_factor, fmpz_t n_in, fmpz_t yi, fmpz_t ai, mp_limb_t max_iters); int fmpz_factor_pollard_brent(fmpz_t factor, flint_rand_t state, fmpz_t n, mp_limb_t max_tries, mp_limb_t max_iters); /* Expansion *****************************************************************/ void fmpz_factor_expand_iterative(fmpz_t n, const fmpz_factor_t factor); void fmpz_factor_expand_multiexp(fmpz_t n, const fmpz_factor_t factor); void fmpz_factor_expand(fmpz_t n, const fmpz_factor_t factor); /* Multiplicative functions **************************************************/ void fmpz_factor_euler_phi(fmpz_t res, const fmpz_factor_t fac); int fmpz_factor_moebius_mu(const fmpz_factor_t fac); void fmpz_factor_divisor_sigma(fmpz_t res, ulong k, const fmpz_factor_t fac); /* ECM Factoring functions ***************************************************/ typedef struct ecm_s { mp_ptr t, u, v, w; /* temp variables */ mp_ptr x, z; /* the coordinates */ mp_ptr a24; /* value (a + 2)/4 */ mp_ptr ninv; /* invere of n */ mp_ptr one; /* one shifted */ unsigned char *GCD_table; /* checks whether baby step int is coprime to Primorial or not */ unsigned char **prime_table; mp_limb_t n_size; mp_limb_t normbits; } ecm_s; typedef ecm_s ecm_t[1]; void fmpz_factor_ecm_init(ecm_t ecm_inf, mp_limb_t sz); void fmpz_factor_ecm_clear(ecm_t ecm_inf); void fmpz_factor_ecm_addmod(mp_ptr a, mp_ptr b, mp_ptr c, mp_ptr n, mp_limb_t n_size); void fmpz_factor_ecm_submod(mp_ptr x, mp_ptr a, mp_ptr b, mp_ptr n, mp_limb_t n_size); void fmpz_factor_ecm_double(mp_ptr x, mp_ptr z, mp_ptr x0, mp_ptr z0, mp_ptr n, ecm_t ecm_inf); void fmpz_factor_ecm_add(mp_ptr x, mp_ptr z, mp_ptr x1, mp_ptr z1, mp_ptr x2, mp_ptr z2, mp_ptr x0, mp_ptr z0, mp_ptr n, ecm_t ecm_inf); void fmpz_factor_ecm_mul_montgomery_ladder(mp_ptr x, mp_ptr z, mp_ptr x0, mp_ptr z0, mp_limb_t k, mp_ptr n, ecm_t ecm_inf); int fmpz_factor_ecm_select_curve(mp_ptr f, mp_ptr sig, mp_ptr n, ecm_t ecm_inf); int fmpz_factor_ecm_stage_I(mp_ptr f, const mp_limb_t *prime_array, mp_limb_t num, mp_limb_t B1, mp_ptr n, ecm_t ecm_inf); int fmpz_factor_ecm_stage_II(mp_ptr f, mp_limb_t B1, mp_limb_t B2, mp_limb_t P, mp_ptr n, ecm_t ecm_inf); int fmpz_factor_ecm(fmpz_t f, mp_limb_t curves, mp_limb_t B1, mp_limb_t B2, flint_rand_t state, const fmpz_t n_in); /* Inlines *******************************************************************/ void fmpz_factor_get_fmpz(fmpz_t z, const fmpz_factor_t factor, slong i); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_factor/000077500000000000000000000000001461254215100157345ustar00rootroot00000000000000flint-3.1.3/src/fmpz_factor/append.c000066400000000000000000000016431461254215100173530ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" void _fmpz_factor_append(fmpz_factor_t factor, const fmpz_t p, ulong exp) { _fmpz_factor_fit_length(factor, factor->num + 1); fmpz_set(factor->p + factor->num, p); factor->exp[factor->num] = exp; factor->num++; } void _fmpz_factor_append_ui(fmpz_factor_t factor, mp_limb_t p, ulong exp) { _fmpz_factor_fit_length(factor, factor->num + 1); fmpz_set_ui(factor->p + factor->num, p); factor->exp[factor->num] = exp; factor->num++; } flint-3.1.3/src/fmpz_factor/clear.c000066400000000000000000000011261461254215100171660ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" #include "fmpz_vec.h" void fmpz_factor_clear(fmpz_factor_t factor) { _fmpz_vec_clear(factor->p, factor->alloc); flint_free(factor->exp); } flint-3.1.3/src/fmpz_factor/concat.c000066400000000000000000000015201461254215100173450ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" void _fmpz_factor_concat(fmpz_factor_t factor1, fmpz_factor_t factor2, ulong exp) { slong i; _fmpz_factor_fit_length(factor1, factor1->num + factor2->num); for (i = 0; i < factor2->num; i++) { fmpz_set(factor1->p + factor1->num + i, factor2->p + i); factor1->exp[factor1->num + i] = factor2->exp[i]*exp; } factor1->num += factor2->num; } flint-3.1.3/src/fmpz_factor/ecm.c000066400000000000000000000162061461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Outer wrapper for ECM makes calls to stage I and stage II (one) */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" static ulong n_ecm_primorial[] = { #ifdef FLINT64 UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030), UWORD(510510), UWORD(9699690), UWORD(223092870), UWORD(6469693230), UWORD(200560490130), UWORD(7420738134810), UWORD(304250263527210), UWORD(13082761331670030), UWORD(614889782588491410) /* 15 values */ #else UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030), UWORD(510510), UWORD(9699690) /* 9 values */ #endif }; #ifdef FLINT64 #define num_n_ecm_primorials 15 #else #define num_n_ecm_primorials 9 #endif int fmpz_factor_ecm(fmpz_t f, mp_limb_t curves, mp_limb_t B1, mp_limb_t B2, flint_rand_t state, const fmpz_t n_in) { fmpz_t sig, nm8; mp_limb_t P, num, maxP, mmin, mmax, mdiff, prod, maxj, n_size, cy; int i, j, ret; ecm_t ecm_inf; __mpz_struct *fac, *mptr; mp_ptr n, mpsig; TMP_INIT; const mp_limb_t *prime_array; n_size = fmpz_size(n_in); if (n_size == 1) { ret = n_factor_ecm(&P, curves, B1, B2, state, fmpz_get_ui(n_in)); fmpz_set_ui(f, P); return ret; } fmpz_factor_ecm_init(ecm_inf, n_size); TMP_START; n = TMP_ALLOC(n_size * sizeof(mp_limb_t)); mpsig = TMP_ALLOC(n_size * sizeof(mp_limb_t)); if ((!COEFF_IS_MPZ(* n_in))) { ecm_inf->normbits = flint_clz(fmpz_get_ui(n_in)); n[0] = fmpz_get_ui(n_in); n[0] <<= ecm_inf->normbits; } else { mptr = COEFF_TO_PTR(* n_in); ecm_inf->normbits = flint_clz(mptr->_mp_d[n_size - 1]); if (ecm_inf->normbits) mpn_lshift(n, mptr->_mp_d, n_size, ecm_inf->normbits); else flint_mpn_copyi(n, mptr->_mp_d, n_size); } flint_mpn_preinvn(ecm_inf->ninv, n, n_size); ecm_inf->one[0] = UWORD(1) << ecm_inf->normbits; fmpz_init(sig); fmpz_init(nm8); fmpz_sub_ui(nm8, n_in, 8); ret = 0; fac = _fmpz_promote(f); mpz_realloc(fac, fmpz_size(n_in)); /************************ STAGE I PRECOMPUTATIONS ************************/ num = n_prime_pi(B1); /* number of primes under B1 */ /* compute list of primes under B1 for stage I */ prime_array = n_primes_arr_readonly(num); /************************ STAGE II PRECOMPUTATIONS ***********************/ maxP = n_sqrt(B2); /* Selecting primorial */ j = 1; while ((j < num_n_ecm_primorials) && (n_ecm_primorial[j] < maxP)) j += 1; P = n_ecm_primorial[j - 1]; mmin = (B1 + (P/2)) / P; mmax = ((B2 - P/2) + P - 1)/P; /* ceil */ if (mmax < mmin) { flint_throw(FLINT_ERROR, "Exception (ecm). B1 > B2 encountered.\n"); } maxj = (P + 1)/2; mdiff = mmax - mmin + 1; /* compute GCD_table */ ecm_inf->GCD_table = flint_malloc(maxj + 1); for (j = 1; j <= maxj; j += 2) { if ((j%2) && n_gcd(j, P) == 1) ecm_inf->GCD_table[j] = 1; else ecm_inf->GCD_table[j] = 0; } /* compute prime table */ ecm_inf->prime_table = flint_malloc(mdiff * sizeof(unsigned char*)); for (i = 0; i < mdiff; i++) ecm_inf->prime_table[i] = flint_malloc((maxj + 1) * sizeof(unsigned char)); for (i = 0; i < mdiff; i++) { for (j = 1; j <= maxj; j += 2) { ecm_inf->prime_table[i][j] = 0; /* if (i + mmin)*P + j is prime, mark 1. Can be possibly prime only if gcd(j, P) = 1 */ if (ecm_inf->GCD_table[j] == 1) { prod = (i + mmin)*P + j; if (n_is_prime(prod)) ecm_inf->prime_table[i][j] = 1; prod = (i + mmin)*P - j; if (n_is_prime(prod)) ecm_inf->prime_table[i][j] = 1; } } } /****************************** TRY "CURVES" *****************************/ for (j = 0; j < curves; j++) { fmpz_randm(sig, state, nm8); fmpz_add_ui(sig, sig, 7); mpn_zero(mpsig, ecm_inf->n_size); if ((!COEFF_IS_MPZ(*sig))) { mpsig[0] = fmpz_get_ui(sig); if (ecm_inf->normbits) { cy = mpn_lshift(mpsig, mpsig, 1, ecm_inf->normbits); if (cy) mpsig[1] = cy; } } else { mptr = COEFF_TO_PTR(*sig); if (ecm_inf->normbits) { cy = mpn_lshift(mpsig, mptr->_mp_d, mptr->_mp_size, ecm_inf->normbits); if (cy) mpsig[mptr->_mp_size] = cy; } else { flint_mpn_copyi(mpsig, mptr->_mp_d, mptr->_mp_size); } } /************************ SELECT CURVE ************************/ ret = fmpz_factor_ecm_select_curve(fac->_mp_d, mpsig, n, ecm_inf); if (ret) { /* Found factor while selecting curve, very very lucky :) */ if (ecm_inf->normbits) mpn_rshift(fac->_mp_d, fac->_mp_d, ret, ecm_inf->normbits); MPN_NORM(fac->_mp_d, ret); fac->_mp_size = ret; _fmpz_demote_val(f); ret = -1; goto cleanup; } if (ret != -1) { /************************** STAGE I ***************************/ ret = fmpz_factor_ecm_stage_I(fac->_mp_d, prime_array, num, B1, n, ecm_inf); if (ret) { /* Found factor after stage I */ if (ecm_inf->normbits) mpn_rshift(fac->_mp_d, fac->_mp_d, ret, ecm_inf->normbits); MPN_NORM(fac->_mp_d, ret); fac->_mp_size = ret; _fmpz_demote_val(f); ret = 1; goto cleanup; } /************************** STAGE II ***************************/ ret = fmpz_factor_ecm_stage_II(fac->_mp_d, B1, B2, P, n, ecm_inf); if (ret) { /* Found factor after stage II */ if (ecm_inf->normbits) mpn_rshift(fac->_mp_d, fac->_mp_d, ret, ecm_inf->normbits); MPN_NORM(fac->_mp_d, ret); fac->_mp_size = ret; _fmpz_demote_val(f); ret = 2; goto cleanup; } } } cleanup: flint_free(ecm_inf->GCD_table); for (i = 0; i < mdiff; i++) flint_free(ecm_inf->prime_table[i]); flint_free(ecm_inf->prime_table); fmpz_factor_ecm_clear(ecm_inf); fmpz_clear(nm8); fmpz_clear(sig); TMP_END; return ret; } flint-3.1.3/src/fmpz_factor/ecm_add.c000066400000000000000000000057751461254215100174720ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Outer wrapper for ECM makes calls to stage I and stage II (two) */ #include "mpn_extras.h" #include "fmpz_factor.h" /* P (x : z) = P1 (x1 : z1) + P2 (x2 : z2) where P0 (x0 : zo) is P - Q */ /* Coordinates of P : x = 4 * z0 * (x1 * x2 - z1 * z2)^2 mod n z = 4 * x0 * (x2 * z1 - x1 * z2)^2 mod n */ void fmpz_factor_ecm_add(mp_ptr x, mp_ptr z, mp_ptr x1, mp_ptr z1, mp_ptr x2, mp_ptr z2, mp_ptr x0, mp_ptr z0, mp_ptr n, ecm_t ecm_inf) { if (flint_mpn_zero_p(z1, ecm_inf->n_size)) { flint_mpn_copyi(x, x2, ecm_inf->n_size); flint_mpn_copyi(z, z2, ecm_inf->n_size); return; } if (flint_mpn_zero_p(z2, ecm_inf->n_size)) { flint_mpn_copyi(x, x1, ecm_inf->n_size); flint_mpn_copyi(z, z1, ecm_inf->n_size); return; } if (flint_mpn_zero_p(z0, ecm_inf->n_size)) { fmpz_factor_ecm_double(x, z, x1, z1, n, ecm_inf); return; } /* u = (x2 - z2) */ fmpz_factor_ecm_submod(ecm_inf->u, x2, z2, n, ecm_inf->n_size); /* v = (x1 + z1) */ fmpz_factor_ecm_addmod(ecm_inf->v, x1, z1, n, ecm_inf->n_size); /* u = (x2 - z2) * (x1 + z1) */ flint_mpn_mulmod_preinvn(ecm_inf->u, ecm_inf->u, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* v = (x1 - z1) */ fmpz_factor_ecm_submod(ecm_inf->v, x1, z1, n, ecm_inf->n_size); /* w = (x2 + z2) */ fmpz_factor_ecm_addmod(ecm_inf->w, x2, z2, n, ecm_inf->n_size); /* v = (x1 - z1) * (x2 + z2) */ flint_mpn_mulmod_preinvn(ecm_inf->v, ecm_inf->v, ecm_inf->w, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* w = 2 * (x1 * x2 - z1 * z2) */ fmpz_factor_ecm_addmod(ecm_inf->w, ecm_inf->u, ecm_inf->v, n, ecm_inf->n_size); /* v = 2 * (x2 * z1 - x1 * z2) */ fmpz_factor_ecm_submod(ecm_inf->v, ecm_inf->v, ecm_inf->u, n, ecm_inf->n_size); /* w = 4 * (x1 * x2 - z1 * z2)^2 */ flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->w, ecm_inf->w, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* v = 4 * (x2 * z1 - x1 * z2)^2 */ flint_mpn_mulmod_preinvn(ecm_inf->v, ecm_inf->v, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* x = 4 * z0 * (x1 * x2 - z1 * z2)^2 */ flint_mpn_mulmod_preinvn(x, z0, ecm_inf->w, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* z = 4 * x0 * (x2 * z1 - x1 * z2)^2 */ flint_mpn_mulmod_preinvn(z, x0, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); } flint-3.1.3/src/fmpz_factor/ecm_addmod.c000066400000000000000000000014021461254215100201510ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" /* a = (b + c) mod n Not a normal add mod function, assumes n is normalized (highest bit set) and b and c are reduced modulo n */ void fmpz_factor_ecm_addmod(mp_ptr a, mp_ptr b, mp_ptr c, mp_ptr n, mp_limb_t n_size) { mp_limb_t cy; cy = mpn_add_n(a, b, c, n_size); if (cy || (mpn_cmp(a, n, n_size) > 0)) mpn_sub_n(a, a, n, n_size); } flint-3.1.3/src/fmpz_factor/ecm_clear.c000066400000000000000000000013111461254215100200060ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" void fmpz_factor_ecm_clear(ecm_t ecm_inf) { flint_free(ecm_inf->t); flint_free(ecm_inf->u); flint_free(ecm_inf->v); flint_free(ecm_inf->w); flint_free(ecm_inf->x); flint_free(ecm_inf->z); flint_free(ecm_inf->a24); flint_free(ecm_inf->ninv); flint_free(ecm_inf->one); } flint-3.1.3/src/fmpz_factor/ecm_double.c000066400000000000000000000042731461254215100202040ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz_factor.h" /* P (x : z) = 2 * P1 (x0 : z0) */ /* Coordinates of P : x = (x0 + z0)^2 * (x0 - z0)^2 mod n z = 4 * x0 * z0 * ((x0 - z0)^2 + a24 * 4 * x0 * z0) mod n */ void fmpz_factor_ecm_double(mp_ptr x, mp_ptr z, mp_ptr x0, mp_ptr z0, mp_ptr n, ecm_t ecm_inf) { if (flint_mpn_zero_p(z0, ecm_inf->n_size)) { flint_mpn_copyi(x, x0, ecm_inf->n_size); mpn_zero(z, ecm_inf->n_size); return; } /* u = x0 + z0 */ fmpz_factor_ecm_addmod(ecm_inf->u, x0, z0, n, ecm_inf->n_size); /* u = (x0 + z0)^2 */ flint_mpn_mulmod_preinvn(ecm_inf->u, ecm_inf->u, ecm_inf->u, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* v = x0 - z0 */ fmpz_factor_ecm_submod(ecm_inf->v, x0, z0, n, ecm_inf->n_size); /* v = (x0 - z0)^2 */ flint_mpn_mulmod_preinvn(ecm_inf->v, ecm_inf->v, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* x = (x0 + z0)^2 * (x0 - z0)^2 */ flint_mpn_mulmod_preinvn(x, ecm_inf->u, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* w = 4 * x0 * z0 */ fmpz_factor_ecm_submod(ecm_inf->w, ecm_inf->u, ecm_inf->v, n, ecm_inf->n_size); /* u = a24 * 4 * x0 * z0 */ flint_mpn_mulmod_preinvn(ecm_inf->u, ecm_inf->w, ecm_inf->a24, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); /* u = (x0 - z0)^2 + a24 * 4 * x0 * z0 */ fmpz_factor_ecm_addmod(ecm_inf->u, ecm_inf->u, ecm_inf->v, n, ecm_inf->n_size); /* z = 4 * x0 * z0 * ((x0 - z0)^2 + a24 * 4 * x0 * z0) */ flint_mpn_mulmod_preinvn(z, ecm_inf->w, ecm_inf->u, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); } flint-3.1.3/src/fmpz_factor/ecm_init.c000066400000000000000000000023741461254215100176750ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" void fmpz_factor_ecm_init(ecm_t ecm_inf, mp_limb_t sz) { ecm_inf->t = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->u = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->v = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->w = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->x = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->z = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->a24 = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->ninv = flint_malloc(sz * sizeof(mp_limb_t)); ecm_inf->one = flint_malloc(sz * sizeof(mp_limb_t)); mpn_zero(ecm_inf->t, sz); mpn_zero(ecm_inf->u, sz); mpn_zero(ecm_inf->v, sz); mpn_zero(ecm_inf->w, sz); mpn_zero(ecm_inf->x, sz); mpn_zero(ecm_inf->z, sz); mpn_zero(ecm_inf->a24, sz); mpn_zero(ecm_inf->ninv, sz); mpn_zero(ecm_inf->one, sz); ecm_inf->n_size = sz; } flint-3.1.3/src/fmpz_factor/ecm_mul_montgomery_ladder.c000066400000000000000000000044121461254215100233150ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_factor.h" /* P (x0 : z0) <- kP using Montgomery ladder algorithm */ /* tstbit uses 0 based indexing */ void fmpz_factor_ecm_mul_montgomery_ladder(mp_ptr x, mp_ptr z, mp_ptr x0, mp_ptr z0, mp_limb_t k, mp_ptr n, ecm_t ecm_inf) { mp_ptr x1, z1, x2, z2; /* Q (x1 : z1), P (x2 : z2) */ mp_limb_t len; TMP_INIT; if (k == 0) { mpn_zero(x, ecm_inf->n_size); mpn_zero(z, ecm_inf->n_size); return; } if (k == 1) { flint_mpn_copyi(x, x0, ecm_inf->n_size); flint_mpn_copyi(z, z0, ecm_inf->n_size); return; } TMP_START; x1 = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); z1 = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); x2 = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); z2 = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); flint_mpn_copyi(x1, x0, ecm_inf->n_size); /* Q <- P0 */ flint_mpn_copyi(z1, z0, ecm_inf->n_size); mpn_zero(x2, ecm_inf->n_size); mpn_zero(z2, ecm_inf->n_size); fmpz_factor_ecm_double(x2, z2, x0, z0, n, ecm_inf); /* P <- 2P0 */ len = n_sizeinbase(k, 2) - 2; while (1) { if (((UWORD(1) << len) & k) != 0) /* ith bit is 1 */ { /* Q <- P + Q */ fmpz_factor_ecm_add(x1, z1, x1, z1, x2, z2, x0, z0, n, ecm_inf); /* P <- 2 * P */ fmpz_factor_ecm_double(x2, z2, x2, z2, n, ecm_inf); } else { /* P <- P + Q */ fmpz_factor_ecm_add(x2, z2, x1, z1, x2, z2, x0, z0, n, ecm_inf); /* Q <- 2 * Q */ fmpz_factor_ecm_double(x1, z1, x1, z1, n, ecm_inf); } if (len == 0) break; else len -= 1; } flint_mpn_copyi(x, x1, ecm_inf->n_size); flint_mpn_copyi(z, z1, ecm_inf->n_size); TMP_END; } flint-3.1.3/src/fmpz_factor/ecm_select_curve.c000066400000000000000000000144531461254215100214160ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz_factor.h" /* Select Montgomery Elliptic Curve given a sigma (Suyama's parameterization) Returns 1 in case factor is found while selecting the curve. */ /* Also selects initial point Q0 [x0 :: z0] (z0 = 1) */ int fmpz_factor_ecm_select_curve(mp_ptr f, mp_ptr sig, mp_ptr n, ecm_t ecm_inf) { mp_size_t sz, cy; mp_size_t invlimbs, gcdlimbs; mp_ptr temp, tempv, tempn, tempi, tempf; int ret; TMP_INIT; TMP_START; temp = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); tempv = TMP_ALLOC((ecm_inf->n_size) * sizeof(mp_limb_t)); tempn = TMP_ALLOC((ecm_inf->n_size) * sizeof(mp_limb_t)); tempi = TMP_ALLOC((ecm_inf->n_size + 1) * sizeof(mp_limb_t)); tempf = TMP_ALLOC((ecm_inf->n_size + 1) * sizeof(mp_limb_t)); mpn_zero(tempn, ecm_inf->n_size); mpn_zero(tempv, ecm_inf->n_size); mpn_zero(temp, ecm_inf->n_size); flint_mpn_copyi(ecm_inf->u, sig, ecm_inf->n_size); temp[0] = UWORD(4); ret = 0; if (ecm_inf->normbits) mpn_lshift(temp, temp, ecm_inf->n_size, ecm_inf->normbits); /* temp = (4 << norm) */ flint_mpn_mulmod_preinvn(ecm_inf->v, ecm_inf->u, temp, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->u, ecm_inf->u, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); mpn_add_n(temp, temp, ecm_inf->one, ecm_inf->n_size); /* temp = (5 << norm) */ fmpz_factor_ecm_submod(ecm_inf->u, ecm_inf->w, temp, n, ecm_inf->n_size); flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->u, ecm_inf->u, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->x, ecm_inf->w, ecm_inf->u, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->v, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->z, ecm_inf->w, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->x, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); mpn_sub_n(temp, temp, ecm_inf->one, ecm_inf->n_size); /* temp = (4 << norm) */ flint_mpn_mulmod_preinvn(ecm_inf->t, ecm_inf->w, temp, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); mpn_sub_n(temp, temp, ecm_inf->one, ecm_inf->n_size); /* temp = (3 << norm) */ flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->u, temp, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); fmpz_factor_ecm_submod(ecm_inf->u, ecm_inf->v, ecm_inf->u, n, ecm_inf->n_size); fmpz_factor_ecm_addmod(ecm_inf->v, ecm_inf->v, ecm_inf->w, n, ecm_inf->n_size); flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->u, ecm_inf->u, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->u, ecm_inf->u, ecm_inf->w, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->a24, ecm_inf->u, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->v, ecm_inf->t, ecm_inf->z, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); sz = ecm_inf->n_size; MPN_NORM(ecm_inf->v, sz); /* sz has number of limbs of v */ if (sz == 0) /* v = 0, gcd(0, n) = n. Hence inverse will not exist. */ { /* No point in further computation with curve */ ret = (-1); goto cleanup; } flint_mpn_copyi(tempv, ecm_inf->v, sz); flint_mpn_copyi(tempn, n, ecm_inf->n_size); gcdlimbs = mpn_gcdext(tempf, tempi, &invlimbs, tempv, sz, tempn, ecm_inf->n_size); if (!(gcdlimbs == 1 && tempf[0] == ecm_inf->one[0]) && !(gcdlimbs == ecm_inf->n_size && mpn_cmp(tempf, n, ecm_inf->n_size) == 0)) { /* Found factor */ flint_mpn_copyi(f, tempf, gcdlimbs); ret = gcdlimbs; goto cleanup; } if (invlimbs < 0) /* negative inverse, add n */ { invlimbs *= -1; if (ecm_inf->normbits) { cy = mpn_lshift(tempi, tempi, invlimbs, ecm_inf->normbits); if (cy) tempi[invlimbs] = cy; } mpn_sub_n(tempi, n, tempi, ecm_inf->n_size);\ } else { if (ecm_inf->normbits) { cy = mpn_lshift(tempi, tempi, invlimbs, ecm_inf->normbits); if (cy) tempi[invlimbs] = cy; } } MPN_NORM(tempi, invlimbs); mpn_zero(ecm_inf->u, ecm_inf->n_size); flint_mpn_copyi(ecm_inf->u, tempi, invlimbs); flint_mpn_mulmod_preinvn(ecm_inf->v, ecm_inf->u, ecm_inf->t, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->x, ecm_inf->x, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->v, ecm_inf->u, ecm_inf->z, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(ecm_inf->w, ecm_inf->a24, ecm_inf->v, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); mpn_zero(temp, sz); temp[0] = UWORD(2); if (ecm_inf->normbits) mpn_lshift(temp, temp, ecm_inf->n_size, ecm_inf->normbits); fmpz_factor_ecm_addmod(ecm_inf->a24, ecm_inf->w, temp, n, ecm_inf->n_size); mpn_rshift(ecm_inf->a24, ecm_inf->a24, ecm_inf->n_size, 2); if (ecm_inf->normbits) ecm_inf->a24[0] &= ~((UWORD(1)<normbits) - 1); flint_mpn_copyi(ecm_inf->z, ecm_inf->one, ecm_inf->n_size); cleanup: TMP_END; return ret; } flint-3.1.3/src/fmpz_factor/ecm_stage_I.c000066400000000000000000000032111461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz_factor.h" /* Implementation of the stage I of ECM */ int fmpz_factor_ecm_stage_I(mp_ptr f, const mp_limb_t *prime_array, mp_limb_t num, mp_limb_t B1, mp_ptr n, ecm_t ecm_inf) { mp_limb_t times; mp_size_t sz, gcdlimbs; int i, j, p; for (i = 0; i < num; i++) { p = n_flog(B1, prime_array[i]); times = prime_array[i]; for (j = 1; j <= p; j ++) { fmpz_factor_ecm_mul_montgomery_ladder(ecm_inf->x, ecm_inf->z, ecm_inf->x, ecm_inf->z, times, n, ecm_inf); } sz = ecm_inf->n_size; MPN_NORM(ecm_inf->z, sz); if (sz == 0) return 0; gcdlimbs = flint_mpn_gcd_full(f, n, ecm_inf->n_size, ecm_inf->z, sz); /* condition one -> gcd = n_ecm->one condition two -> gcd = n if neither is true, factor found */ if (!(gcdlimbs == 1 && f[0] == ecm_inf->one[0]) && !(gcdlimbs == ecm_inf->n_size && mpn_cmp(f, n, ecm_inf->n_size) == 0)) { /* Found factor in stage I */ return gcdlimbs; } } return 0; } flint-3.1.3/src/fmpz_factor/ecm_stage_II.c000066400000000000000000000122721461254215100204140ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz_factor.h" /* Implementation of the stage II of ECM */ int fmpz_factor_ecm_stage_II(mp_ptr f, mp_limb_t B1, mp_limb_t B2, mp_limb_t P, mp_ptr n, ecm_t ecm_inf) { mp_ptr Qx, Qz, Rx, Rz, Qdx, Qdz, a, b, g; mp_limb_t mmin, mmax, maxj, sz, gcdlimbs; int i, j, ret; mp_ptr arrx, arrz, Q0x2, Q0z2; TMP_INIT; mmin = (B1 + (P/2)) / P; mmax = ((B2 - P/2) + P - 1)/P; /* ceil */ maxj = (P + 1)/2; TMP_START; Qx = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); Qz = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); Rx = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); Rz = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); Qdx = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); Qdz = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); Q0x2 = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); Q0z2 = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); a = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); b = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); g = TMP_ALLOC(ecm_inf->n_size * sizeof(mp_limb_t)); arrx = flint_malloc(((maxj >> 1) + 1) * ecm_inf->n_size * sizeof(mp_limb_t)); arrz = flint_malloc(((maxj >> 1) + 1) * ecm_inf->n_size * sizeof(mp_limb_t)); mpn_zero(arrx, ((maxj >> 1) + 1) * ecm_inf->n_size); mpn_zero(arrz, ((maxj >> 1) + 1) * ecm_inf->n_size); mpn_zero(Q0x2, ecm_inf->n_size); mpn_zero(Q0z2, ecm_inf->n_size); mpn_zero(g, ecm_inf->n_size); g[0] = ecm_inf->one[0]; ret = 0; /* arr[0] = Q0 */ flint_mpn_copyi(arrx, ecm_inf->x, ecm_inf->n_size); flint_mpn_copyi(arrz, ecm_inf->z, ecm_inf->n_size); /* Q0x2, Q0z2 = 2Q0 */ fmpz_factor_ecm_double(Q0x2, Q0z2, arrx, arrz, n, ecm_inf); /* arr[1] = 3Q0 */ fmpz_factor_ecm_add(arrx + 1 * ecm_inf->n_size, arrz + 1 * ecm_inf->n_size, Q0x2, Q0z2, arrx, arrz, arrx, arrz, n, ecm_inf); /* For each odd j (j > 3) , compute j * Q0 [x0 :: z0] */ /* jth stored in arr[j/2] */ /* We are adding 2Q0 every time. Need to calculate all j's as (j - 2)Q0 is required for (j + 2)Q0 */ for (j = 2; j <= (maxj >> 1); j += 1) { /* jQ0 = (j - 2)Q0 + 2Q0 Difference is (j - 4)Q0 */ fmpz_factor_ecm_add(arrx + j * ecm_inf->n_size, arrz + j * ecm_inf->n_size, arrx + (j - 1) * ecm_inf->n_size, arrz + (j - 1) * ecm_inf->n_size, Q0x2, Q0z2, arrx + (j - 2) * ecm_inf->n_size, arrz + (j - 2) * ecm_inf->n_size, n, ecm_inf); } /* Q = P * Q_0 */ fmpz_factor_ecm_mul_montgomery_ladder(Qx, Qz, ecm_inf->x, ecm_inf->z, P, n, ecm_inf); /* R = mmin * Q */ fmpz_factor_ecm_mul_montgomery_ladder(Rx, Rz, Qx, Qz, mmin, n, ecm_inf); /* Qd = (mmin - 1) * Q */ fmpz_factor_ecm_mul_montgomery_ladder(Qdx, Qdz, Qx, Qz, mmin - 1, n, ecm_inf); /* main stage II step */ for (i = mmin; i <= mmax; i ++) { for (j = 1; j <= maxj; j += 2) { if (ecm_inf->prime_table[i - mmin][j] == 1) { flint_mpn_mulmod_preinvn(a, Rx, arrz + (j >> 1) * ecm_inf->n_size, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); flint_mpn_mulmod_preinvn(b, Rz, arrx + (j >> 1) * ecm_inf->n_size, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); fmpz_factor_ecm_submod(a, a, b, n, ecm_inf->n_size); flint_mpn_mulmod_preinvn(g, g, a, ecm_inf->n_size, n, ecm_inf->ninv, ecm_inf->normbits); } } flint_mpn_copyi(a, Rx, ecm_inf->n_size); flint_mpn_copyi(b, Rz, ecm_inf->n_size); /* R = R + Q difference is stored in Qd, initially (Mmin - 1)Q */ fmpz_factor_ecm_add(Rx, Rz, Rx, Rz, Qx, Qz, Qdx, Qdz, n, ecm_inf); flint_mpn_copyi(Qdx, a, ecm_inf->n_size); flint_mpn_copyi(Qdz, b, ecm_inf->n_size); } sz = ecm_inf->n_size; MPN_NORM(g, sz); if (sz == 0) { ret = 0; goto cleanup; } gcdlimbs = flint_mpn_gcd_full(f, n, ecm_inf->n_size, g, sz); /* condition one -> gcd = n_ecm->one condition two -> gcd = n if neither is true, factor found */ if (!(gcdlimbs == 1 && f[0] == ecm_inf->one[0]) && !(gcdlimbs == ecm_inf->n_size && mpn_cmp(f, n, ecm_inf->n_size) == 0)) { /* Found factor in stage II */ ret = gcdlimbs; goto cleanup; } cleanup: TMP_END; flint_free(arrx); flint_free(arrz); return ret; } flint-3.1.3/src/fmpz_factor/ecm_submod.c000066400000000000000000000016301461254215100202150ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" /* x = (a - b) mod n Not a normal sub mod function, assumes n is normalized (highest bit set) and a and b are reduced modulo n */ void fmpz_factor_ecm_submod(mp_ptr x, mp_ptr a, mp_ptr b, mp_ptr n, mp_limb_t n_size) { mp_ptr temp; TMP_INIT; TMP_START; temp = TMP_ALLOC(n_size * sizeof(mp_limb_t)); if (mpn_cmp(a, b, n_size) > 0) mpn_sub_n(x, a, b, n_size); else { mpn_sub_n(temp, n, b, n_size); mpn_add_n(x, temp, a, n_size); } TMP_END; } flint-3.1.3/src/fmpz_factor/expand.c000066400000000000000000000010071461254215100173550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" void fmpz_factor_expand(fmpz_t n, const fmpz_factor_t factor) { fmpz_factor_expand_multiexp(n, factor); } flint-3.1.3/src/fmpz_factor/expand_iterative.c000066400000000000000000000013511461254215100214330ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" void fmpz_factor_expand_iterative(fmpz_t n, const fmpz_factor_t factor) { slong i; fmpz_t tmp; fmpz_set_si(n, factor->sign); fmpz_init(tmp); for (i = 0; i < factor->num; i++) { fmpz_pow_ui(tmp, factor->p + i, factor->exp[i]); fmpz_mul(n, n, tmp); } fmpz_clear(tmp); } flint-3.1.3/src/fmpz_factor/expand_multiexp.c000066400000000000000000000032551461254215100213130ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 Paul Zimmermann Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_factor.h" void _fmpz_factor_eval_multiexp(fmpz_t res, const fmpz * p, const ulong * e, slong len) { slong i, j; ulong mask, emax; fmpz * q; fmpz_t tmp; if (len <= 1) { if (len < 1) fmpz_one(res); else fmpz_pow_ui(res, p, e[0]); return; } q = flint_malloc(sizeof(fmpz) * len); emax = e[0]; for (i = 1; i < len; i++) emax = FLINT_MAX(emax, e[i]); for (mask = 1; emax >= (mask << 1); mask <<= 1); fmpz_init(tmp); fmpz_one(res); while (mask) { for (i = 0, j = 0; i < len; i++) if (e[i] & mask) q[j++] = p[i]; _fmpz_vec_prod(tmp, q, j); fmpz_mul(res, res, res); fmpz_mul(res, res, tmp); mask >>= 1; } fmpz_clear(tmp); flint_free(q); } void fmpz_factor_expand_multiexp(fmpz_t n, const fmpz_factor_t factor) { if (factor->num != 0 && factor->p[0] == 2) { _fmpz_factor_eval_multiexp(n, factor->p + 1, factor->exp + 1, factor->num - 1); fmpz_mul_2exp(n, n, factor->exp[0]); } else _fmpz_factor_eval_multiexp(n, factor->p, factor->exp, factor->num); fmpz_mul_si(n, n, factor->sign); } flint-3.1.3/src/fmpz_factor/extend_factor_ui.c000066400000000000000000000020351461254215100214220ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" void _fmpz_factor_extend_factor_ui(fmpz_factor_t factor, mp_limb_t n) { slong i, len; n_factor_t nfac; if (n == 0) { _fmpz_factor_set_length(factor, 0); factor->sign = 0; return; } n_factor_init(&nfac); n_factor(&nfac, n, 0); len = factor->num; _fmpz_factor_fit_length(factor, len + nfac.num); _fmpz_factor_set_length(factor, len + nfac.num); for (i = 0; i < nfac.num; i++) { fmpz_set_ui(factor->p + len + i, nfac.p[i]); factor->exp[len + i] = nfac.exp[i]; } } flint-3.1.3/src/fmpz_factor/factor.c000066400000000000000000000066341461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" void fmpz_factor(fmpz_factor_t factor, const fmpz_t n) { ulong exp; mp_limb_t p; __mpz_struct * xsrc; mp_ptr xd; mp_size_t xsize; slong found; slong trial_start, trial_stop; TMP_INIT; if (!COEFF_IS_MPZ(*n)) { fmpz_factor_si(factor, *n); return; } _fmpz_factor_set_length(factor, 0); /* Get sign and size */ xsrc = COEFF_TO_PTR(*n); if (xsrc->_mp_size < 0) { xsize = -(xsrc->_mp_size); factor->sign = -1; } else { xsize = xsrc->_mp_size; factor->sign = 1; } /* Just a single limb */ if (xsize == 1) { _fmpz_factor_extend_factor_ui(factor, xsrc->_mp_d[0]); return; } /* Create a temporary copy to be mutated */ TMP_START; xd = TMP_ALLOC(xsize * sizeof(mp_limb_t)); flint_mpn_copyi(xd, xsrc->_mp_d, xsize); /* Factor out powers of two */ xsize = flint_mpn_remove_2exp(xd, xsize, &exp); if (exp != 0) _fmpz_factor_append_ui(factor, UWORD(2), exp); trial_start = 1; trial_stop = 1000; while (xsize > 1) { found = flint_mpn_factor_trial(xd, xsize, trial_start, trial_stop); if (found) { p = n_primes_arr_readonly(found+1)[found]; exp = 1; xsize = flint_mpn_divexact_1(xd, xsize, p); /* Check if p^2 divides n */ if (flint_mpn_divisible_1_odd(xd, xsize, p)) { /* TODO: when searching for squarefree numbers (Moebius function, etc), we can abort here. */ xsize = flint_mpn_divexact_1(xd, xsize, p); exp = 2; } /* If we're up to cubes, then maybe there are higher powers */ if (exp == 2 && flint_mpn_divisible_1_odd(xd, xsize, p)) { xsize = flint_mpn_divexact_1(xd, xsize, p); xsize = flint_mpn_remove_power_ascending(xd, xsize, &p, 1, &exp); exp += 3; } _fmpz_factor_append_ui(factor, p, exp); /* flint_printf("added %wu %wu\n", p, exp); */ /* Continue using only trial division whilst it is successful. This allows quickly factoring huge highly composite numbers such as factorials, which can arise in some applications. */ trial_start = found + 1; trial_stop = trial_start + 1000; continue; } else { fmpz_t n2; __mpz_struct * data; fmpz_init2(n2, xsize); data = _fmpz_promote(n2); flint_mpn_copyi(data->_mp_d, xd, xsize); data->_mp_size = xsize; fmpz_factor_no_trial(factor, n2); fmpz_clear(n2); goto cleanup; } } /* Any single-limb factor left? */ if (xd[0] != 1) _fmpz_factor_extend_factor_ui(factor, xd[0]); cleanup: TMP_END; return; } flint-3.1.3/src/fmpz_factor/factor_no_trial.c000066400000000000000000000040211461254215100212420ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "qsieve.h" void fmpz_factor_no_trial(fmpz_factor_t factor, const fmpz_t n) { int exp, i; if (fmpz_is_prime(n)) _fmpz_factor_append(factor, n, 1); else { fmpz_t root; fmpz_init(root); exp = fmpz_is_perfect_power(root, n); if (exp != 0) { fmpz_factor_t fac; fmpz_factor_init(fac); fmpz_factor_no_trial(fac, root); _fmpz_factor_concat(factor, fac, exp); fmpz_factor_clear(fac); } else { fmpz_factor_t fac, fac2, fac3; slong bits = fmpz_sizeinbase(n, 2); int done; fmpz_factor_init(fac3); done = fmpz_factor_smooth(fac3, n, FLINT_MAX(bits/3 - 17, 2), 1); if (!done) { fmpz_t n2; slong exp2; fmpz_init(n2); /* take out cofactor and factor it */ fmpz_set(n2, fac3->p + fac3->num - 1); exp = fac3->exp[fac3->num - 1]; fac3->exp[fac3->num - 1] = 0; fac3->num--; fmpz_factor_init(fac); /* qsieve can't factor perfect powers */ exp2 = fmpz_is_perfect_power(root, n2); if (exp2) _fmpz_factor_append(fac, root, exp2); else qsieve_factor(fac, n2); for (i = 0; i < fac->num; i++) { fmpz_factor_init(fac2); fmpz_factor_no_trial(fac2, fac->p + i); _fmpz_factor_concat(fac3, fac2, exp*fac->exp[i]); fmpz_factor_clear(fac2); } fmpz_factor_clear(fac); fmpz_clear(n2); } _fmpz_factor_concat(factor, fac3, 1); fmpz_factor_clear(fac3); } fmpz_clear(root); } } flint-3.1.3/src/fmpz_factor/factor_pp1.c000066400000000000000000000357031461254215100201460ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #define DEBUG 0 /* turn on some trace information */ #define pp1_mulmod(rxx, axx, bxx, nnn, nxx, ninv, norm) \ flint_mpn_mulmod_preinvn(rxx, axx, bxx, nnn, nxx, ninv, norm) #ifdef FLINT64 static ulong pp1_primorial[15] = { UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030), UWORD(510510), UWORD(9699690), UWORD(223092870), UWORD(6469693230), UWORD(200560490130), UWORD(7420738134810), UWORD(304250263527210), UWORD(13082761331670030), UWORD(614889782588491410) }; #define num_primorials 15 #else static ulong pp1_primorial[9] = { UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030), UWORD(510510), UWORD(9699690), UWORD(223092870) }; #define num_primorials 9 #endif void pp1_set(mp_ptr x1, mp_ptr y1, mp_srcptr x2, mp_srcptr y2, mp_size_t nn) { flint_mpn_copyi(x1, x2, nn); flint_mpn_copyi(y1, y2, nn); } void pp1_set_ui(mp_ptr x, mp_size_t nn, ulong norm, ulong c) { mpn_zero(x, nn); x[0] = (c << norm); if (nn > 1 && norm) x[1] = (c >> (FLINT_BITS - norm)); } void pp1_2k(mp_ptr x, mp_ptr y, mp_size_t nn, mp_srcptr n, mp_srcptr ninv, mp_srcptr x0, ulong norm) { pp1_mulmod(y, y, x, nn, n, ninv, norm); if (mpn_sub_n(y, y, x0, nn)) mpn_add_n(y, y, n, nn); pp1_mulmod(x, x, x, nn, n, ninv, norm); if (mpn_sub_1(x, x, nn, UWORD(2) << norm)) mpn_add_n(x, x, n, nn); } void pp1_2kp1(mp_ptr x, mp_ptr y, mp_size_t nn, mp_srcptr n, mp_srcptr ninv, mp_srcptr x0, ulong norm) { pp1_mulmod(x, x, y, nn, n, ninv, norm); if (mpn_sub_n(x, x, x0, nn)) mpn_add_n(x, x, n, nn); pp1_mulmod(y, y, y, nn, n, ninv, norm); if (mpn_sub_1(y, y, nn, UWORD(2) << norm)) mpn_add_n(y, y, n, nn); } void pp1_pow_ui(mp_ptr x, mp_ptr y, mp_size_t nn, ulong exp, mp_srcptr n, mp_srcptr ninv, ulong norm) { mp_limb_t t[30]; mp_ptr x0 = t; ulong bit = ((UWORD(1) << FLINT_BIT_COUNT(exp)) >> 2); if (nn > 30) x0 = flint_malloc(nn*sizeof(mp_limb_t)); flint_mpn_copyi(x0, x, nn); pp1_mulmod(y, x, x, nn, n, ninv, norm); if (mpn_sub_1(y, y, nn, UWORD(2) << norm)) mpn_add_n(y, y, n, nn); while (bit) { if (exp & bit) pp1_2kp1(x, y, nn, n, ninv, x0, norm); else pp1_2k(x, y, nn, n, ninv, x0, norm); bit >>= 1; } if (nn > 30) flint_free(x0); } mp_size_t pp1_factor(mp_ptr factor, mp_srcptr n, mp_srcptr x, mp_size_t nn, ulong norm) { mp_size_t ret = 0, xn = nn; mp_ptr n2 = flint_malloc(nn*sizeof(mp_limb_t)); mp_ptr x2 = flint_malloc(nn*sizeof(mp_limb_t)); if (norm) mpn_rshift(n2, n, nn, norm); else flint_mpn_copyi(n2, n, nn); if (norm) mpn_rshift(x2, x, nn, norm); else flint_mpn_copyi(x2, x, nn); if (mpn_sub_1(x2, x2, nn, 2)) mpn_add_n(x2, x2, n2, nn); MPN_NORM(x2, xn); if (xn == 0) goto cleanup; ret = flint_mpn_gcd_full(factor, n2, nn, x2, xn); cleanup: flint_free(n2); flint_free(x2); return ret; } mp_size_t pp1_find_power(mp_ptr factor, mp_ptr x, mp_ptr y, mp_size_t nn, ulong p, mp_srcptr n, mp_srcptr ninv, ulong norm) { mp_size_t ret; do { pp1_pow_ui(x, y, nn, p, n, ninv, norm); ret = pp1_factor(factor, n, x, nn, norm); } while (ret == 1 && factor[0] == 1); return ret; } int fmpz_factor_pp1(fmpz_t fac, const fmpz_t n_in, ulong B1, ulong B2sqrt, ulong c) { slong i, j; int ret = 0; mp_size_t nn = fmpz_size(n_in), r; mp_ptr x, y, oldx, oldy, n, ninv, factor, ptr_0, ptr_1, ptr_2, ptr_k; ulong pr, oldpr, sqrt, bits0, norm; n_primes_t iter; if (fmpz_is_even(n_in)) { fmpz_set_ui(fac, 2); return 1; } #if DEBUG flint_printf("starting stage 1\n"); #endif n_primes_init(iter); sqrt = n_sqrt(B1); bits0 = FLINT_BIT_COUNT(B1); x = flint_malloc(nn*sizeof(mp_limb_t)); y = flint_malloc(nn*sizeof(mp_limb_t)); oldx = flint_malloc(nn*sizeof(mp_limb_t)); oldy = flint_malloc(nn*sizeof(mp_limb_t)); n = flint_malloc(nn*sizeof(mp_limb_t)); ninv = flint_malloc(nn*sizeof(mp_limb_t)); factor = flint_malloc(nn*sizeof(mp_limb_t)); if (nn == 1) { n[0] = fmpz_get_ui(n_in); norm = flint_clz(n[0]); n[0] <<= norm; } else { mp_ptr np = COEFF_TO_PTR(*n_in)->_mp_d; norm = flint_clz(np[nn - 1]); if (norm) mpn_lshift(n, np, nn, norm); else flint_mpn_copyi(n, np, nn); } flint_mpn_preinvn(ninv, n, nn); pp1_set_ui(x, nn, norm, c); /* mul by various prime powers */ pr = 0; oldpr = 0; for (i = 0; pr < B1; ) { j = i + 1024; oldpr = pr; pp1_set(oldx, oldy, x, y, nn); for ( ; i < j; i++) { pr = n_primes_next(iter); if (pr < sqrt) { ulong bits = FLINT_BIT_COUNT(pr); ulong exp = bits0 / bits; pp1_pow_ui(x, y, nn, n_pow(pr, exp), n, ninv, norm); } else pp1_pow_ui(x, y, nn, pr, n, ninv, norm); } r = pp1_factor(factor, n, x, nn, norm); if (r == 0) break; if (r != 1 || factor[0] != 1) { ret = 1; goto cleanup; } } if (pr < B1) /* factor = 0 */ { n_primes_jump_after(iter, oldpr); pp1_set(x, y, oldx, oldy, nn); do { pr = n_primes_next(iter); pp1_set(oldx, oldy, x, y, nn); if (pr < sqrt) { ulong bits = FLINT_BIT_COUNT(pr); ulong exp = bits0 / bits; pp1_pow_ui(x, y, nn, n_pow(pr, exp), n, ninv, norm); } else pp1_pow_ui(x, y, nn, pr, n, ninv, norm); r = pp1_factor(factor, n, x, nn, norm); if (r == 0) break; if (r != 1 || factor[0] != 1) { ret = 1; goto cleanup; } } while (1); /* factor is still 0 */ ret = pp1_find_power(factor, oldx, oldy, nn, pr, n, ninv, norm); } else /* stage 2 */ { double quot; int num; char * sieve = flint_malloc(32768); slong * sieve_index = flint_malloc(32768*sizeof(slong)); mp_ptr diff = flint_malloc(16384*nn*sizeof(mp_limb_t)); ulong offset[15], num_roots; slong k, index = 0, s; fmpz * roots, * roots2, * evals; fmpz_poly_struct ** tree2; #if DEBUG ulong primorial; flint_printf("starting stage 2\n"); #endif /* find primorial <= B2sqrt ... */ for (num = 1; num < num_primorials; num++) { if (pp1_primorial[num] > B2sqrt) break; } num--; /* ... but not too big */ quot = (double) B2sqrt / (double) pp1_primorial[num]; if (quot < 1.1 && num > 0) num--; #if DEBUG primorial = pp1_primorial[num]; flint_printf("found primorial %wu\n", primorial); #endif /* adjust B2sqrt to multiple of primorial */ B2sqrt = (((B2sqrt - 1)/ pp1_primorial[num]) + 1) * pp1_primorial[num]; #if DEBUG flint_printf("adjusted B2sqrt %wu\n", B2sqrt); #endif /* compute num roots */ num++; /* number of primes is 1 more than primorial index */ pr = 2; num_roots = B2sqrt; for (i = 0; i < num; i++) { num_roots = (num_roots*(pr - 1))/pr; pr = n_nextprime(pr, 0); } #if DEBUG flint_printf("computed num_roots %wu\n", num_roots); flint_printf("B2 = %wu\n", num_roots * B2sqrt); #endif /* construct roots */ roots = _fmpz_vec_init(num_roots); for (i = 0; i < num_roots; i++) { __mpz_struct * m = _fmpz_promote(roots + i); mpz_realloc(m, nn); } roots2 = _fmpz_vec_init(num_roots); for (i = 0; i < num_roots; i++) { __mpz_struct * m = _fmpz_promote(roots2 + i); mpz_realloc(m, nn); } evals = _fmpz_vec_init(num_roots); #if DEBUG flint_printf("constructed roots\n"); #endif /* compute differences table v0, ... */ mpn_zero(diff, nn); diff[0] = (UWORD(2) << norm); /* ... v2, ... */ pp1_mulmod(diff + nn, x, x, nn, n, ninv, norm); if (mpn_sub_1(diff + nn, diff + nn, nn, UWORD(2) << norm)) mpn_add_n(diff + nn, diff + nn, n, nn); /* ... the rest ... v_{k+2} = v_k v_2 - v_{k-2} */ k = 2*nn; for (i = 2; i < 16384; i++, k += nn) { pp1_mulmod(diff + k, diff + k - nn, diff + nn, nn, n, ninv, norm); if (mpn_sub_n(diff + k, diff + k, diff + k - 2*nn, nn)) mpn_add_n(diff + k, diff + k, n, nn); } #if DEBUG flint_printf("conputed differences table\n"); #endif /* initial positions */ pr = 2; for (i = 0; i < num; i++) { offset[i] = pr/2; pr = n_nextprime(pr, 0); } s = 0; while (2*s + 1 < B2sqrt) { /* sieve */ memset(sieve, 1, 32768); pr = 3; for (i = 1; i < num; i++) { j = offset[i]; while (j < 32768) sieve[j] = 0, j += pr; /* store offset for start of next sieve run */ offset[i] = j - 32768; pr = n_nextprime(pr, 0); } /* compute roots */ for (i = 0; i < 32768 && 2*(s + i) + 1 < B2sqrt; i++) { if (sieve[i]) { ptr_2 = COEFF_TO_PTR(roots[index])->_mp_d; k = (i + 1)/2; for (j = i - 1; j >= k; j--) { if (sieve[j] && sieve[2*j - i]) { /* V_{n+k} = V_n V_k - V_{n-k} */ ptr_0 = COEFF_TO_PTR(roots[sieve_index[2*j - i]])->_mp_d; ptr_1 = COEFF_TO_PTR(roots[sieve_index[j]])->_mp_d; ptr_k = diff + (i - j)*nn; pp1_mulmod(ptr_2, ptr_1, ptr_k, nn, n, ninv, norm); if (mpn_sub_n(ptr_2, ptr_2, ptr_0, nn)) mpn_add_n(ptr_2, ptr_2, n, nn); break; } } if (j < k) /* pair not found, compute using pow_ui */ { flint_mpn_copyi(ptr_2, x, nn); pp1_pow_ui(ptr_2, y, nn, 2*(s + i) + 1, n, ninv, norm); } sieve_index[i] = index; index++; } } s += 32768; } #if DEBUG flint_printf("roots computed %wd\n", index); #endif /* v_1 */ flint_mpn_copyi(oldx, x, nn); pp1_pow_ui(oldx, y, nn, B2sqrt, n, ninv, norm); ptr_0 = COEFF_TO_PTR(roots2[0])->_mp_d; flint_mpn_copyi(ptr_0, oldx, nn); /* v_2 */ ptr_1 = COEFF_TO_PTR(roots2[1])->_mp_d; pp1_mulmod(ptr_1, ptr_0, ptr_0, nn, n, ninv, norm); if (mpn_sub_1(ptr_1, ptr_1, nn, UWORD(2) << norm)) mpn_add_n(ptr_1, ptr_1, n, nn); for (i = 2; i < num_roots; i++) { /* V_{k+n} = V_k V_n - V_{k-n} */ ptr_2 = COEFF_TO_PTR(roots2[i])->_mp_d; pp1_mulmod(ptr_2, ptr_1, oldx, nn, n, ninv, norm); if (mpn_sub_n(ptr_2, ptr_2, ptr_0, nn)) mpn_add_n(ptr_2, ptr_2, n, nn); ptr_0 = ptr_1; ptr_1 = ptr_2; } #if DEBUG flint_printf("roots2 computed %wu\n", num_roots); #endif for (i = 0; i < num_roots; i++) { mp_size_t sn; __mpz_struct * m1 = COEFF_TO_PTR(roots[i]); __mpz_struct * m2 = COEFF_TO_PTR(roots2[i]); ptr_1 = m1->_mp_d; ptr_2 = m2->_mp_d; if (norm) { mpn_rshift(ptr_1, ptr_1, nn, norm); mpn_rshift(ptr_2, ptr_2, nn, norm); } sn = nn; MPN_NORM(ptr_1, sn); m1->_mp_size = sn; sn = nn; MPN_NORM(ptr_2, sn); m2->_mp_size = sn; _fmpz_demote_val(roots + i); _fmpz_demote_val(roots2 + i); } #if DEBUG flint_printf("normalised roots\n"); #endif fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init(ctx, n_in); tree2 = _fmpz_mod_poly_tree_alloc(num_roots); _fmpz_mod_poly_tree_build(tree2, roots2, num_roots, ctx); /* todo: use fmpz_mod_poly_mul */ fmpz_poly_mul(tree2[FLINT_CLOG2(num_roots)], tree2[FLINT_CLOG2(num_roots)-1], tree2[FLINT_CLOG2(num_roots)-1]+1); fmpz_poly_scalar_mod_fmpz(tree2[FLINT_CLOG2(num_roots)], tree2[FLINT_CLOG2(num_roots)], n_in); #if DEBUG flint_printf("built trees\n"); #endif _fmpz_mod_poly_evaluate_fmpz_vec_fast(evals, tree2[FLINT_CLOG2(num_roots)]->coeffs, tree2[FLINT_CLOG2(num_roots)]->length, roots, num_roots, ctx); _fmpz_mod_poly_tree_free(tree2, num_roots); fmpz_mod_ctx_clear(ctx); #if DEBUG flint_printf("evaluated at roots\n"); #endif for (i = 0; i < num_roots; i++) { fmpz_gcd(fac, n_in, evals + i); if (!fmpz_is_zero(fac) && !fmpz_is_one(fac)) { ret = 1; break; } } _fmpz_vec_clear(evals, num_roots); _fmpz_vec_clear(roots, num_roots); _fmpz_vec_clear(roots2, num_roots); flint_free(sieve); flint_free(sieve_index); flint_free(diff); if (i < num_roots) goto cleanup2; } #if DEBUG flint_printf("done stage2\n"); #endif cleanup: if (ret) { __mpz_struct * fm = _fmpz_promote(fac); mpz_realloc(fm, r); flint_mpn_copyi(fm->_mp_d, factor, r); fm->_mp_size = r; _fmpz_demote_val(fac); } cleanup2: flint_free(x); flint_free(y); flint_free(oldx); flint_free(oldy); flint_free(n); flint_free(ninv); flint_free(factor); n_primes_clear(iter); return ret; } flint-3.1.3/src/fmpz_factor/factor_si.c000066400000000000000000000013751461254215100200570ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" void fmpz_factor_si(fmpz_factor_t factor, slong n) { _fmpz_factor_set_length(factor, 0); if (n < 0) { _fmpz_factor_extend_factor_ui(factor, -n); factor->sign = -1; return; } else { factor->sign = 1; _fmpz_factor_extend_factor_ui(factor, n); } } flint-3.1.3/src/fmpz_factor/factor_smooth.c000066400000000000000000000173061461254215100207560ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" static slong trial_cutoff[15] = {4, 4, 4, 6, 11, 18, 31, 54, 97, 172, 309, 564, 1028, 1900, 3512}; /* Tuning values to give a roughly 1/3 chance of finding a factor of the given number of bits. Parameters are {bits, B1, curves}. B2 should be taken to be 100*B1. Tuning values are a bit rough from 62 bits on. */ static slong ecm_tuning[][3] = { {0, 0, 0}, {2, 1, 1}, {4, 3, 1}, {6, 5, 1}, {8, 7, 1}, {10, 9, 2}, {12, 11, 2}, {14, 13, 2}, {16, 15, 2}, {18, 17, 2}, {20, 19, 5}, {22, 25, 8}, {24, 32, 10}, {26, 47, 11}, {28, 67, 13}, {30, 102, 13}, {32, 126, 13}, {34, 207, 15}, {36, 293, 16}, {38, 415, 17}, {40, 610, 18}, {42, 920, 18}, {44, 1270, 20}, {46, 1800, 20}, {48, 2650, 20}, {50, 3850, 21}, {52, 5300, 22}, {54, 8500, 22}, {56, 10000, 26}, {58, 12000, 33}, {60, 14000, 42}, {62, 15000, 57}, {64, 16500, 72}, {66, 18000, 87}, {68, 22000, 102}, {70, 26000, 117}, {72, 30000, 131}, {74, 40000, 146}, {76, 50000, 161}, {78, 60000, 175}, {80, 70000, 190}, {82, 80000, 205}, {84, 100000, 220}, {86, 140000, 240}, {88, 190000, 255}, {90, 240000, 291}, {92, 280000, 318}, {94, 320000, 345}, {96, 370000, 372}, {98, 420000, 400}, {100, 470000, 430} }; int _is_prime(const fmpz_t n, int proved) { if (proved) return fmpz_is_prime(n); else return fmpz_is_probabprime(n); } void remove_found_factors(fmpz_factor_t factor, fmpz_t n, fmpz_t f) { slong i; fmpz_factor_t fac; fmpz_tdiv_q(n, n, f); fmpz_factor_init(fac); fmpz_factor_no_trial(fac, f); for (i = 0; i < fac->num; i++) fac->exp[i] += fmpz_remove(n, n, fac->p + i); _fmpz_factor_concat(factor, fac, 1); fmpz_factor_clear(fac); } int fmpz_factor_smooth(fmpz_factor_t factor, const fmpz_t n, slong bits, int proved) { ulong exp; mp_limb_t p; __mpz_struct * xsrc; mp_ptr xd; mp_size_t xsize; slong found; slong trial_stop; slong * idx; slong i, b, bits2, istride; const mp_limb_t * primes; int ret = 0; TMP_INIT; if (!COEFF_IS_MPZ(*n)) { fmpz_factor_si(factor, *n); return 1; } _fmpz_factor_set_length(factor, 0); /* Get sign and size */ xsrc = COEFF_TO_PTR(*n); if (xsrc->_mp_size < 0) { xsize = -(xsrc->_mp_size); factor->sign = -1; } else { xsize = xsrc->_mp_size; factor->sign = 1; } /* Just a single limb */ if (xsize == 1) { _fmpz_factor_extend_factor_ui(factor, xsrc->_mp_d[0]); return 1; } /* Create a temporary copy to be mutated */ TMP_START; xd = TMP_ALLOC(xsize * sizeof(mp_limb_t)); flint_mpn_copyi(xd, xsrc->_mp_d, xsize); /* Factor out powers of two */ xsize = flint_mpn_remove_2exp(xd, xsize, &exp); if (exp != 0) _fmpz_factor_append_ui(factor, UWORD(2), exp); if (bits <= 0) { flint_throw(FLINT_ERROR, "(fmpz_factor_smooth) Number of bits must be at least 1\n"); } if (bits <= 15) trial_stop = trial_cutoff[bits - 1]; else trial_stop = 3512; b = fmpz_sizeinbase(n, 2) - exp; idx = (slong *) flint_malloc((5 + b/4)*sizeof(slong)); found = flint_mpn_factor_trial_tree(idx, xd, xsize, trial_stop); if (found) { primes = n_primes_arr_readonly(trial_stop); for (i = 0; i < found; i++) { p = primes[idx[i]]; if (p == 2) continue; exp = 1; xsize = flint_mpn_divexact_1(xd, xsize, p); /* Check if p^2 divides n */ if (flint_mpn_divisible_1_odd(xd, xsize, p)) { xsize = flint_mpn_divexact_1(xd, xsize, p); exp = 2; } /* If we're up to cubes, then maybe there are higher powers */ if (exp == 2 && flint_mpn_divisible_1_odd(xd, xsize, p)) { xsize = flint_mpn_divexact_1(xd, xsize, p); xsize = flint_mpn_remove_power_ascending(xd, xsize, &p, 1, &exp); exp += 3; } _fmpz_factor_append_ui(factor, p, exp); } } if (xsize == 1) { /* Any single-limb factor left? */ if (xd[0] != 1) _fmpz_factor_extend_factor_ui(factor, xd[0]); ret = 1; } else { fmpz_t n2, f; __mpz_struct * data; fmpz_init2(n2, xsize); data = _fmpz_promote(n2); flint_mpn_copyi(data->_mp_d, xd, xsize); data->_mp_size = xsize; if (proved != -1 && _is_prime(n2, proved)) { _fmpz_factor_append(factor, n2, 1); ret = 1; } else { fmpz_t root; fmpz_init(root); exp = fmpz_is_perfect_power(root, n2); if (exp != 0) { fmpz_factor_t fac; fmpz_factor_init(fac); ret = fmpz_factor_smooth(fac, root, bits, proved); fmpz_set_ui(n2, 1); _fmpz_factor_concat(factor, fac, exp); fmpz_factor_clear(fac); } else if (bits >= 16) /* trial factored already up to 15 bits */ { int found; flint_rand_t state; fmpz_init(f); flint_randinit(state); /* currently only tuning values up to factors of 100 bits */ bits = FLINT_MIN(bits, 100); bits2 = (bits + 1)/2; /* tuning is in increments of 2 bits */ istride = 3; /* start with 18-22 bits, advance by 6 bits at a time */ for (i = 9 + (bits2 % 3); i <= bits2; i += istride) { found = fmpz_factor_ecm(f, ecm_tuning[i][2], ecm_tuning[i][1], ecm_tuning[i][1]*100, state, n2); if (found != 0) { /* make sure all prime divisors in factor are removed from n2 */ remove_found_factors(factor, n2, f); if (fmpz_is_one(n2)) { ret = 1; break; } /* if what remains is below the bound, just factor it */ if (fmpz_sizeinbase(n2, 2) < bits) { fmpz_factor_no_trial(factor, n2); ret = 1; break; } if (_is_prime(n2, proved)) { _fmpz_factor_append(factor, n2, 1); ret = 1; break; } i -= istride; /* redo with the same parameters if factor found */ } } flint_randclear(state); fmpz_clear(f); } } if (ret != 1 && !fmpz_is_one(n2)) _fmpz_factor_append(factor, n2, 1); /* place cofactor in factor struct */ else ret = 1; fmpz_clear(n2); } flint_free(idx); TMP_END; return ret; } flint-3.1.3/src/fmpz_factor/factor_trial.c000066400000000000000000000061621461254215100205560ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" int fmpz_factor_trial(fmpz_factor_t factor, const fmpz_t n, slong num_primes) { ulong exp; mp_limb_t p; mpz_t x; mp_ptr xd; mp_size_t xsize; slong found; int ret = 1; slong * idx; slong bits, i; const mp_limb_t * primes; if (num_primes > 3512 || num_primes < 0) { flint_throw(FLINT_ERROR, "(fmpz_factor_trial) Number of primes must be in 0..3512\n"); } if (!COEFF_IS_MPZ(*n)) { fmpz_factor_si(factor, *n); return ret; } _fmpz_factor_set_length(factor, 0); /* Make an mpz_t copy whose limbs will be mutated */ mpz_init(x); fmpz_get_mpz(x, n); if (x->_mp_size < 0) { x->_mp_size = -(x->_mp_size); factor->sign = -1; } else { factor->sign = 1; } xd = x->_mp_d; xsize = x->_mp_size; /* Factor out powers of two */ xsize = flint_mpn_remove_2exp(xd, xsize, &exp); if (exp != 0) _fmpz_factor_append_ui(factor, UWORD(2), exp); bits = fmpz_sizeinbase(n, 2) - exp; idx = (slong *) flint_malloc((5 + bits/4)*sizeof(slong)); found = flint_mpn_factor_trial_tree(idx, xd, xsize, num_primes); if (found) { primes = n_primes_arr_readonly(3512); for (i = 0; i < found; i++) { p = primes[idx[i]]; if (p == 2) continue; exp = 1; xsize = flint_mpn_divexact_1(xd, xsize, p); /* Check if p^2 divides n */ if (flint_mpn_divisible_1_odd(xd, xsize, p)) { /* TODO: when searching for squarefree numbers (Moebius function, etc), we can abort here. */ xsize = flint_mpn_divexact_1(xd, xsize, p); exp = 2; } /* If we're up to cubes, then maybe there are higher powers */ if (exp == 2 && flint_mpn_divisible_1_odd(xd, xsize, p)) { xsize = flint_mpn_divexact_1(xd, xsize, p); xsize = flint_mpn_remove_power_ascending(xd, xsize, &p, 1, &exp); exp += 3; } _fmpz_factor_append_ui(factor, p, exp); } } /* Any factor left? */ if (xsize > 1 || xd[0] != 1) { fmpz_t cofactor; mpz_t mockx; /* do not free */ fmpz_init(cofactor); mockx->_mp_d = xd; mockx->_mp_size = xsize; mockx->_mp_alloc = x->_mp_alloc; fmpz_set_mpz(cofactor, mockx); _fmpz_factor_append(factor, cofactor, 1); fmpz_clear(cofactor); ret = 0; } mpz_clear(x); flint_free(idx); return ret; } flint-3.1.3/src/fmpz_factor/factor_trial_range.c000066400000000000000000000063721461254215100217350ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" int fmpz_factor_trial_range(fmpz_factor_t factor, const fmpz_t n, ulong start, ulong num_primes) { ulong exp; mp_limb_t p; mpz_t x; mp_ptr xd; mp_size_t xsize; slong found; slong trial_start, trial_stop; int ret = 1; if (!COEFF_IS_MPZ(*n)) { fmpz_factor_si(factor, *n); return ret; } _fmpz_factor_set_length(factor, 0); /* Make an mpz_t copy whose limbs will be mutated */ mpz_init(x); fmpz_get_mpz(x, n); if (x->_mp_size < 0) { x->_mp_size = -(x->_mp_size); factor->sign = -1; } else { factor->sign = 1; } xd = x->_mp_d; xsize = x->_mp_size; /* Factor out powers of two */ if (start == 0) { xsize = flint_mpn_remove_2exp(xd, xsize, &exp); if (exp != 0) _fmpz_factor_append_ui(factor, UWORD(2), exp); } trial_start = FLINT_MAX(1, start); trial_stop = FLINT_MIN(start + 1000, start + num_primes); do { found = flint_mpn_factor_trial(xd, xsize, trial_start, trial_stop); if (found) { p = n_primes_arr_readonly(found+1)[found]; exp = 1; xsize = flint_mpn_divexact_1(xd, xsize, p); /* Check if p^2 divides n */ if (flint_mpn_divisible_1_odd(xd, xsize, p)) { /* TODO: when searching for squarefree numbers (Moebius function, etc), we can abort here. */ xsize = flint_mpn_divexact_1(xd, xsize, p); exp = 2; } /* If we're up to cubes, then maybe there are higher powers */ if (exp == 2 && flint_mpn_divisible_1_odd(xd, xsize, p)) { xsize = flint_mpn_divexact_1(xd, xsize, p); xsize = flint_mpn_remove_power_ascending(xd, xsize, &p, 1, &exp); exp += 3; } _fmpz_factor_append_ui(factor, p, exp); /* flint_printf("added %wu %wu\n", p, exp); */ /* Continue using only trial division whilst it is successful. This allows quickly factoring huge highly composite numbers such as factorials, which can arise in some applications. */ trial_start = found + 1; trial_stop = FLINT_MIN(trial_start + 1000, start + num_primes); continue; } else { /* Insert primality test, perfect power test, other factoring algorithms here... */ trial_start = trial_stop; trial_stop = FLINT_MIN(trial_start + 1000, start + num_primes); } } while ((xsize > 1 || xd[0] != 1) && trial_start != trial_stop); /* Any factor left? */ if (xsize > 1 || xd[0] != 1) ret = 0; mpz_clear(x); return ret; } flint-3.1.3/src/fmpz_factor/fit_length.c000066400000000000000000000020111461254215100202150ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" void _fmpz_factor_fit_length(fmpz_factor_t factor, slong len) { if (len > factor->alloc) { if (len < 2 * factor->alloc) len = 2 * factor->alloc; factor->p = (fmpz *) flint_realloc(factor->p, len * sizeof(fmpz)); factor->exp = flint_realloc(factor->exp, len * sizeof(slong)); if (len > factor->alloc) { flint_mpn_zero((mp_ptr)(factor->p + factor->alloc), len-factor->alloc); flint_mpn_zero((mp_ptr)(factor->exp + factor->alloc), len-factor->alloc); } factor->alloc = len; } } flint-3.1.3/src/fmpz_factor/get_fmpz.c000066400000000000000000000010241461254215100177100ustar00rootroot00000000000000/* Copyright (C) 2017 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" void fmpz_factor_get_fmpz(fmpz_t z, const fmpz_factor_t factor, slong i) { fmpz_set(z, factor->p + i); } flint-3.1.3/src/fmpz_factor/init.c000066400000000000000000000011541461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" void fmpz_factor_init(fmpz_factor_t factor) { factor->sign = 1; factor->p = NULL; factor->exp = NULL; factor->num = 0; factor->alloc = 0; } flint-3.1.3/src/fmpz_factor/io.c000066400000000000000000000024021461254215100165050ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_factor.h" int fmpz_factor_fprint(FILE * fs, const fmpz_factor_t factor) { slong i; int res = 0; if (factor->sign == 0) return (fputc('0', fs) != EOF); if (factor->sign == -1) res += fwrite("-1 * ", sizeof(char), 2 + 3 * (factor->num != 0), fs); else if (factor->num == 0) return (fputc('1', fs) != EOF); for (i = 0; i < factor->num; i++) { res += fmpz_fprint(fs, factor->p + i); if (factor->exp[i] != UWORD(1)) res += fprintf(fs, "^" WORD_FMT "u", factor->exp[i]); if (i != factor->num - 1) res += fwrite(" * ", sizeof(char), 3, fs); } return res; } int fmpz_factor_print(const fmpz_factor_t factor) { return fmpz_factor_fprint(stdout, factor); } flint-3.1.3/src/fmpz_factor/pollard_brent.c000066400000000000000000000077661461254215100207470ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* This is an implementation of the pollard rho algorithm, with a more efficient cycle finding algorithm, as proposed by Richard Brent. Details can be found in the paper https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf, pseudocode is available on page 182 of the same paper */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" int fmpz_factor_pollard_brent(fmpz_t p_factor, flint_rand_t state, fmpz_t n_in, mp_limb_t max_tries, mp_limb_t max_iters) { fmpz_t fa, fy, maxa, maxy; mp_ptr a, y, n, ninv, temp; mp_limb_t n_size, normbits, ans, val, size, cy; __mpz_struct *fac, *mptr; int ret; TMP_INIT; if (fmpz_is_even(n_in)) { fmpz_set_ui(p_factor, 2); return 1; } n_size = fmpz_size(n_in); if (n_size == 1) { val = fmpz_get_ui(n_in); ret = n_factor_pollard_brent(&ans, state, val, max_tries, max_iters); fmpz_set_ui(p_factor, ans); return ret; } fmpz_init2(fa, n_size); fmpz_init2(fy, n_size); fmpz_init2(maxa, n_size); fmpz_init2(maxy, n_size); fmpz_sub_ui(maxa, n_in, 3); /* 1 <= a <= n - 3 */ fmpz_sub_ui(maxy, n_in, 1); /* 1 <= y <= n - 1 */ TMP_START; a = TMP_ALLOC(n_size * sizeof(mp_limb_t)); y = TMP_ALLOC(n_size * sizeof(mp_limb_t)); n = TMP_ALLOC(n_size * sizeof(mp_limb_t)); ninv = TMP_ALLOC(n_size * sizeof(mp_limb_t)); /* copying n_in onto n, and normalizing */ temp = COEFF_TO_PTR(*n_in)->_mp_d; normbits = flint_clz(temp[n_size - 1]); if (normbits) mpn_lshift(n, temp, n_size, normbits); else flint_mpn_copyi(n, temp, n_size); flint_mpn_preinvn(ninv, n, n_size); fac = _fmpz_promote(p_factor); mpz_realloc2(fac, n_size * FLINT_BITS); fac->_mp_size = n_size; while (max_tries--) { fmpz_randm(fa, state, maxa); fmpz_add_ui(fa, fa, 1); fmpz_randm(fy, state, maxy); fmpz_add_ui(fy, fy, 1); mpn_zero(a, n_size); mpn_zero(y, n_size); if (normbits) { if ((!COEFF_IS_MPZ(*fy))) { y[0] = fmpz_get_ui(fy); cy = mpn_lshift(y, y, 1, normbits); if (cy) y[1] = cy; } else { mptr = COEFF_TO_PTR(*fy); temp = mptr->_mp_d; size = mptr->_mp_size; cy = mpn_lshift(y, temp, size, normbits); if (cy) y[size] = cy; } if ((!COEFF_IS_MPZ(*fa))) { a[0] = fmpz_get_ui(fa); cy = mpn_lshift(a, a, 1, normbits); if (cy) a[1] = cy; } else { mptr = COEFF_TO_PTR(*fa); temp = mptr->_mp_d; size = mptr->_mp_size; cy = mpn_lshift(a, temp, size, normbits); if (cy) a[size] = cy; } } else { temp = COEFF_TO_PTR(*fy)->_mp_d; flint_mpn_copyi(y, temp, n_size); temp = COEFF_TO_PTR(*fa)->_mp_d; flint_mpn_copyi(a, temp, n_size); } ret = flint_mpn_factor_pollard_brent_single(fac->_mp_d, n, ninv, a, y, n_size, normbits, max_iters); if (ret) { fac->_mp_size = ret; /* ret is number of limbs of factor found */ _fmpz_demote_val(p_factor); break; } } fmpz_clear(fa); fmpz_clear(fy); fmpz_clear(maxa); fmpz_clear(maxy); TMP_END; return ret; } flint-3.1.3/src/fmpz_factor/pollard_brent_single.c000066400000000000000000000201601461254215100222670ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* This is an implementation of the pollard rho algorithm, with a more efficient cycle finding algorithm, as proposed by Richard Brent. Details can be found in the paper https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf, pseudocode is available on page 182 of the same paper */ #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_factor.h" /* Sets y to (y^2 + a) % n */ void flint_mpn_sqr_and_add_a(mp_ptr y, mp_ptr a, mp_ptr n, mp_limb_t n_size, mp_ptr ninv, mp_limb_t normbits) { mp_limb_t cy; flint_mpn_mulmod_preinvn(y, y, y, n_size, n, ninv, normbits); /* y^2 mod n */ cy = mpn_add_n(y, y, a, n_size); /* Since carry cannot be greater than 1, if carry then simply subtract for modulo (a < n, y < n, a + y < 2n). If no carry, then check if y > n before subtracting. */ if (cy) mpn_sub_n(y, y, n, n_size); else if (mpn_cmp(y, n, n_size) > 0) mpn_sub_n(y, y, n, n_size); } int flint_mpn_factor_pollard_brent_single(mp_ptr factor, mp_ptr n, mp_ptr ninv, mp_ptr a, mp_ptr y, mp_limb_t n_size, mp_limb_t normbits, mp_limb_t max_iters) { /* n_size >= 2, one limb fmpz_t's are passed on to n_factor_pollard_brent in outer function */ mp_ptr x, q, ys, subval; mp_limb_t iter, i, k, minval, m, one_shift_norm, gcdlimbs; int ret, j; TMP_INIT; TMP_START; x = TMP_ALLOC(n_size * sizeof(mp_limb_t)); /* initial value to evaluate f(x) */ q = TMP_ALLOC(n_size * sizeof(mp_limb_t)); /* product of gcd's */ ys = TMP_ALLOC(n_size * sizeof(mp_limb_t)); subval = TMP_ALLOC(n_size * sizeof(mp_limb_t)); /* one shifted by normbits, used for comparisons */ one_shift_norm = UWORD(1) << normbits; /* set factor and q to one (shifted) */ mpn_zero(q, n_size); mpn_zero(factor, n_size); q[0] = one_shift_norm; factor[0] = one_shift_norm; m = 100; iter = 1; do { flint_mpn_copyi(x, y, n_size); k = 0; for (i = 0; i < iter; i++) flint_mpn_sqr_and_add_a(y, a, n, n_size, ninv, normbits); do { minval = iter - k; if (m < minval) minval = m; flint_mpn_copyi(ys, y, n_size); for (i = 0; i < minval; i++) { flint_mpn_sqr_and_add_a(y, a, n, n_size, ninv, normbits); if (mpn_cmp(x, y, n_size) > 0) mpn_sub_n(subval, x, y, n_size); else mpn_sub_n(subval, y, x, n_size); flint_mpn_mulmod_preinvn(q, q, subval, n_size, n, ninv, normbits); } /* if q is 0, then gcd is n (gcd(0, a) = a). Not passing through flint_mpn_gcd_full due to input parameter restrictions. */ if (flint_mpn_zero_p(q, n_size) == 0) gcdlimbs = flint_mpn_gcd_full(factor, q, n_size, n, n_size); else { flint_mpn_copyi(factor, n, n_size); gcdlimbs = n_size; } k += m; j = ((gcdlimbs == 1) && (factor[0] == one_shift_norm)); /* gcd == 1 */ } while ((k < iter) && j); if (iter > max_iters) /* max iterations crossed */ break; iter *= 2; } while (j); /* if gcd == n, could be possible q has all factors of n, start backtracing. if gcd != 1 after backtracing, then at least one factor has been found (can be n) */ if ((gcdlimbs == n_size) && (mpn_cmp(factor, n, n_size) == 0)) { do { flint_mpn_sqr_and_add_a(ys, a, n, n_size, ninv, normbits); if (mpn_cmp(x, ys, n_size) > 0) mpn_sub_n(subval, x, ys, n_size); else mpn_sub_n(subval, ys, x, n_size); if (flint_mpn_zero_p(q, n_size) == 0) gcdlimbs = flint_mpn_gcd_full(factor, q, n_size, n, n_size); else { flint_mpn_copyi(factor, n, n_size); gcdlimbs = n_size; } j = ((gcdlimbs == 1) && (factor[0] == one_shift_norm)); } while (j); /* gcd == 1 */ } ret = gcdlimbs; /* if gcd == 1 or gcd == n, trivial factor found. return 0 */ if ((gcdlimbs == 1) && (factor[0] == one_shift_norm)) /* gcd == 1 */ ret = 0; else if ((gcdlimbs == n_size && (mpn_cmp(factor, n, n_size) == 0))) /* gcd == n*/ ret = 0; if (ret) { /* If in case after shifting, "actual" factor has lesser limbs than gcdlimbs, then decrease ret by 1. */ j = n_sizeinbase(factor[gcdlimbs - 1], 2); if (normbits >= j) ret -= 1; if (normbits) mpn_rshift(factor, factor, gcdlimbs, normbits); } TMP_END; return ret; } int fmpz_factor_pollard_brent_single(fmpz_t p_factor, fmpz_t n_in, fmpz_t yi, fmpz_t ai, mp_limb_t max_iters) { mp_ptr a, y, n, ninv, temp; mp_limb_t n_size, normbits, ans, size, cy; mp_limb_t al, yl, val, valinv; __mpz_struct *fac, *mptr; int ret; TMP_INIT; if (fmpz_is_even(n_in)) { fmpz_set_ui(p_factor, 2); return 1; } n_size = fmpz_size(n_in); if (n_size == 1) { val = fmpz_get_ui(n_in); normbits = flint_clz(val); val <<= normbits; valinv = n_preinvert_limb(val); al = fmpz_get_ui(ai); yl = fmpz_get_ui(yi); al <<= normbits; yl <<= normbits; ret = n_factor_pollard_brent_single(&ans, val, valinv, al, yl, normbits, max_iters); ans >>= normbits; fmpz_set_ui(p_factor, ans); return ret; } mptr = COEFF_TO_PTR(*yi); temp = COEFF_TO_PTR(*n_in)->_mp_d; normbits = flint_clz(temp[n_size - 1]); TMP_START; a = TMP_ALLOC(n_size * sizeof(mp_limb_t)); y = TMP_ALLOC(n_size * sizeof(mp_limb_t)); n = TMP_ALLOC(n_size * sizeof(mp_limb_t)); ninv = TMP_ALLOC(n_size * sizeof(mp_limb_t)); /* copying n_in onto n, and normalizing */ temp = COEFF_TO_PTR(*n_in)->_mp_d; normbits = flint_clz(temp[n_size - 1]); if (normbits) mpn_lshift(n, temp, n_size, normbits); else flint_mpn_copyi(n, temp, n_size); flint_mpn_preinvn(ninv, n, n_size); fac = _fmpz_promote(p_factor); mpz_realloc2(fac, n_size * FLINT_BITS); fac->_mp_size = n_size; mpn_zero(a, n_size); mpn_zero(y, n_size); if (normbits) { if ((!COEFF_IS_MPZ(*yi))) { y[0] = fmpz_get_ui(yi); cy = mpn_lshift(y, y, 1, normbits); if (cy) y[1] = cy; } else { mptr = COEFF_TO_PTR(*yi); temp = mptr->_mp_d; size = mptr->_mp_size; cy = mpn_lshift(y, temp, size, normbits); if (cy) y[size] = cy; } if ((!COEFF_IS_MPZ(*ai))) { a[0] = fmpz_get_ui(ai); cy = mpn_lshift(a, a, 1, normbits); if (cy) a[1] = cy; } else { mptr = COEFF_TO_PTR(*ai); temp = mptr->_mp_d; size = mptr->_mp_size; cy = mpn_lshift(a, temp, size, normbits); if (cy) a[size] = cy; } } else { temp = COEFF_TO_PTR(*yi)->_mp_d; flint_mpn_copyi(y, temp, n_size); temp = COEFF_TO_PTR(*ai)->_mp_d; flint_mpn_copyi(a, temp, n_size); } ret = flint_mpn_factor_pollard_brent_single(fac->_mp_d, n, ninv, a, y, n_size, normbits, max_iters); if (ret) { fac->_mp_size = ret; /* ret is number of limbs of factor found */ _fmpz_demote_val(p_factor); } TMP_END; return ret; } flint-3.1.3/src/fmpz_factor/profile/000077500000000000000000000000001461254215100173745ustar00rootroot00000000000000flint-3.1.3/src/fmpz_factor/profile/p-factor_bench.c000066400000000000000000000024451461254215100224170ustar00rootroot00000000000000/* Copyright 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz.h" #include "fmpz_factor.h" #include "ulong_extras.h" slong bits[] = { 1, 32, 64, 128, 192, 224 }; slong reps[] = { 1000000, 100000, 10000, 100, 30, 10 }; int main(void) { slong i, b; fmpz_t n; fmpz_factor_t fac; flint_set_num_threads(8); fmpz_init(n); fmpz_factor_init(fac); for (b = 0; b < 6; b++) { flint_printf("%wd x %wd bits: ", reps[b], bits[b]); fmpz_one(n); fmpz_mul_2exp(n, n, bits[b] - 1); TIMEIT_ONCE_START for (i = 0; i < reps[b]; i++) { fmpz_add_ui(n, n, 1); fmpz_factor(fac, n); /* if (bits[b] >= 190) { fmpz_factor_print(fac); flint_printf("\n"); } */ } TIMEIT_ONCE_STOP } fmpz_factor_clear(fac); fmpz_clear(n); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz_factor/profile/p-factor_pp1.c000066400000000000000000000025021461254215100220320ustar00rootroot00000000000000/* Copyright 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz.h" #include "fmpz_factor.h" #include "ulong_extras.h" int main(void) { fmpz_t n, p; ulong c; ulong B1; FLINT_TEST_INIT(state); fmpz_init(n); fmpz_init(p); while(1) { flint_printf("Enter number to be factored: "); fflush(stdout); if (!fmpz_read(n)) { flint_printf("Read failed\n"); flint_abort(); } flint_printf("Enter B1: "); fflush(stdout); if (!flint_scanf("%wu", &B1)) { flint_printf("Read failed\n"); flint_abort(); } do { c = n_randlimb(state); } while (c <= UWORD(2)); if (fmpz_factor_pp1(p, n, B1, B1/100, c)) { flint_printf("Factor: "); fmpz_print(p); flint_printf("\n"); } else flint_printf("Factor not found!\n"); } while(1); flint_randclear(state); fmpz_clear(n); fmpz_clear(p); return 0; } flint-3.1.3/src/fmpz_factor/refine.c000066400000000000000000000251761461254215100173630ustar00rootroot00000000000000/* Copyright (C) 2015 FLINT authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_factor.h" #define fr_node_mref(x) (&(x)->m) typedef struct fr_node_struct { fmpz m; ulong e; struct fr_node_struct * next; } fr_node_struct; typedef fr_node_struct * fr_node_ptr; /* functions related to factor refinement nodes */ void fr_node_init(fr_node_ptr x); void fr_node_init_fmpz_ui(fr_node_ptr x, const fmpz_t m, ulong e); void fr_node_clear(fr_node_ptr x); int fr_node_is_one(fr_node_ptr x); void fr_node_set_fmpz_ui(fr_node_ptr x, const fmpz_t m, ulong e); void fr_node_get_fmpz_ui(fmpz_t m, ulong * e, fr_node_ptr x); int fr_node_base_cmp(const fr_node_ptr x, const fr_node_ptr y); int fr_node_base_pcmp(const void * a, const void * b); /* functions related to lists of factor refinement nodes */ slong fr_node_list_length(fr_node_ptr x); void fr_node_list_pop_front(fr_node_ptr *phead, fr_node_ptr *ptail); void fr_node_list_concat(fr_node_ptr *phead, fr_node_ptr *ptail, fr_node_ptr rhead, fr_node_ptr rtail); void fr_node_list_clear(fr_node_ptr head); void fr_node_list_print(fr_node_ptr head); /* fmpz_factor_t convenience function */ int _fmpz_factor_sgn(const fmpz_factor_t f); /* functions related to the actual algorithms of interest */ void pair_refine_unreduced(fr_node_ptr *phead, fmpz_t m1, ulong e1, fmpz_t m2, ulong e2); void remove_ones(fr_node_ptr *phead, fr_node_ptr *ptail, fr_node_ptr ohead); void pair_refine(fr_node_ptr *phead, fr_node_ptr *ptail, fmpz_t m1, ulong e1, fmpz_t m2, ulong e2); void augment_refinement(fr_node_ptr *phead, fr_node_ptr *ptail, const fmpz_t m_jp1, ulong e_jp1, fr_node_ptr L_j, fr_node_ptr L_j_tail); void fr_node_init(fr_node_ptr x) { fmpz_init(fr_node_mref(x)); x->e = 0; x->next = NULL; } void fr_node_init_fmpz_ui(fr_node_ptr x, const fmpz_t m, ulong e) { fmpz_init_set(fr_node_mref(x), m); x->e = e; x->next = NULL; } void fr_node_clear(fr_node_ptr x) { fmpz_clear(fr_node_mref(x)); x->e = 0; x->next = NULL; } int fr_node_is_one(fr_node_ptr x) { /* follow the fmpz_pow_ui convention 0^0 = 1 */ return (x->e == WORD(0) || fmpz_is_one(fr_node_mref(x))); } void fr_node_set_fmpz_ui(fr_node_ptr x, const fmpz_t m, ulong e) { fmpz_set(fr_node_mref(x), m); x->e = e; } void fr_node_get_fmpz_ui(fmpz_t m, ulong * e, fr_node_ptr x) { fmpz_set(m, fr_node_mref(x)); *e = x->e; } int fr_node_base_cmp(const fr_node_ptr x, const fr_node_ptr y) { return fmpz_cmp(fr_node_mref(x), fr_node_mref(y)); } int fr_node_base_pcmp(const void * a, const void * b) { /* intended for qsorting an array of node pointers */ fr_node_ptr x = *( (fr_node_ptr *) a); fr_node_ptr y = *( (fr_node_ptr *) b); return fr_node_base_cmp(x, y); } slong fr_node_list_length(fr_node_ptr x) { slong count; count = 0; while (x) { count++; x = x->next; } return count; } void fr_node_list_pop_front(fr_node_ptr *phead, fr_node_ptr *ptail) { fr_node_ptr tmp; if (phead == ptail) { flint_throw(FLINT_ERROR, "aliasing issue...\n"); } if (*phead) { if (*phead == *ptail) { *ptail = NULL; } tmp = (*phead)->next; fr_node_clear(*phead); flint_free(*phead); *phead = tmp; } } void fr_node_list_concat(fr_node_ptr *phead, fr_node_ptr *ptail, fr_node_ptr rhead, fr_node_ptr rtail) { /* if the second list is empty then do nothing */ if (!rhead) { return; } /* if the first list is empty then use the second list */ if (!(*phead)) { *phead = rhead; *ptail = rtail; return; } /* neither list is empty so connect the tail to the head */ (*ptail)->next = rhead; *ptail = rtail; } void fr_node_list_clear(fr_node_ptr head) { fr_node_ptr curr, next; curr = head; while (curr) { next = curr->next; fr_node_clear(curr); flint_free(curr); curr = next; } } void fr_node_list_print(fr_node_ptr head) { fr_node_ptr curr; curr = head; while (curr) { fmpz_print(fr_node_mref(curr)); flint_printf("^%wu ", curr->e); curr = curr->next; } flint_printf("\n"); } void pair_refine_unreduced(fr_node_ptr *phead, fmpz_t m1, ulong e1, fmpz_t m2, ulong e2) { fr_node_ptr head, tail, curr, next, neo; fmpz_t d; int boring; if (fmpz_is_one(m1) && fmpz_is_one(m2)) { *phead = NULL; return; } fmpz_init(d); head = flint_malloc(sizeof(fr_node_struct)); fr_node_init_fmpz_ui(head, m1, e1); tail = flint_malloc(sizeof(fr_node_struct)); fr_node_init_fmpz_ui(tail, m2, e2); head->next = tail; boring = 0; while (!boring) { curr = head; next = curr->next; boring = 1; while (next) { if (!fr_node_is_one(curr) && !fr_node_is_one(next)) { fmpz_gcd(d, fr_node_mref(curr), fr_node_mref(next)); fmpz_divexact(fr_node_mref(curr), fr_node_mref(curr), d); fmpz_divexact(fr_node_mref(next), fr_node_mref(next), d); neo = flint_malloc(sizeof(fr_node_struct)); fr_node_init(neo); fmpz_set(fr_node_mref(neo), d); neo->e = curr->e + next->e; curr->next = neo; neo->next = next; next = neo; boring = 0; } else { curr = next; next = next->next; } } } fmpz_clear(d); *phead = head; } void remove_ones(fr_node_ptr *phead, fr_node_ptr *ptail, fr_node_ptr ohead) { fr_node_ptr head, curr, ocurr, onext; if (!ohead) { *phead = NULL; *ptail = NULL; return; } head = NULL; curr = NULL; ocurr = ohead; while (ocurr) { onext = ocurr->next; if (fr_node_is_one(ocurr)) { fr_node_clear(ocurr); flint_free(ocurr); } else { if (!head) { head = ocurr; curr = ocurr; } else { curr->next = ocurr; curr = curr->next; } } ocurr = onext; } curr->next = NULL; *phead = head; *ptail = curr; } void pair_refine(fr_node_ptr *phead, fr_node_ptr *ptail, fmpz_t m1, ulong e1, fmpz_t m2, ulong e2) { pair_refine_unreduced(phead, m1, e1, m2, e2); remove_ones(phead, ptail, *phead); } void augment_refinement(fr_node_ptr *phead, fr_node_ptr *ptail, const fmpz_t m_jp1, ulong e_jp1, fr_node_ptr L_j, fr_node_ptr L_j_tail) { /* * m_jp1 must have absolute value greater than 1, * and its sign will be discarded. * This function is destructive to the existing refinement L_j */ fr_node_ptr L_jp1, L_jp1_tail, L_prime, L_prime_tail, neo; fmpz_t m; ulong e; /* initialize (m, e) <- (m_{j+1}, 1), L_{j+1} <- empty list */ fmpz_init(m); fmpz_abs(m, m_jp1); e = e_jp1; L_jp1 = NULL; L_jp1_tail = NULL; L_prime = NULL; L_prime_tail = NULL; while (L_j && !fmpz_is_one(m)) { if (!fr_node_is_one(L_j)) { /* L' <- Pair-Refine((m, e), First(L_j)) */ pair_refine(&L_prime, &L_prime_tail, m, e, fr_node_mref(L_j), L_j->e); /* (m, e) <- First(L') */ fr_node_get_fmpz_ui(m, &e, L_prime); /* L' <- Rest(L') */ fr_node_list_pop_front(&L_prime, &L_prime_tail); /* L_{j+1} <- Concat(L_{j+1}, L') */ fr_node_list_concat(&L_jp1, &L_jp1_tail, L_prime, L_prime_tail); } /* L_j <- Rest(L_j) */ fr_node_list_pop_front(&L_j, &L_j_tail); } /* create a single-element list like [(m, e)] */ neo = flint_malloc(sizeof(fr_node_struct)); fr_node_init_fmpz_ui(neo, m, e); /* L_{j+1} <- Concat(L_{j+1}, Rest(L_j), [(m, e)]) */ fr_node_list_pop_front(&L_j, &L_j_tail); fr_node_list_concat(&L_jp1, &L_jp1_tail, L_j, L_j_tail); fr_node_list_concat(&L_jp1, &L_jp1_tail, neo, neo); /* output list of pairs (n_i, e_i) in L_{j+1} with n_i != 1 */ remove_ones(phead, ptail, L_jp1); fmpz_clear(m); } int _fmpz_factor_sgn(const fmpz_factor_t f) { int i, s; ulong e, neg; if (!f->sign) { return 0; } neg = f->sign < 0; for (i = 0; i < f->num; i++) { /* follow the fmpz_pow_ui convention 0^0 = 1 */ e = f->exp[i]; if (e != WORD(0)) { s = fmpz_sgn(f->p+i); if (!s) { return 0; } else if (s < 0) { neg = (neg + e) % 2; } } } return neg ? -1 : 1; } void fmpz_factor_refine(fmpz_factor_t res, const fmpz_factor_t f) { int s; fr_node_ptr L, L_tail, curr; slong i, len; fmpz * b; ulong e; fr_node_ptr * qsort_arr; /* check the sign of f without requiring canonical form */ s = _fmpz_factor_sgn(f); if (!s) { _fmpz_factor_set_length(res, 0); res->sign = 0; return; } /* compute the refinement as a linked list */ for (L = L_tail = NULL, i = 0; i < f->num; i++) { b = f->p+i; e = f->exp[i]; if (e != WORD(0) && !fmpz_is_pm1(b)) { augment_refinement(&L, &L_tail, b, e, L, L_tail); } } /* this is the length of the list of refined factors */ len = fr_node_list_length(L); /* make a sorted array of pointers to the refined factor nodes */ qsort_arr = flint_malloc(sizeof(fr_node_ptr) * len); for (i = 0, curr = L; i < len; i++, curr = curr->next) { qsort_arr[i] = curr; } qsort(qsort_arr, len, sizeof(fr_node_ptr), fr_node_base_pcmp); /* set the length, sign, bases, and exponents of the output structure */ _fmpz_factor_fit_length(res, len); _fmpz_factor_set_length(res, len); res->sign = s; for (i = 0; i < len; i++) { curr = qsort_arr[i]; fmpz_set(res->p+i, fr_node_mref(curr)); res->exp[i] = curr->e; } flint_free(qsort_arr); fr_node_list_clear(L); } flint-3.1.3/src/fmpz_factor/set_length.c000066400000000000000000000013071461254215100202350ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" void _fmpz_factor_set_length(fmpz_factor_t factor, slong newlen) { if (factor->num > newlen) { slong i; for (i = newlen; i < factor->num; i++) _fmpz_demote(factor->p + i); } factor->num = newlen; } flint-3.1.3/src/fmpz_factor/test/000077500000000000000000000000001461254215100167135ustar00rootroot00000000000000flint-3.1.3/src/fmpz_factor/test/main.c000066400000000000000000000024201461254215100200010ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-ecm.c" #include "t-factor.c" #include "t-factor_pp1.c" #include "t-factor_smooth.c" #include "t-factor_trial.c" #include "t-io.c" #include "t-pollard_brent.c" #include "t-pollard_brent_single.c" #include "t-refine.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_factor), TEST_FUNCTION(fmpz_factor_ecm), TEST_FUNCTION(fmpz_factor_fprint), TEST_FUNCTION(fmpz_factor_pp1), TEST_FUNCTION(fmpz_factor_smooth), TEST_FUNCTION(fmpz_factor_trial), TEST_FUNCTION(fmpz_factor_pollard_brent), TEST_FUNCTION(fmpz_factor_pollard_brent_single), TEST_FUNCTION(fmpz_factor_refine) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_factor/test/t-ecm.c000066400000000000000000000057171461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" TEST_FUNCTION_START(fmpz_factor_ecm, state) { fmpz_t prime1, prime2, primeprod, fac, modval; int i, j, k, fails; fmpz_init(prime1); fmpz_init(prime2); fmpz_init(primeprod); fmpz_init(fac); fmpz_init(modval); fails = 0; for (i = 35; i <= 50; i += 5) { for (j = 0; j < flint_test_multiplier(); j++) { fmpz_set_ui(prime1, n_randprime(state, i, 1)); fmpz_set_ui(prime2, n_randprime(state, i, 1)); fmpz_mul(primeprod, prime1, prime2); k = fmpz_factor_ecm(fac, i << 2, 2000, 50000, state, primeprod); if (k == 0) fails += 1; else { fmpz_mod(modval, primeprod, fac); k = fmpz_cmp_ui(modval, 0); if (k != 0) { printf("FAIL : Wrong factor calculated\n"); printf("n : "); fmpz_print(primeprod); printf(" factor calculated : "); fmpz_print(fac); fflush(stdout); flint_abort(); } } } } if (fails > flint_test_multiplier()) { printf("FAIL : ECM failed too many times (%d times)\n", fails); fflush(stdout); flint_abort(); } /* Tests for hangs and crashes, don't care about result */ #if FLINT64 fmpz_set_ui(prime1, 1123047674690129); fmpz_set_ui(prime2, 66049336315331); fmpz_mul(primeprod, prime1, prime2); fmpz_mul(primeprod, primeprod, primeprod); fmpz_factor_ecm(fac, 1, 100, 1000, state, primeprod); /* (p*q)^2 for p and q of 53 bits */ for (i = 0; i < 5; i++) { fmpz_set_ui(prime1, n_randprime(state, 53, 1)); fmpz_set_ui(prime2, n_randprime(state, 53, 1)); fmpz_mul(primeprod, prime1, prime2); fmpz_mul(primeprod, primeprod, primeprod); fmpz_factor_ecm(fac, 212, 2000, 50000, state, primeprod); } /* p^2*q*r for p and q of 53 bits */ for (i = 0; i < 5; i++) { fmpz_set_ui(primeprod, n_randprime(state, 53, 1)); fmpz_mul(primeprod, primeprod, primeprod); fmpz_mul_ui(primeprod, primeprod, n_randprime(state, 53, 1)); fmpz_mul_ui(primeprod, primeprod, n_randprime(state, 53, 1)); fmpz_factor_ecm(fac, 212, 2000, 50000, state, primeprod); } #endif fmpz_clear(prime1); fmpz_clear(prime2); fmpz_clear(primeprod); fmpz_clear(fac); fmpz_clear(modval); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_factor/test/t-factor.c000066400000000000000000000204261461254215100206020ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_factor.h" /* Defined in t-factor.c and t-factor_trial.c */ #define check check_factor void check(fmpz_t n) { fmpz_factor_t factor; fmpz_t m; slong i, j; fmpz_factor_init(factor); fmpz_init(m); fmpz_factor(factor, n); fmpz_factor_expand(m, factor); if (!fmpz_equal(n, m)) { flint_printf("ERROR: factors do not unfactor to original number!\n"); flint_printf("input: "); fmpz_print(n); flint_printf("\n"); flint_printf("computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); flint_printf("value: "); fmpz_print(m); flint_printf("\n"); fflush(stdout); flint_abort(); } for (i = 0; i < factor->num; i++) { if (!fmpz_is_probabprime(factor->p + i)) { flint_printf("ERROR: factor is not prime!\n"); flint_printf("input: "); fmpz_print(n); flint_printf("\n"); flint_printf("computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < factor->num; i++) for (j = i + 1; j < factor->num; j++) { if (!fmpz_cmp(factor->p + i, factor->p + j)) { flint_printf("ERROR: duplicated prime factors, the form is not canonical!\n"); flint_printf("input: "); fmpz_print(n); flint_printf("\n"); flint_printf("computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_clear(m); fmpz_factor_clear(factor); } TEST_FUNCTION_START(fmpz_factor, state) { int i; fmpz_t x, y, z, n; fmpz_factor_t factors; fmpz_init(x); /* Fredrik's example */ #if FLINT64 fmpz_set_ui(x, 3); fmpz_mul_ui(x, x, 73); fmpz_mul_ui(x, x, 137); fmpz_mul_ui(x, x, 1676321); fmpz_mul_ui(x, x, 1676321); fmpz_mul_ui(x, x, 1676321); fmpz_mul_ui(x, x, 5964848081); fmpz_mul_ui(x, x, 78875943472201); fmpz_mul_ui(x, x, 78875943472201); check(x); #endif /* Some corner cases */ fmpz_set_ui(x, UWORD_MAX); check(x); fmpz_set_si(x, WORD_MAX); check(x); fmpz_set_si(x, WORD_MIN); check(x); fmpz_set_si(x, COEFF_MAX); check(x); fmpz_set_si(x, COEFF_MIN); check(x); fmpz_set_si(x, 1); check(x); fmpz_set_si(x, 0); check(x); fmpz_set_si(x, -1); check(x); /* Small integers */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong b = n_randint(state, 10000); if (n_randint(state, 2)) b = -b; fmpz_set_si(x, b); check(x); } /* Powers */ for (i = 1; i < 100 * flint_test_multiplier(); i++) { fmpz_set_ui(x, n_randint(state, 300)); fmpz_pow_ui(x, x, n_randint(state, 300)); check(x); } /* Factorials */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_fac_ui(x, n_randint(state, 1000)); check(x); } /* Powers of factorials */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_fac_ui(x, n_randint(state, 100)); fmpz_pow_ui(x, x, n_randint(state, 5)); check(x); } /* Whole limbs */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_set_ui(x, n_randtest(state)); if (n_randint(state, 2)) fmpz_neg(x, x); check(x); } /* Large negative integers */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_set_ui(x, 10 + n_randint(state, 10)); fmpz_pow_ui(x, x, n_randint(state, 100)); fmpz_neg(x, x); check(x); } fmpz_init(y); fmpz_init(z); fmpz_init(n); for (i = 0; i < 10 + flint_test_multiplier(); i++) /* Test random n, two factors */ { fmpz_randprime(x, state, 50, 0); fmpz_randprime(y, state, 50, 0); fmpz_mul(n, x, y); fmpz_factor_init(factors); fmpz_factor(factors, n); if (factors->num < 2) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 10 + flint_test_multiplier(); i++) /* Test random n, three factors */ { fmpz_randprime(x, state, 40, 0); fmpz_randprime(y, state, 40, 0); fmpz_randprime(z, state, 40, 0); fmpz_mul(n, x, y); fmpz_mul(n, n, z); fmpz_factor_init(factors); fmpz_factor(factors, n); if (factors->num < 3) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 10 + flint_test_multiplier(); i++) /* Test random n, small factors */ { fmpz_randprime(x, state, 10, 0); fmpz_randprime(y, state, 10, 0); fmpz_randprime(z, state, 40, 0); fmpz_mul(n, x, y); fmpz_mul(n, n, z); fmpz_factor_init(factors); fmpz_factor(factors, n); if (factors->num < 3 && !fmpz_equal(x, y)) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5 + flint_test_multiplier(); i++) /* Test random squares */ { fmpz_randprime(x, state, 40, 0); fmpz_mul(n, x, x); fmpz_factor_init(factors); fmpz_factor(factors, n); if (factors->num < 1) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5 + flint_test_multiplier(); i++) /* Test random cubes */ { fmpz_randprime(x, state, 40, 0); fmpz_mul(n, x, x); fmpz_mul(n, n, x); fmpz_factor_init(factors); fmpz_factor(factors, n); if (factors->num < 1) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5 + flint_test_multiplier(); i++) /* Test random p1*p2*p3^2 */ { fmpz_randprime(x, state, 40, 0); fmpz_randprime(y, state, 40, 0); fmpz_randprime(z, state, 40, 0); fmpz_mul(n, x, y); fmpz_mul(n, n, z); fmpz_mul(n, n, z); fmpz_factor_init(factors); fmpz_factor(factors, n); if (factors->num != 3) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 10 + flint_test_multiplier(); i++) /* p1^e1 * p2^e2 * p3^e3 * p4^e4, e1, .., e4 in [1, .., 5] */ { slong j; fmpz_set_ui(n, 1); for (j = 0; j < 4; j++) { fmpz_randprime(x, state, 20 + n_randint(state, 30), 0); fmpz_pow_ui(x, x, n_randint(state, 5) + 1); fmpz_mul(n, n, x); } fmpz_factor_init(factors); fmpz_factor(factors, n); if (factors->num != 4) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); TEST_FUNCTION_END(state); } #undef check flint-3.1.3/src/fmpz_factor/test/t-factor_pp1.c000066400000000000000000000042711461254215100213620ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" TEST_FUNCTION_START(fmpz_factor_pp1, state) { int i, j, result; ulong count = UWORD(0); gmp_randstate_t st; gmp_randinit_default(st); for (i = 0; i < 50 * flint_test_multiplier(); i++) /* Test random numbers */ { flint_bitcnt_t bits; mpz_t m, n; fmpz_t n1, n2, r; mpz_init(n); mpz_init(m); fmpz_init(n1); fmpz_init(n2); fmpz_init(r); do { mpz_urandomb(n, st, n_randint(state, 128) + 2); } while (flint_mpz_cmp_ui(n, 2) < 0); do { mpz_urandomb(m, st, n_randint(state, 50) + 2); } while (!mpz_probab_prime_p(m, 20)); mpz_mul(n, n, m); fmpz_set_mpz(n1, n); bits = FLINT_MIN(fmpz_bits(n1), FLINT_BITS); for (j = 0; j < 20; j++) { fmpz_factor_pp1(n2, n1, 10000, 10000, n_randbits(state, bits - 2) + 3); if (fmpz_cmp_ui(n2, 1) > 0) break; } if (fmpz_cmp_ui(n2, 1) > 0) { count++; fmpz_mod(r, n1, n2); result = (fmpz_is_zero(r)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n1 = "); fmpz_print(n1); flint_printf(", n2 = "); fmpz_print(n2); flint_printf("\n"); fmpz_print(r); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_clear(n1); fmpz_clear(n2); fmpz_clear(r); mpz_clear(m); mpz_clear(n); } if (count < 49 * flint_test_multiplier()) { flint_printf("FAIL:\n"); flint_printf("Only %wu numbers factored\n", count); fflush(stdout); flint_abort(); } gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_factor/test/t-factor_smooth.c000066400000000000000000000127051461254215100221740ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_factor.h" void checkb(fmpz_t n, slong bits) { fmpz_factor_t factor; fmpz_t m; slong i; fmpz_factor_init(factor); fmpz_init(m); fmpz_factor_smooth(factor, n, bits, 0); fmpz_factor_expand(m, factor); if (!fmpz_equal(n, m)) { flint_printf("ERROR: factors do not unfactor to original number!\n"); flint_printf("input: "); fmpz_print(n); flint_printf("\n"); flint_printf("computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); flint_printf("value: "); fmpz_print(m); flint_printf("\n"); fflush(stdout); flint_abort(); } for (i = 0; i < factor->num; i++) { if (!fmpz_is_probabprime(factor->p + i)) { flint_printf("ERROR: factor is not prime!\n"); flint_printf("input: "); fmpz_print(n); flint_printf("\n"); flint_printf("computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_clear(m); fmpz_factor_clear(factor); } TEST_FUNCTION_START(fmpz_factor_smooth, state) { int i; fmpz_t x, y, z, n; fmpz_factor_t factors; fmpz_init(x); /* Some corner cases */ fmpz_set_ui(x, UWORD_MAX); checkb(x, 32); fmpz_set_si(x, WORD_MAX); checkb(x, 32); fmpz_set_si(x, WORD_MIN); checkb(x, 32); fmpz_set_si(x, COEFF_MAX); checkb(x, 32); fmpz_set_si(x, COEFF_MIN); checkb(x, 32); /* Small integers */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong b = n_randint(state, 10000); if (n_randint(state, 2)) b = -b; fmpz_set_si(x, b); checkb(x, 16); } /* Powers */ for (i = 1; i < 100 * flint_test_multiplier(); i++) { fmpz_set_ui(x, n_randint(state, 250)); fmpz_pow_ui(x, x, n_randint(state, 250)); checkb(x, 10); } /* Factorials */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_fac_ui(x, n_randint(state, 1000)); checkb(x, 12); } /* Powers of factorials */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_fac_ui(x, n_randint(state, 100)); fmpz_pow_ui(x, x, n_randint(state, 5)); checkb(x, 12); } /* Whole limbs */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_set_ui(x, n_randtest(state)); if (n_randint(state, 2)) fmpz_neg(x, x); checkb(x, 32); } /* Large negative integers */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_set_ui(x, 10 + n_randint(state, 10)); fmpz_pow_ui(x, x, n_randint(state, 100)); fmpz_neg(x, x); checkb(x, 8); } fmpz_init(y); fmpz_init(z); fmpz_init(n); for (i = 0; i < 20; i++) /* Test random n, three factors */ { fmpz_randprime(x, state, 40, 0); fmpz_randprime(y, state, 40, 0); fmpz_randprime(z, state, 40, 0); fmpz_mul(n, x, y); fmpz_mul(n, n, z); fmpz_factor_init(factors); fmpz_factor_smooth(factors, n, 60, 1); if (factors->num < 3) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 20; i++) /* Test random n, small factors */ { fmpz_randprime(x, state, 10, 0); fmpz_randprime(y, state, 10, 0); fmpz_randprime(z, state, 40, 0); fmpz_mul(n, x, y); fmpz_mul(n, n, z); fmpz_factor_init(factors); fmpz_factor_smooth(factors, n, 20, 1); if (factors->num < 3 && !fmpz_equal(x, y)) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5; i++) /* Test random squares */ { fmpz_randprime(x, state, 40, 0); fmpz_mul(n, x, x); fmpz_factor_init(factors); fmpz_factor_smooth(factors, n, 60, 1); if (factors->num < 1) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5; i++) /* Test random cubes */ { fmpz_randprime(x, state, 40, 0); fmpz_mul(n, x, x); fmpz_mul(n, n, x); fmpz_factor_init(factors); fmpz_factor_smooth(factors, n, 60, 1); if (factors->num < 1) { flint_printf("FAIL:\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_factor/test/t-factor_trial.c000066400000000000000000000076401461254215100220000ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_factor.h" /* Defined in t-factor.c and t-factor_trial.c */ #define check check_factor_trial void check(fmpz_t n) { fmpz_factor_t factor, factor2; fmpz_t m; slong i; int full; fmpz_factor_init(factor); fmpz_factor_init(factor2); fmpz_init(m); full = fmpz_factor_trial(factor, n, 1000); fmpz_factor_trial_range(factor2, n, 0, 1000); fmpz_factor_expand(m, factor); if (!fmpz_equal(n, m)) { flint_printf("ERROR: factors do not unfactor to original number!\n"); flint_printf("input: "); fmpz_print(n); flint_printf("\n"); flint_printf("computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); flint_printf("value: "); fmpz_print(m); flint_printf("\n"); fflush(stdout); flint_abort(); } if (factor->num != factor2->num) { flint_printf("ERROR: number of factors do not agree\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n"); flint_printf("factor_trial computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); flint_printf("factor_trial_range computed factors: "); fmpz_factor_print(factor2); flint_printf("\n"); fflush(stdout); flint_abort(); } for (i = 0; i < factor->num - (full != 1); i++) { if (!fmpz_is_probabprime(factor->p + i)) { flint_printf("ERROR: factor is not prime!\n"); flint_printf("input: "); fmpz_print(n); flint_printf("\n"); flint_printf("computed factors: "); fmpz_factor_print(factor); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_clear(m); fmpz_factor_clear(factor); fmpz_factor_clear(factor2); } TEST_FUNCTION_START(fmpz_factor_trial, state) { int i; fmpz_t x; fmpz_init(x); /* Some corner cases */ fmpz_set_si(x, COEFF_MAX); check(x); fmpz_set_si(x, COEFF_MIN); check(x); /* Small integers */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong b = n_randint(state, 10000); if (n_randint(state, 2)) b = -b; fmpz_set_si(x, b); check(x); } /* Powers */ for (i = 1; i < 100 * flint_test_multiplier(); i++) { fmpz_set_ui(x, n_randint(state, 300)); fmpz_pow_ui(x, x, n_randint(state, 300)); check(x); } /* Factorials */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_fac_ui(x, n_randint(state, 1000)); check(x); } /* Powers of factorials */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_fac_ui(x, n_randint(state, 100)); fmpz_pow_ui(x, x, n_randint(state, 5)); check(x); } /* Large negative integers */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_set_ui(x, 10 + n_randint(state, 10)); fmpz_pow_ui(x, x, n_randint(state, 100)); fmpz_neg(x, x); check(x); } /* regression test */ { fmpz_factor_t fac; fmpz_factor_init(fac); fmpz_set_str(x, "-27881013806671883810", 10); fmpz_factor_trial(fac, x, 0); fmpz_factor_clear(fac); fmpz_factor_init(fac); fmpz_factor_trial(fac, x, 0); fmpz_factor_clear(fac); } fmpz_clear(x); TEST_FUNCTION_END(state); } #undef check flint-3.1.3/src/fmpz_factor/test/t-io.c000066400000000000000000000063171461254215100177360ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "fmpz.h" #include "fmpz_factor.h" #define TMP_FILENAME "tmp" #define STRLEN(x) (sizeof(x) - sizeof(char)) #define RESULT_STRING \ "0\n" \ "1\n" \ "-1\n" \ "3 * 5 * 7\n" \ "-1 * 3^2 * 5^3 * 7" TEST_FUNCTION_START(fmpz_factor_fprint, state) { FILE * fs; fmpz_t a; fmpz_factor_t f; int res, tmp; char str[sizeof(RESULT_STRING)]; fs = fopen(TMP_FILENAME, "w+"); if (fs == NULL) flint_throw(FLINT_TEST_FAIL, "Could not open temporary file \"" TMP_FILENAME "\"\n"); fmpz_init(a); fmpz_factor_init(f); res = 0; /* Print 0 */ fmpz_zero(a); fmpz_factor(f, a); tmp = fmpz_factor_fprint(fs, f); if (tmp != STRLEN("0")) goto wrong_return_value; res += tmp; res += (fputc('\n', fs) != EOF); /* Print 1 */ fmpz_one(a); fmpz_factor(f, a); tmp = fmpz_factor_fprint(fs, f); if (tmp != STRLEN("1")) goto wrong_return_value; res += tmp; res += (fputc('\n', fs) != EOF); /* Print -1 */ fmpz_set_si(a, -1); fmpz_factor(f, a); tmp = fmpz_factor_fprint(fs, f); if (tmp != STRLEN("-1")) goto wrong_return_value; res += tmp; res += (fputc('\n', fs) != EOF); /* Print 3 * 5 * 7 */ fmpz_set_si(a, 3 * 5 * 7); fmpz_factor(f, a); tmp = fmpz_factor_fprint(fs, f); if (tmp != STRLEN("3 * 5 * 7")) goto wrong_return_value; res += tmp; res += (fputc('\n', fs) != EOF); /* Print -1 * 3^2 * 5^3 * 7 */ fmpz_set_si(a, -1 * 9 * 125 * 7); fmpz_factor(f, a); tmp = fmpz_factor_fprint(fs, f); if (tmp != STRLEN("-1 * 3^2 * 5^3 * 7")) { wrong_return_value: fseek(fs, -tmp, SEEK_CUR); fread(str, sizeof(char), tmp, fs); str[tmp] = '\0'; flint_throw(FLINT_TEST_FAIL, "Wrong return value for a = %{fmpz}\n" "Got string: %s\n", a, str); } res += tmp; res += (fputc('\0', fs) != EOF); fseek(fs, 0, SEEK_SET); if (fread(str, sizeof(char), res, fs) != res) flint_throw(FLINT_TEST_FAIL, "Could not read %d bytes from filestream.\n", res); if (strcmp(str, RESULT_STRING)) flint_throw(FLINT_TEST_FAIL, "Result differed from expected output.\n" "Got:\n" "%s\n\n" "Expected:\n" "%s\n", str, RESULT_STRING); fmpz_clear(a); fmpz_factor_clear(f); if (fclose(fs)) flint_throw(FLINT_TEST_FAIL, "Could not close temporary file \"" TMP_FILENAME "\"\n"); if (remove(TMP_FILENAME)) flint_throw(FLINT_TEST_FAIL, "Could not remove temporary file \"" TMP_FILENAME "\"\n"); TEST_FUNCTION_END(state); } #undef TMP_FILENAME #undef STRLEN #undef RESULT_STRING flint-3.1.3/src/fmpz_factor/test/t-pollard_brent.c000066400000000000000000000044251461254215100221540ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" TEST_FUNCTION_START(fmpz_factor_pollard_brent, state) { fmpz_t prime1, prime2, prime3, prime4, primeprod, fac, modval; int i, j, k, fails; fmpz_init(prime1); fmpz_init(prime2); fmpz_init(prime3); fmpz_init(prime4); fmpz_init(primeprod); fmpz_init(fac); fmpz_init(modval); fails = 0; for (i = 10; i < 26; i += 5) { for (j = 0; j < 10 * flint_test_multiplier(); j++) { fmpz_set_ui(prime1, n_randprime(state, i, 1)); fmpz_set_ui(prime2, n_randprime(state, i, 1)); fmpz_set_ui(prime3, n_randprime(state, i, 1)); fmpz_set_ui(prime4, n_randprime(state, i, 1)); fmpz_mul(prime1, prime1, prime2); fmpz_mul(prime3, prime3, prime4); fmpz_mul(primeprod, prime1, prime3); k = fmpz_factor_pollard_brent(fac, state, primeprod, 5, 2500); if (k == 0) fails += 1; else { fmpz_mod(modval, primeprod, fac); k = fmpz_cmp_ui(modval, 0); if (k != 0) { printf("FAIL : Wrong factor calculated\n"); printf("n : "); fmpz_print(primeprod); printf(" factor calculated : "); fmpz_print(fac); fflush(stdout); flint_abort(); } } } } if (fails > 2*flint_test_multiplier()) { printf("FAIL : Pollard Rho failed too many times (%d times)\n", fails); fflush(stdout); flint_abort(); } fmpz_clear(prime1); fmpz_clear(prime2); fmpz_clear(prime3); fmpz_clear(prime4); fmpz_clear(primeprod); fmpz_clear(fac); fmpz_clear(modval); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_factor/test/t-pollard_brent_single.c000066400000000000000000000056271461254215100235220ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" TEST_FUNCTION_START(fmpz_factor_pollard_brent_single, state) { fmpz_t prime1, prime2, prime3, prime4, primeprod, fac, modval, maxa, maxy, a, y; int i, j, k, fails; fmpz_init(prime1); fmpz_init(prime2); fmpz_init(prime3); fmpz_init(prime4); fmpz_init(primeprod); fmpz_init(fac); fmpz_init(modval); fmpz_init(a); fmpz_init(y); fmpz_init(maxa); fmpz_init(maxy); fails = 0; for (i = 5; i < 36 && i <= FLINT_BITS; i += 5) { mp_limb_t maxiter = UWORD(1) << FLINT_MIN(i, FLINT_BITS - 1); for (j = 0; j < 10 * flint_test_multiplier(); j++) { fmpz_set_ui(prime1, n_randprime(state, i, 1)); fmpz_set_ui(prime2, n_randprime(state, i, 1)); fmpz_set_ui(prime3, n_randprime(state, i, 1)); fmpz_set_ui(prime4, n_randprime(state, i, 1)); fmpz_mul(prime1, prime1, prime2); fmpz_mul(prime3, prime3, prime4); fmpz_mul(primeprod, prime1, prime3); /* Assigning random values of y and a */ fmpz_sub_ui(maxa, primeprod, 3); fmpz_randm(a, state, maxa); fmpz_add_ui(a, a, 1); /* 1 <= a <= n - 3 */ fmpz_sub_ui(maxa, primeprod, 1); fmpz_randm(y, state, primeprod); fmpz_add_ui(y, y, 1); /* 1 <= y <= n - 1 */ k = fmpz_factor_pollard_brent_single(fac, primeprod, y, a, maxiter); if (k == 0) fails += 1; else { fmpz_mod(modval, primeprod, fac); k = fmpz_cmp_ui(modval, 0); if (k != 0) { printf("FAIL : Wrong factor calculated\n"); printf("n : "); fmpz_print(primeprod); printf(" factor calculated : "); fmpz_print(fac); fflush(stdout); flint_abort(); } } } } if (fails > flint_test_multiplier()) { printf("FAIL : Pollard Rho failed too many times (%d times)\n", fails); fflush(stdout); flint_abort(); } fmpz_clear(prime1); fmpz_clear(prime2); fmpz_clear(prime3); fmpz_clear(prime4); fmpz_clear(primeprod); fmpz_clear(fac); fmpz_clear(modval); fmpz_clear(a); fmpz_clear(y); fmpz_clear(maxa); fmpz_clear(maxy); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_factor/test/t-refine.c000066400000000000000000000217151461254215100205760ustar00rootroot00000000000000/* Copyright (C) 2015 FLINT authors This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_factor.h" void _fmpz_factor_randtest(fmpz_factor_t f, flint_rand_t state, slong num, flint_bitcnt_t bits); void _fmpz_factor_set(fmpz_factor_t z, const fmpz_factor_t x); int _fmpz_factor_equal(const fmpz_factor_t x, const fmpz_factor_t y); void _fmpz_factor_randtest(fmpz_factor_t f, flint_rand_t state, slong num, flint_bitcnt_t bits) { slong i; ulong n; int s; ulong bases_not_zero, exp_not_zero; bases_not_zero = n_randint(state, 2); exp_not_zero = n_randint(state, 2); /* sign is -1 or 1 or rarely 0 */ s = 0; n = n_randint(state, 11); if (n) { s = (n % 2) ? 1 : -1; } f->sign = s; _fmpz_factor_fit_length(f, num); _fmpz_factor_set_length(f, num); for (i = 0; i < num; i++) { if (bases_not_zero) { fmpz_randtest_not_zero(f->p+i, state, bits); } else { fmpz_randtest(f->p+i, state, bits); } if (exp_not_zero) { f->exp[i] = n_randint(state, 3) + 1; } else { f->exp[i] = n_randint(state, 4); } } } void _fmpz_factor_set(fmpz_factor_t z, const fmpz_factor_t x) { if (z != x) { slong i, len; len = x->num; z->sign = x->sign; _fmpz_factor_fit_length(z, len); _fmpz_factor_set_length(z, len); _fmpz_vec_set(z->p, x->p, len); for (i = 0; i < len; i++) { z->exp[i] = x->exp[i]; } } } int _fmpz_factor_equal(const fmpz_factor_t x, const fmpz_factor_t y) { /* this is not equivalence, but equality in the entrywise sense */ slong len, i; if (x->sign != y->sign || x->num != y->num) { return 0; } len = x->num; if (!_fmpz_vec_equal(x->p, y->p, len)) { return 0; } for (i = 0; i < len; i++) { if (x->exp[i] != y->exp[i]) { return 0; } } return 1; } TEST_FUNCTION_START(fmpz_factor_refine, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { int i; fmpz_factor_t f, g; slong num; flint_bitcnt_t bits; bits = n_randint(state, 80) + 2; num = n_randint(state, 10); /* sample a factor structure that is probably not in canonical form */ fmpz_factor_init(f); _fmpz_factor_randtest(f, state, num, bits); /* compute the factor refinement */ fmpz_factor_init(g); fmpz_factor_refine(g, f); /* each base must not be less than 2 */ for (i = 0; i < g->num; i++) { if (fmpz_cmp_ui(g->p+i, 2) < 0) { flint_printf("FAIL (base minimum)\n"); fmpz_print(g->p+i); flint_printf("\n"); fflush(stdout); flint_abort(); } } /* bases must be increasing */ for (i = 0; i < g->num-1; i++) { if (fmpz_cmp(g->p+i, g->p+i+1) >= 0) { flint_printf("FAIL (base sorting)\n"); fmpz_print(g->p+i); flint_printf(" "); fmpz_print(g->p+i+1); flint_printf("\n"); fflush(stdout); flint_abort(); } } /* each exponent must not be less than 1 */ for (i = 0; i < g->num; i++) { if (g->exp[i] < 1) { flint_printf("FAIL (exponent minimum)\n"); flint_printf("%wd\n", g->exp[i]); fflush(stdout); flint_abort(); } } /* bases must be coprime */ { slong u, v; fmpz_t x; fmpz_init(x); for (u = 0; u < g->num; u++) { for (v = 0; v < u; v++) { fmpz_gcd(x, g->p+u, g->p+v); if (!fmpz_is_one(x)) { flint_printf("FAIL (coprime bases)\n"); fmpz_print(g->p+u); flint_printf(" "); fmpz_print(g->p+v); flint_printf("\n"); fflush(stdout); flint_abort(); } } } fmpz_clear(x); } /* pre- and post- refinement products must be equal */ { fmpz_t x, y; fmpz_init(x); fmpz_init(y); fmpz_factor_expand(x, f); fmpz_factor_expand(y, g); if (!fmpz_equal(x, y)) { flint_printf("FAIL (product equality)\n"); fmpz_factor_print(f); flint_printf(" : "); fmpz_print(x); flint_printf("\n"); fmpz_factor_print(g); flint_printf(" : "); fmpz_print(y); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); } /* * If the product is not zero, each pre-refinement base with a positive * exponent must be representable as a product of powers of * post-refinement bases. */ if (g->sign) { slong i, j; fmpz_t x; fmpz_init(x); for (i = 0; i < f->num; i++) { if (f->exp[i] != WORD(0)) { fmpz_abs(x, f->p+i); for (j = 0; j < g->num; j++) { while (fmpz_divisible(x, g->p+j)) { fmpz_divexact(x, x, g->p+j); } } if (!fmpz_is_one(x)) { flint_printf("FAIL (representation)\n"); fmpz_factor_print(f); flint_printf("\n"); fmpz_factor_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } } } fmpz_clear(x); } /* check idempotence */ { fmpz_factor_t h; fmpz_factor_init(h); fmpz_factor_refine(h, g); if (!_fmpz_factor_equal(g, h)) { flint_printf("FAIL (idempotence)\n"); fmpz_factor_print(f); flint_printf("\n"); fmpz_factor_print(g); flint_printf("\n"); fmpz_factor_print(h); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_factor_clear(h); } /* check aliasing */ { fmpz_factor_t h; fmpz_factor_init(h); _fmpz_factor_set(h, f); fmpz_factor_refine(h, h); if (!_fmpz_factor_equal(g, h)) { flint_printf("FAIL (aliasing)\n"); fmpz_factor_print(f); flint_printf("\n"); fmpz_factor_print(g); flint_printf("\n"); fmpz_factor_print(h); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_factor_clear(h); } fmpz_factor_clear(f); fmpz_factor_clear(g); } /* * check that factor refinement of (1, 2, 3, ..., n) gives the same * result as factoring factorial(n). */ { slong i, j; for (i = 0; i < 100; i++) { fmpz_t x, z; mpz_t y; fmpz_factor_t f, g, h; fmpz_init(x); fmpz_init(z); mpz_init(y); fmpz_factor_init(f); fmpz_factor_init(g); fmpz_factor_init(h); flint_mpz_fac_ui(y, i); fmpz_set_mpz(x, y); f->sign = 1; _fmpz_factor_append(f, x, 1); g->sign = 1; for (j = 1; j < i+1; j++) { _fmpz_factor_append_ui(g, j, 1); } fmpz_factor(f, x); fmpz_factor_refine(h, g); if (!_fmpz_factor_equal(f, h)) { flint_printf("FAIL (factorial)\n"); flint_printf("%wd\n", i); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(z); mpz_clear(y); fmpz_factor_clear(f); fmpz_factor_clear(g); fmpz_factor_clear(h); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll.h000066400000000000000000000131161461254215100154140ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_LLL_H #define FMPZ_LLL_H #ifdef FMPZ_LLL_INLINES_C #define FMPZ_LLL_INLINE #else #define FMPZ_LLL_INLINE static inline #endif #include "fmpz_types.h" #include "d_mat.h" #include "mpf-impl.h" #ifdef __cplusplus extern "C" { #endif #if FLINT_BITS == 32 #define CPU_SIZE_1 31 #define FMPZ_LLL_MAX_LONG WORD(2147483647) #else #define CPU_SIZE_1 53 #define FMPZ_LLL_MAX_LONG WORD(9007199254740991) #endif #define SIZE_RED_FAILURE_THRESH 5 typedef enum { GRAM, Z_BASIS } rep_type; typedef enum { APPROX, EXACT } gram_type; typedef struct { double delta; double eta; rep_type rt; gram_type gt; } fmpz_lll_struct; typedef fmpz_lll_struct fmpz_lll_t[1]; typedef union { d_mat_t appSP; mpf_mat_t appSP2; fmpz_mat_t exactSP; } fmpz_gram_union; typedef fmpz_gram_union fmpz_gram_t[1]; /* Parameter manipulation ***************************************************/ void fmpz_lll_context_init_default(fmpz_lll_t fl); void fmpz_lll_context_init(fmpz_lll_t fl, double delta, double eta, rep_type rt, gram_type gt); /* Random parameter generation **********************************************/ void fmpz_lll_randtest(fmpz_lll_t fl, flint_rand_t state); /* The various Babai's ******************************************************/ double fmpz_lll_heuristic_dot(const double * vec1, const double * vec2, slong len2, const fmpz_mat_t B, slong k, slong j, slong exp_adj); int fmpz_lll_check_babai(int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, d_mat_t appB, int *expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl); int fmpz_lll_check_babai_heuristic_d(int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, d_mat_t appB, int *expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl); int fmpz_lll_shift(const fmpz_mat_t B); int fmpz_lll_d(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); int fmpz_lll_d_heuristic(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); int fmpz_lll_check_babai_heuristic(int kappa, fmpz_mat_t B, fmpz_mat_t U, mpf_mat_t mu, mpf_mat_t r, mpf *s, mpf_mat_t appB, fmpz_gram_t A, int a, int zeros, int kappamax, int n, mpf_t tmp, mpf_t rtmp, flint_bitcnt_t prec, const fmpz_lll_t fl); int fmpz_lll_mpf2(fmpz_mat_t B, fmpz_mat_t U, flint_bitcnt_t prec, const fmpz_lll_t fl); int fmpz_lll_mpf(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); int fmpz_lll_wrapper(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); int fmpz_lll_advance_check_babai(int cur_kappa, int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, d_mat_t appB, int *expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl); int fmpz_lll_advance_check_babai_heuristic_d(int cur_kappa, int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, d_mat_t appB, int *expo, fmpz_gram_t A, int a, int zeros, int kappamax, int n, const fmpz_lll_t fl); /* LLL with removals ********************************************************/ int fmpz_lll_d_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); int fmpz_lll_d_heuristic_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); int fmpz_lll_mpf2_with_removal(fmpz_mat_t B, fmpz_mat_t U, flint_bitcnt_t prec, const fmpz_t gs_B, const fmpz_lll_t fl); int fmpz_lll_mpf_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); int fmpz_lll_wrapper_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); int fmpz_lll_d_with_removal_knapsack(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); int fmpz_lll_wrapper_with_removal_knapsack(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); /* ULLL *********************************************************************/ int fmpz_lll_with_removal_ulll(fmpz_mat_t FM, fmpz_mat_t UM, slong new_size, const fmpz_t gs_B, const fmpz_lll_t fl); /* LLL-reducedness ***********************************************************/ int fmpz_lll_is_reduced_d(const fmpz_mat_t B, const fmpz_lll_t fl); int fmpz_lll_is_reduced_mpfr(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec); int fmpz_lll_is_reduced(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec); int fmpz_lll_is_reduced_d_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd); int fmpz_lll_is_reduced_mpfr_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd,flint_bitcnt_t prec); int fmpz_lll_is_reduced_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd, flint_bitcnt_t prec); /* Default functions *********************************************************/ void fmpz_lll(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); int fmpz_lll_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); /* Modified ULLL ************************************************************/ void fmpz_lll_storjohann_ulll(fmpz_mat_t FM, slong new_size, const fmpz_lll_t fl); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_lll/000077500000000000000000000000001461254215100152415ustar00rootroot00000000000000flint-3.1.3/src/fmpz_lll/advance_check_babai.c000066400000000000000000000025331461254215100212640ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef LIMIT #undef LIMIT #endif #ifdef COMPUTE #undef COMPUTE #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_advance_check_babai(int cur_kappa, int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, \ d_mat_t appB, int *expo, fmpz_gram_t A, \ int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) #define LIMIT cur_kappa #define COMPUTE(G, I, J, C) \ do { \ d_mat_entry(G, I, J) = \ _d_vec_dot(appB->rows[I], appB->rows[J], C); \ } while (0) #define TYPE 2 #include "babai.c" #undef FUNC_HEAD #undef LIMIT #undef COMPUTE #undef TYPE flint-3.1.3/src/fmpz_lll/advance_check_babai_heuristic_d.c000066400000000000000000000026721461254215100236520ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef LIMIT #undef LIMIT #endif #ifdef COMPUTE #undef COMPUTE #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_advance_check_babai_heuristic_d(int cur_kappa, int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, \ d_mat_t appB, int *expo, fmpz_gram_t A, \ int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) #define LIMIT cur_kappa #define COMPUTE(G, I, J, C) \ do { \ d_mat_entry(G, I, J) = \ fmpz_lll_heuristic_dot(appB->rows[I], appB->rows[J], C, \ B, I, J, expo[I] + expo[J]); \ } while (0) #define TYPE 2 #include "babai.c" #undef FUNC_HEAD #undef LIMIT #undef COMPUTE #undef TYPE flint-3.1.3/src/fmpz_lll/babai.c000066400000000000000000000652061461254215100164540ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" #if defined(FUNC_HEAD) && defined(LIMIT) && defined(COMPUTE) && defined(TYPE) #ifdef GM #undef GM #endif #define GM ((fl->rt == Z_BASIS) ? A->exactSP : B) FUNC_HEAD { if (fl->rt == Z_BASIS && fl->gt == APPROX) { int i, j, k, test, aa, exponent, max_expo = INT_MAX; slong xx; double tmp, rtmp, halfplus, onedothalfplus; ulong loops; aa = (a > zeros) ? a : zeros + 1; halfplus = (fl->eta + 0.5) / 2; onedothalfplus = 1.0 + halfplus; loops = 0; do { test = 0; /* ************************************** */ /* Step2: compute the GSO for stage kappa */ /* ************************************** */ for (j = aa; j < LIMIT; j++) { if (d_is_nan(d_mat_entry(A->appSP, kappa, j))) { COMPUTE(A->appSP, kappa, j, n); } if (j > zeros + 2) { tmp = d_mat_entry(mu, j, zeros + 1) * d_mat_entry(r, kappa, zeros + 1); rtmp = d_mat_entry(A->appSP, kappa, j) - tmp; for (k = zeros + 2; k < j - 1; k++) { tmp = d_mat_entry(mu, j, k) * d_mat_entry(r, kappa, k); rtmp = rtmp - tmp; } tmp = d_mat_entry(mu, j, j - 1) * d_mat_entry(r, kappa, j - 1); d_mat_entry(r, kappa, j) = rtmp - tmp; } else if (j == zeros + 2) { tmp = d_mat_entry(mu, j, zeros + 1) * d_mat_entry(r, kappa, zeros + 1); d_mat_entry(r, kappa, j) = d_mat_entry(A->appSP, kappa, j) - tmp; } else d_mat_entry(r, kappa, j) = d_mat_entry(A->appSP, kappa, j); d_mat_entry(mu, kappa, j) = d_mat_entry(r, kappa, j) / d_mat_entry(r, j, j); } if (loops >= 20) { int new_max_expo = INT_MIN; for (j = 0; j < kappa; j++) { int expo2; frexp(d_mat_entry(mu, kappa, j), &expo2); new_max_expo = FLINT_MAX(new_max_expo, expo[kappa] - expo[j] + expo2); } if (new_max_expo > max_expo - SIZE_RED_FAILURE_THRESH) { return -1; } max_expo = new_max_expo; } /* **************************** */ /* Step3--5: compute the X_j's */ /* **************************** */ for (j = LIMIT - 1; j > zeros; j--) { /* test of the relaxed size-reduction condition */ tmp = fabs(d_mat_entry(mu, kappa, j)); tmp = d_mul_2exp(tmp, expo[kappa] - expo[j]); if (tmp > halfplus) { test = 1; exponent = expo[j] - expo[kappa]; /* we consider separately the cases X = +-1 */ if (tmp <= onedothalfplus) { if (d_mat_entry(mu, kappa, j) >= 0) /* in this case, X is 1 */ { for (k = zeros + 1; k < j; k++) { tmp = d_mul_2exp(d_mat_entry(mu, j, k), exponent); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - tmp; } _fmpz_vec_sub(B->rows[kappa], B->rows[kappa], B->rows[j], n); if (U != NULL) { _fmpz_vec_sub(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } else /* otherwise X is -1 */ { for (k = zeros + 1; k < j; k++) { tmp = d_mul_2exp(d_mat_entry(mu, j, k), exponent); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) + tmp; } _fmpz_vec_add(B->rows[kappa], B->rows[kappa], B->rows[j], n); if (U != NULL) { _fmpz_vec_add(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } } else /* we must have |X| >= 2 */ { tmp = d_mul_2exp(d_mat_entry(mu, kappa, j), -exponent); if ((tmp < (double) FMPZ_LLL_MAX_LONG) && (tmp > (double) -FMPZ_LLL_MAX_LONG)) { if (tmp < 0) tmp = ceil(tmp - 0.5); else tmp = floor(tmp + 0.5); for (k = zeros + 1; k < j; k++) { rtmp = tmp * d_mat_entry(mu, j, k); rtmp = d_mul_2exp(rtmp, exponent); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - rtmp; } xx = (slong) tmp; _fmpz_vec_scalar_submul_si(B->rows[kappa], B->rows[j], n, xx); if (U != NULL) { _fmpz_vec_scalar_submul_si(U->rows[kappa], U->rows[j], U->c, xx); } } else { tmp = frexp(d_mat_entry(mu, kappa, j), &exponent); tmp = tmp * FMPZ_LLL_MAX_LONG; xx = (slong) tmp; exponent += expo[kappa] - expo[j] - CPU_SIZE_1; /* This case is extremely rare: never happened for me. Check this: done */ if (exponent <= 0) { /* flint_printf("rare case kappa = %d, j = %d ******\n", kappa, j); */ xx = xx << -exponent; exponent = 0; _fmpz_vec_scalar_submul_si(B->rows[kappa], B->rows[j], n, xx); if (U != NULL) { _fmpz_vec_scalar_submul_si(U->rows [kappa], U->rows[j], U->c, xx); } for (k = zeros + 1; k < j; k++) { rtmp = ((double) xx) * d_mat_entry(mu, j, k); rtmp = d_mul_2exp(rtmp, expo[j] - expo[kappa]); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - rtmp; } } else { _fmpz_vec_scalar_submul_si_2exp(B->rows [kappa], B->rows[j], n, xx, exponent); if (U != NULL) { _fmpz_vec_scalar_submul_si_2exp(U->rows [kappa], U->rows [j], U->c, xx, exponent); } for (k = zeros + 1; k < j; k++) { rtmp = ((double) xx) * d_mat_entry(mu, j, k); rtmp = d_mul_2exp(rtmp, exponent + expo[j] - expo[kappa]); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - rtmp; } } } } } } if (test) /* Anything happened? */ { expo[kappa] = _fmpz_vec_get_d_vec_2exp(appB->rows[kappa], B->rows[kappa], n); aa = zeros + 1; for (i = zeros + 1; i <= LIMIT; i++) d_mat_entry(A->appSP, kappa, i) = D_NAN; for (i = LIMIT + 1; i <= kappamax; i++) d_mat_entry(A->appSP, i, kappa) = D_NAN; } else { #if TYPE == 2 for (i = zeros + 1; i <= LIMIT; i++) d_mat_entry(A->appSP, kappa, i) = D_NAN; #endif } loops++; } while (test); #if TYPE == 1 if (d_is_nan(d_mat_entry(A->appSP, kappa, kappa))) { COMPUTE(A->appSP, kappa, kappa, n); } s[zeros + 1] = d_mat_entry(A->appSP, kappa, kappa); for (k = zeros + 1; k < kappa - 1; k++) { tmp = d_mat_entry(mu, kappa, k) * d_mat_entry(r, kappa, k); s[k + 1] = s[k] - tmp; } #endif } else { int i, j, k, test, aa, exponent, max_expo = INT_MAX; slong exp; slong xx; double tmp, rtmp, halfplus, onedothalfplus; fmpz_t t; ulong loops; aa = (a > zeros) ? a : zeros + 1; fmpz_init(t); halfplus = (fl->eta + 0.5) / 2; onedothalfplus = 1.0 + halfplus; loops = 0; do { fmpz *x; test = 0; /* ************************************** */ /* Step2: compute the GSO for stage kappa */ /* ************************************** */ for (j = aa; j < kappa; j++) { if (j > zeros + 2) { tmp = d_mul_2exp(d_mat_entry(mu, j, zeros + 1) * d_mat_entry(r, kappa, zeros + 1), (expo[j] - expo[zeros + 1])); rtmp = fmpz_get_d_2exp(&exp, fmpz_mat_entry(GM, kappa, j)); rtmp = d_mul_2exp(rtmp, (exp - expo[kappa])) - tmp; for (k = zeros + 2; k < j - 1; k++) { tmp = d_mul_2exp(d_mat_entry(mu, j, k) * d_mat_entry(r, kappa, k), (expo[j] - expo[k])); rtmp = rtmp - tmp; } tmp = d_mul_2exp(d_mat_entry(mu, j, j - 1) * d_mat_entry(r, kappa, j - 1), (expo[j] - expo[j - 1])); d_mat_entry(r, kappa, j) = rtmp - tmp; } else if (j == zeros + 2) { tmp = d_mul_2exp(d_mat_entry(mu, j, zeros + 1) * d_mat_entry(r, kappa, zeros + 1), (expo[j] - expo[zeros + 1])); d_mat_entry(r, kappa, j) = fmpz_get_d_2exp(&exp, fmpz_mat_entry(GM, kappa, j)); d_mat_entry(r, kappa, j) = d_mul_2exp(d_mat_entry(r, kappa, j), (exp - expo[kappa])) - tmp; } else { d_mat_entry(r, kappa, j) = fmpz_get_d_2exp(&exp, fmpz_mat_entry(GM, kappa, j)); d_mat_entry(r, kappa, j) = d_mul_2exp(d_mat_entry(r, kappa, j), (exp - expo[kappa])); } d_mat_entry(mu, kappa, j) = d_mat_entry(r, kappa, j) / d_mat_entry(r, j, j); } if (loops >= 20) { int new_max_expo = INT_MIN; for (j = 0; j < kappa; j++) { int expo2; frexp(d_mat_entry(mu, kappa, j), &expo2); new_max_expo = FLINT_MAX(new_max_expo, expo[kappa] - expo[j] + expo2); } if (new_max_expo > max_expo - SIZE_RED_FAILURE_THRESH) { fmpz_clear(t); return -1; } max_expo = new_max_expo; } /* **************************** */ /* Step3--5: compute the X_j's */ /* **************************** */ x = _fmpz_vec_init(kappa - 1 - zeros); for (j = kappa - 1; j > zeros; j--) { /* test of the relaxed size-reduction condition */ tmp = fabs(d_mat_entry(mu, kappa, j)); tmp = d_mul_2exp(tmp, expo[kappa] - expo[j]); if (tmp > halfplus) { test = 1; exponent = expo[j] - expo[kappa]; /* we consider separately the cases X = +-1 */ if (tmp <= onedothalfplus) { if (d_mat_entry(mu, kappa, j) >= 0) /* in this case, X is 1 */ { fmpz_set_ui(x + j - zeros - 1, 1); for (k = zeros + 1; k < j; k++) { tmp = d_mul_2exp(d_mat_entry(mu, j, k), exponent); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - tmp; } if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_sub(B->rows[kappa], B->rows[kappa], B->rows[j], n); } if (U != NULL) { _fmpz_vec_sub(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } else /* otherwise X is -1 */ { fmpz_set_si(x + j - zeros - 1, -WORD(1)); for (k = zeros + 1; k < j; k++) { tmp = d_mul_2exp(d_mat_entry(mu, j, k), exponent); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) + tmp; } if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_add(B->rows[kappa], B->rows[kappa], B->rows[j], n); } if (U != NULL) { _fmpz_vec_add(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } } else /* we must have |X| >= 2 */ { tmp = d_mul_2exp(d_mat_entry(mu, kappa, j), -exponent); if ((tmp < (double) FMPZ_LLL_MAX_LONG) && (tmp > (double) -FMPZ_LLL_MAX_LONG)) { if (tmp < 0) tmp = ceil(tmp - 0.5); else tmp = floor(tmp + 0.5); for (k = zeros + 1; k < j; k++) { rtmp = tmp * d_mat_entry(mu, j, k); rtmp = d_mul_2exp(rtmp, exponent); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - rtmp; } xx = (slong) tmp; fmpz_set_si(x + j - zeros - 1, xx); if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_scalar_submul_si(B->rows[kappa], B->rows[j], n, xx); } if (U != NULL) { _fmpz_vec_scalar_submul_si(U->rows[kappa], U->rows[j], U->c, xx); } } else { tmp = frexp(d_mat_entry(mu, kappa, j), &exponent); tmp = tmp * FMPZ_LLL_MAX_LONG; xx = (slong) tmp; exponent += expo[kappa] - expo[j] - CPU_SIZE_1; /* This case is extremely rare: never happened for me. Check this: done */ if (exponent <= 0) { /* flint_printf("rare case kappa = %d, j = %d ******\n", kappa, j); */ xx = xx << -exponent; exponent = 0; fmpz_set_si(x + j - zeros - 1, xx); if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_scalar_submul_si(B->rows [kappa], B->rows[j], n, xx); } if (U != NULL) { _fmpz_vec_scalar_submul_si(U->rows [kappa], U->rows[j], U->c, xx); } for (k = zeros + 1; k < j; k++) { rtmp = ((double) xx) * d_mat_entry(mu, j, k); rtmp = d_mul_2exp(rtmp, expo[j] - expo[kappa]); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - rtmp; } } else { fmpz_set_si(x + j - zeros - 1, xx); fmpz_mul_2exp(x + j - zeros - 1, x + j - zeros - 1, exponent); if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_scalar_submul_si_2exp(B->rows [kappa], B->rows [j], n, xx, exponent); } if (U != NULL) { _fmpz_vec_scalar_submul_si_2exp(U->rows [kappa], U->rows [j], U->c, xx, exponent); } for (k = zeros + 1; k < j; k++) { rtmp = ((double) xx) * d_mat_entry(mu, j, k); rtmp = d_mul_2exp(rtmp, exponent + expo[j] - expo[kappa]); d_mat_entry(mu, kappa, k) = d_mat_entry(mu, kappa, k) - rtmp; } } } } } } if (test) /* Anything happened? */ { aa = zeros + 1; for (j = zeros + 1; j < kappa; j++) { fmpz_pow_ui(t, x + j - zeros - 1, 2); fmpz_addmul(fmpz_mat_entry(GM, kappa, kappa), t, fmpz_mat_entry(GM, j, j)); fmpz_mul(t, x + j - zeros - 1, fmpz_mat_entry(GM, kappa, j)); fmpz_mul_2exp(t, t, 1); fmpz_sub(fmpz_mat_entry(GM, kappa, kappa), fmpz_mat_entry(GM, kappa, kappa), t); for (i = zeros + 1; i < j; i++) { fmpz_mul(t, x + i - zeros - 1, x + j - zeros - 1); fmpz_mul(t, t, fmpz_mat_entry(GM, j, i)); fmpz_mul_2exp(t, t, 1); fmpz_add(fmpz_mat_entry(GM, kappa, kappa), fmpz_mat_entry(GM, kappa, kappa), t); } } fmpz_get_d_2exp(&exp, fmpz_mat_entry(GM, kappa, kappa)); expo[kappa] = exp; for (i = zeros + 1; i < kappa; i++) { for (j = zeros + 1; j <= i; j++) fmpz_submul(fmpz_mat_entry(GM, kappa, i), x + j - zeros - 1, fmpz_mat_entry(GM, i, j)); for (j = i + 1; j < kappa; j++) fmpz_submul(fmpz_mat_entry(GM, kappa, i), x + j - zeros - 1, fmpz_mat_entry(GM, j, i)); } for (i = kappa + 1; i < GM->r; i++) { for (j = zeros + 1; j < kappa; j++) fmpz_submul(fmpz_mat_entry(GM, i, kappa), x + j - zeros - 1, fmpz_mat_entry(GM, i, j)); } } _fmpz_vec_clear(x, kappa - 1 - zeros); loops++; } while (test); s[zeros + 1] = fmpz_get_d_2exp(&exp, fmpz_mat_entry(GM, kappa, kappa)); s[zeros + 1] = d_mul_2exp(s[zeros + 1], exp - expo[kappa]); for (k = zeros + 1; k < kappa - 1; k++) { tmp = d_mul_2exp(d_mat_entry(mu, kappa, k) * d_mat_entry(r, kappa, k), (expo[kappa] - expo[k])); s[k + 1] = s[k] - tmp; } fmpz_clear(t); } return 0; } #undef GM #endif flint-3.1.3/src/fmpz_lll/check_babai.c000066400000000000000000000030621461254215100176010ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef LIMIT #undef LIMIT #endif #ifdef COMPUTE #undef COMPUTE #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_check_babai(int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, \ d_mat_t appB, int *expo, fmpz_gram_t A, \ int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) #define LIMIT kappa #define COMPUTE(G, I, J, C) \ do { \ if (I != J) \ d_mat_entry(G, I, J) = \ _d_vec_dot(appB->rows[I], appB->rows[J], C); \ else \ d_mat_entry(G, I, J) = _d_vec_norm(appB->rows[I], C); \ } while (0) #define TYPE 1 #include "babai.c" #undef FUNC_HEAD #undef LIMIT #undef COMPUTE #undef TYPE flint-3.1.3/src/fmpz_lll/check_babai_heuristic.c000066400000000000000000000503761461254215100216720ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef GM #undef GM #endif #define GM ((fl->rt == Z_BASIS) ? A->exactSP : B) int fmpz_lll_check_babai_heuristic(int kappa, fmpz_mat_t B, fmpz_mat_t U, mpf_mat_t mu, mpf_mat_t r, mpf * s, mpf_mat_t appB, fmpz_gram_t A, int a, int zeros, int kappamax, int n, mpf_t tmp, mpf_t rtmp, flint_bitcnt_t prec, const fmpz_lll_t fl) { if (fl->rt == Z_BASIS && fl->gt == APPROX) { int i, j, k, test, aa; slong xx, exponent, max_expo = WORD_MAX; fmpz_t ztmp; double halfplus, onedothalfplus; ulong loops; fmpz_init(ztmp); aa = (a > zeros) ? a : zeros + 1; halfplus = (fl->eta + 0.5) / 2; onedothalfplus = 1.0 + halfplus; loops = 0; do { test = 0; /* ************************************** */ /* Step2: compute the GSO for stage kappa */ /* ************************************** */ for (j = aa; j < kappa; j++) { if (mpf_cmp_d(mpf_mat_entry(A->appSP2, kappa, j), DBL_MIN) == 0) { if (! (_mpf_vec_dot2 (mpf_mat_entry(A->appSP2, kappa, j), appB->rows[kappa], appB->rows[j], n, prec))) { /* In this case a heuristic told us that some cancellation probably happened so we just compute the scalar product at full precision */ _fmpz_vec_dot(ztmp, B->rows[kappa], B->rows[j], n); fmpz_get_mpf(mpf_mat_entry(A->appSP2, kappa, j), ztmp); } } if (j > zeros + 2) { mpf_mul(tmp, mpf_mat_entry(mu, j, zeros + 1), mpf_mat_entry(r, kappa, zeros + 1)); mpf_sub(rtmp, mpf_mat_entry(A->appSP2, kappa, j), tmp); for (k = zeros + 2; k < j - 1; k++) { mpf_mul(tmp, mpf_mat_entry(mu, j, k), mpf_mat_entry(r, kappa, k)); mpf_sub(rtmp, rtmp, tmp); } mpf_mul(tmp, mpf_mat_entry(mu, j, j - 1), mpf_mat_entry(r, kappa, j - 1)); mpf_sub(mpf_mat_entry(r, kappa, j), rtmp, tmp); } else if (j == zeros + 2) { mpf_mul(tmp, mpf_mat_entry(mu, j, zeros + 1), mpf_mat_entry(r, kappa, zeros + 1)); mpf_sub(mpf_mat_entry(r, kappa, j), mpf_mat_entry(A->appSP2, kappa, j), tmp); } else mpf_set(mpf_mat_entry(r, kappa, j), mpf_mat_entry(A->appSP2, kappa, j)); mpf_div(mpf_mat_entry(mu, kappa, j), mpf_mat_entry(r, kappa, j), mpf_mat_entry(r, j, j)); } if (loops >= 20) { slong new_max_expo = WORD_MIN; for (j = 0; j < kappa; j++) { slong expo2; flint_mpf_get_d_2exp(&expo2, mpf_mat_entry(mu, kappa, j)); new_max_expo = FLINT_MAX(new_max_expo, expo2); } if (new_max_expo > max_expo - SIZE_RED_FAILURE_THRESH) { fmpz_clear(ztmp); return -1; } max_expo = new_max_expo; } /* **************************** */ /* Step3--5: compute the X_j's */ /* **************************** */ for (j = kappa - 1; j > zeros; j--) { /* test of the relaxed size-reduction condition */ mpf_abs(tmp, mpf_mat_entry(mu, kappa, j)); if (mpf_cmp_d(tmp, halfplus) > 0) { test = 1; /* we consider separately the cases X = +-1 */ if (mpf_cmp_d(tmp, onedothalfplus) <= 0) { int sgn = mpf_sgn(mpf_mat_entry(mu, kappa, j)); if (sgn >= 0) /* in this case, X is 1 */ { for (k = zeros + 1; k < j; k++) { mpf_sub(mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, j, k)); } _fmpz_vec_sub(B->rows[kappa], B->rows[kappa], B->rows[j], n); if (U != NULL) { _fmpz_vec_sub(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } else /* otherwise X is -1 */ { for (k = zeros + 1; k < j; k++) { mpf_add(mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, j, k)); } _fmpz_vec_add(B->rows[kappa], B->rows[kappa], B->rows[j], n); if (U != NULL) { _fmpz_vec_add(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } } else /* we must have |X| >= 2 */ { mpf_set(tmp, mpf_mat_entry(mu, kappa, j)); mpf_set_d(rtmp, 0.5); if (flint_mpf_cmp_ui(tmp, 0) < 0) { mpf_sub(tmp, tmp, rtmp); mpf_ceil(tmp, tmp); } else { mpf_add(tmp, tmp, rtmp); mpf_floor(tmp, tmp); } for (k = zeros + 1; k < j; k++) { mpf_mul(rtmp, tmp, mpf_mat_entry(mu, j, k)); mpf_sub(mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, kappa, k), rtmp); } flint_mpf_get_d_2exp(&exponent, tmp); if (exponent < CPU_SIZE_1 - 2) { /* X is stored in an slong */ xx = flint_mpf_get_si(tmp); _fmpz_vec_scalar_submul_si(B->rows[kappa], B->rows[j], n, xx); if (U != NULL) { _fmpz_vec_scalar_submul_si(U->rows[kappa], U->rows[j], U->c, xx); } } else { fmpz_set_mpf(ztmp, tmp); _fmpz_vec_scalar_submul_fmpz(B->rows[kappa], B->rows[j], n, ztmp); if (U != NULL) { _fmpz_vec_scalar_submul_fmpz(U->rows [kappa], U->rows[j], U->c, ztmp); } } } } } if (test) /* Anything happened? */ { _mpf_vec_set_fmpz_vec(appB->rows[kappa], B->rows[kappa], n); aa = zeros + 1; for (i = zeros + 1; i <= kappa; i++) mpf_set_d(mpf_mat_entry(A->appSP2, kappa, i), DBL_MIN); for (i = kappa + 1; i <= kappamax; i++) mpf_set_d(mpf_mat_entry(A->appSP2, i, kappa), DBL_MIN); } loops++; } while (test); if (mpf_cmp_d(mpf_mat_entry(A->appSP2, kappa, kappa), DBL_MIN) == 0) { _mpf_vec_norm2(mpf_mat_entry(A->appSP2, kappa, kappa), appB->rows[kappa], n, prec); } mpf_set(s + zeros + 1, mpf_mat_entry(A->appSP2, kappa, kappa)); for (k = zeros + 1; k < kappa - 1; k++) { mpf_mul(tmp, mpf_mat_entry(mu, kappa, k), mpf_mat_entry(r, kappa, k)); mpf_sub(s + k + 1, s + k, tmp); } fmpz_clear(ztmp); } else { int i, j, k, test, aa; slong xx, exponent, max_expo = WORD_MAX; fmpz_t ztmp; double halfplus, onedothalfplus; ulong loops; fmpz_init(ztmp); aa = (a > zeros) ? a : zeros + 1; halfplus = (fl->eta + 0.5) / 2; onedothalfplus = 1.0 + halfplus; loops = 0; do { fmpz *x; test = 0; /* ************************************** */ /* Step2: compute the GSO for stage kappa */ /* ************************************** */ for (j = aa; j < kappa; j++) { if (j > zeros + 2) { mpf_mul(tmp, mpf_mat_entry(mu, j, zeros + 1), mpf_mat_entry(r, kappa, zeros + 1)); fmpz_get_mpf(rtmp, fmpz_mat_entry(GM, kappa, j)); mpf_sub(rtmp, rtmp, tmp); for (k = zeros + 2; k < j - 1; k++) { mpf_mul(tmp, mpf_mat_entry(mu, j, k), mpf_mat_entry(r, kappa, k)); mpf_sub(rtmp, rtmp, tmp); } mpf_mul(tmp, mpf_mat_entry(mu, j, j - 1), mpf_mat_entry(r, kappa, j - 1)); mpf_sub(mpf_mat_entry(r, kappa, j), rtmp, tmp); } else if (j == zeros + 2) { mpf_mul(tmp, mpf_mat_entry(mu, j, zeros + 1), mpf_mat_entry(r, kappa, zeros + 1)); fmpz_get_mpf(mpf_mat_entry(r, kappa, j), fmpz_mat_entry(GM, kappa, j)); mpf_sub(mpf_mat_entry(r, kappa, j), mpf_mat_entry(r, kappa, j), tmp); } else fmpz_get_mpf(mpf_mat_entry(r, kappa, j), fmpz_mat_entry(GM, kappa, j)); mpf_div(mpf_mat_entry(mu, kappa, j), mpf_mat_entry(r, kappa, j), mpf_mat_entry(r, j, j)); } if (loops >= 20) { slong new_max_expo = WORD_MIN; for (j = 0; j < kappa; j++) { slong expo2; flint_mpf_get_d_2exp(&expo2, mpf_mat_entry(mu, kappa, j)); new_max_expo = FLINT_MAX(new_max_expo, expo2); } if (new_max_expo > max_expo - SIZE_RED_FAILURE_THRESH) { fmpz_clear(ztmp); return -1; } max_expo = new_max_expo; } /* **************************** */ /* Step3--5: compute the X_j's */ /* **************************** */ x = _fmpz_vec_init(kappa - 1 - zeros); for (j = kappa - 1; j > zeros; j--) { /* test of the relaxed size-reduction condition */ mpf_abs(tmp, mpf_mat_entry(mu, kappa, j)); if (mpf_cmp_d(tmp, halfplus) > 0) { test = 1; /* we consider separately the cases X = +-1 */ if (mpf_cmp_d(tmp, onedothalfplus) <= 0) { int sgn = mpf_sgn(mpf_mat_entry(mu, kappa, j)); if (sgn >= 0) /* in this case, X is 1 */ { fmpz_set_ui(x + j, 1); for (k = zeros + 1; k < j; k++) { mpf_sub(mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, j, k)); } if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_sub(B->rows[kappa], B->rows[kappa], B->rows[j], n); } if (U != NULL) { _fmpz_vec_sub(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } else /* otherwise X is -1 */ { fmpz_set_si(x + j, -WORD(1)); for (k = zeros + 1; k < j; k++) { mpf_add(mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, j, k)); } if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_add(B->rows[kappa], B->rows[kappa], B->rows[j], n); } if (U != NULL) { _fmpz_vec_add(U->rows[kappa], U->rows[kappa], U->rows[j], U->c); } } } else /* we must have |X| >= 2 */ { mpf_set(tmp, mpf_mat_entry(mu, kappa, j)); mpf_set_d(rtmp, 0.5); if (flint_mpf_cmp_ui(tmp, 0) < 0) { mpf_sub(tmp, tmp, rtmp); mpf_ceil(tmp, tmp); } else { mpf_add(tmp, tmp, rtmp); mpf_floor(tmp, tmp); } for (k = zeros + 1; k < j; k++) { mpf_mul(rtmp, tmp, mpf_mat_entry(mu, j, k)); mpf_sub(mpf_mat_entry(mu, kappa, k), mpf_mat_entry(mu, kappa, k), rtmp); } flint_mpf_get_d_2exp(&exponent, tmp); if (exponent < CPU_SIZE_1 - 2) { /* X is stored in an slong */ xx = flint_mpf_get_si(tmp); fmpz_set_si(x + j, xx); if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_scalar_submul_si(B->rows[kappa], B->rows[j], n, xx); } if (U != NULL) { _fmpz_vec_scalar_submul_si(U->rows[kappa], U->rows[j], U->c, xx); } } else { fmpz_set_mpf(x + j, tmp); if (fl->rt == Z_BASIS && B != NULL) { _fmpz_vec_scalar_submul_fmpz(B->rows[kappa], B->rows[j], n, x + j); } if (U != NULL) { _fmpz_vec_scalar_submul_fmpz(U->rows [kappa], U->rows[j], U->c, x + j); } } } } } if (test) /* Anything happened? */ { aa = zeros + 1; for (j = zeros + 1; j < kappa; j++) { fmpz_pow_ui(ztmp, x + j, 2); fmpz_addmul(fmpz_mat_entry(GM, kappa, kappa), ztmp, fmpz_mat_entry(GM, j, j)); fmpz_mul(ztmp, x + j, fmpz_mat_entry(GM, kappa, j)); fmpz_mul_2exp(ztmp, ztmp, 1); fmpz_sub(fmpz_mat_entry(GM, kappa, kappa), fmpz_mat_entry(GM, kappa, kappa), ztmp); for (i = zeros + 1; i < j; i++) { fmpz_mul(ztmp, x + i, x + j); fmpz_mul(ztmp, ztmp, fmpz_mat_entry(GM, j, i)); fmpz_mul_2exp(ztmp, ztmp, 1); fmpz_add(fmpz_mat_entry(GM, kappa, kappa), fmpz_mat_entry(GM, kappa, kappa), ztmp); } } for (i = zeros + 1; i < kappa; i++) { for (j = zeros + 1; j <= i; j++) fmpz_submul(fmpz_mat_entry(GM, kappa, i), x + j, fmpz_mat_entry(GM, i, j)); for (j = i + 1; j < kappa; j++) fmpz_submul(fmpz_mat_entry(GM, kappa, i), x + j, fmpz_mat_entry(GM, j, i)); } for (i = kappa + 1; i < GM->r; i++) { for (j = zeros + 1; j < kappa; j++) fmpz_submul(fmpz_mat_entry(GM, i, kappa), x + j, fmpz_mat_entry(GM, i, j)); } } _fmpz_vec_clear(x, kappa - 1 - zeros); loops++; } while (test); fmpz_get_mpf(s + zeros + 1, fmpz_mat_entry(GM, kappa, kappa)); for (k = zeros + 1; k < kappa - 1; k++) { mpf_mul(tmp, mpf_mat_entry(mu, kappa, k), mpf_mat_entry(r, kappa, k)); mpf_sub(s + k + 1, s + k, tmp); } fmpz_clear(ztmp); } return 0; } #undef GM flint-3.1.3/src/fmpz_lll/check_babai_heuristic_d.c000066400000000000000000000026371461254215100221720ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef LIMIT #undef LIMIT #endif #ifdef COMPUTE #undef COMPUTE #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_check_babai_heuristic_d(int kappa, fmpz_mat_t B, fmpz_mat_t U, d_mat_t mu, d_mat_t r, double *s, \ d_mat_t appB, int *expo, fmpz_gram_t A, \ int a, int zeros, int kappamax, int n, const fmpz_lll_t fl) #define LIMIT kappa #define COMPUTE(G, I, J, C) \ do { \ d_mat_entry(G, I, J) = \ fmpz_lll_heuristic_dot(appB->rows[I], appB->rows[J], C, \ B, I, J, expo[I] + expo[J]); \ } while (0) #define TYPE 1 #include "babai.c" #undef FUNC_HEAD #undef LIMIT #undef COMPUTE #undef TYPE flint-3.1.3/src/fmpz_lll/context_init.c000066400000000000000000000012431461254215100201140ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" void fmpz_lll_context_init(fmpz_lll_t fl, double delta, double eta, rep_type rt, gram_type gt) { fl->delta = delta; fl->eta = eta; fl->rt = rt; fl->gt = gt; } flint-3.1.3/src/fmpz_lll/context_init_default.c000066400000000000000000000011511461254215100216160ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" void fmpz_lll_context_init_default(fmpz_lll_t fl) { fl->delta = 0.99; fl->eta = 0.51; fl->rt = Z_BASIS; fl->gt = APPROX; } flint-3.1.3/src/fmpz_lll/d_lll.c000066400000000000000000000600271461254215100165000ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" #if defined(FUNC_HEAD) && defined(CALL_BABAI) && defined(TYPE) #ifdef GM #undef GM #endif #define GM ((fl->rt == Z_BASIS) ? A->exactSP : B) FUNC_HEAD { int newd = 0; #if TYPE int ok = 1; fmpz_t rii; #endif int *expo = NULL; if (fl->rt == Z_BASIS && fl->gt == APPROX) { int kappa, kappa2, d, n, i, j, zeros, kappamax, shift; int num_failed_fast = 0; int babai_ok = 0; int heuristic_fail = 0; d_mat_t mu, r, appB; fmpz_gram_t A; double *s, *mutmp, *appBtmp, *appSPtmp; double ctt; int *alpha; fmpz *Btmp; ulong max_exp, iter, max_iter, newvec, newvec_max; n = B->c; d = B->r; ctt = (fl->delta + 1) / 2; shift = fmpz_lll_shift(B); alpha = (int *) flint_malloc(d * sizeof(int)); expo = (int *) flint_malloc(d * sizeof(int)); d_mat_init(mu, d, d); d_mat_init(r, d, d); d_mat_init(appB, d, n); d_mat_init(A->appSP, d, d); s = _d_vec_init(d); appSPtmp = _d_vec_init(d); if (U != NULL) { if (U->r != d) { flint_throw(FLINT_ERROR, "(fmpz_lll_d*): Incompatible dimensions of capturing matrix.\n"); } } for (i = 0; i < d; i++) { for (j = 0; j < d; j++) { d_mat_entry(A->appSP, i, j) = D_NAN; } } /* ************************** */ /* Step1: Initialization Step */ /* ************************** */ max_exp = 0; for (i = 0; i < d; i++) { expo[i] = _fmpz_vec_get_d_vec_2exp(appB->rows[i], B->rows[i], n); max_exp = FLINT_MAX(max_exp, expo[i]); } max_iter = (ulong) ((d - 1) + (d - 1) * d * (2 * max_exp + d_log2(d)) / d_log2(8 / (fl->delta + 7))); /* ********************************* */ /* Step2: Initializing the main loop */ /* ********************************* */ kappamax = 0; i = 0; do { d_mat_entry(A->appSP, i, i) = _d_vec_norm(appB->rows[i], n); } while ((d_mat_entry(A->appSP, i, i) <= 0.0) && (++i < d)); /* Check if this should be D_EPS and not 0.0: done */ zeros = i - 1; /* all vectors B[i] with i <= zeros are zero vectors */ kappa = i + 1; kappamax = kappa; if (zeros < d - 1) { d_mat_entry(r, i, i) = d_mat_entry(A->appSP, i, i); } for (i = zeros + 1; i < d; i++) alpha[i] = 0; newvec = 0; newvec_max = 1; iter = 0; while (kappa < d) { int new_kappa; double tmp = 0.0; if (iter >= max_iter) { break; } iter++; new_kappa = 0; if (kappa > kappamax) { /* In the first time we hit a new kappa we're going to size-reduce in advance (for knapsack)... */ kappamax = kappa; newvec++; if (newvec > newvec_max) { newvec_max *= 2; newvec = 0; new_kappa = 1; } } /* ********************************** */ /* Step3: Call to the Babai algorithm */ /* ********************************** */ CALL_BABAI(num_failed_fast, babai_ok, heuristic_fail); if (heuristic_fail == -1) { flint_free(alpha); flint_free(expo); d_mat_clear(mu); d_mat_clear(r); d_mat_clear(appB); d_mat_clear(A->appSP); _d_vec_clear(s); _d_vec_clear(appSPtmp); /* Need to switch to mpf / arb */ return -1; } /* End of the real Babai part... */ if (new_kappa == 1) { #if TYPE == 2 /* running ahead to kappa = d, without upsetting LLL... */ for (kappa2 = d - 1; kappa2 > kappa; kappa2--) { babai_ok = fmpz_lll_advance_check_babai(kappa, kappa2, B, U, mu, r, s, appB, expo, A, alpha[kappa2], zeros, kappa + 1, n, fl); if (babai_ok == -1) { heuristic_fail = fmpz_lll_advance_check_babai_heuristic_d(kappa, kappa2, B, U, mu, r, s, appB, expo, A, alpha [kappa2], zeros, kappa + 1, n, fl); } } #endif } /* ************************************ */ /* Step4: Success of Lovasz's condition */ /* ************************************ */ tmp = d_mat_entry(r, kappa - 1, kappa - 1) * ctt; tmp = d_mul_2exp(tmp, 2 * (expo[kappa - 1] - expo[kappa])); if (tmp <= s[kappa - 1]) { alpha[kappa] = kappa; tmp = d_mat_entry(mu, kappa, kappa - 1) * d_mat_entry(r, kappa, kappa - 1); d_mat_entry(r, kappa, kappa) = s[kappa - 1] - tmp; kappa++; } else { /* ******************************************* */ /* Step5: Find the right insertion index kappa */ /* kappa2 remains the initial kappa */ /* ******************************************* */ kappa2 = kappa; #if TYPE if (kappa == d - 1 && gs_B != NULL) { fmpz_init(rii); tmp = 2 * d_mat_entry(mu, kappa, kappa - 1) * d_mat_entry(r, kappa, kappa - 1); fmpz_set_d_2exp(rii, s[kappa - 1] - tmp, 2 * expo[kappa]); /* using a heuristic lower bound on the final GS norm */ if (fmpz_cmp(rii, gs_B) > 0) { d--; } fmpz_clear(rii); if (kappa >= d) { break; } } #endif do { kappa--; if (kappa > zeros + 1) { tmp = d_mat_entry(r, kappa - 1, kappa - 1) * ctt; tmp = d_mul_2exp(tmp, 2 * (expo[kappa - 1] - expo[kappa2])); } } while ((kappa >= zeros + 2) && (s[kappa - 1] <= tmp)); for (i = kappa; i < kappa2; i++) if (kappa <= alpha[i]) alpha[i] = kappa; for (i = kappa2; i > kappa; i--) alpha[i] = alpha[i - 1]; for (i = kappa2 + 1; i <= kappamax; i++) if (kappa < alpha[i]) alpha[i] = kappa; alpha[kappa] = kappa; /* ****************************** */ /* Step6: Update the mu's and r's */ /* ****************************** */ mutmp = mu->rows[kappa2]; for (i = kappa2; i > kappa; i--) mu->rows[i] = mu->rows[i - 1]; mu->rows[kappa] = mutmp; mutmp = r->rows[kappa2]; for (i = kappa2; i > kappa; i--) r->rows[i] = r->rows[i - 1]; r->rows[kappa] = mutmp; d_mat_entry(r, kappa, kappa) = s[kappa]; /* ************************ */ /* Step7: Update B and appB */ /* ************************ */ Btmp = B->rows[kappa2]; for (i = kappa2; i > kappa; i--) B->rows[i] = B->rows[i - 1]; B->rows[kappa] = Btmp; if (U != NULL) { Btmp = _fmpz_vec_init(U->c); _fmpz_vec_set(Btmp, U->rows[kappa2], U->c); for (i = kappa2; i > kappa; i--) _fmpz_vec_set(U->rows[i], U->rows[i - 1], U->c); _fmpz_vec_set(U->rows[kappa], Btmp, U->c); _fmpz_vec_clear(Btmp, U->c); } appBtmp = appB->rows[kappa2]; for (i = kappa2; i > kappa; i--) appB->rows[i] = appB->rows[i - 1]; appB->rows[kappa] = appBtmp; j = expo[kappa2]; for (i = kappa2; i > kappa; i--) expo[i] = expo[i - 1]; expo[kappa] = j; /* *************************** */ /* Step8: Update appSP: tricky */ /* *************************** */ for (i = 0; i <= kappa2; i++) appSPtmp[i] = d_mat_entry(A->appSP, kappa2, i); for (i = kappa2 + 1; i <= kappamax; i++) appSPtmp[i] = d_mat_entry(A->appSP, i, kappa2); for (i = kappa2; i > kappa; i--) { for (j = 0; j < kappa; j++) d_mat_entry(A->appSP, i, j) = d_mat_entry(A->appSP, i - 1, j); d_mat_entry(A->appSP, i, kappa) = appSPtmp[i - 1]; for (j = kappa + 1; j <= i; j++) d_mat_entry(A->appSP, i, j) = d_mat_entry(A->appSP, i - 1, j - 1); for (j = kappa2 + 1; j <= kappamax; j++) d_mat_entry(A->appSP, j, i) = d_mat_entry(A->appSP, j, i - 1); } for (i = 0; i < kappa; i++) d_mat_entry(A->appSP, kappa, i) = appSPtmp[i]; d_mat_entry(A->appSP, kappa, kappa) = appSPtmp[kappa2]; for (i = kappa2 + 1; i <= kappamax; i++) d_mat_entry(A->appSP, i, kappa) = appSPtmp[i]; if (d_mat_entry(r, kappa, kappa) <= 0.0) { zeros++; kappa++; d_mat_entry(A->appSP, kappa, kappa) = _d_vec_norm(appB->rows[kappa], n); d_mat_entry(r, kappa, kappa) = d_mat_entry(A->appSP, kappa, kappa); } kappa++; } } #if TYPE if (gs_B != NULL) { newd = d; fmpz_init(rii); for (i = d - 1; (i >= 0) && (ok > 0); i--) { /* rii is the G-S length of ith vector divided by 2 */ fmpz_set_d_2exp(rii, d_mat_entry(r, i, i), 2 * expo[i] - 1); if ((ok = fmpz_cmp(rii, gs_B)) > 0) { newd--; } } fmpz_clear(rii); } #endif flint_free(alpha); flint_free(expo); d_mat_clear(mu); d_mat_clear(r); d_mat_clear(appB); d_mat_clear(A->appSP); _d_vec_clear(s); _d_vec_clear(appSPtmp); if (kappa < d) return -1; } else { int kappa, kappa2, d, n, i, j, zeros, kappamax, update_b = 1; slong exp; int num_failed_fast = 0; int babai_ok = 0; int heuristic_fail = 0; d_mat_t mu, r; fmpz_gram_t A; double *s, *mutmp; double ctt; int *alpha; fmpz *Btmp; ulong max_exp, iter, max_iter; n = B->c; d = B->r; ctt = (fl->delta + 1) / 2; alpha = (int *) flint_malloc(d * sizeof(int)); expo = (int *) flint_malloc(d * sizeof(int)); d_mat_init(mu, d, d); d_mat_init(r, d, d); if (fl->rt == Z_BASIS) { fmpz_mat_init(A->exactSP, d, d); } s = _d_vec_init(d); if (U != NULL) { if (U->r != d) { flint_throw(FLINT_ERROR, "(fmpz_lll_d*): Incompatible dimensions of capturing matrix.\n"); } else if (U->c == d && n > d && fmpz_mat_is_one(U)) { update_b = 0; } } if (fl->rt == Z_BASIS) { fmpz_mat_gram(A->exactSP, B); } /* ************************** */ /* Step1: Initialization Step */ /* ************************** */ max_exp = 0; for (i = 0; i < d; i++) { fmpz_get_d_2exp(&exp, fmpz_mat_entry(GM, i, i)); max_exp = FLINT_MAX(max_exp, (expo[i] = exp)); } max_iter = (ulong) ((d - 1) + (d - 1) * d * max_exp / d_log2(8 / (fl->delta + 7))); /* ********************************* */ /* Step2: Initializing the main loop */ /* ********************************* */ kappamax = 0; i = 0; do ; while ((fmpz_cmp_ui(fmpz_mat_entry(GM, i, i), 0) <= 0) && (++i < d)); zeros = i - 1; /* all vectors B[i] with i <= zeros are zero vectors */ kappa = i + 1; kappamax = kappa; if (zeros < d - 1) { d_mat_entry(r, i, i) = fmpz_get_d_2exp(&exp, fmpz_mat_entry(GM, i, i)); d_mat_entry(r, i, i) = d_mul_2exp(d_mat_entry(r, i, i), exp - expo[i]); } for (i = zeros + 1; i < d; i++) alpha[i] = 0; iter = 0; while (kappa < d) { double tmp = 0.0; if (iter >= max_iter) { break; } iter++; if (kappa > kappamax) { kappamax = kappa; } /* ********************************** */ /* Step3: Call to the Babai algorithm */ /* ********************************** */ if (num_failed_fast < 50) { babai_ok = fmpz_lll_check_babai(kappa, (update_b ? B : NULL), U, mu, r, s, NULL, expo, A, alpha[kappa], zeros, kappamax, n, fl); } else { babai_ok = -1; } if (babai_ok == -1) { num_failed_fast++; heuristic_fail = fmpz_lll_check_babai_heuristic_d(kappa, (update_b ? B : NULL), U, mu, r, s, NULL, expo, A, alpha[kappa], zeros, kappamax, n, fl); } if (heuristic_fail == -1) { flint_free(alpha); flint_free(expo); d_mat_clear(mu); d_mat_clear(r); if (fl->rt == Z_BASIS) { fmpz_mat_clear(A->exactSP); } _d_vec_clear(s); /* Need to switch to mpf / arb */ return -1; } /* ************************************ */ /* Step4: Success of Lovasz's condition */ /* ************************************ */ tmp = d_mat_entry(r, kappa - 1, kappa - 1) * ctt; tmp = d_mul_2exp(tmp, (expo[kappa - 1] - expo[kappa])); if (tmp <= s[kappa - 1]) { alpha[kappa] = kappa; tmp = d_mul_2exp(d_mat_entry(mu, kappa, kappa - 1) * d_mat_entry(r, kappa, kappa - 1), (expo[kappa] - expo[kappa - 1])); d_mat_entry(r, kappa, kappa) = s[kappa - 1] - tmp; kappa++; } else { /* ******************************************* */ /* Step5: Find the right insertion index kappa */ /* kappa2 remains the initial kappa */ /* ******************************************* */ kappa2 = kappa; #if TYPE if (kappa == d - 1 && gs_B != NULL) { fmpz_init(rii); tmp = d_mul_2exp(2 * d_mat_entry(mu, kappa, kappa - 1) * d_mat_entry(r, kappa, kappa - 1), (expo[kappa] - expo[kappa - 1])); fmpz_set_d(rii, d_mul_2exp(s[kappa - 1] - tmp, expo[kappa])); /* using a heuristic lower bound on the final GS norm */ if (fmpz_cmp(rii, gs_B) > 0) { d--; } fmpz_clear(rii); if (kappa >= d) { break; } } #endif do { kappa--; if (kappa > zeros + 1) { tmp = d_mat_entry(r, kappa - 1, kappa - 1) * ctt; tmp = d_mul_2exp(tmp, (expo[kappa - 1] - expo[kappa2])); } } while ((kappa >= zeros + 2) && (s[kappa - 1] <= tmp)); for (i = kappa; i < kappa2; i++) if (kappa <= alpha[i]) alpha[i] = kappa; for (i = kappa2; i > kappa; i--) alpha[i] = alpha[i - 1]; for (i = kappa2 + 1; i <= kappamax; i++) if (kappa < alpha[i]) alpha[i] = kappa; alpha[kappa] = kappa; /* ****************************** */ /* Step6: Update the mu's and r's */ /* ****************************** */ mutmp = mu->rows[kappa2]; for (i = kappa2; i > kappa; i--) mu->rows[i] = mu->rows[i - 1]; mu->rows[kappa] = mutmp; mutmp = r->rows[kappa2]; for (i = kappa2; i > kappa; i--) r->rows[i] = r->rows[i - 1]; r->rows[kappa] = mutmp; d_mat_entry(r, kappa, kappa) = s[kappa]; /* *************** */ /* Step7: Update B */ /* *************** */ if (fl->rt == Z_BASIS && update_b) { Btmp = B->rows[kappa2]; for (i = kappa2; i > kappa; i--) B->rows[i] = B->rows[i - 1]; B->rows[kappa] = Btmp; } if (U != NULL) { Btmp = _fmpz_vec_init(U->c); _fmpz_vec_set(Btmp, U->rows[kappa2], U->c); for (i = kappa2; i > kappa; i--) _fmpz_vec_set(U->rows[i], U->rows[i - 1], U->c); _fmpz_vec_set(U->rows[kappa], Btmp, U->c); _fmpz_vec_clear(Btmp, U->c); } j = expo[kappa2]; for (i = kappa2; i > kappa; i--) expo[i] = expo[i - 1]; expo[kappa] = j; /* ********************* */ /* Step8: Update exactSP */ /* ********************* */ for (j = kappa2; j > kappa; j--) { for (i = kappa2; i < d; i++) fmpz_swap(fmpz_mat_entry(GM, i, j), fmpz_mat_entry(GM, i, j - 1)); for (i = 0; i < kappa; i++) fmpz_swap(fmpz_mat_entry(GM, j, i), fmpz_mat_entry(GM, j - 1, i)); } for (j = kappa2; j > kappa; j--) { for (i = j; i > kappa; i--) fmpz_swap(fmpz_mat_entry(GM, j, i), fmpz_mat_entry(GM, j - 1, i - 1)); } for (j = 0; 2 * j < kappa2 - kappa; j++) fmpz_swap(fmpz_mat_entry(GM, kappa + j, kappa), fmpz_mat_entry(GM, kappa2 - j, kappa)); if (d_mat_entry(r, kappa, kappa) <= 0.0) { zeros++; kappa++; d_mat_entry(r, kappa, kappa) = fmpz_get_d_2exp(&exp, fmpz_mat_entry (GM, kappa, kappa)); d_mat_entry(r, kappa, kappa) = d_mul_2exp(d_mat_entry(r, kappa, kappa), exp - expo[kappa]); } kappa++; } } if (fl->rt == GRAM) { for (i = 0; i < B->r - 1; i++) { for (j = i + 1; j < B->r; j++) { fmpz_set(fmpz_mat_entry(B, i, j), fmpz_mat_entry(B, j, i)); } } } else if (!update_b) { fmpz_mat_mul(B, U, B); } #if TYPE if (gs_B != NULL) { newd = d; fmpz_init(rii); for (i = d - 1; (i >= 0) && (ok > 0); i--) { /* rii is the G-S length of ith vector divided by 2 */ fmpz_set_d(rii, d_mul_2exp(d_mat_entry(r, i, i), expo[i] - 1)); if ((ok = fmpz_cmp(rii, gs_B)) > 0) { newd--; } } fmpz_clear(rii); } #endif flint_free(alpha); flint_free(expo); d_mat_clear(mu); d_mat_clear(r); if (fl->rt == Z_BASIS) { fmpz_mat_clear(A->exactSP); } _d_vec_clear(s); if (kappa < d) return -1; } return newd; } #undef GM #endif flint-3.1.3/src/fmpz_lll/heuristic_dot.c000066400000000000000000000023271461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_lll.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp #else # include #endif double fmpz_lll_heuristic_dot(const double *vec1, const double *vec2, slong len2, const fmpz_mat_t B, slong k, slong j, slong exp_adj) { double sum = _d_vec_dot(vec1, vec2, len2); double tmp = _d_vec_norm(vec1, len2); double tmp2 = _d_vec_norm(vec2, len2); tmp = tmp*tmp2 * ldexp(1.0, -70); tmp2 = sum*sum; if (tmp2 <= tmp) { slong exp; fmpz_t sp; fmpz_init(sp); _fmpz_vec_dot(sp, B->rows[k], B->rows[j], len2); sum = fmpz_get_d_2exp(&exp, sp); sum = ldexp(sum, sum - exp_adj); fmpz_clear(sp); } return sum; } flint-3.1.3/src/fmpz_lll/is_reduced.c000066400000000000000000000031631461254215100175160ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz_lll.h" int fmpz_lll_is_reduced(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) { if (fl->rt == Z_BASIS) { /* The is_reduced checkers below could only return 1 when B has full row rank. Therefore, the definition of fmpz_lll_is_reduced needs to include a stripping out of *initial* zero rows followed by a call to one of these checkers. */ int res; fmpz_mat_t BB; _fmpz_mat_window_readonly_init_strip_initial_zero_rows(BB, B); if (fmpz_lll_is_reduced_d(BB, fl)) { res = 1; } else if (fmpz_lll_is_reduced_mpfr(BB, fl, prec)) { res = 1; } else { res = fmpz_mat_is_reduced(BB, fl->delta, fl->eta); } _fmpz_mat_window_readonly_clear(BB); return res; } else { if (fmpz_lll_is_reduced_d(B, fl)) return 1; if (fmpz_lll_is_reduced_mpfr(B, fl, prec)) return 1; return fmpz_mat_is_reduced_gram(B, fl->delta, fl->eta); } } flint-3.1.3/src/fmpz_lll/is_reduced_d.c000066400000000000000000000573701461254215100200320ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #if HAVE_FENV_H #include #endif #ifdef __GNUC__ # define fabs __builtin_fabs # define sqrt __builtin_sqrt #else # include #endif int fmpz_lll_is_reduced_d(const fmpz_mat_t B, const fmpz_lll_t fl) { #if HAVE_FENV_H d_mat_t A, R, V, Wu, Wd, bound; double * du, * dd; int rounding_direction = fegetround(); if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; d_mat_t Q, bound2, bound3, boundt, mm, rm, mn, rn, absR; double s, norm = 0, ti, tj; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; d_mat_init(A, m, n); d_mat_init(Q, m, n); d_mat_init(R, n, n); d_mat_init(V, n, n); d_mat_zero(R); d_mat_zero(V); if (fmpz_mat_get_d_mat_transpose(A, B) == -1) { d_mat_clear(Q); goto fail_clear_A_R_V; } for (k = 0; k < n; k++) { for (j = 0; j < m; j++) { d_mat_entry(Q, j, k) = d_mat_entry(A, j, k); } for (i = 0; i < k; i++) { s = 0; for (j = 0; j < m; j++) { s += d_mat_entry(Q, j, i) * d_mat_entry(Q, j, k); } d_mat_entry(R, i, k) = s; for (j = 0; j < m; j++) { d_mat_entry(Q, j, k) -= s * d_mat_entry(Q, j, i); } } s = 0; for (j = 0; j < m; j++) { s += d_mat_entry(Q, j, k) * d_mat_entry(Q, j, k); } d_mat_entry(R, k, k) = s = sqrt(s); if (s != 0) { s = 1 / s; for (j = 0; j < m; j++) { d_mat_entry(Q, j, k) *= s; } } } d_mat_clear(Q); for (j = n - 1; j >= 0; j--) { d_mat_entry(V, j, j) = 1.0 / d_mat_entry(R, j, j); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { d_mat_entry(V, j, i) += d_mat_entry(V, k, i) * d_mat_entry(R, j, k); } d_mat_entry(V, j, i) *= -d_mat_entry(V, j, j); } } d_mat_init(Wu, n, n); d_mat_init(Wd, n, n); du = _d_vec_init(n); dd = _d_vec_init(n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, R, V); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, R, V); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 1; } for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { if (i != j) s += FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); else s += FLINT_MAX(fabs(dd[i]), fabs(du[i])); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) goto fail_clear_all; d_mat_init(bound, n, n); fesetround(FE_DOWNWARD); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 2; } fesetround(FE_UPWARD); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 2; } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))) + norm * norm / (1.0 - norm); } else if (j < i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); } else { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(dd[i]), fabs(du[i])) + norm * norm / (1.0 - norm); } } } _d_vec_clear(dd); _d_vec_clear(du); d_mat_init(mm, n, n); d_mat_init(rm, n, n); d_mat_init(mn, n, n); d_mat_init(rn, n, n); d_mat_init(bound2, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(mm, j, i) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rm, j, i) = d_mat_entry(mm, j, i) - d_mat_entry(Wd, i, j); d_mat_entry(mn, i, j) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rn, i, j) = d_mat_entry(mn, i, j) - d_mat_entry(Wd, i, j); } } fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wd, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wu, i, i) -= 1; for (j = 0; j < n; j++) { d_mat_entry(Wu, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); d_mat_entry(mm, i, j) = fabs(d_mat_entry(mm, i, j)); d_mat_entry(mn, i, j) = fabs(d_mat_entry(mn, i, j)); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = d_mat_entry(mn, i, j) + d_mat_entry(rn, i, j); } } d_mat_mul_classical(bound2, rm, bound2); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_mul_classical(Wu, mm, rn); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_clear(Wu); d_mat_clear(Wd); d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(Wu, m, n); d_mat_init(Wd, m, n); d_mat_init(mm, n, m); d_mat_init(mn, m, n); d_mat_init(rm, n, m); d_mat_init(rn, m, n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, A, V); fesetround(FE_UPWARD); d_mat_mul_classical(Wu, A, V); d_mat_clear(A); d_mat_clear(V); d_mat_init(bound3, n, n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { d_mat_entry(mm, j, i) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rm, j, i) = d_mat_entry(mm, j, i) - d_mat_entry(Wd, i, j); d_mat_entry(mn, i, j) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rn, i, j) = d_mat_entry(mn, i, j) - d_mat_entry(Wd, i, j); } } d_mat_clear(Wd); d_mat_clear(Wu); d_mat_init(Wd, n, n); d_mat_init(Wu, n, n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wd, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wu, i, i) -= 1; for (j = 0; j < m; j++) { if (j < n) { d_mat_entry(Wu, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); } d_mat_entry(mm, i, j) = fabs(d_mat_entry(mm, i, j)); } } d_mat_clear(Wd); d_mat_init(Wd, m, n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { d_mat_entry(Wd, i, j) = fabs(d_mat_entry(mn, i, j)) + d_mat_entry(rn, i, j); } } d_mat_mul_classical(bound3, rm, Wd); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound3, i, j) += d_mat_entry(Wu, i, j); } } d_mat_mul_classical(Wu, mm, rn); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound3, i, j) += d_mat_entry(Wu, i, j); } } d_mat_clear(Wu); d_mat_clear(Wd); d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(boundt, n, n); d_mat_transpose(boundt, bound); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = fabs(d_mat_entry(bound2, i, j)) + fabs(d_mat_entry(bound3, i, j)); } } d_mat_mul_classical(bound, bound2, bound); d_mat_mul_classical(bound, boundt, bound); d_mat_clear(bound2); d_mat_clear(bound3); d_mat_clear(boundt); norm = 0; for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { s += fabs(d_mat_entry(bound, i, j)); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) goto fail_clear_R_bound_rounding_direction; d_mat_init(absR, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { d_mat_entry(bound, i, j) += norm * norm / (1.0 - norm); } else { d_mat_entry(bound, i, j) = 0; } d_mat_entry(absR, i, j) = fabs(d_mat_entry(R, i, j)); } } d_mat_mul_classical(bound, bound, absR); d_mat_clear(absR); for (i = 0; i < n - 1; i++) { fesetround(FE_DOWNWARD); ti = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i)) * fl->eta; fesetround(FE_UPWARD); for (j = i + 1; j < n; j++) { tj = fabs(d_mat_entry(R, i, j)) + d_mat_entry(bound, i, j); if (!(tj <= ti)) goto fail_clear_R_bound_rounding_direction; } ti = d_mat_entry(R, i, i) + d_mat_entry(bound, i, i); fesetround(FE_DOWNWARD); tj = d_mat_entry(R, i + 1, i + 1) - d_mat_entry(bound, i + 1, i + 1); s = ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) * ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) - fl->delta; s = -s; fesetround(FE_UPWARD); s = sqrt(s) * ti; if (!(s <= tj)) goto fail_clear_R_bound_rounding_direction; } d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); } else { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; d_mat_t bound2, bound3, boundt, mm, rm, mn, rn, absR; double s, norm = 0, ti, tj; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; d_mat_init(A, m, n); d_mat_init(R, n, n); d_mat_init(V, n, n); d_mat_zero(R); d_mat_zero(V); if (fmpz_mat_get_d_mat_transpose(A, B) == -1) goto fail_clear_A_R_V; for (j = 0; j < n; j++) { d_mat_entry(R, j, j) = d_mat_entry(A, j, j); for (i = 0; i <= j - 1; i++) { d_mat_entry(R, i, j) = d_mat_entry(A, j, i); for (k = 0; k <= i - 1; k++) { d_mat_entry(R, i, j) -= d_mat_entry(R, k, i) * d_mat_entry(R, k, j); } if (d_mat_entry(R, i, i) != 0) { d_mat_entry(R, i, j) /= d_mat_entry(R, i, i); d_mat_entry(R, j, j) -= d_mat_entry(R, i, j) * d_mat_entry(R, i, j); } } if (!(d_mat_entry(R, j, j) > 0)) { /* going to take sqrt and then divide by it */ goto fail_clear_A_R_V; } d_mat_entry(R, j, j) = sqrt(d_mat_entry(R, j, j)); } for (j = n - 1; j >= 0; j--) { d_mat_entry(V, j, j) = 1.0 / d_mat_entry(R, j, j); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { d_mat_entry(V, j, i) += d_mat_entry(V, k, i) * d_mat_entry(R, j, k); } d_mat_entry(V, j, i) *= -d_mat_entry(V, j, j); } } d_mat_init(Wu, n, n); d_mat_init(Wd, n, n); du = _d_vec_init(n); dd = _d_vec_init(n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, R, V); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, R, V); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 1; } for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { if (i != j) s += FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); else s += FLINT_MAX(fabs(dd[i]), fabs(du[i])); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) { fail_clear_all: d_mat_clear(Wu); d_mat_clear(Wd); _d_vec_clear(du); _d_vec_clear(dd); fesetround(rounding_direction); fail_clear_A_R_V: d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); return 0; } d_mat_init(bound, n, n); fesetround(FE_DOWNWARD); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 2; } fesetround(FE_UPWARD); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 2; } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))) + norm * norm / (1.0 - norm); } else if (j < i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); } else { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(dd[i]), fabs(du[i])) + norm * norm / (1.0 - norm); } } } _d_vec_clear(dd); _d_vec_clear(du); d_mat_init(mm, n, n); d_mat_init(rm, n, n); d_mat_init(mn, n, n); d_mat_init(rn, n, n); d_mat_init(bound2, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(mm, j, i) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rm, j, i) = d_mat_entry(mm, j, i) - d_mat_entry(Wd, i, j); d_mat_entry(mn, i, j) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rn, i, j) = d_mat_entry(mn, i, j) - d_mat_entry(Wd, i, j); } } fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wd, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wu, i, i) -= 1; for (j = 0; j < n; j++) { d_mat_entry(Wu, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); d_mat_entry(mm, i, j) = fabs(d_mat_entry(mm, i, j)); d_mat_entry(mn, i, j) = fabs(d_mat_entry(mn, i, j)); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = d_mat_entry(mn, i, j) + d_mat_entry(rn, i, j); } } d_mat_mul_classical(bound2, rm, bound2); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_mul_classical(Wu, mm, rn); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_clear(Wu); d_mat_clear(Wd); d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(Wu, m, n); d_mat_init(Wd, m, n); d_mat_init(mm, n, m); d_mat_init(mn, m, n); d_mat_init(rm, n, m); d_mat_init(rn, m, n); d_mat_transpose(mm, V); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, A); fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, A); d_mat_clear(A); d_mat_init(bound3, n, n); fesetround(FE_DOWNWARD); d_mat_mul_classical(mm, Wd, V); for (i = 0; i < n; i++) { d_mat_entry(mm, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(rm, Wd, V); for (i = 0; i < n; i++) { d_mat_entry(rm, i, i) -= 1; } fesetround(FE_DOWNWARD); d_mat_mul_classical(mn, Wu, V); for (i = 0; i < n; i++) { d_mat_entry(mn, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(rn, Wu, V); for (i = 0; i < n; i++) { d_mat_entry(rn, i, i) -= 1; } d_mat_clear(Wd); d_mat_clear(Wu); d_mat_clear(V); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound3, i, j) = FLINT_MAX(fabs(d_mat_entry(mm, i, j)), fabs(d_mat_entry(mn, i, j))); d_mat_entry(bound3, i, j) = FLINT_MAX(fabs(d_mat_entry(bound3, i, j)), fabs(d_mat_entry(rm, i, j))); d_mat_entry(bound3, i, j) = FLINT_MAX(fabs(d_mat_entry(bound3, i, j)), fabs(d_mat_entry(rn, i, j))); } } d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(boundt, n, n); d_mat_transpose(boundt, bound); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = fabs(d_mat_entry(bound2, i, j)) + fabs(d_mat_entry(bound3, i, j)); } } d_mat_mul_classical(bound, bound2, bound); d_mat_mul_classical(bound, boundt, bound); d_mat_clear(bound2); d_mat_clear(bound3); d_mat_clear(boundt); norm = 0; for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { s += fabs(d_mat_entry(bound, i, j)); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) goto fail_clear_R_bound_rounding_direction; d_mat_init(absR, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { d_mat_entry(bound, i, j) += norm * norm / (1.0 - norm); } else { d_mat_entry(bound, i, j) = 0; } d_mat_entry(absR, i, j) = fabs(d_mat_entry(R, i, j)); } } d_mat_mul_classical(bound, bound, absR); d_mat_clear(absR); for (i = 0; i < n - 1; i++) { fesetround(FE_DOWNWARD); ti = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i)) * fl->eta; fesetround(FE_UPWARD); for (j = i + 1; j < n; j++) { tj = fabs(d_mat_entry(R, i, j)) + d_mat_entry(bound, i, j); if (!(tj <= ti)) goto fail_clear_R_bound_rounding_direction; } ti = d_mat_entry(R, i, i) + d_mat_entry(bound, i, i); fesetround(FE_DOWNWARD); tj = d_mat_entry(R, i + 1, i + 1) - d_mat_entry(bound, i + 1, i + 1); s = ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) * ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) - fl->delta; s = -s; fesetround(FE_UPWARD); s = sqrt(s) * ti; if (!(s <= tj)) { fail_clear_R_bound_rounding_direction: d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); } FLINT_ASSERT((fl->rt == Z_BASIS ? fmpz_mat_is_reduced(B, fl->delta, fl->eta) : fmpz_mat_is_reduced_gram(B, fl->delta, fl->eta))); return 1; #else return 0; #endif } flint-3.1.3/src/fmpz_lll/is_reduced_d_with_removal.c000066400000000000000000000611551461254215100226060ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "d_vec.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #if HAVE_FENV_H #include #endif #ifdef __GNUC__ # define fabs __builtin_fabs # define sqrt __builtin_sqrt #else # include #endif int fmpz_lll_is_reduced_d_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd) { #if HAVE_FENV_H d_mat_t A, R, V, Wu, Wd, bound; double * du, * dd; int rounding_direction = fegetround(); if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; d_mat_t Q, bound2, bound3, boundt, mm, rm, mn, rn, absR; double s, norm = 0, ti, tj, d_gs_B; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; d_mat_init(A, m, n); d_mat_init(Q, m, n); d_mat_init(R, n, n); d_mat_init(V, n, n); d_mat_zero(R); d_mat_zero(V); if (fmpz_mat_get_d_mat_transpose(A, B) == -1) { d_mat_clear(Q); goto fail_clear_A_R_V; } d_gs_B = fmpz_get_d(gs_B); for (k = 0; k < n; k++) { for (j = 0; j < m; j++) { d_mat_entry(Q, j, k) = d_mat_entry(A, j, k); } for (i = 0; i < k; i++) { s = 0; for (j = 0; j < m; j++) { s += d_mat_entry(Q, j, i) * d_mat_entry(Q, j, k); } d_mat_entry(R, i, k) = s; for (j = 0; j < m; j++) { d_mat_entry(Q, j, k) -= s * d_mat_entry(Q, j, i); } } s = 0; for (j = 0; j < m; j++) { s += d_mat_entry(Q, j, k) * d_mat_entry(Q, j, k); } d_mat_entry(R, k, k) = s = sqrt(s); if (s != 0) { s = 1 / s; for (j = 0; j < m; j++) { d_mat_entry(Q, j, k) *= s; } } } d_mat_clear(Q); for (j = n - 1; j >= 0; j--) { d_mat_entry(V, j, j) = 1.0 / d_mat_entry(R, j, j); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { d_mat_entry(V, j, i) += d_mat_entry(V, k, i) * d_mat_entry(R, j, k); } d_mat_entry(V, j, i) *= -d_mat_entry(V, j, j); } } d_mat_init(Wu, n, n); d_mat_init(Wd, n, n); du = _d_vec_init(n); dd = _d_vec_init(n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, R, V); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, R, V); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 1; } for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { if (i != j) s += FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); else s += FLINT_MAX(fabs(dd[i]), fabs(du[i])); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) goto fail_clear_all; d_mat_init(bound, n, n); fesetround(FE_DOWNWARD); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 2; } fesetround(FE_UPWARD); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 2; } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))) + norm * norm / (1.0 - norm); } else if (j < i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); } else { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(dd[i]), fabs(du[i])) + norm * norm / (1.0 - norm); } } } _d_vec_clear(dd); _d_vec_clear(du); d_mat_init(mm, n, n); d_mat_init(rm, n, n); d_mat_init(mn, n, n); d_mat_init(rn, n, n); d_mat_init(bound2, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(mm, j, i) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rm, j, i) = d_mat_entry(mm, j, i) - d_mat_entry(Wd, i, j); d_mat_entry(mn, i, j) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rn, i, j) = d_mat_entry(mn, i, j) - d_mat_entry(Wd, i, j); } } fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wd, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wu, i, i) -= 1; for (j = 0; j < n; j++) { d_mat_entry(Wu, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); d_mat_entry(mm, i, j) = fabs(d_mat_entry(mm, i, j)); d_mat_entry(mn, i, j) = fabs(d_mat_entry(mn, i, j)); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = d_mat_entry(mn, i, j) + d_mat_entry(rn, i, j); } } d_mat_mul_classical(bound2, rm, bound2); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_mul_classical(Wu, mm, rn); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_clear(Wu); d_mat_clear(Wd); d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(Wu, m, n); d_mat_init(Wd, m, n); d_mat_init(mm, n, m); d_mat_init(mn, m, n); d_mat_init(rm, n, m); d_mat_init(rn, m, n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, A, V); fesetround(FE_UPWARD); d_mat_mul_classical(Wu, A, V); d_mat_clear(A); d_mat_clear(V); d_mat_init(bound3, n, n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { d_mat_entry(mm, j, i) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rm, j, i) = d_mat_entry(mm, j, i) - d_mat_entry(Wd, i, j); d_mat_entry(mn, i, j) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rn, i, j) = d_mat_entry(mn, i, j) - d_mat_entry(Wd, i, j); } } d_mat_clear(Wd); d_mat_clear(Wu); d_mat_init(Wd, n, n); d_mat_init(Wu, n, n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wd, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wu, i, i) -= 1; for (j = 0; j < m; j++) { if (j < n) { d_mat_entry(Wu, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); } d_mat_entry(mm, i, j) = fabs(d_mat_entry(mm, i, j)); } } d_mat_clear(Wd); d_mat_init(Wd, m, n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { d_mat_entry(Wd, i, j) = fabs(d_mat_entry(mn, i, j)) + d_mat_entry(rn, i, j); } } d_mat_mul_classical(bound3, rm, Wd); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound3, i, j) += d_mat_entry(Wu, i, j); } } d_mat_mul_classical(Wu, mm, rn); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound3, i, j) += d_mat_entry(Wu, i, j); } } d_mat_clear(Wu); d_mat_clear(Wd); d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(boundt, n, n); d_mat_transpose(boundt, bound); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = fabs(d_mat_entry(bound2, i, j)) + fabs(d_mat_entry(bound3, i, j)); } } d_mat_mul_classical(bound, bound2, bound); d_mat_mul_classical(bound, boundt, bound); d_mat_clear(bound2); d_mat_clear(bound3); d_mat_clear(boundt); norm = 0; for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { s += fabs(d_mat_entry(bound, i, j)); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) goto fail_clear_R_bound_rounding_direction; d_mat_init(absR, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { d_mat_entry(bound, i, j) += norm * norm / (1.0 - norm); } else { d_mat_entry(bound, i, j) = 0; } d_mat_entry(absR, i, j) = fabs(d_mat_entry(R, i, j)); } } d_mat_mul_classical(bound, bound, absR); d_mat_clear(absR); for (i = 0; i < n - 1; i++) { fesetround(FE_DOWNWARD); ti = (s = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i))) * fl->eta; if (i >= newd && !(s*s >= d_gs_B)) goto fail_clear_R_bound_rounding_direction; fesetround(FE_UPWARD); for (j = i + 1; j < n; j++) { tj = fabs(d_mat_entry(R, i, j)) + d_mat_entry(bound, i, j); if (i < newd && !(tj <= ti)) goto fail_clear_R_bound_rounding_direction; } ti = d_mat_entry(R, i, i) + d_mat_entry(bound, i, i); fesetround(FE_DOWNWARD); tj = d_mat_entry(R, i + 1, i + 1) - d_mat_entry(bound, i + 1, i + 1); s = ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) * ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) - fl->delta; s = -s; fesetround(FE_UPWARD); s = sqrt(s) * ti; if (i < newd && !(s <= tj)) goto fail_clear_R_bound_rounding_direction; } fesetround(FE_DOWNWARD); s = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i)); if (i >= newd && !(s*s >= d_gs_B)) goto fail_clear_R_bound_rounding_direction; d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); } else { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; d_mat_t bound2, bound3, boundt, mm, rm, mn, rn, absR; double s, norm = 0, ti, tj, d_gs_B; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; d_mat_init(A, m, n); d_mat_init(R, n, n); d_mat_init(V, n, n); d_mat_zero(R); d_mat_zero(V); if (fmpz_mat_get_d_mat_transpose(A, B) == -1) goto fail_clear_A_R_V; for (j = 0; j < n; j++) { d_mat_entry(R, j, j) = d_mat_entry(A, j, j); for (i = 0; i <= j - 1; i++) { d_mat_entry(R, i, j) = d_mat_entry(A, j, i); for (k = 0; k <= i - 1; k++) { d_mat_entry(R, i, j) -= d_mat_entry(R, k, i) * d_mat_entry(R, k, j); } if (d_mat_entry(R, i, i) != 0) { d_mat_entry(R, i, j) /= d_mat_entry(R, i, i); d_mat_entry(R, j, j) -= d_mat_entry(R, i, j) * d_mat_entry(R, i, j); } } if (!(d_mat_entry(R, j, j) > 0)) { /* going to take sqrt and then divide by it */ goto fail_clear_A_R_V; } d_mat_entry(R, j, j) = sqrt(d_mat_entry(R, j, j)); } d_gs_B = fmpz_get_d(gs_B); for (j = n - 1; j >= 0; j--) { d_mat_entry(V, j, j) = 1.0 / d_mat_entry(R, j, j); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { d_mat_entry(V, j, i) += d_mat_entry(V, k, i) * d_mat_entry(R, j, k); } d_mat_entry(V, j, i) *= -d_mat_entry(V, j, j); } } d_mat_init(Wu, n, n); d_mat_init(Wd, n, n); du = _d_vec_init(n); dd = _d_vec_init(n); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, R, V); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, R, V); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 1; } for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { if (i != j) s += FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); else s += FLINT_MAX(fabs(dd[i]), fabs(du[i])); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) { fail_clear_all: d_mat_clear(Wu); d_mat_clear(Wd); _d_vec_clear(du); _d_vec_clear(dd); fesetround(rounding_direction); fail_clear_A_R_V: d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); return 0; } d_mat_init(bound, n, n); fesetround(FE_DOWNWARD); for (i = 0; i < n; i++) { dd[i] = d_mat_entry(Wd, i, i) - 2; } fesetround(FE_UPWARD); for (i = 0; i < n; i++) { du[i] = d_mat_entry(Wu, i, i) - 2; } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))) + norm * norm / (1.0 - norm); } else if (j < i) { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); } else { d_mat_entry(bound, i, j) = FLINT_MAX(fabs(dd[i]), fabs(du[i])) + norm * norm / (1.0 - norm); } } } _d_vec_clear(dd); _d_vec_clear(du); d_mat_init(mm, n, n); d_mat_init(rm, n, n); d_mat_init(mn, n, n); d_mat_init(rn, n, n); d_mat_init(bound2, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(mm, j, i) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rm, j, i) = d_mat_entry(mm, j, i) - d_mat_entry(Wd, i, j); d_mat_entry(mn, i, j) = (d_mat_entry(Wu, i, j) + d_mat_entry(Wd, i, j)) / 2; d_mat_entry(rn, i, j) = d_mat_entry(mn, i, j) - d_mat_entry(Wd, i, j); } } fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wd, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, mn); for (i = 0; i < n; i++) { d_mat_entry(Wu, i, i) -= 1; for (j = 0; j < n; j++) { d_mat_entry(Wu, i, j) = FLINT_MAX(fabs(d_mat_entry(Wd, i, j)), fabs(d_mat_entry(Wu, i, j))); d_mat_entry(mm, i, j) = fabs(d_mat_entry(mm, i, j)); d_mat_entry(mn, i, j) = fabs(d_mat_entry(mn, i, j)); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = d_mat_entry(mn, i, j) + d_mat_entry(rn, i, j); } } d_mat_mul_classical(bound2, rm, bound2); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_mul_classical(Wu, mm, rn); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) += d_mat_entry(Wu, i, j); } } d_mat_clear(Wu); d_mat_clear(Wd); d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(Wu, m, n); d_mat_init(Wd, m, n); d_mat_init(mm, n, m); d_mat_init(mn, m, n); d_mat_init(rm, n, m); d_mat_init(rn, m, n); d_mat_transpose(mm, V); fesetround(FE_DOWNWARD); d_mat_mul_classical(Wd, mm, A); fesetround(FE_UPWARD); d_mat_mul_classical(Wu, mm, A); d_mat_clear(A); d_mat_init(bound3, n, n); fesetround(FE_DOWNWARD); d_mat_mul_classical(mm, Wd, V); for (i = 0; i < n; i++) { d_mat_entry(mm, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(rm, Wd, V); for (i = 0; i < n; i++) { d_mat_entry(rm, i, i) -= 1; } fesetround(FE_DOWNWARD); d_mat_mul_classical(mn, Wu, V); for (i = 0; i < n; i++) { d_mat_entry(mn, i, i) -= 1; } fesetround(FE_UPWARD); d_mat_mul_classical(rn, Wu, V); for (i = 0; i < n; i++) { d_mat_entry(rn, i, i) -= 1; } d_mat_clear(Wd); d_mat_clear(Wu); d_mat_clear(V); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound3, i, j) = FLINT_MAX(fabs(d_mat_entry(mm, i, j)), fabs(d_mat_entry(mn, i, j))); d_mat_entry(bound3, i, j) = FLINT_MAX(fabs(d_mat_entry(bound3, i, j)), fabs(d_mat_entry(rm, i, j))); d_mat_entry(bound3, i, j) = FLINT_MAX(fabs(d_mat_entry(bound3, i, j)), fabs(d_mat_entry(rn, i, j))); } } d_mat_clear(mm); d_mat_clear(mn); d_mat_clear(rm); d_mat_clear(rn); d_mat_init(boundt, n, n); d_mat_transpose(boundt, bound); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { d_mat_entry(bound2, i, j) = fabs(d_mat_entry(bound2, i, j)) + fabs(d_mat_entry(bound3, i, j)); } } d_mat_mul_classical(bound, bound2, bound); d_mat_mul_classical(bound, boundt, bound); d_mat_clear(bound2); d_mat_clear(bound3); d_mat_clear(boundt); norm = 0; for (i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) { s += fabs(d_mat_entry(bound, i, j)); } norm = FLINT_MAX(norm, s); } if (!(norm < 1)) goto fail_clear_R_bound_rounding_direction; d_mat_init(absR, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { d_mat_entry(bound, i, j) += norm * norm / (1.0 - norm); } else { d_mat_entry(bound, i, j) = 0; } d_mat_entry(absR, i, j) = fabs(d_mat_entry(R, i, j)); } } d_mat_mul_classical(bound, bound, absR); d_mat_clear(absR); for (i = 0; i < n - 1; i++) { fesetround(FE_DOWNWARD); ti = (s = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i))) * fl->eta; if (i >= newd && !(s*s >= d_gs_B)) goto fail_clear_R_bound_rounding_direction; fesetround(FE_UPWARD); for (j = i + 1; j < n; j++) { tj = fabs(d_mat_entry(R, i, j)) + d_mat_entry(bound, i, j); if (i < newd && !(tj <= ti)) goto fail_clear_R_bound_rounding_direction; } ti = d_mat_entry(R, i, i) + d_mat_entry(bound, i, i); fesetround(FE_DOWNWARD); tj = d_mat_entry(R, i + 1, i + 1) - d_mat_entry(bound, i + 1, i + 1); s = ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) * ((fabs(d_mat_entry(R, i, i + 1)) - d_mat_entry(bound, i, i + 1)) / ti) - fl->delta; s = -s; fesetround(FE_UPWARD); s = sqrt(s) * ti; if (i < newd && !(s <= tj)) goto fail_clear_R_bound_rounding_direction; } fesetround(FE_DOWNWARD); s = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i)); if (i >= newd && !(s*s >= d_gs_B)) { fail_clear_R_bound_rounding_direction: d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); } FLINT_ASSERT((fl->rt == Z_BASIS ? fmpz_mat_is_reduced_with_removal(B, fl->delta, fl->eta, gs_B, newd) : fmpz_mat_is_reduced_gram_with_removal(B, fl->delta, fl->eta, gs_B, newd))); return 1; #else return 0; #endif } flint-3.1.3/src/fmpz_lll/is_reduced_mpfr.c000066400000000000000000001006521461254215100205430ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpfr.h" #include "mpfr_vec.h" #include "mpfr_mat.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" int fmpz_lll_is_reduced_mpfr(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) { mpfr_mat_t A, R, V, Wu, Wd, bound; mpfr_ptr du, dd; mpfr_t s, norm, ti, tj, tmp; slong n; if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m; mpfr_mat_t Q, bound2, bound3, boundt, mm, rm, mn, rn, absR; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; mpfr_mat_init(A, m, n, prec); mpfr_mat_init(Q, m, n, prec); mpfr_mat_init(R, n, n, prec); mpfr_mat_init(V, n, n, prec); mpfr_mat_zero(R); mpfr_mat_zero(V); mpfr_inits2(prec, s, norm, ti, tj, tmp, NULL); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { fmpz_get_mpfr(mpfr_mat_entry(A, j, i), fmpz_mat_entry(B, i, j), MPFR_RNDN); } } for (k = 0; k < n; k++) { for (j = 0; j < m; j++) { mpfr_set(mpfr_mat_entry(Q, j, k), mpfr_mat_entry(A, j, k), MPFR_RNDN); } for (i = 0; i < k; i++) { mpfr_set_zero(s, 1); for (j = 0; j < m; j++) { mpfr_mul(norm, mpfr_mat_entry(Q, j, i), mpfr_mat_entry(Q, j, k), MPFR_RNDN); mpfr_add(s, s, norm, MPFR_RNDN); } mpfr_set(mpfr_mat_entry(R, i, k), s, MPFR_RNDN); for (j = 0; j < m; j++) { mpfr_mul(norm, s, mpfr_mat_entry(Q, j, i), MPFR_RNDN); mpfr_sub(mpfr_mat_entry(Q, j, k), mpfr_mat_entry(Q, j, k), norm, MPFR_RNDN); } } mpfr_set_zero(s, 1); for (j = 0; j < m; j++) { mpfr_mul(norm, mpfr_mat_entry(Q, j, k), mpfr_mat_entry(Q, j, k), MPFR_RNDN); mpfr_add(s, s, norm, MPFR_RNDN); } mpfr_sqrt(s, s, MPFR_RNDN); mpfr_set(mpfr_mat_entry(R, k, k), s, MPFR_RNDN); if (!mpfr_zero_p(s)) { mpfr_ui_div(s, 1, s, MPFR_RNDN); for (j = 0; j < m; j++) { mpfr_mul(mpfr_mat_entry(Q, j, k), mpfr_mat_entry(Q, j, k), s, MPFR_RNDN); } } } mpfr_mat_clear(Q); for (j = n - 1; j >= 0; j--) { mpfr_ui_div(mpfr_mat_entry(V, j, j), 1, mpfr_mat_entry(R, j, j), MPFR_RNDN); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { mpfr_mul(norm, mpfr_mat_entry(V, k, i), mpfr_mat_entry(R, j, k), MPFR_RNDN); mpfr_add(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), norm, MPFR_RNDN); } mpfr_mul_si(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), -WORD(1), MPFR_RNDN); mpfr_mul(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, j), MPFR_RNDN); } } mpfr_mat_init(Wu, n, n, prec); mpfr_mat_init(Wd, n, n, prec); du = _mpfr_vec_init(n, prec); dd = _mpfr_vec_init(n, prec); mpfr_mat_mul_classical(Wd, R, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, R, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); } mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { if (i != j) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) goto fail_clear_all; mpfr_mat_init(bound, n, n, prec); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 2, MPFR_RNDD); } for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 2, MPFR_RNDU); } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else if (j < i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } } } _mpfr_vec_clear(dd, n); _mpfr_vec_clear(du, n); mpfr_mat_init(mm, n, n, prec); mpfr_mat_init(rm, n, n, prec); mpfr_mat_init(mn, n, n, prec); mpfr_mat_init(rn, n, n, prec); mpfr_mat_init(bound2, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(tmp, mpfr_mat_entry(Wu, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mm, j, i), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rm, j, i), mpfr_mat_entry(mm, j, i), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mn, i, j), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rn, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wd, mm, mn, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wd, i, i), mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, mm, mn, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wu, i, i), mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); for (j = 0; j < n; j++) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(Wu, i, j), ti, tj, MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mm, i, j), mpfr_mat_entry(mm, i, j), MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mn, i, j), mpfr_mat_entry(mn, i, j), MPFR_RNDU); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(rn, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound2, rm, bound2, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wu, mm, rn, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(Wu, m, n, prec); mpfr_mat_init(Wd, m, n, prec); mpfr_mat_init(mm, n, m, prec); mpfr_mat_init(mn, m, n, prec); mpfr_mat_init(rm, n, m, prec); mpfr_mat_init(rn, m, n, prec); mpfr_mat_mul_classical(Wd, A, V, MPFR_RNDD); mpfr_mat_mul_classical(Wu, A, V, MPFR_RNDU); mpfr_mat_clear(A); mpfr_mat_clear(V); mpfr_mat_init(bound3, n, n, prec); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { mpfr_add(tmp, mpfr_mat_entry(Wu, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mm, j, i), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rm, j, i), mpfr_mat_entry(mm, j, i), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mn, i, j), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rn, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wd); mpfr_mat_clear(Wu); mpfr_mat_init(Wd, n, n, prec); mpfr_mat_init(Wu, n, n, prec); mpfr_mat_mul_classical(Wd, mm, mn, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wd, i, i), mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, mm, mn, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wu, i, i), mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); for (j = 0; j < m; j++) { if (j < n) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(Wu, i, j), ti, tj, MPFR_RNDU); } mpfr_abs(mpfr_mat_entry(mm, i, j), mpfr_mat_entry(mm, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wd); mpfr_mat_init(Wd, m, n, prec); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { mpfr_abs(mpfr_mat_entry(mn, i, j), mpfr_mat_entry(mn, i, j), MPFR_RNDU); mpfr_add(mpfr_mat_entry(Wd, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(rn, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound3, rm, Wd, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wu, mm, rn, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(boundt, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(boundt, j, i), mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_set(ti, mpfr_mat_entry(bound2, i, j), MPFR_RNDU); mpfr_set(tj, mpfr_mat_entry(bound3, i, j), MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound2, i, j), ti, tj, MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound2, bound, MPFR_RNDU); mpfr_mat_mul_classical(bound, boundt, bound, MPFR_RNDU); mpfr_mat_clear(bound2); mpfr_mat_clear(bound3); mpfr_mat_clear(boundt); mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) goto fail_clear_R_bound_bla; mpfr_mat_init(absR, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else { mpfr_set_zero(mpfr_mat_entry(bound, i, j), 1); } mpfr_abs(mpfr_mat_entry(absR, i, j), mpfr_mat_entry(R, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound, absR, MPFR_RNDU); mpfr_mat_clear(absR); for (i = 0; i < n - 1; i++) { mpfr_sub(tmp, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDD); mpfr_mul_d(ti, tmp, fl->eta, MPFR_RNDD); for (j = i + 1; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(R, i, j), MPFR_RNDU); mpfr_add(tj, tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); if (!mpfr_lessequal_p(tj, ti)) goto fail_clear_R_bound_bla; } mpfr_add(ti, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDU); mpfr_sub(tj, mpfr_mat_entry(R, i + 1, i + 1), mpfr_mat_entry(bound, i + 1, i + 1), MPFR_RNDD); mpfr_abs(tmp, mpfr_mat_entry(R, i, i + 1), MPFR_RNDD); mpfr_sub(norm, tmp, mpfr_mat_entry(bound, i, i + 1), MPFR_RNDD); mpfr_div(tmp, norm, ti, MPFR_RNDD); mpfr_sqr(norm, tmp, MPFR_RNDD); mpfr_sub_d(s, norm, fl->delta, MPFR_RNDD); mpfr_neg(s, s, MPFR_RNDD); mpfr_sqrt(tmp, s, MPFR_RNDU); mpfr_mul(s, tmp, ti, MPFR_RNDU); if (!mpfr_lessequal_p(s, tj)) goto fail_clear_R_bound_bla; } mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); } else { slong i, j, k, m; mpfr_mat_t bound2, bound3, boundt, mm, rm, mn, rn, absR; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; mpfr_mat_init(A, m, n, prec); mpfr_mat_init(R, n, n, prec); mpfr_mat_init(V, n, n, prec); mpfr_mat_zero(R); mpfr_mat_zero(V); mpfr_inits2(prec, s, norm, ti, tj, tmp, NULL); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { fmpz_get_mpfr(mpfr_mat_entry(A, j, i), fmpz_mat_entry(B, i, j), MPFR_RNDN); } } for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(R, j, j), mpfr_mat_entry(A, j, j), MPFR_RNDN); for (i = 0; i <= j - 1; i++) { mpfr_set(mpfr_mat_entry(R, i, j), mpfr_mat_entry(A, j, i), MPFR_RNDN); for (k = 0; k <= i - 1; k++) { mpfr_mul(tmp, mpfr_mat_entry(R, k, i), mpfr_mat_entry(R, k, j), MPFR_RNDN); mpfr_sub(mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, j), tmp, MPFR_RNDN); } if (!mpfr_zero_p(mpfr_mat_entry(R, i, i))) { mpfr_div(mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, i), MPFR_RNDN); mpfr_mul(tmp, mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, j), MPFR_RNDN); mpfr_sub(mpfr_mat_entry(R, j, j), mpfr_mat_entry(R, j, j), tmp, MPFR_RNDN); } } if (mpfr_sgn(mpfr_mat_entry(R, j, j)) <= 0) { /* going to take sqrt and then divide by it */ goto fail_clear_A_R_V; } mpfr_sqrt(mpfr_mat_entry(R, j, j), mpfr_mat_entry(R, j, j), MPFR_RNDN); } for (j = n - 1; j >= 0; j--) { mpfr_ui_div(mpfr_mat_entry(V, j, j), 1, mpfr_mat_entry(R, j, j), MPFR_RNDN); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { mpfr_mul(norm, mpfr_mat_entry(V, k, i), mpfr_mat_entry(R, j, k), MPFR_RNDN); mpfr_add(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), norm, MPFR_RNDN); } mpfr_mul_si(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), -WORD(1), MPFR_RNDN); mpfr_mul(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, j), MPFR_RNDN); } } mpfr_mat_init(Wu, n, n, prec); mpfr_mat_init(Wd, n, n, prec); du = _mpfr_vec_init(n, prec); dd = _mpfr_vec_init(n, prec); mpfr_mat_mul_classical(Wd, R, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, R, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); } mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { if (i != j) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) { fail_clear_all: mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); _mpfr_vec_clear(du, n); _mpfr_vec_clear(dd, n); mpfr_clears(s, norm, ti, tj, tmp, NULL); fail_clear_A_R_V: mpfr_mat_clear(A); mpfr_mat_clear(R); mpfr_mat_clear(V); return 0; } mpfr_mat_init(bound, n, n, prec); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 2, MPFR_RNDD); } for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 2, MPFR_RNDU); } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else if (j < i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } } } _mpfr_vec_clear(dd, n); _mpfr_vec_clear(du, n); mpfr_mat_init(mm, n, n, prec); mpfr_mat_init(rm, n, n, prec); mpfr_mat_init(mn, n, n, prec); mpfr_mat_init(rn, n, n, prec); mpfr_mat_init(bound2, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(tmp, mpfr_mat_entry(Wu, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mm, j, i), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rm, j, i), mpfr_mat_entry(mm, j, i), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mn, i, j), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rn, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wd, mm, mn, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wd, i, i), mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, mm, mn, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wu, i, i), mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); for (j = 0; j < n; j++) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(Wu, i, j), ti, tj, MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mm, i, j), mpfr_mat_entry(mm, i, j), MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mn, i, j), mpfr_mat_entry(mn, i, j), MPFR_RNDU); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(rn, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound2, rm, bound2, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wu, mm, rn, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(Wu, m, n, prec); mpfr_mat_init(Wd, m, n, prec); mpfr_mat_init(mm, n, m, prec); mpfr_mat_init(mn, m, n, prec); mpfr_mat_init(rm, n, m, prec); mpfr_mat_init(rn, m, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(mm, j, i), mpfr_mat_entry(V, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wd, mm, A, MPFR_RNDD); mpfr_mat_mul_classical(Wu, mm, A, MPFR_RNDU); mpfr_mat_clear(A); mpfr_mat_init(bound3, n, n, prec); mpfr_mat_mul_classical(mm, Wd, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(mm, i, i), mpfr_mat_entry(mm, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(rm, Wd, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(rm, i, i), mpfr_mat_entry(rm, i, i), 1, MPFR_RNDU); } mpfr_mat_mul_classical(mn, Wu, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(mn, i, i), mpfr_mat_entry(mn, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(rn, Wu, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(rn, i, i), mpfr_mat_entry(rn, i, i), 1, MPFR_RNDU); } mpfr_mat_clear(Wd); mpfr_mat_clear(Wu); mpfr_mat_clear(V); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_abs(ti, mpfr_mat_entry(mm, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(mn, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound3, i, j), ti, tj, MPFR_RNDU); mpfr_abs(tmp, mpfr_mat_entry(rm, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), tmp, MPFR_RNDU); mpfr_abs(tmp, mpfr_mat_entry(rn, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), tmp, MPFR_RNDU); } } mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(boundt, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(boundt, j, i), mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_set(ti, mpfr_mat_entry(bound2, i, j), MPFR_RNDU); mpfr_set(tj, mpfr_mat_entry(bound3, i, j), MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound2, i, j), ti, tj, MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound2, bound, MPFR_RNDU); mpfr_mat_mul_classical(bound, boundt, bound, MPFR_RNDU); mpfr_mat_clear(bound2); mpfr_mat_clear(bound3); mpfr_mat_clear(boundt); mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) goto fail_clear_R_bound_bla; mpfr_mat_init(absR, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else { mpfr_set_zero(mpfr_mat_entry(bound, i, j), 1); } mpfr_abs(mpfr_mat_entry(absR, i, j), mpfr_mat_entry(R, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound, absR, MPFR_RNDU); mpfr_mat_clear(absR); for (i = 0; i < n - 1; i++) { mpfr_sub(tmp, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDD); mpfr_mul_d(ti, tmp, fl->eta, MPFR_RNDD); for (j = i + 1; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(R, i, j), MPFR_RNDU); mpfr_add(tj, tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); if (!mpfr_lessequal_p(tj, ti)) goto fail_clear_R_bound_bla; } mpfr_add(ti, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDU); mpfr_sub(tj, mpfr_mat_entry(R, i + 1, i + 1), mpfr_mat_entry(bound, i + 1, i + 1), MPFR_RNDD); mpfr_abs(tmp, mpfr_mat_entry(R, i, i + 1), MPFR_RNDD); mpfr_sub(norm, tmp, mpfr_mat_entry(bound, i, i + 1), MPFR_RNDD); mpfr_div(tmp, norm, ti, MPFR_RNDD); mpfr_sqr(norm, tmp, MPFR_RNDD); mpfr_sub_d(s, norm, fl->delta, MPFR_RNDD); mpfr_neg(s, s, MPFR_RNDD); mpfr_sqrt(tmp, s, MPFR_RNDU); mpfr_mul(s, tmp, ti, MPFR_RNDU); if (!mpfr_lessequal_p(s, tj)) { fail_clear_R_bound_bla: mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } } mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); } FLINT_ASSERT((fl->rt == Z_BASIS ? fmpz_mat_is_reduced(B, fl->delta, fl->eta) : fmpz_mat_is_reduced_gram(B, fl->delta, fl->eta))); return 1; } flint-3.1.3/src/fmpz_lll/is_reduced_mpfr_with_removal.c000066400000000000000000001032321461254215100233200ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpfr.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #include "mpfr_vec.h" #include "mpfr_mat.h" int fmpz_lll_is_reduced_mpfr_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd, flint_bitcnt_t prec) { mpfr_mat_t A, R, V, Wu, Wd, bound; mpfr_ptr du, dd; mpfr_t s, norm, ti, tj, tmp, mpfr_gs_B; slong n; if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m; mpfr_mat_t Q, bound2, bound3, boundt, mm, rm, mn, rn, absR; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; mpfr_mat_init(A, m, n, prec); mpfr_mat_init(Q, m, n, prec); mpfr_mat_init(R, n, n, prec); mpfr_mat_init(V, n, n, prec); mpfr_mat_zero(R); mpfr_mat_zero(V); mpfr_inits2(prec, s, norm, ti, tj, tmp, NULL); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { fmpz_get_mpfr(mpfr_mat_entry(A, j, i), fmpz_mat_entry(B, i, j), MPFR_RNDN); } } for (k = 0; k < n; k++) { for (j = 0; j < m; j++) { mpfr_set(mpfr_mat_entry(Q, j, k), mpfr_mat_entry(A, j, k), MPFR_RNDN); } for (i = 0; i < k; i++) { mpfr_set_zero(s, 1); for (j = 0; j < m; j++) { mpfr_mul(norm, mpfr_mat_entry(Q, j, i), mpfr_mat_entry(Q, j, k), MPFR_RNDN); mpfr_add(s, s, norm, MPFR_RNDN); } mpfr_set(mpfr_mat_entry(R, i, k), s, MPFR_RNDN); for (j = 0; j < m; j++) { mpfr_mul(norm, s, mpfr_mat_entry(Q, j, i), MPFR_RNDN); mpfr_sub(mpfr_mat_entry(Q, j, k), mpfr_mat_entry(Q, j, k), norm, MPFR_RNDN); } } mpfr_set_zero(s, 1); for (j = 0; j < m; j++) { mpfr_mul(norm, mpfr_mat_entry(Q, j, k), mpfr_mat_entry(Q, j, k), MPFR_RNDN); mpfr_add(s, s, norm, MPFR_RNDN); } mpfr_sqrt(s, s, MPFR_RNDN); mpfr_set(mpfr_mat_entry(R, k, k), s, MPFR_RNDN); if (!mpfr_zero_p(s)) { mpfr_ui_div(s, 1, s, MPFR_RNDN); for (j = 0; j < m; j++) { mpfr_mul(mpfr_mat_entry(Q, j, k), mpfr_mat_entry(Q, j, k), s, MPFR_RNDN); } } } mpfr_mat_clear(Q); for (j = n - 1; j >= 0; j--) { mpfr_ui_div(mpfr_mat_entry(V, j, j), 1, mpfr_mat_entry(R, j, j), MPFR_RNDN); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { mpfr_mul(norm, mpfr_mat_entry(V, k, i), mpfr_mat_entry(R, j, k), MPFR_RNDN); mpfr_add(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), norm, MPFR_RNDN); } mpfr_mul_si(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), -WORD(1), MPFR_RNDN); mpfr_mul(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, j), MPFR_RNDN); } } mpfr_mat_init(Wu, n, n, prec); mpfr_mat_init(Wd, n, n, prec); du = _mpfr_vec_init(n, prec); dd = _mpfr_vec_init(n, prec); mpfr_mat_mul_classical(Wd, R, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, R, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); } mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { if (i != j) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) goto fail_clear_all; mpfr_mat_init(bound, n, n, prec); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 2, MPFR_RNDD); } for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 2, MPFR_RNDU); } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else if (j < i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } } } _mpfr_vec_clear(dd, n); _mpfr_vec_clear(du, n); mpfr_mat_init(mm, n, n, prec); mpfr_mat_init(rm, n, n, prec); mpfr_mat_init(mn, n, n, prec); mpfr_mat_init(rn, n, n, prec); mpfr_mat_init(bound2, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(tmp, mpfr_mat_entry(Wu, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mm, j, i), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rm, j, i), mpfr_mat_entry(mm, j, i), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mn, i, j), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rn, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wd, mm, mn, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wd, i, i), mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, mm, mn, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wu, i, i), mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); for (j = 0; j < n; j++) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(Wu, i, j), ti, tj, MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mm, i, j), mpfr_mat_entry(mm, i, j), MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mn, i, j), mpfr_mat_entry(mn, i, j), MPFR_RNDU); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(rn, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound2, rm, bound2, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wu, mm, rn, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(Wu, m, n, prec); mpfr_mat_init(Wd, m, n, prec); mpfr_mat_init(mm, n, m, prec); mpfr_mat_init(mn, m, n, prec); mpfr_mat_init(rm, n, m, prec); mpfr_mat_init(rn, m, n, prec); mpfr_mat_mul_classical(Wd, A, V, MPFR_RNDD); mpfr_mat_mul_classical(Wu, A, V, MPFR_RNDU); mpfr_mat_clear(A); mpfr_mat_clear(V); mpfr_mat_init(bound3, n, n, prec); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { mpfr_add(tmp, mpfr_mat_entry(Wu, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mm, j, i), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rm, j, i), mpfr_mat_entry(mm, j, i), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mn, i, j), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rn, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wd); mpfr_mat_clear(Wu); mpfr_mat_init(Wd, n, n, prec); mpfr_mat_init(Wu, n, n, prec); mpfr_mat_mul_classical(Wd, mm, mn, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wd, i, i), mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, mm, mn, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wu, i, i), mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); for (j = 0; j < m; j++) { if (j < n) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(Wu, i, j), ti, tj, MPFR_RNDU); } mpfr_abs(mpfr_mat_entry(mm, i, j), mpfr_mat_entry(mm, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wd); mpfr_mat_init(Wd, m, n, prec); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { mpfr_abs(mpfr_mat_entry(mn, i, j), mpfr_mat_entry(mn, i, j), MPFR_RNDU); mpfr_add(mpfr_mat_entry(Wd, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(rn, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound3, rm, Wd, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wu, mm, rn, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(boundt, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(boundt, j, i), mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_set(ti, mpfr_mat_entry(bound2, i, j), MPFR_RNDU); mpfr_set(tj, mpfr_mat_entry(bound3, i, j), MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound2, i, j), ti, tj, MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound2, bound, MPFR_RNDU); mpfr_mat_mul_classical(bound, boundt, bound, MPFR_RNDU); mpfr_mat_clear(bound2); mpfr_mat_clear(bound3); mpfr_mat_clear(boundt); mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) goto fail_clear_R_bound_bla_some; mpfr_mat_init(absR, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else { mpfr_set_zero(mpfr_mat_entry(bound, i, j), 1); } mpfr_abs(mpfr_mat_entry(absR, i, j), mpfr_mat_entry(R, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound, absR, MPFR_RNDU); mpfr_mat_clear(absR); mpfr_init2(mpfr_gs_B, prec); fmpz_get_mpfr(mpfr_gs_B, gs_B, MPFR_RNDN); for (i = 0; i < n - 1; i++) { mpfr_sub(tmp, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDD); mpfr_mul_d(ti, tmp, fl->eta, MPFR_RNDD); mpfr_sqr(tmp, tmp, MPFR_RNDD); if (i >= newd && !mpfr_greaterequal_p(tmp, mpfr_gs_B)) goto fail_clear_R_bound_bla_all; for (j = i + 1; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(R, i, j), MPFR_RNDU); mpfr_add(tj, tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); if (i < newd && !mpfr_lessequal_p(tj, ti)) goto fail_clear_R_bound_bla_all; } mpfr_add(ti, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDU); mpfr_sub(tj, mpfr_mat_entry(R, i + 1, i + 1), mpfr_mat_entry(bound, i + 1, i + 1), MPFR_RNDD); mpfr_abs(tmp, mpfr_mat_entry(R, i, i + 1), MPFR_RNDD); mpfr_sub(norm, tmp, mpfr_mat_entry(bound, i, i + 1), MPFR_RNDD); mpfr_div(tmp, norm, ti, MPFR_RNDD); mpfr_sqr(norm, tmp, MPFR_RNDD); mpfr_sub_d(s, norm, fl->delta, MPFR_RNDD); mpfr_neg(s, s, MPFR_RNDD); mpfr_sqrt(tmp, s, MPFR_RNDU); mpfr_mul(s, tmp, ti, MPFR_RNDU); if (i < newd && !mpfr_lessequal_p(s, tj)) goto fail_clear_R_bound_bla_all; } mpfr_sub(tmp, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDD); mpfr_sqr(tmp, tmp, MPFR_RNDD); if (i >= newd && !mpfr_greaterequal_p(tmp, mpfr_gs_B)) goto fail_clear_R_bound_bla_all; mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); } else { slong i, j, k, m; mpfr_mat_t bound2, bound3, boundt, mm, rm, mn, rn, absR; if (B->r == 0 || B->r == 1) return 1; m = B->c; n = B->r; mpfr_mat_init(A, m, n, prec); mpfr_mat_init(R, n, n, prec); mpfr_mat_init(V, n, n, prec); mpfr_mat_zero(R); mpfr_mat_zero(V); mpfr_inits2(prec, s, norm, ti, tj, tmp, NULL); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { fmpz_get_mpfr(mpfr_mat_entry(A, j, i), fmpz_mat_entry(B, i, j), MPFR_RNDN); } } for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(R, j, j), mpfr_mat_entry(A, j, j), MPFR_RNDN); for (i = 0; i <= j - 1; i++) { mpfr_set(mpfr_mat_entry(R, i, j), mpfr_mat_entry(A, j, i), MPFR_RNDN); for (k = 0; k <= i - 1; k++) { mpfr_mul(tmp, mpfr_mat_entry(R, k, i), mpfr_mat_entry(R, k, j), MPFR_RNDN); mpfr_sub(mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, j), tmp, MPFR_RNDN); } if (!mpfr_zero_p(mpfr_mat_entry(R, i, i))) { mpfr_div(mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, i), MPFR_RNDN); mpfr_mul(tmp, mpfr_mat_entry(R, i, j), mpfr_mat_entry(R, i, j), MPFR_RNDN); mpfr_sub(mpfr_mat_entry(R, j, j), mpfr_mat_entry(R, j, j), tmp, MPFR_RNDN); } } if (mpfr_sgn(mpfr_mat_entry(R, j, j)) <= 0) { /* going to take sqrt and then divide by it */ goto fail_clear_A_R_V; } mpfr_sqrt(mpfr_mat_entry(R, j, j), mpfr_mat_entry(R, j, j), MPFR_RNDN); } for (j = n - 1; j >= 0; j--) { mpfr_ui_div(mpfr_mat_entry(V, j, j), 1, mpfr_mat_entry(R, j, j), MPFR_RNDN); for (i = j + 1; i < n; i++) { for (k = j + 1; k < n; k++) { mpfr_mul(norm, mpfr_mat_entry(V, k, i), mpfr_mat_entry(R, j, k), MPFR_RNDN); mpfr_add(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), norm, MPFR_RNDN); } mpfr_mul_si(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), -WORD(1), MPFR_RNDN); mpfr_mul(mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, i), mpfr_mat_entry(V, j, j), MPFR_RNDN); } } mpfr_mat_init(Wu, n, n, prec); mpfr_mat_init(Wd, n, n, prec); du = _mpfr_vec_init(n, prec); dd = _mpfr_vec_init(n, prec); mpfr_mat_mul_classical(Wd, R, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, R, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); } mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { if (i != j) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(tmp, ti, tj, MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) { fail_clear_all: mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); _mpfr_vec_clear(du, n); _mpfr_vec_clear(dd, n); mpfr_clears(s, norm, ti, tj, tmp, NULL); fail_clear_A_R_V: mpfr_mat_clear(A); mpfr_mat_clear(R); mpfr_mat_clear(V); return 0; } mpfr_mat_init(bound, n, n, prec); for (i = 0; i < n; i++) { mpfr_sub_ui(dd + i, mpfr_mat_entry(Wd, i, i), 2, MPFR_RNDD); } for (i = 0; i < n; i++) { mpfr_sub_ui(du + i, mpfr_mat_entry(Wu, i, i), 2, MPFR_RNDU); } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j > i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else if (j < i) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); } else { mpfr_abs(ti, dd + i, MPFR_RNDU); mpfr_abs(tj, du + i, MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound, i, j), ti, tj, MPFR_RNDU); mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } } } _mpfr_vec_clear(dd, n); _mpfr_vec_clear(du, n); mpfr_mat_init(mm, n, n, prec); mpfr_mat_init(rm, n, n, prec); mpfr_mat_init(mn, n, n, prec); mpfr_mat_init(rn, n, n, prec); mpfr_mat_init(bound2, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(tmp, mpfr_mat_entry(Wu, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mm, j, i), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rm, j, i), mpfr_mat_entry(mm, j, i), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_div_ui(mpfr_mat_entry(mn, i, j), tmp, 2, MPFR_RNDU); mpfr_sub(mpfr_mat_entry(rn, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(Wd, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wd, mm, mn, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wd, i, i), mpfr_mat_entry(Wd, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(Wu, mm, mn, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(Wu, i, i), mpfr_mat_entry(Wu, i, i), 1, MPFR_RNDU); for (j = 0; j < n; j++) { mpfr_abs(ti, mpfr_mat_entry(Wd, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(Wu, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(Wu, i, j), ti, tj, MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mm, i, j), mpfr_mat_entry(mm, i, j), MPFR_RNDU); mpfr_abs(mpfr_mat_entry(mn, i, j), mpfr_mat_entry(mn, i, j), MPFR_RNDU); } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(mn, i, j), mpfr_mat_entry(rn, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound2, rm, bound2, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wu, mm, rn, MPFR_RNDU); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_add(mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(bound2, i, j), mpfr_mat_entry(Wu, i, j), MPFR_RNDU); } } mpfr_mat_clear(Wu); mpfr_mat_clear(Wd); mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(Wu, m, n, prec); mpfr_mat_init(Wd, m, n, prec); mpfr_mat_init(mm, n, m, prec); mpfr_mat_init(mn, m, n, prec); mpfr_mat_init(rm, n, m, prec); mpfr_mat_init(rn, m, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(mm, j, i), mpfr_mat_entry(V, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(Wd, mm, A, MPFR_RNDD); mpfr_mat_mul_classical(Wu, mm, A, MPFR_RNDU); mpfr_mat_clear(A); mpfr_mat_init(bound3, n, n, prec); mpfr_mat_mul_classical(mm, Wd, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(mm, i, i), mpfr_mat_entry(mm, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(rm, Wd, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(rm, i, i), mpfr_mat_entry(rm, i, i), 1, MPFR_RNDU); } mpfr_mat_mul_classical(mn, Wu, V, MPFR_RNDD); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(mn, i, i), mpfr_mat_entry(mn, i, i), 1, MPFR_RNDD); } mpfr_mat_mul_classical(rn, Wu, V, MPFR_RNDU); for (i = 0; i < n; i++) { mpfr_sub_ui(mpfr_mat_entry(rn, i, i), mpfr_mat_entry(rn, i, i), 1, MPFR_RNDU); } mpfr_mat_clear(Wd); mpfr_mat_clear(Wu); mpfr_mat_clear(V); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_abs(ti, mpfr_mat_entry(mm, i, j), MPFR_RNDU); mpfr_abs(tj, mpfr_mat_entry(mn, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound3, i, j), ti, tj, MPFR_RNDU); mpfr_abs(tmp, mpfr_mat_entry(rm, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), tmp, MPFR_RNDU); mpfr_abs(tmp, mpfr_mat_entry(rn, i, j), MPFR_RNDU); mpfr_max(mpfr_mat_entry(bound3, i, j), mpfr_mat_entry(bound3, i, j), tmp, MPFR_RNDU); } } mpfr_mat_clear(mm); mpfr_mat_clear(mn); mpfr_mat_clear(rm); mpfr_mat_clear(rn); mpfr_mat_init(boundt, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { mpfr_set(mpfr_mat_entry(boundt, j, i), mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_set(ti, mpfr_mat_entry(bound2, i, j), MPFR_RNDU); mpfr_set(tj, mpfr_mat_entry(bound3, i, j), MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound2, i, j), ti, tj, MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound2, bound, MPFR_RNDU); mpfr_mat_mul_classical(bound, boundt, bound, MPFR_RNDU); mpfr_mat_clear(bound2); mpfr_mat_clear(bound3); mpfr_mat_clear(boundt); mpfr_set_zero(norm, 1); for (i = 0; i < n; i++) { mpfr_set_zero(s, 1); for (j = 0; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); mpfr_add(s, s, tmp, MPFR_RNDU); } mpfr_max(norm, norm, s, MPFR_RNDU); } if (mpfr_cmp_ui(norm, 1) >= 0) goto fail_clear_R_bound_bla_some; mpfr_mat_init(absR, n, n, prec); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j >= i) { mpfr_mul(ti, norm, norm, MPFR_RNDU); mpfr_ui_sub(tj, 1, norm, MPFR_RNDU); mpfr_div(tmp, ti, tj, MPFR_RNDU); mpfr_add(mpfr_mat_entry(bound, i, j), mpfr_mat_entry(bound, i, j), tmp, MPFR_RNDU); } else { mpfr_set_zero(mpfr_mat_entry(bound, i, j), 1); } mpfr_abs(mpfr_mat_entry(absR, i, j), mpfr_mat_entry(R, i, j), MPFR_RNDU); } } mpfr_mat_mul_classical(bound, bound, absR, MPFR_RNDU); mpfr_mat_clear(absR); mpfr_init2(mpfr_gs_B, prec); fmpz_get_mpfr(mpfr_gs_B, gs_B, MPFR_RNDN); for (i = 0; i < n - 1; i++) { mpfr_sub(tmp, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDD); mpfr_mul_d(ti, tmp, fl->eta, MPFR_RNDD); mpfr_sqr(tmp, tmp, MPFR_RNDD); if (i >= newd && !mpfr_greaterequal_p(tmp, mpfr_gs_B)) goto fail_clear_R_bound_bla_all; for (j = i + 1; j < n; j++) { mpfr_abs(tmp, mpfr_mat_entry(R, i, j), MPFR_RNDU); mpfr_add(tj, tmp, mpfr_mat_entry(bound, i, j), MPFR_RNDU); if (i < newd && !mpfr_lessequal_p(tj, ti)) goto fail_clear_R_bound_bla_all; } mpfr_add(ti, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDU); mpfr_sub(tj, mpfr_mat_entry(R, i + 1, i + 1), mpfr_mat_entry(bound, i + 1, i + 1), MPFR_RNDD); mpfr_abs(tmp, mpfr_mat_entry(R, i, i + 1), MPFR_RNDD); mpfr_sub(norm, tmp, mpfr_mat_entry(bound, i, i + 1), MPFR_RNDD); mpfr_div(tmp, norm, ti, MPFR_RNDD); mpfr_sqr(norm, tmp, MPFR_RNDD); mpfr_sub_d(s, norm, fl->delta, MPFR_RNDD); mpfr_neg(s, s, MPFR_RNDD); mpfr_sqrt(tmp, s, MPFR_RNDU); mpfr_mul(s, tmp, ti, MPFR_RNDU); if (i < newd && !mpfr_lessequal_p(s, tj)) goto fail_clear_R_bound_bla_all; } mpfr_sub(tmp, mpfr_mat_entry(R, i, i), mpfr_mat_entry(bound, i, i), MPFR_RNDD); mpfr_sqr(tmp, tmp, MPFR_RNDD); if (i >= newd && !mpfr_greaterequal_p(tmp, mpfr_gs_B)) { fail_clear_R_bound_bla_all: mpfr_clear(mpfr_gs_B); fail_clear_R_bound_bla_some: mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); } FLINT_ASSERT((fl->rt == Z_BASIS ? fmpz_mat_is_reduced_with_removal(B, fl->delta, fl->eta, gs_B, newd) : fmpz_mat_is_reduced_gram_with_removal(B, fl->delta, fl->eta, gs_B, newd))); return 1; } flint-3.1.3/src/fmpz_lll/is_reduced_with_removal.c000066400000000000000000000031161461254215100222740ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz_lll.h" int fmpz_lll_is_reduced_with_removal(const fmpz_mat_t B, const fmpz_lll_t fl, const fmpz_t gs_B, int newd, flint_bitcnt_t prec) { if (gs_B == NULL) return fmpz_lll_is_reduced(B, fl, prec); if (fl->rt == Z_BASIS) { int res; fmpz_mat_t BB; _fmpz_mat_window_readonly_init_strip_initial_zero_rows(BB, B); if (fmpz_lll_is_reduced_d_with_removal(BB, fl, gs_B, newd)) { res = 1; } else if (fmpz_lll_is_reduced_mpfr_with_removal(BB, fl, gs_B, newd, prec)) { res = 1; } else { res = fmpz_mat_is_reduced_with_removal(BB, fl->delta, fl->eta, gs_B, newd); } _fmpz_mat_window_readonly_clear(BB); return res; } else { if (fmpz_lll_is_reduced_d_with_removal(B, fl, gs_B, newd)) return 1; if (fmpz_lll_is_reduced_mpfr_with_removal(B, fl, gs_B, newd, prec)) return 1; return fmpz_mat_is_reduced_gram_with_removal(B, fl->delta, fl->eta, gs_B, newd); } } flint-3.1.3/src/fmpz_lll/lll.c000066400000000000000000000011431461254215100161670ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" void fmpz_lll(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) { fmpz_lll_with_removal_ulll(B, U, WORD(250), NULL, fl); } flint-3.1.3/src/fmpz_lll/lll_d.c000066400000000000000000000054311461254215100164760ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef CALL_BABAI #undef CALL_BABAI #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_d(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) #define CALL_BABAI(NFF, BO, HF) \ do { \ if (NFF < 50) \ { \ BO = \ fmpz_lll_check_babai(kappa, B, U, mu, r, s, appB, expo, A, \ alpha[kappa], zeros, kappamax, \ FLINT_MIN(kappamax + 1 + shift, \ n), fl); \ } \ else \ { \ BO = -1; \ } \ if (BO == -1) \ { \ NFF++; \ HF = \ fmpz_lll_check_babai_heuristic_d(kappa, B, U, mu, r, s, \ appB, expo, A, \ alpha[kappa], zeros, \ kappamax, \ FLINT_MIN(kappamax + \ 1 + shift, \ n), fl); \ } \ } while (0) #define TYPE 0 /* indicates removals aren't desired */ #include "d_lll.c" #undef FUNC_HEAD #undef CALL_BABAI #undef TYPE flint-3.1.3/src/fmpz_lll/lll_d_heuristic.c000066400000000000000000000057761461254215100205710ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef CALL_BABAI #undef CALL_BABAI #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_d_heuristic(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) #define CALL_BABAI(NFF, BO, HF) \ do { \ if (NFF < 50) \ { \ BO = \ fmpz_lll_check_babai_heuristic_d(kappa, B, U, mu, r, s, \ appB, expo, A, \ alpha[kappa], zeros, \ kappamax, \ FLINT_MIN(kappamax + \ 1 + shift, \ n), fl); \ } \ else \ { \ BO = -1; \ } \ if (BO == -1) \ { \ NFF++; \ HF = \ fmpz_lll_check_babai_heuristic_d(kappa, B, U, mu, r, s, \ appB, expo, A, \ alpha[kappa], zeros, \ kappamax, \ FLINT_MIN(kappamax + \ 1 + shift, \ n), fl); \ } \ } while (0) #define TYPE 0 /* indicates removals aren't desired */ #include "d_lll.c" #undef FUNC_HEAD #undef CALL_BABAI #undef TYPE flint-3.1.3/src/fmpz_lll/lll_d_heuristic_with_removal.c000066400000000000000000000060331461254215100233340ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef CALL_BABAI #undef CALL_BABAI #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_d_heuristic_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) #define CALL_BABAI(NFF, BO, HF) \ do { \ if (NFF < 50) \ { \ BO = \ fmpz_lll_check_babai_heuristic_d(kappa, B, U, mu, r, s, \ appB, expo, A, \ alpha[kappa], zeros, \ kappamax, \ FLINT_MIN(kappamax + \ 1 + shift, \ n), fl); \ } \ else \ { \ BO = -1; \ } \ if (BO == -1) \ { \ NFF++; \ HF = \ fmpz_lll_check_babai_heuristic_d(kappa, B, U, mu, r, s, \ appB, expo, A, \ alpha[kappa], zeros, \ kappamax, \ FLINT_MIN(kappamax + \ 1 + shift, \ n), fl); \ } \ } while (0) #define TYPE 1 /* indicates removals are desired */ #include "d_lll.c" #undef FUNC_HEAD #undef CALL_BABAI #undef TYPE flint-3.1.3/src/fmpz_lll/lll_d_with_removal.c000066400000000000000000000054661461254215100212660ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef CALL_BABAI #undef CALL_BABAI #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_d_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) #define CALL_BABAI(NFF, BO, HF) \ do { \ if (NFF < 50) \ { \ BO = \ fmpz_lll_check_babai(kappa, B, U, mu, r, s, appB, expo, A, \ alpha[kappa], zeros, kappamax, \ FLINT_MIN(kappamax + 1 + shift, \ n), fl); \ } \ else \ { \ BO = -1; \ } \ if (BO == -1) \ { \ NFF++; \ HF = \ fmpz_lll_check_babai_heuristic_d(kappa, B, U, mu, r, s, \ appB, expo, A, \ alpha[kappa], zeros, \ kappamax, \ FLINT_MIN(kappamax + \ 1 + shift, \ n), fl); \ } \ } while (0) #define TYPE 1 /* indicates removals are desired */ #include "d_lll.c" #undef FUNC_HEAD #undef CALL_BABAI #undef TYPE flint-3.1.3/src/fmpz_lll/lll_d_with_removal_knapsack.c000066400000000000000000000055321461254215100231330ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "d_vec.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef CALL_BABAI #undef CALL_BABAI #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_d_with_removal_knapsack(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) #define CALL_BABAI(NFF, BO, HF) \ do { \ if (NFF < 150) \ { \ BO = \ fmpz_lll_check_babai(kappa, B, U, mu, r, s, appB, expo, A, \ alpha[kappa], zeros, kappamax, \ FLINT_MIN(kappamax + 1 + shift, \ n), fl); \ } \ else \ { \ BO = -1; \ } \ if (BO == -1) \ { \ NFF++; \ HF = \ fmpz_lll_check_babai_heuristic_d(kappa, B, U, mu, r, s, \ appB, expo, A, \ alpha[kappa], zeros, \ kappamax, \ FLINT_MIN(kappamax + \ 1 + shift, \ n), fl); \ } \ } while (0) #define TYPE 2 /* indicates early size reductions and removals are desired */ #include "d_lll.c" #undef FUNC_HEAD #undef CALL_BABAI #undef TYPE flint-3.1.3/src/fmpz_lll/lll_mpf.c000066400000000000000000000016611461254215100170360ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz_lll.h" int fmpz_lll_mpf(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) { flint_bitcnt_t prec = 0; int result, num_loops = 0; do { if (num_loops < 20) prec += D_BITS; else prec *= 2; result = fmpz_lll_mpf2(B, U, prec, fl); num_loops++; } while (((result == -1) || (!fmpz_lll_is_reduced(B, fl, prec))) && (prec < UWORD_MAX)); return result; } flint-3.1.3/src/fmpz_lll/lll_mpf2.c000066400000000000000000000015451461254215100171210ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_mpf2(fmpz_mat_t B, fmpz_mat_t U, flint_bitcnt_t prec, const fmpz_lll_t fl) #define TYPE 0 /* indicates removals aren't desired */ #include "mpf2_lll.c" #undef FUNC_HEAD #undef TYPE flint-3.1.3/src/fmpz_lll/lll_mpf2_with_removal.c000066400000000000000000000016021461254215100216730ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #ifdef FUNC_HEAD #undef FUNC_HEAD #endif #ifdef TYPE #undef TYPE #endif #define FUNC_HEAD int fmpz_lll_mpf2_with_removal(fmpz_mat_t B, fmpz_mat_t U, flint_bitcnt_t prec, const fmpz_t gs_B, const fmpz_lll_t fl) #define TYPE 1 /* indicates removals are desired */ #include "mpf2_lll.c" #undef FUNC_HEAD #undef TYPE flint-3.1.3/src/fmpz_lll/lll_mpf_with_removal.c000066400000000000000000000020651461254215100216150ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz_lll.h" int fmpz_lll_mpf_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) { flint_bitcnt_t prec = 0; int result, num_loops = 0; do { if (num_loops < 20) prec += D_BITS; else prec *= 2; result = fmpz_lll_mpf2_with_removal(B, U, prec, gs_B, fl); num_loops++; } while (((result == -1) || (!fmpz_lll_is_reduced_with_removal(B, fl, gs_B, result, prec))) && (prec < UWORD_MAX)); return result; } flint-3.1.3/src/fmpz_lll/lll_with_removal.c000066400000000000000000000012371461254215100207530ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" int fmpz_lll_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) { return fmpz_lll_with_removal_ulll(B, U, WORD(250), gs_B, fl); } flint-3.1.3/src/fmpz_lll/lll_with_removal_ulll.c000066400000000000000000000077221461254215100220100ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" int fmpz_lll_with_removal_ulll(fmpz_mat_t FM, fmpz_mat_t UM, slong new_size, const fmpz_t gs_B, const fmpz_lll_t fl) { int newd; if (fl->rt == Z_BASIS) { slong r, c, mbits, prev_mbits, i, j; int full_prec = 1, done = 0, is_U_I; fmpz_mat_t U, big_td, trunc_data; r = FM->r; c = FM->c; mbits = FLINT_ABS(fmpz_mat_max_bits(FM)); prev_mbits = mbits; fmpz_mat_init(big_td, r, c + r); fmpz_mat_init(trunc_data, r, c); if (mbits > new_size) { full_prec = 0; /* do some truncating */ fmpz_mat_scalar_tdiv_q_2exp(trunc_data, FM, (ulong) (mbits - new_size)); /* make a large lattice which has identity in one corner and trunc_data in the other */ for (i = 0; i < r; i++) { fmpz_one(fmpz_mat_entry(big_td, i, i)); for (j = r; j < r + c; j++) fmpz_set(fmpz_mat_entry(big_td, i, j), fmpz_mat_entry(trunc_data, i, j - r)); } } else { full_prec = 1; } while (done == 0) { if (full_prec == 0) { fmpz_lll_wrapper_with_removal_knapsack(big_td, UM, gs_B, fl); } else { newd = fmpz_lll_wrapper_with_removal_knapsack(FM, UM, gs_B, fl); } if (full_prec == 1) done = 1; else { /* get U and compare it to the identity */ fmpz_mat_window_init(U, big_td, 0, 0, r, r); is_U_I = fmpz_mat_is_one(U); if (is_U_I == 0) { fmpz_mat_mul(FM, U, FM); } mbits = FLINT_ABS(fmpz_mat_max_bits(FM)); /* make this condition better? */ if ((mbits - new_size > 0) && (mbits <= prev_mbits - (slong) (new_size / 4)) && is_U_I == 0) { /* do some truncating */ fmpz_mat_scalar_tdiv_q_2exp(trunc_data, FM, (ulong) (mbits - new_size)); /* keep with the big_td concept */ for (i = 0; i < r; i++) { for (j = 0; j < i; j++) fmpz_zero(fmpz_mat_entry(big_td, i, j)); fmpz_one(fmpz_mat_entry(big_td, i, i)); for (j = i + 1; j < r; j++) fmpz_zero(fmpz_mat_entry(big_td, i, j)); for (j = r; j < r + c; j++) fmpz_set(fmpz_mat_entry (big_td, i, j), fmpz_mat_entry(trunc_data, i, j - r)); } } else { /* can switch to FM, no need for a new identity */ full_prec = 1; } prev_mbits = mbits; fmpz_mat_window_clear(U); } } fmpz_mat_clear(trunc_data); fmpz_mat_clear(big_td); } else { newd = fmpz_lll_wrapper_with_removal_knapsack(FM, UM, gs_B, fl); } return newd; } flint-3.1.3/src/fmpz_lll/mpf-impl.c000066400000000000000000000057071461254215100171370ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpf-impl.h" #include "fmpz.h" mpf * _mpf_vec_init(slong len, flint_bitcnt_t prec) { slong i; mpf * vec = flint_malloc(len * sizeof(mpf)); for (i = 0; i < len; i++) mpf_init2(vec + i, prec); return vec; } void _mpf_vec_clear(mpf * vec, slong len) { slong i; for (i = 0; i < len; i++) mpf_clear(vec + i); flint_free(vec); } void _mpf_vec_set_fmpz_vec(mpf * appv, const fmpz * vec, slong len) { slong i; for (i = 0; i < len; i++) fmpz_get_mpf(appv + i, vec + i); } void _mpf_vec_norm(mpf_t res, const mpf * vec, slong len) { slong i; mpf_t tmp; mpf_init(tmp); flint_mpf_set_ui(res, 0); for (i = 0; i < len; i++) { mpf_mul(tmp, vec + i, vec + i); mpf_add(res, res, tmp); } mpf_clear(tmp); } void _mpf_vec_norm2(mpf_t res, const mpf * vec, slong len, flint_bitcnt_t prec) { slong i; mpf_t tmp; mpf_init2(tmp, prec); flint_mpf_set_ui(res, 0); for (i = 0; i < len; i++) { mpf_mul(tmp, vec + i, vec + i); mpf_add(res, res, tmp); } mpf_clear(tmp); } int _mpf_vec_dot2(mpf_t res, const mpf * vec1, const mpf * vec2, slong len2, flint_bitcnt_t prec) { slong i; int r = 0; mpf_t tmp, tmp2; mpf_init2(tmp, prec); mpf_init2(tmp2, prec); flint_mpf_set_ui(res, 0); for (i = 0; i < len2; i++) { mpf_mul(tmp, vec1 + i, vec2 + i); mpf_add(res, res, tmp); } _mpf_vec_norm(tmp, vec1, len2); _mpf_vec_norm(tmp2, vec2, len2); mpf_mul(tmp, tmp, tmp2); mpf_div_2exp(tmp, tmp, prec); mpf_mul(tmp2, res, res); if (mpf_cmp(tmp2, tmp) > 0) r = 1; mpf_clear(tmp); mpf_clear(tmp2); return r; } void mpf_mat_init(mpf_mat_t mat, slong rows, slong cols, flint_bitcnt_t prec) { if (rows != 0 && cols != 0) { slong i; mat->entries = flint_malloc(flint_mul_sizes(rows, cols) * sizeof(mpf)); mat->rows = flint_malloc(rows * sizeof(mpf *)); for (i = 0; i < rows * cols; i++) mpf_init2(mat->entries + i, prec); for (i = 0; i < rows; i++) mat->rows[i] = mat->entries + i * cols; } else { mat->entries = NULL; mat->rows = NULL; } mat->r = rows; mat->c = cols; mat->prec = prec; } void mpf_mat_clear(mpf_mat_t mat) { if (mat->entries) { slong i; for (i = 0; i < mat->r * mat->c; i++) mpf_clear(mat->entries + i); flint_free(mat->entries); flint_free(mat->rows); } } flint-3.1.3/src/fmpz_lll/mpf2_lll.c000066400000000000000000000464441461254215100171300ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" #if defined(FUNC_HEAD) && defined(TYPE) #ifdef GM #undef GM #endif #define GM ((fl->rt == Z_BASIS) ? A->exactSP : B) FUNC_HEAD { int newd = 0; #if TYPE int ok = 1; fmpz_t rii; #endif if (fl->rt == Z_BASIS && fl->gt == APPROX) { int kappa, kappa2, d, n, i, j, zeros, kappamax; mpf_mat_t mu, r, appB; fmpz_gram_t A; mpf *s, *mutmp, *appBtmp, *appSPtmp; mpf_t ctt, tmp, rtmp; int *alpha; fmpz *Btmp; n = B->c; d = B->r; mpf_init_set_d(ctt, (fl->delta + 1) / 2); alpha = (int *) flint_malloc(d * sizeof(int)); mpf_init2(tmp, prec); mpf_init2(rtmp, prec); mpf_mat_init(mu, d, d, prec); mpf_mat_init(r, d, d, prec); mpf_mat_init(appB, d, n, prec); mpf_mat_init(A->appSP2, d, d, prec); if (U != NULL) { if (U->r != d) { flint_throw(FLINT_ERROR, "(fmpz_lll_mpf*): Incompatible dimensions of capturing matrix.\n"); } } s = _mpf_vec_init(d, prec); appSPtmp = _mpf_vec_init(d, prec); for (i = 0; i < d; i++) { for (j = 0; j < d; j++) { mpf_set_d(mpf_mat_entry(A->appSP2, i, j), DBL_MIN); } } /* ************************** */ /* Step1: Initialization Step */ /* ************************** */ for (i = 0; i < d; i++) _mpf_vec_set_fmpz_vec(appB->rows[i], B->rows[i], n); /* ********************************* */ /* Step2: Initializing the main loop */ /* ********************************* */ kappamax = 0; i = 0; do { _mpf_vec_norm2(mpf_mat_entry(A->appSP2, i, i), appB->rows[i], n, prec); } while ((mpf_sgn(mpf_mat_entry(A->appSP2, i, i)) == 0.0) && (++i < d)); zeros = i - 1; /* all vectors B[i] with i <= zeros are zero vectors */ kappa = i + 1; kappamax = kappa; if (zeros < d - 1) { mpf_set(mpf_mat_entry(r, i, i), mpf_mat_entry(A->appSP2, i, i)); } for (i = zeros + 1; i < d; i++) alpha[i] = 0; while (kappa < d) { int babai_ok = 0; if (kappa > kappamax) kappamax = kappa; /* ********************************** */ /* Step3: Call to the Babai algorithm */ /* ********************************** */ babai_ok = fmpz_lll_check_babai_heuristic(kappa, B, U, mu, r, s, appB, A, alpha[kappa], zeros, kappamax, n, tmp, rtmp, prec, fl); if (babai_ok == -1) { flint_free(alpha); mpf_clears(ctt, tmp, rtmp, NULL); mpf_mat_clear(mu); mpf_mat_clear(r); mpf_mat_clear(appB); mpf_mat_clear(A->appSP2); _mpf_vec_clear(s, d); _mpf_vec_clear(appSPtmp, d); /* Need to switch to mpf / arb */ return -1; } /* ************************************ */ /* Step4: Success of Lovasz's condition */ /* ************************************ */ mpf_mul(tmp, mpf_mat_entry(r, kappa - 1, kappa - 1), ctt); if (mpf_cmp(tmp, s + kappa - 1) <= 0) { alpha[kappa] = kappa; mpf_mul(tmp, mpf_mat_entry(mu, kappa, kappa - 1), mpf_mat_entry(r, kappa, kappa - 1)); mpf_sub(mpf_mat_entry(r, kappa, kappa), s + kappa - 1, tmp); kappa++; } else { /* ******************************************* */ /* Step5: Find the right insertion index kappa */ /* kappa2 remains the initial kappa */ /* ******************************************* */ kappa2 = kappa; #if TYPE if (kappa == d - 1 && gs_B != NULL) { fmpz_init(rii); mpf_mul(tmp, mpf_mat_entry(mu, kappa, kappa - 1), mpf_mat_entry(r, kappa, kappa - 1)); mpf_mul_2exp(tmp, tmp, 1); mpf_sub(tmp, s + kappa - 1, tmp); fmpz_set_mpf(rii, tmp); /* using a heuristic lower bound on the final GS norm */ if (fmpz_cmp(rii, gs_B) > 0) { d--; } fmpz_clear(rii); if (kappa >= d) { break; } } #endif do { kappa--; if (kappa > zeros + 1) { mpf_mul(tmp, mpf_mat_entry(r, kappa - 1, kappa - 1), ctt); } } while ((kappa >= zeros + 2) && (mpf_cmp(s + kappa - 1, tmp) <= 0)); for (i = kappa; i < kappa2; i++) if (kappa <= alpha[i]) alpha[i] = kappa; for (i = kappa2; i > kappa; i--) alpha[i] = alpha[i - 1]; for (i = kappa2 + 1; i <= kappamax; i++) if (kappa < alpha[i]) alpha[i] = kappa; alpha[kappa] = kappa; /* ****************************** */ /* Step6: Update the mu's and r's */ /* ****************************** */ mutmp = mu->rows[kappa2]; for (i = kappa2; i > kappa; i--) mu->rows[i] = mu->rows[i - 1]; mu->rows[kappa] = mutmp; mutmp = r->rows[kappa2]; for (i = kappa2; i > kappa; i--) r->rows[i] = r->rows[i - 1]; r->rows[kappa] = mutmp; mpf_set(mpf_mat_entry(r, kappa, kappa), s + kappa); /* ************************ */ /* Step7: Update B and appB */ /* ************************ */ Btmp = B->rows[kappa2]; for (i = kappa2; i > kappa; i--) B->rows[i] = B->rows[i - 1]; B->rows[kappa] = Btmp; if (U != NULL) { Btmp = _fmpz_vec_init(U->c); _fmpz_vec_set(Btmp, U->rows[kappa2], U->c); for (i = kappa2; i > kappa; i--) _fmpz_vec_set(U->rows[i], U->rows[i - 1], U->c); _fmpz_vec_set(U->rows[kappa], Btmp, U->c); _fmpz_vec_clear(Btmp, U->c); } appBtmp = appB->rows[kappa2]; for (i = kappa2; i > kappa; i--) appB->rows[i] = appB->rows[i - 1]; appB->rows[kappa] = appBtmp; /* *************************** */ /* Step8: Update appSP: tricky */ /* *************************** */ for (i = 0; i <= kappa2; i++) mpf_set(appSPtmp + i, mpf_mat_entry(A->appSP2, kappa2, i)); for (i = kappa2 + 1; i <= kappamax; i++) mpf_set(appSPtmp + i, mpf_mat_entry(A->appSP2, i, kappa2)); for (i = kappa2; i > kappa; i--) { for (j = 0; j < kappa; j++) mpf_set(mpf_mat_entry(A->appSP2, i, j), mpf_mat_entry(A->appSP2, i - 1, j)); mpf_set(mpf_mat_entry(A->appSP2, i, kappa), appSPtmp + i - 1); for (j = kappa + 1; j <= i; j++) mpf_set(mpf_mat_entry(A->appSP2, i, j), mpf_mat_entry(A->appSP2, i - 1, j - 1)); for (j = kappa2 + 1; j <= kappamax; j++) mpf_set(mpf_mat_entry(A->appSP2, j, i), mpf_mat_entry(A->appSP2, j, i - 1)); } for (i = 0; i < kappa; i++) mpf_set(mpf_mat_entry(A->appSP2, kappa, i), appSPtmp + i); mpf_set(mpf_mat_entry(A->appSP2, kappa, kappa), appSPtmp + kappa2); for (i = kappa2 + 1; i <= kappamax; i++) mpf_set(mpf_mat_entry(A->appSP2, i, kappa), appSPtmp + i); if (mpf_sgn(mpf_mat_entry(r, kappa, kappa)) <= 0.0) { zeros++; kappa++; _mpf_vec_norm2(mpf_mat_entry(A->appSP2, kappa, kappa), appB->rows[kappa], n, prec); mpf_set(mpf_mat_entry(r, kappa, kappa), mpf_mat_entry(A->appSP2, kappa, kappa)); } kappa++; } } #if TYPE if (gs_B != NULL) { newd = d; fmpz_init(rii); for (i = d - 1; (i >= 0) && (ok > 0); i--) { mpf_div_2exp(tmp, mpf_mat_entry(r, i, i), 1); /* rii is the G-S length of ith vector divided by 2 */ fmpz_set_mpf(rii, tmp); if ((ok = fmpz_cmp(rii, gs_B)) > 0) { newd--; } } fmpz_clear(rii); } #endif flint_free(alpha); mpf_clears(ctt, tmp, rtmp, NULL); mpf_mat_clear(mu); mpf_mat_clear(r); mpf_mat_clear(appB); mpf_mat_clear(A->appSP2); _mpf_vec_clear(s, B->r); _mpf_vec_clear(appSPtmp, B->r); } else { int kappa, kappa2, d, n, i, j, zeros, kappamax, update_b = 1; mpf_mat_t mu, r; fmpz_gram_t A; mpf *s, *mutmp; mpf_t ctt, tmp, rtmp; int *alpha; fmpz *Btmp; n = B->c; d = B->r; mpf_init_set_d(ctt, (fl->delta + 1) / 2); alpha = (int *) flint_malloc(d * sizeof(int)); mpf_init2(tmp, prec); mpf_init2(rtmp, prec); mpf_mat_init(mu, d, d, prec); mpf_mat_init(r, d, d, prec); if (fl->rt == Z_BASIS) { fmpz_mat_init(A->exactSP, d, d); } s = _mpf_vec_init(d, prec); if (U != NULL) { if (U->r != d) { flint_throw(FLINT_ERROR, "(fmpz_lll_mpf*): Incompatible dimensions of capturing matrix.\n"); } else if (U->c == d && n > d && fmpz_mat_is_one(U)) { update_b = 0; } } if (fl->rt == Z_BASIS) { fmpz_mat_gram(A->exactSP, B); } /* ********************************* */ /* Step2: Initializing the main loop */ /* ********************************* */ kappamax = 0; i = 0; do ; while ((fmpz_cmp_ui(fmpz_mat_entry(GM, i, i), 0) <= 0) && (++i < d)); zeros = i - 1; /* all vectors B[i] with i <= zeros are zero vectors */ kappa = i + 1; kappamax = kappa; if (zeros < d - 1) { fmpz_get_mpf(mpf_mat_entry(r, i, i), fmpz_mat_entry(GM, i, i)); } for (i = zeros + 1; i < d; i++) alpha[i] = 0; while (kappa < d) { int babai_ok = 0; if (kappa > kappamax) kappamax = kappa; /* ********************************** */ /* Step3: Call to the Babai algorithm */ /* ********************************** */ babai_ok = fmpz_lll_check_babai_heuristic(kappa, (update_b ? B : NULL), U, mu, r, s, NULL, A, alpha[kappa], zeros, kappamax, n, tmp, rtmp, prec, fl); if (babai_ok == -1) { flint_free(alpha); mpf_clears(ctt, tmp, rtmp, NULL); mpf_mat_clear(mu); mpf_mat_clear(r); if (fl->rt == Z_BASIS) { fmpz_mat_clear(A->exactSP); } _mpf_vec_clear(s, d); /* Need to switch to mpf / arb */ return -1; } /* ************************************ */ /* Step4: Success of Lovasz's condition */ /* ************************************ */ mpf_mul(tmp, mpf_mat_entry(r, kappa - 1, kappa - 1), ctt); if (mpf_cmp(tmp, s + kappa - 1) <= 0) { alpha[kappa] = kappa; mpf_mul(tmp, mpf_mat_entry(mu, kappa, kappa - 1), mpf_mat_entry(r, kappa, kappa - 1)); mpf_sub(mpf_mat_entry(r, kappa, kappa), s + kappa - 1, tmp); kappa++; } else { /* ******************************************* */ /* Step5: Find the right insertion index kappa */ /* kappa2 remains the initial kappa */ /* ******************************************* */ kappa2 = kappa; #if TYPE if (kappa == d - 1 && gs_B != NULL) { fmpz_init(rii); mpf_mul(tmp, mpf_mat_entry(mu, kappa, kappa - 1), mpf_mat_entry(r, kappa, kappa - 1)); mpf_mul_2exp(tmp, tmp, 1); mpf_sub(tmp, s + kappa - 1, tmp); fmpz_set_mpf(rii, tmp); /* using a heuristic lower bound on the final GS norm */ if (fmpz_cmp(rii, gs_B) > 0) { d--; } fmpz_clear(rii); if (kappa >= d) { break; } } #endif do { kappa--; if (kappa > zeros + 1) { mpf_mul(tmp, mpf_mat_entry(r, kappa - 1, kappa - 1), ctt); } } while ((kappa >= zeros + 2) && (mpf_cmp(s + kappa - 1, tmp) <= 0)); for (i = kappa; i < kappa2; i++) if (kappa <= alpha[i]) alpha[i] = kappa; for (i = kappa2; i > kappa; i--) alpha[i] = alpha[i - 1]; for (i = kappa2 + 1; i <= kappamax; i++) if (kappa < alpha[i]) alpha[i] = kappa; alpha[kappa] = kappa; /* ****************************** */ /* Step6: Update the mu's and r's */ /* ****************************** */ mutmp = mu->rows[kappa2]; for (i = kappa2; i > kappa; i--) mu->rows[i] = mu->rows[i - 1]; mu->rows[kappa] = mutmp; mutmp = r->rows[kappa2]; for (i = kappa2; i > kappa; i--) r->rows[i] = r->rows[i - 1]; r->rows[kappa] = mutmp; mpf_set(mpf_mat_entry(r, kappa, kappa), s + kappa); /* *************** */ /* Step7: Update B */ /* *************** */ if (fl->rt == Z_BASIS && update_b) { Btmp = B->rows[kappa2]; for (i = kappa2; i > kappa; i--) B->rows[i] = B->rows[i - 1]; B->rows[kappa] = Btmp; } if (U != NULL) { Btmp = _fmpz_vec_init(U->c); _fmpz_vec_set(Btmp, U->rows[kappa2], U->c); for (i = kappa2; i > kappa; i--) _fmpz_vec_set(U->rows[i], U->rows[i - 1], U->c); _fmpz_vec_set(U->rows[kappa], Btmp, U->c); _fmpz_vec_clear(Btmp, U->c); } /* ********************* */ /* Step8: Update exactSP */ /* ********************* */ for (j = kappa2; j > kappa; j--) { for (i = kappa2; i < d; i++) fmpz_swap(fmpz_mat_entry(GM, i, j), fmpz_mat_entry(GM, i, j - 1)); for (i = 0; i < kappa; i++) fmpz_swap(fmpz_mat_entry(GM, j, i), fmpz_mat_entry(GM, j - 1, i)); } for (j = kappa2; j > kappa; j--) { for (i = j; i > kappa; i--) fmpz_swap(fmpz_mat_entry(GM, j, i), fmpz_mat_entry(GM, j - 1, i - 1)); } for (j = 0; 2 * j < kappa2 - kappa; j++) fmpz_swap(fmpz_mat_entry(GM, kappa + j, kappa), fmpz_mat_entry(GM, kappa2 - j, kappa)); if (mpf_sgn(mpf_mat_entry(r, kappa, kappa)) <= 0.0) { zeros++; kappa++; fmpz_get_mpf(mpf_mat_entry(r, kappa, kappa), fmpz_mat_entry(GM, kappa, kappa)); } kappa++; } } if (fl->rt == GRAM) { for (i = 0; i < B->r - 1; i++) { for (j = i + 1; j < B->r; j++) { fmpz_set(fmpz_mat_entry(B, i, j), fmpz_mat_entry(B, j, i)); } } } else if (!update_b) { fmpz_mat_mul(B, U, B); } #if TYPE if (gs_B != NULL) { newd = d; fmpz_init(rii); for (i = d - 1; (i >= 0) && (ok > 0); i--) { mpf_div_2exp(tmp, mpf_mat_entry(r, i, i), 1); /* rii is the G-S length of ith vector divided by 2 */ fmpz_set_mpf(rii, tmp); if ((ok = fmpz_cmp(rii, gs_B)) > 0) { newd--; } } fmpz_clear(rii); } #endif flint_free(alpha); mpf_clears(ctt, tmp, rtmp, NULL); mpf_mat_clear(mu); mpf_mat_clear(r); if (fl->rt == Z_BASIS) { fmpz_mat_clear(A->exactSP); } _mpf_vec_clear(s, B->r); } return newd; } #undef GM #endif flint-3.1.3/src/fmpz_lll/profile/000077500000000000000000000000001461254215100167015ustar00rootroot00000000000000flint-3.1.3/src/fmpz_lll/profile/p-lll.c000066400000000000000000000053051461254215100200700ustar00rootroot00000000000000/* Copyright 2009 William Hart Copyright 2010,2011 Fredrik Johansson Copyright 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #include "fmpq.h" #include "ulong_extras.h" typedef struct { slong dim; int algorithm; } mat_lll_t; void sample(void *arg, ulong count) { mat_lll_t *params = (mat_lll_t *) arg; slong i, dim = params->dim; int algorithm = params->algorithm; fmpq_t delta, eta; fmpz_lll_t fl; fmpz_mat_t A, B, C, D; FLINT_TEST_INIT(state); fmpz_mat_init(A, dim, dim); fmpq_init(delta); fmpq_init(eta); fmpq_set_si(delta, 3, 4); fmpq_set_si(eta, 81, 100); fmpz_lll_context_init(fl, 0.75, 0.81, 1, 0); fmpz_mat_randajtai(A, state, 0.5); fmpz_mat_init_set(B, A); fmpz_mat_init_set(C, A); fmpz_mat_init_set(D, A); prof_start(); if (algorithm == 0) for (i = 0; i < count; i++) { fmpz_mat_lll_original(A, delta, eta); } else if (algorithm == 1) for (i = 0; i < count; i++) { fmpz_mat_lll_storjohann(B, delta, eta); } else if (algorithm == 2) for (i = 0; i < count; i++) { fmpz_lll_wrapper(C, NULL, fl); } else if (algorithm == 3) for (i = 0; i < count; i++) { fmpz_lll(D, NULL, fl); } prof_stop(); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); fmpq_clear(delta); fmpq_clear(eta); flint_randclear(state); } int main(void) { double min_classical, min_storjohann, min_wrapper, min_default, max; mat_lll_t params; slong dim; flint_printf("fmpz_lll :\n"); for (dim = 100; dim <= 500; dim += 10) { params.dim = dim; params.algorithm = 0; prof_repeat(&min_classical, &max, sample, ¶ms); params.algorithm = 1; prof_repeat(&min_storjohann, &max, sample, ¶ms); params.algorithm = 2; prof_repeat(&min_wrapper, &max, sample, ¶ms); params.algorithm = 3; prof_repeat(&min_default, &max, sample, ¶ms); flint_printf ("dim = %wd classical/storjohann/wrapper/default %.2f %.2f %.2f %.2f (us)\n", dim, min_classical, min_storjohann, min_wrapper, min_default); } return 0; } flint-3.1.3/src/fmpz_lll/randtest.c000066400000000000000000000020151461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "double_extras.h" #include "fmpz_lll.h" #define EPS 0.000000000003 void fmpz_lll_randtest(fmpz_lll_t fl, flint_rand_t state) { double delta, eta; rep_type rt; gram_type gt; delta = 0.25 + 0.75 * d_randtest(state); if (delta <= 0.25) delta = nextafter(0.25, 1.00); eta = 0.5 + 2 * (d_randtest(state) - 0.5) * (sqrt(delta) - 0.5); if (eta <= 0.5 + EPS) eta = 0.5 + 8 * EPS * d_randtest(state); rt = n_randint(state, 2); gt = n_randint(state, 2); fmpz_lll_context_init(fl, delta, eta, rt, gt); } flint-3.1.3/src/fmpz_lll/shift.c000066400000000000000000000015361461254215100165270ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" int fmpz_lll_shift(const fmpz_mat_t B) { int i, n = B->c; int shift = 0; for (i = 0; i < B->r; i++) { int j; for (j = n - 1; j >= i + shift + 1 && fmpz_size(fmpz_mat_entry(B, i, j)) == 0L; j--) ; if (shift < j - i) shift = j - i; } return shift; } flint-3.1.3/src/fmpz_lll/storjohann_ulll.c000066400000000000000000000102711461254215100206230ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq.h" #include "fmpz_lll.h" void fmpz_lll_storjohann_ulll(fmpz_mat_t FM, slong new_size, const fmpz_lll_t fl) { if (fl->rt == Z_BASIS) { slong r, c, mbits, prev_mbits, i, j; int full_prec = 1, done = 0, is_U_I; fmpz_mat_t U, big_td, trunc_data; mpq_t deltax, etax; fmpq_t delta, eta; r = FM->r; c = FM->c; mbits = FLINT_ABS(fmpz_mat_max_bits(FM)); prev_mbits = mbits; fmpz_mat_init(big_td, r, c + r); fmpz_mat_init(trunc_data, r, c); mpq_init(deltax); mpq_init(etax); fmpq_init(delta); fmpq_init(eta); mpq_set_d(deltax, fl->delta); mpq_set_d(etax, fl->eta); fmpq_set_mpq(delta, deltax); fmpq_set_mpq(eta, etax); mpq_clears(deltax, etax, NULL); if (mbits > new_size) { full_prec = 0; /* do some truncating */ fmpz_mat_scalar_tdiv_q_2exp(trunc_data, FM, (ulong) (mbits - new_size)); /* make a large lattice which has identity in one corner and trunc_data in the other */ for (i = 0; i < r; i++) { fmpz_one(fmpz_mat_entry(big_td, i, i)); for (j = r; j < r + c; j++) fmpz_set(fmpz_mat_entry(big_td, i, j), fmpz_mat_entry(trunc_data, i, j - r)); } } else { full_prec = 1; } while (done == 0) { if (full_prec == 0) { fmpz_mat_lll_storjohann(big_td, delta, eta); } else { fmpz_mat_lll_storjohann(FM, delta, eta); } if (full_prec == 1) done = 1; else { /* get U and compare it to the identity */ fmpz_mat_window_init(U, big_td, 0, 0, r, r); is_U_I = fmpz_mat_is_one(U); if (is_U_I == 0) { fmpz_mat_mul(FM, U, FM); } mbits = FLINT_ABS(fmpz_mat_max_bits(FM)); /* make this condition better? */ if ((mbits - new_size > 0) && (mbits <= prev_mbits - (slong) (new_size / 4)) && is_U_I == 0) { /* do some truncating */ fmpz_mat_scalar_tdiv_q_2exp(trunc_data, FM, (ulong) (mbits - new_size)); /* keep with the big_td concept */ for (i = 0; i < r; i++) { for (j = 0; j < i; j++) fmpz_zero(fmpz_mat_entry(big_td, i, j)); fmpz_one(fmpz_mat_entry(big_td, i, i)); for (j = i + 1; j < r; j++) fmpz_zero(fmpz_mat_entry(big_td, i, j)); for (j = r; j < r + c; j++) fmpz_set(fmpz_mat_entry (big_td, i, j), fmpz_mat_entry(trunc_data, i, j - r)); } } else { /* can switch to FM, no need for a new identity */ full_prec = 1; } prev_mbits = mbits; fmpz_mat_window_clear(U); } } fmpz_mat_clear(trunc_data); fmpz_mat_clear(big_td); fmpq_clear(delta); fmpq_clear(eta); } else { fmpz_lll_with_removal_ulll(FM, NULL, new_size, NULL, fl); } } flint-3.1.3/src/fmpz_lll/test/000077500000000000000000000000001461254215100162205ustar00rootroot00000000000000flint-3.1.3/src/fmpz_lll/test/main.c000066400000000000000000000032271461254215100173140ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-heuristic_dot.c" #include "t-lll.c" #include "t-lll_d.c" #include "t-lll_d_heuristic.c" #include "t-lll_d_heuristic_with_removal.c" #include "t-lll_d_with_removal.c" #include "t-lll_d_with_removal_knapsack.c" #include "t-lll_mpf.c" #include "t-lll_mpf_with_removal.c" #include "t-lll_with_removal.c" #include "t-wrapper.c" #include "t-wrapper_with_removal.c" #include "t-wrapper_with_removal_knapsack.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_lll_heuristic_dot), TEST_FUNCTION(fmpz_lll), TEST_FUNCTION(fmpz_lll_d), TEST_FUNCTION(fmpz_lll_d_heuristic), TEST_FUNCTION(fmpz_lll_d_heuristic_with_removal), TEST_FUNCTION(fmpz_lll_d_with_removal), TEST_FUNCTION(fmpz_lll_d_with_removal_knapsack), TEST_FUNCTION(fmpz_lll_mpf), TEST_FUNCTION(fmpz_lll_mpf_with_removal), TEST_FUNCTION(fmpz_lll_with_removal), TEST_FUNCTION(fmpz_lll_wrapper), TEST_FUNCTION(fmpz_lll_wrapper_with_removal), TEST_FUNCTION(fmpz_lll_wrapper_with_removal_knapsack) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_lll/test/t-heuristic_dot.c000066400000000000000000000043231461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __GNUC__ # define fabs __builtin_fabs #else # include #endif #include "test_helpers.h" #include "d_vec.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #define FMPZ_LLL_HD_EPS (1.0E-9) TEST_FUNCTION_START(fmpz_lll_heuristic_dot, state) { int i; fmpz_mat_t B; for (i = 0; i < 100 * flint_test_multiplier(); i++) { int result, expo1, expo2; double *v1, *v2; slong rows, cols, r1, r2; double d1, d2, d3, d4; rows = n_randint(state, 50) + 1; cols = n_randint(state, 50) + 2; r1 = n_randint(state, rows); r2 = n_randint(state, rows); fmpz_mat_init(B, rows, cols); fmpz_mat_randtest(B, state, 200); v1 = _d_vec_init(cols); v2 = _d_vec_init(cols); expo1 = _fmpz_vec_get_d_vec_2exp(v1, B->rows[r1], cols); expo2 = _fmpz_vec_get_d_vec_2exp(v2, B->rows[r2], cols); d1 = fmpz_lll_heuristic_dot(v1, v2, cols, B, r1, r2, expo1 + expo2); d2 = fmpz_lll_heuristic_dot(v1, v1, cols, B, r1, r1, expo1 + expo1); d3 = fmpz_lll_heuristic_dot(v2, v2, cols, B, r2, r2, expo2 + expo2); _d_vec_add(v2, v1, v2, cols); _fmpz_vec_add(B->rows[r2], B->rows[r1], B->rows[r2], cols); d4 = fmpz_lll_heuristic_dot(v2, v2, cols, B, r2, r2, expo2 + expo2); result = (fabs(d4 - d3 - d2 - 2 * d1) < FMPZ_LLL_HD_EPS); if (!result) { flint_printf("FAIL:\n"); flint_printf ("expo1 = %d, expo2 = %d\nd1 = %g, d2 = %g, d3 = %g, d4 = %g\n", expo1, expo2, d1, d2, d3, d4); flint_printf("%g\n", fabs(d4 - d3 - d2 - 2 * d1)); fflush(stdout); flint_abort(); } _d_vec_clear(v1); _d_vec_clear(v2); fmpz_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll.c000066400000000000000000000322421461254215100174130ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll, state) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; /* test rank deficient matrices */ { fmpz_mat_init(mat, 3, 3); fmpz_lll_context_init_default(fl); fmpz_mat_zero(mat); fmpz_lll(mat, NULL, fl); if (!fmpz_mat_is_zero(mat)) { flint_printf("FAIL: check zero matrix\n"); fflush(stdout); flint_abort(); } fmpz_mat_zero(mat); fmpz_set_ui(fmpz_mat_entry(mat, 1, 0), 4); fmpz_set_ui(fmpz_mat_entry(mat, 2, 0), 6); fmpz_lll(mat, NULL, fl); fmpz_abs(fmpz_mat_entry(mat, 2, 0), fmpz_mat_entry(mat, 2, 0)); fmpz_sub_ui(fmpz_mat_entry(mat, 2, 0), fmpz_mat_entry(mat, 2, 0), 2); if (!fmpz_mat_is_zero(mat)) { flint_printf("FAIL: check gcd(4,6)=2\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; r = n_randint(state, 20) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; fmpz_mat_randintrel(mat, state, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); fmpz_lll(gmat, U, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { fmpz_lll(gmat, NULL, fl); } result = fmpz_mat_is_reduced_gram(gmat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_d.c000066400000000000000000000305501461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_d, state) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_d(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_d(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; /* Note: tests can fail with larger "r" and "bits" */ r = n_randint(state, 10) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 100) + 1; fmpz_mat_randintrel(mat, state, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); fmpz_lll_d(gmat, U, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { fmpz_lll_d(gmat, NULL, fl); } result = fmpz_mat_is_reduced_gram(gmat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_d(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_d(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_d(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_d(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_d_heuristic.c000066400000000000000000000310221461254215100217700ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_d_heuristic, state) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_d_heuristic(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_d_heuristic(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d_heuristic(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d_heuristic(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; /* Note: tests can fail with larger "r" and "bits" */ r = n_randint(state, 10) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 100) + 1; fmpz_mat_randintrel(mat, state, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); fmpz_lll_d_heuristic(gmat, U, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { fmpz_lll_d_heuristic(gmat, NULL, fl); } result = fmpz_mat_is_reduced_gram(gmat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d_heuristic(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d_heuristic(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_d_heuristic(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_d_heuristic(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d_heuristic(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d_heuristic(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_d_heuristic(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_d_heuristic(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_d_heuristic(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_d_heuristic(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_d_heuristic_with_removal.c000066400000000000000000000341731461254215100245620ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_d_heuristic_with_removal, state) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_heuristic_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; /* Note: tests can fail with larger "r" and "bits" */ r = n_randint(state, 10) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 100) + 1; fmpz_mat_randintrel(mat, state, bits); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); newd = fmpz_lll_d_heuristic_with_removal(gmat, U, bound, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { newd = fmpz_lll_d_heuristic_with_removal(gmat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(gmat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_heuristic_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } fmpz_clear(bound); } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 4 * r); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_heuristic_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); fmpz_mul_2exp(bound, bound, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_heuristic_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_heuristic_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_d_with_removal.c000066400000000000000000000336751461254215100225110ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_d_with_removal, state) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; /* Note: tests can fail with larger "r" and "bits" */ r = n_randint(state, 10) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 100) + 1; fmpz_mat_randintrel(mat, state, bits); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); newd = fmpz_lll_d_with_removal(gmat, U, bound, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { newd = fmpz_lll_d_with_removal(gmat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(gmat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } fmpz_clear(bound); } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 4 * r); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); fmpz_mul_2exp(bound, bound, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_d_with_removal_knapsack.c000066400000000000000000000341261461254215100243540ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_d_with_removal_knapsack, state) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; /* Note: tests can fail with larger "r" and "bits" */ r = n_randint(state, 10) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 100) + 1; fmpz_mat_randintrel(mat, state, bits); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); newd = fmpz_lll_d_with_removal_knapsack(gmat, U, bound, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { newd = fmpz_lll_d_with_removal_knapsack(gmat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(gmat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } fmpz_clear(bound); } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 4 * r); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); fmpz_mul_2exp(bound, bound, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_d_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_d_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_mpf.c000066400000000000000000000305141461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_mpf, state) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_mpf(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_mpf(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_mpf(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_mpf(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; r = n_randint(state, 20) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; fmpz_mat_randintrel(mat, state, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); fmpz_lll_mpf(gmat, U, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { fmpz_lll_mpf(gmat, NULL, fl); } result = fmpz_mat_is_reduced_gram(gmat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_mpf(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_mpf(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_mpf(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_mpf(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_mpf(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_mpf(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_mpf(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_mpf(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_mpf(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_mpf(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_mpf_with_removal.c000066400000000000000000000336411461254215100230410ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_mpf_with_removal, state) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_mpf_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_mpf_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_mpf_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_mpf_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; r = n_randint(state, 20) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; fmpz_mat_randintrel(mat, state, bits); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); newd = fmpz_lll_mpf_with_removal(gmat, U, bound, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { newd = fmpz_lll_mpf_with_removal(gmat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(gmat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_mpf_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_mpf_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } fmpz_clear(bound); } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 4 * r); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_mpf_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_mpf_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_mpf_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_mpf_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); fmpz_mul_2exp(bound, bound, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_mpf_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_mpf_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_mpf_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_mpf_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-lll_with_removal.c000066400000000000000000000335351461254215100222010ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_with_removal, state) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; r = n_randint(state, 20) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; fmpz_mat_randintrel(mat, state, bits); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); newd = fmpz_lll_with_removal(gmat, U, bound, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { newd = fmpz_lll_with_removal(gmat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(gmat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } fmpz_clear(bound); } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 4 * r); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); fmpz_mul_2exp(bound, bound, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-wrapper.c000066400000000000000000000306201461254215100203060ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_wrapper, state) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_wrapper(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_wrapper(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_wrapper(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_wrapper(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; r = n_randint(state, 20) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; fmpz_mat_randintrel(mat, state, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); fmpz_lll_wrapper(gmat, U, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { fmpz_lll_wrapper(gmat, NULL, fl); } result = fmpz_mat_is_reduced_gram(gmat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_wrapper(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_wrapper(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_wrapper(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_wrapper(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_wrapper(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_wrapper(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); fmpz_lll_wrapper(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); fmpz_lll_wrapper(mat, NULL, fl); } result = fmpz_mat_is_reduced_gram(mat, fl->delta, fl->eta); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_lll_wrapper(mat, U, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_lll_wrapper(mat, NULL, fl); } result = fmpz_mat_is_reduced(mat, fl->delta, fl->eta); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-wrapper_with_removal.c000066400000000000000000000337451461254215100231010ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_wrapper_with_removal, state) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; r = n_randint(state, 20) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; fmpz_mat_randintrel(mat, state, bits); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); newd = fmpz_lll_wrapper_with_removal(gmat, U, bound, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { newd = fmpz_lll_wrapper_with_removal(gmat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(gmat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } fmpz_clear(bound); } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 4 * r); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); fmpz_mul_2exp(bound, bound, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/test/t-wrapper_with_removal_knapsack.c000066400000000000000000000356261461254215100247540ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" TEST_FUNCTION_START(fmpz_lll_wrapper_with_removal_knapsack, state) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; /* test using NTRU like matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { ulong q; slong r, c; r = 2 * (n_randint(state, 25) + 1); c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 20) + 1; q = n_randint(state, 200) + 1; if (n_randint(state, 2)) fmpz_mat_randntrulike(mat, state, bits, q); else fmpz_mat_randntrulike2(mat, state, bits, q); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randntrulike): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randntrulike):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using integer relations matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; fmpz_mat_t gmat, gmat2; r = n_randint(state, 20) + 1; c = r + 1; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; fmpz_mat_randintrel(mat, state, bits); fmpz_mul_2exp(bound, bound, bits); if (fl->rt == GRAM) { fmpz_mat_init(gmat, r, r); fmpz_mat_gram(gmat, mat); if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_init(gmat2, r, r); newd = fmpz_lll_wrapper_with_removal_knapsack(gmat, U, bound, fl); fmpz_mat_mul(mat2, U, mat); fmpz_mat_gram(gmat2, mat2); result = fmpz_mat_equal(gmat, gmat2); if (!result) { flint_printf ("FAIL (randintrel): gram matrices not equal!\n"); fmpz_mat_print_pretty(gmat); fmpz_mat_print_pretty(gmat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); fmpz_mat_clear(gmat2); } else { newd = fmpz_lll_wrapper_with_removal_knapsack(gmat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(gmat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randintrel): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randintrel):\n"); fmpz_mat_print_pretty(mat); if (fl->rt == GRAM) { fmpz_mat_print_pretty(gmat); } flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); if (fl->rt == GRAM) { fmpz_mat_clear(gmat); } fmpz_clear(bound); } /* test using ajtai matrices */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 10) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 4 * r); fmpz_lll_randtest(fl, state); fmpz_mat_randajtai(mat, state, 0.5); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randajtai): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randajtai):\n"); fmpz_mat_print_pretty(mat); flint_printf("i = %ld\n", i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } /* test using simultaneous diophantine matrices */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { flint_bitcnt_t bits2; slong r, c; r = n_randint(state, 50) + 1; c = r; fmpz_mat_init(mat, r, c); fmpz_init_set_ui(bound, 2); fmpz_lll_randtest(fl, state); bits = n_randint(state, 200) + 1; bits2 = n_randint(state, 5) + 1; fmpz_mat_randsimdioph(mat, state, bits, bits2); fmpz_mul_2exp(bound, bound, bits2); if (fl->rt == GRAM) { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); fmpz_mat_gram(mat2, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): gram matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { fmpz_mat_gram(mat, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_gram_with_removal(mat, fl->delta, fl->eta, bound, newd); } else { if (n_randint(state, 2)) { fmpz_mat_init(U, r, r); fmpz_mat_one(U); fmpz_mat_init(mat2, r, c); fmpz_mat_set(mat2, mat); newd = fmpz_lll_wrapper_with_removal_knapsack(mat, U, bound, fl); fmpz_mat_mul(mat2, U, mat2); result = fmpz_mat_equal(mat, mat2); if (!result) { flint_printf ("FAIL (randsimdioph): basis matrices not equal!\n"); fmpz_mat_print_pretty(mat); fmpz_mat_print_pretty(mat2); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(mat2); } else { newd = fmpz_lll_wrapper_with_removal_knapsack(mat, NULL, bound, fl); } result = fmpz_mat_is_reduced_with_removal(mat, fl->delta, fl->eta, bound, newd); } if (!result) { flint_printf("FAIL (randsimdioph):\n"); fmpz_mat_print_pretty(mat); flint_printf("bits = %ld, i = %ld\n", bits, i); flint_printf("delta = %g, eta = %g\n", fl->delta, fl->eta); flint_printf("rep_type = %d\n", fl->rt); flint_printf("gram_type = %d\n", fl->gt); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_lll/wrapper.c000066400000000000000000000020361461254215100170660ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "fmpz_lll.h" int fmpz_lll_wrapper(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl) { int res = fmpz_lll_d(B, U, fl); if ((res == -1) || (!fmpz_lll_is_reduced(B, fl, D_BITS))) { if (fl->rt == Z_BASIS && fl->gt == APPROX) { res = fmpz_lll_d_heuristic(B, U, fl); if ((res == -1) || (!fmpz_lll_is_reduced(B, fl, D_BITS))) { res = fmpz_lll_mpf(B, U, fl); } } else { res = fmpz_lll_mpf(B, U, fl); } } return res; } flint-3.1.3/src/fmpz_lll/wrapper_with_removal.c000066400000000000000000000023171461254215100216500ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" int fmpz_lll_wrapper_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) { int res = fmpz_lll_d_with_removal(B, U, gs_B, fl); if ((res == -1) || (!fmpz_lll_is_reduced_with_removal(B, fl, gs_B, res, 120))) { if (fl->rt == Z_BASIS && fl->gt == APPROX) { res = fmpz_lll_d_heuristic_with_removal(B, U, gs_B, fl); if ((res == -1) || (!fmpz_lll_is_reduced_with_removal(B, fl, gs_B, res, 120))) { res = fmpz_lll_mpf_with_removal(B, U, gs_B, fl); } } else { res = fmpz_lll_mpf_with_removal(B, U, gs_B, fl); } } return res; } flint-3.1.3/src/fmpz_lll/wrapper_with_removal_knapsack.c000066400000000000000000000023521461254215100235220ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2009, 2010 Andy Novocin Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" int fmpz_lll_wrapper_with_removal_knapsack(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl) { int res = fmpz_lll_d_with_removal_knapsack(B, U, gs_B, fl); if ((res == -1) || (!fmpz_lll_is_reduced_with_removal(B, fl, gs_B, res, 120))) { if (fl->rt == Z_BASIS && fl->gt == APPROX) { res = fmpz_lll_d_heuristic_with_removal(B, U, gs_B, fl); if ((res == -1) || (!fmpz_lll_is_reduced_with_removal(B, fl, gs_B, res, 120))) { res = fmpz_lll_mpf_with_removal(B, U, gs_B, fl); } } else { res = fmpz_lll_mpf_with_removal(B, U, gs_B, fl); } } return res; } flint-3.1.3/src/fmpz_mat.h000066400000000000000000000474741461254215100154300ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MAT_H #define FMPZ_MAT_H #ifdef FMPZ_MAT_INLINES_C #define FMPZ_MAT_INLINE #else #define FMPZ_MAT_INLINE static inline #endif #include "fmpz_types.h" #include "nmod_types.h" #include "d_mat.h" #ifdef __cplusplus extern "C" { #endif /* Element access ********************************************************/ FMPZ_MAT_INLINE fmpz * fmpz_mat_entry(const fmpz_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } FMPZ_MAT_INLINE slong fmpz_mat_nrows(const fmpz_mat_t mat) { return mat->r; } FMPZ_MAT_INLINE slong fmpz_mat_ncols(const fmpz_mat_t mat) { return mat->c; } /* Memory management ********************************************************/ void fmpz_mat_init(fmpz_mat_t mat, slong rows, slong cols); void fmpz_mat_init_set(fmpz_mat_t mat, const fmpz_mat_t src); void fmpz_mat_swap(fmpz_mat_t mat1, fmpz_mat_t mat2); void fmpz_mat_swap_entrywise(fmpz_mat_t mat1, fmpz_mat_t mat2); void fmpz_mat_swap_cols(fmpz_mat_t mat, slong * perm, slong r, slong s); void fmpz_mat_set(fmpz_mat_t mat1, const fmpz_mat_t mat2); void fmpz_mat_clear(fmpz_mat_t mat); int fmpz_mat_equal(const fmpz_mat_t mat1, const fmpz_mat_t mat2); int fmpz_mat_is_zero(const fmpz_mat_t mat); int fmpz_mat_is_one(const fmpz_mat_t mat); int fmpz_mat_is_zero_row(const fmpz_mat_t mat, slong i); #define fmpz_mat_col_equal(M, m, n) _Pragma("GCC warning \"'fmpz_mat_col_equal' is deprecated in favor for 'fmpz_mat_equal_col'\"") fmpz_mat_equal_col(M, m, n) #define fmpz_mat_row_equal(M, m, n) _Pragma("GCC warning \"'fmpz_mat_row_equal' is deprecated in favor for 'fmpz_mat_equal_row'\"") fmpz_mat_equal_row(M, m, n) int fmpz_mat_equal_col(fmpz_mat_t M, slong m, slong n); int fmpz_mat_equal_row(fmpz_mat_t M, slong m, slong n); FMPZ_MAT_INLINE int fmpz_mat_is_empty(const fmpz_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } FMPZ_MAT_INLINE int fmpz_mat_is_square(const fmpz_mat_t mat) { return (mat->r == mat->c); } void fmpz_mat_zero(fmpz_mat_t mat); void fmpz_mat_one(fmpz_mat_t mat); /* Windows and concatenation *************************************************/ void fmpz_mat_window_init(fmpz_mat_t window, const fmpz_mat_t mat, slong r1, slong c1, slong r2, slong c2); void fmpz_mat_window_clear(fmpz_mat_t window); void _fmpz_mat_window_readonly_init_strip_initial_zero_rows(fmpz_mat_t A, const fmpz_mat_t B); #define _fmpz_mat_window_readonly_clear(A) /* Do nothing */ void fmpz_mat_concat_horizontal(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2); void fmpz_mat_concat_vertical(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2); /* Input and output *********************************************************/ #ifdef FLINT_HAVE_FILE int fmpz_mat_fprint(FILE * file, const fmpz_mat_t mat); int fmpz_mat_fprint_pretty(FILE * file, const fmpz_mat_t mat); int fmpz_mat_fread(FILE* file, fmpz_mat_t mat); #endif int fmpz_mat_print(const fmpz_mat_t mat); int fmpz_mat_print_pretty(const fmpz_mat_t mat); int fmpz_mat_read(fmpz_mat_t mat); /* Random matrix generation *************************************************/ void fmpz_mat_randbits(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); void fmpz_mat_randtest(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); void fmpz_mat_randtest_unsigned(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); void fmpz_mat_randintrel(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); void fmpz_mat_randsimdioph(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, flint_bitcnt_t bits2); void fmpz_mat_randntrulike(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q); void fmpz_mat_randntrulike2(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q); void fmpz_mat_randajtai(fmpz_mat_t mat, flint_rand_t state, double alpha); void fmpz_mat_randrank(fmpz_mat_t mat, flint_rand_t state, slong rank, flint_bitcnt_t bits); void fmpz_mat_randdet(fmpz_mat_t mat, flint_rand_t state, const fmpz_t det); void fmpz_mat_randops(fmpz_mat_t mat, flint_rand_t state, slong count); int fmpz_mat_randpermdiag(fmpz_mat_t mat, flint_rand_t state, const fmpz * diag, slong n); /* Norms */ slong fmpz_mat_max_bits(const fmpz_mat_t mat); /* Transpose */ void fmpz_mat_transpose(fmpz_mat_t B, const fmpz_mat_t A); /* Addition and subtraction */ void fmpz_mat_add(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void fmpz_mat_sub(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void fmpz_mat_neg(fmpz_mat_t B, const fmpz_mat_t A); /* Scalar operations */ void fmpz_mat_scalar_mul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); void fmpz_mat_scalar_mul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); void fmpz_mat_scalar_mul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); void fmpz_mat_scalar_addmul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); void fmpz_mat_scalar_addmul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); void fmpz_mat_scalar_addmul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); void fmpz_mat_scalar_submul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); void fmpz_mat_scalar_submul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); void fmpz_mat_scalar_submul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); void fmpz_mat_scalar_addmul_nmod_mat_fmpz(fmpz_mat_t B, const nmod_mat_t A, const fmpz_t c); void fmpz_mat_scalar_addmul_nmod_mat_ui(fmpz_mat_t B, const nmod_mat_t A, ulong c); void fmpz_mat_scalar_divexact_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); void fmpz_mat_scalar_divexact_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); void fmpz_mat_scalar_divexact_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); void fmpz_mat_scalar_mul_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp); void fmpz_mat_scalar_tdiv_q_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp); void fmpz_mat_scalar_smod(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t P); void fmpz_mat_scalar_mod_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t m); /* Multiplication */ void fmpz_mat_mul(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void fmpz_mat_mul_classical(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void fmpz_mat_mul_waksman(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void fmpz_mat_mul_strassen(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); #define fmpz_mat_mul_classical_inline _Pragma("GCC error \"'fmpz_mat_mul_classical_inline' is deprecated. Use 'fmpz_mat_mul_classical' instead.\"") void _fmpz_mat_mul_fft(fmpz_mat_t C, const fmpz_mat_t A, slong abits, const fmpz_mat_t B, slong bbits, int sign); void fmpz_mat_mul_fft(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_mul_multi_mod(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, int sign, flint_bitcnt_t Cbits); void fmpz_mat_mul_multi_mod(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); int _fmpz_mat_mul_blas(fmpz_mat_t C, const fmpz_mat_t A, flint_bitcnt_t Abits, const fmpz_mat_t B, flint_bitcnt_t Bbits, int sign, flint_bitcnt_t Cbits); int fmpz_mat_mul_blas(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_mul_small_1(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_mul_small_2a(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_mul_small_2b(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_mul_small_internal(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, flint_bitcnt_t Cbits); void _fmpz_mat_mul_small(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_mul_double_word(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_mul_double_word_internal(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, int sign, flint_bitcnt_t bits); void fmpz_mat_sqr_bodrato(fmpz_mat_t B, const fmpz_mat_t A); void fmpz_mat_sqr(fmpz_mat_t B, const fmpz_mat_t A); void fmpz_mat_pow(fmpz_mat_t B, const fmpz_mat_t A, ulong exp); void fmpz_mat_mul_fmpz_vec(fmpz * c, const fmpz_mat_t A, const fmpz * b, slong blen); void fmpz_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mat_t A, const fmpz * const * b, slong blen); void fmpz_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mat_t B); void fmpz_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mat_t B); /* Kronecker product */ void fmpz_mat_kronecker_product(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); /* Content */ void fmpz_mat_content(fmpz_t ret, const fmpz_mat_t A); /* Permutations */ FMPZ_MAT_INLINE void fmpz_mat_swap_rows(fmpz_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !fmpz_mat_is_empty(mat)) { if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(fmpz *, mat->rows[r], mat->rows[s]); } } void fmpz_mat_invert_rows(fmpz_mat_t mat, slong * perm); void fmpz_mat_invert_cols(fmpz_mat_t mat, slong * perm); /* Gaussian elimination *****************************************************/ slong fmpz_mat_find_pivot_any(const fmpz_mat_t mat, slong start_row, slong end_row, slong c); slong fmpz_mat_find_pivot_smallest(const fmpz_mat_t mat, slong start_row, slong end_row, slong c); slong fmpz_mat_fflu(fmpz_mat_t B, fmpz_t den, slong * perm, const fmpz_mat_t A, int rank_check); slong fmpz_mat_rank_small_inplace(fmpz_mat_t B); slong fmpz_mat_rref(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); slong fmpz_mat_rref_fflu(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); slong fmpz_mat_rref_mul(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); int fmpz_mat_is_in_rref_with_rank(const fmpz_mat_t A, const fmpz_t den, slong rank); /* Modular Howell and strong echelon form ***********************************/ slong fmpz_mat_howell_form_mod(fmpz_mat_t A, const fmpz_t mod); void fmpz_mat_strong_echelon_form_mod(fmpz_mat_t A, const fmpz_t mod); /* Trace ********************************************************************/ void fmpz_mat_trace(fmpz_t trace, const fmpz_mat_t mat); /* Determinant **************************************************************/ void fmpz_mat_det(fmpz_t det, const fmpz_mat_t A); void fmpz_mat_det_cofactor(fmpz_t det, const fmpz_mat_t A); void fmpz_mat_det_bareiss(fmpz_t det, const fmpz_mat_t A); void fmpz_mat_det_modular(fmpz_t det, const fmpz_mat_t A, int proved); void fmpz_mat_det_modular_accelerated(fmpz_t det, const fmpz_mat_t A, int proved); void fmpz_mat_det_modular_given_divisor(fmpz_t det, const fmpz_mat_t A, const fmpz_t d, int proved); void fmpz_mat_det_bound(fmpz_t bound, const fmpz_mat_t A); void fmpz_mat_det_bound_nonzero(fmpz_t bound, const fmpz_mat_t A); void fmpz_mat_det_divisor(fmpz_t d, const fmpz_mat_t A); /* Transforms */ void fmpz_mat_similarity(fmpz_mat_t A, slong r, fmpz_t d); /* Characteristic polynomial ************************************************/ void _fmpz_mat_charpoly_berkowitz(fmpz * rop, const fmpz_mat_t op); void fmpz_mat_charpoly_berkowitz(fmpz_poly_t cp, const fmpz_mat_t mat); void _fmpz_mat_charpoly_modular(fmpz * rop, const fmpz_mat_t op); void fmpz_mat_charpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat); FMPZ_MAT_INLINE void _fmpz_mat_charpoly(fmpz * cp, const fmpz_mat_t mat) { _fmpz_mat_charpoly_modular(cp, mat); } FMPZ_MAT_INLINE void fmpz_mat_charpoly(fmpz_poly_t cp, const fmpz_mat_t mat) { if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_charpoly). Non-square matrix.\n"); } fmpz_mat_charpoly_modular(cp, mat); } /* Characteristic polynomial ************************************************/ slong _fmpz_mat_minpoly_modular(fmpz * rop, const fmpz_mat_t op); void fmpz_mat_minpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat); FMPZ_MAT_INLINE slong _fmpz_mat_minpoly(fmpz * cp, const fmpz_mat_t mat) { return _fmpz_mat_minpoly_modular(cp, mat); } FMPZ_MAT_INLINE void fmpz_mat_minpoly(fmpz_poly_t cp, const fmpz_mat_t mat) { if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_minpoly). Non-square matrix.\n"); } fmpz_mat_minpoly_modular(cp, mat); } /* Rank **********************************************************************/ slong fmpz_mat_rank(const fmpz_mat_t A); /* Nonsingular solving *******************************************************/ void fmpz_mat_solve_bound(fmpz_t N, fmpz_t D, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_solve_cramer(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_solve_fflu_precomp(fmpz_mat_t X, const slong * perm, const fmpz_mat_t FFLU, const fmpz_mat_t B); mp_limb_t fmpz_mat_find_good_prime_and_invert(nmod_mat_t Ainv, const fmpz_mat_t A, const fmpz_t det_bound); mp_limb_t * fmpz_mat_dixon_get_crt_primes(slong * num_primes, const fmpz_mat_t A, mp_limb_t p); void _fmpz_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_mat_t A, const fmpz_mat_t B, const nmod_mat_t Ainv, mp_limb_t p, const fmpz_t N, const fmpz_t D); int fmpz_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_mat_t A, const fmpz_mat_t B); void _fmpz_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B, const nmod_mat_t Ainv, mp_limb_t p, const fmpz_t N, const fmpz_t D); int fmpz_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_solve_multi_mod_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_can_solve_multi_mod_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_can_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); int fmpz_mat_can_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); /* Nullspace *****************************************************************/ slong fmpz_mat_nullspace(fmpz_mat_t res, const fmpz_mat_t mat); /* Inverse *******************************************************************/ int fmpz_mat_inv(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); /* Modular reduction and reconstruction **************************************/ void fmpz_mat_set_nmod_mat(fmpz_mat_t A, const nmod_mat_t Amod); void fmpz_mat_set_nmod_mat_unsigned(fmpz_mat_t A, const nmod_mat_t Amod); void fmpz_mat_get_nmod_mat(nmod_mat_t Amod, const fmpz_mat_t A); void fmpz_mat_CRT_ui(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_t m1, const nmod_mat_t mat2, int sign); #ifdef FMPZ_H void fmpz_mat_multi_mod_ui_precomp(nmod_mat_t * residues, slong nres, const fmpz_mat_t mat, const fmpz_comb_t comb, fmpz_comb_temp_t temp); void fmpz_mat_multi_CRT_ui_precomp(fmpz_mat_t mat, nmod_mat_t * const residues, slong nres, const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign); #endif void fmpz_mat_multi_mod_ui(nmod_mat_t * residues, slong nres, const fmpz_mat_t mat); void fmpz_mat_multi_CRT_ui(fmpz_mat_t mat, nmod_mat_t * const residues, slong nres, int sign); /* HNF and SNF **************************************************************/ void fmpz_mat_hnf(fmpz_mat_t H, const fmpz_mat_t A); void fmpz_mat_hnf_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A); void fmpz_mat_hnf_classical(fmpz_mat_t H, const fmpz_mat_t A); void fmpz_mat_hnf_xgcd(fmpz_mat_t H, const fmpz_mat_t A); void fmpz_mat_hnf_minors(fmpz_mat_t H, const fmpz_mat_t A); void fmpz_mat_hnf_minors_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A); void fmpz_mat_hnf_modular(fmpz_mat_t H, const fmpz_mat_t A, const fmpz_t D); void fmpz_mat_hnf_modular_eldiv(fmpz_mat_t A, const fmpz_t D); void fmpz_mat_hnf_pernet_stein(fmpz_mat_t H, const fmpz_mat_t A, flint_rand_t state); int fmpz_mat_is_in_hnf(const fmpz_mat_t A); void fmpz_mat_snf(fmpz_mat_t S, const fmpz_mat_t A); void fmpz_mat_snf_diagonal(fmpz_mat_t S, const fmpz_mat_t A); void fmpz_mat_snf_kannan_bachem(fmpz_mat_t S, const fmpz_mat_t A); void fmpz_mat_snf_iliopoulos(fmpz_mat_t S, const fmpz_mat_t A, const fmpz_t mod); int fmpz_mat_is_in_snf(const fmpz_mat_t A); /* Special matrices **********************************************************/ int fmpz_mat_is_hadamard(const fmpz_mat_t A); int fmpz_mat_hadamard(fmpz_mat_t A); /* Gram matrix **************************************************************/ void fmpz_mat_gram(fmpz_mat_t B, const fmpz_mat_t A); int fmpz_mat_is_spd(const fmpz_mat_t A); /* Conversions **************************************************************/ int fmpz_mat_get_d_mat(d_mat_t B, const fmpz_mat_t A); int fmpz_mat_get_d_mat_transpose(d_mat_t B, const fmpz_mat_t A); /* Cholesky Decomposition ****************************************************/ void fmpz_mat_chol_d(d_mat_t R, const fmpz_mat_t A); /* LLL ***********************************************************************/ int fmpz_mat_is_reduced(const fmpz_mat_t A, double delta, double eta); int fmpz_mat_is_reduced_gram(const fmpz_mat_t A, double delta, double eta); int fmpz_mat_is_reduced_with_removal(const fmpz_mat_t A, double delta, double eta, const fmpz_t gs_B, int newd); int fmpz_mat_is_reduced_gram_with_removal(const fmpz_mat_t A, double delta, double eta, const fmpz_t gs_B, int newd); /* Classical LLL *************************************************************/ void fmpz_mat_lll_original(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta); /* Modified LLL **************************************************************/ void fmpz_mat_lll_storjohann(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta); /* Column partitioning *******************************************************/ int fmpz_mat_col_partition(slong * part, fmpz_mat_t M, int short_circuit); /* Van Hoeij helper function *************************************************/ int fmpz_mat_next_col_van_hoeij(fmpz_mat_t M, fmpz_t P, fmpz_mat_t col, slong exp, slong U_exp); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mat/000077500000000000000000000000001461254215100152375ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mat/CRT_ui.c000066400000000000000000000023541461254215100165340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_CRT_ui(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_t m1, const nmod_mat_t mat2, int sign) { slong i, j; mp_limb_t c; mp_limb_t m2 = mat2->mod.n; mp_limb_t m2inv = mat2->mod.ninv; fmpz_t m1m2; c = fmpz_fdiv_ui(m1, m2); c = n_invmod(c, m2); if (c == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_CRT_ui). m1 not invertible modulo m2.\n"); } fmpz_init(m1m2); fmpz_mul_ui(m1m2, m1, m2); for (i = 0; i < mat1->r; i++) { for (j = 0; j < mat1->c; j++) _fmpz_CRT_ui_precomp(fmpz_mat_entry(res, i, j), fmpz_mat_entry(mat1, i, j), m1, nmod_mat_entry(mat2, i, j), m2, m2inv, m1m2, c, sign); } fmpz_clear(m1m2); } flint-3.1.3/src/fmpz_mat/add.c000066400000000000000000000012371461254215100161360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_add(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2) { slong i; if (res->c < 1) return; for (i = 0; i < res->r; i++) _fmpz_vec_add(res->rows[i], mat1->rows[i], mat2->rows[i], res->c); } flint-3.1.3/src/fmpz_mat/can_solve.c000066400000000000000000000012631461254215100173560ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "perm.h" int fmpz_mat_can_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { if (fmpz_mat_nrows(A) <= 15) return fmpz_mat_can_solve_fflu(X, den, A, B); else return fmpz_mat_can_solve_multi_mod_den(X, den, A, B); } flint-3.1.3/src/fmpz_mat/can_solve_fflu.c000066400000000000000000000047041461254215100203750ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" void _fmpz_mat_window_with_perm_init(fmpz_mat_t Ap, slong * perm, const fmpz_mat_t A, slong start) { slong i, n = A->r; Ap->entries = NULL; if (n > start) Ap->rows = (fmpz **) flint_malloc((n - start)*sizeof(fmpz *)); else Ap->rows = NULL; for (i = 0; i < n - start; i++) Ap->rows[i] = A->rows[perm[start + i]]; Ap->r = n - start; Ap->c = A->c; } void _fmpz_mat_window_with_perm_clear(fmpz_mat_t Ap) { if (Ap->r != 0) flint_free(Ap->rows); } int fmpz_mat_can_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { fmpz_mat_t LU, Ap, Bp, P1, P2; slong n, rank, *perm; int result; if (A->r == 0) { fmpz_mat_zero(X); fmpz_one(den); return 1; } if (A->c == 0) { fmpz_mat_zero(X); result = fmpz_mat_is_zero(B); fmpz_set_ui(den, result); return result; } n = fmpz_mat_nrows(A); perm = _perm_init(n); fmpz_mat_init_set(LU, A); rank = fmpz_mat_fflu(LU, den, perm, LU, 0); result = !fmpz_is_zero(den) && fmpz_mat_solve_fflu_precomp(X, perm, LU, B); if (result) { if (_perm_parity(perm, n)) { fmpz_neg(den, den); fmpz_mat_neg(X, X); } if (rank < n) { _fmpz_mat_window_with_perm_init(Ap, perm, A, rank); _fmpz_mat_window_with_perm_init(Bp, perm, B, rank); fmpz_mat_init(P1, fmpz_mat_nrows(Ap), fmpz_mat_ncols(X)); fmpz_mat_init(P2, fmpz_mat_nrows(Bp), fmpz_mat_ncols(Bp)); fmpz_mat_mul(P1, Ap, X); fmpz_mat_scalar_mul_fmpz(P2, Bp, den); result = fmpz_mat_equal(P1, P2); fmpz_mat_clear(P1); fmpz_mat_clear(P2); _fmpz_mat_window_with_perm_clear(Ap); _fmpz_mat_window_with_perm_clear(Bp); } } else fmpz_zero(den); _perm_clear(perm); fmpz_mat_clear(LU); return result; } flint-3.1.3/src/fmpz_mat/can_solve_multi_mod_den.c000066400000000000000000000020311461254215100222470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" int fmpz_mat_can_solve_multi_mod_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { int success; fmpq_mat_t Q; if (A->r != B->r || A->c != X->r || X->c != B->c) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_can_solve_multi_mod_den). Incompatible matrix dimensions.\n"); } fmpq_mat_init(Q, fmpz_mat_nrows(X), fmpz_mat_ncols(X)); success = fmpq_mat_can_solve_fmpz_mat_multi_mod(Q, A, B); if (success) fmpq_mat_get_fmpz_mat_matwise(X, den, Q); fmpq_mat_clear(Q); return success; } flint-3.1.3/src/fmpz_mat/charpoly.c000066400000000000000000000124501461254215100172260ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "gr.h" #include "gr_mat.h" /* Assumes that \code{mat} is an $n \times n$ matrix and sets \code{(cp,n+1)} to its characteristic polynomial. Employs a division-free algorithm using $O(n^4)$ ring operations. */ void _fmpz_mat_charpoly_berkowitz(fmpz *cp, const fmpz_mat_t mat) { gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); GR_MUST_SUCCEED(_gr_mat_charpoly_berkowitz(cp, (const gr_mat_struct *) mat, ctx)); } void fmpz_mat_charpoly_berkowitz(fmpz_poly_t cp, const fmpz_mat_t mat) { fmpz_poly_fit_length(cp, mat->r + 1); _fmpz_poly_set_length(cp, mat->r + 1); _fmpz_mat_charpoly_berkowitz(cp->coeffs, mat); } #define CHARPOLY_M_LOG2E 1.44269504088896340736 /* log2(e) */ static inline long double _log2(const long double x) { return log(x) * CHARPOLY_M_LOG2E; } static void _fmpz_mat_charpoly_small_2x2(fmpz *rop, fmpz ** const x) { fmpz_one (rop + 2); fmpz_add (rop + 1, &x[0][0], &x[1][1]); fmpz_neg (rop + 1, rop + 1); fmpz_mul (rop + 0, &x[0][0], &x[1][1]); fmpz_submul(rop + 0, &x[0][1], &x[1][0]); } static void _fmpz_mat_charpoly_small_3x3(fmpz *rop, fmpz ** const x) { fmpz a[2]; fmpz_init(a + 0); fmpz_init(a + 1); fmpz_mul( a + 0, &x[1][0], &x[2][1]); fmpz_submul(a + 0, &x[1][1], &x[2][0]); fmpz_mul( rop + 0, a + 0, &x[0][2]); fmpz_neg( rop + 0, rop + 0); fmpz_mul( rop + 1, &x[2][0], &x[0][2]); fmpz_neg( rop + 1, rop + 1); fmpz_mul( a + 0, &x[1][2], &x[2][0]); fmpz_submul(a + 0, &x[1][0], &x[2][2]); fmpz_submul(rop + 0, a + 0, &x[0][1]); fmpz_submul(rop + 1, &x[1][0], &x[0][1]); fmpz_mul( a + 0, &x[1][1], &x[2][2]); fmpz_add( a + 1, &x[1][1], &x[2][2]); fmpz_neg( a + 1, a + 1); fmpz_submul(a + 0, &x[1][2], &x[2][1]); fmpz_submul(rop + 0, a + 0, &x[0][0]); fmpz_submul(rop + 1, a + 1, &x[0][0]); fmpz_add( rop + 1, rop + 1, a + 0); fmpz_sub( rop + 2, a + 1, &x[0][0]); fmpz_one( rop + 3); fmpz_clear(a + 0); fmpz_clear(a + 1); } void _fmpz_mat_charpoly_small(fmpz * rop, const fmpz_mat_t op) { if (op->r == 0) { fmpz_one(rop + 0); } else if (op->r == 1) { fmpz_one(rop + 1); fmpz_neg(rop + 0, &(op->rows[0][0])); } else if (op->r == 2) { _fmpz_mat_charpoly_small_2x2(rop, op->rows); } else /* op->r == 3 */ { _fmpz_mat_charpoly_small_3x3(rop, op->rows); } } void _fmpz_mat_charpoly_modular(fmpz * rop, const fmpz_mat_t op) { const slong n = op->r; if (n < 4) { _fmpz_mat_charpoly_small(rop, op); } else { /* If $A$ is an $n \times n$ matrix with $n \geq 4$ and coefficients bounded in absolute value by $B > 1$ then the coefficients of the characteristic polynomial have less than $\ceil{n/2 (\log_2(n) + \log_2(B^2) + 1.6669)}$ bits. See Lemma 4.1 in Dumas, Pernet, and Wan, "Efficient computation of the characteristic polynomial", 2008. */ slong bound; slong pbits = FLINT_BITS - 1; mp_limb_t p = (UWORD(1) << pbits); fmpz_t m; /* Determine the bound in bits */ { slong i, j; fmpz *ptr; double t; ptr = fmpz_mat_entry(op, 0, 0); for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (fmpz_cmpabs(ptr, fmpz_mat_entry(op, i, j)) < 0) ptr = fmpz_mat_entry(op, i, j); if (fmpz_bits(ptr) == 0) /* Zero matrix */ { for (i = 0; i < n; i++) fmpz_zero(rop + i); fmpz_set_ui(rop + n, 1); return; } t = (fmpz_bits(ptr) <= FLINT_D_BITS) ? _log2(FLINT_ABS(fmpz_get_d(ptr))) : fmpz_bits(ptr); bound = ceil( (n / 2.0) * (_log2(n) + 2.0 * t + 1.6669) ); } fmpz_init_set_ui(m, 1); for ( ; fmpz_bits(m) < bound; ) { nmod_mat_t mat; nmod_poly_t poly; p = n_nextprime(p, 0); nmod_mat_init(mat, n, n, p); nmod_poly_init(poly, p); fmpz_mat_get_nmod_mat(mat, op); nmod_mat_charpoly(poly, mat); _fmpz_poly_CRT_ui(rop, rop, n + 1, m, poly->coeffs, n + 1, poly->mod.n, poly->mod.ninv, 1); fmpz_mul_ui(m, m, p); nmod_mat_clear(mat); nmod_poly_clear(poly); } fmpz_clear(m); } } void fmpz_mat_charpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat) { fmpz_poly_fit_length(cp, mat->r + 1); _fmpz_poly_set_length(cp, mat->r + 1); _fmpz_mat_charpoly_modular(cp->coeffs, mat); } flint-3.1.3/src/fmpz_mat/chol_d.c000066400000000000000000000026611461254215100166400ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif void fmpz_mat_chol_d(d_mat_t R, const fmpz_mat_t A) { slong i, k, j, r = A->r; if (A->r != A->c || R->r != A->r || R->c != A->c) { flint_throw(FLINT_ERROR, "(fmpz_mat_chol_d): Incompatible dimensions.\n"); } if (A->r == 0) { return; } for (i = 0; i < r; i++) { for (j = 0; j < i + 1; j++) { double s = 0; for (k = 0; k < j; k++) { s += d_mat_entry(R, i, k) * d_mat_entry(R, j, k); } if (i == j) d_mat_entry(R, i, j) = sqrt(fmpz_get_d(fmpz_mat_entry(A, i, i)) - s); else d_mat_entry(R, i, j) = (fmpz_get_d(fmpz_mat_entry(A, i, j)) - s) / d_mat_entry(R, j, j); } } } flint-3.1.3/src/fmpz_mat/clear.c000066400000000000000000000014571461254215100165000ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_clear(fmpz_mat_t mat) { if (mat->entries) { slong i; for (i = 0; i < mat->r * mat->c; i++) fmpz_clear(mat->entries + i); /* Clear all coefficients */ flint_free(mat->entries); /* Clean up array of entries */ flint_free(mat->rows); /* Clean up row array */ } else if (mat->r != 0) flint_free(mat->rows); } flint-3.1.3/src/fmpz_mat/col_partition.c000066400000000000000000000053771461254215100202650ustar00rootroot00000000000000/* Copyright (C) 2011, 2016 William Hart Copyright (C) 2011 Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_mat.h" typedef struct { ulong col; ulong hash; } col_hash_struct; typedef col_hash_struct * col_hash_ptr; typedef const col_hash_struct * col_hash_srcptr; /* cheap hash of all columns of M */ void fmpz_mat_col_hash(col_hash_ptr col_h, fmpz_mat_t M) { ulong i, j, hash; for (i = 0; i < M->c; i++) { col_h[i].col = i; hash = 0; for (j = 0; j < M->r; j++) { hash ^= fmpz_get_ui(M->rows[j] + i); hash = (hash << 1) + (hash >> (FLINT_BITS - 1)); } col_h[i].hash = hash; } } int fmpz_mat_col_hash_compare(const void * a, const void * b) { col_hash_srcptr col_a = a; col_hash_srcptr col_b = b; if (col_a->hash == col_b->hash) return 0; return 2*(col_a->hash > col_b->hash) - 1; } int fmpz_mat_col_partition(slong * part, fmpz_mat_t M, int short_circuit) { slong start = 0, new_start = 0, upto = 1, p = 0, i, count; ulong hash; col_hash_ptr col_h; TMP_INIT; TMP_START; col_h = TMP_ALLOC(sizeof(col_hash_struct) * M->c); fmpz_mat_col_hash(col_h, M); qsort(col_h, M->c, sizeof(col_hash_struct), fmpz_mat_col_hash_compare); if (short_circuit) { hash = col_h[0].hash; count = 1; for (i = 1; i < M->c; i++) { if (col_h[i].hash != hash) { count++; hash = col_h[i].hash; } } if (count > M->r) goto cleanup; } for (i = 0; i < M->c; i++) part[i] = -WORD(1); while (start < M->c) { new_start = start; p++; if (short_circuit && p > M->r) { p = 0; /* too many partitions */ goto cleanup; } part[col_h[start].col] = p; for (upto = start + 1; upto < M->c && col_h[upto].hash == col_h[start].hash; upto++) { if (part[col_h[upto].col] == -WORD(1)) { if (!fmpz_mat_equal_col(M, col_h[start].col, col_h[upto].col)) { if (new_start == start) new_start = upto; } else part[col_h[upto].col] = p; } } start = start == new_start ? upto : new_start; } cleanup: TMP_END; return p; } flint-3.1.3/src/fmpz_mat/concat.c000066400000000000000000000030061461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_concat_horizontal(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { fmpz_set(fmpz_mat_entry(res, i, j), fmpz_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { fmpz_set(fmpz_mat_entry(res, i, j + c1), fmpz_mat_entry(mat2, i, j)); } } } void fmpz_mat_concat_vertical(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { fmpz_set(fmpz_mat_entry(res, i, j), fmpz_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { fmpz_set(fmpz_mat_entry(res, i + r1, j), fmpz_mat_entry(mat2, i, j)); } } } flint-3.1.3/src/fmpz_mat/content.c000066400000000000000000000013571461254215100170630ustar00rootroot00000000000000/* Copyright (C) 2015 Dharak Kharod This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_content(fmpz_t mat_gcd, const fmpz_mat_t A) { slong rows = A->r; slong cols = A->c; slong i, j; fmpz_set_si(mat_gcd,0); for (i = 0; i < rows; i++ ) { for (j = 0; j < cols; j++) { fmpz_gcd(mat_gcd,mat_gcd, fmpz_mat_entry(A, i, j)); if (fmpz_is_one(mat_gcd)) { return; } } } return; } flint-3.1.3/src/fmpz_mat/det.c000066400000000000000000000017521461254215100161640ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" void fmpz_mat_det(fmpz_t det, const fmpz_mat_t A) { slong dim = A->r; if (dim != A->c) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_det). Non-square matrix.\n"); } if (dim < 5) fmpz_mat_det_cofactor(det, A); else if (dim < 25) fmpz_mat_det_bareiss(det, A); else if (dim < 60) fmpz_mat_det_modular(det, A, 1); else { slong bits = fmpz_mat_max_bits(A); if (dim < FLINT_ABS(bits)) fmpz_mat_det_modular(det, A, 1); else fmpz_mat_det_modular_accelerated(det, A, 1); } } flint-3.1.3/src/fmpz_mat/det_bareiss.c000066400000000000000000000016721461254215100176750ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "perm.h" void _fmpz_mat_det_bareiss(fmpz_t det, fmpz_mat_t tmp) { slong *perm, n = fmpz_mat_nrows(tmp); perm = _perm_init(n); fmpz_mat_fflu(tmp, det, perm, tmp, 1); if (_perm_parity(perm, n) == 1) fmpz_neg(det, det); _perm_clear(perm); } void fmpz_mat_det_bareiss(fmpz_t det, const fmpz_mat_t A) { fmpz_mat_t tmp; if (A->r < 1) { fmpz_one(det); return; } fmpz_mat_init_set(tmp, A); _fmpz_mat_det_bareiss(det, tmp); fmpz_mat_clear(tmp); } flint-3.1.3/src/fmpz_mat/det_bound.c000066400000000000000000000023601461254215100173470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" static void fmpz_mat_det_bound_inner(fmpz_t bound, const fmpz_mat_t A, int zero_cols) { fmpz_t p, s, t; slong i, j; fmpz_init(p); fmpz_init(s); fmpz_init(t); fmpz_one(p); for (i = 0; i < A->r; i++) { fmpz_zero(s); for (j = 0; j < A->c; j++) fmpz_addmul(s, A->rows[i] + j, A->rows[i] + j); fmpz_sqrtrem(s, t, s); if (!fmpz_is_zero(t)) fmpz_add_ui(s, s, UWORD(1)); if (zero_cols || !fmpz_is_zero(s)) fmpz_mul(p, p, s); } fmpz_set(bound, p); fmpz_clear(p); fmpz_clear(s); fmpz_clear(t); } void fmpz_mat_det_bound(fmpz_t bound, const fmpz_mat_t A) { fmpz_mat_det_bound_inner(bound, A, 1); } void fmpz_mat_det_bound_nonzero(fmpz_t bound, const fmpz_mat_t A) { fmpz_mat_det_bound_inner(bound, A, 0); } flint-3.1.3/src/fmpz_mat/det_cofactor.c000066400000000000000000000046201461254215100200410ustar00rootroot00000000000000/* Copyright (C) 2010,2011,2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #define E(i,j) fmpz_mat_entry(A, i, j) static void _fmpz_mat_det_cofactor_2x2(fmpz_t det, const fmpz_mat_t A) { fmpz_fmms(det, E(0,0), E(1,1), E(0,1), E(1,0)); } static void _fmpz_mat_det_cofactor_3x3(fmpz_t det, const fmpz_mat_t A) { fmpz_t a; fmpz_init(a); fmpz_fmms(a, E(1,0), E(2,1), E(1,1), E(2,0)); fmpz_mul(det, a, E(0,2)); fmpz_fmms(a, E(1,2), E(2,0), E(1,0), E(2,2)); fmpz_addmul(det, a, E(0,1)); fmpz_fmms(a, E(1,1), E(2,2), E(1,2), E(2,1)); fmpz_addmul(det, a, E(0,0)); fmpz_clear(a); } static void _fmpz_mat_det_cofactor_4x4(fmpz_t det, const fmpz_mat_t A) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); fmpz_fmms(a, E(0,3), E(1,2), E(0,2), E(1,3)); fmpz_fmms(b, E(2,1), E(3,0), E(2,0), E(3,1)); fmpz_mul(det, a, b); fmpz_fmms(a, E(0,1), E(1,3), E(0,3), E(1,1)); fmpz_fmms(b, E(2,2), E(3,0), E(2,0), E(3,2)); fmpz_addmul(det, a, b); fmpz_fmms(a, E(0,2), E(1,1), E(0,1), E(1,2)); fmpz_fmms(b, E(2,3), E(3,0), E(2,0), E(3,3)); fmpz_addmul(det, a, b); fmpz_fmms(a, E(0,3), E(1,0), E(0,0), E(1,3)); fmpz_fmms(b, E(2,2), E(3,1), E(2,1), E(3,2)); fmpz_addmul(det, a, b); fmpz_fmms(a, E(0,0), E(1,2), E(0,2), E(1,0)); fmpz_fmms(b, E(2,3), E(3,1), E(2,1), E(3,3)); fmpz_addmul(det, a, b); fmpz_fmms(a, E(0,1), E(1,0), E(0,0), E(1,1)); fmpz_fmms(b, E(2,3), E(3,2), E(2,2), E(3,3)); fmpz_addmul(det, a, b); fmpz_clear(a); fmpz_clear(b); } void fmpz_mat_det_cofactor(fmpz_t det, const fmpz_mat_t A) { switch (fmpz_mat_nrows(A)) { case 0: fmpz_one(det); break; case 1: fmpz_set(det, fmpz_mat_entry(A, 0, 0)); break; case 2: _fmpz_mat_det_cofactor_2x2(det, A); break; case 3: _fmpz_mat_det_cofactor_3x3(det, A); break; case 4: _fmpz_mat_det_cofactor_4x4(det, A); break; default: flint_throw(FLINT_ERROR, "Exception (fmpz_mat_det_cofactor). dim > 4 not implemented."); } } flint-3.1.3/src/fmpz_mat/det_divisor.c000066400000000000000000000027071461254215100177240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq.h" void fmpz_mat_det_divisor(fmpz_t d, const fmpz_mat_t A) { fmpz_mat_t X, B; fmpz_t t, u, v, mod; slong i, n; int success; n = A->r; fmpz_mat_init(B, n, 1); fmpz_mat_init(X, n, 1); fmpz_init(t); fmpz_init(u); fmpz_init(v); fmpz_init(mod); /* Create a "random" vector */ for (i = 0; i < n; i++) { fmpz_set_si(fmpz_mat_entry(B, i, 0), 2*(i % 2) - 1); } success = fmpz_mat_solve_dixon(X, mod, A, B); if (success) { fmpz_one(d); for (i = 0; i < n; i++) { fmpz_mul(t, d, fmpz_mat_entry(X, i, 0)); fmpz_fdiv_qr(u, t, t, mod); if (!_fmpq_reconstruct_fmpz(u, v, t, mod)) { flint_throw(FLINT_ERROR, "(fmpz_mat_det_divisor): Rational reconstruction failed.\n"); } fmpz_mul(d, v, d); } } else { fmpz_zero(d); } fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_clear(t); fmpz_clear(u); fmpz_clear(v); fmpz_clear(mod); } flint-3.1.3/src/fmpz_mat/det_modular.c000066400000000000000000000011611461254215100177010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_det_modular(fmpz_t det, const fmpz_mat_t A, int proved) { fmpz_t d; fmpz_init(d); fmpz_one(d); fmpz_mat_det_modular_given_divisor(det, A, d, proved); fmpz_clear(d); } flint-3.1.3/src/fmpz_mat/det_modular_accelerated.c000066400000000000000000000012141461254215100222140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_det_modular_accelerated(fmpz_t det, const fmpz_mat_t A, int proved) { fmpz_t d; fmpz_init(d); fmpz_mat_det_divisor(d, A); fmpz_mat_det_modular_given_divisor(det, A, d, proved); fmpz_clear(d); } flint-3.1.3/src/fmpz_mat/det_modular_given_divisor.c000066400000000000000000000047331461254215100226400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" /* Enable to exercise corner cases */ #define DEBUG_USE_SMALL_PRIMES 0 static mp_limb_t next_good_prime(const fmpz_t d, mp_limb_t p) { mp_limb_t r = 0; while (r == 0) { p = n_nextprime(p, 0); r = fmpz_fdiv_ui(d, p); } return p; } void fmpz_mat_det_modular_given_divisor(fmpz_t det, const fmpz_mat_t A, const fmpz_t d, int proved) { fmpz_t bound, prod, stable_prod, x, xnew; mp_limb_t p, xmod; nmod_mat_t Amod; slong n = A->r; if (n == 0) { fmpz_one(det); return; } if (fmpz_is_zero(d)) { fmpz_zero(det); return; } fmpz_init(bound); fmpz_init(prod); fmpz_init(stable_prod); fmpz_init(x); fmpz_init(xnew); /* Bound x = det(A) / d */ fmpz_mat_det_bound(bound, A); fmpz_mul_ui(bound, bound, UWORD(2)); /* accommodate sign */ fmpz_cdiv_q(bound, bound, d); nmod_mat_init(Amod, n, n, 2); fmpz_zero(x); fmpz_one(prod); #if DEBUG_USE_SMALL_PRIMES p = UWORD(1); #else p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; #endif /* Compute x = det(A) / d */ while (fmpz_cmp(prod, bound) <= 0) { p = next_good_prime(d, p); nmod_mat_set_mod(Amod, p); fmpz_mat_get_nmod_mat(Amod, A); /* Compute x = det(A) / d mod p */ xmod = _nmod_mat_det(Amod); xmod = n_mulmod2_preinv(xmod, n_invmod(fmpz_fdiv_ui(d, p), p), Amod->mod.n, Amod->mod.ninv); fmpz_CRT_ui(xnew, x, prod, xmod, p, 1); if (fmpz_equal(xnew, x)) { fmpz_mul_ui(stable_prod, stable_prod, p); if (!proved && fmpz_bits(stable_prod) > 100) break; } else { fmpz_set_ui(stable_prod, p); } fmpz_mul_ui(prod, prod, p); fmpz_set(x, xnew); } /* det(A) = x * d */ fmpz_mul(det, x, d); nmod_mat_clear(Amod); fmpz_clear(bound); fmpz_clear(prod); fmpz_clear(stable_prod); fmpz_clear(x); fmpz_clear(xnew); } flint-3.1.3/src/fmpz_mat/equal.c000066400000000000000000000023311461254215100165110ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" int fmpz_mat_equal(const fmpz_mat_t mat1, const fmpz_mat_t mat2) { slong j; if (mat1->r != mat2->r || mat1->c != mat2->c) { return 0; } if (mat1->r == 0 || mat1->c == 0) return 1; for (j = 0; j < mat1->r; j++) { if (!_fmpz_vec_equal(mat1->rows[j], mat2->rows[j], mat1->c)) { return 0; } } return 1; } int fmpz_mat_equal_col(fmpz_mat_t M, slong m, slong n) { slong i; for (i = 0; i < M->r; i++) { if (!fmpz_equal(M->rows[i] + m, M->rows[i] + n)) return 0; } return 1; } int fmpz_mat_equal_row(fmpz_mat_t M, slong m, slong n) { slong i; for (i = 0; i < M->c; i++) { if (!fmpz_equal(M->rows[m] + i, M->rows[n] + i)) return 0; } return 1; } flint-3.1.3/src/fmpz_mat/fflu.c000066400000000000000000000116501461254215100163420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" #define E(j,k) fmpz_mat_entry(B,j,k) slong fmpz_mat_fflu(fmpz_mat_t B, fmpz_t den, slong * perm, const fmpz_mat_t A, int rank_check) { slong m, n, j, k, rank, r, pivot_row, pivot_col, norm = 0; ulong p1h, p1l, p2h, p2l, uden = 0, dinv = 0, quo; ulong FLINT_SET_BUT_UNUSED(rem); slong mbits = fmpz_mat_max_bits(A); int small = FLINT_ABS(mbits) <= SMALL_FMPZ_BITCOUNT_MAX; int dsgn = 0, sgn, den1 = 0, work_to_do; /* we set den in case matrix has no pivots */ fmpz_one(den); if (fmpz_mat_is_empty(A)) return 0; fmpz_mat_set(B, A); m = B->r; n = B->c; rank = pivot_row = pivot_col = 0; while (pivot_row < m && pivot_col < n) { r = fmpz_mat_find_pivot_any(B, pivot_row, m, pivot_col); if (r == -1) { if (rank_check) { fmpz_zero(den); rank = 0; break; } pivot_col++; continue; } else if (r != pivot_row) fmpz_mat_swap_rows(B, perm, pivot_row, r); rank++; if (small) { for (j = pivot_row + 1; j < m; j++) { work_to_do = !den1 || !fmpz_is_zero(E(j, pivot_col)) || !fmpz_is_one(E(pivot_row, pivot_col)); if (work_to_do) { for (k = pivot_col + 1; k < n; k++) { smul_ppmm(p1h, p1l, *E(j, k), *E(pivot_row, pivot_col)); smul_ppmm(p2h, p2l, *E(j, pivot_col), *E(pivot_row, k)); sub_ddmmss(p1h, p1l, p1h, p1l, p2h, p2l); sgn = 0 > (slong) p1h; if (sgn) /* take absolute value */ sub_ddmmss(p1h, p1l, UWORD(0), UWORD(0), p1h, p1l); if (pivot_row > 0 && !den1) { if (p1h >= uden) { fmpz_set_uiui(E(j, k), p1h, p1l); if (sgn) fmpz_neg(E(j, k), E(j, k)); fmpz_divexact(E(j, k), E(j, k), den); small = 0; } else { udiv_qrnnd_preinv(quo, rem, (p1h << norm) + r_shift(p1l, (FLINT_BITS - norm)), p1l << norm, uden << norm, dinv); if (sgn ^ dsgn) fmpz_neg_ui(E(j, k), quo); else fmpz_set_ui(E(j, k), quo); if (quo > COEFF_MAX) small = 0; } } else { if (p1h > 0) { fmpz_set_uiui(E(j, k), p1h, p1l); small = 0; } else { fmpz_set_ui(E(j, k), p1l); if (p1l > COEFF_MAX) small = 0; } if (sgn) fmpz_neg(E(j, k), E(j, k)); } } } } } else { for (j = pivot_row + 1; j < m; j++) { for (k = pivot_col + 1; k < n; k++) { fmpz_mul(E(j, k), E(j, k), E(pivot_row, pivot_col)); fmpz_submul(E(j, k), E(j, pivot_col), E(pivot_row, k)); if (pivot_row > 0 && !den1) fmpz_divexact(E(j, k), E(j, k), den); } } } fmpz_set(den, E(pivot_row, pivot_col)); den1 = fmpz_is_one(den); if (small) { uden = FLINT_ABS((slong)(*den)); dsgn = 0 > (slong)(*den); norm = flint_clz(uden); dinv = n_preinvert_limb_prenorm(uden << norm); if (fmpz_sizeinbase(den, 2) > SMALL_FMPZ_BITCOUNT_MAX) small = 0; } pivot_row++; pivot_col++; } return rank; } flint-3.1.3/src/fmpz_mat/find_pivot_any.c000066400000000000000000000013151461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" slong fmpz_mat_find_pivot_any(const fmpz_mat_t mat, slong start_row, slong end_row, slong c) { slong r; for (r = start_row; r < end_row; r++) { if (!fmpz_is_zero(fmpz_mat_entry(mat, r, c))) return r; } return -1; } flint-3.1.3/src/fmpz_mat/find_pivot_smallest.c000066400000000000000000000017111461254215100214500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" slong fmpz_mat_find_pivot_smallest(const fmpz_mat_t mat, slong start_row, slong end_row, slong c) { slong r, smallest = -1; fmpz * currptr, * smallptr = NULL; for (r = start_row; r < end_row; r++) { currptr = fmpz_mat_entry(mat, r, c); if (!fmpz_is_zero(currptr)) { if (0 > smallest || fmpz_cmpabs(currptr, smallptr) < 0) { smallest = r; smallptr = currptr; } } } return smallest; } flint-3.1.3/src/fmpz_mat/fmpz_vec_mul.c000066400000000000000000000021131461254215100200660ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_fmpz_vec_mul( fmpz * c, const fmpz * a, slong alen, const fmpz_mat_t B) { slong i, j; slong len = FLINT_MIN(B->r, alen); for (i = B->c - 1; i >= 0; i--) { fmpz_zero(c + i); for (j = 0; j < len; j++) fmpz_addmul(c + i, a + j, fmpz_mat_entry(B, j, i)); } } void fmpz_mat_fmpz_vec_mul_ptr( fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mat_t B) { slong i, j; slong len = FLINT_MIN(B->r, alen); for (i = B->c - 1; i >= 0; i--) { fmpz_zero(c[i]); for (j = 0; j < len; j++) fmpz_addmul(c[i], a[j], fmpz_mat_entry(B, j, i)); } } flint-3.1.3/src/fmpz_mat/get.c000066400000000000000000000044201461254215100161620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_get_d_mat(d_mat_t B, const fmpz_mat_t A) { slong i, j; fmpz_t dmax; fmpz_init(dmax); fmpz_set_d(dmax, DBL_MAX); for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (fmpz_cmpabs(fmpz_mat_entry(A, i, j), dmax) > 0) { fmpz_clear(dmax); return -1; } d_mat_entry(B, i, j) = fmpz_get_d(fmpz_mat_entry(A, i, j)); } } fmpz_clear(dmax); return 0; } int fmpz_mat_get_d_mat_transpose(d_mat_t B, const fmpz_mat_t A) { slong i, j; fmpz_t dmax; fmpz_init(dmax); fmpz_set_d(dmax, DBL_MAX); for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (fmpz_cmpabs(fmpz_mat_entry(A, i, j), dmax) > 0) { fmpz_clear(dmax); return -1; } d_mat_entry(B, j, i) = fmpz_get_d(fmpz_mat_entry(A, i, j)); } } fmpz_clear(dmax); return 0; } void fmpz_mat_get_nmod_mat(nmod_mat_t Amod, const fmpz_mat_t A) { slong i, j; nmod_t mod = Amod->mod; if (fmpz_mat_is_square(A)) { int symmetric = fmpz_mat_is_square(A); for (i = 0; i < A->r; i++) { Amod->rows[i][i] = fmpz_get_nmod(A->rows[i]+i, mod); for (j = i + 1; j < A->c; j++) { Amod->rows[i][j] = fmpz_get_nmod(A->rows[i] + j, mod); if ((symmetric &= fmpz_equal(A->rows[j] + i, A->rows[i] + j))) Amod->rows[j][i] = Amod->rows[i][j]; else Amod->rows[j][i] = fmpz_get_nmod(A->rows[j] + i, mod); } } } else { for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) Amod->rows[i][j] = fmpz_get_nmod(A->rows[i] + j, mod); } } flint-3.1.3/src/fmpz_mat/gram.c000066400000000000000000000022541461254215100163340ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_gram(fmpz_mat_t B, const fmpz_mat_t A) { slong i, j, k; if (B->r != A->r || B->c != A->r) { flint_throw(FLINT_ERROR, "(fmpz_mat_gram): Incompatible dimensions.\n"); } if(B == A) { fmpz_mat_t t; fmpz_mat_init(t, B->r, B->c); fmpz_mat_gram(t, A); fmpz_mat_swap_entrywise(B, t); fmpz_mat_clear(t); return; } if(A->c == 0) { fmpz_mat_zero(B); return; } for(i = 0; i < B->r; i++) { for(j = 0; j < B->c; j++) { fmpz_mul(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, i, 0), fmpz_mat_entry(A, j, 0)); for (k = 1; k < A->c; k++) { fmpz_addmul(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, i, k), fmpz_mat_entry(A, j, k)); } } } } flint-3.1.3/src/fmpz_mat/hadamard.c000066400000000000000000000130341461254215100171450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fq_nmod.h" static ulong _fq_nmod_rank(const fq_nmod_t x, const fq_nmod_ctx_t ctx) { slong i; ulong t = 0; for (i = x->length - 1; i >= 0; i--) t = t * ctx->mod.n + x->coeffs[i]; return t; } static void _fq_nmod_unrank(fq_nmod_t x, ulong r, const fq_nmod_ctx_t ctx) { slong i; nmod_poly_zero(x); nmod_poly_fit_length(x, fq_nmod_ctx_degree(ctx)); for (i = 0; r != 0; i++) { x->coeffs[i] = r % ctx->mod.n; x->length = i + 1; r = r / ctx->mod.n; } } static int n_is_prime_power(mp_limb_t * p, mp_limb_t n) { n_factor_t fac; if (n < 2) return 0; n_factor_init(&fac); n_factor(&fac, n, 1); if (fac.num == 1) { if (p != NULL) *p = fac.p[0]; return fac.exp[0]; } return 0; } /* Jacobsthal matrix of order q = p^d */ /* Could speed up greatly for d = 1. */ void fmpz_mat_jacobsthal(fmpz_mat_t Q) { int * quadratic; ulong r, c, q, p, d; fq_nmod_ctx_t ctx; fq_nmod_t x, y, x2; q = fmpz_mat_nrows(Q); if (!(d = n_is_prime_power(&p, q)) || q % 2 == 0) flint_throw(FLINT_ERROR, "Not an odd prime power in %s\n", __func__); fq_nmod_ctx_init_ui(ctx, p, d, "x"); fq_nmod_init(x, ctx); fq_nmod_init(y, ctx); fq_nmod_init(x2, ctx); quadratic = flint_malloc(q * sizeof(int)); for (r = 1; r < q; r++) quadratic[r] = -1; for (r = 1; r < q; r++) { _fq_nmod_unrank(x, r, ctx); fq_nmod_sqr(x2, x, ctx); quadratic[_fq_nmod_rank(x2, ctx)] = 1; } quadratic[0] = 0; for (r = 0; r < q; r++) { _fq_nmod_unrank(x, r, ctx); for (c = r; c < q; c++) { _fq_nmod_unrank(y, c, ctx); fq_nmod_sub(x2, x, y, ctx); fmpz_set_si(fmpz_mat_entry(Q, r, c), quadratic[_fq_nmod_rank(x2, ctx)]); if (q % 4 == 1) fmpz_set(fmpz_mat_entry(Q, c, r), fmpz_mat_entry(Q, r, c)); else fmpz_neg(fmpz_mat_entry(Q, c, r), fmpz_mat_entry(Q, r, c)); } } fq_nmod_clear(x, ctx); fq_nmod_clear(y, ctx); fq_nmod_clear(x2, ctx); fq_nmod_ctx_clear(ctx); flint_free(quadratic); } /* 0 -- not possible */ /* 1 -- n = 2^v * (p^e + 1) */ /* 2 -- n = 2^v * 2*(p^e + 1) */ /* 3 -- n = 2^v */ static int paley_construction(mp_limb_t * q, mp_limb_t n) { int i, v; v = flint_ctz(n); if (UWORD(1) << v == n) return 3; if (n % 4 != 0) return 0; for (i = v - 1; i >= 0; i--) { *q = (n >> i) - 1; if (n_is_prime_power(NULL, *q) != 0) { if (*q % 4 == 3) return 1; else return 2; } } return 0; } static void fmpz_mat_set2x2(fmpz_mat_t A, slong i, slong j, slong a, slong b, slong c, slong d) { fmpz_set_si(fmpz_mat_entry(A, i, j), a); fmpz_set_si(fmpz_mat_entry(A, i, j + 1), b); fmpz_set_si(fmpz_mat_entry(A, i + 1, j), c); fmpz_set_si(fmpz_mat_entry(A, i + 1, j + 1), d); } int fmpz_mat_hadamard(fmpz_mat_t A) { slong n, m, i, j; mp_limb_t q; int kind; n = fmpz_mat_nrows(A); if (n != fmpz_mat_ncols(A)) return 0; if (n == 0) return 1; kind = paley_construction(&q, n); if (kind == 0) return 0; if (kind == 3) { fmpz_one(fmpz_mat_entry(A, 0, 0)); m = 1; } else { fmpz_mat_t Q; fmpz_mat_init(Q, q, q); fmpz_mat_jacobsthal(Q); if (kind == 1) { fmpz_zero(fmpz_mat_entry(A, 0, 0)); for (i = 0; i < q; i++) { fmpz_set_si(fmpz_mat_entry(A, 0, i+1), 1); fmpz_set_si(fmpz_mat_entry(A, i+1, 0), -1); } for (i = 0; i < q; i++) for (j = 0; j < q; j++) fmpz_set(fmpz_mat_entry(A, i+1, j+1), fmpz_mat_entry(Q, i, j)); for (i = 0; i < q + 1; i++) fmpz_add_ui(fmpz_mat_entry(A, i, i), fmpz_mat_entry(A, i, i), 1); m = q + 1; } else { for (i = 0; i < q + 1; i++) { for (j = 0; j < q + 1; j++) { if (i == j) fmpz_mat_set2x2(A, 2 * i, 2 * j, 1, -1, -1, -1); else if (i == 0 || j == 0 || fmpz_is_one(fmpz_mat_entry(Q, i - 1, j - 1))) fmpz_mat_set2x2(A, 2 * i, 2 * j, 1, 1, 1, -1); else fmpz_mat_set2x2(A, 2 * i, 2 * j, -1, -1, -1, 1); } } m = 2 * (q + 1); } fmpz_mat_clear(Q); } for ( ; m < n; m *= 2) { for (i = 0; i < m; i++) { _fmpz_vec_set(A->rows[i] + m, A->rows[i], m); _fmpz_vec_set(A->rows[i + m], A->rows[i], m); _fmpz_vec_neg(A->rows[i + m] + m, A->rows[i], m); } } return 1; } flint-3.1.3/src/fmpz_mat/hnf.c000066400000000000000000000022761461254215100161650ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" void fmpz_mat_hnf(fmpz_mat_t H, const fmpz_mat_t A) { slong m = A->r, b = fmpz_mat_max_bits(A), cutoff = 2; if (b < 0) b = -b; if (b <= 2) cutoff = 52; else if (b <= 4) cutoff = 38; else if (b <= 8) cutoff = 30; else if (b <= 16) cutoff = 11; else if (b <= 32) cutoff = 11; else if (b <= 64) cutoff = 5; else if (b <= 128) cutoff = 4; else if (b <= 512) cutoff = 3; /* TODO: we should call Micciancio-Warisnchi or Pauderis-Storjohann when implemented */ if (m < cutoff) fmpz_mat_hnf_classical(H, A); else { flint_rand_t state; flint_randinit(state); fmpz_mat_hnf_pernet_stein(H, A, state); flint_randclear(state); } } flint-3.1.3/src/fmpz_mat/hnf_classical.c000066400000000000000000000064561461254215100202070ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_hnf_classical(fmpz_mat_t H, const fmpz_mat_t A) { slong i, i0, j, j2, k, l, m, n; fmpz_t min, q; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); fmpz_init(q); fmpz_mat_set(H, A); for (j = 0, k = 0, l = (n - m) * (n > m); n - j != l; j++, k++) { int col_finished = 1; for (i = k + 1; (i < m) && col_finished; i++) col_finished = fmpz_is_zero(fmpz_mat_entry(H, i, j)); if (col_finished) { if (fmpz_sgn(fmpz_mat_entry(H, k, j)) < 0) { for (j2 = j; j2 < n; j2++) fmpz_neg(fmpz_mat_entry(H, k, j2), fmpz_mat_entry(H, k, j2)); } if (fmpz_is_zero(fmpz_mat_entry(H, k, j))) { k--; if (l > 0) l--; } else { /* reduce first entries of column j with row k */ for (i = 0; i < k; i++) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, k, j)); for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, i, j2), q, fmpz_mat_entry(H, k, j2)); } } } } else { i0 = 0; fmpz_init(min); /* locate non-zero entry in column j below k with lowest absolute value */ for (i = k + 1; i < m; i++) { if (fmpz_is_zero(fmpz_mat_entry(H, i, j))) continue; if (fmpz_is_zero(min) || fmpz_cmpabs(fmpz_mat_entry(H, i, j), min) < 0) { i0 = i; fmpz_abs(min, fmpz_mat_entry(H, i, j)); } } /* move the row found to row k */ if (i0 > k) fmpz_mat_swap_rows(H, NULL, i0, k); if (fmpz_sgn(fmpz_mat_entry(H, k, j)) < 0) { for (j2 = j; j2 < n; j2++) { fmpz_neg(fmpz_mat_entry(H, k, j2), fmpz_mat_entry(H, k, j2)); } } /* reduce lower entries of column j with row k */ for (i = k + 1; i < m; i++) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, k, j)); for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, i, j2), q, fmpz_mat_entry(H, k, j2)); } } /* don't move to the next column yet */ j--; k--; fmpz_clear(min); } } fmpz_clear(q); } flint-3.1.3/src/fmpz_mat/hnf_minors.c000066400000000000000000000123721461254215100175520ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best Copyright (C) 2017 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" /* This is the algorithm of Kannan, Bachem, "Polynomial algorithms for computing the Smith and Hermite normal forms of an integer matrix", Siam J. Comput., Vol. 8, No. 4, pp. 499-507. */ void fmpz_mat_hnf_minors(fmpz_mat_t H, const fmpz_mat_t A) { slong j, j2, i, k, l, m, n; fmpz_t u, v, d, r2d, r1d, q, b; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); fmpz_init(u); fmpz_init(v); fmpz_init(d); fmpz_init(r1d); fmpz_init(r2d); fmpz_init(q); fmpz_init(b); fmpz_mat_set(H, A); /* put the kth principal minor in HNF */ for (k = 0, l = m - 1; k < n; k++) { for (j = 0; j < k; j++) { if (fmpz_is_zero(fmpz_mat_entry(H, k, j))) { continue; } fmpz_xgcd(d, u, v, fmpz_mat_entry(H, j, j), fmpz_mat_entry(H, k, j)); if (fmpz_cmpabs(d, fmpz_mat_entry(H, j, j)) == 0) { fmpz_divexact(b, fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, j, j)); for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, k, j2), b, fmpz_mat_entry(H, j, j2)); } continue; } fmpz_divexact(r1d, fmpz_mat_entry(H, j, j), d); fmpz_divexact(r2d, fmpz_mat_entry(H, k, j), d); for (j2 = j; j2 < n; j2++) { fmpz_mul(b, u, fmpz_mat_entry(H, j, j2)); fmpz_addmul(b, v, fmpz_mat_entry(H, k, j2)); fmpz_mul(fmpz_mat_entry(H, k, j2), r1d, fmpz_mat_entry(H, k, j2)); fmpz_submul(fmpz_mat_entry(H, k, j2), r2d, fmpz_mat_entry(H, j, j2)); fmpz_set(fmpz_mat_entry(H, j, j2), b); } } /* if H_k,k is zero we swap row k for some other row (starting with the last) */ if (fmpz_is_zero(fmpz_mat_entry(H, k, k))) { fmpz_mat_swap_rows(H, NULL, k, l); l--; k--; continue; } /* ensure H_k,k is positive */ if (fmpz_sgn(fmpz_mat_entry(H, k, k)) < 0) { for (j = k; j < n; j++) { fmpz_neg(fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, k, j)); } } /* reduce above diagonal elements of each row i */ for (i = k - 1; i >= 0; i--) { for (j = i + 1; j <= k; j++) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, j, j)); if (fmpz_is_zero(q)) { continue; } for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, i, j2), q, fmpz_mat_entry(H, j, j2)); } } } l = m - 1; } /* reduce final rows */ for (k = n; k < m; k++) { for (j = 0; j < n; j++) { fmpz_xgcd(d, u, v, fmpz_mat_entry(H, j, j), fmpz_mat_entry(H, k, j)); if (fmpz_cmpabs(d, fmpz_mat_entry(H, j, j)) == 0) { fmpz_divexact(b, fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, j, j)); for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, k, j2), b, fmpz_mat_entry(H, j, j2)); } continue; } fmpz_divexact(r1d, fmpz_mat_entry(H, j, j), d); fmpz_divexact(r2d, fmpz_mat_entry(H, k, j), d); for (j2 = j; j2 < n; j2++) { fmpz_mul(b, u, fmpz_mat_entry(H, j, j2)); fmpz_addmul(b, v, fmpz_mat_entry(H, k, j2)); fmpz_mul(fmpz_mat_entry(H, k, j2), r1d, fmpz_mat_entry(H, k, j2)); fmpz_submul(fmpz_mat_entry(H, k, j2), r2d, fmpz_mat_entry(H, j, j2)); fmpz_set(fmpz_mat_entry(H, j, j2), b); } } /* reduce above diagonal elements of each row i */ for (i = n - 1; i >= 0; i--) { for (j = i + 1; j < n; j++) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, j, j)); if (fmpz_is_zero(q)) { continue; } for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, i, j2), q, fmpz_mat_entry(H, j, j2)); } } } } fmpz_clear(b); fmpz_clear(q); fmpz_clear(r2d); fmpz_clear(r1d); fmpz_clear(d); fmpz_clear(v); fmpz_clear(u); } flint-3.1.3/src/fmpz_mat/hnf_minors_transform.c000066400000000000000000000161461461254215100216500ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best Copyright (C) 2017 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" /* This is the algorithm of Kannan, Bachem, "Polynomial algorithms for computing the Smith and Hermite normal forms of an integer matrix", Siam J. Comput., Vol. 8, No. 4, pp. 499-507. */ void fmpz_mat_hnf_minors_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A) { slong j, j2, i, k, l, m, n; fmpz_t u, v, d, r2d, r1d, q, b; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); fmpz_init(u); fmpz_init(v); fmpz_init(d); fmpz_init(r1d); fmpz_init(r2d); fmpz_init(q); fmpz_init(b); fmpz_mat_set(H, A); fmpz_mat_one(U); /* put the kth principal minor in HNF */ for (k = 0, l = m - 1; k < n; k++) { for (j = 0; j < k; j++) { if (fmpz_is_zero(fmpz_mat_entry(H, k, j))) { continue; } fmpz_xgcd(d, u, v, fmpz_mat_entry(H, j, j), fmpz_mat_entry(H, k, j)); if (fmpz_cmpabs(d, fmpz_mat_entry(H, j, j)) == 0) { fmpz_divexact(b, fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, j, j)); for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, k, j2), b, fmpz_mat_entry(H, j, j2)); } for (j2 = 0; j2 < m; j2++) { fmpz_submul(fmpz_mat_entry(U, k, j2), b, fmpz_mat_entry(U, j, j2)); } continue; } fmpz_divexact(r1d, fmpz_mat_entry(H, j, j), d); fmpz_divexact(r2d, fmpz_mat_entry(H, k, j), d); for (j2 = j; j2 < n; j2++) { fmpz_mul(b, u, fmpz_mat_entry(H, j, j2)); fmpz_addmul(b, v, fmpz_mat_entry(H, k, j2)); fmpz_mul(fmpz_mat_entry(H, k, j2), r1d, fmpz_mat_entry(H, k, j2)); fmpz_submul(fmpz_mat_entry(H, k, j2), r2d, fmpz_mat_entry(H, j, j2)); fmpz_set(fmpz_mat_entry(H, j, j2), b); } for (j2 = 0; j2 < m; j2++) { fmpz_mul(b, u, fmpz_mat_entry(U, j, j2)); fmpz_addmul(b, v, fmpz_mat_entry(U, k, j2)); fmpz_mul(fmpz_mat_entry(U, k, j2), r1d, fmpz_mat_entry(U, k, j2)); fmpz_submul(fmpz_mat_entry(U, k, j2), r2d, fmpz_mat_entry(U, j, j2)); fmpz_set(fmpz_mat_entry(U, j, j2), b); } } /* if H_k,k is zero we swap row k for some other row (starting with the last) */ if (fmpz_is_zero(fmpz_mat_entry(H, k, k))) { fmpz_mat_swap_rows(H, NULL, k, l); fmpz_mat_swap_rows(U, NULL, k, l); l--; k--; continue; } /* ensure H_k,k is positive */ if (fmpz_sgn(fmpz_mat_entry(H, k, k)) < 0) { for (j = k; j < n; j++) { fmpz_neg(fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, k, j)); } for (j = 0; j < m; j++) { fmpz_neg(fmpz_mat_entry(U, k, j), fmpz_mat_entry(U, k, j)); } } /* reduce above diagonal elements of each row i */ for (i = k - 1; i >= 0; i--) { for (j = i + 1; j <= k; j++) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, j, j)); if (fmpz_is_zero(q)) { continue; } for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, i, j2), q, fmpz_mat_entry(H, j, j2)); } for (j2 = 0; j2 < m; j2++) { fmpz_submul(fmpz_mat_entry(U, i, j2), q, fmpz_mat_entry(U, j, j2)); } } } l = m - 1; } /* reduce final rows */ for (k = n; k < m; k++) { for (j = 0; j < n; j++) { fmpz_xgcd(d, u, v, fmpz_mat_entry(H, j, j), fmpz_mat_entry(H, k, j)); if (fmpz_cmpabs(d, fmpz_mat_entry(H, j, j)) == 0) { fmpz_divexact(b, fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, j, j)); for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, k, j2), b, fmpz_mat_entry(H, j, j2)); } for (j2 = 0; j2 < m; j2++) { fmpz_submul(fmpz_mat_entry(U, k, j2), b, fmpz_mat_entry(U, j, j2)); } continue; } fmpz_divexact(r1d, fmpz_mat_entry(H, j, j), d); fmpz_divexact(r2d, fmpz_mat_entry(H, k, j), d); for (j2 = j; j2 < n; j2++) { fmpz_mul(b, u, fmpz_mat_entry(H, j, j2)); fmpz_addmul(b, v, fmpz_mat_entry(H, k, j2)); fmpz_mul(fmpz_mat_entry(H, k, j2), r1d, fmpz_mat_entry(H, k, j2)); fmpz_submul(fmpz_mat_entry(H, k, j2), r2d, fmpz_mat_entry(H, j, j2)); fmpz_set(fmpz_mat_entry(H, j, j2), b); } for (j2 = 0; j2 < m; j2++) { fmpz_mul(b, u, fmpz_mat_entry(U, j, j2)); fmpz_addmul(b, v, fmpz_mat_entry(U, k, j2)); fmpz_mul(fmpz_mat_entry(U, k, j2), r1d, fmpz_mat_entry(U, k, j2)); fmpz_submul(fmpz_mat_entry(U, k, j2), r2d, fmpz_mat_entry(U, j, j2)); fmpz_set(fmpz_mat_entry(U, j, j2), b); } } /* reduce above diagonal elements of each row i */ for (i = n - 1; i >= 0; i--) { for (j = i + 1; j < n; j++) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, j, j)); if (fmpz_is_zero(q)) { continue; } for (j2 = j; j2 < n; j2++) { fmpz_submul(fmpz_mat_entry(H, i, j2), q, fmpz_mat_entry(H, j, j2)); } for (j2 = 0; j2 < m; j2++) { fmpz_submul(fmpz_mat_entry(U, i, j2), q, fmpz_mat_entry(U, j, j2)); } } } } fmpz_clear(b); fmpz_clear(q); fmpz_clear(r2d); fmpz_clear(r1d); fmpz_clear(d); fmpz_clear(v); fmpz_clear(u); } flint-3.1.3/src/fmpz_mat/hnf_modular.c000066400000000000000000000062641461254215100177110ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_hnf_modular(fmpz_mat_t H, const fmpz_mat_t A, const fmpz_t D) { slong j, i, k, m, n; fmpz_t R, R2, d, u, v, r1d, r2d, b, q; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); fmpz_init_set(R, D); fmpz_init(R2); fmpz_init(u); fmpz_init(u); fmpz_init(v); fmpz_init(d); fmpz_init(r1d); fmpz_init(r2d); fmpz_init(b); fmpz_init(q); fmpz_mat_set(H, A); for (k = 0; k != n; k++) { fmpz_fdiv_q_2exp(R2, R, 1); if (fmpz_is_zero(fmpz_mat_entry(H, k, k))) fmpz_set(fmpz_mat_entry(H, k, k), R); for (i = k + 1; i != m; i++) { /* reduce row i with row k mod R */ if (fmpz_is_zero(fmpz_mat_entry(H, i, k))) continue; fmpz_xgcd(d, u, v, fmpz_mat_entry(H, k, k), fmpz_mat_entry(H, i, k)); fmpz_divexact(r1d, fmpz_mat_entry(H, k, k), d); fmpz_divexact(r2d, fmpz_mat_entry(H, i, k), d); for (j = k; j < n; j++) { fmpz_mul(b, u, fmpz_mat_entry(H, k, j)); fmpz_addmul(b, v, fmpz_mat_entry(H, i, j)); fmpz_mul(fmpz_mat_entry(H, i, j), r1d, fmpz_mat_entry(H, i, j)); fmpz_submul(fmpz_mat_entry(H, i, j), r2d, fmpz_mat_entry(H, k, j)); fmpz_mod(fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, i, j), R); if (fmpz_cmp(fmpz_mat_entry(H, i, j), R2) > 0) fmpz_sub(fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, i, j), R); fmpz_mod(fmpz_mat_entry(H, k, j), b, R); if (fmpz_cmp(fmpz_mat_entry(H, k, j), R2) > 0) fmpz_sub(fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, k, j), R); } } fmpz_xgcd(d, u, v, fmpz_mat_entry(H, k, k), R); for (j = k; j < n; j++) { fmpz_mul(fmpz_mat_entry(H, k, j), u, fmpz_mat_entry(H, k, j)); fmpz_mod(fmpz_mat_entry(H, k, j), fmpz_mat_entry(H, k, j), R); } if (fmpz_is_zero(fmpz_mat_entry(H, k, k))) fmpz_set(fmpz_mat_entry(H, k, k), R); /* reduce higher entries of column k with row k */ for (i = k - 1; i >= 0; i--) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, k), fmpz_mat_entry(H, k, k)); for (j = k; j < n; j++) { fmpz_submul(fmpz_mat_entry(H, i, j), q, fmpz_mat_entry(H, k, j)); } } fmpz_divexact(R, R, d); } fmpz_clear(b); fmpz_clear(r2d); fmpz_clear(r1d); fmpz_clear(q); fmpz_clear(d); fmpz_clear(v); fmpz_clear(u); fmpz_clear(R2); fmpz_clear(R); } flint-3.1.3/src/fmpz_mat/hnf_modular_eldiv.c000066400000000000000000000021621461254215100210650ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_hnf_modular_eldiv(fmpz_mat_t A, const fmpz_t D) { slong i; mp_limb_t Dlimbt; nmod_mat_t AmodD; if (fmpz_mat_is_empty(A)) return; if (fmpz_abs_fits_ui(D)) { Dlimbt = fmpz_get_ui(D); nmod_mat_init(AmodD, A->r, A->c, Dlimbt); fmpz_mat_get_nmod_mat(AmodD, A); nmod_mat_strong_echelon_form(AmodD); fmpz_mat_set_nmod_mat_unsigned(A, AmodD); nmod_mat_clear(AmodD); } else { fmpz_mat_strong_echelon_form_mod(A, D); } for (i = 0; i < A->c; i++) { if (fmpz_is_zero(fmpz_mat_entry(A, i, i))) { fmpz_set(fmpz_mat_entry(A, i, i), D); } } } flint-3.1.3/src/fmpz_mat/hnf_pernet_stein.c000066400000000000000000000461141461254215100207430ustar00rootroot00000000000000/* Copyright (C) 2014, 2015 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "nmod.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" static void add_columns(fmpz_mat_t H, const fmpz_mat_t B, const fmpz_mat_t H1, flint_rand_t state) { int neg; slong i, j, n, bits; fmpz_t den, tmp, one; fmpq_t num, alpha; fmpz_mat_t Bu, B1, cols, k; fmpq_mat_t H1_q, cols_q, x; n = B->r; fmpz_mat_init(Bu, n, n); fmpz_mat_init(B1, n - 1, n); fmpz_mat_init(cols, n, B->c - n); fmpz_mat_init(k, n, 1); fmpq_mat_init(x, n, B->c - n); fmpq_mat_init(cols_q, n, B->c - n); fmpq_mat_init(H1_q, n, n); for (i = 0; i < n; i++) for (j = 0; j < cols->c; j++) fmpz_set(fmpz_mat_entry(cols, i, j), fmpz_mat_entry(B, i, n + j)); for (i = 0; i < n - 1; i++) { for (j = 0; j < n; j++) { fmpz_set(fmpz_mat_entry(Bu, i, j), fmpz_mat_entry(B, i, j)); fmpz_set(fmpz_mat_entry(B1, i, j), fmpz_mat_entry(B, i, j)); } } /* find kernel basis vector */ if (fmpz_mat_nullspace(k, B1) != 1) { flint_throw(FLINT_ERROR, "(fmpz_mat_hnf_pernet_stein): " "Nullspace was not dimension one.\n"); } bits = fmpz_mat_max_bits(B1); if (bits < 0) bits = -bits; fmpz_mat_clear(B1); fmpz_init(tmp); /* set the last row of Bu to be random, such that Bu is nonsingular */ while (fmpz_is_zero(tmp)) { _fmpz_vec_randtest(Bu->rows[n - 1], state, n, bits); fmpz_zero(tmp); for (j = 0; j < n; j++) fmpz_addmul(tmp, fmpz_mat_entry(Bu, n - 1, j), fmpz_mat_entry(k, j, 0)); } fmpz_clear(tmp); /* solve Bu*x = cols */ if (!fmpq_mat_solve_fmpz_mat(x, Bu, cols)) { flint_throw(FLINT_ERROR, "(fmpz_mat_hnf_pernet_stein): " "Singular input matrix for solve.\n"); } /* fix final row */ fmpq_init(num); fmpz_init(den); fmpq_init(alpha); fmpz_init(one); fmpz_one(one); /* compute denominator */ for (i = 0; i < n; i++) fmpz_addmul(den, fmpz_mat_entry(B, n - 1, i), fmpz_mat_entry(k, i, 0)); neg = (fmpz_sgn(den) < 0); if (neg) fmpz_neg(den, den); for (j = 0; j < B->c - H1->c; j++) { fmpq_zero(num); for (i = 0; i < n; i++) { _fmpq_addmul(fmpq_numref(num), fmpq_denref(num), fmpz_mat_entry(B, n - 1, i), one, fmpq_mat_entry_num(x, i, j), fmpq_mat_entry_den(x, i, j)); } _fmpq_sub(fmpq_numref(alpha), fmpq_denref(alpha), fmpz_mat_entry(B, n - 1, n + j), one, fmpq_numref(num), fmpq_denref(num)); _fmpq_mul(fmpq_numref(alpha), fmpq_denref(alpha), fmpq_numref(alpha), fmpq_denref(alpha), one, den); if (neg) fmpq_neg(alpha, alpha); /* x_i += alpha*k */ for (i = 0; i < n; i++) { _fmpq_addmul(fmpq_mat_entry_num(x, i, j), fmpq_mat_entry_den(x, i, j), fmpq_numref(alpha), fmpq_denref(alpha), fmpz_mat_entry(k, i, 0), one); } } fmpq_clear(num); fmpz_clear(den); fmpz_clear(one); fmpq_clear(alpha); /* set cols = H1*x and place in position in H */ fmpq_mat_set_fmpz_mat(H1_q, H1); fmpq_mat_mul(cols_q, H1_q, x); fmpq_mat_get_fmpz_mat(cols, cols_q); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(H, i, j), fmpz_mat_entry(H1, i, j)); for (j = n; j < H->c; j++) fmpz_set(fmpz_mat_entry(H, i, j), fmpz_mat_entry(cols, i, j - n)); } fmpq_mat_clear(H1_q); fmpq_mat_clear(x); fmpq_mat_clear(cols_q); fmpz_mat_clear(k); fmpz_mat_clear(cols); fmpz_mat_clear(Bu); } /* takes input matrix H with rows 0 to start_row - 1 in HNF to a HNF matrix */ static void add_rows(fmpz_mat_t H, slong start_row, slong *pivots, slong num_pivots) { slong i, i2, j, j2, new_row, row; fmpz_t b, d, u, v, r1d, r2d, q; fmpz_init(b); fmpz_init(d); fmpz_init(u); fmpz_init(v); fmpz_init(r1d); fmpz_init(r2d); fmpz_init(q); for (row = start_row; row < H->r; row++) { /* reduce row to be added with existing */ for (i = j = 0; i < num_pivots; i++) { /* check if added row can still be reduced */ for (; j < pivots[i]; j++) if (!fmpz_is_zero(fmpz_mat_entry(H, row, j))) break; if (j < pivots[i]) break; if (fmpz_is_zero(fmpz_mat_entry(H, row, j))) continue; fmpz_xgcd(d, u, v, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, row, j)); fmpz_divexact(r1d, fmpz_mat_entry(H, i, j), d); fmpz_divexact(r2d, fmpz_mat_entry(H, row, j), d); for (j2 = j; j2 < H->c; j2++) { fmpz_mul(b, u, fmpz_mat_entry(H, i, j2)); fmpz_addmul(b, v, fmpz_mat_entry(H, row, j2)); fmpz_mul(fmpz_mat_entry(H, row, j2), r1d, fmpz_mat_entry(H, row, j2)); fmpz_submul(fmpz_mat_entry(H, row, j2), r2d, fmpz_mat_entry(H, i, j2)); fmpz_set(fmpz_mat_entry(H, i, j2), b); } } /* find first non-zero entry of the added row */ for (j = 0; j < H->c && fmpz_is_zero(fmpz_mat_entry(H, row, j)); j++) ; new_row = row; if (j != H->c) /* last row non-zero, move to correct position */ { if (fmpz_sgn(fmpz_mat_entry(H, row, j)) < 0) { for (j2 = j; j2 < H->c; j2++) { fmpz_neg(fmpz_mat_entry(H, row, j2), fmpz_mat_entry(H, row, j2)); } } do { if (new_row < row) fmpz_mat_swap_rows(H, NULL, new_row, new_row + 1); if (new_row == 0) break; new_row--; for (j2 = 0; j2 < H->c && fmpz_is_zero(fmpz_mat_entry(H, new_row, j2)); j2++) ; } while (j2 > j); } /* recompute pivots */ for (i = new_row, j = 0; i <= row && i < H->c; i++, j++) { for (; j < H->c && fmpz_is_zero(fmpz_mat_entry(H, i, j)); j++) ; if (j == H->c) break; pivots[i] = j; num_pivots = i + 1; } /* reduce above pivot entries */ for (i = 0; i < num_pivots; i++) { for (i2 = 0; i2 < i; i2++) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i2, pivots[i]), fmpz_mat_entry(H, i, pivots[i])); for (j2 = pivots[i]; j2 < H->c; j2++) { fmpz_submul(fmpz_mat_entry(H, i2, j2), q, fmpz_mat_entry(H, i, j2)); } } } } fmpz_clear(q); fmpz_clear(r2d); fmpz_clear(r1d); fmpz_clear(v); fmpz_clear(u); fmpz_clear(d); fmpz_clear(b); } static void double_det(fmpz_t d1, fmpz_t d2, const fmpz_mat_t B, const fmpz_mat_t c, const fmpz_mat_t d) { slong i, j, n; slong *P; mp_limb_t p, u1mod, u2mod, v1mod, v2mod; fmpz_t bound, prod, s1, s2, t, u1, u2, v1, v2; fmpz_mat_t dt, Bt; fmpq_t tmpq; fmpq_mat_t x; nmod_mat_t Btmod; n = B->c; fmpz_mat_init(dt, n, 1); fmpz_mat_init(Bt, n, n); fmpq_mat_init(x, n, 1); for (i = 0; i < n; i++) { for (j = 0; j < n - 1; j++) fmpz_set(fmpz_mat_entry(Bt, i, j), fmpz_mat_entry(B, j, i)); fmpz_set(fmpz_mat_entry(Bt, i, n - 1), fmpz_mat_entry(c, 0, i)); } /* solve B^Tx = d^T */ fmpz_mat_transpose(dt, d); fmpq_mat_solve_fmpz_mat(x, Bt, dt); if (!fmpq_is_zero(fmpq_mat_entry(x, n - 1, 0))) { fmpz_init(bound); fmpz_init(prod); fmpz_init(t); fmpz_init(s1); fmpz_init(s2); fmpz_init(u1); fmpz_init(u2); fmpz_init(v1); fmpz_init(v2); /* compute lcm of denominators of vectors x and y */ fmpq_init(tmpq); fmpz_one(u1); fmpz_one(u2); for (i = 0; i < n - 1; i++) { fmpz_lcm(u1, u1, fmpq_mat_entry_den(x, i, 0)); fmpq_div(tmpq, fmpq_mat_entry(x, i, 0), fmpq_mat_entry(x, n - 1, 0)); fmpz_lcm(u2, u2, fmpq_denref(tmpq)); } fmpz_lcm(u1, u1, fmpq_mat_entry_den(x, n - 1, 0)); fmpq_inv(tmpq, fmpq_mat_entry(x, n - 1, 0)); fmpz_lcm(u2, u2, fmpq_denref(tmpq)); fmpq_clear(tmpq); /* compute Hadamard bounds */ fmpz_one(bound); for (j = 0; j < n - 1; j++) { fmpz_zero(s1); for (i = 0; i < n; i++) fmpz_addmul(s1, fmpz_mat_entry(Bt, i, j), fmpz_mat_entry(Bt, i, j)); fmpz_sqrtrem(s1, t, s1); if (!fmpz_is_zero(t)) fmpz_add_ui(s1, s1, UWORD(1)); fmpz_mul(bound, bound, s1); } fmpz_zero(s1); fmpz_zero(s2); for (j = 0; j < n; j++) { fmpz_addmul(s1, fmpz_mat_entry(c, 0, j), fmpz_mat_entry(c, 0, j)); fmpz_addmul(s2, fmpz_mat_entry(d, 0, j), fmpz_mat_entry(d, 0, j)); } fmpz_sqrtrem(s1, t, s1); if (!fmpz_is_zero(t)) fmpz_add_ui(s1, s1, UWORD(1)); fmpz_sqrtrem(s2, t, s2); if (!fmpz_is_zero(t)) fmpz_add_ui(s2, s2, UWORD(1)); fmpz_mul(s1, s1, bound); fmpz_mul(s2, s2, bound); fmpz_cdiv_q(s1, s1, u1); fmpz_cdiv_q(s2, s2, u2); if (fmpz_cmp(s1, s2) > 0) fmpz_set(bound, s1); else fmpz_set(bound, s2); fmpz_mul_ui(bound, bound, UWORD(2)); fmpz_one(prod); P = _perm_init(n); nmod_mat_init(Btmod, n, n, 2); p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; /* compute determinants divided by u1 and u2 */ while (fmpz_cmp(prod, bound) <= 0) { p = n_nextprime(p, 0); u1mod = fmpz_fdiv_ui(u1, p); u2mod = fmpz_fdiv_ui(u2, p); if (!(u1mod || u2mod)) continue; nmod_mat_set_mod(Btmod, p); for (i = 0; i < n; i++) { for (j = 0; j < n - 1; j++) nmod_mat_entry(Btmod, i, j) = fmpz_fdiv_ui(fmpz_mat_entry(B, j, i), p); nmod_mat_entry(Btmod, i, n - 1) = fmpz_fdiv_ui(fmpz_mat_entry(c, 0, i), p); } nmod_mat_lu(P, Btmod, 0); v1mod = UWORD(1); for (i = 0; i < n; i++) v1mod = n_mulmod2_preinv(v1mod, nmod_mat_entry(Btmod, i, i), p, Btmod->mod.ninv); if (_perm_parity(P, n) == 1) v1mod = nmod_neg(v1mod, Btmod->mod); for (i = 0; i < n; i++) { for (j = 0; j < n - 1; j++) nmod_mat_entry(Btmod, i, j) = fmpz_fdiv_ui(fmpz_mat_entry(B, j, i), p); nmod_mat_entry(Btmod, i, n - 1) = fmpz_fdiv_ui(fmpz_mat_entry(d, 0, i), p); } nmod_mat_lu(P, Btmod, 0); v2mod = UWORD(1); for (i = 0; i < n; i++) v2mod = n_mulmod2_preinv(v2mod, nmod_mat_entry(Btmod, i, i), p, Btmod->mod.ninv); if (_perm_parity(P, n) == 1) v2mod = nmod_neg(v2mod, Btmod->mod); v1mod = n_mulmod2_preinv(v1mod, n_invmod(u1mod, p), p, Btmod->mod.ninv); v2mod = n_mulmod2_preinv(v2mod, n_invmod(u2mod, p), p, Btmod->mod.ninv); fmpz_CRT_ui(v1, v1, prod, v1mod, p, 1); fmpz_CRT_ui(v2, v2, prod, v2mod, p, 1); fmpz_mul_ui(prod, prod, p); } fmpz_mul(d1, u1, v1); fmpz_mul(d2, u2, v2); fmpz_clear(bound); fmpz_clear(prod); fmpz_clear(s1); fmpz_clear(s2); fmpz_clear(u1); fmpz_clear(u2); fmpz_clear(v1); fmpz_clear(v2); fmpz_clear(t); _perm_clear(P); nmod_mat_clear(Btmod); } else /* can't use the clever method above so naively compute both dets */ { fmpz_mat_det(d1, Bt); for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(Bt, j, n - 1), fmpz_mat_entry(d, 0, j)); fmpz_mat_det(d2, Bt); } fmpz_mat_clear(dt); fmpz_mat_clear(Bt); fmpq_mat_clear(x); } void fmpz_mat_hnf_pernet_stein(fmpz_mat_t H, const fmpz_mat_t A, flint_rand_t state) { slong i, j, m, n, p, r, *P, *pivots, finished; fmpz_t d1, d2, g, s, t; fmpz_mat_t c, d, B, C, H1, H2, H3; nmod_mat_t Amod; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); if (m == 0 || n == 0) return; /* find permutation so we can ensure first rows of H are nonsingular */ P = _perm_init(m); pivots = _perm_init(n); finished = 0; while (!finished) { p = n_randprime(state, NMOD_MAT_OPTIMAL_MODULUS_BITS, 1); nmod_mat_init(Amod, m, n, p); fmpz_mat_get_nmod_mat(Amod, A); r = _nmod_mat_rref(Amod, pivots, P); nmod_mat_clear(Amod); /* rank is zero so matrix is possibly zero too */ if (r == 0) { if (fmpz_mat_is_zero(A)) { fmpz_mat_zero(H); _perm_clear(P); _perm_clear(pivots); return; } continue; } /* if A has full column rank we might wish to use minors based hnf */ if (r == n && n < 52) { slong b = fmpz_mat_max_bits(A), cutoff = 52; if (b < 0) b = -b; if (b <= 8) cutoff = 35; else if (b <= 32) cutoff = 44; else if (b <= 256) cutoff = 48; if (n < cutoff) { fmpz_mat_hnf_minors(H, A); _perm_clear(P); _perm_clear(pivots); return; } } fmpz_mat_init(c, 1, r - 1); fmpz_mat_init(d, 1, r - 1); fmpz_mat_init(B, FLINT_MAX(r - 2, 0), r - 1); fmpz_mat_init(C, r - 1, r - 1); for (i = 0; i < r - 2; i++) { for (j = 0; j < r - 1; j++) { fmpz_set(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, P[i], pivots[j])); fmpz_set(fmpz_mat_entry(C, i, j), fmpz_mat_entry(A, P[i], pivots[j])); } fmpz_set(fmpz_mat_entry(C, i, r - 1), fmpz_mat_entry(A, P[i], pivots[r - 1])); } for (j = 0; j < r - 1; j++) { fmpz_set(fmpz_mat_entry(c, 0, j), fmpz_mat_entry(A, P[r - 2], pivots[j])); fmpz_set(fmpz_mat_entry(d, 0, j), fmpz_mat_entry(A, P[r - 1], pivots[j])); } fmpz_init(g); fmpz_init(s); fmpz_init(t); /* if rank is too low leave g = 0 so we don't try to decompose later */ if (r > 2) { fmpz_init(d1); fmpz_init(d2); double_det(d1, d2, B, c, d); fmpz_xgcd(g, s, t, d1, d2); for (j = 0; j < r - 1; j++) { fmpz_mul(fmpz_mat_entry(C, r - 2, j), s, fmpz_mat_entry(A, P[r - 2], pivots[j])); fmpz_addmul(fmpz_mat_entry(C, r - 2, j), t, fmpz_mat_entry(A, P[r - 1], pivots[j])); } fmpz_clear(d2); fmpz_clear(d1); } if (!fmpz_is_zero(g)) /* chosen matrix invertible */ { fmpz_mat_init(H1, r - 1, r - 1); if (COEFF_IS_MPZ(*g) && C->r > 3) /* if g is too big, recurse */ fmpz_mat_hnf_pernet_stein(H1, C, state); else /* use modulo determinant algorithm to compute HNF of C */ fmpz_mat_hnf_modular(H1, C, g); fmpz_mat_clear(B); fmpz_mat_init(B, r - 1, n); for (j = 0; j < n; j++) { for (i = 0; i < r - 2; i++) fmpz_set(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, P[i], pivots[j])); fmpz_mul(fmpz_mat_entry(B, r - 2, j), s, fmpz_mat_entry(A, P[r - 2], pivots[j])); fmpz_addmul(fmpz_mat_entry(B, r - 2, j), t, fmpz_mat_entry(A, P[r - 1], pivots[j])); } fmpz_mat_init(H2, r - 1, n); fmpz_mat_init(H3, m + 1, n); add_columns(H2, B, H1, state); for (i = 0; i < r - 1; i++) for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(H3, i, pivots[j]), fmpz_mat_entry(H2, i, j)); for (i = 1; i <= m - r + 2; i++) for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(H3, H3->r - i, j), fmpz_mat_entry(A, P[m - i], j)); /* check the pivots of H3 are as expected */ for (i = 0; i < r - 1; i++) { for (j = 0; j < H3->c && fmpz_is_zero(fmpz_mat_entry(H3, i, j)); j++); if (pivots[i] != j) break; } /* the pivots were as expected so our choice of prime was ok */ if (i == r - 1) { /* add final rows in */ add_rows(H3, r - 1, pivots, r - 1); /* fill H with HNF */ for (i = 0; i < m; i++) for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(H, i, j), fmpz_mat_entry(H3, i, j)); finished = 1; } /* otherwise we must restart as our random prime gave us incorrect pivots */ fmpz_mat_clear(H1); fmpz_mat_clear(H2); fmpz_mat_clear(H3); } else { if (r == n) /* if A has full column rank we can use minors based hnf */ fmpz_mat_hnf_minors(H, A); else fmpz_mat_hnf_classical(H, A); finished = 1; } fmpz_clear(t); fmpz_clear(s); fmpz_clear(g); fmpz_mat_clear(C); fmpz_mat_clear(B); fmpz_mat_clear(c); fmpz_mat_clear(d); } _perm_clear(P); _perm_clear(pivots); } flint-3.1.3/src/fmpz_mat/hnf_transform.c000066400000000000000000000040511461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best Copyright (C) 2017 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" void _fmpz_mat_hnf_transform_naive(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A) { slong i, j, m, n; fmpz_mat_t A2, H2; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); fmpz_mat_init(A2, m, n + m); fmpz_mat_init(H2, m, n + m); /* append an identity matrix to the right of A */ for (i = 0; i < m; i++) { for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(A2, i, j), fmpz_mat_entry(A, i, j)); fmpz_one(fmpz_mat_entry(A2, i, n + i)); } fmpz_mat_hnf(H2, A2); /* recover H and U */ for (i = 0; i < m; i++) { for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(H, i, j), fmpz_mat_entry(H2, i, j)); for (j = n; j < n + m; j++) fmpz_set(fmpz_mat_entry(U, i, j - n), fmpz_mat_entry(H2, i, j)); } fmpz_mat_clear(A2); fmpz_mat_clear(H2); } void fmpz_mat_hnf_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A) { slong m, n, r, p; nmod_mat_t Amod; flint_rand_t state; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); if (n > m) _fmpz_mat_hnf_transform_naive(H, U, A); else { flint_randinit(state); p = n_randprime(state, NMOD_MAT_OPTIMAL_MODULUS_BITS, 1); nmod_mat_init(Amod, m, n, p); fmpz_mat_get_nmod_mat(Amod, A); r = nmod_mat_rref(Amod); nmod_mat_clear(Amod); flint_randclear(state); if (r == n) /* Full column rank */ fmpz_mat_hnf_minors_transform(H, U, A); else _fmpz_mat_hnf_transform_naive(H, U, A); } } flint-3.1.3/src/fmpz_mat/hnf_xgcd.c000066400000000000000000000052371461254215100171720ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_hnf_xgcd(fmpz_mat_t H, const fmpz_mat_t A) { slong j, j2, i, k, l; fmpz_t r1d, r2d, b, u, v, d, q; fmpz_init(r1d); fmpz_init(r2d); fmpz_init(b); fmpz_init(u); fmpz_init(v); fmpz_init(d); fmpz_init(q); fmpz_mat_set(H, A); for (j = 0, k = 0, l = (A->c - A->r)*(A->c > A->r); A->c - j != l; j++, k++) { for (i = k + 1; i != A->r; i++) { /* reduce row i - 1 with row i */ if (fmpz_is_zero(fmpz_mat_entry(H, i - 1, j))) continue; fmpz_xgcd(d, u, v, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, i - 1, j)); fmpz_divexact(r2d, fmpz_mat_entry(H, i - 1, j), d); fmpz_divexact(r1d, fmpz_mat_entry(H, i, j), d); for (j2 = j; j2 < A->c; j2++) { fmpz_mul(b, u, fmpz_mat_entry(H, i, j2)); fmpz_addmul(b, v, fmpz_mat_entry(H, i - 1, j2)); fmpz_mul(fmpz_mat_entry(H, i - 1, j2), r1d, fmpz_mat_entry(H, i - 1, j2)); fmpz_submul(fmpz_mat_entry(H, i - 1, j2), r2d, fmpz_mat_entry(H, i, j2)); fmpz_set(fmpz_mat_entry(H, i, j2), b); } } fmpz_mat_swap_rows(H, NULL, A->r - 1, k); if (fmpz_sgn(fmpz_mat_entry(H, k, j)) < 0) { for (j2 = j; j2 < A->c; j2++) { fmpz_neg(fmpz_mat_entry(H, k, j2), fmpz_mat_entry(H, k, j2)); } } if (fmpz_is_zero(fmpz_mat_entry(H, k, j))) { k--; if (l > 0) l--; } else { /* reduce higher entries of column j with row k */ for (i = k - 1; i >= 0; i--) { fmpz_fdiv_q(q, fmpz_mat_entry(H, i, j), fmpz_mat_entry(H, k, j)); for (j2 = j; j2 < A->c; j2++) { fmpz_submul(fmpz_mat_entry(H, i, j2), q, fmpz_mat_entry(H, k, j2)); } } } } fmpz_clear(q); fmpz_clear(r2d); fmpz_clear(r1d); fmpz_clear(b); fmpz_clear(u); fmpz_clear(v); fmpz_clear(d); } flint-3.1.3/src/fmpz_mat/howell_form_mod.c000066400000000000000000000017661461254215100205710ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" slong fmpz_mat_howell_form_mod(fmpz_mat_t A, const fmpz_t mod) { slong i, j, n; slong k; if (fmpz_mat_is_empty(A)) return 0; n = A->r; k = n; fmpz_mat_strong_echelon_form_mod(A, mod); for (i = 0; i < n; i++) { if (fmpz_mat_is_zero_row(A, i)) { k--; for (j = i + 1; j < n; j++) { if (!fmpz_mat_is_zero_row(A, j)) { fmpz_mat_swap_rows(A, NULL, i, j); j = n; k++; } } } } return k; } flint-3.1.3/src/fmpz_mat/init.c000066400000000000000000000022621461254215100163500ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" void fmpz_mat_init(fmpz_mat_t mat, slong rows, slong cols) { slong i; if (rows != 0) mat->rows = (fmpz **) flint_malloc(rows * sizeof(fmpz *)); else mat->rows = NULL; if (rows != 0 && cols != 0) /* Allocate space for r*c small entries */ { mat->entries = (fmpz *) flint_calloc(flint_mul_sizes(rows, cols), sizeof(fmpz)); for (i = 0; i < rows; i++) mat->rows[i] = mat->entries + i * cols; } else { mat->entries = NULL; for (i = 0; i < rows; i++) mat->rows[i] = NULL; } mat->r = rows; mat->c = cols; } void fmpz_mat_init_set(fmpz_mat_t mat, const fmpz_mat_t src) { fmpz_mat_init(mat, src->r, src->c); fmpz_mat_set(mat, src); } flint-3.1.3/src/fmpz_mat/inlines.c000066400000000000000000000006541461254215100170510ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MAT_INLINES_C #include "fmpz_mat.h" flint-3.1.3/src/fmpz_mat/inv.c000066400000000000000000000033411461254215100162000ustar00rootroot00000000000000/* Copyright (C) 2010-2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" static void _fmpz_mat_inv_2x2(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A) { fmpz_fmms(den, fmpz_mat_entry(A, 0, 0), fmpz_mat_entry(A, 1, 1), fmpz_mat_entry(A, 0, 1), fmpz_mat_entry(A, 1, 0)); fmpz_neg(fmpz_mat_entry(B, 0, 1), fmpz_mat_entry(A, 0, 1)); fmpz_neg(fmpz_mat_entry(B, 1, 0), fmpz_mat_entry(A, 1, 0)); if (A == B) { fmpz_swap(fmpz_mat_entry(B, 0, 0), fmpz_mat_entry(B, 1, 1)); } else { fmpz_set(fmpz_mat_entry(B, 0, 0), fmpz_mat_entry(A, 1, 1)); fmpz_set(fmpz_mat_entry(B, 1, 1), fmpz_mat_entry(A, 0, 0)); } } int fmpz_mat_inv(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A) { slong dim = A->r; if (dim == 0) { fmpz_one(den); return 1; } else if (dim == 1) { fmpz_set(den, fmpz_mat_entry(A, 0, 0)); fmpz_one(fmpz_mat_entry(B, 0, 0)); return !fmpz_is_zero(den); } else if (dim == 2) { _fmpz_mat_inv_2x2(B, den, A); return !fmpz_is_zero(den); } else { fmpz_mat_t I; slong i; int success; fmpz_mat_init(I, dim, dim); for (i = 0; i < dim; i++) fmpz_one(fmpz_mat_entry(I, i, i)); success = fmpz_mat_solve(B, den, A, I); fmpz_mat_clear(I); return success; } } flint-3.1.3/src/fmpz_mat/invert.c000066400000000000000000000020371461254215100167140ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_invert_rows(fmpz_mat_t mat, slong * perm) { slong i; for (i = 0; i < mat->r/2; i++) fmpz_mat_swap_rows(mat, perm, i, mat->r - i - 1); } void fmpz_mat_invert_cols(fmpz_mat_t mat, slong * perm) { if (!fmpz_mat_is_empty(mat)) { slong t, i; slong c = mat->c; slong k = mat->c/2; if (perm != NULL) for (i = 0; i < k; i++) FLINT_SWAP(slong, perm[i], perm[c - i - 1]); for (t = 0; t < mat->r; t++) for (i = 0; i < k; i++) fmpz_swap(fmpz_mat_entry(mat, t, i), fmpz_mat_entry(mat, t, c - i - 1)); } } flint-3.1.3/src/fmpz_mat/io.c000066400000000000000000000105661461254215100160220ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_mat.h" /* printing *******************************************************************/ /* The macros xxx_putc, xxx_flint_printf, and xxx_fmpz_print are provided as wrappers to handle return values and error conditions. While this is not exactly pretty, it improves the readability of the functions fmpz_mat_fprint and fmpz_mat_fprint_pretty. Moreover, if we later want to improve the handling of returns values, e.g. to return the number of characters printed, this will be easier. The macros are undef'd at the end of the file. */ #define xxx_putc(c) \ do { \ z = fputc((c), file); \ if (z <= 0) \ return z; \ } while (0) #define xxx_flint_printf() \ do { \ z = flint_fprintf(file, "%wd %wd ", r, c); \ if (z <= 0) \ return z; \ } while (0) #define xxx_fmpz_print(f) \ do { \ z = fmpz_fprint(file, (f)); \ if (z <= 0) \ return z; \ } while(0) int fmpz_mat_fprint(FILE * file, const fmpz_mat_t mat) { int z; slong i, j; slong r = mat->r; slong c = mat->c; xxx_flint_printf(); for (i = 0; (i < r); i++) { for (j = 0; j < c; j++) { xxx_fmpz_print(mat->rows[i] + j); if (j != c - 1) xxx_putc(' '); } if (i != r - 1) xxx_putc(' '); } return z; } int fmpz_mat_fprint_pretty(FILE * file, const fmpz_mat_t mat) { int z; slong i, j; slong r = mat->r; slong c = mat->c; xxx_putc('['); for (i = 0; i < r; i++) { xxx_putc('['); for (j = 0; j < c; j++) { xxx_fmpz_print(mat->rows[i] + j); if (j != c - 1) xxx_putc(' '); } xxx_putc(']'); xxx_putc('\n'); } xxx_putc(']'); return z; } #undef xxx_putc #undef xxx_flint_printf #undef xxx_fmpz_print int fmpz_mat_print(const fmpz_mat_t mat) { return fmpz_mat_fprint(stdout, mat); } int fmpz_mat_print_pretty(const fmpz_mat_t mat) { return fmpz_mat_fprint_pretty(stdout, mat); } /* reading ********************************************************************/ int fmpz_mat_fread(FILE* file, fmpz_mat_t mat) { slong r, c, i, j; int byte_count; mpz_t t; /* first number in file should be row dimension */ mpz_init(t); byte_count = mpz_inp_str(t, file, 10); if (byte_count == 0) { mpz_clear(t); return 0; } if (!mpz_fits_slong_p(t)) { flint_throw(FLINT_ERROR, "(fmpz_mat_fread): " "Number of rows does not fit into a slong.\n"); } r = flint_mpz_get_si(t); /* second number in file should be column dimension */ byte_count = mpz_inp_str(t, file, 10); if (byte_count == 0) { mpz_clear(t); return 0; } if (!mpz_fits_slong_p(t)) { flint_throw(FLINT_ERROR, "(fmpz_mat_fread): " "Number of columns does not fit into a slong.\n"); } c = flint_mpz_get_si(t); mpz_clear(t); /* if the input is 0 by 0 then set the dimensions to r and c */ if (mat->r == 0 && mat->c == 0) { fmpz_mat_clear(mat); fmpz_mat_init(mat,r,c); } else if (mat->r != r || mat->c != c) { flint_throw(FLINT_ERROR, "(fmpz_mat_fread): " "Dimensions are non-zero and do not match input dimensions.\n"); } for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { if (!fmpz_fread(file, fmpz_mat_entry(mat, i, j))) return 0; } } /* a return value of 0 means a problem with the file stream a value of 1 means success*/ return 1; } int fmpz_mat_read(fmpz_mat_t mat) { return fmpz_mat_fread(stdin, mat); } flint-3.1.3/src/fmpz_mat/is_hadamard.c000066400000000000000000000021671461254215100176450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_is_hadamard(const fmpz_mat_t A) { slong i, j, n; fmpz_mat_t B, C; int result; n = fmpz_mat_nrows(A); if (n != fmpz_mat_ncols(A)) return 0; if (n > 2 && n % 4 != 0) return 0; for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (!fmpz_is_pm1(fmpz_mat_entry(A, i, j))) return 0; fmpz_mat_init(B, n, n); fmpz_mat_init(C, n, n); fmpz_mat_transpose(B, A); fmpz_mat_mul(C, A, B); result = 1; for (i = 0; i < n && result; i++) for (j = 0; j < n && result; j++) result = (*fmpz_mat_entry(C, i, j) == n * (i == j)); fmpz_mat_clear(B); fmpz_mat_clear(C); return result; } flint-3.1.3/src/fmpz_mat/is_in_hnf.c000066400000000000000000000027121461254215100173410ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_is_in_hnf(const fmpz_mat_t A) { slong i, last_i, j, prev_j; /* find last non-zero row */ for (last_i = A->r - 1; last_i >= 0; last_i--) { for (j = 0; j < A->c; j++) { if (!fmpz_is_zero(fmpz_mat_entry(A, last_i, j))) break; } if (j < A->c) break; } /* hermite form structure */ prev_j = -1; for (i = 0; i <= last_i; i++) { slong i2; for (j = 0; j < A->c; j++) { if (!fmpz_is_zero(fmpz_mat_entry(A, i, j))) { if (fmpz_sgn(fmpz_mat_entry(A, i, j)) < 0) return 0; break; } } if (j == A->c || j <= prev_j) return 0; prev_j = j; for (i2 = 0; i2 < i; i2++) { if (fmpz_cmp(fmpz_mat_entry(A, i2, j), fmpz_mat_entry(A, i, j)) >= 0) return 0; if (fmpz_sgn(fmpz_mat_entry(A, i2, j)) < 0) return 0; } } return 1; } flint-3.1.3/src/fmpz_mat/is_in_rref_with_rank.c000066400000000000000000000030071461254215100215700ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_is_in_rref_with_rank(const fmpz_mat_t A, const fmpz_t den, slong rank) { slong i, j, k, prev_pivot; /* bottom should be zero */ for (i = rank; i < A->r; i++) for (j = 0; j < A->c; j++) if (!fmpz_is_zero(fmpz_mat_entry(A, i, j))) return 0; prev_pivot = -1; for (i = 0; i < rank; i++) { for (j = 0; j < A->c; j++) { if (!fmpz_is_zero(fmpz_mat_entry(A, i, j))) { /* pivot should have a higher column index than previous */ if (j <= prev_pivot) return 0; /* column should be 0 ... 0 1 0 ... 0 */ for (k = 0; k < rank; k++) { if (i == k && !fmpz_equal(fmpz_mat_entry(A, k, j), den)) return 0; if (i != k && !fmpz_is_zero(fmpz_mat_entry(A, k, j))) return 0; } prev_pivot = j; break; } } } return 1; } flint-3.1.3/src/fmpz_mat/is_in_snf.c000066400000000000000000000023061461254215100173530ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_is_in_snf(const fmpz_mat_t A) { slong i, j; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (i == j) { if (fmpz_sgn(fmpz_mat_entry(A, i, i)) < 0) return 0; if (i > 0) { if (!fmpz_is_zero(fmpz_mat_entry(A, i, i)) && fmpz_is_zero(fmpz_mat_entry(A, i - 1, i - 1))) return 0; if (!fmpz_divisible(fmpz_mat_entry(A, i, i), fmpz_mat_entry(A, i - 1, i - 1))) return 0; } } else if (!fmpz_is_zero(fmpz_mat_entry(A, i, j))) return 0; } } return 1; } flint-3.1.3/src/fmpz_mat/is_one.c000066400000000000000000000014621461254215100166620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_is_one(const fmpz_mat_t mat) { slong i, j; if (mat->r == 0 || mat->c == 0) return 1; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (fmpz_cmp_ui(fmpz_mat_entry(mat, i, j), i == j) != 0) { return 0; } } } return 1; } flint-3.1.3/src/fmpz_mat/is_reduced.c000066400000000000000000000056471461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" int fmpz_mat_is_reduced(const fmpz_mat_t A, double delta, double eta) { int res; slong i, j, k, d = A->r, n = A->c; fmpq_mat_t Aq, Bq, mu; mpq_t deltax, etax; fmpq_t deltaq, etaq, tmp; if (d == 0 || d == 1) return 1; fmpq_mat_init(Aq, d, n); fmpq_mat_init(Bq, d, n); fmpq_mat_init(mu, d, d); mpq_init(deltax); mpq_init(etax); fmpq_init(deltaq); fmpq_init(etaq); fmpq_init(tmp); fmpq_mat_set_fmpz_mat(Aq, A); mpq_set_d(deltax, delta); mpq_set_d(etax, eta); fmpq_set_mpq(deltaq, deltax); fmpq_set_mpq(etaq, etax); mpq_clears(deltax, etax, NULL); for (j = 0; j < n; j++) { fmpq_set(fmpq_mat_entry(Bq, 0, j), fmpq_mat_entry(Aq, 0, j)); } /* diagonal of mu stores the squared GS norms */ _fmpq_vec_dot(fmpq_mat_entry(mu, 0, 0), Bq->rows[0], Bq->rows[0], n); for (i = 1; i < d; i++) { for (j = 0; j < n; j++) { fmpq_set(fmpq_mat_entry(Bq, i, j), fmpq_mat_entry(Aq, i, j)); } for (j = 0; j < i; j++) { _fmpq_vec_dot(tmp, Aq->rows[i], Bq->rows[j], n); /* avoid division by zero (???) */ if (fmpq_is_zero(fmpq_mat_entry(mu, j, j))) { res = 0; goto cleanup; } fmpq_div(fmpq_mat_entry(mu, i, j), tmp, fmpq_mat_entry(mu, j, j)); for (k = 0; k < n; k++) { fmpq_submul(fmpq_mat_entry(Bq, i, k), fmpq_mat_entry(mu, i, j), fmpq_mat_entry(Bq, j, k)); } fmpq_abs(tmp, fmpq_mat_entry(mu, i, j)); if (fmpq_cmp(tmp, etaq) > 0) /* check size reduction */ { res = 0; goto cleanup; } } fmpq_set(tmp, deltaq); fmpq_submul(tmp, fmpq_mat_entry(mu, i, i - 1), fmpq_mat_entry(mu, i, i - 1)); fmpq_mul(tmp, tmp, fmpq_mat_entry(mu, i - 1, i - 1)); _fmpq_vec_dot(fmpq_mat_entry(mu, i, i), Bq->rows[i], Bq->rows[i], n); if (fmpq_cmp(tmp, fmpq_mat_entry(mu, i, i)) > 0) /* check Lovasz condition */ { res = 0; goto cleanup; } } res = 1; cleanup: fmpq_mat_clear(Aq); fmpq_mat_clear(Bq); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); return res; } flint-3.1.3/src/fmpz_mat/is_reduced_gram.c000066400000000000000000000054141461254215100205230ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" int fmpz_mat_is_reduced_gram(const fmpz_mat_t A, double delta, double eta) { slong i, j, k, d = A->r; fmpq_mat_t r, mu; fmpq *s; mpq_t deltax, etax; fmpq_t deltaq, etaq, tmp; if (d == 0 || d == 1) return 1; fmpq_mat_init(r, d, d); fmpq_mat_init(mu, d, d); s = _fmpq_vec_init(d); mpq_init(deltax); mpq_init(etax); fmpq_init(deltaq); fmpq_init(etaq); fmpq_init(tmp); mpq_set_d(deltax, delta); mpq_set_d(etax, eta); fmpq_set_mpq(deltaq, deltax); fmpq_set_mpq(etaq, etax); mpq_clears(deltax, etax, NULL); fmpz_set(fmpq_mat_entry_num(r, 0, 0), fmpz_mat_entry(A, 0, 0)); for (i = 1; i < d; i++) { fmpz_set(fmpq_numref(s), fmpz_mat_entry(A, i, i)); fmpz_one(fmpq_denref(s)); for (j = 0; j <= i - 1; j++) { fmpz_set(fmpq_mat_entry_num(r, i, j), fmpz_mat_entry(A, i, j)); for (k = 0; k <= j - 1; k++) { fmpq_submul(fmpq_mat_entry(r, i, j), fmpq_mat_entry(mu, j, k), fmpq_mat_entry(r, i, k)); } fmpq_div(fmpq_mat_entry(mu, i, j), fmpq_mat_entry(r, i, j), fmpq_mat_entry(r, j, j)); fmpq_abs(tmp, fmpq_mat_entry(mu, i, j)); if (fmpq_cmp(tmp, etaq) > 0) /* check size reduction */ { fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); _fmpq_vec_clear(s, d); return 0; } fmpq_set(s + j + 1, s + j); fmpq_submul(s + j + 1, fmpq_mat_entry(mu, i, j), fmpq_mat_entry(r, i, j)); } fmpq_set(fmpq_mat_entry(r, i, i), s + i); fmpq_mul(tmp, deltaq, fmpq_mat_entry(r, i - 1, i - 1)); if (fmpq_cmp(tmp, s + i - 1) > 0) /* check Lovasz condition */ { fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); _fmpq_vec_clear(s, d); return 0; } } fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); _fmpq_vec_clear(s, d); return 1; } flint-3.1.3/src/fmpz_mat/is_reduced_gram_with_removal.c000066400000000000000000000075401461254215100233050ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" int fmpz_mat_is_reduced_gram_with_removal(const fmpz_mat_t A, double delta, double eta, const fmpz_t gs_B, int newd) { slong i, j, k, d = A->r; fmpq_mat_t r, mu; fmpq *s; mpq_t deltax, etax; fmpq_t deltaq, etaq, tmp, gs_Bq; if (d == 0 || d == 1) return 1; fmpq_mat_init(r, d, d); fmpq_mat_init(mu, d, d); s = _fmpq_vec_init(d); mpq_init(deltax); mpq_init(etax); fmpq_init(deltaq); fmpq_init(etaq); fmpq_init(tmp); fmpq_init(gs_Bq); mpq_set_d(deltax, delta); mpq_set_d(etax, eta); fmpq_set_mpq(deltaq, deltax); fmpq_set_mpq(etaq, etax); mpq_clears(deltax, etax, NULL); fmpz_set(fmpq_mat_entry_num(r, 0, 0), fmpz_mat_entry(A, 0, 0)); if (newd == 0 && fmpz_cmp(fmpz_mat_entry(A, 0, 0), gs_B) < 0) { fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); fmpq_clear(gs_Bq); _fmpq_vec_clear(s, d); return 0; } fmpz_set(fmpq_numref(gs_Bq), gs_B); fmpz_one(fmpq_denref(gs_Bq)); for (i = 1; i < d; i++) { fmpz_set(fmpq_numref(s), fmpz_mat_entry(A, i, i)); fmpz_one(fmpq_denref(s)); for (j = 0; j <= i - 1; j++) { fmpz_set(fmpq_mat_entry_num(r, i, j), fmpz_mat_entry(A, i, j)); for (k = 0; k <= j - 1; k++) { fmpq_submul(fmpq_mat_entry(r, i, j), fmpq_mat_entry(mu, j, k), fmpq_mat_entry(r, i, k)); } fmpq_div(fmpq_mat_entry(mu, i, j), fmpq_mat_entry(r, i, j), fmpq_mat_entry(r, j, j)); if (i < newd) { fmpq_abs(tmp, fmpq_mat_entry(mu, i, j)); if (fmpq_cmp(tmp, etaq) > 0) /* check size reduction */ { fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); fmpq_clear(gs_Bq); _fmpq_vec_clear(s, d); return 0; } } fmpq_set(s + j + 1, s + j); fmpq_submul(s + j + 1, fmpq_mat_entry(mu, i, j), fmpq_mat_entry(r, i, j)); } fmpq_set(fmpq_mat_entry(r, i, i), s + i); if (i >= newd && fmpq_cmp(fmpq_mat_entry(r, i, i), gs_Bq) < 0) /* check removals */ { fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); fmpq_clear(gs_Bq); _fmpq_vec_clear(s, d); return 0; } if (i < newd) { fmpq_mul(tmp, deltaq, fmpq_mat_entry(r, i - 1, i - 1)); if (fmpq_cmp(tmp, s + i - 1) > 0) /* check Lovasz condition */ { fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); fmpq_clear(gs_Bq); _fmpq_vec_clear(s, d); return 0; } } } fmpq_mat_clear(r); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); fmpq_clear(gs_Bq); _fmpq_vec_clear(s, d); return 1; } flint-3.1.3/src/fmpz_mat/is_reduced_with_removal.c000066400000000000000000000067311461254215100223000ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" int fmpz_mat_is_reduced_with_removal(const fmpz_mat_t A, double delta, double eta, const fmpz_t gs_B, int newd) { int res; slong i, j, k, d = A->r, n = A->c; fmpq_mat_t Aq, Bq, mu; mpq_t deltax, etax; fmpq_t deltaq, etaq, tmp, gs_Bq; if (d == 0 || d == 1) return 1; fmpq_mat_init(Aq, d, n); fmpq_mat_init(Bq, d, n); fmpq_mat_init(mu, d, d); mpq_init(deltax); mpq_init(etax); fmpq_init(deltaq); fmpq_init(etaq); fmpq_init(tmp); fmpq_init(gs_Bq); mpq_set_d(deltax, delta); mpq_set_d(etax, eta); fmpq_set_mpq(deltaq, deltax); fmpq_set_mpq(etaq, etax); mpq_clears(deltax, etax, NULL); fmpq_mat_set_fmpz_mat(Aq, A); fmpz_set(fmpq_numref(gs_Bq), gs_B); fmpz_one(fmpq_denref(gs_Bq)); for (j = 0; j < n; j++) { fmpq_set(fmpq_mat_entry(Bq, 0, j), fmpq_mat_entry(Aq, 0, j)); } /* diagonal of mu stores the squared GS norms */ _fmpq_vec_dot(fmpq_mat_entry(mu, 0, 0), Bq->rows[0], Bq->rows[0], n); if (newd == 0 && fmpq_cmp(fmpq_mat_entry(mu, 0, 0), gs_Bq) < 0) { res = 0; goto cleanup; } for (i = 1; i < d; i++) { for (j = 0; j < n; j++) { fmpq_set(fmpq_mat_entry(Bq, i, j), fmpq_mat_entry(Aq, i, j)); } for (j = 0; j < i; j++) { _fmpq_vec_dot(tmp, Aq->rows[i], Bq->rows[j], n); /* avoid division by zero */ if (fmpq_is_zero(fmpq_mat_entry(mu, j, j))) { res = 0; goto cleanup; } fmpq_div(fmpq_mat_entry(mu, i, j), tmp, fmpq_mat_entry(mu, j, j)); for (k = 0; k < n; k++) { fmpq_submul(fmpq_mat_entry(Bq, i, k), fmpq_mat_entry(mu, i, j), fmpq_mat_entry(Bq, j, k)); } if (i < newd) { fmpq_abs(tmp, fmpq_mat_entry(mu, i, j)); if (fmpq_cmp(tmp, etaq) > 0) /* check size reduction */ { res = 0; goto cleanup; } } } _fmpq_vec_dot(fmpq_mat_entry(mu, i, i), Bq->rows[i], Bq->rows[i], n); if (i >= newd && fmpq_cmp(fmpq_mat_entry(mu, i, i), gs_Bq) < 0) /* check removals */ { res = 0; goto cleanup; } if (i < newd) { fmpq_set(tmp, deltaq); fmpq_submul(tmp, fmpq_mat_entry(mu, i, i - 1), fmpq_mat_entry(mu, i, i - 1)); fmpq_mul(tmp, tmp, fmpq_mat_entry(mu, i - 1, i - 1)); if (fmpq_cmp(tmp, fmpq_mat_entry(mu, i, i)) > 0) /* check Lovasz condition */ { res = 0; goto cleanup; } } } res = 1; cleanup: fmpq_mat_clear(Aq); fmpq_mat_clear(Bq); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); fmpq_clear(gs_Bq); return res; } flint-3.1.3/src/fmpz_mat/is_spd.c000066400000000000000000000042571461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2023 Jean Kieffer This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mat.h" #include "arb_mat.h" static int fmpz_mat_is_spd_arb(const fmpz_mat_t A) { slong d = fmpz_mat_nrows(A); slong prec; slong maxprec = 32; arb_mat_t M, L; slong j, k; int res = 0; arb_mat_init(M, d, d); arb_mat_init(L, d, d); for (j = 0; j < d; j++) { for (k = 0; k <= j; k++) { maxprec = FLINT_MAX(maxprec, 32 + fmpz_bits(fmpz_mat_entry(A, j, k))); } } arb_mat_set_fmpz_mat(M, A); for (prec = 32; (prec < 4 * maxprec) && !res; prec *= 2) { res = arb_mat_ldl(L, M, prec); } arb_mat_clear(M); arb_mat_clear(L); return res; } static int fmpz_mat_is_spd_charpoly(const fmpz_mat_t A) { slong d = fmpz_mat_nrows(A); fmpz_poly_t pol; fmpz_t c; slong k; int res = 1; fmpz_poly_init(pol); fmpz_init(c); fmpz_mat_charpoly(pol, A); /* Descartes' rule of signs: pol has only positive roots iff (-1)^k a_k are all positive */ for (k = 1; (k <= d) && res; k++) { fmpz_poly_get_coeff_fmpz(c, pol, d - k); if (k % 2 == 1) { fmpz_neg(c, c); } if (fmpz_cmp_si(c, 0) <= 0) { res = 0; } } fmpz_poly_clear(pol); return res; } int fmpz_mat_is_spd(const fmpz_mat_t A) { slong d = fmpz_mat_nrows(A); slong k, j; if (fmpz_mat_ncols(A) != d) { return 0; } for (j = 0; j < d; j++) { for (k = 0; k < j; k++) { if (!fmpz_equal(fmpz_mat_entry(A, j, k), fmpz_mat_entry(A, k, j))) { return 0; } } } if (fmpz_mat_is_spd_arb(A)) { return 1; } else { return fmpz_mat_is_spd_charpoly(A); } } flint-3.1.3/src/fmpz_mat/is_zero.c000066400000000000000000000014311461254215100170540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" int fmpz_mat_is_zero(const fmpz_mat_t mat) { slong j; if (mat->r == 0 || mat->c == 0) return 1; for (j = 0; j < mat->r; j++) { if (!_fmpz_vec_is_zero(mat->rows[j], mat->c)) return 0; } return 1; } int fmpz_mat_is_zero_row(const fmpz_mat_t mat, slong i) { return _fmpz_vec_is_zero(mat->rows[i], mat->c); } flint-3.1.3/src/fmpz_mat/kronecker_product.c000066400000000000000000000017451461254215100211350ustar00rootroot00000000000000/* Copyright (C) 2018 Martin Raum This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_kronecker_product(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong i, j, k, l; slong ir, jc; fmpz * Aentry; for (i = 0, ir = 0; i < A->r; i++, ir += B->r) { for (j = 0, jc = 0; j < A->c; j++, jc += B->c) { Aentry = fmpz_mat_entry(A, i, j); for (k = 0; k < B->r; k++) { for (l = 0; l < B->c; l++) { fmpz_mul(fmpz_mat_entry(C, ir + k, jc + l), Aentry, fmpz_mat_entry(B, k, l)); } } } } } flint-3.1.3/src/fmpz_mat/lll_original.c000066400000000000000000000136031461254215100200550ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" void fmpz_mat_lll_original(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta) { slong i, j, k, l, m, n; fmpz_t r, one; fmpq_t chi, nu, xi, half, rat; fmpq_mat_t R, mu; if (A->r == 0) { return; } m = A->r; n = A->c; fmpq_mat_init(R, m, m); fmpq_mat_init(mu, m, m); fmpz_init(r); fmpz_init_set_ui(one, 1); fmpq_init(chi); fmpq_init(nu); fmpq_init(xi); fmpq_init(half); fmpq_init(rat); fmpq_set_si(half, 1, 2); /* compute the rational GSO */ for (i = 0; i < m; i++) { _fmpz_vec_dot(fmpq_mat_entry_num(mu, i, i), A->rows[i], A->rows[i], n); for (j = 0; j <= i - 1; j++) { _fmpz_vec_dot(fmpq_mat_entry_num(R, i, j), A->rows[i], A->rows[j], n); for (k = 0; k <= j - 1; k++) { fmpq_submul(fmpq_mat_entry(R, i, j), fmpq_mat_entry(mu, j, k), fmpq_mat_entry(R, i, k)); } fmpq_div(fmpq_mat_entry(mu, i, j), fmpq_mat_entry(R, i, j), fmpq_mat_entry(mu, j, j)); fmpq_submul(fmpq_mat_entry(mu, i, i), fmpq_mat_entry(mu, i, j), fmpq_mat_entry(R, i, j)); } } /* index k counts the current number of LLL-reduced rows */ k = 1; while (k < m) { /* size reduce row k against row k - 1 */ fmpq_abs(rat, fmpq_mat_entry(mu, k, k - 1)); if (fmpq_cmp(rat, eta) > 0) { /* determine reduction coefficient */ fmpq_sub(rat, fmpq_mat_entry(mu, k, k - 1), half); fmpz_cdiv_q(r, fmpq_numref(rat), fmpq_denref(rat)); /* perform reduction */ for (i = 0; i < n; i++) fmpz_submul(fmpz_mat_entry(A, k, i), r, fmpz_mat_entry(A, k - 1, i)); /* update mu */ fmpq_set_fmpz_frac(rat, r, one); for (j = 0; j <= k - 2; j++) fmpq_submul(fmpq_mat_entry(mu, k, j), rat, fmpq_mat_entry(mu, k - 1, j)); fmpq_sub(fmpq_mat_entry(mu, k, k - 1), fmpq_mat_entry(mu, k, k - 1), rat); } /* check exchange condition */ fmpq_set(rat, delta); fmpq_submul(rat, fmpq_mat_entry(mu, k, k - 1), fmpq_mat_entry(mu, k, k - 1)); fmpq_mul(rat, rat, fmpq_mat_entry(mu, k - 1, k - 1)); if (fmpq_cmp(fmpq_mat_entry(mu, k, k), rat) >= 0) { for (l = k - 2; l >= 0; l--) { /* size reduce row k against row l */ fmpq_abs(rat, fmpq_mat_entry(mu, k, l)); if (fmpq_cmp(rat, eta) > 0) { fmpq_sub(rat, fmpq_mat_entry(mu, k, l), half); fmpz_cdiv_q(r, fmpq_numref(rat), fmpq_denref(rat)); for (i = 0; i < n; i++) fmpz_submul(fmpz_mat_entry(A, k, i), r, fmpz_mat_entry(A, l, i)); fmpq_set_fmpz_frac(rat, r, one); for (j = 0; j <= l - 1; j++) fmpq_submul(fmpq_mat_entry(mu, k, j), rat, fmpq_mat_entry(mu, l, j)); fmpq_sub(fmpq_mat_entry(mu, k, l), fmpq_mat_entry(mu, k, l), rat); } } /* increment LLL-reduced index */ k++; } else { fmpq_set(nu, fmpq_mat_entry(mu, k, k - 1)); fmpq_mul(chi, fmpq_mat_entry(mu, k - 1, k - 1), nu); fmpq_mul(chi, chi, nu); fmpq_add(chi, chi, fmpq_mat_entry(mu, k, k)); fmpq_mul(fmpq_mat_entry(mu, k, k - 1), fmpq_mat_entry(mu, k, k - 1), fmpq_mat_entry(mu, k - 1, k - 1)); fmpq_div(fmpq_mat_entry(mu, k, k - 1), fmpq_mat_entry(mu, k, k - 1), chi); fmpq_mul(fmpq_mat_entry(mu, k, k), fmpq_mat_entry(mu, k, k), fmpq_mat_entry(mu, k - 1, k - 1)); fmpq_div(fmpq_mat_entry(mu, k, k), fmpq_mat_entry(mu, k, k), chi); fmpq_set(fmpq_mat_entry(mu, k - 1, k - 1), chi); /* swap row k - 1 and row k */ fmpz_mat_swap_rows(A, NULL, k - 1, k); /* update mu */ for (j = 0; j <= k - 2; j++) { fmpq_swap(fmpq_mat_entry(mu, k - 1, j), fmpq_mat_entry(mu, k, j)); } for (i = k + 1; i < m; i++) { fmpq_set(xi, fmpq_mat_entry(mu, i, k)); fmpq_set(fmpq_mat_entry(mu, i, k), fmpq_mat_entry(mu, i, k - 1)); fmpq_submul(fmpq_mat_entry(mu, i, k), nu, xi); fmpq_mul(fmpq_mat_entry(mu, i, k - 1), fmpq_mat_entry(mu, k, k - 1), fmpq_mat_entry(mu, i, k)); fmpq_add(fmpq_mat_entry(mu, i, k - 1), fmpq_mat_entry(mu, i, k - 1), xi); } /* decrement LLL-reduced index */ if (k > 1) k--; } } fmpz_clear(r); fmpz_clear(one); fmpq_clear(chi); fmpq_clear(nu); fmpq_clear(xi); fmpq_clear(half); fmpq_clear(rat); fmpq_mat_clear(R); fmpq_mat_clear(mu); } flint-3.1.3/src/fmpz_mat/lll_storjohann.c000066400000000000000000000204531461254215100204370ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __GNUC__ # define ceil __builtin_ceil # define sqrt __builtin_sqrt #else # include #endif #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" void fmpz_mat_lll_storjohann(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta) { slong n, np, i, j, k; double e; fmpz_t M, lhs, rhs; fmpz_mat_t T; fmpq_t max, gsn, half; if (A->r == 0) { return; } n = A->r; np = A->c; fmpz_init(M); fmpz_init(lhs); fmpz_init(rhs); fmpz_mat_init(T, n, n); fmpz_mat_gram(T, A); for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { for (k = i + 1; k < n; k++) { fmpz_mul(fmpz_mat_entry(T, j, k), fmpz_mat_entry(T, j, k), fmpz_mat_entry(T, i, i)); fmpz_submul(fmpz_mat_entry(T, j, k), fmpz_mat_entry(T, j, i), fmpz_mat_entry(T, i, k)); if (i > 0) { fmpz_divexact(fmpz_mat_entry(T, j, k), fmpz_mat_entry(T, j, k), fmpz_mat_entry(T, i - 1, i - 1)); } } fmpz_zero(fmpz_mat_entry(T, j, i)); } } fmpq_init(max); fmpq_init(gsn); fmpq_init(half); fmpq_set_si(half, 1, 2); fmpz_set(fmpq_numref(max), fmpz_mat_entry(T, 0, 0)); fmpz_one(fmpq_denref(max)); for (i = 1; i < n; i++) { fmpq_set_fmpz_frac(gsn, fmpz_mat_entry(T, i, i), fmpz_mat_entry(T, i - 1, i - 1)); if (fmpq_cmp(gsn, max) > 0) { fmpq_set(max, gsn); } } fmpz_set_si(M, n); fmpq_mul_fmpz(max, max, M); e = 2 * ceil(sqrt (n * fmpz_get_d(fmpq_numref(max)) / fmpz_get_d(fmpq_denref(max)))) + 1; fmpz_set_d(M, e); k = 1; while (k < n) { fmpq_set_fmpz_frac(max, fmpz_mat_entry(T, k - 1, k), fmpz_mat_entry(T, k - 1, k - 1)); fmpq_abs(gsn, max); if (fmpq_cmp(gsn, eta) > 0) { fmpq_sub(max, max, half); fmpz_cdiv_q(lhs, fmpq_numref(max), fmpq_denref(max)); _fmpz_vec_scalar_submul_fmpz(A->rows[k], A->rows[k - 1], np, lhs); for (i = 0; i < n; i++) { fmpz_submul(fmpz_mat_entry(T, i, k), lhs, fmpz_mat_entry(T, i, k - 1)); if (i <= k - 1) { fmpz_mul(rhs, fmpz_mat_entry(T, i, i), M); if (i > 0) { fmpz_mul(rhs, rhs, fmpz_mat_entry(T, i - 1, i - 1)); } fmpz_smod(fmpz_mat_entry(T, i, k), fmpz_mat_entry(T, i, k), rhs); } } for (j = 0; j < np; j++) { fmpz_smod(fmpz_mat_entry(A, k, j), fmpz_mat_entry(A, k, j), M); } } fmpq_set_fmpz_frac(max, fmpz_mat_entry(T, k, k), fmpz_mat_entry(T, k - 1, k - 1)); fmpq_div_fmpz(max, max, fmpz_mat_entry(T, k - 1, k - 1)); if (k > 1) { fmpq_mul_fmpz(max, max, fmpz_mat_entry(T, k - 2, k - 2)); } fmpq_set(gsn, delta); _fmpq_submul(fmpq_numref(gsn), fmpq_denref(gsn), fmpz_mat_entry(T, k - 1, k), fmpz_mat_entry(T, k - 1, k - 1), fmpz_mat_entry(T, k - 1, k), fmpz_mat_entry(T, k - 1, k - 1)); if (fmpq_cmp(max, gsn) < 0) { fmpz_mat_swap_rows(A, NULL, k - 1, k); if (k > 1) { _fmpz_vec_scalar_mul_fmpz(T->rows[k], T->rows[k], n, fmpz_mat_entry(T, k - 2, k - 2)); } _fmpz_vec_scalar_addmul_fmpz(T->rows[k], T->rows[k - 1], n, fmpz_mat_entry(T, k - 1, k)); _fmpz_vec_scalar_divexact_fmpz(T->rows[k], T->rows[k], n, fmpz_mat_entry(T, k - 1, k - 1)); fmpz_mat_swap_rows(T, NULL, k - 1, k); for (i = 0; i < n; i++) { fmpz_swap(fmpz_mat_entry(T, i, k - 1), fmpz_mat_entry(T, i, k)); } _fmpz_vec_scalar_mul_fmpz(T->rows[k], T->rows[k], n, fmpz_mat_entry(T, k - 1, k - 1)); _fmpz_vec_scalar_submul_fmpz(T->rows[k], T->rows[k - 1], n, fmpz_mat_entry(T, k - 1, k)); if (k > 1) { _fmpz_vec_scalar_divexact_fmpz(T->rows[k], T->rows[k], n, fmpz_mat_entry(T, k - 2, k - 2)); } for (i = 0; i <= k - 2; i++) { fmpz_mul(rhs, fmpz_mat_entry(T, i, i), M); if (i > 0) { fmpz_mul(rhs, rhs, fmpz_mat_entry(T, i - 1, i - 1)); } fmpz_smod(fmpz_mat_entry(T, i, k - 1), fmpz_mat_entry(T, i, k - 1), rhs); fmpz_smod(fmpz_mat_entry(T, i, k), fmpz_mat_entry(T, i, k), rhs); } fmpz_mul(rhs, fmpz_mat_entry(T, k - 1, k - 1), M); fmpz_mul(lhs, rhs, fmpz_mat_entry(T, k, k)); if (k > 1) { fmpz_mul(rhs, rhs, fmpz_mat_entry(T, k - 2, k - 2)); } fmpz_smod(fmpz_mat_entry(T, k - 1, k), fmpz_mat_entry(T, k - 1, k), rhs); for (j = k + 1; j < n; j++) { fmpz_smod(fmpz_mat_entry(T, k - 1, j), fmpz_mat_entry(T, k - 1, j), rhs); fmpz_smod(fmpz_mat_entry(T, k, j), fmpz_mat_entry(T, k, j), lhs); } if (k > 1) k--; } else { k++; } } for (k = 1; k < n; k++) { for (j = k - 1; j >= 0; j--) { fmpq_set_fmpz_frac(max, fmpz_mat_entry(T, j, k), fmpz_mat_entry(T, j, j)); fmpq_abs(gsn, max); if (fmpq_cmp(gsn, eta) > 0) { fmpq_sub(max, max, half); fmpz_cdiv_q(lhs, fmpq_numref(max), fmpq_denref(max)); _fmpz_vec_scalar_submul_fmpz(A->rows[k], A->rows[j], np, lhs); for (i = 0; i < n; i++) { fmpz_submul(fmpz_mat_entry(T, i, k), lhs, fmpz_mat_entry(T, i, j)); if (i <= k - 1) { fmpz_mul(rhs, fmpz_mat_entry(T, i, i), M); if (i > 0) { fmpz_mul(rhs, rhs, fmpz_mat_entry(T, i - 1, i - 1)); } fmpz_smod(fmpz_mat_entry(T, i, k), fmpz_mat_entry(T, i, k), rhs); } } for (i = 0; i < np; i++) { fmpz_smod(fmpz_mat_entry(A, k, i), fmpz_mat_entry(A, k, i), M); } } } } fmpz_clear(M); fmpz_clear(lhs); fmpz_clear(rhs); fmpz_mat_clear(T); fmpq_clear(max); fmpq_clear(gsn); fmpq_clear(half); } flint-3.1.3/src/fmpz_mat/max_bits.c000066400000000000000000000015641461254215100172170ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" slong fmpz_mat_max_bits(const fmpz_mat_t mat) { slong i; slong bits, row_bits, sign; sign = 1; bits = 0; if (mat->r == 0 || mat->c == 0) return 0; for (i = 0; i < mat->r; i++) { row_bits = _fmpz_vec_max_bits(mat->rows[i], mat->c); if (row_bits < 0) { row_bits = -row_bits; sign = -1; } bits = FLINT_MAX(bits, row_bits); } return bits * sign; } flint-3.1.3/src/fmpz_mat/minpoly_modular.c000066400000000000000000000164051461254215100206230ustar00rootroot00000000000000/* Copyright (C) 2013 Sebastian Pancratz Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mat.h" #define MINPOLY_M_LOG2E 1.44269504088896340736 /* log2(e) */ static inline long double _log2(const long double x) { return log(x) * MINPOLY_M_LOG2E; } slong _fmpz_mat_minpoly_small(fmpz * rop, const fmpz_mat_t op) { slong len = 0; if (op->r == 0) { fmpz_one(rop + 0); len = 1; } else if (op->r == 1) { fmpz_one(rop + 1); fmpz_neg(rop + 0, &(op->rows[0][0])); len = 2; } return len; } void _fmpz_mat_bound_ovals_of_cassini(fmpz_t b, const fmpz_mat_t op) { slong n = op->r, i, j; fmpz * v1; fmpz_t t, q, r1, r2; fmpz_init(t); fmpz_init(q); fmpz_init(r1); fmpz_init(r2); v1 = _fmpz_vec_init(n); /* |A| [1,1,...,1]^T */ for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (fmpz_sgn(fmpz_mat_entry(op, i, j)) >= 0) fmpz_add(v1 + i, v1 + i, fmpz_mat_entry(op, i, j)); else fmpz_sub(v1 + i, v1 + i, fmpz_mat_entry(op, i, j)); } } for (i = 0; i < n; i++) { fmpz_zero(t); /* q_i */ fmpz_abs(t, fmpz_mat_entry(op, i, i)); if (fmpz_cmp(t, q) > 0) fmpz_set(q, t); /* r_i */ fmpz_sub(t, v1 + i, t); if (fmpz_cmp(t, r2) > 0) { fmpz_swap(t, r2); if (fmpz_cmp(r2, r1) > 0) fmpz_swap(r2, r1); } } fmpz_mul(r1, r1, r2); fmpz_sqrtrem(b, r2, r1); if (!fmpz_is_zero(r2)) fmpz_add_ui(b, b, 1); fmpz_add(b, b, q); _fmpz_vec_clear(v1, n); fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(t); fmpz_clear(q); } slong _fmpz_mat_minpoly_modular(fmpz * rop, const fmpz_mat_t op) { const slong n = op->r; slong len = 0, oldlen = 0; if (n < 2) { return _fmpz_mat_minpoly_small(rop, op); } else { /* If $A$ is an $n \times n$ matrix with spectral radius bound by b, the coefficients of the minimal polynomial have at most $\ceil{d\log_2(b)}$ bits if $d \leq b$. Otherwise if $d > 0$ it has at most $\min{\ceil{d/2\log_2(bd)}, \ceil{d\log_2(2b)}}$ bits, where $d$ is the degree of the minimal polynomial. See Lemma 3.1 in Dumas, "Bounds on the coefficients of the characteristic and minimal polynomials", 2007. */ slong bound; double b1, b2, b3, bb; slong pbits = FLINT_BITS - 1, i, j; mp_limb_t p = (UWORD(1) << pbits); ulong * P, * Q; fmpz_mat_t v1, v2, v3; fmpz * rold; fmpz_t m; if (fmpz_mat_is_zero(op)) { fmpz_set_ui(rop + 0, 1); return 1; } /* Determine the bound in bits */ { fmpz_t b; fmpz_init(b); _fmpz_mat_bound_ovals_of_cassini(b, op); bb = fmpz_get_d(b); if (bb <= 1.0) bb = 1.0; b1 = _log2(bb); b2 = _log2(bb*n)/2; b3 = _log2(bb*2); if (b3 < b2) b2 = b3; bound = n <= bb ? (slong) ceil(n*b1) : (slong) ceil(n*b2); bound = bound + 1; fmpz_clear(b); } P = (ulong *) flint_calloc(n, sizeof(ulong)); Q = (ulong *) flint_calloc(n, sizeof(ulong)); rold = (fmpz *) _fmpz_vec_init(n + 1); fmpz_mat_init(v1, n, 1); fmpz_mat_init(v2, n, 1); fmpz_mat_init(v3, n, 1); fmpz_init_set_ui(m, 1); oldlen = 0; len = 0; for ( ; fmpz_bits(m) <= bound; ) { nmod_mat_t mat; nmod_poly_t poly; p = n_nextprime(p, 0); nmod_mat_init(mat, n, n, p); nmod_poly_init(poly, p); for (i = 0; i < n; i++) P[i] = 0; fmpz_mat_get_nmod_mat(mat, op); nmod_mat_minpoly_with_gens(poly, mat, P); len = poly->length; if (oldlen != 0 && len > oldlen) { /* all previous primes were bad, discard */ fmpz_one(m); oldlen = len; for (i = 0; i < n + 1; i++) fmpz_zero(rop + i); for (i = 0; i < n; i++) Q[i] = 0; } else if (len < oldlen) { /* this prime was bad, skip */ nmod_mat_clear(mat); nmod_poly_clear(poly); continue; } for (i = 0; i < n; i++) Q[i] |= P[i]; _fmpz_poly_CRT_ui(rop, rop, n + 1, m, poly->coeffs, poly->length, poly->mod.n, poly->mod.ninv, 1); fmpz_mul_ui(m, m, p); /* check if stabilised */ for (i = 0; i < len; i++) { if (!fmpz_equal(rop + i, rold + i)) break; } for (j = 0; j < len; j++) fmpz_set(rold + j, rop + j); if (i == len) /* stabilised */ { for (i = 0; i < n; i++) { if (Q[i] == 1) { fmpz_mat_zero(v1); fmpz_mat_zero(v3); fmpz_set_ui(fmpz_mat_entry(v1, i, 0), 1); for (j = 0; j < len; j++) { fmpz_mat_scalar_mul_fmpz(v2, v1, rop + j); fmpz_mat_add(v3, v3, v2); if (j != len - 1) { fmpz_mat_mul(v2, op, v1); fmpz_mat_swap(v1, v2); } } /* check f(A)v = 0 */ for (j = 0; j < n; j++) { if (!fmpz_is_zero(v3->rows[j] + 0)) break; } if (j != n) break; } } /* if f(A)v = 0 for all generators v, we are done */ if (i == n) { nmod_mat_clear(mat); nmod_poly_clear(poly); break; } } nmod_mat_clear(mat); nmod_poly_clear(poly); } flint_free(P); flint_free(Q); fmpz_mat_clear(v2); fmpz_mat_clear(v1); fmpz_mat_clear(v3); fmpz_clear(m); _fmpz_vec_clear(rold, n); } return len; } void fmpz_mat_minpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat) { slong len; fmpz_poly_fit_length(cp, mat->r + 1); len = _fmpz_mat_minpoly_modular(cp->coeffs, mat); _fmpz_poly_set_length(cp, len); } flint-3.1.3/src/fmpz_mat/mul.c000066400000000000000000000173511461254215100162070ustar00rootroot00000000000000/* Copyright (C) 2010, 2011, 2018, 2024 Fredrik Johansson Copyright (C) 2016 Aaditya Thakkar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void _fmpz_mat_mul_small_1(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong ar, br, bc; slong i, j, k; ar = fmpz_mat_nrows(A); br = fmpz_mat_nrows(B); bc = fmpz_mat_ncols(B); fmpz_mat_zero(C); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { slong s = 0; for (k = 0; k < br; k++) s += *fmpz_mat_entry(A, i, k) * (*fmpz_mat_entry(B, k, j)); *fmpz_mat_entry(C, i, j) = s; } } } void _fmpz_mat_mul_small_2a(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong ar, br, bc; slong i, j, k; ar = fmpz_mat_nrows(A); br = fmpz_mat_nrows(B); bc = fmpz_mat_ncols(B); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { mp_limb_t hi, lo, shi, slo; slong x, y; shi = slo = 0; for (k = 0; k < br; k++) { x = *fmpz_mat_entry(A, i, k); y = *fmpz_mat_entry(B, k, j); smul_ppmm(hi, lo, x, y); add_ssaaaa(shi, slo, shi, slo, hi, lo); } fmpz_set_signed_uiui(fmpz_mat_entry(C, i, j), shi, slo); } } } void _fmpz_mat_mul_small_2b(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong ar, br, bc; slong i, j, k; ar = fmpz_mat_nrows(A); br = fmpz_mat_nrows(B); bc = fmpz_mat_ncols(B); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { mp_limb_t hi, lo, shi, smid, slo; slong x, y; shi = smid = slo = 0; for (k = 0; k < br; k++) { x = *fmpz_mat_entry(A, i, k); y = *fmpz_mat_entry(B, k, j); smul_ppmm(hi, lo, x, y); add_sssaaaaaa(shi, smid, slo, shi, smid, slo, FLINT_SIGN_EXT(hi), hi, lo); } fmpz_set_signed_uiuiui(fmpz_mat_entry(C, i, j), shi, smid, slo); } } } void fmpz_mat_mul(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong ar, br, bc; slong abits, bbits; flint_bitcnt_t cbits; slong i, j, dim, limit; int sign; FLINT_ASSERT(C->r == A->r); FLINT_ASSERT(C->c == B->c); FLINT_ASSERT(A->c == B->r); ar = fmpz_mat_nrows(A); br = fmpz_mat_nrows(B); bc = fmpz_mat_ncols(B); if (ar == 0 || br == 0 || bc == 0) { fmpz_mat_zero(C); return; } if (C == A || C == B) { fmpz_mat_t T; fmpz_mat_init(T, ar, bc); fmpz_mat_mul(T, A, B); fmpz_mat_swap_entrywise(C, T); fmpz_mat_clear(T); return; } if (br == 1) { fmpz_mat_mul_classical(C, A, B); return; } /* todo: use Strassen, Waksman or FFT when entries are huge and the matrix is not structured */ if (br == 2) { for (i = 0; i < ar; i++) for (j = 0; j < bc; j++) fmpz_fmma(fmpz_mat_entry(C, i, j), fmpz_mat_entry(A, i, 0), fmpz_mat_entry(B, 0, j), fmpz_mat_entry(A, i, 1), fmpz_mat_entry(B, 1, j)); return; } dim = FLINT_MIN(ar, bc); dim = FLINT_MIN(dim, br); /* TODO: for space reasons maybe just call strassen here if dim > 10000 */ abits = fmpz_mat_max_bits(A); bbits = fmpz_mat_max_bits(B); sign = 0; if (abits < 0) { sign = 1; abits = -abits; } if (bbits < 0) { sign = 1; bbits = -bbits; } if (abits == 0 || bbits == 0) { fmpz_mat_zero(C); return; } cbits = abits + bbits + FLINT_BIT_COUNT(br); #if FLINT_USES_BLAS && FLINT_BITS == 64 if (dim > 50) { if (cbits <= 53) limit = 0; else if (cbits <= 64) limit = 1000; else if (cbits <= 128) limit = 1300; else if (cbits <= 256) limit = 250; else limit = 200 + 8*FLINT_BIT_COUNT(cbits); if (dim > limit && _fmpz_mat_mul_blas(C, A, abits, B, bbits, sign, cbits)) return; } #endif if (abits <= SMALL_FMPZ_BITCOUNT_MAX && bbits <= SMALL_FMPZ_BITCOUNT_MAX) { /* A and B are small fmpz's: strassen is effective at large dimension either through small fmpz's or through multi_mod. The cutoff for multi_mod's strassen has not been observed, but it must exist somewhere past 4000. */ /* first take care of small cases */ if (ar < 9 || ar + br < 20) { if (cbits <= SMALL_FMPZ_BITCOUNT_MAX) _fmpz_mat_mul_small_1(C, A, B); else if (cbits <= 2*FLINT_BITS - 1) _fmpz_mat_mul_small_2a(C, A, B); else _fmpz_mat_mul_small_2b(C, A, B); return; } if (dim > 1000) { /* do more mul_small with more threads */ limit = 300*flint_get_num_threads(); if (cbits <= SMALL_FMPZ_BITCOUNT_MAX && dim - 1000 > limit) { /* strassen avoids big fmpz intermediates */ fmpz_mat_mul_strassen(C, A, B); return; } else if (cbits > SMALL_FMPZ_BITCOUNT_MAX && dim - 4000 > limit) { _fmpz_mat_mul_multi_mod(C, A, B, sign, cbits); return; } } _fmpz_mat_mul_small_internal(C, A, B, cbits); return; } else if (abits + sign <= 2*FLINT_BITS && bbits + sign <= 2*FLINT_BITS) { /* both A and B fit into two words: the complexity of mul_double_word does not depend on cbits much and hence does better as cbits increases, but mul_multi_mod eventually does strassen. */ /* mul_double_word handles unsigned input better than signed input. */ if (sign) dim = 2*dim; if (dim > 300) { /* do more mul_double_word with more threads and more cbits */ limit = (cbits - 2*FLINT_BITS)/8; limit = limit*limit*flint_get_num_threads(); if (dim - 300 > limit) { _fmpz_mat_mul_multi_mod(C, A, B, sign, cbits); return; } } _fmpz_mat_mul_double_word_internal(C, A, B, sign, cbits); return; } else { /* want balanced entries for mul_waksman */ /* todo: should check for structured matrices (favor mul_classical) */ slong min_bits = FLINT_MIN(abits, bbits); slong max_bits = FLINT_MAX(abits, bbits); if (dim >= 3 * FLINT_BIT_COUNT(cbits)) /* tuning param */ _fmpz_mat_mul_multi_mod(C, A, B, sign, cbits); else if (dim < 20 && ((dim == 2 && min_bits >= 5000 && max_bits <= 1.1 * min_bits) || (max_bits <= 1.6 * min_bits && ((dim == 3 && min_bits >= 3000) || (dim >= 4 && min_bits >= 1000) || (dim >= 12 && min_bits >= 500))))) fmpz_mat_mul_waksman(C, A, B); else if (abits >= 500 && bbits >= 500 && dim >= 8) /* tuning param */ fmpz_mat_mul_strassen(C, A, B); else fmpz_mat_mul_classical(C, A, B); } } flint-3.1.3/src/fmpz_mat/mul_blas.c000066400000000000000000000404641461254215100172110ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" /* todo: squaring optimizations */ #if FLINT_USES_BLAS && FLINT_BITS == 64 #include #include "nmod.h" #include "fmpz.h" #include "thread_pool.h" #include "thread_support.h" #include "cblas.h" typedef struct { slong m; slong k; slong n; slong Astartrow; slong Astoprow; slong Bstartrow; slong Bstoprow; fmpz ** Arows; fmpz ** Brows; double * dA; double * dB; } _red_worker_arg; static void _red_worker(void * varg) { _red_worker_arg * arg = (_red_worker_arg *) varg; slong i, j; slong k = arg->k; slong n = arg->n; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong Bstartrow = arg->Bstartrow; slong Bstoprow = arg->Bstoprow; fmpz ** Arows = arg->Arows; fmpz ** Brows = arg->Brows; double * dA = arg->dA; double * dB = arg->dB; for (i = Astartrow; i < Astoprow; i++) for (j = 0; j < k; j++) dA[k*i + j] = (double)(Arows[i][j]); for (i = Bstartrow; i < Bstoprow; i++) for (j = 0; j < n; j++) dB[n*i + j] = (double)(Brows[i][j]); } static int _fmpz_mat_mul_blas_direct( fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong i, j, start, stop; slong m = A->r; slong k = A->c; slong n = B->c; double * dC, * dA, * dB; slong limit; _red_worker_arg mainarg; _red_worker_arg * args; slong num_workers; thread_pool_handle * handles; dA = FLINT_ARRAY_ALLOC(m*k, double); dB = FLINT_ARRAY_ALLOC(k*n, double); dC = (double *) flint_calloc(m*n, sizeof(double)); mainarg.m = m = A->r; mainarg.k = k = A->c; mainarg.n = n = B->c; mainarg.Arows = A->rows; mainarg.Brows = B->rows; mainarg.dA = dA; mainarg.dB = dB; limit = m + k + n; limit = (limit < 300) ? 0 : (limit - 300)/128; if (limit < 1) { red_single: mainarg.Astartrow = 0; mainarg.Astoprow = m; mainarg.Bstartrow = 0; mainarg.Bstoprow = k; _red_worker(&mainarg); } else { num_workers = flint_request_threads(&handles, limit); if (num_workers < 1) { flint_give_back_threads(handles, num_workers); goto red_single; } args = FLINT_ARRAY_ALLOC(num_workers, _red_worker_arg); for (start = 0, i = 0; i < num_workers; start = stop, i++) { args[i] = mainarg; stop = _thread_pool_find_work_2(m, k, k, n, i + 1, num_workers + 1); _thread_pool_distribute_work_2(start, stop, &args[i].Astartrow, &args[i].Astoprow, m, &args[i].Bstartrow, &args[i].Bstoprow, k); } _thread_pool_distribute_work_2(start, m + k, &mainarg.Astartrow, &mainarg.Astoprow, m, &mainarg.Bstartrow, &mainarg.Bstoprow, k); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _red_worker, &args[i]); _red_worker(&mainarg); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); flint_free(args); } cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, 1.0, dA, k, dB, n, 0.0, dC, n); for (i = 0; i < m; i++) for (j = 0; j < n; j++) fmpz_set_si(&C->rows[i][j], (slong)(dC[n*i + j])); flint_free(dA); flint_free(dB); flint_free(dC); return 1; } /* Stuff that should be shared with nmod_mat_mul_blas */ #define MAX_BLAS_DP_INT (UWORD(1) << 53) /* mod/lift helpers */ static void _lift_vec(double * a, const uint32_t * b, slong len, uint32_t n) { slong i; for (i = 0; i < len; i++) a[i] = (int32_t)(b[i] - (n & (-(uint32_t)((int32_t)(n/2 - b[i]) < 0)))); } static uint32_t _reduce_uint32(mp_limb_t a, nmod_t mod) { mp_limb_t r; NMOD_RED(r, a, mod); return (uint32_t)r; } static void fmpz_multi_mod_uint32_stride( uint32_t * out, slong stride, const fmpz_t input, const fmpz_comb_t C, fmpz_comb_temp_t CT) { slong i, k, l; fmpz * A = CT->A; mod_lut_entry * lu; slong * offsets; slong klen = C->mod_klen; fmpz_t ttt; /* high level split */ if (klen == 1) { *ttt = A[0]; A[0] = *input; } else { _fmpz_multi_mod_precomp(A, C->mod_P, input, -1, CT->T); } offsets = C->mod_offsets; lu = C->mod_lu; for (k = 0, i = 0, l = 0; k < klen; k++) { slong j = offsets[k]; for ( ; i < j; i++) { /* mid level split: depends on FMPZ_MOD_UI_CUTOFF */ mp_limb_t t = fmpz_get_nmod(A + k, lu[i].mod); /* low level split: 1, 2, or 3 small primes */ if (lu[i].mod2.n != 0) { FLINT_ASSERT(l + 3 <= C->num_primes); out[l*stride] = _reduce_uint32(t, lu[i].mod0); l++; out[l*stride] = _reduce_uint32(t, lu[i].mod1); l++; out[l*stride] = _reduce_uint32(t, lu[i].mod2); l++; } else if (lu[i].mod1.n != 0) { FLINT_ASSERT(l + 2 <= C->num_primes); out[l*stride] = _reduce_uint32(t, lu[i].mod0); l++; out[l*stride] = _reduce_uint32(t, lu[i].mod1); l++; } else { FLINT_ASSERT(l + 1 <= C->num_primes); out[l*stride] = (uint32_t)(t); l++; } } } FLINT_ASSERT(l == C->num_primes); if (klen == 1) A[0] = *ttt; } /* workers */ typedef struct { mp_limb_t prime; slong l; slong num_primes; slong m; slong k; slong n; slong Astartrow; slong Astoprow; slong Bstartrow; slong Bstoprow; slong Cstartrow; slong Cstoprow; uint32_t * bigA; uint32_t * bigB; uint32_t * bigC; double * dA; double * dB; double * dC; fmpz ** Arows; fmpz ** Brows; fmpz ** Crows; const fmpz_comb_struct * comb; int sign; } _worker_arg; static void _mod_worker(void * arg_ptr) { _worker_arg * arg = (_worker_arg *) arg_ptr; slong i, j; slong num_primes = arg->num_primes; slong k = arg->k; slong n = arg->n; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong Bstartrow = arg->Bstartrow; slong Bstoprow = arg->Bstoprow; uint32_t * bigA = arg->bigA; uint32_t * bigB = arg->bigB; fmpz ** Arows = arg->Arows; fmpz ** Brows = arg->Brows; const fmpz_comb_struct * comb = arg->comb; fmpz_comb_temp_t comb_temp; fmpz_comb_temp_init(comb_temp, comb); for (i = Astartrow; i < Astoprow; i++) for (j = 0; j < k; j++) fmpz_multi_mod_uint32_stride(bigA + i*k*num_primes + j, k, &Arows[i][j], comb, comb_temp); for (i = Bstartrow; i < Bstoprow; i++) for (j = 0; j < n; j++) fmpz_multi_mod_uint32_stride(bigB + i*n*num_primes + j, n, &Brows[i][j], comb, comb_temp); fmpz_comb_temp_clear(comb_temp); } void _tod_worker(void * arg_ptr) { _worker_arg * arg = (_worker_arg *) arg_ptr; slong i; slong l = arg->l; slong num_primes = arg->num_primes; slong k = arg->k; slong n = arg->n; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong Bstartrow = arg->Bstartrow; slong Bstoprow = arg->Bstoprow; const uint32_t * bigA = arg->bigA; const uint32_t * bigB = arg->bigB; double * dA = arg->dA; double * dB = arg->dB; uint32_t prime = arg->prime; for (i = Astartrow; i < Astoprow; i++) _lift_vec(dA + i*k, bigA + l*k + i*k*num_primes, k, prime); for (i = Bstartrow; i < Bstoprow; i++) _lift_vec(dB + i*n, bigB + l*n + i*n*num_primes, n, prime); } void _fromd_worker(void * arg_ptr) { _worker_arg * arg = (_worker_arg *) arg_ptr; slong i, j; slong l = arg->l; slong num_primes = arg->num_primes; slong n = arg->n; slong Cstartrow = arg->Cstartrow; slong Cstoprow = arg->Cstoprow; uint32_t * bigC = arg->bigC; double * dC = arg->dC; ulong shift; nmod_t mod; nmod_init(&mod, arg->prime); shift = ((2*MAX_BLAS_DP_INT)/mod.n)*mod.n; for (i = Cstartrow; i < Cstoprow; i++) { for (j = 0; j < n; j++) { mp_limb_t r; slong a = (slong) dC[i*n + j]; mp_limb_t b = (a < 0) ? a + shift : a; NMOD_RED(r, b, mod); bigC[n*(num_primes*i + l) + j] = r; } } } void _crt_worker(void * arg_ptr) { _worker_arg * arg = (_worker_arg *) arg_ptr; slong i, j, k; slong num_primes = arg->num_primes; slong n = arg->n; slong Cstartrow = arg->Cstartrow; slong Cstoprow = arg->Cstoprow; uint32_t * bigC = arg->bigC; fmpz ** Crows = arg->Crows; const fmpz_comb_struct * comb = arg->comb; fmpz_comb_temp_t comb_temp; mp_limb_t * r; int sign = arg->sign; fmpz_comb_temp_init(comb_temp, comb); r = FLINT_ARRAY_ALLOC(num_primes, mp_limb_t); for (i = Cstartrow; i < Cstoprow; i++) { for (j = 0; j < n; j++) { for (k = 0; k < num_primes; k++) r[k] = bigC[(i*num_primes + k)*n + j]; fmpz_multi_CRT_ui(&Crows[i][j], r, comb, comb_temp, sign); } } flint_free(r); fmpz_comb_temp_clear(comb_temp); } static mp_limb_t * _calculate_primes( slong * num_primes_, flint_bitcnt_t bits, slong k) { slong num_primes, primes_alloc; mp_limb_t * primes; mp_limb_t p; fmpz_t prod; p = 2 + 2*n_sqrt((MAX_BLAS_DP_INT - 1)/(ulong)k); if (bits > 200) { /* if mod is the bottleneck, ensure p1*p2*p3 < 2^62 */ p = FLINT_MIN(p, UWORD(1664544)); } primes_alloc = 1 + bits/FLINT_BIT_COUNT(p); primes = FLINT_ARRAY_ALLOC(primes_alloc, mp_limb_t); num_primes = 0; fmpz_init_set_ui(prod, 1); do { do { if (p < 1000) { fmpz_clear(prod); flint_free(primes); *num_primes_ = 0; return NULL; } p--; } while (!n_is_prime(p)); if (num_primes + 1 > primes_alloc) { primes_alloc = FLINT_MAX(num_primes + 1, primes_alloc*5/4); primes = FLINT_ARRAY_REALLOC(primes, primes_alloc, mp_limb_t); } primes[num_primes] = p; num_primes++; fmpz_mul_ui(prod, prod, p); } while (fmpz_bits(prod) <= bits); fmpz_clear(prod); *num_primes_ = num_primes; return primes; } /* max|A| < 2^Abits max|B| < 2^Bbits max|C| < 2^Cbits sign = 1: either A or B could have negative entries. sign = 0: all entries are >= 0. */ int _fmpz_mat_mul_blas( fmpz_mat_t C, const fmpz_mat_t A, flint_bitcnt_t Abits, const fmpz_mat_t B, flint_bitcnt_t Bbits, int sign, flint_bitcnt_t Cbits) { slong i, l, start, stop; slong m = A->r; slong k = A->c; slong n = B->c; uint32_t * bigC, * bigA, * bigB; double * dC, * dA, * dB; mp_limb_t * primes; slong num_primes; fmpz_comb_t comb; thread_pool_handle * handles; slong num_workers; _worker_arg * args; FLINT_ASSERT(sign == 0 || sign == 1); FLINT_ASSERT(m == A->r && m == C->r); FLINT_ASSERT(k == A->c && k == B->r); FLINT_ASSERT(n == B->c && n == C->c); if (m < 1 || k < 1 || n < 1 || m > INT_MAX || k > INT_MAX || n > INT_MAX) return 0; if (Abits + Bbits + FLINT_BIT_COUNT(k) <= 53) return _fmpz_mat_mul_blas_direct(C, A, B); primes = _calculate_primes(&num_primes, Cbits + sign, k); if (primes == NULL) return 0; fmpz_comb_init(comb, primes, num_primes); /* To allow the 3D transpose to and from blas to be at least slightly cache friendly, matrices M mod p[l] are stored with the prime index in the middle: M[i,j] mod p[l] is at bigM[(i*num_primes + l)*M->c + j] */ bigA = FLINT_ARRAY_ALLOC(m*k*num_primes, uint32_t); bigB = FLINT_ARRAY_ALLOC(k*n*num_primes, uint32_t); bigC = FLINT_ARRAY_ALLOC(m*n*num_primes, uint32_t); dA = FLINT_ARRAY_ALLOC(m*k, double); dB = FLINT_ARRAY_ALLOC(k*n, double); dC = (double *) flint_calloc(m*n, sizeof(double)); num_workers = flint_request_threads(&handles, INT_MAX); args = FLINT_ARRAY_ALLOC(num_workers + 1, _worker_arg); for (start = 0, i = 0; i <= num_workers; start = stop, i++) { args[i].l = -1; args[i].prime = 0; args[i].num_primes = num_primes; args[i].m = m; args[i].k = k; args[i].n = n; args[i].bigA = bigA; args[i].bigB = bigB; args[i].bigC = bigC; args[i].Arows = A->rows; args[i].Brows = B->rows; args[i].Crows = C->rows; args[i].dA = dA; args[i].dB = dB; args[i].dC = dC; args[i].comb = comb; args[i].sign = sign; /* distribute rows of C evenly */ args[i].Cstartrow = ((i + 0)*m)/(num_workers + 1); args[i].Cstoprow = ((i + 1)*m)/(num_workers + 1); /* distribute rows of A and B evenly as weighted by their columns */ stop = _thread_pool_find_work_2(m, k, k, n, i + 1, num_workers + 1); _thread_pool_distribute_work_2(start, stop, &args[i].Astartrow, &args[i].Astoprow, m, &args[i].Bstartrow, &args[i].Bstoprow, k); } /* mod inputs */ for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _mod_worker, &args[i]); _mod_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); /* multiply and reduce answers mod the primes */ for (l = 0; l < num_primes; l++) { for (i = 0; i <= num_workers; i++) { args[i].l = l; args[i].prime = primes[l]; } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _tod_worker, &args[i]); _tod_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, 1.0, dA, k, dB, n, 0.0, dC, n); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _fromd_worker, &args[i]); _fromd_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); } /* crt output */ for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _crt_worker, &args[i]); _crt_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); /* cleanup */ fmpz_comb_clear(comb); flint_free(primes); flint_free(args); flint_free(bigA); flint_free(bigB); flint_free(bigC); flint_free(dA); flint_free(dB); flint_free(dC); return 1; } #else int _fmpz_mat_mul_blas( fmpz_mat_t C, const fmpz_mat_t A, flint_bitcnt_t Abits, const fmpz_mat_t B, flint_bitcnt_t Bbits, int sign, flint_bitcnt_t Cbits) { return 0; } #endif int fmpz_mat_mul_blas(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong Abits = fmpz_mat_max_bits(A); slong Bbits = fmpz_mat_max_bits(B); flint_bitcnt_t Cbits; int sign = 0; if (Abits < 0) { sign = 1; Abits = -Abits; } if (Bbits < 0) { sign = 1; Bbits = -Bbits; } Cbits = Abits + Bbits + FLINT_BIT_COUNT(A->c); return _fmpz_mat_mul_blas(C, A, Abits, B, Bbits, sign, Cbits); } flint-3.1.3/src/fmpz_mat/mul_classical.c000066400000000000000000000037651461254215100202310ustar00rootroot00000000000000/* Copyright (C) 2010, 2011, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_mul_classical(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong ar, br, bc, i, j; ar = fmpz_mat_nrows(A); br = fmpz_mat_nrows(B); bc = fmpz_mat_ncols(B); if (ar == 0 || br == 0 || bc == 0) { fmpz_mat_zero(C); return; } if (br == 1) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { fmpz_mul(fmpz_mat_entry(C, i, j), fmpz_mat_entry(A, i, 0), fmpz_mat_entry(B, 0, j)); } } } else if (br == 2) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { fmpz_fmma(fmpz_mat_entry(C, i, j), fmpz_mat_entry(A, i, 0), fmpz_mat_entry(B, 0, j), fmpz_mat_entry(A, i, 1), fmpz_mat_entry(B, 1, j)); } } } else { fmpz * tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(sizeof(fmpz) * br * bc); for (i = 0; i < br; i++) for (j = 0; j < bc; j++) tmp[j * br + i] = *fmpz_mat_entry(B, i, j); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { _fmpz_vec_dot_general(fmpz_mat_entry(C, i, j), NULL, 0, fmpz_mat_entry(A, i, 0), tmp + j * br, 0, br); } } TMP_END; } } flint-3.1.3/src/fmpz_mat/mul_double_word.c000066400000000000000000000337751461254215100206040ustar00rootroot00000000000000/* Copyright (C) 2010,2011,2018 Fredrik Johansson Copyright (C) 2016 Aaditya Thakkar Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_mat.h" /* There is a branchy version because the k loop takes time to warmup. Once k is big enough, the loop runs fast and there is no point in checking for small inputs. */ #define FMPZ_MAT_MUL_4_BRANCHLESS_CUTOFF 16 /* 2x2 -> 4 signed addmul */ static void _do_row_22_4_signed_branchy( fmpz * CR, const mp_limb_t * AR, const mp_limb_t * B, slong br, slong bc) { slong j, k, l; mp_limb_t s[4], t3, t2, t1, t0, w3, w2, w1, w0; mp_limb_t A0, A1, B0, B1; mp_limb_t u2, u1, u0; for (j = 0, l = 0; j < bc; j++) { t3 = t2 = t1 = t0 = 0; u2 = u1 = u0 = 0; for (k = 0; k < br; k++, l++) { A0 = AR[2*k + 0]; A1 = AR[2*k + 1]; B0 = B[2*l + 0]; B1 = B[2*l + 1]; if (FLINT_SIGN_EXT(A0) == A1 && FLINT_SIGN_EXT(B0) == B1) { smul_ppmm(w1, w0, B0, A0); add_sssaaaaaa(u2, u1, u0, u2, u1, u0, FLINT_SIGN_EXT(w1), w1, w0); } else { sub_ddmmss(t3, t2, t3, t2, 0, FLINT_SIGN_EXT(A1)&B0); sub_ddmmss(t3, t2, t3, t2, 0, FLINT_SIGN_EXT(B1)&A0); smul_ppmm(w3, w2, B1, A1); add_ssaaaa(t3, t2, t3, t2, w3, w2); umul_ppmm(w1, w0, B0, A0); add_sssaaaaaa(u2, u1, u0, u2, u1, u0, UWORD(0), w1, w0); umul_ppmm(w2, w1, A1, B0); add_sssaaaaaa(t3, t2, t1, t3, t2, t1, UWORD(0), w2, w1); umul_ppmm(w2, w1, B1, A0); add_sssaaaaaa(t3, t2, t1, t3, t2, t1, UWORD(0), w2, w1); } } add_ssssaaaaaaaa(s[3], s[2], s[1], s[0], t3, t2, t1, t0, FLINT_SIGN_EXT(u2), u2, u1, u0); fmpz_set_signed_ui_array(CR + j, s, 4); } } /* 2x2 -> 4 signed addmul */ static void _do_row_22_4_signed( fmpz * CR, const mp_limb_t * AR, const mp_limb_t * B, slong br, slong bc) { slong j, k, l; mp_limb_t s[4], t3, t2, t1, t0, w3, w2, w1, w0; mp_limb_t A0, A1, B0, B1; mp_limb_t v3, v2, u2, u1, u0; for (j = 0, l = 0; j < bc; j++) { t3 = t2 = t1 = t0 = 0; u2 = u1 = u0 = 0; v3 = v2 = 0; for (k = 0; k < br; k++, l++) { A0 = AR[2*k + 0]; A1 = AR[2*k + 1]; B0 = B[2*l + 0]; B1 = B[2*l + 1]; sub_ddmmss(t3, t2, t3, t2, 0, FLINT_SIGN_EXT(A1)&B0); sub_ddmmss(t3, t2, t3, t2, 0, FLINT_SIGN_EXT(B1)&A0); smul_ppmm(w3, w2, B1, A1); add_ssaaaa(t3, t2, t3, t2, w3, w2); umul_ppmm(w1, w0, B0, A0); add_sssaaaaaa(u2, u1, u0, u2, u1, u0, UWORD(0), w1, w0); umul_ppmm(w2, w1, A1, B0); add_sssaaaaaa(t3, t2, t1, t3, t2, t1, UWORD(0), w2, w1); umul_ppmm(w2, w1, B1, A0); add_sssaaaaaa(v3, v2, t1, v3, v2, t1, UWORD(0), w2, w1); } add_ssssaaaaaaaa(t3, t2, t1, t0, t3, t2, t1, t0, FLINT_SIGN_EXT(u2), u2, u1, u0); add_ssaaaa(t3, t2, t3, t2, v3, v2); s[3] = t3; s[2] = t2; s[1] = t1; s[0] = t0; fmpz_set_signed_ui_array(CR + j, s, 4); } } /* 2x2 -> 5 signed addmul */ static void _do_row_22_5_signed( fmpz * CR, const mp_limb_t * AR, const mp_limb_t * B, slong br, slong bc) { slong j, k, l; mp_limb_t s[5]; mp_limb_t A0, A1, B0, B1; mp_limb_t s4, s3, s2, s1, s0; mp_limb_t p3, p2, p1, p0; mp_limb_t u3, u2; mp_limb_t v2; for (j = 0, l = 0; j < bc; j++) { s4 = s3 = s2 = s1 = s0 = 0; u3 = u2 = 0; v2 = 0; for (k = 0; k < br; k++, l++) { A0 = AR[2*k + 0]; A1 = AR[2*k + 1]; B0 = B[2*l + 0]; B1 = B[2*l + 1]; sub_ddmmss(u3, u2, u3, u2, UWORD(0), FLINT_SIGN_EXT(A1)&B0); sub_ddmmss(u3, u2, u3, u2, UWORD(0), FLINT_SIGN_EXT(B1)&A0); smul_ppmm(p3, p2, B1, A1); add_sssaaaaaa(s4, s3, s2, s4, s3, s2, FLINT_SIGN_EXT(p3), p3, p2); umul_ppmm(p2, p1, A1, B0); add_sssaaaaaa(u3, u2, s1, u3, u2, s1, UWORD(0), p2, p1); umul_ppmm(p1, p0, B0, A0); add_sssaaaaaa(v2, s1, s0, v2, s1, s0, UWORD(0), p1, p0); umul_ppmm(p2, p1, B1, A0); add_sssaaaaaa(u3, u2, s1, u3, u2, s1, UWORD(0), p2, p1); } add_sssaaaaaa(s4, s3, s2, s4, s3, s2, FLINT_SIGN_EXT(u3), u3, u2); add_sssaaaaaa(s4, s3, s2, s4, s3, s2, UWORD(0), UWORD(0), v2); s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; s[4] = s4; fmpz_set_signed_ui_array(CR + j, s, 5); } } /* 2x2 -> 4 unsigned addmul */ static void _do_row_22_4_unsigned( fmpz * CR, const mp_limb_t * AR, const mp_limb_t * B, slong br, slong bc) { slong j, k, l; mp_limb_t s[4]; mp_limb_t A0, A1, B0, B1; mp_limb_t p3, p2, p1, p0; mp_limb_t s3, s2, s1, s0; mp_limb_t u3, u2, u1; mp_limb_t v3, v2; for (j = 0, l = 0; j < bc; j++) { s3 = s2 = s1 = s0 = 0; u3 = u2 = u1 = 0; v3 = v2 = 0; for (k = 0; k < br; k++, l++) { A0 = AR[2*k + 0]; A1 = AR[2*k + 1]; B0 = B[2*l + 0]; B1 = B[2*l + 1]; umul_ppmm(p2, p1, A1, B0); add_sssaaaaaa(u3, u2, u1, u3, u2, u1, UWORD(0), p2, p1); umul_ppmm(p3, p2, A1, B1); umul_ppmm(p1, p0, A0, B0); add_ssssaaaaaaaa(s3, s2, s1, s0, s3, s2, s1, s0, p3, p2, p1, p0); umul_ppmm(p2, p1, A0, B1); add_sssaaaaaa(v3, v2, u1, v3, v2, u1, UWORD(0), p2, p1); } add_ssaaaa(u3, u2, u3, u2, v3, v2); add_sssaaaaaa(s3, s2, s1, s3, s2, s1, u3, u2, u1); s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; fmpz_set_ui_array(CR + j, s, 4); } } /* 2x2 -> 5 unsigned addmul */ static void _do_row_22_5_unsigned( fmpz * CR, const mp_limb_t * AR, const mp_limb_t * B, slong br, slong bc) { slong j, k, l; mp_limb_t s[5]; mp_limb_t A0, A1, B0, B1; mp_limb_t p3, p2, p1, p0; mp_limb_t s4, s3, s2, s1, s0; mp_limb_t u2, u1; mp_limb_t v3, v2; for (j = 0, l = 0; j < bc; j++) { s4 = s3 = s2 = s1 = s0 = 0; u2 = u1 = 0; v3 = v2 = 0; for (k = 0; k < br; k++, l++) { A0 = AR[2*k + 0]; A1 = AR[2*k + 1]; B0 = B[2*l + 0]; B1 = B[2*l + 1]; umul_ppmm(p2, p1, A1, B0); add_sssaaaaaa(s3, s2, s1, s3, s2, s1, UWORD(0), p2, p1); umul_ppmm(p1, p0, B0, A0); add_sssaaaaaa(u2, u1, s0, u2, u1, s0, UWORD(0), p1, p0); umul_ppmm(p2, p1, B1, A0); add_sssaaaaaa(s3, s2, s1, s3, s2, s1, UWORD(0), p2, p1); umul_ppmm(p3, p2, B1, A1); add_sssaaaaaa(s4, v3, v2, s4, v3, v2, UWORD(0), p3, p2); } /* s3 is small, so this doesn't overflow */ add_sssaaaaaa(s3, s2, s1, s3, s2, s1, UWORD(0), u2, u1); add_sssaaaaaa(s4, s3, s2, s4, s3, s2, UWORD(0), v3, v2); s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; s[4] = s4; fmpz_set_ui_array(CR + j, s, 5); } } typedef struct { slong Astartrow; slong Astoprow; slong Bstartcol; slong Bstopcol; slong br; slong bc; fmpz ** Crows; fmpz ** Arows; fmpz ** Brows; mp_limb_t * BL; int sign; int words; } _worker_arg; static void _red_worker(void * varg) { _worker_arg * arg = (_worker_arg *) varg; slong Bstartcol = arg->Bstartcol; slong Bstopcol = arg->Bstopcol; slong br = arg->br; fmpz ** Brows = arg->Brows; mp_limb_t * BL = arg->BL; int sign = arg->sign; slong i, j; if (sign) { for (j = Bstartcol; j < Bstopcol; j++) for (i = 0; i < br; i++) fmpz_get_signed_uiui(BL + 2*(j*br + i) + 1, BL + 2*(j*br + i) + 0, &Brows[i][j]); } else { for (j = Bstartcol; j < Bstopcol; j++) for (i = 0; i < br; i++) fmpz_get_uiui(BL + 2*(j*br + i) + 1, BL + 2*(j*br + i) + 0, &Brows[i][j]); } } static void _mul_worker(void * varg) { _worker_arg * arg = (_worker_arg *) varg; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong ac = arg->br; slong br = arg->br; slong bc = arg->bc; fmpz ** Crows = arg->Crows; fmpz ** Arows = arg->Arows; mp_limb_t * BL = arg->BL; int sign = arg->sign; int words = arg->words; mp_limb_t * AL; slong i, j; TMP_INIT; FLINT_ASSERT(sign == 0 || sign == 1); FLINT_ASSERT(words == 4 || words == 5); TMP_START; AL = TMP_ARRAY_ALLOC(2*ac, mp_limb_t); if (sign) { for (i = Astartrow; i < Astoprow; i++) { for (j = 0; j < ac; j++) fmpz_get_signed_uiui(AL + 2*j + 1, AL + 2*j, &Arows[i][j]); if (words == 4 && br < FMPZ_MAT_MUL_4_BRANCHLESS_CUTOFF) _do_row_22_4_signed_branchy(Crows[i], AL, BL, br, bc); else if (words == 4) _do_row_22_4_signed(Crows[i], AL, BL, br, bc); else _do_row_22_5_signed(Crows[i], AL, BL, br, bc); } } else { for (i = Astartrow; i < Astoprow; i++) { for (j = 0; j < ac; j++) fmpz_get_uiui(AL + 2*j + 1, AL + 2*j, &Arows[i][j]); if (words == 4) _do_row_22_4_unsigned(Crows[i], AL, BL, br, bc); else _do_row_22_5_unsigned(Crows[i], AL, BL, br, bc); } } TMP_END; } /* sign = 1: max|A|, max|B| < 2^(2*FLINT_BITS - 1) max|C| < 2^bits sign = 0: all entries are >= 0 and max|A|, max|B| < 2^(2*FLINT_BITS) max|C| < 2^bits bits + sign <= 5*FLINT_BITS */ void _fmpz_mat_mul_double_word_internal( fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, int sign, flint_bitcnt_t bits) { slong i; slong ar = fmpz_mat_nrows(A); slong br = fmpz_mat_nrows(B); slong bc = fmpz_mat_ncols(B); _worker_arg mainarg; thread_pool_handle * handles; slong num_workers; _worker_arg * args; slong limit; TMP_INIT; FLINT_ASSERT(ar > 0); FLINT_ASSERT(br > 0); FLINT_ASSERT(bc > 0); TMP_START; /* limit on number of threads */ limit = FLINT_MAX(br, bc); limit = FLINT_MIN(limit, ar); limit = limit < 16 ? 0 : (limit - 16)/16; mainarg.Astartrow = 0; mainarg.Astoprow = ar; mainarg.Bstartcol = 0; mainarg.Bstopcol = bc; mainarg.br = br; mainarg.bc = bc; mainarg.Crows = C->rows; mainarg.Arows = A->rows; mainarg.Brows = B->rows; mainarg.BL = TMP_ARRAY_ALLOC(br*bc*2, mp_limb_t); mainarg.sign = sign; if (bits + sign <= 4*FLINT_BITS) mainarg.words = 4; else mainarg.words = 5; if (limit < 2) { use_one_thread: _red_worker(&mainarg); _mul_worker(&mainarg); TMP_END; return; } num_workers = flint_request_threads(&handles, limit); if (num_workers < 1) { flint_give_back_threads(handles, num_workers); goto use_one_thread; } args = FLINT_ARRAY_ALLOC(num_workers, _worker_arg); for (i = 0; i < num_workers; i++) { args[i].Astartrow = (i + 0)*ar/(num_workers + 1); args[i].Astoprow = (i + 1)*ar/(num_workers + 1); args[i].Bstartcol = (i + 0)*bc/(num_workers + 1); args[i].Bstopcol = (i + 1)*bc/(num_workers + 1); args[i].br = mainarg.br; args[i].bc = mainarg.bc; args[i].Crows = mainarg.Crows; args[i].Arows = mainarg.Arows; args[i].Brows = mainarg.Brows; args[i].BL = mainarg.BL; args[i].sign = mainarg.sign; args[i].words = mainarg.words; } i = num_workers; mainarg.Astartrow = (i + 0)*ar/(num_workers + 1); mainarg.Astoprow = (i + 1)*ar/(num_workers + 1); mainarg.Bstartcol = (i + 0)*bc/(num_workers + 1); mainarg.Bstopcol = (i + 1)*bc/(num_workers + 1); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _red_worker, &args[i]); _red_worker(&mainarg); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _mul_worker, &args[i]); _mul_worker(&mainarg); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); flint_free(args); TMP_END; return; } void _fmpz_mat_mul_double_word( fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { int sign = 0; slong Abits, Bbits; flint_bitcnt_t Cbits; if (fmpz_mat_is_empty(A) || fmpz_mat_is_empty(B)) { fmpz_mat_zero(C); return; } Abits = fmpz_mat_max_bits(A); Bbits = fmpz_mat_max_bits(B); if (Abits < 0) { sign = 1; Abits = -Abits; } if (Bbits < 0) { sign = 1; Bbits = -Bbits; } FLINT_ASSERT(Abits + sign <= 2*FLINT_BITS); FLINT_ASSERT(Bbits + sign <= 2*FLINT_BITS); Cbits = FLINT_BIT_COUNT(A->c) + Abits + Bbits; _fmpz_mat_mul_double_word_internal(C, A, B, sign, Cbits); } flint-3.1.3/src/fmpz_mat/mul_fft.c000066400000000000000000000360261461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fft.h" /* fft coeffs are mod m = 2^(FLINT_BITS*limbs) + 1. Viewing these coefficients as in the signed range (-m/2, m/2): set the mpn z to the twos complement evaluation at 2^bits. The lower zn limbs are written to z and the lowest bit of the nominal zn^th limb in the twos complement representation is returned. The behaviour of this function does NOT depend on the initial value of z. */ static mp_limb_t fft_combine_bits_signed( mp_limb_t * z, mp_limb_t ** a, mp_size_t alen, flint_bitcnt_t bits, mp_size_t limbs, mp_size_t zn) { mp_size_t i, zout; mp_limb_t * t; mp_limb_t f; TMP_INIT; FLINT_ASSERT(bits > 1); TMP_START; t = TMP_ARRAY_ALLOC((limbs + 1), mp_limb_t); f = 0; zout = 0; for (i = 0; i < alen; i++) { /* add the i^th coeffs a[i] */ mp_limb_t q = (bits*i)/FLINT_BITS; mp_limb_t r = (bits*i)%FLINT_BITS; mp_limb_t s; mp_limb_t halflimb = UWORD(1) << (FLINT_BITS - 1); if (a[i][limbs] | (a[i][limbs - 1] > halflimb)) { mpn_sub_1(t, a[i], limbs, UWORD(1)); s = 1; } else { mpn_copyi(t, a[i], limbs); s = 0; } t[limbs] = -s; /* t[0] ... t[limbs] is now the twos complement signed version of a[i] and the shift occurs without overflow */ if (r != 0) mpn_lshift(t, t, limbs + 1, r); if (q < zn) { size_t new_zout = FLINT_MIN(zn, q + limbs + 1); FLINT_ASSERT(new_zout >= zout); while (zout < new_zout) z[zout++] = -f; FLINT_ASSERT(new_zout > q); f ^= s; f ^= mpn_add_n(z + q, z + q, t, new_zout - q); } else { if (q == zn) f ^= t[0]&1; break; } } while (zout < zn) z[zout++] = -f; TMP_END; FLINT_ASSERT(f == 0 || f == 1); return f; } /* Split into coefficients from |x| evaluated at 2^bits, and do a negmod on each coefficient for x < 0. */ static mp_size_t fft_split_bits_fmpz( mp_limb_t ** poly, const fmpz_t x, flint_bitcnt_t bits, mp_size_t limbs) { mp_size_t len; int x_is_neg = 0; if (COEFF_IS_MPZ(*x)) { mp_size_t s = COEFF_TO_PTR(*x)->_mp_size; x_is_neg = s < 0; len = fft_split_bits(poly, COEFF_TO_PTR(*x)->_mp_d, x_is_neg ? -s : s, bits, limbs); } else if (!fmpz_is_zero(x)) { mp_limb_t ux; x_is_neg = *x < 0; ux = x_is_neg ? -*x : *x; len = fft_split_bits(poly, &ux, 1, bits, limbs); } else { len = 0; } if (x_is_neg) { mp_size_t i; for (i = 0; i < len; i++) mpn_negmod_2expp1(poly[i], poly[i], limbs); } return len; } static void fft_combine_bits_fmpz( fmpz_t x, mp_limb_t ** poly, slong length, flint_bitcnt_t bits, mp_size_t limbs, mp_size_t total_limbs, int sign) { __mpz_struct * mx = _fmpz_promote(x); mp_limb_t * d = FLINT_MPZ_REALLOC(mx, total_limbs); if (sign) { if (fft_combine_bits_signed(d, poly, length, bits, limbs, total_limbs)) { mpn_neg(d, d, total_limbs); MPN_NORM(d, total_limbs); /* total_limbs should have started high enough to prevent d = 0 here */ FLINT_ASSERT(total_limbs > 0); mx->_mp_size = -total_limbs; } else { MPN_NORM(d, total_limbs); mx->_mp_size = total_limbs; } } else { flint_mpn_zero(d, total_limbs); fft_combine_bits(d, poly, length, bits, limbs, total_limbs); MPN_NORM(d, total_limbs); mx->_mp_size = total_limbs; } _fmpz_demote_val(x); } static void _either_fft_or_mfa( ulong ** coeffs, slong n, flint_bitcnt_t w, ulong ** t1, ulong ** t2, ulong ** t3, slong n1, flint_bitcnt_t depth, slong trunc, slong limbs, int use_mfa) { ulong trunc2, rs, s, u; slong l; if (use_mfa) { fft_mfa_truncate_sqrt2(coeffs, n, w, t1, t2, t3, n1, trunc); for (l = 0; l < 2*n; l++) mpn_normmod_2expp1(coeffs[l], limbs); /* the second half is out of order */ trunc2 = (trunc - 2*n)/n1; for (s = 0; s < trunc2; s++) { rs = n_revbin(s, depth - depth/2 + 1); for (u = 0; u < n1; u++) { l = 2*n + rs*n1 + u; mpn_normmod_2expp1(coeffs[l], limbs); } } } else { fft_truncate_sqrt2(coeffs, n, w, t1, t2, t3, trunc); for (l = 0; l < trunc; l++) mpn_normmod_2expp1(coeffs[l], limbs); } } static void _dot( ulong* c, ulong** A, slong Astride, ulong** B, slong Bstride, slong len, slong limbs, ulong* t, /* temp of length limbs + 1 */ ulong* t2) /* temp of length limbs + 1 */ { slong i; flint_bitcnt_t nw = limbs*FLINT_BITS; /* n*w */ FLINT_ASSERT(len > 0); i = 0; do { const ulong* a = A[i*Astride]; const ulong* b = B[i*Bstride]; if (i == 0) { c[limbs] = flint_mpn_mulmod_2expp1_basecase(c, a, b, 2*a[limbs] + b[limbs], nw, t2); } else { t[limbs] = flint_mpn_mulmod_2expp1_basecase(t, a, b, 2*a[limbs] + b[limbs], nw, t2); c[limbs] += t[limbs]; c[limbs] += mpn_add_n(c, c, t, limbs); mpn_normmod_2expp1(c, limbs); } } while (++i < len); } void _fmpz_mat_mul_truncate_sqrt2( fmpz_mat_t C, const fmpz_mat_t A, slong Abits, const fmpz_mat_t B, slong Bbits, flint_bitcnt_t depth, flint_bitcnt_t w, slong j1, slong j2, const int use_mfa, const int sign) { slong M = fmpz_mat_nrows(A); slong K = fmpz_mat_ncols(A); slong N = fmpz_mat_ncols(B); slong clgK = FLINT_CLOG2(K) + sign; slong n = WORD(1) << depth; ulong trunc, sqrt; ulong bits1 = (n*w - (depth + 1 + clgK))/2; /* This bound on Climbs is also ok with the original clgK = FLINT_CLOG2(K) */ slong Climbs = (Abits + Bbits + clgK + FLINT_BITS - 1)/FLINT_BITS; slong limbs = (n*w)/FLINT_BITS; slong size = limbs + 1; slong i, j, l, h; ulong * temp, *t, * t1, * t2, * t3, * Adata, * Bdata, * Cdata; ulong ** coeffs, ** Acoeffs, ** Bcoeffs, ** Ccoeffs; FLINT_ASSERT(limbs > 0); FLINT_ASSERT(limbs*FLINT_BITS == n*w); /* should have K*min(j1,j2)*2^bits1 <= 2^(n*w) */ FLINT_ASSERT(j1 <= 2*n || j2 <= 2*n); /* 1 array of length 2*size for mulmod_2expp1. 1 array of length size for addmulmod 3 arrays of length size for fft/ifft. M*K*4*n arrays of length size for A's fft rep K*N*4*n arrays of length size for B's fft rep 4*n arrays of length size for C's fft rep */ temp = FLINT_ARRAY_ALLOC((6 + 4*n*(M*K + K*N + 1))*size, mp_limb_t); t = temp + 2*size; t1 = t + size; t2 = t1 + size; t3 = t2 + size; Adata = t3 + size; Bdata = Adata + 4*n*M*K*size; Cdata = Bdata + 4*n*K*N*size; /* M*K arrays of pointers of length 4*n for A's coeffs K*N arrays of pointers of length 4*n for B's coeffs 1 array of pointers of length 4*n for C's coeffs */ coeffs = FLINT_ARRAY_ALLOC(4*n*(M*K + K*N + 1), mp_limb_t*); Acoeffs = coeffs; Bcoeffs = Acoeffs + 4*n*M*K; Ccoeffs = Bcoeffs + 4*n*K*N; /* fill in coefficient pointers */ for (i = 0; i < M; i++) for (j = 0; j < K; j++) for (l = 0; l < 4*n; l++) Acoeffs[(i*K + j)*4*n + l] = Adata + ((i*K + j)*4*n + l)*size; for (i = 0; i < K; i++) for (j = 0; j < N; j++) for (l = 0; l < 4*n; l++) Bcoeffs[(i*N + j)*4*n + l] = Bdata + ((i*N + j)*4*n + l)*size; for (l = 0; l < 4*n; l++) Ccoeffs[l] = Cdata + l*size; /* chop inputs into bits */ for (i = 0; i < M; i++) for (j = 0; j < K; j++) { h = fft_split_bits_fmpz(Acoeffs + (i*K + j)*4*n, fmpz_mat_entry(A, i, j), bits1, limbs); for (l = h; l < 4*n; l++) flint_mpn_zero(Acoeffs[(i*K + j)*4*n + l], size); } for (i = 0; i < K; i++) for (j = 0; j < N; j++) { h = fft_split_bits_fmpz(Bcoeffs + (i*N + j)*4*n, fmpz_mat_entry(B, i, j), bits1, limbs); for (l = h; l < 4*n; l++) flint_mpn_zero(Bcoeffs[(i*N + j)*4*n + l], size); } FLINT_ASSERT(j1 > 0); FLINT_ASSERT(j2 > 0); FLINT_ASSERT(j1 + j2 - 1 <= 4*n); trunc = j1 + j2 - 1; trunc = FLINT_MAX(trunc, 2*n + 1); if (use_mfa) { sqrt = UWORD(1) << (depth/2); trunc = (trunc + 2*sqrt - 1) & (-2*sqrt); } else { sqrt = 1; trunc = (trunc + 1) & -UWORD(2); } FLINT_ASSERT(trunc > 2*n); FLINT_ASSERT(trunc % (2*sqrt) == 0); for (i = 0; i < M; i++) for (j = 0; j < K; j++) { _either_fft_or_mfa(Acoeffs + (i*K + j)*4*n, n, w, &t1, &t2, &t3, sqrt, depth, trunc, limbs, use_mfa); } for (i = 0; i < K; i++) for (j = 0; j < N; j++) { _either_fft_or_mfa(Bcoeffs + (i*N + j)*4*n, n, w, &t1, &t2, &t3, sqrt, depth, trunc, limbs, use_mfa); } /* pointwise dot products for C[i,j] */ for (i = 0; i < M; i++) for (j = 0; j < N; j++) { if (use_mfa) { ulong trunc2, rs, s, u; for (l = 0; l < 2*n; l++) { _dot(Ccoeffs[l], Acoeffs + (i*K + 0)*4*n + l, 4*n, Bcoeffs + (0*N + j)*4*n + l, N*4*n, K, limbs, t, temp); } /* second half is out of order */ trunc2 = (trunc - 2*n)/sqrt; for (s = 0; s < trunc2; s++) { rs = n_revbin(s, depth - depth/2 + 1); for (u = 0; u < sqrt; u++) { l = 2*n + rs*sqrt + u; _dot(Ccoeffs[l], Acoeffs + (i*K + 0)*4*n + l, 4*n, Bcoeffs + (0*N + j)*4*n + l, N*4*n, K, limbs, t, temp); } } ifft_mfa_truncate_sqrt2(Ccoeffs, n, w, &t1, &t2, &t3, sqrt, trunc); } else { for (l = 0; l < trunc; l++) { _dot(Ccoeffs[l], Acoeffs + (i*K + 0)*4*n + l, 4*n, Bcoeffs + (0*N + j)*4*n + l, N*4*n, K, limbs, t, temp); } ifft_truncate_sqrt2(Ccoeffs, n, w, &t1, &t2, &t3, trunc); } /* pointwise scalar division by 4*n */ for (l = 0; l < trunc; l++) { mpn_div_2expmod_2expp1(Ccoeffs[l], Ccoeffs[l], limbs, depth + 2); mpn_normmod_2expp1(Ccoeffs[l], limbs); } fft_combine_bits_fmpz(fmpz_mat_entry(C, i, j), Ccoeffs, j1 + j2 - 1, bits1, limbs, Climbs, sign); } flint_free(temp); flint_free(coeffs); } /* For nonnegative input: just like mpn_mul_main but bits = (n*w - (depth + 1))/2; is replaced by bits = (n*w - (depth + 1 + FLINT_CLOG2(k)))/2; the inputs are viewed a polynomials evaluated at 2^bits, with all coeffs in [0, 2^bits) For general input: the inputs are viewed a polynomials evaluated at 2^bits, either with all coeffs in [0, 2^bits), or all coeffs in (-2^bits, 0] (Balancing as (-2^(bits-1), 2^(bits-1)] hardly seems worth the effort.) In either case, the product of the matrices of these polynomials has coefficients bounded in absolute value by k*2^(depth+1)*2^(2*bits) We want this to be less than 2^(n*w) in the unsigned case and less than 2^(n*w)/2 in the signed case. */ void _fmpz_mat_mul_fft( fmpz_mat_t C, const fmpz_mat_t A, slong abits, const fmpz_mat_t B, slong bbits, int sign) { slong K = fmpz_mat_ncols(A); slong clgK = FLINT_CLOG2(K) + sign; slong /*off, */depth = 6; slong w = 1; slong n = WORD(1) << depth; ulong bits = (n*w - (depth + 1 + clgK))/2; ulong bits1 = FLINT_MAX(abits, WORD(2000)); ulong bits2 = FLINT_MAX(bbits, WORD(2000)); /* when viewed as eval of poly at x=2^bits, the max length of the entries */ slong j1 = (bits1 + bits - 1)/bits; /* ditto for B */ slong j2 = (bits2 + bits - 1)/bits; int use_mfa; FLINT_ASSERT(sign == 0 || sign == 1); FLINT_ASSERT(abits > 0); FLINT_ASSERT(bbits > 0); FLINT_ASSERT(j1 + j2 - 1 > 2*n); /* find initial n, w */ while (j1 + j2 - 1 > 4*n) { if (w == 1) { w = 2; } else { depth++; w = 1; n *= 2; } bits = (n*w - (depth + 1 + clgK))/2; j1 = (bits1 + bits - 1)/bits; j2 = (bits2 + bits - 1)/bits; } if (depth < 11) { slong wadj = 1; /* adjust n and w */ if (depth < 6) wadj = WORD(1) << (6 - depth); if (w > wadj) { /* see if a smaller w will work */ do { w -= wadj; bits = (n*w - (depth + 1 + clgK))/2; j1 = (bits1 + bits - 1)/bits; j2 = (bits2 + bits - 1)/bits; } while (j1 + j2 - 1 <= 4*n && w > wadj); w += wadj; } use_mfa = 0; } else { use_mfa = 1; } bits = (n*w - (depth + 1 + clgK))/2; j1 = (bits1 + bits - 1)/bits; j2 = (bits2 + bits - 1)/bits; _fmpz_mat_mul_truncate_sqrt2(C, A, abits, B, bbits, depth, w, j1, j2, use_mfa, sign); } void fmpz_mat_mul_fft(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong ar, br, bc; slong abits, bbits; int sign; ar = fmpz_mat_nrows(A); br = fmpz_mat_nrows(B); bc = fmpz_mat_ncols(B); if (ar == 0 || br == 0 || bc == 0) { fmpz_mat_zero(C); return; } abits = fmpz_mat_max_bits(A); bbits = fmpz_mat_max_bits(B); sign = 0; if (abits < 0) { sign = 1; abits = -abits; } if (bbits < 0) { sign = 1; bbits = -bbits; } if (abits == 0 || bbits == 0) { fmpz_mat_zero(C); return; } _fmpz_mat_mul_fft(C, A, abits, B, bbits, sign); } flint-3.1.3/src/fmpz_mat/mul_fmpz_vec.c000066400000000000000000000020641461254215100200730ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_mul_fmpz_vec( fmpz * c, const fmpz_mat_t A, const fmpz * b, slong blen) { slong i; slong len = FLINT_MIN(A->c, blen); for (i = A->r - 1; i >= 0; i--) _fmpz_vec_dot(c + i, A->rows[i], b, len); } void fmpz_mat_mul_fmpz_vec_ptr( fmpz * const * c, const fmpz_mat_t A, const fmpz * const * b, slong blen) { slong i, j; slong len = FLINT_MIN(A->c, blen); for (i = A->r - 1; i >= 0; i--) { fmpz * ci = c[i]; const fmpz * Ai = A->rows[i]; fmpz_zero(ci); for (j = 0; j < len; j++) fmpz_addmul(ci, Ai + j, b[j]); } } flint-3.1.3/src/fmpz_mat/mul_multi_mod.c000066400000000000000000000353221461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2010, 2018 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" typedef struct { slong m; slong k; slong n; slong Astartrow; slong Astoprow; slong Bstartrow; slong Bstoprow; slong Cstartrow; slong Cstoprow; fmpz ** Arows; fmpz ** Brows; fmpz ** Crows; nmod_mat_t * mod_A; nmod_mat_t * mod_B; nmod_mat_t * mod_C; const fmpz_comb_struct * comb; slong num_primes; mp_ptr primes; int sign; } _worker_arg; static void _mod_worker(void * varg) { _worker_arg * arg = (_worker_arg *) varg; slong i, j, l; slong k = arg->k; slong n = arg->n; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong Bstartrow = arg->Bstartrow; slong Bstoprow = arg->Bstoprow; fmpz ** Arows = arg->Arows; fmpz ** Brows = arg->Brows; nmod_mat_t * mod_A = arg->mod_A; nmod_mat_t * mod_B = arg->mod_B; slong num_primes = arg->num_primes; const fmpz_comb_struct * comb = arg->comb; if (comb != NULL) { mp_limb_t * residues; fmpz_comb_temp_t comb_temp; residues = FLINT_ARRAY_ALLOC(num_primes, mp_limb_t); fmpz_comb_temp_init(comb_temp, comb); for (i = Astartrow; i < Astoprow; i++) { for (j = 0; j < k; j++) { fmpz_multi_mod_ui(residues, &Arows[i][j], comb, comb_temp); for (l = 0; l < num_primes; l++) mod_A[l]->rows[i][j] = residues[l]; } } if (mod_B != NULL) { for (i = Bstartrow; i < Bstoprow; i++) { for (j = 0; j < n; j++) { fmpz_multi_mod_ui(residues, &Brows[i][j], comb, comb_temp); for (l = 0; l < num_primes; l++) mod_B[l]->rows[i][j] = residues[l]; } } } flint_free(residues); fmpz_comb_temp_clear(comb_temp); } else { for (i = Astartrow; i < Astoprow; i++) { for (j = 0; j < k; j++) { for (l = 0; l < num_primes; l++) nmod_mat_entry(mod_A[l], i, j) = fmpz_get_nmod(&Arows[i][j], mod_A[l]->mod); } } if (mod_B != NULL) { for (i = Bstartrow; i < Bstoprow; i++) { for (j = 0; j < n; j++) { for (l = 0; l < num_primes; l++) nmod_mat_entry(mod_B[l], i, j) = fmpz_get_nmod(&Brows[i][j], mod_A[l]->mod); } } } } } static void _crt_worker(void * varg) { _worker_arg * arg = (_worker_arg *) varg; slong i, j, l; slong n = arg->n; slong Cstartrow = arg->Cstartrow; slong Cstoprow = arg->Cstoprow; fmpz ** Crows = arg->Crows; nmod_mat_t * mod_C = arg->mod_C; mp_limb_t * primes = arg->primes; slong num_primes = arg->num_primes; const fmpz_comb_struct * comb = arg->comb; int sign = arg->sign; FLINT_ASSERT(sign == 0 || sign == 1); if (comb != NULL) { mp_limb_t * residues; fmpz_comb_temp_t comb_temp; residues = FLINT_ARRAY_ALLOC(num_primes, mp_limb_t); fmpz_comb_temp_init(comb_temp, comb); for (i = Cstartrow; i < Cstoprow; i++) for (j = 0; j < n; j++) { for (l = 0; l < num_primes; l++) residues[l] = mod_C[l]->rows[i][j]; fmpz_multi_CRT_ui(&Crows[i][j], residues, comb, comb_temp, sign); } flint_free(residues); fmpz_comb_temp_clear(comb_temp); } else if (num_primes == 1) { mp_limb_t r, t, p = primes[0]; if (sign) { for (i = Cstartrow; i < Cstoprow; i++) for (j = 0; j < n; j++) { r = nmod_mat_entry(mod_C[0], i, j); t = p - r; if (t < r) fmpz_neg_ui(&Crows[i][j], t); else fmpz_set_ui(&Crows[i][j], r); } } else { for (i = Cstartrow; i < Cstoprow; i++) for (j = 0; j < n; j++) { r = nmod_mat_entry(mod_C[0], i, j); fmpz_set_ui(&Crows[i][j], r); } } } else if (num_primes == 2) { mp_limb_t r0, r1, i0, i1, m0, m1, M[2], t[2], u[2]; m0 = primes[0]; m1 = primes[1]; i0 = n_invmod(m1 % m0, m0); i1 = n_invmod(m0 % m1, m1); umul_ppmm(M[1], M[0], m0, m1); for (i = Cstartrow; i < Cstoprow; i++) for (j = 0; j < n; j++) { r0 = nmod_mul(i0, nmod_mat_entry(mod_C[0], i, j), mod_C[0]->mod); r1 = nmod_mul(i1, nmod_mat_entry(mod_C[1], i, j), mod_C[1]->mod); /* 0 <= r0 <= m0 - 1 0 <= r1 <= m1 - 1 if m0*m1 < 2^(2*FLINT_BITS-1), then the sum t = r0*m1 + r1*m0 <= 2*m0*m1 - m0 - m1 does not overflow */ FLINT_ASSERT(FLINT_BIT_COUNT(M[1]) < FLINT_BITS); umul_ppmm(t[1], t[0], r0, m1); umul_ppmm(u[1], u[0], r1, m0); add_ssaaaa(t[1], t[0], t[1], t[0], u[1], u[0]); /* t = t mod M */ if (t[1] > M[1] || (t[1] == M[1] && t[0] > M[0])) sub_ddmmss(t[1], t[0], t[1], t[0], M[1], M[0]); FLINT_ASSERT(t[1] < M[1] || (t[1] == M[1] && t[0] < M[0])); if (sign) { sub_ddmmss(u[1], u[0], M[1], M[0], t[1], t[0]); if (u[1] < t[1] || (u[1] == t[1] && u[0] < t[0])) fmpz_neg_uiui(&Crows[i][j], u[1], u[0]); else fmpz_set_uiui(&Crows[i][j], t[1], t[0]); } else { fmpz_set_uiui(&Crows[i][j], t[1], t[0]); } } } else { mp_ptr M, Ns, T, U; mp_size_t Msize, Nsize; mp_limb_t cy, ri; M = FLINT_ARRAY_ALLOC(num_primes + 1, mp_limb_t); M[0] = primes[0]; Msize = 1; for (i = 1; i < num_primes; i++) { FLINT_ASSERT(Msize > 0); M[Msize] = cy = mpn_mul_1(M, M, Msize, primes[i]); Msize += (cy != 0); } /* We add terms with Msize + 1 limbs, with one extra limb for the carry accumulation. todo: reduce Nsize by 1 when the carries do not require an extra limb. */ Nsize = Msize + 2; Ns = FLINT_ARRAY_ALLOC(Nsize*num_primes, mp_limb_t); T = FLINT_ARRAY_ALLOC(Nsize, mp_limb_t); U = FLINT_ARRAY_ALLOC(Nsize, mp_limb_t); for (i = 0; i < num_primes; i++) { Ns[i*Nsize + (Nsize - 1)] = 0; Ns[i*Nsize + (Nsize - 2)] = 0; mpn_divrem_1(Ns + i * Nsize, 0, M, Msize, primes[i]); ri = mpn_mod_1(Ns + i * Nsize, Msize, primes[i]); ri = n_invmod(ri, primes[i]); FLINT_ASSERT(Msize > 0); Ns[i*Nsize + Msize] = mpn_mul_1(Ns + i*Nsize, Ns + i*Nsize, Msize, ri); } for (i = Cstartrow; i < Cstoprow; i++) for (j = 0; j < n; j++) { ri = nmod_mat_entry(mod_C[0], i, j); FLINT_ASSERT(Nsize > 1); T[Nsize - 1] = mpn_mul_1(T, Ns, Nsize - 1, ri); for (l = 1; l < num_primes; l++) { ri = nmod_mat_entry(mod_C[l], i, j); T[Nsize - 1] += mpn_addmul_1(T, Ns + l*Nsize, Nsize - 1, ri); } mpn_tdiv_qr(U, T, 0, T, Nsize, M, Msize); if (sign && (mpn_sub_n(U, M, T, Msize), mpn_cmp(U, T, Msize) < 0)) { fmpz_set_ui_array(&Crows[i][j], U, Msize); fmpz_neg(&Crows[i][j], &Crows[i][j]); } else { fmpz_set_ui_array(&Crows[i][j], T, Msize); } } flint_free(M); flint_free(Ns); flint_free(T); flint_free(U); } } void _fmpz_mat_mul_multi_mod( fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, int sign, flint_bitcnt_t bits) { slong i, start, stop; slong m, k, n; flint_bitcnt_t primes_bits; _worker_arg mainarg; _worker_arg * args; fmpz_comb_t comb; slong num_workers; thread_pool_handle * handles; slong limit; ulong first_prime; /* not prime */ int squaring = (A == B); mainarg.m = m = A->r; mainarg.k = k = A->c; mainarg.n = n = B->c; mainarg.Arows = A->rows; mainarg.Brows = B->rows; mainarg.Crows = C->rows; if (m < 1 || n < 1 || k < 1) { fmpz_mat_zero(C); return; } FLINT_ASSERT(sign == 0 || sign == 1); bits += sign; /* TUNING */ primes_bits = NMOD_MAT_OPTIMAL_MODULUS_BITS; if (bits < primes_bits || bits <= FLINT_BITS - 1) { mainarg.num_primes = 1; first_prime = UWORD(1) << bits; } else { /* Round up in the division */ mainarg.num_primes = 1 + (bits - (FLINT_BITS - 1) + primes_bits - 1)/primes_bits; first_prime = UWORD(1) << (FLINT_BITS - 1); } /* Initialize */ mainarg.sign = sign; mainarg.primes = FLINT_ARRAY_ALLOC(mainarg.num_primes, mp_limb_t); mainarg.primes[0] = first_prime; if (mainarg.num_primes > 1) { mainarg.primes[1] = n_nextprime(UWORD(1) << primes_bits, 0); for (i = 2; i < mainarg.num_primes; i++) mainarg.primes[i] = n_nextprime(mainarg.primes[i-1], 0); } mainarg.mod_A = FLINT_ARRAY_ALLOC(mainarg.num_primes, nmod_mat_t); if (squaring) mainarg.mod_B = NULL; else mainarg.mod_B = FLINT_ARRAY_ALLOC(mainarg.num_primes, nmod_mat_t); mainarg.mod_C = FLINT_ARRAY_ALLOC(mainarg.num_primes, nmod_mat_t); for (i = 0; i < mainarg.num_primes; i++) { nmod_mat_init(mainarg.mod_A[i], A->r, A->c, mainarg.primes[i]); if (!squaring) nmod_mat_init(mainarg.mod_B[i], B->r, B->c, mainarg.primes[i]); nmod_mat_init(mainarg.mod_C[i], C->r, C->c, mainarg.primes[i]); } /* TUNING */ if (mainarg.num_primes > 200) { /* use comb */ fmpz_comb_init(comb, mainarg.primes, mainarg.num_primes); mainarg.comb = comb; } else { /* don't use comb */ mainarg.comb = NULL; } /* limit on the number of threads */ limit = ((m + k + n)/128)*(1 + bits/1024); limit = FLINT_MIN(limit, (m + k)/4); /* mod */ if (limit < 2) { mod_single: mainarg.Astartrow = 0; mainarg.Astoprow = m; mainarg.Bstartrow = 0; mainarg.Bstoprow = k; _mod_worker(&mainarg); } else { num_workers = flint_request_threads(&handles, limit); if (num_workers < 1) { flint_give_back_threads(handles, num_workers); goto mod_single; } args = FLINT_ARRAY_ALLOC(num_workers, _worker_arg); for (start = 0, i = 0; i < num_workers; start = stop, i++) { args[i] = mainarg; stop = _thread_pool_find_work_2(m, k, k, n, i + 1, num_workers + 1); _thread_pool_distribute_work_2(start, stop, &args[i].Astartrow, &args[i].Astoprow, m, &args[i].Bstartrow, &args[i].Bstoprow, k); } _thread_pool_distribute_work_2(start, m + k, &mainarg.Astartrow, &mainarg.Astoprow, m, &mainarg.Bstartrow, &mainarg.Bstoprow, k); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _mod_worker, &args[i]); _mod_worker(&mainarg); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); flint_free(args); } /* mul */ for (i = 0; i < mainarg.num_primes; i++) nmod_mat_mul(mainarg.mod_C[i], mainarg.mod_A[i], squaring ? mainarg.mod_A[i] : mainarg.mod_B[i]); /* limit on the number of threads */ limit = ((m + n)/64)*(1 + bits/1024); limit = FLINT_MIN(limit, m/2); /* crt */ if (limit < 2) { crt_single: mainarg.Cstartrow = 0; mainarg.Cstoprow = m; _crt_worker(&mainarg); } else { num_workers = flint_request_threads(&handles, limit); if (num_workers < 1) { flint_give_back_threads(handles, num_workers); goto crt_single; } args = FLINT_ARRAY_ALLOC(num_workers, _worker_arg); for (start = 0, i = 0; i < num_workers; start = stop, i++) { args[i] = mainarg; stop = (i + 1)*m/(num_workers + 1); args[i].Cstartrow = start; args[i].Cstoprow = stop; } mainarg.Cstartrow = start; mainarg.Cstoprow = m; for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _crt_worker, &args[i]); _crt_worker(&mainarg); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); flint_free(args); } /* Cleanup */ if (mainarg.comb != NULL) fmpz_comb_clear(comb); for (i = 0; i < mainarg.num_primes; i++) { nmod_mat_clear(mainarg.mod_A[i]); if (!squaring) nmod_mat_clear(mainarg.mod_B[i]); nmod_mat_clear(mainarg.mod_C[i]); } flint_free(mainarg.mod_A); if (!squaring) flint_free(mainarg.mod_B); flint_free(mainarg.mod_C); flint_free(mainarg.primes); } void fmpz_mat_mul_multi_mod(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong Abits, Bbits; int sign = 0; flint_bitcnt_t Cbits; Abits = fmpz_mat_max_bits(A); Bbits = fmpz_mat_max_bits(B); if (Abits < 0) { sign = 1; Abits = -Abits; } if (Bbits < 0) { sign = 1; Bbits = -Bbits; } Cbits = Abits + Bbits + FLINT_BIT_COUNT(A->c); _fmpz_mat_mul_multi_mod(C, A, B, sign, Cbits); } flint-3.1.3/src/fmpz_mat/mul_small.c000066400000000000000000000263641461254215100174030ustar00rootroot00000000000000/* Copyright (C) 2010,2011,2018 Fredrik Johansson Copyright (C) 2016 Aaditya Thakkar Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_mat.h" static void _dot1(fmpz_t z, fmpz * a, slong * b, slong len) { slong i; slong s0 = 0; for (i = 0; i < len; i++) s0 += a[i]*b[i]; fmpz_set_si(z, s0); } static void _dot2(fmpz_t z, fmpz * a, slong * b, slong len) { slong i; ulong p1, p0, s1, s0; s1 = s0 = 0; for (i = 0; i < len; i++) { smul_ppmm(p1, p0, a[i], b[i]); add_ssaaaa(s1, s0, s1, s0, p1, p0); } fmpz_set_signed_uiui(z, s1, s0); } static void _dot3(fmpz_t z, fmpz * a, slong * b, slong len) { slong i; ulong p1, p0, s2, s1, s0; s2 = s1 = s0 = 0; for (i = 0; i < len; i++) { smul_ppmm(p1, p0, a[i], b[i]); add_sssaaaaaa(s2, s1, s0, s2, s1, s0, FLINT_SIGN_EXT(p1), p1, p0); } fmpz_set_signed_uiuiui(z, s2, s1, s0); } static void _dot_add1(ulong * s, fmpz * a, slong * b, slong len) { slong i; slong s0 = s[0]; for (i = 0; i < len; i++) s0 += a[i]*b[i]; s[0] = s0; } static void _dot_add2(ulong * s, fmpz * a, slong * b, slong len) { slong i; ulong p1, p0, s1, s0, t1, t0; FLINT_ASSERT(len > 0); s0 = s[0]; s1 = s[1]; if (len & 1) { smul_ppmm(t1, t0, a[0], b[0]); a++; b++; } else { t1 = t0 = 0; } for (i = 0; i < len/2; i++) { smul_ppmm(p1, p0, a[2*i+0], b[2*i+0]); add_ssaaaa(s1, s0, s1, s0, p1, p0); smul_ppmm(p1, p0, a[2*i+1], b[2*i+1]); add_ssaaaa(t1, t0, t1, t0, p1, p0); } add_ssaaaa(s1, s0, s1, s0, t1, t0); s[0] = s0; s[1] = s1; } static void _dot_add3(ulong * s, fmpz * a, slong * b, slong len) { slong i; ulong p1, p0, s2, s1, s0, t2, t1, t0; FLINT_ASSERT(len > 0); s0 = s[0]; s1 = s[1]; s2 = s[2]; if (len & 1) { smul_ppmm(t1, t0, a[0], b[0]); t2 = FLINT_SIGN_EXT(t1); a++; b++; } else { t2 = t1 = t0 = 0; } for (i = 0; i < len/2; i++) { smul_ppmm(p1, p0, a[2*i+0], b[2*i+0]); add_sssaaaaaa(s2, s1, s0, s2, s1, s0, FLINT_SIGN_EXT(p1), p1, p0); smul_ppmm(p1, p0, a[2*i+1], b[2*i+1]); add_sssaaaaaa(t2, t1, t0, t2, t1, t0, FLINT_SIGN_EXT(p1), p1, p0); } add_sssaaaaaa(s2, s1, s0, s2, s1, s0, t2, t1, t0); s[0] = s0; s[1] = s1; s[2] = s2; } typedef struct { slong Astartrow; slong Astoprow; slong Bstartcol; slong Bstopcol; slong n; slong k; slong m; slong k_blk_sz; slong m_blk_sz; fmpz ** Crows; fmpz ** Arows; fmpz ** Brows; slong * BL; int words; } _worker_arg; static void _tr_worker(void * varg) { _worker_arg * arg = (_worker_arg *) varg; slong Bstartcol = arg->Bstartcol; slong Bstopcol = arg->Bstopcol; slong k = arg->k; slong n = arg->n; slong k_blk_sz = arg->k_blk_sz; fmpz ** Brows = arg->Brows; slong * BL = arg->BL; slong i, iq, ir, j; iq = ir = 0; for (i = 0; i < k; i++) { for (j = Bstartcol; j < Bstopcol; j++) BL[iq*n*k_blk_sz + j*k_blk_sz + ir] = Brows[i][j]; /* (iq, ir) = divrem(i, k_blk_sz) */ ir++; if (ir >= k_blk_sz) { iq++; ir = 0; } } } static void _mul_worker(void * varg) { _worker_arg * arg = (_worker_arg *) varg; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong n = arg->n; slong k = arg->k; slong m_blk_sz = arg->m_blk_sz; slong k_blk_sz = arg->k_blk_sz; fmpz ** Crows = arg->Crows; fmpz ** Arows = arg->Arows; slong * BL = arg->BL; slong * TA; ulong * TC; slong h, hh, i, ii, j; int words = arg->words; TMP_INIT; if (k <= k_blk_sz) { /* no blocking overhead: the B matrix is fully transposed in BL */ if (words == 1) { for (h = Astartrow; h < Astoprow; h++) for (j = 0; j < n; j++) _dot1(&Crows[h][j], Arows[h], &BL[j*k_blk_sz], k); } else if (words == 2) { for (h = Astartrow; h < Astoprow; h++) for (j = 0; j < n; j++) _dot2(&Crows[h][j], Arows[h], &BL[j*k_blk_sz], k); } else { for (h = Astartrow; h < Astoprow; h++) for (j = 0; j < n; j++) _dot3(&Crows[h][j], Arows[h], &BL[j*k_blk_sz], k); } return; } TMP_START; TA = TMP_ARRAY_ALLOC(m_blk_sz*k_blk_sz, slong); TC = TMP_ARRAY_ALLOC(n*m_blk_sz*words, ulong); for (h = Astartrow; h < Astoprow; h += m_blk_sz) { slong hstop = FLINT_MIN(Astoprow - h, m_blk_sz); /* TC is a compressed block for the answer C[h:h+hhstop-1, all] */ for (j = 0; j < n*hstop*words; j++) TC[j] = 0; for (i = 0; i < k; i += k_blk_sz) { slong istop = FLINT_MIN(k_blk_sz, k - i); /* get a compressed copy of A[h:h+hhstop, i:i+iistop] into TA */ for (hh = 0; hh < hstop; hh++) for (ii = 0; ii < istop; ii++) TA[hh*k_blk_sz + ii] = Arows[h + hh][i + ii]; /* addmul into answer block */ if (words == 1) { for (j = 0; j < n; j++) for (hh = 0; hh < hstop; hh++) _dot_add1(&TC[1*(hh + hstop*j)], &TA[hh*k_blk_sz], &BL[i*n + j*k_blk_sz], istop); } else if (words == 2) { for (j = 0; j < n; j++) for (hh = 0; hh < hstop; hh++) _dot_add2(&TC[2*(hh + hstop*j)], &TA[hh*k_blk_sz], &BL[i*n + j*k_blk_sz], istop); } else { for (j = 0; j < n; j++) for (hh = 0; hh < hstop; hh++) _dot_add3(&TC[3*(hh + hstop*j)], &TA[hh*k_blk_sz], &BL[i*n + j*k_blk_sz], istop); } } /* copy out answer for C[h:h+hhstop-1, all] */ if (words == 1) { for (j = 0; j < n; j++) for (hh = 0; hh < hstop; hh++) fmpz_set_si(&Crows[h + hh][j], (slong)TC[hh + hstop*j]); } else if (words == 2) { for (j = 0; j < n; j++) for (hh = 0; hh < hstop; hh++) fmpz_set_signed_uiui(&Crows[h + hh][j], TC[2*(hh + hstop*j) + 1], TC[2*(hh + hstop*j) + 0]); } else { for (j = 0; j < n; j++) for (hh = 0; hh < hstop; hh++) fmpz_set_signed_uiuiui(&Crows[h + hh][j], TC[3*(hh + hstop*j) + 2], TC[3*(hh + hstop*j) + 1], TC[3*(hh + hstop*j) + 0]); } } TMP_END; return; } void _fmpz_mat_mul_small_internal( fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, flint_bitcnt_t Cbits) { slong i; slong m = fmpz_mat_nrows(A); slong k = fmpz_mat_nrows(B); slong n = fmpz_mat_ncols(B); _worker_arg mainarg; thread_pool_handle * handles; slong num_workers; _worker_arg * args; slong limit; slong k_blk_ct; slong k_blk_sz; slong m_blk_sz; TMP_INIT; FLINT_ASSERT(m > 0 && k > 0 && n > 0); TMP_START; /* _dot1 moves through the data quickly, so it is worth blocking */ /* block size in the m direction */ m_blk_sz = 16; /* choose a block size in the k direction */ if (k <= 128) { k_blk_sz = k; k_blk_ct = 1; } else { k_blk_sz = 128; k_blk_ct = (k + k_blk_sz - 1)/k_blk_sz; } mainarg.m_blk_sz = m_blk_sz; mainarg.k_blk_sz = k_blk_sz; mainarg.Astartrow = 0; mainarg.Astoprow = m; mainarg.Bstartcol = 0; mainarg.Bstopcol = n; mainarg.k = k; mainarg.m = m; mainarg.n = n; mainarg.Crows = C->rows; mainarg.Arows = A->rows; mainarg.Brows = B->rows; mainarg.BL = TMP_ARRAY_ALLOC(n*k_blk_ct*k_blk_sz, slong); if (Cbits <= SMALL_FMPZ_BITCOUNT_MAX) mainarg.words = 1; else if (Cbits <= 2*FLINT_BITS - 1) mainarg.words = 2; else mainarg.words = 3; /* limit on number of threads */ limit = FLINT_MAX(k, n); limit = FLINT_MIN(limit, m); limit = limit < 32 ? 0 : (limit - 32)/16; if (limit < 2) { use_one_thread: _tr_worker(&mainarg); _mul_worker(&mainarg); TMP_END; return; } num_workers = flint_request_threads(&handles, limit); if (num_workers < 1) { flint_give_back_threads(handles, num_workers); goto use_one_thread; } args = FLINT_ARRAY_ALLOC(num_workers, _worker_arg); for (i = 0; i < num_workers; i++) { args[i].m_blk_sz = mainarg.m_blk_sz; args[i].k_blk_sz = mainarg.k_blk_sz; args[i].Astartrow = (i + 0)*m/(num_workers + 1); args[i].Astoprow = (i + 1)*m/(num_workers + 1); args[i].Bstartcol = (i + 0)*n/(num_workers + 1); args[i].Bstopcol = (i + 1)*n/(num_workers + 1); args[i].k = mainarg.k; args[i].m = mainarg.m; args[i].n = mainarg.n; args[i].Crows = mainarg.Crows; args[i].Arows = mainarg.Arows; args[i].Brows = mainarg.Brows; args[i].BL = mainarg.BL; args[i].words = mainarg.words; } i = num_workers; mainarg.Astartrow = (i + 0)*m/(num_workers + 1); mainarg.Astoprow = (i + 1)*m/(num_workers + 1); mainarg.Bstartcol = (i + 0)*n/(num_workers + 1); mainarg.Bstopcol = (i + 1)*n/(num_workers + 1); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _tr_worker, &args[i]); _tr_worker(&mainarg); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _mul_worker, &args[i]); _mul_worker(&mainarg); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); flint_free(args); TMP_END; } void _fmpz_mat_mul_small(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong Abits, Bbits; flint_bitcnt_t Cbits; if (fmpz_mat_is_empty(A) || fmpz_mat_is_empty(B)) { fmpz_mat_zero(C); return; } Abits = fmpz_mat_max_bits(A); Bbits = fmpz_mat_max_bits(B); Abits = FLINT_ABS(Abits); Bbits = FLINT_ABS(Bbits); Cbits = Abits + Bbits + FLINT_BIT_COUNT(A->c); _fmpz_mat_mul_small_internal(C, A, B, Cbits); } flint-3.1.3/src/fmpz_mat/mul_strassen.c000066400000000000000000000100261461254215100201210ustar00rootroot00000000000000/* Copyright (C) 2016 Aaditya Thakkar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" /* The implemented sequence is not Strassen's nor Winograd's, but the sequence proposed by Bodrato, which is equivalent to Winograd's, and can be easily adapted to compute the square of a matrix. */ void fmpz_mat_mul_strassen(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong a, b, c; slong anr, anc, bnr, bnc; fmpz_mat_t A11, A12, A21, A22; fmpz_mat_t B11, B12, B21, B22; fmpz_mat_t C11, C12, C21, C22; fmpz_mat_t X1, X2; a = A->r; b = A->c; c = B->c; if (a <= 1 || b <= 1 || c <= 1) { fmpz_mat_mul_classical(C, A, B); return; } anr = a / 2; anc = b / 2; bnr = anc; bnc = c / 2; fmpz_mat_window_init(A11, A, 0, 0, anr, anc); fmpz_mat_window_init(A12, A, 0, anc, anr, 2*anc); fmpz_mat_window_init(A21, A, anr, 0, 2*anr, anc); fmpz_mat_window_init(A22, A, anr, anc, 2*anr, 2*anc); fmpz_mat_window_init(B11, B, 0, 0, bnr, bnc); fmpz_mat_window_init(B12, B, 0, bnc, bnr, 2*bnc); fmpz_mat_window_init(B21, B, bnr, 0, 2*bnr, bnc); fmpz_mat_window_init(B22, B, bnr, bnc, 2*bnr, 2*bnc); fmpz_mat_window_init(C11, C, 0, 0, anr, bnc); fmpz_mat_window_init(C12, C, 0, bnc, anr, 2*bnc); fmpz_mat_window_init(C21, C, anr, 0, 2*anr, bnc); fmpz_mat_window_init(C22, C, anr, bnc, 2*anr, 2*bnc); fmpz_mat_init(X1, anr, FLINT_MAX(bnc, anc)); fmpz_mat_init(X2, anc, bnc); X1->c = anc; fmpz_mat_add(X1, A22, A12); fmpz_mat_add(X2, B22, B12); fmpz_mat_mul(C21, X1, X2); fmpz_mat_sub(X1, A22, A21); fmpz_mat_sub(X2, B22, B21); fmpz_mat_mul(C22, X1, X2); fmpz_mat_add(X1, X1, A12); fmpz_mat_add(X2, X2, B12); fmpz_mat_mul(C11, X1, X2); fmpz_mat_sub(X1, X1, A11); fmpz_mat_mul(C12, X1, B12); X1->c = bnc; fmpz_mat_mul(X1, A12, B21); fmpz_mat_add(C11, C11, X1); fmpz_mat_add(C12, C12, C22); fmpz_mat_sub(C12, C11, C12); fmpz_mat_sub(C11, C21, C11); fmpz_mat_sub(X2, X2, B11); fmpz_mat_mul(C21, A21, X2); fmpz_mat_clear(X2); fmpz_mat_sub(C21, C11, C21); fmpz_mat_add(C22, C22, C11); fmpz_mat_mul(C11, A11, B11); fmpz_mat_add(C11, X1, C11); X1->c = FLINT_MAX(bnc, anc); fmpz_mat_clear(X1); fmpz_mat_window_clear(A11); fmpz_mat_window_clear(A12); fmpz_mat_window_clear(A21); fmpz_mat_window_clear(A22); fmpz_mat_window_clear(B11); fmpz_mat_window_clear(B12); fmpz_mat_window_clear(B21); fmpz_mat_window_clear(B22); fmpz_mat_window_clear(C11); fmpz_mat_window_clear(C12); fmpz_mat_window_clear(C21); fmpz_mat_window_clear(C22); if (c > 2*bnc) { fmpz_mat_t Bc, Cc; fmpz_mat_window_init(Bc, B, 0, 2*bnc, b, c); fmpz_mat_window_init(Cc, C, 0, 2*bnc, a, c); fmpz_mat_mul(Cc, A, Bc); fmpz_mat_window_clear(Bc); fmpz_mat_window_clear(Cc); } if (a > 2*anr) { fmpz_mat_t Ar, Cr; fmpz_mat_window_init(Ar, A, 2*anr, 0, a, b); fmpz_mat_window_init(Cr, C, 2*anr, 0, a, c); fmpz_mat_mul(Cr, Ar, B); fmpz_mat_window_clear(Ar); fmpz_mat_window_clear(Cr); } if (b > 2*anc) { fmpz_mat_t Ac, Br, Cb, tmp; slong mt, nt; fmpz_mat_window_init(Ac, A, 0, 2*anc, 2*anr, b); fmpz_mat_window_init(Br, B, 2*bnr, 0, b, 2*bnc); fmpz_mat_window_init(Cb, C, 0, 0, 2*anr, 2*bnc); mt = Ac->r; nt = Br->c; fmpz_mat_init(tmp, mt, nt); fmpz_mat_mul(tmp, Ac, Br); fmpz_mat_add(Cb, Cb, tmp); fmpz_mat_clear(tmp); fmpz_mat_window_clear(Ac); fmpz_mat_window_clear(Br); fmpz_mat_window_clear(Cb); } } flint-3.1.3/src/fmpz_mat/mul_waksman.c000066400000000000000000000077501461254215100177320ustar00rootroot00000000000000/* Copyright (C) 2024 Éric Schost Copyright (C) 2024 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" /** ------------------------------------------------------------ */ /** Waksman's algorithm for matrix multiplication */ /** does n^3/2+O(n^2) products, but many additions */ /** good for small matrices with large entries */ /** ------------------------------------------------------------ */ void fmpz_mat_mul_waksman(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong m = A->r; slong n = B->r; slong p = B->c; if (m == 0 || n == 0 || p == 0) { fmpz_mat_zero(C); return; } slong i, l, j, k; fmpz * Crow = _fmpz_vec_init(p + m); fmpz * Ccol = Crow + p; slong np = n >> 1; fmpz_t val0, val1, val2, crow; fmpz_init(val0); fmpz_init(val1); fmpz_init(val2); fmpz_init(crow); for (i = 0; i < p; i++) fmpz_zero(Crow + i); for (i = 0; i < m; i++) fmpz_zero(Ccol + i); for (i = 0; i < m; i++) for (j = 0; j < p; j++) fmpz_zero(fmpz_mat_entry(C, i, j)); for (j = 1; j <= np; j++) { slong j2 = (j << 1) - 1; for (k = 0; k < p; k++) { fmpz_add(val1, fmpz_mat_entry(A, 0, j2-1), fmpz_mat_entry(B, j2, k)); fmpz_add(val2, fmpz_mat_entry(A, 0, j2), fmpz_mat_entry(B, j2-1, k)); fmpz_addmul(fmpz_mat_entry(C, 0, k), val1, val2); fmpz_sub(val1, fmpz_mat_entry(A, 0, j2-1), fmpz_mat_entry(B, j2, k)); fmpz_sub(val2, fmpz_mat_entry(A, 0, j2), fmpz_mat_entry(B, j2-1, k)); fmpz_addmul(Crow + k, val1, val2); } for (l = 1; l < m; l++) { fmpz_add(val1, fmpz_mat_entry(A, l, j2-1), fmpz_mat_entry(B, j2, 0)); fmpz_add(val2, fmpz_mat_entry(A, l, j2), fmpz_mat_entry(B, j2-1, 0)); fmpz_addmul(fmpz_mat_entry(C, l, 0), val1, val2); fmpz_sub(val1, fmpz_mat_entry(A, l, j2-1), fmpz_mat_entry(B, j2, 0)); fmpz_sub(val2, fmpz_mat_entry(A, l, j2), fmpz_mat_entry(B, j2-1, 0)); fmpz_addmul(Ccol + l, val1, val2); } for (k = 1; k < p; k++) { for (l = 1; l < m; l++) { fmpz_add(val1, fmpz_mat_entry(A, l, j2-1), fmpz_mat_entry(B, j2, k)); fmpz_add(val2, fmpz_mat_entry(A, l, j2), fmpz_mat_entry(B, j2-1, k)); fmpz_addmul(fmpz_mat_entry(C, l, k), val1, val2); } } } for (l = 1; l < m; l++) { fmpz_add(val1, Ccol + l, fmpz_mat_entry(C, l, 0)); fmpz_tdiv_q_2exp(Ccol+ l, val1, 1); fmpz_sub(fmpz_mat_entry(C, l, 0), fmpz_mat_entry(C, l, 0), Ccol + l); } fmpz_add(val1, Crow, fmpz_mat_entry(C, 0, 0)); fmpz_tdiv_q_2exp(val0, val1, 1); fmpz_sub(fmpz_mat_entry(C, 0, 0), fmpz_mat_entry(C, 0, 0), val0); for (k = 1; k < p; k++) { fmpz_add(crow, Crow + k, fmpz_mat_entry(C, 0, k)); fmpz_tdiv_q_2exp(val1, crow, 1); fmpz_sub(fmpz_mat_entry(C, 0, k), fmpz_mat_entry(C, 0, k), val1); fmpz_sub(crow, val1, val0); for (l = 1; l < m; l++) { fmpz_sub(val2, fmpz_mat_entry(C, l, k), crow); fmpz_sub(fmpz_mat_entry(C, l, k), val2, Ccol + l); } } if ((n & 1) == 1) for (l = 0; l < m; l++) for (k = 0; k < p; k++) fmpz_addmul(fmpz_mat_entry(C, l, k), fmpz_mat_entry(A, l, n-1), fmpz_mat_entry(B, n-1, k)); _fmpz_vec_clear(Crow, p + m); fmpz_clear(val0); fmpz_clear(val1); fmpz_clear(val2); fmpz_clear(crow); } flint-3.1.3/src/fmpz_mat/multi_CRT_ui.c000066400000000000000000000030241461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_multi_CRT_ui_precomp(fmpz_mat_t mat, nmod_mat_t * const residues, slong nres, const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign) { slong i, j, k; mp_ptr r; r = _nmod_vec_init(nres); for (i = 0; i < fmpz_mat_nrows(mat); i++) { for (j = 0; j < fmpz_mat_ncols(mat); j++) { for (k = 0; k < nres; k++) r[k] = nmod_mat_entry(residues[k], i, j); fmpz_multi_CRT_ui(fmpz_mat_entry(mat, i, j), r, comb, temp, sign); } } _nmod_vec_clear(r); } void fmpz_mat_multi_CRT_ui(fmpz_mat_t mat, nmod_mat_t * const residues, slong nres, int sign) { fmpz_comb_t comb; fmpz_comb_temp_t temp; mp_ptr primes; slong i; primes = _nmod_vec_init(nres); for (i = 0; i < nres; i++) primes[i] = residues[i]->mod.n; fmpz_comb_init(comb, primes, nres); fmpz_comb_temp_init(temp, comb); fmpz_mat_multi_CRT_ui_precomp(mat, residues, nres, comb, temp, sign); fmpz_comb_clear(comb); fmpz_comb_temp_clear(temp); _nmod_vec_clear(primes); } flint-3.1.3/src/fmpz_mat/multi_mod_ui.c000066400000000000000000000027531461254215100201000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_multi_mod_ui_precomp(nmod_mat_t * residues, slong nres, const fmpz_mat_t mat, const fmpz_comb_t comb, fmpz_comb_temp_t temp) { slong i, j, k; mp_ptr r; r = _nmod_vec_init(nres); for (i = 0; i < fmpz_mat_nrows(mat); i++) { for (j = 0; j < fmpz_mat_ncols(mat); j++) { fmpz_multi_mod_ui(r, fmpz_mat_entry(mat, i, j), comb, temp); for (k = 0; k < nres; k++) nmod_mat_entry(residues[k], i, j) = r[k]; } } _nmod_vec_clear(r); } void fmpz_mat_multi_mod_ui(nmod_mat_t * residues, slong nres, const fmpz_mat_t mat) { fmpz_comb_t comb; fmpz_comb_temp_t temp; mp_ptr primes; slong i; primes = _nmod_vec_init(nres); for (i = 0; i < nres; i++) primes[i] = residues[i]->mod.n; fmpz_comb_init(comb, primes, nres); fmpz_comb_temp_init(temp, comb); fmpz_mat_multi_mod_ui_precomp(residues, nres, mat, comb, temp); fmpz_comb_clear(comb); fmpz_comb_temp_clear(temp); _nmod_vec_clear(primes); } flint-3.1.3/src/fmpz_mat/neg.c000066400000000000000000000011671461254215100161610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_neg(fmpz_mat_t res, const fmpz_mat_t mat) { slong i; if (res->c < 1) return; for (i = 0; i < res->r; i++) _fmpz_vec_neg(res->rows[i], mat->rows[i], res->c); } flint-3.1.3/src/fmpz_mat/next_col_van_hoeij.c000066400000000000000000000065021461254215100212430ustar00rootroot00000000000000/* Copyright (C) 2011, 2016 William Hart Copyright (C) 2011 Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void _fmpz_mat_resize_van_hoeij(fmpz_mat_t M, slong r, slong c) { slong i, j; fmpz * old_entries = M->entries; M->entries = (fmpz *) flint_realloc(M->entries, r*c*sizeof(fmpz)); mpn_zero((mp_ptr) M->entries + M->r*M->c, r*c - M->r*M->c); if (r != M->r) /* we will have an extra row and column */ { M->rows = (fmpz **) flint_realloc(M->rows, r*sizeof(fmpz *)); for (i = r - 1; i >= 1; i--) { fmpz * old_row = M->entries + (i - 1)*M->c; fmpz * new_row = M->entries + i*c; for (j = M->c - 1; j >= 0; j--) fmpz_swap(old_row + j, new_row + j); } for (i = M->r - 1; i >= 0; i--) { slong diff = (slong) (M->rows[i] - old_entries); if (M->rows[i] >= old_entries + M->c*M->r) flint_throw(FLINT_ERROR, "(%s)\n", __func__); j = diff/M->c; M->rows[i + 1] = M->entries + (j + 1)*c; } M->rows[0] = M->entries; } else /* have only an extra column */ { /* rows of M may be out of order */ for (i = r - 1; i >= 0; i--) { fmpz * old_row = M->entries + i*M->c; fmpz * new_row = M->entries + i*c; for (j = M->c - 1; j >= 0; j--) fmpz_swap(old_row + j, new_row + j); } for (i = 0; i < r; i++) { slong diff = (slong) (M->rows[i] - old_entries); j = diff/M->c; M->rows[i] = M->entries + j*c; } } M->r = r; M->c = c; } int fmpz_mat_next_col_van_hoeij(fmpz_mat_t M, fmpz_t P, fmpz_mat_t col, slong exp, slong U_exp) { slong j, k, r = col->r; slong bit_r = FLINT_MAX(r, 20); slong s = M->r; fmpz_mat_t U, x, y; fmpz_t P_trunc; k = fmpz_bits(P) - bit_r - bit_r/2; /* check if LLL justified */ if (k < exp + (slong) FLINT_BIT_COUNT(r + 1)) return 0; fmpz_init(P_trunc); fmpz_mat_init(x, r, 1); fmpz_mat_init(y, s, 1); /* find U, the combinatorial part of M */ fmpz_mat_window_init(U, M, 0, 0, s, r); /* find scale factor 2^k */ k -= U_exp; /* we want this many bits beyond the radix point */ if (k >= 0) { fmpz_mat_scalar_tdiv_q_2exp(x, col, k); fmpz_tdiv_q_2exp(P_trunc, P, k); } else { fmpz_mat_scalar_mul_2exp(x, col, -k); fmpz_mul_2exp(P_trunc, P, -k); } /* multiply column by U */ fmpz_mat_mul(y, U, x); /* everything in U was already scaled by U_exp, so divide out scaling */ fmpz_mat_scalar_tdiv_q_2exp(y, y, U_exp); fmpz_mat_scalar_smod(y, y, P_trunc); /* resize M */ _fmpz_mat_resize_van_hoeij(M, s + 1, M->c + 1); /* insert new column and row data */ fmpz_set(M->rows[0] + M->c - 1, P_trunc); for (j = 1; j < M->r; j++) fmpz_set(M->rows[j] + M->c - 1, y->rows[j - 1]); fmpz_mat_clear(x); fmpz_mat_clear(y); fmpz_clear(P_trunc); fmpz_mat_window_clear(U); return 1; } flint-3.1.3/src/fmpz_mat/nullspace.c000066400000000000000000000034241461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" slong fmpz_mat_nullspace(fmpz_mat_t res, const fmpz_mat_t mat) { slong i, j, k, n, rank, nullity; slong * pivots; slong * nonpivots; fmpz_mat_t tmp; fmpz_t den; n = mat->c; fmpz_mat_init_set(tmp, mat); fmpz_init(den); rank = fmpz_mat_rref(tmp, den, mat); nullity = n - rank; fmpz_mat_zero(res); if (rank == 0) { for (i = 0; i < nullity; i++) fmpz_one(res->rows[i] + i); } else if (nullity) { pivots = flint_malloc(rank * sizeof(slong)); nonpivots = flint_malloc(nullity * sizeof(slong)); for (i = j = k = 0; i < rank; i++) { while (fmpz_is_zero(tmp->rows[i] + j)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } fmpz_set(den, tmp->rows[0] + pivots[0]); for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) fmpz_set(res->rows[pivots[j]] + i, tmp->rows[j] + nonpivots[i]); fmpz_neg(res->rows[nonpivots[i]] + i, den); } flint_free(pivots); flint_free(nonpivots); } fmpz_clear(den); fmpz_mat_clear(tmp); return nullity; } flint-3.1.3/src/fmpz_mat/one.c000066400000000000000000000011441461254215100161640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_one(fmpz_mat_t mat) { slong i, n; fmpz_mat_zero(mat); n = FLINT_MIN(mat->r, mat->c); for (i = 0; i < n; i++) fmpz_one(fmpz_mat_entry(mat, i, i)); } flint-3.1.3/src/fmpz_mat/pow.c000066400000000000000000000026021461254215100162100ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_pow(fmpz_mat_t B, const fmpz_mat_t A, ulong exp) { slong d = fmpz_mat_nrows(A); if (exp <= 2 || d <= 1) { if (exp == 0 || d == 0) { fmpz_mat_one(B); } else if (d == 1) { fmpz_pow_ui(fmpz_mat_entry(B, 0, 0), fmpz_mat_entry(A, 0, 0), exp); } else if (exp == 1) { fmpz_mat_set(B, A); } else if (exp == 2) { fmpz_mat_sqr(B, A); } } else { fmpz_mat_t T, U; slong i; fmpz_mat_init_set(T, A); fmpz_mat_init(U, d, d); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { fmpz_mat_sqr(U, T); if (exp & (WORD(1) << i)) fmpz_mat_mul(T, U, A); else fmpz_mat_swap(T, U); } fmpz_mat_swap(B, T); fmpz_mat_clear(T); fmpz_mat_clear(U); } } flint-3.1.3/src/fmpz_mat/profile/000077500000000000000000000000001461254215100166775ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mat/profile/p-big_mul.c000066400000000000000000000145351461254215100207260ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz_mat.h" #include "fmpz.h" #include "ulong_extras.h" /* run this code on two version and redirect the output of each to new.jl and old.jl, and then run this simple julia program: randtest = Dict{Tuple{Int, Int, Int, Int, Int}, Float64}() pascal = Dict{Tuple{Int, Int, Int, Int, Int}, Float64}() include("old.jl") old_randtest = deepcopy(randtest) old_pascal = deepcopy(pascal) randtest = Dict{Tuple{Int, Int, Int, Int, Int}, Float64}() pascal = Dict{Tuple{Int, Int, Int, Int, Int}, Float64}() include("new.jl") new_randtest = deepcopy(randtest) new_pascal = deepcopy(pascal) function scan_output(newtest, oldtest, name::String) for (a, b) in newtest if !haskey(oldtest, a) continue end c = oldtest[a] r = c/b if r < 0.5 col = 1 elseif r < 0.75 col = 166 elseif r < 0.875 col = 3 elseif r < 1.125 col = 0 elseif r < 2.0 col = 82 else col = 51 end printstyled(name, a, " new ", b, " old ", c, " ratio ", r, "\n"; color = col) end end scan_output(new_randtest, old_randtest, "randtest") scan_output(new_pascal, old_pascal, "pascal") */ static void fmpz_mat_pascal(fmpz_mat_t mat, int triangular) { slong R, C, i, j; R = fmpz_mat_nrows(mat); C = fmpz_mat_ncols(mat); if (R == 0 || C == 0) return; if (triangular > 0) { for (i = 1; i < R; i++) for (j = 0; j < i && j < C; j++) fmpz_zero(fmpz_mat_entry(mat, i, j)); for (j = 0; j < C; j++) fmpz_one(fmpz_mat_entry(mat, 0, j)); for (i = 1; i < R && i < C; i++) fmpz_one(fmpz_mat_entry(mat, i, i)); for (i = 1; i < R; i++) for (j = i + 1; j < C; j++) fmpz_add(fmpz_mat_entry(mat, i, j), fmpz_mat_entry(mat, i, j - 1), fmpz_mat_entry(mat, i - 1, j - 1)); } else if (triangular < 0) { for (i = 0; i < R; i++) for (j = i + 1; j < C; j++) fmpz_zero(fmpz_mat_entry(mat, i, j)); for (i = 0; i < R; i++) fmpz_one(fmpz_mat_entry(mat, i, 0)); for (i = 1; i < R && i < C; i++) fmpz_one(fmpz_mat_entry(mat, i, i)); for (i = 2; i < R; i++) for (j = 1; j < i && j < C; j++) fmpz_add(fmpz_mat_entry(mat, i, j), fmpz_mat_entry(mat, i - 1, j - 1), fmpz_mat_entry(mat, i - 1, j)); } else { for (j = 0; j < C; j++) fmpz_one(fmpz_mat_entry(mat, 0, j)); for (i = 1; i < R; i++) fmpz_one(fmpz_mat_entry(mat, i, 0)); for (i = 1; i < R; i++) for (j = 1; j < C; j++) fmpz_add(fmpz_mat_entry(mat, i, j), fmpz_mat_entry(mat, i, j - 1), fmpz_mat_entry(mat, i - 1, j)); } } slong rep_time(timeit_t timer, fmpz_mat_t C, fmpz_mat_t A, fmpz_mat_t B) { slong i, j, t, reps = 1; timeit_start(timer); fmpz_mat_mul(C, A, B); t = timeit_query_wall(timer); if (t < 300) { j = 2 + 300/(1 + t); do { reps += j; for (i = j; i > 0; i--) fmpz_mat_mul(C, A, B); } while (timeit_query_wall(timer) < 300); } timeit_stop(timer); return reps; } int main(void) { slong t, tmul = 300; slong m, k, n, reps; flint_bitcnt_t Abits, Bbits; fmpz_mat_t A, B, C; timeit_t timer; FLINT_TEST_INIT(state); flint_set_num_threads(8); for (t = 0; t < tmul; t++) { if (t % 10 == 0) fprintf(stderr, "#randtest %d/%d\n", (int)t, (int)tmul); m = 2 + n_randint(state, 500); k = 3 + n_randint(state, 500); n = 2 + n_randint(state, 500); Abits = 5 + n_randint(state, 1000); Bbits = 5 + n_randint(state, 1000); fmpz_mat_init(A, m, k); fmpz_mat_init(B, k, n); fmpz_mat_init(C, m, n); fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); reps = rep_time(timer, C, A, B); flint_printf("randtest[%wd, %wd, %wd, %wd, %wd] = %.3f #ns %wd reps\n", m, k, n, Abits, Bbits, timer->wall*1000000.0/reps/m/k/n, reps); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } for (t = 0; t < tmul; t++) { if (t % 10 == 0) fprintf(stderr, "#randtest square %d/%d\n", (int)t, (int)tmul); m = k = n = 3 + n_randint(state, 1500); Abits = Bbits = 5 + n_randint(state, 1 + 100000/(10 + m)); fmpz_mat_init(A, m, k); fmpz_mat_init(B, k, n); fmpz_mat_init(C, m, n); fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); reps = rep_time(timer, C, A, B); flint_printf("randtest[%wd, %wd, %wd, %wd, %wd] = %.3f #ns %wd reps\n", m, k, n, Abits, Bbits, timer->wall*1000000.0/reps/m/k/n, reps); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } for (t = 0; t < tmul; t++) { int atri, btri; if (t % 10 == 0) fprintf(stderr, "#pascal %d/%d\n", (int)t, (int)tmul); m = 2 + n_randint(state, 600); k = 3 + n_randint(state, 600); n = 2 + n_randint(state, 600); fmpz_mat_init(A, m, k); fmpz_mat_init(B, k, n); fmpz_mat_init(C, m, n); atri = -1 + (int)n_randint(state, 3); btri = -1 + (int)n_randint(state, 3); fmpz_mat_pascal(A, atri); fmpz_mat_pascal(B, btri); reps = rep_time(timer, C, A, B); flint_printf("pascal[%wd, %wd, %wd, %d, %d] = %.3f #ns %wd reps\n", m, k, n, atri, btri, timer->wall*1000000.0/reps/m/k/n, reps); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mat/profile/p-det.c000066400000000000000000000044421461254215100200600ustar00rootroot00000000000000/* Copyright 2009 William Hart Copyright 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz_mat.h" #include "fmpz.h" #include "ulong_extras.h" typedef struct { ulong dim; int algorithm; slong bits; } mat_mul_t; void sample(void * arg, ulong count) { mat_mul_t * params = (mat_mul_t *) arg; ulong i, dim = params->dim; slong bits = params->bits; int algorithm = params->algorithm; fmpz_mat_t A; fmpz_t d; FLINT_TEST_INIT(state); fmpz_mat_init(A, dim, dim); fmpz_init(d); fmpz_mat_randtest(A, state, bits); prof_start(); if (algorithm == 0) for (i = 0; i < count; i++) fmpz_mat_det_bareiss(d, A); else if (algorithm == 1) for (i = 0; i < count; i++) fmpz_mat_det_modular(d, A, 1); else if (algorithm == 2) for (i = 0; i < count; i++) fmpz_mat_det_modular_accelerated(d, A, 1); prof_stop(); fmpz_mat_clear(A); fmpz_clear(d); flint_randclear(state); } int main(void) { double min_classical, min_modular, min_modular_2, max; mat_mul_t params; slong dim, bits; params.bits = 200; for (bits = 2; bits <= 4096; bits *= 2) { params.bits = bits; flint_printf("fmpz_mat_det (bits = %wd):\n", params.bits); for (dim = 2; dim <= 512; dim = (slong) ((double) dim * 1.1) + 1) { params.dim = dim; params.algorithm = 0; prof_repeat(&min_classical, &max, sample, ¶ms); params.algorithm = 1; prof_repeat(&min_modular, &max, sample, ¶ms); params.algorithm = 2; prof_repeat(&min_modular_2, &max, sample, ¶ms); flint_printf("dim = %wd classical/modular/acc. %.2f %.2f %.2f (us)\n", dim, min_classical, min_modular, min_modular_2); if (min_modular > 1.1*min_modular_2) break; } } return 0; } flint-3.1.3/src/fmpz_mat/profile/p-mul.c000066400000000000000000000100761461254215100201010ustar00rootroot00000000000000/* Copyright 2009 William Hart Copyright 2010, 2011, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "fmpz_mat.h" #include "fmpz.h" #include "ulong_extras.h" #define RANDOMIZED 1 #define TABLE 2 slong ns_tab[10]; slong bits_tab[10]; #define DEFAULT 0 #define CLASSICAL 1 #define WAKSMAN 2 #define MULTIMOD 3 #define STRASSEN 4 const char * names[] = {"DEFAULT", "CLASSICAL", "WAKSMAN", "MULTIMOD", "STRASSEN"}; double timing(flint_rand_t state, slong n, slong m, slong k, slong bits1, slong bits2, int randtest, int algorithm) { double __attribute__((unused)) tcpu, twall; fmpz_mat_t A, B, C; fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); if (randtest) { fmpz_mat_randtest(A, state, bits1); fmpz_mat_randtest(B, state, bits2); } else { fmpz_mat_randbits(A, state, bits1); fmpz_mat_randbits(B, state, bits2); } TIMEIT_START if (algorithm == DEFAULT) fmpz_mat_mul(C, A, B); else if (algorithm == CLASSICAL) fmpz_mat_mul_classical(C, A, B); else if (algorithm == WAKSMAN) fmpz_mat_mul_waksman(C, A, B); else if (algorithm == MULTIMOD) fmpz_mat_mul_multi_mod(C, A, B); else if (algorithm == STRASSEN) fmpz_mat_mul_strassen(C, A, B); TIMEIT_STOP_VALUES(tcpu, twall) fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); return twall; } void compare_two(int parameters, int alg1, int alg2) { double t1, t2; slong m, n, k, bits1, bits2, iter; int randtest; flint_rand_t state, state1, state2; flint_randinit(state); flint_randinit(state1); flint_randinit(state2); flint_printf("A = %s\n", names[alg1]); flint_printf("B = %s\n\n", names[alg2]); flint_printf(" m n k bits1 bits2 r A B speedup\n"); for (iter = 0; iter < 100; iter++) { if (parameters == RANDOMIZED) { m = 1 + n_randint(state, 60); if (n_randint(state, 2)) { n = 1 + n_randint(state, 60); k = 1 + n_randint(state, 60); } else { n = m + n_randint(state, 2); k = m + n_randint(state, 2); } bits1 = 2 + n_randint(state, 1 << (5 + n_randint(state, 10))); if (n_randint(state, 2)) bits2 = bits1; else bits2 = 2 + n_randint(state, 1 + bits1); randtest = (n_randint(state, 4) == 0); } else { m = n = k = ns_tab[iter / 10]; bits1 = bits2 = bits_tab[iter % 10]; randtest = 0; } t1 = timing(state1, m, n, k, bits1, bits2, randtest, alg1); t2 = timing(state2, m, n, k, bits1, bits2, randtest, alg2); flint_printf("%4wd %4wd %4wd %5wd %5wd %d %6.8f %6.8f %.3f\n", m, n, k, bits1, bits2, randtest, t1, t2, t1 / t2); } flint_randclear(state); flint_randclear(state1); flint_randclear(state2); } int main(int argc, char * argv[]) { int params = RANDOMIZED; if (argc == 5) { slong i, a, b; a = atol(argv[1]); b = atol(argv[2]); for (i = 0; i < 10; i++) { ns_tab[i] = round(exp(((9-i) * log(a) + i * log(b))/9)); flint_printf("%wd\n", ns_tab[i]); } a = atol(argv[3]); b = atol(argv[4]); for (i = 0; i < 10; i++) { bits_tab[i] = round(exp(((9-i) * log(a) + i * log(b))/9)); flint_printf("%wd\n", bits_tab[i]); } params = TABLE; } compare_two(params, DEFAULT, WAKSMAN); return 0; } flint-3.1.3/src/fmpz_mat/profile/p-mul_blas_v_mul.c000066400000000000000000000050331461254215100223010ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_mat.h" #include "profiler.h" #if FLINT_USES_BLAS #include "cblas.h" int main(void) { slong dim, i, reps; flint_bitcnt_t Abits, Bbits, Cbits, maxAbits; slong time1, time2, Cbitscheckup = 0; double ratio; timeit_t timer; FLINT_TEST_INIT(state); flint_set_num_threads(8); openblas_set_num_threads(8); for (dim = 50; dim <= 3000; dim += 2 + dim/4) { fmpz_mat_t A, B, C, D; fmpz_mat_init(A, dim, dim); fmpz_mat_init(B, dim, dim); fmpz_mat_init(C, dim, dim); fmpz_mat_init(D, dim, dim); maxAbits = 700 + (20+50)*(3000-800)/(20+dim); if (--Cbitscheckup < 0) { flint_printf(" C bits : "); for (Abits = 10; Abits < maxAbits; Abits += 1 + Abits/4) { Bbits = Abits; Cbits = Abits + Bbits + FLINT_BIT_COUNT(dim); flint_printf("%5wd ", Cbits); } flint_printf("\n"); Cbitscheckup = 5; } flint_printf("dim %4wd: |", dim); fflush(stdout); for (Abits = 10; Abits < maxAbits; Abits += 1 + Abits/4) { Bbits = Abits; Cbits = Abits + Bbits + FLINT_BIT_COUNT(dim); fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); reps = 1 + 2000000000/dim/dim/dim/(20 + Cbits); timeit_start(timer); for (i = reps; i > 0; i--) fmpz_mat_mul_blas(C, A, B); timeit_stop(timer); time1 = timer->wall; timeit_start(timer); for (i = reps; i > 0; i--) fmpz_mat_mul(D, A, B); timeit_stop(timer); time2 = timer->wall; ratio = (double)time2/(double)time1; ratio = FLINT_MIN(ratio, 9.0); flint_printf(" %.2f |", ratio); fflush(stdout); } flint_printf("\n"); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); return 0; } #else int main(void) { return 0; } #endif flint-3.1.3/src/fmpz_mat/profile/p-mul_double_word.c000066400000000000000000000055601461254215100224700ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_mat.h" #include "profiler.h" int main(void) { slong sign; slong dim, i, reps, total, mint, maxt; double total_den, den; flint_bitcnt_t Abits, Bbits; timeit_t timer; FLINT_TEST_INIT(state); flint_set_num_threads(1); flint_printf("*** timings are nanoseconds per dim^3 ***\n"); for (sign = 0; sign <= 1; sign++) for (dim = 5; dim <= 400; dim += 4 + dim/16) { fmpz_mat_t A, B, C, D, E; fmpz_mat_init(A, dim, dim); fmpz_mat_init(B, dim, dim); fmpz_mat_init(C, dim, dim); fmpz_mat_init(D, dim, dim); fmpz_mat_init(E, dim, dim); reps = 2 + 3000000/dim/dim/dim; den = reps*dim*dim*dim; total = total_den = 0; mint = 10000000000; maxt = 0; for (Abits = FLINT_BITS - 1; Abits + sign <= 2*FLINT_BITS; Abits += 1) for (Bbits = Abits; Bbits + sign <= 2*FLINT_BITS; Bbits += 27) { if (sign) { fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); } else { fmpz_mat_randtest_unsigned(A, state, Abits); fmpz_mat_randtest_unsigned(B, state, Bbits); } timeit_start(timer); for (i = reps; i > 0; i--) _fmpz_mat_mul_double_word(E, A, B); timeit_stop(timer); total += timer->wall; total_den += ((double)reps)*dim*dim*dim; mint = FLINT_MIN(mint, timer->wall); maxt = FLINT_MAX(maxt, timer->wall); if (dim < 150) { fmpz_mat_mul_classical(D, A, B); if (!fmpz_mat_equal(D, E)) { flint_printf("E: "); fmpz_mat_print_pretty(E); flint_printf("\n"); flint_printf("D: "); fmpz_mat_print_pretty(D); flint_printf("\n"); flint_printf("oops %d %wu %wu\n", sign, Abits, Bbits); flint_abort(); } } } flint_printf("sign %d dim %3wd: min %.3f ns max %.3f ns aver %.3f ns\n", sign, dim, 1000000*mint/den, 1000000*maxt/den, 1000000*total/total_den); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); fmpz_mat_clear(E); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mat/profile/p-mul_double_word_v_mul_multi_mod.c000066400000000000000000000057521461254215100257460ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_mat.h" #include "profiler.h" int main(void) { slong sign, dim, i, reps, den; slong min1, max1, total1, min2, max2, total2, count; flint_bitcnt_t Abits, Bbits; timeit_t timer; FLINT_TEST_INIT(state); flint_set_num_threads(4); flint_printf("*** timings are nanoseconds per dim^3 ***\n"); for (sign = 1; sign <= 1; sign++) for (dim = 50; dim <= 2000; dim += 2 + dim/4) { fmpz_mat_t A, B, C, D; fmpz_mat_init(A, dim, dim); fmpz_mat_init(B, dim, dim); fmpz_mat_init(C, dim, dim); fmpz_mat_init(D, dim, dim); reps = 1 + 2000000/dim/dim/dim; den = reps*dim*dim*dim; count = 0; total1 = 0; min1 = 10000000000; max1 = 0; total2 = 0; min2 = 10000000000; max2 = 0; for (Abits = FLINT_BITS - 1; Abits + sign <= 2*FLINT_BITS; Abits += FLINT_BITS/3 - 1) for (Bbits = Abits; Bbits + sign <= 2*FLINT_BITS; Bbits += FLINT_BITS/3 - 1) { if (sign) { fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); } else { fmpz_mat_randtest_unsigned(A, state, Abits); fmpz_mat_randtest_unsigned(B, state, Bbits); } timeit_start(timer); for (i = reps; i > 0; i--) _fmpz_mat_mul_double_word(C, A, B); timeit_stop(timer); total1 += timer->wall; min1 = FLINT_MIN(min1, timer->wall); max1 = FLINT_MAX(max1, timer->wall); timeit_start(timer); for (i = reps; i > 0; i--) fmpz_mat_mul_multi_mod(D, A, B); timeit_stop(timer); total2 += timer->wall; min2 = FLINT_MIN(min2, timer->wall); max2 = FLINT_MAX(max2, timer->wall); count++; if (!fmpz_mat_equal(C, D)) { flint_printf("oops\n"); flint_abort(); } } flint_printf("sign %d dim %3wd: " "| min %.3f v %0.3f " "| avr %.3f v %0.3f " "| max %.3f v %0.3f |\n", sign, dim, 1000000.0*min1/den, 1000000.0*min2/den, 1000000.0*total1/den/count, 1000000.0*total2/den/count, 1000000.0*max1/den, 1000000.0*max2/den); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mat/profile/p-mul_fft.c000066400000000000000000000040641461254215100207400ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz_mat.h" #include "fmpz.h" #include "ulong_extras.h" #include "test_helpers.h" int main(void) { slong i, j, reps; slong dim, sz; fmpz_mat_t A, B, C, D; fmpz_t t; timeit_t timer; slong time1, time2; reps = 1; for (dim = 6; dim > 0; dim--) { flint_printf("****** %wd x %wd *********\n", dim, dim); for (sz = 10000; sz < 100000; sz += 10000) { fmpz_mat_init(A, dim, dim); fmpz_mat_init(B, dim, dim); fmpz_mat_init(C, dim, dim); fmpz_mat_init(D, dim, dim); fmpz_init_set_ui(t, 1); flint_printf("sz = %wd\n", sz); fmpz_mul_2exp(t, t, FLINT_BITS*sz); fmpz_sub_ui(t, t, 1); for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) { fmpz_set(fmpz_mat_entry(A, i, j), t); fmpz_set(fmpz_mat_entry(B, i, j), t); } for (i = 0; i < reps; i++) { timeit_start(timer); fmpz_mat_mul_fft(C, A, B); timeit_stop(timer); time1 = timer->wall; timeit_start(timer); fmpz_mat_mul_classical(D, A, B); timeit_stop(timer); time2 = timer->wall; flint_printf("new: %wd, old: %wd, ratio: %f\n", time1, time2, (double)time2/(double)time1); FLINT_TEST(fmpz_mat_equal(C, D)); } fmpz_clear(t); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } } return 0; } flint-3.1.3/src/fmpz_mat/profile/p-mul_multi_mod.c000066400000000000000000000045701461254215100221540ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_mat.h" #include "profiler.h" int main(void) { slong dim, i, reps, total, mint, maxt, count, den; flint_bitcnt_t Abits, Bbits; timeit_t timer; FLINT_TEST_INIT(state); flint_set_num_threads(8); flint_printf("*** timings are nanoseconds per dim^3 ***\n"); for (dim = 50; dim <= 1000; dim += 5 + dim/8) { fmpz_mat_t A, B, C, D, E; fmpz_mat_init(A, dim, dim); fmpz_mat_init(B, dim, dim); fmpz_mat_init(C, dim, dim); fmpz_mat_init(D, dim, dim); fmpz_mat_init(E, dim, dim); reps = 1 + 2000000/dim/dim/dim; den = reps*dim*dim*dim; count = 0; total = 0; mint = 10000000000; maxt = 0; for (Abits = 1*FLINT_BITS; Abits < 7*FLINT_BITS; Abits += 40) for (Bbits = Abits; Bbits < 7*FLINT_BITS; Bbits += 40) { fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); timeit_start(timer); for (i = reps; i > 0; i--) fmpz_mat_mul_multi_mod(E, A, B); timeit_stop(timer); total += timer->wall; mint = FLINT_MIN(mint, timer->wall); maxt = FLINT_MAX(maxt, timer->wall); count++; if (dim < 150) { fmpz_mat_mul_classical(D, A, B); if (!fmpz_mat_equal(D, E)) { flint_printf("oops %wu %wu\n", Abits, Bbits); flint_abort(); } } } flint_printf("dim %3wd: | min %.3f | aver %.3f | max %.3f ns | %wd reps\n", dim, 1000000.0*mint/den, 1000000.0*total/den/count, 1000000.0*maxt/den, reps); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); fmpz_mat_clear(E); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mat/profile/p-mul_small.c000066400000000000000000000115371461254215100212740ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "profiler.h" int main(void) { slong m, k, n; slong dim, i, reps; slong new_total, new_mint, new_maxt; slong old_total, old_mint, old_maxt; double total_den, den; flint_bitcnt_t Abits, Bbits; timeit_t timer; FLINT_TEST_INIT(state); flint_set_num_threads(1); flint_printf("(m, k, n) *** timings for mul_small nanoseconds per m*k*n (mul in parentheses) ***\n"); for (m = 3; m < 10; m++) for (k = 3; k < 10; k++) for (n = 3; n < 10; n++) { fmpz_mat_t A, B, C, D; fmpz_mat_init(A, m, k); fmpz_mat_init(B, k, n); fmpz_mat_init(C, m, n); fmpz_mat_init(D, m, n); reps = 1 + 8000000/m/n/k; den = reps*m*n*k; total_den = 0; new_total = 0; new_mint = 10000000000; new_maxt = 0; old_total = 0; old_mint = 10000000000; old_maxt = 0; for (Abits = 14; Abits <= SMALL_FMPZ_BITCOUNT_MAX; Abits += 16) for (Bbits = Abits; Bbits <= SMALL_FMPZ_BITCOUNT_MAX; Bbits += 16) { fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); total_den += den; timeit_start(timer); for (i = reps; i > 0; i--) _fmpz_mat_mul_small(C, A, B); timeit_stop(timer); new_total += timer->wall; new_mint = FLINT_MIN(new_mint, timer->wall); new_maxt = FLINT_MAX(new_maxt, timer->wall); timeit_start(timer); for (i = reps; i > 0; i--) fmpz_mat_mul(D, A, B); timeit_stop(timer); old_total += timer->wall; old_mint = FLINT_MIN(old_mint, timer->wall); old_maxt = FLINT_MAX(old_maxt, timer->wall); } flint_printf("(%2wd,%2wd,%2wd): min %.3f ns (%.3f) max %.3f ns (%.3f) aver %.3f ns (%.3f) ratio %.3f\n", m, k, n, 1000000*new_mint/den, 1000000*old_mint/den, 1000000*new_maxt/den, 1000000*old_maxt/den, 1000000*new_total/total_den, 1000000*old_total/total_den, (double)new_total/old_total); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } flint_printf("*** timings for mul_small nanoseconds per dim^3 (mul in parentheses) ***\n"); for (dim = 5; dim <= 1100; dim += 2 + dim/4) { fmpz_mat_t A, B, C, D; fmpz_mat_init(A, dim, dim); fmpz_mat_init(B, dim, dim); fmpz_mat_init(C, dim, dim); fmpz_mat_init(D, dim, dim); reps = 1 + 5000000/dim/dim/dim; den = reps*dim*dim*dim; total_den = 0; new_total = 0; new_mint = 10000000000; new_maxt = 0; old_total = 0; old_mint = 10000000000; old_maxt = 0; for (Abits = 14; Abits <= SMALL_FMPZ_BITCOUNT_MAX; Abits += 8) for (Bbits = Abits; Bbits <= SMALL_FMPZ_BITCOUNT_MAX; Bbits += 8) { fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); total_den += den; timeit_start(timer); for (i = reps; i > 0; i--) _fmpz_mat_mul_small(C, A, B); timeit_stop(timer); new_total += timer->wall; new_mint = FLINT_MIN(new_mint, timer->wall); new_maxt = FLINT_MAX(new_maxt, timer->wall); timeit_start(timer); for (i = reps; i > 0; i--) fmpz_mat_mul(D, A, B); timeit_stop(timer); old_total += timer->wall; old_mint = FLINT_MIN(old_mint, timer->wall); old_maxt = FLINT_MAX(old_maxt, timer->wall); if (!fmpz_mat_equal(C, D)) { flint_printf("oops C != D %wu %wu\n", Abits, Bbits); flint_abort(); } } flint_printf("%4wd: min %.3f ns (%.3f) max %.3f ns (%.3f) aver %.3f ns (%.3f) ratio %.3f\n", dim, 1000000*new_mint/den, 1000000*old_mint/den, 1000000*new_maxt/den, 1000000*old_maxt/den, 1000000*new_total/total_den, 1000000*old_total/total_den, (double)new_total/old_total); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mat/profile/p-mul_small_v_mul_multi_mod.c000066400000000000000000000054711461254215100245470ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "profiler.h" int main(void) { slong dim, i, reps, den; slong min1, max1, total1, min2, max2, total2, count; flint_bitcnt_t Abits, Bbits; timeit_t timer; FLINT_TEST_INIT(state); flint_set_num_threads(1); flint_printf("*** timings are nanoseconds per dim^3 ***\n"); for (dim = 50; dim <= 5000; dim += 2 + dim/4) { fmpz_mat_t A, B, C, D; fmpz_mat_init(A, dim, dim); fmpz_mat_init(B, dim, dim); fmpz_mat_init(C, dim, dim); fmpz_mat_init(D, dim, dim); reps = 1 + 3000000/dim/dim/dim; den = reps*dim*dim*dim; count = 0; total1 = 0; min1 = 10000000000; max1 = 0; total2 = 0; min2 = 10000000000; max2 = 0; for (Abits = FLINT_BITS/2; Abits <= SMALL_FMPZ_BITCOUNT_MAX; Abits += FLINT_BITS) for (Bbits = Abits; Bbits <= SMALL_FMPZ_BITCOUNT_MAX; Bbits += 16) { if (FLINT_BIT_COUNT(dim) + Abits + Bbits <= SMALL_FMPZ_BITCOUNT_MAX) continue; fmpz_mat_randtest(A, state, Abits); fmpz_mat_randtest(B, state, Bbits); timeit_start(timer); for (i = reps; i > 0; i--) _fmpz_mat_mul_small(C, A, B); timeit_stop(timer); total1 += timer->wall; min1 = FLINT_MIN(min1, timer->wall); max1 = FLINT_MAX(max1, timer->wall); timeit_start(timer); for (i = reps; i > 0; i--) fmpz_mat_mul_multi_mod(D, A, B); timeit_stop(timer); total2 += timer->wall; min2 = FLINT_MIN(min2, timer->wall); max2 = FLINT_MAX(max2, timer->wall); count++; if (!fmpz_mat_equal(C, D)) { flint_printf("oops\n"); flint_abort(); } } flint_printf("dim %3wd: " "| min %.3f v %0.3f " "| avr %.3f v %0.3f " "| max %.3f v %0.3f |\n", dim, 1000000.0*min1/den, 1000000.0*min2/den, 1000000.0*total1/den/count, 1000000.0*total2/den/count, 1000000.0*max1/den, 1000000.0*max2/den); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mat/profile/p-sqr.c000066400000000000000000000041311461254215100201040ustar00rootroot00000000000000/* Copyright (C) 2007,2015 Anubhav Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "fmpz_mat.h" #include "fmpz.h" #include "ulong_extras.h" typedef struct { slong m; slong n; slong k; int algorithm; slong bits; } mat_mul_t; void sample(void * arg, ulong count) { mat_mul_t * params = (mat_mul_t *) arg; slong i, n = params->n, m = params->m ; slong bits = params->bits; int algorithm = params->algorithm; fmpz_mat_t A, B, C; FLINT_TEST_INIT(state); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(C, m, n); fmpz_mat_randbits(A, state, bits); fmpz_mat_set(B, A); prof_start(); if (algorithm == 0) for (i = 0; i < count; i++) fmpz_mat_mul(C, A, B); else if (algorithm == 1) for (i = 0; i < count; i++) fmpz_mat_sqr(C, A); prof_stop(); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); flint_randclear(state); } int main(void) { double min_default, min_classical, max; mat_mul_t params; slong bits, dim; for (bits = 32; bits <= 65536; bits *= 2) { params.bits = bits; flint_printf("bits = %wd :\n", params.bits); for (dim = 1; dim <= 200; dim = FLINT_MAX(dim * 1.5, dim + 1)) { params.n = dim; params.m = dim; params.algorithm = 0; prof_repeat(&min_default, &max, sample, ¶ms); params.algorithm = 1; prof_repeat(&min_classical, &max, sample, ¶ms); flint_printf("dim = %wd fmpz_mat_mul : %.2f fmpz_mat_sqr : %.2f ", dim, min_default, min_classical); flint_printf("Ratio : %0.2f \n",min_default/min_classical); } } return 0; } flint-3.1.3/src/fmpz_mat/randajtai.c000066400000000000000000000027021461254215100173410ustar00rootroot00000000000000/* Copyright (C) 2005-2009 Damien Stehle Copyright (C) 2007 David Cade Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_randajtai(fmpz_mat_t mat, flint_rand_t state, double alpha) { const slong c = mat->c, r = mat->r, d = r; slong i, j; fmpz_t tmp; if (c != r) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_ajtai): Non-square matrix.\n"); } fmpz_init(tmp); for (i = 0; i < d; i++) { flint_bitcnt_t bits = (flint_bitcnt_t) pow((double) (2 * d - i), alpha); fmpz_one(tmp); fmpz_mul_2exp(tmp, tmp, bits); fmpz_sub_ui(tmp, tmp, 1); fmpz_randm(mat->rows[i] + i, state, tmp); fmpz_add_ui(mat->rows[i] + i, mat->rows[i] + i, 2); fmpz_fdiv_q_2exp(mat->rows[i] + i, mat->rows[i] + i, 1); for (j = i + 1; j < d; j++) { fmpz_randm(mat->rows[j] + i, state, tmp); if (n_randint(state, 2)) fmpz_neg(mat->rows[j] + i, mat->rows[j] + i); fmpz_zero(mat->rows[i] + j); } } fmpz_clear(tmp); } flint-3.1.3/src/fmpz_mat/randbits.c000066400000000000000000000012451461254215100172130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_randbits(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong r, c, i, j; r = mat->r; c = mat->c; for (i = 0; i < r; i++) for (j = 0; j < c; j++) fmpz_randbits(mat->rows[i] + j, state, bits); } flint-3.1.3/src/fmpz_mat/randdet.c000066400000000000000000000040461461254215100170300ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_randdet(fmpz_mat_t mat, flint_rand_t state, const fmpz_t det) { slong i, j, k, n; int parity; fmpz * diag; fmpz_factor_t factor; n = mat->r; if (n != mat->c) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_randdet). Non-square matrix.\n"); } if (n < 1) return; /* Start with the zero matrix */ fmpz_mat_zero(mat); if (*det == WORD(0)) return; fmpz_factor_init(factor); fmpz_factor(factor, det); diag = _fmpz_vec_init(n); for (i = 0; i < n; i++) fmpz_one(&diag[i]); /* Form diagonal entries that multiply to the determinant */ for (i = 0; i < factor->num; i++) { for (j = 0; j < factor->exp[i]; j++) { k = n_randint(state, n); fmpz_mul(&diag[k], &diag[k], &factor->p[i]); } } /* Reverse signs an even number of times */ for (i = 0; i < 2*n; i++) { k = n_randint(state, n); fmpz_neg(&diag[k], &diag[k]); } if (factor->sign == -1) fmpz_neg(&diag[0], &diag[0]); parity = fmpz_mat_randpermdiag(mat, state, diag, n); /* Need another reversal if the permutation was odd */ if (parity) { for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (!fmpz_is_zero(mat->rows[i] + j)) { fmpz_neg(mat->rows[i] + j, mat->rows[i] + j); goto end; } } } } end: _fmpz_vec_clear(diag, n); fmpz_factor_clear(factor); } flint-3.1.3/src/fmpz_mat/randintrel.c000066400000000000000000000020161461254215100175440ustar00rootroot00000000000000/* Copyright (C) 2005-2009 Damien Stehle Copyright (C) 2007 David Cade Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_randintrel(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { const slong c = mat->c, r = mat->r; slong i, j; if (c != r + 1) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_randintrel). c != r + 1.\n"); } for (i = 0; i < r; i++) { fmpz_randbits(mat->rows[i], state, bits); for (j = 1; j <= i; j++) fmpz_zero(mat->rows[i] + j); fmpz_one(mat->rows[i] + i + 1); for (j = i + 2; j < c; j++) fmpz_zero(mat->rows[i] + j); } } flint-3.1.3/src/fmpz_mat/randntrulike.c000066400000000000000000000033161461254215100201100ustar00rootroot00000000000000/* Copyright (C) 2005-2009 Damien Stehle Copyright (C) 2007 David Cade Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_randntrulike(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q) { const slong c = mat->c, r = mat->r, d = r / 2; slong i, j, k; fmpz *h; if ((c != r) || (c != 2 * d)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_randntrulike). Ill-formed matrix.\n"); } h = _fmpz_vec_init(d); for (i = 0; i < d; i++) fmpz_randbits(h + i, state, bits); for (i = 0; i < d; i++) { for (j = 0; j < i; j++) fmpz_zero(mat->rows[i] + j); fmpz_one(mat->rows[i] + i); for (j = i + 1; j < d; j++) fmpz_zero(mat->rows[i] + j); } for (i = d; i < r; i++) for (j = 0; j < d; j++) fmpz_zero(mat->rows[i] + j); for (i = d; i < r; i++) { for (j = d; j < i; j++) fmpz_zero(mat->rows[i] + j); fmpz_set_ui(mat->rows[i] + i, q); for (j = i + 1; j < c; j++) fmpz_zero(mat->rows[i] + j); } for (i = 0; i < d; i++) { for (j = d; j < c; j++) { k = j + i; while (k >= d) k -= d; fmpz_set(mat->rows[i] + j, h + k); } } _fmpz_vec_clear(h, d); } flint-3.1.3/src/fmpz_mat/randntrulike2.c000066400000000000000000000033201461254215100201650ustar00rootroot00000000000000/* Copyright (C) 2005-2009 Damien Stehle Copyright (C) 2007 David Cade Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_randntrulike2(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q) { const slong c = mat->c, r = mat->r, d = r / 2; slong i, j, k; fmpz *h; if ((c != r) || (c != 2 * d)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_randntrulike2). Ill-formed matrix.\n"); } h = _fmpz_vec_init(d); for (i = 0; i < d; i++) fmpz_randbits(h + i, state, bits); for (i = 0; i < d; i++) { for (j = 0; j < i; j++) fmpz_zero(mat->rows[i] + j); fmpz_set_ui(mat->rows[i] + i, q); for (j = i + 1; j < d; j++) fmpz_zero(mat->rows[i] + j); } for (i = 0; i < d; i++) for (j = d; j < c; j++) fmpz_zero(mat->rows[i] + j); for (i = d; i < c; i++) { for (j = d; j < i; j++) fmpz_zero(mat->rows[i] + j); fmpz_one(mat->rows[i] + i); for (j = i + 1; j < c; j++) fmpz_zero(mat->rows[i] + j); } for (i = d; i < r; i++) { for (j = 0; j < d; j++) { k = j + i; while (k >= d) k -= d; fmpz_set(mat->rows[i] + j, h + k); } } _fmpz_vec_clear(h, d); } flint-3.1.3/src/fmpz_mat/randops.c000066400000000000000000000031551461254215100170550ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_randops(fmpz_mat_t mat, flint_rand_t state, slong count) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; if (mat->r == 0 || mat->c == 0) return; for (c = 0; c < count; c++) { if (n_randint(state, 2)) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) fmpz_add(&mat->rows[j][k], &mat->rows[j][k], &mat->rows[i][k]); else for (k = 0; k < n; k++) fmpz_sub(&mat->rows[j][k], &mat->rows[j][k], &mat->rows[i][k]); } else { if ((i = n_randint(state, n)) == (j = n_randint(state, n))) continue; if (n_randint(state, 2)) for (k = 0; k < m; k++) fmpz_add(&mat->rows[k][j], &mat->rows[k][j], &mat->rows[k][i]); else for (k = 0; k < m; k++) fmpz_sub(&mat->rows[k][j], &mat->rows[k][j], &mat->rows[k][i]); } } } flint-3.1.3/src/fmpz_mat/randpermdiag.c000066400000000000000000000017241461254215100200440ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_randpermdiag(fmpz_mat_t mat, flint_rand_t state, const fmpz * diag, slong n) { int parity; slong i; slong * rows; slong * cols; rows = _perm_init(mat->r); cols = _perm_init(mat->c); parity = _perm_randtest(rows, mat->r, state); parity ^= _perm_randtest(cols, mat->c, state); fmpz_mat_zero(mat); for (i = 0; i < n; i++) fmpz_set(fmpz_mat_entry(mat, rows[i], cols[i]), diag + i); _perm_clear(rows); _perm_clear(cols); return parity; } flint-3.1.3/src/fmpz_mat/randrank.c000066400000000000000000000016641461254215100172120ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_randrank(fmpz_mat_t mat, flint_rand_t state, slong rank, flint_bitcnt_t bits) { slong i; fmpz * diag; if (rank < 0 || rank > mat->r || rank > mat->c) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_randrank). Impossible rank.\n"); } diag = _fmpz_vec_init(rank); for (i = 0; i < rank; i++) fmpz_randtest_not_zero(&diag[i], state, bits); fmpz_mat_randpermdiag(mat, state, diag, rank); _fmpz_vec_clear(diag, rank); } flint-3.1.3/src/fmpz_mat/randsimdioph.c000066400000000000000000000023301461254215100200620ustar00rootroot00000000000000/* Copyright (C) 2005-2009 Damien Stehle Copyright (C) 2007 David Cade Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_randsimdioph(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, flint_bitcnt_t bits2) { const slong c = mat->c, r = mat->r; slong i, j; if (c != r) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_randsimdioph). Ill-formed matrix.\n"); } fmpz_one(mat->rows[0]); fmpz_mul_2exp(mat->rows[0], mat->rows[0], bits2); for (j = 1; j < c; j++) fmpz_randbits(mat->rows[0] + j, state, bits); for (i = 1; i < r; i++) { for (j = 0; j < i; j++) fmpz_zero(mat->rows[i] + j); fmpz_one(mat->rows[i] + i); fmpz_mul_2exp(mat->rows[i] + i, mat->rows[i] + i, bits); for (j = i + 1; j < c; j++) fmpz_zero(mat->rows[i] + j); } } flint-3.1.3/src/fmpz_mat/randtest.c000066400000000000000000000012451461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_randtest(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong r, c, i, j; r = mat->r; c = mat->c; for (i = 0; i < r; i++) for (j = 0; j < c; j++) fmpz_randtest(mat->rows[i] + j, state, bits); } flint-3.1.3/src/fmpz_mat/randtest_unsigned.c000066400000000000000000000012671461254215100211310ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_randtest_unsigned(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { slong r, c, i, j; r = mat->r; c = mat->c; for (i = 0; i < r; i++) for (j = 0; j < c; j++) fmpz_randtest_unsigned(mat->rows[i] + j, state, bits); } flint-3.1.3/src/fmpz_mat/rank.c000066400000000000000000000016721461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" slong fmpz_mat_rank(const fmpz_mat_t A) { fmpz_mat_t tmp; fmpz_t den; slong rank; if (fmpz_mat_is_empty(A)) return 0; fmpz_mat_init_set(tmp, A); fmpz_init(den); if (FLINT_ABS(fmpz_mat_max_bits(tmp)) <= (FLINT_BITS - 4)/2) rank = fmpz_mat_rank_small_inplace(tmp); else if (FLINT_MIN(tmp->r, tmp->c) < 25) rank = fmpz_mat_fflu(tmp, den, NULL, tmp, 0); else rank = fmpz_mat_rref(tmp, den, tmp); fmpz_mat_clear(tmp); fmpz_clear(den); return rank; } flint-3.1.3/src/fmpz_mat/rank_small_inplace.c000066400000000000000000000052641461254215100212300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" #define E(j,k) fmpz_mat_entry(B,j,k) slong _fmpz_mat_rank_overflow(fmpz_mat_t B, slong pivot_row, slong pivot_col) { fmpz_t den; fmpz_mat_t window; slong rank, m = B->r, n = B->c; fmpz_init(den); fmpz_mat_window_init(window, B, pivot_row, pivot_col, m, n); if (FLINT_MIN(m - pivot_row, n - pivot_col) < 25) rank = fmpz_mat_fflu(window, den, NULL, window, 0); else rank = fmpz_mat_rref(window, den, window); fmpz_mat_window_clear(window); fmpz_clear(den); return rank; } slong fmpz_mat_rank_small_inplace(fmpz_mat_t B) { slong m, n, j, k, rank, q, r = -1, pivot_row, pivot_col; /* mask to check that a*b + c will be small */ const ulong mask = ~((UWORD(1)<<((FLINT_BITS - 4)/2)) - 1); ulong largest; if (fmpz_mat_is_empty(B)) { return 0; } m = B->r; n = B->c; rank = pivot_row = pivot_col = 0; if (pivot_row < m && pivot_col < n) r = fmpz_mat_find_pivot_smallest(B, pivot_row, m, pivot_col); while (pivot_row < m && pivot_col < n) { if (r == -1) { pivot_col++; if (pivot_col == n) break; r = fmpz_mat_find_pivot_smallest(B, pivot_row, m, pivot_col); continue; } else if (r != pivot_row) { fmpz_mat_swap_rows(B, NULL, pivot_row, r); } largest = 0; for (j = pivot_row + 1; j < m; j++) { if (*E(j, pivot_col) != 0) { q = (*E(j, pivot_col))/(*E(pivot_row, pivot_col)); for (k = pivot_col; k < n; k++) { (*E(j, k)) -= q*(*E(pivot_row, k)); largest |= FLINT_ABS(*E(j, k)); } } } if ((largest & mask) != 0) /* rest may overflow, call safe code */ return rank + _fmpz_mat_rank_overflow(B, pivot_row, pivot_col); r = fmpz_mat_find_pivot_smallest(B, pivot_row + 1, m, pivot_col); if (r == -1) { pivot_row++; pivot_col++; rank++; if (pivot_row < m && pivot_col < n) r = fmpz_mat_find_pivot_smallest(B, pivot_row, m, pivot_col); } } return rank; } flint-3.1.3/src/fmpz_mat/rref.c000066400000000000000000000013541461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2011-2012 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" slong fmpz_mat_rref(fmpz_mat_t R, fmpz_t den, const fmpz_mat_t A) { if (FLINT_MIN(A->c, A->r) <= 20) return fmpz_mat_rref_fflu(R, den, A); else if (A->r <= 105 && A->c >= 1.4 * A->r) return fmpz_mat_rref_fflu(R, den, A); else return fmpz_mat_rref_mul(R, den, A); } flint-3.1.3/src/fmpz_mat/rref_fflu.c000066400000000000000000000044741461254215100173660ustar00rootroot00000000000000/* Copyright (C) 2011-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" slong fmpz_mat_rref_fflu(fmpz_mat_t R, fmpz_t den, const fmpz_mat_t A) { slong i, j, k, m, n, rank; slong *pivots, *nonpivots; rank = fmpz_mat_fflu(R, den, NULL, A, 0); m = fmpz_mat_nrows(R); n = fmpz_mat_ncols(R); /* clear bottom */ for (i = rank; i < m; i++) for (j = 0; j < n; j++) fmpz_zero(fmpz_mat_entry(R, i, j)); /* Convert row echelon form to reduced row echelon form */ if (rank > 1) { fmpz_t tmp; fmpz_init(tmp); pivots = flint_malloc(sizeof(slong) * n); nonpivots = pivots + rank; for (i = j = k = 0; i < rank; i++) { while (fmpz_is_zero(fmpz_mat_entry(R, i, j))) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (k = 0; k < n - rank; k++) { for (i = rank - 2; i >= 0; i--) { fmpz_mul(tmp, den, fmpz_mat_entry(R, i, nonpivots[k])); for (j = i + 1; j < rank; j++) { fmpz_submul(tmp, fmpz_mat_entry(R, i, pivots[j]), fmpz_mat_entry(R, j, nonpivots[k])); } fmpz_divexact(fmpz_mat_entry(R, i, nonpivots[k]), tmp, fmpz_mat_entry(R, i, pivots[i])); } } /* clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { if (i == j) fmpz_set(fmpz_mat_entry(R, j, pivots[i]), den); else fmpz_zero(fmpz_mat_entry(R, j, pivots[i])); } } flint_free(pivots); fmpz_clear(tmp); } return rank; } flint-3.1.3/src/fmpz_mat/rref_mul.c000066400000000000000000000103211461254215100172130ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "perm.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" slong fmpz_mat_rref_mul(fmpz_mat_t R, fmpz_t den, const fmpz_mat_t A) { nmod_mat_t Amod; mp_limb_t p; slong i, j, m, n, rank, * pivs, * P; fmpz_mat_t B, C, D, E, E2, F, FD; m = fmpz_mat_nrows(A); n = fmpz_mat_ncols(A); pivs = (slong *) flint_malloc(n * sizeof(slong)); P = _perm_init(m); /* use 16 bit primes to ensure it is unlikely we hit a bad one and so that the modular computations are not too long */ p = 1 << 16; while (1) { p = n_nextprime(p, 1); nmod_mat_init(Amod, m, n, p); fmpz_mat_get_nmod_mat(Amod, A); rank = _nmod_mat_rref(Amod, pivs, P); nmod_mat_clear(Amod); /* stop early if the rank is the number of columns */ if (rank == n) { fmpz_mat_one(R); fmpz_one(den); flint_free(pivs); _perm_clear(P); return rank; } fmpz_mat_init(B, rank, rank); fmpz_mat_init(C, rank, n - rank); /* set B to be the pivot columns and rows and C to be the non-pivot columns in the pivot rows */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) fmpz_set(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, P[i], pivs[j])); for (j = 0; j < n - rank; j++) fmpz_set(fmpz_mat_entry(C, i, j), fmpz_mat_entry(A, P[i], pivs[rank + j])); } /* solve B*E2 = den*C */ fmpz_mat_init(E2, rank, n - rank); if (!fmpz_mat_solve(E2, den, B, C)) { flint_throw(FLINT_ERROR, "(fmpz_mat_rref_mul): " "Singular input matrix for solve.\n"); } fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_init(E, rank, n); /* move columns of E2 and identity matrix into E so that it should be in rref */ for (i = 0; i < rank; i++) { fmpz_set(fmpz_mat_entry(E, i, pivs[i]), den); for (j = 0; j < n - rank; j++) fmpz_set(fmpz_mat_entry(E, i, pivs[rank + j]), fmpz_mat_entry(E2, i, j)); } fmpz_mat_clear(E2); if (!fmpz_mat_is_in_rref_with_rank(E, den, rank)) { fmpz_mat_clear(E); continue; } /* set D to be the nullspace basis matrix for E */ fmpz_mat_init(D, n, n - rank); for (j = 0; j < n - rank; j++) { fmpz_set(fmpz_mat_entry(D, pivs[rank + j], j), den); for (i = 0; i < rank; i++) fmpz_neg(fmpz_mat_entry(D, pivs[i], j), fmpz_mat_entry(E, i, pivs[rank + j])); } fmpz_mat_init(F, m - rank, n); for (i = 0; i < m - rank; i++) for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(F, i, j), fmpz_mat_entry(A, P[rank + i], j)); fmpz_mat_init(FD, m - rank, n - rank); fmpz_mat_mul(FD, F, D); fmpz_mat_clear(F); fmpz_mat_clear(D); /* if FD = 0 we have computed the rref right so stop, otherwise try a different p in the next iteration */ if (fmpz_mat_is_zero(FD)) break; fmpz_mat_clear(E); fmpz_mat_clear(FD); } /* write the entries of E into R and zeroes at the bottom */ for (i = 0; i < rank; i++) for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(R, i, j), fmpz_mat_entry(E, i, j)); for (i = rank; i < m; i++) for (j = 0; j < n; j++) fmpz_zero(fmpz_mat_entry(R, i, j)); fmpz_mat_clear(E); fmpz_mat_clear(FD); flint_free(pivs); _perm_clear(P); return rank; } flint-3.1.3/src/fmpz_mat/scalar.c000066400000000000000000000117121461254215100166520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_scalar_addmul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_addmul(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_addmul_nmod_mat_fmpz(fmpz_mat_t B, const nmod_mat_t A, const fmpz_t c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_addmul_ui(fmpz_mat_entry(B,i,j), c, nmod_mat_entry(A,i,j)); } void fmpz_mat_scalar_addmul_nmod_mat_ui(fmpz_mat_t B, const nmod_mat_t A, ulong c) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, c); fmpz_mat_scalar_addmul_nmod_mat_fmpz(B, A, t); fmpz_clear(t); } void fmpz_mat_scalar_addmul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) { if (c > 0) fmpz_mat_scalar_addmul_ui(B, A, c); else fmpz_mat_scalar_submul_ui(B, A, -c); } void fmpz_mat_scalar_addmul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_addmul_ui(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_divexact_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_divexact(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_divexact_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_divexact_si(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_divexact_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_divexact_ui(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_mod_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t m) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_mod(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, i, j), m); } void fmpz_mat_scalar_mul_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp) { slong i, j; if (exp == 0) { fmpz_mat_set(B, A); return; } else if (exp == 1) { fmpz_mat_add(B, A, A); return; } for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_mul_2exp(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, i, j), exp); } void fmpz_mat_scalar_mul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_mul(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_mul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_mul_si(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_mul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_mul_ui(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_smod(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t P) { slong i; for (i = 0; i < A->r; i++) _fmpz_vec_scalar_smod_fmpz(B->rows[i], A->rows[i], A->c, P); } void fmpz_mat_scalar_submul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_submul(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_submul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c) { if (c > 0) fmpz_mat_scalar_submul_ui(B, A, c); else fmpz_mat_scalar_addmul_ui(B, A, -c); } void fmpz_mat_scalar_submul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_submul_ui(fmpz_mat_entry(B,i,j), fmpz_mat_entry(A,i,j), c); } void fmpz_mat_scalar_tdiv_q_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp) { slong i, j; if (exp == 0) { fmpz_mat_set(B, A); return; } for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_tdiv_q_2exp(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, i, j), exp); } flint-3.1.3/src/fmpz_mat/set.c000066400000000000000000000024261461254215100162020ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_set(fmpz_mat_t mat1, const fmpz_mat_t mat2) { if (mat1 != mat2) { slong i; if (mat2->r && mat2->c) for (i = 0; i < mat2->r; i++) _fmpz_vec_set(mat1->rows[i], mat2->rows[i], mat2->c); } } void fmpz_mat_set_nmod_mat(fmpz_mat_t A, const nmod_mat_t Amod) { slong i, j; for (i = 0; i < Amod->r; i++) for (j = 0; j < Amod->c; j++) fmpz_set_ui_smod(fmpz_mat_entry(A, i, j), nmod_mat_entry(Amod, i, j), Amod->mod.n); } void fmpz_mat_set_nmod_mat_unsigned(fmpz_mat_t A, const nmod_mat_t Amod) { slong i, j; for (i = 0; i < Amod->r; i++) for (j = 0; j < Amod->c; j++) fmpz_set_ui(fmpz_mat_entry(A, i, j), nmod_mat_entry(Amod, i, j)); } flint-3.1.3/src/fmpz_mat/similarity.c000066400000000000000000000017741461254215100176020ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_similarity(fmpz_mat_t A, slong r, fmpz_t d) { slong n = A->r, i, j; for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) fmpz_addmul(fmpz_mat_entry(A, i, j), fmpz_mat_entry(A, i, r), d); for (j = r + 1; j < n; j++) fmpz_addmul(fmpz_mat_entry(A, i, j), fmpz_mat_entry(A, i, r), d); } for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) fmpz_submul(fmpz_mat_entry(A, r, i), fmpz_mat_entry(A, j, i), d); for (j = r + 1; j < n; j++) fmpz_submul(fmpz_mat_entry(A, r, i), fmpz_mat_entry(A, j, i), d); } } flint-3.1.3/src/fmpz_mat/snf.c000066400000000000000000000022701461254215100161720ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_snf(fmpz_mat_t S, const fmpz_mat_t A) { fmpz_t det; slong m = A->r, n = A->c, b = fmpz_mat_max_bits(A), cutoff = 9; if (b <= 2) cutoff = 15; else if (b <= 4) cutoff = 13; else if (b <= 8) cutoff = 13; else if (b <= 16) cutoff = 11; else if (b <= 32) cutoff = 11; else if (b <= 64) cutoff = 10; if (FLINT_MAX(m, n) < cutoff || m != n) fmpz_mat_snf_kannan_bachem(S, A); else { fmpz_init(det); fmpz_mat_det(det, A); if (!fmpz_is_zero(det)) { fmpz_abs(det, det); fmpz_mat_snf_iliopoulos(S, A, det); } else { fmpz_mat_snf_kannan_bachem(S, A); } fmpz_clear(det); } } flint-3.1.3/src/fmpz_mat/snf_diagonal.c000066400000000000000000000021751461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" /* sets a to gcd(a,b) and b to lcm(a,b) using temporary fmpz_t t */ static void _gcdlcm(fmpz_t t, fmpz_t a, fmpz_t b) { if (fmpz_equal(a, b)) return; fmpz_gcd(t, a, b); fmpz_divexact(b, b, t); fmpz_mul(b, b, a); fmpz_set(a, t); } void fmpz_mat_snf_diagonal(fmpz_mat_t S, const fmpz_mat_t A) { fmpz_t t; slong i, j, n = FLINT_MIN(A->r, A->c); fmpz_init(t); fmpz_mat_set(S, A); for (i = 0; i < n; i++) fmpz_abs(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i)); for (j = n - 1; j >= 0; j--) { for (i = 0; i < j; i++) { _gcdlcm(t, fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i + 1, i + 1)); } } fmpz_clear(t); } flint-3.1.3/src/fmpz_mat/snf_iliopoulos.c000066400000000000000000000151201461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" static void _eliminate_col(fmpz_mat_t S, slong i, const fmpz_t mod) { slong j, k, m, n; fmpz * t; fmpz_t b, g, u, v, r1g, r2g; m = S->r; n = S->c; if (i == m - 1) { fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); return; } fmpz_init(g); fmpz_init(u); fmpz_init(b); fmpz_init(r1g); fmpz_init(r2g); if (!fmpz_is_zero(fmpz_mat_entry(S, i, i))) { fmpz_init(v); fmpz_xgcd(g, u, v, fmpz_mat_entry(S, i + 1, i), fmpz_mat_entry(S, i, i)); fmpz_divexact(r1g, fmpz_mat_entry(S, i + 1, i), g); fmpz_divexact(r2g, fmpz_mat_entry(S, i, i), g); for (j = i; j < n; j++) { fmpz_mul(b, u, fmpz_mat_entry(S, i + 1, j)); fmpz_addmul(b, v, fmpz_mat_entry(S, i, j)); fmpz_mul(fmpz_mat_entry(S, i, j), r1g, fmpz_mat_entry(S, i, j)); fmpz_submul(fmpz_mat_entry(S, i, j), r2g, fmpz_mat_entry(S, i + 1, j)); fmpz_set(fmpz_mat_entry(S, i + 1, j), b); } fmpz_clear(v); } /* compute extended gcd of entries in column i */ t = _fmpz_vec_init(m - i - 1); fmpz_set(g, fmpz_mat_entry(S, i + 1, i)); fmpz_one(t); for (j = 2; j < m - i; j++) { fmpz_xgcd(g, u, t + j - 1, g, fmpz_mat_entry(S, i + j, i)); for (k = 0; k < j - 1; k++) fmpz_mul(t + k, t + k, u); } /* set row i to have gcd in col i */ for (k = i + 1; k < m; k++) { fmpz_mod(t + k - i - 1, t + k - i - 1, mod); for (j = i; j < n; j++) fmpz_addmul(fmpz_mat_entry(S, i, j), t + k - i - 1, fmpz_mat_entry(S, k, j)); } _fmpz_vec_clear(t, m - i - 1); /* reduce each row k with row i */ if (!fmpz_is_zero(g)) /* if g = 0 then don't need to reduce */ { for (k = i + 1; k < m; k++) { fmpz_divexact(r1g, fmpz_mat_entry(S, k, i), g); fmpz_neg(r1g, r1g); for (j = i; j < n; j++) fmpz_addmul(fmpz_mat_entry(S, k, j), r1g, fmpz_mat_entry(S, i, j)); } for (k = i + 1; k < m; k++) fmpz_mod(fmpz_mat_entry(S, k, i), fmpz_mat_entry(S, k, i), mod); } for (j = i; j < m; j++) for (k = i + 1; k < n; k++) fmpz_fdiv_r(fmpz_mat_entry(S, j, k), fmpz_mat_entry(S, j, k), mod); fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); fmpz_clear(b); fmpz_clear(g); fmpz_clear(u); fmpz_clear(r1g); fmpz_clear(r2g); } static void _eliminate_row(fmpz_mat_t S, slong i, const fmpz_t mod) { slong j, k, m, n; fmpz * t; fmpz_t b, g, u, v, r1g, r2g, halfmod; m = S->r; n = S->c; if (i == n - 1) { fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); return; } fmpz_init(g); fmpz_init(u); fmpz_init(b); fmpz_init(r1g); fmpz_init(r2g); fmpz_init(halfmod); fmpz_fdiv_q_2exp(halfmod, mod, 1); if (!fmpz_is_zero(fmpz_mat_entry(S, i, i))) { fmpz_init(v); fmpz_xgcd(g, u, v, fmpz_mat_entry(S, i, i + 1), fmpz_mat_entry(S, i, i)); fmpz_divexact(r1g, fmpz_mat_entry(S, i, i + 1), g); fmpz_divexact(r2g, fmpz_mat_entry(S, i, i), g); for (j = i; j < m; j++) { fmpz_mul(b, u, fmpz_mat_entry(S, j, i + 1)); fmpz_addmul(b, v, fmpz_mat_entry(S, j, i)); fmpz_mul(fmpz_mat_entry(S, j, i), r1g, fmpz_mat_entry(S, j, i)); fmpz_submul(fmpz_mat_entry(S, j, i), r2g, fmpz_mat_entry(S, j, i + 1)); fmpz_set(fmpz_mat_entry(S, j, i + 1), b); } fmpz_clear(v); } /* compute extended gcd of entries in row i */ t = _fmpz_vec_init(n - i - 1); fmpz_set(g, fmpz_mat_entry(S, i, i + 1)); fmpz_one(t); for (j = 2; j < n - i; j++) { fmpz_xgcd(g, u, t + j - 1, g, fmpz_mat_entry(S, i, i + j)); for (k = 0; k < j - 1; k++) fmpz_mul(t + k, t + k, u); } /* reduce col i to have gcd in row i */ for (k = i + 1; k < n; k++) { fmpz_mod(t + k - i - 1, t + k - i - 1, mod); for (j = i; j < m; j++) fmpz_addmul(fmpz_mat_entry(S, j, i), t + k - i - 1, fmpz_mat_entry(S, j, k)); } _fmpz_vec_clear(t, n - i - 1); /* reduce each col k with col i */ if (!fmpz_is_zero(g)) /* if g = 0 then don't need to reduce */ { for (k = i + 1; k < n; k++) { fmpz_divexact(r1g, fmpz_mat_entry(S, i, k), g); fmpz_neg(r1g, r1g); for (j = i; j < m; j++) fmpz_addmul(fmpz_mat_entry(S, j, k), r1g, fmpz_mat_entry(S, j, i)); } } for (j = i + 1; j < m; j++) for (k = i; k < n; k++) fmpz_fdiv_r(fmpz_mat_entry(S, j, k), fmpz_mat_entry(S, j, k), mod); fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); fmpz_clear(b); fmpz_clear(g); fmpz_clear(u); fmpz_clear(r1g); fmpz_clear(r2g); fmpz_clear(halfmod); } void fmpz_mat_snf_iliopoulos(fmpz_mat_t S, const fmpz_mat_t A, const fmpz_t mod) { slong i, k, n; int done; n = FLINT_MIN(A->c, A->r); fmpz_mat_set(S, A); for (i = 0; i < A->r; i++) for (k = 0; k < A->c; k++) fmpz_mod(fmpz_mat_entry(S, i, k), fmpz_mat_entry(S, i, k), mod); for (k = 0; k != n; k++) { do { _eliminate_row(S, k, mod); _eliminate_col(S, k, mod); done = 1; if (fmpz_is_zero(fmpz_mat_entry(S, k, k))) { for (i = k + 1; i < A->c && done; i++) done = fmpz_is_zero(fmpz_mat_entry(S, k, i)); } else { for (i = k + 1; i < A->c && done; i++) done = fmpz_divisible(fmpz_mat_entry(S, k, i), fmpz_mat_entry(S, k, k)); } } while (!done); for (i = k + 1; i < A->c; i++) fmpz_zero(fmpz_mat_entry(S, k, i)); } fmpz_mat_snf_diagonal(S, S); } flint-3.1.3/src/fmpz_mat/snf_kannan_bachem.c000066400000000000000000000117101461254215100210160ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_snf_kannan_bachem(fmpz_mat_t S, const fmpz_mat_t A) { slong i, j, k, d, m, n; fmpz_t r1g, r2g, b, u, v, g; m = A->r; n = A->c; d = FLINT_MIN(m, n); fmpz_init(r1g); fmpz_init(r2g); fmpz_init(b); fmpz_init(u); fmpz_init(v); fmpz_init(g); fmpz_mat_set(S, A); for (k = 0; k != d; k++) { int col_done; do { /* clear column */ for (i = k + 1; i != m; i++) { /* reduce row i - 1 with row i */ if (fmpz_is_zero(fmpz_mat_entry(S, i - 1, k))) continue; if (fmpz_cmpabs(fmpz_mat_entry(S, i, k), fmpz_mat_entry(S, i - 1, k)) == 0) { if (fmpz_equal(fmpz_mat_entry(S, i, k), fmpz_mat_entry(S, i - 1, k))) { for (j = k; j != n; j++) fmpz_sub(fmpz_mat_entry(S, i - 1, j), fmpz_mat_entry(S, i - 1, j), fmpz_mat_entry(S, i, j)); } else { for (j = k; j != n; j++) fmpz_add(fmpz_mat_entry(S, i - 1, j), fmpz_mat_entry(S, i - 1, j), fmpz_mat_entry(S, i, j)); } continue; } fmpz_xgcd(g, u, v, fmpz_mat_entry(S, i, k), fmpz_mat_entry(S, i - 1, k)); fmpz_divexact(r2g, fmpz_mat_entry(S, i - 1, k), g); fmpz_divexact(r1g, fmpz_mat_entry(S, i, k), g); for (j = k; j != n; j++) { fmpz_mul(b, u, fmpz_mat_entry(S, i, j)); fmpz_addmul(b, v, fmpz_mat_entry(S, i - 1, j)); fmpz_mul(fmpz_mat_entry(S, i - 1, j), r1g, fmpz_mat_entry(S, i - 1, j)); fmpz_submul(fmpz_mat_entry(S, i - 1, j), r2g, fmpz_mat_entry(S, i, j)); fmpz_set(fmpz_mat_entry(S, i, j), b); } } fmpz_mat_swap_rows(S, NULL, m - 1, k); /* clear row */ for (j = k + 1; j != n; j++) { /* reduce col j with col k */ if (fmpz_is_zero(fmpz_mat_entry(S, k, j))) continue; if (fmpz_cmpabs(fmpz_mat_entry(S, k, k), fmpz_mat_entry(S, k, j)) == 0) { if (fmpz_equal(fmpz_mat_entry(S, k, k), fmpz_mat_entry(S, k, j))) { for (i = k; i != m; i++) fmpz_sub(fmpz_mat_entry(S, i, j), fmpz_mat_entry(S, i, j), fmpz_mat_entry(S, i, k)); } else { for (i = k; i != m; i++) fmpz_add(fmpz_mat_entry(S, i, j), fmpz_mat_entry(S, i, j), fmpz_mat_entry(S, i, k)); } continue; } fmpz_xgcd(g, u, v, fmpz_mat_entry(S, k, k), fmpz_mat_entry(S, k, j)); fmpz_divexact(r2g, fmpz_mat_entry(S, k, j), g); fmpz_divexact(r1g, fmpz_mat_entry(S, k, k), g); for (i = k; i != m; i++) { fmpz_mul(b, u, fmpz_mat_entry(S, i, k)); fmpz_addmul(b, v, fmpz_mat_entry(S, i, j)); fmpz_mul(fmpz_mat_entry(S, i, j), r1g, fmpz_mat_entry(S, i, j)); fmpz_submul(fmpz_mat_entry(S, i, j), r2g, fmpz_mat_entry(S, i, k)); fmpz_set(fmpz_mat_entry(S, i, k), b); } } col_done = 1; for (i = 0; i != m; i++) col_done &= (i == k) || fmpz_is_zero(fmpz_mat_entry(S, i, k)); } while (!col_done); if (fmpz_sgn(fmpz_mat_entry(S, k, k)) < 0) fmpz_neg(fmpz_mat_entry(S, k, k), fmpz_mat_entry(S, k, k)); } fmpz_clear(r2g); fmpz_clear(r1g); fmpz_clear(b); fmpz_clear(u); fmpz_clear(v); fmpz_clear(g); fmpz_mat_snf_diagonal(S, S); } flint-3.1.3/src/fmpz_mat/solve.c000066400000000000000000000015411461254215100165340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "fmpz_mat.h" int fmpz_mat_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { if (fmpz_mat_nrows(A) <= 3) return fmpz_mat_solve_cramer(X, den, A, B); else if (fmpz_mat_nrows(A) <= 15) return fmpz_mat_solve_fflu(X, den, A, B); else if (fmpz_mat_ncols(B) == 1) return fmpz_mat_solve_dixon_den(X, den, A, B); else return fmpz_mat_solve_multi_mod_den(X, den, A, B); } flint-3.1.3/src/fmpz_mat/solve_bound.c000066400000000000000000000021331461254215100177210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_solve_bound(fmpz_t N, fmpz_t D, const fmpz_mat_t A, const fmpz_mat_t B) { slong i, j, m, n; fmpz_t t, u; m = B->r; n = B->c; fmpz_mat_det_bound(D, A); fmpz_init(t); fmpz_init(u); fmpz_zero(t); /* Largest column norm of B */ for (j = 0; j < n; j++) { fmpz_zero(u); for (i = 0; i < m; i++) fmpz_addmul(u, fmpz_mat_entry(B, i, j), fmpz_mat_entry(B, i, j)); if (fmpz_cmp(t, u) < 0) fmpz_set(t, u); } fmpz_sqrtrem(t, u, t); if (!fmpz_is_zero(u)) fmpz_add_ui(t, t, UWORD(1)); fmpz_mul(N, D, t); fmpz_clear(t); fmpz_clear(u); } flint-3.1.3/src/fmpz_mat/solve_cramer.c000066400000000000000000000102001461254215100200550ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #define AA(i,j) fmpz_mat_entry(A, i, j) #define BB(i,j) fmpz_mat_entry(B, i, j) #define XX(i,j) fmpz_mat_entry(X, i, j) int _fmpz_mat_solve_cramer_3x3(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { fmpz_t t15, t16, t17; int success; fmpz_init(t15); fmpz_init(t16); fmpz_init(t17); fmpz_fmms(t17, AA(1,0), AA(2,1), AA(1,1), AA(2,0)); fmpz_fmms(t16, AA(1,2), AA(2,0), AA(1,0), AA(2,2)); fmpz_fmms(t15, AA(1,1), AA(2,2), AA(1,2), AA(2,1)); fmpz_mul (den, t15, AA(0,0)); fmpz_addmul(den, t16, AA(0,1)); fmpz_addmul(den, t17, AA(0,2)); success = !fmpz_is_zero(den); if (success) { fmpz_t t12, t13, t14, x0, x1, x2; slong i, n = fmpz_mat_ncols(B); fmpz_init(t12); fmpz_init(t13); fmpz_init(t14); fmpz_init(x0); fmpz_init(x1); fmpz_init(x2); for (i = 0; i < n; i++) { fmpz_fmms(t14, AA(2,0), BB(1,i), AA(1,0), BB(2,i)); fmpz_fmms(t13, AA(2,1), BB(1,i), AA(1,1), BB(2,i)); fmpz_fmms(t12, AA(2,2), BB(1,i), AA(1,2), BB(2,i)); fmpz_mul (x0, t15, BB(0,i)); fmpz_addmul(x0, t13, AA(0,2)); fmpz_submul(x0, t12, AA(0,1)); fmpz_mul (x1, t16, BB(0,i)); fmpz_addmul(x1, t12, AA(0,0)); fmpz_submul(x1, t14, AA(0,2)); fmpz_mul (x2, t17, BB(0,i)); fmpz_addmul(x2, t14, AA(0,1)); fmpz_submul(x2, t13, AA(0,0)); fmpz_swap(XX(0,i), x0); fmpz_swap(XX(1,i), x1); fmpz_swap(XX(2,i), x2); } fmpz_clear(t12); fmpz_clear(t13); fmpz_clear(t14); fmpz_clear(x0); fmpz_clear(x1); fmpz_clear(x2); } fmpz_clear(t15); fmpz_clear(t16); fmpz_clear(t17); return success; } int fmpz_mat_solve_cramer(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { slong i, dim = fmpz_mat_nrows(A); if (dim == 0 || fmpz_mat_ncols(B) == 0) { fmpz_one(den); return 1; } else if (dim == 1) { fmpz_set(den, fmpz_mat_entry(A, 0, 0)); if (fmpz_is_zero(den)) return 0; if (!fmpz_mat_is_empty(B)) _fmpz_vec_set(X->rows[0], B->rows[0], fmpz_mat_ncols(B)); return 1; } else if (dim == 2) { fmpz_t t, u; fmpz_fmms(den, fmpz_mat_entry(A, 0, 0), fmpz_mat_entry(A, 1, 1), fmpz_mat_entry(A, 0, 1), fmpz_mat_entry(A, 1, 0)); if (fmpz_is_zero(den)) return 0; fmpz_init(t); fmpz_init(u); for (i = 0; i < fmpz_mat_ncols(B); i++) { fmpz_fmms(t, fmpz_mat_entry(A, 1, 1), fmpz_mat_entry(B, 0, i), fmpz_mat_entry(A, 0, 1), fmpz_mat_entry(B, 1, i)); fmpz_fmms(u, fmpz_mat_entry(A, 0, 0), fmpz_mat_entry(B, 1, i), fmpz_mat_entry(A, 1, 0), fmpz_mat_entry(B, 0, i)); fmpz_swap(fmpz_mat_entry(X, 0, i), t); fmpz_swap(fmpz_mat_entry(X, 1, i), u); } fmpz_clear(t); fmpz_clear(u); return 1; } else if (dim == 3) { if (X == A) { int success; fmpz_mat_t T; fmpz_mat_init(T, 3, 3); success = _fmpz_mat_solve_cramer_3x3(T, den, A, B); fmpz_mat_swap_entrywise(T, X); fmpz_mat_clear(T); return success; } else { return _fmpz_mat_solve_cramer_3x3(X, den, A, B); } } else { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_solve_cramer). dim > 3 not implemented."); } } flint-3.1.3/src/fmpz_mat/solve_dixon.c000066400000000000000000000141771461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" mp_limb_t fmpz_mat_find_good_prime_and_invert(nmod_mat_t Ainv, const fmpz_mat_t A, const fmpz_t det_bound) { mp_limb_t p; fmpz_t tested; p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; fmpz_init(tested); fmpz_one(tested); while (1) { p = n_nextprime(p, 0); nmod_mat_set_mod(Ainv, p); fmpz_mat_get_nmod_mat(Ainv, A); if (nmod_mat_inv(Ainv, Ainv)) break; fmpz_mul_ui(tested, tested, p); if (fmpz_cmp(tested, det_bound) > 0) { p = 0; break; } } fmpz_clear(tested); return p; } /* We need to perform several matrix-vector products Ay, and speed them up by using modular multiplication (this is only faster if we precompute the modular matrices). Note: we assume that all primes are >= p. This allows reusing y_mod as the right-hand side without reducing it. */ #define USE_SLOW_MULTIPLICATION 0 mp_limb_t * fmpz_mat_dixon_get_crt_primes(slong * num_primes, const fmpz_mat_t A, mp_limb_t p) { fmpz_t bound, prod; mp_limb_t * primes; slong i, j; fmpz_init(bound); fmpz_init(prod); for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) if (fmpz_cmpabs(bound, fmpz_mat_entry(A, i, j)) < 0) fmpz_abs(bound, fmpz_mat_entry(A, i, j)); fmpz_mul_ui(bound, bound, p - UWORD(1)); fmpz_mul_ui(bound, bound, A->r); fmpz_mul_ui(bound, bound, UWORD(2)); /* signs */ primes = (mp_limb_t *) flint_malloc(sizeof(mp_limb_t) * (fmpz_bits(bound) / (FLINT_BIT_COUNT(p) - 1) + 2)); primes[0] = p; fmpz_set_ui(prod, p); *num_primes = 1; while (fmpz_cmp(prod, bound) <= 0) { primes[*num_primes] = p = n_nextprime(p, 0); *num_primes += 1; fmpz_mul_ui(prod, prod, p); } fmpz_clear(bound); fmpz_clear(prod); return primes; } void _fmpz_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_mat_t A, const fmpz_mat_t B, const nmod_mat_t Ainv, mp_limb_t p, const fmpz_t N, const fmpz_t D) { fmpz_t bound, ppow; fmpz_mat_t x, d, y, Ay; fmpz_t prod; mp_limb_t * crt_primes; nmod_mat_t * A_mod; nmod_mat_t Ay_mod, d_mod, y_mod; slong i, n, cols, num_primes; n = A->r; cols = B->c; fmpz_init(bound); fmpz_init(ppow); fmpz_init(prod); fmpz_mat_init(x, n, cols); fmpz_mat_init(y, n, cols); fmpz_mat_init(Ay, n, cols); fmpz_mat_init_set(d, B); /* Compute bound for the needed modulus. TODO: if one of N and D is much smaller than the other, we could use a tighter bound (i.e. 2ND). This would require the ability to forward N and D to the rational reconstruction routine. */ if (fmpz_cmpabs(N, D) < 0) fmpz_mul(bound, D, D); else fmpz_mul(bound, N, N); fmpz_mul_ui(bound, bound, UWORD(2)); /* signs */ crt_primes = fmpz_mat_dixon_get_crt_primes(&num_primes, A, p); A_mod = (nmod_mat_t *) flint_malloc(sizeof(nmod_mat_t) * num_primes); for (i = 0; i < num_primes; i++) { nmod_mat_init(A_mod[i], n, n, crt_primes[i]); fmpz_mat_get_nmod_mat(A_mod[i], A); } nmod_mat_init(Ay_mod, n, cols, UWORD(1)); nmod_mat_init(d_mod, n, cols, p); nmod_mat_init(y_mod, n, cols, p); fmpz_one(ppow); while (fmpz_cmp(ppow, bound) <= 0) { /* y = A^(-1) * d (mod p) */ fmpz_mat_get_nmod_mat(d_mod, d); nmod_mat_mul(y_mod, Ainv, d_mod); /* x = x + y * p^i [= A^(-1) * b mod p^(i+1)] */ fmpz_mat_scalar_addmul_nmod_mat_fmpz(x, y_mod, ppow); /* ppow = p^(i+1) */ fmpz_mul_ui(ppow, ppow, p); if (fmpz_cmp(ppow, bound) > 0) break; /* d = (d - Ay) / p */ #if USE_SLOW_MULTIPLICATION fmpz_mat_set_nmod_mat_unsigned(y, y_mod); fmpz_mat_mul(Ay, A, y); #else for (i = 0; i < num_primes; i++) { nmod_mat_set_mod(y_mod, crt_primes[i]); nmod_mat_set_mod(Ay_mod, crt_primes[i]); nmod_mat_mul(Ay_mod, A_mod[i], y_mod); if (i == 0) { fmpz_mat_set_nmod_mat(Ay, Ay_mod); fmpz_set_ui(prod, crt_primes[0]); } else { fmpz_mat_CRT_ui(Ay, Ay, prod, Ay_mod, 1); fmpz_mul_ui(prod, prod, crt_primes[i]); } } #endif nmod_mat_set_mod(y_mod, p); fmpz_mat_sub(d, d, Ay); fmpz_mat_scalar_divexact_ui(d, d, p); } fmpz_set(mod, ppow); fmpz_mat_set(X, x); nmod_mat_clear(y_mod); nmod_mat_clear(d_mod); nmod_mat_clear(Ay_mod); for (i = 0; i < num_primes; i++) nmod_mat_clear(A_mod[i]); flint_free(A_mod); flint_free(crt_primes); fmpz_clear(bound); fmpz_clear(ppow); fmpz_clear(prod); fmpz_mat_clear(x); fmpz_mat_clear(y); fmpz_mat_clear(d); fmpz_mat_clear(Ay); } int fmpz_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_mat_t A, const fmpz_mat_t B) { nmod_mat_t Ainv; fmpz_t N, D; mp_limb_t p; if (!fmpz_mat_is_square(A)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_solve_dixon). Non-square system matrix.\n"); } if (fmpz_mat_is_empty(A) || fmpz_mat_is_empty(B)) return 1; fmpz_init(N); fmpz_init(D); fmpz_mat_solve_bound(N, D, A, B); nmod_mat_init(Ainv, A->r, A->r, 1); p = fmpz_mat_find_good_prime_and_invert(Ainv, A, D); if (p != 0) _fmpz_mat_solve_dixon(X, mod, A, B, Ainv, p, N, D); nmod_mat_clear(Ainv); fmpz_clear(N); fmpz_clear(D); return p != 0; } flint-3.1.3/src/fmpz_mat/solve_dixon_den.c000066400000000000000000000014551461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" int fmpz_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { int success; fmpq_mat_t Q; fmpq_mat_init(Q, fmpz_mat_nrows(X), fmpz_mat_ncols(X)); success = fmpq_mat_solve_fmpz_mat_dixon(Q, A, B); if (success) fmpq_mat_get_fmpz_mat_matwise(X, den, Q); fmpq_mat_clear(Q); return success; } flint-3.1.3/src/fmpz_mat/solve_fflu.c000066400000000000000000000022201461254215100175430ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" int fmpz_mat_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { fmpz_mat_t LU; slong dim, *perm; int result; if (fmpz_mat_is_empty(A) || fmpz_mat_is_empty(B)) { fmpz_one(den); return 1; } dim = fmpz_mat_nrows(A); perm = _perm_init(dim); fmpz_mat_init_set(LU, A); result = (fmpz_mat_fflu(LU, den, perm, LU, 1) == dim); if (result) { fmpz_mat_solve_fflu_precomp(X, perm, LU, B); if (_perm_parity(perm, dim)) { fmpz_neg(den, den); fmpz_mat_neg(X, X); } } else fmpz_zero(den); _perm_clear(perm); fmpz_mat_clear(LU); return result; } flint-3.1.3/src/fmpz_mat/solve_fflu_precomp.c000066400000000000000000000246261461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2020-2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #define XX(ii,jj) fmpz_mat_entry(X,(ii),(jj)) #define XXx(ii,jj) fmpz_mat_entry(Xx,(ii),(jj)) #define BB(ii,jj) fmpz_mat_entry(B,(ii),(jj)) #define LU(ii,jj) fmpz_mat_entry(FFLU,(ii),(jj)) void fmpz_mat_set_perm(fmpz_mat_t X, const slong * perm, const fmpz_mat_t B) { if (X == B) { /* Not implemented */ flint_throw(FLINT_ERROR, "(%s): Not implemented\n", __func__); } else { slong i, j; if (perm == NULL) flint_throw(FLINT_ERROR, "(%s): perm == NULL\n", __func__); for (i = 0; i < fmpz_mat_nrows(B); i++) for (j = 0; j < fmpz_mat_ncols(B); j++) fmpz_set(fmpz_mat_entry(X, i, j), fmpz_mat_entry(B, perm[i], j)); } } int fmpz_mat_solve_fflu_precomp(fmpz_mat_t X, const slong * perm, const fmpz_mat_t FFLU, const fmpz_mat_t B) { fmpz_t T; slong c, i, j, k, l, m, n, rnk, norm = 0; ulong p1h, p1m, p1l, p2h, p2m, p2l, uden = 0, dinv = 0, quo; ulong FLINT_SET_BUT_UNUSED(rem); slong fbits = fmpz_mat_max_bits(FFLU); slong bbits = fmpz_mat_max_bits(B); int small = FLINT_ABS(fbits) <= SMALL_FMPZ_BITCOUNT_MAX && FLINT_ABS(bbits) <= SMALL_FMPZ_BITCOUNT_MAX; int sgn, dsgn = 0, den1 = 0, work_to_do, flag = 1; fmpz_mat_t Xx; fmpz * diag; slong * piv; n = B->r; m = B->c; c = FFLU->c; fmpz_init(T); fmpz_mat_init(Xx, B->r, B->c); fmpz_mat_set_perm(Xx, perm, B); diag = _fmpz_vec_init(n); piv = (slong *) flint_malloc(n*sizeof(slong)); rnk = 0; for (i = 0, l = 0; i < n; i++, l++) { while (l < c && fmpz_is_zero(LU(i, l))) l++; piv[i] = l; if (l < c) { fmpz_set(diag + i, LU(i, l)); rnk += 1; } } for (k = 0; k < m; k++) { /* Fraction-free forward substitution */ for (i = 0; i < n - 1; i++) { if (small) { den1 = 0; if (i > 0) { uden = FLINT_ABS((slong)(diag[i - 1])); dsgn = 0 > (slong)(diag[i - 1]); if (uden != 0) /* see #1029 */ { norm = flint_clz(uden); dinv = n_preinvert_limb_prenorm(uden << norm); } else dinv = 0; den1 = fmpz_is_one(diag + i - 1); } work_to_do = (!den1 || !fmpz_is_zero(XXx(i, k)) || !fmpz_is_one(diag + i)); if (work_to_do) { for (j = i + 1; j < n; j++) { if (i < c && piv[i] < c) { smul_ppmm(p1h, p1l, *XXx(j, k), diag[i]); smul_ppmm(p2h, p2l, *LU(j, piv[i]), *XXx(i, k)); sub_ddmmss(p1h, p1l, p1h, p1l, p2h, p2l); sgn = 0 > (slong) p1h; if (sgn) /* take absolute value */ sub_ddmmss(p1h, p1l, UWORD(0), UWORD(0), p1h, p1l); if (i > 0 && !den1 && i < c && piv[i - 1] < c) { if (p1h >= uden) { fmpz_set_uiui(XXx(j, k), p1h, p1l); if (sgn) fmpz_neg(XXx(j, k), XXx(j, k)); if (i < c && piv[i - 1] < c) { flag = fmpz_divides(XXx(j, k), XXx(j, k), diag + i - 1); if (!flag) goto cleanup; } small = 0; } else { udiv_qrnnd_preinv(quo, rem, (p1h << norm) + r_shift(p1l, (FLINT_BITS - norm)), p1l << norm, uden << norm, dinv); flag = rem == 0; if (!flag) goto cleanup; if (sgn ^ dsgn) fmpz_neg_ui(XXx(j, k), quo); else fmpz_set_ui(XXx(j, k), quo); if (quo > COEFF_MAX) small = 0; } } else { if (p1h > 0) { fmpz_set_uiui(XXx(j, k), p1h, p1l); small = 0; } else { fmpz_set_ui(XXx(j, k), p1l); if (p1l > COEFF_MAX) small = 0; } if (sgn) fmpz_neg(XXx(j, k), XXx(j, k)); } } else if (i > 0) { if (i < c && piv[i - 1] < c) { flag = fmpz_divides(XXx(j, k), XXx(j, k), diag + i - 1); if (!flag) goto cleanup; } } } } } else { for (j = i + 1; j < n; j++) { if (i < c && piv[i] < c) { fmpz_mul(XXx(j, k), XXx(j, k), diag + i); fmpz_mul(T, LU(j, piv[i]), XXx(i, k)); fmpz_sub(XXx(j, k), XXx(j, k), T); } if (i > 0) { if (i < c && piv[i - 1] < c) { flag = fmpz_divides(XXx(j, k), XXx(j, k), diag + i - 1); if (!flag) goto cleanup; } } } } } l = rnk - 1; /* Fraction-free back substitution */ for (i = c - 1; i >= 0; i--) { if (l > -1 && i == piv[l]) { if (small) { if (rnk != 0) smul_ppmm(p1m, p1l, *XXx(l, k), diag[rnk - 1]); else { p1l = *XXx(l, k); p1m = FLINT_SIGN_EXT(p1l); } p1h = FLINT_SIGN_EXT(p1m); uden = FLINT_ABS((slong)(diag[l])); dsgn = 0 > (slong)(diag[l]); if (uden != 0) /* see #1029 */ { norm = flint_clz(uden); dinv = n_preinvert_limb_prenorm(uden << norm); } else dinv = 0; for (j = piv[l] + 1; j < c; j++) { if (!fmpz_is_zero(LU(l, j))) { smul_ppmm(p2m, p2l, *XX(j, k), *LU(l, j)); p2h = FLINT_SIGN_EXT(p2m); sub_dddmmmsss(p1h, p1m, p1l, p1h, p1m, p1l, p2h, p2m, p2l); } } sgn = 0 > (slong) p1h; if (sgn) /* take absolute value */ sub_dddmmmsss(p1h, p1m, p1l, UWORD(0), UWORD(0), UWORD(0), p1h, p1m, p1l); if (p1h != 0 || p1m >= uden) { fmpz_set_signed_uiuiui(XX(i, k), p1h, p1m, p1l); flag = fmpz_divides(XX(i, k), XX(i, k), diag + l); if (!flag) goto cleanup; if (sgn) fmpz_neg(XX(i, k), XX(i, k)); small = 0; } else { udiv_qrnnd_preinv(quo, rem, (p1m << norm) + r_shift(p1l, (FLINT_BITS - norm)), p1l << norm, uden << norm, dinv); flag = rem == 0; if (!flag) goto cleanup; if (sgn ^ dsgn) fmpz_neg_ui(XX(i, k), quo); else fmpz_set_ui(XX(i, k), quo); if (quo > COEFF_MAX) small = 0; } } else { if (rnk != 0) fmpz_mul(XX(i, k), XXx(l, k), diag + rnk - 1); else fmpz_set(XX(i, k), XXx(l, k)); for (j = piv[l] + 1; j < c; j++) { fmpz_mul(T, XX(j, k), LU(l, j)); fmpz_sub(XX(i, k), XX(i, k), T); } flag = fmpz_divides(XX(i, k), XX(i, k), diag + l); if (!flag) goto cleanup; } l--; } else fmpz_zero(XX(i, k)); } } cleanup: _fmpz_vec_clear(diag, n); flint_free(piv); fmpz_mat_clear(Xx); fmpz_clear(T); return flag; } flint-3.1.3/src/fmpz_mat/solve_multi_mod_den.c000066400000000000000000000032561461254215100214400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" mp_limb_t fmpz_mat_find_good_prime_and_solve(nmod_mat_t Xmod, nmod_mat_t Amod, nmod_mat_t Bmod, const fmpz_mat_t A, const fmpz_mat_t B, const fmpz_t det_bound) { mp_limb_t p; fmpz_t tested; p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; fmpz_init(tested); fmpz_one(tested); while (1) { p = n_nextprime(p, 0); nmod_mat_set_mod(Xmod, p); nmod_mat_set_mod(Amod, p); nmod_mat_set_mod(Bmod, p); fmpz_mat_get_nmod_mat(Amod, A); fmpz_mat_get_nmod_mat(Bmod, B); if (nmod_mat_solve(Xmod, Amod, Bmod)) break; fmpz_mul_ui(tested, tested, p); if (fmpz_cmp(tested, det_bound) > 0) { p = 0; break; } } fmpz_clear(tested); return p; } int fmpz_mat_solve_multi_mod_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { int success; fmpq_mat_t Q; fmpq_mat_init(Q, fmpz_mat_nrows(X), fmpz_mat_ncols(X)); success = fmpq_mat_solve_fmpz_mat_multi_mod(Q, A, B); if (success) fmpq_mat_get_fmpz_mat_matwise(X, den, Q); fmpq_mat_clear(Q); return success; } flint-3.1.3/src/fmpz_mat/sqr.c000066400000000000000000000017351461254215100162160ustar00rootroot00000000000000/* Copyright (C) 2012, 2024 Fredrik Johansson Copyright (C) 2015 Anubhav Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_sqr(fmpz_mat_t B, const fmpz_mat_t A) { slong n = A->r, ab; if (B == A) { fmpz_mat_t t; fmpz_mat_init(t, n, n); fmpz_mat_sqr(t, A); fmpz_mat_swap_entrywise(B, t); fmpz_mat_clear(t); return; } if (n <= 3) { fmpz_mat_sqr_bodrato(B, A); return; } ab = fmpz_mat_max_bits(A); ab = FLINT_ABS(ab); if (n == 4 && ab >= 1024) fmpz_mat_sqr_bodrato(B, A); else fmpz_mat_mul(B, A, A); } flint-3.1.3/src/fmpz_mat/sqr_bodrato.c000066400000000000000000000217241461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2012, 2024 Fredrik Johansson Copyright (C) 2015 Anubhav Srivastava Copyright (C) 2024 Marco Bodrato This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #define E fmpz_mat_entry static void local_fmma(fmpz_t f, mp_limb_t a, fmpz b, fmpz c, fmpz d) { mp_limb_t sh, sl, th, tl; smul_ppmm(sh, sl, a, b); smul_ppmm(th, tl, c, d); add_ssaaaa(sh, sl, sh, sl, th, tl); fmpz_set_signed_uiui(f, sh, sl); } void fmpz_mat_sqr_bodrato(fmpz_mat_t B, const fmpz_mat_t A) { slong n = A->r; if (n == 0) { return; } else if (n == 1) { fmpz_mul(E(B, 0, 0), E(A, 0, 0), E(A, 0, 0)); } else if (n == 2) { const fmpz a = *E(A, 0, 0); const fmpz b = *E(A, 0, 1); const fmpz c = *E(A, 1, 0); const fmpz d = *E(A, 1, 1); if (!COEFF_IS_MPZ(a) && !COEFF_IS_MPZ(b) && !COEFF_IS_MPZ(c) && !COEFF_IS_MPZ(d)) { mp_limb_t s, t, u, v; smul_ppmm(s, t, a, a); smul_ppmm(u, v, b, c); add_ssaaaa(s, t, s, t, u, v); fmpz_set_signed_uiui(E(B, 0, 0), s, t); smul_ppmm(s, t, d, d); add_ssaaaa(s, t, s, t, u, v); fmpz_set_signed_uiui(E(B, 1, 1), s, t); smul_ppmm(s, t, a + d, b); fmpz_set_signed_uiui(E(B, 0, 1), s, t); smul_ppmm(s, t, a + d, c); fmpz_set_signed_uiui(E(B, 1, 0), s, t); } else { fmpz_t t; fmpz_init(t); fmpz_mul(t, E(A, 0, 1), E(A, 1, 0)); fmpz_mul(E(B, 0, 0), E(A, 0, 0), E(A, 0, 0)); fmpz_add(E(B, 0, 0), E(B, 0, 0), t); fmpz_mul(E(B, 1, 1), E(A, 1, 1), E(A, 1, 1)); fmpz_add(E(B, 1, 1), E(B, 1, 1), t); fmpz_add(t, E(A, 0, 0), E(A, 1, 1)); fmpz_mul(E(B, 0, 1), E(A, 0, 1), t); fmpz_mul(E(B, 1, 0), E(A, 1, 0), t); fmpz_clear(t); } } else if (n == 3) { if (!COEFF_IS_MPZ(*E(A, 0, 0)) && !COEFF_IS_MPZ(*E(A, 1, 0)) && !COEFF_IS_MPZ(*E(A, 0, 1)) && !COEFF_IS_MPZ(*E(A, 1, 1)) && !COEFF_IS_MPZ(*E(A, 0, 2)) && !COEFF_IS_MPZ(*E(A, 1, 2)) && !COEFF_IS_MPZ(*E(A, 2, 0)) && !COEFF_IS_MPZ(*E(A, 2, 1)) && !COEFF_IS_MPZ(*E(A, 2, 2))) { mp_limb_t s, t, u, v, j, k; smul_ppmm(s, t, *E(A, 0, 2), *E(A, 2, 0)); smul_ppmm(u, v, *E(A, 0, 1), *E(A, 1, 0)); smul_ppmm(j, k, *E(A, 0, 0), *E(A, 0, 0)); add_ssaaaa(j, k, j, k, u, v); add_ssaaaa(j, k, j, k, s, t); fmpz_set_signed_uiui(E(B, 0, 0), j, k); smul_ppmm(j, k, *E(A, 1, 2), *E(A, 2, 1)); add_ssaaaa(u, v, u, v, j, k); add_ssaaaa(s, t, s, t, j, k); smul_ppmm(j, k, *E(A, 1, 1), *E(A, 1, 1)); add_ssaaaa(j, k, j, k, u, v); fmpz_set_signed_uiui(E(B, 1, 1), j, k); smul_ppmm(j, k, *E(A, 2, 2), *E(A, 2, 2)); add_ssaaaa(j, k, j, k, s, t); fmpz_set_signed_uiui(E(B, 2, 2), j, k); s = *E(A, 0, 0) + *E(A, 1, 1); local_fmma(E(B, 0, 1), s, *E(A, 0, 1), *E(A, 0, 2), *E(A, 2, 1)); local_fmma(E(B, 1, 0), s, *E(A, 1, 0), *E(A, 2, 0), *E(A, 1, 2)); t = *E(A, 0, 0) + *E(A, 2, 2); local_fmma(E(B, 0, 2), t, *E(A, 0, 2), *E(A, 0, 1), *E(A, 1, 2)); local_fmma(E(B, 2, 0), t, *E(A, 2, 0), *E(A, 2, 1), *E(A, 1, 0)); u = *E(A, 1, 1) + *E(A, 2, 2); local_fmma(E(B, 1, 2), u, *E(A, 1, 2), *E(A, 1, 0), *E(A, 0, 2)); local_fmma(E(B, 2, 1), u, *E(A, 2, 1), *E(A, 0, 1), *E(A, 2, 0)); } else { slong bits; int sign; bits = fmpz_mat_max_bits(A); sign = (bits < 0); bits = FLINT_ABS(bits); if (bits + sign <= 2 * FLINT_BITS) { bits = 2 * bits + FLINT_BIT_COUNT(n); /* todo: specialize for squaring */ _fmpz_mat_mul_double_word_internal(B, A, A, sign, bits); } else { fmpz_t temp; fmpz_mul(E(B, 2, 2), E(A, 2, 2), E(A, 2, 2)); fmpz_mul(E(B, 1, 1), E(A, 1, 1), E(A, 1, 1)); fmpz_mul(E(B, 0, 0), E(A, 0, 0), E(A, 0, 0)); fmpz_init(temp); fmpz_mul(temp, E(A, 0, 1), E(A, 1, 0)); fmpz_add(E(B, 0, 0), E(B, 0, 0), temp); fmpz_add(E(B, 1, 1), E(B, 1, 1), temp); fmpz_mul(temp, E(A, 1, 2), E(A, 2, 1)); fmpz_add(E(B, 1, 1), E(B, 1, 1), temp); fmpz_add(E(B, 2, 2), E(B, 2, 2), temp); fmpz_mul(temp, E(A, 0, 2), E(A, 2, 0)); fmpz_add(E(B, 2, 2), E(B, 2, 2), temp); fmpz_add(E(B, 0, 0), E(B, 0, 0), temp); fmpz_add(temp, E(A, 0, 0), E(A, 1, 1)); fmpz_fmma(E(B, 0, 1), temp, E(A, 0, 1), E(A, 0, 2), E(A, 2, 1)); fmpz_fmma(E(B, 1, 0), temp, E(A, 1, 0), E(A, 2, 0), E(A, 1, 2)); fmpz_add(temp, E(A, 0, 0), E(A, 2, 2)); fmpz_fmma(E(B, 0, 2), temp, E(A, 0, 2), E(A, 0, 1), E(A, 1, 2)); fmpz_fmma(E(B, 2, 0), temp, E(A, 2, 0), E(A, 2, 1), E(A, 1, 0)); fmpz_add(temp, E(A, 1, 1), E(A, 2, 2)); fmpz_fmma(E(B, 1, 2), temp, E(A, 1, 2), E(A, 1, 0), E(A, 0, 2)); fmpz_fmma(E(B, 2, 1), temp, E(A, 2, 1), E(A, 0, 1), E(A, 2, 0)); fmpz_clear(temp); } } } else { slong anr; fmpz_mat_t A11, A12, A21, A22; fmpz_mat_t B11, B12, B21, B22; fmpz_mat_t X1, X2; anr = n / 2; fmpz_mat_window_init(A11, A, 0, 0, anr, anr); fmpz_mat_window_init(A12, A, 0, anr, anr, 2*anr); fmpz_mat_window_init(A21, A, anr, 0, 2*anr, anr); fmpz_mat_window_init(A22, A, anr, anr, 2*anr, 2*anr); fmpz_mat_window_init(B11, B, 0, 0, anr, anr); fmpz_mat_window_init(B12, B, 0, anr, anr, 2*anr); fmpz_mat_window_init(B21, B, anr, 0, 2*anr, anr); fmpz_mat_window_init(B22, B, anr, anr, 2*anr, 2*anr); fmpz_mat_init(X2, anr, anr); fmpz_mat_add(X2, A22, A12); fmpz_mat_sqr(B21, X2); fmpz_mat_sub(X2, A22, A21); fmpz_mat_sqr(B22, X2); fmpz_mat_add(X2, X2, A12); fmpz_mat_sqr(B11, X2); fmpz_mat_sub(X2, X2, A11); fmpz_mat_mul(B12, X2, A12); fmpz_mat_init(X1, anr, anr); fmpz_mat_mul(X1, A12, A21); fmpz_mat_add(B11, B11, X1); fmpz_mat_sub(B12, B11, B12); fmpz_mat_sub(B11, B21, B11); fmpz_mat_mul(B21, A21, X2); fmpz_mat_clear(X2); fmpz_mat_sub(B21, B11, B21); fmpz_mat_sub(B12, B12, B22); fmpz_mat_add(B22, B22, B11); fmpz_mat_sqr(B11, A11); fmpz_mat_add(B11, X1, B11); fmpz_mat_clear(X1); fmpz_mat_window_clear(A11); fmpz_mat_window_clear(A12); fmpz_mat_window_clear(A21); fmpz_mat_window_clear(A22); fmpz_mat_window_clear(B11); fmpz_mat_window_clear(B12); fmpz_mat_window_clear(B21); fmpz_mat_window_clear(B22); if (n > 2*anr) { { fmpz_mat_t Ac, Bc; fmpz_mat_window_init(Ac, A, 0, 2*anr, n, n); fmpz_mat_window_init(Bc, B, 0, 2*anr, n, n); fmpz_mat_mul(Bc, A, Ac); fmpz_mat_window_clear(Ac); fmpz_mat_window_clear(Bc); } { fmpz_mat_t Ar, Br; fmpz_mat_t As; fmpz_mat_window_init(Ar, A, 2*anr, 0, n, n); fmpz_mat_window_init(Br, B, 2*anr, 0, n, 2*anr); fmpz_mat_window_init(As, A, 0, 0, n, 2*anr); fmpz_mat_mul(Br, Ar, As); fmpz_mat_window_clear(As); fmpz_mat_window_clear(Ar); fmpz_mat_window_clear(Br); } #if 0 { fmpz_mat_t Ac, Ar, Bb, tmp; fmpz_mat_window_init(Ac, A, 0, 2*anr, 2*anr, n); fmpz_mat_window_init(Ar, A, 2*anr, 0, n, 2*anr); fmpz_mat_window_init(Bb, B, 0, 0, 2*anr, 2*anr); fmpz_mat_init(tmp, 2*anr, 2*anr); fmpz_mat_mul(tmp, Ac, Ar); fmpz_mat_add(Bb, Bb, tmp); fmpz_mat_clear(tmp); fmpz_mat_window_clear(Ac); fmpz_mat_window_clear(Ar); fmpz_mat_window_clear(Bb); } #else { slong i, j; for (i = 0; i < 2*anr; ++i) { const fmpz tmptr = *E(A, i, n - 1); for (j = 0; j < 2*anr; ++j) { fmpz_addmul(E(B, i, j), &tmptr, E(A, n - 1, j)); } } } #endif } } }flint-3.1.3/src/fmpz_mat/strong_echelon_form_mod.c000066400000000000000000000203141461254215100222760ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" static int _fmpz_mat_pivot(fmpz_mat_t A, slong start_row, slong col) { slong j; fmpz * u; if (fmpz_is_zero(fmpz_mat_entry(A, start_row, col)) == 0) return 1; for (j = start_row + 1; j < A->r; j++) { if (!fmpz_is_zero(fmpz_mat_entry(A, j, col))) { u = A->rows[j]; A->rows[j] = A->rows[start_row]; A->rows[start_row] = u; return -1; } } return 0; } static void _fmpz_ppio(fmpz_t ppi, fmpz_t ppo, fmpz_t a, fmpz_t b) { fmpz_t c, n, g; fmpz_init(c); fmpz_init(n); fmpz_init(g); fmpz_gcd(c, a, b); fmpz_divexact(n, a, c); fmpz_gcd(g, c, n); while (!fmpz_is_one(g)) { fmpz_mul(c, c, g); fmpz_divexact(n, n, g); fmpz_gcd(g, c, n); } fmpz_set(ppi, c); fmpz_set(ppo, n); fmpz_clear(c); fmpz_clear(n); fmpz_clear(g); } static void _fmpz_stab(fmpz_t t, const fmpz_t a, const fmpz_t b, const fmpz_t N) { fmpz_t g, gg, s, aa, bb; fmpz_init(g); fmpz_init(gg); fmpz_init(s); fmpz_init(aa); fmpz_init(bb); fmpz_gcd(g, a, b); fmpz_gcd(gg, g, N); fmpz_divexact(bb, N, gg); fmpz_divexact(aa, a, gg); _fmpz_ppio(s, t, bb, aa); fmpz_clear(g); fmpz_clear(gg); fmpz_clear(s); fmpz_clear(aa); fmpz_clear(bb); } static void _fmpz_unit(fmpz_t u, fmpz_t a, const fmpz_t N) { fmpz_t g, s, t, l, d, k; fmpz_init(g); fmpz_init(s); fmpz_init(t); fmpz_init(l); fmpz_init(d); fmpz_init(k); fmpz_xgcd(g, s, t, a, N); if (fmpz_is_one(g) == 1) { fmpz_set(u, s); } else { fmpz_divexact(l, N, g); _fmpz_stab(d, s, l, N); fmpz_mul(u, d, l); fmpz_add(u, u, s); fmpz_mod(u, u, N); } fmpz_clear(g); fmpz_clear(s); fmpz_clear(t); fmpz_clear(l); fmpz_clear(d); fmpz_clear(k); } /* test whether q*a = b mod N has a solution */ static int _fmpz_is_divisible_mod(fmpz_t q, fmpz_t b, fmpz_t a, const fmpz_t N) { fmpz_t g, e, t; fmpz_init(g); fmpz_init(e); fmpz_init(t); fmpz_xgcd(g, e, t, a, N); if (fmpz_divisible(b, g)) { fmpz_divexact(g, b, g); fmpz_mul(g, e, g); fmpz_mod(q, g, N); fmpz_clear(g); fmpz_clear(e); fmpz_clear(t); return 1; } fmpz_clear(g); fmpz_clear(e); fmpz_clear(t); return 0; } void fmpz_mat_strong_echelon_form_mod(fmpz_mat_t A, const fmpz_t mod) { fmpz_t s, t, q, u, v, t1, t2, g; slong m, n, row, col, i, k, l; fmpz ** r; fmpz * extra_row; if (fmpz_mat_is_empty(A)) return; fmpz_init(s); fmpz_init(t); fmpz_init(q); fmpz_init(u); fmpz_init(v); fmpz_init(t1); fmpz_init(t2); fmpz_init(g); n = A->r; m = A->c; r = A->rows; extra_row = _fmpz_vec_init(m); row = col = 0; for (row = 0; row < n; row++) { for (col = 0; col < m; col++) { fmpz_mod(fmpz_mat_entry(A, row, col), fmpz_mat_entry(A, row, col), mod); } } row = col = 0; while (row < n && col < m) { if (_fmpz_mat_pivot(A, row, col) == 0) { col++; continue; } for (i = row + 1; i < n; i++) { if (fmpz_is_zero(fmpz_mat_entry(A, i, col))) { continue; } if ( _fmpz_is_divisible_mod(s, fmpz_mat_entry(A, i, col), fmpz_mat_entry(A, row, col), mod)) { for (k = col; k < m; k++) { fmpz_set(t1, fmpz_mat_entry(A, i, k)); fmpz_submul(t1, s, fmpz_mat_entry(A, row, k)); fmpz_mod(t1, t1, mod); fmpz_set(fmpz_mat_entry(A, i, k), t1); } } else { fmpz_xgcd(g, s, t, fmpz_mat_entry(A, row, col), fmpz_mat_entry(A, i, col)); fmpz_divexact(u, fmpz_mat_entry(A, i, col), g); fmpz_neg(u, u); fmpz_divexact(v, fmpz_mat_entry(A, row, col), g); for (k = col; k < m; k++) { fmpz_mul(t1, s, fmpz_mat_entry(A, row, k)); fmpz_addmul(t1, t, fmpz_mat_entry(A, i, k)); fmpz_mod(t1, t1, mod); fmpz_mul(t2, u, fmpz_mat_entry(A, row, k)); fmpz_addmul(t2, v, fmpz_mat_entry(A, i, k)); fmpz_mod(t2, t2, mod); fmpz_set(fmpz_mat_entry(A, row, k), t1); fmpz_set(fmpz_mat_entry(A, i, k), t2); } } } for (i = row - 1; i >= 0; i--) { fmpz_mod(fmpz_mat_entry(A, i, col), fmpz_mat_entry(A, i, col), mod); } row++; col++; } for (col = 0; col < m; col++) { if (fmpz_is_zero(fmpz_mat_entry(A, col, col)) != 1) { _fmpz_unit(u, fmpz_mat_entry(A, col, col), mod); for (k = col ; k < m; k++) { fmpz_mul(fmpz_mat_entry(A, col, k), u, fmpz_mat_entry(A, col, k)); fmpz_mod(fmpz_mat_entry(A, col, k), fmpz_mat_entry(A, col, k), mod); } for (row = 0; row < col ; row++) { fmpz_fdiv_q(q, fmpz_mat_entry(A, row, col), fmpz_mat_entry(A, col, col)); for (l = row; l< m; l++) { fmpz_submul(fmpz_mat_entry(A, row, l), q, fmpz_mat_entry(A, col, l)); fmpz_mod(fmpz_mat_entry(A, row, l), fmpz_mat_entry(A, row, l), mod); } } fmpz_gcd(g, mod, fmpz_mat_entry(A, col, col)); if (fmpz_is_one(g) == 1) { continue; } fmpz_divexact(g, mod, g); _fmpz_vec_scalar_mul_fmpz(extra_row, r[col], m, g); _fmpz_vec_scalar_mod_fmpz(extra_row, extra_row, m, mod); } else { _fmpz_vec_set(extra_row, r[col], m); } for (row = col + 1; row < m; row++) { fmpz_xgcd(g, s, t, fmpz_mat_entry(A, row, row), extra_row + row); if (fmpz_is_zero(g)) { continue; } fmpz_divexact(u, extra_row + row, g); fmpz_neg(u, u); fmpz_divexact(v, fmpz_mat_entry(A, row, row), g); for (k = row; k < m; k++) { fmpz_mul(t1, s, fmpz_mat_entry(A, row, k)); fmpz_addmul(t1, t, extra_row + k); fmpz_mod(t1, t1, mod); fmpz_mul(t2, u, fmpz_mat_entry(A, row, k)); fmpz_addmul(t2, v, extra_row + k); fmpz_mod(t2, t2, mod); fmpz_set(fmpz_mat_entry(A, row, k), t1); fmpz_set(extra_row + k, t2); } } if (fmpz_is_zero(fmpz_mat_entry(A, col, col)) != 1) { for (i = col - 1; i >= 0; i--) { fmpz_mod(fmpz_mat_entry(A, i, col), fmpz_mat_entry(A, i, col), mod); } } } for (i = 1; i < m; i++) { if (!fmpz_is_zero(fmpz_mat_entry(A, i, i))) { for (k = i - 1; k >= 0; k--) { fmpz_fdiv_q(q, fmpz_mat_entry(A, k, i), fmpz_mat_entry(A, i, i)); for (l = i; l < m; l++) { fmpz_submul(fmpz_mat_entry(A, k, l), fmpz_mat_entry(A, i, l), q); fmpz_mod(fmpz_mat_entry(A, k, l), fmpz_mat_entry(A, k, l), mod); } } } } _fmpz_vec_clear(extra_row, m); fmpz_clear(s); fmpz_clear(t); fmpz_clear(q); fmpz_clear(u); fmpz_clear(v); fmpz_clear(t1); fmpz_clear(t2); fmpz_clear(g); } flint-3.1.3/src/fmpz_mat/sub.c000066400000000000000000000012371461254215100161770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_sub(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2) { slong i; if (res->c < 1) return; for (i = 0; i < res->r; i++) _fmpz_vec_sub(res->rows[i], mat1->rows[i], mat2->rows[i], res->c); } flint-3.1.3/src/fmpz_mat/swap.c000066400000000000000000000021501461254215100163530ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_swap(fmpz_mat_t mat1, fmpz_mat_t mat2) { FLINT_SWAP(fmpz_mat_struct, *mat1, *mat2); } void fmpz_mat_swap_entrywise(fmpz_mat_t mat1, fmpz_mat_t mat2) { slong i, j; for (i = 0; i < fmpz_mat_nrows(mat1); i++) for (j = 0; j < fmpz_mat_ncols(mat1); j++) fmpz_swap(fmpz_mat_entry(mat2, i, j), fmpz_mat_entry(mat1, i, j)); } void fmpz_mat_swap_cols(fmpz_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !fmpz_mat_is_empty(mat)) { slong i; if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); for (i = 0; i < mat->r; i++) fmpz_swap(fmpz_mat_entry(mat, i, r), fmpz_mat_entry(mat, i, s)); } } flint-3.1.3/src/fmpz_mat/test/000077500000000000000000000000001461254215100162165ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mat/test/main.c000066400000000000000000000161561461254215100173170ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Try to get fdopen declared for fmpz_mat_[print/read] */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-can_solve_fflu.c" #include "t-can_solve_multi_mod_den.c" #include "t-charpoly_berkowitz.c" #include "t-charpoly.c" #include "t-chol_d.c" #include "t-col_partition.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-content.c" #include "t-CRT_ui.c" #include "t-CRT_ui_unsigned.c" #include "t-det_bound.c" #include "t-det.c" #include "t-det_divisor.c" #include "t-det_modular_accelerated.c" #include "t-det_modular.c" #include "t-entry.c" #include "t-equal.c" #include "t-fmpz_vec_mul.c" #include "t-get_d_mat.c" #include "t-get_d_mat_transpose.c" #include "t-get_nmod_mat.c" #include "t-gram.c" #include "t-hadamard.c" #include "t-hnf.c" #include "t-hnf_classical.c" #include "t-hnf_minors.c" #include "t-hnf_minors_transform.c" #include "t-hnf_modular.c" #include "t-hnf_modular_eldiv.c" #include "t-hnf_pernet_stein.c" #include "t-hnf_transform.c" #include "t-hnf_xgcd.c" #include "t-howell_form_mod.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-invert_rows_cols.c" #include "t-is_empty.c" #include "t-is_one.c" #include "t-is_spd.c" #include "t-is_square.c" #include "t-is_zero.c" #include "t-kronecker_product.c" #include "t-lll_original.c" #include "t-lll_storjohann.c" #include "t-max_bits.c" #include "t-minpoly.c" #include "t-mul_blas.c" #include "t-mul.c" #include "t-mul_classical.c" #include "t-mul_double_word.c" #include "t-mul_fft.c" #include "t-mul_fmpz_vec.c" #include "t-mul_multi_mod.c" #include "t-mul_small.c" #include "t-mul_strassen.c" #include "t-mul_waksman.c" #include "t-multi_CRT_ui.c" #include "t-multi_CRT_ui_unsigned.c" #include "t-nullspace.c" #include "t-one.c" #include "t-pow.c" #include "t-print_read.c" #include "t-rank.c" #include "t-rref.c" #include "t-rref_fflu.c" #include "t-rref_mul.c" #include "t-scalar_addmul_fmpz.c" #include "t-scalar_addmul_nmod_mat_fmpz.c" #include "t-scalar_addmul_nmod_mat_ui.c" #include "t-scalar_addmul_si.c" #include "t-scalar_addmul_ui.c" #include "t-scalar_mod_fmpz.c" #include "t-scalar_mul_2exp.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_si.c" #include "t-scalar_mul_ui.c" #include "t-scalar_smod.c" #include "t-snf_diagonal.c" #include "t-snf_iliopoulos.c" #include "t-snf_kannan_bachem.c" #include "t-solve_bound.c" #include "t-solve.c" #include "t-solve_cramer.c" #include "t-solve_dixon.c" #include "t-solve_dixon_den.c" #include "t-solve_fflu.c" #include "t-solve_multi_mod_den.c" #include "t-sqr.c" #include "t-trace.c" #include "t-transpose.c" #include "t-window_init_clear.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mat_add_sub), TEST_FUNCTION(fmpz_mat_can_solve_fflu), TEST_FUNCTION(fmpz_mat_can_solve_multi_mod_den), TEST_FUNCTION(fmpz_mat_charpoly_berkowitz), TEST_FUNCTION(fmpz_mat_charpoly), TEST_FUNCTION(fmpz_mat_chol_d), TEST_FUNCTION(fmpz_mat_col_partition), TEST_FUNCTION(fmpz_mat_concat_horizontal), TEST_FUNCTION(fmpz_mat_concat_vertical), TEST_FUNCTION(fmpz_mat_content), TEST_FUNCTION(fmpz_mat_CRT_ui), TEST_FUNCTION(fmpz_mat_CRT_ui_unsigned), TEST_FUNCTION(fmpz_mat_det_bound), TEST_FUNCTION(fmpz_mat_det), TEST_FUNCTION(fmpz_mat_det_divisor), TEST_FUNCTION(fmpz_mat_det_modular_accelerated), TEST_FUNCTION(fmpz_mat_det_modular), TEST_FUNCTION(fmpz_mat_entry), TEST_FUNCTION(fmpz_mat_equal), TEST_FUNCTION(fmpz_mat_fmpz_vec_mul), TEST_FUNCTION(fmpz_mat_get_d_mat), TEST_FUNCTION(fmpz_mat_get_d_mat_transpose), TEST_FUNCTION(fmpz_mat_get_nmod_mat), TEST_FUNCTION(fmpz_mat_gram), TEST_FUNCTION(fmpz_mat_hadamard), TEST_FUNCTION(fmpz_mat_hnf), TEST_FUNCTION(fmpz_mat_hnf_classical), TEST_FUNCTION(fmpz_mat_hnf_minors), TEST_FUNCTION(fmpz_mat_hnf_minors_transform), TEST_FUNCTION(fmpz_mat_hnf_modular), TEST_FUNCTION(fmpz_mat_hnf_modular_eldiv), TEST_FUNCTION(fmpz_mat_hnf_pernet_stein), TEST_FUNCTION(fmpz_mat_hnf_transform), TEST_FUNCTION(fmpz_mat_hnf_xgcd), TEST_FUNCTION(fmpz_mat_howell_form_mod), TEST_FUNCTION(fmpz_mat_init_clear), TEST_FUNCTION(fmpz_mat_inv), TEST_FUNCTION(fmpz_mat_invert_rows_cols), TEST_FUNCTION(fmpz_mat_is_empty), TEST_FUNCTION(fmpz_mat_is_one), TEST_FUNCTION(fmpz_mat_is_spd), TEST_FUNCTION(fmpz_mat_is_square), TEST_FUNCTION(fmpz_mat_is_zero), TEST_FUNCTION(fmpz_mat_kronecker_product), TEST_FUNCTION(fmpz_mat_lll_original), TEST_FUNCTION(fmpz_mat_lll_storjohann), TEST_FUNCTION(fmpz_mat_max_bits), TEST_FUNCTION(fmpz_mat_minpoly), TEST_FUNCTION(fmpz_mat_mul_blas), TEST_FUNCTION(fmpz_mat_mul), TEST_FUNCTION(fmpz_mat_mul_classical), TEST_FUNCTION(fmpz_mat_mul_double_word), TEST_FUNCTION(fmpz_mat_mul_fft), TEST_FUNCTION(fmpz_mat_mul_fmpz_vec), TEST_FUNCTION(fmpz_mat_mul_multi_mod), TEST_FUNCTION(fmpz_mat_mul_small), TEST_FUNCTION(fmpz_mat_mul_strassen), TEST_FUNCTION(fmpz_mat_mul_waksman), TEST_FUNCTION(fmpz_mat_multi_CRT_ui), TEST_FUNCTION(fmpz_mat_multi_CRT_ui_unsigned), TEST_FUNCTION(fmpz_mat_nullspace), TEST_FUNCTION(fmpz_mat_one), TEST_FUNCTION(fmpz_mat_pow), TEST_FUNCTION(fmpz_mat_print_read), TEST_FUNCTION(fmpz_mat_rank), TEST_FUNCTION(fmpz_mat_rref), TEST_FUNCTION(fmpz_mat_rref_fflu), TEST_FUNCTION(fmpz_mat_rref_mul), TEST_FUNCTION(fmpz_mat_scalar_addmul_fmpz), TEST_FUNCTION(fmpz_mat_scalar_addmul_nmod_mat_fmpz), TEST_FUNCTION(fmpz_mat_scalar_addmul_nmod_mat_ui), TEST_FUNCTION(fmpz_mat_scalar_addmul_si), TEST_FUNCTION(fmpz_mat_scalar_addmul_ui), TEST_FUNCTION(fmpz_mat_scalar_mod_fmpz), TEST_FUNCTION(fmpz_mat_scalar_mul_2exp), TEST_FUNCTION(fmpz_mat_scalar_mul_fmpz), TEST_FUNCTION(fmpz_mat_scalar_mul_si), TEST_FUNCTION(fmpz_mat_scalar_mul_ui), TEST_FUNCTION(fmpz_mat_scalar_smod), TEST_FUNCTION(fmpz_mat_snf_diagonal), TEST_FUNCTION(fmpz_mat_snf_iliopoulos), TEST_FUNCTION(fmpz_mat_snf_kannan_bachem), TEST_FUNCTION(fmpz_mat_solve_bound), TEST_FUNCTION(fmpz_mat_solve), TEST_FUNCTION(fmpz_mat_solve_cramer), TEST_FUNCTION(fmpz_mat_solve_dixon), TEST_FUNCTION(fmpz_mat_solve_dixon_den), TEST_FUNCTION(fmpz_mat_solve_fflu), TEST_FUNCTION(fmpz_mat_solve_multi_mod_den), TEST_FUNCTION(fmpz_mat_sqr), TEST_FUNCTION(fmpz_mat_trace), TEST_FUNCTION(fmpz_mat_transpose), TEST_FUNCTION(fmpz_mat_window_init_clear), TEST_FUNCTION(fmpz_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mat/test/t-CRT_ui.c000066400000000000000000000052001461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_CRT_ui, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong bits, prime_bits, rows, cols, num_primes, j; fmpz_t mod; fmpz_mat_t A, B, C; nmod_mat_t Amod; mp_limb_t primes[1000]; bits = n_randint(state, 500) + 1; rows = n_randint(state, 10); cols = n_randint(state, 10); prime_bits = 1 + n_randint(state, FLINT_BITS - 1); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); fmpz_mat_randtest(A, state, bits); fmpz_init(mod); num_primes = 0; primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); fmpz_set_ui(mod, primes[0]); /* + 1 for sign */ while (fmpz_bits(mod) <= bits + 1) { primes[num_primes + 1] = n_nextprime(primes[num_primes], 0); fmpz_mul_ui(mod, mod, primes[num_primes + 1]); num_primes++; } num_primes++; nmod_mat_init(Amod, rows, cols, primes[0]); fmpz_mat_get_nmod_mat(Amod, A); fmpz_mat_set_nmod_mat(B, Amod); fmpz_set_ui(mod, primes[0]); for (j = 1; j < num_primes; j++) { nmod_mat_clear(Amod); nmod_mat_init(Amod, rows, cols, primes[j]); fmpz_mat_get_nmod_mat(Amod, A); fmpz_mat_CRT_ui(B, B, mod, Amod, 1); fmpz_mul_ui(mod, mod, primes[j]); } if (!fmpz_mat_equal(B, A)) { flint_printf("FAIL!\n"); flint_printf("primes: "); for (j = 0; j < num_primes; j++) flint_printf("%wu ", primes[j]); flint_printf("\nA: \n"); fmpz_mat_print_pretty(A); flint_printf("\nB: \n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_mat_clear(Amod); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-CRT_ui_unsigned.c000066400000000000000000000051741461254215100216530ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_CRT_ui_unsigned, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong bits, prime_bits, rows, cols, num_primes, j; fmpz_t mod; fmpz_mat_t A, B, C; nmod_mat_t Amod; mp_limb_t primes[1000]; bits = n_randint(state, 500) + 1; rows = n_randint(state, 10); cols = n_randint(state, 10); prime_bits = 1 + n_randint(state, FLINT_BITS - 1); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); fmpz_mat_randtest_unsigned(A, state, bits); fmpz_init(mod); num_primes = 0; primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); fmpz_set_ui(mod, primes[0]); while (fmpz_bits(mod) <= bits) { primes[num_primes + 1] = n_nextprime(primes[num_primes], 0); fmpz_mul_ui(mod, mod, primes[num_primes + 1]); num_primes++; } num_primes++; nmod_mat_init(Amod, rows, cols, primes[0]); fmpz_mat_get_nmod_mat(Amod, A); fmpz_mat_set_nmod_mat_unsigned(B, Amod); fmpz_set_ui(mod, primes[0]); for (j = 1; j < num_primes; j++) { nmod_mat_clear(Amod); nmod_mat_init(Amod, rows, cols, primes[j]); fmpz_mat_get_nmod_mat(Amod, A); fmpz_mat_CRT_ui(B, B, mod, Amod, 0); fmpz_mul_ui(mod, mod, primes[j]); } if (!fmpz_mat_equal(B, A)) { flint_printf("FAIL!\n"); flint_printf("primes: "); for (j = 0; j < num_primes; j++) flint_printf("%wu ", primes[j]); flint_printf("\nA: \n"); fmpz_mat_print_pretty(A); flint_printf("\nB: \n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_mat_clear(Amod); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-add_sub.c000066400000000000000000000024171461254215100202300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_add_sub, state) { slong m, n, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mat_t A; fmpz_mat_t B; fmpz_mat_t C; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(C, m, n); fmpz_mat_randtest(A, state, 100); fmpz_mat_randtest(B, state, 100); fmpz_mat_neg(C, A); fmpz_mat_add(A, A, B); fmpz_mat_sub(A, A, B); fmpz_mat_neg(A, A); if (!fmpz_mat_equal(A, C)) { flint_printf("FAIL: matrices not equal!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-can_solve_fflu.c000066400000000000000000000077741461254215100216270ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_can_solve_fflu, state) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, k; int success; /* test random systems (likely not soluble) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); fmpz_mat_init(A, m, k); fmpz_mat_init(B, m, n); fmpz_mat_init(X, k, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_can_solve_fflu(X, den, A, B); if (success) { fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); } if (success && !fmpz_mat_equal(AX, B)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } /* test random soluble systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); fmpz_mat_init(A, m, k); fmpz_mat_init(B, m, n); fmpz_mat_init(X, k, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(X, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); fmpz_mat_mul(B, A, X); fmpz_randtest_not_zero(den, state, 20); fmpz_mat_scalar_mul_fmpz(A, A, den); success = fmpz_mat_can_solve_fflu(X, den, A, B); if (success) { fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); } if (!success || !fmpz_mat_equal(AX, B)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-can_solve_multi_mod_den.c000066400000000000000000000100251461254215100234710ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_can_solve_multi_mod_den, state) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, k; int success; /* test random systems (likely not soluble) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); fmpz_mat_init(A, m, k); fmpz_mat_init(B, m, n); fmpz_mat_init(X, k, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_can_solve_multi_mod_den(X, den, A, B); if (success) { fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); } if (success && !fmpz_mat_equal(AX, B)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } /* test random soluble systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); fmpz_mat_init(A, m, k); fmpz_mat_init(B, m, n); fmpz_mat_init(X, k, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(X, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); fmpz_mat_mul(B, A, X); fmpz_randtest_not_zero(den, state, 20); fmpz_mat_scalar_mul_fmpz(A, A, den); success = fmpz_mat_can_solve_multi_mod_den(X, den, A, B); if (success) { fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); } if (!success || !fmpz_mat_equal(AX, B)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-charpoly.c000066400000000000000000000061541461254215100204520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_charpoly, state) { slong m, n, rep, i; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mat_t A, B, C, D; fmpz_poly_t f, g; m = n_randint(state, 4); n = m; fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(C, m, m); fmpz_mat_init(D, n, n); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_mat_randtest(A, state, 10); fmpz_mat_randtest(B, state, 10); fmpz_mat_mul(C, A, B); fmpz_mat_mul(D, B, A); fmpz_mat_charpoly(f, C); fmpz_mat_charpoly(g, D); if (!fmpz_poly_equal(f, g)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), fmpz_mat_print(A), flint_printf("\n"); flint_printf("Matrix B:\n"), fmpz_mat_print(B), flint_printf("\n"); flint_printf("cp(AB) = "), fmpz_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(BA) = "), fmpz_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); fmpz_poly_clear(f); fmpz_poly_clear(g); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_t c; fmpz_mat_t A, B; fmpz_poly_t f, g; m = n_randint(state, 4); n = m; fmpz_init(c); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_mat_randtest(A, state, 10); fmpz_mat_set(B, A); for (i = 0; i < 10; i++) { fmpz_randtest(c, state, 5); fmpz_mat_similarity(B, n_randint(state, m), c); } fmpz_mat_charpoly(f, A); fmpz_mat_charpoly(g, B); if (!fmpz_poly_equal(f, g)) { flint_printf("FAIL: charpoly(A) != charpoly(P^{-1}AP).\n"); flint_printf("Matrix A:\n"), fmpz_mat_print(A), flint_printf("\n"); flint_printf("Matrix P^{-1}AP:\n"), fmpz_mat_print(B), flint_printf("\n"); flint_printf("cp(A) = "), fmpz_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(P^{-1}AP) = "), fmpz_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-charpoly_berkowitz.c000066400000000000000000000062361461254215100225530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_mat_charpoly_berkowitz, state) { slong m, n, rep, i; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mat_t A, B, C, D; fmpz_poly_t f, g; m = n_randint(state, 4); n = m; fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(C, m, m); fmpz_mat_init(D, n, n); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_mat_randtest(A, state, 10); fmpz_mat_randtest(B, state, 10); fmpz_mat_mul(C, A, B); fmpz_mat_mul(D, B, A); fmpz_mat_charpoly_berkowitz(f, C); fmpz_mat_charpoly_berkowitz(g, D); if (!fmpz_poly_equal(f, g)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), fmpz_mat_print(A), flint_printf("\n"); flint_printf("Matrix B:\n"), fmpz_mat_print(B), flint_printf("\n"); flint_printf("cp(AB) = "), fmpz_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(BA) = "), fmpz_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); fmpz_poly_clear(f); fmpz_poly_clear(g); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_t c; fmpz_mat_t A, B; fmpz_poly_t f, g; m = n_randint(state, 4); n = m; fmpz_init(c); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_mat_randtest(A, state, 10); fmpz_mat_set(B, A); for (i = 0; i < 10; i++) { fmpz_randtest(c, state, 5); fmpz_mat_similarity(B, n_randint(state, m), c); } fmpz_mat_charpoly_berkowitz(f, A); fmpz_mat_charpoly_berkowitz(g, B); if (!fmpz_poly_equal(f, g)) { flint_printf("FAIL: charpoly(A) != charpoly(P^{-1}AP).\n"); flint_printf("Matrix A:\n"), fmpz_mat_print(A), flint_printf("\n"); flint_printf("Matrix P^{-1}AP:\n"), fmpz_mat_print(B), flint_printf("\n"); flint_printf("cp(A) = "), fmpz_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(P^{-1}AP) = "), fmpz_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-chol_d.c000066400000000000000000000033011461254215100200500ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #define FMPZ_MAT_CHOL_EPS (1.0E-9) TEST_FUNCTION_START(fmpz_mat_chol_d, state) { int i; /* check RR^T = A */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; d_mat_t R, Rt, Atmp, Btmp; slong m; m = n_randint(state, 10); fmpz_mat_init(A, m, m); d_mat_init(R, m, m); d_mat_init(Rt, m, m); d_mat_init(Atmp, m, m); d_mat_init(Btmp, m, m); fmpz_mat_randtest(A, state, 10); fmpz_mat_gram(A, A); fmpz_mat_get_d_mat(Atmp, A); d_mat_zero(R); fmpz_mat_chol_d(R, A); d_mat_transpose(Rt, R); d_mat_mul_classical(Btmp, R, Rt); if (!d_mat_approx_equal(Atmp, Btmp, FMPZ_MAT_CHOL_EPS)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_mat_print_pretty(A); flint_printf("R:\n"); d_mat_print(R); flint_printf("R^T:\n"); d_mat_print(Rt); flint_printf("Btmp:\n"); d_mat_print(Btmp); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); d_mat_clear(R); d_mat_clear(Rt); d_mat_clear(Atmp); d_mat_clear(Btmp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-col_partition.c000066400000000000000000000047161461254215100215010ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_col_partition, state) { int result = 0; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B; slong m, n, j, k, p1 = 1, p2; slong * part; m = n_randint(state, 20) + 1; n = n_randint(state, 20) + 1; part = (slong *) flint_malloc(m*sizeof(slong)); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, m); /* set first row */ for (j = 0; j < n; j++) fmpz_randtest(A->rows[0] + j, state, 100); /* ensure row is distinct */ fmpz_set_ui(A->rows[0] + n_randint(state, n), 0); /* fill remaining rows */ for (k = 1; k < m; k++) { if (n_randint(state, 2) == 0) { /* random row */ for (j = 0; j < n; j++) fmpz_randtest(A->rows[k] + j, state, 100); /* ensure row is distinct */ fmpz_set_ui(A->rows[k] + n_randint(state, n), k); p1++; } else { /* same as last row */ for (j = 0; j < n; j++) fmpz_set(A->rows[k] + j, A->rows[k - 1] + j); } } /* swap random rows */ for (k = 0; k < m; k++) { slong r1 = n_randint(state, m); slong r2 = n_randint(state, m); fmpz * t = A->rows[r1]; A->rows[r1] = A->rows[r2]; A->rows[r2] = t; } /* transpose so rows are now columns */ fmpz_mat_transpose(B, A); /* check partition is correct */ p2 = fmpz_mat_col_partition(part, B, 1); result = (p1 > n || p2 == p1); if (!result) { flint_printf("FAIL: col_partition failed\n"); flint_printf("m = %ld, n = %ld, p1 = %ld, p2 = %ld\n", m, n, p1, p2); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); flint_free(part); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-concat_horizontal.c000066400000000000000000000031341461254215100223440ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_concat_horizontal, state) { fmpz_mat_t A, B, C; fmpz_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong c1, c2, r1; c1 = n_randint(state, 50); c2 = n_randint(state, 50); r1 = n_randint(state, 50); fmpz_mat_init(A, r1, c1); fmpz_mat_init(B, r1, c2); fmpz_mat_init(C, r1, (c1+c2)); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); fmpz_mat_concat_horizontal(C, A, B); fmpz_mat_window_init(window1, C, 0, 0, r1, c1); fmpz_mat_window_init(window2, C, 0, c1, r1, (c1+c2)); if (!(fmpz_mat_equal(window1, A) && fmpz_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_window_clear(window1); fmpz_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-concat_vertical.c000066400000000000000000000031301461254215100217600ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_concat_vertical, state) { fmpz_mat_t A, B, C; fmpz_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong r1, r2, c1; r1 = n_randint(state, 50); r2 = n_randint(state, 50); c1 = n_randint(state, 50); fmpz_mat_init(A, r1, c1); fmpz_mat_init(B, r2, c1); fmpz_mat_init(C, (r1+r2), c1); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); fmpz_mat_concat_vertical(C, A, B); fmpz_mat_window_init(window1, C, 0, 0, r1, c1); fmpz_mat_window_init(window2, C, r1, 0, (r1+r2), c1); if (!(fmpz_mat_equal(window1, A) && fmpz_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_window_clear(window1); fmpz_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-content.c000066400000000000000000000026231461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2015 Dharak Kharod This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_content, state) { int i; fmpz_mat_t A,B; fmpz_t scalar, gcd_mat, temp; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong r, c; r = n_randint(state, 50); c = n_randint(state, 50); fmpz_mat_init(A, r, c); fmpz_mat_init(B, r, c); fmpz_init(scalar); fmpz_init(gcd_mat); fmpz_init(temp); fmpz_mat_randtest(B, state, 100); fmpz_mat_content(gcd_mat, B); if (r == 0 || c == 0) { if (fmpz_is_zero(gcd_mat)) { goto cleanup; } else { flint_printf("FAIL!\n"); flint_abort(); } } fmpz_randtest_not_zero(scalar, state, 50); fmpz_mat_scalar_mul_fmpz(A, B, scalar); fmpz_mat_content(temp, A); fmpz_mul(gcd_mat, gcd_mat, scalar); if (fmpz_cmpabs(gcd_mat, temp) != 0) { flint_printf("FAIL!\n"); flint_abort(); } cleanup: fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(scalar); fmpz_clear(temp); fmpz_clear(gcd_mat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-det.c000066400000000000000000000040411461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_det, state) { slong ix; for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { slong m; fmpz_mat_t A; fmpz_t det, result; ulong is_small, is_singular; is_singular = n_randint(state, 2); is_small = n_randint(state, 20); m = n_randint(state, 10); if (is_singular) m += 2; if (!is_small) m += 60; /* Generate last conditional in fmpz_det source code */ fmpz_mat_init(A, m, m); fmpz_init(det); fmpz_init(result); if (is_singular) { fmpz_zero(det); fmpz_mat_randrank(A, state, 1 + n_randint(state, m - 1), 1 + n_randint(state, 10)); fmpz_mat_randops(A, state, n_randint(state, 2 * m * m + 1)); } else { if (m) fmpz_randtest(det, state, 30); else fmpz_set_ui(det, UWORD(1)); fmpz_mat_randdet(A, state, det); fmpz_mat_randops(A, state, n_randint(state, 2*m*m + 1)); } fmpz_mat_det(result, A); if (!fmpz_equal(det, result)) { flint_printf("FAIL:\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("expected: "), fmpz_print(det), flint_printf("\n"); flint_printf("ncomputed: "), fmpz_print(result), flint_printf("\n"); flint_abort(); } fmpz_mat_clear(A); fmpz_clear(det); fmpz_clear(result); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-det_bound.c000066400000000000000000000025621461254215100205730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_det_bound, state) { fmpz_mat_t A; slong i, m; fmpz_t det, bound; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_init(det); fmpz_init(bound); fmpz_mat_randtest(A, state, 1+n_randint(state,200)); fmpz_mat_det(det, A); fmpz_mat_det_bound(bound, A); if (fmpz_cmp(det, bound) > 0) { flint_printf("FAIL:\n"); flint_printf("bound too small!\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("det: "), fmpz_print(det), flint_printf("\n"); flint_printf("bound: "), fmpz_print(bound), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(det); fmpz_clear(bound); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-det_divisor.c000066400000000000000000000037421461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_det_divisor, state) { slong i; int result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; fmpz_t det, d, q, r; slong m, bits; m = n_randint(state, 15); bits = 1 + n_randint(state, 50); fmpz_init(det); fmpz_init(d); fmpz_init(q); fmpz_init(r); fmpz_mat_init(A, m, m); if (i % 3 == 0 && m > 1) { /* Generate a nontrivial singular matrix */ fmpz_mat_randrank(A, state, 1 + n_randint(state, m - 1), bits); fmpz_mat_randops(A, state, n_randint(state, 2*m*m + 1)); } else { fmpz_mat_randtest(A, state, bits); } fmpz_mat_det_divisor(d, A); fmpz_mat_det_bareiss(det, A); if (fmpz_is_zero(det) || fmpz_is_zero(d)) { result = fmpz_equal(det, d); } else { fmpz_fdiv_qr(q, r, det, d); result = fmpz_is_zero(r) && (fmpz_sgn(d) > 0); } if (!result) { flint_printf("FAIL:\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("det: "); fmpz_print(det); flint_printf("\n"); flint_printf("d: "); fmpz_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_clear(det); fmpz_clear(d); fmpz_clear(q); fmpz_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-det_modular.c000066400000000000000000000042631461254215100211270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_det_modular, state) { fmpz_mat_t A; slong i, m; fmpz_t det1, det2; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int proved = n_randlimb(state) % 2; m = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_init(det1); fmpz_init(det2); fmpz_mat_randtest(A, state, 1+n_randint(state,200)); fmpz_mat_det_bareiss(det1, A); fmpz_mat_det_modular(det2, A, proved); if (!fmpz_equal(det1, det2)) { flint_printf("FAIL:\n"); flint_printf("different determinants!\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("det1: "), fmpz_print(det1), flint_printf("\n"); flint_printf("det2: "), fmpz_print(det2), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(det1); fmpz_clear(det2); fmpz_mat_clear(A); } for (i = 0; i < 10000; i++) { int proved = n_randlimb(state) % 2; m = 2 + n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_init(det2); fmpz_mat_randrank(A, state, 1+n_randint(state, m - 1), 1+n_randint(state, 10)); fmpz_mat_randops(A, state, n_randint(state, 2*m*m + 1)); fmpz_mat_det_modular(det2, A, proved); if (!fmpz_is_zero(det2)) { flint_printf("FAIL:\n"); flint_printf("expected zero determinant!\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_clear(det2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-det_modular_accelerated.c000066400000000000000000000043271461254215100234440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_det_modular_accelerated, state) { fmpz_mat_t A; slong i, m; fmpz_t det1, det2; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int proved = n_randlimb(state) % 2; m = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_init(det1); fmpz_init(det2); fmpz_mat_randtest(A, state, 1+n_randint(state,200)); fmpz_mat_det_bareiss(det1, A); fmpz_mat_det_modular_accelerated(det2, A, proved); if (!fmpz_equal(det1, det2)) { flint_printf("FAIL:\n"); flint_printf("different determinants!\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("det1: "), fmpz_print(det1), flint_printf("\n"); flint_printf("det2: "), fmpz_print(det2), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(det1); fmpz_clear(det2); fmpz_mat_clear(A); } for (i = 0; i < 10000; i++) { int proved = n_randlimb(state) % 2; m = 2 + n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_init(det2); fmpz_mat_randrank(A, state, 1+n_randint(state, m - 1), 1+n_randint(state, 10)); fmpz_mat_randops(A, state, n_randint(state, 2*m*m + 1)); fmpz_mat_det_modular_accelerated(det2, A, proved); if (!fmpz_is_zero(det2)) { flint_printf("FAIL:\n"); flint_printf("expected zero determinant!\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_clear(det2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-entry.c000066400000000000000000000025661461254215100177750ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_entry, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t a; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(a, rows, cols); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { fmpz_set_ui(fmpz_mat_entry(a,j,k), 3*j + 7*k); } } for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { if (fmpz_get_ui(fmpz_mat_entry(a,j,k)) != 3*j + 7*k) { flint_printf("FAIL: get/set entry %wd,%wd\n", j, k); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-equal.c000066400000000000000000000035111461254215100177320ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_equal, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C, D, E; slong m, n, j; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(C, m, n); fmpz_mat_init(D, m+1, n); fmpz_mat_init(E, m, n+1); if (fmpz_mat_equal(A, D) || fmpz_mat_equal(A, E)) { flint_printf("FAIL: different dimensions should not be equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_randtest(A, state, 1 + n_randint(state, 100)); fmpz_mat_set(B, A); if (!fmpz_mat_equal(A, B)) { flint_printf("FAIL: copied matrices should be equal\n"); fflush(stdout); flint_abort(); } if (m && n) { j = n_randint(state, m*n); fmpz_add_ui(A->entries + j, A->entries + j, 1); if (fmpz_mat_equal(A, B)) { flint_printf("FAIL: modified matrices should not be equal\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); fmpz_mat_clear(E); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-fmpz_vec_mul.c000066400000000000000000000051461461254215100213170ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_fmpz_vec_mul, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; fmpz * a, * c; fmpz ** aa, ** cc; slong j, m, n, alen; m = n_randint(state, 50); n = n_randint(state, 50); alen = n_randint(state, 50); fmpz_mat_init(C, 1, n); fmpz_mat_init(A, 1, m); fmpz_mat_init(B, m, n); c = _fmpz_vec_init(n); a = _fmpz_vec_init(alen); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); _fmpz_vec_randtest(c, state, n, n_randint(state, 200) + 1); _fmpz_vec_randtest(a, state, alen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(n, fmpz*); for (j = 0; j < n; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(cc[j], c + j); } aa = FLINT_ARRAY_ALLOC(alen, fmpz*); for (j = 0; j < alen; j++) { aa[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(aa[j], a + j); } fmpz_mat_fmpz_vec_mul(c, a, alen, B); fmpz_mat_fmpz_vec_mul_ptr(cc, (const fmpz * const *)aa, alen, B); /* supposed to match mul of the chopped or zero-extended a */ for (j = 0; j < m && j < alen; j++) fmpz_set(fmpz_mat_entry(A, 0, j), a + j); fmpz_mat_mul(C, A, B); for (j = 0; j < n; j++) { if (!fmpz_equal(fmpz_mat_entry(C, 0, j), c + j) || !fmpz_equal(fmpz_mat_entry(C, 0, j), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); _fmpz_vec_clear(c, n); _fmpz_vec_clear(a, alen); for (j = 0; j < n; j++) { fmpz_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < alen; j++) { fmpz_clear(aa[j]); flint_free(aa[j]); } flint_free(aa); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-get_d_mat.c000066400000000000000000000033021461254215100205440ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_get_d_mat, state) { int i; /* set entries of an fmpz_mat, convert to d_mat and then check that the entries remain same */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; d_mat_t B; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); d_mat_init(B, rows, cols); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { fmpz_set_ui(fmpz_mat_entry(A, j, k), 3 * j + 7 * k); } } fmpz_mat_get_d_mat(B, A); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { if (d_mat_entry(B, j, k) != 3 * j + 7 * k) { flint_printf("FAIL: j = %wd, k = %wd\n", j, k); fmpz_mat_print_pretty(A); d_mat_print(B); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(A); d_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-get_d_mat_transpose.c000066400000000000000000000033261461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_get_d_mat_transpose, state) { int i; /* set entries of an fmpz_mat, convert to d_mat and then check that the entries remain same */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; d_mat_t B; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); d_mat_init(B, cols, rows); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { fmpz_set_ui(fmpz_mat_entry(A, j, k), 3 * j + 7 * k); } } fmpz_mat_get_d_mat_transpose(B, A); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { if (d_mat_entry(B, k, j) != 3 * j + 7 * k) { flint_printf("FAIL: j = %wd, k = %wd\n", j, k); fmpz_mat_print_pretty(A); d_mat_print(B); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(A); d_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-get_nmod_mat.c000066400000000000000000000027401461254215100212630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_get_nmod_mat, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; nmod_mat_t M, M2; slong rows, cols; mp_limb_t mod; rows = n_randint(state, 50); cols = n_randint(state, 50); mod = n_randtest_prime(state, 0); nmod_mat_init(M, rows, cols, mod); nmod_mat_init(M2, rows, cols, mod); fmpz_mat_init(A, rows, cols); nmod_mat_randtest(M, state); if (i % 2 == 0) fmpz_mat_set_nmod_mat(A, M); else fmpz_mat_set_nmod_mat_unsigned(A, M); fmpz_mat_scalar_mul_ui(A, A, UWORD(2)); nmod_mat_add(M, M, M); fmpz_mat_get_nmod_mat(M2, A); if (!nmod_mat_equal(M, M2)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); nmod_mat_clear(M); nmod_mat_clear(M2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-gram.c000066400000000000000000000023571461254215100175600ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_gram, state) { fmpz_mat_t A, B, C, D; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n; m = n_randint(state, 50); n = n_randint(state, 50); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, m); fmpz_mat_init(C, m, m); fmpz_mat_init(D, m, m); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_transpose(B, A); fmpz_mat_mul(C, A, B); fmpz_mat_gram(D, A); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hadamard.c000066400000000000000000000030171461254215100203650ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" int should_have_hadamard(int n) { if (n <= 2) return 1; if (n % 4 != 0) return 0; if (n <= 300 && n != 92 && n != 116 && n != 156 && n != 172 && n != 184 && n != 188 && n != 232 && n != 236 && n != 260 && n != 268 && n != 292) return 1; return 0; } TEST_FUNCTION_START(fmpz_mat_hadamard, state) { int n; for (n = 0; n <= 300; n++) { fmpz_mat_t h; int success; fmpz_mat_init(h, n, n); success = fmpz_mat_hadamard(h); if (success) { if (!fmpz_mat_is_hadamard(h)) { printf("FAIL: output is not a Hadamard matrix\n"); printf("n = %d\n\n", n); fmpz_mat_print_pretty(h); printf("\n\n"); fflush(stdout); flint_abort(); } } else if (should_have_hadamard(n)) { printf("FAIL: expected Hadamard matrix of size %d to work\n\n", n); fflush(stdout); flint_abort(); } fmpz_mat_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf.c000066400000000000000000000106471461254215100174060ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf, state) { slong iter; /* matrices of random rank */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { fmpz_mat_t A, B, H, H2; slong m, n, r, b, d; int equal; n = 1 + n_randint(state, 30); m = 1 + n_randint(state, 30); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf(H, A); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf(H2, H); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); } /* matrices with random entries */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { fmpz_mat_t A, B, H, H2; slong m, n, b; int equal; n = 1 + n_randint(state, 30); m = 1 + n_randint(state, 30); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); b = 1 + n_randint(state, 8) * n_randint(state, 8); fmpz_mat_randtest(A, state, b); fmpz_mat_hnf(H, A); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf(H2, H); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_classical.c000066400000000000000000000040341461254215100214150ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_classical, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, H, H2; slong m, n, b, d, r; int equal; m = n_randint(state, 10); n = n_randint(state, 10); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf_classical(H, A); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, H); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_minors.c000066400000000000000000000046771461254215100210030ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_minors, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, H, H2; slong m, n, b, d; int equal; n = n_randint(state, 10); m = n + n_randint(state, 10); fmpz_mat_init(A, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); fmpz_mat_randrank(A, state, n, b); /* dense */ d = n_randint(state, 2*m*n + 1); if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf_minors(H, A); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_minors(H2, H); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_minors_transform.c000066400000000000000000000052171461254215100230650ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_minors_transform, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, H, H2, U, UA; slong m, n, b, d; int equal; n = n_randint(state, 10); m = n + n_randint(state, 10); fmpz_mat_init(A, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); fmpz_mat_init(U, m, m); fmpz_mat_init(UA, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); fmpz_mat_randrank(A, state, n, b); /* dense */ d = n_randint(state, 2*m*n + 1); if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf_minors_transform(H, U, A); fmpz_mat_mul(UA, U, A); if (!fmpz_mat_is_in_hnf(H) || !fmpz_mat_equal(UA, H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_minors(H2, H); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(UA); fmpz_mat_clear(U); fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_modular.c000066400000000000000000000061461461254215100211300ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_modular, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { fmpz_t det; fmpz_mat_t A, B, H, H2; slong m, n, b, c, d, i, j; int equal; n = n_randint(state, 10); m = n + n_randint(state, 10); fmpz_init(det); fmpz_mat_init(A, n, n); fmpz_mat_init(B, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); fmpz_mat_randrank(A, state, n, b); fmpz_mat_det(det, A); c = 1 + n_randint(state, 10); fmpz_abs(det, det); fmpz_mul_ui(det, det, c); for (i = 0; i < n; i++) for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, i, j)); /* dense */ d = n_randint(state, 2*m*n + 1); if (n_randint(state, 2)) fmpz_mat_randops(B, state, d); fmpz_mat_hnf_modular(H, B, det); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, B); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fmpz_print(det); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_modular(H2, H, det); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); fmpz_clear(det); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_modular_eldiv.c000066400000000000000000000064401461254215100223100ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_modular_eldiv, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_t det; fmpz_mat_t A, B, H, H2; slong m, n, b, c, d, i, j; int equal; n = n_randint(state, 10); m = n + n_randint(state, 10); fmpz_init(det); fmpz_mat_init(A, n, n); fmpz_mat_init(B, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); fmpz_mat_randrank(A, state, n, b); fmpz_mat_det(det, A); c = 1 + n_randint(state, 10); fmpz_abs(det, det); fmpz_mul_ui(det, det, c); for (i = 0; i < n; i++) for (j = 0; j < n; j++) fmpz_set(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, i, j)); /* dense */ d = n_randint(state, 2*m*n + 1); if (n_randint(state, 2)) fmpz_mat_randops(B, state, d); fmpz_mat_set(H, B); fmpz_mat_hnf_modular_eldiv(H, det); fmpz_mat_hnf(H2, B); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); flint_printf("determinant:"); fmpz_print(det); flint_printf("\n\n"); fflush(stdout); flint_abort(); } equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fmpz_print(det); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_modular(H2, H, det); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); fmpz_clear(det); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_pernet_stein.c000066400000000000000000000110301461254215100221500ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_pernet_stein, state) { slong iter; /* matrices of random rank */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, B, H, H2; slong m, n, r, b, d; int equal; n = 1 + n_randint(state, 10); m = 1 + n_randint(state, 10); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf_pernet_stein(H, A, state); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_pernet_stein(H2, H, state); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); } /* matrices with random entries */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, B, H, H2; slong m, n, b; int equal; n = 1 + n_randint(state, 10); m = 1 + n_randint(state, 10); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); b = 1 + n_randint(state, 8) * n_randint(state, 8); fmpz_mat_randtest(A, state, b); fmpz_mat_hnf_pernet_stein(H, A, state); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_pernet_stein(H2, H, state); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_transform.c000066400000000000000000000135021461254215100214720ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_transform, state) { slong iter; /* Random rectangular matrices */ for (iter = 0; iter < 5000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, H, H2, U; fmpz_t det; slong m, n, b, d, r; int equal; m = n_randint(state, 10); n = n_randint(state, 10); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); fmpz_mat_init(U, m, m); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf_transform(H, U, A); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_init(det); fmpz_mat_det(det, U); if (!fmpz_is_pm1(det)) { flint_printf("FAIL:\n"); flint_printf("transformation matrices should have determinant +-1, U does not!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(U); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(det); fmpz_mat_mul(H2, U, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("multiplying by the transformation matrix should give the same HNF!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(U); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } /* Now matrices with full column rank */ for (iter = 0; iter < 5000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, H, H2, U; fmpz_t det; slong m, n, b, d, r; int equal; n = n_randint(state, 10); m = n + n_randint(state, 10); r = n; fmpz_mat_init(A, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); fmpz_mat_init(U, m, m); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf_transform(H, U, A); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_init(det); fmpz_mat_det(det, U); if (!fmpz_is_pm1(det)) { flint_printf("FAIL:\n"); flint_printf("transformation matrices should have determinant +-1, U does not!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(U); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(det); fmpz_mat_mul(H2, U, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("multiplying by the transformation matrix should give the same HNF!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(U); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-hnf_xgcd.c000066400000000000000000000050521461254215100204050ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_hnf_xgcd, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, H, H2, U; slong m, n, b, d, r; int equal; m = n_randint(state, 10); n = n_randint(state, 10); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(H, m, n); fmpz_mat_init(H2, m, n); fmpz_mat_init(U, m, m); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_hnf_xgcd(H, A); if (!fmpz_mat_is_in_hnf(H)) { flint_printf("FAIL:\n"); flint_printf("matrix not in hnf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_classical(H2, A); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnfs produced by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_hnf_xgcd(H2, H); equal = fmpz_mat_equal(H, H2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("hnf of a matrix in hnf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(H); flint_printf("\n\n"); fmpz_mat_print_pretty(H2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(U); fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-howell_form_mod.c000066400000000000000000000156001461254215100220010ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" int fmpz_mat_mod_is_in_howell_form(const fmpz_mat_t A, const fmpz_t mod) { slong *pivots; slong i, j, r; int numberpivots = 0; int prevrowzero = 0; fmpz * extra_row; fmpz_t g; if (fmpz_mat_is_empty(A)) return 1; pivots = flint_malloc(A->r * sizeof(slong)); if (!fmpz_mat_is_zero_row(A, 0)) { for (j = 0; j < A->c; j++) { if (!fmpz_is_zero(fmpz_mat_entry(A, 0, j))) { if (!fmpz_divisible(mod, fmpz_mat_entry(A, 0, j))) { flint_free(pivots); return 0; } pivots[numberpivots] = j; numberpivots++; break; } } } else { prevrowzero = 1; } for (i = 1; i < A->r; i++) { if (!fmpz_mat_is_zero_row(A, i)) { if (prevrowzero) { flint_free(pivots); return 0; } for (j = 0; j < A->c; j++) { if (!fmpz_is_zero(fmpz_mat_entry(A, i, j))) { if (j <= pivots[numberpivots - 1]) { flint_free(pivots); return 0; } if (!fmpz_divisible(mod, fmpz_mat_entry(A, i, j))) { flint_free(pivots); return 0; } pivots[numberpivots] = j; numberpivots++; j = A->c; } } } else { prevrowzero = 1; } } for (i = 1; i < numberpivots; i++) { for (j = 0; j < i; j++) { if (fmpz_cmp(fmpz_mat_entry(A, j, pivots[i]), fmpz_mat_entry(A, i, pivots[i])) >= 0) { flint_free(pivots); return 0; } } } extra_row = _fmpz_vec_init(A->c); fmpz_init(g); for (i = 0; i < numberpivots; i++) { fmpz_gcd(g, mod, fmpz_mat_entry(A, i, pivots[i])); fmpz_divexact(g, mod, g); _fmpz_vec_scalar_mul_fmpz(extra_row, A->rows[i], A->c, g); _fmpz_vec_scalar_mod_fmpz(extra_row, extra_row, A->c, mod); for ( j = pivots[i] + 1; j < A->c; j++) { if (!fmpz_is_zero(extra_row + j)) { for ( r = i; r < numberpivots; r++) { if (pivots[r] == j) { if (fmpz_divisible(extra_row + j, fmpz_mat_entry(A, r, pivots[r]))) { fmpz_divexact(g, extra_row + j, fmpz_mat_entry(A, r, pivots[r])); fmpz_neg(g, g); _fmpz_vec_scalar_addmul_fmpz(extra_row, A->rows[r], A->c, g); } } } } } _fmpz_vec_scalar_mod_fmpz(extra_row, extra_row, A->c, mod); if (!_fmpz_vec_is_zero(extra_row, A->c)) { _fmpz_vec_clear(extra_row, A->c); flint_free(pivots); fmpz_clear(g); return 0; } } _fmpz_vec_clear(extra_row, A->c); flint_free(pivots); fmpz_clear(g); return 1; } TEST_FUNCTION_START(fmpz_mat_howell_form_mod, state) { slong i; for (i = 0; i < 10000*flint_test_multiplier(); i++) { fmpz_mat_t A, B, D; fmpz_t mod; fmpz_t t, c; slong j, k, m, n, r1, r2; slong *perm; int equal; fmpz_init(mod); fmpz_init(t); fmpz_init(c); do { fmpz_randtest_unsigned(mod, state, 10); } while (fmpz_is_zero(mod)); m = n_randint(state, 20); do { n = n_randint(state, 20); } while (n > m); perm = _perm_init(2*m); fmpz_mat_init(A, m, n); fmpz_mat_init(D, 2*m, n); fmpz_mat_randtest(A, state, 10); fmpz_mat_init_set(B, A); r1 = fmpz_mat_howell_form_mod(B, mod); if (!fmpz_mat_mod_is_in_howell_form(B, mod)) { flint_printf("FAIL (malformed Howell form)\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); flint_printf("Modulus: "); fmpz_print(mod); flint_printf("\n\n"); fflush(stdout); flint_abort(); } _perm_randtest(perm, 2 * m, state); /* Concatenate the original matrix with the Howell form, scramble the rows, and check that the Howell form is the same */ for (j = 0; j < m; j++) { while (1) { fmpz_randtest_mod(c, state, mod); fmpz_gcd(t, c, mod); if (fmpz_is_one(t)) { break; } } for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(D, perm[j], k), fmpz_mat_entry(A, j, k), c); } for (j = 0; j < m; j++) { while (1) { fmpz_randtest_mod(c, state, mod); fmpz_gcd(t, c, mod); if (fmpz_is_one(t)) { break; } } for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(D, perm[m + j], k), fmpz_mat_entry(B, j, k), c); } r2 = fmpz_mat_howell_form_mod(D, mod); equal = (r1 == r2); if (equal) { for (j = 0; j < r1; j++) for (k = 0; k < n; k++) equal = equal && fmpz_equal(fmpz_mat_entry(B, j, k),fmpz_mat_entry(D, j, k)); for (j = r1; j < 2*m; j++) for (k = 0; k < n; k++) equal = equal && fmpz_is_zero(fmpz_mat_entry(D, j, k)); } if (!equal) { flint_printf("FAIL (r1 = %wd, r2 = %wd)!\n", r1, r2); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mat_print_pretty(D); flint_printf("\n\n"); flint_printf("Modulus: "); fmpz_print(mod); fflush(stdout); flint_abort(); } _perm_clear(perm); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(D); fmpz_clear(mod); fmpz_clear(t); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-init_clear.c000066400000000000000000000016341461254215100207400ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t a; slong j, k; slong rows = n_randint(state, 100); slong cols = n_randint(state, 100); fmpz_mat_init(a, rows, cols); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) fmpz_zero(a->rows[j] + k); fmpz_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-inv.c000066400000000000000000000076101461254215100174230ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_inv, state) { fmpz_mat_t A, B, C, I; fmpz_t den; slong i, j, m, r; { fmpz_t d; fmpz_mat_t A, B, C; fmpz_mat_init(A, 1, 1); fmpz_one(fmpz_mat_entry(A, 0, 0)); fmpz_mat_window_init(B, A, 0, 0, 1, 1); fmpz_mat_init(C, 1, 1); fmpz_init(d); fmpz_mat_inv(C, d, B); fmpz_clear(d); fmpz_mat_clear(C); fmpz_mat_window_clear(B); fmpz_mat_clear(A); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, m); fmpz_mat_init(I, m, m); fmpz_init(den); for (j = 0; j < m; j++) fmpz_set_ui(&I->rows[j][j], UWORD(1)); /* Verify that A * A^-1 = I for random matrices */ fmpz_mat_randrank(A, state, m, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense or sparse? */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); fmpz_mat_inv(B, den, A); fmpz_mat_mul(C, A, B); _fmpz_vec_scalar_divexact_fmpz(C->entries, C->entries, m*m, den); if (!fmpz_mat_equal(C, I)) { flint_printf("FAIL:\n"); flint_printf("A * A^-1 != I!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("A^-1:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("den(A^-1) = "), fmpz_print(den), flint_printf("\n"); flint_printf("A * A^-1:\n"), fmpz_mat_print_pretty(C), flint_printf("\n"); fflush(stdout); flint_abort(); } /* Test aliasing */ fmpz_mat_set(C, A); fmpz_mat_inv(A, den, A); fmpz_mat_mul(B, A, C); _fmpz_vec_scalar_divexact_fmpz(B->entries, B->entries, m*m, den); if (!fmpz_mat_equal(B, I)) { flint_printf("FAIL:\n"); flint_printf("aliasing failed!\n"); fmpz_mat_print(C); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(I); fmpz_clear(den); } /* Test singular matrices */ /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 10); r = n_randint(state, m); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, m); fmpz_init(den); fmpz_mat_randrank(A, state, r, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); fmpz_mat_inv(B, den, A); if (!fmpz_is_zero(den)) { flint_printf("FAIL:\n"); flint_printf("singular system gave nonzero denominator\n"); fflush(stdout); flint_abort(); } /* Aliasing */ fmpz_mat_inv(A, den, A); if (!fmpz_is_zero(den)) { flint_printf("FAIL:\n"); flint_printf("singular system gave nonzero denominator\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-invert_rows_cols.c000066400000000000000000000031111461254215100222200ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_invert_rows_cols, state) { slong n, rep; /* Rectangular inversion of rows and cols */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { slong i, j; fmpz_mat_t A, B; n = n_randint(state, 10); fmpz_mat_init(A, n, n); fmpz_mat_init(B, n, n); fmpz_mat_randtest(A, state, 1+n_randint(state, 3)); fmpz_mat_set(B, A); fmpz_mat_invert_rows(A, NULL); fmpz_mat_invert_cols(A, NULL); for (i = 0; i < A->r; i++) { for (j =0; j < A->c; j++) { if (fmpz_cmp(fmpz_mat_entry(B, i, j), fmpz_mat_entry(A, A->r - i - 1, A->c - j - 1)) != 0) { flint_printf("FAIL: B != A\n"); flint_printf("A:\n"); fmpz_mat_print_pretty(A); flint_printf("B:\n"); fmpz_mat_print_pretty(B); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(A); fmpz_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-is_empty.c000066400000000000000000000016571461254215100204650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_is_empty, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); if (fmpz_mat_is_empty(A) != (rows == 0 || cols == 0)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-is_one.c000066400000000000000000000023231461254215100200770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_is_one, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_one(A); if (!fmpz_mat_is_one(A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } if (rows && cols) { fmpz_mat_randbits(A, state, 100); if (fmpz_mat_is_one(A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-is_spd.c000066400000000000000000000040401461254215100201020ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_is_spd, state) { slong iter; /* Test: - fails for non-square matrices - fails for non-symmetric matrices - Gram matrices are positive definite iff full rank */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong n = n_randint(state, 10); slong rk; fmpz_mat_t A, B, C; slong j, k; int res; fmpz_mat_init(A, n, n + 1 + n_randint(state, 10)); fmpz_mat_init(B, n, n); fmpz_mat_init(C, n, n); fmpz_mat_one(A); if (fmpz_mat_is_spd(A)) { flint_printf("FAIL (square)\n"); flint_abort(); } fmpz_mat_randtest(B, state, 1 + n_randint(state, 200)); fmpz_mat_gram(B, B); if (n > 1) { fmpz_mat_set(C, B); j = n_randint(state, n - 1); k = j + 1 + n_randint(state, n - j - 1); fmpz_add_si(fmpz_mat_entry(C, j, k), fmpz_mat_entry(C, j, k), 1); if (fmpz_mat_is_spd(C)) { flint_printf("FAIL (symmetric)\n"); flint_abort(); } } rk = fmpz_mat_rank(B); res = fmpz_mat_is_spd(B); if ((rk < n && res) || (rk == n && !res)) { flint_printf("FAIL\n"); flint_printf("n = %wd, rk = %wd, res = %wd\n", n, rk, res); fmpz_mat_print_pretty(B); flint_printf("\n"); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-is_square.c000066400000000000000000000016471461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_is_square, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); if (fmpz_mat_is_square(A) != (rows == cols)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-is_zero.c000066400000000000000000000022601461254215100202750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_is_zero, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); if (!fmpz_mat_is_zero(A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } if (rows && cols) { fmpz_mat_randrank(A, state, FLINT_MIN(rows, cols), 100); if (fmpz_mat_is_zero(A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-kronecker_product.c000066400000000000000000000042631461254215100223530ustar00rootroot00000000000000/* Copyright (C) 2018 Martin Raum This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_kronecker_product, state) { int r, result; fmpz_mat_t A, B, C; fmpz_mat_t window1, window2; slong m, n, k, l, i, j; slong bits; for (r = 0; r < 100 * flint_test_multiplier(); r++) { m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); l = n_randint(state, 10); if ( m && n ) { i = n_randint(state, m); j = n_randint(state, n); } fmpz_mat_init(A, m, n); fmpz_mat_init(B, k, l); fmpz_mat_init(C, m*k, n*l); bits = 1 + n_randint(state, 100); fmpz_mat_randtest(A, state, bits); fmpz_mat_randtest(B, state, bits); fmpz_mat_kronecker_product(C, A, B); if ( m && n ) { fmpz_mat_window_init(window1, C, 0, 0, k, l); fmpz_mat_window_init(window2, C, i*k, j*l, (i+1)*k, (j+1)*l); fmpz_mat_scalar_mul_fmpz(window1, window1, fmpz_mat_entry(A, i, j)); fmpz_mat_scalar_mul_fmpz(window2, window2, fmpz_mat_entry(A, 0, 0)); result = fmpz_mat_equal(window1, window2); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_mat_print(A); flint_printf("B:\n"); fmpz_mat_print(B); flint_printf("C:\n"); fmpz_mat_print(C); flint_printf("i,j: %d,%d\n", i, j); fflush(stdout); flint_abort(); } fmpz_mat_window_clear(window1); fmpz_mat_window_clear(window2); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-lll_original.c000066400000000000000000000025351461254215100212770ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" TEST_FUNCTION_START(fmpz_mat_lll_original, state) { int i; /* check output basis is LLL reduced (randajtai used) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { int result; fmpz_mat_t A; fmpq_t delta, eta; slong m; m = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpq_init(delta); fmpq_init(eta); fmpq_set_si(delta, 3, 4); fmpq_set_si(eta, 1, 2); fmpz_mat_randajtai(A, state, 0.5); fmpz_mat_lll_original(A, delta, eta); result = fmpz_mat_is_reduced(A, 0.75, 0.5); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_mat_print_pretty(A); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpq_clear(delta); fmpq_clear(eta); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-lll_storjohann.c000066400000000000000000000025411461254215100216550ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "fmpq.h" TEST_FUNCTION_START(fmpz_mat_lll_storjohann, state) { int i; /* check output basis is LLL reduced (randajtai used) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { int result; fmpz_mat_t A; fmpq_t delta, eta; slong m; m = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpq_init(delta); fmpq_init(eta); fmpq_set_si(delta, 3, 4); fmpq_set_si(eta, 1, 2); fmpz_mat_randajtai(A, state, 0.5); fmpz_mat_lll_storjohann(A, delta, eta); result = fmpz_mat_is_reduced(A, 0.75, 0.5); if (!result) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_mat_print_pretty(A); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpq_clear(delta); fmpq_clear(eta); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-max_bits.c000066400000000000000000000021001461254215100204220ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_max_bits, state) { slong m, n, rep, res1, res2; for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { fmpz_mat_t A; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_randtest(A, state, 1 + n_randint(state, 100)); res1 = fmpz_mat_max_bits(A); res2 = _fmpz_vec_max_bits(A->entries, m*n); if (res1 != res2) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-minpoly.c000066400000000000000000000073501461254215100203170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_mat_minpoly, state) { slong m, n, rep, i, j; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_t c; fmpz_mat_t A; fmpz_poly_t f, g, q, r; m = n_randint(state, 4); n = m; fmpz_init(c); fmpz_mat_init(A, m, n); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_mat_randtest(A, state, 10); for (i = 0; i < n/2; i++) { for (j = 0; j < n/2; j++) { fmpz_zero(fmpz_mat_entry(A, i + n/2, j)); fmpz_zero(fmpz_mat_entry(A, i, j + n/2)); fmpz_set(fmpz_mat_entry(A, i + n/2, j + n/2), fmpz_mat_entry(A, i, j)); } } for (i = 0; i < 10; i++) { fmpz_randtest(c, state, 5); fmpz_mat_similarity(A, n_randint(state, m), c); } fmpz_mat_minpoly(f, A); fmpz_mat_charpoly(g, A); fmpz_poly_divrem(q, r, g, f); if (!fmpz_poly_is_zero(r)) { flint_printf("FAIL: minpoly(A) doesn't divide charpoly(A).\n"); flint_printf("Matrix A:\n"), fmpz_mat_print(A), flint_printf("\n"); flint_printf("mp(A) = "), fmpz_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(A) = "), fmpz_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_mat_clear(A); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_t c; fmpz_mat_t A, B; fmpz_poly_t f, g; m = n_randint(state, 4); n = m; fmpz_init(c); fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, n); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_mat_randtest(A, state, 10); for (i = 0; i < n/2; i++) { for (j = 0; j < n/2; j++) { fmpz_zero(fmpz_mat_entry(A, i + n/2, j)); fmpz_zero(fmpz_mat_entry(A, i, j + n/2)); fmpz_set(fmpz_mat_entry(A, i + n/2, j + n/2), fmpz_mat_entry(A, i, j)); } } fmpz_mat_set(B, A); for (i = 0; i < 10; i++) { fmpz_randtest(c, state, 5); fmpz_mat_similarity(B, n_randint(state, m), c); } fmpz_mat_minpoly(f, A); fmpz_mat_minpoly(g, B); if (!fmpz_poly_equal(f, g)) { flint_printf("FAIL: minpoly(A) != minpoly(P^{-1}AP).\n"); flint_printf("Matrix A:\n"), fmpz_mat_print(A), flint_printf("\n"); flint_printf("Matrix P^{-1}AP:\n"), fmpz_mat_print(B), flint_printf("\n"); flint_printf("mp(A) = "), fmpz_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("mp(P^{-1}AP) = "), fmpz_poly_print_pretty(g, "X"), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul.c000066400000000000000000000126311461254215100174230ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul, state) { fmpz_mat_t A, B, C, D; slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong m, n, k; slong abits, bbits, bits; if (n_randint(state, 10) == 0) { m = n_randint(state, 50); n = n_randint(state, 50); k = n_randint(state, 50); } else { m = n_randint(state, 8); n = n_randint(state, 8); k = n_randint(state, 8); } fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); abits = fmpz_mat_max_bits(A); bbits = fmpz_mat_max_bits(B); abits = FLINT_ABS(abits); bbits = FLINT_ABS(bbits); bits = abits + bbits + FLINT_BIT_COUNT(n) + 1; /* Make sure noise in the output is ok */ fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); fmpz_mat_mul(C, A, B); fmpz_mat_mul_classical(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fmpz_mat_print(C); flint_printf("\n\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (bits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_mat_mul_small_1(C, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal (mul_small_1)\n\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fmpz_mat_print(C); flint_printf("\n\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } if (abits <= SMALL_FMPZ_BITCOUNT_MAX && bbits <= SMALL_FMPZ_BITCOUNT_MAX && bits <= 2 * FLINT_BITS - 1) { _fmpz_mat_mul_small_2a(C, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal (mul_small_2a)\n\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fmpz_mat_print(C); flint_printf("\n\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } if (abits <= SMALL_FMPZ_BITCOUNT_MAX && bbits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_mat_mul_small_2b(C, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal (mul_small_2b)\n\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fmpz_mat_print(C); flint_printf("\n\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } if (abits < 2 * FLINT_BITS && bbits < 2 * FLINT_BITS) { _fmpz_mat_mul_double_word(C, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal (mul_double_word)\n\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fmpz_mat_print(C); flint_printf("\n\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } if (n == k) { fmpz_mat_mul(A, A, B); if (!fmpz_mat_equal(A, C)) { flint_printf("FAIL: aliasing failed\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } /* Test aliasing with windows */ { fmpz_mat_t A, B, A_window; fmpz_mat_init(A, 2, 2); fmpz_mat_init(B, 2, 2); fmpz_mat_window_init(A_window, A, 0, 0, 2, 2); fmpz_mat_one(A); fmpz_mat_one(B); fmpz_set_ui(fmpz_mat_entry(B, 0, 1), 1); fmpz_set_ui(fmpz_mat_entry(B, 1, 0), 1); fmpz_mat_mul(A_window, B, A_window); if (!fmpz_mat_equal(A, B)) { flint_printf("FAIL: window aliasing failed\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_window_clear(A_window); fmpz_mat_clear(A); fmpz_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_blas.c000066400000000000000000000065421461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_blas, state) { slong i; slong max_num_threads = 5; for (i = 0; i < 2 * flint_test_multiplier(); i++) { slong m, n, k; fmpz_mat_t A, B, C, D; m = 1 + n_randint(state, 50); n = 1 + n_randint(state, 50); k = 1 + n_randint(state, 50); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); if (n_randint(state, 2)) fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); else fmpz_mat_randtest_unsigned(A, state, n_randint(state, 200) + 1); if (n_randint(state, 2)) fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); else fmpz_mat_randtest_unsigned(B, state, n_randint(state, 200) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); fmpz_mat_mul_classical(C, A, B); if (fmpz_mat_mul_blas(D, A, B)) { if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } } #if FLINT_USES_BLAS && FLINT_BITS == 64 else { flint_printf("FAIL: blas should have worked\n"); fflush(stdout); flint_abort(); } #endif flint_set_num_threads(1 + n_randint(state, max_num_threads)); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } for (i = 0; i < 1 * flint_test_multiplier(); i++) { slong m, n, k; fmpz_mat_t A, B, C, D; m = 1 + n_randint(state, 3); n = 1 + n_randint(state, 3); k = 1 + n_randint(state, 3); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); fmpz_mat_randtest(A, state, n_randint(state, 20000) + 1); fmpz_mat_randtest(B, state, n_randint(state, 20000) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); fmpz_mat_randtest(D, state, n_randint(state, 200) + 1); fmpz_mat_mul_classical(C, A, B); if (fmpz_mat_mul_blas(D, A, B)) { if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } } #if FLINT_USES_BLAS && FLINT_BITS == 64 else { flint_printf("FAIL: blas should have worked\n"); fflush(stdout); flint_abort(); } #endif flint_set_num_threads(1 + n_randint(state, max_num_threads)); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_classical.c000066400000000000000000000033131461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_classical, state) { fmpz_mat_t A, B, C, D; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n, k; slong i, j, h; m = n_randint(state, 50); n = n_randint(state, 50); k = n_randint(state, 50); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); fmpz_mat_mul_classical(C, A, B); for (i = 0; i < D->r; i++) for (j = 0; j < D->c; j++) for (h = 0; h < B->r; h++) fmpz_addmul(fmpz_mat_entry(D, i, j), fmpz_mat_entry(A, i, h), fmpz_mat_entry(B, h, j)); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_double_word.c000066400000000000000000000056471461254215100220210ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" void _fmpz_mat_full(fmpz_mat_t A, flint_bitcnt_t bits) { slong i, j; for (i = 0; i < A->r; i++ ) { for (j = 0; j < A->c; j++) { fmpz_one(fmpz_mat_entry(A, i, j)); fmpz_mul_2exp(fmpz_mat_entry(A, i, j), fmpz_mat_entry(A, i, j), bits); fmpz_sub_ui(fmpz_mat_entry(A, i, j), fmpz_mat_entry(A, i, j), 1); } } } TEST_FUNCTION_START(fmpz_mat_mul_double_word, state) { fmpz_mat_t A, B, C, D; slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int sign; slong m, n, k; flint_bitcnt_t abits, bbits; sign = n_randint(state, 2); m = n_randint(state, 50); k = n_randint(state, 50); n = n_randint(state, 50); abits = n_randint(state, 2*FLINT_BITS - sign) + 1; bbits = n_randint(state, 2*FLINT_BITS - sign) + 1; fmpz_mat_init(A, m, k); fmpz_mat_init(B, k, n); fmpz_mat_init(C, m, n); fmpz_mat_init(D, m, n); if (sign) { if (n_randint(state, 2)) { _fmpz_mat_full(A, abits); _fmpz_mat_full(B, bbits); if (n_randint(state, 2)) fmpz_mat_neg(A, A); if (n_randint(state, 2)) fmpz_mat_neg(B, B); } else { fmpz_mat_randtest(A, state, abits); fmpz_mat_randtest(B, state, bbits); } } else { if (n_randint(state, 2)) { _fmpz_mat_full(A, abits); _fmpz_mat_full(B, bbits); } else { fmpz_mat_randtest_unsigned(A, state, abits); fmpz_mat_randtest_unsigned(B, state, bbits); } } fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); _fmpz_mat_mul_double_word(C, A, B); fmpz_mat_mul_classical(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fmpz_mat_print(C); flint_printf("\n\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_fft.c000066400000000000000000000034651461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_fft, state) { fmpz_mat_t A, B, C, D; slong i; for (i = 0; i < 100*flint_test_multiplier(); i++) { slong m, n, k; m = 1 + n_randint(state, 3); k = 1 + n_randint(state, 3); n = 1 + n_randint(state, 3); fmpz_mat_init(A, m, k); fmpz_mat_init(B, k, n); fmpz_mat_init(C, m, n); fmpz_mat_init(D, m, n); do { fmpz_mat_randtest(A, state, n_randint(state, 99999) + 1); fmpz_mat_randtest(B, state, n_randint(state, 99999) + 1); } while (fmpz_mat_is_zero(A) || fmpz_mat_is_zero(B)); fmpz_mat_randtest(C, state, n_randint(state, 2000) + 1); fmpz_mat_mul_fft(C, A, B); fmpz_mat_mul_classical(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n\n"); flint_printf("inputs:\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); flint_printf("fft:\n"); fmpz_mat_print(C); flint_printf("\n\n"); flint_printf("classical:\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_fmpz_vec.c000066400000000000000000000051461461254215100213170ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_fmpz_vec, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; fmpz * b, * c; fmpz ** bb, ** cc; slong j, m, n, blen; m = n_randint(state, 50); n = n_randint(state, 50); blen = n_randint(state, 50); fmpz_mat_init(C, m, 1); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, 1); c = _fmpz_vec_init(m); b = _fmpz_vec_init(blen); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); _fmpz_vec_randtest(c, state, m, n_randint(state, 200) + 1); _fmpz_vec_randtest(b, state, blen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(m, fmpz*); for (j = 0; j < m; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(cc[j], c + j); } bb = FLINT_ARRAY_ALLOC(blen, fmpz*); for (j = 0; j < blen; j++) { bb[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(bb[j], b + j); } fmpz_mat_mul_fmpz_vec(c, A, b, blen); fmpz_mat_mul_fmpz_vec_ptr(cc, A, (const fmpz * const *)bb, blen); /* supposed to match mul of the chopped or zero-extended b */ for (j = 0; j < n && j < blen; j++) fmpz_set(fmpz_mat_entry(B, j, 0), b + j); fmpz_mat_mul(C, A, B); for (j = 0; j < m; j++) { if (!fmpz_equal(fmpz_mat_entry(C, j, 0), c + j) || !fmpz_equal(fmpz_mat_entry(C, j, 0), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); _fmpz_vec_clear(c, m); _fmpz_vec_clear(b, blen); for (j = 0; j < m; j++) { fmpz_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < blen; j++) { fmpz_clear(bb[j]); flint_free(bb[j]); } flint_free(bb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_multi_mod.c000066400000000000000000000063761461254215100215050ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_multi_mod, state) { fmpz_mat_t A, B, C, D; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n, k; m = n_randint(state, 100); n = n_randint(state, 100); k = n_randint(state, 100); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); flint_set_num_threads(1 + n_randint(state, 4)); fmpz_mat_mul_classical(C, A, B); fmpz_mat_mul_multi_mod(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n, k; m = n_randint(state, 3); n = n_randint(state, 3); k = n_randint(state, 3); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); fmpz_mat_randtest(A, state, n_randint(state, 25000) + 1); fmpz_mat_randtest(B, state, n_randint(state, 25000) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); flint_set_num_threads(1 + n_randint(state, 4)); fmpz_mat_mul_classical(C, A, B); fmpz_mat_mul_multi_mod(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong n; n = n_randint(state, 100); fmpz_mat_init(A, n, n); fmpz_mat_init(C, n, n); fmpz_mat_init(D, n, n); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); flint_set_num_threads(1 + n_randint(state, 4)); fmpz_mat_mul_classical(C, A, A); fmpz_mat_mul_multi_mod(D, A, A); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal (squaring)\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_small.c000066400000000000000000000040531461254215100206120ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_small, state) { fmpz_mat_t A, B, C, D; slong i; slong max_threads = 6; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, k, n; if (flint_get_num_threads() >= max_threads - 1) { m = n_randint(state, 200); n = n_randint(state, 200); k = n_randint(state, 200); } else { m = n_randint(state, 50); n = n_randint(state, 50); k = n_randint(state, 50); } fmpz_mat_init(A, m, k); fmpz_mat_init(B, k, n); fmpz_mat_init(C, m, n); fmpz_mat_init(D, m, n); fmpz_mat_randtest(A, state, n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1); fmpz_mat_randtest(B, state, n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1); fmpz_mat_randtest(C, state, n_randint(state, 200) + 1); fmpz_mat_randtest(D, state, n_randint(state, 200) + 1); _fmpz_mat_mul_small(C, A, B); fmpz_mat_mul_classical(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n\n"); fmpz_mat_print(A); flint_printf("\n\n"); fmpz_mat_print(B); flint_printf("\n\n"); fmpz_mat_print(C); flint_printf("\n\n"); fmpz_mat_print(D); flint_printf("\n\n"); fflush(stdout); flint_abort(); } flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_strassen.c000066400000000000000000000027611461254215100213500ustar00rootroot00000000000000/* Copyright (C) 2016 Aaditya Thakkar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_strassen, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C, D; slong m, k, n; m = n_randint(state, 20); k = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); fmpz_mat_mul_classical(C, A, B); fmpz_mat_mul_strassen(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fmpz_mat_print_pretty(A); fmpz_mat_print_pretty(B); fmpz_mat_print_pretty(C); fmpz_mat_print_pretty(D); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-mul_waksman.c000066400000000000000000000027611461254215100211470ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_mul_waksman, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C, D; slong m, k, n; m = n_randint(state, 20); k = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, k); fmpz_mat_init(C, m, k); fmpz_mat_init(D, m, k); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); fmpz_mat_mul_classical(C, A, B); fmpz_mat_mul_waksman(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fmpz_mat_print_pretty(A); fmpz_mat_print_pretty(B); fmpz_mat_print_pretty(C); fmpz_mat_print_pretty(D); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-multi_CRT_ui.c000066400000000000000000000047001461254215100211630ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_multi_CRT_ui, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong bits, prime_bits, rows, cols, num_primes, j; fmpz_t mod; fmpz_mat_t A, B, C; nmod_mat_t Amod[1000]; mp_limb_t primes[1000]; bits = n_randint(state, 500) + 1; rows = n_randint(state, 10); cols = n_randint(state, 10); prime_bits = 1 + n_randint(state, FLINT_BITS - 1); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); fmpz_mat_randtest(A, state, bits); fmpz_init(mod); num_primes = 0; primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); fmpz_set_ui(mod, primes[0]); /* + 1 for sign */ while (fmpz_bits(mod) <= bits + 1) { primes[num_primes + 1] = n_nextprime(primes[num_primes], 0); fmpz_mul_ui(mod, mod, primes[num_primes + 1]); num_primes++; } num_primes++; for (j = 0; j < num_primes; j++) nmod_mat_init(Amod[j], rows, cols, primes[j]); fmpz_mat_multi_mod_ui(Amod, num_primes, A); fmpz_mat_multi_CRT_ui(B, Amod, num_primes, 1); if (!fmpz_mat_equal(B, A)) { flint_printf("FAIL!\n"); flint_printf("primes: "); for (j = 0; j < num_primes; j++) flint_printf("%wu ", primes[j]); flint_printf("\nA: \n"); fmpz_mat_print_pretty(A); flint_printf("\nB: \n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fflush(stdout); flint_abort(); } for (j = 0; j < num_primes; j++) nmod_mat_clear(Amod[j]); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-multi_CRT_ui_unsigned.c000066400000000000000000000046631461254215100230670ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_multi_CRT_ui_unsigned, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong bits, prime_bits, rows, cols, num_primes, j; fmpz_t mod; fmpz_mat_t A, B, C; nmod_mat_t Amod[1000]; mp_limb_t primes[1000]; bits = n_randint(state, 500) + 1; rows = n_randint(state, 10); cols = n_randint(state, 10); prime_bits = 1 + n_randint(state, FLINT_BITS - 1); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); fmpz_mat_randtest_unsigned(A, state, bits); fmpz_init(mod); num_primes = 0; primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); fmpz_set_ui(mod, primes[0]); while (fmpz_bits(mod) <= bits) { primes[num_primes + 1] = n_nextprime(primes[num_primes], 0); fmpz_mul_ui(mod, mod, primes[num_primes + 1]); num_primes++; } num_primes++; for (j = 0; j < num_primes; j++) nmod_mat_init(Amod[j], rows, cols, primes[j]); fmpz_mat_multi_mod_ui(Amod, num_primes, A); fmpz_mat_multi_CRT_ui(B, Amod, num_primes, 0); if (!fmpz_mat_equal(B, A)) { flint_printf("FAIL!\n"); flint_printf("primes: "); for (j = 0; j < num_primes; j++) flint_printf("%wu ", primes[j]); flint_printf("\nA: \n"); fmpz_mat_print_pretty(A); flint_printf("\nB: \n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fflush(stdout); flint_abort(); } for (j = 0; j < num_primes; j++) nmod_mat_clear(Amod[j]); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-nullspace.c000066400000000000000000000100071461254215100206070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_nullspace, state) { fmpz_mat_t A, B, ker; slong i, m, n, b, d, r, nullity, nulrank; /* small dimension */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m,n); r++) { b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(ker, n, n); fmpz_mat_init(B, m, n); fmpz_mat_randrank(A, state, r, b); /* Densify */ if (n_randlimb(state) % 2) fmpz_mat_randops(A, state, d); nullity = fmpz_mat_nullspace(ker, A); nulrank = fmpz_mat_rank(ker); if (nullity != nulrank) { flint_printf("FAIL:\n"); flint_printf("rank(ker) != nullity!\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); fflush(stdout); flint_abort(); } if (nullity + r != n) { flint_printf("FAIL:\n"); flint_printf("nullity + rank != n\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_mul(B, A, ker); if (fmpz_mat_rank(B) != 0) { flint_printf("FAIL:\n"); flint_printf("A * ker != 0\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(ker); fmpz_mat_clear(B); } } /* larger dimension */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { m = 25 + n_randint(state, 10); n = 25 + n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m,n); r++) { b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(ker, n, n); fmpz_mat_init(B, m, n); fmpz_mat_randrank(A, state, r, b); /* Densify */ if (n_randlimb(state) % 2) fmpz_mat_randops(A, state, d); nullity = fmpz_mat_nullspace(ker, A); nulrank = fmpz_mat_rank(ker); if (nullity != nulrank) { flint_printf("FAIL:\n"); flint_printf("rank(ker) != nullity!\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); fflush(stdout); flint_abort(); } if (nullity + r != n) { flint_printf("FAIL:\n"); flint_printf("nullity + rank != n\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_mul(B, A, ker); if (fmpz_mat_rank(B) != 0) { flint_printf("FAIL:\n"); flint_printf("A * ker != 0\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(ker); fmpz_mat_clear(B); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-one.c000066400000000000000000000022601461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_one, state) { slong m, n, i, j, rep; for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { fmpz_mat_t A; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_randtest(A, state, 100); fmpz_mat_one(A); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (fmpz_cmp_ui(fmpz_mat_entry(A,i,j), i == j) != 0) { flint_printf("FAIL: nonzero entry\n"); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-pow.c000066400000000000000000000031421461254215100174300ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_pow, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; slong i, n; ulong e; n = n_randint(state, 10); e = n_randint(state, 20); fmpz_mat_init(A, n, n); fmpz_mat_init(B, n, n); fmpz_mat_init(C, n, n); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); fmpz_mat_pow(B, A, e); fmpz_mat_one(C); for (i = 0; i < e; i++) fmpz_mat_mul(C, C, A); if (!fmpz_mat_equal(C, B)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_pow(A, A, e); if (!fmpz_mat_equal(A, B)) { flint_printf("FAIL: aliasing failed\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-print_read.c000066400000000000000000000153011461254215100207520ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) # include # include # include #endif #include "test_helpers.h" #include "fmpz_mat.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) TEST_FUNCTION_START(fmpz_mat_print_read, state) { int i, j, m, n, k = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; fflush(stdout); /* Ensure buffer does not flow into child process */ /* Randomise k mats, write to and read from a pipe */ { fmpz_mat_t *M; M = flint_malloc(k * sizeof(fmpz_mat_t)); for (i = 0; i < k; i++) { m = n_randint(state, 10); n = n_randint(state, 10); fmpz_mat_init(M[i], m, n); fmpz_mat_randtest(M[i], state, 100); } if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } for (j = 0; j < k; j++) { r = fmpz_mat_fprint(out, M[j]); if ((j < k - 1) && (r > 0)) r = flint_fprintf(out, "\n"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } } fclose(out); for (i = 0; i < k; ++i) fmpz_mat_clear(M[i]); flint_free(M); exit(0); } else /* Parent process */ { int r; fmpz_mat_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } for (i = 0; i < k && !feof(in); i++) { fmpz_mat_init(t, 0, 0); r = fmpz_mat_fread(in, t); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Read error.\n"); fflush(stdout); flint_abort(); } result = fmpz_mat_equal(t, M[i]); if (!result) { flint_printf("FAIL:\n"); flint_printf("M[i] = "), fmpz_mat_print(M[i]), flint_printf("\n"); flint_printf("t = "), fmpz_mat_print(t), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(t); } fclose(in); waitpid(childpid, NULL, 0); } if (i != k) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); fflush(stdout); flint_abort(); } for (i = 0; i < k; i++) fmpz_mat_clear(M[i]); flint_free(M); } /* Write bad data to a pipe and read it */ { char str[5] = {'b', 'l', 'a', 'h', '\0'}; if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } fclose(out); exit(0); } else /* Parent process */ { int r; fmpz_mat_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_mat_init(t,0,0); i = 0; while (!feof(in)) { r = fmpz_mat_fread(in, t); if (r > 0) { flint_printf("FAIL:\n"); flint_printf("r = %d\n", r); fflush(stdout); flint_abort(); } ++i; } fmpz_mat_clear(t); fclose(in); waitpid(childpid, NULL, 0); } /* For {'b','l','a','h','\0'} we expect 5 reads */ if (i != 5) { flint_printf("FAIL:\n"); flint_printf("Carried out %d reads, but \"%s\" has only 4 characters.\n", i, str); fflush(stdout); flint_abort(); } } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(fmpz_mat_print_read, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/fmpz_mat/test/t-rank.c000066400000000000000000000036421461254215100175630ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_rank, state) { fmpz_mat_t A; slong i, m, n, b, d, r; /* Maximally sparse matrices of given rank */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { m = n_randint(state, 35); n = n_randint(state, 35); for (r = 0; r <= FLINT_MIN(m,n); r++) { b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_init(A, m, n); fmpz_mat_randrank(A, state, r, b); if (r != fmpz_mat_rank(A)) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); } } /* Dense */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { m = n_randint(state, 35); n = n_randint(state, 35); for (r = 0; r <= FLINT_MIN(m,n); r++) { b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_init(A, m, n); fmpz_mat_randrank(A, state, r, b); fmpz_mat_randops(A, state, d); if (r != fmpz_mat_rank(A)) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-rref.c000066400000000000000000000072321461254215100175650ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_rref, state) { slong iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { fmpz_mat_t A, R, B, R2; fmpz_t den, c, den2; slong j, k, m, n, b, d, r, rank1, rank2; slong *perm; int equal; m = n_randint(state, 30); n = n_randint(state, 30); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(R, m, n); fmpz_mat_init(B, 2 * m, n); fmpz_mat_init(R2, 2 * m, n); fmpz_init(c); fmpz_init(den); fmpz_init(den2); perm = _perm_init(2 * m); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); rank1 = fmpz_mat_rref(R, den, A); if (r != rank1) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } if (!fmpz_mat_is_in_rref_with_rank(R, den, rank1)) { flint_printf("FAIL matrix not in rref!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fflush(stdout); flint_abort(); } /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { fmpz_randtest_not_zero(c, state, 5); for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(B, perm[j], k), fmpz_mat_entry(A, j, k), c); } for (j = 0; j < m; j++) { fmpz_randtest_not_zero(c, state, 5); for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(B, perm[m + j], k), fmpz_mat_entry(R, j, k), c); } rank2 = fmpz_mat_rref(R2, den2, B); equal = (rank1 == rank2); if (equal) { fmpz_mat_scalar_mul_fmpz(R, R, den2); fmpz_mat_scalar_mul_fmpz(R2, R2, den); for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_equal(fmpz_mat_entry(R, j, k), fmpz_mat_entry(R2, j, k)); for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_is_zero(fmpz_mat_entry(R2, j, k)); } if (!equal) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fmpz_mat_print_pretty(R2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_clear(den); fmpz_clear(den2); _perm_clear(perm); fmpz_mat_clear(A); fmpz_mat_clear(R); fmpz_mat_clear(B); fmpz_mat_clear(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-rref_fflu.c000066400000000000000000000072411461254215100206010ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_rref_fflu, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, R, B, R2; fmpz_t den, c, den2; slong j, k, m, n, b, d, r, rank1, rank2; slong *perm; int equal; m = n_randint(state, 10); n = n_randint(state, 10); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(R, m, n); fmpz_mat_init(B, 2 * m, n); fmpz_mat_init(R2, 2 * m, n); fmpz_init(c); fmpz_init(den); fmpz_init(den2); perm = _perm_init(2 * m); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); rank1 = fmpz_mat_rref(R, den, A); if (r != rank1) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } if (!fmpz_mat_is_in_rref_with_rank(R, den, rank1)) { flint_printf("FAIL matrix not in rref!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fflush(stdout); flint_abort(); } /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { fmpz_randtest_not_zero(c, state, 5); for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(B, perm[j], k), fmpz_mat_entry(A, j, k), c); } for (j = 0; j < m; j++) { fmpz_randtest_not_zero(c, state, 5); for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(B, perm[m + j], k), fmpz_mat_entry(R, j, k), c); } rank2 = fmpz_mat_rref(R2, den2, B); equal = (rank1 == rank2); if (equal) { fmpz_mat_scalar_mul_fmpz(R, R, den2); fmpz_mat_scalar_mul_fmpz(R2, R2, den); for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_equal(fmpz_mat_entry(R, j, k), fmpz_mat_entry(R2, j, k)); for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_is_zero(fmpz_mat_entry(R2, j, k)); } if (!equal) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fmpz_mat_print_pretty(R2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_clear(den); fmpz_clear(den2); _perm_clear(perm); fmpz_mat_clear(A); fmpz_mat_clear(R); fmpz_mat_clear(B); fmpz_mat_clear(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-rref_mul.c000066400000000000000000000116021461254215100204360ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_rref_mul, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, R, B, R2, R3; fmpz_t den, c, den2; slong j, k, m, n, b, d, r, rank1, rank2; slong * perm; int equal; m = 1 + n_randint(state, 10); n = 1 + n_randint(state, 10); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(R, m, n); fmpz_mat_init(R2, m, n); fmpz_mat_init(R3, 2 * m, n); fmpz_mat_init(B, 2 * m, n); fmpz_init(c); fmpz_init(den); fmpz_init(den2); perm = _perm_init(2 * m); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); rank1 = fmpz_mat_rref_mul(R, den, A); if (r != rank1) { flint_printf("FAIL wrong rank! (r = %wd, rank1 = %wd)!\n", r, rank1); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (!fmpz_mat_is_in_rref_with_rank(R, den, rank1)) { flint_printf("FAIL matrix not in rref!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fflush(stdout); flint_abort(); } /* check rref is the same as when computed classically */ rank2 = fmpz_mat_rref_fflu(R2, den2, A); equal = (rank1 == rank2); if (equal) { fmpz_mat_scalar_mul_fmpz(R, R, den2); fmpz_mat_scalar_mul_fmpz(R2, R2, den); for (j = 0; j < m; j++) for (k = 0; k < n; k++) equal = equal && fmpz_equal(fmpz_mat_entry(R, j, k), fmpz_mat_entry(R2, j, k)); if (!fmpz_is_zero(den2)) /* TODO should den2 be able to be? */ fmpz_mat_scalar_divexact_fmpz(R, R, den2); } if (!equal) { flint_printf("FAIL different to classical (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fmpz_mat_print_pretty(R2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { fmpz_randtest_not_zero(c, state, 5); for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(B, perm[j], k), fmpz_mat_entry(A, j, k), c); } for (j = 0; j < m; j++) { fmpz_randtest_not_zero(c, state, 5); for (k = 0; k < n; k++) fmpz_mul(fmpz_mat_entry(B, perm[m + j], k), fmpz_mat_entry(R, j, k), c); } rank2 = fmpz_mat_rref_mul(R3, den2, B); equal = (rank1 == rank2); if (equal) { fmpz_mat_scalar_mul_fmpz(R, R, den2); fmpz_mat_scalar_mul_fmpz(R3, R3, den); for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_equal(fmpz_mat_entry(R, j, k), fmpz_mat_entry(R3, j, k)); for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_is_zero(fmpz_mat_entry(R3, j, k)); } if (!equal) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(R); flint_printf("\n\n"); fmpz_mat_print_pretty(R3); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_clear(den); fmpz_clear(den2); _perm_clear(perm); fmpz_mat_clear(B); fmpz_mat_clear(R3); fmpz_mat_clear(R2); fmpz_mat_clear(R); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_addmul_fmpz.c000066400000000000000000000025721461254215100224600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_addmul_fmpz, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; slong rows, cols; fmpz_t c; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); fmpz_init(c); fmpz_randtest(c, state, 100); fmpz_mat_randtest(A, state, 100); fmpz_mat_randtest(B, state, 100); fmpz_mat_set(C, B); fmpz_mat_scalar_addmul_fmpz(B, A, c); fmpz_mat_scalar_submul_fmpz(B, A, c); if (!fmpz_mat_equal(B, C)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_addmul_nmod_mat_fmpz.c000066400000000000000000000031771461254215100243400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_addmul_nmod_mat_fmpz, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; nmod_mat_t M; slong rows, cols; fmpz_t c; ulong mod; rows = n_randint(state, 10); cols = n_randint(state, 10); mod = n_randtest_prime(state, 0); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); nmod_mat_init(M, rows, cols, mod); fmpz_init(c); fmpz_randtest(c, state, 100); nmod_mat_randtest(M, state); fmpz_mat_set_nmod_mat_unsigned(A, M); fmpz_mat_randtest(B, state, 100); fmpz_mat_set(C, B); fmpz_mat_scalar_addmul_nmod_mat_fmpz(B, M, c); fmpz_mat_scalar_addmul_fmpz(C, A, c); if (!fmpz_mat_equal(B, C)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); nmod_mat_clear(M); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_addmul_nmod_mat_ui.c000066400000000000000000000030621461254215100237720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_addmul_nmod_mat_ui, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; nmod_mat_t M; slong rows, cols; ulong c; ulong mod; rows = n_randint(state, 10); cols = n_randint(state, 10); mod = n_randtest_prime(state, 0); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); nmod_mat_init(M, rows, cols, mod); c = n_randtest(state); nmod_mat_randtest(M, state); fmpz_mat_set_nmod_mat_unsigned(A, M); fmpz_mat_randtest(B, state, 100); fmpz_mat_set(C, B); fmpz_mat_scalar_addmul_nmod_mat_ui(B, M, c); fmpz_mat_scalar_addmul_ui(C, A, c); if (!fmpz_mat_equal(B, C)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); nmod_mat_clear(M); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_addmul_si.c000066400000000000000000000025071461254215100221150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_addmul_si, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; slong rows, cols; slong c; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); c = z_randtest(state); fmpz_mat_randtest(A, state, 100); fmpz_mat_randtest(B, state, 100); fmpz_mat_set(C, B); fmpz_mat_scalar_addmul_si(B, A, c); fmpz_mat_scalar_submul_si(B, A, c); if (!fmpz_mat_equal(B, C)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_addmul_ui.c000066400000000000000000000024561461254215100221220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_addmul_ui, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; slong rows, cols; ulong c; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); c = n_randtest(state); fmpz_mat_randtest(A, state, 100); fmpz_mat_randtest(B, state, 100); fmpz_mat_set(C, B); fmpz_mat_scalar_addmul_ui(B, A, c); fmpz_mat_scalar_submul_ui(B, A, c); if (!fmpz_mat_equal(B, C)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_mod_fmpz.c000066400000000000000000000025051461254215100217650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_mod_fmpz, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A, Amod; fmpz_t mod; slong rows, cols; rows = n_randint(state, 20); cols = n_randint(state, 20); fmpz_mat_init(A, rows, cols); fmpz_mat_init(Amod, rows, cols); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 100); fmpz_mat_randtest(A, state, 100); fmpz_mat_randtest(Amod, state, 100); fmpz_mat_scalar_mod_fmpz(Amod, A, mod); fmpz_mat_scalar_mod_fmpz(A, A, mod); if (!fmpz_mat_equal(A, Amod)) { flint_printf("FAIL: aliasing!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(Amod); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_mul_2exp.c000066400000000000000000000041541461254215100217070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_mul_2exp, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t C, B, A; slong rows, cols; ulong exp; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); exp = n_randint(state, 200); fmpz_mat_randtest(A, state, 100); fmpz_mat_scalar_mul_2exp(B, A, exp); fmpz_mat_scalar_tdiv_q_2exp(C, B, exp); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } /* test aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t C, B, A; slong rows, cols; ulong exp; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); exp = n_randint(state, 200); fmpz_mat_randtest(A, state, 100); fmpz_mat_scalar_mul_2exp(B, A, exp); fmpz_mat_scalar_tdiv_q_2exp(C, B, exp); fmpz_mat_scalar_mul_2exp(A, A, exp); fmpz_mat_scalar_tdiv_q_2exp(A, A, exp); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000031111461254215100217750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_mul_fmpz, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t C, B, A; slong rows, cols; fmpz_t c; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); fmpz_init(c); fmpz_randtest(c, state, 100); fmpz_mat_randtest(A, state, 100); fmpz_mat_scalar_mul_fmpz(B, A, c); if (fmpz_is_zero(c)) { if (!fmpz_mat_is_zero(B)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } else { fmpz_mat_scalar_divexact_fmpz(C, B, c); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_mul_si.c000066400000000000000000000030141461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_mul_si, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t C, B, A; slong rows, cols; slong c; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); c = z_randtest(state); fmpz_mat_randtest(A, state, 100); fmpz_mat_scalar_mul_si(B, A, c); if (c == 0) { if (!fmpz_mat_is_zero(B)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } else { fmpz_mat_scalar_divexact_si(C, B, c); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_mul_ui.c000066400000000000000000000027631461254215100214520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_mul_ui, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t C, B, A; slong rows, cols; ulong c; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_mat_init(C, rows, cols); c = n_randtest(state); fmpz_mat_randtest(A, state, 100); fmpz_mat_scalar_mul_ui(B, A, c); if (c == 0) { if (!fmpz_mat_is_zero(B)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } else { fmpz_mat_scalar_divexact_ui(C, B, c); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-scalar_smod.c000066400000000000000000000034421461254215100211150ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_scalar_smod, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t B, A; slong j, k, rows, cols; fmpz_t P, c; rows = n_randint(state, 10); cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); fmpz_mat_init(B, rows, cols); fmpz_init(P); fmpz_init(c); do { fmpz_randtest(P, state, 100); fmpz_abs(P, P); } while (fmpz_is_zero(P)); fmpz_mat_randtest(A, state, 100); fmpz_mat_scalar_smod(B, A, P); for (j = 0; j < A->r; j++) { for (k = 0; k < A->c; k++) { fmpz_smod(c, A->rows[j] + k, P); if (!fmpz_equal(c, B->rows[j] + k)) { flint_printf("FAIL!\n"); flint_printf("%wd, %wd\n", j, k); fmpz_print(c); flint_printf("\n"); fmpz_print(A->rows[j] + k); flint_printf("\n"); fmpz_print(B->rows[j] + k); flint_printf("\n"); fmpz_print(P); flint_printf("\n"); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(P); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-snf_diagonal.c000066400000000000000000000036641461254215100212600ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_snf_diagonal, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, S, S2; slong b, i, m, n; int equal; m = n_randint(state, 10); n = n_randint(state, 10); b = 1 + n_randint(state, 10) * n_randint(state, 10); fmpz_mat_init(A, m, n); fmpz_mat_init(S, m, n); fmpz_mat_init(S2, m, n); for (i = 0; i < FLINT_MIN(m, n); i++) { fmpz_randtest_unsigned(fmpz_mat_entry(A, i, i), state, b); } fmpz_mat_snf_diagonal(S, A); if (!fmpz_mat_is_in_snf(S)) { flint_printf("FAIL:\n"); flint_printf("matrix not in snf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(S); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_snf_diagonal(S2, S); equal = fmpz_mat_equal(S, S2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("snf of a matrix in snf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(S); flint_printf("\n\n"); fmpz_mat_print_pretty(S2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(S2); fmpz_mat_clear(S); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-snf_iliopoulos.c000066400000000000000000000051221461254215100216670ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_snf_iliopoulos, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, S, S2; fmpz_t mod; slong m, n, b, d; int equal; m = n_randint(state, 10); n = m; fmpz_init(mod); fmpz_mat_init(A, m, n); fmpz_mat_init(S, m, n); fmpz_mat_init(S2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, m, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_det(mod, A); fmpz_abs(mod, mod); fmpz_mat_snf_iliopoulos(S, A, mod); if (!fmpz_mat_is_in_snf(S)) { flint_printf("FAIL:\n"); flint_printf("matrix not in snf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(S); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_snf_iliopoulos(S2, S, mod); equal = fmpz_mat_equal(S, S2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("snf of a matrix in snf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(S); flint_printf("\n\n"); fmpz_mat_print_pretty(S2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_snf_kannan_bachem(S2, S); equal = fmpz_mat_equal(S, S2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("snfs found by different methods should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(S); flint_printf("\n\n"); fmpz_mat_print_pretty(S2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(S2); fmpz_mat_clear(S); fmpz_mat_clear(A); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-snf_kannan_bachem.c000066400000000000000000000040501461254215100222350ustar00rootroot00000000000000/* Copyright (C) 2014 Alex J. Best This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_snf_kannan_bachem, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_mat_t A, S, S2; slong m, n, b, d, r; int equal; m = n_randint(state, 10); n = n_randint(state, 10); r = n_randint(state, FLINT_MIN(m, n) + 1); fmpz_mat_init(A, m, n); fmpz_mat_init(S, m, n); fmpz_mat_init(S2, m, n); /* sparse */ b = 1 + n_randint(state, 10) * n_randint(state, 10); d = n_randint(state, 2*m*n + 1); fmpz_mat_randrank(A, state, r, b); /* dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, d); fmpz_mat_snf_kannan_bachem(S, A); if (!fmpz_mat_is_in_snf(S)) { flint_printf("FAIL:\n"); flint_printf("matrix not in snf!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(S); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_snf_kannan_bachem(S2, S); equal = fmpz_mat_equal(S, S2); if (!equal) { flint_printf("FAIL:\n"); flint_printf("snf of a matrix in snf should be the same!\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mat_print_pretty(S); flint_printf("\n\n"); fmpz_mat_print_pretty(S2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(S2); fmpz_mat_clear(S); fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-solve.c000066400000000000000000000061321461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_solve, state) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, m, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve(X, den, A, B); fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); if (!fmpz_mat_equal(AX, B) || !success) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 10); n = 1 + n_randint(state, 10); r = n_randint(state, m); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, r, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve(X, den, A, B); if (!fmpz_is_zero(den) || success) { flint_printf("FAIL:\n"); flint_printf("singular system gave nonzero determinant\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-solve_bound.c000066400000000000000000000052531461254215100211470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_solve_bound, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, X; fmpz_t N, D, den; slong m, n, b1, b2; slong j, k; b1 = 1 + n_randint(state, 100); b2 = 1 + n_randint(state, 100); m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(den); fmpz_init(N); fmpz_init(D); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_randrank(A, state, m, b1); fmpz_mat_randops(A, state, n_randint(state, m)*n_randint(state, m)); fmpz_mat_randtest(B, state, b2); fmpz_mat_solve_bound(N, D, A, B); fmpz_mat_solve(X, den, A, B); if (fmpz_cmpabs(D, den) < 0) { flint_printf("FAIL:\n"); flint_printf("denominator bound:\n"); fmpz_print(D); flint_printf("\ndenominator:\n"); fmpz_print(den); flint_printf("\n"); flint_printf("A:\n"); fmpz_mat_print_pretty(A); flint_printf("B:\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fflush(stdout); flint_abort(); } for (j = 0; j < m; j++) { for (k = 0; k < n; k++) { if (fmpz_cmpabs(N, fmpz_mat_entry(X, j, k)) < 0) { flint_printf("FAIL:\n"); flint_printf("numerator bound:\n"); fmpz_print(N); flint_printf("\nnumerator:\n"); fmpz_print(fmpz_mat_entry(X, j, k)); flint_printf("\n"); flint_printf("A:\n"); fmpz_mat_print_pretty(A); flint_printf("B:\n"); fmpz_mat_print_pretty(B); flint_printf("\n"); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_clear(den); fmpz_clear(N); fmpz_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-solve_cramer.c000066400000000000000000000061551461254215100213130ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_solve_cramer, state) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 4); n = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, m, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve_cramer(X, den, A, B); fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); if (!fmpz_mat_equal(AX, B) || !success) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 3); n = 1 + n_randint(state, 10); r = n_randint(state, m); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, r, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve_cramer(X, den, A, B); if (!fmpz_is_zero(den) || success) { flint_printf("FAIL:\n"); flint_printf("singular system gave nonzero determinant\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-solve_dixon.c000066400000000000000000000063141461254215100211600ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_solve_dixon, state) { fmpz_mat_t A, X, B, AX, AXm, Bm; fmpz_t mod; slong i, m, n, r; int success; for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(Bm, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_mat_init(AXm, m, n); fmpz_init(mod); fmpz_mat_randrank(A, state, m, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve_dixon(X, mod, A, B); fmpz_mat_set(AXm, X); fmpz_mat_mul(AX, A, AXm); fmpz_mat_scalar_mod_fmpz(AXm, AX, mod); fmpz_mat_scalar_mod_fmpz(Bm, B, mod); if (!fmpz_mat_equal(AXm, Bm) || !success) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("mod = "), fmpz_print(mod), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(Bm); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_mat_clear(AXm); fmpz_clear(mod); } /* Test singular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 10); n = 1 + n_randint(state, 10); r = n_randint(state, m); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_init(mod); fmpz_mat_randrank(A, state, r, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); if (fmpz_mat_solve_dixon(X, mod, A, B) != 0) { flint_printf("FAIL:\n"); flint_printf("singular system, returned nonzero\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-solve_dixon_den.c000066400000000000000000000061661461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_solve_dixon_den, state) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, m, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve_dixon_den(X, den, A, B); fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); if (!fmpz_mat_equal(AX, B) || !success) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } /* Test singular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 10); n = 1 + n_randint(state, 10); r = n_randint(state, m); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, r, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve_dixon_den(X, den, A, B); if (!fmpz_is_zero(den) || success) { flint_printf("FAIL:\n"); flint_printf("singular system gave nonzero determinant\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-solve_fflu.c000066400000000000000000000061651461254215100207770ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_solve_fflu, state) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, m, 1 + n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1 + n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1 + n_randint(state, 1 + m*m)); success = fmpz_mat_solve_fflu(X, den, A, B); fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); if (!fmpz_mat_equal(AX, B) || !success) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 10); n = 1 + n_randint(state, 10); r = n_randint(state, m); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, r, 1 + n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1 + n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1 + n_randint(state, 1 + m*m)); success = fmpz_mat_solve_fflu(X, den, A, B); if (!fmpz_is_zero(den) || success) { flint_printf("FAIL:\n"); flint_printf("singular system gave nonzero determinant\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-solve_multi_mod_den.c000066400000000000000000000062021461254215100226520ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_solve_multi_mod_den, state) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, m, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve_multi_mod_den(X, den, A, B); fmpz_mat_mul(AX, A, X); fmpz_mat_scalar_divexact_fmpz(AX, AX, den); if (!fmpz_mat_equal(AX, B) || !success) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"), fmpz_mat_print_pretty(A), flint_printf("\n"); flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); flint_printf("den(X) = "), fmpz_print(den), flint_printf("\n"); flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } /* Test singular systems */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 10); n = 1 + n_randint(state, 10); r = n_randint(state, m); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, n); fmpz_mat_init(X, m, n); fmpz_mat_init(AX, m, n); fmpz_init(den); fmpz_mat_randrank(A, state, r, 1+n_randint(state, 2)*n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*n_randint(state, 100)); /* Dense */ if (n_randint(state, 2)) fmpz_mat_randops(A, state, 1+n_randint(state, 1 + m*m)); success = fmpz_mat_solve_multi_mod_den(X, den, A, B); if (!fmpz_is_zero(den) || success) { flint_printf("FAIL:\n"); flint_printf("singular system gave nonzero determinant\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-sqr.c000066400000000000000000000027621461254215100174370ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_sqr, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C; slong n; n = n_randint(state, 20); fmpz_mat_init(A, n, n); fmpz_mat_init(B, n, n); fmpz_mat_init(C, n, n); fmpz_mat_randtest(A, state, n_randint(state, 200) + 1); fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); /* Make sure noise in the output is ok */ fmpz_mat_randtest(B, state, n_randint(state, 200) + 1); fmpz_mat_sqr(B, A); fmpz_mat_mul_classical(C, A, A); if (!fmpz_mat_equal(C, B)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_sqr(A, A); if (!fmpz_mat_equal(A, B)) { flint_printf("FAIL: aliasing failed\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-trace.c000066400000000000000000000036351461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_trace, state) { slong i; /* Test trace(AB) = trace(BA) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, AB, BA; fmpz_t trab, trba; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, m); fmpz_mat_init(AB, m, m); fmpz_mat_init(BA, n, n); fmpz_init(trab); fmpz_init(trba); fmpz_mat_randtest(A, state, 1 + n_randint(state, 100)); fmpz_mat_randtest(B, state, 1 + n_randint(state, 100)); fmpz_mat_mul(AB, A, B); fmpz_mat_mul(BA, B, A); fmpz_mat_trace(trab, AB); fmpz_mat_trace(trba, BA); if (!fmpz_equal(trab, trba)) { flint_printf("FAIL:\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); fmpz_mat_print_pretty(B), flint_printf("\n"); fmpz_mat_print_pretty(AB), flint_printf("\n"); fmpz_mat_print_pretty(BA), flint_printf("\n"); flint_printf("tr(AB): "), fmpz_print(trab), flint_printf("\n"); flint_printf("tr(BA): "), fmpz_print(trba), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(AB); fmpz_mat_clear(BA); fmpz_clear(trab); fmpz_clear(trba); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-transpose.c000066400000000000000000000034541461254215100206470ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_transpose, state) { slong m, n, rep; /* Rectangular transpose */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { fmpz_mat_t A, B, C; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_init(B, n, m); fmpz_mat_init(C, m, n); fmpz_mat_randtest(A, state, 1+n_randint(state, 100)); fmpz_mat_randtest(B, state, 1+n_randint(state, 100)); fmpz_mat_transpose(B, A); fmpz_mat_transpose(C, B); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL: C != A\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } /* Self-transpose */ for (rep = 0; rep < 1000; rep++) { fmpz_mat_t A, B; m = n_randint(state, 20); fmpz_mat_init(A, m, m); fmpz_mat_init(B, m, m); fmpz_mat_randtest(A, state, 1+n_randint(state, 100)); fmpz_mat_set(B, A); fmpz_mat_transpose(B, B); fmpz_mat_transpose(B, B); if (!fmpz_mat_equal(B, A)) { flint_printf("FAIL: B != A\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-window_init_clear.c000066400000000000000000000026011461254215100223220ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_window_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t a, w; slong j, k, r1, r2, c1, c2; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(a, rows, cols); fmpz_mat_randtest(a, state, n_randint(state, 200) + 1); r2 = n_randint(state, rows + 1); c2 = n_randint(state, cols + 1); if (r2) r1 = n_randint(state, r2); else r1 = 0; if (c2) c1 = n_randint(state, c2); else c1 = 0; fmpz_mat_window_init(w, a, r1, c1, r2, c2); for (j = 0; j < r2 - r1; j++) for (k = 0; k < c2 - c1; k++) fmpz_zero(fmpz_mat_entry(w, j, k)); fmpz_mat_window_clear(w); fmpz_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/test/t-zero.c000066400000000000000000000022471461254215100176070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mat_zero, state) { slong m, n, i, j, rep; for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { fmpz_mat_t A; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mat_init(A, m, n); fmpz_mat_randtest(A, state, 100); fmpz_mat_zero(A); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (!fmpz_is_zero(fmpz_mat_entry(A,i,j))) { flint_printf("FAIL: nonzero entry\n"); fflush(stdout); flint_abort(); } } } fmpz_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mat/trace.c000066400000000000000000000013351461254215100165030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_trace(fmpz_t trace, const fmpz_mat_t mat) { slong i, n = fmpz_mat_nrows(mat); if (n == 0) fmpz_zero(trace); else { fmpz_set(trace, fmpz_mat_entry(mat, 0, 0)); for (i = 1; i < n; i++) fmpz_add(trace, trace, fmpz_mat_entry(mat, i, i)); } } flint-3.1.3/src/fmpz_mat/transpose.c000066400000000000000000000021761461254215100174270ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" void fmpz_mat_transpose(fmpz_mat_t B, const fmpz_mat_t A) { fmpz tmp; slong i, j; if (B->r != A->c || B->c != A->r) { flint_throw(FLINT_ERROR, "Exception (fmpz_mat_transpose). Incompatible dimensions.\n"); } if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < A->r - 1; i++) for (j = i + 1; j < A->c; j++) { tmp = A->rows[i][j]; A->rows[i][j] = A->rows[j][i]; A->rows[j][i] = tmp; } } else /* Not aliased; general case */ { for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) fmpz_set(&B->rows[i][j], &A->rows[j][i]); } } flint-3.1.3/src/fmpz_mat/window.c000066400000000000000000000027131461254215100167150ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_window_init(fmpz_mat_t window, const fmpz_mat_t mat, slong r1, slong c1, slong r2, slong c2) { slong i; window->entries = NULL; if (r2 > r1) window->rows = (fmpz **) flint_malloc((r2 - r1) * sizeof(fmpz *)); else window->rows = NULL; if (mat->c > 0) { for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; } else { for (i = 0; i < r2 - r1; i++) window->rows[i] = NULL; } window->r = r2 - r1; window->c = c2 - c1; } void fmpz_mat_window_clear(fmpz_mat_t window) { if (window->r != 0) flint_free(window->rows); } void _fmpz_mat_window_readonly_init_strip_initial_zero_rows(fmpz_mat_t A, const fmpz_mat_t B) { slong r = B->r; slong c = B->c; slong i; for (i = 0; i < r; i++) { if (!_fmpz_vec_is_zero(B->rows[i], c)) break; } A->entries = NULL; A->rows = B->rows + i; A->r = r - i; A->c = c; } flint-3.1.3/src/fmpz_mat/zero.c000066400000000000000000000011251461254215100163610ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" void fmpz_mat_zero(fmpz_mat_t mat) { slong i; if (mat->c < 1) return; for (i = 0; i < mat->r; i++) _fmpz_vec_zero(mat->rows[i], mat->c); } flint-3.1.3/src/fmpz_mod.h000066400000000000000000000163731461254215100154200ustar00rootroot00000000000000/* Copyright (C) 2017 - 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_H #define FMPZ_MOD_H #ifdef FMPZ_MOD_INLINES_C #define FMPZ_MOD_INLINE #else #define FMPZ_MOD_INLINE static inline #endif #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif /* all of the data we need to do arithmetic mod n ****************************/ /* Currently operations are special cased according to if n < 2^FLINT_BITS -> add1, sub1, mul1 using nmod else if n = 2^FLINT_BITS -> add2s, sub2s, mul2s else if n < 2^(2*FLINT_BITS) -> add2, sub2, mul2 else -> addN, subN, mulN A special case for the multiplication for 3-word shows no signs of diminishing returns, but it is not implemented currently. */ void fmpz_mod_ctx_init(fmpz_mod_ctx_t ctx, const fmpz_t n); void fmpz_mod_ctx_init_ui(fmpz_mod_ctx_t ctx, ulong n); void fmpz_mod_ctx_init_rand_bits(fmpz_mod_ctx_t ctx, flint_rand_t state, flint_bitcnt_t max_bits); void fmpz_mod_ctx_init_rand_bits_prime(fmpz_mod_ctx_t ctx, flint_rand_t state, flint_bitcnt_t max_bits); void fmpz_mod_ctx_clear(fmpz_mod_ctx_t ctx); FMPZ_MOD_INLINE const fmpz * fmpz_mod_ctx_modulus(const fmpz_mod_ctx_t ctx) { return ctx->n; } void fmpz_mod_ctx_set_modulus(fmpz_mod_ctx_t ctx, const fmpz_t n); void fmpz_mod_ctx_set_modulus_ui(fmpz_mod_ctx_t ctx, ulong n); int fmpz_mod_is_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx); void fmpz_mod_assert_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx); int fmpz_mod_is_one(const fmpz_t a, const fmpz_mod_ctx_t ctx); int fmpz_mod_equal_fmpz(const fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); int fmpz_mod_equal_si(const fmpz_t a, slong b, const fmpz_mod_ctx_t ctx); void fmpz_mod_set_fmpz(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); void fmpz_mod_set_ui(fmpz_t a, ulong b, const fmpz_mod_ctx_t ctx); void fmpz_mod_set_si(fmpz_t a, slong b, const fmpz_mod_ctx_t ctx); void _fmpz_mod_add1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_add2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_add2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_addN(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FMPZ_MOD_INLINE void fmpz_mod_add(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { (ctx->add_fxn)(a, b, c, ctx); } void fmpz_mod_add_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_add_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_add_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_sub1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_sub2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_sub2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_subN(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FMPZ_MOD_INLINE void fmpz_mod_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { (ctx->sub_fxn)(a, b, c, ctx); } void fmpz_mod_sub_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_sub_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_sub_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_fmpz_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_ui_sub(fmpz_t a, ulong b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_si_sub(fmpz_t a, slong b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_neg(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); void _fmpz_mod_mul1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_mul2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_mul2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_mulN(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FMPZ_MOD_INLINE void fmpz_mod_mul(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { (ctx->mul_fxn)(a, b, c, ctx); } void fmpz_mod_mul_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_mul_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_mul_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_addmul(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d, const fmpz_mod_ctx_t ctx); int fmpz_mod_is_invertible(const fmpz_t a, const fmpz_mod_ctx_t ctx); void fmpz_mod_inv(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); int fmpz_mod_divides(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_pow_ui(fmpz_t a, const fmpz_t b, ulong pow, const fmpz_mod_ctx_t ctx); int fmpz_mod_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t pow, const fmpz_mod_ctx_t ctx); void fmpz_mod_rand(fmpz_t a, flint_rand_t state, const fmpz_mod_ctx_t ctx); void fmpz_mod_rand_not_zero(fmpz_t a, flint_rand_t state, const fmpz_mod_ctx_t ctx); /* discrete logs a la Pohlig - Hellman ***************************************/ typedef struct { fmpz_t gammapow; ulong cm; } fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct; typedef struct { slong exp; ulong prime; fmpz_t gamma; fmpz_t gammainv; fmpz_t startingbeta; fmpz_t co; fmpz_t startinge; fmpz_t idem; ulong cbound; ulong dbound; fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct * table; /* length cbound */ } fmpz_mod_discrete_log_pohlig_hellman_entry_struct; typedef struct { fmpz_mod_ctx_t fpctx; fmpz_t pm1; /* p - 1 */ fmpz_t alpha; /* p.r. of p */ fmpz_t alphainv; slong num_factors; /* factors of p - 1*/ fmpz_mod_discrete_log_pohlig_hellman_entry_struct * entries; } fmpz_mod_discrete_log_pohlig_hellman_struct; typedef fmpz_mod_discrete_log_pohlig_hellman_struct fmpz_mod_discrete_log_pohlig_hellman_t[1]; void fmpz_mod_discrete_log_pohlig_hellman_init(fmpz_mod_discrete_log_pohlig_hellman_t L); void fmpz_mod_discrete_log_pohlig_hellman_clear(fmpz_mod_discrete_log_pohlig_hellman_t L); double fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t p); void fmpz_mod_discrete_log_pohlig_hellman_run(fmpz_t x, const fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t y); FMPZ_MOD_INLINE const fmpz * fmpz_mod_discrete_log_pohlig_hellman_primitive_root(fmpz_mod_discrete_log_pohlig_hellman_t L) { return L->alpha; } int fmpz_next_smooth_prime(fmpz_t a, const fmpz_t b); /* Declare dead functions *****************************************************/ #define fmpz_mod_ctx_get_modulus_mpz_read_only _Pragma("GCC error \"'fmpz_mod_ctx_get_modulus_mpz_read_only' is deprecated. Use 'fmpz_mod_ctx_modulus' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mod/000077500000000000000000000000001461254215100152355ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod/add.c000066400000000000000000000062671461254215100161440ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_mod.h" void _fmpz_mod_add1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { ulong a0, b0, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); b0 = fmpz_get_ui(b); c0 = fmpz_get_ui(c); a0 = nmod_add(b0, c0, ctx->mod); fmpz_set_ui(a, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void _fmpz_mod_add2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t a0, b0, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); b0 = fmpz_get_ui(b); c0 = fmpz_get_ui(c); a0 = b0 + c0; fmpz_set_ui(a, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void _fmpz_mod_add2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t t2, t1, t0, a2, a1, a0, b1, b0, c1, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_get_uiui(&b1, &b0, b); fmpz_get_uiui(&c1, &c0, c); add_sssaaaaaa(a2, a1, a0, 0, b1, b0, 0, c1, c0); /* at most one subtraction of n */ sub_dddmmmsss(t2, t1, t0, a2, a1, a0, 0, ctx->n_limbs[1], ctx->n_limbs[0]); if ((slong)(t2) >= 0) { a1 = t1; a0 = t0; } fmpz_set_uiui(a, a1, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void _fmpz_mod_addN(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_add(a, b, c); if (fmpz_cmp(a, ctx->n) >= 0) { fmpz_sub(a, a, ctx->n); } FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_add_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_add(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_add_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_add_ui(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_add_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_add_si(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint-3.1.3/src/fmpz_mod/addmul.c000066400000000000000000000014141461254215100166470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" void fmpz_mod_addmul( fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d, const fmpz_mod_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_mul(t, c, d); fmpz_add(t, t, b); if (ctx->ninv_huge == NULL) fmpz_mod(a, t, ctx->n); else fmpz_fdiv_r_preinvn(a, t, ctx->n, ctx->ninv_huge); fmpz_clear(t); } flint-3.1.3/src/fmpz_mod/ctx.c000066400000000000000000000061651461254215100162070ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_mod.h" void fmpz_mod_ctx_init(fmpz_mod_ctx_t ctx, const fmpz_t n) { flint_bitcnt_t bits; if (fmpz_sgn(n) <= 0) { flint_throw(FLINT_ERROR, "Exception in fmpz_mod_ctx_init: " "Modulus is nonpositive."); } /* prepare for general case */ fmpz_init_set(ctx->n, n); ctx->n_limbs[0] = 0; ctx->n_limbs[1] = 0; ctx->n_limbs[2] = 0; ctx->add_fxn = _fmpz_mod_addN; ctx->sub_fxn = _fmpz_mod_subN; ctx->mul_fxn = _fmpz_mod_mulN; ctx->ninv_huge = NULL; bits = fmpz_bits(n); if (bits <= FLINT_BITS) { ctx->add_fxn = _fmpz_mod_add1; ctx->sub_fxn = _fmpz_mod_sub1; ctx->mul_fxn = _fmpz_mod_mul1; nmod_init(&ctx->mod, fmpz_get_ui(n)); } else if (bits <= 2*FLINT_BITS) { fmpz_get_ui_array(ctx->n_limbs, 3, n); /* n_limbs[2] will be 0 */ /* n = 2^FLINT_BITS must be special case */ if (ctx->n_limbs[1] == 1 && ctx->n_limbs[0] == 0) { ctx->add_fxn = _fmpz_mod_add2s; ctx->sub_fxn = _fmpz_mod_sub2s; ctx->mul_fxn = _fmpz_mod_mul2s; } else { fmpz_t t; fmpz_init(t); fmpz_one(t); fmpz_mul_2exp(t, t, 4*FLINT_BITS); fmpz_tdiv_q(t, t, n); fmpz_get_ui_array(ctx->ninv_limbs, 3, t); fmpz_clear(t); FLINT_ASSERT(ctx->ninv_limbs[2] != 0); ctx->add_fxn = _fmpz_mod_add2; ctx->sub_fxn = _fmpz_mod_sub2; ctx->mul_fxn = _fmpz_mod_mul2; } } #ifdef FLINT_HAVE_FFT_SMALL else if (bits >= 19000) { ctx->ninv_huge = flint_malloc(sizeof(fmpz_preinvn_struct)); fmpz_preinvn_init(ctx->ninv_huge, n); } #endif } void fmpz_mod_ctx_init_ui(fmpz_mod_ctx_t ctx, ulong n) { fmpz_t n_; fmpz_init_set_ui(n_, n); fmpz_mod_ctx_init(ctx, n_); fmpz_clear(n_); } void fmpz_mod_ctx_clear(fmpz_mod_ctx_t ctx) { if (ctx->ninv_huge != NULL) { fmpz_preinvn_clear(ctx->ninv_huge); flint_free(ctx->ninv_huge); } fmpz_clear(ctx->n); } void fmpz_mod_ctx_init_rand_bits(fmpz_mod_ctx_t ctx, flint_rand_t state, flint_bitcnt_t max_bits) { fmpz_t m; fmpz_init(m); fmpz_randtest_unsigned(m, state, max_bits); fmpz_add_ui(m, m, 2); fmpz_mod_ctx_init(ctx, m); fmpz_clear(m); } void fmpz_mod_ctx_init_rand_bits_prime(fmpz_mod_ctx_t ctx, flint_rand_t state, flint_bitcnt_t max_bits) { fmpz_t m; fmpz_init(m); fmpz_randtest_unsigned(m, state, max_bits); fmpz_nextprime(m, m, 0); fmpz_mod_ctx_init(ctx, m); fmpz_clear(m); } flint-3.1.3/src/fmpz_mod/discrete_log_pohlig_hellman.c000066400000000000000000000267441461254215100231230ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_mod.h" /* Assumption on fmpz_mod_discrete_log_pohlig_hellman_t: p is prime. The prime factors of p - 1 all fit a ulong. If the prime factors of p - 1 do not fit a ulong you do not want to calculate dlog mod p. so we have p - 1 = p1^e1 * ... * pn^en for ulong pi and ei The assumption p is prime could be removed, but then phi(p) needs to be calculated by someone somewhere. */ static int fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct_cmp( const fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct * lhs, const fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct * rhs) { return fmpz_cmp(lhs->gammapow, rhs->gammapow); } void fmpz_mod_discrete_log_pohlig_hellman_init(fmpz_mod_discrete_log_pohlig_hellman_t L) { fmpz_t two; fmpz_init_set_ui(two, 2); L->num_factors = 0; L->entries = NULL; fmpz_init(L->alpha); fmpz_init(L->alphainv); fmpz_init(L->pm1); fmpz_mod_ctx_init(L->fpctx, two); fmpz_clear(two); return; } void fmpz_mod_discrete_log_pohlig_hellman_clear(fmpz_mod_discrete_log_pohlig_hellman_t L) { slong i; ulong c; fmpz_mod_discrete_log_pohlig_hellman_entry_struct * Li; for (i = 0; i < L->num_factors; i++) { Li = L->entries + i; fmpz_clear(Li->idem); fmpz_clear(Li->co); fmpz_clear(Li->startinge); fmpz_clear(Li->startingbeta); fmpz_clear(Li->gamma); fmpz_clear(Li->gammainv); for (c = 0; c < Li->cbound; c++) { fmpz_clear(Li->table[c].gammapow); } flint_free(Li->table); } if (L->entries) { flint_free(L->entries); } fmpz_clear(L->alpha); fmpz_clear(L->alphainv); fmpz_clear(L->pm1); fmpz_mod_ctx_clear(L->fpctx); return; } static slong _pow_fmpz_cost(const fmpz_t pow) { slong cost = fmpz_bits(pow) + fmpz_popcnt(pow) - 2; return FLINT_MAX(cost, 0); } /* Assume that p is prime, don't check. Return an estimate on the number of multiplications need for one run. */ double fmpz_mod_discrete_log_pohlig_hellman_precompute_prime( fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t p) { slong i; ulong c; fmpz_mod_discrete_log_pohlig_hellman_entry_struct * Li; fmpz_factor_t factors; fmpz_t temp; double total_cost; /* just clear it and allocate everything again */ fmpz_mod_discrete_log_pohlig_hellman_clear(L); fmpz_init(L->alpha); fmpz_init(L->alphainv); fmpz_init(L->pm1); fmpz_mod_ctx_init(L->fpctx, p); fmpz_init(temp); fmpz_factor_init(factors); fmpz_sub_ui(L->pm1, p, 1); fmpz_factor(factors, L->pm1); L->num_factors = factors->num; L->entries = NULL; if (L->num_factors > 0) { L->entries = (fmpz_mod_discrete_log_pohlig_hellman_entry_struct*) flint_malloc( L->num_factors*sizeof(fmpz_mod_discrete_log_pohlig_hellman_entry_struct)); } for (i = 0; i < L->num_factors; i++) { fmpz_t pipow, recp; Li = L->entries + i; fmpz_init(Li->idem); fmpz_init(Li->co); fmpz_init(Li->startinge); fmpz_init(Li->startingbeta); fmpz_init(Li->gamma); fmpz_init(Li->gammainv); if (!fmpz_abs_fits_ui(factors->p + i)) { /* L is corrupted */ fmpz_clear(temp); fmpz_factor_clear(factors); flint_throw(FLINT_ERROR, "Exception in fmpz_mod_discrete_log_" "pohlig_hellman_precompute_prime: Prime factor is large.\n"); } Li->exp = factors->exp[i]; Li->prime = fmpz_get_ui(factors->p + i); fmpz_init(recp); fmpz_init_set_ui(pipow, Li->prime); fmpz_pow_ui(pipow, pipow, Li->exp); fmpz_divexact(recp, L->pm1, pipow); fmpz_invmod(temp, recp, pipow); fmpz_mul(temp, temp, recp); fmpz_mod(Li->idem, temp, L->pm1); fmpz_set(Li->co, recp); fmpz_divexact_ui(Li->startinge, pipow, Li->prime); fmpz_clear(pipow); fmpz_clear(recp); } fmpz_factor_clear(factors); /* alpha will be a primitive root */ fmpz_zero(L->alpha); try_alpha: fmpz_add_ui(L->alpha, L->alpha, 1); if (fmpz_cmp(L->alpha, p) >= 0) { /* L is corrupted */ fmpz_clear(temp); /* factors was already cleared */ flint_throw(FLINT_ERROR, "Exception in fmpz_mod_discrete_log_pohlig_" "hellman_precompute_prime: Could not find primitive root."); } for (i = 0; i < L->num_factors; i++) { Li = L->entries + i; fmpz_divexact_ui(temp, L->pm1, Li->prime); fmpz_mod_pow_fmpz(Li->gamma, L->alpha, temp, L->fpctx); if (fmpz_is_one(Li->gamma)) { goto try_alpha; } } fmpz_mod_inv(L->alphainv, L->alpha, L->fpctx); for (i = 0; i < L->num_factors; i++) { Li = L->entries + i; fmpz_mod_inv(Li->gammainv, Li->gamma, L->fpctx); fmpz_mod_pow_fmpz(Li->startingbeta, L->alphainv, Li->co, L->fpctx); Li->dbound = ceil(sqrt((double) Li->prime)); Li->cbound = (Li->prime + Li->dbound - 1)/Li->dbound; while (Li->cbound > 100) { Li->dbound *= 2; Li->cbound = (Li->prime + Li->dbound - 1)/Li->dbound; } FLINT_ASSERT(Li->dbound > 0); FLINT_ASSERT(Li->cbound > 0); Li->table = (fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct *) flint_malloc(Li->cbound*sizeof(fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct)); for (c = 0; c < Li->cbound; c++) { Li->table[c].cm = c*Li->dbound; fmpz_init(Li->table[c].gammapow); fmpz_mod_pow_ui(Li->table[c].gammapow, Li->gamma, Li->table[c].cm, L->fpctx); } qsort(Li->table, Li->cbound, sizeof(fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct), (int(*)(const void*, const void*)) fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct_cmp); for (c = 1; c < Li->cbound; c++) { FLINT_ASSERT(fmpz_cmp(Li->table[c - 1].gammapow, Li->table[c].gammapow) < 0); } } fmpz_clear(temp); total_cost = 0; for (i = 0; i < L->num_factors; i++) { double this_cost = 0; fmpz_t e; slong j; Li = L->entries + i; this_cost += _pow_fmpz_cost(Li->co); fmpz_init_set(e, Li->startinge); j = 0; do { this_cost += _pow_fmpz_cost(e); this_cost += Li->dbound*(1 + log(Li->cbound)); /* bsgs search */ this_cost += 2*log(Li->prime); /* some power < Li->prime */ fmpz_divexact_ui(e, e, Li->prime); } while (++j < Li->exp); total_cost += this_cost; fmpz_clear(e); } return total_cost; } /* return with xx such that xx = alpha^y mod p, alpha is the p.r. L->alpha*/ void fmpz_mod_discrete_log_pohlig_hellman_run( fmpz_t xx, const fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t y) { slong i, j; ulong g; fmpz_t x; fmpz_t pipow, e, acc; ulong lo, mid, hi, d; fmpz_t beta, z, w, temp; fmpz_mod_discrete_log_pohlig_hellman_entry_struct * Li; fmpz_init(x); fmpz_init(acc); fmpz_init(pipow); fmpz_init(e); fmpz_init(beta); fmpz_init(z); fmpz_init(w); fmpz_init(temp); FLINT_ASSERT(!fmpz_is_zero(y)); FLINT_ASSERT(fmpz_mod_is_canonical(y, L->fpctx)); i = 0; if (i < L->num_factors && L->entries[i].prime == 2) { Li = L->entries + i; FLINT_ASSERT(Li->prime == 2); fmpz_mod_pow_fmpz(z, y, Li->co, L->fpctx); fmpz_set(beta, Li->startingbeta); fmpz_set(e, Li->startinge); j = 0; fmpz_one(pipow); /* Li->prime^j */ fmpz_zero(acc); do { fmpz_mod_pow_fmpz(w, z, e, L->fpctx); /* solve Li->gamma ^ g == w mod p */ if (fmpz_is_one(w)) { g = 0; } else { if (!fmpz_equal(w, Li->gamma)) { goto cleanup_and_throw; } g = 1; fmpz_mod_mul(z, z, beta, L->fpctx); } fmpz_mod_mul(beta, beta, beta, L->fpctx); fmpz_addmul_ui(acc, pipow, g); fmpz_mul_2exp(pipow, pipow, 1); fmpz_tdiv_q_2exp(e, e, 1); } while (++j < Li->exp); fmpz_addmul(x, acc, Li->idem); i = 1; } for (; i < L->num_factors; i++) { Li = L->entries + i; fmpz_mod_pow_fmpz(z, y, Li->co, L->fpctx); fmpz_set(beta, Li->startingbeta); fmpz_set(e, Li->startinge); j = 0; fmpz_one(pipow); /* Li->prime^j */ fmpz_zero(acc); do { fmpz_mod_pow_fmpz(w, z, e, L->fpctx); /* solve Li->gamma ^ g == w mod p */ d = 0; while (1) { lo = 0; hi = Li->cbound; while (hi - lo > 4) { int cmp; mid = lo + (hi - lo)/2; cmp = fmpz_cmp(Li->table[mid].gammapow, w); if (cmp == 0) { g = Li->table[mid].cm + d; goto found_g; } else if (cmp > 0) { hi = mid; } else { lo = mid; } } while (lo < hi) { if (fmpz_equal(Li->table[lo].gammapow, w)) { g = Li->table[lo].cm + d; goto found_g; } lo++; } fmpz_mod_mul(w, w, Li->gammainv, L->fpctx); d++; if (d >= Li->dbound) { goto cleanup_and_throw; } } found_g: FLINT_ASSERT(g < Li->prime); fmpz_mod_pow_ui(temp, beta, g, L->fpctx); fmpz_mod_mul(z, z, temp, L->fpctx); fmpz_mod_pow_ui(beta, beta, Li->prime, L->fpctx); fmpz_addmul_ui(acc, pipow, g); fmpz_mul_ui(pipow, pipow, Li->prime); fmpz_divexact_ui(e, e, Li->prime); } while (++j < Li->exp); fmpz_addmul(x, acc, Li->idem); } fmpz_mod(xx, x, L->pm1); fmpz_clear(acc); fmpz_clear(pipow); fmpz_clear(e); fmpz_clear(beta); fmpz_clear(z); fmpz_clear(w); fmpz_clear(temp); fmpz_clear(x); return; cleanup_and_throw: fmpz_clear(acc); fmpz_clear(pipow); fmpz_clear(e); fmpz_clear(beta); fmpz_clear(z); fmpz_clear(w); fmpz_clear(temp); fmpz_clear(x); flint_throw(FLINT_ERROR, "Exception in fmpz_mod_discrete_log_pohlig_" "hellman_run: Could not find log."); return; } flint-3.1.3/src/fmpz_mod/divides.c000066400000000000000000000024531461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" int fmpz_mod_divides(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { int success; fmpz_t g, x, y, q; if (fmpz_is_zero(c)) { if (fmpz_is_zero(b)) { fmpz_zero(a); return 1; } else { return 0; } } else if (fmpz_is_zero(b)) { fmpz_zero(a); return 1; } /* b and c both not zero now */ fmpz_init(g); fmpz_init(x); fmpz_init(y); fmpz_init(q); /* solve g = c*x + n*y where g = gcd(c, n) */ fmpz_xgcd(g, x, y, c, ctx->n); fmpz_fdiv_qr(q, y, b, g); success = fmpz_is_zero(y); if (success) { fmpz_mul(a, q, x); fmpz_mod(a, a, ctx->n); } fmpz_clear(g); fmpz_clear(x); fmpz_clear(y); fmpz_clear(q); return success; } flint-3.1.3/src/fmpz_mod/equal_fmpz.c000066400000000000000000000017051461254215100175470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" int fmpz_mod_equal_fmpz(const fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) { int res; fmpz_t t; FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); fmpz_init(t); fmpz_mod_set_fmpz(t, b, ctx); res = fmpz_equal(a, t); fmpz_clear(t); return res; } int fmpz_mod_equal_si(const fmpz_t a, slong b, const fmpz_mod_ctx_t ctx) { int res; fmpz_t t; FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); fmpz_init(t); fmpz_mod_set_si(t, b, ctx); res = fmpz_equal(a, t); fmpz_clear(t); return res; } flint-3.1.3/src/fmpz_mod/inlines.c000066400000000000000000000006561461254215100170510ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_INLINES_C #include "fmpz_mod.h" flint-3.1.3/src/fmpz_mod/inv.c000066400000000000000000000016011461254215100161730ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" void fmpz_mod_inv(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) { fmpz_t d; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_init(d); fmpz_gcdinv(d, a, b, ctx->n); if (!fmpz_is_one(d)) { fmpz_clear(d); /* printing b and n would entail leaking the string so no b nor n */ flint_throw(FLINT_IMPINV, "Exception in fmpz_mod_inv: Cannot invert.\n"); } fmpz_clear(d); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint-3.1.3/src/fmpz_mod/is_canonical.c000066400000000000000000000013211461254215100200200ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" int fmpz_mod_is_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx) { return fmpz_sgn(a) >= 0 && fmpz_cmp(a, ctx->n) < 0; } void fmpz_mod_assert_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx) { if (!fmpz_mod_is_canonical(a, ctx)) flint_throw(FLINT_ERROR, "Fmpz mod invalid"); } flint-3.1.3/src/fmpz_mod/is_invertible.c000066400000000000000000000011641461254215100202410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" int fmpz_mod_is_invertible(const fmpz_t a, const fmpz_mod_ctx_t ctx) { int res; fmpz_t d; fmpz_init(d); fmpz_gcd(d, a, ctx->n); res = fmpz_is_one(d); fmpz_clear(d); return res; } flint-3.1.3/src/fmpz_mod/is_one.c000066400000000000000000000010311461254215100166500ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" int fmpz_mod_is_one(const fmpz_t a, const fmpz_mod_ctx_t ctx) { return fmpz_is_one(a) || fmpz_is_one(ctx->n); } flint-3.1.3/src/fmpz_mod/mul.c000066400000000000000000000136361461254215100162070ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_mod.h" void _fmpz_mod_mul1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t a0, b0, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); b0 = fmpz_get_ui(b); c0 = fmpz_get_ui(c); a0 = nmod_mul(b0, c0, ctx->mod); fmpz_set_ui(a, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } /* Multiplication modulo 2^FLINT_BITS is easy. */ void _fmpz_mod_mul2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t a0, b0, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); b0 = fmpz_get_ui(b); c0 = fmpz_get_ui(c); a0 = b0*c0; fmpz_set_ui(a, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } /* Standard Barrett reduction: (set r = FLINT_BITS) We have n fits into 2 words and 2^r < n < 2^(2r). Therefore 2^(3r) > 2^(4r) / n > 2^(2r) and the precomputed number ninv = floor(2^(4r) / n) fits into 3 words. The inputs b and c are < n and therefore fit into 2 words. The computation of a = b*c mod n is: x = b*c x < n^2 and therefore fits into 4 words z = (x >> r)*ninv z <= n*2^(3*r) and therefore fits into 5 words q = (z >> (3r))*n q fits into 4 words x = x - q x fits into 3 words after the subtraction at this point the canonical reduction in the range [0, n) is one of a = x, a = x - n, or a = x - 2n */ void _fmpz_mod_mul2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t a1, a0, b1, b0, c1, c0; mp_limb_t x3, x2, x1, x0; mp_limb_t q2, q1, q0; mp_limb_t z4, z3, z2, z1, z0; mp_limb_t t4, t3, t2, t1; mp_limb_t s3, s2, s1; mp_limb_t u4, u3, u2, u1; mp_limb_t v4, v3, v2, v1; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_get_uiui(&b1, &b0, b); fmpz_get_uiui(&c1, &c0, c); /* x[3:0] = b[1:0]*c[1:0] */ umul_ppmm(t2, t1, b0, c1); umul_ppmm(s2, s1, b1, c0); umul_ppmm(x3, x2, b1, c1); umul_ppmm(x1, x0, b0, c0); t3 = 0; add_sssaaaaaa(t3, t2, t1, t3, t2, t1, 0, s2, s1); add_sssaaaaaa(x3, x2, x1, x3, x2, x1, t3, t2, t1); /* z[5:0] = x[3:1] * ninv[2:0], z[5] should end up zero */ umul_ppmm(z1, z0, x1, ctx->ninv_limbs[0]); umul_ppmm(z3, z2, x2, ctx->ninv_limbs[1]); z4 = x3 * ctx->ninv_limbs[2]; umul_ppmm(t3, t2, x3, ctx->ninv_limbs[0]); umul_ppmm(s3, s2, x1, ctx->ninv_limbs[2]); t4 = 0; add_sssaaaaaa(t4, t3, t2, t4, t3, t2, 0, s3, s2); umul_ppmm(u2, u1, x2, ctx->ninv_limbs[0]); umul_ppmm(u4, u3, x3, ctx->ninv_limbs[1]); add_sssaaaaaa(z4, z3, z2, z4, z3, z2, t4, t3, t2); umul_ppmm(v2, v1, x1, ctx->ninv_limbs[1]); umul_ppmm(v4, v3, x2, ctx->ninv_limbs[2]); add_ssssaaaaaaaa(z4, z3, z2, z1, z4, z3, z2, z1, u4, u3, u2, u1); add_ssssaaaaaaaa(z4, z3, z2, z1, z4, z3, z2, z1, v4, v3, v2, v1); /* q[3:0] = z[4:3] * n[1:0], q[3] is not needed */ /* x[3:0] -= q[3:0], x[3] should end up zero */ umul_ppmm(t2, t1, z3, ctx->n_limbs[1]); umul_ppmm(s2, s1, z4, ctx->n_limbs[0]); umul_ppmm(q1, q0, z3, ctx->n_limbs[0]); sub_ddmmss(x2, x1, x2, x1, t2, t1); q2 = z4 * ctx->n_limbs[1]; sub_ddmmss(x2, x1, x2, x1, s2, s1); sub_dddmmmsss(x2, x1, x0, x2, x1, x0, q2, q1, q0); /* at most two subtractions of n, use q as temp space */ sub_dddmmmsss(q2, q1, q0, x2, x1, x0, 0, ctx->n_limbs[1], ctx->n_limbs[0]); if ((slong)(q2) >= 0) { sub_dddmmmsss(x2, x1, x0, q2, q1, q0, 0, ctx->n_limbs[1], ctx->n_limbs[0]); if ((slong)(x2) >= 0) { a1 = x1; a0 = x0; } else { a1 = q1; a0 = q0; } } else { a1 = x1; a0 = x0; } fmpz_set_uiui(a, a1, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void _fmpz_mod_mulN(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_mul(a, b, c); if (ctx->ninv_huge == NULL) fmpz_mod(a, a, ctx->n); else fmpz_fdiv_r_preinvn(a, a, ctx->n, ctx->ninv_huge); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_mul_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_mul(a, b, c); if (ctx->ninv_huge == NULL) fmpz_mod(a, a, ctx->n); else fmpz_fdiv_r_preinvn(a, a, ctx->n, ctx->ninv_huge); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_mul_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_mul_ui(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_mul_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_mul_si(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint-3.1.3/src/fmpz_mod/neg.c000066400000000000000000000012521461254215100161520ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" void fmpz_mod_neg(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_neg(a, b); if (fmpz_sgn(a) < 0) { fmpz_add(a, a, ctx->n); } FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint-3.1.3/src/fmpz_mod/next_smooth_prime.c000066400000000000000000000762151461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" /* An entry of {a, b, c, d, e, f, g, h} gives a prime 2^a * 5^b * 7^c * 11^d * 13^e * 17^f * 19^g * 23^h + 1 */ static const unsigned char _eight_primes[8] = {2, 5, 7, 11, 13, 17, 19, 23}; static const unsigned char _smooth_prime_lut[][8] = { {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.844100*2^16 = 33857 */ {0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00}, /*0x.895100*2^16 = 35153 */ {0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00}, /*0x.9df100*2^16 = 40433 */ {0x03, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00}, /*0x.b63900*2^16 = 46649 */ {0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.cea500*2^16 = 52901 */ {0x04, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, /*0x.840880*2^17 = 67601 */ {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, /*0x.8d1d80*2^17 = 72251 */ {0x01, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00}, /*0x.91e580*2^17 = 74699 */ {0x06, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, /*0x.992080*2^17 = 78401 */ {0x04, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, /*0x.e1c880*2^17 = 115601 */ {0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00}, /*0x.8fb040*2^18 = 147137 */ {0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00}, /*0x.998840*2^18 = 157217 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}, /*0x.9d0c40*2^18 = 160817 */ {0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00}, /*0x.a30f40*2^18 = 166973 */ {0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}, /*0x.a66040*2^18 = 170369 */ {0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00}, /*0x.865720*2^19 = 275129 */ {0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, /*0x.8d1d20*2^19 = 289001 */ {0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, /*0x.b04520*2^19 = 361001 */ {0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.ca8220*2^19 = 414737 */ {0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00}, /*0x.cbc4a0*2^19 = 417317 */ {0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03}, /*0x.82b350*2^20 = 535349 */ {0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, /*0x.8d0410*2^20 = 577601 */ {0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.b131d0*2^20 = 725789 */ {0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00}, /*0x.b65190*2^20 = 746777 */ {0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.cea410*2^20 = 846401 */ {0x05, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00}, /*0x.865708*2^21 = 1100513 */ {0x01, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00}, /*0x.912298*2^21 = 1188947 */ {0x05, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00}, /*0x.91e508*2^21 = 1195169 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}, /*0x.a32088*2^21 = 1336337 */ {0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, /*0x.be1c08*2^21 = 1557377 */ {0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00}, /*0x.816404*2^22 = 2119937 */ {0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, /*0x.9485e4*2^22 = 2433401 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02}, /*0x.954c44*2^22 = 2446097 */ {0x04, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, /*0x.b06444*2^22 = 2890001 */ {0x03, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00}, /*0x.bbd264*2^22 = 3077273 */ {0x04, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00}, /*0x.81cda2*2^23 = 4253393 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, /*0x.88a422*2^23 = 4477457 */ {0x07, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00}, /*0x.91e502*2^23 = 4780673 */ {0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03}, /*0x.9a76c2*2^23 = 5061473 */ {0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.ca8202*2^23 = 6635777 */ {0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00}, /*0x.d24282*2^23 = 6889793 */ {0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00}, /*0x.95eed1*2^24 = 9826001 */ {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00}, /*0x.97210d*2^24 = 9904397 */ {0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00}, /*0x.a30f01*2^24 = 10686209 */ {0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03}, /*0x.a65881*2^24 = 10901633 */ {0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00}, /*0x.bec901*2^24 = 12503297 */ {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, /*0x.c46bef*2^24 = 12872687 */ {0x02, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00}, /*0x.8120a2*2^25 = 16924997 */ {0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.a17020*2^25 = 21160001 */ {0x01, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00}, /*0x.a4b385*2^25 = 21587723 */ {0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02}, /*0x.ae9c80*2^25 = 22886657 */ {0x08, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00}, /*0x.c19b80*2^25 = 25376513 */ {0x07, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00}, /*0x.eb1840*2^25 = 30814337 */ {0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02}, /*0x.ec5c82*2^25 = 30980357 */ {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03}, /*0x.860abe*2^26 = 35138297 */ {0x07, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00}, /*0x.861820*2^26 = 35152001 */ {0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00}, /*0x.8f97f4*2^26 = 37642193 */ {0x06, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00}, /*0x.9b0350*2^26 = 40635713 */ {0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03}, /*0x.cbf0c9*2^26 = 53461799 */ {0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00}, /*0x.e5f027*2^26 = 60276893 */ {0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02}, /*0x.e68aa1*2^26 = 60435077 */ {0x06, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00}, /*0x.848a68*2^27 = 69489473 */ {0x04, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00}, /*0x.99414e*2^27 = 80349809 */ {0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.9b0b88*2^27 = 81288257 */ {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00}, /*0x.a8081c*2^27 = 88096997 */ {0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02}, /*0x.abe630*2^27 = 90124673 */ {0x05, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00}, /*0x.c30d4c*2^27 = 102263393 */ {0x07, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00}, /*0x.cab590*2^27 = 106278017 */ {0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, /*0x.d58072*2^27 = 111936401 */ {0x08, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00}, /*0x.95eed0*2^28 = 157216001 */ {0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00}, /*0x.9d5379*2^28 = 164968337 */ {0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00}, /*0x.a38803*2^28 = 171475001 */ {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04}, /*0x.b468b2*2^28 = 189172517 */ {0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04}, /*0x.de0ab4*2^28 = 232827713 */ {0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03}, /*0x.dee093*2^28 = 233703737 */ {0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03}, /*0x.f71ae5*2^28 = 259108433 */ {0x06, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00}, /*0x.f9c9c4*2^28 = 261921857 */ {0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00}, /*0x.85d1dc*2^29 = 280640387 */ {0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00}, /*0x.8b4d71*2^29 = 292138529 */ {0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00}, /*0x.8d8018*2^29 = 296747777 */ {0x03, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00}, /*0x.9103b8*2^29 = 304117529 */ {0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04}, /*0x.9a4148*2^29 = 323496197 */ {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04}, /*0x.a242e6*2^29 = 340286657 */ {0x07, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00}, /*0x.b27abc*2^29 = 374298497 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00}, /*0x.e608d4*2^29 = 482417297 */ {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00}, /*0x.861924*2^30 = 562448657 */ {0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x02}, /*0x.87aa17*2^30 = 569017793 */ {0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04}, /*0x.912e62*2^30 = 608934017 */ {0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00}, /*0x.aa8471*2^30 = 715201649 */ {0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03}, /*0x.cbf0c9*2^30 = 855388769 */ {0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04}, /*0x.d13b51*2^30 = 877581377 */ {0x09, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00}, /*0x.d880c8*2^30 = 908079617 */ {0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02}, /*0x.e68aa1*2^30 = 966961217 */ {0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03}, /*0x.fb00f8*2^30 = 1052786177 */ {0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x00}, /*0x.a0931c*2^31 = 1346997857 */ {0x03, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00}, /*0x.a3d804*2^31 = 1374421577 */ {0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00}, /*0x.a8081c*2^31 = 1409551937 */ {0x05, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00}, /*0x.b18cde*2^31 = 1489399649 */ {0x08, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00}, /*0x.b928fe*2^31 = 1553235713 */ {0x09, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00}, /*0x.bb6a84*2^31 = 1572160001 */ {0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04}, /*0x.bbe1ac*2^31 = 1576064513 */ {0x06, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00}, /*0x.f568c2*2^31 = 2058641729 */ {0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}, /*0x.f8e977*2^31 = 2088025001 */ {0x05, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00}, /*0x.8932ac*2^32 = 2301799457 */ {0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00}, /*0x.a38803*2^32 = 2743600001 */ {0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03}, /*0x.a5b3a3*2^32 = 2780013497 */ {0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00}, /*0x.aa8471*2^32 = 2860806593 */ {0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04}, /*0x.b19b54*2^32 = 2979746969 */ {0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00}, /*0x.bf3e7a*2^32 = 3208542737 */ {0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03}, /*0x.cbf0c9*2^32 = 3421555073 */ {0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00}, /*0x.e5f027*2^32 = 3857721089 */ {0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03}, /*0x.f71ae5*2^32 = 4145734913 */ {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02}, /*0x.837e04*2^33 = 4412147777 */ {0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00}, /*0x.9533e3*2^33 = 5006411537 */ {0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00}, /*0x.a56bf6*2^33 = 5550632033 */ {0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00}, /*0x.bf8a7b*2^33 = 6427047617 */ {0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00}, /*0x.939645*2^34 = 9904396001 */ {0x06, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00}, /*0x.a94298*2^34 = 11358856001 */ {0x08, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}, /*0x.c7212c*2^34 = 13363360001 */ {0x07, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00}, /*0x.d4087e*2^34 = 14229305729 */ {0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00}, /*0x.91c5d6*2^35 = 19565295377 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02}, /*0x.9c25a4*2^35 = 20957701937 */ {0x0b, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00}, /*0x.a4b385*2^35 = 22105827329 */ {0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00}, /*0x.b9eea9*2^35 = 24955406633 */ {0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00}, /*0x.88953e*2^36 = 36663714497 */ {0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00}, /*0x.8e2ef9*2^36 = 38167092497 */ {0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02}, /*0x.a88b14*2^36 = 45242991617 */ {0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00}, /*0x.dddab5*2^36 = 59553569297 */ {0x0b, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00}, /*0x.808c76*2^37 = 69014050817 */ {0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02}, /*0x.837e04*2^37 = 70594364417 */ {0x06, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x00}, /*0x.e14906*2^37 = 120949098689 */ {0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03}, /*0x.f247ed*2^37 = 130073600897 */ {0x05, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00}, /*0x.891584*2^38 = 147192883553 */ {0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, /*0x.8d2d93*2^38 = 151588750337 */ {0x05, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x00}, /*0x.a9b974*2^38 = 182240227937 */ {0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00}, /*0x.aa9c4e*2^38 = 183191708417 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02}, /*0x.be4501*2^38 = 204300384017 */ {0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00}, /*0x.83b9db*2^39 = 282879454157 */ {0x03, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02}, /*0x.8dc0da*2^39 = 304412978057 */ {0x08, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00}, /*0x.91c5d6*2^39 = 313044726017 */ {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05}, /*0x.a475be*2^39 = 353175013097 */ {0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00}, /*0x.b12d9e*2^39 = 380487276737 */ {0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02}, /*0x.84d120*2^40 = 570444263777 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04}, /*0x.87dbb3*2^40 = 583506543377 */ {0x0b, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04}, /*0x.b19b54*2^40 = 762815223809 */ {0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00}, /*0x.b441b3*2^40 = 774196400849 */ {0x09, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x00}, /*0x.d97505*2^40 = 933971204609 */ {0x08, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00}, /*0x.843c07*2^41 = 1135885600001 */ {0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00}, /*0x.888697*2^41 = 1172747210753 */ {0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04}, /*0x.e4d056*2^41 = 1965495725057 */ {0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05}, /*0x.eb99b5*2^41 = 2023792202177 */ {0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05}, /*0x.ff4f49*2^41 = 2193093768449 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00}, /*0x.9a307b*2^42 = 2648953372337 */ {0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03}, /*0x.a0981a*2^42 = 2758986583937 */ {0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00}, /*0x.b441b3*2^42 = 3096785603393 */ {0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04}, /*0x.b905ed*2^42 = 3178673621897 */ {0x0c, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00}, /*0x.91c5d6*2^43 = 5008715616257 */ {0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04}, /*0x.9d3f29*2^43 = 5402956229477 */ {0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06}, /*0x.b780fc*2^43 = 6305144584289 */ {0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04}, /*0x.c188d0*2^43 = 6649792282433 */ {0x09, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05}, /*0x.e64708*2^43 = 7912273686017 */ {0x0e, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00}, /*0x.88953e*2^44 = 9385910910977 */ {0x08, 0x00, 0x00, 0x03, 0x00, 0x03, 0x03, 0x00}, /*0x.a71693*2^44 = 11482212704513 */ {0x09, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00}, /*0x.b1cc15*2^44 = 12218130738689 */ {0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00}, /*0x.b71992*2^44 = 12582528518597 */ {0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00}, /*0x.c09a74*2^44 = 13235600933057 */ {0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0x03}, /*0x.81f434*2^45 = 17860731323033 */ {0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, /*0x.824fa5*2^45 = 17909824000001 */ {0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05}, /*0x.8a7e19*2^45 = 19034274390017 */ {0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x03}, /*0x.aac163*2^45 = 23468446238849 */ {0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x04}, /*0x.afd1ec*2^45 = 24164518848809 */ {0x07, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00}, /*0x.8f8e40*2^46 = 39460283394689 */ {0x09, 0x00, 0x00, 0x02, 0x00, 0x03, 0x04, 0x00}, /*0x.904dad*2^46 = 39665825706497 */ {0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x05}, /*0x.949185*2^46 = 40838184409049 */ {0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04}, /*0x.994991*2^46 = 42135314605889 */ {0x0c, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02}, /*0x.be4501*2^46 = 52300898308097 */ {0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00}, /*0x.d70414*2^46 = 59103129876737 */ {0x06, 0x04, 0x00, 0x03, 0x00, 0x05, 0x00, 0x00}, /*0x.8980d2*2^47 = 75593186680001 */ {0x06, 0x00, 0x00, 0x00, 0x03, 0x04, 0x03, 0x00}, /*0x.928519*2^47 = 80550180747713 */ {0x09, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04}, /*0x.9aeed1*2^47 = 85175254422017 */ {0x0c, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04}, /*0x.ae23b2*2^47 = 95734170259457 */ {0x07, 0x00, 0x00, 0x00, 0x04, 0x03, 0x03, 0x00}, /*0x.e016dc*2^47 = 123194394084737 */ {0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x03}, /*0x.f990cc*2^47 = 137200147242497 */ {0x05, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04}, /*0x.9eb652*2^48 = 174505901433953 */ {0x0c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00}, /*0x.b441b3*2^48 = 198194278617089 */ {0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00}, /*0x.c09a74*2^48 = 211769614928897 */ {0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00}, /*0x.d60e05*2^48 = 235355705857793 */ {0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05}, /*0x.f158f3*2^48 = 265364345982209 */ {0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06}, /*0x.f61ae6*2^48 = 270595393646657 */ {0x07, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00}, /*0x.9269d5*2^49 = 321966500707457 */ {0x05, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x04}, /*0x.9acde5*2^49 = 340418212612193 */ {0x05, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x02}, /*0x.a006b7*2^49 = 351901402632737 */ {0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x03}, /*0x.aac163*2^49 = 375495139821569 */ {0x07, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x04}, /*0x.afd1ec*2^49 = 386632301580929 */ {0x09, 0x00, 0x00, 0x03, 0x00, 0x04, 0x03, 0x00}, /*0x.b187fc*2^49 = 390395231953409 */ {0x0a, 0x00, 0x00, 0x04, 0x00, 0x02, 0x04, 0x00}, /*0x.80633a*2^50 = 564654695351297 */ {0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04}, /*0x.995f05*2^50 = 674533564142657 */ {0x05, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x02}, /*0x.9c1601*2^50 = 686473325633057 */ {0x0d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05}, /*0x.af8682*2^50 = 771969006493697 */ {0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00}, /*0x.e4b76a*2^50 = 1005905670912257 */ {0x0b, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00}, /*0x.f57d1b*2^50 = 1079670712526849 */ {0x04, 0x00, 0x03, 0x00, 0x00, 0x04, 0x05, 0x00}, /*0x.810779*2^51 = 1134952780009553 */ {0x0a, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04}, /*0x.89d83e*2^51 = 1212494798242817 */ {0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00}, /*0x.979a60*2^51 = 1333514367843857 */ {0x08, 0x00, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00}, /*0x.988724*2^51 = 1341649635419393 */ {0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05}, /*0x.ab341a*2^51 = 1505922190729217 */ {0x09, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00}, /*0x.e24678*2^51 = 1990338368009729 */ {0x08, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x04}, /*0x.82fcfd*2^52 = 2304369439220993 */ {0x09, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00}, /*0x.c775a6*2^52 = 3508929815712257 */ {0x07, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x03}, /*0x.d32cd5*2^52 = 3715032115190657 */ {0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05}, /*0x.e20acb*2^52 = 3976575784894337 */ {0x0d, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00}, /*0x.f57d1b*2^52 = 4318682850107393 */ {0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06}, /*0x.f61ae6*2^52 = 4329526298346497 */ {0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07}, /*0x.83e4b5*2^53 = 4640586414035969 */ {0x0a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x04}, /*0x.86205f*2^53 = 4719155235859457 */ {0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x04}, /*0x.91be0f*2^53 = 5127855503188289 */ {0x09, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x02}, /*0x.a006b7*2^53 = 5630422442123777 */ {0x04, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x02}, /*0x.a5d761*2^53 = 5835023267880977 */ {0x05, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x05}, /*0x.a7b2d0*2^53 = 5900366165444129 */ {0x0a, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04}, /*0x.c4964c*2^53 = 6916793801245697 */ {0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03}, /*0x.fff2d5*2^53 = 9005389675632797 */ {0x0a, 0x00, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00}, /*0x.826a76*2^54 = 9177201056478209 */ {0x0e, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00}, /*0x.a08308*2^54 = 11295016684896257 */ {0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07}, /*0x.a9eba6*2^54 = 11957093243378177 */ {0x0f, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04}, /*0x.b905ed*2^54 = 13019847155286017 */ {0x08, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x04}, /*0x.cc2799*2^54 = 14366108924559617 */ {0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00}, /*0x.d60e05*2^54 = 15062765174898689 */ {0x0a, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x04}, /*0x.ff86a2*2^54 = 17981038331696129 */ {0x03, 0x00, 0x00, 0x04, 0x00, 0x05, 0x04, 0x00}, /*0x.99ff05*2^55 = 21673035298913417 */ {0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04}, /*0x.9f4671*2^55 = 22415987370332417 */ {0x06, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04}, /*0x.a61283*2^55 = 23372600161000001 */ {0x07, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x05}, /*0x.a7b2d0*2^55 = 23601464661776513 */ {0x04, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x04}, /*0x.acf206*2^55 = 24339902201771729 */ {0x0d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00}, /*0x.cca41b*2^55 = 28800667630329857 */ {0x05, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05}, /*0x.81de59*2^56 = 36554746651804001 */ {0x09, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x03}, /*0x.83933c*2^56 = 37035109568375297 */ {0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x07, 0x00}, /*0x.9049b5*2^56 = 40613441463082337 */ {0x07, 0x00, 0x00, 0x00, 0x04, 0x03, 0x05, 0x00}, /*0x.9e001e*2^56 = 44473176264589697 */ {0x0b, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06}, /*0x.ad77ef*2^56 = 48827039660726273 */ {0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x05}, /*0x.b06ccf*2^56 = 49659232241402369 */ {0x0d, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00}, /*0x.c775a6*2^56 = 56142877051396097 */ {0x0a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x05, 0x00}, /*0x.810779*2^57 = 72636977920611329 */ {0x09, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07, 0x00}, /*0x.82ee0d*2^57 = 73706975968096769 */ {0x04, 0x00, 0x00, 0x00, 0x04, 0x06, 0x03, 0x00}, /*0x.8664b5*2^57 = 75656757267288497 */ {0x06, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04}, /*0x.8d2955*2^57 = 79466840547400001 */ {0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x04}, /*0x.9aea8e*2^57 = 87210089490338657 */ {0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x04}, /*0x.ad11b2*2^57 = 97429254560577473 */ {0x08, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x04}, /*0x.f07e74*2^57 = 135386066903794433 */ {0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04}, /*0x.819081*2^58 = 145876635844000001 */ {0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06}, /*0x.84014d*2^58 = 148624519960425809 */ {0x05, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x05}, /*0x.90be60*2^58 = 162966878976323489 */ {0x0b, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03}, /*0x.9a628e*2^58 = 173822035526957057 */ {0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00}, /*0x.ceb3de*2^58 = 232726447479951617 */ {0x04, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x04}, /*0x.d2e3bb*2^58 = 237440562208387409 */ {0x07, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x03}, /*0x.e501b1*2^58 = 257838525449696897 */ {0x0b, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x03}, /*0x.f0e48c*2^58 = 271221147877881857 */ {0x05, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x05}, /*0x.8064e7*2^59 = 289117942106762273 */ {0x0a, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x03}, /*0x.8408ea*2^59 = 297315993395233793 */ {0x07, 0x00, 0x00, 0x04, 0x00, 0x05, 0x04, 0x00}, /*0x.99ff05*2^59 = 346768564782614657 */ {0x06, 0x00, 0x00, 0x00, 0x04, 0x04, 0x05, 0x00}, /*0x.a7e020*2^59 = 378021998249012417 */ {0x03, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x03}, /*0x.a9d925*2^59 = 382464196812169337 */ {0x08, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x04}, /*0x.acf206*2^59 = 389438435228347649 */ {0x0a, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x05}, /*0x.d28947*2^59 = 474085466112941057 */ {0x0c, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05}, /*0x.e42616*2^59 = 513745373821554689 */ {0x0b, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x04}, /*0x.8c9301*2^60 = 633090104031987713 */ {0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07}, /*0x.8fb8b5*2^60 = 647264181602801153 */ {0x08, 0x05, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05}, /*0x.94ffc8*2^60 = 671032524882400001 */ {0x06, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x05}, /*0x.a6d946*2^60 = 751419878122533569 */ {0x02, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x04}, /*0x.ab5908*2^60 = 771681827177259077 */ {0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07}, /*0x.c9c7d6*2^60 = 908739086496741377 */ {0x08, 0x00, 0x00, 0x00, 0x05, 0x04, 0x04, 0x00}, /*0x.e5b96f*2^60 = 1034586521523612929 */ {0x05, 0x00, 0x00, 0x05, 0x00, 0x04, 0x05, 0x00}, /*0x.eca7e8*2^60 = 1065803382934800929 */ {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04}, /*0x.87146c*2^61 = 1216690499828859137 */ {0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x05}, /*0x.8b1613*2^61 = 1252777462003947857 */ {0x06, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00}, /*0x.8be775*2^61 = 1260144420067663937 */ {0x04, 0x00, 0x00, 0x06, 0x05, 0x00, 0x04, 0x00}, /*0x.984566*2^61 = 1371536150082683729 */ {0x09, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06}, /*0x.a3fb5f*2^61 = 1477017949736969729 */ {0x03, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05}, /*0x.b146da*2^61 = 1596767241010383833 */ {0x0a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x04}, /*0x.bd23a6*2^61 = 1703615040145263617 */ {0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x05}, /*0x.eff6f1*2^61 = 2161409183296708049 */ {0x09, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x03}, /*0x.f46a41*2^61 = 2201495174870396417 */ {0x09, 0x00, 0x06, 0x00, 0x04, 0x05, 0x00, 0x00}, /*0x.879957*2^62 = 2442734224193675777 */ {0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05}, /*0x.953920*2^62 = 2688165230588571137 */ {0x0a, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x04}, /*0x.9c4e51*2^62 = 2815757349213684737 */ {0x0a, 0x00, 0x00, 0x04, 0x00, 0x04, 0x05, 0x00}, /*0x.ac1d06*2^62 = 3100518932173966337 */ {0x0a, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x05}, /*0x.b22dfd*2^62 = 3209799194001605633 */ {0x04, 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x05}, /*0x.b7a892*2^62 = 3308497009961476433 */ {0x05, 0x00, 0x00, 0x00, 0x05, 0x06, 0x00, 0x03}, /*0x.c1b28f*2^62 = 3489343914192823649 */ {0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x05}, /*0x.e7d2cf*2^62 = 4176160476488696177 */ {0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04}, /*0x.ecd4d8*2^62 = 4266375778652655617 */ {0x08, 0x00, 0x07, 0x00, 0x00, 0x04, 0x00, 0x04}, /*0x.88c487*2^63 = 4927575361123948289 */ {0x0a, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x03}, /*0x.89e678*2^63 = 4968381033816251393 */ {0x03, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05, 0x03}, /*0x.a177b1*2^63 = 5817481730458786217 */ {0x09, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x05}, /*0x.ae850c*2^63 = 6287735805954059777 */ {0x0b, 0x00, 0x05, 0x00, 0x00, 0x05, 0x04, 0x00}, /*0x.b0c74a*2^63 = 6369116063986235393 */ {0x07, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x04}, /*0x.b7f689*2^63 = 6627966801265737857 */ {0x08, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x05}, /*0x.d25c89*2^63 = 7579071085597842689 */ {0x0a, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x04}, /*0x.f6a55c*2^63 = 8886356819536049153 */ {0x07, 0x00, 0x00, 0x06, 0x04, 0x05, 0x00, 0x00}, /*0x.ff3b45*2^63 = 9195685226705650817 */ {0x07, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x06}, /*0x.80110e*2^64 = 9228172682754616193 */ {0x07, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x06}, /*0x.81f468*2^64 = 9364224192536177537 */ {0x0a, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0x03}, /*0x.86689d*2^64 = 9685164563070211073 */ {0x0b, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x03}, /*0x.8c4978*2^64 = 10108743775437948929 */ {0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x05}, /*0x.8e7a9f*2^64 = 10266693620659363229 */ {0x0a, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00, 0x00}, /*0x.8f6f97*2^64 = 10335646205222880257 */ {0x05, 0x00, 0x07, 0x00, 0x00, 0x05, 0x00, 0x04}, /*0x.9150cf*2^64 = 10471097642388390113 */ {0x0a, 0x00, 0x05, 0x00, 0x04, 0x06, 0x00, 0x00}, /*0x.a4a7ea*2^64 = 11864709088940710913 */ {0x05, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x06}, /*0x.e01dd8*2^64 = 16149302194820578337 */ {0x08, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04}, /*0x.e3578a*2^64 = 16381714095359126273 */ {0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x04}, /*0x.e58808*2^64 = 16539478967835678977 */ {0x0d, 0x00, 0x00, 0x08, 0x06, 0x08, 0x00, 0x07}, /*0x.977400*2^128 = 201315753943344863644036821430284967937 */ {0x03, 0x00, 0x00, 0x00, 0x07, 0x08, 0x08, 0x07}, /*0x.985698*2^128 = 202492286286810790437922936221068336153 */ {0x0e, 0x00, 0x00, 0x00, 0x05, 0x07, 0x06, 0x09}, /*0x.9f2141*2^128 = 211519923313957068893521212124359344129 */ {0x08, 0x07, 0x00, 0x00, 0x00, 0x08, 0x07, 0x09}, /*0x.a8fc1b*2^128 = 224619314500089695434264067444740000001 */ {0x08, 0x00, 0x00, 0x00, 0x09, 0x06, 0x06, 0x08}, /*0x.b59f3c*2^128 = 241417060812417193281164455701879284993 */ {0x14, 0x00, 0x00, 0x00, 0x00, 0x07, 0x09, 0x09}, /*0x.bc233f*2^128 = 250077889582264191015188456592240541697 */ {0x09, 0x00, 0x00, 0x07, 0x00, 0x08, 0x06, 0x08}, /*0x.c0e8fb*2^128 = 256421491496774145772985886547254564353 */ {0x0b, 0x00, 0x00, 0x08, 0x09, 0x07, 0x00, 0x06}, /*0x.d4c040*2^128 = 282794572515043903725031263863386236929 */ {0x0c, 0x00, 0x00, 0x00, 0x07, 0x06, 0x09, 0x06}, /*0x.def31f*2^128 = 296350979539355403848369839560486350849 */ {0x0e, 0x00, 0x00, 0x08, 0x00, 0x06, 0x06, 0x08}, /*0x.eaf691*2^128 = 312319602099877160249449937939908673537 */ {0x0a, 0x00, 0x00, 0x07, 0x00, 0x09, 0x07, 0x06}, /*0x.eb938f*2^128 = 313134751430843285764364617598348674049 */ {0x0e, 0x00, 0x00, 0x07, 0x00, 0x07, 0x08, 0x06}, /*0x.f7cdb5*2^128 = 329387420190229615475317798442553622529 */ {0x17, 0x00, 0x00, 0x00, 0x0d, 0x0b, 0x07, 0x0a}, /*0x.838004*2^192 = 3224372305314505999731230563592619434528670607112207859713 */ {0x1c, 0x00, 0x00, 0x00, 0x07, 0x0b, 0x0a, 0x0b}, /*0x.898840*2^192 = 3372280456223566487919284082022261011830810717167059730433 */ {0x17, 0x00, 0x00, 0x00, 0x07, 0x0b, 0x08, 0x0e}, /*0x.90daa6*2^192 = 3551812353780482466976621314574519540421180228165825462273 */ {0x1c, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x0a, 0x0a}, /*0x.916542*2^192 = 3565088486727419991008074270946581990658772639631336800257 */ {0x1a, 0x00, 0x00, 0x00, 0x0b, 0x07, 0x0d, 0x09}, /*0x.987331*2^192 = 3738062417125879757367726246205088567592814768935128793089 */ {0x18, 0x00, 0x00, 0x09, 0x0a, 0x06, 0x08, 0x09}, /*0x.a439ca*2^192 = 4026803574740221083962824220953216561664085820467721535489 */ {0x18, 0x00, 0x00, 0x0a, 0x0a, 0x0c, 0x0b, 0x00}, /*0x.a60cb0*2^192 = 4071523423234022089688349550455788710099661020875672518657 */ {0x1b, 0x00, 0x00, 0x0d, 0x00, 0x0a, 0x0a, 0x08}, /*0x.b6e99c*2^192 = 4485002623661810971674618955226749177284334955906719547393 */ {0x18, 0x00, 0x00, 0x00, 0x09, 0x08, 0x09, 0x0e}, /*0x.bd5860*2^192 = 4642731312024884673910820696559650822020113866330334035969 */ {0x19, 0x00, 0x00, 0x09, 0x0a, 0x08, 0x07, 0x08}, /*0x.d936c3*2^192 = 5326069716704457177415360182404940898493916714485910863873 */ {0x1a, 0x00, 0x00, 0x07, 0x00, 0x0a, 0x0c, 0x0b}, /*0x.e2c01b*2^192 = 5559904152009347893564996369584799073711455527208675704833 */ {0x17, 0x00, 0x00, 0x0d, 0x00, 0x0b, 0x09, 0x09}, /*0x.eb425c*2^192 = 5768539558722921348436763195702825422099259762366866259969 */ }; static const slong num_entries = sizeof(_smooth_prime_lut)/sizeof(const unsigned char [8]); static void _get_lut_entry(fmpz_t p, slong i) { slong j; fmpz_one(p); for (j = 0; j < 8; j++) { fmpz_t t; fmpz_init_set_ui(t, _eight_primes[j]); fmpz_pow_ui(t, t, _smooth_prime_lut[i][j]); fmpz_mul(p, p, t); fmpz_clear(t); } fmpz_add_ui(p, p, 1); } int fmpz_next_smooth_prime(fmpz_t a, const fmpz_t b) { int success; slong lo, mid, hi; fmpz_t lo_p, mid_p, hi_p; fmpz_init(lo_p); fmpz_init(mid_p); fmpz_init(hi_p); FLINT_ASSERT(num_entries > 1); lo = 0; hi = num_entries - 1; _get_lut_entry(lo_p, lo); _get_lut_entry(hi_p, hi); if (fmpz_cmp(b, lo_p) < 0) { fmpz_swap(a, lo_p); success = 1; goto cleanup; } if (fmpz_cmp(hi_p, b) <= 0) { fmpz_zero(a); success = 0; goto cleanup; } /* lo_p <= b < hi_p now */ while (hi - lo > 4) { mid = lo + (hi - lo)/2; _get_lut_entry(mid_p, mid); if (fmpz_cmp(b, mid_p) < 0) { hi = mid; fmpz_swap(hi_p, mid_p); } else { lo = mid; fmpz_swap(lo_p, mid_p); } } for (; lo <= hi; lo++) { _get_lut_entry(lo_p, lo); if (fmpz_cmp(lo_p, b) > 0) { fmpz_swap(a, lo_p); success = 1; goto cleanup; } } success = 0; fmpz_zero(a); cleanup: fmpz_clear(lo_p); fmpz_clear(mid_p); fmpz_clear(hi_p); return success; } flint-3.1.3/src/fmpz_mod/pow.c000066400000000000000000000064741461254215100162210ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "gr.h" #include "gr_generic.h" #ifdef FLINT_HAVE_FFT_SMALL void _fmpz_mod_pow_fmpz(fmpz_t res, const fmpz_t x, const fmpz_t e, const fmpz_mod_ctx_t ctx) { if (*e <= 2) { if (*e == 0) fmpz_mod_set_ui(res, 1, ctx); else if (*e == 1) fmpz_set(res, x); else fmpz_mod_mul(res, x, x, ctx); } else if (fmpz_is_zero(x) || fmpz_is_one(x)) { fmpz_set(res, x); } else if (fmpz_bits(ctx->n) < 70000) { fmpz_powm(res, x, e, ctx->n); } else { gr_ctx_t gctx; _gr_ctx_init_fmpz_mod_from_ref(gctx, ctx); if (!COEFF_IS_MPZ(*x) || fmpz_bits(e) < 20) GR_MUST_SUCCEED(gr_generic_pow_fmpz_binexp(res, x, e, gctx)); else GR_MUST_SUCCEED(gr_generic_pow_fmpz_sliding(res, x, e, gctx)); } } #else void _fmpz_mod_pow_fmpz(fmpz_t res, const fmpz_t x, const fmpz_t e, const fmpz_mod_ctx_t ctx) { fmpz_powm(res, x, e, ctx->n); } #endif int fmpz_mod_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t pow, const fmpz_mod_ctx_t ctx) { int success = 1; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); if (fmpz_sgn(pow) >= 0) { _fmpz_mod_pow_fmpz(a, b, pow, ctx); } else { fmpz_t d; fmpz_init(d); fmpz_gcdinv(d, a, b, ctx->n); if (fmpz_is_one(d)) { fmpz_neg(d, pow); _fmpz_mod_pow_fmpz(a, a, d, ctx); } else { success = 0; } fmpz_clear(d); } FLINT_ASSERT(!success || fmpz_mod_is_canonical(a, ctx)); return success; } #ifdef FLINT_HAVE_FFT_SMALL void _fmpz_mod_pow_ui(fmpz_t res, const fmpz_t x, ulong e, const fmpz_mod_ctx_t ctx) { if (e <= 2) { if (e == 0) fmpz_mod_set_ui(res, 1, ctx); else if (e == 1) fmpz_set(res, x); else fmpz_mod_mul(res, x, x, ctx); } else if (fmpz_is_zero(x) || fmpz_is_one(x)) { fmpz_set(res, x); } else if (fmpz_bits(ctx->n) < 70000) { fmpz_powm_ui(res, x, e, ctx->n); } else { gr_ctx_t gctx; _gr_ctx_init_fmpz_mod_from_ref(gctx, ctx); if (!COEFF_IS_MPZ(*x) || FLINT_BIT_COUNT(e) < 20) GR_MUST_SUCCEED(gr_generic_pow_ui_binexp(res, x, e, gctx)); else GR_MUST_SUCCEED(gr_generic_pow_ui_sliding(res, x, e, gctx)); } } #else void _fmpz_mod_pow_ui(fmpz_t res, const fmpz_t x, ulong e, const fmpz_mod_ctx_t ctx) { fmpz_powm_ui(res, x, e, ctx->n); } #endif void fmpz_mod_pow_ui(fmpz_t a, const fmpz_t b, ulong pow, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); _fmpz_mod_pow_ui(a, b, pow, ctx); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint-3.1.3/src/fmpz_mod/rand.c000066400000000000000000000014671461254215100163350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" void fmpz_mod_rand(fmpz_t a, flint_rand_t state, const fmpz_mod_ctx_t ctx) { fmpz_randm(a, state, fmpz_mod_ctx_modulus(ctx)); } void fmpz_mod_rand_not_zero(fmpz_t a, flint_rand_t state, const fmpz_mod_ctx_t ctx) { slong i = 3; for (i = 0; i < 3; i++) { fmpz_randm(a, state, fmpz_mod_ctx_modulus(ctx)); if (!fmpz_is_zero(a)) return; } fmpz_one(a); } flint-3.1.3/src/fmpz_mod/set_fmpz.c000066400000000000000000000020021461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" void fmpz_mod_set_fmpz(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) { if (ctx->ninv_huge == NULL) fmpz_mod(a, b, ctx->n); else fmpz_fdiv_r_preinvn(a, b, ctx->n, ctx->ninv_huge); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_set_ui(fmpz_t a, ulong b, const fmpz_mod_ctx_t ctx) { fmpz_set_ui(a, b); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_set_si(fmpz_t a, slong b, const fmpz_mod_ctx_t ctx) { fmpz_set_si(a, b); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint-3.1.3/src/fmpz_mod/set_modulus.c000066400000000000000000000012271461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" void fmpz_mod_ctx_set_modulus(fmpz_mod_ctx_t ctx, const fmpz_t n) { fmpz_mod_ctx_clear(ctx); fmpz_mod_ctx_init(ctx, n); } void fmpz_mod_ctx_set_modulus_ui(fmpz_mod_ctx_t ctx, ulong n) { fmpz_mod_ctx_clear(ctx); fmpz_mod_ctx_init_ui(ctx, n); } flint-3.1.3/src/fmpz_mod/sub.c000066400000000000000000000077551461254215100162100ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_mod.h" void _fmpz_mod_sub1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t a0, b0, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); b0 = fmpz_get_ui(b); c0 = fmpz_get_ui(c); a0 = nmod_sub(b0, c0, ctx->mod); fmpz_set_ui(a, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void _fmpz_mod_sub2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t a0, b0, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); b0 = fmpz_get_ui(b); c0 = fmpz_get_ui(c); a0 = b0 - c0; fmpz_set_ui(a, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void _fmpz_mod_sub2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { mp_limb_t a2, a1, a0, b1, b0, c1, c0; FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_get_uiui(&b1, &b0, b); fmpz_get_uiui(&c1, &c0, c); sub_dddmmmsss(a2, a1, a0, 0, b1, b0, 0, c1, c0); if (a2 != 0) { add_ssaaaa(a1, a0, a1, a0, ctx->n_limbs[1], ctx->n_limbs[0]); } fmpz_set_uiui(a, a1, a0); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void _fmpz_mod_subN(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_sub(a, b, c); if (fmpz_sgn(a) < 0) { fmpz_add(a, a, ctx->n); } FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_sub_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_sub(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_sub_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_sub_ui(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_sub_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(b, ctx)); fmpz_sub_si(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_fmpz_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_sub(a, b, c); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_ui_sub(fmpz_t a, ulong b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_sub_ui(a, c, b); fmpz_neg(a, a); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } void fmpz_mod_si_sub(fmpz_t a, slong b, const fmpz_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx)); fmpz_sub_si(a, c, b); fmpz_neg(a, a); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint-3.1.3/src/fmpz_mod/test/000077500000000000000000000000001461254215100162145ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod/test/main.c000066400000000000000000000023311461254215100173030ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub_neg.c" #include "t-discrete_log_pohlig_hellman.c" #include "t-divides.c" #include "t-inv.c" #include "t-mul.c" #include "t-next_smooth_prime.c" #include "t-pow_fmpz.c" #include "t-pow_ui.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mod_add_sub_neg), TEST_FUNCTION(fmpz_mod_discrete_log_pohlig_hellman), TEST_FUNCTION(fmpz_mod_divides), TEST_FUNCTION(fmpz_mod_inv), TEST_FUNCTION(fmpz_mod_mul), TEST_FUNCTION(fmpz_mod_next_smooth_prime), TEST_FUNCTION(fmpz_mod_pow_fmpz), TEST_FUNCTION(fmpz_mod_pow_ui) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mod/test/t-add_sub_neg.c000066400000000000000000000044241461254215100210570ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_add_sub_neg, state) { slong i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; /* p not nec prime */ fmpz_t a, b, c, d, e; fmpz_mod_ctx_t fpctx; fmpz_init_set_ui(p, 2); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(e); fmpz_mod_ctx_init(fpctx, p); for (j = 0; j < 10; j++) { fmpz_randtest_unsigned(p, state, 300); fmpz_add_ui(p, p, 1); fmpz_mod_ctx_set_modulus(fpctx, p); fmpz_randtest_mod(a, state, p); fmpz_randtest_mod(b, state, p); fmpz_randtest_mod(c, state, p); fmpz_randtest_mod(d, state, p); fmpz_randtest_mod(e, state, p); fmpz_mod_add(c, a, b, fpctx); fmpz_mod_assert_canonical(c, fpctx); fmpz_mod_sub(c, c, b, fpctx); fmpz_mod_assert_canonical(c, fpctx); if (!fmpz_equal(c, a)) { printf("FAIL1\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_sub(d, a, b, fpctx); fmpz_mod_assert_canonical(d, fpctx); fmpz_mod_sub(e, b, a, fpctx); fmpz_mod_assert_canonical(e, fpctx); fmpz_mod_neg(d, d, fpctx); if (!fmpz_equal(d, e)) { printf("FAIL2\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_ctx_clear(fpctx); fmpz_clear(p); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod/test/t-discrete_log_pohlig_hellman.c000066400000000000000000000110501461254215100243230ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_discrete_log_pohlig_hellman, state) { slong i, j, k; /* check random word-sized primes */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_t p, pm1; fmpz_mod_ctx_t fpctx; fmpz_mod_discrete_log_pohlig_hellman_t L; fmpz_init_set_ui(p, 2); fmpz_init_set_ui(pm1, 1); fmpz_mod_ctx_init(fpctx, p); fmpz_mod_discrete_log_pohlig_hellman_init(L); for (j = 0; j < 10; j++) { double score; fmpz_set_ui(p, n_randtest_prime(state, 1)); fmpz_sub_ui(pm1, p, 1); fmpz_mod_ctx_set_modulus(fpctx, p); score = fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(L, p); if (score > 10000) { continue; } for (k = 0; k < 10; k++) { fmpz_t x, y, xr; const fmpz * alpha = fmpz_mod_discrete_log_pohlig_hellman_primitive_root(L); fmpz_init(x); fmpz_init(y); fmpz_init(xr); fmpz_randm(x, state, pm1); fmpz_mod_pow_fmpz(y, alpha, x, fpctx); fmpz_mod_discrete_log_pohlig_hellman_run(xr, L, y); if (!fmpz_equal(x, xr)) { printf("FAIL\ncheck random word-sized primes\n"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); fmpz_clear(xr); } } fmpz_mod_discrete_log_pohlig_hellman_clear(L); fmpz_mod_ctx_clear(fpctx); fmpz_clear(p); fmpz_clear(pm1); } /* check smooth primes */ for (i = 0; i < flint_test_multiplier(); i++) { fmpz_t p; int success; double score; fmpz_mod_ctx_t fpctx; fmpz_mod_discrete_log_pohlig_hellman_t L; fmpz_init_set_ui(p, 2); fmpz_mod_ctx_init(fpctx, p); fmpz_mod_discrete_log_pohlig_hellman_init(L); for (j = 0; j < 1000; j++) { success = fmpz_next_smooth_prime(p, p); if (!success) { break; } if (1 != fmpz_is_prime(p)) { printf("FAIL\nprimality test failed p = "); fmpz_print(p); fflush(stdout); flint_abort(); } /* The primes returned by fmpz_next_smooth_prime should not require too many operations for discrete logarithms. */ fmpz_mod_ctx_set_modulus(fpctx, p); score = fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(L, p); if (score > 10000) { printf("FAIL\nsmooth prime score %f too high\np = ", score); fmpz_print(p); fflush(stdout); flint_abort(); } for (k = 0; k < 10; k++) { fmpz_t x, y, xr, pm1; const fmpz * alpha = fmpz_mod_discrete_log_pohlig_hellman_primitive_root(L); fmpz_init(x); fmpz_init(y); fmpz_init(xr); fmpz_init(pm1); fmpz_sub_ui(pm1, p, 1); fmpz_randm(x, state, pm1); fmpz_mod_pow_fmpz(y, alpha, x, fpctx); fmpz_mod_discrete_log_pohlig_hellman_run(xr, L, y); if (!fmpz_equal(x, xr)) { printf("FAIL\n"); flint_printf("i = %wd, j = %kw, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_clear(y); fmpz_clear(xr); fmpz_clear(pm1); } } fmpz_clear(p); fmpz_mod_ctx_clear(fpctx); fmpz_mod_discrete_log_pohlig_hellman_clear(L); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod/test/t-divides.c000066400000000000000000000074301461254215100202540ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_divides, state) { flint_bitcnt_t max_modulus_bits = 200; slong i, j; { fmpz_t p, a, b, c; fmpz_mod_ctx_t fpctx; fmpz_init_set_ui(p, 12); fmpz_mod_ctx_init(fpctx, p); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_set_ui(b, 6); fmpz_set_ui(c, 3); if (!fmpz_mod_divides(a, b, c, fpctx) || !( fmpz_equal_ui(a, 2) || fmpz_equal_ui(a, 6) || fmpz_equal_ui(a, 10) )) { printf("FAIL\n"); flint_printf("check 6/3 is 2, 6, or 10 mod 12\n"); fflush(stdout); flint_abort(); } fmpz_set_ui(b, 5); fmpz_set_ui(c, 3); if (fmpz_mod_divides(a, b, c, fpctx)) { printf("FAIL\n"); flint_printf("check 3 does not divide 5 mod 12\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_ctx_clear(fpctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; /* p not nec. prime */ fmpz_t a, b, c, u; fmpz_mod_ctx_t fpctx; fmpz_init_set_ui(p, 2); fmpz_mod_ctx_init(fpctx, p); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(u); for (j = 0; j < 100; j++) { fmpz_randtest_unsigned(p, state, max_modulus_bits); fmpz_add_ui(p, p, 1); fmpz_mod_ctx_set_modulus(fpctx, p); fmpz_randtest_mod(a, state, p); fmpz_randtest_mod(b, state, p); fmpz_randtest_mod(c, state, p); if (fmpz_mod_divides(a, b, c, fpctx)) { fmpz_mod_mul(u, a, c, fpctx); if (!fmpz_equal(u, b)) { printf("FAIL\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_randtest_mod(a, state, p); fmpz_randtest_mod(b, state, p); fmpz_randtest_mod(c, state, p); fmpz_set(a, b); if (fmpz_mod_divides(a, a, c, fpctx)) { fmpz_mod_mul(u, a, c, fpctx); if (!fmpz_equal(u, b)) { printf("FAIL\n"); flint_printf("aliasing first\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_randtest_mod(a, state, p); fmpz_randtest_mod(b, state, p); fmpz_randtest_mod(c, state, p); fmpz_set(a, c); if (fmpz_mod_divides(a, b, a, fpctx)) { fmpz_mod_mul(u, a, c, fpctx); if (!fmpz_equal(u, b)) { printf("FAIL\n"); flint_printf("aliasing second\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpz_clear(p); fmpz_mod_ctx_clear(fpctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod/test/t-inv.c000066400000000000000000000036261461254215100174240ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_inv, state) { slong i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_t a, ainv, b, g; fmpz_mod_ctx_t fpctx; fmpz_init_set_ui(p, 2); fmpz_init(a); fmpz_init(ainv); fmpz_init(b); fmpz_init(g); fmpz_mod_ctx_init(fpctx, p); for (j = 0; j < 20; j++) { fmpz_randtest_unsigned(p, state, 200); fmpz_add_ui(p, p, 1); fmpz_mod_ctx_set_modulus(fpctx, p); fmpz_randtest_mod(a, state, p); fmpz_gcd(g, a, p); if (!fmpz_is_one(g)) { continue; } fmpz_mod_inv(ainv, a, fpctx); fmpz_mod_mul(b, a, ainv, fpctx); if (!fmpz_mod_is_one(b, fpctx)) { printf("FAIL\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_inv(a, a, fpctx); if (!fmpz_equal(a, ainv)) { printf("FAIL\ncheck aliasing"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_ctx_clear(fpctx); fmpz_clear(p); fmpz_clear(a); fmpz_clear(ainv); fmpz_clear(b); fmpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod/test/t-mul.c000066400000000000000000000101721461254215100174170ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_mul, state) { flint_bitcnt_t max_bits = 200, max_bits_huge = 500 * FLINT_BITS; slong i, j, k; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; /* p not nec prime */ fmpz_t a, b, c, d, ab, bc; fmpz_mod_ctx_t fpctx; fmpz_init_set_ui(p, 2); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(ab); fmpz_init(bc); fmpz_mod_ctx_init(fpctx, p); for (j = 0; j < 10; j++) { if (j == 0) { /* exact powers of 2 */ fmpz_one(p); fmpz_mul_2exp(p, p, n_randint(state, max_bits)); } else if (j == 1) { /* sum of two powers of 2 */ fmpz_one(p); fmpz_mul_2exp(p, p, n_randint(state, max_bits/2)); fmpz_add_ui(p, p, 1); fmpz_mul_2exp(p, p, n_randint(state, max_bits/2)); } else if (j == 2) { /* one less than a power of 2 */ fmpz_one(p); fmpz_mul_2exp(p, p, 1 + n_randint(state, max_bits)); fmpz_sub_ui(p, p, 1); } else if (j == 3 && n_randint(state, 30) == 0) { fmpz_randtest_unsigned(p, state, max_bits_huge); fmpz_add_ui(p, p, 1); } else { fmpz_randtest_unsigned(p, state, max_bits); fmpz_add_ui(p, p, 1); } fmpz_mod_ctx_set_modulus(fpctx, p); for (k = 0; k < 10; k++) { if (k == 0) { fmpz_sub_ui(a, p, 1); fmpz_sub_ui(b, p, 1); fmpz_sub_ui(c, p, 1); fmpz_sub_ui(d, p, 1); fmpz_sub_ui(ab, p, 1); fmpz_sub_ui(bc, p, 1); } else { fmpz_randtest_mod(a, state, p); fmpz_randtest_mod(b, state, p); fmpz_randtest_mod(c, state, p); fmpz_randtest_mod(d, state, p); fmpz_randtest_mod(ab, state, p); fmpz_randtest_mod(bc, state, p); } fmpz_mul(ab, a, b); fmpz_mod(ab, ab, p); fmpz_mul(bc, b, c); fmpz_mod(bc, bc, p); fmpz_mod_mul(d, a, b, fpctx); if (!fmpz_equal(d, ab)) { printf("FAIL\n"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } fmpz_mod_mul(a, a, b, fpctx); if (!fmpz_equal(a, ab)) { printf("FAIL\ncheck aliasing first"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } fmpz_mod_mul(c, b, c, fpctx); if (!fmpz_equal(c, bc)) { printf("FAIL\ncheck aliasing second"); flint_printf("i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } } fmpz_mod_ctx_clear(fpctx); fmpz_clear(p); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(ab); fmpz_clear(bc); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod/test/t-next_smooth_prime.c000066400000000000000000000017201461254215100223640ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_next_smooth_prime, state) { slong i; fmpz_t p; int success; fmpz_init_set_ui(p, 2); for (i = 0; i < 2000; i++) { success = fmpz_next_smooth_prime(p, p); if (!success) { break; } if (1 != fmpz_is_prime(p)) { printf("FAIL\nprimality test failed p = "); fmpz_print(p); fflush(stdout); flint_abort(); } } fmpz_clear(p); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod/test/t-pow_fmpz.c000066400000000000000000000104111461254215100204570ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_pow_fmpz, state) { flint_bitcnt_t max_exp_bits = 200; flint_bitcnt_t max_modulus_bits = 200; slong i, j; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_t p; /* p not nec. prime */ fmpz_t a, b, u, v, w, x; fmpz_t e, f, t; fmpz_mod_ctx_t fpctx; fmpz_init_set_ui(p, 2); fmpz_mod_ctx_init(fpctx, p); fmpz_init(a); fmpz_init(b); fmpz_init(u); fmpz_init(v); fmpz_init(w); fmpz_init(x); fmpz_init(e); fmpz_init(f); fmpz_init(t); for (j = 0; j < 100; j++) { if (n_randint(state, 1000) == 0) fmpz_randtest_unsigned(p, state, 100000); else fmpz_randtest_unsigned(p, state, max_modulus_bits); fmpz_add_ui(p, p, 1); fmpz_mod_ctx_set_modulus(fpctx, p); fmpz_randtest_mod(a, state, p); fmpz_randtest_mod(b, state, p); fmpz_randtest(e, state, max_exp_bits); fmpz_randtest(f, state, max_exp_bits); /* check a^(e + f) = a^e * a^f */ if (!fmpz_mod_pow_fmpz(u, a, e, fpctx)) goto skip1; if (!fmpz_mod_pow_fmpz(v, a, f, fpctx)) goto skip1; fmpz_add(t, e, f); if (!fmpz_mod_pow_fmpz(w, a, t, fpctx)) goto skip1; fmpz_mod_mul(x, u, v, fpctx); if (!fmpz_equal(w, x)) { printf("FAIL\n"); flint_printf("check a^(e + f) = a^e * a^f\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } skip1: /* check a^(e + f) = a^e * a^f with aliasing */ if (!fmpz_mod_pow_fmpz(u, a, e, fpctx)) goto skip2; if (!fmpz_mod_pow_fmpz(v, a, f, fpctx)) goto skip2; fmpz_add(t, e, f); if (!fmpz_mod_pow_fmpz(a, a, t, fpctx)) goto skip2; fmpz_mod_mul(x, u, v, fpctx); if (!fmpz_equal(a, x)) { printf("FAIL\n"); flint_printf("check a^(e + f) = a^e * a^f with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } skip2: /* check 0^0 = 1 */ fmpz_zero(a); fmpz_zero(e); fmpz_mod_pow_fmpz(u, a, e, fpctx); if (!fmpz_mod_is_one(u, fpctx)) { printf("FAIL\n"); flint_printf("check 0^0 = 1\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } /* check (a*b)^e = a^e * b^e with aliasing */ fmpz_mod_mul(u, a, b, fpctx); if (!fmpz_mod_pow_fmpz(a, a, e, fpctx)) goto skip3; if (!fmpz_mod_pow_fmpz(b, b, e, fpctx)) goto skip3; if (!fmpz_mod_pow_fmpz(u, u, e, fpctx)) goto skip3; fmpz_mod_mul(a, a, b, fpctx); if (!fmpz_equal(a, u)) { printf("FAIL\n"); flint_printf("check (a*b)^e = a^e * b^e with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } skip3:; } fmpz_clear(p); fmpz_mod_ctx_clear(fpctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(u); fmpz_clear(v); fmpz_clear(w); fmpz_clear(x); fmpz_clear(e); fmpz_clear(f); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod/test/t-pow_ui.c000066400000000000000000000074111461254215100201260ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" TEST_FUNCTION_START(fmpz_mod_pow_ui, state) { flint_bitcnt_t max_modulus_bits = 200; slong i, j; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; /* p not nec. prime */ fmpz_t a, b, u, v, w, x; ulong e, f, t; fmpz_mod_ctx_t fpctx; fmpz_init_set_ui(p, 2); fmpz_mod_ctx_init(fpctx, p); fmpz_init(a); fmpz_init(b); fmpz_init(u); fmpz_init(v); fmpz_init(w); fmpz_init(x); for (j = 0; j < 100; j++) { if (n_randint(state, 1000) == 0) fmpz_randtest_unsigned(p, state, 100000); else fmpz_randtest_unsigned(p, state, max_modulus_bits); fmpz_add_ui(p, p, 1); fmpz_mod_ctx_set_modulus(fpctx, p); fmpz_randtest_mod(a, state, p); fmpz_randtest_mod(b, state, p); e = n_randlimb(state); f = n_randlimb(state); t = e + f; if (t < e || t < f) { continue; } /* check a^(e + f) = a^e * a^f */ fmpz_mod_pow_ui(u, a, e, fpctx); fmpz_mod_pow_ui(v, a, f, fpctx); fmpz_mod_pow_ui(w, a, t, fpctx); fmpz_mod_mul(x, u, v, fpctx); if (!fmpz_equal(w, x)) { printf("FAIL\n"); flint_printf("check a^(e + f) = a^e * a^f\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } /* check a^(e + f) = a^e * a^f with aliasing */ fmpz_mod_pow_ui(u, a, e, fpctx); fmpz_mod_pow_ui(v, a, f, fpctx); fmpz_mod_pow_ui(a, a, t, fpctx); fmpz_mod_mul(x, u, v, fpctx); if (!fmpz_equal(a, x)) { printf("FAIL\n"); flint_printf("check a^(e + f) = a^e * a^f with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } /* check 0^0 = 1 */ fmpz_zero(a); fmpz_mod_pow_ui(u, a, 0, fpctx); if (!fmpz_mod_is_one(u, fpctx)) { printf("FAIL\n"); flint_printf("check 0^0 = 1\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } /* check (a*b)^e = a^e * b^e with aliasing */ fmpz_mod_mul(u, a, b, fpctx); fmpz_mod_pow_ui(a, a, e, fpctx); fmpz_mod_pow_ui(b, b, e, fpctx); fmpz_mod_pow_ui(u, u, e, fpctx); fmpz_mod_mul(a, a, b, fpctx); if (!fmpz_equal(a, u)) { printf("FAIL\n"); flint_printf("check (a*b)^e = a^e * b^e with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(p); fmpz_mod_ctx_clear(fpctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(u); fmpz_clear(v); fmpz_clear(w); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat.h000066400000000000000000000243551461254215100162600ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_MAT_H #define FMPZ_MOD_MAT_H #ifdef FMPZ_MOD_MAT_INLINES_C #define FMPZ_MOD_MAT_INLINE #else #define FMPZ_MOD_MAT_INLINE static inline #endif #include "fmpz_mat.h" #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif #define FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF 10 /* Element access ********************************************************/ FMPZ_MOD_MAT_INLINE fmpz * fmpz_mod_mat_entry(const fmpz_mod_mat_t mat, slong i, slong j) { return fmpz_mat_entry(mat, i, j); } void fmpz_mod_mat_set_entry(fmpz_mod_mat_t mat, slong i, slong j, const fmpz_t val, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_get_entry(fmpz_t x, const fmpz_mod_mat_t mat, slong i, slong j, const fmpz_mod_ctx_t ctx); /* Memory management ********************************************************/ void fmpz_mod_mat_init(fmpz_mod_mat_t mat, slong rows, slong cols, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_init_set(fmpz_mod_mat_t mat, const fmpz_mod_mat_t src, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_clear(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); /* Basic manipulation ********************************************************/ FMPZ_MOD_MAT_INLINE slong fmpz_mod_mat_nrows(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_nrows(mat); } FMPZ_MOD_MAT_INLINE slong fmpz_mod_mat_ncols(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_ncols(mat); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_one(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { if (*ctx->n == WORD(1)) fmpz_mat_zero(mat); else fmpz_mat_one(mat); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_zero(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { fmpz_mat_zero(mat); } FMPZ_MOD_MAT_INLINE int fmpz_mod_mat_is_empty(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_is_empty(mat); } FMPZ_MOD_MAT_INLINE int fmpz_mod_mat_is_square(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_is_square(mat); } void fmpz_mod_mat_swap(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_swap_entrywise(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_set(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx); /* Conversions */ FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_set_nmod_mat(fmpz_mod_mat_t A, const nmod_mat_t B, const fmpz_mod_ctx_t ctx) { fmpz_mat_set_nmod_mat_unsigned(A, B); } void fmpz_mod_mat_set_fmpz_mat(fmpz_mod_mat_t A, const fmpz_mat_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_get_fmpz_mat(fmpz_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MAT_INLINE void _fmpz_mod_mat_reduce(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { fmpz_mod_mat_set_fmpz_mat(mat, mat, ctx); } /* Random matrix generation */ void fmpz_mod_mat_randtest(fmpz_mod_mat_t mat, flint_rand_t state, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_randrank(fmpz_mod_mat_t mat, flint_rand_t state, slong rank, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_randtril(fmpz_mod_mat_t mat, flint_rand_t state, int unit, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_randtriu(fmpz_mod_mat_t mat, flint_rand_t state, int unit, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_randops(fmpz_mod_mat_t mat, flint_rand_t state, slong count, const fmpz_mod_ctx_t ctx) { fmpz_mat_randops(mat, state, count); _fmpz_mod_mat_reduce(mat, ctx); } /* Windows and concatenation */ void fmpz_mod_mat_window_init(fmpz_mod_mat_t window, const fmpz_mod_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_window_clear(fmpz_mod_mat_t window, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_concat_horizontal(fmpz_mod_mat_t res, const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) { fmpz_mat_concat_horizontal(res, mat1, mat2); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_concat_vertical(fmpz_mod_mat_t res, const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) { fmpz_mat_concat_vertical(res, mat1, mat2); } /* Input/output */ #ifdef FLINT_HAVE_FILE int fmpz_mod_mat_fprint(FILE * file, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); int fmpz_mod_mat_fprint_pretty(FILE * file, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); #endif int fmpz_mod_mat_print(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_print_pretty(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); /* Comparison */ int fmpz_mod_mat_equal(const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx); int fmpz_mod_mat_is_zero(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); int fmpz_mod_mat_is_one(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); /* Transpose */ FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_transpose(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { fmpz_mat_transpose(B, A); } /* Addition and subtraction */ void fmpz_mod_mat_add(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_sub(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_neg(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx); /* Matrix-scalar arithmetic */ void fmpz_mod_mat_scalar_mul_si(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, slong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_scalar_mul_ui(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, ulong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_scalar_mul_fmpz(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, fmpz_t c, const fmpz_mod_ctx_t ctx); /* Matrix multiplication */ void fmpz_mod_mat_mul(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); void _fmpz_mod_mat_mul_classical_threaded_pool_op(fmpz_mod_mat_t D, const fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, int op, thread_pool_handle * threads, slong num_threads, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_mul_classical_threaded(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_sqr(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_submul(fmpz_mod_mat_t D, const fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_mul_fmpz_vec(fmpz * c, const fmpz_mod_mat_t A, const fmpz * b, slong blen, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mod_mat_t A, const fmpz * const * b, slong blen, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); /* Trace */ void fmpz_mod_mat_trace(fmpz_t trace, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); /* Gaussian elimination *********************************************/ void fmpz_mod_mat_det(fmpz_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); slong fmpz_mod_mat_rref(fmpz_mod_mat_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); slong fmpz_mod_mat_reduce_row(fmpz_mod_mat_t A, slong * P, slong * L, slong m, const fmpz_mod_ctx_t ctx); slong fmpz_mod_mat_lu(slong * P, fmpz_mod_mat_t A, int rank_check, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_solve_triu(fmpz_mod_mat_t X, const fmpz_mod_mat_t L, const fmpz_mod_mat_t B, int unit, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_solve_tril(fmpz_mod_mat_t X, const fmpz_mod_mat_t L, const fmpz_mod_mat_t B, int unit, const fmpz_mod_ctx_t ctx); int fmpz_mod_mat_can_solve(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); int fmpz_mod_mat_solve(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx); int fmpz_mod_mat_inv(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx); slong fmpz_mod_mat_rank(const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx); slong fmpz_mod_mat_nullspace(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx); /* Howell and strong echelon form ***********************************/ slong fmpz_mod_mat_howell_form(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_strong_echelon_form(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx); /* Transforms ****************************************************************/ void fmpz_mod_mat_similarity(fmpz_mod_mat_t A, slong r, fmpz_t d, const fmpz_mod_ctx_t ctx); /* Permutations ************************************************************/ FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_swap_rows(fmpz_mod_mat_t mat, slong * perm, slong r, slong s, const fmpz_mod_ctx_t ctx) { fmpz_mat_swap_rows(mat, perm, r, s); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_invert_rows(fmpz_mod_mat_t mat, slong * perm, const fmpz_mod_ctx_t ctx) { fmpz_mat_invert_rows(mat, perm); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_swap_cols(fmpz_mod_mat_t mat, slong * perm, slong r, slong s, const fmpz_mod_ctx_t ctx) { fmpz_mat_swap_cols(mat, perm, r, s); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_invert_cols(fmpz_mod_mat_t mat, slong * perm, const fmpz_mod_ctx_t ctx) { fmpz_mat_invert_cols(mat, perm); } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mod_mat/000077500000000000000000000000001461254215100160765ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_mat/add.c000066400000000000000000000014521461254215100167740ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_add(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { slong i; slong r = fmpz_mod_mat_nrows(A, ctx); slong c = fmpz_mod_mat_ncols(A, ctx); if (c != 0) for (i = 0; i < r; i++) _fmpz_mod_vec_add(C->rows[i], A->rows[i], B->rows[i], c, ctx); } flint-3.1.3/src/fmpz_mod_mat/can_solve.c000066400000000000000000000017401461254215100202150ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann Copyright (C) 2020 William Hart Copyright (C) 2021 Daniel Schultz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_mod_mat.h" #include "gr.h" #include "gr_mat.h" int fmpz_mod_mat_can_solve(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; int status; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); status = gr_mat_solve_field((gr_mat_struct *) X, (const gr_mat_struct *) A, (const gr_mat_struct *) B, gr_ctx); return (status == GR_SUCCESS) ? 1 : 0; } flint-3.1.3/src/fmpz_mod_mat/charpoly_berkowitz.c000066400000000000000000000026051461254215100221660ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_mat.h" void _fmpz_mod_mat_charpoly_berkowitz(fmpz* cp, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_mat_charpoly_berkowitz(cp, (const gr_mat_struct *) mat, gr_ctx)); } void fmpz_mod_mat_charpoly_berkowitz(fmpz_mod_poly_t cp, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { if (!fmpz_mod_mat_is_square(mat, ctx)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_mat_charpoly_berkowitz). Non-square matrix.\n"); } fmpz_mod_poly_fit_length(cp, fmpz_mod_mat_nrows(mat, ctx) + 1, ctx); _fmpz_mod_mat_charpoly_berkowitz(cp->coeffs, mat, ctx); _fmpz_mod_poly_set_length(cp, fmpz_mod_mat_nrows(mat, ctx) + 1); _fmpz_mod_poly_normalise(cp); } flint-3.1.3/src/fmpz_mod_mat/clear.c000066400000000000000000000010111461254215100173210ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_clear(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { fmpz_mat_clear(mat); } flint-3.1.3/src/fmpz_mod_mat/comparison.c000066400000000000000000000014701461254215100204160ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" int fmpz_mod_mat_equal(const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) { return fmpz_mat_equal(mat1, mat2); } int fmpz_mod_mat_is_zero(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_is_zero(mat); } int fmpz_mod_mat_is_one(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_is_one(ctx->n) || fmpz_mat_is_one(mat); } flint-3.1.3/src/fmpz_mod_mat/det.c000066400000000000000000000024571461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "gr.h" #include "gr_mat.h" void fmpz_mod_mat_det(fmpz_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; slong n = mat->r; if (!fmpz_mod_mat_is_square(mat, ctx)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_mat_charpoly_berkowitz). Non-square matrix.\n"); } _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); if (n <= 4) { GR_MUST_SUCCEED(gr_mat_det_cofactor(res, (const gr_mat_struct *) mat, gr_ctx)); } else { if (gr_mat_det_lu(res, (const gr_mat_struct *) mat, gr_ctx) != GR_SUCCESS) { /* Fall back on division-free algorithm if we encountered an impossible inverse */ /* Could try something else here: faddeev_bsgs (O(n^3.5)) or Howell form. */ GR_MUST_SUCCEED(gr_mat_det_berkowitz(res, (const gr_mat_struct *) mat, gr_ctx)); } } }flint-3.1.3/src/fmpz_mod_mat/fmpz_vec_mul.c000066400000000000000000000013471461254215100207350ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { fmpz_mat_fmpz_vec_mul(c, a, alen, B); _fmpz_mod_vec_set_fmpz_vec(c, c, fmpz_mod_mat_ncols(B, ctx), ctx); } flint-3.1.3/src/fmpz_mod_mat/fmpz_vec_mul_ptr.c000066400000000000000000000013751461254215100216230ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mat_fmpz_vec_mul_ptr(c, a, alen, B); for (i = 0; i < fmpz_mod_mat_ncols(B, ctx); i++) fmpz_mod_set_fmpz(c[i], c[i], ctx); } flint-3.1.3/src/fmpz_mod_mat/howell_form.c000066400000000000000000000010311461254215100205520ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" slong fmpz_mod_mat_howell_form(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_howell_form_mod(mat, ctx->n); } flint-3.1.3/src/fmpz_mod_mat/init.c000066400000000000000000000010531461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_init(fmpz_mod_mat_t mat, slong rows, slong cols, const fmpz_mod_ctx_t ctx) { fmpz_mat_init(mat, rows, cols); } flint-3.1.3/src/fmpz_mod_mat/init_set.c000066400000000000000000000010561461254215100200620ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_init_set(fmpz_mod_mat_t mat, const fmpz_mod_mat_t src, const fmpz_mod_ctx_t ctx) { fmpz_mat_init_set(mat, src); } flint-3.1.3/src/fmpz_mod_mat/inlines.c000066400000000000000000000007311461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_MAT_INLINES_C #include "fmpz_mod_mat.h" flint-3.1.3/src/fmpz_mod_mat/inv.c000066400000000000000000000024261461254215100170420ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" int fmpz_mod_mat_inv(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { fmpz_mod_mat_t I; slong dim; int result; dim = A->r; switch (dim) { case 0: result = 1; break; case 1: if (fmpz_is_zero(fmpz_mod_mat_entry(A, 0, 0))) { result = 0; } else { fmpz_mod_inv(fmpz_mod_mat_entry(B, 0, 0), fmpz_mod_mat_entry(A, 0, 0), ctx); result = 1; } break; default: fmpz_mod_mat_init(I, dim, dim, ctx); fmpz_mod_mat_one(I, ctx); result = fmpz_mod_mat_solve(B, A, I, ctx); fmpz_mod_mat_clear(I, ctx); } return result; } flint-3.1.3/src/fmpz_mod_mat/io.c000066400000000000000000000016261461254215100166560ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_mat.h" int fmpz_mod_mat_fprint(FILE * file, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_fprint(file, mat); } int fmpz_mod_mat_fprint_pretty(FILE * file, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_fprint_pretty(file, mat); } int fmpz_mod_mat_print(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { return fmpz_mat_print(mat); } void fmpz_mod_mat_print_pretty(const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { fmpz_mat_print_pretty(mat); } flint-3.1.3/src/fmpz_mod_mat/lu.c000066400000000000000000000015031461254215100166610ustar00rootroot00000000000000/* Copyright (C) 2011, 2024 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr.h" #include "gr_mat.h" #include "fmpz_mod_mat.h" slong fmpz_mod_mat_lu(slong * P, fmpz_mod_mat_t A, int rank_check, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; slong rank; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(gr_mat_lu(&rank, P, (gr_mat_struct *) A, (const gr_mat_struct *) A, rank_check, gr_ctx)); return rank; } flint-3.1.3/src/fmpz_mod_mat/minpoly.c000066400000000000000000000020771461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2021 Daniel Schultz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_mat.h" void fmpz_mod_mat_minpoly(fmpz_mod_poly_t p, const fmpz_mod_mat_t X, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; slong n = fmpz_mod_mat_nrows(X, ctx); if (n != fmpz_mod_mat_ncols(X, ctx)) flint_throw(FLINT_ERROR, "Exception (fmpz_mod_mat_minpoly). Non-square matrix.\n"); _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(gr_mat_minpoly_field((gr_poly_struct *) p, (const gr_mat_struct *) X, gr_ctx)); } flint-3.1.3/src/fmpz_mod_mat/mul.c000066400000000000000000000012221461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_mul(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { /* N.B. don't call classical_threaded, instead, thread fmpz_mat_mul */ fmpz_mat_mul(C, A, B); _fmpz_mod_mat_reduce(C, ctx); } flint-3.1.3/src/fmpz_mod_mat/mul_classical_threaded.c000066400000000000000000000162111461254215100227160ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #define FLINT_FMPZ_MUL_CLASSICAL_CACHE_SIZE 32768 /* size of L1 cache in words */ /* with op = 0, computes D = A*B with op = 1, computes D = C + A*B with op = -1, computes D = C - A*B */ static inline void _fmpz_vec_dot_ptr(fmpz_t c, const fmpz * vec1, fmpz ** const vec2, slong offset, slong len) { slong i; fmpz_zero(c); for (i = 0; i < len; i++) fmpz_addmul(c, vec1 + i, vec2[i] + offset); } static inline void _fmpz_mod_mat_addmul_basic_op(fmpz ** D, fmpz ** const C, fmpz ** const A, fmpz ** const B, slong m, slong k, slong n, int op, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_t c; fmpz_init(c); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { _fmpz_vec_dot_ptr(c, A[i], B, j, k); if (op == 1) fmpz_add(c, C[i] + j, c); else if (op == -1) fmpz_sub(c, C[i] + j, c); fmpz_mod_set_fmpz(D[i] + j, c, ctx); } } fmpz_clear(c); } typedef struct { slong block; volatile slong * i; volatile slong * j; slong k; slong m; slong n; fmpz ** A; fmpz ** C; fmpz ** D; fmpz * tmp; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif int op; const fmpz_mod_ctx_struct * ctx; } fmpz_mod_mat_transpose_arg_t; void _fmpz_mod_mat_addmul_transpose_worker(void * arg_ptr) { fmpz_mod_mat_transpose_arg_t arg = *((fmpz_mod_mat_transpose_arg_t *) arg_ptr); slong i, j, iend, jend, jstart; slong block = arg.block; slong k = arg.k; slong m = arg.m; slong n = arg.n; fmpz ** const A = arg.A; fmpz ** const C = arg.C; fmpz ** D = arg.D; fmpz * tmp = arg.tmp; int op = arg.op; const fmpz_mod_ctx_struct * ctx = arg.ctx; fmpz_t c; fmpz_init(c); while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; j = *arg.j; if (j >= n) { i += block; *arg.i = i; j = 0; } *arg.j = j + block; #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= m) { fmpz_clear(c); return; } iend = FLINT_MIN(i + block, m); jend = FLINT_MIN(j + block, n); jstart = j; for ( ; i < iend; i++) { for (j = jstart ; j < jend; j++) { _fmpz_vec_dot(c, A[i], tmp + j*k, k); /* todo: use dot_general */ if (op == 1) fmpz_add(c, C[i] + j, c); else if (op == -1) fmpz_sub(c, C[i] + j, c); fmpz_mod_set_fmpz(D[i] + j, c, ctx); } } } } static inline void _fmpz_mod_mat_addmul_transpose_threaded_pool_op(fmpz ** D, fmpz ** const C, fmpz ** const A, fmpz ** const B, slong m, slong k, slong n, int op, thread_pool_handle * threads, slong num_threads, const fmpz_mod_ctx_t ctx) { fmpz * tmp; slong i, j, block, nlimbs; slong shared_i = 0, shared_j = 0; fmpz_mod_mat_transpose_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif tmp = _fmpz_vec_init(k*n); /* transpose B */ for (i = 0; i < k; i++) for (j = 0; j < n; j++) fmpz_set(tmp + j*k + i, B[i] + j); nlimbs = fmpz_size(ctx->n); /* compute optimal block width */ block = FLINT_MAX(FLINT_MIN(m/(num_threads + 1), n/(num_threads + 1)), 1); while (2*block*k*nlimbs > FLINT_FMPZ_MUL_CLASSICAL_CACHE_SIZE && block > 1) block >>= 1; args = flint_malloc(sizeof(fmpz_mod_mat_transpose_arg_t) * (num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].block = block; args[i].i = &shared_i; args[i].j = &shared_j; args[i].k = k; args[i].m = m; args[i].n = n; args[i].A = A; args[i].C = C; args[i].D = D; args[i].tmp = tmp; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif args[i].op = op; args[i].ctx = ctx; } #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif for (i = 0; i < num_threads; i++) { thread_pool_wake(global_thread_pool, threads[i], 0, _fmpz_mod_mat_addmul_transpose_worker, &args[i]); } _fmpz_mod_mat_addmul_transpose_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) { thread_pool_wait(global_thread_pool, threads[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif flint_free(args); _fmpz_vec_clear(tmp, k*n); } void _fmpz_mod_mat_mul_classical_threaded_pool_op(fmpz_mod_mat_t D, const fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, int op, thread_pool_handle * threads, slong num_threads, const fmpz_mod_ctx_t ctx) { slong m, k, n; m = A->r; k = A->c; n = B->c; _fmpz_mod_mat_addmul_transpose_threaded_pool_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, m, k, n, op, threads, num_threads, ctx); } void fmpz_mod_mat_mul_classical_threaded_op(fmpz_mod_mat_t D, const fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, int op, const fmpz_mod_ctx_t ctx) { thread_pool_handle * threads; slong num_threads; if (A->c == 0) { if (op == 0) fmpz_mod_mat_zero(D, ctx); else fmpz_mod_mat_set(D, C, ctx); return; } if (A->r < FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF || A->c < FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF || B->c < FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF) { _fmpz_mod_mat_addmul_basic_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, A->r, A->c, B->c, op, ctx); return; } num_threads = flint_request_threads(&threads, flint_get_num_threads()); _fmpz_mod_mat_mul_classical_threaded_pool_op(D, C, A, B, op, threads, num_threads, ctx); flint_give_back_threads(threads, num_threads); } void fmpz_mod_mat_mul_classical_threaded(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_mat_mul_classical_threaded_op(C, NULL, A, B, 0, ctx); } flint-3.1.3/src/fmpz_mod_mat/mul_fmpz_vec.c000066400000000000000000000013421461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_mul_fmpz_vec(fmpz* c, const fmpz_mod_mat_t A, const fmpz * b, slong blen, const fmpz_mod_ctx_t ctx) { fmpz_mat_mul_fmpz_vec(c, A, b, blen); _fmpz_mod_vec_set_fmpz_vec(c, c, fmpz_mod_mat_nrows(A, ctx), ctx); } flint-3.1.3/src/fmpz_mod_mat/mul_fmpz_vec_ptr.c000066400000000000000000000013751461254215100216230ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mod_mat_t A, const fmpz * const * b, slong blen, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mat_mul_fmpz_vec_ptr(c, A, b, blen); for (i = 0; i < fmpz_mod_mat_nrows(A, ctx); i++) fmpz_mod_set_fmpz(c[i], c[i], ctx); } flint-3.1.3/src/fmpz_mod_mat/neg.c000066400000000000000000000013351461254215100170150ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_neg(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { slong i; slong r = fmpz_mod_mat_nrows(A, ctx); slong c = fmpz_mod_mat_ncols(A, ctx); if (c != 0) for (i = 0; i < r; i++) _fmpz_mod_vec_neg(B->rows[i], A->rows[i], c, ctx); } flint-3.1.3/src/fmpz_mod_mat/nullspace.c000066400000000000000000000037531461254215100202400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" slong fmpz_mod_mat_nullspace(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { slong i, j, k, m, n, rank, nullity; slong *p; slong *pivots; slong *nonpivots; fmpz_mod_mat_t tmp; m = A->r; n = A->c; p = flint_malloc(sizeof(slong) * FLINT_MAX(m, n)); fmpz_mod_mat_init_set(tmp, A, ctx); rank = fmpz_mod_mat_rref(tmp, tmp, ctx); nullity = n - rank; fmpz_mod_mat_zero(X, ctx); if (rank == 0) { for (i = 0; i < nullity; i++) fmpz_one(fmpz_mod_mat_entry(X, i, i)); } else if (nullity) { pivots = p; /* length = rank */ nonpivots = p + rank; /* length = nullity */ for (i = j = k = 0; i < rank; i++) { while (fmpz_is_zero(fmpz_mod_mat_entry(tmp, i, j))) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) { fmpz_mod_neg(fmpz_mod_mat_entry(X, pivots[j], i), fmpz_mod_mat_entry(tmp, j, nonpivots[i]), ctx); } fmpz_one(fmpz_mod_mat_entry(X, nonpivots[i], i)); } } flint_free(p); fmpz_mod_mat_clear(tmp, ctx); return nullity; } flint-3.1.3/src/fmpz_mod_mat/randrank.c000066400000000000000000000021231461254215100200400ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_randrank(fmpz_mod_mat_t mat, flint_rand_t state, slong rank, const fmpz_mod_ctx_t ctx) { slong i; fmpz * diag; if (rank < 0 || rank > fmpz_mod_mat_nrows(mat, ctx) || rank > fmpz_mod_mat_ncols(mat, ctx)) flint_throw(FLINT_ERROR, "Impossible rank in %s\n", __func__); diag = _fmpz_vec_init(rank); for (i = 0; i < rank; i++) { fmpz_randm(diag + i, state, ctx->n); if (fmpz_is_zero(diag + i)) fmpz_one(diag + i); } fmpz_mat_randpermdiag(mat, state, diag, rank); _fmpz_vec_clear(diag, rank); } flint-3.1.3/src/fmpz_mod_mat/randtest.c000066400000000000000000000011411461254215100200630ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_randtest(fmpz_mod_mat_t mat, flint_rand_t state, const fmpz_mod_ctx_t ctx) { fmpz_mat_randtest(mat, state, fmpz_bits(ctx->n)); _fmpz_mod_mat_reduce(mat, ctx); } flint-3.1.3/src/fmpz_mod_mat/randtril.c000066400000000000000000000022401461254215100200570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_randtril(fmpz_mod_mat_t mat, flint_rand_t state, int unit, const fmpz_mod_ctx_t ctx) { fmpz* e; slong i, j; for (i = 0; i < fmpz_mod_mat_nrows(mat, ctx); i++) { for (j = 0; j < fmpz_mod_mat_ncols(mat, ctx); j++) { e = fmpz_mod_mat_entry(mat, i, j); if (j < i) { fmpz_randm(e, state, ctx->n); } else if (i == j) { fmpz_randm(e, state, ctx->n); if (unit || fmpz_is_zero(e)) fmpz_one(e); } else { fmpz_zero(e); } } } } flint-3.1.3/src/fmpz_mod_mat/randtriu.c000066400000000000000000000022401461254215100200700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_randtriu(fmpz_mod_mat_t mat, flint_rand_t state, int unit, const fmpz_mod_ctx_t ctx) { fmpz* e; slong i, j; for (i = 0; i < fmpz_mod_mat_nrows(mat, ctx); i++) { for (j = 0; j < fmpz_mod_mat_ncols(mat, ctx); j++) { e = fmpz_mod_mat_entry(mat, i, j); if (j > i) { fmpz_randm(e, state, ctx->n); } else if (i == j) { fmpz_randm(e, state, ctx->n); if (unit || fmpz_is_zero(e)) fmpz_one(e); } else { fmpz_zero(e); } } } } flint-3.1.3/src/fmpz_mod_mat/rank.c000066400000000000000000000016111461254215100171740ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" slong fmpz_mod_mat_rank(const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { slong m, n, rank; slong *perm; fmpz_mod_mat_t tmp; m = A->r; n = A->c; if (m == 0 || n == 0) return 0; fmpz_mod_mat_init_set(tmp, A, ctx); perm = flint_malloc(sizeof(slong) * m); rank = fmpz_mod_mat_lu(perm, tmp, 0, ctx); flint_free(perm); fmpz_mod_mat_clear(tmp, ctx); return rank; } flint-3.1.3/src/fmpz_mod_mat/reduce_row.c000066400000000000000000000034121461254215100204000ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" slong fmpz_mod_mat_reduce_row(fmpz_mod_mat_t A, slong * P, slong * L, slong m, const fmpz_mod_ctx_t ctx) { slong n = fmpz_mod_mat_ncols(A, ctx), i, j, r; fmpz_t h; fmpz_init(h); for (i = 0; i < n; i++) { if (!fmpz_is_zero(fmpz_mod_mat_entry(A, m, i))) { r = P[i]; if (r != -WORD(1)) { for (j = i + 1; j < L[r]; j++) { fmpz_mod_mul(h, fmpz_mod_mat_entry(A, r, j), fmpz_mod_mat_entry(A, m, i), ctx); fmpz_mod_sub(fmpz_mod_mat_entry(A, m, j), fmpz_mod_mat_entry(A, m, j), h, ctx); } fmpz_zero(fmpz_mod_mat_entry(A, m, i)); } else { fmpz_mod_inv(h, fmpz_mod_mat_entry(A, m, i), ctx); fmpz_one(fmpz_mod_mat_entry(A, m, i)); for (j = i + 1; j < L[m]; j++) fmpz_mod_mul(fmpz_mod_mat_entry(A, m, j), fmpz_mod_mat_entry(A, m, j), h, ctx); P[i] = m; fmpz_clear(h); return i; } } } fmpz_clear(h); return -WORD(1); } flint-3.1.3/src/fmpz_mod_mat/rref.c000066400000000000000000000014161461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" #include "gr.h" #include "gr_mat.h" slong fmpz_mod_mat_rref(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; slong rank; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(gr_mat_rref_lu(&rank, (gr_mat_struct *) B, (const gr_mat_struct *) A, gr_ctx)); return rank; } flint-3.1.3/src/fmpz_mod_mat/scalar_mul_fmpz.c000066400000000000000000000013161461254215100214210ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_scalar_mul_fmpz(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, fmpz_t c, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); fmpz_mod_set_fmpz(d, c, ctx); fmpz_mat_scalar_mul_fmpz(B, A, d); _fmpz_mod_mat_reduce(B, ctx); fmpz_clear(d); } flint-3.1.3/src/fmpz_mod_mat/scalar_mul_si.c000066400000000000000000000011141461254215100210540ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_scalar_mul_si(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, slong c, const fmpz_mod_ctx_t ctx) { fmpz_mat_scalar_mul_si(B, A, c); _fmpz_mod_mat_reduce(B, ctx); } flint-3.1.3/src/fmpz_mod_mat/scalar_mul_ui.c000066400000000000000000000011141461254215100210560ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_scalar_mul_ui(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, ulong c, const fmpz_mod_ctx_t ctx) { fmpz_mat_scalar_mul_ui(B, A, c); _fmpz_mod_mat_reduce(B, ctx); } flint-3.1.3/src/fmpz_mod_mat/set_fmpz_mat.c000066400000000000000000000034431461254215100207360ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" typedef struct { fmpz ** Mrows; fmpz * const * Arows; slong c; const fmpz_mod_ctx_struct * ctx; } _worker_arg; static void _red_worker(slong i, void * varg) { _worker_arg * arg = (_worker_arg *) varg; _fmpz_mod_vec_set_fmpz_vec(arg->Mrows[i], arg->Arows[i], arg->c, arg->ctx); } static void _fmpz_mod_mat_set_fmpz_mat(fmpz_mod_mat_t M, const fmpz_mat_t A, const fmpz_mod_ctx_t ctx) { slong i, r, c; r = fmpz_mod_mat_nrows(M, ctx); c = fmpz_mod_mat_ncols(M, ctx); for (i = 0; i < r; i++) _fmpz_mod_vec_set_fmpz_vec(M->rows[i], A->rows[i], c, ctx); } void fmpz_mod_mat_set_fmpz_mat(fmpz_mod_mat_t M, const fmpz_mat_t A, const fmpz_mod_ctx_t ctx) { slong r, c; slong limit; r = fmpz_mod_mat_nrows(M, ctx); c = fmpz_mod_mat_ncols(M, ctx); /* limit on threads */ limit = fmpz_size(ctx->n) + r + c; limit = limit < 64 ? 0 : (limit - 64)/64; limit = FLINT_MIN(limit, r); if (limit < 2) { _fmpz_mod_mat_set_fmpz_mat(M, A, ctx); } else { _worker_arg arg; arg.Mrows = M->rows; arg.Arows = A->rows; arg.c = c; arg.ctx = ctx; flint_parallel_do(_red_worker, &arg, r, limit, FLINT_PARALLEL_UNIFORM); } } flint-3.1.3/src/fmpz_mod_mat/set_get.c000066400000000000000000000021771461254215100177030ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" /* Setters ********************************************************************/ void fmpz_mod_mat_set_entry(fmpz_mod_mat_t mat, slong i, slong j, const fmpz_t val, const fmpz_mod_ctx_t ctx) { fmpz_set(fmpz_mat_entry(mat, i, j), val); } void fmpz_mod_mat_set(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { fmpz_mat_set(B, A); } /* Getters ********************************************************************/ void fmpz_mod_mat_get_entry(fmpz_t x, const fmpz_mod_mat_t mat, slong i, slong j, const fmpz_mod_ctx_t ctx) { fmpz_set(x, fmpz_mod_mat_entry(mat, i, j)); } void fmpz_mod_mat_get_fmpz_mat(fmpz_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { fmpz_mat_set(A, B); } flint-3.1.3/src/fmpz_mod_mat/similarity.c000066400000000000000000000030761461254215100204360ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_similarity(fmpz_mod_mat_t A, slong r, fmpz_t d, const fmpz_mod_ctx_t ctx) { slong n = A->r, i, j; fmpz_t t; fmpz_init(t); for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) { fmpz_mod_mul(t, fmpz_mod_mat_entry(A, i, r), d, ctx); fmpz_mod_add(fmpz_mod_mat_entry(A, i, j), fmpz_mod_mat_entry(A, i, j), t, ctx); } for (j = r + 1; j < n; j++) { fmpz_mod_mul(t, fmpz_mod_mat_entry(A, i, r), d, ctx); fmpz_mod_add(fmpz_mod_mat_entry(A, i, j), fmpz_mod_mat_entry(A, i, j), t, ctx); } } for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) { fmpz_mod_mul(t, fmpz_mod_mat_entry(A, j, i), d, ctx); fmpz_mod_sub(fmpz_mod_mat_entry(A, r, i), fmpz_mod_mat_entry(A, r, i), t, ctx); } for (j = r + 1; j < n; j++) { fmpz_mod_mul(t, fmpz_mod_mat_entry(A, j, i), d, ctx); fmpz_mod_sub(fmpz_mod_mat_entry(A, r, i), fmpz_mod_mat_entry(A, r, i), t, ctx); } } fmpz_clear(t); } flint-3.1.3/src/fmpz_mod_mat/solve.c000066400000000000000000000016661461254215100174030ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann Copyright (C) 2021 Daniel Schultz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" #include "gr.h" #include "gr_mat.h" int fmpz_mod_mat_solve(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; int status; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); status = gr_mat_nonsingular_solve_lu((gr_mat_struct *) X, (const gr_mat_struct *) A, (const gr_mat_struct *) B, gr_ctx); return (status == GR_SUCCESS) ? 1 : 0; } flint-3.1.3/src/fmpz_mod_mat/solve_tril.c000066400000000000000000000016111461254215100204230ustar00rootroot00000000000000/* Copyright (C) 2010, 2011, 2024 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" #include "gr.h" #include "gr_mat.h" void fmpz_mod_mat_solve_tril(fmpz_mod_mat_t X, const fmpz_mod_mat_t L, const fmpz_mod_mat_t B, int unit, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(gr_mat_nonsingular_solve_tril((gr_mat_struct *)X, (const gr_mat_struct *) L, (const gr_mat_struct *) B, unit, gr_ctx)); } flint-3.1.3/src/fmpz_mod_mat/solve_triu.c000066400000000000000000000016111461254215100204340ustar00rootroot00000000000000/* Copyright (C) 2010, 2011, 2024 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" #include "gr.h" #include "gr_mat.h" void fmpz_mod_mat_solve_triu(fmpz_mod_mat_t X, const fmpz_mod_mat_t U, const fmpz_mod_mat_t B, int unit, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(gr_mat_nonsingular_solve_triu((gr_mat_struct *)X, (const gr_mat_struct *) U, (const gr_mat_struct *) B, unit, gr_ctx)); } flint-3.1.3/src/fmpz_mod_mat/sqr.c000066400000000000000000000010541461254215100170470ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_sqr(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { fmpz_mat_sqr(B, A); _fmpz_mod_mat_reduce(B, ctx); } flint-3.1.3/src/fmpz_mod_mat/strong_echelon_form.c000066400000000000000000000010411461254215100222720ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_strong_echelon_form(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { fmpz_mat_strong_echelon_form_mod(mat, ctx->n); } flint-3.1.3/src/fmpz_mod_mat/sub.c000066400000000000000000000014521461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_sub(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { slong i; slong r = fmpz_mod_mat_nrows(A, ctx); slong c = fmpz_mod_mat_ncols(A, ctx); if (c != 0) for (i = 0; i < r; i++) _fmpz_mod_vec_sub(C->rows[i], A->rows[i], B->rows[i], c, ctx); } flint-3.1.3/src/fmpz_mod_mat/submul.c000066400000000000000000000015621461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_submul(fmpz_mod_mat_t D, const fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_mat_t tmp; fmpz_mod_mat_init(tmp, A->r, B->c, ctx); fmpz_mod_mat_mul(tmp, A, B, ctx); fmpz_mod_mat_sub(D, C, tmp, ctx); fmpz_mod_mat_clear(tmp, ctx); } flint-3.1.3/src/fmpz_mod_mat/swap.c000066400000000000000000000016011461254215100172120ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_swap(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) { FLINT_SWAP(fmpz_mod_mat_struct, *mat1, *mat2); } void fmpz_mod_mat_swap_entrywise(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx) { slong i, j; for (i = 0; i < fmpz_mod_mat_nrows(mat1, ctx); i++) for (j = 0; j < fmpz_mod_mat_ncols(mat1, ctx); j++) fmpz_swap(fmpz_mod_mat_entry(mat2, i, j), fmpz_mod_mat_entry(mat1, i, j)); } flint-3.1.3/src/fmpz_mod_mat/test/000077500000000000000000000000001461254215100170555ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_mat/test/main.c000066400000000000000000000046631461254215100201560ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub_neg.c" #include "t-can_solve.c" #include "t-charpoly.c" #include "t-det.c" #include "t-fmpz_vec_mul.c" #include "t-get_set_fmpz_mat.c" #include "t-howell_form.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-lu.c" #include "t-minpoly.c" #include "t-mul.c" #include "t-mul_classical_threaded.c" #include "t-mul_fmpz_vec.c" #include "t-nullspace.c" #include "t-rank.c" #include "t-rref.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_si.c" #include "t-scalar_mul_ui.c" #include "t-solve.c" #include "t-solve_tril.c" #include "t-solve_triu.c" #include "t-sqr.c" #include "t-trace.c" #include "t-window_init_clear.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mod_mat_add_sub_neg), TEST_FUNCTION(fmpz_mod_mat_can_solve), TEST_FUNCTION(fmpz_mod_mat_charpoly), TEST_FUNCTION(fmpz_mod_mat_det), TEST_FUNCTION(fmpz_mod_mat_fmpz_vec_mul), TEST_FUNCTION(fmpz_mod_mat_get_set_fmpz_mat), TEST_FUNCTION(fmpz_mod_mat_howell_form), TEST_FUNCTION(fmpz_mod_mat_init_clear), TEST_FUNCTION(fmpz_mod_mat_inv), TEST_FUNCTION(fmpz_mod_mat_lu), TEST_FUNCTION(fmpz_mod_mat_minpoly), TEST_FUNCTION(fmpz_mod_mat_mul), TEST_FUNCTION(fmpz_mod_mat_mul_classical_threaded), TEST_FUNCTION(fmpz_mod_mat_mul_fmpz_vec), TEST_FUNCTION(fmpz_mod_mat_nullspace), TEST_FUNCTION(fmpz_mod_mat_rank), TEST_FUNCTION(fmpz_mod_mat_rref), TEST_FUNCTION(fmpz_mod_mat_scalar_mul_fmpz), TEST_FUNCTION(fmpz_mod_mat_scalar_mul_si), TEST_FUNCTION(fmpz_mod_mat_scalar_mul_ui), TEST_FUNCTION(fmpz_mod_mat_solve), TEST_FUNCTION(fmpz_mod_mat_solve_tril), TEST_FUNCTION(fmpz_mod_mat_solve_triu), TEST_FUNCTION(fmpz_mod_mat_sqr), TEST_FUNCTION(fmpz_mod_mat_trace), TEST_FUNCTION(fmpz_mod_mat_window_init_clear) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mod_mat/test/t-add_sub_neg.c000066400000000000000000000027561461254215100217260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_add_sub_neg, state) { slong m, n, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A, B, C; fmpz_mod_ctx_t ctx; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(C, m, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_neg(C, A, ctx); fmpz_mod_mat_add(A, A, B, ctx); fmpz_mod_mat_sub(A, A, B, ctx); fmpz_mod_mat_neg(A, A, ctx); if (!fmpz_mod_mat_equal(A, C, ctx)) { flint_printf("FAIL: matrices not equal!\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-can_solve.c000066400000000000000000000054451461254215100214430ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann Copyright (C) 2020 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_can_solve, state) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, X, X2, B, AX; slong i, k, m, n; int solved; /* test random systems */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); m = n_randint(state, 50); n = n_randint(state, 50); k = n_randint(state, 50); fmpz_mod_mat_init(A, m, k, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(X, k, n, ctx); fmpz_mod_mat_init(AX, m, n, ctx); fmpz_mod_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), ctx); fmpz_mod_mat_randtest(B, state, ctx); /* Dense */ if (n_randint(state, 2)) fmpz_mod_mat_randops(A, state, 1+n_randint(state, 1+m*m), ctx); solved = fmpz_mod_mat_can_solve(X, A, B, ctx); fmpz_mod_mat_mul(AX, A, X, ctx); FLINT_TEST(!solved || fmpz_mod_mat_equal(AX, B, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(X, ctx); fmpz_mod_mat_clear(AX, ctx); fmpz_mod_ctx_clear(ctx); } /* test random solvable systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); fmpz_mod_mat_init(A, m, k, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(X, k, n, ctx); fmpz_mod_mat_init(X2, k, n, ctx); fmpz_mod_mat_init(AX, m, n, ctx); fmpz_mod_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), ctx); fmpz_mod_mat_randtest(X2, state, ctx); fmpz_mod_mat_mul(B, A, X2, ctx); solved = fmpz_mod_mat_can_solve(X, A, B, ctx); fmpz_mod_mat_mul(AX, A, X, ctx); FLINT_TEST(solved && fmpz_mod_mat_equal(AX, B, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(X, ctx); fmpz_mod_mat_clear(X2, ctx); fmpz_mod_mat_clear(AX, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-charpoly.c000066400000000000000000000033351461254215100213070ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2015 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_mat_charpoly, state) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, B, C; fmpz_mod_poly_t p1, p2; slong i, n; /* charpoly(AB) == charpoly(BA) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { n = n_randint(state, 10); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_poly_init(p1, ctx); fmpz_mod_poly_init(p2, ctx); fmpz_mod_mat_init(A, n, n, ctx); fmpz_mod_mat_init(B, n, n, ctx); fmpz_mod_mat_init(C, n, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_mul(C, A, B, ctx); fmpz_mod_mat_charpoly(p1, C, ctx); fmpz_mod_mat_mul(C, B, A, ctx); fmpz_mod_mat_charpoly(p2, C, ctx); FLINT_TEST(fmpz_mod_poly_degree(p1, ctx) == n); FLINT_TEST(fmpz_mod_poly_equal(p1, p2, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_poly_clear(p1, ctx); fmpz_mod_poly_clear(p2, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-det.c000066400000000000000000000025321461254215100202400ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" #include "fmpz_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_det, state) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A; fmpz_mat_t B; fmpz_t d1, d2; slong i, n; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { n = n_randint(state, 7); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_init(d1); fmpz_init(d2); fmpz_mod_mat_init(A, n, n, ctx); fmpz_mat_init(B, n, n); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_get_fmpz_mat(B, A, ctx); fmpz_mod_mat_det(d1, A, ctx); fmpz_mat_det(d2, B); fmpz_mod_set_fmpz(d2, d2, ctx); FLINT_TEST(fmpz_equal(d1, d2)); fmpz_mod_mat_clear(A, ctx); fmpz_mat_clear(B); fmpz_clear(d1); fmpz_clear(d2); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-fmpz_vec_mul.c000066400000000000000000000054711461254215100221570ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_fmpz_vec_mul, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, C; fmpz * a, * c; fmpz ** aa, ** cc; slong j, m, n, alen; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits(ctx, state, 200); m = n_randint(state, 50); n = n_randint(state, 50); alen = n_randint(state, 50); fmpz_mod_mat_init(C, 1, n, ctx); fmpz_mod_mat_init(A, 1, m, ctx); fmpz_mod_mat_init(B, m, n, ctx); c = _fmpz_vec_init(n); a = _fmpz_vec_init(alen); fmpz_mod_mat_randtest(B, state, ctx); _fmpz_vec_randtest(c, state, n, n_randint(state, 200) + 1); _fmpz_vec_randtest(a, state, alen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(n, fmpz*); for (j = 0; j < n; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(cc[j], c + j); } aa = FLINT_ARRAY_ALLOC(alen, fmpz*); for (j = 0; j < alen; j++) { aa[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(aa[j], a + j); } fmpz_mod_mat_fmpz_vec_mul(c, a, alen, B, ctx); fmpz_mod_mat_fmpz_vec_mul_ptr(cc, (const fmpz * const *)aa, alen, B, ctx); /* supposed to match mul of the chopped or zero-extended a */ for (j = 0; j < m && j < alen; j++) fmpz_mod(fmpz_mod_mat_entry(A, 0, j), a + j, ctx->n); fmpz_mod_mat_mul(C, A, B, ctx); for (j = 0; j < n; j++) { if (!fmpz_equal(fmpz_mod_mat_entry(C, 0, j), c + j) || !fmpz_equal(fmpz_mod_mat_entry(C, 0, j), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); _fmpz_vec_clear(c, n); _fmpz_vec_clear(a, alen); fmpz_mod_ctx_clear(ctx); for (j = 0; j < n; j++) { fmpz_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < alen; j++) { fmpz_clear(aa[j]); flint_free(aa[j]); } flint_free(aa); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-get_set_fmpz_mat.c000066400000000000000000000027011461254215100230110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_get_set_fmpz_mat, state) { slong m, n, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A; fmpz_mod_mat_t B; fmpz_mod_ctx_t ctx; fmpz_mat_t C; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mat_init(C, m, n); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_get_fmpz_mat(C, A, ctx); fmpz_mod_mat_set_fmpz_mat(B, C, ctx); if (!fmpz_mod_mat_equal(A, B, ctx)) { flint_printf("FAIL: matrices not equal!\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(C); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-howell_form.c000066400000000000000000000162021461254215100220000ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_vec.h" #include "fmpz_mod_mat.h" int fmpz_mod_mat_is_in_howell_form(const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) { slong *pivots; slong i, j, r; int numberpivots = 0; int prevrowzero = 0; fmpz * extra_row; fmpz_t g; if (fmpz_mod_mat_is_empty(A, ctx)) return 1; pivots = flint_malloc(A->r * sizeof(slong)); if (!fmpz_mat_is_zero_row(A, 0)) { for (j = 0; j < A->c; j++) { if (!fmpz_is_zero(fmpz_mod_mat_entry(A, 0, j))) { if (!fmpz_divisible(ctx->n, fmpz_mod_mat_entry(A, 0, j))) { flint_free(pivots); return 0; } pivots[numberpivots] = j; numberpivots++; break; } } } else { prevrowzero = 1; } for (i = 1; i < A->r; i++) { if (!fmpz_mat_is_zero_row(A, i)) { if (prevrowzero) { flint_free(pivots); return 0; } for (j = 0; j < A->c; j++) { if (!fmpz_is_zero(fmpz_mod_mat_entry(A, i, j))) { if (j <= pivots[numberpivots - 1]) { flint_free(pivots); return 0; } if (!fmpz_divisible(ctx->n, fmpz_mod_mat_entry(A, i, j))) { flint_free(pivots); return 0; } pivots[numberpivots] = j; numberpivots++; j = A->c; } } } else { prevrowzero = 1; } } for (i = 1; i < numberpivots; i++) { for (j = 0; j < i; j++) { if (fmpz_cmp(fmpz_mod_mat_entry(A, j, pivots[i]), fmpz_mod_mat_entry(A, i, pivots[i])) >= 0) { flint_free(pivots); return 0; } } } extra_row = _fmpz_vec_init(A->c); fmpz_init(g); for (i = 0; i < numberpivots; i++) { fmpz_gcd(g, ctx->n, fmpz_mod_mat_entry(A, i, pivots[i])); fmpz_divexact(g, ctx->n, g); _fmpz_vec_scalar_mul_fmpz(extra_row, A->rows[i], A->c, g); _fmpz_vec_scalar_mod_fmpz(extra_row, extra_row, A->c, ctx->n); for ( j = pivots[i] + 1; j < A->c; j++) { if (!fmpz_is_zero(extra_row + j)) { for ( r = i; r < numberpivots; r++) { if (pivots[r] == j) { if (fmpz_divisible(extra_row + j, fmpz_mod_mat_entry(A, r, pivots[r]))) { fmpz_divexact(g, extra_row + j, fmpz_mod_mat_entry(A, r, pivots[r])); fmpz_neg(g, g); _fmpz_vec_scalar_addmul_fmpz(extra_row, A->rows[r], A->c, g); } } } } } _fmpz_vec_scalar_mod_fmpz(extra_row, extra_row, A->c, ctx->n); if (!_fmpz_vec_is_zero(extra_row, A->c)) { _fmpz_vec_clear(extra_row, A->c); flint_free(pivots); fmpz_clear(g); return 0; } } _fmpz_vec_clear(extra_row, A->c); flint_free(pivots); fmpz_clear(g); return 1; } TEST_FUNCTION_START(fmpz_mod_mat_howell_form, state) { slong i; for (i = 0; i < 10000*flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, D; fmpz_mod_ctx_t ctx; fmpz_t t, c; slong j, k, m, n, r1, r2; slong *perm; int equal; fmpz_init(t); fmpz_init(c); fmpz_mod_ctx_init_rand_bits(ctx, state, 10); m = n_randint(state, 20); do { n = n_randint(state, 20); } while (n > m); perm = _perm_init(2*m); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(D, 2*m, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_init_set(B, A, ctx); r1 = fmpz_mod_mat_howell_form(B, ctx); if (!fmpz_mod_mat_is_in_howell_form(B, ctx)) { flint_printf("FAIL (malformed Howell form)\n"); fmpz_mod_mat_print_pretty(A, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B, ctx); flint_printf("\n\n"); flint_printf("Modulus: "); fmpz_print(ctx->n); flint_printf("\n\n"); fflush(stdout); flint_abort(); } _perm_randtest(perm, 2 * m, state); /* Concatenate the original matrix with the Howell form, scramble the rows, and check that the Howell form is the same */ for (j = 0; j < m; j++) { while (1) { fmpz_randtest_mod(c, state, ctx->n); fmpz_gcd(t, c, ctx->n); if (fmpz_is_one(t)) { break; } } for (k = 0; k < n; k++) fmpz_mul(fmpz_mod_mat_entry(D, perm[j], k), fmpz_mod_mat_entry(A, j, k), c); } for (j = 0; j < m; j++) { while (1) { fmpz_randtest_mod(c, state, ctx->n); fmpz_gcd(t, c, ctx->n); if (fmpz_is_one(t)) { break; } } for (k = 0; k < n; k++) fmpz_mul(fmpz_mod_mat_entry(D, perm[m + j], k), fmpz_mod_mat_entry(B, j, k), c); } _fmpz_mod_mat_reduce(D, ctx); r2 = fmpz_mod_mat_howell_form(D, ctx); equal = (r1 == r2); if (equal) { for (j = 0; j < r1; j++) for (k = 0; k < n; k++) equal = equal && fmpz_equal(fmpz_mod_mat_entry(B, j, k), fmpz_mod_mat_entry(D, j, k)); for (j = r1; j < 2*m; j++) for (k = 0; k < n; k++) equal = equal && fmpz_is_zero(fmpz_mod_mat_entry(D, j, k)); } if (!equal) { flint_printf("FAIL (r1 = %wd, r2 = %wd)!\n", r1, r2); fmpz_mod_mat_print_pretty(A, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(D, ctx); flint_printf("\n\n"); flint_printf("Modulus: "); fmpz_print(ctx->n); fflush(stdout); flint_abort(); } _perm_clear(perm); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(D, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(t); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-init_clear.c000066400000000000000000000020711461254215100215730ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_init_clear, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mat_t a; slong j, k; slong rows = n_randint(state, 100); slong cols = n_randint(state, 100); fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_mat_init(a, rows, cols, ctx); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) fmpz_zero(fmpz_mod_mat_entry(a, j, k)); fmpz_mod_mat_clear(a, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-inv.c000066400000000000000000000050151461254215100202570ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_inv, state) { fmpz_mod_mat_t A, B, C, I; fmpz_mod_ctx_t ctx; slong i, j, m, r; int result; for (i = 0; i < 5 * flint_test_multiplier(); i++) { m = n_randint(state, 20); fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); fmpz_mod_mat_init(A, m, m, ctx); fmpz_mod_mat_init(B, m, m, ctx); fmpz_mod_mat_init(C, m, m, ctx); fmpz_mod_mat_init(I, m, m, ctx); for (j = 0; j < m; j++) fmpz_one(fmpz_mod_mat_entry(I, j, j)); /* Verify that A * A^-1 = I for random matrices */ fmpz_mod_mat_randrank(A, state, m, ctx); /* Dense or sparse? */ if (n_randint(state, 2)) fmpz_mod_mat_randops(A, state, 1+n_randint(state, 1+m*m), ctx); result = fmpz_mod_mat_inv(B, A, ctx); fmpz_mod_mat_mul(C, A, B, ctx); FLINT_TEST(result && fmpz_mod_mat_equal(C, I, ctx)); /* Test aliasing */ fmpz_mod_mat_set(C, A, ctx); fmpz_mod_mat_inv(A, A, ctx); fmpz_mod_mat_mul(B, A, C, ctx); FLINT_TEST(fmpz_mod_mat_equal(B, I, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_mat_clear(I, ctx); fmpz_mod_ctx_clear(ctx); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 20); r = n_randint(state, m); fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); fmpz_mod_mat_init(A, m, m, ctx); fmpz_mod_mat_init(B, m, m, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); /* Dense */ if (n_randint(state, 2)) fmpz_mod_mat_randops(A, state, 1+n_randint(state, 1+m*m), ctx); FLINT_TEST(!fmpz_mod_mat_inv(B, A, ctx)); FLINT_TEST(!fmpz_mod_mat_inv(A, A, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-lu.c000066400000000000000000000056731461254215100201150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" void perm(fmpz_mod_mat_t A, slong * P) { slong i; fmpz ** tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(fmpz *) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } void check(slong * P, fmpz_mod_mat_t LU, const fmpz_mod_mat_t A, slong rank, const fmpz_mod_ctx_t ctx) { fmpz_mod_mat_t B, L, U; slong m, n, i, j; m = A->r; n = A->c; fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(L, m, m, ctx); fmpz_mod_mat_init(U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { FLINT_TEST(fmpz_is_zero(fmpz_mod_mat_entry(LU, i, j))); } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) fmpz_mod_mat_set_entry(L, i, j, fmpz_mod_mat_entry(LU, i, j), ctx); if (i < rank) fmpz_one(fmpz_mod_mat_entry(L, i, i)); for (j = i; j < n; j++) fmpz_mod_mat_set_entry(U, i, j, fmpz_mod_mat_entry(LU, i, j), ctx); } fmpz_mod_mat_mul(B, L, U, ctx); perm(B, P); FLINT_TEST(fmpz_mod_mat_equal(A, B, ctx)); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(L, ctx); fmpz_mod_mat_clear(U, ctx); } TEST_FUNCTION_START(fmpz_mod_mat_lu, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, LU; slong m, n, r, d, rank; slong *P; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); m = n_randint(state, 20); n = n_randint(state, 20); for (r = 0; r <= FLINT_MIN(m, n); r++) { fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2 * m * n + 1); fmpz_mod_mat_randops(A, state, d, ctx); } fmpz_mod_mat_init_set(LU, A, ctx); P = flint_malloc(sizeof(slong) * m); rank = fmpz_mod_mat_lu(P, LU, 0, ctx); FLINT_TEST(r == rank); check(P, LU, A, rank, ctx); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(LU, ctx); flint_free(P); } fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-minpoly.c000066400000000000000000000057441461254215100211630ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2015 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_mat_minpoly, state) { fmpz_mod_ctx_t ctx; fmpz_t t; fmpz_mod_mat_t A, B; fmpz_mod_poly_t p1, p2, q, r; slong i, j, k, m, n; /* minpoly(A) divides charpoly(A) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = m; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); fmpz_mod_poly_init(p1, ctx); fmpz_mod_poly_init(p2, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_charpoly(p1, A, ctx); fmpz_mod_mat_minpoly(p2, A, ctx); fmpz_mod_poly_divrem(q, r, p1, p2, ctx); FLINT_TEST(fmpz_mod_poly_is_zero(r, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_poly_clear(p1, ctx); fmpz_mod_poly_clear(p2, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_ctx_clear(ctx); } /* minpoly(P^{-1}AP) == minpoly(A) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = m; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); fmpz_init(t); fmpz_mod_poly_init(p1, ctx); fmpz_mod_poly_init(p2, ctx); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); for (j = 0; j < n/2; j++) { for (k = 0; k < n/2; k++) { fmpz_zero(fmpz_mod_mat_entry(A, j + n/2, k)); fmpz_zero(fmpz_mod_mat_entry(A, j, k + n/2)); fmpz_set(fmpz_mod_mat_entry(A, j + n/2, k + n/2), fmpz_mod_mat_entry(A, j, k)); } } fmpz_mod_mat_set(B, A, ctx); fmpz_mod_mat_minpoly(p1, A, ctx); for (j = 0; j < n; j++) { fmpz_mod_set_ui(t, n_randint(state, 6) - 3, ctx); fmpz_mod_mat_similarity(B, n_randint(state, n), t, ctx); } fmpz_mod_mat_minpoly(p2, B, ctx); FLINT_TEST(fmpz_mod_poly_equal(p1, p2, ctx)); fmpz_clear(t); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_poly_clear(p1, ctx); fmpz_mod_poly_clear(p2, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-mul.c000066400000000000000000000105221461254215100202570ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_mul, state) { fmpz_mod_mat_t A, B, B1, B2, C, C1, C2, D; slong max_threads = 5; slong i; /* test A*(B1+B1) = A*B1 + A*B2 */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong m, n, k; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits(ctx, state, 200); flint_set_num_threads(n_randint(state, max_threads) + 1); if (n_randint(state, 100) == 0) { m = n_randint(state, 300) + 100; n = n_randint(state, 300) + 100; k = n_randint(state, 300) + 100; } else if (n_randint(state, 10) == 0) { m = n_randint(state, 50); n = n_randint(state, 50); k = n_randint(state, 50); } else { m = n_randint(state, 8); n = n_randint(state, 8); k = n_randint(state, 8); } fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, n, k, ctx); fmpz_mod_mat_init(B1, n, k, ctx); fmpz_mod_mat_init(B2, n, k, ctx); fmpz_mod_mat_init(C, m, k, ctx); fmpz_mod_mat_init(C1, m, k, ctx); fmpz_mod_mat_init(C2, m, k, ctx); fmpz_mod_mat_init(D, m, k, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B1, state, ctx); fmpz_mod_mat_randtest(B2, state, ctx); /* Make sure noise in the output is ok */ fmpz_mod_mat_randtest(C, state, ctx); fmpz_mod_mat_randtest(C1, state, ctx); fmpz_mod_mat_randtest(C2, state, ctx); fmpz_mod_mat_mul(C1, A, B1, ctx); fmpz_mod_mat_mul(C2, A, B2, ctx); fmpz_mod_mat_add(B, B1, B2, ctx); fmpz_mod_mat_mul(C, A, B, ctx); fmpz_mod_mat_add(D, C1, C2, ctx); if (!fmpz_mod_mat_equal(C, D, ctx)) { flint_printf("FAIL: results not equal\n\n"); fmpz_mod_mat_print_pretty(A, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B1, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B2, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(C, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(D, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (n == k) { fmpz_mod_mat_mul(A, A, B, ctx); if (!fmpz_mod_mat_equal(A, C, ctx)) { flint_printf("FAIL: aliasing failed\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(B1, ctx); fmpz_mod_mat_clear(B2, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_mat_clear(C1, ctx); fmpz_mod_mat_clear(C2, ctx); fmpz_mod_mat_clear(D, ctx); fmpz_mod_ctx_clear(ctx); } /* Test aliasing with windows */ { fmpz_mod_mat_t A, B, A_window; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 3); fmpz_mod_mat_init(A, 2, 2, ctx); fmpz_mod_mat_init(B, 2, 2, ctx); fmpz_mod_mat_window_init(A_window, A, 0, 0, 2, 2, ctx); fmpz_mod_mat_one(A, ctx); fmpz_mod_mat_one(B, ctx); fmpz_set_ui(fmpz_mod_mat_entry(B, 0, 1), 1); fmpz_set_ui(fmpz_mod_mat_entry(B, 1, 0), 1); fmpz_mod_mat_mul(A_window, B, A_window, ctx); if (!fmpz_mod_mat_equal(A, B, ctx)) { flint_printf("FAIL: window aliasing failed\n"); fmpz_mod_mat_print_pretty(A, ctx); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_window_clear(A_window, ctx); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-mul_classical_threaded.c000077500000000000000000000044451461254215100241470ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_mul_classical_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) slong i, max_threads = 5; slong tmul = 1000; #ifdef _WIN32 tmul = 50; #endif for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, C, D; fmpz_mod_ctx_t ctx; slong m, k, n; flint_set_num_threads(n_randint(state, max_threads) + 1); m = n_randint(state, 50); k = n_randint(state, 50); n = n_randint(state, 50); /* We want to generate matrices with many entries close to half or full limbs with high probability, to stress overflow handling */ fmpz_mod_ctx_init_rand_bits(ctx, state, 100); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, n, k, ctx); fmpz_mod_mat_init(C, m, k, ctx); fmpz_mod_mat_init(D, m, k, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_randtest(C, state, ctx); /* make sure noise in the output is ok */ fmpz_mod_mat_mul_classical_threaded(C, A, B, ctx); fmpz_mod_mat_mul(D, A, B, ctx); if (!fmpz_mod_mat_equal(C, D, ctx)) { flint_printf("FAIL: results not equal\n"); fmpz_mod_mat_print_pretty(A, ctx); fmpz_mod_mat_print_pretty(B, ctx); fmpz_mod_mat_print_pretty(C, ctx); fmpz_mod_mat_print_pretty(D, ctx); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_mat_clear(D, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/fmpz_mod_mat/test/t-mul_fmpz_vec.c000066400000000000000000000054771461254215100221650ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_mul_fmpz_vec, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, C; fmpz * b, * c; fmpz ** bb, ** cc; slong j, m, n, blen; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits(ctx, state, 200); m = n_randint(state, 50); n = n_randint(state, 50); blen = n_randint(state, 50); fmpz_mod_mat_init(C, m, 1, ctx); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, n, 1, ctx); c = _fmpz_vec_init(m); b = _fmpz_vec_init(blen); fmpz_mod_mat_randtest(A, state, ctx); _fmpz_vec_randtest(c, state, m, n_randint(state, 200) + 1); _fmpz_vec_randtest(b, state, blen, n_randint(state, 200) + 1); cc = FLINT_ARRAY_ALLOC(m, fmpz*); for (j = 0; j < m; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(cc[j], c + j); } bb = FLINT_ARRAY_ALLOC(blen, fmpz*); for (j = 0; j < blen; j++) { bb[j] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init_set(bb[j], b + j); } fmpz_mod_mat_mul_fmpz_vec(c, A, b, blen, ctx); fmpz_mod_mat_mul_fmpz_vec_ptr(cc, A, (const fmpz * const *)bb, blen, ctx); /* supposed to match mul of the chopped or zero-extended b */ for (j = 0; j < n && j < blen; j++) fmpz_mod_set_fmpz(fmpz_mod_mat_entry(B, j, 0), b + j, ctx); fmpz_mod_mat_mul(C, A, B, ctx); for (j = 0; j < m; j++) { if (!fmpz_equal(fmpz_mod_mat_entry(C, j, 0), c + j) || !fmpz_equal(fmpz_mod_mat_entry(C, j, 0), cc[j])) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); _fmpz_vec_clear(c, m); _fmpz_vec_clear(b, blen); fmpz_mod_ctx_clear(ctx); for (j = 0; j < m; j++) { fmpz_clear(cc[j]); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < blen; j++) { fmpz_clear(bb[j]); flint_free(bb[j]); } flint_free(bb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-nullspace.c000066400000000000000000000034761461254215100214620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_nullspace, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, B, ker; slong m, n, d, r, nullity, nulrank; m = n_randint(state, 30); n = n_randint(state, 30); for (r = 0; r <= FLINT_MIN(m, n); r++) { fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); d = n_randint(state, 2 * m * n + 1); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(ker, n, n, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); /* Densify */ if (n_randlimb(state) % 2) fmpz_mod_mat_randops(A, state, d, ctx); nullity = fmpz_mod_mat_nullspace(ker, A, ctx); nulrank = fmpz_mod_mat_rank(ker, ctx); FLINT_TEST(nullity == nulrank); FLINT_TEST(nullity + r == n); fmpz_mod_mat_mul(B, A, ker, ctx); FLINT_TEST(fmpz_mod_mat_rank(B, ctx) == 0); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(ker, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_ctx_clear(ctx); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-rank.c000066400000000000000000000034511461254215100204200ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_rank, state) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A; slong i, m, n, d, r; /* Maximally sparse matrices of given rank */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); for (r = 0; r <= FLINT_MIN(m, n); r++) { fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); FLINT_TEST(r == fmpz_mod_mat_rank(A, ctx)); fmpz_mod_mat_clear(A, ctx); } fmpz_mod_ctx_clear(ctx); } /* Dense */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); for (r = 0; r <= FLINT_MIN(m, n); r++) { d = n_randint(state, 2 * m * n + 1); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); fmpz_mod_mat_randops(A, state, d, ctx); FLINT_TEST(r == fmpz_mod_mat_rank(A, ctx)); fmpz_mod_mat_clear(A, ctx); } fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-rref.c000066400000000000000000000061741461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_mat.h" static void check_rref(fmpz_mod_mat_t A) { slong i, j, prev_pivot, prev_row_zero; prev_row_zero = 0; prev_pivot = -1; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { /* Found nonzero entry */ if (!fmpz_is_zero(A->rows[i] + j)) { if (prev_row_zero) { flint_printf("nonzero row after zero row\n"); fflush(stdout); flint_abort(); } if (j <= prev_pivot) { flint_printf("pivot not strictly to the right of previous\n"); fflush(stdout); flint_abort(); } prev_pivot = j; break; } prev_row_zero = (j + 1 == A->c); } } } TEST_FUNCTION_START(fmpz_mod_mat_rref, state) { fmpz_mod_mat_t A; fmpz_mod_ctx_t ctx; slong i, m, n, d, r, rank; /* Maximally sparse matrices of given rank */ for (i = 0; i < 10000; i++) { m = n_randint(state, 10); n = n_randint(state, 10); fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 100); for (r = 0; r <= FLINT_MIN(m, n); r++) { fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); rank = fmpz_mod_mat_rref(A, A, ctx); if (r < rank) { fmpz_mod_mat_print_pretty(A, ctx); flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } check_rref(A); fmpz_mod_mat_clear(A, ctx); } fmpz_mod_ctx_clear(ctx); } /* Dense */ for (i = 0; i < 10000; i++) { m = n_randint(state, 5); n = n_randint(state, 4); fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 100); for (r = 0; r <= FLINT_MIN(m, n); r++) { d = n_randint(state, 2 * m * n + 1); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); fmpz_mod_mat_randops(A, state, d, ctx); rank = fmpz_mod_mat_rref(A, A, ctx); if (r < rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } check_rref(A); fmpz_mod_mat_clear(A, ctx); } fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000040111461254215100226340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_scalar_mul_fmpz, state) { slong m, n, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A, B, C, D; fmpz_t c, c1; fmpz_mod_ctx_t ctx; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(c); fmpz_init(c1); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(C, m, n, ctx); fmpz_mod_mat_init(D, m, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_scalar_mul_fmpz(C, A, c, ctx); fmpz_set(c1, c); fmpz_sub_ui(c1, c1, 1); fmpz_mod_mat_scalar_mul_fmpz(D, A, c1, ctx); /* c*A - (c-1)*A == A */ fmpz_mod_mat_sub(D, C, D, ctx); if (!fmpz_mod_mat_equal(A, D, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } /* Aliasing */ fmpz_mod_mat_scalar_mul_fmpz(C, A, c, ctx); fmpz_mod_mat_scalar_mul_fmpz(A, A, c, ctx); if (!fmpz_mod_mat_equal(A, C, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_mat_clear(D, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(c1); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-scalar_mul_si.c000066400000000000000000000041001461254215100222720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_scalar_mul_si, state) { slong m, n, rep; for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A, B, C, D; ulong c; fmpz_t c1; fmpz_mod_ctx_t ctx; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(c1); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); c = n_randtest(state); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(C, m, n, ctx); fmpz_mod_mat_init(D, m, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_scalar_mul_si(C, A, c, ctx); fmpz_set_si(c1, c); fmpz_sub_si(c1, c1, 1); fmpz_mod(c1, c1, ctx->n); fmpz_mod_mat_scalar_mul_fmpz(D, A, c1, ctx); /* c*A - (c-1)*A == A */ fmpz_mod_mat_sub(D, C, D, ctx); if (!fmpz_mod_mat_equal(A, D, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } /* Aliasing */ fmpz_mod_mat_scalar_mul_si(C, A, c, ctx); fmpz_mod_mat_scalar_mul_si(A, A, c, ctx); if (!fmpz_mod_mat_equal(A, C, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_mat_clear(D, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(c1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-scalar_mul_ui.c000066400000000000000000000041001461254215100222740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_scalar_mul_ui, state) { slong m, n, rep; for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A, B, C, D; ulong c; fmpz_t c1; fmpz_mod_ctx_t ctx; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(c1); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); c = n_randtest(state); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(C, m, n, ctx); fmpz_mod_mat_init(D, m, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_scalar_mul_ui(C, A, c, ctx); fmpz_set_ui(c1, c); fmpz_sub_ui(c1, c1, 1); fmpz_mod(c1, c1, ctx->n); fmpz_mod_mat_scalar_mul_fmpz(D, A, c1, ctx); /* c*A - (c-1)*A == A */ fmpz_mod_mat_sub(D, C, D, ctx); if (!fmpz_mod_mat_equal(A, D, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } /* Aliasing */ fmpz_mod_mat_scalar_mul_ui(C, A, c, ctx); fmpz_mod_mat_scalar_mul_ui(A, A, c, ctx); if (!fmpz_mod_mat_equal(A, C, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_mat_clear(D, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(c1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-solve.c000066400000000000000000000050061461254215100206130ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_solve, state) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, X, B, AX; slong i, m, n, r; int solved; for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); m = n_randint(state, 50); n = n_randint(state, 50); fmpz_mod_mat_init(A, m, m, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(X, m, n, ctx); fmpz_mod_mat_init(AX, m, n, ctx); fmpz_mod_mat_randrank(A, state, m, ctx); fmpz_mod_mat_randtest(B, state, ctx); /* Dense */ if (n_randint(state, 2)) fmpz_mod_mat_randops(A, state, 1+n_randint(state, 1+m*m), ctx); solved = fmpz_mod_mat_solve(X, A, B, ctx); fmpz_mod_mat_mul(AX, A, X, ctx); FLINT_TEST(solved && fmpz_mod_mat_equal(AX, B, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(X, ctx); fmpz_mod_mat_clear(AX, ctx); fmpz_mod_ctx_clear(ctx); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); r = n_randint(state, m); fmpz_mod_mat_init(A, m, m, ctx); fmpz_mod_mat_init(B, m, n, ctx); fmpz_mod_mat_init(X, m, n, ctx); fmpz_mod_mat_init(AX, m, n, ctx); fmpz_mod_mat_randrank(A, state, r, ctx); fmpz_mod_mat_randtest(B, state, ctx); /* Dense */ if (n_randint(state, 2)) fmpz_mod_mat_randops(A, state, 1+n_randint(state, 1+m*m), ctx); solved = fmpz_mod_mat_solve(X, A, B, ctx); FLINT_TEST(!solved); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(X, ctx); fmpz_mod_mat_clear(AX, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-solve_tril.c000066400000000000000000000033561461254215100216530ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_solve_tril, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, X, B, Y; slong rows, cols; int unit; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); fmpz_mod_mat_init(A, rows, rows, ctx); fmpz_mod_mat_init(B, rows, cols, ctx); fmpz_mod_mat_init(X, rows, cols, ctx); fmpz_mod_mat_init(Y, rows, cols, ctx); fmpz_mod_mat_randtril(A, state, unit, ctx); fmpz_mod_mat_randtest(X, state, ctx); fmpz_mod_mat_mul(B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ fmpz_mod_mat_solve_tril(Y, A, B, unit, ctx); FLINT_TEST(fmpz_mod_mat_equal(Y, X, ctx)); /* Check aliasing */ fmpz_mod_mat_solve_tril(B, A, B, unit, ctx); FLINT_TEST(fmpz_mod_mat_equal(B, X, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(X, ctx); fmpz_mod_mat_clear(Y, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-solve_triu.c000066400000000000000000000033561461254215100216640ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_solve_triu, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, X, B, Y; slong rows, cols; int unit; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, 200); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); fmpz_mod_mat_init(A, rows, rows, ctx); fmpz_mod_mat_init(B, rows, cols, ctx); fmpz_mod_mat_init(X, rows, cols, ctx); fmpz_mod_mat_init(Y, rows, cols, ctx); fmpz_mod_mat_randtriu(A, state, unit, ctx); fmpz_mod_mat_randtest(X, state, ctx); fmpz_mod_mat_mul(B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ fmpz_mod_mat_solve_triu(Y, A, B, unit, ctx); FLINT_TEST(fmpz_mod_mat_equal(Y, X, ctx)); /* Check aliasing */ fmpz_mod_mat_solve_triu(B, A, B, unit, ctx); FLINT_TEST(fmpz_mod_mat_equal(B, X, ctx)); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(X, ctx); fmpz_mod_mat_clear(Y, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-sqr.c000066400000000000000000000032471461254215100202750ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_sqr, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, C; slong n; fmpz_mod_ctx_t ctx; n = n_randint(state, 20); fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_mat_init(A, n, n, ctx); fmpz_mod_mat_init(B, n, n, ctx); fmpz_mod_mat_init(C, n, n, ctx); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); /* Make sure noise in the output is ok */ fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_sqr(B, A, ctx); fmpz_mod_mat_mul(C, A, A, ctx); if (!fmpz_mod_mat_equal(C, B, ctx)) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_sqr(A, A, ctx); if (!fmpz_mod_mat_equal(A, B, ctx)) { flint_printf("FAIL: aliasing failed\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-trace.c000066400000000000000000000042111461254215100205560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_trace, state) { slong i; /* Test trace(AB) = trace(BA) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t A, B, AB, BA; fmpz_t trab, trba; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); fmpz_mod_ctx_init_rand_bits(ctx, state, 100); fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, n, m, ctx); fmpz_mod_mat_init(AB, m, m, ctx); fmpz_mod_mat_init(BA, n, n, ctx); fmpz_init(trab); fmpz_init(trba); fmpz_mod_mat_randtest(A, state, ctx); fmpz_mod_mat_randtest(B, state, ctx); fmpz_mod_mat_mul(AB, A, B, ctx); fmpz_mod_mat_mul(BA, B, A, ctx); fmpz_mod_mat_trace(trab, AB, ctx); fmpz_mod_mat_trace(trba, BA, ctx); if (!fmpz_equal(trab, trba)) { flint_printf("FAIL:\n"); fmpz_mod_mat_print_pretty(A, ctx), flint_printf("\n"); fmpz_mod_mat_print_pretty(B, ctx), flint_printf("\n"); fmpz_mod_mat_print_pretty(AB, ctx), flint_printf("\n"); fmpz_mod_mat_print_pretty(BA, ctx), flint_printf("\n"); flint_printf("tr(AB): "); fmpz_print(trab); flint_printf("\n"); flint_printf("tr(BA): "); fmpz_print(trba); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(AB, ctx); fmpz_mod_mat_clear(BA, ctx); fmpz_clear(trab); fmpz_clear(trba); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/test/t-window_init_clear.c000066400000000000000000000030261461254215100231630ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_mat.h" TEST_FUNCTION_START(fmpz_mod_mat_window_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t a, w; slong j, k, r1, r2, c1, c2; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mod_ctx_init_rand_bits(ctx, state, 100); fmpz_mod_mat_init(a, rows, cols, ctx); fmpz_mod_mat_randtest(a, state, ctx); r2 = n_randint(state, rows + 1); c2 = n_randint(state, cols + 1); if (r2) r1 = n_randint(state, r2); else r1 = 0; if (c2) c1 = n_randint(state, c2); else c1 = 0; fmpz_mod_mat_window_init(w, a, r1, c1, r2, c2, ctx); for (j = 0; j < r2 - r1; j++) for (k = 0; k < c2 - c1; k++) fmpz_zero(fmpz_mod_mat_entry(w, j, k)); fmpz_mod_mat_window_clear(w, ctx); fmpz_mod_mat_clear(a, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mat/trace.c000066400000000000000000000011441461254215100173400ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_trace(fmpz_t trace, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) { fmpz_mat_trace(trace, mat); fmpz_mod_set_fmpz(trace, trace, ctx); } flint-3.1.3/src/fmpz_mod_mat/window_clear.c000066400000000000000000000010351461254215100207160ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_window_clear(fmpz_mod_mat_t window, const fmpz_mod_ctx_t ctx) { fmpz_mat_window_clear(window); } flint-3.1.3/src/fmpz_mod_mat/window_init.c000066400000000000000000000012201461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_window_init(fmpz_mod_mat_t window, const fmpz_mod_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fmpz_mod_ctx_t ctx) { fmpz_mat_window_init(window, mat, r1, c1, r2, c2); } flint-3.1.3/src/fmpz_mod_mpoly.h000066400000000000000000001163121461254215100166320ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_MPOLY_H #define FMPZ_MOD_MPOLY_H #ifdef FMPZ_MOD_MPOLY_INLINES_C #define FMPZ_MOD_MPOLY_INLINE #else #define FMPZ_MOD_MPOLY_INLINE static inline #endif #include "fmpz.h" #include "mpoly_types.h" #if FLINT_WANT_ASSERT # include "mpoly.h" #endif #ifdef __cplusplus extern "C" { #endif /* type definitions **********************************************************/ /* fmpz_mod_mpoly_univar_t sparse univariates with multivariate coefficients */ typedef struct { fmpz_mod_mpoly_struct * coeffs; /* multivariate coefficients */ fmpz * exps; slong alloc; slong length; } fmpz_mod_mpoly_univar_struct; typedef fmpz_mod_mpoly_univar_struct fmpz_mod_mpoly_univar_t[1]; /* Context object ************************************************************/ void fmpz_mod_mpoly_ctx_init(fmpz_mod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fmpz_t modulus); void fmpz_mod_mpoly_ctx_init_rand(fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, const fmpz_t modulus); void fmpz_mod_mpoly_ctx_init_rand_bits_prime(fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, flint_bitcnt_t max_bits); void fmpz_mod_mpoly_ctx_init_rand_bits(fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, flint_bitcnt_t max_bits); void fmpz_mod_mpoly_ctx_clear(fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_mpoly_ctx_nvars(const fmpz_mod_mpoly_ctx_t ctx) { return ctx->minfo->nvars; } FMPZ_MOD_MPOLY_INLINE ordering_t fmpz_mod_mpoly_ctx_ord(const fmpz_mod_mpoly_ctx_t ctx) { return ctx->minfo->ord; } FMPZ_MOD_MPOLY_INLINE const fmpz * fmpz_mod_mpoly_ctx_modulus(const fmpz_mod_mpoly_ctx_t ctx) { return ctx->ffinfo->n; } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_ctx_get_modulus(fmpz_t m, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_set(m, fmpz_mod_mpoly_ctx_modulus(ctx)); } /* Memory management ********************************************************/ FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_init(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->bits = MPOLY_MIN_BITS; A->coeffs_alloc = 0; A->exps_alloc = 0; } void fmpz_mod_mpoly_clear(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_init2(fmpz_mod_mpoly_t A, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_init3(fmpz_mod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_realloc(fmpz_mod_mpoly_t A, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_fit_length(fmpz_mod_mpoly_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_fit_length_fit_bits(fmpz_mod_mpoly_t A, slong len, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_fit_length_reset_bits(fmpz_mod_mpoly_t A, slong len, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void _fmpz_mod_mpoly_fit_length( fmpz ** coeffs, slong * coeffs_alloc, ulong ** exps, slong * exps_alloc, slong N, slong length) { if (length > *coeffs_alloc) { slong i, old_alloc = *coeffs_alloc; slong new_alloc = FLINT_MAX(length, old_alloc*2); *coeffs_alloc = new_alloc; *coeffs = (fmpz *) flint_realloc(*coeffs, new_alloc*sizeof(fmpz)); for (i = old_alloc; i < new_alloc; i++) fmpz_init(*coeffs + i); } if (N*length > *exps_alloc) { *exps_alloc = FLINT_MAX(N*length, *exps_alloc*2); *exps = (ulong *) flint_realloc(*exps, *exps_alloc*sizeof(ulong)); } } FMPZ_MOD_MPOLY_INLINE void _fmpz_mod_mpoly_set_length(fmpz_mod_mpoly_t A, slong newlen, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(newlen <= A->coeffs_alloc); FLINT_ASSERT(mpoly_words_per_exp(A->bits, ctx->minfo)*newlen <= A->exps_alloc); A->length = newlen; } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_truncate(fmpz_mod_mpoly_t A, slong newlen, const fmpz_mod_mpoly_ctx_t ctx) { if (A->length > newlen) { slong i; for (i = newlen; i < A->length; i++) _fmpz_demote(A->coeffs + i); A->length = newlen; } } /* Input/output **************************************************************/ int fmpz_mod_mpoly_set_str_pretty(fmpz_mod_mpoly_t A, const char * str, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); char * fmpz_mod_mpoly_get_str_pretty(const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); #ifdef FLINT_HAVE_FILE int fmpz_mod_mpoly_fprint_pretty(FILE * file, const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); #endif int fmpz_mod_mpoly_print_pretty(const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); /* Basic manipulation *******************************************************/ void fmpz_mod_mpoly_gen(fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_is_gen(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_equal(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_swap(fmpz_mod_mpoly_t A, fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_SWAP(fmpz_mod_mpoly_struct, *A, *B); } /* Constants *****************************************************************/ int fmpz_mod_mpoly_is_fmpz(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_fmpz_mod(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_ui(fmpz_mod_mpoly_t A, ulong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_si(fmpz_mod_mpoly_t A, slong c, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_zero(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_set_length(A, 0, ctx); } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_one(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_set_si(A, 1, ctx); } int fmpz_mod_mpoly_equal_fmpz(const fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_equal_ui(const fmpz_mod_mpoly_t A, ulong c, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_equal_si(const fmpz_mod_mpoly_t A, slong c, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE int fmpz_mod_mpoly_is_zero(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return A->length < 1; } FMPZ_MOD_MPOLY_INLINE int fmpz_mod_mpoly_is_one(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_equal_si(A, 1, ctx); } /* Degrees *******************************************************************/ int fmpz_mod_mpoly_degrees_fit_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_degrees_fmpz(fmpz ** degs, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_degrees_si(slong * degs, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); slong fmpz_mod_mpoly_degree_si(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_total_degree_fits_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_total_degree_fmpz(fmpz_t td, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); slong fmpz_mod_mpoly_total_degree_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_used_vars(int * used, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); /* Coefficients **************************************************************/ void fmpz_mod_mpoly_get_coeff_fmpz_monomial(fmpz_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_coeff_fmpz_monomial(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_coeff_fmpz_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_coeff_fmpz_ui(fmpz_t c, const fmpz_mod_mpoly_t A, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_set_coeff_fmpz_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_coeff_fmpz_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_coeff_ui_fmpz(fmpz_mod_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_coeff_si_fmpz(fmpz_mod_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_coeff_fmpz_ui(fmpz_mod_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_coeff_ui_ui(fmpz_mod_mpoly_t A, ulong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_coeff_si_ui(fmpz_mod_mpoly_t A, slong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_coeff_vars_ui(fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE fmpz * fmpz_mod_mpoly_leadcoeff(fmpz_mod_mpoly_t A) { FLINT_ASSERT(A->length > 0); return A->coeffs + 0; } /* conversion ****************************************************************/ int fmpz_mod_mpoly_is_fmpz_mod_poly(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_get_fmpz_mod_poly(fmpz_mod_poly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_set_fmpz_mod_poly(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz * Bcoeffs, slong Blen, slong var, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_fmpz_mod_poly(fmpz_mod_mpoly_t A, const fmpz_mod_poly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); /* comparison ****************************************************************/ int fmpz_mod_mpoly_cmp(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); /* container operations ******************************************************/ int fmpz_mod_mpoly_is_canonical(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_mpoly_length(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return A->length; } void fmpz_mod_mpoly_resize(fmpz_mod_mpoly_t A, slong new_length, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_term_coeff_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_term_coeff_fmpz(fmpz_mod_mpoly_t A, slong i, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_term_coeff_ui(fmpz_mod_mpoly_t A, slong i, ulong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_term_coeff_si(fmpz_mod_mpoly_t A, slong i, slong c, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_term_exp_fits_ui(const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_term_exp_fits_si(const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_term_exp_ui(ulong * exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_term_exp_si(slong * exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); ulong fmpz_mod_mpoly_get_term_var_exp_ui(const fmpz_mod_mpoly_t A, slong i, slong var, const fmpz_mod_mpoly_ctx_t ctx); slong fmpz_mod_mpoly_get_term_var_exp_si(const fmpz_mod_mpoly_t A, slong i, slong var, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_term_exp_fmpz(fmpz_mod_mpoly_t A, slong i, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_term_exp_ui(fmpz_mod_mpoly_t A, slong i, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_term(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_get_term_monomial(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_fmpz_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_fmpz_ffmpz(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_ui_fmpz(fmpz_mod_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_ui_ffmpz(fmpz_mod_mpoly_t A, ulong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_si_fmpz(fmpz_mod_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_si_ffmpz(fmpz_mod_mpoly_t A, slong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_fmpz_ui(fmpz_mod_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_ui_ui(fmpz_mod_mpoly_t A, ulong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_push_term_si_ui(fmpz_mod_mpoly_t A, slong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_sort_terms(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_combine_like_terms(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_reverse(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_assert_canonical(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_radix_sort1(fmpz *, ulong *, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); void _fmpz_mod_mpoly_radix_sort(fmpz *, ulong *, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); void _fmpz_mod_mpoly_push_exp_ffmpz(fmpz_mod_mpoly_t A, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_push_exp_pfmpz(fmpz_mod_mpoly_t A, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_push_exp_ui(fmpz_mod_mpoly_t A, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); /* Random generation *********************************************************/ void fmpz_mod_mpoly_randtest_bounds(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_randtest_bound(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_randtest_bits(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const fmpz_mod_mpoly_ctx_t ctx); /* Addition/Subtraction ******************************************************/ void fmpz_mod_mpoly_add_fmpz_mod(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_add_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_add_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_add_si(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_sub_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_sub_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_sub_si(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_add(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_sub(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx); /* Scalar operations *********************************************************/ void fmpz_mod_mpoly_neg(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_scalar_mul_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_scalar_mul_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_scalar_mul_si(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_scalar_addmul_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_t d, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_make_monic(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); /* Differentiation ************************************************************/ void fmpz_mod_mpoly_derivative(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ void _fmpz_mod_mpoly_eval_all_fmpz_mod(fmpz_t eval, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const fmpz * alphas, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fctx); void fmpz_mod_mpoly_evaluate_all_fmpz(fmpz_t eval, const fmpz_mod_mpoly_t A, fmpz * const * alphas, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_evaluate_one_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_t val, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_compose_mat(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mat_t M, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC); int fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz_mod_mpoly_struct * const * C, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC); int fmpz_mod_mpoly_compose_fmpz_mod_mpoly(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz_mod_mpoly_struct * const * C, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC); /* Multiplication ************************************************************/ void fmpz_mod_mpoly_mul(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_mul_johnson(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_mul_johnson_maxfields(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_t C, fmpz * maxCfields, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_mul_dense(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx); int _fmpz_mod_mpoly_mul_dense_maxfields(fmpz_mod_mpoly_t P, const fmpz_mod_mpoly_t A, fmpz * maxAfields, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_ctx_t ctx); /* Powering ******************************************************************/ int fmpz_mod_mpoly_pow_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t k, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_pow_ui(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong k, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_pow_rmul(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong k, const fmpz_mod_mpoly_ctx_t ctx); /* Division ******************************************************************/ int fmpz_mod_mpoly_divides(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_div(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_divrem(fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_divrem_ideal(fmpz_mod_mpoly_struct ** Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, fmpz_mod_mpoly_struct * const * B, slong len, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_divexact(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_divides(Q, A, B, ctx)) return; flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_divexact: nonexact division"); } int _fmpz_mod_mpoly_divides_dense_maxfields(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, fmpz * maxAfields, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_divides_dense(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int _fmpz_mod_mpoly_divides_monagan_pearce_maxfields( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, fmpz * maxAfields, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_divides_monagan_pearce(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_div_monagan_pearce(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_divrem_monagan_pearce(fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_divrem_ideal_monagan_pearce( fmpz_mod_mpoly_struct ** Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, fmpz_mod_mpoly_struct * const * B, slong len, const fmpz_mod_mpoly_ctx_t ctx); /* Square root ***************************************************************/ int fmpz_mod_mpoly_sqrt_heap(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE int fmpz_mod_mpoly_sqrt(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_sqrt_heap(Q, A, ctx); } FMPZ_MOD_MPOLY_INLINE int fmpz_mod_mpoly_is_square(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { int res; fmpz_mod_mpoly_t Q; fmpz_mod_mpoly_init(Q, ctx); res = fmpz_mod_mpoly_sqrt_heap(Q, A, ctx); fmpz_mod_mpoly_clear(Q, ctx); return res; } int fmpz_mod_mpoly_quadratic_root(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); /* GCD ***********************************************************************/ void fmpz_mod_mpoly_term_content(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_content_vars(fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_t A, slong * vars, slong vars_length, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_gcd(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_gcd_cofactors(fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_gcd_subresultant(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_gcd_brown(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_gcd_hensel(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_gcd_zippel(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_gcd_zippel2(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_deflate(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_inflate(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mod_mpoly_ctx_t ctx); /* Univariates ***************************************************************/ void fmpz_mod_mpoly_univar_init(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_univar_clear(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_univar_fit_length(fmpz_mod_mpoly_univar_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_univar_print_pretty(const fmpz_mod_mpoly_univar_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_univar_assert_canonical(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_univar_zero(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) { A->length = 0; } void fmpz_mod_mpoly_univar_set_coeff_ui(fmpz_mod_mpoly_univar_t A, ulong e, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_to_univar(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_from_univar(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_univar_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_from_univar(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_univar_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_univar_swap(fmpz_mod_mpoly_univar_t A, fmpz_mod_mpoly_univar_t B, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_SWAP(fmpz_mod_mpoly_univar_struct, *A, *B); } FMPZ_MOD_MPOLY_INLINE int fmpz_mod_mpoly_univar_degree_fits_si(const fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) { return A->length == 0 || fmpz_fits_si(A->exps + 0); } FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_mpoly_univar_length(const fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) { return A->length; } FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_mpoly_univar_get_term_exp_si(fmpz_mod_mpoly_univar_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong)A->length); return fmpz_get_si(A->exps + i); } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_univar_get_term_coeff(fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_univar_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fmpz_mod_mpoly_set(c, A->coeffs + i, ctx); } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_univar_swap_term_coeff(fmpz_mod_mpoly_t c, fmpz_mod_mpoly_univar_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fmpz_mod_mpoly_swap(c, A->coeffs + i, ctx); } int fmpz_mod_mpoly_univar_pseudo_gcd(fmpz_mod_mpoly_univar_t Gx, const fmpz_mod_mpoly_univar_t Ax, const fmpz_mod_mpoly_univar_t Bx, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_univar_resultant(fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_univar_t Ax, const fmpz_mod_mpoly_univar_t Bx, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_univar_discriminant(fmpz_mod_mpoly_t D, const fmpz_mod_mpoly_univar_t Fx, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_resultant(fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_discriminant(fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ FMPZ_MOD_MPOLY_INLINE void _fmpz_mod_mpoly_clear_dense_mock(fmpz_mod_poly_t D) { flint_free(D->coeffs); } void _fmpz_mod_mpoly_init_dense_mock(fmpz_mod_poly_t D, const fmpz_mod_mpoly_t A, const slong * Adeg_bounds, const fmpz_mod_mpoly_ctx_t ctx); void mpoly_void_ring_init_fmpz_mod_mpoly_ctx(mpoly_void_ring_t R, const fmpz_mod_mpoly_ctx_t ctx); /* geobuckets ****************************************************************/ typedef struct fmpz_mod_mpoly_geobucket { fmpz_mod_mpoly_struct polys[FLINT_BITS/2]; fmpz_mod_mpoly_struct temps[FLINT_BITS/2]; slong length; } fmpz_mod_mpoly_geobucket_struct; typedef fmpz_mod_mpoly_geobucket_struct fmpz_mod_mpoly_geobucket_t[1]; void fmpz_mod_mpoly_geobucket_init(fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_geobucket_clear(fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_geobucket_empty(fmpz_mod_mpoly_t p, fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_geobucket_fit_length(fmpz_mod_mpoly_geobucket_t B, slong i, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_geobucket_set(fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_geobucket_add(fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_geobucket_sub(fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyl_lead_coeff(fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_t A, slong num_vars, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyl_content(fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_t A, slong num_vars, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_to_fmpz_mod_poly_deflate(fmpz_mod_poly_t A, const fmpz_mod_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_from_fmpz_mod_poly_inflate(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_set_nmod_mpoly(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, const nmod_mpoly_t nA, const nmod_mpoly_ctx_t nctx); void _fmpz_mod_mpoly_get_nmod_mpoly(nmod_mpoly_t nA, const nmod_mpoly_ctx_t nctx, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_repack_bits(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_repack_bits_inplace(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_to_mpolyl_perm_deflate(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t lctx, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride); void fmpz_mod_mpoly_from_mpolyl_perm_inflate(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride); /****************************************************************************** Internal consistency checks ******************************************************************************/ void fmpz_mod_mpoly_remainder_strongtest(const fmpz_mod_mpoly_t r, const fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mod_mpoly/000077500000000000000000000000001461254215100164555ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_mpoly/add.c000066400000000000000000000077261461254215100173650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" slong _fmpz_mod_mpoly_add( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, const fmpz_mod_ctx_t fctx) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_mod_add(Acoeffs + k, Bcoeffs + i, Ccoeffs + j, fctx); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_set(Acoeffs + k, Ccoeffs + j); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_set(Acoeffs + k, Ccoeffs + j); j++; k++; } return k; } void fmpz_mod_mpoly_add( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) { slong Abits, N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_set(A, C, ctx); return; } else if (fmpz_mod_mpoly_is_zero(C, ctx)) { fmpz_mod_mpoly_set(A, B, ctx); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init3(T, B->length + C->length, Abits, ctx); T->length = _fmpz_mod_mpoly_add(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->ffinfo); fmpz_mod_mpoly_swap(A, T, ctx); fmpz_mod_mpoly_clear(T, ctx); } else { fmpz_mod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _fmpz_mod_mpoly_add(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->ffinfo); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/add_fmpz.c000066400000000000000000000056631461254215100204170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_add_fmpz_mod( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong Blen = B->length; FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx->ffinfo)); if (fmpz_is_zero(c)) { fmpz_mod_mpoly_set(A, B, ctx); return; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_set_fmpz_mod(A, c, ctx); return; } if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); _fmpz_vec_set(A->coeffs, B->coeffs, Blen - 1); mpoly_copy_monomials(A->exps, B->exps, Blen, N); _fmpz_mod_mpoly_set_length(A, B->length, ctx); } fmpz_mod_add(A->coeffs + Blen - 1, B->coeffs + Blen - 1, c, ctx->ffinfo); if (fmpz_is_zero(A->coeffs + Blen - 1)) _fmpz_mod_mpoly_set_length(A, Blen - 1, ctx); } else { if (A != B) { fmpz_mod_mpoly_fit_length_reset_bits(A, Blen + 1, B->bits, ctx); _fmpz_vec_set(A->coeffs, B->coeffs, Blen); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } else { fmpz_mod_mpoly_fit_length(A, Blen + 1, ctx); } mpoly_monomial_zero(A->exps + N*Blen, N); fmpz_set(A->coeffs + Blen, c); _fmpz_mod_mpoly_set_length(A, Blen + 1, ctx); } } void fmpz_mod_mpoly_add_fmpz( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; if (fmpz_mod_is_canonical(c, ctx->ffinfo)) { fmpz_mod_mpoly_add_fmpz_mod(A, B, c, ctx); return; } fmpz_init(cc); fmpz_mod_set_fmpz(cc, c, ctx->ffinfo); fmpz_mod_mpoly_add_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } void fmpz_mod_mpoly_add_ui( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_ui(cc, c, ctx->ffinfo); fmpz_mod_mpoly_add_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } void fmpz_mod_mpoly_add_si( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_si(cc, c, ctx->ffinfo); fmpz_mod_mpoly_add_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } flint-3.1.3/src/fmpz_mod_mpoly/clear.c000066400000000000000000000012741461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_clear(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->coeffs_alloc; i++) fmpz_clear(A->coeffs + i); if (A->coeffs_alloc > 0) flint_free(A->coeffs); if (A->exps_alloc > 0) flint_free(A->exps); } flint-3.1.3/src/fmpz_mod_mpoly/cmp.c000066400000000000000000000021731461254215100174030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_cmp( const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int cmp; slong i; slong length = A->length; fmpz * Acoeffs = A->coeffs; fmpz * Bcoeffs = B->coeffs; if (A->length != B->length) return A->length < B->length ? -1 : 1; if (length <= 0) return 0; cmp = mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, length, ctx->minfo); if (cmp != 0) return cmp; for (i = 0; i < length; i++) { cmp = fmpz_cmp(Acoeffs + i, Bcoeffs + i); if (cmp != 0) return cmp < 0 ? -1 : 1; } return 0; } flint-3.1.3/src/fmpz_mod_mpoly/combine_like_terms.c000066400000000000000000000030321461254215100224510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* assuming that the exponents are valid and sorted, put the polynomial in canonical form i.e. 2*x^e + 3*x^e -> 5x^e 2*x^e - 2*x^e -> 0 */ void fmpz_mod_mpoly_combine_like_terms( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong in, out, N = mpoly_words_per_exp(A->bits, ctx->minfo); out = -WORD(1); for (in = 0; in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= 0 && mpoly_monomial_equal(A->exps + N*out, A->exps + N*in, N)) { fmpz_mod_add(A->coeffs + out, A->coeffs + out, A->coeffs + in, ctx->ffinfo); } else { if (out < 0 || !fmpz_is_zero(A->coeffs + out)) out++; if (out != in) { mpoly_monomial_set(A->exps + N*out, A->exps + N*in, N); fmpz_swap(A->coeffs + out, A->coeffs + in); } } } if (out < 0 || !fmpz_is_zero(A->coeffs + out)) out++; A->length = out; } flint-3.1.3/src/fmpz_mod_mpoly/compose_fmpz_mod_mpoly.c000066400000000000000000000036211461254215100234030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* evaluate B(xbar) at xbar = C */ int fmpz_mod_mpoly_compose_fmpz_mod_mpoly( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz_mod_mpoly_struct * const * C, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC) { slong i; fmpz_mat_t M; FLINT_ASSERT(A != B); if (B->length == 0) { fmpz_mod_mpoly_zero(A, ctxAC); return 1; } fmpz_mat_init(M, ctxAC->minfo->nfields + 1, ctxB->minfo->nfields); fmpz_mat_zero(M); for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) goto matrix_no_good; if (C[i]->length < 1) { mpoly_compose_mat_fill_column(M, NULL, 0, i, ctxB->minfo, ctxAC->minfo); } else { if (!fmpz_is_zero(C[i]->coeffs + 0)) goto matrix_no_good; mpoly_compose_mat_fill_column(M, C[i]->exps, C[i]->bits, i, ctxB->minfo, ctxAC->minfo); } } _fmpz_mod_mpoly_compose_mat(A, B, M, ctxB, ctxAC); fmpz_mat_clear(M); return 1; matrix_no_good: fmpz_mat_clear(M); /* for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) { return nmod_mpoly_compose_nmod_mpoly_horner(A, B, C, ctxB, ctxAC); } } */ return fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket(A, B, C, ctxB, ctxAC); } flint-3.1.3/src/fmpz_mod_mpoly/compose_fmpz_mod_mpoly_geobucket.c000066400000000000000000000036711461254215100254400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* evaluate B(xbar) at xbar = C */ int fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz_mod_mpoly_struct * const * C, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC) { int success = 1; slong i, j; slong Blen = B->length; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fmpz_mod_mpoly_t U, V, W; fmpz_mod_mpoly_geobucket_t T; fmpz * e; fmpz_mod_mpoly_init(U, ctxAC); fmpz_mod_mpoly_init(V, ctxAC); fmpz_mod_mpoly_init(W, ctxAC); fmpz_mod_mpoly_geobucket_init(T, ctxAC); e = _fmpz_vec_init(ctxB->minfo->nvars); for (i = 0; success && i < Blen; i++) { fmpz_mod_mpoly_set_fmpz(U, Bcoeff + i, ctxAC); mpoly_get_monomial_ffmpz(e, Bexp + BN*i, Bbits, ctxB->minfo); for (j = 0; j < ctxB->minfo->nvars; j++) { success = success && fmpz_mod_mpoly_pow_fmpz(V, C[j], e + j, ctxAC); fmpz_mod_mpoly_mul(W, U, V, ctxAC); fmpz_mod_mpoly_swap(U, W, ctxAC); } fmpz_mod_mpoly_geobucket_add(T, U, ctxAC); } if (success) fmpz_mod_mpoly_geobucket_empty(A, T, ctxAC); fmpz_mod_mpoly_clear(U, ctxAC); fmpz_mod_mpoly_clear(V, ctxAC); fmpz_mod_mpoly_clear(W, ctxAC); fmpz_mod_mpoly_geobucket_clear(T, ctxAC); _fmpz_vec_clear(e, ctxB->minfo->nvars); return success; } flint-3.1.3/src/fmpz_mod_mpoly/compose_mat.c000066400000000000000000000042561461254215100211360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* essentially exps(A) = M*exps(B) */ void _fmpz_mod_mpoly_compose_mat( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mat_t M, const fmpz_mod_mpoly_ctx_t ctxB, const fmpz_mod_mpoly_ctx_t ctxAC) { slong i; fmpz * u, * v; flint_bitcnt_t vbits; slong Blen = B->length; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); const ulong * Bexp = B->exps; const fmpz * Bcoeffs = B->coeffs; slong AN; FLINT_ASSERT(A != B); FLINT_ASSERT(fmpz_mat_nrows(M) == ctxAC->minfo->nfields + 1); FLINT_ASSERT(fmpz_mat_ncols(M) == ctxB->minfo->nfields); u = _fmpz_vec_init(ctxB->minfo->nfields); v = _fmpz_vec_init(ctxAC->minfo->nfields + 1); fmpz_mod_mpoly_fit_length_reset_bits(A, Blen, MPOLY_MIN_BITS, ctxAC); A->length = 0; for (i = 0; i < Blen; i++) { mpoly_unpack_vec_fmpz(u, Bexp + BN*i, Bbits, ctxB->minfo->nfields, 1); fmpz_mat_mul_fmpz_vec(v, M, u, fmpz_mat_ncols(M)); if (!fmpz_is_zero(v + ctxAC->minfo->nfields)) continue; vbits = _fmpz_vec_max_bits(v, ctxAC->minfo->nfields); FLINT_ASSERT(vbits >= 0); vbits = mpoly_fix_bits(vbits + 1, ctxAC->minfo); fmpz_mod_mpoly_fit_length_fit_bits(A, A->length + 1, vbits, ctxAC); fmpz_set(A->coeffs + A->length, Bcoeffs + i); AN = mpoly_words_per_exp(A->bits, ctxAC->minfo); mpoly_pack_vec_fmpz(A->exps + AN*A->length, v, A->bits, ctxAC->minfo->nfields, 1); A->length++; } _fmpz_vec_clear(u, ctxB->minfo->nfields); _fmpz_vec_clear(v, ctxAC->minfo->nfields + 1); fmpz_mod_mpoly_sort_terms(A, ctxAC); fmpz_mod_mpoly_combine_like_terms(A, ctxAC); return; } flint-3.1.3/src/fmpz_mod_mpoly/content_vars.c000066400000000000000000000130211461254215100213230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" /* content wrt gen(0), ..., gen(num_vars-1) successful answer will be returned with g->bits == A->bits */ int fmpz_mod_mpolyl_content( fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_t A, slong num_vars, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j, off, shift; ulong old_shift, new_shift; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; slong Alen = A->length; fmpz_mod_mpoly_struct * v; slong vlen, valloc; FLINT_ASSERT(g != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); i = 0; old_shift = (Aexps + N*i)[off] >> shift; valloc = 4; v = FLINT_ARRAY_ALLOC(valloc, fmpz_mod_mpoly_struct); vlen = 0; v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + i; v[vlen].exps = Aexps + N*i; v[vlen].coeffs_alloc = 0; v[vlen].exps_alloc = 0; v[vlen].length = i; v[vlen].coeffs_alloc = v[vlen].length; v[vlen].exps_alloc = N*v[vlen].length; vlen++; for (i = 1; i < Alen; old_shift = new_shift, i++) { new_shift = (Aexps + N*i)[off] >> shift; if (new_shift != old_shift) goto new_one; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto new_one; continue; new_one: v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].coeffs_alloc = v[vlen - 1].length; v[vlen - 1].exps_alloc = N*v[vlen - 1].length; if (vlen + 1 > valloc) { valloc += 2 + valloc/2; v = FLINT_ARRAY_REALLOC(v, valloc, fmpz_mod_mpoly_struct); } v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + i; v[vlen].exps = Aexps + N*i; v[vlen].coeffs_alloc = 0; v[vlen].exps_alloc = 0; v[vlen].length = i; vlen++; } v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].coeffs_alloc = v[vlen - 1].length; v[vlen - 1].exps_alloc = N*v[vlen - 1].length; success = _fmpz_mod_mpoly_vec_content_mpoly(g, v, vlen, ctx); if (success) { /* remove gen(0) ... gen(num_vars-1) from the answer */ ulong * gexps; ulong mask; fmpz_mod_mpoly_repack_bits_inplace(g, A->bits, ctx); gexps = g->exps; mask = (shift > 0) ? ((-UWORD(1)) >> (FLINT_BITS - shift)) : 0; for (i = 0; i < g->length; i++) { (gexps + N*i)[off] &= mask; for (j = off + 1; j < N; j++) (gexps + N*i)[j] = 0; } } flint_free(v); return success; } int fmpz_mod_mpoly_content_vars( fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_t A, slong * vars, slong num_vars, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j, k; fmpz_mod_mpolyv_t v, w; fmpz_mod_mpoly_univar_t u; if (num_vars < 1) { fmpz_mod_mpoly_set(g, A, ctx); return 1; } for (i = 0; i < num_vars; i++) { if (vars[i] >= (ulong) ctx->minfo->nvars) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_content_vars: variable out of range"); } if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(g, ctx); return 1; } if (A->bits <= FLINT_BITS && ctx->minfo->ord == ORD_LEX && num_vars < ctx->minfo->nvars) { for (i = 0; i < num_vars; i++) if (vars[i] != i) goto do_general; if (g == A) { fmpz_mod_mpoly_t t; fmpz_mod_mpoly_init(t, ctx); success = fmpz_mod_mpolyl_content(t, A, num_vars, ctx); fmpz_mod_mpoly_swap(g, t, ctx); fmpz_mod_mpoly_clear(t, ctx); return success; } return fmpz_mod_mpolyl_content(g, A, num_vars, ctx); } do_general: fmpz_mod_mpolyv_init(v, ctx); fmpz_mod_mpolyv_init(w, ctx); fmpz_mod_mpoly_univar_init(u, ctx); i = 0; fmpz_mod_mpoly_to_univar(u, A, vars[i], ctx); fmpz_mod_mpolyv_fit_length(v, u->length, ctx); v->length = u->length; for (j = 0; j < u->length; j++) fmpz_mod_mpoly_swap(v->coeffs + j, u->coeffs + j, ctx); for (i = 1; i < num_vars; i++) { w->length = 0; for (k = 0; k < v->length; k++) { fmpz_mod_mpoly_to_univar(u, v->coeffs + k, vars[i], ctx); fmpz_mod_mpolyv_fit_length(w, w->length + u->length, ctx); for (j = 0; j < u->length; j++) { fmpz_mod_mpoly_swap(w->coeffs + w->length, u->coeffs + j, ctx); w->length++; } } fmpz_mod_mpolyv_swap(v, w, ctx); } fmpz_mod_mpoly_univar_clear(u, ctx); fmpz_mod_mpolyv_clear(w, ctx); success = _fmpz_mod_mpoly_vec_content_mpoly(g, v->coeffs, v->length, ctx); fmpz_mod_mpolyv_clear(v, ctx); return success; } flint-3.1.3/src/fmpz_mod_mpoly/ctx_clear.c000066400000000000000000000011041461254215100205610ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_ctx_clear(fmpz_mod_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); fmpz_mod_ctx_clear(ctx->ffinfo); } flint-3.1.3/src/fmpz_mod_mpoly/ctx_init.c000066400000000000000000000012631461254215100204440ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_ctx_init(fmpz_mod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fmpz_t modulus) { mpoly_ctx_init(ctx->minfo, nvars, ord); fmpz_mod_ctx_init(ctx->ffinfo, modulus); } flint-3.1.3/src/fmpz_mod_mpoly/ctx_init_rand.c000066400000000000000000000023311461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_ctx_init_rand(fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, const fmpz_t modulus) { mpoly_ctx_init_rand(ctx->minfo, state, max_nvars); fmpz_mod_ctx_init(ctx->ffinfo, modulus); } void fmpz_mod_mpoly_ctx_init_rand_bits(fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, flint_bitcnt_t max_bits) { mpoly_ctx_init_rand(ctx->minfo, state, max_nvars); fmpz_mod_ctx_init_rand_bits(ctx->ffinfo, state, max_bits); } void fmpz_mod_mpoly_ctx_init_rand_bits_prime(fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, flint_bitcnt_t max_bits) { mpoly_ctx_init_rand(ctx->minfo, state, max_nvars); fmpz_mod_ctx_init_rand_bits_prime(ctx->ffinfo, state, max_bits); } flint-3.1.3/src/fmpz_mod_mpoly/deflate.c000066400000000000000000000031561461254215100202320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_deflate( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mod_mpoly_ctx_t ctx) { slong bits = B->bits; slong NA = mpoly_words_per_exp(bits, ctx->minfo); if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_zero(A, ctx); return; } if (A == B) { slong new_alloc = NA*A->length; ulong * texps = flint_malloc(new_alloc*sizeof(ulong)); mpoly_monomials_deflate(texps, bits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = bits; A->exps_alloc = new_alloc; } else { fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, bits, ctx); _fmpz_vec_set(A->coeffs, B->coeffs, B->length); mpoly_monomials_deflate(A->exps, bits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _fmpz_mod_mpoly_set_length(A, B->length, ctx); } if (ctx->minfo->ord != ORD_LEX) fmpz_mod_mpoly_sort_terms(A, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/deflation.c000066400000000000000000000013251461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_monomials_deflation(shift, stride, A->exps, A->bits, A->length, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/degrees.c000066400000000000000000000052361461254215100202450ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_degrees_fit_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_degrees_fit_si(A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mod_mpoly_degrees_fmpz(fmpz ** degs, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_degrees_pfmpz(degs, A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mod_mpoly_degrees_si(slong * degs, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_degrees_si(degs, A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mod_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } slong fmpz_mod_mpoly_degree_si(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } int fmpz_mod_mpoly_total_degree_fits_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return mpoly_total_degree_fits_si(A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mod_mpoly_total_degree_fmpz(fmpz_t td, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_total_degree_fmpz(td, A->exps, A->length, A->bits, ctx->minfo); } slong fmpz_mod_mpoly_total_degree_si(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return mpoly_total_degree_si(A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mod_mpoly_used_vars(int * used, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < ctx->minfo->nvars; i++) used[i] = 0; mpoly_used_vars_or(used, A->exps, A->length, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/derivative.c000066400000000000000000000062211461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static slong _fmpz_mod_mpoly_derivative( fmpz * coeff1, ulong * exp1, const fmpz * coeff2, const ulong * exp2, slong len2, flint_bitcnt_t bits, slong N, slong offset, slong shift, ulong * oneexp, const fmpz_mod_ctx_t fctx) { slong i, len1; /* x^c -> c*x^(c-1) */ len1 = 0; for (i = 0; i < len2; i++) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong c = (exp2[N*i + offset] >> shift) & mask; if (c == 0) continue; fmpz_mod_mul_ui(coeff1 + len1, coeff2 + i, c, fctx); if (fmpz_is_zero(coeff1 + len1)) continue; mpoly_monomial_sub(exp1 + N*len1, exp2 + N*i, oneexp, N); len1++; } return len1; } static slong _fmpz_mod_mpoly_derivative_mp( fmpz * coeff1, ulong * exp1, const fmpz * coeff2, const ulong * exp2, slong len2, flint_bitcnt_t bits, slong N, slong offset, ulong * oneexp, const fmpz_mod_ctx_t fctx) { slong i, len1; fmpz_t c; fmpz_init(c); /* x^c -> c*x^(c-1) */ len1 = 0; for (i = 0; i < len2; i++) { fmpz_set_ui_array(c, exp2 + N*i + offset, bits/FLINT_BITS); if (fmpz_is_zero(c)) continue; fmpz_mod_mul_fmpz(coeff1 + len1, coeff2 + i, c, fctx); if (fmpz_is_zero(coeff1 + len1)) continue; mpoly_monomial_sub_mp(exp1 + N*len1, exp2 + N*i, oneexp, N); len1++; } fmpz_clear(c); return len1; } void fmpz_mod_mpoly_derivative( fmpz_mod_mpoly_t poly1, const fmpz_mod_mpoly_t poly2, slong var, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = poly2->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong offset, shift; ulong * oneexp; slong len1; TMP_INIT; TMP_START; fmpz_mod_mpoly_fit_length_reset_bits(poly1, poly2->length, bits, ctx); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (bits <= FLINT_BITS) { mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, bits, ctx->minfo); len1 = _fmpz_mod_mpoly_derivative(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, shift, oneexp, ctx->ffinfo); } else { offset = mpoly_gen_monomial_offset_mp(oneexp, var, bits, ctx->minfo); len1 = _fmpz_mod_mpoly_derivative_mp(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, oneexp, ctx->ffinfo); } _fmpz_mod_mpoly_set_length(poly1, len1, ctx); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/discriminant.c000066400000000000000000000015051461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_discriminant(fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { int success; fmpz_mod_mpoly_univar_t Ax; fmpz_mod_mpoly_univar_init(Ax, ctx); fmpz_mod_mpoly_to_univar(Ax, A, var, ctx); success = fmpz_mod_mpoly_univar_discriminant(R, Ax, ctx); fmpz_mod_mpoly_univar_clear(Ax, ctx); return success; } flint-3.1.3/src/fmpz_mod_mpoly/div.c000066400000000000000000000011501461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_div(fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_div_monagan_pearce(Q, A, B, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/div_monagan_pearce.c000066400000000000000000000260711461254215100224300ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static int _fmpz_mod_mpoly_div_monagan_pearce( fmpz_mod_mpoly_t Q, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fmpz_mod_ctx_t fctx) { int success; slong i, j, q_len, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; int lt_divides; fmpz_t lc_inv, acc; TMP_INIT; TMP_START; fmpz_init(lc_inv); fmpz_init(acc); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; q_len = 0; /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coefficient info */ fmpz_mod_inv(lc_inv, Bcoeffs + 0, fctx); while (heap_len > 1) { _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, q_len + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides(Qexps + q_len*N, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; lt_divides = mpoly_monomial_divides_mp(Qexps + q_len*N, exp, Bexps, N, bits); } fmpz_zero(acc); if (!lt_divides) { /* optimization: coeff arithmetic not needed */ if (mpoly_monomial_gt(Bexps + 0, exp, N, cmpmask)) { /* optimization: no more quotient terms possible */ goto done; } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else { do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { fmpz_add(acc, acc, Acoeffs + x->j); } else { hind[x->i] |= WORD(1); fmpz_submul(acc, Bcoeffs + x->i, Qcoeffs + x->j); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } fmpz_mod_set_fmpz(acc, acc, fctx); while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ((i + 1 < Blen) && (hind[i + 1] == 2*j + 1)) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if (((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1))) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term */ if (fmpz_is_zero(acc)) continue; if (!lt_divides) continue; fmpz_mod_mul(Qcoeffs + q_len, acc, lc_inv, fctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; q_len++; } done: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = q_len; success = 1; cleanup: fmpz_clear(lc_inv); fmpz_clear(acc); TMP_END; return success; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; success = 0; goto cleanup; } void fmpz_mod_mpoly_div_monagan_pearce( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t Qbits; ulong * Aexps = A->exps, * Bexps = B->exps; ulong * cmpmask; int freeAexps = 0, freeBexps = 0; fmpz_mod_mpoly_t TQ; fmpz_mod_mpoly_struct * q; if (fmpz_mod_mpoly_is_zero(B, ctx)) flint_throw(FLINT_DIVZERO, "fmpz_mod_mpoly_div_monagan_pearce: divide by zero"); if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(Q, ctx); return; } fmpz_mod_mpoly_init(TQ, ctx); Qbits = FLINT_MAX(A->bits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = FLINT_ARRAY_ALLOC(N, ulong); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (Qbits > A->bits) { freeAexps = 1; Aexps = FLINT_ARRAY_ALLOC(N*A->length, ulong); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits > B->bits) { freeBexps = 1; Bexps = FLINT_ARRAY_ALLOC(N*B->length, ulong); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(Aexps, Bexps, N, cmpmask)) { fmpz_mod_mpoly_zero(Q, ctx); goto cleanup; } /* take care of aliasing */ if (Q == A || Q == B) q = TQ; else q = Q; /* do division with remainder */ while (1) { fmpz_mod_mpoly_fit_length_reset_bits(q, A->length/B->length + 1, Qbits, ctx); if (_fmpz_mod_mpoly_div_monagan_pearce(q, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->ffinfo)) { break; } Qbits = mpoly_fix_bits(Qbits + 1, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = FLINT_ARRAY_REALLOC(cmpmask, N, ulong); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = FLINT_ARRAY_ALLOC(N*A->length, ulong); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; if (freeBexps) flint_free(Bexps); Bexps = FLINT_ARRAY_ALLOC(N*B->length, ulong); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); freeBexps = 1; } /* deal with aliasing */ if (Q == A || Q == B) fmpz_mod_mpoly_swap(Q, TQ, ctx); cleanup: fmpz_mod_mpoly_clear(TQ, ctx); if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); flint_free(cmpmask); } flint-3.1.3/src/fmpz_mod_mpoly/divides.c000066400000000000000000000065121461254215100202540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static int _fmpz_mod_mpoly_divides_try_dense( const fmpz * maxAfields, const fmpz * maxBfields, slong Alen, slong Blen, const mpoly_ctx_t mctx) { const int max_bit_size = FLINT_MIN(FLINT_BITS/3 + 16, FLINT_BITS - 4); slong i; ulong * Adegs; ulong total_dense_size; TMP_INIT; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); if (mctx->nvars < 1 || mctx->nvars > FLINT_BITS) return 0; TMP_START; Adegs = TMP_ARRAY_ALLOC(mctx->nvars, ulong); mpoly_get_monomial_ui_unpacked_ffmpz(Adegs, maxAfields, mctx); total_dense_size = 1; for (i = 0; i < mctx->nvars; i++) { if (n_mul_checked(&total_dense_size, total_dense_size, Adegs[i] + 1)) { TMP_END; return 0; } } TMP_END; return total_dense_size < (UWORD(1) << max_bit_size) && total_dense_size/16 < Alen; } int fmpz_mod_mpoly_divides( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i; fmpz * maxAfields, * maxBfields; TMP_INIT; if (fmpz_mod_mpoly_is_zero(B, ctx)) { if (!fmpz_mod_mpoly_is_zero(A, ctx) && !fmpz_is_one(fmpz_mod_mpoly_ctx_modulus(ctx))) { flint_throw(FLINT_DIVZERO, "fmpz_mod_mpoly_divides: divide by zero"); } fmpz_mod_mpoly_zero(Q, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(Q, ctx); return 1; } TMP_START; maxAfields = TMP_ARRAY_ALLOC(2*ctx->minfo->nfields, fmpz); maxBfields = maxAfields + ctx->minfo->nfields; for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_init(maxAfields + i); mpoly_max_fields_fmpz(maxAfields, A->exps, A->length, A->bits, ctx->minfo); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); /* quick degree check */ for (i = 0; i < ctx->minfo->nfields; i++) { if (fmpz_cmp(maxAfields + i, maxBfields + i) < 0) { fmpz_mod_mpoly_zero(Q, ctx); success = 0; goto cleanup; } } if (A->length < 30 || A->bits > FLINT_BITS || B->bits > FLINT_BITS) { goto do_heap; } if (_fmpz_mod_mpoly_divides_try_dense(maxAfields, maxBfields, A->length, B->length, ctx->minfo)) { success = _fmpz_mod_mpoly_divides_dense_maxfields(Q, A, maxAfields, B, maxBfields, ctx); if (success >= 0) goto cleanup; } do_heap: success = _fmpz_mod_mpoly_divides_monagan_pearce_maxfields(Q, A, maxAfields, B, maxBfields, ctx); cleanup: for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_clear(maxAfields + i); TMP_END; return success; } flint-3.1.3/src/fmpz_mod_mpoly/divides_dense.c000066400000000000000000000206521461254215100214330ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "fmpz_mod_poly.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* Convert D to A if the degrees of A are <= expected_deg If not, return 0 and set A to 0. */ static int _from_dense( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, slong * Adeg_bounds, slong * expect_deg, fmpz_mod_poly_t D, const fmpz_mod_mpoly_ctx_t ctx) { int ret; slong off, j, k, N; flint_bitcnt_t bits; slong nvars = ctx->minfo->nvars; slong Alen; ulong topmask, outrange; ulong * exps, * pcurexp, * pexps, * rangemask; TMP_INIT; FLINT_ASSERT(nvars <= FLINT_BITS); TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); /* find bits needed for the result */ off = 1; for (j = 0; j < nvars; j++) { FLINT_ASSERT(expect_deg[j] >= 0); off *= Adeg_bounds[j]; exps[j] = expect_deg[j]; } bits = mpoly_exp_bits_required_ui(exps, ctx->minfo); bits = FLINT_MAX(Abits, bits); bits = mpoly_fix_bits(bits, ctx->minfo); N = mpoly_words_per_exp(bits, ctx->minfo); /* we are going to push back terms manually */ fmpz_mod_mpoly_fit_length_reset_bits(A, 0, bits, ctx); Alen = 0; /* find exponent vector for all variables */ pexps = (ulong *) TMP_ALLOC(N*nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) mpoly_gen_monomial_sp(pexps + k*N, k, bits, ctx->minfo); /* get most significant exponent in exps and its vector in ptempexp */ off--; pcurexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); rangemask = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); outrange = 0; mpoly_monomial_zero(pcurexp, N); k = off; for (j = nvars - 1; j >= 0; j--) { exps[j] = k % Adeg_bounds[j]; rangemask[j] = UWORD(1) << j; outrange ^= (outrange ^ FLINT_SIGN_EXT(expect_deg[j] - exps[j])) & rangemask[j]; k = k / Adeg_bounds[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } /* scan down through the exponents */ topmask = 0; for (; off >= 0; off--) { if (off < D->length && !fmpz_is_zero(D->coeffs + off)) { if (outrange) { _fmpz_mod_mpoly_set_length(A, 0, ctx); ret = 0; goto cleanup; } _fmpz_mod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, Alen + 1); fmpz_swap(A->coeffs + Alen, D->coeffs + off); mpoly_monomial_set(A->exps + N*Alen, pcurexp, N); topmask |= (A->exps + N*Alen)[N - 1]; Alen++; } j = nvars - 1; do { --exps[j]; outrange ^= (outrange ^ FLINT_SIGN_EXT(expect_deg[j] - exps[j])) & rangemask[j]; if (FLINT_SIGN_EXT(exps[j]) != 0) { FLINT_ASSERT(off == 0 || j > 0); FLINT_ASSERT(exps[j] == -UWORD(1)); exps[j] = Adeg_bounds[j] - 1; outrange ^= (outrange ^ FLINT_SIGN_EXT(expect_deg[j] - exps[j])) & rangemask[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } else { mpoly_monomial_sub_mp(pcurexp, pcurexp, pexps + N*j, N); break; } } while (--j >= 0); } _fmpz_mod_mpoly_set_length(A, Alen, ctx); /* sort the exponents if needed */ if (ctx->minfo->ord != ORD_LEX) { flint_bitcnt_t pos; mpoly_get_cmpmask(pcurexp, N, bits, ctx->minfo); pos = FLINT_BIT_COUNT(topmask); if (N == 1) _fmpz_mod_mpoly_radix_sort1(A->coeffs, A->exps, 0, A->length, pos, pcurexp[0], topmask); else _fmpz_mod_mpoly_radix_sort(A->coeffs, A->exps, 0, A->length, (N - 1)*FLINT_BITS + pos, N, pcurexp); } ret = 1; cleanup: TMP_END; return ret; } int _fmpz_mod_mpoly_divides_dense_maxfields( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, fmpz * maxAfields, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i; slong nvars = ctx->minfo->nvars; fmpz_mod_poly_t Ad, Bd, Qd, Rd; slong * Abounds, * Bbounds, * Qbounds, * Edegs; slong prod_deg; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(0 < ctx->minfo->nvars); FLINT_ASSERT(ctx->minfo->nvars <= FLINT_BITS); TMP_START; /* for each variable v we need to pack to degree deg_v(A) except for the outermost variable */ Abounds = TMP_ARRAY_ALLOC(4*nvars, slong); Bbounds = Abounds + nvars; Qbounds = Bbounds + nvars; Edegs = Qbounds + nvars; mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Abounds, maxAfields, ctx->minfo); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Bbounds, maxBfields, ctx->minfo); prod_deg = 1; for (i = 0; i < ctx->minfo->nvars; i++) { /* if divides, expected degrees */ Edegs[i] = Abounds[i] - Bbounds[i]; if (Abounds[i] < Bbounds[i]) { success = 0; fmpz_mod_mpoly_zero(Q, ctx); goto cleanup; } if (i != 0) { /* variable of index i is not the outermost */ Qbounds[i] = Abounds[i] + 1; Bbounds[i] = Abounds[i] + 1; } else { /* variable of index i is the outermost */ Qbounds[i] = Abounds[i] - Bbounds[i] + 1; Bbounds[i] = Bbounds[i] + 1; } if (z_add_checked(&Abounds[i], Abounds[i], 1) || z_mul_checked(&prod_deg, prod_deg, Abounds[i])) { success = -1; fmpz_mod_mpoly_zero(Q, ctx); goto cleanup; } } _fmpz_mod_mpoly_init_dense_mock(Ad, A, Abounds, ctx); _fmpz_mod_mpoly_init_dense_mock(Bd, B, Bbounds, ctx); fmpz_mod_poly_init(Qd, ctx->ffinfo); fmpz_mod_poly_init(Rd, ctx->ffinfo); fmpz_mod_poly_divrem(Qd, Rd, Ad, Bd, ctx->ffinfo); success = fmpz_mod_poly_is_zero(Rd, ctx->ffinfo) && _from_dense(Q, A->bits, Qbounds, Edegs, Qd, ctx); fmpz_mod_poly_clear(Qd, ctx->ffinfo); fmpz_mod_poly_clear(Rd, ctx->ffinfo); _fmpz_mod_mpoly_clear_dense_mock(Ad); _fmpz_mod_mpoly_clear_dense_mock(Bd); cleanup: TMP_END; return success; } /* return -1 : function failed 0 : B does not divide A 1 : B divides A and quotient is in Q */ int fmpz_mod_mpoly_divides_dense( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i; fmpz * maxAfields, * maxBfields; TMP_INIT; if (fmpz_mod_mpoly_is_zero(B, ctx)) { if (!fmpz_mod_mpoly_is_zero(A, ctx) && !fmpz_is_one(fmpz_mod_mpoly_ctx_modulus(ctx))) { flint_throw(FLINT_DIVZERO, "fmpz_mod_mpoly_divides_dense: divide by zero"); } fmpz_mod_mpoly_zero(Q, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(Q, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS || ctx->minfo->nvars > FLINT_BITS || ctx->minfo->nvars < 1) { return -1; } TMP_START; maxAfields = TMP_ARRAY_ALLOC(2*ctx->minfo->nfields, fmpz); maxBfields = maxAfields + ctx->minfo->nfields; for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_init(maxAfields + i); mpoly_max_fields_fmpz(maxAfields, A->exps, A->length, A->bits, ctx->minfo); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); success = _fmpz_mod_mpoly_divides_dense_maxfields(Q, A, maxAfields, B, maxBfields, ctx); for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_clear(maxAfields + i); TMP_END; return success; } flint-3.1.3/src/fmpz_mod_mpoly/divides_monagan_pearce.c000066400000000000000000000506631461254215100233010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static int _fmpz_mod_mpoly_divides_monagan_pearce1( fmpz_mod_mpoly_t Q, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, slong bits, ulong cmpmask, const fmpz_mod_ctx_t fctx) { int lt_divides; slong i, j, Qlen, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; slong * hind; ulong mask, exp, maxexp = Aexps[Alen - 1]; mpz_t t, acc, modulus; ulong acc_sm[3]; fmpz_t lc_minus_inv; TMP_INIT; mpz_init(t); mpz_init(acc); mpz_init(modulus); fmpz_get_mpz(modulus, fmpz_mod_ctx_modulus(fctx)); fmpz_init(lc_minus_inv); fmpz_mod_inv(lc_minus_inv, Bcoeffs + 0, fctx); fmpz_mod_neg(lc_minus_inv, lc_minus_inv, fctx); TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); Qlen = 0; /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexps[0], x); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_exact_division; _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Bexps[0], mask); mpz_set_ui(acc, 0); acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { fmpz Aj = Acoeffs[x->j]; if (COEFF_IS_MPZ(Aj)) mpz_sub(acc, acc, COEFF_TO_PTR(Aj)); else flint_mpz_sub_ui(acc, acc, Aj); } else { fmpz Bi = Bcoeffs[x->i]; fmpz Qj = Qcoeffs[x->j]; hind[x->i] |= WORD(1); if (COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { mpz_addmul(acc, COEFF_TO_PTR(Bi), COEFF_TO_PTR(Qj)); } else if (COEFF_IS_MPZ(Bi) && !COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Bi), Qj); } else if (!COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Qj), Bi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Bi, Qj); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], 0, pp1, pp0); } } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); flint_mpz_add_uiuiui(acc, acc, acc_sm[2], acc_sm[1], acc_sm[0]); if (mpz_sgn(acc) < 0) mpz_add(acc, acc, modulus); mpz_tdiv_qr(t, _fmpz_promote(Qcoeffs + Qlen), acc, modulus); _fmpz_demote_val(Qcoeffs + Qlen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexps[x->j], x, &next_loc, &heap_len, cmpmask); } } else { /* should we go right? */ if ((i + 1 < Blen) && (hind[i + 1] == 2*j + 1)) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if (((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1))) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } } } fmpz_mod_mul(Qcoeffs + Qlen, Qcoeffs + Qlen, lc_minus_inv, fctx); if (fmpz_is_zero(Qcoeffs + Qlen)) continue; if (!lt_divides || (exp^cmpmask) < (maxexp^cmpmask)) goto not_exact_division; /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } s = 1; Qlen++; } cleanup: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; TMP_END; fmpz_clear(lc_minus_inv); mpz_clear(t); mpz_clear(acc); mpz_clear(modulus); return Qlen > 0; not_exact_division: Qlen = 0; goto cleanup; } int _fmpz_mod_mpoly_divides_monagan_pearce( fmpz_mod_mpoly_t Q, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fmpz_mod_ctx_t fctx) { int lt_divides; slong i, j, Qlen, s; slong next_loc, heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; ulong mask; mpz_t t, acc, modulus; ulong acc_sm[3]; fmpz_t lc_minus_inv; TMP_INIT; if (N == 1) return _fmpz_mod_mpoly_divides_monagan_pearce1(Q, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, Blen, bits, cmpmask[0], fctx); mpz_init(t); mpz_init(acc); mpz_init(modulus); fmpz_get_mpz(modulus, fmpz_mod_ctx_modulus(fctx)); fmpz_init(lc_minus_inv); fmpz_mod_inv(lc_minus_inv, Bcoeffs + 0, fctx); fmpz_mod_neg(lc_minus_inv, lc_minus_inv, fctx); TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; Qlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); while (heap_len > 1) { _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, Qlen + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; lt_divides = mpoly_monomial_divides(Qexps + Qlen*N, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto not_exact_division; lt_divides = mpoly_monomial_divides_mp(Qexps + Qlen*N, exp, Bexps, N, bits); } mpz_set_ui(acc, 0); acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { fmpz Aj = Acoeffs[x->j]; if (COEFF_IS_MPZ(Aj)) mpz_sub(acc, acc, COEFF_TO_PTR(Aj)); else flint_mpz_sub_ui(acc, acc, Aj); } else { fmpz Bi = Bcoeffs[x->i]; fmpz Qj = Qcoeffs[x->j]; hind[x->i] |= WORD(1); if (COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { mpz_addmul(acc, COEFF_TO_PTR(Bi), COEFF_TO_PTR(Qj)); } else if (COEFF_IS_MPZ(Bi) && !COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Bi), Qj); } else if (!COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Qj), Bi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Bi, Qj); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], 0, pp1, pp0); } } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); flint_mpz_add_uiuiui(acc, acc, acc_sm[2], acc_sm[1], acc_sm[0]); if (mpz_sgn(acc) < 0) mpz_add(acc, acc, modulus); mpz_tdiv_qr(t, _fmpz_promote(Qcoeffs + Qlen), acc, modulus); _fmpz_demote_val(Qcoeffs + Qlen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go up */ if ((i + 1 < Blen) && (hind[i + 1] == 2*j + 1)) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if (((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1))) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } fmpz_mod_mul(Qcoeffs + Qlen, Qcoeffs + Qlen, lc_minus_inv, fctx); if (fmpz_is_zero(Qcoeffs + Qlen)) continue; if (!lt_divides || mpoly_monomial_gt(Aexps + N*(Alen - 1), exp, N, cmpmask)) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; Qlen++; } cleanup: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; TMP_END; fmpz_clear(lc_minus_inv); mpz_clear(t); mpz_clear(acc); mpz_clear(modulus); return Qlen > 0; not_exact_division: Qlen = 0; goto cleanup; } int _fmpz_mod_mpoly_divides_monagan_pearce_maxfields( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, fmpz * maxAfields, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t Qbits; ulong * cmpmask; ulong * Aexps = A->exps, * Bexps = B->exps, * expq; int divides, freeAexps = 0, freeBexps = 0; TMP_INIT; for (i = 0; i < ctx->minfo->nfields; i++) { /* cannot be exact division if any max field from A is less than corresponding max field from B */ if (fmpz_cmp(maxAfields + i, maxBfields + i) < 0) { fmpz_mod_mpoly_zero(Q, ctx); return 0; } } Qbits = 1 + _fmpz_vec_max_bits(maxAfields, ctx->minfo->nfields); Qbits = FLINT_MAX(Qbits, A->bits); Qbits = FLINT_MAX(Qbits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); TMP_START; N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = TMP_ARRAY_ALLOC(2*N, ulong); expq = cmpmask + N; /* temp space to check leading monomials divide */ mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* quick check for easy case of inexact division of leading monomials */ if (Qbits == A->bits && Qbits == B->bits && A->exps[N - 1] < B->exps[N - 1]) { fmpz_mod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } /* ensure input exponents packed to same size as output exponents */ if (Qbits != A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); } /* check leading monomial divides exactly */ if (Qbits > FLINT_BITS) divides = mpoly_monomial_divides_mp(expq, Aexps, Bexps, N, Qbits); else divides = mpoly_monomial_divides(expq, Aexps, Bexps, N, mpoly_overflow_mask_sp(Qbits)); if (!divides) { fmpz_mod_mpoly_zero(Q, ctx); goto cleanup; } /* deal with aliasing and divide polynomials */ if (Q == A || Q == B) { fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init3(T, A->length/B->length + 1, Qbits, ctx); divides = _fmpz_mod_mpoly_divides_monagan_pearce(T, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->ffinfo); fmpz_mod_mpoly_swap(T, Q, ctx); fmpz_mod_mpoly_clear(T, ctx); } else { fmpz_mod_mpoly_fit_length_reset_bits(Q, A->length/B->length + 1, Qbits, ctx); divides = _fmpz_mod_mpoly_divides_monagan_pearce(Q, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->ffinfo); } cleanup: if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); TMP_END; return divides; } /* return 1 if quotient is exact */ int fmpz_mod_mpoly_divides_monagan_pearce( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int divides; slong i; fmpz * maxAfields, * maxBfields; TMP_INIT; if (fmpz_mod_mpoly_is_zero(B, ctx)) { if (!fmpz_mod_mpoly_is_zero(A, ctx) && !fmpz_is_one(fmpz_mod_ctx_modulus(ctx->ffinfo))) { flint_throw(FLINT_DIVZERO, "fmpz_mod_mpoly_divides_monagan_pearce: divide by zero"); } fmpz_mod_mpoly_zero(Q, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(Q, ctx); return 1; } TMP_START; maxAfields = TMP_ARRAY_ALLOC(2*ctx->minfo->nfields, fmpz); maxBfields = maxAfields + ctx->minfo->nfields; for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_init(maxAfields + i); mpoly_max_fields_fmpz(maxAfields, A->exps, A->length, A->bits, ctx->minfo); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); divides = _fmpz_mod_mpoly_divides_monagan_pearce_maxfields(Q, A, maxAfields, B, maxBfields, ctx); for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_clear(maxAfields + i); TMP_END; return divides; } flint-3.1.3/src/fmpz_mod_mpoly/divrem.c000066400000000000000000000012041461254215100201040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_divrem( fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_divrem_monagan_pearce(Q, R, A, B, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/divrem_ideal.c000066400000000000000000000012651461254215100212510ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_divrem_ideal( fmpz_mod_mpoly_struct ** Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, fmpz_mod_mpoly_struct * const * B, slong len, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_divrem_ideal_monagan_pearce(Q, R, A, B, len, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/divrem_ideal_monagan_pearce.c000066400000000000000000000314311461254215100242660ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int _fmpz_mod_mpoly_divrem_ideal_monagan_pearce( fmpz_mod_mpoly_struct ** Q, fmpz_mod_mpoly_t R, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, fmpz_mod_mpoly_struct * const * Bs, ulong * const * Bexps, slong Blen, slong N, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx, const ulong * cmpmask) { int overflows, divides, success; slong i, j, p, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_nheap_t ** chains, * chains_ptr; slong ** hinds, * hinds_ptr; mpoly_nheap_t * x; fmpz * r_coeff = R->coeffs; ulong * r_exp = R->exps; slong r_len; ulong * exp, * exps, * texp; ulong ** exp_list; slong exp_next; ulong mask; slong * q_len, * s; fmpz * lc_inv; fmpz_t acc; TMP_INIT; TMP_START; fmpz_init(acc); chains = TMP_ARRAY_ALLOC(Blen, mpoly_nheap_t *); hinds = TMP_ARRAY_ALLOC(Blen, slong *); /* chains[w], hinds[w] will be arrays of length Bs[w]->length; combine the allocations*/ len3 = 0; for (w = 0; w < Blen; w++) len3 += Bs[w]->length; chains_ptr = TMP_ARRAY_ALLOC(len3, mpoly_nheap_t); hinds_ptr = TMP_ARRAY_ALLOC(len3, slong); len3 = 0; for (w = 0; w < Blen; w++) { chains[w] = chains_ptr + len3; hinds[w] = hinds_ptr + len3; len3 += Bs[w]->length; for (i = 0; i < Bs[w]->length; i++) hinds[w][i] = 1; } next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong *)); exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); q_len = (slong *) TMP_ALLOC(Blen*sizeof(slong)); s = (slong *) TMP_ALLOC(Blen*sizeof(slong)); exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; for (w = 0; w < Blen; w++) { q_len[w] = WORD(0); s[w] = Bs[w]->length; } r_len = WORD(0); x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coeff info */ lc_inv = TMP_ARRAY_ALLOC(Blen, fmpz); for (w = 0; w < Blen; w++) { fmpz_init(lc_inv + w); fmpz_mod_inv(lc_inv + w, Bs[w]->coeffs + 0, ctx->ffinfo); } while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); overflows = (bits <= FLINT_BITS) ? mpoly_monomial_overflows(exp, N, mask) : mpoly_monomial_overflows_mp(exp, N, bits); if (overflows) goto exp_overflow; fmpz_zero(acc); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i == -WORD(1)) { fmpz_add(acc, acc, Acoeffs + x->j); } else { hinds[x->p][x->i] |= WORD(1); fmpz_submul(acc, Bs[x->p]->coeffs + x->i, Q[x->p]->coeffs + x->j); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); fmpz_mod_set_fmpz(acc, acc, ctx->ffinfo); while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < Alen) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ((i + 1 < Bs[p]->length) && (hinds[p][i + 1] == 2*j + 1)) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps[x->p] + N*x->i, Q[x->p]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len[p]) { s[p]++; } else if (((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1))) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps[x->p] + N*x->i, Q[x->p]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (fmpz_is_zero(acc)) continue; for (w = 0; w < Blen; w++) { divides = (bits <= FLINT_BITS) ? mpoly_monomial_divides(texp, exp, Bexps[w] + N*0, N, mask) : mpoly_monomial_divides_mp(texp, exp, Bexps[w] + N*0, N, bits); if (!divides) continue; fmpz_mod_mpoly_fit_length(Q[w], q_len[w] + 1, ctx); mpoly_monomial_set(Q[w]->exps + N*q_len[w], texp, N); fmpz_mod_mul(Q[w]->coeffs + q_len[w], acc, lc_inv + w, ctx->ffinfo); if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = q_len[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps[w] + N*x->i, Q[w]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s[w] = 1; q_len[w]++; goto break_continue; /* continue in heap loop */ } /* if get here, no leading terms divided */ _fmpz_mod_mpoly_fit_length(&r_coeff, &R->coeffs_alloc, &r_exp, &R->exps_alloc, N, r_len + 1); fmpz_set(r_coeff + r_len, acc); mpoly_monomial_set(r_exp + N*r_len, exp, N); r_len++; break_continue:; } R->coeffs = r_coeff; R->exps = r_exp; R->length = r_len; for (i = 0; i < Blen; i++) Q[i]->length = q_len[i]; success = 1; cleanup: for (w = 0; w < Blen; w++) fmpz_clear(lc_inv + w); fmpz_clear(acc); TMP_END; return success; exp_overflow: R->coeffs = r_coeff; R->exps = r_exp; R->length = 0; for (i = 0; i < Blen; i++) Q[i]->length = 0; success = 0; goto cleanup; } /* Assumes divisor polys don't alias any output polys */ void fmpz_mod_mpoly_divrem_ideal_monagan_pearce( fmpz_mod_mpoly_struct ** Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, fmpz_mod_mpoly_struct * const * B, slong Blen, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t QRbits; slong len3 = 0; ulong * cmpmask; ulong * Aexps; ulong ** Bexps; int freeAexps, * freeBexps; fmpz_mod_mpoly_t TR; fmpz_mod_mpoly_struct * r; TMP_INIT; for (i = 0; i < Blen; i++) { len3 = FLINT_MAX(len3, B[i]->length); if (fmpz_mod_mpoly_is_zero(B[i], ctx)) flint_throw(FLINT_DIVZERO, "fmpz_mod_mpoly_divrem_ideal_monagan_pearce: divide by zero"); } /* dividend is zero, write out quotients and remainder */ if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(R, ctx); for (i = 0; i < Blen; i++) fmpz_mod_mpoly_zero(Q[i], ctx); return; } TMP_START; fmpz_mod_mpoly_init(TR, ctx); freeBexps = TMP_ARRAY_ALLOC(Blen, int); Bexps = TMP_ARRAY_ALLOC(Blen, ulong *); /* compute maximum degrees that can occur in any input or output polys */ QRbits = A->bits; for (i = 0; i < Blen; i++) QRbits = FLINT_MAX(QRbits, B[i]->bits); QRbits = mpoly_fix_bits(QRbits, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = FLINT_ARRAY_ALLOC(N, ulong); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ Aexps = A->exps; freeAexps = 0; if (QRbits > A->bits) { freeAexps = 1; Aexps = FLINT_ARRAY_ALLOC(N*A->length, ulong); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); } for (i = 0; i < Blen; i++) { Bexps[i] = B[i]->exps; freeBexps[i] = 0; if (QRbits > B[i]->bits) { freeBexps[i] = 1; Bexps[i] = FLINT_ARRAY_ALLOC(N*B[i]->length, ulong); mpoly_repack_monomials(Bexps[i], QRbits, B[i]->exps, B[i]->bits, B[i]->length, ctx->minfo); } } /* check leading mon. of at least one divisor is at most that of dividend */ for (i = 0; i < Blen; i++) { if (!mpoly_monomial_lt(Aexps + N*0, Bexps[i] + N*0, N, cmpmask)) break; } if (i == Blen) { fmpz_mod_mpoly_set(R, A, ctx); for (i = 0; i < Blen; i++) fmpz_mod_mpoly_zero(Q[i], ctx); goto cleanup; } /* take care of aliasing */ if (R == A) r = TR; else r = R; /* do division with remainder */ while (1) { fmpz_mod_mpoly_fit_length_reset_bits(r, len3, QRbits, ctx); for (i = 0; i < Blen; i++) fmpz_mod_mpoly_fit_length_reset_bits(Q[i], 1, QRbits, ctx); if (_fmpz_mod_mpoly_divrem_ideal_monagan_pearce(Q, r, A->coeffs, Aexps, A->length, B, Bexps, Blen, N, QRbits, ctx, cmpmask)) { break; } QRbits = mpoly_fix_bits(QRbits + 1, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = FLINT_ARRAY_REALLOC(cmpmask, N, ulong); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = FLINT_ARRAY_ALLOC(N*A->length, ulong); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; for (i = 0; i < Blen; i++) { if (freeBexps[i]) flint_free(Bexps[i]); Bexps[i] = FLINT_ARRAY_ALLOC(N*B[i]->length, ulong); mpoly_repack_monomials(Bexps[i], QRbits, B[i]->exps, B[i]->bits, B[i]->length, ctx->minfo); freeBexps[i] = 1; } } /* take care of aliasing */ if (R == A) fmpz_mod_mpoly_swap(R, TR, ctx); cleanup: fmpz_mod_mpoly_clear(TR, ctx); if (freeAexps) flint_free(Aexps); for (i = 0; i < Blen; i++) { if (freeBexps[i]) flint_free(Bexps[i]); } flint_free(cmpmask); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/divrem_monagan_pearce.c000066400000000000000000000577721461254215100231500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static int _fmpz_mod_mpoly_divrem_monagan_pearce1_binomial( fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, const fmpz * Bcoeffs, const ulong * Bexps, flint_bitcnt_t bits, ulong cmpmask, const fmpz_mod_ctx_t fctx) { fmpz * Qcoeffs = Q->coeffs; fmpz * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; ulong lexp, mask = mpoly_overflow_mask_sp(bits); fmpz_t lc_inv, mBcoeff1; slong Qlen = 0; slong Rlen = 0; slong Aidx = 0; slong Qidx = 0; fmpz_init(lc_inv); fmpz_init(mBcoeff1); fmpz_mod_inv(lc_inv, Bcoeffs + 0, fctx); fmpz_mod_neg(mBcoeff1, Bcoeffs + 1, fctx); while (1) { FLINT_ASSERT(0 <= Aidx && Aidx <= Alen); FLINT_ASSERT(0 <= Qidx && Qidx <= Qlen); _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); if (Aidx < Alen) { lexp = Aexps[Aidx]; if (Qidx < Qlen) { ulong thisexp = Bexps[1] + Qexps[Qidx]; int cmp = mpoly_monomial_cmp1(lexp, thisexp, cmpmask); if (cmp < 0) { lexp = thisexp; fmpz_mod_mul(Qcoeffs + Qlen, mBcoeff1, Qcoeffs + Qidx, fctx); Qidx++; } else if (cmp == 0) { fmpz_mod_mul(Qcoeffs + Qlen, mBcoeff1, Qcoeffs + Qidx, fctx); fmpz_mod_add(Qcoeffs + Qlen, Qcoeffs + Qlen, Acoeffs + Aidx, fctx); Aidx++; Qidx++; } else { fmpz_set(Qcoeffs + Qlen, Acoeffs + Aidx); Aidx++; } } else { fmpz_set(Qcoeffs + Qlen, Acoeffs + Aidx); Aidx++; } } else if (Qidx < Qlen) { lexp = Bexps[1] + Qexps[Qidx]; fmpz_mod_mul(Qcoeffs + Qlen, mBcoeff1, Qcoeffs + Qidx, fctx); Qidx++; } else { break; } if (mpoly_monomial_overflows1(lexp, mask)) goto exp_overflow; if (fmpz_is_zero(Qcoeffs + Qlen)) continue; if (!mpoly_monomial_divides1(Qexps + Qlen, lexp, Bexps[0], mask)) { _fmpz_mod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, &Rexps, &R->exps_alloc, 1, Rlen + 1); fmpz_swap(Rcoeffs + Rlen, Qcoeffs + Qlen); Rexps[Rlen] = lexp; Rlen++; continue; } if (!fmpz_is_one(lc_inv)) fmpz_mod_mul(Qcoeffs + Qlen, Qcoeffs + Qlen, lc_inv, fctx); Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; fmpz_clear(lc_inv); fmpz_clear(mBcoeff1); return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; fmpz_clear(lc_inv); fmpz_clear(mBcoeff1); return 0; } static int _fmpz_mod_mpoly_divrem_monagan_pearce1( fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, ulong cmpmask, const fmpz_mod_ctx_t fctx) { slong i, j, Qlen, Rlen, s; slong next_loc, heap_len = 2; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = Q->coeffs; fmpz * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; slong * hind; ulong mask, exp; int lt_divides; mpz_t t, acc, modulus; ulong acc_sm[3]; fmpz_t lc_minus_inv; TMP_INIT; mpz_init(t); mpz_init(acc); mpz_init(modulus); fmpz_get_mpz(modulus, fmpz_mod_ctx_modulus(fctx)); fmpz_init(lc_minus_inv); fmpz_mod_inv(lc_minus_inv, Bcoeffs + 0, fctx); fmpz_mod_neg(lc_minus_inv, lc_minus_inv, fctx); TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* quotient and remainder poly indices start at -1 */ Qlen = WORD(0); Rlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexps[0], x); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Bexps[0], mask); mpz_set_ui(acc, 0); acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -UWORD(1)) { fmpz Aj = Acoeffs[x->j]; if (COEFF_IS_MPZ(Aj)) mpz_sub(acc, acc, COEFF_TO_PTR(Aj)); else flint_mpz_sub_ui(acc, acc, Aj); } else { fmpz Bi = Bcoeffs[x->i]; fmpz Qj = Qcoeffs[x->j]; hind[x->i] |= WORD(1); if (COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { mpz_addmul(acc, COEFF_TO_PTR(Bi), COEFF_TO_PTR(Qj)); } else if (COEFF_IS_MPZ(Bi) && !COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Bi), Qj); } else if (!COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Qj), Bi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Bi, Qj); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], 0, pp1, pp0); } } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); flint_mpz_add_uiuiui(acc, acc, acc_sm[2], acc_sm[1], acc_sm[0]); if (mpz_sgn(acc) < 0) mpz_add(acc, acc, modulus); mpz_tdiv_qr(t, _fmpz_promote(Qcoeffs + Qlen), acc, modulus); _fmpz_demote_val(Qcoeffs + Qlen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -UWORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexps[x->j], x, &next_loc, &heap_len, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } } } if (fmpz_is_zero(Qcoeffs + Qlen)) continue; if (!lt_divides) { _fmpz_mod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, &Rexps, &R->exps_alloc, 1, Rlen + 1); fmpz_sub(Rcoeffs + Rlen, fmpz_mod_ctx_modulus(fctx), Qcoeffs + Qlen); Rexps[Rlen] = exp; Rlen++; continue; } fmpz_mod_mul(Qcoeffs + Qlen, Qcoeffs + Qlen, lc_minus_inv, fctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; TMP_END; fmpz_clear(lc_minus_inv); mpz_clear(t); mpz_clear(acc); mpz_clear(modulus); return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; TMP_END; fmpz_clear(lc_minus_inv); mpz_clear(t); mpz_clear(acc); mpz_clear(modulus); return 0; } static int _fmpz_mod_mpoly_divrem_monagan_pearce( fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, slong bits, slong N, const ulong * cmpmask, const fmpz_mod_ctx_t fctx) { slong i, j, Qlen, Rlen, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = Q->coeffs; fmpz * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; int lt_divides; mpz_t t, acc, modulus; ulong acc_sm[3]; fmpz_t lc_minus_inv; TMP_INIT; if (N == 1) { if (Blen == 2) return _fmpz_mod_mpoly_divrem_monagan_pearce1_binomial(Q, R, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, bits, cmpmask[0], fctx); else return _fmpz_mod_mpoly_divrem_monagan_pearce1(Q, R, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, Blen, bits, cmpmask[0], fctx); } mpz_init(t); mpz_init(acc); mpz_init(modulus); fmpz_get_mpz(modulus, fmpz_mod_ctx_modulus(fctx)); fmpz_init(lc_minus_inv); fmpz_mod_inv(lc_minus_inv, Bcoeffs + 0, fctx); fmpz_mod_neg(lc_minus_inv, lc_minus_inv, fctx); TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; Qlen = 0; Rlen = 0; /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); while (heap_len > 1) { _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, Qlen + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow2; lt_divides = mpoly_monomial_divides(Qexps + Qlen*N, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow2; lt_divides = mpoly_monomial_divides_mp(Qexps + Qlen*N, exp, Bexps, N, bits); } mpz_set_ui(acc, 0); acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { fmpz Aj = Acoeffs[x->j]; if (COEFF_IS_MPZ(Aj)) mpz_sub(acc, acc, COEFF_TO_PTR(Aj)); else flint_mpz_sub_ui(acc, acc, Aj); } else { fmpz Bi = Bcoeffs[x->i]; fmpz Qj = Qcoeffs[x->j]; hind[x->i] |= WORD(1); if (COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { mpz_addmul(acc, COEFF_TO_PTR(Bi), COEFF_TO_PTR(Qj)); } else if (COEFF_IS_MPZ(Bi) && !COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Bi), Qj); } else if (!COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Qj), Bi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Bi, Qj); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], 0, pp1, pp0); } } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); flint_mpz_add_uiuiui(acc, acc, acc_sm[2], acc_sm[1], acc_sm[0]); if (mpz_sgn(acc) < 0) mpz_add(acc, acc, modulus); mpz_tdiv_qr(t, _fmpz_promote(Qcoeffs + Qlen), acc, modulus); _fmpz_demote_val(Qcoeffs + Qlen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (fmpz_is_zero(Qcoeffs + Qlen)) continue; if (!lt_divides) { _fmpz_mod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, &Rexps, &R->exps_alloc, N, Rlen + 1); fmpz_sub(Rcoeffs + Rlen, fmpz_mod_ctx_modulus(fctx), Qcoeffs + Qlen); mpoly_monomial_set(Rexps + Rlen*N, exp, N); Rlen++; continue; } fmpz_mod_mul(Qcoeffs + Qlen, Qcoeffs + Qlen, lc_minus_inv, fctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; TMP_END; fmpz_clear(lc_minus_inv); mpz_clear(t); mpz_clear(acc); mpz_clear(modulus); return 1; exp_overflow2: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; TMP_END; fmpz_clear(lc_minus_inv); mpz_clear(t); mpz_clear(acc); mpz_clear(modulus); return 0; } void fmpz_mod_mpoly_divrem_monagan_pearce( fmpz_mod_mpoly_t Q, fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t QRbits; ulong * Aexps = A->exps, * Bexps = B->exps; ulong * cmpmask; int freeAexps = 0, freeBexps = 0; fmpz_mod_mpoly_t TQ, TR; fmpz_mod_mpoly_struct * q, * r; if (fmpz_mod_mpoly_is_zero(B, ctx)) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx->ffinfo))) { fmpz_mod_mpoly_zero(Q, ctx); fmpz_mod_mpoly_zero(R, ctx); return; } else { flint_throw(FLINT_DIVZERO, "fmpz_mod_mpoly_divrem_monagan_pearce: divide by zero"); } } if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(Q, ctx); fmpz_mod_mpoly_zero(R, ctx); return; } fmpz_mod_mpoly_init(TQ, ctx); fmpz_mod_mpoly_init(TR, ctx); QRbits = FLINT_MAX(A->bits, B->bits); QRbits = mpoly_fix_bits(QRbits, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (QRbits != A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); } if (QRbits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, QRbits, B->exps, B->bits, B->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(Aexps, Bexps, N, cmpmask)) { fmpz_mod_mpoly_set(R, A, ctx); fmpz_mod_mpoly_zero(Q, ctx); goto cleanup; } /* take care of aliasing */ if (Q == A || Q == B) q = TQ; else q = Q; if (R == A || R == B) r = TR; else r = R; /* do division with remainder */ while (1) { fmpz_mod_mpoly_fit_length_reset_bits(q, A->length/B->length + 1, QRbits, ctx); fmpz_mod_mpoly_fit_length_reset_bits(r, B->length, QRbits, ctx); if (_fmpz_mod_mpoly_divrem_monagan_pearce(q, r, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, QRbits, N, cmpmask, ctx->ffinfo)) { break; } QRbits = mpoly_fix_bits(QRbits + 1, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; if (freeBexps) flint_free(Bexps); Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, QRbits, B->exps, B->bits, B->length, ctx->minfo); freeBexps = 1; } /* deal with aliasing */ if (Q == A || Q == B) fmpz_mod_mpoly_swap(Q, TQ, ctx); if (R == A || R == B) fmpz_mod_mpoly_swap(R, TR, ctx); cleanup: fmpz_mod_mpoly_clear(TQ, ctx); fmpz_mod_mpoly_clear(TR, ctx); if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); flint_free(cmpmask); } flint-3.1.3/src/fmpz_mod_mpoly/equal.c000066400000000000000000000015741461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_equal( const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (A == B) return 1; if (A->length != B->length) return 0; if (!_fmpz_vec_equal(A->coeffs, B->coeffs, A->length)) return 0; return 0 == mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, A->length, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/equal_fmpz.c000066400000000000000000000034061461254215100207670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_equal_fmpz( const fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong N; if (A->length > 1) return 0; if (A->length < 1) return fmpz_divisible(c, fmpz_mod_mpoly_ctx_modulus(ctx)); N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return fmpz_mod_equal_fmpz(A->coeffs + 0, c, ctx->ffinfo); } int fmpz_mod_mpoly_equal_ui( const fmpz_mod_mpoly_t A, ulong c, const fmpz_mod_mpoly_ctx_t ctx) { int result; fmpz_t C; fmpz_init_set_ui(C, c); result = fmpz_mod_mpoly_equal_fmpz(A, C, ctx); fmpz_clear(C); return result; } int fmpz_mod_mpoly_equal_si( const fmpz_mod_mpoly_t A, slong c, const fmpz_mod_mpoly_ctx_t ctx) { slong N; if (A->length > 1) return 0; if (A->length < 1) { ulong uc; if (c == 0) return 1; if (!fmpz_abs_fits_ui(fmpz_mod_mpoly_ctx_modulus(ctx))) return 0; uc = FLINT_ABS(c); return 0 == (uc % fmpz_get_ui(fmpz_mod_mpoly_ctx_modulus(ctx))); } N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return fmpz_mod_equal_si(A->coeffs + 0, c, ctx->ffinfo); } flint-3.1.3/src/fmpz_mod_mpoly/evaluate_all_fmpz.c000066400000000000000000000056751461254215100223300ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void _fmpz_mod_mpoly_eval_all_fmpz_mod( fmpz_t eval, const fmpz * Acoeffs, /* need not be reduced mod fctx */ const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const fmpz * alphas, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fctx) { slong i, j; slong nvars = mctx->nvars; ulong mask = (Abits <= FLINT_BITS) ? (-UWORD(1)) >> (FLINT_BITS - Abits) : 0; slong N = mpoly_words_per_exp(Abits, mctx); ulong varexp_sp; fmpz_t varexp_mp, m, p; slong * offsets, * shifts; TMP_INIT; TMP_START; fmpz_init(varexp_mp); fmpz_init(m); fmpz_init(p); offsets = (slong *) TMP_ALLOC(2*nvars*sizeof(slong)); shifts = offsets + nvars; for (j = 0; j < nvars; j++) { if (Abits <= FLINT_BITS) mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, Abits, mctx); else offsets[j] = mpoly_gen_offset_mp(j, Abits, mctx); } fmpz_zero(eval); for (i = 0; i < Alen; i++) { fmpz_one(m); if (Abits <= FLINT_BITS) { for (j = 0; j < nvars; j++) { varexp_sp = ((Aexps + N*i)[offsets[j]]>>shifts[j])&mask; fmpz_mod_pow_ui(p, alphas + j, varexp_sp, fctx); fmpz_mod_mul(m, m, p, fctx); } } else { for (j = 0; j < nvars; j++) { fmpz_set_ui_array(varexp_mp, Aexps + N*i + offsets[j], Abits/FLINT_BITS); fmpz_mod_pow_fmpz(p, alphas + j, varexp_mp, fctx); fmpz_mod_mul(m, m, p, fctx); } } fmpz_addmul(eval, Acoeffs + i, m); } fmpz_clear(varexp_mp); fmpz_clear(m); fmpz_clear(p); TMP_END; fmpz_mod_set_fmpz(eval, eval, fctx); } void fmpz_mod_mpoly_evaluate_all_fmpz( fmpz_t eval, const fmpz_mod_mpoly_t A, fmpz * const * vals, const fmpz_mod_mpoly_ctx_t ctx) { slong i; fmpz * t; TMP_INIT; if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_zero(eval); return; } TMP_START; t = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) { fmpz_init(t + i); fmpz_mod_set_fmpz(t + i, vals[i], ctx->ffinfo); } _fmpz_mod_mpoly_eval_all_fmpz_mod(eval, A->coeffs, A->exps, A->length, A->bits, t, ctx->minfo, ctx->ffinfo); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(t + i); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/evaluate_one.c000066400000000000000000000130751461254215100212760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* exponents of B are not multiprecision */ void _fmpz_mod_mpoly_evaluate_one_fmpz_mod_sp( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_t val, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N, off, shift; ulong * cmpmask, * one; slong Blen = B->length; const fmpz * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; fmpz * Acoeffs; ulong * Aexps; ulong mask, k; int need_sort = 0, cmp; fmpz_t t; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; fmpz_init(t); fmpz_mod_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; mask = (-UWORD(1)) >> (FLINT_BITS - bits); N = mpoly_words_per_exp_sp(bits, ctx->minfo); one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; fmpz_mod_pow_ui(t, val, k, ctx->ffinfo); fmpz_mod_mul(Acoeffs + Alen, Bcoeffs + i, t, ctx->ffinfo); if (fmpz_is_zero(Acoeffs + Alen)) continue; mpoly_monomial_msub(Aexps + N*Alen, Bexps + N*i, k, one, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fmpz_mod_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen, ctx->ffinfo); Alen -= fmpz_is_zero(Acoeffs + Alen - 1); } A->length = Alen; fmpz_clear(t); TMP_END; if (need_sort) { fmpz_mod_mpoly_sort_terms(A, ctx); fmpz_mod_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(A, ctx)); } /* exponents of B are multiprecision */ static void _fmpz_mod_mpoly_evaluate_one_fmpz_mod_mp( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_t val, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N, off; ulong * cmpmask, * one, * tmp; slong Blen = B->length; const fmpz * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; fmpz * Acoeffs; ulong * Aexps; fmpz_t k, t; int need_sort = 0, cmp; TMP_INIT; FLINT_ASSERT((B->bits % FLINT_BITS) == 0); TMP_START; fmpz_init(k); fmpz_init(t); fmpz_mod_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; N = mpoly_words_per_exp(bits, ctx->minfo); one = (ulong *) TMP_ALLOC(3*N*sizeof(ulong)); cmpmask = one + N; tmp = cmpmask + N; off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexps + N*i + off, bits/FLINT_BITS); fmpz_mod_pow_fmpz(t, val, k, ctx->ffinfo); fmpz_mod_mul(Acoeffs + Alen, Bcoeffs + i, t, ctx->ffinfo); if (fmpz_is_zero(Acoeffs + Alen)) continue; mpoly_monomial_mul_fmpz(tmp, one, N, k); mpoly_monomial_sub_mp(Aexps + N*Alen, Bexps + N*i, tmp, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fmpz_mod_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen, ctx->ffinfo); Alen -= fmpz_is_zero(Acoeffs + Alen - 1); } A->length = Alen; fmpz_clear(k); fmpz_clear(t); TMP_END; if (need_sort) { fmpz_mod_mpoly_sort_terms(A, ctx); fmpz_mod_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(A, ctx)); } void fmpz_mod_mpoly_evaluate_one_fmpz( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_t val, const fmpz_mod_mpoly_ctx_t ctx) { #if FLINT_WANT_ASSERT flint_bitcnt_t bits = B->bits; #endif if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_zero(A, ctx); return; } if (fmpz_mod_is_canonical(val, ctx->ffinfo)) { if (B->bits <= FLINT_BITS) _fmpz_mod_mpoly_evaluate_one_fmpz_mod_sp(A, B, var, val, ctx); else _fmpz_mod_mpoly_evaluate_one_fmpz_mod_mp(A, B, var, val, ctx); } else { fmpz_t t; fmpz_init(t); fmpz_mod_set_fmpz(t, val, ctx->ffinfo); if (B->bits <= FLINT_BITS) _fmpz_mod_mpoly_evaluate_one_fmpz_mod_sp(A, B, var, t, ctx); else _fmpz_mod_mpoly_evaluate_one_fmpz_mod_mp(A, B, var, t, ctx); fmpz_clear(t); } /* unwritten rule that output bits = input bits if input != 0 */ FLINT_ASSERT(A->bits == bits); } flint-3.1.3/src/fmpz_mod_mpoly/fit_length.c000066400000000000000000000013231461254215100207430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_fit_length( fmpz_mod_mpoly_t A, slong len, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); _fmpz_mod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, len); } flint-3.1.3/src/fmpz_mod_mpoly/fit_length_fit_bits.c000066400000000000000000000033501461254215100226300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_fit_length_fit_bits( fmpz_mod_mpoly_t A, slong len, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N = mpoly_words_per_exp(A->bits, ctx->minfo); if (len > A->coeffs_alloc) { slong old_alloc = A->coeffs_alloc; slong new_alloc = FLINT_MAX(len, 2*old_alloc); A->coeffs_alloc = new_alloc; A->coeffs = (fmpz*) flint_realloc(A->coeffs, new_alloc*sizeof(fmpz)); for (i = old_alloc; i < new_alloc; i++) fmpz_init(A->coeffs + i); } if (bits > A->bits) { slong newN = mpoly_words_per_exp(bits, ctx->minfo); slong new_exps_alloc = newN*len; ulong * t; if (len < 1) { A->bits = bits; return; } t = (ulong *) flint_malloc(new_exps_alloc*sizeof(ulong)); if (A->length > 0) mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, ctx->minfo); if (A->exps_alloc > 0) flint_free(A->exps); A->exps = t; A->exps_alloc = new_exps_alloc; A->bits = bits; } else { if (N*len > A->exps_alloc) { A->exps_alloc = FLINT_MAX(N*len, 2*A->exps_alloc); A->exps = flint_realloc(A->exps, A->exps_alloc*sizeof(ulong)); } } } flint-3.1.3/src/fmpz_mod_mpoly/fit_length_reset_bits.c000066400000000000000000000014071461254215100231710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_fit_length_reset_bits( fmpz_mod_mpoly_t A, slong len, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(bits, ctx->minfo); _fmpz_mod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, len); A->bits = bits; } flint-3.1.3/src/fmpz_mod_mpoly/gcd.c000066400000000000000000000020051461254215100173530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_gcd( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_zero(A, ctx)) { if (fmpz_mod_mpoly_is_zero(B, ctx)) fmpz_mod_mpoly_zero(G, ctx); else fmpz_mod_mpoly_make_monic(G, B, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_make_monic(G, A, ctx); return 1; } return _fmpz_mod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/fmpz_mod_mpoly/gcd_brown.c000066400000000000000000000014711461254215100205700ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_gcd_brown( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_zero(A, ctx) || fmpz_mod_mpoly_is_zero(B, ctx)) return fmpz_mod_mpoly_gcd(G, A, B, ctx); return _fmpz_mod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_BROWN); } flint-3.1.3/src/fmpz_mod_mpoly/gcd_cofactors.c000066400000000000000000000040661461254215100214270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_gcd_cofactors( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_zero(A, ctx)) { if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_zero(G, ctx); fmpz_mod_mpoly_zero(Abar, ctx); fmpz_mod_mpoly_zero(Bbar, ctx); return 1; } fmpz_mod_mpoly_set(G, B, ctx); fmpz_mod_mpoly_zero(Abar, ctx); fmpz_mod_mpoly_one(Bbar, ctx); if (!fmpz_is_one(G->coeffs + 0)) { _fmpz_mod_vec_scalar_mul_fmpz_mod(Bbar->coeffs, Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx->ffinfo); _fmpz_mod_vec_scalar_div_fmpz_mod(G->coeffs, G->coeffs, G->length, G->coeffs + 0, ctx->ffinfo); } return 1; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_set(G, A, ctx); fmpz_mod_mpoly_zero(Bbar, ctx); fmpz_mod_mpoly_one(Abar, ctx); if (!fmpz_is_one(G->coeffs + 0)) { _fmpz_mod_vec_scalar_mul_fmpz_mod(Abar->coeffs, Abar->coeffs, Abar->length, G->coeffs + 0, ctx->ffinfo); _fmpz_mod_vec_scalar_div_fmpz_mod(G->coeffs, G->coeffs, G->length, G->coeffs + 0, ctx->ffinfo); } return 1; } return _fmpz_mod_mpoly_gcd_algo(G, Abar, Bbar, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/fmpz_mod_mpoly/gcd_hensel.c000066400000000000000000000014731461254215100207210ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_gcd_hensel( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_zero(A, ctx) || fmpz_mod_mpoly_is_zero(B, ctx)) return fmpz_mod_mpoly_gcd(G, A, B, ctx); return _fmpz_mod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_HENSEL); } flint-3.1.3/src/fmpz_mod_mpoly/gcd_subresultant.c000066400000000000000000000014761461254215100222010ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_gcd_subresultant( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_zero(A, ctx) || fmpz_mod_mpoly_is_zero(B, ctx)) return fmpz_mod_mpoly_gcd(G, A, B, ctx); return _fmpz_mod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_PRS); } flint-3.1.3/src/fmpz_mod_mpoly/gcd_zippel.c000066400000000000000000000014731461254215100207460ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_gcd_zippel( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_zero(A, ctx) || fmpz_mod_mpoly_is_zero(B, ctx)) return fmpz_mod_mpoly_gcd(G, A, B, ctx); return _fmpz_mod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL); } flint-3.1.3/src/fmpz_mod_mpoly/gcd_zippel2.c000066400000000000000000000014751461254215100210320ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_gcd_zippel2( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_zero(A, ctx) || fmpz_mod_mpoly_is_zero(B, ctx)) return fmpz_mod_mpoly_gcd(G, A, B, ctx); return _fmpz_mod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL2); } flint-3.1.3/src/fmpz_mod_mpoly/gen.c000066400000000000000000000020351461254215100173720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_gen(fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t bits; bits = mpoly_gen_bits_required(var, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, 1, bits, ctx); fmpz_one(A->coeffs + 0); if (bits <= FLINT_BITS) mpoly_gen_monomial_sp(A->exps, var, bits, ctx->minfo); else mpoly_gen_monomial_offset_mp(A->exps, var, bits, ctx->minfo); _fmpz_mod_mpoly_set_length(A, !fmpz_is_one( fmpz_mod_ctx_modulus(ctx->ffinfo)), ctx); } flint-3.1.3/src/fmpz_mod_mpoly/geobuckets.c000066400000000000000000000077461461254215100207720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_geobucket_init( fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { fmpz_mod_mpoly_init(B->polys + i, ctx); fmpz_mod_mpoly_init(B->temps + i, ctx); } B->length = 0; } void fmpz_mod_mpoly_geobucket_clear( fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { fmpz_mod_mpoly_clear(B->polys + i, ctx); fmpz_mod_mpoly_clear(B->temps + i, ctx); } } /* empty out bucket B into polynomial p */ void fmpz_mod_mpoly_geobucket_empty( fmpz_mod_mpoly_t p, fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (B->length < 2) { if (B->length < 1) fmpz_mod_mpoly_zero(p, ctx); else fmpz_mod_mpoly_set(p, B->polys + 0, ctx); } else if (B->length == 2) { fmpz_mod_mpoly_add(p, B->polys + 1, B->polys + 0, ctx); } else { fmpz_mod_mpoly_add(B->temps + 1, B->polys + 1, B->polys + 0, ctx); for (i = 2; i < B->length - 1; i++) fmpz_mod_mpoly_add(B->temps + i, B->polys + i, B->temps + i - 1, ctx); fmpz_mod_mpoly_add(p, B->polys + i, B->temps + i - 1, ctx); } B->length = 0; } void fmpz_mod_mpoly_geobucket_fit_length( fmpz_mod_mpoly_geobucket_t B, slong len, const fmpz_mod_mpoly_ctx_t ctx) { slong j; for (j = B->length; j < len; j++) fmpz_mod_mpoly_zero(B->polys + j, ctx); B->length = j; } /* set bucket B to polynomial p */ void fmpz_mod_mpoly_geobucket_set( fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx) { slong i = mpoly_geobucket_clog4(p->length); B->length = 0; fmpz_mod_mpoly_geobucket_fit_length(B, i + 1, ctx); fmpz_mod_mpoly_swap(B->polys + i, p, ctx); B->length = i + 1; } /* internal function for fixing overflows */ void _fmpz_mod_mpoly_geobucket_fix( fmpz_mod_mpoly_geobucket_t B, slong i, const fmpz_mod_mpoly_ctx_t ctx) { while (mpoly_geobucket_clog4(B->polys[i].length) > i) { FLINT_ASSERT(i + 1 <= B->length); if (i + 1 == B->length) { B->length = i + 2; fmpz_mod_mpoly_set(B->polys + i + 1, B->polys + i, ctx); } else { fmpz_mod_mpoly_add(B->temps + i + 1, B->polys + i + 1, B->polys + i, ctx); fmpz_mod_mpoly_swap(B->polys + i + 1, B->temps + i + 1, ctx); } fmpz_mod_mpoly_zero(B->polys + i, ctx); i++; } } /* add polynomial p to bucket B */ void fmpz_mod_mpoly_geobucket_add( fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (fmpz_mod_mpoly_is_zero(p, ctx)) return; i = mpoly_geobucket_clog4(p->length); fmpz_mod_mpoly_geobucket_fit_length(B, i + 1, ctx); fmpz_mod_mpoly_add(B->temps + i, B->polys + i, p, ctx); fmpz_mod_mpoly_swap(B->polys + i, B->temps + i, ctx); _fmpz_mod_mpoly_geobucket_fix(B, i, ctx); } /* sub polynomial p to bucket B */ void fmpz_mod_mpoly_geobucket_sub( fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (fmpz_mod_mpoly_is_zero(p, ctx)) return; i = mpoly_geobucket_clog4(p->length); fmpz_mod_mpoly_geobucket_fit_length(B, i + 1, ctx); fmpz_mod_mpoly_sub(B->temps + i, B->polys + i, p, ctx); fmpz_mod_mpoly_swap(B->polys + i, B->temps + i, ctx); _fmpz_mod_mpoly_geobucket_fix(B, i, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/get_coeff_fmpz_fmpz.c000066400000000000000000000016141461254215100226340ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_coeff_fmpz_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_pfmpz(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { fmpz_zero(c); } else { FLINT_ASSERT(index < A->length); fmpz_set(c, A->coeffs + index); } } flint-3.1.3/src/fmpz_mod_mpoly/get_coeff_fmpz_monomial.c000066400000000000000000000020171461254215100234710ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_coeff_fmpz_monomial(fmpz_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_ctx_t ctx) { slong index; if (M->length != WORD(1)) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_coeff_fmpz_monomial: M not monomial"); index = mpoly_monomial_index_monomial(A->exps, A->bits, A->length, M->exps, M->bits, ctx->minfo); if (index < 0) { fmpz_zero(c); } else { FLINT_ASSERT(index < A->length); fmpz_set(c, A->coeffs + index); } } flint-3.1.3/src/fmpz_mod_mpoly/get_coeff_fmpz_ui.c000066400000000000000000000016071461254215100222770ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_coeff_fmpz_ui(fmpz_t c, const fmpz_mod_mpoly_t A, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_ui(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { fmpz_zero(c); } else { FLINT_ASSERT(index < A->length); fmpz_set(c, A->coeffs + index); } } flint-3.1.3/src/fmpz_mod_mpoly/get_coeff_vars_ui.c000066400000000000000000000076751461254215100223110ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_coeff_vars_ui( fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j, N; slong offset, shift; slong maxoffset, minoffset; ulong * uexp; ulong * tmask, * texp; slong nvars = ctx->minfo->nvars; fmpz * Ccoeff; ulong * Cexp; slong Clen; TMP_INIT; if (C == A) { fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init(T, ctx); fmpz_mod_mpoly_get_coeff_vars_ui(T, A, vars, exps,length, ctx); fmpz_mod_mpoly_swap(T, C, ctx); fmpz_mod_mpoly_clear(T, ctx); return; } TMP_START; uexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); for (i = 0; i < nvars; i++) uexp[i] = 0; for (i = 0; i < length; i++) uexp[vars[i]] = exps[i]; if (A->bits < mpoly_exp_bits_required_ui(uexp, ctx->minfo)) { fmpz_mod_mpoly_zero(C, ctx); goto cleanup; } fmpz_mod_mpoly_fit_length_reset_bits(C, 4, A->bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); tmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(tmask, N); mpoly_set_monomial_ui(texp, uexp, A->bits, ctx->minfo); Ccoeff = C->coeffs; Cexp = C->exps; Clen = 0; if (A->bits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { mpoly_gen_offset_shift_sp(&offset, &shift, vars[i], A->bits, ctx->minfo); tmask[offset] |= mask << shift; maxoffset = FLINT_MAX(maxoffset, offset); minoffset = FLINT_MIN(minoffset, offset); } FLINT_ASSERT(minoffset < N); for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_sp; } _fmpz_mod_mpoly_fit_length(&Ccoeff, &C->coeffs_alloc, &Cexp, &C->exps_alloc, N, Clen + 1); mpoly_monomial_sub(Cexp + N*Clen, A->exps + N*i, texp, N); fmpz_set(Ccoeff + Clen, A->coeffs + i); Clen++; continue_outer_sp:; } } else { ulong wpf = A->bits/FLINT_BITS; maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { offset = mpoly_gen_offset_mp(vars[i], A->bits, ctx->minfo); minoffset = FLINT_MIN(minoffset, offset); maxoffset = FLINT_MAX(maxoffset, offset + wpf - 1); for (j = 0; j < wpf; j++) tmask[offset + j] = -UWORD(1); } FLINT_ASSERT(minoffset < N); for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_mp; } _fmpz_mod_mpoly_fit_length(&Ccoeff, &C->coeffs_alloc, &Cexp, &C->exps_alloc, N, Clen + 1); mpoly_monomial_sub_mp(Cexp + N*Clen, A->exps + N*i, texp, N); fmpz_set(Ccoeff + Clen, A->coeffs + i); Clen++; continue_outer_mp:; } } C->coeffs = Ccoeff; C->exps = Cexp; _fmpz_mod_mpoly_set_length(C, Clen, ctx); cleanup: TMP_END; return; } flint-3.1.3/src/fmpz_mod_mpoly/get_fmpz.c000066400000000000000000000016761461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_fmpz( fmpz_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong N; if (A->length > 1) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_fmpz: nonconstant polynomial"); if (A->length < 1) { fmpz_zero(c); return; } N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_fmpz: nonconstant polynomial"); fmpz_set(c, A->coeffs + 0); } flint-3.1.3/src/fmpz_mod_mpoly/get_set_is_fmpz_mod_poly.c000066400000000000000000000070161461254215100237100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_is_fmpz_mod_poly( const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { return mpoly_is_poly(A->exps, A->length, A->bits, var, ctx->minfo); } int fmpz_mod_mpoly_get_fmpz_mod_poly( fmpz_mod_poly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong Blen = B->length; const fmpz * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t Bbits = B->bits; slong i, N = mpoly_words_per_exp(Bbits, ctx->minfo); ulong k; fmpz_mod_poly_zero(A, ctx->ffinfo); if (B->length < 1) return 1; if (Bbits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - Bbits); slong off, shift; mpoly_gen_offset_shift_sp(&off, &shift, var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; fmpz_mod_poly_set_coeff_fmpz(A, k, Bcoeffs + i, ctx->ffinfo); } return 1; } else { slong j, off; ulong check, wpf = Bbits/FLINT_BITS; off = mpoly_gen_offset_mp(var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = Bexps[N*i + off + 0]; check = 0; for (j = 1; j < wpf; j++) check |= Bexps[N*i + off + j]; if (check != 0 || (slong) k < 0) return 0; fmpz_mod_poly_set_coeff_fmpz(A, k, Bcoeffs + i, ctx->ffinfo); } return 1; } } void _fmpz_mod_mpoly_set_fmpz_mod_poly( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz * Bcoeffs, slong Blen, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += (Bcoeffs[i] != 0); fmpz_mod_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { if (fmpz_is_zero(Bcoeffs + i)) continue; FLINT_ASSERT(Alen < A->coeffs_alloc); fmpz_set(A->coeffs+ Alen, Bcoeffs + i); if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } void fmpz_mod_mpoly_set_fmpz_mod_poly( fmpz_mod_mpoly_t A, const fmpz_mod_poly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t bits; if (B->length < 1) { fmpz_mod_mpoly_zero(A, ctx); return; } bits = mpoly_gen_pow_exp_bits_required(var, B->length - 1, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); _fmpz_mod_mpoly_set_fmpz_mod_poly(A, bits, B->coeffs, B->length, var, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/get_set_nmod_mpoly.c000066400000000000000000000026021461254215100225100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" #include "fmpz_mod_mpoly.h" void _fmpz_mod_mpoly_set_nmod_mpoly( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, const nmod_mpoly_t nA, const nmod_mpoly_ctx_t nctx) { slong i, N = mpoly_words_per_exp(nA->bits, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, nA->length, nA->bits, ctx); mpoly_copy_monomials(A->exps, nA->exps, nA->length, N); for (i = 0; i < nA->length; i++) fmpz_set_ui(A->coeffs + i, nA->coeffs[i]); _fmpz_mod_mpoly_set_length(A, nA->length, ctx); } void _fmpz_mod_mpoly_get_nmod_mpoly( nmod_mpoly_t nA, const nmod_mpoly_ctx_t nctx, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N = mpoly_words_per_exp(A->bits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(nA, A->length, A->bits, nctx); mpoly_copy_monomials(nA->exps, A->exps, A->length, N); for (i = 0; i < A->length; i++) nA->coeffs[i] = fmpz_get_ui(A->coeffs + i); nA->length = A->length; } flint-3.1.3/src/fmpz_mod_mpoly/get_str_pretty.c000066400000000000000000000013151461254215100216770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #include "fmpz_mod_mpoly.h" char * fmpz_mod_mpoly_get_str_pretty(const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) { return _fmpz_mpoly_get_str_pretty(A->coeffs, A->exps, A->length, x, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/get_term.c000066400000000000000000000017411461254215100204320ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_term(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term: index out of range"); fmpz_mod_mpoly_fit_length_reset_bits(M, 1, bits, ctx); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); fmpz_set(M->coeffs + 0, A->coeffs + i); _fmpz_mod_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/get_term_coeff_fmpz.c000066400000000000000000000013531461254215100226270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_term_coeff_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term_coeff_fmpz: index out of range"); fmpz_set(c, A->coeffs + i); } flint-3.1.3/src/fmpz_mod_mpoly/get_term_exp_fmpz.c000066400000000000000000000015141461254215100223400ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term_exp_fmpz: index out of range"); mpoly_get_monomial_pfmpz(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/get_term_exp_si.c000066400000000000000000000015011461254215100217730ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_term_exp_si(slong * exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term_exp_si: index out of range"); mpoly_get_monomial_si(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/get_term_exp_ui.c000066400000000000000000000015011461254215100217750ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_term_exp_ui(ulong * exp, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term_exp_ui: index out of range"); mpoly_get_monomial_ui(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/get_term_monomial.c000066400000000000000000000017171461254215100223300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_get_term_monomial( fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term_monomial: index out of range"); fmpz_mod_mpoly_fit_length_reset_bits(M, 1, bits, ctx); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); fmpz_one(M->coeffs + 0); _fmpz_mod_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/get_term_var_exp_si.c000066400000000000000000000015251461254215100226510ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" slong fmpz_mod_mpoly_get_term_var_exp_si(const fmpz_mod_mpoly_t A, slong i, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term_var_exp_si: index out of range"); return mpoly_get_monomial_var_exp_si(A->exps + N*i, var, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/get_term_var_exp_ui.c000066400000000000000000000015311461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" ulong fmpz_mod_mpoly_get_term_var_exp_ui(const fmpz_mod_mpoly_t A, slong i, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_get_term_var_exp_ui: index out of range"); return mpoly_get_monomial_var_exp_ui(A->exps + N*i, var, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/inflate.c000066400000000000000000000047571461254215100202600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_inflate( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mod_mpoly_ctx_t ctx) { int have_zero_stride; slong j; slong Abits; slong nvars = ctx->minfo->nvars; fmpz * exps; TMP_INIT; if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_zero(A, ctx); return; } TMP_START; exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exps + j); /* quick and safe bound on bits required */ mpoly_degrees_ffmpz(exps, B->exps, B->length, B->bits, ctx->minfo); have_zero_stride = 0; for (j = 0; j < nvars; j++) { have_zero_stride |= fmpz_is_zero(stride + j); fmpz_mul(exps + j, exps + j, stride + j); fmpz_add(exps + j, exps + j, shift + j); } Abits = mpoly_exp_bits_required_ffmpz(exps, ctx->minfo); Abits = mpoly_fix_bits(Abits, ctx->minfo); for (j = 0; j < nvars; j++) fmpz_clear(exps + j); if (A == B) { slong NA = mpoly_words_per_exp(Abits, ctx->minfo); slong exps_alloc = NA*B->length; ulong * texps = flint_malloc(exps_alloc*sizeof(ulong)); mpoly_monomials_inflate(texps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = Abits; A->exps_alloc = exps_alloc; } else { fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); _fmpz_vec_set(A->coeffs, B->coeffs, B->length); mpoly_monomials_inflate(A->exps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _fmpz_mod_mpoly_set_length(A, B->length, ctx); } TMP_END; if (have_zero_stride || ctx->minfo->ord != ORD_LEX) { fmpz_mod_mpoly_sort_terms(A, ctx); if (have_zero_stride) fmpz_mod_mpoly_combine_like_terms(A, ctx); } return; } flint-3.1.3/src/fmpz_mod_mpoly/init.c000066400000000000000000000023251461254215100175660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_init3( fmpz_mod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(bits, ctx->minfo); if (alloc > 0) { A->coeffs_alloc = alloc; A->coeffs = (fmpz *) flint_calloc(A->coeffs_alloc, sizeof(fmpz)); A->exps_alloc = N*alloc; A->exps = FLINT_ARRAY_ALLOC(A->exps_alloc, ulong); } else { A->coeffs = NULL; A->exps = NULL; A->coeffs_alloc = 0; A->exps_alloc = 0; } A->length = 0; A->bits = bits; } void fmpz_mod_mpoly_init2( fmpz_mod_mpoly_t A, slong alloc, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = mpoly_fix_bits(MPOLY_MIN_BITS, ctx->minfo); fmpz_mod_mpoly_init3(A, alloc, bits, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/inlines.c000066400000000000000000000006721461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_MPOLY_INLINES_C #include "fmpz_mod_mpoly.h" flint-3.1.3/src/fmpz_mod_mpoly/io.c000066400000000000000000000052641461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mod_mpoly.h" /* printing *******************************************************************/ int fmpz_mod_mpoly_fprint_pretty(FILE * file, const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) { return _fmpz_mpoly_fprint_pretty(file, A->coeffs, A->exps, A->length, x, A->bits, ctx->minfo); } int fmpz_mod_mpoly_print_pretty(const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_fprint_pretty(stdout, A, x, ctx); } /* debugging ******************************************************************/ /* test that r is a valid remainder upon division by g this means that no monomial of r is divisible by lm(g) */ void fmpz_mod_mpoly_remainder_strongtest(const fmpz_mod_mpoly_t r, const fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N, bits; ulong mask = 0; ulong * rexp, * gexp; bits = FLINT_MAX(r->bits, g->bits); N = mpoly_words_per_exp(bits, ctx->minfo); if (g->length == 0) flint_throw(FLINT_ERROR, "Zero denominator in remainder test"); if (r->length == 0) return; rexp = (ulong *) flint_malloc(N*r->length*sizeof(ulong)); gexp = (ulong *) flint_malloc(N*1 *sizeof(ulong)); mpoly_repack_monomials(rexp, bits, r->exps, r->bits, r->length, ctx->minfo); mpoly_repack_monomials(gexp, bits, g->exps, g->bits, 1, ctx->minfo); if (bits <= FLINT_BITS) mask = mpoly_overflow_mask_sp(bits); else mask = 0; for (i = 0; i < r->length; i++) { int divides; if (bits <= FLINT_BITS) divides = mpoly_monomial_divides_test(rexp + i*N, gexp + 0*N, N, mask); else divides = mpoly_monomial_divides_mp_test(rexp + i*N, gexp + 0*N, N, bits); if (divides) { flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_remainder_strongtest FAILED i = %wd\n" "rem %s\n\n" "den %s\n\n", i, fmpz_mod_mpoly_get_str_pretty(r, NULL, ctx), fmpz_mod_mpoly_get_str_pretty(g, NULL, ctx)); } } flint_free(rexp); flint_free(gexp); } flint-3.1.3/src/fmpz_mod_mpoly/is_canonical.c000066400000000000000000000045371461254215100212540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_is_canonical( const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong i; if (A->length > A->coeffs_alloc) return 0; if (N*A->length > A->exps_alloc) return 0; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { if (!fmpz_mod_is_canonical(A->coeffs + i, ctx->ffinfo)) return 0; if (fmpz_is_zero(A->coeffs + i)) return 0; } return 1; } void fmpz_mod_mpoly_assert_canonical( const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong i; if (A->length > A->coeffs_alloc) flint_throw(FLINT_ERROR, "Polynomial coefficient allocation is bad"); if (N*A->length > A->exps_alloc) flint_throw(FLINT_ERROR, "Polynomial exponent allocation is bad"); if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents out of order"); for (i = 0; i < A->length; i++) { if (!fmpz_mod_is_canonical(A->coeffs + i, ctx->ffinfo)) flint_throw(FLINT_ERROR, "Polynomial has a bad coefficient"); if (fmpz_is_zero(A->coeffs + i)) flint_throw(FLINT_ERROR, "Polynomial has a zero coefficient"); } } flint-3.1.3/src/fmpz_mod_mpoly/is_fmpz.c000066400000000000000000000013271461254215100202730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_is_fmpz( const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong N; if (A->length > 1) return 0; if (A->length < 1) return 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } flint-3.1.3/src/fmpz_mod_mpoly/is_gen.c000066400000000000000000000014261461254215100200700ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_is_gen(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { if (A->length != 1) return fmpz_is_one(fmpz_mod_ctx_modulus(ctx->ffinfo)); if (!fmpz_is_one(A->coeffs + 0)) return 0; return mpoly_is_gen(A->exps, var, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/lead_coeff_vars.c000066400000000000000000000036401461254215100217260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* leading coefficient wrt gen(0), ..., gen(num_vars-1) c will be returned with c->bits == A->bits */ void fmpz_mod_mpolyl_lead_coeff( fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_t A, slong num_vars, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j, off, shift; ulong mask, first_mask; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; ulong * cexps; slong Alen = A->length; FLINT_ASSERT(c != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) << shift; i = 0; first_mask = (Aexps + N*i)[off] & mask; for (i = 1; i < Alen; i++) { if (((Aexps + N*i)[off] & mask) != first_mask) goto break_outer; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto break_outer; } break_outer: fmpz_mod_mpoly_fit_length_reset_bits(c, i, A->bits, ctx); c->length = i; cexps = c->exps; _fmpz_vec_set(c->coeffs, A->coeffs, c->length); mask = ~mask; for (i = 0; i < c->length; i++) { for (j = 0; j < off; j++) (cexps + N*i)[j] = (Aexps + N*i)[j]; (cexps + N*i)[off] = mask & (Aexps + N*i)[off]; for (j = off + 1; j < N; j++) (cexps + N*i)[j] = 0; } } flint-3.1.3/src/fmpz_mod_mpoly/make_monic.c000066400000000000000000000014761461254215100207330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_make_monic( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t c; if (B->length < 1) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_make_monic: polynomial is zero"); fmpz_init(c); fmpz_mod_inv(c, B->coeffs + 0, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(A, B, c, ctx); fmpz_clear(c); } flint-3.1.3/src/fmpz_mod_mpoly/mul.c000066400000000000000000000057521461254215100174270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static int _try_dense( const fmpz * maxBfields, const fmpz * maxCfields, slong Blen, slong Clen, const mpoly_ctx_t mctx) { int ret; const int max_bit_size = FLINT_MIN(FLINT_BITS/3 + 16, FLINT_BITS - 4); slong i, product_count; ulong * Bdegs, * Cdegs; ulong t, dense_size; TMP_INIT; if (mctx->nvars < 1) return 0; TMP_START; Bdegs = TMP_ARRAY_ALLOC(2*mctx->nvars, ulong); Cdegs = Bdegs + mctx->nvars; mpoly_get_monomial_ui_unpacked_ffmpz(Bdegs, maxBfields, mctx); mpoly_get_monomial_ui_unpacked_ffmpz(Cdegs, maxCfields, mctx); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); dense_size = 1; for (i = 0; i < mctx->nvars; i++) { if (n_add_checked(&t, Bdegs[i], Cdegs[i] + 1) || n_mul_checked(&dense_size, dense_size, t)) { ret = 0; goto cleanup; } } if (dense_size >= (UWORD(1) << max_bit_size)) { ret = 0; goto cleanup; } if (z_mul_checked(&product_count, Blen, Clen)) { ret = 1; goto cleanup; } ret = dense_size < product_count/32; cleanup: TMP_END; return ret; } void fmpz_mod_mpoly_mul( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields, * maxCfields; slong min_length, max_length; TMP_INIT; if (B->length < 1 || C->length < 1) { fmpz_mod_mpoly_zero(A, ctx); return; } TMP_START; maxBfields = TMP_ARRAY_ALLOC(2*ctx->minfo->nfields, fmpz); maxCfields = maxBfields + ctx->minfo->nfields; for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); min_length = FLINT_MIN(B->length, C->length); max_length = FLINT_MAX(B->length, C->length); if (min_length < 20 || max_length < 50 || B->bits > FLINT_BITS || C->bits > FLINT_BITS) { goto do_heap; } if (_try_dense(maxBfields, maxCfields, B->length, C->length, ctx->minfo)) { if (_fmpz_mod_mpoly_mul_dense_maxfields(A, B, maxBfields, C, maxCfields, ctx)) goto cleanup; } do_heap: _fmpz_mod_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); cleanup: for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/mul_dense.c000066400000000000000000000166541461254215100206100ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "fmpz_mod_poly.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void _fmpz_mod_mpoly_init_dense_mock( fmpz_mod_poly_t D, const fmpz_mod_mpoly_t A, const slong * Adeg_bounds, const fmpz_mod_mpoly_ctx_t ctx) { slong N, i, j, off, Ddeg, degb_prod; ulong * exps; slong nvars = ctx->minfo->nvars; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); degb_prod = 1; for (i = 0; i < nvars; i++) degb_prod *= Adeg_bounds[i]; D->alloc = degb_prod; D->coeffs = (fmpz *) flint_calloc(degb_prod, sizeof(fmpz)); TMP_START; exps = TMP_ARRAY_ALLOC(nvars, ulong); N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); Ddeg = -1; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ui(exps, A->exps + N*i, A->bits, ctx->minfo); off = exps[0]; for (j = 1; j < nvars; j++) off = exps[j] + Adeg_bounds[j]*off; D->coeffs[off] = A->coeffs[i]; /* shallow copy */ Ddeg = FLINT_MAX(Ddeg, off); } D->length = Ddeg + 1; TMP_END; } static void _from_dense( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const slong * Adeg_bounds, fmpz_mod_poly_t D, const fmpz_mod_mpoly_ctx_t ctx) { slong off, Alen, j, k, N; flint_bitcnt_t bits; slong nvars = ctx->minfo->nvars; ulong topmask; slong * exps; ulong * pcurexp, * pexps; TMP_INIT; TMP_START; exps = TMP_ARRAY_ALLOC(nvars, slong); /* find bits needed for the result */ off = 1; for (j = 0; j < nvars; j++) { off *= Adeg_bounds[j]; exps[j] = Adeg_bounds[j] - 1; } bits = mpoly_exp_bits_required_ui((ulong *)exps, ctx->minfo); bits = FLINT_MAX(bits, Abits); bits = mpoly_fix_bits(bits, ctx->minfo); N = mpoly_words_per_exp(bits, ctx->minfo); pcurexp = TMP_ARRAY_ALLOC(N*(nvars + 1), ulong); pexps = pcurexp + N; /* we are going to push back terms manually */ fmpz_mod_mpoly_fit_length_reset_bits(A, 0, bits, ctx); Alen = 0; /* find exponent vector for all variables */ for (k = 0; k < nvars; k++) mpoly_gen_monomial_sp(pexps + k*N, k, bits, ctx->minfo); /* get most significant exponent in exps and its vector in ptempexp */ off--; mpoly_monomial_zero(pcurexp, N); k = off; for (j = nvars - 1; j >= 0; j--) { exps[j] = k % Adeg_bounds[j]; k = k / Adeg_bounds[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } /* scan down through the exponents */ topmask = 0; for (; off >= 0; off--) { if (off < D->length && !fmpz_is_zero(D->coeffs + off)) { _fmpz_mod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, Alen + 1); fmpz_swap(A->coeffs + Alen, D->coeffs + off); mpoly_monomial_set(A->exps + N*Alen, pcurexp, N); topmask |= (A->exps + N*Alen)[N - 1]; Alen++; } j = nvars - 1; do { --exps[j]; if (exps[j] < 0) { FLINT_ASSERT(off == 0 || j > 0); FLINT_ASSERT(exps[j] == -UWORD(1)); exps[j] = Adeg_bounds[j] - 1; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } else { mpoly_monomial_sub_mp(pcurexp, pcurexp, pexps + N*j, N); break; } } while (--j >= 0); } _fmpz_mod_mpoly_set_length(A, Alen, ctx); /* sort the exponents if needed */ if (ctx->minfo->ord != ORD_LEX) { flint_bitcnt_t pos; mpoly_get_cmpmask(pcurexp, N, bits, ctx->minfo); pos = FLINT_BIT_COUNT(topmask); if (N == 1) _fmpz_mod_mpoly_radix_sort1(A->coeffs, A->exps, 0, A->length, pos, pcurexp[0], topmask); else _fmpz_mod_mpoly_radix_sort(A->coeffs, A->exps, 0, A->length, (N - 1)*FLINT_BITS + pos, N, pcurexp); } TMP_END; } int _fmpz_mod_mpoly_mul_dense_maxfields( fmpz_mod_mpoly_t P, const fmpz_mod_mpoly_t A, fmpz * maxAfields, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_ctx_t ctx) { int success = 1; slong i, nvars = ctx->minfo->nvars; fmpz_mod_poly_t Ad, Bd, Pd; slong prod_deg, * Abounds, * Bbounds, * Pbounds; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(nvars > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; /* for each variable v except for the outermost variable, we need to pack to degree deg_v(A) + deg_v(B) */ Abounds = TMP_ARRAY_ALLOC(3*nvars, slong); Bbounds = Abounds + nvars; Pbounds = Bbounds + nvars; mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Abounds, maxAfields, ctx->minfo); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Bbounds, maxBfields, ctx->minfo); prod_deg = 1; for (i = 0; i < nvars; i++) { if (z_add_checked(&Abounds[i], Abounds[i], 1) || z_add_checked(&Bbounds[i], Bbounds[i], 1) || z_add_checked(&Pbounds[i], Abounds[i], Bbounds[i] - 1) || z_mul_checked(&prod_deg, prod_deg, Pbounds[i])) { success = 0; goto cleanup; } if (i != 0) { /* variable of index i is not the outermost */ Abounds[i] = Pbounds[i]; Bbounds[i] = Pbounds[i]; } } _fmpz_mod_mpoly_init_dense_mock(Ad, A, Abounds, ctx); _fmpz_mod_mpoly_init_dense_mock(Bd, B, Bbounds, ctx); fmpz_mod_poly_init(Pd, ctx->ffinfo); fmpz_mod_poly_mul(Pd, Ad, Bd, ctx->ffinfo); _from_dense(P, FLINT_MAX(A->bits, B->bits), Pbounds, Pd, ctx); fmpz_mod_poly_clear(Pd, ctx->ffinfo); _fmpz_mod_mpoly_clear_dense_mock(Ad); _fmpz_mod_mpoly_clear_dense_mock(Bd); success = 1; cleanup: TMP_END; return success; } int fmpz_mod_mpoly_mul_dense(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) { slong i; int success; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length < 1 || C->length < 1) { fmpz_mod_mpoly_zero(A, ctx); return 1; } if (B->bits > FLINT_BITS || C->bits > FLINT_BITS || ctx->minfo->nvars < 1) { return 0; } TMP_START; maxBfields = TMP_ARRAY_ALLOC(2*ctx->minfo->nfields, fmpz); maxCfields = maxBfields + ctx->minfo->nfields; for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); success = _fmpz_mod_mpoly_mul_dense_maxfields(A, B, maxBfields, C, maxCfields, ctx); for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return success; } flint-3.1.3/src/fmpz_mod_mpoly/mul_johnson.c000066400000000000000000000401411461254215100211540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "mpn_extras.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" #ifdef fmpz_mod_ctx_get_modulus_mpz_read_only # undef fmpz_mod_ctx_get_modulus_mpz_read_only #endif static inline void fmpz_mod_ctx_get_modulus_mpz_read_only(mpz_t m, const fmpz_mod_ctx_t ctx) { const fmpz * p = fmpz_mod_ctx_modulus(ctx); if (COEFF_IS_MPZ(*p)) { *m = *COEFF_TO_PTR(*p); } else { m->_mp_size = 1; m->_mp_alloc = 1; m->_mp_d = (mp_ptr) p; } } void _fmpz_mod_mpoly_mul_johnson1( fmpz_mod_mpoly_t A, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, ulong cmpmask, const fmpz_mod_ctx_t ctx) { slong n = fmpz_size(fmpz_mod_ctx_modulus(ctx)); slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; ulong exp; fmpz * Acoeffs = A->coeffs; ulong * Aexps = A->exps; slong Alen; mpz_t t, acc, modulus; mp_limb_t * Bcoeffs_packed = NULL; mp_limb_t * Ccoeffs_packed = NULL; TMP_INIT; TMP_START; mpz_init(t); mpz_init(acc); fmpz_mod_ctx_get_modulus_mpz_read_only(modulus, ctx); next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; if (Blen > 8*n) { Bcoeffs_packed = FLINT_ARRAY_ALLOC(n*(Blen + Clen), mp_limb_t); Ccoeffs_packed = Bcoeffs_packed + n*Blen; for (i = 0; i < Blen; i++) fmpz_get_ui_array(Bcoeffs_packed + n*i, n, Bcoeffs + i); for (i = 0; i < Clen; i++) fmpz_get_ui_array(Ccoeffs_packed + n*i, n, Ccoeffs + i); } /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Bexps[0] + Cexps[0], x); hind[0] = 2*1 + 0; Alen = 0; while (heap_len > 1) { exp = heap[1].exp; _fmpz_mod_mpoly_fit_length(&Acoeffs, &A->coeffs_alloc, &Aexps, &A->exps_alloc, 1, Alen + 1); Aexps[Alen] = exp; if (Bcoeffs_packed) { mp_limb_t * acc_d, * t_d; slong acc_len; FLINT_MPZ_REALLOC(acc, 2*n+1); FLINT_MPZ_REALLOC(t, 2*n); acc_d = acc->_mp_d; t_d = t->_mp_d; flint_mpn_zero(acc_d, 2*n+1); do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; hind[x->i] |= WORD(1); flint_mpn_mul_n(t_d, Bcoeffs_packed + n*x->i, Ccoeffs_packed + n*x->j, n); acc_d[2*n] += mpn_add_n(acc_d, acc_d, t_d, 2*n); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); acc_len = 2*n+1; MPN_NORM(acc_d, acc_len); acc->_mp_size = acc_len; } else { mpz_set_ui(acc, 0); do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { fmpz Bi = Bcoeffs[x->i]; fmpz Cj = Ccoeffs[x->j]; *store++ = x->i; *store++ = x->j; hind[x->i] |= WORD(1); if (COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Cj)) { mpz_addmul(acc, COEFF_TO_PTR(Bi), COEFF_TO_PTR(Cj)); } else if (COEFF_IS_MPZ(Bi) && !COEFF_IS_MPZ(Cj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Bi), Cj); } else if (!COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Cj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Cj), Bi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Bi, Cj); flint_mpz_add_uiui(acc, acc, pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } mpz_tdiv_qr(t, _fmpz_promote(Acoeffs + Alen), acc, modulus); _fmpz_demote_val(Acoeffs + Alen); Alen += !fmpz_is_zero(Acoeffs + Alen); while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ((i + 1 < Blen) && (hind[i + 1] == 2*j + 1)) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Cexps[x->j], x, &next_loc, &heap_len, cmpmask); } /* should we go up? */ if ((j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1))) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Cexps[x->j], x, &next_loc, &heap_len, cmpmask); } } } A->coeffs = Acoeffs; A->exps = Aexps; A->length = Alen; mpz_clear(t); mpz_clear(acc); flint_free(Bcoeffs_packed); TMP_END; } void _fmpz_mod_mpoly_mul_johnson( fmpz_mod_mpoly_t A, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fmpz_mod_ctx_t ctx) { slong n = fmpz_size(fmpz_mod_ctx_modulus(ctx)); slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; ulong * exps; ulong ** exp_list; slong exp_next; slong * hind; fmpz * Acoeffs = A->coeffs; ulong * Aexps = A->exps; slong Alen; mpz_t t, acc, modulus; mp_limb_t * Bcoeffs_packed = NULL; mp_limb_t * Ccoeffs_packed = NULL; TMP_INIT; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); FLINT_ASSERT(A->bits == bits); if (N == 1) { _fmpz_mod_mpoly_mul_johnson1(A, Bcoeffs, Bexps, Blen, Ccoeffs, Cexps, Clen, cmpmask[0], ctx); return; } TMP_START; mpz_init(t); mpz_init(acc); fmpz_mod_ctx_get_modulus_mpz_read_only(modulus, ctx); next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) { exp_list[i] = exps + i*N; hind[i] = 1; } if (Blen > 8*n) { Bcoeffs_packed = FLINT_ARRAY_ALLOC(n*(Blen + Clen), mp_limb_t); Ccoeffs_packed = Bcoeffs_packed + n*Blen; for (i = 0; i < Blen; i++) fmpz_get_ui_array(Bcoeffs_packed + n*i, n, Bcoeffs + i); for (i = 0; i < Clen; i++) fmpz_get_ui_array(Ccoeffs_packed + n*i, n, Ccoeffs + i); } /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_add_mp(heap[1].exp, Bexps + N*0, Cexps + N*0, N); hind[0] = 2*1 + 0; Alen = 0; while (heap_len > 1) { _fmpz_mod_mpoly_fit_length(&Acoeffs, &A->coeffs_alloc, &Aexps, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexps + N*Alen, heap[1].exp, N); if (Bcoeffs_packed) { mp_limb_t * acc_d, * t_d; slong acc_len; FLINT_MPZ_REALLOC(acc, 2*n+1); FLINT_MPZ_REALLOC(t, 2*n); acc_d = acc->_mp_d; t_d = t->_mp_d; flint_mpn_zero(acc_d, 2*n+1); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; hind[x->i] |= WORD(1); flint_mpn_mul_n(t_d, Bcoeffs_packed + n*x->i, Ccoeffs_packed + n*x->j, n); acc_d[2*n] += mpn_add_n(acc_d, acc_d, t_d, 2*n); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, Aexps + N*Alen, N)); acc_len = 2*n+1; MPN_NORM(acc_d, acc_len); acc->_mp_size = acc_len; } else { mpz_set_ui(acc, 0); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { fmpz Bi, Cj; *store++ = x->i; *store++ = x->j; Bi = Bcoeffs[x->i]; Cj = Ccoeffs[x->j]; hind[x->i] |= WORD(1); if (COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Cj)) { mpz_addmul(acc, COEFF_TO_PTR(Bi), COEFF_TO_PTR(Cj)); } else if (COEFF_IS_MPZ(Bi) && !COEFF_IS_MPZ(Cj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Bi), Cj); } else if (!COEFF_IS_MPZ(Bi) && COEFF_IS_MPZ(Cj)) { flint_mpz_addmul_ui(acc, COEFF_TO_PTR(Cj), Bi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Bi, Cj); flint_mpz_add_uiui(acc, acc, pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, Aexps + N*Alen, N)); } mpz_tdiv_qr(t, _fmpz_promote(Acoeffs + Alen), acc, modulus); _fmpz_demote_val(Acoeffs + Alen); Alen += !fmpz_is_zero(Acoeffs + Alen); while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ((i + 1 < Blen) && (hind[i + 1] == 2*j + 1)) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Cexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ((j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1))) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Cexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } A->coeffs = Acoeffs; A->exps = Aexps; A->length = Alen; mpz_clear(t); mpz_clear(acc); flint_free(Bcoeffs_packed); TMP_END; } void _fmpz_mod_mpoly_mul_johnson_maxfields( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, fmpz * maxBfields, const fmpz_mod_mpoly_t C, fmpz * maxCfields, const fmpz_mod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t Abits; ulong * cmpmask; ulong * Bexps = B->exps, * Cexps = C->exps; int freeBexps = 0, freeCexps = 0; fmpz_mod_mpoly_struct * P, T[1]; TMP_INIT; FLINT_ASSERT(B->length > 0 && C->length > 0); TMP_START; _fmpz_vec_add(maxBfields, maxBfields, maxCfields, ctx->minfo->nfields); Abits = 1 + _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); Abits = FLINT_MAX(Abits, B->bits); Abits = FLINT_MAX(Abits, C->bits); Abits = mpoly_fix_bits(Abits, ctx->minfo); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); /* ensure input exponents are packed into same sized fields as output */ if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fmpz_mod_mpoly_init(T, ctx); P = T; } else { P = A; } fmpz_mod_mpoly_fit_length_reset_bits(P, B->length + C->length, Abits, ctx); if (B->length > C->length) { _fmpz_mod_mpoly_mul_johnson(P, C->coeffs, Cexps, C->length, B->coeffs, Bexps, B->length, Abits, N, cmpmask, ctx->ffinfo); } else { _fmpz_mod_mpoly_mul_johnson(P, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, Abits, N, cmpmask, ctx->ffinfo); } if (A == B || A == C) { fmpz_mod_mpoly_swap(A, T, ctx); fmpz_mod_mpoly_clear(T, ctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } void fmpz_mod_mpoly_mul_johnson( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length < 1 || C->length < 1) { fmpz_mod_mpoly_zero(A, ctx); return; } TMP_START; maxBfields = TMP_ARRAY_ALLOC(2*ctx->minfo->nfields, fmpz); maxCfields = maxBfields + ctx->minfo->nfields; for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); _fmpz_mod_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); for (i = 0; i < 2*ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/neg.c000066400000000000000000000017061461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_neg(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong Blen = B->length; if (A != B) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, Blen, B->bits, ctx); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } _fmpz_mod_vec_neg(A->coeffs, B->coeffs, Blen, ctx->ffinfo); _fmpz_mod_mpoly_set_length(A, B->length, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/pow_fmpz.c000066400000000000000000000037731461254215100204740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_pow_fmpz(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t k, const fmpz_mod_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields; flint_bitcnt_t exp_bits; TMP_INIT; if (fmpz_sgn(k) < 0) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_pow_fmpz: power is negative"); if (fmpz_fits_si(k)) return fmpz_mod_mpoly_pow_ui(A, B, fmpz_get_ui(k), ctx); /* we are raising a polynomial to an unreasonable exponent It must either be zero or a monomial with unit coefficient */ if (B->length == 0) { fmpz_mod_mpoly_zero(A, ctx); return 1; } if (B->length != 1) return 0; TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_fmpz(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = 1 + _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, 1, exp_bits, ctx); fmpz_mod_pow_fmpz(A->coeffs + 0, B->coeffs + 0, k, ctx->ffinfo); mpoly_pack_vec_fmpz(A->exps + 0, maxBfields, exp_bits, ctx->minfo->nfields, 1); _fmpz_mod_mpoly_set_length(A, !fmpz_is_zero(A->coeffs + 0), ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/fmpz_mod_mpoly/pow_rmul.c000066400000000000000000000017121461254215100204660ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_pow_rmul(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong k, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init(T, ctx); if (A == B) { fmpz_mod_mpoly_pow_rmul(T, A, k, ctx); fmpz_mod_mpoly_swap(T, A, ctx); goto cleanup; } fmpz_mod_mpoly_one(A, ctx); while (k >= 1) { fmpz_mod_mpoly_mul(T, A, B, ctx); fmpz_mod_mpoly_swap(A, T, ctx); k -= 1; } cleanup: fmpz_mod_mpoly_clear(T, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/pow_ui.c000066400000000000000000000036601461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_pow_ui( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong k, const fmpz_mod_mpoly_ctx_t ctx) { slong i, exp_bits; fmpz * maxBfields; TMP_INIT; if (k == 0) { fmpz_mod_mpoly_one(A, ctx); return 1; } if (B->length == 0) { fmpz_mod_mpoly_zero(A, ctx); return 1; } if (k == 1) { fmpz_mod_mpoly_set(A, B, ctx); return 1; } if (k == 2) { fmpz_mod_mpoly_mul(A, B, B, ctx); return 1; } if (B->length != 1) { fmpz_mod_mpoly_pow_rmul(A, B, k, ctx); return 1; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_ui(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, 1, exp_bits, ctx); fmpz_mod_pow_ui(A->coeffs + 0, B->coeffs + 0, k, ctx->ffinfo); mpoly_pack_vec_fmpz(A->exps + 0, maxBfields, exp_bits, ctx->minfo->nfields, 1); _fmpz_mod_mpoly_set_length(A, !fmpz_is_zero(A->coeffs + 0), ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/fmpz_mod_mpoly/profile/000077500000000000000000000000001461254215100201155ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_mpoly/profile/p-gcd.c000066400000000000000000000273661461254215100212710ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" slong count = 0; slong total_super = 0; void profile_gcd( const fmpz_mod_mpoly_t realG, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { fmpz_mod_mpoly_t G; timeit_t timer; slong hensel = -1, brown = -1, zippel = -1, zippel2 = -1, super = -1; fmpz_mod_mpoly_init(G, ctx); if (algo & MPOLY_GCD_USE_BROWN) { fmpz_mod_mpoly_add(G, A, B, ctx); timeit_start(timer); fmpz_mod_mpoly_gcd_brown(G, A, B, ctx); timeit_stop(timer); brown = timer->wall; if (!fmpz_mod_mpoly_equal(G, realG, ctx)) { flint_printf("brown is wrong\n"); flint_abort(); } } flint_printf("%10wd ", brown); fflush(stdout); if (algo & MPOLY_GCD_USE_HENSEL) { fmpz_mod_mpoly_add(G, A, B, ctx); timeit_start(timer); fmpz_mod_mpoly_gcd_hensel(G, A, B, ctx); timeit_stop(timer); hensel = timer->wall; if (!fmpz_mod_mpoly_equal(G, realG, ctx)) { flint_printf("hensel is wrong\n"); flint_abort(); } } flint_printf("%10wd ", hensel); fflush(stdout); if (algo & MPOLY_GCD_USE_ZIPPEL2) { fmpz_mod_mpoly_add(G, A, B, ctx); timeit_start(timer); fmpz_mod_mpoly_gcd_zippel2(G, A, B, ctx); timeit_stop(timer); zippel2 = timer->wall; if (!fmpz_mod_mpoly_equal(G, realG, ctx)) { flint_printf("zippel2 is wrong\n"); flint_abort(); } } flint_printf("%10wd ", zippel2); fflush(stdout); if (0 && algo & MPOLY_GCD_USE_ZIPPEL) { fmpz_mod_mpoly_add(G, A, B, ctx); timeit_start(timer); fmpz_mod_mpoly_gcd_zippel(G, A, B, ctx); timeit_stop(timer); zippel = timer->wall; if (!fmpz_mod_mpoly_equal(G, realG, ctx)) { flint_printf("zippel is wrong\n"); flint_abort(); } } flint_printf("%10wd ", zippel); fflush(stdout); { fmpz_mod_mpoly_add(G, A, B, ctx); timeit_start(timer); fmpz_mod_mpoly_gcd(G, A, B, ctx); timeit_stop(timer); super = timer->wall; if (!fmpz_mod_mpoly_equal(G, realG, ctx)) { flint_printf("super is wrong\n"); flint_abort(); } } count++; flint_printf("%10wd #%wd\n", super, count); fflush(stdout); total_super += super; fmpz_mod_mpoly_clear(G, ctx); } void print_banner(void) { flint_printf("| brown | hensel | zippel2 | zippel | super |\n"); flint_printf("+----------+----------+----------+----------+----------+\n"); } int main(int argc, char *argv[]) { slong i, j; const char * vars[] = {"x", "y", "z", "t" ,"u", "v", "w", "s", "p"}; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fmpz_pow_ui(p, p, 70); fmpz_nextprime(p, p, 1); print_banner(); for (i = 3; i <= 10; i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t g, a, b, t; fmpz_mod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_one(a, ctx); fmpz_mod_mpoly_one(b, ctx); for (j = 0; j < i; j++) { fmpz_mod_mpoly_gen(t, j, ctx); fmpz_mod_mpoly_add_si(t, t, 1, ctx); fmpz_mod_mpoly_mul(g, g, t, ctx); fmpz_mod_mpoly_gen(t, j, ctx); fmpz_mod_mpoly_sub_si(t, t, 2, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_gen(t, j, ctx); fmpz_mod_mpoly_add_si(t, t, 2, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); } fmpz_mod_mpoly_sub_si(g, g, 2, ctx); fmpz_mod_mpoly_add_si(a, a, 2, ctx); fmpz_mod_mpoly_sub_si(b, b, 2, ctx); fmpz_mod_mpoly_mul(a, a, g, ctx); fmpz_mod_mpoly_mul(b, b, g, ctx); fmpz_mod_mpoly_make_monic(g, g, ctx); profile_gcd(g, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 50; i < 100; i += 4) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, t, m; fmpz_mod_mpoly_ctx_init(ctx, 2, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_mod_mpoly_set_str_pretty(a, "1+x+y", vars, ctx); fmpz_mod_mpoly_pow_ui(a, a, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "x", vars, ctx); fmpz_mod_mpoly_add(a, a, m, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1-2*x-y", vars, ctx); fmpz_mod_mpoly_pow_ui(b, b, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "y", vars, ctx); fmpz_mod_mpoly_add(b, b, m, ctx); fmpz_mod_mpoly_set_str_pretty(t, "2-x+y", vars, ctx); fmpz_mod_mpoly_pow_ui(t, t, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "x-y", vars, ctx); fmpz_mod_mpoly_add(t, t, m, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 5; i < 15; i += 1) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, t, m; fmpz_mod_mpoly_ctx_init(ctx, 2, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_mod_mpoly_set_str_pretty(a, "1+x^31+y^51", vars, ctx); fmpz_mod_mpoly_pow_ui(a, a, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "x^7", vars, ctx); fmpz_mod_mpoly_add(a, a, m, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1-2*x^23-y^47", vars, ctx); fmpz_mod_mpoly_pow_ui(b, b, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "y^9", vars, ctx); fmpz_mod_mpoly_add(b, b, m, ctx); fmpz_mod_mpoly_set_str_pretty(t, "2-x^39+y^24", vars, ctx); fmpz_mod_mpoly_pow_ui(t, t, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "x^6*y^7", vars, ctx); fmpz_mod_mpoly_add(t, t, m, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 15; i < 30; i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, t, m; fmpz_mod_mpoly_ctx_init(ctx, 3, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_mod_mpoly_set_str_pretty(a, "1+x+y+z", vars, ctx); fmpz_mod_mpoly_pow_ui(a, a, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "x", vars, ctx); fmpz_mod_mpoly_add(a, a, m, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1-2*x-y+z", vars, ctx); fmpz_mod_mpoly_pow_ui(b, b, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "y", vars, ctx); fmpz_mod_mpoly_add(b, b, m, ctx); fmpz_mod_mpoly_set_str_pretty(t, "3+x+y-2*z", vars, ctx); fmpz_mod_mpoly_pow_ui(t, t, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "z", vars, ctx); fmpz_mod_mpoly_add(t, t, m, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_ALL); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 1; i < 7; i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, t, m; fmpz_mod_mpoly_ctx_init(ctx, 7, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_mod_mpoly_set_str_pretty(a, "1+x+y+z+t+u+2*v+w", vars, ctx); fmpz_mod_mpoly_pow_ui(a, a, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "x", vars, ctx); fmpz_mod_mpoly_add(a, a, m, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1-2*x-y+z+t+u+v+w", vars, ctx); fmpz_mod_mpoly_pow_ui(b, b, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "y", vars, ctx); fmpz_mod_mpoly_add(b, b, m, ctx); fmpz_mod_mpoly_set_str_pretty(t, "1+x+y+z-t-u+v+3*w", vars, ctx); fmpz_mod_mpoly_pow_ui(t, t, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "z", vars, ctx); fmpz_mod_mpoly_add(t, t, m, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_HENSEL | MPOLY_GCD_USE_ZIPPEL2); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 1; i < 5; i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, t, m; fmpz_mod_mpoly_ctx_init(ctx, 9, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_mod_mpoly_set_str_pretty(a, "1+x+y+z+t+u+2*v+w+s-p", vars, ctx); fmpz_mod_mpoly_pow_ui(a, a, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "x", vars, ctx); fmpz_mod_mpoly_add(a, a, m, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1-2*x-y+z+t+u+v+w-2*s+p", vars, ctx); fmpz_mod_mpoly_pow_ui(b, b, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "y", vars, ctx); fmpz_mod_mpoly_add(b, b, m, ctx); fmpz_mod_mpoly_set_str_pretty(t, "1+x+y+z-t-u+v+3*w+2*s-3*p", vars, ctx); fmpz_mod_mpoly_pow_ui(t, t, i, ctx); fmpz_mod_mpoly_set_str_pretty(m, "z", vars, ctx); fmpz_mod_mpoly_add(t, t, m, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_HENSEL | MPOLY_GCD_USE_ZIPPEL2); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } flint_printf("--------------------\n"); flint_printf("total time: %wd\n", total_super); flint_printf(" record: 25312\n"); fmpz_clear(p); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz_mod_mpoly/push_term_fmpz_fmpz.c000066400000000000000000000060451461254215100227240ustar00rootroot00000000000000/* Copyright (C) 2020, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void _fmpz_mod_mpoly_push_exp_ffmpz( fmpz_mod_mpoly_t A, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ffmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void _fmpz_mod_mpoly_push_exp_pfmpz( fmpz_mod_mpoly_t A, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_pfmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void fmpz_mod_mpoly_push_term_fmpz_fmpz( fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_pfmpz(A, exp, ctx); fmpz_mod_set_fmpz(A->coeffs + A->length - 1, c, ctx->ffinfo); } void fmpz_mod_mpoly_push_term_ui_fmpz( fmpz_mod_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_pfmpz(A, exp, ctx); fmpz_mod_set_ui(A->coeffs + A->length - 1, c, ctx->ffinfo); } void fmpz_mod_mpoly_push_term_si_fmpz( fmpz_mod_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_pfmpz(A, exp, ctx); fmpz_mod_set_si(A->coeffs + A->length - 1, c, ctx->ffinfo); } void fmpz_mod_mpoly_push_term_fmpz_ffmpz( fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_mod_set_fmpz(A->coeffs + A->length - 1, c, ctx->ffinfo); } void fmpz_mod_mpoly_push_term_ui_ffmpz( fmpz_mod_mpoly_t A, ulong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_mod_set_ui(A->coeffs + A->length - 1, c, ctx->ffinfo); } void fmpz_mod_mpoly_push_term_si_ffmpz( fmpz_mod_mpoly_t A, slong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_mod_set_si(A->coeffs + A->length - 1, c, ctx->ffinfo); } flint-3.1.3/src/fmpz_mod_mpoly/push_term_fmpz_ui.c000066400000000000000000000033271461254215100223650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void _fmpz_mod_mpoly_push_exp_ui( fmpz_mod_mpoly_t A, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ui(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void fmpz_mod_mpoly_push_term_fmpz_ui( fmpz_mod_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_ui(A, exp, ctx); fmpz_mod_set_fmpz(A->coeffs + A->length - 1, c, ctx->ffinfo); } void fmpz_mod_mpoly_push_term_ui_ui( fmpz_mod_mpoly_t A, ulong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_ui(A, exp, ctx); fmpz_mod_set_ui(A->coeffs + A->length - 1, c, ctx->ffinfo); } void fmpz_mod_mpoly_push_term_si_ui( fmpz_mod_mpoly_t A, slong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { _fmpz_mod_mpoly_push_exp_ui(A, exp, ctx); fmpz_mod_set_si(A->coeffs + A->length - 1, c, ctx->ffinfo); } flint-3.1.3/src/fmpz_mod_mpoly/quadratic_root.c000066400000000000000000000045041461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz_mod.h" #include "nmod_mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_quadratic_root( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success; if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_zero(Q, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(A, ctx)) { return fmpz_mod_mpoly_sqrt(Q, B, ctx); } if (fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))) { nmod_mpoly_ctx_t nctx; nmod_mpoly_t nQ, nA, nB; nctx->minfo[0] = ctx->minfo[0]; nmod_init(&nctx->mod, fmpz_get_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); nmod_mpoly_init(nQ, nctx); nmod_mpoly_init(nA, nctx); nmod_mpoly_init(nB, nctx); _fmpz_mod_mpoly_get_nmod_mpoly(nA, nctx, A, ctx); _fmpz_mod_mpoly_get_nmod_mpoly(nB, nctx, B, ctx); success = nmod_mpoly_quadratic_root(nQ, nA, nB, nctx); _fmpz_mod_mpoly_set_nmod_mpoly(Q, ctx, nQ, nctx); nmod_mpoly_clear(nA, nctx); nmod_mpoly_clear(nQ, nctx); nmod_mpoly_clear(nB, nctx); return success; } else { fmpz_t c, c2; fmpz_mod_mpoly_t t1, t2; fmpz_init(c); fmpz_init(c2); FLINT_ASSERT(fmpz_is_odd(fmpz_mod_ctx_modulus(ctx->ffinfo))); fmpz_fdiv_q_2exp(c, fmpz_mod_ctx_modulus(ctx->ffinfo), 1); fmpz_mod_mul(c2, c, c, ctx->ffinfo); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); fmpz_mod_mpoly_mul(t1, A, A, ctx); fmpz_mod_mpoly_scalar_addmul_fmpz(t2, B, t1, c2, ctx); success = fmpz_mod_mpoly_sqrt(t1, t2, ctx); if (success) fmpz_mod_mpoly_scalar_addmul_fmpz(Q, t1, A, c, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_clear(c); fmpz_clear(c2); return success; } } flint-3.1.3/src/fmpz_mod_mpoly/randtest_bits.c000066400000000000000000000026511461254215100214720ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_randtest_bits(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j, nvars = ctx->minfo->nvars; fmpz * exp; TMP_INIT; TMP_START; exp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exp + j); fmpz_mod_mpoly_zero(A, ctx); fmpz_mod_mpoly_fit_length_reset_bits(A, 0, MPOLY_MIN_BITS, ctx); for (i = 0; i < length; i++) { mpoly_monomial_randbits_fmpz(exp, state, exp_bits, ctx->minfo); _fmpz_mod_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_randm(A->coeffs + A->length - 1, state, fmpz_mod_ctx_modulus(ctx->ffinfo)); } fmpz_mod_mpoly_sort_terms(A, ctx); fmpz_mod_mpoly_combine_like_terms(A, ctx); for (j = 0; j < nvars; j++) fmpz_clear(exp + j); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/randtest_bound.c000066400000000000000000000023411461254215100216340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_randtest_bound(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); fmpz_mod_mpoly_zero(A, ctx); fmpz_mod_mpoly_fit_length_reset_bits(A, 0, MPOLY_MIN_BITS, ctx); for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bound); _fmpz_mod_mpoly_push_exp_ui(A, exp, ctx); fmpz_randm(A->coeffs + A->length - 1, state, fmpz_mod_ctx_modulus(ctx->ffinfo)); } fmpz_mod_mpoly_sort_terms(A, ctx); fmpz_mod_mpoly_combine_like_terms(A, ctx); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/randtest_bounds.c000066400000000000000000000023461461254215100220240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_randtest_bounds(fmpz_mod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); fmpz_mod_mpoly_zero(A, ctx); fmpz_mod_mpoly_fit_length_reset_bits(A, 0, MPOLY_MIN_BITS, ctx); for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bounds[j]); _fmpz_mod_mpoly_push_exp_ui(A, exp, ctx); fmpz_randm(A->coeffs + A->length - 1, state, fmpz_mod_ctx_modulus(ctx->ffinfo)); } fmpz_mod_mpoly_sort_terms(A, ctx); fmpz_mod_mpoly_combine_like_terms(A, ctx); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/repack_bits.c000066400000000000000000000041111461254215100211040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_repack_bits( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx) { int success; Abits = mpoly_fix_bits(Abits, ctx->minfo); if (B->bits == Abits || B->length == 0) { fmpz_mod_mpoly_set(A, B, ctx); return 1; } if (A == B) return fmpz_mod_mpoly_repack_bits_inplace(A, Abits, ctx); fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); success = mpoly_repack_monomials(A->exps, Abits, B->exps, B->bits, B->length, ctx->minfo); if (success) { _fmpz_vec_set(A->coeffs, B->coeffs, B->length); A->length = B->length; } else { A->length = 0; } return success; } int fmpz_mod_mpoly_repack_bits_inplace( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx) { int success; ulong * texps; slong talloc; slong N = mpoly_words_per_exp(Abits, ctx->minfo); if (A->bits == Abits) { return 1; } if (A->length < 1) { A->bits = Abits; return 1; } N = mpoly_words_per_exp(Abits, ctx->minfo); talloc = N*A->length; texps = FLINT_ARRAY_ALLOC(talloc, ulong); success = mpoly_repack_monomials(texps, Abits, A->exps, A->bits, A->length, ctx->minfo); A->bits = Abits; if (success) { flint_free(A->exps); A->exps = texps; A->exps_alloc = talloc; } else { flint_free(texps); A->length = 0; } return success; } flint-3.1.3/src/fmpz_mod_mpoly/resize.c000066400000000000000000000024011461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_vec.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_resize(fmpz_mod_mpoly_t A, slong new_length, const fmpz_mod_mpoly_ctx_t ctx) { slong old_length = A->length; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); new_length = FLINT_MAX(WORD(0), new_length); if (new_length > old_length) { fmpz_mod_mpoly_fit_length(A, new_length, ctx); /* must zero out the new coeffs/exps past the old end */ flint_mpn_zero(A->exps + N*old_length, N*(new_length - old_length)); _fmpz_vec_zero(A->coeffs + old_length, new_length - old_length); } else if (new_length < old_length) { /* just zero out the extra unused fmpz's past the new end */ _fmpz_vec_zero(A->coeffs + new_length, old_length - new_length); } A->length = new_length; } flint-3.1.3/src/fmpz_mod_mpoly/resultant.c000066400000000000000000000017111461254215100206420ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_resultant(fmpz_mod_mpoly_t R, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { int success; fmpz_mod_mpoly_univar_t Ax, Bx; fmpz_mod_mpoly_univar_init(Ax, ctx); fmpz_mod_mpoly_univar_init(Bx, ctx); fmpz_mod_mpoly_to_univar(Ax, A, var, ctx); fmpz_mod_mpoly_to_univar(Bx, B, var, ctx); success = fmpz_mod_mpoly_univar_resultant(R, Ax, Bx, ctx); fmpz_mod_mpoly_univar_clear(Ax, ctx); fmpz_mod_mpoly_univar_clear(Bx, ctx); return success; } flint-3.1.3/src/fmpz_mod_mpoly/scalar_addmul_fmpz.c000066400000000000000000000136551461254215100224620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static slong _fmpz_mod_mpoly_scalar_addmul_fmpz_mod1( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, const fmpz_t d, ulong cmpmask, const fmpz_mod_ctx_t fctx) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { if ((Bexps[i]^cmpmask) > (Cexps[j]^cmpmask)) { Aexps[k] = Bexps[i]; fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if ((Bexps[i]^cmpmask) == (Cexps[j]^cmpmask)) { Aexps[k] = Bexps[i]; fmpz_mod_addmul(Acoeffs + k, Bcoeffs + i, Ccoeffs + j, d, fctx); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { Aexps[k] = Cexps[j]; fmpz_mod_mul(Acoeffs + k, Ccoeffs + j, d, fctx); k += !fmpz_is_zero(Acoeffs + k); j++; } } while (i < Blen) { Aexps[k] = Bexps[i]; fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { Aexps[k] = Cexps[j]; fmpz_mod_mul(Acoeffs + k, Ccoeffs + j, d, fctx); k += !fmpz_is_zero(Acoeffs + k); j++; } return k; } static slong _fmpz_mod_mpoly_scalar_addmul_fmpz_mod( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, const fmpz_t d, slong N, const ulong * cmpmask, const fmpz_mod_ctx_t fctx) { slong i = 0, j = 0, k = 0; if (N == 1) { return _fmpz_mod_mpoly_scalar_addmul_fmpz_mod1(Acoeffs, Aexps, Bcoeffs, Bexps, Blen, Ccoeffs, Cexps, Clen, d, cmpmask[0], fctx); } while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_mod_addmul(Acoeffs + k, Bcoeffs + i, Ccoeffs + j, d, fctx); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_mod_mul(Acoeffs + k, Ccoeffs + j, d, fctx); k += !fmpz_is_zero(Acoeffs + k); j++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_mod_mul(Acoeffs + k, Ccoeffs + j, d, fctx); k += !fmpz_is_zero(Acoeffs + k); j++; } return k; } void fmpz_mod_mpoly_scalar_addmul_fmpz( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_t d, const fmpz_mod_mpoly_ctx_t ctx) { slong Abits, N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; fmpz_t dd; TMP_INIT; if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_scalar_mul_fmpz(A, C, d, ctx); return; } if (fmpz_mod_mpoly_is_zero(C, ctx)) { fmpz_mod_mpoly_set(A, B, ctx); return; } fmpz_init(dd); fmpz_mod_set_fmpz(dd, d, ctx->ffinfo); if (fmpz_is_zero(dd)) { fmpz_mod_mpoly_set(A, B, ctx); fmpz_clear(dd); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init3(T, B->length + C->length, Abits, ctx); T->length = _fmpz_mod_mpoly_scalar_addmul_fmpz_mod(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, dd, N, cmpmask, ctx->ffinfo); fmpz_mod_mpoly_swap(A, T, ctx); fmpz_mod_mpoly_clear(T, ctx); } else { fmpz_mod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _fmpz_mod_mpoly_scalar_addmul_fmpz_mod(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, dd, N, cmpmask, ctx->ffinfo); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; fmpz_clear(dd); } flint-3.1.3/src/fmpz_mod_mpoly/scalar_mul_fmpz.c000066400000000000000000000062471461254215100220100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* c is assumed to be reduced and invertible mod n */ void fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong N, Blen = B->length; FLINT_ASSERT(fmpz_mod_is_invertible(c, ctx->ffinfo)); if (A != B) { fmpz_mod_mpoly_fit_length_reset_bits(A, Blen, B->bits, ctx); A->length = Blen; N = mpoly_words_per_exp(B->bits, ctx->minfo); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } _fmpz_mod_vec_scalar_mul_fmpz_mod(A->coeffs, B->coeffs, Blen, c, ctx->ffinfo); } /* c is assumed to be reduced mod n */ void fmpz_mod_mpoly_scalar_mul_fmpz_mod( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N; slong Alen; slong Blen = B->length; ulong * Aexp; const ulong * Bexp; fmpz * Acoeff; const fmpz * Bcoeff; if (fmpz_is_zero(c) || Blen < 1) { fmpz_mod_mpoly_zero(A, ctx); return; } if (fmpz_is_one(c) || (Blen > 10 && fmpz_mod_is_invertible(c, ctx->ffinfo))) { fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(A, B, c, ctx); return; } N = mpoly_words_per_exp(B->bits, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); Aexp = A->exps; Bexp = B->exps; Acoeff = A->coeffs; Bcoeff = B->coeffs; Alen = 0; for (i = 0; i < Blen; i++) { mpoly_monomial_set(Aexp + N*Alen, Bexp + N*i, N); fmpz_mod_mul(Acoeff + Alen, Bcoeff + i, c, ctx->ffinfo); Alen += !fmpz_is_zero(Acoeff + Alen); } A->length = Alen; } void fmpz_mod_mpoly_scalar_mul_fmpz( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_is_canonical(c, ctx->ffinfo)) { fmpz_mod_mpoly_scalar_mul_fmpz_mod(A, B, c, ctx); } else { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_fmpz(cc, c, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } } void fmpz_mod_mpoly_scalar_mul_ui( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_ui(cc, c, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } void fmpz_mod_mpoly_scalar_mul_si( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_si(cc, c, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } flint-3.1.3/src/fmpz_mod_mpoly/set.c000066400000000000000000000015731461254215100174220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_set( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); if (A == B) return; fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); _fmpz_vec_set(A->coeffs, B->coeffs, B->length); mpoly_copy_monomials(A->exps, B->exps, B->length, N); _fmpz_mod_mpoly_set_length(A, B->length, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/set_coeff_fmpz_fmpz.c000066400000000000000000000070361461254215100226540ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void _fmpz_mod_mpoly_set_coeff_fmpz_fmpz( fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t exp_bits; slong i, N, index; ulong * cmpmask; ulong * packed_exp; int exists; fmpz_t C; TMP_INIT; TMP_START; fmpz_init(C); fmpz_mod_set_fmpz(C, c, ctx->ffinfo); exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, A->bits, ctx->minfo); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, A->bits, ctx->minfo); exists = mpoly_monomial_exists(&index, A->exps, packed_exp, A->length, N, cmpmask); if (!exists) { if (!fmpz_is_zero(C)) /* make new term only if coeff is nonzero*/ { fmpz_mod_mpoly_fit_length(A, A->length + 1, ctx); for (i = A->length; i >= index + 1; i--) { fmpz_set(A->coeffs + i, A->coeffs + i - 1); mpoly_monomial_set(A->exps + N*i, A->exps + N*(i - 1), N); } fmpz_swap(A->coeffs + index, C); mpoly_monomial_set(A->exps + N*index, packed_exp, N); A->length++; } } else if (fmpz_is_zero(C)) /* zero coeff, remove term */ { for (i = index; i < A->length - 1; i++) { fmpz_set(A->coeffs + i, A->coeffs + i + 1); mpoly_monomial_set(A->exps + N*i, A->exps + N*(i + 1), N); } A->length--; } else /* term with that monomial exists, coeff is nonzero */ { fmpz_swap(A->coeffs + index, C); } fmpz_clear(C); TMP_END; } void fmpz_mod_mpoly_set_coeff_fmpz_fmpz( fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = TMP_ALLOC(nvars * sizeof(fmpz)); for (i = 0; i < nvars; i++) newexp[i] = *exp[i]; /* GCC really wants to complain about this one */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif _fmpz_mod_mpoly_set_coeff_fmpz_fmpz(A, c, newexp, ctx); #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif TMP_END; } void fmpz_mod_mpoly_set_coeff_ui_fmpz(fmpz_mod_mpoly_t poly, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init_set_ui(C, c); fmpz_mod_mpoly_set_coeff_fmpz_fmpz(poly, C, exp, ctx); fmpz_clear(C); } void fmpz_mod_mpoly_set_coeff_si_fmpz(fmpz_mod_mpoly_t poly, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init_set_si(C, c); fmpz_mod_mpoly_set_coeff_fmpz_fmpz(poly, C, exp, ctx); fmpz_clear(C); } flint-3.1.3/src/fmpz_mod_mpoly/set_coeff_fmpz_monomial.c000066400000000000000000000021541461254215100235070ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_set_coeff_fmpz_monomial(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * texps; TMP_INIT; if (M->length != 1) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_set_coeff_fmpz_monomial: M not monomial"); TMP_START; texps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init(texps + i); mpoly_get_monomial_ffmpz(texps, M->exps + 0, M->bits, ctx->minfo); _fmpz_mod_mpoly_set_coeff_fmpz_fmpz(A, c, texps, ctx); for (i = 0; i < nvars; i++) fmpz_clear(texps + i); TMP_END; return; } flint-3.1.3/src/fmpz_mod_mpoly/set_coeff_fmpz_ui.c000066400000000000000000000026411461254215100223120ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_set_coeff_fmpz_ui(fmpz_mod_mpoly_t poly, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); _fmpz_mod_mpoly_set_coeff_fmpz_fmpz(poly, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } void fmpz_mod_mpoly_set_coeff_ui_ui(fmpz_mod_mpoly_t poly, ulong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init_set_ui(C, c); fmpz_mod_mpoly_set_coeff_fmpz_ui(poly, C, exp, ctx); fmpz_clear(C); } void fmpz_mod_mpoly_set_coeff_si_ui(fmpz_mod_mpoly_t poly, slong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t C; fmpz_init_set_si(C, c); fmpz_mod_mpoly_set_coeff_fmpz_ui(poly, C, exp, ctx); fmpz_clear(C); } flint-3.1.3/src/fmpz_mod_mpoly/set_fmpz.c000066400000000000000000000035521461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_set_fmpz_mod( fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_is_canonical(c, ctx->ffinfo)); fmpz_mod_mpoly_fit_length(A, 1, ctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, ctx->minfo)); fmpz_set(A->coeffs + 0, c); _fmpz_mod_mpoly_set_length(A, !fmpz_is_zero(A->coeffs + 0), ctx); } void fmpz_mod_mpoly_set_fmpz( fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_fit_length(A, 1, ctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, ctx->minfo)); fmpz_mod_set_fmpz(A->coeffs + 0, c, ctx->ffinfo); _fmpz_mod_mpoly_set_length(A, !fmpz_is_zero(A->coeffs + 0), ctx); } void fmpz_mod_mpoly_set_ui( fmpz_mod_mpoly_t A, ulong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_fit_length(A, 1, ctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, ctx->minfo)); fmpz_mod_set_ui(A->coeffs + 0, c, ctx->ffinfo); _fmpz_mod_mpoly_set_length(A, !fmpz_is_zero(A->coeffs + 0), ctx); } void fmpz_mod_mpoly_set_si( fmpz_mod_mpoly_t A, slong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_fit_length(A, 1, ctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, ctx->minfo)); fmpz_mod_set_si(A->coeffs + 0, c, ctx->ffinfo); _fmpz_mod_mpoly_set_length(A, !fmpz_is_zero(A->coeffs + 0), ctx); } flint-3.1.3/src/fmpz_mod_mpoly/set_str_pretty.c000066400000000000000000000024051461254215100217140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_set_str_pretty( fmpz_mod_mpoly_t poly, const char * str, const char** x, const fmpz_mod_mpoly_ctx_t ctx) { int ret; slong i; fmpz_mod_mpoly_t val; mpoly_parse_t E; char dummy[FLINT_BITS/2]; mpoly_void_ring_init_fmpz_mod_mpoly_ctx(E->R, ctx); mpoly_parse_init(E); fmpz_mod_mpoly_init(val, ctx); for (i = 0; i < ctx->minfo->nvars; i++) { fmpz_mod_mpoly_gen(val, i, ctx); if (x == NULL) { flint_sprintf(dummy, "x%wd", i + 1); mpoly_parse_add_terminal(E, dummy, (const void *)val); } else { mpoly_parse_add_terminal(E, x[i], (const void *)val); } } fmpz_mod_mpoly_clear(val, ctx); ret = mpoly_parse_parse(E, poly, str, strlen(str)); mpoly_parse_clear(E); return ret; } flint-3.1.3/src/fmpz_mod_mpoly/set_term_coeff_fmpz.c000066400000000000000000000025661461254215100226520ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_set_term_coeff_fmpz(fmpz_mod_mpoly_t A, slong i, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_set_term_coeff_fmpz: index is out of range"); fmpz_mod_set_fmpz(A->coeffs + i, c, ctx->ffinfo); } void fmpz_mod_mpoly_set_term_coeff_ui(fmpz_mod_mpoly_t A, slong i, ulong c, const fmpz_mod_mpoly_ctx_t ctx) { if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_set_term_coeff_ui: index is out of range"); fmpz_mod_set_ui(A->coeffs + i, c, ctx->ffinfo); } void fmpz_mod_mpoly_set_term_coeff_si(fmpz_mod_mpoly_t A, slong i, slong c, const fmpz_mod_mpoly_ctx_t ctx) { if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_set_term_coeff_si: index is out of range"); fmpz_mod_set_si(A->coeffs + i, c, ctx->ffinfo); } flint-3.1.3/src/fmpz_mod_mpoly/set_term_exp_fmpz.c000066400000000000000000000020271461254215100223540ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_set_term_exp_fmpz(fmpz_mod_mpoly_t A, slong i, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_set_term_exp_fmpz: index is out of range."); exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_pfmpz(A->exps + N*i, exp, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/set_term_exp_ui.c000066400000000000000000000020131461254215100220100ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_set_term_exp_ui(fmpz_mod_mpoly_t A, slong i, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if (i >= (ulong) A->length) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_set_term_exp_ui: index is out of range"); exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ui(A->exps + N*i, exp, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/sort_terms.c000066400000000000000000000134251461254215100210270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* sort terms in [left, right) by exponent assuming that bits in position >= pos are already sorted and assuming exponent vectors fit into one word and assuming that all bit positions that need to be sorted are in totalmask */ void _fmpz_mod_mpoly_radix_sort1( fmpz * Acoeffs, ulong * Aexps, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask) { ulong mask, cmp; slong mid, cur; while (pos > 0) { pos--; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < FLINT_BITS); mask = UWORD(1) << pos; cmp = cmpmask & mask; /* insertion base case */ if (right - left < 10) { slong i, j; for (i = left + 1; i < right; i++) { for (j = i; j > left && mpoly_monomial_gt1(Aexps[j], Aexps[j - 1], cmpmask); j--) { fmpz_swap(Acoeffs + j, Acoeffs + j - 1); FLINT_SWAP(ulong, Aexps[j], Aexps[j - 1]); } } return; } /* return if there is no information to sort on this bit */ if ((totalmask & mask) == 0) continue; /* find first 'zero' */ mid = left; while (mid < right && (Aexps[mid] & mask) != cmp) mid++; /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ cur = mid; while (++cur < right) { if ((Aexps[cur] & mask) != cmp) { fmpz_swap(Acoeffs + cur, Acoeffs + mid); FLINT_SWAP(ulong, Aexps[cur], Aexps[mid]); mid++; } } if (mid - left < right - mid) { _fmpz_mod_mpoly_radix_sort1(Acoeffs, Aexps, left, mid, pos, cmpmask, totalmask); left = mid; } else { _fmpz_mod_mpoly_radix_sort1(Acoeffs, Aexps, mid, right, pos, cmpmask, totalmask); right = mid; } } } /* sort terms in [left, right) by exponent assuming that bits in position >= pos are already sorted */ void _fmpz_mod_mpoly_radix_sort( fmpz * Acoeffs, ulong * Aexps, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask) { ulong off, bit, mask, cmp; slong mid, check; while (pos > 0) { pos--; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < N*FLINT_BITS); off = pos/FLINT_BITS; bit = pos%FLINT_BITS; mask = UWORD(1) << bit; cmp = cmpmask[off] & mask; /* insertion base case */ if (right - left < 20) { slong i, j; for (i = left + 1; i < right; i++) { for (j = i; j > left && mpoly_monomial_gt(Aexps + N*j, Aexps + N*(j - 1), N, cmpmask); j--) { fmpz_swap(Acoeffs + j, Acoeffs + j - 1); mpoly_monomial_swap(Aexps + N*j, Aexps + N*(j - 1), N); } } return; } /* find first 'zero' */ mid = left; while (mid < right && ((Aexps+N*mid)[off] & mask) != cmp) mid++; /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ check = mid; while (++check < right) { if (((Aexps + N*check)[off] & mask) != cmp) { fmpz_swap(Acoeffs + check, Acoeffs + mid); mpoly_monomial_swap(Aexps + N*check, Aexps + N*mid, N); mid++; } } FLINT_ASSERT(left <= mid && mid <= right); if (mid - left < right - mid) { _fmpz_mod_mpoly_radix_sort(Acoeffs, Aexps, left, mid, pos, N, cmpmask); left = mid; } else { _fmpz_mod_mpoly_radix_sort(Acoeffs, Aexps, mid, right, pos, N, cmpmask); right = mid; } } } /* sort the terms in A by exponent assuming that the exponents are valid (other than being in order) */ void fmpz_mod_mpoly_sort_terms(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t pos; fmpz * Acoeffs = A->coeffs; ulong * Aexps = A->exps; ulong himask, * ptempexp; TMP_INIT; TMP_START; N = mpoly_words_per_exp(A->bits, ctx->minfo); ptempexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(ptempexp, N, A->bits, ctx->minfo); himask = 0; for (i = 0; i < A->length; i++) himask |= (Aexps + N*i)[N - 1]; pos = FLINT_BIT_COUNT(himask); if (N == 1) _fmpz_mod_mpoly_radix_sort1(Acoeffs, Aexps, 0, A->length, pos, ptempexp[0], himask); else _fmpz_mod_mpoly_radix_sort(Acoeffs, Aexps, 0, A->length, (N - 1)*FLINT_BITS + pos, N, ptempexp); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/sqrt_heap.c000066400000000000000000000521311461254215100206110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gmpcompat.h" #include "nmod.h" #include "fmpz_mod.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fmpz_mod_mpoly.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif /* try to prove that A is not a square */ static int _is_proved_not_square( int count, flint_rand_t state, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fctx) { int tries_left, success = 0; slong i, N = mpoly_words_per_exp(Abits, mctx); fmpz eval[1], * alphas; ulong * t; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; t = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (count == 1) { success = mpoly_is_proved_not_square(Aexps, Alen, Abits, N, t); if (success) goto cleanup; } tries_left = 3*count; fmpz_init(eval); alphas = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(alphas + i); next_p: for (i = 0; i < mctx->nvars; i++) fmpz_randm(alphas + i, state, fmpz_mod_ctx_modulus(fctx)); _fmpz_mod_mpoly_eval_all_fmpz_mod(eval, Acoeffs, Aexps, Alen, Abits, alphas, mctx, fctx); success = fmpz_jacobi(eval, fmpz_mod_ctx_modulus(fctx)) < 0; if (!success && --tries_left >= 0) goto next_p; fmpz_clear(eval); for (i = 0; i < mctx->nvars; i++) fmpz_clear(alphas + i); cleanup: TMP_END; return success; } static int _fmpz_mod_mpoly_sqrt_heap1( fmpz_mod_mpoly_t Q, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t bits, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fctx) { slong i, j, Qlen, Ai; slong next_loc, heap_len = 1, heap_alloc; mpoly_heap1_s * heap; mpoly_heap_t * chain_nodes[64]; mpoly_heap_t ** chain; slong exp_alloc; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong mask, exp, exp3 = 0; ulong cmpmask; mpz_t acc, acc2, modulus; fmpz zero = 0; const fmpz * s; fmpz_t lc_inv; int lt_divides; flint_rand_t heuristic_state; int heuristic_count = 0; fmpz_init(lc_inv); mpz_init(modulus); mpz_init(acc); mpz_init(acc2); fmpz_get_mpz(modulus, fmpz_mod_ctx_modulus(fctx)); FLINT_ASSERT(mpoly_words_per_exp(bits, mctx) == 1); mpoly_get_cmpmask(&cmpmask, 1, bits, mctx); flint_randinit(heuristic_state); /* alloc array of heap nodes which can be chained together */ next_loc = 2*n_sqrt(Alen) + 4; /* something bigger than heap can ever be */ heap_alloc = next_loc - 3; heap = (mpoly_heap1_s *) flint_malloc((heap_alloc + 1)*sizeof(mpoly_heap1_s)); chain_nodes[0] = (mpoly_heap_t *) flint_malloc(heap_alloc*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_malloc(heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_malloc(2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc; i++) chain[i] = chain_nodes[0] + i; exp_alloc = 1; mask = mpoly_overflow_mask_sp(bits); /* "insert" (-1, 1, Aexps[1]) into "heap" */ Ai = 1; /* compute first term */ Qlen = 0; _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); if (!fmpz_sqrtmod(Qcoeffs + 0, Acoeffs + 0, fmpz_mod_ctx_modulus(fctx))) goto not_sqrt; Qlen = 1; /* precompute leading coefficient info */ fmpz_mod_add(lc_inv, Qcoeffs + 0, Qcoeffs + 0, fctx); fmpz_mod_inv(lc_inv, lc_inv, fctx); if (!mpoly_monomial_halves1(Qexps + 0, Aexps[0], mask)) goto not_sqrt; /* exponent is not square */ /* optimisation, compute final exponent */ { if (fmpz_jacobi(Acoeffs + Alen - 1, fmpz_mod_ctx_modulus(fctx)) < 0) goto not_sqrt; if (!mpoly_monomial_halves1(&exp3, Aexps[Alen - 1], mask)) goto not_sqrt; /* exponent is not square */ exp3 += Qexps[0]; /* overflow not possible */ } while (heap_len > 1 || Ai < Alen) { _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); if (heap_len > 1 && Ai < Alen && Aexps[Ai] == heap[1].exp) { /* take from both A and heap */ exp = Aexps[Ai]; s = Acoeffs + Ai; Ai++; } else if (heap_len > 1 && (Ai >= Alen || mpoly_monomial_gt1(heap[1].exp, Aexps[Ai], cmpmask))) { /* take only from heap */ exp = heap[1].exp; s = &zero; if (mpoly_monomial_overflows1(exp, mask)) goto not_sqrt; } else { FLINT_ASSERT(Ai < Alen); /* take only from A */ exp = Aexps[Ai]; s = Acoeffs + Ai; Ai++; goto skip_heap; } /* total is always acc + 2*acc2 */ mpz_set_ui(acc, 0); mpz_set_ui(acc2, 0); do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { mpz_ptr t; fmpz Qi, Qj; *store++ = x->i; *store++ = x->j; Qi = Qcoeffs[x->i]; Qj = Qcoeffs[x->j]; t = (x->i != x->j) ? acc2 : acc; if (COEFF_IS_MPZ(Qi) && COEFF_IS_MPZ(Qj)) { mpz_addmul(t, COEFF_TO_PTR(Qi), COEFF_TO_PTR(Qj)); } else if (COEFF_IS_MPZ(Qi) && !COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qi), Qj); } else if (!COEFF_IS_MPZ(Qi) && COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qj), Qi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Qcoeffs[x->i], Qcoeffs[x->j]); flint_mpz_add_uiui(t, t, pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); mpz_addmul_ui(acc, acc2, 2); mpz_tdiv_qr(acc2, _fmpz_promote(Qcoeffs + Qlen), acc, modulus); _fmpz_demote_val(Qcoeffs + Qlen); fmpz_mod_sub(Qcoeffs + Qlen, s, Qcoeffs + Qlen, fctx); s = Qcoeffs + Qlen; /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right */ if (j < i) { x = chain[i]; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Qexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } } skip_heap: fmpz_mod_mul(Qcoeffs + Qlen, s, lc_inv, fctx); if (fmpz_is_zero(Qcoeffs + Qlen)) continue; lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Qexps[0], mask); if (!lt_divides) goto not_sqrt; if (Qlen >= heap_alloc) { /* run some tests if the square root is getting long */ if (Qlen > Alen && _is_proved_not_square( ++heuristic_count, heuristic_state, Acoeffs, Aexps, Alen, bits, mctx, fctx)) { goto not_sqrt; } heap_alloc *= 2; heap = (mpoly_heap1_s *) flint_realloc(heap, (heap_alloc + 1)*sizeof(mpoly_heap1_s)); chain_nodes[exp_alloc] = (mpoly_heap_t *) flint_malloc((heap_alloc/2)*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_realloc(chain, heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_realloc(store_base, 2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc/2; i++) chain[i + heap_alloc/2] = chain_nodes[exp_alloc] + i; exp_alloc++; } /* put (Qlen, 1) in heap */ i = Qlen; x = chain[i]; x->i = i; x->j = 1; x->next = NULL; _mpoly_heap_insert1(heap, Qexps[i] + Qexps[1], x, &next_loc, &heap_len, cmpmask); Qlen++; } cleanup: flint_randclear(heuristic_state); Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; fmpz_clear(lc_inv); mpz_clear(modulus); mpz_clear(acc); mpz_clear(acc2); flint_free(heap); flint_free(chain); flint_free(store_base); for (i = 0; i < exp_alloc; i++) flint_free(chain_nodes[i]); return Qlen > 0; not_sqrt: Qlen = 0; goto cleanup; } static int _fmpz_mod_mpoly_sqrt_heap( fmpz_mod_mpoly_t Q, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t bits, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fctx) { slong N = mpoly_words_per_exp(bits, mctx); ulong * cmpmask; slong i, j, Qlen, Ai; slong next_loc; slong heap_len = 1, heap_alloc; int exp_alloc; mpoly_heap_s * heap; mpoly_heap_t * chain_nodes[64]; mpoly_heap_t ** chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exp3; ulong * exps[64]; ulong ** exp_list; slong exp_next; ulong mask; mpz_t acc, acc2, modulus; fmpz zero = 0; const fmpz * s; fmpz_t lc_inv; int halves, lt_divides; flint_rand_t heuristic_state; int heuristic_count = 0; TMP_INIT; if (N == 1) return _fmpz_mod_mpoly_sqrt_heap1(Q, Acoeffs, Aexps, Alen, bits, mctx, fctx); fmpz_init(lc_inv); mpz_init(modulus); mpz_init(acc); mpz_init(acc2); fmpz_get_mpz(modulus, fmpz_mod_ctx_modulus(fctx)); TMP_START; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, mctx); flint_randinit(heuristic_state); /* alloc array of heap nodes which can be chained together */ next_loc = 2*sqrt(Alen) + 4; /* something bigger than heap can ever be */ heap_alloc = next_loc - 3; heap = (mpoly_heap_s *) flint_malloc((heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[0] = (mpoly_heap_t *) flint_malloc(heap_alloc*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_malloc(heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_malloc(2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc; i++) chain[i] = chain_nodes[0] + i; /* array of exponent vectors, each of "N" words */ exps[0] = (ulong *) flint_malloc(heap_alloc*N*sizeof(ulong)); exp_alloc = 1; /* list of pointers to available exponent vectors */ exp_list = (ulong **) flint_malloc(heap_alloc*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* final exponent */ exp3 = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < heap_alloc; i++) exp_list[i] = exps[0] + i*N; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; /* "insert" (-1, 1, Aexps[0]) into "heap" */ Ai = 1; /* compute first term */ Qlen = 0; _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(!fmpz_is_zero(Acoeffs + 0)); FLINT_ASSERT(fmpz_mod_is_canonical(Acoeffs + 0, fctx)); if (!fmpz_sqrtmod(Qcoeffs + 0, Acoeffs + 0, fmpz_mod_ctx_modulus(fctx))) goto not_sqrt; Qlen = 1; /* precompute leading coefficient info */ fmpz_mod_add(lc_inv, Qcoeffs + 0, Qcoeffs + 0, fctx); fmpz_mod_inv(lc_inv, lc_inv, fctx); if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(Qexps + 0, Aexps + 0, N, mask); else halves = mpoly_monomial_halves_mp(Qexps + 0, Aexps + 0, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ /* optimisation, compute final term */ { if (fmpz_jacobi(Acoeffs + Alen - 1, fmpz_mod_ctx_modulus(fctx)) < 0) goto not_sqrt; if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(exp3, Aexps + (Alen - 1)*N, N, mask); else halves = mpoly_monomial_halves_mp(exp3, Aexps + (Alen - 1)*N, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ if (bits <= FLINT_BITS) mpoly_monomial_add(exp3, exp3, Qexps + 0, N); else mpoly_monomial_add_mp(exp3, exp3, Qexps + 0, N); } while (heap_len > 1 || Ai < Alen) { _fmpz_mod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, Qlen + 1); if (heap_len > 1 && Ai < Alen && mpoly_monomial_equal(Aexps + N*Ai, heap[1].exp, N)) { /* take from both A and heap */ mpoly_monomial_set(exp, Aexps + N*Ai, N); s = Acoeffs + Ai; Ai++; } else if (heap_len > 1 && (Ai >= Alen || mpoly_monomial_lt( Aexps + N*Ai, heap[1].exp, N, cmpmask))) { /* take only from heap */ mpoly_monomial_set(exp, heap[1].exp, N); s = &zero; if (bits <= FLINT_BITS ? mpoly_monomial_overflows(exp, N, mask) : mpoly_monomial_overflows_mp(exp, N, bits)) goto not_sqrt; } else { FLINT_ASSERT(Ai < Alen); /* take only from A */ mpoly_monomial_set(exp, Aexps + N*Ai, N); s = Acoeffs + Ai; Ai++; goto skip_heap; } /* total is always acc + 2*acc2 */ mpz_set_ui(acc, 0); mpz_set_ui(acc2, 0); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { mpz_ptr t; fmpz Qi, Qj; *store++ = x->i; *store++ = x->j; Qi = Qcoeffs[x->i]; Qj = Qcoeffs[x->j]; t = (x->i != x->j) ? acc2 : acc; if (COEFF_IS_MPZ(Qi) && COEFF_IS_MPZ(Qj)) { mpz_addmul(t, COEFF_TO_PTR(Qi), COEFF_TO_PTR(Qj)); } else if (COEFF_IS_MPZ(Qi) && !COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qi), Qj); } else if (!COEFF_IS_MPZ(Qi) && COEFF_IS_MPZ(Qj)) { flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qj), Qi); } else { ulong pp1, pp0; umul_ppmm(pp1, pp0, Qcoeffs[x->i], Qcoeffs[x->j]); flint_mpz_add_uiui(t, t, pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); mpz_addmul_ui(acc, acc2, 2); mpz_tdiv_qr(acc2, _fmpz_promote(Qcoeffs + Qlen), acc, modulus); _fmpz_demote_val(Qcoeffs + Qlen); fmpz_mod_sub(Qcoeffs + Qlen, s, Qcoeffs + Qlen, fctx); s = Qcoeffs + Qlen; /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right */ if (j < i) { x = chain[i]; x->i = i; x->j = j + 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + N*x->i, Qexps + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } skip_heap: fmpz_mod_mul(Qcoeffs + Qlen, s, lc_inv, fctx); if (fmpz_is_zero(Qcoeffs + Qlen)) continue; if (bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(Qexps + N*Qlen, exp, Qexps + N*0, N, mask); else lt_divides = mpoly_monomial_divides_mp(Qexps + N*Qlen, exp, Qexps + N*0, N, bits); if (!lt_divides) goto not_sqrt; if (Qlen >= heap_alloc) { /* run some tests if the square root is getting long */ if (Qlen > Alen && _is_proved_not_square( ++heuristic_count, heuristic_state, Acoeffs, Aexps, Alen, bits, mctx, fctx)) { goto not_sqrt; } heap_alloc *= 2; heap = (mpoly_heap_s *) flint_realloc(heap, (heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[exp_alloc] = (mpoly_heap_t *) flint_malloc((heap_alloc/2)*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_realloc(chain, heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_realloc(store_base, 2*heap_alloc*sizeof(mpoly_heap_t *)); exps[exp_alloc] = (ulong *) flint_malloc((heap_alloc/2)*N*sizeof(ulong)); exp_list = (ulong **) flint_realloc(exp_list, heap_alloc*sizeof(ulong *)); for (i = 0; i < heap_alloc/2; i++) { chain[i + heap_alloc/2] = chain_nodes[exp_alloc] + i; exp_list[i + heap_alloc/2] = exps[exp_alloc] + i*N; } exp_alloc++; } /* put (Qlen, 1) in heap */ i = Qlen; x = chain[i]; x->i = i; x->j = 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); Qlen++; } cleanup: flint_randclear(heuristic_state); Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; fmpz_clear(lc_inv); mpz_clear(modulus); mpz_clear(acc); mpz_clear(acc2); flint_free(heap); flint_free(chain); flint_free(store_base); flint_free(exp_list); for (i = 0; i < exp_alloc; i++) { flint_free(exps[i]); flint_free(chain_nodes[i]); } TMP_END; return Qlen > 0; not_sqrt: Qlen = 0; goto cleanup; } int fmpz_mod_mpoly_sqrt_heap( fmpz_mod_mpoly_t Q, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong lenq_est; if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(Q, ctx); return 1; } if (fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))) { nmod_mpoly_ctx_t nctx; nmod_mpoly_t nQ, nA; nctx->minfo[0] = ctx->minfo[0]; nmod_init(&nctx->mod, fmpz_get_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); nmod_mpoly_init(nQ, nctx); nmod_mpoly_init(nA, nctx); _fmpz_mod_mpoly_get_nmod_mpoly(nA, nctx, A, ctx); success = nmod_mpoly_sqrt_heap(nQ, nA, nctx); _fmpz_mod_mpoly_set_nmod_mpoly(Q, ctx, nQ, nctx); nmod_mpoly_clear(nA, nctx); nmod_mpoly_clear(nQ, nctx); return success; } lenq_est = n_sqrt(A->length); if (Q == A) { fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init3(T, lenq_est, A->bits, ctx); success = _fmpz_mod_mpoly_sqrt_heap(T, A->coeffs, A->exps, A->length, A->bits, ctx->minfo, ctx->ffinfo); fmpz_mod_mpoly_swap(Q, T, ctx); fmpz_mod_mpoly_clear(T, ctx); } else { fmpz_mod_mpoly_fit_length_reset_bits(Q, lenq_est, A->bits, ctx); success = _fmpz_mod_mpoly_sqrt_heap(Q, A->coeffs, A->exps, A->length, A->bits, ctx->minfo, ctx->ffinfo); } return success; } flint-3.1.3/src/fmpz_mod_mpoly/sub.c000066400000000000000000000100161461254215100174100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" slong _fmpz_mod_mpoly_sub( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, const fmpz_mod_ctx_t fctx) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_mod_sub(Acoeffs + k, Bcoeffs + i, Ccoeffs + j, fctx); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_sub(Acoeffs + k, fmpz_mod_ctx_modulus(fctx), Ccoeffs + j); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_sub(Acoeffs + k, fmpz_mod_ctx_modulus(fctx), Ccoeffs + j); j++; k++; } return k; } void fmpz_mod_mpoly_sub( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t C, const fmpz_mod_mpoly_ctx_t ctx) { slong Abits, N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_neg(A, C, ctx); return; } else if (fmpz_mod_mpoly_is_zero(C, ctx)) { fmpz_mod_mpoly_set(A, B, ctx); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init3(T, B->length + C->length, Abits, ctx); T->length = _fmpz_mod_mpoly_sub(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->ffinfo); fmpz_mod_mpoly_swap(A, T, ctx); fmpz_mod_mpoly_clear(T, ctx); } else { fmpz_mod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _fmpz_mod_mpoly_sub(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->ffinfo); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/sub_fmpz.c000066400000000000000000000025631461254215100204540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_sub_fmpz( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_fmpz(cc, c, ctx->ffinfo); fmpz_mod_neg(cc, cc, ctx->ffinfo); fmpz_mod_mpoly_add_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } void fmpz_mod_mpoly_sub_ui( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, ulong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_ui(cc, c, ctx->ffinfo); fmpz_mod_neg(cc, cc, ctx->ffinfo); fmpz_mod_mpoly_add_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } void fmpz_mod_mpoly_sub_si( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong c, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t cc; fmpz_init(cc); fmpz_mod_set_si(cc, c, ctx->ffinfo); fmpz_mod_neg(cc, cc, ctx->ffinfo); fmpz_mod_mpoly_add_fmpz_mod(A, B, cc, ctx); fmpz_clear(cc); } flint-3.1.3/src/fmpz_mod_mpoly/term_content.c000066400000000000000000000032641461254215100213270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_term_content( fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t Abits; fmpz * minAfields, * min_degs; TMP_INIT; if (fmpz_mod_mpoly_is_zero(A, ctx)) { fmpz_mod_mpoly_zero(M, ctx); return; } TMP_START; Abits = A->bits; /* get the field-wise minimum */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, Abits, ctx->minfo); /* unpack to get the min exponents of each variable */ min_degs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(min_degs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(min_degs, minAfields, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(M, 1, Abits, ctx); mpoly_set_monomial_ffmpz(M->exps, min_degs, Abits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(minAfields + i); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(min_degs + i); TMP_END; fmpz_one(M->coeffs + 0); _fmpz_mod_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/fmpz_mod_mpoly/term_exp_fits.c000066400000000000000000000015621461254215100214750ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly.h" int fmpz_mod_mpoly_term_exp_fits_ui(const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_ui(A->exps, A->bits, i, ctx->minfo); } int fmpz_mod_mpoly_term_exp_fits_si(const fmpz_mod_mpoly_t A, slong i, const fmpz_mod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_si(A->exps, A->bits, i, ctx->minfo); } flint-3.1.3/src/fmpz_mod_mpoly/test/000077500000000000000000000000001461254215100174345ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_mpoly/test/main.c000066400000000000000000000104471461254215100205320ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-add_sub_fmpz.c" #include "t-add_sub_si.c" #include "t-cmp.c" #include "t-degree.c" #include "t-degrees_term_exp_fits_ui_si.c" #include "t-derivative.c" #include "t-divides.c" #include "t-divides_dense.c" #include "t-divides_monagan_pearce.c" #include "t-div_monagan_pearce.c" #include "t-divrem.c" #include "t-divrem_ideal_monagan_pearce.c" #include "t-evaluate.c" #include "t-gcd_brown.c" #include "t-gcd_cofactors.c" #include "t-gcd_hensel.c" #include "t-gcd_subresultant.c" #include "t-gcd_zippel2.c" #include "t-gcd_zippel.c" #include "t-gen.c" #include "t-get_coeff_vars_ui.c" #include "t-get_set_coeff_fmpz_fmpz.c" #include "t-get_set_coeff_fmpz_monomial.c" #include "t-get_set_coeff_fmpz_ui.c" #include "t-get_set_is_fmpz.c" #include "t-get_set_str_pretty.c" #include "t-get_set_term_coeff_fmpz.c" #include "t-get_set_term_exp_fmpz.c" #include "t-get_set_term_exp_si.c" #include "t-get_set_term_exp_ui.c" #include "t-get_term.c" #include "t-get_term_monomial.c" #include "t-mul.c" #include "t-mul_dense.c" #include "t-mul_johnson.c" #include "t-push_term_fmpz_fmpz.c" #include "t-push_term_fmpz_ui.c" #include "t-quadratic_root.c" #include "t-resultant_discriminant.c" #include "t-scalar_addmul_fmpz.c" #include "t-scalar_mul_fmpz.c" #include "t-sqrt.c" #include "t-total_degree.c" #include "t-univar_resultant.c" #include "t-used_vars.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mod_mpoly_add_sub), TEST_FUNCTION(fmpz_mod_mpoly_add_sub_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_add_sub_si), TEST_FUNCTION(fmpz_mod_mpoly_cmp), TEST_FUNCTION(fmpz_mod_mpoly_degree), TEST_FUNCTION(fmpz_mod_mpoly_degrees_term_exp_fits_ui_si), TEST_FUNCTION(fmpz_mod_mpoly_derivative), TEST_FUNCTION(fmpz_mod_mpoly_divides), TEST_FUNCTION(fmpz_mod_mpoly_divides_dense), TEST_FUNCTION(fmpz_mod_mpoly_divides_monagan_pearce), TEST_FUNCTION(fmpz_mod_mpoly_div_monagan_pearce), TEST_FUNCTION(fmpz_mod_mpoly_divrem), TEST_FUNCTION(fmpz_mod_mpoly_divrem_ideal_monagan_pearce), TEST_FUNCTION(fmpz_mod_mpoly_evaluate), TEST_FUNCTION(fmpz_mod_mpoly_gcd_brown), TEST_FUNCTION(fmpz_mod_mpoly_gcd_cofactors), TEST_FUNCTION(fmpz_mod_mpoly_gcd_hensel), TEST_FUNCTION(fmpz_mod_mpoly_gcd_subresultant), TEST_FUNCTION(fmpz_mod_mpoly_gcd_zippel2), TEST_FUNCTION(fmpz_mod_mpoly_gcd_zippel), TEST_FUNCTION(fmpz_mod_mpoly_gen), TEST_FUNCTION(fmpz_mod_mpoly_get_coeff_vars_ui), TEST_FUNCTION(fmpz_mod_mpoly_get_set_coeff_fmpz_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_get_set_coeff_fmpz_monomial), TEST_FUNCTION(fmpz_mod_mpoly_get_set_coeff_fmpz_ui), TEST_FUNCTION(fmpz_mod_mpoly_get_set_is_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_get_set_str_pretty), TEST_FUNCTION(fmpz_mod_mpoly_get_set_term_coeff_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_get_set_term_exp_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_get_set_term_exp_si), TEST_FUNCTION(fmpz_mod_mpoly_get_set_term_exp_ui), TEST_FUNCTION(fmpz_mod_mpoly_get_term), TEST_FUNCTION(fmpz_mod_mpoly_get_term_monomial), TEST_FUNCTION(fmpz_mod_mpoly_mul), TEST_FUNCTION(fmpz_mod_mpoly_mul_dense), TEST_FUNCTION(fmpz_mod_mpoly_mul_johnson), TEST_FUNCTION(fmpz_mod_mpoly_push_term_fmpz_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_push_term_fmpz_ui), TEST_FUNCTION(fmpz_mod_mpoly_quadratic_root), TEST_FUNCTION(fmpz_mod_mpoly_resultant_discriminant), TEST_FUNCTION(fmpz_mod_mpoly_scalar_addmul_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_scalar_mul_fmpz), TEST_FUNCTION(fmpz_mod_mpoly_sqrt), TEST_FUNCTION(fmpz_mod_mpoly_total_degree), TEST_FUNCTION(fmpz_mod_mpoly_univar_resultant), TEST_FUNCTION(fmpz_mod_mpoly_used_vars) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mod_mpoly/test/t-add_sub.c000066400000000000000000000271301461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_add_sub, state) { slong i, j; /* Check (f + g) - g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_add(h, g, f, ctx); fmpz_mod_mpoly_sub(k, h, g, ctx); if (!fmpz_mod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: Check (f + g) - g = f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f + g = g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_add(h, f, g, ctx); fmpz_mod_mpoly_add(k, g, f, ctx); if (!fmpz_mod_mpoly_equal(h, k, ctx)) { flint_printf("FAIL: Check f + g = g + f\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f - g = -g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_sub(h, f, g, ctx); fmpz_mod_mpoly_neg(k, g, ctx); fmpz_mod_mpoly_add(k, k, f, ctx); if (!fmpz_mod_mpoly_equal(h, k, ctx)) { flint_printf("FAIL: Check f - g = -g + f\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f + (g + h) = (f + g) + h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k1, ctx); fmpz_mod_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); fmpz_mod_mpoly_add(k1, f, g, ctx); fmpz_mod_mpoly_add(k1, k1, h, ctx); fmpz_mod_mpoly_add(k2, g, h, ctx); fmpz_mod_mpoly_add(k2, k2, f, ctx); if (!fmpz_mod_mpoly_equal(k1, k2, ctx)) { flint_printf("FAIL Check f + (g + h) = (f + g) + h\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k1, ctx); fmpz_mod_mpoly_clear(k2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f - (g + h) = (f - g) - h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k1, ctx); fmpz_mod_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); fmpz_mod_mpoly_add(k1, g, h, ctx); fmpz_mod_mpoly_sub(k1, f, k1, ctx); fmpz_mod_mpoly_sub(k2, f, g, ctx); fmpz_mod_mpoly_sub(k2, k2, h, ctx); if (!fmpz_mod_mpoly_equal(k1, k2, ctx)) { flint_printf("FAIL: Check f - (g + h) = (f - g) - h\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k1, ctx); fmpz_mod_mpoly_clear(k2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_set(h, f, ctx); fmpz_mod_mpoly_add(f, f, g, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_sub(f, f, g, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check aliasing first arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); if ((j % 2) == 0) { fmpz_mod_mpoly_add(h, g, f, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_add(f, g, f, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); } else { fmpz_mod_mpoly_sub(h, g, f, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_sub(f, g, f, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); } if (!fmpz_mod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check aliasing second arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-add_sub_fmpz.c000066400000000000000000000052761461254215100225100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_add_sub_fmpz, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; fmpz_t c; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_init(c); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_randtest(c, state, 200); fmpz_mod_mpoly_add_fmpz(g, f, c, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); fmpz_mod_mpoly_sub_fmpz(h, g, c, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); if (!fmpz_mod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check (f + c) - c = f\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(g, f, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_add_fmpz(f, f, c, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_sub_fmpz(f, f, c, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(c); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-add_sub_si.c000066400000000000000000000052301461254215100221350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_add_sub_si, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong c; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); c = z_randtest(state); fmpz_mod_mpoly_add_si(g, f, c, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); fmpz_mod_mpoly_sub_si(h, g, c, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); if (!fmpz_mod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check (f + c) - c = f\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(g, f, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_add_si(f, f, c, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_sub_si(f, f, c, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-cmp.c000066400000000000000000000130301461254215100206150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_cmp, state) { int result; slong i, j1, j2; /* check polynomial terms are in order */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, mf, mg; slong len; flint_bitcnt_t exp_bits; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(mf, ctx); fmpz_mod_mpoly_init(mg, ctx); len = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits = n_randint(state, exp_bits) + 2; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fmpz_mod_mpoly_repack_bits(g, f, f->bits + n_randint(state, FLINT_BITS), ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); for (j1 = 0; j1 < f->length; j1++) for (j2 = 0; j2 < g->length; j2++) { fmpz_mod_mpoly_get_term_monomial(mf, f, j1, ctx); fmpz_mod_mpoly_get_term_monomial(mg, g, j2, ctx); result = fmpz_mod_mpoly_cmp(mf, mg, ctx); if (!((result == 0 && j1 == j2) || (result == +1 && j1 < j2) || (result == -1 && j1 > j2))) { flint_printf("FAIL: check polynomial terms are in order\n" "i = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(mf, ctx); fmpz_mod_mpoly_clear(mg, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, c, aa, bb, cc; int a_a, a_b, a_c, a_aa, a_bb, a_cc; int b_a, b_b, b_c, b_aa, b_bb, b_cc; int c_a, c_b, c_c, c_aa, c_bb, c_cc; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(c, ctx); fmpz_mod_mpoly_init(aa, ctx); fmpz_mod_mpoly_init(bb, ctx); fmpz_mod_mpoly_init(cc, ctx); fmpz_mod_mpoly_randtest_bits(a, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fmpz_mod_mpoly_randtest_bits(b, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fmpz_mod_mpoly_randtest_bits(c, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fmpz_mod_mpoly_repack_bits(aa, a, a->bits + n_randint(state, 2*FLINT_BITS), ctx); fmpz_mod_mpoly_repack_bits(bb, b, b->bits + n_randint(state, 2*FLINT_BITS), ctx); fmpz_mod_mpoly_repack_bits(cc, c, c->bits + n_randint(state, 2*FLINT_BITS), ctx); a_a = fmpz_mod_mpoly_cmp(a, a, ctx); a_b = fmpz_mod_mpoly_cmp(a, b, ctx); a_c = fmpz_mod_mpoly_cmp(a, c, ctx); a_aa = fmpz_mod_mpoly_cmp(a, aa, ctx); a_bb = fmpz_mod_mpoly_cmp(a, bb, ctx); a_cc = fmpz_mod_mpoly_cmp(a, cc, ctx); b_a = fmpz_mod_mpoly_cmp(b, a, ctx); b_b = fmpz_mod_mpoly_cmp(b, b, ctx); b_c = fmpz_mod_mpoly_cmp(b, c, ctx); b_aa = fmpz_mod_mpoly_cmp(b, aa, ctx); b_bb = fmpz_mod_mpoly_cmp(b, bb, ctx); b_cc = fmpz_mod_mpoly_cmp(b, cc, ctx); c_a = fmpz_mod_mpoly_cmp(c, a, ctx); c_b = fmpz_mod_mpoly_cmp(c, b, ctx); c_c = fmpz_mod_mpoly_cmp(c, c, ctx); c_aa = fmpz_mod_mpoly_cmp(c, aa, ctx); c_bb = fmpz_mod_mpoly_cmp(c, bb, ctx); c_cc = fmpz_mod_mpoly_cmp(c, cc, ctx); if (a_a != 0 || a_aa != 0 || b_b != 0 || b_bb != 0 || c_c != 0 || c_cc != 0) { flint_printf("FAIL: check polynomial compares equal to itself\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if (a_b != a_bb || a_c != a_cc || b_a != b_aa || b_c != b_cc || c_a != c_aa || c_b != c_bb) { flint_printf("FAIL: check differing bits\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if ((a_b*b_c == 0 && a_c != a_b + b_c) || (a_b*b_c > 0 && a_c != a_b)) { flint_printf("FAIL: check transitivity\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(c, ctx); fmpz_mod_mpoly_clear(aa, ctx); fmpz_mod_mpoly_clear(bb, ctx); fmpz_mod_mpoly_clear(cc, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-degree.c000066400000000000000000000106311461254215100212750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_degree, state) { slong i, j; /* Check degree does not go up under addition */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 100); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_add(h, f, g, ctx); fmpz_mod_mpoly_degree_fmpz(hdeg, h, j, ctx); fmpz_mod_mpoly_degree_fmpz(fdeg, f, j, ctx); fmpz_mod_mpoly_degree_fmpz(gdeg, g, j, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { flint_printf("FAIL: Check degree does not go up under addition\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check degree adds under multiplication */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { int ok; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 100); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_degree_fmpz(hdeg, h, j, ctx); fmpz_mod_mpoly_degree_fmpz(fdeg, f, j, ctx); fmpz_mod_mpoly_degree_fmpz(gdeg, g, j, ctx); if (fmpz_mod_mpoly_is_zero(f, ctx) || fmpz_mod_mpoly_is_zero(g, ctx)) { ok = fmpz_equal_si(hdeg, -WORD(1)) && (fmpz_equal_si(fdeg, -WORD(1)) || fmpz_equal_si(gdeg, -WORD(1))); } else { fmpz_add(gdeg, gdeg, fdeg); if (fmpz_is_prime(fmpz_mod_mpoly_ctx_modulus(ctx))) { ok = fmpz_equal(hdeg, gdeg); } else { ok = fmpz_cmp(hdeg, gdeg) <= 0; } } if (!ok) { flint_printf("FAIL: Check degree adds under multiplication\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-degrees_term_exp_fits_ui_si.c000066400000000000000000000216051461254215100256030ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_degrees_term_exp_fits_ui_si, state) { slong i, j, k; int result; /* basic corner cases */ { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; const char * vars[] = {"x","y","z"}; fmpz p = 101; fmpz_mod_mpoly_ctx_init(ctx, 3, ORD_DEGLEX, &p); fmpz_mod_mpoly_init(f, ctx); if (FLINT_BITS == 64) { fmpz_mod_mpoly_set_str_pretty(f, "x^9223372036854775807", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 1\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "(x*y)^9223372036854775807", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 2\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^9223372036854775808", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 3\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "(x*y)^9223372036854775808", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 4\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^18446744073709551615", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 1\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "(x*y)^18446744073709551615", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 2\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^18446744073709551616", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 3\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "(x*y)^18446744073709551616", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 4\n"); fflush(stdout); flint_abort(); } } else if (FLINT_BITS == 32) { fmpz_mod_mpoly_set_str_pretty(f, "x^2147483647", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 1\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^2147483647*y^2147483647", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 2\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^2147483648", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 3\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^2147483648*y^2147483648", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nsi test 4\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^4294967295", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 1\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^4294967295*y^4294967295", vars, ctx); if (!fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 2\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^4294967296", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 3\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set_str_pretty(f, "x^4294967296*y^4294967296", vars, ctx); if (fmpz_mod_mpoly_term_exp_fits_ui(f, 0, ctx)) { flint_printf("FAIL\nui test 4\n"); fflush(stdout); flint_abort(); } } else { flint_printf("FAIL\nFLINT_BITS is not 64 or 32\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check fit */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; fmpz ** exp, ** deg; slong nvars, len; flint_bitcnt_t exp_bits; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 300); fmpz_mod_mpoly_init(f, ctx); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); exp = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); deg = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); deg[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_init(deg[k]); fmpz_set_si(deg[k], -WORD(1)); } len = n_randint(state, 100); exp_bits = n_randint(state, FLINT_BITS + 10) + 1; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (j = 0; j < fmpz_mod_mpoly_length(f, ctx); j++) { fmpz_mod_mpoly_get_term_exp_fmpz(exp, f, j, ctx); for (k = 0; k < nvars; k++) if (fmpz_cmp(deg[k], exp[k]) < 0) fmpz_set(deg[k], exp[k]); result = 1; for (k = 0; k < nvars; k++) result = result && fmpz_fits_si(exp[k]); if (result != fmpz_mod_mpoly_term_exp_fits_si(f, j, ctx)) { flint_printf("FAIL\nCheck monomial_fit_si\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } result = 1; for (k = 0; k < nvars; k++) result = result && fmpz_abs_fits_ui(exp[k]); if (result != fmpz_mod_mpoly_term_exp_fits_ui(f, j, ctx)) { flint_printf("FAIL\nCheck monomial_fit_ui\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } result = 1; fmpz_mod_mpoly_degrees_fmpz(exp, f, ctx); for (k = 0; k < nvars; k++) { if (!fmpz_equal(exp[k], deg[k])) { flint_printf("FAIL\nCheck degree computation\ni = %wd\n", i); fflush(stdout); flint_abort(); } result = result && fmpz_fits_si(exp[k]); } if (result != fmpz_mod_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nCheck degrees_fit_si\ni = %wd\n", i); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { fmpz_clear(deg[k]); flint_free(deg[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(deg); flint_free(exp); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-derivative.c000066400000000000000000000145011461254215100222040ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_derivative, state) { slong i, j; slong tmul = 5; /* Check d(f*g) = df*g + f*dg */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, fp, gp, hp, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; slong idx; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); if (fmpz_mod_mpoly_ctx_nvars(ctx) < 1) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(fp, ctx); fmpz_mod_mpoly_init(gp, ctx); fmpz_mod_mpoly_init(hp, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; fmpz_mod_mpoly_randtest_bits(hp, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(fp, state, len, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(gp, state, len, exp_bits2, ctx); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); idx = n_randint(state, ctx->minfo->nvars); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_derivative(hp, h, idx, ctx); fmpz_mod_mpoly_assert_canonical(hp, ctx); fmpz_mod_mpoly_derivative(fp, f, idx, ctx); fmpz_mod_mpoly_assert_canonical(fp, ctx); fmpz_mod_mpoly_derivative(gp, g, idx, ctx); fmpz_mod_mpoly_assert_canonical(gp, ctx); fmpz_mod_mpoly_mul_johnson(t1, f, gp, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); fmpz_mod_mpoly_mul_johnson(t2, g, fp, ctx); fmpz_mod_mpoly_assert_canonical(t2, ctx); fmpz_mod_mpoly_add(t1, t1, t2, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); if (!fmpz_mod_mpoly_equal(hp, t1, ctx)) { flint_printf("FAIL: Check d(f*g) = df*g + f*dg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(fp, ctx); fmpz_mod_mpoly_clear(gp, ctx); fmpz_mod_mpoly_clear(hp, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check d(f*g) = df*g + f*dg with aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, fp, gp, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; slong idx; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); if (fmpz_mod_mpoly_ctx_nvars(ctx) < 1) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(fp, ctx); fmpz_mod_mpoly_init(gp, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(fp, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(gp, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); idx = n_randint(state, ctx->minfo->nvars); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_derivative(h, h, idx, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_set(fp, f, ctx); fmpz_mod_mpoly_derivative(fp, fp, idx, ctx); fmpz_mod_mpoly_assert_canonical(fp, ctx); fmpz_mod_mpoly_set(gp, g, ctx); fmpz_mod_mpoly_derivative(gp, gp, idx, ctx); fmpz_mod_mpoly_assert_canonical(gp, ctx); fmpz_mod_mpoly_mul_johnson(t1, f, gp, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); fmpz_mod_mpoly_mul_johnson(t2, g, fp, ctx); fmpz_mod_mpoly_assert_canonical(t2, ctx); fmpz_mod_mpoly_add(t1, t1, t2, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); if (!fmpz_mod_mpoly_equal(h, t1, ctx)) { flint_printf("FAIL: Check d(f*g) = df*g + f*dg with aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(fp, ctx); fmpz_mod_mpoly_clear(gp, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000150441461254215100236460ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_div_monagan_pearce, state) { slong i, j; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, l; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(l, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(l, state, len, exp_bits, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_div_monagan_pearce(k, h, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); if (!fmpz_mod_mpoly_equal(k, f, ctx)) { flint_printf("FAIL: Check f*g/g = f\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(l, h, ctx); fmpz_mod_mpoly_div_monagan_pearce(l, l, g, ctx); fmpz_mod_mpoly_assert_canonical(l, ctx); if (!fmpz_mod_mpoly_equal(l, f, ctx)) { flint_printf("FAIL: Check f*g/g = f aliasing dividend\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_div_monagan_pearce(g, h, g, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!fmpz_mod_mpoly_equal(g, f, ctx)) { flint_printf("FAIL: Check f*g/g = f aliasing divisor\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(l, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check div matches divrem for random polys */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, q, r, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(q, ctx); fmpz_mod_mpoly_init(r, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bound(q, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_divrem_monagan_pearce(q, r, f, g, ctx); fmpz_mod_mpoly_assert_canonical(q, ctx); fmpz_mod_mpoly_assert_canonical(r, ctx); fmpz_mod_mpoly_remainder_strongtest(r, g, ctx); fmpz_mod_mpoly_mul(k, q, g, ctx); fmpz_mod_mpoly_add(k, k, r, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); if (!fmpz_mod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: Check f = g*q + r for random polys\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_div_monagan_pearce(k, f, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); if (!fmpz_mod_mpoly_equal(k, q, ctx)) { flint_printf("FAIL: Check div matches divrem\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(k, f, ctx); fmpz_mod_mpoly_div_monagan_pearce(k, k, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); if (!fmpz_mod_mpoly_equal(k, q, ctx)) { flint_printf("FAIL: Check div matches divrem aliasing dividend\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_div_monagan_pearce(g, f, g, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!fmpz_mod_mpoly_equal(g, q, ctx)) { flint_printf("FAIL: Check div matches divrem aliasing divisor\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(q, ctx); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-divides.c000066400000000000000000000340261461254215100214750ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_divides, state) { slong i, j, result, ret, max_threads = 5, tmul = 25; /* Check f*g/g = f sparse */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, hsave, gsave; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(hsave, ctx); fmpz_mod_mpoly_init(gsave, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2 + 1, exp_bits2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_set(hsave, h, ctx); fmpz_mod_mpoly_set(gsave, g, ctx); ret = fmpz_mod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f sparse\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if ( !fmpz_mod_mpoly_equal(h, hsave, ctx) || !fmpz_mod_mpoly_equal(g, gsave, ctx)) { flint_printf("FAIL: Check f*g/g = f sparse input modification\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(hsave, ctx); fmpz_mod_mpoly_clear(gsave, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f dense */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 150/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f dense\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check divisibility of random polys */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; fmpz * shifts, * strides; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 20/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mod_mpoly_inflate(g, g, shifts, strides, ctx); ret = fmpz_mod_mpoly_divides(h, f, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); if (ret == 0) continue; fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_mul(k, h, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); result = fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check divisibility of random polys\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_set(h, f, ctx); fmpz_mod_mpoly_mul(h, h, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f aliasing first\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_set(h, g, ctx); fmpz_mod_mpoly_mul(h, f, h, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f aliasing second\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-divides_dense.c000066400000000000000000000251221461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_divides_dense, state) { slong i, j; int result, ret; /* Check f*g/g = f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides_dense(k, h, g, ctx); if (ret == -1) continue; fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check divisibility of random polys */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 20/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); ret = fmpz_mod_mpoly_divides_dense(h, f, g, ctx); if (ret == -1 || ret == 0) continue; fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_mul(k, h, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); result = fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check divisibility of random polys\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing first argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_set(h, f, ctx); fmpz_mod_mpoly_mul(h, h, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides_dense(k, h, g, ctx); if (ret == -1) continue; fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f aliasing second argument\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing second argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_set(h, g, ctx); fmpz_mod_mpoly_mul(h, f, h, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides_dense(k, h, g, ctx); if (ret == -1) continue; fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f aliasing second argument\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-divides_monagan_pearce.c000066400000000000000000000341601461254215100245130ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_divides_monagan_pearce, state) { slong i, j, result, ret, max_threads = 5, tmul = 25; /* Check f*g/g = f sparse */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, hsave, gsave; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(hsave, ctx); fmpz_mod_mpoly_init(gsave, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2 + 1, exp_bits2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_set(hsave, h, ctx); fmpz_mod_mpoly_set(gsave, g, ctx); ret = fmpz_mod_mpoly_divides_monagan_pearce(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f sparse\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if ( !fmpz_mod_mpoly_equal(h, hsave, ctx) || !fmpz_mod_mpoly_equal(g, gsave, ctx)) { flint_printf("FAIL: Check f*g/g = f sparse input modification\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(hsave, ctx); fmpz_mod_mpoly_clear(gsave, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f dense */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 150/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides_monagan_pearce(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f dense\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check divisibility of random polys */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; fmpz * shifts, * strides; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 20/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mod_mpoly_inflate(g, g, shifts, strides, ctx); ret = fmpz_mod_mpoly_divides_monagan_pearce(h, f, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); if (ret == 0) continue; fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_mul(k, h, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); result = fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check divisibility of random polys\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_set(h, f, ctx); fmpz_mod_mpoly_mul(h, h, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides_monagan_pearce(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f aliasing first\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_set(h, g, ctx); fmpz_mod_mpoly_mul(h, f, h, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); ret = fmpz_mod_mpoly_divides_monagan_pearce(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mod_mpoly_equal(k, f, ctx); if (!result) { flint_printf("FAIL: Check f*g/g = f aliasing second\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-divrem.c000066400000000000000000000337111461254215100213340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_divrem, state) { slong i, j; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, r; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1; exp_bits1 = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1; exp_bits2 = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(r, state, len, exp_bits, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_divrem(k, r, h, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); fmpz_mod_mpoly_assert_canonical(r, ctx); if (!fmpz_mod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: Check f*g/g = f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f = g*q + r for random polys */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_divrem(h, r, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_assert_canonical(r, ctx); fmpz_mod_mpoly_remainder_strongtest(r, g, ctx); fmpz_mod_mpoly_mul(k, h, g, ctx); fmpz_mod_mpoly_add(k, k, r, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); if (!fmpz_mod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: Check f = g*q + r for random polys\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, r1, r2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(r1, ctx); fmpz_mod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); fmpz_mod_mpoly_divrem(h, r1, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_assert_canonical(r1, ctx); fmpz_mod_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mod_mpoly_divrem(f, r2, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_assert_canonical(r2, ctx); fmpz_mod_mpoly_remainder_strongtest(r2, g, ctx); if (!(fmpz_mod_mpoly_equal(h, f, ctx) && fmpz_mod_mpoly_equal(r1, r2, ctx))) { flint_printf("FAIL: Check aliasing of quotient with first argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(r1, ctx); fmpz_mod_mpoly_clear(r2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, r1, r2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(r1, ctx); fmpz_mod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); fmpz_mod_mpoly_divrem(h, r1, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_assert_canonical(r1, ctx); fmpz_mod_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mod_mpoly_divrem(g, r2, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_assert_canonical(r2, ctx); if (!(fmpz_mod_mpoly_equal(h, g, ctx) && fmpz_mod_mpoly_equal(r1, r2, ctx))) { flint_printf("FAIL: Check aliasing of quotient with second argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(r1, ctx); fmpz_mod_mpoly_clear(r2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, r1; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_divrem(h, r1, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_assert_canonical(r1, ctx); fmpz_mod_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mod_mpoly_divrem(k, f, f, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_remainder_strongtest(f, g, ctx); if (!(fmpz_mod_mpoly_equal(h, k, ctx) && fmpz_mod_mpoly_equal(r1, f, ctx))) { flint_printf("FAIL: Check aliasing of remainder with first argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(r1, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, r1; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_divrem(h, r1, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_assert_canonical(r1, ctx); fmpz_mod_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mod_mpoly_divrem(k, g, f, g, ctx); fmpz_mod_mpoly_assert_canonical(k, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!(fmpz_mod_mpoly_equal(h, k, ctx) && fmpz_mod_mpoly_equal(r1, g, ctx))) { flint_printf("FAIL: Check aliasing of remainder with second argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(r1, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000275301461254215100255130ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_divrem_ideal_monagan_pearce, state) { slong i, j, w; { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_struct q[4], r[1], g[1], v[4], s[1], t[1]; fmpz_mod_mpoly_struct* Q[4], * V[4]; fmpz_t m; fmpz_init_set_ui(m, 23); fmpz_mod_mpoly_ctx_init(ctx, 8, ORD_LEX, m); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_set_str_pretty(g, "12*x1^83*x2^72*x3^58*x4^35*x5^92*x6^56*x7^87*x8^69 + 22*x1^51*x2^51*x3^42*x4^12*x5^33*x6^61*x7^97*x8^14 + x1^28*x2^60*x3^77*x4^29*x5^4*x6^63*x7^51*x8^92", NULL, ctx); fmpz_mod_mpoly_init(v+0, ctx); V[0] = v+0; fmpz_mod_mpoly_set_str_pretty(V[0], "12*x1^78*x2^71*x3^53*x4*x5^63*x6^49*x7^49*x8^14 + 17*x1^21*x2^68*x3^59*x4^41*x5^40*x6^43*x7^89*x8^87 + 7*x1^4*x2^22*x3^20*x4^87*x5^98*x6^84*x7^36*x8^4", NULL, ctx); fmpz_mod_mpoly_init(v+1, ctx); V[1] = v+1; fmpz_mod_mpoly_set_str_pretty(V[1], "4*x1^78*x2^96*x3^85*x4^29*x5^97*x6^79*x7^65*x8^58 + 13*x1^77*x2^86*x3^99*x4^39*x5^41*x6^83*x7^21*x8^31", NULL, ctx); fmpz_mod_mpoly_init(v+2, ctx); V[2] = v+2; fmpz_mod_mpoly_set_str_pretty(V[2], "6*x1^72*x2^43*x3^56*x4^76*x5^81*x6^94*x7^67*x8^44 + 4*x1^43*x2^11*x3^31*x4^89*x5^55*x6^55*x7^10*x8^78 + 11*x1^38*x2^23*x3^17*x4^87*x5^89*x6^10*x7^87*x8^96", NULL, ctx); fmpz_mod_mpoly_init(v+3, ctx); V[3] = v+3; fmpz_mod_mpoly_set_str_pretty(V[3], "7*x1^100*x2^94*x3^48*x4^46*x5^81*x6^15*x7^58*x8^83 + 22*x1^84*x2^64*x3^32*x4^43*x5^72*x6^47*x7^62*x8^83 + 5*x1^42*x2^10*x3^22*x4^69*x5^62*x6^36*x7^11*x8^72 + 13*x1^22*x2^62*x3^62*x4^29*x5^97*x6^3*x7^96*x8^40", NULL, ctx); fmpz_mod_mpoly_init(s, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(r, ctx); fmpz_mod_mpoly_init(q+0, ctx); Q[0] = q+0; fmpz_mod_mpoly_init(q+1, ctx); Q[1] = q+1; fmpz_mod_mpoly_init(q+2, ctx); Q[2] = q+2; fmpz_mod_mpoly_init(q+3, ctx); Q[3] = q+3; fmpz_mod_mpoly_divrem_ideal_monagan_pearce(Q, r, g, V, 4, ctx); fmpz_mod_mpoly_mul(t, Q[0], V[0], ctx); fmpz_mod_mpoly_add(s, r, t, ctx); fmpz_mod_mpoly_mul(t, Q[1], V[1], ctx); fmpz_mod_mpoly_add(s, s, t, ctx); fmpz_mod_mpoly_mul(t, Q[2], V[2], ctx); fmpz_mod_mpoly_add(s, s, t, ctx); fmpz_mod_mpoly_mul(t, Q[3], V[3], ctx); fmpz_mod_mpoly_add(s, s, t, ctx); if (!fmpz_mod_mpoly_equal(s, g, ctx)) { flint_printf("FAIL: Check exponent overflow\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(v+0, ctx); fmpz_mod_mpoly_clear(v+1, ctx); fmpz_mod_mpoly_clear(v+2, ctx); fmpz_mod_mpoly_clear(v+3, ctx); fmpz_mod_mpoly_clear(s, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_clear(q+0, ctx); fmpz_mod_mpoly_clear(q+1, ctx); fmpz_mod_mpoly_clear(q+2, ctx); fmpz_mod_mpoly_clear(q+3, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k, r; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_struct * qarr[1], * darr[1]; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); fmpz_mod_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 100) + 1; exp_bits1 = n_randint(state, 100) + 1; exp_bits2 = n_randint(state, 100) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2 + 1, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(r, state, len, exp_bits, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); qarr[0] = k; darr[0] = g; fmpz_mod_mpoly_divrem_ideal_monagan_pearce(qarr, r, h, darr, 1, ctx); fmpz_mod_mpoly_assert_canonical(qarr[0], ctx); fmpz_mod_mpoly_assert_canonical(r, ctx); if (!fmpz_mod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: Check f*g/g = f\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check f = g1*q1 + ... + gn*qn + r for random polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, r, k1, k2; fmpz_mod_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; fmpz_mod_mpoly_struct * qarr[5], * darr[5]; slong n; num = n_randint(state, 5) + 1; g = FLINT_ARRAY_ALLOC(num, fmpz_mod_mpoly_struct); q = FLINT_ARRAY_ALLOC(num, fmpz_mod_mpoly_struct); fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); for (w = 0; w < num; w++) { fmpz_mod_mpoly_init(g + w, ctx); darr[w] = g + w; fmpz_mod_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(k1, ctx); fmpz_mod_mpoly_init(k2, ctx); fmpz_mod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 10/n + 1) + 2; exp_bound1 = n_randint(state, 25/n + 1) + 2; exp_bound2 = n_randint(state, 20/n + 1) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); for (w = 0; w < num; w++) { fmpz_mod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (fmpz_mod_mpoly_is_zero(darr[w], ctx)) fmpz_mod_mpoly_one(darr[w], ctx); fmpz_mod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } fmpz_mod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); fmpz_mod_mpoly_divrem_ideal_monagan_pearce(qarr, r, f, darr, num, ctx); fmpz_mod_mpoly_assert_canonical(r, ctx); for (w = 0; w < num; w++) { fmpz_mod_mpoly_assert_canonical(qarr[w], ctx); fmpz_mod_mpoly_remainder_strongtest(r, darr[w], ctx); } fmpz_mod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { fmpz_mod_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fmpz_mod_mpoly_add(k2, k2, k1, ctx); } fmpz_mod_mpoly_add(k2, k2, r, ctx); if (!fmpz_mod_mpoly_equal(f, k2, ctx)) { flint_printf("FAIL: Check f = g1*q1 + ... + gn*qn + r\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) fmpz_mod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpz_mod_mpoly_clear(darr[w], ctx); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(k1, ctx); fmpz_mod_mpoly_clear(k2, ctx); fmpz_mod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, r, k1, k2; fmpz_mod_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; fmpz_mod_mpoly_struct * qarr[5], * darr[5]; slong n; num = n_randint(state, 5) + 1; g = FLINT_ARRAY_ALLOC(num, fmpz_mod_mpoly_struct); q = FLINT_ARRAY_ALLOC(num, fmpz_mod_mpoly_struct); fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); for (w = 0; w < num; w++) { fmpz_mod_mpoly_init(g + w, ctx); darr[w] = g + w; fmpz_mod_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(k1, ctx); fmpz_mod_mpoly_init(k2, ctx); fmpz_mod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 10/n + 1) + 2; exp_bound1 = n_randint(state, 25/n + 1) + 2; exp_bound2 = n_randint(state, 20/n + 1) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); for (w = 0; w < num; w++) { fmpz_mod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (fmpz_mod_mpoly_is_zero(darr[w], ctx)) fmpz_mod_mpoly_one(darr[w], ctx); fmpz_mod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } fmpz_mod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); fmpz_mod_mpoly_set(r, f, ctx); fmpz_mod_mpoly_divrem_ideal_monagan_pearce(qarr, f, f, darr, num, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); for (w = 0; w < num; w++) { fmpz_mod_mpoly_assert_canonical(qarr[w], ctx); fmpz_mod_mpoly_remainder_strongtest(f, darr[w], ctx); } fmpz_mod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { fmpz_mod_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fmpz_mod_mpoly_add(k2, k2, k1, ctx); } fmpz_mod_mpoly_add(k2, k2, f, ctx); if (!fmpz_mod_mpoly_equal(r, k2, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) fmpz_mod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpz_mod_mpoly_clear(darr[w], ctx); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(k1, ctx); fmpz_mod_mpoly_clear(k2, ctx); fmpz_mod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-evaluate.c000066400000000000000000000161641461254215100216570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_evaluate, state) { slong i, j, v; int tmul = 20; /* Check repeated evalone matches evalall */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g; fmpz_t fe; fmpz ** vals; slong * perm; slong nvars, len; flint_bitcnt_t exp_bits; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); nvars = ctx->minfo->nvars; fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_init(fe); len = n_randint(state, 50); exp_bits = n_randint(state, 200) + 1; perm = FLINT_ARRAY_ALLOC(nvars, slong); vals = FLINT_ARRAY_ALLOC(nvars, fmpz *); for (v = 0; v < nvars; v++) { vals[v] = FLINT_ARRAY_ALLOC(1, fmpz); perm[v] = v; fmpz_init(vals[v]); fmpz_randtest(vals[v], state, 200); } for (j = 0; j < 2*nvars; j++) { slong a = n_randint(state, nvars); slong b = n_randint(state, nvars); FLINT_SWAP(slong, perm[a], perm[b]); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fmpz_mod_mpoly_evaluate_all_fmpz(fe, f, vals, ctx); for (v = 0; v < nvars; v++) { fmpz_mod_mpoly_evaluate_one_fmpz(g, f, perm[v], vals[perm[v]], ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(f, f, perm[v], vals[perm[v]], ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: Check evalone aliasing\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } if (!fmpz_mod_mpoly_equal_fmpz(f, fe, ctx)) { flint_printf("FAIL: Check repeated evalone matches evalall\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpz_clear(vals[v]); flint_free(vals[v]); } flint_free(perm); flint_free(vals); fmpz_clear(fe); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, fg; fmpz_t fe, ge, fge; fmpz ** vals; slong nvars, len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); nvars = ctx->minfo->nvars; fmpz_init(fe); fmpz_init(ge); fmpz_init(fge); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(fg, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 1; exp_bits2 = n_randint(state, 100) + 1; vals = FLINT_ARRAY_ALLOC(nvars, fmpz *); for (v = 0; v < nvars; v++) { vals[v] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init(vals[v]); fmpz_randtest(vals[v], state, 200); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_add(fg, f, g, ctx); fmpz_mod_mpoly_evaluate_all_fmpz(fe, f, vals, ctx); fmpz_mod_mpoly_evaluate_all_fmpz(ge, g, vals, ctx); fmpz_mod_mpoly_evaluate_all_fmpz(fge, fg, vals, ctx); fmpz_mod_add(fe, fe, ge, ctx->ffinfo); if (!fmpz_equal(fge, fe)) { flint_printf("FAIL: Check add commutes with evalall\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpz_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpz_clear(fe); fmpz_clear(ge); fmpz_clear(fge); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(fg, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, fg; fmpz_t fe, ge, fge; fmpz ** vals; slong nvars, len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); nvars = ctx->minfo->nvars; fmpz_init(fe); fmpz_init(ge); fmpz_init(fge); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(fg, ctx); len1 = n_randint(state, 30); len2 = n_randint(state, 30); exp_bits1 = n_randint(state, 100) + 1; exp_bits2 = n_randint(state, 100) + 1; vals = FLINT_ARRAY_ALLOC(nvars, fmpz *); for (v = 0; v < nvars; v++) { vals[v] = FLINT_ARRAY_ALLOC(1, fmpz); fmpz_init(vals[v]); fmpz_randtest(vals[v], state, 200); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_mul(fg, f, g, ctx); fmpz_mod_mpoly_evaluate_all_fmpz(fe, f, vals, ctx); fmpz_mod_mpoly_evaluate_all_fmpz(ge, g, vals, ctx); fmpz_mod_mpoly_evaluate_all_fmpz(fge, fg, vals, ctx); fmpz_mod_mul(fe, fe, ge, ctx->ffinfo); if (!fmpz_equal(fge, fe)) { flint_printf("FAIL: Check mul commutes with evalall\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpz_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpz_clear(fe); fmpz_clear(ge); fmpz_clear(fge); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(fg, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-gcd_brown.c000066400000000000000000000135701461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_brown void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, fmpz_mod_mpoly_t t, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); if (!fmpz_mod_mpoly_gcd_brown(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(g, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(t, ctx) && !fmpz_mod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_divides(ca, a, g, ctx) || !fmpz_mod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_gcd_brown(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_gcd_brown, state) { slong i, j; slong tmul = 5; slong max_threads = 6; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 4, 250); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 40) + 1; len1 = n_randint(state, 80); len2 = n_randint(state, 80); degbound = 1 + 20/FLINT_MAX(WORD(1), ctx->minfo->nvars); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random small"); flint_set_num_threads(n_randint(state, max_threads) + 1); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong n, degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 4, 250); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 100) + 1; len1 = n_randint(state, 150); len2 = n_randint(state, 150); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); degbound = 1 + 60/n/n; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense"); flint_set_num_threads(n_randint(state, max_threads) + 1); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mod_mpoly/test/t-gcd_cofactors.c000066400000000000000000001055541461254215100226530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_cofactors void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t abar, fmpz_mod_mpoly_t bbar, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, const fmpz_mod_mpoly_t gdiv, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpz_mod_mpoly_t ca, cb, cg, u, v, w; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); fmpz_mod_mpoly_init(u, ctx); fmpz_mod_mpoly_init(v, ctx); fmpz_mod_mpoly_init(w, ctx); res = fmpz_mod_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); fmpz_mod_mpoly_assert_canonical(abar, ctx); fmpz_mod_mpoly_assert_canonical(bbar, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_mul(ca, g, abar, ctx); fmpz_mod_mpoly_mul(cb, g, bbar, ctx); if (!fmpz_mod_mpoly_equal(ca, a, ctx) || !fmpz_mod_mpoly_equal(cb, b, ctx)) { flint_printf("FAIL: Check cofactors\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: Check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(u, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, a, u, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(v, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, a, v, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(w, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, a, w, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(u, a, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, u, b, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(v, a, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, v, b, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(w, a, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, w, b, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(u, a, ctx); fmpz_mod_mpoly_set(v, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, u, v, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(v, a, ctx); fmpz_mod_mpoly_set(u, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, v, u, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(u, a, ctx); fmpz_mod_mpoly_set(w, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, u, w, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(w, a, ctx); fmpz_mod_mpoly_set(u, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, w, u, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(v, a, ctx); fmpz_mod_mpoly_set(w, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, v, w, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(w, a, ctx); fmpz_mod_mpoly_set(v, b, ctx); fmpz_mod_mpoly_gcd_cofactors(u, v, w, w, v, ctx); if (!fmpz_mod_mpoly_equal(g, u, ctx) || !fmpz_mod_mpoly_equal(abar, v, ctx) || !fmpz_mod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpz_mod_mpoly_gcd_cofactors(cg, ca, cb, abar, bbar, ctx); fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_equal(ca, abar, ctx) || !fmpz_mod_mpoly_equal(cb, bbar, ctx)) { flint_printf("FAIL: Check cofactors of cofactors\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpz_mod_mpoly_gcd_cofactors(cg, abar, bbar, abar, bbar, ctx); fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!fmpz_mod_mpoly_equal(ca, abar, ctx) || !fmpz_mod_mpoly_equal(cb, bbar, ctx)) { flint_printf("FAIL: Check cofactors of cofactors with aliasing\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); fmpz_mod_mpoly_clear(u, ctx); fmpz_mod_mpoly_clear(v, ctx); fmpz_mod_mpoly_clear(w, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_gcd_cofactors, state) { const slong max_threads = 5; slong i, j, k, tmul = 2; fmpz_t p; fmpz_init_set_ui(p, 1); fmpz_mul_2exp(p, p, 100); fmpz_nextprime(p, p, 1); for (i = 3; i <= 6; i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t g, abar, bbar, a, b, t; fmpz_mod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_one(g, ctx); fmpz_mod_mpoly_one(a, ctx); fmpz_mod_mpoly_one(b, ctx); for (j = 0; j < i; j++) { fmpz_mod_mpoly_gen(t, j, ctx); fmpz_mod_mpoly_add_si(t, t, 1, ctx); fmpz_mod_mpoly_mul(g, g, t, ctx); fmpz_mod_mpoly_gen(t, j, ctx); fmpz_mod_mpoly_sub_si(t, t, 2, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_gen(t, j, ctx); fmpz_mod_mpoly_add_si(t, t, 2, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); } fmpz_mod_mpoly_sub_si(g, g, 2, ctx); fmpz_mod_mpoly_add_si(a, a, 2, ctx); fmpz_mod_mpoly_sub_si(b, b, 2, ctx); fmpz_mod_mpoly_mul(a, a, g, ctx); fmpz_mod_mpoly_mul(b, b, g, ctx); fmpz_mod_mpoly_set(t, g, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, 0, "dense examples"); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } if (0) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t g, abar, bbar, a, b, t; const char * vars[] = {"t" ,"x", "y", "z"}; fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mod_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, 0, 0, "example"); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } { int success; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t g, abar, bbar, a, b; const char * vars[] = {"x" ,"y", "z", "t"}; fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_set_str_pretty(a, "x^3 + 1", vars, ctx); fmpz_mod_mpoly_set_str_pretty(b, "x^9999999999999999999999 + x^3333333333333333333333 + x", vars, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); success = fmpz_mod_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); if (success) { flint_printf("FAIL\n"); flint_printf("Check non-example\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t g, abar, bbar, a, b, t; const char * vars[] = {"x" ,"y", "z", "t"}; fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_set_str_pretty(a, "(1 + x)^1*(2 + y)^1*(1 + z)^2", vars, ctx); fmpz_mod_mpoly_set_str_pretty(b, "(2 + x)^1*(1 + y)^1*(1 - z)^2", vars, ctx); fmpz_mod_mpoly_set_str_pretty(t, "(1 - x)^1*(2 - y)^1*(1 - z)^2", vars, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, 0, 0, "total dense example"); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { do { fmpz_mod_mpoly_randtest_bits(t, state, 1, exp_bits, ctx); } while (t->length != 1); fmpz_mod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(b, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "monomial"); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { do { fmpz_mod_mpoly_randtest_bits(t1, state, 1, exp_bits1, ctx); } while (t1->length != 1); do { fmpz_mod_mpoly_randtest_bits(t2, state, 1, exp_bits2, ctx); } while (t2->length != 1); fmpz_mod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); fmpz_mod_mpoly_mul(b, a, t1, ctx); fmpz_mod_mpoly_mul(t2, a, t2, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, t2, b, a, ctx, i, j, "monomial cofactors"); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t c; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 150); fmpz_init(c); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t1, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(t2, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_mul(b, t1, t2, ctx); fmpz_randm(c, state, fmpz_mod_mpoly_ctx_modulus(ctx)); fmpz_mod_mpoly_scalar_mul_fmpz(a, t2, c, ctx); fmpz_randm(c, state, fmpz_mod_mpoly_ctx_modulus(ctx)); fmpz_mod_mpoly_scalar_mul_fmpz(b, b, c, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); if ((j%2) == 0) fmpz_mod_mpoly_swap(a, b, ctx); gcd_check(g, abar, bbar, a, b, t2, ctx, i, j, "one input divides the other"); } fmpz_clear(c); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { do { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); } while (t->length == 0); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse inputs"); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mod_mpoly_repack_bits(b, b, newbits, ctx); } fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with repacking"); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_one(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpz_mod_mpoly_inflate(a, a, shifts1, strides, ctx); fmpz_mod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpz_mod_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 4, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fmpz_mod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input"); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 4, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fmpz_mod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mod_mpoly_repack_bits(b, b, newbits, ctx); } fmpz_mod_mpoly_randtest_bits(g, state, len4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with repacking"); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 4, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fmpz_mod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len4, bits4, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpz_mod_mpoly_inflate(a, a, shifts1, strides, ctx); fmpz_mod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpz_mod_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } fmpz_clear(p); TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mod_mpoly/test/t-gcd_hensel.c000066400000000000000000000127061461254215100221420ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_hensel void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, fmpz_mod_mpoly_t t, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); if (!fmpz_mod_mpoly_gcd_hensel(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(g, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(t, ctx) && !fmpz_mod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_divides(ca, a, g, ctx) || !fmpz_mod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_gcd_hensel(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_gcd_hensel, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t1, t2, t3; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, 100); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); fmpz_mod_mpoly_init(t3, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 42/(2*ctx->minfo->nvars - 1); degbounds = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 6; j++) { fmpz_mod_mpoly_randtest_bounds(t1, state, len, degbounds, ctx); fmpz_mod_mpoly_randtest_bounds(t2, state, len1, degbounds1, ctx); fmpz_mod_mpoly_randtest_bounds(t3, state, len2, degbounds2, ctx); switch (n_randint(state, 4)) { case 3: fmpz_mod_mpoly_mul(t3, t1, t2, ctx); break; case 2: fmpz_mod_mpoly_mul(t3, t3, t1, ctx); break; case 1: fmpz_mod_mpoly_mul(t3, t3, t2, ctx); break; default: break; } fmpz_mod_mpoly_mul(a, t1, t3, ctx); fmpz_mod_mpoly_mul(b, t2, t3, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t3, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_clear(t3, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mod_mpoly/test/t-gcd_subresultant.c000066400000000000000000000105561461254215100234200ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_subresultant void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, fmpz_mod_mpoly_t t, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); if (!fmpz_mod_mpoly_gcd_subresultant(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(g, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(t, ctx) && !fmpz_mod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_divides(ca, a, g, ctx) || !fmpz_mod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_gcd_subresultant(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_gcd_subresultant, state) { slong i, j; slong tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 3, 250); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 1 + 10/FLINT_MAX(WORD(1), ctx->minfo->nvars); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random small"); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mod_mpoly/test/t-gcd_zippel.c000066400000000000000000000123511461254215100221630ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_zippel void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, fmpz_mod_mpoly_t t, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); if (!fmpz_mod_mpoly_gcd_zippel(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(g, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->length < 1 || !fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(t, ctx) && !fmpz_mod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_divides(ca, a, g, ctx) || !fmpz_mod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_gcd_zippel(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_gcd_zippel, state) { slong i, j; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, ca, cb, cg, t; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 100); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 16) + 1; len1 = n_randint(state, 16); len2 = n_randint(state, 16); degbound = 120/(2*ctx->minfo->nvars - 1); degbounds = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); degbounds1[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); degbounds2[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); } for (j = 0; j < 5; j++) { fmpz_mod_mpoly_randtest_bounds(t, state, len, degbounds, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bounds(a, state, len1, degbounds1, ctx); fmpz_mod_mpoly_randtest_bounds(b, state, len2, degbounds2, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mod_mpoly/test/t-gcd_zippel2.c000066400000000000000000000123551461254215100222510ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_zippel2 void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, fmpz_mod_mpoly_t t, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); if (!fmpz_mod_mpoly_gcd_zippel2(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(g, ctx); if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->length < 1 || !fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(t, ctx) && !fmpz_mod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_divides(ca, a, g, ctx) || !fmpz_mod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_gcd_zippel2(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_gcd_zippel2, state) { slong i, j; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, ca, cb, cg, t; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 100); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 16) + 1; len1 = n_randint(state, 16); len2 = n_randint(state, 16); degbound = 120/(2*ctx->minfo->nvars - 1); degbounds = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); degbounds1[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); degbounds2[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); } for (j = 0; j < 5; j++) { fmpz_mod_mpoly_randtest_bounds(t, state, len, degbounds, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bounds(a, state, len1, degbounds1, ctx); fmpz_mod_mpoly_randtest_bounds(b, state, len2, degbounds2, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mod_mpoly/test/t-gen.c000066400000000000000000000050331461254215100206130ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_gen, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f1, f2; slong nvars, len, exp_bits, k1, k2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); if (nvars < 1) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(f1, ctx); fmpz_mod_mpoly_init(f2, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; fmpz_mod_mpoly_randtest_bits(f1, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(f2, state, len, exp_bits, ctx); k1 = n_randint(state, nvars); k2 = n_randint(state, nvars); fmpz_mod_mpoly_gen(f1, k1, ctx); fmpz_mod_mpoly_assert_canonical(f1, ctx); fmpz_mod_mpoly_gen(f2, k2, ctx); fmpz_mod_mpoly_assert_canonical(f2, ctx); result = 1; result = result && fmpz_mod_mpoly_is_gen(f1, k1, ctx); result = result && fmpz_mod_mpoly_is_gen(f1, -WORD(1), ctx); result = result && fmpz_mod_mpoly_is_gen(f2, k2, ctx); result = result && fmpz_mod_mpoly_is_gen(f2, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check one generator\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_mul(f1, f1, f2, ctx); result = 0; result += !!fmpz_mod_mpoly_is_gen(f1, k1, ctx); result += !!fmpz_mod_mpoly_is_gen(f1, k2, ctx); result += !!fmpz_mod_mpoly_is_gen(f1, -WORD(1), ctx); if (result != (fmpz_is_one(fmpz_mod_mpoly_ctx_modulus(ctx)) ? 3 : 0)) { printf("FAIL\n"); flint_printf("Check product of two generators\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(f1, ctx); fmpz_mod_mpoly_clear(f2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000126101461254215100235120ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_coeff_vars_ui, state) { slong i, j1, j2; { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g; /* get the coefficient of y^1*x^2*/ slong varl[2] = {1, 0}; ulong expl[2] = {1, 2}; const char * vars[] = {"x", "y", "z", "w"}; fmpz p = 101; fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_DEGREVLEX, &p); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_set_str_pretty(f, "x^2*y*(z+w)+x+y+x*y^2+z^2+w^2", vars, ctx); fmpz_mod_mpoly_set_str_pretty(g, "z+w", vars, ctx); fmpz_mod_mpoly_get_coeff_vars_ui(f, f, varl, expl, 2, ctx); if (!fmpz_mod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check simple example\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* check 1 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, m; slong len; ulong exp_bound; slong vars[1]; ulong exps[1]; slong var1; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); if (fmpz_mod_mpoly_ctx_nvars(ctx) < 1) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 20) + 1; fmpz_mod_mpoly_randtest_bound(f, state, len, exp_bound, ctx); fmpz_mod_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, fmpz_mod_mpoly_ctx_nvars(ctx)); fmpz_mod_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { vars[0] = var1; exps[0] = j1; fmpz_mod_mpoly_get_coeff_vars_ui(g, f, vars, exps, 1, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); fmpz_mod_mpoly_gen(m, var1, ctx); fmpz_mod_mpoly_pow_ui(m, m, j1, ctx); fmpz_mod_mpoly_mul(g, g, m, ctx); fmpz_mod_mpoly_add(h, h, g, ctx); } if (!fmpz_mod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: check 1 variable sum of coefficients\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* check 2 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, m; slong len; ulong exp_bound; slong vars[2]; ulong exps[2]; slong var1, var2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); if (fmpz_mod_mpoly_ctx_nvars(ctx) < 2) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 12) + 1; fmpz_mod_mpoly_randtest_bound(f, state, len, exp_bound, ctx); fmpz_mod_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, fmpz_mod_mpoly_ctx_nvars(ctx) - 1); var2 = 1 + var1 + n_randint(state, fmpz_mod_mpoly_ctx_nvars(ctx) - 1 - var1); fmpz_mod_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) for (j2 = 0; j2 < exp_bound; j2++) { vars[0] = var1; exps[0] = j1; vars[1] = var2; exps[1] = j2; fmpz_mod_mpoly_get_coeff_vars_ui(g, f, vars, exps, 2, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); fmpz_mod_mpoly_gen(m, var1, ctx); fmpz_mod_mpoly_pow_ui(m, m, j1, ctx); fmpz_mod_mpoly_mul(g, g, m, ctx); fmpz_mod_mpoly_gen(m, var2, ctx); fmpz_mod_mpoly_pow_ui(m, m, j2, ctx); fmpz_mod_mpoly_mul(g, g, m, ctx); fmpz_mod_mpoly_add(h, h, g, ctx); } if (!fmpz_mod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: check 2 variable sum of coefficients\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_coeff_fmpz_fmpz.c000066400000000000000000000044221461254215100247270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_coeff_fmpz_fmpz, state) { slong i, j, k; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; flint_bitcnt_t exp_bits, exp_bits2; slong len; fmpz_t c, d; fmpz_init(c); fmpz_init(d); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (j = 0; j < 10; j++) { fmpz ** exp = (fmpz **) flint_malloc(ctx->minfo->nvars*sizeof(fmpz*)); fmpz_randtest_unsigned(c, state, 200); for (k = 0; k < fmpz_mod_mpoly_ctx_nvars(ctx); k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_randtest_unsigned(exp[k], state, exp_bits2); } fmpz_mod_mpoly_set_coeff_fmpz_fmpz(f, c, exp, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_get_coeff_fmpz_fmpz(d, f, exp, ctx); if (!fmpz_mod_equal_fmpz(d, c, ctx->ffinfo)) { printf("FAIL\n"); flint_printf("Check _fmpz_fmpz\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } for (k = 0; k < fmpz_mod_mpoly_ctx_nvars(ctx); k++) { fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp); } fmpz_mod_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_coeff_fmpz_monomial.c000066400000000000000000000074371461254215100255770ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_coeff_fmpz_monomial, state) { slong i, j, k; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, m; fmpz ** exp; fmpz_t cm, ce, q; slong len; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_init(cm); fmpz_init(ce); fmpz_init(q); fmpz_one(q); /* anything nonzero is ok */ len = n_randint(state, 100); exp_bits = n_randint(state, FLINT_BITS + 10) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); /* check a random monomial - this also randomizes m->bits */ exp = (fmpz **) flint_malloc(ctx->minfo->nvars*sizeof(fmpz *)); for (k = 0; k < ctx->minfo->nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_randtest_unsigned(exp[k], state, exp_bits1); } fmpz_mod_mpoly_zero(m, ctx); fmpz_mod_mpoly_set_coeff_fmpz_fmpz(m, q, exp, ctx); fmpz_mod_mpoly_get_coeff_fmpz_monomial(cm, f, m, ctx); fmpz_mod_mpoly_get_coeff_fmpz_fmpz(ce, f, exp, ctx); if (!fmpz_equal(cm, ce)) { flint_printf("FAIL\ncheck a random monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } /* check all coeffs in f */ for (j = 0; j < fmpz_mod_mpoly_length(f, ctx); j++) { fmpz_mod_mpoly_get_term_exp_fmpz(exp, f, j, ctx); fmpz_mod_mpoly_zero(m, ctx); fmpz_mod_mpoly_set_coeff_fmpz_fmpz(m, q, exp, ctx); fmpz_mod_mpoly_get_coeff_fmpz_monomial(cm, f, m, ctx); fmpz_mod_mpoly_get_coeff_fmpz_fmpz(ce, f, exp, ctx); if (!fmpz_equal(cm, ce)) { flint_printf("FAIL\ncheck all coeffs in f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } /* set random coeff and check */ for (j = 0; j < 10; j++) { for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits2); } fmpz_randtest(cm, state, 200); fmpz_mod_mpoly_zero(m, ctx); fmpz_mod_mpoly_set_coeff_fmpz_fmpz(m, q, exp, ctx); fmpz_mod_mpoly_set_coeff_fmpz_monomial(f, cm, m, ctx); fmpz_mod_mpoly_get_coeff_fmpz_monomial(ce, f, m, ctx); if (!fmpz_mod_equal_fmpz(ce, cm, ctx->ffinfo)) { flint_printf("FAIL\nset random coeff and check\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp); fmpz_clear(q); fmpz_clear(cm); fmpz_clear(ce); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_coeff_fmpz_ui.c000066400000000000000000000036001461254215100243650ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_coeff_fmpz_ui, state) { slong i, j, k; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; flint_bitcnt_t exp_bits; slong len; fmpz_t c, d; fmpz_init(c); fmpz_init(d); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (j = 0; j < 10; j++) { ulong * exp = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); fmpz_randtest_unsigned(c, state, 200); for (k = 0; k < ctx->minfo->nvars; k++) exp[k] = n_randtest(state); fmpz_mod_mpoly_set_coeff_fmpz_ui(f, c, exp, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_get_coeff_fmpz_ui(d, f, exp, ctx); if (!fmpz_mod_equal_fmpz(d, c, ctx->ffinfo)) { printf("FAIL\n"); flint_printf("Check _fmpz_ui\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } flint_free(exp); } fmpz_mod_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_is_fmpz.c000066400000000000000000000040471461254215100232270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_is_fmpz, state) { slong i; /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; fmpz_t c, d; fmpz_init(c); fmpz_init(d); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_randtest_bits(f, state, n_randint(state, 10), n_randint(state, 200), ctx); if (fmpz_mod_mpoly_is_fmpz(f, ctx)) { fmpz_mod_mpoly_get_fmpz(c, f, ctx); fmpz_add(c, c, fmpz_mod_mpoly_ctx_modulus(ctx)); if (!fmpz_mod_mpoly_equal_fmpz(f, c, ctx)) { flint_printf("FAIL: Check is_fmpz and get_fmpz match\n"); fflush(stdout); flint_abort(); } } fmpz_randtest(c, state, n_randint(state, 300)); fmpz_mod_mpoly_set_fmpz(f, c, ctx); if (!fmpz_mod_mpoly_is_fmpz(f, ctx)) { flint_printf("FAIL: Check set_fmpz makes is_fmpz true\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_get_fmpz(d, f, ctx); if (!fmpz_mod_equal_fmpz(d, c, ctx->ffinfo)) { flint_printf("FAIL: Check get_fmpz matches set_fmpz\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_str_pretty.c000066400000000000000000000032221461254215100237710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_str_pretty, state) { slong i; { slong len1; flint_bitcnt_t exp_bits1; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, f1; char * str; const char * vars[] = {"x","y","z","w","u","v"}; for (i = 0; i < flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(f1, ctx); for (len1 = 3; len1 < 1000; len1 += len1/2) { exp_bits1 = 200; fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); str = fmpz_mod_mpoly_get_str_pretty(f, vars, ctx); fmpz_mod_mpoly_set_str_pretty(f1, str, vars, ctx); flint_free(str); if (!fmpz_mod_mpoly_equal(f, f1, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(f1, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_term_coeff_fmpz.c000066400000000000000000000042251461254215100247230ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_term_coeff_fmpz, state) { slong i, j; /* Set coeff and get coeff and compare */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; fmpz_t c, d; slong len, index; flint_bitcnt_t exp_bits; fmpz_init(c); fmpz_init(d); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (f->length > 0) { for (j = 0; j < 10; j++) { fmpz_randtest(c, state, n_randint(state, 200)); index = n_randint(state, f->length); fmpz_mod_mpoly_set_term_coeff_fmpz(f, index, c, ctx); fmpz_mod_mpoly_get_term_coeff_fmpz(d, f, index, ctx); if (!fmpz_mod_equal_fmpz(d, c, ctx->ffinfo)) { flint_printf("FAIL: check get and set match\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } if (!fmpz_equal(f->coeffs + index, d)) { flint_printf("FAIL: check reference match\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpz_mod_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000054331461254215100244370ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_term_exp_fmpz, state) { slong i, j, k; int result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); do { len = n_randint(state, 50); exp_bits = n_randint(state, 100) + 1; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); } while (f->length == 0); for (j = 0; j < 10; j++) { fmpz ** exp1 = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); fmpz ** exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); for (k = 0; k < nvars; k++) { exp1[k] = (fmpz *) flint_malloc(sizeof(fmpz)); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp1[k]); fmpz_init(exp2[k]); fmpz_randtest_unsigned(exp1[k], state, 200); } index = n_randint(state, f->length); fmpz_mod_mpoly_set_term_exp_fmpz(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpz_mod_mpoly_get_term_exp_fmpz(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && fmpz_equal(exp1[k], exp2[k]); fmpz_clear(exp1[k]); fmpz_clear(exp2[k]); flint_free(exp1[k]); flint_free(exp2[k]); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000052121461254215100240710ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_term_exp_si, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; do { fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); } while (fmpz_mod_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { slong * exp1 = (slong *) flint_malloc(nvars*sizeof(slong)); slong * exp2 = (slong *) flint_malloc(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS - 1) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); fmpz_mod_mpoly_set_term_exp_ui(f, index, (ulong *) exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpz_mod_mpoly_get_term_exp_si(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fmpz_mod_mpoly_get_term_var_exp_si(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000051751461254215100241030ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_set_term_exp_ui, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 100) + 2; do { fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); } while (fmpz_mod_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { ulong * exp1 = (ulong *) flint_malloc(nvars*sizeof(ulong)); ulong * exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); fmpz_mod_mpoly_set_term_exp_ui(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpz_mod_mpoly_get_term_exp_ui(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fmpz_mod_mpoly_get_term_var_exp_ui(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_term.c000066400000000000000000000040341461254215100216500ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_term, state) { int i, j; /* Check a polynomial is the sum of its terms */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); fmpz_mod_mpoly_zero(h, ctx); for (j = fmpz_mod_mpoly_length(f, ctx) - 1; j >= 0; j--) { fmpz_mod_mpoly_get_term(g, f, j, ctx); fmpz_mod_mpoly_add(h, h, g, ctx); } if (!fmpz_mod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check a polynomial is the sum of its terms\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-get_term_monomial.c000066400000000000000000000047061461254215100235510ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_get_term_monomial, state) { int i, j; /* Check getting a coeff by its monomial */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t c, d; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; fmpz_init(c); fmpz_init(d); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); fmpz_mod_mpoly_repack_bits(h, f, f->bits + n_randint(state, 2*FLINT_BITS), ctx); for (j = fmpz_mod_mpoly_length(f, ctx) - 1; j >= 0; j--) { fmpz_mod_mpoly_get_term_monomial(g, f, j, ctx); fmpz_mod_mpoly_repack_bits(g, g, g->bits + n_randint(state, FLINT_BITS), ctx); fmpz_mod_mpoly_get_term_coeff_fmpz(d, f, j, ctx); fmpz_mod_mpoly_get_coeff_fmpz_monomial(c, h, g, ctx); if (!fmpz_equal(c, d)) { flint_printf("FAIL\nCheck getting a coeff by its monomial\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } } fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-mul.c000066400000000000000000000130551461254215100206420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_mul, state) { slong i, j, max_threads = 5; slong tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 2, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k1, ctx); fmpz_mod_mpoly_init(k2, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; fmpz_mod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len2, exp_bits, ctx); fmpz_mod_mpoly_add(t1, g, h, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); fmpz_mod_mpoly_mul(k1, f, t1, ctx); fmpz_mod_mpoly_assert_canonical(k1, ctx); fmpz_mod_mpoly_mul(t1, f, g, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); fmpz_mod_mpoly_mul(t2, f, h, ctx); fmpz_mod_mpoly_assert_canonical(t2, ctx); fmpz_mod_mpoly_add(k2, t1, t2, ctx); fmpz_mod_mpoly_assert_canonical(k2, ctx); if (!fmpz_mod_mpoly_equal(k1, k2, ctx)) { flint_printf("FAIL: Check f*(g + h) = f*g + f*h\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k1, ctx); fmpz_mod_mpoly_clear(k2, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 4, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); exp_bound = 3 + n_randint(state, 1 + 100/n/n); exp_bound1 = 3 + n_randint(state, 1 + 100/n/n); exp_bound2 = 3 + n_randint(state, 1 + 100/n/n); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, n) + 2; j >= 0; j--) { len *= exp_bound + 1; len1 *= exp_bound1 + 1; len2 *= exp_bound2 + 1; len = FLINT_MIN(len, WORD(100)); len1 = FLINT_MIN(len, WORD(100)); len2 = FLINT_MIN(len, WORD(100)); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_mul(f, f, g, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(h, f, ctx)) { flint_printf("FAIL: Check aliasing first arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_mul(g, f, g, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!fmpz_mod_mpoly_equal(h, g, ctx)) { flint_printf("FAIL: Check aliasing second arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-mul_dense.c000066400000000000000000000135571461254215100220270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_mul_dense, state) { slong i, j; /* Check mul_dense matches mul_johnson */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; slong len, len1, len2; slong max_bound, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); if (!fmpz_mod_mpoly_mul_dense(k, f, g, ctx)) continue; fmpz_mod_mpoly_assert_canonical(k, ctx); if (!fmpz_mod_mpoly_equal(h, k, ctx)) { flint_printf("FAIL: Check mul_dense matches mul_johnson\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong len, len1, len2; slong max_bound, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); if (!fmpz_mod_mpoly_mul_dense(f, f, g, ctx)) continue; fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(h, f, ctx)) { flint_printf("FAIL: Check aliasing first argument\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong len, len1, len2; slong max_bound, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 6, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); if (!fmpz_mod_mpoly_mul_dense(f, g, f, ctx)) continue; fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(h, f, ctx)) { flint_printf("FAIL: Check aliasing first argument\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-mul_johnson.c000066400000000000000000000131551461254215100224010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_mul_johnson, state) { slong i, j, max_threads = 5; slong tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 2, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k1, ctx); fmpz_mod_mpoly_init(k2, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; fmpz_mod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len2, exp_bits, ctx); fmpz_mod_mpoly_add(t1, g, h, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); fmpz_mod_mpoly_mul_johnson(k1, f, t1, ctx); fmpz_mod_mpoly_assert_canonical(k1, ctx); fmpz_mod_mpoly_mul_johnson(t1, f, g, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); fmpz_mod_mpoly_mul_johnson(t2, f, h, ctx); fmpz_mod_mpoly_assert_canonical(t2, ctx); fmpz_mod_mpoly_add(k2, t1, t2, ctx); fmpz_mod_mpoly_assert_canonical(k2, ctx); if (!fmpz_mod_mpoly_equal(k1, k2, ctx)) { flint_printf("FAIL: Check f*(g + h) = f*g + f*h\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k1, ctx); fmpz_mod_mpoly_clear(k2, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 4, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); exp_bound = 3 + n_randint(state, 1 + 100/n/n); exp_bound1 = 3 + n_randint(state, 1 + 100/n/n); exp_bound2 = 3 + n_randint(state, 1 + 100/n/n); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, n) + 2; j >= 0; j--) { len *= exp_bound + 1; len1 *= exp_bound1 + 1; len2 *= exp_bound2 + 1; len = FLINT_MIN(len, WORD(100)); len1 = FLINT_MIN(len, WORD(100)); len2 = FLINT_MIN(len, WORD(100)); } for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_mul_johnson(f, f, g, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); if (!fmpz_mod_mpoly_equal(h, f, ctx)) { flint_printf("FAIL: Check aliasing first arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mod_mpoly_mul_johnson(h, f, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); fmpz_mod_mpoly_mul_johnson(g, f, g, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!fmpz_mod_mpoly_equal(h, g, ctx)) { flint_printf("FAIL: Check aliasing second arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-push_term_fmpz_fmpz.c000066400000000000000000000110661461254215100241430ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_push_term_fmpz_fmpz, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f1, f2, f3, m; flint_bitcnt_t exp_bits; fmpz **exp, **exp2, *exp3; slong len, nvars; fmpz_t c, c2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 10, 200); fmpz_mod_mpoly_init(f1, ctx); fmpz_mod_mpoly_init(f2, ctx); fmpz_mod_mpoly_init(f3, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_init(c); fmpz_init(c2); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); fmpz_init(exp3 + k); } len = n_randint(state, 20); exp_bits = n_randint(state, 200); fmpz_mod_mpoly_zero(f1, ctx); fmpz_mod_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fmpz_randtest(c, state, 200); for (k = 0; k < nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits); fmpz_set(exp3 + k, exp[k]); } /* add it to f1 */ fmpz_mod_mpoly_zero(m, ctx); fmpz_mod_mpoly_set_coeff_fmpz_fmpz(m, c, exp, ctx); fmpz_mod_mpoly_add(f1, f1, m, ctx); fmpz_mod_mpoly_assert_canonical(f1, ctx); /* push it back on f2 and f3*/ fmpz_mod_mpoly_push_term_fmpz_fmpz(f2, c, exp, ctx); fmpz_mod_mpoly_push_term_fmpz_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ fmpz_mod_mpoly_get_term_coeff_fmpz(c2, f2, fmpz_mod_mpoly_length(f2, ctx) - 1, ctx); fmpz_mod_mpoly_get_term_exp_fmpz(exp2, f2, fmpz_mod_mpoly_length(f2, ctx) - 1, ctx); if (!fmpz_mod_equal_fmpz(c2, c, ctx->ffinfo)) { flint_printf("FAIL: Check pushed coefficient matches\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (!fmpz_equal(exp[k], exp2[k])) { flint_printf("FAIL: Check pushed exponent matches\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpz_mod_mpoly_sort_terms(f2, ctx); fmpz_mod_mpoly_combine_like_terms(f2, ctx); fmpz_mod_mpoly_assert_canonical(f2, ctx); fmpz_mod_mpoly_sort_terms(f3, ctx); fmpz_mod_mpoly_combine_like_terms(f3, ctx); fmpz_mod_mpoly_assert_canonical(f3, ctx); if (!fmpz_mod_mpoly_equal(f1, f2, ctx)) { flint_printf("FAIL: Check pushed polynomial matches add\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_equal(f1, f3, ctx)) { flint_printf("FAIL: Check pushed ffmpz polynomial matches add\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_clear(c2); fmpz_clear(c); fmpz_mod_mpoly_clear(f1, ctx); fmpz_mod_mpoly_clear(f2, ctx); fmpz_mod_mpoly_clear(f3, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); fmpz_clear(exp3 + k); } flint_free(exp3); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-push_term_fmpz_ui.c000066400000000000000000000066041461254215100236060ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_push_term_fmpz_ui, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f1, f2, m; flint_bitcnt_t exp_bits; ulong * exp, * exp2; slong len, nvars; fmpz_t c, c2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 10, 200); fmpz_mod_mpoly_init(f1, ctx); fmpz_mod_mpoly_init(f2, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_init(c); fmpz_init(c2); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 20); exp_bits = n_randint(state, FLINT_BITS + 1); fmpz_mod_mpoly_zero(f1, ctx); fmpz_mod_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fmpz_randtest(c, state, 200); for (k = 0; k < nvars; k++) exp[k] = n_randtest_bits(state, n_randint(state, exp_bits) + 1); /* add it to f1 */ fmpz_mod_mpoly_zero(m, ctx); fmpz_mod_mpoly_set_coeff_fmpz_ui(m, c, exp, ctx); fmpz_mod_mpoly_add(f1, f1, m, ctx); /* push it back on f2 */ fmpz_mod_mpoly_push_term_fmpz_ui(f2, c, exp, ctx); /* make sure last term matches */ fmpz_mod_mpoly_get_term_coeff_fmpz(c2, f2, fmpz_mod_mpoly_length(f2, ctx) - 1, ctx); fmpz_mod_mpoly_get_term_exp_ui(exp2, f2, fmpz_mod_mpoly_length(f2, ctx) - 1, ctx); if (!fmpz_mod_equal_fmpz(c2, c, ctx->ffinfo)) { flint_printf("FAIL: Check pushed coefficient matches\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (exp[k] != exp2[k]) { flint_printf("FAIL: Check pushed exponent matches\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpz_mod_mpoly_sort_terms(f2, ctx); fmpz_mod_mpoly_combine_like_terms(f2, ctx); fmpz_mod_mpoly_assert_canonical(f2, ctx); if (!fmpz_mod_mpoly_equal(f1, f2, ctx)) { flint_printf("FAIL: Check pushback matches add\n"); flint_printf("i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_clear(c2); fmpz_clear(c); fmpz_mod_mpoly_clear(f1, ctx); fmpz_mod_mpoly_clear(f2, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-quadratic_root.c000066400000000000000000000067111461254215100230660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" void _test_root( fmpz_mod_mpoly_t x, const fmpz_mod_mpoly_t a, const fmpz_mod_mpoly_t b, const fmpz_mod_mpoly_ctx_t ctx, int sol_exists) { int success, success2; fmpz_mod_mpoly_t s, t; fmpz_mod_mpoly_init(s, ctx); fmpz_mod_mpoly_init(t, ctx); success = fmpz_mod_mpoly_quadratic_root(x, a, b, ctx); if (sol_exists && !success) { flint_printf("FAIL: solution exists but root failed\n"); fflush(stdout); flint_abort(); } if (success) { fmpz_mod_mpoly_add(t, x, a, ctx); fmpz_mod_mpoly_mul(s, t, x, ctx); if (!fmpz_mod_mpoly_equal(s, b, ctx)) { flint_printf("FAIL: reported solution is not a solution\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_set(t, a, ctx); success2 = fmpz_mod_mpoly_quadratic_root(t, t, b, ctx); if (success != success2 || (success && !fmpz_mod_mpoly_equal(x, t, ctx))) { flint_printf("FAIL: Check aliasing first argument\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(t, b, ctx); success2 = fmpz_mod_mpoly_quadratic_root(t, a, t, ctx); if (success != success2 || (success && !fmpz_mod_mpoly_equal(x, t, ctx))) { flint_printf("FAIL: Check aliasing second argument\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(s, ctx); fmpz_mod_mpoly_clear(t, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_quadratic_root, state) { slong i, j, tmul = 20; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, a, b, x; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 100); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(x, ctx); for (j = 0; j < 5; j++) { len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 100) + 1; exp_bits1 = n_randint(state, 100) + 1; fmpz_mod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fmpz_mod_mpoly_add(b, f, a, ctx); fmpz_mod_mpoly_mul(b, b, f, ctx); _test_root(x, a, b, ctx, 1); len = n_randint(state, 50); len1 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 20) + 1; exp_bits1 = n_randint(state, 20) + 1; fmpz_mod_mpoly_randtest_bits(a, state, len1, 10, ctx); fmpz_mod_mpoly_randtest_bits(b, state, len, 10, ctx); _test_root(x, a, b, ctx, 0); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(x, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-resultant_discriminant.c000066400000000000000000000211761461254215100246350ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_resultant_discriminant, state) { slong i, j; /* Check quadratic polynomial */ { fmpz_t p; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, d, d1; const char * vars[] = {"x","a","b","c"}; fmpz_init_set_ui(p, 100003); fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_DEGLEX, p); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(d, ctx); fmpz_mod_mpoly_init(d1, ctx); fmpz_mod_mpoly_set_str_pretty(f, "a^10*x^2 + b^100*x + c^100000000000000000000", vars, ctx); fmpz_mod_mpoly_set_str_pretty(d1, "b^200 - 4*a^10*c^100000000000000000000", vars, ctx); if (!fmpz_mod_mpoly_discriminant(d, f, 0, ctx)) { flint_printf("FAIL: could not compute quadratic discriminant\n"); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(d, ctx); fmpz_mod_mpoly_clear(d1, ctx); fmpz_mod_mpoly_ctx_clear(ctx); fmpz_clear(p); } /* Check univariate resultant */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, r; fmpz_mod_poly_t au, bu; fmpz_t ru; slong len1, len2, exp_bound1, exp_bound2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 1, 100); if (fmpz_mod_mpoly_ctx_nvars(ctx) < 1) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(r, ctx); fmpz_mod_poly_init(au, ctx->ffinfo); fmpz_mod_poly_init(bu, ctx->ffinfo); fmpz_init(ru); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 50) + 1; exp_bound2 = n_randint(state, 50) + 1; fmpz_mod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_get_fmpz_mod_poly(au, a, 0, ctx); fmpz_mod_mpoly_get_fmpz_mod_poly(bu, b, 0, ctx); fmpz_mod_poly_resultant(ru, au, bu, ctx->ffinfo); if (!fmpz_mod_mpoly_resultant(r, a, b, 0, ctx) || !fmpz_mod_mpoly_equal_fmpz(r, ru, ctx)) { flint_printf("FAIL: Check univariate resultant \n"); flint_printf("i: %wd\n",i); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_poly_clear(au, ctx->ffinfo); fmpz_mod_poly_clear(bu, ctx->ffinfo); fmpz_mod_mpoly_ctx_clear(ctx); fmpz_clear(ru); } /* Check res(a*b,c) = res(a,c)*res(b,c) */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, c, ab, ra, rb, rab, p; slong len1, len2, len3, exp_bound1, exp_bound2, exp_bound3; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 3, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(c, ctx); fmpz_mod_mpoly_init(ab, ctx); fmpz_mod_mpoly_init(ra, ctx); fmpz_mod_mpoly_init(rb, ctx); fmpz_mod_mpoly_init(rab, ctx); fmpz_mod_mpoly_init(p, ctx); len1 = n_randint(state, 15); len2 = n_randint(state, 15); len3 = n_randint(state, 15); exp_bound1 = n_randint(state, 5) + 1; exp_bound2 = n_randint(state, 5) + 1; exp_bound3 = n_randint(state, 5) + 1; fmpz_mod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); fmpz_mod_mpoly_randtest_bound(c, state, len3, exp_bound3, ctx); for (j = 0; j < fmpz_mod_mpoly_ctx_nvars(ctx); j++) { fmpz_mod_mpoly_mul(ab, a, b, ctx); if (!fmpz_mod_mpoly_resultant(ra, a, c, j, ctx)) continue; fmpz_mod_mpoly_assert_canonical(ra, ctx); if (!fmpz_mod_mpoly_resultant(rb, b, c, j, ctx)) continue; fmpz_mod_mpoly_assert_canonical(rb, ctx); if (!fmpz_mod_mpoly_resultant(rab, ab, c, j, ctx)) continue; fmpz_mod_mpoly_assert_canonical(rab, ctx); fmpz_mod_mpoly_mul(p, ra, rb, ctx); if (!fmpz_mod_mpoly_equal(p,rab,ctx)) { flint_printf("FAIL: Check res(a*b,c) = res(a,c)*res(b,c)\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(c, ctx); fmpz_mod_mpoly_clear(ab, ctx); fmpz_mod_mpoly_clear(ra, ctx); fmpz_mod_mpoly_clear(rb, ctx); fmpz_mod_mpoly_clear(rab, ctx); fmpz_mod_mpoly_clear(p, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2 */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, ab, r, da, db, dab, p; slong len1, len2, exp_bound1, exp_bound2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 3, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(ab, ctx); fmpz_mod_mpoly_init(da, ctx); fmpz_mod_mpoly_init(db, ctx); fmpz_mod_mpoly_init(dab, ctx); fmpz_mod_mpoly_init(r, ctx); fmpz_mod_mpoly_init(p, ctx); len1 = n_randint(state, 15); len2 = n_randint(state, 15); exp_bound1 = n_randint(state, 4) + 1; exp_bound2 = n_randint(state, 5) + 1; fmpz_mod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); for (j = 0; j < fmpz_mod_mpoly_ctx_nvars(ctx); j++) { if (fmpz_mod_mpoly_degree_si(a, j, ctx) < 1) continue; if (fmpz_mod_mpoly_degree_si(b, j, ctx) < 1) continue; fmpz_mod_mpoly_mul(ab, a, b, ctx); if (!fmpz_mod_mpoly_resultant(r, a, b, j, ctx)) continue; if (!fmpz_mod_mpoly_discriminant(da, a, j, ctx)) continue; if (!fmpz_mod_mpoly_discriminant(db, b, j, ctx)) continue; if (!fmpz_mod_mpoly_discriminant(dab, ab, j, ctx)) continue; fmpz_mod_mpoly_mul(p, da, db, ctx); fmpz_mod_mpoly_mul(p, p, r, ctx); fmpz_mod_mpoly_mul(p, p, r, ctx); if (!fmpz_mod_mpoly_equal(dab, p, ctx)) { flint_printf("FAIL: Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2\n"); flint_printf("a: "); fmpz_mod_mpoly_print_pretty(a, NULL, ctx); flint_printf("\n"); flint_printf("b: "); fmpz_mod_mpoly_print_pretty(b, NULL, ctx); flint_printf("\n"); flint_printf("disc(a*b): "); fmpz_mod_mpoly_print_pretty(dab, NULL, ctx); flint_printf("\n"); flint_printf("disc(a): "); fmpz_mod_mpoly_print_pretty(da, NULL, ctx); flint_printf("\n"); flint_printf("disc(b): "); fmpz_mod_mpoly_print_pretty(db, NULL, ctx); flint_printf("\n"); flint_printf("res(a, b): "); fmpz_mod_mpoly_print_pretty(r, NULL, ctx); flint_printf("\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(ab, ctx); fmpz_mod_mpoly_clear(da, ctx); fmpz_mod_mpoly_clear(db, ctx); fmpz_mod_mpoly_clear(dab, ctx); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_clear(p, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-scalar_addmul_fmpz.c000066400000000000000000000075161461254215100237010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_scalar_addmul_fmpz, state) { slong i, j; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, t1, t2; fmpz_t a, b; slong len, exp_bits; fmpz_init(a); fmpz_init(b); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; for (j = 0; j < 10; j++) { fmpz_one(a); fmpz_randtest(b, state, n_randint(state, 200)); fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(t1, state, len, exp_bits, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(t2, state, len, exp_bits, ctx); fmpz_mod_mpoly_scalar_addmul_fmpz(f, g, h, b, ctx); fmpz_mod_mpoly_assert_canonical(f, ctx); fmpz_mod_mpoly_scalar_mul_fmpz(t1, g, a, ctx); fmpz_mod_mpoly_scalar_mul_fmpz(t2, h, b, ctx); fmpz_mod_mpoly_add(t1, t1, t2, ctx); if (!fmpz_mod_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check addmul definition\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(t1, g, ctx); fmpz_mod_mpoly_scalar_addmul_fmpz(t1, t1, h, b, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); if (!fmpz_mod_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check aliasing first argument\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_set(t1, h, ctx); fmpz_mod_mpoly_scalar_addmul_fmpz(t1, g, t1, b, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); if (!fmpz_mod_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check aliasing second argument\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_scalar_addmul_fmpz(f, g, g, b, ctx); fmpz_mod_mpoly_set(t1, g, ctx); fmpz_mod_mpoly_scalar_addmul_fmpz(t1, t1, t1, b, ctx); fmpz_mod_mpoly_assert_canonical(t1, ctx); if (!fmpz_mod_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check aliasing both arguments\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_ctx_clear(ctx); fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-scalar_mul_fmpz.c000066400000000000000000000070331461254215100232220ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_scalar_mul_fmpz, state) { slong i, j; /* Check (f*a)*b = f*(a*b) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h, k; fmpz_t a, b, c; slong len, exp_bits; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_mod_mpoly_init(k, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fmpz_randtest(a, state, n_randint(state, 200)); fmpz_randtest(b, state, n_randint(state, 200)); fmpz_mul(c, a, b); fmpz_mod_mpoly_scalar_mul_fmpz(g, f, a, ctx); fmpz_mod_mpoly_scalar_mul_fmpz(h, g, b, ctx); fmpz_mod_mpoly_scalar_mul_fmpz(k, f, c, ctx); if (!fmpz_mod_mpoly_equal(h, k, ctx)) { flint_printf("FAIL: Check (f*a)*b = f*(a*b)\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_clear(k, ctx); fmpz_mod_mpoly_ctx_clear(ctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; fmpz_t c; slong len, exp_bits; fmpz_init(c); fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mod_mpoly_set(g, f, ctx); fmpz_mod_mpoly_scalar_mul_fmpz(h, f, c, ctx); fmpz_mod_mpoly_scalar_mul_fmpz(g, g, c, ctx); if (!fmpz_mod_mpoly_equal(g, h, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-sqrt.c000066400000000000000000000127371461254215100210440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_sqrt, state) { slong i, j, tmul = 10; /* Check sqrt(f^2) = +-f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 5) + 1; exp_bits1 = n_randint(state, 5) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_mul(g, f, f, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); sqr = fmpz_mod_mpoly_sqrt(h, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); if (!sqr) { flint_printf("FAIL: Check sqrt(f^2) returns 1\n"); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_equal(h, f, ctx) && !(fmpz_mod_mpoly_neg(h, h, ctx), fmpz_mod_mpoly_equal(h, f, ctx))) { flint_printf("FAIL: Check sqrt(f^2) = +-f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check sqrt(random) */ for (i = 0; i < 2*tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; /* low bits: sqrt(random) is less reliable in positive char */ exp_bits1 = n_randint(state, 100) + 1; for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); sqr = fmpz_mod_mpoly_sqrt(g, f, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (sqr) { fmpz_mod_mpoly_mul(g, g, g, ctx); if (!fmpz_mod_mpoly_equal(g, f, ctx)) { flint_printf("FAIL: Check sqrt(random)\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } else if (!fmpz_mod_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check aliasing of square root with input */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr1, sqr2; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fmpz_mod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fmpz_mod_mpoly_mul(g, f, f, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); sqr1 = fmpz_mod_mpoly_sqrt(h, g, ctx); fmpz_mod_mpoly_assert_canonical(h, ctx); sqr2 = fmpz_mod_mpoly_sqrt(g, g, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (sqr1 != sqr2 || !fmpz_mod_mpoly_equal(g, h, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-total_degree.c000066400000000000000000000116551461254215100225070ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" /* foolproof way to check totdeg_check is correct */ void _check_total_degree(const fmpz_t totdeg_check, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t totdeg; fmpz_init(totdeg); mpoly_total_degree_fmpz_ref(totdeg, A->exps, A->length, A->bits, ctx->minfo); if (!fmpz_equal(totdeg_check, totdeg)) flint_throw(FLINT_ERROR, "Total degree is wrong"); fmpz_clear(totdeg); } TEST_FUNCTION_START(fmpz_mod_mpoly_total_degree, state) { slong i, j; /* Check total_degree does not go up under addition */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_add(h, f, g, ctx); fmpz_mod_mpoly_total_degree_fmpz(hdeg, h, ctx); fmpz_mod_mpoly_total_degree_fmpz(fdeg, f, ctx); fmpz_mod_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { flint_printf("FAIL: Check degree does not go up under addition\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } /* Check total_degree adds under multiplication */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { int ok; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fmpz_mod_mpoly_mul(h, f, g, ctx); fmpz_mod_mpoly_total_degree_fmpz(hdeg, h, ctx); fmpz_mod_mpoly_total_degree_fmpz(fdeg, f, ctx); fmpz_mod_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if (fmpz_mod_mpoly_is_zero(f, ctx) || fmpz_mod_mpoly_is_zero(g, ctx)) { ok = fmpz_equal_si(hdeg, -WORD(1)) && (fmpz_equal_si(fdeg, -WORD(1)) || fmpz_equal_si(gdeg, -WORD(1))); } else { fmpz_add(gdeg, gdeg, fdeg); ok = (fmpz_cmp(hdeg, gdeg) <= 0); } if (!ok) { flint_printf("FAIL: Check degree adds under multiplication\n"); flint_printf("i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(h, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-univar_resultant.c000066400000000000000000000137201461254215100234510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_mpoly.h" void test_resultant( const fmpz_mod_mpoly_t fx, const fmpz_mod_mpoly_t gx, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_univar_t F, G; fmpz_mod_poly_t f, g; fmpz_mod_mpoly_t R; fmpz_t r; fmpz_mod_mpoly_univar_init(F, ctx); fmpz_mod_mpoly_univar_init(G, ctx); fmpz_mod_poly_init(f, ctx->ffinfo); fmpz_mod_poly_init(g, ctx->ffinfo); fmpz_mod_mpoly_init(R, ctx); fmpz_init(r); fmpz_mod_mpoly_get_fmpz_mod_poly(f, fx, 0, ctx); fmpz_mod_mpoly_get_fmpz_mod_poly(g, gx, 0, ctx); fmpz_mod_poly_resultant(r, f, g, ctx->ffinfo); fmpz_mod_mpoly_to_univar(F, fx, 0, ctx); fmpz_mod_mpoly_to_univar(G, gx, 0, ctx); fmpz_mod_mpoly_univar_resultant(R, F, G, ctx); if (!fmpz_mod_mpoly_equal_fmpz(R, r, ctx)) { flint_printf("FAIL: Check resultant against univariate\n"); flint_printf("fx: "); fmpz_mod_mpoly_print_pretty(fx, NULL, ctx); flint_printf("\n"); flint_printf("gx: "); fmpz_mod_mpoly_print_pretty(gx, NULL, ctx); flint_printf("\n"); flint_printf("R: "); fmpz_mod_mpoly_print_pretty(R, NULL, ctx); flint_printf("\n"); flint_printf("r: "); fmpz_print(r); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_univar_clear(F, ctx); fmpz_mod_mpoly_univar_clear(G, ctx); fmpz_mod_poly_clear(f, ctx->ffinfo); fmpz_mod_poly_clear(g, ctx->ffinfo); fmpz_mod_mpoly_clear(R, ctx); fmpz_clear(r); } TEST_FUNCTION_START(fmpz_mod_mpoly_univar_resultant, state) { slong i, j; { fmpz p = 1000003; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t t, s; fmpz_mod_mpoly_univar_t f; const char * vars[] = {"a", "b", "c", "d"}; fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_DEGLEX, &p); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(s, ctx); fmpz_mod_mpoly_univar_init(f, ctx); fmpz_mod_mpoly_univar_zero(f, ctx); fmpz_mod_mpoly_set_str_pretty(t, "a", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "b", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "1", vars, ctx); fmpz_mod_mpoly_univar_discriminant(s, f, ctx); if (!fmpz_mod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check linear discriminant\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_univar_zero(f, ctx); fmpz_mod_mpoly_set_str_pretty(t, "a", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 2, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "b", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "c", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "b^2-4*a*c", vars, ctx); fmpz_mod_mpoly_univar_discriminant(s, f, ctx); if (!fmpz_mod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check quadratic discriminant\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_univar_zero(f, ctx); fmpz_mod_mpoly_set_str_pretty(t, "a", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 3, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "b", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 2, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "c", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "d", vars, ctx); fmpz_mod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "b^2*c^2-4*a*c^3-4*b^3*d-27*a^2*d^2+18*a*b*c*d", vars, ctx); fmpz_mod_mpoly_univar_discriminant(s, f, ctx); if (!fmpz_mod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check cubic discriminant\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(s, ctx); fmpz_mod_mpoly_univar_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f, g, t; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 1, 200); if (fmpz_mod_mpoly_ctx_nvars(ctx) < 1) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(t, ctx); for (j = 0; j < 10; j++) { fmpz_mod_mpoly_randtest_bound(f, state, 3, 3, ctx); if (fmpz_mod_mpoly_is_zero(f, ctx)) fmpz_mod_mpoly_one(f, ctx); fmpz_mod_mpoly_zero(g, ctx); while (fmpz_mod_mpoly_degree_si(f, 0, ctx) < 100) { fmpz_mod_mpoly_randtest_bound(t, state, 5, 10, ctx); fmpz_mod_mpoly_mul(t, t, f, ctx); fmpz_mod_mpoly_add(g, g, t, ctx); fmpz_mod_mpoly_swap(f, g, ctx); } fmpz_mod_mpoly_randtest_bound(f, state, 20, 50, ctx); fmpz_mod_mpoly_randtest_bound(g, state, 20, 50, ctx); test_resultant(f, g, ctx); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/test/t-used_vars.c000066400000000000000000000042121461254215100220330ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly.h" TEST_FUNCTION_START(fmpz_mod_mpoly_used_vars, state) { slong i, j, k; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t f; fmpz_t one, fdeg; slong len, var; flint_bitcnt_t exp_bits; int * used; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); fmpz_mod_mpoly_init(f, ctx); fmpz_init(fdeg); fmpz_init_set_ui(one, 1); used = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, int); for (j = 0; j < ctx->minfo->nvars; j++) { len = n_randint(state, 200); exp_bits = n_randint(state, 150) + 2; fmpz_mod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (k = n_randint(state, ctx->minfo->nvars); k > 0; k--) { var = n_randint(state, ctx->minfo->nvars); fmpz_mod_mpoly_evaluate_one_fmpz(f, f, var, one, ctx); } fmpz_mod_mpoly_used_vars(used, f, ctx); for (var = 0; var < ctx->minfo->nvars; var++) { fmpz_mod_mpoly_degree_fmpz(fdeg, f, var, ctx); if ((fmpz_sgn(fdeg) <= 0) != !used[var]) { flint_printf("FAIL: checked used matches degree\n"); flint_printf("var = %wd\n", var); flint_printf("deg: "); fmpz_print(fdeg); flint_printf("\n"); fflush(stdout); flint_abort(); } } } flint_free(used); fmpz_clear(one); fmpz_clear(fdeg); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly/to_from_nmod_poly.c000066400000000000000000000072501461254215100223520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" /* set A(x_var^Bstride[var]) to B/xbar^Bshifts it is asserted that the conversion is correct */ void _fmpz_mod_mpoly_to_fmpz_mod_poly_deflate( fmpz_mod_poly_t A, const fmpz_mod_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const fmpz_mod_mpoly_ctx_t ctx) { ulong mask; slong i, shift, off, N; slong len = B->length; const fmpz * coeff = B->coeffs; ulong * exp = B->exps; ulong var_shift, var_stride; flint_bitcnt_t bits = B->bits; FLINT_ASSERT(len > 0); FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo); fmpz_mod_poly_zero(A, ctx->ffinfo); mask = (-UWORD(1)) >> (FLINT_BITS - bits); var_shift = Bshift[var]; var_stride = Bstride[var]; for (i = 0; i < len; i++) { ulong k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT(k >= var_shift); k -= var_shift; if (k != 0) k /= var_stride; fmpz_mod_poly_set_coeff_fmpz(A, k, coeff + i, ctx->ffinfo); } #if FLINT_WANT_ASSERT for (i = 0; i < len; i++) { slong v; for (v = 0; v < ctx->minfo->nvars; v++) { ulong k; mpoly_gen_offset_shift_sp(&off, &shift, v, bits, ctx->minfo); k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT( (v == var && k >= Bshift[v]) || (v != var && k == Bshift[v])); } } #endif } /* set A to B(x_var^Astride[var])*xbar^Ashift A must be packed into bits = Abits */ void _fmpz_mod_mpoly_from_fmpz_mod_poly_inflate( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const fmpz_mod_mpoly_ctx_t ctx) { slong N; slong k; slong Alen; fmpz * Acoeff; ulong * Aexp; ulong * shiftexp; ulong * strideexp; slong Bdeg = fmpz_mod_poly_degree(B, ctx->ffinfo); TMP_INIT; TMP_START; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(!fmpz_mod_poly_is_zero(B, ctx->ffinfo)); /* must have at least space for the highest exponent of var */ FLINT_ASSERT(1 + FLINT_BIT_COUNT(Ashift[var] + Bdeg*Astride[var]) <= Abits); N = mpoly_words_per_exp_sp(Abits, ctx->minfo); strideexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); shiftexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ui(shiftexp, Ashift, Abits, ctx->minfo); mpoly_gen_monomial_sp(strideexp, var, Abits, ctx->minfo); mpoly_monomial_mul_ui(strideexp, strideexp, N, Astride[var]); fmpz_mod_mpoly_fit_length_reset_bits(A, 0, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (k = Bdeg; k >= 0; k--) { _fmpz_mod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + 1); fmpz_mod_poly_get_coeff_fmpz(Acoeff + Alen, B, k, ctx->ffinfo); if (fmpz_is_zero(Acoeff + Alen)) continue; mpoly_monomial_madd(Aexp + N*Alen, shiftexp, k, strideexp, N); Alen++; } A->coeffs = Acoeff; A->exps = Aexp; _fmpz_mod_mpoly_set_length(A, Alen, ctx); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly/univar.c000066400000000000000000000444001461254215100201270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mod_mpoly_univar_init( fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; } void fmpz_mod_mpoly_univar_clear( fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) { fmpz_mod_mpoly_clear(A->coeffs + i, ctx); fmpz_clear(A->exps + i); } if (A->coeffs) flint_free(A->coeffs); if (A->exps) flint_free(A->exps); } void fmpz_mod_mpoly_univar_fit_length( fmpz_mod_mpoly_univar_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length <= old_alloc) return; A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, fmpz); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fmpz_mod_mpoly_struct); for (i = old_alloc; i < new_alloc; i++) { fmpz_init(A->exps + i); fmpz_mod_mpoly_init(A->coeffs + i, ctx); } A->alloc = new_alloc; } void fmpz_mod_mpoly_univar_set_coeff_ui( fmpz_mod_mpoly_univar_t A, ulong e, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j; for (i = A->length; i >= 0; i--) { int cmp = i > 0 ? fmpz_cmp_ui(A->exps + i - 1, e) : 1; if (cmp > 0) { if (fmpz_mod_mpoly_is_zero(c, ctx)) return; fmpz_mod_mpoly_univar_fit_length(A, A->length + 1, ctx); for (j = A->length; j > i; j--) { fmpz_mod_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } A->length++; fmpz_set_ui(A->exps + i, e); fmpz_mod_mpoly_set(A->coeffs + i, c, ctx); return; } else if (cmp == 0) { fmpz_mod_mpoly_set(A->coeffs + i, c, ctx); if (!fmpz_mod_mpoly_is_zero(A->coeffs + i, ctx)) return; A->length--; for (j = i; j < A->length; j++) { fmpz_mod_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } } } FLINT_ASSERT(0 && "unreachable"); return; } void fmpz_mod_mpoly_univar_assert_canonical( fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i + 1 < A->length; i++) { if (fmpz_cmp(A->exps + i, A->exps + i + 1) <= 0 || fmpz_sgn(A->exps + i) < 0 || fmpz_sgn(A->exps + i + 1) < 0) { flint_throw(FLINT_ERROR, "Univariate polynomial exponents out of order"); } } for (i = 0; i < A->length; i++) fmpz_mod_mpoly_assert_canonical(A->coeffs + i, ctx); } void fmpz_mod_mpoly_univar_print_pretty( const fmpz_mod_mpoly_univar_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (A->length == 0) flint_printf("0"); for (i = 0; i < A->length; i++) { if (i != 0) flint_printf("+"); flint_printf("("); fmpz_mod_mpoly_print_pretty(A->coeffs + i,x,ctx); flint_printf(")*X^"); fmpz_print(A->exps + i); } } static void _tree_data_clear_sp( fmpz_mod_mpoly_univar_t A, mpoly_rbtree_ui_t tree, slong idx, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_rbnode_ui_struct * nodes = tree->nodes + 2; fmpz_mod_mpoly_struct * data = (fmpz_mod_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_sp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set_ui(A->exps + A->length, nodes[idx].key); fmpz_mod_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fmpz_mod_mpoly_clear(data + idx, ctx); _tree_data_clear_sp(A, tree, nodes[idx].left, ctx); } static void _tree_data_clear_mp( fmpz_mod_mpoly_univar_t A, mpoly_rbtree_fmpz_t tree, slong idx, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_rbnode_fmpz_struct * nodes = tree->nodes + 2; fmpz_mod_mpoly_struct * data = (fmpz_mod_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_mp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set(A->exps + A->length, nodes[idx].key); fmpz_mod_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fmpz_mod_mpoly_clear(data + idx, ctx); _tree_data_clear_mp(A, tree, nodes[idx].left, ctx); } /* the coefficients of A should be constructed with the same bits as B */ void fmpz_mod_mpoly_to_univar( fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong shift, off; slong Blen = B->length; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; slong i; int its_new; ulong * one; #define LUT_limit (48) fmpz_mod_mpoly_struct LUT[LUT_limit]; if (B->length == 0) { A->length = 0; return; } one = FLINT_ARRAY_ALLOC(N, ulong); if (bits <= FLINT_BITS) { slong Alen; mpoly_rbtree_ui_t tree; fmpz_mod_mpoly_struct * d; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); mpoly_rbtree_ui_init(tree, sizeof(fmpz_mod_mpoly_struct)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); for (i = 0; i < LUT_limit; i++) fmpz_mod_mpoly_init3(LUT + i, 4, bits, ctx); /* fill in tree/LUT from B */ for (i = 0; i < Blen; i++) { ulong k = (Bexp[N*i + off] >> shift) & mask; if (k < LUT_limit) { d = LUT + k; } else { d = mpoly_rbtree_ui_lookup(tree, &its_new, k); if (its_new) fmpz_mod_mpoly_init3(d, 4, bits, ctx); } fmpz_mod_mpoly_fit_length(d, d->length + 1, ctx); fmpz_set(d->coeffs + d->length, Bcoeff + i); mpoly_monomial_msub(d->exps + N*d->length, Bexp + N*i, k, one, N); d->length++; } /* clear out tree to A */ Alen = tree->length; for (i = LUT_limit - 1; i >= 0; i--) Alen += (LUT[i].length > 0); fmpz_mod_mpoly_univar_fit_length(A, Alen, ctx); A->length = 0; _tree_data_clear_sp(A, tree, mpoly_rbtree_ui_head(tree), ctx); for (i = LUT_limit - 1; i >= 0; i--) { d = LUT + i; if (d->length > 0) { FLINT_ASSERT(A->length < A->alloc); fmpz_set_si(A->exps + A->length, i); fmpz_mod_mpoly_swap(A->coeffs + A->length, d, ctx); A->length++; } fmpz_mod_mpoly_clear(d, ctx); } mpoly_rbtree_ui_clear(tree); } else { mpoly_rbtree_fmpz_t tree; fmpz_mod_mpoly_struct * d; fmpz_t k; fmpz_init(k); mpoly_rbtree_fmpz_init(tree, sizeof(fmpz_mod_mpoly_struct)); off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); /* fill in tree from B */ for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexp + N*i + off, bits/FLINT_BITS); d = mpoly_rbtree_fmpz_lookup(tree, &its_new, k); if (its_new) fmpz_mod_mpoly_init3(d, 4, bits, ctx); fmpz_mod_mpoly_fit_length(d, d->length + 1, ctx); fmpz_set(d->coeffs + d->length, Bcoeff + i); mpoly_monomial_msub_ui_array(d->exps + N*d->length, Bexp + N*i, Bexp + N*i + off, bits/FLINT_BITS, one, N); d->length++; } /* clear out tree to A */ fmpz_mod_mpoly_univar_fit_length(A, tree->length, ctx); A->length = 0; _tree_data_clear_mp(A, tree, mpoly_rbtree_fmpz_head(tree), ctx); fmpz_clear(k); mpoly_rbtree_fmpz_clear(tree); } flint_free(one); } /* Currently this function does not work if the coefficients depend on "var". The assertion x->next == NULL would need to be replaced by a loop. Other asserts would need to be removed as well. */ void _fmpz_mod_mpoly_from_univar( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_univar_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i; slong next_loc, heap_len = 1; ulong * cmpmask; slong total_len; mpoly_heap_s * heap; slong Alen; ulong ** Btexp; ulong * exp; ulong * one; mpoly_heap_t * chain, * x; TMP_INIT; if (B->length == 0) { fmpz_mod_mpoly_fit_length_reset_bits(A, 0, Abits, ctx); A->length = 0; return; } TMP_START; /* pack everything into Abits */ one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); Btexp = (ulong **) TMP_ALLOC(B->length*sizeof(ulong*)); total_len = 0; for (i = 0; i < B->length; i++) { fmpz_mod_mpoly_struct * Bi = B->coeffs + i; total_len += Bi->length; Btexp[i] = Bi->exps; if (Abits != Bi->bits) { Btexp[i] = (ulong *) flint_malloc(N*Bi->length*sizeof(ulong)); if (!mpoly_repack_monomials(Btexp[i], Abits, Bi->exps, Bi->bits, Bi->length, ctx->minfo)) { FLINT_ASSERT(0 && "repack does not fit"); } } } fmpz_mod_mpoly_fit_length_reset_bits(A, total_len, Abits, ctx); next_loc = B->length + 2; heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); exp = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); Alen = 0; if (Abits <= FLINT_BITS) { mpoly_gen_monomial_sp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { FLINT_ASSERT(fmpz_fits_si(B->exps + i)); x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + i), one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->coeffs_alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fmpz_set(A->coeffs + Alen, B->coeffs[x->i].coeffs + x->j); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { FLINT_ASSERT(fmpz_fits_si(B->exps + x->i)); x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + x->i), one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } else { mpoly_gen_monomial_offset_mp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + i, one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->coeffs_alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fmpz_set(A->coeffs + Alen, B->coeffs[x->i].coeffs + x->j); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + x->i, one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } A->length = Alen; for (i = 0; i < B->length; i++) { if (Btexp[i] != (B->coeffs + i)->exps) flint_free(Btexp[i]); } TMP_END; } void fmpz_mod_mpoly_from_univar( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_univar_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong n = ctx->minfo->nfields; flint_bitcnt_t bits; slong i; fmpz * gen_fields, * tmp_fields, * max_fields; TMP_INIT; if (B->length == 0) { fmpz_mod_mpoly_zero(A, ctx); return; } TMP_START; /* find bits required to represent result */ gen_fields = TMP_ARRAY_ALLOC(3*ctx->minfo->nfields, fmpz); tmp_fields = gen_fields + ctx->minfo->nfields; max_fields = tmp_fields + ctx->minfo->nfields; for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(gen_fields + i); fmpz_init(tmp_fields + i); fmpz_init(max_fields + i); } mpoly_gen_fields_fmpz(gen_fields, var, ctx->minfo); for (i = 0; i < B->length; i++) { fmpz_mod_mpoly_struct * Bi = B->coeffs + i; mpoly_max_fields_fmpz(tmp_fields, Bi->exps, Bi->length, Bi->bits, ctx->minfo); _fmpz_vec_scalar_addmul_fmpz(tmp_fields, gen_fields, n, B->exps + i); _fmpz_vec_max_inplace(max_fields, tmp_fields, n); } bits = _fmpz_vec_max_bits(max_fields, n); bits = FLINT_MAX(MPOLY_MIN_BITS, bits + 1); bits = mpoly_fix_bits(bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(gen_fields + i); fmpz_clear(tmp_fields + i); fmpz_clear(max_fields + i); } TMP_END; _fmpz_mod_mpoly_from_univar(A, bits, B, var, ctx); } void fmpz_mod_mpoly_univar_set( fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_univar_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; fmpz_mod_mpoly_univar_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { fmpz_mod_mpoly_set(A->coeffs + i, B->coeffs+ i, ctx); fmpz_set(A->exps + i, B->exps + i); } A->length = B->length; } #define COEFF(A, i) ((void*)(A->coeffs + (i)*R->elem_size)) static void mpoly_univar_set_fmpz_mod_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, const fmpz_mod_mpoly_univar_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); A->length = B->length; for (i = B->length - 1; i >= 0; i--) { fmpz_set(A->exps + i, B->exps + i); fmpz_mod_mpoly_set(COEFF(A, i), B->coeffs + i, ctx); } } static void mpoly_univar_swap_fmpz_mod_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, fmpz_mod_mpoly_univar_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); fmpz_mod_mpoly_univar_fit_length(B, A->length, ctx); for (i = FLINT_MAX(A->length, B->length) - 1; i >= 0; i--) { fmpz_swap(A->exps + i, B->exps + i); fmpz_mod_mpoly_swap(COEFF(A, i), B->coeffs + i, ctx); } FLINT_SWAP(slong, A->length, B->length); } int fmpz_mod_mpoly_univar_pseudo_gcd( fmpz_mod_mpoly_univar_t gx, const fmpz_mod_mpoly_univar_t ax, const fmpz_mod_mpoly_univar_t bx, const fmpz_mod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx, Gx; mpoly_void_ring_init_fmpz_mod_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_init(Gx, R); mpoly_univar_set_fmpz_mod_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_fmpz_mod_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_pseudo_gcd_ducos(Gx, Ax, Bx, R); if (success) mpoly_univar_swap_fmpz_mod_mpoly_univar(Gx, R, gx, ctx); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); mpoly_univar_clear(Gx, R); return success; } int fmpz_mod_mpoly_univar_resultant( fmpz_mod_mpoly_t d, const fmpz_mod_mpoly_univar_t ax, const fmpz_mod_mpoly_univar_t bx, const fmpz_mod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx; mpoly_void_ring_init_fmpz_mod_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_set_fmpz_mod_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_fmpz_mod_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_resultant(d, Ax, Bx, R); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); return success; } int fmpz_mod_mpoly_univar_discriminant( fmpz_mod_mpoly_t d, const fmpz_mod_mpoly_univar_t fx, const fmpz_mod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Fx; mpoly_void_ring_init_fmpz_mod_mpoly_ctx(R, ctx); mpoly_univar_init(Fx, R); mpoly_univar_set_fmpz_mod_mpoly_univar(Fx, R, fx, ctx); success = mpoly_univar_discriminant(d, Fx, R); mpoly_univar_clear(Fx, R); return success; } flint-3.1.3/src/fmpz_mod_mpoly/void_ring.c000066400000000000000000000075251461254215100206120ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" static void fmpz_mod_mpoly_void_init(void * a, const void * ctx) { fmpz_mod_mpoly_init(a, ctx); } static void fmpz_mod_mpoly_void_clear(void * a, const void * ctx) { fmpz_mod_mpoly_clear(a, ctx); } static int fmpz_mod_mpoly_void_is_zero(const void * a, const void * ctx) { return fmpz_mod_mpoly_is_zero(a, ctx); } static void fmpz_mod_mpoly_void_zero(void * a, const void * ctx) { fmpz_mod_mpoly_zero(a, ctx); } static void fmpz_mod_mpoly_void_one(void * a, const void * ctx) { fmpz_mod_mpoly_one(a, ctx); } static void fmpz_mod_mpoly_void_set(void * a, const void * b, const void * ctx) { fmpz_mod_mpoly_set(a, b, ctx); } static void fmpz_mod_mpoly_void_set_fmpz(void * a, const fmpz_t b, const void * ctx) { fmpz_mod_mpoly_set_fmpz(a, b, ctx); } static void fmpz_mod_mpoly_void_swap(void * a, void * b, const void * ctx) { fmpz_mod_mpoly_swap(a, b, ctx); } static void fmpz_mod_mpoly_void_neg(void * a, const void * b, const void * ctx) { fmpz_mod_mpoly_neg(a, b, ctx); } static void fmpz_mod_mpoly_void_add(void * a, const void * b, const void * c, const void * ctx) { fmpz_mod_mpoly_add(a, b, c, ctx); } static void fmpz_mod_mpoly_void_sub(void * a, const void * b, const void * c, const void * ctx) { fmpz_mod_mpoly_sub(a, b, c, ctx); } static void fmpz_mod_mpoly_void_mul(void * a, const void * b, const void * c, const void * ctx) { fmpz_mod_mpoly_mul(a, b, c, ctx); } static void fmpz_mod_mpoly_void_mul_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { fmpz_mod_mpoly_scalar_mul_fmpz(a, b, c, ctx); } static void fmpz_mod_mpoly_void_divexact(void * a, const void * b, const void * c, const void * ctx) { if (!fmpz_mod_mpoly_divides(a, b, c, ctx)) flint_throw(FLINT_ERROR, "fmpz_mod_mpoly_void_divexact: nonexact"); } static int fmpz_mod_mpoly_void_divides(void * a, const void * b, const void * c, const void * ctx) { return fmpz_mod_mpoly_divides(a, b, c, ctx); } static int fmpz_mod_mpoly_void_pow_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { return fmpz_mod_mpoly_pow_fmpz(a, b, c, ctx); } static slong fmpz_mod_mpoly_void_length(const void * a, const void * ctx) { return fmpz_mod_mpoly_length(a, ctx); } void mpoly_void_ring_init_fmpz_mod_mpoly_ctx( mpoly_void_ring_t R, const fmpz_mod_mpoly_ctx_t ctx) { R->elem_size = sizeof(fmpz_mod_mpoly_struct); R->ctx = ctx; R->init = fmpz_mod_mpoly_void_init; R->clear = fmpz_mod_mpoly_void_clear; R->is_zero = fmpz_mod_mpoly_void_is_zero; R->zero = fmpz_mod_mpoly_void_zero; R->one = fmpz_mod_mpoly_void_one; R->set = fmpz_mod_mpoly_void_set; R->set_fmpz = fmpz_mod_mpoly_void_set_fmpz; R->swap = fmpz_mod_mpoly_void_swap; R->neg = fmpz_mod_mpoly_void_neg; R->add = fmpz_mod_mpoly_void_add; R->sub = fmpz_mod_mpoly_void_sub; R->mul = fmpz_mod_mpoly_void_mul; R->mul_fmpz = fmpz_mod_mpoly_void_mul_fmpz; R->divexact = fmpz_mod_mpoly_void_divexact; R->divides = fmpz_mod_mpoly_void_divides; R->pow_fmpz = fmpz_mod_mpoly_void_pow_fmpz; R->length = fmpz_mod_mpoly_void_length; } flint-3.1.3/src/fmpz_mod_mpoly_factor.h000066400000000000000000001261061461254215100201720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_MPOLY_FACTOR_H #define FMPZ_MOD_MPOLY_FACTOR_H #ifdef FMPZ_MOD_MPOLY_FACTOR_INLINES_C #define FMPZ_MOD_MPOLY_FACTOR_INLINE #else #define FMPZ_MOD_MPOLY_FACTOR_INLINE static inline #endif #include "fmpz_mod_poly.h" #include "fmpz_mod_mpoly.h" #ifdef __cplusplus extern "C" { #endif FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpoly_factor_init(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_init_set_ui(f->constant, 1); f->poly = NULL; f->exp = NULL; f->num = 0; f->alloc = 0; } void fmpz_mod_mpoly_factor_init2(fmpz_mod_mpoly_factor_t f, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_factor_realloc(fmpz_mod_mpoly_factor_t f, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_factor_fit_length(fmpz_mod_mpoly_factor_t f, slong len, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_factor_clear(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_FACTOR_INLINE slong fmpz_mod_mpoly_factor_length(const fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) { return f->num; } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpoly_factor_get_constant_fmpz(fmpz_t c, const fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_set(c, f->constant); } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpoly_factor_get_base(fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_factor_t f, slong i, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fmpz_mod_mpoly_set(p, f->poly + i, ctx); } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpoly_factor_swap_base(fmpz_mod_mpoly_t p, fmpz_mod_mpoly_factor_t f, slong i, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fmpz_mod_mpoly_swap(p, f->poly + i, ctx); } FMPZ_MOD_MPOLY_FACTOR_INLINE slong fmpz_mod_mpoly_factor_get_exp_si(fmpz_mod_mpoly_factor_t f, slong i, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); return fmpz_get_si(f->exp + i); } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpoly_factor_swap(fmpz_mod_mpoly_factor_t f, fmpz_mod_mpoly_factor_t g, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_factor_struct t = *f; *f = *g; *g = t; } void fmpz_mod_mpoly_factor_set(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_factor_t g, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_factor_print_pretty(const fmpz_mod_mpoly_factor_t f, const char ** vars, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_factor_content(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_factor_squarefree(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_factor(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_factor_sort(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_factor_cmp(const fmpz_mod_mpoly_factor_t A, const fmpz_mod_mpoly_factor_t B, const fmpz_mod_mpoly_ctx_t ctx); /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ /* fmpz_mod_poly extras ******************************************************/ FMPZ_MOD_MPOLY_FACTOR_INLINE slong _fmpz_mod_poly_degree(const fmpz_mod_poly_t a) { return a->length - 1; } void fmpz_mod_poly_scalar_addmul_fmpz_mod(fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t C, const fmpz_t d0, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_addmul_linear(fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t C, const fmpz_t d1, const fmpz_t d0, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod( fmpz_mod_poly_t A, slong k, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_eval_pow(fmpz_t eval, const fmpz_mod_poly_t P, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_eval2_pow(fmpz_t evalp, fmpz_t evalm, const fmpz_mod_poly_t P, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx); /* fmpz_mod_mat extras *******************************************************/ int fmpz_mod_mat_is_reduced(const fmpz_mod_mat_t N, const fmpz_mod_ctx_t ctx); void fmpz_mod_mat_init_nullspace_tr(fmpz_mod_mat_t X, fmpz_mod_mat_t tmp, const fmpz_mod_ctx_t ctx); /*****************************************************************************/ typedef struct { fmpz_mod_poly_struct * coeffs; slong alloc; slong length; } fmpz_mod_bpoly_struct; typedef fmpz_mod_bpoly_struct fmpz_mod_bpoly_t[1]; typedef struct { fmpz_mod_bpoly_struct * coeffs; slong alloc; slong length; } fmpz_mod_tpoly_struct; typedef fmpz_mod_tpoly_struct fmpz_mod_tpoly_t[1]; typedef struct { ulong * exps; fmpz * coeffs; slong length; slong alloc; } fmpz_mod_polyu_struct; typedef fmpz_mod_polyu_struct fmpz_mod_polyu_t[1]; typedef struct { fmpz_mod_poly_struct * coeffs; ulong * exps; slong alloc; slong length; } fmpz_mod_polyun_struct; typedef fmpz_mod_polyun_struct fmpz_mod_polyun_t[1]; /* fmpz_mod_mpolyu_t sparse univariates with fmpz_mod_mpoly_t coefficients with uniform bits and LEX ordering */ typedef struct { fmpz_mod_mpoly_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* default bits to construct coeffs */ } fmpz_mod_mpolyu_struct; typedef fmpz_mod_mpolyu_struct fmpz_mod_mpolyu_t[1]; /* fmpz_mod_mpolyn_t sparse multivariates with fmpz_mod_poly_t coefficients with LEX ordering */ typedef struct { fmpz_mod_poly_struct * coeffs; ulong * exps; slong alloc; slong length; slong bits; } fmpz_mod_mpolyn_struct; typedef fmpz_mod_mpolyn_struct fmpz_mod_mpolyn_t[1]; /*****************************************************************************/ int fmpz_mod_mpoly_factor_separable(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, int sep); int fmpz_mod_mpoly_factor_expand(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_FACTOR_INLINE int fmpz_mod_mpoly_factor_matches(const fmpz_mod_mpoly_t a, const fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) { int matches; fmpz_mod_mpoly_t t; fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_factor_expand(t, f, ctx); matches = fmpz_mod_mpoly_equal(t, a, ctx); fmpz_mod_mpoly_clear(t, ctx); return matches; } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpoly_factor_append_fmpz_swap(fmpz_mod_mpoly_factor_t f, fmpz_mod_mpoly_t A, const fmpz_t e, const fmpz_mod_mpoly_ctx_t ctx) { slong i = f->num; fmpz_mod_mpoly_factor_fit_length(f, i + 1, ctx); fmpz_mod_mpoly_swap(f->poly + i, A, ctx); fmpz_set(f->exp + i, e); f->num = i + 1; } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpoly_factor_one(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_one(f->constant); f->num = 0; } void _fmpz_mod_mpoly_get_lead0( fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_set_lead0( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx); /*****************************************************************************/ void _fmpz_mod_mpoly_factor_set_nmod_mpoly_factor( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx, const nmod_mpoly_factor_t nf, const nmod_mpoly_ctx_t nctx); /* stack *********************************************************************/ typedef struct { fmpz_mod_poly_struct ** array; slong alloc; slong top; } fmpz_mod_poly_stack_struct; typedef fmpz_mod_poly_stack_struct fmpz_mod_poly_stack_t[1]; typedef struct { fmpz_mod_bpoly_struct ** array; slong alloc; slong top; } fmpz_mod_bpoly_stack_struct; typedef fmpz_mod_bpoly_stack_struct fmpz_mod_bpoly_stack_t[1]; typedef struct { fmpz_mod_polyun_struct ** array; slong alloc; slong top; } fmpz_mod_polyun_stack_struct; typedef fmpz_mod_polyun_stack_struct fmpz_mod_polyun_stack_t[1]; typedef struct { fmpz_mod_mpolyn_struct ** array; slong alloc; slong top; flint_bitcnt_t bits; } fmpz_mod_mpolyn_stack_struct; typedef fmpz_mod_mpolyn_stack_struct fmpz_mod_mpolyn_stack_t[1]; typedef struct { fmpz_mod_poly_stack_t poly_stack; fmpz_mod_bpoly_stack_t bpoly_stack; } fmpz_mod_poly_bpoly_stack_struct; typedef fmpz_mod_poly_bpoly_stack_struct fmpz_mod_poly_bpoly_stack_t[1]; typedef struct { fmpz_mod_poly_stack_t poly_stack; fmpz_mod_polyun_stack_t polyun_stack; } fmpz_mod_poly_polyun_stack_struct; typedef fmpz_mod_poly_polyun_stack_struct fmpz_mod_poly_polyun_stack_t[1]; typedef struct { fmpz_mod_poly_stack_t poly_stack; fmpz_mod_polyun_stack_t polyun_stack; fmpz_mod_mpolyn_stack_t mpolyn_stack; } fmpz_mod_poly_polyun_mpolyn_stack_struct; typedef fmpz_mod_poly_polyun_mpolyn_stack_struct fmpz_mod_poly_polyun_mpolyn_stack_t[1]; void fmpz_mod_poly_stack_init(fmpz_mod_poly_stack_t S); void fmpz_mod_poly_stack_clear(fmpz_mod_poly_stack_t S); fmpz_mod_poly_struct ** fmpz_mod_poly_stack_fit_request( fmpz_mod_poly_stack_t S, slong k); FMPZ_MOD_MPOLY_INLINE fmpz_mod_poly_struct ** fmpz_mod_poly_stack_request( fmpz_mod_poly_stack_t S, slong k) { fmpz_mod_poly_struct ** poly_top; poly_top = fmpz_mod_poly_stack_fit_request(S, k); S->top += k; return poly_top; } FMPZ_MOD_MPOLY_INLINE fmpz_mod_poly_struct * fmpz_mod_poly_stack_take_top(fmpz_mod_poly_stack_t S) { /* assume the request for 1 has already been fitted */ fmpz_mod_poly_struct ** poly_top; FLINT_ASSERT(S->top + 1 <= S->alloc); poly_top = S->array + S->top; S->top += 1; return poly_top[0]; } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_poly_stack_give_back(fmpz_mod_poly_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_poly_stack_size(const fmpz_mod_poly_stack_t S) { return S->top; } void fmpz_mod_bpoly_stack_init(fmpz_mod_bpoly_stack_t S); void fmpz_mod_bpoly_stack_clear(fmpz_mod_bpoly_stack_t S); fmpz_mod_bpoly_struct ** fmpz_mod_bpoly_stack_fit_request( fmpz_mod_bpoly_stack_t S, slong k); FMPZ_MOD_MPOLY_INLINE fmpz_mod_bpoly_struct ** fmpz_mod_bpoly_stack_request( fmpz_mod_bpoly_stack_t S, slong k) { fmpz_mod_bpoly_struct ** bpoly_top; bpoly_top = fmpz_mod_bpoly_stack_fit_request(S, k); S->top += k; return bpoly_top; } FMPZ_MOD_MPOLY_INLINE fmpz_mod_bpoly_struct * fmpz_mod_bpoly_stack_take_top(fmpz_mod_bpoly_stack_t S) { /* assume the request for 1 has already been fitted */ fmpz_mod_bpoly_struct ** bpoly_top; FLINT_ASSERT(S->top + 1 <= S->alloc); bpoly_top = S->array + S->top; S->top += 1; return bpoly_top[0]; } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_bpoly_stack_give_back(fmpz_mod_bpoly_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_bpoly_stack_size(const fmpz_mod_bpoly_stack_t S) { return S->top; } void fmpz_mod_polyun_stack_init(fmpz_mod_polyun_stack_t S); void fmpz_mod_polyun_stack_clear(fmpz_mod_polyun_stack_t S); fmpz_mod_polyun_struct ** fmpz_mod_polyun_stack_fit_request( fmpz_mod_polyun_stack_t S, slong k); FMPZ_MOD_MPOLY_INLINE fmpz_mod_polyun_struct ** fmpz_mod_polyun_stack_request( fmpz_mod_polyun_stack_t S, slong k) { fmpz_mod_polyun_struct ** polyun_top; polyun_top = fmpz_mod_polyun_stack_fit_request(S, k); S->top += k; return polyun_top; } FMPZ_MOD_MPOLY_INLINE fmpz_mod_polyun_struct * fmpz_mod_polyun_stack_take_top(fmpz_mod_polyun_stack_t S) { /* assume the request for 1 has already been fitted */ fmpz_mod_polyun_struct ** polyun_top; FLINT_ASSERT(S->top + 1 <= S->alloc); polyun_top = S->array + S->top; S->top += 1; return polyun_top[0]; } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_polyun_stack_give_back(fmpz_mod_polyun_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_polyun_stack_size(const fmpz_mod_polyun_stack_t S) { return S->top; } void fmpz_mod_mpolyn_stack_init(fmpz_mod_mpolyn_stack_t S, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_stack_clear(fmpz_mod_mpolyn_stack_t S, const fmpz_mod_mpoly_ctx_t ctx); fmpz_mod_mpolyn_struct ** fmpz_mod_mpolyn_stack_fit_request( fmpz_mod_mpolyn_stack_t S, slong k, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE fmpz_mod_mpolyn_struct ** fmpz_mod_mpolyn_stack_request( fmpz_mod_mpolyn_stack_t S, slong k, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpolyn_struct ** mpolyn_top; mpolyn_top = fmpz_mod_mpolyn_stack_fit_request(S, k, ctx); S->top += k; return mpolyn_top; } FMPZ_MOD_MPOLY_INLINE fmpz_mod_mpolyn_struct * fmpz_mod_mpolyn_stack_take_top(fmpz_mod_mpolyn_stack_t S) { /* assume the request for 1 has already been fitted */ fmpz_mod_mpolyn_struct ** mpolyn_top; FLINT_ASSERT(S->top + 1 <= S->alloc); mpolyn_top = S->array + S->top; S->top += 1; return mpolyn_top[0]; } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpolyn_stack_give_back(fmpz_mod_mpolyn_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_mpolyn_stack_size(const fmpz_mod_mpolyn_stack_t S) { return S->top; } /* poly_vec ******************************************************************/ slong _fmpz_mod_poly_vec_max_degree(const fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_vec_content(fmpz_mod_poly_t g, const fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_vec_remove_content(fmpz_mod_poly_t g, fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_vec_mul_poly(fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_vec_divexact_poly(fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_vec_mul_fmpz_mod(fmpz_mod_poly_struct * A, slong Alen, const fmpz_t g, const fmpz_mod_ctx_t ctx); /* polyun ********************************************************************/ FMPZ_MOD_MPOLY_FACTOR_INLINE ulong fmpz_mod_polyu1n_bidegree(const fmpz_mod_polyun_t A) { ulong x, y; FLINT_ASSERT(A->length > 0); x = A->exps[0]; y = A->coeffs[0].length - 1; return (x << (FLINT_BITS/2)) + y; } FMPZ_MOD_MPOLY_FACTOR_INLINE const fmpz * fmpz_mod_polyun_leadcoeff(const fmpz_mod_polyun_t A) { FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0].length > 0); return A->coeffs[0].coeffs + A->coeffs[0].length - 1; } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_polyun_swap(fmpz_mod_polyun_t A, fmpz_mod_polyun_t B) { fmpz_mod_polyun_struct t = *A; *A = *B; *B = t; } int fmpz_mod_polyun_is_canonical(const fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_polyun_init(fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx) { A->length = 0; A->alloc = 0; A->coeffs = NULL; A->exps = NULL; } void fmpz_mod_polyun_clear(fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx); void fmpz_mod_polyun_realloc(fmpz_mod_polyun_t A, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_polyu2n_print_pretty(const fmpz_mod_polyun_t A, const char * var0, const char * var1, const char * varlast, const fmpz_mod_ctx_t ctx); int fmpz_mod_polyun_equal(fmpz_mod_polyun_t A, const fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_polyun_set(fmpz_mod_polyun_t A, const fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_polyu3n_print_pretty( const fmpz_mod_polyun_t A, const char * var0, const char * var1, const char * var2, const char * varlast, const fmpz_mod_ctx_t ctx); void fmpz_mod_polyu1n_print_pretty(const fmpz_mod_polyun_t A, const char * var0, const char * varlast, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_polyun_fit_length(fmpz_mod_polyun_t A, slong len, const fmpz_mod_ctx_t ctx) { if (len > A->alloc) fmpz_mod_polyun_realloc(A, len, ctx); } void fmpz_mod_polyun_one(fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx); void fmpz_mod_mpoly_get_polyu1n(fmpz_mod_polyun_t A, const fmpz_mod_mpoly_t B, slong varx, slong vary, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_polyu1n(fmpz_mod_mpoly_t B, const fmpz_mod_polyun_t A, slong varx, slong vary, const fmpz_mod_mpoly_ctx_t ctx); /* mpolyn ********************************************************************/ void fmpz_mod_mpolyn_init(fmpz_mod_mpolyn_t A, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpolyn_swap(fmpz_mod_mpolyn_t A, fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpolyn_struct t = *A; *A = *B; *B = t; } void fmpz_mod_mpolyn_fit_length(fmpz_mod_mpolyn_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_FACTOR_INLINE const fmpz * fmpz_mod_mpolyn_leadcoeff(const fmpz_mod_mpolyn_t A) { FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0].length > 0); return A->coeffs[0].coeffs + A->coeffs[0].length - 1; } int fmpz_mod_mpolyn_is_canonical(const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); slong fmpz_mod_mpolyn_lastdeg(const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_clear(fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_one(fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_scalar_mul_fmpz_mod(fmpz_mod_mpolyn_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyn_equal(const fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_print_pretty(const fmpz_mod_mpolyn_t poly, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_cvtfrom_mpolyn( fmpz_mod_mpoly_t A, const fmpz_mod_mpolyn_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_cvtto_mpolyn( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_to_mpolyn_perm_deflate( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t nctx, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride); void fmpz_mod_mpoly_from_mpolyn_perm_inflate( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t nctx, const slong * perm, const ulong * shift, const ulong * stride); void fmpz_mod_mpolyn_set( fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyn_is_nonzero_fmpz( const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyn_divides( fmpz_mod_mpolyn_t Q, const fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx); /* interp ********************************************************************/ void fmpz_mod_polyu1n_interp_reduce_2sm_poly( fmpz_mod_poly_t E, fmpz_mod_poly_t F, const fmpz_mod_polyun_t A, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx); void fmpz_mod_polyu1n_interp_lift_2sm_poly( slong * lastdeg, fmpz_mod_polyun_t F, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_t alpha, const fmpz_mod_ctx_t ctx); int fmpz_mod_polyu1n_interp_crt_2sm_poly( slong * lastdeg, fmpz_mod_polyun_t F, fmpz_mod_polyun_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx); void fmpz_mod_mpolyn_interp_reduce_sm_poly( fmpz_mod_poly_t E, const fmpz_mod_mpolyn_t A, const fmpz_t alpha, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_interp_lift_sm_poly( fmpz_mod_mpolyn_t A, const fmpz_mod_poly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyn_interp_crt_sm_poly( slong * lastdeg_, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t modulus, const fmpz_t alpha, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_interp_reduce_2sm_mpolyn( fmpz_mod_mpolyn_t E, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t A, slong var, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_interp_lift_2sm_mpolyn( slong * lastdeg, fmpz_mod_mpolyn_t T, fmpz_mod_mpolyn_t A, fmpz_mod_mpolyn_t B, slong var, const fmpz_t alpha, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyn_interp_crt_2sm_mpolyn( slong * lastdeg, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t T, fmpz_mod_mpolyn_t A, fmpz_mod_mpolyn_t B, slong var, fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyn_interp_lift_sm_mpoly( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyn_interp_crt_sm_mpoly( slong * lastdeg, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t T, fmpz_mod_mpoly_t A, fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyn_interp_mcrt_sm_mpoly( slong * lastdeg, fmpz_mod_mpolyn_t F, const fmpz_mod_mpoly_t A, const fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx); /* polyu *********************************************************************/ FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_polyu_swap( fmpz_mod_polyu_t A, fmpz_mod_polyu_t B) { fmpz_mod_polyu_struct t = *A; *A = *B; *B = t; } void fmpz_mod_polyu_init(fmpz_mod_polyu_t A); void fmpz_mod_polyu_clear(fmpz_mod_polyu_t A); void fmpz_mod_polyu_realloc(fmpz_mod_polyu_t A, slong len); FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_polyu_fit_length( fmpz_mod_polyu_t a, slong len, const fmpz_mod_ctx_t ctx) { if (len > a->alloc) fmpz_mod_polyu_realloc(a, len); } void fmpz_mod_polyu3_degrees( slong * deg0, slong * deg1, slong * deg2, const fmpz_mod_polyu_t A); void fmpz_mod_polyu3_print_pretty( const fmpz_mod_polyu_t A, const char * var0, const char * var1, const char * var2, const fmpz_mod_ctx_t ctx); /* mpolyu ********************************************************************/ int fmpz_mod_mpolyu_is_canonical(const fmpz_mod_mpolyu_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyu3_print_pretty(const fmpz_mod_mpolyu_t A, const char * var0, const char * var1, const char * var2, const char ** vars, const fmpz_mod_mpoly_ctx_t ctx); /* bpoly *********************************************************************/ int fmpz_mod_bpoly_is_canonical(const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_bpoly_init(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } void fmpz_mod_bpoly_clear(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_bpoly_swap(fmpz_mod_bpoly_t A, fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_bpoly_struct t = *A; *A = *B; *B = t; } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_bpoly_get_coeff(fmpz_t c, const fmpz_mod_bpoly_t A, slong e0, slong e1, const fmpz_mod_ctx_t ctx) { if (e0 >= A->length) fmpz_zero(c); else fmpz_mod_poly_get_coeff_fmpz(c, A->coeffs + e0, e1, ctx); } FMPZ_MOD_MPOLY_FACTOR_INLINE slong fmpz_mod_bpoly_degree0(const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { return A->length - 1; } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_bpoly_normalise(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { while (A->length > 0 && fmpz_mod_poly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; } int fmpz_mod_bpoly_equal( const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_set( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_set_poly_gen1( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_set_poly_gen0( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_one(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MPOLY_FACTOR_INLINE int fmpz_mod_bpoly_is_one(const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { return A->length == 1 && fmpz_mod_poly_is_one(A->coeffs + 0, ctx); } slong fmpz_mod_bpoly_degree1(const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_print_pretty(const fmpz_mod_bpoly_t A, const char * xvar, const char * yvar, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_fit_length(fmpz_mod_bpoly_t A, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_set_coeff(fmpz_mod_bpoly_t A, slong xi, slong yi, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_zero(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_reverse_vars(fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_taylor_shift_gen1( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_sub( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_add( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_make_primitive( fmpz_mod_poly_t g, fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_mul( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_mul_series( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, slong order, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_divrem_series( fmpz_mod_bpoly_t Q, fmpz_mod_bpoly_t R, const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, slong order, const fmpz_mod_ctx_t ctx); int fmpz_mod_bpoly_divides( fmpz_mod_bpoly_t Q, const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_taylor_shift_gen0( fmpz_mod_bpoly_t A, const fmpz_t alpha, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_derivative_gen0( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_bpoly_make_monic_series( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, slong order, const fmpz_mod_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE void fmpz_mod_tpoly_init(fmpz_mod_tpoly_t A, const fmpz_mod_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_tpoly_swap(fmpz_mod_tpoly_t A, fmpz_mod_tpoly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_tpoly_struct t = *A; *A = *B; *B = t; } void fmpz_mod_tpoly_fit_length(fmpz_mod_tpoly_t A, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_tpoly_clear(fmpz_mod_tpoly_t A, const fmpz_mod_ctx_t ctx); void fmpz_mod_mpoly_get_fmpz_mod_bpoly(fmpz_mod_bpoly_t A, const fmpz_mod_mpoly_t B, slong var0, slong var1, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_set_fmpz_mod_bpoly(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_bpoly_t B, slong var0, slong var1, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_bpoly_factor_smprime(fmpz_mod_poly_t c, fmpz_mod_tpoly_t F, fmpz_mod_bpoly_t B, int allow_shift, const fmpz_mod_ctx_t ctx); /*****************************************************************************/ int _fmpz_mod_zip_vand_solve( fmpz * coeffs, /* in Fp: size mlength */ const fmpz * monomials, /* in Fp: size mlength */ slong mlength, const fmpz * evals, /* in Fp: size elength */ slong elength, const fmpz * master, /* in Fp: size mlength + 1 */ fmpz * scratch, /* in Fp: size mlength */ const fmpz_mod_ctx_t ctx); void _fmpz_mod_zip_eval_step( fmpz_t ev, fmpz * cur, /* in Fp */ const fmpz * inc, /* in Fp */ const fmpz * coeffs, /* in Fp */ slong length, const fmpz_mod_ctx_t ctx); /*****************************************************************************/ typedef struct { fmpz_mod_mpoly_struct * coeffs; slong alloc; slong length; } fmpz_mod_mpolyv_struct; typedef fmpz_mod_mpolyv_struct fmpz_mod_mpolyv_t[1]; FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpolyv_init(fmpz_mod_mpolyv_t A, const fmpz_mod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FMPZ_MOD_MPOLY_FACTOR_INLINE void fmpz_mod_mpolyv_swap(fmpz_mod_mpolyv_t A, fmpz_mod_mpolyv_t B, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpolyv_struct t = *A; *A = *B; *B = t; } void fmpz_mod_mpolyv_clear(fmpz_mod_mpolyv_t A, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyv_print_pretty(const fmpz_mod_mpolyv_t poly, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyv_fit_length(fmpz_mod_mpolyv_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpolyv_set_coeff(fmpz_mod_mpolyv_t A, slong i, fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_to_mpolyv(fmpz_mod_mpolyv_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t xalpha, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_from_mpolyv(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpolyv_t B, const fmpz_mod_mpoly_t xalpha, const fmpz_mod_mpoly_ctx_t ctx); int _fmpz_mod_mpoly_vec_content_mpoly(fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_struct * A, slong Alen, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_vec_divexact_mpoly(fmpz_mod_mpoly_struct * A, slong Alen, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_vec_mul_mpoly(fmpz_mod_mpoly_struct * A, slong Alen, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx); /*****************************************************************************/ int _fmpz_mod_mpoly_factor_separable(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, int sep); int fmpz_mod_mpoly_factor_lcc_wang(fmpz_mod_mpoly_struct * lc_divs, const fmpz_mod_mpoly_factor_t lcAfac, const fmpz_mod_poly_t Auc, const fmpz_mod_bpoly_struct * Auf, slong r, const fmpz_mod_poly_struct * alpha, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_factor_irred_smprime_zassenhaus( fmpz_mod_mpolyv_t fac, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state); int fmpz_mod_mpoly_factor_irred_smprime_wang(fmpz_mod_mpolyv_t fac, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_factor_t lcAfac, const fmpz_mod_mpoly_t lcA, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state); int fmpz_mod_mpoly_factor_irred_smprime_zippel(fmpz_mod_mpolyv_t fac, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_factor_t lcAfac, const fmpz_mod_mpoly_t lcA, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state); /*****************************************************************************/ void fmpz_mod_mpoly_compression_do(fmpz_mod_mpoly_t L, const fmpz_mod_mpoly_ctx_t Lctx, fmpz * Acoeffs, slong Alen, mpoly_compression_t M); void fmpz_mod_mpoly_compression_undo(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t Actx, fmpz_mod_mpoly_t L, const fmpz_mod_mpoly_ctx_t Lctx, mpoly_compression_t M); /*****************************************************************************/ typedef struct { flint_bitcnt_t bits; slong w; slong r; fmpz_mod_poly_struct * inv_prod_dbetas; fmpz_mod_mpoly_struct * inv_prod_dbetas_mvar; fmpz_mod_poly_struct * dbetas; fmpz_mod_mpoly_struct * dbetas_mvar; fmpz_mod_mpoly_struct * prod_mbetas; fmpz_mod_mpolyv_struct * prod_mbetas_coeffs; fmpz_mod_mpoly_struct * mbetas; fmpz_mod_mpoly_struct * deltas; fmpz_mod_mpoly_struct * xalpha; fmpz_mod_mpoly_struct * q; fmpz_mod_mpoly_geobucket_struct * G; fmpz_mod_mpoly_struct * qt; fmpz_mod_mpoly_struct * newt; fmpz_mod_mpolyv_struct * delta_coeffs; fmpz_mod_mpoly_t T; fmpz_mod_mpoly_t Q; fmpz_mod_mpoly_t R; } fmpz_mod_mpoly_pfrac_struct; typedef fmpz_mod_mpoly_pfrac_struct fmpz_mod_mpoly_pfrac_t[1]; int fmpz_mod_mpoly_pfrac_init(fmpz_mod_mpoly_pfrac_t I, flint_bitcnt_t bits, slong l, slong r, const fmpz_mod_mpoly_struct * betas, const fmpz * alpha, const fmpz_mod_mpoly_ctx_t ctx); void fmpz_mod_mpoly_pfrac_clear(fmpz_mod_mpoly_pfrac_t I, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_pfrac(slong r, fmpz_mod_mpoly_t t, const slong * deg, fmpz_mod_mpoly_pfrac_t I, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_hlift(slong m, fmpz_mod_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_bpoly_pfrac(slong r, fmpz_mod_bpoly_struct * C, slong * C_deg1_bound, fmpz_mod_bpoly_t A, fmpz_mod_bpoly_struct * B, const fmpz_mod_ctx_t ctx); int fmpz_mod_bpoly_hlift2(fmpz_mod_bpoly_t A, fmpz_mod_bpoly_t B0, fmpz_mod_bpoly_t B1, const fmpz_t alpha, slong degree_inner, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_bpoly_stack_t St); int fmpz_mod_bpoly_hlift(slong r, fmpz_mod_bpoly_t A, fmpz_mod_bpoly_struct * B, const fmpz_t alpha, slong degree_inner, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_bpoly_stack_t St); int fmpz_mod_polyu3_hlift(slong r, fmpz_mod_polyun_struct * BB, fmpz_mod_polyu_t A, fmpz_mod_polyu_struct * B, const fmpz_t beta, slong degree_inner, const fmpz_mod_ctx_t ctx); int fmpz_mod_mpoly_hlift_zippel(slong m, fmpz_mod_mpoly_struct * B, slong r, const fmpz * alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state); int fmpz_mod_mpoly_factor_algo(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo); int fmpz_mod_mpoly_factor_zassenhaus(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_factor_wang(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpoly_factor_zippel(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); int _fmpz_mod_mpoly_evaluate_rest_fmpz_mod_poly(fmpz_mod_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, slong var, const fmpz_mod_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, const fmpz_mod_ctx_t ctx); void _fmpz_mod_mpoly_eval_rest_to_fmpz_mod_bpoly(fmpz_mod_bpoly_t E, const fmpz_mod_mpoly_t A, const fmpz_mod_poly_struct * alphabetas, const fmpz_mod_mpoly_ctx_t ctx); void _fmpz_mod_mpoly_set_fmpz_mod_bpoly_var1_zero(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_bpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx); /* gcd ***********************************************************************/ int _fmpz_mod_mpoly_gcd_algo(fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo); int fmpz_mod_polyu1n_gcd_brown_smprime( fmpz_mod_polyun_t G, fmpz_mod_polyun_t Abar, fmpz_mod_polyun_t Bbar, fmpz_mod_polyun_t A, fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_stack_t St_poly, fmpz_mod_polyun_stack_t St_polyun); int fmpz_mod_mpolyn_gcd_brown_smprime( fmpz_mod_mpolyn_t G, fmpz_mod_mpolyn_t Abar, fmpz_mod_mpolyn_t Bbar, fmpz_mod_mpolyn_t A, fmpz_mod_mpolyn_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, fmpz_mod_poly_polyun_mpolyn_stack_t St); int fmpz_mod_mpolyl_gcdp_zippel( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, fmpz_mod_mpoly_t A, fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state); int fmpz_mod_mpolyl_gcd_zippel2_smprime( fmpz_mod_mpoly_t rG, const slong * rGdegs, fmpz_mod_mpoly_t rAbar, fmpz_mod_mpoly_t rBbar, const fmpz_mod_mpoly_t A, const slong * Adegs, const fmpz_mod_mpoly_t B, const slong * Bdegs, const fmpz_mod_mpoly_t gamma, const slong * gammadegs, const fmpz_mod_mpoly_ctx_t ctx); int fmpz_mod_mpolyl_gcd_hensel_smprime( fmpz_mod_mpoly_t G, slong Gdeg, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); /* pow_cache */ void fmpz_mod_pow_cache_start(const fmpz_t b, fmpz_mod_poly_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_pow_cache_mulpow_ui(fmpz_t a, const fmpz_t b, ulong e, fmpz_mod_poly_t c, const fmpz_mod_ctx_t ctx); /* zip helpers */ void mpoly_monomial_evals_fmpz_mod( fmpz_mod_poly_t EH, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, fmpz_mod_poly_struct * alpha_caches, slong start, slong stop, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fpctx); void mpoly1_monomial_evals_fmpz_mod( fmpz_mod_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Amarks, slong Amarkslen, fmpz_mod_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fpctx); void mpoly2_monomial_evals_fmpz_mod( fmpz_mod_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, ulong * Amarks, slong Amarkslen, fmpz_mod_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fpctx); void fmpz_mod_mpoly_mock_eval_coeff( fmpz_mod_polyun_t mock, const fmpz_mod_mpoly_t A, const fmpz_mod_polyun_t Aeh_inc, const fmpz_mod_mpoly_ctx_t ctx); slong fmpz_mod_polyun_product_roots( fmpz_mod_polyun_t M, const fmpz_mod_polyun_t H, const fmpz_mod_ctx_t ctx); void fmpz_mod_polyun_zip_start( fmpz_mod_polyun_t Z, fmpz_mod_polyun_t H, slong req_images, const fmpz_mod_ctx_t fctx); void fmpz_mod_polyu2n_zip_eval_cur_inc_coeff( fmpz_mod_polyun_t E, fmpz_mod_polyun_t Acur, const fmpz_mod_polyun_t Ainc, const fmpz_mod_polyun_t Acoeff, const fmpz_mod_ctx_t ctx); int fmpz_mod_polyun_zip_solve( fmpz_mod_mpoly_t A, fmpz_mod_polyun_t Z, fmpz_mod_polyun_t H, fmpz_mod_polyun_t M, const fmpz_mod_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mod_mpoly_factor/000077500000000000000000000000001461254215100200135ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_mpoly_factor/bpoly_factor_smprime.c000066400000000000000000001254021461254215100244020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" #include "fmpz_poly_factor.h" #include "fmpz_mod_poly_factor.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_tpoly_fit_length( fmpz_mod_tpoly_t A, slong len, const fmpz_mod_ctx_t ctx) { slong i = A->alloc; if (len <= i) return; len = FLINT_MAX(len, 2*i); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, len, fmpz_mod_bpoly_struct); for ( ; i < len; i++) fmpz_mod_bpoly_init(A->coeffs + i, ctx); A->alloc = len; } void fmpz_mod_tpoly_clear(fmpz_mod_tpoly_t A, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mod_bpoly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } void fmpz_mod_bpoly_reverse_vars( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_mod_bpoly_zero(A, ctx); for (i = 0; i < B->length; i++) { fmpz_mod_poly_struct * Bi = B->coeffs + i; for (j = 0; j < Bi->length; j++) { if (!fmpz_is_zero(Bi->coeffs + j)) { fmpz_mod_bpoly_set_coeff(A, j, i, Bi->coeffs + j, ctx); } } } } void fmpz_mod_bpoly_make_monic_series( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, slong order, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t lcinv; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(B, ctx)); fmpz_mod_poly_init(lcinv, ctx); fmpz_mod_poly_inv_series(lcinv, B->coeffs + B->length - 1, order, ctx); fmpz_mod_bpoly_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) fmpz_mod_poly_mullow(A->coeffs + i, B->coeffs + i, lcinv, order, ctx); A->length = B->length; fmpz_mod_bpoly_normalise(A, ctx); fmpz_mod_poly_clear(lcinv, ctx); FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(A, ctx)); } static void fmpz_mod_bpoly_eval( fmpz_mod_poly_t E, const fmpz_mod_bpoly_t A, const fmpz_t alpha, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_zero(E, ctx); if (fmpz_is_zero(alpha)) { for (i = A->length - 1; i >= 0; i--) if (A->coeffs[i].length > 0) fmpz_mod_poly_set_coeff_fmpz(E, i, A->coeffs[i].coeffs + 0, ctx); return; } fmpz_mod_poly_fit_length(E, A->length, ctx); for (i = A->length - 1; i >= 0; i--) fmpz_mod_poly_evaluate_fmpz(E->coeffs + i, A->coeffs + i, alpha, ctx); _fmpz_mod_poly_set_length(E, A->length); _fmpz_mod_poly_normalise(E); } /****************** lifting **************************************************/ static void _hensel_lift_fac( fmpz_mod_bpoly_t G, fmpz_mod_bpoly_t H, const fmpz_mod_bpoly_t f, fmpz_mod_bpoly_t g, fmpz_mod_bpoly_t h, const fmpz_mod_bpoly_t a, const fmpz_mod_bpoly_t b, slong p0, slong p1, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_mod_bpoly_t c, t1, t2, q, r; fmpz_mod_bpoly_init(c, ctx); fmpz_mod_bpoly_init(t1, ctx); fmpz_mod_bpoly_init(t2, ctx); fmpz_mod_bpoly_init(q, ctx); fmpz_mod_bpoly_init(r, ctx); fmpz_mod_bpoly_mul(t1, g, h, ctx); fmpz_mod_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { for (j = 0; j < p0; j++) FLINT_ASSERT(j >= c->coeffs[i].length || fmpz_is_zero(c->coeffs[i].coeffs + j)); fmpz_mod_poly_shift_right(c->coeffs + i, c->coeffs + i, p0, ctx); fmpz_mod_poly_truncate(c->coeffs + i, p1, ctx); } fmpz_mod_bpoly_mul_series(t1, c, b, p1, ctx); fmpz_mod_bpoly_divrem_series(q, r, t1, g, p1, ctx); for (i = 0; i < r->length; i++) fmpz_mod_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < g->length; i++) fmpz_mod_poly_truncate(g->coeffs + i, p0, ctx); fmpz_mod_bpoly_add(t1, r, g, ctx); fmpz_mod_bpoly_mul_series(t2, c, a, p1, ctx); fmpz_mod_bpoly_divrem_series(q, r, t2, h, p1, ctx); for (i = 0; i < r->length; i++) fmpz_mod_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < h->length; i++) fmpz_mod_poly_truncate(h->coeffs + i, p0, ctx); fmpz_mod_bpoly_add(t2, r, h, ctx); fmpz_mod_bpoly_swap(G, t1, ctx); fmpz_mod_bpoly_swap(H, t2, ctx); #if FLINT_WANT_ASSERT fmpz_mod_bpoly_mul(t1, G, H, ctx); fmpz_mod_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) for (j = 0; j < p0 + p1; j++) FLINT_ASSERT(j >= c->coeffs[i].length || fmpz_is_zero(c->coeffs[i].coeffs + j)); #endif fmpz_mod_bpoly_clear(c, ctx); fmpz_mod_bpoly_clear(t1, ctx); fmpz_mod_bpoly_clear(t2, ctx); fmpz_mod_bpoly_clear(q, ctx); fmpz_mod_bpoly_clear(r, ctx); } static void _hensel_lift_inv( fmpz_mod_bpoly_t A, fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t G, const fmpz_mod_bpoly_t H, fmpz_mod_bpoly_t a, fmpz_mod_bpoly_t b, slong p0, slong p1, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_mod_bpoly_t c, t1, t2, q, r; fmpz_mod_bpoly_init(c, ctx); fmpz_mod_bpoly_init(t1, ctx); fmpz_mod_bpoly_init(t2, ctx); fmpz_mod_bpoly_init(q, ctx); fmpz_mod_bpoly_init(r, ctx); for (i = 0; i < a->length; i++) fmpz_mod_poly_truncate(a->coeffs + i, p0, ctx); for (i = 0; i < b->length; i++) fmpz_mod_poly_truncate(b->coeffs + i, p0, ctx); fmpz_mod_bpoly_mul(t1, G, a, ctx); fmpz_mod_bpoly_mul(t2, H, b, ctx); fmpz_mod_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) fmpz_mod_poly_neg(c->coeffs + i, c->coeffs + i, ctx); fmpz_mod_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); fmpz_mod_bpoly_normalise(c, ctx); for (i = 0; i < c->length; i++) { for (j = 0; j < p0; j++) FLINT_ASSERT(j >= c->coeffs[i].length || fmpz_is_zero(c->coeffs[i].coeffs + j)); fmpz_mod_poly_shift_right(c->coeffs + i, c->coeffs + i, p0, ctx); fmpz_mod_poly_truncate(c->coeffs + i, p1, ctx); } fmpz_mod_bpoly_mul_series(t1, c, b, p1, ctx); fmpz_mod_bpoly_divrem_series(q, r, t1, G, p1, ctx); for (i = 0; i < r->length; i++) fmpz_mod_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); fmpz_mod_bpoly_add(t1, r, b, ctx); fmpz_mod_bpoly_mul_series(t2, c, a, p1, ctx); fmpz_mod_bpoly_divrem_series(q, r, t2, H, p1, ctx); for (i = 0; i < r->length; i++) fmpz_mod_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); fmpz_mod_bpoly_add(t2, r, a, ctx); fmpz_mod_bpoly_swap(t1, B, ctx); fmpz_mod_bpoly_swap(t2, A, ctx); #if FLINT_WANT_ASSERT fmpz_mod_bpoly_mul(t1, G, A, ctx); fmpz_mod_bpoly_mul(t2, H, B, ctx); fmpz_mod_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) fmpz_mod_poly_neg(c->coeffs + i, c->coeffs + i, ctx); fmpz_mod_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); fmpz_mod_bpoly_normalise(c, ctx); for (i = 0; i < c->length; i++) for (j = 0; j < p0 + p1; j++) FLINT_ASSERT(j >= c->coeffs[i].length || fmpz_is_zero(c->coeffs[i].coeffs + j)); #endif fmpz_mod_bpoly_clear(c, ctx); fmpz_mod_bpoly_clear(t1, ctx); fmpz_mod_bpoly_clear(t2, ctx); fmpz_mod_bpoly_clear(q, ctx); fmpz_mod_bpoly_clear(r, ctx); } static void _hensel_lift_tree( int opt, slong * link, fmpz_mod_bpoly_struct * v, fmpz_mod_bpoly_struct * w, const fmpz_mod_bpoly_t f, slong j, slong p0, slong p1, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(p1 <= p0); if (j < 0) return; if (opt >= 0) _hensel_lift_fac(v + j, v + j + 1, f, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); if (opt <= 0) _hensel_lift_inv(w + j, w + j + 1, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j, link[j], p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j + 1, link[j + 1], p0, p1, ctx); } typedef struct { slong * link; fmpz_mod_bpoly_struct ** lifted_fac; fmpz_mod_tpoly_t tmp; fmpz_mod_bpoly_t bmp; slong r; slong fac_lift_order; slong inv_lift_order; int use_linear; } fmpz_mod_bpoly_lift_struct; typedef fmpz_mod_bpoly_lift_struct fmpz_mod_bpoly_lift_t[1]; static void fmpz_mod_bpoly_lift_init( fmpz_mod_bpoly_lift_t L, const fmpz_mod_ctx_t ctx) { L->link = NULL; L->lifted_fac = NULL; fmpz_mod_tpoly_init(L->tmp, ctx); fmpz_mod_bpoly_init(L->bmp, ctx); L->r = 0; L->fac_lift_order = 0; L->inv_lift_order = 0; } static void fmpz_mod_bpoly_lift_clear( fmpz_mod_bpoly_lift_t L, const fmpz_mod_ctx_t ctx) { flint_free(L->link); flint_free(L->lifted_fac); fmpz_mod_tpoly_clear(L->tmp, ctx); fmpz_mod_bpoly_clear(L->bmp, ctx); } static void _fmpz_mod_bpoly_lift_build_tree( fmpz_mod_bpoly_lift_t L, fmpz_mod_bpoly_struct * local_facs, slong r, const fmpz_mod_bpoly_t monicA, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_mod_bpoly_struct * v, * w; slong e[FLINT_BITS+1]; slong * link; fmpz_mod_poly_t d, g, h, a, b; fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); FLINT_ASSERT(r > 1); L->link = FLINT_ARRAY_REALLOC(L->link, 2*r - 2, slong); link = L->link; fmpz_mod_tpoly_clear(L->tmp, ctx); fmpz_mod_tpoly_init(L->tmp, ctx); fmpz_mod_tpoly_fit_length(L->tmp, 2*(2*r - 2), ctx); v = L->tmp->coeffs + 0; w = L->tmp->coeffs + (2*r - 2); for (i = 0; i < r; i++) { fmpz_mod_bpoly_swap(v + i, local_facs + i, ctx); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp, mind; minp = j; mind = fmpz_mod_bpoly_degree0(v + j, ctx); for (s = j + 1; s < i; s++) { if (fmpz_mod_bpoly_degree0(v + s, ctx) < mind) { minp = s; mind = fmpz_mod_bpoly_degree0(v + s, ctx); } } fmpz_mod_bpoly_swap(v + j, v + minp, ctx); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = fmpz_mod_bpoly_degree0(v + j + 1, ctx); for (s = j + 2; s < i; s++) { if (fmpz_mod_bpoly_degree0(v + s, ctx) < mind) { minp = s; mind = fmpz_mod_bpoly_degree0(v + s, ctx); } } fmpz_mod_bpoly_swap(v + j + 1, v + minp, ctx); FLINT_SWAP(slong, link[j + 1], link[minp]); fmpz_mod_bpoly_mul_series(v + i, v + j, v + j + 1, L->fac_lift_order, ctx); link[i] = j; } for (j = 0; j < 2*r - 2; j += 2) { fmpz zero = 0; fmpz_mod_bpoly_eval(g, v + j, &zero, ctx); fmpz_mod_bpoly_eval(h, v + j + 1, &zero, ctx); fmpz_mod_poly_xgcd(d, a, b, g, h, ctx); if (!fmpz_mod_poly_is_one(d, ctx)) flint_throw(FLINT_IMPINV, "fmpz_mod_bpoly_lift: bad inverse"); fmpz_mod_bpoly_set_poly_gen0(w + j, a, ctx); fmpz_mod_bpoly_set_poly_gen0(w + j + 1, b, ctx); } fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); for (i = 0; i < 2*r - 2; i++) if (-L->link[i] - 1 >= 0) L->lifted_fac[-L->link[i] - 1] = v + i; for (i = 0, e[i] = L->inv_lift_order; e[i] > 1; i++) e[i+1] = (e[i] + 1)/2; e[i] = 1; for (i--; i >= 0; i--) _hensel_lift_tree(-1, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); } static void _fmpz_mod_bpoly_lift_build_steps( fmpz_mod_bpoly_lift_t L, const fmpz_mod_ctx_t ctx) { slong i, j, k; slong r = L->r; slong order = L->fac_lift_order; fmpz_mod_bpoly_struct * A, * Bfinal, * U, * B; fmpz_mod_poly_struct * s, * Binv; fmpz_mod_poly_struct * c, * t; FLINT_ASSERT(L->tmp->alloc >= 4*r + 1); A = L->tmp->coeffs; Bfinal = A + 1; U = Bfinal + r; B = U + r; FLINT_ASSERT(L->bmp->alloc >= 2*r + 5); s = L->bmp->coeffs; Binv = s + r; c = Binv + r; t = c + 1; for (k = 0; k < r; k++) { /* s[k] = (prod_{i!=k} B[i].coeffs[0])^-1 (mod B[k].coeffs[0]) */ fmpz_mod_poly_div(t, A->coeffs + 0, B[k].coeffs + 0, ctx); if (!fmpz_mod_poly_invmod(s + k, t, B[k].coeffs + 0, ctx)) flint_throw(FLINT_IMPINV, "fmpz_mod_bpoly_lift: bad inverse"); /* set up mul (mod B[k].coeffs[0]) */ fmpz_mod_poly_reverse(t, B[k].coeffs + 0, B[k].coeffs[0].length, ctx); fmpz_mod_poly_inv_series(Binv + k, t, B[k].coeffs[0].length, ctx); } /* U[0], U[r-1] are not used, zero out both U and Ue */ for (k = 1; k < r - 1; k++) { fmpz_mod_bpoly_fit_length(U + k, order, ctx); for (i = U[k].length; i < order; i++) U[k].coeffs[i].length = 0; U[k].length = order; } if (r > 2) { for (j = 0; j < order; j++) { k = r - 2; fmpz_mod_poly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { fmpz_mod_poly_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (k--; k > 0; k--) { fmpz_mod_poly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length) { fmpz_mod_poly_mul(t, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } } } } } /* linear lifting has large memory requirements wrt r */ static int _use_linear_cutoff(slong r, slong degx) { return r < 30 + 5*FLINT_BIT_COUNT(degx); } static void fmpz_mod_bpoly_lift_start( fmpz_mod_bpoly_lift_t L, fmpz_mod_poly_struct * local_facs, slong r, const fmpz_mod_bpoly_t monicA, const fmpz_mod_ctx_t ctx) { slong i, k; slong degx = fmpz_mod_bpoly_degree0(monicA, ctx); fmpz_mod_bpoly_struct * A, * Bfinal, * U, * B; FLINT_ASSERT(r > 1); L->r = r; L->lifted_fac = FLINT_ARRAY_REALLOC(L->lifted_fac, r, fmpz_mod_bpoly_struct*); L->fac_lift_order = 1; L->inv_lift_order = 1; L->use_linear = _use_linear_cutoff(r, degx); if (!L->use_linear) { fmpz_mod_bpoly_struct * new_facs = FLINT_ARRAY_ALLOC(r, fmpz_mod_bpoly_struct); for (i = 0; i < r; i++) { fmpz_mod_bpoly_init(new_facs + i, ctx); fmpz_mod_bpoly_set_poly_gen0(new_facs + i, local_facs + i, ctx); } _fmpz_mod_bpoly_lift_build_tree(L, new_facs, r, monicA, ctx); for (i = 0; i < r; i++) fmpz_mod_bpoly_clear(new_facs + i, ctx); flint_free(new_facs); } else { fmpz_mod_tpoly_fit_length(L->tmp, 4*r + 1, ctx); A = L->tmp->coeffs; Bfinal = A + 1; U = Bfinal + r; B = U + r; fmpz_mod_bpoly_fit_length(L->bmp, 2*r + 5, ctx); fmpz_mod_bpoly_fit_length(A, 1, ctx); A->length = 1; fmpz_mod_poly_one(A->coeffs + 0, ctx); for (k = 0; k < r; k++) { fmpz_mod_bpoly_fit_length(B + k, 1, ctx); B[k].length = 1; fmpz_mod_poly_set(B[k].coeffs + 0, local_facs + k, ctx); fmpz_mod_poly_mul(A->coeffs + 0, A->coeffs + 0, B[k].coeffs + 0, ctx); L->lifted_fac[k] = Bfinal + k; fmpz_mod_bpoly_reverse_vars(L->lifted_fac[k], B + k, ctx); U[k].length = 0; } _fmpz_mod_bpoly_lift_build_steps(L, ctx); } } /* assuming N is reduced combine the factors in L according to the rows of N and then replace N by an identity matrix */ void fmpz_mod_bpoly_lift_combine( fmpz_mod_bpoly_lift_t L, fmpz_mod_mat_t N, const fmpz_mod_bpoly_t monicA, const fmpz_mod_ctx_t ctx) { slong i, j, k, r, degx; fmpz_mod_bpoly_struct * A, * Bfinal, * U, * B; slong oldr = L->r; slong newr = fmpz_mod_mat_nrows(N, ctx); slong order = L->fac_lift_order; fmpz_mod_bpoly_struct * new_facs; fmpz_mod_bpoly_t T; FLINT_ASSERT(newr > 1); FLINT_ASSERT(newr < oldr); FLINT_ASSERT(oldr == fmpz_mod_mat_ncols(N, ctx)); FLINT_ASSERT(fmpz_mod_mat_is_reduced(N, ctx)); /* on input we should have a factorization of monicA mod y^order */ #if FLINT_WANT_ASSERT { fmpz_mod_bpoly_t t1, t2; fmpz_mod_bpoly_init(t1, ctx); fmpz_mod_bpoly_init(t2, ctx); fmpz_mod_bpoly_set(t1, L->lifted_fac[0], ctx); for (k = 1; k < L->r; k++) { fmpz_mod_bpoly_mul_series(t2, t1, L->lifted_fac[k], order, ctx); fmpz_mod_bpoly_swap(t1, t2, ctx); } fmpz_mod_bpoly_sub(t2, monicA, t1, ctx); for (i = 0; i < t2->length; i++) for (j = 0; j < order; j++) FLINT_ASSERT(j >= t2->coeffs[i].length || fmpz_is_zero(t2->coeffs[i].coeffs + j)); fmpz_mod_bpoly_clear(t1, ctx); fmpz_mod_bpoly_clear(t2, ctx); } #endif fmpz_mod_bpoly_init(T, ctx); new_facs = FLINT_ARRAY_ALLOC(newr, fmpz_mod_bpoly_struct); for (i = 0; i < newr; i++) { fmpz_mod_bpoly_init(new_facs + i, ctx); fmpz_mod_bpoly_one(new_facs + i, ctx); for (j = 0; j < oldr; j++) { if (fmpz_is_zero(fmpz_mod_mat_entry(N, i, j))) continue; FLINT_ASSERT(fmpz_is_one(fmpz_mod_mat_entry(N, i, j))); fmpz_mod_bpoly_mul_series(T, new_facs + i, L->lifted_fac[j], order, ctx); fmpz_mod_bpoly_swap(new_facs + i, T, ctx); } } L->r = r = newr; degx = fmpz_mod_bpoly_degree0(monicA, ctx); /* do not use quadratic lifting if we were not already */ L->use_linear = L->use_linear || _use_linear_cutoff(r, degx); if (!L->use_linear) { _fmpz_mod_bpoly_lift_build_tree(L, new_facs, newr, monicA, ctx); for (i = 0; i < newr; i++) fmpz_mod_bpoly_clear(new_facs + i, ctx); flint_free(new_facs); fmpz_mod_bpoly_clear(T, ctx); } else { A = L->tmp->coeffs; Bfinal = A + 1; fmpz_mod_bpoly_swap(T, A, ctx); fmpz_mod_tpoly_clear(L->tmp, ctx); fmpz_mod_tpoly_init(L->tmp, ctx); fmpz_mod_tpoly_fit_length(L->tmp, 4*r + 1, ctx); A = L->tmp->coeffs; fmpz_mod_bpoly_swap(A, T, ctx); fmpz_mod_bpoly_clear(T, ctx); Bfinal = A + 1; U = Bfinal + r; B = U + r; fmpz_mod_bpoly_clear(L->bmp, ctx); fmpz_mod_bpoly_init(L->bmp, ctx); fmpz_mod_bpoly_fit_length(L->bmp, 2*r + 5, ctx); for (i = 0; i < newr; i++) { L->lifted_fac[i] = Bfinal + i; fmpz_mod_bpoly_swap(Bfinal + i, new_facs + i, ctx); fmpz_mod_bpoly_clear(new_facs + i, ctx); } flint_free(new_facs); for (k = 0; k < r; k++) { fmpz_mod_bpoly_reverse_vars(B + k, L->lifted_fac[k], ctx); FLINT_ASSERT(B[k].length <= order); fmpz_mod_bpoly_fit_length(B + k, order, ctx); for (i = B[k].length; i < order; i++) fmpz_mod_poly_zero(B[k].coeffs + i, ctx); } _fmpz_mod_bpoly_lift_build_steps(L, ctx); } fmpz_mod_mat_clear(N, ctx); fmpz_mod_mat_init(N, L->r, L->r, ctx); for (i = 0; i < L->r; i++) fmpz_one(fmpz_mod_mat_entry(N, i, i)); /* on output we should have a factorization of monicA mod y^order */ #if FLINT_WANT_ASSERT { fmpz_mod_bpoly_t t1, t2; fmpz_mod_bpoly_init(t1, ctx); fmpz_mod_bpoly_init(t2, ctx); fmpz_mod_bpoly_set(t1, L->lifted_fac[0], ctx); for (k = 1; k < L->r; k++) { fmpz_mod_bpoly_mul_series(t2, t1, L->lifted_fac[k], order, ctx); fmpz_mod_bpoly_swap(t1, t2, ctx); } fmpz_mod_bpoly_sub(t2, monicA, t1, ctx); for (i = 0; i < t2->length; i++) for (j = 0; j < order; j++) FLINT_ASSERT(j >= t2->coeffs[i].length || fmpz_is_zero(t2->coeffs[i].coeffs + j)); fmpz_mod_bpoly_clear(t1, ctx); fmpz_mod_bpoly_clear(t2, ctx); } #endif } static void fmpz_mod_bpoly_lift_continue( fmpz_mod_bpoly_lift_t L, const fmpz_mod_bpoly_t monicA, slong order, const fmpz_mod_ctx_t ctx) { slong i, j, k; slong r = L->r; fmpz_mod_bpoly_struct * A, * Bfinal, * U, * Ue, * B; fmpz_mod_poly_struct * s, * Binv; fmpz_mod_poly_struct * c, * t, * ce, * vk; if (order <= L->fac_lift_order) return; if (!L->use_linear) { fmpz_mod_bpoly_struct * v = L->tmp->coeffs + 0; fmpz_mod_bpoly_struct * w = L->tmp->coeffs + (2*r - 2); slong e[FLINT_BITS+1]; FLINT_ASSERT(1 <= L->inv_lift_order); FLINT_ASSERT(L->fac_lift_order <= 2*L->inv_lift_order); for (i = 0, e[i] = order; e[i] > L->fac_lift_order; i++) e[i+1] = (e[i] + 1)/2; e[i] = L->fac_lift_order; e[i+1] = L->inv_lift_order; if (e[i+1] < e[i]) _hensel_lift_tree(-1, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); for (i--; i > 0; i--) _hensel_lift_tree(0, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); _hensel_lift_tree(1, L->link, v, w, monicA, 2*r-4, e[1], e[0]-e[1], ctx); L->fac_lift_order = e[0]; L->inv_lift_order = e[1]; return; } A = L->tmp->coeffs; Bfinal = A + 1; U = Ue = Bfinal + r; B = U + r; s = L->bmp->coeffs; Binv = s + r; c = Binv + r; t = c + 1; ce = t + 1; vk = ce + 1; /* tack on reversal of monicA */ for (i = 0; i < monicA->length; i++) { fmpz_mod_poly_struct * Bi = monicA->coeffs + i; j = FLINT_MIN(Bi->length, order); for (j--; j >= L->fac_lift_order; j--) fmpz_mod_bpoly_set_coeff(A, j, i, Bi->coeffs + j, ctx); } /* tack on zeros to the B[k] */ for (k = 0; k < r; k++) { fmpz_mod_bpoly_fit_length(B + k, order, ctx); for (i = B[k].length; i < order; i++) { fmpz_mod_poly_zero(B[k].coeffs + i, ctx); } /* U[0] is not used, zero out both U and Ue */ if (k > 0) { fmpz_mod_bpoly_fit_length(U + k, order, ctx); for (i = U[k].length; i < order; i++) U[k].coeffs[i].length = 0; U[k].length = order; } } if (r > 2) { for (j = L->fac_lift_order; j < order; j++) { k = r - 2; fmpz_mod_poly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { fmpz_mod_poly_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (k--; k > 0; k--) { fmpz_mod_poly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length) { fmpz_mod_poly_mul(t, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } } if (j < A->length) fmpz_mod_poly_set(c, A->coeffs + j, ctx); else fmpz_mod_poly_zero(c, ctx); for (i = 0; i <= j; i++) { if (i < B[0].length) { fmpz_mod_poly_mul(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx); fmpz_mod_poly_sub(c, c, t, ctx); } } if (fmpz_mod_poly_is_zero(c, ctx)) continue; for (k = r - 1; k >= 0; k--) { fmpz_mod_poly_rem(t, c, B[k].coeffs + 0, ctx); fmpz_mod_poly_mulmod_preinv(vk, s + k, t, B[k].coeffs + 0, Binv + k, ctx); if (!fmpz_mod_poly_is_zero(vk, ctx)) { fmpz_mod_poly_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!fmpz_mod_poly_is_zero(B[k].coeffs + j, ctx)) B[k].length = FLINT_MAX(B[k].length, j + 1); } /* correct the U's */ if (k > r - 2) { fmpz_mod_poly_swap(ce, vk, ctx); } else if (k > 0) { fmpz_mod_poly_struct * p; fmpz_mod_poly_mul(t, B[k].coeffs + 0, ce, ctx); p = (k == r - 2) ? B[k + 1].coeffs : U[k + 1].coeffs; fmpz_mod_poly_mul(ce, p, vk, ctx); fmpz_mod_poly_add(ce, ce, t, ctx); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, ce, ctx); } } } } else { FLINT_ASSERT(r == 2); for (j = L->fac_lift_order; j < order; j++) { if (j < A->length) fmpz_mod_poly_set(c, A->coeffs + j, ctx); else fmpz_mod_poly_zero(c, ctx); for (i = FLINT_MIN(j, B[0].length - 1); i >= 0; i--) { fmpz_mod_poly_mul(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx); fmpz_mod_poly_sub(c, c, t, ctx); } if (fmpz_mod_poly_is_zero(c, ctx)) continue; for (k = 0; k < r; k++) { fmpz_mod_poly_rem(t, c, B[k].coeffs + 0, ctx); fmpz_mod_poly_mulmod_preinv(vk, s + k, t, B[k].coeffs + 0, Binv + k, ctx); if (!fmpz_mod_poly_is_zero(vk, ctx)) { fmpz_mod_poly_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!fmpz_mod_poly_is_zero(B[k].coeffs + j, ctx)) B[k].length = FLINT_MAX(B[k].length, j + 1); } } } } L->fac_lift_order = order; for (k = 0; k < r; k++) fmpz_mod_bpoly_reverse_vars(Bfinal + k, B + k, ctx); #if FLINT_WANT_ASSERT { fmpz_mod_bpoly_t t1, t2; fmpz_mod_bpoly_init(t1, ctx); fmpz_mod_bpoly_init(t2, ctx); fmpz_mod_bpoly_set(t1, Bfinal + 0, ctx); for (k = 1; k < r; k++) { fmpz_mod_bpoly_mul_series(t2, t1, Bfinal + k, order, ctx); fmpz_mod_bpoly_swap(t1, t2, ctx); } fmpz_mod_bpoly_sub(t2, monicA, t1, ctx); for (i = 0; i < t2->length; i++) { for (j = 0; j < FLINT_MIN(order, t2->coeffs[i].length); j++) { FLINT_ASSERT(fmpz_is_zero(t2->coeffs[i].coeffs + j)); } } fmpz_mod_bpoly_clear(t1, ctx); fmpz_mod_bpoly_clear(t2, ctx); } #endif } /************* lattice reduction ********************************************/ /* The rows of N, if they are 0-1, correspond to combinations of the g that give factors of A. Compute {A/g[i]*g[i]'}_i and use the CLD bounds to try to make N smaller. */ static void _lattice( fmpz_mod_mat_t N, fmpz_mod_bpoly_struct * const * g, slong r, slong lift_order, slong * CLD, slong * lattice_order, const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { slong i, j, k; fmpz_mod_bpoly_t Q, R, dg; fmpz_mod_bpoly_struct * ld; fmpz_mod_mat_t M, T1, T2; fmpz * trow; trow = _fmpz_vec_init(r); fmpz_mod_bpoly_init(Q, ctx); fmpz_mod_bpoly_init(R, ctx); fmpz_mod_bpoly_init(dg, ctx); ld = FLINT_ARRAY_ALLOC(r, fmpz_mod_bpoly_struct); for (i = 0; i < r; i++) { fmpz_mod_bpoly_init(ld + i, ctx); fmpz_mod_bpoly_divrem_series(Q, R, A, g[i], lift_order, ctx); FLINT_ASSERT(R->length == 0); fmpz_mod_bpoly_derivative_gen0(R, g[i], ctx); fmpz_mod_bpoly_mul_series(ld + i, Q, R, lift_order, ctx); } for (k = 0; k + 1 < A->length; k++) { slong nrows = fmpz_mod_mat_nrows(N, ctx); slong lower = FLINT_MAX(CLD[k], *lattice_order); FLINT_ASSERT(nrows > 0); /* consider powers y^j for which j >= lattice_order (j < lattice_order has already been added) j >= CLD[k] j < lift_order */ if (lift_order <= lower) continue; fmpz_mod_mat_init(M, lift_order - lower, nrows, ctx); for (j = lower; j < lift_order; j++) { for (i = 0; i < r; i++) fmpz_mod_bpoly_get_coeff(trow + i, ld + i, k, j, ctx); for (i = 0; i < nrows; i++) _fmpz_mod_vec_dot(fmpz_mod_mat_entry(M, j - lower, i), trow, N->rows[i], r, ctx); } fmpz_mod_mat_init_nullspace_tr(T1, M, ctx); fmpz_mod_mat_init(T2, fmpz_mod_mat_nrows(T1, ctx), fmpz_mod_mat_ncols(N, ctx), ctx); fmpz_mod_mat_mul(T2, T1, N, ctx); fmpz_mod_mat_swap(T2, N, ctx); fmpz_mod_mat_rref(N, N, ctx); fmpz_mod_mat_clear(M, ctx); fmpz_mod_mat_clear(T1, ctx); fmpz_mod_mat_clear(T2, ctx); } _fmpz_vec_clear(trow, r); fmpz_mod_bpoly_clear(Q, ctx); fmpz_mod_bpoly_clear(R, ctx); fmpz_mod_bpoly_clear(dg, ctx); for (i = 0; i < r; i++) fmpz_mod_bpoly_clear(ld + i, ctx); flint_free(ld); *lattice_order = lift_order; } /**************** recombination **********************************************/ /* First multiply the g[i] into the gprod[i] according the the rows of N. Then, run zassenhaus on the gprod[i] as factors of A. */ static int _zassenhaus( const zassenhaus_prune_t zas, slong limit, fmpz_mod_tpoly_t F, const fmpz_t malpha, const fmpz_mod_mat_t N, fmpz_mod_bpoly_struct * const * g, slong r, slong order, const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { slong total_deg; int success; fmpz_mod_bpoly_t Q, R, t1, t2; fmpz_mod_poly_t cont; slong i, j, k, len, nrows = fmpz_mod_mat_nrows(N, ctx); slong * subset; fmpz_mod_bpoly_struct * gprod; fmpz_mod_bpoly_struct * f; fmpz_mod_bpoly_t A_copy; int is_simple_check = (limit == 1 && r == fmpz_mod_mat_nrows(N, ctx)); FLINT_ASSERT(fmpz_mod_mat_is_reduced(N, ctx)); FLINT_ASSERT(fmpz_mod_mat_ncols(N, ctx) == r); fmpz_mod_poly_init(cont, ctx); fmpz_mod_bpoly_init(Q, ctx); fmpz_mod_bpoly_init(R, ctx); fmpz_mod_bpoly_init(t1, ctx); fmpz_mod_bpoly_init(t2, ctx); fmpz_mod_bpoly_init(A_copy, ctx); gprod = FLINT_ARRAY_ALLOC(nrows, fmpz_mod_bpoly_struct); subset = FLINT_ARRAY_ALLOC(nrows, slong); for (i = 0; i < nrows; i++) { subset[i] = i; fmpz_mod_bpoly_init(gprod + i, ctx); fmpz_mod_bpoly_one(gprod + i, ctx); for (j = 0; j < r; j++) { if (fmpz_is_zero(fmpz_mod_mat_entry(N, i, j))) continue; FLINT_ASSERT(fmpz_is_one(fmpz_mod_mat_entry(N, i, j))); fmpz_mod_bpoly_mul_series(t1, gprod + i, g[j], order, ctx); fmpz_mod_bpoly_swap(gprod + i, t1, ctx); } } f = (fmpz_mod_bpoly_struct *) A; len = nrows; for (k = 1; k <= len/2; k++) { if (k > limit) { success = 0; goto cleanup; } zassenhaus_subset_first(subset, len, k); while (1) { total_deg = 0; for (i = 0; i < len; i++) { if (subset[i] >= 0) total_deg += gprod[subset[i]].length - 1; } if (!zassenhaus_prune_degree_is_possible(zas, total_deg)) { if (!zassenhaus_subset_next(subset, len)) break; continue; } FLINT_ASSERT(f->length > 0); fmpz_mod_bpoly_set_poly_gen1(t1, f->coeffs + f->length - 1, ctx); for (i = 0; i < len; i++) { if (subset[i] >= 0) { fmpz_mod_bpoly_mul_series(t2, t1, gprod + subset[i], order, ctx); fmpz_mod_bpoly_swap(t1, t2, ctx); } } fmpz_mod_bpoly_make_primitive(cont, t1, ctx); if (fmpz_mod_bpoly_divides(Q, f, t1, ctx)) { fmpz_mod_bpoly_taylor_shift_gen1(t1, t1, malpha, ctx); fmpz_mod_tpoly_fit_length(F, F->length + 1, ctx); fmpz_mod_bpoly_swap(F->coeffs + F->length, t1, ctx); F->length++; f = A_copy; fmpz_mod_bpoly_swap(f, Q, ctx); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else if (is_simple_check) { success = 0; goto cleanup; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (f->length > 1) { fmpz_mod_tpoly_fit_length(F, F->length + 1, ctx); fmpz_mod_bpoly_taylor_shift_gen1(F->coeffs + F->length, f, malpha, ctx); F->length++; } else { FLINT_ASSERT(f->length == 1); FLINT_ASSERT(fmpz_mod_poly_is_one(f->coeffs + 0, ctx)); } success = 1; cleanup: for (i = 0; i < nrows; i++) fmpz_mod_bpoly_clear(gprod + i, ctx); flint_free(gprod); flint_free(subset); fmpz_mod_poly_clear(cont, ctx); fmpz_mod_bpoly_clear(Q, ctx); fmpz_mod_bpoly_clear(R, ctx); fmpz_mod_bpoly_clear(t1, ctx); fmpz_mod_bpoly_clear(t2, ctx); fmpz_mod_bpoly_clear(A_copy, ctx); return success; } /*****************************************************************************/ /* x = gen(0), y = gen(1). A is supposed to be separable wrt x. Put the content of A wrt x in c, and the factors in F. Return 1 for success, i.e. a good small prime (y - alpha) was found. If allow_shift is false, only (y - 0) is tried. TODO: copy this precision strategy to the other bpoly factorers The helpers fmpz_mod_bpoly_lift_{start|continue|combine} are used: start: start the lift mod y^0 continue: lift up to mod y^n combine: when the lattice work has proven several factors to be grouped together, combine these and start over with fewer local factors. ex: if N = [1 1 0 1 0], [0 0 1 0 1] then combine the five factors f1,...,f5 into two f1*f2*f4, f3*f5 */ int fmpz_mod_bpoly_factor_smprime( fmpz_mod_poly_t c, /* poly in y */ fmpz_mod_tpoly_t F, fmpz_mod_bpoly_t A, /* clobbered */ int allow_shift, const fmpz_mod_ctx_t ctx) { int success; slong i, r; slong Alenx, Aleny; slong final_order, lift_order, lattice_order; slong * CLD; fmpz_mod_poly_t Aeval; fmpz_t alpha_best, alpha_tmp, malpha_best; fmpz_mod_poly_factor_t local_fac_best, local_fac_tmp; int local_fac_tries = 0; fmpz_mod_bpoly_t monicA; fmpz_mod_mat_t N; slong zas_limit; zassenhaus_prune_t zas; fmpz_mod_bpoly_lift_t L; fmpz_mod_bpoly_make_primitive(c, A, ctx); Alenx = A->length; FLINT_ASSERT(Alenx > 1); fmpz_init(alpha_tmp); fmpz_init(alpha_best); fmpz_init(malpha_best); fmpz_mod_poly_init(Aeval, ctx); fmpz_mod_poly_factor_init(local_fac_best, ctx); fmpz_mod_poly_factor_init(local_fac_tmp, ctx); fmpz_mod_bpoly_init(monicA, ctx); fmpz_mod_mat_init(N, 0, 0, ctx); CLD = FLINT_ARRAY_ALLOC(Alenx, slong); zassenhaus_prune_init(zas); fmpz_mod_bpoly_lift_init(L, ctx); Aleny = 0; for (i = 0; i < Alenx; i++) { Aleny = FLINT_MAX(Aleny, A->coeffs[i].length); CLD[i] = A->coeffs[i].length; } mpoly_bivar_cld_bounds(CLD, Alenx); zassenhaus_prune_set_degree(zas, Alenx - 1); fmpz_zero(alpha_tmp); fmpz_zero(alpha_best); goto got_alpha; next_alpha: fmpz_add_ui(alpha_tmp, alpha_tmp, 1); if (!allow_shift || fmpz_cmp(alpha_tmp, fmpz_mod_ctx_modulus(ctx)) >= 0) { if (local_fac_best->num > 0) goto doit; success = 0; goto cleanup; } got_alpha: fmpz_mod_bpoly_eval(Aeval, A, alpha_tmp, ctx); /* if killed leading coeff, get new alpha */ if (Aeval->length != Alenx) goto next_alpha; /* note the constant term of Aeval can be zero */ fmpz_mod_poly_factor(local_fac_tmp, Aeval, ctx); r = local_fac_tmp->num; zassenhaus_prune_start_add_factors(zas); for (i = 0; i < r; i++) zassenhaus_prune_add_factor(zas, local_fac_tmp->poly[i].length - 1, local_fac_tmp->exp[i]); zassenhaus_prune_end_add_factors(zas); if (r < 2 && local_fac_tmp->exp[0] == 1) goto irreducible; if (zassenhaus_prune_must_be_irreducible(zas)) goto irreducible; /* if multiple factors, get new alpha */ for (i = 0; i < r; i++) { FLINT_ASSERT(local_fac_tmp->poly[i].length > 1); FLINT_ASSERT(fmpz_is_one(fmpz_mod_poly_lead(local_fac_tmp->poly + i, ctx))); if (local_fac_tmp->exp[i] != 1) goto next_alpha; } /* done if A is constant in y */ if (Aleny < 2) { fmpz_mod_tpoly_fit_length(F, r, ctx); F->length = r; for (i = 0; i < r; i++) fmpz_mod_bpoly_set_poly_gen0(F->coeffs + i, local_fac_tmp->poly + i, ctx); success = 1; goto cleanup; } /* alpha_tmp & local_fac_tmp are good; update best */ if (local_fac_best->num < 1 || local_fac_best->num > local_fac_tmp->num) { fmpz_set(alpha_best, alpha_tmp); fmpz_mod_poly_factor_swap(local_fac_best, local_fac_tmp, ctx); } if (++local_fac_tries < 2) goto next_alpha; doit: fmpz_mod_bpoly_taylor_shift_gen1(A, A, alpha_best, ctx); /* local_fac_best is a factorization mod (y - alpha_best) */ r = local_fac_best->num; /* precision for constructing true factors */ final_order = Aleny; /* precision for lifted local factors */ lift_order = Aleny; for (i = 0; i < Alenx - 1; i++) if (CLD[i] > 0 && lift_order > CLD[i]) lift_order = CLD[i]; lift_order = lift_order + 4; /* lift up to y^lift_order */ fmpz_mod_bpoly_make_monic_series(monicA, A, lift_order, ctx); fmpz_mod_bpoly_lift_start(L, local_fac_best->poly, r, monicA, ctx); fmpz_mod_bpoly_lift_continue(L, monicA, lift_order, ctx); /* the rows of N give the combinations of local factors */ fmpz_mod_mat_clear(N, ctx); fmpz_mod_mat_init(N, r, r, ctx); for (i = 0; i < r; i++) fmpz_one(fmpz_mod_mat_entry(N, i, i)); /* size limit on subsets in zassenhaus combination */ zas_limit = 1; lattice_order = 0; _lattice(N, L->lifted_fac, L->r, lift_order, CLD, &lattice_order, A, ctx); if (fmpz_mod_mat_nrows(N, ctx) < 2) goto irreducible_shift; if (!fmpz_mod_mat_is_reduced(N, ctx)) goto increase; if (fmpz_mod_mat_nrows(N, ctx) < fmpz_mod_mat_ncols(N, ctx)/4*3) fmpz_mod_bpoly_lift_combine(L, N, monicA, ctx); try_zas: /* zassenhaus only make sense if N is a nice 0-1 mat */ FLINT_ASSERT(fmpz_mod_mat_is_reduced(N, ctx)); while (fmpz_mod_mat_nrows(N, ctx) > 2 && 2*L->fac_lift_order < final_order) { lift_order = 2*L->fac_lift_order; fmpz_mod_bpoly_make_monic_series(monicA, A, lift_order, ctx); fmpz_mod_bpoly_lift_continue(L, monicA, lift_order, ctx); _lattice(N, L->lifted_fac, L->r, lift_order, CLD, &lattice_order, A, ctx); if (fmpz_mod_mat_nrows(N, ctx) < 2) goto irreducible_shift; if (!fmpz_mod_mat_is_reduced(N, ctx)) goto increase; if (fmpz_mod_mat_nrows(N, ctx) < fmpz_mod_mat_ncols(N, ctx)/4*3) fmpz_mod_bpoly_lift_combine(L, N, monicA, ctx); } if (L->fac_lift_order < final_order) { lift_order = final_order; fmpz_mod_bpoly_make_monic_series(monicA, A, lift_order, ctx); fmpz_mod_bpoly_lift_continue(L, monicA, lift_order, ctx); } /* combine local factors according the rows of N, then by subsets */ F->length = 0; fmpz_mod_neg(malpha_best, alpha_best, ctx); success = _zassenhaus(zas, zas_limit, F, malpha_best, N, L->lifted_fac, L->r, final_order, A, ctx); if (success) goto cleanup; /* first attempt failed, try subsets of size 1 or 2 from now on */ zas_limit = 2; more: /* increase precision until N is a nice 0-1 mat */ _lattice(N, L->lifted_fac, L->r, lift_order, CLD, &lattice_order, A, ctx); if (fmpz_mod_mat_nrows(N, ctx) < 2) goto irreducible_shift; if (!fmpz_mod_mat_is_reduced(N, ctx)) goto increase; if (fmpz_mod_mat_nrows(N, ctx) < fmpz_mod_mat_ncols(N, ctx)/4*3) fmpz_mod_bpoly_lift_combine(L, N, monicA, ctx); goto try_zas; increase: if (lift_order < final_order) lift_order += 4 + lift_order/2; else lift_order += 1 + lift_order/8; fmpz_mod_bpoly_make_monic_series(monicA, A, lift_order, ctx); fmpz_mod_bpoly_lift_continue(L, monicA, lift_order, ctx); goto more; cleanup: fmpz_mod_bpoly_lift_clear(L, ctx); flint_free(CLD); fmpz_clear(alpha_tmp); fmpz_clear(alpha_best); fmpz_clear(malpha_best); fmpz_mod_mat_clear(N, ctx); fmpz_mod_poly_clear(Aeval, ctx); fmpz_mod_poly_factor_clear(local_fac_best, ctx); fmpz_mod_poly_factor_clear(local_fac_tmp, ctx); fmpz_mod_bpoly_clear(monicA, ctx); zassenhaus_prune_clear(zas); return success; irreducible_shift: fmpz_mod_neg(malpha_best, alpha_best, ctx); fmpz_mod_bpoly_taylor_shift_gen1(A, A, malpha_best, ctx); irreducible: fmpz_mod_tpoly_fit_length(F, 1, ctx); F->length = 1; fmpz_mod_bpoly_swap(F->coeffs + 0, A, ctx); success = 1; goto cleanup; } flint-3.1.3/src/fmpz_mod_mpoly_factor/bpoly_hlift.c000066400000000000000000000265041461254215100225010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_bpoly_hlift2( fmpz_mod_bpoly_t A, /* clobbered (shifted by alpha) */ fmpz_mod_bpoly_t B0, fmpz_mod_bpoly_t B1, const fmpz_t alpha, slong degree_inner, /* required degree in x */ const fmpz_mod_ctx_t ctx, fmpz_mod_poly_bpoly_stack_t St) { int success; slong i, j; fmpz_t malpha; fmpz_mod_poly_struct * c, * s, * t, * u, * v; FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(B0, ctx)); FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(B1, ctx)); if (A->length < 1 || B0->length < 1 || B1->length < 1) return -1; fmpz_init(malpha); fmpz_mod_poly_stack_fit_request(St->poly_stack, 5); c = fmpz_mod_poly_stack_take_top(St->poly_stack); s = fmpz_mod_poly_stack_take_top(St->poly_stack); t = fmpz_mod_poly_stack_take_top(St->poly_stack); u = fmpz_mod_poly_stack_take_top(St->poly_stack); v = fmpz_mod_poly_stack_take_top(St->poly_stack); fmpz_mod_bpoly_taylor_shift_gen0(A, alpha, ctx); fmpz_mod_bpoly_taylor_shift_gen0(B0, alpha, ctx); fmpz_mod_bpoly_taylor_shift_gen0(B1, alpha, ctx); /* supposed to have A(alpha,x) = B0(alpha,x) * B1(alpha,x) */ FLINT_ASSERT(fmpz_mod_poly_degree(A->coeffs + 0, ctx) == fmpz_mod_poly_degree(B0->coeffs + 0, ctx) + fmpz_mod_poly_degree(B1->coeffs + 0, ctx)); if (fmpz_mod_poly_degree(A->coeffs + 0, ctx) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(fmpz_mod_bpoly_degree1(A, ctx) == fmpz_mod_poly_degree(A->coeffs + 0, ctx)); if (!fmpz_mod_poly_invmod(s, B1->coeffs + 0, B0->coeffs + 0, ctx)) { success = -2; goto cleanup; } fmpz_mod_bpoly_fit_length(B0, A->length, ctx); fmpz_mod_bpoly_fit_length(B1, A->length, ctx); for (j = 1; j < A->length; j++) { fmpz_mod_poly_set(c, A->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { fmpz_mod_poly_mul(t, B0->coeffs + i, B1->coeffs + j - i, ctx); fmpz_mod_poly_sub(c, c, t, ctx); } } if (fmpz_mod_poly_is_zero(c, ctx)) continue; fmpz_mod_poly_mul(t, s, c, ctx); fmpz_mod_poly_rem(u, t, B0->coeffs + 0, ctx); fmpz_mod_poly_mul(t, u, B1->coeffs + 0, ctx); fmpz_mod_poly_sub(c, c, t, ctx); fmpz_mod_poly_div(v, c, B0->coeffs + 0, ctx); if (j < B0->length) fmpz_mod_poly_add(B0->coeffs + j, B0->coeffs + j, u, ctx); else fmpz_mod_poly_set(B0->coeffs + j, u, ctx); if (j < B1->length) fmpz_mod_poly_add(B1->coeffs + j, B1->coeffs + j, v, ctx); else fmpz_mod_poly_set(B1->coeffs + j, v, ctx); if (!fmpz_mod_poly_is_zero(B0->coeffs + j, ctx)) B0->length = FLINT_MAX(B0->length, j + 1); if (!fmpz_mod_poly_is_zero(B1->coeffs + j, ctx)) B1->length = FLINT_MAX(B1->length, j + 1); if (B0->length - 1 + B1->length - 1 > A->length - 1) { success = 0; goto cleanup; } } fmpz_mod_neg(malpha, alpha, ctx); fmpz_mod_bpoly_taylor_shift_gen0(B0, malpha, ctx); fmpz_mod_bpoly_taylor_shift_gen0(B1, malpha, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { fmpz_mod_bpoly_t tp1, tp2; fmpz_mod_bpoly_init(tp1, ctx); fmpz_mod_bpoly_init(tp2, ctx); fmpz_mod_neg(malpha, alpha, ctx); fmpz_mod_bpoly_taylor_shift_gen0(A, malpha, ctx); fmpz_mod_bpoly_mul(tp1, B0, B1, ctx); FLINT_ASSERT(fmpz_mod_bpoly_equal(tp1, A, ctx)); fmpz_mod_bpoly_clear(tp1, ctx); fmpz_mod_bpoly_clear(tp2, ctx); } #endif fmpz_clear(malpha); fmpz_mod_poly_stack_give_back(St->poly_stack, 5); return success; } /* y = gen(0), x = gen(1) input A, Bi with A(y,x) = prod_i Bi(y,x) ctx (y-alpha) return -1: the Bi(alpha,x) are not pairwise prime, or A(alpha,x) has wrong degree w.r.t x 0: lift of the Bi to true factors is impossible 1: successfully lifted the Bi to true factors without changing lc_x */ int fmpz_mod_bpoly_hlift( slong r, fmpz_mod_bpoly_t A, /* clobbered (shifted by alpha) */ fmpz_mod_bpoly_struct * B, const fmpz_t alpha, slong degree_inner, /* required degree in x */ const fmpz_mod_ctx_t ctx, fmpz_mod_poly_bpoly_stack_t St) { int success; slong i, j, k, tdeg; fmpz_t malpha; fmpz_mod_poly_struct * c, * t, * u; fmpz_mod_poly_struct ** s, ** v, ** Binv; fmpz_mod_bpoly_struct ** U; TMP_INIT; FLINT_ASSERT(r >= 2); if (r < 3) return fmpz_mod_bpoly_hlift2(A, B + 0, B + 1, alpha, degree_inner, ctx, St); FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(A, ctx)); if (A->length < 1) return -1; for (i = 0; i < r; i++) { FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(B + i, ctx)); if (B[i].length < 1) return -1; } TMP_START; fmpz_mod_bpoly_stack_fit_request(St->bpoly_stack, r); U = TMP_ARRAY_ALLOC(r, fmpz_mod_bpoly_struct *); for (i = 0; i < r; i++) { U[i] = fmpz_mod_bpoly_stack_take_top(St->bpoly_stack); fmpz_mod_bpoly_fit_length(U[i], A->length, ctx); for (j = 0; j < A->length; j++) fmpz_mod_poly_zero(U[i]->coeffs + j, ctx); U[i]->length = A->length; fmpz_mod_bpoly_fit_length(B + i, A->length, ctx); } fmpz_mod_poly_stack_fit_request(St->poly_stack, 3*r + 3); s = TMP_ARRAY_ALLOC(3*r, fmpz_mod_poly_struct *); v = s + r; Binv = v + r; for (i = 0; i < r; i++) { s[i] = fmpz_mod_poly_stack_take_top(St->poly_stack); v[i] = fmpz_mod_poly_stack_take_top(St->poly_stack); Binv[i] = fmpz_mod_poly_stack_take_top(St->poly_stack); } fmpz_init(malpha); c = fmpz_mod_poly_stack_take_top(St->poly_stack); t = fmpz_mod_poly_stack_take_top(St->poly_stack); u = fmpz_mod_poly_stack_take_top(St->poly_stack); fmpz_mod_bpoly_taylor_shift_gen0(A, alpha, ctx); for (i = 0; i < r; i++) fmpz_mod_bpoly_taylor_shift_gen0(B + i, alpha, ctx); /* supposed to have A(alpha,x) = B0(alpha,x) * B1(alpha,x) * ... */ j = 0; for (i = 0; i < r; i++) j += fmpz_mod_poly_degree(B[i].coeffs + 0, ctx); FLINT_ASSERT(j == fmpz_mod_poly_degree(A->coeffs + 0, ctx)); if (fmpz_mod_poly_degree(A->coeffs + 0, ctx) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(fmpz_mod_bpoly_degree1(A, ctx) == fmpz_mod_poly_degree(A->coeffs + 0, ctx)); for (i = 0; i < r; i++) { fmpz_mod_poly_one(t, ctx); for (j = 0; j < r; j++) { if (j != i) fmpz_mod_poly_mul(t, t, B[j].coeffs + 0, ctx); } if (!fmpz_mod_poly_invmod(s[i], t, B[i].coeffs + 0, ctx)) { success = -1; goto cleanup; } fmpz_mod_poly_reverse(t, B[i].coeffs + 0, B[i].coeffs[0].length, ctx); fmpz_mod_poly_inv_series(Binv[i], t, B[i].coeffs[0].length, ctx); } k = r - 2; fmpz_mod_poly_mul(U[k]->coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k > 0; k--) fmpz_mod_poly_mul(U[k]->coeffs + 0, B[k].coeffs + 0, U[k + 1]->coeffs + 0, ctx); for (j = 1; j < A->length; j++) { for (k = 0; k < r; k++) fmpz_mod_poly_zero(U[k]->coeffs + j, ctx); k = r - 2; fmpz_mod_poly_zero(U[k]->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { fmpz_mod_poly_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fmpz_mod_poly_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); } } for (k--; k > 0; k--) { fmpz_mod_poly_zero(U[k]->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length) { fmpz_mod_poly_mul(t, B[k].coeffs + i, U[k + 1]->coeffs + j - i, ctx); fmpz_mod_poly_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); } } } fmpz_mod_poly_set(c, A->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[0].length) { fmpz_mod_poly_mul(t, B[0].coeffs + i, U[1]->coeffs + j - i, ctx); fmpz_mod_poly_sub(c, c, t, ctx); } } if (fmpz_mod_poly_is_zero(c, ctx)) continue; tdeg = 0; for (i = 0; i < r; i++) { fmpz_mod_poly_rem(t, c, B[i].coeffs + 0, ctx); fmpz_mod_poly_mulmod_preinv(v[i], s[i], t, B[i].coeffs + 0, Binv[i], ctx); while (j >= B[i].length) { fmpz_mod_poly_zero(B[i].coeffs + B[i].length, ctx); B[i].length++; } fmpz_mod_poly_add(B[i].coeffs + j, B[i].coeffs + j, v[i], ctx); fmpz_mod_bpoly_normalise(B + i, ctx); tdeg += B[i].length - 1; } if (tdeg >= A->length) { success = 0; goto cleanup; } k = r - 2; fmpz_mod_poly_mul(t, B[k].coeffs + 0, v[k + 1], ctx); fmpz_mod_poly_mul(u, B[k + 1].coeffs + 0, v[k], ctx); fmpz_mod_poly_add(t, t, u, ctx); fmpz_mod_poly_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); for (k--; k > 0; k--) { fmpz_mod_poly_mul(u, B[k].coeffs + 0, t, ctx); fmpz_mod_poly_mul(t, U[k + 1]->coeffs + 0, v[k], ctx); fmpz_mod_poly_add(t, t, u, ctx); fmpz_mod_poly_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); } } fmpz_mod_neg(malpha, alpha, ctx); for (i = 0; i < r; i++) fmpz_mod_bpoly_taylor_shift_gen0(B + i, malpha, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { fmpz_mod_bpoly_t tp1, tp2; fmpz_mod_bpoly_init(tp1, ctx); fmpz_mod_bpoly_init(tp2, ctx); fmpz_mod_neg(malpha, alpha, ctx); fmpz_mod_bpoly_taylor_shift_gen0(A, malpha, ctx); fmpz_mod_bpoly_mul(tp1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { fmpz_mod_bpoly_mul(tp2, tp1, B + i, ctx); fmpz_mod_bpoly_swap(tp1, tp2, ctx); } FLINT_ASSERT(fmpz_mod_bpoly_equal(tp1, A, ctx)); fmpz_mod_bpoly_clear(tp1, ctx); fmpz_mod_bpoly_clear(tp2, ctx); } #endif fmpz_clear(malpha); fmpz_mod_bpoly_stack_give_back(St->bpoly_stack, r); fmpz_mod_poly_stack_give_back(St->poly_stack, 3*r + 3); TMP_END; return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/clear.c000066400000000000000000000014571461254215100212540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_mpoly_factor_clear( fmpz_mod_mpoly_factor_t fac, const fmpz_mod_mpoly_ctx_t ctx) { if (fac->alloc > 0) { slong i; for (i = 0; i < fac->alloc; i++) { fmpz_mod_mpoly_clear(fac->poly + i, ctx); fmpz_clear(fac->exp + i); } flint_free(fac->poly); flint_free(fac->exp); } fmpz_clear(fac->constant); } flint-3.1.3/src/fmpz_mod_mpoly_factor/cmp.c000066400000000000000000000017571461254215100207500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_factor_cmp( const fmpz_mod_mpoly_factor_t A, const fmpz_mod_mpoly_factor_t B, const fmpz_mod_mpoly_ctx_t ctx) { int cmp; slong i; cmp = fmpz_cmp(A->constant, B->constant); if (cmp != 0) return cmp; if (A->num != B->num) return A->num > B->num ? 1 : -1; for (i = 0; i < A->num; i++) { cmp = fmpz_cmp(A->exp + i, B->exp + i); if (cmp != 0) return cmp; cmp = fmpz_mod_mpoly_cmp(A->poly + i, B->poly + i, ctx); if (cmp != 0) return cmp; } return 0; } flint-3.1.3/src/fmpz_mod_mpoly_factor/compression.c000066400000000000000000000062321461254215100225230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_mpoly_compression_do( fmpz_mod_mpoly_t L, const fmpz_mod_mpoly_ctx_t Lctx, fmpz * Acoeffs, slong Alen, mpoly_compression_t M) { slong i, max_deg; flint_bitcnt_t Lbits; slong mvars = Lctx->minfo->nvars; slong nvars = M->nvars; slong LN; FLINT_ASSERT(mvars == M->mvars); max_deg = M->degs[0]; for (i = 1; i < mvars; i++) max_deg = FLINT_MAX(max_deg, M->degs[i]); Lbits = mpoly_fix_bits(1 + FLINT_BIT_COUNT(max_deg), Lctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(L, Alen, Lbits, Lctx); LN = mpoly_words_per_exp_sp(Lbits, Lctx->minfo); L->length = Alen; for (i = 0; i < Alen; i++) { fmpz_set(L->coeffs + i, Acoeffs + i); mpoly_set_monomial_ui(L->exps + LN*i, (ulong *)M->exps + nvars*i, Lbits, Lctx->minfo); } fmpz_mod_mpoly_sort_terms(L, Lctx); fmpz_mod_mpoly_make_monic(L, L, Lctx); } void fmpz_mod_mpoly_compression_undo( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t Actx, fmpz_mod_mpoly_t L, const fmpz_mod_mpoly_ctx_t Lctx, mpoly_compression_t M) { slong i, k, l; slong nvars = Actx->minfo->nvars; slong NA = mpoly_words_per_exp(Abits, Actx->minfo); slong mvars = Lctx->minfo->nvars; flint_bitcnt_t Lbits = L->bits; slong NL = mpoly_words_per_exp(Lbits, Lctx->minfo); slong * mins, * texps; TMP_INIT; FLINT_ASSERT(mvars == M->mvars); FLINT_ASSERT(fmpz_mod_mpoly_degrees_fit_si(L, Lctx)); TMP_START; texps = (slong *) TMP_ALLOC(nvars*sizeof(slong)); mins = (slong *) TMP_ALLOC(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) mins[k] = WORD_MAX; _slong_array_fit_length(&M->exps, &M->exps_alloc, L->length*nvars); fmpz_mod_mpoly_fit_length_reset_bits(A, L->length, Abits, Actx); _fmpz_mod_mpoly_set_length(A, L->length, Actx); for (i = 0; i < L->length; i++) { fmpz_set(A->coeffs + i, L->coeffs + i); mpoly_get_monomial_ui((ulong *)texps, L->exps + NL*i, Lbits, Lctx->minfo); for (k = 0; k < nvars; k++) { slong tot = M->deltas[k]; for (l = 0; l < mvars; l++) tot += M->umat[k*nvars + l]*texps[l]; M->exps[i*nvars + k] = tot; mins[k] = FLINT_MIN(mins[k], tot); } } for (i = 0; i < L->length; i++) { for (k = 0; k < nvars; k++) M->exps[i*nvars + k] -= mins[k]; mpoly_set_monomial_ui(A->exps + NA*i, (ulong *)M->exps + i*nvars, Abits, Actx->minfo); } TMP_END; fmpz_mod_mpoly_sort_terms(A, Actx); fmpz_mod_mpoly_make_monic(A, A, Actx); } flint-3.1.3/src/fmpz_mod_mpoly_factor/eval.c000066400000000000000000000142311461254215100211070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" /* only E and alphas are shifted by "var" so output is in E[0] */ int _fmpz_mod_mpoly_evaluate_rest_fmpz_mod_poly( fmpz_mod_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, slong var, const fmpz_mod_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, const fmpz_mod_ctx_t ctx) { slong v, stop; ulong next_e; FLINT_ASSERT(var < nvars); E -= var; alphas -= var; v = var; starts[v] = 0; ends[v] = Alen; fmpz_mod_poly_zero(E + v, ctx); if (Alen < 1) return 1; calculate: /* input: v starts[v] ends[v] */ FLINT_ASSERT(ends[v] > starts[v]); es[v] = mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]); fmpz_mod_poly_zero(E + v, ctx); next: FLINT_ASSERT(es[v] == (mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]))); stop = starts[v] + 1; while (stop < ends[v] && (mask & (Aexps[N*stop + offsets[v]] >> shifts[v])) == es[v]) { stop++; } stops[v] = stop; if (v + 1 < nvars) { starts[v + 1] = starts[v]; ends[v + 1] = stops[v]; v++; goto calculate; calculate_return: fmpz_mod_poly_add(E + v, E + v, E + v + 1, ctx); } else { fmpz_mod_poly_add_fmpz(E + v, E + v, Acoeffs + starts[v], ctx); } if (stops[v] < ends[v]) { next_e = mask & (Aexps[N*stops[v] + offsets[v]] >> shifts[v]); FLINT_ASSERT(next_e < es[v]); fmpz_mod_poly_pow(E + v + 1, alphas + v, es[v] - next_e, ctx); fmpz_mod_poly_mul(E + v, E + v, E + v + 1, ctx); es[v] = next_e; starts[v] = stops[v]; goto next; } else { fmpz_mod_poly_pow(E + v + 1, alphas + v, es[v], ctx); fmpz_mod_poly_mul(E + v, E + v, E + v + 1, ctx); } if (v > var) { v--; goto calculate_return; } return 1; } void _fmpz_mod_mpoly_eval_rest_to_fmpz_mod_bpoly( fmpz_mod_bpoly_t E, const fmpz_mod_mpoly_t A, const fmpz_mod_poly_struct * alphabetas, const fmpz_mod_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong * offsets, * shifts; slong offset, shift; slong start, stop; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * starts, * ends, * stops; ulong * es; fmpz_mod_poly_struct * realE; E->length = 0; if (A->length < 1) return; starts = FLINT_ARRAY_ALLOC(n, slong); ends = FLINT_ARRAY_ALLOC(n, slong); stops = FLINT_ARRAY_ALLOC(n, slong); es = FLINT_ARRAY_ALLOC(n, ulong); realE = FLINT_ARRAY_ALLOC(n + 1, fmpz_mod_poly_struct); for (i = 0; i < n + 1; i++) fmpz_mod_poly_init(realE + i, ctx->ffinfo); offsets = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); shifts = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); for (i = 0; i < ctx->minfo->nvars; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, A->bits, ctx->minfo); offset = offsets[0]; shift = shifts[0]; start = 0; e = mask & (A->exps[N*start + offset] >> shift); next: FLINT_ASSERT(start < A->length); FLINT_ASSERT(e == (mask & (A->exps[N*start + offset] >> shift))); stop = start + 1; while (stop < A->length && (mask & (A->exps[N*stop + offset] >> shift)) == e) stop++; fmpz_mod_bpoly_fit_length(E, e + 1, ctx->ffinfo); while (E->length <= e) { fmpz_mod_poly_zero(E->coeffs + E->length, ctx->ffinfo); E->length++; } _fmpz_mod_mpoly_evaluate_rest_fmpz_mod_poly(realE, starts, ends, stops, es, A->coeffs + start, A->exps + N*start, stop - start, 1, alphabetas, offsets, shifts, N, mask, ctx->minfo->nvars, ctx->ffinfo); fmpz_mod_poly_set(E->coeffs + e, realE + 0, ctx->ffinfo); if (stop < A->length) { FLINT_ASSERT(e > (mask & (A->exps[N*stop + offset] >> shift))); e = (mask & (A->exps[N*stop + offset] >> shift)); start = stop; goto next; } fmpz_mod_bpoly_normalise(E, ctx->ffinfo); for (i = 0; i < n + 1; i++) fmpz_mod_poly_clear(realE + i, ctx->ffinfo); flint_free(realE); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); } /* A = B(gen(var), 0) */ void _fmpz_mod_mpoly_set_fmpz_mod_bpoly_var1_zero( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_bpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; slong Blen = B->length; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += (B->coeffs[i].length > 0); fmpz_mod_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { FLINT_ASSERT(Alen < A->coeffs_alloc); fmpz_mod_poly_get_coeff_fmpz(A->coeffs + Alen, B->coeffs + i, 0, ctx->ffinfo); if (fmpz_is_zero(A->coeffs + Alen)) continue; if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly_factor/expand.c000066400000000000000000000020211461254215100214310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_factor_expand( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) { int success = 1; slong i; fmpz_mod_mpoly_t t1; fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_set_fmpz_mod(A, f->constant, ctx); for (i = 0; i < f->num; i++) { if (fmpz_sgn(f->exp + i) < 0 || !fmpz_mod_mpoly_pow_fmpz(t1, f->poly + i, f->exp + i, ctx)) { success = 0; goto cleanup; } fmpz_mod_mpoly_mul(A, A, t1, ctx); } cleanup: fmpz_mod_mpoly_clear(t1, ctx); return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/factor.c000066400000000000000000000514011461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz_mod.h" #include "fmpz_mod_poly_factor.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #include "fmpz_mod_mpoly_factor.h" /* The property "sep" used here is that of the returned factors of _nmod_mpoly_factor_separable with sep = 1, namely: (1) monic (2) primitive wrt each variable (3) for all i, derivative(A, gen(i)) = 0, or gcd(A, derivative(A, gen(i))) = 1 (4) there is at least one i for which derivative(A, gen(i)) != 0 Input A is sep and compressed. return 1 for success, 0 for failure */ static int _factor_irred_compressed( fmpz_mod_mpolyv_t Af, fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { slong i; int success; slong nvars = ctx->minfo->nvars; flint_bitcnt_t Abits; flint_rand_t state; #if FLINT_WANT_ASSERT fmpz_mod_mpoly_t Aorg; #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(fmpz_is_one(A->coeffs + 0)); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(!fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); if (A->length < 2) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(!fmpz_mod_mpoly_is_fmpz(A, ctx)); fmpz_mod_mpolyv_fit_length(Af, 1, ctx); fmpz_mod_mpoly_swap(Af->coeffs + 0, A, ctx); Af->length = 1; return 1; } if (A->bits > FLINT_BITS && !fmpz_mod_mpoly_repack_bits_inplace(A, FLINT_BITS, ctx)) { return 0; } #if FLINT_WANT_ASSERT fmpz_mod_mpoly_init(Aorg, ctx); fmpz_mod_mpoly_set(Aorg, A, ctx); #endif Abits = A->bits; flint_randinit(state); if (nvars < 2) { fmpz_mod_poly_t Au; fmpz_mod_poly_factor_t Auf; FLINT_ASSERT(nvars == 1); fmpz_mod_poly_init(Au, ctx->ffinfo); fmpz_mod_poly_factor_init(Auf, ctx->ffinfo); FLINT_ASSERT(fmpz_mod_mpoly_is_fmpz_mod_poly(A, 0, ctx)); success = fmpz_mod_mpoly_get_fmpz_mod_poly(Au, A, 0, ctx); FLINT_ASSERT(success); fmpz_mod_poly_factor(Auf, Au, ctx->ffinfo); fmpz_mod_mpolyv_fit_length(Af, Auf->num, ctx); Af->length = Auf->num; for (i = 0; i < Auf->num; i++) { FLINT_ASSERT(Auf->exp[i] == 1); _fmpz_mod_mpoly_set_fmpz_mod_poly(Af->coeffs + i, Abits, Auf->poly[i].coeffs, Auf->poly[i].length, 0, ctx); } fmpz_mod_poly_clear(Au, ctx->ffinfo); fmpz_mod_poly_factor_clear(Auf, ctx->ffinfo); success = 1; } else if (nvars == 2) { fmpz_mod_poly_t c; fmpz_mod_bpoly_t Ab; fmpz_mod_tpoly_t Abf; fmpz_mod_poly_init(c, ctx->ffinfo); fmpz_mod_bpoly_init(Ab, ctx->ffinfo); fmpz_mod_tpoly_init(Abf, ctx->ffinfo); fmpz_mod_mpoly_get_fmpz_mod_bpoly(Ab, A, 0, 1, ctx); success = fmpz_mod_bpoly_factor_smprime(c, Abf, Ab, 1, ctx->ffinfo); FLINT_ASSERT(!success || fmpz_mod_poly_degree(c, ctx->ffinfo) == 0); fmpz_mod_mpolyv_fit_length(Af, Abf->length, ctx); Af->length = Abf->length; for (i = 0; i < Abf->length; i++) { fmpz_mod_mpoly_set_fmpz_mod_bpoly(Af->coeffs + i, Abits, Abf->coeffs + i, 0, 1, ctx); fmpz_mod_mpoly_make_monic(Af->coeffs + i, Af->coeffs + i, ctx); } fmpz_mod_poly_clear(c, ctx->ffinfo); fmpz_mod_bpoly_clear(Ab, ctx->ffinfo); fmpz_mod_tpoly_clear(Abf, ctx->ffinfo); } else { fmpz_mod_mpoly_t lcA; fmpz_mod_mpoly_factor_t lcAf; fmpz_mod_mpoly_init(lcA, ctx); fmpz_mod_mpoly_factor_init(lcAf, ctx); #if FLINT_WANT_ASSERT { fmpz_mod_mpoly_t g; fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_derivative(g, A, 0, ctx); FLINT_ASSERT(fmpz_mod_mpoly_gcd(g, g, A, ctx)); FLINT_ASSERT(fmpz_mod_mpoly_is_one(g, ctx)); fmpz_mod_mpoly_clear(g, ctx); } #endif success = 0; if (!(algo & (MPOLY_FACTOR_USE_WANG | MPOLY_FACTOR_USE_ZIP))) goto try_zassenhaus; /* TODO lcc_kaltofen */ _fmpz_mod_mpoly_get_lead0(lcA, A, ctx); if (!fmpz_mod_mpoly_factor(lcAf, lcA, ctx)) goto try_zassenhaus; if (!(algo & MPOLY_FACTOR_USE_ZIP)) { if (success == 0) success = fmpz_mod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); } else if (!(algo & MPOLY_FACTOR_USE_WANG)) { if (success == 0) success = fmpz_mod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { double tdensity = 0; fmpz_t x; fmpz_init(x); fmpz_mod_mpoly_total_degree_fmpz(x, A, ctx); if (fmpz_fits_si(x)) { fmpz_bin_uiui(x, fmpz_get_si(x) + nvars, nvars); tdensity = A->length/fmpz_get_d(x); } fmpz_clear(x); if (tdensity > 0.005) { if (success == 0) success = fmpz_mod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fmpz_mod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { if (success == 0) success = fmpz_mod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fmpz_mod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); } } try_zassenhaus: if (algo & MPOLY_FACTOR_USE_ZAS) { if (success == 0) success = fmpz_mod_mpoly_factor_irred_smprime_zassenhaus( Af, A, ctx, state); } success = (success > 0); fmpz_mod_mpoly_clear(lcA, ctx); fmpz_mod_mpoly_factor_clear(lcAf, ctx); } flint_randclear(state); #if FLINT_WANT_ASSERT if (success) { fmpz_mod_mpoly_t prod; fmpz_mod_mpoly_init(prod, ctx); fmpz_mod_mpoly_one(prod, ctx); for (i = 0; i < Af->length; i++) fmpz_mod_mpoly_mul(prod, prod, Af->coeffs + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(prod, Aorg, ctx)); fmpz_mod_mpoly_clear(prod, ctx); } fmpz_mod_mpoly_clear(Aorg, ctx); #endif FLINT_ASSERT(success == 0 || success == 1); return success; } /* f is already squarefree make the factors in f have the sep property */ static int _refine_sep( fmpz_mod_mpolyv_t f, const fmpz_mod_mpoly_ctx_t ctx, fmpz_mod_mpolyv_t g) /* temp */ { int success; slong v, i; fmpz_mod_mpoly_struct * t; fmpz_mod_mpoly_univar_t u; fmpz_mod_mpoly_univar_init(u, ctx); /* first make primitive */ for (v = 0; v < ctx->minfo->nvars; v++) { g->length = 0; for (i = 0; i < f->length; i++) { fmpz_mod_mpoly_to_univar(u, f->coeffs + i, v, ctx); FLINT_ASSERT(u->length > 0); FLINT_ASSERT(fmpz_is_zero(u->exps + u->length - 1)); fmpz_mod_mpolyv_fit_length(g, g->length + 2, ctx); success = _fmpz_mod_mpoly_vec_content_mpoly(g->coeffs + g->length, u->coeffs, u->length, ctx); if (!success) goto cleanup; if (fmpz_mod_mpoly_is_fmpz(g->coeffs + g->length, ctx)) { fmpz_mod_mpoly_swap(g->coeffs + g->length, f->coeffs + i, ctx); g->length++; } else { success = fmpz_mod_mpoly_divides(g->coeffs + g->length + 1, f->coeffs + i, g->coeffs + g->length, ctx); FLINT_ASSERT(success); if (fmpz_mod_mpoly_is_fmpz(g->coeffs + g->length + 1, ctx)) g->length += 1; else g->length += 2; } } fmpz_mod_mpolyv_swap(f, g, ctx); } /* now make separable/derivative zero wrt each variable */ fmpz_mod_mpolyv_fit_length(g, 1, ctx); t = g->coeffs + 0; for (v = 0; v < ctx->minfo->nvars; v++) { i = 0; while (i < f->length) { fmpz_mod_mpoly_derivative(t, f->coeffs + i, v, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) { /* f[i] has zero derivative */ FLINT_ASSERT(fmpz_mod_mpoly_degree_si(f->coeffs + i, v, ctx) == 0); i++; continue; } fmpz_mod_mpolyv_fit_length(f, f->length + 1, ctx); success = fmpz_mod_mpoly_gcd_cofactors(f->coeffs + f->length, f->coeffs + i, t, f->coeffs + i, t, ctx); if (!success) goto cleanup; if (fmpz_mod_mpoly_is_fmpz(f->coeffs + f->length, ctx)) { /* f[i] is comprime with its derivative */ i++; } else { /* f[i] and f[end] at least got smaller */ f->length++; } } } success = 1; cleanup: fmpz_mod_mpoly_univar_clear(u, ctx); return 1; } /* A is sep. return 1 for success, 0 for failure */ static int _factor_irred( fmpz_mod_mpolyv_t Af, fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t Actx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t Abits; mpoly_compression_t M; #if FLINT_WANT_ASSERT fmpz_mod_mpoly_t Aorg; fmpz_mod_mpoly_init(Aorg, Actx); fmpz_mod_mpoly_set(Aorg, A, Actx); #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(!fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(Actx->ffinfo))); if (A->length < 2) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(!fmpz_mod_mpoly_is_fmpz(A, Actx)); fmpz_mod_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; fmpz_mod_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; goto cleanup_less; } if (A->bits > FLINT_BITS && !fmpz_mod_mpoly_repack_bits_inplace(A, FLINT_BITS, Actx)) { success = 0; goto cleanup_less; } Abits = A->bits; mpoly_compression_init(M); mpoly_compression_set(M, A->exps, A->bits, A->length, Actx->minfo); if (M->is_irred) { fmpz_mod_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; fmpz_mod_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; } else if (M->is_trivial) { success = _factor_irred_compressed(Af, A, Actx, algo); } else { fmpz_mod_mpoly_ctx_t Lctx; fmpz_mod_mpolyv_t Lf, Lft, Lfs; fmpz_mod_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX, fmpz_mod_ctx_modulus(Actx->ffinfo)); fmpz_mod_mpolyv_init(Lf, Lctx); fmpz_mod_mpolyv_init(Lft, Lctx); fmpz_mod_mpolyv_init(Lfs, Lctx); fmpz_mod_mpolyv_fit_length(Lft, 1, Lctx); Lft->length = 1; fmpz_mod_mpoly_compression_do(Lft->coeffs + 0, Lctx, A->coeffs, A->length, M); _refine_sep(Lft, Lctx, Lf); if (Lft->length == 1) { success = _factor_irred_compressed(Lf, Lft->coeffs + 0, Lctx, algo); } else { success = 1; Lf->length = 0; for (i = 0; i < Lft->length; i++) { success = _factor_irred(Lfs, Lft->coeffs + i, Lctx, algo); if (!success) break; fmpz_mod_mpolyv_fit_length(Lf, Lf->length + Lfs->length, Lctx); for (j = 0; j < Lfs->length; j++) { fmpz_mod_mpoly_swap(Lf->coeffs + Lf->length, Lfs->coeffs + j, Lctx); Lf->length++; } } } if (success) { fmpz_mod_mpolyv_fit_length(Af, Lf->length, Actx); Af->length = Lf->length; for (i = 0; i < Lf->length; i++) { fmpz_mod_mpoly_compression_undo(Af->coeffs + i, Abits, Actx, Lf->coeffs + i, Lctx, M); } } fmpz_mod_mpolyv_clear(Lf, Lctx); fmpz_mod_mpolyv_clear(Lft, Lctx); fmpz_mod_mpolyv_clear(Lfs, Lctx); fmpz_mod_mpoly_ctx_clear(Lctx); } mpoly_compression_clear(M); cleanup_less: #if FLINT_WANT_ASSERT if (success) { fmpz_mod_mpoly_t prod; fmpz_mod_mpoly_init(prod, Actx); fmpz_mod_mpoly_one(prod, Actx); for (i = 0; i < Af->length; i++) fmpz_mod_mpoly_mul(prod, prod, Af->coeffs + i, Actx); FLINT_ASSERT(fmpz_mod_mpoly_equal(prod, Aorg, Actx)); fmpz_mod_mpoly_clear(prod, Actx); fmpz_mod_mpoly_clear(Aorg, Actx); } #endif FLINT_ASSERT(success == 0 || success == 1); return success; } /* Assume each factor in f is sep. Replace f by an irreducible factorization. */ int fmpz_mod_mpoly_factor_irred( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; fmpz_mod_mpolyv_t t; fmpz_mod_mpoly_factor_t g; fmpz_mod_mpolyv_init(t, ctx); fmpz_mod_mpoly_factor_init(g, ctx); fmpz_swap(g->constant, f->constant); g->num = 0; for (j = 0; j < f->num; j++) { success = _factor_irred(t, f->poly + j, ctx, algo); if (!success) goto cleanup; fmpz_mod_mpoly_factor_fit_length(g, g->num + t->length, ctx); for (i = 0; i < t->length; i++) { fmpz_set(g->exp + g->num, f->exp + j); fmpz_mod_mpoly_swap(g->poly + g->num, t->coeffs + i, ctx); g->num++; } } fmpz_mod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fmpz_mod_mpolyv_clear(t, ctx); fmpz_mod_mpoly_factor_clear(g, ctx); return success; } /* append factor(f)^e to g assuming f is compressed and content free */ static int _compressed_content_to_irred( fmpz_mod_mpoly_factor_t g, fmpz_mod_mpoly_t f, const fmpz_t e, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong j, k; fmpz_mod_mpoly_factor_t h; fmpz_mod_mpolyv_t v; FLINT_ASSERT(!fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); fmpz_mod_mpoly_factor_init(h, ctx); fmpz_mod_mpolyv_init(v, ctx); success = _fmpz_mod_mpoly_factor_separable(h, f, ctx, 1); if (!success) goto cleanup; for (j = 0; j < h->num; j++) { success = h->num > 1 ? _factor_irred(v, h->poly + j, ctx, algo) : _factor_irred_compressed(v, h->poly + j, ctx, algo); if (!success) goto cleanup; fmpz_mod_mpoly_factor_fit_length(g, g->num + v->length, ctx); for (k = 0; k < v->length; k++) { fmpz_mul(g->exp + g->num, h->exp + j, e); fmpz_mod_mpoly_swap(g->poly + g->num, v->coeffs + k, ctx); g->num++; } } cleanup: fmpz_mod_mpoly_factor_clear(h, ctx); fmpz_mod_mpolyv_clear(v, ctx); return success; } int fmpz_mod_mpoly_factor_algo( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t bits; fmpz_mod_mpoly_factor_t g; mpoly_compression_t M; if (fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))) { nmod_mpoly_ctx_t nctx; nmod_mpoly_t nA; nmod_mpoly_factor_t nf; *nctx->minfo = *ctx->minfo; nmod_init(&nctx->mod, fmpz_get_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); nmod_mpoly_init(nA, nctx); nmod_mpoly_factor_init(nf, nctx); _fmpz_mod_mpoly_get_nmod_mpoly(nA, nctx, A, ctx); success = nmod_mpoly_factor_algo(nf, nA, nctx, algo); _fmpz_mod_mpoly_factor_set_nmod_mpoly_factor(f, ctx, nf, nctx); nmod_mpoly_factor_clear(nf, nctx); nmod_mpoly_clear(nA, nctx); return success; } if (!fmpz_mod_mpoly_factor_content(f, A, ctx)) return 0; fmpz_mod_mpoly_factor_init(g, ctx); mpoly_compression_init(M); /* write into g */ fmpz_swap(g->constant, f->constant); g->num = 0; for (i = 0; i < f->num; i++) { if (f->poly[i].length < 2) { fmpz_mod_mpoly_factor_fit_length(g, g->num + 1, ctx); fmpz_mod_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; continue; } if (f->poly[i].bits > FLINT_BITS && !fmpz_mod_mpoly_repack_bits_inplace(f->poly + i, FLINT_BITS, ctx)) { success = 0; goto cleanup; } bits = f->poly[i].bits; mpoly_compression_set(M, f->poly[i].exps, bits, f->poly[i].length, ctx->minfo); if (M->is_irred) { fmpz_mod_mpoly_factor_fit_length(g, g->num + 1, ctx); fmpz_mod_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; } else if (M->is_trivial) { success = _compressed_content_to_irred(g, f->poly + i, f->exp + i, ctx, algo); if (!success) goto cleanup; } else { fmpz_mod_mpoly_ctx_t Lctx; fmpz_mod_mpoly_t L; fmpz_mod_mpoly_factor_t h; /* compression may have messed up the content factorization */ fmpz_mod_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_mod_mpoly_init(L, Lctx); fmpz_mod_mpoly_factor_init(h, Lctx); fmpz_mod_mpoly_compression_do(L, Lctx, f->poly[i].coeffs, f->poly[i].length, M); if (M->is_perm) { success = _compressed_content_to_irred(h, L, f->exp + i, Lctx, algo); fmpz_one(f->exp + i); } else { success = fmpz_mod_mpoly_factor_separable(h, L, Lctx, 1) && fmpz_mod_mpoly_factor_irred(h, Lctx, algo); } if (success) { FLINT_ASSERT(fmpz_is_one(h->constant)); fmpz_mod_mpoly_factor_fit_length(g, g->num + h->num, ctx); for (j = 0; j < h->num; j++) { fmpz_mul(g->exp + g->num, f->exp + i, h->exp + j); fmpz_mod_mpoly_compression_undo(g->poly + g->num, bits, ctx, h->poly + j, Lctx, M); g->num++; } } fmpz_mod_mpoly_factor_clear(h, Lctx); fmpz_mod_mpoly_clear(L, Lctx); fmpz_mod_mpoly_ctx_clear(Lctx); if (!success) goto cleanup; } } fmpz_mod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fmpz_mod_mpoly_factor_clear(g, ctx); mpoly_compression_clear(M); FLINT_ASSERT(!success || fmpz_mod_mpoly_factor_matches(A, f, ctx)); return success; } int fmpz_mod_mpoly_factor( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ALL); } int fmpz_mod_mpoly_factor_zassenhaus( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZAS); } int fmpz_mod_mpoly_factor_wang( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_WANG); } int fmpz_mod_mpoly_factor_zippel( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZIP); } flint-3.1.3/src/fmpz_mod_mpoly_factor/factor_content.c000066400000000000000000000123621461254215100231730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" /* either give a non-trivial split a = f*g or establish that a is primitive wrt all variables return: 1: split a = f*g 0: a is primitive wrt all variables (f & g undefined) -1: failed */ static int _split( fmpz_mod_mpoly_t f, fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_t a_vars_left, const fmpz_mod_mpoly_ctx_t ctx, fmpz_mod_mpoly_univar_struct * u, /* temp */ slong * vars) { slong i, j, v; slong nvars = ctx->minfo->nvars; slong mvars = 0; FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(f, ctx)); FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(g, ctx)); FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(a, ctx)); for (v = 0; v < nvars; v++) { if (!fmpz_tstbit(a_vars_left, v)) continue; fmpz_mod_mpoly_to_univar(u + v, a, v, ctx); vars[mvars] = v; mvars++; } if (mvars < 1) return 0; /* sort vars by decreasing length */ for (i = 1; i < mvars; i++) for (j = i; j > 0 && u[vars[j]].length > u[vars[j - 1]].length; j--) FLINT_SWAP(slong, vars[j], vars[j - 1]); for (i = 0; i < mvars; i++) { v = vars[i]; FLINT_ASSERT(fmpz_tstbit(a_vars_left, v)); fmpz_clrbit(a_vars_left, v); if (u[v].length < 2) { FLINT_ASSERT(u[v].length == 1); FLINT_ASSERT(fmpz_is_zero(u[v].exps + 0)); continue; } if (!_fmpz_mod_mpoly_vec_content_mpoly(g, u[v].coeffs, u[v].length, ctx)) return -1; FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(g, ctx)); if (g->length < 2) { FLINT_ASSERT(fmpz_mod_mpoly_is_one(g, ctx)); continue; } fmpz_mod_mpoly_divides(f, a, g, ctx); FLINT_ASSERT(f->length > 1); return 1; } return 0; } /* return factors that are primitive wrt each variable */ int fmpz_mod_mpoly_factor_content( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong nvars = ctx->minfo->nvars; slong v; fmpz_mod_mpoly_univar_struct * u; fmpz_mod_mpoly_factor_t g; /* exponents are bitsets */ slong * vars; f->num = 0; if (fmpz_mod_mpoly_is_fmpz(A, ctx)) { fmpz_mod_mpoly_get_fmpz(f->constant, A, ctx); return 1; } vars = FLINT_ARRAY_ALLOC(nvars, slong); fmpz_mod_mpoly_factor_init(g, ctx); u = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_mpoly_univar_struct); for (v = 0; v < nvars; v++) fmpz_mod_mpoly_univar_init(u + v, ctx); /* remove leading coefficient */ FLINT_ASSERT(A->length > 0); fmpz_set(f->constant, A->coeffs + 0); fmpz_mod_mpoly_factor_fit_length(g, nvars, ctx); fmpz_mod_mpoly_make_monic(g->poly + 0, A, ctx); /* remove monomial divisors */ mpoly_remove_var_powers(g->exp, g->poly[0].exps, g->poly[0].bits, g->poly[0].length, ctx->minfo); for (v = 0; v < nvars; v++) { if (fmpz_is_zero(g->exp + v)) continue; fmpz_mod_mpoly_factor_fit_length(f, f->num + 1, ctx); fmpz_mod_mpoly_gen(f->poly + f->num, v, ctx); fmpz_swap(f->exp + f->num, g->exp + v); f->num++; } /* done if g->poly[0] is constant */ if (g->poly[0].length == 1) { success = 1; goto cleanup; } /* g has length one and no variable has been checked yet */ fmpz_one(g->exp + 0); fmpz_mul_2exp(g->exp + 0, g->exp + 0, nvars); fmpz_sub_ui(g->exp + 0, g->exp + 0, 1); g->num = 1; while (g->num > 0) { slong t = g->num - 1; fmpz_mod_mpoly_factor_fit_length(g, t + 3, ctx); success = _split(g->poly + t + 2, g->poly + t + 1, g->poly + t, g->exp + t, ctx, u, vars); if (success < 0) { success = 0; goto cleanup; } else if (success == 0) { FLINT_ASSERT(!fmpz_mod_mpoly_is_fmpz(g->poly + t, ctx)); fmpz_mod_mpoly_factor_fit_length(f, f->num + 1, ctx); fmpz_mod_mpoly_swap(f->poly + f->num, g->poly + t, ctx); fmpz_one(f->exp + f->num); f->num++; g->num = t; } else { FLINT_ASSERT(!fmpz_mod_mpoly_is_fmpz(g->poly + t + 1, ctx)); FLINT_ASSERT(!fmpz_mod_mpoly_is_fmpz(g->poly + t + 2, ctx)); fmpz_mod_mpoly_swap(g->poly + t, g->poly + t + 2, ctx); fmpz_set(g->exp + t + 1, g->exp + t); g->num = t + 2; } } success = 1; cleanup: fmpz_mod_mpoly_factor_clear(g, ctx); for (v = 0; v < nvars; v++) fmpz_mod_mpoly_univar_clear(u + v, ctx); flint_free(u); flint_free(vars); FLINT_ASSERT(!success || fmpz_mod_mpoly_factor_matches(A, f, ctx)); return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/factor_squarefree.c000066400000000000000000000120141461254215100236550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz_mod.h" #include "nmod_mpoly_factor.h" #include "fmpz_mod_mpoly_factor.h" static void _fmpz_mod_mpoly_factor_mul_mpoly_fmpz( fmpz_mod_mpoly_factor_t f, fmpz_mod_mpoly_t A, const fmpz_t e, const fmpz_mod_mpoly_ctx_t ctx) { if (fmpz_mod_mpoly_is_fmpz(A, ctx)) { FLINT_ASSERT(fmpz_mod_mpoly_is_one(A, ctx)); } else { fmpz_mod_mpoly_factor_append_fmpz_swap(f, A, e, ctx); } } int _fmpz_mod_mpoly_factor_separable( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, int sep) { int success; slong v, var; fmpz_t k; fmpz_mod_mpoly_t U, V, W, G; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(fmpz_is_one(A->coeffs + 0)); if (fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))) { nmod_mpoly_ctx_t nctx; nmod_mpoly_t nA; nmod_mpoly_factor_t nf; *nctx->minfo = *ctx->minfo; nmod_init(&nctx->mod, fmpz_get_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); nmod_mpoly_init(nA, nctx); nmod_mpoly_factor_init(nf, nctx); _fmpz_mod_mpoly_get_nmod_mpoly(nA, nctx, A, ctx); success = _nmod_mpoly_factor_separable(nf, nA, nctx, sep); _fmpz_mod_mpoly_factor_set_nmod_mpoly_factor(f, ctx, nf, nctx); nmod_mpoly_factor_clear(nf, nctx); nmod_mpoly_clear(nA, nctx); return success; } fmpz_mod_mpoly_factor_one(f, ctx); if (!fmpz_mod_mpoly_degrees_fit_si(A, ctx)) return 0; fmpz_init(k); fmpz_mod_mpoly_init(U, ctx); fmpz_mod_mpoly_init(V, ctx); fmpz_mod_mpoly_init(W, ctx); fmpz_mod_mpoly_init(G, ctx); /* take the variable with shortest derivative */ var = -1; for (v = 0; v < ctx->minfo->nvars; v++) { fmpz_mod_mpoly_derivative(U, A, v, ctx); if (U->length > 0 && (var < 0 || U->length < G->length)) { var = v; fmpz_mod_mpoly_swap(V, U, ctx); } } if (var < 0) { FLINT_ASSERT(fmpz_mod_mpoly_is_one(A, ctx)); success = 1; goto cleanup; } success = fmpz_mod_mpoly_gcd_cofactors(G, W, V, A, V, ctx); if (!success) goto cleanup; fmpz_one(k); while (1) { fmpz_add_ui(k, k, 1); if (fmpz_cmp(k, fmpz_mod_ctx_modulus(ctx->ffinfo)) >= 0) break; fmpz_sub_ui(k, k, 1); fmpz_mod_mpoly_derivative(G, W, var, ctx); fmpz_mod_mpoly_sub(U, V, G, ctx); if (fmpz_mod_mpoly_is_zero(U, ctx)) break; success = fmpz_mod_mpoly_gcd_cofactors(G, W, V, W, U, ctx); if (!success) goto cleanup; _fmpz_mod_mpoly_factor_mul_mpoly_fmpz(f, G, k, ctx); fmpz_add_ui(k, k, 1); } _fmpz_mod_mpoly_factor_mul_mpoly_fmpz(f, W, k, ctx); success = 1; cleanup: fmpz_clear(k); fmpz_mod_mpoly_clear(U, ctx); fmpz_mod_mpoly_clear(V, ctx); fmpz_mod_mpoly_clear(W, ctx); fmpz_mod_mpoly_clear(G, ctx); return success; } /* if sep = true, each returned factor should satisfy: (1) monic (2) primitive wrt each variable (3) for all i, derivative(a, gen(i)) = 0, or gcd(a, derivative(a, gen(i))) = 1 (4) there is at least i for which derivative(a, gen(i)) != 0 otherwise, the factors are just squarefree */ int fmpz_mod_mpoly_factor_separable( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, int sep) { int success; slong i, j; fmpz_mod_mpoly_factor_t g, t; if (!fmpz_mod_mpoly_factor_content(f, A, ctx)) return 0; fmpz_mod_mpoly_factor_init(g, ctx); fmpz_mod_mpoly_factor_init(t, ctx); fmpz_swap(g->constant, f->constant); g->num = 0; for (j = 0; j < f->num; j++) { success = _fmpz_mod_mpoly_factor_separable(t, f->poly + j, ctx, sep); if (!success) goto cleanup; FLINT_ASSERT(fmpz_is_one(t->constant)); fmpz_mod_mpoly_factor_fit_length(g, g->num + t->num, ctx); for (i = 0; i < t->num; i++) { fmpz_mul(g->exp + g->num, t->exp + i, f->exp + j); fmpz_mod_mpoly_swap(g->poly + g->num, t->poly + i, ctx); g->num++; } } fmpz_mod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fmpz_mod_mpoly_factor_clear(t, ctx); fmpz_mod_mpoly_factor_clear(g, ctx); FLINT_ASSERT(!success || fmpz_mod_mpoly_factor_matches(A, f, ctx)); return success; } int fmpz_mod_mpoly_factor_squarefree( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { return fmpz_mod_mpoly_factor_separable(f, A, ctx, 0); } flint-3.1.3/src/fmpz_mod_mpoly_factor/fit_length.c000066400000000000000000000013701461254215100223030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_mpoly_factor_fit_length( fmpz_mod_mpoly_factor_t fac, slong len, const fmpz_mod_mpoly_ctx_t ctx) { if (len > fac->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * fac->alloc) len = 2 * fac->alloc; fmpz_mod_mpoly_factor_realloc(fac, len, ctx); } } flint-3.1.3/src/fmpz_mod_mpoly_factor/fmpz_mod_bpoly.c000066400000000000000000000500461461254215100232040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_bpoly_is_canonical(const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { slong i; if (A->length < 1) return A->length == 0; for (i = 0; i < A->length; i++) { if (!fmpz_mod_poly_is_canonical(A->coeffs + i, ctx)) return 0; if (i + 1 == A->length && fmpz_mod_poly_is_zero(A->coeffs + i, ctx)) return 0; } return 1; } void fmpz_mod_bpoly_clear(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mod_poly_clear(A->coeffs + i, ctx); if (A->alloc > 0) flint_free(A->coeffs); } void fmpz_mod_bpoly_fit_length( fmpz_mod_bpoly_t A, slong len, const fmpz_mod_ctx_t ctx) { slong i = A->alloc; if (len <= i) return; len = FLINT_MAX(len, 2*i); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, len, fmpz_mod_poly_struct); for ( ; i < len; i++) fmpz_mod_poly_init(A->coeffs + i, ctx); A->alloc = len; } void fmpz_mod_bpoly_zero(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { A->length = 0; } void fmpz_mod_bpoly_set_coeff( fmpz_mod_bpoly_t A, slong xi, slong yi, const fmpz_t c, const fmpz_mod_ctx_t ctx) { slong i; if (xi >= A->length) { fmpz_mod_bpoly_fit_length(A, xi + 1, ctx); for (i = A->length; i <= xi; i++) fmpz_mod_poly_zero(A->coeffs + i, ctx); A->length = xi + 1; } fmpz_mod_poly_set_coeff_fmpz(A->coeffs + xi, yi, c, ctx); while (A->length > 0 && fmpz_mod_poly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; } void fmpz_mod_bpoly_set_poly_gen1( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_bpoly_fit_length(A, 1, ctx); fmpz_mod_poly_set(A->coeffs + 0, B, ctx); A->length = !fmpz_mod_poly_is_zero(A->coeffs + 0, ctx); } void fmpz_mod_bpoly_set_poly_gen0( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_bpoly_fit_length(A, B->length, ctx); A->length = B->length; for (i = 0; i < B->length; i++) fmpz_mod_poly_set_fmpz(A->coeffs + i, B->coeffs + i, ctx); } void fmpz_mod_bpoly_one(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { fmpz_mod_bpoly_fit_length(A, 1, ctx); A->length = 1; fmpz_mod_poly_one(A->coeffs + 0, ctx); } slong fmpz_mod_bpoly_degree1( const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { slong i, len = 0; for (i = 0; i < A->length; i++) len = FLINT_MAX(len, A->coeffs[i].length); return len - 1; } int fmpz_mod_bpoly_equal( const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (!fmpz_mod_poly_equal(A->coeffs + i, B->coeffs + i, ctx)) return 0; } return 1; } void fmpz_mod_bpoly_set( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx) { slong i; if (A == B) return; fmpz_mod_bpoly_fit_length(A, B->length, ctx); A->length = B->length; for (i = 0; i < B->length; i++) fmpz_mod_poly_set(A->coeffs + i, B->coeffs + i, ctx); } void _fmpz_mod_poly_taylor_shift_horner( fmpz * a, const fmpz_t c, slong n, const fmpz_mod_ctx_t ctx) { slong i, j; if (!fmpz_is_zero(c)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) fmpz_mod_addmul(a + j, a + j, a + j + 1, c, ctx); } } void fmpz_mod_bpoly_taylor_shift_gen1( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_t c, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_bpoly_set(A, B, ctx); for (i = A->length - 1; i >= 0; i--) _fmpz_mod_poly_taylor_shift_horner(A->coeffs[i].coeffs, c, A->coeffs[i].length, ctx); } void fmpz_mod_bpoly_sub( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, const fmpz_mod_ctx_t ctx) { slong i; slong Alen = FLINT_MAX(B->length, C->length); fmpz_mod_bpoly_fit_length(A, Alen, ctx); for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) fmpz_mod_poly_sub(A->coeffs + i, B->coeffs + i, C->coeffs + i, ctx); else fmpz_mod_poly_set(A->coeffs + i, B->coeffs + i, ctx); } else { FLINT_ASSERT(i < C->length); fmpz_mod_poly_neg(A->coeffs + i, C->coeffs + i, ctx); } } A->length = Alen; fmpz_mod_bpoly_normalise(A, ctx); } void fmpz_mod_bpoly_add( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, const fmpz_mod_ctx_t ctx) { slong i; slong Alen = FLINT_MAX(B->length, C->length); fmpz_mod_bpoly_fit_length(A, Alen, ctx); for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) fmpz_mod_poly_add(A->coeffs + i, B->coeffs + i, C->coeffs + i, ctx); else fmpz_mod_poly_set(A->coeffs + i, B->coeffs + i, ctx); } else { FLINT_ASSERT(i < C->length); fmpz_mod_poly_set(A->coeffs + i, C->coeffs + i, ctx); } } A->length = Alen; fmpz_mod_bpoly_normalise(A, ctx); } void fmpz_mod_bpoly_make_primitive( fmpz_mod_poly_t g, fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx) { slong Alen = A->length; slong i; fmpz_mod_poly_t q, r; fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_zero(g, ctx); for (i = 0; i < Alen; i++) { fmpz_mod_poly_gcd(q, g, A->coeffs + i, ctx); fmpz_mod_poly_swap(g, q, ctx); } for (i = 0; i < Alen; i++) { fmpz_mod_poly_divrem(q, r, A->coeffs + i, g, ctx); FLINT_ASSERT(fmpz_mod_poly_is_zero(r, ctx)); fmpz_mod_poly_swap(A->coeffs + i, q, ctx); } /* make lc_xy(A) one */ if (Alen > 0) { fmpz * c = A->coeffs[Alen - 1].coeffs + A->coeffs[Alen - 1].length - 1; if (!fmpz_is_one(c)) { fmpz_t cinv; fmpz_mod_poly_scalar_mul_fmpz(g, g, c, ctx); fmpz_init(cinv); fmpz_mod_inv(cinv, c, ctx); for (i = 0; i < Alen; i++) fmpz_mod_poly_scalar_mul_fmpz(A->coeffs + i, A->coeffs + i, cinv, ctx); fmpz_clear(cinv); } } fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); } /* multiplication in F[y][x] */ void fmpz_mod_bpoly_mul( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_mod_poly_struct * t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); if (B->length < 1 || C->length < 1) { A->length = 0; return; } #if 0 if (B->length > 2 && C->length > 2) { n_poly_t a, b, c; slong order = n_bpoly_degree1(B) + n_bpoly_degree1(C) + 1; n_poly_init(a); n_poly_init(b); n_poly_init(c); for (i = B->length - 1; i >= 0; i--) { n_poly_struct * Bi = B->coeffs + i; for (j = Bi->length - 1; j >= 0; j--) n_poly_set_coeff(b, order*i + j, Bi->coeffs[j]); } for (i = C->length - 1; i >= 0; i--) { n_poly_struct * Ci = C->coeffs + i; for (j = Ci->length - 1; j >= 0; j--) n_poly_set_coeff(c, order*i + j, Ci->coeffs[j]); } n_poly_mod_mul(a, b, c, ctx); A->length = 0; for (i = B->length + C->length - 1; i >= 0; i--) { for (j = order - 1; j >= 0; j--) n_bpoly_set_coeff(A, i, j, n_poly_get_coeff(a, order*i + j)); } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); return; } #endif fmpz_mod_bpoly_fit_length(A, B->length + C->length, ctx); for (i = 0; i < B->length + C->length - 1; i++) fmpz_mod_poly_zero(A->coeffs + i, ctx); t = A->coeffs + B->length + C->length - 1; for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { fmpz_mod_poly_mul(t, B->coeffs + i, C->coeffs + j, ctx); fmpz_mod_poly_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } A->length = B->length + C->length - 1; fmpz_mod_bpoly_normalise(A, ctx); } /* multiplication in (F[y]/y^order)[x] B, C need not be reduced mod y^order A should come out reduced mod y^order */ void fmpz_mod_bpoly_mul_series( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_bpoly_t C, slong order, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_mod_poly_struct * t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); if (B->length < 1 || C->length < 1) { A->length = 0; return; } #if 0 if (B->length > 2 && C->length > 2) { n_poly_t a, b, c; n_poly_init(a); n_poly_init(b); n_poly_init(c); for (i = B->length - 1; i >= 0; i--) { n_poly_struct * Bi = B->coeffs + i; for (j = FLINT_MIN(order, Bi->length) - 1; j >= 0; j--) n_poly_set_coeff(b, 2*order*i + j, Bi->coeffs[j]); } for (i = C->length - 1; i >= 0; i--) { n_poly_struct * Ci = C->coeffs + i; for (j = FLINT_MIN(order, Ci->length) - 1; j >= 0; j--) n_poly_set_coeff(c, 2*order*i + j, Ci->coeffs[j]); } n_poly_mod_mul(a, b, c, ctx); A->length = 0; for (i = B->length + C->length - 1; i >= 0; i--) { for (j = order - 1; j >= 0; j--) n_bpoly_set_coeff(A, i, j, n_poly_get_coeff(a, 2*order*i + j)); } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); return; } #endif fmpz_mod_bpoly_fit_length(A, B->length + C->length, ctx); for (i = 0; i < B->length + C->length - 1; i++) fmpz_mod_poly_zero(A->coeffs + i, ctx); t = A->coeffs + B->length + C->length - 1; for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { fmpz_mod_poly_mullow(t, B->coeffs + i, C->coeffs + j, order, ctx); fmpz_mod_poly_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } A->length = B->length + C->length - 1; fmpz_mod_bpoly_normalise(A, ctx); } /* division in (F[y]/y^order)[x] A, B need not be reduced mod y^order Q, R should come out reduced mod y^order TODO: make this faster */ void fmpz_mod_bpoly_divrem_series( fmpz_mod_bpoly_t Q, fmpz_mod_bpoly_t R, const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, slong order, const fmpz_mod_ctx_t ctx) { slong i, qoff; fmpz_mod_poly_t q, t; FLINT_ASSERT(R != A); FLINT_ASSERT(R != B); FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_bpoly_set(R, A, ctx); for (i = 0; i < R->length; i++) fmpz_mod_poly_truncate(R->coeffs + i, order, ctx); fmpz_mod_bpoly_normalise(R, ctx); Q->length = 0; while (R->length >= B->length) { fmpz_mod_poly_div_series(q, R->coeffs + R->length - 1, B->coeffs + B->length - 1, order, ctx); for (i = 0; i < B->length; i++) { fmpz_mod_poly_mullow(t, B->coeffs + i, q, order, ctx); fmpz_mod_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { fmpz_mod_bpoly_fit_length(Q, qoff + 1, ctx); for (i = Q->length; i <= qoff; i++) fmpz_mod_poly_zero(Q->coeffs + i, ctx); Q->length = qoff + 1; } fmpz_mod_poly_set(Q->coeffs + qoff, q, ctx); FLINT_ASSERT(fmpz_mod_poly_is_zero(R->coeffs + R->length - 1, ctx)); fmpz_mod_bpoly_normalise(R, ctx); } fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(t, ctx); } /* divisibility in F[y][x] */ int fmpz_mod_bpoly_divides( fmpz_mod_bpoly_t Q, const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx) { slong i, qoff; int divides; fmpz_mod_poly_t q, t; fmpz_mod_bpoly_t R; FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); #if 0 /* ksub not faster :( */ if (0 && A->length > B->length && B->length > 2) { n_poly_t a, b, q, r; slong j; slong Adeg = n_bpoly_degree1(A); slong Bdeg = n_bpoly_degree1(B); slong Qdeg = Adeg - Bdeg; slong order = Adeg + 1; if (Qdeg < 0) return 0; n_poly_init(a); n_poly_init(b); n_poly_init(q); n_poly_init(r); for (i = B->length - 1; i >= 0; i--) { n_poly_struct * Bi = B->coeffs + i; for (j = Bi->length - 1; j >= 0; j--) n_poly_set_coeff(b, order*i + j, Bi->coeffs[j]); } for (i = A->length - 1; i >= 0; i--) { n_poly_struct * Ai = A->coeffs + i; for (j = Ai->length - 1; j >= 0; j--) n_poly_set_coeff(a, order*i + j, Ai->coeffs[j]); } n_poly_mod_divrem(q, r, a, b, ctx); if (r->length > 0 || q->length - 1 < order*(A->length - B->length) || q->length - 1 > Qdeg + order*(A->length - B->length)) { divides = 0; goto cleanup_inner; } for (i = A->length - B->length; i >= 0; i--) { for (j = order - 1; j >= 0; j--) { mp_limb_t qc = n_poly_get_coeff(q, order*i + j); if (qc == 0) continue; if (j > Qdeg) { divides = 0; goto cleanup_inner; } n_bpoly_set_coeff(Q, i, j, qc); } } divides = 1; cleanup_inner: n_poly_clear(a); n_poly_clear(b); n_poly_clear(q); n_poly_clear(r); return divides; } #endif fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_bpoly_init(R, ctx); fmpz_mod_bpoly_set(R, A, ctx); Q->length = 0; while (R->length >= B->length) { fmpz_mod_poly_divrem(q, t, R->coeffs + R->length - 1, B->coeffs + B->length - 1, ctx); if (!fmpz_mod_poly_is_zero(t, ctx)) { divides = 0; goto cleanup; } for (i = 0; i < B->length; i++) { fmpz_mod_poly_mul(t, B->coeffs + i, q, ctx); fmpz_mod_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { fmpz_mod_bpoly_fit_length(Q, qoff + 1, ctx); for (i = Q->length; i <= qoff; i++) fmpz_mod_poly_zero(Q->coeffs + i, ctx); Q->length = qoff + 1; } fmpz_mod_poly_set(Q->coeffs + qoff, q, ctx); while (R->length > 0 && fmpz_mod_poly_is_zero(R->coeffs + R->length - 1, ctx)) R->length--; } divides = (R->length == 0); cleanup: fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_bpoly_clear(R, ctx); return divides; } void fmpz_mod_bpoly_taylor_shift_gen0( fmpz_mod_bpoly_t A, const fmpz_t alpha, const fmpz_mod_ctx_t ctx) { slong i, j; slong n = A->length; fmpz_mod_poly_struct * Acoeffs = A->coeffs; fmpz_t c, alpha_inv; FLINT_ASSERT(fmpz_mod_is_canonical(alpha, ctx)); if (fmpz_is_zero(alpha)) return; fmpz_init(c); fmpz_init(alpha_inv); fmpz_mod_inv(alpha_inv, alpha, ctx); fmpz_one(c); for (i = 1; i < n; i++) { fmpz_mod_mul(c, c, alpha, ctx); _fmpz_mod_vec_scalar_mul_fmpz_mod(Acoeffs[i].coeffs, Acoeffs[i].coeffs, Acoeffs[i].length, c, ctx); } for (i = n - 2; i >= 0; i--) { for (j = i; j < n - 1; j++) { fmpz_mod_poly_add(Acoeffs + j, Acoeffs + j, Acoeffs + j + 1, ctx); } } fmpz_one(c); for (i = 1; i < n; i++) { fmpz_mod_mul(c, c, alpha_inv, ctx); _fmpz_mod_vec_scalar_mul_fmpz_mod(Acoeffs[i].coeffs, Acoeffs[i].coeffs, Acoeffs[i].length, c, ctx); } fmpz_clear(c); fmpz_clear(alpha_inv); } void fmpz_mod_bpoly_derivative_gen0( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx) { slong i; FLINT_ASSERT(A != B); if (B->length < 2) { fmpz_mod_bpoly_zero(A, ctx); return; } fmpz_mod_bpoly_fit_length(A, B->length - 1, ctx); for (i = 1; i < B->length; i++) fmpz_mod_poly_scalar_mul_ui(A->coeffs + i - 1, B->coeffs + i, i, ctx); A->length = B->length - 1; fmpz_mod_bpoly_normalise(A, ctx); } void fmpz_mod_mpoly_get_fmpz_mod_bpoly( fmpz_mod_bpoly_t A, const fmpz_mod_mpoly_t B, slong varx, slong vary, const fmpz_mod_mpoly_ctx_t ctx) { slong j; slong NB; ulong Bexpx, Bexpy; slong Boffx, Bshiftx, Boffy, Bshifty; ulong mask; FLINT_ASSERT(B->bits <= FLINT_BITS); NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); fmpz_mod_bpoly_zero(A, ctx->ffinfo); for (j = 0; j < B->length; j++) { Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask; Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask; fmpz_mod_bpoly_set_coeff(A, Bexpx, Bexpy, B->coeffs + j, ctx->ffinfo); } } void fmpz_mod_mpoly_set_fmpz_mod_bpoly( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_bpoly_t B, slong varx, slong vary, const fmpz_mod_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, j; slong NA; slong Alen; fmpz * Acoeff; ulong * Aexp; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); TMP_START; Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); for (i = 0; i < n; i++) Aexps[i] = 0; NA = mpoly_words_per_exp(Abits, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, 4, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { fmpz_mod_poly_struct * Bc = B->coeffs + i; _fmpz_mod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, NA, Alen + Bc->length); for (j = 0; j < Bc->length; j++) { if (fmpz_is_zero(Bc->coeffs + j)) continue; Aexps[varx] = i; Aexps[vary] = j; fmpz_set(Acoeff + Alen, Bc->coeffs + j); mpoly_set_monomial_ui(Aexp + NA*Alen, Aexps, Abits, ctx->minfo); Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; TMP_END; fmpz_mod_mpoly_sort_terms(A, ctx); } flint-3.1.3/src/fmpz_mod_mpoly_factor/fmpz_mod_mat_extras.c000066400000000000000000000045221461254215100242240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mat_is_reduced(const fmpz_mod_mat_t N, const fmpz_mod_ctx_t ctx) { slong i, j, k = 0; slong r = fmpz_mod_mat_ncols(N, ctx); slong d = fmpz_mod_mat_nrows(N, ctx); for (i = 0; i < d; i++) for (j = 0; j < r; j++) { if (!fmpz_is_zero(fmpz_mod_mat_entry(N, i, j))) { if (fmpz_is_one(fmpz_mod_mat_entry(N, i, j))) k++; else return 0; } } return k == r; } void fmpz_mod_mat_init_nullspace_tr(fmpz_mod_mat_t X, fmpz_mod_mat_t tmp, const fmpz_mod_ctx_t ctx) { slong i, j, k, m, n, rank, nullity; slong * p; slong * pivots; slong * nonpivots; m = fmpz_mod_mat_nrows(tmp, ctx); n = fmpz_mod_mat_ncols(tmp, ctx); p = FLINT_ARRAY_ALLOC(FLINT_MAX(m, n), slong); rank = fmpz_mod_mat_rref(tmp, tmp, ctx); nullity = n - rank; fmpz_mod_mat_init(X, nullity, n, ctx); if (rank == 0) { for (i = 0; i < nullity; i++) fmpz_one(fmpz_mod_mat_entry(X, i, i)); } else if (nullity) { pivots = p; /* length = rank */ nonpivots = p + rank; /* length = nullity */ for (i = j = k = 0; i < rank; i++) { while (fmpz_is_zero(fmpz_mod_mat_entry(tmp, i, j))) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) { fmpz_mod_neg(fmpz_mod_mat_entry(X, i, pivots[j]), fmpz_mod_mat_entry(tmp, j, nonpivots[i]), ctx); } fmpz_one(fmpz_mod_mat_entry(X, i, nonpivots[i])); } } flint_free(p); } flint-3.1.3/src/fmpz_mod_mpoly_factor/fmpz_mod_poly_extras.c000066400000000000000000000113641461254215100244300ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_mpoly_factor.h" /* multiply A by (x^k + c) */ void fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod( fmpz_mod_poly_t A, slong k, const fmpz_t c, const fmpz_mod_ctx_t ctx) { fmpz * Acoeffs; slong i; slong Alen = A->length; fmpz_mod_poly_fit_length(A, Alen + k, ctx); Acoeffs = A->coeffs; for (i = Alen - 1; i >= 0; i--) fmpz_set(Acoeffs + k + i, Acoeffs + i); for (i = 0; i < k; i++) fmpz_zero(Acoeffs + i); for (i = 0; i < Alen; i++) fmpz_mod_addmul(Acoeffs + i, Acoeffs + i, c, Acoeffs + i + k, ctx); A->length = Alen + k; } /* A = B + C*d0 */ void fmpz_mod_poly_scalar_addmul_fmpz_mod( fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t C, const fmpz_t d0, const fmpz_mod_ctx_t ctx) { slong i; fmpz * Acoeffs, * Bcoeffs, * Ccoeffs; slong Blen = B->length; slong Clen = C->length; slong Alen = FLINT_MAX(B->length, C->length); fmpz_mod_poly_fit_length(A, Alen, ctx); Acoeffs = A->coeffs; Bcoeffs = B->coeffs; Ccoeffs = C->coeffs; for (i = 0; i < FLINT_MIN(Blen, Clen); i++) fmpz_mod_addmul(Acoeffs + i, Bcoeffs + i, Ccoeffs + i, d0, ctx); for ( ; i < Clen; i++) fmpz_mod_mul(Acoeffs + i, Ccoeffs + i, d0, ctx); for ( ; i < Blen; i++) fmpz_set(Acoeffs + i, Bcoeffs + i); A->length = Alen; _fmpz_mod_poly_normalise(A); } /* A = B + C*(d1*x+d0) */ void fmpz_mod_poly_addmul_linear( fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t C, const fmpz_t d1, const fmpz_t d0, const fmpz_mod_ctx_t ctx) { slong i; fmpz * Acoeffs, * Bcoeffs, * Ccoeffs; slong Blen = B->length; slong Clen = C->length; slong Alen = FLINT_MAX(B->length, C->length + 1); FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); fmpz_mod_poly_fit_length(A, Alen, ctx); Acoeffs = A->coeffs; Bcoeffs = B->coeffs; Ccoeffs = C->coeffs; for (i = 0; i < Alen; i++) { if (i < Blen) fmpz_set(Acoeffs + i, Bcoeffs + i); else fmpz_zero(Acoeffs + i); if (i < Clen) fmpz_addmul(Acoeffs + i, Ccoeffs + i, d0); if (0 < i && i - 1 < Clen) fmpz_addmul(Acoeffs + i, Ccoeffs + i - 1, d1); fmpz_mod_set_fmpz(Acoeffs + i, Acoeffs + i, ctx); } A->length = Alen; _fmpz_mod_poly_normalise(A); } /* evaluation at alphapow->coeffs[1] */ void fmpz_mod_poly_eval_pow( fmpz_t eval, const fmpz_mod_poly_t P, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx) { slong Plen = P->length; if (Plen > alphapow->length) { slong i = alphapow->length; FLINT_ASSERT(2 <= i); fmpz_mod_poly_fit_length(alphapow, Plen, ctx); alphapow->length = Plen; for ( ; i < Plen; i++) fmpz_mod_mul(alphapow->coeffs + i, alphapow->coeffs + i - 1, alphapow->coeffs + 1, ctx); } _fmpz_mod_vec_dot(eval, P->coeffs, alphapow->coeffs, Plen, ctx); } void fmpz_mod_poly_eval2_pow( fmpz_t vp, fmpz_t vm, const fmpz_mod_poly_t P, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx) { const fmpz * Pcoeffs = P->coeffs; slong Plen = P->length; fmpz * alpha_powers = alphapow->coeffs; fmpz_t a, b; slong k; fmpz_init(a); fmpz_init(b); if (Plen > alphapow->length) { slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); fmpz_mod_poly_fit_length(alphapow, Plen, ctx); for (k = oldlength; k < Plen; k++) { fmpz_mod_mul(alphapow->coeffs + k, alphapow->coeffs + k - 1, alphapow->coeffs + 1, ctx); } alphapow->length = Plen; alpha_powers = alphapow->coeffs; } for (k = 0; k + 2 <= Plen; k += 2) { fmpz_addmul(a, Pcoeffs + k + 0, alpha_powers + k + 0); fmpz_addmul(b, Pcoeffs + k + 1, alpha_powers + k + 1); } if (k < Plen) { fmpz_addmul(a, Pcoeffs + k + 0, alpha_powers + k + 0); k++; } FLINT_ASSERT(k == Plen); fmpz_mod_set_fmpz(a, a, ctx); fmpz_mod_set_fmpz(b, b, ctx); fmpz_mod_add(vp, a, b, ctx); fmpz_mod_sub(vm, a, b, ctx); fmpz_clear(a); fmpz_clear(b); } flint-3.1.3/src/fmpz_mod_mpoly_factor/fmpz_mod_poly_vec.c000066400000000000000000000047311461254215100236770ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" slong _fmpz_mod_poly_vec_max_degree(const fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_ctx_t ctx) { slong i, len = 0; for (i = 0; i < Alen; i++) len = FLINT_MAX(len, fmpz_mod_poly_length(A + i, ctx)); return len - 1; } void _fmpz_mod_poly_vec_content( fmpz_mod_poly_t g, const fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_zero(g, ctx); for (i = 0; i < Alen; i++) { fmpz_mod_poly_gcd(g, g, A + i, ctx); if (fmpz_mod_poly_is_one(g, ctx)) break; } } void _fmpz_mod_poly_vec_remove_content( fmpz_mod_poly_t g, fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t r; _fmpz_mod_poly_vec_content(g, A, Alen, ctx); if (fmpz_mod_poly_is_one(g, ctx)) return; fmpz_mod_poly_init(r, ctx); for (i = 0; i < Alen; i++) fmpz_mod_poly_divrem(A + i, r, A + i, g, ctx); fmpz_mod_poly_clear(r, ctx); } void _fmpz_mod_poly_vec_mul_poly( fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) { slong i; if (fmpz_mod_poly_is_one(g, ctx)) return; for (i = 0; i < Alen; i++) fmpz_mod_poly_mul(A + i, A + i, g, ctx); } void _fmpz_mod_poly_vec_divexact_poly( fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t t; if (fmpz_mod_poly_is_one(g, ctx)) return; fmpz_mod_poly_init(t, ctx); for (i = 0; i < Alen; i++) { fmpz_mod_poly_divrem(A + i, t, A + i, g, ctx); FLINT_ASSERT(fmpz_mod_poly_is_zero(t, ctx)); } fmpz_mod_poly_clear(t, ctx); } void _fmpz_mod_poly_vec_mul_fmpz_mod( fmpz_mod_poly_struct * A, slong Alen, const fmpz_t g, const fmpz_mod_ctx_t ctx) { slong i; if (fmpz_is_one(g)) return; for (i = 0; i < Alen; i++) fmpz_mod_poly_scalar_mul_fmpz(A + i, A + i, g, ctx); } flint-3.1.3/src/fmpz_mod_mpoly_factor/fmpz_mod_pow_cache.c000066400000000000000000000026661461254215100240140ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_pow_cache_start( const fmpz_t b, fmpz_mod_poly_t c, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(c, 2, ctx); c->length = 2; fmpz_one(c->coeffs + 0); fmpz_set(c->coeffs + 1, b); } /* a = b*c^e */ void fmpz_mod_pow_cache_mulpow_ui( fmpz_t a, const fmpz_t b, ulong e, fmpz_mod_poly_t c, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(c->length > 1); if (e < c->length) { fmpz_mod_mul(a, b, c->coeffs + e, ctx); return; } if (e > 50) { fmpz_mod_poly_fit_length(c, c->length + 1, ctx); fmpz_mod_pow_ui(c->coeffs + c->length, c->coeffs + 1, e, ctx); fmpz_mod_mul(a, b, c->coeffs + c->length, ctx); return; } fmpz_mod_poly_fit_length(c, e + 1, ctx); while (e >= c->length) { fmpz_mod_mul(c->coeffs + c->length, c->coeffs + c->length - 1, c->coeffs + 1, ctx); c->length++; } fmpz_mod_mul(a, b, c->coeffs + e, ctx); return; } flint-3.1.3/src/fmpz_mod_mpoly_factor/gcd_algo.c000066400000000000000000001576371461254215100217410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "nmod_mpoly.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" /* For each j, set out[j] to the evaluation of A at x_i = alpha[i] (i != j) i.e. if nvars = 3 out[0] = A(x, alpha[1], alpha[2]) out[1] = A(alpha[0], x, alpha[2]) out[2] = A(alpha[0], alpha[1], x) If ignore[j] is nonzero, then out[j] need not be calculated, probably because we shouldn't calculate it in dense form. */ static void fmpz_mod_mpoly_evals( slong * Atdeg, /* total degree of deflated A, or -1 for overflow */ fmpz_mod_poly_struct * out, const int * ignore, const fmpz_mod_mpoly_t A, ulong * Amin_exp, ulong * Amax_exp, ulong * Astride, const fmpz * alphas, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j; slong nvars = ctx->minfo->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * offsets, * shifts; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * varexps; ulong varexp; slong total_degree, lo, hi; fmpz_t meval, t, t1; fmpz_init(meval); fmpz_init(t); fmpz_init(t1); offsets = FLINT_ARRAY_ALLOC(2*nvars, slong); shifts = offsets + nvars; varexps = FLINT_ARRAY_ALLOC(nvars, ulong); for (j = 0; j < nvars; j++) { fmpz_mod_poly_zero(out + j, ctx->ffinfo); mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, ctx->minfo); } total_degree = 0; for (i = 0; i < A->length; i++) { fmpz * s = A->coeffs + i; hi = lo = 0; for (j = 0; j < nvars; j++) { varexp = ((A->exps + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexps[j] = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; add_ssaaaa(hi, lo, hi, lo, 0, varexps[j]); fmpz_mod_pow_ui(t1, alphas + j, varexps[j], ctx->ffinfo); fmpz_mod_mul(meval, s, t1, ctx->ffinfo); s = meval; } if (hi == 0 && FLINT_SIGN_EXT(lo) == 0 && total_degree >= 0) total_degree = FLINT_MAX(total_degree, lo); else total_degree = -1; for (j = 0; j < nvars; j++) { varexp = varexps[j]; if (ignore[j]) continue; fmpz_mod_poly_fit_length(out + j, varexp + 1, ctx->ffinfo); while (out[j].length <= varexp) { fmpz_zero(out[j].coeffs + out[j].length); out[j].length++; } fmpz_mod_inv(t1, alphas + j, ctx->ffinfo); fmpz_mod_pow_ui(t1, t1, varexps[j], ctx->ffinfo); fmpz_mod_mul(t, meval, t1, ctx->ffinfo); fmpz_mod_add(out[j].coeffs + varexp, out[j].coeffs + varexp, t, ctx->ffinfo); } } *Atdeg = total_degree; for (j = 0; j < nvars; j++) _fmpz_mod_poly_normalise(out + j); flint_free(offsets); flint_free(varexps); fmpz_clear(meval); fmpz_clear(t); fmpz_clear(t1); } static void _set_estimates( mpoly_gcd_info_t I, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int try_count = 0; slong nvars = ctx->minfo->nvars; slong i, j; fmpz_mod_poly_t Geval; fmpz_mod_poly_struct * Aevals, * Bevals; fmpz * alphas; flint_rand_t state; slong ignore_limit; int * ignore; flint_randinit(state); ignore = FLINT_ARRAY_ALLOC(nvars, int); alphas = _fmpz_vec_init(nvars); Aevals = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_poly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_poly_struct); fmpz_mod_poly_init(Geval, ctx->ffinfo); for (j = 0; j < nvars; j++) { fmpz_mod_poly_init(Aevals + j, ctx->ffinfo); fmpz_mod_poly_init(Bevals + j, ctx->ffinfo); } ignore_limit = (A->length + B->length)/4096; ignore_limit = FLINT_MAX(WORD(9999), ignore_limit); I->Gdeflate_deg_bounds_are_nice = 1; for (j = 0; j < nvars; j++) { if (I->Adeflate_deg[j] > ignore_limit || I->Bdeflate_deg[j] > ignore_limit) { ignore[j] = 1; I->Gdeflate_deg_bounds_are_nice = 0; } else { ignore[j] = 0; } } try_again: if (++try_count > 10) { I->Gdeflate_deg_bounds_are_nice = 0; for (j = 0; j < nvars; j++) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } goto cleanup; } for (j = 0; j < nvars; j++) fmpz_mod_rand_not_zero(alphas + j, state, ctx->ffinfo); fmpz_mod_mpoly_evals(&I->Adeflate_tdeg, Aevals, ignore, A, I->Amin_exp, I->Amax_exp, I->Gstride, alphas, ctx); fmpz_mod_mpoly_evals(&I->Bdeflate_tdeg, Bevals, ignore, B, I->Bmin_exp, I->Bmax_exp, I->Gstride, alphas, ctx); for (j = 0; j < nvars; j++) { if (ignore[j]) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } else { if (I->Adeflate_deg[j] != fmpz_mod_poly_degree(Aevals + j, ctx->ffinfo) || I->Bdeflate_deg[j] != fmpz_mod_poly_degree(Bevals + j, ctx->ffinfo)) { goto try_again; } fmpz_mod_poly_gcd(Geval, Aevals + j, Bevals + j, ctx->ffinfo); I->Gterm_count_est[j] = 0; I->Gdeflate_deg_bound[j] = fmpz_mod_poly_degree(Geval, ctx->ffinfo); for (i = I->Gdeflate_deg_bound[j]; i >= 0; i--) I->Gterm_count_est[j] += (Geval->coeffs[i] != 0); } } cleanup: fmpz_mod_poly_clear(Geval, ctx->ffinfo); for (j = 0; j < nvars; j++) { fmpz_mod_poly_clear(Aevals + j, ctx->ffinfo); fmpz_mod_poly_clear(Bevals + j, ctx->ffinfo); } flint_free(ignore); _fmpz_vec_clear(alphas, nvars); flint_free(Aevals); flint_free(Bevals); flint_randclear(state); return; } /* (Abar, Bbar) = (A, B) */ static void _parallel_set( fmpz_mod_mpoly_t Abar, /* could be NULL */ fmpz_mod_mpoly_t Bbar, /* could be NULL */ const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { if (Abar == B && Bbar == A) { FLINT_ASSERT(Abar != NULL && Bbar != NULL); fmpz_mod_mpoly_set(Abar, B, ctx); fmpz_mod_mpoly_set(Bbar, A, ctx); fmpz_mod_mpoly_swap(Abar, Bbar, ctx); } else if (Abar == B && Bbar != A) { FLINT_ASSERT(Abar != NULL); if (Bbar != NULL) fmpz_mod_mpoly_set(Bbar, B, ctx); fmpz_mod_mpoly_set(Abar, A, ctx); } else { if (Abar != NULL) fmpz_mod_mpoly_set(Abar, A, ctx); if (Bbar != NULL) fmpz_mod_mpoly_set(Bbar, B, ctx); } } /* The variables in ess(A) and ess(B) are disjoint. gcd is trivial to compute */ static void _do_trivial( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, /* could be NULL */ fmpz_mod_mpoly_t Bbar, /* could be NULL */ const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mod_mpoly_ctx_t ctx) { _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) mpoly_monomials_shift_right_ui(Abar->exps, Abar->bits, Abar->length, I->Gmin_exp, ctx->minfo); if (Bbar != NULL) mpoly_monomials_shift_right_ui(Bbar->exps, Bbar->bits, Bbar->length, I->Gmin_exp, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(G, 1, I->Gbits, ctx); mpoly_set_monomial_ui(G->exps, I->Gmin_exp, I->Gbits, ctx->minfo); fmpz_one(G->coeffs + 0); _fmpz_mod_mpoly_set_length(G, 1, ctx); } /*********************** Easy when B is a monomial ***************************/ static int _do_monomial_gcd( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, /* could be NULL */ fmpz_mod_mpoly_t Bbar, /* could be NULL */ const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); fmpz * minAfields, * minAdegs, * minBdegs; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length == 1); TMP_START; /* get the field-wise minimum of A */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, A->bits, ctx->minfo); /* unpack to get the min degrees of each variable in A */ minAdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minAdegs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(minAdegs, minAfields, ctx->minfo); /* get the degree of each variable in B */ minBdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minBdegs + i); mpoly_get_monomial_ffmpz(minBdegs, B->exps, B->bits, ctx->minfo); /* compute the degree of each variable in G */ _fmpz_vec_min_inplace(minBdegs, minAdegs, ctx->minfo->nvars); _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) mpoly_monomials_shift_right_ffmpz(Abar->exps, Abar->bits, Abar->length, minBdegs, ctx->minfo); if (Bbar != NULL) mpoly_monomials_shift_right_ffmpz(Bbar->exps, Bbar->bits, Bbar->length, minBdegs, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(G, 1, Gbits, ctx); mpoly_set_monomial_ffmpz(G->exps, minBdegs, Gbits, ctx->minfo); fmpz_one(G->coeffs + 0); _fmpz_mod_mpoly_set_length(G, 1, ctx); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(minAfields + i); } for (i = 0; i < ctx->minfo->nvars; i++) { fmpz_clear(minAdegs + i); fmpz_clear(minBdegs + i); } TMP_END; return 1; } /********************** See if cofactors are monomials ***********************/ static int _try_monomial_cofactors( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, /* could be NULL */ fmpz_mod_mpoly_t Bbar, /* could be NULL */ const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j; slong NA, NG; slong nvars = ctx->minfo->nvars; fmpz * Abarexps, * Bbarexps, * Texps; fmpz_t a0, b0, t1, t2; fmpz_mod_mpoly_t T; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); flint_bitcnt_t Abarbits = A->bits; flint_bitcnt_t Bbarbits = B->bits; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (A->length != B->length) return 0; fmpz_init(t1); fmpz_init(t2); fmpz_init(a0); fmpz_init(b0); for (i = A->length - 1; i > 0; i--) { fmpz_mod_mul(t1, A->coeffs + 0, B->coeffs + i, ctx->ffinfo); fmpz_mod_mul(t2, B->coeffs + 0, A->coeffs + i, ctx->ffinfo); success = fmpz_equal(t1, t2); if (!success) goto cleanup_less; } fmpz_set(a0, A->coeffs + 0); fmpz_set(b0, B->coeffs + 0); TMP_START; Abarexps = (fmpz *) TMP_ALLOC(3*nvars*sizeof(fmpz)); Bbarexps = Abarexps + 1*nvars; Texps = Abarexps + 2*nvars; for (j = 0; j < nvars; j++) { fmpz_init(Abarexps + j); fmpz_init(Bbarexps + j); fmpz_init(Texps + j); } success = mpoly_monomial_cofactors(Abarexps, Bbarexps, A->exps, A->bits, B->exps, B->bits, A->length, ctx->minfo); if (!success) goto cleanup_more; fmpz_mod_mpoly_init3(T, A->length, Gbits, ctx); NG = mpoly_words_per_exp(Gbits, ctx->minfo); NA = mpoly_words_per_exp(A->bits, ctx->minfo); fmpz_mod_inv(t1, A->coeffs + 0, ctx->ffinfo); T->length = A->length; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ffmpz(Texps, A->exps + NA*i, A->bits, ctx->minfo); _fmpz_vec_sub(Texps, Texps, Abarexps, nvars); mpoly_set_monomial_ffmpz(T->exps + NG*i, Texps, Gbits, ctx->minfo); fmpz_mod_mul(T->coeffs + i, A->coeffs + i, t1, ctx->ffinfo); } fmpz_mod_mpoly_swap(G, T, ctx); fmpz_mod_mpoly_clear(T, ctx); if (Abar != NULL) { fmpz_mod_mpoly_fit_length_reset_bits(Abar, 1, Abarbits, ctx); mpoly_set_monomial_ffmpz(Abar->exps, Abarexps, Abarbits, ctx->minfo); fmpz_set(Abar->coeffs + 0, a0); _fmpz_mod_mpoly_set_length(Abar, 1, ctx); } if (Bbar != NULL) { fmpz_mod_mpoly_fit_length_reset_bits(Bbar, 1, Bbarbits, ctx); mpoly_set_monomial_ffmpz(Bbar->exps, Bbarexps, Bbarbits, ctx->minfo); fmpz_set(Bbar->coeffs + 0, b0); _fmpz_mod_mpoly_set_length(Bbar, 1, ctx); } success = 1; cleanup_more: for (j = 0; j < nvars; j++) { fmpz_clear(Abarexps + j); fmpz_clear(Bbarexps + j); fmpz_clear(Texps + j); } TMP_END; cleanup_less: fmpz_clear(t1); fmpz_clear(t2); fmpz_clear(a0); fmpz_clear(b0); return success; } /*** ess(A) and ess(B) depend on only one variable v_in_both ****************/ static int _do_univar( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, slong v_in_both, const mpoly_gcd_info_t I, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_poly_t a, b, g, t, r; fmpz_mod_poly_init(a, ctx->ffinfo); fmpz_mod_poly_init(b, ctx->ffinfo); fmpz_mod_poly_init(g, ctx->ffinfo); fmpz_mod_poly_init(t, ctx->ffinfo); fmpz_mod_poly_init(r, ctx->ffinfo); _fmpz_mod_mpoly_to_fmpz_mod_poly_deflate(a, A, v_in_both, I->Amin_exp, I->Gstride, ctx); _fmpz_mod_mpoly_to_fmpz_mod_poly_deflate(b, B, v_in_both, I->Bmin_exp, I->Gstride, ctx); fmpz_mod_poly_gcd(g, a, b, ctx->ffinfo); _fmpz_mod_mpoly_from_fmpz_mod_poly_inflate(G, I->Gbits, g, v_in_both, I->Gmin_exp, I->Gstride, ctx); if (Abar != NULL) { fmpz_mod_poly_divrem(t, r, a, g, ctx->ffinfo); _fmpz_mod_mpoly_from_fmpz_mod_poly_inflate(Abar, I->Abarbits, t, v_in_both, I->Abarmin_exp, I->Gstride, ctx); } if (Bbar != NULL) { fmpz_mod_poly_divrem(t, r, b, g, ctx->ffinfo); _fmpz_mod_mpoly_from_fmpz_mod_poly_inflate(Bbar, I->Bbarbits, t, v_in_both, I->Bbarmin_exp, I->Gstride, ctx); } fmpz_mod_poly_clear(a, ctx->ffinfo); fmpz_mod_poly_clear(b, ctx->ffinfo); fmpz_mod_poly_clear(g, ctx->ffinfo); fmpz_mod_poly_clear(t, ctx->ffinfo); fmpz_mod_poly_clear(r, ctx->ffinfo); return 1; } /********* Assume B has length one when converted to univar format ***********/ static int _try_missing_var( fmpz_mod_mpoly_t G, flint_bitcnt_t Gbits, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, slong var, const fmpz_mod_mpoly_t A, ulong Ashift, const fmpz_mod_mpoly_t B, ulong Bshift, const fmpz_mod_mpoly_ctx_t ctx) { int success; fmpz_mod_mpoly_univar_t Au; fmpz_mod_mpoly_univar_init(Au, ctx); #if FLINT_WANT_ASSERT fmpz_mod_mpoly_to_univar(Au, B, var, ctx); FLINT_ASSERT(Au->length == 1); #endif fmpz_mod_mpoly_to_univar(Au, A, var, ctx); fmpz_mod_mpoly_univar_fit_length(Au, Au->length + 1, ctx); fmpz_mod_mpoly_set(Au->coeffs + Au->length, B, ctx); Au->length++; if (Abar == NULL && Bbar == NULL) { success = _fmpz_mod_mpoly_vec_content_mpoly(G, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_repack_bits_inplace(G, Gbits, ctx); _mpoly_gen_shift_left(G->exps, G->bits, G->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); } else { fmpz_mod_mpoly_t tG, tAbar, tBbar; fmpz_mod_mpoly_init(tG, ctx); fmpz_mod_mpoly_init(tAbar, ctx); fmpz_mod_mpoly_init(tBbar, ctx); success = _fmpz_mod_mpoly_vec_content_mpoly(tG, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_repack_bits_inplace(tG, Gbits, ctx); _mpoly_gen_shift_left(tG->exps, tG->bits, tG->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); if (Abar != NULL) { success = fmpz_mod_mpoly_divides(tAbar, A, tG, ctx); FLINT_ASSERT(success); } if (Bbar != NULL) { success = fmpz_mod_mpoly_divides(tBbar, B, tG, ctx); FLINT_ASSERT(success); } fmpz_mod_mpoly_swap(G, tG, ctx); if (Abar != NULL) fmpz_mod_mpoly_swap(Abar, tAbar, ctx); if (Bbar != NULL) fmpz_mod_mpoly_swap(Bbar, tBbar, ctx); fmpz_mod_mpoly_clear(tG, ctx); fmpz_mod_mpoly_clear(tAbar, ctx); fmpz_mod_mpoly_clear(tBbar, ctx); } success = 1; cleanup: fmpz_mod_mpoly_univar_clear(Au, ctx); return success; } /************************ See if B divides A ********************************/ static int _try_divides( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t BB, const fmpz_mod_mpoly_ctx_t ctx) { int success = 0; fmpz_mod_mpoly_t Q, B, M; fmpz_mod_mpoly_init(Q, ctx); fmpz_mod_mpoly_init(B, ctx); fmpz_mod_mpoly_init(M, ctx); /* BB = M*B */ fmpz_mod_mpoly_term_content(M, BB, ctx); fmpz_mod_mpoly_divides(B, BB, M, ctx); success = fmpz_mod_mpoly_divides(Q, A, B, ctx); if (success) { _do_monomial_gcd(G, Abar, Bbar, Q, M, ctx); fmpz_mod_mpoly_mul(G, G, B, ctx); } fmpz_mod_mpoly_clear(Q, ctx); fmpz_mod_mpoly_clear(B, ctx); fmpz_mod_mpoly_clear(M, ctx); return success; } /********************* Hit A and B with a prs ********************************/ static int _try_prs( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong j, var = -WORD(1); fmpz_mod_mpoly_t Ac, Bc, Gc, s, t; fmpz_mod_mpoly_univar_t Ax, Bx, Gx; for (j = 0; j < ctx->minfo->nvars; j++) { if (I->Amax_exp[j] <= I->Amin_exp[j] || I->Bmax_exp[j] <= I->Bmin_exp[j] /* not needed */) { FLINT_ASSERT(I->Amax_exp[j] == I->Amin_exp[j]); FLINT_ASSERT(I->Bmax_exp[j] == I->Bmin_exp[j]); continue; } FLINT_ASSERT(I->Gstride[j] != UWORD(0)); FLINT_ASSERT((I->Amax_exp[j] - I->Amin_exp[j]) % I->Gstride[j] == 0); FLINT_ASSERT((I->Bmax_exp[j] - I->Bmin_exp[j]) % I->Gstride[j] == 0); var = j; break; } if (var < 0) return 0; fmpz_mod_mpoly_init(Ac, ctx); fmpz_mod_mpoly_init(Bc, ctx); fmpz_mod_mpoly_init(Gc, ctx); fmpz_mod_mpoly_init(s, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_univar_init(Ax, ctx); fmpz_mod_mpoly_univar_init(Bx, ctx); fmpz_mod_mpoly_univar_init(Gx, ctx); fmpz_mod_mpoly_to_univar(Ax, A, var, ctx); fmpz_mod_mpoly_to_univar(Bx, B, var, ctx); success = _fmpz_mod_mpoly_vec_content_mpoly(Ac, Ax->coeffs, Ax->length, ctx) && _fmpz_mod_mpoly_vec_content_mpoly(Bc, Bx->coeffs, Bx->length, ctx) && fmpz_mod_mpoly_gcd(Gc, Ac, Bc, ctx); if (!success) goto cleanup; _fmpz_mod_mpoly_vec_divexact_mpoly(Ax->coeffs, Ax->length, Ac, ctx); _fmpz_mod_mpoly_vec_divexact_mpoly(Bx->coeffs, Bx->length, Bc, ctx); success = fmpz_cmp(Ax->exps + 0, Bx->exps + 0) > 0 ? fmpz_mod_mpoly_univar_pseudo_gcd(Gx, Ax, Bx, ctx) : fmpz_mod_mpoly_univar_pseudo_gcd(Gx, Bx, Ax, ctx); if (!success) goto cleanup; if (fmpz_mod_mpoly_gcd(t, Ax->coeffs + 0, Bx->coeffs + 0, ctx) && t->length == 1) { fmpz_mod_mpoly_term_content(s, Gx->coeffs + 0, ctx); fmpz_mod_mpoly_divexact(t, Gx->coeffs + 0, s, ctx); _fmpz_mod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } else if (fmpz_mod_mpoly_gcd(t, Ax->coeffs + Ax->length - 1, Bx->coeffs + Bx->length - 1, ctx) && t->length == 1) { fmpz_mod_mpoly_term_content(s, Gx->coeffs + Gx->length - 1, ctx); fmpz_mod_mpoly_divexact(t, Gx->coeffs + Gx->length - 1, s, ctx); _fmpz_mod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } success = _fmpz_mod_mpoly_vec_content_mpoly(t, Gx->coeffs, Gx->length, ctx); if (!success) goto cleanup; _fmpz_mod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); _fmpz_mod_mpoly_vec_mul_mpoly(Gx->coeffs, Gx->length, Gc, ctx); _fmpz_mod_mpoly_from_univar(Gc, I->Gbits, Gx, var, ctx); if (Abar != NULL) fmpz_mod_mpoly_divexact(s, A, Gc, ctx); if (Bbar != NULL) fmpz_mod_mpoly_divexact(t, B, Gc, ctx); fmpz_mod_mpoly_swap(G, Gc, ctx); if (Abar != NULL) fmpz_mod_mpoly_swap(Abar, s, ctx); if (Bbar != NULL) fmpz_mod_mpoly_swap(Bbar, t, ctx); success = 1; cleanup: fmpz_mod_mpoly_clear(Ac, ctx); fmpz_mod_mpoly_clear(Bc, ctx); fmpz_mod_mpoly_clear(Gc, ctx); fmpz_mod_mpoly_clear(s, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_univar_clear(Ax, ctx); fmpz_mod_mpoly_univar_clear(Bx, ctx); fmpz_mod_mpoly_univar_clear(Gx, ctx); return success; } /********************** Hit A and B with zippel ******************************/ static int _try_zippel( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mod_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; fmpz_mod_mpoly_ctx_t lctx; fmpz_mod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mod_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; slong max_deg; flint_rand_t state; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL)) return 0; FLINT_ASSERT(m >= 2); flint_randinit(state); fmpz_mod_mpoly_ctx_init(lctx, m, ORD_LEX, fmpz_mod_ctx_modulus(ctx->ffinfo)); max_deg = 0; for (i = 0; i < m; i++) { k = I->zippel_perm[i]; max_deg = FLINT_MAX(max_deg, I->Adeflate_deg[k]); max_deg = FLINT_MAX(max_deg, I->Bdeflate_deg[k]); } wbits = 1 + FLINT_BIT_COUNT(max_deg); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fmpz_mod_mpoly_init3(Al, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarc, 0, wbits, lctx); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->zippel_perm, I->Amin_exp, I->Gstride); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->zippel_perm, I->Bmin_exp, I->Gstride); success = fmpz_mod_mpolyl_content(Ac, Al, 1, lctx) && fmpz_mod_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; success = _fmpz_mod_mpoly_gcd_algo(Gc, Abar == NULL ? NULL : Abarc, Bbar == NULL ? NULL : Bbarc, Ac, Bc, lctx, MPOLY_GCD_USE_ALL); if (!success) goto cleanup; success = fmpz_mod_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = fmpz_mod_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fmpz_mod_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mod_mpoly_repack_bits_inplace(Bl, wbits, lctx); success = fmpz_mod_mpolyl_gcdp_zippel(Gl, Abarl, Bbarl, Al, Bl, m - 1, lctx, state); if (!success) goto cleanup; fmpz_mod_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->zippel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fmpz_mod_mpoly_mul(Abarl, Abarl, Abarc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->zippel_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fmpz_mod_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->zippel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fmpz_mod_mpoly_clear(Al, lctx); fmpz_mod_mpoly_clear(Bl, lctx); fmpz_mod_mpoly_clear(Gl, lctx); fmpz_mod_mpoly_clear(Abarl, lctx); fmpz_mod_mpoly_clear(Bbarl, lctx); fmpz_mod_mpoly_clear(Ac, lctx); fmpz_mod_mpoly_clear(Bc, lctx); fmpz_mod_mpoly_clear(Gc, lctx); fmpz_mod_mpoly_clear(Abarc, lctx); fmpz_mod_mpoly_clear(Bbarc, lctx); fmpz_mod_mpoly_ctx_clear(lctx); flint_randclear(state); return success; } static int _try_zippel2( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mod_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; fmpz_mod_mpoly_ctx_t lctx; fmpz_mod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mod_mpoly_t Al_lc, Bl_lc, Ac, Bc, Gc, Abarc, Bbarc, Gamma; slong * tmp, * Gl_degs, * Al_degs, * Bl_degs, * Gamma_degs, * Gguess; slong max_degree; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL2)) return 0; FLINT_ASSERT(m >= 3); tmp = FLINT_ARRAY_ALLOC(5*m, slong); Al_degs = tmp + 1*m; Bl_degs = tmp + 2*m; Gl_degs = tmp + 3*m; Gamma_degs = tmp + 4*m; fmpz_mod_mpoly_ctx_init(lctx, m, ORD_LEX, fmpz_mod_ctx_modulus(ctx->ffinfo)); max_degree = 0; for (i = 0; i < m; i++) { k = I->zippel2_perm[i]; Gl_degs[i] = I->Gdeflate_deg_bound[k]; Al_degs[i] = I->Adeflate_deg[k]; max_degree = FLINT_MAX(max_degree, Al_degs[i]); Bl_degs[i] = I->Bdeflate_deg[k]; max_degree = FLINT_MAX(max_degree, Bl_degs[i]); } wbits = 1 + FLINT_BIT_COUNT(max_degree); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fmpz_mod_mpoly_init3(Al, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gamma, 0, wbits, lctx); fmpz_mod_mpoly_init3(Al_lc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl_lc, 0, wbits, lctx); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->zippel2_perm, I->Amin_exp, I->Gstride); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->zippel2_perm, I->Bmin_exp, I->Gstride); success = fmpz_mod_mpolyl_content(Ac, Al, 2, lctx) && fmpz_mod_mpolyl_content(Bc, Bl, 2, lctx); if (!success) goto cleanup; success = _fmpz_mod_mpoly_gcd_algo(Gc, Abar == NULL ? NULL : Abarc, Bbar == NULL ? NULL : Bbarc, Ac, Bc, lctx, MPOLY_GCD_USE_ALL); if (!success) goto cleanup; fmpz_mod_mpoly_degrees_si(tmp, Ac, lctx); for (i = 0; i < m; i++) Al_degs[i] -= tmp[i]; success = fmpz_mod_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); fmpz_mod_mpoly_degrees_si(tmp, Bc, lctx); for (i = 0; i < m; i++) Bl_degs[i] -= tmp[i]; success = fmpz_mod_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fmpz_mod_mpoly_degrees_si(tmp, Gc, lctx); for (i = 0; i < m; i++) Gl_degs[i] -= tmp[i]; fmpz_mod_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mod_mpoly_repack_bits_inplace(Bl, wbits, lctx); fmpz_mod_mpolyl_lead_coeff(Al_lc, Al, 2, lctx); fmpz_mod_mpolyl_lead_coeff(Bl_lc, Bl, 2, lctx); success = fmpz_mod_mpoly_gcd(Gamma, Al_lc, Bl_lc, lctx); if (!success) goto cleanup; fmpz_mod_mpoly_repack_bits_inplace(Gamma, wbits, lctx); fmpz_mod_mpoly_degrees_si(Gamma_degs, Gamma, lctx); Gguess = I->Gdeflate_deg_bounds_are_nice ? Gl_degs : NULL; success = fmpz_mod_mpolyl_gcd_zippel2_smprime(Gl, Gguess, Abarl, Bbarl, Al, Al_degs, Bl, Bl_degs, Gamma, Gamma_degs, lctx); if (!success) goto cleanup; fmpz_mod_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->zippel2_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fmpz_mod_mpoly_mul(Abarl, Abarl, Abarc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->zippel2_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fmpz_mod_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->zippel2_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fmpz_mod_mpoly_clear(Al, lctx); fmpz_mod_mpoly_clear(Bl, lctx); fmpz_mod_mpoly_clear(Gl, lctx); fmpz_mod_mpoly_clear(Abarl, lctx); fmpz_mod_mpoly_clear(Bbarl, lctx); fmpz_mod_mpoly_clear(Ac, lctx); fmpz_mod_mpoly_clear(Bc, lctx); fmpz_mod_mpoly_clear(Gc, lctx); fmpz_mod_mpoly_clear(Abarc, lctx); fmpz_mod_mpoly_clear(Bbarc, lctx); fmpz_mod_mpoly_clear(Gamma, lctx); fmpz_mod_mpoly_clear(Al_lc, lctx); fmpz_mod_mpoly_clear(Bl_lc, lctx); fmpz_mod_mpoly_ctx_clear(lctx); flint_free(tmp); return success; } /******************** Hit A and B with hensel lifting ************************/ static int _try_hensel( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mod_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; fmpz_mod_mpoly_ctx_t lctx; fmpz_mod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mod_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; slong max_deg; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_HENSEL)) return 0; FLINT_ASSERT(m >= 2); fmpz_mod_mpoly_ctx_init(lctx, m, ORD_LEX, fmpz_mod_ctx_modulus(ctx->ffinfo)); max_deg = 0; for (i = 0; i < m; i++) { k = I->hensel_perm[i]; max_deg = FLINT_MAX(max_deg, I->Adeflate_deg[k]); max_deg = FLINT_MAX(max_deg, I->Bdeflate_deg[k]); } wbits = 1 + FLINT_BIT_COUNT(max_deg); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fmpz_mod_mpoly_init3(Al, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarc, 0, wbits, lctx); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->hensel_perm, I->Amin_exp, I->Gstride); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->hensel_perm, I->Bmin_exp, I->Gstride); success = fmpz_mod_mpolyl_content(Ac, Al, 1, lctx) && fmpz_mod_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; success = _fmpz_mod_mpoly_gcd_algo(Gc, Abar == NULL ? NULL : Abarc, Bbar == NULL ? NULL : Bbarc, Ac, Bc, lctx, MPOLY_GCD_USE_ALL); if (!success) goto cleanup; success = fmpz_mod_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = fmpz_mod_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fmpz_mod_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mod_mpoly_repack_bits_inplace(Bl, wbits, lctx); max_deg = I->Gdeflate_deg_bound[I->hensel_perm[0]]; success = fmpz_mod_mpolyl_gcd_hensel_smprime(Gl, max_deg, Abarl, Bbarl, Al, Bl, lctx); if (!success) goto cleanup; fmpz_mod_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->hensel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fmpz_mod_mpoly_mul(Abarl, Abarl, Abarc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->hensel_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fmpz_mod_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->hensel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fmpz_mod_mpoly_clear(Al, lctx); fmpz_mod_mpoly_clear(Bl, lctx); fmpz_mod_mpoly_clear(Gl, lctx); fmpz_mod_mpoly_clear(Abarl, lctx); fmpz_mod_mpoly_clear(Bbarl, lctx); fmpz_mod_mpoly_clear(Ac, lctx); fmpz_mod_mpoly_clear(Bc, lctx); fmpz_mod_mpoly_clear(Gc, lctx); fmpz_mod_mpoly_clear(Abarc, lctx); fmpz_mod_mpoly_clear(Bbarc, lctx); fmpz_mod_mpoly_ctx_clear(lctx); return success; } /*********************** Hit A and B with brown ******************************/ static int _try_brown( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, mpoly_gcd_info_t I, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong m = I->mvars; flint_bitcnt_t wbits; fmpz_mod_mpoly_ctx_t nctx; fmpz_mod_mpolyn_t An, Bn, Gn, Abarn, Bbarn; fmpz_mod_poly_polyun_mpolyn_stack_t St; if (!(I->can_use & MPOLY_GCD_USE_BROWN)) return 0; FLINT_ASSERT(m >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); wbits = FLINT_MAX(A->bits, B->bits); fmpz_mod_mpoly_ctx_init(nctx, m, ORD_LEX, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_mod_mpolyn_init(An, wbits, nctx); fmpz_mod_mpolyn_init(Bn, wbits, nctx); fmpz_mod_mpolyn_init(Gn, wbits, nctx); fmpz_mod_mpolyn_init(Abarn, wbits, nctx); fmpz_mod_mpolyn_init(Bbarn, wbits, nctx); fmpz_mod_poly_stack_init(St->poly_stack); fmpz_mod_polyun_stack_init(St->polyun_stack); fmpz_mod_mpolyn_stack_init(St->mpolyn_stack, wbits, nctx); fmpz_mod_mpoly_to_mpolyn_perm_deflate(An, nctx, A, ctx, I->brown_perm, I->Amin_exp, I->Gstride); fmpz_mod_mpoly_to_mpolyn_perm_deflate(Bn, nctx, B, ctx, I->brown_perm, I->Bmin_exp, I->Gstride); FLINT_ASSERT(An->bits == wbits); FLINT_ASSERT(Bn->bits == wbits); FLINT_ASSERT(An->length > 0); FLINT_ASSERT(Bn->length > 0); success = fmpz_mod_mpolyn_gcd_brown_smprime(Gn, Abarn, Bbarn, An, Bn, m - 1, nctx, I, St); if (!success) goto cleanup; fmpz_mod_mpoly_from_mpolyn_perm_inflate(G, I->Gbits, ctx, Gn, nctx, I->brown_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) fmpz_mod_mpoly_from_mpolyn_perm_inflate(Abar, I->Abarbits, ctx, Abarn, nctx, I->brown_perm, I->Abarmin_exp, I->Gstride); if (Bbar != NULL) fmpz_mod_mpoly_from_mpolyn_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarn, nctx, I->brown_perm, I->Bbarmin_exp, I->Gstride); success = 1; cleanup: fmpz_mod_poly_stack_clear(St->poly_stack); fmpz_mod_polyun_stack_clear(St->polyun_stack); fmpz_mod_mpolyn_stack_clear(St->mpolyn_stack, nctx); fmpz_mod_mpolyn_clear(An, nctx); fmpz_mod_mpolyn_clear(Bn, nctx); fmpz_mod_mpolyn_clear(Gn, nctx); fmpz_mod_mpolyn_clear(Abarn, nctx); fmpz_mod_mpolyn_clear(Bbarn, nctx); fmpz_mod_mpoly_ctx_clear(nctx); return success; } static int _try_nmod( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { int success; nmod_mpoly_ctx_t nctx; nmod_mpoly_t nG, nAbar, nBbar, nA, nB; FLINT_ASSERT(fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); *nctx->minfo = *ctx->minfo; nmod_init(&nctx->mod, fmpz_get_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); nmod_mpoly_init(nG, nctx); nmod_mpoly_init(nAbar, nctx); nmod_mpoly_init(nBbar, nctx); nmod_mpoly_init(nA, nctx); nmod_mpoly_init(nB, nctx); _fmpz_mod_mpoly_get_nmod_mpoly(nA, nctx, A, ctx); _fmpz_mod_mpoly_get_nmod_mpoly(nB, nctx, B, ctx); success = _nmod_mpoly_gcd_algo_small(nG, Abar == NULL ? NULL : nAbar, Bbar == NULL ? NULL : nBbar, nA, nB, nctx, algo); _fmpz_mod_mpoly_set_nmod_mpoly(G, ctx, nG, nctx); if (Abar != NULL) _fmpz_mod_mpoly_set_nmod_mpoly(Abar, ctx, nAbar, nctx); if (Bbar != NULL) _fmpz_mod_mpoly_set_nmod_mpoly(Bbar, ctx, nBbar, nctx); nmod_mpoly_clear(nG, nctx); nmod_mpoly_clear(nAbar, nctx); nmod_mpoly_clear(nBbar, nctx); nmod_mpoly_clear(nA, nctx); nmod_mpoly_clear(nB, nctx); return success; } /* Both A and B have to be packed into bits <= FLINT_BITS return is 1 for success, 0 for failure. */ static int _fmpz_mod_mpoly_gcd_algo_small( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, /* could be NULL */ fmpz_mod_mpoly_t Bbar, /* could be NULL */ const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong v_in_both; slong v_in_either; slong v_in_A_only; slong v_in_B_only; slong j; slong nvars = ctx->minfo->nvars; mpoly_gcd_info_t I; #if FLINT_WANT_ASSERT fmpz_mod_mpoly_t T, Asave, Bsave; #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); #if FLINT_WANT_ASSERT fmpz_mod_mpoly_init(T, ctx); fmpz_mod_mpoly_init(Asave, ctx); fmpz_mod_mpoly_init(Bsave, ctx); fmpz_mod_mpoly_set(Asave, A, ctx); fmpz_mod_mpoly_set(Bsave, B, ctx); #endif mpoly_gcd_info_init(I, nvars); /* entries of I are all now invalid */ I->Gbits = FLINT_MIN(A->bits, B->bits); I->Abarbits = A->bits; I->Bbarbits = B->bits; mpoly_gcd_info_limits(I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, A->exps, A->bits, A->length, ctx->minfo); mpoly_gcd_info_limits(I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, B->exps, B->bits, B->length, ctx->minfo); /* set ess(p) := p/term_content(p) */ /* check if the cofactors could be monomials, i.e. ess(A) == ess(B) */ for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] - I->Amin_exp[j] != I->Bmax_exp[j] - I->Bmin_exp[j]) goto skip_monomial_cofactors; } if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) goto successful; skip_monomial_cofactors: if (fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))) { success = _try_nmod(G, Abar, Bbar, A, B, ctx, algo); goto cleanup; } mpoly_gcd_info_stride(I->Gstride, A->exps, A->bits, A->length, I->Amax_exp, I->Amin_exp, B->exps, B->bits, B->length, I->Bmax_exp, I->Bmin_exp, ctx->minfo); for (j = 0; j < nvars; j++) { ulong t = I->Gstride[j]; if (t == 0) { FLINT_ASSERT(I->Amax_exp[j] == I->Amin_exp[j] || I->Bmax_exp[j] == I->Bmin_exp[j]); } else { FLINT_ASSERT((I->Amax_exp[j] - I->Amin_exp[j]) % t == 0); FLINT_ASSERT((I->Bmax_exp[j] - I->Bmin_exp[j]) % t == 0); } I->Adeflate_deg[j] = t == 0 ? 0 : (I->Amax_exp[j] - I->Amin_exp[j])/t; I->Bdeflate_deg[j] = t == 0 ? 0 : (I->Bmax_exp[j] - I->Bmin_exp[j])/t; t = FLINT_MIN(I->Amin_exp[j], I->Bmin_exp[j]); I->Gmin_exp[j] = t; I->Abarmin_exp[j] = I->Amin_exp[j] - t; I->Bbarmin_exp[j] = I->Bmin_exp[j] - t; } /* The following are now valid: I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, I->Gstride I->Adeflate_deg I->Bdeflate_deg I->Gmin_exp */ /* check if ess(A) and ess(B) have a variable v_in_both in common */ v_in_both = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_both = j; break; } } if (v_in_both == -WORD(1)) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } /* check if ess(A) and ess(B) depend on another variable v_in_either */ FLINT_ASSERT(0 <= v_in_both && v_in_both < nvars); v_in_either = -WORD(1); for (j = 0; j < nvars; j++) { if (j == v_in_both) continue; if (I->Amax_exp[j] > I->Amin_exp[j] || I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_either = j; break; } } if (v_in_either == -WORD(1)) { _do_univar(G, Abar, Bbar, A, B, v_in_both, I, ctx); goto successful; } /* check if there is a variable in ess(A) that is not in ess(B) */ v_in_A_only = -WORD(1); v_in_B_only = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] == I->Bmin_exp[j]) { v_in_A_only = j; break; } if (I->Bmax_exp[j] > I->Bmin_exp[j] && I->Amax_exp[j] == I->Amin_exp[j]) { v_in_B_only = j; break; } } if (v_in_A_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Abar, Bbar, v_in_A_only, A, I->Amin_exp[v_in_A_only], B, I->Bmin_exp[v_in_A_only], ctx); goto cleanup; } if (v_in_B_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Bbar, Abar, v_in_B_only, B, I->Bmin_exp[v_in_B_only], A, I->Amin_exp[v_in_B_only], ctx); goto cleanup; } /* all variable are now either missing from both ess(A) and ess(B), or present in both ess(A) and ess(B) and there are at least two in the latter case */ mpoly_gcd_info_set_perm(I, A->length, B->length, ctx->minfo); /* _set_estimates will probably calculate the correct total degrees */ I->Adeflate_tdeg = I->Bdeflate_tdeg = -1; _set_estimates(I, A, B, ctx); /* everything in I is valid now */ /* check divisibility A/B and B/A */ { int gcd_is_trivial = 1; int try_a = I->Gdeflate_deg_bounds_are_nice; int try_b = I->Gdeflate_deg_bounds_are_nice; for (j = 0; j < nvars; j++) { if (I->Gdeflate_deg_bound[j] != 0) gcd_is_trivial = 0; if (I->Adeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_a = 0; if (I->Bdeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_b = 0; } if (gcd_is_trivial) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } if (try_a && _try_divides(G, Bbar, Abar, B, A, ctx)) goto successful; if (try_b && _try_divides(G, Abar, Bbar, A, B, ctx)) goto successful; } if (algo == MPOLY_GCD_USE_PRS) { success = _try_prs(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } if (I->mvars < 3) { mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); algo &= (MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); if (algo == MPOLY_GCD_USE_BROWN) { success = _try_brown(G, Abar, Bbar, A, B, I, ctx); } else if (algo == MPOLY_GCD_USE_HENSEL) { success = _try_hensel(G, Abar, Bbar, A, B, I, ctx); } else { if (I->Adensity + I->Bdensity > 0.05) { success = _try_brown(G, Abar, Bbar, A, B, I, ctx) || _try_hensel(G, Abar, Bbar, A, B, I, ctx); } else { success = _try_hensel(G, Abar, Bbar, A, B, I, ctx) || _try_brown(G, Abar, Bbar, A, B, I, ctx); } } goto cleanup; } else if (algo == MPOLY_GCD_USE_HENSEL) { mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); success = _try_hensel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_BROWN) { mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); success = _try_brown(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL) { mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); success = _try_zippel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL2) { mpoly_gcd_info_measure_zippel2(I, A->length, B->length, ctx->minfo); success = _try_zippel2(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else { slong k; int deg_is_small = 1; double density = I->Adensity + I->Bdensity; /* mpoly gcd case. Only rule is that measure_X must be called before try_X is called or I->X_perm is accessed. */ mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_zippel2(I, A->length, B->length, ctx->minfo); if (density > 0.08) { if (!deg_is_small && _try_hensel(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_brown(G, Abar, Bbar, A, B, I, ctx)) goto successful; } if (I->Adeflate_tdeg > 0 && I->Bdeflate_tdeg > 0) { fmpz_t x; double tdensity; fmpz_init(x); fmpz_bin_uiui(x, (ulong)I->Adeflate_tdeg + I->mvars, I->mvars); tdensity = A->length/fmpz_get_d(x); fmpz_bin_uiui(x, (ulong)I->Bdeflate_tdeg + I->mvars, I->mvars); tdensity += B->length/fmpz_get_d(x); density = FLINT_MAX(density, tdensity); fmpz_clear(x); } if (density > (deg_is_small ? 0.05 : 0.001)) { if (_try_hensel(G, Abar, Bbar, A, B, I, ctx)) goto successful; } k = I->zippel2_perm[1]; k = FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); if ((A->length + B->length)/64 < k) { if (_try_zippel(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_zippel2(G, Abar, Bbar, A, B, I, ctx)) goto successful; } else { if (_try_zippel2(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_zippel(G, Abar, Bbar, A, B, I, ctx)) goto successful; } success = _try_hensel(G, Abar, Bbar, A, B, I, ctx) || _try_brown(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } success = 0; goto cleanup; successful: success = 1; cleanup: mpoly_gcd_info_clear(I); if (success) { FLINT_ASSERT(G->length > 0); if (!fmpz_is_one(G->coeffs + 0)) { if (Abar != NULL) _fmpz_mod_vec_scalar_mul_fmpz_mod(Abar->coeffs, Abar->coeffs, Abar->length, G->coeffs + 0, ctx->ffinfo); if (Bbar != NULL) _fmpz_mod_vec_scalar_mul_fmpz_mod(Bbar->coeffs, Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx->ffinfo); _fmpz_mod_vec_scalar_div_fmpz_mod(G->coeffs, G->coeffs, G->length, G->coeffs + 0, ctx->ffinfo); } FLINT_ASSERT(fmpz_mod_mpoly_divides(T, Asave, G, ctx)); FLINT_ASSERT(Abar == NULL || fmpz_mod_mpoly_equal(T, Abar, ctx)); FLINT_ASSERT(fmpz_mod_mpoly_divides(T, Bsave, G, ctx)); FLINT_ASSERT(Bbar == NULL || fmpz_mod_mpoly_equal(T, Bbar, ctx)); } #if FLINT_WANT_ASSERT fmpz_mod_mpoly_clear(T, ctx); fmpz_mod_mpoly_clear(Asave, ctx); fmpz_mod_mpoly_clear(Bsave, ctx); #endif return success; } /* The gcd calculation is unusual. First see if both inputs fit into FLINT_BITS. Then, try deflation as a last resort. */ static int _fmpz_mod_mpoly_gcd_algo_large( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong k; fmpz * Ashift, * Astride; fmpz * Bshift, * Bstride; fmpz * Gshift, * Gstride; fmpz_mod_mpoly_t Anew, Bnew; const fmpz_mod_mpoly_struct * Ause, * Buse; if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) return 1; fmpz_mod_mpoly_init(Anew, ctx); fmpz_mod_mpoly_init(Bnew, ctx); Ause = A; if (A->bits > FLINT_BITS) { if (!fmpz_mod_mpoly_repack_bits(Anew, A, FLINT_BITS, ctx)) goto could_not_repack; Ause = Anew; } Buse = B; if (B->bits > FLINT_BITS) { if (!fmpz_mod_mpoly_repack_bits(Bnew, B, FLINT_BITS, ctx)) goto could_not_repack; Buse = Bnew; } success = _fmpz_mod_mpoly_gcd_algo_small(G, Abar, Bbar, Ause, Buse, ctx, algo); goto cleanup; could_not_repack: /* One of A or B could not be repacked into FLINT_BITS. See if they both fit into FLINT_BITS after deflation. */ Ashift = _fmpz_vec_init(ctx->minfo->nvars); Astride = _fmpz_vec_init(ctx->minfo->nvars); Bshift = _fmpz_vec_init(ctx->minfo->nvars); Bstride = _fmpz_vec_init(ctx->minfo->nvars); Gshift = _fmpz_vec_init(ctx->minfo->nvars); Gstride = _fmpz_vec_init(ctx->minfo->nvars); fmpz_mod_mpoly_deflation(Ashift, Astride, A, ctx); fmpz_mod_mpoly_deflation(Bshift, Bstride, B, ctx); _fmpz_vec_min(Gshift, Ashift, Bshift, ctx->minfo->nvars); for (k = 0; k < ctx->minfo->nvars; k++) fmpz_gcd(Gstride + k, Astride + k, Bstride + k); fmpz_mod_mpoly_deflate(Anew, A, Ashift, Gstride, ctx); if (Anew->bits > FLINT_BITS) { success = fmpz_mod_mpoly_repack_bits(Anew, Anew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } fmpz_mod_mpoly_deflate(Bnew, B, Bshift, Gstride, ctx); if (Bnew->bits > FLINT_BITS) { success = fmpz_mod_mpoly_repack_bits(Bnew, Bnew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } success = _fmpz_mod_mpoly_gcd_algo_small(G, Abar, Bbar, Anew, Bnew, ctx, algo); if (!success) goto deflate_cleanup; for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_sub(Ashift + k, Ashift + k, Gshift + k); fmpz_sub(Bshift + k, Bshift + k, Gshift + k); FLINT_ASSERT(fmpz_sgn(Ashift + k) >= 0); FLINT_ASSERT(fmpz_sgn(Bshift + k) >= 0); } fmpz_mod_mpoly_inflate(G, G, Gshift, Gstride, ctx); if (Abar != NULL) fmpz_mod_mpoly_inflate(Abar, Abar, Ashift, Gstride, ctx); if (Bbar != NULL) fmpz_mod_mpoly_inflate(Bbar, Bbar, Bshift, Gstride, ctx); FLINT_ASSERT(G->length > 0); if (!fmpz_is_one(G->coeffs + 0)) { if (Abar != NULL) _fmpz_mod_vec_scalar_mul_fmpz_mod(Abar->coeffs, Abar->coeffs, Abar->length, G->coeffs + 0, ctx->ffinfo); if (Bbar != NULL) _fmpz_mod_vec_scalar_mul_fmpz_mod(Bbar->coeffs, Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx->ffinfo); _fmpz_mod_vec_scalar_div_fmpz_mod(G->coeffs, G->coeffs, G->length, G->coeffs + 0, ctx->ffinfo); } deflate_cleanup: _fmpz_vec_clear(Ashift, ctx->minfo->nvars); _fmpz_vec_clear(Astride, ctx->minfo->nvars); _fmpz_vec_clear(Bshift, ctx->minfo->nvars); _fmpz_vec_clear(Bstride, ctx->minfo->nvars); _fmpz_vec_clear(Gshift, ctx->minfo->nvars); _fmpz_vec_clear(Gstride, ctx->minfo->nvars); cleanup: fmpz_mod_mpoly_clear(Anew, ctx); fmpz_mod_mpoly_clear(Bnew, ctx); return success; } int _fmpz_mod_mpoly_gcd_algo( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, unsigned int algo) { FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(B, ctx)); if (A->bits <= FLINT_BITS && B->bits <= FLINT_BITS) return _fmpz_mod_mpoly_gcd_algo_small(G, Abar, Bbar, A, B, ctx, algo); else return _fmpz_mod_mpoly_gcd_algo_large(G, Abar, Bbar, A, B, ctx, algo); } flint-3.1.3/src/fmpz_mod_mpoly_factor/gcd_brown.c000066400000000000000000000603151461254215100221300ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" static void _fmpz_mod_poly_gcd_cofactors( fmpz_mod_poly_t G, fmpz_mod_poly_t Abar, fmpz_mod_poly_t Bbar, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_t t) { fmpz_mod_poly_gcd(G, A, B, ctx); fmpz_mod_poly_divrem(Abar, t, A, G, ctx); fmpz_mod_poly_divrem(Bbar, t, B, G, ctx); } int fmpz_mod_polyu1n_gcd_brown_smprime( fmpz_mod_polyun_t G, fmpz_mod_polyun_t Abar, fmpz_mod_polyun_t Bbar, fmpz_mod_polyun_t A, fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_stack_t St_poly, fmpz_mod_polyun_stack_t St_polyun) { int success; slong bound; fmpz_t alpha, temp, gammaevalp, gammaevalm; fmpz_mod_poly_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp; fmpz_mod_poly_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm; fmpz_mod_polyun_struct * T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; fmpz_mod_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma; fmpz_mod_poly_struct * modulus, * alphapow, * r; int gstab, astab, bstab, use_stab; #if FLINT_WANT_ASSERT fmpz_mod_poly_t leadA, leadB; #endif fmpz_init(alpha); fmpz_init(temp); fmpz_init(gammaevalp); fmpz_init(gammaevalm); #if FLINT_WANT_ASSERT fmpz_mod_poly_init(leadA, ctx); fmpz_mod_poly_init(leadB, ctx); fmpz_mod_poly_set(leadA, A->coeffs + 0, ctx); fmpz_mod_poly_set(leadB, B->coeffs + 0, ctx); #endif fmpz_mod_poly_stack_fit_request(St_poly, 19); cA = fmpz_mod_poly_stack_take_top(St_poly); cB = fmpz_mod_poly_stack_take_top(St_poly); cG = fmpz_mod_poly_stack_take_top(St_poly); cAbar = fmpz_mod_poly_stack_take_top(St_poly); cBbar = fmpz_mod_poly_stack_take_top(St_poly); gamma = fmpz_mod_poly_stack_take_top(St_poly); Aevalp = fmpz_mod_poly_stack_take_top(St_poly); Bevalp = fmpz_mod_poly_stack_take_top(St_poly); Gevalp = fmpz_mod_poly_stack_take_top(St_poly); Abarevalp = fmpz_mod_poly_stack_take_top(St_poly); Bbarevalp = fmpz_mod_poly_stack_take_top(St_poly); Aevalm = fmpz_mod_poly_stack_take_top(St_poly); Bevalm = fmpz_mod_poly_stack_take_top(St_poly); Gevalm = fmpz_mod_poly_stack_take_top(St_poly); Abarevalm = fmpz_mod_poly_stack_take_top(St_poly); Bbarevalm = fmpz_mod_poly_stack_take_top(St_poly); r = fmpz_mod_poly_stack_take_top(St_poly); alphapow = fmpz_mod_poly_stack_take_top(St_poly); modulus = fmpz_mod_poly_stack_take_top(St_poly); fmpz_mod_polyun_stack_fit_request(St_polyun, 1); T = fmpz_mod_polyun_stack_take_top(St_polyun); _fmpz_mod_poly_vec_remove_content(cA, A->coeffs, A->length, ctx); _fmpz_mod_poly_vec_remove_content(cB, B->coeffs, B->length, ctx); _fmpz_mod_poly_gcd_cofactors(cG, cAbar, cBbar, cA, cB, ctx, r); fmpz_mod_poly_gcd(gamma, A->coeffs + 0, B->coeffs + 0, ctx); ldegA = _fmpz_mod_poly_vec_max_degree(A->coeffs, A->length, ctx); ldegB = _fmpz_mod_poly_vec_max_degree(B->coeffs, B->length, ctx); deggamma = fmpz_mod_poly_degree(gamma, ctx); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); fmpz_mod_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1), ctx); fmpz_mod_poly_one(modulus, ctx); use_stab = 1; gstab = bstab = astab = 0; fmpz_fdiv_q_2exp(alpha, fmpz_mod_ctx_modulus(ctx), 1); choose_prime: fmpz_sub_ui(alpha, alpha, 1); if (fmpz_sgn(alpha) <= 0) { success = 0; goto cleanup; } FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; fmpz_one(alphapow->coeffs + 0); fmpz_set(alphapow->coeffs + 1, alpha); /* make sure evaluation point does not kill both lc(A) and lc(B) */ fmpz_mod_poly_eval2_pow(gammaevalp, gammaevalm, gamma, alphapow, ctx); if (fmpz_is_zero(gammaevalp) || fmpz_is_zero(gammaevalm)) { goto choose_prime; } /* evaluation point should kill neither A nor B */ fmpz_mod_polyu1n_interp_reduce_2sm_poly(Aevalp, Aevalm, A, alphapow, ctx); fmpz_mod_polyu1n_interp_reduce_2sm_poly(Bevalp, Bevalm, B, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); if (use_stab && gstab) { slong Gdeg; fmpz_mod_polyu1n_interp_reduce_2sm_poly(Gevalp, Gevalm, G, alphapow, ctx); Gdeg = G->exps[0]; success = 1; success = success && _fmpz_mod_poly_degree(Gevalp) == Gdeg; success = success && _fmpz_mod_poly_degree(Gevalm) == Gdeg; success = success && fmpz_equal(Gevalp->coeffs + Gdeg, gammaevalp); success = success && fmpz_equal(Gevalm->coeffs + Gdeg, gammaevalm); fmpz_mod_poly_divrem(Abarevalp, r, Aevalp, Gevalp, ctx); success = success && (r->length == 0); fmpz_mod_poly_divrem(Abarevalm, r, Aevalm, Gevalm, ctx); success = success && (r->length == 0); fmpz_mod_poly_divrem(Bbarevalp, r, Bevalp, Gevalp, ctx); success = success && (r->length == 0); fmpz_mod_poly_divrem(Bbarevalm, r, Bevalm, Gevalm, ctx); success = success && (r->length == 0); if (!success) { use_stab = 0; fmpz_mod_poly_one(modulus, ctx); goto choose_prime; } fmpz_mod_poly_scalar_mul_fmpz(Abarevalp, Abarevalp, gammaevalp, ctx); fmpz_mod_poly_scalar_mul_fmpz(Abarevalm, Abarevalm, gammaevalm, ctx); fmpz_mod_poly_scalar_mul_fmpz(Bbarevalp, Bbarevalp, gammaevalp, ctx); fmpz_mod_poly_scalar_mul_fmpz(Bbarevalm, Bbarevalm, gammaevalm, ctx); } else { _fmpz_mod_poly_gcd_cofactors(Gevalp, Abarevalp, Bbarevalp, Aevalp, Bevalp, ctx, r); _fmpz_mod_poly_gcd_cofactors(Gevalm, Abarevalm, Bbarevalm, Aevalm, Bevalm, ctx, r); } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); if (_fmpz_mod_poly_degree(Gevalp) == 0 || _fmpz_mod_poly_degree(Gevalm) == 0) { fmpz_mod_polyun_one(G, ctx); fmpz_mod_polyun_swap(Abar, A); fmpz_mod_polyun_swap(Bbar, B); goto successful_put_content; } if (_fmpz_mod_poly_degree(Gevalp) != _fmpz_mod_poly_degree(Gevalm)) { goto choose_prime; } if (_fmpz_mod_poly_degree(modulus) > 0) { FLINT_ASSERT(G->length > 0); if (_fmpz_mod_poly_degree(Gevalp) > G->exps[0]) { goto choose_prime; } else if (_fmpz_mod_poly_degree(Gevalp) < G->exps[0]) { fmpz_mod_poly_one(modulus, ctx); } } fmpz_mod_poly_scalar_mul_fmpz(Gevalp, Gevalp, gammaevalp, ctx); fmpz_mod_poly_scalar_mul_fmpz(Gevalm, Gevalm, gammaevalm, ctx); if (fmpz_mod_poly_degree(modulus, ctx) > 0) { fmpz_mod_poly_evaluate_fmpz(temp, modulus, alpha, ctx); fmpz_mod_mul(temp, temp, alpha, ctx); fmpz_mod_add(temp, temp, temp, ctx); fmpz_mod_poly_scalar_div_fmpz(modulus, modulus, temp, ctx); gstab = gstab || !fmpz_mod_polyu1n_interp_crt_2sm_poly(&ldegG, G, T, Gevalp, Gevalm, modulus, alphapow, ctx); fmpz_mod_polyu1n_interp_crt_2sm_poly(&ldegAbar, Abar, T, Abarevalp, Abarevalm, modulus, alphapow, ctx); fmpz_mod_polyu1n_interp_crt_2sm_poly(&ldegBbar, Bbar, T, Bbarevalp, Bbarevalm, modulus, alphapow, ctx); } else { fmpz_mod_polyu1n_interp_lift_2sm_poly(&ldegG, G, Gevalp, Gevalm, alpha, ctx); fmpz_mod_polyu1n_interp_lift_2sm_poly(&ldegAbar, Abar, Abarevalp, Abarevalm, alpha, ctx); fmpz_mod_polyu1n_interp_lift_2sm_poly(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, alpha, ctx); gstab = astab = bstab = 0; } fmpz_mod_mul(temp, alpha, alpha, ctx); fmpz_mod_neg(temp, temp, ctx); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 2, temp, ctx); if (fmpz_mod_poly_degree(modulus, ctx) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if (deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar) { goto successful; } fmpz_mod_poly_one(modulus, ctx); goto choose_prime; successful: _fmpz_mod_poly_vec_remove_content(r, G->coeffs, G->length, ctx); _fmpz_mod_poly_vec_divexact_poly(Abar->coeffs, Abar->length, G->coeffs + 0, ctx); _fmpz_mod_poly_vec_divexact_poly(Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx); successful_put_content: _fmpz_mod_poly_vec_mul_poly(G->coeffs, G->length, cG, ctx); _fmpz_mod_poly_vec_mul_poly(Abar->coeffs, Abar->length, cAbar, ctx); _fmpz_mod_poly_vec_mul_poly(Bbar->coeffs, Bbar->length, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { FLINT_ASSERT(fmpz_is_one(fmpz_mod_poly_lead(G->coeffs + 0, ctx))); fmpz_mod_poly_mul(modulus, G->coeffs + 0, Abar->coeffs + 0, ctx); FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadA, ctx)); fmpz_mod_poly_mul(modulus, G->coeffs + 0, Bbar->coeffs + 0, ctx); FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadB, ctx)); } fmpz_mod_poly_clear(leadA, ctx); fmpz_mod_poly_clear(leadB, ctx); #endif fmpz_mod_poly_stack_give_back(St_poly, 19); fmpz_mod_polyun_stack_give_back(St_polyun, 1); fmpz_clear(alpha); fmpz_clear(temp); fmpz_clear(gammaevalp); fmpz_clear(gammaevalm); return success; } static void fmpz_mod_mpolyn_set_polyun_swap( fmpz_mod_mpolyn_t A, fmpz_mod_polyun_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N, off, shift; flint_bitcnt_t bits = A->bits; N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo); fmpz_mod_mpolyn_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { mpoly_monomial_zero(A->exps + N*i, N); (A->exps + N*i)[off] = B->exps[i] << shift; fmpz_mod_poly_swap(A->coeffs + i, B->coeffs + i, ctx->ffinfo); } A->length = B->length; } static void fmpz_mod_mpolyn_get_polyun_swap( fmpz_mod_polyun_t B, fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N, off, shift; flint_bitcnt_t bits = A->bits; N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo); fmpz_mod_polyun_fit_length(B, A->length, ctx->ffinfo); for (i = 0; i < A->length; i++) { B->exps[i] = (A->exps + N*i)[off] >> shift; fmpz_mod_poly_swap(B->coeffs + i, A->coeffs + i, ctx->ffinfo); } B->length = A->length; } int fmpz_mod_mpolyn_gcd_brown_smprime( fmpz_mod_mpolyn_t G, fmpz_mod_mpolyn_t Abar, fmpz_mod_mpolyn_t Bbar, fmpz_mod_mpolyn_t A, fmpz_mod_mpolyn_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, fmpz_mod_poly_polyun_mpolyn_stack_t St) { int success, changed; slong bound, upper_limit; slong offset, shift; fmpz_t alpha, temp, gammaevalp, gammaevalm; fmpz_mod_mpolyn_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp; fmpz_mod_mpolyn_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm; fmpz_mod_mpolyn_struct * T1, * T2; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; fmpz_mod_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma; fmpz_mod_poly_struct * modulus, * alphapow, * t1; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); #if FLINT_WANT_ASSERT fmpz_mod_mpolyn_t Aorg, Borg; fmpz_mod_poly_t leadA, leadB; #endif FLINT_ASSERT(bits == St->mpolyn_stack->bits); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == G->bits); FLINT_ASSERT(bits == Abar->bits); FLINT_ASSERT(bits == Bbar->bits); FLINT_ASSERT(var > 0); if (var == 1) { fmpz_mod_polyun_struct * mA, * mB, * mG, * mAbar, * mBbar; fmpz_mod_polyun_stack_fit_request(St->polyun_stack, 5); mA = fmpz_mod_polyun_stack_take_top(St->polyun_stack); mB = fmpz_mod_polyun_stack_take_top(St->polyun_stack); mG = fmpz_mod_polyun_stack_take_top(St->polyun_stack); mAbar = fmpz_mod_polyun_stack_take_top(St->polyun_stack); mBbar = fmpz_mod_polyun_stack_take_top(St->polyun_stack); fmpz_mod_mpolyn_get_polyun_swap(mA, A, ctx); fmpz_mod_mpolyn_get_polyun_swap(mB, B, ctx); success = fmpz_mod_polyu1n_gcd_brown_smprime(mG, mAbar, mBbar, mA, mB, ctx->ffinfo, St->poly_stack, St->polyun_stack); fmpz_mod_mpolyn_set_polyun_swap(G, mG, ctx); fmpz_mod_mpolyn_set_polyun_swap(Abar, mAbar, ctx); fmpz_mod_mpolyn_set_polyun_swap(Bbar, mBbar, ctx); fmpz_mod_polyun_stack_give_back(St->polyun_stack, 5); return success; } mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, G->bits, ctx->minfo); #if FLINT_WANT_ASSERT fmpz_mod_poly_init(leadA, ctx->ffinfo); fmpz_mod_poly_init(leadB, ctx->ffinfo); fmpz_mod_poly_set(leadA, A->coeffs + 0, ctx->ffinfo); fmpz_mod_poly_set(leadB, B->coeffs + 0, ctx->ffinfo); fmpz_mod_mpolyn_init(Aorg, bits, ctx); fmpz_mod_mpolyn_init(Borg, bits, ctx); fmpz_mod_mpolyn_set(Aorg, A, ctx); fmpz_mod_mpolyn_set(Borg, B, ctx); #endif fmpz_init(alpha); fmpz_init(temp); fmpz_init(gammaevalp); fmpz_init(gammaevalm); fmpz_mod_poly_stack_fit_request(St->poly_stack, 9); cA = fmpz_mod_poly_stack_take_top(St->poly_stack); cB = fmpz_mod_poly_stack_take_top(St->poly_stack); cG = fmpz_mod_poly_stack_take_top(St->poly_stack); cAbar = fmpz_mod_poly_stack_take_top(St->poly_stack); cBbar = fmpz_mod_poly_stack_take_top(St->poly_stack); gamma = fmpz_mod_poly_stack_take_top(St->poly_stack); alphapow = fmpz_mod_poly_stack_take_top(St->poly_stack); modulus = fmpz_mod_poly_stack_take_top(St->poly_stack); t1 = fmpz_mod_poly_stack_take_top(St->poly_stack); fmpz_mod_mpolyn_stack_fit_request(St->mpolyn_stack, 12, ctx); Aevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Bevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Gevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Abarevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Bbarevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Aevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Bevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Gevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Abarevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); Bbarevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); T1 = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); T2 = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack); _fmpz_mod_poly_vec_remove_content(cA, A->coeffs, A->length, ctx->ffinfo); _fmpz_mod_poly_vec_remove_content(cB, B->coeffs, B->length, ctx->ffinfo); _fmpz_mod_poly_gcd_cofactors(cG, cAbar, cBbar, cA, cB, ctx->ffinfo, t1); fmpz_mod_poly_gcd(gamma, A->coeffs + 0, B->coeffs + 0, ctx->ffinfo); ldegA = fmpz_mod_mpolyn_lastdeg(A, ctx); ldegB = fmpz_mod_mpolyn_lastdeg(B, ctx); deggamma = fmpz_mod_poly_degree(gamma, ctx->ffinfo); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); upper_limit = mpoly_gcd_info_get_brown_upper_limit(I, var, bound); fmpz_mod_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1), ctx->ffinfo); fmpz_mod_poly_one(modulus, ctx->ffinfo); fmpz_fdiv_q_2exp(alpha, fmpz_mod_ctx_modulus(ctx->ffinfo), 1); choose_prime: fmpz_sub_ui(alpha, alpha, 1); if (fmpz_sgn(alpha) <= 0) { success = 0; goto cleanup; } FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; fmpz_one(alphapow->coeffs + 0); fmpz_set(alphapow->coeffs + 1, alpha); /* make sure evaluation point does not kill both lc(A) and lc(B) */ fmpz_mod_poly_eval2_pow(gammaevalp, gammaevalm, gamma, alphapow, ctx->ffinfo); if (fmpz_is_zero(gammaevalp) || fmpz_is_zero(gammaevalm)) { goto choose_prime; } /* evaluation point should kill neither A nor B */ fmpz_mod_mpolyn_interp_reduce_2sm_mpolyn(Aevalp, Aevalm, A, var, alphapow, ctx); fmpz_mod_mpolyn_interp_reduce_2sm_mpolyn(Bevalp, Bevalm, B, var, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); success = fmpz_mod_mpolyn_gcd_brown_smprime(Gevalp, Abarevalp, Bbarevalp, Aevalp, Bevalp, var - 1, ctx, I, St); success = success && fmpz_mod_mpolyn_gcd_brown_smprime(Gevalm, Abarevalm, Bbarevalm, Aevalm, Bevalm, var - 1, ctx, I, St); if (success == 0) { goto choose_prime; } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); if (fmpz_mod_mpolyn_is_nonzero_fmpz(Gevalp, ctx) || fmpz_mod_mpolyn_is_nonzero_fmpz(Gevalm, ctx)) { fmpz_mod_mpolyn_one(G, ctx); fmpz_mod_mpolyn_swap(Abar, A, ctx); fmpz_mod_mpolyn_swap(Bbar, B, ctx); goto successful_put_content; } if (Gevalp->coeffs[0].length != Gevalm->coeffs[0].length || !mpoly_monomial_equal(Gevalp->exps + N*0, Gevalm->exps + N*0, N)) { goto choose_prime; } /* the Geval have matching degrees */ if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) > 0) { slong k = fmpz_mod_poly_degree(Gevalp->coeffs + 0, ctx->ffinfo); int cmp = mpoly_monomial_cmp_nomask_extra(G->exps + N*0, Gevalp->exps + N*0, N, offset, k << shift); if (cmp < 0) { goto choose_prime; } else if (cmp > 0) { fmpz_mod_poly_one(modulus, ctx->ffinfo); } } /* update interpolants */ fmpz_mod_mpolyn_scalar_mul_fmpz_mod(Gevalp, gammaevalp, ctx); fmpz_mod_mpolyn_scalar_mul_fmpz_mod(Gevalm, gammaevalm, ctx); if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) > 0) { fmpz_mod_poly_evaluate_fmpz(temp, modulus, alpha, ctx->ffinfo); fmpz_mod_mul(temp, temp, alpha, ctx->ffinfo); fmpz_mod_add(temp, temp, temp, ctx->ffinfo); fmpz_mod_poly_scalar_div_fmpz(modulus, modulus, temp, ctx->ffinfo); changed = fmpz_mod_mpolyn_interp_crt_2sm_mpolyn(&ldegG, G, T1, Gevalp, Gevalm, var, modulus, alphapow, ctx); if (!changed && _fmpz_mod_poly_degree(modulus) < upper_limit) { _fmpz_mod_poly_vec_remove_content(t1, G->coeffs, G->length, ctx->ffinfo); if (fmpz_mod_mpolyn_divides(T1, A, G, ctx) && fmpz_mod_mpolyn_divides(T2, B, G, ctx)) { fmpz_mod_mpolyn_swap(Abar, T1, ctx); fmpz_mod_mpolyn_swap(Bbar, T2, ctx); goto successful_fix_lc; } _fmpz_mod_poly_vec_mul_poly(G->coeffs, G->length, t1, ctx->ffinfo); } changed = fmpz_mod_mpolyn_interp_crt_2sm_mpolyn(&ldegAbar, Abar, T1, Abarevalp, Abarevalm, var, modulus, alphapow, ctx); if (!changed && _fmpz_mod_poly_degree(modulus) < upper_limit) { _fmpz_mod_poly_vec_remove_content(t1, Abar->coeffs, Abar->length, ctx->ffinfo); if (fmpz_mod_mpolyn_divides(T1, A, Abar, ctx) && fmpz_mod_mpolyn_divides(T2, B, T1, ctx)) { fmpz_mod_mpolyn_swap(G, T1, ctx); fmpz_mod_mpolyn_swap(Bbar, T2, ctx); goto successful_fix_lc; } _fmpz_mod_poly_vec_mul_poly(Abar->coeffs, Abar->length, t1, ctx->ffinfo); } changed = fmpz_mod_mpolyn_interp_crt_2sm_mpolyn(&ldegBbar, Bbar, T1, Bbarevalp, Bbarevalm, var, modulus, alphapow, ctx); if (!changed && _fmpz_mod_poly_degree(modulus) < upper_limit) { _fmpz_mod_poly_vec_remove_content(t1, Bbar->coeffs, Bbar->length, ctx->ffinfo); if (fmpz_mod_mpolyn_divides(T1, B, Bbar, ctx) && fmpz_mod_mpolyn_divides(T2, A, T1, ctx)) { fmpz_mod_mpolyn_swap(G, T1, ctx); fmpz_mod_mpolyn_swap(Abar, T2, ctx); goto successful_fix_lc; } _fmpz_mod_poly_vec_mul_poly(Bbar->coeffs, Bbar->length, t1, ctx->ffinfo); } } else { fmpz_mod_mpolyn_interp_lift_2sm_mpolyn(&ldegG, G, Gevalp, Gevalm, var, alpha, ctx); fmpz_mod_mpolyn_interp_lift_2sm_mpolyn(&ldegAbar, Abar, Abarevalp, Abarevalm, var, alpha, ctx); fmpz_mod_mpolyn_interp_lift_2sm_mpolyn(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, var, alpha, ctx); } fmpz_mod_mul(temp, alpha, alpha, ctx->ffinfo); fmpz_mod_neg(temp, temp, ctx->ffinfo); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 2, temp, ctx->ffinfo); if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if (deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar) { goto successful; } fmpz_mod_poly_one(modulus, ctx->ffinfo); goto choose_prime; successful_fix_lc: fmpz_set(temp, fmpz_mod_poly_lead(G->coeffs + 0, ctx->ffinfo)); if (fmpz_is_one(temp)) goto successful_put_content; _fmpz_mod_poly_vec_mul_fmpz_mod(Abar->coeffs, Abar->length, temp, ctx->ffinfo); _fmpz_mod_poly_vec_mul_fmpz_mod(Bbar->coeffs, Bbar->length, temp, ctx->ffinfo); fmpz_mod_inv(temp, temp, ctx->ffinfo); _fmpz_mod_poly_vec_mul_fmpz_mod(G->coeffs, G->length, temp, ctx->ffinfo); goto successful_put_content; successful: _fmpz_mod_poly_vec_remove_content(t1, G->coeffs, G->length, ctx->ffinfo); _fmpz_mod_poly_vec_divexact_poly(Abar->coeffs, Abar->length, G->coeffs + 0, ctx->ffinfo); _fmpz_mod_poly_vec_divexact_poly(Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx->ffinfo); successful_put_content: _fmpz_mod_poly_vec_mul_poly(G->coeffs, G->length, cG, ctx->ffinfo); _fmpz_mod_poly_vec_mul_poly(Abar->coeffs, Abar->length, cAbar, ctx->ffinfo); _fmpz_mod_poly_vec_mul_poly(Bbar->coeffs, Bbar->length, cBbar, ctx->ffinfo); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { FLINT_ASSERT(fmpz_is_one(fmpz_mod_mpolyn_leadcoeff(G))); fmpz_mod_poly_mul(modulus, G->coeffs + 0, Abar->coeffs + 0, ctx->ffinfo); FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadA, ctx->ffinfo)); fmpz_mod_poly_mul(modulus, G->coeffs + 0, Bbar->coeffs + 0, ctx->ffinfo); FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadB, ctx->ffinfo)); } fmpz_mod_poly_clear(leadA, ctx->ffinfo); fmpz_mod_poly_clear(leadB, ctx->ffinfo); fmpz_mod_mpolyn_clear(Aorg, ctx); fmpz_mod_mpolyn_clear(Borg, ctx); #endif fmpz_clear(alpha); fmpz_clear(temp); fmpz_clear(gammaevalp); fmpz_clear(gammaevalm); fmpz_mod_poly_stack_give_back(St->poly_stack, 9); fmpz_mod_mpolyn_stack_give_back(St->mpolyn_stack, 12); FLINT_ASSERT(success || fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 60); return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/gcd_hensel.c000066400000000000000000000302521461254215100222540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpolyl_gcd_hensel_smprime( fmpz_mod_mpoly_t G, slong Gdeg, /* upperbound on deg_X(G) */ fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success, alphas_tries_remaining, gamma_is_one; const slong n = ctx->minfo->nvars - 1; slong i, k; flint_bitcnt_t bits = A->bits; fmpz * alphas, * prev_alphas; fmpz_t q, mu1, mu2; fmpz_mod_mpoly_struct * Aevals, * Bevals, * Hevals; fmpz_mod_mpoly_struct * H; /* points to A, B, or Hevals + n */ fmpz_mod_mpoly_struct * Glcs, * Hlcs; fmpz_mod_mpoly_struct Hfac[2], Htfac[2]; slong * Hdegs; slong Adegx, Bdegx, gdegx; fmpz_mod_mpoly_t t1, t2, g, abar, bbar, hbar; flint_rand_t state; FLINT_ASSERT(n > 0); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); flint_randinit(state); Hdegs = FLINT_ARRAY_ALLOC(n + 1, slong); Glcs = FLINT_ARRAY_ALLOC(3*(n + 1), fmpz_mod_mpoly_struct); Hlcs = Glcs + (n + 1); Hevals = Hlcs + (n + 1); for (i = 0; i < n + 1; i++) { fmpz_mod_mpoly_init(Glcs + i, ctx); fmpz_mod_mpoly_init(Hlcs + i, ctx); fmpz_mod_mpoly_init(Hevals + i, ctx); } alphas = _fmpz_vec_init(2*n); prev_alphas = alphas + n; Aevals = FLINT_ARRAY_ALLOC(2*(n + 1), fmpz_mod_mpoly_struct); Bevals = Aevals + (n + 1); for (i = 0; i < n; i++) { fmpz_mod_mpoly_init(Aevals + i, ctx); fmpz_mod_mpoly_init(Bevals + i, ctx); } fmpz_init(q); fmpz_init(mu1); fmpz_init(mu2); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(abar, ctx); fmpz_mod_mpoly_init(bbar, ctx); fmpz_mod_mpoly_init(hbar, ctx); fmpz_mod_mpoly_init(Hfac + 0, ctx); fmpz_mod_mpoly_init(Hfac + 1, ctx); fmpz_mod_mpoly_init(Htfac + 0, ctx); fmpz_mod_mpoly_init(Htfac + 1, ctx); /* init done */ alphas_tries_remaining = 10; /* try all zeros first */ for (i = 0; i < n; i++) { /* no previous at this point */ fmpz_set(prev_alphas + i, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_zero(alphas + i); } goto got_alpha; next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) { do { fmpz_mod_rand(alphas + i, state, ctx->ffinfo); } while (fmpz_equal(alphas + i, prev_alphas + i)); } got_alpha: /* ensure deg_X do not drop under evaluation */ Adegx = fmpz_mod_mpoly_degree_si(A, 0, ctx); Bdegx = fmpz_mod_mpoly_degree_si(B, 0, ctx); for (i = n - 1; i >= 0; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alphas + i, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(Bevals + i, i == n - 1 ? B : Bevals + i + 1, i + 1, alphas + i, ctx); if (Adegx != fmpz_mod_mpoly_degree_si(Aevals + i, 0, ctx) || Bdegx != fmpz_mod_mpoly_degree_si(Bevals + i, 0, ctx)) { goto next_alpha; } } /* univariate gcd */ success = fmpz_mod_mpoly_gcd_cofactors(g, abar, bbar, Aevals + 0, Bevals + 0, ctx) && fmpz_mod_mpoly_gcd(t1, g, abar, ctx) && fmpz_mod_mpoly_gcd(t2, g, bbar, ctx); if (!success) goto cleanup; gdegx = fmpz_mod_mpoly_degree_si(g, 0, ctx); if (gdegx == 0) { /* G is trivial */ fmpz_mod_mpoly_set(Abar, A, ctx); fmpz_mod_mpoly_set(Bbar, B, ctx); fmpz_mod_mpoly_one(G, ctx); success = 1; goto cleanup; } else if (gdegx > Gdeg) { goto next_alpha; } else if (gdegx < Gdeg) { Gdeg = gdegx; for (i = 0; i < n; i++) fmpz_set(prev_alphas + i, alphas + i); goto next_alpha; } /* the degbound gdegx (== Gdeg) has at least two witnesses now */ if (gdegx == Adegx) { if (fmpz_mod_mpoly_divides(Bbar, B, A, ctx)) { fmpz_mod_mpoly_set(G, A, ctx); fmpz_mod_mpoly_one(Abar, ctx); success = 1; goto cleanup; } goto next_alpha; } else if (gdegx == Bdegx) { if (fmpz_mod_mpoly_divides(Abar, A, B, ctx)) { fmpz_mod_mpoly_set(G, B, ctx); fmpz_mod_mpoly_one(Bbar, ctx); success = 1; goto cleanup; } goto next_alpha; } FLINT_ASSERT(0 < gdegx && gdegx < FLINT_MIN(Adegx, Bdegx)); /* set Hlcs[n], Glcs[n] (gamma), H, and Hevals */ if (fmpz_mod_mpoly_is_one(t1, ctx)) { fmpz_one(mu1); fmpz_zero(mu2); fmpz_mod_mpoly_swap(hbar, abar, ctx); fmpz_mod_mpolyl_lead_coeff(Hlcs + n, A, 1, ctx); fmpz_mod_mpolyl_lead_coeff(t2, B, 1, ctx); success = fmpz_mod_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fmpz_mod_mpoly_struct *) A; gamma_is_one = fmpz_mod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fmpz_mod_mpoly_swap(Hevals + i, Aevals + i, ctx); } else if (fmpz_mod_mpoly_is_one(t2, ctx)) { fmpz_zero(mu1); fmpz_one(mu2); fmpz_mod_mpoly_swap(hbar, bbar, ctx); fmpz_mod_mpolyl_lead_coeff(Hlcs + n, B, 1, ctx); fmpz_mod_mpolyl_lead_coeff(t2, A, 1, ctx); success = fmpz_mod_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fmpz_mod_mpoly_struct *) B; gamma_is_one = fmpz_mod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fmpz_mod_mpoly_swap(Hevals + i, Bevals + i, ctx); } else { int mu_tries_remaining = 10; next_mu: if (--mu_tries_remaining < 0) { success = 0; goto cleanup; } fmpz_one(mu1); fmpz_mod_rand_not_zero(mu2, state, ctx->ffinfo); fmpz_mod_mpoly_scalar_addmul_fmpz(hbar, abar, bbar, mu2, ctx); /* make sure the linear combo did not drop degree */ if (fmpz_mod_mpoly_degree_si(hbar, 0, ctx) != FLINT_MAX(Adegx, Bdegx) - gdegx) goto next_mu; /* make sure the linear combo is prime to g */ success = fmpz_mod_mpoly_gcd(t1, hbar, g, ctx); if (!success) goto cleanup; if (!fmpz_mod_mpoly_is_one(t1, ctx)) goto next_mu; fmpz_mod_mpolyl_lead_coeff(t1, A, 1, ctx); fmpz_mod_mpolyl_lead_coeff(t2, B, 1, ctx); success = fmpz_mod_mpoly_gcd(Glcs + n, t1, t2, ctx); if (!success) goto cleanup; H = Hevals + n; fmpz_mod_mpoly_scalar_addmul_fmpz(H, A, B, mu2, ctx); fmpz_mod_mpolyl_lead_coeff(Hlcs + n, H, 1, ctx); gamma_is_one = fmpz_mod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fmpz_mod_mpoly_scalar_addmul_fmpz(Hevals + i, Aevals + i, Bevals + i, mu2, ctx); } if (!gamma_is_one) { fmpz_mod_mpoly_mul(Hevals + n, H, Glcs + n, ctx); H = Hevals + n; for (i = n - 1; i >= 0; i--) fmpz_mod_mpoly_evaluate_one_fmpz(Hevals + i, Hevals + i + 1, i + 1, alphas + i, ctx); } success = H->bits <= FLINT_BITS || fmpz_mod_mpoly_repack_bits_inplace(H, FLINT_BITS, ctx); if (!success) goto cleanup; /* the evals should all fit in H->bits */ for (i = 0; i < n; i++) fmpz_mod_mpoly_repack_bits_inplace(Hevals + i, H->bits, ctx); fmpz_mod_mpoly_degrees_si(Hdegs, H, ctx); /* computed evaluated leading coeffs */ for (i = n - 1; i >= 0; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(Glcs + i, Glcs + i + 1, i + 1, alphas + i, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(Hlcs + i, Hlcs + i + 1, i + 1, alphas + i, ctx); /* evaluation could have killed gamma */ if (fmpz_mod_mpoly_is_zero(Glcs + i, ctx) || fmpz_mod_mpoly_is_zero(Hlcs + i, ctx)) { goto next_alpha; } } /* make the leading coefficients match Glcs[0], Hlcs[0] */ FLINT_ASSERT(fmpz_mod_mpoly_is_fmpz(Glcs + 0, ctx) && Glcs[0].length == 1); FLINT_ASSERT(fmpz_mod_mpoly_is_fmpz(Hlcs + 0, ctx) && Hlcs[0].length == 1); fmpz_mod_inv(q, g->coeffs + 0, ctx->ffinfo); fmpz_mod_mul(q, q, Glcs[0].coeffs + 0, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(Hfac + 0, g, q, ctx); fmpz_mod_inv(q, hbar->coeffs + 0, ctx->ffinfo); fmpz_mod_mul(q, q, Hlcs[0].coeffs + 0, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(Hfac + 1, hbar, q, ctx); for (k = 1; k <= n; k++) { _fmpz_mod_mpoly_set_lead0(Htfac + 0, Hfac + 0, Glcs + k, ctx); _fmpz_mod_mpoly_set_lead0(Htfac + 1, Hfac + 1, Hlcs + k, ctx); success = fmpz_mod_mpoly_hlift(k, Htfac, 2, alphas, k < n ? Hevals + k : H, Hdegs, ctx); if (!success) goto next_alpha; fmpz_mod_mpoly_swap(Hfac + 0, Htfac + 0, ctx); fmpz_mod_mpoly_swap(Hfac + 1, Htfac + 1, ctx); } success = fmpz_mod_mpolyl_content(t1, Hfac + 0, 1, ctx); if (!success) goto cleanup; success = fmpz_mod_mpoly_divides(G, Hfac + 0, t1, ctx); FLINT_ASSERT(success); if (fmpz_is_zero(mu2)) { FLINT_ASSERT(fmpz_is_one(mu1)); /* the division by t1 should succeed, but let's be careful */ fmpz_mod_mpolyl_lead_coeff(t1, G, 1, ctx); success = fmpz_mod_mpoly_divides(Abar, Hfac + 1, t1, ctx) && fmpz_mod_mpoly_divides(Bbar, B, G, ctx); } else if (fmpz_is_zero(mu1)) { FLINT_ASSERT(fmpz_is_one(mu2)); /* ditto */ fmpz_mod_mpolyl_lead_coeff(t1, G, 1, ctx); success = fmpz_mod_mpoly_divides(Bbar, Hfac + 1, t1, ctx) && fmpz_mod_mpoly_divides(Abar, A, G, ctx); } else { FLINT_ASSERT(fmpz_is_one(mu1)); success = fmpz_mod_mpoly_divides(Abar, A, G, ctx) && fmpz_mod_mpoly_divides(Bbar, B, G, ctx); } if (!success) goto next_alpha; success = 1; cleanup: flint_randclear(state); flint_free(Hdegs); for (i = 0; i < n + 1; i++) { fmpz_mod_mpoly_clear(Glcs + i, ctx); fmpz_mod_mpoly_clear(Hlcs + i, ctx); fmpz_mod_mpoly_clear(Hevals + i, ctx); } flint_free(Glcs); _fmpz_vec_clear(alphas, 2*n); for (i = 0; i < n; i++) { fmpz_mod_mpoly_clear(Aevals + i, ctx); fmpz_mod_mpoly_clear(Bevals + i, ctx); } flint_free(Aevals); fmpz_clear(q); fmpz_clear(mu1); fmpz_clear(mu2); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(abar, ctx); fmpz_mod_mpoly_clear(bbar, ctx); fmpz_mod_mpoly_clear(hbar, ctx); fmpz_mod_mpoly_clear(Hfac + 0, ctx); fmpz_mod_mpoly_clear(Hfac + 1, ctx); fmpz_mod_mpoly_clear(Htfac + 0, ctx); fmpz_mod_mpoly_clear(Htfac + 1, ctx); if (success) { fmpz_mod_mpoly_repack_bits_inplace(G, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(Abar, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(Bbar, bits, ctx); FLINT_ASSERT(G->length > 0); FLINT_ASSERT(Abar->length > 0); FLINT_ASSERT(Bbar->length > 0); } return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/gcd_zippel.c000066400000000000000000000665051461254215100223130ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" #include "n_poly.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" static void fmpz_mod_mpoly_monomial_evals1( fmpz_mod_polyun_t E, const fmpz_mod_mpoly_t A, const ulong * Amarks, slong Amarkslen, fmpz_mod_poly_struct * betas, slong m, const fmpz_mod_mpoly_ctx_t ctx) /* temp space */ { mpoly1_monomial_evals_fmpz_mod(E, A->exps, A->bits, Amarks, Amarkslen, betas, m, ctx->minfo, ctx->ffinfo); } static void fmpz_mod_polyu1n_zip_eval_cur_inc_coeff( fmpz_mod_poly_t E, fmpz_mod_polyun_t Acur, const fmpz_mod_polyun_t Ainc, const fmpz_mod_polyun_t Acoeff, const fmpz_mod_ctx_t ctx) { slong i; fmpz_t c; FLINT_ASSERT(Acur->length > 0); FLINT_ASSERT(Acur->length == Ainc->length); FLINT_ASSERT(Acur->length == Acoeff->length); fmpz_init(c); fmpz_mod_poly_zero(E, ctx); for (i = 0; i < Acur->length; i++) { slong this_len = Acur->coeffs[i].length; FLINT_ASSERT(this_len == Ainc->coeffs[i].length); FLINT_ASSERT(this_len == Acoeff->coeffs[i].length); _fmpz_mod_zip_eval_step(c, Acur->coeffs[i].coeffs, Ainc->coeffs[i].coeffs, Acoeff->coeffs[i].coeffs, this_len, ctx); fmpz_mod_poly_set_coeff_fmpz(E, Acur->exps[i], c, ctx); } fmpz_clear(c); } static int fmpz_mod_poly_add_zip_must_match( fmpz_mod_polyun_t Z, fmpz_mod_poly_t A, slong cur_length) { slong i, ai; slong Alen = A->length; ulong * Zexps = Z->exps; fmpz_mod_poly_struct * Zcoeffs = Z->coeffs; fmpz * Acoeffs = A->coeffs; ai = Alen - 1; for (i = 0; i < Z->length; i++) { if (ai >= 0 && Zexps[i] == ai) { /* Z present, A present */ fmpz_set(Zcoeffs[i].coeffs + cur_length, Acoeffs + ai); Zcoeffs[i].length = cur_length + 1; do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs + ai)); } else if (ai < 0 || Zexps[i] > ai) { /* Z present, A missing */ fmpz_zero(Zcoeffs[i].coeffs + cur_length); Zcoeffs[i].length = cur_length + 1; } else { /* Z missing, A present */ return 0; } } return ai < 0; } static fmpz * fmpz_mod_mat_row_ref(fmpz_mod_mat_t M, slong i) { return M->rows[i]; } /* Try to set G to the gcd of A and B given the form f of G. f = sum_i X^i sum_j c_ij x^e_j images are formed from evaluation at x = alpha^(k+1), 0 <= k < l Assume all image gcds have the same degree and are sum_i X^i g_ik, 0 <= k < l Then, for each 0 <= k < l there is a scalar factor s_k such that sum_j c_ij alpha^((k+1)e_j) = s_k g_ik for 0 <= i <= degree(gcd) */ int fmpz_mod_mpolyl_gcds_zippel( fmpz_mod_mpoly_t G, const ulong * Gmarks, slong Gmarkslen, fmpz_mod_mpoly_t A, fmpz_mod_mpoly_t B, slong *perm, slong l, slong var, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong * Gdegbound, n_poly_t Amarks, n_poly_t Bmarks) { int success; int betas_tries_left, underdetermined_left, exceeded_left; slong i, s, S, n, cur_zip_image; slong Adeg, Bdeg, Gdeg; flint_bitcnt_t bits = A->bits; fmpz_mod_poly_t Aev, Bev, Gev; fmpz_mod_polyun_t Aeh_inc, Aeh_cur, Aeh_coeff_mock; fmpz_mod_polyun_t Beh_inc, Beh_cur, Beh_coeff_mock; fmpz_mod_polyun_t HG, MG, ZG; fmpz * betas; fmpz_mod_poly_struct * beta_caches; fmpz_mod_mat_struct * ML; fmpz_mod_mat_t MF, Msol, MFtemp, Mwindow; FLINT_ASSERT(1 < var && var < ctx->minfo->nvars); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(G->length > 0); FLINT_ASSERT(Gmarkslen > 0); FLINT_ASSERT(*Gdegbound == mpoly_degree_si(G->exps, G->length, bits, 0, ctx->minfo)); if (Gmarkslen < 2) { fmpz_one(G->coeffs + 0); return Gmarks[1] - Gmarks[0] == 1; } betas = _fmpz_vec_init(var); beta_caches = FLINT_ARRAY_ALLOC(var, fmpz_mod_poly_struct); for (i = 0; i < var; i++) fmpz_mod_poly_init(beta_caches + i, ctx->ffinfo); ML = FLINT_ARRAY_ALLOC(Gmarkslen, fmpz_mod_mat_struct); for (i = 0; i < Gmarkslen; i++) fmpz_mod_mat_init(ML + i, 0, 0, ctx->ffinfo); fmpz_mod_mat_init(MF, 0, l, ctx->ffinfo); fmpz_mod_mat_init(Msol, l, 1, ctx->ffinfo); fmpz_mod_poly_init(Aev, ctx->ffinfo); fmpz_mod_poly_init(Bev, ctx->ffinfo); fmpz_mod_poly_init(Gev, ctx->ffinfo); fmpz_mod_polyun_init(Aeh_inc, ctx->ffinfo); fmpz_mod_polyun_init(Aeh_cur, ctx->ffinfo); fmpz_mod_polyun_init(Beh_inc, ctx->ffinfo); fmpz_mod_polyun_init(Beh_cur, ctx->ffinfo); Aeh_coeff_mock->exps = NULL; Aeh_coeff_mock->coeffs = NULL; Aeh_coeff_mock->length = 0; Aeh_coeff_mock->alloc = 0; Beh_coeff_mock->exps = NULL; Beh_coeff_mock->coeffs = NULL; Beh_coeff_mock->length = 0; Beh_coeff_mock->alloc = 0; fmpz_mod_polyun_init(HG, ctx->ffinfo); fmpz_mod_polyun_init(MG, ctx->ffinfo); fmpz_mod_polyun_init(ZG, ctx->ffinfo); Adeg = fmpz_mod_mpoly_degree_si(A, 0, ctx); Bdeg = fmpz_mod_mpoly_degree_si(B, 0, ctx); mpoly1_fill_marks(&Amarks->coeffs, &Amarks->length, &Amarks->alloc, A->exps, A->length, bits, ctx->minfo); mpoly1_fill_marks(&Bmarks->coeffs, &Bmarks->length, &Bmarks->alloc, B->exps, B->length, bits, ctx->minfo); betas_tries_left = 10; underdetermined_left = 3; exceeded_left = 3; next_betas: if (--betas_tries_left < 0) { success = -1; goto cleanup; } for (i = 1; i < var; i++) { fmpz_mod_rand_not_zero(betas + i, state, ctx->ffinfo); fmpz_mod_pow_cache_start(betas + i, beta_caches + i, ctx->ffinfo); } fmpz_mod_mpoly_monomial_evals1(Aeh_inc, A, Amarks->coeffs, Amarks->length, beta_caches + 1, var, ctx); fmpz_mod_mpoly_monomial_evals1(Beh_inc, B, Bmarks->coeffs, Bmarks->length, beta_caches + 1, var, ctx); fmpz_mod_polyun_set(Aeh_cur, Aeh_inc, ctx->ffinfo); fmpz_mod_polyun_set(Beh_cur, Beh_inc, ctx->ffinfo); fmpz_mod_mpoly_mock_eval_coeff(Aeh_coeff_mock, A, Aeh_inc, ctx); fmpz_mod_mpoly_mock_eval_coeff(Beh_coeff_mock, B, Beh_inc, ctx); fmpz_mod_mpoly_monomial_evals1(HG, G, Gmarks, Gmarkslen, beta_caches + 1, var, ctx); fmpz_mod_polyun_zip_start(ZG, HG, l, ctx->ffinfo); n = fmpz_mod_polyun_product_roots(MG, HG, ctx->ffinfo); FLINT_ASSERT(n <= l); for (cur_zip_image = 0; cur_zip_image < l; cur_zip_image++) { fmpz_mod_polyu1n_zip_eval_cur_inc_coeff(Aev, Aeh_cur, Aeh_inc, Aeh_coeff_mock, ctx->ffinfo); fmpz_mod_polyu1n_zip_eval_cur_inc_coeff(Bev, Beh_cur, Beh_inc, Beh_coeff_mock, ctx->ffinfo); if (_fmpz_mod_poly_degree(Aev) != Adeg) goto next_betas; if (_fmpz_mod_poly_degree(Bev) != Bdeg) goto next_betas; fmpz_mod_poly_gcd(Gev, Aev, Bev, ctx->ffinfo); Gdeg = _fmpz_mod_poly_degree(Gev); if (Gdeg > *Gdegbound) { if (--exceeded_left >= 0) goto next_betas; success = -1; goto cleanup; } if (Gdeg < *Gdegbound) { *Gdegbound = Gdeg; success = 0; goto cleanup; } if (!fmpz_mod_poly_add_zip_must_match(ZG, Gev, cur_zip_image)) goto next_betas; } fmpz_mod_mat_clear(Msol, ctx->ffinfo); fmpz_mod_mat_init(Msol, 1, l, ctx->ffinfo); s = perm[0]; if (Gmarks[s + 1] - Gmarks[s] == 1) { /* monic case */ fmpz * temp = betas; /* use betas[0] for tmp space */ fmpz_one(temp); for (i = 0; i < l; i++) { fmpz_mod_mul(temp, temp, HG->coeffs[s].coeffs + 0, ctx->ffinfo); if (!fmpz_mod_divides(fmpz_mod_mat_entry(Msol, 0, i), temp, ZG->coeffs[s].coeffs + i, ctx->ffinfo)) { goto general_case; } } goto try_it; } general_case: fmpz_mod_mat_clear(Msol, ctx->ffinfo); fmpz_mod_mat_init(Msol, 0, l, ctx->ffinfo); fmpz_mod_mat_clear(MF, ctx->ffinfo); fmpz_mod_mat_init(MF, 0, l, ctx->ffinfo); for (S = 0; S < Gmarkslen; S++) { s = perm[S]; n = Gmarks[s + 1] - Gmarks[s]; FLINT_ASSERT(n <= l); if (fmpz_mod_mat_nrows(ML + s, ctx->ffinfo) != l || fmpz_mod_mat_ncols(ML + s, ctx->ffinfo) != l + n) { fmpz_mod_mat_clear(ML + s, ctx->ffinfo); fmpz_mod_mat_init(ML + s, l, l + n, ctx->ffinfo); } _fmpz_vec_set(fmpz_mod_mat_row_ref(ML + s, 0), HG->coeffs[s].coeffs, n); for (i = 1; i < l; i++) { _fmpz_mod_vec_mul(fmpz_mod_mat_row_ref(ML + s, i), fmpz_mod_mat_row_ref(ML + s, i - 1), HG->coeffs[s].coeffs, n, ctx->ffinfo); } for (i = 0; i < l; i++) { _fmpz_vec_zero(fmpz_mod_mat_row_ref(ML + s, i) + n, l); fmpz_set(fmpz_mod_mat_row_ref(ML + s, i) + n + i, ZG->coeffs[s].coeffs + i); } /* l x (n + l) matrix ML[s] n l | monomial evals 1 | image coeffs 0 | l | ... | on the | | monomial evals l | 0 diagonal | */ fmpz_mod_mat_rref(ML + s, ML + s, ctx->ffinfo); for (i = 0; i < n; i++) if (!fmpz_is_one(fmpz_mod_mat_entry(ML + s, i, i))) goto next_betas; /* delete zero rows from MF, matrix interface makes this fun */ i = fmpz_mod_mat_nrows(MF, ctx->ffinfo); while (i > 1 && _fmpz_vec_is_zero(fmpz_mod_mat_row_ref(MF, i - 1), l)) i--; if (i < fmpz_mod_mat_nrows(MF, ctx->ffinfo)) { fmpz_mod_mat_window_init(Mwindow, MF, 0, 0, i, l, ctx->ffinfo); fmpz_mod_mat_init(MFtemp, i, l, ctx->ffinfo); fmpz_mod_mat_set(MFtemp, Mwindow, ctx->ffinfo); fmpz_mod_mat_swap(MF, MFtemp, ctx->ffinfo); fmpz_mod_mat_clear(MFtemp, ctx->ffinfo); fmpz_mod_mat_window_clear(Mwindow, ctx->ffinfo); } /* appends rows to MF */ fmpz_mod_mat_window_init(Mwindow, ML + s, n, n, l, n + l, ctx->ffinfo); fmpz_mod_mat_init(MFtemp, i + l - n, l, ctx->ffinfo); fmpz_mod_mat_concat_vertical(MFtemp, MF, Mwindow, ctx->ffinfo); fmpz_mod_mat_swap(MF, MFtemp, ctx->ffinfo); fmpz_mod_mat_clear(MFtemp, ctx->ffinfo); fmpz_mod_mat_window_clear(Mwindow, ctx->ffinfo); fmpz_mod_mat_clear(Msol, ctx->ffinfo); fmpz_mod_mat_init_nullspace_tr(Msol, MF, ctx->ffinfo); if (fmpz_mod_mat_nrows(Msol, ctx->ffinfo) < 1) { success = 0; goto cleanup; } if (fmpz_mod_mat_nrows(Msol, ctx->ffinfo) == 1) break; } if (fmpz_mod_mat_nrows(Msol, ctx->ffinfo) != 1) { if (--underdetermined_left >= 0) goto next_betas; success = -1; goto cleanup; } try_it: /* the first row of Msol has the scales */ for (s = 0; s < Gmarkslen; s++) { _fmpz_mod_vec_mul(ZG->coeffs[s].coeffs, ZG->coeffs[s].coeffs, fmpz_mod_mat_row_ref(Msol, 0), l, ctx->ffinfo); } success = fmpz_mod_polyun_zip_solve(G, ZG, HG, MG, ctx); if (success < 0) goto next_betas; cleanup: fmpz_mod_poly_clear(Aev, ctx->ffinfo); fmpz_mod_poly_clear(Bev, ctx->ffinfo); fmpz_mod_poly_clear(Gev, ctx->ffinfo); _fmpz_vec_clear(betas, var); for (i = 0; i < var; i++) fmpz_mod_poly_clear(beta_caches + i, ctx->ffinfo); flint_free(beta_caches); for (i = 0; i < Gmarkslen; i++) fmpz_mod_mat_clear(ML + i, ctx->ffinfo); flint_free(ML); fmpz_mod_mat_clear(MF, ctx->ffinfo); fmpz_mod_mat_clear(Msol, ctx->ffinfo); fmpz_mod_polyun_clear(Aeh_inc, ctx->ffinfo); fmpz_mod_polyun_clear(Aeh_cur, ctx->ffinfo); fmpz_mod_polyun_clear(Beh_inc, ctx->ffinfo); fmpz_mod_polyun_clear(Beh_cur, ctx->ffinfo); flint_free(Aeh_coeff_mock->coeffs); flint_free(Beh_coeff_mock->coeffs); fmpz_mod_polyun_clear(HG, ctx->ffinfo); fmpz_mod_polyun_clear(MG, ctx->ffinfo); fmpz_mod_polyun_clear(ZG, ctx->ffinfo); return success; } static int _do_bivar_or_univar( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, fmpz_mod_mpoly_t A, fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state) { if (var == 1) { int success; fmpz_mod_poly_t c; fmpz_mod_polyun_t Aev, Bev, Gev, Abarev, Bbarev; fmpz_mod_poly_polyun_stack_t St; fmpz_mod_poly_stack_init(St->poly_stack); fmpz_mod_polyun_stack_init(St->polyun_stack); fmpz_mod_polyun_init(Aev, ctx->ffinfo); fmpz_mod_polyun_init(Bev, ctx->ffinfo); fmpz_mod_polyun_init(Gev, ctx->ffinfo); fmpz_mod_polyun_init(Abarev, ctx->ffinfo); fmpz_mod_polyun_init(Bbarev, ctx->ffinfo); fmpz_mod_poly_init(c, ctx->ffinfo); fmpz_mod_mpoly_get_polyu1n(Aev, A, 0, 1, ctx); fmpz_mod_mpoly_get_polyu1n(Bev, B, 0, 1, ctx); success = fmpz_mod_polyu1n_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->ffinfo, St->poly_stack, St->polyun_stack); if (success) { _fmpz_mod_poly_vec_content(c, Gev->coeffs, Gev->length, ctx->ffinfo); success = fmpz_mod_poly_is_one(c, ctx->ffinfo); fmpz_mod_mpoly_set_polyu1n(G, Gev, 0, 1, ctx); } fmpz_mod_poly_clear(c, ctx->ffinfo); fmpz_mod_polyun_clear(Aev, ctx->ffinfo); fmpz_mod_polyun_clear(Bev, ctx->ffinfo); fmpz_mod_polyun_clear(Gev, ctx->ffinfo); fmpz_mod_polyun_clear(Abarev, ctx->ffinfo); fmpz_mod_polyun_clear(Bbarev, ctx->ffinfo); fmpz_mod_poly_stack_clear(St->poly_stack); fmpz_mod_polyun_stack_clear(St->polyun_stack); return success; } else { fmpz_mod_poly_t a, b, c; fmpz_mod_poly_init(a, ctx->ffinfo); fmpz_mod_poly_init(b, ctx->ffinfo); fmpz_mod_poly_init(c, ctx->ffinfo); fmpz_mod_mpoly_get_fmpz_mod_poly(a, A, 0, ctx); fmpz_mod_mpoly_get_fmpz_mod_poly(b, B, 0, ctx); fmpz_mod_poly_gcd(c, a, b, ctx->ffinfo); _fmpz_mod_mpoly_set_fmpz_mod_poly(G, G->bits, c->coeffs, c->length, 0, ctx); fmpz_mod_poly_clear(a, ctx->ffinfo); fmpz_mod_poly_clear(b, ctx->ffinfo); fmpz_mod_poly_clear(c, ctx->ffinfo); return 1; } } /* Assume content_x0(G) = 1, and fail otherwise when var = 1, this is checked explicitly. when var = 2, The possibility of f(x2) | G(x0,x1,x2) for nonconstant f(x2) is ruled out by the explicit check. suppose f(x1,x2) | G(x0,x1,x2) where f is not in Fp[x2] the evaluation point x2 = a2 is chosen so that lc_{x0,x1}(G(x0,x1,x2)) does not vanish at x2 = a2. This means that lc_x1(f(x1, x2)) does not vanish at x2 = a2, and so f(x1, a2) is a nontrivial divisor of G(x0,x1,a2) which would be caught by the recursive call. when var = 3, The possibility of f(x3) | G(x0,x1,x2,x3) for nonconstant f(x3) is ruled out by the explicit check. suppose f(x1,x2,x3) | G(x0,x1,x2,x3) where f is not in Fp[x3] the evaluation point x3 = a3 is chosen so that lc_{x0,x1,X2}(G(x0,x1,x2,X3)) does not vanish at x3 = a3. This means that G(x0, x1, x2, a3) has content that would be caught be the recursive call. ... */ int fmpz_mod_mpolyl_gcdp_zippel( fmpz_mod_mpoly_t G, fmpz_mod_mpoly_t Abar, fmpz_mod_mpoly_t Bbar, fmpz_mod_mpoly_t A, fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state) { flint_bitcnt_t bits = A->bits; slong i, j, N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong Adeg, Bdeg, Alastdeg, Blastdeg, Gdeg; slong bound, Gdegbound, lastdeg, req_zip_images; int success, changed, have_enough; fmpz_t alpha, start_alpha, gammaeval, temp; fmpz_mod_poly_t a, b, c, gamma, modulus, alphapow; fmpz_mod_mpoly_t Ac, Bc, Aeval, Beval, Geval, Abareval, Bbareval; fmpz_mod_mpolyn_t H, T; n_poly_t Amarks, Bmarks, Gmarks; slong * perm = NULL; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (var < 2) return _do_bivar_or_univar(G, Abar, Bbar, A, B, var, ctx, state); fmpz_init(alpha); fmpz_init(start_alpha); fmpz_init(gammaeval); fmpz_init(temp); fmpz_mod_mpoly_init3(Ac, 0, bits, ctx); fmpz_mod_mpoly_init3(Bc, 0, bits, ctx); fmpz_mod_mpoly_init3(Aeval, 0, bits, ctx); fmpz_mod_mpoly_init3(Beval, 0, bits, ctx); fmpz_mod_mpoly_init3(Geval, 0, bits, ctx); fmpz_mod_mpoly_init3(Abareval, 0, bits, ctx); fmpz_mod_mpoly_init3(Bbareval, 0, bits, ctx); fmpz_mod_poly_init(a, ctx->ffinfo); fmpz_mod_poly_init(b, ctx->ffinfo); fmpz_mod_poly_init(c, ctx->ffinfo); fmpz_mod_poly_init(gamma, ctx->ffinfo); fmpz_mod_poly_init(modulus, ctx->ffinfo); fmpz_mod_poly_init2(alphapow, 3, ctx->ffinfo); fmpz_mod_mpolyn_init(H, bits, ctx); fmpz_mod_mpolyn_init(T, bits, ctx); n_poly_init(Amarks); n_poly_init(Bmarks); n_poly_init(Gmarks); fmpz_mod_mpolyl_content(Ac, A, var, ctx); if (!fmpz_mod_mpoly_is_one(Ac, ctx)) { success = fmpz_mod_mpoly_divides(A, A, Ac, ctx); FLINT_ASSERT(success); } fmpz_mod_mpolyl_content(Bc, B, var, ctx); if (!fmpz_mod_mpoly_is_one(Bc, ctx)) { success = fmpz_mod_mpoly_divides(B, B, Bc, ctx); FLINT_ASSERT(success); } fmpz_mod_mpoly_get_fmpz_mod_poly(a, Ac, var, ctx); fmpz_mod_mpoly_get_fmpz_mod_poly(b, Bc, var, ctx); fmpz_mod_poly_gcd(c, a, b, ctx->ffinfo); success = fmpz_mod_poly_is_one(c, ctx->ffinfo); if (!success) goto cleanup; fmpz_mod_mpolyl_lead_coeff(Ac, A, var, ctx); fmpz_mod_mpolyl_lead_coeff(Bc, B, var, ctx); fmpz_mod_mpoly_get_fmpz_mod_poly(a, Ac, var, ctx); fmpz_mod_mpoly_get_fmpz_mod_poly(b, Bc, var, ctx); fmpz_mod_poly_gcd(gamma, a, b, ctx->ffinfo); /* degree bound on the gcd */ Adeg = fmpz_mod_mpoly_degree_si(A, 0, ctx); Bdeg = fmpz_mod_mpoly_degree_si(B, 0, ctx); Gdegbound = FLINT_MIN(Adeg, Bdeg); /* bound of the number of images required */ Alastdeg = fmpz_mod_mpoly_degree_si(A, var, ctx); Blastdeg = fmpz_mod_mpoly_degree_si(B, var, ctx); bound = 1 + FLINT_MIN(Alastdeg, Blastdeg) + _fmpz_mod_poly_degree(gamma); fmpz_mod_poly_one(modulus, ctx->ffinfo); fmpz_mod_rand_not_zero(start_alpha, state, ctx->ffinfo); fmpz_set(alpha, start_alpha); outer_loop: /* get new evaluation point */ if (fmpz_cmp_ui(alpha, 2) < 0) fmpz_set(alpha, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_sub_ui(alpha, alpha, 1); success = !fmpz_equal(alpha, start_alpha); if (!success) goto cleanup; FLINT_ASSERT(alphapow->alloc >= 2); fmpz_one(alphapow->coeffs + 0); fmpz_set(alphapow->coeffs + 1, alpha); alphapow->length = 2; /* make sure evaluation point does not kill both lc(A) and lc(B) */ fmpz_mod_poly_eval_pow(gammaeval, gamma, alphapow, ctx->ffinfo); if (fmpz_is_zero(gammaeval)) goto outer_loop; /* make sure evaluation point does not kill either A or B */ fmpz_mod_mpoly_evaluate_one_fmpz(Aeval, A, var, alpha, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(Beval, B, var, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) goto outer_loop; fmpz_mod_mpoly_repack_bits_inplace(Aeval, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(Beval, bits, ctx); success = fmpz_mod_mpolyl_gcdp_zippel(Geval, Abareval, Bbareval, Aeval, Beval, var - 1, ctx, state); if (!success) goto cleanup; FLINT_ASSERT(Geval->length > 0); FLINT_ASSERT(fmpz_is_one(Geval->coeffs + 0)); if (fmpz_mod_mpoly_is_one(Geval, ctx)) goto gcd_is_trivial; Gdeg = fmpz_mod_mpoly_degree_si(Geval, 0, ctx); if (Gdeg > Gdegbound) goto outer_loop; if (Gdeg < Gdegbound) fmpz_mod_poly_one(modulus, ctx->ffinfo); Gdegbound = Gdeg; /* update interpolant H */ fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(Geval, Geval, gammaeval, ctx); if (_fmpz_mod_poly_degree(modulus) > 0) { fmpz_mod_poly_eval_pow(temp, modulus, alphapow, ctx->ffinfo); fmpz_mod_poly_scalar_div_fmpz(modulus, modulus, temp, ctx->ffinfo); changed = fmpz_mod_mpolyn_interp_crt_sm_mpoly(&lastdeg, H, T, Geval, modulus, alphapow, ctx); if (!changed) { _fmpz_mod_poly_vec_remove_content(c, H->coeffs, H->length, ctx->ffinfo); fmpz_mod_mpoly_cvtfrom_mpolyn(G, H, var, ctx); fmpz_mod_mpoly_make_monic(G, G, ctx); success = fmpz_mod_mpoly_divides(Abar, A, G, ctx) && fmpz_mod_mpoly_divides(Bbar, B, G, ctx); if (success) goto cleanup; /* restore H */ _fmpz_mod_poly_vec_mul_poly(H->coeffs, H->length, c, ctx->ffinfo); goto outer_loop; } } else { fmpz_mod_mpolyn_interp_lift_sm_mpoly(H, Geval, ctx); } fmpz_mod_neg(temp, alpha, ctx->ffinfo); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, temp, ctx->ffinfo); fmpz_mod_mpoly_fit_length(G, H->length, ctx); mpoly_copy_monomials(G->exps, H->exps, H->length, N); G->length = H->length; mpoly1_fill_marks(&Gmarks->coeffs, &Gmarks->length, &Gmarks->alloc, G->exps, G->length, bits, ctx->minfo); perm = FLINT_ARRAY_REALLOC(perm, Gmarks->length, slong); for (i = 0; i < Gmarks->length; i++) perm[i] = i; #define length(k) Gmarks->coeffs[(k)+1] - Gmarks->coeffs[k] for (i = 1; i < Gmarks->length; i++) for (j = i; j > 0 && length(perm[j-1]) > length(perm[j]); j--) FLINT_SWAP(slong, perm[j-1], perm[j]); req_zip_images = Gmarks->length - 2; j = 0; for (i = 0; i < Gmarks->length; i++) { req_zip_images += length(i); j = FLINT_MAX(j, length(i)); } if (Gmarks->length > 1) req_zip_images = req_zip_images / (Gmarks->length - 1); req_zip_images = FLINT_MAX(req_zip_images, j); req_zip_images += 1; inner_loop: /* get new evaluation point */ if (fmpz_cmp_ui(alpha, 2) < 0) fmpz_set(alpha, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_sub_ui(alpha, alpha, 1); success = !fmpz_equal(alpha, start_alpha); if (!success) goto cleanup; FLINT_ASSERT(alphapow->alloc >= 2); fmpz_one(alphapow->coeffs + 0); fmpz_set(alphapow->coeffs + 1, alpha); alphapow->length = 2; /* make sure evaluation does not kill both lc(A) and lc(B) */ fmpz_mod_poly_eval_pow(gammaeval, gamma, alphapow, ctx->ffinfo); if (fmpz_is_zero(gammaeval)) goto inner_loop; /* make sure evaluation does not kill either A or B */ fmpz_mod_mpoly_evaluate_one_fmpz(Aeval, A, var, alpha, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(Beval, B, var, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) goto outer_loop; fmpz_mod_mpoly_repack_bits_inplace(Aeval, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(Beval, bits, ctx); success = fmpz_mod_mpolyl_gcds_zippel(Geval, Gmarks->coeffs, Gmarks->length, Aeval, Beval, perm, req_zip_images, var, ctx, state, &Gdegbound, Amarks, Bmarks); if (success == 0) { fmpz_mod_poly_one(modulus, ctx->ffinfo); goto outer_loop; } if (success < 0 || fmpz_is_zero(Geval->coeffs + 0)) goto inner_loop; /* update interpolant H */ fmpz_mod_divides(temp, gammaeval, Geval->coeffs + 0, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(Geval, Geval, temp, ctx); FLINT_ASSERT(_fmpz_mod_poly_degree(modulus) > 0); fmpz_mod_poly_eval_pow(temp, modulus, alphapow, ctx->ffinfo); fmpz_mod_poly_scalar_div_fmpz(modulus, modulus, temp, ctx->ffinfo); changed = fmpz_mod_mpolyn_interp_mcrt_sm_mpoly(&lastdeg, H, Geval, modulus, alphapow, ctx); fmpz_mod_neg(temp, alpha, ctx->ffinfo); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, temp, ctx->ffinfo); have_enough = _fmpz_mod_poly_degree(modulus) >= bound; if (changed && !have_enough) goto inner_loop; if (!changed || have_enough) { /* since H started from a correct modular image and was scaled wrt to the univariate gamma, if H is the correct gcd modulo content, the only content is univariate in the last variable */ _fmpz_mod_poly_vec_remove_content(c, H->coeffs, H->length, ctx->ffinfo); fmpz_mod_mpoly_cvtfrom_mpolyn(G, H, var, ctx); fmpz_mod_mpoly_make_monic(G, G, ctx); success = fmpz_mod_mpoly_divides(Abar, A, G, ctx) && fmpz_mod_mpoly_divides(Bbar, B, G, ctx); if (success) goto cleanup; /* restore H */ _fmpz_mod_poly_vec_mul_poly(H->coeffs, H->length, c, ctx->ffinfo); } if (have_enough) { fmpz_mod_poly_one(modulus, ctx->ffinfo); goto outer_loop; } goto inner_loop; cleanup: flint_free(perm); fmpz_clear(alpha); fmpz_clear(start_alpha); fmpz_clear(gammaeval); fmpz_clear(temp); fmpz_mod_mpoly_clear(Ac, ctx); fmpz_mod_mpoly_clear(Bc, ctx); fmpz_mod_mpoly_clear(Aeval, ctx); fmpz_mod_mpoly_clear(Beval, ctx); fmpz_mod_mpoly_clear(Geval, ctx); fmpz_mod_mpoly_clear(Abareval, ctx); fmpz_mod_mpoly_clear(Bbareval, ctx); fmpz_mod_poly_clear(a, ctx->ffinfo); fmpz_mod_poly_clear(b, ctx->ffinfo); fmpz_mod_poly_clear(c, ctx->ffinfo); fmpz_mod_poly_clear(gamma, ctx->ffinfo); fmpz_mod_poly_clear(modulus, ctx->ffinfo); fmpz_mod_poly_clear(alphapow, ctx->ffinfo); fmpz_mod_mpolyn_clear(H, ctx); fmpz_mod_mpolyn_clear(T, ctx); n_poly_clear(Amarks); n_poly_clear(Bmarks); n_poly_clear(Gmarks); FLINT_ASSERT(success || fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx->ffinfo))); return success; gcd_is_trivial: fmpz_mod_mpoly_one(G, ctx); fmpz_mod_mpoly_set(Abar, A, ctx); fmpz_mod_mpoly_set(Bbar, B, ctx); success = 1; goto cleanup; } flint-3.1.3/src/fmpz_mod_mpoly_factor/gcd_zippel2.c000066400000000000000000001302031461254215100223600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "n_poly.h" #include "nmod_mpoly.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_mpolyn_interp_lift_sm_polyu1n( fmpz_mod_mpolyn_t F, fmpz_mod_polyun_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); slong i, j, Fi; slong off0, shift0, off1, shift1; mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo); Fi = 0; for (i = 0; i < A->length; i++) { fmpz * Aicoeffs = A->coeffs[i].coeffs; ulong e0 = A->exps[i] << shift0; for (j = A->coeffs[i].length - 1; j >= 0; j--) { if (fmpz_is_zero(Aicoeffs + j)) continue; fmpz_mod_mpolyn_fit_length(F, Fi + 1, ctx); mpoly_monomial_zero(F->exps + N*Fi, N); (F->exps + N*Fi)[off0] = e0; (F->exps + N*Fi)[off1] += (j << shift1); fmpz_mod_poly_set_fmpz(F->coeffs + Fi, Aicoeffs + j, ctx->ffinfo); Fi++; } } F->length = Fi; } int fmpz_mod_mpolyn_interp_crt_sm_polyu1n( slong * lastdeg, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t T, fmpz_mod_polyun_t A, fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx) { int changed = 0; slong N = mpoly_words_per_exp(F->bits, ctx->minfo); slong off0, shift0, off1, shift1; fmpz_mod_poly_struct * Acoeffs = A->coeffs; ulong * Aexps = A->exps; slong Fi, Ti, Ai, ai; slong Alen = A->length; slong Flen = F->length; ulong * Fexps = F->exps; fmpz_mod_poly_struct * Fcoeffs = F->coeffs; ulong * Texps = T->exps; fmpz_mod_poly_struct * Tcoeffs = T->coeffs; fmpz_t v; ulong Fexpi, mask; fmpz_init(v); mask = (-UWORD(1)) >> (FLINT_BITS - F->bits); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo); FLINT_ASSERT(T->bits == F->bits); *lastdeg = -1; Ti = Fi = 0; Ai = 0; ai = 0; if (Ai < Alen) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx->ffinfo); while (Fi < Flen || Ai < Alen) { if (Ti >= T->alloc) { slong extra = FLINT_MAX(Flen - Fi, Alen - Ai); fmpz_mod_mpolyn_fit_length(T, Ti + extra + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; } if (Fi < Flen) Fexpi = pack_exp2(((Fexps + N*Fi)[off0]>>shift0)&mask, ((Fexps + N*Fi)[off1]>>shift1)&mask); else Fexpi = 0; if (Fi < Flen && Ai < Alen && Fexpi == pack_exp2(Aexps[Ai], ai)) { /* F term ok, A term ok */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); fmpz_mod_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx->ffinfo); fmpz_mod_sub(v, Acoeffs[Ai].coeffs + ai, v, ctx->ffinfo); changed |= !fmpz_is_zero(v); fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx->ffinfo); Fi++; do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); if (ai < 0) { Ai++; if (Ai < Alen) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx->ffinfo); } } else if (Ai < Alen && (Fi >= Flen || Fexpi < pack_exp2(Aexps[Ai], ai))) { /* F term missing, A term ok */ mpoly_monomial_zero(Texps + N*Ti, N); (Texps + N*Ti)[off0] += (Ai << shift0); (Texps + N*Ti)[off1] += (ai << shift1); changed = 1; fmpz_mod_poly_scalar_mul_fmpz(Tcoeffs + Ti, modulus, Acoeffs[Ai].coeffs + ai, ctx->ffinfo); do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); if (ai < 0) { Ai++; if (Ai < Alen) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx->ffinfo); } } else { FLINT_ASSERT(Fi < Flen && (Ai >= Alen || Fexpi > pack_exp2(Aexps[Ai], ai))); /* F term ok, Aterm missing */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); fmpz_mod_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx->ffinfo); fmpz_mod_neg(v, v, ctx->ffinfo); changed |= !fmpz_is_zero(v); fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx->ffinfo); Fi++; } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeffs + Ti, ctx->ffinfo)); *lastdeg = FLINT_MAX(*lastdeg, fmpz_mod_poly_degree(Tcoeffs + Ti, ctx->ffinfo)); Ti++; } T->length = Ti; if (changed) fmpz_mod_mpolyn_swap(T, F, ctx); fmpz_clear(v); return changed; } static ulong _fmpz_mod_mpoly_bidegree( const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return _mpoly_bidegree(A->exps, A->bits, ctx->minfo); } int fmpz_mod_polyun_zip_solve( fmpz_mod_mpoly_t A, fmpz_mod_polyun_t Z, fmpz_mod_polyun_t H, fmpz_mod_polyun_t M, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong Ai, i, n; fmpz * Acoeffs = A->coeffs; fmpz_mod_poly_t t; fmpz_mod_poly_init(t, ctx->ffinfo); FLINT_ASSERT(Z->length == H->length); FLINT_ASSERT(Z->length == M->length); Ai = 0; for (i = 0; i < H->length; i++) { n = H->coeffs[i].length; FLINT_ASSERT(M->coeffs[i].length == n + 1); FLINT_ASSERT(Z->coeffs[i].length >= n); FLINT_ASSERT(Ai + n <= A->length); fmpz_mod_poly_fit_length(t, n, ctx->ffinfo); success = _fmpz_mod_zip_vand_solve(Acoeffs + Ai, H->coeffs[i].coeffs, n, Z->coeffs[i].coeffs, Z->coeffs[i].length, M->coeffs[i].coeffs, t->coeffs, ctx->ffinfo); if (success < 1) { fmpz_mod_poly_clear(t, ctx->ffinfo); return success; } Ai += n; FLINT_ASSERT(Ai <= A->length); } FLINT_ASSERT(Ai == A->length); fmpz_mod_poly_clear(t, ctx->ffinfo); return 1; } #define USE_G 1 #define USE_ABAR 2 #define USE_BBAR 4 static double interp_cost( double degG, double numABgamma, double maxnumci, double totnumci, double degxAB, double degyAB) { return degG*(degG*totnumci + numABgamma + 0.01*maxnumci*( numABgamma + totnumci + (degxAB*degyAB)*(degxAB*degyAB))); } int fmpz_mod_mpoly_gcd_get_use_new( slong rGdeg, slong Adeg, slong Bdeg, slong gammadeg, slong degxAB, slong degyAB, slong numABgamma, const fmpz_mod_polyun_t G, const fmpz_mod_polyun_t Abar, const fmpz_mod_polyun_t Bbar) { int use = 0; slong i, lower = FLINT_MAX(gammadeg, rGdeg); slong upper = gammadeg + FLINT_MIN(FLINT_MIN(Adeg, Bdeg), rGdeg); if (lower <= upper) { slong Gdeg = ((ulong)upper + (ulong)lower)/2; slong maxnumci, totnumci; double Gcost, Abarcost, Bbarcost; maxnumci = totnumci = 0; for (i = 0; i < G->length; i++) { maxnumci = FLINT_MAX(maxnumci, G->coeffs[i].length); totnumci += G->coeffs[i].length; } FLINT_ASSERT(Gdeg >= 0); Gcost = interp_cost(Gdeg, numABgamma, maxnumci, totnumci, degxAB, degyAB); maxnumci = totnumci = 0; for (i = 0; i < Abar->length; i++) { maxnumci = FLINT_MAX(maxnumci, Abar->coeffs[i].length); totnumci += Abar->coeffs[i].length; } FLINT_ASSERT(gammadeg + Adeg - Gdeg >= 0); Abarcost = interp_cost(gammadeg + Adeg - Gdeg, numABgamma, maxnumci, totnumci, degxAB, degyAB); maxnumci = totnumci = 0; for (i = 0; i < Bbar->length; i++) { maxnumci = FLINT_MAX(maxnumci, Bbar->coeffs[i].length); totnumci += Bbar->coeffs[i].length; } FLINT_ASSERT(gammadeg + Bdeg - Gdeg >= 0); Bbarcost = interp_cost(gammadeg + Bdeg - Gdeg, numABgamma, maxnumci, totnumci, degxAB, degyAB); if (Gcost <= FLINT_MIN(Abarcost, Bbarcost)*1.125) use |= USE_G; if (Abarcost <= FLINT_MIN(Gcost, Bbarcost)*1.125) use |= USE_ABAR; if (Bbarcost <= FLINT_MIN(Gcost, Abarcost)*1.125) use |= USE_BBAR; } if (use == 0) use = USE_G | USE_ABAR | USE_BBAR; return use; } static void fmpz_mod_poly_zip_eval_cur_inc_coeff( fmpz_t eval, fmpz_mod_poly_t cur, const fmpz_mod_poly_t inc, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length == cur->length); FLINT_ASSERT(A->length == inc->length); _fmpz_mod_zip_eval_step(eval, cur->coeffs, inc->coeffs, A->coeffs, A->length, ctx->ffinfo); } void fmpz_mod_mpoly_mock_eval_coeff( fmpz_mod_polyun_t mock, const fmpz_mod_mpoly_t A, const fmpz_mod_polyun_t Aeh_inc, const fmpz_mod_mpoly_ctx_t ctx) { slong i, k; if (mock->alloc < Aeh_inc->length) { mock->alloc = FLINT_MAX(Aeh_inc->length, mock->alloc + mock->alloc/2); mock->coeffs = FLINT_ARRAY_REALLOC(mock->coeffs, mock->alloc, fmpz_mod_poly_struct); } mock->length = Aeh_inc->length; k = 0; for (i = 0; i < Aeh_inc->length; i++) { slong l = Aeh_inc->coeffs[i].length; mock->coeffs[i].coeffs = A->coeffs + k; mock->coeffs[i].alloc = l; mock->coeffs[i].length = l; k += l; } FLINT_ASSERT(k == A->length); } static void fmpz_mod_mpoly_monomial_evals( fmpz_mod_poly_t E, const fmpz_mod_mpoly_t A, fmpz_mod_poly_struct * beta_caches, slong start, slong stop, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_monomial_evals_fmpz_mod(E, A->exps, A->length, A->bits, beta_caches, start, stop, ctx->minfo, ctx->ffinfo); } static void fmpz_mod_mpoly_monomial_evals2( fmpz_mod_polyun_t E, const fmpz_mod_mpoly_t A, fmpz_mod_poly_struct * betas, slong m, const fmpz_mod_mpoly_ctx_t ctx, n_poly_t tmark) /* temp space */ { mpoly2_fill_marks(&tmark->coeffs, &tmark->length, &tmark->alloc, A->exps, A->length, A->bits, ctx->minfo); mpoly2_monomial_evals_fmpz_mod(E, A->exps, A->bits, tmark->coeffs, tmark->length, betas, m, ctx->minfo, ctx->ffinfo); } static int fmpz_mod_polyun_add_zip_must_match( fmpz_mod_polyun_t Z, const fmpz_mod_polyun_t A, slong cur_length) { slong i, Ai, ai; slong Alen = A->length; ulong * Zexps = Z->exps; fmpz_mod_poly_struct * Zcoeffs = Z->coeffs; ulong * Aexps = A->exps; fmpz_mod_poly_struct * Acoeffs = A->coeffs; Ai = 0; ai = 0; if (Ai < Alen) ai = Acoeffs[Ai].length - 1; for (i = 0; i < Z->length; i++) { if (Ai < Alen && Zexps[i] == pack_exp2(Aexps[Ai], ai)) { /* Z present, A present */ fmpz_set(Zcoeffs[i].coeffs + cur_length, Acoeffs[Ai].coeffs + ai); Zcoeffs[i].length = cur_length + 1; do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); if (ai < 0) { Ai++; if (Ai < Alen) ai = Acoeffs[Ai].length - 1; } } else if (Ai >= Alen || Zexps[i] > pack_exp2(Aexps[Ai], ai)) { /* Z present, A missing */ fmpz_zero(Zcoeffs[i].coeffs + cur_length); Zcoeffs[i].length = cur_length + 1; } else { /* Z missing, A present */ return 0; } } return Ai >= Alen; } void fmpz_mod_polyu2n_zip_eval_cur_inc_coeff( fmpz_mod_polyun_t E, fmpz_mod_polyun_t Acur, const fmpz_mod_polyun_t Ainc, const fmpz_mod_polyun_t Acoeff, const fmpz_mod_ctx_t ctx) { slong i, Ei; slong e0, e1; fmpz_t c; FLINT_ASSERT(Acur->length > 0); FLINT_ASSERT(Acur->length == Ainc->length); FLINT_ASSERT(Acur->length == Acoeff->length); fmpz_init(c); e0 = extract_exp(Acur->exps[0], 1, 2); e1 = extract_exp(Acur->exps[0], 0, 2); fmpz_mod_polyun_fit_length(E, 4, ctx); Ei = 0; E->exps[Ei] = e1; fmpz_mod_poly_zero(E->coeffs + Ei, ctx); for (i = 0; i < Acur->length; i++) { slong this_len = Acur->coeffs[i].length; FLINT_ASSERT(this_len == Ainc->coeffs[i].length); FLINT_ASSERT(this_len == Acoeff->coeffs[i].length); _fmpz_mod_zip_eval_step(c, Acur->coeffs[i].coeffs, Ainc->coeffs[i].coeffs, Acoeff->coeffs[i].coeffs, this_len, ctx); e0 = extract_exp(Acur->exps[i], 1, 2); e1 = extract_exp(Acur->exps[i], 0, 2); if (E->exps[Ei] != e0) { fmpz_mod_polyun_fit_length(E, Ei + 2, ctx); Ei += !fmpz_mod_poly_is_zero(E->coeffs + Ei, ctx); E->exps[Ei] = e0; fmpz_mod_poly_zero(E->coeffs + Ei, ctx); } fmpz_mod_poly_set_coeff_fmpz(E->coeffs + Ei, e1, c, ctx); } Ei += !fmpz_mod_poly_is_zero(E->coeffs + Ei, ctx); E->length = Ei; FLINT_ASSERT(fmpz_mod_polyun_is_canonical(E, ctx)); fmpz_clear(c); } /* gamma = gcd(lc(A), lc(B)) fake answers G, Abar, Bbar with G*Abar = gamma*A G*Bbar = gamma*B lc(G) = gamma lc(Abar) = lc(A) lc(Bbar) = lc(B) real answers rG = pp(G) rAbar = Abar/lc(rG) rBbar = Bbar/lc(rG) The degrees of A, B, and gamma wrt the minor vars must be passed in. A guess of the degrees of rG wrt the minor vars can be passed in. deg(G) = deg(gamma) - deg(lc(rG)) + deg(rG) deg(G) <= deg(gamma) + deg(rG) deg(G) <= deg(gamma) + deg(A) deg(G) <= deg(gamma) + deg(B) deg(G) >= deg(gamma) deg(G) >= deg(rG) deg(A) = deg(gamma) + deg(A) - deg(G) deg(B) = deg(gamma) + deg(B) - deg(G) */ int fmpz_mod_mpolyl_gcd_zippel2_smprime( fmpz_mod_mpoly_t rG, const slong * rGdegs, /* guess at rG degrees, could be NULL */ fmpz_mod_mpoly_t rAbar, fmpz_mod_mpoly_t rBbar, const fmpz_mod_mpoly_t A, const slong * Adegs, const fmpz_mod_mpoly_t B, const slong * Bdegs, const fmpz_mod_mpoly_t gamma, const slong * gammadegs, const fmpz_mod_mpoly_ctx_t ctx) { int success, use, alpha_tries_left; slong i, m; slong nvars = ctx->minfo->nvars; flint_bitcnt_t bits = A->bits; fmpz * alphas, * betas; fmpz_mod_poly_struct * alpha_caches, * beta_caches; flint_rand_t state; n_poly_t tmark; fmpz_mod_mpoly_t cont; fmpz_mod_mpoly_t T, G, Abar, Bbar; fmpz_mod_polyun_t HG, HAbar, HBbar, MG, MAbar, MBbar, ZG, ZAbar, ZBbar; fmpz_mod_polyun_t Aev, Bev, Gev, Abarev, Bbarev; fmpz_t gammaev; fmpz_mod_mpolyn_t Tn, Gn, Abarn, Bbarn; slong lastdeg; slong cur_zip_image, req_zip_images, this_length; fmpz_mod_polyun_t Aeh_coeff_mock, Beh_coeff_mock; fmpz_mod_polyun_t Aeh_cur, Aeh_inc, Beh_cur, Beh_inc; fmpz_mod_poly_t gammaeh_cur, gammaeh_inc; fmpz_mod_poly_t modulus, alphapow; fmpz_mod_mpoly_struct * Aevals, * Bevals; fmpz_mod_mpoly_struct * gammaevals; fmpz_mod_poly_polyun_stack_t St; fmpz_t c, start_alpha; ulong GdegboundXY, newdegXY, Abideg, Bbideg; slong degxAB, degyAB; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == gamma->bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(gamma->length > 0); fmpz_mod_mpoly_fit_length_reset_bits(rG, 1, bits, ctx); fmpz_mod_mpoly_fit_length_reset_bits(rAbar, 1, bits, ctx); fmpz_mod_mpoly_fit_length_reset_bits(rBbar, 1, bits, ctx); fmpz_init(gammaev); fmpz_init(c); fmpz_init(start_alpha); #if FLINT_WANT_ASSERT { slong * tmp_degs = FLINT_ARRAY_ALLOC(nvars, slong); fmpz_mod_mpoly_degrees_si(tmp_degs, A, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Adegs[i]); fmpz_mod_mpoly_degrees_si(tmp_degs, B, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Bdegs[i]); fmpz_mod_mpoly_degrees_si(tmp_degs, gamma, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == gammadegs[i]); flint_free(tmp_degs); } #endif FLINT_ASSERT(gammadegs[0] == 0); FLINT_ASSERT(gammadegs[1] == 0); n_poly_init(tmark); fmpz_mod_polyun_init(HG, ctx->ffinfo); fmpz_mod_polyun_init(HAbar, ctx->ffinfo); fmpz_mod_polyun_init(HBbar, ctx->ffinfo); fmpz_mod_polyun_init(MG, ctx->ffinfo); fmpz_mod_polyun_init(MAbar, ctx->ffinfo); fmpz_mod_polyun_init(MBbar, ctx->ffinfo); fmpz_mod_polyun_init(ZG, ctx->ffinfo); fmpz_mod_polyun_init(ZAbar, ctx->ffinfo); fmpz_mod_polyun_init(ZBbar, ctx->ffinfo); fmpz_mod_polyun_init(Aev, ctx->ffinfo); fmpz_mod_polyun_init(Bev, ctx->ffinfo); fmpz_mod_polyun_init(Gev, ctx->ffinfo); fmpz_mod_polyun_init(Abarev, ctx->ffinfo); fmpz_mod_polyun_init(Bbarev, ctx->ffinfo); fmpz_mod_poly_init2(alphapow, 4, ctx->ffinfo); fmpz_mod_mpoly_init3(cont, 1, bits, ctx); fmpz_mod_mpoly_init3(T, 1, bits, ctx); fmpz_mod_mpoly_init3(G, 1, bits, ctx); fmpz_mod_mpoly_init3(Abar, 1, bits, ctx); fmpz_mod_mpoly_init3(Bbar, 1, bits, ctx); fmpz_mod_mpolyn_init(Tn, bits, ctx); fmpz_mod_mpolyn_init(Gn, bits, ctx); fmpz_mod_mpolyn_init(Abarn, bits, ctx); fmpz_mod_mpolyn_init(Bbarn, bits, ctx); fmpz_mod_polyun_init(Aeh_cur, ctx->ffinfo); fmpz_mod_polyun_init(Aeh_inc, ctx->ffinfo); fmpz_mod_polyun_init(Beh_cur, ctx->ffinfo); fmpz_mod_polyun_init(Beh_inc, ctx->ffinfo); fmpz_mod_poly_init(gammaeh_cur, ctx->ffinfo); fmpz_mod_poly_init(gammaeh_inc, ctx->ffinfo); fmpz_mod_poly_init(modulus, ctx->ffinfo); fmpz_mod_poly_stack_init(St->poly_stack); fmpz_mod_polyun_stack_init(St->polyun_stack); Aeh_coeff_mock->exps = NULL; Aeh_coeff_mock->coeffs = NULL; Aeh_coeff_mock->length = 0; Aeh_coeff_mock->alloc = 0; Beh_coeff_mock->exps = NULL; Beh_coeff_mock->coeffs = NULL; Beh_coeff_mock->length = 0; Beh_coeff_mock->alloc = 0; betas = _fmpz_vec_init(nvars); alphas = _fmpz_vec_init(nvars); flint_randinit(state); beta_caches = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_poly_struct); alpha_caches = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_poly_struct); for (i = 0; i < nvars; i++) { fmpz_mod_poly_init(beta_caches + i, ctx->ffinfo); fmpz_mod_poly_init(alpha_caches + i, ctx->ffinfo); } Aevals = FLINT_ARRAY_ALLOC(nvars + 1, fmpz_mod_mpoly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars + 1, fmpz_mod_mpoly_struct); gammaevals = FLINT_ARRAY_ALLOC(nvars + 1, fmpz_mod_mpoly_struct); for (i = 0; i < nvars; i++) { fmpz_mod_mpoly_init3(Aevals + i, 0, bits, ctx); fmpz_mod_mpoly_init3(Bevals + i, 0, bits, ctx); fmpz_mod_mpoly_init3(gammaevals + i, 0, bits, ctx); } Aevals[nvars] = *A; Bevals[nvars] = *B; gammaevals[nvars] = *gamma; Abideg = _fmpz_mod_mpoly_bidegree(A, ctx); Bbideg = _fmpz_mod_mpoly_bidegree(B, ctx); degxAB = FLINT_MAX(Adegs[0], Bdegs[0]); degyAB = FLINT_MAX(Adegs[1], Bdegs[1]); GdegboundXY = pack_exp2(FLINT_MIN(Adegs[0], Bdegs[0]), FLINT_MIN(Adegs[1], Bdegs[1])); if (GdegboundXY == 0) goto gcd_is_trivial; alpha_tries_left = 20; choose_alphas: if (--alpha_tries_left < 0) { success = 0; goto cleanup; } for (i = 2; i < nvars; i++) fmpz_mod_rand_not_zero(alphas + i, state, ctx->ffinfo); for (i = nvars - 1; i >= 2; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + i, Aevals + i + 1, i, alphas + i, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(Bevals + i, Bevals + i + 1, i, alphas + i, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(gammaevals + i, gammaevals + i + 1, i, alphas + i, ctx); if (fmpz_mod_mpoly_is_zero(gammaevals + i, ctx)) goto choose_alphas; if (Aevals[i].length < 1 || _fmpz_mod_mpoly_bidegree(Aevals + i, ctx) != Abideg) goto choose_alphas; if (Bevals[i].length < 1 || _fmpz_mod_mpoly_bidegree(Bevals + i, ctx) != Bbideg) goto choose_alphas; } m = 2; if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = mpoly_gcd_get_use_first(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m]); fmpz_mod_mpoly_get_polyu1n(Aev, Aevals + m, 0, 1, ctx); fmpz_mod_mpoly_get_polyu1n(Bev, Bevals + m, 0, 1, ctx); success = fmpz_mod_polyu1n_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->ffinfo, St->poly_stack, St->polyun_stack); if (!success) goto cleanup; newdegXY = fmpz_mod_polyu1n_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alphas; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; } fmpz_mod_mpoly_get_fmpz(gammaev, gammaevals + m, ctx); _fmpz_mod_poly_vec_mul_fmpz_mod(Gev->coeffs, Gev->length, gammaev, ctx->ffinfo); fmpz_mod_mpolyn_interp_lift_sm_polyu1n(Gn, Gev, ctx); fmpz_mod_mpolyn_interp_lift_sm_polyu1n(Abarn, Abarev, ctx); fmpz_mod_mpolyn_interp_lift_sm_polyu1n(Bbarn, Bbarev, ctx); fmpz_mod_poly_one(modulus, ctx->ffinfo); fmpz_mod_neg(c, alphas + m, ctx->ffinfo); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo); fmpz_set(start_alpha, alphas + m); while (1) { choose_alpha_2: if (fmpz_cmp_ui(alphas + m, 2) < 0) fmpz_set(alphas + m, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_sub_ui(alphas + m, alphas + m, 1); if (fmpz_equal(alphas + m, start_alpha)) goto choose_alphas; FLINT_ASSERT(alphapow->alloc >= 2); fmpz_one(alphapow->coeffs + 0); fmpz_set(alphapow->coeffs + 1, alphas + m); alphapow->length = 2; fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + m, Aevals + m + 1, m, alphas + m, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(Bevals + m, Bevals + m + 1, m, alphas + m, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(gammaevals + m, gammaevals + m + 1, m, alphas + m, ctx); if (fmpz_mod_mpoly_is_zero(gammaevals + m, ctx)) goto choose_alpha_2; if (Aevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Aevals + m, ctx) != Abideg) goto choose_alpha_2; if (Bevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Bevals + m, ctx) != Bbideg) goto choose_alpha_2; fmpz_mod_mpoly_get_polyu1n(Aev, Aevals + m, 0, 1, ctx); fmpz_mod_mpoly_get_polyu1n(Bev, Bevals + m, 0, 1, ctx); success = fmpz_mod_polyu1n_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->ffinfo, St->poly_stack, St->polyun_stack); if (!success) goto cleanup; newdegXY = fmpz_mod_polyu1n_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alpha_2; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } fmpz_mod_mpoly_get_fmpz(gammaev, gammaevals + m, ctx); _fmpz_mod_poly_vec_mul_fmpz_mod(Gev->coeffs, Gev->length, gammaev, ctx->ffinfo); fmpz_mod_poly_eval_pow(c, modulus, alphapow, ctx->ffinfo); fmpz_mod_inv(c, c, ctx->ffinfo); fmpz_mod_poly_scalar_mul_fmpz(modulus, modulus, c, ctx->ffinfo); if ((use & USE_G) && !fmpz_mod_mpolyn_interp_crt_sm_polyu1n( &lastdeg, Gn, Tn, Gev, modulus, alphapow, ctx)) { if (m == nvars - 1) { fmpz_mod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx); success = fmpz_mod_mpolyl_content(cont, rG, 2, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_divides(rG, rG, cont, ctx); fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); if (fmpz_mod_mpoly_divides(rAbar, A, rG, ctx) && fmpz_mod_mpoly_divides(rBbar, B, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fmpz_mod_mpoly_cvtfrom_mpolyn(G, Gn, m, ctx); fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(Abar, T, G, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(Abar, bits, ctx); fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(Bbar, T, G, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(Bbar, bits, ctx); break; } } } } if ((use & USE_ABAR) && !fmpz_mod_mpolyn_interp_crt_sm_polyu1n( &lastdeg, Abarn, Tn, Abarev, modulus, alphapow, ctx)) { if (m == nvars - 1) { fmpz_mod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx); success = fmpz_mod_mpolyl_content(cont, rAbar, 2, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_divides(rAbar, rAbar, cont, ctx); fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); if (fmpz_mod_mpoly_divides(rG, A, rAbar, ctx) && fmpz_mod_mpoly_divides(rBbar, B, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fmpz_mod_mpoly_cvtfrom_mpolyn(Abar, Abarn, m, ctx); fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(G, T, Abar, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(G, bits, ctx); fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(Bbar, T, G, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(Bbar, bits, ctx); break; } } } } if ((use & USE_BBAR) && !fmpz_mod_mpolyn_interp_crt_sm_polyu1n( &lastdeg, Bbarn, Tn, Bbarev, modulus, alphapow, ctx)) { if (m == nvars - 1) { fmpz_mod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx); success = fmpz_mod_mpolyl_content(cont, rBbar, 2, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_divides(rBbar, rBbar, cont, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); if (fmpz_mod_mpoly_divides(rG, B, rBbar, ctx) && fmpz_mod_mpoly_divides(rAbar, A, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); break; } } else { fmpz_mod_mpoly_cvtfrom_mpolyn(Bbar, Bbarn, m, ctx); fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(G, T, Bbar, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(G, bits, ctx); fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(Abar, T, G, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(Abar, bits, ctx); break; } } } } if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) > gammadegs[m] + Adegs[m] && fmpz_mod_poly_degree(modulus, ctx->ffinfo) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } fmpz_mod_neg(c, alphas + m, ctx->ffinfo); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo); } for (m = 3; m < nvars; m++) { /* G, Abar, Bbar are in Fp[gen(0), ..., gen(m - 1)] */ fmpz_mod_mpolyn_interp_lift_sm_mpoly(Gn, G, ctx); fmpz_mod_mpolyn_interp_lift_sm_mpoly(Abarn, Abar, ctx); fmpz_mod_mpolyn_interp_lift_sm_mpoly(Bbarn, Bbar, ctx); if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = 0; fmpz_mod_poly_one(modulus, ctx->ffinfo); fmpz_mod_neg(c, alphas + m, ctx->ffinfo); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo); fmpz_set(start_alpha, alphas + m); choose_betas: /* only beta[2], beta[1], ..., beta[m - 1] will be used */ for (i = 2; i < nvars; i++) { fmpz_mod_rand_not_zero(betas + i, state, ctx->ffinfo); fmpz_mod_pow_cache_start(betas + i, beta_caches + i, ctx->ffinfo); } fmpz_mod_mpoly_monomial_evals2(HG, G, beta_caches + 2, m, ctx, tmark); fmpz_mod_mpoly_monomial_evals2(HAbar, Abar, beta_caches + 2, m, ctx, tmark); fmpz_mod_mpoly_monomial_evals2(HBbar, Bbar, beta_caches + 2, m, ctx, tmark); if (use == 0) { this_length = gammaevals[m + 1].length + Aevals[m + 1].length + Bevals[m + 1].length; use = fmpz_mod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar); } req_zip_images = 1; if (use & USE_G) { this_length = fmpz_mod_polyun_product_roots(MG, HG, ctx->ffinfo); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_ABAR) { this_length = fmpz_mod_polyun_product_roots(MAbar, HAbar, ctx->ffinfo); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_BBAR) { this_length = fmpz_mod_polyun_product_roots(MBbar, HBbar, ctx->ffinfo); req_zip_images = FLINT_MAX(req_zip_images, this_length); } while (1) { choose_alpha_m: if (fmpz_cmp_ui(alphas + m, 2) < 0) fmpz_set(alphas + m, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_sub_ui(alphas + m, alphas + m, 1); if (fmpz_equal(alphas + m, start_alpha)) goto choose_alphas; FLINT_ASSERT(alphapow->alloc >= 2); fmpz_one(alphapow->coeffs + 0); fmpz_set(alphapow->coeffs + 1, alphas + m); alphapow->length = 2; fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + m, Aevals + m + 1, m, alphas + m, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(Bevals + m, Bevals + m + 1, m, alphas + m, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(gammaevals + m, gammaevals + m + 1, m, alphas + m, ctx); if (fmpz_mod_mpoly_is_zero(gammaevals + m, ctx)) goto choose_alpha_m; if (Aevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Aevals + m, ctx) != Abideg) goto choose_alpha_m; if (Bevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Bevals + m, ctx) != Bbideg) goto choose_alpha_m; fmpz_mod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, beta_caches + 2, m, ctx, tmark); fmpz_mod_mpoly_monomial_evals2(Beh_inc, Bevals + m, beta_caches + 2, m, ctx, tmark); fmpz_mod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, beta_caches + 2, 2, m, ctx); fmpz_mod_polyun_set(Aeh_cur, Aeh_inc, ctx->ffinfo); fmpz_mod_polyun_set(Beh_cur, Beh_inc, ctx->ffinfo); fmpz_mod_poly_set(gammaeh_cur, gammaeh_inc, ctx->ffinfo); fmpz_mod_mpoly_mock_eval_coeff(Aeh_coeff_mock, Aevals + m, Aeh_inc, ctx); fmpz_mod_mpoly_mock_eval_coeff(Beh_coeff_mock, Bevals + m, Beh_inc, ctx); fmpz_mod_polyun_zip_start(ZG, HG, req_zip_images, ctx->ffinfo); fmpz_mod_polyun_zip_start(ZAbar, HAbar, req_zip_images, ctx->ffinfo); fmpz_mod_polyun_zip_start(ZBbar, HBbar, req_zip_images, ctx->ffinfo); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(Aev, Aeh_cur, Aeh_inc, Aeh_coeff_mock, ctx->ffinfo); fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(Bev, Beh_cur, Beh_inc, Beh_coeff_mock, ctx->ffinfo); fmpz_mod_poly_zip_eval_cur_inc_coeff(gammaev, gammaeh_cur, gammaeh_inc, gammaevals + m, ctx); if (fmpz_is_zero(gammaev)) goto choose_betas; if (Aev->length < 1 || fmpz_mod_polyu1n_bidegree(Aev) != Abideg) goto choose_betas; if (Bev->length < 1 || fmpz_mod_polyu1n_bidegree(Bev) != Bbideg) goto choose_betas; success = fmpz_mod_polyu1n_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->ffinfo, St->poly_stack, St->polyun_stack); if (!success) goto cleanup; newdegXY = fmpz_mod_polyu1n_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_betas; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } _fmpz_mod_poly_vec_mul_fmpz_mod(Gev->coeffs, Gev->length, gammaev, ctx->ffinfo); if ((use & USE_G) && !fmpz_mod_polyun_add_zip_must_match(ZG, Gev, cur_zip_image)) goto choose_alphas; if ((use & USE_ABAR) && !fmpz_mod_polyun_add_zip_must_match(ZAbar, Abarev, cur_zip_image)) goto choose_alphas; if ((use & USE_BBAR) && !fmpz_mod_polyun_add_zip_must_match(ZBbar, Bbarev, cur_zip_image)) goto choose_alphas; } if ((use & USE_G) && fmpz_mod_polyun_zip_solve(G, ZG, HG, MG, ctx) < 1) goto choose_alphas; if ((use & USE_ABAR) && fmpz_mod_polyun_zip_solve(Abar, ZAbar, HAbar, MAbar, ctx) < 1) goto choose_alphas; if ((use & USE_BBAR) && fmpz_mod_polyun_zip_solve(Bbar, ZBbar, HBbar, MBbar, ctx) < 1) goto choose_alphas; FLINT_ASSERT(fmpz_mod_poly_degree(modulus, ctx->ffinfo) > 0); fmpz_mod_poly_eval_pow(c, modulus, alphapow, ctx->ffinfo); fmpz_mod_inv(c, c, ctx->ffinfo); fmpz_mod_poly_scalar_mul_fmpz(modulus, modulus, c, ctx->ffinfo); if ((use & USE_G) && !fmpz_mod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Gn, G, modulus, alphapow, ctx)) { fmpz_mod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx); if (m == nvars - 1) { success = fmpz_mod_mpolyl_content(cont, rG, 2, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_divides(rG, rG, cont, ctx); fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); if (fmpz_mod_mpoly_divides(rAbar, A, rG, ctx) && fmpz_mod_mpoly_divides(rBbar, B, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(rAbar, T, rG, ctx)) { fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(rBbar, T, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); fmpz_mod_mpoly_swap(G, rG, ctx); fmpz_mod_mpoly_swap(Abar, rAbar, ctx); fmpz_mod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if ((use & USE_ABAR) && !fmpz_mod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Abarn, Abar, modulus, alphapow, ctx)) { fmpz_mod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx); if (m == nvars - 1) { success = fmpz_mod_mpolyl_content(cont, rAbar, 2, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_divides(rAbar, rAbar, cont, ctx); fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); if (fmpz_mod_mpoly_divides(rG, A, rAbar, ctx) && fmpz_mod_mpoly_divides(rBbar, B, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(rG, T, rAbar, ctx)) { fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(rBbar, T, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); fmpz_mod_mpoly_swap(G, rG, ctx); fmpz_mod_mpoly_swap(Abar, rAbar, ctx); fmpz_mod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if ((use & USE_BBAR) && !fmpz_mod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Bbarn, Bbar, modulus, alphapow, ctx)) { fmpz_mod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx); if (m == nvars - 1) { success = fmpz_mod_mpolyl_content(cont, rBbar, 2, ctx); if (!success) goto cleanup; fmpz_mod_mpoly_divides(rBbar, rBbar, cont, ctx); fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx); if (fmpz_mod_mpoly_divides(rG, B, rBbar, ctx) && fmpz_mod_mpoly_divides(rAbar, A, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); break; } } else { fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(rG, T, rBbar, ctx)) { fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fmpz_mod_mpoly_divides(rAbar, T, rG, ctx)) { fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx); fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fmpz_mod_mpoly_swap(G, rG, ctx); fmpz_mod_mpoly_swap(Abar, rAbar, ctx); fmpz_mod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if (_fmpz_mod_poly_degree(modulus) > gammadegs[m] + Adegs[m] && _fmpz_mod_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } fmpz_mod_neg(c, alphas + m, ctx->ffinfo); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo); } } success = 1; cleanup: n_poly_clear(tmark); fmpz_mod_polyun_clear(HG, ctx->ffinfo); fmpz_mod_polyun_clear(HAbar, ctx->ffinfo); fmpz_mod_polyun_clear(HBbar, ctx->ffinfo); fmpz_mod_polyun_clear(MG, ctx->ffinfo); fmpz_mod_polyun_clear(MAbar, ctx->ffinfo); fmpz_mod_polyun_clear(MBbar, ctx->ffinfo); fmpz_mod_polyun_clear(ZG, ctx->ffinfo); fmpz_mod_polyun_clear(ZAbar, ctx->ffinfo); fmpz_mod_polyun_clear(ZBbar, ctx->ffinfo); fmpz_mod_polyun_clear(Aev, ctx->ffinfo); fmpz_mod_polyun_clear(Bev, ctx->ffinfo); fmpz_mod_polyun_clear(Gev, ctx->ffinfo); fmpz_mod_polyun_clear(Abarev, ctx->ffinfo); fmpz_mod_polyun_clear(Bbarev, ctx->ffinfo); fmpz_mod_poly_clear(alphapow, ctx->ffinfo); fmpz_mod_mpoly_clear(cont, ctx); fmpz_mod_mpoly_clear(T, ctx); fmpz_mod_mpoly_clear(G, ctx); fmpz_mod_mpoly_clear(Abar, ctx); fmpz_mod_mpoly_clear(Bbar, ctx); fmpz_mod_mpolyn_clear(Tn, ctx); fmpz_mod_mpolyn_clear(Gn, ctx); fmpz_mod_mpolyn_clear(Abarn, ctx); fmpz_mod_mpolyn_clear(Bbarn, ctx); fmpz_mod_polyun_clear(Aeh_cur, ctx->ffinfo); fmpz_mod_polyun_clear(Aeh_inc, ctx->ffinfo); fmpz_mod_polyun_clear(Beh_cur, ctx->ffinfo); fmpz_mod_polyun_clear(Beh_inc, ctx->ffinfo); fmpz_mod_poly_clear(gammaeh_cur, ctx->ffinfo); fmpz_mod_poly_clear(gammaeh_inc, ctx->ffinfo); fmpz_mod_poly_clear(modulus, ctx->ffinfo); fmpz_mod_poly_stack_clear(St->poly_stack); fmpz_mod_polyun_stack_clear(St->polyun_stack); flint_free(Aeh_coeff_mock->coeffs); flint_free(Beh_coeff_mock->coeffs); for (i = 0; i < nvars; i++) { fmpz_mod_poly_clear(beta_caches + i, ctx->ffinfo); fmpz_mod_poly_clear(alpha_caches + i, ctx->ffinfo); } flint_free(beta_caches); flint_free(alpha_caches); _fmpz_vec_clear(betas, nvars); _fmpz_vec_clear(alphas, nvars); flint_randclear(state); for (i = 0; i < nvars; i++) { fmpz_mod_mpoly_clear(Aevals + i, ctx); fmpz_mod_mpoly_clear(Bevals + i, ctx); fmpz_mod_mpoly_clear(gammaevals + i, ctx); } flint_free(Aevals); flint_free(Bevals); flint_free(gammaevals); fmpz_clear(gammaev); fmpz_clear(c); fmpz_clear(start_alpha); FLINT_ASSERT(!success || rG->bits == bits); FLINT_ASSERT(!success || rAbar->bits == bits); FLINT_ASSERT(!success || rBbar->bits == bits); FLINT_ASSERT(success || fmpz_abs_fits_ui(fmpz_mod_mpoly_ctx_modulus(ctx))); return success; gcd_is_trivial: fmpz_mod_mpoly_one(rG, ctx); fmpz_mod_mpoly_set(rAbar, A, ctx); fmpz_mod_mpoly_set(rBbar, B, ctx); success = 1; goto cleanup; } flint-3.1.3/src/fmpz_mod_mpoly_factor/get_set_lead0.c000066400000000000000000000023211461254215100226540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" void _fmpz_mod_mpoly_get_lead0( fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpolyl_lead_coeff(c, A, 1, ctx); } void _fmpz_mod_mpoly_set_lead0( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong deg; fmpz_mod_mpoly_t t, g; fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(g, ctx); deg = fmpz_mod_mpoly_degree_si(B, 0, ctx); FLINT_ASSERT(deg >= 0); fmpz_mod_mpoly_gen(g, 0, ctx); fmpz_mod_mpoly_pow_ui(g, g, deg, ctx); _fmpz_mod_mpoly_get_lead0(t, B, ctx); fmpz_mod_mpoly_sub(t, c, t, ctx); fmpz_mod_mpoly_mul(t, t, g, ctx); fmpz_mod_mpoly_add(A, B, t, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(g, ctx); } flint-3.1.3/src/fmpz_mod_mpoly_factor/inlines.c000066400000000000000000000007101461254215100216160ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_MPOLY_FACTOR_INLINES_C #include "fmpz_mod_mpoly_factor.h" flint-3.1.3/src/fmpz_mod_mpoly_factor/interp.c000066400000000000000000001062241461254215100214650ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" /* E = A(v = alpha) A is in R[v][x] E is in R[x] */ void fmpz_mod_polyu1n_intp_reduce_sm_poly( fmpz_mod_poly_t E, const fmpz_mod_polyun_t A, const fmpz_t alpha, const fmpz_mod_ctx_t ctx) { fmpz_t v; slong Ai; fmpz_init(v); fmpz_mod_poly_zero(E, ctx); for (Ai = 0; Ai < A->length; Ai++) { fmpz_mod_poly_evaluate_fmpz(v, A->coeffs + Ai, alpha, ctx); fmpz_mod_poly_set_coeff_fmpz(E, A->exps[Ai], v, ctx); } fmpz_clear(v); } /* A = B A, B are in R[X] */ void fmpz_mod_polyu1n_intp_lift_sm_poly( fmpz_mod_polyun_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { slong Bi; slong Blen = B->length; fmpz * Bcoeff = B->coeffs; slong Ai; fmpz_mod_polyun_fit_length(A, Blen, ctx); Ai = 0; for (Bi = Blen - 1; Bi >= 0; Bi--) { if (fmpz_is_zero(Bcoeff + Bi)) continue; FLINT_ASSERT(Ai < A->alloc); fmpz_mod_poly_set_fmpz(A->coeffs + Ai, Bcoeff + Bi, ctx); A->exps[Ai] = Bi; Ai++; } A->length = Ai; } /* F = F + modulus*(A - F(v = alpha)) no assumptions about matching monomials F is in Fp[X][v] A is in Fp[X] it is expected that modulus(alpha) == 1 */ int fmpz_mod_polyu1n_intp_crt_sm_poly( slong * lastdeg, fmpz_mod_polyun_t F, fmpz_mod_polyun_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t modulus, const fmpz_t alpha, const fmpz_mod_ctx_t ctx) { int changed = 0; slong lastlen = 0; fmpz_t v; slong Fi, Ti, Ai; fmpz * Acoeffs = A->coeffs; slong Flen = F->length; fmpz_mod_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; fmpz_mod_poly_struct * Tcoeffs; ulong * Texps; Fi = 0; Ai = fmpz_mod_poly_degree(A, ctx); fmpz_init(v); fmpz_mod_polyun_fit_length(T, Flen + Ai + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; Ti = 0; while (Fi < Flen || Ai >= 0) { FLINT_ASSERT(Ti < T->alloc); if (Fi < Flen) { FLINT_ASSERT(!fmpz_mod_poly_is_zero(Fcoeffs + Fi, ctx)); FLINT_ASSERT(fmpz_mod_poly_degree(Fcoeffs + Fi, ctx) < fmpz_mod_poly_degree(modulus, ctx)); } if (Ai >= 0) { FLINT_ASSERT(!fmpz_is_zero(Acoeffs + Ai)); } if (Fi < Flen && Ai >= 0 && Fexps[Fi] == Ai) { /* F term ok, A term ok */ fmpz_mod_poly_evaluate_fmpz(v, Fcoeffs + Fi, alpha, ctx); fmpz_mod_sub(v, Acoeffs + Ai, v, ctx); changed |= !fmpz_is_zero(v); fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx); Texps[Ti] = Ai; Fi++; do { Ai--; } while (Ai >= 0 && fmpz_is_zero(Acoeffs + Ai)); } else if (Fi < Flen && (Ai < 0 || Fexps[Fi] > Ai)) { /* F term ok, A term missing */ fmpz_mod_poly_evaluate_fmpz(v, Fcoeffs + Fi, alpha, ctx); fmpz_mod_neg(v, v, ctx); changed |= !fmpz_is_zero(v); fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx); Texps[Ti] = Fexps[Fi]; Fi++; } else { FLINT_ASSERT(Ai >= 0 && (Fi >= Flen || Fexps[Fi] < Ai)); /* F term missing, A term ok */ changed = 1; fmpz_mod_poly_scalar_mul_fmpz(Tcoeffs + Ti, modulus, Acoeffs + Ai, ctx); Texps[Ti] = Ai; do { Ai--; } while (Ai >= 0 && fmpz_is_zero(Acoeffs + Ai)); } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeffs + Ti, ctx)); lastlen = FLINT_MAX(lastlen, Tcoeffs[Ti].length); Ti++; } T->length = Ti; fmpz_clear(v); if (changed) fmpz_mod_polyun_swap(T, F); *lastdeg = lastlen - 1; return changed; } void fmpz_mod_polyu1n_interp_reduce_2sm_poly( fmpz_mod_poly_t E, fmpz_mod_poly_t F, const fmpz_mod_polyun_t A, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx) { slong i; fmpz_t u, v; fmpz_init(u); fmpz_init(v); fmpz_mod_poly_zero(E, ctx); fmpz_mod_poly_zero(F, ctx); for (i = 0; i < A->length; i++) { fmpz_mod_poly_eval2_pow(u, v, A->coeffs + i, alphapow, ctx); fmpz_mod_poly_set_coeff_fmpz(E, A->exps[i], u, ctx); fmpz_mod_poly_set_coeff_fmpz(F, A->exps[i], v, ctx); } fmpz_clear(u); fmpz_clear(v); } void fmpz_mod_polyu1n_interp_lift_2sm_poly( slong * lastdeg, fmpz_mod_polyun_t F, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_t alpha, const fmpz_mod_ctx_t ctx) { slong lastlen = 0; fmpz_t u, v, d0, d1, Avalue, Bvalue; slong Fi, Aexp, Bexp; const fmpz * Acoeff = A->coeffs; const fmpz * Bcoeff = B->coeffs; fmpz_mod_poly_struct * Fcoeffs; ulong * Fexps; slong e; fmpz_init(u); fmpz_init(v); fmpz_init(d0); fmpz_init(d1); fmpz_init(Avalue); fmpz_init(Bvalue); Aexp = _fmpz_mod_poly_degree(A); Bexp = _fmpz_mod_poly_degree(B); fmpz_mod_polyun_fit_length(F, FLINT_MAX(Aexp, Bexp) + 1, ctx); Fcoeffs = F->coeffs; Fexps = F->exps; fmpz_set_ui(d0, 2); fmpz_mod_inv(d0, d0, ctx); fmpz_mod_add(d1, alpha, alpha, ctx); fmpz_mod_inv(d1, d1, ctx); Fi = 0; while (Aexp >= 0 || Bexp >= 0) { e = Aexp; fmpz_zero(Avalue); fmpz_zero(Bvalue); if (Aexp == Bexp) { fmpz_set(Avalue, Acoeff + Aexp); fmpz_set(Bvalue, Bcoeff + Bexp); } else if (Aexp > Bexp) { fmpz_set(Avalue, Acoeff + Aexp); } else { FLINT_ASSERT(Bexp > Aexp); e = Bexp; fmpz_set(Bvalue, Bcoeff + Bexp); } FLINT_ASSERT(!fmpz_is_zero(Avalue) || !fmpz_is_zero(Bvalue)); fmpz_mod_add(u, Avalue, Bvalue, ctx); fmpz_mod_sub(v, Avalue, Bvalue, ctx); fmpz_mod_mul(u, u, d0, ctx); fmpz_mod_mul(v, v, d1, ctx); FLINT_ASSERT(Fi < F->alloc); Fexps[Fi] = e; FLINT_ASSERT(!fmpz_is_zero(u) || !fmpz_is_zero(v)); fmpz_mod_poly_fit_length(Fcoeffs + Fi, 2, ctx); fmpz_set(Fcoeffs[Fi].coeffs + 0, u); fmpz_set(Fcoeffs[Fi].coeffs + 1, v); Fcoeffs[Fi].length = 1 + !fmpz_is_zero(v); lastlen = FLINT_MAX(lastlen, Fcoeffs[Fi].length); Fi++; if (e == Aexp) { do { Aexp--; } while (Aexp >= 0 && fmpz_is_zero(Acoeff + Aexp)); } if (e == Bexp) { do { Bexp--; } while (Bexp >= 0 && fmpz_is_zero(Bcoeff + Bexp)); } } F->length = Fi; fmpz_clear(u); fmpz_clear(v); fmpz_clear(d0); fmpz_clear(d1); fmpz_clear(Avalue); fmpz_clear(Bvalue); *lastdeg = lastlen - 1; return; } int fmpz_mod_polyu1n_interp_crt_2sm_poly( slong * lastdeg, fmpz_mod_polyun_t F, fmpz_mod_polyun_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx) { int changed = 0, Finc; slong lastlen = 0; fmpz_mod_poly_struct * Fvalue; fmpz_t u, v, FvalueA, FvalueB; slong Fi, Ti, Aexp, Bexp, e, fexp; const fmpz * Acoeff = A->coeffs; const fmpz * Bcoeff = B->coeffs; slong Flen = F->length; fmpz_mod_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; fmpz_mod_poly_struct * Tcoeffs; ulong * Texps; fmpz_mod_poly_t zero; zero->alloc = 0; zero->length = 0; zero->coeffs = NULL; fmpz_init(u); fmpz_init(v); fmpz_init(FvalueA); fmpz_init(FvalueB); Fi = 0; Aexp = _fmpz_mod_poly_degree(A); Bexp = _fmpz_mod_poly_degree(B); fmpz_mod_polyun_fit_length(T, Flen + FLINT_MAX(Aexp, Bexp) + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; Ti = 0; #if FLINT_WANT_ASSERT fmpz_mod_poly_evaluate_fmpz(u, modulus, alphapow->coeffs + 1, ctx); fmpz_mod_mul(u, u, alphapow->coeffs + 1, ctx); fmpz_mod_add(u, u, u, ctx); FLINT_ASSERT(fmpz_is_one(u)); fmpz_mod_neg(v, alphapow->coeffs + 1, ctx); fmpz_mod_poly_evaluate_fmpz(u, modulus, v, ctx); fmpz_mod_mul(u, u, alphapow->coeffs + 1, ctx); fmpz_mod_add(u, u, u, ctx); FLINT_ASSERT(fmpz_is_one(u)); #endif while (Fi < Flen || Aexp >= 0 || Bexp >= 0) { FLINT_ASSERT(Ti < T->alloc); fexp = e = -WORD(1); if (Fi < Flen) { fexp = e = Fexps[Fi]; FLINT_ASSERT(!fmpz_mod_poly_is_zero(Fcoeffs + Fi, ctx)); FLINT_ASSERT(_fmpz_mod_poly_degree(Fcoeffs + Fi) < _fmpz_mod_poly_degree(modulus)); } if (Aexp >= 0) { e = FLINT_MAX(e, Aexp); FLINT_ASSERT(!fmpz_is_zero(Acoeff + Aexp)); } if (Bexp >= 0) { e = FLINT_MAX(e, Bexp); FLINT_ASSERT(!fmpz_is_zero(Bcoeff + Bexp)); } FLINT_ASSERT(e >= 0); Texps[Ti] = e; Fvalue = zero; fmpz_zero(FvalueA); fmpz_zero(FvalueB); Finc = 0; if (Fi < Flen && e == fexp) { Finc = 1; Fvalue = Fcoeffs + Fi; fmpz_mod_poly_eval2_pow(FvalueA, FvalueB, Fcoeffs + Fi, alphapow, ctx); } if (e == Aexp) { fmpz_mod_sub(FvalueA, FvalueA, Acoeff + Aexp, ctx); } if (e == Bexp) { fmpz_mod_sub(FvalueB, FvalueB, Bcoeff + Bexp, ctx); } fmpz_mod_sub(u, FvalueB, FvalueA, ctx); fmpz_mod_add(v, FvalueB, FvalueA, ctx); fmpz_mod_mul(v, v, alphapow->coeffs + 1, ctx); fmpz_mod_neg(v, v, ctx); changed |= !fmpz_is_zero(u) || !fmpz_is_zero(v); fmpz_mod_poly_addmul_linear(Tcoeffs + Ti, Fvalue, modulus, u, v, ctx); FLINT_ASSERT(Tcoeffs[Ti].length > 0); lastlen = FLINT_MAX(lastlen, Tcoeffs[Ti].length); Ti++; Fi += Finc; if (e == Aexp) { do { Aexp--; } while (Aexp >= 0 && fmpz_is_zero(Acoeff + Aexp)); } if (e == Bexp) { do { Bexp--; } while (Bexp >= 0 && fmpz_is_zero(Bcoeff + Bexp)); } } T->length = Ti; fmpz_clear(u); fmpz_clear(v); fmpz_clear(FvalueA); fmpz_clear(FvalueB); if (changed) fmpz_mod_polyun_swap(T, F); *lastdeg = lastlen - 1; return changed; } /* E = A(v = alpha) A is in R[X][v] E is in R[X] */ void fmpz_mod_mpolyn_interp_reduce_sm_poly( fmpz_mod_poly_t E, const fmpz_mod_mpolyn_t A, const fmpz_t alpha, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_t v; slong Ai, Alen, k; fmpz_mod_poly_struct * Acoeff; ulong * Aexp; slong N, off, shift; fmpz_init(v); N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); Acoeff = A->coeffs; Aexp = A->exps; Alen = A->length; Ai = 0; fmpz_mod_poly_zero(E, ctx->ffinfo); for (Ai = 0; Ai < Alen; Ai++) { fmpz_mod_poly_evaluate_fmpz(v, Acoeff + Ai, alpha, ctx->ffinfo); k = (Aexp + N*Ai)[off] >> shift; fmpz_mod_poly_set_coeff_fmpz(E, k, v, ctx->ffinfo); } fmpz_clear(v); } /* A = B A, B are in R[X] */ void fmpz_mod_mpolyn_interp_lift_sm_poly( fmpz_mod_mpolyn_t A, const fmpz_mod_poly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong Bi; slong Blen = fmpz_mod_poly_length(B, ctx->ffinfo); fmpz * Bcoeff = B->coeffs; fmpz_mod_poly_struct * Acoeff; ulong * Aexp; slong Ai; slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fmpz_mod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; Ai = 0; for (Bi = Blen - 1; Bi >= 0; Bi--) { if (!fmpz_is_zero(Bcoeff + Bi)) { FLINT_ASSERT(Ai < A->alloc); fmpz_mod_poly_set_fmpz(Acoeff + Ai, Bcoeff + Bi, ctx->ffinfo); mpoly_monomial_zero(Aexp + N*Ai, N); (Aexp + N*Ai)[off] = Bi << shift; Ai++; } } A->length = Ai; } /* F = F + modulus*(A - F(v = alpha)) no assumptions about matching monomials F is in Fp[X][v] A is in Fp[X] it is expected that modulus(alpha) == 1 */ int fmpz_mod_mpolyn_interp_crt_sm_poly( slong * lastdeg_, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t modulus, const fmpz_t alpha, const fmpz_mod_mpoly_ctx_t ctx) { int changed = 0; slong lastdeg = -WORD(1); fmpz_t u, v; slong Fi, Ti, Ai; fmpz * Acoeff = A->coeffs; slong Flen = F->length; fmpz_mod_poly_struct * Fcoeff = F->coeffs; ulong * Fexp = F->exps; fmpz_mod_poly_struct * Tcoeff; ulong * Texp; fmpz_mod_poly_t tp; slong N, off, shift; N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, F->bits, ctx->minfo); Fi = 0; Ai = fmpz_mod_poly_degree(A, ctx->ffinfo); fmpz_init(u); fmpz_init(v); fmpz_mod_poly_init(tp, ctx->ffinfo); fmpz_mod_mpolyn_fit_length(T, Flen + Ai + 1, ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = 0; while (Fi < Flen || Ai >= 0) { FLINT_ASSERT(Ti < T->alloc); if (Fi < Flen) { FLINT_ASSERT(!fmpz_mod_poly_is_zero(Fcoeff + Fi, ctx->ffinfo)); FLINT_ASSERT(fmpz_mod_poly_degree(Fcoeff + Fi, ctx->ffinfo) < fmpz_mod_poly_degree(modulus, ctx->ffinfo)); } if (Ai >= 0) { FLINT_ASSERT(!fmpz_is_zero(Acoeff + Ai)); } mpoly_monomial_zero(Texp + N*Ti, N); if (Fi < Flen && Ai >= 0 && ((Fexp + N*Fi)[off]>>shift) == Ai) { /* F term ok, A term ok */ fmpz_mod_poly_evaluate_fmpz(u, Fcoeff + Fi, alpha, ctx->ffinfo); fmpz_mod_sub(v, Acoeff + Ai, u, ctx->ffinfo); if (!fmpz_is_zero(v)) { changed = 1; fmpz_mod_poly_scalar_mul_fmpz(tp, modulus, v, ctx->ffinfo); fmpz_mod_poly_add(Tcoeff + Ti, Fcoeff + Fi, tp, ctx->ffinfo); } else { fmpz_mod_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->ffinfo); } (Texp + N*Ti)[off] = Ai << shift; Fi++; do { Ai--; } while (Ai >= 0 && fmpz_is_zero(Acoeff + Ai)); } else if (Fi < Flen && (Ai < 0 || ((Fexp + N*Fi)[off]>>shift) > Ai)) { /* F term ok, A term missing */ fmpz_mod_poly_evaluate_fmpz(v, Fcoeff + Fi, alpha, ctx->ffinfo); if (!fmpz_is_zero(v)) { changed = 1; fmpz_mod_poly_scalar_mul_fmpz(tp, modulus, v, ctx->ffinfo); fmpz_mod_poly_sub(Tcoeff + Ti, Fcoeff + Fi, tp, ctx->ffinfo); } else { fmpz_mod_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->ffinfo); } (Texp + N*Ti)[off] = (Fexp + N*Fi)[off]; Fi++; } else if (Ai >= 0 && (Fi >= Flen || ((Fexp + N*Fi)[off]>>shift) < Ai)) { /* F term missing, A term ok */ changed = 1; fmpz_mod_poly_scalar_mul_fmpz(Tcoeff + Ti, modulus, Acoeff + Ai, ctx->ffinfo); (Texp + N*Ti)[off] = Ai << shift; do { Ai--; } while (Ai >= 0 && fmpz_is_zero(Acoeff + Ai)); } else { FLINT_ASSERT(0); } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeff + Ti, ctx->ffinfo)); lastdeg = FLINT_MAX(lastdeg, fmpz_mod_poly_degree(Tcoeff + Ti, ctx->ffinfo)); Ti++; } T->length = Ti; fmpz_clear(u); fmpz_clear(v); fmpz_mod_poly_clear(tp, ctx->ffinfo); if (changed) { fmpz_mod_mpolyn_swap(T, F, ctx); } *lastdeg_ = lastdeg; return changed; } void fmpz_mod_mpolyn_interp_reduce_2sm_mpolyn( fmpz_mod_mpolyn_t E, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t A, slong var, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong offset, shift, k; ulong mask; fmpz_t e, f; fmpz_mod_poly_struct * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong Alen = A->length; slong Ai; fmpz_mod_poly_struct * Ecoeff; ulong * Eexp; slong Ei; fmpz_mod_poly_struct * Fcoeff; ulong * Fexp; slong Fi; fmpz_init(e); fmpz_init(f); FLINT_ASSERT(var > 0); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); Ecoeff = E->coeffs; Eexp = E->exps; Ei = 0; Fcoeff = F->coeffs; Fexp = F->exps; Fi = 0; for (Ai = 0; Ai < Alen; Ai++) { fmpz_mod_poly_eval2_pow(e, f, Acoeff + Ai, alphapow, ctx->ffinfo); k = ((Aexp + N*Ai)[offset] >> shift) & mask; if (!fmpz_is_zero(e)) { if (Ei > 0 && mpoly_monomial_equal_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ fmpz_mod_poly_set_coeff_fmpz(Ecoeff + Ei - 1, k, e, ctx->ffinfo); } else { FLINT_ASSERT(Ei == 0 || mpoly_monomial_gt_nomask_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Ei >= E->alloc) { fmpz_mod_mpolyn_fit_length(E, Ei + 1, ctx); Ecoeff = E->coeffs; Eexp = E->exps; } mpoly_monomial_set_extra(Eexp + N*Ei, Aexp + N*Ai, N, offset, -(k << shift)); fmpz_mod_poly_zero(Ecoeff + Ei, ctx->ffinfo); fmpz_mod_poly_set_coeff_fmpz(Ecoeff + Ei, k, e, ctx->ffinfo); Ei++; } } if (!fmpz_is_zero(f)) { if (Fi > 0 && mpoly_monomial_equal_extra(Fexp + N*(Fi - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ fmpz_mod_poly_set_coeff_fmpz(Fcoeff + Fi - 1, k, f, ctx->ffinfo); } else { FLINT_ASSERT(Fi == 0 || mpoly_monomial_gt_nomask_extra(Fexp + N*(Fi - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Fi >= F->alloc) { fmpz_mod_mpolyn_fit_length(F, Fi + 1, ctx); Fcoeff = F->coeffs; Fexp = F->exps; } mpoly_monomial_set_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, -(k << shift)); fmpz_mod_poly_zero(Fcoeff + Fi, ctx->ffinfo); fmpz_mod_poly_set_coeff_fmpz(Fcoeff + Fi, k, f, ctx->ffinfo); Fi++; } } } E->length = Ei; F->length = Fi; fmpz_clear(e); fmpz_clear(f); } void fmpz_mod_mpolyn_interp_lift_2sm_mpolyn( slong * lastdeg, fmpz_mod_mpolyn_t T, fmpz_mod_mpolyn_t A, fmpz_mod_mpolyn_t B, slong var, const fmpz_t alpha, const fmpz_mod_mpoly_ctx_t ctx) { slong lastlen = 0; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift; fmpz_mod_poly_struct * Tcoeff; ulong * Texp; slong Ti; fmpz_mod_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai, ai; fmpz_mod_poly_struct * Bcoeff = B->coeffs; slong Blen = B->length; ulong * Bexp = B->exps; slong Bi, bi; fmpz zero0 = 0; fmpz * Avalue, * Bvalue; fmpz_t u, v, FvalueA, FvalueB; int cmp; fmpz_t d0; fmpz_init(d0); fmpz_mod_add(d0, alpha, alpha, ctx->ffinfo); fmpz_mod_inv(d0, d0, ctx->ffinfo); fmpz_init(u); fmpz_init(v); fmpz_init(FvalueA); fmpz_init(FvalueB); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); fmpz_mod_mpolyn_fit_length(T, FLINT_MAX(Alen, Blen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = Ai = Bi = 0; ai = (Ai >= Alen) ? 0 : A->coeffs[Ai].length - 1; bi = (Bi >= Blen) ? 0 : B->coeffs[Bi].length - 1; while (Ai < Alen || Bi < Blen) { if (Ti >= T->alloc) { slong extra = FLINT_MAX(Alen - Ai, Blen - Bi); fmpz_mod_mpolyn_fit_length(T, Ti + extra + 1, ctx); Tcoeff = T->coeffs; Texp = T->exps; } FLINT_ASSERT(Ai >= Alen || !fmpz_is_zero((Acoeff + Ai)->coeffs + ai)); FLINT_ASSERT(Bi >= Blen || !fmpz_is_zero((Bcoeff + Bi)->coeffs + bi)); Avalue = &zero0; if (Ai < Alen) { Avalue = (Acoeff + Ai)->coeffs + ai; mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, ai << shift); } Bvalue = &zero0; if (Bi < Blen) { cmp = (Avalue == &zero0) ? -1 : mpoly_monomial_cmp_nomask_extra( Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); if (cmp <= 0) { Bvalue = (Bcoeff + Bi)->coeffs + bi; } if (cmp < 0) { Avalue = &zero0; mpoly_monomial_set_extra(Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); } } fmpz_mod_neg(FvalueA, Avalue, ctx->ffinfo); fmpz_mod_neg(FvalueB, Bvalue, ctx->ffinfo); fmpz_mod_sub(u, FvalueB, FvalueA, ctx->ffinfo); fmpz_mod_add(v, FvalueB, FvalueA, ctx->ffinfo); fmpz_mod_mul(v, alpha, v, ctx->ffinfo); fmpz_mod_neg(v, v, ctx->ffinfo); FLINT_ASSERT(!fmpz_is_zero(u) || !fmpz_is_zero(v)); fmpz_mod_poly_zero(Tcoeff + Ti, ctx->ffinfo); fmpz_mod_mul(u, u, d0, ctx->ffinfo); fmpz_mod_mul(v, v, d0, ctx->ffinfo); fmpz_mod_poly_set_coeff_fmpz(Tcoeff + Ti, 0, v, ctx->ffinfo); fmpz_mod_poly_set_coeff_fmpz(Tcoeff + Ti, 1, u, ctx->ffinfo); if (Avalue != &zero0) { do { ai--; } while (ai >= 0 && fmpz_is_zero((Acoeff + Ai)->coeffs + ai)); if (ai < 0) { Ai++; if (Ai < Alen) ai = A->coeffs[Ai].length - 1; } } if (Bvalue != &zero0) { do { bi--; } while (bi >= 0 && fmpz_is_zero((Bcoeff + Bi)->coeffs + bi)); if (bi < 0) { Bi++; if (Bi < Blen) bi = B->coeffs[Bi].length - 1; } } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeff + Ti, ctx->ffinfo)); lastlen = FLINT_MAX(lastlen, Tcoeff[Ti].length); Ti++; } T->length = Ti; *lastdeg = lastlen - 1; FLINT_ASSERT(fmpz_mod_mpolyn_is_canonical(T, ctx)); fmpz_clear(d0); fmpz_clear(u); fmpz_clear(v); fmpz_clear(FvalueA); fmpz_clear(FvalueB); return; } int fmpz_mod_mpolyn_interp_crt_2sm_mpolyn( slong * lastdeg, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t T, fmpz_mod_mpolyn_t A, fmpz_mod_mpolyn_t B, slong var, fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx) { slong lastlen = 0; int changed = 0; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift; fmpz_mod_poly_t zero; fmpz zero0 = 0; fmpz_mod_poly_struct * Tcoeff; ulong * Texp; slong Ti; fmpz_mod_poly_struct * Fcoeff = F->coeffs; slong Flen = F->length; ulong * Fexp = F->exps; slong Fi; fmpz_mod_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai, ai; fmpz_mod_poly_struct * Bcoeff = B->coeffs; slong Blen = B->length; ulong * Bexp = B->exps; slong Bi, bi; fmpz_mod_poly_struct * Fvalue; fmpz * Avalue, * Bvalue; fmpz_t u, v, FvalueA, FvalueB; int texp_set, cmp; FLINT_ASSERT(fmpz_mod_poly_degree(modulus, ctx->ffinfo) > 0); zero->coeffs = NULL; zero->alloc = 0; zero->length = 0; fmpz_init(u); fmpz_init(v); fmpz_init(FvalueA); fmpz_init(FvalueB); #if FLINT_WANT_ASSERT fmpz_mod_poly_evaluate_fmpz(u, modulus, alphapow->coeffs + 1, ctx->ffinfo); fmpz_mod_mul(u, u, alphapow->coeffs + 1, ctx->ffinfo); fmpz_mod_add(u, u, u, ctx->ffinfo); FLINT_ASSERT(fmpz_is_one(u)); fmpz_mod_neg(v, alphapow->coeffs + 1, ctx->ffinfo); fmpz_mod_poly_evaluate_fmpz(u, modulus, v, ctx->ffinfo); fmpz_mod_mul(u, u, alphapow->coeffs + 1, ctx->ffinfo); fmpz_mod_add(u, u, u, ctx->ffinfo); FLINT_ASSERT(fmpz_is_one(u)); #endif FLINT_ASSERT(fmpz_mod_mpolyn_is_canonical(A, ctx)); FLINT_ASSERT(fmpz_mod_mpolyn_is_canonical(B, ctx)); FLINT_ASSERT(fmpz_mod_mpolyn_is_canonical(F, ctx)); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); FLINT_ASSERT(F->bits == A->bits); FLINT_ASSERT(A->bits <= FLINT_BITS); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Flen = F->length; fmpz_mod_mpolyn_fit_length(T, FLINT_MAX(Flen, Alen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = Fi = Ai = Bi = 0; ai = (Ai >= Alen) ? 0 : A->coeffs[Ai].length - 1; bi = (Bi >= Blen) ? 0 : B->coeffs[Bi].length - 1; while (Fi < Flen || Ai < Alen || Bi < Blen) { if (Ti >= T->alloc) { slong extra = Flen - Fi; extra = FLINT_MAX(extra, Alen - Ai); extra = FLINT_MAX(extra, Blen - Bi); fmpz_mod_mpolyn_fit_length(T, Ti + extra + 1, ctx); Tcoeff = T->coeffs; Texp = T->exps; } FLINT_ASSERT(Fi >= Flen || (Fcoeff + Fi)->length != 0); FLINT_ASSERT(Ai >= Alen || !fmpz_is_zero((Acoeff + Ai)->coeffs + ai)); FLINT_ASSERT(Bi >= Blen || !fmpz_is_zero((Bcoeff + Bi)->coeffs + bi)); Fvalue = zero; texp_set = 0; if (Fi < Flen) { Fvalue = Fcoeff + Fi; texp_set = 1; mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); } Avalue = &zero0; if (Ai < Alen) { cmp = (!texp_set) ? -1 : mpoly_monomial_cmp_nomask_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, ai << shift); if (cmp <= 0) { Avalue = (Acoeff + Ai)->coeffs + ai; } if (cmp < 0) { Fvalue = zero; texp_set = 1; mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, ai << shift); } } Bvalue = &zero0; if (Bi < Blen) { cmp = (!texp_set) ? -1 : mpoly_monomial_cmp_nomask_extra( Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); if (cmp <= 0) { Bvalue = (Bcoeff + Bi)->coeffs + bi; } if (cmp < 0) { Fvalue = zero; Avalue = &zero0; texp_set = 1; mpoly_monomial_set_extra(Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); } } FLINT_ASSERT(texp_set); fmpz_mod_poly_eval2_pow(FvalueA, FvalueB, Fvalue, alphapow, ctx->ffinfo); fmpz_mod_sub(FvalueA, FvalueA, Avalue, ctx->ffinfo); fmpz_mod_sub(FvalueB, FvalueB, Bvalue, ctx->ffinfo); fmpz_mod_sub(u, FvalueB, FvalueA, ctx->ffinfo); fmpz_mod_add(v, FvalueB, FvalueA, ctx->ffinfo); fmpz_mod_mul(v, alphapow->coeffs + 1, v, ctx->ffinfo); fmpz_mod_neg(v, v, ctx->ffinfo); changed |= !fmpz_is_zero(u) || !fmpz_is_zero(v); fmpz_mod_poly_addmul_linear(Tcoeff + Ti, Fvalue, modulus, u, v, ctx->ffinfo); Fi += (Fvalue != zero); if (Avalue != &zero0) { do { ai--; } while (ai >= 0 && fmpz_is_zero((Acoeff + Ai)->coeffs + ai)); if (ai < 0) { Ai++; if (Ai < Alen) ai = A->coeffs[Ai].length - 1; } } if (Bvalue != &zero0) { do { bi--; } while (bi >= 0 && fmpz_is_zero((Bcoeff + Bi)->coeffs + bi)); if (bi < 0) { Bi++; if (Bi < Blen) bi = B->coeffs[Bi].length - 1; } } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeff + Ti, ctx->ffinfo)); lastlen = FLINT_MAX(lastlen, Tcoeff[Ti].length); Ti++; } T->length = Ti; *lastdeg = lastlen - 1; if (changed) fmpz_mod_mpolyn_swap(T, F, ctx); fmpz_clear(u); fmpz_clear(v); fmpz_clear(FvalueA); fmpz_clear(FvalueB); FLINT_ASSERT(fmpz_mod_mpolyn_is_canonical(F, ctx)); return changed; } void fmpz_mod_mpolyn_interp_lift_sm_mpoly( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N; fmpz_mod_poly_struct * Acoeff; const fmpz * Bcoeff; ulong * Aexp, * Bexp; slong Blen; FLINT_ASSERT(A->bits == B->bits); Blen = B->length; fmpz_mod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < Blen; i++) { fmpz_mod_poly_set_fmpz(Acoeff + i, Bcoeff + i, ctx->ffinfo); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } A->length = Blen; } int fmpz_mod_mpolyn_interp_crt_sm_mpoly( slong * lastdeg, fmpz_mod_mpolyn_t F, fmpz_mod_mpolyn_t T, fmpz_mod_mpoly_t A, fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx) { slong lastlen = 0; int changed = 0; slong i, j, k; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong Flen = F->length, Alen = A->length; ulong * Fexp = F->exps, * Aexp = A->exps; ulong * Texp; fmpz * Acoeff = A->coeffs; fmpz_mod_poly_struct * Fcoeff = F->coeffs; fmpz_mod_poly_struct * Tcoeff; fmpz_t v; FLINT_ASSERT(F->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); fmpz_mod_mpolyn_fit_length(T, Flen + Alen, ctx); Texp = T->exps; Tcoeff = T->coeffs; i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || mpoly_monomial_gt_nomask(Fexp + N*i, Aexp + N*j, N))) { FLINT_ASSERT(!fmpz_mod_poly_is_zero(Fcoeff + i, ctx->ffinfo)); FLINT_ASSERT(fmpz_mod_poly_degree(Fcoeff + i, ctx->ffinfo) < fmpz_mod_poly_degree(modulus, ctx->ffinfo)); /* F term ok, A term missing */ fmpz_mod_poly_eval_pow(v, Fcoeff + i, alphapow, ctx->ffinfo); if (!fmpz_is_zero(v)) { changed = 1; fmpz_mod_neg(v, v, ctx->ffinfo); fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeff + k, Fcoeff + i, modulus, v, ctx->ffinfo); } else { fmpz_mod_poly_set(Tcoeff + k, Fcoeff + i, ctx->ffinfo); } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeff + k, ctx->ffinfo)); lastlen = FLINT_MAX(lastlen, Tcoeff[k].length); mpoly_monomial_set(Texp + N*k, Fexp + N*i, N); k++; i++; } else if (j < Alen && (i >= Flen || mpoly_monomial_lt_nomask(Fexp + N*i, Aexp + N*j, N))) { /* F term missing, A term ok */ FLINT_ASSERT(!fmpz_is_zero(Acoeff + j)); changed = 1; fmpz_mod_poly_scalar_mul_fmpz(Tcoeff + k, modulus, Acoeff + j, ctx->ffinfo); lastlen = FLINT_MAX(lastlen, Tcoeff[k].length); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; j++; } else if (i < Flen && j < Alen && mpoly_monomial_equal(Fexp + N*i, Aexp + N*j, N)) { FLINT_ASSERT(!fmpz_mod_poly_is_zero(Fcoeff + i, ctx->ffinfo)); FLINT_ASSERT(fmpz_mod_poly_degree(Fcoeff + i, ctx->ffinfo) < fmpz_mod_poly_degree(modulus, ctx->ffinfo)); /* F term ok, A term ok */ fmpz_mod_poly_eval_pow(v, Fcoeff + i, alphapow, ctx->ffinfo); fmpz_mod_sub(v, Acoeff + j, v, ctx->ffinfo); if (!fmpz_is_zero(v)) { changed = 1; fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeff + k, Fcoeff + i, modulus, v, ctx->ffinfo); } else { fmpz_mod_poly_set(Tcoeff + k, Fcoeff + i, ctx->ffinfo); } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeff + k, ctx->ffinfo)); lastlen = FLINT_MAX(lastlen, Tcoeff[k].length); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; i++; j++; } else { FLINT_ASSERT(0); } } T->length = k; *lastdeg = lastlen - 1; if (changed) fmpz_mod_mpolyn_swap(T, F, ctx); return changed; } int fmpz_mod_mpolyn_interp_mcrt_sm_mpoly( slong * lastdeg, fmpz_mod_mpolyn_t F, const fmpz_mod_mpoly_t A, const fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_mpoly_ctx_t ctx) { slong lastlen = 0; int changed = 0; slong i; fmpz_t v; fmpz * Acoeff = A->coeffs; slong Flen = F->length; FLINT_ASSERT(Flen == A->length); fmpz_init(v); for (i = 0; i < Flen; i++) { /* F term ok, A term ok */ fmpz_mod_poly_eval_pow(v, F->coeffs + i, alphapow, ctx->ffinfo); fmpz_mod_sub(v, Acoeff + i, v, ctx->ffinfo); if (!fmpz_is_zero(v)) { changed = 1; fmpz_mod_poly_scalar_addmul_fmpz_mod(F->coeffs + i, F->coeffs + i, modulus, v, ctx->ffinfo); } lastlen = FLINT_MAX(lastlen, F->coeffs[i].length); } fmpz_clear(v); *lastdeg = lastlen - 1; return changed; } flint-3.1.3/src/fmpz_mod_mpoly_factor/io.c000066400000000000000000000141501461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" /* printing *******************************************************************/ void fmpz_mod_polyu2n_print_pretty( const fmpz_mod_polyun_t A, const char * var0, const char * var1, const char * varlast, const fmpz_mod_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; flint_printf("("); fmpz_mod_poly_print_pretty(A->coeffs + i, varlast, ctx); flint_printf(")*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 1, 2), var1, extract_exp(A->exps[i], 0, 2)); } if (first) flint_printf("0"); } void fmpz_mod_polyu1n_print_pretty( const fmpz_mod_polyun_t A, const char * var0, const char * varlast, const fmpz_mod_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); fmpz_mod_poly_print_pretty(A->coeffs + i, varlast, ctx); flint_printf(")*%s^%wu", var0, A->exps[i]); } if (first) flint_printf("0"); } void fmpz_mod_polyu3n_print_pretty( const fmpz_mod_polyun_t A, const char * var0, const char * var1, const char * var2, const char * varlast, const fmpz_mod_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); fmpz_mod_poly_print_pretty(A->coeffs + i, varlast, ctx); flint_printf(")*%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } void fmpz_mod_mpoly_factor_print_pretty( const fmpz_mod_mpoly_factor_t f, const char ** vars, const fmpz_mod_mpoly_ctx_t ctx) { slong i; fmpz_print(f->constant); for (i = 0; i < f->num; i++) { flint_printf("\n*(", i); fmpz_mod_mpoly_print_pretty(f->poly + i, vars, ctx); flint_printf(")^"); fmpz_print(f->exp + i); } } void fmpz_mod_mpolyu_print_pretty( const fmpz_mod_mpolyu_t poly, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (poly->length == 0) flint_printf("0"); for (i = 0; i < poly->length; i++) { if (i != 0) flint_printf(" + "); flint_printf("("); fmpz_mod_mpoly_print_pretty(poly->coeffs + i,x,ctx); flint_printf(")*X^%wd",poly->exps[i]); } } void fmpz_mod_bpoly_print_pretty( const fmpz_mod_bpoly_t A, const char * xvar, const char * yvar, const fmpz_mod_ctx_t ctx) { slong i; int first; first = 1; for (i = A->length - 1; i >= 0; i--) { if (fmpz_mod_poly_is_zero(A->coeffs + i, ctx)) continue; if (!first) flint_printf(" + "); first = 0; flint_printf("("); fmpz_mod_poly_print_pretty(A->coeffs + i, yvar, ctx); flint_printf(")*%s^%wd", xvar, i); } if (first) flint_printf("0"); } void fmpz_mod_polyu3_print_pretty( const fmpz_mod_polyu_t A, const char * var0, const char * var1, const char * var2, const fmpz_mod_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; fmpz_print(A->coeffs + i); flint_printf("*%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } void fmpz_mod_mpolyv_print_pretty( const fmpz_mod_mpolyv_t poly, const char ** x, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < poly->length; i++) { flint_printf("coeff[%wd]: ", i); fmpz_mod_mpoly_print_pretty(poly->coeffs + i, x, ctx); flint_printf("\n"); } } void fmpz_mod_mpolyn_print_pretty( const fmpz_mod_mpolyn_t A, const char ** x_in, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_poly_struct * coeff = A->coeffs; slong len = A->length; ulong * exp = A->exps; slong bits = A->bits; slong i, j, N; fmpz * exponents; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { flint_printf("0"); return; } N = mpoly_words_per_exp(bits, ctx->minfo); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(ctx->minfo->nvars*sizeof(char *)); for (i = 0; i < ctx->minfo->nvars; i++) { x[i] = (char *) TMP_ALLOC(((FLINT_BITS+4)/3)*sizeof(char)); flint_sprintf(x[i], "x%wd", i+1); } } exponents = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(exponents + i); for (i = 0; i < len; i++) { if (i > 0) { printf(" + "); } printf("("); fmpz_mod_poly_print_pretty(coeff + i, "v", ctx->ffinfo); printf(")"); mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, ctx->minfo); for (j = 0; j < ctx->minfo->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, WORD(1)); if (cmp > 0) { printf("*%s^", x[j]); fmpz_print(exponents + j); } else if (cmp == 0) { printf("*%s", x[j]); } } } for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(exponents + i); TMP_END; } flint-3.1.3/src/fmpz_mod_mpoly_factor/irred_smprime_wang.c000066400000000000000000000224001461254215100240320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_mpoly_factor.h" /* return 1: success 0: failed -1: exception (large exps) */ int fmpz_mod_mpoly_factor_irred_smprime_wang( fmpz_mod_mpolyv_t fac, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_factor_t lcAfac, const fmpz_mod_mpoly_t lcA, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state) { int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; fmpz * alpha; fmpz_mod_poly_struct * alphabetas; fmpz_mod_mpoly_struct * Aevals; slong * degs, * degeval; fmpz_mod_mpolyv_t tfac; fmpz_mod_mpoly_t t, Acopy; fmpz_mod_mpoly_struct * newA; fmpz_mod_poly_t Abfc; fmpz_mod_bpoly_t Ab; fmpz_mod_tpoly_t Abfp; fmpz_mod_mpoly_t m, mpow; fmpz_mod_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(fmpz_is_one(A->coeffs + 0)); FLINT_ASSERT(A->bits <= FLINT_BITS); fmpz_mod_mpoly_init(Acopy, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_mod_mpoly_init(mpow, ctx); fmpz_mod_mpolyv_init(new_lcs, ctx); fmpz_mod_mpolyv_init(lc_divs, ctx); fmpz_mod_poly_init(Abfc, ctx->ffinfo); fmpz_mod_tpoly_init(Abfp, ctx->ffinfo); fmpz_mod_bpoly_init(Ab, ctx->ffinfo); degs = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); alpha = _fmpz_vec_init(n); alphabetas = FLINT_ARRAY_ALLOC(n, fmpz_mod_poly_struct); Aevals = FLINT_ARRAY_ALLOC(n, fmpz_mod_mpoly_struct); for (i = 0; i < n; i++) { fmpz_mod_poly_init(alphabetas + i, ctx->ffinfo); fmpz_mod_mpoly_init(Aevals + i, ctx); } fmpz_mod_mpolyv_init(tfac, ctx); fmpz_mod_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; fmpz_mod_mpoly_degrees_si(degs, A, ctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) fmpz_mod_rand_not_zero(alpha + i, state, ctx->ffinfo); /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fmpz_mod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } /* make sure univar is squarefree */ fmpz_mod_mpoly_derivative(t, Aevals + 0, 0, ctx); if (!fmpz_mod_mpoly_gcd(t, t, Aevals + 0, ctx)) { success = -1; goto cleanup; } if (!fmpz_mod_mpoly_is_one(t, ctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 10) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { fmpz_mod_poly_fit_length(alphabetas + i, alphabetas_length, ctx->ffinfo); fmpz_set(alphabetas[i].coeffs + 0, alpha + i); for (j = 1; j < alphabetas_length; j++) fmpz_mod_rand(alphabetas[i].coeffs + j, state, ctx->ffinfo); _fmpz_mod_poly_set_length(alphabetas + i, alphabetas_length); _fmpz_mod_poly_normalise(alphabetas + i); } _fmpz_mod_mpoly_eval_rest_to_fmpz_mod_bpoly(Ab, A, alphabetas, ctx); success = fmpz_mod_bpoly_factor_smprime(Abfc, Abfp, Ab, 0, ctx->ffinfo); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { fmpz_mod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } fmpz_mod_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = fmpz_mod_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) fmpz_mod_mpoly_one(lc_divs->coeffs + i, ctx); } success = fmpz_mod_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = fmpz_mod_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } fmpz_mod_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fmpz_mod_mpoly_is_one(mpow, ctx)) { newA = (fmpz_mod_mpoly_struct *) A; } else { newA = Acopy; fmpz_mod_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } fmpz_mod_mpoly_degrees_si(degs, newA, ctx); fmpz_mod_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(t, mpow, i + 1, alpha + i, ctx); fmpz_mod_mpoly_swap(t, mpow, ctx); fmpz_mod_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); fmpz_mod_mpoly_repack_bits_inplace(Aevals + i, newA->bits, ctx); } fmpz_mod_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fmpz_mod_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mod_mpoly_evaluate_one_fmpz(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fmpz_mod_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { fmpz_t q; fmpz_init(q); FLINT_ASSERT(fmpz_mod_mpoly_is_fmpz(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fmpz_mod_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _fmpz_mod_mpoly_set_fmpz_mod_bpoly_var1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); fmpz_mod_inv(q, fac->coeffs[i].coeffs + 0, ctx->ffinfo); fmpz_mod_mul(q, q, new_lcs->coeffs[0*r + i].coeffs + 0, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(fac->coeffs + i, fac->coeffs + i, q, ctx); fmpz_clear(q); } fmpz_mod_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _fmpz_mod_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } success = fmpz_mod_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); if (!success) goto next_alphabetas; fmpz_mod_mpolyv_swap(tfac, fac, ctx); } if (!fmpz_mod_mpoly_is_fmpz(m, ctx)) { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!fmpz_mod_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fmpz_mod_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } } for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); fmpz_mod_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); } success = 1; cleanup: fmpz_mod_mpolyv_clear(new_lcs, ctx); fmpz_mod_mpolyv_clear(lc_divs, ctx); fmpz_mod_poly_clear(Abfc, ctx->ffinfo); fmpz_mod_tpoly_clear(Abfp, ctx->ffinfo); fmpz_mod_bpoly_clear(Ab, ctx->ffinfo); for (i = 0; i < n; i++) { fmpz_mod_mpoly_clear(Aevals + i, ctx); fmpz_mod_poly_clear(alphabetas + i, ctx->ffinfo); } flint_free(alphabetas); _fmpz_vec_clear(alpha, n); flint_free(Aevals); flint_free(degs); flint_free(degeval); fmpz_mod_mpolyv_clear(tfac, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(Acopy, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { fmpz_mod_mpoly_t prod; fmpz_mod_mpoly_init(prod, ctx); fmpz_mod_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) fmpz_mod_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(prod, A, ctx)); fmpz_mod_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000266471461254215100253030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_poly_factor.h" #include "fmpz_mod_mpoly_factor.h" /* return: 1: success 0: lift is impossible -1: failed, don't try again */ static int _try_lift( fmpz_mod_mpolyv_t qfac, const fmpz_mod_mpoly_t q, const fmpz_mod_mpolyv_t pfac, const fmpz_mod_mpoly_t p, slong m, const fmpz * alphas, slong n, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i; slong * newdeg; fmpz_mod_mpoly_t lcq, lcp, t, newq; FLINT_ASSERT(pfac->length > 1); newdeg = FLINT_ARRAY_ALLOC(n + 1, slong); fmpz_mod_mpoly_init(lcq, ctx); fmpz_mod_mpoly_init(lcp, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(newq, ctx); #if FLINT_WANT_ASSERT fmpz_mod_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fmpz_mod_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(t, p, ctx)); #endif _fmpz_mod_mpoly_get_lead0(lcq, q, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(lcp, lcq, m, alphas + m - 1, ctx); FLINT_ASSERT(lcp->length > 0); fmpz_mod_mpoly_pow_ui(t, lcq, pfac->length - 1, ctx); fmpz_mod_mpoly_mul(newq, q, t, ctx); if (newq->bits > FLINT_BITS) { success = -1; goto cleanup; } fmpz_mod_mpoly_degrees_si(newdeg, newq, ctx); fmpz_mod_mpolyv_fit_length(qfac, pfac->length, ctx); qfac->length = pfac->length; for (i = 0; i < pfac->length; i++) { _fmpz_mod_mpoly_get_lead0(t, pfac->coeffs + i, ctx); success = fmpz_mod_mpoly_divides(t, lcp, t, ctx); FLINT_ASSERT(success); fmpz_mod_mpoly_mul(qfac->coeffs + i, pfac->coeffs + i, t, ctx); _fmpz_mod_mpoly_set_lead0(qfac->coeffs + i, qfac->coeffs + i, lcq, ctx); } success = fmpz_mod_mpoly_hlift(m, qfac->coeffs, qfac->length, alphas, newq, newdeg, ctx); if (!success) goto cleanup; for (i = 0; i < qfac->length; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(qfac->coeffs[i].bits <= FLINT_BITS); if (!fmpz_mod_mpolyl_content(t, qfac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fmpz_mod_mpoly_divides(qfac->coeffs + i, qfac->coeffs + i, t, ctx); FLINT_ASSERT(success); fmpz_mod_mpoly_make_monic(qfac->coeffs + i, qfac->coeffs + i, ctx); } success = 1; cleanup: flint_free(newdeg); fmpz_mod_mpoly_clear(lcq, ctx); fmpz_mod_mpoly_clear(lcp, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(newq, ctx); #if FLINT_WANT_ASSERT if (success > 0) { fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_one(t, ctx); for (i = 0; i < qfac->length; i++) fmpz_mod_mpoly_mul(t, t, qfac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(t, q, ctx)); fmpz_mod_mpoly_clear(t, ctx); } #endif return success; } int fmpz_mod_mpoly_factor_irred_smprime_zassenhaus( fmpz_mod_mpolyv_t fac, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state) { int success; int tries_remaining = 10; const slong n = ctx->minfo->nvars - 1; slong i, j, k, m, len; slong * subset; fmpz * alphas; fmpz_mod_mpoly_struct * Aevals; slong * deg, * degeval; fmpz_mod_mpolyv_t qfac, pfac, tfac, dfac; fmpz_mod_mpoly_t t, p, q; fmpz_mod_poly_t c; fmpz_mod_bpoly_t B; fmpz_mod_tpoly_t F; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(A->bits <= FLINT_BITS); subset = FLINT_ARRAY_ALLOC(4, slong); alphas = _fmpz_vec_init(n); Aevals = FLINT_ARRAY_ALLOC(n, fmpz_mod_mpoly_struct); deg = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); for (i = 0; i < n; i++) fmpz_mod_mpoly_init(Aevals + i, ctx); fmpz_mod_mpolyv_init(pfac, ctx); fmpz_mod_mpolyv_init(qfac, ctx); fmpz_mod_mpolyv_init(tfac, ctx); fmpz_mod_mpolyv_init(dfac, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(p, ctx); fmpz_mod_mpoly_init(q, ctx); fmpz_mod_poly_init(c, ctx->ffinfo); fmpz_mod_bpoly_init(B, ctx->ffinfo); fmpz_mod_tpoly_init(F, ctx->ffinfo); fmpz_mod_mpoly_degrees_si(deg, A, ctx); next_alpha: if (--tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) fmpz_mod_rand_not_zero(alphas + i, state, ctx->ffinfo); /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alphas + i, ctx); fmpz_mod_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); fmpz_mod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != deg[j]) goto next_alpha; } /* make sure univar is squarefree */ fmpz_mod_mpoly_derivative(t, Aevals + 0, 0, ctx); success = fmpz_mod_mpoly_gcd(t, t, Aevals + 0, ctx); if (!success) goto cleanup; if (!fmpz_mod_mpoly_is_one(t, ctx)) goto next_alpha; /* make evaluations primitive */ for (i = n - 1; i > 0; i--) { success = fmpz_mod_mpolyl_content(t, Aevals + i, 1, ctx); if (!success) goto cleanup; success = fmpz_mod_mpoly_divides(Aevals + i, Aevals + i, t, ctx); FLINT_ASSERT(success); fmpz_mod_mpoly_make_monic(Aevals + i, Aevals + i, ctx); fmpz_mod_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); } fmpz_mod_mpoly_get_fmpz_mod_bpoly(B, Aevals + 1, 0, 1, ctx); success = fmpz_mod_bpoly_factor_smprime(c, F, B, 1, ctx->ffinfo); if (!success) goto next_alpha; FLINT_ASSERT(fmpz_mod_poly_degree(c, ctx->ffinfo) == 0); fmpz_mod_mpolyv_fit_length(pfac, F->length, ctx); pfac->length = F->length; for (i = 0; i < F->length; i++) { fmpz_mod_mpoly_set_fmpz_mod_bpoly(pfac->coeffs + i, A->bits, F->coeffs + i, 0, 1, ctx); fmpz_mod_mpoly_make_monic(pfac->coeffs + i, pfac->coeffs + i, ctx); } /* number of of local factors can only decrease from here on */ subset = FLINT_ARRAY_REALLOC(subset, pfac->length, slong); for (m = 2; m <= n; m++) { fmpz_mod_mpoly_set(q, m < n ? Aevals + m : A, ctx); fmpz_mod_mpoly_set(p, Aevals + m - 1, ctx); #if FLINT_WANT_ASSERT fmpz_mod_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fmpz_mod_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(t, p, ctx)); #endif /* if one local factor, A must be irreducible */ if (pfac->length < 2) { fmpz_mod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } success = _try_lift(qfac, q, pfac, p, m, alphas, n, ctx); if (success > 0) { fmpz_mod_mpolyv_swap(qfac, pfac, ctx); continue; } else if (success < 0) { success = 0; goto cleanup; } /* if we couldn't lift two local, A must be irreducible */ if (pfac->length == 2) { fmpz_mod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } qfac->length = 0; len = pfac->length; for (k = 0; k < len; k++) subset[k] = k; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); #if FLINT_WANT_ASSERT fmpz_mod_mpoly_one(t, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fmpz_mod_mpoly_mul(t, t, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } FLINT_ASSERT(fmpz_mod_mpoly_equal(t, p, ctx)); #endif while (1) { fmpz_mod_mpolyv_fit_length(dfac, 2, ctx); dfac->length = 2; fmpz_mod_mpoly_one(dfac->coeffs + 0, ctx); fmpz_mod_mpoly_one(dfac->coeffs + 1, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fmpz_mod_mpoly_mul(dfac->coeffs + in, dfac->coeffs + in, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } success = _try_lift(tfac, q, dfac, p, m, alphas, n, ctx); if (success > 0) { fmpz_mod_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fmpz_mod_mpoly_swap(qfac->coeffs + qfac->length, tfac->coeffs + 1, ctx); qfac->length++; fmpz_mod_mpoly_swap(q, tfac->coeffs + 0, ctx); fmpz_mod_mpoly_swap(p, dfac->coeffs + 0, ctx); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else if (success < 0) { success = 0; goto cleanup; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } /* remnants are irreducible */ if (!fmpz_mod_mpoly_is_fmpz(q, ctx)) { fmpz_mod_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fmpz_mod_mpoly_swap(qfac->coeffs + qfac->length, q, ctx); qfac->length++; } else { FLINT_ASSERT(fmpz_mod_mpoly_is_one(q, ctx)); } fmpz_mod_mpolyv_swap(qfac, pfac, ctx); } success = 1; fmpz_mod_mpolyv_swap(fac, pfac, ctx); cleanup: flint_free(subset); _fmpz_vec_clear(alphas, n); for (i = 0; i < n; i++) fmpz_mod_mpoly_clear(Aevals + i, ctx); flint_free(Aevals); flint_free(deg); flint_free(degeval); fmpz_mod_mpolyv_clear(pfac, ctx); fmpz_mod_mpolyv_clear(qfac, ctx); fmpz_mod_mpolyv_clear(tfac, ctx); fmpz_mod_mpolyv_clear(dfac, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(p, ctx); fmpz_mod_mpoly_clear(q, ctx); fmpz_mod_poly_clear(c, ctx->ffinfo); fmpz_mod_bpoly_clear(B, ctx->ffinfo); fmpz_mod_tpoly_clear(F, ctx->ffinfo); #if FLINT_WANT_ASSERT if (success) { fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_one(t, ctx); for (i = 0; i < fac->length; i++) fmpz_mod_mpoly_mul(t, t, fac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(t, A, ctx)); fmpz_mod_mpoly_clear(t, ctx); } #endif return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/irred_smprime_zippel.c000066400000000000000000000232561461254215100244130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_mpoly_factor.h" /* return 1: success 0: failed -1: exception (large exps) */ int fmpz_mod_mpoly_factor_irred_smprime_zippel( fmpz_mod_mpolyv_t fac, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_factor_t lcAfac, const fmpz_mod_mpoly_t lcA, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state) { int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; fmpz * alpha; fmpz_mod_poly_struct * alphabetas; fmpz_mod_mpoly_struct * Aevals; slong * degs, * degeval; fmpz_mod_mpolyv_t tfac; fmpz_mod_mpoly_t t, Acopy; fmpz_mod_mpoly_struct * newA; fmpz_mod_poly_t Abfc; fmpz_mod_bpoly_t Ab; fmpz_mod_tpoly_t Abfp; fmpz_mod_mpoly_t m, mpow; fmpz_mod_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(fmpz_is_one(A->coeffs + 0)); FLINT_ASSERT(A->bits <= FLINT_BITS); fmpz_mod_mpoly_init(Acopy, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_mod_mpoly_init(mpow, ctx); fmpz_mod_mpolyv_init(new_lcs, ctx); fmpz_mod_mpolyv_init(lc_divs, ctx); fmpz_mod_poly_init(Abfc, ctx->ffinfo); fmpz_mod_tpoly_init(Abfp, ctx->ffinfo); fmpz_mod_bpoly_init(Ab, ctx->ffinfo); degs = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); alpha = _fmpz_vec_init(n); alphabetas = FLINT_ARRAY_ALLOC(n, fmpz_mod_poly_struct); Aevals = FLINT_ARRAY_ALLOC(n, fmpz_mod_mpoly_struct); for (i = 0; i < n; i++) { fmpz_mod_poly_init(alphabetas + i, ctx->ffinfo); fmpz_mod_mpoly_init(Aevals + i, ctx); } fmpz_mod_mpolyv_init(tfac, ctx); fmpz_mod_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; fmpz_mod_mpoly_degrees_si(degs, A, ctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) fmpz_mod_rand_not_zero(alpha + i, state, ctx->ffinfo); /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fmpz_mod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } /* make sure univar is squarefree */ fmpz_mod_mpoly_derivative(t, Aevals + 0, 0, ctx); if (!fmpz_mod_mpoly_gcd(t, t, Aevals + 0, ctx)) { success = -1; goto cleanup; } if (!fmpz_mod_mpoly_is_one(t, ctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 10) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { fmpz_mod_poly_fit_length(alphabetas + i, alphabetas_length, ctx->ffinfo); fmpz_set(alphabetas[i].coeffs + 0, alpha + i); for (j = 1; j < alphabetas_length; j++) fmpz_mod_rand(alphabetas[i].coeffs + j, state, ctx->ffinfo); _fmpz_mod_poly_set_length(alphabetas + i, alphabetas_length); _fmpz_mod_poly_normalise(alphabetas + i); } _fmpz_mod_mpoly_eval_rest_to_fmpz_mod_bpoly(Ab, A, alphabetas, ctx); success = fmpz_mod_bpoly_factor_smprime(Abfc, Abfp, Ab, 0, ctx->ffinfo); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { fmpz_mod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } fmpz_mod_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = fmpz_mod_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) fmpz_mod_mpoly_one(lc_divs->coeffs + i, ctx); } success = fmpz_mod_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = fmpz_mod_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } fmpz_mod_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fmpz_mod_mpoly_is_one(mpow, ctx)) { newA = (fmpz_mod_mpoly_struct *) A; } else { newA = Acopy; fmpz_mod_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } fmpz_mod_mpoly_degrees_si(degs, newA, ctx); for (i = 0; i < n + 1; i++) { if (FLINT_BIT_COUNT(degs[i]) >= FLINT_BITS/3) { success = -1; goto cleanup; } } fmpz_mod_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fmpz_mod_mpoly_evaluate_one_fmpz(t, mpow, i + 1, alpha + i, ctx); fmpz_mod_mpoly_swap(t, mpow, ctx); fmpz_mod_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); fmpz_mod_mpoly_repack_bits_inplace(Aevals + i, newA->bits, ctx); } fmpz_mod_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fmpz_mod_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mod_mpoly_evaluate_one_fmpz(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fmpz_mod_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { fmpz_t q; fmpz_init(q); FLINT_ASSERT(fmpz_mod_mpoly_is_fmpz(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fmpz_mod_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _fmpz_mod_mpoly_set_fmpz_mod_bpoly_var1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); fmpz_mod_inv(q, fac->coeffs[i].coeffs + 0, ctx->ffinfo); fmpz_mod_mul(q, q, new_lcs->coeffs[0*r + i].coeffs + 0, ctx->ffinfo); fmpz_mod_mpoly_scalar_mul_fmpz_mod_invertible(fac->coeffs + i, fac->coeffs + i, q, ctx); fmpz_clear(q); } fmpz_mod_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _fmpz_mod_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } if (k > 2) { success = fmpz_mod_mpoly_hlift_zippel(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx, state); } else { success = fmpz_mod_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); } if (!success) goto next_alphabetas; fmpz_mod_mpolyv_swap(tfac, fac, ctx); } if (!fmpz_mod_mpoly_is_fmpz(m, ctx)) { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!fmpz_mod_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fmpz_mod_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } } for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); fmpz_mod_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); } success = 1; cleanup: fmpz_mod_mpolyv_clear(new_lcs, ctx); fmpz_mod_mpolyv_clear(lc_divs, ctx); fmpz_mod_poly_clear(Abfc, ctx->ffinfo); fmpz_mod_tpoly_clear(Abfp, ctx->ffinfo); fmpz_mod_bpoly_clear(Ab, ctx->ffinfo); for (i = 0; i < n; i++) { fmpz_mod_mpoly_clear(Aevals + i, ctx); fmpz_mod_poly_clear(alphabetas + i, ctx->ffinfo); } flint_free(alphabetas); flint_free(Aevals); _fmpz_vec_clear(alpha, n); flint_free(degs); flint_free(degeval); fmpz_mod_mpolyv_clear(tfac, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(Acopy, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { fmpz_mod_mpoly_t prod; fmpz_mod_mpoly_init(prod, ctx); fmpz_mod_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) fmpz_mod_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(prod, A, ctx)); fmpz_mod_mpoly_clear(prod, ctx); } #endif FLINT_ASSERT(success); return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/lcc_wang.c000066400000000000000000000107411461254215100217370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_factor_lcc_wang( fmpz_mod_mpoly_struct * lc_divs, const fmpz_mod_mpoly_factor_t lcAfac, const fmpz_mod_poly_t Auc, const fmpz_mod_bpoly_struct * Auf, slong r, const fmpz_mod_poly_struct * alpha, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j, k; const slong n = ctx->minfo->nvars - 1; fmpz_mod_poly_struct * lcAfaceval; fmpz_mod_poly_struct * d; fmpz_mod_poly_t Q, R; fmpz_mod_mpoly_t t; slong N, * offsets, * shifts, * starts, * ends, * stops; ulong mask, * es; fmpz_mod_poly_struct * T; fmpz_mod_poly_init(Q, ctx->ffinfo); fmpz_mod_poly_init(R, ctx->ffinfo); fmpz_mod_mpoly_init(t, ctx); lcAfaceval = FLINT_ARRAY_ALLOC(lcAfac->num, fmpz_mod_poly_struct); for (i = 0; i < lcAfac->num; i++) fmpz_mod_poly_init(lcAfaceval + i, ctx->ffinfo); d = FLINT_ARRAY_ALLOC(lcAfac->num + 1, fmpz_mod_poly_struct); for (i = 0; i < lcAfac->num + 1; i++) fmpz_mod_poly_init(d + i, ctx->ffinfo); starts = FLINT_ARRAY_ALLOC(n + 1, slong); ends = FLINT_ARRAY_ALLOC(n + 1, slong); stops = FLINT_ARRAY_ALLOC(n + 1, slong); es = FLINT_ARRAY_ALLOC(n + 1, ulong); T = FLINT_ARRAY_ALLOC(n + 2, fmpz_mod_poly_struct); for (i = 0; i < n + 2; i++) fmpz_mod_poly_init(T + i, ctx->ffinfo); offsets = FLINT_ARRAY_ALLOC(n + 1, slong); shifts = FLINT_ARRAY_ALLOC(n + 1, slong); for (j = 0; j < lcAfac->num; j++) { fmpz_mod_mpoly_struct * P = lcAfac->poly + j; for (i = 0; i < n + 1; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, P->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - P->bits); N = mpoly_words_per_exp_sp(P->bits, ctx->minfo); _fmpz_mod_mpoly_evaluate_rest_fmpz_mod_poly(T, starts, ends, stops, es, P->coeffs, P->exps, P->length, 1, alpha, offsets, shifts, N, mask, n + 1, ctx->ffinfo); fmpz_mod_poly_set(lcAfaceval + j, T + 0, ctx->ffinfo); } fmpz_mod_poly_set(d + 0, Auc, ctx->ffinfo); for (i = 0; i < lcAfac->num; i++) { fmpz_mod_poly_make_monic(Q, lcAfaceval + i, ctx->ffinfo); if (fmpz_mod_poly_degree(Q, ctx->ffinfo) < 1) { success = 0; goto cleanup; } for (j = i; j >= 0; j--) { fmpz_mod_poly_set(R, d + j, ctx->ffinfo); while (fmpz_mod_poly_degree(R, ctx->ffinfo) > 0) { fmpz_mod_poly_gcd(R, R, Q, ctx->ffinfo); fmpz_mod_poly_divrem(Q, T + 0, Q, R, ctx->ffinfo); if (fmpz_mod_poly_degree(Q, ctx->ffinfo) < 1) { success = 0; goto cleanup; } } } fmpz_mod_poly_set(d + i + 1, Q, ctx->ffinfo); } for (j = 0; j < r; j++) { fmpz_mod_mpoly_one(lc_divs + j, ctx); fmpz_mod_poly_mul(R, Auf[j].coeffs + Auf[j].length - 1, Auc, ctx->ffinfo); for (i = lcAfac->num - 1; i >= 0; i--) { fmpz_mod_poly_make_monic(Q, lcAfaceval + i, ctx->ffinfo); if (fmpz_mod_poly_degree(Q, ctx->ffinfo) < 1) continue; k = fmpz_mod_poly_remove(R, Q, ctx->ffinfo); fmpz_mod_mpoly_pow_ui(t, lcAfac->poly + i, k, ctx); fmpz_mod_mpoly_mul(lc_divs + j, lc_divs + j, t, ctx); } } success = 1; cleanup: fmpz_mod_poly_clear(Q, ctx->ffinfo); fmpz_mod_poly_clear(R, ctx->ffinfo); fmpz_mod_mpoly_clear(t, ctx); for (i = 0; i < lcAfac->num; i++) fmpz_mod_poly_clear(lcAfaceval + i, ctx->ffinfo); flint_free(lcAfaceval); for (i = 0; i < lcAfac->num + 1; i++) fmpz_mod_poly_clear(d + i, ctx->ffinfo); flint_free(d); for (i = 0; i < n + 2; i++) fmpz_mod_poly_clear(T + i, ctx->ffinfo); flint_free(T); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/mpoly_hlift.c000066400000000000000000000336301461254215100225120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" static int _hlift_quartic2( slong m, fmpz_mod_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j; fmpz_mod_mpoly_t Aq, t, t2, t3, xalpha; fmpz_mod_mpoly_geobucket_t G; fmpz_mod_mpoly_struct betas[2], * deltas; fmpz_mod_mpoly_pfrac_t I; fmpz_mod_mpolyv_struct B[2]; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r == 2); r = 2; fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(t2, ctx); fmpz_mod_mpoly_init(t3, ctx); fmpz_mod_mpoly_init(xalpha, ctx); fmpz_mod_mpoly_init(Aq, ctx); fmpz_mod_mpoly_geobucket_init(G, ctx); fmpz_mod_mpoly_gen(xalpha, m, ctx); fmpz_mod_mpoly_sub_fmpz(xalpha, xalpha, alpha + m - 1 , ctx); fmpz_mod_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (i = 0; i < r; i++) { fmpz_mod_mpolyv_init(B + i, ctx); fmpz_mod_mpoly_repack_bits_inplace(f + i, bits, ctx); fmpz_mod_mpoly_to_mpolyv(B + i, f + i, xalpha, ctx); fmpz_mod_mpolyv_fit_length(B + i, degs[m] + 1, ctx); for (j = B[i].length; j <= degs[m]; j++) fmpz_mod_mpoly_zero(B[i].coeffs + j, ctx); } for (i = 0; i < r; i++) betas[i] = B[i].coeffs[0]; success = fmpz_mod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; fmpz_mod_mpoly_divrem(Aq, t, A, xalpha, ctx); #if FLINT_WANT_ASSERT fmpz_mod_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fmpz_mod_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { fmpz_mod_mpoly_divrem(t2, t, Aq, xalpha, ctx); fmpz_mod_mpoly_swap(Aq, t2, ctx); fmpz_mod_mpoly_geobucket_set(G, t, ctx); for (i = 0; i <= j; i++) { fmpz_mod_mpoly_mul(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx); fmpz_mod_mpoly_mul(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx); fmpz_mod_mpoly_geobucket_sub(G, t, ctx); } fmpz_mod_mpoly_geobucket_empty(t, G, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) continue; success = fmpz_mod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fmpz_mod_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fmpz_mod_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fmpz_mod_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } } success = 1; cleanup: fmpz_mod_mpoly_pfrac_clear(I, ctx); for (i = 0; i < r; i++) { if (success) fmpz_mod_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); fmpz_mod_mpolyv_clear(B + i, ctx); } fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_clear(t3, ctx); fmpz_mod_mpoly_clear(xalpha, ctx); fmpz_mod_mpoly_clear(Aq, ctx); fmpz_mod_mpoly_geobucket_clear(G, ctx); return success; } static int _hlift_quartic( slong m, fmpz_mod_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j, k; fmpz_mod_mpoly_t Aq, t, t1, t2, t3, xalpha; fmpz_mod_mpoly_geobucket_t G; fmpz_mod_mpoly_struct * betas, * deltas; fmpz_mod_mpoly_pfrac_t I; fmpz_mod_mpolyv_struct * B, * U; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 2); B = FLINT_ARRAY_ALLOC(2*r, fmpz_mod_mpolyv_struct); U = B + r; fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(t1, ctx); fmpz_mod_mpoly_init(t2, ctx); fmpz_mod_mpoly_init(t3, ctx); fmpz_mod_mpoly_init(xalpha, ctx); fmpz_mod_mpoly_init(Aq, ctx); fmpz_mod_mpoly_geobucket_init(G, ctx); fmpz_mod_mpoly_gen(xalpha, m, ctx); fmpz_mod_mpoly_sub_fmpz(xalpha, xalpha, alpha + m - 1, ctx); fmpz_mod_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (k = 0; k < r; k++) { fmpz_mod_mpolyv_init(U + k, ctx); fmpz_mod_mpolyv_fit_length(U + k, degs[m] + 1, ctx); for (j = 0; j <= degs[m]; j++) fmpz_mod_mpoly_zero(U[k].coeffs + j, ctx); fmpz_mod_mpolyv_init(B + k, ctx); fmpz_mod_mpoly_repack_bits_inplace(f + k, bits, ctx); fmpz_mod_mpoly_to_mpolyv(B + k, f + k, xalpha, ctx); fmpz_mod_mpolyv_fit_length(B + k, degs[m] + 1, ctx); for (j = B[k].length; j <= degs[m]; j++) fmpz_mod_mpoly_zero(B[k].coeffs + j, ctx); } betas = FLINT_ARRAY_ALLOC(r, fmpz_mod_mpoly_struct); for (i = 0; i < r; i++) betas[i] = B[i].coeffs[0]; success = fmpz_mod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; k = r - 2; fmpz_mod_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k >= 1; k--) fmpz_mod_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx); fmpz_mod_mpoly_divrem(t2, t, A, xalpha, ctx); fmpz_mod_mpoly_swap(Aq, t2, ctx); #if FLINT_WANT_ASSERT fmpz_mod_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fmpz_mod_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fmpz_mod_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { k = r - 2; G->length = 0; for (i = 0; i <= j; i++) { fmpz_mod_mpoly_mul(t1, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fmpz_mod_mpoly_geobucket_add(G, t1, ctx); } fmpz_mod_mpoly_geobucket_empty(U[k].coeffs + j, G, ctx); for (k--; k >= 1; k--) { G->length = 0; for (i = 0; i <= j; i++) { fmpz_mod_mpoly_mul(t1, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); fmpz_mod_mpoly_geobucket_add(G, t1, ctx); } fmpz_mod_mpoly_geobucket_empty(U[k].coeffs + j, G, ctx); } fmpz_mod_mpoly_divrem(t2, t, Aq, xalpha, ctx); fmpz_mod_mpoly_swap(Aq, t2, ctx); fmpz_mod_mpoly_geobucket_set(G, t, ctx); for (i = 0; i <= j; i++) { fmpz_mod_mpoly_mul(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx); fmpz_mod_mpoly_geobucket_sub(G, t, ctx); } fmpz_mod_mpoly_geobucket_empty(t, G, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) continue; success = fmpz_mod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fmpz_mod_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fmpz_mod_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fmpz_mod_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } k = r - 2; fmpz_mod_mpoly_mul(t, B[k].coeffs + 0, deltas + k + 1, ctx); fmpz_mod_mpoly_mul(t1, deltas + k, B[k + 1].coeffs + 0, ctx); fmpz_mod_mpoly_add(t, t, t1, ctx); fmpz_mod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); for (k--; k >= 1; k--) { fmpz_mod_mpoly_mul(t1, B[k].coeffs + 0, t, ctx); fmpz_mod_mpoly_swap(t, t1, ctx); fmpz_mod_mpoly_mul(t1, deltas + k, U[k + 1].coeffs + 0, ctx); fmpz_mod_mpoly_add(t, t, t1, ctx); fmpz_mod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } success = 1; cleanup: fmpz_mod_mpoly_pfrac_clear(I, ctx); flint_free(betas); for (i = 0; i < r; i++) { if (success) fmpz_mod_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); fmpz_mod_mpolyv_clear(B + i, ctx); fmpz_mod_mpolyv_clear(U + i, ctx); } flint_free(B); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(t1, ctx); fmpz_mod_mpoly_clear(t2, ctx); fmpz_mod_mpoly_clear(t3, ctx); fmpz_mod_mpoly_clear(xalpha, ctx); fmpz_mod_mpoly_clear(Aq, ctx); fmpz_mod_mpoly_geobucket_clear(G, ctx); return success; } static int _hlift_quintic( slong m, fmpz_mod_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j; fmpz_mod_mpoly_t e, t, pow, xalpha, q; fmpz_mod_mpoly_struct * betas, * deltas; fmpz_mod_mpoly_pfrac_t I; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 1); fmpz_mod_mpoly_init(e, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_init(pow, ctx); fmpz_mod_mpoly_init(xalpha, ctx); fmpz_mod_mpoly_init(q, ctx); betas = FLINT_ARRAY_ALLOC(r, fmpz_mod_mpoly_struct); for (i = 0; i < r; i++) { fmpz_mod_mpoly_init(betas + i, ctx); fmpz_mod_mpoly_repack_bits_inplace(f + i, bits, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(betas + i, f + i, m, alpha + m - 1, ctx); } fmpz_mod_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fmpz_mod_mpoly_mul(t, t, f + i, ctx); fmpz_mod_mpoly_sub(e, A, t, ctx); fmpz_mod_mpoly_one(pow, ctx); fmpz_mod_mpoly_repack_bits_inplace(pow, bits, ctx); fmpz_mod_mpoly_gen(xalpha, m, ctx); fmpz_mod_mpoly_sub_fmpz(xalpha, xalpha, alpha + m - 1, ctx); fmpz_mod_mpoly_repack_bits_inplace(xalpha, bits, ctx); fmpz_mod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); deltas = I->deltas + (m - 1)*I->r; for (j = 1; j <= degs[m]; j++) { if (fmpz_mod_mpoly_is_zero(e, ctx)) { success = 1; goto cleanup; } fmpz_mod_mpoly_mul(pow, pow, xalpha, ctx); success = fmpz_mod_mpoly_divides(q, e, pow, ctx); FLINT_ASSERT(success); fmpz_mod_mpoly_evaluate_one_fmpz(t, q, m, alpha + m - 1, ctx); success = fmpz_mod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } for (i = 0; i < r; i++) { fmpz_mod_mpoly_mul(t, deltas + i, pow, ctx); fmpz_mod_mpoly_add(f + i, f + i, t, ctx); } fmpz_mod_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fmpz_mod_mpoly_mul(t, t, f + i, ctx); fmpz_mod_mpoly_sub(e, A, t, ctx); } success = fmpz_mod_mpoly_is_zero(e, ctx); cleanup: fmpz_mod_mpoly_pfrac_clear(I, ctx); fmpz_mod_mpoly_clear(e, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(pow, ctx); fmpz_mod_mpoly_clear(xalpha, ctx); fmpz_mod_mpoly_clear(q, ctx); for (i = 0; i < r; i++) { if (success) fmpz_mod_mpoly_repack_bits_inplace(f + i, bits, ctx); fmpz_mod_mpoly_clear(betas + i, ctx); } flint_free(betas); return success; } /* 1 ok 0 lift failed -1 inclusive, not tried */ static int _try_dense( slong m, fmpz_mod_mpoly_struct * f, /* length r */ slong r, const fmpz_t alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, degx, degy; fmpz_mod_bpoly_t Ab; fmpz_mod_bpoly_struct * fb; fmpz_mod_poly_bpoly_stack_t St; if (m != 1) return -1; degx = fmpz_mod_mpoly_degree_si(A, 0, ctx); degy = fmpz_mod_mpoly_degree_si(A, 1, ctx); if (degx < 1 || A->length/degx < degy/16) return -1; fmpz_mod_bpoly_init(Ab, ctx->ffinfo); fmpz_mod_mpoly_get_fmpz_mod_bpoly(Ab, A, 1, 0, ctx); fb = FLINT_ARRAY_ALLOC(r, fmpz_mod_bpoly_struct); for (i = 0; i < r; i++) { fmpz_mod_bpoly_init(fb + i, ctx->ffinfo); fmpz_mod_mpoly_get_fmpz_mod_bpoly(fb + i, f + i, 1, 0, ctx); } fmpz_mod_poly_stack_init(St->poly_stack); fmpz_mod_bpoly_stack_init(St->bpoly_stack); success = fmpz_mod_bpoly_hlift(r, Ab, fb, alpha, degx, ctx->ffinfo, St); for (i = 0; i < r; i++) { fmpz_mod_mpoly_set_fmpz_mod_bpoly(f + i, A->bits, fb + i, 1, 0, ctx); fmpz_mod_bpoly_clear(fb + i, ctx->ffinfo); } flint_free(fb); fmpz_mod_bpoly_clear(Ab, ctx->ffinfo); fmpz_mod_poly_stack_clear(St->poly_stack); fmpz_mod_bpoly_stack_clear(St->bpoly_stack); return success; } /* should have A = prod_i f[i] mod (gen(m) - alpha[m-1]) */ int fmpz_mod_mpoly_hlift( slong m, fmpz_mod_mpoly_struct * f, /* length r */ slong r, const fmpz * alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx) { int success; FLINT_ASSERT(r >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); success = _try_dense(m, f, r, alpha, A, degs, ctx); if (success >= 0) return success; if (r == 2) return _hlift_quartic2(m, f, r, alpha, A, degs, ctx); else if (r < 20) return _hlift_quartic(m, f, r, alpha, A, degs, ctx); else return _hlift_quintic(m, f, r, alpha, A, degs, ctx); } flint-3.1.3/src/fmpz_mod_mpoly_factor/mpoly_hlift_zippel.c000066400000000000000000000644261461254215100241040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "n_poly.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_polyu_init(fmpz_mod_polyu_t A) { A->length = 0; A->alloc = 0; A->exps = NULL; A->coeffs = NULL; } void fmpz_mod_polyu_clear(fmpz_mod_polyu_t A) { slong i; for (i = 0; i < A->alloc; i++) fmpz_clear(A->coeffs + i); flint_free(A->exps); flint_free(A->coeffs); } void fmpz_mod_polyu_realloc(fmpz_mod_polyu_t A, slong len) { slong i, old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, ulong); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fmpz); for (i = old_alloc; i < new_alloc; i++) fmpz_init(A->coeffs + i); A->alloc = new_alloc; } void fmpz_mod_polyu3_degrees( slong * deg0, slong * deg1, slong * deg2, const fmpz_mod_polyu_t A) { slong i; ulong m; ulong mask = mpoly_overflow_mask_sp(FLINT_BITS/3); if (A->length <= 0) { *deg0 = *deg1 = *deg2 = -1; return; } m = A->exps[0]; for (i = 1; i < A->length; i++) m = mpoly_monomial_max1(m, A->exps[i], FLINT_BITS/3, mask); *deg0 = extract_exp(m, 2, 3); *deg1 = extract_exp(m, 1, 3); *deg2 = extract_exp(m, 0, 3); } /***************************************************************************/ void fmpz_mod_mpolyu_init( fmpz_mod_mpolyu_t A, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void fmpz_mod_mpolyu_clear( fmpz_mod_mpolyu_t A, const fmpz_mod_mpoly_ctx_t uctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mod_mpoly_clear(A->coeffs + i, uctx); flint_free(A->coeffs); flint_free(A->exps); } void fmpz_mod_mpolyu_swap( fmpz_mod_mpolyu_t A, fmpz_mod_mpolyu_t B, const fmpz_mod_mpoly_ctx_t uctx) { fmpz_mod_mpolyu_struct t = *A; *A = *B; *B = t; } void fmpz_mod_mpolyu_zero( fmpz_mod_mpolyu_t A, const fmpz_mod_mpoly_ctx_t uctx) { A->length = 0; } int fmpz_mod_mpolyu_is_one( fmpz_mod_mpolyu_t A, const fmpz_mod_mpoly_ctx_t uctx) { if (A->length != 1 || A->exps[0] != UWORD(0)) return 0; return fmpz_mod_mpoly_is_one(A->coeffs + 0, uctx); } void fmpz_mod_mpolyu_fit_length( fmpz_mod_mpolyu_t A, slong length, const fmpz_mod_mpoly_ctx_t uctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (fmpz_mod_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fmpz_mod_mpoly_struct)); for (i = old_alloc; i < new_alloc; i++) fmpz_mod_mpoly_init3(A->coeffs + i, 0, A->bits, uctx); A->alloc = new_alloc; } } void fmpz_mod_mpolyu_one(fmpz_mod_mpolyu_t A, const fmpz_mod_mpoly_ctx_t uctx) { fmpz_mod_mpolyu_fit_length(A, WORD(1), uctx); A->exps[0] = UWORD(0); fmpz_mod_mpoly_one(A->coeffs + 0, uctx); A->length = WORD(1); } void fmpz_mod_mpolyu_repack_bits_inplace( fmpz_mod_mpolyu_t A, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (bits == A->bits) return; A->bits = bits; for (i = 0; i < A->alloc; i++) fmpz_mod_mpoly_repack_bits_inplace(A->coeffs + i, bits, ctx); } /* if the coefficient doesn't exist, a new one is created (and set to zero) */ fmpz_mod_mpoly_struct * _fmpz_mod_mpolyu_get_coeff( fmpz_mod_mpolyu_t A, ulong pow, const fmpz_mod_mpoly_ctx_t uctx) { slong i, j; fmpz_mod_mpoly_struct * xk; for (i = 0; i < A->length && A->exps[i] >= pow; i++) { if (A->exps[i] == pow) { return A->coeffs + i; } } fmpz_mod_mpolyu_fit_length(A, A->length + 1, uctx); for (j = A->length; j > i; j--) { A->exps[j] = A->exps[j - 1]; fmpz_mod_mpoly_swap(A->coeffs + j, A->coeffs + j - 1, uctx); } A->length++; A->exps[i] = pow; xk = A->coeffs + i; xk->length = 0; FLINT_ASSERT(xk->bits == A->bits); return xk; } /****************************************************************/ static void _delete_duplicates( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); j = -1; for (i = 0; i < A->length; i++) { if (j >= 0 && mpoly_monomial_equal(A->exps + N*j, A->exps + N*i, N)) { FLINT_ASSERT(fmpz_equal(A->coeffs + j, A->coeffs + i)); continue; } j++; fmpz_set(A->coeffs + j, A->coeffs + i); mpoly_monomial_set(A->exps + N*j, A->exps + N*i, N); } j++; A->length = j; } static int fmpz_mod_mpoly_from_zip( fmpz_mod_mpoly_t B, const fmpz_mod_polyun_t Z, fmpz_mod_mpolyu_t H, ulong deg, slong yvar, /* Y = gen(yvar) */ const fmpz_mod_mpoly_ctx_t ctx, fmpz_mod_polyun_t M) /* temp */ { int success; slong Hi, Zi, Bi, i, j; slong xvar = 0; slong zvar = 1; ulong x, y, z; flint_bitcnt_t bits = B->bits; fmpz * Bcoeffs; ulong * Bexps; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong xoff, xshift, yoff, yshift, zoff, zshift; fmpz_mod_poly_struct * Zcoeffs = Z->coeffs; ulong * Zexps = Z->exps; fmpz_mod_mpoly_struct * Hc; slong Hlen = H->length; FLINT_ASSERT(bits == H->bits); fmpz_mod_polyun_fit_length(M, Hlen + 1, ctx->ffinfo); for (i = 0; i <= Hlen; i++) M->coeffs[i].length = 0; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); /* x is most significant in ctx, so keeping the lc_x in B is easy */ FLINT_ASSERT(xvar == 0); for (Bi = 0; Bi < B->length; Bi++) { x = (((B->exps + N*Bi)[xoff] >> xshift) & mask); FLINT_ASSERT(x <= deg); if (x != deg) break; } for (Zi = 0; Zi < Z->length; Zi++) { y = extract_exp(Zexps[Zi], 2, 3); x = extract_exp(Zexps[Zi], 1, 3); z = extract_exp(Zexps[Zi], 0, 3); FLINT_ASSERT(x < deg); Hi = mpoly_monomial_index1_nomask(H->exps, H->length, pack_exp3(0, x, z)); if (Hi < 0) return 0; FLINT_ASSERT(Hi < Hlen); FLINT_ASSERT(H->exps[Hi] == pack_exp3(0, x, z)); Hc = H->coeffs + Hi; FLINT_ASSERT(bits == Hc->bits); FLINT_ASSERT(Hc->length > 0); fmpz_mod_mpoly_fit_length(B, Bi + Hc->length, ctx); Bcoeffs = B->coeffs; if (M->coeffs[Hi].length < 1) fmpz_mod_poly_product_roots_fmpz_vec(M->coeffs + Hi, Hc->coeffs, Hc->length, ctx->ffinfo); fmpz_mod_poly_fit_length(M->coeffs + Hlen, Hc->length, ctx->ffinfo); success = _fmpz_mod_zip_vand_solve(Bcoeffs + Bi, Hc->coeffs, Hc->length, Zcoeffs[Zi].coeffs, Zcoeffs[Zi].length, M->coeffs[Hi].coeffs, M->coeffs[Hlen].coeffs, ctx->ffinfo); if (success < 1) return success; Bexps = B->exps; for (j = Bi, i = 0; i < Hc->length; j++, i++) { if (fmpz_is_zero(Bcoeffs + j)) continue; FLINT_ASSERT(Bi < B->coeffs_alloc); FLINT_ASSERT(N*Bi < B->exps_alloc); fmpz_set(Bcoeffs + Bi, Bcoeffs + j); mpoly_monomial_set(Bexps + N*Bi, Hc->exps + N*i, N); (Bexps + N*Bi)[yoff] += y << yshift; Bi++; } } B->length = Bi; fmpz_mod_mpoly_sort_terms(B, ctx); FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(B, ctx)); return 1; } static void _clearit( n_polyun_t W, mpoly_rbtree_ui_t T, slong idx) { mpoly_rbnode_ui_struct * nodes = T->nodes + 2; FLINT_ASSERT(0 <= idx && idx < T->length); if (nodes[idx].right >= 0) _clearit(W, T, nodes[idx].right); FLINT_ASSERT(W->length < W->alloc); W->exps[W->length] = nodes[idx].key; W->coeffs[W->length] = ((n_poly_struct *) T->data)[idx]; W->length++; if (nodes[idx].left >= 0) _clearit(W, T, nodes[idx].left); } static void fmpz_mod_mpoly_set_eval_helper3( fmpz_mod_polyun_t EH, const fmpz_mod_mpoly_t A, slong yvar, const fmpz * alphas, const fmpz_mod_mpoly_ctx_t ctx) { slong xvar = 0; slong zvar = 1; slong i, j, k, n; ulong y, x, z; slong yoff, xoff, zoff, * off; slong yshift, xshift, zshift, * shift; fmpz_mod_poly_struct * EHcoeffs; ulong * EHexps; fmpz * p; flint_bitcnt_t bits = A->bits; slong Alen = A->length; const ulong * Aexps = A->exps; const fmpz * Acoeffs = A->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; mpoly_rbtree_ui_t W; TMP_INIT; TMP_START; n_polyun_init(T); mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Alen; i++) { n_poly_struct * Wc; int its_new; y = (Aexps[N*i + yoff] >> yshift) & mask; x = (Aexps[N*i + xoff] >> xshift) & mask; z = (Aexps[N*i + zoff] >> zshift) & mask; Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); fmpz_mod_polyun_fit_length(EH, T->length, ctx->ffinfo); EH->length = T->length; EHcoeffs = EH->coeffs; EHexps = EH->exps; for (i = 0; i < T->length; i++) { EHexps[i] = T->exps[i]; n = T->coeffs[i].length; fmpz_mod_poly_fit_length(EHcoeffs + i, 3*n, ctx->ffinfo); EHcoeffs[i].length = n; p = EHcoeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Ai = ind[j]; fmpz_one(p + j); for (k = 2; k < yvar; k++) { fmpz_t tt; ulong ei = (Aexps[N*Ai + off[k]] >> shift[k]) & mask; fmpz_init(tt); fmpz_mod_pow_ui(tt, alphas + k, ei, ctx->ffinfo); fmpz_mod_mul(p + j, p + j, tt, ctx->ffinfo); fmpz_clear(tt); } /* set cur = monomial eval */ /* copy cur to inc */ fmpz_set(p + j + n, p + j); /* copy coeff */ fmpz_set(p + j + 2*n, Acoeffs + Ai); } } n_polyun_clear(T); TMP_END; } /* for each term Y^y*X^x*Z^z * pol(x1,...) in B with j < deg set Y^0*X^x*Z^z in H as the monomials with the monomial evals as coeffs merge monomial sets coming from different y's (shouldn't happen) */ static slong fmpz_mod_mpoly_set_eval_helper_and_zip_form3( ulong * deg_, /* deg_X(B), output */ fmpz_mod_polyun_t EH, fmpz_mod_mpolyu_t H, const fmpz_mod_mpoly_t B, fmpz * alphas, slong yvar, /* Y = gen(yvar) (X = gen(0), Z = gen(1))*/ const fmpz_mod_mpoly_ctx_t ctx) { slong xvar = 0; slong zvar = 1; slong i, j, k, n; slong * off, * shift; ulong y, x, z; fmpz_mod_poly_struct * EHcoeffs; ulong * EHexps; fmpz * p; fmpz_mod_mpoly_struct * Hc; slong old_len, zip_length = 0; flint_bitcnt_t bits = B->bits; slong Blen = B->length; const ulong * Bexps = B->exps; const fmpz * Bcoeffs = B->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; ulong deg; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == H->bits); FLINT_ASSERT(Blen > 0); TMP_START; off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); /* init T */ { mpoly_rbtree_ui_t W; n_poly_struct * Wc; slong yoff, xoff, zoff; slong yshift, xshift, zshift; int its_new; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); deg = (Bexps[N*0 + xoff] >> xshift) & mask; mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Blen; i++) { y = (Bexps[N*i + yoff] >> yshift) & mask; x = (Bexps[N*i + xoff] >> xshift) & mask; z = (Bexps[N*i + zoff] >> zshift) & mask; FLINT_ASSERT(x <= deg); Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); } fmpz_mod_polyun_fit_length(EH, T->length, ctx->ffinfo); EH->length = T->length; EHcoeffs = EH->coeffs; EHexps = EH->exps; H->length = 0; for (i = 0; i < T->length; i++) { EHexps[i] = T->exps[i]; y = extract_exp(EHexps[i], 2, 3); x = extract_exp(EHexps[i], 1, 3); z = extract_exp(EHexps[i], 0, 3); n = T->coeffs[i].length; fmpz_mod_poly_fit_length(EHcoeffs + i, 3*n, ctx->ffinfo); EHcoeffs[i].length = n; p = EHcoeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Bi = ind[j]; fmpz_one(p + j); for (k = 2; k < yvar; k++) { fmpz_t tt; ulong ei = (Bexps[N*Bi + off[k]] >> shift[k]) & mask; fmpz_init(tt); fmpz_init(tt); fmpz_mod_pow_ui(tt, alphas + k, ei, ctx->ffinfo); fmpz_mod_mul(p + j, p + j, tt, ctx->ffinfo); fmpz_clear(tt); } /* set cur = monomial eval */ /* copy cur to inc */ fmpz_set(p + j + n, p + j); /* copy coeff */ fmpz_set(p + j + 2*n, Bcoeffs + Bi); } if (x < deg) { FLINT_ASSERT(y == 0 && "strange but ok"); Hc = _fmpz_mod_mpolyu_get_coeff(H, pack_exp3(0, x, z), ctx); fmpz_mod_mpoly_fit_length(Hc, n, ctx); old_len = Hc->length; _fmpz_vec_set(Hc->coeffs + old_len, p, n); for (j = 0; j < n; j++) mpoly_monomial_set(Hc->exps + N*(old_len + j), Bexps + N*ind[j], N); Hc->length += n; zip_length = FLINT_MAX(zip_length, Hc->length); if (old_len > 0) { FLINT_ASSERT(0 && "strange but ok"); fmpz_mod_mpoly_sort_terms(Hc, ctx); _delete_duplicates(Hc, ctx); } } } n_polyun_clear(T); TMP_END; *deg_ = deg; return zip_length; } static void fmpz_mod_polyu_eval_step( fmpz_mod_polyu_t E, fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx) { slong Ai, Ei, n; fmpz * p; fmpz_mod_polyu_fit_length(E, A->length, ctx); Ei = 0; for (Ai = 0; Ai < A->length; Ai++) { FLINT_ASSERT(Ei < E->alloc); E->exps[Ei] = A->exps[Ai]; n = A->coeffs[Ai].length; p = A->coeffs[Ai].coeffs; FLINT_ASSERT(A->coeffs[Ai].alloc >= 3*n); _fmpz_mod_zip_eval_step(E->coeffs + Ei, p + 0*n, p + 1*n, p + 2*n, n, ctx); Ei += !fmpz_is_zero(E->coeffs + Ei); } E->length = Ei; } static void fmpz_mod_polyu3_add_zip_limit1( fmpz_mod_polyun_t Z, const fmpz_mod_polyun_t A, const ulong deg1, slong cur_length, slong fit_length, const fmpz_mod_ctx_t ctx) { const fmpz_mod_poly_struct * Acoeffs = A->coeffs; ulong * Aexps = A->exps; fmpz_mod_poly_struct * Zcoeffs = Z->coeffs; ulong * Zexps = Z->exps; slong Ai, ai, Zi, j; Ai = -1; ai = -1; do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx); Zi = 0; while (Ai < A->length && Zi < Z->length) { if (Aexps[Ai] + ai > Zexps[Zi]) { /* missing from Z */ fmpz_mod_polyun_fit_length(Z, Z->length + 1, ctx); Zcoeffs = Z->coeffs; Zexps = Z->exps; for (j = Z->length; j > Zi; j--) { fmpz_mod_poly_swap(Zcoeffs + j, Zcoeffs + j - 1, ctx); FLINT_SWAP(ulong, Zexps[j], Zexps[j - 1]); } Z->length++; Zexps[Zi] = Aexps[Ai] + ai; fmpz_mod_poly_fit_length(Zcoeffs + Zi, fit_length, ctx); Zcoeffs[Zi].length = cur_length; _fmpz_vec_zero(Zcoeffs[Zi].coeffs, cur_length); goto in_both; } else if (Aexps[Ai] + ai < Zexps[Zi]) { /* missing from A */ FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fmpz_zero(Zcoeffs[Zi].coeffs + cur_length); Zcoeffs[Zi].length = cur_length + 1; Zi++; } else { in_both: FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fmpz_set(Zcoeffs[Zi].coeffs + cur_length, Acoeffs[Ai].coeffs + ai); Zcoeffs[Zi].length = cur_length + 1; Zi++; do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx); } } } /* everything in A must be put on the end of Z */ while (Ai < A->length) { Zi = Z->length; fmpz_mod_polyun_fit_length(Z, Zi + A->length - Ai, ctx); Zcoeffs = Z->coeffs; Zexps = Z->exps; Zexps[Zi] = Aexps[Ai] + ai; fmpz_mod_poly_fit_length(Zcoeffs + Zi, fit_length, ctx); Zcoeffs[Zi].length = cur_length; _fmpz_vec_zero(Zcoeffs[Zi].coeffs, cur_length); FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fmpz_set(Zcoeffs[Zi].coeffs + cur_length, Acoeffs[Ai].coeffs + ai); Zcoeffs[Zi].length = cur_length + 1; Z->length = ++Zi; do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx); } } /* everything in Z must have a zero appended */ while (Zi < Z->length) { FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fmpz_zero(Zcoeffs[Zi].coeffs + cur_length); Zcoeffs[Zi].length = cur_length + 1; Zi++; } for (Zi = 0; Zi < Z->length; Zi++) { FLINT_ASSERT(Z->coeffs[Zi].length == cur_length + 1); } } int fmpz_mod_mpoly_hlift_zippel( slong m, fmpz_mod_mpoly_struct * B, slong r, const fmpz * alpha, const fmpz_mod_mpoly_t A, const slong * degs, const fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state) { flint_bitcnt_t bits = A->bits; int success; slong i, zip_fails_remaining, req_zip_images, cur_zip_image; fmpz_mod_mpolyu_struct * H; fmpz_mod_polyun_struct M[1], Aeh[1], * Beh, * BBeval, * Z; fmpz_mod_polyu_struct Aeval[1], * Beval; fmpz * beta; fmpz_mod_mpoly_t T1, T2; ulong * Bdegs; const slong degs0 = degs[0]; FLINT_ASSERT(m > 2); FLINT_ASSERT(r > 1); FLINT_ASSERT(bits <= FLINT_BITS); #if FLINT_WANT_ASSERT { fmpz_mod_mpoly_t T; slong j, * check_degs = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); fmpz_mod_mpoly_init(T, ctx); fmpz_mod_mpoly_degrees_si(check_degs, A, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); fmpz_mod_mpoly_one(T, ctx); for (i = 0; i < r; i++) { fmpz_mod_mpoly_degrees_si(check_degs, B + i, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); fmpz_mod_mpoly_mul(T, T, B + i, ctx); } fmpz_mod_mpoly_sub(T, A, T, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(T, T, m, alpha + m - 1, ctx); FLINT_ASSERT(fmpz_mod_mpoly_is_zero(T, ctx)); fmpz_mod_mpoly_clear(T, ctx); flint_free(check_degs); } #endif beta = _fmpz_vec_init(ctx->minfo->nvars); Bdegs = FLINT_ARRAY_ALLOC(r, ulong); H = FLINT_ARRAY_ALLOC(r, fmpz_mod_mpolyu_struct); Beh = FLINT_ARRAY_ALLOC(r, fmpz_mod_polyun_struct); Beval = FLINT_ARRAY_ALLOC(r, fmpz_mod_polyu_struct); BBeval = FLINT_ARRAY_ALLOC(r, fmpz_mod_polyun_struct); Z = FLINT_ARRAY_ALLOC(r, fmpz_mod_polyun_struct); fmpz_mod_polyun_init(Aeh, ctx->ffinfo); fmpz_mod_polyu_init(Aeval); fmpz_mod_polyun_init(M, ctx->ffinfo); for (i = 0; i < r; i++) { fmpz_mod_mpolyu_init(H + i, bits, ctx); fmpz_mod_polyun_init(Beh + i, ctx->ffinfo); fmpz_mod_polyu_init(Beval + i); fmpz_mod_polyun_init(BBeval + i, ctx->ffinfo); fmpz_mod_polyun_init(Z + i, ctx->ffinfo); } /* init done */ for (i = 0; i < r; i++) { success = fmpz_mod_mpoly_repack_bits_inplace(B + i, bits, ctx); if (!success) goto cleanup; } zip_fails_remaining = 3; choose_betas: /* only beta[2], beta[3], ..., beta[m - 1] will be used */ for (i = 0; i < ctx->minfo->nvars; i++) fmpz_mod_rand_not_zero(beta + i, state, ctx->ffinfo); fmpz_mod_mpoly_set_eval_helper3(Aeh, A, m, beta, ctx); req_zip_images = 1; for (i = 0; i < r; i++) { slong this_images; this_images = fmpz_mod_mpoly_set_eval_helper_and_zip_form3(Bdegs + i, Beh + i, H + i, B + i, beta, m, ctx); req_zip_images = FLINT_MAX(req_zip_images, this_images); FLINT_ASSERT(Bdegs[i] > 0); Z[i].length = 0; } cur_zip_image = 0; next_zip_image: fmpz_mod_polyu_eval_step(Aeval, Aeh, ctx->ffinfo); for (i = 0; i < r; i++) fmpz_mod_polyu_eval_step(Beval + i, Beh + i, ctx->ffinfo); success = fmpz_mod_polyu3_hlift(r, BBeval, Aeval, Beval, alpha + m - 1, degs0, ctx->ffinfo); if (success < 1) { if (--zip_fails_remaining >= 0) goto choose_betas; success = 0; goto cleanup; } for (i = 0; i < r; i++) { fmpz_mod_polyu3_add_zip_limit1(Z + i, BBeval + i, Bdegs[i], cur_zip_image, req_zip_images, ctx->ffinfo); } cur_zip_image++; if (cur_zip_image < req_zip_images) goto next_zip_image; for (i = 0; i < r; i++) { success = fmpz_mod_mpoly_from_zip(B + i, Z + i, H + i, Bdegs[i], m, ctx, M); if (success < 1) { FLINT_ASSERT(0); success = 0; goto cleanup; } } fmpz_mod_mpoly_init3(T1, A->length, bits, ctx); fmpz_mod_mpoly_init3(T2, A->length, bits, ctx); fmpz_mod_mpoly_mul(T1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { fmpz_mod_mpoly_mul(T2, T1, B + i, ctx); fmpz_mod_mpoly_swap(T1, T2, ctx); } success = fmpz_mod_mpoly_equal(T1, A, ctx); fmpz_mod_mpoly_clear(T1, ctx); fmpz_mod_mpoly_clear(T2, ctx); cleanup: fmpz_mod_polyun_clear(Aeh, ctx->ffinfo); fmpz_mod_polyu_clear(Aeval); fmpz_mod_polyun_clear(M, ctx->ffinfo); for (i = 0; i < r; i++) { fmpz_mod_mpolyu_clear(H + i, ctx); fmpz_mod_polyun_clear(Beh + i, ctx->ffinfo); fmpz_mod_polyu_clear(Beval + i); fmpz_mod_polyun_clear(BBeval + i, ctx->ffinfo); fmpz_mod_polyun_clear(Z + i, ctx->ffinfo); } _fmpz_vec_clear(beta, ctx->minfo->nvars); flint_free(Bdegs); flint_free(H); flint_free(Beh); flint_free(Beval); flint_free(BBeval); flint_free(Z); FLINT_ASSERT(success); return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/mpoly_pfrac.c000066400000000000000000000233301461254215100224730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mpoly_pfrac_init( fmpz_mod_mpoly_pfrac_t I, flint_bitcnt_t bits, slong r, slong w, const fmpz_mod_mpoly_struct * betas, const fmpz * alpha, const fmpz_mod_mpoly_ctx_t ctx) { int success = 1; slong i, j, k; fmpz_mod_poly_t p; fmpz_mod_poly_t G, S, pq; FLINT_ASSERT(bits <= FLINT_BITS); I->bits = bits; I->r = r; I->w = w; I->dbetas = FLINT_ARRAY_ALLOC(r, fmpz_mod_poly_struct); I->inv_prod_dbetas = FLINT_ARRAY_ALLOC(r, fmpz_mod_poly_struct); I->prod_mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mod_mpoly_struct); I->prod_mbetas_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mod_mpolyv_struct); I->mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mod_mpoly_struct); I->deltas = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mod_mpoly_struct); I->xalpha = FLINT_ARRAY_ALLOC(w + 1, fmpz_mod_mpoly_struct); I->q = FLINT_ARRAY_ALLOC(w + 1, fmpz_mod_mpoly_struct); I->G = FLINT_ARRAY_ALLOC(w + 1, fmpz_mod_mpoly_geobucket_struct); I->qt = FLINT_ARRAY_ALLOC(w + 1, fmpz_mod_mpoly_struct); I->newt = FLINT_ARRAY_ALLOC(w + 1, fmpz_mod_mpoly_struct); I->delta_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mod_mpolyv_struct); for (i = 0; i <= w; i++) { fmpz_mod_mpoly_init(I->xalpha + i, ctx); fmpz_mod_mpoly_init(I->q + i, ctx); fmpz_mod_mpoly_geobucket_init(I->G + i, ctx); fmpz_mod_mpoly_init(I->qt + i, ctx); fmpz_mod_mpoly_init(I->newt + i, ctx); for (j = 0; j < r; j++) { fmpz_mod_mpoly_init(I->deltas + i*r + j, ctx); fmpz_mod_mpolyv_init(I->delta_coeffs + i*r + j, ctx); } if (i < 1) continue; fmpz_mod_mpoly_gen(I->xalpha + i, i, ctx); fmpz_mod_mpoly_sub_fmpz(I->xalpha + i, I->xalpha + i, alpha + i - 1, ctx); fmpz_mod_mpoly_repack_bits_inplace(I->xalpha + i, I->bits, ctx); } fmpz_mod_poly_init(p, ctx->ffinfo); fmpz_mod_poly_init(G, ctx->ffinfo); fmpz_mod_poly_init(S, ctx->ffinfo); fmpz_mod_poly_init(pq, ctx->ffinfo); /* set betas */ i = w; for (j = 0; j < r; j++) { fmpz_mod_mpoly_init(I->mbetas + i*r + j, ctx); fmpz_mod_mpoly_set(I->mbetas + i*r + j, betas + j, ctx); } for (i--; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mod_mpoly_init(I->mbetas + i*r + j, ctx); fmpz_mod_mpoly_evaluate_one_fmpz(I->mbetas + i*r + j, I->mbetas + (i + 1)*r + j, i + 1, alpha + i, ctx); } } for (j = 0; j < r; j++) { fmpz_mod_poly_init(I->dbetas + j, ctx->ffinfo); if (!fmpz_mod_mpoly_get_fmpz_mod_poly(I->dbetas + j, I->mbetas + 0*r + j, 0, ctx)) { success = 0; } } /* set product of betas */ for (i = w; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mod_mpoly_init(I->prod_mbetas + i*r + j, ctx); fmpz_mod_mpoly_one(I->prod_mbetas + i*r + j, ctx); for (k = 0; k < r; k++) { if (k == j) continue; fmpz_mod_mpoly_mul(I->prod_mbetas + i*r + j, I->prod_mbetas + i*r + j, I->mbetas + i*r + k, ctx); } fmpz_mod_mpolyv_init(I->prod_mbetas_coeffs + i*r + j, ctx); if (i > 0) { fmpz_mod_mpoly_to_mpolyv(I->prod_mbetas_coeffs + i*r + j, I->prod_mbetas + i*r + j, I->xalpha + i, ctx); } } } for (j = 0; j < r; j++) fmpz_mod_poly_init(I->inv_prod_dbetas + j, ctx->ffinfo); for (j = 0; success && j < r; j++) { if (fmpz_mod_poly_degree(I->dbetas + j, ctx->ffinfo) != fmpz_mod_mpoly_degree_si(betas + j, 0, ctx)) { success = 0; } } for (j = 0; success && j < r; j++) { fmpz_mod_poly_one(pq, ctx->ffinfo); for (k = 0; k < r; k++) { if (k == j) continue; fmpz_mod_poly_mul(pq, pq, I->dbetas + k, ctx->ffinfo); } fmpz_mod_poly_xgcd(G, S, I->inv_prod_dbetas + j, I->dbetas + j, pq, ctx->ffinfo); if (!fmpz_mod_poly_is_one(G, ctx->ffinfo)) success = 0; } fmpz_mod_poly_clear(p, ctx->ffinfo); fmpz_mod_poly_clear(G, ctx->ffinfo); fmpz_mod_poly_clear(S, ctx->ffinfo); fmpz_mod_poly_clear(pq, ctx->ffinfo); I->dbetas_mvar = FLINT_ARRAY_ALLOC(r, fmpz_mod_mpoly_struct); I->inv_prod_dbetas_mvar = FLINT_ARRAY_ALLOC(r, fmpz_mod_mpoly_struct); for (j = 0; j < r; j++) { fmpz_mod_mpoly_init(I->dbetas_mvar + j, ctx); fmpz_mod_mpoly_init(I->inv_prod_dbetas_mvar + j, ctx); _fmpz_mod_mpoly_set_fmpz_mod_poly(I->dbetas_mvar + j, I->bits, I->dbetas[j].coeffs, I->dbetas[j].length, 0, ctx); _fmpz_mod_mpoly_set_fmpz_mod_poly(I->inv_prod_dbetas_mvar + j, I->bits, I->inv_prod_dbetas[j].coeffs, I->inv_prod_dbetas[j].length, 0, ctx); } fmpz_mod_mpoly_init(I->T, ctx); fmpz_mod_mpoly_init(I->Q, ctx); fmpz_mod_mpoly_init(I->R, ctx); FLINT_ASSERT(success == 1); return success; } void fmpz_mod_mpoly_pfrac_clear( fmpz_mod_mpoly_pfrac_t I, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j; for (i = 0; i <= I->w; i++) { fmpz_mod_mpoly_clear(I->xalpha + i, ctx); fmpz_mod_mpoly_clear(I->q + i, ctx); fmpz_mod_mpoly_geobucket_clear(I->G + i, ctx); fmpz_mod_mpoly_clear(I->qt + i, ctx); fmpz_mod_mpoly_clear(I->newt + i, ctx); for (j = 0; j < I->r; j++) fmpz_mod_mpolyv_clear(I->delta_coeffs + i*I->r + j, ctx); } flint_free(I->xalpha); flint_free(I->q); flint_free(I->G); flint_free(I->qt); flint_free(I->newt); flint_free(I->delta_coeffs); for (j = 0; j < I->r; j++) { fmpz_mod_poly_clear(I->inv_prod_dbetas + j, ctx->ffinfo); fmpz_mod_poly_clear(I->dbetas + j, ctx->ffinfo); for (i = 0; i <= I->w; i++) { fmpz_mod_mpolyv_clear(I->prod_mbetas_coeffs + i*I->r + j, ctx); fmpz_mod_mpoly_clear(I->prod_mbetas + i*I->r + j, ctx); fmpz_mod_mpoly_clear(I->mbetas + i*I->r + j, ctx); fmpz_mod_mpoly_clear(I->deltas + i*I->r + j, ctx); } } flint_free(I->inv_prod_dbetas); flint_free(I->dbetas); flint_free(I->prod_mbetas); flint_free(I->prod_mbetas_coeffs); flint_free(I->mbetas); flint_free(I->deltas); for (j = 0; j < I->r; j++) { fmpz_mod_mpoly_clear(I->dbetas_mvar + j, ctx); fmpz_mod_mpoly_clear(I->inv_prod_dbetas_mvar + j, ctx); } flint_free(I->dbetas_mvar); flint_free(I->inv_prod_dbetas_mvar); fmpz_mod_mpoly_clear(I->T, ctx); fmpz_mod_mpoly_clear(I->Q, ctx); fmpz_mod_mpoly_clear(I->R, ctx); } int fmpz_mod_mpoly_pfrac( slong l, fmpz_mod_mpoly_t t, const slong * degs, fmpz_mod_mpoly_pfrac_t I, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong i, j, k; fmpz_mod_mpoly_struct * deltas = I->deltas + l*I->r; fmpz_mod_mpoly_struct * newdeltas = I->deltas + (l - 1)*I->r; fmpz_mod_mpoly_struct * q = I->q + l; fmpz_mod_mpoly_struct * qt = I->qt + l; fmpz_mod_mpoly_struct * newt = I->newt + l; fmpz_mod_mpolyv_struct * delta_coeffs = I->delta_coeffs + l*I->r; fmpz_mod_mpoly_geobucket_struct * G = I->G + l; FLINT_ASSERT(l >= 0); if (!fmpz_mod_mpoly_repack_bits_inplace(t, I->bits, ctx)) return -1; if (l < 1) { for (i = 0; i < I->r; i++) { fmpz_mod_mpoly_divrem(I->Q, I->R, t, I->dbetas_mvar + i, ctx); fmpz_mod_mpoly_mul(I->T, I->R, I->inv_prod_dbetas_mvar + i, ctx); fmpz_mod_mpoly_divrem(I->Q, deltas + i, I->T, I->dbetas_mvar + i, ctx); } return 1; } for (i = 0; i < I->r; i++) delta_coeffs[i].length = 0; for (k = 0; k <= degs[l]; k++) { fmpz_mod_mpoly_divrem(q, newt, t, I->xalpha + l, ctx); fmpz_mod_mpoly_swap(t, q, ctx); fmpz_mod_mpoly_geobucket_set(G, newt, ctx); for (j = 0; j < k; j++) for (i = 0; i < I->r; i++) { if (j >= delta_coeffs[i].length) continue; if (k - j >= I->prod_mbetas_coeffs[l*I->r + i].length) continue; fmpz_mod_mpoly_mul(qt, delta_coeffs[i].coeffs + j, I->prod_mbetas_coeffs[l*I->r + i].coeffs + k - j, ctx); fmpz_mod_mpoly_geobucket_sub(G, qt, ctx); } fmpz_mod_mpoly_geobucket_empty(newt, G, ctx); if (fmpz_mod_mpoly_is_zero(newt, ctx)) continue; success = fmpz_mod_mpoly_pfrac(l - 1, newt, degs, I, ctx); if (success < 1) return success; for (i = 0; i < I->r; i++) { if (fmpz_mod_mpoly_is_zero(newdeltas + i, ctx)) continue; if (k + I->prod_mbetas_coeffs[l*I->r + i].length - 1 > degs[l]) return 0; fmpz_mod_mpolyv_set_coeff(delta_coeffs + i, k, newdeltas + i, ctx); } } for (i = 0; i < I->r; i++) fmpz_mod_mpoly_from_mpolyv(deltas + i, I->bits, delta_coeffs + i, I->xalpha + l, ctx); return 1; } flint-3.1.3/src/fmpz_mod_mpoly_factor/mpolyn.c000066400000000000000000000251121461254215100214760ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_mpolyn_init( fmpz_mod_mpolyn_t A, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void fmpz_mod_mpolyn_clear( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mod_poly_clear(A->coeffs + i, ctx->ffinfo); if (A->coeffs) flint_free(A->coeffs); if (A->exps) flint_free(A->exps); } int fmpz_mod_mpolyn_is_canonical( const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { if (!fmpz_mod_poly_is_canonical(A->coeffs + i, ctx->ffinfo) || fmpz_mod_poly_is_zero(A->coeffs + i, ctx->ffinfo)) { return 0; } } return 1; } void fmpz_mod_mpolyn_fit_length( fmpz_mod_mpolyn_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx) { slong i, N; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length <= old_alloc) return; N = mpoly_words_per_exp(A->bits, ctx->minfo); A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc*N, ulong); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fmpz_mod_poly_struct); for (i = old_alloc; i < new_alloc; i++) fmpz_mod_poly_init(A->coeffs + i, ctx->ffinfo); A->alloc = new_alloc; } slong fmpz_mod_mpolyn_lastdeg( const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; slong deg = -WORD(1); for (i = 0; i < A->length; i++) { slong newdeg = fmpz_mod_poly_degree(A->coeffs + i, ctx->ffinfo); deg = FLINT_MAX(deg, newdeg); } return deg; } void fmpz_mod_mpolyn_one( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); fmpz_mod_mpolyn_fit_length(A, 1, ctx); fmpz_mod_poly_set_ui(A->coeffs + 0, 1, ctx->ffinfo); mpoly_monomial_zero(A->exps + N*0, N); A->length = 1; } void fmpz_mod_mpolyn_scalar_mul_fmpz_mod( fmpz_mod_mpolyn_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->length; i++) fmpz_mod_poly_scalar_mul_fmpz(A->coeffs + i, A->coeffs + i, c, ctx->ffinfo); } int fmpz_mod_mpolyn_equal( const fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong i; FLINT_ASSERT(A->bits == B->bits); if (A->length != B->length) { return 0; } for (i = 0; i < A->length; i++) { if (!mpoly_monomial_equal(A->exps + N*i, B->exps + N*i, N)) return 0; if (!fmpz_mod_poly_equal(A->coeffs + i, B->coeffs + i, ctx->ffinfo)) return 0; } return 1; } /* put the last variable of B back into A */ void fmpz_mod_mpoly_cvtfrom_mpolyn( fmpz_mod_mpoly_t A, const fmpz_mod_mpolyn_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j, k; slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); ulong * genexp; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_sp(genexp, var, B->bits, ctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); k = 0; for (i = 0; i < B->length; i++) { for (j = B->coeffs[i].length - 1; j >= 0; j--) { fmpz * c = B->coeffs[i].coeffs + j; if (fmpz_is_zero(c)) continue; _fmpz_mod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, k + 1); fmpz_set(A->coeffs + k, c); mpoly_monomial_madd(A->exps + N*k, B->exps + N*i, j, genexp, N); k++; } } A->length = k; TMP_END; } /* take the last variable of B out */ void fmpz_mod_mpoly_cvtto_mpolyn( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_t B, slong var, const fmpz_mod_mpoly_ctx_t ctx) { slong i; slong k; ulong * oneexp; slong offset; slong shift; ulong mask; slong N; TMP_INIT; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); TMP_START; N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, B->bits, ctx->minfo); k = 0; fmpz_mod_mpolyn_fit_length(A, k + 1, ctx); for (i = 0; i < B->length; i++) { ulong c = (B->exps[N*i + offset] >> shift) & mask; mpoly_monomial_msub(A->exps + N*k, B->exps + N*i, c, oneexp, N); if (k > 0 && mpoly_monomial_equal(A->exps + N*k, A->exps + N*(k - 1), N)) { fmpz_mod_poly_set_coeff_fmpz(A->coeffs + k - 1, c, B->coeffs + i, ctx->ffinfo); } else { fmpz_mod_poly_zero(A->coeffs + k, ctx->ffinfo); fmpz_mod_poly_set_coeff_fmpz(A->coeffs + k, c, B->coeffs + i, ctx->ffinfo); k++; fmpz_mod_mpolyn_fit_length(A, k + 1, ctx); } } A->length = k; TMP_END; } void fmpz_mod_mpoly_to_mpolyn_perm_deflate( fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t nctx, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { slong j, k, l; slong NA = mpoly_words_per_exp_sp(A->bits, nctx->minfo); slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong n = ctx->minfo->nvars; slong m = nctx->minfo->nvars; ulong * Bexps; slong * offs, * shifts; fmpz_mod_mpoly_t T; TMP_INIT; FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); offs = (slong *) TMP_ALLOC(m*sizeof(slong)); shifts = (slong *) TMP_ALLOC(m*sizeof(slong)); for (k = 0; k < m; k++) { mpoly_gen_offset_shift_sp(offs + k, shifts + k, k, A->bits, nctx->minfo); } fmpz_mod_mpoly_init3(T, B->length, A->bits, nctx); T->length = B->length; for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); fmpz_set(T->coeffs + j, B->coeffs + j); mpoly_monomial_zero(T->exps + NA*j, NA); for (k = 0; k < m; k++) { l = perm[k]; (T->exps + NA*j)[offs[k]] += ((Bexps[l] - shift[l]) / stride[l]) << shifts[k]; } } fmpz_mod_mpoly_sort_terms(T, nctx); fmpz_mod_mpoly_cvtto_mpolyn(A, T, nctx->minfo->nvars - 1, nctx); fmpz_mod_mpoly_clear(T, nctx); TMP_END; } void fmpz_mod_mpoly_from_mpolyn_perm_inflate( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t nctx, const slong * perm, const ulong * shift, const ulong * stride) { slong n = ctx->minfo->nvars; slong m = nctx->minfo->nvars; slong i, h, k, l; slong NA, NB; slong Alen; fmpz * Acoeff; ulong * Aexp; ulong * Bexps; ulong * Aexps, * tAexp, * tAgexp; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, nctx->minfo); tAexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); tAgexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); mpoly_gen_monomial_sp(tAgexp, perm[m - 1], Abits, ctx->minfo); for (i = 0; i < NA; i++) tAgexp[i] *= stride[perm[m - 1]]; fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, nctx->minfo); FLINT_ASSERT(Bexps[m - 1] == 0); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m; k++) { l = perm[k]; Aexps[l] += stride[l]*Bexps[k]; } mpoly_set_monomial_ui(tAexp, Aexps, Abits, ctx->minfo); h = (B->coeffs + i)->length; _fmpz_mod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, NA, Alen + h); for (h--; h >= 0; h--) { fmpz * c = (B->coeffs + i)->coeffs + h; if (fmpz_is_zero(c)) continue; mpoly_monomial_madd(Aexp + NA*Alen, tAexp, h, tAgexp, NA); fmpz_set(Acoeff + Alen, c); Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; _fmpz_mod_mpoly_set_length(A, Alen, ctx); fmpz_mod_mpoly_sort_terms(A, ctx); TMP_END; } void fmpz_mod_mpolyn_set( fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; slong Blen = B->length; slong N = mpoly_words_per_exp(B->bits, ctx->minfo); FLINT_ASSERT(A->bits == B->bits); fmpz_mod_mpolyn_fit_length(A, Blen, ctx); mpoly_copy_monomials(A->exps, B->exps, Blen, N); for (i = 0; i < Blen; i++) fmpz_mod_poly_set(A->coeffs + i, B->coeffs + i, ctx->ffinfo); A->length = Blen; } int fmpz_mod_mpolyn_is_nonzero_fmpz( const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong N; if (A->length != 1 || A->coeffs[0].length != 1) return 0; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } flint-3.1.3/src/fmpz_mod_mpoly_factor/mpolyn_divides.c000066400000000000000000000170501461254215100232070ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" static void _clear_dense_mock( fmpz_mod_poly_t D) { flint_free(D->coeffs); } static void _init_dense_mock( fmpz_mod_poly_t D, const fmpz_mod_mpolyn_t A, const slong * Adeg_bounds, const fmpz_mod_mpoly_ctx_t ctx) { slong N, i, j, k, off, degb_prod; ulong * exps; slong nvars = ctx->minfo->nvars; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); degb_prod = 1; for (i = 0; i <= nvars; i++) degb_prod *= Adeg_bounds[i]; D->alloc = degb_prod; D->coeffs = (fmpz *) flint_calloc(degb_prod, sizeof(fmpz)); TMP_START; exps = TMP_ARRAY_ALLOC(nvars + 1, ulong); N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); D->length = 0; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ui(exps, A->exps + N*i, A->bits, ctx->minfo); off = exps[0]; for (j = 1; j < nvars; j++) off = exps[j] + Adeg_bounds[j]*off; off *= Adeg_bounds[nvars]; D->length = FLINT_MAX(D->length, off + A->coeffs[i].length); FLINT_ASSERT(D->length <= D->alloc); for (k = 0; k < A->coeffs[i].length; k++) D->coeffs[off + k] = A->coeffs[i].coeffs[k]; /* shallow copy */ } TMP_END; } /* Convert D to A if the degrees of A are <= expected_deg If not, return 0. */ static int _from_dense( fmpz_mod_mpolyn_t A, slong * Adeg_bounds, slong * expect_deg, fmpz_mod_poly_t D, const fmpz_mod_mpoly_ctx_t ctx) { int ret; slong off, j, k; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong nvars = ctx->minfo->nvars; ulong outrange; ulong * exps, * pcurexp, * pexps, * rangemask; TMP_INIT; FLINT_ASSERT(nvars + 1 <= FLINT_BITS); TMP_START; exps = (ulong *) TMP_ALLOC((nvars + 1)*sizeof(ulong)); off = 1; for (j = 0; j <= nvars; j++) { FLINT_ASSERT(expect_deg[j] >= 0); off *= Adeg_bounds[j]; exps[j] = expect_deg[j]; } /* we are going to push back terms manually */ A->length = 0; /* find exponent vector for all variables */ pexps = TMP_ARRAY_ALLOC((N + 1)*(nvars + 1), ulong); for (k = 0; k < nvars; k++) { mpoly_gen_monomial_sp(pexps + (N + 1)*k, k, A->bits, ctx->minfo); (pexps + (N + 1)*k)[N] = 0; } mpoly_monomial_zero(pexps + (N + 1)*nvars, N); (pexps + (N + 1)*nvars)[N] = 1; /* get most significant exponent in exps and its vector in ptempexp */ off--; pcurexp = TMP_ARRAY_ALLOC(N + 1, ulong); rangemask = TMP_ARRAY_ALLOC(nvars + 1, ulong); outrange = 0; mpoly_monomial_zero(pcurexp, N + 1); k = off; for (j = nvars; j >= 0; j--) { exps[j] = k % Adeg_bounds[j]; rangemask[j] = UWORD(1) << j; outrange ^= (outrange ^ FLINT_SIGN_EXT(expect_deg[j] - exps[j])) & rangemask[j]; k = k / Adeg_bounds[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + (N + 1)*j, N + 1); } /* scan down through the exponents */ for (; off >= 0; off--) { if (off < D->length && !fmpz_is_zero(D->coeffs + off)) { if (outrange) { ret = 0; goto cleanup; } if (A->length < 1 || !mpoly_monomial_equal(A->exps + N*(A->length - 1), pcurexp, N)) { fmpz_mod_mpolyn_fit_length(A, A->length + 1, ctx); fmpz_mod_poly_zero(A->coeffs + A->length, ctx->ffinfo); fmpz_mod_poly_set_coeff_fmpz(A->coeffs + A->length, pcurexp[N], D->coeffs + off, ctx->ffinfo); mpoly_monomial_set(A->exps + N*A->length, pcurexp, N); A->length++; } else { fmpz_mod_poly_set_coeff_fmpz(A->coeffs + A->length - 1, pcurexp[N], D->coeffs + off, ctx->ffinfo); } } j = nvars; do { --exps[j]; outrange ^= (outrange ^ FLINT_SIGN_EXT(expect_deg[j] - exps[j])) & rangemask[j]; if (FLINT_SIGN_EXT(exps[j]) != 0) { FLINT_ASSERT(off == 0 || j > 0); FLINT_ASSERT(exps[j] == -UWORD(1)); exps[j] = Adeg_bounds[j] - 1; outrange ^= (outrange ^ FLINT_SIGN_EXT(expect_deg[j] - exps[j])) & rangemask[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + (N + 1)*j, (N + 1)); } else { mpoly_monomial_sub_mp(pcurexp, pcurexp, pexps + (N + 1)*j, N + 1); break; } } while (--j >= 0); } ret = 1; cleanup: TMP_END; return ret; } /* return 1: yes it divides and Q=A/B 0: no or dunno */ int fmpz_mod_mpolyn_divides( fmpz_mod_mpolyn_t Q, const fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success; flint_bitcnt_t bits = A->bits; slong i; slong nvars = ctx->minfo->nvars; fmpz_mod_poly_t Ad, Bd, Qd, Rd; slong * Abounds, * Bbounds, * Qbounds, * Edegs; slong prod_deg; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(Q->bits == bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (nvars + 1 > FLINT_BITS) return 0; TMP_START; /* for each variable v we need to pack to degree deg_v(A) except for the outermost variable */ Abounds = TMP_ARRAY_ALLOC(4*(nvars + 1), slong); Bbounds = Abounds + nvars + 1; Qbounds = Bbounds + nvars + 1; Edegs = Qbounds + nvars + 1; mpoly_degrees_si(Abounds, A->exps, A->length, bits, ctx->minfo); mpoly_degrees_si(Bbounds, B->exps, B->length, bits, ctx->minfo); Abounds[nvars] = fmpz_mod_mpolyn_lastdeg(A, ctx); Bbounds[nvars] = fmpz_mod_mpolyn_lastdeg(B, ctx); prod_deg = 1; for (i = 0; i <= nvars; i++) { /* if divides, expected degrees */ Edegs[i] = Abounds[i] - Bbounds[i]; if (Abounds[i] < Bbounds[i]) { success = 0; goto cleanup; } if (i != 0) { /* variable of index i is not the outermost */ Qbounds[i] = Abounds[i] + 1; Bbounds[i] = Abounds[i] + 1; } else { /* variable of index i is the outermost */ Qbounds[i] = Abounds[i] - Bbounds[i] + 1; Bbounds[i] = Bbounds[i] + 1; } if (z_add_checked(&Abounds[i], Abounds[i], 1) || z_mul_checked(&prod_deg, prod_deg, Abounds[i])) { success = 0; goto cleanup; } } _init_dense_mock(Ad, A, Abounds, ctx); _init_dense_mock(Bd, B, Bbounds, ctx); fmpz_mod_poly_init(Qd, ctx->ffinfo); fmpz_mod_poly_init(Rd, ctx->ffinfo); fmpz_mod_poly_divrem(Qd, Rd, Ad, Bd, ctx->ffinfo); success = fmpz_mod_poly_is_zero(Rd, ctx->ffinfo) && _from_dense(Q, Qbounds, Edegs, Qd, ctx); fmpz_mod_poly_clear(Qd, ctx->ffinfo); fmpz_mod_poly_clear(Rd, ctx->ffinfo); _clear_dense_mock(Ad); _clear_dense_mock(Bd); cleanup: TMP_END; return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/mpolyu.c000066400000000000000000000073511461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" /** 0 variables *************************************/ void fmpz_mod_mpoly_to_mpolyl_perm_deflate( fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t lctx, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { slong j, k, l; slong m = lctx->minfo->nvars; slong n = ctx->minfo->nvars; slong NA, NB; ulong * lexps; ulong * Bexps; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; fmpz_mod_mpoly_fit_length(A, B->length, ctx); A->length = B->length; lexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(A->bits, lctx->minfo); NB = mpoly_words_per_exp(B->bits, ctx->minfo); for (j = 0; j < B->length; j++) { fmpz_set(A->coeffs + j, B->coeffs + j); mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); for (k = 0; k < m; k++) { l = perm[k]; if (stride[l] == 1) { lexps[k] = (Bexps[l] - shift[l]); } else { FLINT_ASSERT(stride[l] != 0); FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == 0); lexps[k] = (Bexps[l] - shift[l]) / stride[l]; } } mpoly_set_monomial_ui(A->exps + NA*j, lexps, A->bits, lctx->minfo); } TMP_END; fmpz_mod_mpoly_sort_terms(A, lctx); FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(A, lctx)); } /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k < m + 2 l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void fmpz_mod_mpoly_from_mpolyl_perm_inflate( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride) { slong n = ctx->minfo->nvars; slong m = lctx->minfo->nvars; slong i, k, l; slong NA, NB; ulong * Bexps; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, lctx->minfo); fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); A->length = B->length; for (i = 0; i < B->length; i++) { fmpz_set(A->coeffs + i, B->coeffs + i); mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, lctx->minfo); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m; k++) { l = perm[k]; Aexps[l] += stride[l]*Bexps[k]; } mpoly_set_monomial_ui(A->exps + NA*i, Aexps, Abits, ctx->minfo); } TMP_END; fmpz_mod_mpoly_sort_terms(A, ctx); FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(A, ctx)); } flint-3.1.3/src/fmpz_mod_mpoly_factor/mpolyv.c000066400000000000000000000101721461254215100215060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_mpolyv_clear(fmpz_mod_mpolyv_t A, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mod_mpoly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } void fmpz_mod_mpolyv_fit_length( fmpz_mod_mpolyv_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length <= old_alloc) return; A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fmpz_mod_mpoly_struct); for (i = old_alloc; i < new_alloc; i++) fmpz_mod_mpoly_init(A->coeffs + i, ctx); A->alloc = new_alloc; } void fmpz_mod_mpolyv_set_coeff( fmpz_mod_mpolyv_t A, slong i, fmpz_mod_mpoly_t c, /* clobbered */ const fmpz_mod_mpoly_ctx_t ctx) { slong j; FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(c, ctx)); fmpz_mod_mpolyv_fit_length(A, i + 1, ctx); for (j = A->length; j < i; j++) fmpz_mod_mpoly_zero(A->coeffs + j, ctx); fmpz_mod_mpoly_swap(A->coeffs + i, c, ctx); A->length = FLINT_MAX(A->length, i + 1); } void fmpz_mod_mpoly_to_mpolyv( fmpz_mod_mpolyv_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_t xalpha, const fmpz_mod_mpoly_ctx_t ctx) { fmpz_mod_mpoly_t Q, T; fmpz_mod_mpoly_init(Q, ctx); fmpz_mod_mpoly_init(T, ctx); fmpz_mod_mpolyv_fit_length(A, 8, ctx); fmpz_mod_mpoly_divrem(Q, A->coeffs + 0, B, xalpha, ctx); A->length = 1; while (!fmpz_mod_mpoly_is_zero(Q, ctx)) { fmpz_mod_mpolyv_fit_length(A, A->length + 1, ctx); fmpz_mod_mpoly_divrem(T, A->coeffs + A->length, Q, xalpha, ctx); fmpz_mod_mpoly_swap(Q, T, ctx); A->length++; } while (A->length > 0 && fmpz_mod_mpoly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; fmpz_mod_mpoly_clear(Q, ctx); fmpz_mod_mpoly_clear(T, ctx); } void fmpz_mod_mpoly_from_mpolyv( fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpolyv_t B, const fmpz_mod_mpoly_t xalpha, const fmpz_mod_mpoly_ctx_t ctx) { slong i; fmpz_mod_mpoly_t T; fmpz_mod_mpoly_init(T, ctx); fmpz_mod_mpoly_zero(A, ctx); for (i = B->length - 1; i >= 0; i--) { fmpz_mod_mpoly_mul(T, A, xalpha, ctx); fmpz_mod_mpoly_add(A, T, B->coeffs + i, ctx); } fmpz_mod_mpoly_clear(T, ctx); fmpz_mod_mpoly_repack_bits_inplace(A, Abits, ctx); } int _fmpz_mod_mpoly_vec_content_mpoly( fmpz_mod_mpoly_t g, const fmpz_mod_mpoly_struct * A, slong Alen, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j1, j2; if (Alen <= 1) { if (Alen == 1) fmpz_mod_mpoly_make_monic(g, A + 0, ctx); else fmpz_mod_mpoly_zero(g, ctx); return 1; } j1 = 0; j2 = 1; for (i = 2; i < Alen; i++) { if (A[i].length < A[j1].length) j1 = i; else if (A[i].length < A[j2].length) j2 = i; } FLINT_ASSERT(j1 != j2); if (!fmpz_mod_mpoly_gcd(g, A + j1, A + j2, ctx)) return 0; for (i = 0; i < Alen; i++) { if (i == j1 || i == j2) continue; if (!fmpz_mod_mpoly_gcd(g, g, A + i, ctx)) return 0; } return 1; } void _fmpz_mod_mpoly_vec_divexact_mpoly( fmpz_mod_mpoly_struct * A, slong Alen, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) fmpz_mod_mpoly_divexact(A + i, A + i, c, ctx); } void _fmpz_mod_mpoly_vec_mul_mpoly( fmpz_mod_mpoly_struct * A, slong Alen, const fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) fmpz_mod_mpoly_mul(A + i, A + i, c, ctx); } flint-3.1.3/src/fmpz_mod_mpoly_factor/polyu3_mod_hlift.c000066400000000000000000000531721461254215100234470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" #if FLINT_WANT_ASSERT static void fmpz_mod_polyu_get_fmpz_mod_polyun( fmpz_mod_polyu_t A, const fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx) { slong i, j; A->length = 0; for (i = 0; i < B->length; i++) { for (j = B->coeffs[i].length - 1; j >= 0; j--) { if (fmpz_is_zero(B->coeffs[i].coeffs + j)) continue; fmpz_mod_polyu_fit_length(A, A->length + 1, ctx); fmpz_set(A->coeffs + A->length, B->coeffs[i].coeffs + j); A->exps[A->length] = B->exps[i] + j; A->length++; } } } static void fmpz_mod_polyu_sort_terms(fmpz_mod_polyu_t A) { slong i, j; for (i = 1; i < A->length; i++) for (j = i; j > 0 && A->exps[j - 1] < A->exps[j]; j--) { fmpz_swap(A->coeffs + j - 1, A->coeffs + j); FLINT_SWAP(ulong, A->exps[j - 1], A->exps[j]); } return; } int fmpz_mod_polyu_is_canonical( const fmpz_mod_polyu_t A, const fmpz_mod_ctx_t ctx) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (!fmpz_mod_is_canonical(A->coeffs + i, ctx) || fmpz_is_zero(A->coeffs + i)) return 0; if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } static void fmpz_mod_polyu_combine_like_terms( fmpz_mod_polyu_t A, const fmpz_mod_ctx_t ctx) { slong in, out; out = -1; for (in = 0; in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= 0 && A->exps[out] == A->exps[in]) { fmpz_mod_add(A->coeffs + out, A->coeffs + out, A->coeffs + in, ctx); } else { if (out < 0 || !fmpz_is_zero(A->coeffs + out)) out++; if (out != in) { A->exps[out] = A->exps[in]; fmpz_set(A->coeffs + out, A->coeffs + in); } } } if (out < 0 || !fmpz_is_zero(A->coeffs + out)) out++; A->length = out; } static int fmpz_mod_polyu_equal( fmpz_mod_polyu_t A, fmpz_mod_polyu_t B) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (!fmpz_equal(A->coeffs + i, B->coeffs + i)) return 0; if (A->exps[i] != B->exps[i]) return 0; } return 1; } static void fmpz_mod_polyu_mul( fmpz_mod_polyu_t A, const fmpz_mod_polyu_t B, const fmpz_mod_polyu_t C, const fmpz_mod_ctx_t ctx) { slong Ai, Bi, Ci; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); fmpz_mod_polyu_fit_length(A, B->length*C->length, ctx); Ai = 0; for (Bi = 0; Bi < B->length; Bi++) for (Ci = 0; Ci < C->length; Ci++) { A->exps[Ai] = B->exps[Bi] + C->exps[Ci]; fmpz_mod_mul(A->coeffs + Ai, B->coeffs + Bi, C->coeffs + Ci, ctx); Ai++; } A->length = Ai; fmpz_mod_polyu_sort_terms(A); fmpz_mod_polyu_combine_like_terms(A, ctx); } #endif void fmpz_mod_poly_fill_powers( fmpz_mod_poly_t alphapow, slong target, const fmpz_mod_ctx_t ctx) { if (target + 1 > alphapow->length) { slong k; slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); fmpz_mod_poly_fit_length(alphapow, target + 1, ctx); for (k = oldlength; k <= target; k++) { fmpz_mod_mul(alphapow->coeffs + k, alphapow->coeffs + k - 1, alphapow->coeffs + 1, ctx); } alphapow->length = target + 1; } } void fmpz_mod_polyu3_interp_reduce_2sm_bpoly( fmpz_mod_bpoly_t Ap, fmpz_mod_bpoly_t Am, const fmpz_mod_polyu_t A, fmpz_mod_poly_t alpha, const fmpz_mod_ctx_t ctx) { slong i; slong cur0, cur1, e0, e1, e2; fmpz_t t, tp, tm; const fmpz * Acoeffs = A->coeffs; const ulong * Aexps = A->exps; fmpz_init(t); fmpz_init(tp); fmpz_init(tm); fmpz_mod_bpoly_zero(Ap, ctx); fmpz_mod_bpoly_zero(Am, ctx); FLINT_ASSERT(A->length > 0); i = 0; cur0 = extract_exp(Aexps[i], 2, 3); cur1 = extract_exp(Aexps[i], 1, 3); e2 = extract_exp(Aexps[i], 0, 3); fmpz_mod_poly_fill_powers(alpha, e2, ctx); fmpz_zero(tp); fmpz_zero(tm); if (e2 & 1) fmpz_mod_mul(tm, alpha->coeffs + e2, Acoeffs + i, ctx); else fmpz_mod_mul(tp, alpha->coeffs + e2, Acoeffs + i, ctx); for (i = 1; i < A->length; i++) { e0 = extract_exp(Aexps[i], 2, 3); e1 = extract_exp(Aexps[i], 1, 3); e2 = extract_exp(Aexps[i], 0, 3); FLINT_ASSERT(e0 <= cur0); if (e0 < cur0 || e1 < cur1) { fmpz_mod_add(t, tp, tm, ctx); fmpz_mod_bpoly_set_coeff(Ap, cur0, cur1, t, ctx); fmpz_mod_sub(t, tp, tm, ctx); fmpz_mod_bpoly_set_coeff(Am, cur0, cur1, t, ctx); fmpz_zero(tp); fmpz_zero(tm); } else { FLINT_ASSERT(e0 == cur0); FLINT_ASSERT(e1 == cur1); } cur0 = e0; cur1 = e1; fmpz_mod_poly_fill_powers(alpha, e2, ctx); #if WANT_ASSERT fmpz_mod_pow_ui(t, alpha->coeffs + 1, e2, ctx); FLINT_ASSERT(fmpz_equal(alpha->coeffs + e2, t)); #endif if (e2 & 1) fmpz_mod_addmul(tm, tm, alpha->coeffs + e2, Acoeffs + i, ctx); else fmpz_mod_addmul(tp, tp, alpha->coeffs + e2, Acoeffs + i, ctx); } fmpz_mod_add(t, tp, tm, ctx); fmpz_mod_bpoly_set_coeff(Ap, cur0, cur1, t, ctx); fmpz_mod_sub(t, tp, tm, ctx); fmpz_mod_bpoly_set_coeff(Am, cur0, cur1, t, ctx); fmpz_clear(t); fmpz_clear(tp); fmpz_clear(tm); } /* T(x0, x1, x2) is in F[x2][x0, x1] A(x0, x1) are B(x0, x1) are in F[x0, x1] set T so that T(x0, x1, x2) == A(x0, x1) mod (x2 - alpha) T(x0, x1, x2) == B(x0, x1) mod (x2 + alpha) */ void fmpz_mod_polyu3n_interp_lift_2sm_bpoly( slong * lastdeg, fmpz_mod_polyun_t T, const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_t alpha, const fmpz_mod_ctx_t ctx) { slong lastlength = 0; fmpz_mod_poly_struct * Tcoeffs; ulong * Texps; slong Ti; fmpz_mod_poly_struct * Acoeffs = A->coeffs; slong Ai, ai; fmpz_mod_poly_struct * Bcoeffs = B->coeffs; slong Bi, bi; fmpz_t u, v, Avalue, Bvalue; fmpz_t d0, d1; fmpz_init(d0); fmpz_init(d1); fmpz_init(u); fmpz_init(v); fmpz_init(Avalue); fmpz_init(Bvalue); fmpz_cdiv_q_2exp(d0, fmpz_mod_ctx_modulus(ctx), 1); fmpz_mod_add(d1, alpha, alpha, ctx); fmpz_mod_inv(d1, d1, ctx); fmpz_mod_polyun_fit_length(T, FLINT_MAX(A->length, B->length), ctx); Tcoeffs = T->coeffs; Texps = T->exps; Ti = 0; Ai = A->length - 1; Bi = B->length - 1; ai = (Ai < 0) ? 0 : fmpz_mod_poly_degree(A->coeffs + Ai, ctx); bi = (Bi < 0) ? 0 : fmpz_mod_poly_degree(B->coeffs + Bi, ctx); while (Ai >= 0 || Bi >= 0) { if (Ti >= T->alloc) { fmpz_mod_polyun_fit_length(T, Ti + FLINT_MAX(Ai, Bi) + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; } FLINT_ASSERT(Ai < 0 || !fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); FLINT_ASSERT(Bi < 0 || !fmpz_is_zero(Bcoeffs[Bi].coeffs + bi)); fmpz_zero(Avalue); if (Ai >= 0) { fmpz_set(Avalue, Acoeffs[Ai].coeffs + ai); Texps[Ti] = pack_exp3(Ai, ai, 0); } fmpz_zero(Bvalue); if (Bi >= 0) { ulong Bexp = pack_exp3(Bi, bi, 0); if (fmpz_is_zero(Avalue)) { fmpz_set(Bvalue, Bcoeffs[Bi].coeffs + bi); Texps[Ti] = Bexp; } else { if (Texps[Ti] <= Bexp) { fmpz_set(Bvalue, Bcoeffs[Bi].coeffs + bi); } if (Texps[Ti] < Bexp) { fmpz_zero(Avalue); Texps[Ti] = Bexp; } } } fmpz_mod_sub(u, Avalue, Bvalue, ctx); fmpz_mod_add(v, Avalue, Bvalue, ctx); fmpz_mod_mul(u, u, d1, ctx); fmpz_mod_mul(v, v, d0, ctx); FLINT_ASSERT(!fmpz_is_zero(u) || !fmpz_is_zero(v)); fmpz_mod_poly_fit_length(Tcoeffs + Ti, 2, ctx); fmpz_set(Tcoeffs[Ti].coeffs + 0, v); fmpz_set(Tcoeffs[Ti].coeffs + 1, u); Tcoeffs[Ti].length = 1 + !fmpz_is_zero(u); lastlength = FLINT_MAX(lastlength, Tcoeffs[Ti].length); Ti++; if (!fmpz_is_zero(Avalue)) { do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx); } } if (!fmpz_is_zero(Bvalue)) { do { bi--; } while (bi >= 0 && fmpz_is_zero(Bcoeffs[Bi].coeffs + bi)); if (bi < 0) { do { Bi--; } while (Bi >= 0 && Bcoeffs[Bi].length == 0); if (Bi >= 0) bi = fmpz_mod_poly_degree(Bcoeffs + Bi, ctx); } } } T->length = Ti; FLINT_ASSERT(fmpz_mod_polyun_is_canonical(T, ctx)); fmpz_clear(d0); fmpz_clear(d1); fmpz_clear(u); fmpz_clear(v); fmpz_clear(Avalue); fmpz_clear(Bvalue); *lastdeg = lastlength - 1; return; } int fmpz_mod_polyu3n_interp_crt_2sm_bpoly( slong * lastdeg, fmpz_mod_polyun_t F, fmpz_mod_polyun_t T, fmpz_mod_bpoly_t A, fmpz_mod_bpoly_t B, const fmpz_mod_poly_t modulus, fmpz_mod_poly_t alphapow, const fmpz_mod_ctx_t ctx) { int changed = 0; slong lastlength = 0; fmpz_t zzero; fmpz_mod_poly_t zero; fmpz_mod_poly_struct * Tcoeffs; ulong * Texps; slong Ti; fmpz_mod_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; slong Flen = F->length; slong Fi; fmpz_mod_poly_struct * Acoeffs = A->coeffs; slong Ai, ai; fmpz_mod_poly_struct * Bcoeffs = B->coeffs; slong Bi, bi; fmpz_mod_poly_struct * Fvalue; fmpz_t u, v, FvalueA, FvalueB; const fmpz * Avalue, * Bvalue; int texp_set, cmp; fmpz_init(u); fmpz_init(v); fmpz_init(FvalueA); fmpz_init(FvalueB); #if FLINT_WANT_ASSERT fmpz_mod_poly_evaluate_fmpz(u, modulus, alphapow->coeffs + 1, ctx); fmpz_mod_mul(u, u, alphapow->coeffs + 1, ctx); fmpz_mod_add(u, u, u, ctx); FLINT_ASSERT(fmpz_is_one(u)); fmpz_mod_neg(u, alphapow->coeffs + 1, ctx); fmpz_mod_poly_evaluate_fmpz(u, modulus, u, ctx); fmpz_mod_mul(u, u, alphapow->coeffs + 1, ctx); fmpz_mod_add(u, u, u, ctx); FLINT_ASSERT(fmpz_is_one(u)); #endif FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(fmpz_mod_bpoly_is_canonical(B, ctx)); FLINT_ASSERT(fmpz_mod_polyun_is_canonical(F, ctx)); fmpz_mod_polyun_fit_length(T, FLINT_MAX(Flen, A->length), ctx); Tcoeffs = T->coeffs; Texps = T->exps; fmpz_init(zzero); zero->alloc = 0; zero->length = 0; zero->coeffs = NULL; Ti = Fi = 0; Ai = A->length - 1; Bi = B->length - 1; ai = (Ai < 0) ? 0 : fmpz_mod_poly_degree(A->coeffs + Ai, ctx); bi = (Bi < 0) ? 0 : fmpz_mod_poly_degree(B->coeffs + Bi, ctx); while (Fi < Flen || Ai >= 0 || Bi >= 0) { if (Ti >= T->alloc) { slong extra = Flen - Fi; extra = FLINT_MAX(extra, Ai); extra = FLINT_MAX(extra, Bi); fmpz_mod_polyun_fit_length(T, Ti + extra + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; } FLINT_ASSERT(Fi >= Flen || Fcoeffs[Fi].length > 0); FLINT_ASSERT(Ai < 0 ||!fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); FLINT_ASSERT(Bi < 0 ||!fmpz_is_zero(Bcoeffs[Bi].coeffs + bi)); Fvalue = zero; texp_set = 0; if (Fi < Flen) { Fvalue = Fcoeffs + Fi; texp_set = 1; Texps[Ti] = Fexps[Fi]; } Avalue = zzero; if (Ai >= 0) { ulong Aexp = pack_exp3(Ai, ai, 0); cmp = (!texp_set) ? -1 : Texps[Ti] < Aexp ? -1 : Texps[Ti] > Aexp ? 1 : 0; if (cmp <= 0) { Avalue = Acoeffs[Ai].coeffs + ai; } if (cmp < 0) { Fvalue = zero; texp_set = 1; Texps[Ti] = Aexp; } } Bvalue = zzero; if (Bi >= 0) { ulong Bexp = pack_exp3(Bi, bi, 0); cmp = (!texp_set) ? -1 : Texps[Ti] < Bexp ? -1 : Texps[Ti] > Bexp ? 1 : 0; if (cmp <= 0) { Bvalue = Bcoeffs[Bi].coeffs + bi; } if (cmp < 0) { Fvalue = zero; Avalue = zzero; texp_set = 1; Texps[Ti] = Bexp; } } FLINT_ASSERT(texp_set); fmpz_mod_poly_eval2_pow(FvalueA, FvalueB, Fvalue, alphapow, ctx); fmpz_mod_sub(FvalueA, FvalueA, Avalue, ctx); fmpz_mod_sub(FvalueB, FvalueB, Bvalue, ctx); fmpz_mod_sub(u, FvalueB, FvalueA, ctx); fmpz_mod_add(v, FvalueB, FvalueA, ctx); fmpz_mod_mul(v, v, alphapow->coeffs + 1, ctx); fmpz_mod_neg(v, v, ctx); changed |= !fmpz_is_zero(u) || !fmpz_is_zero(v); fmpz_mod_poly_addmul_linear(Tcoeffs + Ti, Fvalue, modulus, u, v, ctx); FLINT_ASSERT(Tcoeffs[Ti].length >= Fvalue->length); Fi += (Fvalue != zero); if (Avalue != zzero) { do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx); } } if (Bvalue != zzero) { do { bi--; } while (bi >= 0 && fmpz_is_zero(Bcoeffs[Bi].coeffs + bi)); if (bi < 0) { do { Bi--; } while (Bi >= 0 && Bcoeffs[Bi].length == 0); if (Bi >= 0) bi = fmpz_mod_poly_degree(Bcoeffs + Bi, ctx); } } FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeffs + Ti, ctx)); lastlength = FLINT_MAX(lastlength, Tcoeffs[Ti].length); Ti++; } T->length = Ti; if (changed) fmpz_mod_polyun_swap(T, F); FLINT_ASSERT(fmpz_mod_polyun_is_canonical(F, ctx)); fmpz_clear(zzero); fmpz_clear(u); fmpz_clear(v); fmpz_clear(FvalueA); fmpz_clear(FvalueB); *lastdeg = lastlength - 1; return changed; } /* Input A, B0, B1, with A(y,x,z) = B0(y,x,z)*B1(y,x,z) mod (y-beta) return -1: suspect that B0(beta,x,z) & B1(beta,x,z) are not pairwise prime, i.e. could not find an eval point for z making them pairwise prime, or A(y,x,z) has wrong degree in x, or could not find enough eval points for z with the required degree in x 0: lift of B0*B1 to true factors is impossible 1: successfully lifted B0*B1 to true factors BB0*BB1 without changing lc_x */ /* r factor version */ int fmpz_mod_polyu3_hlift( slong r, fmpz_mod_polyun_struct * BB, fmpz_mod_polyu_t A, fmpz_mod_polyu_struct * B, const fmpz_t beta, slong degree_inner, /* required degree in x */ const fmpz_mod_ctx_t ctx) { int success/*, Eok*/; slong i, j; fmpz_mod_polyun_t T; fmpz_mod_bpoly_struct * Bp, * Bm; fmpz_mod_bpoly_t Ap, Am; fmpz_mod_poly_t modulus, alphapow, t1, t2; fmpz_t alpha, c; slong * BBdegZ; slong AdegY, AdegX, AdegZ; slong bad_primes_left; fmpz_mod_poly_bpoly_stack_t St; /* if (r < 3) return n_polyu3_mod_hlift2(BB + 0, BB + 1, A, B + 0, B + 1, beta, degree_inner, ctx); */ FLINT_ASSERT(fmpz_mod_polyu_is_canonical(A, ctx)); for (i = 0; i < r; i++) FLINT_ASSERT(fmpz_mod_polyu_is_canonical(B + i, ctx)); fmpz_init(alpha); fmpz_init(c); BBdegZ = FLINT_ARRAY_ALLOC(r, slong); Bp = FLINT_ARRAY_ALLOC(r, fmpz_mod_bpoly_struct); Bm = FLINT_ARRAY_ALLOC(r, fmpz_mod_bpoly_struct); for (i = 0; i < r; i++) { fmpz_mod_bpoly_init(Bp + i, ctx); fmpz_mod_bpoly_init(Bm + i, ctx); } fmpz_mod_polyun_init(T, ctx); fmpz_mod_bpoly_init(Ap, ctx); fmpz_mod_bpoly_init(Am, ctx); fmpz_mod_poly_init(modulus, ctx); fmpz_mod_poly_init(alphapow, ctx); fmpz_mod_poly_init(t1, ctx); fmpz_mod_poly_init(t2, ctx); fmpz_mod_poly_stack_init(St->poly_stack); fmpz_mod_bpoly_stack_init(St->bpoly_stack); fmpz_mod_polyu3_degrees(&AdegY, &AdegX, &AdegZ, A); if (AdegX != degree_inner) { success = -1; goto cleanup; } fmpz_mod_poly_fit_length(alphapow, FLINT_MAX(WORD(3), AdegZ + 2), ctx); fmpz_mod_poly_one(modulus, ctx); FLINT_ASSERT(fmpz_is_odd(fmpz_mod_ctx_modulus(ctx))); fmpz_fdiv_q_2exp(alpha, fmpz_mod_ctx_modulus(ctx), 1); bad_primes_left = FLINT_MAX(5, AdegZ); goto choose_prime; choose_prime: fmpz_sub_ui(alpha, alpha, 1); if (fmpz_sgn(alpha) <= 0) { success = -1; goto cleanup; } FLINT_ASSERT(fmpz_mod_is_canonical(alpha, ctx)); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; fmpz_one(alphapow->coeffs + 0); fmpz_set(alphapow->coeffs + 1, alpha); fmpz_mod_polyu3_interp_reduce_2sm_bpoly(Ap, Am, A, alphapow, ctx); for (i = 0; i < r; i++) { fmpz_mod_polyu3_interp_reduce_2sm_bpoly(Bp + i, Bm + i, B + i, alphapow, ctx); } success = fmpz_mod_bpoly_hlift(r, Ap, Bp, beta, degree_inner, ctx, St); if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } success = fmpz_mod_bpoly_hlift(r, Am, Bm, beta, degree_inner, ctx, St); if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } if (fmpz_mod_poly_degree(modulus, ctx) > 0) { fmpz_mod_poly_evaluate_fmpz(c, modulus, alpha, ctx); #if WANT_ASSERT { fmpz_t cc; fmpz_init(cc); fmpz_mod_neg(cc, alpha, ctx); fmpz_mod_poly_evaluate_fmpz(cc, modulus, cc, ctx); FLINT_ASSERT(fmpz_equal(cc, c)); fmpz_clear(cc); } #endif fmpz_mod_mul(c, c, alpha, ctx); fmpz_mod_add(c, c, c, ctx); fmpz_mod_inv(c, c, ctx); fmpz_mod_poly_scalar_mul_fmpz(modulus, modulus, c, ctx); for (i = 0; i < r; i++) { fmpz_mod_polyu3n_interp_crt_2sm_bpoly(BBdegZ + i, BB + i, T, Bp + i, Bm + i, modulus, alphapow, ctx); } } else { for (i = 0; i < r; i++) { fmpz_mod_polyu3n_interp_lift_2sm_bpoly(BBdegZ + i, BB + i, Bp + i, Bm + i, alpha, ctx); } } fmpz_mod_mul(c, alpha, alpha, ctx); fmpz_mod_neg(c, c, ctx); fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 2, c, ctx); j = BBdegZ[0]; for (i = 1; i < r; i++) j += BBdegZ[i]; if (j > AdegZ) { success = 0; goto cleanup; } if (fmpz_mod_poly_degree(modulus, ctx) <= AdegZ) { goto choose_prime; } success = 1; cleanup: #if FLINT_WANT_ASSERT if (success == 1) { fmpz_mod_polyu_t T1, T2, T3; fmpz_mod_polyu_init(T1); fmpz_mod_polyu_init(T2); fmpz_mod_polyu_init(T3); fmpz_mod_polyu_get_fmpz_mod_polyun(T2, BB + 0, ctx); fmpz_mod_polyu_get_fmpz_mod_polyun(T3, BB + 1, ctx); fmpz_mod_polyu_mul(T1, T2, T3, ctx); for (i = 2; i < r; i++) { fmpz_mod_polyu_get_fmpz_mod_polyun(T3, BB + i, ctx); fmpz_mod_polyu_mul(T2, T1, T3, ctx); fmpz_mod_polyu_swap(T2, T1); } FLINT_ASSERT(fmpz_mod_polyu_equal(A, T1)); fmpz_mod_polyu_clear(T1); fmpz_mod_polyu_clear(T2); fmpz_mod_polyu_clear(T3); } #endif fmpz_mod_polyun_clear(T, ctx); fmpz_mod_bpoly_clear(Ap, ctx); fmpz_mod_bpoly_clear(Am, ctx); for (i = 0; i < r; i++) { fmpz_mod_bpoly_clear(Bp + i, ctx); fmpz_mod_bpoly_clear(Bm + i, ctx); } flint_free(BBdegZ); flint_free(Bp); flint_free(Bm); fmpz_mod_poly_clear(modulus, ctx); fmpz_mod_poly_clear(alphapow, ctx); fmpz_mod_poly_clear(t1, ctx); fmpz_mod_poly_clear(t2, ctx); fmpz_mod_poly_stack_clear(St->poly_stack); fmpz_mod_bpoly_stack_clear(St->bpoly_stack); fmpz_clear(alpha); fmpz_clear(c); FLINT_ASSERT(success || fmpz_abs_fits_ui(fmpz_mod_ctx_modulus(ctx))); return success; } flint-3.1.3/src/fmpz_mod_mpoly_factor/polyun.c000066400000000000000000000113001461254215100215000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_polyun_is_canonical( const fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (!fmpz_mod_poly_is_canonical(A->coeffs + i, ctx) || fmpz_mod_poly_is_zero(A->coeffs + i, ctx)) { return 0; } if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } void fmpz_mod_polyun_clear( fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mod_poly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); flint_free(A->exps); } void fmpz_mod_polyun_realloc( fmpz_mod_polyun_t A, slong len, const fmpz_mod_ctx_t ctx) { slong i, old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, ulong); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fmpz_mod_poly_struct); for (i = old_alloc; i < new_alloc; i++) fmpz_mod_poly_init(A->coeffs + i, ctx); A->alloc = new_alloc; } int fmpz_mod_polyun_equal( fmpz_mod_polyun_t A, const fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (A->exps[i] != B->exps[i]) return 0; if (!fmpz_mod_poly_equal(A->coeffs + i, B->coeffs + i, ctx)) return 0; } return 1; } void fmpz_mod_polyun_set( fmpz_mod_polyun_t A, const fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_polyun_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; fmpz_mod_poly_set(A->coeffs + i, B->coeffs + i, ctx); } A->length = B->length; } void fmpz_mod_polyun_one(fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx) { fmpz_mod_polyun_fit_length(A, 1, ctx); fmpz_mod_poly_one(A->coeffs + 0, ctx); A->exps[0] = 0; A->length = 1; } void fmpz_mod_mpoly_get_polyu1n( fmpz_mod_polyun_t A, const fmpz_mod_mpoly_t B, slong varx, slong vary, const fmpz_mod_mpoly_ctx_t ctx) { slong j, Ai; ulong Bexpx, Bexpy; slong Boffx, Bshiftx, Boffy, Bshifty; ulong mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); Ai = -1; for (j = 0; j < B->length; j++) { Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask; Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask; if (Ai < 0 || A->exps[Ai] != Bexpx) { Ai++; fmpz_mod_polyun_fit_length(A, Ai + 1, ctx->ffinfo); A->exps[Ai] = Bexpx; fmpz_mod_poly_zero(A->coeffs + Ai, ctx->ffinfo); } fmpz_mod_poly_set_coeff_fmpz(A->coeffs + Ai, Bexpy, B->coeffs + j, ctx->ffinfo); if (fmpz_mod_poly_is_zero(A->coeffs + Ai, ctx->ffinfo)) Ai--; } A->length = Ai + 1; FLINT_ASSERT(fmpz_mod_polyun_is_canonical(A, ctx->ffinfo)); } void fmpz_mod_mpoly_set_polyu1n( fmpz_mod_mpoly_t B, const fmpz_mod_polyun_t A, slong varx, slong vary, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j; slong Boffx, Bshiftx, Boffy, Bshifty; slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); B->length = 0; for (i = 0; i < A->length; i++) { for (j = A->coeffs[i].length - 1; j >= 0; j--) { if (fmpz_is_zero(A->coeffs[i].coeffs + j)) continue; fmpz_mod_mpoly_fit_length(B, B->length + 1, ctx); mpoly_monomial_zero(B->exps + N*B->length, N); (B->exps + N*B->length)[Boffx] += A->exps[i] << Bshiftx; (B->exps + N*B->length)[Boffy] += j << Bshifty; fmpz_set(B->coeffs + B->length, A->coeffs[i].coeffs + j); B->length++; } } FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(B, ctx)); } flint-3.1.3/src/fmpz_mod_mpoly_factor/realloc.c000066400000000000000000000032751461254215100216070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_mpoly_factor_realloc( fmpz_mod_mpoly_factor_t f, slong alloc, const fmpz_mod_mpoly_ctx_t ctx) { slong i; if (alloc < 1) { fmpz_mod_mpoly_factor_clear(f, ctx); fmpz_mod_mpoly_factor_init(f, ctx); return; } if (f->alloc > 0) { if (f->alloc > alloc) { for (i = alloc; i < f->alloc; i++) { fmpz_mod_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } f->exp = FLINT_ARRAY_REALLOC(f->exp, alloc, fmpz); f->poly = FLINT_ARRAY_REALLOC(f->poly, alloc, fmpz_mod_mpoly_struct); } else if (f->alloc < alloc) { f->exp = FLINT_ARRAY_REALLOC(f->exp, alloc, fmpz); f->poly = FLINT_ARRAY_REALLOC(f->poly, alloc, fmpz_mod_mpoly_struct); for (i = f->alloc; i < alloc; i++) { fmpz_mod_mpoly_init(f->poly + i, ctx); fmpz_init(f->exp + i); } } } else { f->exp = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); f->poly = FLINT_ARRAY_ALLOC(alloc, fmpz_mod_mpoly_struct); for (i = 0; i < alloc; i++) fmpz_mod_mpoly_init(f->poly + i, ctx); } f->alloc = alloc; } flint-3.1.3/src/fmpz_mod_mpoly_factor/set_nmod_mpoly_factor.c000066400000000000000000000016121461254215100245450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" void _fmpz_mod_mpoly_factor_set_nmod_mpoly_factor( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx, const nmod_mpoly_factor_t nf, const nmod_mpoly_ctx_t nctx) { slong i; fmpz_set_ui(f->constant, nf->constant); fmpz_mod_mpoly_factor_fit_length(f, nf->num, ctx); f->num = nf->num; for (i = 0; i < nf->num; i++) { fmpz_set(f->exp + i, nf->exp + i); _fmpz_mod_mpoly_set_nmod_mpoly(f->poly + i, ctx, nf->poly + i, nctx); } } flint-3.1.3/src/fmpz_mod_mpoly_factor/sort.c000066400000000000000000000034661461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly_factor.h" typedef struct { slong idx; fmpz exp; const fmpz_mod_mpoly_struct * polys; const fmpz_mod_mpoly_ctx_struct * ctx; } sort_struct; static int _sort(const void * a_, const void * b_) { int cmp; const sort_struct * a = (const sort_struct *) a_; const sort_struct * b = (const sort_struct *) b_; const fmpz_mod_mpoly_struct * apoly = a->polys + a->idx; const fmpz_mod_mpoly_struct * bpoly = b->polys + b->idx; cmp = fmpz_cmp(&a->exp, &b->exp); if (cmp != 0) return cmp; return fmpz_mod_mpoly_cmp(apoly, bpoly, a->ctx); } void fmpz_mod_mpoly_factor_sort( fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx) { slong i; sort_struct * data; fmpz_mod_mpoly_struct * fc; if (f->num < 1) return; data = FLINT_ARRAY_ALLOC(f->num, sort_struct); for (i = 0; i < f->num; i++) { data[i].idx = i; data[i].exp = f->exp[i]; data[i].polys = f->poly; data[i].ctx = ctx; } qsort(data, f->num, sizeof(sort_struct), _sort); /* we will not permute in place */ fc = FLINT_ARRAY_ALLOC(f->num, fmpz_mod_mpoly_struct); memcpy(fc, f->poly, f->num*sizeof(fmpz_mod_mpoly_struct)); for (i = 0; i < f->num; i++) { f->exp[i] = data[i].exp; f->poly[i] = fc[data[i].idx]; } flint_free(fc); flint_free(data); return; } flint-3.1.3/src/fmpz_mod_mpoly_factor/stack.c000066400000000000000000000113321461254215100212640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" void fmpz_mod_poly_stack_init(fmpz_mod_poly_stack_t S) { S->alloc = 0; S->array = NULL; S->top = 0; } void fmpz_mod_poly_stack_clear(fmpz_mod_poly_stack_t S) { slong i; FLINT_ASSERT(S->top == 0); for (i = 0; i < S->alloc; i++) { fmpz_mod_poly_clear(S->array[i], NULL); flint_free(S->array[i]); } flint_free(S->array); } /* insure that k slots are available after top and return pointer to top */ fmpz_mod_poly_struct ** fmpz_mod_poly_stack_fit_request( fmpz_mod_poly_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->alloc >= S->top); if (S->top + k > S->alloc) { newalloc = FLINT_MAX(1, S->top + k); S->array = FLINT_ARRAY_REALLOC(S->array, newalloc, fmpz_mod_poly_struct *); for (i = S->alloc; i < newalloc; i++) { S->array[i] = FLINT_ARRAY_ALLOC(1, fmpz_mod_poly_struct); fmpz_mod_poly_init(S->array[i], NULL); } S->alloc = newalloc; } return S->array + S->top; } void fmpz_mod_bpoly_stack_init(fmpz_mod_bpoly_stack_t S) { S->alloc = 0; S->array = NULL; S->top = 0; } void fmpz_mod_bpoly_stack_clear(fmpz_mod_bpoly_stack_t S) { slong i; FLINT_ASSERT(S->top == 0); for (i = 0; i < S->alloc; i++) { fmpz_mod_bpoly_clear(S->array[i], NULL); flint_free(S->array[i]); } flint_free(S->array); } /* insure that k slots are available after top and return pointer to top */ fmpz_mod_bpoly_struct ** fmpz_mod_bpoly_stack_fit_request( fmpz_mod_bpoly_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->alloc >= S->top); if (S->top + k > S->alloc) { newalloc = FLINT_MAX(1, S->top + k); S->array = FLINT_ARRAY_REALLOC(S->array, newalloc, fmpz_mod_bpoly_struct *); for (i = S->alloc; i < newalloc; i++) { S->array[i] = FLINT_ARRAY_ALLOC(1, fmpz_mod_bpoly_struct); fmpz_mod_bpoly_init(S->array[i], NULL); } S->alloc = newalloc; } return S->array + S->top; } void fmpz_mod_polyun_stack_init(fmpz_mod_polyun_stack_t S) { S->alloc = 0; S->array = NULL; S->top = 0; } void fmpz_mod_polyun_stack_clear(fmpz_mod_polyun_stack_t S) { slong i; FLINT_ASSERT(S->top == 0); for (i = 0; i < S->alloc; i++) { fmpz_mod_polyun_clear(S->array[i], NULL); flint_free(S->array[i]); } flint_free(S->array); } /* insure that k slots are available after top and return pointer to top */ fmpz_mod_polyun_struct ** fmpz_mod_polyun_stack_fit_request( fmpz_mod_polyun_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->alloc >= S->top); if (S->top + k > S->alloc) { newalloc = FLINT_MAX(1, S->top + k); S->array = FLINT_ARRAY_REALLOC(S->array, newalloc, fmpz_mod_polyun_struct *); for (i = S->alloc; i < newalloc; i++) { S->array[i] = FLINT_ARRAY_ALLOC(1, fmpz_mod_polyun_struct); fmpz_mod_polyun_init(S->array[i], NULL); } S->alloc = newalloc; } return S->array + S->top; } void fmpz_mod_mpolyn_stack_init(fmpz_mod_mpolyn_stack_t S, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx) { S->alloc = 0; S->array = NULL; S->top = 0; S->bits = bits; } void fmpz_mod_mpolyn_stack_clear( fmpz_mod_mpolyn_stack_t S, const fmpz_mod_mpoly_ctx_t ctx) { slong i; FLINT_ASSERT(S->top == 0); for (i = 0; i < S->alloc; i++) { fmpz_mod_mpolyn_clear(S->array[i], ctx); flint_free(S->array[i]); } flint_free(S->array); } /* insure that k slots are available after top and return pointer to top */ fmpz_mod_mpolyn_struct ** fmpz_mod_mpolyn_stack_fit_request( fmpz_mod_mpolyn_stack_t S, slong k, const fmpz_mod_mpoly_ctx_t ctx) { slong newalloc, i; FLINT_ASSERT(S->alloc >= S->top); if (S->top + k > S->alloc) { newalloc = FLINT_MAX(1, S->top + k); S->array = FLINT_ARRAY_REALLOC(S->array, newalloc, fmpz_mod_mpolyn_struct *); for (i = S->alloc; i < newalloc; i++) { S->array[i] = FLINT_ARRAY_ALLOC(1, fmpz_mod_mpolyn_struct); fmpz_mod_mpolyn_init(S->array[i], S->bits, ctx); } S->alloc = newalloc; } return S->array + S->top; } flint-3.1.3/src/fmpz_mod_mpoly_factor/test/000077500000000000000000000000001461254215100207725ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_mpoly_factor/test/main.c000066400000000000000000000027401461254215100220650ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor.c" #include "t-factor_squarefree.c" #include "t-factor_wang.c" #include "t-factor_zassenhaus.c" #include "t-factor_zippel.c" #include "t-gcd_brown.c" #include "t-gcd_hensel.c" #include "t-gcd_subresultant.c" #include "t-gcd_zippel2.c" #include "t-gcd_zippel.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mod_mpoly_factor), TEST_FUNCTION(fmpz_mod_mpoly_factor_squarefree), TEST_FUNCTION(fmpz_mod_mpoly_factor_wang), TEST_FUNCTION(fmpz_mod_mpoly_factor_zassenhaus), TEST_FUNCTION(fmpz_mod_mpoly_factor_zippel), TEST_FUNCTION(fmpz_mod_mpoly_factor_gcd_brown), TEST_FUNCTION(fmpz_mod_mpoly_factor_gcd_hensel), TEST_FUNCTION(fmpz_mod_mpoly_factor_gcd_subresultant), TEST_FUNCTION(fmpz_mod_mpoly_factor_gcd_zippel2), TEST_FUNCTION(fmpz_mod_mpoly_factor_gcd_zippel) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-factor.c000066400000000000000000000134721461254215100226640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx, int factor_fun(fmpz_mod_mpoly_factor_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { slong i; fmpz_mod_mpoly_t q; fmpz_mod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mod_mpoly_factor_init(g, ctx); fmpz_mod_mpoly_factor_init(h, ctx); fmpz_mod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) if (!fmpz_mod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || !fmpz_is_one(g->poly[i].coeffs + 0)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_factor_expand(q, g, ctx); if (!fmpz_mod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) { fmpz_mod_mpoly_factor_sort(g, ctx); fmpz_mod_mpoly_factor_sort(h, ctx); if (fmpz_mod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(q, ctx); fmpz_mod_mpoly_factor_clear(g, ctx); fmpz_mod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor, state) { slong i, j, tmul = 30; for (i = 0; i < tmul*flint_test_multiplier(); i++) { slong lower; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, t; slong nfacs, len; ulong expbound, powbound, pow, expbounds[2]; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 2, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); nfacs = 5 + n_randint(state, 5); powbound = 1 + n_randint(state, 3); expbound = 3 + 70/nfacs/powbound; lower = 0; fmpz_mod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10); expbounds[0] = 1 + n_randint(state, expbound); expbounds[1] = 1 + n_randint(state, expbound); fmpz_mod_mpoly_randtest_bounds(t, state, len, expbounds, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fmpz_mod_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mod_mpoly_pow_ui(t, t, pow, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mod_mpoly_factor); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 100/nfacs/n/powbound; lower = 0; fmpz_mod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); fmpz_mod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fmpz_mod_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mod_mpoly_pow_ui(t, t, pow, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mod_mpoly_factor); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000070131461254215100251000ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" void check_it(const fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx) { slong i, j; fmpz_mod_mpoly_t q; fmpz_mod_mpoly_factor_t g, h; fmpz_mod_mpoly_factor_init(g, ctx); fmpz_mod_mpoly_factor_init(h, ctx); fmpz_mod_mpoly_init(q, ctx); if (!fmpz_mod_mpoly_factor_squarefree(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || !fmpz_is_one(g->poly[i].coeffs + 0)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_factor_expand(q, g, ctx); if (!fmpz_mod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { fmpz_mod_mpoly_factor_squarefree(h, g->poly + i, ctx); for (j = 0; j < h->num; j++) { if (!fmpz_is_one(h->exp + j)) { flint_printf("FAIL:\nfactor has a square factor\n"); fflush(stdout); flint_abort(); } } } for (i = 1; i < g->num; i++) for (j = 0; j < i; j++) { if (!fmpz_mod_mpoly_gcd(q, g->poly + i, g->poly + j, ctx)) { flint_printf("FAIL:\ncheck gcd could be computed\n"); } if (!fmpz_mod_mpoly_is_one(q, ctx)) { flint_printf("FAIL:\nbases have a common factor\n"); } } fmpz_mod_mpoly_clear(q, ctx); fmpz_mod_mpoly_factor_clear(g, ctx); fmpz_mod_mpoly_factor_clear(h, ctx); } TEST_FUNCTION_START(fmpz_mod_mpoly_factor_squarefree, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 6, 150); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); expbound = 3 + 25/nfacs/n/powbound; fmpz_mod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 80/powbound/n); fmpz_mod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); fmpz_mod_mpoly_pow_ui(t, t, pow, ctx); fmpz_mod_mpoly_mul(t, a, t, ctx); if (fmpz_mod_mpoly_length(t, ctx) < 500) fmpz_mod_mpoly_swap(a, t, ctx); } check_it(a, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-factor_wang.c000066400000000000000000000110011461254215100236620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx, int factor_fun(fmpz_mod_mpoly_factor_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { slong i; fmpz_mod_mpoly_t q; fmpz_mod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mod_mpoly_factor_init(g, ctx); fmpz_mod_mpoly_factor_init(h, ctx); fmpz_mod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) if (!fmpz_mod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || !fmpz_is_one(g->poly[i].coeffs + 0)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_factor_expand(q, g, ctx); if (!fmpz_mod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) { fmpz_mod_mpoly_factor_sort(g, ctx); fmpz_mod_mpoly_factor_sort(h, ctx); if (fmpz_mod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(q, ctx); fmpz_mod_mpoly_factor_clear(g, ctx); fmpz_mod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_wang, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, t; slong nfacs, len; ulong expbound, powbound, pow; slong n; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 7, 100); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 20/nfacs/n/powbound; lower = 0; fmpz_mod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); fmpz_mod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fmpz_mod_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mod_mpoly_pow_ui(t, t, pow, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mod_mpoly_factor_wang); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000107771461254215100251350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx, int factor_fun(fmpz_mod_mpoly_factor_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { slong i; fmpz_mod_mpoly_t q; fmpz_mod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mod_mpoly_factor_init(g, ctx); fmpz_mod_mpoly_factor_init(h, ctx); fmpz_mod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) if (!fmpz_mod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || !fmpz_is_one(g->poly[i].coeffs + 0)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_factor_expand(q, g, ctx); if (!fmpz_mod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) { fmpz_mod_mpoly_factor_sort(g, ctx); fmpz_mod_mpoly_factor_sort(h, ctx); if (fmpz_mod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(q, ctx); fmpz_mod_mpoly_factor_clear(g, ctx); fmpz_mod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_zassenhaus, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 15/nfacs/n/powbound; lower = 0; fmpz_mod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); fmpz_mod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fmpz_mod_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mod_mpoly_pow_ui(t, t, pow, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mod_mpoly_factor_zassenhaus); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000107701461254215100242450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx, int factor_fun(fmpz_mod_mpoly_factor_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { slong i; fmpz_mod_mpoly_t q; fmpz_mod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mod_mpoly_factor_init(g, ctx); fmpz_mod_mpoly_factor_init(h, ctx); fmpz_mod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) if (!fmpz_mod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || !fmpz_is_one(g->poly[i].coeffs + 0)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_factor_expand(q, g, ctx); if (!fmpz_mod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mod_mpoly_factor) { fmpz_mod_mpoly_factor_sort(g, ctx); fmpz_mod_mpoly_factor_sort(h, ctx); if (fmpz_mod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mod_mpoly_clear(q, ctx); fmpz_mod_mpoly_factor_clear(g, ctx); fmpz_mod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_zippel, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 80/nfacs/n/powbound; lower = 0; fmpz_mod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); fmpz_mod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fmpz_mod_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mod_mpoly_pow_ui(t, t, pow, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mod_mpoly_factor_zippel); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-gcd_brown.c000066400000000000000000000172061461254215100233510ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_brown int compute_gcd( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong nvars = ctx->minfo->nvars; slong * perm; ulong * shift, * stride; slong i; flint_bitcnt_t wbits; fmpz_mod_mpoly_ctx_t nctx; fmpz_mod_mpolyn_t An, Bn, Gn, Abarn, Bbarn; fmpz_mod_poly_polyun_mpolyn_stack_t St; if (fmpz_mod_mpoly_is_zero(A, ctx)) { if (fmpz_mod_mpoly_is_zero(B, ctx)) fmpz_mod_mpoly_zero(G, ctx); else fmpz_mod_mpoly_make_monic(G, B, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_make_monic(G, A, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (nvars < 2) { return fmpz_mod_mpoly_gcd(G, A, B, ctx); } perm = (slong *) flint_malloc(nvars*sizeof(slong)); shift = (ulong *) flint_malloc(nvars*sizeof(ulong)); stride = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (i = 0; i < nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } wbits = FLINT_MAX(A->bits, B->bits); fmpz_mod_mpoly_ctx_init(nctx, nvars, ORD_LEX, fmpz_mod_mpoly_ctx_modulus(ctx)); fmpz_mod_mpolyn_init(An, wbits, nctx); fmpz_mod_mpolyn_init(Bn, wbits, nctx); fmpz_mod_mpolyn_init(Gn, wbits, nctx); fmpz_mod_mpolyn_init(Abarn, wbits, nctx); fmpz_mod_mpolyn_init(Bbarn, wbits, nctx); fmpz_mod_poly_stack_init(St->poly_stack); fmpz_mod_polyun_stack_init(St->polyun_stack); fmpz_mod_mpolyn_stack_init(St->mpolyn_stack, wbits, nctx); fmpz_mod_mpoly_to_mpolyn_perm_deflate(An, nctx, A, ctx, perm, shift, stride); fmpz_mod_mpoly_to_mpolyn_perm_deflate(Bn, nctx, B, ctx, perm, shift, stride); success = fmpz_mod_mpolyn_gcd_brown_smprime(Gn, Abarn, Bbarn, An, Bn, nvars - 1, nctx, NULL, St); if (!success) goto cleanup; fmpz_mod_mpoly_from_mpolyn_perm_inflate(G, FLINT_MIN(A->bits, B->bits), ctx, Gn, nctx, perm, shift, stride); fmpz_mod_mpoly_make_monic(G, G, ctx); success = 1; cleanup: fmpz_mod_poly_stack_clear(St->poly_stack); fmpz_mod_polyun_stack_clear(St->polyun_stack); fmpz_mod_mpolyn_stack_clear(St->mpolyn_stack, nctx); fmpz_mod_mpolyn_clear(An, nctx); fmpz_mod_mpolyn_clear(Bn, nctx); fmpz_mod_mpolyn_clear(Gn, nctx); fmpz_mod_mpolyn_clear(Abarn, nctx); fmpz_mod_mpolyn_clear(Bbarn, nctx); fmpz_mod_mpoly_ctx_clear(nctx); flint_free(perm); flint_free(shift); flint_free(stride); return success; } /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, const fmpz_mod_mpoly_t gdiv, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name, int (* compute_gcd_fun)(fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { int res; fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mod_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_gcd_brown, state) { slong i, j, tmul = 5; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong n, degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, 150); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 40) + 1; len1 = n_randint(state, 60); len2 = n_randint(state, 60); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); degbound = 1 + 50/n/n; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense", compute_gcd); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-gcd_hensel.c000066400000000000000000000213211461254215100234710ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_hensel int compute_gcd( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t wbits; flint_rand_t state; int success = 0; fmpz_mod_mpoly_ctx_t lctx; fmpz_mod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mod_mpoly_t Ac, Bc, Gc; ulong * shift, * stride; slong * perm; slong Gdeg_bound; if (fmpz_mod_mpoly_is_zero(A, ctx)) { if (fmpz_mod_mpoly_is_zero(B, ctx)) fmpz_mod_mpoly_zero(G, ctx); else fmpz_mod_mpoly_make_monic(G, B, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_make_monic(G, A, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (ctx->minfo->nvars < 3) { return fmpz_mod_mpoly_gcd(G, A, B, ctx); } perm = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); shift = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); stride = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(B, ctx)); FLINT_ASSERT(ctx->minfo->nvars >= 3); flint_randinit(state); wbits = FLINT_MAX(A->bits, B->bits); fmpz_mod_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX, fmpz_mod_mpoly_ctx_modulus(ctx)); fmpz_mod_mpoly_init3(Al, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); success = fmpz_mod_mpolyl_content(Ac, Al, 1, lctx) && fmpz_mod_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; if (!fmpz_mod_mpoly_divides(Al, Al, Ac, lctx) || !fmpz_mod_mpoly_divides(Bl, Bl, Bc, lctx)) { flint_printf("FAIL: Check content divides\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mod_mpoly_repack_bits_inplace(Bl, wbits, lctx); Gdeg_bound = FLINT_MIN(fmpz_mod_mpoly_degree_si(Al, 0, lctx), fmpz_mod_mpoly_degree_si(Bl, 0, lctx)); success = fmpz_mod_mpolyl_gcd_hensel_smprime(Gl, Gdeg_bound, Abarl, Bbarl, Al, Bl, lctx); if (!success) goto cleanup; success = fmpz_mod_mpoly_gcd(Gc, Ac, Bc, lctx); if (!success) goto cleanup; fmpz_mod_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(G, FLINT_MIN(A->bits, B->bits), ctx, Gl, lctx, perm, shift, stride); fmpz_mod_mpoly_make_monic(G, G, ctx); success = 1; cleanup: fmpz_mod_mpoly_clear(Al, lctx); fmpz_mod_mpoly_clear(Bl, lctx); fmpz_mod_mpoly_clear(Gl, lctx); fmpz_mod_mpoly_clear(Abarl, lctx); fmpz_mod_mpoly_clear(Bbarl, lctx); fmpz_mod_mpoly_clear(Ac, lctx); fmpz_mod_mpoly_clear(Bc, lctx); fmpz_mod_mpoly_clear(Gc, lctx); fmpz_mod_mpoly_ctx_clear(lctx); flint_randclear(state); flint_free(perm); flint_free(shift); flint_free(stride); return success; } /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, const fmpz_mod_mpoly_t gdiv, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name, int (* compute_gcd_fun)(fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { int res; fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mod_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_gcd_hensel, state) { slong i, j, tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, (i & 1) ? 150 : 15); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 30) + 1; len1 = n_randint(state, 30) + 1; len2 = n_randint(state, 30) + 1; degbound = 2 + 30/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse", compute_gcd); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000201231461254215100247450ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_subresultant int compute_gcd( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { int success; slong var = 0; fmpz_mod_mpoly_t Ac, Bc, Gc, s, t; fmpz_mod_mpoly_univar_t Ax, Bx, Gx; if (fmpz_mod_mpoly_is_zero(A, ctx)) { if (fmpz_mod_mpoly_is_zero(B, ctx)) fmpz_mod_mpoly_zero(G, ctx); else fmpz_mod_mpoly_make_monic(G, B, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_make_monic(G, A, ctx); return 1; } fmpz_mod_mpoly_init(Ac, ctx); fmpz_mod_mpoly_init(Bc, ctx); fmpz_mod_mpoly_init(Gc, ctx); fmpz_mod_mpoly_init(s, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_univar_init(Ax, ctx); fmpz_mod_mpoly_univar_init(Bx, ctx); fmpz_mod_mpoly_univar_init(Gx, ctx); fmpz_mod_mpoly_to_univar(Ax, A, var, ctx); fmpz_mod_mpoly_to_univar(Bx, B, var, ctx); success = _fmpz_mod_mpoly_vec_content_mpoly(Ac, Ax->coeffs, Ax->length, ctx) && _fmpz_mod_mpoly_vec_content_mpoly(Bc, Bx->coeffs, Bx->length, ctx) && fmpz_mod_mpoly_gcd(Gc, Ac, Bc, ctx); if (!success) goto cleanup; _fmpz_mod_mpoly_vec_divexact_mpoly(Ax->coeffs, Ax->length, Ac, ctx); _fmpz_mod_mpoly_vec_divexact_mpoly(Bx->coeffs, Bx->length, Bc, ctx); success = fmpz_cmp(Ax->exps + 0, Bx->exps + 0) > 0 ? fmpz_mod_mpoly_univar_pseudo_gcd(Gx, Ax, Bx, ctx) : fmpz_mod_mpoly_univar_pseudo_gcd(Gx, Bx, Ax, ctx); if (!success) goto cleanup; if (fmpz_mod_mpoly_gcd(t, Ax->coeffs + 0, Bx->coeffs + 0, ctx) && t->length == 1) { fmpz_mod_mpoly_term_content(s, Gx->coeffs + 0, ctx); fmpz_mod_mpoly_divexact(t, Gx->coeffs + 0, s, ctx); _fmpz_mod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } else if (fmpz_mod_mpoly_gcd(t, Ax->coeffs + Ax->length - 1, Bx->coeffs + Bx->length - 1, ctx) && t->length == 1) { fmpz_mod_mpoly_term_content(s, Gx->coeffs + Gx->length - 1, ctx); fmpz_mod_mpoly_divexact(t, Gx->coeffs + Gx->length - 1, s, ctx); _fmpz_mod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } success = _fmpz_mod_mpoly_vec_content_mpoly(t, Gx->coeffs, Gx->length, ctx); if (!success) goto cleanup; _fmpz_mod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); _fmpz_mod_mpoly_vec_mul_mpoly(Gx->coeffs, Gx->length, Gc, ctx); _fmpz_mod_mpoly_from_univar(G, FLINT_MIN(A->bits, B->bits), Gx, var, ctx); fmpz_mod_mpoly_make_monic(G, G, ctx); success = 1; cleanup: fmpz_mod_mpoly_clear(Ac, ctx); fmpz_mod_mpoly_clear(Bc, ctx); fmpz_mod_mpoly_clear(Gc, ctx); fmpz_mod_mpoly_clear(s, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_univar_clear(Ax, ctx); fmpz_mod_mpoly_univar_clear(Bx, ctx); fmpz_mod_mpoly_univar_clear(Gx, ctx); return success; } /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, const fmpz_mod_mpoly_t gdiv, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name, int (* compute_gcd_fun)(fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { int res; fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mod_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_gcd_subresultant, state) { slong i, j, tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 3, 250); if (fmpz_mod_mpoly_ctx_nvars(ctx) < 1) { fmpz_mod_mpoly_ctx_clear(ctx); continue; } fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 15); len2 = n_randint(state, 15); degbound = 1 + 10/ctx->minfo->nvars; for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense", compute_gcd); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-gcd_zippel.c000066400000000000000000000400551461254215100235230ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_zippel int compute_gcd( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t wbits; flint_rand_t state; int success = 0; fmpz_mod_mpoly_ctx_t lctx; fmpz_mod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mod_mpoly_t Ac, Bc, Gc; ulong * shift, * stride; slong * perm; if (fmpz_mod_mpoly_is_zero(A, ctx)) { if (fmpz_mod_mpoly_is_zero(B, ctx)) fmpz_mod_mpoly_zero(G, ctx); else fmpz_mod_mpoly_make_monic(G, B, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_make_monic(G, A, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (ctx->minfo->nvars < 2) { return fmpz_mod_mpoly_gcd(G, A, B, ctx); } perm = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); shift = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); stride = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(B, ctx)); FLINT_ASSERT(ctx->minfo->nvars >= 2); flint_randinit(state); wbits = FLINT_MAX(A->bits, B->bits); fmpz_mod_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX, fmpz_mod_mpoly_ctx_modulus(ctx)); fmpz_mod_mpoly_init3(Al, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); success = fmpz_mod_mpolyl_content(Ac, Al, 1, lctx) && fmpz_mod_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; if (!fmpz_mod_mpoly_divides(Al, Al, Ac, lctx) || !fmpz_mod_mpoly_divides(Bl, Bl, Bc, lctx)) { flint_printf("FAIL: Check content divides\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mod_mpoly_repack_bits_inplace(Bl, wbits, lctx); success = fmpz_mod_mpolyl_gcdp_zippel(Gl, Abarl, Bbarl, Al, Bl, ctx->minfo->nvars - 1, lctx, state); if (!success) goto cleanup; success = fmpz_mod_mpoly_gcd(Gc, Ac, Bc, lctx); if (!success) goto cleanup; fmpz_mod_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(G, FLINT_MIN(A->bits, B->bits), ctx, Gl, lctx, perm, shift, stride); success = 1; fmpz_mod_mpoly_make_monic(G, G, ctx); cleanup: fmpz_mod_mpoly_clear(Al, lctx); fmpz_mod_mpoly_clear(Bl, lctx); fmpz_mod_mpoly_clear(Gl, lctx); fmpz_mod_mpoly_clear(Abarl, lctx); fmpz_mod_mpoly_clear(Bbarl, lctx); fmpz_mod_mpoly_clear(Ac, lctx); fmpz_mod_mpoly_clear(Bc, lctx); fmpz_mod_mpoly_clear(Gc, lctx); fmpz_mod_mpoly_ctx_clear(lctx); flint_randclear(state); flint_free(perm); flint_free(shift); flint_free(stride); return success; } /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, const fmpz_mod_mpoly_t gdiv, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name, int (* compute_gcd_fun)(fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { int res; fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mod_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_gcd_zippel, state) { slong i, j, tmul = 10; { fmpz p = 1009; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t r, a, b, g; fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_LEX, &p); fmpz_mod_mpoly_init(r, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_set_str_pretty(a, "x1+x2+x3+1", NULL, ctx); fmpz_mod_mpoly_set_str_pretty(b, "x1+x2+x3+2", NULL, ctx); fmpz_mod_mpoly_set_str_pretty(g, "x1^3*(x3+1)*x4 + x1^2*(x3+1)*(x4+1) + x1*(x3+1)*(x3+2)*x2 + (x3^2+x3+2)*x4 + 1", NULL, ctx); fmpz_mod_mpoly_mul(a, a, g, ctx); fmpz_mod_mpoly_mul(b, b, g, ctx); gcd_check(r, a, b, g, ctx, -2, 0, "example", compute_gcd); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } { fmpz_t p; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t g, a, b, t; const char * vars[] = {"t" ,"z", "y", "x"}; fmpz_init_set_ui(p, 1); fmpz_mul_2exp(p, p, 100); fmpz_nextprime(p, p, 1); fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mod_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -2, 1, "example", compute_gcd); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); fmpz_clear(p); } { fmpz p = 1009; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t r, d, f, g; const char* vars[] = {"x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"}; const char * example[][3] = {{ "x1^2 + x1 + 3", "2*x1^2 + 2*x1 + 1", "x1^2 + 2*x1 + 2" }, { "2*x1^2*x2^2 + x1*x2 + 2*x1", "x2^2 + 2*x1^2*x2 + x1^2 + 1", "x1^2*x2^2 + x1^2*x2 + x1*x2 + x1^2 + x1" }, { "x2^2*x3^2 + x2^2*x3 + 2*x1^2*x2*x3 + x1*x3", "x3^2 + x2^2*x3 + x1^2*x2*x3 + x1*x3 + x1^2*x2^2", "x2*x3 + 2*x1*x3 + x3 + x1" }, { "x1^2*x4^2 + x2^2*x3*x4 + x1^2*x2*x4 + x2*x4 + x1^2*x2*x3", "x1*x2*x3^2*x4^2 + x1*x3^2*x4^2 + x1*x4^2 + x4^2 + x1*x3*x4", "x1*x3^2*x4^2 + x3^2*x4^2 + x4^2 + x1*x2^2*x3*x4 + x1*x2^2" }, { "x1^3*x2^2*x3^2*x4*x5^2 + x1*x2^2*x5^2 + x1^3*x3*x4^2*x5" " + x1^3*x2*x3^2*x4*x5 + x1^2*x2*x3^2*x4^2" , "x1*x2^2*x5^2 + x1*x2*x3^2*x4*x5 + x1*x2*x3^2*x4^2" " + x1*x2^2*x4^2 + 1" , "x1*x3^2*x4*x5^2 + x2*x5^2 + x1*x2*x4*x5 + x2*x5 + x1*x2*x3*x4^2" }, { "x1*x2*x4^2*x5^2*x6^2 + x1*x2^2*x3^2*x4*x5^2*x6^2 + x1^2*x3*x6^2" " + x1^2*x2*x3^2*x4*x5^2*x6 + x1^2*x3*x5*x6" , "x1^2*x2*x4*x5^2*x6^2 + x1*x3*x5^2*x6^2 + x1*x2^2*x6^2" " + x1^2*x2^2*x3^2*x5*x6 + x1*x3^2*x4*x5" , "x2^2*x3^2*x4*x5^2*x6 + x1*x4^2*x5*x6 + x2^2*x3^2*x4*x5*x6" " + x1*x2^2*x3*x4^2*x6 + x1^2*x3*x5^2" }, { "x1*x2^2*x4^2*x6^2*x7^2 + x1^2*x3*x4*x6^2*x7^2 + x3^2*x4^2*x7^2" " + x1^2*x2*x4^2*x6 + x3*x4*x5^2" , "x1^2*x2*x4^2*x5*x6^2*x7^2 + x1*x2*x3*x6*x7 + x3*x4^2*x5^2*x7" " + x1*x4^2*x5^2*x7 + x1^2*x2*x3*x4^2+x5*x6" , "x1*x3*x5*x6^2*x7^2 + x2^2*x3^2*x4^2*x5*x6*x7^2 + x4*x6*x7^2" " + x1^2*x2*x3*x5*x6*x7 + x1^2*x3^2*x4*x5^2" }, { "x2^2*x4*x5*x6*x7*x8^2 + x1^2*x2*x3^2*x4^2*x6^2*x7^2*x8" " + x1^2*x3*x4^2*x6^2*x7^2 + x1^2*x2^2*x3^2*x4*x5^2*x6*x7^2" " + x2^2*x4*x6" , "x1^2*x2^2*x3*x4^2*x5*x6^2*x8^2 + x2*x5*x6^2*x8^2" " + x1^2*x2^2*x3^2*x4^2*x6^2*x7^2*x8 + x1^2*x3^2*x4*x5^2*x7^2*x8" " + x1*x2^2*x3^2*x5^2*x7" , "x1*x4^2*x5*x6*x7*x8^2 + x1*x2^2*x4^2*x5^2*x6^2*x8" " + x1^2*x2*x3*x4^2*x6^2*x8 + x1^2*x2^2*x3^2*x4*x5^2*x8" " + x1*x2*x4^2*x5^2" }, { "x1^2*x3^3*x4*x6*x8*x9^2 + x1*x2*x3*x4^2*x5^2*x8*x9" " + x2*x3*x4*x5^2*x8*x9 + x1*x3^3*x4^2*x5^2*x6^2*x7*x8^2" " + x2*x3*x4*x5^2*x6*x7*x8^2" , "x1^2*x2^2*x3*x7^2*x8*x9 + x2^2*x9 + x1^2*x3*x4^2*x5^2*x6*x7^2" " + x4^2*x5^2*x7^2 + x3*x4^2*x6*x7" , "x1^2*x2*x4*x5*x6*x7^2*x8^2*x9^2 + x1^2*x2*x3*x5*x6^2*x7^2*x8*x9^2" " + x1^2*x3*x4*x6*x7^2*x8*x9 + x1^2*x2^2*x6*x8^2" " + x2^2*x4*x5*x6^2*x7" }, { "x1*x2^2*x4^2*x8*x9^2*x10^2 + x2^2*x4*x5^2*x6*x7*x9*x10^2" " + x1^2*x2*x3*x5^2*x7^2*x9^2 + x1*x3^2*x4^2*x7^2*x9^2" " + x1^2*x3*x4*x7^2*x8^2" , "x1*x2*x3^2*x4*x6*x7*x8*x9^2*x10^2 + x2^2*x3^2*x4^2*x6^2*x9*x10^2" " + x1*x2^2*x3^2*x4*x5*x6*x7*x8^2*x9^2*x10" " + x1^2*x2*x4^2*x5^2*x8^2*x9^2*x10 + x3*x4^2*x5*x6*x7^2*x9*x10" , "x1*x2^2*x3^2*x5^2*x6^2*x7*x8*x9^2*x10^2 + x3*x8*x9^2*x10^2" " + x1*x2^2*x3*x4*x5^2*x6^2*x8^2*x9*x10 + x1*x3*x6*x7*x8*x10" " + x4^2*x5^2*x6^2*x7*x9^2" }}; for (i = 1; i <= 10; i++) { fmpz_mod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, &p); fmpz_mod_mpoly_init(r, ctx); fmpz_mod_mpoly_init(d, ctx); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_set_str_pretty(d, example[i - 1][0], vars, ctx); fmpz_mod_mpoly_set_str_pretty(f, example[i - 1][1], vars, ctx); fmpz_mod_mpoly_set_str_pretty(g, example[i - 1][2], vars, ctx); fmpz_mod_mpoly_mul(f, f, d, ctx); fmpz_mod_mpoly_mul(g, g, d, ctx); fmpz_mod_mpoly_randtest_bits(r, state, 10, FLINT_BITS, ctx); gcd_check(r, f, g, d, ctx, -1, i, "example", compute_gcd); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_clear(d, ctx); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, (i & 1) ? 150 : 15); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20) + 1; len2 = n_randint(state, 20) + 1; degbound = 2 + 100/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse", compute_gcd); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mod_mpoly_factor/test/t-gcd_zippel2.c000066400000000000000000000401401461254215100236000ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_zippel2 int compute_gcd( fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t wbits; flint_rand_t state; int success = 0; fmpz_mod_mpoly_ctx_t lctx; fmpz_mod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mod_mpoly_t Ac, Bc, Gc, Gamma, Al_lc, Bl_lc; ulong * shift, * stride; slong * perm; slong * tmp, * Al_degs, * Bl_degs, * Gamma_degs; if (fmpz_mod_mpoly_is_zero(A, ctx)) { if (fmpz_mod_mpoly_is_zero(B, ctx)) fmpz_mod_mpoly_zero(G, ctx); else fmpz_mod_mpoly_make_monic(G, B, ctx); return 1; } if (fmpz_mod_mpoly_is_zero(B, ctx)) { fmpz_mod_mpoly_make_monic(G, A, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (ctx->minfo->nvars < 3) { return fmpz_mod_mpoly_gcd(G, A, B, ctx); } perm = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); shift = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); stride = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } tmp = FLINT_ARRAY_ALLOC(4*ctx->minfo->nvars, slong); Al_degs = tmp + 1*ctx->minfo->nvars; Bl_degs = tmp + 2*ctx->minfo->nvars; Gamma_degs = tmp + 3*ctx->minfo->nvars; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!fmpz_mod_mpoly_is_zero(B, ctx)); FLINT_ASSERT(ctx->minfo->nvars >= 3); flint_randinit(state); wbits = FLINT_MAX(A->bits, B->bits); fmpz_mod_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX, fmpz_mod_mpoly_ctx_modulus(ctx)); fmpz_mod_mpoly_init3(Al, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mod_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Gamma, 0, wbits, lctx); fmpz_mod_mpoly_init3(Al_lc, 0, wbits, lctx); fmpz_mod_mpoly_init3(Bl_lc, 0, wbits, lctx); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); fmpz_mod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); success = fmpz_mod_mpolyl_content(Ac, Al, 2, lctx) && fmpz_mod_mpolyl_content(Bc, Bl, 2, lctx); if (!success) goto cleanup; if (!fmpz_mod_mpoly_divides(Al, Al, Ac, lctx) || !fmpz_mod_mpoly_divides(Bl, Bl, Bc, lctx)) { flint_printf("FAIL: Check content divides\n"); fflush(stdout); flint_abort(); } fmpz_mod_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mod_mpoly_repack_bits_inplace(Bl, wbits, lctx); fmpz_mod_mpolyl_lead_coeff(Al_lc, Al, 2, lctx); fmpz_mod_mpolyl_lead_coeff(Bl_lc, Bl, 2, lctx); success = fmpz_mod_mpoly_gcd(Gamma, Al_lc, Bl_lc, lctx); if (!success) goto cleanup; fmpz_mod_mpoly_repack_bits_inplace(Gamma, wbits, lctx); fmpz_mod_mpoly_degrees_si(Al_degs, Al, lctx); fmpz_mod_mpoly_degrees_si(Bl_degs, Bl, lctx); fmpz_mod_mpoly_degrees_si(Gamma_degs, Gamma, lctx); success = fmpz_mod_mpolyl_gcd_zippel2_smprime(Gl, NULL, Abarl, Bbarl, Al, Al_degs, Bl, Bl_degs, Gamma, Gamma_degs, lctx); if (!success) goto cleanup; success = fmpz_mod_mpoly_gcd(Gc, Ac, Bc, lctx); if (!success) goto cleanup; fmpz_mod_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mod_mpoly_from_mpolyl_perm_inflate(G, FLINT_MIN(A->bits, B->bits), ctx, Gl, lctx, perm, shift, stride); success = 1; fmpz_mod_mpoly_make_monic(G, G, ctx); cleanup: fmpz_mod_mpoly_clear(Al, lctx); fmpz_mod_mpoly_clear(Bl, lctx); fmpz_mod_mpoly_clear(Gl, lctx); fmpz_mod_mpoly_clear(Abarl, lctx); fmpz_mod_mpoly_clear(Bbarl, lctx); fmpz_mod_mpoly_clear(Ac, lctx); fmpz_mod_mpoly_clear(Bc, lctx); fmpz_mod_mpoly_clear(Gc, lctx); fmpz_mod_mpoly_clear(Gamma, lctx); fmpz_mod_mpoly_clear(Al_lc, lctx); fmpz_mod_mpoly_clear(Bl_lc, lctx); fmpz_mod_mpoly_ctx_clear(lctx); flint_randclear(state); flint_free(perm); flint_free(shift); flint_free(stride); flint_free(tmp); return success; } /* Defined in t-gcd_brown.c, t-gcd_hensel.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mod_mpoly_t g, fmpz_mod_mpoly_t a, fmpz_mod_mpoly_t b, const fmpz_mod_mpoly_t gdiv, fmpz_mod_mpoly_ctx_t ctx, slong i, slong j, const char * name, int (* compute_gcd_fun)(fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_t, const fmpz_mod_mpoly_ctx_t)) { int res; fmpz_mod_mpoly_t ca, cb, cg; fmpz_mod_mpoly_init(ca, ctx); fmpz_mod_mpoly_init(cb, ctx); fmpz_mod_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mod_mpoly_assert_canonical(g, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mod_mpoly_is_zero(g, ctx)) { if (!fmpz_mod_mpoly_is_zero(a, ctx) || !fmpz_mod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fmpz_is_one(g->coeffs + 0)) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mod_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mod_mpoly_assert_canonical(cg, ctx); if (!res) { if (fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mod_mpoly_factor_gcd_zippel2, state) { slong i, j, tmul = 10; { fmpz_t p; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t g, a, b, t; const char * vars[] = {"t" ,"z", "y", "x"}; fmpz_init_set_ui(p, 1); fmpz_mul_2exp(p, p, 100); fmpz_nextprime(p, p, 1); fmpz_mod_mpoly_ctx_init(ctx, 4, ORD_LEX, p); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(t, ctx); fmpz_mod_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mod_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mod_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -2, 1, "example", compute_gcd); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); fmpz_clear(p); } { fmpz p = 1009; fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t r, d, f, g; const char* vars[] = {"x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"}; const char * example[][3] = {{ "x1^2 + x1 + 3", "2*x1^2 + 2*x1 + 1", "x1^2 + 2*x1 + 2" }, { "2*x1^2*x2^2 + x1*x2 + 2*x1", "x2^2 + 2*x1^2*x2 + x1^2 + 1", "x1^2*x2^2 + x1^2*x2 + x1*x2 + x1^2 + x1" }, { "x2^2*x3^2 + x2^2*x3 + 2*x1^2*x2*x3 + x1*x3", "x3^2 + x2^2*x3 + x1^2*x2*x3 + x1*x3 + x1^2*x2^2", "x2*x3 + 2*x1*x3 + x3 + x1" }, { "x1^2*x4^2 + x2^2*x3*x4 + x1^2*x2*x4 + x2*x4 + x1^2*x2*x3", "x1*x2*x3^2*x4^2 + x1*x3^2*x4^2 + x1*x4^2 + x4^2 + x1*x3*x4", "x1*x3^2*x4^2 + x3^2*x4^2 + x4^2 + x1*x2^2*x3*x4 + x1*x2^2" }, { "x1^3*x2^2*x3^2*x4*x5^2 + x1*x2^2*x5^2 + x1^3*x3*x4^2*x5" " + x1^3*x2*x3^2*x4*x5 + x1^2*x2*x3^2*x4^2" , "x1*x2^2*x5^2 + x1*x2*x3^2*x4*x5 + x1*x2*x3^2*x4^2" " + x1*x2^2*x4^2 + 1" , "x1*x3^2*x4*x5^2 + x2*x5^2 + x1*x2*x4*x5 + x2*x5 + x1*x2*x3*x4^2" }, { "x1*x2*x4^2*x5^2*x6^2 + x1*x2^2*x3^2*x4*x5^2*x6^2 + x1^2*x3*x6^2" " + x1^2*x2*x3^2*x4*x5^2*x6 + x1^2*x3*x5*x6" , "x1^2*x2*x4*x5^2*x6^2 + x1*x3*x5^2*x6^2 + x1*x2^2*x6^2" " + x1^2*x2^2*x3^2*x5*x6 + x1*x3^2*x4*x5" , "x2^2*x3^2*x4*x5^2*x6 + x1*x4^2*x5*x6 + x2^2*x3^2*x4*x5*x6" " + x1*x2^2*x3*x4^2*x6 + x1^2*x3*x5^2" }, { "x1*x2^2*x4^2*x6^2*x7^2 + x1^2*x3*x4*x6^2*x7^2 + x3^2*x4^2*x7^2" " + x1^2*x2*x4^2*x6 + x3*x4*x5^2" , "x1^2*x2*x4^2*x5*x6^2*x7^2 + x1*x2*x3*x6*x7 + x3*x4^2*x5^2*x7" " + x1*x4^2*x5^2*x7 + x1^2*x2*x3*x4^2+x5*x6" , "x1*x3*x5*x6^2*x7^2 + x2^2*x3^2*x4^2*x5*x6*x7^2 + x4*x6*x7^2" " + x1^2*x2*x3*x5*x6*x7 + x1^2*x3^2*x4*x5^2" }, { "x2^2*x4*x5*x6*x7*x8^2 + x1^2*x2*x3^2*x4^2*x6^2*x7^2*x8" " + x1^2*x3*x4^2*x6^2*x7^2 + x1^2*x2^2*x3^2*x4*x5^2*x6*x7^2" " + x2^2*x4*x6" , "x1^2*x2^2*x3*x4^2*x5*x6^2*x8^2 + x2*x5*x6^2*x8^2" " + x1^2*x2^2*x3^2*x4^2*x6^2*x7^2*x8 + x1^2*x3^2*x4*x5^2*x7^2*x8" " + x1*x2^2*x3^2*x5^2*x7" , "x1*x4^2*x5*x6*x7*x8^2 + x1*x2^2*x4^2*x5^2*x6^2*x8" " + x1^2*x2*x3*x4^2*x6^2*x8 + x1^2*x2^2*x3^2*x4*x5^2*x8" " + x1*x2*x4^2*x5^2" }, { "x1^2*x3^3*x4*x6*x8*x9^2 + x1*x2*x3*x4^2*x5^2*x8*x9" " + x2*x3*x4*x5^2*x8*x9 + x1*x3^3*x4^2*x5^2*x6^2*x7*x8^2" " + x2*x3*x4*x5^2*x6*x7*x8^2" , "x1^2*x2^2*x3*x7^2*x8*x9 + x2^2*x9 + x1^2*x3*x4^2*x5^2*x6*x7^2" " + x4^2*x5^2*x7^2 + x3*x4^2*x6*x7" , "x1^2*x2*x4*x5*x6*x7^2*x8^2*x9^2 + x1^2*x2*x3*x5*x6^2*x7^2*x8*x9^2" " + x1^2*x3*x4*x6*x7^2*x8*x9 + x1^2*x2^2*x6*x8^2" " + x2^2*x4*x5*x6^2*x7" }, { "x1*x2^2*x4^2*x8*x9^2*x10^2 + x2^2*x4*x5^2*x6*x7*x9*x10^2" " + x1^2*x2*x3*x5^2*x7^2*x9^2 + x1*x3^2*x4^2*x7^2*x9^2" " + x1^2*x3*x4*x7^2*x8^2" , "x1*x2*x3^2*x4*x6*x7*x8*x9^2*x10^2 + x2^2*x3^2*x4^2*x6^2*x9*x10^2" " + x1*x2^2*x3^2*x4*x5*x6*x7*x8^2*x9^2*x10" " + x1^2*x2*x4^2*x5^2*x8^2*x9^2*x10 + x3*x4^2*x5*x6*x7^2*x9*x10" , "x1*x2^2*x3^2*x5^2*x6^2*x7*x8*x9^2*x10^2 + x3*x8*x9^2*x10^2" " + x1*x2^2*x3*x4*x5^2*x6^2*x8^2*x9*x10 + x1*x3*x6*x7*x8*x10" " + x4^2*x5^2*x6^2*x7*x9^2" }}; for (i = 1; i <= 10; i++) { fmpz_mod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, &p); fmpz_mod_mpoly_init(r, ctx); fmpz_mod_mpoly_init(d, ctx); fmpz_mod_mpoly_init(f, ctx); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_set_str_pretty(d, example[i - 1][0], vars, ctx); fmpz_mod_mpoly_set_str_pretty(f, example[i - 1][1], vars, ctx); fmpz_mod_mpoly_set_str_pretty(g, example[i - 1][2], vars, ctx); fmpz_mod_mpoly_mul(f, f, d, ctx); fmpz_mod_mpoly_mul(g, g, d, ctx); fmpz_mod_mpoly_randtest_bits(r, state, 10, FLINT_BITS, ctx); gcd_check(r, f, g, d, ctx, -1, i, "example", compute_gcd); fmpz_mod_mpoly_clear(r, ctx); fmpz_mod_mpoly_clear(d, ctx); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, (i & 1) ? 150 : 15); fmpz_mod_mpoly_init(g, ctx); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(b, ctx); fmpz_mod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20) + 1; len2 = n_randint(state, 20) + 1; degbound = 2 + 100/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fmpz_mod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fmpz_mod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fmpz_mod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fmpz_mod_mpoly_is_zero(t, ctx)) fmpz_mod_mpoly_one(t, ctx); fmpz_mod_mpoly_mul(a, a, t, ctx); fmpz_mod_mpoly_mul(b, b, t, ctx); fmpz_mod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse", compute_gcd); } fmpz_mod_mpoly_clear(g, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_clear(b, ctx); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mod_mpoly_factor/zip_helpers.c000066400000000000000000000213111461254215100225010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "mpoly.h" #include "fmpz_mod_mpoly_factor.h" /* evaluation at gen(start) -> caches[0] gen(start+1) -> caches[1] ... gen(stop-1) -> caches[stop-start-1] the other gen are assumed to not appear in A */ void mpoly_monomial_evals_fmpz_mod( fmpz_mod_poly_t EH, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, fmpz_mod_poly_struct * alpha_caches, slong start, slong stop, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fpctx) { slong i, k; fmpz * p; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; slong num = stop - start; TMP_INIT; TMP_START; off = TMP_ARRAY_ALLOC(2*num, slong); shift = off + num; for (k = 0; k < num; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k + start, Abits, mctx); fmpz_mod_poly_fit_length(EH, Alen, fpctx); EH->length = Alen; p = EH->coeffs; for (i = 0; i < Alen; i++) { fmpz_one(p + i); for (k = 0; k < num; k++) { ulong ei = (Aexps[N*i + off[k]] >> shift[k]) & mask; fmpz_mod_pow_cache_mulpow_ui(p + i, p + i, ei, alpha_caches + k, fpctx); } } TMP_END; } /* evaluation at gen(0) -> x gen(1) -> alphas[0] gen(2) -> alphas[1] gen(3) -> alphas[2] ... gen(m-1) -> alphas[m-2] the uniivariate marks should be filled in by mpoly1_fill_marks */ void mpoly1_monomial_evals_fmpz_mod( fmpz_mod_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Amarks, slong Amarkslen, fmpz_mod_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fpctx) { slong start, stop, i, j, k, n; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; fmpz * p; TMP_INIT; FLINT_ASSERT(1 < m && m <= mctx->nvars); FLINT_ASSERT(Amarkslen > 0); TMP_START; off = TMP_ARRAY_ALLOC(2*m, slong); shift = off + m; for (k = 0; k < m; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k, Abits, mctx); fmpz_mod_polyun_fit_length(EH, Amarkslen, fpctx); for (i = 0; i < Amarkslen; i++) { start = Amarks[i]; stop = Amarks[i + 1]; FLINT_ASSERT(start < stop); n = stop - start; EH->exps[i] = (Aexps[N*start + off[0]] >> shift[0]) & mask; fmpz_mod_poly_fit_length(EH->coeffs + i, n, fpctx); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; for (j = 0; j < n; j++) { fmpz_one(p + j); for (k = 1; k < m; k++) { ulong ei = (Aexps[N*(start + j) + off[k]] >> shift[k]) & mask; fmpz_mod_pow_cache_mulpow_ui(p + j, p + j, ei, alpha_caches + k - 1, fpctx); } } } EH->length = Amarkslen; TMP_END; } /* evaluation at gen(0) -> x gen(1) -> y gen(2) -> alphas[0] gen(3) -> alphas[1] ... gen(m-1) -> alphas[m-3] the bivariate marks should be filled in by mpoly2_fill_marks */ void mpoly2_monomial_evals_fmpz_mod( fmpz_mod_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, ulong * Amarks, slong Amarkslen, fmpz_mod_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const fmpz_mod_ctx_t fpctx) { slong start, stop, i, j, k, n; ulong e0, e1; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; fmpz * p; TMP_INIT; FLINT_ASSERT(2 < m && m <= mctx->nvars); FLINT_ASSERT(Amarkslen > 0); TMP_START; off = TMP_ARRAY_ALLOC(2*m, slong); shift = off + m; for (k = 0; k < m; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k, Abits, mctx); fmpz_mod_polyun_fit_length(EH, Amarkslen, fpctx); for (i = 0; i < Amarkslen; i++) { start = Amarks[i]; stop = Amarks[i + 1]; FLINT_ASSERT(start < stop); n = stop - start; e0 = (Aexps[N*start + off[0]] >> shift[0]) & mask; e1 = (Aexps[N*start + off[1]] >> shift[1]) & mask; EH->exps[i] = pack_exp2(e0, e1); fmpz_mod_poly_fit_length(EH->coeffs + i, n, fpctx); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; for (j = 0; j < n; j++) { fmpz_one(p + j); for (k = 2; k < m; k++) { ulong ei = (Aexps[N*(start + j) + off[k]] >> shift[k]) & mask; fmpz_mod_pow_cache_mulpow_ui(p + j, p + j, ei, alpha_caches + k - 2, fpctx); } } } EH->length = Amarkslen; TMP_END; } /* return the largest degree */ slong fmpz_mod_polyun_product_roots( fmpz_mod_polyun_t M, const fmpz_mod_polyun_t H, const fmpz_mod_ctx_t ctx) { slong i, max_length = 0; fmpz_mod_polyun_fit_length(M, H->length, ctx); M->length = H->length; for (i = 0; i < H->length; i++) { slong len = H->coeffs[i].length; M->exps[i] = H->exps[i]; max_length = FLINT_MAX(max_length, len); fmpz_mod_poly_product_roots_fmpz_vec(M->coeffs + i, H->coeffs[i].coeffs, len, ctx); } return max_length; } void fmpz_mod_polyun_zip_start( fmpz_mod_polyun_t Z, fmpz_mod_polyun_t H, slong req_images, const fmpz_mod_ctx_t fctx) { slong j; fmpz_mod_polyun_fit_length(Z, H->length, fctx); Z->length = H->length; for (j = 0; j < H->length; j++) { Z->exps[j] = H->exps[j]; fmpz_mod_poly_fit_length(Z->coeffs + j, req_images, fctx); Z->coeffs[j].length = 0; } } /* return -1: singular 0: inconsistent 1: success */ int _fmpz_mod_zip_vand_solve( fmpz * coeffs, /* in Fp: size mlength */ const fmpz * monomials, /* in Fp: size mlength */ slong mlength, const fmpz * evals, /* in Fp: size elength */ slong elength, const fmpz * master, /* in Fp: size mlength + 1 */ fmpz * scratch, /* in Fp: size mlength */ const fmpz_mod_ctx_t ctx) { int success; slong i, j; fmpz_t V, T, S, r; FLINT_ASSERT(elength >= mlength); fmpz_init(V); fmpz_init(T); fmpz_init(S); fmpz_init(r); for (i = 0; i < mlength; i++) { /* coeffs[i] is (coeffs(P).values)/P(roots[i]) =: V/S where P(x) = master(x)/(x-roots[i]) */ fmpz_zero(V); fmpz_zero(T); fmpz_zero(S); fmpz_set(r, monomials + i); for (j = mlength; j > 0; j--) { fmpz_mod_addmul(T, master + j, r, T, ctx); fmpz_mod_addmul(S, T, r, S, ctx); fmpz_mod_addmul(V, V, T, evals + j - 1, ctx); } /* roots[i] should be a root of master */ #if FLINT_WANT_ASSERT fmpz_mod_addmul(T, master + 0, r, T, ctx); FLINT_ASSERT(fmpz_is_zero(T)); #endif fmpz_mod_mul(S, S, r, ctx); if (fmpz_is_zero(S)) { success = -1; goto cleanup; } fmpz_mod_inv(S, S, ctx); fmpz_mod_mul(coeffs + i, V, S, ctx); } /* check that the remaining points match */ for (j = 0; j < mlength; j++) fmpz_mod_pow_ui(scratch + j, monomials + j, mlength, ctx); for (i = mlength; i < elength; i++) { fmpz_zero(V); for (j = 0; j < mlength; j++) { fmpz_mod_mul(scratch + j, scratch + j, monomials + j, ctx); fmpz_mod_addmul(V, V, coeffs + j, scratch + j, ctx); } if (!fmpz_equal(V, evals + i)) { success = 0; goto cleanup; } } success = 1; cleanup: fmpz_clear(V); fmpz_clear(T); fmpz_clear(S); fmpz_clear(r); return success; } void _fmpz_mod_zip_eval_step( fmpz_t ev, fmpz * cur, /* in Fp */ const fmpz * inc, /* in Fp */ const fmpz * coeffs, /* in Fp */ slong length, const fmpz_mod_ctx_t ctx) { slong i; fmpz_zero(ev); for (i = 0; i < length; i++) { fmpz_mod_addmul(ev, ev, cur + i, coeffs + i, ctx); fmpz_mod_mul(cur + i, cur + i, inc + i, ctx); } } flint-3.1.3/src/fmpz_mod_poly.h000066400000000000000000001323531461254215100164600ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_POLY_H #define FMPZ_MOD_POLY_H #ifdef FMPZ_MOD_POLY_INLINES_C #define FMPZ_MOD_POLY_INLINE #else #define FMPZ_MOD_POLY_INLINE static inline #endif #include "nmod_types.h" #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif #define FMPZ_MOD_POLY_HGCD_CUTOFF 128 /* HGCD: Basecase -> Recursion */ #define FMPZ_MOD_POLY_GCD_CUTOFF 256 /* GCD: Euclidean -> HGCD */ #define FMPZ_MOD_POLY_INV_NEWTON_CUTOFF 64 /* Inv series newton: Basecase -> Newton */ #define FMPZ_MOD_POLY_DIV_DIVCONQUER_CUTOFF #define FMPZ_MOD_POLY_EVALUATE_FMPZ_VEC 32 /* Evaluate fmpz_vec: Iter -> Fast */ /* Type definitions *********************************************************/ typedef struct { fmpz_t res; fmpz_t lc; slong len0; slong len1; slong off; } fmpz_mod_poly_res_struct; typedef fmpz_mod_poly_res_struct fmpz_mod_poly_res_t[1]; typedef struct { fmpz_mod_poly_struct * pow; slong len; } fmpz_mod_poly_frobenius_powers_2exp_struct; typedef fmpz_mod_poly_frobenius_powers_2exp_struct fmpz_mod_poly_frobenius_powers_2exp_t[1]; typedef struct { fmpz_mod_poly_struct * pow; slong len; } fmpz_mod_poly_frobenius_powers_struct; typedef fmpz_mod_poly_frobenius_powers_struct fmpz_mod_poly_frobenius_powers_t[1]; typedef struct { fmpz_mat_struct * A; fmpz_mod_poly_struct * poly1; fmpz_mod_poly_struct * poly2; fmpz_mod_poly_struct * poly2inv; const fmpz_mod_ctx_struct * ctx; } fmpz_mod_poly_matrix_precompute_arg_t; typedef struct { fmpz_mat_struct * A; fmpz_mod_poly_struct * res; fmpz_mod_poly_struct * poly1; fmpz_mod_poly_struct * poly3; fmpz_mod_poly_struct * poly3inv; const fmpz_mod_ctx_struct * ctx; } fmpz_mod_poly_compose_mod_precomp_preinv_arg_t; /* Initialisation and memory management *************************************/ FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_init(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { poly->coeffs = NULL; poly->alloc = 0; poly->length = 0; } void fmpz_mod_poly_init2(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_clear(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_realloc(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_fit_length(fmpz_mod_poly_t poly, slong len); FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_fit_length(fmpz_mod_poly_t poly, slong len, const fmpz_mod_ctx_t ctx) { _fmpz_mod_poly_fit_length(poly, len); } /* Normalisation and truncation *********************************************/ FMPZ_MOD_POLY_INLINE void _fmpz_mod_poly_normalise(fmpz_mod_poly_t poly) { slong i; for (i = poly->length - 1; (i >= 0) && !poly->coeffs[i]; i--) ; poly->length = i + 1; } void _fmpz_mod_poly_set_length(fmpz_mod_poly_t poly, slong len); void fmpz_mod_poly_truncate(fmpz_mod_poly_t poly, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_set_trunc(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_canonical(const fmpz_mod_poly_t A, const fmpz_mod_ctx_t ctx); /* Randomisation ************************************************************/ void fmpz_mod_poly_randtest(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_not_zero(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_monic(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_monic_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_monic_primitive(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_trinomial(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_randtest_trinomial_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, slong max_attempts, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_pentomial(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_randtest_pentomial_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, slong max_attempts, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_randtest_sparse_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); /* Attributes ***************************************************************/ FMPZ_MOD_POLY_INLINE slong fmpz_mod_poly_length(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return poly->length; } FMPZ_MOD_POLY_INLINE slong fmpz_mod_poly_degree(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return poly->length - 1; } FMPZ_MOD_POLY_INLINE fmpz * fmpz_mod_poly_lead(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { if (poly->length) return poly->coeffs + (poly->length - 1); else return NULL; } FMPZ_MOD_POLY_INLINE int fmpz_mod_poly_is_monic(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { return f->length > 0 && f->coeffs[f->length - 1] == WORD(1); } FMPZ_MOD_POLY_INLINE int fmpz_mod_poly_is_one(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return poly->length == 1 && poly->coeffs[0] == WORD(1); } FMPZ_MOD_POLY_INLINE int fmpz_mod_poly_is_gen(const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx) { return op->length == 2 && op->coeffs[1] == WORD(1) && op->coeffs[0] == WORD(0); } int fmpz_mod_poly_is_unit(const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx); /* Assignment and basic manipulation ****************************************/ void fmpz_mod_poly_set(fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_swap(fmpz_mod_poly_t poly1, fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) { FLINT_SWAP(fmpz_mod_poly_struct, *poly1, *poly2); } void _fmpz_mod_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_mod_poly_reverse(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_zero(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { _fmpz_mod_poly_set_length(poly, 0); } void fmpz_mod_poly_one(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_gen(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_zero_coeffs(fmpz_mod_poly_t poly, slong i, slong j, const fmpz_mod_ctx_t ctx); ulong fmpz_mod_poly_deflation(const fmpz_mod_poly_t input, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_deflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong deflation, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_inflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong inflation, const fmpz_mod_ctx_t ctx); /* Conversion ***************************************************************/ void fmpz_mod_poly_set_ui(fmpz_mod_poly_t f, ulong x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_set_nmod_poly(fmpz_mod_poly_t f, const nmod_poly_t g); void fmpz_mod_poly_set_fmpz(fmpz_mod_poly_t poly, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_set_fmpz_poly(fmpz_mod_poly_t f, const fmpz_poly_t g, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_get_nmod_poly(nmod_poly_t f, const fmpz_mod_poly_t g); void fmpz_mod_poly_get_fmpz_poly(fmpz_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx); /* Comparison ***************************************************************/ int fmpz_mod_poly_equal(const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_equal_trunc(const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_zero(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); /* Getting and setting coefficients *****************************************/ void fmpz_mod_poly_set_coeff_fmpz(fmpz_mod_poly_t poly, slong n, const fmpz_t x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_set_coeff_ui(fmpz_mod_poly_t poly, slong n, ulong x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_set_coeff_si(fmpz_mod_poly_t poly, slong n, slong x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_get_coeff_fmpz(fmpz_t x, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx); /* Shifting *****************************************************************/ void _fmpz_mod_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_mod_poly_shift_left(fmpz_mod_poly_t f, const fmpz_mod_poly_t g, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_mod_poly_shift_right(fmpz_mod_poly_t f, const fmpz_mod_poly_t g, slong n, const fmpz_mod_ctx_t ctx); /* Addition and subtraction *************************************************/ void _fmpz_mod_poly_neg(fmpz *res, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_neg(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_add(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_add(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_sub(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_sub(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_add_series(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_sub_series(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx); /* Scalar multiplication ****************************************************/ void _fmpz_mod_poly_scalar_mul_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_scalar_mul_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t x, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_scalar_mul_ui(fmpz *res, const fmpz *poly, slong len, ulong x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_scalar_mul_ui(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_scalar_addmul_fmpz(fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_t x, const fmpz_mod_ctx_t ctx); /* Scalar division ****************************************************/ void _fmpz_mod_poly_scalar_div_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_scalar_div_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t x, const fmpz_mod_ctx_t ctx); /* Multiplication ***********************************************************/ void _fmpz_mod_poly_mul(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_mul(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_mullow(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_mullow(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_sqr(fmpz *res, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_mulhigh(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong start, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_sqr(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_mulmod(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_mulmod(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_mulmod_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz* finv, slong lenfinv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_mulmod_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx); /* Powering *****************************************************************/ void _fmpz_mod_poly_pow(fmpz *rop, const fmpz *op, slong len, ulong e, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_pow(fmpz_mod_poly_t rop, const fmpz_mod_poly_t op, ulong e, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_pow_trunc(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_pow_trunc_binexp(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_pow_trunc_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_powmod_ui_binexp(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_powmod_ui_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz * finv, slong lenfinv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_powmod_fmpz_binexp(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_powmod_fmpz_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz* finv, slong lenfinv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz * res, const fmpz_t e, const fmpz * f, slong lenf, const fmpz* finv, slong lenfinv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz_mod_poly_t res, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_powmod_linear_fmpz_preinv(fmpz_mod_poly_t res, const fmpz_t a, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_powers_mod_preinv_naive(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_powers_mod_naive(fmpz_mod_poly_struct * res, const fmpz_mod_poly_t f, slong n, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_powers_mod_preinv_threaded_pool(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads); void fmpz_mod_poly_powers_mod_bsgs(fmpz_mod_poly_struct * res, const fmpz_mod_poly_t f, slong n, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_frobenius_powers_2exp_precomp( fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, ulong m, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_frobenius_powers_2exp_clear( fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_frobenius_power(fmpz_mod_poly_t res, fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_poly_t f, ulong m, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_frobenius_powers_precomp( fmpz_mod_poly_frobenius_powers_t pow, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, ulong m, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_frobenius_powers_clear( fmpz_mod_poly_frobenius_powers_t pow, const fmpz_mod_ctx_t ctx); /* Division *****************************************************************/ void _fmpz_mod_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_divrem_basecase(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_div_newton_n_preinv (fmpz* Q, const fmpz* A, slong lenA, const fmpz* B, slong lenB, const fmpz* Binv, slong lenBinv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_div_newton_n_preinv(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_divrem_newton_n_preinv (fmpz* Q, fmpz* R, const fmpz* A, slong lenA, const fmpz* B, slong lenB, const fmpz* Binv, slong lenBinv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_divrem_newton_n_preinv(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx); ulong fmpz_mod_poly_remove(fmpz_mod_poly_t f, const fmpz_mod_poly_t p, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_rem_basecase(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_rem_basecase(fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_divrem(fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_divrem(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_div(fmpz *Q, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_div(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_divrem_f(fmpz_t f, fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_divrem_f(fmpz_t f, fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_rem(fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_rem(fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_rem_f(fmpz_t f, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); /* Divisibility testing ******************************************************/ int _fmpz_mod_poly_divides_classical(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_divides_classical(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); int _fmpz_mod_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_divides(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); /* Power series inversion ***************************************************/ void _fmpz_mod_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_inv_series(fmpz_mod_poly_t Qinv, const fmpz_mod_poly_t Q, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_inv_series_f(fmpz_t f, fmpz_mod_poly_t Qinv, const fmpz_mod_poly_t Q, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_div_series(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, slong n, const fmpz_mod_ctx_t ctx); /* Greatest common divisor **************************************************/ void fmpz_mod_poly_make_monic(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_make_monic_f(fmpz_t f, fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_gcd(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_gcd(fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE slong _fmpz_mod_poly_gcd_f(fmpz_t f, fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx) { return _fmpz_mod_poly_gcd_euclidean_f(f, G, A, lenA, B, lenB, ctx); } FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_gcd_f(fmpz_t f, fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_gcd_euclidean_f(f, G, A, B, ctx); } slong _fmpz_mod_poly_hgcd(fmpz **M, slong *lenM, fmpz *A, slong *lenA, fmpz *B, slong *lenB, const fmpz *a, slong lena, const fmpz *b, slong lenb, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_xgcd(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_xgcd(fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE slong _fmpz_mod_poly_xgcd_f(fmpz_t f, fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { return _fmpz_mod_poly_xgcd_euclidean_f(f, G, S, T, A, lenA, B, lenB, invB, ctx); } FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_xgcd_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_xgcd_euclidean_f(f, G, S, T, A, B, ctx); } slong _fmpz_mod_poly_gcdinv_euclidean_f(fmpz_t f, fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_gcdinv_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_gcdinv_euclidean(fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_gcdinv_euclidean(fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_gcdinv(fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_gcdinv(fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_gcdinv_f(fmpz_t f, fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_gcdinv_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); int _fmpz_mod_poly_invmod(fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_mod_ctx_t ctx); int _fmpz_mod_poly_invmod_f(fmpz_t f, fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_invmod(fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_invmod_f(fmpz_t f, fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx); /* Square root ***************************************************************/ void _fmpz_mod_poly_invsqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t mod); void fmpz_mod_poly_invsqrt_series(fmpz_mod_poly_t g, const fmpz_mod_poly_t h, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_sqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t mod); void fmpz_mod_poly_sqrt_series(fmpz_mod_poly_t g, const fmpz_mod_poly_t h, slong n, const fmpz_mod_ctx_t ctx); int _fmpz_mod_poly_sqrt(fmpz * s, const fmpz * p, slong len, const fmpz_mod_ctx_t mod); int fmpz_mod_poly_sqrt(fmpz_mod_poly_t b, const fmpz_mod_poly_t a, const fmpz_mod_ctx_t ctx); /* Minpoly *****************************************************************/ slong _fmpz_mod_poly_minpoly_bm(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_minpoly_bm(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_minpoly_hgcd(fmpz * poly, const fmpz* seq, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_minpoly_hgcd(fmpz_mod_poly_t poly, const fmpz* seq, slong len, const fmpz_mod_ctx_t ctx); slong _fmpz_mod_poly_minpoly(fmpz* poly, const fmpz* seq, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_minpoly(fmpz_mod_poly_t poly, const fmpz* seq, slong len, const fmpz_mod_ctx_t ctx); /* Resultant ***************************************************************/ void _fmpz_mod_poly_resultant(fmpz_t res, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_resultant(fmpz_t res, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); /* Discriminant ************************************************************/ void _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_discriminant(fmpz_t d, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); /* Derivative **************************************************************/ void _fmpz_mod_poly_derivative(fmpz *res, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_derivative(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); /* Evaluation **************************************************************/ void _fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz *poly, slong len, const fmpz_t a, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz_mod_poly_t poly, const fmpz_t a, const fmpz_mod_ctx_t ctx); fmpz_poly_struct ** _fmpz_mod_poly_tree_alloc(slong len); void _fmpz_mod_poly_tree_free(fmpz_poly_struct ** tree, slong len); void _fmpz_mod_poly_tree_build(fmpz_poly_struct ** tree, const fmpz * roots, slong len, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp(fmpz * vs, const fmpz * poly, slong plen, fmpz_poly_struct * const * tree, slong len, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz * poly, slong plen, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); /* Composition *************************************************************/ void _fmpz_mod_poly_compose(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_compose(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx); /* Modular composition ******************************************************/ void _fmpz_mod_poly_compose_mod(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_compose_mod(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_compose_mod_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, const fmpz * poly3, slong len3, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_compose_mod_brent_kung(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_reduce_matrix_mod_poly (fmpz_mat_t A, const fmpz_mat_t B, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_precompute_matrix(fmpz_mat_t A, const fmpz * poly1, const fmpz * poly2, slong len2, const fmpz * poly2inv, slong len2inv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_precompute_matrix_worker(void * arg_ptr); void fmpz_mod_poly_precompute_matrix(fmpz_mat_t A, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly2inv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz_mat_t A, const fmpz * poly3, slong len3, const fmpz * poly3inv, slong len3inv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr); void fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mat_t A, const fmpz_mod_poly_t poly3, const fmpz_mod_poly_t poly3inv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, const fmpz * poly3, slong len3, const fmpz * poly3inv, slong len3inv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_poly_t poly3inv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_compose_mod_horner(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_compose_mod_horner(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong l, const fmpz * g, slong glen, const fmpz * poly, slong len, const fmpz * polyinv, slong leninv, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv( fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1,slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong lenpolys, slong l, const fmpz * g, slong glen, const fmpz * poly, slong len, const fmpz * polyinv, slong leninv, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads); void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads); void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx); /* Norms *********************************************************************/ slong fmpz_mod_poly_hamming_weight(const fmpz_mod_poly_t A, const fmpz_mod_ctx_t ctx); /* Radix conversion *********************************************************/ typedef struct { fmpz *V; fmpz *W; fmpz **Rpow; fmpz **Rinv; slong degR; slong k; fmpz invL; } fmpz_mod_poly_radix_struct; typedef fmpz_mod_poly_radix_struct fmpz_mod_poly_radix_t[1]; void _fmpz_mod_poly_radix_init(fmpz **Rpow, fmpz **Rinv, const fmpz *R, slong lenR, slong k, const fmpz_t invL, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_radix_init(fmpz_mod_poly_radix_t D, const fmpz_mod_poly_t R, slong degF, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_radix_clear(fmpz_mod_poly_radix_t D); void _fmpz_mod_poly_radix(fmpz **B, const fmpz *F, fmpz **Rpow, fmpz **Rinv, slong degR, slong k, slong i, fmpz *W, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_radix(fmpz_mod_poly_struct **B, const fmpz_mod_poly_t F, const fmpz_mod_poly_radix_t D, const fmpz_mod_ctx_t ctx); /* Input and output *********************************************************/ char * fmpz_mod_poly_get_str(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); char * fmpz_mod_poly_get_str_pretty(const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx); #ifdef FLINT_HAVE_FILE int _fmpz_mod_poly_fprint(FILE * file, const fmpz *poly, slong len, const fmpz_t p); int fmpz_mod_poly_fprint(FILE * file, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_fprint_pretty(FILE * file, const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_fread(FILE * file, fmpz_mod_poly_t poly, fmpz_mod_ctx_t ctx); #endif int _fmpz_mod_poly_print(const fmpz *poly, slong len, const fmpz_t p); int fmpz_mod_poly_print(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_print_pretty(const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx); /* Products *****************************************************************/ void _fmpz_mod_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_product_roots_fmpz_vec(fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_find_distinct_nonzero_roots(fmpz * roots, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_split_rabin(fmpz_mod_poly_t a, fmpz_mod_poly_t b, const fmpz_mod_poly_t f, const fmpz_t halfp, fmpz_mod_poly_t t, fmpz_mod_poly_t t2, flint_rand_t randstate, const fmpz_mod_ctx_t ctx); /* Characteristic polynomial and minimal polynomial */ void fmpz_mod_mat_charpoly_berkowitz(fmpz_mod_poly_t p, const fmpz_mod_mat_t M, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE void fmpz_mod_mat_charpoly(fmpz_mod_poly_t p, const fmpz_mod_mat_t M, const fmpz_mod_ctx_t ctx) { fmpz_mod_mat_charpoly_berkowitz(p, M, ctx); } void fmpz_mod_mat_minpoly(fmpz_mod_poly_t p, const fmpz_mod_mat_t M, const fmpz_mod_ctx_t ctx); /* Berlekamp-Massey Algorithm - see fmpz_mod_poly/berlekamp_massey.c for more info ********/ typedef struct { slong npoints; fmpz_mod_poly_t R0, R1; fmpz_mod_poly_t V0, V1; fmpz_mod_poly_t qt, rt; fmpz_mod_poly_t points; } fmpz_mod_berlekamp_massey_struct; typedef fmpz_mod_berlekamp_massey_struct fmpz_mod_berlekamp_massey_t[1]; void fmpz_mod_berlekamp_massey_init( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_berlekamp_massey_start_over( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_berlekamp_massey_clear(fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_berlekamp_massey_print( const fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); void fmpz_mod_berlekamp_massey_add_points( fmpz_mod_berlekamp_massey_t B, const fmpz * a, slong count, const fmpz_mod_ctx_t ctx); void fmpz_mod_berlekamp_massey_add_zeros( fmpz_mod_berlekamp_massey_t B, slong count, const fmpz_mod_ctx_t ctx); void fmpz_mod_berlekamp_massey_add_point( fmpz_mod_berlekamp_massey_t B, const fmpz_t a, const fmpz_mod_ctx_t ctx); void fmpz_mod_berlekamp_massey_add_point_ui( fmpz_mod_berlekamp_massey_t B, ulong a, const fmpz_mod_ctx_t ctx); int fmpz_mod_berlekamp_massey_reduce( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE const fmpz * fmpz_mod_berlekamp_massey_points( const fmpz_mod_berlekamp_massey_t B) { return B->points->coeffs; } FMPZ_MOD_POLY_INLINE slong fmpz_mod_berlekamp_massey_point_count( const fmpz_mod_berlekamp_massey_t B) { return B->points->length; } FMPZ_MOD_POLY_INLINE const fmpz_mod_poly_struct * fmpz_mod_berlekamp_massey_V_poly( const fmpz_mod_berlekamp_massey_t B) { return B->V1; } FMPZ_MOD_POLY_INLINE const fmpz_mod_poly_struct * fmpz_mod_berlekamp_massey_R_poly( const fmpz_mod_berlekamp_massey_t B) { return B->R1; } /* Inlines *******************************************************************/ void fmpz_mod_poly_add_si(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_sub_si(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong c, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_si_sub(fmpz_mod_poly_t res, slong c, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_add_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_sub_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t c, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_fmpz_sub(fmpz_mod_poly_t res, const fmpz_t c, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); /* Declare dead functions *******************************************************************/ #define fmpz_mod_poly_set_coeff_mpz _Pragma("GCC error \"'fmpz_mod_poly_set_coeff_mpz' is deprecated. Use 'fmpz_mod_poly_set_coeff_fmpz' instead.\"") #define fmpz_mod_poly_get_coeff_mpz _Pragma("GCC error \"'fmpz_mod_poly_get_coeff_mpz' is deprecated. Use 'fmpz_mod_poly_get_coeff_fmpz' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mod_poly/000077500000000000000000000000001461254215100163005ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_poly/add.c000066400000000000000000000026531461254215100172020ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_add(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx) { slong len3 = FLINT_MIN(len1, len2); _fmpz_mod_vec_add(res, poly1, poly2, len3, ctx); if (len1 > len3) _fmpz_vec_set(res + len3, poly1 + len3, len1 - len3); if (len2 > len3) _fmpz_vec_set(res + len3, poly2 + len3, len2 - len3); } void fmpz_mod_poly_add(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) { slong max = FLINT_MAX(poly1->length, poly2->length); fmpz_mod_poly_fit_length(res, max, ctx); _fmpz_mod_poly_add(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/add_series.c000066400000000000000000000021731461254215100205510ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_add_series(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); fmpz_mod_poly_fit_length(res, max, ctx); _fmpz_mod_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/attributes.c000066400000000000000000000011571461254215100206360ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" /* bogus for non-prime modulus */ int fmpz_mod_poly_is_unit(const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx) { return (op->length == 1) && fmpz_mod_is_invertible(op->coeffs + 0, ctx); } flint-3.1.3/src/fmpz_mod_poly/berlekamp_massey.c000066400000000000000000000201701461254215100217670ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #if FLINT_WANT_ASSERT # include "fmpz_mod.h" #endif /* typedef struct { slong npoints; fmpz_mod_poly_t R0, R1; fmpz_mod_poly_t V0, V1; fmpz_mod_poly_t qt, rt; temporaries fmpz_mod_poly_t points; } fmpz_mod_berlekamp_massey_struct; typedef fmpz_mod_berlekamp_massey_struct nmod_berlekamp_massey_t[1]; n = B->npoints is the number of points a_1, ..., a_n that have been added to the sequence. The polynomials A and S are then defined as A = x^n S = a_1*x^(n-1) + a_2*x^(n-2) + ... + a_n We maintain polynomials U0, V0, U1, V1 such that U0*A + V0*S = R0 deg(R0) >= n/2 U1*A + V1*S = R1 deg(R1) < n/2 where R0 and R1 are consecutive euclidean remainders and U0, V0, U1, V1 are the corresponding Bezout coefficients. Note that deg(U1) < deg(V1) = deg(A) - deg(R0) <= n/2 The U0 and U1 are not stored explicitly. The points a_1, ..., a_n are stored in B->points, which is used merely as a resizable array. The main usage of this function is the rational reconstruction of a series a1 a2 a3 -U1 --- + --- + --- + ... = ---- maybe x x^2 x^3 V1 It can be seen that a1 a2 an -U1 R1 --- + --- + ... --- = --- + ------- x x^2 x^n V1 V1*x^n Thus the error is O(1/x^(n+1)) iff deg(R1) < deg(V1). */ void fmpz_mod_berlekamp_massey_init( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_init(B->V0, ctx); fmpz_mod_poly_init(B->R0, ctx); fmpz_mod_poly_set_ui(B->R0, 1, ctx); fmpz_mod_poly_init(B->V1, ctx); fmpz_mod_poly_set_ui(B->V1, 1, ctx); fmpz_mod_poly_init(B->R1, ctx); fmpz_mod_poly_init(B->rt, ctx); fmpz_mod_poly_init(B->qt, ctx); fmpz_mod_poly_init(B->points, ctx); B->npoints = 0; B->points->length = 0; } void fmpz_mod_berlekamp_massey_start_over( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) { B->npoints = 0; B->points->length = 0; fmpz_mod_poly_zero(B->V0, ctx); fmpz_mod_poly_set_ui(B->R0, 1, ctx); fmpz_mod_poly_set_ui(B->V1, 1, ctx); fmpz_mod_poly_zero(B->R1, ctx); } void fmpz_mod_berlekamp_massey_clear( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_clear(B->R0, ctx); fmpz_mod_poly_clear(B->R1, ctx); fmpz_mod_poly_clear(B->V0, ctx); fmpz_mod_poly_clear(B->V1, ctx); fmpz_mod_poly_clear(B->rt, ctx); fmpz_mod_poly_clear(B->qt, ctx); fmpz_mod_poly_clear(B->points, ctx); } void fmpz_mod_berlekamp_massey_print( const fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_print_pretty(B->V1, "#", ctx); flint_printf(","); for (i = 0; i < B->points->length; i++) { flint_printf(" "); fmpz_print(B->points->coeffs + i); } } void fmpz_mod_berlekamp_massey_add_points( fmpz_mod_berlekamp_massey_t B, const fmpz * a, slong count, const fmpz_mod_ctx_t ctx) { slong i; slong old_length = B->points->length; fmpz_mod_poly_fit_length(B->points, old_length + count, ctx); for (i = 0; i < count; i++) { FLINT_ASSERT(fmpz_mod_is_canonical(a + i, ctx)); fmpz_set(B->points->coeffs + old_length + i, a + i); } B->points->length = old_length + count; } void fmpz_mod_berlekamp_massey_add_zeros( fmpz_mod_berlekamp_massey_t B, slong count, const fmpz_mod_ctx_t ctx) { slong i; slong old_length = B->points->length; fmpz_mod_poly_fit_length(B->points, old_length + count, ctx); for (i = 0; i < count; i++) { fmpz_zero(B->points->coeffs + old_length + i); } B->points->length = old_length + count; } void fmpz_mod_berlekamp_massey_add_point( fmpz_mod_berlekamp_massey_t B, const fmpz_t a, const fmpz_mod_ctx_t ctx) { slong old_length = B->points->length; fmpz_mod_poly_fit_length(B->points, old_length + 1, ctx); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); fmpz_set(B->points->coeffs + old_length, a); B->points->length = old_length + 1; } void fmpz_mod_berlekamp_massey_add_point_ui( fmpz_mod_berlekamp_massey_t B, ulong a, const fmpz_mod_ctx_t ctx) { slong old_length = B->points->length; fmpz_mod_poly_fit_length(B->points, old_length + 1, ctx); FLINT_ASSERT(fmpz_cmp_ui(fmpz_mod_ctx_modulus(ctx), a) > 0); fmpz_set_ui(B->points->coeffs + old_length, a); B->points->length = old_length + 1; } /* return 1 if reduction changed the master poly, 0 otherwise */ int fmpz_mod_berlekamp_massey_reduce( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx) { slong i, l, k, queue_len, queue_lo, queue_hi; /* the points in B->points->coeffs[j] for queue_lo <= j < queue_hi need to be added to the internal polynomials. These are first reversed into rt. deg(rt) < queue_len. */ queue_lo = B->npoints; queue_hi = B->points->length; queue_len = queue_hi - queue_lo; FLINT_ASSERT(queue_len >= 0); fmpz_mod_poly_zero(B->rt, ctx); for (i = 0; i < queue_len; i++) { fmpz_mod_poly_set_coeff_fmpz(B->rt, queue_len - i - 1, B->points->coeffs + queue_lo + i, ctx); } B->npoints = queue_hi; /* Ri = Ri * x^queue_len + Vi*rt */ fmpz_mod_poly_mul(B->qt, B->V0, B->rt, ctx); fmpz_mod_poly_shift_left(B->R0, B->R0, queue_len, ctx); fmpz_mod_poly_add(B->R0, B->R0, B->qt, ctx); fmpz_mod_poly_mul(B->qt, B->V1, B->rt, ctx); fmpz_mod_poly_shift_left(B->R1, B->R1, queue_len, ctx); fmpz_mod_poly_add(B->R1, B->R1, B->qt, ctx); /* now start reducing R0, R1 */ if (2*fmpz_mod_poly_degree(B->R1, ctx) < B->npoints) { /* already have deg(R1) < B->npoints/2 */ return 0; } /* one iteration of euclid to get deg(R0) >= B->npoints/2 */ fmpz_mod_poly_divrem(B->qt, B->rt, B->R0, B->R1, ctx); fmpz_mod_poly_swap(B->R0, B->R1, ctx); fmpz_mod_poly_swap(B->R1, B->rt, ctx); fmpz_mod_poly_mul(B->rt, B->qt, B->V1, ctx); fmpz_mod_poly_sub(B->qt, B->V0, B->rt, ctx); fmpz_mod_poly_swap(B->V0, B->V1, ctx); fmpz_mod_poly_swap(B->V1, B->qt, ctx); l = fmpz_mod_poly_degree(B->R0, ctx); FLINT_ASSERT(B->npoints <= 2*l && l < B->npoints); k = B->npoints - l; FLINT_ASSERT(0 <= k && k <= l); /* (l - k)/2 is the expected number of required euclidean iterations. Either branch is OK anytime. TODO: find cutoff */ if (l - k < 10) { while (B->npoints <= 2*fmpz_mod_poly_degree(B->R1, ctx)) { fmpz_mod_poly_divrem(B->qt, B->rt, B->R0, B->R1, ctx); fmpz_mod_poly_swap(B->R0, B->R1, ctx); fmpz_mod_poly_swap(B->R1, B->rt, ctx); fmpz_mod_poly_mul(B->rt, B->qt, B->V1, ctx); fmpz_mod_poly_sub(B->qt, B->V0, B->rt, ctx); fmpz_mod_poly_swap(B->V0, B->V1, ctx); fmpz_mod_poly_swap(B->V1, B->qt, ctx); } } else { /* TODO: get hgcd working in this branch */ while (B->npoints <= 2*fmpz_mod_poly_degree(B->R1, ctx)) { fmpz_mod_poly_divrem(B->qt, B->rt, B->R0, B->R1, ctx); fmpz_mod_poly_swap(B->R0, B->R1, ctx); fmpz_mod_poly_swap(B->R1, B->rt, ctx); fmpz_mod_poly_mul(B->rt, B->qt, B->V1, ctx); fmpz_mod_poly_sub(B->qt, B->V0, B->rt, ctx); fmpz_mod_poly_swap(B->V0, B->V1, ctx); fmpz_mod_poly_swap(B->V1, B->qt, ctx); } } FLINT_ASSERT(fmpz_mod_poly_degree(B->V1, ctx) >= 0); FLINT_ASSERT(2*fmpz_mod_poly_degree(B->V1, ctx) <= B->npoints); FLINT_ASSERT(2*fmpz_mod_poly_degree(B->R0, ctx) >= B->npoints); FLINT_ASSERT(2*fmpz_mod_poly_degree(B->R1, ctx) < B->npoints); return 1; } flint-3.1.3/src/fmpz_mod_poly/clear.c000066400000000000000000000013131461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_clear(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < poly->alloc; i++) /* Clean up any mpz_t's */ _fmpz_demote(poly->coeffs + i); if (poly->coeffs) flint_free(poly->coeffs); /* clean up ordinary coeffs */ } flint-3.1.3/src/fmpz_mod_poly/comparison.c000066400000000000000000000020411461254215100206130ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" int fmpz_mod_poly_equal(const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) { return fmpz_poly_equal((fmpz_poly_struct *) poly1, (fmpz_poly_struct *) poly2); } int fmpz_mod_poly_equal_trunc(const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) { return fmpz_poly_equal_trunc((fmpz_poly_struct *) poly1, (fmpz_poly_struct *) poly2, n); } int fmpz_mod_poly_is_zero(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return poly->length == 0; } flint-3.1.3/src/fmpz_mod_poly/compose.c000066400000000000000000000040201461254215100201050ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr_poly.h" void _fmpz_mod_poly_compose(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_poly_compose(res, poly1, len1, poly2, len2, gr_ctx)); } void fmpz_mod_poly_compose(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { fmpz_mod_poly_zero(res, ctx); } else if (len1 == 1 || len2 == 0) { fmpz_mod_poly_set_fmpz(res, poly1->coeffs, ctx); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if ((res != poly1) && (res != poly2)) { fmpz_mod_poly_fit_length(res, lenr, ctx); _fmpz_mod_poly_compose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); } else { fmpz *t = _fmpz_vec_init(lenr); _fmpz_mod_poly_compose(t, poly1->coeffs, len1, poly2->coeffs, len2, ctx); _fmpz_vec_clear(res->coeffs, res->alloc); res->coeffs = t; res->alloc = lenr; res->length = lenr; } _fmpz_mod_poly_set_length(res, lenr); _fmpz_mod_poly_normalise(res); } } flint-3.1.3/src/fmpz_mod_poly/compose_mod.c000066400000000000000000000051411461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_compose_mod(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_mod_ctx_t ctx) { if (lenh < 12 || lenf >= lenh) _fmpz_mod_poly_compose_mod_horner(res, f, lenf, g, h, lenh, ctx); else _fmpz_mod_poly_compose_mod_brent_kung(res, f, lenf, g, h, lenh, ctx); } void fmpz_mod_poly_compose_mod(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_ctx_t ctx) { fmpz_t inv3; slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); fmpz * ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod):" "Division by zero.\n"); } if (len1 == 0 || len3 == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (len1 == 1) { fmpz_mod_poly_set(res, poly1, ctx); return; } if (res == poly3 || res == poly1) { fmpz_mod_poly_t tmp; fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_compose_mod(tmp, poly1, poly2, poly3, ctx); fmpz_mod_poly_swap(tmp, res, ctx); fmpz_mod_poly_clear(tmp, ctx); return; } ptr2 = _fmpz_vec_init(vec_len); if (len2 <= len) { _fmpz_vec_set(ptr2, poly2->coeffs, len2); _fmpz_vec_zero(ptr2 + len2, len - len2); } else { fmpz_init(inv3); fmpz_invmod(inv3, poly3->coeffs + len, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); fmpz_clear(inv3); } fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_compose_mod(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, vec_len); } flint-3.1.3/src/fmpz_mod_poly/compose_mod_brent_kung.c000066400000000000000000000106131461254215100231670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_compose_mod_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, const fmpz * poly3, slong len3, const fmpz_mod_ctx_t ctx) { fmpz_mat_t A, B, C; fmpz * t, * h, * tmp; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { fmpz_set(res, poly1); return; } if (len3 == 2) { _fmpz_mod_poly_evaluate_fmpz(res, poly1, len1, poly2, ctx); return; } m = n_sqrt(n) + 1; fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, n); h = _fmpz_vec_init(2 * n - 1); t = _fmpz_vec_init(2 * n - 1); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _fmpz_vec_set(B->rows[i], poly1 + i * m, m); _fmpz_vec_set(B->rows[i], poly1 + i * m, len1 % m); /* Set rows of A to powers of poly2 */ fmpz_one(A->rows[0]); _fmpz_vec_set(A->rows[1], poly2, n); tmp = _fmpz_vec_init(2 * n - 1); for (i = 2; i < m; i++) { _fmpz_mod_poly_mulmod(tmp, A->rows[i - 1], n, poly2, n, poly3, len3, ctx); _fmpz_vec_set(A->rows[i], tmp, n); } _fmpz_vec_clear(tmp, 2 * n - 1); fmpz_mat_mul(C, B, A); for (i = 0; i < m; i++) _fmpz_mod_vec_set_fmpz_vec(C->rows[i], C->rows[i], n, ctx); /* Evaluate block composition using the Horner scheme */ _fmpz_vec_set(res, C->rows[m - 1], n); _fmpz_mod_poly_mulmod(h, A->rows[m - 1], n, poly2, n, poly3, len3, ctx); for (i = m - 2; i >= 0; i--) { _fmpz_mod_poly_mulmod(t, res, n, h, n, poly3, len3, ctx); _fmpz_mod_poly_add(res, t, n, C->rows[i], n, ctx); } _fmpz_vec_clear(h, 2 * n - 1); _fmpz_vec_clear(t, 2 * n - 1); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } void fmpz_mod_poly_compose_mod_brent_kung(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); fmpz * ptr2; fmpz_t inv3; if (len3 == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung): Division by zero\n"); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung): " "The degree of the first polynomial must be smaller than that of the modulus\n"); } if (len1 == 0 || len3 == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (len1 == 1) { fmpz_mod_poly_set(res, poly1, ctx); return; } if (res == poly3 || res == poly1) { fmpz_mod_poly_t tmp; fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_compose_mod_brent_kung(tmp, poly1, poly2, poly3, ctx); fmpz_mod_poly_swap(tmp, res, ctx); fmpz_mod_poly_clear(tmp, ctx); return; } ptr2 = _fmpz_vec_init(vec_len); if (len2 <= len) { _fmpz_vec_set(ptr2, poly2->coeffs, len2); _fmpz_vec_zero(ptr2 + len2, vec_len - len2); } else { fmpz_init(inv3); fmpz_invmod(inv3, poly3->coeffs + len, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); fmpz_clear(inv3); } fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_compose_mod_brent_kung(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, vec_len); } flint-3.1.3/src/fmpz_mod_poly/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000146141461254215100263040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013, 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_reduce_matrix_mod_poly(fmpz_mat_t A, const fmpz_mat_t B, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { fmpz * tmp1, *tmp2; slong n = f->length - 1; slong i, m = n_sqrt(n) + 1; fmpz_t invf; fmpz_init(invf); fmpz_invmod(invf, f->coeffs + n, fmpz_mod_ctx_modulus(ctx)); fmpz_mat_init(A, m, n); tmp1 = _fmpz_vec_init(2 * (B->c) - n); tmp2 = tmp1 + (B->c - n); fmpz_one(A->rows[0]); for (i= 1; i < m; i++) { _fmpz_mod_poly_divrem(tmp1, tmp2, B->rows[i], B->c, f->coeffs, f->length, invf, ctx); _fmpz_vec_set(A->rows[i], tmp2, n); } _fmpz_vec_clear(tmp1, 2*(B->c) - n); fmpz_clear(invf); } void _fmpz_mod_poly_precompute_matrix(fmpz_mat_t A, const fmpz * poly1, const fmpz * poly2, slong len2, const fmpz * poly2inv, slong len2inv, const fmpz_mod_ctx_t ctx) { /* Set rows of A to powers of poly1 */ slong n, m; n = len2 - 1; m = n_sqrt(n) + 1; _fmpz_mod_poly_powers_mod_preinv_naive(A->rows, poly1, n, m, poly2, len2, poly2inv, len2inv, ctx); } void fmpz_mod_poly_precompute_matrix(fmpz_mat_t A, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly2inv, const fmpz_mod_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong len = len2 - 1; slong vec_len = FLINT_MAX(len2 - 1, len1); slong m = n_sqrt(len) + 1; fmpz * ptr; fmpz_t inv2; if (len2 == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_precompute_matrix): Division by zero.\n"); } if (A->r != m || A->c != len) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_precompute_matrix): Wrong dimensions.\n"); } if (len2 == 1) { fmpz_mat_zero(A); return; } ptr = _fmpz_vec_init(vec_len); if (len1 <= len) { _fmpz_vec_set(ptr, poly1->coeffs, len1); _fmpz_vec_zero(ptr + len1, vec_len - len1); } else { fmpz_init(inv2); fmpz_invmod(inv2, poly2->coeffs + len, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_rem(ptr, poly1->coeffs, len1, poly2->coeffs, len2, inv2, ctx); fmpz_clear(inv2); } _fmpz_mod_poly_precompute_matrix (A, ptr, poly2->coeffs, len2, poly2inv->coeffs, poly2inv->length, ctx); _fmpz_vec_clear(ptr, vec_len); } void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz_mat_t A, const fmpz * poly3, slong len3, const fmpz * poly3inv, slong len3inv, const fmpz_mod_ctx_t ctx) { fmpz_mat_t B, C; fmpz * t, * h; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { fmpz_set(res, poly1); return; } if (len3 == 2) { _fmpz_mod_poly_evaluate_fmpz(res, poly1, len1, A->rows[1], ctx); return; } m = n_sqrt(n) + 1; fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, n); h = _fmpz_vec_init(n); t = _fmpz_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _fmpz_vec_set(B->rows[i], poly1 + i * m, m); _fmpz_vec_set(B->rows[i], poly1 + i * m, len1 % m); fmpz_mat_mul(C, B, A); for (i = 0; i < m; i++) _fmpz_mod_vec_set_fmpz_vec(C->rows[i], C->rows[i], n, ctx); /* Evaluate block composition using the Horner scheme */ _fmpz_vec_set(res, C->rows[m - 1], n); _fmpz_mod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly3, len3, poly3inv, len3inv, ctx); for (i = m - 2; i >= 0; i--) { _fmpz_mod_poly_mulmod_preinv(t, res, n, h, n, poly3, len3, poly3inv, len3inv, ctx); _fmpz_mod_poly_add(res, t, n, C->rows[i], n, ctx); } _fmpz_vec_clear(h, n); _fmpz_vec_clear(t, n); fmpz_mat_clear(B); fmpz_mat_clear(C); } void fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mat_t A, const fmpz_mod_poly_t poly3, const fmpz_mod_poly_t poly3inv, const fmpz_mod_ctx_t ctx) { slong len1 = poly1->length; slong len3 = poly3->length; slong len = len3 - 1; if (len3 == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv): " "Division by zero\n"); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv): " "The degree of the first polynomial must be smaller than that of the modulus\n"); } if (len1 == 0 || len3 == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (len1 == 1) { fmpz_mod_poly_set(res, poly1, ctx); return; } if (res == poly3 || res == poly1 || res == poly3inv) { fmpz_mod_poly_t tmp; fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(tmp, poly1, A, poly3, poly3inv, ctx); fmpz_mod_poly_swap(tmp, res, ctx); fmpz_mod_poly_clear(tmp, ctx); return; } fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(res->coeffs, poly1->coeffs, len1, A, poly3->coeffs, len3, poly3inv->coeffs, poly3inv->length, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/compose_mod_brent_kung_preinv.c000066400000000000000000000111231461254215100245470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, const fmpz * poly3, slong len3, const fmpz * poly3inv, slong len3inv, const fmpz_mod_ctx_t ctx) { fmpz_mat_t A, B, C; fmpz * t, * h; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { fmpz_set(res, poly1); return; } if (len3 == 2) { _fmpz_mod_poly_evaluate_fmpz(res, poly1, len1, poly2, ctx); return; } m = n_sqrt(n) + 1; fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, n); h = _fmpz_vec_init(2 * n - 1); t = _fmpz_vec_init(2 * n - 1); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _fmpz_vec_set(B->rows[i], poly1 + i * m, m); _fmpz_vec_set(B->rows[i], poly1 + i * m, len1 % m); /* Set rows of A to powers of poly2 */ _fmpz_mod_poly_powers_mod_preinv_naive(A->rows, poly2, n, m, poly3, len3, poly3inv, len3inv, ctx); fmpz_mat_mul(C, B, A); for (i = 0; i < m; i++) _fmpz_mod_vec_set_fmpz_vec(C->rows[i], C->rows[i], n, ctx); /* Evaluate block composition using the Horner scheme */ _fmpz_vec_set(res, C->rows[m - 1], n); _fmpz_mod_poly_mulmod_preinv(h, A->rows[m - 1], n, poly2, n, poly3, len3, poly3inv, len3inv, ctx); for (i = m - 2; i >= 0; i--) { _fmpz_mod_poly_mulmod_preinv(t, res, n, h, n, poly3, len3, poly3inv, len3inv, ctx); _fmpz_mod_poly_add(res, t, n, C->rows[i], n, ctx); } _fmpz_vec_clear(h, 2 * n - 1); _fmpz_vec_clear(t, 2 * n - 1); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } void fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_poly_t poly3inv, const fmpz_mod_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; fmpz * ptr2; fmpz_t inv3; if (len3 == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung preinv): " "Division by zero\n"); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung_preinv): " "The degree of the first polynomial must be smaller than that of the modulus\n"); } if (len1 == 0 || len3 == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (len1 == 1) { fmpz_mod_poly_set(res, poly1, ctx); return; } if (res == poly3 || res == poly1 || res == poly3inv) { fmpz_mod_poly_t tmp; fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(tmp, poly1, poly2, poly3, poly3inv, ctx); fmpz_mod_poly_swap(tmp, res, ctx); fmpz_mod_poly_clear(tmp, ctx); return; } ptr2 = _fmpz_vec_init(len); if (len2 <= len) { _fmpz_vec_set(ptr2, poly2->coeffs, len2); _fmpz_vec_zero(ptr2 + len2, len - len2); } else { fmpz_init(inv3); fmpz_invmod(inv3, poly3->coeffs + len, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); fmpz_clear(inv3); } fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_compose_mod_brent_kung_preinv(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, poly3inv->coeffs, poly3inv->length, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, len); } flint-3.1.3/src/fmpz_mod_poly/compose_mod_brent_kung_vec_preinv.c000066400000000000000000000116521461254215100254130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong lenpolys, slong l, const fmpz * g, slong glen, const fmpz * poly, slong len, const fmpz * polyinv, slong leninv, const fmpz_mod_ctx_t ctx) { fmpz_mat_t A, B, C; fmpz *t, *h; slong i, j, k, n, m, len2 = l, len1; n = len - 1; m = n_sqrt(n * len2) + 1; h = _fmpz_vec_init(n); t = _fmpz_vec_init(n); k = len / m + 1; fmpz_mat_init(A, m, n); fmpz_mat_init(B, k * len2, m); fmpz_mat_init(C, k * len2, n); /* Set rows of B to the segments of polys */ for (j = 0; j < len2; j++) { len1 = (polys + j)->length; for (i = 0; i < len1 / m; i++) _fmpz_vec_set(B->rows[i + j * k], (polys + j)->coeffs + i * m, m); _fmpz_vec_set(B->rows[i + j * k], (polys + j)->coeffs + i * m, len1 % m); } /* Set rows of A to powers of last element of polys */ _fmpz_mod_poly_powers_mod_preinv_naive(A->rows, g, glen, m, poly, len, polyinv, leninv, ctx); fmpz_mat_mul(C, B, A); for (i = 0; i < k * len2; i++) _fmpz_mod_vec_set_fmpz_vec(C->rows[i], C->rows[i], n, ctx); /* Evaluate block composition using the Horner scheme */ if (n == 1) fmpz_mod_mul(h + 0, A->rows[m - 1] + 0, A->rows[1] + 0, ctx); else _fmpz_mod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly, len, polyinv, leninv, ctx); for (j = 0; j < len2; j++) { _fmpz_vec_set((res + j)->coeffs, C->rows[(j + 1) * k - 1], n); if (n == 1) { for (i = 2; i <= k; i++) { fmpz_mod_mul(t + 0, res[j].coeffs + 0, h + 0, ctx); fmpz_mod_add(res[j].coeffs + 0, t + 0, C->rows[(j + 1)*k - i] + 0, ctx); } } else { for (i = 2; i <= k; i++) { _fmpz_mod_poly_mulmod_preinv(t, res[j].coeffs, n, h, n, poly, len, polyinv, leninv, ctx); _fmpz_mod_poly_add(res[j].coeffs, t, n, C->rows[(j + 1)*k - i], n, ctx); } } } _fmpz_vec_clear(h, n); _fmpz_vec_clear(t, n); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv( fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx) { slong len2 = poly->length; slong len3, i; for (i = 0; i < len1; i++) { len3 = (polys + i)->length; if (len3 >= len2) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv): " "The degree of the first polynomial must be smaller than that of the modulus\n"); } } if (n > len1) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv): " "n is larger than the length of polys\n"); } if (n == 0) return; if (len2 == 1) { for (i = 0; i < n; i++) fmpz_mod_poly_zero(res + i, ctx); return; } if (len2 == 2) { for (i = 0; i < n; i++) fmpz_mod_poly_set(res + i, polys + i, ctx); return; } for (i = 0; i < n; i++) { fmpz_mod_poly_fit_length(res + i, len2 - 1, ctx); _fmpz_mod_poly_set_length(res + i, len2 - 1); } _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(res, polys, len1, n, g->coeffs, g->length, poly->coeffs, len2, polyinv->coeffs, polyinv->length, ctx); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); } flint-3.1.3/src/fmpz_mod_poly/compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000242471461254215100272570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" typedef struct { fmpz_mod_poly_struct * res; fmpz_mod_mat_struct * C; const fmpz * h; const fmpz * poly; const fmpz * polyinv; const fmpz_mod_ctx_struct * ctx; fmpz * t; volatile slong * j; slong k; slong m; slong len; slong leninv; slong len2; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } compose_vec_arg_t; void _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_worker(void * arg_ptr) { compose_vec_arg_t arg = *((compose_vec_arg_t *) arg_ptr); slong i, j, k = arg.k, n = arg.len - 1; slong len = arg.len, leninv = arg.leninv; fmpz * t = arg.t; const fmpz * h = arg.h; const fmpz * poly = arg.poly; const fmpz * polyinv = arg.polyinv; fmpz_mod_poly_struct * res = arg.res; fmpz_mat_struct * C = arg.C; const fmpz_mod_ctx_struct * ctx = arg.ctx; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif j = *arg.j; *arg.j = j + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (j >= arg.len2) return; _fmpz_vec_set(res[j].coeffs, C->rows[(j + 1)*k - 1], n); if (n == 1) /* special case, constant polynomials */ { for (i = 2; i <= k; i++) { fmpz_mod_mul(t + 0, res[j].coeffs + 0, h + 0, ctx); fmpz_mod_add(res[j].coeffs + 0, t + 0, C->rows[(j + 1)*k - i] + 0, ctx); } } else { for (i = 2; i <= k; i++) { _fmpz_mod_poly_mulmod_preinv(t, res[j].coeffs, n, h, n, poly, len, polyinv, leninv, ctx); _fmpz_mod_poly_add(res[j].coeffs, t, n, C->rows[(j + 1)*k - i], n, ctx); } } } } void _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong lenpolys, slong l, const fmpz * g, slong glen, const fmpz * poly, slong len, const fmpz * polyinv, slong leninv, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads) { fmpz_mod_mat_t A, B, C; slong i, j, n, m, k, len2 = l, len1, shared_j = 0; fmpz * h; compose_vec_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif n = len - 1; m = n_sqrt(n*len2) + 1; h = _fmpz_vec_init(n); k = len/m + 1; fmpz_mod_mat_init(A, m, n, ctx); fmpz_mod_mat_init(B, k*len2, m, ctx); fmpz_mod_mat_init(C, k*len2, n, ctx); /* Set rows of B to the segments of polys */ for (j = 0; j < len2; j++) { len1 = polys[j].length; for (i = 0; i < len1 / m; i++) _fmpz_vec_set(B->rows[i + j*k], polys[j].coeffs + i*m, m); _fmpz_vec_set(B->rows[i + j*k], polys[j].coeffs + i*m, len1 % m); } /* Set rows of A to powers of last element of polys */ _fmpz_mod_poly_powers_mod_preinv_threaded_pool(A->rows, g, glen, m, poly, len, polyinv, leninv, ctx, threads, num_threads); _fmpz_mod_mat_mul_classical_threaded_pool_op(C, NULL, B, A, 0, threads, num_threads, ctx); /* Evaluate block composition using the Horner scheme */ if (n == 1) { fmpz_mod_mul(h + 0, A->rows[m - 1] + 0, A->rows[1] + 0, ctx); } else { _fmpz_mod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly, len, polyinv, leninv, ctx); } args = (compose_vec_arg_t *) flint_malloc(sizeof(compose_vec_arg_t)*(num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].res = res; args[i].C = C; args[i].h = h; args[i].k = k; args[i].m = m; args[i].j = &shared_j; args[i].poly = poly; args[i].t = _fmpz_vec_init(len); args[i].len = len; args[i].polyinv = polyinv; args[i].leninv = leninv; args[i].ctx = ctx; args[i].len2 = len2; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif } #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif for (i = 0; i < num_threads; i++) { thread_pool_wake(global_thread_pool, threads[i], 0, _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_worker, &args[i]); } _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) { thread_pool_wait(global_thread_pool, threads[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif for (i = 0; i < num_threads + 1; i++) _fmpz_vec_clear(args[i].t, len); flint_free(args); _fmpz_vec_clear(h, n); fmpz_mod_mat_clear(A, ctx); fmpz_mod_mat_clear(B, ctx); fmpz_mod_mat_clear(C, ctx); } void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads) { slong len2 = poly->length; slong i; if (n == 0) return; if (len2 == 1) { for (i = 0; i < n; i++) fmpz_mod_poly_zero(res + i, ctx); } if (len2 == 2) { for (i = 0; i < n; i++) fmpz_mod_poly_set(res + i, polys + i, ctx); return; } for (i = 0; i < n; i++) { fmpz_mod_poly_fit_length(res + i, len2 - 1, ctx); _fmpz_mod_poly_set_length(res + i, len2 - 1); } _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(res, polys, len1, n, g->coeffs, g->length, poly->coeffs, len2, polyinv->coeffs, polyinv->length, ctx, threads, num_threads); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); } void fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded(fmpz_mod_poly_struct * res, const fmpz_mod_poly_struct * polys, slong len1, slong n, const fmpz_mod_poly_t g, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_ctx_t ctx) { slong i, len2 = poly->length; thread_pool_handle * threads; slong num_threads; for (i = 0; i < len1; i++) { if (polys[i].length >= len2) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded): " "The degree of the first polynomial must be smaller than that of the modulus\n"); } } if (n > len1) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded): " "n is larger than the length of polys\n"); } if (n == 0) return; if (len2 == 1) { for (i = 0; i < n; i++) fmpz_mod_poly_zero(res + i, ctx); return; } if (len2 == 2) { for (i = 0; i < n; i++) fmpz_mod_poly_set(res + i, polys + i, ctx); return; } for (i = 0; i < n; i++) { fmpz_mod_poly_fit_length(res + i, len2 - 1, ctx); _fmpz_mod_poly_set_length(res + i, len2 - 1); } num_threads = flint_request_threads(&threads, flint_get_num_threads()); _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(res, polys, len1, n, g->coeffs, g->length, poly->coeffs, len2, polyinv->coeffs, polyinv->length, ctx, threads, num_threads); flint_give_back_threads(threads, num_threads); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); } flint-3.1.3/src/fmpz_mod_poly/compose_mod_horner.c000066400000000000000000000061051461254215100223270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_compose_mod_horner(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_mod_ctx_t ctx) { slong i, len; fmpz * t; if (lenh == 1) return; if (lenf == 1) { fmpz_set(res, f); return; } if (lenh == 2) { _fmpz_mod_poly_evaluate_fmpz(res, f, lenf, g, ctx); return; } len = lenh - 1; i = lenf - 1; t = _fmpz_vec_init(2 * lenh - 3); _fmpz_mod_poly_scalar_mul_fmpz(res, g, len, f + i, ctx); i--; if (i >= 0) fmpz_mod_add(res, res, f + i, ctx); while (i > 0) { i--; _fmpz_mod_poly_mulmod(t, res, len, g, len, h, lenh, ctx); _fmpz_mod_poly_add(res, t, len, f + i, 1, ctx); } _fmpz_vec_clear(t, 2 * lenh - 3); } void fmpz_mod_poly_compose_mod_horner(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t poly3, const fmpz_mod_ctx_t ctx) { fmpz_t inv3; slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); fmpz * ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_compose_mod_horner). Division by zero \n"); } if (len1 == 0 || len3 == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (len1 == 1) { fmpz_mod_poly_set(res, poly1, ctx); return; } if (res == poly3 || res == poly1) { fmpz_mod_poly_t tmp; fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_compose_mod_horner(tmp, poly1, poly2, poly3, ctx); fmpz_mod_poly_swap(tmp, res, ctx); fmpz_mod_poly_clear(tmp, ctx); return; } ptr2 = _fmpz_vec_init(vec_len); if (len2 <= len3 - 1) { _fmpz_vec_set(ptr2, poly2->coeffs, len2); _fmpz_vec_zero(ptr2 + len2, vec_len - len2); } else { fmpz_init(inv3); fmpz_invmod(inv3, poly3->coeffs + len, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); fmpz_clear(inv3); } fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_compose_mod_horner(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, vec_len); } flint-3.1.3/src/fmpz_mod_poly/deflate.c000066400000000000000000000021051461254215100200460ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_deflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong deflation, const fmpz_mod_ctx_t ctx) { slong res_length, i; if (deflation == 0) flint_throw(FLINT_DIVZERO, "fmpz_mod_poly_deflate"); if (input->length <= 1 || deflation == 1) { fmpz_mod_poly_set(result, input, ctx); return; } res_length = (input->length - 1) / deflation + 1; fmpz_mod_poly_fit_length(result, res_length, ctx); for (i = 0; i < res_length; i++) fmpz_set(result->coeffs + i, input->coeffs + (i * deflation)); _fmpz_mod_poly_set_length(result, res_length); } flint-3.1.3/src/fmpz_mod_poly/deflation.c000066400000000000000000000011071461254215100204100ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" ulong fmpz_mod_poly_deflation(const fmpz_mod_poly_t input, const fmpz_mod_ctx_t ctx) { return _fmpz_poly_deflation(input->coeffs, input->length); } flint-3.1.3/src/fmpz_mod_poly/derivative.c000066400000000000000000000026201461254215100206060ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_derivative(fmpz *res, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx) { slong j, k = 1; for (j = 1; j < len; j++) { if (k == 0) fmpz_zero(res + (j - 1)); else if (k == 1) fmpz_set(res + (j - 1), poly + j); else fmpz_mod_mul_ui(res + (j - 1), poly + j, k, ctx); if (fmpz_equal_ui(fmpz_mod_ctx_modulus(ctx), ++k)) k = 0; } } void fmpz_mod_poly_derivative(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { const slong len = poly->length; if (len < 2) { fmpz_mod_poly_zero(res, ctx); } else { fmpz_mod_poly_fit_length(res, len - 1, ctx); _fmpz_mod_poly_derivative(res->coeffs, poly->coeffs, len, ctx); _fmpz_mod_poly_set_length(res, len - 1); _fmpz_mod_poly_normalise(res); } } flint-3.1.3/src/fmpz_mod_poly/discriminant.c000066400000000000000000000030201461254215100211230ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx) { fmpz *der = _fmpz_vec_init(len - 1); slong dlen = len - 1, exp; fmpz_t pow; _fmpz_mod_poly_derivative(der, poly, len, ctx); FMPZ_VEC_NORM(der, dlen); if (dlen == 0) { fmpz_zero(d); } else { fmpz_init(pow); _fmpz_mod_poly_resultant(d, poly, len, der, dlen, ctx); exp = len - dlen - 2; if (exp >= 0) fmpz_mod_pow_ui(pow, poly + len - 1, exp, ctx); else fmpz_mod_inv(pow, poly + len - 1, ctx); fmpz_mod_mul(d, d, pow, ctx); if ((len & 3) == 0 || (len & 3) == 3) /* degree is not 0, 1 mod 4 */ fmpz_mod_neg(d, d, ctx); fmpz_clear(pow); } _fmpz_vec_clear(der, len - 1); } void fmpz_mod_poly_discriminant(fmpz_t d, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { const slong len = f->length; if (len <= 1) fmpz_zero(d); else _fmpz_mod_poly_discriminant(d, f->coeffs, len, ctx); } flint-3.1.3/src/fmpz_mod_poly/div.c000066400000000000000000000042771461254215100172400ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr_poly.h" void _fmpz_mod_poly_div(fmpz * Q, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); if (lenB <= 15 || lenA - lenB <= 15) GR_MUST_SUCCEED(_gr_poly_div_basecase_preinv1(Q, A, lenA, B, lenB, invB, gr_ctx)); else GR_MUST_SUCCEED(_gr_poly_div_newton(Q, A, lenA, B, lenB, gr_ctx)); /* todo: pass inverse */ } void fmpz_mod_poly_div(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; fmpz *q; fmpz_t invB; if (lenB == 0) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) { fmpz_mod_poly_set(Q, A, ctx); return; } else { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_div_basecase). Division by zero.\n"); } } if (lenA < lenB) { fmpz_mod_poly_zero(Q, ctx); return; } fmpz_init(invB); fmpz_invmod(invB, B->coeffs + (lenB - 1), fmpz_mod_ctx_modulus(ctx)); if (Q == A || Q == B) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } _fmpz_mod_poly_div(q, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } fmpz_clear(invB); } flint-3.1.3/src/fmpz_mod_poly/div_newton_n_preinv.c000066400000000000000000000047701461254215100225300ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_div_newton_n_preinv (fmpz* Q, const fmpz* A, slong lenA, const fmpz* B, slong lenB, const fmpz* Binv, slong lenBinv, const fmpz_mod_ctx_t ctx) { const slong lenQ = lenA - lenB + 1; fmpz * Arev; Arev = _fmpz_vec_init(lenQ); _fmpz_poly_reverse(Arev, A + (lenA - lenQ), lenQ, lenQ); _fmpz_mod_poly_mullow(Q, Arev, lenQ, Binv, FLINT_MIN(lenQ, lenBinv), lenQ, ctx); _fmpz_poly_reverse(Q, Q, lenQ, lenQ); _fmpz_vec_clear(Arev, lenQ); } void fmpz_mod_poly_div_newton_n_preinv(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1, lenBinv = Binv->length; fmpz *q; if (lenB == 0) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) { fmpz_mod_poly_set(Q, A, ctx); return; } else { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_div_newton_n_preinv). Division by zero.\n"); } } if (lenA < lenB) { fmpz_mod_poly_zero(Q, ctx); return; } if (lenA > 2 * lenB - 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_div_newton_n_preinv).\n"); } if (Q == A || Q == B || Q == Binv) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } _fmpz_mod_poly_div_newton_n_preinv (q, A->coeffs, lenA, B->coeffs, lenB, Binv->coeffs, lenBinv, ctx); if (Q == A || Q == B || Q == Binv) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } } flint-3.1.3/src/fmpz_mod_poly/div_series.c000066400000000000000000000062241461254215100206040ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_poly.h" void _fmpz_mod_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n, const fmpz_mod_ctx_t ctx) { fmpz_t u, d; fmpz_init(d); fmpz_init(u); if (!fmpz_is_one(B + 0)) { fmpz_gcdinv(d, u, B + 0, fmpz_mod_ctx_modulus(ctx)); if (!fmpz_is_one(d)) /* check for invertibility */ flint_throw(FLINT_ERROR, "Impossible inverse in %s\n", __func__); } else fmpz_one(u); Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (Blen == 1) { if (fmpz_is_one(B + 0)) _fmpz_vec_set(Q, A, Alen); else _fmpz_mod_poly_scalar_mul_fmpz(Q, A, Alen, u, ctx); _fmpz_vec_zero(Q + Alen, n - Alen); } else if (n < 32 || Blen < 20) { slong i, j; if (fmpz_is_one(B + 0)) fmpz_set(Q + 0, A + 0); else { fmpz_mod_mul(Q + 0, u, A + 0, ctx); } for (i = 1; i < n; i++) { fmpz_mul(Q + i, B + 1, Q + i - 1); for (j = 2; j < FLINT_MIN(i + 1, Blen); j++) fmpz_addmul(Q + i, B + j, Q + i - j); if (i < Alen) fmpz_sub(Q + i, A + i, Q + i); else fmpz_neg(Q + i, Q + i); if (!fmpz_is_one(B + 0)) fmpz_mul(Q + i, Q + i, u); fmpz_mod_set_fmpz(Q + i, Q + i, ctx); } } else { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_poly_div_series(Q, A, Alen, B, Blen, n, gr_ctx)); } fmpz_clear(d); fmpz_clear(u); } void fmpz_mod_poly_div_series(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, slong n, const fmpz_mod_ctx_t ctx) { slong Alen = FLINT_MIN(A->length, n); slong Blen = FLINT_MIN(B->length, n); if (Blen == 0) flint_throw(FLINT_ERROR, "Division by zero in %s\n", __func__); if (Alen == 0) { fmpz_mod_poly_zero(Q, ctx); return; } if (Q == A || Q == B) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, n, ctx); _fmpz_mod_poly_div_series(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, ctx); fmpz_mod_poly_swap(Q, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { fmpz_mod_poly_fit_length(Q, n, ctx); _fmpz_mod_poly_div_series(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, ctx); } _fmpz_mod_poly_set_length(Q, n); _fmpz_mod_poly_normalise(Q); } flint-3.1.3/src/fmpz_mod_poly/divides.c000066400000000000000000000064061461254215100201010ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" int _fmpz_mod_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) { fmpz * R; fmpz_t invB; slong i, lenQ = lenA - lenB + 1; int res = 1; const fmpz * p = fmpz_mod_ctx_modulus(ctx); if (lenA < 40 && lenB < 20) return _fmpz_mod_poly_divides_classical(Q, A, lenA, B, lenB, ctx); R = _fmpz_vec_init(lenB - 1); fmpz_init(invB); fmpz_invmod(invB, B + lenB - 1, p); if (lenA < 2*lenB - 1) { slong offset = 0; fmpz * P; P = (fmpz *) _fmpz_vec_init(2*lenQ - 1); _fmpz_vec_zero(R, lenB - 1); _fmpz_mod_poly_div(Q, A, lenA, B, lenB, invB, ctx); while (offset < lenB - 1) { if (offset + 2*lenQ - 1 < lenB) { _fmpz_mod_poly_mul(P, B + offset, lenQ, Q, lenQ, ctx); _fmpz_mod_poly_add(R + offset, R + offset, 2*lenQ - 1, P, 2*lenQ - 1, ctx); } else { _fmpz_mod_poly_mullow(P, Q, lenQ, B + offset, lenQ, lenB - offset - 1, ctx); _fmpz_mod_poly_add(R + offset, R + offset, lenB - offset - 1, P, lenB - offset - 1, ctx); } for (i = 0; i < FLINT_MIN(lenQ, lenB - offset - 1); i++) { if (!fmpz_equal(R + offset + i, A + offset + i)) { res = 0; break; } } offset += lenQ; } _fmpz_vec_clear(P, 2*lenQ - 1); } else { _fmpz_mod_poly_divrem(Q, R, A, lenA, B, lenB, invB, ctx); for (i = 0; i < lenB - 1; i++) { if (!fmpz_is_zero(R + i)) { res = 0; break; } } } fmpz_clear(invB); _fmpz_vec_clear(R, lenB - 1); if (res == 0) _fmpz_vec_zero(Q, lenQ); return res; } int fmpz_mod_poly_divides(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t tQ; fmpz * q; slong lenA, lenB; int res; lenA = A->length; lenB = B->length; if (lenB == 0 || lenA < lenB) { fmpz_mod_poly_zero(Q, ctx); return lenA == 0; } if (Q == A || Q == B) { fmpz_mod_poly_init2(tQ, lenA - lenB + 1, ctx); q = tQ->coeffs; } else { fmpz_mod_poly_fit_length(Q, lenA - lenB + 1, ctx); q = Q->coeffs; } res = _fmpz_mod_poly_divides(q, A->coeffs, lenA, B->coeffs, lenB, ctx); if (Q == A || Q == B) { fmpz_mod_poly_swap(tQ, Q, ctx); fmpz_mod_poly_clear(tQ, ctx); } _fmpz_mod_poly_set_length(Q, lenA - lenB + 1); _fmpz_mod_poly_normalise(Q); return res; } flint-3.1.3/src/fmpz_mod_poly/divides_classical.c000066400000000000000000000056541461254215100221230ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" /* check if (p, n) = mullow(poly1, len1, poly2, n, n) where len1 > 0, n >= 0 */ static int _fmpz_mod_poly_mullow_classical_check(const fmpz * p, const fmpz * poly1, slong len1, const fmpz * poly2, slong n, const fmpz_mod_ctx_t mod) { slong i, n1; fmpz_t c; int res = 1; len1 = FLINT_MIN(len1, n); if (n == 0) return 1; fmpz_init(c); if (n == 1) { fmpz_mod_mul(c, poly1 + 0, poly2 + 0, mod); res = fmpz_equal(p + 0, c); } else { for (i = 0; i < n; i++) { n1 = FLINT_MIN(len1 - 1, i); _fmpz_mod_vec_dot_rev(c, poly1, poly2 + i - n1, n1 + 1, mod); if (!fmpz_equal(p + i, c)) { res = 0; break; } } } fmpz_clear(c); return res; } int _fmpz_mod_poly_divides_classical(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx) { slong lenQ = lenA - lenB + 1; int res; fmpz_t invB; fmpz_init(invB); fmpz_invmod(invB, B + lenB - 1, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_div(Q, A, lenA, B, lenB, invB, ctx); /* check coefficients of product one at a time */ res = _fmpz_mod_poly_mullow_classical_check(A, Q, lenQ, B, lenB - 1, ctx); if (!res) _fmpz_vec_zero(Q, lenQ); fmpz_clear(invB); return res; } int fmpz_mod_poly_divides_classical(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t tQ; fmpz * q; slong lenA, lenB; int res; lenA = A->length; lenB = B->length; if (lenB == 0 || lenA < lenB) { fmpz_mod_poly_zero(Q, ctx); return lenA == 0; } if (Q == A || Q == B) { fmpz_mod_poly_init2(tQ, lenA - lenB + 1, ctx); q = tQ->coeffs; } else { fmpz_mod_poly_fit_length(Q, lenA - lenB + 1, ctx); q = Q->coeffs; } res = _fmpz_mod_poly_divides_classical(q, A->coeffs, lenA, B->coeffs, lenB, ctx); if (Q == A || Q == B) { fmpz_mod_poly_swap(tQ, Q, ctx); fmpz_mod_poly_clear(tQ, ctx); } _fmpz_mod_poly_set_length(Q, lenA - lenB + 1); _fmpz_mod_poly_normalise(Q); return res; } flint-3.1.3/src/fmpz_mod_poly/divrem.c000066400000000000000000000056551461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr_poly.h" void _fmpz_mod_poly_divrem(fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { if (lenB <= 30 || lenA - lenB <= 10) { _fmpz_mod_poly_divrem_basecase(Q, R, A, lenA, B, lenB, invB, ctx); } else { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, gr_ctx)); } } void fmpz_mod_poly_divrem(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length; const slong lenB = B->length; const slong lenQ = lenA - lenB + 1; fmpz *q, *r; fmpz_t invB; if (lenB == 0) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) { fmpz_mod_poly_set(Q, A, ctx); fmpz_mod_poly_zero(R, ctx); return; } else { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_divrem). Division by zero.\n"); } } if (lenA < lenB) { fmpz_mod_poly_set(R, A, ctx); fmpz_mod_poly_zero(Q, ctx); return; } if (B->length < 8) { fmpz_mod_poly_divrem_basecase(Q, R, A, B, ctx); return; } fmpz_init(invB); fmpz_invmod(invB, fmpz_mod_poly_lead(B, ctx), fmpz_mod_ctx_modulus(ctx)); if (Q == A || Q == B) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == A || R == B) { r = _fmpz_vec_init(lenB - 1); } else { fmpz_mod_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } _fmpz_mod_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } if (R == A || R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenB - 1; R->length = lenB - 1; } _fmpz_mod_poly_set_length(R, lenB - 1); _fmpz_mod_poly_normalise(R); fmpz_clear(invB); } flint-3.1.3/src/fmpz_mod_poly/divrem_basecase.c000066400000000000000000000063701461254215100215660ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_divrem_basecase(fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { slong iQ, iR; fmpz * W; TMP_INIT; TMP_START; if (R != A) { /* cannot use R as it might not have enough space */ FMPZ_VEC_TMP_INIT(W, lenA); _fmpz_vec_set(W, A, lenA); } else { W = R; } for (iQ = lenA - lenB, iR = lenA - 1; iQ >= 0; iQ--, iR--) { if (fmpz_is_zero(W + iR)) { fmpz_zero(Q + iQ); } else { fmpz_mul(Q + iQ, W + iR, invB); fmpz_mod_set_fmpz(Q + iQ, Q + iQ, ctx); _fmpz_vec_scalar_submul_fmpz(W + iQ, B, lenB, Q + iQ); } if (iQ > 0) fmpz_mod_set_fmpz(W + iR - 1, W + iR - 1, ctx); } _fmpz_mod_vec_set_fmpz_vec(W, W, lenB - 1, ctx); if (R != A) { _fmpz_vec_swap(R, W, lenB - 1); FMPZ_VEC_TMP_CLEAR(W, lenA); } TMP_END; } void fmpz_mod_poly_divrem_basecase(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; fmpz *q, *r; fmpz_t invB; if (lenB == 0) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) { fmpz_mod_poly_set(Q, A, ctx); fmpz_mod_poly_zero(R, ctx); return; } else { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_divrem_basecase). Division by zero.\n"); } } if (lenA < lenB) { fmpz_mod_poly_set(R, A, ctx); fmpz_mod_poly_zero(Q, ctx); return; } fmpz_init(invB); fmpz_invmod(invB, B->coeffs + (lenB - 1), fmpz_mod_ctx_modulus(ctx)); if (Q == A || Q == B) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { r = _fmpz_vec_init(lenB - 1); } else { fmpz_mod_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } _fmpz_mod_poly_divrem_basecase(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } if (R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenB - 1; R->length = lenB - 1; } else { _fmpz_mod_poly_set_length(R, lenB - 1); } _fmpz_mod_poly_normalise(R); fmpz_clear(invB); } flint-3.1.3/src/fmpz_mod_poly/divrem_f.c000066400000000000000000000051731461254215100202450ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_divrem_f(fmpz_t f, fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx) { fmpz_t invB; fmpz_init(invB); fmpz_gcdinv(f, invB, B + lenB - 1, fmpz_mod_ctx_modulus(ctx)); if (fmpz_is_one(f)) { _fmpz_mod_poly_divrem(Q, R, A, lenA, B, lenB, invB, ctx); } fmpz_clear(invB); } void fmpz_mod_poly_divrem_f(fmpz_t f, fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length; const slong lenB = B->length; const slong lenQ = lenA - lenB + 1; fmpz *q, *r; fmpz_t invB; fmpz_init(invB); fmpz_gcdinv(f, invB, fmpz_mod_poly_lead(B, ctx), fmpz_mod_ctx_modulus(ctx)); if (!fmpz_is_one(f)) { fmpz_clear(invB); return; } if (lenB == 0) { fmpz_clear(invB); /* flint_throw */ flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_divrem_f). Division by zero.\n"); } if (lenA < lenB) { fmpz_mod_poly_set(R, A, ctx); fmpz_mod_poly_zero(Q, ctx); fmpz_clear(invB); return; } if (Q == A || Q == B) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == A || R == B) { r = _fmpz_vec_init(lenA); } else { fmpz_mod_poly_fit_length(R, lenA, ctx); r = R->coeffs; } _fmpz_mod_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } if (R == A || R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenA; R->length = lenA; } _fmpz_mod_poly_set_length(R, lenB - 1); _fmpz_mod_poly_normalise(R); fmpz_clear(invB); } flint-3.1.3/src/fmpz_mod_poly/divrem_newton_n_preinv.c000066400000000000000000000061651461254215100232340ustar00rootroot00000000000000/* Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_divrem_newton_n_preinv (fmpz* Q, fmpz* R, const fmpz* A, slong lenA, const fmpz* B, slong lenB, const fmpz* Binv, slong lenBinv, const fmpz_mod_ctx_t ctx) { const slong lenQ = lenA - lenB + 1; _fmpz_mod_poly_div_newton_n_preinv(Q, A, lenA, B, lenB, Binv, lenBinv, ctx); if (lenB > 1) { if (lenQ >= lenB - 1) _fmpz_mod_poly_mullow(R, Q, lenQ, B, lenB - 1, lenB - 1, ctx); else _fmpz_mod_poly_mullow(R, B, lenB - 1, Q, lenQ, lenB - 1, ctx); _fmpz_mod_vec_sub(R, A, R, lenB - 1, ctx); } } void fmpz_mod_poly_divrem_newton_n_preinv(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length, lenBinv= Binv->length, lenQ = lenA - lenB + 1; fmpz* q, * r; if (lenB == 0) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) { fmpz_mod_poly_set(Q, A, ctx); fmpz_mod_poly_zero(R, ctx); return; } else { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_divrem_newton_n_preinv): Division by zero.\n"); } } if (lenA < lenB) { fmpz_mod_poly_set(R, A, ctx); fmpz_mod_poly_zero(Q, ctx); return; } if (lenA > 2 * lenB - 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_divrem_newton_n_preinv).\n"); } if (Q == A || Q == B || Q == Binv) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == A || R == B || R == Binv) { r = _fmpz_vec_init(lenB - 1); } else { fmpz_mod_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } _fmpz_mod_poly_divrem_newton_n_preinv (q, r, A->coeffs, lenA, B->coeffs, lenB, Binv->coeffs, lenBinv, ctx); if (Q == A || Q == B || Q == Binv) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } if (R == A || R == B || R == Binv) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenB - 1; R->length = lenB - 1; } else { _fmpz_mod_poly_set_length(R, lenB - 1); } _fmpz_mod_poly_normalise(R); } flint-3.1.3/src/fmpz_mod_poly/evaluate_fmpz.c000066400000000000000000000027741461254215100213200ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_poly.h" void _fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz *poly, slong len, const fmpz_t a, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); if (fmpz_sgn(a) >= 0 && fmpz_cmp(a, fmpz_mod_ctx_modulus(ctx)) < 0) { GR_MUST_SUCCEED(_gr_poly_evaluate_horner(res, poly, len, a, gr_ctx)); } else { fmpz_t t; fmpz_init(t); fmpz_mod_set_fmpz(t, a, ctx); GR_MUST_SUCCEED(_gr_poly_evaluate_horner(res, poly, len, t, gr_ctx)); fmpz_clear(t); } } void fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz_mod_poly_t poly, const fmpz_t a, const fmpz_mod_ctx_t ctx) { if (res == a) { fmpz_t t; fmpz_init(t); _fmpz_mod_poly_evaluate_fmpz(t, poly->coeffs, poly->length, a, ctx); fmpz_swap(res, t); fmpz_clear(t); } else { _fmpz_mod_poly_evaluate_fmpz(res, poly->coeffs, poly->length, a, ctx); } } flint-3.1.3/src/fmpz_mod_poly/evaluate_fmpz_vec.c000066400000000000000000000115551461254215100221520ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Fredrik Johansson Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr_poly.h" void _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp(fmpz * vs, const fmpz * poly, slong plen, fmpz_poly_struct * const * tree, slong len, const fmpz_mod_ctx_t ctx) { slong height, i, j, pow, left; slong tree_height; fmpz_t temp, inv; fmpz * t, * u, * pb, * pc, * swap; fmpz_poly_struct * pa; fmpz_init(temp); fmpz_init(inv); /* avoid worrying about some degenerate cases */ if (len < 2 || plen < 2) { if (len == 1) { fmpz_mod_neg(temp, tree[0]->coeffs, ctx); _fmpz_mod_poly_evaluate_fmpz(vs, poly, plen, temp, ctx); } else if (len != 0 && plen == 0) _fmpz_vec_zero(vs, len); else if (len != 0 && plen == 1) for (i = 0; i < len; i++) fmpz_set(vs + i, poly); fmpz_clear(temp); return; } t = _fmpz_vec_init(2*len); u = _fmpz_vec_init(2*len); left = len; /* Initial reduction. We allow the polynomial to be larger or smaller than the number of points. */ height = FLINT_BIT_COUNT(plen - 1) - 1; tree_height = FLINT_CLOG2(len); while (height >= tree_height) height--; pow = WORD(1) << height; for (i = j = 0; i < len; i += pow, j++) { pa = tree[height] + j; fmpz_mod_inv(inv, pa->coeffs + pa->length - 1, ctx); _fmpz_mod_poly_rem(t + i, poly, plen, pa->coeffs, pa->length, inv, ctx); } for (i = height - 1; i >= 0; i--) { pow = WORD(1) << i; left = len; pa = tree[i]; pb = t; pc = u; left = len; while (left >= 2 * pow) { fmpz_mod_inv(inv, pa->coeffs + pa->length - 1, ctx); _fmpz_mod_poly_rem(pc, pb, 2 * pow, pa->coeffs, pa->length, inv, ctx); pa++; fmpz_mod_inv(inv, pa->coeffs + pa->length - 1, ctx); _fmpz_mod_poly_rem(pc + pow, pb, 2 * pow, pa->coeffs, pa->length, inv, ctx); pa++; pb += 2 * pow; pc += 2 * pow; left -= 2 * pow; } if (left > pow) { fmpz_mod_inv(inv, pa->coeffs + pa->length - 1, ctx); _fmpz_mod_poly_rem(pc, pb, left, pa->coeffs, pa->length, inv, ctx); pa ++; fmpz_mod_inv(inv, pa->coeffs + pa->length - 1, ctx); _fmpz_mod_poly_rem(pc + pow, pb, left, pa->coeffs, pa->length, inv, ctx); } else if (left > 0) _fmpz_vec_set(pc, pb, left); swap = t; t = u; u = swap; } fmpz_clear(temp); fmpz_clear(inv); _fmpz_vec_set(vs, t, len); _fmpz_vec_clear(t, 2*len); _fmpz_vec_clear(u, 2*len); } void _fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz * poly, slong plen, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_poly_evaluate_vec_fast(ys, poly, plen, xs, n, gr_ctx)); } void fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) { _fmpz_mod_poly_evaluate_fmpz_vec_fast(ys, poly->coeffs, poly->length, xs, n, ctx); } void _fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < n; i++) _fmpz_mod_poly_evaluate_fmpz(ys + i, coeffs, len, xs + i, ctx); } void fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) { _fmpz_mod_poly_evaluate_fmpz_vec_iter(ys, poly->coeffs, poly->length, xs, n, ctx); } void _fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) { if (len < FMPZ_MOD_POLY_EVALUATE_FMPZ_VEC) _fmpz_mod_poly_evaluate_fmpz_vec_iter(ys, coeffs, len, xs, n, ctx); else _fmpz_mod_poly_evaluate_fmpz_vec_fast(ys, coeffs, len, xs, n, ctx); } void fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) { _fmpz_mod_poly_evaluate_fmpz_vec(ys, poly->coeffs, poly->length, xs, n, ctx); } flint-3.1.3/src/fmpz_mod_poly/find_distinct_nonzero_roots.c000066400000000000000000000153661461254215100243000ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" /* split f assuming that f has degree(f) distinct nonzero roots in Fp */ void _fmpz_mod_poly_split_rabin( fmpz_mod_poly_t a, fmpz_mod_poly_t b, const fmpz_mod_poly_t f, const fmpz_t halfp, /* floor((p-1)/2) */ fmpz_mod_poly_t t, fmpz_mod_poly_t t2, flint_rand_t randstate, const fmpz_mod_ctx_t ctx) { FLINT_ASSERT(fmpz_mod_poly_degree(f, ctx) > 1); fmpz_mod_poly_fit_length(a, 2, ctx); fmpz_mod_poly_fit_length(b, 2, ctx); fmpz_mod_poly_fit_length(t, 3, ctx); if (fmpz_mod_poly_degree(f, ctx) == 2) { fmpz * A, * T; const fmpz * B; B = f->coeffs + 0; A = t->coeffs + 1; T = t->coeffs + 2; if (!fmpz_is_zero(halfp)) { fmpz_mod_mul(A, f->coeffs + 1, halfp, ctx); fmpz_mod_neg(A, A, ctx); if (!fmpz_is_one(f->coeffs + 2)) { fmpz_mod_inv(T, f->coeffs + 2, ctx); fmpz_mod_mul(A, A, T, ctx); fmpz_mod_mul(t->coeffs + 0, B, T, ctx); B = t->coeffs + 0; } fmpz_mod_mul(T, A, A, ctx); fmpz_mod_sub(T, T, B, ctx); if (!fmpz_sqrtmod(b->coeffs + 0, T, fmpz_mod_ctx_modulus(ctx))) flint_throw(FLINT_ERROR, "_fmpz_mod_poly_split_rabin: f is irreducible"); fmpz_mod_add(a->coeffs + 0, A, b->coeffs + 0, ctx); fmpz_mod_sub(b->coeffs + 0, A, b->coeffs + 0, ctx); } else { fmpz_one(a->coeffs + 0); fmpz_zero(b->coeffs + 0); } fmpz_one(a->coeffs + 1); fmpz_one(b->coeffs + 1); _fmpz_mod_poly_set_length(a, 2); _fmpz_mod_poly_set_length(b, 2); #if FLINT_WANT_ASSERT fmpz_mod_add(T, a->coeffs + 0, b->coeffs + 0, ctx); fmpz_mod_mul(T, T, f->coeffs + 2, ctx); FLINT_ASSERT(fmpz_equal(T, f->coeffs + 1)); fmpz_mod_mul(T, a->coeffs + 0, b->coeffs + 0, ctx); fmpz_mod_mul(T, T, f->coeffs + 2, ctx); FLINT_ASSERT(fmpz_equal(T, f->coeffs + 0)); #endif return; } fmpz_mod_poly_reverse(t, f, f->length, ctx); fmpz_mod_poly_inv_series(t2, t, t->length, ctx); try_again: fmpz_randm(a->coeffs, randstate, fmpz_mod_ctx_modulus(ctx)); fmpz_mod_poly_powmod_linear_fmpz_preinv(t, a->coeffs, halfp, f, t2, ctx); fmpz_mod_poly_sub_si(t, t, 1, ctx); fmpz_mod_poly_gcd(a, t, f, ctx); if (a->length <= 1 || a->length >= f->length) goto try_again; fmpz_mod_poly_divrem(b, t, f, a, ctx); FLINT_ASSERT(fmpz_mod_poly_is_zero(t, ctx)); /* ensure deg a >= deg b */ if (a->length < b->length) fmpz_mod_poly_swap(a, b, ctx); return; } /* If P has deg(P) distinct nonzero roots of P, fill them in and return 1. Otherwise return 0. Function is undefined for zero P. The modulus of P is assumed to be prime. */ int fmpz_mod_poly_find_distinct_nonzero_roots( fmpz * roots, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx) { fmpz_t a0, a1; int success; slong i, roots_idx, sp; fmpz_t halfp; fmpz_mod_poly_struct * a , * b; fmpz_mod_poly_t f, t, t2; fmpz_mod_poly_struct stack[FLINT_BITS + 1]; flint_rand_t randstate; slong d = fmpz_mod_poly_degree(P, ctx); FLINT_ASSERT(d >= 0); fmpz_init(a0); fmpz_init(a1); fmpz_init(halfp); if (d < 2) { if (d == 1) { fmpz_mod_poly_get_coeff_fmpz(a0, P, 0, ctx); fmpz_mod_poly_get_coeff_fmpz(a1, P, 1, ctx); if (fmpz_is_zero(a0)) { success = 0; goto cleanup1; } fmpz_mod_inv(a1, a1, ctx); fmpz_mod_neg(a1, a1, ctx); fmpz_mod_mul(roots + 0, a0, a1, ctx); } success = 1; goto cleanup1; } if (fmpz_cmp_ui(fmpz_mod_ctx_modulus(ctx), 2) <= 0) { success = 0; goto cleanup1; } if (fmpz_is_zero(P->coeffs + 0)) { success = 0; goto cleanup1; } flint_randinit(randstate); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(t2, ctx); fmpz_mod_poly_init(f, ctx); for (i = 0; i <= FLINT_BITS; i++) fmpz_mod_poly_init(stack + i, ctx); roots_idx = 0; fmpz_mod_poly_make_monic(f, P, ctx); fmpz_mod_poly_reverse(t, f, f->length, ctx); fmpz_mod_poly_inv_series(t2, t, f->length, ctx); a = stack + 0; fmpz_sub_ui(halfp, fmpz_mod_ctx_modulus(ctx), 1); fmpz_divexact_ui(halfp, halfp, 2); fmpz_mod_poly_powmod_x_fmpz_preinv(t, halfp, f, t2, ctx); fmpz_mod_poly_sub_si(t, t, 1, ctx); fmpz_mod_poly_gcd(a, t, f, ctx); b = stack + 1; fmpz_mod_poly_add_si(t, t, 2, ctx); fmpz_mod_poly_gcd(b, t, f, ctx); if (fmpz_mod_poly_degree(b, ctx) + fmpz_mod_poly_degree(a, ctx) != d) { success = 0; goto cleanup; } /* deg a >= deg b */ if (fmpz_mod_poly_degree(a, ctx) < fmpz_mod_poly_degree(b, ctx)) { fmpz_mod_poly_swap(a, b, ctx); } sp = fmpz_mod_poly_degree(b, ctx) > 0 ? 2 : 1; while (sp > 0) { FLINT_ASSERT(sp < FLINT_BITS); sp--; fmpz_mod_poly_swap(f, stack + sp, ctx); FLINT_ASSERT(fmpz_mod_poly_degree(f, ctx) > 0); if (fmpz_mod_poly_degree(f, ctx) == 1) { fmpz_mod_poly_get_coeff_fmpz(a0, f, 0, ctx); fmpz_mod_poly_get_coeff_fmpz(a1, f, 1, ctx); FLINT_ASSERT(!fmpz_is_zero(a0)); FLINT_ASSERT(fmpz_is_one(a1)); fmpz_mod_neg(roots + roots_idx, a0, ctx); roots_idx++; } else { _fmpz_mod_poly_split_rabin(stack + sp + 0, stack + sp + 1, f, halfp, t, t2, randstate, ctx); FLINT_ASSERT( FLINT_BIT_COUNT(fmpz_mod_poly_degree(stack + sp + 1, ctx)) <= FLINT_BITS - sp - 1); sp += 2; } } success = 1; cleanup: flint_randclear(randstate); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(t2, ctx); fmpz_mod_poly_clear(f, ctx); for (i = 0; i <= FLINT_BITS; i++) fmpz_mod_poly_clear(stack + i, ctx); FLINT_ASSERT((!success) || roots_idx == d); cleanup1: fmpz_clear(a0); fmpz_clear(a1); fmpz_clear(halfp); return success; } flint-3.1.3/src/fmpz_mod_poly/fit_length.c000066400000000000000000000014031461254215100205650ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" void _fmpz_mod_poly_fit_length(fmpz_mod_poly_t f, slong len) { if (f->alloc < len) { slong alloc = FLINT_MAX(2*f->alloc, len); f->coeffs = FLINT_ARRAY_REALLOC(f->coeffs, alloc, fmpz); flint_mpn_zero((mp_ptr) (f->coeffs + f->alloc), alloc - f->alloc); f->alloc = alloc; } } flint-3.1.3/src/fmpz_mod_poly/frobenius_power.c000066400000000000000000000034531461254215100216610ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" void fmpz_mod_poly_frobenius_power(fmpz_mod_poly_t res, fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_poly_t f, ulong m, const fmpz_mod_ctx_t ctx) { slong i = 0; ulong bit; fmpz_mod_poly_struct * r; fmpz_mod_poly_t tr; if (res == f) { fmpz_mod_poly_init(tr, ctx); r = tr; } else { r = res; } /* res = x^(p^0) = x */ if (m == 0) { fmpz_mod_poly_set_coeff_ui(r, 1, 1, ctx); fmpz_mod_poly_set_coeff_ui(r, 0, 0, ctx); _fmpz_mod_poly_set_length(r, 2); /* This is safe wrt impossible inverses, because any zero divisors in the leading coefficient of f will have been found in the precomp stage. */ if (f->length <= 2) fmpz_mod_poly_rem(r, r, f, ctx); } else { /* first nonzero bit */ while ((m & (WORD(1) << i)) == 0) i++; /* res = f^(p^(2^i)) */ fmpz_mod_poly_set(r, pow->pow + i, ctx); m ^= (WORD(1) << i); while (m != 0) { i++; bit = (WORD(1) << i); if ((bit & m) != 0) { fmpz_mod_poly_compose_mod(r, pow->pow + i, r, f, ctx); m ^= bit; } } } if (res == f) { fmpz_mod_poly_swap(res, r, ctx); fmpz_mod_poly_clear(tr, ctx); } } flint-3.1.3/src/fmpz_mod_poly/frobenius_powers_2exp_clear.c000066400000000000000000000012521461254215100241430ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" void fmpz_mod_poly_frobenius_powers_2exp_clear( fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < pow->len; i++) fmpz_mod_poly_clear(pow->pow + i, ctx); if (pow->len) flint_free(pow->pow); } flint-3.1.3/src/fmpz_mod_poly/frobenius_powers_2exp_precomp.c000066400000000000000000000024011461254215100245170ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_frobenius_powers_2exp_precomp( fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, ulong m, const fmpz_mod_ctx_t ctx) { slong i, l = 0; if (m == 0) { pow->len = 0; return; } l = FLINT_CLOG2(m); if ((WORD(1) << l) == m) l++; pow->pow = (fmpz_mod_poly_struct *) flint_malloc(l*sizeof(fmpz_mod_poly_struct)); for (i = 0; i < l; i++) fmpz_mod_poly_init(pow->pow + i, ctx); pow->len = l; fmpz_mod_poly_powmod_x_fmpz_preinv(pow->pow + 0, fmpz_mod_ctx_modulus(ctx), f, finv, ctx); for (i = 1; i < l; i++) fmpz_mod_poly_compose_mod(pow->pow + i, pow->pow + i - 1, pow->pow + i - 1, f, ctx); } flint-3.1.3/src/fmpz_mod_poly/frobenius_powers_clear.c000066400000000000000000000012661461254215100232120ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" void fmpz_mod_poly_frobenius_powers_clear(fmpz_mod_poly_frobenius_powers_t pow, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i <= pow->len; i++) fmpz_mod_poly_clear(pow->pow + i, ctx); flint_free(pow->pow); } flint-3.1.3/src/fmpz_mod_poly/frobenius_powers_precomp.c000066400000000000000000000026751461254215100235760ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_frobenius_powers_precomp(fmpz_mod_poly_frobenius_powers_t pow, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, ulong m, const fmpz_mod_ctx_t ctx) { slong i; pow->pow = (fmpz_mod_poly_struct *) flint_malloc((m + 1)*sizeof(fmpz_mod_poly_struct)); for (i = 0; i <= m; i++) fmpz_mod_poly_init(pow->pow + i, ctx); pow->len = m; /* x mod f */ fmpz_mod_poly_set_coeff_ui(pow->pow + 0, 1, 1, ctx); fmpz_mod_poly_set_coeff_ui(pow->pow + 0, 0, 0, ctx); _fmpz_mod_poly_set_length(pow->pow + 0, 2); if (f->length <= 2) fmpz_mod_poly_rem(pow->pow + 0, pow->pow + 0, f, ctx); if (m >= 1) fmpz_mod_poly_powmod_x_fmpz_preinv(pow->pow + 1, fmpz_mod_ctx_modulus(ctx), f, finv, ctx); for (i = 2; i <= m; i++) fmpz_mod_poly_compose_mod(pow->pow + i, pow->pow + i - 1, pow->pow + 1, f, ctx); } flint-3.1.3/src/fmpz_mod_poly/gcd.c000066400000000000000000000051611461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "gr_poly.h" slong _fmpz_mod_poly_gcd(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx) { if (lenB == 1) { fmpz_one(G); return 1; } else /* lenA >= lenB > 1 */ { slong lenG; gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); if (FLINT_MIN(lenA, lenB) < FMPZ_MOD_POLY_GCD_CUTOFF) GR_MUST_SUCCEED(_gr_poly_gcd_euclidean(G, &lenG, A, lenA, B, lenB, gr_ctx)); else GR_MUST_SUCCEED(_gr_poly_gcd_hgcd(G, &lenG, A, lenA, B, lenB, FMPZ_MOD_POLY_HGCD_CUTOFF, FMPZ_MOD_POLY_GCD_CUTOFF, gr_ctx)); return lenG; } } void fmpz_mod_poly_gcd(fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { if (A->length < B->length) { fmpz_mod_poly_gcd(G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; slong lenG; fmpz *g; if (lenA == 0) /* lenA = lenB = 0 */ { fmpz_mod_poly_zero(G, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { fmpz_mod_poly_make_monic(G, A, ctx); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { g = _fmpz_vec_init(FLINT_MIN(lenA, lenB)); } else { fmpz_mod_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } lenG = _fmpz_mod_poly_gcd(g, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _fmpz_mod_poly_set_length(G, lenG); if (lenG == 1) fmpz_one(G->coeffs); else fmpz_mod_poly_make_monic(G, G, ctx); } } } flint-3.1.3/src/fmpz_mod_poly/gcd_euclidean_f.c000066400000000000000000000114241461254215100215210ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx) { slong lenG = 0; if (lenB == 1) { fmpz_t invB; fmpz_init(invB); fmpz_gcdinv(f, invB, B, fmpz_mod_ctx_modulus(ctx)); if (fmpz_is_one(f)) { fmpz_one(G); lenG = 1; } fmpz_clear(invB); } else /* lenA >= lenB > 1 */ { const slong lenW = FLINT_MAX(lenA - lenB + 1, lenB) + lenA + 2 * lenB; fmpz *Q, *R1, *R2, *R3, *T, *W; slong lenR2, lenR3; TMP_INIT; TMP_START; FMPZ_VEC_TMP_INIT(W, lenW); Q = W; R1 = W + FLINT_MAX(lenA - lenB + 1, lenB); R2 = R1 + lenA; R3 = R2 + lenB; _fmpz_mod_poly_divrem_f(f, Q, R1, A, lenA, B, lenB, ctx); if (!fmpz_is_one(f)) goto exit; lenR3 = lenB - 1; FMPZ_VEC_NORM(R1, lenR3); if (lenR3 == 0) { _fmpz_vec_set(G, B, lenB); lenG = lenB; } else { fmpz_t inv; T = R3; R3 = R1; R1 = T; _fmpz_vec_set(R2, B, lenB); lenR2 = lenB; fmpz_init(inv); do { fmpz_gcdinv(f, inv, R3 + (lenR3 - 1), fmpz_mod_ctx_modulus(ctx)); if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_divrem_basecase(Q, R2, R2, lenR2, R3, lenR3, inv, ctx); lenR2 = lenR3 - 1; FMPZ_VEC_NORM(R2, lenR2); FMPZ_VEC_SWAP(R2, lenR2, R3, lenR3); } while (lenR3 > 0); _fmpz_vec_set(G, R2, lenR2); lenG = lenR2; cleanup: fmpz_clear(inv); } exit: FMPZ_VEC_TMP_CLEAR(W, lenW); TMP_END; } return lenG; } void fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { if (A->length < B->length) { fmpz_mod_poly_gcd_euclidean_f(f, G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; slong lenG; fmpz *g; if (lenA == 0) /* lenA = lenB = 0 */ { fmpz_mod_poly_zero(G, ctx); fmpz_one(f); } else if (lenB == 0) /* lenA > lenB = 0 */ { fmpz_t invA; fmpz_init(invA); fmpz_gcdinv(f, invA, A->coeffs + lenA - 1, fmpz_mod_ctx_modulus(ctx)); if (fmpz_is_one(f)) fmpz_mod_poly_scalar_mul_fmpz(G, A, invA, ctx); else fmpz_mod_poly_zero(G, ctx); fmpz_clear(invA); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { g = _fmpz_vec_init(FLINT_MIN(lenA, lenB)); } else { fmpz_mod_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } lenG = _fmpz_mod_poly_gcd_euclidean_f(f, g, A->coeffs, lenA, B->coeffs, lenB, ctx); if (fmpz_is_one(f)) { if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _fmpz_mod_poly_set_length(G, lenG); if (lenG == 1) fmpz_one(G->coeffs); else fmpz_mod_poly_make_monic(G, G, ctx); } else /* Factor found, ensure G is normalised */ { if (G == A || G == B) _fmpz_vec_clear(g, FLINT_MIN(lenA, lenB)); else { _fmpz_vec_zero(G->coeffs, FLINT_MIN(lenA, lenB)); _fmpz_mod_poly_set_length(G, 0); } } } } } flint-3.1.3/src/fmpz_mod_poly/gcdinv.c000066400000000000000000000063231461254215100177220ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_gcdinv(fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx) { fmpz *T; fmpz_t inv; slong ans; fmpz_init(inv); fmpz_invmod(inv, A + (lenA - 1), fmpz_mod_ctx_modulus(ctx)); if (lenB < 16) { ans = _fmpz_mod_poly_gcdinv_euclidean(G, S, A, lenA, B, lenB, inv, ctx); } else { T = _fmpz_vec_init(lenA - 1); ans = _fmpz_mod_poly_xgcd(G, T, S, B, lenB, A, lenA, inv, ctx); _fmpz_vec_clear(T, lenA - 1); } fmpz_clear(inv); return ans; } void fmpz_mod_poly_gcdinv(fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length; if (lenB < 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_gcdinv). lenB < 2.\n"); } if (lenA >= lenB) { fmpz_mod_poly_t T; fmpz_mod_poly_init(T, ctx); fmpz_mod_poly_rem(T, A, B, ctx); fmpz_mod_poly_gcdinv(G, S, T, B, ctx); fmpz_mod_poly_clear(T, ctx); return; } if (lenA == 0) { fmpz_mod_poly_zero(G, ctx); fmpz_mod_poly_zero(S, ctx); } else { const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz *g, *s; slong lenG; if (G == A || G == B) { g = _fmpz_vec_init(lenA); } else { fmpz_mod_poly_fit_length(G, lenA, ctx); g = G->coeffs; } if (S == A || S == B) { s = _fmpz_vec_init(lenB - 1); } else { fmpz_mod_poly_fit_length(S, lenB - 1, ctx); s = S->coeffs; } lenG = _fmpz_mod_poly_gcdinv(g, s, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = lenA; } if (S == A || S == B) { _fmpz_vec_clear(S->coeffs, S->alloc); S->coeffs = s; S->alloc = lenB - 1; } _fmpz_mod_poly_set_length(G, lenG); _fmpz_mod_poly_set_length(S, lenB - lenG); _fmpz_mod_poly_normalise(S); if (!fmpz_is_one(fmpz_mod_poly_lead(G, ctx))) { fmpz_t inv; fmpz_init(inv); fmpz_invmod(inv, fmpz_mod_poly_lead(G, ctx), p); fmpz_mod_poly_scalar_mul_fmpz(G, G, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(S, S, inv, ctx); fmpz_clear(inv); } } } flint-3.1.3/src/fmpz_mod_poly/gcdinv_euclidean.c000066400000000000000000000136201461254215100217310ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_gcdinv_euclidean(fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx) { _fmpz_vec_zero(G, lenA); _fmpz_vec_zero(S, lenB - 1); if (lenA == 1) { fmpz_set(G + 0, A + 0); fmpz_one(S + 0); return 1; } else { fmpz *Q, *R; slong i, lenQ, lenR; TMP_INIT; TMP_START; FMPZ_VEC_TMP_INIT(Q, 2*lenB); R = Q + lenB; _fmpz_mod_poly_divrem(Q, R, B, lenB, A, lenA, invA, ctx); lenR = lenA - 1; FMPZ_VEC_NORM(R, lenR); if (lenR == 0) { _fmpz_vec_set(G, A, lenA); fmpz_one(S + 0); FMPZ_VEC_TMP_CLEAR(Q, 2*lenB); TMP_END; return lenA; } else if (lenR == 1) { lenQ = lenB - lenA + 1; FMPZ_VEC_NORM(Q, lenQ); _fmpz_vec_swap(G, R, lenR); _fmpz_vec_swap(S, Q, lenQ); _fmpz_mod_vec_neg(S, S, lenQ, ctx); FMPZ_VEC_TMP_CLEAR(Q, 2*lenB); TMP_END; return 1; } else { fmpz_t inv; fmpz *D, *U1, *U2, *V3, *W; slong lenD, lenU1, lenU2, lenV3, lenW; fmpz_init(inv); FMPZ_VEC_TMP_INIT(W, 3*lenB + 2*lenA); D = W + lenB; U1 = D + lenA; U2 = U1 + lenB; V3 = U2 + lenB; lenQ = lenB - lenA + 1; FMPZ_VEC_NORM(Q, lenQ); fmpz_set_ui(U1, 1); lenU1 = 1; _fmpz_vec_set(D, A, lenA); lenD = lenA; _fmpz_mod_vec_neg(U2, Q, lenQ, ctx); lenU2 = lenQ; lenV3 = 0; FMPZ_VEC_SWAP(V3, lenV3, R, lenR); do { fmpz_invmod(inv, V3 + (lenV3 - 1), fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_divrem_basecase(Q, D, D, lenD, V3, lenV3, inv, ctx); lenQ = lenD - lenV3 + 1; lenD = lenV3 - 1; FMPZ_VEC_NORM(D, lenD); if (lenV3 != 0) { if (lenU2 >= lenQ) _fmpz_mod_poly_mul(W, U2, lenU2, Q, lenQ, ctx); else _fmpz_mod_poly_mul(W, Q, lenQ, U2, lenU2, ctx); lenW = lenQ + lenU2 - 1; _fmpz_mod_poly_sub(U1, U1, lenU1, W, lenW, ctx); lenU1 = FLINT_MAX(lenU1, lenW); FMPZ_VEC_NORM(U1, lenU1); } FMPZ_VEC_SWAP(U1, lenU1, U2, lenU2); FMPZ_VEC_SWAP(V3, lenV3, D, lenD); } while (lenV3 != 0); _fmpz_vec_swap(G, D, lenD); _fmpz_vec_swap(S, U1, lenU1); for (i = 0; i < lenU1; i++) { if (fmpz_sgn(S + i) < 0) fmpz_add(S + i, S + i, fmpz_mod_ctx_modulus(ctx)); } FMPZ_VEC_TMP_CLEAR(W, 3*lenB + 2*lenA); FMPZ_VEC_TMP_CLEAR(Q, 2*lenB); fmpz_clear(inv); TMP_END; return lenD; } } } void fmpz_mod_poly_gcdinv_euclidean(fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length; fmpz_t inv; if (lenB < 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_gcdinv). lenB < 2.\n"); } if (lenA >= lenB) { fmpz_mod_poly_t T; fmpz_mod_poly_init(T, ctx); fmpz_mod_poly_rem(T, A, B, ctx); fmpz_mod_poly_gcdinv_euclidean(G, S, T, B, ctx); fmpz_mod_poly_clear(T, ctx); return; } fmpz_init(inv); if (lenA == 0) { fmpz_mod_poly_zero(G, ctx); fmpz_mod_poly_zero(S, ctx); } else /* lenB >= lenA >= 1 */ { fmpz *g, *s; slong lenG; if (G == A || G == B) { g = _fmpz_vec_init(FLINT_MIN(lenA, lenB)); } else { fmpz_mod_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = _fmpz_vec_init(lenB); } else { fmpz_mod_poly_fit_length(S, lenB, ctx); s = S->coeffs; } fmpz_invmod(inv, fmpz_mod_poly_lead(A, ctx), fmpz_mod_ctx_modulus(ctx)); lenG = _fmpz_mod_poly_gcdinv_euclidean(g, s, A->coeffs, lenA, B->coeffs, lenB, inv, ctx); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { _fmpz_vec_clear(S->coeffs, S->alloc); S->coeffs = s; S->alloc = lenB; } _fmpz_mod_poly_set_length(G, lenG); _fmpz_mod_poly_set_length(S, FLINT_MAX(lenB - lenG, 1)); _fmpz_mod_poly_normalise(S); if (!fmpz_is_one(fmpz_mod_poly_lead(G, ctx))) { fmpz_invmod(inv, fmpz_mod_poly_lead(G, ctx), fmpz_mod_ctx_modulus(ctx)); fmpz_mod_poly_scalar_mul_fmpz(G, G, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(S, S, inv, ctx); } fmpz_clear(inv); } } flint-3.1.3/src/fmpz_mod_poly/gcdinv_euclidean_f.c000066400000000000000000000137511461254215100222430ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_gcdinv_euclidean_f(fmpz_t f, fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx) { _fmpz_vec_zero(G, lenA); _fmpz_vec_zero(S, lenB - 1); if (lenA == 1) { fmpz_set_ui(f, 1); fmpz_set(G + 0, A + 0); fmpz_one(S + 0); return 1; } else { fmpz *Q, *R; slong lenQ, lenR, lenD = 0; TMP_INIT; TMP_START; FMPZ_VEC_TMP_INIT(Q, 2*lenB); R = Q + lenB; _fmpz_mod_poly_divrem_f(f, Q, R, B, lenB, A, lenA, ctx); if (!fmpz_is_one(f)) goto cleanup2; lenR = lenA - 1; FMPZ_VEC_NORM(R, lenR); if (lenR == 0) { fmpz_set_ui(f, 1); _fmpz_vec_set(G, A, lenA); fmpz_one(S + 0); FMPZ_VEC_TMP_CLEAR(Q, 2*lenB); TMP_END; return lenA; } else if (lenR == 1) { lenQ = lenB - lenA + 1; FMPZ_VEC_NORM(Q, lenQ); _fmpz_vec_swap(G, R, lenR); _fmpz_vec_swap(S, Q, lenQ); _fmpz_mod_vec_neg(S, S, lenQ, ctx); FMPZ_VEC_TMP_CLEAR(Q, 2*lenB); TMP_END; return 1; } else { fmpz_t inv; fmpz *D, *U1, *U2, *V3, *W; slong lenU1, lenU2, lenV3, lenW; fmpz_init(inv); FMPZ_VEC_TMP_INIT(W, 3*lenB + 2*lenA); D = W + lenB; U1 = D + lenA; U2 = U1 + lenB; V3 = U2 + lenB; lenQ = lenB - lenA + 1; FMPZ_VEC_NORM(Q, lenQ); fmpz_set_ui(U1, 1); lenU1 = 1; _fmpz_vec_set(D, A, lenA); lenD = lenA; _fmpz_mod_vec_neg(U2, Q, lenQ, ctx); lenU2 = lenQ; lenV3 = 0; FMPZ_VEC_SWAP(V3, lenV3, R, lenR); do { fmpz_gcdinv(f, inv, V3 + (lenV3 - 1), fmpz_mod_ctx_modulus(ctx)); if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_divrem_basecase(Q, D, D, lenD, V3, lenV3, inv, ctx); lenQ = lenD - lenV3 + 1; lenD = lenV3 - 1; FMPZ_VEC_NORM(D, lenD); if (lenV3 != 0) { if (lenU2 >= lenQ) _fmpz_mod_poly_mul(W, U2, lenU2, Q, lenQ, ctx); else _fmpz_mod_poly_mul(W, Q, lenQ, U2, lenU2, ctx); lenW = lenQ + lenU2 - 1; _fmpz_mod_poly_sub(U1, U1, lenU1, W, lenW, ctx); lenU1 = FLINT_MAX(lenU1, lenW); FMPZ_VEC_NORM(U1, lenU1); } FMPZ_VEC_SWAP(U1, lenU1, U2, lenU2); FMPZ_VEC_SWAP(V3, lenV3, D, lenD); } while (lenV3 != 0); _fmpz_vec_swap(G, D, lenD); _fmpz_vec_swap(S, U1, lenU1); cleanup: FMPZ_VEC_TMP_CLEAR(W, 3*lenB + 2*lenA); cleanup2: FMPZ_VEC_TMP_CLEAR(Q, 2*lenB); fmpz_clear(inv); TMP_END; return lenD; } } } void fmpz_mod_poly_gcdinv_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length; fmpz_t inv; if (lenB < 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_gcdinv_euclidean_f). lenB < 2.\n"); } if (lenA >= lenB) { fmpz_mod_poly_t T; fmpz_mod_poly_init(T, ctx); fmpz_mod_poly_rem(T, A, B, ctx); fmpz_mod_poly_gcdinv_euclidean_f(f, G, S, T, B, ctx); fmpz_mod_poly_clear(T, ctx); return; } fmpz_init(inv); if (lenA == 0) { fmpz_set_ui(f, 1); fmpz_mod_poly_zero(G, ctx); fmpz_mod_poly_zero(S, ctx); } else /* lenB >= lenA >= 1 */ { fmpz *g, *s; slong lenG; const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_gcdinv(f, inv, fmpz_mod_poly_lead(A, ctx), p); if (!fmpz_is_one(f)) goto cleanup; if (G == A || G == B) { g = _fmpz_vec_init(FLINT_MIN(lenA, lenB)); } else { fmpz_mod_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = _fmpz_vec_init(lenB); } else { fmpz_mod_poly_fit_length(S, lenB, ctx); s = S->coeffs; } lenG = _fmpz_mod_poly_gcdinv_euclidean_f(f, g, s, A->coeffs, lenA, B->coeffs, lenB, inv, ctx); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { _fmpz_vec_clear(S->coeffs, S->alloc); S->coeffs = s; S->alloc = lenB; } if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_set_length(G, lenG); _fmpz_mod_poly_set_length(S, FLINT_MAX(lenB - lenG, 1)); _fmpz_mod_poly_normalise(S); if (!fmpz_is_one(fmpz_mod_poly_lead(G, ctx))) { fmpz_invmod(inv, fmpz_mod_poly_lead(G, ctx), p); fmpz_mod_poly_scalar_mul_fmpz(G, G, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(S, S, inv, ctx); } cleanup: fmpz_clear(inv); } } flint-3.1.3/src/fmpz_mod_poly/gcdinv_f.c000066400000000000000000000070521461254215100202270ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_gcdinv_f(fmpz_t f, fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx) { fmpz *T; fmpz_t inv; slong ans = 0; fmpz_init(inv); fmpz_gcdinv(f, inv, A + (lenA - 1), fmpz_mod_ctx_modulus(ctx)); if (fmpz_is_one(f)) { if (lenB < 16) { ans = _fmpz_mod_poly_gcdinv_euclidean_f(f, G, S, A, lenA, B, lenB, inv, ctx); } else { T = _fmpz_vec_init(lenA - 1); ans = _fmpz_mod_poly_xgcd_f(f, G, T, S, B, lenB, A, lenA, inv, ctx); _fmpz_vec_clear(T, lenA - 1); } } fmpz_clear(inv); return ans; } void fmpz_mod_poly_gcdinv_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length; if (lenB < 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_gcdinv). lenB < 2.\n"); } if (lenA >= lenB) { fmpz_mod_poly_t T; fmpz_mod_poly_init(T, ctx); fmpz_mod_poly_rem_f(f, T, A, B, ctx); if (fmpz_is_one(f)) fmpz_mod_poly_gcdinv_f(f, G, S, T, B, ctx); fmpz_mod_poly_clear(T, ctx); return; } if (lenA == 0) { fmpz_mod_poly_zero(G, ctx); fmpz_mod_poly_zero(S, ctx); fmpz_one(f); } else { fmpz *g, *s; slong lenG; if (G == A || G == B) { g = _fmpz_vec_init(lenA); } else { fmpz_mod_poly_fit_length(G, lenA, ctx); g = G->coeffs; } if (S == A || S == B) { s = _fmpz_vec_init(lenB - 1); } else { fmpz_mod_poly_fit_length(S, lenB - 1, ctx); s = S->coeffs; } lenG = _fmpz_mod_poly_gcdinv_f(f, g, s, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = lenA; } if (S == A || S == B) { _fmpz_vec_clear(S->coeffs, S->alloc); S->coeffs = s; S->alloc = lenB - 1; } if (fmpz_is_one(f)) { _fmpz_mod_poly_set_length(G, lenG); _fmpz_mod_poly_set_length(S, lenB - lenG); _fmpz_mod_poly_normalise(S); if (!fmpz_is_one(fmpz_mod_poly_lead(G, ctx))) { fmpz_t inv; fmpz_init(inv); fmpz_gcdinv(f, inv, fmpz_mod_poly_lead(G, ctx), fmpz_mod_ctx_modulus(ctx)); fmpz_mod_poly_scalar_mul_fmpz(G, G, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(S, S, inv, ctx); fmpz_clear(inv); } } } } flint-3.1.3/src/fmpz_mod_poly/gen.c000066400000000000000000000013101461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_gen(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, 2, ctx); fmpz_zero(poly->coeffs + 0); fmpz_one(poly->coeffs + 1); _fmpz_mod_poly_set_length(poly, 2*!fmpz_is_one(fmpz_mod_ctx_modulus(ctx))); } flint-3.1.3/src/fmpz_mod_poly/get.c000066400000000000000000000017421461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_poly.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_get_fmpz_poly(fmpz_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) { fmpz_poly_fit_length(f, g->length); _fmpz_poly_set_length(f, g->length); _fmpz_vec_set(f->coeffs, g->coeffs, g->length); } void fmpz_mod_poly_get_nmod_poly(nmod_poly_t f, const fmpz_mod_poly_t g) { slong i; nmod_poly_fit_length(f, g->length); _nmod_poly_set_length(f, g->length); for (i = 0; i < g->length; i++) f->coeffs[i] = fmpz_get_ui(g->coeffs + i); } flint-3.1.3/src/fmpz_mod_poly/get_str.c000066400000000000000000000014531461254215100201160ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" char * fmpz_mod_poly_get_str(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return _fmpz_poly_get_str(poly->coeffs, poly->length); } char * fmpz_mod_poly_get_str_pretty(const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx) { return _fmpz_poly_get_str_pretty(poly->coeffs, poly->length, x); } flint-3.1.3/src/fmpz_mod_poly/hamming_weight.c000066400000000000000000000011051461254215100214300ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" slong fmpz_mod_poly_hamming_weight(const fmpz_mod_poly_t A, const fmpz_mod_ctx_t ctx) { return _fmpz_poly_hamming_weight(A->coeffs, A->length); } flint-3.1.3/src/fmpz_mod_poly/hgcd.c000066400000000000000000000017361461254215100173600ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "gr_poly.h" slong _fmpz_mod_poly_hgcd(fmpz **M, slong *lenM, fmpz *A, slong *lenA, fmpz *B, slong *lenB, const fmpz *a, slong lena, const fmpz *b, slong lenb, const fmpz_mod_ctx_t ctx) { slong sgnM; gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_poly_hgcd(NULL, &sgnM, (gr_ptr *) M, lenM, A, lenA, B, lenB, a, lena, b, lenb, FMPZ_MOD_POLY_HGCD_CUTOFF, gr_ctx)); return sgnM; } flint-3.1.3/src/fmpz_mod_poly/inflate.c000066400000000000000000000026121461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_inflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong inflation, const fmpz_mod_ctx_t ctx) { if (input->length <= 1 || inflation == 1) { fmpz_mod_poly_set(result, input, ctx); } else if (inflation == 0) { fmpz_t v; fmpz_init_set_ui(v, 1); fmpz_mod_poly_evaluate_fmpz(v, input, v, ctx); fmpz_mod_poly_set_fmpz(result, v, ctx); fmpz_clear(v); } else { slong i, j, res_length = (input->length - 1) * inflation + 1; fmpz_mod_poly_fit_length(result, res_length, ctx); for (i = input->length - 1; i > 0; i--) { fmpz_set(result->coeffs + (i * inflation), input->coeffs + i); for (j = i * inflation - 1; j > (i - 1) * inflation; j--) fmpz_zero(result->coeffs + j); } fmpz_set(result->coeffs + 0, input->coeffs + 0); result->length = res_length; } } flint-3.1.3/src/fmpz_mod_poly/init.c000066400000000000000000000014211461254215100174050ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" void fmpz_mod_poly_init2(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx) { if (alloc) /* allocate space for alloc small coeffs */ poly->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); else poly->coeffs = NULL; poly->alloc = alloc; poly->length = 0; } flint-3.1.3/src/fmpz_mod_poly/inlines.c000066400000000000000000000122251461254215100201070ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_POLY_INLINES_C #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" /* FIXME: These should be moved to their own files */ void fmpz_mod_poly_add_si(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong c, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); fmpz_set_si(d, c); if (fmpz_size(fmpz_mod_ctx_modulus(ctx)) > 1) { if (c < 0) fmpz_add(d, d, fmpz_mod_ctx_modulus(ctx)); } else fmpz_mod(d, d, fmpz_mod_ctx_modulus(ctx)); if (poly->length == 0) fmpz_mod_poly_set_fmpz(res, d, ctx); else { fmpz_mod_poly_set(res, poly, ctx); fmpz_add(res->coeffs + 0, res->coeffs + 0, d); if (fmpz_cmp(res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)) >= 0) fmpz_sub(res->coeffs + 0, res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(res); } fmpz_clear(d); } void fmpz_mod_poly_sub_si(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong c, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); fmpz_set_si(d, c); if (fmpz_size(fmpz_mod_ctx_modulus(ctx)) > 1) { if (c < 0) fmpz_add(d, d, fmpz_mod_ctx_modulus(ctx)); } else fmpz_mod(d, d, fmpz_mod_ctx_modulus(ctx)); if (poly->length == 0) { fmpz_sub(d, fmpz_mod_ctx_modulus(ctx), d); if (fmpz_cmp(d, fmpz_mod_ctx_modulus(ctx)) == 0) fmpz_zero(d); fmpz_mod_poly_set_fmpz(res, d, ctx); } else { fmpz_mod_poly_set(res, poly, ctx); fmpz_sub(res->coeffs + 0, res->coeffs + 0, d); if (fmpz_sgn(res->coeffs + 0) < 0) fmpz_add(res->coeffs + 0, res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(res); } fmpz_clear(d); } void fmpz_mod_poly_si_sub(fmpz_mod_poly_t res, slong c, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); fmpz_set_si(d, c); if (fmpz_size(fmpz_mod_ctx_modulus(ctx)) > 1) { if (c < 0) fmpz_add(d, d, fmpz_mod_ctx_modulus(ctx)); } else fmpz_mod(d, d, fmpz_mod_ctx_modulus(ctx)); if (poly->length == 0) fmpz_mod_poly_set_fmpz(res, d, ctx); else { fmpz_mod_poly_neg(res, poly, ctx); fmpz_add(res->coeffs + 0, res->coeffs + 0, d); if (fmpz_cmp(res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)) >= 0) fmpz_sub(res->coeffs + 0, res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(res); } fmpz_clear(d); } void fmpz_mod_poly_add_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t c, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); if (fmpz_sgn(c) < 0 || fmpz_cmp(c, fmpz_mod_ctx_modulus(ctx)) >= 0) fmpz_mod(d, c, fmpz_mod_ctx_modulus(ctx)); else fmpz_set(d, c); if (poly->length == 0) fmpz_mod_poly_set_fmpz(res, d, ctx); else { fmpz_mod_poly_set(res, poly, ctx); fmpz_add(res->coeffs + 0, res->coeffs + 0, d); if (fmpz_cmp(res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)) >= 0) fmpz_sub(res->coeffs + 0, res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(res); } fmpz_clear(d); } void fmpz_mod_poly_sub_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t c, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); if (fmpz_sgn(c) < 0 || fmpz_cmp(c, fmpz_mod_ctx_modulus(ctx)) >= 0) fmpz_mod(d, c, fmpz_mod_ctx_modulus(ctx)); else fmpz_set(d, c); if (poly->length == 0) { fmpz_sub(d, fmpz_mod_ctx_modulus(ctx), d); if (fmpz_cmp(d, fmpz_mod_ctx_modulus(ctx)) == 0) fmpz_zero(d); fmpz_mod_poly_set_fmpz(res, d, ctx); } else { fmpz_mod_poly_set(res, poly, ctx); fmpz_sub(res->coeffs + 0, res->coeffs + 0, d); if (fmpz_sgn(res->coeffs + 0) < 0) fmpz_add(res->coeffs + 0, res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(res); } fmpz_clear(d); } void fmpz_mod_poly_fmpz_sub(fmpz_mod_poly_t res, const fmpz_t c, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); if (fmpz_sgn(c) < 0 || fmpz_cmp(c, fmpz_mod_ctx_modulus(ctx)) >= 0) fmpz_mod(d, c, fmpz_mod_ctx_modulus(ctx)); else fmpz_set(d, c); if (poly->length == 0) fmpz_mod_poly_set_fmpz(res, d, ctx); else { fmpz_mod_poly_neg(res, poly, ctx); fmpz_add(res->coeffs + 0, res->coeffs + 0, d); if (fmpz_cmp(res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)) >= 0) fmpz_sub(res->coeffs + 0, res->coeffs + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(res); } fmpz_clear(d); } flint-3.1.3/src/fmpz_mod_poly/inv_series.c000066400000000000000000000032511461254215100206130ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_poly.h" void _fmpz_mod_poly_inv_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t mod) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, mod); GR_MUST_SUCCEED(_gr_poly_inv_series(g, h, hlen, n, gr_ctx)); } void fmpz_mod_poly_inv_series(fmpz_mod_poly_t g, const fmpz_mod_poly_t h, slong n, const fmpz_mod_ctx_t ctx) { const slong hlen = h->length; if (n == 0 || h->length == 0 || fmpz_is_zero(h->coeffs + 0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_inv). Division by zero.\n"); } if (hlen == 1) n = 1; if (g == h) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, n, ctx); _fmpz_mod_poly_inv_series(t->coeffs, h->coeffs, hlen, n, ctx); _fmpz_mod_poly_set_length(t, n); _fmpz_mod_poly_normalise(t); fmpz_mod_poly_swap(g, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { _fmpz_mod_poly_fit_length(g, n); _fmpz_mod_poly_inv_series(g->coeffs, h->coeffs, hlen, n, ctx); _fmpz_mod_poly_set_length(g, n); _fmpz_mod_poly_normalise(g); } } flint-3.1.3/src/fmpz_mod_poly/inv_series_newton_f.c000066400000000000000000000037371461254215100225230ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_inv_series_f(fmpz_t f, fmpz_mod_poly_t Qinv, const fmpz_mod_poly_t Q, slong n, const fmpz_mod_ctx_t ctx) { const fmpz *p = fmpz_mod_ctx_modulus(ctx); fmpz_t cinv; fmpz *Qcopy; int Qalloc; if (Q->length >= n) { Qcopy = Q->coeffs; Qalloc = 0; } else { slong i; Qcopy = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < Q->length; i++) Qcopy[i] = Q->coeffs[i]; flint_mpn_zero((mp_ptr) Qcopy + i, n - i); Qalloc = 1; } fmpz_init(cinv); fmpz_gcdinv(f, cinv, Q->coeffs, p); if (!fmpz_is_one(f)) goto cleanup; if (Qinv != Q) { fmpz_mod_poly_fit_length(Qinv, n, ctx); /* TODO: _fmpz_mod_poly_inv_series no longer accepts a precomputed inverse leading coefficient; add back a version that does this. */ /* _fmpz_mod_poly_inv_series(Qinv->coeffs, Qcopy, n, cinv, ctx); */ _fmpz_mod_poly_inv_series(Qinv->coeffs, Qcopy, n, n, ctx); } else { fmpz *t = _fmpz_vec_init(n); /* _fmpz_mod_poly_inv_series(t, Qcopy, n, cinv, ctx); */ _fmpz_mod_poly_inv_series(Qinv->coeffs, Qcopy, n, n, ctx); _fmpz_vec_clear(Qinv->coeffs, Qinv->alloc); Qinv->coeffs = t; Qinv->alloc = n; Qinv->length = n; } _fmpz_mod_poly_set_length(Qinv, n); _fmpz_mod_poly_normalise(Qinv); cleanup: if (Qalloc) flint_free(Qcopy); fmpz_clear(cinv); } flint-3.1.3/src/fmpz_mod_poly/invmod.c000066400000000000000000000043731461254215100177470ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" int _fmpz_mod_poly_invmod(fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_mod_ctx_t ctx) { fmpz *G; slong lenG; FMPZ_VEC_NORM(B, lenB); G = _fmpz_vec_init(lenB); lenG = _fmpz_mod_poly_gcdinv(G, A, B, lenB, P, lenP, ctx); if (lenG == 1 && !fmpz_is_one(G + 0)) { fmpz_t invG; fmpz_init(invG); fmpz_invmod(invG, G + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_scalar_mul_fmpz(A, A, lenP - 1, invG, ctx); fmpz_clear(invG); } _fmpz_vec_clear(G, lenB); return (lenG == 1); } int fmpz_mod_poly_invmod(fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx) { const slong lenB = B->length, lenP = P->length; fmpz *t; int ans; if (lenP < 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_invmod). lenP < 2.\n"); } if (lenB == 0) { fmpz_mod_poly_zero(A, ctx); return 0; } if (lenB >= lenP) { fmpz_mod_poly_t T; fmpz_mod_poly_init(T, ctx); fmpz_mod_poly_rem(T, B, P, ctx); ans = fmpz_mod_poly_invmod(A, T, P, ctx); fmpz_mod_poly_clear(T, ctx); return ans; } if (A != B && A != P) { fmpz_mod_poly_fit_length(A, lenP - 1, ctx); t = A->coeffs; } else { t = _fmpz_vec_init(lenP); } ans = _fmpz_mod_poly_invmod(t, B->coeffs, lenB, P->coeffs, lenP, ctx); if (A == B || A == P) { _fmpz_vec_clear(A->coeffs, A->alloc); A->coeffs = t; A->alloc = lenP - 1; } _fmpz_mod_poly_set_length(A, lenP - 1); _fmpz_mod_poly_normalise(A); return ans; } flint-3.1.3/src/fmpz_mod_poly/invmod_f.c000066400000000000000000000046521461254215100202540ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" int _fmpz_mod_poly_invmod_f(fmpz_t f, fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_mod_ctx_t ctx) { fmpz *G; slong lenG; FMPZ_VEC_NORM(B, lenB); G = _fmpz_vec_init(lenB); lenG = _fmpz_mod_poly_gcdinv_f(f, G, A, B, lenB, P, lenP, ctx); if (fmpz_is_one(f) && lenG == 1 && !fmpz_is_one(G + 0)) { fmpz_t invG; fmpz_init(invG); fmpz_gcdinv(f, invG, G + 0, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_scalar_mul_fmpz(A, A, lenP - 1, invG, ctx); fmpz_clear(invG); } _fmpz_vec_clear(G, lenB); return (lenG == 1); } int fmpz_mod_poly_invmod_f(fmpz_t f, fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx) { const slong lenB = B->length, lenP = P->length; fmpz *t; int ans; if (lenP < 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_invmod). lenP < 2.\n"); } if (lenB == 0) { fmpz_mod_poly_zero(A, ctx); fmpz_one(f); return 0; } if (lenB >= lenP) { fmpz_mod_poly_t T; fmpz_mod_poly_init(T, ctx); fmpz_mod_poly_rem(T, B, P, ctx); ans = fmpz_mod_poly_invmod_f(f, A, T, P, ctx); fmpz_mod_poly_clear(T, ctx); return ans; } if (A != B && A != P) { fmpz_mod_poly_fit_length(A, lenP - 1, ctx); t = A->coeffs; } else { t = _fmpz_vec_init(lenP); } ans = _fmpz_mod_poly_invmod_f(f, t, B->coeffs, lenB, P->coeffs, lenP, ctx); if (A == B || A == P) { _fmpz_vec_clear(A->coeffs, A->alloc); A->coeffs = t; A->alloc = lenP - 1; } if (fmpz_is_one(f)) { _fmpz_mod_poly_set_length(A, lenP - 1); _fmpz_mod_poly_normalise(A); } return ans; } flint-3.1.3/src/fmpz_mod_poly/invsqrt_series.c000066400000000000000000000034231461254215100215260ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 William Hart Copyright (C) 2011, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_poly.h" void _fmpz_mod_poly_invsqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t mod) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, mod); GR_MUST_SUCCEED(_gr_poly_rsqrt_series(g, h, hlen, n, gr_ctx)); } void fmpz_mod_poly_invsqrt_series(fmpz_mod_poly_t g, const fmpz_mod_poly_t h, slong n, const fmpz_mod_ctx_t ctx) { const slong hlen = h->length; if (n == 0 || h->length == 0 || fmpz_is_zero(h->coeffs + 0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_invsqrt). Division by zero.\n"); } if (!fmpz_is_one(h->coeffs + 0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_invsqrt_series). Constant term != 1.\n"); } if (hlen == 1) n = 1; if (g == h) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, n, ctx); _fmpz_mod_poly_invsqrt_series(t->coeffs, h->coeffs, hlen, n, ctx); _fmpz_mod_poly_set_length(t, n); _fmpz_mod_poly_normalise(t); fmpz_mod_poly_swap(g, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { _fmpz_mod_poly_fit_length(g, n); _fmpz_mod_poly_invsqrt_series(g->coeffs, h->coeffs, hlen, n, ctx); _fmpz_mod_poly_set_length(g, n); _fmpz_mod_poly_normalise(g); } } flint-3.1.3/src/fmpz_mod_poly/io.c000066400000000000000000000055371461254215100170650ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" /* printing *******************************************************************/ int _fmpz_mod_poly_fprint(FILE * file, const fmpz *poly, slong len, const fmpz_t p) { int r; slong i; r = flint_fprintf(file, "%wd ", len); if (r <= 0) return r; r = fmpz_fprint(file, p); if (r <= 0) return r; if (len == 0) return r; r = flint_fprintf(file, " "); if (r <= 0) return r; for (i = 0; (r > 0) && (i < len); i++) { r = flint_fprintf(file, " "); if (r <= 0) return r; r = fmpz_fprint(file, poly + i); if (r <= 0) return r; } return r; } int fmpz_mod_poly_fprint(FILE * file, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return _fmpz_mod_poly_fprint(file, poly->coeffs, poly->length, fmpz_mod_ctx_modulus(ctx)); } int _fmpz_mod_poly_print(const fmpz *poly, slong len, const fmpz_t p) { return _fmpz_mod_poly_fprint(stdout, poly, len, p); } int fmpz_mod_poly_print(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return fmpz_mod_poly_fprint(stdout, poly, ctx); } int fmpz_mod_poly_fprint_pretty(FILE * file, const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx) { return _fmpz_poly_fprint_pretty(file, poly->coeffs, poly->length, x); } int fmpz_mod_poly_print_pretty(const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx) { return fmpz_mod_poly_fprint_pretty(stdout, poly, x, ctx); } /* reading ********************************************************************/ int fmpz_mod_poly_fread(FILE * f, fmpz_mod_poly_t poly, fmpz_mod_ctx_t ctx) { int success = 0; slong i, length; fmpz_t coeff; fmpz_init(coeff); poly->length = 0; if (flint_fscanf(f, "%wd", &length) != 1) goto cleanup; if (!fmpz_fread(f, coeff)) goto cleanup; if (fmpz_cmp_ui(coeff, 2) < 0) goto cleanup; fmpz_mod_ctx_set_modulus(ctx, coeff); fmpz_mod_poly_fit_length(poly, length, ctx); for (i = 0; i < length; i++) { if (!fmpz_fread(f, coeff)) goto cleanup; fmpz_mod_poly_set_coeff_fmpz(poly, i, coeff, ctx); } poly->length = length; _fmpz_mod_poly_normalise(poly); success = 1; cleanup: fmpz_clear(coeff); return success; } flint-3.1.3/src/fmpz_mod_poly/is_canonical.c000066400000000000000000000014601461254215100210670ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" int fmpz_mod_poly_is_canonical(const fmpz_mod_poly_t A, const fmpz_mod_ctx_t ctx) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (!fmpz_mod_is_canonical(A->coeffs + i, ctx)) return 0; if (fmpz_is_zero(A->coeffs + i) && i + 1 == A->length) return 0; } return 1; } flint-3.1.3/src/fmpz_mod_poly/make_monic.c000066400000000000000000000020211461254215100205410ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_make_monic(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { const slong len = poly->length; fmpz_t inv; if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } fmpz_init(inv); fmpz_invmod(inv, fmpz_mod_poly_lead(poly, ctx), fmpz_mod_ctx_modulus(ctx)); fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_scalar_mul_fmpz(res->coeffs, poly->coeffs, len, inv, ctx); fmpz_clear(inv); } flint-3.1.3/src/fmpz_mod_poly/make_monic_f.c000066400000000000000000000020031461254215100210460ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_make_monic_f(fmpz_t f, fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { const slong len = poly->length; fmpz_t inv; if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } fmpz_init(inv); fmpz_gcdinv(f, inv, fmpz_mod_poly_lead(poly, ctx), fmpz_mod_ctx_modulus(ctx)); fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_scalar_mul_fmpz(res->coeffs, poly->coeffs, len, inv, ctx); fmpz_clear(inv); } flint-3.1.3/src/fmpz_mod_poly/minpoly.c000066400000000000000000000132231461254215100201340ustar00rootroot00000000000000/* This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /****************************************************************************** Authored 2016 by Daniel S. Roche; US Government work in the public domain. ******************************************************************************/ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_minpoly_bm(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) { fmpz *buf, *curpoly, *prevpoly; slong curlen, prevlen; fmpz_t disc; slong i, m; buf = _fmpz_vec_init(len + 1); curpoly = poly; _fmpz_vec_zero(curpoly, len + 1); prevpoly = buf; fmpz_init(disc); fmpz_one(curpoly + 0); curlen = 1; fmpz_one(prevpoly + 0); prevlen = 1; m = -1; /* m = last switching point */ for (i = 0; i < len; ++i) { /* compute next discrepancy */ _fmpz_vec_dot(disc, curpoly, seq + (i - curlen + 1), curlen); fmpz_mod_set_fmpz(disc, disc, ctx); if (fmpz_is_zero(disc)) { } else if (i - m <= curlen - prevlen) { /* quick update; no switch, curlen doesn't change. */ slong pos = (curlen - prevlen) - (i - m); _fmpz_vec_scalar_addmul_fmpz(curpoly + pos, prevpoly, prevlen, disc); _fmpz_mod_vec_set_fmpz_vec(curpoly + pos, curpoly + pos, prevlen, ctx); } else { /* switching update */ slong pos = (i - m) - (curlen - prevlen); _fmpz_mod_vec_scalar_mul_fmpz_mod(prevpoly, prevpoly, prevlen, disc, ctx); _fmpz_mod_poly_add(prevpoly + pos, prevpoly + pos, FLINT_MAX(0, prevlen - pos), curpoly, curlen, ctx); prevlen = curlen + pos; fmpz_mod_neg(disc, disc, ctx); fmpz_mod_inv(disc, disc, ctx); _fmpz_mod_vec_scalar_mul_fmpz_mod(curpoly, curpoly, curlen, disc, ctx); FMPZ_VEC_SWAP(curpoly, curlen, prevpoly, prevlen); m = i; } } /* make curpoly monic and copy to poly if necessary */ fmpz_mod_inv(disc, curpoly + (curlen - 1), ctx); _fmpz_mod_poly_scalar_mul_fmpz(poly, curpoly, curlen, disc, ctx); _fmpz_vec_clear(buf, len + 1); fmpz_clear(disc); return curlen; } void fmpz_mod_poly_minpoly_bm(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, len + 1, ctx); poly->length = _fmpz_mod_poly_minpoly_bm(poly->coeffs, seq, len, ctx); } slong _fmpz_mod_poly_minpoly_hgcd(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) { fmpz *buf, *f, *g, *A, *B; fmpz* M[4]; slong lenM[4]; slong buflen, lenA, lenB, len_poly, leng; int i; M[0] = poly; buflen = 7 * len + 5; /* for f, g, A, B, M[1], M[2], M[3] */ buf = _fmpz_vec_init(buflen); f = buf; g = f + (len + 1); A = g + len; B = A + (len + 1); M[1] = B + len; M[2] = M[1] + (len + 1); M[3] = M[2] + (len + 1); /* f = x^len */ fmpz_one(f + len); /* g = reversal of seq */ for (i = 0; i < len; ++i) fmpz_set(g + i, seq + (len - i - 1)); leng = len; FMPZ_VEC_NORM(g, leng); /* leng is invalid intput for hgcd. todo: change hgcd to allow this? */ if (leng == 0) { fmpz_one(M[0]); fmpz_one(M[3]); lenM[0] = lenM[3] = 1; lenM[1] = lenM[2] = 0; lenA = len + 1; _fmpz_vec_set(A, f, lenA); lenB = leng; _fmpz_vec_set(B, g, leng); } else { _fmpz_mod_poly_hgcd(M, lenM, A, &lenA, B, &lenB, f, len + 1, g, leng, ctx); } len_poly = lenM[0]; /* one more step may be necessary */ if (len_poly <= lenB) { slong quo_len = lenA - lenB + 1; fmpz_mod_inv(buf, B + (lenB - 1), ctx); _fmpz_mod_poly_divrem(M[2], M[3], A, lenA, B, lenB, buf, ctx); if (len_poly >= quo_len) { _fmpz_mod_poly_mul(M[3], poly, len_poly, M[2], quo_len, ctx); } else { _fmpz_mod_poly_mul(M[3], M[2], quo_len, poly, len_poly, ctx); } len_poly += quo_len - 1; _fmpz_mod_poly_add(poly, M[3], len_poly, M[1], lenM[1], ctx); } /* make poly monic */ fmpz_mod_inv(buf, poly + (len_poly - 1), ctx); _fmpz_mod_poly_scalar_mul_fmpz(poly, poly, len_poly, buf, ctx); _fmpz_vec_clear(buf, buflen); return len_poly; } void fmpz_mod_poly_minpoly_hgcd(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, len + 1, ctx); poly->length = _fmpz_mod_poly_minpoly_hgcd(poly->coeffs, seq, len, ctx); } slong _fmpz_mod_poly_minpoly(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) { if (len < FLINT_MAX(200, 530-22*fmpz_size(fmpz_mod_ctx_modulus(ctx)))) return _fmpz_mod_poly_minpoly_bm(poly, seq, len, ctx); else return _fmpz_mod_poly_minpoly_hgcd(poly, seq, len, ctx); } void fmpz_mod_poly_minpoly(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, len+1, ctx); poly->length = _fmpz_mod_poly_minpoly(poly->coeffs, seq, len, ctx); } flint-3.1.3/src/fmpz_mod_poly/mul.c000066400000000000000000000037451461254215100172520ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_mul(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx) { _fmpz_poly_mul(res, poly1, len1, poly2, len2); _fmpz_mod_vec_set_fmpz_vec(res, res, len1 + len2 - 1, ctx); } void fmpz_mod_poly_mul(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) { const slong len1 = poly1->length; const slong len2 = poly2->length; const slong lenr = len1 + len2 - 1; if ((len1 == 0) || (len2 == 0)) { fmpz_mod_poly_zero(res, ctx); return; } if ((res == poly1) || (res == poly2)) { fmpz *t = _fmpz_vec_init(lenr); if (len1 >= len2) _fmpz_mod_poly_mul(t, poly1->coeffs, len1, poly2->coeffs, len2, ctx); else _fmpz_mod_poly_mul(t, poly2->coeffs, len2, poly1->coeffs, len1, ctx); _fmpz_vec_clear(res->coeffs, res->alloc); res->alloc = lenr; res->length = lenr; res->coeffs = t; } else { fmpz_mod_poly_fit_length(res, lenr, ctx); if (len1 >= len2) _fmpz_mod_poly_mul(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); else _fmpz_mod_poly_mul(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, ctx); _fmpz_mod_poly_set_length(res, lenr); } _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/mulhigh.c000066400000000000000000000040121461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_mulhigh(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong start, const fmpz_mod_ctx_t ctx) { slong len1, len2, len_out; len1 = poly1->length; len2 = poly2->length; len_out = len1 + len2 - 1; if (start == 0) { fmpz_mod_poly_mul(res, poly1, poly2, ctx); return; } if (len1 < 1 || len2 < 1 || start >= len_out) { fmpz_mod_poly_zero(res, ctx); return; } if (res == poly1 || res == poly2) { fmpz_mod_poly_t temp; fmpz_mod_poly_init2(temp, len_out, ctx); if (len1 >= len2) _fmpz_poly_mulhigh(temp->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, start); else _fmpz_poly_mulhigh(temp->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, start); fmpz_mod_poly_swap(temp, res, ctx); fmpz_mod_poly_clear(temp, ctx); } else { fmpz_mod_poly_fit_length(res, len_out, ctx); if (len1 >= len2) _fmpz_poly_mulhigh(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, start); else _fmpz_poly_mulhigh(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, start); } _fmpz_mod_vec_set_fmpz_vec(res->coeffs, res->coeffs, len_out, ctx); _fmpz_mod_poly_set_length(res, len_out); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/mullow.c000066400000000000000000000041031461254215100177610ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_mullow(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, slong n, const fmpz_mod_ctx_t ctx) { _fmpz_poly_mullow(res, poly1, len1, poly2, len2, n); _fmpz_mod_vec_set_fmpz_vec(res, res, n, ctx); } void fmpz_mod_poly_mullow(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) { const slong len1 = poly1->length; const slong len2 = poly2->length; if ((len1 == 0) || (len2 == 0) || (n == 0)) { fmpz_mod_poly_zero(res, ctx); return; } n = FLINT_MIN(n, len1 + len2 - 1); if ((res == poly1) || (res == poly2)) { fmpz *t = _fmpz_vec_init(n); if (len1 >= len2) _fmpz_mod_poly_mullow(t, poly1->coeffs, len1, poly2->coeffs, len2, n, ctx); else _fmpz_mod_poly_mullow(t, poly2->coeffs, len2, poly1->coeffs, len1, n, ctx); _fmpz_vec_clear(res->coeffs, res->alloc); res->coeffs = t; res->alloc = n; res->length = n; _fmpz_mod_poly_normalise(res); } else { fmpz_mod_poly_fit_length(res, n, ctx); if (len1 >= len2) _fmpz_mod_poly_mullow(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, ctx); else _fmpz_mod_poly_mullow(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, n, ctx); _fmpz_mod_poly_set_length(res, n); _fmpz_mod_poly_normalise(res); } } flint-3.1.3/src/fmpz_mod_poly/mulmod.c000066400000000000000000000046521461254215100177500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_mulmod(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; fmpz_t invf; slong lenT, lenQ; lenT = len1 + len2 - 1; lenQ = lenT - lenf + 1; T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; if (len1 >= len2) _fmpz_mod_poly_mul(T, poly1, len1, poly2, len2, ctx); else _fmpz_mod_poly_mul(T, poly2, len2, poly1, len1, ctx); fmpz_init(invf); fmpz_mod_inv(invf, f + lenf - 1, ctx); _fmpz_mod_poly_divrem(Q, res, T, lenT, f, lenf, invf, ctx); _fmpz_vec_clear(T, lenT + lenQ); fmpz_clear(invf); } void fmpz_mod_poly_mulmod(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { slong len1, len2, lenf; fmpz * fcoeffs; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_mulmod). Divide by zero\n"); } if (lenf == 1 || len1 == 0 || len2 == 0) { fmpz_mod_poly_zero(res, ctx); return; } if (len1 + len2 - lenf > 0) { if (f == res) { fcoeffs = _fmpz_vec_init(lenf); _fmpz_vec_set(fcoeffs, f->coeffs, lenf); } else { fcoeffs = f->coeffs; } fmpz_mod_poly_fit_length(res, len1 + len2 - 1, ctx); _fmpz_mod_poly_mulmod(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fcoeffs, lenf, ctx); if (f == res) _fmpz_vec_clear(fcoeffs, lenf); _fmpz_mod_poly_set_length(res, lenf - 1); _fmpz_mod_poly_normalise(res); } else { fmpz_mod_poly_mul(res, poly1, poly2, ctx); } } flint-3.1.3/src/fmpz_mod_poly/mulmod_preinv.c000066400000000000000000000052471461254215100213340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_mulmod_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz* finv, slong lenfinv, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; slong lenT, lenQ; lenT = len1 + len2 - 1; lenQ = lenT - lenf + 1; T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; if (len1 >= len2) _fmpz_mod_poly_mul(T, poly1, len1, poly2, len2, ctx); else _fmpz_mod_poly_mul(T, poly2, len2, poly1, len1, ctx); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, lenT, f, lenf, finv, lenfinv, ctx); _fmpz_vec_clear(T, lenT + lenQ); } void fmpz_mod_poly_mulmod_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) { slong len1, len2, lenf; fmpz * fcoeffs; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_mulmod_preinv). Divide by zero\n"); } if (lenf <= len1 || lenf <= len2) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_mulmod_preinv). Input larger than modulus.\n"); } if (lenf == 1 || len1 == 0 || len2 == 0) { fmpz_mod_poly_zero(res, ctx); return; } if (len1 + len2 - lenf > 0) { if (f == res) { fcoeffs = _fmpz_vec_init(lenf); _fmpz_vec_set(fcoeffs, f->coeffs, lenf); } else fcoeffs = f->coeffs; fmpz_mod_poly_fit_length(res, len1 + len2 - 1, ctx); _fmpz_mod_poly_mulmod_preinv(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fcoeffs, lenf, finv->coeffs, finv->length, ctx); if (f == res) _fmpz_vec_clear(fcoeffs, lenf); _fmpz_mod_poly_set_length(res, lenf - 1); _fmpz_mod_poly_normalise(res); } else { fmpz_mod_poly_mul(res, poly1, poly2, ctx); } } flint-3.1.3/src/fmpz_mod_poly/neg.c000066400000000000000000000017071461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_neg(fmpz *res, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx) { _fmpz_mod_vec_neg(res, poly, len, ctx); } void fmpz_mod_poly_neg(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { const slong len = poly->length; fmpz_mod_poly_fit_length(res, len, ctx); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_neg(res->coeffs, poly->coeffs, poly->length, ctx); } flint-3.1.3/src/fmpz_mod_poly/one.c000066400000000000000000000012541461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_one(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, 1, ctx); fmpz_one(poly->coeffs + 0); _fmpz_mod_poly_set_length(poly, fmpz_is_one(fmpz_mod_ctx_modulus(ctx)) ? 0 : 1); } flint-3.1.3/src/fmpz_mod_poly/pow.c000066400000000000000000000067411461254215100172610ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_pow(fmpz *res, const fmpz *poly, slong len, ulong e, const fmpz_mod_ctx_t ctx) { ulong bit = ~((~UWORD(0)) >> 1); slong rlen; slong alloc = (slong) e * (len - 1) + 1; fmpz *v = _fmpz_vec_init(alloc); fmpz *R, *S, *T; /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, len} */ _fmpz_mod_poly_sqr(R, poly, len, ctx); rlen = 2 * len - 1; if ((bit & e)) { _fmpz_mod_poly_mul(S, R, rlen, poly, len, ctx); rlen += len - 1; T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _fmpz_mod_poly_sqr(S, R, rlen, ctx); rlen += rlen - 1; _fmpz_mod_poly_mul(R, S, rlen, poly, len, ctx); rlen += len - 1; } else { _fmpz_mod_poly_sqr(S, R, rlen, ctx); rlen += rlen - 1; T = R; R = S; S = T; } } _fmpz_vec_clear(v, alloc); } void fmpz_mod_poly_pow(fmpz_mod_poly_t rop, const fmpz_mod_poly_t op, ulong e, const fmpz_mod_ctx_t ctx) { const slong len = op->length; slong rlen; if ((len < 2) || (e < UWORD(3))) { if (e == UWORD(0)) fmpz_mod_poly_set_ui(rop, 1, ctx); else if (len == 0) fmpz_mod_poly_zero(rop, ctx); else if (len == 1) { fmpz_mod_poly_fit_length(rop, 1, ctx); fmpz_mod_pow_ui(rop->coeffs, op->coeffs, e, ctx); _fmpz_mod_poly_set_length(rop, 1); _fmpz_mod_poly_normalise(rop); } else if (e == UWORD(1)) fmpz_mod_poly_set(rop, op, ctx); else /* e == UWORD(2) */ fmpz_mod_poly_sqr(rop, op, ctx); return; } rlen = (slong) e * (len - 1) + 1; if (rop != op) { fmpz_mod_poly_fit_length(rop, rlen, ctx); _fmpz_mod_poly_pow(rop->coeffs, op->coeffs, len, e, ctx); _fmpz_mod_poly_set_length(rop, rlen); } else { fmpz *t = _fmpz_vec_init(rlen); _fmpz_mod_poly_pow(t, op->coeffs, len, e, ctx); _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = rlen; rop->length = rlen; } _fmpz_mod_poly_normalise(rop); } flint-3.1.3/src/fmpz_mod_poly/pow_trunc.c000066400000000000000000000051501461254215100204650ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) { _fmpz_mod_poly_pow_trunc_binexp(res, poly, e, trunc, ctx); } void fmpz_mod_poly_pow_trunc(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) { const slong len = poly->length; fmpz * q; int qcopy = 0; if (len < 2 || e < UWORD(3) || trunc == 0) { if (len == 0 || trunc == 0) { fmpz_mod_poly_zero(res, ctx); } else if (len == 1) { fmpz_mod_poly_fit_length(res, 1, ctx); fmpz_powm_ui(res->coeffs, poly->coeffs, e, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, 1); _fmpz_mod_poly_normalise(res); } else if (e == UWORD(0)) { fmpz_mod_poly_set_coeff_ui(res, 0, UWORD(1), ctx); _fmpz_mod_poly_set_length(res, 1); _fmpz_mod_poly_normalise(res); } else if (e == UWORD(1)) { fmpz_mod_poly_set(res, poly, ctx); fmpz_mod_poly_truncate(res, trunc, ctx); } else /* e == UWORD(2) */ fmpz_mod_poly_mullow(res, poly, poly, trunc, ctx); return; } if (poly->length < trunc) { q = _fmpz_vec_init(trunc); _fmpz_vec_set(q, poly->coeffs, poly->length); _fmpz_vec_zero(q + poly->length, trunc - poly->length); qcopy = 1; } else { q = poly->coeffs; } if (res != poly || qcopy) { fmpz_mod_poly_fit_length(res, trunc, ctx); _fmpz_mod_poly_pow_trunc(res->coeffs, q, e, trunc, ctx); } else { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, trunc, ctx); _fmpz_mod_poly_pow_trunc(t->coeffs, q, e, trunc, ctx); fmpz_mod_poly_swap(res, t, ctx); fmpz_mod_poly_clear(t, ctx); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/pow_trunc_binexp.c000066400000000000000000000100401461254215100220240ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_pow_trunc_binexp(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) { ulong bit = ~((~UWORD(0)) >> 1); fmpz * v = _fmpz_vec_init(trunc); fmpz * R, * S, * T; /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, len} */ _fmpz_mod_poly_mullow(R, poly, trunc, poly, trunc, trunc, ctx); if ((bit & e)) { _fmpz_mod_poly_mullow(S, R, trunc, poly, trunc, trunc, ctx); T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _fmpz_mod_poly_mullow(S, R, trunc, R, trunc, trunc, ctx); _fmpz_mod_poly_mullow(R, S, trunc, poly, trunc, trunc, ctx); } else { _fmpz_mod_poly_mullow(S, R, trunc, R, trunc, trunc, ctx); T = R; R = S; S = T; } } _fmpz_vec_clear(v, trunc); } void fmpz_mod_poly_pow_trunc_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx) { const slong len = poly->length; fmpz * q; int qcopy = 0; if (len < 2 || e < UWORD(3) || trunc == 0) { if (len == 0 || trunc == 0) { fmpz_mod_poly_zero(res, ctx); } else if (len == 1) { fmpz_mod_poly_fit_length(res, 1, ctx); fmpz_powm_ui(res->coeffs, poly->coeffs, e, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, 1); _fmpz_mod_poly_normalise(res); } else if (e == UWORD(0)) { fmpz_mod_poly_set_coeff_ui(res, 0, UWORD(1), ctx); _fmpz_mod_poly_set_length(res, 1); _fmpz_mod_poly_normalise(res); } else if (e == UWORD(1)) { fmpz_mod_poly_set(res, poly, ctx); fmpz_mod_poly_truncate(res, trunc, ctx); } else /* e == UWORD(2) */ fmpz_mod_poly_mullow(res, poly, poly, trunc, ctx); return; } if (poly->length < trunc) { q = _fmpz_vec_init(trunc); _fmpz_vec_set(q, poly->coeffs, poly->length); _fmpz_vec_zero(q + poly->length, trunc - poly->length); qcopy = 1; } else q = poly->coeffs; if (res != poly || qcopy) { fmpz_mod_poly_fit_length(res, trunc, ctx); _fmpz_mod_poly_pow_trunc_binexp(res->coeffs, q, e, trunc, ctx); } else { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, trunc, ctx); _fmpz_mod_poly_pow_trunc_binexp(t->coeffs, q, e, trunc, ctx); fmpz_mod_poly_swap(res, t, ctx); fmpz_mod_poly_clear(t, ctx); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/powers_mod_bsgs_threaded.c000077500000000000000000000146711461254215100235140ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" typedef struct { volatile slong * j; slong k; slong n; slong glen; slong ginvlen; const fmpz * g; const fmpz * ginv; fmpz ** res; const fmpz_mod_ctx_struct * ctx; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } fmpz_powers_preinv_arg_t; void _fmpz_mod_poly_powers_mod_preinv_worker(void * arg_ptr) { fmpz_powers_preinv_arg_t arg = *((fmpz_powers_preinv_arg_t *) arg_ptr); slong i, j, k = arg.k, n = arg.n; slong glen = arg.glen, ginvlen = arg.ginvlen; fmpz ** res = arg.res; const fmpz * g = arg.g, * ginv = arg.ginv; const fmpz_mod_ctx_struct * ctx = arg.ctx; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif j = *arg.j + k; *arg.j = j; #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (j >= n) return; if (glen == 2) /* special case, constant polynomials */ { for (i = j + 1; i < j + k && i < n; i++) { fmpz_mod_mul(res[i] + 0, res[j] + 0, res[i - j] + 0, ctx); } } else { for (i = j + 1; i < j + k && i < n; i++) _fmpz_mod_poly_mulmod_preinv(res[i], res[j], glen - 1, res[i - j], glen - 1, g, glen, ginv, ginvlen, ctx); } } } /* compute f^0, f^1, ..., f^(n-1) mod g, where g has length glen and f is reduced mod g and has length flen (possibly zero spaced) assumes res is an array of n arrays each with space for at least glen - 1 coefficients and that flen > 0 {ginv, ginvlen} must be set to the power series inverse of the reverse of g */ void _fmpz_mod_poly_powers_mod_preinv_threaded_pool(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads) { slong i, k, shared_j = 0; fmpz_powers_preinv_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif if (n == 0) return; if (n == 1) { if (glen > 1) fmpz_set_ui(res[0] + 0, 1); if (glen > 2) { for (i = 1; i < glen - 1; i++) fmpz_zero(res[0] + i); } return; } k = n_sqrt(n); /* compute baby steps */ _fmpz_mod_poly_powers_mod_preinv_naive(res, f, flen, k + 1, g, glen, ginv, ginvlen, ctx); /* compute giant steps */ /* f^(k*i) = f^(k*(i - 1))*f^k */ if (glen == 2) /* special case, constant polys */ { for (i = 2*k; i < n; i += k) { fmpz_mod_mul(res[i] + 0, res[i - k] + 0, res[k] + 0, ctx); } } else { for (i = 2*k; i < n; i += k) _fmpz_mod_poly_mulmod_preinv(res[i], res[i - k], glen - 1, res[k], glen - 1, g, glen, ginv, ginvlen, ctx); } args = (fmpz_powers_preinv_arg_t *) flint_malloc(sizeof(fmpz_powers_preinv_arg_t) * (num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].j = &shared_j; args[i].k = k; args[i].n = n; args[i].glen = glen; args[i].ginvlen = ginvlen; args[i].g = g; args[i].ginv = ginv; args[i].res = res; args[i].ctx = ctx; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif } #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif for (i = 0; i < num_threads; i++) thread_pool_wake(global_thread_pool, threads[i], 0, _fmpz_mod_poly_powers_mod_preinv_worker, &args[i]); _fmpz_mod_poly_powers_mod_preinv_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) thread_pool_wait(global_thread_pool, threads[i]); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif flint_free(args); } void fmpz_mod_poly_powers_mod_bsgs(fmpz_mod_poly_struct * res, const fmpz_mod_poly_t f, slong n, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t ginv; fmpz ** res_arr; thread_pool_handle * threads; slong num_threads; if (fmpz_mod_poly_length(g, ctx) == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_powers_mod_bsgs). Divide by zero.\n"); } if (fmpz_mod_poly_length(f, ctx) == 0 || fmpz_mod_poly_length(g, ctx) == 1) { if (n > 0) fmpz_mod_poly_one(res + 0, ctx); for (i = 1; i < n; i++) fmpz_mod_poly_zero(res + i, ctx); return; } if (fmpz_mod_poly_length(f, ctx) >= fmpz_mod_poly_length(g, ctx)) { fmpz_mod_poly_t q, r; fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_divrem(q, r, f, g, ctx); fmpz_mod_poly_powers_mod_naive(res, r, n, g, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); return; } res_arr = (fmpz **) flint_malloc(n*sizeof(fmpz *)); fmpz_mod_poly_init(ginv, ctx); for (i = 0; i < n; i++) { fmpz_mod_poly_fit_length(res + i, fmpz_mod_poly_length(g, ctx) - 1, ctx); res_arr[i] = res[i].coeffs; _fmpz_mod_poly_set_length(res + i, fmpz_mod_poly_length(g, ctx) - 1); } fmpz_mod_poly_reverse(ginv, g, fmpz_mod_poly_length(g, ctx), ctx); fmpz_mod_poly_inv_series(ginv, ginv, fmpz_mod_poly_length(g, ctx), ctx); num_threads = flint_request_threads(&threads, flint_get_num_threads()); _fmpz_mod_poly_powers_mod_preinv_threaded_pool(res_arr, f->coeffs, f->length, n, g->coeffs, g->length, ginv->coeffs, ginv->length, ctx, threads, num_threads); flint_give_back_threads(threads, num_threads); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); fmpz_mod_poly_clear(ginv, ctx); flint_free(res_arr); } flint-3.1.3/src/fmpz_mod_poly/powers_mod_naive.c000077500000000000000000000072231461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" /* compute f^0, f^1, ..., f^(n-1) mod g, where g has length glen and f is reduced mod g and has length flen (possibly zero spaced) assumes res is an array of n arrays each with space for at least glen - 1 coefficients and that flen > 0 {ginv, ginvlen} must be set to the power series inverse of the reverse of g */ void _fmpz_mod_poly_powers_mod_preinv_naive(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t ctx) { slong i; if (n == 0) return; /* f^0 = 1 */ if (glen > 1) fmpz_set_ui(res[0] + 0, 1); if (glen > 2) { for (i = 1; i < glen - 1; i++) fmpz_zero(res[0] + i); } if (n == 1) return; /* f^1 = f */ _fmpz_vec_set(res[1], f, flen); for (i = flen; i < glen - 1; i++) fmpz_zero(res[1] + i); if (n == 2) return; /* f^i = f^(i - 1)*f */ if (glen == 2) /* special case, constant polys */ { for (i = 2; i < n; i++) { fmpz_mod_mul(res[i] + 0, res[i - 1] + 0, res[1] + 0, ctx); } } else { for (i = 2; i < n; i++) _fmpz_mod_poly_mulmod_preinv(res[i], res[i - 1], glen - 1, res[1], glen - 1, g, glen, ginv, ginvlen, ctx); } } void fmpz_mod_poly_powers_mod_naive(fmpz_mod_poly_struct * res, const fmpz_mod_poly_t f, slong n, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t ginv; fmpz ** res_arr; if (fmpz_mod_poly_length(g, ctx) == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_powers_mod_naive). Divide by zero.\n"); } if (fmpz_mod_poly_length(f, ctx) == 0 || fmpz_mod_poly_length(g, ctx) == 1) { if (n > 0) fmpz_mod_poly_one(res + 0, ctx); for (i = 1; i < n; i++) fmpz_mod_poly_zero(res + i, ctx); return; } if (fmpz_mod_poly_length(f, ctx) >= fmpz_mod_poly_length(g, ctx)) { fmpz_mod_poly_t q, r; fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_divrem(q, r, f, g, ctx); fmpz_mod_poly_powers_mod_naive(res, r, n, g, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); return; } res_arr = (fmpz **) flint_malloc(n*sizeof(fmpz *)); fmpz_mod_poly_init(ginv, ctx); for (i = 0; i < n; i++) { fmpz_mod_poly_fit_length(res + i, fmpz_mod_poly_length(g, ctx) - 1, ctx); res_arr[i] = res[i].coeffs; _fmpz_mod_poly_set_length(res + i, fmpz_mod_poly_length(g, ctx) - 1); } fmpz_mod_poly_reverse(ginv, g, fmpz_mod_poly_length(g, ctx), ctx); fmpz_mod_poly_inv_series(ginv, ginv, fmpz_mod_poly_length(g, ctx), ctx); _fmpz_mod_poly_powers_mod_preinv_naive(res_arr, f->coeffs, f->length, n, g->coeffs, g->length, ginv->coeffs, ginv->length, ctx); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); fmpz_mod_poly_clear(ginv, ctx); flint_free(res_arr); } flint-3.1.3/src/fmpz_mod_poly/powmod_fmpz_binexp.c000066400000000000000000000101701461254215100223510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_powmod_fmpz_binexp(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; fmpz_t invf; slong lenT, lenQ; slong i; if (lenf == 2) { fmpz_mod_pow_fmpz(res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; fmpz_init(invf); fmpz_mod_inv(invf, f + lenf - 1, ctx); _fmpz_vec_set(res, poly, lenf - 1); for (i = fmpz_sizeinbase(e, 2) - 2; i >= 0; i--) { _fmpz_mod_poly_sqr(T, res, lenf - 1, ctx); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); if (fmpz_tstbit(e, i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, ctx); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); } } fmpz_clear(invf); _fmpz_vec_clear(T, lenT + lenQ); } void fmpz_mod_poly_powmod_fmpz_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { fmpz * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_powmod_fmpz_binexp). Divide by zero\n"); } if (lenf == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_powmod_fmpz_binexp). negative exp not implemented\n"); } if (len >= lenf) { fmpz_mod_poly_t t, r; fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_divrem(t, r, poly, f, ctx); fmpz_mod_poly_powmod_fmpz_binexp(res, r, e, f, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(r, ctx); return; } if (fmpz_abs_fits_ui(e)) { ulong exp = fmpz_get_ui(e); if (exp <= 2) { if (exp == UWORD(0)) { fmpz_mod_poly_fit_length(res, 1, ctx); fmpz_one(res->coeffs); _fmpz_mod_poly_set_length(res, 1); } else if (exp == UWORD(1)) { fmpz_mod_poly_set(res, poly, ctx); } else { fmpz_mod_poly_mulmod(res, poly, poly, f, ctx); } return; } } if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } if (poly->length < trunc) { q = _fmpz_vec_init(trunc); _fmpz_vec_set(q, poly->coeffs, len); _fmpz_vec_zero(q + len, trunc - len); qcopy = 1; } else { q = poly->coeffs; } if ((res == poly && !qcopy) || (res == f)) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_fmpz_binexp(t->coeffs, q, e, f->coeffs, lenf, ctx); fmpz_mod_poly_swap(res, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { fmpz_mod_poly_fit_length(res, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_fmpz_binexp(res->coeffs, q, e, f->coeffs, lenf, ctx); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/powmod_fmpz_binexp_preinv.c000066400000000000000000000105461461254215100237430ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz* finv, slong lenfinv, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; slong lenT, lenQ; slong i; if (lenf == 2) { fmpz_mod_pow_fmpz(res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; _fmpz_vec_set(res, poly, lenf - 1); for (i = fmpz_sizeinbase(e, 2) - 2; i >= 0; i--) { _fmpz_mod_poly_sqr(T, res, lenf - 1, ctx); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); if (fmpz_tstbit(e, i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, ctx); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); } } _fmpz_vec_clear(T, lenT + lenQ); } void fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) { fmpz * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_powmod_fmpz_binexp_preinv): Divide by zero.\n"); } if (lenf == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_powmod_fmpz_binexp_preinv): " "Negative exp not implemented\n"); } if (len >= lenf) { fmpz_mod_poly_t t, r; fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_divrem(t, r, poly, f, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res, r, e, f, finv, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(r, ctx); return; } if (fmpz_abs_fits_ui(e)) { ulong exp = fmpz_get_ui(e); if (exp <= 2) { if (exp == UWORD (0)) { fmpz_mod_poly_fit_length(res, 1, ctx); fmpz_one(res->coeffs); _fmpz_mod_poly_set_length(res, 1); } else if (exp == UWORD (1)) { fmpz_mod_poly_set(res, poly, ctx); } else { fmpz_mod_poly_mulmod_preinv(res, poly, poly, f, finv, ctx); } return; } } if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } if (poly->length < trunc) { q = _fmpz_vec_init(trunc); _fmpz_vec_set(q, poly->coeffs, len); _fmpz_vec_zero(q + len, trunc - len); qcopy = 1; } else q = poly->coeffs; if ((res == poly && !qcopy) || (res == f) || (res == finv)) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_fmpz_binexp_preinv(t->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); fmpz_mod_poly_swap(res, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { fmpz_mod_poly_fit_length(res, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_fmpz_binexp_preinv(res->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/powmod_linear_fmpz_preinv.c000066400000000000000000000066061461254215100237320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" static void _fmpz_mod_poly_powmod_linear_fmpz_preinv( fmpz * res, const fmpz_t a, const fmpz_t e, const fmpz * f, slong lenf, const fmpz* finv, slong lenfinv, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; slong lenT = 2 * lenf - 3; slong lenQ = lenT - lenf + 1; slong i, j; fmpz_t t, lcinv; FLINT_ASSERT(lenf > 1); FLINT_ASSERT(!fmpz_is_zero(e)); fmpz_init(t); if (lenf <= 2) { fmpz_mod_mul(t, f + 0, finv + 0, ctx); fmpz_mod_sub(t, a, t, ctx); fmpz_mod_pow_fmpz(res + 0, t, e, ctx); fmpz_clear(t); return; } fmpz_init(lcinv); T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; _fmpz_vec_zero(res, lenf - 1); fmpz_set(res + 0, a); fmpz_one(res + 1); for (i = fmpz_sizeinbase(e, 2) - 2; i >= 0; i--) { _fmpz_mod_poly_sqr(T, res, lenf - 1, ctx); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); if (fmpz_tstbit(e, i)) { j = lenf - 1; fmpz_mod_mul(lcinv, finv + 0, res + j - 1, ctx); fmpz_mod_neg(lcinv, lcinv, ctx); for (j--; j > 0; j--) { fmpz_mul(t, a, res + j); fmpz_addmul(t, lcinv, f + j); fmpz_add(t, t, res + j - 1); fmpz_mod_set_fmpz(res + j, t, ctx); } fmpz_mul(t, a, res + j); fmpz_addmul(t, lcinv, f + j); fmpz_mod_set_fmpz(res + j, t, ctx); } } fmpz_clear(lcinv); fmpz_clear(t); _fmpz_vec_clear(T, lenT + lenQ); } /* res = (x+a)^e mod f */ void fmpz_mod_poly_powmod_linear_fmpz_preinv( fmpz_mod_poly_t res, const fmpz_t a, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) { slong lenf = f->length; slong trunc = lenf - 1; int sgn = fmpz_sgn(e); fmpz_mod_poly_t tmp; if (lenf < 2) { fmpz_mod_poly_zero(res, ctx); return; } if (sgn < 0) { flint_throw(FLINT_ERROR, "fmpz_mod_poly_powmod_linear_fmpz_preinv: " "negative exp not implemented"); } if (sgn == 0) { fmpz_mod_poly_one(res, ctx); return; } if (res == f || res == finv) { fmpz_mod_poly_init2(tmp, trunc, ctx); _fmpz_mod_poly_powmod_linear_fmpz_preinv(tmp->coeffs, a, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); fmpz_mod_poly_swap(res, tmp, ctx); fmpz_mod_poly_clear(tmp, ctx); } else { fmpz_mod_poly_fit_length(res, trunc, ctx); _fmpz_mod_poly_powmod_linear_fmpz_preinv(res->coeffs, a, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/powmod_ui_binexp.c000066400000000000000000000072641461254215100220240ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_powmod_ui_binexp(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; fmpz_t invf; slong lenT, lenQ; int i; if (lenf == 2) { fmpz_mod_pow_ui(res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; fmpz_init(invf); fmpz_mod_inv(invf, f + lenf - 1, ctx); _fmpz_vec_set(res, poly, lenf - 1); for (i = ((int) FLINT_BIT_COUNT(e) - 2); i >= 0; i--) { _fmpz_mod_poly_sqr(T, res, lenf - 1, ctx); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); if (e & (UWORD(1) << i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, ctx); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); } } fmpz_clear(invf); _fmpz_vec_clear(T, lenT + lenQ); } void fmpz_mod_poly_powmod_ui_binexp(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { fmpz * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_powmod). Divide by zero\n"); } if (lenf == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (len >= lenf) { fmpz_mod_poly_t t, r; fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_divrem(t, r, poly, f, ctx); fmpz_mod_poly_powmod_ui_binexp(res, r, e, f, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(r, ctx); return; } if (e <= 2) { if (e == UWORD(0)) { fmpz_mod_poly_fit_length(res, 1, ctx); fmpz_one(res->coeffs); _fmpz_mod_poly_set_length(res, 1); } else if (e == UWORD(1)) { fmpz_mod_poly_set(res, poly, ctx); } else { fmpz_mod_poly_mulmod(res, poly, poly, f, ctx); } return; } if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } if (len < trunc) { q = _fmpz_vec_init(trunc); _fmpz_vec_set(q, poly->coeffs, len); _fmpz_vec_zero(q + len, trunc - len); qcopy = 1; } else q = poly->coeffs; if ((res == poly && !qcopy) || (res == f)) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_ui_binexp(t->coeffs, q, e, f->coeffs, lenf, ctx); fmpz_mod_poly_swap(res, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { fmpz_mod_poly_fit_length(res, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_ui_binexp(res->coeffs, q, e, f->coeffs, lenf, ctx); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/powmod_ui_binexp_preinv.c000066400000000000000000000100071461254215100233740ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz * finv, slong lenfinv, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; slong lenT, lenQ; int i; if (lenf == 2) { fmpz_mod_pow_ui(res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; _fmpz_vec_set(res, poly, lenf - 1); for (i = ((int) FLINT_BIT_COUNT(e) - 2); i >= 0; i--) { _fmpz_mod_poly_sqr(T, res, lenf - 1, ctx); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); if (e & (UWORD (1) << i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, ctx); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); } } _fmpz_vec_clear(T, lenT + lenQ); } void fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) { fmpz * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_powmod_ui_binexp_preinv): " "Divide by zero\n"); } if (lenf == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (len >= lenf) { fmpz_mod_poly_t t, r; fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_divrem(t, r, poly, f, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(res, r, e, f, finv, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(r, ctx); return; } if (e <= 2) { if (e == UWORD (0)) { fmpz_mod_poly_fit_length(res, 1, ctx); fmpz_one(res->coeffs); _fmpz_mod_poly_set_length(res, 1); } else if (e == UWORD (1)) { fmpz_mod_poly_set(res, poly, ctx); } else { fmpz_mod_poly_mulmod_preinv(res, poly, poly, f, finv, ctx); } return; } if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } if (len < trunc) { q = _fmpz_vec_init(trunc); _fmpz_vec_set(q, poly->coeffs, len); _fmpz_vec_zero(q + len, trunc - len); qcopy = 1; } else { q = poly->coeffs; } if ((res == poly && !qcopy) || (res == f) || (res == finv)) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_ui_binexp_preinv(t->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); fmpz_mod_poly_swap(res, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { fmpz_mod_poly_fit_length(res, 2*lenf - 3, ctx); _fmpz_mod_poly_powmod_ui_binexp_preinv(res->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/powmod_x_fmpz_preinv.c000066400000000000000000000122551461254215100227240ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz * res, const fmpz_t e, const fmpz * f, slong lenf, const fmpz* finv, slong lenfinv, const fmpz_mod_ctx_t ctx) { fmpz * T, * Q; slong lenT, lenQ; slong i, window, l, c; lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; fmpz_one(res); _fmpz_vec_zero(res + 1, lenf - 2); l = z_sizeinbase(lenf - 1, 2) - 2; window = (WORD(1) << l); c = l; i = fmpz_sizeinbase(e, 2) - 2; if (i <= l) { window = (WORD(1) << i); c = i; l = i; } if (c == 0) { _fmpz_mod_poly_shift_left(T, res, lenf - 1, window); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, ctx); c = l + 1; window = WORD(0); } for (; i >= 0; i--) { _fmpz_mod_poly_sqr(T, res, lenf - 1, ctx); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); c--; if (fmpz_tstbit(e, i)) { if (window == WORD(0) && i <= l - 1) c = i; if ( c >= 0) window = window | (WORD(1) << c); } else if (window == WORD(0)) c = l + 1; if (c == 0) { _fmpz_mod_poly_shift_left(T, res, lenf - 1, window); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, ctx); c = l + 1; window = WORD(0); } } _fmpz_vec_clear(T, lenT + lenQ); } void fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz_mod_poly_t res, const fmpz_t e, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx) { slong lenf = f->length; slong trunc = lenf - 1; fmpz_mod_poly_t tmp; if (lenf == 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_powmod_x_fmpz_preinv): " "Divide by zero\n"); } if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "(fmpz_mod_poly_powmod_x_fmpz_preinv): " "Negative exp not implemented\n"); } if (lenf == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (lenf == 2) { fmpz_mod_poly_t r, poly; fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init2(poly, 2, ctx); fmpz_mod_poly_set_coeff_ui(poly, 1, 1, ctx); fmpz_mod_poly_divrem(tmp, r, poly, f, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res, r, e, f, finv, ctx); fmpz_mod_poly_clear(tmp, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly, ctx); return; } if (fmpz_abs_fits_ui(e)) { ulong exp = fmpz_get_ui(e); if (exp <= 2) { if (exp == UWORD(0)) { fmpz_mod_poly_fit_length(res, 1, ctx); fmpz_one(res->coeffs); _fmpz_mod_poly_set_length(res, 1); } else if (exp == UWORD(1)) { fmpz_mod_poly_t r; fmpz_mod_poly_init2(r, 2, ctx); fmpz_mod_poly_set_coeff_ui(r, 1, 1, ctx); fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_divrem(tmp, res, r, f, ctx); fmpz_mod_poly_clear(tmp, ctx); fmpz_mod_poly_clear(r, ctx); } else { fmpz_mod_poly_init2(tmp, 3, ctx); fmpz_mod_poly_set_coeff_ui(tmp, 1, 1, ctx); fmpz_mod_poly_mulmod(res, tmp, tmp, f, ctx); fmpz_mod_poly_clear(tmp, ctx); } return; } } if ((res == f) || (res == finv)) { fmpz_mod_poly_init2(tmp, trunc, ctx); _fmpz_mod_poly_powmod_x_fmpz_preinv(tmp->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); fmpz_mod_poly_swap(res, tmp, ctx); fmpz_mod_poly_clear(tmp, ctx); } else { fmpz_mod_poly_fit_length(res, trunc, ctx); _fmpz_mod_poly_powmod_x_fmpz_preinv(res->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/product_roots_fmpz_vec.c000066400000000000000000000041671461254215100232530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) { if (n == 0) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) fmpz_zero(poly); else fmpz_one(poly); } else if (n < 20) { slong i, j; if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) fmpz_zero(poly + n); else fmpz_one(poly + n); fmpz_mod_neg(poly + n - 1, xs, ctx); for (i = 1; i < n; i++) { fmpz_mod_mul(poly + n - i - 1, poly + n - i, xs + i, ctx); fmpz_mod_neg(poly + n - i - 1, poly + n - i - 1, ctx); for (j = 0; j < i - 1; j++) { fmpz_submul(poly + n - i + j, poly + n - i + j + 1, xs + i); fmpz_mod_set_fmpz(poly + n - i + j, poly + n - i + j, ctx); } fmpz_mod_sub(poly + n - 1, poly + n - 1, xs + i, ctx); } } else { slong m; fmpz * tmp; m = (n + 1) / 2; tmp = _fmpz_vec_init(n + 2); _fmpz_mod_poly_product_roots_fmpz_vec(tmp, xs, m, ctx); _fmpz_mod_poly_product_roots_fmpz_vec(tmp + m + 1, xs + m, n - m, ctx); _fmpz_mod_poly_mul(poly, tmp, m + 1, tmp + m + 1, n - m + 1, ctx); _fmpz_vec_clear(tmp, n + 2); } } void fmpz_mod_poly_product_roots_fmpz_vec( fmpz_mod_poly_t poly, const fmpz * xs, slong xlen, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, xlen + 1, ctx); _fmpz_mod_poly_product_roots_fmpz_vec(poly->coeffs, xs, xlen, ctx); _fmpz_mod_poly_set_length(poly, xlen + 1); } flint-3.1.3/src/fmpz_mod_poly/profile/000077500000000000000000000000001461254215100177405ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_poly/profile/p-gcd.c000066400000000000000000000145401461254215100211020ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "profiler.h" /* Definitions for the parameters of the timing process. lenlo Minimum length lenhi Maximum length lenh Ratio for the length bitslo Minimum bit size bitshi Maximum bit size bitsh Step size for the bit size cols Number of different lengths rows Number of different bit sizes cpumin Minimum number of ms spent on each test case ncases Number of test cases per point (length, bit size) nalgs Number of algorithms img Whether an RGB coloured image should be produced imgname File name for image */ #define lenlo 1 #define lenhi 2000 #define lenr 1.2 #define bitslo 16 #define bitshi 640 #define bitsr 1.2 #define cols (slong) (ceil(log((double)(lenhi/lenlo))/log((double)lenr))) #define rows (slong) (ceil(log((double)(bitshi/bitslo))/log((double)bitsr))) #define cpumin 10 #define ncases 1 #define nalgs 2 #define img 1 #define imgname "out.ppm" /* Write a binary 24-bit ppm image. */ int write_rgb_ppm(const char* file_name, unsigned char* pixels, unsigned int width, unsigned int height) { FILE* file = fopen(file_name, "wb"); if (file == NULL) return -1; flint_fprintf(file, "P6\n%d %d\n255\n", width, height); fwrite(pixels, sizeof(unsigned char), width * height * 3, file); fclose(file); return 0; } int main(void) { int i, j, len, bits, maxcols, maxrows; int X[rows][cols]; double T[rows][cols][nalgs]; fmpz_mod_poly_t f, g, h; fmpz_t p; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_mod_ctx_init_ui(ctx, 2); for (len = lenlo, j = 0; len <= lenhi; len = ceil((double)len*lenr), j++) { slong s[nalgs]; for (bits = bitslo, i = 0; bits <= bitshi; bits = ceil((double)bits*bitsr), i++) { int c, n, reps = 0; for (c = 0; c < nalgs; c++) s[c] = WORD(0); do { fmpz_randbits(p, state, bits); } while (!fmpz_is_probabprime(p)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init2(f, len, ctx); fmpz_mod_poly_init2(g, len, ctx); fmpz_mod_poly_init2(h, len, ctx); for (n = 0; n < ncases; n++) { timeit_t t[nalgs]; int l, loops = 1; /* Construct random polynomials f and g */ { slong k; for (k = 0; k < len; k++) { fmpz_randm(f->coeffs + k, state, p); fmpz_randm(g->coeffs + k, state, p); } while ((f->coeffs)[len-1] == WORD(0)) fmpz_randm(f->coeffs + (len - 1), state, p); while ((g->coeffs)[len-1] == WORD(0)) fmpz_randm(g->coeffs + (len - 1), state, p); f->length = len; g->length = len; } loop: timeit_start(t[0]); for (l = 0; l < loops; l++) /* fmpz_mod_poly_gcd_euclidean(h, f, g, ctx); */ fmpz_mod_poly_gcd(h, f, g, ctx); timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) /* fmpz_mod_poly_gcd_hgcd(h, f, g, ctx); */ fmpz_mod_poly_gcd(h, f, g, ctx); timeit_stop(t[1]); for (c = 0; c < nalgs; c++) if (t[c]->cpu <= cpumin) { loops *= 2; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]->cpu; reps += loops; } for (c = 0; c < nalgs; c++) T[i][j][c] = s[c] / (double) reps; if (s[0] <= s[1]) X[i][j] = 0; else X[i][j] = 1; fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); } { slong sum = 0, c; for (c = 0; c < nalgs; c++) sum += s[c]; flint_printf("len = %d, time = %wdms\n", len, sum), fflush(stdout); } } fmpz_clear(p); fmpz_mod_ctx_clear(ctx); maxcols = j; maxrows = i; /* Print 2-D ASCII image of the winning algorithms */ for (i = 0; i < maxrows; i++) { for (j = 0; j < maxcols; j++) flint_printf("%d", X[i][j]); flint_printf("\n"); } /* Print 2-D coloured image to file */ if (img) { unsigned char * PIXELS; int k; PIXELS = (unsigned char *) flint_malloc(3 * maxrows * maxcols * sizeof(unsigned char)); k = 0; for (i = 0; i < maxrows; i++) { for (j = 0; j < maxcols; j++) { double max = DBL_MIN, v[nalgs]; int m; for (m = 0; m < nalgs; m++) { v[m] = T[i][j][m] - T[i][j][X[i][j]]; if (v[m] > max) max = v[m]; } for (m = 0; m < nalgs; m++) { v[m] = (max - v[m]) / max; PIXELS[k++] = (unsigned char) (v[m] * 255); } for (; m < 3; m++) PIXELS[k++] = (unsigned char) 0; } } k = write_rgb_ppm(imgname, PIXELS, maxcols, maxrows); flint_free(PIXELS); if (k) { flint_printf("Exception: writing ppm image failed\n"); } } flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_mod_poly/profile/p-invert.c000066400000000000000000000036001461254215100216470ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "profiler.h" int main(void) { slong len, iter; fmpz_mod_poly_t f, g, q, r; fmpz_t N, c, one; fmpz_mod_ctx_t ctx; timeit_t t; char N_str[201] = "29799904256775982671863388319999573561548825027149399972531599612392671227006866151136667908641695103422986028076864929902803267437351318167549013218980573566942647077444419419003164546362008247462049"; FLINT_TEST_INIT(state); len = 36865; fmpz_init(N); fmpz_init(c); fmpz_init(one); fmpz_set_str(N, N_str, 10); fmpz_mod_ctx_init(ctx, N); fmpz_set_ui(one, 1); fmpz_mod_poly_init2(f, len, ctx); fmpz_mod_poly_init2(g, 2*len - 1, ctx); fmpz_mod_poly_init2(q, len, ctx); fmpz_mod_poly_init2(r, len - 1, ctx); /* Construct random polynomial f */ fmpz_mod_poly_randtest(f, state, len, ctx); fmpz_mod_poly_set_coeff_fmpz(g, 2*len - 2, one, ctx); /* Time inversion */ timeit_start(t); for (iter = 0; iter < 10; iter++) fmpz_mod_poly_inv_series(q, f, len, ctx); timeit_stop(t); flint_printf("len = %wd, time = %wdms\n", len, ((slong) t->cpu)/10); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(N); fmpz_clear(c); fmpz_clear(one); fmpz_mod_ctx_clear(ctx); flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_mod_poly/profile/p-minpoly.c000066400000000000000000000104741461254215100220360ustar00rootroot00000000000000/* This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /****************************************************************************** Authored 2016 by Daniel S. Roche; US Government work in the public domain. ******************************************************************************/ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "profiler.h" #define NUMEX (10) #define BITSLOW (50) #define BITSINC (100) #define BITSHIGH (2000) #define MINCPU (10) #define TOLERANCE (1.05) #define TIME_INNER(ALG, TIMEVAR) do \ { \ /* warm-up */ \ for (i=0, curseq=seqs; icpu <= MINCPU); \ \ /* cool-down */ \ for (i=0, curseq=seqs; icpu) / (NUMEX * loops); \ } while(0) void time_algs(double* times, flint_rand_t state, const fmpz_mod_ctx_struct * primes, slong len) { fmpz_mod_poly_struct polys[NUMEX]; fmpz *seqs, *curseq, *gen; slong genlen = len/2, i, j, loops; timeit_t timer; seqs = _fmpz_vec_init(len*NUMEX); gen = _fmpz_vec_init(genlen); /* initialize polys and sequences */ for (i=0, curseq = seqs; i TOLERANCE*times[0]) lower = len; else if (lower > 0 && times[0] > TOLERANCE*times[1]) break; len = len*3/2; } upper = len; while (upper - lower + 1 > 3) { len = lower + (upper-lower)/3; len2 = lower + (upper-lower)*2/3; time_algs(times, state, primes, len); if (times[1] > TOLERANCE*times[0]) lower = len; else if (times[0] > TOLERANCE*times[1]) { upper = len; continue; } time_algs(times, state, primes, len2); if (times[1] > TOLERANCE*times[0]) lower = len2; else if (times[0] > TOLERANCE*times[1]) upper = len2; else if (lower < len) break; } flint_printf("bits: %wd, lower: %wd, upper: %wd\n", bits, lower, upper); fflush(stdout); } fmpz_clear(p); for (i=0; i. */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "profiler.h" int main(void) { slong len, iter; fmpz_mod_poly_t f, g, r; fmpz_t N; fmpz_mod_ctx_t ctx; timeit_t t; char N_str[201] = "29799904256775982671863388319999573561548825027149399972531599612392671227006866151136667908641695103422986028076864929902803267437351318167549013218980573566942647077444419419003164546362008247462049"; FLINT_TEST_INIT(state); len = 36865; fmpz_init(N); fmpz_set_str(N, N_str, 10); fmpz_mod_ctx_init(ctx, N); fmpz_mod_poly_init2(f, len, ctx); fmpz_mod_poly_init2(g, len, ctx); fmpz_mod_poly_init2(r, 2*len - 1, ctx); /* Construct random polynomials f, g */ fmpz_mod_poly_randtest(f, state, len, ctx); fmpz_mod_poly_randtest(g, state, len, ctx); /* Time multiplication */ timeit_start(t); for (iter = 0; iter < 10; iter++) fmpz_mod_poly_mul(r, f, g, ctx); timeit_stop(t); flint_printf("len = %wd, time = %wdms\n", len, ((slong) t->cpu)/10); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(N); fmpz_mod_ctx_clear(ctx); flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_mod_poly/profile/p-tree.c000066400000000000000000000032751461254215100213070ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "profiler.h" int main(void) { slong len, iter, i; fmpz_mod_poly_t f; fmpz * roots; fmpz_poly_struct ** tree; fmpz_t N; fmpz_mod_ctx_t ctx; timeit_t t; char N_str[201] = "29799904256775982671863388319999573561548825027149399972531599612392671227006866151136667908641695103422986028076864929902803267437351318167549013218980573566942647077444419419003164546362008247462049"; FLINT_TEST_INIT(state); len = 36865; fmpz_init(N); fmpz_set_str(N, N_str, 10); fmpz_mod_ctx_init(ctx, N); roots = _fmpz_vec_init(len); for (i = 0; i < len; i++) fmpz_randm(roots + i, state, N); fmpz_mod_poly_init(f, ctx); /* Time tree */ timeit_start(t); for (iter = 0; iter < 10; iter++) { tree = _fmpz_mod_poly_tree_alloc(len); _fmpz_mod_poly_tree_build(tree, roots, len, ctx); _fmpz_mod_poly_tree_free(tree, len); } timeit_stop(t); flint_printf("len = %wd, time = %wdms\n", len, ((slong) t->cpu)/10); fmpz_mod_poly_clear(f, ctx); _fmpz_vec_clear(roots, len); fmpz_clear(N); fmpz_mod_ctx_clear(ctx); flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_mod_poly/radix.c000066400000000000000000000141601461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_radix_init(fmpz **Rpow, fmpz **Rinv, const fmpz *R, slong lenR, slong k, const fmpz_t invL, const fmpz_mod_ctx_t ctx) { const slong degR = lenR - 1; slong i; fmpz_t invLP; fmpz *W; fmpz_init_set(invLP, invL); W = flint_malloc((WORD(1) << (k - 1)) * degR * sizeof(fmpz)); _fmpz_vec_set(Rpow[0], R, lenR); for (i = 1; i < k; i++) { _fmpz_mod_poly_sqr(Rpow[i], Rpow[i - 1], degR * (WORD(1) << (i - 1)) + 1, ctx); } for (i = 0; i < k; i++) { const slong lenQ = (WORD(1) << i) * degR; slong j; /* W := rev{Rpow[i], lenQ} */ for (j = 0; j < lenQ; j++) { W[j] = Rpow[i][lenQ - j]; } /* TODO: _fmpz_mod_poly_inv_series no longer accepts a precomputed inverse leading coefficient; add back a version that does this. _fmpz_mod_poly_inv_series(Rinv[i], W, lenQ, invLP, ctx); */ _fmpz_mod_poly_inv_series(Rinv[i], W, lenQ, lenQ, ctx); /* invLP := inv{lead{R^{2^i}}} */ if (i != k - 1) fmpz_mod_mul(invLP, invLP, invLP, ctx); } fmpz_clear(invLP); flint_free(W); } void fmpz_mod_poly_radix_init(fmpz_mod_poly_radix_t D, const fmpz_mod_poly_t R, slong degF, const fmpz_mod_ctx_t ctx) { const slong degR = R->length - 1; if (degF < degR) { D->k = 0; D->degR = degR; } else { const slong N = degF / degR; const slong k = FLINT_BIT_COUNT(N); /* k := ceil{log{N+1}} */ const slong lenV = degR * ((WORD(1) << k) - 1) + k; const slong lenW = degR * ((WORD(1) << k) - 1); slong i; D->V = _fmpz_vec_init(lenV + lenW); D->W = D->V + lenV; D->Rpow = flint_malloc(k * sizeof(fmpz *)); D->Rinv = flint_malloc(k * sizeof(fmpz *)); for (i = 0; i < k; i++) { D->Rpow[i] = D->V + (degR * ((WORD(1) << i) - 1) + i); D->Rinv[i] = D->W + (degR * ((WORD(1) << i) - 1)); } fmpz_init(&(D->invL)); fmpz_invmod(&(D->invL), R->coeffs + degR, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_radix_init(D->Rpow, D->Rinv, R->coeffs, degR + 1, k, &(D->invL), ctx); D->k = k; D->degR = degR; } } void fmpz_mod_poly_radix_clear(fmpz_mod_poly_radix_t D) { if (D->k) { const slong degR = D->degR; const slong k = D->k; const slong lenV = degR * ((WORD(1) << k) - 1) + k; const slong lenW = degR * ((WORD(1) << k) - 1); _fmpz_vec_clear(D->V, lenV + lenW); flint_free(D->Rpow); flint_free(D->Rinv); fmpz_clear(&(D->invL)); } } void _fmpz_mod_poly_radix(fmpz **B, const fmpz *F, fmpz **Rpow, fmpz **Rinv, slong degR, slong k, slong i, fmpz *W, const fmpz_mod_ctx_t ctx) { if (i == -1) { _fmpz_vec_set(B[k], F, degR); } else { const slong lenQ = (WORD(1) << i) * degR; fmpz *Frev = W; fmpz *Q = W + lenQ; fmpz *S = W; _fmpz_poly_reverse(Frev, F + lenQ, lenQ, lenQ); _fmpz_mod_poly_mullow(Q, Frev, lenQ, Rinv[i], lenQ, lenQ, ctx); _fmpz_poly_reverse(Q, Q, lenQ, lenQ); _fmpz_mod_poly_radix(B, Q, Rpow, Rinv, degR, k + (WORD(1) << i), i-1, W, ctx); _fmpz_mod_poly_mullow(S, Rpow[i], lenQ, Q, lenQ, lenQ, ctx); _fmpz_mod_poly_sub(S, F, lenQ, S, lenQ, ctx); _fmpz_mod_poly_radix(B, S, Rpow, Rinv, degR, k, i-1, W + lenQ, ctx); } } void fmpz_mod_poly_radix(fmpz_mod_poly_struct **B, const fmpz_mod_poly_t F, const fmpz_mod_poly_radix_t D, const fmpz_mod_ctx_t ctx) { const slong lenF = F->length; const slong degF = F->length - 1; const slong degR = D->degR; const slong N = degF / degR; if (N == 0) { fmpz_mod_poly_set(B[0], F, ctx); } else { const slong k = FLINT_BIT_COUNT(N); /* k := ceil{log{N+1}} */ const slong lenG = (WORD(1) << k) * degR; /* Padded size */ const slong t = (lenG - 1) / degR - N; /* Extra {degR}-blocks */ fmpz *G; /* Padded copy of F */ fmpz *T; /* Additional B[i] */ fmpz **C; /* Enlarged version of B */ fmpz *W; /* Temporary space */ slong i; if (lenF < lenG) { G = flint_malloc(lenG * sizeof(fmpz)); for (i = 0; i < lenF; i++) G[i] = F->coeffs[i]; flint_mpn_zero((mp_ptr) G + lenF, lenG - lenF); T = t ? _fmpz_vec_init(t * degR) : NULL; } else /* lenF == lenG */ { G = F->coeffs; T = NULL; } C = flint_malloc((N + 1 + t) * sizeof(fmpz *)); for (i = 0; i <= N; i++) { fmpz_mod_poly_fit_length(B[i], degR, ctx); C[i] = B[i]->coeffs; } for (i = 0; i < t; i++) { C[N + 1 + i] = T + i * degR; } W = _fmpz_vec_init(lenG); _fmpz_mod_poly_radix(C, G, D->Rpow, D->Rinv, degR, 0, k-1, W, ctx); _fmpz_vec_clear(W, lenG); for (i = 0; i <= N; i++) { _fmpz_mod_poly_set_length(B[i], degR); _fmpz_mod_poly_normalise(B[i]); } flint_free(C); if (lenF < lenG) { flint_free(G); } if (t) { _fmpz_vec_clear(T, t * degR); } } } flint-3.1.3/src/fmpz_mod_poly/randtest.c000066400000000000000000000150421461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2009 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_randtest(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_fit_length(f, len, ctx); for (i = 0; i < len; i++) fmpz_randm(f->coeffs + i, state, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(f, len); _fmpz_mod_poly_normalise(f); } void fmpz_mod_poly_randtest_monic(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { slong i; FLINT_ASSERT(len > 0); fmpz_mod_poly_fit_length(f, len, ctx); for (i = 0; i < len - 1; i++) fmpz_randm(f->coeffs + i, state, fmpz_mod_ctx_modulus(ctx)); fmpz_one(f->coeffs + len - 1); _fmpz_mod_poly_set_length(f, len); } static void fmpz_mod_poly_randtest_monic_sparse(fmpz_mod_poly_t poly, flint_rand_t state, slong len, slong nonzero, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_fit_length(poly, len, ctx); _fmpz_vec_zero(poly->coeffs, len); fmpz_randm(poly->coeffs + 0, state, fmpz_mod_ctx_modulus(ctx)); for (i = 1; i < nonzero; i++) fmpz_randm(poly->coeffs + n_randint(state, len - 1) + 1, state, fmpz_mod_ctx_modulus(ctx)); fmpz_set_ui(poly->coeffs + len - 1, 1); _fmpz_mod_poly_set_length(poly, len); } void fmpz_mod_poly_randtest_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { if (len == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_randtest_irreducible). len == 0.\n"); } do { fmpz_mod_poly_randtest(f, state, len, ctx); } while (fmpz_mod_poly_is_zero(f, ctx) || !fmpz_mod_poly_is_irreducible(f, ctx)); } void fmpz_mod_poly_randtest_monic_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { if (len == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_randtest_monic_irreducible). len == 0.\n"); } do { fmpz_mod_poly_randtest_monic(f, state, len, ctx); } while (fmpz_mod_poly_is_zero(f, ctx) || !fmpz_mod_poly_is_irreducible(f, ctx)); } void fmpz_mod_poly_randtest_not_zero(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { if (len == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_randtest_not_zero). len == 0.\n"); } do { fmpz_mod_poly_randtest(f, state, len, ctx); } while (fmpz_mod_poly_is_zero(f, ctx)); } static void fmpz_mod_poly_randtest_monic_irreducible_sparse(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { slong i = 0; slong terms = 3; do { i++; terms += ((i % 4) == 0); if (terms >= len) terms = 3; fmpz_mod_poly_randtest_monic_sparse(poly, state, len, terms, ctx); } while (fmpz_mod_poly_is_zero(poly, ctx) || !fmpz_mod_poly_is_irreducible(poly, ctx)); } void fmpz_mod_poly_randtest_trinomial(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { ulong k; fmpz_mod_poly_fit_length(poly, len, ctx); _fmpz_vec_zero(poly->coeffs, len); fmpz_randm(poly->coeffs, state, fmpz_mod_ctx_modulus(ctx)); k = (n_randtest(state) % (len - 2)) + 1; fmpz_randm(poly->coeffs + k, state, fmpz_mod_ctx_modulus(ctx)); fmpz_one(poly->coeffs + len - 1); _fmpz_mod_poly_set_length(poly, len); } void fmpz_mod_poly_randtest_pentomial(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, len, ctx); _fmpz_vec_zero(poly->coeffs, len); fmpz_randm(poly->coeffs, state, fmpz_mod_ctx_modulus(ctx)); fmpz_randm(poly->coeffs + 1, state, fmpz_mod_ctx_modulus(ctx)); fmpz_randm(poly->coeffs + 2, state, fmpz_mod_ctx_modulus(ctx)); fmpz_randm(poly->coeffs + 3, state, fmpz_mod_ctx_modulus(ctx)); fmpz_one(poly->coeffs + len - 1); _fmpz_mod_poly_set_length(poly, len); } int fmpz_mod_poly_randtest_trinomial_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, slong max_attempts, const fmpz_mod_ctx_t ctx) { slong i = 0; while (max_attempts == 0 || i < max_attempts) { fmpz_mod_poly_randtest_trinomial(poly, state, len, ctx); if (!fmpz_mod_poly_is_zero(poly, ctx) && fmpz_mod_poly_is_irreducible(poly, ctx)) { return 1; } i++; } return 0; } int fmpz_mod_poly_randtest_pentomial_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, slong max_attempts, const fmpz_mod_ctx_t ctx) { slong i = 0; while (max_attempts == 0 || i < max_attempts) { fmpz_mod_poly_randtest_pentomial(poly, state, len, ctx); if (!fmpz_mod_poly_is_zero(poly, ctx) && fmpz_mod_poly_is_irreducible(poly, ctx)) { return 1; } i++; } return 0; } void fmpz_mod_poly_randtest_sparse_irreducible(fmpz_mod_poly_t poly, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { if (len < 3) { fmpz_mod_poly_randtest_monic_irreducible(poly, state, len, ctx); return; } /* Try trinomials */ if (fmpz_mod_poly_randtest_trinomial_irreducible(poly, state, len, 2*len, ctx)) return; if (len < 5) { fmpz_mod_poly_randtest_monic_irreducible(poly, state, len, ctx); return; } /* Try pentomials */ if (fmpz_mod_poly_randtest_pentomial_irreducible(poly, state, len, 2*len, ctx)) return; /* Random monic sparse */ fmpz_mod_poly_randtest_monic_irreducible_sparse(poly, state, len, ctx); } flint-3.1.3/src/fmpz_mod_poly/randtest_monic_primitive.c000066400000000000000000000016471461254215100235550ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fq.h" void fmpz_mod_poly_randtest_monic_primitive(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx) { fq_ctx_t fqctx; fq_t X; int primitive = 0; while (!primitive) { fmpz_mod_poly_randtest_monic_irreducible(f, state, len, ctx); fq_ctx_init_modulus(fqctx, f, ctx, "X"); fq_init(X, fqctx); fq_gen(X, fqctx); primitive = fq_is_primitive(X, fqctx); fq_clear(X, fqctx); fq_ctx_clear(fqctx); } } flint-3.1.3/src/fmpz_mod_poly/realloc.c000066400000000000000000000025071461254215100200710ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_realloc(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx) { if (alloc == 0) /* Clear up, reinitialise */ { if (poly->coeffs) _fmpz_vec_clear(poly->coeffs, poly->alloc); poly->coeffs = NULL; poly->length = 0; poly->alloc = 0; return; } if (poly->alloc) /* Realloc */ { fmpz_mod_poly_truncate(poly, alloc, ctx); poly->coeffs = (fmpz *) flint_realloc(poly->coeffs, alloc * sizeof(fmpz)); if (alloc > poly->alloc) flint_mpn_zero((mp_ptr) (poly->coeffs + poly->alloc), alloc - poly->alloc); } else /* Nothing allocated already so do it now */ { poly->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); } poly->alloc = alloc; } flint-3.1.3/src/fmpz_mod_poly/rem.c000066400000000000000000000025321461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_rem(fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { fmpz * Q = _fmpz_vec_init(lenA - lenB + 1); _fmpz_mod_poly_divrem(Q, R, A, lenA, B, lenB, invB, ctx); _fmpz_vec_clear(Q, lenA - lenB + 1); } void fmpz_mod_poly_rem(fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t Q; fmpz_mod_poly_init(Q, ctx); fmpz_mod_poly_divrem(Q, R, A, B, ctx); fmpz_mod_poly_clear(Q, ctx); } void fmpz_mod_poly_rem_f(fmpz_t f, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t Q; fmpz_mod_poly_init(Q, ctx); fmpz_mod_poly_divrem_f(f, Q, R, A, B, ctx); fmpz_mod_poly_clear(Q, ctx); } flint-3.1.3/src/fmpz_mod_poly/rem_basecase.c000066400000000000000000000046221461254215100210610ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_rem_basecase(fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { fmpz_t q; slong iR; fmpz * W; TMP_INIT; TMP_START; fmpz_init(q); if (R != A) { /* cannot use R as it might not have enough space */ FMPZ_VEC_TMP_INIT(W, lenA); _fmpz_vec_set(W, A, lenA); } else { W = R; } for (iR = lenA - 1; iR >= lenB - 1; iR--) { if (!fmpz_is_zero(W + iR)) { fmpz_mul(q, W + iR, invB); fmpz_mod_set_fmpz(q, q, ctx); _fmpz_vec_scalar_submul_fmpz(W + (iR - lenB + 1), B, lenB, q); _fmpz_mod_vec_set_fmpz_vec(W + (iR - lenB + 1), W + (iR - lenB + 1), lenB, ctx); } } if (R != A) { _fmpz_vec_set(R, W, lenB - 1); FMPZ_VEC_TMP_CLEAR(W, lenA); } fmpz_clear(q); TMP_END; } void fmpz_mod_poly_rem_basecase(fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { const slong lenA = A->length, lenB = B->length; fmpz *r; fmpz_t invB; if (lenA < lenB) { fmpz_mod_poly_set(R, A, ctx); return; } fmpz_init(invB); fmpz_invmod(invB, B->coeffs + (lenB - 1), fmpz_mod_ctx_modulus(ctx)); if (R == B) { r = _fmpz_vec_init(lenB - 1); } else { fmpz_mod_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } _fmpz_mod_poly_rem_basecase(r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenB - 1; R->length = lenB - 1; } _fmpz_mod_poly_set_length(R, lenB - 1); _fmpz_mod_poly_normalise(R); fmpz_clear(invB); } flint-3.1.3/src/fmpz_mod_poly/remove.c000066400000000000000000000021551461254215100177440ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" ulong fmpz_mod_poly_remove(fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t q, r; ulong i = 0; fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); while (1) { if (f->length < g->length) break; fmpz_mod_poly_divrem(q, r, f, g, ctx); if (r->length == 0) fmpz_mod_poly_swap(q, f, ctx); else break; i++; } fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); return i; } flint-3.1.3/src/fmpz_mod_poly/resultant.c000066400000000000000000000027131461254215100204700ustar00rootroot00000000000000/* Copyright (C) 2011, 2014 William Hart Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr_poly.h" void _fmpz_mod_poly_resultant(fmpz_t res, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_mod_ctx_t ctx) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_poly_resultant(res, A, lenA, B, lenB, gr_ctx)); } void fmpz_mod_poly_resultant(fmpz_t res, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { if (A->length == 0 || B->length == 0) { fmpz_zero(res); } else if (A->length < B->length) { fmpz_mod_poly_resultant(res, B, A, ctx); if (((A->length | B->length) & 1) == 0) fmpz_mod_neg(res, res, ctx); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length; /* lenA >= lenB >= 1 */ _fmpz_mod_poly_resultant(res, A->coeffs, lenA, B->coeffs, lenB, ctx); } } flint-3.1.3/src/fmpz_mod_poly/reverse.c000066400000000000000000000027001461254215100201160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n) { if (res == poly) { slong i; for (i = 0; i < n / 2; i++) { fmpz t = res[i]; res[i] = res[n - 1 - i]; res[n - 1 - i] = t; } for (i = 0; i < n - len; i++) fmpz_zero(res + i); } else { slong i; for (i = 0; i < n - len; i++) fmpz_zero(res + i); for (i = 0; i < len; i++) fmpz_set(res + (n - len) + i, poly + (len - 1) - i); } } void fmpz_mod_poly_reverse(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) { slong len = FLINT_MIN(n, poly->length); if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } fmpz_mod_poly_fit_length(res, n, ctx); _fmpz_mod_poly_reverse(res->coeffs, poly->coeffs, len, n); _fmpz_mod_poly_set_length(res, n); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/scalar.c000066400000000000000000000102071461254215100177110ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2015 Vladimir Glazachev Copyright (C) 2021 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_scalar_addmul_fmpz(fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_t x, const fmpz_mod_ctx_t ctx) { slong len = FLINT_MAX(A->length, B->length); if (fmpz_is_zero(x) || B->length < 1) return; fmpz_mod_poly_fit_length(A, B->length, ctx); if (B->length > A->length) _fmpz_vec_zero(A->coeffs + A->length, B->length - A->length); _fmpz_vec_scalar_addmul_fmpz(A->coeffs, B->coeffs, B->length, x); _fmpz_mod_vec_set_fmpz_vec(A->coeffs, A->coeffs, len, ctx); _fmpz_mod_poly_set_length(A, len); _fmpz_mod_poly_normalise(A); } void _fmpz_mod_poly_scalar_div_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx) { fmpz_t g, xinv; fmpz_init(g); fmpz_init(xinv); if (fmpz_sgn(x) < 0 || fmpz_cmp(x, fmpz_mod_ctx_modulus(ctx)) >= 0) { fmpz_mod(xinv, x, fmpz_mod_ctx_modulus(ctx)); fmpz_gcdinv(g, xinv, xinv, fmpz_mod_ctx_modulus(ctx)); } else fmpz_gcdinv(g, xinv, x, fmpz_mod_ctx_modulus(ctx)); if (!fmpz_is_one(g)) { flint_throw(FLINT_ERROR, "Exception (_fmpz_mod_poly_scalar_div_fmpz). Impossible inverse.\n"); } _fmpz_mod_vec_scalar_mul_fmpz_mod(res, poly, len, xinv, ctx); fmpz_clear(xinv); fmpz_clear(g); } void fmpz_mod_poly_scalar_div_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t x, const fmpz_mod_ctx_t ctx) { if (fmpz_is_zero(x)) { if (fmpz_is_one(fmpz_mod_ctx_modulus(ctx))) { fmpz_mod_poly_set(res, poly, ctx); return; } else { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_scalar_div_fmpz). Division by zero.\n"); } } fmpz_mod_poly_fit_length(res, poly->length, ctx); _fmpz_mod_poly_scalar_div_fmpz(res->coeffs, poly->coeffs, poly->length, x, ctx); _fmpz_mod_poly_set_length(res, poly->length); _fmpz_mod_poly_normalise(res); } void _fmpz_mod_poly_scalar_mul_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx) { if (fmpz_sgn(x) >= 0 && fmpz_cmp(x, fmpz_mod_ctx_modulus(ctx)) < 0) { _fmpz_mod_vec_scalar_mul_fmpz_mod(res, poly, len, x, ctx); } else { fmpz_t t; fmpz_init(t); /* todo: handle small negative coefficients specially */ fmpz_mod_set_fmpz(t, x, ctx); _fmpz_mod_vec_scalar_mul_fmpz_mod(res, poly, len, t, ctx); fmpz_clear(t); } } void fmpz_mod_poly_scalar_mul_fmpz(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_t x, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(res, poly->length, ctx); _fmpz_mod_poly_scalar_mul_fmpz(res->coeffs, poly->coeffs, poly->length, x, ctx); _fmpz_mod_poly_set_length(res, poly->length); _fmpz_mod_poly_normalise(res); } void _fmpz_mod_poly_scalar_mul_ui(fmpz *res, const fmpz *poly, slong len, ulong x, const fmpz_mod_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_mod_set_ui(t, x, ctx); _fmpz_mod_vec_scalar_mul_fmpz_mod(res, poly, len, t, ctx); fmpz_clear(t); } void fmpz_mod_poly_scalar_mul_ui(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, ulong x, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(res, poly->length, ctx); _fmpz_mod_poly_scalar_mul_ui(res->coeffs, poly->coeffs, poly->length, x, ctx); _fmpz_mod_poly_set_length(res, poly->length); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/set.c000066400000000000000000000044771461254215100172530ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_set(fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) { if (poly1 != poly2) /* Aliasing is trivial */ { slong i, len = poly2->length; fmpz_mod_poly_fit_length(poly1, len, ctx); for (i = 0; i < len; i++) fmpz_set(poly1->coeffs + i, poly2->coeffs + i); _fmpz_mod_poly_set_length(poly1, len); } } void fmpz_mod_poly_set_fmpz(fmpz_mod_poly_t poly, const fmpz_t c, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, 1, ctx); fmpz_mod(poly->coeffs, c, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(poly, 1); _fmpz_mod_poly_normalise(poly); } void fmpz_mod_poly_set_fmpz_poly(fmpz_mod_poly_t f, const fmpz_poly_t g, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(f, g->length, ctx); _fmpz_mod_poly_set_length(f, g->length); _fmpz_mod_vec_set_fmpz_vec(f->coeffs, g->coeffs, g->length, ctx); _fmpz_mod_poly_normalise(f); } void fmpz_mod_poly_set_nmod_poly(fmpz_mod_poly_t f, const nmod_poly_t g) { slong i; _fmpz_mod_poly_fit_length(f, g->length); _fmpz_mod_poly_set_length(f, g->length); for (i = 0; i < g->length; i++) fmpz_set_ui(f->coeffs + i, g->coeffs[i]); } void fmpz_mod_poly_set_ui(fmpz_mod_poly_t f, ulong x, const fmpz_mod_ctx_t ctx) { if (x == 0) { fmpz_mod_poly_zero(f, ctx); } else { fmpz_mod_poly_fit_length(f, 1, ctx); _fmpz_mod_poly_set_length(f, 1); fmpz_set_ui(f->coeffs, x); fmpz_mod(f->coeffs, f->coeffs, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(f); } } flint-3.1.3/src/fmpz_mod_poly/set_get_coeff.c000066400000000000000000000055241461254215100212460ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" /* Setters ********************************************************************/ void fmpz_mod_poly_set_coeff_si(fmpz_mod_poly_t poly, slong n, slong x, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { flint_mpn_zero((mp_ptr) (poly->coeffs + poly->length), n - poly->length); poly->length = n + 1; } fmpz_set_si(poly->coeffs + n, x); fmpz_mod(poly->coeffs + n, poly->coeffs + n, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_normalise(poly); } void fmpz_mod_poly_set_coeff_ui(fmpz_mod_poly_t poly, slong n, ulong x, const fmpz_mod_ctx_t ctx) { if (x == 0) { if (n >= poly->length) return; fmpz_zero(poly->coeffs + n); } else { fmpz_mod_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { flint_mpn_zero((mp_ptr) (poly->coeffs + poly->length), n - poly->length); poly->length = n + 1; } fmpz_set_ui(poly->coeffs + n, x); fmpz_mod(poly->coeffs + n, poly->coeffs + n, fmpz_mod_ctx_modulus(ctx)); } if (n == poly->length - 1) _fmpz_mod_poly_normalise(poly); /* we may have set the leading coefficient to 0 */ } void fmpz_mod_poly_set_coeff_fmpz(fmpz_mod_poly_t poly, slong n, const fmpz_t x, const fmpz_mod_ctx_t ctx) { if (fmpz_is_zero(x)) { if (n >= poly->length) return; fmpz_zero(poly->coeffs + n); } else { fmpz_mod_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { flint_mpn_zero((mp_ptr) (poly->coeffs + poly->length), n - poly->length); poly->length = n + 1; } fmpz_mod_set_fmpz(poly->coeffs + n, x, ctx); } if (n == poly->length - 1) _fmpz_mod_poly_normalise(poly); /* we may have set the leading coefficient to 0 */ } /* Getters ********************************************************************/ void fmpz_mod_poly_get_coeff_fmpz(fmpz_t x, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) { if (n < poly->length) fmpz_set(x, poly->coeffs + n); else fmpz_zero(x); } flint-3.1.3/src/fmpz_mod_poly/set_length.c000066400000000000000000000012311461254215100205750ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_set_length(fmpz_mod_poly_t poly, slong len) { if (poly->length > len) { slong i; for (i = len; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); } poly->length = len; } flint-3.1.3/src/fmpz_mod_poly/set_trunc.c000066400000000000000000000017671461254215100204650ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_set_trunc(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) { if (poly == res) { fmpz_mod_poly_truncate(res, n, ctx); } else { slong rlen; rlen = FLINT_MIN(n, poly->length); while (rlen > 0 && fmpz_is_zero(poly->coeffs + rlen - 1)) rlen--; fmpz_mod_poly_fit_length(res, rlen, ctx); _fmpz_vec_set(res->coeffs, poly->coeffs, rlen); _fmpz_mod_poly_set_length(res, rlen); } } flint-3.1.3/src/fmpz_mod_poly/shift_left.c000066400000000000000000000026411461254215100205760ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2009, 2008 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n) { slong i; /* Copy in reverse to avoid writing over unshifted coefficients */ if (res != poly) { for (i = len; i--; ) fmpz_set(res + n + i, poly + i); } else { for (i = len; i--; ) fmpz_swap(res + n + i, res + i); } for (i = 0; i < n; i++) fmpz_zero(res + i); } void fmpz_mod_poly_shift_left(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) { if (n == 0) { fmpz_mod_poly_set(res, poly, ctx); return; } if (poly->length == 0) { fmpz_mod_poly_zero(res, ctx); return; } fmpz_mod_poly_fit_length(res, poly->length + n, ctx); _fmpz_mod_poly_shift_left(res->coeffs, poly->coeffs, poly->length, n); _fmpz_mod_poly_set_length(res, poly->length + n); } flint-3.1.3/src/fmpz_mod_poly/shift_right.c000066400000000000000000000026041461254215100207600ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2009, 2008 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n) { slong i; /* Copy in forward order to avoid writing over unshifted coefficients */ if (res != poly) { for (i = 0; i < len - n; i++) fmpz_set(res + i, poly + n + i); } else { for (i = 0; i < len - n; i++) fmpz_swap(res + i, res + n + i); } } void fmpz_mod_poly_shift_right(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) { if (n == 0) { fmpz_mod_poly_set(res, poly, ctx); return; } if (poly->length <= n) { fmpz_mod_poly_zero(res, ctx); return; } fmpz_mod_poly_fit_length(res, poly->length - n, ctx); _fmpz_mod_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n); _fmpz_mod_poly_set_length(res, poly->length - n); } flint-3.1.3/src/fmpz_mod_poly/sqr.c000066400000000000000000000030471461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_sqr(fmpz *res, const fmpz *poly, slong len, const fmpz_mod_ctx_t ctx) { _fmpz_poly_sqr(res, poly, len); _fmpz_mod_vec_set_fmpz_vec(res, res, 2 * len - 1, ctx); } void fmpz_mod_poly_sqr(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { const slong len = poly->length; if (len == 0) { fmpz_mod_poly_zero(res, ctx); return; } if (res == poly) { fmpz *t = flint_calloc(2 * len - 1, sizeof(fmpz)); _fmpz_mod_poly_sqr(t, poly->coeffs, len, ctx); _fmpz_vec_clear(res->coeffs, res->alloc); res->alloc = 2 * len - 1; res->length = 2 * len - 1; res->coeffs = t; _fmpz_mod_poly_normalise(res); } else { fmpz_mod_poly_fit_length(res, 2*len - 1, ctx); _fmpz_mod_poly_sqr(res->coeffs, poly->coeffs, len, ctx); _fmpz_mod_poly_set_length(res, 2 * len - 1); _fmpz_mod_poly_normalise(res); } } flint-3.1.3/src/fmpz_mod_poly/sqrt.c000066400000000000000000000061431461254215100174410ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" static inline int _fmpz_mod_poly_sqrt_2(fmpz * s, const fmpz * p, slong len) { slong i; for (i = 1; i < len; i += 2) if (!fmpz_is_zero(p + i)) return 0; for (i = 0; i < len; i += 2) fmpz_set(s + i / 2, p + i); return 1; } int _fmpz_mod_poly_sqrt(fmpz * s, const fmpz * p, slong len, const fmpz_mod_ctx_t mod) { slong slen, i; int result; fmpz * t; fmpz_t c, d; if (len % 2 == 0) return len == 0; if (fmpz_cmp_ui(mod->n, 2) == 0) return _fmpz_mod_poly_sqrt_2(s, p, len); /* valuation must be even, and then can be reduced to 0 */ while (fmpz_is_zero(p + 0)) { if (!fmpz_is_zero(p + 1)) return 0; fmpz_zero(s + 0); p += 2; len -= 2; s++; } fmpz_init(c); fmpz_init(d); fmpz_set(d, p + 0); fmpz_set(c, d); if (!fmpz_is_one(c)) { if (!fmpz_sqrtmod(c, c, mod->n)) { result = 0; goto cleanup; } } if (len == 1) { fmpz_set(s + 0, c); result = 1; goto cleanup; } slen = len / 2 + 1; t = _fmpz_vec_init(len); if (fmpz_is_one(c)) _fmpz_mod_poly_sqrt_series(s, p, slen, slen, mod); else { fmpz_invmod(d, d, mod->n); _fmpz_mod_vec_scalar_mul_fmpz_mod(t, p, slen, d, mod); _fmpz_mod_poly_sqrt_series(s, t, slen, slen, mod); } if (!fmpz_is_one(c)) _fmpz_mod_vec_scalar_mul_fmpz_mod(s, s, slen, c, mod); _fmpz_poly_mulhigh(t, s, slen, s, slen, slen); for (i = 0; i < slen; i++) fmpz_zero(t + i); _fmpz_mod_vec_set_fmpz_vec(t + slen, t + slen, slen - 1, mod); result = _fmpz_vec_equal(t + slen, p + slen, len - slen); _fmpz_vec_clear(t, len); cleanup: fmpz_clear(c); fmpz_clear(d); return result; } int fmpz_mod_poly_sqrt(fmpz_mod_poly_t b, const fmpz_mod_poly_t a, const fmpz_mod_ctx_t ctx) { slong blen, len = a->length; int result; if (len % 2 == 0) { fmpz_mod_poly_zero(b, ctx); return len == 0; } if (b == a) { fmpz_mod_poly_t tmp; fmpz_mod_poly_init(tmp, ctx); result = fmpz_mod_poly_sqrt(tmp, a, ctx); fmpz_mod_poly_swap(b, tmp, ctx); fmpz_mod_poly_clear(tmp, ctx); return result; } blen = len / 2 + 1; fmpz_mod_poly_fit_length(b, blen, ctx); result = _fmpz_mod_poly_sqrt(b->coeffs, a->coeffs, len, ctx); if (!result) blen = 0; _fmpz_mod_poly_set_length(b, blen); _fmpz_mod_poly_normalise(b); return result; } flint-3.1.3/src/fmpz_mod_poly/sqrt_series.c000066400000000000000000000032741461254215100210150ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 William Hart Copyright (C) 2011, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_poly.h" void _fmpz_mod_poly_sqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t mod) { gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, mod); GR_MUST_SUCCEED(_gr_poly_sqrt_series(g, h, hlen, n, gr_ctx)); } void fmpz_mod_poly_sqrt_series(fmpz_mod_poly_t g, const fmpz_mod_poly_t h, slong n, const fmpz_mod_ctx_t ctx) { const slong hlen = h->length; if (n == 0 || h->length == 0) { fmpz_mod_poly_zero(g, ctx); return; } if (!fmpz_is_one(h->coeffs + 0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_sqrt_series). Constant term != 1.\n"); } if (hlen == 1) n = 1; if (g == h) { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, n, ctx); _fmpz_mod_poly_sqrt_series(t->coeffs, h->coeffs, hlen, n, ctx); _fmpz_mod_poly_set_length(t, n); _fmpz_mod_poly_normalise(t); fmpz_mod_poly_swap(g, t, ctx); fmpz_mod_poly_clear(t, ctx); } else { _fmpz_mod_poly_fit_length(g, n); _fmpz_mod_poly_sqrt_series(g->coeffs, h->coeffs, hlen, n, ctx); _fmpz_mod_poly_set_length(g, n); _fmpz_mod_poly_normalise(g); } } flint-3.1.3/src/fmpz_mod_poly/sub.c000066400000000000000000000026341461254215100172420ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_sub(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_mod_ctx_t ctx) { slong len3 = FLINT_MIN(len1, len2); _fmpz_mod_vec_sub(res, poly1, poly2, len3, ctx); if (len1 > len3) _fmpz_vec_set(res + len3, poly1 + len3, len1 - len3); if (len2 > len3) _fmpz_mod_vec_neg(res + len3, poly2 + len3, len2 - len3, ctx); } void fmpz_mod_poly_sub(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) { slong max = FLINT_MAX(poly1->length, poly2->length); fmpz_mod_poly_fit_length(res, max, ctx); _fmpz_mod_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/sub_series.c000066400000000000000000000020511461254215100206050ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009, 2104 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_sub_series(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n, const fmpz_mod_ctx_t ctx) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); fmpz_mod_poly_fit_length(res, max, ctx); _fmpz_mod_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint-3.1.3/src/fmpz_mod_poly/test/000077500000000000000000000000001461254215100172575ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_poly/test/main.c000066400000000000000000000145061461254215100203550ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Try to get fdopen declared for t-print_read.c */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_series.c" #include "t-berlekamp_massey.c" #include "t-compose.c" #include "t-compose_mod_brent_kung.c" #include "t-compose_mod_brent_kung_precomp_preinv.c" #include "t-compose_mod_brent_kung_precomp_preinv_threaded.c" #include "t-compose_mod_brent_kung_preinv.c" #include "t-compose_mod_brent_kung_vec_preinv.c" #include "t-compose_mod_brent_kung_vec_preinv_threaded.c" #include "t-compose_mod.c" #include "t-compose_mod_horner.c" #include "t-deflate_deflation_inflate.c" #include "t-derivative.c" #include "t-discriminant.c" #include "t-div.c" #include "t-divides.c" #include "t-divides_classical.c" #include "t-div_newton_n_preinv.c" #include "t-divrem_basecase.c" #include "t-divrem_f.c" #include "t-divrem_newton_n_preinv.c" #include "t-div_series.c" #include "t-evaluate_fmpz.c" #include "t-evaluate_fmpz_vec.c" #include "t-find_distinct_nonzero_roots.c" #include "t-frobenius_powers_precomp.c" #include "t-gcd.c" #include "t-gcd_euclidean_f.c" #include "t-gcdinv.c" #include "t-gcdinv_euclidean.c" #include "t-get_set_fmpz_poly.c" #include "t-get_set_nmod_poly.c" #include "t-init_realloc_clear.c" #include "t-invmod.c" #include "t-inv_series.c" #include "t-invsqrt_series.c" #include "t-minpoly.c" #include "t-mul.c" #include "t-mulhigh.c" #include "t-mullow.c" #include "t-mulmod.c" #include "t-mulmod_preinv.c" #include "t-neg.c" #include "t-powers_mod_bsgs.c" #include "t-powers_mod_naive.c" #include "t-powmod_fmpz_binexp.c" #include "t-powmod_fmpz_binexp_preinv.c" #include "t-powmod_ui_binexp.c" #include "t-powmod_ui_binexp_preinv.c" #include "t-powmod_x_fmpz_preinv.c" #include "t-pow_trunc_binexp.c" #include "t-pow_trunc.c" #include "t-print_read.c" #include "t-product_roots_fmpz_vec.c" #include "t-radix.c" #include "t-randtest_monic_primitive.c" #include "t-rem_basecase.c" #include "t-resultant.c" #include "t-scalar_div_fmpz.c" #include "t-scalar_mul_fmpz.c" #include "t-set_equal.c" #include "t-set_trunc.c" #include "t-shift_left_right.c" #include "t-sqrt.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-swap.c" #include "t-xgcd.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mod_poly_add), TEST_FUNCTION(fmpz_mod_poly_add_series), TEST_FUNCTION(fmpz_mod_poly_berlekamp_massey), TEST_FUNCTION(fmpz_mod_poly_compose), TEST_FUNCTION(fmpz_mod_poly_compose_mod_brent_kung), TEST_FUNCTION(fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv), TEST_FUNCTION(fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_threaded), TEST_FUNCTION(fmpz_mod_poly_compose_mod_brent_kung_preinv), TEST_FUNCTION(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv), TEST_FUNCTION(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded), TEST_FUNCTION(fmpz_mod_poly_compose_mod), TEST_FUNCTION(fmpz_mod_poly_compose_mod_horner), TEST_FUNCTION(fmpz_mod_poly_deflate_deflation_inflate), TEST_FUNCTION(fmpz_mod_poly_derivative), TEST_FUNCTION(fmpz_mod_poly_discriminant), TEST_FUNCTION(fmpz_mod_poly_div), TEST_FUNCTION(fmpz_mod_poly_divides), TEST_FUNCTION(fmpz_mod_poly_divides_classical), TEST_FUNCTION(fmpz_mod_poly_div_newton_n_preinv), TEST_FUNCTION(fmpz_mod_poly_divrem_basecase), TEST_FUNCTION(fmpz_mod_poly_divrem_f), TEST_FUNCTION(fmpz_mod_poly_divrem_newton_n_preinv), TEST_FUNCTION(fmpz_mod_poly_div_series), TEST_FUNCTION(fmpz_mod_poly_evaluate_fmpz), TEST_FUNCTION(fmpz_mod_poly_evaluate_fmpz_vec), TEST_FUNCTION(fmpz_mod_poly_find_distinct_nonzero_roots), TEST_FUNCTION(fmpz_mod_poly_frobenius_powers_precomp), TEST_FUNCTION(fmpz_mod_poly_gcd), TEST_FUNCTION(fmpz_mod_poly_gcd_euclidean_f), TEST_FUNCTION(fmpz_mod_poly_gcdinv), TEST_FUNCTION(fmpz_mod_poly_gcdinv_euclidean), TEST_FUNCTION(fmpz_mod_poly_get_set_fmpz_poly), TEST_FUNCTION(fmpz_mod_poly_get_set_nmod_poly), TEST_FUNCTION(fmpz_mod_poly_init_realloc_clear), TEST_FUNCTION(fmpz_mod_poly_invmod), TEST_FUNCTION(fmpz_mod_poly_inv_series), TEST_FUNCTION(fmpz_mod_poly_invsqrt_series), TEST_FUNCTION(fmpz_mod_poly_minpoly), TEST_FUNCTION(fmpz_mod_poly_mul), TEST_FUNCTION(fmpz_mod_poly_mulhigh), TEST_FUNCTION(fmpz_mod_poly_mullow), TEST_FUNCTION(fmpz_mod_poly_mulmod), TEST_FUNCTION(fmpz_mod_poly_mulmod_preinv), TEST_FUNCTION(fmpz_mod_poly_neg), TEST_FUNCTION(fmpz_mod_poly_powers_mod_bsgs), TEST_FUNCTION(fmpz_mod_poly_powers_mod_naive), TEST_FUNCTION(fmpz_mod_poly_powmod_fmpz_binexp), TEST_FUNCTION(fmpz_mod_poly_powmod_fmpz_binexp_preinv), TEST_FUNCTION(fmpz_mod_poly_powmod_ui_binexp), TEST_FUNCTION(fmpz_mod_poly_powmod_ui_binexp_preinv), TEST_FUNCTION(fmpz_mod_poly_powmod_x_fmpz_preinv), TEST_FUNCTION(fmpz_mod_poly_pow_trunc_binexp), TEST_FUNCTION(fmpz_mod_poly_pow_trunc), TEST_FUNCTION(fmpz_mod_poly_print_read), TEST_FUNCTION(fmpz_mod_poly_product_roots_fmpz_vec), TEST_FUNCTION(fmpz_mod_poly_radix), TEST_FUNCTION(fmpz_mod_poly_randtest_monic_primitive), TEST_FUNCTION(fmpz_mod_poly_rem_basecase), TEST_FUNCTION(fmpz_mod_poly_resultant), TEST_FUNCTION(fmpz_mod_poly_scalar_div_fmpz), TEST_FUNCTION(fmpz_mod_poly_scalar_mul_fmpz), TEST_FUNCTION(fmpz_mod_poly_set_equal), TEST_FUNCTION(fmpz_mod_poly_set_trunc), TEST_FUNCTION(fmpz_mod_poly_shift_left_right), TEST_FUNCTION(fmpz_mod_poly_sqrt), TEST_FUNCTION(fmpz_mod_poly_sqrt_series), TEST_FUNCTION(fmpz_mod_poly_sub), TEST_FUNCTION(fmpz_mod_poly_sub_series), TEST_FUNCTION(fmpz_mod_poly_swap), TEST_FUNCTION(fmpz_mod_poly_xgcd), TEST_FUNCTION(fmpz_mod_poly_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mod_poly/test/t-add.c000066400000000000000000000057031461254215100204210ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_add, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_add(c, a, b, ctx); fmpz_mod_poly_add(a, a, b, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_add(c, a, b, ctx); fmpz_mod_poly_add(b, a, b, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-add_series.c000066400000000000000000000107501461254215100217710ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_add_series, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; slong n; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); fmpz_mod_poly_add_series(c, a, b, n, ctx); fmpz_mod_poly_add_series(a, a, b, n, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; slong n; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); fmpz_mod_poly_add_series(c, a, b, n, ctx); fmpz_mod_poly_add_series(b, a, b, n, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check truncate(a + b, n) = add_series(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d; slong n; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); fmpz_mod_poly_add(c, a, b, ctx); fmpz_mod_poly_truncate(c, n, ctx); fmpz_mod_poly_add_series(d, a, b, n, ctx); result = (fmpz_mod_poly_equal(d, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-berlekamp_massey.c000066400000000000000000000141141461254215100232100ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_berlekamp_massey, state) { slong i, j, k, l; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 101); { fmpz_mod_berlekamp_massey_t B; fmpz_mod_berlekamp_massey_init(B, ctx); fmpz_mod_berlekamp_massey_add_point_ui(B, 1, ctx); fmpz_mod_berlekamp_massey_add_point_ui(B, 1, ctx); fmpz_mod_berlekamp_massey_add_point_ui(B, 2, ctx); fmpz_mod_berlekamp_massey_add_point_ui(B, 3, ctx); fmpz_mod_berlekamp_massey_add_point_ui(B, 5, ctx); fmpz_mod_berlekamp_massey_reduce(B, ctx); if (2 != fmpz_mod_poly_degree(fmpz_mod_berlekamp_massey_V_poly(B), ctx)) { printf("FAIL\n"); flint_printf("check fibonacci\n"); fflush(stdout); flint_abort(); } fmpz_mod_berlekamp_massey_clear(B, ctx); } for (i = 0; i < 15 * flint_test_multiplier(); i++) { fmpz_mod_berlekamp_massey_t B1, B2; fmpz_mod_berlekamp_massey_init(B1, ctx); fmpz_mod_berlekamp_massey_init(B2, ctx); for (j = 0; j < 10; j++) { fmpz_t p, apoint; fmpz_init(apoint); fmpz_init_set_ui(p, n_randtest_prime(state, 1)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_berlekamp_massey_start_over(B1, ctx); fmpz_mod_berlekamp_massey_start_over(B2, ctx); /* check intermediate reductions match */ for (k = 0; k < 10; k++) { fmpz_randm(apoint, state, p); fmpz_mod_berlekamp_massey_add_point(B1, apoint, ctx); fmpz_mod_berlekamp_massey_add_zeros(B1, n_randint(state, 5), ctx); fmpz_randm(apoint, state, p); fmpz_mod_berlekamp_massey_add_point(B1, apoint, ctx); if (n_randlimb(state) & 1) fmpz_mod_berlekamp_massey_reduce(B1, ctx); } fmpz_mod_berlekamp_massey_add_points(B2, fmpz_mod_berlekamp_massey_points(B1), fmpz_mod_berlekamp_massey_point_count(B1), ctx); fmpz_mod_berlekamp_massey_reduce(B2, ctx); fmpz_mod_berlekamp_massey_reduce(B1, ctx); if (!fmpz_mod_poly_equal(fmpz_mod_berlekamp_massey_V_poly(B1), fmpz_mod_berlekamp_massey_V_poly(B2), ctx)) { printf("FAIL\n"); flint_printf("check intermediate reductions match\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } /* Check berlekamp-massey does its job - 2k coefficients of u a1 a2 a(2k) --- = --- + --- + ... + ------ + ... v x x^2 x^(2k) should be sufficient to reconstruct a divisor of v */ for (k = 0; k < 15; k++) { fmpz_mod_poly_t u, v, s, q, r; fmpz_mod_poly_init(u, ctx); fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); /* deg(u) < deg(v), deg(v) = k */ fmpz_mod_poly_randtest(u, state, k, ctx); fmpz_mod_poly_randtest_monic(v, state, k + 1, ctx); /* q has enough coefficients of expansion of u/v at infty */ fmpz_mod_poly_shift_left(s, u, 2*k, ctx); fmpz_mod_poly_divrem(q, r, s, v, ctx); fmpz_mod_berlekamp_massey_start_over(B1, ctx); for (l = 2*k - 1; l >= 0 ; l--) { fmpz_mod_poly_get_coeff_fmpz(apoint, q, l, ctx); fmpz_mod_berlekamp_massey_add_point(B1, apoint, ctx); } fmpz_mod_berlekamp_massey_reduce(B1, ctx); fmpz_mod_poly_divrem(q, r, v, fmpz_mod_berlekamp_massey_V_poly(B1), ctx); if (!fmpz_mod_poly_is_zero(r, ctx)) { flint_printf("check berlekamp_massey does its job\n" "i = %wd, j = %wd, k = %wd\n", i, j, k); printf("v: "); fmpz_mod_poly_print_pretty(v, "#", ctx); printf("\n"); printf("B: "); fmpz_mod_berlekamp_massey_print(B1, ctx); printf("\n"); fflush(stdout); flint_abort(); } if (fmpz_mod_poly_degree(fmpz_mod_berlekamp_massey_R_poly(B1), ctx) >= fmpz_mod_poly_degree(fmpz_mod_berlekamp_massey_V_poly(B1), ctx)) { flint_printf("check discrepancy\n" "i = %wd, j = %wd, k = %wd\n", i, j, k); printf("v: "); fmpz_mod_poly_print_pretty(v, "#", ctx); printf("\n"); printf("B: "); fmpz_mod_berlekamp_massey_print(B1, ctx); printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(u, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); } fmpz_clear(p); fmpz_clear(apoint); } fmpz_mod_berlekamp_massey_clear(B1, ctx); fmpz_mod_berlekamp_massey_clear(B2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose.c000066400000000000000000000111071461254215100213310ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 80), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 30), ctx); fmpz_mod_poly_compose(c, a, b, ctx); fmpz_mod_poly_compose(a, a, b, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 80), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 30), ctx); fmpz_mod_poly_compose(c, a, b, ctx); fmpz_mod_poly_compose(b, a, b, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Compare with composition over Z[X] */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d; fmpz_poly_t A, B, C; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 80), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 30), ctx); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_init(C); fmpz_mod_poly_get_fmpz_poly(A, a, ctx); fmpz_mod_poly_get_fmpz_poly(B, b, ctx); fmpz_mod_poly_compose(c, a, b, ctx); fmpz_poly_compose(C, A, B); fmpz_mod_poly_set_fmpz_poly(d, C, ctx); result = (fmpz_mod_poly_equal(c, d, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(C); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod.c000066400000000000000000000147201461254215100221740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d, e; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(e, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod(d, a, b, c, ctx); fmpz_mod_poly_compose(e, a, b, ctx); fmpz_mod_poly_rem(e, e, c, ctx); if (!fmpz_mod_poly_equal(d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); flint_printf("e:\n"); fmpz_mod_poly_print(e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(e, ctx); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod(d, a, b, c, ctx); fmpz_mod_poly_compose_mod(a, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod(d, a, b, c, ctx); fmpz_mod_poly_compose_mod(b, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod(d, a, b, c, ctx); fmpz_mod_poly_compose_mod(c, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000153141461254215100244120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod_brent_kung, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d, e; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(e, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung(d, a, b, c, ctx); fmpz_mod_poly_compose(e, a, b, ctx); fmpz_mod_poly_rem(e, e, c, ctx); if (!fmpz_mod_poly_equal(d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); flint_printf("e:\n"); fmpz_mod_poly_print(e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(e, ctx); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung(d, a, b, c, ctx); fmpz_mod_poly_compose_mod_brent_kung(a, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung(d, a, b, c, ctx); fmpz_mod_poly_compose_mod_brent_kung(b, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung(d, a, b, c, ctx); fmpz_mod_poly_compose_mod_brent_kung(c, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000206711461254215100275240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d, e; fmpz_t p; fmpz_mat_t B; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(e, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mat_init (B, n_sqrt (c->length-1)+1, c->length-1); fmpz_mod_poly_precompute_matrix (B, b, c, cinv, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv, ctx); fmpz_mod_poly_compose(e, a, b, ctx); fmpz_mod_poly_rem(e, e, c, ctx); if (!fmpz_mod_poly_equal(d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); flint_printf("e:\n"); fmpz_mod_poly_print(e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mat_clear(B); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(e, ctx); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_t p; fmpz_mat_t B; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mat_init (B, n_sqrt (c->length-1)+1, c->length-1); fmpz_mod_poly_precompute_matrix (B, b, c, cinv, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(a, a, B, c, cinv, ctx); if (!fmpz_mod_poly_equal(d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mat_clear(B); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_t p; fmpz_mat_t B; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mat_init (B, n_sqrt (c->length-1)+1, c->length-1); fmpz_mod_poly_precompute_matrix (B, b, c, cinv, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(c, a, B, c, cinv, ctx); if (!fmpz_mod_poly_equal(d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mat_clear(B); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and cinv */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_t p; fmpz_mat_t B; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mat_init (B, n_sqrt (c->length-1)+1, c->length-1); fmpz_mod_poly_precompute_matrix (B, b, c, cinv, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(cinv, a, B, c, cinv, ctx); if (!fmpz_mod_poly_equal(d, cinv, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mat_clear(B); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod_brent_kung_precomp_preinv_threaded.c000066400000000000000000000220051461254215100313550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* check precomputation */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv; fmpz_mod_poly_struct * tmp; fmpz_t p; fmpz_mat_t B; fmpz_mat_struct * C; slong j, num_threads; fmpz_mod_poly_matrix_precompute_arg_t * args1; thread_pool_handle * threads; flint_set_num_threads(1 + n_randint(state, 3)); num_threads = flint_request_threads(&threads, FLINT_DEFAULT_THREAD_LIMIT); tmp = (fmpz_mod_poly_struct *) flint_malloc(sizeof(fmpz_mod_poly_struct)*(num_threads + 1)); fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); for (j = 0; j < num_threads + 1; j++) fmpz_mod_poly_init(tmp + j, ctx); fmpz_mod_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 20) + 1, ctx); do { fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); } while (c->length < 2); fmpz_mod_poly_reverse(cinv, c, c->length, ctx); fmpz_mod_poly_inv_series(cinv, cinv, c->length, ctx); fmpz_mat_init(B, n_sqrt(c->length - 1) + 1, c->length - 1); fmpz_mod_poly_precompute_matrix(B, b, c, cinv, ctx); args1 = (fmpz_mod_poly_matrix_precompute_arg_t *) flint_malloc(sizeof(fmpz_mod_poly_matrix_precompute_arg_t) *(num_threads + 1)); C = (fmpz_mat_struct* ) flint_malloc(sizeof(fmpz_mat_struct)*(num_threads + 1)); for (j = 0; j < num_threads + 1; j++) { fmpz_mat_init(C + j, n_sqrt(c->length - 1) + 1, c->length - 1); fmpz_mod_poly_set(tmp + j, b, ctx); fmpz_mod_poly_rem(tmp + j, tmp + j, c, ctx); if (tmp[j].length < c->length - 1) { fmpz_mod_poly_fit_length(tmp + j, c->length - 1, ctx); _fmpz_vec_zero(tmp[j].coeffs + tmp[j].length, c->length - 1 - b->length); } args1[j].A = C + j; args1[j].poly1 = tmp + j; args1[j].poly2 = c; args1[j].poly2inv = cinv; args1[j].ctx = ctx; } for (j = 1; j < num_threads + 1; j++) thread_pool_wake(global_thread_pool, threads[j - 1], 0, _fmpz_mod_poly_precompute_matrix_worker, &args1[j]); _fmpz_mod_poly_precompute_matrix_worker(&args1[0]); for (j = 0; j < num_threads; j++) { thread_pool_wait(global_thread_pool, threads[j]); } for (j = 0; j < num_threads + 1; j++) { if (!fmpz_mat_equal(B, C + j)) { flint_printf("FAIL (precomputation):\n"); flint_printf("B:\n"); fmpz_mat_print(B); flint_printf("\n"); flint_printf("C[j]:\n"); fmpz_mat_print(C + j); flint_printf("\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } flint_give_back_threads(threads, num_threads); fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mat_clear(B); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); for (j = 0; j < num_threads + 1; j++) { fmpz_mod_poly_clear(tmp + j, ctx); fmpz_mat_clear(C + j); } flint_free(C); flint_free(tmp); flint_free(args1); } /* check composition */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_mod_poly_struct * res; fmpz_t p; fmpz_mat_t B; slong j, num_threads; fmpz_mod_poly_compose_mod_precomp_preinv_arg_t * args1; thread_pool_handle * threads; flint_set_num_threads(1 + n_randint(state, 3)); num_threads = flint_request_threads(&threads, FLINT_DEFAULT_THREAD_LIMIT); res = (fmpz_mod_poly_struct* ) flint_malloc(sizeof(fmpz_mod_poly_struct)*(num_threads + 1)); fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); for (j = 0; j < num_threads + 1; j++) fmpz_mod_poly_init(res + j, ctx); fmpz_mod_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 20) + 1, ctx); do { fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); } while (c->length < 2); fmpz_mod_poly_reverse(cinv, c, c->length, ctx); fmpz_mod_poly_inv_series(cinv, cinv, c->length, ctx); fmpz_mat_init(B, n_sqrt(c->length - 1) + 1, c->length - 1); fmpz_mod_poly_precompute_matrix(B, b, c, cinv, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod(d, a, b, c, ctx); args1 = (fmpz_mod_poly_compose_mod_precomp_preinv_arg_t *) flint_malloc((num_threads + 1)* sizeof(fmpz_mod_poly_compose_mod_precomp_preinv_arg_t)); for (j = 0; j < num_threads + 1; j++) { fmpz_mod_poly_fit_length(res + j, c->length - 1, ctx); _fmpz_mod_poly_set_length(res + j, c->length - 1); args1[j].A = B; args1[j].res = res + j; args1[j].poly1 = a; args1[j].poly3 = c; args1[j].poly3inv = cinv; args1[j].ctx = ctx; } for (j = 1; j < num_threads + 1; j++) thread_pool_wake(global_thread_pool, threads[j - 1], 0, _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker, &args1[j]); _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker(&args1[0]); _fmpz_mod_poly_normalise(res + 0); for (j = 1; j < num_threads + 1; j++) { thread_pool_wait(global_thread_pool, threads[j - 1]); _fmpz_mod_poly_normalise(res + j); } for (j = 0; j < num_threads + 1; j++) { if (!fmpz_mod_poly_equal(d, res + j, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("res[j]:\n"); fmpz_mod_poly_print(res + j, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } flint_give_back_threads(threads, num_threads); fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mat_clear(B); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); for (j = 0; j < num_threads + 1; j++) fmpz_mod_poly_clear(res + j, ctx); flint_free(res); flint_free(args1); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000226161461254215100260000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod_brent_kung_preinv, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d, e; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(e, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv, ctx); fmpz_mod_poly_compose(e, a, b, ctx); fmpz_mod_poly_rem(e, e, c, ctx); if (!fmpz_mod_poly_equal(d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); flint_printf("e:\n"); fmpz_mod_poly_print(e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(e, ctx); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(a, a, b, c, cinv, ctx); if (!fmpz_mod_poly_equal(d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(b, a, b, c, cinv, ctx); if (!fmpz_mod_poly_equal(d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(c, a, b, c, cinv, ctx); if (!fmpz_mod_poly_equal(d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and cinv */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse (cinv, c, c->length, ctx); fmpz_mod_poly_inv_series (cinv, cinv, c->length, ctx); fmpz_mod_poly_rem(a, a, c, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(cinv, a, b, c, cinv, ctx); if (!fmpz_mod_poly_equal(d, cinv, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod_brent_kung_vec_preinv.c000066400000000000000000000064221461254215100266320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2014 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, ainv, b, c; fmpz_t p; slong l, j, k; fmpz_mod_poly_struct * pow, * res; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(ainv, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1, ctx); l = 1 + n_randint(state, 20); k = 1 + n_randint(state, l); fmpz_mod_poly_reverse(ainv, a, a->length, ctx); fmpz_mod_poly_inv_series(ainv, ainv, a->length, ctx); pow = (fmpz_mod_poly_struct *) flint_malloc((l + k)*sizeof(fmpz_mod_poly_struct)); res = pow + l; fmpz_mod_poly_rem(b, b, a, ctx); for (j = 0; j < l; j++) { fmpz_mod_poly_init(pow + j, ctx); fmpz_mod_poly_randtest(pow + j, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_rem(pow + j, pow + j, a, ctx); } for (j = 0; j < k; j++) { fmpz_mod_poly_init(res + j, ctx); } fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(res, pow, l, k, b, a, ainv, ctx); for (j = 0; j < k; j++) { fmpz_mod_poly_compose_mod(c, pow + j, b, a, ctx); if (!fmpz_mod_poly_equal(res + j, c, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res + j, ctx); flint_printf("\n"); flint_printf("pow:\n"); fmpz_mod_poly_print(pow + j, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("j: %wd\n", j); fflush(stdout); flint_abort(); } } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(ainv, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); for (j = 0; j < l; j++) fmpz_mod_poly_clear(pow + j, ctx); for (j = 0; j < k; j++) fmpz_mod_poly_clear(res + j, ctx); flint_free(pow); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000070321461254215100304700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded, state) { int i; int tmul = 200; fmpz_mod_ctx_t ctx; #ifdef _WIN32 tmul = 1; #endif fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, ainv, b, c; fmpz_t p; slong l, j, k; fmpz_mod_poly_struct * pow, * res; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); flint_set_num_threads(1 + n_randint(state, 3)); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(ainv, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1, ctx); l = n_randint(state, 20) + 1; k = n_randint(state, l ) + 1; fmpz_mod_poly_reverse(ainv, a, a->length, ctx); fmpz_mod_poly_inv_series(ainv, ainv, a->length, ctx); pow = (fmpz_mod_poly_struct *) flint_malloc((l + k) * sizeof(fmpz_mod_poly_struct)); res = pow + l; fmpz_mod_poly_rem(b, b, a, ctx); for (j = 0; j < l; j++) { fmpz_mod_poly_init(pow + j, ctx); fmpz_mod_poly_randtest(pow + j, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_rem(pow + j, pow + j, a, ctx); } for (j = 0; j < k; j++) fmpz_mod_poly_init(res + j, ctx); fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded(res, pow, l, k, b, a, ainv, ctx); for (j = 0; j < k; j++) { fmpz_mod_poly_compose_mod(c, pow + j, b, a, ctx); if (!fmpz_mod_poly_equal(res + j, c, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res + j, ctx); flint_printf("\n"); flint_printf("pow:\n"); fmpz_mod_poly_print(pow + j, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("j: %wd\n", j); fflush(stdout); flint_abort(); } } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(ainv, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); for (j = 0; j < l; j++) fmpz_mod_poly_clear(pow + j, ctx); for (j = 0; j < k; j++) fmpz_mod_poly_clear(res + j, ctx); flint_free(pow); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-compose_mod_horner.c000066400000000000000000000150101461254215100235420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_compose_mod_horner, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d, e; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(e, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod_horner(d, a, b, c, ctx); fmpz_mod_poly_compose(e, a, b, ctx); fmpz_mod_poly_rem(e, e, c, ctx); if (!fmpz_mod_poly_equal(d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); flint_printf("e:\n"); fmpz_mod_poly_print(e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(e, ctx); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod_horner(d, a, b, c, ctx); fmpz_mod_poly_compose_mod_horner(a, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod_horner(d, a, b, c, ctx); fmpz_mod_poly_compose_mod_horner(b, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, d; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_compose_mod_horner(d, a, b, c, ctx); fmpz_mod_poly_compose_mod_horner(c, a, b, c, ctx); if (!fmpz_mod_poly_equal(d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx); flint_printf("\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("d:\n"); fmpz_mod_poly_print(d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-deflate_deflation_inflate.c000066400000000000000000000034201461254215100250160ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_deflate_deflation_inflate, state) { slong i; /* Compare with left truncated product of a and b */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_poly_t a, b, c; ulong k; fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(c, state, n_randint(state, 50), ctx); fmpz_mod_poly_inflate(b, b, n_randint(state, 5), ctx); k = fmpz_mod_poly_deflation(b, ctx); if (k > 0) { fmpz_mod_poly_deflate(a, b, k, ctx); fmpz_mod_poly_inflate(c, a, k, ctx); FLINT_TEST(fmpz_mod_poly_equal(b, c, ctx)); fmpz_mod_poly_inflate(a, a, k, ctx); FLINT_TEST(fmpz_mod_poly_equal(a, c, ctx)); } else { FLINT_TEST(fmpz_mod_poly_is_zero(b, ctx)); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-derivative.c000066400000000000000000000107321461254215100220310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_derivative, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_set(b, a, ctx); fmpz_mod_poly_derivative(c, b, ctx); fmpz_mod_poly_derivative(b, b, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL (alias):\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check constants have derivative zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 2), ctx); fmpz_mod_poly_derivative(b, a, ctx); result = (b->length == 0); if (!result) { flint_printf("FAIL (da == 0):\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(p); } /* Check (f g)' = f' g + f g' */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d, lhs, rhs; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(lhs, ctx); fmpz_mod_poly_init(rhs, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_mul(lhs, a, b, ctx); fmpz_mod_poly_derivative(lhs, lhs, ctx); fmpz_mod_poly_derivative(c, a, ctx); fmpz_mod_poly_derivative(d, b, ctx); fmpz_mod_poly_mul(c, c, b, ctx); fmpz_mod_poly_mul(d, a, d, ctx); fmpz_mod_poly_add(rhs, c, d, ctx); result = fmpz_mod_poly_equal(lhs, rhs, ctx); if (!result) { flint_printf("FAIL (Leibniz):\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("(ab)' = "), fmpz_mod_poly_print(lhs, ctx), flint_printf("\n\n"); flint_printf("a'b + ab' = "), fmpz_mod_poly_print(rhs, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(lhs, ctx); fmpz_mod_poly_clear(rhs, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-discriminant.c000066400000000000000000000067341461254215100223620ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_discriminant, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check disc(fg) == disc(f) * disc(g) * res(f, g)^2 */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t f, g, h; fmpz_t x, y, z, r; fmpz_t n; fmpz_init(n); fmpz_init(x); fmpz_init(y); fmpz_init(z); fmpz_init(r); fmpz_set_ui(n, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, n); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(h, ctx); do { fmpz_mod_poly_randtest(f, state, n_randint(state, 200), ctx); } while (f->length < 2); do { fmpz_mod_poly_randtest(g, state, n_randint(state, 200), ctx); } while (g->length < 2); fmpz_mod_poly_discriminant(y, f, ctx); fmpz_mod_poly_discriminant(z, g, ctx); fmpz_mod_mul(y, y, z, ctx); fmpz_mod_poly_resultant(r, f, g, ctx); fmpz_mod_mul(r, r, r, ctx); fmpz_mod_mul(y, y, r, ctx); fmpz_mod_poly_mul(h, f, g, ctx); fmpz_mod_poly_discriminant(x, h, ctx); result = (fmpz_equal(x, y)); if (!result) { flint_printf("FAIL (disc(fg) == res(f, g)^2 * disc(f) * disc(g):\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); flint_printf("x = "); fmpz_print(x); printf("\n"); flint_printf("y = "); fmpz_print(y); printf("\n"); flint_printf("z = "); fmpz_print(z); printf("\n"); flint_printf("n = "); fmpz_print(n); printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); fmpz_clear(r); } /* Check disc(f) == 0 for length < 2 */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t f; fmpz_t y; fmpz_t n; fmpz_init(y); fmpz_init(n); fmpz_set_ui(n, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, n); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest(f, state, 1, ctx); fmpz_mod_poly_discriminant(y, f, ctx); result = fmpz_is_zero(y); if (!result) { flint_printf("FAIL disc(f) == 0 for len f < 2:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_clear(y); fmpz_mod_poly_clear(f, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-div.c000066400000000000000000000134411461254215100204510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_div, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Compare to divrem */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, q2, r2; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(q2, ctx); fmpz_mod_poly_init(r2, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_div(q, a, b, ctx); fmpz_mod_poly_divrem(q2, r2, a, b, ctx); result = (fmpz_mod_poly_equal(q, q2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("q2 = "), fmpz_mod_poly_print(q2, ctx), flint_printf("\n\n"); flint_printf("r2 = "), fmpz_mod_poly_print(r2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(q2, ctx); fmpz_mod_poly_clear(r2, ctx); fmpz_clear(p); } /* Alias a and q */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_div(q, a, b, ctx); fmpz_mod_poly_div(a, a, b, ctx); result = (fmpz_mod_poly_equal(q, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_clear(p); } /* Alias b and q */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_div(q, a, b, ctx); fmpz_mod_poly_div(b, a, b, ctx); result = (fmpz_mod_poly_equal(q, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-div_newton_n_preinv.c000066400000000000000000000215661461254215100237520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_div_newton_n_preinv, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Compare to div_basecase */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, q2, binv; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(q2, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_div(q, a, b, ctx); fmpz_mod_poly_div_newton_n_preinv(q2, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, q2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("q2 = "), fmpz_mod_poly_print(q2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(q2, ctx); fmpz_clear(p); } /* Alias a and q */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, binv; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_div_newton_n_preinv(q, a, b, binv, ctx); fmpz_mod_poly_div_newton_n_preinv(a, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_clear(p); } /* Alias b and q */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, binv; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_div_newton_n_preinv(q, a, b, binv, ctx); fmpz_mod_poly_div_newton_n_preinv(b, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_clear(p); } /* Alias binv and q */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, binv; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_div_newton_n_preinv(q, a, b, binv, ctx); fmpz_mod_poly_div_newton_n_preinv(binv, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, binv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("binv = "), fmpz_mod_poly_print(binv, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-div_series.c000066400000000000000000000047331461254215100220270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_div_series, state) { slong i, j; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check A*B^{-1} * B is congruent A mod t^n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d; slong n = n_randint(state, 80) + 1; fmpz_init(p); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); for (j = 0; j < 10; j++) { fmpz_mod_poly_randtest(a, state, n_randint(state, 80), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, ctx); if (fmpz_is_zero(b->coeffs + 0)) fmpz_add_ui(b->coeffs + 0, b->coeffs + 0, 1); fmpz_mod_poly_div_series(c, a, b, n, ctx); fmpz_mod_poly_mullow(d, c, b, n, ctx); if (!fmpz_mod_poly_equal_trunc(d, a, n, ctx)) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("d = "), fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-divides.c000066400000000000000000000147411461254215100213220ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_divides, state) { int i, result; /* Random polynomials */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q, prod; fmpz_mod_ctx_t ctx; int divides; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(prod, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 300), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 300), ctx); divides = fmpz_mod_poly_divides(q, a, b, ctx); fmpz_mod_poly_mul(prod, q, b, ctx); result = ((divides && fmpz_mod_poly_equal(a, prod, ctx)) || (!divides && fmpz_mod_poly_is_zero(q, ctx) && !fmpz_mod_poly_equal(prod, a, ctx))); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(prod, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(prod, ctx); } /* Random divisible polynomials */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q, prod; fmpz_mod_ctx_t ctx; int divides; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(prod, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 300), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 300), ctx); fmpz_mod_poly_mul(a, b, a, ctx); divides = fmpz_mod_poly_divides(q, a, b, ctx); fmpz_mod_poly_mul(prod, q, b, ctx); result = (divides && fmpz_mod_poly_equal(a, prod, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(prod, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(prod, ctx); } /* Check aliasing of a and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q; fmpz_mod_ctx_t ctx; int divides1, divides2; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); divides1 = fmpz_mod_poly_divides(q, a, b, ctx); divides2 = fmpz_mod_poly_divides(a, a, b, ctx); result = (divides1 == divides2 && fmpz_mod_poly_equal(q, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); } /* Check aliasing of b and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q; fmpz_mod_ctx_t ctx; int divides1, divides2; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); divides1 = fmpz_mod_poly_divides(q, a, b, ctx); divides2 = fmpz_mod_poly_divides(b, a, b, ctx); result = (divides1 == divides2 && fmpz_mod_poly_equal(q, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-divides_classical.c000066400000000000000000000150511461254215100233330ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_divides_classical, state) { int i, result; /* Random polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q, prod; fmpz_mod_ctx_t ctx; int divides; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(prod, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); divides = fmpz_mod_poly_divides_classical(q, a, b, ctx); fmpz_mod_poly_mul(prod, q, b, ctx); result = ((divides && fmpz_mod_poly_equal(a, prod, ctx)) || (!divides && fmpz_mod_poly_is_zero(q, ctx) && !fmpz_mod_poly_equal(prod, a, ctx))); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(prod, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(prod, ctx); } /* Random divisible polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q, prod; fmpz_mod_ctx_t ctx; int divides; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(prod, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_mul(a, b, a, ctx); divides = fmpz_mod_poly_divides_classical(q, a, b, ctx); fmpz_mod_poly_mul(prod, q, b, ctx); result = (divides && fmpz_mod_poly_equal(a, prod, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(prod, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(prod, ctx); } /* Check aliasing of a and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q; fmpz_mod_ctx_t ctx; int divides1, divides2; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); divides1 = fmpz_mod_poly_divides_classical(q, a, b, ctx); divides2 = fmpz_mod_poly_divides_classical(a, a, b, ctx); result = (divides1 == divides2 && fmpz_mod_poly_equal(q, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); } /* Check aliasing of b and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, q; fmpz_mod_ctx_t ctx; int divides1, divides2; fmpz_t n; fmpz_init(n); do fmpz_randtest_unsigned(n, state, 2 * FLINT_BITS); while (!fmpz_is_probabprime(n)); fmpz_mod_ctx_init(ctx, n); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); divides1 = fmpz_mod_poly_divides_classical(q, a, b, ctx); divides2 = fmpz_mod_poly_divides_classical(b, a, b, ctx); result = (divides1 == divides2 && fmpz_mod_poly_equal(q, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_ctx_clear(ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-divrem_basecase.c000066400000000000000000000144631461254215100230100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_divrem_basecase, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check q*b + r = a, no aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, r, t; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_divrem_basecase(q, r, a, b, ctx); fmpz_mod_poly_mul(t, q, b, ctx); fmpz_mod_poly_add(t, t, r, ctx); result = (fmpz_mod_poly_equal(a, t, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(p); } /* Alias a and q, b and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_divrem_basecase(q, r, a, b, ctx); fmpz_mod_poly_divrem_basecase(a, b, a, b, ctx); result = (fmpz_mod_poly_equal(q, a, ctx) && fmpz_mod_poly_equal(r, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } /* Alias b and q, a and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_divrem_basecase(q, r, a, b, ctx); fmpz_mod_poly_divrem_basecase(b, a, a, b, ctx); result = (fmpz_mod_poly_equal(q, b, ctx) && fmpz_mod_poly_equal(r, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-divrem_f.c000066400000000000000000000123711461254215100214630ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_divrem_f, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check q*b + r = a when gcd(lead(B),p) = 1, no aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t f, p; fmpz_mod_poly_t a, b, q, r, t; fmpz_init(f); fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_divrem_f(f, q, r, a, b, ctx); fmpz_mod_poly_mul(t, q, b, ctx); fmpz_mod_poly_add(t, t, r, ctx); result = (fmpz_is_one(f) && fmpz_mod_poly_equal(a, t, ctx)); if (!result) { flint_printf("FAIL (divrem):\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(f); fmpz_clear(p); } /* Check f | p when gcd(lead(B),p) > 1 */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t f, p, q1, q2; fmpz_mod_poly_t a, b, q, r, t; fmpz_init(f); fmpz_init(p); fmpz_init(q1); fmpz_init(q2); fmpz_randtest_unsigned(q1, state, 2 * FLINT_BITS); fmpz_randtest_unsigned(q2, state, 2 * FLINT_BITS); fmpz_add_ui(q1, q1, 2); fmpz_add_ui(q2, q2, 2); fmpz_mul(p, q1, q2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); if (fmpz_is_one(d)) fmpz_set(leadB, q1); fmpz_clear(d); } fmpz_mod_poly_divrem_f(f, q, r, a, b, ctx); fmpz_mod_poly_mul(t, q, b, ctx); fmpz_mod_poly_add(t, t, r, ctx); result = (fmpz_cmp_ui(f, 1) > 0 && fmpz_cmp(f, p) < 0 && fmpz_divisible(p, f)); if (!result) { flint_printf("FAIL (factor):\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n\n"); flint_printf("q1 = "), fmpz_print(q1), flint_printf("\n\n"); flint_printf("q2 = "), fmpz_print(q2), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(f); fmpz_clear(p); fmpz_clear(q1); fmpz_clear(q2); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000430571461254215100244550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_divrem_newton_n_preinv, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check q*b + r = a, no aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, binv, q, r, t, q2, r2; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(q2, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init(r2, ctx); fmpz_mod_poly_init(t, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_divrem_newton_n_preinv (q, r, a, b, binv, ctx); fmpz_mod_poly_mul(t, q, b, ctx); fmpz_mod_poly_add(t, t, r, ctx); result = (fmpz_mod_poly_equal(a, t, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_divrem_basecase(q2, r2, a, b, ctx); result = (fmpz_mod_poly_equal(q2, q, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("q2 = "), fmpz_mod_poly_print(q2, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(q2, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(r2, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(p); } /* Alias a and q, b and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, binv, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_divrem_newton_n_preinv(q, r, a, b, binv, ctx); fmpz_mod_poly_divrem_newton_n_preinv(a, b, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, a, ctx) && fmpz_mod_poly_equal(r, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } /* Alias b and q, a and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, binv, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_divrem_newton_n_preinv(q, r, a, b, binv, ctx); fmpz_mod_poly_divrem_newton_n_preinv(b, a, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, b, ctx) && fmpz_mod_poly_equal(r, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } /* Alias binv and q, a and r*/ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, binv, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_divrem_newton_n_preinv(q, r, a, b, binv, ctx); fmpz_mod_poly_divrem_newton_n_preinv(binv, a, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, binv, ctx) && fmpz_mod_poly_equal(r, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("binv = "), fmpz_mod_poly_print(binv, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } /* Alias binv and q, b and r*/ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, binv, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_divrem_newton_n_preinv(q, r, a, b, binv, ctx); fmpz_mod_poly_divrem_newton_n_preinv(binv, b, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, binv, ctx) && fmpz_mod_poly_equal(r, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("binv = "), fmpz_mod_poly_print(binv, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } /* Alias a and q, binv and r*/ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, binv, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_divrem_newton_n_preinv(q, r, a, b, binv, ctx); fmpz_mod_poly_divrem_newton_n_preinv(a, binv, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, a, ctx) && fmpz_mod_poly_equal(r, binv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("binv = "), fmpz_mod_poly_print(binv, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } /* Alias b and q, binv and r*/ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, binv, q, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(binv, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); while (b->length <= 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); if (a->length > 2*(b->length)-3) fmpz_mod_poly_truncate (a, 2*(b->length)-3, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_reverse (binv, b, b->length, ctx); fmpz_mod_poly_inv_series (binv, binv, b->length, ctx); fmpz_mod_poly_divrem_newton_n_preinv(q, r, a, b, binv, ctx); fmpz_mod_poly_divrem_newton_n_preinv(b, binv, a, b, binv, ctx); result = (fmpz_mod_poly_equal(q, b, ctx) && fmpz_mod_poly_equal(r, binv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("binv = "), fmpz_mod_poly_print(binv, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(binv, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-evaluate_fmpz.c000066400000000000000000000060741461254215100225350ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_evaluate_fmpz, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, p; fmpz_mod_poly_t f; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(a); fmpz_init(b); fmpz_randm(a, state, p); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 100), ctx); fmpz_mod_poly_evaluate_fmpz(b, f, a, ctx); fmpz_mod_poly_evaluate_fmpz(a, f, a, ctx); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(f, ctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(p); } /* Check that the result agrees with Z[X] */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, p; fmpz_mod_poly_t f; fmpz_poly_t g; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_mod_poly_init(f, ctx); fmpz_poly_init(g); fmpz_randm(a, state, p); fmpz_mod_poly_randtest(f, state, n_randint(state, 100), ctx); fmpz_mod_poly_get_fmpz_poly(g, f, ctx); fmpz_mod_poly_evaluate_fmpz(b, f, a, ctx); fmpz_poly_evaluate_fmpz(c, g, a); fmpz_mod(c, c, p); result = (fmpz_equal(b, c)); if (!result) { flint_printf("FAIL (cmp with fmpz_poly):\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fmpz_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(p); fmpz_mod_poly_clear(f, ctx); fmpz_poly_clear(g); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-evaluate_fmpz_vec.c000066400000000000000000000050311461254215100233620ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 William Hart Copyright (C) 2011, 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_evaluate_fmpz_vec, state) { int i, result = 1; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t P; fmpz * x, * y, * z; fmpz_t mod; slong j, n, npoints; fmpz_init(mod); do { fmpz_randtest_unsigned(mod, state, 5); fmpz_add_ui(mod, mod, 2); } while (!fmpz_is_probabprime(mod)); fmpz_mod_ctx_set_modulus(ctx, mod); npoints = n_randint(state, 10); n = n_randint(state, FMPZ_MOD_POLY_EVALUATE_FMPZ_VEC + 2); fmpz_mod_poly_init(P, ctx); x = _fmpz_vec_init(npoints); y = _fmpz_vec_init(npoints); z = _fmpz_vec_init(npoints); fmpz_mod_poly_randtest(P, state, n, ctx); for (j = 0; j < npoints; j++) fmpz_randtest_mod(x + j, state, mod); if (npoints < FMPZ_MOD_POLY_EVALUATE_FMPZ_VEC) { fmpz_mod_poly_evaluate_fmpz_vec(y, P, x, npoints, ctx); fmpz_mod_poly_evaluate_fmpz_vec_fast(z, P, x, npoints, ctx); } else { fmpz_mod_poly_evaluate_fmpz_vec_iter(y, P, x, npoints, ctx); fmpz_mod_poly_evaluate_fmpz_vec(z, P, x, npoints, ctx); } result = _fmpz_vec_equal(y, z, npoints); if (!result) flint_throw(FLINT_TEST_FAIL, "mod = %{fmpz}\n" "n = %wd\n" "npoints = %wd\n\n" "P = %{fmpz_mod_poly}\n\n" "y = %{fmpz*}\n\n" "z = %{fmpz*}\n", mod, n, npoints, P, y, npoints, z, npoints); fmpz_clear(mod); fmpz_mod_poly_clear(P, ctx); _fmpz_vec_clear(x, npoints); _fmpz_vec_clear(y, npoints); _fmpz_vec_clear(z, npoints); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-find_distinct_nonzero_roots.c000066400000000000000000000066501461254215100255140ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_find_distinct_nonzero_roots, state) { slong i, j; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 200 * flint_test_multiplier(); i++) { int highdegreefactor; fmpz_mod_poly_t a, b, r; fmpz_t p, e, zero; fmpz_init(zero); fmpz_init_set_ui(p, n_randtest_prime(state, 1)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(e); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_set_ui(a, 1 + n_randint(state, fmpz_get_ui(p) - 1), ctx); highdegreefactor = 0; for (j = n_randint(state, 10); j >= 0; j--) { if (n_randint(state, 10) > 1) { fmpz_mod_poly_randtest_monic_irreducible(b, state, 1, ctx); } else { highdegreefactor = 1; fmpz_mod_poly_randtest_monic_irreducible(b, state, 2 + n_randint(state, 9), ctx); } fmpz_mod_poly_mul(a, a, b, ctx); } fmpz_mod_poly_fit_length(r, fmpz_mod_poly_degree(a, ctx), ctx); if (fmpz_mod_poly_find_distinct_nonzero_roots(r->coeffs, a, ctx)) { /* check that a is square free */ fmpz_mod_poly_derivative(b, a, ctx); fmpz_mod_poly_gcd(b, b, a, ctx); if (fmpz_mod_poly_degree(b, ctx) > 0) { flint_printf("FAIL\ncheck multiple roots i = %wd\n", i); fflush(stdout); flint_abort(); } /* check that each root is a root */ for (j = fmpz_mod_poly_degree(a, ctx) - 1; j >= 0; j--) { if (fmpz_is_zero(r->coeffs + j)) { flint_printf("FAIL\ncheck zero root i = %wd\n", i); fflush(stdout); flint_abort(); } if (fmpz_mod_poly_evaluate_fmpz(e, a, r->coeffs + j, ctx), !fmpz_is_zero(e)) { flint_printf("FAIL\ncheck root is a root i = %wd\n", i); fflush(stdout); flint_abort(); } } } else { fmpz_mod_poly_derivative(b, a, ctx); fmpz_mod_poly_gcd(b, b, a, ctx); if (!highdegreefactor && fmpz_mod_poly_degree(b, ctx) == 0 && (fmpz_mod_poly_evaluate_fmpz(e, a, zero, ctx), !fmpz_is_zero(e))) { flint_printf("FAIL\ncheck fail return i = %wd\n", i); fflush(stdout); flint_abort(); } } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); fmpz_clear(e); fmpz_clear(zero); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-frobenius_powers_precomp.c000066400000000000000000000075661461254215100250220ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_frobenius_powers_precomp, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Aliasing of res and f */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t res, f, finv; fmpz_mod_poly_frobenius_powers_2exp_t pow; fmpz_t p; ulong exp; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_frobenius_powers_2exp_precomp(pow, f, finv, exp, ctx); fmpz_mod_poly_frobenius_power(res, pow, f, exp, ctx); fmpz_mod_poly_frobenius_power(f, pow, f, exp, ctx); result = (fmpz_mod_poly_equal(res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_mod_poly_frobenius_powers_2exp_clear(pow, ctx); } /* Compare powers_2exp and powers */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t res, f, finv; fmpz_mod_poly_frobenius_powers_t pow; fmpz_mod_poly_frobenius_powers_2exp_t pow2; fmpz_t p; ulong exp, exp2; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50) + 1; exp2 = n_randint(state, exp); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_frobenius_powers_precomp(pow, f, finv, exp, ctx); fmpz_mod_poly_frobenius_powers_2exp_precomp(pow2, f, finv, exp, ctx); fmpz_mod_poly_frobenius_power(res, pow2, f, exp2, ctx); result = (fmpz_mod_poly_equal(res, pow->pow + exp2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("pow->pow + exp2:\n"); fmpz_mod_poly_print(pow->pow + exp2, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_mod_poly_frobenius_powers_clear(pow, ctx); fmpz_mod_poly_frobenius_powers_2exp_clear(pow2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-gcd.c000066400000000000000000000252721461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_gcd, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Generic case, most likely co-prime arguments ******************************/ /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_gcd(c, a, b, ctx); fmpz_mod_poly_gcd(a, a, b, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_gcd(c, a, b, ctx); fmpz_mod_poly_gcd(b, a, b, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check that g = GCD(a,b) divides a and b, and that 1 == GCD(a/g, b/g) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d, g, h, s, t; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_gcd(g, a, b, ctx); if (fmpz_mod_poly_is_zero(g, ctx)) { result = 1; } else { fmpz_mod_poly_divrem_basecase(c, s, a, g, ctx); fmpz_mod_poly_divrem_basecase(d, t, b, g, ctx); fmpz_mod_poly_gcd(h, c, d, ctx); result = (fmpz_mod_poly_is_zero(s, ctx) && fmpz_mod_poly_is_zero(t, ctx) && (h->length == 1) && (fmpz_is_one(h->coeffs))); } if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("d = "), fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); flint_printf("g = "), fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("h = "), fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); flint_printf("s = "), fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(p); } /* Special case, arguments share a factor ********************************/ /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, f; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 20), ctx); fmpz_mod_poly_mul(a, a, f, ctx); fmpz_mod_poly_mul(b, b, f, ctx); fmpz_mod_poly_gcd(c, a, b, ctx); fmpz_mod_poly_gcd(a, a, b, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, f; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 20), ctx); fmpz_mod_poly_mul(a, a, f, ctx); fmpz_mod_poly_mul(b, b, f, ctx); fmpz_mod_poly_gcd(c, a, b, ctx); fmpz_mod_poly_gcd(b, a, b, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_clear(p); } /* Check that g = GCD(a,b) divides a and b, and that 1 == GCD(a/g, b/g) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d, f, g, h, s, t; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 20), ctx); fmpz_mod_poly_mul(a, a, f, ctx); fmpz_mod_poly_mul(b, b, f, ctx); fmpz_mod_poly_gcd(g, a, b, ctx); if (fmpz_mod_poly_is_zero(g, ctx)) { result = 1; } else { fmpz_mod_poly_divrem_basecase(c, s, a, g, ctx); fmpz_mod_poly_divrem_basecase(d, t, b, g, ctx); fmpz_mod_poly_gcd(h, c, d, ctx); result = (fmpz_mod_poly_is_zero(s, ctx) && fmpz_mod_poly_is_zero(t, ctx) && (h->length == 1) && (fmpz_is_one(h->coeffs))); } if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("d = "), fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); flint_printf("g = "), fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("h = "), fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); flint_printf("s = "), fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-gcd_euclidean_f.c000066400000000000000000000047341461254215100227470ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_gcd_euclidean_f, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Compare with the usual GCD function. N.B. I checked by hand that this test shows both outcomes, i.e. trivial and non-trivial factors, sufficiently frequently. */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p, f; fmpz_mod_poly_t a, b, c, d; fmpz_init(f); fmpz_init(p); fmpz_randtest_unsigned(p, state, 100); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 60), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 60), ctx); fmpz_mod_poly_gcd_euclidean_f(f, c, a, b, ctx); if (!fmpz_is_one(f)) { result = 1; } else { fmpz_mod_poly_gcd(d, a, b, ctx); result = fmpz_mod_poly_equal(c, d, ctx); } if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("d = "), fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_clear(f); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-gcdinv.c000066400000000000000000000105231461254215100211370ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_gcdinv, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Generic case, most likely co-prime arguments ******************************/ /* Check s*a == g mod b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, g, s, u; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(u, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 2); fmpz_mod_poly_gcdinv(g, s, a, b, ctx); fmpz_mod_poly_mul(u, s, a, ctx); fmpz_mod_poly_rem(u, u, b, ctx); result = (fmpz_mod_poly_equal(g, u, ctx) || fmpz_mod_poly_is_zero(g, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("g = "), fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("s = "), fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); flint_printf("u = "), fmpz_mod_poly_print(u, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(u, ctx); fmpz_clear(p); } /* Special case, arguments share a factor ********************************/ /* Check s*a == g mod b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, g, s, u; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(u, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 2); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_mul(a, f, a, ctx); fmpz_mod_poly_mul(b, f, b, ctx); fmpz_mod_poly_gcdinv(g, s, a, b, ctx); fmpz_mod_poly_mul(u, s, a, ctx); fmpz_mod_poly_rem(u, u, b, ctx); result = (fmpz_mod_poly_equal(u, g, ctx) || fmpz_mod_poly_is_zero(g, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f = "), fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("g = "), fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("s = "), fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); flint_printf("u = "), fmpz_mod_poly_print(u, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(u, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-gcdinv_euclidean.c000066400000000000000000000105611461254215100231520ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_gcdinv_euclidean, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Generic case, most likely co-prime arguments ******************************/ /* Check s*a == g mod b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, g, s, u; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(u, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 2); fmpz_mod_poly_gcdinv_euclidean(g, s, a, b, ctx); fmpz_mod_poly_mul(u, s, a, ctx); fmpz_mod_poly_rem(u, u, b, ctx); result = (fmpz_mod_poly_equal(g, u, ctx) || fmpz_mod_poly_is_zero(g, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("g = "), fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("s = "), fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); flint_printf("u = "), fmpz_mod_poly_print(u, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(u, ctx); fmpz_clear(p); } /* Special case, arguments share a factor ********************************/ /* Check s*a == g mod b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, g, s, u; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(u, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 2); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_mul(a, f, a, ctx); fmpz_mod_poly_mul(b, f, b, ctx); fmpz_mod_poly_gcdinv_euclidean(g, s, a, b, ctx); fmpz_mod_poly_mul(u, s, a, ctx); fmpz_mod_poly_rem(u, u, b, ctx); result = (fmpz_mod_poly_equal(u, g, ctx) || fmpz_mod_poly_is_zero(g, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f = "), fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("g = "), fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("s = "), fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); flint_printf("u = "), fmpz_mod_poly_print(u, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(u, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-get_set_fmpz_poly.c000066400000000000000000000033431461254215100234200ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_get_set_fmpz_poly, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b; fmpz_poly_t c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_poly_init(c); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_get_fmpz_poly(c, a, ctx); fmpz_mod_poly_set_fmpz_poly(b, c, ctx); result = fmpz_mod_poly_equal(a, b, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n"); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_poly_clear(c); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-get_set_nmod_poly.c000066400000000000000000000033521461254215100234010ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_get_set_nmod_poly, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b; nmod_poly_t c; fmpz_init(p); fmpz_randtest_unsigned(p, state, FLINT_BITS - 1); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); nmod_poly_init(c, fmpz_get_ui(p)); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_get_nmod_poly(c, a); fmpz_mod_poly_set_nmod_poly(b, c); result = fmpz_mod_poly_equal(a, b, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n"); flint_printf("c = "), nmod_poly_print(c), flint_printf("\n"); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); nmod_poly_clear(c); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-init_realloc_clear.c000066400000000000000000000036401461254215100235010ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_init_realloc_clear, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init2(a, n_randint(state, 100), ctx); fmpz_mod_poly_clear(a, ctx); fmpz_clear(p); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init2(a, n_randint(state, 100), ctx); fmpz_mod_poly_realloc(a, n_randint(state, 100), ctx); fmpz_mod_poly_clear(a, ctx); fmpz_clear(p); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_clear(a, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-inv_series.c000066400000000000000000000045331461254215100220370ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_inv_series, state) { int i, result; /* Check Q^{-1} * Q is congruent 1 mod t^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_ctx_t ctx; fmpz_mod_poly_t a, b, c, one; slong n = n_randint(state, 80) + 1; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_init(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(one, ctx); fmpz_mod_poly_randtest_not_zero(a, state, n_randint(state, 80) + 1, ctx); { fmpz_t d; fmpz_init(d); fmpz_gcd(d, a->coeffs, p); while (!fmpz_is_one(d)) { fmpz_randm(a->coeffs, state, p); fmpz_gcd(d, a->coeffs, p); } fmpz_clear(d); } fmpz_mod_poly_set_ui(one, 1, ctx); fmpz_mod_poly_inv_series(b, a, n, ctx); fmpz_mod_poly_mullow(c, a, b, n, ctx); result = (fmpz_mod_poly_equal(c, one, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(one, ctx); fmpz_clear(p); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-invmod.c000066400000000000000000000152321461254215100211630ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_invmod, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Test aliasing *************************************************************/ /* Aliasing c and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; int ans1, ans2; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 3); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); ans1 = fmpz_mod_poly_invmod(c, a, b, ctx); ans2 = fmpz_mod_poly_invmod(a, a, b, ctx); result = (ans1 == ans2 && fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL (alias a and c):\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("ans1 = %d\n\n", ans1); flint_printf("ans2 = %d\n\n", ans2); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Aliasing c and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; int ans1, ans2; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 3); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); ans1 = fmpz_mod_poly_invmod(c, a, b, ctx); ans2 = fmpz_mod_poly_invmod(b, a, b, ctx); result = ((ans1 == ans2) && fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL (alias b and c):\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("ans1 = %d\n\n", ans1); flint_printf("ans2 = %d\n\n", ans2); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Compare with result from XGCD */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, g, s, t, u; int ans; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(u, ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 3); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); ans = fmpz_mod_poly_invmod(u, a, b, ctx); fmpz_mod_poly_xgcd(g, s, t, a, b, ctx); result = (((ans) && g->length == 1 && fmpz_is_one(g->coeffs) && fmpz_mod_poly_equal(s, u, ctx)) || (!(ans) && g->length > 1)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(u, ctx), flint_printf("\n\n"); flint_printf("ans = %d\n\n", ans); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(u, ctx); fmpz_clear(p); } /* Special case, arguments share a factor ********************************/ /* Check correctness */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, u; int ans; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(u, ctx); do fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); while (b->length < 2); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); do fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 20) + 1, ctx); while (f->length < 2); fmpz_mod_poly_mul(a, f, a, ctx); fmpz_mod_poly_mul(b, f, b, ctx); ans = fmpz_mod_poly_invmod(u, a, b, ctx); result = (!ans); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(u, ctx), flint_printf("\n\n"); flint_printf("ans = %d\n\n", ans); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(u, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-invsqrt_series.c000066400000000000000000000070321461254215100227460ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_invsqrt_series, state) { int i, result; /* Check 1/g^2 = h mod x^m */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t h, g, r; slong m; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, FLINT_BITS); if (!fmpz_equal_ui(fmpz_mod_ctx_modulus(ctx), 2)) { fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest(h, state, n_randint(state, 1000), ctx); while (h->length == 0); fmpz_mod_poly_set_coeff_ui(h, 0, 1, ctx); m = n_randint(state, h->length) + 1; fmpz_mod_poly_invsqrt_series(g, h, m, ctx); fmpz_mod_poly_mullow(r, g, g, m, ctx); fmpz_mod_poly_inv_series(r, r, m, ctx); fmpz_mod_poly_truncate(h, m, ctx); result = (fmpz_cmp_ui(ctx->n, 2) == 0) || (fmpz_mod_poly_equal(r, h, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("n = "); fmpz_print(ctx->n); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(r, ctx); } fmpz_mod_ctx_clear(ctx); } /* Check aliasing of h and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t g, h; slong m; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, FLINT_BITS); if (!fmpz_equal_ui(fmpz_mod_ctx_modulus(ctx), 2)) { fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(g, ctx); do fmpz_mod_poly_randtest(h, state, n_randint(state, 500), ctx); while (h->length == 0); fmpz_mod_poly_set_coeff_ui(h, 0, 1, ctx); m = n_randint(state, h->length) + 1; fmpz_mod_poly_invsqrt_series(g, h, m, ctx); fmpz_mod_poly_invsqrt_series(h, h, m, ctx); result = (fmpz_cmp_ui(ctx->n, 2) == 0) || fmpz_mod_poly_equal(g, h, ctx); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("n = "); fmpz_print(ctx->n); flint_printf("\n"); flint_printf("m = %wd\n", m); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); } fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-minpoly.c000066400000000000000000000140511461254215100213540ustar00rootroot00000000000000/* This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /****************************************************************************** Authored 2016 by Daniel S. Roche; US Government work in the public domain ******************************************************************************/ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" /* checks that poly actually annihilates the given sequence. */ int check(const fmpz_mod_poly_t poly, const fmpz* seq, slong len, const fmpz_mod_ctx_t ctx) { fmpz_t sum, temp; slong d = fmpz_mod_poly_degree(poly, ctx); int i, j; if (d < 0) return 0; fmpz_init(sum); fmpz_init(temp); for (i=0; i < len-d; ++i) { fmpz_zero(sum); for (j=0; j fmpz_mod_poly_degree(poly2, ctx)) { flint_printf("FAIL 1:\n"); _fmpz_vec_print(seq, len); flint_printf("\n\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (!check(poly2, seq, len, ctx) || fmpz_mod_poly_degree(poly2, ctx) > fmpz_mod_poly_degree(poly1, ctx)) { flint_printf("FAIL 2:\n"); _fmpz_vec_print(seq, len); flint_printf("\n\n"); fmpz_mod_poly_print(poly2, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); fmpz_clear(p); _fmpz_vec_clear(seq, len); } /* test sequences with a known generator */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz* seq; slong len, d; fmpz_mod_poly_t poly1, poly2, gen, rem; fmpz_t p, temp; int j, k; fmpz_init(p); fmpz_init(temp); fmpz_randprime(p, state, 100, 0); fmpz_mod_ctx_set_modulus(ctx, p); len = n_randtest(state) % UWORD(200) + 2; seq = _fmpz_vec_init(len); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly2, ctx); fmpz_mod_poly_init(gen, ctx); fmpz_mod_poly_init(rem, ctx); fmpz_mod_poly_randtest_monic(gen, state, n_randint(state, len/2)+2, ctx); d = fmpz_mod_poly_degree(gen, ctx); FLINT_ASSERT (d > 0); for (j=0; j. */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_mul, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(c, state, n_randint(state, 50), ctx); fmpz_mod_poly_mul(a, b, c, ctx); fmpz_mod_poly_mul(b, b, c, ctx); result = (fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(c, state, n_randint(state, 50), ctx); fmpz_mod_poly_mul(a, b, c, ctx); fmpz_mod_poly_mul(c, b, c, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a1, a2, b, c, d; fmpz_t p; fmpz_init(p); if (n_randint(state, 100) == 0) { flint_set_num_threads(2 + n_randint(state, 3)); fmpz_randtest_unsigned(p, state, 40000); } else { flint_set_num_threads(1); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); } fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a1, ctx); fmpz_mod_poly_init(a2, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(c, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(d, state, n_randint(state, 100), ctx); fmpz_mod_poly_mul(a1, b, c, ctx); fmpz_mod_poly_mul(a2, b, d, ctx); fmpz_mod_poly_add(a1, a1, a2, ctx); fmpz_mod_poly_add(c, c, d, ctx); fmpz_mod_poly_mul(a2, b, c, ctx); result = (fmpz_mod_poly_equal(a1, a2, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a1, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(a2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a1, ctx); fmpz_mod_poly_clear(a2, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-mulhigh.c000066400000000000000000000031451461254215100213240ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_mulhigh, state) { slong i; /* Compare with left truncated product of a and b */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mod_ctx_t ctx; fmpz_mod_poly_t a, b, c; slong j, n; fmpz_mod_ctx_init_rand_bits(ctx, state, 200); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); n = n_randint(state, 50); fmpz_mod_poly_randtest(b, state, n, ctx); fmpz_mod_poly_randtest(c, state, n, ctx); fmpz_mod_poly_mulhigh(a, b, c, n, ctx); fmpz_mod_poly_mul(b, b, c, ctx); for (j = 0; j < n; j++) { if (j < a->length) fmpz_zero(a->coeffs + j); if (j < b->length) fmpz_zero(b->coeffs + j); } _fmpz_mod_poly_normalise(a); _fmpz_mod_poly_normalise(b); FLINT_TEST(fmpz_mod_poly_equal(a, b, ctx)); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-mullow.c000066400000000000000000000035451461254215100212120ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_mullow, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; slong trunc; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); trunc = n_randint(state, 50); fmpz_mod_poly_randtest(b, state, trunc, ctx); fmpz_mod_poly_randtest(c, state, trunc, ctx); fmpz_mod_poly_mullow(a, b, c, trunc, ctx); fmpz_mod_poly_mul(b, b, c, ctx); fmpz_mod_poly_truncate(b, trunc, ctx); result = (fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-mulmod.c000066400000000000000000000153271461254215100211710ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_mulmod, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of res and a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, res, f; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_mulmod(res, a, b, f, ctx); fmpz_mod_poly_mulmod(a, a, b, f, ctx); result = (fmpz_mod_poly_equal(res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(p); } /* Check aliasing of res and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, res; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_mulmod(res, a, b, f, ctx); fmpz_mod_poly_mulmod(b, a, b, f, ctx); result = (fmpz_mod_poly_equal(res, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(p); } /* Check aliasing of res and f */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, res; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_mulmod(res, a, b, f, ctx); fmpz_mod_poly_mulmod(f, a, b, f, ctx); result = (fmpz_mod_poly_equal(res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(p); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, res1, res2, t, f; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_mulmod(res1, a, b, f, ctx); fmpz_mod_poly_mul(res2, a, b, ctx); fmpz_mod_poly_divrem(t, res2, res2, f, ctx); result = (fmpz_mod_poly_equal(res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); fmpz_mod_poly_print(res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-mulmod_preinv.c000066400000000000000000000240561461254215100225530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_mulmod_preinv, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of res and a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, res, f, finv; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); if (a->length >= f->length) fmpz_mod_poly_rem (a, a, f, ctx); if (b->length >= f->length) fmpz_mod_poly_rem (b, b, f, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_mulmod_preinv(res, a, b, f, finv, ctx); fmpz_mod_poly_mulmod_preinv(a, a, b, f, finv, ctx); result = (fmpz_mod_poly_equal(res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(p); } /* Check aliasing of res and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, finv, res; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); if (a->length >= f->length) fmpz_mod_poly_rem (a, a, f, ctx); if (b->length >= f->length) fmpz_mod_poly_rem (b, b, f, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_mulmod_preinv(res, a, b, f, finv, ctx); fmpz_mod_poly_mulmod_preinv(b, a, b, f, finv, ctx); result = (fmpz_mod_poly_equal(res, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(p); } /* Check aliasing of res and f */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, finv, res; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); if (a->length >= f->length) fmpz_mod_poly_rem (a, a, f, ctx); if (b->length >= f->length) fmpz_mod_poly_rem (b, b, f, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_mulmod_preinv(res, a, b, f, finv, ctx); fmpz_mod_poly_mulmod_preinv(f, a, b, f, finv, ctx); result = (fmpz_mod_poly_equal(res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(p); } /* Check aliasing of res and finv */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, f, finv, res; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); if (a->length >= f->length) fmpz_mod_poly_rem (a, a, f, ctx); if (b->length >= f->length) fmpz_mod_poly_rem (b, b, f, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_mulmod_preinv(res, a, b, f, finv, ctx); fmpz_mod_poly_mulmod_preinv(finv, a, b, f, finv, ctx); result = (fmpz_mod_poly_equal(res, finv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(p); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, res1, res2, f, finv; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); if (a->length >= f->length) fmpz_mod_poly_rem (a, a, f, ctx); if (b->length >= f->length) fmpz_mod_poly_rem (b, b, f, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_mulmod(res1, a, b, f, ctx); fmpz_mod_poly_mulmod_preinv(res2, a, b, f, finv, ctx); result = (fmpz_mod_poly_equal(res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); fmpz_mod_poly_print(res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-neg.c000066400000000000000000000033501461254215100204360ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_neg, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_neg(b, a, ctx); fmpz_mod_poly_neg(c, b, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-pow_trunc.c000066400000000000000000000070431461254215100217100ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_pow_trunc, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c; fmpz_t p; slong e, trunc; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 30), ctx); e = n_randint(state, 20); trunc = n_randint(state, 30); fmpz_mod_poly_set(c, a, ctx); fmpz_mod_poly_pow_trunc(b, a, e, trunc, ctx); fmpz_mod_poly_pow_trunc(c, c, e, trunc, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL aliasing:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); } /* Check powering against naive method */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c; fmpz_t p; slong e, trunc; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 30), ctx); e = n_randint(state, 20); trunc = n_randint(state, 30); fmpz_mod_poly_pow_trunc(b, a, e, trunc, ctx); fmpz_mod_poly_pow(c, a, e, ctx); fmpz_mod_poly_truncate(c, trunc, ctx); result = (fmpz_mod_poly_equal(b, c, ctx) || (a->length == 0 && e == 0 && c->length == 1 && c->coeffs[0] == 1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-pow_trunc_binexp.c000066400000000000000000000070661461254215100232620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_pow_trunc_binexp, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c; fmpz_t p; slong e, trunc; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 30), ctx); e = n_randint(state, 20); trunc = n_randint(state, 30); fmpz_mod_poly_set(c, a, ctx); fmpz_mod_poly_pow_trunc_binexp(b, a, e, trunc, ctx); fmpz_mod_poly_pow_trunc_binexp(c, c, e, trunc, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); } /* Check powering against naive method */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c; fmpz_t p; slong e, trunc; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 30), ctx); e = n_randint(state, 20); trunc = n_randint(state, 30); fmpz_mod_poly_pow_trunc_binexp(b, a, e, trunc, ctx); fmpz_mod_poly_pow(c, a, e, ctx); fmpz_mod_poly_truncate(c, trunc, ctx); result = (fmpz_mod_poly_equal(b, c, ctx) || (a->length == 0 && e == 0 && c->length == 1 && c->coeffs[0] == 1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-powers_mod_bsgs.c000077500000000000000000000055601461254215100230710ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_powers_mod_bsgs, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i, result, max_threads = 5; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Compare with powmod */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t f, g, pow; fmpz_mod_poly_struct * res; fmpz_t n; ulong exp; slong j; fmpz_init(n); flint_set_num_threads(n_randint(state, max_threads)); fmpz_randprime(n, state, 100, 0); fmpz_mod_ctx_set_modulus(ctx, n); exp = n_randint(state, 32); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(pow, ctx); res = (fmpz_mod_poly_struct *) flint_malloc(exp*sizeof(fmpz_mod_poly_struct)); for (j = 0; j < exp; j++) fmpz_mod_poly_init(res + j, ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(g, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powers_mod_bsgs(res, f, exp, g, ctx); result = 1; j = 0; if (exp > 0) { fmpz_mod_poly_one(pow, ctx); result = fmpz_mod_poly_equal(res + 0, pow, ctx); } for (j = 1 ; j < exp && result; j++) { fmpz_mod_poly_mulmod(pow, pow, f, g, ctx); result &= fmpz_mod_poly_equal(res + j, pow, ctx); } j--; if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("g:\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("j: %w\n", j); flint_printf("pow:\n"); fmpz_mod_poly_print(pow, ctx), flint_printf("\n\n"); flint_printf("res[%w]:\n", j); fmpz_mod_poly_print(res + j, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(pow, ctx); for (j = 0; j < exp; j++) fmpz_mod_poly_clear(res + j, ctx); flint_free(res); fmpz_clear(n); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/fmpz_mod_poly/test/t-powers_mod_naive.c000077500000000000000000000052631461254215100232350ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_powers_mod_naive, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Compare with powmod */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t f, g, pow; fmpz_mod_poly_struct * res; fmpz_t n; ulong exp; slong j; fmpz_init(n); fmpz_randprime(n, state, 100, 0); fmpz_mod_ctx_set_modulus(ctx, n); exp = n_randint(state, 32); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(pow, ctx); res = (fmpz_mod_poly_struct *) flint_malloc(exp*sizeof(fmpz_mod_poly_struct)); for (j = 0; j < exp; j++) fmpz_mod_poly_init(res + j, ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(g, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powers_mod_naive(res, f, exp, g, ctx); result = 1; j = 0; if (exp > 0) { fmpz_mod_poly_one(pow, ctx); result = fmpz_mod_poly_equal(res + 0, pow, ctx); } for (j = 1 ; j < exp && result; j++) { fmpz_mod_poly_mulmod(pow, pow, f, g, ctx); result &= fmpz_mod_poly_equal(res + j, pow, ctx); } j--; if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("g:\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("j: %w\n", j); flint_printf("pow:\n"); fmpz_mod_poly_print(pow, ctx), flint_printf("\n\n"); flint_printf("res[%w]:\n", j); fmpz_mod_poly_print(res + j, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(pow, ctx); for (j = 0; j < exp; j++) fmpz_mod_poly_clear(res + j, ctx); flint_free(res); fmpz_clear(n); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000166031461254215100236000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_powmod_fmpz_binexp, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Aliasing of res and a */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, t, f; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powmod_fmpz_binexp(res, a, expz, f, ctx); fmpz_mod_poly_powmod_fmpz_binexp(a, a, expz, f, ctx); result = (fmpz_mod_poly_equal(res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(expz); } /* Aliasing of res and f */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, t, f; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powmod_fmpz_binexp(res, a, expz, f, ctx); fmpz_mod_poly_powmod_fmpz_binexp(f, a, expz, f, ctx); result = (fmpz_mod_poly_equal(res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(expz); } /* No aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, t, f; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_powmod_fmpz_binexp(res1, a, expz, f, ctx); fmpz_mod_poly_powmod_ui_binexp(res2, a, exp, f, ctx); result = (fmpz_mod_poly_equal(res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); fmpz_mod_poly_print(res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(expz); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, res3, res4, t, f; fmpz_t p; fmpz_t exp1, exp2, exp3; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(exp1); fmpz_init(exp2); fmpz_randtest(exp1, state, 200); if (fmpz_sgn(exp1) == -1) fmpz_neg(exp1, exp1); fmpz_randtest(exp2, state, 200); if (fmpz_sgn(exp2) == -1) fmpz_neg(exp2, exp2); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(res3, ctx); fmpz_mod_poly_init(res4, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powmod_fmpz_binexp(res1, a, exp1, f, ctx); fmpz_mod_poly_powmod_fmpz_binexp(res2, a, exp2, f, ctx); fmpz_mod_poly_mulmod(res4, res1, res2, f, ctx); fmpz_init(exp3); fmpz_add(exp3, exp1, exp2); fmpz_mod_poly_powmod_fmpz_binexp(res3, a, exp3, f, ctx); result = (fmpz_mod_poly_equal(res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); fmpz_mod_poly_print(res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); fmpz_mod_poly_print(res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(res3, ctx); fmpz_mod_poly_clear(res4, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(exp1); fmpz_clear(exp2); fmpz_clear(exp3); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000234541461254215100251650ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_powmod_fmpz_binexp_preinv, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Aliasing of res and a */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, f, finv; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res, a, expz, f, finv, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(a, a, expz, f, finv, ctx); result = (fmpz_mod_poly_equal(res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(expz); } /* Aliasing of res and f */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, f, finv; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res, a, expz, f, finv, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(f, a, expz, f, finv, ctx); result = (fmpz_mod_poly_equal(res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(expz); } /* Aliasing of res and finv */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, f, finv; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res, a, expz, f, finv, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(finv, a, expz, f, finv, ctx); result = (fmpz_mod_poly_equal(res, finv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(expz); } /* No aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, f, finv; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_fmpz_binexp(res1, a, expz, f, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res2, a, expz, f, finv, ctx); result = (fmpz_mod_poly_equal(res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); fmpz_mod_poly_print(res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_clear(expz); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, res3, res4, f, finv; fmpz_t p; fmpz_t exp1, exp2, exp3; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(exp1); fmpz_init(exp2); fmpz_randtest(exp1, state, 200); if (fmpz_sgn(exp1) == -1) fmpz_neg(exp1, exp1); fmpz_randtest(exp2, state, 200); if (fmpz_sgn(exp2) == -1) fmpz_neg(exp2, exp2); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(res3, ctx); fmpz_mod_poly_init(res4, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res1, a, exp1, f, finv, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res2, a, exp2, f, finv, ctx); fmpz_mod_poly_mulmod(res4, res1, res2, f, ctx); fmpz_init(exp3); fmpz_add(exp3, exp1, exp2); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res3, a, exp3, f, finv, ctx); result = (fmpz_mod_poly_equal(res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); fmpz_mod_poly_print(res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); fmpz_mod_poly_print(res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(res3, ctx); fmpz_mod_poly_clear(res4, ctx); fmpz_clear(exp1); fmpz_clear(exp2); fmpz_clear(exp3); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-powmod_ui_binexp.c000066400000000000000000000162601461254215100232400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_powmod_ui_binexp, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Aliasing of res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, t, f; fmpz_t p; ulong exp; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powmod_ui_binexp(res1, a, exp, f, ctx); fmpz_mod_poly_powmod_ui_binexp(a, a, exp, f, ctx); result = (fmpz_mod_poly_equal(res1, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(t, ctx); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, t, f; fmpz_t p; ulong exp; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powmod_ui_binexp(res1, a, exp, f, ctx); fmpz_mod_poly_powmod_ui_binexp(f, a, exp, f, ctx); result = (fmpz_mod_poly_equal(res1, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(t, ctx); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, t, f; fmpz_t p; ulong exp; int j; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powmod_ui_binexp(res1, a, exp, f, ctx); fmpz_mod_poly_zero(res2, ctx); if (fmpz_mod_poly_length(f, ctx) > 1) fmpz_mod_poly_set_coeff_ui(res2, 0, 1, ctx); for (j = 1; j <= exp; j++) fmpz_mod_poly_mulmod(res2, res2, a, f, ctx); result = (fmpz_mod_poly_equal(res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); fmpz_mod_poly_print(res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(t, ctx); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, res3, res4, t, f; fmpz_t p; ulong exp1, exp2, exp3; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp1 = n_randint(state, 50); exp2 = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(res3, ctx); fmpz_mod_poly_init(res4, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_powmod_ui_binexp(res1, a, exp1, f, ctx); fmpz_mod_poly_powmod_ui_binexp(res2, a, exp2, f, ctx); fmpz_mod_poly_mulmod(res4, res1, res2, f, ctx); exp3 = exp1 + exp2; fmpz_mod_poly_powmod_ui_binexp(res3, a, exp3, f, ctx); result = (fmpz_mod_poly_equal(res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); fmpz_mod_poly_print(res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); fmpz_mod_poly_print(res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(res3, ctx); fmpz_mod_poly_clear(res4, ctx); fmpz_mod_poly_clear(t, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000225351461254215100246250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_powmod_ui_binexp_preinv, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Aliasing of res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, f, finv; fmpz_t p; ulong exp; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(res, a, exp, f, finv, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(a, a, exp, f, finv, ctx); result = (fmpz_mod_poly_equal(res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, f, finv; fmpz_t p; ulong exp; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(res, a, exp, f, finv, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(f, a, exp, f, finv, ctx); result = (fmpz_mod_poly_equal(res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); } /* Aliasing of res and finv */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res, f, finv; fmpz_t p; ulong exp; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(res, a, exp, f, finv, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(finv, a, exp, f, finv, ctx); result = (fmpz_mod_poly_equal(res, finv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, f, finv; fmpz_t p; ulong exp; int j; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(res1, a, exp, f, finv, ctx); fmpz_mod_poly_zero(res2, ctx); if (fmpz_mod_poly_length(f, ctx) > 1) fmpz_mod_poly_set_coeff_ui(res2, 0, 1, ctx); for (j = 1; j <= exp; j++) fmpz_mod_poly_mulmod(res2, res2, a, f, ctx); result = (fmpz_mod_poly_equal(res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); fmpz_mod_poly_print(res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(finv, ctx); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, res3, res4, f, finv; fmpz_t p; ulong exp1, exp2, exp3; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp1 = n_randint(state, 50); exp2 = n_randint(state, 50); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(res3, ctx); fmpz_mod_poly_init(res4, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 50), ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(res1, a, exp1, f, finv, ctx); fmpz_mod_poly_powmod_ui_binexp_preinv(res2, a, exp2, f, finv, ctx); fmpz_mod_poly_mulmod(res4, res1, res2, f, ctx); exp3= exp1+exp2; fmpz_mod_poly_powmod_ui_binexp_preinv(res3, a, exp3, f, finv, ctx); result = (fmpz_mod_poly_equal(res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); fmpz_mod_poly_print(res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); fmpz_mod_poly_print(res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(res3, ctx); fmpz_mod_poly_clear(res4, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000174621461254215100241510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_powmod_x_fmpz_preinv, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* No aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, res1, res2, f, finv; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_init2(a, f->length-1, ctx); fmpz_mod_poly_set_coeff_ui (a, 1, 1, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(res1, expz, f, finv, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(res2, a, expz, f, finv, ctx); result = (fmpz_mod_poly_equal(res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("expz:\n"); fmpz_print(expz), flint_printf("\n\n"); flint_printf("a:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); fmpz_mod_poly_print(res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); fmpz_mod_poly_print(res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_clear(expz); } /* Aliasing of res and f */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t res, f, finv; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(res, expz, f, finv, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(f, expz, f, finv, ctx); result = (fmpz_mod_poly_equal(res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("expz:\n"); fmpz_print(expz), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(expz); } /* Aliasing of res and finv */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { fmpz_mod_poly_t res, f, finv; fmpz_t p; ulong exp; fmpz_t expz; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(res, expz, f, finv, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(finv, expz, f, finv, ctx); result = (fmpz_mod_poly_equal(res, finv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("expz:\n"); fmpz_print(expz), flint_printf("\n\n"); flint_printf("finv:\n"); fmpz_mod_poly_print(finv, ctx), flint_printf("\n\n"); flint_printf("res:\n"); fmpz_mod_poly_print(res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res, ctx); fmpz_clear(expz); } /* Check that x^(b+c) = x^b * x^c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mod_poly_t res1, res2, res3, res4, f, finv; fmpz_t p; fmpz_t exp1, exp2, exp3; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(exp1); fmpz_init(exp2); fmpz_randtest(exp1, state, 200); if (fmpz_sgn(exp1) == -1) fmpz_neg(exp1, exp1); fmpz_randtest(exp2, state, 200); if (fmpz_sgn(exp2) == -1) fmpz_neg(exp2, exp2); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_init(res1, ctx); fmpz_mod_poly_init(res2, ctx); fmpz_mod_poly_init(res3, ctx); fmpz_mod_poly_init(res4, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n_randint(state, 50) + 1, ctx); fmpz_mod_poly_reverse (finv, f, f->length, ctx); fmpz_mod_poly_inv_series (finv, finv, f->length, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(res1, exp1, f, finv, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(res2, exp2, f, finv, ctx); fmpz_mod_poly_mulmod(res4, res1, res2, f, ctx); fmpz_init(exp3); fmpz_add(exp3, exp1, exp2); fmpz_mod_poly_powmod_x_fmpz_preinv(res3, exp3, f, finv, ctx); result = (fmpz_mod_poly_equal(res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f:\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); fmpz_mod_poly_print(res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); fmpz_mod_poly_print(res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(res1, ctx); fmpz_mod_poly_clear(res2, ctx); fmpz_mod_poly_clear(res3, ctx); fmpz_mod_poly_clear(res4, ctx); fmpz_clear(exp1); fmpz_clear(exp2); fmpz_clear(exp3); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-print_read.c000066400000000000000000000161231461254215100220160ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) # include # include # include #endif #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_print_read, state) { #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int i, j, n, result; FILE *in, *out; int fd[2]; pid_t childpid; fmpz_mod_ctx_t ctx; n = 100 * flint_test_multiplier(); fmpz_mod_ctx_init_ui(ctx, 2); fflush(stdout); /* Ensure buffer does not flow into child process */ /* Randomise n polynomials, write to and read from a pipe */ { fmpz_mod_poly_t *a; a = flint_malloc(n * sizeof(fmpz_mod_poly_t)); for (i = 0; i < n; i++) { fmpz_mod_poly_init(a[i], ctx); fmpz_mod_poly_randtest(a[i], state, n_randint(state, 100), ctx); } if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } for (j = 0; j < n; j++) { r = fmpz_mod_poly_fprint(out, a[j], ctx); if ((j < n - 1) && (r > 0)) r = flint_fprintf(out, "\n"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } } for (j = 0; j < n; j++) fmpz_mod_poly_clear(a[j], ctx); flint_free(a); fclose(out); exit(0); } else /* Parent process */ { int r; fmpz_mod_poly_t t; fmpz_mod_ctx_t newctx; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_mod_ctx_init_ui(newctx, 3); fmpz_mod_poly_init(t, newctx); i = 0; while (!feof(in)) { r = fmpz_mod_poly_fread(in, t, newctx); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Read error.\n"); fflush(stdout); flint_abort(); } result = fmpz_equal(fmpz_mod_ctx_modulus(ctx), fmpz_mod_ctx_modulus(newctx)); result = result && fmpz_mod_poly_equal(t, a[i], newctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("a[i] = "), fmpz_mod_poly_print(a[i], ctx), flint_printf("\n"); flint_printf("t = "), fmpz_mod_poly_print(t, newctx), flint_printf("\n"); fflush(stdout); flint_abort(); } ++i; } fmpz_mod_poly_clear(t, newctx); fmpz_mod_ctx_clear(newctx); fclose(in); waitpid(childpid, NULL, 0); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); fflush(stdout); flint_abort(); } for (i = 0; i < n; i++) fmpz_mod_poly_clear(a[i], ctx); flint_free(a); } /* Write bad data to a pipe and read it */ { if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } fclose(out); exit(0); } else /* Parent process */ { int r; fmpz_mod_poly_t t; fmpz_mod_ctx_t newctx; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_init(t, ctx); fmpz_mod_ctx_init_ui(newctx, 3); i = 0; /* Only four junk bytes are sent and our read doesn't consume invalid bytes, so eof is never reached */ for(i = 0; i < 500; i++) { r = fmpz_mod_poly_fread(in, t, newctx); if (r > 0) { flint_printf("FAIL:\n"); flint_printf("r = %d\n", r); fflush(stdout); flint_abort(); } } fmpz_mod_poly_clear(t, newctx); fmpz_mod_ctx_clear(newctx); fclose(in); waitpid(childpid, NULL, 0); } } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/fmpz_mod_poly/test/t-product_roots_fmpz_vec.c000066400000000000000000000043041461254215100244640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_product_roots_fmpz_vec, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t P, Q, tmp; fmpz * x; slong j, n, bits; fmpz_t mod; fmpz_mod_ctx_t ctx; n = n_randint(state, 100); bits = n_randint(state, 100); fmpz_init(mod); fmpz_randtest_unsigned(mod, state, bits); fmpz_add_ui(mod, mod, 2); fmpz_mod_ctx_init(ctx, mod); x = _fmpz_vec_init(n); _fmpz_vec_randtest(x, state, n, bits); for (j = 0; j < n; j++) fmpz_mod_set_fmpz(x + j, x + j, ctx); fmpz_mod_poly_init(P, ctx); fmpz_mod_poly_init(Q, ctx); fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_product_roots_fmpz_vec(P, x, n, ctx); fmpz_mod_poly_one(Q, ctx); for (j = 0; j < n; j++) { fmpz_mod_poly_zero(tmp, ctx); fmpz_mod_poly_set_coeff_si(tmp, 1, -WORD(1), ctx); fmpz_mod_poly_set_coeff_fmpz(tmp, 0, x + j, ctx); fmpz_mod_poly_neg(tmp, tmp, ctx); fmpz_mod_poly_mul(Q, Q, tmp, ctx); } if (!fmpz_mod_poly_equal(P, Q, ctx)) { flint_printf("FAIL (P != Q):\n"); fmpz_mod_poly_print(P, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(Q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(P, ctx); fmpz_mod_poly_clear(Q, ctx); fmpz_mod_poly_clear(tmp, ctx); _fmpz_vec_clear(x, n); fmpz_mod_ctx_clear(ctx); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-radix.c000066400000000000000000000073021461254215100207750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" static int _check(fmpz_mod_poly_struct **B, const fmpz_mod_poly_t F, const fmpz_mod_poly_t R, const fmpz_mod_ctx_t ctx) { const slong lenF = F->length; const slong lenR = R->length; const slong N = (lenF - 1) / (lenR - 1); slong i; int result; fmpz_mod_poly_t S; fmpz_mod_poly_init(S, ctx); fmpz_mod_poly_set(S, B[N], ctx); for (i = N; i > 0; i--) { fmpz_mod_poly_mul(S, S, R, ctx); fmpz_mod_poly_add(S, S, B[i - 1], ctx); } result = fmpz_mod_poly_equal(F, S, ctx); fmpz_mod_poly_clear(S, ctx); return result; } TEST_FUNCTION_START(fmpz_mod_poly_radix, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t f, r; fmpz_mod_poly_struct **b; fmpz_mod_poly_radix_t D; slong j, N; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 500), ctx); do fmpz_mod_poly_randtest_not_zero(r, state, n_randint(state, 20) + 2, ctx); while (r->length < 2); N = FLINT_MAX(0, fmpz_mod_poly_degree(f, ctx) / fmpz_mod_poly_degree(r, ctx)); b = flint_malloc((N + 1) * sizeof(fmpz_mod_poly_struct *)); for (j = 0; j <= N; j++) { b[j] = flint_malloc(sizeof(fmpz_mod_poly_struct)); fmpz_mod_poly_init(b[j], ctx); } /* Ensure that lead(r) is a unit mod p */ { fmpz_t d; fmpz *leadR = fmpz_mod_poly_lead(r, ctx); fmpz_init(d); fmpz_gcd(d, p, leadR); while (!fmpz_is_one(d)) { fmpz_divexact(leadR, leadR, d); fmpz_gcd(d, p, leadR); } fmpz_clear(d); } fmpz_mod_poly_radix_init(D, r, f->length - 1 + n_randint(state, 50), ctx); fmpz_mod_poly_radix(b, f, D, ctx); result = _check(b, f, r, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("result = %d\n", result); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("f = "), fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("N = %wd\n\n", N); for (j = 0; j <= N; j++) { flint_printf("b[%wd] = ", j), fmpz_mod_poly_print(b[j], ctx), flint_printf("\n\n"); } fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_radix_clear(D); for (j = 0; j <= N; j++) { fmpz_mod_poly_clear(b[j], ctx); flint_free(b[j]); } flint_free(b); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-randtest_monic_primitive.c000066400000000000000000000023321461254215100247650ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_randtest_monic_primitive, state) { int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t poly; slong d; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, FLINT_MIN(FLINT_BITS - 1, 10)), 1)); fmpz_mod_ctx_set_modulus(ctx, p); d = n_randint(state, 5) + 3; fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_randtest_monic_primitive(poly, state, d, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-rem_basecase.c000066400000000000000000000135541461254215100223050ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_rem_basecase, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check q*b + r = a, no aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, q, r, t; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_divrem_basecase(q, r, a, b, ctx); fmpz_mod_poly_rem_basecase(t, a, b, ctx); result = (fmpz_mod_poly_equal(r, t, ctx)); if (!result) { flint_printf("FAIL (cmp with divrem):\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("q = "), fmpz_mod_poly_print(q, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("t = "), fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_clear(p); } /* Alias b and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_rem_basecase(r, a, b, ctx); fmpz_mod_poly_rem_basecase(b, a, b, ctx); result = (fmpz_mod_poly_equal(r, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } /* a and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, ctx); { fmpz_t d; fmpz *leadB = fmpz_mod_poly_lead(b, ctx); fmpz_init(d); fmpz_gcd(d, p, leadB); while (!fmpz_is_one(d)) { fmpz_divexact(leadB, leadB, d); fmpz_gcd(d, p, leadB); } fmpz_clear(d); } fmpz_mod_poly_rem_basecase(r, a, b, ctx); fmpz_mod_poly_rem_basecase(a, a, b, ctx); result = (fmpz_mod_poly_equal(r, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("r = "), fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-resultant.c000066400000000000000000000074611461254215100217150ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_resultant, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ for (i = 0; i < 60 * flint_test_multiplier(); i++) { fmpz_t x, y, n; fmpz_mod_poly_t f, g; fmpz_init(n); fmpz_init(x); fmpz_init(y); fmpz_set_ui(n, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, n); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 300), ctx); fmpz_mod_poly_randtest(g, state, n_randint(state, 300), ctx); fmpz_mod_poly_resultant(x, f, g, ctx); fmpz_mod_poly_resultant(y, g, f, ctx); if ((fmpz_mod_poly_degree(f, ctx) * fmpz_mod_poly_degree(g, ctx)) % 2) fmpz_mod_neg(y, y, ctx); result = (fmpz_equal(x, y)); if (!result) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); fmpz_print(x); printf("\n"); printf("y = "); fmpz_print(y); printf("\n"); printf("n = "); fmpz_print(n); printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (i = 0; i < 60 * flint_test_multiplier(); i++) { fmpz_t x, y, z, n; fmpz_mod_poly_t f, g, h; fmpz_init(n); fmpz_init(x); fmpz_init(y); fmpz_init(z); fmpz_set_ui(n, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, n); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 200), ctx); fmpz_mod_poly_randtest(g, state, n_randint(state, 200), ctx); fmpz_mod_poly_randtest(h, state, n_randint(state, 100), ctx); fmpz_mod_poly_resultant(y, f, g, ctx); fmpz_mod_poly_resultant(z, h, g, ctx); fmpz_mod_mul(y, y, z, ctx); fmpz_mod_poly_mul(f, f, h, ctx); fmpz_mod_poly_resultant(x, f, g, ctx); result = (fmpz_equal(x, y)); if (!result) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); printf("x = "); fmpz_print(x); printf("\n"); printf("y = "); fmpz_print(y); printf("\n"); printf("z = "); fmpz_print(z); printf("\n"); printf("n = "); fmpz_print(n); printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-scalar_div_fmpz.c000066400000000000000000000063541461254215100230370ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_scalar_div_fmpz, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t n, p, g; fmpz_mod_poly_t a, b; fmpz_init(p); fmpz_init(g); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(n); do { fmpz_randtest(n, state, 200); fmpz_gcd(g, n, p); } while (!fmpz_is_one(g)); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_scalar_div_fmpz(b, a, n, ctx); fmpz_mod_poly_scalar_div_fmpz(a, a, n, ctx); result = (fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_print(n), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(g); fmpz_clear(p); } /* Check (a*n)/n = a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t n, p, g; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_init(g); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(n); do { fmpz_randtest(n, state, 200); fmpz_gcd(g, n, p); } while (!fmpz_is_one(g)); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_scalar_mul_fmpz(b, a, n, ctx); fmpz_mod_poly_scalar_div_fmpz(c, b, n, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fmpz_print(n), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(g); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-scalar_mul_fmpz.c000066400000000000000000000033501461254215100230430ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_scalar_mul_fmpz, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t n, p; fmpz_mod_poly_t a, b; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(n); fmpz_randtest(n, state, 200); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_scalar_mul_fmpz(b, a, n, ctx); fmpz_mod_poly_scalar_mul_fmpz(a, a, n, ctx); result = (fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-set_equal.c000066400000000000000000000053421461254215100216520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_set_equal, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_set(b, a, ctx); result = (fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(p); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b; slong coeff = n_randint(state, 100); fmpz_t x; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_init(x); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_set(b, a, ctx); fmpz_mod_poly_get_coeff_fmpz(x, b, coeff, ctx); fmpz_sub_ui(x, x, 1); fmpz_mod_poly_set_coeff_fmpz(b, coeff, x, ctx); result = (!fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-set_trunc.c000066400000000000000000000043071461254215100216760ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_set_trunc, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c; fmpz_t p; slong n; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); n = n_randint(state, 50); fmpz_mod_poly_set_trunc(b, a, n, ctx); fmpz_mod_poly_set(c, a, ctx); fmpz_mod_poly_truncate(c, n, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_set_trunc(a, a, n, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-shift_left_right.c000066400000000000000000000075041461254215100232160ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_shift_left_right, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and b for left shift */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b; slong shift = n_randint(state, 100); fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest(a, state, 200, ctx); fmpz_mod_poly_shift_left(b, a, shift, ctx); fmpz_mod_poly_shift_left(a, a, shift, ctx); result = (fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(p); } /* Check aliasing of a and b for right shift */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b; slong shift; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest_not_zero(a, state, 200, ctx); shift = n_randint(state, a->length); fmpz_mod_poly_shift_right(b, a, shift, ctx); fmpz_mod_poly_shift_right(a, a, shift, ctx); result = (fmpz_mod_poly_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(p); } /* Check shift left then right does nothing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; slong shift = n_randint(state, 100); fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, 200, ctx); fmpz_mod_poly_shift_left(b, a, shift, ctx); fmpz_mod_poly_shift_right(c, b, shift, ctx); result = (fmpz_mod_poly_equal(c, a, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-sqrt.c000066400000000000000000000112341461254215100206560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_sqrt, state) { int i; /* Test aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b; int square1, square2; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, FLINT_BITS); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_randtest(a, state, 1 + n_randint(state, 50), ctx); if (n_randint(state, 2)) fmpz_mod_poly_mul(a, a, a, ctx); square1 = fmpz_mod_poly_sqrt(b, a, ctx); square2 = fmpz_mod_poly_sqrt(a, a, ctx); if (square1 != square2 || (square1 && !fmpz_mod_poly_equal(a, b, ctx))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); fmpz_mod_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b: "); fmpz_mod_poly_print(b, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_ctx_clear(ctx); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c; int square; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, FLINT_BITS); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, 1 + n_randint(state, 50), ctx); fmpz_mod_poly_mul(b, a, a, ctx); square = fmpz_mod_poly_sqrt(c, b, ctx); if (!square) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); fmpz_mod_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b: "); fmpz_mod_poly_print(b, ctx); flint_printf("\n\n"); flint_printf("c: "); fmpz_mod_poly_print(c, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_mul(c, c, c, ctx); if (!fmpz_mod_poly_equal(c, b, ctx)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_mod_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b: "); fmpz_mod_poly_print(b, ctx); flint_printf("\n\n"); flint_printf("c: "); fmpz_mod_poly_print(c, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_ctx_clear(ctx); } /* Test "almost" squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c; slong j; int square; fmpz_mod_ctx_t ctx; fmpz_t t; fmpz_init(t); fmpz_mod_ctx_init_rand_bits_prime(ctx, state, FLINT_BITS); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 50), ctx); fmpz_mod_poly_mul(b, a, a, ctx); j = n_randint(state, fmpz_mod_poly_length(b, ctx)); fmpz_randm(t, state, ctx->n); fmpz_set(b->coeffs + j, t); _fmpz_mod_poly_normalise(b); square = fmpz_mod_poly_sqrt(c, b, ctx); if (square) { fmpz_mod_poly_mul(c, c, c, ctx); if (!fmpz_mod_poly_equal(c, b, ctx)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_mod_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b: "); fmpz_mod_poly_print(b, ctx); flint_printf("\n\n"); flint_printf("c: "); fmpz_mod_poly_print(c, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(t); fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-sqrt_series.c000066400000000000000000000065161461254215100222370ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_sqrt_series, state) { int i, result; /* Check g^2 = h mod x^m */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t h, g, r; slong m; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, FLINT_BITS); if (fmpz_cmp_ui(ctx->n, 2) != 0) { fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(r, ctx); do fmpz_mod_poly_randtest(h, state, n_randint(state, 1000), ctx); while (h->length == 0); fmpz_mod_poly_set_coeff_ui(h, 0, 1, ctx); m = n_randint(state, h->length) + 1; fmpz_mod_poly_sqrt_series(g, h, m, ctx); fmpz_mod_poly_mullow(r, g, g, m, ctx); fmpz_mod_poly_truncate(h, m, ctx); result = (fmpz_mod_poly_equal(r, h, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(r, ctx), flint_printf("\n\n"); flint_printf("n = "); fmpz_print(ctx->n); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(r, ctx); } fmpz_mod_ctx_clear(ctx); } /* Check aliasing of h and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_poly_t g, h; slong m; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_rand_bits_prime(ctx, state, FLINT_BITS); if (fmpz_cmp_ui(ctx->n, 2) != 0) { fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(g, ctx); do fmpz_mod_poly_randtest(h, state, n_randint(state, 500), ctx); while (h->length == 0); fmpz_mod_poly_set_coeff_ui(h, 0, 1, ctx); m = n_randint(state, h->length) + 1; fmpz_mod_poly_sqrt_series(g, h, m, ctx); fmpz_mod_poly_sqrt_series(h, h, m, ctx); result = (fmpz_mod_poly_equal(g, h, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(h, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("n = "); fmpz_print(ctx->n); flint_printf("m = %wd\n", m); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); } fmpz_mod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-sub.c000066400000000000000000000103541461254215100204600ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_sub, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check a - b = a + neg(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_sub(c, a, b, ctx); fmpz_mod_poly_neg(b, b, ctx); fmpz_mod_poly_add(d, a, b, ctx); result = (fmpz_mod_poly_equal(c, d, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_clear(p); } /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_sub(c, a, b, ctx); fmpz_mod_poly_sub(a, a, b, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_sub(c, a, b, ctx); fmpz_mod_poly_sub(b, a, b, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-sub_series.c000066400000000000000000000107501461254215100220320ustar00rootroot00000000000000/* Copyright (C) 2009, 2014 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_sub_series, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; slong n; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); fmpz_mod_poly_sub_series(c, a, b, n, ctx); fmpz_mod_poly_sub_series(a, a, b, n, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; slong n; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); fmpz_mod_poly_sub_series(c, a, b, n, ctx); fmpz_mod_poly_sub_series(b, a, b, n, ctx); result = (fmpz_mod_poly_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } /* Check truncate(a + b, n) = add_series(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c, d; slong n; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); fmpz_mod_poly_sub(c, a, b, ctx); fmpz_mod_poly_truncate(c, n, ctx); fmpz_mod_poly_sub_series(d, a, b, n, ctx); result = (fmpz_mod_poly_equal(d, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-swap.c000066400000000000000000000034261461254215100206430ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_swap, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, c; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_set(c, b, ctx); fmpz_mod_poly_swap(a, b, ctx); result = (fmpz_mod_poly_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-xgcd.c000066400000000000000000000120341461254215100206110ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_xgcd, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* Generic case, most likely co-prime arguments ******************************/ /* Compare with result from GCD and check correctness */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, d, g, s, t, v, w; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(w, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_gcd(d, a, b, ctx); fmpz_mod_poly_xgcd(g, s, t, a, b, ctx); fmpz_mod_poly_mul(v, s, a, ctx); fmpz_mod_poly_mul(w, t, b, ctx); fmpz_mod_poly_add(w, v, w, ctx); result = (fmpz_mod_poly_equal(d, g, ctx) && fmpz_mod_poly_equal(g, w, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(v, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(w, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(w, ctx); fmpz_clear(p); } /* Special case, arguments share a factor ********************************/ /* Compare with result from GCD and check correctness */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a, b, d, f, g, s, t, v, w; fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(d, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(s, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(w, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(f, state, n_randint(state, 20), ctx); fmpz_mod_poly_mul(a, a, f, ctx); fmpz_mod_poly_mul(b, b, f, ctx); fmpz_mod_poly_gcd(d, a, b, ctx); fmpz_mod_poly_xgcd(g, s, t, a, b, ctx); fmpz_mod_poly_mul(v, s, a, ctx); fmpz_mod_poly_mul(w, t, b, ctx); fmpz_mod_poly_add(w, v, w, ctx); result = (fmpz_mod_poly_equal(d, g, ctx) && fmpz_mod_poly_equal(g, w, ctx)); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(b, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(d, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(f, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(g, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(s, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(t, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(v, ctx), flint_printf("\n\n"); fmpz_mod_poly_print(w, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(d, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(s, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(w, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/test/t-zero.c000066400000000000000000000026531461254215100206510ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" TEST_FUNCTION_START(fmpz_mod_poly_zero, state) { int i, result; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t a; fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_randtest(a, state, n_randint(state, 100), ctx); fmpz_mod_poly_zero(a, ctx); result = (fmpz_mod_poly_is_zero(a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_mod_poly_print(a, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly/tree.c000066400000000000000000000052111461254215100174020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" fmpz_poly_struct ** _fmpz_mod_poly_tree_alloc(slong len) { fmpz_poly_struct ** tree = NULL; if (len) { slong i, j, height = FLINT_CLOG2(len); tree = flint_malloc(sizeof(fmpz_poly_struct *) * (height + 1)); for (i = 0; i <= height; i++, len = (len + 1)/2) { tree[i] = flint_malloc(sizeof(fmpz_poly_struct) * len); for (j = 0; j < len; j++) fmpz_poly_init(tree[i] + j); } } return tree; } void _fmpz_mod_poly_tree_free(fmpz_poly_struct ** tree, slong len) { if (len) { slong i, j, height = FLINT_CLOG2(len); for (i = 0; i <= height; i++, len = (len + 1)/2) { for (j = 0; j < len; j++) fmpz_poly_clear(tree[i] + j); flint_free(tree[i]); } flint_free(tree); } } void _fmpz_mod_poly_tree_build(fmpz_poly_struct ** tree, const fmpz * roots, slong len, const fmpz_mod_ctx_t ctx) { slong height, pow, left, i; fmpz_poly_struct * pa, * pb; if (len == 0) return; height = FLINT_CLOG2(len); /* zeroth level, (x-a) */ for (i = 0; i < len; i++) { fmpz_poly_set_coeff_ui(tree[0] + i, 1, 1); fmpz_negmod((tree[0] + i)->coeffs, roots + i, fmpz_mod_ctx_modulus(ctx)); } for (i = 0; i < height - 1; i++) { left = len; pow = WORD(1) << i; pa = tree[i]; pb = tree[i + 1]; while (left >= 2 * pow) { fmpz_poly_fit_length(pb, pa->length + (pa + 1)->length - 1); _fmpz_mod_poly_mul(pb->coeffs, pa->coeffs, pa->length, (pa + 1)->coeffs, (pa + 1)->length, ctx); _fmpz_poly_set_length(pb, pa->length + (pa + 1)->length - 1); left -= 2 * pow; pa += 2; pb += 1; } if (left > pow) { fmpz_poly_fit_length(pb, pa->length + (pa + 1)->length - 1); _fmpz_mod_poly_mul(pb->coeffs, pa->coeffs, pa->length, (pa + 1)->coeffs, (pa + 1)->length, ctx); _fmpz_poly_set_length(pb, pa->length + (pa + 1)->length - 1); } else if (left > 0) fmpz_poly_set(pb, pa); } } flint-3.1.3/src/fmpz_mod_poly/truncate.c000066400000000000000000000013341461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_truncate(fmpz_mod_poly_t poly, slong len, const fmpz_mod_ctx_t ctx) { if (poly->length > len) { slong i; for (i = len; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); poly->length = len; _fmpz_mod_poly_normalise(poly); } } flint-3.1.3/src/fmpz_mod_poly/xgcd.c000066400000000000000000000111531461254215100173720ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr_poly.h" slong _fmpz_mod_poly_xgcd(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { if (lenB == 1) { _fmpz_vec_zero(T, lenA - 1); fmpz_set(G + 0, B + 0); fmpz_one(T + 0); return 1; } else { slong lenG; gr_ctx_t gr_ctx; _gr_ctx_init_fmpz_mod_from_ref(gr_ctx, ctx); /* todo: use invB */ if (FLINT_MIN(lenA, lenB) < FMPZ_MOD_POLY_GCD_CUTOFF) GR_MUST_SUCCEED(_gr_poly_xgcd_euclidean(&lenG, G, S, T, A, lenA, B, lenB, gr_ctx)); else GR_MUST_SUCCEED(_gr_poly_xgcd_hgcd(&lenG, G, S, T, A, lenA, B, lenB, FMPZ_MOD_POLY_HGCD_CUTOFF, FMPZ_MOD_POLY_GCD_CUTOFF, gr_ctx)); return lenG; } } void fmpz_mod_poly_xgcd(fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { if (A->length < B->length) { fmpz_mod_poly_xgcd(G, T, S, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_t inv; fmpz_init(inv); if (lenA == 0) /* lenA = lenB = 0 */ { fmpz_mod_poly_zero(G, ctx); fmpz_mod_poly_zero(S, ctx); fmpz_mod_poly_zero(T, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { fmpz_invmod(inv, fmpz_mod_poly_lead(A, ctx), p); fmpz_mod_poly_scalar_mul_fmpz(G, A, inv, ctx); fmpz_mod_poly_zero(T, ctx); fmpz_mod_poly_set_fmpz(S, inv, ctx); } else /* lenA >= lenB >= 1 */ { fmpz *g, *s, *t; slong lenG; if (G == A || G == B) { g = _fmpz_vec_init(FLINT_MIN(lenA, lenB)); } else { fmpz_mod_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = _fmpz_vec_init(lenB); } else { fmpz_mod_poly_fit_length(S, lenB, ctx); s = S->coeffs; } if (T == A || T == B) { t = _fmpz_vec_init(lenA); } else { fmpz_mod_poly_fit_length(T, lenA, ctx); t = T->coeffs; } fmpz_invmod(inv, fmpz_mod_poly_lead(B, ctx), p); lenG = _fmpz_mod_poly_xgcd(g, s, t, A->coeffs, lenA, B->coeffs, lenB, inv, ctx); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { _fmpz_vec_clear(S->coeffs, S->alloc); S->coeffs = s; S->alloc = lenB; } if (T == A || T == B) { _fmpz_vec_clear(T->coeffs, T->alloc); T->coeffs = t; T->alloc = lenA; } _fmpz_mod_poly_set_length(G, lenG); _fmpz_mod_poly_set_length(S, FLINT_MAX(lenB - lenG, 1)); _fmpz_mod_poly_set_length(T, FLINT_MAX(lenA - lenG, 1)); _fmpz_mod_poly_normalise(S); _fmpz_mod_poly_normalise(T); if (!fmpz_is_one(fmpz_mod_poly_lead(G, ctx))) { fmpz_invmod(inv, fmpz_mod_poly_lead(G, ctx), p); fmpz_mod_poly_scalar_mul_fmpz(G, G, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(S, S, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(T, T, inv, ctx); } } fmpz_clear(inv); } } flint-3.1.3/src/fmpz_mod_poly/xgcd_euclidean_f.c000066400000000000000000000157221461254215100217160ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx) { _fmpz_vec_zero(G, lenB); _fmpz_vec_zero(S, lenB - 1); _fmpz_vec_zero(T, lenA - 1); if (lenB == 1) { fmpz_set_ui(f, 1); fmpz_set(G + 0, B + 0); fmpz_one(T + 0); return 1; } else { fmpz *Q, *R; slong lenQ, lenR, lenD = 0; TMP_INIT; TMP_START; FMPZ_VEC_TMP_INIT(Q, 2*lenA); R = Q + lenA; _fmpz_mod_poly_divrem_f(f, Q, R, A, lenA, B, lenB, ctx); if (!fmpz_is_one(f)) goto cleanup2; lenR = lenB - 1; FMPZ_VEC_NORM(R, lenR); if (lenR == 0) { fmpz_set_ui(f, 1); _fmpz_vec_set(G, B, lenB); fmpz_one(T + 0); FMPZ_VEC_TMP_CLEAR(Q, 2*lenA); TMP_END; return lenB; } else { fmpz_t inv; fmpz *D, *U, *V1, *V3, *W; slong lenU, lenV1, lenV3, lenW; fmpz_init(inv); FMPZ_VEC_TMP_INIT(W, FLINT_MAX(5*lenB, lenA + lenB)); D = W + lenB; U = D + lenB; V1 = U + lenB; V3 = V1 + lenB; lenU = 0; _fmpz_vec_set(D, B, lenB); lenD = lenB; fmpz_one(V1 + 0); lenV1 = 1; lenV3 = 0; FMPZ_VEC_SWAP(V3, lenV3, R, lenR); do { fmpz_gcdinv(f, inv, V3 + (lenV3 - 1), fmpz_mod_ctx_modulus(ctx)); if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_divrem_basecase(Q, D, D, lenD, V3, lenV3, inv, ctx); lenQ = lenD - lenV3 + 1; lenD = lenV3 - 1; FMPZ_VEC_NORM(D, lenD); if (lenV1 >= lenQ) _fmpz_mod_poly_mul(W, V1, lenV1, Q, lenQ, ctx); else _fmpz_mod_poly_mul(W, Q, lenQ, V1, lenV1, ctx); lenW = lenQ + lenV1 - 1; _fmpz_mod_poly_sub(U, U, lenU, W, lenW, ctx); lenU = FLINT_MAX(lenU, lenW); FMPZ_VEC_NORM(U, lenU); FMPZ_VEC_SWAP(U, lenU, V1, lenV1); FMPZ_VEC_SWAP(D, lenD, V3, lenV3); } while (lenV3 != 0); _fmpz_vec_set(G, D, lenD); _fmpz_vec_set(S, U, lenU); { lenQ = lenA + lenU - 1; _fmpz_mod_poly_mul(Q, A, lenA, S, lenU, ctx); _fmpz_mod_poly_neg(Q, Q, lenQ, ctx); _fmpz_mod_poly_add(Q, G, lenD, Q, lenQ, ctx); _fmpz_mod_poly_divrem(T, W, Q, lenQ, B, lenB, invB, ctx); } cleanup: fmpz_clear(inv); FMPZ_VEC_TMP_CLEAR(W, FLINT_MAX(5*lenB, lenA + lenB)); cleanup2: FMPZ_VEC_TMP_CLEAR(Q, 2*lenA); TMP_END; return lenD; } } } void fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { if (A->length < B->length) { fmpz_mod_poly_xgcd_euclidean_f(f, G, T, S, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const fmpz * p = fmpz_mod_ctx_modulus(ctx); const slong lenA = A->length, lenB = B->length; fmpz_t inv; fmpz_init(inv); if (lenA == 0) /* lenA = lenB = 0 */ { fmpz_set_ui(f, 1); fmpz_mod_poly_zero(G, ctx); fmpz_mod_poly_zero(S, ctx); fmpz_mod_poly_zero(T, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { fmpz_gcdinv(f, inv, fmpz_mod_poly_lead(A, ctx), p); fmpz_mod_poly_scalar_mul_fmpz(G, A, inv, ctx); fmpz_mod_poly_zero(T, ctx); fmpz_mod_poly_set_fmpz(S, inv, ctx); } else /* lenA >= lenB >= 1 */ { fmpz *g, *s, *t; slong lenG; fmpz_gcdinv(f, inv, fmpz_mod_poly_lead(B, ctx), p); if (!fmpz_is_one(f)) goto cleanup; if (G == A || G == B) { g = _fmpz_vec_init(FLINT_MIN(lenA, lenB)); } else { fmpz_mod_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = _fmpz_vec_init(lenB); } else { fmpz_mod_poly_fit_length(S, lenB, ctx); s = S->coeffs; } if (T == A || T == B) { t = _fmpz_vec_init(lenA); } else { fmpz_mod_poly_fit_length(T, lenA, ctx); t = T->coeffs; } lenG = _fmpz_mod_poly_xgcd_euclidean_f(f, g, s, t, A->coeffs, lenA, B->coeffs, lenB, inv, ctx); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, G->alloc); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { _fmpz_vec_clear(S->coeffs, S->alloc); S->coeffs = s; S->alloc = lenB; } if (T == A || T == B) { _fmpz_vec_clear(T->coeffs, T->alloc); T->coeffs = t; T->alloc = lenA; } if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_set_length(G, lenG); _fmpz_mod_poly_set_length(S, FLINT_MAX(lenB - lenG, 1)); _fmpz_mod_poly_set_length(T, FLINT_MAX(lenA - lenG, 1)); _fmpz_mod_poly_normalise(S); _fmpz_mod_poly_normalise(T); if (!fmpz_is_one(fmpz_mod_poly_lead(G, ctx))) { fmpz_gcdinv(f, inv, fmpz_mod_poly_lead(G, ctx), p); fmpz_mod_poly_scalar_mul_fmpz(G, G, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(S, S, inv, ctx); fmpz_mod_poly_scalar_mul_fmpz(T, T, inv, ctx); } } cleanup: fmpz_clear(inv); } } flint-3.1.3/src/fmpz_mod_poly/zero_coeffs.c000066400000000000000000000015171461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_zero_coeffs(fmpz_mod_poly_t poly, slong i, slong j, const fmpz_mod_ctx_t ctx) { if (i < 0) i = 0; if (j > poly->length) j = poly->length; _fmpz_vec_zero(poly->coeffs + i, j - i); if (j == poly->length) { _fmpz_mod_poly_set_length(poly, i); _fmpz_mod_poly_normalise(poly); } } flint-3.1.3/src/fmpz_mod_poly_factor.h000066400000000000000000000162501461254215100200130ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_POLY_FACTOR_H #define FMPZ_MOD_POLY_FACTOR_H #ifdef FMPZ_MOD_POLY_FACTOR_INLINES_C #define FMPZ_MOD_POLY_FACTOR_INLINE #else #define FMPZ_MOD_POLY_FACTOR_INLINE static inline #endif #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif /* Factoring ****************************************************************/ void fmpz_mod_poly_factor_init(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx); typedef struct { fmpz_mod_poly_struct * baby; fmpz_mod_poly_struct * res; fmpz_mod_poly_struct * H; fmpz_mod_poly_struct * v; fmpz_mod_poly_struct * vinv; const fmpz_mod_ctx_struct * ctx; fmpz * tmp; slong m; } fmpz_mod_poly_interval_poly_arg_t; void fmpz_mod_poly_factor_clear(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_realloc(fmpz_mod_poly_factor_t fac, slong alloc, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_fit_length(fmpz_mod_poly_factor_t fac, slong len, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_set(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_FACTOR_INLINE void fmpz_mod_poly_factor_swap(fmpz_mod_poly_factor_t a, fmpz_mod_poly_factor_t b, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_factor_struct t = *a; *a = *b; *b = t; } void fmpz_mod_poly_factor_get_poly(fmpz_mod_poly_t a, const fmpz_mod_poly_factor_t b, slong i, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_insert(fmpz_mod_poly_factor_t fac, const fmpz_mod_poly_t poly, slong exp, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_print(const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_print_pretty(const fmpz_mod_poly_factor_t fac, const char *var, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_concat(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_pow(fmpz_mod_poly_factor_t fac, slong exp, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_irreducible(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_irreducible_ddf(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_irreducible_rabin(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_irreducible_rabin_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); int _fmpz_mod_poly_is_squarefree(const fmpz * f, slong len, const fmpz_mod_ctx_t ctx); int _fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz * f, slong len, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_squarefree(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_factor_equal_deg_prob(fmpz_mod_poly_t factor, flint_rand_t state, const fmpz_mod_poly_t pol, slong d, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_equal_deg_with_frob( fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, slong d, const fmpz_mod_poly_t frob, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_equal_deg(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t pol, slong d, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_distinct_deg_with_frob( fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_poly_t frob, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_distinct_deg(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const *degs, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_distinct_deg_threaded_with_frob( fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_poly_t frob, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_distinct_deg_threaded( fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const * degs, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_squarefree(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_cantor_zassenhaus(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_kaltofen_shoup(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); void fmpz_mod_poly_factor_berlekamp(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); void _fmpz_mod_poly_interval_poly_worker(void * arg_ptr); /* Roots *********************************************************************/ void fmpz_mod_poly_roots(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_roots_factored(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_factor_t n, const fmpz_mod_ctx_t ctx); int fmpz_mod_poly_roots_factored_with_length_limit(fmpz_mod_poly_factor_t x0, const fmpz_mod_poly_t f, int with_mult, slong length_limit, const fmpz_factor_t fac, const fmpz_mod_ctx_t ctx); /* Inlines *******************************************************************/ void fmpz_mod_poly_factor_get_fmpz_mod_poly(fmpz_mod_poly_t z, fmpz_mod_poly_factor_t fac, slong i, const fmpz_mod_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mod_poly_factor/000077500000000000000000000000001461254215100176365ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_poly_factor/clear.c000066400000000000000000000015331461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_clear(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < fac->alloc; i++) fmpz_mod_poly_clear(fac->poly + i, ctx); flint_free(fac->poly); flint_free(fac->exp); } flint-3.1.3/src/fmpz_mod_poly_factor/concat.c000066400000000000000000000015311461254215100212510ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_concat(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < fac->num; i++) fmpz_mod_poly_factor_insert(res, fac->poly + i, fac->exp[i], ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/factor.c000066400000000000000000000015631461254215100212650ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { slong n = fmpz_mod_poly_degree(f, ctx); flint_bitcnt_t bits = fmpz_bits(fmpz_mod_ctx_modulus(ctx)); if (5 * bits + n > 75) fmpz_mod_poly_factor_kaltofen_shoup(res, f, ctx); else fmpz_mod_poly_factor_cantor_zassenhaus(res, f, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/factor_berlekamp.c000066400000000000000000000201551461254215100233050ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #include "fmpz_mod_mat.h" static void fmpz_mod_poly_to_fmpz_mat_col(fmpz_mat_t mat, slong col, fmpz_mod_poly_t poly) { slong i; for (i = 0; i < poly->length; i++) fmpz_set(fmpz_mat_entry(mat, i, col), poly->coeffs + i); for (; i < mat->r; i++) fmpz_zero(fmpz_mat_entry(mat, i, col)); } static void fmpz_mat_col_to_fmpz_mod_poly_shifted(fmpz_mod_poly_t poly, fmpz_mat_t mat, slong col, slong *shift, const fmpz_mod_ctx_t ctx) { slong i, j, rows = mat->r; fmpz_mod_poly_fit_length(poly, rows, ctx); for (i = 0, j = 0; j < rows; j++) { if (shift[j]) fmpz_zero(poly->coeffs + j); else { fmpz_set(poly->coeffs + j, fmpz_mat_entry(mat, i, col)); i++; } } _fmpz_mod_poly_set_length(poly, rows); _fmpz_mod_poly_normalise(poly); } static void __fmpz_mod_poly_factor_berlekamp(fmpz_mod_poly_factor_t factors, flint_rand_t state, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { const slong n = fmpz_mod_poly_degree(f, ctx); const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_mod_poly_factor_t fac1, fac2; fmpz_mod_poly_t x, x_p; fmpz_mod_poly_t x_pi, x_pi2; fmpz_mod_poly_t Q, r; fmpz_mat_t matrix; fmpz_t coeff, q, mul, pow; slong i, nullity, col, row; slong *shift; fmpz_mod_poly_t *basis; if (f->length <= 2) { fmpz_mod_poly_factor_insert(factors, f, 1, ctx); return; } fmpz_init(coeff); fmpz_init(mul); /* q = p - 1 */ fmpz_init_set(q, p); fmpz_sub_ui(q, q, 1); fmpz_mod(q, q, p); /* pow = (p-1)/2 */ fmpz_init(pow); if (fmpz_cmp_ui(p, 3) > 0) { fmpz_set(pow, q); fmpz_divexact_ui(pow, pow, 2); } /* Step 1, compute x^p mod f in F_p[X]/ */ fmpz_mod_poly_init(x, ctx); fmpz_mod_poly_init(x_p, ctx); fmpz_mod_poly_set_coeff_ui(x, 1, 1, ctx); fmpz_mod_poly_powmod_fmpz_binexp(x_p, x, p, f, ctx); fmpz_mod_poly_clear(x, ctx); /* Step 2, compute the matrix for the Berlekamp Map */ fmpz_mat_init(matrix, n, n); fmpz_mod_poly_init(x_pi, ctx); fmpz_mod_poly_init(x_pi2, ctx); fmpz_mod_poly_set_coeff_ui(x_pi, 0, 1, ctx); for (i = 0; i < n; i++) { /* Q - I */ fmpz_mod_poly_set(x_pi2, x_pi, ctx); fmpz_mod_poly_get_coeff_fmpz(coeff, x_pi2, i, ctx); if (!fmpz_is_zero(coeff)) { fmpz_sub_ui(coeff, coeff, 1); fmpz_mod(coeff, coeff, p); fmpz_mod_poly_set_coeff_fmpz(x_pi2, i, coeff, ctx); } else { fmpz_mod_poly_set_coeff_fmpz(x_pi2, i, q, ctx); } fmpz_mod_poly_to_fmpz_mat_col(matrix, i, x_pi2); fmpz_mod_poly_mulmod(x_pi, x_pi, x_p, f, ctx); } fmpz_mod_poly_clear(x_p, ctx); fmpz_mod_poly_clear(x_pi, ctx); fmpz_mod_poly_clear(x_pi2, ctx); /* Row reduce Q - I */ nullity = n - fmpz_mod_mat_rref(matrix, matrix, ctx); /* Find a basis for the nullspace */ basis = (fmpz_mod_poly_t *) flint_malloc(nullity * sizeof(fmpz_mod_poly_t)); shift = (slong *) flint_calloc(n, sizeof(slong)); col = 1; /* first column is always zero */ row = 0; shift[0] = 1; for (i = 1; i < nullity; i++) { fmpz_mod_poly_init(basis[i], ctx); while (!fmpz_is_zero(fmpz_mat_entry(matrix, row, col))) { row++; col++; } fmpz_mat_col_to_fmpz_mod_poly_shifted(basis[i], matrix, col, shift, ctx); fmpz_mod_poly_set_coeff_fmpz(basis[i], col, q, ctx); shift[col] = 1; col++; } flint_free(shift); fmpz_mat_clear(matrix); /* we are done */ if (nullity == 1) { fmpz_mod_poly_factor_insert(factors, f, 1, ctx); } else { /* Generate random linear combinations */ fmpz_mod_poly_t factor, b, power, g; fmpz_mod_poly_init(factor, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(power, ctx); fmpz_mod_poly_init(g, ctx); while (1) { do { fmpz_mod_poly_zero(factor, ctx); for (i = 1; i < nullity; i++) { fmpz_randm(mul, state, p); fmpz_mod_poly_scalar_mul_fmpz(b, basis[i], mul, ctx); fmpz_mod_poly_add(factor, factor, b, ctx); } fmpz_randm(coeff, state, p); fmpz_mod_poly_set_coeff_fmpz(factor, 0, coeff, ctx); if (!fmpz_mod_poly_is_zero(factor, ctx)) fmpz_mod_poly_make_monic(factor, factor, ctx); } while (fmpz_mod_poly_is_zero(factor, ctx) || (factor->length < 2 && fmpz_is_one(factor->coeffs))); fmpz_mod_poly_gcd(g, f, factor, ctx); if (fmpz_mod_poly_length(g, ctx) != 1) break; if (fmpz_cmp_ui(p, 3) > 0) fmpz_mod_poly_powmod_fmpz_binexp(power, factor, pow, f, ctx); else fmpz_mod_poly_set(power, factor, ctx); fmpz_add(power->coeffs, power->coeffs, q); fmpz_mod(power->coeffs, power->coeffs, p); _fmpz_mod_poly_normalise(power); fmpz_mod_poly_gcd(g, power, f, ctx); if (fmpz_mod_poly_length(g, ctx) != 1) break; } fmpz_mod_poly_clear(power, ctx); fmpz_mod_poly_clear(factor, ctx); fmpz_mod_poly_clear(b, ctx); if (!fmpz_mod_poly_is_zero(g, ctx)) fmpz_mod_poly_make_monic(g, g, ctx); fmpz_mod_poly_factor_init(fac1, ctx); fmpz_mod_poly_factor_init(fac2, ctx); __fmpz_mod_poly_factor_berlekamp(fac1, state, g, ctx); fmpz_mod_poly_init(Q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_divrem(Q, r, f, g, ctx); fmpz_mod_poly_clear(r, ctx); if (!fmpz_mod_poly_is_zero(Q, ctx)) fmpz_mod_poly_make_monic(Q, Q, ctx); __fmpz_mod_poly_factor_berlekamp(fac2, state, Q, ctx); fmpz_mod_poly_factor_concat(factors, fac1, ctx); fmpz_mod_poly_factor_concat(factors, fac2, ctx); fmpz_mod_poly_factor_clear(fac1, ctx); fmpz_mod_poly_factor_clear(fac2, ctx); fmpz_mod_poly_clear(Q, ctx); fmpz_mod_poly_clear(g, ctx); } for (i = 1; i < nullity; i++) fmpz_mod_poly_clear(basis[i], ctx); flint_free(basis); fmpz_clear(coeff); fmpz_clear(q); fmpz_clear(mul); fmpz_clear(pow); } void fmpz_mod_poly_factor_berlekamp(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { slong i; flint_rand_t r; fmpz_mod_poly_t v; fmpz_mod_poly_factor_t sq_free; fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_make_monic(v, f, ctx); /* compute squarefree factorisation */ fmpz_mod_poly_factor_init(sq_free, ctx); fmpz_mod_poly_factor_squarefree(sq_free, v, ctx); /* run Berlekamp algorithm for all squarefree factors */ flint_randinit(r); for (i = 0; i < sq_free->num; i++) { __fmpz_mod_poly_factor_berlekamp(factors, r, sq_free->poly + i, ctx); } flint_randclear(r); /* compute multiplicities of factors in f */ for (i = 0; i < factors->num; i++) factors->exp[i] = fmpz_mod_poly_remove(v, factors->poly + i, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_factor_clear(sq_free, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/factor_cantor_zassenhaus.c000066400000000000000000000044111461254215100250720ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_cantor_zassenhaus(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { slong i, j; fmpz_mod_poly_t t, h, v, g, x; fmpz_mod_poly_factor_t tfac; res->num = 0; fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(x, ctx); fmpz_mod_poly_factor_init(tfac, ctx); fmpz_mod_poly_gen(h, ctx); fmpz_mod_poly_gen(x, ctx); fmpz_mod_poly_make_monic(v, f, ctx); i = 0; do { i++; fmpz_mod_poly_powmod_fmpz_binexp(t, h, fmpz_mod_ctx_modulus(ctx), v, ctx); fmpz_mod_poly_swap(h, t, ctx); fmpz_mod_poly_sub(t, h, x, ctx); fmpz_mod_poly_gcd(g, t, v, ctx); if (g->length != 1) { FLINT_ASSERT(fmpz_mod_poly_is_monic(g, ctx)); fmpz_mod_poly_factor_equal_deg(tfac, g, i, ctx); fmpz_mod_poly_factor_fit_length(res, res->num + tfac->num, ctx); for (j = 0; j < tfac->num; j++) { res->exp[res->num] = fmpz_mod_poly_remove(v, tfac->poly + j, ctx); fmpz_mod_poly_swap(res->poly + res->num, tfac->poly + j, ctx); res->num++; } } } while (v->length >= 2 * i + 3); if (v->length > 1) fmpz_mod_poly_factor_insert(res, v, 1, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(x, ctx); fmpz_mod_poly_factor_clear(tfac, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/factor_distinct_deg.c000066400000000000000000000205371461254215100240070ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2020 William Hart Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #ifdef __GNUC__ # define ceil __builtin_ceil # define log __builtin_log # define pow __builtin_pow #else # include #endif /* the degrees are written as exponents of the corresponding factors */ void fmpz_mod_poly_factor_distinct_deg_with_frob( fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_poly_t frob, /* x^p mod poly */ const fmpz_mod_ctx_t ctx) { const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_mod_poly_t f, g, v, vinv, tmp; fmpz_mod_poly_t *h, *H, *I; slong i, j, l, m, n, d; fmpz_mat_t HH, HHH; double beta; FLINT_ASSERT(fmpz_mod_poly_is_monic(poly, ctx)); n = fmpz_mod_poly_degree(poly, ctx); if (n == 1) { fmpz_mod_poly_factor_fit_length(res, 1, ctx); fmpz_mod_poly_set(res->poly + 0, poly, ctx); res->exp[0] = 1; res->num = 1; return; } beta = 0.5 * (1. - (log(2) / log(n))); l = ceil(pow(n, beta)); m = ceil(0.5 * n / l); /* initialization */ fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(vinv, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(tmp, ctx); h = FLINT_ARRAY_ALLOC(2*m + l + 1, fmpz_mod_poly_t); H = h + (l + 1); I = H + m; for (i = 0; i < 2*m + l + 1; i++) fmpz_mod_poly_init(h[i], ctx); fmpz_mod_poly_set(v, poly, ctx); fmpz_mod_poly_set(vinv, polyinv, ctx); /* compute baby steps: h[i]=x^{p^i}mod v */ fmpz_mod_poly_set_coeff_ui(h[0], 1, 1, ctx); fmpz_mod_poly_set(h[1], frob, ctx); #if FLINT_WANT_ASSERT fmpz_mod_poly_powmod_x_fmpz_preinv(tmp, p, v, vinv, ctx); FLINT_ASSERT(fmpz_mod_poly_equal(tmp, h[1], ctx)); #endif if (fmpz_sizeinbase(p, 2) > ((n_sqrt(v->length - 1) + 1) * 3) / 4) { for (i = 1; i < FLINT_BIT_COUNT(l); i++) fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(*(h + 1 + (1 << (i - 1))), *(h + 1), (1 << (i - 1)), (1 << (i - 1)), *(h + (1 << (i - 1))), v, vinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_vec_preinv(*(h + 1 + (1 << (i - 1))), *(h + 1), (1 << (i - 1)), l - (1 << (i - 1)), *(h + (1 << (i - 1))), v, vinv, ctx); } else { for (i = 2; i < l + 1; i++) { fmpz_mod_poly_init(h[i], ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(h[i], h[i - 1], p, v, vinv, ctx); } } /* compute coarse distinct-degree factorisation */ res->num = 0; fmpz_mod_poly_set(H[0], h[l], ctx); fmpz_mat_init(HH, n_sqrt(v->length - 1) + 1, v->length - 1); fmpz_mod_poly_precompute_matrix(HH, H[0], v, vinv, ctx); d = 1; for (j = 0; j < m; j++) { /* compute giant steps: H[i]=x^{p^(li)}mod v */ if (j > 0) { if (I[j - 1]->length > 1) { _fmpz_mod_poly_reduce_matrix_mod_poly(HHH, HH, v, ctx); fmpz_mat_clear(HH); fmpz_mat_init_set(HH, HHH); fmpz_mat_clear(HHH); fmpz_mod_poly_rem(tmp, H[j - 1], v, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(H[j], tmp, HH, v, vinv, ctx); } else fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(H[j], H[j - 1], HH, v, vinv, ctx); } /* compute interval polynomials */ fmpz_mod_poly_set_coeff_ui(I[j], 0, 1, ctx); for (i = l - 1; (i >= 0) && (2 * d <= v->length - 1); i--, d++) { fmpz_mod_poly_rem(tmp, h[i], v, ctx); fmpz_mod_poly_sub(tmp, H[j], tmp, ctx); fmpz_mod_poly_mulmod_preinv(I[j], tmp, I[j], v, vinv, ctx); } /* compute F_j=f^{[j*l+1]} * ... * f^{[j*l+l]} */ /* F_j is stored on the place of I_j */ fmpz_mod_poly_gcd(I[j], v, I[j], ctx); if (I[j]->length > 1) { fmpz_mod_poly_divrem(v, tmp, v, I[j], ctx); fmpz_mod_poly_reverse(vinv, v, v->length, ctx); fmpz_mod_poly_inv_series(vinv, vinv, v->length, ctx); } if (v->length - 1 < 2 * d) { break; } } if (v->length > 1) { fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = v->length - 1; fmpz_mod_poly_swap(res->poly + res->num, v, ctx); res->num++; } /* compute fine distinct-degree factorisation */ for (j = 0; j < m; j++) { if (I[j]->length - 1 > (j + 1)*l || j == 0) { fmpz_mod_poly_set(g, I[j], ctx); for (i = l - 1; i >= 0 && (g->length > 1); i--) { /* compute f^{[l*(j+1)-i]} */ fmpz_mod_poly_sub(tmp, H[j], h[i], ctx); fmpz_mod_poly_gcd(f, g, tmp, ctx); if (f->length > 1) { /* insert f^{[l*(j+1)-i]} into res */ fmpz_mod_poly_divrem(g, tmp, g, f, ctx); FLINT_ASSERT(fmpz_mod_poly_is_monic(f, ctx)); fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = l * (j + 1) - i; fmpz_mod_poly_swap(res->poly + res->num, f, ctx); res->num++; } } } else if (I[j]->length > 1) { FLINT_ASSERT(fmpz_mod_poly_is_monic(I[j], ctx)); fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = I[j]->length - 1; fmpz_mod_poly_swap(res->poly + res->num, I[j], ctx); res->num++; } } /* cleanup */ fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(vinv, ctx); fmpz_mod_poly_clear(tmp, ctx); fmpz_mat_clear(HH); for (i = 0; i < l + 1; i++) fmpz_mod_poly_clear(h[i], ctx); for (i = 0; i < m; i++) { fmpz_mod_poly_clear(H[i], ctx); fmpz_mod_poly_clear(I[i], ctx); } flint_free(h); } void fmpz_mod_poly_factor_distinct_deg(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const *degs, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t v, vinv, xp; fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(vinv, ctx); fmpz_mod_poly_init(xp, ctx); fmpz_mod_poly_make_monic(v, poly, ctx); fmpz_mod_poly_reverse(vinv, v, v->length, ctx); fmpz_mod_poly_inv_series(vinv, vinv, v->length, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(xp, fmpz_mod_ctx_modulus(ctx), v, vinv, ctx); fmpz_mod_poly_factor_distinct_deg_with_frob(res, v, vinv, xp, ctx); /* satisfy the requirements of the interface */ for (i = 0; i < res->num; i++) { (*degs)[i] = res->exp[i]; res->exp[i] = 1; } fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(vinv, ctx); fmpz_mod_poly_clear(xp, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/factor_distinct_deg_threaded.c000066400000000000000000000575611461254215100256560ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013, 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #ifdef __GNUC__ # define ceil __builtin_ceil # define log __builtin_log # define pow __builtin_pow #else # include #endif void _fmpz_mod_poly_precompute_matrix_worker (void * arg_ptr) { fmpz_mod_poly_matrix_precompute_arg_t arg = *((fmpz_mod_poly_matrix_precompute_arg_t *) arg_ptr); /* Set rows of A to powers of poly1 */ slong i, n, m; fmpz_mod_poly_struct * poly1 = arg.poly1; fmpz_mod_poly_struct * poly2 = arg.poly2; fmpz_mod_poly_struct * poly2inv = arg.poly2inv; fmpz_mat_struct * A = arg.A; const fmpz_mod_ctx_struct * ctx = arg.ctx; n = poly2->length - 1; m = n_sqrt(n) + 1; fmpz_one(A->rows[0] + 0); _fmpz_vec_set(A->rows[1], poly1->coeffs, n); for (i = 2; i < m; i++) _fmpz_mod_poly_mulmod_preinv(A->rows[i], A->rows[i - 1], n, poly1->coeffs, n, poly2->coeffs, n + 1, poly2inv->coeffs, n + 1, ctx); } void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr) { fmpz_mod_poly_compose_mod_precomp_preinv_arg_t arg= *((fmpz_mod_poly_compose_mod_precomp_preinv_arg_t*) arg_ptr); fmpz_mat_t B, C; fmpz * t, * h; slong i, n, m; fmpz_mod_poly_struct * res = arg.res; fmpz_mod_poly_struct * poly1 = arg.poly1; fmpz_mod_poly_struct * poly3 = arg.poly3; fmpz_mod_poly_struct * poly3inv = arg.poly3inv; fmpz_mat_struct * A = arg.A; const fmpz_mod_ctx_struct * ctx = arg.ctx; if (poly3->length == 1) return; if (poly1->length == 1) { fmpz_set(res->coeffs, poly1->coeffs); return; } if (poly3->length == 2) { _fmpz_mod_poly_evaluate_fmpz(res->coeffs, poly1->coeffs, poly1->length, A->rows[1] + 0, ctx); return; } n = poly3->length - 1; m = n_sqrt(n) + 1; fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, n); h = _fmpz_vec_init(n); t = _fmpz_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < poly1->length / m; i++) _fmpz_vec_set(B->rows[i], poly1->coeffs + i*m, m); _fmpz_vec_set(B->rows[i], poly1->coeffs + i*m, poly1->length % m); fmpz_mat_mul(C, B, A); for (i = 0; i < m; i++) _fmpz_mod_vec_set_fmpz_vec(C->rows[i], C->rows[i], n, ctx); /* Evaluate block composition using the Horner scheme */ _fmpz_vec_set(res->coeffs, C->rows[m - 1], n); _fmpz_mod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly3->coeffs, poly3->length, poly3inv->coeffs, poly3inv->length, ctx); for (i = m - 2; i >= 0; i--) { _fmpz_mod_poly_mulmod_preinv(t, res->coeffs, n, h, n, poly3->coeffs, poly3->length, poly3inv->coeffs, poly3->length, ctx); _fmpz_mod_poly_add(res->coeffs, t, n, C->rows[i], n, ctx); } _fmpz_vec_clear(h, n); _fmpz_vec_clear(t, n); fmpz_mat_clear(B); fmpz_mat_clear(C); return; } void _fmpz_mod_poly_interval_poly_worker(void * arg_ptr) { fmpz_mod_poly_interval_poly_arg_t arg = *((fmpz_mod_poly_interval_poly_arg_t *) arg_ptr); slong k, m = arg.m; fmpz_mod_poly_struct * H = arg.H; fmpz_mod_poly_struct * res = arg.res; fmpz_mod_poly_struct * v = arg.v; fmpz_mod_poly_struct * vinv = arg.vinv; fmpz_mod_poly_struct * baby = arg.baby; const fmpz_mod_ctx_struct * ctx = arg.ctx; const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz * tmp = arg.tmp; fmpz_t invV; fmpz_init(invV); fmpz_invmod(invV, v->coeffs + v->length - 1, p); fmpz_set_ui(res->coeffs + 0, 1); for (k = m - 1; k >= 0; k--) { _fmpz_vec_zero(tmp, v->length - 1); if (baby[k].length < v->length) _fmpz_vec_set(tmp, baby[k].coeffs, baby[k].length); else _fmpz_mod_poly_rem(tmp, baby[k].coeffs, baby[k].length, v->coeffs , v->length, invV, ctx); _fmpz_mod_poly_sub(tmp, H->coeffs, H->length, tmp, v->length - 1, ctx); _fmpz_mod_poly_mulmod_preinv(res->coeffs, tmp, v->length - 1, res->coeffs, v->length - 1, v->coeffs, v->length, vinv->coeffs, vinv->length, ctx); } fmpz_clear(invV); return; } /* the degrees are written as exponents of the corresponding factors */ void fmpz_mod_poly_factor_distinct_deg_threaded_with_frob( fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_poly_t polyinv, const fmpz_mod_poly_t frob, /* x^p mod poly */ const fmpz_mod_ctx_t ctx) { const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_mod_poly_t f, g, v, vinv, tmp, II; fmpz_mod_poly_struct * h, * H, * I, * scratch; slong i, j, k, l, m, n, d, c1 = 1, c2; fmpz_mat_struct * HH; double beta; thread_pool_handle * threads; slong num_threads; fmpz_mod_poly_matrix_precompute_arg_t * args1; fmpz_mod_poly_compose_mod_precomp_preinv_arg_t * args2; fmpz_mod_poly_interval_poly_arg_t * args3; FLINT_ASSERT(fmpz_mod_poly_is_monic(poly, ctx)); n = fmpz_mod_poly_degree(poly, ctx); if (n == 1) { fmpz_mod_poly_factor_fit_length(res, 1, ctx); fmpz_mod_poly_set(res->poly + 0, poly, ctx); res->exp[0] = 1; res->num = 1; return; } beta = 0.5 * (1. - (log(2) / log(n))); l = ceil(pow(n, beta)); m = ceil(0.5 * n / l); /* initialization */ fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(vinv, ctx); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(tmp, ctx); fmpz_mod_poly_init(II, ctx); num_threads = flint_request_threads(&threads, flint_get_num_threads()); h = FLINT_ARRAY_ALLOC(2*m + l + num_threads + 2, fmpz_mod_poly_struct); for (i = 0; i < 2*m + l + 2 + num_threads; i++) fmpz_mod_poly_init(h + i, ctx); H = h + (l + 1); I = H + m; scratch = I + m; HH = FLINT_ARRAY_ALLOC(num_threads + 2, fmpz_mat_struct); args1 = FLINT_ARRAY_ALLOC(num_threads + 1, fmpz_mod_poly_matrix_precompute_arg_t); args2 = FLINT_ARRAY_ALLOC(num_threads + 1, fmpz_mod_poly_compose_mod_precomp_preinv_arg_t); args3 = FLINT_ARRAY_ALLOC(num_threads + 1, fmpz_mod_poly_interval_poly_arg_t); fmpz_mod_poly_set(v, poly, ctx); fmpz_mod_poly_set(vinv, polyinv, ctx); /* compute baby steps: h[i]=x^{p^i}mod v */ fmpz_mod_poly_set_coeff_ui(h + 0, 1, 1, ctx); fmpz_mod_poly_set(h + 1, frob, ctx); #if FLINT_WANT_ASSERT fmpz_mod_poly_powmod_x_fmpz_preinv(tmp, p, v, vinv, ctx); FLINT_ASSERT(fmpz_mod_poly_equal(tmp, h + 1, ctx)); #endif if (fmpz_sizeinbase(p, 2) > ((n_sqrt(v->length - 1) + 1) * 3) / 4) { for (i = 1; i < FLINT_BIT_COUNT(l); i++) fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(h + 1 + (1 << (i - 1)), h + 1, 1 << (i - 1), 1 << (i - 1), h + (1 << (i - 1)), v, vinv, ctx, threads, num_threads); fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(h + 1 + (1 << (i - 1)), h + 1, 1 << (i - 1), l - (1 << (i - 1)), h + (1 << (i - 1)), v, vinv, ctx, threads, num_threads); } else { for (i = 2; i < l + 1; i++) { fmpz_mod_poly_init(h + i, ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(h + i, h + i - 1, p, v, vinv, ctx); } } /* compute coarse distinct-degree factorisation */ res->num = 0; fmpz_mod_poly_set(H + 0, h + l, ctx); fmpz_mat_init(HH + 0, n_sqrt(v->length - 1) + 1, v->length - 1); fmpz_mod_poly_precompute_matrix(HH + 0, H + 0, v, vinv, ctx); for (d = 1, j = 0; j < m /(num_threads + 1) + 1; j++) { if (j == 0) { for (i = 0; i < num_threads + 1; i++) { if (i > 0 && I[i - 1].length > 1) { _fmpz_mod_poly_reduce_matrix_mod_poly(HH + num_threads + 1, HH + 0, v, ctx); fmpz_mat_clear(HH + 0); fmpz_mat_init_set(HH + 0, HH + num_threads + 1); fmpz_mat_clear(HH + num_threads + 1); fmpz_mod_poly_rem(tmp, H + i - 1, v, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(H + i, tmp, HH + 0, v, vinv, ctx); } else if (i > 0) fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(H + i, H + i - 1, HH + 0, v, vinv, ctx); /* compute interval polynomials */ fmpz_mod_poly_set_coeff_ui(I + i, 0, 1, ctx); for (k = l - 1; k >= 0 && 2*d <= v->length - 1; k--, d++) { fmpz_mod_poly_rem(tmp, h + k, v, ctx); fmpz_mod_poly_sub(tmp, H + i, tmp, ctx); fmpz_mod_poly_mulmod_preinv(I + i, tmp, I + i, v, vinv, ctx); } /* compute F_j=f^{[j*l+1]} * ... * f^{[j*l+l]} */ /* F_j is stored on the place of I_j */ fmpz_mod_poly_gcd(I + i, v, I + i, ctx); if (I[i].length > 1) { fmpz_mod_poly_remove(v, I + i, ctx); fmpz_mod_poly_reverse(vinv, v, v->length, ctx); fmpz_mod_poly_inv_series(vinv, vinv, v->length, ctx); } if (v->length - 1 < 2*d) break; } if (v->length - 1 < 2*d) break; } else if (j == 1 && num_threads + 1 < m) { if (I[num_threads].length > 1) { _fmpz_mod_poly_reduce_matrix_mod_poly(HH + num_threads + 1, HH + 0, v, ctx); fmpz_mat_clear(HH + 0); fmpz_mat_init_set(HH + 0, HH + num_threads + 1); fmpz_mat_clear(HH + num_threads + 1); } /* we make thread 0 the master thread, but don't use it in this loop */ for (c1 = 1, i = 1; i < num_threads + 1 && i + num_threads + 1 < m; i++, c1++) { fmpz_mat_init(HH + i, n_sqrt(v->length - 1) + 1, v->length - 1); fmpz_mod_poly_rem(scratch + i, H + i, v, ctx); if (scratch[i].length < v->length - 1) { fmpz_mod_poly_fit_length(scratch + i, v->length - 1, ctx); _fmpz_vec_zero(scratch[i].coeffs + scratch[i].length, v->length - 1 - scratch[i].length); _fmpz_mod_poly_set_length(scratch + i, v->length - 1); } args1[i].A = HH + i; args1[i].poly1 = scratch + i; args1[i].poly2 = v; args1[i].poly2inv = vinv; args1[i].ctx = ctx; thread_pool_wake(global_thread_pool, threads[i - 1], 0, _fmpz_mod_poly_precompute_matrix_worker, &args1[i]); } for (i = 1; i < c1; i++) thread_pool_wait(global_thread_pool, threads[i - 1]); fmpz_mod_poly_rem(tmp, H + num_threads, v, ctx); for (i = 0; i < c1; i++) { fmpz_mod_poly_fit_length(H + num_threads + 1 + i, v->length - 1, ctx); _fmpz_mod_poly_set_length(H + num_threads + 1 + i, v->length - 1); args2[i].A = HH + i; args2[i].res = H + num_threads + i + 1; args2[i].poly1 = tmp; args2[i].poly3 = v; args2[i].poly3inv = vinv; args2[i].ctx = ctx; } for (i = 1; i < c1; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker, &args2[i]); } _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker(&args2[0]); _fmpz_mod_poly_normalise(H + num_threads + 1); for (i = 1; i < c1; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _fmpz_mod_poly_normalise(H + num_threads + 1 + i); } for (i = 0; i < c1; i++) { fmpz_mod_poly_fit_length(I + num_threads + 1 + i, v->length - 1, ctx); _fmpz_mod_poly_set_length(I + num_threads + 1 + i, v->length - 1); _fmpz_vec_zero(I[num_threads + 1 + i].coeffs, v->length - 1); args3[i].baby = h; args3[i].H = H + num_threads + 1 + i; args3[i].m = l; args3[i].res = I + num_threads + 1 + i; args3[i].v = v; args3[i].vinv = vinv; args3[i].ctx = ctx; args3[i].tmp = _fmpz_vec_init(v->length - 1); } for (i = 1; i < c1; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _fmpz_mod_poly_interval_poly_worker, &args3[i]); } _fmpz_mod_poly_interval_poly_worker(&args3[0]); _fmpz_mod_poly_normalise(I + num_threads + 1); for (i = 1; i < c1; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _fmpz_mod_poly_normalise(I + num_threads + i + 1); } for (i = 0; i < c1; i++) { _fmpz_vec_clear(args3[i].tmp, v->length - 1); } fmpz_mod_poly_set_ui(II, 1, ctx); for (i = 0; i < c1; i++) fmpz_mod_poly_mulmod_preinv(II, II, I + num_threads + 1 + i, v, vinv, ctx); fmpz_mod_poly_gcd(II, v, II, ctx); if (II->length > 1) { fmpz_mod_poly_remove(v, II, ctx); fmpz_mod_poly_reverse(vinv, v, v->length, ctx); fmpz_mod_poly_inv_series(vinv, vinv, v->length, ctx); for (i = 0; i < c1; i++) { fmpz_mod_poly_gcd(I + num_threads + 1 + i, I + num_threads + 1 + i, II, ctx); if (I[num_threads + 1 + i].length > 1) fmpz_mod_poly_remove(II, I + num_threads + 1 + i, ctx); } } else { for (i = 0; i < c1; i++) fmpz_mod_poly_set_ui(I + num_threads + 1 + i, 1, ctx); } d = d + c1*l; if (v->length-1 < 2*d) break; } else if (j*(num_threads + 1) < m) { for (c2 = 0, i = 0; i < num_threads + 1 && j*(num_threads + 1) + i < m; i++, c2++) { if (HH[i].c > v -> length - 1) { _fmpz_mod_poly_reduce_matrix_mod_poly(HH + num_threads + 1, HH + i, v, ctx); fmpz_mat_clear(HH + i); fmpz_mat_init_set(HH + i, HH + num_threads + 1); fmpz_mat_clear(HH + num_threads + 1); } } fmpz_mod_poly_rem(tmp, H + j*(num_threads + 1) - 1, v, ctx); for (i = 0; i < c2; i++) { fmpz_mod_poly_fit_length(H + j*(num_threads + 1) + i, v->length - 1, ctx); _fmpz_mod_poly_set_length(H + j*(num_threads + 1) + i, v->length - 1); args2[i].A = HH + i; args2[i].res = H + j*(num_threads + 1) + i; args2[i].poly1 = tmp; args2[i].poly3 = v; args2[i].poly3inv = vinv; args2[i].ctx = ctx; } for (i = 1; i < c2; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker, &args2[i]); } _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker(&args2[0]); _fmpz_mod_poly_normalise(H + j*(num_threads + 1)); for (i = 1; i < c2; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _fmpz_mod_poly_normalise(H + j*(num_threads + 1) + i); } for (i = 0; i < c2; i++) { fmpz_mod_poly_fit_length(I + j*(num_threads + 1) + i, v->length - 1, ctx); _fmpz_mod_poly_set_length(I + j*(num_threads + 1) + i, v->length - 1); _fmpz_vec_zero(I[j*(num_threads + 1) + i].coeffs, v->length - 1); args3[i].baby = h; args3[i].H = H + j*(num_threads + 1) + i; args3[i].m = l; args3[i].res = I + j*(num_threads + 1) + i; args3[i].v = v; args3[i].vinv = vinv; args3[i].ctx = ctx; args3[i].tmp = _fmpz_vec_init(v->length - 1); } for (i = 1; i < c2; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _fmpz_mod_poly_interval_poly_worker, &args3[i]); } _fmpz_mod_poly_interval_poly_worker(&args3[0]); _fmpz_mod_poly_normalise(I + j*(num_threads + 1)); for (i = 1; i < c2; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _fmpz_mod_poly_normalise(I + j*(num_threads + 1) + i); } for (i = 0; i < c2; i++) { _fmpz_vec_clear(args3[i].tmp, v->length - 1); } fmpz_mod_poly_set_ui(II, 1, ctx); for (i = 0; i < c2; i++) fmpz_mod_poly_mulmod_preinv(II, II, I + j*(num_threads + 1) + i, v, vinv, ctx); fmpz_mod_poly_gcd(II, v, II, ctx); if (II->length > 1) { fmpz_mod_poly_remove(v, II, ctx); fmpz_mod_poly_reverse(vinv, v, v->length, ctx); fmpz_mod_poly_inv_series(vinv, vinv, v->length, ctx); for (i = 0; i < c2; i++) { fmpz_mod_poly_gcd(I + j*(num_threads + 1) + i, I + j*(num_threads + 1) + i, II, ctx); if (I[j*(num_threads + 1) + i].length > 1) fmpz_mod_poly_remove(II, I + j*(num_threads + 1) + i, ctx); } } else { for (i = 0; i < c2; i++) fmpz_mod_poly_set_ui(I + j*(num_threads + 1) + i, 1, ctx); } d = d + c2*l; if (v->length - 1 < 2*d) break; } } flint_give_back_threads(threads, num_threads); if (v->length > 1) { fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = v->length - 1; fmpz_mod_poly_swap(res->poly + res->num, v, ctx); res->num++; } /* compute fine distinct-degree factorisation */ for (j = 0; j < m; j++) { if (I[j].length - 1 > (j + 1)*l || j == 0) { fmpz_mod_poly_set(g, I + j, ctx); for (i = l - 1; i >= 0 && g->length > 1; i--) { /* compute f^{[l*(j+1)-i]} */ fmpz_mod_poly_sub(tmp, H + j, h + i, ctx); fmpz_mod_poly_gcd(f, g, tmp, ctx); if (f->length > 1) { /* insert f^{[l*(j+1)-i]} into res */ fmpz_mod_poly_divrem(g, tmp, g, f, ctx); FLINT_ASSERT(fmpz_mod_poly_is_monic(f, ctx)); fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = l * (j + 1) - i; fmpz_mod_poly_swap(res->poly + res->num, f, ctx); res->num++; } } } else if (I[j].length > 1) { FLINT_ASSERT(fmpz_mod_poly_is_monic(I + j, ctx)); fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = I[j].length - 1; fmpz_mod_poly_swap(res->poly + res->num, I + j, ctx); res->num++; } } /* cleanup */ fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(vinv, ctx); fmpz_mod_poly_clear(tmp, ctx); fmpz_mod_poly_clear(II, ctx); for (i = 0; i < 2*m + l + num_threads + 2; i++) fmpz_mod_poly_clear(h + i, ctx); for (i = 0; i < c1; i++) fmpz_mat_clear(HH + i); flint_free(h); flint_free(HH); flint_free(args1); flint_free(args2); flint_free(args3); } void fmpz_mod_poly_factor_distinct_deg_threaded(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const *degs, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t v, vinv, xp; fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(vinv, ctx); fmpz_mod_poly_init(xp, ctx); fmpz_mod_poly_make_monic(v, poly, ctx); fmpz_mod_poly_reverse(vinv, v, v->length, ctx); fmpz_mod_poly_inv_series(vinv, vinv, v->length, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(xp, fmpz_mod_ctx_modulus(ctx), v, vinv, ctx); fmpz_mod_poly_factor_distinct_deg_threaded_with_frob(res, v, vinv, xp, ctx); /* satisfy the requirements of the interface */ for (i = 0; i < res->num; i++) { (*degs)[i] = res->exp[i]; res->exp[i] = 1; } fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(vinv, ctx); fmpz_mod_poly_clear(xp, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/factor_equal_deg.c000066400000000000000000000361131461254215100232720ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" typedef struct { fmpz_mod_poly_t f, xp, a, g; } split_struct; typedef struct { fmpz_mod_poly_t f, xp; } queue_struct; static void _queue_vec_fit_length(queue_struct ** Q, slong * Qalloc, slong new_length, const fmpz_mod_ctx_t ctx) { if (new_length > *Qalloc) { slong i; slong old_alloc = *Qalloc; slong new_alloc = FLINT_MAX(2*old_alloc, new_length); *Q = (queue_struct *) flint_realloc(*Q, new_alloc*sizeof(queue_struct)); *Qalloc = new_alloc; for (i = old_alloc; i < new_alloc; i++) { fmpz_mod_poly_init((*Q)[i].f, ctx); fmpz_mod_poly_init((*Q)[i].xp, ctx); } } } /* given g|f, update Q and res with g and f/g */ void _add_split( fmpz_mod_poly_factor_t res, queue_struct ** Q_, slong * Qlen_, slong * Qalloc_, fmpz_mod_poly_t f, fmpz_mod_poly_t g, slong d, const fmpz_mod_poly_t xp, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_t tmp) { queue_struct * Q = *Q_; slong Qlen = *Qlen_; slong Qalloc = *Qalloc_; slong i, inc = 0; _queue_vec_fit_length(&Q, &Qalloc, Qlen + 2, ctx); fmpz_mod_poly_divrem(Q[Qlen + 0].f, tmp, f, g, ctx); fmpz_mod_poly_swap(Q[Qlen + 1].f, g, ctx); if (Q[Qlen + 0].f->length < Q[Qlen + 1].f->length) fmpz_mod_poly_swap(Q[Qlen + 0].f, Q[Qlen + 1].f, ctx); /* {Q[Qlen + 0], Q[Qlen + 1]} has been sorted by length */ for (i = 0; i < 2; i++) { if (fmpz_mod_poly_degree(Q[Qlen + i].f, ctx) > d) { inc++; fmpz_mod_poly_divrem(tmp, Q[Qlen + i].xp, xp, Q[Qlen + i].f, ctx); } else if (fmpz_mod_poly_degree(Q[Qlen + i].f, ctx) == d) { fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = 1; fmpz_mod_poly_set(res->poly + res->num, Q[Qlen + i].f, ctx); res->num++; } } *Q_ = Q; *Qlen_ = Qlen + inc; *Qalloc_ = Qalloc; } /* a = b^p^0 + ... + b^p^(d-1) in berlekamp subalgebra, i.e. a^p = a mod f */ static void _compute_trace( fmpz_mod_poly_t a, fmpz_mod_poly_t b, slong d, const fmpz_mod_poly_t xp, const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_t xi, fmpz_mod_poly_t t) { slong i; fmpz_mat_t H; #if FLINT_WANT_ASSERT fmpz_mod_poly_t a_check; fmpz_mod_poly_init(a_check, ctx); fmpz_mod_poly_set(t, b, ctx); fmpz_mod_poly_set(a_check, b, ctx); for (i = 1; i < d; i++) { fmpz_mod_poly_powmod_fmpz_binexp(t, t, fmpz_mod_ctx_modulus(ctx), f, ctx); fmpz_mod_poly_add(a_check, a_check, t, ctx); } #endif fmpz_mat_init(H, n_sqrt(f->length - 1) + 1, f->length - 1); if (d < 2) { fmpz_mod_poly_swap(a, b, ctx); } else if (d < 16) { fmpz_mod_poly_precompute_matrix(H, xp, f, finv, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(xi, b, H, f, finv, ctx); fmpz_mod_poly_add(a, b, xi, ctx); for (i = 2; i < d; i++) { fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(t, xi, H, f, finv, ctx); fmpz_mod_poly_swap(xi, t, ctx); fmpz_mod_poly_add(a, a, xi, ctx); } } else { /* Optimized trace calculation from Computing Frobenius maps and factoring polynomials Gathen and Shoup underwhelming for small d */ fmpz_mod_poly_zero(a, ctx); fmpz_mod_poly_set(xi, xp, ctx); /* x^p^2^i*/ while (1) { FLINT_ASSERT(d > 1); fmpz_mod_poly_precompute_matrix(H, xi, f, finv, ctx); if (d % 2 == 0) { fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(t, b, H, f, finv, ctx); fmpz_mod_poly_add(b, b, t, ctx); } else if (fmpz_mod_poly_is_zero(a, ctx)) { fmpz_mod_poly_swap(a, b, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(b, a, H, f, finv, ctx); fmpz_mod_poly_add(b, b, a, ctx); } else { fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(t, a, H, f, finv, ctx); fmpz_mod_poly_add(a, b, t, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(t, b, H, f, finv, ctx); fmpz_mod_poly_add(b, b, t, ctx); } d = d/2; if (d <= 1) { if (fmpz_mod_poly_is_zero(a, ctx)) { fmpz_mod_poly_swap(a, b, ctx); break; } fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(t, xi, H, f, finv, ctx); fmpz_mod_poly_swap(xi, t, ctx); fmpz_mod_poly_precompute_matrix(H, xi, f, finv, ctx); fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(t, a, H, f, finv, ctx); fmpz_mod_poly_add(a, t, b, ctx); break; } fmpz_mod_poly_compose_mod(t, xi, xi, f, ctx); fmpz_mod_poly_swap(xi, t, ctx); } } fmpz_mat_clear(H); FLINT_ASSERT(fmpz_mod_poly_equal(a, a_check, ctx)); #if FLINT_WANT_ASSERT fmpz_mod_poly_clear(a_check, ctx); #endif } /* Two (non-deterministic) algorithms Algorithm 3 and Theorem 2.3.1 from Deterministic Factorization of Polynomials over Finite Fields thesis by David Marquis */ static void _fmpz_mod_poly_factor_equal_deg_via_trace( fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t ff, slong d, const fmpz_mod_poly_t frob, const fmpz_mod_ctx_t ctx) { slong i, j, k; const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_t halfp; /* floor((p-1)/2) */ slong n = fmpz_mod_poly_degree(ff, ctx); slong r = n/d; flint_bitcnt_t r_cutoff; fmpz_mod_poly_t t, tq, tr, finv; slong Qlen, Qalloc; queue_struct * Q; split_struct S[FLINT_BITS + 1]; fmpz_mod_berlekamp_massey_t bma; flint_rand_t state; FLINT_ASSERT(r > 1 && d > 1); r_cutoff = 8*FLINT_BIT_COUNT(d + 1) + fmpz_bits(p); res->num = 0; flint_randinit(state); fmpz_init(halfp); fmpz_sub_ui(halfp, p, 1); fmpz_fdiv_q_2exp(halfp, halfp, 1); fmpz_mod_berlekamp_massey_init(bma, ctx); for (i = 0; i <= FLINT_BITS; i++) { fmpz_mod_poly_init(S[i].f, ctx); fmpz_mod_poly_init(S[i].xp, ctx); fmpz_mod_poly_init(S[i].a, ctx); fmpz_mod_poly_init(S[i].g, ctx); } fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(tq, ctx); fmpz_mod_poly_init(tr, ctx); fmpz_mod_poly_init(finv, ctx); Qalloc = 1; Q = FLINT_ARRAY_ALLOC(Qalloc, queue_struct); for (j = 0; j < Qalloc; j++) { fmpz_mod_poly_init(Q[j].f, ctx); fmpz_mod_poly_init(Q[j].xp, ctx); } fmpz_mod_poly_set(Q[0].f, ff, ctx); fmpz_mod_poly_set(Q[0].xp, frob, ctx); Qlen = 1; /* init done */ next_queued: /* try to factor Q[end].f */ Qlen--; if (Qlen < 0) goto cleanup; n = fmpz_mod_poly_degree(Q[Qlen].f, ctx); r = n/d; FLINT_ASSERT(n == r*d); FLINT_ASSERT(r > 1); fmpz_mod_poly_swap(S->f, Q[Qlen].f, ctx); fmpz_mod_poly_swap(S->xp, Q[Qlen].xp, ctx); fmpz_mod_poly_reverse(finv, S->f, S->f->length, ctx); fmpz_mod_poly_inv_series(finv, finv, S->f->length, ctx); #if FLINT_WANT_ASSERT fmpz_mod_poly_powmod_x_fmpz_preinv(tq, p, S->f, finv, ctx); FLINT_ASSERT(fmpz_mod_poly_equal(S->xp, tq, ctx)); #endif next_alpha: fmpz_mod_poly_randtest(t, state, S->f->length - 1, ctx); _compute_trace(S->a, t, d, S->xp, S->f, finv, ctx, tq, tr); if (fmpz_mod_poly_degree(S->a, ctx) < 1) goto next_alpha; if (r > r_cutoff) { if (fmpz_is_zero(halfp)) fmpz_mod_poly_set(tr, S->a, ctx); else fmpz_mod_poly_powmod_fmpz_binexp_preinv(tr, S->a, halfp, S->f, finv, ctx); fmpz_mod_poly_sub_si(tr, tr, 1, ctx); fmpz_mod_poly_gcd(t, tr, S->f, ctx); if (t->length <= 1 || t->length >= S->f->length) goto next_alpha; _add_split(res, &Q, &Qlen, &Qalloc, S->f, t, d, S->xp, ctx, tr); goto next_queued; } /* If r is not too big, try the "deterministic simplification" to root finding. Instead of constructing h(y) = Res_x(f(x), a(x) - y), find probablistically a non-trivial divisor g of h, which is good enough. If p is large, g^d = h is likely. */ fmpz_mod_berlekamp_massey_start_over(bma, ctx); fmpz_mod_poly_one(t, ctx); fmpz_mod_berlekamp_massey_add_point_ui(bma, 1, ctx); for (i = 1; i < 2*r; i++) { fmpz_mod_poly_mulmod_preinv(tq, t, S->a, S->f, finv, ctx); fmpz_mod_poly_swap(t, tq, ctx); FLINT_ASSERT(t->length > 0); fmpz_mod_berlekamp_massey_add_point(bma, t->coeffs + 0, ctx); } /* something went wrong if V does not kill the whole sequence */ fmpz_mod_berlekamp_massey_reduce(bma, ctx); FLINT_ASSERT(bma->R1->length < bma->V1->length); fmpz_mod_poly_make_monic(S->g, bma->V1, ctx); /* S->g should be squarefree and factor into linears */ FLINT_ASSERT(1 <= fmpz_mod_poly_degree(S->g, ctx)); FLINT_ASSERT(fmpz_mod_poly_degree(S->g, ctx) <= r); #if FLINT_WANT_ASSERT fmpz_mod_poly_gen(t, ctx); fmpz_mod_poly_powmod_fmpz_binexp(tq, t, p, S->g, ctx); fmpz_mod_poly_sub(tq, tq, t, ctx); fmpz_mod_poly_gcd(t, tq, S->g, ctx); FLINT_ASSERT(fmpz_mod_poly_equal(t, S->g, ctx)); #endif /* split S->g into linears and split S->f along the way */ k = 1; while (k > 0) { k--; FLINT_ASSERT(k + 1 < FLINT_BITS); FLINT_ASSERT(fmpz_mod_poly_degree(S[k].g, ctx) >= 1); if (fmpz_mod_poly_degree(S[k].g, ctx) < 2) { if (fmpz_mod_poly_degree(S[k].f, ctx) == d) { fmpz_mod_poly_factor_fit_length(res, res->num + 1, ctx); res->exp[res->num] = 1; fmpz_mod_poly_set(res->poly + res->num, S[k].f, ctx); res->num++; } else { FLINT_ASSERT(fmpz_mod_poly_degree(S[k].f, ctx) > d); /* S[k].g should be a monic linear */ FLINT_ASSERT(S[k].g->length == 2); FLINT_ASSERT(fmpz_is_one(S[k].g->coeffs + 1)); fmpz_mod_poly_add_fmpz(tr, S[k].a, S[k].g->coeffs + 0, ctx); fmpz_mod_poly_gcd(t, tr, S[k].f, ctx); _add_split(res, &Q, &Qlen, &Qalloc, S[k].f, t, d, S[k].xp, ctx, tr); } continue; } if (fmpz_mod_poly_is_zero(finv, ctx)) { fmpz_mod_poly_reverse(finv, S[k].f, S[k].f->length, ctx); fmpz_mod_poly_inv_series(finv, finv, S[k].f->length, ctx); } fmpz_mod_poly_swap(t, S[k].g, ctx); _fmpz_mod_poly_split_rabin(S[k+0].g, S[k+1].g, t, halfp, tq, tr, state, ctx); fmpz_mod_poly_compose_mod_brent_kung_preinv(tr, S[k+1].g, S[k].a, S[k].f, finv, ctx); fmpz_mod_poly_gcd(t, tr, S[k].f, ctx); fmpz_mod_poly_divrem(tq, tr, S[k].f, t, ctx); fmpz_mod_poly_swap(S[k+0].f, tq, ctx); fmpz_mod_poly_swap(S[k+1].f, t, ctx); fmpz_mod_poly_zero(finv, ctx); /* finv no longer inv(S[0].f) */ fmpz_mod_poly_divrem(tq, S[k+1].a, S[k].a, S[k+1].f, ctx); fmpz_mod_poly_divrem(tq, tr, S[k].a, S[k+0].f, ctx); fmpz_mod_poly_swap(S[k+0].a, tr, ctx); fmpz_mod_poly_divrem(tq, S[k+1].xp, S[k+0].xp, S[k+1].f, ctx); fmpz_mod_poly_divrem(tq, tr, S[k+0].xp, S[k+0].f, ctx); fmpz_mod_poly_swap(S[k+0].xp, tr, ctx); k += 2; } goto next_queued; cleanup: fmpz_mod_berlekamp_massey_clear(bma, ctx); for (i = 0; i < Qalloc; i++) { fmpz_mod_poly_clear(Q[i].f, ctx); fmpz_mod_poly_clear(Q[i].xp, ctx); } flint_free(Q); for (i = 0; i <= FLINT_BITS; i++) { fmpz_mod_poly_clear(S[i].f, ctx); fmpz_mod_poly_clear(S[i].xp, ctx); fmpz_mod_poly_clear(S[i].a, ctx); fmpz_mod_poly_clear(S[i].g, ctx); } fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(tq, ctx); fmpz_mod_poly_clear(tr, ctx); fmpz_mod_poly_clear(finv, ctx); flint_randclear(state); fmpz_clear(halfp); return; } void fmpz_mod_poly_factor_equal_deg_with_frob( fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, slong d, const fmpz_mod_poly_t frob, const fmpz_mod_ctx_t ctx) { slong r = fmpz_mod_poly_degree(f, ctx)/d; FLINT_ASSERT(fmpz_mod_poly_degree(f, ctx) == r*d); if (r == 1) { factors->num = 0; fmpz_mod_poly_factor_insert(factors, f, 1, ctx); } else if (d == 1) { fmpz_mod_poly_roots(factors, f, 0, ctx); } else { _fmpz_mod_poly_factor_equal_deg_via_trace(factors, f, d, frob, ctx); } } void fmpz_mod_poly_factor_equal_deg( fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, slong d, const fmpz_mod_ctx_t ctx) { slong r = fmpz_mod_poly_degree(f, ctx)/d; FLINT_ASSERT(fmpz_mod_poly_degree(f, ctx) == r*d); if (r == 1) { factors->num = 0; fmpz_mod_poly_factor_insert(factors, f, 1, ctx); } else if (d == 1) { fmpz_mod_poly_roots(factors, f, 0, ctx); } else { fmpz_mod_poly_t xp, t; fmpz_mod_poly_init(xp, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_reverse(t, f, f->length, ctx); fmpz_mod_poly_inv_series(t, t, f->length, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(xp, fmpz_mod_ctx_modulus(ctx), f, t, ctx); fmpz_mod_poly_clear(t, ctx); _fmpz_mod_poly_factor_equal_deg_via_trace(factors, f, d, xp, ctx); fmpz_mod_poly_clear(xp, ctx); } } flint-3.1.3/src/fmpz_mod_poly_factor/factor_equal_deg_prob.c000066400000000000000000000052221461254215100243110ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" int fmpz_mod_poly_factor_equal_deg_prob(fmpz_mod_poly_t factor, flint_rand_t state, const fmpz_mod_poly_t pol, slong d, const fmpz_mod_ctx_t ctx) { const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_mod_poly_t a, b, c, polinv; fmpz_t exp; int res = 1; slong i; if (pol->length <= 1) { flint_throw(FLINT_ERROR, "Exception (fmpz_mod_poly_factor_equal_deg_prob): Input polynomial is linear.\n"); } fmpz_mod_poly_init(a, ctx); do { fmpz_mod_poly_randtest(a, state, pol->length - 1, ctx); } while (a->length <= 1); fmpz_mod_poly_gcd(factor, a, pol, ctx); if (factor->length != 1) { fmpz_mod_poly_clear(a, ctx); return 1; } fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(polinv, ctx); fmpz_mod_poly_reverse(polinv, pol, pol->length, ctx); fmpz_mod_poly_inv_series(polinv, polinv, polinv->length, ctx); fmpz_init(exp); if (fmpz_cmp_ui(p, 2) > 0) { /* compute a^{(p^d-1)/2} rem pol */ fmpz_pow_ui(exp, p, d); fmpz_sub_ui(exp, exp, 1); fmpz_fdiv_q_2exp(exp, exp, 1); fmpz_mod_poly_powmod_fmpz_binexp_preinv(b, a, exp, pol, polinv, ctx); } else { /* compute b = (a^{2^{d-1}}+a^{2^{d-2}}+...+a^4+a^2+a) rem pol */ fmpz_mod_poly_rem(b, a, pol, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_set(c, b, ctx); for (i = 1; i < d; i++) { /* c = a^{2^i} = (a^{2^{i-1}})^2 */ fmpz_mod_poly_powmod_ui_binexp_preinv(c, c, 2, pol, polinv, ctx); fmpz_mod_poly_add(b, b, c, ctx); } fmpz_mod_poly_rem(b, b, pol, ctx); fmpz_mod_poly_clear(c, ctx); } fmpz_clear(exp); fmpz_mod_poly_sub_si(b, b, 1, ctx); fmpz_mod_poly_gcd(factor, b, pol, ctx); if ((factor->length <= 1) || (factor->length == pol->length)) res = 0; fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(polinv, ctx); return res; } flint-3.1.3/src/fmpz_mod_poly_factor/factor_kaltofen_shoup.c000066400000000000000000000053441461254215100243670ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_kaltofen_shoup(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { slong i, j, k; slong num_threads = flint_get_num_threads(); fmpz_mod_poly_t t, DDxp, EDxp; fmpz_mod_poly_factor_t SF, DD, ED; res->num = 0; fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_make_monic(t, poly, ctx); if (poly->length <= 2) { fmpz_mod_poly_factor_insert(res, t, 1, ctx); fmpz_mod_poly_clear(t, ctx); return; } fmpz_mod_poly_init(DDxp, ctx); fmpz_mod_poly_init(EDxp, ctx); fmpz_mod_poly_factor_init(SF, ctx); fmpz_mod_poly_factor_init(DD, ctx); fmpz_mod_poly_factor_init(ED, ctx); fmpz_mod_poly_factor_squarefree(SF, t, ctx); for (i = 0; i < SF->num; i++) { fmpz_mod_poly_struct * f = SF->poly + i; fmpz_mod_poly_reverse(t, f, f->length, ctx); fmpz_mod_poly_inv_series(t, t, f->length, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(DDxp, fmpz_mod_ctx_modulus(ctx), f, t, ctx); /* TODO Since there is a fair amount of code duplicated in the threaded version, the two functions should be combined into one. */ if (num_threads > 1 && f->length > 256*num_threads) fmpz_mod_poly_factor_distinct_deg_threaded_with_frob(DD, f, t, DDxp, ctx); else fmpz_mod_poly_factor_distinct_deg_with_frob(DD, f, t, DDxp, ctx); for (j = 0; j < DD->num; j++) { fmpz_mod_poly_divrem(t, EDxp, DDxp, DD->poly + j, ctx); fmpz_mod_poly_factor_equal_deg_with_frob(ED, DD->poly + j, DD->exp[j], EDxp, ctx); fmpz_mod_poly_factor_fit_length(res, res->num + ED->num, ctx); for (k = 0; k < ED->num; k++) { fmpz_mod_poly_swap(res->poly + res->num, ED->poly + k, ctx); res->exp[res->num] = SF->exp[i]; res->num++; } } } fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(DDxp, ctx); fmpz_mod_poly_clear(EDxp, ctx); fmpz_mod_poly_factor_clear(SF, ctx); fmpz_mod_poly_factor_clear(DD, ctx); fmpz_mod_poly_factor_clear(ED, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/factor_squarefree.c000066400000000000000000000105461461254215100235100ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_squarefree(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t f_d, g, g_1, r; fmpz_t x; slong deg, i, p_ui; res->num = 0; if (f->length <= 1) return; if (f->length == 2) { fmpz_mod_poly_factor_insert(res, f, 1, ctx); fmpz_mod_poly_make_monic(res->poly + (res->num - 1), res->poly + (res->num - 1), ctx); return; } p_ui = fmpz_get_ui(fmpz_mod_ctx_modulus(ctx)); /* TODO what? */ deg = fmpz_mod_poly_degree(f, ctx); /* Step 1, look at f', if it is zero then we are done since f = h(x)^p for some particular h(x), clearly f(x) = sum a_k x^kp, k <= deg(f) */ fmpz_init(x); fmpz_mod_poly_init(g_1, ctx); fmpz_mod_poly_init(f_d, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_derivative(f_d, f, ctx); /* Case 1 */ if (fmpz_mod_poly_is_zero(f_d, ctx)) { fmpz_mod_poly_factor_t new_res; fmpz_mod_poly_t h; fmpz_mod_poly_init(h, ctx); for (i = 0; i <= deg / p_ui; i++) /* this will be an integer since f'=0 */ { fmpz_mod_poly_get_coeff_fmpz(x, f, i * p_ui, ctx); fmpz_mod_poly_set_coeff_fmpz(h, i, x, ctx); } /* Now run squarefree on h, and return it to the pth power */ fmpz_mod_poly_factor_init(new_res, ctx); fmpz_mod_poly_factor_squarefree(new_res, h, ctx); fmpz_mod_poly_factor_pow(new_res, p_ui, ctx); fmpz_mod_poly_factor_concat(res, new_res, ctx); fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_factor_clear(new_res, ctx); } else { fmpz_mod_poly_t h, z; fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_gcd(g, f, f_d, ctx); fmpz_mod_poly_divrem(g_1, r, f, g, ctx); i = 1; fmpz_mod_poly_init(h, ctx); fmpz_mod_poly_init(z, ctx); /* Case 2 */ while (g_1->length > 1) { fmpz_mod_poly_gcd(h, g_1, g, ctx); fmpz_mod_poly_divrem(z, r, g_1, h, ctx); /* out <- out.z */ if (z->length > 1) { fmpz_mod_poly_factor_insert(res, z, 1, ctx); fmpz_mod_poly_make_monic(res->poly + (res->num - 1), res->poly + (res->num - 1), ctx); if (res->num) res->exp[res->num - 1] *= i; } i++; fmpz_mod_poly_set(g_1, h, ctx); fmpz_mod_poly_divrem(g, r, g, h, ctx); } fmpz_mod_poly_clear(h, ctx); fmpz_mod_poly_clear(z, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_make_monic(g, g, ctx); if (g->length > 1) { /* so now we multiply res with squarefree(g^1/p) ^ p */ fmpz_mod_poly_t g_p; /* g^(1/p) */ fmpz_mod_poly_factor_t new_res_2; fmpz_mod_poly_init(g_p, ctx); for (i = 0; i <= fmpz_mod_poly_degree(g, ctx) / p_ui; i++) { fmpz_mod_poly_get_coeff_fmpz(x, g, i * p_ui, ctx); fmpz_mod_poly_set_coeff_fmpz(g_p, i, x, ctx); } fmpz_mod_poly_factor_init(new_res_2, ctx); /* squarefree(g^(1/p)) */ fmpz_mod_poly_factor_squarefree(new_res_2, g_p, ctx); fmpz_mod_poly_factor_pow(new_res_2, p_ui, ctx); fmpz_mod_poly_factor_concat(res, new_res_2, ctx); fmpz_mod_poly_clear(g_p, ctx); fmpz_mod_poly_factor_clear(new_res_2, ctx); } } fmpz_clear(x); fmpz_mod_poly_clear(g_1, ctx); fmpz_mod_poly_clear(f_d, ctx); fmpz_mod_poly_clear(g, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/fit_length.c000066400000000000000000000015521461254215100221300ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_fit_length(fmpz_mod_poly_factor_t fac, slong len, const fmpz_mod_ctx_t ctx) { if (len > fac->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * fac->alloc) len = 2 * fac->alloc; fmpz_mod_poly_factor_realloc(fac, len, ctx); } } flint-3.1.3/src/fmpz_mod_poly_factor/get_poly.c000066400000000000000000000012031461254215100216200ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_get_poly(fmpz_mod_poly_t a, const fmpz_mod_poly_factor_t b, slong i, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_set(a, b->poly + i, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/init.c000066400000000000000000000014251461254215100207470ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" void fmpz_mod_poly_factor_init(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) { fac->alloc = 0; fac->num = 0; fac->poly = NULL; fac->exp = NULL; } flint-3.1.3/src/fmpz_mod_poly_factor/inlines.c000066400000000000000000000012421461254215100214420ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_POLY_FACTOR_INLINES_C #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_get_fmpz_mod_poly(fmpz_mod_poly_t z, fmpz_mod_poly_factor_t fac, slong i, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_set(z, fac->poly + i, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/insert.c000066400000000000000000000030011461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_insert(fmpz_mod_poly_factor_t fac, const fmpz_mod_poly_t poly, slong exp, const fmpz_mod_ctx_t ctx) { slong i; if (poly->length <= 1) return; for (i = 0; i < fac->num; i++) { if (fmpz_mod_poly_equal(poly, fac->poly + i, ctx)) { fac->exp[i] += exp; return; } } if (fac->alloc <= fac->num) { slong new_size = FLINT_MAX(fac->num + 1, 2*fac->alloc); fac->poly = flint_realloc(fac->poly, sizeof(fmpz_mod_poly_struct) * new_size); fac->exp = flint_realloc(fac->exp, sizeof(slong) * new_size); for (i = fac->alloc; i < new_size; i++) fmpz_mod_poly_init(fac->poly + i, ctx); fac->alloc = new_size; } fmpz_mod_poly_set(fac->poly + fac->num, poly, ctx); fac->exp[fac->num] = exp; fac->num++; } flint-3.1.3/src/fmpz_mod_poly_factor/is_irreducible.c000066400000000000000000000014751461254215100227750ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" int fmpz_mod_poly_is_irreducible(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { if (fmpz_mod_poly_length(f, ctx) > 2) { return fmpz_mod_poly_is_irreducible_ddf(f, ctx); } return 1; } flint-3.1.3/src/fmpz_mod_poly_factor/is_irreducible_ddf.c000066400000000000000000000114671461254215100236140ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013, 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #ifdef __GNUC__ # define ceil __builtin_ceil # define log __builtin_log # define pow __builtin_pow #else # include #endif int fmpz_mod_poly_is_irreducible_ddf(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { const fmpz * p = fmpz_mod_ctx_modulus(ctx); fmpz_mod_poly_t f, v, vinv, tmp; fmpz_mod_poly_t *h, *H, *I; fmpz_mat_t HH; slong i, j, l, m, n, d; double beta; int result = 1; n = fmpz_mod_poly_degree(poly, ctx); if (n < 2) return 1; if (!fmpz_mod_poly_is_squarefree(poly, ctx)) return 0; beta = 0.5 * (1. - (log(2) / log(n))); l = ceil(pow(n, beta)); m = ceil(0.5 * n / l); /* initialization */ fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(v, ctx); fmpz_mod_poly_init(vinv, ctx); fmpz_mod_poly_init(tmp, ctx); h = flint_malloc((2 * m + l + 1) * sizeof(fmpz_mod_poly_struct)); H = h + (l + 1); I = H + m; for (i = 0; i < 2*m + l + 1; i++) fmpz_mod_poly_init(h[i], ctx); fmpz_mod_poly_make_monic(v, poly, ctx); fmpz_mod_poly_reverse(vinv, v, v->length, ctx); fmpz_mod_poly_inv_series(vinv, vinv, v->length, ctx); /* compute baby steps: h[i]=x^{p^i}mod v */ fmpz_mod_poly_set_coeff_ui(h[0], 1, 1, ctx); fmpz_mod_poly_powmod_x_fmpz_preinv(h[1], p, v, vinv, ctx); if (fmpz_sizeinbase(p, 2) > ((n_sqrt(v->length - 1) + 1) * 3) / 4) { for (i= 1; i < FLINT_BIT_COUNT (l); i++) fmpz_mod_poly_compose_mod_brent_kung_vec_preinv (*(h + 1 + (1 << (i - 1))), *(h + 1), (1 << (i - 1)), (1 << (i - 1)), *(h + (1 << (i - 1))), v, vinv, ctx); fmpz_mod_poly_compose_mod_brent_kung_vec_preinv (*(h + 1 + (1 << (i - 1))), *(h + 1), (1 << (i - 1)), l - (1 << (i - 1)), *(h + (1 << (i - 1))), v, vinv, ctx); } else { for (i = 2; i < l + 1; i++) { fmpz_mod_poly_init(h[i], ctx); fmpz_mod_poly_powmod_fmpz_binexp_preinv(h[i], h[i - 1], p, v, vinv, ctx); } } /* compute coarse distinct-degree factorisation */ fmpz_mod_poly_set(H[0], h[l], ctx); fmpz_mat_init(HH, n_sqrt(v->length - 1) + 1, v->length - 1); fmpz_mod_poly_precompute_matrix(HH, H[0], v, vinv, ctx); d = 1; for (j = 0; j < m; j++) { /* compute giant steps: H[i]=x^{p^(li)}mod v */ if (j > 0) fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(H[j], H[j - 1], HH, v, vinv, ctx); /* compute interval polynomials */ fmpz_mod_poly_set_coeff_ui(I[j], 0, 1, ctx); for (i = l - 1; (i >= 0) && (2*d <= v->length - 1); i--, d++) { fmpz_mod_poly_rem(tmp, h[i], v, ctx); fmpz_mod_poly_sub(tmp, H[j], tmp, ctx); fmpz_mod_poly_mulmod_preinv(I[j], tmp, I[j], v, vinv, ctx); } /* compute F_j=f^{[j*l+1]} * ... * f^{[j*l+l]} */ /* F_j is stored on the place of I_j */ fmpz_mod_poly_gcd(I[j], v, I[j], ctx); if (I[j]->length > 1) { result = 0; break; } } fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(v, ctx); fmpz_mod_poly_clear(vinv, ctx); fmpz_mod_poly_clear(tmp, ctx); fmpz_mat_clear(HH); for (i = 0; i < l + 1; i++) fmpz_mod_poly_clear(h[i], ctx); for (i = 0; i < m; i++) { fmpz_mod_poly_clear(H[i], ctx); fmpz_mod_poly_clear(I[i], ctx); } flint_free(h); return result; } flint-3.1.3/src/fmpz_mod_poly_factor/is_irreducible_rabin.c000066400000000000000000000061221461254215100241420ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_powpowmod(fmpz_mod_poly_t res, const fmpz_mod_poly_t pol, const fmpz_t exp, ulong exp2, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t pow; ulong i; fmpz_mod_poly_init(pow, ctx); fmpz_mod_poly_powmod_fmpz_binexp(pow, pol, exp, f, ctx); fmpz_mod_poly_set(res, pow, ctx); if (!fmpz_mod_poly_equal(pow, pol, ctx)) for (i = 1; i < exp2; i++) fmpz_mod_poly_powmod_fmpz_binexp(res, res, exp, f, ctx); fmpz_mod_poly_clear(pow, ctx); } int fmpz_mod_poly_is_irreducible_rabin(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { int res = 1; if (fmpz_mod_poly_length(f, ctx) > 2) { const slong n = fmpz_mod_poly_degree(f, ctx); fmpz_mod_poly_t a, x, x_p, finv; fmpz_mod_poly_frobenius_powers_2exp_t pow; fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(x, ctx); fmpz_mod_poly_init(x_p, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_set_coeff_ui(x, 1, 1, ctx); /* Compute x^q mod f */ fmpz_mod_poly_reverse(finv, f, f->length, ctx); fmpz_mod_poly_inv_series(finv, finv, f->length, ctx); fmpz_mod_poly_frobenius_powers_2exp_precomp(pow, f, finv, n, ctx); fmpz_mod_poly_frobenius_power(x_p, pow, f, n, ctx); if (!fmpz_mod_poly_is_zero(x_p, ctx)) fmpz_mod_poly_make_monic(x_p, x_p, ctx); /* Now do the irreducibility test */ if (!fmpz_mod_poly_equal(x_p, x, ctx)) { res = 0; } else { n_factor_t factors; slong i; n_factor_init(&factors); n_factor(&factors, n, 1); for (i = 0; i < factors.num; i++) { fmpz_mod_poly_frobenius_power(a, pow, f, n / factors.p[i], ctx); fmpz_mod_poly_sub(a, a, x, ctx); if (!fmpz_mod_poly_is_zero(a, ctx)) fmpz_mod_poly_make_monic(a, a, ctx); fmpz_mod_poly_gcd(a, a, f, ctx); if (a->length != 1) res = 0; } } fmpz_mod_poly_frobenius_powers_2exp_clear(pow, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(x, ctx); fmpz_mod_poly_clear(x_p, ctx); } return res; } flint-3.1.3/src/fmpz_mod_poly_factor/is_irreducible_rabin_f.c000066400000000000000000000055331461254215100244540ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" int fmpz_mod_poly_is_irreducible_rabin_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { int res = 1; if (fmpz_mod_poly_length(f, ctx) > 2) { const slong n = fmpz_mod_poly_degree(f, ctx); fmpz_mod_poly_t a, x, x_p, finv; fmpz_mod_poly_frobenius_powers_2exp_t pow; fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(x, ctx); fmpz_mod_poly_init(x_p, ctx); fmpz_mod_poly_init(finv, ctx); fmpz_mod_poly_set_coeff_ui(x, 1, 1, ctx); /* Compute x^q mod f */ fmpz_mod_poly_reverse(finv, f, f->length, ctx); fmpz_mod_poly_inv_series_f(fac, finv, finv, f->length, ctx); if (!fmpz_is_one(fac)) goto cleanup; fmpz_mod_poly_frobenius_powers_2exp_precomp(pow, f, finv, n, ctx); fmpz_mod_poly_frobenius_power(x_p, pow, f, n, ctx); if (!fmpz_mod_poly_is_zero(x_p, ctx)) { fmpz_mod_poly_make_monic_f(fac, x_p, x_p, ctx); if (!fmpz_is_one(fac)) goto cleanup; } /* Now do the irreducibility test */ if (!fmpz_mod_poly_equal(x_p, x, ctx)) { res = 0; } else { n_factor_t factors; slong i; n_factor_init(&factors); n_factor(&factors, n, 1); for (i = 0; i < factors.num; i++) { fmpz_mod_poly_frobenius_power(a, pow, f, n / factors.p[i], ctx); fmpz_mod_poly_sub(a, a, x, ctx); if (!fmpz_mod_poly_is_zero(a, ctx)) { fmpz_mod_poly_make_monic_f(fac, a, a, ctx); if (!fmpz_is_one(fac)) goto cleanup; } fmpz_mod_poly_gcd(a, a, f, ctx); if (a->length != 1) res = 0; } } cleanup: fmpz_mod_poly_frobenius_powers_2exp_clear(pow, ctx); fmpz_mod_poly_clear(finv, ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(x, ctx); fmpz_mod_poly_clear(x_p, ctx); } return res; } flint-3.1.3/src/fmpz_mod_poly_factor/is_squarefree.c000066400000000000000000000024031461254215100226360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" int _fmpz_mod_poly_is_squarefree(const fmpz * f, slong len, const fmpz_mod_ctx_t ctx) { fmpz * fd, * g; slong dlen; int res; if (len <= 2) return len != 0; fd = _fmpz_vec_init(2 * (len - 1)); g = fd + len - 1; _fmpz_mod_poly_derivative(fd, f, len, ctx); dlen = len - 1; FMPZ_VEC_NORM(fd, dlen); if (dlen) res = (_fmpz_mod_poly_gcd(g, f, len, fd, dlen, ctx) == 1); else res = 0; /* gcd(f, 0) = f, and len(f) > 2 */ _fmpz_vec_clear(fd, 2 * (len - 1)); return res; } int fmpz_mod_poly_is_squarefree(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { return _fmpz_mod_poly_is_squarefree(f->coeffs, f->length, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/is_squarefree_f.c000066400000000000000000000027711461254215100231530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" int _fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz * f, slong len, const fmpz_mod_ctx_t ctx) { fmpz * fd, * g; fmpz_t invd; slong dlen; int res = 0; if (len <= 2) return len != 0; fd = _fmpz_vec_init(2 * (len - 1)); g = fd + len - 1; _fmpz_mod_poly_derivative(fd, f, len, ctx); dlen = len - 1; FMPZ_VEC_NORM(fd, dlen); if (dlen) { fmpz_init(invd); fmpz_gcdinv(fac, invd, fd + dlen - 1, fmpz_mod_ctx_modulus(ctx)); if (fmpz_is_one(fac)) res = (_fmpz_mod_poly_gcd_euclidean_f(fac, g, f, len, fd, dlen, ctx) == 1); fmpz_clear(invd); } /* else gcd(f, 0) = f, and len(f) > 2 */ _fmpz_vec_clear(fd, 2 * (len - 1)); return res; } int fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { return _fmpz_mod_poly_is_squarefree_f(fac, f->coeffs, f->length, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/pow.c000066400000000000000000000014621461254215100206120ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_pow(fmpz_mod_poly_factor_t fac, slong exp, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < fac->num; i++) fac->exp[i] *= exp; } flint-3.1.3/src/fmpz_mod_poly_factor/print.c000066400000000000000000000016321461254215100211400ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_print(const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < fac->num; i++) { fmpz_mod_poly_print(fac->poly + i, ctx); flint_printf(" ^ %wd\n", fac->exp[i]); } } flint-3.1.3/src/fmpz_mod_poly_factor/print_pretty.c000066400000000000000000000013761461254215100225540ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_print_pretty(const fmpz_mod_poly_factor_t fac, const char *var, const fmpz_mod_ctx_t ctx) { slong i; for (i = 0; i < fac->num; i++) { fmpz_mod_poly_print_pretty(fac->poly + i, var, ctx); flint_printf(" ^ %wd\n", fac->exp[i]); } } flint-3.1.3/src/fmpz_mod_poly_factor/profile/000077500000000000000000000000001461254215100212765ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_poly_factor/profile/p-factor.c000066400000000000000000000261601461254215100231620ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #define NP 20 /* number of moduli */ #define ND 8 /* number of degrees */ /* Benchmarking code for factorisation in fmpz_mod_poly. Test how the relation between n (degree of polynomial) and p affects working time for Cantor-Zassenhaus, Berlekamp and Kaltofen-Shoup algorithms. p and n are chosen independently. */ int main(void) { fmpz_mod_poly_t f, g; fmpz_mod_poly_factor_t res; fmpz_t p; fmpz_mod_ctx_t ctx; mpz_t pz, curr; int i, j, k, n, num; double t, T1, T2, T3; const slong degs[] = {8, 16, 32, 64, 128, 256, 512, 1024}; const int iter_count[] = {10000, 5000, 1000, 500, 300, 100, 50, 20}; FLINT_TEST_INIT(state); mpz_init(pz); mpz_init(curr); fmpz_init(p); fmpz_mod_ctx_init_ui(ctx, 2); flint_printf("Random polynomials\n"); flint_mpz_set_ui(pz, 2); flint_mpz_set_ui(curr, 10); for (i = 0; i < NP; i++) { fmpz_set_mpz(p, pz); fmpz_mod_ctx_set_modulus(ctx, p); flint_printf("========== p: "); fmpz_print(p); flint_printf(" ==========\n"); fflush(stdout); for (j = 0; j < ND; j++) { n = degs[j]; flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n, ctx); t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_cantor_zassenhaus(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_berlekamp(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_kaltofen_shoup(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; fmpz_mod_poly_clear(f, ctx); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } mpz_nextprime(pz, curr); flint_mpz_mul_ui(curr, curr, 10); } /* This code checks whether fmpz_mod_poly_factor made a correct choice between CZ and KS */ flint_printf("Check choice correctness\n"); flint_mpz_set_ui(pz, 2); flint_mpz_set_ui(curr, 10); for (i = 0; i < NP; i++) { fmpz_set_mpz(p, pz); fmpz_mod_ctx_set_modulus(ctx, p); flint_printf("========== p: "); fmpz_print(p); flint_printf(" ==========\n"); fflush(stdout); for (j = 0; j < ND; j++) { n = degs[j]; flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest_not_zero(f, state, n, ctx); t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_cantor_zassenhaus(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_kaltofen_shoup(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; fmpz_mod_poly_clear(f, ctx); } flint_printf("CZ: %.2lf F: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } mpz_nextprime(pz, curr); flint_mpz_mul_ui(curr, curr, 10); } flint_printf("Irreducible polynomials\n"); flint_mpz_set_ui(pz, 2); flint_mpz_set_ui(curr, 10); for (i = 0; i < NP; i++) { fmpz_set_mpz(p, pz); fmpz_mod_ctx_set_modulus(ctx, p); flint_printf("========== p: "); fmpz_print(p); flint_printf(" ==========\n"); fflush(stdout); for (j = 0; j < ND; j++) { n = degs[j]; flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_randtest_irreducible(f, state, n, ctx); t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_cantor_zassenhaus(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_berlekamp(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_kaltofen_shoup(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; fmpz_mod_poly_clear(f, ctx); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } mpz_nextprime(pz, curr); flint_mpz_mul_ui(curr, curr, 10); } flint_printf("Product of two irreducible polynomials\n"); flint_mpz_set_ui(pz, 2); flint_mpz_set_ui(curr, 10); for (i = 0; i < NP; i++) { fmpz_set_mpz(p, pz); fmpz_mod_ctx_set_modulus(ctx, p); flint_printf("========== p: "); fmpz_print(p); flint_printf(" ==========\n"); fflush(stdout); for (j = 0; j < ND; j++) { n = (degs[j] >> 1); flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_randtest_irreducible(f, state, n, ctx); fmpz_mod_poly_randtest_irreducible(g, state, n, ctx); fmpz_mod_poly_mul(f, f, g, ctx); t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_cantor_zassenhaus(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_berlekamp(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_kaltofen_shoup(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } mpz_nextprime(pz, curr); flint_mpz_mul_ui(curr, curr, 10); } flint_printf("Product of 8 small irreducible polynomials\n"); flint_mpz_set_ui(pz, 2); flint_mpz_set_ui(curr, 10); for (i = 0; i < NP; i++) { fmpz_set_mpz(p, pz); fmpz_mod_ctx_set_modulus(ctx, p); flint_printf("========== p: "); fmpz_print(p); flint_printf(" ==========\n"); fflush(stdout); for (j = 1; j < ND; j++) { n = (degs[j] >> 3); flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_randtest_irreducible(f, state, n, ctx); for (num = 1; num < 8; num++) { fmpz_mod_poly_randtest_irreducible(g, state, n, ctx); fmpz_mod_poly_mul(f, f, g, ctx); } t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_cantor_zassenhaus(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_berlekamp(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_kaltofen_shoup(res, f, ctx); fmpz_mod_poly_factor_clear(res, ctx); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; fmpz_mod_poly_clear(f, ctx); fmpz_mod_poly_clear(g, ctx); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } mpz_nextprime(pz, curr); flint_mpz_mul_ui(curr, curr, 10); } mpz_clear(pz); mpz_clear(curr); fmpz_clear(p); fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mod_poly_factor/profile/p-factor_equal_deg.c000066400000000000000000000056721461254215100251750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #include "profiler.h" int main(void) { slong i, j, d, r; flint_rand_t state; fmpz_t p, t; fmpz_mod_ctx_t ctx; fmpz_mod_poly_t a, b, c; fmpz_mod_poly_factor_t f; timeit_t timer; flint_randinit(state); fmpz_init_set_ui(p, 1); fmpz_init(t); fmpz_mod_ctx_init(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_factor_init(f, ctx); while (fmpz_bits(p) < 100) { if (fmpz_cmp_ui(p, 10) > 0) { fmpz_sqrt(t, p); fmpz_sqrt(t, t); fmpz_sqrt(t, t); fmpz_add_ui(t, t, 1); fmpz_mul(p, p, t); } fmpz_nextprime(p, p, 0); fmpz_mod_ctx_set_modulus(ctx, p); flint_printf("++++++++++ p = "); fmpz_print(p); flint_printf(" ++++++++++\n"); for (d = 2; d <= 5; d++) { flint_printf("d = %wd: ", d); fmpz_mod_poly_randtest_monic_irreducible(a, state, d + 1, ctx); for (r = 1; r <= 10; r++) { slong reps = a->length + 1; reps = 1000000/reps/reps/fmpz_bits(p); fmpz_mod_poly_randtest_monic_irreducible(b, state, d + 1, ctx); fmpz_mod_poly_mul(a, a, b, ctx); timeit_start(timer); for (i = 0; i <= reps; i++) fmpz_mod_poly_factor(f, a, ctx); timeit_stop(timer); flint_printf(" %06wd", timer->wall*100/reps); fflush(stdout); fmpz_mod_poly_one(c, ctx); for (i = 0; i < f->num; i++) { if (fmpz_mod_poly_degree(f->poly + i, ctx) != d) { flint_printf("!!! oops !!!"); flint_abort(); } for (j = 0; j < f->exp[i]; j++) fmpz_mod_poly_mul(c, c, f->poly + i, ctx); } if (!fmpz_mod_poly_equal(c, a, ctx)) { flint_printf("!!! oops !!!"); flint_abort(); } } flint_printf("\n"); } } fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_factor_clear(f, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(p); fmpz_clear(t); flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_mod_poly_factor/realloc.c000066400000000000000000000040421461254215100214230ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_realloc(fmpz_mod_poly_factor_t fac, slong alloc, const fmpz_mod_ctx_t ctx) { if (alloc == 0) /* Clear up, reinitialise */ { fmpz_mod_poly_factor_clear(fac, ctx); fmpz_mod_poly_factor_init(fac, ctx); } else if (fac->alloc) /* Realloc */ { if (fac->alloc > alloc) { slong i; for (i = alloc; i < fac->num; i++) fmpz_mod_poly_clear(fac->poly + i, ctx); fac->poly = flint_realloc(fac->poly, alloc * sizeof(fmpz_mod_poly_struct)); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); fac->alloc = alloc; } else if (fac->alloc < alloc) { slong i; fac->poly = flint_realloc(fac->poly, alloc * sizeof(fmpz_mod_poly_struct)); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); for (i = fac->alloc; i < alloc; i++) { fmpz_mod_poly_init(fac->poly + i, ctx); fac->exp[i] = WORD(0); } fac->alloc = alloc; } } else /* Nothing allocated already so do it now */ { slong i; fac->poly = flint_malloc(alloc * sizeof(fmpz_mod_poly_struct)); fac->exp = flint_calloc(alloc, sizeof(slong)); for (i = 0; i < alloc; i++) fmpz_mod_poly_init(fac->poly + i, ctx); fac->num = 0; fac->alloc = alloc; } } flint-3.1.3/src/fmpz_mod_poly_factor/roots.c000066400000000000000000000151711461254215100211550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" /* Helper function for finding roots. The roots of a monic f are written with exponent given in mult to r. Uses Rabin's Las Vegas algorithm via gcd computations with (x + delta)^halfp - 1. */ static void _fmpz_mod_poly_push_roots( fmpz_mod_poly_factor_t r, fmpz_mod_poly_t f, /* clobbered */ slong mult, /* expoenent to write on the roots */ const fmpz_t halfp, /* (f->p - 1)/2 */ fmpz_mod_poly_t t, /* temp */ fmpz_mod_poly_t t2, /* more temp */ fmpz_mod_poly_struct * stack, /* temp of size FLINT_BITS */ flint_rand_t randstate, const fmpz_mod_ctx_t ctx) { slong i, sp; fmpz_mod_poly_struct * a, * b; const fmpz * p = fmpz_mod_ctx_modulus(ctx); FLINT_ASSERT(fmpz_mod_poly_degree(f, ctx) >= 1); FLINT_ASSERT(fmpz_is_one(f->coeffs + f->length - 1)); FLINT_ASSERT(fmpz_is_probabprime(p)); /* handle at least p = 2 */ if (fmpz_cmp_ui(p, 10) < 0) { fmpz_t x, e; fmpz_init(x); fmpz_init(e); for (fmpz_zero(x); fmpz_cmp(x, p) < 0; fmpz_add_ui(x, x, 1)) { fmpz_mod_poly_evaluate_fmpz(e, f, x, ctx); if (!fmpz_is_zero(e)) continue; fmpz_mod_poly_factor_fit_length(r, r->num + 1, ctx); fmpz_mod_poly_fit_length(r->poly + r->num, 2, ctx); fmpz_mod_neg(r->poly[r->num].coeffs + 0, x, ctx); fmpz_one(r->poly[r->num].coeffs + 1); r->poly[r->num].length = 2; r->exp[r->num] = mult; r->num++; } fmpz_clear(e); fmpz_clear(x); return; } /* handle zero roots */ if (fmpz_is_zero(f->coeffs + 0)) { fmpz_mod_poly_factor_fit_length(r, r->num + 1, ctx); fmpz_mod_poly_fit_length(r->poly + r->num, 2, ctx); fmpz_zero(r->poly[r->num].coeffs + 0); fmpz_one(r->poly[r->num].coeffs + 1); r->poly[r->num].length = 2; r->exp[r->num] = mult; r->num++; i = 1; while (i < f->length && fmpz_is_zero(f->coeffs + i)) i++; fmpz_mod_poly_shift_right(f, f, i, ctx); } if (fmpz_mod_poly_degree(f, ctx) <= 1) { if (fmpz_mod_poly_degree(f, ctx) == 1) { fmpz_mod_poly_factor_fit_length(r, r->num + 1, ctx); fmpz_mod_poly_swap(r->poly + r->num, f, ctx); r->exp[r->num] = mult; r->num++; } return; } FLINT_ASSERT(!fmpz_is_zero(f->coeffs + 0)); fmpz_mod_poly_reverse(t, f, f->length, ctx); fmpz_mod_poly_inv_series(t2, t, t->length, ctx); a = stack + 0; fmpz_mod_poly_powmod_x_fmpz_preinv(t, halfp, f, t2, ctx); fmpz_mod_poly_sub_si(t, t, 1, ctx); fmpz_mod_poly_gcd(a, t, f, ctx); b = stack + 1; fmpz_mod_poly_add_si(t, t, 2, ctx); fmpz_mod_poly_gcd(b, t, f, ctx); /* ensure deg a >= deg b */ if (fmpz_mod_poly_degree(a, ctx) < fmpz_mod_poly_degree(b, ctx)) fmpz_mod_poly_swap(a, b, ctx); fmpz_mod_poly_factor_fit_length(r, r->num + fmpz_mod_poly_degree(a, ctx) + fmpz_mod_poly_degree(b, ctx), ctx); /* initial split failed if b = 1 */ sp = (fmpz_mod_poly_degree(b, ctx) > 0) ? 2 : 1; while (sp > 0) { sp--; FLINT_ASSERT(sp < FLINT_BITS); fmpz_mod_poly_swap(f, stack + sp, ctx); FLINT_ASSERT(fmpz_mod_poly_degree(f, ctx) >= 0); FLINT_ASSERT(FLINT_BIT_COUNT(fmpz_mod_poly_degree(f, ctx)) <= FLINT_BITS - sp); if (fmpz_mod_poly_degree(f, ctx) <= 1) { if (fmpz_mod_poly_degree(f, ctx) == 1) { FLINT_ASSERT(r->num < r->alloc); fmpz_mod_poly_set(r->poly + r->num, f, ctx); r->exp[r->num] = mult; r->num++; } } else { FLINT_ASSERT(sp + 1 < FLINT_BITS); _fmpz_mod_poly_split_rabin(stack + sp + 0, stack + sp + 1, f, halfp, t, t2, randstate, ctx); FLINT_ASSERT(FLINT_BIT_COUNT(fmpz_mod_poly_degree(stack + sp + 1, ctx)) <= FLINT_BITS - (sp + 1)); FLINT_ASSERT(FLINT_BIT_COUNT(fmpz_mod_poly_degree(stack + sp + 0, ctx)) <= FLINT_BITS - (sp + 0)); sp += 2; } } } void fmpz_mod_poly_roots(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_mult, const fmpz_mod_ctx_t ctx) { slong i; fmpz_t p2; flint_rand_t randstate; fmpz_mod_poly_struct t[FLINT_BITS + 3]; FLINT_ASSERT(fmpz_is_probabprime(fmpz_mod_ctx_modulus(ctx))); r->num = 0; if (fmpz_mod_poly_degree(f, ctx) < 2) { if (fmpz_mod_poly_degree(f, ctx) == 1) { fmpz_mod_poly_factor_fit_length(r, 1, ctx); fmpz_mod_poly_make_monic(r->poly + 0, f, ctx); r->exp[0] = 1; r->num = 1; } else if (fmpz_mod_poly_degree(f, ctx) < 0) { flint_throw(FLINT_ERROR, "Exception in fmpz_mod_poly_roots: input polynomial is zero."); } return; } fmpz_init_set(p2, fmpz_mod_ctx_modulus(ctx)); fmpz_sub_ui(p2, p2, 1); fmpz_fdiv_q_2exp(p2, p2, 1); flint_randinit(randstate); for (i = 0; i < FLINT_BITS + 3; i++) fmpz_mod_poly_init(t + i, ctx); fmpz_mod_poly_make_monic(t + 0, f, ctx); if (with_mult) { fmpz_mod_poly_factor_t sqf; fmpz_mod_poly_factor_init(sqf, ctx); fmpz_mod_poly_factor_squarefree(sqf, t + 0, ctx); for (i = 0; i < sqf->num; i++) { _fmpz_mod_poly_push_roots(r, sqf->poly + i, sqf->exp[i], p2, t + 1, t + 2, t + 3, randstate, ctx); } fmpz_mod_poly_factor_clear(sqf, ctx); } else { _fmpz_mod_poly_push_roots(r, t + 0, 1, p2, t + 1, t + 2, t + 3, randstate, ctx); } fmpz_clear(p2); flint_randclear(randstate); for (i = 0; i < FLINT_BITS + 3; i++) fmpz_mod_poly_clear(t + i, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/roots_factored.c000066400000000000000000000232161461254215100230230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" typedef fmpz_poly_t fmpz_list_t; /* lets not generate solutions lists with length longer than LENGTH_LIMIT */ #if FLINT64 #define LENGTH_LIMIT (WORD(1) << 32) #else #define LENGTH_LIMIT (WORD(1) << 25) #endif /* The modulus of b is divisible by the modulus of a. Map b via the projection. */ static void map_down(fmpz_mod_poly_t a, const fmpz_mod_ctx_t ctxa, const fmpz_mod_poly_t b, const fmpz_mod_ctx_t ctxb) { slong i; FLINT_ASSERT(fmpz_divisible(fmpz_mod_ctx_modulus(ctxb), fmpz_mod_ctx_modulus(ctxa))); fmpz_mod_poly_fit_length(a, b->length, ctxa); for (i = 0; i < b->length; i++) fmpz_mod(a->coeffs + i, b->coeffs + i, fmpz_mod_ctx_modulus(ctxa)); a->length = b->length; _fmpz_mod_poly_normalise(a); } /* Fill x with the roots of fpk, where f->p is p^k */ static int roots_mod_prime_power(fmpz_mod_poly_factor_t x, fmpz_mod_poly_t fpk, slong k, int with_multiplicity, const fmpz_mod_ctx_t ctxp, const fmpz_mod_ctx_t ctxpk) { int success = 1; slong i, j, e1, e2; fmpz_list_t x1, x2; fmpz_mod_poly_t f, dfpk, tf, tr, tq; fmpz_t pe1, pe2e1, fprime, mfpe1; fmpz_t xstart, xstride, xlength; FLINT_ASSERT(k >= 1); FLINT_ASSERT(fmpz_is_probabprime(fmpz_mod_ctx_modulus(ctxp))); fmpz_init(pe1); fmpz_init(pe2e1); fmpz_init(fprime); fmpz_init(mfpe1); fmpz_init(xstart); fmpz_init(xstride); fmpz_init(xlength); fmpz_mod_poly_init(tf, ctxpk); fmpz_mod_poly_init(tr, ctxpk); fmpz_mod_poly_init(tq, ctxpk); fmpz_mod_poly_init(dfpk, ctxpk); fmpz_mod_poly_derivative(dfpk, fpk, ctxpk); fmpz_poly_init(x1); fmpz_poly_init(x2); fmpz_mod_poly_init(f, ctxp); map_down(f, ctxp, fpk, ctxpk); /* try to fill x1 with solution mod p */ x1->length = 0; if (f->length > 0) { fmpz_mod_poly_factor_t r; fmpz_mod_poly_factor_init(r, ctxp); fmpz_mod_poly_roots(r, f, 0, ctxp); fmpz_poly_fit_length(x1, r->num); for (i = 0; i < r->num; i++) fmpz_mod_neg(x1->coeffs + i, r->poly[i].coeffs + 0, ctxp); x1->length = r->num; fmpz_mod_poly_factor_clear(r, ctxp); } else { slong p_si; if (fmpz_cmp_si(fmpz_mod_ctx_modulus(ctxp), LENGTH_LIMIT) >= 0) { /* too many solution mod p */ success = 0; goto cleanup; } p_si = fmpz_get_si(fmpz_mod_ctx_modulus(ctxp)); fmpz_poly_fit_length(x1, p_si); for (i = 0; i < p_si; i++) fmpz_set_si(x1->coeffs + i, i); x1->length = p_si; } /* lift roots mod p^e1 to roots mod p^e2 */ for (e1 = 1; e1 < k; e1 = e2) { e2 = FLINT_MIN(k, 2*e1); fmpz_pow_ui(pe1, fmpz_mod_ctx_modulus(ctxp), e1); fmpz_pow_ui(pe2e1, fmpz_mod_ctx_modulus(ctxp), e2 - e1); x2->length = 0; for (i = 0; i < x1->length; i++) { fmpz_mod_poly_evaluate_fmpz(mfpe1, fpk, x1->coeffs + i, ctxpk); fmpz_neg(mfpe1, mfpe1); FLINT_ASSERT(fmpz_divisible(mfpe1, pe1)); fmpz_divexact(mfpe1, mfpe1, pe1); fmpz_mod_poly_evaluate_fmpz(fprime, dfpk, x1->coeffs + i, ctxpk); fmpz_mod(fprime, fprime, pe2e1); fmpz_divides_mod_list(xstart, xstride, xlength, mfpe1, fprime, pe2e1); j = *xlength; if ((!COEFF_IS_MPZ(j)) && (j + x2->length < LENGTH_LIMIT)) { fmpz_poly_fit_length(x2, j + x2->length); for (; j > 0; j--) { FLINT_ASSERT(x2->length < x2->alloc); fmpz_set(x2->coeffs + x2->length, x1->coeffs + i); fmpz_addmul(x2->coeffs + x2->length, xstart, pe1); fmpz_add(xstart, xstart, xstride); x2->length++; } } else { /* too many solutions */ success = 0; goto cleanup; } } fmpz_poly_swap(x1, x2); } /* fill in roots and multiplicies if wanted */ fmpz_mod_poly_factor_fit_length(x, x1->length, ctxpk); for (i = 0; i < x1->length; i++) { fmpz_mod_poly_fit_length(x->poly + i, 2, ctxpk); fmpz_one(x->poly[i].coeffs + 1); fmpz_mod_neg(x->poly[i].coeffs + 0, x1->coeffs + i, ctxpk); _fmpz_mod_poly_set_length(x->poly + i, 2); x->exp[i] = 1; if (with_multiplicity) { if (fpk->length > 0) { fmpz_mod_poly_divrem(tf, tr, fpk, x->poly + i, ctxpk); FLINT_ASSERT(fmpz_mod_poly_is_zero(tr, ctxpk)); while (fmpz_mod_poly_divrem(tq, tr, tf, x->poly + i, ctxpk), fmpz_mod_poly_is_zero(tr, ctxpk)) { FLINT_ASSERT(tf->length >= (x->poly + i)->length); x->exp[i]++; fmpz_mod_poly_swap(tq, tf, ctxpk); } } else { x->exp[i] = WORD_MAX; } } } x->num = x1->length; cleanup: fmpz_mod_poly_clear(tf, ctxpk); fmpz_mod_poly_clear(tr, ctxpk); fmpz_mod_poly_clear(tq, ctxpk); fmpz_poly_clear(x1); fmpz_poly_clear(x2); fmpz_mod_poly_clear(f, ctxp); fmpz_clear(pe1); fmpz_clear(pe2e1); fmpz_clear(fprime); fmpz_clear(mfpe1); fmpz_clear(xstart); fmpz_clear(xstride); fmpz_clear(xlength); fmpz_mod_poly_clear(dfpk, ctxpk); return success; } int fmpz_mod_poly_roots_factored_with_length_limit(fmpz_mod_poly_factor_t x0, const fmpz_mod_poly_t f, int with_mult, slong length_limit, const fmpz_factor_t fac, const fmpz_mod_ctx_t ctx) { int success = 1; slong i, j, k, new_length; fmpz_t m, pe; fmpz_mod_poly_factor_t x1, x2; fmpz_mod_poly_t fpe; fmpz_mod_ctx_t ctxp, ctxpe; if (f->length < 1) { flint_throw(FLINT_ERROR, "Exception in fmpz_mod_poly_roots_factored: " "input polynomial is zero."); return 0; } fmpz_init(pe); fmpz_mod_poly_init(fpe, ctx); fmpz_init_set_ui(m, 1); fmpz_mod_poly_factor_init(x1, ctx); fmpz_mod_poly_factor_init(x2, ctx); i = 0; fmpz_mod_ctx_init(ctxp, fac->p + i); fmpz_pow_ui(pe, fac->p + i, fac->exp[i]); fmpz_mod_ctx_init(ctxpe, pe); map_down(fpe, ctxpe, f, ctx); if (!roots_mod_prime_power(x0, fpe, fac->exp[i], with_mult, ctxp, ctxpe)) { goto almost_failed; } for (i = 1; x0->num > 0 && i < fac->num; i++) { fmpz_mul(m, m, pe); fmpz_mod_ctx_set_modulus(ctxp, fac->p + i); fmpz_pow_ui(pe, fac->p + i, fac->exp[i]); fmpz_mod_ctx_set_modulus(ctxpe, pe); map_down(fpe, ctxpe, f, ctx); if (!roots_mod_prime_power(x1, fpe, fac->exp[i], with_mult, ctxp, ctxpe)) { goto almost_failed; } if (z_mul_checked(&new_length, x0->num, x1->num) || new_length >= length_limit) { goto almost_failed; } /* combine roots with CRT, multiplicities with FLINT_MIN */ x2->num = 0; fmpz_mod_poly_factor_fit_length(x2, new_length, ctx); for (j = 0; j < x0->num; j++) for (k = 0; k < x1->num; k++) { fmpz_mod_poly_struct * r = x2->poly + x2->num; fmpz_mod_poly_fit_length(r, 2, ctx); fmpz_one(r->coeffs + 1); FLINT_ASSERT(x1->poly[k].length == 2); FLINT_ASSERT(x0->poly[j].length == 2); fmpz_CRT(r->coeffs + 0, x1->poly[k].coeffs + 0, pe, x0->poly[j].coeffs + 0, m, 0); _fmpz_mod_poly_set_length(r, 2); FLINT_ASSERT(x0->exp[j] >= 1); FLINT_ASSERT(x1->exp[k] >= 1); x2->exp[x2->num] = FLINT_MIN(x0->exp[j], x1->exp[k]); x2->num++; } fmpz_mod_poly_factor_swap(x0, x2, ctx); } cleanup: fmpz_mod_poly_factor_clear(x1, ctx); fmpz_mod_poly_factor_clear(x2, ctx); fmpz_clear(m); fmpz_clear(pe); fmpz_mod_poly_clear(fpe, ctx); fmpz_mod_ctx_clear(ctxp); fmpz_mod_ctx_clear(ctxpe); return success; almost_failed: /* if any prime power is lacking roots, we can still succeed */ x0->num = 0; for (i++; i < fac->num; i++) { fmpz_mod_ctx_set_modulus(ctxp, fac->p + i); fmpz_pow_ui(pe, fac->p + i, fac->exp[i]); fmpz_mod_ctx_set_modulus(ctxpe, pe); map_down(fpe, ctxpe, f, ctx); if (roots_mod_prime_power(x1, fpe, fac->exp[i], 0, ctxp, ctxpe) && x1->num == 0) { goto cleanup; } } success = 0; goto cleanup; } int fmpz_mod_poly_roots_factored(fmpz_mod_poly_factor_t x0, const fmpz_mod_poly_t f, int with_mult, const fmpz_factor_t fac, const fmpz_mod_ctx_t ctx) { return fmpz_mod_poly_roots_factored_with_length_limit(x0, f, with_mult, LENGTH_LIMIT, fac, ctx); } flint-3.1.3/src/fmpz_mod_poly_factor/set.c000066400000000000000000000024171461254215100206010ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" void fmpz_mod_poly_factor_set(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx) { if (res != fac) { if (fac->num == 0) { fmpz_mod_poly_factor_clear(res, ctx); fmpz_mod_poly_factor_init(res, ctx); } else { slong i; fmpz_mod_poly_factor_fit_length(res, fac->num, ctx); for (i = 0; i < fac->num; i++) { fmpz_mod_poly_set(res->poly + i, fac->poly + i, ctx); res->exp[i] = fac->exp[i]; } for (; i < res->num; i++) { fmpz_mod_poly_zero(res->poly + i, ctx); res->exp[i] = 0; } res->num = fac->num; } } } flint-3.1.3/src/fmpz_mod_poly_factor/test/000077500000000000000000000000001461254215100206155ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_poly_factor/test/main.c000066400000000000000000000037551461254215100217170ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor_berlekamp.c" #include "t-factor.c" #include "t-factor_cantor_zassenhaus.c" #include "t-factor_distinct_deg.c" #include "t-factor_distinct_deg_threaded.c" #include "t-factor_equal_deg_prob.c" #include "t-factor_kaltofen_shoup.c" #include "t-factor_squarefree.c" #include "t-interval_threaded.c" #include "t-is_irreducible.c" #include "t-is_irreducible_ddf.c" #include "t-is_irreducible_rabin.c" #include "t-is_squarefree.c" #include "t-roots.c" #include "t-roots_factored.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mod_poly_factor_berlekamp), TEST_FUNCTION(fmpz_mod_poly_factor), TEST_FUNCTION(fmpz_mod_poly_factor_cantor_zassenhaus), TEST_FUNCTION(fmpz_mod_poly_factor_distinct_deg), TEST_FUNCTION(fmpz_mod_poly_factor_distinct_deg_threaded), TEST_FUNCTION(fmpz_mod_poly_factor_equal_deg_prob), TEST_FUNCTION(fmpz_mod_poly_factor_kaltofen_shoup), TEST_FUNCTION(fmpz_mod_poly_factor_squarefree), TEST_FUNCTION(fmpz_mod_poly_factor_interval_threaded), TEST_FUNCTION(fmpz_mod_poly_factor_is_irreducible), TEST_FUNCTION(fmpz_mod_poly_factor_is_irreducible_ddf), TEST_FUNCTION(fmpz_mod_poly_factor_is_irreducible_rabin), TEST_FUNCTION(fmpz_mod_poly_factor_is_squarefree), TEST_FUNCTION(fmpz_mod_poly_factor_roots), TEST_FUNCTION(fmpz_mod_poly_factor_roots_factored) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor.c000066400000000000000000000100371461254215100225010ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly, q, r, product; fmpz_mod_poly_factor_t res; fmpz_t modulus; slong i, j, length, num; slong exp[6]; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_zero(poly1, ctx); fmpz_mod_poly_set_coeff_ui(poly1, 0, 1, ctx); length = n_randint(state, 7) + 2; do { fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) fmpz_mod_poly_make_monic(poly, poly, ctx); } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx))); exp[0] = n_randint(state, 30) + 1; for (i = 0; i < exp[0]; i++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num = n_randint(state, 6) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) { fmpz_mod_poly_make_monic(poly, poly, ctx); fmpz_mod_poly_divrem(q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx)) || (r->length == 0)); exp[i] = n_randint(state, 30) + 1; for (j = 0; j < exp[i]; j++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); } fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor(res, poly1, ctx); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); fflush(stdout); flint_abort(); } fmpz_mod_poly_init(product, ctx); fmpz_mod_poly_set_coeff_ui(product, 0, 1, ctx); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) fmpz_mod_poly_mul(product, product, res->poly + i, ctx); fmpz_mod_poly_scalar_mul_fmpz(product, product, &(poly1->coeffs[poly1->length - 1]), ctx); if (!fmpz_mod_poly_equal(poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); fmpz_mod_poly_print(product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(product, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_factor_clear(res, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000100631461254215100245220ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_berlekamp, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly, q, r, product; fmpz_mod_poly_factor_t res; fmpz_t modulus; slong i, j, length, num; slong exp[6]; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_zero(poly1, ctx); fmpz_mod_poly_set_coeff_ui(poly1, 0, 1, ctx); length = n_randint(state, 7) + 2; do { fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) fmpz_mod_poly_make_monic(poly, poly, ctx); } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx))); exp[0] = n_randint(state, 30) + 1; for (i = 0; i < exp[0]; i++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num = n_randint(state, 6) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) { fmpz_mod_poly_make_monic(poly, poly, ctx); fmpz_mod_poly_divrem(q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx)) || (r->length == 0)); exp[i] = n_randint(state, 30) + 1; for (j = 0; j < exp[i]; j++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); } fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_berlekamp(res, poly1, ctx); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); fflush(stdout); flint_abort(); } fmpz_mod_poly_init(product, ctx); fmpz_mod_poly_set_coeff_ui(product, 0, 1, ctx); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) fmpz_mod_poly_mul(product, product, res->poly + i, ctx); fmpz_mod_poly_scalar_mul_fmpz(product, product, &(poly1->coeffs[poly1->length - 1]), ctx); if (!fmpz_mod_poly_equal(poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); fmpz_mod_poly_print(product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(product, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_factor_clear(res, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000101031461254215100263050ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_cantor_zassenhaus, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly, q, r, product; fmpz_mod_poly_factor_t res; fmpz_t modulus; slong i, j, length, num; slong exp[6]; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_zero(poly1, ctx); fmpz_mod_poly_set_coeff_ui(poly1, 0, 1, ctx); length = n_randint(state, 7) + 2; do { fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) fmpz_mod_poly_make_monic(poly, poly, ctx); } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx))); exp[0] = n_randint(state, 30) + 1; for (i = 0; i < exp[0]; i++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num = n_randint(state, 6) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) { fmpz_mod_poly_make_monic(poly, poly, ctx); fmpz_mod_poly_divrem(q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx)) || (r->length == 0)); exp[i] = n_randint(state, 30) + 1; for (j = 0; j < exp[i]; j++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); } fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_cantor_zassenhaus(res, poly1, ctx); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); fflush(stdout); flint_abort(); } fmpz_mod_poly_init(product, ctx); fmpz_mod_poly_set_coeff_ui(product, 0, 1, ctx); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) fmpz_mod_poly_mul(product, product, res->poly + i, ctx); fmpz_mod_poly_scalar_mul_fmpz(product, product, &(poly1->coeffs[poly1->length - 1]), ctx); if (!fmpz_mod_poly_equal(poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); fmpz_mod_poly_print(product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(product, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_factor_clear(res, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000112051461254215100252170ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" /* Defined in t-factor_distinct_deg.c and t-factor_distinct_deg_threaded.c */ #define MAX_DEG 7 TEST_FUNCTION_START(fmpz_mod_poly_factor_distinct_deg, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly, q, r, product; fmpz_mod_poly_factor_t res; fmpz_t modulus; slong i, length, num; slong *degs; slong num_of_deg[MAX_DEG + 1]; for (i = 0; i < MAX_DEG + 1; i++) num_of_deg[i] = 0; fmpz_init(modulus); fmpz_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_zero(poly1, ctx); fmpz_mod_poly_set_coeff_ui(poly1, 0, 1, ctx); length = n_randint(state, MAX_DEG) + 2; do { fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) fmpz_mod_poly_make_monic(poly, poly, ctx); } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx))); fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num_of_deg[fmpz_mod_poly_degree(poly, ctx)]++; num = n_randint(state, 6) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, MAX_DEG) + 2; fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) { fmpz_mod_poly_make_monic(poly, poly, ctx); fmpz_mod_poly_divrem(q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx)) || (r->length == 0)); fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num_of_deg[fmpz_mod_poly_degree(poly, ctx)]++; } if (!(degs = flint_malloc((poly1->length - 1) * sizeof(slong)))) { flint_printf("Fatal error: not enough memory."); fflush(stdout); flint_abort(); } fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_distinct_deg(res, poly1, °s, ctx); fmpz_mod_poly_init(product, ctx); fmpz_mod_poly_set_coeff_ui(product, 0, 1, ctx); for (i = 0; i < res->num; i++) { fmpz_mod_poly_mul(product, product, res->poly + i, ctx); if (fmpz_mod_poly_degree(res->poly + i, ctx) != degs[i]*num_of_deg[degs[i]]) { flint_printf("Error: product of factors of degree %w incorrect\n", degs[i]); flint_printf("Degree %w != %w * %w\n", fmpz_mod_poly_degree(res->poly + i, ctx), degs[i], num_of_deg[degs[i]]); fflush(stdout); flint_abort(); } } fmpz_mod_poly_scalar_mul_fmpz(product, product, &(poly1->coeffs[poly1->length - 1]), ctx); if (!fmpz_mod_poly_equal(poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); fmpz_mod_poly_print(product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(degs); fmpz_clear(modulus); fmpz_mod_poly_clear(product, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_factor_clear(res, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } #undef MAX_DEG flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor_distinct_deg_threaded.c000066400000000000000000000115521461254215100270640ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010, 2020 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2014 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" /* Defined in t-factor_distinct_deg.c and t-factor_distinct_deg_threaded.c */ #define MAX_DEG 9 TEST_FUNCTION_START(fmpz_mod_poly_factor_distinct_deg_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 50 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly, q, r, product; fmpz_mod_poly_factor_t res; fmpz_t modulus; slong i, length, num; slong * degs; slong num_of_deg[MAX_DEG + 1]; for (i = 0; i < MAX_DEG + 1; i++) num_of_deg[i] = 0; fmpz_init(modulus); fmpz_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); flint_set_num_threads(1 + n_randint(state, 5)); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_zero(poly1, ctx); fmpz_mod_poly_set_coeff_ui(poly1, 0, 1, ctx); length = n_randint(state, MAX_DEG) + 2; do { fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) fmpz_mod_poly_make_monic(poly, poly, ctx); } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx))); fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num_of_deg[fmpz_mod_poly_degree(poly, ctx)]++; num = n_randint(state, 10) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, MAX_DEG) + 2; fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) { fmpz_mod_poly_make_monic(poly, poly, ctx); fmpz_mod_poly_divrem(q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx)) || (r->length == 0)); fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num_of_deg[fmpz_mod_poly_degree(poly, ctx)]++; } if (!(degs = flint_malloc((poly1->length - 1) * sizeof(slong)))) { flint_printf("Fatal error: not enough memory."); fflush(stdout); flint_abort(); } fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_distinct_deg_threaded(res, poly1, °s, ctx); fmpz_mod_poly_init(product, ctx); fmpz_mod_poly_set_coeff_ui(product, 0, 1, ctx); for (i = 0; i < res->num; i++) { fmpz_mod_poly_mul(product, product, res->poly + i, ctx); if (fmpz_mod_poly_degree(res->poly + i, ctx) != degs[i]*num_of_deg[degs[i]]) { flint_printf("Error: product of factors of degree %w incorrect\n", degs[i]); flint_printf("Degree %w != %w * %w\n", fmpz_mod_poly_degree(res->poly + i, ctx), degs[i], num_of_deg[degs[i]]); fflush(stdout); flint_abort(); } } fmpz_mod_poly_scalar_mul_fmpz(product, product, &(poly1->coeffs[poly1->length - 1]), ctx); if (!fmpz_mod_poly_equal(poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); fmpz_mod_poly_print(product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(degs); fmpz_clear(modulus); fmpz_mod_poly_clear(product, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_factor_clear(res, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } #undef MAX_DEG flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000054021461254215100255310ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_equal_deg_prob, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly2, q, r; fmpz_t modulus; slong length; int i, num; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly2, ctx); length = n_randint(state, 10) + 2; do { fmpz_mod_poly_randtest(poly1, state, length, ctx); if (poly1->length) fmpz_mod_poly_make_monic(poly1, poly1, ctx); } while ((poly1->length < 2) || (!fmpz_mod_poly_is_irreducible(poly1, ctx))); num = n_randint(state, 6) + 1; for (i = 0; i < num; i++) { do { fmpz_mod_poly_randtest(poly2, state, length, ctx); if (poly2->length) fmpz_mod_poly_make_monic(poly2, poly2, ctx); } while ((poly2->length < 2) || (!fmpz_mod_poly_is_irreducible(poly2, ctx))); fmpz_mod_poly_mul(poly1, poly1, poly2, ctx); } while (!fmpz_mod_poly_factor_equal_deg_prob (poly2, state, poly1, length - 1, ctx)) { }; fmpz_mod_poly_divrem(q, r, poly1, poly2, ctx); if (!fmpz_mod_poly_is_zero(r, ctx)) { flint_printf("FAIL:\n"); flint_printf("Error: factor does not divide original polynomial\n"); flint_printf("factor:\n"); fmpz_mod_poly_print(poly2, ctx); flint_printf("\n\n"); flint_printf("polynomial:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000100751461254215100256040ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_kaltofen_shoup, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly, q, r, product; fmpz_mod_poly_factor_t res; fmpz_t modulus; slong i, j, length, num; slong exp[6]; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_zero(poly1, ctx); fmpz_mod_poly_set_coeff_ui(poly1, 0, 1, ctx); length = n_randint(state, 7) + 2; do { fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) fmpz_mod_poly_make_monic(poly, poly, ctx); } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx))); exp[0] = n_randint(state, 30) + 1; for (i = 0; i < exp[0]; i++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); num = n_randint(state, 6) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) { fmpz_mod_poly_make_monic(poly, poly, ctx); fmpz_mod_poly_divrem(q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!fmpz_mod_poly_is_irreducible(poly, ctx)) || (r->length == 0)); exp[i] = n_randint(state, 30) + 1; for (j = 0; j < exp[i]; j++) fmpz_mod_poly_mul(poly1, poly1, poly, ctx); } fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_kaltofen_shoup(res, poly1, ctx); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); fflush(stdout); flint_abort(); } fmpz_mod_poly_init(product, ctx); fmpz_mod_poly_set_coeff_ui(product, 0, 1, ctx); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) fmpz_mod_poly_mul(product, product, res->poly + i, ctx); fmpz_mod_poly_scalar_mul_fmpz(product, product, &(poly1->coeffs[poly1->length - 1]), ctx); if (!fmpz_mod_poly_equal(poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); fmpz_mod_poly_print(product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(product, ctx); fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(r, ctx); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_factor_clear(res, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-factor_squarefree.c000066400000000000000000000073531461254215100247320ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_squarefree, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 30 * flint_test_multiplier(); iter++) { int result = 1; fmpz_mod_poly_t pol1, poly, quot, rem; fmpz_mod_poly_factor_t res; fmpz_t modulus; slong exp[6], prod1; slong length, i, j, num; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(pol1, ctx); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(quot, ctx); fmpz_mod_poly_init(rem, ctx); fmpz_mod_poly_zero(pol1, ctx); fmpz_mod_poly_set_coeff_ui(pol1, 0, 1, ctx); length = n_randint(state, 7) + 2; do { fmpz_mod_poly_randtest(poly, state, length, ctx); fmpz_mod_poly_make_monic(poly, poly, ctx); } while ((!fmpz_mod_poly_is_irreducible(poly, ctx)) || (poly->length < 2)); exp[0] = n_randprime(state, 5, 0); prod1 = exp[0]; for (i = 0; i < exp[0]; i++) fmpz_mod_poly_mul(pol1, pol1, poly, ctx); num = n_randint(state, 6) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; fmpz_mod_poly_randtest(poly, state, length, ctx); if (poly->length) { fmpz_mod_poly_make_monic(poly, poly, ctx); fmpz_mod_poly_divrem(quot, rem, pol1, poly, ctx); } } while ((!fmpz_mod_poly_is_irreducible(poly, ctx)) || (poly->length < 2) || (rem->length == 0)); do exp[i] = n_randprime(state, 6, 0); while (prod1 % exp[i] == 0); prod1 *= exp[i]; for (j = 0; j < exp[i]; j++) fmpz_mod_poly_mul(pol1, pol1, poly, ctx); } fmpz_mod_poly_factor_init(res, ctx); fmpz_mod_poly_factor_squarefree(res, pol1, ctx); result &= (res->num == num); if (result) { ulong prod2 = 1; for (i = 0; i < num; i++) prod2 *= res->exp[i]; result &= (prod1 == prod2); } if (!result) { flint_printf("Error: exp don't match. Modulus = "); fmpz_print(modulus); flint_printf("\n"); for (i = 0; i < res->num; i++) flint_printf("%wd ", res->exp[i]); flint_printf("\n"); for (i = 0; i < num; i++) flint_printf("%wd ", exp[i]); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(quot, ctx); fmpz_mod_poly_clear(rem, ctx); fmpz_mod_poly_clear(pol1, ctx); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_factor_clear(res, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-interval_threaded.c000066400000000000000000000122151461254215100247070ustar00rootroot00000000000000/* Copyright (C) 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_interval_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); /* no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_mod_poly_t a, b, c, cinv, d; fmpz_mod_poly_struct * tmp; fmpz_mod_poly_struct * e; fmpz_t p; slong j, num_threads, l; fmpz_mod_poly_interval_poly_arg_t * args1; thread_pool_handle * threads; flint_set_num_threads(1 + n_randint(state, 3)); num_threads = flint_request_threads(&threads, FLINT_DEFAULT_THREAD_LIMIT); l = n_randint(state, 20) + 1; e = (fmpz_mod_poly_struct *) flint_malloc(sizeof(fmpz_mod_poly_struct)*(num_threads + 1)); tmp = (fmpz_mod_poly_struct *) flint_malloc(sizeof(fmpz_mod_poly_struct)*l); args1 = (fmpz_mod_poly_interval_poly_arg_t *) flint_malloc((num_threads + 1)* sizeof(fmpz_mod_poly_interval_poly_arg_t)); fmpz_init(p); fmpz_set_ui(p, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(c, ctx); fmpz_mod_poly_init(cinv, ctx); fmpz_mod_poly_init(d, ctx); for (j = 0; j < l; j++) fmpz_mod_poly_init(tmp + j, ctx); for (j = 0; j < num_threads + 1; j++) fmpz_mod_poly_init(e + j, ctx); fmpz_mod_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1, ctx); do { fmpz_mod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1, ctx); } while (c->length < 3); fmpz_mod_poly_rem(a, a, c, ctx); for (j = 0; j < l; j++) fmpz_mod_poly_randtest_not_zero(tmp + j, state, n_randint(state, 20) + 1, ctx); fmpz_mod_poly_reverse(cinv, c, c->length, ctx); fmpz_mod_poly_inv_series(cinv, cinv, c->length, ctx); fmpz_mod_poly_set_ui(b, 1, ctx); for (j = l - 1; j >= 0; j--) { fmpz_mod_poly_rem(d, tmp + j, c, ctx); fmpz_mod_poly_sub(d, a, d, ctx); fmpz_mod_poly_mulmod_preinv(b, d, b, c, cinv, ctx); } for (j = 0; j < num_threads + 1; j++) { fmpz_mod_poly_fit_length(e + j, c->length - 1, ctx); _fmpz_mod_poly_set_length(e + j, c->length - 1); _fmpz_vec_zero(e[j].coeffs, c->length - 1); args1[j].baby = tmp; args1[j].res = e + j; args1[j].H = a; args1[j].v = c; args1[j].vinv = cinv; args1[j].m = l; args1[j].tmp = _fmpz_vec_init(c->length - 1); args1[j].ctx = ctx; } for (j = 0; j < num_threads; j++) thread_pool_wake(global_thread_pool, threads[j], 0, _fmpz_mod_poly_interval_poly_worker, &args1[j]); _fmpz_mod_poly_interval_poly_worker(&args1[num_threads]); for (j = 0; j < num_threads; j++) thread_pool_wait(global_thread_pool, threads[j]); for (j = 0; j < num_threads + 1; j++) { _fmpz_mod_poly_normalise(e + j); _fmpz_vec_clear(args1[j].tmp, c->length - 1); } for (j = 0; j < num_threads + 1; j++) { if (!fmpz_mod_poly_equal(b, e + j, ctx)) { flint_printf("j: %wd\n", j); flint_printf("FAIL (interval_poly):\n"); flint_printf("b:\n"); fmpz_mod_poly_print(b, ctx); flint_printf("\n"); flint_printf("c:\n"); fmpz_mod_poly_print(c, ctx); flint_printf("\n"); flint_printf("e[j]:\n"); fmpz_mod_poly_print(e + j, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } flint_give_back_threads(threads, num_threads); fmpz_clear(p); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(c, ctx); fmpz_mod_poly_clear(cinv, ctx); fmpz_mod_poly_clear(d, ctx); for (j = 0; j < num_threads + 1; j++) fmpz_mod_poly_clear(e + j, ctx); for (j = 0; j < l; j++) fmpz_mod_poly_clear(tmp + j, ctx); flint_free(e); flint_free(tmp); flint_free(args1); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-is_irreducible.c000066400000000000000000000045321461254215100242120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_is_irreducible, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly2; fmpz_t modulus; slong length; int i, num; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly2, ctx); length = n_randint(state, 10) + 2; do { fmpz_mod_poly_randtest(poly1, state, length, ctx); if (!fmpz_mod_poly_is_zero(poly1, ctx)) fmpz_mod_poly_make_monic(poly1, poly1, ctx); } while ((!fmpz_mod_poly_is_irreducible(poly1, ctx)) || (poly1->length < 2)); num = n_randint(state, 5) + 1; for (i = 0; i < num; i++) { do { fmpz_mod_poly_randtest(poly2, state, length, ctx); if (!fmpz_mod_poly_is_zero(poly1, ctx)) fmpz_mod_poly_make_monic(poly2, poly2, ctx); } while ((!fmpz_mod_poly_is_irreducible(poly2, ctx)) || (poly2->length < 2)); fmpz_mod_poly_mul(poly1, poly1, poly2, ctx); } if (fmpz_mod_poly_is_irreducible(poly1, ctx)) { flint_printf("Error: reducible polynomial declared irreducible!\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000045521461254215100250310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_is_irreducible_ddf, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly2; fmpz_t modulus; slong length; int i, num; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly2, ctx); length = n_randint(state, 10) + 2; do { fmpz_mod_poly_randtest(poly1, state, length, ctx); if (!fmpz_mod_poly_is_zero(poly1, ctx)) fmpz_mod_poly_make_monic(poly1, poly1, ctx); } while ((!fmpz_mod_poly_is_irreducible_ddf(poly1, ctx)) || (poly1->length < 2)); num = n_randint(state, 5) + 1; for (i = 0; i < num; i++) { do { fmpz_mod_poly_randtest(poly2, state, length, ctx); if (!fmpz_mod_poly_is_zero(poly1, ctx)) fmpz_mod_poly_make_monic(poly2, poly2, ctx); } while ((!fmpz_mod_poly_is_irreducible_ddf(poly2, ctx)) || (poly2->length < 2)); fmpz_mod_poly_mul(poly1, poly1, poly2, ctx); } if (fmpz_mod_poly_is_irreducible_ddf(poly1, ctx)) { flint_printf("Error: reducible polynomial declared irreducible!\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-is_irreducible_rabin.c000066400000000000000000000045621461254215100253700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_is_irreducible_rabin, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly1, poly2; fmpz_t modulus; slong length; int i, num; fmpz_init_set_ui(modulus, n_randtest_prime(state, 0)); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly1, ctx); fmpz_mod_poly_init(poly2, ctx); length = n_randint(state, 10) + 2; do { fmpz_mod_poly_randtest(poly1, state, length, ctx); if (!fmpz_mod_poly_is_zero(poly1, ctx)) fmpz_mod_poly_make_monic(poly1, poly1, ctx); } while ((!fmpz_mod_poly_is_irreducible_rabin(poly1, ctx)) || (poly1->length < 2)); num = n_randint(state, 5) + 1; for (i = 0; i < num; i++) { do { fmpz_mod_poly_randtest(poly2, state, length, ctx); if (!fmpz_mod_poly_is_zero(poly1, ctx)) fmpz_mod_poly_make_monic(poly2, poly2, ctx); } while ((!fmpz_mod_poly_is_irreducible_rabin(poly2, ctx)) || (poly2->length < 2)); fmpz_mod_poly_mul(poly1, poly1, poly2, ctx); } if (fmpz_mod_poly_is_irreducible_rabin(poly1, ctx)) { flint_printf("Error: reducible polynomial declared irreducible!\n"); flint_printf("poly:\n"); fmpz_mod_poly_print(poly1, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-is_squarefree.c000066400000000000000000000053521461254215100240640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" TEST_FUNCTION_START(fmpz_mod_poly_factor_is_squarefree, state) { int iter; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { fmpz_mod_poly_t poly, Q, R, t; fmpz_t modulus; mp_limb_t mod; slong i, num_factors, exp, max_exp; int v, result; mod = n_randtest_prime(state, 0); fmpz_init_set_ui(modulus, mod); fmpz_mod_ctx_set_modulus(ctx, modulus); fmpz_mod_poly_init(poly, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_init(Q, ctx); fmpz_mod_poly_init(R, ctx); fmpz_mod_poly_set_coeff_ui(poly, 0, n_randint(state, mod), ctx); num_factors = n_randint(state, 5); max_exp = 0; for (i = 0; i < num_factors; i++) { do { fmpz_mod_poly_randtest(t, state, n_randint(state, 10), ctx); } while (!fmpz_mod_poly_is_irreducible(t, ctx) || (fmpz_mod_poly_length(t, ctx) < 2)); exp = n_randint(state, 4) + 1; if (n_randint(state, 2) == 0) exp = 1; fmpz_mod_poly_divrem(Q, R, poly, t, ctx); if (!fmpz_mod_poly_is_zero(R, ctx)) { fmpz_mod_poly_pow(t, t, exp, ctx); fmpz_mod_poly_mul(poly, poly, t, ctx); max_exp = FLINT_MAX(exp, max_exp); } } v = fmpz_mod_poly_is_squarefree(poly, ctx); if (v == 1) result = (max_exp <= 1 && !fmpz_mod_poly_is_zero(poly, ctx)); else result = (max_exp > 1 || fmpz_mod_poly_is_zero(poly, ctx)); if (!result) { flint_printf("FAIL: "); fmpz_print(modulus); flint_printf(" %wd, %d\n", max_exp, v); fmpz_mod_poly_print(poly, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(poly, ctx); fmpz_mod_poly_clear(t, ctx); fmpz_mod_poly_clear(Q, ctx); fmpz_mod_poly_clear(R, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mod_poly_factor/test/t-roots.c000066400000000000000000000075721461254215100224030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" /* Defined in t-roots.c and t-roots_factored.c */ #define test_poly test_poly_roots void test_poly( fmpz_mod_poly_factor_t roots, const fmpz_mod_poly_t f, int want_mult, const fmpz_mod_ctx_t ctx) { slong i, multiplicity; fmpz_mod_poly_t q, qt, r; fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(qt, ctx); fmpz_mod_poly_init(r, ctx); fmpz_mod_poly_set(q, f, ctx); fmpz_mod_poly_roots(roots, f, want_mult, ctx); for (i = 0; i < roots->num; i++) { if (fmpz_mod_poly_degree(roots->poly + i, ctx) != 1) { flint_printf("FAILED:\ncheck root is linear\n"); fflush(stdout); flint_abort(); } if (!fmpz_is_one(roots->poly[i].coeffs + 1)) { flint_printf("FAILED:\ncheck root is monic\n"); fflush(stdout); flint_abort(); } multiplicity = 0; while (fmpz_mod_poly_divrem(qt, r, q, roots->poly + i, ctx), fmpz_mod_poly_is_zero(r, ctx)) { fmpz_mod_poly_swap(q, qt, ctx); multiplicity++; } if (multiplicity <= 0) { flint_printf("FAILED:\ncheck root is a root\n"); fflush(stdout); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); fflush(stdout); flint_abort(); } } fmpz_mod_poly_roots(roots, q, want_mult, ctx); if (roots->num > 0) { flint_printf("FAILED:\ncheck missing roots\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(qt, ctx); fmpz_mod_poly_clear(r, ctx); } TEST_FUNCTION_START(fmpz_mod_poly_factor_roots, state) { slong i, j, k, l; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t f; fmpz_mod_poly_factor_t r; fmpz_init(p); fmpz_randtest_unsigned(p, state, 100); fmpz_nextprime(p, p, 1); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_factor_init(r, ctx); for (j = 0; j < 4; j++) { do { fmpz_mod_poly_randtest(f, state, n_randint(state, 20) + 1, ctx); } while (fmpz_mod_poly_is_zero(f, ctx)); for (k = 0; k < 5; k++) { fmpz_mod_poly_t ff; fmpz_mod_poly_init(ff, ctx); fmpz_mod_poly_fit_length(ff, 2, ctx); fmpz_one(ff->coeffs + 1); fmpz_randm(ff->coeffs + 0, state, p); ff->length = 2; for (l = 1 + n_randint(state, 5); l > 0; l--) fmpz_mod_poly_mul(f, f, ff, ctx); fmpz_mod_poly_clear(ff, ctx); } if (n_randint(state, 2)) { test_poly(r, f, 1, ctx); test_poly(r, f, 0, ctx); } else { test_poly(r, f, 0, ctx); test_poly(r, f, 1, ctx); } } fmpz_mod_poly_factor_clear(r, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } #undef test_poly flint-3.1.3/src/fmpz_mod_poly_factor/test/t-roots_factored.c000066400000000000000000000166551461254215100242540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" /* Defined in t-roots.c and t-roots_factored.c */ #define test_poly test_poly_roots_factored void test_poly( fmpz_mod_poly_factor_t roots, const fmpz_mod_poly_t f, int want_mult, const fmpz_factor_t n, const fmpz_mod_ctx_t ctx) { slong i, multiplicity; fmpz_mod_poly_t q, qt, r; fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_init(qt, ctx); fmpz_mod_poly_init(r, ctx); if (!fmpz_mod_poly_roots_factored(roots, f, want_mult, n, ctx)) { flint_printf("FAILED:\ncheck roots could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < roots->num; i++) { if (fmpz_mod_poly_degree(roots->poly + i, ctx) != 1) { flint_printf("FAILED:\ncheck root is linear\n"); fflush(stdout); flint_abort(); } if (!fmpz_is_one(roots->poly[i].coeffs + 1)) { flint_printf("FAILED:\ncheck root is monic\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_set(q, f, ctx); multiplicity = 0; while (fmpz_mod_poly_divrem(qt, r, q, roots->poly + i, ctx), fmpz_mod_poly_is_zero(r, ctx)) { fmpz_mod_poly_swap(q, qt, ctx); multiplicity++; } if (multiplicity <= 0) { flint_printf("FAILED:\ncheck root is a root\n"); fmpz_mod_poly_print_pretty(roots->poly + i, "x", ctx); printf("\n"); fflush(stdout); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); fflush(stdout); flint_abort(); } } if (fmpz_cmp_si(fmpz_mod_ctx_modulus(ctx), 1000) < 0) { fmpz_t e, k; fmpz_init(e); fmpz_init(k); for (fmpz_zero(k); fmpz_cmp(k, fmpz_mod_ctx_modulus(ctx)) < 0; fmpz_add_ui(k, k, 1)) { int found = 0; fmpz_mod_poly_evaluate_fmpz(e, f, k, ctx); if (!fmpz_is_zero(e)) continue; for (i = 0; i < roots->num; i++) { fmpz_mod_poly_evaluate_fmpz(e, roots->poly + i, k, ctx); if (fmpz_is_zero(e)) { if (found) { flint_printf("FAILED:\ncheck duplicate roots\n"); fflush(stdout); flint_abort(); } found = 1; } } if (!found) { flint_printf("FAILED:\ncheck missing roots\n"); fflush(stdout); flint_abort(); } } fmpz_clear(k); fmpz_clear(e); } fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(qt, ctx); fmpz_mod_poly_clear(r, ctx); } TEST_FUNCTION_START(fmpz_mod_poly_factor_roots_factored, state) { slong i, j, k, l; fmpz_mod_ctx_t ctx; fmpz_mod_ctx_init_ui(ctx, 2); { fmpz_t p, p2; fmpz_mod_poly_t f; fmpz_mod_poly_factor_t r; fmpz_factor_t n; fmpz_init_set_ui(p, UWORD_MAX_PRIME); fmpz_init(p2); fmpz_pow_ui(p2, p, 2); fmpz_mod_ctx_set_modulus(ctx, p2); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_factor_init(r, ctx); fmpz_factor_init(n); _fmpz_factor_append(n, p, 2); fmpz_mod_poly_set_coeff_fmpz(f, 1, p, ctx); if (fmpz_mod_poly_roots_factored(r, f, 0, n, ctx)) { flint_printf("FAILED:\ncheck non example with too many roots\n"); fflush(stdout); flint_abort(); } fmpz_factor_clear(n); fmpz_mod_poly_factor_clear(r, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_clear(p); fmpz_clear(p2); } { fmpz_t one, p, q, p2q; fmpz_mod_poly_t f; fmpz_mod_poly_factor_t r; fmpz_factor_t n; ulong tp = n_nextprime(UWORD(1) << (FLINT_BITS - 1), 1); ulong tq = n_nextprime(tp, 1); fmpz_init_set_ui(one, 1); fmpz_init_set_ui(p, tp); fmpz_init_set_ui(q, tq); fmpz_init_set(p2q, q); fmpz_mul(p2q, p2q, p); fmpz_mul(p2q, p2q, p); fmpz_mod_ctx_set_modulus(ctx, p2q); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_factor_init(r, ctx); fmpz_factor_init(n); _fmpz_factor_append(n, p, 2); _fmpz_factor_append(n, q, 1); fmpz_mod_poly_set_coeff_fmpz(f, 0, one, ctx); fmpz_mod_poly_set_coeff_fmpz(f, 1, q, ctx); fmpz_mod_poly_scalar_mul_fmpz(f, f, p, ctx); if ((!fmpz_mod_poly_roots_factored(r, f, 0, n, ctx)) || (r->num != 0)) { flint_printf("FAILED:\ncheck example with no roots\n"); fflush(stdout); flint_abort(); } fmpz_factor_clear(n); fmpz_mod_poly_factor_clear(r, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_clear(p); fmpz_clear(q); fmpz_clear(p2q); fmpz_clear(one); } for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t f; fmpz_mod_poly_factor_t r; fmpz_factor_t n; fmpz_init(p); fmpz_randtest_unsigned(p, state, 9); fmpz_add_ui(p, p, 2); for (j = n_randint(state, 3) + 1; j > 0; j--) { fmpz_t q; fmpz_init(q); fmpz_randtest_unsigned(q, state, 6); fmpz_add_ui(q, q, 3); fmpz_nextprime(q, q, 1); fmpz_pow_ui(q, q, n_randint(state, 3) + 1); fmpz_mul(p, p, q); } fmpz_factor_init(n); fmpz_factor(n, p); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_mod_poly_init(f, ctx); fmpz_mod_poly_factor_init(r, ctx); for (j = 0; j < 4; j++) { slong m = 80/fmpz_bits(p); do { fmpz_mod_poly_randtest(f, state, n_randint(state, 6 + m) + 1, ctx); } while (fmpz_mod_poly_is_zero(f, ctx)); for (k = 0; k < m; k++) { fmpz_mod_poly_t ff; fmpz_mod_poly_init(ff, ctx); fmpz_mod_poly_fit_length(ff, 2, ctx); fmpz_one(ff->coeffs + 1); fmpz_randm(ff->coeffs + 0, state, p); ff->length = 2; for (l = n_randint(state, m); l > 0; l--) fmpz_mod_poly_mul(f, f, ff, ctx); fmpz_mod_poly_clear(ff, ctx); } test_poly(r, f, 0, n, ctx); if (r->num < 1000) test_poly(r, f, 1, n, ctx); } fmpz_mod_poly_factor_clear(r, ctx); fmpz_mod_poly_clear(f, ctx); fmpz_factor_clear(n); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } #undef test_poly flint-3.1.3/src/fmpz_mod_types.h000066400000000000000000000037411461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_TYPES_H #define FMPZ_MOD_TYPES_H #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct fmpz_mod_ctx { fmpz_t n; void (* add_fxn)(fmpz_t, const fmpz_t, const fmpz_t, const struct fmpz_mod_ctx *); void (* sub_fxn)(fmpz_t, const fmpz_t, const fmpz_t, const struct fmpz_mod_ctx *); void (* mul_fxn)(fmpz_t, const fmpz_t, const fmpz_t, const struct fmpz_mod_ctx *); nmod_t mod; ulong n_limbs[3]; ulong ninv_limbs[3]; fmpz_preinvn_struct * ninv_huge; } fmpz_mod_ctx_struct; typedef fmpz_mod_ctx_struct fmpz_mod_ctx_t[1]; typedef fmpz_mat_struct fmpz_mod_mat_struct; typedef fmpz_mod_mat_struct fmpz_mod_mat_t[1]; typedef struct { fmpz * coeffs; slong alloc; slong length; } fmpz_mod_poly_struct; typedef fmpz_mod_poly_struct fmpz_mod_poly_t[1]; typedef struct { fmpz_mod_poly_struct * poly; slong *exp; slong num; slong alloc; } fmpz_mod_poly_factor_struct; typedef fmpz_mod_poly_factor_struct fmpz_mod_poly_factor_t[1]; typedef struct { fmpz * coeffs; ulong * exps; slong length; flint_bitcnt_t bits; /* number of bits per exponent */ slong coeffs_alloc; /* abs size in mp_limb_t units */ slong exps_alloc; /* abs size in ulong units */ } fmpz_mod_mpoly_struct; typedef fmpz_mod_mpoly_struct fmpz_mod_mpoly_t[1]; typedef struct { fmpz_t constant; fmpz_mod_mpoly_struct * poly; fmpz * exp; slong num; slong alloc; } fmpz_mod_mpoly_factor_struct; typedef fmpz_mod_mpoly_factor_struct fmpz_mod_mpoly_factor_t[1]; #ifdef __cplusplus } #endif #endif /* FMPZ_MOD_TYPES_H */ flint-3.1.3/src/fmpz_mod_vec.h000066400000000000000000000041241461254215100162440ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_VEC_H #define FMPZ_MOD_VEC_H #ifdef FMPZ_MOD_VEC_INLINES_C #define FMPZ_MOD_VEC_INLINE #else #define FMPZ_MOD_VEC_INLINE static inline \ error fmpz_mod_vec/inlines.c does not exist #endif #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif void _fmpz_mod_vec_set_fmpz_vec(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_neg(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_add(fmpz * a, const fmpz * b, const fmpz * c, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_sub(fmpz * a, const fmpz * b, const fmpz * c, slong n, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_scalar_mul_fmpz_mod(fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_scalar_addmul_fmpz_mod(fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_mul(fmpz * A, const fmpz * B, const fmpz * C, slong len, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_scalar_div_fmpz_mod(fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_dot(fmpz_t d, const fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx); void _fmpz_mod_vec_dot_rev(fmpz_t r, const fmpz * a, const fmpz * b, slong len, const fmpz_mod_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mod_vec/000077500000000000000000000000001461254215100160725ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mod_vec/add.c000066400000000000000000000012071461254215100167660ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_vec.h" void _fmpz_mod_vec_add(fmpz * a, const fmpz * b, const fmpz * c, slong n, const fmpz_mod_ctx_t ctx) { while (--n >= 0) fmpz_mod_add(a + n, b + n, c + n, ctx); } flint-3.1.3/src/fmpz_mod_vec/dot.c000066400000000000000000000016141461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_vec.h" #include "fmpz_mod_vec.h" void _fmpz_mod_vec_dot(fmpz_t d, const fmpz * a, const fmpz * b, slong len, const fmpz_mod_ctx_t ctx) { _fmpz_vec_dot(d, a, b, len); fmpz_mod_set_fmpz(d, d, ctx); } void _fmpz_mod_vec_dot_rev(fmpz_t r, const fmpz * a, const fmpz * b, slong len, const fmpz_mod_ctx_t ctx) { _fmpz_vec_dot_general(r, NULL, 0, a, b, 1, len); fmpz_mod_set_fmpz(r, r, ctx); } flint-3.1.3/src/fmpz_mod_vec/mul.c000066400000000000000000000012031461254215100170270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_vec.h" void _fmpz_mod_vec_mul( fmpz * A, const fmpz * B, const fmpz * C, slong len, const fmpz_mod_ctx_t ctx) { for (len--; len >= 0; len--) fmpz_mod_mul(A + len, B + len, C + len, ctx); } flint-3.1.3/src/fmpz_mod_vec/neg.c000066400000000000000000000012131461254215100170040ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_vec.h" void _fmpz_mod_vec_neg(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) { for (len--; len >= 0; len--) fmpz_mod_neg(A + len, B + len, ctx); } flint-3.1.3/src/fmpz_mod_vec/scalar.c000066400000000000000000000030121461254215100174770ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" void _fmpz_mod_vec_scalar_addmul_fmpz_mod( fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx) { if (fmpz_is_zero(c)) { } else if (fmpz_is_one(c)) { _fmpz_mod_vec_add(A, A, B, len, ctx); } else { for (len--; len >= 0; len--) { fmpz_addmul(A + len, B + len, c); fmpz_mod_set_fmpz(A + len, A + len, ctx); } } } void _fmpz_mod_vec_scalar_div_fmpz_mod( fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx) { fmpz_t d; fmpz_init(d); fmpz_mod_inv(d, c, ctx); for (len--; len >= 0; len--) fmpz_mod_mul(A + len, B + len, d, ctx); fmpz_clear(d); } void _fmpz_mod_vec_scalar_mul_fmpz_mod( fmpz * A, const fmpz * B, slong len, const fmpz_t c, const fmpz_mod_ctx_t ctx) { if (fmpz_is_one(c)) { _fmpz_vec_set(A, B, len); } else { for (len--; len >= 0; len--) fmpz_mod_mul(A + len, B + len, c, ctx); } } flint-3.1.3/src/fmpz_mod_vec/set_fmpz_vec.c000066400000000000000000000034451461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "thread_support.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "long_extras.h" typedef struct { fmpz * res; const fmpz * vec; const fmpz_mod_ctx_struct * ctx; } work_t; static void worker(slong i, void * args) { work_t * w = (work_t *) args; fmpz_mod_set_fmpz(w->res + i, w->vec + i, w->ctx); } void _fmpz_mod_vec_set_fmpz_vec_threaded(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) { work_t work[1]; work->res = A; work->vec = B; work->ctx = ctx; flint_parallel_do(worker, work, len, 0, FLINT_PARALLEL_UNIFORM); } void _fmpz_mod_vec_set_fmpz_vec(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) { if (len >= 2) { slong bits = fmpz_bits(fmpz_mod_ctx_modulus(ctx)); if ((len >= 10000 || (bits >= 20000 && fabs((double) _fmpz_vec_max_bits(B, len)) >= 20000) || (len * (double) bits >= 400000 && len * fabs((double)_fmpz_vec_max_bits(B, len)) >= 400000)) && flint_get_num_threads() >= 2) { _fmpz_mod_vec_set_fmpz_vec_threaded(A, B, len, ctx); return; } } for (len--; len >= 0; len--) fmpz_mod_set_fmpz(A + len, B + len, ctx); } flint-3.1.3/src/fmpz_mod_vec/sub.c000066400000000000000000000012071461254215100170270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include "fmpz_mod_vec.h" void _fmpz_mod_vec_sub(fmpz * a, const fmpz * b, const fmpz * c, slong n, const fmpz_mod_ctx_t ctx) { while (--n >= 0) fmpz_mod_sub(a + n, b + n, c + n, ctx); } flint-3.1.3/src/fmpz_mpoly.h000066400000000000000000001533731461254215100160030ustar00rootroot00000000000000/* Copyright (C) 2016-2017 William Hart Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MPOLY_H #define FMPZ_MPOLY_H #ifdef FMPZ_MPOLY_INLINES_C #define FMPZ_MPOLY_INLINE #else #define FMPZ_MPOLY_INLINE static inline #endif #include "mpoly_types.h" #ifdef __cplusplus extern "C" { #endif FMPZ_MPOLY_INLINE fmpz * fmpz_mpoly_term_coeff_ref(fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(i < A->length); return A->coeffs + i; } FMPZ_MPOLY_INLINE fmpz * fmpz_mpoly_leadcoeff(const fmpz_mpoly_t A) { FLINT_ASSERT(A->length > 0); return A->coeffs + 0; } /* Internal type definitions *************************************************/ /* fmpz_mpoly_univar_t sparse univariates with multivariate coefficients */ typedef struct { fmpz_mpoly_struct * coeffs; /* multivariate coefficients */ fmpz * exps; slong alloc; slong length; } fmpz_mpoly_univar_struct; typedef fmpz_mpoly_univar_struct fmpz_mpoly_univar_t[1]; /* fmpz_mpolyd_t A dense mpoly is stored as a flat array of coefficients. Suppose deg_bounds = {r0, r1, r2}. The coefficient of the monomial with exponents {e0, e1, e2} is stored at the coefficient of index e2 + r2*(e1 + r1*(e0 + r0*0)) */ typedef struct { slong nvars; slong degb_alloc; slong * deg_bounds; slong length; /* usage is inconsistent currently */ slong coeff_alloc; fmpz * coeffs; } fmpz_mpolyd_struct; typedef fmpz_mpolyd_struct fmpz_mpolyd_t[1]; /* Context object ************************************************************/ void fmpz_mpoly_ctx_init(fmpz_mpoly_ctx_t ctx, slong nvars, const ordering_t ord); void fmpz_mpoly_ctx_init_rand(fmpz_mpoly_ctx_t mctx, flint_rand_t state, slong max_nvars); void fmpz_mpoly_ctx_clear(fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE slong fmpz_mpoly_ctx_nvars(const fmpz_mpoly_ctx_t ctx) { return ctx->minfo->nvars; } FMPZ_MPOLY_INLINE ordering_t fmpz_mpoly_ctx_ord(const fmpz_mpoly_ctx_t ctx) { return ctx->minfo->ord; } /* Memory management ********************************************************/ void fmpz_mpoly_init(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_init2(fmpz_mpoly_t A, slong alloc, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_init3(fmpz_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_realloc(fmpz ** Acoeff, ulong ** Aexp, slong * Aalloc, slong len, slong N); void fmpz_mpoly_realloc(fmpz_mpoly_t A, slong alloc, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_fit_length(fmpz ** Acoeff, ulong ** Aexp, slong * Aalloc, slong len, slong N); void fmpz_mpoly_fit_length(fmpz_mpoly_t A, slong len, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_fit_length_reset_bits(fmpz_mpoly_t A, slong len, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_clear(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_set_length(fmpz_mpoly_t A, slong newlen, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_truncate(fmpz_mpoly_t A, slong newlen, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_fit_bits(fmpz_mpoly_t A, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx); /* Input/output **************************************************************/ int fmpz_mpoly_set_str_pretty(fmpz_mpoly_t A, const char * str, const char ** x, const fmpz_mpoly_ctx_t ctx); char * _fmpz_mpoly_get_str_pretty(const fmpz * poly, const ulong * exps, slong len, const char ** x, slong bits, const mpoly_ctx_t mctx); char * fmpz_mpoly_get_str_pretty(const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx); #ifdef FLINT_HAVE_FILE int _fmpz_mpoly_fprint_pretty(FILE * file, const fmpz * poly, const ulong * exps, slong len, const char ** x_in, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int fmpz_mpoly_fprint_pretty(FILE * file, const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx); #endif int _fmpz_mpoly_print_pretty(const fmpz * poly, const ulong * exps, slong len, const char ** x, slong bits, const mpoly_ctx_t mctx); int fmpz_mpoly_print_pretty(const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx); /* Basic manipulation *******************************************************/ void fmpz_mpoly_gen(fmpz_mpoly_t poly, slong i, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_is_gen(const fmpz_mpoly_t poly, slong k, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_set(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong n, slong N); void fmpz_mpoly_set(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); int _fmpz_mpoly_equal(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong n, slong N); int fmpz_mpoly_equal(const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE void fmpz_mpoly_swap(fmpz_mpoly_t A, fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { FLINT_SWAP(fmpz_mpoly_struct, *A, *B); } FMPZ_MPOLY_INLINE int _fmpz_mpoly_fits_small(const fmpz * poly, slong len) { slong i; for (i = 0; i < len; i++) { if (COEFF_IS_MPZ(poly[i])) return 0; } return 1; } slong fmpz_mpoly_max_bits(const fmpz_mpoly_t A); /* Constants *****************************************************************/ int fmpz_mpoly_is_fmpz(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_fmpz(fmpz_t c, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_fmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_ui(fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_si(fmpz_mpoly_t A, slong c, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE void fmpz_mpoly_zero(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_set_length(A, 0, ctx); } FMPZ_MPOLY_INLINE void fmpz_mpoly_one(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_set_ui(A, UWORD(1), ctx); } int fmpz_mpoly_equal_fmpz(const fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_equal_ui(const fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_equal_si(const fmpz_mpoly_t A, slong c, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE int fmpz_mpoly_is_zero(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return A->length == 0; } FMPZ_MPOLY_INLINE int fmpz_mpoly_is_one(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_equal_ui(A, UWORD(1), ctx); } /* Degrees *******************************************************************/ int fmpz_mpoly_degrees_fit_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_degrees_fmpz(fmpz ** degs, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_degrees_si(slong * degs, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx); slong fmpz_mpoly_degree_si(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_total_degree_fits_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_total_degree_fmpz(fmpz_t td, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); slong fmpz_mpoly_total_degree_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_used_vars(int * used, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); /* Coefficients **************************************************************/ void fmpz_mpoly_get_coeff_fmpz_monomial(fmpz_t c, const fmpz_mpoly_t A, const fmpz_mpoly_t M, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_coeff_fmpz_monomial(fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_t M, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_coeff_fmpz_fmpz(fmpz_t c, const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); ulong fmpz_mpoly_get_coeff_ui_fmpz( const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); slong fmpz_mpoly_get_coeff_si_fmpz( const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_coeff_fmpz_ui(fmpz_t c, const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); ulong fmpz_mpoly_get_coeff_ui_ui( const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); slong fmpz_mpoly_get_coeff_si_ui( const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_set_coeff_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_coeff_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_coeff_ui_fmpz(fmpz_mpoly_t A, const ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_coeff_si_fmpz(fmpz_mpoly_t A, const slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_coeff_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_coeff_ui_ui(fmpz_mpoly_t A, const ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_coeff_si_ui(fmpz_mpoly_t A, const slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_coeff_vars_ui(fmpz_mpoly_t C, const fmpz_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpz_mpoly_ctx_t ctx); /* conversion ****************************************************************/ int fmpz_mpoly_is_fmpz_poly(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_get_fmpz_poly(fmpz_poly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_set_fmpz_poly(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz * Bcoeffs, slong Blen, slong var, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_fmpz_poly(fmpz_mpoly_t A, const fmpz_poly_t B, slong v, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_set_fmpz_poly_one_var(fmpz_mpoly_t A, flint_bitcnt_t Aminbits, fmpz * Acoeffs, slong Adeg, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_gen_fmpz_poly(fmpz_mpoly_t res, slong var, const fmpz_poly_t pol, const fmpz_mpoly_ctx_t ctx); /* comparison ****************************************************************/ int fmpz_mpoly_cmp(const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); /* container operations ******************************************************/ int fmpz_mpoly_is_canonical(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE slong fmpz_mpoly_length(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return A->length; } void fmpz_mpoly_resize(fmpz_mpoly_t A, slong new_length, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_term_coeff_fmpz(fmpz_t c, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); ulong fmpz_mpoly_get_term_coeff_ui(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); slong fmpz_mpoly_get_term_coeff_si(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_term_coeff_fmpz(fmpz_mpoly_t A, slong i, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_term_coeff_ui(fmpz_mpoly_t A, slong i, ulong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_term_coeff_si(fmpz_mpoly_t A, slong i, slong c, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_term_exp_fits_ui(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_term_exp_fits_si(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_term_exp_ui(ulong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_term_exp_si(slong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); ulong fmpz_mpoly_get_term_var_exp_ui(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx); slong fmpz_mpoly_get_term_var_exp_si(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_term_exp_fmpz(fmpz_mpoly_t A, slong i, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_set_term_exp_ui(fmpz_mpoly_t A, slong i, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_term(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_term_monomial(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_fmpz_ffmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz *exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz *const *exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_ui_ffmpz(fmpz_mpoly_t A, ulong c, const fmpz *exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, slong c, fmpz *const *exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_si_ffmpz(fmpz_mpoly_t A, slong c, const fmpz *exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_ui_ui(fmpz_mpoly_t A, ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_si_ui(fmpz_mpoly_t A, slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_sort_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_combine_like_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_reverse(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_assert_canonical(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_radix_sort1(fmpz_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); void _fmpz_mpoly_radix_sort(fmpz_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); void _fmpz_mpoly_push_exp_ffmpz(fmpz_mpoly_t A, const fmpz * exp, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_push_exp_pfmpz(fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_push_exp_ui(fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); /* Random generation *********************************************************/ void fmpz_mpoly_randtest_bound(fmpz_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, ulong exp_bound, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_randtest_bounds(fmpz_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, ulong * exp_bounds, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_randtest_bits(fmpz_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, flint_bitcnt_t exp_bits, const fmpz_mpoly_ctx_t ctx); /* Addition/Subtraction ******************************************************/ void fmpz_mpoly_add_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_add_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_add_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_sub_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_sub_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_sub_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_add(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); slong _fmpz_mpoly_add(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong len2, const fmpz * poly3, const ulong * exps3, slong len3, slong N, const ulong * cmpmask); void fmpz_mpoly_sub(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); slong _fmpz_mpoly_sub(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong len2, const fmpz * poly3, const ulong * exps3, slong len3, slong N, const ulong * cmpmask); /* Scalar operations *********************************************************/ void fmpz_mpoly_neg(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_scalar_mul_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_scalar_mul_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_scalar_fmma(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_t D, const fmpz_t e, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_scalar_divexact_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_scalar_divexact_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_scalar_divexact_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_scalar_divides_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_scalar_divides_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_scalar_divides_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); /* Differentiation/Integration ***********************************************/ void fmpz_mpoly_derivative(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_integral(fmpz_mpoly_t A, fmpz_t scale, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ int _fmpz_pow_ui_is_not_feasible(flint_bitcnt_t bbits, ulong e); int _fmpz_pow_fmpz_is_not_feasible(flint_bitcnt_t bbits, const fmpz_t e); int fmpz_mpoly_evaluate_all_fmpz(fmpz_t ev, const fmpz_mpoly_t A, fmpz * const * vals, const fmpz_mpoly_ctx_t ctx); mp_limb_t fmpz_mpoly_evaluate_all_nmod(const fmpz_mpoly_t A, const mp_limb_t * alphas, const fmpz_mpoly_ctx_t ctx, nmod_t fpctx); void fmpz_mpoly_evaluate_all_fmpz_mod(fmpz_t ev, const fmpz_mpoly_t A, const fmpz * alphas, const fmpz_mpoly_ctx_t ctx, const fmpz_mod_ctx_t fpctx); int fmpz_mpoly_evaluate_one_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_t val, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_compose_fmpz_poly(fmpz_poly_t A, const fmpz_mpoly_t B, fmpz_poly_struct * const * C, const fmpz_mpoly_ctx_t ctxB); void _fmpz_mpoly_compose_mat(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mat_t M, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC); int fmpz_mpoly_compose_fmpz_mpoly_geobucket(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC); int fmpz_mpoly_compose_fmpz_mpoly_horner(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC); int fmpz_mpoly_compose_fmpz_mpoly(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC); void fmpz_mpoly_compose_fmpz_mpoly_gen(fmpz_mpoly_t A, const fmpz_mpoly_t B, const slong * c, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC); /* Multiplication ************************************************************/ void fmpz_mpoly_mul(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_mul_monomial(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_mul_johnson(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_mul_heap_threaded(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_mul_array(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_mul_array_threaded(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_mul_dense(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); slong _fmpz_mpoly_mul_johnson(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask); void _fmpz_mpoly_mul_johnson_maxfields(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_mul_heap_threaded_pool_maxfields(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); int _fmpz_mpoly_mul_array_DEG(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx); int _fmpz_mpoly_mul_array_LEX(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx); int _fmpz_mpoly_mul_array_threaded_pool_DEG(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); int _fmpz_mpoly_mul_array_threaded_pool_LEX(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); int _fmpz_mpoly_mul_dense(fmpz_mpoly_t P, const fmpz_mpoly_t A, fmpz * maxAfields, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_ctx_t ctx); /* Powering ******************************************************************/ int fmpz_mpoly_pow_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t k, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_pow_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx); /* Division ******************************************************************/ int fmpz_mpoly_divides(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_divides_monagan_pearce(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); #if FLINT_KNOW_STRONG_ORDER #define fmpz_mpoly_divides_heap_threaded fmpz_mpoly_divides_heap_threaded int fmpz_mpoly_divides_heap_threaded(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); #define _fmpz_mpoly_divides_heap_threaded_pool _fmpz_mpoly_divides_heap_threaded_pool int _fmpz_mpoly_divides_heap_threaded_pool(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); #endif slong _fmpz_mpoly_divides_array(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits); int fmpz_mpoly_divides_array(fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx); int mpoly_divides_select_exps(fmpz_mpoly_t S, fmpz_mpoly_ctx_t zctx, slong nworkers, ulong * Aexp, slong Alen, ulong * Bexp, slong Blen, flint_bitcnt_t bits); slong _fmpz_mpoly_divides_monagan_pearce(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask); void fmpz_mpoly_divrem(fmpz_mpoly_t Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_quasidivrem(fmpz_t scale, fmpz_mpoly_t Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_div(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_quasidiv(fmpz_t scale, fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_divrem_ideal(fmpz_mpoly_struct ** Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, fmpz_mpoly_struct * const * B, slong len, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_quasidivrem_ideal(fmpz_t scale, fmpz_mpoly_struct ** Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, fmpz_mpoly_struct * const * B, slong len, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE void fmpz_mpoly_divexact(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_divides(Q, A, B, ctx)) return; flint_throw(FLINT_ERROR, "fmpz_mpoly_divexact: nonexact division"); } slong _fmpz_mpoly_div_monagan_pearce(fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const ulong * cmpmask); void fmpz_mpoly_div_monagan_pearce(fmpz_mpoly_t q, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx); slong _fmpz_mpoly_divrem_monagan_pearce(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const ulong * cmpmask); void fmpz_mpoly_divrem_monagan_pearce(fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx); slong _fmpz_mpoly_divrem_array(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits); int fmpz_mpoly_divrem_array(fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_quasidivrem_heap(fmpz_t scale, fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_quasidiv_heap(fmpz_t scale, fmpz_mpoly_t q, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx); slong _fmpz_mpoly_divrem_ideal_monagan_pearce(fmpz_mpoly_struct ** polyq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, fmpz_mpoly_struct * const * poly3, ulong * const * exp3, slong len, slong N, slong bits, const fmpz_mpoly_ctx_t ctx, const ulong * cmpmask); void fmpz_mpoly_divrem_ideal_monagan_pearce(fmpz_mpoly_struct ** q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, fmpz_mpoly_struct * const * poly3, slong len, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_quasidivrem_ideal_heap(fmpz_t scale, fmpz_mpoly_struct ** q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, fmpz_mpoly_struct * const * poly3, slong len, const fmpz_mpoly_ctx_t ctx); /* Square root ***************************************************************/ slong _fmpz_mpoly_sqrt_heap(fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * poly2, const ulong * exp2, slong len2, flint_bitcnt_t bits, const mpoly_ctx_t mctx, int check); int fmpz_mpoly_sqrt_heap(fmpz_mpoly_t q, const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx, int check); FMPZ_MPOLY_INLINE int fmpz_mpoly_sqrt(fmpz_mpoly_t q, const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_sqrt_heap(q, poly2, ctx, 1); } FMPZ_MPOLY_INLINE int fmpz_mpoly_is_square(const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) { int res; fmpz_mpoly_t q; fmpz_mpoly_init(q, ctx); res = fmpz_mpoly_sqrt_heap(q, poly2, ctx, 1); fmpz_mpoly_clear(q, ctx); return res; } /* GCD ***********************************************************************/ void fmpz_mpoly_term_content(fmpz_mpoly_t M, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_primitive_part(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_content_vars(fmpz_mpoly_t g, const fmpz_mpoly_t A, slong * vars, slong vars_length, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_gcd(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_gcd_cofactors(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_deflate(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_inflate(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_gcd_hensel(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_gcd_brown(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_gcd_subresultant(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_gcd_zippel(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_gcd_zippel2(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); /* Univariates ***************************************************************/ void fmpz_mpoly_univar_init(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_univar_clear(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_univar_fit_length(fmpz_mpoly_univar_t A, slong length, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_univar_print_pretty(const fmpz_mpoly_univar_t A, const char ** x, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_univar_assert_canonical(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE void fmpz_mpoly_univar_zero(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) { A->length = 0; } void fmpz_mpoly_univar_set_coeff_ui(fmpz_mpoly_univar_t A, ulong e, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_to_univar(fmpz_mpoly_univar_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_from_univar(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_univar_t B, slong var, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_from_univar(fmpz_mpoly_t A, const fmpz_mpoly_univar_t B, slong var, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE void fmpz_mpoly_univar_swap(fmpz_mpoly_univar_t A, fmpz_mpoly_univar_t B, const fmpz_mpoly_ctx_t ctx) { FLINT_SWAP(fmpz_mpoly_univar_struct, *A, *B); } int fmpz_mpoly_univar_degree_fits_si(const fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE slong fmpz_mpoly_univar_length(const fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) { return A->length; } slong fmpz_mpoly_univar_get_term_exp_si(fmpz_mpoly_univar_t A, slong i, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE void fmpz_mpoly_univar_get_term_coeff(fmpz_mpoly_t c, const fmpz_mpoly_univar_t A, slong i, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fmpz_mpoly_set(c, A->coeffs + i, ctx); } FMPZ_MPOLY_INLINE void fmpz_mpoly_univar_swap_term_coeff(fmpz_mpoly_t c, fmpz_mpoly_univar_t A, slong i, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fmpz_mpoly_swap(c, A->coeffs + i, ctx); } int fmpz_mpoly_univar_pseudo_gcd(fmpz_mpoly_univar_t gx, const fmpz_mpoly_univar_t ax, const fmpz_mpoly_univar_t bx, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_univar_resultant(fmpz_mpoly_t d, const fmpz_mpoly_univar_t ax, const fmpz_mpoly_univar_t bx, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_univar_discriminant(fmpz_mpoly_t d, const fmpz_mpoly_univar_t fx, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_resultant(fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_discriminant(fmpz_mpoly_t R, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx); /* Special polynomials */ void fmpz_mpoly_symmetric_gens(fmpz_mpoly_t res, ulong k, slong * vars, slong n, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_symmetric(fmpz_mpoly_t res, ulong k, const fmpz_mpoly_ctx_t ctx); /* Vectors of multivariate polynomials */ typedef struct { fmpz_mpoly_struct * p; slong alloc; slong length; } fmpz_mpoly_vec_struct; typedef fmpz_mpoly_vec_struct fmpz_mpoly_vec_t[1]; #define fmpz_mpoly_vec_entry(vec, i) ((vec)->p + (i)) void fmpz_mpoly_vec_init(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_print(const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_swap(fmpz_mpoly_vec_t x, fmpz_mpoly_vec_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_fit_length(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_clear(fmpz_mpoly_vec_t vec, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_set(fmpz_mpoly_vec_t dest, const fmpz_mpoly_vec_t src, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_append(fmpz_mpoly_vec_t vec, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx); slong fmpz_mpoly_vec_insert_unique(fmpz_mpoly_vec_t vec, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_set_length(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_randtest_not_zero(fmpz_mpoly_vec_t vec, flint_rand_t state, slong len, slong poly_len, slong bits, ulong exp_bound, fmpz_mpoly_ctx_t ctx); /* Ideals and Groenber bases */ void fmpz_mpoly_spoly(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_set_primitive_unique(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_reduction_primitive_part(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_vec_t I, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_vec_is_groebner(const fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_buchberger_naive(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_buchberger_naive_with_limits(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, slong ideal_len_limit, slong poly_len_limit, slong poly_bits_limit, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_autoreduction(fmpz_mpoly_vec_t H, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_vec_autoreduction_groebner(fmpz_mpoly_vec_t H, const fmpz_mpoly_vec_t G, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_vec_is_autoreduced(const fmpz_mpoly_vec_t G, const fmpz_mpoly_ctx_t ctx); /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ void mpoly_void_ring_init_fmpz_mpoly_ctx(mpoly_void_ring_t R, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_pow_fps(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx); void fmpz_mpolyl_lead_coeff(fmpz_mpoly_t c, const fmpz_mpoly_t A, slong num_vars, const fmpz_mpoly_ctx_t ctx); int fmpz_mpolyl_content(fmpz_mpoly_t g, const fmpz_mpoly_t A, slong num_vars, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_to_fmpz_poly_deflate(fmpz_poly_t A, const fmpz_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_from_fmpz_poly_inflate(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_repack_bits(fmpz_mpoly_t A, const fmpz_mpoly_t B, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_repack_bits_inplace(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx); typedef struct _fmpz_mpoly_stripe_struct { char * big_mem; slong big_mem_alloc; slong N; flint_bitcnt_t bits; const ulong * cmpmask; slong * startidx; slong * endidx; ulong * emin; ulong * emax; flint_bitcnt_t coeff_bits; int upperclosed; int flint_small; } fmpz_mpoly_stripe_struct; typedef fmpz_mpoly_stripe_struct fmpz_mpoly_stripe_t[1]; /* mpolyd ********************************************************************/ typedef struct { slong nvars; slong * perm; } fmpz_mpolyd_ctx_struct; typedef fmpz_mpolyd_ctx_struct fmpz_mpolyd_ctx_t[1]; void fmpz_mpolyd_init(fmpz_mpolyd_t poly, slong nvars); void fmpz_mpolyd_fit_length(fmpz_mpolyd_t poly, slong len); void fmpz_mpolyd_clear(fmpz_mpolyd_t poly); /*****************************************************************************/ typedef struct { fmpz * powers; slong length; slong alloc; fmpz_t tmp; } fmpz_pow_cache_t[1]; void fmpz_pow_cache_init(fmpz_pow_cache_t T, const fmpz_t val); void fmpz_pow_cache_clear(fmpz_pow_cache_t T); int fmpz_pow_cache_mulpow_ui(fmpz_t a, const fmpz_t b, ulong k, fmpz_pow_cache_t T); int fmpz_pow_cache_mulpow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t k, fmpz_pow_cache_t T); /*****************************************************************************/ void fmpz_mpoly_to_mpoly_perm_deflate_threaded_pool( fmpz_mpoly_t A, const fmpz_mpoly_ctx_t lctx, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const thread_pool_handle * handles, slong num_handles); void fmpz_mpoly_from_mpoly_perm_inflate( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride); void fmpz_mpoly_height(fmpz_t max, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_heights(fmpz_t max, fmpz_t sum, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); /* geobuckets ****************************************************************/ typedef struct fmpz_mpoly_geobucket { fmpz_mpoly_struct polys[FLINT_BITS/2]; fmpz_mpoly_struct temps[FLINT_BITS/2]; slong length; } fmpz_mpoly_geobucket_struct; typedef fmpz_mpoly_geobucket_struct fmpz_mpoly_geobucket_t[1]; void fmpz_mpoly_geobucket_init(fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_geobucket_clear(fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_geobucket_empty(fmpz_mpoly_t p, fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_geobucket_fit_length(fmpz_mpoly_geobucket_t B, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_geobucket_set(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_geobucket_add(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_geobucket_sub(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx); /* Helpers for array methods *************************************************/ void _fmpz_mpoly_mul_array_chunked_DEG(fmpz_mpoly_t P, const fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong degb, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_mul_array_chunked_LEX(fmpz_mpoly_t P, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const ulong * mults, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_addmul_array1_slong1(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_addmul_array1_slong(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_addmul_array1_slong2(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_addmul_array1_fmpz(fmpz * poly1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_submul_array1_slong(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_submul_array1_slong2(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_submul_array1_slong1(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_submul_array1_fmpz(fmpz * poly1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_submul_array1_slong_1(ulong * poly1, slong d, const ulong exp2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_submul_array1_slong2_1(ulong * poly1, slong d, const ulong exp2, const slong * poly3, const ulong * exp3, slong len3); void _fmpz_mpoly_submul_array1_fmpz_1(fmpz * poly1, const fmpz_t d, ulong exp2, const fmpz * poly3, const ulong * exp3, slong len3); slong fmpz_mpoly_append_array_sm1_LEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, const ulong * mults, slong num, slong array_size, slong top); slong fmpz_mpoly_append_array_sm2_LEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, const ulong * mults, slong num, slong array_size, slong top); slong fmpz_mpoly_append_array_sm3_LEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, const ulong * mults, slong num, slong array_size, slong top); slong fmpz_mpoly_append_array_fmpz_LEX(fmpz_mpoly_t P, slong Plen, fmpz * coeff_array, const ulong * mults, slong num, slong array_size, slong top); slong fmpz_mpoly_append_array_sm1_DEGLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); slong fmpz_mpoly_append_array_sm2_DEGLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); slong fmpz_mpoly_append_array_sm3_DEGLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); slong fmpz_mpoly_append_array_fmpz_DEGLEX(fmpz_mpoly_t P, slong Plen, fmpz * coeff_array, slong top, slong nvars, slong degb); slong fmpz_mpoly_append_array_sm1_DEGREVLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); slong fmpz_mpoly_append_array_sm2_DEGREVLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); slong fmpz_mpoly_append_array_sm3_DEGREVLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); slong fmpz_mpoly_append_array_fmpz_DEGREVLEX(fmpz_mpoly_t P, slong Plen, fmpz * coeff_array, slong top, slong nvars, slong degb); slong _fmpz_mpoly_from_ulong_array(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k); slong _fmpz_mpoly_from_ulong_array2(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k); slong _fmpz_mpoly_from_ulong_array1(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k); slong _fmpz_mpoly_from_fmpz_array(fmpz ** poly1, ulong ** exp1, slong * alloc, fmpz * poly2, const slong * mults, slong num, slong bits, slong k); void _fmpz_mpoly_to_ulong_array2(ulong * p, const fmpz * coeffs, const ulong * exps, slong len); void _fmpz_mpoly_to_ulong_array1(ulong * p, const fmpz * coeffs, const ulong * exps, slong len); void _fmpz_mpoly_to_ulong_array(ulong * p, const fmpz * coeffs, const ulong * exps, slong len); void _fmpz_mpoly_to_fmpz_array(fmpz * p, const fmpz * coeffs, const ulong * exps, slong len); /* Misc arithmetic - has nothing to do with mpoly, should be moved out *******/ void _fmpz_mpoly_add_uiuiui_fmpz(ulong * c, const fmpz_t d); void _fmpz_mpoly_sub_uiuiui_fmpz(ulong * c, const fmpz_t d); FMPZ_MPOLY_INLINE void _fmpz_mpoly_submul_uiuiui_fmpz(ulong * c, slong d1, slong d2) { ulong p[2], p2; smul_ppmm(p[1], p[0], d1, d2); p2 = FLINT_SIGN_EXT(p[1]); sub_dddmmmsss(c[2], c[1], c[0], c[2], c[1], c[0], p2, p[1], p[0]); } FMPZ_MPOLY_INLINE void _fmpz_mpoly_addmul_uiuiui_fmpz(ulong * c, slong d1, slong d2) { ulong p[2], p2; smul_ppmm(p[1], p[0], d1, d2); p2 = FLINT_SIGN_EXT(p[1]); add_sssaaaaaa(c[2], c[1], c[0], c[2], c[1], c[0], p2, p[1], p[0]); } /****************************************************************************** Internal consistency checks ******************************************************************************/ void fmpz_mpoly_remainder_test(const fmpz_mpoly_t r, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_remainder_strongtest(const fmpz_mpoly_t r, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mpoly/000077500000000000000000000000001461254215100156165ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly/add.c000066400000000000000000000175701461254215100165240ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_add1( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, ulong maskhi) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { if ((Bexps[i]^maskhi) > (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if ((Bexps[i]^maskhi) == (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; fmpz_add(Acoeffs + k, Bcoeffs + i, Ccoeffs + j); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { Aexps[k] = Cexps[j]; fmpz_set(Acoeffs + k, Ccoeffs + j); j++; k++; } } while (i < Blen) { Aexps[k] = Bexps[i]; fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { Aexps[k] = Cexps[j]; fmpz_set(Acoeffs + k, Ccoeffs + j); j++; k++; } return k; } slong _fmpz_mpoly_add( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask) { slong i = 0, j = 0, k = 0; if (N == 1) { return _fmpz_mpoly_add1(Acoeffs, Aexps, Bcoeffs, Bexps, Blen, Ccoeffs, Cexps, Clen, cmpmask[0]); } while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_add(Acoeffs + k, Bcoeffs + i, Ccoeffs + j); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_set(Acoeffs + k, Ccoeffs + j); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_set(Acoeffs + k, Ccoeffs + j); j++; k++; } return k; } void fmpz_mpoly_add_inplace(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { slong i, s, new_len, N; slong Alen = A->length; slong Blen = B->length; ulong * Bexps, * cmpmask; int cmp, freeBexps; flint_bitcnt_t Abits; fmpz_mpoly_t T; TMP_INIT; FLINT_ASSERT(A != B); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); TMP_START; if (A->bits <= B->bits) { Abits = B->bits; if (A->bits < B->bits) fmpz_mpoly_repack_bits_inplace(A, Abits, ctx); N = mpoly_words_per_exp(Abits, ctx->minfo); Bexps = B->exps; freeBexps = 0; } else { Abits = A->bits; N = mpoly_words_per_exp(Abits, ctx->minfo); Bexps = (ulong *) flint_malloc(N*Blen*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, Blen, ctx->minfo); freeBexps = 1; } cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); /* We will move s terms from the end of A. The complexity is roughly s from search s from move s + B->length from addition s from move cleanup So as long as 4*s + B->length < A->length + B->length, it is technically a win over the simple T = A + B; swap(A, T) */ for (s = 0; s < Alen/4; s++) { cmp = mpoly_monomial_cmp(A->exps + N*(Alen - s - 1), Bexps + N*0, N, cmpmask); if (cmp >= 0) { s += (cmp == 0); goto doit; } } fmpz_mpoly_init3(T, Alen + Blen, Abits, ctx); T->length = _fmpz_mpoly_add(T->coeffs, T->exps, A->coeffs, A->exps, Alen, B->coeffs, Bexps, Blen, N, cmpmask); fmpz_mpoly_swap(A, T, ctx); fmpz_mpoly_clear(T, ctx); goto cleanup; doit: FLINT_ASSERT(0 <= s && s <= Alen); FLINT_ASSERT(s == 0 || mpoly_monomial_cmp(A->exps + N*(Alen - s), Bexps + N*0, N, cmpmask) <= 0); FLINT_ASSERT(s == Alen || mpoly_monomial_cmp(A->exps + N*(Alen - s - 1), Bexps + N*0, N, cmpmask) > 0); fmpz_mpoly_fit_length(A, Alen + Blen + s, ctx); mpoly_copy_monomials(A->exps + N*(Alen + Blen), A->exps + N*(Alen - s), s, N); _fmpz_vec_swap(A->coeffs + Alen + Blen, A->coeffs + Alen - s, s); new_len = _fmpz_mpoly_add(A->coeffs + Alen - s, A->exps + N*(Alen - s), A->coeffs + (Alen + Blen), A->exps + N*(Alen + Blen), s, B->coeffs, Bexps, Blen, N, cmpmask); for (i = 0; i < s; i++) _fmpz_demote(A->coeffs + Alen + Blen + i); _fmpz_mpoly_set_length(A, Alen - s + new_len, ctx); cleanup: if (freeBexps) flint_free(Bexps); TMP_END; return; } void fmpz_mpoly_add(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong Alen, N; flint_bitcnt_t Abits; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_set(A, C, ctx); return; } else if (fmpz_mpoly_is_zero(C, ctx)) { fmpz_mpoly_set(A, B, ctx); return; } else if (A == B) { if (A == C) _fmpz_vec_add(A->coeffs, A->coeffs, A->coeffs, A->length); else fmpz_mpoly_add_inplace(A, C, ctx); return; } else if (A == C) { fmpz_mpoly_add_inplace(A, B, ctx); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits > C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } fmpz_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); Alen = _fmpz_mpoly_add(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask); _fmpz_mpoly_set_length(A, Alen, ctx); if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fmpz_mpoly/add_fmpz.c000066400000000000000000000051731461254215100175540ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017, 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_add_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { slong i, N; slong Blen = B->length; if (Blen == 0) { fmpz_mpoly_set_fmpz(A, c, ctx); return; } if (!fmpz_is_zero(c)) { N = mpoly_words_per_exp(B->bits, ctx->minfo); if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { fmpz_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); for (i = 0; i < Blen - 1; i++) fmpz_set(A->coeffs + i, B->coeffs + i); for (i = 0; i < Blen*N; i++) A->exps[i] = B->exps[i]; _fmpz_mpoly_set_length(A, B->length, ctx); } fmpz_add(A->coeffs + Blen - 1, B->coeffs + Blen - 1, c); if (fmpz_is_zero(A->coeffs + Blen - 1)) _fmpz_mpoly_set_length(A, Blen - 1, ctx); } else { fmpz_mpoly_fit_length(A, Blen + 1, ctx); if (A != B) { fmpz_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; for (i = 0; i < Blen; i++) fmpz_set(A->coeffs + i, B->coeffs + i); for (i = 0; i < Blen*N; i++) A->exps[i] = B->exps[i]; } for (i = 0; i < N; i++) A->exps[Blen*N + i] = 0; fmpz_set(A->coeffs + Blen, c); _fmpz_mpoly_set_length(A, Blen + 1, ctx); } } else if (A != B) { fmpz_mpoly_set(A, B, ctx); } } void fmpz_mpoly_add_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, c); fmpz_mpoly_add_fmpz(A, B, t, ctx); fmpz_clear(t); } void fmpz_mpoly_add_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_si(t, c); fmpz_mpoly_add_fmpz(A, B, t, ctx); fmpz_clear(t); } flint-3.1.3/src/fmpz_mpoly/buchberger_naive.c000066400000000000000000000152531461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" /* Index pairs (for Buchberger algorithm) */ typedef struct { slong a; slong b; } pair_t; typedef struct { pair_t * pairs; slong length; slong alloc; } pairs_struct; typedef pairs_struct pairs_t[1]; static void pairs_init(pairs_t vec) { vec->pairs = NULL; vec->length = 0; vec->alloc = 0; } static void pairs_fit_length(pairs_t vec, slong len) { if (len > vec->alloc) { if (len < 2 * vec->alloc) len = 2 * vec->alloc; vec->pairs = flint_realloc(vec->pairs, len * sizeof(pair_t)); vec->alloc = len; } } static void pairs_clear(pairs_t vec) { flint_free(vec->pairs); } static void pairs_append(pairs_t vec, slong i, slong j) { pairs_fit_length(vec, vec->length + 1); vec->pairs[vec->length].a = i; vec->pairs[vec->length].b = j; vec->length++; } /* static void pairs_insert_unique(pairs_t vec, slong i, slong j) { slong k; for (k = 0; k < vec->length; k++) { if (vec->pairs[k].a == i && vec->pairs[k].b == j) return; } pairs_append(vec, i, j); } */ static pair_t fmpz_mpoly_select_pop_pair(pairs_t pairs, const fmpz_mpoly_vec_t G, const fmpz_mpoly_ctx_t ctx) { slong len, choice, nvars; pair_t result; nvars = ctx->minfo->nvars; len = pairs->length; choice = 0; if (len > 1) { slong i, j, a, b; ulong * exp; ulong * tmp; ulong * lcm; ulong * best_lcm; ulong l, total; int best; exp = flint_malloc(sizeof(ulong) * G->length * nvars); lcm = flint_malloc(sizeof(ulong) * (nvars + 1)); tmp = flint_malloc(sizeof(ulong) * (nvars + 1)); best_lcm = flint_malloc(sizeof(ulong) * (nvars + 1)); for (i = 0; i <= nvars; i++) best_lcm[i] = UWORD_MAX; for (i = 0; i < G->length; i++) fmpz_mpoly_get_term_exp_ui(exp + i * nvars, G->p + i, 0, ctx); for (i = 0; i < len; i++) { a = pairs->pairs[i].a; b = pairs->pairs[i].b; total = 0; best = 1; if (ctx->minfo->ord == ORD_LEX) { for (j = 0; j < nvars; j++) { l = FLINT_MAX(exp[a * nvars + j], exp[b * nvars + j]); if (l > best_lcm[j]) { best = 0; break; } lcm[j] = l; total += l; /* total degree */ } } else /* todo: correct order */ { for (j = 0; j < nvars; j++) { l = FLINT_MAX(exp[a * nvars + j], exp[b * nvars + j]); total += l; /* total degree */ if (total >= best_lcm[j]) { best = 0; break; } lcm[j] = l; } } if (best) { for (j = 0; j < nvars; j++) best_lcm[j] = lcm[j]; best_lcm[nvars] = total; choice = i; } } flint_free(exp); flint_free(tmp); flint_free(lcm); flint_free(best_lcm); } result = pairs->pairs[choice]; pairs->pairs[choice] = pairs->pairs[pairs->length - 1]; pairs->length--; return result; } static int within_limits(const fmpz_mpoly_t poly, slong poly_len_limit, slong poly_bits_limit, const fmpz_mpoly_ctx_t ctx) { slong bits; if (fmpz_mpoly_length(poly, ctx) > poly_len_limit) return 0; bits = fmpz_mpoly_max_bits(poly); bits = FLINT_ABS(bits); if (bits > poly_bits_limit) return 0; return 1; } static int fmpz_mpoly_disjoint_lt(const fmpz_mpoly_t f, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx) { int result; slong i, nvars; ulong * exp1, * exp2; nvars = ctx->minfo->nvars; exp1 = flint_malloc(2 * nvars * sizeof(ulong)); exp2 = exp1 + nvars; fmpz_mpoly_get_term_exp_ui(exp1, f, 0, ctx); fmpz_mpoly_get_term_exp_ui(exp2, g, 0, ctx); result = 1; for (i = 0; i < nvars && result; i++) if (exp1[i] && exp2[i]) result = 0; flint_free(exp1); return result; } int fmpz_mpoly_buchberger_naive_with_limits(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, slong ideal_len_limit, slong poly_len_limit, slong poly_bits_limit, const fmpz_mpoly_ctx_t ctx) { pairs_t B; fmpz_mpoly_t h; slong i, j, index_h; pair_t pair; int success; fmpz_mpoly_vec_set_primitive_unique(G, F, ctx); if (G->length <= 1) return 1; if (G->length >= ideal_len_limit) return 0; for (i = 0; i < G->length; i++) if (!within_limits(fmpz_mpoly_vec_entry(G, i), poly_len_limit, poly_bits_limit, ctx)) return 0; pairs_init(B); fmpz_mpoly_init(h, ctx); for (i = 0; i < G->length; i++) for (j = i + 1; j < G->length; j++) if (!fmpz_mpoly_disjoint_lt(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, j), ctx)) pairs_append(B, i, j); success = 1; while (B->length != 0) { pair = fmpz_mpoly_select_pop_pair(B, G, ctx); fmpz_mpoly_spoly(h, fmpz_mpoly_vec_entry(G, pair.a), fmpz_mpoly_vec_entry(G, pair.b), ctx); fmpz_mpoly_reduction_primitive_part(h, h, G, ctx); if (!fmpz_mpoly_is_zero(h, ctx)) { /* printf("h stats %ld, %ld, %ld\n", h->length, h->bits, G->length); */ if (G->length >= ideal_len_limit || !within_limits(h, poly_len_limit, poly_bits_limit, ctx)) { success = 0; break; } index_h = G->length; fmpz_mpoly_vec_append(G, h, ctx); for (i = 0; i < index_h; i++) if (!fmpz_mpoly_disjoint_lt(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, index_h), ctx)) pairs_append(B, i, index_h); } } fmpz_mpoly_clear(h, ctx); pairs_clear(B); return success; } void fmpz_mpoly_buchberger_naive(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_buchberger_naive_with_limits(G, F, WORD_MAX, WORD_MAX, WORD_MAX, ctx); } flint-3.1.3/src/fmpz_mpoly/clear.c000066400000000000000000000012051461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_clear(fmpz_mpoly_t poly, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < poly->alloc; i++) _fmpz_demote(poly->coeffs + i); flint_free(poly->coeffs); flint_free(poly->exps); } flint-3.1.3/src/fmpz_mpoly/cmp.c000066400000000000000000000022401461254215100165370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_cmp(const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int cmp; slong i; slong length = A->length; fmpz * Acoeffs = A->coeffs; fmpz * Bcoeffs = B->coeffs; if (A->length != B->length) return A->length < B->length ? -1 : 1; if (length <= 0) return 0; cmp = mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, length, ctx->minfo); if (cmp != 0) return cmp; for (i = 0; i < length; i++) { cmp = fmpz_cmp(Acoeffs + i, Bcoeffs + i); if (cmp != 0) return cmp < 0 ? -1 : 1; } return 0; } flint-3.1.3/src/fmpz_mpoly/combine_like_terms.c000066400000000000000000000027161461254215100216220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* assuming that the exponents are valid and sorted, put the polynomial in canonical form i.e. 2*x^e + 3*x^e -> 5x^e 2*x^e - 2*x^e -> 0 */ void fmpz_mpoly_combine_like_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong in, out, N = mpoly_words_per_exp(A->bits, ctx->minfo); out = -WORD(1); for (in = WORD(0); in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= WORD(0) && mpoly_monomial_equal(A->exps + N*out, A->exps + N*in, N)) { fmpz_add(A->coeffs + out, A->coeffs + out, A->coeffs + in); } else { if (out < WORD(0) || !fmpz_is_zero(A->coeffs + out)) out++; if (out != in) { mpoly_monomial_set(A->exps + N*out, A->exps + N*in, N); fmpz_swap(A->coeffs + out, A->coeffs + in); } } } if (out < WORD(0) || !fmpz_is_zero(A->coeffs + out)) out++; _fmpz_mpoly_set_length(A, out, ctx); } flint-3.1.3/src/fmpz_mpoly/compose_fmpz_mpoly.c000066400000000000000000000036041461254215100217060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* evaluate B(xbar) at xbar = C */ int fmpz_mpoly_compose_fmpz_mpoly(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) { slong i; fmpz_mat_t M; FLINT_ASSERT(A != B); if (B->length == 0) { fmpz_mpoly_zero(A, ctxAC); return 1; } fmpz_mat_init(M, ctxAC->minfo->nfields + 1, ctxB->minfo->nfields); fmpz_mat_zero(M); for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) goto matrix_no_good; if (C[i]->length == 0) { mpoly_compose_mat_fill_column(M, NULL, 0, i, ctxB->minfo, ctxAC->minfo); } else { if (!fmpz_is_one(C[i]->coeffs + 0)) goto matrix_no_good; mpoly_compose_mat_fill_column(M, C[i]->exps, C[i]->bits, i, ctxB->minfo, ctxAC->minfo); } } _fmpz_mpoly_compose_mat(A, B, M, ctxB, ctxAC); fmpz_mat_clear(M); return 1; matrix_no_good: fmpz_mat_clear(M); for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) { return fmpz_mpoly_compose_fmpz_mpoly_horner(A, B, C, ctxB, ctxAC); } } return fmpz_mpoly_compose_fmpz_mpoly_geobucket(A, B, C, ctxB, ctxAC); } flint-3.1.3/src/fmpz_mpoly/compose_fmpz_mpoly_gen.c000066400000000000000000000024121461254215100225330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* evaluate B(x_1,...,x_n) at x_i = y_c[i], y_j are vars of ctxAC */ void fmpz_mpoly_compose_fmpz_mpoly_gen(fmpz_mpoly_t A, const fmpz_mpoly_t B, const slong * c, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) { fmpz_mat_t M; if (B->length == 0) { fmpz_mpoly_zero(A, ctxAC); return; } fmpz_mat_init(M, ctxAC->minfo->nfields + 1, ctxB->minfo->nfields); mpoly_compose_mat_gen(M, c, ctxB->minfo, ctxAC->minfo); if (A == B) { fmpz_mpoly_t T; fmpz_mpoly_init(T, ctxAC); _fmpz_mpoly_compose_mat(T, B, M, ctxB, ctxAC); fmpz_mpoly_swap(A, T, ctxAC); fmpz_mpoly_clear(T, ctxAC); } else { _fmpz_mpoly_compose_mat(A, B, M, ctxB, ctxAC); } fmpz_mat_clear(M); return; } flint-3.1.3/src/fmpz_mpoly/compose_fmpz_mpoly_geobucket.c000066400000000000000000000035531461254215100237410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* evaluate B(xbar) at xbar = C */ int fmpz_mpoly_compose_fmpz_mpoly_geobucket(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) { int success = 1; slong i, j; slong Blen = B->length; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fmpz_mpoly_t U, V, W; fmpz_mpoly_geobucket_t T; fmpz * e; fmpz_mpoly_init(U, ctxAC); fmpz_mpoly_init(V, ctxAC); fmpz_mpoly_init(W, ctxAC); fmpz_mpoly_geobucket_init(T, ctxAC); e = _fmpz_vec_init(ctxB->minfo->nvars); for (i = 0; success && i < Blen; i++) { fmpz_mpoly_set_fmpz(U, Bcoeff + i, ctxAC); mpoly_get_monomial_ffmpz(e, Bexp + BN*i, Bbits, ctxB->minfo); for (j = 0; j < ctxB->minfo->nvars; j++) { success = success && fmpz_mpoly_pow_fmpz(V, C[j], e + j, ctxAC); fmpz_mpoly_mul(W, U, V, ctxAC); fmpz_mpoly_swap(U, W, ctxAC); } fmpz_mpoly_geobucket_add(T, U, ctxAC); } if (success) fmpz_mpoly_geobucket_empty(A, T, ctxAC); fmpz_mpoly_clear(U, ctxAC); fmpz_mpoly_clear(V, ctxAC); fmpz_mpoly_clear(W, ctxAC); fmpz_mpoly_geobucket_clear(T, ctxAC); _fmpz_vec_clear(e, ctxB->minfo->nvars); return success; } flint-3.1.3/src/fmpz_mpoly/compose_fmpz_mpoly_horner.c000066400000000000000000000264021461254215100232640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* The conversion to Horner form can be stated as recursive. However, the call stack has depth proportial to the length of the input polynomial in the worst case. Therefore, we must convert it to an iterative algorithm. The procedure is HornerForm(f): if f is simple to evaluate return eval(f) else choose a variable v and the smallest non zero exponent e appearing in the terms of f write f = q * v^e + r where r is independent of the variable v return HornerForm(q) * v^e + HornerForm(r) */ typedef struct { slong f; slong r; slong v_var; fmpz_t v_exp; /* will be managed as stack grows / shrinks */ int ret; } stack_entry_struct; typedef stack_entry_struct stack_entry_t[1]; /* A = A * X^pow */ static int _fmpz_mpoly_pmul(fmpz_mpoly_t A, const fmpz_mpoly_t X, const fmpz_t pow, fmpz_mpoly_t T, const fmpz_mpoly_ctx_t ctx) { ulong p; FLINT_ASSERT(fmpz_sgn(pow) > 0); if (!fmpz_fits_si(pow)) { if (!fmpz_mpoly_pow_fmpz(T, X, pow, ctx)) { fmpz_mpoly_zero(A, ctx); return 0; } fmpz_mpoly_mul(A, A, T, ctx); return 1; } p = fmpz_get_ui(pow); if (X->length <= WORD(2) || A->length/p < X->length) { if (!fmpz_mpoly_pow_ui(T, X, p, ctx)) { fmpz_mpoly_zero(A, ctx); return 0; } fmpz_mpoly_mul(A, A, T, ctx); } else { while (p >= 1) { fmpz_mpoly_mul(T, A, X, ctx); fmpz_mpoly_swap(A, T, ctx); p--; } } return 1; } /* evaluate B(xbar) at xbar = C */ int fmpz_mpoly_compose_fmpz_mpoly_horner(fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz_mpoly_struct * const * C, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) { int success = 1; int ret; slong nvars = ctxB->minfo->nvars; slong i, j, k, cur, next, f, r, f_prev, r_prev, v; slong sp, rp; stack_entry_struct * stack; fmpz_mpoly_struct * regs; fmpz_mpoly_t temp; slong * rtypes; ulong totalcounts, maxcounts; ulong * counts; slong Blen = B->length; slong * Blist; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fmpz * Buexp; fmpz * mdegs; fmpz_t score, tz; TMP_INIT; if (Blen < 1) { fmpz_mpoly_zero(A, ctxAC); return 1; } if (nvars < 1) { FLINT_ASSERT(Blen == 1); fmpz_mpoly_set_fmpz(A, B->coeffs + 0, ctxAC); return 1; } FLINT_ASSERT(A != B); FLINT_ASSERT(Blen > 0); TMP_START; fmpz_init(score); fmpz_init(tz); /* unpack B exponents */ Buexp = _fmpz_vec_init(nvars*Blen); for (i = 0; i < Blen; i++) mpoly_get_monomial_ffmpz(Buexp + nvars*i, Bexp + BN*i, Bbits, ctxB->minfo); counts = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); mdegs = _fmpz_vec_init(nvars); /* stack */ sp = -WORD(1); /* start with empty stack */ stack = (stack_entry_struct *) TMP_ALLOC(nvars*(Blen + 1)*sizeof(stack_entry_struct)); Blist = (slong *) TMP_ALLOC(Blen*sizeof(slong)); /* registers of polynomials */ rp = 0; rtypes = (slong *) TMP_ALLOC((nvars + 1)*sizeof(slong)); regs = (fmpz_mpoly_struct *) TMP_ALLOC(nvars*sizeof(fmpz_mpoly_struct)); for (i = 0; i < nvars; i++) fmpz_mpoly_init(regs + i, ctxAC); fmpz_mpoly_init(temp, ctxAC); /* polynomials will be stored as link lists */ for (i = 0; i + 1 < Blen; i++) Blist[i] = i + 1; Blist[i] = -WORD(1); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 0; (stack + sp)->f = 0; HornerForm: f = (stack + sp)->f; FLINT_ASSERT(f != -WORD(1)); /* f is not supposed to be zero */ /* obtain a count of the number of terms containing each variable */ for (i = 0; i < nvars; i++) { counts[i] = 0; fmpz_set_si(mdegs + i, -WORD(1)); } for (j = f; j != -WORD(1); j = Blist[j]) { for (i = 0; i < nvars; i++) { if (!fmpz_is_zero(Buexp + nvars*j + i )) { counts[i]++; if (fmpz_sgn(mdegs + i) < 0 || fmpz_cmp(mdegs + i, Buexp + nvars*j + i) > 0) { fmpz_set(mdegs + i, Buexp + nvars*j + i); } } } } totalcounts = 0; maxcounts = 0; v = -WORD(1); for (i = 0; i < nvars; i++) { maxcounts = FLINT_MAX(maxcounts, counts[i]); totalcounts += counts[i]; if (counts[i] != 0) v = i; } /* handle simple cases */ if (totalcounts == 0) { FLINT_ASSERT(Blist[f] == -WORD(1)); /* f should have had only one term */ rtypes[rp] = f; goto HornerFormReturn; } else if (totalcounts == 1) { FLINT_ASSERT(!fmpz_is_zero(Buexp + nvars*f + v)); /* this term should not be a scalar */ if (!fmpz_mpoly_pow_fmpz(regs + rp, C[v], Buexp + nvars*f + v, ctxAC)) { success = 0; } fmpz_mpoly_scalar_mul_fmpz(regs + rp, regs + rp, Bcoeff + f, ctxAC); if (Blist[f] != -WORD(1)) /* if f has a second term */ { /* this term should be a scalar */ FLINT_ASSERT(fmpz_is_zero(Buexp + nvars*Blist[f] + v)); fmpz_mpoly_add_fmpz(regs + rp, regs + rp, Bcoeff + Blist[f], ctxAC); } rtypes[rp] = -WORD(1); goto HornerFormReturn; } /* pick best power to pull out */ k = 0; if (maxcounts == 1) { fmpz_set_si(score, -WORD(1)); for (i = 0; i < nvars; i++) { if (counts[i] == 1 && (fmpz_sgn(score) < 0 || fmpz_cmp(mdegs + i, score) < 0)) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_set(score, mdegs + i); k = i; } } } else { fmpz_zero(score); for (i = 0; i < nvars; i++) { if (counts[i] > 1) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_mul_ui(tz, mdegs + i, counts[i] - 1); if (fmpz_cmp(tz, score) > 0) { fmpz_swap(score, tz); k = i; } } } } /* set variable power v */ (stack + sp)->v_var = k; fmpz_set((stack + sp)->v_exp, mdegs + k); /* scan f and split into q and v with f = q*v + r then set f = q */ r = -WORD(1); cur = f; f_prev = -WORD(1); r_prev = -WORD(1); while (cur != -WORD(1)) { next = Blist[cur]; if (fmpz_is_zero(Buexp + nvars*cur + k)) { if (f_prev == -WORD(1)) f = Blist[cur]; else Blist[f_prev] = Blist[cur]; if (r_prev == -WORD(1)) r = cur; else Blist[r_prev] = cur; Blist[cur] = -WORD(1); r_prev = cur; } else { /* mdegs[k] should be minimum non zero exponent */ fmpz_sub(Buexp + nvars*cur + k, Buexp + nvars*cur + k, mdegs + k); FLINT_ASSERT(fmpz_sgn(Buexp + nvars*cur + k) >= 0); f_prev = cur; } cur = next; } (stack + sp)->r = r; /* convert the quotient */ sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 1; (stack + sp)->f = f; goto HornerForm; HornerForm1: /* convert the remainder */ r = (stack + sp)->r; if (r != -WORD(1)) { /* remainder is non zero */ rp++; FLINT_ASSERT(0 <= rp && rp <= nvars); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 2; (stack + sp)->f = r; goto HornerForm; HornerForm2: if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] == -WORD(1)) { /* both quotient and remainder are polynomials */ if (!_fmpz_mpoly_pmul(regs + rp - 1, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } fmpz_mpoly_add(temp, regs + rp - 1, regs + rp, ctxAC); fmpz_mpoly_swap(temp, regs + rp - 1, ctxAC); } else if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] != -WORD(1)) { /* quotient is a polynomial, remainder is a scalar */ if (!_fmpz_mpoly_pmul(regs + rp - 1, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } fmpz_mpoly_add_fmpz(regs + rp - 1, regs + rp - 1, Bcoeff + rtypes[rp], ctxAC); } else if (rtypes[rp - 1] != -WORD(1) && rtypes[rp] == -WORD(1)) { /* quotient is a scalar, remainder is a polynomial */ if (!fmpz_mpoly_pow_fmpz(temp, C[(stack + sp)->v_var], (stack + sp)->v_exp, ctxAC)) { success = 0; } fmpz_mpoly_scalar_mul_fmpz(temp, temp, Bcoeff + rtypes[rp - 1], ctxAC); fmpz_mpoly_add(regs + rp - 1, temp, regs + rp, ctxAC); } else { /* quotient is a scalar, remainder is a scalar */ FLINT_ASSERT(0); /* this should have been handled by simple case */ } rp--; FLINT_ASSERT(0 <= rp && rp <= nvars); } else { /* remainder is zero */ FLINT_ASSERT(rtypes[rp] == -WORD(1)); /* quotient is not a scalar */ /* quotient is a polynomial */ if (!_fmpz_mpoly_pmul(regs + rp, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } } rtypes[rp] = -WORD(1); HornerFormReturn: if (!success) { while (sp >= 0) { fmpz_clear((stack + sp)->v_exp); sp--; } goto cleanup; } ret = (stack + sp)->ret; fmpz_clear((stack + sp)->v_exp); sp--; if (ret == 1) goto HornerForm1; if (ret == 2) goto HornerForm2; FLINT_ASSERT(rp == 0); FLINT_ASSERT(sp == -WORD(1)); if (rtypes[rp] == -WORD(1)) { fmpz_mpoly_swap(A, regs + rp, ctxAC); } else { fmpz_mpoly_set_fmpz(A, Bcoeff + rtypes[rp], ctxAC); } cleanup: for (i = 0; i < nvars; i++) fmpz_mpoly_clear(regs + i, ctxAC); fmpz_mpoly_clear(temp, ctxAC); fmpz_clear(score); fmpz_clear(tz); _fmpz_vec_clear(mdegs, nvars); _fmpz_vec_clear(Buexp, nvars*Blen); TMP_END; return success; } flint-3.1.3/src/fmpz_mpoly/compose_fmpz_poly.c000066400000000000000000000152741461254215100215370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" static int _fmpz_poly_pow_fmpz_is_not_feasible(const fmpz_poly_t b, const fmpz_t e) { if (b->length < 2) { if (b->length == 1) { return _fmpz_pow_fmpz_is_not_feasible(fmpz_bits(b->coeffs + 0), e); } else { return 0; } } else { ulong limit = (ulong)(WORD_MAX)/(ulong)(2*sizeof(fmpz)); return fmpz_cmp_ui(e, limit/(ulong)(b->length)) >= 0; } } static int _fmpz_poly_pow_ui_is_not_feasible(const fmpz_poly_t b, ulong e) { if (b->length < 2) { if (b->length == 1) { return _fmpz_pow_ui_is_not_feasible(fmpz_bits(b->coeffs + 0), e); } else { return 0; } } else { ulong limit = (ulong)(WORD_MAX)/(ulong)(2*sizeof(fmpz)); return e >= limit/(ulong)(b->length); } } int _fmpz_mpoly_compose_fmpz_poly_sp(fmpz_poly_t A, const fmpz_mpoly_t B, fmpz_poly_struct * const * C, const fmpz_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t bits = B->bits; slong i, j, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, shift, off; slong Blen = B->length; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; fmpz * degrees; slong * offs; ulong * masks; fmpz_poly_struct * powers; fmpz_poly_t t, t2; TMP_INIT; FLINT_ASSERT(Blen != 0); TMP_START; degrees = TMP_ARRAY_ALLOC(nvars, slong); mpoly_degrees_si(degrees, Bexp, Blen, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_fmpz_poly_pow_ui_is_not_feasible(C[i], degrees[i])) { success = 0; goto cleanup_degrees; } entries += FLINT_BIT_COUNT(degrees[i]); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fmpz_poly_struct); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the non-main variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = FLINT_BIT_COUNT(degrees[i]); mpoly_gen_offset_shift_sp(&off, &shift, i, bits, ctx->minfo); for (j = 0; j < varibits; j++) { offs[k] = off; masks[k] = UWORD(1) << (shift + j); fmpz_poly_init(powers + k); if (j == 0) fmpz_poly_set(powers + k, C[i]); else fmpz_poly_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fmpz_poly_zero(A); fmpz_poly_init(t); fmpz_poly_init(t2); for (i = 0; i < Blen; i++) { fmpz_poly_set_fmpz(t, Bcoeff + i); for (k = 0; k < k_len; k++) { if ((Bexp[N*i + offs[k]] & masks[k]) != WORD(0)) { fmpz_poly_mul(t2, t, powers + k); fmpz_poly_swap(t, t2); } } fmpz_poly_add(A, A, t); } fmpz_poly_clear(t); fmpz_poly_clear(t2); for (k = 0; k < k_len; k++) fmpz_poly_clear(powers + k); cleanup_degrees: TMP_END; return success; } int _fmpz_mpoly_compose_fmpz_poly_mp(fmpz_poly_t A, const fmpz_mpoly_t B, fmpz_poly_struct * const * C, const fmpz_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t bits = B->bits; ulong l; slong i, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, off; slong Blen = B->length; fmpz * Bcoeff = B->coeffs; ulong * Bexp = B->exps; fmpz * degrees; slong * offs; ulong * masks; fmpz_poly_struct * powers; fmpz_poly_t t, t2; TMP_INIT; FLINT_ASSERT(Blen > 0); TMP_START; degrees = TMP_ARRAY_ALLOC(nvars, fmpz); for (i = 0; i < nvars; i++) fmpz_init(degrees + i); mpoly_degrees_ffmpz(degrees, Bexp, Blen, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_fmpz_poly_pow_fmpz_is_not_feasible(C[i], degrees + i)) { success = 0; goto cleanup_degrees; } entries += fmpz_bits(degrees + i); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fmpz_poly_struct); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = fmpz_bits(degrees + i); off = mpoly_gen_offset_mp(i, bits, ctx->minfo); for (l = 0; l < varibits; l++) { offs[k] = off + (l / FLINT_BITS); masks[k] = UWORD(1) << (l % FLINT_BITS); fmpz_poly_init(powers + k); if (l == 0) fmpz_poly_set(powers + k, C[i]); else fmpz_poly_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fmpz_poly_zero(A); fmpz_poly_init(t); fmpz_poly_init(t2); for (i = 0; i < Blen; i++) { fmpz_poly_set_fmpz(t, Bcoeff + i); for (k = 0; k < k_len; k++) { if ((Bexp[N*i + offs[k]] & masks[k]) != WORD(0)) { fmpz_poly_mul(t2, t, powers + k); fmpz_poly_swap(t, t2); } } fmpz_poly_add(A, A, t); } fmpz_poly_clear(t); fmpz_poly_clear(t2); for (k = 0; k < k_len; k++) fmpz_poly_clear(powers + k); cleanup_degrees: for (i = 0; i < nvars; i++) fmpz_clear(degrees + i); TMP_END; return success; } int fmpz_mpoly_compose_fmpz_poly(fmpz_poly_t A, const fmpz_mpoly_t B, fmpz_poly_struct * const * C, const fmpz_mpoly_ctx_t ctx) { if (B->length == 0) { fmpz_poly_zero(A); return 1; } if (B->bits <= FLINT_BITS) { return _fmpz_mpoly_compose_fmpz_poly_sp(A, B, C, ctx); } else { return _fmpz_mpoly_compose_fmpz_poly_mp(A, B, C, ctx); } } flint-3.1.3/src/fmpz_mpoly/compose_mat.c000066400000000000000000000044521461254215100202750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* essentially exps(A) = M*exps(B) */ void _fmpz_mpoly_compose_mat(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mat_t M, const fmpz_mpoly_ctx_t ctxB, const fmpz_mpoly_ctx_t ctxAC) { slong i; fmpz * u, * v; flint_bitcnt_t vbits; slong Blen = B->length; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); const ulong * Bexp = B->exps; const fmpz * Bcoeffs = B->coeffs; slong Alen_old = A->length; slong AN; FLINT_ASSERT(A != B); FLINT_ASSERT(fmpz_mat_nrows(M) == ctxAC->minfo->nfields + 1); FLINT_ASSERT(fmpz_mat_ncols(M) == ctxB->minfo->nfields); u = _fmpz_vec_init(ctxB->minfo->nfields); v = _fmpz_vec_init(ctxAC->minfo->nfields + 1); fmpz_mpoly_fit_length(A, Blen, ctxAC); A->length = 0; fmpz_mpoly_fit_bits(A, MPOLY_MIN_BITS, ctxAC); A->bits = MPOLY_MIN_BITS; for (i = 0; i < Blen; i++) { mpoly_unpack_vec_fmpz(u, Bexp + BN*i, Bbits, ctxB->minfo->nfields, 1); fmpz_mat_mul_fmpz_vec(v, M, u, fmpz_mat_ncols(M)); if (!fmpz_is_zero(v + ctxAC->minfo->nfields)) continue; vbits = _fmpz_vec_max_bits(v, ctxAC->minfo->nfields); FLINT_ASSERT(vbits >= 0); fmpz_mpoly_fit_bits(A, mpoly_fix_bits(vbits + 1, ctxAC->minfo), ctxAC); fmpz_set(A->coeffs + A->length, Bcoeffs + i); AN = mpoly_words_per_exp(A->bits, ctxAC->minfo); mpoly_pack_vec_fmpz(A->exps + AN*A->length, v, A->bits, ctxAC->minfo->nfields, 1); A->length++; } while (--Alen_old >= A->length) _fmpz_demote(A->coeffs + Alen_old); _fmpz_vec_clear(u, ctxB->minfo->nfields); _fmpz_vec_clear(v, ctxAC->minfo->nfields + 1); fmpz_mpoly_sort_terms(A, ctxAC); fmpz_mpoly_combine_like_terms(A, ctxAC); return; } flint-3.1.3/src/fmpz_mpoly/content_vars.c000066400000000000000000000123311461254215100204670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" /* content wrt gen(0), ..., gen(num_vars-1) successful answer will be returned with g->bits == A->bits */ int fmpz_mpolyl_content( fmpz_mpoly_t g, const fmpz_mpoly_t A, slong num_vars, const fmpz_mpoly_ctx_t ctx) { int success; slong i, j, off, shift; ulong old_shift, new_shift; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; slong Alen = A->length; fmpz_mpoly_struct * v; slong vlen, valloc; FLINT_ASSERT(g != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); i = 0; old_shift = (Aexps + N*i)[off] >> shift; valloc = 4; v = (fmpz_mpoly_struct *) flint_malloc(valloc*sizeof(fmpz_mpoly_struct)); vlen = 0; v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + i; v[vlen].exps = Aexps + N*i; v[vlen].length = i; v[vlen].alloc = v[vlen].length; vlen++; for (i = 1; i < Alen; old_shift = new_shift, i++) { new_shift = (Aexps + N*i)[off] >> shift; if (new_shift != old_shift) goto new_one; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto new_one; continue; new_one: v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].alloc = v[vlen - 1].length; if (vlen + 1 > valloc) { valloc += 2 + valloc/2; v = (fmpz_mpoly_struct *) flint_realloc(v, valloc* sizeof(fmpz_mpoly_struct)); } v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + i; v[vlen].exps = Aexps + N*i; v[vlen].alloc = 0; v[vlen].length = i; vlen++; } v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].alloc = v[vlen - 1].length; success = _fmpz_mpoly_vec_content_mpoly(g, v, vlen, ctx); if (success) { /* remove gen(0) ... gen(num_vars-1) from the answer */ ulong * gexps; ulong mask; fmpz_mpoly_repack_bits_inplace(g, A->bits, ctx); gexps = g->exps; mask = (shift > 0) ? ((-UWORD(1)) >> (FLINT_BITS - shift)) : 0; for (i = 0; i < g->length; i++) { (gexps + N*i)[off] &= mask; for (j = off + 1; j < N; j++) (gexps + N*i)[j] = 0; } } flint_free(v); return success; } int fmpz_mpoly_content_vars( fmpz_mpoly_t g, const fmpz_mpoly_t A, slong * vars, slong num_vars, const fmpz_mpoly_ctx_t ctx) { int success; slong i, j, k; fmpz_mpolyv_t v, w; fmpz_mpoly_univar_t u; if (num_vars < 1) { fmpz_mpoly_set(g, A, ctx); return 1; } for (i = 0; i < num_vars; i++) { if (vars[i] >= (ulong) ctx->minfo->nvars) flint_throw(FLINT_ERROR, "fmpz_mpoly_content_vars: variable out of range"); } if (fmpz_mpoly_is_zero(A, ctx)) { fmpz_mpoly_zero(g, ctx); return 1; } if (A->bits <= FLINT_BITS && ctx->minfo->ord == ORD_LEX && num_vars < ctx->minfo->nvars) { for (i = 0; i < num_vars; i++) if (vars[i] != i) goto do_general; if (g == A) { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); success = fmpz_mpolyl_content(t, A, num_vars, ctx); fmpz_mpoly_swap(g, t, ctx); fmpz_mpoly_clear(t, ctx); return success; } return fmpz_mpolyl_content(g, A, num_vars, ctx); } do_general: fmpz_mpolyv_init(v, ctx); fmpz_mpolyv_init(w, ctx); fmpz_mpoly_univar_init(u, ctx); i = 0; fmpz_mpoly_to_univar(u, A, vars[i], ctx); fmpz_mpolyv_fit_length(v, u->length, ctx); v->length = u->length; for (j = 0; j < u->length; j++) fmpz_mpoly_swap(v->coeffs + j, u->coeffs + j, ctx); for (i = 1; i < num_vars; i++) { w->length = 0; for (k = 0; k < v->length; k++) { fmpz_mpoly_to_univar(u, v->coeffs + k, vars[i], ctx); fmpz_mpolyv_fit_length(w, w->length + u->length, ctx); for (j = 0; j < u->length; j++) { fmpz_mpoly_swap(w->coeffs + w->length, u->coeffs + j, ctx); w->length++; } } fmpz_mpolyv_swap(v, w, ctx); } fmpz_mpoly_univar_clear(u, ctx); fmpz_mpolyv_clear(w, ctx); success = _fmpz_mpoly_vec_content_mpoly(g, v->coeffs, v->length, ctx); fmpz_mpolyv_clear(v, ctx); return success; } flint-3.1.3/src/fmpz_mpoly/ctx.c000066400000000000000000000014251461254215100165620ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_ctx_init(fmpz_mpoly_ctx_t ctx, slong nvars, const ordering_t ord) { mpoly_ctx_init(ctx->minfo, nvars, ord); } void fmpz_mpoly_ctx_init_rand(fmpz_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars) { mpoly_ctx_init_rand(ctx->minfo, state, max_nvars); } void fmpz_mpoly_ctx_clear(fmpz_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/deflate.c000066400000000000000000000031541461254215100173710ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_deflate(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mpoly_ctx_t ctx) { slong Abits; if (B->length == 0) { fmpz_mpoly_zero(A, ctx); return; } /* quick and safe bound on bits required */ Abits = B->bits; if (A == B) { slong NA = mpoly_words_per_exp(Abits, ctx->minfo); ulong * texps = flint_malloc(NA*A->alloc*sizeof(ulong)); mpoly_monomials_deflate(texps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = Abits; } else { fmpz_mpoly_fit_length(A, B->length, ctx); fmpz_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; _fmpz_vec_set(A->coeffs, B->coeffs, B->length); mpoly_monomials_deflate(A->exps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _fmpz_mpoly_set_length(A, B->length, ctx); } if (ctx->minfo->ord != ORD_LEX) { fmpz_mpoly_sort_terms(A, ctx); } } flint-3.1.3/src/fmpz_mpoly/deflation.c000066400000000000000000000013161461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { mpoly_monomials_deflation(shift, stride, A->exps, A->bits, A->length, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/degrees.c000066400000000000000000000042471461254215100174070ustar00rootroot00000000000000/* Copyright (C) 2016-2017 William Hart Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_degrees_fit_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_degrees_fit_si(A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mpoly_degrees_fmpz(fmpz ** degs, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { mpoly_degrees_pfmpz(degs, A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mpoly_degrees_si(slong * degs, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { mpoly_degrees_si(degs, A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } slong fmpz_mpoly_degree_si(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } int fmpz_mpoly_total_degree_fits_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return mpoly_total_degree_fits_si(A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mpoly_total_degree_fmpz(fmpz_t td, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { mpoly_total_degree_fmpz(td, A->exps, A->length, A->bits, ctx->minfo); } slong fmpz_mpoly_total_degree_si(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return mpoly_total_degree_si(A->exps, A->length, A->bits, ctx->minfo); } void fmpz_mpoly_used_vars(int * used, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < ctx->minfo->nvars; i++) used[i] = 0; mpoly_used_vars_or(used, A->exps, A->length, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/derivative.c000066400000000000000000000057331461254215100201340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_derivative(fmpz * coeff1, ulong * exp1, const fmpz * coeff2, const ulong * exp2, slong len2, flint_bitcnt_t bits, slong N, slong offset, slong shift, ulong * oneexp) { slong i, len1; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); /* x^c -> c*x^(c-1) */ len1 = 0; for (i = 0; i < len2; i++) { ulong c = (exp2[N*i + offset] >> shift) & mask; if (c != 0) { mpoly_monomial_sub(exp1 + N*len1, exp2 + N*i, oneexp, N); fmpz_mul_ui(coeff1 + len1, coeff2 + i, c); len1++; } } return len1; } slong _fmpz_mpoly_derivative_mp(fmpz * coeff1, ulong * exp1, const fmpz * coeff2, const ulong * exp2, slong len2, flint_bitcnt_t bits, slong N, slong offset, ulong * oneexp) { slong i, len1; fmpz_t c; fmpz_init(c); /* x^c -> c*x^(c-1) */ len1 = 0; for (i = 0; i < len2; i++) { fmpz_set_ui_array(c, exp2 + N*i + offset, bits/FLINT_BITS); if (!fmpz_is_zero(c)) { mpoly_monomial_sub_mp(exp1 + N*len1, exp2 + N*i, oneexp, N); fmpz_mul(coeff1 + len1, coeff2 + i, c); len1++; } } fmpz_clear(c); return len1; } void fmpz_mpoly_derivative(fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, slong var, const fmpz_mpoly_ctx_t ctx) { slong N, offset, shift; flint_bitcnt_t bits; ulong * oneexp; slong len1; TMP_INIT; TMP_START; bits = poly2->bits; if (poly1 != poly2) fmpz_mpoly_fit_length_reset_bits(poly1, poly2->length, bits, ctx); N = mpoly_words_per_exp(bits, ctx->minfo); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (bits <= FLINT_BITS) { mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, bits, ctx->minfo); len1 = _fmpz_mpoly_derivative(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, shift, oneexp); } else { offset = mpoly_gen_monomial_offset_mp(oneexp, var, bits, ctx->minfo); len1 = _fmpz_mpoly_derivative_mp(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, oneexp); } _fmpz_mpoly_set_length(poly1, len1, ctx); TMP_END; } flint-3.1.3/src/fmpz_mpoly/discriminant.c000066400000000000000000000014411461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int fmpz_mpoly_discriminant(fmpz_mpoly_t R, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { int success; fmpz_mpoly_univar_t Ax; fmpz_mpoly_univar_init(Ax, ctx); fmpz_mpoly_to_univar(Ax, A, var, ctx); success = fmpz_mpoly_univar_discriminant(R, Ax, ctx); fmpz_mpoly_univar_clear(Ax, ctx); return success; } flint-3.1.3/src/fmpz_mpoly/div.c000066400000000000000000000011471461254215100165470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_div(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { /* TODO !!! */ fmpz_mpoly_div_monagan_pearce(Q, A, B, ctx); } flint-3.1.3/src/fmpz_mpoly/div_monagan_pearce.c000066400000000000000000000635201461254215100215710ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* Set polyq to the quotient poly2 by poly3 discarding remainder (with notional remainder coeffs reduced modulo the leading coeff of poly3), and return the length of the quotient. This version of the function assumes the exponent vectors all fit in a single word. The exponent vectors are assumed to have fields with the given number of bits. Assumes input polys are nonzero. Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce [1]. The word "maxhi" is set to a mask for the degree field of the exponent vector (in the case of a degree ordering) to facilitate the reverse ordering in degrevlex. Division is from left to right with a heap with largest exponent at the head. Quotient poly is written in order. [1] http://www.cecm.sfu.ca/~rpearcea/sdmp/sdmp_paper.pdf */ slong _fmpz_mpoly_div_monagan_pearce1(fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, ulong maskhi) { slong i, j, q_len, s; slong next_loc, heap_len = 2; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * q_coeff = *polyq; ulong * q_exp = *expq; slong * hind; ulong mask, exp; fmpz_t r, acc_lg; ulong acc_sm[3]; int lt_divides, small; slong bits2, bits3; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; TMP_INIT; TMP_START; fmpz_init(acc_lg); fmpz_init(r); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); q_len = WORD(0); /* see description of divisor heap division in paper */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); /* precompute leading coefficient info assuming "small" case */ if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, 1); lt_divides = mpoly_monomial_divides1(q_exp + q_len, exp, exp3[0], mask); /* take nodes from heap with exponent matching exp */ if (!lt_divides) { /* optimization: coeff arithmetic not needed */ if (mpoly_monomial_gt1(exp3[0], exp, maskhi)) { /* optimization: no more quotient terms possible */ goto cleanup; } do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else if (small) { /* optimization: small coeff arithmetic, acc_sm used below */ acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else { /* general coeff arithmetic */ fmpz_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } } } /* try to divide accumulated term by leading term */ if (!lt_divides) continue; if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) continue; if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); (void) rr; /* silence compiler warning */ if (qq == 0) continue; if (qq <= COEFF_MAX) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = qq; if (ds != lc_sign) q_coeff[q_len] = -q_coeff[q_len]; } else { small = 0; fmpz_set_ui(q_coeff + q_len, qq); if (ds != lc_sign) fmpz_neg(q_coeff + q_len, q_coeff + q_len); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) continue; large_lt_divides: fmpz_fdiv_qr(q_coeff + q_len, r, acc_lg, poly3 + 0); if (fmpz_is_zero(q_coeff + q_len)) continue; } /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; q_len++; } cleanup: fmpz_clear(acc_lg); fmpz_clear(r); (*polyq) = q_coeff; (*expq) = q_exp; TMP_END; /* return quotient poly length */ return q_len; exp_overflow: for (i = 0; i < q_len; i++) _fmpz_demote(q_coeff + i); q_len = -WORD(1); goto cleanup; } slong _fmpz_mpoly_div_monagan_pearce(fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const ulong * cmpmask) { slong i, j, q_len, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * q_coeff = *polyq; ulong * q_exp = *expq; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; fmpz_t r, acc_lg; ulong acc_sm[3]; slong * hind; int lt_divides, small; slong bits2, bits3; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; TMP_INIT; if (N == 1) return _fmpz_mpoly_div_monagan_pearce1(polyq, expq, allocq, poly2, exp2, len2, poly3, exp3, len3, bits, cmpmask[0]); TMP_START; fmpz_init(acc_lg); fmpz_init(r); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; q_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coefficient info in "small" case */ if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; } _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, N); if (bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(q_exp + q_len*N, exp, exp3, N, mask); else lt_divides = mpoly_monomial_divides_mp(q_exp + q_len*N, exp, exp3, N, bits); /* take nodes from heap with exponent matching exp */ if (!lt_divides) { /* optimization: coeff arithmetic not needed */ if (mpoly_monomial_gt(exp3 + 0, exp, N, cmpmask)) { /* optimization: no more quotient terms possible */ goto cleanup; } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else if (small) { /* optimization: small coeff arithmetic, acc_sm used below */ acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else { /* general coeff arithmetic */ fmpz_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go up */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term */ if (!lt_divides) { continue; } if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) { continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); (void) rr; if (qq == 0) continue; if (qq <= COEFF_MAX) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = qq; if (ds != lc_sign) q_coeff[q_len] = -q_coeff[q_len]; } else { small = 0; fmpz_set_ui(q_coeff + q_len, qq); if (ds != lc_sign) fmpz_neg(q_coeff + q_len, q_coeff + q_len); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) { continue; } large_lt_divides: fmpz_fdiv_qr(q_coeff + q_len, r, acc_lg, poly3 + 0); if (fmpz_is_zero(q_coeff + q_len)) { continue; } } /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; q_len++; } cleanup: fmpz_clear(acc_lg); fmpz_clear(r); (*polyq) = q_coeff; (*expq) = q_exp; TMP_END; /* return quotient poly length */ return q_len; exp_overflow: for (i = 0; i < q_len; i++) _fmpz_demote(q_coeff + i); q_len = -WORD(1); goto cleanup; } void fmpz_mpoly_div_monagan_pearce(fmpz_mpoly_t q, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) { slong exp_bits, N, lenq = 0; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; ulong * cmpmask; int free2 = 0, free3 = 0; fmpz_mpoly_t temp1; fmpz_mpoly_struct * tq; /* check divisor is nonzero */ if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_div_monagan_pearce"); /* dividend zero, write out quotient */ if (poly2->length == 0) { fmpz_mpoly_zero(q, ctx); return; } /* maximum bits in quotient exps and inputs is max for poly2 and poly3 */ exp_bits = FLINT_MAX(poly2->bits, poly3->bits); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(exp2, exp3, N, cmpmask)) { fmpz_mpoly_zero(q, ctx); goto cleanup3; } /* take care of aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_init2(temp1, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(temp1, exp_bits, ctx); temp1->bits = exp_bits; tq = temp1; } else { fmpz_mpoly_fit_length(q, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(q, exp_bits, ctx); q->bits = exp_bits; tq = q; } /* do division without remainder */ while ((lenq = _fmpz_mpoly_div_monagan_pearce(&tq->coeffs, &tq->exps, &tq->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask)) == -WORD(1) ) { ulong * old_exp2 = exp2, * old_exp3 = exp3; slong old_exp_bits = exp_bits; exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, old_exp2, old_exp_bits, poly2->length, ctx->minfo); exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, old_exp3, old_exp_bits, poly3->length, ctx->minfo); if (free2) flint_free(old_exp2); if (free3) flint_free(old_exp3); free2 = free3 = 1; fmpz_mpoly_fit_bits(tq, exp_bits, ctx); tq->bits = exp_bits; } /* take care of aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_swap(temp1, q, ctx); fmpz_mpoly_clear(temp1, ctx); } _fmpz_mpoly_set_length(q, lenq, ctx); cleanup3: if (free2) flint_free(exp2); if (free3) flint_free(exp3); flint_free(cmpmask); } flint-3.1.3/src/fmpz_mpoly/divides.c000066400000000000000000000035461461254215100174210ustar00rootroot00000000000000/* Copyright (C) 2018-2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #ifdef _fmpz_mpoly_divides_heap_threaded_pool #include "thread_support.h" int fmpz_mpoly_divides( fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { thread_pool_handle * handles; slong num_handles; int divides; slong thread_limit; thread_limit = A->length/1024; if (B->length < 2 || A->length < 2) { if (B->length == 0) { flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divides"); } if (A->length == 0) { fmpz_mpoly_zero(Q, ctx); return 1; } return fmpz_mpoly_divides_monagan_pearce(Q, A, B, ctx); } num_handles = flint_request_threads(&handles, thread_limit); divides = (num_handles > 0) ? _fmpz_mpoly_divides_heap_threaded_pool(Q, A, B, ctx, handles, num_handles) : fmpz_mpoly_divides_monagan_pearce(Q, A, B, ctx); flint_give_back_threads(handles, num_handles); return divides; } #else int fmpz_mpoly_divides( fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (B->length == 0) { flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divides"); } if (A->length == 0) { fmpz_mpoly_zero(Q, ctx); return 1; } return fmpz_mpoly_divides_monagan_pearce(Q, A, B, ctx); } #endif flint-3.1.3/src/fmpz_mpoly/divides_array.c000066400000000000000000001334261461254215100206200ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* improve locality */ #define BLOCK 128 #define MAX_ARRAY_SIZE (WORD(300000)) /* Submul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into three words per coefficient. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_submul_array1_slong(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong cy; ulong p[2]; /* for products of coefficients */ ulong * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + 3*((slong) exp2[i]); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + 3*((slong) exp3[j]); smul_ppmm(p[1], p[0], poly2[i], poly3[j]); sub_dddmmmsss(cy, c[1], c[0], 0, c[1], c[0], 0, p[1], p[0]); c[2] += (0 <= (slong) p[1]) ? cy : cy + 1; } } } } } } /* Submul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into two words per coefficient. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_submul_array1_slong2(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong p[2]; /* for products of coefficients */ ulong * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { /* hack: see mul_array */ c2 = poly1 + (((slong) exp2[i]) << 1); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { /* hack: see mul_array */ c = c2 + (((slong) exp3[j]) << 1); smul_ppmm(p[1], p[0], poly2[i], poly3[j]); sub_ddmmss(c[1], c[0], c[1], c[0], p[1], p[0]); } } } } } } /* Submul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into one word per coefficient. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_submul_array1_slong1(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong p; /* for products of coefficients */ ulong * c2; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + ((slong) exp2[i]); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { p = (ulong) ((slong) poly2[i])*((slong) poly3[j]); c2[(slong) exp3[j]] -= p; } } } } } } /* Addmul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is unrestricted, having multiprecision coefficients. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_submul_array1_fmpz(fmpz * poly1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; fmpz * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + (slong) exp2[i]; if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + (slong) exp3[j]; fmpz_submul(c, poly2 + i, poly3 + j); } } } } } } /* Polynomial by monomial submul into a dense array poly1, given an input poly and monomial with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input poly and monomial have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into three words per coefficient. */ void _fmpz_mpoly_submul_array1_slong_1(ulong * poly1, slong d, const ulong exp2, const slong * poly3, const ulong * exp3, slong len3) { slong j; ulong cy; ulong p[2]; /* for products of coefficients */ ulong * c2, * c; c2 = poly1 + 3*((slong) exp2); if (d != 0) { for (j = 0; j < len3; j++) { c = c2 + 3*((slong) exp3[j]); smul_ppmm(p[1], p[0], d, poly3[j]); sub_dddmmmsss(cy, c[1], c[0], 0, c[1], c[0], 0, p[1], p[0]); c[2] += (0 <= (slong) p[1]) ? cy : cy + 1; } } } /* Polynomial by monomial submul into a dense array poly1, given an input poly and monomial with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input poly and monomial have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into two words per coefficient. */ void _fmpz_mpoly_submul_array1_slong2_1(ulong * poly1, slong d, const ulong exp2, const slong * poly3, const ulong * exp3, slong len3) { slong j; ulong p[2]; /* for products of coefficients */ ulong * c2, * c; c2 = poly1 + (((slong) exp2) << 1); if (d != 0) { for (j = 0; j < len3; j++) { c = c2 + (((slong) exp3[j]) << 1); smul_ppmm(p[1], p[0], d, poly3[j]); sub_ddmmss(c[1], c[0], c[1], c[0], p[1], p[0]); } } } /* Polynomial by monomial submul into a dense array poly1, given an input poly and monomial with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input poly and monomial have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is unrestricted, having multiprecision coefficients. */ void _fmpz_mpoly_submul_array1_fmpz_1(fmpz * poly1, const fmpz_t d, ulong exp2, const fmpz * poly3, const ulong * exp3, slong len3) { slong j; fmpz * c2, * c; c2 = poly1 + (slong) exp2; if (*d != 0) { for (j = 0; j < len3; j++) { c = c2 + (slong) exp3[j]; fmpz_submul(c, d, poly3 + j); } } } /* Convert an fmpz_mpoly to dense array format, where the exponents of the input poly are tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. The output array is assumed to have two words per coefficient. */ void _fmpz_mpoly_to_ulong_array2(ulong * p, const fmpz * coeffs, const ulong * exps, slong len) { slong i, j; /* for each term of the input poly */ for (i = 0; i < len; i++) { ulong * ptr = p + 2*((slong) exps[i]); slong size = fmpz_size(coeffs + i); fmpz c = coeffs[i]; if (!COEFF_IS_MPZ(c)) { ptr[0] = (ulong) c; ptr[1] = (ulong) (c > 0 ? 0 : -WORD(1)); } else { __mpz_struct * m = COEFF_TO_PTR(c); for (j = 0; j < size; j++) ptr[j] = m->_mp_d[j]; if (fmpz_sgn(coeffs + i) < 0) mpn_neg(ptr, ptr, 2); } } } /* Convert an fmpz_mpoly to dense array format, where the exponents of the input poly are tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. The output array is assumed to have one word per coefficient. */ void _fmpz_mpoly_to_ulong_array1(ulong * p, const fmpz * coeffs, const ulong * exps, slong len) { slong i; for (i = 0; i < len; i++) { ulong * ptr = p + ((slong) exps[i]); slong size = fmpz_size(coeffs + i); fmpz c = coeffs[i]; if (!COEFF_IS_MPZ(c)) ptr[0] = c; else { __mpz_struct * m = COEFF_TO_PTR(c); if (size != 0) { if (fmpz_sgn(coeffs + i) > 0) ptr[0] = m->_mp_d[0]; else ptr[0] = -m->_mp_d[0]; } } } } /* Convert an fmpz_mpoly to dense array format, where the exponents of the input poly are tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. The output array is assumed to have three words per coefficient. */ void _fmpz_mpoly_to_ulong_array(ulong * p, const fmpz * coeffs, const ulong * exps, slong len) { slong i, j; for (i = 0; i < len; i++) { ulong * ptr = p + 3*((slong) exps[i]); slong size = fmpz_size(coeffs + i); fmpz c = coeffs[i]; if (!COEFF_IS_MPZ(c)) { ptr[0] = (ulong) c; if (c > 0) { ptr[1] = 0; ptr[2] = 0; } else { ptr[1] = (ulong) -WORD(1); ptr[2] = (ulong) -WORD(1); } } else { __mpz_struct * m = COEFF_TO_PTR(c); for (j = 0; j < size; j++) ptr[j] = m->_mp_d[j]; if (fmpz_sgn(coeffs + i) < 0) mpn_neg(ptr, ptr, 3); } } } /* Convert an fmpz_mpoly to dense array format, where the exponents of the input poly are tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. The output array is unrestricted, having multiprecision coefficients. */ void _fmpz_mpoly_to_fmpz_array(fmpz * p, const fmpz * coeffs, const ulong * exps, slong len) { slong i; for (i = 0; i < len; i++) fmpz_set(p + (slong) exps[i], coeffs + i); } /* Set poly1 to the quotient of poly2 by poly3 if the quotient is exact, and return the length of the quotient. If the quotient is not exact, return 0. The algorithm aborts as early as possible if the quotient is not exact. It is assumed that poly2 is nonzero so that the quotient is either exact and nonzero, or inexact. The polynomials have their exponents tightly packed, with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. There are assumed to be "num" variables and the bases b_i are passed in the array "mults". The function reallocates its output. The quotient poly is not assumed to be zero on input. The quotient are appended to the existing terms in that polys. */ slong _fmpz_mpoly_divides_array_tight(fmpz ** poly1, ulong ** exp1, slong * alloc, slong len1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num) { slong i, j, q, r, prod, bits1, bits2, bits3, len = len1; slong max3 = (slong) exp3[0]; /* largest exponent in poly3 */ slong min3 = (slong) exp3[len3 - 1]; /* smallest exponent in poly3 */ slong * prods; fmpz c3 = poly3[0]; /* abs val of trailing coeff of poly3 */ ulong u3 = ((ulong) FLINT_ABS(c3)) >> 1; fmpz * p1 = *poly1; ulong * e1 = *exp1; int small; TMP_INIT; TMP_START; /* check there are at least as many zero exponents in dividend as divisor */ if (exp2[len2 - 1] < min3) goto cleanup; /* not an exact quotient */ prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods[0] = 1; for (i = 1; i <= num; i++) prods[i] = mults[i - 1]*prods[i - 1]; prod = prods[num]; /* quick check leading terms divide */ if (!mpoly_monomial_divides_tight(exp2[0], exp3[0], prods, num)) goto cleanup; /* compute bound on poly2 - q*poly3 assuming quotient remains small */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* we assume a bound of SMALL_FMPZ_BITCOUNT_MAX for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; bits1 += 2; /* incr. so poly2 - q*poly3 doesn't overflow and for sign */ /* input coeffs small and intermediate computations fit two words */ if (small && bits1 <= 2*FLINT_BITS) { ulong * p2 = (ulong *) TMP_ALLOC(2*prod*sizeof(ulong)); for (i = 0; i < 2*prod; i++) p2[i] = 0; /* poly2 to array format */ _fmpz_mpoly_to_ulong_array2(p2, poly2, exp2, len2); /* for each term of poly2 array relevant to exact quotient */ for (i = prod - 1; i >= max3; i--) { ulong * ptr = p2 + 2*i; ulong p[2]; /* if coeff is nonzero */ if (ptr[0] != 0 || ptr[1] != 0) { if (0 > (slong) ptr[1]) mpn_neg(p, ptr, 2); else flint_mpn_copyi(p, ptr, 2); /* check quotient won't overflow a word */ if (u3 <= p[1] || (u3 == 0 && 0 > (slong) p[0])) /* quotient too large */ { for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto big; } /* quotient and remainder of coeffs */ sdiv_qrnnd(q, r, ptr[1], ptr[0], c3); /* check coefficient is small, else restart with multiprec code */ if (COEFF_IS_MPZ(FLINT_ABS(q))) { for (j = len1; j < len; j++) /* quotient too large */ _fmpz_demote(p1 + j); len = len1; goto big; } /* check coeff and monomial quotients were exact */ if (r != 0 || /* not an exact division */ !mpoly_monomial_divides_tight(i, max3, prods, num)) { for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto cleanup; } /* submul q*poly3 */ _fmpz_mpoly_submul_array1_slong2_1(p2, q, i - max3, poly3, exp3, len3); /* reallocate quotient */ _fmpz_mpoly_fit_length(&p1, &e1, alloc, len + 1, 1); /* write quotient term */ fmpz_set_si(p1 + len, q); e1[len++] = i - max3; } } /* check there are no nonzero terms left in array */ for ( ; i >= min3; i--) { ulong * ptr = p2 + 2*i; /* if coeff nonzero */ if (ptr[0] != 0 || ptr[1] != 0) /* not an exact division */ { for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto cleanup; } } } /* not done, coeffs small, intermediate computations fit three words */ if (len == len1 && small) { ulong * p2 = (ulong *) TMP_ALLOC(3*prod*sizeof(ulong)); for (i = 0; i < 3*prod; i++) p2[i] = 0; /* poly2 to array format */ _fmpz_mpoly_to_ulong_array(p2, poly2, exp2, len2); /* for each term of poly2 array relevant to exact quotient */ for (i = prod - 1; i >= max3; i--) { ulong * ptr = p2 + 3*i; ulong p[3]; /* if coeff is nonzero */ if (ptr[0] != 0 || ptr[1] != 0 || ptr[2] != 0) { if (0 > (slong) ptr[2]) mpn_neg(p, ptr, 3); else flint_mpn_copyi(p, ptr, 3); /* check quotient won't overflow a word */ if (p[2] > 0 || u3 <= p[1] || (u3 == 0 && 0 > (slong) p[0])) /* quotient too large */ { for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto big; } /* quotient and remainder of coeffs */ sdiv_qrnnd(q, r, ptr[1], ptr[0], c3); /* check coefficient is small, else restart with multiprec code */ if (COEFF_IS_MPZ(FLINT_ABS(q))) { for (j = len1; j < len; j++) /* quotient too large */ _fmpz_demote(p1 + j); len = len1; goto big; } /* check coeff and monomial quotients were exact */ if (r != 0 || /* not an exact division */ !mpoly_monomial_divides_tight(i, max3, prods, num)) { for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto cleanup; } /* submul q*poly3 */ _fmpz_mpoly_submul_array1_slong_1(p2, q, i - max3, poly3, exp3, len3); /* reallocate quotient */ _fmpz_mpoly_fit_length(&p1, &e1, alloc, len + 1, 1); /* write quotient term */ fmpz_set_si(p1 + len, q); e1[len++] = i - max3; } } /* check there are no nonzero terms left in array */ for ( ; i >= min3; i--) { ulong * ptr = p2 + 3*i; /* if coeff nonzero */ if (ptr[0] != 0 || ptr[1] != 0 || ptr[2] != 0) { /* not an exact division */ for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto cleanup; } } } big: /* if not done, use multiprecision coeffs instead */ if (len == len1) { fmpz * p2 = (fmpz *) TMP_ALLOC(prod*sizeof(fmpz)); fmpz_t fq, fr; fmpz_init(fq); fmpz_init(fr); for (i = 0; i < prod; i++) fmpz_init(p2 + i); /* poly2 to array format */ _fmpz_mpoly_to_fmpz_array(p2, poly2, exp2, len2); /* for each term of poly2 array relevant to exact quotient */ for (i = prod - 1; i >= max3; i--) { /* if coeff is nonzero */ if (!fmpz_is_zero(p2 + i)) { /* quotient and remainder of coeffs */ fmpz_fdiv_qr(fq, fr, p2 + i, poly3); /* check coeff and monomial quotients were exact */ if (!fmpz_is_zero(fr) || /* not an exact division */ !mpoly_monomial_divides_tight(i, max3, prods, num)) { for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto cleanup2; } /* submul q*poly3 */ _fmpz_mpoly_submul_array1_fmpz_1(p2, fq, i - max3, poly3, exp3, len3); /* reallocate quotient */ _fmpz_mpoly_fit_length(&p1, &e1, alloc, len + 1, 1); /* write quotient term */ fmpz_set(p1 + len, fq); e1[len++] = i - max3; } } /* check there are no nonzero terms left in array */ for ( ; i >= min3; i--) { /* if coeff nonzero */ if (!fmpz_is_zero(p2 + i)) { /* not an exact division */ for (j = len1; j < len; j++) _fmpz_demote(p1 + j); len = len1; goto cleanup2; } } cleanup2: fmpz_clear(fq); fmpz_clear(fr); for (i = 0; i < prod; i++) fmpz_clear(p2 + i); } cleanup: (*poly1) = p1; (*exp1) = e1; TMP_END; return len - len1; } /* Use dense array exact division to set poly1 to poly2/poly3 in num + 1 variables, given a list of multipliers to tightly pack exponents and a number of bits for the fields of the exponents of the result, assuming no aliasing. Classical exact division in main variable, array multiplication (submul) for multivariate coefficients in remaining num variables. The array "mults" is a list of bases to be used in encoding the array indices from the exponents. The function reallocates its output and returns the length of its output if the quotient is exact, or zero if not. It is assumed that poly2 is not zero. */ slong _fmpz_mpoly_divides_array_chunked(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits) { slong i, j, k, prod, len = 0, l1, l2, l3; slong bits1, bits2, bits3 = 0, tlen, talloc, skip, max_exp; slong shift = bits*(num); slong * i1, * i2, * i3, * n1, * n2, * n3; slong * b1, * b3, * maxb1, * maxb3, * max_exp1, * max_exp3; ulong * e2, * e3, * texp, * p2; fmpz * temp; int small; TMP_INIT; /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prod = 1; for (i = 0; i < num; i++) prod *= mults[i]; /* lengths of poly2, poly3 in chunks, and poly1 assuming exact division */ l2 = 1 + (slong) (exp2[0] >> shift); l3 = 1 + (slong) (exp3[0] >> shift); l1 = l2 - l3 + 1; TMP_START; /* indices and lengths of coefficients/chunks of polys in main variable */ i1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); n1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); i2 = (slong *) TMP_ALLOC(l2*sizeof(slong)); n2 = (slong *) TMP_ALLOC(l2*sizeof(slong)); i3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); n3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); b1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); maxb1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); b3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); maxb3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); max_exp1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); max_exp3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); mpoly_main_variable_terms1(i2, n2, exp2, l2, len2, num + 1, num + 1, bits); mpoly_main_variable_terms1(i3, n3, exp3, l3, len3, num + 1, num + 1, bits); /* alloc space for copy of coeff/chunk of poly2 */ temp = (fmpz *) flint_calloc(n2[0] + 1, sizeof(fmpz)); texp = (ulong *) flint_malloc((n2[0] + 1)*sizeof(ulong)); talloc = n2[0] + 1; /* figure out how many trailing zero chunks poly3 has */ skip = 0; while (n3[l3 - skip - 1] == 0) { /* check poly2 has at least as many trailing zero chunks */ if (n2[l2 - skip - 1] != 0) /* not an exact quotient */ { goto cleanup; } skip++; } /* work out max bits for each coeff/chunk, optimal bits */ for (i = 0; i < l3; i++) { _fmpz_vec_sum_max_bits(&b3[i], &maxb3[i], poly3+i3[i], n3[i]); if (bits3 < maxb3[i]) bits3 = maxb3[i]; } /* pack input coefficients tightly */ e2 = (ulong *) TMP_ALLOC(len2*sizeof(ulong)); e3 = (ulong *) TMP_ALLOC(len3*sizeof(ulong)); mpoly_pack_monomials_tight(e2, exp2, len2, mults, num, bits); mpoly_pack_monomials_tight(e3, exp3, len3, mults, num, bits); /* work out maximum packed exponent for each chunk */ for (i = 0; i < l3; i++) { max_exp = 0; for (j = 0; j < n3[i]; j++) { if (e3[i3[i] + j] > max_exp) max_exp = e3[i3[i] + j]; } max_exp3[i] = max_exp; } /* bound poly2 coeffs and check input/output coeffs likely small */ bits2 = _fmpz_vec_max_bits(poly2, len2); /* we assume a bound of SMALL_FMPZ_BITCOUNT_MAX for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* enough space for three words per coeff, even if only one or two needed */ p2 = (ulong *) TMP_ALLOC(3*prod*sizeof(ulong)); /* coefficients likely to be small */ if (small) { /* for each chunk of poly2 */ for (i = 0; i < l2 - skip; i++) { slong num1 = 0; bits1 = 0; /* if there are already quotient terms */ if (i != 0) { /* compute bound on intermediate computations a - q*b */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3) { bits1 = FLINT_MAX(bits1, FLINT_MIN(b1[j] + maxb3[k], maxb1[j] + b3[k])); num1++; } } bits1 += FLINT_BIT_COUNT(num1); bits1 = FLINT_MAX(FLINT_ABS(bits2), bits1); bits1 += 2; /* bit for sign and so a - q*b doesn't overflow */ } else bits1 = FLINT_ABS(bits2) + 1; /* extra bit for sign */ /* intermediate computations fit in one word */ if (bits1 <= FLINT_BITS) { for (j = 0; j < prod; j++) p2[j] = 0; /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_ulong_array1(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3) { /* check for exponent overflow: not exact division */ if (max_exp1[j] + max_exp3[k] >= prod) { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup; } _fmpz_mpoly_submul_array1_slong1(p2, (*poly1) + i1[j], (*exp1) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_ulong_array1(&temp, &texp, &talloc, p2, mults, num, bits, 0); } else if (bits1 <= 2*FLINT_BITS) /* intermed comps fit two words */ { for (j = 0; j < 2*prod; j++) p2[j] = 0; /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_ulong_array2(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3) { /* check for exponent overflow: not exact division */ if (max_exp1[j] + max_exp3[k] >= prod) { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup; } _fmpz_mpoly_submul_array1_slong2(p2, (*poly1) + i1[j], (*exp1) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_ulong_array2(&temp, &texp, &talloc, p2, mults, num, bits, 0); } else /* intermed comps fit three words */ { for (j = 0; j < 3*prod; j++) p2[j] = 0; /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_ulong_array(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3) { /* check for exponent overflow: not exact division */ if (max_exp1[j] + max_exp3[k] >= prod) { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup; } _fmpz_mpoly_submul_array1_slong(p2, (*poly1) + i1[j], (*exp1) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_ulong_array(&temp, &texp, &talloc, p2, mults, num, bits, 0); } /* for terms where there may be a nonzero quotient if exact */ if (i < l1) { /* tightly pack chunk exponents */ mpoly_pack_monomials_tight(texp, texp, tlen, mults, num, bits); /* set starting index for quotient chunk we are about to compute */ i1[i] = len; /* if chunk is nonzero */ if (tlen != 0) { /* compute quotient chunk and set length of quotient chunk */ n1[i] = _fmpz_mpoly_divides_array_tight(poly1, exp1, alloc, len, temp, texp, tlen, poly3 + i3[0], e3 + i3[0], n3[0], mults, num); /* check quotient was exact */ if (n1[i] == 0) /* not an exact division */ { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup; } } else n1[i] = 0; /* compute maximum packed exponent for chunk */ max_exp = 0; for (j = 0; j < n1[i]; j++) { if ((*exp1)[i1[i] + j] > max_exp) max_exp = (*exp1)[i1[i] + j]; } max_exp1[i] = max_exp; /* check the quotient chunk didn't have large coefficients */ if (FLINT_ABS(_fmpz_vec_max_bits((*poly1) + len, n1[i])) > SMALL_FMPZ_BITCOUNT_MAX) { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto big; } /* abs bound and sum of abs vals of coeffs of quotient chunk */ _fmpz_vec_sum_max_bits(&b1[i], &maxb1[i], (*poly1)+i1[i], n1[i]); /* update length of output quotient poly */ len += n1[i]; } else /* should be zero quotient, check coefficient is zero */ { /* for each coeff in chunk */ for (j = 0; j < tlen; j++) { /* if coeff is nonzero */ if (!fmpz_is_zero(temp + j)) /* not an exact division */ { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup; } } } } } big: /* if not done, use multiprecision coeffs instead */ if (len == 0) { fmpz * p2 = (fmpz *) TMP_ALLOC(prod*sizeof(fmpz)); for (j = 0; j < prod; j++) fmpz_init(p2 + j); /* for each chunk of poly2 */ for (i = 0; i < l2 - skip; i++) { for (j = 0; j < prod; j++) fmpz_zero(p2 + j); /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_fmpz_array(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3) { /* check for exponent overflow: not exact division */ if (max_exp1[j] + max_exp3[k] >= prod) { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup; } _fmpz_mpoly_submul_array1_fmpz(p2, (*poly1) + i1[j], (*exp1) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_fmpz_array(&temp, &texp, &talloc, p2, mults, num, bits, 0); /* for terms where there may be a nonzero quotient if exact */ if (i < l1) { /* tightly pack chunk exponents */ mpoly_pack_monomials_tight(texp, texp, tlen, mults, num, bits); /* set starting index of quotient chunk we are about to compute */ i1[i] = len; /* if chunk is nonzero */ if (tlen != 0) { /* compute quotient chunk and set length of quotient chunk */ n1[i] = _fmpz_mpoly_divides_array_tight(poly1, exp1, alloc, len, temp, texp, tlen, poly3 + i3[0], e3 + i3[0], n3[0], mults, num); /* check quotient was exact */ if (n1[i] == 0) /* not an exact division */ { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup2; } } else n1[i] = 0; /* compute maximum packed exponent for chunk */ max_exp = 0; for (j = 0; j < n1[i]; j++) { if ((*exp1)[i1[i] + j] > max_exp) max_exp = (*exp1)[i1[i] + j]; } max_exp1[i] = max_exp; /* update length of output quotient poly */ len += n1[i]; } else /* should be zero quotient, check coefficient is zero */ { /* for each coeff in chunk */ for (j = 0; j < tlen; j++) { if (!fmpz_is_zero(temp + j)) /* not an exact division */ { for (j = 0; j < len; j++) _fmpz_demote((*poly1) + j); len = 0; goto cleanup2; } } } } cleanup2: for (j = 0; j < prod; j++) fmpz_clear(p2 + j); } /* if quotient was exact */ if (len != 0) { /* unpack monomials of quotient */ mpoly_unpack_monomials_tight((*exp1), (*exp1), len, mults, num, bits); /* put main variable back in quotient */ for (i = 0; i < l1; i++) { for (j = 0; j < n1[i]; j++) (*exp1)[i1[i] + j] += ((l1 - i - 1) << shift); } } cleanup: for (j = 0; j < talloc; j++) fmpz_clear(temp + j); flint_free(temp); flint_free(texp); TMP_END; return len; } /* Use dense array exact division to set poly1 to poly2/poly3 in num variables, given a list of multipliers to tightly pack exponents and a number of bits for the fields of the exponents of the result, assuming no aliasing. The array "mults" is a list of bases to be used in encoding the array indices from the exponents. The function reallocates its output and returns the length of its output if the quotient is exact, or zero if not. It is assumed that poly2 is not zero. */ slong _fmpz_mpoly_divides_array(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits) { slong i; ulong * e2, * e3; slong len, prod; TMP_INIT; /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prod = 1; for (i = 0; i < num; i++) prod *= mults[i]; /* if array size will be too large, chunk the polynomials */ if (prod > MAX_ARRAY_SIZE) return _fmpz_mpoly_divides_array_chunked(poly1, exp1, alloc, poly2, exp2, len2, poly3, exp3, len3, mults, num - 1, bits); TMP_START; e2 = (ulong *) TMP_ALLOC(len2*sizeof(ulong)); e3 = (ulong *) TMP_ALLOC(len3*sizeof(ulong)); /* pack input exponents tightly with mixed bases specified by "mults" */ mpoly_pack_monomials_tight(e2, exp2, len2, mults, num, bits); mpoly_pack_monomials_tight(e3, exp3, len3, mults, num, bits); /* do exact quotient with divisibility test on tightly packed polys */ len = _fmpz_mpoly_divides_array_tight(poly1, exp1, alloc, 0, poly2, e2, len2, poly3, e3, len3, mults, num); /* unpack output quotient exponents */ mpoly_unpack_monomials_tight((*exp1), (*exp1), len, mults, num, bits); TMP_END; return len; } /* Return 1 if exact quotient and set poly1 to poly2/poly3, else return 0 if not exact quotient or -1 if array method not suitable. */ int fmpz_mpoly_divides_array(fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) { slong i, bits, exp_bits, N, len = 0, array_size; ulong max, * max_fields1, * max_fields2, * max_fields3; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; int free2 = 0, free3 = 0; int res = -1; TMP_INIT; /* check divisor is not zero */ if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divides_array"); /* dividend is zero */ if (poly2->length == 0) { fmpz_mpoly_zero(poly1, ctx); return 1; } TMP_START; /* compute maximum fields */ max_fields1 = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); max_fields2 = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); max_fields3 = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); mpoly_max_fields_ui_sp(max_fields2, poly2->exps, poly2->length, poly2->bits, ctx->minfo); mpoly_max_fields_ui_sp(max_fields3, poly3->exps, poly3->length, poly3->bits, ctx->minfo); max = 0; for (i = 0; i < ctx->minfo->nfields; i++) { if (max_fields2[i] > max) max = max_fields2[i]; /* cannot be an exact division if variable in dividend has smaller degree than corresponding variable in divisor */ if (max_fields2[i] < max_fields3[i]) { res = 0; goto cleanup; } } /* compute number of bits required for output exponents */ bits = FLINT_BIT_COUNT(max); exp_bits = FLINT_MAX(WORD(8), bits + 1); exp_bits = FLINT_MAX(exp_bits, poly2->bits); exp_bits = FLINT_MAX(exp_bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); /* array division expects each exponent vector in one word */ /* current code is wrong for reversed orderings */ if (N != 1 || mpoly_ordering_isrev(ctx->minfo)) goto cleanup; /* compute bounds on output exps, used as mixed bases for packing exps */ array_size = 1; for (i = 0; i < ctx->minfo->nfields - 1; i++) { max_fields2[i]++; array_size *= max_fields2[i]; } max_fields2[ctx->minfo->nfields - 1]++; /* if exponents too large for array multiplication, exit silently */ if (array_size > MAX_ARRAY_SIZE) goto cleanup; /* expand input exponents to same number of bits as output */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* handle aliasing and do array division */ if (poly1 == poly2 || poly1 == poly3) { fmpz_mpoly_t temp; fmpz_mpoly_init2(temp, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(temp, exp_bits, ctx); temp->bits = exp_bits; len = _fmpz_mpoly_divides_array(&temp->coeffs, &temp->exps, &temp->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, (slong *) max_fields2, ctx->minfo->nfields, exp_bits); fmpz_mpoly_swap(temp, poly1, ctx); fmpz_mpoly_clear(temp, ctx); } else { fmpz_mpoly_fit_length(poly1, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(poly1, exp_bits, ctx); poly1->bits = exp_bits; len = _fmpz_mpoly_divides_array(&poly1->coeffs, &poly1->exps, &poly1->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, (slong *) max_fields2, ctx->minfo->nfields, exp_bits); } _fmpz_mpoly_set_length(poly1, len, ctx); /* Check that the maximum degrees for each variable are correct. This can only happen if there was an overflow in the tightly packed exponents, which can only happen if the division was not exact. If no overflow is detected here, none happened and the division was provably exact. */ if (len != 0) { mpoly_max_fields_ui_sp(max_fields1, poly1->exps, poly1->length, poly1->bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { /* we incremented max_fields2[i] by 1 previously, so add 1 here */ if (max_fields2[i] != max_fields1[i] + max_fields3[i] + 1) { fmpz_mpoly_zero(poly1, ctx); len = 0; break; } } } /* len will be nonzero if quotient was exact */ res = len != 0; if (free2) flint_free(exp2); if (free3) flint_free(exp3); cleanup: TMP_END; return res; } flint-3.1.3/src/fmpz_mpoly/divides_heap_threaded.c000066400000000000000000002004151461254215100222500ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #if FLINT_KNOW_STRONG_ORDER #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" /* a thread safe mpoly supports three mutating operations - init from an array of terms - append an array of terms - clear out contents to a normal mpoly */ typedef struct _fmpz_mpoly_ts_struct { fmpz * volatile coeffs; /* this is coeff_array[idx] */ ulong * volatile exps; /* this is exp_array[idx] */ volatile slong length; slong alloc; flint_bitcnt_t bits; flint_bitcnt_t idx; ulong * exp_array[FLINT_BITS]; fmpz * coeff_array[FLINT_BITS]; } fmpz_mpoly_ts_struct; typedef fmpz_mpoly_ts_struct fmpz_mpoly_ts_t[1]; /* Bcoeff is changed */ static void fmpz_mpoly_ts_init(fmpz_mpoly_ts_t A, fmpz * Bcoeff, ulong * Bexp, slong Blen, flint_bitcnt_t bits, slong N) { slong i; flint_bitcnt_t idx = FLINT_BIT_COUNT(Blen); idx = (idx <= 8) ? 0 : idx - 8; for (i = 0; i < FLINT_BITS; i++) { A->exp_array[i] = NULL; A->coeff_array[i] = NULL; } A->bits = bits; A->idx = idx; A->alloc = WORD(256) << idx; A->exps = A->exp_array[idx] = (ulong *) flint_malloc(N*A->alloc*sizeof(ulong)); A->coeffs = A->coeff_array[idx] = (fmpz *) flint_calloc(A->alloc, sizeof(fmpz)); A->length = Blen; for (i = 0; i < Blen; i++) { fmpz_swap(A->coeffs + i, Bcoeff + i); mpoly_monomial_set(A->exps + N*i, Bexp + N*i, N); } } #if 0 static void fmpz_mpoly_ts_print(const fmpz_mpoly_ts_t B, const char ** x, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_t A; A->length = B->length; A->alloc = B->alloc; A->coeffs = B->coeffs; A->exps = B->exps; A->bits = B->bits; fmpz_mpoly_print_pretty(A, x, ctx); fmpz_mpoly_assert_canonical(A, ctx); } #endif static void fmpz_mpoly_ts_clear(fmpz_mpoly_ts_t A) { slong i; for (i = 0; i < A->length; i++) { fmpz_clear(A->coeffs + i); } for (i = 0; i < FLINT_BITS; i++) { if (A->exp_array[i] != NULL) { FLINT_ASSERT(A->coeff_array[i] != NULL); flint_free(A->coeff_array[i]); flint_free(A->exp_array[i]); } } } static void fmpz_mpoly_ts_clear_poly(fmpz_mpoly_t Q, fmpz_mpoly_ts_t A) { if (Q->alloc != 0) { slong i; FLINT_ASSERT(Q->exps != NULL); FLINT_ASSERT(Q->coeffs != NULL); for (i = 0; i < Q->alloc; i++) { _fmpz_demote(Q->coeffs + i); } flint_free(Q->exps); flint_free(Q->coeffs); } Q->exps = A->exps; Q->coeffs = A->coeffs; Q->bits = A->bits; Q->alloc = A->alloc; Q->length = A->length; A->length = 0; A->coeff_array[A->idx] = NULL; A->exp_array[A->idx] = NULL; fmpz_mpoly_ts_clear(A); } /* put B on the end of A - Bcoeff is changed*/ static void fmpz_mpoly_ts_append(fmpz_mpoly_ts_t A, fmpz * Bcoeff, ulong * Bexps, slong Blen, slong N) { /* TODO: this needs barriers on non-x86 */ slong i; ulong * oldexps = A->exps; fmpz * oldcoeffs = A->coeffs; slong oldlength = A->length; slong newlength = A->length + Blen; if (newlength <= A->alloc) { /* write new terms first */ for (i = 0; i < Blen; i++) { fmpz_swap(oldcoeffs + oldlength + i, Bcoeff + i); mpoly_monomial_set(oldexps + N*(oldlength + i), Bexps + N*i, N); } } else { slong newalloc; ulong * newexps; fmpz * newcoeffs; flint_bitcnt_t newidx; newidx = FLINT_BIT_COUNT(newlength - 1); newidx = (newidx > 8) ? newidx - 8 : 0; FLINT_ASSERT(newidx > A->idx); newalloc = UWORD(256) << newidx; FLINT_ASSERT(newlength <= newalloc); newexps = A->exp_array[newidx] = (ulong *) flint_malloc(N*newalloc*sizeof(ulong)); newcoeffs = A->coeff_array[newidx] = (fmpz *) flint_calloc(newalloc, sizeof(fmpz)); for (i = 0; i < oldlength; i++) { newcoeffs[i] = oldcoeffs[i]; /* just copy the bits */ mpoly_monomial_set(newexps + N*i, oldexps + N*i, N); } for (i = 0; i < Blen; i++) { fmpz_swap(newcoeffs + oldlength + i, Bcoeff + i); mpoly_monomial_set(newexps + N*(oldlength + i), Bexps + N*i, N); } A->alloc = newalloc; A->exps = newexps; A->coeffs = newcoeffs; A->idx = newidx; /* do not free oldcoeff/exps as other threads may be using them */ } /* update length at the very end */ A->length = newlength; } /* a chunk holds an exponent range on the dividend */ typedef struct _divides_heap_chunk_struct { fmpz_mpoly_t polyC; struct _divides_heap_chunk_struct * next; ulong * emin; ulong * emax; slong startidx; slong endidx; int upperclosed; volatile int lock; volatile int producer; volatile slong ma; volatile slong mq; int Cinited; } divides_heap_chunk_struct; typedef divides_heap_chunk_struct divides_heap_chunk_t[1]; /* the base struct includes a linked list of chunks */ typedef struct { #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif divides_heap_chunk_struct * head; divides_heap_chunk_struct * tail; divides_heap_chunk_struct * volatile cur; fmpz_mpoly_t polyA; fmpz_mpoly_t polyB; fmpz_mpoly_ts_t polyQ; const fmpz_mpoly_ctx_struct * ctx; slong length; slong N; flint_bitcnt_t bits; slong polyBcoeff_bits; ulong * cmpmask; int failed; } divides_heap_base_struct; typedef divides_heap_base_struct divides_heap_base_t[1]; /* the worker struct has a big chunk of memory in the stripe_t and two polys for work space */ typedef struct _worker_arg_struct { divides_heap_base_struct * H; fmpz_mpoly_stripe_t S; fmpz_mpoly_t polyT1; fmpz_mpoly_t polyT2; } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void divides_heap_base_init(divides_heap_base_t H) { H->head = NULL; H->tail = NULL; H->cur = NULL; H->ctx = NULL; H->length = 0; H->N = 0; H->bits = 0; H->cmpmask = NULL; } static void divides_heap_chunk_clear(divides_heap_chunk_t L, divides_heap_base_t H) { if (L->Cinited) { fmpz_mpoly_clear(L->polyC, H->ctx); } } static int divides_heap_base_clear(fmpz_mpoly_t Q, divides_heap_base_t H) { divides_heap_chunk_struct * L = H->head; while (L != NULL) { divides_heap_chunk_struct * nextL = L->next; divides_heap_chunk_clear(L, H); flint_free(L); L = nextL; } H->head = NULL; H->tail = NULL; H->cur = NULL; H->ctx = NULL; H->length = 0; H->N = 0; H->bits = 0; H->cmpmask = NULL; if (H->failed) { fmpz_mpoly_zero(Q, H->ctx); fmpz_mpoly_ts_clear(H->polyQ); return 0; } else { fmpz_mpoly_ts_clear_poly(Q, H->polyQ); return 1; } } static void divides_heap_base_add_chunk(divides_heap_base_t H, divides_heap_chunk_t L) { L->next = NULL; if (H->tail == NULL) { FLINT_ASSERT(H->head == NULL); H->tail = L; H->head = L; } else { divides_heap_chunk_struct * tail = H->tail; FLINT_ASSERT(tail->next == NULL); tail->next = L; H->tail = L; } H->length++; } /* A = D - (a stripe of B * C) S->startidx and S->endidx are assumed to be correct that is, we expect and successive calls to keep B decreasing C the same saveD: 0 means we can modify coeffs of input D 1 means we must not modify coeffs of input D */ static slong _fmpz_mpoly_mulsub_stripe1(fmpz ** A_coeff, ulong ** A_exp, slong * A_alloc, const fmpz * Dcoeff, const ulong * Dexp, slong Dlen, int saveD, const fmpz * Bcoeff, const ulong * Bexp, slong Blen, const fmpz * Ccoeff, const ulong * Cexp, slong Clen, const fmpz_mpoly_stripe_t S) { int upperclosed; slong startidx, endidx; ulong prev_startidx; ulong maskhi = S->cmpmask[0]; ulong emax = S->emax[0]; ulong emin = S->emin[0]; slong i, j; slong next_loc = Blen + 4; /* something bigger than heap can ever be */ slong heap_len = 1; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; slong Aalloc = *A_alloc; fmpz * Acoeff = *A_coeff; ulong * Aexp = *A_exp; ulong exp; slong * ends; ulong texp; slong * hind; int small; ulong acc_sm[3], pp0, pp1; FLINT_ASSERT(S->N == 1); i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); ends = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); startidx = *S->startidx; endidx = *S->endidx; upperclosed = S->upperclosed; emax = S->emax[0]; emin = S->emin[0]; /* put all the starting nodes on the heap */ prev_startidx = -UWORD(1); for (i = 0; i < Blen; i++) { if (startidx < Clen) { texp = Bexp[i] + Cexp[startidx]; FLINT_ASSERT(mpoly_monomial_cmp1(emax, texp, maskhi) > -upperclosed); } while (startidx > 0) { texp = Bexp[i] + Cexp[startidx - 1]; if (mpoly_monomial_cmp1(emax, texp, maskhi) <= -upperclosed) { break; } startidx--; } if (endidx < Clen) { texp = Bexp[i] + Cexp[endidx]; FLINT_ASSERT(mpoly_monomial_cmp1(emin, texp, maskhi) > 0); } while (endidx > 0) { texp = Bexp[i] + Cexp[endidx - 1]; if (mpoly_monomial_cmp1(emin, texp, maskhi) <= 0) { break; } endidx--; } ends[i] = endidx; hind[i] = 2*startidx + 1; if ( (startidx < endidx) && (((ulong)startidx) < prev_startidx) ) { x = chain + i; x->i = i; x->j = startidx; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } prev_startidx = startidx; } /* set the indices for the next time mul is called */ *S->startidx = startidx; *S->endidx = endidx; /* whether input coeffs are small, thus output coeffs fit in three words */ FLINT_ASSERT(ends[0] >= startidx); FLINT_ASSERT(S->coeff_bits == FLINT_ABS(_fmpz_vec_max_bits(Ccoeff, Clen))); small = S->coeff_bits <= SMALL_FMPZ_BITCOUNT_MAX && _fmpz_mpoly_fits_small(Bcoeff, Blen) && FLINT_ABS(_fmpz_vec_max_bits(Dcoeff, Dlen)) < 3*FLINT_BITS - 3; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt1(Dexp[Di], exp, maskhi)) { _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, 1); Aexp[Alen] = Dexp[Di]; if (saveD) fmpz_set(Acoeff + Alen, Dcoeff + Di); else fmpz_swap(Acoeff + Alen, (fmpz *)(Dcoeff + Di)); Alen++; Di++; } _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, 1); Aexp[Alen] = exp; if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; if (Di < Dlen && Dexp[Di] == exp) { _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, Dcoeff + Di); Di++; } do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; FLINT_ASSERT(startidx <= x->j); FLINT_ASSERT(x->j < ends[0]); FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[x->i])); FLINT_ASSERT(!COEFF_IS_MPZ(Ccoeff[x->j])); smul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], FLINT_SIGN_EXT(pp1), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; FLINT_ASSERT(startidx <= x->j); FLINT_ASSERT(x->j < ends[0]); FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[x->i])); FLINT_ASSERT(!COEFF_IS_MPZ(Ccoeff[x->j])); smul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], FLINT_SIGN_EXT(pp1), pp1, pp0); } } while (heap_len > 1 && heap[1].exp == exp); fmpz_set_signed_uiuiui(Acoeff + Alen, acc_sm[2], acc_sm[1], acc_sm[0]); } else { if (Di < Dlen && Dexp[Di] == exp) { fmpz_set(Acoeff + Alen, Dcoeff + Di); Di++; } else { fmpz_zero(Acoeff + Alen); } do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; fmpz_submul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; fmpz_submul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); } } while (heap_len > 1 && heap[1].exp == exp); } Alen += !fmpz_is_zero(Acoeff + Alen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < ends[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if ( (j + 1 < ends[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } } } FLINT_ASSERT(Di <= Dlen); _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + Dlen - Di, 1); if (saveD) _fmpz_vec_set(Acoeff + Alen, Dcoeff + Di, Dlen - Di); else _fmpz_vec_swap(Acoeff + Alen, (fmpz *)(Dcoeff + Di), Dlen - Di); mpoly_copy_monomials(Aexp + 1*Alen, Dexp + 1*Di, Dlen - Di, 1); Alen += Dlen - Di; *A_coeff = Acoeff; *A_exp = Aexp; *A_alloc = Aalloc; return Alen; } static slong _fmpz_mpoly_mulsub_stripe(fmpz ** A_coeff, ulong ** A_exp, slong * A_alloc, const fmpz * Dcoeff, const ulong * Dexp, slong Dlen, int saveD, const fmpz * Bcoeff, const ulong * Bexp, slong Blen, const fmpz * Ccoeff, const ulong * Cexp, slong Clen, const fmpz_mpoly_stripe_t S) { int upperclosed; slong startidx, endidx; ulong prev_startidx; ulong * emax = S->emax; ulong * emin = S->emin; slong N = S->N; slong i, j; slong next_loc = Blen + 4; /* something bigger than heap can ever be */ slong heap_len = 1; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; slong Aalloc = *A_alloc; fmpz * Acoeff = *A_coeff; ulong * Aexp = *A_exp; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * ends; ulong * texp; slong * hind; int small; ulong acc_sm[3], pp0, pp1; i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); ends = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); exps = (ulong *)(S->big_mem + i); i += Blen*N*sizeof(ulong); exp_list = (ulong **)(S->big_mem + i); i += Blen*sizeof(ulong *); texp = (ulong *)(S->big_mem + i); i += N*sizeof(ulong); FLINT_ASSERT(i <= S->big_mem_alloc); exp_next = 0; startidx = *S->startidx; endidx = *S->endidx; upperclosed = S->upperclosed; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* put all the starting nodes on the heap */ prev_startidx = -UWORD(1); for (i = 0; i < Blen; i++) { if (startidx < Clen) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*startidx, N); FLINT_ASSERT(mpoly_monomial_cmp(emax, texp, N, S->cmpmask) > -upperclosed); } while (startidx > 0) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*(startidx - 1), N); if (mpoly_monomial_cmp(emax, texp, N, S->cmpmask) <= -upperclosed) { break; } startidx--; } if (endidx < Clen) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*endidx, N); FLINT_ASSERT(mpoly_monomial_cmp(emin, texp, N, S->cmpmask) > 0); } while (endidx > 0) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*(endidx - 1), N); if (mpoly_monomial_cmp(emin, texp, N, S->cmpmask) <= 0) { break; } endidx--; } ends[i] = endidx; hind[i] = 2*startidx + 1; if ( (startidx < endidx) && (((ulong)startidx) < prev_startidx) ) { x = chain + i; x->i = i; x->j = startidx; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } prev_startidx = startidx; } *S->startidx = startidx; *S->endidx = endidx; /* whether input coeffs are small, thus output coeffs fit in three words */ FLINT_ASSERT(ends[0] >= startidx); FLINT_ASSERT(S->coeff_bits == FLINT_ABS(_fmpz_vec_max_bits(Ccoeff, Clen))); small = S->coeff_bits <= SMALL_FMPZ_BITCOUNT_MAX && _fmpz_mpoly_fits_small(Bcoeff, Blen) && FLINT_ABS(_fmpz_vec_max_bits(Dcoeff, Dlen)) < 3*FLINT_BITS - 3; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt(Dexp + N*Di, exp, N, S->cmpmask)) { _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N); mpoly_monomial_set(Aexp + N*Alen, Dexp + N*Di, N); if (saveD) fmpz_set(Acoeff + Alen, Dcoeff + Di); else fmpz_swap(Acoeff + Alen, (fmpz *)(Dcoeff + Di)); Alen++; Di++; } _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N); mpoly_monomial_set(Aexp + N*Alen, exp, N); if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; if (Di < Dlen && mpoly_monomial_equal(Dexp + N*Di, exp, N)) { _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, Dcoeff + Di); Di++; } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; FLINT_ASSERT(startidx <= x->j); FLINT_ASSERT(x->j < ends[0]); FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[x->i])); FLINT_ASSERT(!COEFF_IS_MPZ(Ccoeff[x->j])); smul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], FLINT_SIGN_EXT(pp1), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; FLINT_ASSERT(startidx <= x->j); FLINT_ASSERT(x->j < ends[0]); FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[x->i])); FLINT_ASSERT(!COEFF_IS_MPZ(Ccoeff[x->j])); smul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], FLINT_SIGN_EXT(pp1), pp1, pp0); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); fmpz_set_signed_uiuiui(Acoeff + Alen, acc_sm[2], acc_sm[1], acc_sm[0]); } else { if (Di < Dlen && mpoly_monomial_equal(Dexp + N*Di, exp, N)) { fmpz_set(Acoeff + Alen, Dcoeff + Di); Di++; } else { fmpz_zero(Acoeff + Alen); } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; FLINT_ASSERT(startidx <= x->j); FLINT_ASSERT(x->j < ends[0]); fmpz_submul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; FLINT_ASSERT(startidx <= x->j); FLINT_ASSERT(x->j < ends[0]); fmpz_submul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } Alen += !fmpz_is_zero(Acoeff + Alen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < ends[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } /* should we go up? */ if ( (j + 1 < ends[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } } } FLINT_ASSERT(Di <= Dlen); _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + Dlen - Di, N); if (saveD) _fmpz_vec_set(Acoeff + Alen, Dcoeff + Di, Dlen - Di); else _fmpz_vec_swap(Acoeff + Alen, (fmpz *)(Dcoeff + Di), Dlen - Di); mpoly_copy_monomials(Aexp + N*Alen, Dexp + N*Di, Dlen - Di, N); Alen += Dlen - Di; *A_coeff = Acoeff; *A_exp = Aexp; *A_alloc = Aalloc; return Alen; } /* Q = stripe of A/B (assume A != 0) return Qlen = 0 if exact division is impossible */ static slong _fmpz_mpoly_divides_stripe1( fmpz ** Q_coeff, ulong ** Q_exp, slong * Q_alloc, const fmpz * Acoeff, const ulong * Aexp, slong Alen, const fmpz * Bcoeff, const ulong * Bexp, slong Blen, const fmpz_mpoly_stripe_t S) { flint_bitcnt_t bits = S->bits; ulong emin = S->emin[0]; ulong cmpmask = S->cmpmask[0]; ulong texp; int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Qlen; slong Qalloc = * Q_alloc; fmpz * Qcoeff = * Q_coeff; ulong * Qexp = * Q_exp; ulong exp; ulong mask; slong * hind; fmpz_t acc_lg, r; ulong acc_sm[3]; slong Acoeffbits; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; int small; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(S->N == 1); Acoeffbits = _fmpz_vec_max_bits(Acoeff, Alen); FLINT_ASSERT(S->coeff_bits == FLINT_ABS(_fmpz_vec_max_bits(Bcoeff, Blen))); /* whether intermediate computations A - Q*B will fit in three words */ /* allow one bit for sign, one bit for subtraction NOT QUITE */ small = S->coeff_bits <= SMALL_FMPZ_BITCOUNT_MAX && FLINT_ABS(Acoeffbits) <= (S->coeff_bits + FLINT_BIT_COUNT(Blen) + SMALL_FMPZ_BITCOUNT_MAX); next_loc = Blen + 4; /* something bigger than heap can ever be */ i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); fmpz_init(acc_lg); fmpz_init(r); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); Qlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; HEAP_ASSIGN(heap[1], Aexp[0], x); FLINT_ASSERT(mpoly_monomial_cmp1(Aexp[0], emin, cmpmask) >= 0); if (small) { FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[0])); lc_abs = FLINT_ABS(Bcoeff[0]); lc_sign = FLINT_SIGN_EXT(Bcoeff[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_exact_division; FLINT_ASSERT(mpoly_monomial_cmp1(exp, emin, cmpmask) >= 0); _fmpz_mpoly_fit_length(&Qcoeff, &Qexp, &Qalloc, Qlen + 1, 1); lt_divides = mpoly_monomial_divides1(Qexp + Qlen, exp, Bexp[0], mask); if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, Acoeff + x->j); } else { FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[x->i])); FLINT_ASSERT(!COEFF_IS_MPZ(Qcoeff[x->j])); _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, Bcoeff[x->i], Qcoeff[x->j]); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else { fmpz_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { fmpz_add(acc_lg, acc_lg, Acoeff + x->j); } else { fmpz_submul(acc_lg, Bcoeff + x->i, Qcoeff + x->j); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; FLINT_ASSERT(mpoly_monomial_cmp1(Aexp[x->j], emin, cmpmask) >= 0); _mpoly_heap_insert1(heap, Aexp[x->j], x, &next_loc, &heap_len, cmpmask); } } else { /* should we go up */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } } } if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) { continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr != UWORD(0)) goto not_exact_division; if (qq <= COEFF_MAX) { _fmpz_demote(Qcoeff + Qlen); Qcoeff[Qlen] = qq; if (ds != lc_sign) Qcoeff[Qlen] = -Qcoeff[Qlen]; } else { small = 0; fmpz_set_ui(Qcoeff + Qlen, qq); if (ds != lc_sign) fmpz_neg(Qcoeff + Qlen, Qcoeff + Qlen); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); fmpz_fdiv_qr(Qcoeff + Qlen, r, acc_lg, Bcoeff + 0); if (!fmpz_is_zero(r)) goto not_exact_division; } } else { if (fmpz_is_zero(acc_lg)) { continue; } fmpz_fdiv_qr(Qcoeff + Qlen, r, acc_lg, Bcoeff + 0); if (!fmpz_is_zero(r)) { goto not_exact_division; } } if (!lt_divides) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } s = 1; Qlen++; } cleanup: fmpz_clear(acc_lg); fmpz_clear(r); *Q_alloc = Qalloc; *Q_coeff = Qcoeff; *Q_exp = Qexp; return Qlen; not_exact_division: Qlen = 0; goto cleanup; } static slong _fmpz_mpoly_divides_stripe( fmpz ** Q_coeff, ulong ** Q_exp, slong * Q_alloc, const fmpz * Acoeff, const ulong * Aexp, slong Alen, const fmpz * Bcoeff, const ulong * Bexp, slong Blen, const fmpz_mpoly_stripe_t S) { flint_bitcnt_t bits = S->bits; slong N = S->N; int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Qlen; slong Qalloc = * Q_alloc; fmpz * Qcoeff = * Q_coeff; ulong * Qexp = * Q_exp; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; fmpz_t acc_lg, r; ulong acc_sm[3]; slong Acoeffbits; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; int small; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); Acoeffbits = _fmpz_vec_max_bits(Acoeff, Alen); FLINT_ASSERT(S->coeff_bits == FLINT_ABS(_fmpz_vec_max_bits(Bcoeff, Blen))); /* whether intermediate computations A - Q*B will fit in three words */ /* allow one bit for sign, one bit for subtraction NOT QUITE */ small = S->coeff_bits <= SMALL_FMPZ_BITCOUNT_MAX && FLINT_ABS(Acoeffbits) <= (S->coeff_bits + FLINT_BIT_COUNT(Blen) + SMALL_FMPZ_BITCOUNT_MAX); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); next_loc = Blen + 4; /* something bigger than heap can ever be */ i = 0; hind = (slong *) (S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); exps = (ulong *)(S->big_mem + i); i += Blen*N*sizeof(ulong); exp_list = (ulong **)(S->big_mem + i); i += Blen*sizeof(ulong *); exp = (ulong *)(S->big_mem + i); i += N*sizeof(ulong); FLINT_ASSERT(i <= S->big_mem_alloc); fmpz_init(acc_lg); fmpz_init(r); exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; Qlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; FLINT_ASSERT(mpoly_monomial_cmp(Aexp + N*0, S->emin, N, S->cmpmask) >= 0); mpoly_monomial_set(heap[1].exp, Aexp + N*0, N); if (small) { FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[0])); lc_abs = FLINT_ABS(Bcoeff[0]); lc_sign = FLINT_SIGN_EXT(Bcoeff[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { _fmpz_mpoly_fit_length(&Qcoeff, &Qexp, &Qalloc, Qlen + 1, N); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; lt_divides = mpoly_monomial_divides(Qexp + N*Qlen, exp, Bexp + N*0, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto not_exact_division; lt_divides = mpoly_monomial_divides_mp(Qexp + N*Qlen, exp, Bexp + N*0, N, bits); } FLINT_ASSERT(mpoly_monomial_cmp(exp, S->emin, N, S->cmpmask) >= 0); if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, Acoeff + x->j); } else { hind[x->i] |= WORD(1); FLINT_ASSERT(!COEFF_IS_MPZ(Bcoeff[x->i])); FLINT_ASSERT(!COEFF_IS_MPZ(Qcoeff[x->j])); _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, Bcoeff[x->i], Qcoeff[x->j]); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else { fmpz_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { fmpz_add(acc_lg, acc_lg, Acoeff + x->j); } else { hind[x->i] |= WORD(1); fmpz_submul(acc_lg, Bcoeff + x->i, Qcoeff + x->j); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexp + x->j*N, N); FLINT_ASSERT(mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } } else { /* should we go up */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } } } if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) { continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr != UWORD(0)) goto not_exact_division; if (qq <= COEFF_MAX) { _fmpz_demote(Qcoeff + Qlen); Qcoeff[Qlen] = qq; if (ds != lc_sign) Qcoeff[Qlen] = -Qcoeff[Qlen]; } else { small = 0; fmpz_set_ui(Qcoeff + Qlen, qq); if (ds != lc_sign) fmpz_neg(Qcoeff + Qlen, Qcoeff + Qlen); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); fmpz_fdiv_qr(Qcoeff + Qlen, r, acc_lg, Bcoeff + 0); if (!fmpz_is_zero(r)) goto not_exact_division; } } else { if (fmpz_is_zero(acc_lg)) { continue; } fmpz_fdiv_qr(Qcoeff + Qlen, r, acc_lg, Bcoeff + 0); if (!fmpz_is_zero(r)) { goto not_exact_division; } } if (!lt_divides) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } s = 1; Qlen++; } cleanup: fmpz_clear(acc_lg); fmpz_clear(r); *Q_alloc = Qalloc; *Q_coeff = Qcoeff; *Q_exp = Qexp; return Qlen; not_exact_division: Qlen = 0; goto cleanup; } static slong chunk_find_exp(ulong * exp, slong a, const divides_heap_base_t H) { slong N = H->N; slong b = H->polyA->length; const ulong * Aexp = H->polyA->exps; try_again: FLINT_ASSERT(b >= a); FLINT_ASSERT(a > 0); FLINT_ASSERT(mpoly_monomial_cmp(Aexp + N*(a - 1), exp, N, H->cmpmask) >= 0); FLINT_ASSERT(b >= H->polyA->length || mpoly_monomial_cmp(Aexp + N*b, exp, N, H->cmpmask) < 0); if (b - a < 5) { slong i = a; while (i < b && mpoly_monomial_cmp(Aexp + N*i, exp, N, H->cmpmask) >= 0) { i++; } return i; } else { slong c = a + (b - a)/2; if (mpoly_monomial_cmp(Aexp + N*c, exp, N, H->cmpmask) < 0) { b = c; } else { a = c; } goto try_again; } } static void stripe_fit_length(fmpz_mpoly_stripe_struct * S, slong new_len) { slong N = S->N; slong new_alloc; new_alloc = 0; if (N == 1) { new_alloc += new_len*sizeof(slong); new_alloc += new_len*sizeof(slong); new_alloc += 2*new_len*sizeof(slong); new_alloc += (new_len + 1)*sizeof(mpoly_heap1_s); new_alloc += new_len*sizeof(mpoly_heap_t); } else { new_alloc += new_len*sizeof(slong); new_alloc += new_len*sizeof(slong); new_alloc += 2*new_len*sizeof(slong); new_alloc += (new_len + 1)*sizeof(mpoly_heap_s); new_alloc += new_len*sizeof(mpoly_heap_t); new_alloc += new_len*N*sizeof(ulong); new_alloc += new_len*sizeof(ulong *); new_alloc += N*sizeof(ulong); } if (S->big_mem_alloc >= new_alloc) { return; } new_alloc = FLINT_MAX(new_alloc, S->big_mem_alloc + S->big_mem_alloc/4); S->big_mem_alloc = new_alloc; if (S->big_mem != NULL) { S->big_mem = (char *) flint_realloc(S->big_mem, new_alloc); } else { S->big_mem = (char *) flint_malloc(new_alloc); } } static void chunk_mulsub(worker_arg_t W, divides_heap_chunk_t L, slong q_prev_length) { divides_heap_base_struct * H = W->H; slong N = H->N; fmpz_mpoly_struct * C = L->polyC; const fmpz_mpoly_struct * B = H->polyB; const fmpz_mpoly_struct * A = H->polyA; fmpz_mpoly_ts_struct * Q = H->polyQ; fmpz_mpoly_struct * T1 = W->polyT1; fmpz_mpoly_stripe_struct * S = W->S; S->startidx = &L->startidx; S->endidx = &L->endidx; S->emin = L->emin; S->emax = L->emax; S->upperclosed = L->upperclosed; FLINT_ASSERT(S->N == N); stripe_fit_length(S, q_prev_length - L->mq); if (L->Cinited) { if (N == 1) { T1->length = _fmpz_mpoly_mulsub_stripe1( &T1->coeffs, &T1->exps, &T1->alloc, C->coeffs, C->exps, C->length, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } else { T1->length = _fmpz_mpoly_mulsub_stripe( &T1->coeffs, &T1->exps, &T1->alloc, C->coeffs, C->exps, C->length, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } fmpz_mpoly_swap(C, T1, H->ctx); } else { slong startidx, stopidx; if (L->upperclosed) { startidx = 0; stopidx = chunk_find_exp(L->emin, 1, H); } else { startidx = chunk_find_exp(L->emax, 1, H); stopidx = chunk_find_exp(L->emin, startidx, H); } L->Cinited = 1; fmpz_mpoly_init2(C, 16 + stopidx - startidx, H->ctx); /*any is OK*/ fmpz_mpoly_fit_bits(C, H->bits, H->ctx); C->bits = H->bits; if (N == 1) { C->length = _fmpz_mpoly_mulsub_stripe1( &C->coeffs, &C->exps, &C->alloc, A->coeffs + startidx, A->exps + N*startidx, stopidx - startidx, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } else { C->length = _fmpz_mpoly_mulsub_stripe( &C->coeffs, &C->exps, &C->alloc, A->coeffs + startidx, A->exps + N*startidx, stopidx - startidx, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } } L->mq = q_prev_length; } static void trychunk(worker_arg_t W, divides_heap_chunk_t L) { divides_heap_base_struct * H = W->H; slong i; slong N = H->N; fmpz_mpoly_struct * C = L->polyC; slong q_prev_length; ulong mask; const fmpz_mpoly_struct * B = H->polyB; const fmpz_mpoly_struct * A = H->polyA; fmpz_mpoly_ts_struct * Q = H->polyQ; fmpz_mpoly_struct * T2 = W->polyT2; mask = 0; for (i = 0; i < FLINT_BITS/H->bits; i++) mask = (mask << H->bits) + (UWORD(1) << (H->bits - 1)); /* return if this section has already finished processing */ if (L->mq < 0) { return; } /* process more quotient terms if available */ q_prev_length = Q->length; if (q_prev_length > L->mq) { if (L->producer == 0 && q_prev_length - L->mq < 20) return; chunk_mulsub(W, L, q_prev_length); } if (L->producer == 1) { divides_heap_chunk_struct * next; fmpz * Rcoeff; ulong * Rexp; slong Rlen; /* process the remaining quotient terms */ q_prev_length = Q->length; if (q_prev_length > L->mq) { chunk_mulsub(W, L, q_prev_length); } /* find location of remaining terms */ if (L->Cinited) { Rlen = C->length; Rexp = C->exps; Rcoeff = C->coeffs; } else { slong startidx, stopidx; if (L->upperclosed) { startidx = 0; stopidx = chunk_find_exp(L->emin, 1, H); } else { startidx = chunk_find_exp(L->emax, 1, H); stopidx = chunk_find_exp(L->emin, startidx, H); } Rlen = stopidx - startidx; Rcoeff = A->coeffs + startidx; Rexp = A->exps + N*startidx; } /* if we have remaining terms, add to quotient */ if (Rlen > 0) { fmpz_mpoly_stripe_struct * S = W->S; S->startidx = &L->startidx; S->endidx = &L->endidx; S->emin = L->emin; S->emax = L->emax; S->upperclosed = L->upperclosed; if (N == 1) { T2->length = _fmpz_mpoly_divides_stripe1( &T2->coeffs, &T2->exps, &T2->alloc, Rcoeff, Rexp, Rlen, B->coeffs, B->exps, B->length, S); } else { T2->length = _fmpz_mpoly_divides_stripe( &T2->coeffs, &T2->exps, &T2->alloc, Rcoeff, Rexp, Rlen, B->coeffs, B->exps, B->length, S); } if (T2->length == 0) { H->failed = 1; return; } else { fmpz_mpoly_ts_append(H->polyQ, T2->coeffs, T2->exps, T2->length, N); } } next = L->next; H->length--; H->cur = next; if (next != NULL) { next->producer = 1; } L->producer = 0; L->mq = -1; } return; } static void worker_loop(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; divides_heap_base_struct * H = W->H; fmpz_mpoly_stripe_struct * S = W->S; const fmpz_mpoly_struct * B = H->polyB; fmpz_mpoly_struct * T1 = W->polyT1; fmpz_mpoly_struct * T2 = W->polyT2; slong N = H->N; slong Blen = B->length; /* initialize stripe working memory */ S->N = N; S->bits = H->bits; S->coeff_bits = FLINT_ABS(H->polyBcoeff_bits); S->cmpmask = H->cmpmask; S->big_mem_alloc = 0; S->big_mem = NULL; stripe_fit_length(S, Blen); fmpz_mpoly_init2(T1, 16, H->ctx); fmpz_mpoly_fit_bits(T1, H->bits, H->ctx); T1->bits = H->bits; fmpz_mpoly_init2(T2, 16, H->ctx); fmpz_mpoly_fit_bits(T2, H->bits, H->ctx); T2->bits = H->bits; while (!H->failed) { divides_heap_chunk_struct * L; L = H->cur; if (L == NULL) { break; } while (L != NULL) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&H->mutex); #endif if (L->lock != -1) { L->lock = -1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif trychunk(W, L); #if FLINT_USES_PTHREAD pthread_mutex_lock(&H->mutex); #endif L->lock = 0; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif break; } else { #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif } L = L->next; } } fmpz_mpoly_clear(T1, H->ctx); fmpz_mpoly_clear(T2, H->ctx); flint_free(S->big_mem); return; } /* return 1 if quotient is exact */ int _fmpz_mpoly_divides_heap_threaded_pool( fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { ulong mask; int divides; fmpz_mpoly_ctx_t zctx; fmpz_mpoly_t S; slong i, k, N; flint_bitcnt_t exp_bits; ulong * cmpmask; ulong * Aexp, * Bexp; int freeAexp, freeBexp; worker_arg_struct * worker_args; fmpz_t qcoeff, r; ulong * texps, * qexps; divides_heap_base_t H; TMP_INIT; if (B->length < 2 || A->length < 2) { return fmpz_mpoly_divides_monagan_pearce(Q, A, B, ctx); } TMP_START; fmpz_init(qcoeff); fmpz_init(r); exp_bits = MPOLY_MIN_BITS; exp_bits = FLINT_MAX(exp_bits, A->bits); exp_bits = FLINT_MAX(exp_bits, B->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ Aexp = A->exps; freeAexp = 0; if (exp_bits > A->bits) { freeAexp = 1; Aexp = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexp, exp_bits, A->exps, A->bits, A->length, ctx->minfo); } Bexp = B->exps; freeBexp = 0; if (exp_bits > B->bits) { freeBexp = 1; Bexp = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexp, exp_bits, B->exps, B->bits, B->length, ctx->minfo); } fmpz_mpoly_ctx_init(zctx, ctx->minfo->nvars, ctx->minfo->ord); fmpz_mpoly_init(S, zctx); fmpz_mod(r, A->coeffs + 0, B->coeffs + 0); if (!fmpz_is_zero(r)) { divides = 0; fmpz_mpoly_zero(Q, ctx); goto cleanup1; } if (mpoly_divides_select_exps(S, zctx, num_handles, Aexp, A->length, Bexp, B->length, exp_bits)) { divides = 0; fmpz_mpoly_zero(Q, ctx); goto cleanup1; } /* At this point A and B both have at least two terms and the leading coefficients and monomials divide and the exponent selection did not give an easy exit */ divides_heap_base_init(H); H->polyA->coeffs = A->coeffs; H->polyA->exps = Aexp; H->polyA->bits = exp_bits; H->polyA->length = A->length; H->polyA->alloc = A->alloc; H->polyB->coeffs = B->coeffs; H->polyB->exps = Bexp; H->polyB->bits = exp_bits; H->polyB->length = B->length; H->polyB->alloc = B->alloc; H->polyBcoeff_bits = _fmpz_vec_max_bits(B->coeffs, B->length); H->ctx = ctx; H->bits = exp_bits; H->N = N; H->cmpmask = cmpmask; H->failed = 0; for (i = 0; i + 1 < S->length; i++) { divides_heap_chunk_struct * L; L = (divides_heap_chunk_struct *) flint_malloc( sizeof(divides_heap_chunk_struct)); L->ma = 0; L->mq = 0; L->emax = S->exps + N*i; L->emin = S->exps + N*(i + 1); L->upperclosed = 0; L->startidx = B->length; L->endidx = B->length; L->producer = 0; L->Cinited = 0; L->lock = -2; divides_heap_base_add_chunk(H, L); } H->head->upperclosed = 1; H->head->producer = 1; H->cur = H->head; /* generate at least the first quotient term */ texps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); qexps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_sub_mp(qexps + N*0, Aexp + N*0, Bexp + N*0, N); fmpz_divexact(qcoeff, A->coeffs + 0, B->coeffs + 0); /* already checked */ fmpz_mpoly_ts_init(H->polyQ, qcoeff, qexps, 1, H->bits, H->N); mpoly_monomial_add_mp(texps, qexps + N*0, Bexp + N*1, N); mask = 0; for (i = 0; i < FLINT_BITS/exp_bits; i++) mask = (mask << exp_bits) + (UWORD(1) << (exp_bits - 1)); k = 1; while (k < A->length && mpoly_monomial_gt(Aexp + N*k, texps, N, cmpmask)) { int lt_divides; if (exp_bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(qexps, Aexp + N*k, Bexp + N*0, N, mask); else lt_divides = mpoly_monomial_divides_mp(qexps, Aexp + N*k, Bexp + N*0, N, exp_bits); if (!lt_divides) { H->failed = 1; break; } fmpz_fdiv_qr(qcoeff, r, A->coeffs + k, B->coeffs + 0); if (!fmpz_is_zero(r)) { H->failed = 1; break; } fmpz_mpoly_ts_append(H->polyQ, qcoeff, qexps, 1, H->N); k++; } /* start the workers */ #if FLINT_USES_PTHREAD pthread_mutex_init(&H->mutex, NULL); #endif worker_args = (worker_arg_struct *) flint_malloc((num_handles + 1) *sizeof(worker_arg_t)); for (i = 0; i < num_handles; i++) { (worker_args + i)->H = H; thread_pool_wake(global_thread_pool, handles[i], 0, worker_loop, worker_args + i); } (worker_args + num_handles)->H = H; worker_loop(worker_args + num_handles); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } flint_free(worker_args); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&H->mutex); #endif divides = divides_heap_base_clear(Q, H); cleanup1: fmpz_mpoly_clear(S, zctx); fmpz_mpoly_ctx_clear(zctx); if (freeAexp) flint_free(Aexp); if (freeBexp) flint_free(Bexp); fmpz_clear(qcoeff); fmpz_clear(r); TMP_END; return divides; } int fmpz_mpoly_divides_heap_threaded( fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { thread_pool_handle * handles; slong num_handles; int divides; slong thread_limit = A->length/32; if (B->length < 2 || A->length < 2) { if (B->length == 0) { flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divides_heap_threaded"); } if (A->length == 0) { fmpz_mpoly_zero(Q, ctx); return 1; } return fmpz_mpoly_divides_monagan_pearce(Q, A, B, ctx); } num_handles = flint_request_threads(&handles, thread_limit); divides = _fmpz_mpoly_divides_heap_threaded_pool(Q, A, B, ctx, handles, num_handles); flint_give_back_threads(handles, num_handles); return divides; } #else typedef int this_file_is_empty; #endif flint-3.1.3/src/fmpz_mpoly/divides_monagan_pearce.c000066400000000000000000000623031461254215100224340ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* Set poly1 to poly2/poly3 if the division is exact, and return the length of the quotient. Otherwise return 0. This version of the function assumes the exponent vectors all fit in a single word. The exponent vectors are assumed to have fields with the given number of bits. Assumes input polys are nonzero. Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce [1], except that we divide from right to left and use a heap with smallest exponent at head. [1] http://www.cecm.sfu.ca/~rpearcea/sdmp/sdmp_paper.pdf */ slong _fmpz_mpoly_divides_monagan_pearce1(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, ulong maskhi) { slong i, j, k, s; slong next_loc, heap_len = 2; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * p1 = *poly1; ulong * e1 = *exp1; slong * hind; ulong mask, exp, maxexp = exp2[len2 - 1]; fmpz_t r, acc_lg; ulong acc_sm[3]; int lt_divides, small; slong bits2, bits3; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; TMP_INIT; TMP_START; fmpz_init(acc_lg); fmpz_init(r); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* output poly index starts at -1, will be immediately updated to 0 */ k = -WORD(1); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_exact_division; k++; _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, 1); lt_divides = mpoly_monomial_divides1(e1 + k, exp, exp3[0], mask); if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], p1[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else { fmpz_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, p1 + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + e1[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == k) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + e1[x->j], x, &next_loc, &heap_len, maskhi); } } } /* try to divide accumulated term by leading term */ if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) { k--; continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr != WORD(0)) goto not_exact_division; if ((qq & (WORD(3) << (SMALL_FMPZ_BITCOUNT_MAX))) == WORD(0)) { _fmpz_demote(p1 + k); p1[k] = (qq^ds^lc_sign) - (ds^lc_sign); } else { small = 0; fmpz_set_ui(p1 + k, qq); if (ds != lc_sign) fmpz_neg(p1 + k, p1 + k); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); fmpz_fdiv_qr(p1 + k, r, acc_lg, poly3 + 0); if (!fmpz_is_zero(r)) goto not_exact_division; } } else { if (fmpz_is_zero(acc_lg)) { k--; continue; } fmpz_fdiv_qr(p1 + k, r, acc_lg, poly3 + 0); if (!fmpz_is_zero(r)) goto not_exact_division; } if (!lt_divides || (exp^maskhi) < (maxexp^maskhi)) goto not_exact_division; /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = k; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + e1[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; } k++; cleanup: fmpz_clear(acc_lg); fmpz_clear(r); (*poly1) = p1; (*exp1) = e1; TMP_END; return k; not_exact_division: for (i = 0; i <= k; i++) _fmpz_demote(p1 + i); k = 0; goto cleanup; } slong _fmpz_mpoly_divides_monagan_pearce(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask) { slong i, j, k, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * p1 = *poly1; ulong * e1 = *exp1; ulong * exp, * exps; ulong ** exp_list; slong exp_next; fmpz_t r, acc_lg; ulong acc_sm[3]; ulong mask; slong * hind; int lt_divides, small; slong bits2, bits3; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; TMP_INIT; /* if exponent vectors are all one word, call specialised version */ if (N == 1) return _fmpz_mpoly_divides_monagan_pearce1(poly1, exp1, alloc, poly2, exp2, len2, poly3, exp3, len3, bits, cmpmask[0]); TMP_START; fmpz_init(acc_lg); fmpz_init(r); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; /* output poly index starts at -1, will be immediately updated to 0 */ k = -WORD(1); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto not_exact_division; } k++; _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, N); if (bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(e1 + k*N, exp, exp3, N, mask); else lt_divides = mpoly_monomial_divides_mp(e1 + k*N, exp, exp3, N, bits); if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], p1[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else { fmpz_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, p1 + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, e1 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, e1 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == k) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, e1 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, e1 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term */ if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) { k--; continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr != WORD(0)) goto not_exact_division; if ((qq & (WORD(3) << (SMALL_FMPZ_BITCOUNT_MAX))) == WORD(0)) { _fmpz_demote(p1 + k); p1[k] = (qq^(ds^lc_sign)) - (ds^lc_sign); } else { small = 0; fmpz_set_ui(p1 + k, qq); if (ds != lc_sign) fmpz_neg(p1 + k, p1 + k); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); fmpz_fdiv_qr(p1 + k, r, acc_lg, poly3 + 0); if (!fmpz_is_zero(r)) goto not_exact_division; } } else { if (fmpz_is_zero(acc_lg)) { k--; continue; } fmpz_fdiv_qr(p1 + k, r, acc_lg, poly3 + 0); if (!fmpz_is_zero(r)) goto not_exact_division; } if (!lt_divides || mpoly_monomial_gt(exp2 + (len2 - 1)*N, exp, N, cmpmask)) goto not_exact_division; if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = k; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, e1 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, e1 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; } k++; cleanup: fmpz_clear(acc_lg); fmpz_clear(r); (*poly1) = p1; (*exp1) = e1; TMP_END; return k; not_exact_division: for (i = 0; i <= k; i++) _fmpz_demote(p1 + i); k = 0; goto cleanup; } /* return 1 if quotient is exact */ int fmpz_mpoly_divides_monagan_pearce(fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) { slong i, N, len = 0; flint_bitcnt_t exp_bits; fmpz * max_fields2, * max_fields3; ulong * cmpmask; ulong * exp2 = poly2->exps, * exp3 = poly3->exps, * expq; int easy_exit, free2 = 0, free3 = 0; ulong mask = 0; TMP_INIT; /* check divisor is nonzero */ if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divides_monagan_pearce"); /* dividend zero, write out quotient */ if (poly2->length == 0) { fmpz_mpoly_zero(poly1, ctx); return 1; } TMP_START; max_fields2 = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields3 = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(max_fields2 + i); fmpz_init(max_fields3 + i); } mpoly_max_fields_fmpz(max_fields2, poly2->exps, poly2->length, poly2->bits, ctx->minfo); mpoly_max_fields_fmpz(max_fields3, poly3->exps, poly3->length, poly3->bits, ctx->minfo); easy_exit = 0; for (i = 0; i < ctx->minfo->nfields; i++) { /* cannot be exact division if any max field from poly2 is less than corresponding max field from poly3 */ if (fmpz_cmp(max_fields2 + i, max_fields3 + i) < 0) easy_exit = 1; } exp_bits = _fmpz_vec_max_bits(max_fields2, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = FLINT_MAX(exp_bits, poly2->bits); exp_bits = FLINT_MAX(exp_bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(max_fields2 + i); fmpz_clear(max_fields3 + i); } if (easy_exit) { len = 0; goto cleanup; } N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* temporary space to check leading monomials divide */ expq = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* quick check for easy case of inexact division of leading monomials */ if (poly2->bits == poly3->bits && N == 1 && poly2->exps[0] < poly3->exps[0]) { goto cleanup; } /* ensure input exponents packed to same size as output exponents */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* check leading monomial divides exactly */ if (exp_bits <= FLINT_BITS) { /* mask with high bit of each exponent vector field set */ for (i = 0; i < FLINT_BITS/exp_bits; i++) mask = (mask << exp_bits) + (UWORD(1) << (exp_bits - 1)); if (!mpoly_monomial_divides(expq, exp2, exp3, N, mask)) { len = 0; goto cleanup; } } else { if (!mpoly_monomial_divides_mp(expq, exp2, exp3, N, exp_bits)) { len = 0; goto cleanup; } } /* deal with aliasing and divide polynomials */ if (poly1 == poly2 || poly1 == poly3) { fmpz_mpoly_t temp; fmpz_mpoly_init2(temp, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(temp, exp_bits, ctx); temp->bits = exp_bits; len = _fmpz_mpoly_divides_monagan_pearce(&temp->coeffs, &temp->exps, &temp->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask); fmpz_mpoly_swap(temp, poly1, ctx); fmpz_mpoly_clear(temp, ctx); } else { fmpz_mpoly_fit_length(poly1, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(poly1, exp_bits, ctx); poly1->bits = exp_bits; len = _fmpz_mpoly_divides_monagan_pearce(&poly1->coeffs, &poly1->exps, &poly1->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask); } cleanup: _fmpz_mpoly_set_length(poly1, len, ctx); if (free2) flint_free(exp2); if (free3) flint_free(exp3); TMP_END; /* division is exact if len is nonzero */ return (len != 0); } flint-3.1.3/src/fmpz_mpoly/divrem.c000066400000000000000000000706231461254215100172600ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_divrem(fmpz_mpoly_t Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { /* TODO !!! */ fmpz_mpoly_divrem_monagan_pearce(Q, R, A, B, ctx); } /* Set polyq, polyr to the quotient and remainder of poly2 by poly3 (with remainder coeffs reduced modulo the leading coeff of poly3), and return the length of the quotient. This version of the function assumes the exponent vectors all fit in a single word. The exponent vectors are assumed to have fields with the given number of bits. Assumes input polys are nonzero. Implements "Polynomial division using dynamic arrays, heaps and packed exponents" by Michael Monagan and Roman Pearce [1], except that we use a heap with smallest exponent at head. Note that if a < b then (n - b) < (n - b) where n is the maximum value a and b can take. The word "maxn" is set to an exponent vector whose fields are all set to such a value n. This allows division from left to right with a heap with smallest exponent at the head. Quotient and remainder polys are written in reverse order. [1] http://www.cecm.sfu.ca/~rpearcea/sdmp/sdmp_paper.pdf */ slong _fmpz_mpoly_divrem_monagan_pearce1(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, ulong maskhi) { slong i, j, q_len, r_len, s; slong next_loc, heap_len = 2; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * q_coeff = *polyq; fmpz * r_coeff = *polyr; ulong * q_exp = *expq; ulong * r_exp = *expr; slong * hind; ulong mask, exp; fmpz_t r, acc_lg; ulong acc_sm[3]; int lt_divides, small; slong bits2, bits3; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; TMP_INIT; TMP_START; fmpz_init(acc_lg); fmpz_init(r); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* quotient and remainder poly indices start at -1 */ q_len = WORD(0); r_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); /* precompute leading coefficient info in "small" case */ if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, 1); lt_divides = mpoly_monomial_divides1(q_exp + q_len, exp, exp3[0], mask); /* take nodes from heap with exponent matching exp */ if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else { fmpz_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } } } /* try to divide accumulated term by leading term */ if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) { continue; } if (!lt_divides) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, 1); fmpz_set_signed_uiuiui(r_coeff + r_len, acc_sm[2], acc_sm[1], acc_sm[0]); r_exp[r_len] = exp; r_len++; continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); rr = rr >> lc_norm; if (rr != 0) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, 1); if (ds == 0) fmpz_set_si(r_coeff + r_len, rr); else fmpz_neg_ui(r_coeff + r_len, rr); r_exp[r_len] = exp; r_len++; } if (qq == 0) continue; if (qq <= COEFF_MAX) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = qq; if (ds != lc_sign) q_coeff[q_len] = -q_coeff[q_len]; } else { small = 0; fmpz_set_ui(q_coeff + q_len, qq); if (ds != lc_sign) fmpz_neg(q_coeff + q_len, q_coeff + q_len); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) { continue; } if (!lt_divides) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, 1); fmpz_set(r_coeff + r_len, acc_lg); r_exp[r_len] = exp; r_len++; continue; } large_lt_divides: fmpz_fdiv_qr(q_coeff + q_len, r, acc_lg, poly3 + 0); if (!fmpz_is_zero(r)) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, 1); fmpz_set(r_coeff + r_len, r); r_exp[r_len] = exp; r_len++; } if (fmpz_is_zero(q_coeff + q_len)) { continue; } } /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; q_len++; } cleanup: fmpz_clear(acc_lg); fmpz_clear(r); (*polyq) = q_coeff; (*expq) = q_exp; (*polyr) = r_coeff; (*expr) = r_exp; /* set remainder poly length */ (*lenr) = r_len; TMP_END; return q_len; exp_overflow: for (i = 0; i < q_len; i++) _fmpz_demote(q_coeff + i); for (i = 0; i < r_len; i++) _fmpz_demote(r_coeff + i); q_len = 0; r_len = 0; goto cleanup; } slong _fmpz_mpoly_divrem_monagan_pearce(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const ulong * cmpmask) { slong i, j, q_len, r_len, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * q_coeff = *polyq; fmpz * r_coeff = *polyr; ulong * q_exp = *expq; ulong * r_exp = *expr; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; fmpz_t r, acc_lg; ulong acc_sm[3]; slong * hind; int lt_divides, small; slong bits2, bits3; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; TMP_INIT; if (N == 1) return _fmpz_mpoly_divrem_monagan_pearce1(lenr, polyq, expq, allocq, polyr, expr, allocr, poly2, exp2, len2, poly3, exp3, len3, bits, cmpmask[0]); TMP_START; fmpz_init(acc_lg); fmpz_init(r); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; /* quotient and remainder poly indices start at -1 */ q_len = WORD(0); r_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coefficient info in "small" case */ if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow2; } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow2; } _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, N); if (bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(q_exp + q_len*N, exp, exp3, N, mask); else lt_divides = mpoly_monomial_divides_mp(q_exp + q_len*N, exp, exp3, N, bits); /* take nodes from heap with exponent matching exp */ if (small) { acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else { fmpz_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term */ if (small) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) { continue; } if (!lt_divides) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, N); fmpz_set_signed_uiuiui(r_coeff + r_len, acc_sm[2], acc_sm[1], acc_sm[0]); mpoly_monomial_set(r_exp + r_len*N, exp, N); r_len++; continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); rr = rr >> lc_norm; if (rr != 0) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, N); if (ds == 0) fmpz_set_ui(r_coeff + r_len, rr); else fmpz_neg_ui(r_coeff + r_len, rr); mpoly_monomial_set(r_exp + r_len*N, exp, N); r_len++; } if (qq == 0) continue; if (qq <= COEFF_MAX) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = qq; if (ds != lc_sign) q_coeff[q_len] = -q_coeff[q_len]; } else { small = 0; fmpz_set_ui(q_coeff + q_len, qq); if (ds != lc_sign) fmpz_neg(q_coeff + q_len, q_coeff + q_len); } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) { continue; } if (!lt_divides) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, N); fmpz_set(r_coeff + r_len, acc_lg); mpoly_monomial_set(r_exp + r_len*N, exp, N); r_len++; continue; } large_lt_divides: fmpz_fdiv_qr(q_coeff + q_len, r, acc_lg, poly3 + 0); if (!fmpz_is_zero(r)) { _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, N); fmpz_set(r_coeff + r_len, r); mpoly_monomial_set(r_exp + r_len*N, exp, N); r_len++; } if (fmpz_is_zero(q_coeff + q_len)) { continue; } } /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; q_len++; } cleanup2: fmpz_clear(acc_lg); fmpz_clear(r); (*polyq) = q_coeff; (*expq) = q_exp; (*polyr) = r_coeff; (*expr) = r_exp; (*lenr) = r_len; TMP_END; return q_len; exp_overflow2: for (i = 0; i < q_len; i++) _fmpz_demote(q_coeff + i); for (i = 0; i < r_len; i++) _fmpz_demote(r_coeff + i); q_len = 0; r_len = 0; goto cleanup2; } void fmpz_mpoly_divrem_monagan_pearce(fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) { slong exp_bits, N, lenq = 0, lenr = 0; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; ulong * cmpmask; int free2 = 0, free3 = 0; fmpz_mpoly_t temp1, temp2; fmpz_mpoly_struct * tq, * tr; /* check divisor is nonzero */ if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divrem_monagan_pearce"); /* dividend zero, write out quotient and remainder */ if (poly2->length == 0) { fmpz_mpoly_zero(q, ctx); fmpz_mpoly_zero(r, ctx); return; } exp_bits = FLINT_MAX(poly2->bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(exp2, exp3, N, cmpmask)) { fmpz_mpoly_set(r, poly2, ctx); fmpz_mpoly_zero(q, ctx); goto cleanup3; } /* take care of aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_init2(temp1, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(temp1, exp_bits, ctx); temp1->bits = exp_bits; tq = temp1; } else { fmpz_mpoly_fit_length(q, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(q, exp_bits, ctx); q->bits = exp_bits; tq = q; } if (r == poly2 || r == poly3) { fmpz_mpoly_init2(temp2, poly3->length, ctx); fmpz_mpoly_fit_bits(temp2, exp_bits, ctx); temp2->bits = exp_bits; tr = temp2; } else { fmpz_mpoly_fit_length(r, poly3->length, ctx); fmpz_mpoly_fit_bits(r, exp_bits, ctx); r->bits = exp_bits; tr = r; } /* do division with remainder */ while ((lenq = _fmpz_mpoly_divrem_monagan_pearce(&lenr, &tq->coeffs, &tq->exps, &tq->alloc, &tr->coeffs, &tr->exps, &tr->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask)) == 0 && lenr == 0) { ulong * old_exp2 = exp2, * old_exp3 = exp3; slong old_exp_bits = exp_bits; exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, old_exp2, old_exp_bits, poly2->length, ctx->minfo); exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, old_exp3, old_exp_bits, poly3->length, ctx->minfo); if (free2) flint_free(old_exp2); if (free3) flint_free(old_exp3); free2 = free3 = 1; fmpz_mpoly_fit_bits(tq, exp_bits, ctx); tq->bits = exp_bits; fmpz_mpoly_fit_bits(tr, exp_bits, ctx); tr->bits = exp_bits; } /* deal with aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_swap(temp1, q, ctx); fmpz_mpoly_clear(temp1, ctx); } if (r == poly2 || r == poly3) { fmpz_mpoly_swap(temp2, r, ctx); fmpz_mpoly_clear(temp2, ctx); } _fmpz_mpoly_set_length(q, lenq, ctx); _fmpz_mpoly_set_length(r, lenr, ctx); cleanup3: if (free2) flint_free(exp2); if (free3) flint_free(exp3); flint_free(cmpmask); } flint-3.1.3/src/fmpz_mpoly/divrem_array.c000066400000000000000000001124361461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* improve locality */ #define BLOCK 128 #define MAX_ARRAY_SIZE (WORD(300000)) /* Set polyq to the quotient and polyr to the remainder of poly2 divided by poly3, and return the length of the quotient. The polynomials have their exponents tightly packed, with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. The dividend poly3 is assumed to be nonzero. There are assumed to be "num" variables and the bases b_i are passed in the array "mults". The function reallocates its output. The quotient and remainder are written out in reverse order. The quotient and remainder poly are not assumed to be zero on input. The quotient and remainder terms are appended to the existing terms in those polys. */ slong _fmpz_mpoly_divrem_array_tight(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, slong len0, fmpz ** polyr, ulong ** expr, slong * allocr, slong len1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num) { slong i, j, q, r, prod, bits1, bits2, bits3, k = len0, l = len1; slong max3 = (slong) exp3[0]; /* largest exponent in poly3 */ slong * prods; fmpz c3 = poly3[0]; /* abs val of leading coeff of poly3 */ ulong u3 = ((ulong) FLINT_ABS(c3)) >> 1; fmpz * p1 = *polyq, * p2 = *polyr; ulong * e1 = *expq, * e2 = *expr; int small; TMP_INIT; TMP_START; prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods[0] = 1; for (i = 1; i <= num; i++) prods[i] = mults[i - 1]*prods[i - 1]; prod = prods[num]; /* compute bound on poly2 - q*poly3 assuming quotient remains small */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* we assume a bound of SMALL_FMPZ_BITCOUNT_MAX for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; bits1 += 2; /* incr. so poly2 - q*poly3 doesn't overflow and for sign */ /* input coeffs small and intermediate computations fit two words */ if (small && bits1 <= 2*FLINT_BITS) { ulong * t2 = (ulong *) TMP_ALLOC(2*prod*sizeof(ulong)); for (i = 0; i < 2*prod; i++) t2[i] = 0; /* poly2 to array format */ _fmpz_mpoly_to_ulong_array2(t2, poly2, exp2, len2); /* for each term of poly2 array relevant to quotient */ for (i = prod - 1; i >= max3; i--) { ulong * ptr = t2 + 2*i; ulong p[2]; /* if coeff is nonzero */ if (ptr[0] != 0 || ptr[1] != 0) { if (0 > (slong) ptr[1]) mpn_neg(p, ptr, 2); else flint_mpn_copyi(p, ptr, 2); /* not exact quotient monomial, thus remainder monomial */ if (!mpoly_monomial_divides_tight(i, max3, prods, num)) { /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set_signed_uiui(p2 + l, ptr[1], ptr[0]); /* ...and exponent */ e2[l++] = i; } else /* monomials can be divided exactly */ { /* check quotient won't overflow a word */ if (u3 <= p[1] || (u3 == 0 && 0 > (slong) p[0])) /* quotient too large */ { for (j = len0; j < k; j++) _fmpz_demote(p1 + j); for (j = len1; j < l; j++) _fmpz_demote(p2 + j); k = len0; l = len1; goto big; } /* quotient and remainder of coeffs */ sdiv_qrnnd(q, r, ptr[1], ptr[0], c3); /* check coefficient is small, else restart with multiprec code */ if (COEFF_IS_MPZ(FLINT_ABS(q))) /* quotient too large */ { for (j = len0; j < k; j++) _fmpz_demote(p1 + j); for (j = len1; j < l; j++) _fmpz_demote(p2 + j); k = len0; l = len1; goto big; } /* check coeff quotient was exact */ if (r != 0) /* not an exact division */ { /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set_si(p2 + l, (slong) r); /* ... and exponent */ e2[l++] = i; } if (q != 0) { /* submul a - q*b */ _fmpz_mpoly_submul_array1_slong2_1(t2, q, i - max3, poly3, exp3, len3); /* realloc quotient poly */ _fmpz_mpoly_fit_length(&p1, &e1, allocq, k + 1, 1); /* set quotient coeff and exponent */ fmpz_set_si(p1 + k, q); e1[k++] = i - max3; } } } } /* all remaining terms are remainder terms */ for ( ; i >= 0; i--) { ulong * ptr = t2 + 2*i; /* if coeff nonzero */ if (ptr[0] != 0 || ptr[1] != 0) /* not an exact division */ { /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set_signed_uiui(p2 + l, ptr[1], ptr[0]); /* and exponent */ e2[l++] = i; } } } /* not done, coeffs small and intermediate computations fit three words */ if (k == len0 && l == len1 && small) { ulong * t2 = (ulong *) TMP_ALLOC(3*prod*sizeof(ulong)); for (i = 0; i < 3*prod; i++) t2[i] = 0; /* poly2 to array format */ _fmpz_mpoly_to_ulong_array(t2, poly2, exp2, len2); /* for each term of poly2 array relevant to exact quotient */ for (i = prod - 1; i >= max3; i--) { ulong * ptr = t2 + 3*i; ulong p[3]; /* if coeff is nonzero */ if (ptr[0] != 0 || ptr[1] != 0 || ptr[2] != 0) { if (0 > (slong) ptr[2]) mpn_neg(p, ptr, 3); else flint_mpn_copyi(p, ptr, 3); /* not exact quotient monomial, thus remainder monomial */ if (!mpoly_monomial_divides_tight(i, max3, prods, num)) { /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set_signed_uiuiui(p2 + l, ptr[2], ptr[1], ptr[0]); /* ... and exponent */ e2[l++] = i; } else /* monomials can be divided exact */ { /* check quotient won't overflow a word */ if (p[2] > 0 || u3 <= p[1] || (u3 == 0 && 0 > (slong) p[0])) /* quotient too large */ { for (j = len0; j < k; j++) _fmpz_demote(p1 + j); for (j = len1; j < l; j++) _fmpz_demote(p2 + j); k = len0; l = len1; goto big; } /* quotient and remainder of coeffs */ sdiv_qrnnd(q, r, ptr[1], ptr[0], c3); /* check coefficient is small, else restart with multiprec code */ if (COEFF_IS_MPZ(FLINT_ABS(q))) /* quotient too large */ { for (j = len0; j < k; j++) _fmpz_demote(p1 + j); for (j = len1; j < l; j++) _fmpz_demote(p2 + j); k = len0; l = len1; goto big; } /* check if coeff quotient was exact */ if (r != 0) /* else remainder term */ { /* reallocate remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set_si(p2 + l, (slong) r); /* and exponent */ e2[l++] = i; } /* if nonzero quotient */ if (q != 0) { /* submul a - q*b */ _fmpz_mpoly_submul_array1_slong_1(t2, q, i - max3, poly3, exp3, len3); /* realloc quotient poly */ _fmpz_mpoly_fit_length(&p1, &e1, allocq, k + 1, 1); /* set quotient coeff and exponent */ fmpz_set_si(p1 + k, q); e1[k++] = i - max3; } } } } /* all remaining terms are remainder terms */ for ( ; i >= 0; i--) { ulong * ptr = t2 + 3*i; /* if coeff nonzero */ if (ptr[0] != 0 || ptr[1] != 0 || ptr[2] != 0) { /* not an exact division */ /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set_signed_uiuiui(p2 + l, ptr[2], ptr[1], ptr[0]); /* ...and exponent */ e2[l++] = i; } } } big: /* if still not done, use multiprecision coeffs instead */ if (k == len0 && l == len1) { fmpz * t2 = (fmpz *) TMP_ALLOC(prod*sizeof(fmpz)); fmpz_t fq, fr; fmpz_init(fq); fmpz_init(fr); for (i = 0; i < prod; i++) fmpz_init(t2 + i); /* poly2 to array format */ _fmpz_mpoly_to_fmpz_array(t2, poly2, exp2, len2); /* for each term of poly2 array relevant to exact quotient */ for (i = prod - 1; i >= max3; i--) { /* if coeff is nonzero */ if (!fmpz_is_zero(t2 + i)) { /* not exact quotient monomial, thus remainder monomial */ if (!mpoly_monomial_divides_tight(i, max3, prods, num)) { /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set(p2 + l, t2 + i); /* ... and exponent */ e2[l++] = i; } else /* monomials can be divided exactly */ { /* quotient and remainder of coeffs */ fmpz_fdiv_qr(fq, fr, t2 + i, poly3); /* check if coeff quotient was exact */ if (!fmpz_is_zero(fr)) /* else remainder term */ { /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set(p2 + l, fr); /* and exponent */ e2[l++] = i; } /* if nonzero quotient */ if (!fmpz_is_zero(fq)) { /* submul a - q*b */ _fmpz_mpoly_submul_array1_fmpz_1(t2, fq, i - max3, poly3, exp3, len3); /* realloc quotient poly */ _fmpz_mpoly_fit_length(&p1, &e1, allocq, k + 1, 1); /* set quotient coeff and exponent */ fmpz_set(p1 + k, fq); e1[k++] = i - max3; } } } } /* all remaining terms are remainder terms */ for ( ; i >= 0; i--) { /* if coeff nonzero */ if (!fmpz_is_zero(t2 + i)) { /* remainder */ /* realloc remainder poly */ _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); /* set remainder coeff... */ fmpz_set(p2 + l, t2 + i); /* ... and exponent */ e2[l++] = i; } } fmpz_clear(fq); fmpz_clear(fr); for (i = 0; i < prod; i++) fmpz_clear(t2 + i); } (*polyq) = p1; (*expq) = e1; (*polyr) = p2; (*expr) = e2; /* set remainder poly length */ (*lenr) = l - len1; TMP_END; /* return quotient poly length */ return k - len0; } /* Use dense array division to set polyq, polyr to poly2/poly3 in num + 1 variables, given a list of multipliers to tightly pack exponents and a number of bits for the fields of the exponents of the result, assuming no aliasing. classical exact division in main variable, array multiplication (submul) for multivariate coefficients in remaining num variables. The function reallocates its output and returns the length of the quotient poly. It is assumed that poly2 is not zero. The quotient and remainder are written in reverse order. */ slong _fmpz_mpoly_divrem_array_chunked(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits) { slong i, j, k, l = 0, m, prod, len = 0, l1, l2, l3; slong bits1, bits2, bits3 = 0, tlen, talloc; slong shift = bits*(num); slong * i1, * i2, * i3, * n1, * n2, * n3, * prods; slong * b1, * b3, * maxb1, * maxb3, * max_exp1, * max_exp3; ulong * e2, * e3, * texp, * p2; fmpz * temp; int small; TMP_INIT; TMP_START; /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); prods[0] = 1; for (i = 0; i < num; i++) prods[i + 1] = prods[i]*mults[i]; prod = prods[num]; /* lengths of poly2, poly3 and polyq in chunks */ l2 = 1 + (slong) (exp2[0] >> shift); l3 = 1 + (slong) (exp3[0] >> shift); l1 = FLINT_MAX(l2 - l3 + 1, 0); /* compute indices and lengths of coefficients of polys in main variable */ i1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); n1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); i2 = (slong *) TMP_ALLOC(l2*sizeof(slong)); n2 = (slong *) TMP_ALLOC(l2*sizeof(slong)); i3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); n3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); b1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); maxb1 = (slong *) TMP_ALLOC(l1*sizeof(slong)); b3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); maxb3 = (slong *) TMP_ALLOC(l3*sizeof(slong)); max_exp1 = (slong *) TMP_ALLOC(l1*num*sizeof(slong)); max_exp3 = (slong *) TMP_ALLOC(l3*num*sizeof(slong)); mpoly_main_variable_terms1(i2, n2, exp2, l2, len2, num + 1, num + 1, bits); mpoly_main_variable_terms1(i3, n3, exp3, l3, len3, num + 1, num + 1, bits); /* work out max bits for each coeff and optimal bits */ for (i = 0; i < l3; i++) { _fmpz_vec_sum_max_bits(&b3[i], &maxb3[i], poly3+i3[i], n3[i]); if (bits3 < maxb3[i]) bits3 = maxb3[i]; } /* pack input coefficients tightly */ e2 = (ulong *) TMP_ALLOC(len2*sizeof(ulong)); e3 = (ulong *) TMP_ALLOC(len3*sizeof(ulong)); mpoly_pack_monomials_tight(e2, exp2, len2, mults, num, bits); mpoly_pack_monomials_tight(e3, exp3, len3, mults, num, bits); /* work out maximum exponents for each chunk */ for (i = 0; i < l3; i++) mpoly_max_degrees_tight(max_exp3 + i*num, e3 + i3[i], n3[i], prods, num); /* bound poly2 coeffs and check input/output coeffs likely small */ bits2 = _fmpz_vec_max_bits(poly2, len2); /* we assume a bound of SMALL_FMPZ_BITCOUNT_MAX for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; /* alloc space for copy of coeff/chunk of poly2 */ temp = (fmpz *) flint_calloc(n2[0] + 1, sizeof(fmpz)); texp = (ulong *) flint_malloc((n2[0] + 1)*sizeof(ulong)); talloc = n2[0] + 1; /* plus one so doubling always increases size */ /* enough space for three words per coeff, even if only one or two needed */ p2 = (ulong *) TMP_ALLOC(3*prod*sizeof(ulong)); /* coefficients likely to be small */ if (small) { /* for each chunk of poly2 */ for (i = 0; i < l2; i++) { slong num1 = 0; bits1 = 0; /* if there are already quotient terms */ if (i != 0) { /* compute bound on intermediate computations a - q*b */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3 && k >= 0) { for (m = 0; m < num; m++) { if (max_exp1[j*num + m] + max_exp3[k*num + m] >= mults[m]) { for (j = 0; j < len; j++) _fmpz_demote((*polyq) + j); for (j = 0; j < l; j++) _fmpz_demote((*polyr) + j); len = 0; l = 0; goto cleanup3; } } bits1 = FLINT_MAX(bits1, FLINT_MIN(b1[j] + maxb3[k], maxb1[j] + b3[k])); num1++; } } bits1 += FLINT_BIT_COUNT(num1); bits1 = FLINT_MAX(FLINT_ABS(bits2), bits1); bits1 += 2; /* bit for sign and so a - q*b doesn't overflow */ } else bits1 = FLINT_ABS(bits2) + 1; /* extra bit for sign */ /* intermediate computations fit in one word */ if (bits1 <= FLINT_BITS) { for (j = 0; j < prod; j++) p2[j] = 0; /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_ulong_array1(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3 && k >= 0) { _fmpz_mpoly_submul_array1_slong1(p2, (*polyq) + i1[j], (*expq) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_ulong_array1(&temp, &texp, &talloc, p2, mults, num, bits, 0); } else if (bits1 <= 2*FLINT_BITS) /* intermed comps fit two words */ { for (j = 0; j < 2*prod; j++) p2[j] = 0; /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_ulong_array2(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3 && k >= 0) { _fmpz_mpoly_submul_array1_slong2(p2, (*polyq) + i1[j], (*expq) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_ulong_array2(&temp, &texp, &talloc, p2, mults, num, bits, 0); } else /* intermed comps fit three words */ { for (j = 0; j < 3*prod; j++) p2[j] = 0; /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_ulong_array(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3 && k >= 0) _fmpz_mpoly_submul_array1_slong(p2, (*polyq) + i1[j], (*expq) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_ulong_array(&temp, &texp, &talloc, p2, mults, num, bits, 0); } if (tlen != 0) /* nonzero coeff/chunk */ { if (i < l1) /* potentially a quotient with remainder */ { /* tightly pack chunk exponents */ mpoly_pack_monomials_tight(texp, texp, tlen, mults, num, bits); /* set starting index for quotient chunk we are about to compute */ i1[i] = len; /* compute quotient chunk and set length of quotient chunk */ n1[i] = _fmpz_mpoly_divrem_array_tight(lenr, polyq, expq, allocq, len, polyr, expr, allocr, l, temp, texp, tlen, poly3 + i3[0], e3 + i3[0], n3[0], mults, num); /* unpack remainder exponents */ mpoly_unpack_monomials_tight(*expr + l, *expr + l, *lenr, mults, num, bits); /* insert main variable */ for (j = 0; j < *lenr; j++) (*expr)[l + j] += ((l2 - i - 1) << shift); /* work out maximum exponents for chunk */ mpoly_max_degrees_tight(max_exp1 + i*num, (*expq) + i1[i], n1[i], prods, num); /* check there were no exponent overflows */ for (m = 0; m < num; m++) { if (max_exp3[m] + max_exp1[i*num + m] >= mults[m]) { for (j = 0; j < len; j++) _fmpz_demote((*polyq) + j); for (j = 0; j < l; j++) _fmpz_demote((*polyr) + j); len = 0; l = 0; goto cleanup3; } } /* check the quotient didn't have large coefficients */ if (FLINT_ABS(_fmpz_vec_max_bits((*polyq) + len, n1[i])) > SMALL_FMPZ_BITCOUNT_MAX) { for (j = 0; j < len; j++) _fmpz_demote((*polyq) + j); for (j = 0; j < l; j++) _fmpz_demote((*polyr) + j); len = 0; l = 0; goto big; } /* abs bound and sum of abs vals of coeffs of quotient chunk */ _fmpz_vec_sum_max_bits(&b1[i], &maxb1[i], (*polyq)+i1[i], n1[i]); /* update length of output quotient and remainder polys */ len += n1[i]; l += *lenr; } else /* remainder terms only */ { /* realloc remainder poly */ _fmpz_mpoly_fit_length(polyr, expr, allocr, l + tlen, 1); /* for each term in remainder chunk */ for (j = 0; j < tlen; j++) { /* set remainder coeff and exponent */ fmpz_set(*polyr + l + j, temp + j); (*expr)[l + j] = (texp[j]) + ((l2 - i - 1) << shift); } l += tlen; } } else if (i < l1) /* zero chunk, no quotient or remainder */ { /* set index and length of quotient chunk */ i1[i] = len; n1[i] = 0; b1[i] = 0; maxb1[i] = 0; /* write out maximum exponents in chunk */ mpoly_max_degrees_tight(max_exp1 + i*num, (*expq) + i1[i], n1[i], prods, num); } } } big: /* if not done, use multiprecision coeffs instead */ if (len == 0 && l == 0) { fmpz * p2 = (fmpz *) TMP_ALLOC(prod*sizeof(fmpz)); for (j = 0; j < prod; j++) fmpz_init(p2 + j); /* for each chunk of poly2 */ for (i = 0; i < l2; i++) { for (j = 0; j < prod; j++) fmpz_zero(p2 + j); /* convert relevant coeff/chunk of poly2 to array format */ _fmpz_mpoly_to_fmpz_array(p2, poly2 + i2[i], e2 + i2[i], n2[i]); /* submuls */ for (j = 0; j < i && j < l1; j++) { k = i - j; if (k < l3 && k >= 0) { for (m = 0; m < num; m++) { if (max_exp1[j*num + m] + max_exp3[k*num + m] >= mults[m]) { for (j = 0; j < len; j++) _fmpz_demote((*polyq) + j); for (j = 0; j < l; j++) _fmpz_demote((*polyr) + j); len = 0; l = 0; for (j = 0; j < prod; j++) fmpz_clear(p2 + j); goto cleanup3; } } _fmpz_mpoly_submul_array1_fmpz(p2, (*polyq) + i1[j], (*expq) + i1[j], n1[j], poly3 + i3[k], e3 + i3[k], n3[k]); } } /* convert chunk from array format */ tlen = _fmpz_mpoly_from_fmpz_array(&temp, &texp, &talloc, p2, mults, num, bits, 0); if (tlen != 0) /* nonzero coeff/chunk */ { if (i < l1) /* potentially a quotient with remainder */ { /* tightly pack chunk exponents */ mpoly_pack_monomials_tight(texp, texp, tlen, mults, num, bits); /* set start index of quotient chunk we are about to compute */ i1[i] = len; /* compute quotient chunk and set length of quotient chunk */ n1[i] = _fmpz_mpoly_divrem_array_tight(lenr, polyq, expq, allocq, len, polyr, expr, allocr, l, temp, texp, tlen, poly3 + i3[0], e3 + i3[0], n3[0], mults, num); /* unpack remainder exponents */ mpoly_unpack_monomials_tight(*expr + l, *expr + l, *lenr, mults, num, bits); /* insert main variable */ for (j = 0; j < *lenr; j++) (*expr)[l + j] += ((l2 - i - 1) << shift); /* work out maximum exponents for chunk */ mpoly_max_degrees_tight(max_exp1 + i*num, (*expq) + i1[i], n1[i], prods, num); /* check there were no exponent overflows */ for (m = 0; m < num; m++) { if (max_exp3[m] + max_exp1[i*num + m] >= mults[m]) { for (j = 0; j < len; j++) _fmpz_demote((*polyq) + j); for (j = 0; j < l; j++) _fmpz_demote((*polyr) + j); len = 0; l = 0; for (j = 0; j < prod; j++) fmpz_clear(p2 + j); goto cleanup3; } } /* abs bound and sum of abs vals of coeffs of quotient chunk */ _fmpz_vec_sum_max_bits(&b1[i], &maxb1[i], (*polyq)+i1[i], n1[i]); /* update length of output quotient and remainder polys */ len += n1[i]; l += *lenr; } else /* remainder terms only */ { /* realloc remainder poly */ _fmpz_mpoly_fit_length(polyr, expr, allocr, l + tlen, 1); /* for each term in chunk */ for (j = 0; j < tlen; j++) { /* set remainder coeff and exponent */ fmpz_set(*polyr + l + j, temp + j); (*expr)[l + j] = (texp[j]) + ((l2 - i - 1) << shift); } /* update length of output remainder poly */ l += tlen; } } else if (i < l1) /* zero chunk, no quotient or remainder */ { /* set index and length of quotient chunk */ i1[i] = len; n1[i] = 0; b1[i] = 0; maxb1[i] = 0; /* write out maximum exponents in chunk */ mpoly_max_degrees_tight(max_exp1 + i*num, (*expq) + i1[i], n1[i], prods, num); } } for (j = 0; j < prod; j++) fmpz_clear(p2 + j); } /* if there were quotient terms */ if (len != 0) { /* unpack monomials of quotient */ mpoly_unpack_monomials_tight((*expq), (*expq), len, mults, num, bits); /* put main variable back in quotient */ for (i = 0; i < l1; i++) { for (j = 0; j < n1[i]; j++) { (*expq)[i1[i] + j] += ((l1 - i - 1) << shift); } } } cleanup3: for (j = 0; j < talloc; j++) fmpz_clear(temp + j); flint_free(temp); flint_free(texp); TMP_END; /* set remainder length */ *lenr = l; /* return quotient length */ return len; } /* Use dense array division to set polyq, polyr to poly2/poly3 in num variables, given a list of multipliers to tightly pack exponents and a number of bits for the fields of the exponents of the result, assuming no aliasing. The array "mults" is a list of bases to be used in encoding the array indices from the exponents. The function reallocates its output and returns the length of the quotient. It is assumed that poly2 is not zero. The quotient and remainder are written in reverse order. */ slong _fmpz_mpoly_divrem_array(slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong * mults, slong num, slong bits) { slong i; ulong * e2, * e3; slong len, prod; slong * prods, * max_exp1, * max_exp3; TMP_INIT; TMP_START; /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); prods[0] = 1; for (i = 0; i < num; i++) prods[i + 1] = prods[i]*mults[i]; prod = prods[num]; /* if array size will be too large, chunk the polynomials */ if (prod > MAX_ARRAY_SIZE) { TMP_END; return _fmpz_mpoly_divrem_array_chunked(lenr, polyq, expq, allocq, polyr, expr, allocr, poly2, exp2, len2, poly3, exp3, len3, mults, num - 1, bits); } e2 = (ulong *) TMP_ALLOC(len2*sizeof(ulong)); e3 = (ulong *) TMP_ALLOC(len3*sizeof(ulong)); max_exp1 = (slong *) TMP_ALLOC(num*sizeof(slong)); max_exp3 = (slong *) TMP_ALLOC(num*sizeof(slong)); /* pack input exponents tightly with mixed bases specified by "mults" */ mpoly_pack_monomials_tight(e2, exp2, len2, mults, num, bits); mpoly_pack_monomials_tight(e3, exp3, len3, mults, num, bits); /* do divrem on tightly packed polys */ len = _fmpz_mpoly_divrem_array_tight(lenr, polyq, expq, allocq, 0, polyr, expr, allocr, 0, poly2, e2, len2, poly3, e3, len3, mults, num); /* check for overflows */ mpoly_max_degrees_tight(max_exp3, e3, len3, prods, num); mpoly_max_degrees_tight(max_exp1, *expq, len, prods, num); for (i = 0; i < num; i++) { if (max_exp3[i] + max_exp1[i] >= mults[i]) { len = 0; *lenr = 0; break; } } /* unpack output quotient and remainder exponents */ mpoly_unpack_monomials_tight((*expq), (*expq), len, mults, num, bits); mpoly_unpack_monomials_tight((*expr), (*expr), *lenr, mults, num, bits); TMP_END; return len; } /* Return 1 if q, r can be set to quotient and remainder of poly2 by poly3, else return 0 if array division not able to be performed. */ int fmpz_mpoly_divrem_array(fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) { slong i, exp_bits, N, lenq = 0, lenr = 0, array_size; ulong * max_fields, * max_fields2, * max_fields3; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; int free2 = 0, free3 = 0; fmpz_mpoly_t temp1, temp2; fmpz_mpoly_struct * tq, * tr; int res = 0; TMP_INIT; /* check divisor is not zero */ if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divrem_array"); /* dividend is zero */ if (poly2->length == 0) { fmpz_mpoly_zero(q, ctx); fmpz_mpoly_zero(r, ctx); return 1; } TMP_START; /* compute maximum exponents for each variable */ max_fields = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); max_fields2 = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); max_fields3 = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); mpoly_max_fields_ui_sp(max_fields2, poly2->exps, poly2->length, poly2->bits, ctx->minfo); mpoly_max_fields_ui_sp(max_fields3, poly3->exps, poly3->length, poly3->bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) max_fields[i] = FLINT_MAX(max_fields2[i], max_fields3[i]); /* compute number of bits required for output exponents */ exp_bits = FLINT_MAX(poly2->bits, poly3->bits); N = mpoly_words_per_exp(exp_bits, ctx->minfo); /* array division expects each exponent vector in one word */ /* current code is wrong for reversed orderings */ if (N != 1 || mpoly_ordering_isrev(ctx->minfo)) goto cleanup; /* compute bounds on output exps, used as mixed bases for packing exps */ array_size = 1; for (i = 0; i < ctx->minfo->nfields - 1; i++) { max_fields2[i] = max_fields[i] + 1; array_size *= max_fields2[i]; } max_fields2[ctx->minfo->nfields - 1] = max_fields[ctx->minfo->nfields - 1] + 1; /* if exponents too large for array multiplication, exit silently */ if (array_size > MAX_ARRAY_SIZE) goto cleanup; /* expand input exponents to same number of bits as output */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } if (exp2[0] < exp3[0]) { fmpz_mpoly_set(r, poly2, ctx); fmpz_mpoly_zero(q, ctx); res = 1; goto cleanup2; } /* handle aliasing and do array division */ if (q == poly2 || q == poly3) { fmpz_mpoly_init2(temp1, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(temp1, exp_bits, ctx); temp1->bits = exp_bits; tq = temp1; } else { fmpz_mpoly_fit_length(q, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(q, exp_bits, ctx); q->bits = exp_bits; tq = q; } if (r == poly2 || r == poly3) { fmpz_mpoly_init2(temp2, poly3->length, ctx); fmpz_mpoly_fit_bits(temp2, exp_bits, ctx); temp2->bits = exp_bits; tr = temp2; } else { fmpz_mpoly_fit_length(r, poly3->length, ctx); fmpz_mpoly_fit_bits(r, exp_bits, ctx); r->bits = exp_bits; tr = r; } lenq = _fmpz_mpoly_divrem_array(&lenr, &tq->coeffs, &tq->exps, &tq->alloc, &tr->coeffs, &tr->exps, &tr->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, (slong *) max_fields2, ctx->minfo->nfields, exp_bits); res = (lenq != 0 || lenr != 0); if (res) { if (q == poly2 || q == poly3) { fmpz_mpoly_swap(temp1, q, ctx); fmpz_mpoly_clear(temp1, ctx); } if (r == poly2 || r == poly3) { fmpz_mpoly_swap(temp2, r, ctx); fmpz_mpoly_clear(temp2, ctx); } } else { if (q == poly2 || q == poly3) { fmpz_mpoly_clear(temp1, ctx); } if (r == poly2 || r == poly3) { fmpz_mpoly_clear(temp2, ctx); } for (i = q->length; i < q->alloc; i++) { _fmpz_demote(q->coeffs + i); } for (i = r->length; i < r->alloc; i++) { _fmpz_demote(r->coeffs + i); } } _fmpz_mpoly_set_length(q, lenq, ctx); _fmpz_mpoly_set_length(r, lenr, ctx); cleanup2: if (free2) flint_free(exp2); if (free3) flint_free(exp3); cleanup: TMP_END; return res; } flint-3.1.3/src/fmpz_mpoly/divrem_ideal.c000066400000000000000000000706241461254215100204170ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_divrem_ideal(fmpz_mpoly_struct ** Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, fmpz_mpoly_struct * const * B, slong len, const fmpz_mpoly_ctx_t ctx) { /* TODO !!! */ fmpz_mpoly_divrem_ideal_monagan_pearce(Q, R, A, B, len, ctx); } /* ensure rounding is towards -\infty like fmpz_fdiv_qr */ #define fdiv_qrnnd(qxx, rxx, nhixx, nloxx, dxx) \ do { \ slong __dxx = (dxx); \ sdiv_qrnnd(qxx, rxx, nhixx, nloxx, dxx); \ if (((slong) (rxx) < 0 && (slong) (dxx) > 0) || \ ((slong) (rxx) > 0 && (slong) (dxx) < 0)) \ { \ (rxx) += __dxx; \ (qxx)--; \ } \ } while (0) /* As for divrem_monagan_pearce1 except that an array of divisor polynomials is passed and an array of quotient polynomials is returned. These are not in low level format. */ slong _fmpz_mpoly_divrem_ideal_monagan_pearce1(fmpz_mpoly_struct ** polyq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, fmpz_mpoly_struct * const * poly3, ulong * const * exp3, slong len, slong bits, const fmpz_mpoly_ctx_t ctx, ulong maskhi) { slong i, j, p, l, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_nheap_t ** chains, * chains_ptr; slong ** hinds, * hinds_ptr; mpoly_nheap_t * x; fmpz * p2 = *polyr; ulong * e2 = *expr; ulong exp, texp; ulong c[3]; /* for accumulating coefficients */ ulong mask; ulong * ub; slong * k, * s; fmpz_t qc, q; fmpz * mb; int small; slong bits2, bits3; int d1, d2, div_flag; TMP_INIT; TMP_START; fmpz_init(q); fmpz_init(qc); bits2 = _fmpz_vec_max_bits(poly2, len2); chains = TMP_ARRAY_ALLOC(len, mpoly_nheap_t *); hinds = TMP_ARRAY_ALLOC(len, slong *); /* chains[w], hinds[w] will be arrays of length poly3[w]->length; combine the allocations*/ len3 = 0; for (w = 0; w < len; w++) len3 += poly3[w]->length; chains_ptr = TMP_ARRAY_ALLOC(len3, mpoly_nheap_t); hinds_ptr = TMP_ARRAY_ALLOC(len3, slong); bits3 = 0; len3 = 0; for (w = 0; w < len; w++) { chains[w] = chains_ptr + len3; hinds[w] = hinds_ptr + len3; bits3 = FLINT_MAX(bits3, FLINT_ABS(fmpz_mpoly_max_bits(poly3[w]))); len3 += poly3[w]->length; for (i = 0; i < poly3[w]->length; i++) hinds[w][i] = 1; } /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong)); k = (slong *) TMP_ALLOC(len*sizeof(slong)); s = (slong *) TMP_ALLOC(len*sizeof(slong)); ub = (ulong *) TMP_ALLOC(len*sizeof(ulong)); mb = (fmpz * ) TMP_ALLOC(len*sizeof(fmpz)); mask = mpoly_overflow_mask_sp(bits); for (w = 0; w < len; w++) { k[w] = -WORD(1); s[w] = poly3[w]->length; } l = -WORD(1); x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); for (i = 0; i < len; i++) { fmpz_init(mb + i); fmpz_neg(mb + i, poly3[i]->coeffs); ub[i] = ((ulong) FLINT_ABS(mb[i])) >> 1; /* abs(poly3[0])/2 */ } while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; c[0] = c[1] = c[2] = 0; fmpz_zero(qc); while (heap_len > 1 && heap[1].exp == exp) { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i != -WORD(1)) hinds[x->p][x->i] |= WORD(1); if (small) { if (x->i == -WORD(1)) _fmpz_mpoly_sub_uiuiui_fmpz(c, poly2 + x->j); else _fmpz_mpoly_addmul_uiuiui_fmpz(c, poly3[x->p]->coeffs[x->i], polyq[x->p]->coeffs[x->j]); } else { if (x->i == -WORD(1)) fmpz_sub(qc, qc, poly2 + x->j); else fmpz_addmul(qc, poly3[x->p]->coeffs + x->i, polyq[x->p]->coeffs + x->j); } } while ((x = x->next) != NULL); } while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { if ( (i + 1 < poly3[p]->length) && (hinds[p][i + 1] == 2*j + 1) ) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->p][x->i] + polyq[x->p]->exps[x->j], x, &next_loc, &heap_len, maskhi); } if (j == k[p]) { s[p]++; } else if ( ((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1)) ) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->p][x->i] + polyq[x->p]->exps[x->j], x, &next_loc, &heap_len, maskhi); } } } if ((small && (c[2] != 0 || c[1] != 0 || c[0] != 0)) || (!small && !fmpz_is_zero(qc))) { div_flag = 0; for (w = 0; w < len; w++) { d1 = mpoly_monomial_divides1(&texp, exp, exp3[w][0], mask); if (d1) { d2 = 0; if (small) { ulong d[3]; if (0 > (slong) c[2]) mpn_neg(d, c, 3); else flint_mpn_copyi(d, c, 3); if (d[2] != 0 || ub[w] <= d[1] || (ub[w] == 0 && 0 > (slong) d[0])) /* quotient not a small */ { fmpz_set_signed_uiuiui(qc, c[2], c[1], c[0]); small = 0; } else /* quotient fits a small */ { slong r1; slong tq; fdiv_qrnnd(tq, r1, c[1], c[0], mb[w]); if (tq > COEFF_MAX || tq < COEFF_MIN) { small = 0; fmpz_set_signed_uiuiui(qc, c[2], c[1], c[0]); } else { div_flag = (r1 == 0); d2 = tq != 0; if (d2) { k[w]++; fmpz_mpoly_fit_length(polyq[w], k[w] + 1, ctx); fmpz_set_si(polyq[w]->coeffs + k[w], tq); polyq[w]->exps[k[w]] = texp; } c[0] = r1; c[2] = c[1] = -(slong)(r1 < 0); } } } /* quotient non-small case */ if (!small) { fmpz_fdiv_qr(q, qc, qc, mb + w); div_flag = fmpz_is_zero(qc); d2 = !fmpz_is_zero(q); if (d2) { k[w]++; fmpz_mpoly_fit_length(polyq[w], k[w] + 1, ctx); fmpz_set(polyq[w]->coeffs + k[w], q); polyq[w]->exps[k[w]] = texp; } } if (d2) { if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = k[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[w][i] + polyq[w]->exps[k[w]], x, &next_loc, &heap_len, maskhi); } s[w] = 1; } } } if (!div_flag) { l++; _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, 1); if (small) { fmpz_set_signed_uiuiui(p2 + l, c[2], c[1], c[0]); fmpz_neg(p2 + l, p2 + l); } else { fmpz_neg(p2 + l, qc); } e2[l] = exp; } } } cleanup: for (i = 0; i < len; i++) _fmpz_mpoly_set_length(polyq[i], k[i] + 1, ctx); for (i = 0; i < len; i++) fmpz_clear(mb + i); fmpz_clear(qc); fmpz_clear(q); (*polyr) = p2; (*expr) = e2; TMP_END; return l + 1; exp_overflow: for (i = 0; i < l; i++) _fmpz_demote(p2 + i); for (w = 0; w < len; w++) { for (i = 0; i < k[w]; i++) _fmpz_demote(polyq[w]->coeffs + i); k[w] = -WORD(1); /* we add 1 to this before exit */ } l = -WORD(2); /* we add 1 to this upon return */ goto cleanup; } /* As for divrem_monagan_pearce except that an array of divisor polynomials is passed and an array of quotient polynomials is returned. These are not in low level format. */ slong _fmpz_mpoly_divrem_ideal_monagan_pearce(fmpz_mpoly_struct ** polyq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, fmpz_mpoly_struct * const * poly3, ulong * const * exp3, slong len, slong N, slong bits, const fmpz_mpoly_ctx_t ctx, const ulong * cmpmask) { slong i, j, p, l, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_nheap_t ** chains; slong ** hinds; mpoly_nheap_t * x; fmpz * p2 = *polyr; ulong * e2 = *expr; ulong * exp, * exps, * texp; ulong ** exp_list; ulong c[3]; /* for accumulating coefficients */ slong exp_next; ulong mask = 0; ulong * ub; slong * k, * s; fmpz_t qc, q; fmpz * mb; int small; slong bits2, bits3; int d1, d2, div_flag; TMP_INIT; if (N == 1) return _fmpz_mpoly_divrem_ideal_monagan_pearce1(polyq, polyr, expr, allocr, poly2, exp2, len2, poly3, exp3, len, bits, ctx, cmpmask[0]); TMP_START; fmpz_init(q); fmpz_init(qc); bits2 = _fmpz_vec_max_bits(poly2, len2); chains = (mpoly_nheap_t **) TMP_ALLOC(len*sizeof(mpoly_nheap_t *)); hinds = (slong **) TMP_ALLOC(len*sizeof(slong *)); bits3 = 0; len3 = 0; for (w = 0; w < len; w++) { chains[w] = (mpoly_nheap_t *) TMP_ALLOC((poly3[w]->length)*sizeof(mpoly_nheap_t)); hinds[w] = (slong *) TMP_ALLOC((poly3[w]->length)*sizeof(slong)); bits3 = FLINT_MAX(bits3, FLINT_ABS(fmpz_mpoly_max_bits(poly3[w]))); len3 += poly3[w]->length; for (i = 0; i < poly3[w]->length; i++) hinds[w][i] = 1; } /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong)); exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); k = (slong *) TMP_ALLOC(len*sizeof(slong)); s = (slong *) TMP_ALLOC(len*sizeof(slong)); ub = (ulong *) TMP_ALLOC(len*sizeof(ulong)); mb = (fmpz * ) TMP_ALLOC(len*sizeof(fmpz)); exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; for (w = 0; w < len; w++) { k[w] = -WORD(1); s[w] = poly3[w]->length; } l = -WORD(1); x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); for (i = 0; i < len; i++) { fmpz_init(mb + i); fmpz_neg(mb + i, poly3[i]->coeffs); ub[i] = ((ulong) FLINT_ABS(mb[i])) >> 1; /* abs(poly3[0])/2 */ } while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); c[0] = c[1] = c[2] = 0; fmpz_zero(qc); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)) { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i != -WORD(1)) hinds[x->p][x->i] |= WORD(1); if (small) { if (x->i == -WORD(1)) _fmpz_mpoly_sub_uiuiui_fmpz(c, poly2 + x->j); else _fmpz_mpoly_addmul_uiuiui_fmpz(c, poly3[x->p]->coeffs[x->i], polyq[x->p]->coeffs[x->j]); } else { if (x->i == -WORD(1)) fmpz_sub(qc, qc, poly2 + x->j); else fmpz_addmul(qc, poly3[x->p]->coeffs + x->i, polyq[x->p]->coeffs + x->j); } } while ((x = x->next) != NULL); } while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right */ if ( (i + 1 < poly3[p]->length) && (hinds[p][i + 1] == 2*j + 1) ) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[x->p] + x->i*N, polyq[x->p]->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j == k[p]) { s[p]++; } else if ( ((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1)) ) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[x->p] + x->i*N, polyq[x->p]->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if ((small && (c[2] != 0 || c[1] != 0 || c[0] != 0)) || (!small && !fmpz_is_zero(qc))) { div_flag = 0; for (w = 0; w < len; w++) { if (bits <= FLINT_BITS) d1 = mpoly_monomial_divides(texp, exp, exp3[w], N, mask); else d1 = mpoly_monomial_divides_mp(texp, exp, exp3[w], N, bits); if (d1) { d2 = 0; if (small) { ulong d[3]; if (0 > (slong) c[2]) mpn_neg(d, c, 3); else flint_mpn_copyi(d, c, 3); if (d[2] != 0 || ub[w] <= d[1] || (ub[w] == 0 && 0 > (slong) d[0])) /* quotient not a small */ { small = 0; fmpz_set_signed_uiuiui(qc, c[2], c[1], c[0]); } else /* quotient fits a small */ { slong r1; slong tq; fdiv_qrnnd(tq, r1, c[1], c[0], mb[w]); if (tq > COEFF_MAX || tq < COEFF_MIN) { small = 0; fmpz_set_signed_uiuiui(qc, c[2], c[1], c[0]); } else { d2 = tq != 0; div_flag = r1 == 0; if (d2) { k[w]++; fmpz_mpoly_fit_length(polyq[w], k[w] + 1, ctx); fmpz_set_si(polyq[w]->coeffs + k[w], tq); mpoly_monomial_set(polyq[w]->exps + k[w]*N, texp, N); } c[0] = r1; c[2] = c[1] = -(slong)(r1 < 0); } } } /* quotient non-small case */ if (!small) { fmpz_fdiv_qr(q, qc, qc, mb + w); d2 = !fmpz_is_zero(q); div_flag = fmpz_is_zero(qc); if (d2) { k[w]++; fmpz_mpoly_fit_length(polyq[w], k[w] + 1, ctx); fmpz_set(polyq[w]->coeffs + k[w], q); mpoly_monomial_set(polyq[w]->exps + k[w]*N, texp, N); } } if (d2) { if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = k[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[w] + i*N, polyq[w]->exps + k[w]*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s[w] = 1; } } } if (!div_flag) { l++; _fmpz_mpoly_fit_length(&p2, &e2, allocr, l + 1, N); if (small) { fmpz_set_signed_uiuiui(p2 + l, c[2], c[1], c[0]); fmpz_neg(p2 + l, p2 + l); } else { fmpz_neg(p2 + l, qc); } mpoly_monomial_set(e2 + l*N, exp, N); } } } cleanup2: for (i = 0; i < len; i++) _fmpz_mpoly_set_length(polyq[i], k[i] + 1, ctx); for (i = 0; i < len; i++) fmpz_clear(mb + i); fmpz_clear(qc); fmpz_clear(q); (*polyr) = p2; (*expr) = e2; TMP_END; return l + 1; exp_overflow: for (i = 0; i < l; i++) _fmpz_demote(p2 + i); for (w = 0; w < len; w++) { for (i = 0; i < k[w]; i++) _fmpz_demote(polyq[w]->coeffs + i); k[w] = -WORD(1); } l = -WORD(2); goto cleanup2; } /* Assumes divisor polys don't alias any output polys */ void fmpz_mpoly_divrem_ideal_monagan_pearce(fmpz_mpoly_struct ** q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, fmpz_mpoly_struct * const * poly3, slong len, const fmpz_mpoly_ctx_t ctx) { slong i, exp_bits, N, lenr = 0; slong len3 = 0; ulong * cmpmask; ulong * exp2; ulong ** exp3; int free2 = 0; int * free3; fmpz_mpoly_t temp2; fmpz_mpoly_struct * tr; TMP_INIT; /* check none of the divisor polynomials is zero */ for (i = 0; i < len; i++) { if (poly3[i]->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divrem_ideal_monagan_pearce"); len3 = FLINT_MAX(len3, poly3[i]->length); } /* dividend is zero, write out quotients and remainder */ if (poly2->length == 0) { for (i = 0; i < len; i++) { fmpz_mpoly_zero(q[i], ctx); } fmpz_mpoly_zero(r, ctx); return; } TMP_START; free3 = (int *) TMP_ALLOC(len*sizeof(int)); exp3 = (ulong **) TMP_ALLOC(len*sizeof(ulong *)); /* compute maximum degrees that can occur in any input or output polys */ exp_bits = poly2->bits; for (i = 0; i < len; i++) exp_bits = FLINT_MAX(exp_bits, poly3[i]->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ exp2 = poly2->exps; free2 = 0; if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } for (i = 0; i < len; i++) { exp3[i] = poly3[i]->exps; free3[i] = 0; if (exp_bits > poly3[i]->bits) { free3[i] = 1; exp3[i] = (ulong *) flint_malloc(N*poly3[i]->length*sizeof(ulong)); mpoly_repack_monomials(exp3[i], exp_bits, poly3[i]->exps, poly3[i]->bits, poly3[i]->length, ctx->minfo); } fmpz_mpoly_fit_length(q[i], 1, ctx); fmpz_mpoly_fit_bits(q[i], exp_bits, ctx); q[i]->bits = exp_bits; } /* check leading mon. of at least one divisor is at most that of dividend */ for (i = 0; i < len; i++) { if (!mpoly_monomial_lt(exp2, exp3[i], N, cmpmask)) break; } if (i == len) { fmpz_mpoly_set(r, poly2, ctx); for (i = 0; i < len; i++) fmpz_mpoly_zero(q[i], ctx); goto cleanup3; } /* take care of aliasing */ if (r == poly2) { fmpz_mpoly_init2(temp2, len3, ctx); fmpz_mpoly_fit_bits(temp2, exp_bits, ctx); temp2->bits = exp_bits; tr = temp2; } else { fmpz_mpoly_fit_length(r, len3, ctx); fmpz_mpoly_fit_bits(r, exp_bits, ctx); r->bits = exp_bits; tr = r; } /* do division with remainder */ while (1) { slong old_exp_bits = exp_bits; ulong * old_exp2 = exp2, * old_exp3; lenr = _fmpz_mpoly_divrem_ideal_monagan_pearce(q, &tr->coeffs, &tr->exps, &tr->alloc, poly2->coeffs, exp2, poly2->length, poly3, exp3, len, N, exp_bits, ctx, cmpmask); if (lenr >= 0) /* check if division was successful */ break; exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, old_exp2, old_exp_bits, poly2->length, ctx->minfo); if (free2) flint_free(old_exp2); free2 = 1; fmpz_mpoly_fit_bits(tr, exp_bits, ctx); tr->bits = exp_bits; for (i = 0; i < len; i++) { old_exp3 = exp3[i]; exp3[i] = (ulong *) flint_malloc(N*poly3[i]->length*sizeof(ulong)); mpoly_repack_monomials(exp3[i], exp_bits, old_exp3, old_exp_bits, poly3[i]->length, ctx->minfo); if (free3[i]) flint_free(old_exp3); free3[i] = 1; fmpz_mpoly_fit_bits(q[i], exp_bits, ctx); q[i]->bits = exp_bits; } } /* take care of aliasing */ if (r == poly2) { fmpz_mpoly_swap(temp2, r, ctx); fmpz_mpoly_clear(temp2, ctx); } _fmpz_mpoly_set_length(r, lenr, ctx); cleanup3: if (free2) flint_free(exp2); for (i = 0; i < len; i++) { if (free3[i]) flint_free(exp3[i]); } flint_free(cmpmask); TMP_END; } flint-3.1.3/src/fmpz_mpoly/equal.c000066400000000000000000000041661461254215100171000ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int _fmpz_mpoly_equal(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong n, slong N) { slong i; if (poly1 != poly2) { for (i = 0; i < n; i++) { if (!fmpz_equal(poly1 + i, poly2 + i)) return 0; } } if (exps1 != exps2) { for (i = 0; i < n*N; i++) { if (exps1[i] != exps2[i]) return 0; } } return 1; } int fmpz_mpoly_equal(const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) { ulong * ptr1 = poly1->exps, * ptr2 = poly2->exps; slong max_bits, N; int r, free1 = 0, free2 = 0; if (poly1 == poly2) return 1; if (poly1->length != poly2->length) return 0; max_bits = FLINT_MAX(poly1->bits, poly2->bits); N = mpoly_words_per_exp(max_bits, ctx->minfo); if (max_bits > poly1->bits) { free1 = 1; ptr1 = (ulong *) flint_malloc(N*poly1->length*sizeof(ulong)); mpoly_repack_monomials(ptr1, max_bits, poly1->exps, poly1->bits, poly1->length, ctx->minfo); } if (max_bits > poly2->bits) { free2 = 1; ptr2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(ptr2, max_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } r = _fmpz_mpoly_equal(poly1->coeffs, ptr1, poly2->coeffs, ptr2, poly2->length, N); if (free1) flint_free(ptr1); if (free2) flint_free(ptr2); return r; } flint-3.1.3/src/fmpz_mpoly/equal_fmpz.c000066400000000000000000000015661461254215100201350ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_equal_fmpz(const fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { slong N; if (fmpz_is_zero(c)) return A->length == 0; if (A->length != 1) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return fmpz_equal(A->coeffs + 0, c); } flint-3.1.3/src/fmpz_mpoly/equal_si.c000066400000000000000000000015561461254215100175730ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_equal_si(const fmpz_mpoly_t A, slong c, const fmpz_mpoly_ctx_t ctx) { slong N; if (c == 0) return A->length == 0; if (A->length != 1) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return fmpz_equal_si(A->coeffs + 0, c); } flint-3.1.3/src/fmpz_mpoly/equal_ui.c000066400000000000000000000015561461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_equal_ui(const fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx) { slong N; if (c == 0) return A->length == 0; if (A->length != 1) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return fmpz_equal_ui(A->coeffs + 0, c); } flint-3.1.3/src/fmpz_mpoly/evaluate_all.c000066400000000000000000000135331461254215100204250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* given the exponent and the bit count of the base, can we expect b^e to fail */ int _fmpz_pow_fmpz_is_not_feasible(flint_bitcnt_t bbits, const fmpz_t e) { ulong limit = (ulong)(WORD_MAX)/(ulong)(2*sizeof(fmpz)); FLINT_ASSERT(fmpz_sgn(e) >= 0); return bbits > 1 && fmpz_cmp_ui(e, limit/bbits) >= 0; } int _fmpz_pow_ui_is_not_feasible(flint_bitcnt_t bbits, ulong e) { ulong limit = (ulong)(WORD_MAX)/(ulong)(2*sizeof(fmpz)); return bbits > 1 && e >= limit/bbits; } int _fmpz_mpoly_evaluate_all_fmpz_sp(fmpz_t ev, const fmpz_mpoly_t A, fmpz * const * val, const fmpz_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t bits = A->bits; slong i, j, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, shift, off; slong Alen = A->length; const fmpz * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong * degrees; slong * offs; ulong * masks; fmpz * powers; fmpz_t t; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; degrees = TMP_ARRAY_ALLOC(nvars, slong); mpoly_degrees_si(degrees, Aexp, Alen, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_fmpz_pow_ui_is_not_feasible(fmpz_bits(val[i]), degrees[i])) { success = 0; goto cleanup_degrees; } entries += FLINT_BIT_COUNT(degrees[i]); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fmpz); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = FLINT_BIT_COUNT(degrees[i]); mpoly_gen_offset_shift_sp(&off, &shift, i, bits, ctx->minfo); for (j = 0; j < varibits; j++) { offs[k] = off; masks[k] = UWORD(1) << (shift + j); fmpz_init(powers + k); if (j == 0) fmpz_set(powers + k, val[i]); else fmpz_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fmpz_zero(ev); fmpz_init(t); for (i = 0; i < Alen; i++) { fmpz_set(t, Acoeff + i); for (k = 0; k < k_len; k++) { if ((Aexp[N*i + offs[k]] & masks[k]) != WORD(0)) fmpz_mul(t, t, powers + k); } fmpz_add(ev, ev, t); } fmpz_clear(t); for (k = 0; k < k_len; k++) fmpz_clear(powers + k); cleanup_degrees: TMP_END; return success; } int _fmpz_mpoly_evaluate_all_fmpz_mp(fmpz_t ev, const fmpz_mpoly_t A, fmpz * const * vals, const fmpz_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t Abits = A->bits; slong i, j, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, off; slong Alen = A->length; const fmpz * Acoeff = A->coeffs; const ulong * Aexp = A->exps; slong * degrees; slong * offs; ulong * masks; fmpz * powers; fmpz_t t; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; degrees = _fmpz_vec_init(nvars); mpoly_degrees_ffmpz(degrees, Aexp, Alen, Abits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_fmpz_pow_fmpz_is_not_feasible(fmpz_bits(vals[i]), degrees + i)) { success = 0; goto cleanup_degrees; } entries += fmpz_bits(degrees + i); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fmpz); N = mpoly_words_per_exp(Abits, ctx->minfo); /* store bit masks for each power of two of the variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = fmpz_bits(degrees + i); off = mpoly_gen_offset_mp(i, Abits, ctx->minfo); for (j = 0; j < varibits; j++) { offs[k] = off + (j / FLINT_BITS); masks[k] = UWORD(1) << (j % FLINT_BITS); fmpz_init(powers + k); if (j == 0) fmpz_set(powers + k, vals[i]); else fmpz_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fmpz_zero(ev); fmpz_init(t); for (i = 0; i < Alen; i++) { fmpz_set(t, Acoeff + i); for (k = 0; k < k_len; k++) { if ((Aexp[N*i + offs[k]] & masks[k]) != WORD(0)) fmpz_mul(t, t, powers + k); } fmpz_add(ev, ev, t); } fmpz_clear(t); for (k = 0; k < k_len; k++) fmpz_clear(powers + k); cleanup_degrees: _fmpz_vec_clear(degrees, nvars); TMP_END; return success; } /* evaluate A(xbar) at xbar = vals */ int fmpz_mpoly_evaluate_all_fmpz(fmpz_t ev, const fmpz_mpoly_t A, fmpz * const * vals, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx)) { fmpz_zero(ev); return 1; } if (A->bits <= FLINT_BITS) { return _fmpz_mpoly_evaluate_all_fmpz_sp(ev, A, vals, ctx); } else { return _fmpz_mpoly_evaluate_all_fmpz_mp(ev, A, vals, ctx); } } flint-3.1.3/src/fmpz_mpoly/evaluate_all_fmpz_mod.c000066400000000000000000000013351461254215100223150ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #include "fmpz_mod_mpoly.h" void fmpz_mpoly_evaluate_all_fmpz_mod( fmpz_t ev, const fmpz_mpoly_t A, const fmpz * alphas, const fmpz_mpoly_ctx_t ctx, const fmpz_mod_ctx_t fpctx) { _fmpz_mod_mpoly_eval_all_fmpz_mod(ev, A->coeffs, A->exps, A->length, A->bits, alphas, ctx->minfo, fpctx); } flint-3.1.3/src/fmpz_mpoly/evaluate_all_nmod.c000066400000000000000000000016561461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nmod_mpoly.h" #include "fmpz_mpoly.h" mp_limb_t fmpz_mpoly_evaluate_all_nmod( const fmpz_mpoly_t A, const mp_limb_t * alphas, const fmpz_mpoly_ctx_t ctx, nmod_t fpctx) { mp_limb_t eval, * t; TMP_INIT; TMP_START; t = TMP_ARRAY_ALLOC(A->length, mp_limb_t); _fmpz_vec_get_nmod_vec(t, A->coeffs, A->length, fpctx); eval = _nmod_mpoly_eval_all_ui(t, A->exps, A->length, A->bits, alphas, ctx->minfo, fpctx); TMP_END; return eval; } flint-3.1.3/src/fmpz_mpoly/evaluate_one.c000066400000000000000000000156531461254215100204430ustar00rootroot00000000000000/*r Copyright (C) 2018, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_pow_cache_init(fmpz_pow_cache_t T, const fmpz_t val) { fmpz_init(T->tmp); T->alloc = 10; T->powers = _fmpz_vec_init(T->alloc); fmpz_one(T->powers + 0); fmpz_set(T->powers + 1, val); T->length = 2; } void fmpz_pow_cache_clear(fmpz_pow_cache_t T) { fmpz_clear(T->tmp); _fmpz_vec_clear(T->powers, T->alloc); } /* a = b * val^k */ int fmpz_pow_cache_mulpow_ui( fmpz_t a, const fmpz_t b, ulong k, fmpz_pow_cache_t T) { slong i; if (k > 100) { fmpz_pow_ui(T->tmp, T->powers + 1, k); fmpz_mul(a, b, T->tmp); return 1; } if (k >= T->length) { if (k + 1 >= T->alloc) { slong new_alloc = FLINT_MAX(k + 1, 2*T->alloc); T->powers = FLINT_ARRAY_REALLOC(T->powers, new_alloc, fmpz); for (i = T->alloc; i < new_alloc; i++) fmpz_init(T->powers + i); T->alloc = new_alloc; } do { fmpz_mul(T->powers + T->length, T->powers + T->length - 1, T->powers + 1); T->length++; } while (k >= T->length); } fmpz_mul(a, b, T->powers + k); return 1; } int fmpz_pow_cache_mulpow_fmpz( fmpz_t a, const fmpz_t b, const fmpz_t k, fmpz_pow_cache_t T) { if (fmpz_abs_fits_ui(k)) return fmpz_pow_cache_mulpow_ui(a, b, fmpz_get_ui(k), T); if (!fmpz_pow_fmpz(T->tmp, T->powers + 1, k)) return 0; fmpz_mul(a, b, T->tmp); return 1; } /* exponents of B are not multiprecision */ static int _fmpz_mpoly_evaluate_one_fmpz_sp( fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, fmpz_pow_cache_t cache, const fmpz_mpoly_ctx_t ctx) { int success = 1; slong i, N, off, shift; ulong * cmpmask, * one; slong Blen = B->length; const fmpz * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; fmpz * Acoeffs; ulong * Aexps; ulong mask, k; int need_sort = 0, cmp; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; if (A != B) fmpz_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; mask = (-UWORD(1)) >> (FLINT_BITS - bits); N = mpoly_words_per_exp_sp(bits, ctx->minfo); cmpmask = TMP_ARRAY_ALLOC(2*N, ulong); one = cmpmask + N; mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; success = fmpz_pow_cache_mulpow_ui(Acoeffs + Alen, Bcoeffs + i, k, cache); if (!success) break; if (fmpz_is_zero(Acoeffs + Alen)) continue; mpoly_monomial_msub(Aexps + N*Alen, Bexps + N*i, k, one, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fmpz_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen); Alen -= fmpz_is_zero(Acoeffs + Alen - 1); } /* from the fmpz_add: at most two junk coeffs past length */ for (i = Alen; i < Alen + 2 && i < A->alloc; i++) _fmpz_demote(Acoeffs + i); _fmpz_mpoly_set_length(A, Alen, ctx); TMP_END; if (need_sort) { fmpz_mpoly_sort_terms(A, ctx); fmpz_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fmpz_mpoly_is_canonical(A, ctx)); return success; } /* exponents of B are multiprecision */ static int _fmpz_mpoly_evaluate_one_fmpz_mp( fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, fmpz_pow_cache_t cache, const fmpz_mpoly_ctx_t ctx) { int success = 1; slong i, N, off; ulong * cmpmask, * one, * tmp; slong Blen = B->length; const fmpz * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; fmpz * Acoeffs; ulong * Aexps; fmpz_t k; int need_sort = 0, cmp; TMP_INIT; FLINT_ASSERT((B->bits % FLINT_BITS) == 0); TMP_START; fmpz_init(k); if (A != B) fmpz_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; N = mpoly_words_per_exp(bits, ctx->minfo); one = (ulong *) TMP_ALLOC(3*N*sizeof(ulong)); cmpmask = one + N; tmp = cmpmask + N; off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexps + N*i + off, bits/FLINT_BITS); success = fmpz_pow_cache_mulpow_fmpz(Acoeffs + Alen, Bcoeffs + i, k, cache); if (!success) break; if (fmpz_is_zero(Acoeffs + Alen)) continue; mpoly_monomial_mul_fmpz(tmp, one, N, k); mpoly_monomial_sub_mp(Aexps + N*Alen, Bexps + N*i, tmp, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fmpz_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen); Alen -= fmpz_is_zero(Acoeffs + Alen - 1); } /* from the fmpz_add: at most two junk coeffs past length */ for (i = Alen; i < Alen + 2 && i < A->alloc; i++) _fmpz_demote(Acoeffs + i); _fmpz_mpoly_set_length(A, Alen, ctx); fmpz_clear(k); TMP_END; if (need_sort) { fmpz_mpoly_sort_terms(A, ctx); fmpz_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fmpz_mpoly_is_canonical(A, ctx)); return success; } int fmpz_mpoly_evaluate_one_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_t val, const fmpz_mpoly_ctx_t ctx) { int success; fmpz_pow_cache_t T; if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_zero(A, ctx); return 1; } fmpz_pow_cache_init(T, val); if (B->bits <= FLINT_BITS) success = _fmpz_mpoly_evaluate_one_fmpz_sp(A, B, var, T, ctx); else success = _fmpz_mpoly_evaluate_one_fmpz_mp(A, B, var, T, ctx); fmpz_pow_cache_clear(T); return success; } flint-3.1.3/src/fmpz_mpoly/fit_bits.c000066400000000000000000000020211461254215100175600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_fit_bits(fmpz_mpoly_t A, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx) { if (A->bits < bits) { if (A->alloc != 0) { slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong * t = (ulong *) flint_malloc(N*A->alloc*sizeof(ulong)); mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, ctx->minfo); flint_free(A->exps); A->exps = t; } A->bits = bits; } } slong fmpz_mpoly_max_bits(const fmpz_mpoly_t A) { return _fmpz_vec_max_bits(A->coeffs, A->length); } flint-3.1.3/src/fmpz_mpoly/fit_length.c000066400000000000000000000027111461254215100201060ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void _fmpz_mpoly_fit_length(fmpz ** poly, ulong ** exps, slong * alloc, slong len, slong N) { if (len > *alloc) { /* at least double size */ len = FLINT_MAX(len, 2*(*alloc)); _fmpz_mpoly_realloc(poly, exps, alloc, len, N); } } void fmpz_mpoly_fit_length(fmpz_mpoly_t poly, slong len, const fmpz_mpoly_ctx_t ctx) { if (len > poly->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * poly->alloc) len = 2 * poly->alloc; fmpz_mpoly_realloc(poly, len, ctx); } } void _fmpz_mpoly_set_length(fmpz_mpoly_t A, slong newlen, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = newlen; i < A->length; i++) _fmpz_demote(A->coeffs + i); A->length = newlen; } void fmpz_mpoly_truncate(fmpz_mpoly_t A, slong newlen, const fmpz_mpoly_ctx_t ctx) { if (A->length > newlen) { slong i; for (i = newlen; i < A->length; i++) _fmpz_demote(A->coeffs + i); A->length = newlen; } } flint-3.1.3/src/fmpz_mpoly/fit_length_reset_bits.c000066400000000000000000000027631461254215100223400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* Ensure that A has space for "len" terms with bits "bits" and set A->bits The value of A is destroyed. Since the coefficient alloc and the exponent alloc are coupled, we must have the assumption that A is allocated wrt ctx upon entry. TODO: decouple the two allocations as in nmod_mpoly/fq_nmod_mpoly */ void fmpz_mpoly_fit_length_reset_bits( fmpz_mpoly_t A, slong len, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx) { slong i; slong oldN = mpoly_words_per_exp(A->bits, ctx->minfo); slong newN = mpoly_words_per_exp(bits, ctx->minfo); if (len > A->alloc) { len = FLINT_MAX(len, 2*A->alloc); A->exps = (ulong *) flint_realloc(A->exps, newN*len*sizeof(ulong)); A->coeffs = (fmpz *) flint_realloc(A->coeffs, len*sizeof(fmpz)); for (i = A->alloc; i < len; i++) fmpz_init(A->coeffs + i); A->alloc = len; } else if (newN > oldN && A->alloc > 0) { A->exps = (ulong *) flint_realloc(A->exps, newN*A->alloc*sizeof(ulong)); } A->bits = bits; } flint-3.1.3/src/fmpz_mpoly/gcd.c000066400000000000000000000022161461254215100165200ustar00rootroot00000000000000/* Copyright (C) 2018-2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_gcd( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx)) { if (fmpz_mpoly_is_zero(B, ctx)) fmpz_mpoly_zero(G, ctx); else if (fmpz_sgn(B->coeffs + 0) < 0) fmpz_mpoly_neg(G, B, ctx); else fmpz_mpoly_set(G, B, ctx); return 1; } if (fmpz_mpoly_is_zero(B, ctx)) { if (fmpz_sgn(A->coeffs + 0) < 0) fmpz_mpoly_neg(G, A, ctx); else fmpz_mpoly_set(G, A, ctx); return 1; } return _fmpz_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/fmpz_mpoly/gcd_brown.c000066400000000000000000000014151461254215100177270ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_gcd_brown( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx) || fmpz_mpoly_is_zero(B, ctx)) return fmpz_mpoly_gcd(G, A, B, ctx); return _fmpz_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_BROWN); } flint-3.1.3/src/fmpz_mpoly/gcd_cofactors.c000066400000000000000000000030471461254215100205660ustar00rootroot00000000000000/* Copyright (C) 2018-2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_gcd_cofactors( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx)) { if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_zero(G, ctx); fmpz_mpoly_zero(Abar, ctx); fmpz_mpoly_zero(Bbar, ctx); return 1; } fmpz_mpoly_set(G, B, ctx); fmpz_mpoly_zero(Abar, ctx); fmpz_mpoly_one(Bbar, ctx); if (fmpz_sgn(G->coeffs + 0) < 0) { fmpz_mpoly_neg(G, G, ctx); fmpz_mpoly_neg(Bbar, Bbar, ctx); } return 1; } if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_set(G, A, ctx); fmpz_mpoly_zero(Bbar, ctx); fmpz_mpoly_one(Abar, ctx); if (fmpz_sgn(G->coeffs + 0) < 0) { fmpz_mpoly_neg(G, G, ctx); fmpz_mpoly_neg(Abar, Abar, ctx); } return 1; } return _fmpz_mpoly_gcd_algo(G, Abar, Bbar, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/fmpz_mpoly/gcd_hensel.c000066400000000000000000000014171461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_gcd_hensel( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx) || fmpz_mpoly_is_zero(B, ctx)) return fmpz_mpoly_gcd(G, A, B, ctx); return _fmpz_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_HENSEL); } flint-3.1.3/src/fmpz_mpoly/gcd_subresultant.c000066400000000000000000000014221461254215100213310ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_gcd_subresultant( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx) || fmpz_mpoly_is_zero(B, ctx)) return fmpz_mpoly_gcd(G, A, B, ctx); return _fmpz_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_PRS); } flint-3.1.3/src/fmpz_mpoly/gcd_zippel.c000066400000000000000000000014171461254215100201050ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_gcd_zippel( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx) || fmpz_mpoly_is_zero(B, ctx)) return fmpz_mpoly_gcd(G, A, B, ctx); return _fmpz_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL); } flint-3.1.3/src/fmpz_mpoly/gcd_zippel2.c000066400000000000000000000014211461254215100201620ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_gcd_zippel2( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(A, ctx) || fmpz_mpoly_is_zero(B, ctx)) return fmpz_mpoly_gcd(G, A, B, ctx); return _fmpz_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL2); } flint-3.1.3/src/fmpz_mpoly/gen.c000066400000000000000000000017231461254215100165360ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_gen(fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { flint_bitcnt_t bits; bits = mpoly_gen_bits_required(var, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); fmpz_mpoly_fit_length_reset_bits(A, 1, bits, ctx); fmpz_one(A->coeffs); if (bits <= FLINT_BITS) mpoly_gen_monomial_sp(A->exps, var, bits, ctx->minfo); else mpoly_gen_monomial_offset_mp(A->exps, var, bits, ctx->minfo); _fmpz_mpoly_set_length(A, WORD(1), ctx); } flint-3.1.3/src/fmpz_mpoly/geobuckets.c000066400000000000000000000101111461254215100201070ustar00rootroot00000000000000/* Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_geobucket_init(fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { fmpz_mpoly_init(B->polys + i, ctx); fmpz_mpoly_init(B->temps + i, ctx); } B->length = 0; } void fmpz_mpoly_geobucket_clear(fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { fmpz_mpoly_clear(B->polys + i, ctx); fmpz_mpoly_clear(B->temps + i, ctx); } } /* empty out bucket B into polynomial p */ void fmpz_mpoly_geobucket_empty(fmpz_mpoly_t p, fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx) { slong i; if (B->length < 2) { if (B->length < 1) fmpz_mpoly_zero(p, ctx); else fmpz_mpoly_set(p, B->polys + 0, ctx); } else if (B->length == 2) { fmpz_mpoly_add(p, B->polys + 1, B->polys + 0, ctx); } else { fmpz_mpoly_add(B->temps + 1, B->polys + 1, B->polys + 0, ctx); for (i = 2; i < B->length - 1; i++) fmpz_mpoly_add(B->temps + i, B->polys + i, B->temps + i - 1, ctx); fmpz_mpoly_add(p, B->polys + i, B->temps + i - 1, ctx); } B->length = 0; } void fmpz_mpoly_geobucket_fit_length(fmpz_mpoly_geobucket_t B, slong len, const fmpz_mpoly_ctx_t ctx) { slong j; for (j = B->length; j < len; j++) fmpz_mpoly_zero(B->polys + j, ctx); B->length = j; } /* set bucket B to polynomial p */ void fmpz_mpoly_geobucket_set(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { slong i; i = mpoly_geobucket_clog4(p->length); B->length = 0; fmpz_mpoly_geobucket_fit_length(B, i + 1, ctx); fmpz_mpoly_swap(B->polys + i, p, ctx); B->length = i + 1; } /* internal function for fixing overflows */ static void _fmpz_mpoly_geobucket_fix(fmpz_mpoly_geobucket_t B, slong i, const fmpz_mpoly_ctx_t ctx) { while (mpoly_geobucket_clog4((B->polys + i)->length) > i) { FLINT_ASSERT(i + 1 <= B->length); if (i + 1 == B->length) { B->length = i + 2; fmpz_mpoly_set(B->polys + i + 1, B->polys + i, ctx); } else { fmpz_mpoly_add(B->temps + i + 1, B->polys + i + 1, B->polys + i, ctx); fmpz_mpoly_swap(B->polys + i + 1, B->temps + i + 1, ctx); } fmpz_mpoly_zero(B->polys + i, ctx); i++; } } /* add polynomial p to buckect B */ void fmpz_mpoly_geobucket_add(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { slong i; if (p->length < 1) return; i = mpoly_geobucket_clog4(p->length); fmpz_mpoly_geobucket_fit_length(B, i + 1, ctx); fmpz_mpoly_add(B->temps + i, B->polys + i, p, ctx); fmpz_mpoly_swap(B->polys + i, B->temps + i, ctx); _fmpz_mpoly_geobucket_fix(B, i, ctx); } /* sub polynomial p to buckect B */ void fmpz_mpoly_geobucket_sub(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { slong i; if (p->length < 1) return; i = mpoly_geobucket_clog4(p->length); fmpz_mpoly_geobucket_fit_length(B, i + 1, ctx); fmpz_mpoly_sub(B->temps + i, B->polys + i, p, ctx); fmpz_mpoly_swap(B->polys + i, B->temps + i, ctx); _fmpz_mpoly_geobucket_fix(B, i, ctx); } flint-3.1.3/src/fmpz_mpoly/get_coeff_fmpz_fmpz.c000066400000000000000000000016301461254215100217730ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_coeff_fmpz_fmpz(fmpz_t c, const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_pfmpz(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { fmpz_zero(c); } else { FLINT_ASSERT(index < A->length); fmpz_set(c, A->coeffs + index); } } flint-3.1.3/src/fmpz_mpoly/get_coeff_fmpz_monomial.c000066400000000000000000000020321461254215100226270ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_coeff_fmpz_monomial(fmpz_t c, const fmpz_mpoly_t A, const fmpz_mpoly_t M, const fmpz_mpoly_ctx_t ctx) { slong index; if (M->length != WORD(1)) { flint_throw(FLINT_ERROR, "M not monomial in fmpz_mpoly_get_coeff_fmpz_monomial"); } index = mpoly_monomial_index_monomial(A->exps, A->bits, A->length, M->exps, M->bits, ctx->minfo); if (index < 0) { fmpz_zero(c); } else { FLINT_ASSERT(index < A->length); fmpz_set(c, A->coeffs + index); } } flint-3.1.3/src/fmpz_mpoly/get_coeff_fmpz_ui.c000066400000000000000000000016151461254215100214370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_coeff_fmpz_ui(fmpz_t c, const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_ui(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { fmpz_zero(c); } else { FLINT_ASSERT(index < A->length); fmpz_set(c, A->coeffs + index); } } flint-3.1.3/src/fmpz_mpoly/get_coeff_si_fmpz.c000066400000000000000000000016121461254215100214320ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong fmpz_mpoly_get_coeff_si_fmpz(const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_pfmpz(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { return 0; } else { FLINT_ASSERT(index < A->length); return fmpz_get_si(A->coeffs + index); } } flint-3.1.3/src/fmpz_mpoly/get_coeff_si_ui.c000066400000000000000000000016051461254215100210750ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong fmpz_mpoly_get_coeff_si_ui(const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_ui(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { return 0; } else { FLINT_ASSERT(index < A->length); return fmpz_get_si(A->coeffs + index); } } flint-3.1.3/src/fmpz_mpoly/get_coeff_ui_fmpz.c000066400000000000000000000016121461254215100214340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" ulong fmpz_mpoly_get_coeff_ui_fmpz(const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_pfmpz(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { return 0; } else { FLINT_ASSERT(index < A->length); return fmpz_get_ui(A->coeffs + index); } } flint-3.1.3/src/fmpz_mpoly/get_coeff_ui_ui.c000066400000000000000000000016051461254215100210770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" ulong fmpz_mpoly_get_coeff_ui_ui(const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_ui(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { return 0; } else { FLINT_ASSERT(index < A->length); return fmpz_get_ui(A->coeffs + index); } } flint-3.1.3/src/fmpz_mpoly/get_coeff_vars_ui.c000066400000000000000000000102431461254215100214330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_coeff_vars_ui(fmpz_mpoly_t C, const fmpz_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fmpz_mpoly_ctx_t ctx) { slong i, j, N; slong offset, shift; slong maxoffset, minoffset; ulong * uexp; ulong * tmask, * texp; slong nvars = ctx->minfo->nvars; fmpz * Ccoeff; ulong * Cexp; slong Calloc; slong Clen; TMP_INIT; if (C == A) { fmpz_mpoly_t T; fmpz_mpoly_init(T, ctx); fmpz_mpoly_get_coeff_vars_ui(T, A, vars, exps,length, ctx); fmpz_mpoly_swap(T, C, ctx); fmpz_mpoly_clear(T, ctx); return; } TMP_START; uexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); for (i = 0; i < nvars; i++) { uexp[i] = 0; } for (i = 0; i < length; i++) { uexp[vars[i]] = exps[i]; } if (A->bits < mpoly_exp_bits_required_ui(uexp, ctx->minfo)) { fmpz_mpoly_zero(C, ctx); goto cleanup; } fmpz_mpoly_fit_bits(C, A->bits, ctx); C->bits = A->bits; N = mpoly_words_per_exp(A->bits, ctx->minfo); tmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(tmask, N); mpoly_set_monomial_ui(texp, uexp, A->bits, ctx->minfo); if (A->bits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { mpoly_gen_offset_shift_sp(&offset, &shift, vars[i], A->bits, ctx->minfo); tmask[offset] |= mask << shift; maxoffset = FLINT_MAX(maxoffset, offset); minoffset = FLINT_MIN(minoffset, offset); } FLINT_ASSERT(minoffset < N); Ccoeff = C->coeffs; Cexp = C->exps; Calloc = C->alloc; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_sp; } _fmpz_mpoly_fit_length(&Ccoeff, &Cexp, &Calloc, Clen + 1, N); mpoly_monomial_sub(Cexp + N*Clen, A->exps + N*i, texp, N); fmpz_set(Ccoeff + Clen, A->coeffs + i); Clen++; continue_outer_sp:; } C->coeffs = Ccoeff; C->exps = Cexp; C->alloc = Calloc; _fmpz_mpoly_set_length(C, Clen, ctx); } else { ulong wpf = A->bits/FLINT_BITS; maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { offset = mpoly_gen_offset_mp(vars[i], A->bits, ctx->minfo); minoffset = FLINT_MIN(minoffset, offset); maxoffset = FLINT_MAX(maxoffset, offset + wpf - 1); for (j = 0; j < wpf; j++) tmask[offset + j] = -UWORD(1); } FLINT_ASSERT(minoffset < N); Ccoeff = C->coeffs; Cexp = C->exps; Calloc = C->alloc; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_mp; } _fmpz_mpoly_fit_length(&Ccoeff, &Cexp, &Calloc, Clen + 1, N); mpoly_monomial_sub_mp(Cexp + N*Clen, A->exps + N*i, texp, N); fmpz_set(Ccoeff + Clen, A->coeffs + i); Clen++; continue_outer_mp:; } C->coeffs = Ccoeff; C->exps = Cexp; C->alloc = Calloc; _fmpz_mpoly_set_length(C, Clen, ctx); } cleanup: TMP_END; return; } flint-3.1.3/src/fmpz_mpoly/get_fmpz.c000066400000000000000000000020221461254215100175710ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_fmpz(fmpz_t c, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong N; if (A->length > WORD(1)) flint_throw(FLINT_ERROR, "Nonconstant polynomial in fmpz_mpoly_get_fmpz"); if (A->length == WORD(0)) { fmpz_zero(c); return; } N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) flint_throw(FLINT_ERROR, "Nonconstant monomial in fmpz_mpoly_get_fmpz"); fmpz_set(c, A->coeffs + 0); } flint-3.1.3/src/fmpz_mpoly/get_set_is_fmpz_poly.c000066400000000000000000000131161461254215100222100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_is_fmpz_poly( const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { return mpoly_is_poly(A->exps, A->length, A->bits, var, ctx->minfo); } int fmpz_mpoly_get_fmpz_poly( fmpz_poly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) { slong Blen = B->length; const fmpz * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t Bbits = B->bits; slong i, N = mpoly_words_per_exp(Bbits, ctx->minfo); ulong k; fmpz_poly_zero(A); if (B->length < 1) return 1; if (Bbits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - Bbits); slong off, shift; mpoly_gen_offset_shift_sp(&off, &shift, var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; fmpz_poly_set_coeff_fmpz(A, k, Bcoeffs + i); } return 1; } else { slong j, off; ulong check, wpf = Bbits/FLINT_BITS; off = mpoly_gen_offset_mp(var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = Bexps[N*i + off + 0]; check = 0; for (j = 1; j < wpf; j++) check |= Bexps[N*i + off + j]; if (check != 0 || (slong) k < 0) return 0; fmpz_poly_set_coeff_fmpz(A, k, Bcoeffs + i); } return 1; } } void _fmpz_mpoly_set_fmpz_poly( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz * Bcoeffs, slong Blen, slong var, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += (Bcoeffs[i] != 0); fmpz_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { if (fmpz_is_zero(Bcoeffs + i)) continue; FLINT_ASSERT(Alen < A->alloc); fmpz_set(A->coeffs + Alen, Bcoeffs + i); if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } _fmpz_mpoly_set_length(A, Alen, ctx); TMP_END; } void fmpz_mpoly_set_fmpz_poly( fmpz_mpoly_t A, const fmpz_poly_t B, slong v, const fmpz_mpoly_ctx_t ctx) { flint_bitcnt_t bits; if (B->length == 0) { fmpz_mpoly_zero(A, ctx); } else if (B->length == 1) { fmpz_mpoly_set_fmpz(A, B->coeffs, ctx); } else { bits = mpoly_gen_pow_exp_bits_required(v, B->length - 1, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); _fmpz_mpoly_set_fmpz_poly(A, bits, B->coeffs, B->length, v, ctx); } } void fmpz_mpoly_set_gen_fmpz_poly(fmpz_mpoly_t res, slong var, const fmpz_poly_t pol, const fmpz_mpoly_ctx_t ctx) { if (ctx->minfo->nvars == 0) { flint_throw(FLINT_ERROR, "fmpz_mpoly_set_gen_fmpz_poly: require nvars >= 1"); } fmpz_mpoly_set_fmpz_poly(res, pol, var, ctx); } /* construct a polynomial with at least Aminbits bits from the coefficients Acoeffs[0], ..., Acoeffs[deg]. *** These fmpz's are cleared *** . */ void _fmpz_mpoly_set_fmpz_poly_one_var( fmpz_mpoly_t A, flint_bitcnt_t Aminbits, fmpz * Acoeffs, /* cleared upon return */ slong Adeg, const fmpz_mpoly_ctx_t ctx) { slong i, Alen; flint_bitcnt_t Abits; Abits = mpoly_gen_pow_exp_bits_required(0, Adeg, ctx->minfo); Abits = FLINT_MAX(Abits, Aminbits); Abits = mpoly_fix_bits(Abits, ctx->minfo); fmpz_mpoly_fit_length_reset_bits(A, Adeg + 1, Abits, ctx); FLINT_ASSERT(Abits <= FLINT_BITS); Alen = 0; if (ctx->minfo->ord == ORD_LEX) { FLINT_ASSERT(1 == mpoly_words_per_exp(Abits, ctx->minfo)); for (i = Adeg; i >= 0; i--) { if (fmpz_is_zero(Acoeffs + i)) continue; fmpz_swap(A->coeffs + Alen, Acoeffs + i); A->exps[Alen] = i; Alen++; fmpz_clear(Acoeffs + i); } } else if (1 == mpoly_words_per_exp(Abits, ctx->minfo)) { for (i = Adeg; i >= 0; i--) { if (fmpz_is_zero(Acoeffs + i)) continue; fmpz_swap(A->coeffs + Alen, Acoeffs + i); A->exps[Alen] = i + (i << Abits); Alen++; fmpz_clear(Acoeffs + i); } } else { FLINT_ASSERT(2 == mpoly_words_per_exp(Abits, ctx->minfo)); for (i = Adeg; i >= 0; i--) { if (fmpz_is_zero(Acoeffs + i)) continue; fmpz_swap(A->coeffs + Alen, Acoeffs + i); A->exps[2*Alen + 1] = A->exps[2*Alen + 0] = i; Alen++; fmpz_clear(Acoeffs + i); } } _fmpz_mpoly_set_length(A, Alen, ctx); } flint-3.1.3/src/fmpz_mpoly/get_str_pretty.c000066400000000000000000000072741461254215100210520ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" #define ALLOC_PER_VAR ((FLINT_BITS+4)/3) char * _fmpz_mpoly_get_str_pretty(const fmpz * coeffs, const ulong * exps, slong len, const char ** x_in, slong bits, const mpoly_ctx_t mctx) { char * str, ** x = (char **) x_in, *xtmp; slong i, j, N, bound, off; fmpz * exponents; int first; TMP_INIT; if (len == 0) { str = flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } N = mpoly_words_per_exp(bits, mctx); TMP_START; if (x == NULL) { xtmp = (char *) TMP_ALLOC(mctx->nvars * ALLOC_PER_VAR * sizeof(char)); x = (char **) TMP_ALLOC(mctx->nvars*sizeof(char *)); for (i = 0; i < mctx->nvars; i++) { x[i] = xtmp + i * ALLOC_PER_VAR; flint_sprintf(x[i], "x%wd", i + 1); } } bound = 1; for (i = 0; i < len; i++) bound += fmpz_sizeinbase(coeffs + i, 10) + 1; exponents = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(exponents + i); mpoly_degrees_ffmpz((fmpz *) exponents, exps, len, bits, mctx); for (i = 0; i < mctx->nvars; i++) bound += (fmpz_sizeinbase(exponents + i, 10) + strlen(x[i]) + 3)*len; str = flint_malloc(bound); off = 0; for (i = 0; i < len; i++) { if (fmpz_sgn(coeffs + i) > 0 && i != 0) str[off++] = '+'; if (coeffs[i] == -WORD(1)) str[off++] = '-'; if (coeffs[i] != WORD(1) && coeffs[i] != -WORD(1)) { if (!COEFF_IS_MPZ(coeffs[i])) off += flint_sprintf(str + off, "%wd", coeffs[i]); else off += gmp_sprintf(str + off, "%Zd", COEFF_TO_PTR(coeffs[i])); } mpoly_get_monomial_ffmpz(exponents, exps + N*i, bits, mctx); first = 1; for (j = 0; j < mctx->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, WORD(1)); if (cmp > 0) { if (!first || (coeffs[i] != WORD(1) && coeffs[i] != -WORD(1))) off += flint_sprintf(str + off, "*"); off += flint_sprintf(str + off, "%s^", x[j]); if (!COEFF_IS_MPZ(exponents[j])) off += flint_sprintf(str + off, "%wd", exponents[j]); else off += gmp_sprintf(str + off, "%Zd", COEFF_TO_PTR(exponents[j])); first = 0; } else if (cmp == 0) { if (!first || (coeffs[i] != WORD(1) && coeffs[i] != -WORD(1))) off += flint_sprintf(str + off, "*"); off += flint_sprintf(str + off, "%s", x[j]); first = 0; } } if (mpoly_monomial_is_zero(exps + i*N, N) && (coeffs[i] == WORD(1) || coeffs[i] == -WORD(1))) off += flint_sprintf(str + off, "1"); } for (i = 0; i < mctx->nvars; i++) fmpz_clear(exponents + i); TMP_END; return str; } char * fmpz_mpoly_get_str_pretty(const fmpz_mpoly_t poly, const char ** x, const fmpz_mpoly_ctx_t ctx) { return _fmpz_mpoly_get_str_pretty(poly->coeffs, poly->exps, poly->length, x, poly->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/get_term.c000066400000000000000000000020461461254215100175720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_term(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t bits = A->bits; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term"); } fmpz_mpoly_fit_length(M, WORD(1), ctx); fmpz_mpoly_fit_bits(M, bits, ctx); M->bits = bits; N = mpoly_words_per_exp(bits, ctx->minfo); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); fmpz_set(M->coeffs + 0, A->coeffs + i); _fmpz_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/fmpz_mpoly/get_term_coeff_fmpz.c000066400000000000000000000027141461254215100217720ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2016 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_term_coeff_fmpz(fmpz_t c, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "index out of range in fmpz_mpoly_get_term_coeff_fmpz"); } fmpz_set(c, A->coeffs + i); } ulong fmpz_mpoly_get_term_coeff_ui(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "index out of range in fmpz_mpoly_get_term_coeff_ui"); } return fmpz_get_ui(A->coeffs + i); } slong fmpz_mpoly_get_term_coeff_si(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "index out of range in fmpz_mpoly_get_term_coeff_si"); } return fmpz_get_si(A->coeffs + i); } flint-3.1.3/src/fmpz_mpoly/get_term_exp_fmpz.c000066400000000000000000000015251461254215100215030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term_exp_fmpz"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_pfmpz(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/get_term_exp_si.c000066400000000000000000000016151461254215100211420ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_term_exp_si(slong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term_exp_si"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_si(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/get_term_exp_ui.c000066400000000000000000000015621461254215100211450ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_term_exp_ui(ulong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term_exp_ui"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_ui(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/get_term_monomial.c000066400000000000000000000020511461254215100214610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_get_term_monomial(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t bits = A->bits; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term_monomial"); } fmpz_mpoly_fit_length(M, WORD(1), ctx); fmpz_mpoly_fit_bits(M, bits, ctx); M->bits = bits; N = mpoly_words_per_exp(bits, ctx->minfo); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); fmpz_one(M->coeffs + 0); _fmpz_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/fmpz_mpoly/get_term_var_exp_si.c000066400000000000000000000016061461254215100220120ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" slong fmpz_mpoly_get_term_var_exp_si(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term_var_exp_si"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_get_monomial_var_exp_si(A->exps + N*i, var, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/get_term_var_exp_ui.c000066400000000000000000000016061461254215100220140ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" ulong fmpz_mpoly_get_term_var_exp_ui(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_get_term_var_exp_ui"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_get_monomial_var_exp_ui(A->exps + N*i, var, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/inflate.c000066400000000000000000000046461461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_inflate(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz * shift, const fmpz * stride, const fmpz_mpoly_ctx_t ctx) { int have_zero_stride; slong j; slong Abits; slong nvars = ctx->minfo->nvars; fmpz * exps; TMP_INIT; if (B->length == 0) { fmpz_mpoly_zero(A, ctx); return; } TMP_START; exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exps + j); /* quick and safe bound on bits required */ mpoly_degrees_ffmpz(exps, B->exps, B->length, B->bits, ctx->minfo); have_zero_stride = 0; for (j = 0; j < nvars; j++) { have_zero_stride |= fmpz_is_zero(stride + j); fmpz_mul(exps + j, exps + j, stride + j); fmpz_add(exps + j, exps + j, shift + j); } Abits = mpoly_exp_bits_required_ffmpz(exps, ctx->minfo); Abits = mpoly_fix_bits(Abits, ctx->minfo); for (j = 0; j < nvars; j++) fmpz_clear(exps + j); if (A == B) { slong NA = mpoly_words_per_exp(Abits, ctx->minfo); ulong * texps = flint_malloc(NA*A->alloc*sizeof(ulong)); mpoly_monomials_inflate(texps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = Abits; } else { fmpz_mpoly_fit_length(A, B->length, ctx); fmpz_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; _fmpz_vec_set(A->coeffs, B->coeffs, B->length); mpoly_monomials_inflate(A->exps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _fmpz_mpoly_set_length(A, B->length, ctx); } TMP_END; if (have_zero_stride || ctx->minfo->ord != ORD_LEX) { fmpz_mpoly_sort_terms(A, ctx); if (have_zero_stride) fmpz_mpoly_combine_like_terms(A, ctx); } return; } flint-3.1.3/src/fmpz_mpoly/init.c000066400000000000000000000026371461254215100167350ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_init(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { /* default to MPOLY_MIN_BITS bits per exponent */ A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = MPOLY_MIN_BITS; } void fmpz_mpoly_init3(fmpz_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(bits, ctx->minfo); /* sanitize alloc input */ alloc = FLINT_MAX(alloc, WORD(0)); if (alloc != 0) { A->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); A->exps = (ulong *) flint_malloc(alloc*N*sizeof(ulong)); } else { A->coeffs = NULL; A->exps = NULL; } A->alloc = alloc; A->length = 0; A->bits = bits; } void fmpz_mpoly_init2(fmpz_mpoly_t A, slong alloc, const fmpz_mpoly_ctx_t ctx) { /* default to MPOLY_MIN_BITS bits per exponent */ fmpz_mpoly_init3(A, alloc, MPOLY_MIN_BITS, ctx); } flint-3.1.3/src/fmpz_mpoly/inlines.c000066400000000000000000000006601461254215100174250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MPOLY_INLINES_C #include "fmpz_mpoly.h" flint-3.1.3/src/fmpz_mpoly/integral.c000066400000000000000000000131721461254215100175730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_integral(fmpz_t s, fmpz * coeff1, ulong * exp1, const fmpz * coeff2, const ulong * exp2, slong len2, slong var, slong bits, const mpoly_ctx_t mctx) { slong i, N; fmpz_t d, g; slong offset; slong shift; ulong * oneexp; TMP_INIT; TMP_START; fmpz_init(d); fmpz_init(g); fmpz_set_ui(s, WORD(1)); N = mpoly_words_per_exp(bits, mctx); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (bits <= FLINT_BITS) { ulong c, mask; mask = (-UWORD(1)) >> (FLINT_BITS - bits); mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, bits, mctx); /* scan once to find required denominator */ for (i = 0; i < len2; i++) { c = (exp2[N*i + offset] >> shift) & mask; fmpz_set_ui(d, c + 1); fmpz_gcd(g, d, coeff2 + i); fmpz_divexact(d, d, g); fmpz_lcm(s, s, d); } /* then scan again to compute the terms */ /* x^c -> x^(c+1)/(c+1) */ for (i = 0; i < len2; i++) { c = (exp2[N*i + offset] >> shift) & mask; mpoly_monomial_add(exp1 + N*i, exp2 + N*i, oneexp, N); fmpz_set_ui(d, c + 1); fmpz_mul(g, coeff2 + i, s); fmpz_mul(coeff1 + i, coeff2 + i, g); fmpz_divexact(coeff1 + i, g, d); } } else { fmpz_t c; fmpz_init(c); offset = mpoly_gen_monomial_offset_mp(oneexp, var, bits, mctx); /* scan once to find required denominator */ for (i = 0; i < len2; i++) { fmpz_set_ui_array(c, exp2 + N*i + offset, bits/FLINT_BITS); fmpz_add_ui(d, c, 1); fmpz_gcd(g, d, coeff2 + i); fmpz_divexact(d, d, g); fmpz_lcm(s, s, d); } /* then scan again to compute the terms */ /* x^c -> x^(c+1)/(c+1) */ for (i = 0; i < len2; i++) { fmpz_set_ui_array(c, exp2 + N*i + offset, bits/FLINT_BITS); mpoly_monomial_add_mp(exp1 + N*i, exp2 + N*i, oneexp, N); fmpz_add_ui(d, c, 1); fmpz_mul(g, coeff2 + i, s); fmpz_mul(coeff1 + i, coeff2 + i, g); fmpz_divexact(coeff1 + i, g, d); } fmpz_clear(c); } fmpz_clear(g); fmpz_clear(d); TMP_END; return len2; } void fmpz_mpoly_integral(fmpz_mpoly_t poly1, fmpz_t scale, const fmpz_mpoly_t poly2, slong var, const fmpz_mpoly_ctx_t ctx) { slong i, len1, exp_bits; ulong * exp2 = poly2->exps; fmpz * gen_fields, * max_fields; int free2 = 0; TMP_INIT; TMP_START; /* compute bits required to represent result */ gen_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(gen_fields + i); fmpz_init(max_fields + i); } mpoly_gen_fields_fmpz(gen_fields, var, ctx->minfo); mpoly_max_fields_fmpz(max_fields, poly2->exps, poly2->length, poly2->bits, ctx->minfo); _fmpz_vec_add(max_fields, max_fields, gen_fields, ctx->minfo->nfields); exp_bits = _fmpz_vec_max_bits(max_fields, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = FLINT_MAX(exp_bits, poly2->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(gen_fields + i); fmpz_clear(max_fields + i); } /* ensure input exponents are packed into same sized fields as output */ if (exp_bits > poly2->bits) { slong N = mpoly_words_per_exp(exp_bits, ctx->minfo); free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } /* deal with aliasing and do integration */ if (poly1 == poly2) { fmpz_mpoly_t temp; fmpz_mpoly_init2(temp, poly2->length, ctx); fmpz_mpoly_fit_bits(temp, exp_bits, ctx); temp->bits = exp_bits; len1 = _fmpz_mpoly_integral(scale, temp->coeffs, temp->exps, poly2->coeffs, exp2, poly2->length, var, exp_bits, ctx->minfo); _fmpz_mpoly_set_length(temp, len1, ctx); fmpz_mpoly_swap(temp, poly1, ctx); fmpz_mpoly_clear(temp, ctx); } else { fmpz_mpoly_fit_length(poly1, poly2->length, ctx); fmpz_mpoly_fit_bits(poly1, exp_bits, ctx); poly1->bits = exp_bits; len1 = _fmpz_mpoly_integral(scale, poly1->coeffs, poly1->exps, poly2->coeffs, exp2, poly2->length, var, exp_bits, ctx->minfo); _fmpz_mpoly_set_length(poly1, len1, ctx); } if (free2) { flint_free(exp2); } TMP_END; } flint-3.1.3/src/fmpz_mpoly/io.c000066400000000000000000000162201461254215100163720ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* printing *******************************************************************/ int _fmpz_mpoly_fprint_pretty(FILE * file, const fmpz * poly, const ulong * exps, slong len, const char ** x_in, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, j, N; fmpz * exponents; int r, first; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { r = fputc('0', file); r = (r != EOF) ? 1 : EOF; return r; } N = mpoly_words_per_exp(bits, mctx); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(mctx->nvars*sizeof(char *)); for (i = 0; i < mctx->nvars; i++) { x[i] = (char *) TMP_ALLOC(22*sizeof(char)); flint_sprintf(x[i], "x%wd", i + 1); } } exponents = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(exponents + i); r = 1; for (i = 0; r > 0 && i < len; i++) { if (fmpz_sgn(poly + i) >= 0 && i != 0) { r = fputc('+', file); r = (r != EOF) ? 1 : EOF; } if (poly[i] == WORD(-1)) { r = fputc('-', file); r = (r != EOF) ? 1 : EOF; } if (r > 0 && poly[i] != WORD(1) && poly[i] != WORD(-1)) r = fmpz_fprint(file, poly + i); if (r > 0) mpoly_get_monomial_ffmpz(exponents, exps + N*i, bits, mctx); first = 1; for (j = 0; r > 0 && j < mctx->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, WORD(1)); if (cmp > 0) { if (!first || (poly[i] != WORD(1) && poly[i] != WORD(-1))) { r = fputc('*', file); r = (r != EOF) ? 1 : EOF; } if (r > 0) r = flint_fprintf(file, "%s^", x[j]); if (r > 0) r = fmpz_fprint(file, exponents + j); first = 0; } else if (cmp == 0) { if (!first || (poly[i] != WORD(1) && poly[i] != WORD(-1))) { r = fputc('*', file); r = (r != EOF) ? 1 : EOF; } if (r > 0) r = flint_fprintf(file, "%s", x[j]); first = 0; } } if (r > 0 && mpoly_monomial_is_zero(exps + N*i, N) && (poly[i] == WORD(1) || poly[i] == WORD(-1))) { r = flint_fprintf(file, "1"); } } for (i = 0; i < mctx->nvars; i++) fmpz_clear(exponents + i); TMP_END; return r; } int fmpz_mpoly_fprint_pretty(FILE * file, const fmpz_mpoly_t poly, const char ** x, const fmpz_mpoly_ctx_t ctx) { return _fmpz_mpoly_fprint_pretty(file, poly->coeffs, poly->exps, poly->length, x, poly->bits, ctx->minfo); } int _fmpz_mpoly_print_pretty(const fmpz * poly, const ulong * exps, slong len, const char ** x, slong bits, const mpoly_ctx_t mctx) { return _fmpz_mpoly_fprint_pretty(stdout, poly, exps, len, x, bits, mctx); } int fmpz_mpoly_print_pretty(const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_fprint_pretty(stdout, A, x, ctx); } /* debugging ******************************************************************/ /* test that r is a valid remainder upon division by g this means that if c*x^a is a term of r and x^a is divisible by the leading monomial of g, then |c| < |leading coefficient of g| */ void fmpz_mpoly_remainder_test(const fmpz_mpoly_t r, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx) { slong i, N, bits; ulong mask = 0; ulong * rexp, * gexp; bits = FLINT_MAX(r->bits, g->bits); N = mpoly_words_per_exp(bits, ctx->minfo); if (g->length == 0 ) flint_throw(FLINT_ERROR, "Zero denominator in remainder test"); if (r->length == 0 ) return; rexp = (ulong *) flint_malloc(N*r->length*sizeof(ulong)); gexp = (ulong *) flint_malloc(N*1 *sizeof(ulong)); mpoly_repack_monomials(rexp, bits, r->exps, r->bits, r->length, ctx->minfo); mpoly_repack_monomials(gexp, bits, g->exps, g->bits, 1, ctx->minfo); if (bits <= FLINT_BITS) mask = mpoly_overflow_mask_sp(bits); else mask = 0; for (i = 0; i < r->length; i++) { int divides; if (bits <= FLINT_BITS) divides = mpoly_monomial_divides_test(rexp + i*N, gexp + 0*N, N, mask); else divides = mpoly_monomial_divides_mp_test(rexp + i*N, gexp + 0*N, N, bits); if (divides && fmpz_cmpabs(g->coeffs + 0, r->coeffs + i) <= 0) { flint_throw(FLINT_ERROR, "fmpz_mpoly_remainder_test FAILED i = %wd\n" "rem %s\n\n" "den %s\n\n", i, fmpz_mpoly_get_str_pretty(r, NULL, ctx), fmpz_mpoly_get_str_pretty(g, NULL, ctx)); } } flint_free(rexp); flint_free(gexp); } /* test that r is a valid remainder upon division by g over Q this means that no term of r is divisible by lt(g) */ void fmpz_mpoly_remainder_strongtest(const fmpz_mpoly_t r, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx) { slong i, N, bits; ulong mask = 0; ulong * rexp, * gexp; bits = FLINT_MAX(r->bits, g->bits); N = mpoly_words_per_exp(bits, ctx->minfo); if (g->length == 0 ) flint_throw(FLINT_ERROR, "Zero denominator in remainder test"); if (r->length == 0 ) return; rexp = (ulong *) flint_malloc(N*r->length*sizeof(ulong)); gexp = (ulong *) flint_malloc(N*1 *sizeof(ulong)); mpoly_repack_monomials(rexp, bits, r->exps, r->bits, r->length, ctx->minfo); mpoly_repack_monomials(gexp, bits, g->exps, g->bits, 1, ctx->minfo); if (bits <= FLINT_BITS) mask = mpoly_overflow_mask_sp(bits); else mask = 0; for (i = 0; i < r->length; i++) { int divides; if (bits <= FLINT_BITS) divides = mpoly_monomial_divides_test(rexp + i*N, gexp + 0*N, N, mask); else divides = mpoly_monomial_divides_mp_test(rexp + i*N, gexp + 0*N, N, bits); if (divides) { flint_throw(FLINT_ERROR, "fmpz_mpoly_remainder_strongtest FAILED i = %wd\n" "rem %s\n\n" "den %s\n\n", i, fmpz_mpoly_get_str_pretty(r, NULL, ctx), fmpz_mpoly_get_str_pretty(g, NULL, ctx)); } } flint_free(rexp); flint_free(gexp); } flint-3.1.3/src/fmpz_mpoly/is_canonical.c000066400000000000000000000034661461254215100204150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_is_canonical(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { if (fmpz_is_zero(A->coeffs + i)) return 0; } return 1; } void fmpz_mpoly_assert_canonical(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents out of order"); for (i = 0; i < A->length; i++) { if (fmpz_is_zero(A->coeffs + i)) flint_throw(FLINT_ERROR, "Polynomial has a zero coefficient"); } for (i = A->length; i < A->alloc; i++) { if (COEFF_IS_MPZ(A->coeffs[i])) flint_throw(FLINT_ERROR, "Polynomial has a big coeff past length"); } } flint-3.1.3/src/fmpz_mpoly/is_fmpz.c000066400000000000000000000013571461254215100174370ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_is_fmpz(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong N; if (A->length > WORD(1)) return 0; if (A->length == WORD(0)) return 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } flint-3.1.3/src/fmpz_mpoly/is_gen.c000066400000000000000000000014031461254215100172240ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_is_gen(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { if (A->length != WORD(1)) return 0; if (!fmpz_is_one(A->coeffs + 0)) return 0; return mpoly_is_gen(A->exps, var, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/lead_coeff_vars.c000066400000000000000000000036111461254215100210650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* leading coefficient wrt gen(0), ..., gen(num_vars-1) c will be returned with c->bits == A->bits */ void fmpz_mpolyl_lead_coeff( fmpz_mpoly_t c, const fmpz_mpoly_t A, slong num_vars, const fmpz_mpoly_ctx_t ctx) { slong i, j, off, shift; ulong mask, first_mask; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; ulong * cexps; slong Alen = A->length; FLINT_ASSERT(c != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) << shift; i = 0; first_mask = (Aexps + N*i)[off] & mask; for (i = 1; i < Alen; i++) { if (((Aexps + N*i)[off] & mask) != first_mask) goto break_outer; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto break_outer; } break_outer: fmpz_mpoly_fit_length_reset_bits(c, i, A->bits, ctx); c->length = i; cexps = c->exps; _fmpz_vec_set(c->coeffs, A->coeffs, c->length); mask = ~mask; for (i = 0; i < c->length; i++) { for (j = 0; j < off; j++) (cexps + N*i)[j] = (Aexps + N*i)[j]; (cexps + N*i)[off] = mask & (Aexps + N*i)[off]; for (j = off + 1; j < N; j++) (cexps + N*i)[j] = 0; } } flint-3.1.3/src/fmpz_mpoly/misc.c000066400000000000000000000026431461254215100167220ustar00rootroot00000000000000/* Copyright (C) 2016-2017 William Hart Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void _fmpz_mpoly_sub_uiuiui_fmpz(ulong * c, const fmpz_t d) { fmpz fc = *d; if (!COEFF_IS_MPZ(fc)) { ulong f0, f1, f2; f0 = fc; f1 = f2 = FLINT_SIGN_EXT(f0); sub_dddmmmsss(c[2], c[1], c[0], c[2], c[1], c[0], f2, f1, f0); } else { slong size = fmpz_size(d); __mpz_struct * m = COEFF_TO_PTR(fc); if (fmpz_sgn(d) < 0) mpn_add(c, c, 3, m->_mp_d, size); else mpn_sub(c, c, 3, m->_mp_d, size); } } void _fmpz_mpoly_add_uiuiui_fmpz(ulong * c, const fmpz_t d) { fmpz fc = *d; if (!COEFF_IS_MPZ(fc)) { ulong f0, f1, f2; f0 = fc; f1 = f2 = FLINT_SIGN_EXT(f0); add_sssaaaaaa(c[2], c[1], c[0], c[2], c[1], c[0], f2, f1, f0); } else { slong size = fmpz_size(d); __mpz_struct * m = COEFF_TO_PTR(fc); if (fmpz_sgn(d) < 0) mpn_sub(c, c, 3, m->_mp_d, size); else mpn_add(c, c, 3, m->_mp_d, size); } } flint-3.1.3/src/fmpz_mpoly/mpolyd.c000066400000000000000000000146221461254215100172730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" #if 0 void fmpz_mpolyd_swap(fmpz_mpolyd_t A, fmpz_mpolyd_t B) { fmpz_mpolyd_struct t = *A; *A = *B; *B = t; } void fmpz_mpolyd_ctx_init(fmpz_mpolyd_ctx_t dctx, slong nvars) { slong i; dctx->nvars = nvars; dctx->perm = (slong *) flint_malloc(nvars*sizeof(slong)); for (i = 0; i < nvars; i++) { dctx->perm[i] = i; } } int fmpz_mpolyd_ctx_init_version1(fmpz_mpolyd_ctx_t dctx, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int success = 0; slong i, j, degb_prod; slong * Aexps, * Bexps, * deg_bounds; slong nvars = ctx->minfo->nvars; slong * perm = dctx->perm; TMP_INIT; TMP_START; Aexps = (slong *) TMP_ALLOC(nvars*sizeof(slong)); Bexps = (slong *) TMP_ALLOC(nvars*sizeof(slong)); if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) goto cleanup; fmpz_mpoly_degrees_si(Aexps, A, ctx); fmpz_mpoly_degrees_si(Bexps, B, ctx); deg_bounds = (slong *) TMP_ALLOC(nvars*sizeof(slong)); for (i = 0; i < nvars; i++) { dctx->perm[i] = i; } degb_prod = 1; for (i = 0; i < nvars; i++) { ulong hi; deg_bounds[i] = FLINT_MAX(Aexps[i] + 1, Bexps[i] + 1); umul_ppmm(hi, degb_prod, degb_prod, deg_bounds[i]); if (hi != WORD(0) || degb_prod < 0) goto cleanup; } success = 1; for (i = 1; i < nvars; i++) { for (j = i; (j > 0) && (deg_bounds[j-1] < deg_bounds[j-0]); j--) { slong t1, t2; t1 = deg_bounds[j-1]; t2 = deg_bounds[j-0]; deg_bounds[j-0] = t1; deg_bounds[j-1] = t2; t1 = perm[j-1]; t2 = perm[j-0]; perm[j-0] = t1; perm[j-1] = t2; } } cleanup: TMP_END; return success; } void fmpz_mpolyd_ctx_clear(fmpz_mpolyd_ctx_t dctx) { flint_free(dctx->perm); } void fmpz_mpolyd_zero(fmpz_mpolyd_t poly) { slong i; for (i = 0; i < poly->nvars; i++) { poly->deg_bounds[i] = WORD(1); } poly->coeffs[0] = UWORD(0); } void fmpz_mpolyd_set_fmpz(fmpz_mpolyd_t poly, fmpz_t num) { slong i; for (i = 0; i < poly->nvars; i++) { poly->deg_bounds[i] = WORD(1); } fmpz_set(poly->coeffs + 0, num); } void fmpz_mpolyd_set_nvars(fmpz_mpolyd_t poly, slong nvars) { poly->nvars = nvars; if (poly->degb_alloc < nvars) { poly->deg_bounds = (slong *) flint_realloc(poly->deg_bounds, nvars*sizeof(slong)); poly->degb_alloc = nvars; } } void fmpz_mpoly_convert_to_fmpz_mpolyd( fmpz_mpolyd_t poly1, const fmpz_mpolyd_ctx_t dctx, const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) { slong degb_prod; slong i, j, N; slong * exps; const slong * perm = dctx->perm; slong nvars = ctx->minfo->nvars; TMP_INIT; fmpz_mpolyd_set_nvars(poly1, ctx->minfo->nvars); FLINT_ASSERT(poly2->bits <= FLINT_BITS); if (poly2->length == 0) { fmpz_mpolyd_zero(poly1); return; } TMP_START; exps = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); fmpz_mpoly_degrees_si(exps, poly2, ctx); degb_prod = WORD(1); for (i = 0; i < nvars; i++) { poly1->deg_bounds[i] = exps[perm[i]] + 1; degb_prod *= poly1->deg_bounds[i]; } fmpz_mpolyd_fit_length(poly1, degb_prod); for (i = 0; i < degb_prod; i++) { fmpz_zero(poly1->coeffs + i); } N = mpoly_words_per_exp(poly2->bits, ctx->minfo); for (i = 0; i < poly2->length; i++) { slong off = 0; mpoly_get_monomial_ui((ulong *)exps, poly2->exps + N*i, poly2->bits, ctx->minfo); for (j = 0; j < nvars; j++) { off = exps[perm[j]] + poly1->deg_bounds[j]*off; } fmpz_set(poly1->coeffs + off, poly2->coeffs + i); } TMP_END; } void fmpz_mpoly_convert_from_fmpz_mpolyd( fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, const fmpz_mpolyd_t B, const fmpz_mpolyd_ctx_t dctx) { slong i, j; slong degb_prod; slong * perm = dctx->perm; ulong * exps; TMP_INIT; FLINT_ASSERT(ctx->minfo->nvars == B->nvars); degb_prod = WORD(1); for (j = 0; j < B->nvars; j++) { degb_prod *= B->deg_bounds[j]; } TMP_START; exps = (ulong *) TMP_ALLOC(B->nvars*sizeof(ulong)); fmpz_mpoly_zero(A, ctx); for (i = 0; i < degb_prod; i++) { ulong k = i; if (fmpz_is_zero(B->coeffs + i)) continue; for (j = B->nvars - 1; j >= 0; j--) { ulong m = B->deg_bounds[j]; ulong e = k % m; k = k / m; exps[perm[j]] = e; } FLINT_ASSERT(k == 0); fmpz_mpoly_set_coeff_fmpz_ui(A, B->coeffs + i, exps, ctx); } TMP_END; } #endif void fmpz_mpolyd_init(fmpz_mpolyd_t poly, slong nvars) { slong i; poly->nvars = nvars; poly->degb_alloc = nvars; poly->deg_bounds = (slong *) flint_malloc(poly->degb_alloc*sizeof(slong)); for (i = 0; i < nvars; i++) { poly->deg_bounds[i] = WORD(1); } poly->coeff_alloc = WORD(16); poly->coeffs = (fmpz *) flint_malloc(poly->coeff_alloc*sizeof(fmpz)); for (i = 0; i < poly->coeff_alloc; i++) { fmpz_init(poly->coeffs + i); } } void fmpz_mpolyd_fit_length(fmpz_mpolyd_t poly, slong len) { if (poly->coeff_alloc < len) { slong i; poly->coeffs = (fmpz *) flint_realloc(poly->coeffs, len*sizeof(fmpz)); for (i = poly->coeff_alloc; i < len; i++) { fmpz_init(poly->coeffs + i); } poly->coeff_alloc = len; } } void fmpz_mpolyd_clear(fmpz_mpolyd_t poly) { slong i; for (i = 0; i < poly->coeff_alloc; i++) { fmpz_clear(poly->coeffs + i); } flint_free(poly->deg_bounds); flint_free(poly->coeffs); poly->deg_bounds = NULL; poly->coeffs = NULL; } flint-3.1.3/src/fmpz_mpoly/mul.c000066400000000000000000000244431461254215100165660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "long_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" static int _try_dense(int try_array, slong * Bdegs, slong * Cdegs, slong Blen, slong Clen, slong nvars) { const int max_bit_size = FLINT_MIN(FLINT_BITS/3 + 16, FLINT_BITS - 3); slong i, product_count, dense_size; ulong hi; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); dense_size = WORD(1); for (i = 0; i < nvars; i++) { umul_ppmm(hi, dense_size, dense_size, Bdegs[i] + Cdegs[i] + 1); if (hi != 0 || dense_size <= 0) return 0; } if (dense_size >= WORD(1) << max_bit_size) return 0; umul_ppmm(hi, product_count, Blen, Clen); if (hi != 0 || product_count < 0) return 1; /* Assume that the running time of the dense method is linear in "dense_size" and that the running time of the array|heap method is linear in "product_count". Assume further that the array method is 4x faster than heap. */ if (try_array) return dense_size < product_count/128; else return dense_size < product_count/32; } static int _try_array_LEX(slong * Bdegs, slong * Cdegs, slong Blen, slong Clen, slong nvars) { slong i, dense_size; ulong hi; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); /* accept array method if the array is probably at least 10% full */ dense_size = WORD(1); for (i = 0; i < nvars; i++) { umul_ppmm(hi, dense_size, dense_size, Bdegs[i] + Cdegs[i] + 1); if (hi != 0 || dense_size <= 0) return 0; } return dense_size <= WORD(50000000) && dense_size/Blen/Clen < WORD(10); } static int _try_array_DEG(slong Btotaldeg, slong Ctotaldeg, slong Blen, slong Clen, slong nvars) { slong i, dense_size, total_degree; ulong hi; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); total_degree = Btotaldeg + Btotaldeg; if (total_degree <= 0) return 0; /* the relevant portion of the array has approx size d^nvars/nvars!*/ dense_size = WORD(1); for (i = 0; i < nvars; i++) { umul_ppmm(hi, dense_size, dense_size, total_degree); if (hi != WORD(0) || dense_size < 0) return 0; } for (i = 0; i < nvars; i++) { dense_size /= i + 1; } return dense_size <= WORD(5000000) && dense_size/Blen/Clen < WORD(10); } /* !!! this function DOES need to change with new orderings */ static int _try_dense_univar( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i; ulong maskB = (-UWORD(1)) >> (FLINT_BITS - B->bits); ulong maskC = (-UWORD(1)) >> (FLINT_BITS - C->bits); slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong NC = mpoly_words_per_exp_sp(C->bits, ctx->minfo); slong Blen = B->length; slong Clen = C->length; slong BClen; const ulong * Bexps = B->exps; const ulong * Cexps = C->exps; fmpz * Acoeffs, * Bcoeffs, * Ccoeffs; slong Adeg, Bdeg, Cdeg; TMP_INIT; /* the variable power is stored at offset 0 */ Bdeg = Bexps[NB*0 + 0] & maskB; Cdeg = Cexps[NC*0 + 0] & maskC; if (z_mul_checked(&BClen, Blen, Clen) || z_add_checked(&Adeg, Bdeg, Cdeg)) return 0; if (Adeg > WORD_MAX/FLINT_BITS) return 0; if (Adeg > BClen) return 0; { slong Bcoeffbits = _fmpz_vec_max_bits(B->coeffs, Blen); slong Ccoeffbits = _fmpz_vec_max_bits(C->coeffs, Clen); slong t = FLINT_ABS(Bcoeffbits) + FLINT_ABS(Ccoeffbits); if (t > FLINT_BITS && Adeg > BClen/4) return 0; } TMP_START; Acoeffs = TMP_ARRAY_ALLOC(Adeg + 1 + Bdeg + 1 + Cdeg + 1, fmpz); Bcoeffs = Acoeffs + Adeg + 1; Ccoeffs = Bcoeffs + Bdeg + 1; /* we own the fmpz's in Acoeffs */ for (i = 0; i < Adeg + 1; i++) fmpz_init(Acoeffs + i); if (A != B && A != C) { for (i = FLINT_MIN(A->length - 1, Adeg); i >= 0; i--) fmpz_swap(Acoeffs + i, A->coeffs + i); } /* Bcoeffs and Ccoeffs are shallow copies */ for (i = 0; i < Bdeg + 1 + Cdeg + 1; i++) Bcoeffs[i] = 0; for (i = 0; i < Blen; i++) Bcoeffs[Bexps[NB*i + 0] & maskB] = B->coeffs[i]; for (i = 0; i < Clen; i++) Ccoeffs[Cexps[NC*i + 0] & maskC] = C->coeffs[i]; if (Bdeg >= Cdeg) _fmpz_poly_mul(Acoeffs, Bcoeffs, Bdeg + 1, Ccoeffs, Cdeg + 1); else _fmpz_poly_mul(Acoeffs, Ccoeffs, Cdeg + 1, Bcoeffs, Bdeg + 1); /* Acoeffs cleared */ _fmpz_mpoly_set_fmpz_poly_one_var(A, FLINT_MAX(B->bits, C->bits), Acoeffs, Adeg, ctx); TMP_END; return 1; } void fmpz_mpoly_mul( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i; slong nvars = ctx->minfo->nvars; int success, try_array; slong * Bdegs, * Cdegs; fmpz * maxBfields, * maxCfields; thread_pool_handle * handles; slong num_handles; slong min_length, max_length; slong thread_limit; TMP_INIT; if (B->length < 1 || C->length < 1) { fmpz_mpoly_zero(A, ctx); return; } else if (B->length == 1) { fmpz_mpoly_mul_monomial(A, C, B, ctx); return; } else if (C->length == 1) { fmpz_mpoly_mul_monomial(A, B, C, ctx); return; } FLINT_ASSERT(nvars > 0); if (nvars == 1 && B->bits <= FLINT_BITS && C->bits <= FLINT_BITS) { if (_try_dense_univar(A, B, C, ctx)) return; } TMP_START; /* All methods require a linear scan of the exponents. Do it here once and for all. */ maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); min_length = FLINT_MIN(B->length, C->length); max_length = FLINT_MAX(B->length, C->length); thread_limit = min_length/512; /* If one polynomial is tiny or if both polynomials are small, heap method with operational complexity O(B->length*C->length) is fine. */ if (min_length < 20 || max_length < 50) { _fmpz_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); goto cleanup; } /* If either polynomial has multi-word fields, only heap will do. */ if (B->bits > FLINT_BITS || C->bits > FLINT_BITS) { num_handles = flint_request_threads(&handles, thread_limit); goto do_heap; } /* The multiplication is not trivial and each packed field fits into one word. In particular, the degrees must fit an slong. */ Bdegs = (slong *) TMP_ALLOC(nvars*sizeof(slong)); Cdegs = (slong *) TMP_ALLOC(nvars*sizeof(slong)); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Bdegs, maxBfields, ctx->minfo); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Cdegs, maxCfields, ctx->minfo); /* See if array method is applicable. If so, it should be about 4x faster than heap. */ try_array = 0; if (nvars > WORD(1) && nvars < WORD(8) && 1 == mpoly_words_per_exp(B->bits, ctx->minfo) && 1 == mpoly_words_per_exp(C->bits, ctx->minfo)) { if (ctx->minfo->ord == ORD_LEX) { try_array = _try_array_LEX(Bdegs, Cdegs, B->length, C->length, nvars); } else if (ctx->minfo->ord == ORD_DEGLEX || ctx->minfo->ord == ORD_DEGREVLEX) { slong Btdeg = fmpz_get_si(maxBfields + nvars); slong Ctdeg = fmpz_get_si(maxCfields + nvars); try_array = _try_array_DEG(Btdeg, Ctdeg, B->length, C->length, nvars); } } success = 0; if (_try_dense(try_array, Bdegs, Cdegs, B->length, C->length, nvars)) { success = _fmpz_mpoly_mul_dense(A, B, maxBfields, C, maxCfields, ctx); if (success) { goto cleanup; } } num_handles = flint_request_threads(&handles, thread_limit); if (!try_array) { goto do_heap; } if (ctx->minfo->ord == ORD_LEX) { success = (num_handles > 0) ? _fmpz_mpoly_mul_array_threaded_pool_LEX( A, B, maxBfields, C, maxCfields, ctx, handles, num_handles) : _fmpz_mpoly_mul_array_LEX( A, B, maxBfields, C, maxCfields, ctx); } else if (ctx->minfo->ord == ORD_DEGLEX || ctx->minfo->ord == ORD_DEGREVLEX) { success = (num_handles > 0) ? _fmpz_mpoly_mul_array_threaded_pool_DEG( A, B, maxBfields, C, maxCfields, ctx, handles, num_handles) : _fmpz_mpoly_mul_array_DEG( A, B, maxBfields, C, maxCfields, ctx); } if (success) { goto cleanup_threads; } do_heap: if (num_handles > 0) { _fmpz_mpoly_mul_heap_threaded_pool_maxfields(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); } else { _fmpz_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); } cleanup_threads: flint_give_back_threads(handles, num_handles); cleanup: for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; } flint-3.1.3/src/fmpz_mpoly/mul_array.c000066400000000000000000001464451461254215100177730ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* Currently we do not -funroll-loops by default in the fmpz_mpoly module, but it is worthwhile for the basic loops here. */ #pragma GCC push_options #pragma GCC optimize("-funroll-loops") /* NOTE: this file is dirty - it assumes that a zero fmpz is zero */ /* improve locality */ #define BLOCK 128 #define MAX_ARRAY_SIZE (WORD(300000)) #define MAX_LEX_SIZE (WORD(300)) /* Addmul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into one word per coefficient. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_addmul_array1_slong1(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong * c2; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + (slong) exp2[i]; if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c2[(slong) exp3[j]] += poly2[i]*poly3[j]; } } } } } } /* Addmul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into three words per coefficient. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_addmul_array1_slong(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong cy; ulong p[2]; /* for products of coefficients */ ulong * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + 3*((slong) exp2[i]); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + 3*((slong) exp3[j]); smul_ppmm(p[1], p[0], poly2[i], poly3[j]); add_sssaaaaaa(cy, c[1], c[0], 0, c[1], c[0], 0, p[1], p[0]); c[2] += (0 <= (slong) p[1]) ? cy : cy - 1; } } } } } } /* Addmul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is assumed to fit into two words per coefficient. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_addmul_array1_slong2(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong p[2]; /* for products of coefficients */ ulong * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { /* Hack: both the (slong) cast and writing as a shift by 1 instead of a multiply by 2 are needed to get GCC to generate good code on Zen3. Check build/fmpz_mpoly/profile/p-mul 1 dense 30 20 before changing this. */ c2 = poly1 + (((slong) exp2[i]) << 1); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { /* Hack. */ c = c2 + (((slong) exp3[j]) << 1); smul_ppmm(p[1], p[0], poly2[i], poly3[j]); add_ssaaaa(c[1], c[0], c[1], c[0], p[1], p[0]); } } } } } } #pragma GCC pop_options /* Addmul into a dense array poly1, given polys with coefficients fitting into a word, and exponents tightly packed with mixed bases equal to the largest exponent for each variable, e.g. the input polys have exponents of the form a_0 + a_1*b1 + a_2*b_2*b_2 + .... where b_0, b_1, b_2, etc, are the bases, which are equal to the largest possible exponent for each of the respective variables in the exponent. These exponents are use as array indices in the output polynomial. The output poly is unrestricted, having multiprecision coefficients. The input polynomials are broken into blocks to improve cache efficiency. */ void _fmpz_mpoly_addmul_array1_fmpz(fmpz * poly1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; fmpz * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + (slong) exp2[i]; if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + (slong) exp3[j]; fmpz_addmul(c, poly2 + i, poly3 + j); } } } } } } /* Convert a polynomial in dense array format to an fmpz_mpoly with the given number of bits per exponent field. This function destroys poly2 and starts writing poly1 at index k. The function may reallocate its output. The array "mults" is a list of bases uses in encoding the array indices from the exponents. The value num is the number of fields in the output exponent vectors, also the number of entries in mults. Exponents are assumed to be packed into a single word. The array, poly2 is assumed to have three words per coefficient. */ slong _fmpz_mpoly_from_ulong_array(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k) { slong i, j; ulong exp; ulong * c; slong * prods; fmpz * p1 = *poly1; ulong * e1 = *exp1; TMP_INIT; TMP_START; prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods[0] = 1; for (i = 1; i <= num; i++) prods[i] = mults[i - 1]*prods[i - 1]; /* for each coeff in array */ for (i = prods[num] - 1; i >= 0; i--) { c = poly2 + i*3; /* if coeff is nonzero */ if (c[0] != 0 || c[1] != 0 || c[2] != 0) { _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, 1); exp = 0; /* compute exponent from index */ for (j = 0; j < num; j++) exp += (i % prods[j + 1])/prods[j] << bits*j; /* shift exponent vector into place */ e1[k] = exp; /* set coefficient */ fmpz_set_signed_uiuiui(p1 + k, c[2], c[1], c[0]); k++; } } *poly1 = p1; *exp1 = e1; TMP_END; return k; } /* Convert a polynomial in dense array format to an fmpz_mpoly with the given number of bits per exponent field. This function destroys poly2 and starts writing poly1 at index k. The function may reallocate its output. The array "mults" is a list of bases uses in encoding the array indices from the exponents. The value num is the number of fields in the output exponent vectors, also the number of entries in mults. Exponents are assumed to be packed into a single word. The array, poly2 is assumed to have two words per coefficient. */ slong _fmpz_mpoly_from_ulong_array2(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k) { slong i, j; ulong exp; ulong * c; slong * prods; fmpz * p1 = *poly1; ulong * e1 = *exp1; TMP_INIT; TMP_START; prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods[0] = 1; for (i = 1; i <= num; i++) prods[i] = mults[i - 1]*prods[i - 1]; /* for each coeff in array */ for (i = prods[num] - 1; i >= 0; i--) { c = poly2 + i*2; /* if coeff is nonzero */ if (c[0] != 0 || c[1] != 0) { _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, 1); exp = 0; /* compute exponent from index */ for (j = 0; j < num; j++) exp += (i % prods[j + 1])/prods[j] << bits*j; /* shift exponent vector into place */ e1[k] = exp; /* set coefficient */ fmpz_set_signed_uiui(p1 + k, c[1], c[0]); k++; } } *poly1 = p1; *exp1 = e1; TMP_END; return k; } /* Convert a polynomial in dense array format to an fmpz_mpoly with the given number of bits per exponent field. This function destroys poly2 and starts writing poly1 at index k. The function may reallocate its output. The array "mults" is a list of bases uses in encoding the array indices from the exponents. The value num is the number of fields in the output exponent vectors, also the number of entries in mults. Exponents are assumed to be packed into a single word. The array, poly2 is assumed to have three words per coefficient. */ slong _fmpz_mpoly_from_ulong_array1(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k) { slong i, j; ulong exp; ulong * c; slong * prods; fmpz * p1 = *poly1; ulong * e1 = *exp1; TMP_INIT; TMP_START; prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods[0] = 1; for (i = 1; i <= num; i++) prods[i] = mults[i - 1]*prods[i - 1]; /* for each coeff in array */ for (i = prods[num] - 1; i >= 0; i--) { c = poly2 + i; /* if coeff is nonzero */ if (c[0] != 0) { _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, 1); exp = 0; /* compute exponent from index */ for (j = 0; j < num; j++) exp += (i % prods[j + 1])/prods[j] << bits*j; /* shift exponent vector into place */ e1[k] = exp; /* set coefficient */ fmpz_set_si(p1 + k, c[0]); k++; } } *poly1 = p1; *exp1 = e1; TMP_END; return k; } /* Convert a polynomial in dense array format to an fmpz_mpoly with the given number of bits per exponent field. This function destroys poly2 and starts writing poly1 at index k. The function may reallocate its output. The array "mults" is a list of bases uses in encoding the array indices from the exponents. The value num is the number of fields in the output exponent vectors, also the number of entries in mults. Exponents are assumed to be packed into a single word. The array, poly2 has no restrictions with respect to coefficients; they may be multiprecision integers. */ slong _fmpz_mpoly_from_fmpz_array(fmpz ** poly1, ulong ** exp1, slong * alloc, fmpz * poly2, const slong * mults, slong num, slong bits, slong k) { slong i, j; ulong exp; fmpz * c; slong * prods; fmpz * p1 = *poly1; ulong * e1 = *exp1; TMP_INIT; TMP_START; prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); /* compute products 1, b0, b0*b1, b0*b1*b2 ... from list of bases b0, b1, b2, ... */ prods[0] = 1; for (i = 1; i <= num; i++) prods[i] = mults[i - 1]*prods[i - 1]; /* for each coeff in array */ for (i = prods[num] - 1; i >= 0; i--) { c = poly2 + i; /* if coeff is nonzero */ if (!fmpz_is_zero(c)) { _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, 1); exp = 0; /* compute exponent from index */ for (j = 0; j < num; j++) exp += (i % prods[j + 1])/prods[j] << bits*j; /* shift exponent vector into place */ e1[k] = exp; /* set coefficient */ fmpz_set(p1 + k, poly2 + i); k++; } } *poly1 = p1; *exp1 = e1; TMP_END; return k; } /**************************************************** LEX ****************************************************/ #define LEX_UNPACK_MACRO(fxn_name, coeff_decl, nonzero_test, swapper) \ slong fxn_name(fmpz_mpoly_t P, slong Plen, coeff_decl, \ const ulong * mults, slong num, slong array_size, slong top) \ { \ slong off, j; \ slong topmult = num == 0 ? 1 : mults[num - 1]; \ slong lastd = topmult - 1; \ slong reset = array_size/topmult; \ slong counter = reset; \ ulong startexp = (top << (P->bits*num)) + (lastd << (P->bits*(num-1))); \ for (off = array_size - 1; off >= 0; off--) \ { \ if (nonzero_test) \ { \ slong d = off; \ ulong exp = startexp; \ for (j = 0; j + 1 < num; j++) { \ exp += (d % mults[j]) << (P->bits*j); \ d = d / mults[j]; \ } \ _fmpz_mpoly_fit_length(&P->coeffs, &P->exps, &P->alloc, Plen + 1, 1); \ P->exps[Plen] = exp; \ swapper \ Plen++; \ } \ counter--; \ if (counter <= 0) { \ counter = reset; \ lastd--; \ startexp -= UWORD(1) << (P->bits*(num-1)); \ } \ } \ return Plen; \ } /* These four functions will replace _fmpz_mpoly_from_ulong_array, ..., _fmpz_mpoly_from_fmpz_array defined above. WARNING: In order for the coeff_array to be used interchangeably between the small versions and fmpz version, it is necessary that zero is represented as a real zero in the fmpz type. */ LEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm1_LEX, ulong * coeff_array , coeff_array[off] != WORD(0) , fmpz_set_si(P->coeffs + Plen, coeff_array[off]); coeff_array[off] = 0; ) LEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm2_LEX, ulong * coeff_array , (coeff_array[2*off+0] || coeff_array[2*off+1]) != WORD(0) , fmpz_set_signed_uiui(P->coeffs + Plen, coeff_array[2*off+1], coeff_array[2*off+0]); coeff_array[2*off+0] = coeff_array[2*off+1] = 0; ) LEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm3_LEX, ulong * coeff_array , (coeff_array[3*off+0] || coeff_array[3*off+1] || coeff_array[3*off+2]) != WORD(0) , fmpz_set_signed_uiuiui(P->coeffs + Plen, coeff_array[3*off+2], coeff_array[3*off+1], coeff_array[3*off+0]); coeff_array[3*off+0] = coeff_array[3*off+1] = coeff_array[3*off+2] = 0; ) LEX_UNPACK_MACRO( fmpz_mpoly_append_array_fmpz_LEX, fmpz * coeff_array , !fmpz_is_zero(coeff_array + off) , fmpz_swap(P->coeffs + Plen, coeff_array + off); fmpz_zero(coeff_array + off); ) void _fmpz_mpoly_mul_array_chunked_LEX( fmpz_mpoly_t P, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const ulong * mults, const fmpz_mpoly_ctx_t ctx) { slong num = ctx->minfo->nfields - 1; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong Abits, * Asum, * Amax, Bbits, * Bsum, * Bmax; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; int small; TMP_INIT; array_size = 1; for (i = 0; i < num; i++) { array_size *= mults[i]; } /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*num)); Bl = 1 + (slong) (B->exps[0] >> (B->bits*num)); TMP_START; /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC(((Al + 1) + Al + Al + (Bl + 1) + Bl + Bl)*sizeof(slong)); Asum = Amain + Al + 1; Amax = Asum + Al; Bmain = Amax + Al; Bsum = Bmain + Bl + 1; Bmax = Bsum + Bl; Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_LEX(Amain, Apexp, A->exps, Al, A->length, mults, num, A->bits); mpoly_main_variable_split_LEX(Bmain, Bpexp, B->exps, Bl, B->length, mults, num, B->bits); /* work out bit counts for each chunk */ Abits = 0; for (i = 0; i < Al; i++) { _fmpz_vec_sum_max_bits(&Asum[i], &Amax[i], A->coeffs + Amain[i], Amain[i + 1] - Amain[i]); Abits = FLINT_MAX(Abits, Amax[i]); } Bbits = 0; for (j = 0; j < Bl; j++) { _fmpz_vec_sum_max_bits(&Bsum[j], &Bmax[j], B->coeffs + Bmain[j], Bmain[j + 1] - Bmain[j]); Bbits = FLINT_MAX(Bbits, Bmax[j]); } /* whether the output coefficients are "small" */ small = Abits <= (SMALL_FMPZ_BITCOUNT_MAX) && Bbits <= (SMALL_FMPZ_BITCOUNT_MAX); Pl = Al + Bl - 1; Plen = 0; if (small) { ulong * coeff_array = (ulong *) TMP_ALLOC(3*array_size*sizeof(ulong)); for (j = 0; j < 3*array_size; j++) coeff_array[j] = 0; /* for each output chunk */ for (Pi = 0; Pi < Pl; Pi++) { /* compute bound on coeffs of output chunk */ slong number = 0; slong Pbits = 0; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { Pbits = FLINT_MAX(Pbits, FLINT_MIN(Asum[i] + Bmax[j], Amax[i] + Bsum[j])); number++; } } Pbits += FLINT_BIT_COUNT(number) + 1; /* includes one bit for sign */ if (Pbits <= FLINT_BITS) { /* fits into one word */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_slong1(coeff_array, (slong *) A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], (slong *) B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = fmpz_mpoly_append_array_sm1_LEX(P, Plen, coeff_array, mults, num, array_size, Pl - Pi - 1); } else if (Pbits <= 2*FLINT_BITS) { /* fits into two words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_slong2(coeff_array, (slong *) A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], (slong *) B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = fmpz_mpoly_append_array_sm2_LEX(P, Plen, coeff_array, mults, num, array_size, Pl - Pi - 1); } else { /* fits into three word */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_slong(coeff_array, (slong *) A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], (slong *) B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = fmpz_mpoly_append_array_sm3_LEX(P, Plen, coeff_array, mults, num, array_size, Pl - Pi - 1); } } } else { fmpz * coeff_array = (fmpz *) TMP_ALLOC(array_size*sizeof(fmpz)); for (j = 0; j < array_size; j++) fmpz_init(coeff_array + j); /* for each output chunk */ for (Pi = 0; Pi < Pl; Pi++) { /* addmuls for each cross product of chunks */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_fmpz(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = fmpz_mpoly_append_array_fmpz_LEX(P, Plen, coeff_array, mults, num, array_size, Pl - Pi - 1); } } _fmpz_mpoly_set_length(P, Plen, ctx); flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _fmpz_mpoly_mul_array_LEX( fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx) { slong i, exp_bits, array_size; ulong max, * mults; int success; TMP_INIT; FLINT_ASSERT(ctx->minfo->nvars > 0); FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); TMP_START; /* compute maximum exponents for each variable */ mults = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); /* the field of index n-1 is the one that will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max = mults[i]; if (((slong) mults[i]) <= 0 || mults[i] > MAX_LEX_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...0, contribute to the array size */ array_size = WORD(1); for (i--; i >= 0; i--) { ulong hi; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max |= mults[i]; umul_ppmm(hi, array_size, array_size, mults[i]); if (hi != 0 || (slong) mults[i] <= 0 || array_size <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(max) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fits into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { fmpz_mpoly_t T; fmpz_mpoly_init3(T, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_LEX(T, C, B, mults, ctx); fmpz_mpoly_swap(T, A, ctx); fmpz_mpoly_clear(T, ctx); } else { fmpz_mpoly_fit_length_reset_bits(A, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_LEX(A, C, B, mults, ctx); } success = 1; cleanup: TMP_END; return success; } /**************************************************** DEGLEX and DEGREVLEX ****************************************************/ #define DEGLEX_UNPACK_MACRO(fxn_name, coeff_decl, nonzero_test, swapper) \ slong fxn_name(fmpz_mpoly_t P, slong Plen, coeff_decl, \ slong top, slong nvars, slong degb) \ { \ slong i; \ ulong exp, lomask = (UWORD(1) << (P->bits - 1)) - 1; \ slong off, array_size; \ slong * curexp, * degpow; \ ulong * oneexp; \ int carry; \ TMP_INIT; \ \ TMP_START; \ curexp = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ degpow = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ oneexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); \ array_size = 1; \ curexp[0] = 0; \ oneexp[0] = 0; \ degpow[0] = 1; \ for (i = 0; i < nvars-1; i++) \ { \ curexp[i] = 0; \ degpow[i] = array_size; \ oneexp[i] = (UWORD(1) << (P->bits*(i+1))) - UWORD(1); \ array_size *= degb; \ } \ off = 0; \ if (nvars > 1) \ { \ curexp[nvars - 2] = top; \ off = top * degpow[nvars - 2]; \ } \ exp = (top << (P->bits*nvars)) + (top << (P->bits*(nvars-1))); \ \ carry = 1; \ do { \ if (nonzero_test) \ { \ _fmpz_mpoly_fit_length(&P->coeffs, &P->exps, &P->alloc, Plen + 1, 1); \ P->exps[Plen] = exp; \ swapper \ Plen++; \ } \ \ exp -= oneexp[0]; \ off -= 1; \ curexp[0] -= 1; \ if (curexp[0] >= 0) \ { \ carry = 0; \ } else \ { \ exp -= curexp[0]*oneexp[0]; \ off -= curexp[0]; \ curexp[0] = 0; \ carry = 1; \ \ for (i = 1; i < nvars - 1; i++) \ { \ exp -= oneexp[i]; \ off -= degpow[i]; \ curexp[i] -= 1; \ if (curexp[i] < 0) \ { \ exp -= curexp[i]*oneexp[i]; \ off -= curexp[i]*degpow[i]; \ curexp[i] = 0; \ carry = 1; \ } else \ { \ ulong t = exp & lomask; \ off += t*degpow[i - 1]; \ curexp[i - 1] = t; \ exp += t*oneexp[i - 1]; \ carry = 0; \ break; \ } \ } \ } \ } while (!carry); \ \ TMP_END; \ \ return Plen; \ } DEGLEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm1_DEGLEX, ulong * coeff_array , coeff_array[off] != WORD(0) , fmpz_set_si(P->coeffs + Plen, coeff_array[off]); coeff_array[off] = 0; ) DEGLEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm2_DEGLEX, ulong * coeff_array , (coeff_array[2*off + 0] || coeff_array[2*off + 1]) != WORD(0) , fmpz_set_signed_uiui(P->coeffs + Plen, coeff_array[2*off + 1], coeff_array[2*off + 0]); coeff_array[2*off + 0] = coeff_array[2*off + 1] = 0; ) DEGLEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm3_DEGLEX, ulong * coeff_array , (coeff_array[3*off + 0] || coeff_array[3*off + 1] || coeff_array[3*off + 2]) != WORD(0) , fmpz_set_signed_uiuiui(P->coeffs + Plen, coeff_array[3*off + 2], coeff_array[3*off + 1], coeff_array[3*off + 0]); coeff_array[3*off + 0] = coeff_array[3*off + 1] = coeff_array[3*off + 2] = 0; ) DEGLEX_UNPACK_MACRO( fmpz_mpoly_append_array_fmpz_DEGLEX, fmpz * coeff_array , !fmpz_is_zero(coeff_array + off) , fmpz_swap(P->coeffs + Plen, coeff_array + off); fmpz_zero(coeff_array + off); ) #define DEGREVLEX_UNPACK_MACRO(fxn_name, coeff_decl, nonzero_test, swapper) \ slong fxn_name(fmpz_mpoly_t P, slong Plen, coeff_decl, \ slong top, slong nvars, slong degb) \ { \ slong i; \ ulong exp, mask = UWORD(1) << (P->bits - 1); \ slong off, array_size; \ slong * curexp, * degpow; \ ulong * oneexp; \ int carry; \ TMP_INIT; \ \ TMP_START; \ curexp = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ degpow = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ oneexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); \ array_size = 1; \ oneexp[0] = 0; \ for (i = 0; i < nvars-1; i++) { \ curexp[i] = 0; \ degpow[i] = array_size; \ oneexp[i] = (UWORD(1) << (P->bits*(i+1))) - UWORD(1); \ array_size *= degb; \ } \ \ off = 0; \ exp = (top << (P->bits*nvars)) + top; \ \ do { \ if (nonzero_test) \ { \ _fmpz_mpoly_fit_length(&P->coeffs, &P->exps, &P->alloc, Plen + 1, 1); \ P->exps[Plen] = exp; \ swapper \ Plen++; \ } \ \ exp += oneexp[0]; \ off += 1; \ curexp[0] += 1; \ if ((exp & mask) == 0) \ { \ carry = (nvars - 1 == 0); \ } else \ { \ carry = 1; \ exp -= curexp[0]*oneexp[0]; \ off -= curexp[0]; \ curexp[0] = 0; \ for (i = 1; i < nvars - 1; i++) \ { \ exp += oneexp[i]; \ off += degpow[i]; \ curexp[i] += 1; \ if ((exp & mask) == 0) \ { \ carry = 0; \ break; \ } else { \ carry = 1; \ exp -= curexp[i]*oneexp[i]; \ off -= curexp[i]*degpow[i]; \ curexp[i] = 0; \ } \ } \ } \ } while (!carry); \ \ TMP_END; \ \ return Plen; \ } DEGREVLEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm1_DEGREVLEX, ulong * coeff_array , coeff_array[off] != WORD(0) , fmpz_set_si(P->coeffs + Plen, coeff_array[off]); coeff_array[off] = 0; ) DEGREVLEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm2_DEGREVLEX, ulong * coeff_array , (coeff_array[2*off + 0] || coeff_array[2*off + 1]) != WORD(0) , fmpz_set_signed_uiui(P->coeffs + Plen, coeff_array[2*off + 1], coeff_array[2*off + 0]); coeff_array[2*off + 0] = coeff_array[2*off + 1] = 0; ) DEGREVLEX_UNPACK_MACRO( fmpz_mpoly_append_array_sm3_DEGREVLEX, ulong * coeff_array , (coeff_array[3*off + 0] || coeff_array[3*off + 1] || coeff_array[3*off + 2]) != WORD(0) , fmpz_set_signed_uiuiui(P->coeffs + Plen, coeff_array[3*off + 2], coeff_array[3*off + 1], coeff_array[3*off + 0]); coeff_array[3*off + 0] = coeff_array[3*off + 1] = coeff_array[3*off + 2] = 0; ) DEGREVLEX_UNPACK_MACRO( fmpz_mpoly_append_array_fmpz_DEGREVLEX, fmpz * coeff_array , !fmpz_is_zero(coeff_array + off) , fmpz_swap(P->coeffs + Plen, coeff_array + off); fmpz_zero(coeff_array + off); ) void _fmpz_mpoly_mul_array_chunked_DEG( fmpz_mpoly_t P, const fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong degb, const fmpz_mpoly_ctx_t ctx) { slong nvars = ctx->minfo->nvars; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong Abits, * Asum, * Amax, Bbits, * Bsum, * Bmax; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; slong (* upack_sm1)(fmpz_mpoly_t, slong, ulong *, slong, slong, slong); slong (* upack_sm2)(fmpz_mpoly_t, slong, ulong *, slong, slong, slong); slong (* upack_sm3)(fmpz_mpoly_t, slong, ulong *, slong, slong, slong); slong (* upack_fmpz)(fmpz_mpoly_t, slong, fmpz *, slong, slong, slong); TMP_INIT; TMP_START; /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*nvars)); Bl = 1 + (slong) (B->exps[0] >> (B->bits*nvars)); array_size = 1; for (i = 0; i < nvars-1; i++) { array_size *= degb; } upack_sm1 = &fmpz_mpoly_append_array_sm1_DEGLEX; upack_sm2 = &fmpz_mpoly_append_array_sm2_DEGLEX; upack_sm3 = &fmpz_mpoly_append_array_sm3_DEGLEX; upack_fmpz = &fmpz_mpoly_append_array_fmpz_DEGLEX; if (ctx->minfo->ord == ORD_DEGREVLEX) { upack_sm1 = &fmpz_mpoly_append_array_sm1_DEGREVLEX; upack_sm2 = &fmpz_mpoly_append_array_sm2_DEGREVLEX; upack_sm3 = &fmpz_mpoly_append_array_sm3_DEGREVLEX; upack_fmpz = &fmpz_mpoly_append_array_fmpz_DEGREVLEX; } /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC(((Al + 1) + Al + Al + (Bl + 1) + Bl + Bl)*sizeof(slong)); Asum = Amain + Al + 1; Amax = Asum + Al; Bmain = Amax + Al; Bsum = Bmain + Bl + 1; Bmax = Bsum + Bl; Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_DEG(Amain, Apexp, A->exps, Al, A->length, degb, nvars, A->bits); mpoly_main_variable_split_DEG(Bmain, Bpexp, B->exps, Bl, B->length, degb, nvars, B->bits); /* work out bit counts for each chunk */ Abits = 0; for (i = 0; i < Al; i++) { _fmpz_vec_sum_max_bits(&Asum[i], &Amax[i], A->coeffs + Amain[i], Amain[i + 1] - Amain[i]); Abits = FLINT_MAX(Abits, Amax[i]); } Bbits = 0; for (j = 0; j < Bl; j++) { _fmpz_vec_sum_max_bits(&Bsum[j], &Bmax[j], B->coeffs + Bmain[j], Bmain[j + 1] - Bmain[j]); Bbits = FLINT_MAX(Bbits, Bmax[j]); } Pl = Al + Bl - 1; FLINT_ASSERT(Pl == degb); Plen = 0; if (Abits <= (SMALL_FMPZ_BITCOUNT_MAX) && Bbits <= (SMALL_FMPZ_BITCOUNT_MAX)) { ulong * coeff_array = (ulong *) TMP_ALLOC(3*array_size*sizeof(ulong)); for (j = 0; j < 3*array_size; j++) coeff_array[j] = 0; /* for each output chunk */ for (Pi = 0; Pi < Pl; Pi++) { /* compute bound on coeffs of output chunk */ slong number = 0; slong Pbits = 0; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { Pbits = FLINT_MAX(Pbits, FLINT_MIN(Asum[i] + Bmax[j], Amax[i] + Bsum[j])); number++; } } Pbits += FLINT_BIT_COUNT(number) + 1; /* includes one bit for sign */ if (Pbits <= FLINT_BITS) { /* fits into one word */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_slong1(coeff_array, (slong *) A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], (slong *) B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = upack_sm1(P, Plen, coeff_array, Pl - Pi - 1, nvars, degb); } else if (Pbits <= 2*FLINT_BITS) { /* fits into two words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_slong2(coeff_array, (slong *) A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], (slong *) B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = upack_sm2(P, Plen, coeff_array, Pl - Pi - 1, nvars, degb); } else { /* fits into three words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_slong(coeff_array, (slong *) A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], (slong *) B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = upack_sm3(P, Plen, coeff_array, Pl - Pi - 1, nvars, degb); } } } else { fmpz * coeff_array = (fmpz *) TMP_ALLOC(array_size*sizeof(fmpz)); for (j = 0; j < array_size; j++) fmpz_init(coeff_array + j); /* for each output chunk */ for (Pi = 0; Pi < Pl; Pi++) { /* addmuls for each cross product of chunks */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _fmpz_mpoly_addmul_array1_fmpz(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = upack_fmpz(P, Plen, coeff_array, Pl - Pi - 1, nvars, degb); } } _fmpz_mpoly_set_length(P, Plen, ctx); flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _fmpz_mpoly_mul_array_DEG( fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx) { slong i, exp_bits, array_size; ulong deg; int success; FLINT_ASSERT(ctx->minfo->nvars > 0); FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT( ctx->minfo->ord == ORD_DEGREVLEX || ctx->minfo->ord == ORD_DEGLEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); /* the field of index n-1 is the degree and will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); deg = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); if (((slong) deg) <= 0 || deg > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...1, contribute to the array size */ array_size = WORD(1); for (i--; i >= 1; i--) { ulong hi; umul_ppmm(hi, array_size, array_size, deg); if (hi != WORD(0) || array_size <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(deg) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fits into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { fmpz_mpoly_t T; fmpz_mpoly_init3(T, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_DEG(T, C, B, deg, ctx); fmpz_mpoly_swap(T, A, ctx); fmpz_mpoly_clear(T, ctx); } else { fmpz_mpoly_fit_length_reset_bits(A, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_DEG(A, C, B, deg, ctx); } success = 1; cleanup: return success; } int fmpz_mpoly_mul_array( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i; int success; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length == 0 || C->length == 0) { fmpz_mpoly_zero(A, ctx); return 1; } if (ctx->minfo->nvars < 1 || 1 != mpoly_words_per_exp(B->bits, ctx->minfo) || 1 != mpoly_words_per_exp(C->bits, ctx->minfo)) { return 0; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); switch (ctx->minfo->ord) { case ORD_LEX: { success = _fmpz_mpoly_mul_array_LEX(A, B, maxBfields, C, maxCfields, ctx); break; } case ORD_DEGLEX: case ORD_DEGREVLEX: { success = _fmpz_mpoly_mul_array_DEG(A, B, maxBfields, C, maxCfields, ctx); break; } default: { success = 0; break; } } for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; return success; } flint-3.1.3/src/fmpz_mpoly/mul_array_threaded.c000066400000000000000000000732011461254215100216200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* NOTE: this file is dirty - it assumes that a zero fmpz is zero */ /* improve locality */ #define BLOCK 128 #define MAX_ARRAY_SIZE (WORD(300000)) #define MAX_LEX_SIZE (WORD(300)) typedef struct { slong idx; slong work; slong len; fmpz_mpoly_t poly; } _chunk_struct; typedef struct { #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif volatile int idx; slong nthreads; slong Al, Bl, Pl; fmpz * Acoeffs, * Bcoeffs; slong * Amax, * Bmax, * Asum, * Bsum; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; slong * perm; slong nvars; const ulong * mults; slong array_size; slong degb; _chunk_struct * Pchunks; int rev; } _base_struct; typedef _base_struct _base_t[1]; typedef struct { slong idx; slong time; _base_struct * base; ulong * exp; } _worker_arg_struct; /****************** LEX ******************/ void _fmpz_mpoly_mul_array_threaded_worker_LEX(void * varg) { slong i, j, Pi; _worker_arg_struct * arg = (_worker_arg_struct *) varg; _base_struct * base = arg->base; ulong * coeff_array; TMP_INIT; TMP_START; coeff_array = (ulong *) TMP_ALLOC(3*base->array_size*sizeof(ulong)); for (j = 0; j < 3*base->array_size; j++) coeff_array[j] = 0; #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif while (Pi < base->Pl) { /* work out bit counts for this chunk */ slong Abits = 0; slong Bbits = 0; slong Pbits = 0; slong number = 0; for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { number++; Abits = FLINT_MAX(Abits, base->Amax[i]); Bbits = FLINT_MAX(Bbits, base->Bmax[j]); Pbits = FLINT_MAX(Pbits, FLINT_MIN(base->Asum[i] + base->Bmax[j], base->Amax[i] + base->Bsum[j])); } } Pbits += FLINT_BIT_COUNT(number) + 1; /* includes one bit for sign */ if (Abits <= SMALL_FMPZ_BITCOUNT_MAX && Bbits <= SMALL_FMPZ_BITCOUNT_MAX) { if (Pbits <= FLINT_BITS) { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_slong1((ulong *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = fmpz_mpoly_append_array_sm1_LEX( (base->Pchunks + base->perm[Pi])->poly, 0, (ulong *)coeff_array, base->mults, base->nvars - 1, base->array_size, base->Pl - base->perm[Pi] - 1); } else if (Pbits <= 2*FLINT_BITS) { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_slong2((ulong *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = fmpz_mpoly_append_array_sm2_LEX( (base->Pchunks + base->perm[Pi])->poly, 0, (ulong *)coeff_array, base->mults, base->nvars - 1, base->array_size, base->Pl - base->perm[Pi] - 1); } else { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_slong((ulong *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = fmpz_mpoly_append_array_sm3_LEX( (base->Pchunks + base->perm[Pi])->poly, 0, (ulong *)coeff_array, base->mults, base->nvars - 1, base->array_size, base->Pl - base->perm[Pi] - 1); } } else { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_fmpz((fmpz *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = fmpz_mpoly_append_array_fmpz_LEX( (base->Pchunks + base->perm[Pi])->poly, 0, (fmpz *)coeff_array, base->mults, base->nvars - 1, base->array_size, base->Pl - base->perm[Pi] - 1); } #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } TMP_END; } void _fmpz_mpoly_mul_array_chunked_threaded_LEX( fmpz_mpoly_t P, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const ulong * mults, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong nvars = ctx->minfo->nvars; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong * Asum, * Amax, * Bsum, * Bmax; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; _base_t base; _worker_arg_struct * args; _chunk_struct * Pchunks; slong * perm; TMP_INIT; array_size = 1; for (i = 0; i < nvars - 1; i++) { array_size *= mults[i]; } /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*(nvars - 1))); Bl = 1 + (slong) (B->exps[0] >> (B->bits*(nvars - 1))); TMP_START; /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC(((Al + 1) + Al + Al + (Bl + 1) + Bl + Bl)*sizeof(slong)); Asum = Amain + Al + 1; Amax = Asum + Al; Bmain = Amax + Al; Bsum = Bmain + Bl + 1; Bmax = Bsum + Bl; Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_LEX(Amain, Apexp, A->exps, Al, A->length, mults, nvars - 1, A->bits); mpoly_main_variable_split_LEX(Bmain, Bpexp, B->exps, Bl, B->length, mults, nvars - 1, B->bits); /* work out bit counts for each chunk */ for (i = 0; i < Al; i++) { _fmpz_vec_sum_max_bits(&Asum[i], &Amax[i], A->coeffs + Amain[i], Amain[i + 1] - Amain[i]); } for (j = 0; j < Bl; j++) { _fmpz_vec_sum_max_bits(&Bsum[j], &Bmax[j], B->coeffs + Bmain[j], Bmain[j + 1] - Bmain[j]); } Pl = Al + Bl - 1; /* work out data for each chunk of the output */ Pchunks = (_chunk_struct *) TMP_ALLOC(Pl*sizeof(_chunk_struct)); perm = (slong *) TMP_ALLOC(Pl*sizeof(slong)); for (Pi = 0; Pi < Pl; Pi++) { fmpz_mpoly_init3((Pchunks + Pi)->poly, 8, P->bits, ctx); (Pchunks + Pi)->work = 0; perm[Pi] = Pi; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { (Pchunks + Pi)->work += (Amain[i + 1] - Amain[i]) *(Bmain[j + 1] - Bmain[j]); } } } for (i = 0; i < Pl; i++) { for (j = i; j > 0 && (Pchunks + perm[j - 1])->work < (Pchunks + perm[j])->work; j--) { slong t = perm[j - 1]; perm[j - 1] = perm[j]; perm[j] = t; } } base->nthreads = num_handles + 1; base->Al = Al; base->Bl = Bl; base->Pl = Pl; base->Amax = Amax; base->Bmax = Bmax; base->Asum = Asum; base->Bsum = Bsum; base->Acoeffs = A->coeffs; base->Amain = Amain; base->Apexp = Apexp; base->Bcoeffs = B->coeffs; base->Bmain = Bmain; base->Bpexp = Bpexp; base->idx = 0; base->perm = perm; base->nvars = nvars; base->Pchunks = Pchunks; base->array_size = array_size; base->mults = mults; args = (_worker_arg_struct *) TMP_ALLOC(base->nthreads *sizeof(_worker_arg_struct)); #if FLINT_USES_PTHREAD pthread_mutex_init(&base->mutex, NULL); #endif for (i = 0; i < num_handles; i++) { args[i].idx = i; args[i].base = base; thread_pool_wake(global_thread_pool, handles[i], 0, _fmpz_mpoly_mul_array_threaded_worker_LEX, &args[i]); } i = num_handles; args[i].idx = i; args[i].base = base; _fmpz_mpoly_mul_array_threaded_worker_LEX(&args[i]); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&base->mutex); #endif /* join answers */ Plen = 0; for (Pi = 0; Pi < Pl; Pi++) { _fmpz_mpoly_fit_length(&P->coeffs, &P->exps, &P->alloc, Plen + (Pchunks + Pi)->len, 1); for (i = 0; i < (Pchunks + Pi)->len; i++) { P->exps[Plen] = (Pchunks + Pi)->poly->exps[i]; fmpz_swap(P->coeffs + Plen, (Pchunks + Pi)->poly->coeffs + i); fmpz_clear((Pchunks + Pi)->poly->coeffs + i); Plen++; } flint_free((Pchunks + Pi)->poly->coeffs); flint_free((Pchunks + Pi)->poly->exps); } _fmpz_mpoly_set_length(P, Plen, ctx); flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _fmpz_mpoly_mul_array_threaded_pool_LEX( fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong i, exp_bits, array_size; ulong max, * mults; int success; TMP_INIT; FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); TMP_START; /* compute maximum exponents for each variable */ mults = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); /* the field of index n-1 is the one that will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max = mults[i]; if (((slong) mults[i]) <= 0 || mults[i] > MAX_LEX_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...0, contribute to the array size */ array_size = WORD(1); for (i--; i >= 0; i--) { ulong hi; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max |= mults[i]; umul_ppmm(hi, array_size, array_size, mults[i]); if (hi != WORD(0) || (array_size | (slong) mults[i]) <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(max) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fits into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { fmpz_mpoly_t T; fmpz_mpoly_init3(T, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_threaded_LEX(T, C, B, mults, ctx, handles, num_handles); fmpz_mpoly_swap(T, A, ctx); fmpz_mpoly_clear(T, ctx); } else { fmpz_mpoly_fit_length_reset_bits(A, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_threaded_LEX(A, C, B, mults, ctx, handles, num_handles); } success = 1; cleanup: TMP_END; return success; } /***************************** DEGLEX and DEGREVLEX *****************************/ void _fmpz_mpoly_mul_array_threaded_worker_DEG(void * varg) { slong i, j, Pi; _worker_arg_struct * arg = (_worker_arg_struct *) varg; _base_struct * base = arg->base; ulong * coeff_array; slong (* upack_sm1)(fmpz_mpoly_t, slong, ulong *, slong, slong, slong); slong (* upack_sm2)(fmpz_mpoly_t, slong, ulong *, slong, slong, slong); slong (* upack_sm3)(fmpz_mpoly_t, slong, ulong *, slong, slong, slong); slong (* upack_fmpz)(fmpz_mpoly_t, slong, fmpz *, slong, slong, slong); TMP_INIT; upack_sm1 = &fmpz_mpoly_append_array_sm1_DEGLEX; upack_sm2 = &fmpz_mpoly_append_array_sm2_DEGLEX; upack_sm3 = &fmpz_mpoly_append_array_sm3_DEGLEX; upack_fmpz = &fmpz_mpoly_append_array_fmpz_DEGLEX; if (base->rev) { upack_sm1 = &fmpz_mpoly_append_array_sm1_DEGREVLEX; upack_sm2 = &fmpz_mpoly_append_array_sm2_DEGREVLEX; upack_sm3 = &fmpz_mpoly_append_array_sm3_DEGREVLEX; upack_fmpz = &fmpz_mpoly_append_array_fmpz_DEGREVLEX; } TMP_START; coeff_array = (ulong *) TMP_ALLOC(3*base->array_size*sizeof(ulong)); for (j = 0; j < 3*base->array_size; j++) coeff_array[j] = 0; #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif while (Pi < base->Pl) { /* work out bit counts for this chunk */ slong Abits = 0; slong Bbits = 0; slong Pbits = 0; slong number = 0; for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { number++; Abits = FLINT_MAX(Abits, base->Amax[i]); Bbits = FLINT_MAX(Bbits, base->Bmax[j]); Pbits = FLINT_MAX(Pbits, FLINT_MIN(base->Asum[i] + base->Bmax[j], base->Amax[i] + base->Bsum[j])); } } Pbits += FLINT_BIT_COUNT(number) + 1; /* includes one bit for sign */ if (Abits <= SMALL_FMPZ_BITCOUNT_MAX && Bbits <= SMALL_FMPZ_BITCOUNT_MAX) { if (Pbits <= FLINT_BITS) { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_slong1((ulong *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = upack_sm1((base->Pchunks + base->perm[Pi])->poly, 0, (ulong *)coeff_array, base->Pl - base->perm[Pi] - 1, base->nvars, base->degb); } else if (Pbits <= 2*FLINT_BITS) { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_slong2((ulong *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = upack_sm2((base->Pchunks + base->perm[Pi])->poly, 0, (ulong *)coeff_array, base->Pl - base->perm[Pi] - 1, base->nvars, base->degb); } else { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_slong((ulong *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = upack_sm3((base->Pchunks + base->perm[Pi])->poly, 0, (ulong *)coeff_array, base->Pl - base->perm[Pi] - 1, base->nvars, base->degb); } } else { for (i = 0, j = base->perm[Pi]; i < base->Al && j >= 0; i++, j--) { if (j < base->Bl) { _fmpz_mpoly_addmul_array1_fmpz((fmpz *)coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } } (base->Pchunks + base->perm[Pi])->len = upack_fmpz((base->Pchunks + base->perm[Pi])->poly, 0, (fmpz *)coeff_array, base->Pl - base->perm[Pi] - 1, base->nvars, base->degb); } #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } TMP_END; } void _fmpz_mpoly_mul_array_chunked_threaded_DEG( fmpz_mpoly_t P, const fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong degb, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong nvars = ctx->minfo->nvars; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong * Asum, * Amax, * Bsum, * Bmax; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; _base_t base; _worker_arg_struct * args; _chunk_struct * Pchunks; slong * perm; TMP_INIT; /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*nvars)); Bl = 1 + (slong) (B->exps[0] >> (B->bits*nvars)); array_size = 1; for (i = 0; i < nvars-1; i++) { array_size *= degb; } TMP_START; /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC(((Al + 1) + Al + Al + (Bl + 1) + Bl + Bl)*sizeof(slong)); Asum = Amain + Al + 1; Amax = Asum + Al; Bmain = Amax + Al; Bsum = Bmain + Bl + 1; Bmax = Bsum + Bl; Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_DEG(Amain, Apexp, A->exps, Al, A->length, degb, nvars, A->bits); mpoly_main_variable_split_DEG(Bmain, Bpexp, B->exps, Bl, B->length, degb, nvars, B->bits); /* work out bit counts for each chunk */ for (i = 0; i < Al; i++) { _fmpz_vec_sum_max_bits(&Asum[i], &Amax[i], A->coeffs + Amain[i], Amain[i + 1] - Amain[i]); } for (j = 0; j < Bl; j++) { _fmpz_vec_sum_max_bits(&Bsum[j], &Bmax[j], B->coeffs + Bmain[j], Bmain[j + 1] - Bmain[j]); } Pl = Al + Bl - 1; FLINT_ASSERT(Pl == degb); /* work out data for each chunk of the output */ Pchunks = (_chunk_struct *) TMP_ALLOC(Pl*sizeof(_chunk_struct)); perm = (slong *) TMP_ALLOC(Pl*sizeof(slong)); for (Pi = 0; Pi < Pl; Pi++) { fmpz_mpoly_init3((Pchunks + Pi)->poly, 8, P->bits, ctx); (Pchunks + Pi)->work = 0; perm[Pi] = Pi; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { (Pchunks + Pi)->work += (Amain[i + 1] - Amain[i]) *(Bmain[j + 1] - Bmain[j]); } } } for (i = 0; i < Pl; i++) { for (j = i; j > 0 && (Pchunks + perm[j-1])->work < (Pchunks + perm[j])->work; j--) { slong t = perm[j - 1]; perm[j - 1] = perm[j]; perm[j] = t; } } base->nthreads = num_handles + 1; base->Al = Al; base->Bl = Bl; base->Pl = Pl; base->Amax = Amax; base->Bmax = Bmax; base->Asum = Asum; base->Bsum = Bsum; base->Acoeffs = A->coeffs; base->Amain = Amain; base->Apexp = Apexp; base->Bcoeffs = B->coeffs; base->Bmain = Bmain; base->Bpexp = Bpexp; base->idx = 0; base->perm = perm; base->nvars = nvars; base->Pchunks = Pchunks; base->array_size = array_size; base->degb = degb; base->rev = (ctx->minfo->ord == ORD_DEGREVLEX); args = (_worker_arg_struct *) TMP_ALLOC(base->nthreads *sizeof(_worker_arg_struct)); #if FLINT_USES_PTHREAD pthread_mutex_init(&base->mutex, NULL); #endif for (i = 0; i < num_handles; i++) { args[i].idx = i; args[i].base = base; thread_pool_wake(global_thread_pool, handles[i], 0, _fmpz_mpoly_mul_array_threaded_worker_DEG, &args[i]); } i = num_handles; args[i].idx = i; args[i].base = base; _fmpz_mpoly_mul_array_threaded_worker_DEG(&args[i]); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&base->mutex); #endif /* join answers */ Plen = 0; for (Pi = 0; Pi < Pl; Pi++) { _fmpz_mpoly_fit_length(&P->coeffs, &P->exps, &P->alloc, Plen + (Pchunks + Pi)->len, 1); for (i = 0; i < (Pchunks + Pi)->len; i++) { P->exps[Plen] = (Pchunks + Pi)->poly->exps[i]; fmpz_swap(P->coeffs + Plen, (Pchunks + Pi)->poly->coeffs + i); fmpz_clear((Pchunks + Pi)->poly->coeffs + i); Plen++; } flint_free((Pchunks + Pi)->poly->coeffs); flint_free((Pchunks + Pi)->poly->exps); } _fmpz_mpoly_set_length(P, Plen, ctx); flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _fmpz_mpoly_mul_array_threaded_pool_DEG( fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong i, exp_bits, array_size; ulong deg; int success; FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT( ctx->minfo->ord == ORD_DEGREVLEX || ctx->minfo->ord == ORD_DEGLEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); /* the field of index n-1 is the one that will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); deg = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); if (((slong) deg) <= 0 || deg > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...1, contribute to the array size */ array_size = WORD(1); for (i--; i >= 1; i--) { ulong hi; umul_ppmm(hi, array_size, array_size, deg); if (hi != WORD(0) || array_size <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(deg) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fit into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { fmpz_mpoly_t T; fmpz_mpoly_init3(T, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_threaded_DEG(T, C, B, deg, ctx, handles, num_handles); fmpz_mpoly_swap(T, A, ctx); fmpz_mpoly_clear(T, ctx); } else { fmpz_mpoly_fit_length_reset_bits(A, B->length + C->length, exp_bits, ctx); _fmpz_mpoly_mul_array_chunked_threaded_DEG(A, C, B, deg, ctx, handles, num_handles); } success = 1; cleanup: return success; } int fmpz_mpoly_mul_array_threaded( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i; int success; fmpz * maxBfields, * maxCfields; thread_pool_handle * handles; slong num_handles; slong thread_limit = FLINT_MIN(A->length, B->length)/16; TMP_INIT; if (B->length == 0 || C->length == 0) { fmpz_mpoly_zero(A, ctx); return 1; } if (ctx->minfo->nvars < 1 || 1 != mpoly_words_per_exp(B->bits, ctx->minfo) || 1 != mpoly_words_per_exp(C->bits, ctx->minfo)) { return 0; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); num_handles = flint_request_threads(&handles, thread_limit); switch (ctx->minfo->ord) { case ORD_LEX: { success = _fmpz_mpoly_mul_array_threaded_pool_LEX(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); break; } case ORD_DEGREVLEX: case ORD_DEGLEX: { success = _fmpz_mpoly_mul_array_threaded_pool_DEG(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); break; } default: { success = 0; break; } } flint_give_back_threads(handles, num_handles); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; return success; } flint-3.1.3/src/fmpz_mpoly/mul_dense.c000066400000000000000000000251061461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" static slong fmpz_mpolyd_length(const fmpz_mpolyd_t A) { slong i, j; slong degb_prod; degb_prod = WORD(1); for (j = 0; j < A->nvars; j++) { degb_prod *= A->deg_bounds[j]; } for (i = degb_prod; i > 0; i--) { if (!fmpz_is_zero(A->coeffs + i - 1)) { break; } } return i; } static int fmpz_mpolyd_set_degbounds(fmpz_mpolyd_t A, slong * bounds) { slong i; int success = 0; slong degb_prod; degb_prod = 1; for (i = 0; i < A->nvars; i++) { ulong hi; A->deg_bounds[i] = bounds[i]; umul_ppmm(hi, degb_prod, degb_prod, A->deg_bounds[i]); if (hi != WORD(0) || degb_prod < 0) { goto done; } } success = 1; fmpz_mpolyd_fit_length(A, degb_prod); done: return success; } /* assuming poly1 has valid degree bounds set, pack poly2 into it. */ static void fmpz_mpoly_convert_to_fmpz_mpolyd_degbound(fmpz_mpolyd_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) { slong degb_prod; slong i, j, N; ulong * exps; slong nvars = ctx->minfo->nvars; TMP_INIT; FLINT_ASSERT(poly1->nvars == nvars); FLINT_ASSERT(poly2->bits <= FLINT_BITS); degb_prod = WORD(1); for (i = 0; i < nvars; i++) { degb_prod *= poly1->deg_bounds[i]; } for (i = 0; i < degb_prod; i++) { fmpz_zero(poly1->coeffs + i); } if (poly2->length == 0) { return; } TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); N = mpoly_words_per_exp(poly2->bits, ctx->minfo); for (i = 0; i < poly2->length; i++) { slong off; mpoly_get_monomial_ui(exps, poly2->exps + N*i, poly2->bits, ctx->minfo); off = 0; for (j = 0; j < nvars; j++) { off = exps[j] + poly1->deg_bounds[j]*off; } fmpz_set(poly1->coeffs + off, poly2->coeffs + i); } TMP_END; } /* Convert B to A and clear B in the process */ static void fmpz_mpoly_consume_fmpz_mpolyd_clear(fmpz_mpoly_t A, fmpz_mpolyd_t B, const fmpz_mpoly_ctx_t ctx) { slong i, j, k, N; slong bits, nvars = ctx->minfo->nvars; slong Alen; ulong diff; ulong topmask; ulong * exps, * ptempexp, * plastexp; TMP_INIT; FLINT_ASSERT(nvars == B->nvars); TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); /* clear all irrelevant coefficients */ for (i = B->coeff_alloc - 1; i >= B->length; i--) fmpz_clear(B->coeffs + i); /* find bits needed for the result */ for (j = 0; j < nvars; j++) { exps[j] = B->deg_bounds[j] - 1; } bits = mpoly_exp_bits_required_ui(exps, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); N = mpoly_words_per_exp(bits, ctx->minfo); /* we are going to push back terms manually */ Alen = 0; fmpz_mpoly_zero(A, ctx); fmpz_mpoly_fit_length_reset_bits(A, 0, bits, ctx); /* find exponent vector for least significant variable */ plastexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); for (j = 0; j < nvars; j++) exps[j] = (j == nvars - 1); mpoly_set_monomial_ui(plastexp, exps, bits, ctx->minfo); /* get most significant exponent in exps and its vector in ptempexp */ ptempexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); k = i; for (j = nvars - 1; j >= 0; j--) { exps[j] = k % B->deg_bounds[j]; k = k / B->deg_bounds[j]; } mpoly_set_monomial_ui(ptempexp, exps, bits, ctx->minfo); diff = 0; /* scan down through the exponents */ topmask = 0; for (; i >= 0; i--) { if (!fmpz_is_zero(B->coeffs + i)) { _fmpz_mpoly_fit_length(&A->coeffs, &A->exps, &A->alloc, Alen + 1, N); fmpz_swap(A->coeffs + Alen, B->coeffs + i); mpoly_monomial_msub_mp(A->exps + N*Alen, ptempexp, diff, plastexp, N); topmask |= (A->exps + N*Alen)[N - 1]; Alen++; } fmpz_clear(B->coeffs + i); diff++; --exps[nvars - 1]; if ((slong)(exps[nvars - 1]) < WORD(0)) { exps[nvars - 1] = B->deg_bounds[nvars - 1] - 1; for (j = nvars - 2; j >= 0; j--) { --exps[j]; if ((slong)(exps[j]) < WORD(0)) { FLINT_ASSERT(i == 0 || j > 0); exps[j] = B->deg_bounds[j] - 1; } else { break; } } mpoly_set_monomial_ui(ptempexp, exps, bits, ctx->minfo); diff = 0; } } _fmpz_mpoly_set_length(A, Alen, ctx); /* sort the exponents if needed */ if (ctx->minfo->ord != ORD_LEX) { slong msb; mpoly_get_cmpmask(ptempexp, N, bits, ctx->minfo); if (topmask != WORD(0)) { msb = flint_clz(topmask); msb = (FLINT_BITS - 1)^msb; } else { msb = -WORD(1); } if (N == 1) { if (msb >= WORD(0)) { _fmpz_mpoly_radix_sort1(A, 0, A->length, msb, ptempexp[0], topmask); } } else { _fmpz_mpoly_radix_sort(A, 0, A->length, (N - 1)*FLINT_BITS + msb, N, ptempexp); } } flint_free(B->deg_bounds); flint_free(B->coeffs); B->deg_bounds = NULL; B->coeffs = NULL; TMP_END; } int _fmpz_mpoly_mul_dense(fmpz_mpoly_t P, const fmpz_mpoly_t A, fmpz * maxAfields, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_ctx_t ctx) { int success, P_is_stolen; slong i; slong nvars = ctx->minfo->nvars; fmpz_mpolyd_t Ad, Bd, Pd; fmpz_poly_t Au, Bu, Pu; slong * Abounds, * Bbounds, * Pbounds; TMP_INIT; FLINT_ASSERT(A->length != 0); FLINT_ASSERT(B->length != 0); FLINT_ASSERT(nvars > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; /* for each variable v except for the outer variable, we need to pack to degree deg_v(A) + deg_v(A) */ Abounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Bbounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Pbounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Abounds, maxAfields, ctx->minfo); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Bbounds, maxBfields, ctx->minfo); for (i = 0; i < ctx->minfo->nvars; i++) { Abounds[i] = Abounds[i] + 1; Bbounds[i] = Bbounds[i] + 1; Pbounds[i] = Abounds[i] + Bbounds[i] - 1; if ((Abounds[i] | Bbounds[i] | Pbounds[i]) < 0) { goto failed_stage1; } if (i > 0) { Abounds[i] = Pbounds[i]; Bbounds[i] = Pbounds[i]; } } fmpz_mpolyd_init(Ad, nvars); fmpz_mpolyd_init(Bd, nvars); P_is_stolen = 0; if (P != A && P != B && P->alloc > 0) { /* we may steal the coeffs of P in this case to init Pd */ Pd->nvars = nvars; Pd->degb_alloc = nvars; Pd->deg_bounds = (slong *) flint_malloc(Pd->degb_alloc*sizeof(slong)); for (i = 0; i < nvars; i++) { Pd->deg_bounds[i] = WORD(1); } Pd->coeffs = P->coeffs; Pd->coeff_alloc = P->alloc; P->coeffs = (fmpz *) flint_calloc(P->alloc, sizeof(fmpz)); P_is_stolen = 1; } else { fmpz_mpolyd_init(Pd, ctx->minfo->nvars); } success = 1; success = success && fmpz_mpolyd_set_degbounds(Ad, Abounds); success = success && fmpz_mpolyd_set_degbounds(Bd, Bbounds); success = success && fmpz_mpolyd_set_degbounds(Pd, Pbounds); if (!success) { goto failed_stage2; } fmpz_mpoly_convert_to_fmpz_mpolyd_degbound(Ad, A, ctx); fmpz_mpoly_convert_to_fmpz_mpolyd_degbound(Bd, B, ctx); /* let Au and Bu borrow Ad and Bd */ Au->alloc = Ad->coeff_alloc; Au->coeffs = Ad->coeffs; Au->length = fmpz_mpolyd_length(Ad); Bu->alloc = Bd->coeff_alloc; Bu->coeffs = Bd->coeffs; Bu->length = fmpz_mpolyd_length(Bd); /* manually move P to Pu */ Pu->alloc = Pd->coeff_alloc; Pu->coeffs = Pd->coeffs; Pu->length = 0; fmpz_poly_mul(Pu, Au, Bu); /* manually move Pu to P */ Pd->coeff_alloc = Pu->alloc; Pd->coeffs = Pu->coeffs; Pd->length = Pu->length; fmpz_mpolyd_clear(Bd); fmpz_mpolyd_clear(Ad); fmpz_mpoly_consume_fmpz_mpolyd_clear(P, Pd, ctx); done: TMP_END; return success; failed_stage2: fmpz_mpolyd_clear(Ad); fmpz_mpolyd_clear(Bd); if (P_is_stolen) { fmpz * t = Pd->coeffs; Pd->coeffs = P->coeffs; P->coeffs = t; } fmpz_mpolyd_clear(Pd); failed_stage1: success = 0; goto done; } int fmpz_mpoly_mul_dense(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i; int success; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length == 0 || C->length == 0) { fmpz_mpoly_zero(A, ctx); return 1; } if (B->bits > FLINT_BITS || C->bits > FLINT_BITS || ctx->minfo->nvars < 1) { return 0; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); success = _fmpz_mpoly_mul_dense(A, B, maxBfields, C, maxCfields, ctx); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; return success; } flint-3.1.3/src/fmpz_mpoly/mul_heap_threaded.c000066400000000000000000000677301461254215100214310ustar00rootroot00000000000000/* Copyright (C) 2017-2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_mul_heap_part1(fmpz ** A_coeff, ulong ** A_exp, slong * A_alloc, const fmpz * Bcoeff, const ulong * Bexp, slong Blen, const fmpz * Ccoeff, const ulong * Cexp, slong Clen, slong * start, slong * end, slong * hind, const fmpz_mpoly_stripe_t S) { const int flint_small = S->flint_small; const ulong cmpmask = S->cmpmask[0]; slong i, j; ulong exp; mpoly_heap_t * x; slong next_loc; slong heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; slong Alen; fmpz * Acoeff = *A_coeff; ulong * Aexp = *A_exp; slong Aalloc = *A_alloc; ulong acc[3], p[3]; int first_prod; i = 0; store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); /* put all the starting nodes on the heap */ heap_len = 1; /* heap zero index unused */ next_loc = Blen + 4; /* something bigger than heap can ever be */ for (i = 0; i < Blen; i++) { hind[i] = 2*start[i] + 1; } for (i = 0; i < Blen; i++) { if ( (start[i] < end[i]) && ( (i == 0) || (start[i] < start[i - 1]) ) ) { x = chain + i; x->i = i; x->j = start[i]; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, cmpmask); } } Alen = 0; while (heap_len > 1) { exp = heap[1].exp; _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, 1); Aexp[Alen] = exp; acc[0] = acc[1] = acc[2] = 0; first_prod = 1; while (heap_len > 1 && heap[1].exp == exp) { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; if (flint_small) { smul_ppmm(p[1], p[0], Bcoeff[x->i], Ccoeff[x->j]); p[2] = FLINT_SIGN_EXT(p[1]); add_sssaaaaaa(acc[2], acc[1], acc[0], acc[2], acc[1], acc[0], p[2], p[1], p[0]); first_prod = 0; while ((x = x->next) != NULL) { smul_ppmm(p[1], p[0], Bcoeff[x->i], Ccoeff[x->j]); p[2] = FLINT_SIGN_EXT(p[1]); add_sssaaaaaa(acc[2], acc[1], acc[0], acc[2], acc[1], acc[0], p[2], p[1], p[0]); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; } } else /* output coeffs require multiprecision */ { if (first_prod) fmpz_mul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); else fmpz_addmul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); first_prod = 0; while ((x = x->next) != NULL) { fmpz_addmul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; } } } /* for each node temporarily stored */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < end[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, cmpmask); } /* should we go up? */ if ( (j + 1 < end[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, cmpmask); } } /* set output poly coeff from temporary accumulation, if not multiprec */ if (flint_small) { fmpz_set_signed_uiuiui(Acoeff + Alen, acc[2], acc[1], acc[0]); } Alen += !fmpz_is_zero(Acoeff + Alen); } *A_coeff = Acoeff; *A_exp = Aexp; *A_alloc = Aalloc; return Alen; } slong _fmpz_mpoly_mul_heap_part(fmpz ** A_coeff, ulong ** A_exp, slong * A_alloc, const fmpz * Bcoeff, const ulong * Bexp, slong Blen, const fmpz * Ccoeff, const ulong * Cexp, slong Clen, slong * start, slong * end, slong * hind, const fmpz_mpoly_stripe_t S) { const int flint_small = S->flint_small; flint_bitcnt_t bits = S->bits; slong N = S->N; const ulong * cmpmask = S->cmpmask; slong i, j; ulong * exp, * exps; ulong ** exp_list; slong exp_next; mpoly_heap_t * x; slong next_loc; slong heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; slong Alen; ulong * Aexp = *A_exp; slong Aalloc = *A_alloc; fmpz * Acoeff = *A_coeff; ulong acc[3], p[3]; int first_prod; i = 0; store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); exp_list = (ulong **) (S->big_mem + i); i += Blen*sizeof(ulong *); exps = (ulong *) (S->big_mem + i); i += Blen*N*sizeof(ulong); heap = (mpoly_heap_s *) (S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *) (S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); /* put all the starting nodes on the heap */ heap_len = 1; /* heap zero index unused */ next_loc = Blen + 4; /* something bigger than heap can ever be */ exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; for (i = 0; i < Blen; i++) hind[i] = 2*start[i] + 1; for (i = 0; i < Blen; i++) { if ( (start[i] < end[i]) && ( (i == 0) || (start[i] < start[i - 1]) ) ) { x = chain + i; x->i = i; x->j = start[i]; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + x->i*N, Cexp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + x->i*N, Cexp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } Alen = 0; while (heap_len > 1) { exp = heap[1].exp; _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N); mpoly_monomial_set(Aexp + N*Alen, exp, N); acc[0] = acc[1] = acc[2] = 0; first_prod = 1; while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)) { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; /* if output coeffs will fit in three words */ if (flint_small) { smul_ppmm(p[1], p[0], Bcoeff[x->i], Ccoeff[x->j]); p[2] = FLINT_SIGN_EXT(p[1]); add_sssaaaaaa(acc[2], acc[1], acc[0], acc[2], acc[1], acc[0], p[2], p[1], p[0]); first_prod = 0; while ((x = x->next) != NULL) { smul_ppmm(p[1], p[0], Bcoeff[x->i], Ccoeff[x->j]); p[2] = FLINT_SIGN_EXT(p[1]); add_sssaaaaaa(acc[2], acc[1], acc[0], acc[2], acc[1], acc[0], p[2], p[1], p[0]); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; } } else /* output coeffs require multiprecision */ { if (first_prod) fmpz_mul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); else fmpz_addmul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); first_prod = 0; while ((x = x->next) != NULL) { fmpz_addmul(Acoeff + Alen, Bcoeff + x->i, Ccoeff + x->j); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; } } } /* for each node temporarily stored */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < end[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + x->i*N, Cexp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + x->i*N, Cexp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ( (j + 1 < end[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + x->i*N, Cexp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + x->i*N, Cexp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } /* set output poly coeff from temporary accumulation, if not multiprec */ if (flint_small) { fmpz_set_signed_uiuiui(Acoeff + Alen, acc[2], acc[1], acc[0]); } Alen += !fmpz_is_zero(Acoeff + Alen); } *A_coeff = Acoeff; *A_exp = Aexp; *A_alloc = Aalloc; return Alen; } /* The workers calculate product terms from 4*n divisions, where n is the number of threads. */ typedef struct { volatile int idx; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong nthreads; slong ndivs; fmpz * Acoeff; ulong * Aexp; const fmpz * Bcoeff; const ulong * Bexp; slong Blen; const fmpz * Ccoeff; const ulong * Cexp; slong Clen; slong N; flint_bitcnt_t bits; const ulong * cmpmask; int flint_small; } _base_struct; typedef _base_struct _base_t[1]; typedef struct { slong lower; slong upper; slong thread_idx; slong Aoffset; slong Alen; slong Aalloc; ulong * Aexp; fmpz * Acoeff; } _div_struct; typedef struct { fmpz_mpoly_stripe_t S; slong idx; slong time; _base_struct * base; _div_struct * divs; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; pthread_cond_t cond; #endif slong * t1, * t2, * t3, * t4; ulong * exp; } _worker_arg_struct; /* The workers simply take the next available division and calculate all product terms in this division. */ #define SWAP_PTRS(xx, yy) \ do { \ tt = xx; \ xx = yy; \ yy = tt; \ } while (0) static void _fmpz_mpoly_mul_heap_threaded_worker(void * varg) { _worker_arg_struct * arg = (_worker_arg_struct *) varg; fmpz_mpoly_stripe_struct * S = arg->S; _div_struct * divs = arg->divs; _base_struct * base = arg->base; slong Blen = base->Blen; slong N = base->N; slong i, j; ulong *exp; slong score; slong *start, *end, *t1, *t2, *t3, *t4, *tt; exp = (ulong *) flint_malloc(N*sizeof(ulong)); t1 = (slong *) flint_malloc(Blen*sizeof(slong)); t2 = (slong *) flint_malloc(Blen*sizeof(slong)); t3 = (slong *) flint_malloc(Blen*sizeof(slong)); t4 = (slong *) flint_malloc(Blen*sizeof(slong)); S->N = N; S->bits = base->bits; S->cmpmask = base->cmpmask; S->flint_small = base->flint_small; S->big_mem_alloc = 0; if (N == 1) { S->big_mem_alloc += 2*Blen*sizeof(slong); S->big_mem_alloc += (Blen + 1)*sizeof(mpoly_heap1_s); S->big_mem_alloc += Blen*sizeof(mpoly_heap_t); } else { S->big_mem_alloc += 2*Blen*sizeof(slong); S->big_mem_alloc += (Blen + 1)*sizeof(mpoly_heap_s); S->big_mem_alloc += Blen*sizeof(mpoly_heap_t); S->big_mem_alloc += Blen*S->N*sizeof(ulong); S->big_mem_alloc += Blen*sizeof(ulong *); } S->big_mem = (char *) flint_malloc(S->big_mem_alloc); /* get index to start working on */ if (arg->idx + 1 < base->nthreads) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif i = base->idx - 1; base->idx = i; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } else { i = base->ndivs - 1; } while (i >= 0) { FLINT_ASSERT(divs[i].thread_idx == -WORD(1)); divs[i].thread_idx = arg->idx; /* calculate start */ if (i + 1 < base-> ndivs) { mpoly_search_monomials( &start, exp, &score, t1, t2, t3, divs[i].lower, divs[i].lower, base->Bexp, base->Blen, base->Cexp, base->Clen, base->N, base->cmpmask); if (start == t2) { SWAP_PTRS(t1, t2); } else if (start == t3) { SWAP_PTRS(t1, t3); } } else { start = t1; for (j = 0; j < base->Blen; j++) start[j] = 0; } /* calculate end */ if (i > 0) { mpoly_search_monomials( &end, exp, &score, t2, t3, t4, divs[i - 1].lower, divs[i - 1].lower, base->Bexp, base->Blen, base->Cexp, base->Clen, base->N, base->cmpmask); if (end == t3) { SWAP_PTRS(t2, t3); } else if (end == t4) { SWAP_PTRS(t2, t4); } } else { end = t2; for (j = 0; j < base->Blen; j++) end[j] = base->Clen; } /* t3 and t4 are free for workspace at this point */ /* join code assumes all divisions have been allocated */ _fmpz_mpoly_fit_length(&divs[i].Acoeff, &divs[i].Aexp, &divs[i].Aalloc, 256, N); /* calculate products in [start, end) */ if (N == 1) { divs[i].Alen = _fmpz_mpoly_mul_heap_part1( &divs[i].Acoeff, &divs[i].Aexp, &divs[i].Aalloc, base->Bcoeff, base->Bexp, base->Blen, base->Ccoeff, base->Cexp, base->Clen, start, end, t3, S); } else { divs[i].Alen = _fmpz_mpoly_mul_heap_part( &divs[i].Acoeff, &divs[i].Aexp, &divs[i].Aalloc, base->Bcoeff, base->Bexp, base->Blen, base->Ccoeff, base->Cexp, base->Clen, start, end, t3, S); } /* get next index to work on */ #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif i = base->idx - 1; base->idx = i; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } flint_free(S->big_mem); flint_free(t4); flint_free(t3); flint_free(t2); flint_free(t1); flint_free(exp); } static void _join_worker(void * varg) { _worker_arg_struct * arg = (_worker_arg_struct *) varg; _div_struct * divs = arg->divs; _base_struct * base = arg->base; slong N = base->N; slong i; for (i = base->ndivs - 2; i >= 0; i--) { FLINT_ASSERT(divs[i].thread_idx != -WORD(1)); if (divs[i].thread_idx != arg->idx) continue; FLINT_ASSERT(divs[i].Acoeff != NULL); FLINT_ASSERT(divs[i].Aexp != NULL); memcpy(base->Acoeff + divs[i].Aoffset, divs[i].Acoeff, divs[i].Alen*sizeof(fmpz)); memcpy(base->Aexp + N*divs[i].Aoffset, divs[i].Aexp, N*divs[i].Alen*sizeof(ulong)); flint_free(divs[i].Acoeff); flint_free(divs[i].Aexp); } } void _fmpz_mpoly_mul_heap_threaded( fmpz_mpoly_t A, const fmpz * Bcoeff, const ulong * Bexp, slong Blen, const fmpz * Ccoeff, const ulong * Cexp, slong Clen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const thread_pool_handle * handles, slong num_handles) { slong i, j; slong BClen, hi; _base_t base; _div_struct * divs; _worker_arg_struct * args; slong Aalloc; slong Alen; fmpz * Acoeff; ulong * Aexp; /* bail if product of lengths overflows a word */ umul_ppmm(hi, BClen, Blen, Clen); if (hi != 0 || BClen < 0) { Alen = _fmpz_mpoly_mul_johnson(&A->coeffs, &A->exps, &A->alloc, Bcoeff, Bexp, Blen, Ccoeff, Cexp, Clen, bits, N, cmpmask); _fmpz_mpoly_set_length(A, Alen, NULL); return; } base->nthreads = num_handles + 1; base->ndivs = base->nthreads*4; /* number of divisions */ base->Bcoeff = Bcoeff; base->Bexp = Bexp; base->Blen = Blen; base->Ccoeff = Ccoeff; base->Cexp = Cexp; base->Clen = Clen; base->bits = bits; base->N = N; base->cmpmask = cmpmask; base->idx = base->ndivs - 1; /* decremented by worker threads */ base->flint_small = _fmpz_mpoly_fits_small(Bcoeff, Blen) && _fmpz_mpoly_fits_small(Ccoeff, Clen); divs = (_div_struct *) flint_malloc(base->ndivs*sizeof(_div_struct)); args = (_worker_arg_struct *) flint_malloc(base->nthreads *sizeof(_worker_arg_struct)); /* allocate space and set the boundary for each division */ FLINT_ASSERT(BClen/Blen == Clen); for (i = base->ndivs - 1; i >= 0; i--) { double d = (double)(i + 1) / (double)(base->ndivs); /* divisions decrease in size so that no worker finishes too early */ divs[i].lower = (d * d) * BClen; divs[i].lower = FLINT_MIN(divs[i].lower, BClen); divs[i].lower = FLINT_MAX(divs[i].lower, WORD(0)); divs[i].upper = divs[i].lower; divs[i].Aoffset = -WORD(1); divs[i].thread_idx = -WORD(1); divs[i].Alen = 0; if (i == base->ndivs - 1) { /* highest division writes to original poly */ divs[i].Aalloc = A->alloc; divs[i].Aexp = A->exps; divs[i].Acoeff = A->coeffs; /* must clear output coefficients before working in parallel */ for (j = 0; j < A->length; j++) _fmpz_demote(A->coeffs + j); } else { /* lower divisions write to a new worker poly */ divs[i].Aalloc = 0; divs[i].Aexp = NULL; divs[i].Acoeff = NULL; } } /* compute each chunk in parallel */ #if FLINT_USES_PTHREAD pthread_mutex_init(&base->mutex, NULL); #endif for (i = 0; i < num_handles; i++) { args[i].idx = i; args[i].base = base; args[i].divs = divs; thread_pool_wake(global_thread_pool, handles[i], 0, _fmpz_mpoly_mul_heap_threaded_worker, &args[i]); } i = num_handles; args[i].idx = i; args[i].base = base; args[i].divs = divs; _fmpz_mpoly_mul_heap_threaded_worker(&args[i]); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } /* calculate and allocate space for final answer */ i = base->ndivs - 1; Alen = divs[i].Alen; Acoeff = divs[i].Acoeff; Aexp = divs[i].Aexp; Aalloc = divs[i].Aalloc; for (i = base->ndivs - 2; i >= 0; i--) { divs[i].Aoffset = Alen; Alen += divs[i].Alen; } if (Alen > Aalloc) { Acoeff = (fmpz *) flint_realloc(Acoeff, Alen*sizeof(fmpz)); Aexp = (ulong *) flint_realloc(Aexp, Alen*N*sizeof(ulong)); Aalloc = Alen; } base->Acoeff = Acoeff; base->Aexp = Aexp; /* join answers */ for (i = 0; i < num_handles; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, _join_worker, &args[i]); } _join_worker(&args[num_handles]); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&base->mutex); #endif flint_free(args); flint_free(divs); /* we should have managed to keep coefficients past length demoted */ FLINT_ASSERT(Alen <= Aalloc); #if FLINT_WANT_ASSERT for (i = Alen; i < Aalloc; i++) { FLINT_ASSERT(!COEFF_IS_MPZ(*(Acoeff + i))); } #endif A->coeffs = Acoeff; A->exps = Aexp; A->alloc = Aalloc; A->length = Alen; } /* maxBfields gets clobbered */ void _fmpz_mpoly_mul_heap_threaded_pool_maxfields( fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong N; flint_bitcnt_t exp_bits; ulong * cmpmask; ulong * Bexp, * Cexp; int freeBexp, freeCexp; TMP_INIT; TMP_START; _fmpz_vec_add(maxBfields, maxBfields, maxCfields, ctx->minfo->nfields); exp_bits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = FLINT_MAX(exp_bits, B->bits); exp_bits = FLINT_MAX(exp_bits, C->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents are packed into same sized fields as output */ freeBexp = 0; Bexp = B->exps; if (exp_bits > B->bits) { freeBexp = 1; Bexp = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexp, exp_bits, B->exps, B->bits, B->length, ctx->minfo); } freeCexp = 0; Cexp = C->exps; if (exp_bits > C->bits) { freeCexp = 1; Cexp = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexp, exp_bits, C->exps, C->bits, C->length, ctx->minfo); } /* deal with aliasing and do multiplication */ if (A == B || A == C) { fmpz_mpoly_t T; fmpz_mpoly_init3(T, 0, exp_bits, ctx); /* algorithm more efficient if smaller poly first */ if (B->length >= C->length) { _fmpz_mpoly_mul_heap_threaded(T, C->coeffs, Cexp, C->length, B->coeffs, Bexp, B->length, exp_bits, N, cmpmask, handles, num_handles); } else { _fmpz_mpoly_mul_heap_threaded(T, B->coeffs, Bexp, B->length, C->coeffs, Cexp, C->length, exp_bits, N, cmpmask, handles, num_handles); } fmpz_mpoly_swap(T, A, ctx); fmpz_mpoly_clear(T, ctx); } else { fmpz_mpoly_fit_length_reset_bits(A, A->length, exp_bits, ctx); /* algorithm more efficient if smaller poly first */ if (B->length > C->length) { _fmpz_mpoly_mul_heap_threaded(A, C->coeffs, Cexp, C->length, B->coeffs, Bexp, B->length, exp_bits, N, cmpmask, handles, num_handles); } else { _fmpz_mpoly_mul_heap_threaded(A, B->coeffs, Bexp, B->length, C->coeffs, Cexp, C->length, exp_bits, N, cmpmask, handles, num_handles); } } if (freeBexp) flint_free(Bexp); if (freeCexp) flint_free(Cexp); TMP_END; } void fmpz_mpoly_mul_heap_threaded( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields, * maxCfields; thread_pool_handle * handles; slong num_handles; slong thread_limit = FLINT_MIN(A->length, B->length)/16; TMP_INIT; if (B->length == 0 || C->length == 0) { fmpz_mpoly_zero(A, ctx); return; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); num_handles = flint_request_threads(&handles, thread_limit); _fmpz_mpoly_mul_heap_threaded_pool_maxfields(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); flint_give_back_threads(handles, num_handles); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; } flint-3.1.3/src/fmpz_mpoly/mul_johnson.c000066400000000000000000000450701461254215100203230ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* Set poly1 to poly2*poly3 using Johnson's heap method. The function realocates its output and returns the length of the product. This version of the function assumes the exponent vectors all fit in a single word. Assumes input polys are nonzero. */ slong _fmpz_mpoly_mul_johnson1(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, ulong maskhi) { slong i, j, k; slong next_loc; slong Q_len = 0, heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * Q; mpoly_heap_t * x; fmpz * p1 = *poly1; ulong * e1 = *exp1; slong * hind; ulong exp, cy; ulong c[3], p[2]; /* for accumulating coefficients */ int first, small; TMP_INIT; TMP_START; /* whether input coeffs are small, thus output coeffs fit in three words */ small = _fmpz_mpoly_fits_small(poly2, len2) && _fmpz_mpoly_fits_small(poly3, len3); next_loc = len2 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len2 + 1)*sizeof(mpoly_heap1_s)); /* alloc array of heap nodes which can be chained together */ chain = (mpoly_heap_t *) TMP_ALLOC(len2*sizeof(mpoly_heap_t)); /* space for temporary storage of pointers to heap nodes */ Q = (slong *) TMP_ALLOC(2*len2*sizeof(slong)); /* space for heap indices */ hind = (slong *) TMP_ALLOC(len2*sizeof(slong)); for (i = 0; i < len2; i++) hind[i] = 1; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0] + exp3[0], x); hind[0] = 2*1 + 0; /* output poly index starts at -1, will be immediately updated to 0 */ k = -WORD(1); /* while heap is nonempty */ while (heap_len > 1) { /* get exponent field of heap top */ exp = heap[1].exp; /* realloc output poly ready for next product term */ k++; _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, 1); /* whether we are on first coeff product for this output exponent */ first = 1; /* set temporary coeff to zero */ c[0] = c[1] = c[2] = 0; /* while heap nonempty and contains chain with current output exponent */ while (heap_len > 1 && heap[1].exp == exp) { /* pop chain from heap */ x = _mpoly_heap_pop1(heap, &heap_len, maskhi); /* take node out of heap and put into store */ hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; /* if output coeffs will fit in three words */ if (small) { /* compute product of input poly coeffs */ if (first) { smul_ppmm(c[1], c[0], poly2[x->i], poly3[x->j]); c[2] = -(c[1] >> (FLINT_BITS - 1)); /* set output monomial */ e1[k] = exp; first = 0; } else /* addmul product of input poly coeffs */ { smul_ppmm(p[1], p[0], poly2[x->i], poly3[x->j]); add_sssaaaaaa(cy, c[1], c[0], 0, c[1], c[0], 0, p[1], p[0]); c[2] += (0 <= (slong) p[1]) ? cy : cy - 1; } /* for every node in this chain */ while ((x = x->next) != NULL) { /* addmul product of input poly coeffs */ smul_ppmm(p[1], p[0], poly2[x->i], poly3[x->j]); add_sssaaaaaa(cy, c[1], c[0], 0, c[1], c[0], 0, p[1], p[0]); c[2] += (0 <= (slong) p[1]) ? cy : cy - 1; /* take node out of heap and put into store */ hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; } } else /* output coeffs require multiprecision */ { if (first) /* compute product of input poly coeffs */ { fmpz_mul(p1 + k, poly2 + x->i, poly3 + x->j); e1[k] = exp; first = 0; } else { /* addmul product of input poly coeffs */ fmpz_addmul(p1 + k, poly2 + x->i, poly3 + x->j); } /* for each node in this chain */ while ((x = x->next) != NULL) { /* addmul product of input poly coeffs */ fmpz_addmul(p1 + k, poly2 + x->i, poly3 + x->j); /* take node out of heap and put into store */ hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; } } } /* for each node temporarily stored */ while (Q_len > 0) { /* take node from store */ j = Q[--Q_len]; i = Q[--Q_len]; /* should we go right? */ if ( (i + 1 < len2) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; _mpoly_heap_insert1(heap, exp2[x->i] + exp3[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if ( (j + 1 < len3) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] > 2*(j + 2) + 1) || (hind[i - 1] == 2*(j + 2) + 1) /* gcc should fuse */ ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; _mpoly_heap_insert1(heap, exp2[x->i] + exp3[x->j], x, &next_loc, &heap_len, maskhi); } } /* set output poly coeff from temporary accumulation, if not multiprec */ if (small) fmpz_set_signed_uiuiui(p1 + k, c[2], c[1], c[0]); if (fmpz_is_zero(p1 + k)) k--; } k++; (*poly1) = p1; (*exp1) = e1; TMP_END; return k; } /* Set poly1 to poly2*poly3 using Johnson's heap method. The function realocates its output and returns the length of the product. This version of the function assumes the exponent vectors take N words. */ slong _fmpz_mpoly_mul_johnson(fmpz ** poly1, ulong ** exp1, slong * alloc, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask) { slong i, j, k; slong next_loc; slong Q_len = 0, heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * Q; mpoly_heap_t * x; fmpz * p1 = *poly1; ulong * e1 = *exp1; ulong cy; ulong c[3], p[2]; /* for accumulating coefficients */ ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; int first, small; TMP_INIT; /* if exponent vectors fit in single word, call special version */ if (N == 1) return _fmpz_mpoly_mul_johnson1(poly1, exp1, alloc, poly2, exp2, len2, poly3, exp3, len3, cmpmask[0]); TMP_START; /* whether input coeffs are small, thus output coeffs fit in three words */ small = _fmpz_mpoly_fits_small(poly2, len2) && _fmpz_mpoly_fits_small(poly3, len3); next_loc = len2 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len2 + 1)*sizeof(mpoly_heap_s)); /* alloc array of heap nodes which can be chained together */ chain = (mpoly_heap_t *) TMP_ALLOC(len2*sizeof(mpoly_heap_t)); /* space for temporary storage of pointers to heap nodes */ Q = (slong *) TMP_ALLOC(2*len2*sizeof(slong)); /* allocate space for exponent vectors of N words */ exps = (ulong *) TMP_ALLOC(len2*N*sizeof(ulong)); /* list of pointers to allocated exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len2*sizeof(ulong *)); for (i = 0; i < len2; i++) exp_list[i] = exps + i*N; /* space for heap indices */ hind = (slong *) TMP_ALLOC(len2*sizeof(slong)); for (i = 0; i < len2; i++) hind[i] = 1; /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; if (bits <= FLINT_BITS) mpoly_monomial_add(heap[1].exp, exp2, exp3, N); else mpoly_monomial_add_mp(heap[1].exp, exp2, exp3, N); hind[0] = 2*1 + 0; /* output poly index starts at -1, will be immediately updated to 0 */ k = -WORD(1); /* while heap is nonempty */ while (heap_len > 1) { /* get pointer to exponent field of heap top */ exp = heap[1].exp; /* realloc output poly ready for next product term */ k++; _fmpz_mpoly_fit_length(&p1, &e1, alloc, k + 1, N); /* whether we are on first coeff product for this output exponent */ first = 1; /* set temporary coeff to zero */ c[0] = c[1] = c[2] = 0; /* while heap nonempty and contains chain with current output exponent */ while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)) { /* pop chain from heap and set exponent field to be reused */ exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); /* take node out of heap and put into store */ hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; /* if output coeffs will fit in three words */ if (small) { /* compute product of input poly coeffs */ if (first) { smul_ppmm(c[1], c[0], poly2[x->i], poly3[x->j]); c[2] = -(c[1] >> (FLINT_BITS - 1)); /* set output monomial */ mpoly_monomial_set(e1 + k*N, exp, N); first = 0; } else /* addmul product of input poly coeffs */ { smul_ppmm(p[1], p[0], poly2[x->i], poly3[x->j]); add_sssaaaaaa(cy, c[1], c[0], 0, c[1], c[0], 0, p[1], p[0]); c[2] += (0 <= (slong) p[1]) ? cy : cy - 1; } /* for every node in this chain */ while ((x = x->next) != NULL) { /* addmul product of input poly coeffs */ smul_ppmm(p[1], p[0], poly2[x->i], poly3[x->j]); add_sssaaaaaa(cy, c[1], c[0], 0, c[1], c[0], 0, p[1], p[0]); c[2] += (0 <= (slong) p[1]) ? cy : cy - 1; /* take node out of heap and put into store */ hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; } } else /* output coeffs require multiprecision */ { if (first) /* compute product of input poly coeffs */ { fmpz_mul(p1 + k, poly2 + x->i, poly3 + x->j); /* set output monomial */ mpoly_monomial_set(e1 + k*N, exp, N); first = 0; } else { /* addmul product of input poly coeffs */ fmpz_addmul(p1 + k, poly2 + x->i, poly3 + x->j); } /* for each node in this chain */ while ((x = x->next) != NULL) { /* addmul product of input poly coeffs */ fmpz_addmul(p1 + k, poly2 + x->i, poly3 + x->j); /* take node out of heap and put into store */ hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; } } } /* for each node temporarily stored */ while (Q_len > 0) { /* take node from store */ j = Q[--Q_len]; i = Q[--Q_len]; /* should we go right? */ if ( (i + 1 < len2) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, cmpmask)) exp_next--; } /* should we go up? */ if ( (j + 1 < len3) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] > 2*(j + 2) + 1) || (hind[i - 1] == 2*(j + 2) + 1) /* gcc should fuse */ ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, cmpmask)) exp_next--; } } /* set output poly coeff from temporary accumulation, if not multiprec */ if (small) fmpz_set_signed_uiuiui(p1 + k, c[2], c[1], c[0]); if (fmpz_is_zero(p1 + k)) k--; } k++; (*poly1) = p1; (*exp1) = e1; TMP_END; return k; } /* maxBfields gets clobbered */ void _fmpz_mpoly_mul_johnson_maxfields( fmpz_mpoly_t A, const fmpz_mpoly_t B, fmpz * maxBfields, const fmpz_mpoly_t C, fmpz * maxCfields, const fmpz_mpoly_ctx_t ctx) { slong N, Alen; flint_bitcnt_t Abits; ulong * cmpmask; ulong * Bexp, * Cexp; int freeBexp, freeCexp; TMP_INIT; TMP_START; _fmpz_vec_add(maxBfields, maxBfields, maxCfields, ctx->minfo->nfields); Abits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); Abits = FLINT_MAX(MPOLY_MIN_BITS, Abits + 1); Abits = FLINT_MAX(Abits, B->bits); Abits = FLINT_MAX(Abits, C->bits); Abits = mpoly_fix_bits(Abits, ctx->minfo); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); /* ensure input exponents are packed into same sized fields as output */ freeBexp = 0; Bexp = B->exps; if (Abits > B->bits) { freeBexp = 1; Bexp = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexp, Abits, B->exps, B->bits, B->length, ctx->minfo); } freeCexp = 0; Cexp = C->exps; if (Abits > C->bits) { freeCexp = 1; Cexp = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexp, Abits, C->exps, C->bits, C->length, ctx->minfo); } /* deal with aliasing and do multiplication */ if (A == B || A == C) { fmpz_mpoly_t T; fmpz_mpoly_init3(T, B->length + C->length, Abits, ctx); /* algorithm more efficient if smaller poly first */ if (B->length > C->length) { Alen = _fmpz_mpoly_mul_johnson(&T->coeffs, &T->exps, &T->alloc, C->coeffs, Cexp, C->length, B->coeffs, Bexp, B->length, Abits, N, cmpmask); } else { Alen = _fmpz_mpoly_mul_johnson(&T->coeffs, &T->exps, &T->alloc, B->coeffs, Bexp, B->length, C->coeffs, Cexp, C->length, Abits, N, cmpmask); } fmpz_mpoly_swap(T, A, ctx); fmpz_mpoly_clear(T, ctx); } else { fmpz_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); /* algorithm more efficient if smaller poly first */ if (B->length > C->length) { Alen = _fmpz_mpoly_mul_johnson(&A->coeffs, &A->exps, &A->alloc, C->coeffs, Cexp, C->length, B->coeffs, Bexp, B->length, Abits, N, cmpmask); } else { Alen = _fmpz_mpoly_mul_johnson(&A->coeffs, &A->exps, &A->alloc, B->coeffs, Bexp, B->length, C->coeffs, Cexp, C->length, Abits, N, cmpmask); } } if (freeBexp) flint_free(Bexp); if (freeCexp) flint_free(Cexp); _fmpz_mpoly_set_length(A, Alen, ctx); TMP_END; } void fmpz_mpoly_mul_johnson( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length == 0 || C->length == 0) { fmpz_mpoly_zero(A, ctx); return; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); _fmpz_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; } flint-3.1.3/src/fmpz_mpoly/mul_monomial.c000066400000000000000000000062711461254215100204600ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* TODO: decouple the exp/coeff alloc in fmpz_mpoly and move this to mpoly */ void fmpz_mpoly_mul_monomial( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong i, N, Blen = B->length; ulong ofmask; flint_bitcnt_t Abits; ulong * Aexps, * Bexps = B->exps, * Cexps = C->exps; fmpz Ccoeff0 = C->coeffs[0]; int freeCcoeff0 = 0, overflowed = 0; TMP_INIT; FLINT_ASSERT(C->length == 1); if (A == C) { freeCcoeff0 = 1; fmpz_init_set(&Ccoeff0, C->coeffs + 0); } if (C->exps[0] == 0 && mpoly_monomial_is_zero(C->exps, mpoly_words_per_exp(C->bits, ctx->minfo))) { fmpz_mpoly_scalar_mul_fmpz(A, B, &Ccoeff0, ctx); goto cleanup_C; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); if (A == C || Abits != C->bits) { Cexps = TMP_ARRAY_ALLOC(N, ulong); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, 1, ctx->minfo); } if (A == B) { /* inplace operation on A */ fmpz_mpoly_fit_bits(A, Abits, ctx); Bexps = Aexps = A->exps; } else { if (Abits != B->bits) { Bexps = TMP_ARRAY_ALLOC(N*Blen, ulong); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, Blen, ctx->minfo); } fmpz_mpoly_fit_length_reset_bits(A, Blen, Abits, ctx); Aexps = A->exps; } if (Abits > FLINT_BITS) { for (i = 0; i < Blen; i++) mpoly_monomial_add_mp(Aexps + N*i, Bexps + N*i, Cexps + N*0, N); for (i = 0; !overflowed && i < Blen; i++) overflowed = mpoly_monomial_overflows_mp(Aexps + N*i, N, Abits); } else { for (i = 0; i < Blen; i++) mpoly_monomial_add(Aexps + N*i, Bexps + N*i, Cexps + N*0, N); ofmask = mpoly_overflow_mask_sp(Abits); for (i = 0; !overflowed && i < Blen; i++) overflowed = mpoly_monomial_overflows(Aexps + N*i, N, ofmask); } TMP_END; /* slightly dirty: repack monomials can handle 1-bit overfown fields */ if (overflowed) { ulong * newAexps; flint_bitcnt_t newAbits = mpoly_fix_bits(Abits + 1, ctx->minfo); N = mpoly_words_per_exp(newAbits, ctx->minfo); newAexps = FLINT_ARRAY_ALLOC(N*A->alloc, ulong); mpoly_repack_monomials(newAexps, newAbits, A->exps, Abits, Blen, ctx->minfo); flint_free(A->exps); A->exps = newAexps; A->bits = newAbits; } _fmpz_vec_scalar_mul_fmpz(A->coeffs, B->coeffs, Blen, &Ccoeff0); _fmpz_mpoly_set_length(A, Blen, ctx); cleanup_C: if (freeCcoeff0) fmpz_clear(&Ccoeff0); } flint-3.1.3/src/fmpz_mpoly/neg.c000066400000000000000000000016531461254215100165400ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_neg(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { slong N; if (A != B) { N = mpoly_words_per_exp(B->bits, ctx->minfo); fmpz_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); mpn_copyi(A->exps, B->exps, N*B->length); } _fmpz_vec_neg(A->coeffs, B->coeffs, B->length); _fmpz_mpoly_set_length(A, B->length, ctx); } flint-3.1.3/src/fmpz_mpoly/pow_fmpz.c000066400000000000000000000041741461254215100176310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_pow_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t k, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields; flint_bitcnt_t exp_bits; TMP_INIT; if (fmpz_sgn(k) < 0) flint_throw(FLINT_ERROR, "Negative power in fmpz_mpoly_pow_fmpz"); if (fmpz_fits_si(k)) return fmpz_mpoly_pow_ui(A, B, fmpz_get_ui(k), ctx); /* we are raising a polynomial to an unreasonable exponent It must either be zero or a monomial with unit coefficient */ if (B->length == 0) { fmpz_mpoly_zero(A, ctx); return 1; } if (B->length != 1) return 0; if (!fmpz_is_pm1(B->coeffs + 0)) return 0; TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_fmpz(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_length(A, 1, ctx); fmpz_mpoly_fit_bits(A, exp_bits, ctx); A->bits = exp_bits; fmpz_set_si(A->coeffs + 0, (fmpz_is_one(B->coeffs + 0) || fmpz_is_even(k)) ? 1 : -1); mpoly_pack_vec_fmpz(A->exps + 0, maxBfields, exp_bits, ctx->minfo->nfields, 1); _fmpz_mpoly_set_length(A, 1, ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/fmpz_mpoly/pow_fps.c000066400000000000000000000406301461254215100174420ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017,2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* Dense algorithm (reference) for the k^th power: f = f[0] + f[1]*x + ... + f[d]*x^d g = f^k = g[0] + g[1]*x + ... + g[k*d]*x^(k*d) where i*g[i]*f[0] = sum_{0 <= j <= min(i, d)} ((k + 1)*j - i)*f[j]*g[i - j] g_[k*d] = f[d]^k for i from k*d - 1 to 0 c = 0 for j from 1 to min(d,k*d-i) c += (i + j - k*(d - j))*g[i + j]*f[d - j] end g[i] = c/((k*d - i)*f[d]) end Dense algorithm (used here) for the k^th power and (k - 1)^st power: g comes out as f^(k-1) a comes out as f^k g[(k - 1)*d] = f[d]^(k-1) a[k*d] = f[d]^k for i from k*d - 1 to 0 s = c = 0 for k from max(0, d + i - d*k) to min(d - 1, i) s += g[i - j]*f[j] if i >= d c += (i - k*j)*g[i - j]*f[j] end end c = c/((d*k - i)*f[d]) s += c*f[d] if i >= d g[i - d] = c end a[i] = s end For the sparse version, the only thing to note is that the i >= d condition is implemented as _divisibility_ of monomials and not merely a comparison. */ static slong _fmpz_mpoly_pow_fps1( fmpz_mpoly_t A, const fmpz * Fcoeffs, const ulong * Fexps, slong Flen, ulong k, ulong cmpmask, ulong ofmask) { slong i, j; slong next_loc, Qlen = 0, heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; ulong exp; slong * hind; slong * Q; mpoly_heap_t * x; fmpz * Acoeffs = A->coeffs; ulong * Aexps = A->exps; slong Alen; fmpz * Gcoeffs = NULL; ulong * Gexps; slong Galloc, Glen, Gdemote = 0; fmpz_t t1, temp1; fmpz * S, * C; int divides; TMP_INIT; TMP_START; next_loc = Flen + 4; /* something bigger than heap can ever be */ heap = TMP_ARRAY_ALLOC(Flen + 1, mpoly_heap1_s); chain = TMP_ARRAY_ALLOC(Flen, mpoly_heap_t); Q = TMP_ARRAY_ALLOC(3*Flen, slong); hind = Q + 2*Flen; /* flagged heap indices */ for (i = 0; i < Flen; i++) hind[i] = 1; fmpz_init(t1); fmpz_init(temp1); _fmpz_mpoly_fit_length(&Acoeffs, &Aexps, &A->alloc, 2, 1); Galloc = k*(Flen - 1) + 2; Gexps = FLINT_ARRAY_ALLOC(Galloc, ulong); Gcoeffs = (fmpz *) flint_calloc(Galloc, sizeof(fmpz)); Gexps[0] = Fexps[0]*(k - 1); Aexps[0] = Fexps[0]*k; fmpz_pow_ui(Gcoeffs + 0, Fcoeffs + 0, k - 1); fmpz_mul(Acoeffs + 0, Gcoeffs + 0, Fcoeffs + 0); Glen = 1; Alen = 1; x = chain + 1; x->i = 1; x->j = 0; x->next = NULL; hind[1] = 2*1 + 0; HEAP_ASSIGN(heap[1], Fexps[1] + Gexps[0], x); while (heap_len > 1) { exp = heap[1].exp; Aexps[Alen] = exp; S = Acoeffs + Alen; C = Gcoeffs + Glen; fmpz_zero(C); fmpz_zero(S); Qlen = 0; Gexps[Glen] = exp - Fexps[0]; divides = !mpoly_monomial_overflows1(Gexps[Glen], ofmask); do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { fmpz fi; slong dd, ddd; Q[Qlen++] = i = x->i; Q[Qlen++] = j = x->j; hind[i] |= 1; fi = Fcoeffs[i]; FLINT_ASSERT(j >= Gdemote); dd = (k - 1)*Fexps[i] - Gexps[j]; if (divides) { if (!COEFF_IS_MPZ(fi) && !z_mul_checked(&ddd, dd, fi)) { fmpz_addmul_si(S, Gcoeffs + j, fi); fmpz_addmul_si(C, Gcoeffs + j, ddd); } else { fmpz_mul(t1, Fcoeffs + i, Gcoeffs + j); fmpz_add(S, S, t1); fmpz_addmul_si(C, t1, dd); } } else { fmpz_addmul(S, Fcoeffs + x->i, Gcoeffs + x->j); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); FLINT_ASSERT(Qlen <= 2*Flen); while (Qlen > 0) { /* take node from store */ j = Q[--Qlen]; i = Q[--Qlen]; /* should we go right? */ if (i + 1 < Flen && hind[i + 1] == 2*j + 1) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*j + 2; FLINT_ASSERT(j >= Gdemote); _mpoly_heap_insert1(heap, Fexps[i + 1] + Gexps[j], x, &next_loc, &heap_len, cmpmask); } /* should we go up? */ if (j + 1 < Glen && hind[i] < 2*j + 4) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*j + 4; FLINT_ASSERT(j + 1 >= Gdemote); _mpoly_heap_insert1(heap, Fexps[i] + Gexps[j + 1], x, &next_loc, &heap_len, cmpmask); } } /* cleanup unused Gcoeffs */ j = hind[Flen - 1]/2 - 1; for ( ; Gdemote < j; Gdemote++) fmpz_clear(Gcoeffs + Gdemote); if (!fmpz_is_zero(C)) { if (fmpz_is_one(Fcoeffs + 0)) { fmpz_divexact_si(C, C, exp - k*Fexps[0]); fmpz_add(S, S, C); } else { fmpz_divexact_si(temp1, C, exp - k*Fexps[0]); fmpz_add(S, S, temp1); fmpz_divexact(C, temp1, Fcoeffs + 0); } if ((hind[1] & 1) != 0) { x = chain + 1; x->i = 1; x->j = Glen; x->next = NULL; hind[x->i] = 2*(Glen + 1) + 0; FLINT_ASSERT(Glen >= Gdemote); _mpoly_heap_insert1(heap, Fexps[1] + Gexps[Glen], x, &next_loc, &heap_len, cmpmask); } Glen++; if (Glen >= Galloc) { Gexps = FLINT_ARRAY_REALLOC(Gexps, 2*Galloc, ulong); Gcoeffs = FLINT_ARRAY_REALLOC(Gcoeffs, 2*Galloc, fmpz); flint_mpn_zero(Gcoeffs + Galloc, Galloc); Galloc *= 2; } } Alen += !fmpz_is_zero(S); _fmpz_mpoly_fit_length(&Acoeffs, &Aexps, &A->alloc, Alen + 1, 1); } A->coeffs = Acoeffs; A->exps = Aexps; fmpz_clear(t1); fmpz_clear(temp1); for ( ; Gdemote < Galloc; Gdemote++) fmpz_clear(Gcoeffs + Gdemote); flint_free(Gcoeffs); flint_free(Gexps); TMP_END; return Alen; } static slong _fmpz_mpoly_pow_fps( fmpz_mpoly_t A, const fmpz * Fcoeffs, const ulong * Fexps, slong Flen, ulong k, slong N, const ulong * cmpmask) { flint_bitcnt_t bits = A->bits; ulong ofmask = (bits > FLINT_BITS) ? 0 : mpoly_overflow_mask_sp(bits); slong i, j, exp_next; slong next_loc, heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * Q; slong Qlen = 0; slong * hind; mpoly_heap_t * x; fmpz * Acoeffs = A->coeffs; ulong * Aexps = A->exps; slong Alen; fmpz * Gcoeffs; slong Galloc, Glen, Gdemote = 0; ulong * Gexps; ulong * fik, * exps; ulong ** exp_list; ulong * temp2; fmpz_t t1, t2, C; int divides; TMP_INIT; if (N == 1) return _fmpz_mpoly_pow_fps1(A, Fcoeffs, Fexps, Flen, k, cmpmask[0], ofmask); TMP_START; next_loc = Flen + 4; /* something bigger than heap can ever be */ heap = TMP_ARRAY_ALLOC(Flen + 1, mpoly_heap_s); chain = TMP_ARRAY_ALLOC(Flen, mpoly_heap_t); exp_list = TMP_ARRAY_ALLOC((Flen + 1), ulong *); exps = TMP_ARRAY_ALLOC(N*(Flen + 1) + N*Flen + N, ulong); fik = exps + N*(Flen + 1); temp2 = fik + N*Flen; Q = TMP_ARRAY_ALLOC(3*Flen, slong); hind = Q + 2*Flen; /* flagged heap indices */ for (i = 0; i < Flen; i++) mpoly_monomial_mul_ui_mp(fik + i*N, Fexps + i*N, N, k - 1); for (i = 0; i < Flen; i++) hind[i] = 1; exp_next = 0; for (i = 0; i < Flen + 1; i++) exp_list[i] = exps + N*i; fmpz_init(t1); fmpz_init(t2); fmpz_init(C); _fmpz_mpoly_fit_length(&Acoeffs, &Aexps, &A->alloc, 2, N); Galloc = (k - 1)*Flen + 2; Gexps = (ulong *) flint_malloc(Galloc*sizeof(ulong)*N); Gcoeffs = (fmpz *) flint_calloc(Galloc, sizeof(fmpz)); mpoly_monomial_mul_ui_mp(Gexps + 0, Fexps + 0, N, k - 1); mpoly_monomial_mul_ui_mp(Aexps + 0, Fexps + 0, N, k); fmpz_pow_ui(Gcoeffs + 0, Fcoeffs + 0, k - 1); fmpz_mul(Acoeffs + 0, Gcoeffs + 0, Fcoeffs + 0); Glen = 1; Alen = 1; hind[1] = 2*1 + 0; x = chain + 1; x->i = 1; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_add_mp(heap[1].exp, Fexps + N, Gexps + 0, N); while (heap_len > 1) { fmpz * const S = Acoeffs + Alen; mpoly_monomial_set(Aexps + N*Alen, heap[1].exp, N); mpoly_monomial_sub_mp(Gexps + N*Glen, Aexps + N*Alen, Fexps + 0, N); if (bits > FLINT_BITS) divides = !mpoly_monomial_overflows_mp(Gexps + N*Glen, N, bits); else divides = !mpoly_monomial_overflows(Gexps + N*Glen, N, ofmask); fmpz_zero(C); fmpz_zero(S); Qlen = 0; while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, Aexps + N*Alen, N)) { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { Q[Qlen++] = i = x->i; Q[Qlen++] = j = x->j; hind[i] |= 1; FLINT_ASSERT(j >= Gdemote); fmpz_mul(t1, Fcoeffs + i, Gcoeffs + j); fmpz_add(S, S, t1); if (divides) { mpn_sub_n(temp2, fik + N*i, Gexps + N*j, N); fmpz_set_signed_ui_array(t2, temp2, N); fmpz_addmul(C, t1, t2); } } while ((x = x->next) != NULL); } FLINT_ASSERT(Qlen <= 2*Flen); while (Qlen > 0) { /* take node from store */ j = Q[--Qlen]; i = Q[--Qlen]; /* should we go right? */ if (i + 1 < Flen && hind[i + 1] == 2*j + 1) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*j + 2; FLINT_ASSERT(j >= Gdemote); mpoly_monomial_add_mp(exp_list[exp_next], Fexps + N*(i + 1), Gexps + N*j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 < Glen && hind[i] < 2*j + 4) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*j + 4; FLINT_ASSERT(j + 1 >= Gdemote); mpoly_monomial_add_mp(exp_list[exp_next], Fexps + N*i, Gexps + N*(j + 1), N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } /* cleanup unused Gcoeffs */ j = hind[Flen - 1]/2 - 1; for ( ; Gdemote < j; Gdemote++) fmpz_clear(Gcoeffs + Gdemote); if (!fmpz_is_zero(C)) { mpoly_monomial_mul_ui_mp(temp2, Fexps + 0, N, k); mpn_sub_n(temp2, Aexps + N*Alen, temp2, N); fmpz_set_signed_ui_array(t2, temp2, N); if (fmpz_is_one(Fcoeffs + 0)) { fmpz_divexact(Gcoeffs + Glen, C, t2); fmpz_add(S, S, Gcoeffs + Glen); } else { fmpz_divexact(t1, C, t2); fmpz_add(S, S, t1); fmpz_divexact(Gcoeffs + Glen, t1, Fcoeffs + 0); } if ((hind[1] & 1) != 0) { x = chain + 1; x->i = 1; x->j = Glen; x->next = NULL; hind[x->i] = 2*(Glen + 1) + 0; FLINT_ASSERT(Glen >= Gdemote); mpoly_monomial_add_mp(exp_list[exp_next], Fexps + N, Gexps + N*Glen, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } Glen++; if (Glen >= Galloc) { Gexps = FLINT_ARRAY_REALLOC(Gexps, 2*N*Galloc, ulong); Gcoeffs = FLINT_ARRAY_REALLOC(Gcoeffs, 2*Galloc, fmpz); flint_mpn_zero(Gcoeffs + Galloc, Galloc); Galloc *= 2; } } Alen += !fmpz_is_zero(Acoeffs + Alen); _fmpz_mpoly_fit_length(&Acoeffs, &Aexps, &A->alloc, Alen + 1, N); } A->coeffs = Acoeffs; A->exps = Aexps; fmpz_clear(t1); fmpz_clear(t2); fmpz_clear(C); for ( ; Gdemote < Galloc; Gdemote++) fmpz_clear(Gcoeffs + Gdemote); flint_free(Gcoeffs); flint_free(Gexps); TMP_END; return Alen; } void fmpz_mpoly_pow_fps(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx) { slong i, N, len; fmpz * maxBfields; flint_bitcnt_t Abits; ulong * cmpmask; ulong * Bexps; int freeBexps; TMP_INIT; FLINT_ASSERT(k >= 2); FLINT_ASSERT(B->length > 0); TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_ui(maxBfields, maxBfields, ctx->minfo->nfields, k); Abits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); Abits = FLINT_MAX(MPOLY_MIN_BITS, Abits + 1); Abits = FLINT_MAX(Abits, B->bits); Abits = mpoly_fix_bits(Abits, ctx->minfo); N = mpoly_words_per_exp(Abits, ctx->minfo); if (B->length == 1) { /* powering a monomial */ fmpz_mpoly_fit_length_reset_bits(A, 1, Abits, ctx); if (B->bits == Abits && B != A) mpoly_monomial_mul_ui_mp(A->exps, B->exps, N, k); else mpoly_pack_vec_fmpz(A->exps, maxBfields, Abits, ctx->minfo->nfields, 1); fmpz_pow_ui(A->coeffs + 0, B->coeffs + 0, k); len = 1; goto cleanup; } freeBexps = 0; Bexps = B->exps; if (Abits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (A == B) { fmpz_mpoly_t T; fmpz_mpoly_init3(T, k*(B->length - 1) + 1, Abits, ctx); len = _fmpz_mpoly_pow_fps(T, B->coeffs, Bexps, B->length, k, N, cmpmask); fmpz_mpoly_swap(T, A, ctx); fmpz_mpoly_clear(T, ctx); } else { fmpz_mpoly_fit_length_reset_bits(A, k*(B->length - 1) + 1, Abits, ctx); len = _fmpz_mpoly_pow_fps(A, B->coeffs, Bexps, B->length, k, N, cmpmask); } if (freeBexps) flint_free(Bexps); cleanup: for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); _fmpz_mpoly_set_length(A, len, ctx); TMP_END; } flint-3.1.3/src/fmpz_mpoly/pow_ui.c000066400000000000000000000022151461254215100172640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int fmpz_mpoly_pow_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx) { if (B->length == 0) { fmpz_mpoly_set_ui(A, k == 0, ctx); return 1; } else if (k <= 2) { if (k == 2) { fmpz_mpoly_mul(A, B, B, ctx); } else if (k == 1) { fmpz_mpoly_set(A, B, ctx); } else { fmpz_mpoly_one(A, ctx); } return 1; } else { ulong limit = (ulong)(WORD_MAX)/(ulong)(2*sizeof(fmpz)); if (B->length > 1 && k > limit/(ulong)(B->length - 1)) return 0; fmpz_mpoly_pow_fps(A, B, k, ctx); return 1; } } flint-3.1.3/src/fmpz_mpoly/primitive_part.c000066400000000000000000000017451461254215100210270ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mpoly.h" void fmpz_mpoly_primitive_part(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx) { if (res != f) fmpz_mpoly_set(res, f, ctx); if (fmpz_mpoly_is_zero(res, ctx)) return; if (fmpz_sgn(res->coeffs) < 0) fmpz_mpoly_neg(res, res, ctx); if (!fmpz_is_one(res->coeffs)) { fmpz_t c; fmpz_init(c); _fmpz_vec_content(c, res->coeffs, res->length); if (!fmpz_is_one(c)) fmpz_mpoly_scalar_divexact_fmpz(res, res, c, ctx); fmpz_clear(c); } } flint-3.1.3/src/fmpz_mpoly/profile/000077500000000000000000000000001461254215100172565ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly/profile/p-divides.c000066400000000000000000000170551461254215100213160ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* usage: likwid-setFrequencies -g performance make profile MOD=fmpz_mpoly && ./build/fmpz_mpoly/profile/p-divides 4 sparse 12 12 p-divides nthreads sparse m n: run the sparse benchmark on nthreads with powers (m, n) divides((1+x+y+2*z^2+3*t^3+5*u^5)^m*(1+u+t+2*z^2+3*y^3+5*x^5)^n, (1+u+t+2*z^2+3*y^3+5*x^5)^n) */ #include #include #include "profiler.h" #include "fmpz_mpoly.h" #define CALCULATE_MACHINE_EFFICIENCY 0 int * cpu_affinities; #if CALCULATE_MACHINE_EFFICIENCY typedef struct _worker_arg_struct { fmpz_mpoly_t Q; const fmpz_mpoly_struct * A, * B; const fmpz_mpoly_ctx_struct * ctx; } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void worker_divides(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; fmpz_mpoly_divides_threaded(W->Q, W->A, W->B, W->ctx, 1); } #endif void profile_divides( const fmpz_mpoly_t realQ, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, slong max_threads) { fmpz_mpoly_t Q; timeit_t timer; slong num_threads; slong serial_time; flint_set_num_threads(1); fmpz_mpoly_init(Q, ctx); timeit_start(timer); fmpz_mpoly_divides(Q, A, B, ctx); timeit_stop(timer); serial_time = FLINT_MAX(WORD(1), timer->wall); flint_printf("serial time: %wd\n", serial_time); if (!fmpz_mpoly_equal(Q, realQ, ctx)) { printf("quotient wrong\n"); flint_abort(); } for (num_threads = 2; num_threads <= max_threads; num_threads++) { slong parallel_time; double parallel_efficiency; #if CALCULATE_MACHINE_EFFICIENCY thread_pool_handle * handles; worker_arg_struct * worker_args; slong i; double machine_efficiency; slong num_workers; #endif flint_set_num_threads(num_threads); flint_set_thread_affinity(cpu_affinities, num_threads); #if CALCULATE_MACHINE_EFFICIENCY handles = (thread_pool_handle *) flint_malloc((num_threads - 1)*sizeof(thread_pool_handle)); num_workers = thread_pool_request(global_thread_pool, handles, num_threads - 1); worker_args = (worker_arg_struct *) flint_malloc((num_workers + 1)*sizeof(worker_arg_t)); timeit_start(timer); for (i = 0; i <= num_workers; i++) { fmpz_mpoly_init((worker_args + i)->Q, ctx); (worker_args + i)->A = A; (worker_args + i)->B = B; (worker_args + i)->ctx = ctx; if (i < num_workers) { thread_pool_wake(global_thread_pool, handles[i], 0, worker_divides, worker_args + i); } else { worker_divides(worker_args + i); } } for (i = 0; i < num_workers; i++) { thread_pool_wait(global_thread_pool, handles[i]); } timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); for (i = 0; i <= num_workers; i++) { if (!fmpz_mpoly_equal((worker_args + i)->Q, realQ, ctx)) { printf("quotient wrong\n"); flint_abort(); } fmpz_mpoly_clear((worker_args + i)->Q, ctx); if (i < num_workers) { thread_pool_give_back(global_thread_pool, handles[i]); } } flint_free(worker_args); flint_free(handles); machine_efficiency = (double)(serial_time)/(double)(parallel_time); #endif fmpz_mpoly_clear(Q, ctx); fmpz_mpoly_init(Q, ctx); timeit_start(timer); fmpz_mpoly_divides(Q, A, B, ctx); timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); if (!fmpz_mpoly_equal(Q, realQ, ctx)) { printf("quotient wrong\n"); flint_abort(); } parallel_efficiency = (double)(serial_time)/(double)(parallel_time)/(double)(num_threads); #if CALCULATE_MACHINE_EFFICIENCY flint_printf("parallel %wd time: %wd, efficiency %f (machine %f)\n", num_threads, parallel_time, parallel_efficiency, machine_efficiency); #else flint_printf("parallel %wd time: %wd, efficiency %f\n", num_threads, parallel_time, parallel_efficiency); #endif } fmpz_mpoly_clear(Q, ctx); } int main(int argc, char *argv[]) { slong i, m, n, max_threads; const slong thread_limit = 64; const char * name; cpu_affinities = flint_malloc(thread_limit*sizeof(int)); for (i = 0; i < thread_limit; i++) cpu_affinities[i] = i; if (argc == 5) { max_threads = atoi(argv[1]); max_threads = FLINT_MIN(max_threads, thread_limit); max_threads = FLINT_MAX(max_threads, WORD(1)); name = argv[2]; m = atoi(argv[3]); n = atoi(argv[4]); } else { printf(" usage: p-divides nthreads {dense|sparse} m n\n"); printf("running: p-divides 4 sparse 12 12\n"); max_threads = 4; name = "sparse"; m = 12; n = 12; } m = FLINT_MIN(m, WORD(30)); m = FLINT_MAX(m, WORD(5)); n = FLINT_MIN(n, WORD(30)); n = FLINT_MAX(n, WORD(5)); flint_printf("setting up fmpz_mpoly %s divides ... ", name); if (strcmp(name, "dense") == 0) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, A, B, Q; const char * vars[] = {"x", "y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(A, ctx); fmpz_mpoly_init(B, ctx); fmpz_mpoly_init(Q, ctx); fmpz_mpoly_set_str_pretty(a, "1 + x + y + z + t", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x + y + z + t", vars, ctx); fmpz_mpoly_pow_ui(Q, a, m, ctx); fmpz_mpoly_pow_ui(B, b, n, ctx); fmpz_mpoly_mul(A, Q, B, ctx); flint_printf("starting dense divides (%wu, %wd):\n", m, n); profile_divides(Q, A, B, ctx, max_threads); fmpz_mpoly_clear(Q, ctx); fmpz_mpoly_clear(B, ctx); fmpz_mpoly_clear(A, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } else { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, A, B, Q; const char * vars[] = {"x", "y", "z", "t", "u"}; fmpz_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(A, ctx); fmpz_mpoly_init(B, ctx); fmpz_mpoly_init(Q, ctx); fmpz_mpoly_set_str_pretty(a, "1 + x + y + 2*z^2 + 3*t^3 + 5*u^5", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + u + t + 2*z^2 + 3*y^3 + 5*x^5", vars, ctx); fmpz_mpoly_pow_ui(Q, a, m, ctx); fmpz_mpoly_pow_ui(B, b, n, ctx); fmpz_mpoly_mul(A, Q, B, ctx); flint_printf("starting sparse divides (%wu, %wd):\n", m, n); profile_divides(Q, A, B, ctx, max_threads); fmpz_mpoly_clear(Q, ctx); fmpz_mpoly_clear(B, ctx); fmpz_mpoly_clear(A, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } flint_free(cpu_affinities); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz_mpoly/profile/p-gcd.c000066400000000000000000000220051461254215100204130ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* usage likwid-setFrequencies -c S0 -g powersave likwid-setFrequencies -g performance make profile MOD=fmpz_mpoly && ./build/fmpz_mpoly/profile/p-gcd 4 sparse 7 5 4 8 p-gcd nthreads sparse m1 n1 m2 n2: run the sparse benchmark on nthreads with powers (m1, n1) and (m2, n2) */ #include #include #include "profiler.h" #include "fmpz.h" #include "fmpz_mpoly.h" #define CALCULATE_MACHINE_EFFICIENCY 0 int * cpu_affinities; #if CALCULATE_MACHINE_EFFICIENCY typedef struct _worker_arg_struct { fmpz_mpoly_t G; const fmpz_mpoly_struct * A, * B; const fmpz_mpoly_ctx_struct * ctx; } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void worker_gcd(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; fmpz_mpoly_gcd_threaded(W->G, W->A, W->B, W->ctx, 1); } #endif void profile_gcd( const fmpz_mpoly_t realG, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, slong max_threads) { fmpz_mpoly_t G; timeit_t timer; slong num_threads; slong serial_time; flint_set_num_threads(1); flint_set_thread_affinity(cpu_affinities, 1); fmpz_mpoly_init(G, ctx); timeit_start(timer); fmpz_mpoly_gcd(G, A, B, ctx); timeit_stop(timer); serial_time = FLINT_MAX(WORD(1), timer->wall); flint_printf("serial time: %wd\n", serial_time); if (!fmpz_mpoly_equal(G, realG, ctx)) { printf("gcd wrong\n"); flint_abort(); } for (num_threads = 2; num_threads <= max_threads; num_threads++) { slong parallel_time; double parallel_efficiency; #if CALCULATE_MACHINE_EFFICIENCY thread_pool_handle * handles; worker_arg_struct * worker_args; slong i; double machine_efficiency; slong num_workers; #endif flint_set_num_threads(num_threads); flint_set_thread_affinity(cpu_affinities, num_threads); #if CALCULATE_MACHINE_EFFICIENCY handles = (thread_pool_handle *) flint_malloc((num_threads - 1)*sizeof(thread_pool_handle)); num_workers = thread_pool_request(global_thread_pool, handles, num_threads - 1); worker_args = (worker_arg_struct *) flint_malloc((num_workers + 1)*sizeof(worker_arg_t)); timeit_start(timer); for (i = 0; i <= num_workers; i++) { fmpz_mpoly_init((worker_args + i)->G, ctx); (worker_args + i)->A = A; (worker_args + i)->B = B; (worker_args + i)->ctx = ctx; if (i < num_workers) { thread_pool_wake(global_thread_pool, handles[i], 0, worker_gcd, worker_args + i); } else { worker_gcd(worker_args + i); } } for (i = 0; i < num_workers; i++) { thread_pool_wait(global_thread_pool, handles[i]); } timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); for (i = 0; i <= num_workers; i++) { if (!fmpz_mpoly_equal((worker_args + i)->G, realG, ctx)) { printf("gcd wrong\n"); flint_abort(); } fmpz_mpoly_clear((worker_args + i)->G, ctx); if (i < num_workers) { thread_pool_give_back(global_thread_pool, handles[i]); } } flint_free(worker_args); flint_free(handles); machine_efficiency = (double)(serial_time)/(double)(parallel_time); #endif fmpz_mpoly_clear(G, ctx); fmpz_mpoly_init(G, ctx); timeit_start(timer); fmpz_mpoly_gcd(G, A, B, ctx); timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); if (!fmpz_mpoly_equal(G, realG, ctx)) { printf("gcd wrong\n"); flint_abort(); } parallel_efficiency = (double)(serial_time)/(double)(parallel_time)/(double)(num_threads); #if CALCULATE_MACHINE_EFFICIENCY flint_printf("parallel %wd time: %wd, efficiency %f (machine %f)\n", num_threads, parallel_time, parallel_efficiency, machine_efficiency); #else flint_printf("parallel %wd time: %wd, efficiency %f\n", num_threads, parallel_time, parallel_efficiency); #endif } fmpz_mpoly_clear(G, ctx); } void profile_power(const char * astr, const char * bstr, slong nvars, const char * name, slong m1, slong n1, slong m2, slong n2, slong max_threads) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, t, A, B, G; const char * vars[] = {"x", "y", "z", "t", "u", "v" , "w"}; FLINT_ASSERT(nvars <= 7); fmpz_mpoly_ctx_init(ctx, nvars, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(A, ctx); fmpz_mpoly_init(B, ctx); fmpz_mpoly_init(G, ctx); fmpz_mpoly_set_str_pretty(a, astr, vars, ctx); fmpz_mpoly_set_str_pretty(b, bstr, vars, ctx); fmpz_mpoly_pow_ui(A, a, m1, ctx); fmpz_mpoly_pow_ui(t, b, n1, ctx); fmpz_mpoly_mul(A, A, t, ctx); fmpz_mpoly_pow_ui(B, a, m2, ctx); fmpz_mpoly_pow_ui(t, b, n2, ctx); fmpz_mpoly_mul(B, B, t, ctx); fmpz_mpoly_pow_ui(G, a, FLINT_MIN(m1, m2), ctx); fmpz_mpoly_pow_ui(t, b, FLINT_MIN(n1, n2), ctx); fmpz_mpoly_mul(G, G, t, ctx); if (fmpz_sgn(G->coeffs + 0) < 0) fmpz_mpoly_neg(G, G, ctx); flint_printf("starting %s gcd (%wu, %wd), (%wd, %wd):\n", name, m1, n1, m2, n2); profile_gcd(G, A, B, ctx, max_threads); fmpz_mpoly_clear(G, ctx); fmpz_mpoly_clear(B, ctx); fmpz_mpoly_clear(A, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } int main(int argc, char *argv[]) { slong i, m1, n1, m2, n2, max_threads; const slong thread_limit = 64; const char * name; cpu_affinities = flint_malloc(thread_limit*sizeof(int)); for (i = 0; i < thread_limit; i++) cpu_affinities[i] = i; if (argc == 7) { max_threads = atoi(argv[1]); max_threads = FLINT_MIN(max_threads, thread_limit); max_threads = FLINT_MAX(max_threads, WORD(1)); name = argv[2]; m1 = atoi(argv[3]); n1 = atoi(argv[4]); m2 = atoi(argv[5]); n2 = atoi(argv[6]); } else { printf(" usage: p-gcd nthreads sparse m1 n1 m2 n2\n"); printf("running: p-gcd 4 sparse 7 5 4 8 \n"); max_threads = 4; name = "sparse"; m1 = 7; n1 = 5; m2 = 4; n2 = 8; } flint_printf("setting up fmpz_mpoly %s gcd ... ", name); if (strcmp(name, "dense2") == 0) { profile_power("1 + x + 2*y + x*y", "1 + 2*x + y + x*y", 2, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "semisparse2") == 0) { profile_power("1 + x + 2*y", "1 + x + y", 2, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "dense3") == 0) { profile_power("1 + x + y + z + x*y + x*z", "1 + x + y + z + y*z + y*z", 3, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "semisparse3") == 0) { profile_power("1 + 2*x + 3*y - z", "1 + x + y + z", 3, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "sparse3") == 0) { profile_power("1 + x^2 + y^20 + z^33", "1 + x^21 + y^11 + z^7", 3, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "semisparse4") == 0) { profile_power("1 + 2*x + 3*y - z - 2*t", "1 + x + y + z + t", 4, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "boldsparse4") == 0) { profile_power("1 + x + y^2 + z^3 + t^4", "1 + x^4 + y^3 + z^2 + t", 4, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "semisparse5") == 0) { profile_power("1 + 2*x + 3*y - z - 2*t - 3*u", "1 + x + y + z + t + u", 5, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "boldsparse5") == 0) { profile_power("1 + x^1 + y^2 + z^3 + t^4 + u^5", "1 + x^5 + y^4 + z^3 + t^2 + u^1", 5, name, m1, n1, m2, n2, max_threads); } else if (strcmp(name, "heavysparse5") == 0) { profile_power("1 + x^1 + y^2 + z^6 + t^4 + u^9", "1 + x^9 + y^4 + z^3 + t^7 + u^1", 5, name, m1, n1, m2, n2, max_threads); } else { profile_power("1 + x^1 + y^5 + z^4 + t^40 + u^50", "1 + x^9 + y^2 + z^11 + t^7 + u^27", 5, "sparse", m1, n1, m2, n2, max_threads); } flint_free(cpu_affinities); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz_mpoly/profile/p-mul.c000066400000000000000000000160101461254215100204520ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* usage: likwid-setFrequencies -g performance make profile MOD=fmpz_mpoly && ./build/fmpz_mpoly/profile/p-mul 4 sparse 12 12 p-mul nthreads sparse m n: run the sparse benchmark on nthreads with powers (m, n) mul((1+x+y+2*z^2+3*t^3+5*u^5)^m, (1+u+t+2*z^2+3*y^3+5*x^5)^n) p-mul nthreads dense m n: run the dense benchmark on nthreads with powers (m, n) mul((1+x+y+z+t)^m, (1+x+y+z+t)^n) */ #include #include #include "profiler.h" #include "fmpz_mpoly.h" #define CALCULATE_MACHINE_EFFICIENCY 0 int * cpu_affinities; #if CALCULATE_MACHINE_EFFICIENCY typedef struct _worker_arg_struct { fmpz_mpoly_t G; const fmpz_mpoly_struct * A, * B; const fmpz_mpoly_ctx_struct * ctx; } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void worker_mul(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; fmpz_mpoly_mul_threaded(W->G, W->A, W->B, W->ctx, 1); } #endif void profile_mul( const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, slong max_threads) { fmpz_mpoly_t G; timeit_t timer; slong num_threads; slong serial_time; flint_set_num_threads(1); flint_set_thread_affinity(cpu_affinities, 1); fmpz_mpoly_init(G, ctx); timeit_start(timer); fmpz_mpoly_mul(G, A, B, ctx); timeit_stop(timer); serial_time = FLINT_MAX(WORD(1), timer->wall); flint_printf(" serial time: %wd\n", serial_time); for (num_threads = 2; num_threads <= max_threads; num_threads++) { slong parallel_time; double parallel_efficiency; #if CALCULATE_MACHINE_EFFICIENCY thread_pool_handle * handles; worker_arg_struct * worker_args; slong i; double machine_efficiency; slong num_workers; #endif flint_set_num_threads(num_threads); flint_set_thread_affinity(cpu_affinities, num_threads); #if CALCULATE_MACHINE_EFFICIENCY handles = (thread_pool_handle *) flint_malloc((num_threads - 1)*sizeof(thread_pool_handle)); num_workers = thread_pool_request(global_thread_pool, handles, num_threads - 1); worker_args = (worker_arg_struct *) flint_malloc((num_workers + 1)*sizeof(worker_arg_t)); timeit_start(timer); for (i = 0; i <= num_workers; i++) { fmpz_mpoly_init((worker_args + i)->G, ctx); (worker_args + i)->A = A; (worker_args + i)->B = B; (worker_args + i)->ctx = ctx; if (i < num_workers) { thread_pool_wake(global_thread_pool, handles[i], 0, worker_mul, worker_args + i); } else { worker_mul(worker_args + i); } } for (i = 0; i < num_workers; i++) { thread_pool_wait(global_thread_pool, handles[i]); } timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); for (i = 0; i <= num_workers; i++) { fmpz_mpoly_clear((worker_args + i)->G, ctx); if (i < num_workers) { thread_pool_give_back(global_thread_pool, handles[i]); } } flint_free(worker_args); flint_free(handles); machine_efficiency = (double)(serial_time)/(double)(parallel_time); #endif /* find parallel efficiency */ fmpz_mpoly_clear(G, ctx); fmpz_mpoly_init(G, ctx); timeit_start(timer); fmpz_mpoly_mul(G, A, B, ctx); timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); parallel_efficiency = (double)(serial_time)/(double)(parallel_time)/(double)(num_threads); #if CALCULATE_MACHINE_EFFICIENCY flint_printf("parallel %wd time: %wd, efficiency %f (machine %f)\n", num_threads, parallel_time, parallel_efficiency, machine_efficiency); #else flint_printf("parallel %wd time: %wd, efficiency %f\n", num_threads, parallel_time, parallel_efficiency); #endif } fmpz_mpoly_clear(G, ctx); } int main(int argc, char *argv[]) { slong i, m, n, max_threads; const slong thread_limit = 64; const char * name; cpu_affinities = flint_malloc(thread_limit*sizeof(int)); for (i = 0; i < thread_limit; i++) cpu_affinities[i] = i; if (argc == 5) { max_threads = atoi(argv[1]); max_threads = FLINT_MIN(max_threads, thread_limit); max_threads = FLINT_MAX(max_threads, WORD(1)); name = argv[2]; m = atoi(argv[3]); n = atoi(argv[4]); } else { printf(" usage: p-mul nthreads {dense|sparse} m n\n"); printf("running: p-mul 4 sparse 12 12\n"); max_threads = 4; name = "sparse"; m = 12; n = 12; } m = FLINT_MIN(m, WORD(30)); m = FLINT_MAX(m, WORD(5)); n = FLINT_MIN(n, WORD(30)); n = FLINT_MAX(n, WORD(5)); flint_printf("setting up fmpz_mpoly %s mul ... ", name); if (strcmp(name, "dense") == 0) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, A, B; const char * vars[] = {"x", "y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(A, ctx); fmpz_mpoly_init(B, ctx); fmpz_mpoly_set_str_pretty(a, "1 + x + y + z + t", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x + y + z + t", vars, ctx); fmpz_mpoly_pow_ui(A, a, m, ctx); fmpz_mpoly_pow_ui(B, b, n, ctx); flint_printf("starting dense mul (%wu, %wd):\n", m, n); profile_mul(A, B, ctx, max_threads); fmpz_mpoly_clear(B, ctx); fmpz_mpoly_clear(A, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } else /* "sparse" */ { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, A, B; const char * vars[] = {"x", "y", "z", "t", "u"}; fmpz_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(A, ctx); fmpz_mpoly_init(B, ctx); fmpz_mpoly_set_str_pretty(a, "1 + x + y + 2*z^2 + 3*t^3 + 5*u^5", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + u + t + 2*z^2 + 3*y^3 + 5*x^5", vars, ctx); fmpz_mpoly_pow_ui(A, a, m, ctx); fmpz_mpoly_pow_ui(B, b, n, ctx); flint_printf("starting sparse mul (%wu, %wd):\n", m, n); profile_mul(A, B, ctx, max_threads); fmpz_mpoly_clear(B, ctx); fmpz_mpoly_clear(A, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } flint_free(cpu_affinities); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz_mpoly/profile/p-sqrt.c000066400000000000000000000066201461254215100206540ustar00rootroot00000000000000/* Copyright 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #include "profiler.h" int iter_list[21] = {0, 3000000, 500000, 50000, 10000, 3000, 1000, 400, 100, 50, 30, 20, 10, 5, 2, 1, 1, 1, 1, 1, 1}; int main(void) { fmpz_mpoly_t f, g, h, k; timeit_t timer; slong iters, j, n; fmpz_mpoly_ctx_t ctx; const char * vars[] = {"x", "y", "z", "t", "u"}; fmpz_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)", vars, ctx); printf("Timing sqrt(p^2) where p = (1+x+y+2z^2+3t^3+5u^5)^n\n\n"); printf("LEX ordering\n\n"); for (n = 1; n <= 20; n++) { fmpz_mpoly_pow_ui(k, f, n, ctx); fmpz_mpoly_pow_ui(g, f, 2*n, ctx); iters = iter_list[n]; timeit_start(timer); for (j = 0; j < iters; j++) fmpz_mpoly_sqrt(h, g, ctx); timeit_stop(timer); if (!fmpz_mpoly_equal(h, k, ctx)) { printf("ERROR\n"); flint_abort(); } flint_printf("n = %wd: %.10lf s", n, (((double)timer->wall)/iters)/1000); fflush(stdout); timeit_start(timer); for (j = 0; j < iters; j++) fmpz_mpoly_sqrt_heap(h, g, ctx, 0); timeit_stop(timer); if (!fmpz_mpoly_equal(h, k, ctx)) { printf("ERROR\n"); flint_abort(); } flint_printf(" unchecked %.10lf s\n", n, (((double)timer->wall)/iters)/1000); } fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); fmpz_mpoly_ctx_init(ctx, 5, ORD_DEGREVLEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)", vars, ctx); printf("Timing sqrt(p^2) where p = (1+x+y+2z^2+3t^3+5u^5)^n\n\n"); printf("DEGREVLEX ordering:\n\n"); for (n = 1; n <= 20; n++) { fmpz_mpoly_pow_ui(k, f, n, ctx); fmpz_mpoly_pow_ui(g, f, 2*n, ctx); iters = iter_list[n]; timeit_start(timer); for (j = 0; j < iters; j++) fmpz_mpoly_sqrt(h, g, ctx); timeit_stop(timer); if (!fmpz_mpoly_equal(h, k, ctx)) { printf("ERROR\n"); flint_abort(); } flint_printf("n = %wd: %.10lf s", n, (((double)timer->wall)/iters)/1000); fflush(stdout); timeit_start(timer); for (j = 0; j < iters; j++) fmpz_mpoly_sqrt_heap(h, g, ctx, 0); timeit_stop(timer); if (!fmpz_mpoly_equal(h, k, ctx)) { printf("ERROR\n"); flint_abort(); } flint_printf(" unchecked %.10lf s\n", n, (((double)timer->wall)/iters)/1000); } fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); return 0; } flint-3.1.3/src/fmpz_mpoly/profile/p-univar.c000066400000000000000000000220051461254215100211620ustar00rootroot00000000000000/* Copyright 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz_poly.h" #include "fmpz_mpoly.h" void run_cmp( fmpz_mpoly_struct * mpolys, fmpz_poly_struct * polys, fmpz_mpoly_struct * mres, fmpz_poly_struct * res, slong npolys, const fmpz_mpoly_ctx_t ctx, void (*f)(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t), void (*g)(fmpz_poly_t, const fmpz_poly_t, const fmpz_poly_t)) { slong i, j, k; slong nreps = 100; timeit_t timer; for (j = 0; j < 2; j++) { timeit_start(timer); for (k = 0; k < nreps; k++) for (i = 1; i < npolys; i++) f(mres + i, mpolys + i, mpolys + i - 1, ctx); timeit_stop(timer); flint_printf("mpoly: %wd ", timer->wall); fflush(stdout); timeit_start(timer); for (k = 0; k < nreps; k++) for (i = 1; i < npolys; i++) g(res + i, polys + i, polys + i - 1); timeit_stop(timer); flint_printf("poly: %wd\n", timer->wall); fflush(stdout); for (i = 1; i < npolys; i++) { if (!fmpz_mpoly_get_fmpz_poly(res + 0, mres + i, 0, ctx) || !fmpz_poly_equal(res + 0, res + i)) { flint_printf("oops"); flint_abort(); } } } } int main(int argc, char *argv[]) { slong i; FLINT_TEST_INIT(state); flint_printf("\n"); { slong npolys = 10000; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_struct * mpolys, * mres; fmpz_poly_struct * polys, * res; slong len; ulong exp_bound; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init(ctx, 1, ORD_LEX); mpolys = FLINT_ARRAY_ALLOC(npolys, fmpz_mpoly_struct); polys = FLINT_ARRAY_ALLOC(npolys, fmpz_poly_struct); mres = FLINT_ARRAY_ALLOC(npolys, fmpz_mpoly_struct); res = FLINT_ARRAY_ALLOC(npolys, fmpz_poly_struct); for (i = 0; i < npolys; i++) { fmpz_mpoly_init(mpolys + i, ctx); fmpz_poly_init(polys + i); fmpz_mpoly_init(mres + i, ctx); fmpz_poly_init(res + i); } flint_printf("****** dense mul, small coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 10); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 10); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** dense mul, large coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 10); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 200); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** large dense mul, small coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 30); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 10); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** large dense mul, large coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 30); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 200); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** sparse mul, small coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 10); exp_bound = n_randint(state, 10*len) + 10; coeff_bits = 10 + n_randint(state, 10); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** sparse mul, large coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 10); exp_bound = n_randint(state, 10*len) + 10; coeff_bits = 10 + n_randint(state, 100); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** very sparse mul, small coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 10); exp_bound = n_randint(state, 20*len) + 10; coeff_bits = 10 + n_randint(state, 10); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** very sparse mul, large coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 10); exp_bound = n_randint(state, 20*len) + 10; coeff_bits = 10 + n_randint(state, 100); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, fmpz_mpoly_mul, fmpz_poly_mul); flint_printf("****** gcd, small coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 5); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 10); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); } for (i = 0; i + 2 <= npolys; i += 2) { len = 1 + n_randint(state, 5); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 10); fmpz_mpoly_randtest_bound(mres + 0, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul(mpolys + i, mpolys + i, mres + 0, ctx); fmpz_mpoly_mul(mpolys + i + 1, mpolys + i + 1, mres + 0, ctx); } for (i = 0; i < npolys; i++) { fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, (void (*)(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) fmpz_mpoly_gcd, fmpz_poly_gcd); flint_printf("****** gcd, large coeffs ********\n"); for (i = 0; i < npolys; i++) { len = 1 + n_randint(state, 5); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 200); fmpz_mpoly_randtest_bound(mpolys + i, state, len, coeff_bits, exp_bound, ctx); } for (i = 0; i + 2 <= npolys; i += 2) { len = 1 + n_randint(state, 5); exp_bound = len + 1; coeff_bits = 10 + n_randint(state, 200); fmpz_mpoly_randtest_bound(mres + 0, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul(mpolys + i, mpolys + i, mres + 0, ctx); fmpz_mpoly_mul(mpolys + i + 1, mpolys + i + 1, mres + 0, ctx); } for (i = 0; i < npolys; i++) { fmpz_mpoly_get_fmpz_poly(polys + i, mpolys + i, 0, ctx); } run_cmp(mpolys, polys, mres, res, npolys, ctx, (void (*)(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) fmpz_mpoly_gcd, fmpz_poly_gcd); for (i = 0; i < npolys; i++) { fmpz_mpoly_clear(mpolys + i, ctx); fmpz_poly_clear(polys + i); fmpz_mpoly_clear(mres + i, ctx); fmpz_poly_clear(res + i); } flint_free(mpolys); flint_free(polys); flint_free(mres); flint_free(res); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fmpz_mpoly/push_term_fmpz_fmpz.c000066400000000000000000000057021461254215100220640ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void _fmpz_mpoly_push_exp_ffmpz(fmpz_mpoly_t A, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_bits(A, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); fmpz_mpoly_fit_length(A, old_length + 1, ctx); A->length = old_length + 1; mpoly_set_monomial_ffmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void _fmpz_mpoly_push_exp_pfmpz(fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_bits(A, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); fmpz_mpoly_fit_length(A, old_length + 1, ctx); A->length = old_length + 1; mpoly_set_monomial_pfmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void fmpz_mpoly_push_term_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_pfmpz(A, exp, ctx); fmpz_set(A->coeffs + A->length - 1, c); } void fmpz_mpoly_push_term_fmpz_ffmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz *exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_set(A->coeffs + A->length - 1, c); } void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_pfmpz(A, exp, ctx); fmpz_set_ui(A->coeffs + A->length - 1, c); } void fmpz_mpoly_push_term_ui_ffmpz(fmpz_mpoly_t A, ulong c, const fmpz *exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_set_ui(A->coeffs + A->length - 1, c); } void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, slong c, fmpz *const *exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_pfmpz(A, exp, ctx); fmpz_set_si(A->coeffs + A->length - 1, c); } void fmpz_mpoly_push_term_si_ffmpz(fmpz_mpoly_t A, slong c, const fmpz *exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_set_ui(A->coeffs + A->length - 1, c); } flint-3.1.3/src/fmpz_mpoly/push_term_fmpz_ui.c000066400000000000000000000032301461254215100215170ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void _fmpz_mpoly_push_exp_ui(fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_bits(A, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); fmpz_mpoly_fit_length(A, old_length + 1, ctx); A->length = old_length + 1; mpoly_set_monomial_ui(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void fmpz_mpoly_push_term_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_ui(A, exp, ctx); fmpz_set(A->coeffs + A->length - 1, c); } void fmpz_mpoly_push_term_ui_ui(fmpz_mpoly_t A, ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_ui(A, exp, ctx); fmpz_set_ui(A->coeffs + A->length - 1, c); } void fmpz_mpoly_push_term_si_ui(fmpz_mpoly_t A, slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_push_exp_ui(A, exp, ctx); fmpz_set_si(A->coeffs + A->length - 1, c); } flint-3.1.3/src/fmpz_mpoly/quasidiv.c000066400000000000000000000012621461254215100176100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_quasidiv(fmpz_t scale, fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { /* TODO !!! */ fmpz_mpoly_quasidiv_heap(scale, Q, A, B, ctx); } flint-3.1.3/src/fmpz_mpoly/quasidiv_heap.c000066400000000000000000000707171461254215100206200ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_quasidiv_heap1(fmpz_t scale, fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, ulong maskhi) { slong i, j, s = len3; slong q_len = 0; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; fmpz * q_coeff = *polyq; ulong * q_exp = *expq; ulong acc_sm[3]; /* for accumulating coefficients */ ulong mask, exp; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; fmpz_t lc_abs_lg, ns, gcd, acc_lg, r, tp; slong bits2, bits3; int lt_divides, scale_is_one, small; fmpz * qs; slong qs_alloc; TMP_INIT; TMP_START; fmpz_init(lc_abs_lg); fmpz_init(acc_lg); fmpz_init(r); fmpz_init(tp); fmpz_init(ns); fmpz_init(gcd); fmpz_set_ui(scale, 1); scale_is_one = 1; qs_alloc = 64; qs = (fmpz *) flint_calloc(qs_alloc, sizeof(fmpz)); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); /* precompute leading coefficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { /* make sure quotient array has space for q_len + 1 entries */ _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, 1); if (q_len + 1 > qs_alloc) { slong len; len = FLINT_MAX(q_len + 1, 2*qs_alloc); qs = (fmpz *) flint_realloc(qs, len*sizeof(fmpz)); if (len > qs_alloc) flint_mpn_zero((mp_ptr) (qs + qs_alloc), len - qs_alloc); qs_alloc = len; } exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides1(q_exp + q_len, exp, exp3[0], mask); /* accumulate terms from highest terms on heap */ if (!lt_divides) { /* optimization: coeff arithmetic not needed */ if (mpoly_monomial_gt1(exp3[0], exp, maskhi)) { /* optimization: no more quotient terms possible */ goto cleanup; } do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else if (small) { /* optimization: small coeff arithmetic, acc_sm used below */ FLINT_ASSERT(scale_is_one); acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else if (scale_is_one) { /* general coeff arithmetic with scale 1 */ fmpz_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else { /* general coeff arithmetic */ fmpz_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_addmul(acc_lg, scale, poly2 + x->j); else { fmpz_divexact(tp, scale, qs + x->j); fmpz_mul(tp, tp, q_coeff + x->j); fmpz_submul(acc_lg, poly3 + x->i, tp); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } /* process popped nodes */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } } } if (!lt_divides) continue; /* try to divide accumulated term by leading term of divisor */ if (small) { ulong d0, d1, ds = acc_sm[2]; FLINT_ASSERT(scale_is_one); sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) continue; if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr == 0 && (qq & (WORD(3) << (SMALL_FMPZ_BITCOUNT_MAX))) == 0) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = (qq^ds^lc_sign) - (ds^lc_sign); fmpz_set_ui(qs + q_len, 1); } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) continue; large_lt_divides: fmpz_gcd(gcd, acc_lg, poly3 + 0); fmpz_divexact(ns, lc_abs_lg, gcd); if (!fmpz_is_one(ns)) scale_is_one = 0; fmpz_mul(q_coeff + q_len, ns, acc_lg); fmpz_divexact(q_coeff + q_len, q_coeff + q_len, poly3 + 0); fmpz_mul(qs + q_len, scale, ns); fmpz_set(scale, qs + q_len); } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } q_len++; s = 1; } cleanup: (*polyq) = q_coeff; (*expq) = q_exp; TMP_END; for (i = 0; i < q_len; i++) { fmpz_divexact(tp, scale, qs + i); fmpz_mul(q_coeff + i, q_coeff + i, tp); } for (i = 0; i < qs_alloc; i++) fmpz_clear(qs + i); flint_free(qs); fmpz_clear(lc_abs_lg); fmpz_clear(acc_lg); fmpz_clear(r); fmpz_clear(tp); fmpz_clear(ns); fmpz_clear(gcd); return q_len; exp_overflow: for (i = 0; i <= q_len; i++) _fmpz_demote(q_coeff + i); q_len = -WORD(1); goto cleanup; } slong _fmpz_mpoly_quasidiv_heap(fmpz_t scale, fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const ulong * cmpmask) { slong i, j, s = len3; slong q_len = 0; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; fmpz * q_coeff = *polyq; ulong * q_exp = *expq; ulong * exp, * exps; ulong ** exp_list; ulong acc_sm[3]; /* for accumulating coefficients */ slong exp_next; ulong mask; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; fmpz_t lc_abs_lg, ns, gcd, acc_lg, r, tp; slong bits2, bits3; int lt_divides, scale_is_one, small; fmpz * qs; slong qs_alloc; TMP_INIT; if (N == 1) return _fmpz_mpoly_quasidiv_heap1(scale, polyq, expq, allocq, poly2, exp2, len2, poly3, exp3, len3, bits, cmpmask[0]); TMP_START; fmpz_init(lc_abs_lg); fmpz_init(acc_lg); fmpz_init(r); fmpz_init(tp); fmpz_init(ns); fmpz_init(gcd); fmpz_set_ui(scale, 1); scale_is_one = 1; qs_alloc = 64; qs = (fmpz *) flint_calloc(qs_alloc, sizeof(fmpz)); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* array of exponents of N words each */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* array of pointers to unused exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coefficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { /* make sure quotient array has space for q_len + 1 entries */ _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, N); if (q_len + 1 > qs_alloc) { slong len; len = FLINT_MAX(q_len + 1, 2*qs_alloc); qs = (fmpz *) flint_realloc(qs, len*sizeof(fmpz)); if (len > qs_alloc) flint_mpn_zero((mp_ptr) (qs + qs_alloc), len - qs_alloc); qs_alloc = len; } mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides(q_exp + q_len*N, exp, exp3, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; lt_divides = mpoly_monomial_divides_mp(q_exp + q_len*N, exp, exp3, N, bits); } if (!lt_divides) { /* optimization: coeff arithmetic not needed */ if (mpoly_monomial_gt(exp3 + 0, exp, N, cmpmask)) { /* optimization: no more quotient terms possible */ goto cleanup; } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else if (small) { /* optimization: small coeff arithmetic, acc_sm used below */ FLINT_ASSERT(scale_is_one); acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else if (scale_is_one) { /* general coeff arithmetic with scale 1 */ fmpz_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else { /* general coeff arithmetic */ fmpz_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) fmpz_addmul(acc_lg, scale, poly2 + x->j); else { fmpz_divexact(tp, scale, qs + x->j); fmpz_mul(tp, tp, q_coeff + x->j); fmpz_submul(acc_lg, poly3 + x->i, tp); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } /* process popped nodes */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (!lt_divides) continue; /* try to divide accumulated term by leading term of divisor */ if (small) { ulong d0, d1, ds = acc_sm[2]; FLINT_ASSERT(scale_is_one); sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) continue; if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr ==0 && (qq & (WORD(3) << (SMALL_FMPZ_BITCOUNT_MAX))) == 0) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = (qq^ds^lc_sign) - (ds^lc_sign); fmpz_set_ui(qs + q_len, 1); } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) continue; large_lt_divides: fmpz_gcd(gcd, acc_lg, poly3 + 0); fmpz_divexact(ns, lc_abs_lg, gcd); if (!fmpz_is_one(ns)) scale_is_one = 0; fmpz_mul(q_coeff + q_len, ns, acc_lg); fmpz_divexact(q_coeff + q_len, q_coeff + q_len, poly3 + 0); fmpz_mul(qs + q_len, scale, ns); fmpz_set(scale, qs + q_len); } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } q_len++; s = 1; } cleanup: (*polyq) = q_coeff; (*expq) = q_exp; TMP_END; for (i = 0; i < q_len; i++) { fmpz_divexact(tp, scale, qs + i); fmpz_mul(q_coeff + i, q_coeff + i, tp); } for (i = 0; i < qs_alloc; i++) fmpz_clear(qs + i); flint_free(qs); fmpz_clear(lc_abs_lg); fmpz_clear(acc_lg); fmpz_clear(r); fmpz_clear(tp); fmpz_clear(ns); fmpz_clear(gcd); return q_len; exp_overflow: for (i = 0; i <= q_len; i++) _fmpz_demote(q_coeff + i); q_len = -WORD(1); goto cleanup; } void fmpz_mpoly_quasidiv_heap(fmpz_t scale, fmpz_mpoly_t q, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) { slong exp_bits, N, lenq = 0; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; ulong * cmpmask; int free2 = 0, free3 = 0; fmpz_mpoly_t temp1; fmpz_mpoly_struct * tq; /* check divisor is nonzero */ if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_quasidiv_heap"); fmpz_set_ui(scale, 1); /* dividend zero, write out quotient and remainder */ if (poly2->length == 0) { fmpz_mpoly_zero(q, ctx); return; } exp_bits = FLINT_MAX(poly2->bits, poly3->bits); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(exp2, exp3, N, cmpmask)) { fmpz_mpoly_zero(q, ctx); goto cleanup3; } /* take care of aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_init2(temp1, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(temp1, exp_bits, ctx); temp1->bits = exp_bits; tq = temp1; } else { fmpz_mpoly_fit_length(q, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(q, exp_bits, ctx); q->bits = exp_bits; tq = q; } /* do division with remainder */ while ((lenq = _fmpz_mpoly_quasidiv_heap(scale, &tq->coeffs, &tq->exps, &tq->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask)) == -WORD(1)) { ulong * old_exp2 = exp2, * old_exp3 = exp3; slong old_exp_bits = exp_bits; exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, old_exp2, old_exp_bits, poly2->length, ctx->minfo); exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, old_exp3, old_exp_bits, poly3->length, ctx->minfo); if (free2) flint_free(old_exp2); if (free3) flint_free(old_exp3); free2 = free3 = 1; fmpz_mpoly_fit_bits(tq, exp_bits, ctx); tq->bits = exp_bits; } /* take care of aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_swap(temp1, q, ctx); fmpz_mpoly_clear(temp1, ctx); } _fmpz_mpoly_set_length(q, lenq, ctx); cleanup3: if (free2) flint_free(exp2); if (free3) flint_free(exp3); flint_free(cmpmask); } flint-3.1.3/src/fmpz_mpoly/quasidivrem.c000066400000000000000000000011771461254215100203210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_quasidivrem(fmpz_t scale, fmpz_mpoly_t Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { /* TODO !!! */ fmpz_mpoly_quasidivrem_heap(scale, Q, R, A, B, ctx); } flint-3.1.3/src/fmpz_mpoly/quasidivrem_heap.c000066400000000000000000000706161461254215100213220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_quasidivrem_heap1(fmpz_t scale, slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, ulong maskhi) { slong i, j, s = len3; slong q_len = 0, r_len = 0; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; fmpz * q_coeff = *polyq; fmpz * r_coeff = *polyr; ulong * q_exp = *expq; ulong * r_exp = *expr; ulong acc_sm[3]; /* for accumulating coefficients */ ulong mask, exp; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; fmpz_t lc_abs_lg, ns, gcd, acc_lg, r, tp; slong bits2, bits3; int lt_divides, scaleis1, small; fmpz * qs, * rs; slong qs_alloc, rs_alloc; TMP_INIT; TMP_START; fmpz_init(lc_abs_lg); fmpz_init(acc_lg); fmpz_init(r); fmpz_init(tp); fmpz_init(ns); fmpz_init(gcd); fmpz_set_ui(scale, 1); scaleis1 = 1; qs_alloc = 64; qs = (fmpz *) flint_calloc(qs_alloc, sizeof(fmpz)); rs_alloc = 64; rs = (fmpz *) flint_calloc(rs_alloc, sizeof(fmpz)); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); /* precompute leading coefficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { /* make sure quotient array has space for q_len + 1 entries */ _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, 1); if (q_len + 1 > qs_alloc) { slong len; len = FLINT_MAX(q_len + 1, 2*qs_alloc); qs = (fmpz *) flint_realloc(qs, len*sizeof(fmpz)); if (len > qs_alloc) flint_mpn_zero((mp_ptr) (qs + qs_alloc), len - qs_alloc); qs_alloc = len; } /* make sure remainder array has space for r_len + 1 entries */ _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, 1); if (r_len + 1 > rs_alloc) { slong len; len = FLINT_MAX(r_len + 1, 2*rs_alloc); rs = (fmpz *) flint_realloc(rs, len*sizeof(fmpz)); if (len > rs_alloc) flint_mpn_zero((mp_ptr) (rs + rs_alloc), len - rs_alloc); rs_alloc = len; } exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides1(q_exp + q_len, exp, exp3[0], mask); /* accumulate terms from highest terms on heap */ if (small) acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; else fmpz_zero(acc_lg); while (heap_len > 1 && heap[1].exp == exp) { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (small) { if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } else if (scaleis1) { if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } else { if (x->i == -WORD(1)) fmpz_addmul(acc_lg, scale, poly2 + x->j); else { fmpz_divexact(tp, scale, qs + x->j); fmpz_mul(tp, tp, q_coeff + x->j); fmpz_submul(acc_lg, poly3 + x->i, tp); } } } while ((x = x->next) != NULL); } /* process popped nodes */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } } } /* try to divide accumulated term by leading term of divisor */ if (small) { ulong d0, d1, ds = acc_sm[2]; sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) continue; if (!lt_divides) { fmpz_set_signed_uiuiui(r_coeff + r_len, acc_sm[2], acc_sm[1], acc_sm[0]); r_exp[r_len] = exp; fmpz_one(rs + r_len); r_len++; continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr == 0 && qq <= COEFF_MAX) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = qq; if (ds != lc_sign) q_coeff[q_len] = -q_coeff[q_len]; fmpz_one(qs + q_len); } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) continue; if (!lt_divides) { fmpz_set(r_coeff + r_len, acc_lg); r_exp[r_len] = exp; fmpz_set(rs + r_len, scale); r_len++; continue; } large_lt_divides: fmpz_gcd(gcd, acc_lg, poly3 + 0); fmpz_divexact(ns, lc_abs_lg, gcd); if (!fmpz_is_one(ns)) scaleis1 = 0; fmpz_mul(q_coeff + q_len, ns, acc_lg); fmpz_divexact(q_coeff + q_len, q_coeff + q_len, poly3 + 0); fmpz_mul(qs + q_len, scale, ns); fmpz_set(scale, qs + q_len); } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } q_len++; s = 1; } cleanup2: (*polyq) = q_coeff; (*expq) = q_exp; (*polyr) = r_coeff; (*expr) = r_exp; (*lenr) = r_len; TMP_END; for (i = 0; i < q_len; i++) { fmpz_divexact(tp, scale, qs + i); fmpz_mul(q_coeff + i, q_coeff + i, tp); } for (i = 0; i < qs_alloc; i++) fmpz_clear(qs + i); for (i = 0; i < r_len; i++) { fmpz_divexact(tp, scale, rs + i); fmpz_mul(r_coeff + i, r_coeff + i, tp); } for (i = 0; i < rs_alloc; i++) fmpz_clear(rs + i); flint_free(qs); flint_free(rs); fmpz_clear(lc_abs_lg); fmpz_clear(acc_lg); fmpz_clear(r); fmpz_clear(tp); fmpz_clear(ns); fmpz_clear(gcd); return q_len; exp_overflow: for (i = 0; i < q_len; i++) _fmpz_demote(q_coeff + i); for (i = 0; i < r_len; i++) _fmpz_demote(r_coeff + i); q_len = 0; r_len = 0; goto cleanup2; } slong _fmpz_mpoly_quasidivrem_heap(fmpz_t scale, slong * lenr, fmpz ** polyq, ulong ** expq, slong * allocq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3, slong bits, slong N, const ulong * cmpmask) { slong i, j, s = len3; slong q_len = 0, r_len = 0; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; fmpz * q_coeff = *polyq; fmpz * r_coeff = *polyr; ulong * q_exp = *expq; ulong * r_exp = *expr; ulong * exp, * exps; ulong ** exp_list; ulong acc_sm[3]; /* for accumulating coefficients */ slong exp_next; ulong mask; ulong lc_norm = 0, lc_abs = 0, lc_sign = 0, lc_n = 0, lc_i = 0; fmpz_t lc_abs_lg, ns, gcd, acc_lg, r, tp; slong bits2, bits3; int lt_divides, scaleis1, small; fmpz * qs, * rs; slong qs_alloc, rs_alloc; TMP_INIT; if (N == 1) return _fmpz_mpoly_quasidivrem_heap1(scale, lenr, polyq, expq, allocq, polyr, expr, allocr, poly2, exp2, len2, poly3, exp3, len3, bits, cmpmask[0]); TMP_START; fmpz_init(lc_abs_lg); fmpz_init(acc_lg); fmpz_init(r); fmpz_init(tp); fmpz_init(ns); fmpz_init(gcd); fmpz_set_ui(scale, 1); scaleis1 = 1; qs_alloc = 64; qs = (fmpz *) flint_calloc(qs_alloc, sizeof(fmpz)); rs_alloc = 64; rs = (fmpz *) flint_calloc(rs_alloc, sizeof(fmpz)); /* whether intermediate computations q - a*b will fit in three words */ bits2 = _fmpz_vec_max_bits(poly2, len2); bits3 = _fmpz_vec_max_bits(poly3, len3); /* allow one bit for sign, one bit for subtraction */ small = FLINT_ABS(bits2) <= (FLINT_ABS(bits3) + FLINT_BIT_COUNT(len3) + SMALL_FMPZ_BITCOUNT_MAX) && FLINT_ABS(bits3) <= SMALL_FMPZ_BITCOUNT_MAX; next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(mpoly_heap_t *)); /* array of exponents of N words each */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* array of pointers to unused exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coefficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } while (heap_len > 1) { /* make sure quotient array has space for q_len + 1 entries */ _fmpz_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, N); if (q_len + 1 > qs_alloc) { slong len; len = FLINT_MAX(q_len + 1, 2*qs_alloc); qs = (fmpz *) flint_realloc(qs, len*sizeof(fmpz)); if (len > qs_alloc) flint_mpn_zero((mp_ptr) (qs + qs_alloc), len - qs_alloc); qs_alloc = len; } /* make sure remainder array has space for r_len + 1 entries */ _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, N); if (r_len + 1 > rs_alloc) { slong len; len = FLINT_MAX(r_len + 1, 2*rs_alloc); rs = (fmpz *) flint_realloc(rs, len*sizeof(fmpz)); if (len > rs_alloc) flint_mpn_zero((mp_ptr) (rs + rs_alloc), len - rs_alloc); rs_alloc = len; } mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides(q_exp + q_len*N, exp, exp3, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; lt_divides = mpoly_monomial_divides_mp(q_exp + q_len*N, exp, exp3, N, bits); } /* accumulate terms from highest terms on heap */ if (small) acc_sm[0] = acc_sm[1] = acc_sm[2] = 0; else fmpz_zero(acc_lg); while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)) { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (small) { if (x->i == -WORD(1)) _fmpz_mpoly_add_uiuiui_fmpz(acc_sm, poly2 + x->j); else _fmpz_mpoly_submul_uiuiui_fmpz(acc_sm, poly3[x->i], q_coeff[x->j]); } else if (scaleis1) { if (x->i == -WORD(1)) fmpz_add(acc_lg, acc_lg, poly2 + x->j); else fmpz_submul(acc_lg, poly3 + x->i, q_coeff + x->j); } else { if (x->i == -WORD(1)) fmpz_addmul(acc_lg, scale, poly2 + x->j); else { fmpz_divexact(tp, scale, qs + x->j); fmpz_mul(tp, tp, q_coeff + x->j); fmpz_submul(acc_lg, poly3 + x->i, tp); } } } while ((x = x->next) != NULL); } /* process popped nodes */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term of divisor */ if (small) { ulong d0, d1, ds = acc_sm[2]; sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) continue; if (!lt_divides) { fmpz_set_signed_uiuiui(r_coeff + r_len, acc_sm[2], acc_sm[1], acc_sm[0]); mpoly_monomial_set(r_exp + r_len*N, exp, N); fmpz_one(rs + r_len); r_len++; continue; } if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; FLINT_ASSERT(0 < lc_norm && lc_norm < FLINT_BITS); nhi = (d1 << lc_norm) | (d0 >> (FLINT_BITS - lc_norm)); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr == 0 && qq <= COEFF_MAX) { _fmpz_demote(q_coeff + q_len); q_coeff[q_len] = qq; if (ds != lc_sign) q_coeff[q_len] = -q_coeff[q_len]; fmpz_one(qs + q_len); } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { small = 0; fmpz_set_signed_uiuiui(acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { if (fmpz_is_zero(acc_lg)) continue; if (!lt_divides) { fmpz_set(r_coeff + r_len, acc_lg); mpoly_monomial_set(r_exp + r_len*N, exp, N); fmpz_set(rs + r_len, scale); r_len++; continue; } large_lt_divides: fmpz_gcd(gcd, acc_lg, poly3 + 0); fmpz_divexact(ns, lc_abs_lg, gcd); if (!fmpz_is_one(ns)) scaleis1 = 0; fmpz_mul(q_coeff + q_len, ns, acc_lg); fmpz_divexact(q_coeff + q_len, q_coeff + q_len, poly3 + 0); fmpz_mul(qs + q_len, scale, ns); fmpz_set(scale, qs + q_len); } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } q_len++; s = 1; } cleanup2: (*polyq) = q_coeff; (*expq) = q_exp; (*polyr) = r_coeff; (*expr) = r_exp; (*lenr) = r_len; TMP_END; for (i = 0; i < q_len; i++) { fmpz_divexact(tp, scale, qs + i); fmpz_mul(q_coeff + i, q_coeff + i, tp); } for (i = 0; i < qs_alloc; i++) fmpz_clear(qs + i); for (i = 0; i < r_len; i++) { fmpz_divexact(tp, scale, rs + i); fmpz_mul(r_coeff + i, r_coeff + i, tp); } for (i = 0; i < rs_alloc; i++) fmpz_clear(rs + i); flint_free(qs); flint_free(rs); fmpz_clear(lc_abs_lg); fmpz_clear(acc_lg); fmpz_clear(r); fmpz_clear(tp); fmpz_clear(ns); fmpz_clear(gcd); return q_len; exp_overflow: for (i = 0; i < q_len; i++) _fmpz_demote(q_coeff + i); for (i = 0; i < r_len; i++) _fmpz_demote(r_coeff + i); q_len = 0; r_len = 0; goto cleanup2; } void fmpz_mpoly_quasidivrem_heap(fmpz_t scale, fmpz_mpoly_t q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, const fmpz_mpoly_t poly3, const fmpz_mpoly_ctx_t ctx) { slong exp_bits, N, lenq = 0, lenr = 0; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; ulong * cmpmask; int free2 = 0, free3 = 0; fmpz_mpoly_t temp1, temp2; fmpz_mpoly_struct * tq, * tr; /* check divisor is nonzero */ if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_quasidivrem_heap"); fmpz_set_ui(scale, 1); /* dividend zero, write out quotient and remainder */ if (poly2->length == 0) { fmpz_mpoly_zero(q, ctx); fmpz_mpoly_zero(r, ctx); return; } exp_bits = FLINT_MAX(poly2->bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(exp2, exp3, N, cmpmask)) { fmpz_mpoly_set(r, poly2, ctx); fmpz_mpoly_zero(q, ctx); goto cleanup3; } /* take care of aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_init2(temp1, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(temp1, exp_bits, ctx); temp1->bits = exp_bits; tq = temp1; } else { fmpz_mpoly_fit_length(q, poly2->length/poly3->length + 1, ctx); fmpz_mpoly_fit_bits(q, exp_bits, ctx); q->bits = exp_bits; tq = q; } if (r == poly2 || r == poly3) { fmpz_mpoly_init2(temp2, poly3->length, ctx); fmpz_mpoly_fit_bits(temp2, exp_bits, ctx); temp2->bits = exp_bits; tr = temp2; } else { fmpz_mpoly_fit_length(r, poly3->length, ctx); fmpz_mpoly_fit_bits(r, exp_bits, ctx); r->bits = exp_bits; tr = r; } /* do division with remainder */ while ((lenq = _fmpz_mpoly_quasidivrem_heap(scale, &lenr, &tq->coeffs, &tq->exps, &tq->alloc, &tr->coeffs, &tr->exps, &tr->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask)) == 0 && lenr == 0) { ulong * old_exp2 = exp2, * old_exp3 = exp3; slong old_exp_bits = exp_bits; exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, old_exp2, old_exp_bits, poly2->length, ctx->minfo); exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, old_exp3, old_exp_bits, poly3->length, ctx->minfo); if (free2) flint_free(old_exp2); if (free3) flint_free(old_exp3); free2 = free3 = 1; fmpz_mpoly_fit_bits(tq, exp_bits, ctx); tq->bits = exp_bits; fmpz_mpoly_fit_bits(tr, exp_bits, ctx); tr->bits = exp_bits; } /* deal with aliasing */ if (q == poly2 || q == poly3) { fmpz_mpoly_swap(temp1, q, ctx); fmpz_mpoly_clear(temp1, ctx); } if (r == poly2 || r == poly3) { fmpz_mpoly_swap(temp2, r, ctx); fmpz_mpoly_clear(temp2, ctx); } _fmpz_mpoly_set_length(q, lenq, ctx); _fmpz_mpoly_set_length(r, lenr, ctx); cleanup3: if (free2) flint_free(exp2); if (free3) flint_free(exp3); flint_free(cmpmask); } flint-3.1.3/src/fmpz_mpoly/quasidivrem_ideal.c000066400000000000000000000013211461254215100214460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_quasidivrem_ideal(fmpz_t scale, fmpz_mpoly_struct ** Q, fmpz_mpoly_t R, const fmpz_mpoly_t A, fmpz_mpoly_struct * const * B, slong len, const fmpz_mpoly_ctx_t ctx) { /* TODO !!! */ fmpz_mpoly_quasidivrem_ideal_heap(scale, Q, R, A, B, len, ctx); } flint-3.1.3/src/fmpz_mpoly/quasidivrem_ideal_heap.c000066400000000000000000000602711461254215100224540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_quasidivrem_ideal_heap1(fmpz_t scale, fmpz_mpoly_struct ** polyq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, fmpz_mpoly_struct * const * poly3, ulong * const * exp3, slong len, slong bits, const fmpz_mpoly_ctx_t ctx, ulong maskhi) { slong i, j, p, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_nheap_t ** chains, * chains_ptr; slong ** hinds, * hinds_ptr; mpoly_nheap_t * x; ulong exp, texp; ulong mask; fmpz ** qs, * rs; slong * qs_alloc, rs_alloc; slong * q_len, * s; fmpz * r_coeff = *polyr; ulong * r_exp = *expr; slong r_len; fmpz_t ns, gcd, acc_lg, tp; TMP_INIT; TMP_START; fmpz_init(ns); fmpz_init(gcd); fmpz_init(acc_lg); fmpz_init(tp); fmpz_one(scale); s = (slong *) TMP_ALLOC(len*sizeof(slong)); q_len = (slong *) TMP_ALLOC(len*sizeof(slong)); qs_alloc = (slong *) TMP_ALLOC(len*sizeof(slong)); qs = (fmpz **) TMP_ALLOC(len*sizeof(fmpz *)); for (w = 0; w < len; w++) { q_len[w] = WORD(0); qs_alloc[w] = 16; qs[w] = (fmpz *) flint_calloc(qs_alloc[w], sizeof(fmpz)); s[w] = poly3[w]->length; } r_len = WORD(0); rs_alloc = 64; rs = (fmpz *) flint_calloc(rs_alloc, sizeof(fmpz)); chains = TMP_ARRAY_ALLOC(len, mpoly_nheap_t *); hinds = TMP_ARRAY_ALLOC(len, slong *); /* chains[w], hinds[w] will be arrays of length poly3[w]->length; combine the allocations*/ len3 = 0; for (w = 0; w < len; w++) len3 += poly3[w]->length; chains_ptr = TMP_ARRAY_ALLOC(len3, mpoly_nheap_t); hinds_ptr = TMP_ARRAY_ALLOC(len3, slong); len3 = 0; for (w = 0; w < len; w++) { chains[w] = chains_ptr + len3; hinds[w] = hinds_ptr + len3; len3 += poly3[w]->length; for (i = 0; i < poly3[w]->length; i++) hinds[w][i] = 1; } next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong)); mask = mpoly_overflow_mask_sp(bits); x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; fmpz_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i != -WORD(1)) hinds[x->p][x->i] |= WORD(1); if (x->i == -WORD(1)) { fmpz_addmul(acc_lg, scale, poly2 + x->j); } else { fmpz_divexact(tp, scale, qs[x->p] + x->j); fmpz_mul(tp, tp, polyq[x->p]->coeffs + x->j); fmpz_submul(acc_lg, poly3[x->p]->coeffs + x->i, tp); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { if ( (i + 1 < poly3[p]->length) && (hinds[p][i + 1] == 2*j + 1) ) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->p][x->i] + polyq[x->p]->exps[x->j], x, &next_loc, &heap_len, maskhi); } if (j + 1 == q_len[p]) { s[p]++; } else if ( ((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1)) ) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->p][x->i] + polyq[x->p]->exps[x->j], x, &next_loc, &heap_len, maskhi); } } } if (fmpz_is_zero(acc_lg)) continue; for (w = 0; w < len; w++) { if (mpoly_monomial_divides1(&texp, exp, exp3[w][0], mask)) { fmpz_mpoly_fit_length(polyq[w], q_len[w] + 1, ctx); if (q_len[w] + 1 > qs_alloc[w]) { slong len = FLINT_MAX(q_len[w] + 1, 2*qs_alloc[w]); qs[w] = (fmpz *) flint_realloc(qs[w], len*sizeof(fmpz)); flint_mpn_zero((mp_ptr) (qs[w] + qs_alloc[w]), len - qs_alloc[w]); qs_alloc[w] = len; } fmpz_gcd(gcd, acc_lg, poly3[w]->coeffs + 0); fmpz_divexact(ns, poly3[w]->coeffs + 0, gcd); fmpz_abs(ns, ns); fmpz_mul(polyq[w]->coeffs + q_len[w], ns, acc_lg); fmpz_divexact(polyq[w]->coeffs + q_len[w], polyq[w]->coeffs + q_len[w], poly3[w]->coeffs + 0); fmpz_mul(qs[w] + q_len[w], scale, ns); fmpz_set(scale, qs[w] + q_len[w]); polyq[w]->exps[q_len[w]] = texp; if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = q_len[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[w][x->i] + polyq[w]->exps[x->j], x, &next_loc, &heap_len, maskhi); } s[w] = 1; q_len[w]++; goto break_continue; /* break out of w for loop and continue in heap loop */ } } /* if get here, no leading terms divided */ _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, 1); if (r_len + 1 > rs_alloc) { slong len = FLINT_MAX(r_len + 1, 2*rs_alloc); rs = (fmpz *) flint_realloc(rs, len*sizeof(fmpz)); flint_mpn_zero((mp_ptr) (rs + rs_alloc), len - rs_alloc); rs_alloc = len; } fmpz_set(r_coeff + r_len, acc_lg); fmpz_set(rs + r_len, scale); r_exp[r_len] = exp; r_len++; break_continue: (void)(NULL); } cleanup2: for (w = 0; w < len; w++) { _fmpz_mpoly_set_length(polyq[w], q_len[w], ctx); for (i = 0; i < q_len[w]; i++) { fmpz_divexact(tp, scale, qs[w] + i); fmpz_mul(polyq[w]->coeffs + i, polyq[w]->coeffs + i, tp); } for (i = 0; i < qs_alloc[w]; i++) fmpz_clear(qs[w] + i); flint_free(qs[w]); } (*polyr) = r_coeff; (*expr) = r_exp; for (i = 0; i < r_len; i++) { fmpz_divexact(tp, scale, rs + i); fmpz_mul(r_coeff + i, r_coeff + i, tp); } for (i = 0; i < rs_alloc; i++) fmpz_clear(rs + i); flint_free(rs); fmpz_clear(ns); fmpz_clear(gcd); fmpz_clear(acc_lg); fmpz_clear(tp); TMP_END; return r_len; exp_overflow: for (i = 0; i < r_len; i++) _fmpz_demote(r_coeff + i); r_len = -WORD(1); for (w = 0; w < len; w++) { for (i = 0; i < q_len[w]; i++) _fmpz_demote(polyq[w]->coeffs + i); q_len[w] = WORD(0); } goto cleanup2; } slong _fmpz_mpoly_quasidivrem_ideal_heap(fmpz_t scale, fmpz_mpoly_struct ** polyq, fmpz ** polyr, ulong ** expr, slong * allocr, const fmpz * poly2, const ulong * exp2, slong len2, fmpz_mpoly_struct * const * poly3, ulong * const * exp3, slong len, slong N, slong bits, const fmpz_mpoly_ctx_t ctx, const ulong * cmpmask) { slong i, j, p, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_nheap_t ** chains; slong ** hinds; mpoly_nheap_t * x; ulong * exp, * exps, * texp; ulong ** exp_list; slong exp_next; ulong mask; fmpz ** qs, * rs; slong * qs_alloc, rs_alloc; slong * q_len, * s; fmpz * r_coeff = *polyr; ulong * r_exp = *expr; slong r_len; fmpz_t ns, gcd, acc_lg, tp; TMP_INIT; if (N == 1) return _fmpz_mpoly_quasidivrem_ideal_heap1(scale, polyq, polyr, expr, allocr, poly2, exp2, len2, poly3, exp3, len, bits, ctx, cmpmask[0]); TMP_START; fmpz_init(ns); fmpz_init(gcd); fmpz_init(acc_lg); fmpz_init(tp); fmpz_one(scale); s = (slong *) TMP_ALLOC(len*sizeof(slong)); q_len = (slong *) TMP_ALLOC(len*sizeof(slong)); qs_alloc = (slong *) TMP_ALLOC(len*sizeof(slong)); qs = (fmpz **) TMP_ALLOC(len*sizeof(fmpz *)); for (w = 0; w < len; w++) { q_len[w] = WORD(0); qs_alloc[w] = 16; qs[w] = (fmpz *) flint_calloc(qs_alloc[w], sizeof(fmpz)); s[w] = poly3[w]->length; } r_len = WORD(0); rs_alloc = 64; rs = (fmpz *) flint_calloc(rs_alloc, sizeof(fmpz)); chains = (mpoly_nheap_t **) TMP_ALLOC(len*sizeof(mpoly_nheap_t *)); hinds = (slong **) TMP_ALLOC(len*sizeof(slong *)); len3 = 0; for (w = 0; w < len; w++) { chains[w] = (mpoly_nheap_t *) TMP_ALLOC((poly3[w]->length)*sizeof(mpoly_nheap_t)); hinds[w] = (slong *) TMP_ALLOC((poly3[w]->length)*sizeof(slong)); len3 += poly3[w]->length; for (i = 0; i < poly3[w]->length; i++) hinds[w][i] = 1; } next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong)); exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; } fmpz_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i != -WORD(1)) hinds[x->p][x->i] |= WORD(1); if (x->i == -WORD(1)) { fmpz_addmul(acc_lg, scale, poly2 + x->j); } else { fmpz_divexact(tp, scale, qs[x->p] + x->j); fmpz_mul(tp, tp, polyq[x->p]->coeffs + x->j); fmpz_submul(acc_lg, poly3[x->p]->coeffs + x->i, tp); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right */ if ( (i + 1 < poly3[p]->length) && (hinds[p][i + 1] == 2*j + 1) ) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[x->p] + x->i*N, polyq[x->p]->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len[p]) { s[p]++; } else if ( ((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1)) ) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[x->p] + x->i*N, polyq[x->p]->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (fmpz_is_zero(acc_lg)) continue; for (w = 0; w < len; w++) { int divides; if (bits <= FLINT_BITS) divides = mpoly_monomial_divides(texp, exp, exp3[w] + N*0, N, mask); else divides = mpoly_monomial_divides_mp(texp, exp, exp3[w] + N*0, N, bits); if (divides) { fmpz_mpoly_fit_length(polyq[w], q_len[w] + 1, ctx); if (q_len[w] + 1 > qs_alloc[w]) { slong len = FLINT_MAX(q_len[w] + 1, 2*qs_alloc[w]); qs[w] = (fmpz *) flint_realloc(qs[w], len*sizeof(fmpz)); flint_mpn_zero((mp_ptr) (qs[w] + qs_alloc[w]), len - qs_alloc[w]); qs_alloc[w] = len; } fmpz_gcd(gcd, acc_lg, poly3[w]->coeffs + 0); fmpz_divexact(ns, poly3[w]->coeffs + 0, gcd); fmpz_abs(ns, ns); fmpz_mul(polyq[w]->coeffs + q_len[w], ns, acc_lg); fmpz_divexact(polyq[w]->coeffs + q_len[w], polyq[w]->coeffs + q_len[w], poly3[w]->coeffs + 0); fmpz_mul(qs[w] + q_len[w], scale, ns); fmpz_set(scale, qs[w] + q_len[w]); mpoly_monomial_set(polyq[w]->exps + N*q_len[w], texp, N); if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = q_len[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[w] + N*x->i, polyq[w]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s[w] = 1; q_len[w]++; goto break_continue; /* break out of w for loop and continue in heap loop */ } } /* if get here, no leading terms divided */ _fmpz_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, N); if (r_len + 1 > rs_alloc) { slong len = FLINT_MAX(r_len + 1, 2*rs_alloc); rs = (fmpz *) flint_realloc(rs, len*sizeof(fmpz)); flint_mpn_zero((mp_ptr) (rs + rs_alloc), len - rs_alloc); rs_alloc = len; } fmpz_set(r_coeff + r_len, acc_lg); fmpz_set(rs + r_len, scale); mpoly_monomial_set(r_exp + r_len*N, exp, N); r_len++; break_continue: (void)(NULL); } cleanup2: for (w = 0; w < len; w++) { _fmpz_mpoly_set_length(polyq[w], q_len[w], ctx); for (i = 0; i < q_len[w]; i++) { fmpz_divexact(tp, scale, qs[w] + i); fmpz_mul(polyq[w]->coeffs + i, polyq[w]->coeffs + i, tp); } for (i = 0; i < qs_alloc[w]; i++) fmpz_clear(qs[w] + i); flint_free(qs[w]); } (*polyr) = r_coeff; (*expr) = r_exp; for (i = 0; i < r_len; i++) { fmpz_divexact(tp, scale, rs + i); fmpz_mul(r_coeff + i, r_coeff + i, tp); } for (i = 0; i < rs_alloc; i++) fmpz_clear(rs + i); flint_free(rs); fmpz_clear(ns); fmpz_clear(gcd); fmpz_clear(acc_lg); fmpz_clear(tp); TMP_END; return r_len; exp_overflow: for (i = 0; i < r_len; i++) _fmpz_demote(r_coeff + i); r_len = -WORD(1); for (w = 0; w < len; w++) { for (i = 0; i < q_len[w]; i++) _fmpz_demote(polyq[w]->coeffs + i); q_len[w] = WORD(0); } goto cleanup2; } /* Assumes divisor polys don't alias any output polys */ void fmpz_mpoly_quasidivrem_ideal_heap(fmpz_t scale, fmpz_mpoly_struct ** q, fmpz_mpoly_t r, const fmpz_mpoly_t poly2, fmpz_mpoly_struct * const * poly3, slong len, const fmpz_mpoly_ctx_t ctx) { slong i, exp_bits, N, lenr = 0; slong len3 = 0; ulong * cmpmask; ulong * exp2; ulong ** exp3; int free2 = 0; int * free3; fmpz_mpoly_t temp2; fmpz_mpoly_struct * tr; TMP_INIT; /* check none of the divisor polynomials is zero */ for (i = 0; i < len; i++) { if (poly3[i]->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fmpz_mpoly_divrem_ideal_monagan_pearce"); len3 = FLINT_MAX(len3, poly3[i]->length); } fmpz_one(scale); /* dividend is zero, write out quotients and remainder */ if (poly2->length == 0) { for (i = 0; i < len; i++) { fmpz_mpoly_zero(q[i], ctx); } fmpz_mpoly_zero(r, ctx); return; } TMP_START; free3 = (int *) TMP_ALLOC(len*sizeof(int)); exp3 = (ulong **) TMP_ALLOC(len*sizeof(ulong *)); /* compute maximum degrees that can occur in any input or output polys */ exp_bits = poly2->bits; for (i = 0; i < len; i++) exp_bits = FLINT_MAX(exp_bits, poly3[i]->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ exp2 = poly2->exps; free2 = 0; if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } for (i = 0; i < len; i++) { exp3[i] = poly3[i]->exps; free3[i] = 0; if (exp_bits > poly3[i]->bits) { free3[i] = 1; exp3[i] = (ulong *) flint_malloc(N*poly3[i]->length*sizeof(ulong)); mpoly_repack_monomials(exp3[i], exp_bits, poly3[i]->exps, poly3[i]->bits, poly3[i]->length, ctx->minfo); } fmpz_mpoly_fit_length(q[i], 1, ctx); fmpz_mpoly_fit_bits(q[i], exp_bits, ctx); q[i]->bits = exp_bits; } /* check leading mon. of at least one divisor is at most that of dividend */ for (i = 0; i < len; i++) { if (!mpoly_monomial_lt(exp2, exp3[i], N, cmpmask)) break; } if (i == len) { fmpz_mpoly_set(r, poly2, ctx); for (i = 0; i < len; i++) fmpz_mpoly_zero(q[i], ctx); goto cleanup3; } /* take care of aliasing */ if (r == poly2) { fmpz_mpoly_init2(temp2, len3, ctx); fmpz_mpoly_fit_bits(temp2, exp_bits, ctx); temp2->bits = exp_bits; tr = temp2; } else { fmpz_mpoly_fit_length(r, len3, ctx); fmpz_mpoly_fit_bits(r, exp_bits, ctx); r->bits = exp_bits; tr = r; } /* do division with remainder */ while (1) { slong old_exp_bits = exp_bits; ulong * old_exp2 = exp2, * old_exp3; lenr = _fmpz_mpoly_quasidivrem_ideal_heap(scale, q, &tr->coeffs, &tr->exps, &tr->alloc, poly2->coeffs, exp2, poly2->length, poly3, exp3, len, N, exp_bits, ctx, cmpmask); if (lenr >= 0) /* check if division was successful */ break; exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, old_exp2, old_exp_bits, poly2->length, ctx->minfo); if (free2) flint_free(old_exp2); free2 = 1; fmpz_mpoly_fit_bits(tr, exp_bits, ctx); tr->bits = exp_bits; for (i = 0; i < len; i++) { old_exp3 = exp3[i]; exp3[i] = (ulong *) flint_malloc(N*poly3[i]->length*sizeof(ulong)); mpoly_repack_monomials(exp3[i], exp_bits, old_exp3, old_exp_bits, poly3[i]->length, ctx->minfo); if (free3[i]) flint_free(old_exp3); free3[i] = 1; fmpz_mpoly_fit_bits(q[i], exp_bits, ctx); q[i]->bits = exp_bits; } } /* take care of aliasing */ if (r == poly2) { fmpz_mpoly_swap(temp2, r, ctx); fmpz_mpoly_clear(temp2, ctx); } _fmpz_mpoly_set_length(r, lenr, ctx); cleanup3: if (free2) flint_free(exp2); for (i = 0; i < len; i++) { if (free3[i]) flint_free(exp3[i]); } flint_free(cmpmask); TMP_END; } flint-3.1.3/src/fmpz_mpoly/randtest_bits.c000066400000000000000000000024221461254215100206270ustar00rootroot00000000000000/* Copyright (C) 2017, 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_randtest_bits(fmpz_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, flint_bitcnt_t exp_bits, const fmpz_mpoly_ctx_t ctx) { slong i, j, nvars = ctx->minfo->nvars; fmpz * exp; TMP_INIT; TMP_START; exp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exp + j); fmpz_mpoly_zero(A, ctx); for (i = 0; i < length; i++) { mpoly_monomial_randbits_fmpz(exp, state, exp_bits, ctx->minfo); _fmpz_mpoly_push_exp_ffmpz(A, exp, ctx); fmpz_randtest(A->coeffs + A->length - 1, state, coeff_bits); } for (j = 0; j < nvars; j++) fmpz_clear(exp + j); TMP_END; fmpz_mpoly_sort_terms(A, ctx); fmpz_mpoly_combine_like_terms(A, ctx); } flint-3.1.3/src/fmpz_mpoly/randtest_bound.c000066400000000000000000000022661461254215100210030ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_randtest_bound(fmpz_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, ulong exp_bound, const fmpz_mpoly_ctx_t ctx) { slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); fmpz_mpoly_zero(A, ctx); for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bound); _fmpz_mpoly_push_exp_ui(A, exp, ctx); fmpz_randtest(A->coeffs + A->length - 1, state, coeff_bits); } TMP_END; fmpz_mpoly_sort_terms(A, ctx); fmpz_mpoly_combine_like_terms(A, ctx); } flint-3.1.3/src/fmpz_mpoly/randtest_bounds.c000066400000000000000000000022271461254215100211630ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_randtest_bounds(fmpz_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t coeff_bits, ulong * exp_bounds, const fmpz_mpoly_ctx_t ctx) { slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); fmpz_mpoly_zero(A, ctx); for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bounds[j]); _fmpz_mpoly_push_exp_ui(A, exp, ctx); fmpz_randtest(A->coeffs + A->length - 1, state, coeff_bits); } TMP_END; fmpz_mpoly_sort_terms(A, ctx); fmpz_mpoly_combine_like_terms(A, ctx); } flint-3.1.3/src/fmpz_mpoly/realloc.c000066400000000000000000000035571461254215100174150ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void _fmpz_mpoly_realloc(fmpz ** poly, ulong ** exps, slong * alloc, slong len, slong N) { (*poly) = (fmpz *) flint_realloc(*poly, len*sizeof(fmpz)); (*exps) = (ulong *) flint_realloc(*exps, len*N*sizeof(ulong)); if (len > *alloc) memset(*poly + *alloc, 0, (len - *alloc)*sizeof(fmpz)); (*alloc) = len; } void fmpz_mpoly_realloc(fmpz_mpoly_t poly, slong alloc, const fmpz_mpoly_ctx_t ctx) { slong N; if (alloc == 0) /* Clear up, reinitialise */ { fmpz_mpoly_clear(poly, ctx); fmpz_mpoly_init(poly, ctx); return; } N = mpoly_words_per_exp(poly->bits, ctx->minfo); if (poly->alloc != 0) /* Realloc */ { fmpz_mpoly_truncate(poly, alloc, ctx); poly->coeffs = (fmpz *) flint_realloc(poly->coeffs, alloc*sizeof(fmpz)); poly->exps = (ulong *) flint_realloc(poly->exps, alloc*N*sizeof(ulong)); if (alloc > poly->alloc) memset(poly->coeffs + poly->alloc, 0, (alloc - poly->alloc)*sizeof(fmpz)); } else /* Nothing allocated already so do it now */ { poly->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); poly->exps = (ulong *) flint_malloc(alloc*N*sizeof(ulong)); } poly->alloc = alloc; } flint-3.1.3/src/fmpz_mpoly/reduction_primitive_part.c000066400000000000000000000023441461254215100230770ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_reduction_primitive_part(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_vec_t I, const fmpz_mpoly_ctx_t ctx) { fmpz_t scale; fmpz_mpoly_struct ** Q, ** B; slong i, len; len = I->length; fmpz_init(scale); Q = flint_malloc(sizeof(fmpz_mpoly_struct *) * len); B = flint_malloc(sizeof(fmpz_mpoly_struct *) * len); for (i = 0; i < len; i++) { Q[i] = flint_malloc(sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(Q[i], ctx); B[i] = fmpz_mpoly_vec_entry(I, i); } fmpz_mpoly_quasidivrem_ideal(scale, Q, res, f, B, len, ctx); fmpz_mpoly_primitive_part(res, res, ctx); for (i = 0; i < len; i++) { fmpz_mpoly_clear(Q[i], ctx); flint_free(Q[i]); } flint_free(Q); flint_free(B); fmpz_clear(scale); } flint-3.1.3/src/fmpz_mpoly/repack_bits.c000066400000000000000000000042101461254215100202450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_repack_bits(fmpz_mpoly_t A, const fmpz_mpoly_t B, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx) { int success; fmpz_mpoly_t T; Abits = mpoly_fix_bits(Abits, ctx->minfo); if (B->bits == Abits || B->length == 0) { fmpz_mpoly_set(A, B, ctx); return 1; } /* must use B->alloc because we are going to swap coeff in aliasing case */ fmpz_mpoly_init3(T, B->alloc, Abits, ctx); success = mpoly_repack_monomials(T->exps, Abits, B->exps, B->bits, B->length, ctx->minfo); if (success) { if (A == B) { fmpz * temp = A->coeffs; A->coeffs = T->coeffs; T->coeffs = temp; } else { _fmpz_vec_set(T->coeffs, B->coeffs, B->length); } _fmpz_mpoly_set_length(T, B->length, ctx); fmpz_mpoly_swap(A, T, ctx); } fmpz_mpoly_clear(T, ctx); return success; } int fmpz_mpoly_repack_bits_inplace( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx) { int success; ulong * texps; slong N = mpoly_words_per_exp(Abits, ctx->minfo); if (A->bits == Abits) { return 1; } if (A->alloc < 1) { A->bits = Abits; return 1; } texps = (ulong *) flint_malloc(A->alloc*N*sizeof(ulong)); success = mpoly_repack_monomials(texps, Abits, A->exps, A->bits, A->length, ctx->minfo); if (success) { ulong * t = A->exps; A->exps = texps; texps = t; A->bits = Abits; } flint_free(texps); return success; } flint-3.1.3/src/fmpz_mpoly/resize.c000066400000000000000000000024601461254215100172650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_resize(fmpz_mpoly_t A, slong new_length, const fmpz_mpoly_ctx_t ctx) { slong old_length = A->length; slong N; new_length = FLINT_MAX(WORD(0), new_length); N = mpoly_words_per_exp(A->bits, ctx->minfo); if (new_length < old_length) { /* just zero out the extra unused fmpz's past the new end */ _fmpz_vec_zero(A->coeffs + new_length, old_length - new_length); } else if (new_length > old_length) { if (new_length > A->alloc) fmpz_mpoly_realloc(A, FLINT_MAX(new_length, 2*A->alloc), ctx); /* must zero out the new coeffs/exps past the old end */ flint_mpn_zero(A->exps + N*old_length, N*(new_length - old_length)); _fmpz_vec_zero(A->coeffs + old_length, new_length - old_length); } A->length = new_length; } flint-3.1.3/src/fmpz_mpoly/resultant.c000066400000000000000000000016311461254215100200040ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int fmpz_mpoly_resultant(fmpz_mpoly_t R, const fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) { int success; fmpz_mpoly_univar_t Ax, Bx; fmpz_mpoly_univar_init(Ax, ctx); fmpz_mpoly_univar_init(Bx, ctx); fmpz_mpoly_to_univar(Ax, A, var, ctx); fmpz_mpoly_to_univar(Bx, B, var, ctx); success = fmpz_mpoly_univar_resultant(R, Ax, Bx, ctx); fmpz_mpoly_univar_clear(Ax, ctx); fmpz_mpoly_univar_clear(Bx, ctx); return success; } flint-3.1.3/src/fmpz_mpoly/reverse.c000066400000000000000000000022421461254215100174350ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_reverse(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { slong i; slong Blen = B->length; slong N = mpoly_words_per_exp(B->bits, ctx->minfo); if (A != B) { fmpz_mpoly_fit_length(A, Blen, ctx); fmpz_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; A->length = B->length; for (i = 0; i < Blen; i++) { fmpz_set(A->coeffs + i, B->coeffs + Blen - i - 1); } } else { for (i = 0; i < Blen/2; i++) { fmpz_swap(A->coeffs + i, A->coeffs + Blen - i - 1); } } mpoly_reverse(A->exps, B->exps, Blen, N); } flint-3.1.3/src/fmpz_mpoly/scalar_divexact_fmpz.c000066400000000000000000000031001461254215100221440ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_scalar_divexact_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { slong N; if (A != B) { N = mpoly_words_per_exp(B->bits, ctx->minfo); fmpz_mpoly_fit_length(A, B->length, ctx); fmpz_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; mpn_copyi(A->exps, B->exps, N*B->length); } _fmpz_vec_scalar_divexact_fmpz(A->coeffs, B->coeffs, B->length, c); _fmpz_mpoly_set_length(A, B->length, ctx); } void fmpz_mpoly_scalar_divexact_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, c); fmpz_mpoly_scalar_divexact_fmpz(A, B, t, ctx); fmpz_clear(t); } void fmpz_mpoly_scalar_divexact_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_si(t, c); fmpz_mpoly_scalar_divexact_fmpz(A, B, t, ctx); fmpz_clear(t); } flint-3.1.3/src/fmpz_mpoly/scalar_divides_fmpz.c000066400000000000000000000042031461254215100217710ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* leave vec1 undefined but valid if division is not exact */ int _fmpz_vec_scalar_divides_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x) { slong i; fmpz_t r; fmpz_init(r); for (i = 0; i < len2; i++) { fmpz_fdiv_qr(vec1 + i, r, vec2 + i, x); if (!fmpz_is_zero(r)) { fmpz_clear(r); return 0; } } fmpz_clear(r); return 1; } int fmpz_mpoly_scalar_divides_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { int divides; slong N; if (A != B) { N = mpoly_words_per_exp(B->bits, ctx->minfo); fmpz_mpoly_fit_length(A, B->length, ctx); fmpz_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; mpn_copyi(A->exps, B->exps, N*B->length); } divides = _fmpz_vec_scalar_divides_fmpz(A->coeffs, B->coeffs, B->length, c); _fmpz_mpoly_set_length(A, divides ? B->length : WORD(0), ctx); return divides; } int fmpz_mpoly_scalar_divides_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) { int divides; fmpz_t t; fmpz_init_set_ui(t, c); divides = fmpz_mpoly_scalar_divides_fmpz(A, B, t, ctx); fmpz_clear(t); return divides; } int fmpz_mpoly_scalar_divides_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) { int divides; fmpz_t t; fmpz_init(t); fmpz_set_si(t, c); divides = fmpz_mpoly_scalar_divides_fmpz(A, B, t, ctx); fmpz_clear(t); return divides; } flint-3.1.3/src/fmpz_mpoly/scalar_fmma.c000066400000000000000000000202521461254215100202300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" static slong _fmpz_mpoly_scalar_fmma1( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz_t c, const fmpz * Dcoeffs, const ulong * Dexps, slong Dlen, const fmpz_t e, ulong maskhi) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Dlen) { if ((Bexps[i]^maskhi) > (Dexps[j]^maskhi)) { fmpz_mul(Acoeffs + k, Bcoeffs + i, c); Aexps[k] = Bexps[i]; i++; k++; } else if ((Bexps[i]^maskhi) == (Dexps[j]^maskhi)) { fmpz_fmma(Acoeffs + k, Bcoeffs + i, c, Dcoeffs + j, e); Aexps[k] = Bexps[i]; k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { fmpz_mul(Acoeffs + k, Dcoeffs + j, e); Aexps[k] = Dexps[j]; j++; k++; } } while (i < Blen) { fmpz_mul(Acoeffs + k, Bcoeffs + i, c); Aexps[k] = Bexps[i]; i++; k++; } while (j < Dlen) { fmpz_mul(Acoeffs + k, Dcoeffs + j, e); Aexps[k] = Dexps[j]; j++; k++; } return k; } static slong _fmpz_mpoly_scalar_fmma( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz_t c, const fmpz * Dcoeffs, const ulong * Dexps, slong Dlen, const fmpz_t e, slong N, const ulong * cmpmask) { slong i = 0, j = 0, k = 0; if (N == 1) { return _fmpz_mpoly_scalar_fmma1(Acoeffs, Aexps, Bcoeffs, Bexps, Blen, c, Dcoeffs, Dexps, Dlen, e, cmpmask[0]); } while (i < Blen && j < Dlen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Dexps + j*N, N, cmpmask); if (cmp > 0) { fmpz_mul(Acoeffs + k, Bcoeffs + i, c); mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); i++; k++; } else if (cmp == 0) { fmpz_fmma(Acoeffs + k, Bcoeffs + i, c, Dcoeffs + j, e); mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { fmpz_mul(Acoeffs + k, Dcoeffs + j, e); mpoly_monomial_set(Aexps + k*N, Dexps + j*N, N); j++; k++; } } while (i < Blen) { fmpz_mul(Acoeffs + k, Bcoeffs + i, c); mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); i++; k++; } while (j < Dlen) { fmpz_mul(Acoeffs + k, Dcoeffs + j, e); mpoly_monomial_set(Aexps + k*N, Dexps + j*N, N); j++; k++; } return k; } /* A = A*a + B*b */ void fmpz_mpoly_scalar_fmma_inplace( fmpz_mpoly_t A, const fmpz_t a, const fmpz_mpoly_t B, const fmpz_t b, const fmpz_mpoly_ctx_t ctx) { slong i, s, new_len, N; slong Alen = A->length; slong Blen = B->length; ulong * Bexps, * cmpmask; int cmp, freeBexps; flint_bitcnt_t Abits; fmpz_mpoly_t T; TMP_INIT; FLINT_ASSERT(A != B); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(!fmpz_is_zero(a)); FLINT_ASSERT(!fmpz_is_zero(b)); TMP_START; if (A->bits <= B->bits) { Abits = B->bits; if (A->bits < B->bits) fmpz_mpoly_repack_bits_inplace(A, Abits, ctx); N = mpoly_words_per_exp(Abits, ctx->minfo); Bexps = B->exps; freeBexps = 0; } else { Abits = A->bits; N = mpoly_words_per_exp(Abits, ctx->minfo); Bexps = (ulong *) flint_malloc(N*Blen*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, Blen, ctx->minfo); freeBexps = 1; } cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); for (s = 0; s < Alen/4; s++) { cmp = mpoly_monomial_cmp(A->exps + N*(Alen - s - 1), Bexps + N*0, N, cmpmask); if (cmp >= 0) { s += (cmp == 0); goto doit; } } fmpz_mpoly_init3(T, Alen + Blen, Abits, ctx); T->length = _fmpz_mpoly_scalar_fmma(T->coeffs, T->exps, A->coeffs, A->exps, Alen, a, B->coeffs, Bexps, Blen, b, N, cmpmask); fmpz_mpoly_swap(A, T, ctx); fmpz_mpoly_clear(T, ctx); goto cleanup; doit: FLINT_ASSERT(0 <= s && s <= Alen); FLINT_ASSERT(s == 0 || mpoly_monomial_cmp(A->exps + N*(Alen - s), Bexps + N*0, N, cmpmask) <= 0); FLINT_ASSERT(s == Alen || mpoly_monomial_cmp(A->exps + N*(Alen - s - 1), Bexps + N*0, N, cmpmask) > 0); fmpz_mpoly_fit_length(A, Alen + Blen + s, ctx); mpoly_copy_monomials(A->exps + N*(Alen + Blen), A->exps + N*(Alen - s), s, N); _fmpz_vec_swap(A->coeffs + Alen + Blen, A->coeffs + Alen - s, s); if (!fmpz_is_one(a)) _fmpz_vec_scalar_mul_fmpz(A->coeffs, A->coeffs, Alen - s, a); new_len = _fmpz_mpoly_scalar_fmma( A->coeffs + Alen - s, A->exps + N*(Alen - s), A->coeffs + (Alen + Blen), A->exps + N*(Alen + Blen), s, a, B->coeffs, Bexps, Blen, b, N, cmpmask); for (i = 0; i < s; i++) _fmpz_demote(A->coeffs + Alen + Blen + i); _fmpz_mpoly_set_length(A, Alen - s + new_len, ctx); cleanup: if (freeBexps) flint_free(Bexps); TMP_END; return; } /* A = B*c + D*e */ void fmpz_mpoly_scalar_fmma( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_t D, const fmpz_t e, const fmpz_mpoly_ctx_t ctx) { slong len, N; flint_bitcnt_t Abits; ulong * Bexps = B->exps, * Dexps = D->exps; ulong * cmpmask; int freeBexps = 0, freeDexps = 0; TMP_INIT; if (fmpz_mpoly_is_zero(B, ctx) || fmpz_is_zero(c)) { fmpz_mpoly_scalar_mul_fmpz(A, D, e, ctx); return; } else if (fmpz_mpoly_is_zero(D, ctx) || fmpz_is_zero(e)) { fmpz_mpoly_scalar_mul_fmpz(A, B, c, ctx); return; } else if (A == B) { if (A == D) { fmpz_t t; fmpz_init(t); fmpz_add(t, c, e); fmpz_mpoly_scalar_mul_fmpz(A, A, t, ctx); fmpz_clear(t); } else { fmpz_mpoly_scalar_fmma_inplace(A, c, D, e, ctx); } return; } else if (A == D) { fmpz_mpoly_scalar_fmma_inplace(A, e, B, c, ctx); return; } Abits = FLINT_MAX(B->bits, D->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); TMP_START; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != D->bits) { freeDexps = 1; Dexps = (ulong *) flint_malloc(N*D->length*sizeof(ulong)); mpoly_repack_monomials(Dexps, Abits, D->exps, D->bits, D->length, ctx->minfo); } fmpz_mpoly_fit_length_reset_bits(A, B->length + D->length, Abits, ctx); len = _fmpz_mpoly_scalar_fmma(A->coeffs, A->exps, B->coeffs, Bexps, B->length, c, D->coeffs, Dexps, D->length, e, N, cmpmask); _fmpz_mpoly_set_length(A, len, ctx); if (freeBexps) flint_free(Bexps); if (freeDexps) flint_free(Dexps); TMP_END; } flint-3.1.3/src/fmpz_mpoly/scalar_mul_fmpz.c000066400000000000000000000031371461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { slong N; if (fmpz_is_zero(c)) { _fmpz_mpoly_set_length(A, 0, ctx); return; } if (A != B) { N = mpoly_words_per_exp(B->bits, ctx->minfo); fmpz_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); } if ((A != B) || !fmpz_is_one(c)) _fmpz_vec_scalar_mul_fmpz(A->coeffs, B->coeffs, B->length, c); _fmpz_mpoly_set_length(A, B->length, ctx); } void fmpz_mpoly_scalar_mul_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, c); fmpz_mpoly_scalar_mul_fmpz(A, B, t, ctx); fmpz_clear(t); } void fmpz_mpoly_scalar_mul_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_si(t, c); fmpz_mpoly_scalar_mul_fmpz(A, B, t, ctx); fmpz_clear(t); } flint-3.1.3/src/fmpz_mpoly/select_exps.c000066400000000000000000000107721461254215100203070ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* When selecting expoenent ranges for the parallel division A/B, we can also detect if an exact division is impossible. The return is non zero in this case. This function is used by {fmpz|nmod}_mpoly_divides_heap_threaded, and must be placed in the fmpz_mpoly module because it uses an fmpz_mpoly_t to accumulate and sort the exponents. */ int mpoly_divides_select_exps(fmpz_mpoly_t S, fmpz_mpoly_ctx_t zctx, slong nworkers, ulong * Aexp, slong Alen, ulong * Bexp, slong Blen, flint_bitcnt_t bits) { int failure; ulong mask; ulong * Sexp; slong Slen; fmpz * Scoeff; slong nA = 30 + 8*nworkers; /* number of division of A */ slong nB = (1 + nworkers)/2; /* number of division of B */ slong tot; ulong * T0, * T1; slong i, j, N; TMP_INIT; TMP_START; N = mpoly_words_per_exp(bits, zctx->minfo); mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); tot = 16 + nA + 2*nB; fmpz_mpoly_fit_bits(S, bits, zctx); S->bits = bits; fmpz_mpoly_fit_length(S, tot, zctx); Sexp = S->exps; Scoeff = S->coeffs; Slen = 0; /* get a (non-strict) upper bound on the exponents of A */ mpoly_monomial_set(Sexp + N*Slen, Aexp + N*0, N); fmpz_one(Scoeff + Slen); Slen++; for (i = 1; i < nA; i++) { double a = 1.0; double b = 0.2; double d = (double)(i) / (double)(nA); /* set d to p(d) where p is the cubic satisfying p(0) = 0, p'(0) = a p(1) = 1, p'(1) = b */ FLINT_ASSERT(a >= 0); FLINT_ASSERT(b >= 0); d = d*(1 + (1 - d)*((2 - a - b)*d - (1 - a))); /* choose exponent at relative position d in A */ j = d * Alen; j = FLINT_MAX(j, WORD(0)); j = FLINT_MIN(j, Alen - 1); mpoly_monomial_set(Sexp + N*Slen, Aexp + N*j, N); fmpz_one(Scoeff + Slen); Slen++; } _fmpz_mpoly_set_length(S, Slen, zctx); T0 = (ulong *) TMP_ALLOC(N*sizeof(ulong)); T1 = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_sub_mp(T0, Aexp + N*0, Bexp + N*0, N); mpoly_monomial_sub_mp(T1, Aexp + N*(Alen - 1), Bexp + N*(Blen - 1), N); if (bits <= FLINT_BITS) { if ( mpoly_monomial_overflows(T0, N, mask) || mpoly_monomial_overflows(T1, N, mask)) { failure = 1; goto cleanup; } } else { if ( mpoly_monomial_overflows_mp(T0, N, bits) || mpoly_monomial_overflows_mp(T1, N, bits)) { failure = 1; goto cleanup; } } for (i = 1; i < nB; i++) { double d = (double)(i) / (double)(nB); /* choose exponent at relative position d in B */ j = d * Blen; j = FLINT_MAX(j, WORD(0)); j = FLINT_MIN(j, Blen - 1); mpoly_monomial_sub_mp(Sexp + N*Slen, Aexp + N*0, Bexp + N*0, N); mpoly_monomial_add_mp(Sexp + N*Slen, Sexp + N*Slen, Bexp + N*j, N); fmpz_one(Scoeff + Slen); if (bits <= FLINT_BITS) Slen += !(mpoly_monomial_overflows(Sexp + N*Slen, N, mask)); else Slen += !(mpoly_monomial_overflows_mp(Sexp + N*Slen, N, bits)); mpoly_monomial_sub_mp(Sexp + N*Slen, Aexp + N*(Alen - 1), Bexp + N*(Blen - 1), N); mpoly_monomial_add_mp(Sexp + N*Slen, Sexp + N*Slen, Bexp + N*j, N); fmpz_one(Scoeff + Slen); if (bits <= FLINT_BITS) Slen += !(mpoly_monomial_overflows(Sexp + N*Slen, N, mask)); else Slen += !(mpoly_monomial_overflows_mp(Sexp + N*Slen, N, bits)); } /* get a lower bound on the exponents of A */ mpoly_monomial_zero(Sexp + N*Slen, N); fmpz_one(Scoeff + Slen); Slen++; /* done constructing S */ FLINT_ASSERT(Slen < tot); _fmpz_mpoly_set_length(S, Slen, zctx); fmpz_mpoly_sort_terms(S, zctx); fmpz_mpoly_combine_like_terms(S, zctx); failure = 0; cleanup: TMP_END; return failure; } flint-3.1.3/src/fmpz_mpoly/set.c000066400000000000000000000024771461254215100165670ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void _fmpz_mpoly_set(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong n, slong N) { slong i; if (poly1 != poly2) { for (i = 0; i < n; i++) fmpz_set(poly1 + i, poly2 + i); } if (exps1 != exps2) { for (i = 0; i < n*N; i++) exps1[i] = exps2[i]; } } void fmpz_mpoly_set(fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, const fmpz_mpoly_ctx_t ctx) { slong N; N = mpoly_words_per_exp(poly2->bits, ctx->minfo); fmpz_mpoly_fit_length(poly1, poly2->length, ctx); fmpz_mpoly_fit_bits(poly1, poly2->bits, ctx); _fmpz_mpoly_set(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, N); _fmpz_mpoly_set_length(poly1, poly2->length, ctx); poly1->bits = poly2->bits; } flint-3.1.3/src/fmpz_mpoly/set_coeff_fmpz_fmpz.c000066400000000000000000000055471461254215100220220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void _fmpz_mpoly_set_coeff_fmpz_fmpz(fmpz_mpoly_t poly, const fmpz_t c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) { flint_bitcnt_t exp_bits; slong i, N, index; ulong * cmpmask; ulong * packed_exp; int exists; TMP_INIT; TMP_START; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_bits(poly, exp_bits, ctx); N = mpoly_words_per_exp(poly->bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, poly->bits, ctx->minfo); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, poly->bits, ctx->minfo); exists = mpoly_monomial_exists(&index, poly->exps, packed_exp, poly->length, N, cmpmask); if (!exists) { if (!fmpz_is_zero(c)) /* make new term only if coeff is nonzero*/ { fmpz_mpoly_fit_length(poly, poly->length + 1, ctx); for (i = poly->length; i >= index + 1; i--) { fmpz_set(poly->coeffs + i, poly->coeffs + i - 1); mpoly_monomial_set(poly->exps + N*i, poly->exps + N*(i - 1), N); } fmpz_set(poly->coeffs + index, c); mpoly_monomial_set(poly->exps + N*index, packed_exp, N); poly->length++; /* safe because length is increasing */ } } else if (fmpz_is_zero(c)) /* zero coeff, remove term */ { for (i = index; i < poly->length - 1; i++) { fmpz_set(poly->coeffs + i, poly->coeffs + i + 1); mpoly_monomial_set(poly->exps + N*i, poly->exps + N*(i + 1), N); } _fmpz_mpoly_set_length(poly, poly->length - 1, ctx); } else /* term with that monomial exists, coeff is nonzero */ { fmpz_set(poly->coeffs + index, c); } TMP_END; } void fmpz_mpoly_set_coeff_fmpz_fmpz(fmpz_mpoly_t poly, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_init(newexp + i); fmpz_set(newexp + i, exp[i]); } _fmpz_mpoly_set_coeff_fmpz_fmpz(poly, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fmpz_mpoly/set_coeff_fmpz_monomial.c000066400000000000000000000021711461254215100226470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_coeff_fmpz_monomial(fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_t M, const fmpz_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * texps; TMP_INIT; if (M->length != WORD(1)) { flint_throw(FLINT_ERROR, "M not monomial in fmpz_mpoly_set_coeff_fmpz_monomial"); } TMP_START; texps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init(texps + i); mpoly_get_monomial_ffmpz(texps, M->exps + 0, M->bits, ctx->minfo); _fmpz_mpoly_set_coeff_fmpz_fmpz(A, c, texps, ctx); for (i = 0; i < nvars; i++) fmpz_clear(texps + i); TMP_END; return; } flint-3.1.3/src/fmpz_mpoly/set_coeff_fmpz_ui.c000066400000000000000000000016271461254215100214560ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_coeff_fmpz_ui(fmpz_mpoly_t poly, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); _fmpz_mpoly_set_coeff_fmpz_fmpz(poly, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fmpz_mpoly/set_coeff_si_fmpz.c000066400000000000000000000013011461254215100214410ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_coeff_si_fmpz(fmpz_mpoly_t poly, const slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { fmpz_t newc; fmpz_init(newc); fmpz_set_si(newc, c); fmpz_mpoly_set_coeff_fmpz_fmpz(poly, newc, exp, ctx); fmpz_clear(newc); } flint-3.1.3/src/fmpz_mpoly/set_coeff_si_ui.c000066400000000000000000000012741461254215100211130ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_coeff_si_ui(fmpz_mpoly_t poly, const slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { fmpz_t newc; fmpz_init(newc); fmpz_set_si(newc, c); fmpz_mpoly_set_coeff_fmpz_ui(poly, newc, exp, ctx); fmpz_clear(newc); } flint-3.1.3/src/fmpz_mpoly/set_coeff_ui_fmpz.c000066400000000000000000000013011461254215100214430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_coeff_ui_fmpz(fmpz_mpoly_t poly, const ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { fmpz_t newc; fmpz_init(newc); fmpz_set_ui(newc, c); fmpz_mpoly_set_coeff_fmpz_fmpz(poly, newc, exp, ctx); fmpz_clear(newc); } flint-3.1.3/src/fmpz_mpoly/set_coeff_ui_ui.c000066400000000000000000000012741461254215100211150ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_coeff_ui_ui(fmpz_mpoly_t poly, const ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { fmpz_t newc; fmpz_init(newc); fmpz_set_ui(newc, c); fmpz_mpoly_set_coeff_fmpz_ui(poly, newc, exp, ctx); fmpz_clear(newc); } flint-3.1.3/src/fmpz_mpoly/set_fmpz.c000066400000000000000000000016151461254215100176140ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_fmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (fmpz_is_zero(c)) { _fmpz_mpoly_set_length(A, 0, ctx); return; } fmpz_mpoly_fit_length(A, 1, ctx); fmpz_set(A->coeffs + 0, c); mpoly_monomial_zero(A->exps + N*0, N); _fmpz_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/fmpz_mpoly/set_si.c000066400000000000000000000015321461254215100172510ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_si(fmpz_mpoly_t A, slong c, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (c == 0) { _fmpz_mpoly_set_length(A, 0, ctx); return; } fmpz_mpoly_fit_length(A, 1, ctx); fmpz_set_si(A->coeffs + 0, c); mpoly_monomial_zero(A->exps + N*0, N); _fmpz_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/fmpz_mpoly/set_str_pretty.c000066400000000000000000000023711461254215100210570ustar00rootroot00000000000000/* Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_set_str_pretty(fmpz_mpoly_t poly, const char * str, const char** x, const fmpz_mpoly_ctx_t ctx) { int ret; slong i; fmpz_mpoly_t val; mpoly_parse_t E; char dummy[FLINT_BITS/2]; mpoly_void_ring_init_fmpz_mpoly_ctx(E->R, ctx); mpoly_parse_init(E); fmpz_mpoly_init(val, ctx); for (i = 0; i < ctx->minfo->nvars; i++) { fmpz_mpoly_gen(val, i, ctx); if (x == NULL) { flint_sprintf(dummy, "x%wd", i + 1); mpoly_parse_add_terminal(E, dummy, (const void *)val); } else { mpoly_parse_add_terminal(E, x[i], (const void *)val); } } fmpz_mpoly_clear(val, ctx); ret = mpoly_parse_parse(E, poly, str, strlen(str)); mpoly_parse_clear(E); return ret; } flint-3.1.3/src/fmpz_mpoly/set_term_coeff_fmpz.c000066400000000000000000000025741461254215100220120ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_term_coeff_fmpz(fmpz_mpoly_t A, slong i, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_set_term_coeff_fmpz"); } fmpz_set(A->coeffs + i, c); } void fmpz_mpoly_set_term_coeff_ui(fmpz_mpoly_t A, slong i, ulong c, const fmpz_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_set_term_coeff_ui"); } fmpz_set_ui(A->coeffs + i, c); } void fmpz_mpoly_set_term_coeff_si(fmpz_mpoly_t A, slong i, slong c, const fmpz_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_set_term_coeff_si"); } fmpz_set_si(A->coeffs + i, c); } flint-3.1.3/src/fmpz_mpoly/set_term_exp_fmpz.c000066400000000000000000000017771461254215100215300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_term_exp_fmpz(fmpz_mpoly_t A, slong i, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_set_term_exp_fmpz"); } exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_bits(A, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_pfmpz(A->exps + N*i, exp, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/set_term_exp_ui.c000066400000000000000000000020301461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_term_exp_ui(fmpz_mpoly_t A, slong i, const ulong * exp, const fmpz_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fmpz_mpoly_set_term_exp_ui"); } exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fmpz_mpoly_fit_bits(A, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ui(A->exps + N*i, exp, A->bits, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/set_ui.c000066400000000000000000000016151461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_set_ui(fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (c == 0) { _fmpz_mpoly_set_length(A, 0, ctx); return; } N = mpoly_words_per_exp(A->bits, ctx->minfo); fmpz_mpoly_fit_length(A, 1, ctx); fmpz_set_ui(A->coeffs + 0, c); mpoly_monomial_zero(A->exps + N*0, N); _fmpz_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/fmpz_mpoly/sort_terms.c000066400000000000000000000107021461254215100201630ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* sort terms in [left, right) by exponent assuming that bits in position > pos are already sorted and assuming exponent vectors fit into one word and assuming that all bit positions that need to be sorted are in totalmask */ void _fmpz_mpoly_radix_sort1(fmpz_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask) { ulong mask = UWORD(1) << pos; ulong cmp = cmpmask & mask; slong mid, cur; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < FLINT_BITS); /* do nothing on lists of 0 or 1 elements */ if (left + 1 >= right) { return; } /* return if there is no information to sort on this bit */ if ((totalmask & mask) == WORD(0)) { --pos; if ((slong)(pos) >= 0) { _fmpz_mpoly_radix_sort1(A, left, right, pos, cmpmask, totalmask); } return; } /* find first 'zero' */ mid = left; while (mid < right && ((A->exps + 1*mid)[0] & mask) != cmp) { mid++; } /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ cur = mid; while (++cur < right) { if (((A->exps + 1*cur)[0] & mask) != cmp) { fmpz_swap(A->coeffs + cur, A->coeffs + mid); mpoly_monomial_swap(A->exps + 1*cur, A->exps + 1*mid, 1); mid++; } } --pos; if ((slong)(pos) >= 0) { _fmpz_mpoly_radix_sort1(A, left, mid, pos, cmpmask, totalmask); _fmpz_mpoly_radix_sort1(A, mid, right, pos, cmpmask, totalmask); } } /* sort terms in [left, right) by exponent assuming that bits in position > pos are already sorted TODO: Stack depth is proportional to N*FLINT_BITS Might turn into iterative version Low priority */ void _fmpz_mpoly_radix_sort(fmpz_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask) { ulong off = pos/FLINT_BITS; ulong bit = pos%FLINT_BITS; ulong mask = UWORD(1) << bit; ulong cmp = cmpmask[off] & mask; slong mid, check; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < N*FLINT_BITS); /* do nothing on lists of 0 or 1 elements */ if (left + 1 >= right) return; /* find first 'zero' */ mid = left; while (mid < right && ((A->exps+N*mid)[off] & mask) != cmp) { mid++; } /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ check = mid; while (++check < right) { if (((A->exps + N*check)[off] & mask) != cmp) { fmpz_swap(A->coeffs + check, A->coeffs + mid); mpoly_monomial_swap(A->exps + N*check, A->exps + N*mid, N); mid++; } } --pos; if ((slong)(pos) >= 0) { _fmpz_mpoly_radix_sort(A, left, mid, pos, N, cmpmask); _fmpz_mpoly_radix_sort(A, mid, right, pos, N, cmpmask); } } /* sort the terms in A by exponent assuming that the exponents are valid (other than being in order) */ void fmpz_mpoly_sort_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i, msb, N; ulong himask, * ptempexp; TMP_INIT; TMP_START; N = mpoly_words_per_exp(A->bits, ctx->minfo); ptempexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(ptempexp, N, A->bits, ctx->minfo); himask = 0; for (i = 0; i < A->length; i++) { himask |= (A->exps + N*i)[N - 1]; } if (himask != 0) { msb = flint_clz(himask); msb = (FLINT_BITS - 1)^msb; } else { msb = -WORD(1); } if (N == 1) { if (msb >= 0) { _fmpz_mpoly_radix_sort1(A, 0, A->length, msb, ptempexp[0], himask); } } else { _fmpz_mpoly_radix_sort(A, 0, A->length, (N - 1)*FLINT_BITS + msb, N, ptempexp); } TMP_END; } flint-3.1.3/src/fmpz_mpoly/spoly.c000066400000000000000000000033421461254215100171320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_spoly(fmpz_mpoly_t res, const fmpz_mpoly_t f, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx) { slong n, i; ulong * exp, * expf, * expg; fmpz_t c, d; fmpz_mpoly_t T, U; if (f->length == 0 || g->length == 0) { fmpz_mpoly_zero(res, ctx); return; } n = ctx->minfo->nvars; exp = flint_malloc(sizeof(ulong) * n); expf = flint_malloc(sizeof(ulong) * n); expg = flint_malloc(sizeof(ulong) * n); fmpz_init(c); fmpz_init(d); fmpz_mpoly_init(T, ctx); fmpz_mpoly_init(U, ctx); fmpz_mpoly_get_term_exp_ui(expf, f, 0, ctx); fmpz_mpoly_get_term_exp_ui(expg, g, 0, ctx); for (i = 0; i < n; i++) exp[i] = FLINT_MAX(expf[i], expg[i]); fmpz_lcm(c, f->coeffs, g->coeffs); fmpz_divexact(d, c, g->coeffs); fmpz_divexact(c, c, f->coeffs); for (i = 0; i < n; i++) { expf[i] = exp[i] - expf[i]; expg[i] = exp[i] - expg[i]; } fmpz_mpoly_set_coeff_fmpz_ui(T, c, expf, ctx); fmpz_mpoly_mul(T, T, f, ctx); fmpz_mpoly_set_coeff_fmpz_ui(U, d, expg, ctx); fmpz_mpoly_mul(U, U, g, ctx); fmpz_mpoly_sub(res, T, U, ctx); flint_free(exp); flint_free(expf); flint_free(expg); fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_clear(T, ctx); fmpz_mpoly_clear(U, ctx); } flint-3.1.3/src/fmpz_mpoly/sqrt_heap.c000066400000000000000000001072551461254215100177620ustar00rootroot00000000000000/* Copyright (C) 2016, 2020 William Hart Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif #include "gmpcompat.h" #include "mpn_extras.h" #include "nmod.h" #include "nmod_mpoly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* if r is the returned mpz, then x = r + sm, where sm is a signed 3 limb integer it must be safe to add +-COEFF_MAX^2*2^FLINT_BITS to the returned sm t is temp space since x is not to be modified */ static mpz_srcptr _fmpz_mpoly_get_mpz_signed_uiuiui(ulong * sm, fmpz x, mpz_ptr t) { mpz_ptr p; slong i, abs_size; ulong s; if (!COEFF_IS_MPZ(x)) { sm[0] = x; sm[1] = FLINT_SIGN_EXT(x); sm[2] = FLINT_SIGN_EXT(x); } else { p = COEFF_TO_PTR(x); sm[0] = 0; sm[1] = 0; sm[2] = 0; s = FLINT_SIGN_EXT(p->_mp_size); abs_size = FLINT_ABS(p->_mp_size); if (abs_size > 3 || (abs_size == 3 && p->_mp_d[2] >= COEFF_MAX)) return p; for (i = 0; i < abs_size; i++) sm[i] = p->_mp_d[i]; sub_dddmmmsss(sm[2], sm[1], sm[0], s^sm[2], s^sm[1], s^sm[0], s, s, s); } mpz_set_ui(t, 0); return t; } /* try to prove that A is not a square */ static int _is_proved_not_square( int count, mp_limb_t * p, flint_rand_t state, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx) { int success = 0; slong i, N = mpoly_words_per_exp(Abits, mctx); mp_limb_t eval, * alphas; nmod_t mod; ulong * t; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; t = (ulong *) TMP_ALLOC(FLINT_MAX(Alen, N)*sizeof(ulong)); if (count == 1) { success = mpoly_is_proved_not_square(Aexps, Alen, Abits, N, t); if (success) goto cleanup; } /* try at most 3*count evaluations */ count *= 3; alphas = (mp_limb_t *) TMP_ALLOC(mctx->nvars*sizeof(mp_limb_t)); next_p: if (*p >= UWORD_MAX_PRIME) *p = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); *p = n_nextprime(*p, 1); nmod_init(&mod, *p); for (i = 0; i < mctx->nvars; i++) alphas[i] = n_urandint(state, mod.n); _fmpz_vec_get_nmod_vec(t, Acoeffs, Alen, mod); eval = _nmod_mpoly_eval_all_ui(t, Aexps, Alen, Abits, alphas, mctx, mod); success = n_jacobi_unsigned(eval, mod.n) < 0; if (!success && --count >= 0) goto next_p; cleanup: TMP_END; return success; } /* Set polyq to the square root of A and return the length of the square root if it exists or zero otherwise. This version of the function assumes the exponent vectors all fit in a single word. The exponent vectors are assumed to have fields with the given number of bits. Assumes input poly is nonzero. Implements "Heap based multivariate square root" by William Hart. Square root is from left to right with a heap with largest exponent at the head. Output poly is written in order. A never explicitly goes into the heap and is only scanned once. TODO: copy this strategy for the "small" case (i.e. no fmpz arithmetic) to the other fmpz mpoly mul/div functions. */ slong _fmpz_mpoly_sqrt_heap1( fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t bits, const mpoly_ctx_t mctx, int check) { slong i, j, Qlen, Ai; slong next_loc, heap_len = 1, heap_alloc; mpoly_heap1_s * heap; mpoly_heap_t * chain_nodes[64]; mpoly_heap_t ** chain; slong exp_alloc; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = *polyq; ulong * Qexps = *expq; ulong mask, exp, exp3 = 0; ulong maskhi; mpz_t r, acc, acc2; mpz_srcptr acc_lg; mpz_ptr t; ulong acc_sm[3], acc_sm2[3], pp[3]; int lt_divides, q_rest_small; flint_rand_t heuristic_state; mp_limb_t heuristic_p = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); int heuristic_count = 0; ulong lc_abs = 0; /* 2*sqrt(lc) if it fits in ulong, otherwise 0 */ ulong lc_norm = 0; ulong lc_n = 0; ulong lc_i = 0; mpz_ptr lc_lg = NULL; /* 2*sqrt(lc) if it is large */ FLINT_ASSERT(mpoly_words_per_exp(bits, mctx) == 1); mpoly_get_cmpmask(&maskhi, 1, bits, mctx); flint_randinit(heuristic_state); mpz_init(r); mpz_init(acc); mpz_init(acc2); /* alloc array of heap nodes which can be chained together */ next_loc = 2*n_sqrt(Alen) + 4; /* something bigger than heap can ever be */ heap_alloc = next_loc - 3; heap = (mpoly_heap1_s *) flint_malloc((heap_alloc + 1)*sizeof(mpoly_heap1_s)); chain_nodes[0] = (mpoly_heap_t *) flint_malloc(heap_alloc*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_malloc(heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_malloc(2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc; i++) chain[i] = chain_nodes[0] + i; exp_alloc = 1; mask = mpoly_overflow_mask_sp(bits); Qlen = 0; /* "insert" (-1, 1, Aexps[1]) into "heap" */ Ai = 1; /* compute first term */ if (!fmpz_is_square(Acoeffs + 0)) goto not_sqrt; _fmpz_mpoly_fit_length(&Qcoeffs, &Qexps, allocq, Qlen + 1, 1); fmpz_sqrt(Qcoeffs + 0, Acoeffs + 0); Qlen++; /* multiply by 2, we revert this at the end */ fmpz_mul_2exp(Qcoeffs + 0, Qcoeffs + 0, 1); /* q_rest_small means Qcoeffs[1] ... Qcoeffs[Qlen-1] are small */ q_rest_small = 1; if (fmpz_abs_fits_ui(Qcoeffs + 0)) { lc_abs = fmpz_get_ui(Qcoeffs + 0); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } else { lc_lg = COEFF_TO_PTR(Qcoeffs[0]); } if (!mpoly_monomial_halves1(Qexps + 0, Aexps[0], mask)) goto not_sqrt; /* exponent is not square */ /* optimisation, compute final exponent */ { if (!fmpz_is_square(Acoeffs + Alen - 1)) goto not_sqrt; if (!mpoly_monomial_halves1(&exp3, Aexps[Alen - 1], mask)) goto not_sqrt; /* exponent is not square */ exp3 += Qexps[0]; /* overflow not possible */ } while (heap_len > 1 || Ai < Alen) { _fmpz_mpoly_fit_length(&Qcoeffs, &Qexps, allocq, Qlen + 1, 1); if (heap_len > 1 && Ai < Alen && Aexps[Ai] == heap[1].exp) { /* take from both A and heap */ exp = Aexps[Ai]; acc_lg = _fmpz_mpoly_get_mpz_signed_uiuiui(acc_sm, Acoeffs[Ai], acc); Ai++; } else if (heap_len > 1 && (Ai >= Alen || mpoly_monomial_gt1(heap[1].exp, Aexps[Ai], maskhi))) { /* take only from heap */ exp = heap[1].exp; mpz_set_ui(acc, 0); acc_lg = acc; acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; if (mpoly_monomial_overflows1(exp, mask)) goto not_sqrt; } else { FLINT_ASSERT(Ai < Alen); /* take only from A */ exp = Aexps[Ai]; acc_lg = _fmpz_mpoly_get_mpz_signed_uiuiui(acc_sm, Acoeffs[Ai], acc); Ai++; if (!check && mpoly_monomial_gt1(exp3, exp, maskhi)) break; lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Qexps[0], mask); goto skip_heap; } lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Qexps[0], mask); /* take nodes from heap with exponent matching exp */ if (!lt_divides && !check) { do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); mpz_set_ui(acc, 0); acc_lg = acc; } else if (q_rest_small) { /* optimization: small coeff arithmetic */ acc_sm2[2] = acc_sm2[1] = acc_sm2[0] = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; smul_ppmm(pp[1], pp[0], Qcoeffs[x->i], Qcoeffs[x->j]); pp[2] = FLINT_SIGN_EXT(pp[1]); if (x->i != x->j) sub_dddmmmsss(acc_sm2[2], acc_sm2[1], acc_sm2[0], acc_sm2[2], acc_sm2[1], acc_sm2[0], pp[2], pp[1], pp[0]); else sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], pp[2], pp[1], pp[0]); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); if (mpz_sgn(acc_lg) != 0) { flint_mpz_add_signed_uiuiui(acc, acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); acc_lg = acc; acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; } } else { acc_sm2[2] = acc_sm2[1] = acc_sm2[0] = 0; /* total is always acc + acc_sm + 2*(acc2 + acc_sm2) */ mpz_tdiv_q_2exp(acc2, acc_lg, 1); mpz_tdiv_r_2exp(acc, acc_lg, 1); do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { fmpz Qi, Qj; *store++ = x->i; *store++ = x->j; Qi = Qcoeffs[x->i]; Qj = Qcoeffs[x->j]; t = (x->i != x->j) ? acc2 : acc; if (!COEFF_IS_MPZ(Qi) && !COEFF_IS_MPZ(Qj)) { smul_ppmm(pp[1], pp[0], Qi, Qj); pp[2] = FLINT_SIGN_EXT(pp[1]); if (x->i != x->j) sub_dddmmmsss(acc_sm2[2], acc_sm2[1], acc_sm2[0], acc_sm2[2], acc_sm2[1], acc_sm2[0], pp[2], pp[1], pp[0]); else sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], pp[2], pp[1], pp[0]); } else if (!COEFF_IS_MPZ(Qi) && COEFF_IS_MPZ(Qj)) { if (Qi < WORD(0)) flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qj), -Qi); else flint_mpz_submul_ui(t, COEFF_TO_PTR(Qj), Qi); } else if (COEFF_IS_MPZ(Qi) && !COEFF_IS_MPZ(Qj)) { if (Qj < WORD(0)) flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qi), -Qj); else flint_mpz_submul_ui(t, COEFF_TO_PTR(Qi), Qj); } else { mpz_submul(t, COEFF_TO_PTR(Qi), COEFF_TO_PTR(Qj)); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); flint_mpz_add_signed_uiuiui(acc, acc, acc_sm[2], acc_sm[1], acc_sm[0]); mpz_addmul_ui(acc, acc2, 2); acc_lg = acc; acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right */ if (j < i) { x = chain[i]; x->i = i; x->j = j + 1; x->next = NULL; if (check || !mpoly_monomial_gt1(exp3, Qexps[x->i] + Qexps[x->j], maskhi)) { _mpoly_heap_insert1(heap, Qexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } } } skip_heap: /* try to divide accumulated term by leading term */ if (!check && !lt_divides) continue; if (mpz_sgn(acc_lg) == 0) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) continue; if (!lt_divides) goto not_sqrt; if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; nhi = MPN_LEFT_SHIFT_HI(d1, d0, lc_norm); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr != 0) goto not_sqrt; if (qq == 0) continue; if (qq <= COEFF_MAX) { _fmpz_demote(Qcoeffs + Qlen); Qcoeffs[Qlen] = qq; if (ds != 0) Qcoeffs[Qlen] = -Qcoeffs[Qlen]; } else { q_rest_small = 0; if (ds == 0) fmpz_set_ui(Qcoeffs + Qlen, qq); else fmpz_neg_ui(Qcoeffs + Qlen, qq); } } else { flint_mpz_add_signed_uiuiui(acc, acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { flint_mpz_add_signed_uiuiui(acc, acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); if (mpz_sgn(acc) == 0) continue; if (!lt_divides) goto not_sqrt; large_lt_divides: t = _fmpz_promote(Qcoeffs + Qlen); if (lc_abs > 0) flint_mpz_fdiv_qr_ui(t, r, acc, lc_abs); else mpz_fdiv_qr(t, r, acc, lc_lg); _fmpz_demote_val(Qcoeffs + Qlen); q_rest_small = q_rest_small && !COEFF_IS_MPZ(Qcoeffs[Qlen]); if (mpz_sgn(r) != 0) { Qlen++; goto not_sqrt; } } if (Qlen >= heap_alloc) { /* run some tests if the square root is getting long */ if (Qlen > Alen && _is_proved_not_square( ++heuristic_count, &heuristic_p, heuristic_state, Acoeffs, Aexps, Alen, bits, mctx)) { Qlen++; /* for demotion */ goto not_sqrt; } heap_alloc *= 2; heap = (mpoly_heap1_s *) flint_realloc(heap, (heap_alloc + 1)*sizeof(mpoly_heap1_s)); chain_nodes[exp_alloc] = (mpoly_heap_t *) flint_malloc((heap_alloc/2)*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_realloc(chain, heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_realloc(store_base, 2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc/2; i++) chain[i + heap_alloc/2] = chain_nodes[exp_alloc] + i; exp_alloc++; } /* put (Qlen, 1) in heap */ i = Qlen; x = chain[i]; x->i = i; x->j = 1; x->next = NULL; if (check || !mpoly_monomial_gt1(exp3, Qexps[i] + Qexps[1], maskhi)) { _mpoly_heap_insert1(heap, Qexps[i] + Qexps[1], x, &next_loc, &heap_len, maskhi); } Qlen++; } /* divide extra factor of 2 back out of leading coefficient */ fmpz_fdiv_q_2exp(Qcoeffs + 0, Qcoeffs + 0, 1); cleanup: flint_randclear(heuristic_state); mpz_clear(r); mpz_clear(acc); mpz_clear(acc2); (*polyq) = Qcoeffs; (*expq) = Qexps; flint_free(heap); flint_free(chain); flint_free(store_base); for (i = 0; i < exp_alloc; i++) flint_free(chain_nodes[i]); /* return sqrt poly length, or zero if not a square root */ return Qlen; not_sqrt: for (i = 0; i < Qlen; i++) _fmpz_demote(Qcoeffs + i); Qlen = 0; goto cleanup; } slong _fmpz_mpoly_sqrt_heap( fmpz ** polyq, ulong ** expq, slong * allocq, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t bits, const mpoly_ctx_t mctx, int check) { slong N = mpoly_words_per_exp(bits, mctx); ulong * cmpmask; slong i, j, Qlen, Ai; slong next_loc; slong heap_len = 1, heap_alloc; int exp_alloc; mpoly_heap_s * heap; mpoly_heap_t * chain_nodes[64]; mpoly_heap_t ** chain; slong * store, * store_base; mpoly_heap_t * x; fmpz * Qcoeffs = *polyq; ulong * Qexps = *expq; ulong * exp, * exp3; ulong * exps[64]; ulong ** exp_list; slong exp_next; ulong mask; mpz_t r, acc, acc2; mpz_srcptr acc_lg; mpz_ptr t; ulong acc_sm[3], acc_sm2[3], pp[3]; int halves, use_heap, lt_divides, q_rest_small; flint_rand_t heuristic_state; mp_limb_t heuristic_p = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); int heuristic_count = 0; ulong lc_abs = 0; /* 2*sqrt(lc) if it fits in ulong, otherwise 0 */ ulong lc_norm = 0; ulong lc_n = 0; ulong lc_i = 0; mpz_ptr lc_lg = NULL; /* 2*sqrt(lc) if it is large */ TMP_INIT; if (N == 1) return _fmpz_mpoly_sqrt_heap1(polyq, expq, allocq, Acoeffs, Aexps, Alen, bits, mctx, check); TMP_START; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, mctx); flint_randinit(heuristic_state); mpz_init(r); mpz_init(acc); mpz_init(acc2); /* alloc array of heap nodes which can be chained together */ next_loc = 2*sqrt(Alen) + 4; /* something bigger than heap can ever be */ heap_alloc = next_loc - 3; heap = (mpoly_heap_s *) flint_malloc((heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[0] = (mpoly_heap_t *) flint_malloc(heap_alloc*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_malloc(heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_malloc(2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc; i++) chain[i] = chain_nodes[0] + i; /* array of exponent vectors, each of "N" words */ exps[0] = (ulong *) flint_malloc(heap_alloc*N*sizeof(ulong)); exp_alloc = 1; /* list of pointers to available exponent vectors */ exp_list = (ulong **) flint_malloc(heap_alloc*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* final exponent */ exp3 = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < heap_alloc; i++) exp_list[i] = exps[0] + i*N; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; Qlen = 0; /* "insert" (-1, 1, Aexps[0]) into "heap" */ Ai = 1; /* compute first term */ if (!fmpz_is_square(Acoeffs + 0)) goto not_sqrt; _fmpz_mpoly_fit_length(&Qcoeffs, &Qexps, allocq, Qlen + 1, 1); fmpz_sqrt(Qcoeffs + 0, Acoeffs + 0); Qlen++; /* multiply by 2, we revert this at the end */ fmpz_mul_2exp(Qcoeffs + 0, Qcoeffs + 0, 1); /* q_rest_small means Qcoeffs[1] ... Qcoeffs[Qlen-1] are small */ q_rest_small = 1; if (fmpz_abs_fits_ui(Qcoeffs + 0)) { lc_abs = fmpz_get_ui(Qcoeffs + 0); lc_norm = flint_clz(lc_abs); lc_n = lc_abs << lc_norm; lc_i = n_preinvert_limb_prenorm(lc_n); } else { lc_lg = COEFF_TO_PTR(Qcoeffs[0]); } if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(Qexps + 0, Aexps + 0, N, mask); else halves = mpoly_monomial_halves_mp(Qexps + 0, Aexps + 0, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ /* optimisation, compute final term */ { if (!fmpz_is_square(Acoeffs + Alen - 1)) goto not_sqrt; if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(exp3, Aexps + (Alen - 1)*N, N, mask); else halves = mpoly_monomial_halves_mp(exp3, Aexps + (Alen - 1)*N, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ if (bits <= FLINT_BITS) mpoly_monomial_add(exp3, exp3, Qexps + 0, N); else mpoly_monomial_add_mp(exp3, exp3, Qexps + 0, N); } while (heap_len > 1 || Ai < Alen) { _fmpz_mpoly_fit_length(&Qcoeffs, &Qexps, allocq, Qlen + 1, N); if (heap_len > 1 && Ai < Alen && mpoly_monomial_equal(Aexps + N*Ai, heap[1].exp, N)) { /* take from both A and heap */ mpoly_monomial_set(exp, Aexps + N*Ai, N); acc_lg = _fmpz_mpoly_get_mpz_signed_uiuiui(acc_sm, Acoeffs[Ai], acc); Ai++; use_heap = 1; } else if (heap_len > 1 && (Ai >= Alen || mpoly_monomial_lt(Aexps + N*Ai, heap[1].exp, N, cmpmask))) { /* take only from heap */ mpoly_monomial_set(exp, heap[1].exp, N); mpz_set_ui(acc, 0); acc_lg = acc; acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; if (bits <= FLINT_BITS ? mpoly_monomial_overflows(exp, N, mask) : mpoly_monomial_overflows_mp(exp, N, bits)) goto not_sqrt; use_heap = 1; } else { FLINT_ASSERT(Ai < Alen); /* take only from A */ mpoly_monomial_set(exp, Aexps + N*Ai, N); acc_lg = _fmpz_mpoly_get_mpz_signed_uiuiui(acc_sm, Acoeffs[Ai], acc); Ai++; if (!check && mpoly_monomial_gt(exp3, exp, N, cmpmask)) break; use_heap = 0; } if (bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(Qexps + N*Qlen, exp, Qexps + 0, N, mask); else lt_divides = mpoly_monomial_divides_mp(Qexps + N*Qlen, exp, Qexps + 0, N, bits); if (!use_heap) goto skip_heap; /* take nodes from heap with exponent matching exp */ if (!lt_divides && !check) { do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); mpz_set_ui(acc, 0); acc_lg = acc; } else if (q_rest_small) { /* optimization: small coeff arithmetic */ acc_sm2[2] = acc_sm2[1] = acc_sm2[0] = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; smul_ppmm(pp[1], pp[0], Qcoeffs[x->i], Qcoeffs[x->j]); pp[2] = FLINT_SIGN_EXT(pp[1]); if (x->i != x->j) sub_dddmmmsss(acc_sm2[2], acc_sm2[1], acc_sm2[0], acc_sm2[2], acc_sm2[1], acc_sm2[0], pp[2], pp[1], pp[0]); else sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], pp[2], pp[1], pp[0]); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); if (mpz_sgn(acc_lg) != 0) { flint_mpz_add_signed_uiuiui(acc, acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); acc_lg = acc; acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; } } else { acc_sm2[2] = acc_sm2[1] = acc_sm2[0] = 0; /* total is always acc + acc_sm + 2*(acc2 + acc_sm2) */ mpz_tdiv_q_2exp(acc2, acc_lg, 1); mpz_tdiv_r_2exp(acc, acc_lg, 1); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { fmpz Qi, Qj; *store++ = x->i; *store++ = x->j; Qi = Qcoeffs[x->i]; Qj = Qcoeffs[x->j]; t = (x->i != x->j) ? acc2 : acc; if (!COEFF_IS_MPZ(Qi) && !COEFF_IS_MPZ(Qj)) { smul_ppmm(pp[1], pp[0], Qi, Qj); pp[2] = FLINT_SIGN_EXT(pp[1]); if (x->i != x->j) sub_dddmmmsss(acc_sm2[2], acc_sm2[1], acc_sm2[0], acc_sm2[2], acc_sm2[1], acc_sm2[0], pp[2], pp[1], pp[0]); else sub_dddmmmsss(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], pp[2], pp[1], pp[0]); } else if (!COEFF_IS_MPZ(Qi) && COEFF_IS_MPZ(Qj)) { if (Qi < WORD(0)) flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qj), -Qi); else flint_mpz_submul_ui(t, COEFF_TO_PTR(Qj), Qi); } else if (COEFF_IS_MPZ(Qi) && !COEFF_IS_MPZ(Qj)) { if (Qj < WORD(0)) flint_mpz_addmul_ui(t, COEFF_TO_PTR(Qi), -Qj); else flint_mpz_submul_ui(t, COEFF_TO_PTR(Qi), Qj); } else { mpz_submul(t, COEFF_TO_PTR(Qi), COEFF_TO_PTR(Qj)); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); add_sssaaaaaa(acc_sm[2], acc_sm[1], acc_sm[0], acc_sm[2], acc_sm[1], acc_sm[0], acc_sm2[2], acc_sm2[1], acc_sm2[0]); flint_mpz_add_signed_uiuiui(acc, acc, acc_sm[2], acc_sm[1], acc_sm[0]); mpz_addmul_ui(acc, acc2, 2); acc_lg = acc; acc_sm[2] = acc_sm[1] = acc_sm[0] = 0; } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right */ if (j < i) { x = chain[i]; x->i = i; x->j = j + 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); if (check || !mpoly_monomial_gt(exp3 + 0, exp_list[exp_next], N, cmpmask)) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } skip_heap: /* try to divide accumulated term by leading term */ if (!check && !lt_divides) continue; if (mpz_sgn(acc_lg) == 0) { ulong d0, d1, ds = acc_sm[2]; /* d1:d0 = abs(acc_sm[1:0]) assuming ds is sign extension of acc_sm[1] */ sub_ddmmss(d1, d0, acc_sm[1]^ds, acc_sm[0]^ds, ds, ds); if ((acc_sm[0] | acc_sm[1] | acc_sm[2]) == 0) continue; if (!lt_divides) goto not_sqrt; if (ds == FLINT_SIGN_EXT(acc_sm[1]) && d1 < lc_abs) { ulong qq, rr, nhi, nlo; nhi = MPN_LEFT_SHIFT_HI(d1, d0, lc_norm); nlo = d0 << lc_norm; udiv_qrnnd_preinv(qq, rr, nhi, nlo, lc_n, lc_i); if (rr != 0) goto not_sqrt; if (qq == 0) continue; if (qq <= COEFF_MAX) { _fmpz_demote(Qcoeffs + Qlen); Qcoeffs[Qlen] = qq; if (ds != 0) Qcoeffs[Qlen] = -Qcoeffs[Qlen]; } else { q_rest_small = 0; if (ds == 0) fmpz_set_ui(Qcoeffs + Qlen, qq); else fmpz_neg_ui(Qcoeffs + Qlen, qq); } } else { flint_mpz_add_signed_uiuiui(acc, acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); goto large_lt_divides; } } else { flint_mpz_add_signed_uiuiui(acc, acc_lg, acc_sm[2], acc_sm[1], acc_sm[0]); if (mpz_sgn(acc) == 0) continue; if (!lt_divides) goto not_sqrt; large_lt_divides: t = _fmpz_promote(Qcoeffs + Qlen); if (lc_abs > 0) flint_mpz_fdiv_qr_ui(t, r, acc, lc_abs); else mpz_fdiv_qr(t, r, acc, lc_lg); _fmpz_demote_val(Qcoeffs + Qlen); q_rest_small = q_rest_small && !COEFF_IS_MPZ(Qcoeffs[Qlen]); if (mpz_sgn(r) != 0) { Qlen++; goto not_sqrt; } } if (Qlen >= heap_alloc) { /* run some tests if the square root is getting long */ if (Qlen > Alen && _is_proved_not_square( ++heuristic_count, &heuristic_p, heuristic_state, Acoeffs, Aexps, Alen, bits, mctx)) { Qlen++; /* for demotion */ goto not_sqrt; } heap_alloc *= 2; heap = (mpoly_heap_s *) flint_realloc(heap, (heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[exp_alloc] = (mpoly_heap_t *) flint_malloc((heap_alloc/2)*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_realloc(chain, heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_realloc(store_base, 2*heap_alloc*sizeof(mpoly_heap_t *)); exps[exp_alloc] = (ulong *) flint_malloc((heap_alloc/2)*N*sizeof(ulong)); exp_list = (ulong **) flint_realloc(exp_list, heap_alloc*sizeof(ulong *)); for (i = 0; i < heap_alloc/2; i++) { chain[i + heap_alloc/2] = chain_nodes[exp_alloc] + i; exp_list[i + heap_alloc/2] = exps[exp_alloc] + i*N; } exp_alloc++; } /* put (Qlen, 1) in heap */ i = Qlen; x = chain[i]; x->i = i; x->j = 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); if (check || !mpoly_monomial_gt(exp3 + 0, exp_list[exp_next], N, cmpmask)) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } Qlen++; } /* divide extra factor of 2 back out of leading coefficient */ fmpz_fdiv_q_2exp(Qcoeffs + 0, Qcoeffs + 0, 1); cleanup: flint_randclear(heuristic_state); mpz_clear(r); mpz_clear(acc); mpz_clear(acc2); (*polyq) = Qcoeffs; (*expq) = Qexps; flint_free(heap); flint_free(chain); flint_free(store_base); flint_free(exp_list); for (i = 0; i < exp_alloc; i++) { flint_free(exps[i]); flint_free(chain_nodes[i]); } TMP_END; /* return sqrt poly length, or zero if not a square root */ return Qlen; not_sqrt: for (i = 0; i < Qlen; i++) _fmpz_demote(Qcoeffs + i); Qlen = 0; goto cleanup; } int fmpz_mpoly_sqrt_heap(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, int check) { slong lenq, lenq_est; flint_bitcnt_t exp_bits; fmpz_mpoly_t T; fmpz_mpoly_struct * q; if (fmpz_mpoly_is_zero(A, ctx)) { fmpz_mpoly_zero(Q, ctx); return 1; } /* square root fits in A->bits if it exists */ exp_bits = A->bits; /* rought lower estimate on length of square root */ lenq_est = n_sqrt(A->length); if (Q == A) { fmpz_mpoly_init3(T, lenq_est, exp_bits, ctx); q = T; } else { fmpz_mpoly_fit_length_reset_bits(Q, lenq_est, exp_bits, ctx); q = Q; } lenq = _fmpz_mpoly_sqrt_heap(&q->coeffs, &q->exps, &q->alloc, A->coeffs, A->exps, A->length, exp_bits, ctx->minfo, check); if (Q == A) { fmpz_mpoly_swap(Q, T, ctx); fmpz_mpoly_clear(T, ctx); } _fmpz_mpoly_set_length(Q, lenq, ctx); return lenq != 0; } flint-3.1.3/src/fmpz_mpoly/sub.c000066400000000000000000000170101461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" slong _fmpz_mpoly_sub1( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, ulong maskhi) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { if ((Bexps[i]^maskhi) > (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if ((Bexps[i]^maskhi) == (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; fmpz_sub(Acoeffs + k, Bcoeffs + i, Ccoeffs + j); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { Aexps[k] = Cexps[j]; fmpz_neg(Acoeffs + k, Ccoeffs + j); j++; k++; } } while (i < Blen) { Aexps[k] = Bexps[i]; fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { Aexps[k] = Cexps[j]; fmpz_neg(Acoeffs + k, Ccoeffs + j); j++; k++; } return k; } slong _fmpz_mpoly_sub( fmpz * Acoeffs, ulong * Aexps, const fmpz * Bcoeffs, const ulong * Bexps, slong Blen, const fmpz * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask) { slong i = 0, j = 0, k = 0; if (N == 1) { return _fmpz_mpoly_sub1(Acoeffs, Aexps, Bcoeffs, Bexps, Blen, Ccoeffs, Cexps, Clen, cmpmask[0]); } while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_sub(Acoeffs + k, Bcoeffs + i, Ccoeffs + j); k += !fmpz_is_zero(Acoeffs + k); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_neg(Acoeffs + k, Ccoeffs + j); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fmpz_set(Acoeffs + k, Bcoeffs + i); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fmpz_neg(Acoeffs + k, Ccoeffs + j); j++; k++; } return k; } void fmpz_mpoly_sub_inplace(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { slong i, s, new_len, N; slong Alen = A->length; slong Blen = B->length; ulong * Bexps, * cmpmask; int cmp, freeBexps; flint_bitcnt_t Abits; fmpz_mpoly_t T; TMP_INIT; FLINT_ASSERT(A != B); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); TMP_START; if (A->bits <= B->bits) { Abits = B->bits; if (A->bits < B->bits) fmpz_mpoly_repack_bits_inplace(A, Abits, ctx); N = mpoly_words_per_exp(Abits, ctx->minfo); Bexps = B->exps; freeBexps = 0; } else { Abits = A->bits; N = mpoly_words_per_exp(Abits, ctx->minfo); Bexps = (ulong *) flint_malloc(N*Blen*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, Blen, ctx->minfo); freeBexps = 1; } cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); for (s = 0; s < Alen/4; s++) { cmp = mpoly_monomial_cmp(A->exps + N*(Alen - s - 1), Bexps + N*0, N, cmpmask); if (cmp >= 0) { s += (cmp == 0); goto doit; } } fmpz_mpoly_init3(T, Alen + Blen, Abits, ctx); T->length = _fmpz_mpoly_sub(T->coeffs, T->exps, A->coeffs, A->exps, Alen, B->coeffs, Bexps, Blen, N, cmpmask); fmpz_mpoly_swap(A, T, ctx); fmpz_mpoly_clear(T, ctx); goto cleanup; doit: FLINT_ASSERT(0 <= s && s <= Alen); FLINT_ASSERT(s == 0 || mpoly_monomial_cmp(A->exps + N*(Alen - s), Bexps + N*0, N, cmpmask) <= 0); FLINT_ASSERT(s == Alen || mpoly_monomial_cmp(A->exps + N*(Alen - s - 1), Bexps + N*0, N, cmpmask) > 0); fmpz_mpoly_fit_length(A, Alen + Blen + s, ctx); mpoly_copy_monomials(A->exps + N*(Alen + Blen), A->exps + N*(Alen - s), s, N); _fmpz_vec_swap(A->coeffs + Alen + Blen, A->coeffs + Alen - s, s); new_len = _fmpz_mpoly_sub(A->coeffs + Alen - s, A->exps + N*(Alen - s), A->coeffs + (Alen + Blen), A->exps + N*(Alen + Blen), s, B->coeffs, Bexps, Blen, N, cmpmask); for (i = 0; i < s; i++) _fmpz_demote(A->coeffs + Alen + Blen + i); _fmpz_mpoly_set_length(A, Alen - s + new_len, ctx); cleanup: if (freeBexps) flint_free(Bexps); TMP_END; return; } void fmpz_mpoly_sub(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx) { slong Alen, N; flint_bitcnt_t Abits; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_neg(A, C, ctx); return; } else if (fmpz_mpoly_is_zero(C, ctx)) { fmpz_mpoly_set(A, B, ctx); return; } else if (A == B) { if (A == C) fmpz_mpoly_zero(A, ctx); else fmpz_mpoly_sub_inplace(A, C, ctx); return; } else if (A == C) { fmpz_mpoly_sub_inplace(A, B, ctx); _fmpz_vec_neg(A->coeffs, A->coeffs, A->length); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits > C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } fmpz_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); Alen = _fmpz_mpoly_sub(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask); _fmpz_mpoly_set_length(A, Alen, ctx); if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fmpz_mpoly/sub_fmpz.c000066400000000000000000000053031461254215100176100ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_sub_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx) { slong i, N; slong Blen = B->length; if (Blen == 0) { fmpz_mpoly_set_fmpz(A, c, ctx); if (A->length != 0) fmpz_neg(A->coeffs, A->coeffs); return; } if (!fmpz_is_zero(c)) { N = mpoly_words_per_exp(B->bits, ctx->minfo); if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { fmpz_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); for (i = 0; i < Blen - 1; i++) fmpz_set(A->coeffs + i, B->coeffs + i); for (i = 0; i < Blen*N; i++) A->exps[i] = B->exps[i]; _fmpz_mpoly_set_length(A, B->length, ctx); } fmpz_sub(A->coeffs + Blen - 1, B->coeffs + Blen - 1, c); if (fmpz_is_zero(A->coeffs + Blen - 1)) _fmpz_mpoly_set_length(A, Blen - 1, ctx); } else { fmpz_mpoly_fit_length(A, Blen + 1, ctx); if (A != B) { fmpz_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; for (i = 0; i < Blen; i++) fmpz_set(A->coeffs + i, B->coeffs + i); for (i = 0; i < Blen*N; i++) A->exps[i] = B->exps[i]; } for (i = 0; i < N; i++) A->exps[Blen*N + i] = 0; fmpz_neg(A->coeffs + Blen, c); _fmpz_mpoly_set_length(A, B->length + 1, ctx); } } else if (A != B) { fmpz_mpoly_set(A, B, ctx); } } void fmpz_mpoly_sub_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_ui(t, c); fmpz_mpoly_sub_fmpz(A, B, t, ctx); fmpz_clear(t); } void fmpz_mpoly_sub_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_si(t, c); fmpz_mpoly_sub_fmpz(A, B, t, ctx); fmpz_clear(t); } flint-3.1.3/src/fmpz_mpoly/symmetric.c000066400000000000000000000036061461254215100200030ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_symmetric_gens(fmpz_mpoly_t res, ulong k, slong * vars, slong n, const fmpz_mpoly_ctx_t ctx) { ulong * exp; slong * c; slong nvars, i, j; if (k == 0) { fmpz_mpoly_one(res, ctx); return; } fmpz_mpoly_zero(res, ctx); if (k > n) return; nvars = ctx->minfo->nvars; /* Generate all combinations (Knuth algorithm L). Todo: Knuth algorithm T is faster. */ c = flint_malloc(sizeof(slong) * (k + 2)); exp = flint_calloc(nvars, sizeof(ulong)); for (j = 0; j < k; j++) c[j] = j; c[k] = n; c[k + 1] = 0; while (1) { /* Visit this combination */ for (i = 0; i < n; i++) exp[vars[i]] = 0; for (i = 0; i < k; i++) exp[vars[c[i]]] = 1; fmpz_mpoly_push_term_ui_ui(res, 1, exp, ctx); j = 1; while (c[j - 1] + 1 == c[j]) { c[j - 1] = j - 1; j++; if (c[j - 1] + 1 != c[j]) break; } if (j > k) break; c[j - 1]++; } fmpz_mpoly_sort_terms(res, ctx); flint_free(c); flint_free(exp); } void fmpz_mpoly_symmetric(fmpz_mpoly_t res, ulong k, const fmpz_mpoly_ctx_t ctx) { slong i, nvars; slong * vars; nvars = ctx->minfo->nvars; vars = flint_malloc(sizeof(slong) * nvars); for (i = 0; i < nvars; i++) vars[i] = i; fmpz_mpoly_symmetric_gens(res, k, vars, nvars, ctx); flint_free(vars); } flint-3.1.3/src/fmpz_mpoly/term_content.c000066400000000000000000000034731461254215100204720ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_term_content(fmpz_mpoly_t M, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t Abits; fmpz * minAfields, * min_degs; fmpz_t g; TMP_INIT; if (A->length == 0) { fmpz_mpoly_zero(M, ctx); return; } TMP_START; Abits = A->bits; /* get the field-wise minimum */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, Abits, ctx->minfo); /* unpack to get the min exponents of each variable */ min_degs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(min_degs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(min_degs, minAfields, ctx->minfo); fmpz_mpoly_fit_length_reset_bits(M, 1, Abits, ctx); mpoly_set_monomial_ffmpz(M->exps, min_degs, Abits, ctx->minfo); fmpz_init(g); _fmpz_vec_content(g, A->coeffs, A->length); fmpz_swap(M->coeffs + 0, g); fmpz_clear(g); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(minAfields + i); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(min_degs + i); _fmpz_mpoly_set_length(M, 1, ctx); TMP_END; } flint-3.1.3/src/fmpz_mpoly/term_exp_fits.c000066400000000000000000000015771461254215100206440ustar00rootroot00000000000000/* Copyright (C) 2016-2017 William Hart Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" int fmpz_mpoly_term_exp_fits_ui(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_ui(A->exps, A->bits, i, ctx->minfo); } int fmpz_mpoly_term_exp_fits_si(const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_si(A->exps, A->bits, i, ctx->minfo); } flint-3.1.3/src/fmpz_mpoly/test/000077500000000000000000000000001461254215100165755ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly/test/main.c000066400000000000000000000153511461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-add_sub_fmpz.c" #include "t-add_sub_si.c" #include "t-add_sub_ui.c" #include "t-buchberger_naive.c" #include "t-cmp.c" #include "t-compose_fmpz_mpoly.c" #include "t-compose_fmpz_poly.c" #include "t-content_vars.c" #include "t-degree.c" #include "t-degrees_term_exp_fits_ui_si.c" #include "t-derivative_integral.c" #include "t-divides_array.c" #include "t-divides.c" #include "t-divides_heap_threaded.c" #include "t-divides_monagan_pearce.c" #include "t-div_monagan_pearce.c" #include "t-divrem_array.c" #include "t-divrem_ideal_monagan_pearce.c" #include "t-divrem_monagan_pearce.c" #include "t-evaluate.c" #include "t-gcd_brown.c" #include "t-gcd.c" #include "t-gcd_cofactors.c" #include "t-gcd_hensel.c" #include "t-gcd_subresultant.c" #include "t-gcd_zippel2.c" #include "t-gcd_zippel.c" #include "t-gen.c" #include "t-get_coeff_vars_ui.c" #include "t-get_set_coeff.c" #include "t-get_set_coeff_fmpz_monomial.c" #include "t-get_set_is_fmpz.c" #include "t-get_set_str_pretty.c" #include "t-get_set_term_coeff_fmpz.c" #include "t-get_set_term_exp_fmpz.c" #include "t-get_set_term_exp_si.c" #include "t-get_set_term_exp_ui.c" #include "t-get_term.c" #include "t-get_term_monomial.c" #include "t-inflate_deflate.c" #include "t-init.c" #include "t-mul_array.c" #include "t-mul_array_threaded.c" #include "t-mul.c" #include "t-mul_dense.c" #include "t-mul_heap_threaded.c" #include "t-mul_johnson.c" #include "t-mul_monomial.c" #include "t-neg.c" #include "t-pow_fps.c" #include "t-pow_ui.c" #include "t-push_term_fmpz_fmpz.c" #include "t-push_term_fmpz_ui.c" #include "t-quasidiv_heap.c" #include "t-quasidivrem_heap.c" #include "t-quasidivrem_ideal_heap.c" #include "t-repack_bits.c" #include "t-resize.c" #include "t-resultant_discriminant.c" #include "t-reverse.c" #include "t-scalar_divexact_fmpz.c" #include "t-scalar_divexact_si.c" #include "t-scalar_divexact_ui.c" #include "t-scalar_divides_fmpz.c" #include "t-scalar_fmma.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_si.c" #include "t-scalar_mul_ui.c" #include "t-set_equal.c" #include "t-set_fmpz.c" #include "t-set_gen_fmpz_poly.c" #include "t-set_si.c" #include "t-set_ui.c" #include "t-sort_terms.c" #include "t-sqrt_heap.c" #include "t-symmetric.c" #include "t-term_content.c" #include "t-total_degree.c" #include "t-univar.c" #include "t-univar_resultant.c" #include "t-used_vars.c" #include "t-vec_autoreduction.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mpoly_add_sub), TEST_FUNCTION(fmpz_mpoly_add_sub_fmpz), TEST_FUNCTION(fmpz_mpoly_add_sub_si), TEST_FUNCTION(fmpz_mpoly_add_sub_ui), TEST_FUNCTION(fmpz_mpoly_buchberger_naive), TEST_FUNCTION(fmpz_mpoly_cmp), TEST_FUNCTION(fmpz_mpoly_compose_fmpz_mpoly), TEST_FUNCTION(fmpz_mpoly_compose_fmpz_poly), TEST_FUNCTION(fmpz_mpoly_content_vars), TEST_FUNCTION(fmpz_mpoly_degree), TEST_FUNCTION(fmpz_mpoly_degrees_term_exp_fits_ui_si), TEST_FUNCTION(fmpz_mpoly_derivative_integral), TEST_FUNCTION(fmpz_mpoly_divides_array), TEST_FUNCTION(fmpz_mpoly_divides), TEST_FUNCTION(fmpz_mpoly_divides_heap_threaded), TEST_FUNCTION(fmpz_mpoly_divides_monagan_pearce), TEST_FUNCTION(fmpz_mpoly_div_monagan_pearce), TEST_FUNCTION(fmpz_mpoly_divrem_array), TEST_FUNCTION(fmpz_mpoly_divrem_ideal_monagan_pearce), TEST_FUNCTION(fmpz_mpoly_divrem_monagan_pearce), TEST_FUNCTION(fmpz_mpoly_evaluate), TEST_FUNCTION(fmpz_mpoly_gcd_brown), TEST_FUNCTION(fmpz_mpoly_gcd), TEST_FUNCTION(fmpz_mpoly_gcd_cofactors), TEST_FUNCTION(fmpz_mpoly_gcd_hensel), TEST_FUNCTION(fmpz_mpoly_gcd_subresultant), TEST_FUNCTION(fmpz_mpoly_gcd_zippel2), TEST_FUNCTION(fmpz_mpoly_gcd_zippel), TEST_FUNCTION(fmpz_mpoly_gen), TEST_FUNCTION(fmpz_mpoly_get_coeff_vars_ui), TEST_FUNCTION(fmpz_mpoly_get_set_coeff), TEST_FUNCTION(fmpz_mpoly_get_set_coeff_fmpz_monomial), TEST_FUNCTION(fmpz_mpoly_get_set_is_fmpz), TEST_FUNCTION(fmpz_mpoly_get_set_str_pretty), TEST_FUNCTION(fmpz_mpoly_get_set_term_coeff_fmpz), TEST_FUNCTION(fmpz_mpoly_get_set_term_exp_fmpz), TEST_FUNCTION(fmpz_mpoly_get_set_term_exp_si), TEST_FUNCTION(fmpz_mpoly_get_set_term_exp_ui), TEST_FUNCTION(fmpz_mpoly_get_term), TEST_FUNCTION(fmpz_mpoly_get_term_monomial), TEST_FUNCTION(fmpz_mpoly_inflate_deflate), TEST_FUNCTION(fmpz_mpoly_init), TEST_FUNCTION(fmpz_mpoly_mul_array), TEST_FUNCTION(fmpz_mpoly_mul_array_threaded), TEST_FUNCTION(fmpz_mpoly_mul), TEST_FUNCTION(fmpz_mpoly_mul_dense), TEST_FUNCTION(fmpz_mpoly_mul_heap_threaded), TEST_FUNCTION(fmpz_mpoly_mul_johnson), TEST_FUNCTION(fmpz_mpoly_mul_monomial), TEST_FUNCTION(fmpz_mpoly_neg), TEST_FUNCTION(fmpz_mpoly_pow_fps), TEST_FUNCTION(fmpz_mpoly_pow_ui), TEST_FUNCTION(fmpz_mpoly_push_term_fmpz_fmpz), TEST_FUNCTION(fmpz_mpoly_push_term_fmpz_ui), TEST_FUNCTION(fmpz_mpoly_quasidiv_heap), TEST_FUNCTION(fmpz_mpoly_quasidivrem_heap), TEST_FUNCTION(fmpz_mpoly_quasidivrem_ideal_heap), TEST_FUNCTION(fmpz_mpoly_repack_bits), TEST_FUNCTION(fmpz_mpoly_resize), TEST_FUNCTION(fmpz_mpoly_resultant_discriminant), TEST_FUNCTION(fmpz_mpoly_reverse), TEST_FUNCTION(fmpz_mpoly_scalar_divexact_fmpz), TEST_FUNCTION(fmpz_mpoly_scalar_divexact_si), TEST_FUNCTION(fmpz_mpoly_scalar_divexact_ui), TEST_FUNCTION(fmpz_mpoly_scalar_divides_fmpz), TEST_FUNCTION(fmpz_mpoly_scalar_fmma), TEST_FUNCTION(fmpz_mpoly_scalar_mul_fmpz), TEST_FUNCTION(fmpz_mpoly_scalar_mul_si), TEST_FUNCTION(fmpz_mpoly_scalar_mul_ui), TEST_FUNCTION(fmpz_mpoly_set_equal), TEST_FUNCTION(fmpz_mpoly_set_fmpz), TEST_FUNCTION(fmpz_mpoly_set_gen_fmpz_poly), TEST_FUNCTION(fmpz_mpoly_set_si), TEST_FUNCTION(fmpz_mpoly_set_ui), TEST_FUNCTION(fmpz_mpoly_sort_terms), TEST_FUNCTION(fmpz_mpoly_sqrt_heap), TEST_FUNCTION(fmpz_mpoly_symmetric), TEST_FUNCTION(fmpz_mpoly_term_content), TEST_FUNCTION(fmpz_mpoly_total_degree), TEST_FUNCTION(fmpz_mpoly_univar), TEST_FUNCTION(fmpz_mpoly_univar_resultant), TEST_FUNCTION(fmpz_mpoly_used_vars), TEST_FUNCTION(fmpz_mpoly_vec_autoreduction) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mpoly/test/t-add_sub.c000066400000000000000000000321231461254215100206040ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_add_sub, state) { int i, j, result; /* Check (f + g) - g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 1; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_add(h, g, f, ctx); fmpz_mpoly_sub(k, h, g, ctx); result = fmpz_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + g) - g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f + g = g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_add(h, f, g, ctx); fmpz_mpoly_add(k, g, f, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + g = g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f - g = -g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_sub(h, f, g, ctx); fmpz_mpoly_neg(k, g, ctx); fmpz_mpoly_add(k, k, f, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f - g = -g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f + (g + h) = (f + g) + h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k1, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k2, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_add(k1, f, g, ctx); fmpz_mpoly_add(k1, k1, h, ctx); fmpz_mpoly_add(k2, g, h, ctx); fmpz_mpoly_add(k2, k2, f, ctx); result = fmpz_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + (g + h) = (f + g) + h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f - (g + h) = (f - g) - h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k1, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k2, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_add(k1, g, h, ctx); fmpz_mpoly_sub(k1, f, k1, ctx); fmpz_mpoly_sub(k2, f, g, ctx); fmpz_mpoly_sub(k2, k2, h, ctx); result = fmpz_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f - (g + h) = (f - g) - h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); if ((j % 2) == 0) { fmpz_mpoly_add(h, g, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_add(f, g, f, ctx); fmpz_mpoly_assert_canonical(f, ctx); } else { fmpz_mpoly_sub(h, g, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_sub(f, g, f, ctx); fmpz_mpoly_assert_canonical(f, ctx); } result = fmpz_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); if ((j % 2) == 0) { fmpz_mpoly_add(h, g, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_add(g, g, f, ctx); fmpz_mpoly_assert_canonical(f, ctx); } else { fmpz_mpoly_sub(h, g, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_sub(g, g, f, ctx); fmpz_mpoly_assert_canonical(f, ctx); } result = fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); if ((j % 2) == 0) { fmpz_mpoly_add(h, f, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_add(f, f, f, ctx); fmpz_mpoly_assert_canonical(f, ctx); } else { fmpz_mpoly_sub(h, f, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_sub(f, f, f, ctx); fmpz_mpoly_assert_canonical(f, ctx); } result = fmpz_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing both args\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-add_sub_fmpz.c000066400000000000000000000062051461254215100216420ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_add_sub_fmpz, state) { int i, j, result; /* Check (f + a) - a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mpoly_add_fmpz(g, f, c, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_sub_fmpz(h, g, c, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + a) - a = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_set(g, f, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mpoly_add_fmpz(f, f, c, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_sub_fmpz(f, f, c, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-add_sub_si.c000066400000000000000000000061701461254215100213020ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "mpoly.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_add_sub_si, state) { int i, j, result; /* Check (f + a) - a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; ordering_t ord; slong c; slong nvars, len, coeff_bits, exp_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = z_randtest(state); fmpz_mpoly_add_si(g, f, c, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_sub_si(h, g, c, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + a) - a = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_set(g, f, ctx); c = z_randtest(state); fmpz_mpoly_add_si(f, f, c, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_sub_si(f, f, c, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-add_sub_ui.c000066400000000000000000000057331461254215100213100ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_add_sub_ui, state) { int i, j, result; /* Check (f + a) - a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; ulong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = n_randtest(state); fmpz_mpoly_add_ui(g, f, c, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_sub_ui(h, g, c, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + a) - a = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; ulong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_set(g, f, ctx); c = n_randtest(state); fmpz_mpoly_add_ui(f, f, c, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_sub_ui(f, f, c, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-buchberger_naive.c000066400000000000000000000056621461254215100225050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "calcium.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_buchberger_naive, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_vec_t F, G, H; slong nvars; fmpz_mpoly_ctx_init_rand(ctx, state, 4); nvars = ctx->minfo->nvars; fmpz_mpoly_vec_init(F, 0, ctx); fmpz_mpoly_vec_init(G, 0, ctx); fmpz_mpoly_vec_init(H, 0, ctx); /* flint_printf("iter %ld %ld %d\n\n", iter, nvars, ctx->minfo->ord); printf("--------------------------------------------------------------------\n"); */ if (nvars == 4) fmpz_mpoly_vec_randtest_not_zero(F, state, 1 + n_randint(state, 3), 1 + n_randint(state, 3), 1 + n_randint(state, 3), 1 + n_randint(state, 2), ctx); else if (nvars == 3) fmpz_mpoly_vec_randtest_not_zero(F, state, 1 + n_randint(state, 4), 1 + n_randint(state, 4), 1 + n_randint(state, 4), 1 + n_randint(state, 2), ctx); else fmpz_mpoly_vec_randtest_not_zero(F, state, 1 + n_randint(state, 5), 1 + n_randint(state, 5), 1 + n_randint(state, 5), 1 + n_randint(state, 3), ctx); /* flint_printf("F = "); fmpz_mpoly_vec_print(F, ctx); flint_printf("\n"); */ fmpz_mpoly_buchberger_naive(G, F, ctx); /* flint_printf("G = "); fmpz_mpoly_vec_print(G, ctx); flint_printf("\n"); */ if (!fmpz_mpoly_vec_is_groebner(G, F, ctx)) { flint_printf("FAIL\n\n"); mpoly_ordering_print(ctx->minfo->ord); printf("\n"); flint_printf("F = "); fmpz_mpoly_vec_print(F, ctx); flint_printf("\n"); flint_printf("G = "); fmpz_mpoly_vec_print(G, ctx); flint_printf("\n"); flint_abort(); } fmpz_mpoly_vec_autoreduction_groebner(H, G, ctx); if (!fmpz_mpoly_vec_is_groebner(H, F, ctx) || !fmpz_mpoly_vec_is_autoreduced(H, ctx)) { flint_printf("FAIL (reduced GB)\n\n"); mpoly_ordering_print(ctx->minfo->ord); printf("\n"); flint_printf("F = "); fmpz_mpoly_vec_print(F, ctx); flint_printf("\n"); flint_printf("G = "); fmpz_mpoly_vec_print(G, ctx); flint_printf("\n"); flint_printf("H = "); fmpz_mpoly_vec_print(H, ctx); flint_printf("\n"); flint_abort(); } fmpz_mpoly_vec_clear(F, ctx); fmpz_mpoly_vec_clear(G, ctx); fmpz_mpoly_vec_clear(H, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-cmp.c000066400000000000000000000135461461254215100177720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_cmp, state) { int result; slong i, j1, j2; /* check polynomial terms are in order */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, mf, mg; slong len; flint_bitcnt_t coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(mf, ctx); fmpz_mpoly_init(mg, ctx); len = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits = n_randint(state, exp_bits) + 2; coeff_bits = n_randint(state, 100) + 1; fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_repack_bits(g, f, f->bits + n_randint(state, FLINT_BITS), ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_assert_canonical(g, ctx); for (j1 = 0; j1 < f->length; j1++) for (j2 = 0; j2 < g->length; j2++) { fmpz_mpoly_get_term_monomial(mf, f, j1, ctx); fmpz_mpoly_get_term_monomial(mg, g, j2, ctx); result = fmpz_mpoly_cmp(mf, mg, ctx); result = (result == 0 && j1 == j2) || (result == +1 && j1 < j2) || (result == -1 && j1 > j2); if (!result) { flint_printf("FAIL\n" "check polynomial terms are in order\n" "i = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(mf, ctx); fmpz_mpoly_clear(mg, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, c, aa, bb, cc; int a_a, a_b, a_c, a_aa, a_bb, a_cc; int b_a, b_b, b_c, b_aa, b_bb, b_cc; int c_a, c_b, c_c, c_aa, c_bb, c_cc; flint_bitcnt_t newbits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(c, ctx); fmpz_mpoly_init(aa, ctx); fmpz_mpoly_init(bb, ctx); fmpz_mpoly_init(cc, ctx); fmpz_mpoly_randtest_bits(a, state, n_randint(state, 100) + 1, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fmpz_mpoly_randtest_bits(b, state, n_randint(state, 100) + 1, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fmpz_mpoly_randtest_bits(c, state, n_randint(state, 100) + 1, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(aa, a, newbits, ctx); newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(bb, b, newbits, ctx); newbits = c->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(cc, c, newbits, ctx); a_a = fmpz_mpoly_cmp(a, a, ctx); a_b = fmpz_mpoly_cmp(a, b, ctx); a_c = fmpz_mpoly_cmp(a, c, ctx); a_aa = fmpz_mpoly_cmp(a, aa, ctx); a_bb = fmpz_mpoly_cmp(a, bb, ctx); a_cc = fmpz_mpoly_cmp(a, cc, ctx); b_a = fmpz_mpoly_cmp(b, a, ctx); b_b = fmpz_mpoly_cmp(b, b, ctx); b_c = fmpz_mpoly_cmp(b, c, ctx); b_aa = fmpz_mpoly_cmp(b, aa, ctx); b_bb = fmpz_mpoly_cmp(b, bb, ctx); b_cc = fmpz_mpoly_cmp(b, cc, ctx); c_a = fmpz_mpoly_cmp(c, a, ctx); c_b = fmpz_mpoly_cmp(c, b, ctx); c_c = fmpz_mpoly_cmp(c, c, ctx); c_aa = fmpz_mpoly_cmp(c, aa, ctx); c_bb = fmpz_mpoly_cmp(c, bb, ctx); c_cc = fmpz_mpoly_cmp(c, cc, ctx); if (a_a != 0 || a_aa != 0 || b_b != 0 || b_bb != 0 || c_c != 0 || c_cc != 0) { flint_printf("FAIL\n" "check polynomial compares equal to itself\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if (a_b != a_bb || a_c != a_cc || b_a != b_aa || b_c != b_cc || c_a != c_aa || c_b != c_bb) { flint_printf("FAIL\n" "check polynomial comparison with differing bits\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if ((a_b*b_c == 0 && a_c != a_b + b_c) || (a_b*b_c > 0 && a_c != a_b)) { flint_printf("FAIL\n" "check transitivity\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(c, ctx); fmpz_mpoly_clear(aa, ctx); fmpz_mpoly_clear(bb, ctx); fmpz_mpoly_clear(cc, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-compose_fmpz_mpoly.c000066400000000000000000000314301461254215100231240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_compose_fmpz_mpoly, state) { slong i, j, v; { fmpz_mpoly_t A, A1, A2, B; fmpz_mpoly_struct * Cp[3]; fmpz_mpoly_struct C[3]; fmpz_mpoly_ctx_t ctxAC, ctxB; fmpz_mpoly_ctx_init(ctxB, 3, ORD_LEX); fmpz_mpoly_ctx_init(ctxAC, 2, ORD_LEX); fmpz_mpoly_init(B, ctxB); fmpz_mpoly_init(A, ctxAC); fmpz_mpoly_init(A1, ctxAC); fmpz_mpoly_init(A2, ctxAC); for (i = 0; i < 3; i++) { Cp[i] = C + i; fmpz_mpoly_init(C + i, ctxAC); } fmpz_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB); fmpz_mpoly_set_str_pretty(C + 0, "x1 + x2", NULL, ctxAC); fmpz_mpoly_set_str_pretty(C + 1, "x1 - x2", NULL, ctxAC); fmpz_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (fmpz_mpoly_compose_fmpz_mpoly(A, B, Cp, ctxB, ctxAC) || fmpz_mpoly_compose_fmpz_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || fmpz_mpoly_compose_fmpz_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(C + 0, "x1", NULL, ctxAC); fmpz_mpoly_set_str_pretty(C + 1, "2*x2", NULL, ctxAC); fmpz_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (fmpz_mpoly_compose_fmpz_mpoly(A, B, Cp, ctxB, ctxAC) || fmpz_mpoly_compose_fmpz_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || fmpz_mpoly_compose_fmpz_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 2\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(C + 0, "2*x1", NULL, ctxAC); fmpz_mpoly_set_str_pretty(C + 1, "x2", NULL, ctxAC); fmpz_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (!fmpz_mpoly_compose_fmpz_mpoly(A, B, Cp, ctxB, ctxAC) || !fmpz_mpoly_compose_fmpz_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || !fmpz_mpoly_compose_fmpz_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check example 3\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(B, ctxB); fmpz_mpoly_clear(A, ctxAC); fmpz_mpoly_clear(A1, ctxAC); fmpz_mpoly_clear(A2, ctxAC); for (i = 0; i < 3; i++) fmpz_mpoly_clear(C + i, ctxAC); fmpz_mpoly_ctx_clear(ctxB); fmpz_mpoly_ctx_clear(ctxAC); } /* check composition with generators */ for (i = 0; i < 20*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctxB, ctxAC; fmpz_mpoly_t B, A, A1, A2, A3; fmpz_mpoly_struct ** C; slong * c; slong nvarsB, nvarsAC; slong len; flint_bitcnt_t exp_bits, coeff_bits; fmpz_mpoly_ctx_init_rand(ctxB, state, 20); fmpz_mpoly_ctx_init_rand(ctxAC, state, 20); nvarsB = ctxB->minfo->nvars; nvarsAC = ctxAC->minfo->nvars; fmpz_mpoly_init(B, ctxB); fmpz_mpoly_init(A, ctxAC); fmpz_mpoly_init(A1, ctxAC); fmpz_mpoly_init(A2, ctxAC); fmpz_mpoly_init(A3, ctxAC); c = (slong *) flint_malloc(nvarsB*sizeof(slong)); C = (fmpz_mpoly_struct **) flint_malloc(nvarsB * sizeof(fmpz_mpoly_struct *)); for (v = 0; v < nvarsB; v++) { C[v] = (fmpz_mpoly_struct *) flint_malloc(sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(C[v], ctxAC); } for (j = 0; j < 4; j++) { len = n_randint(state, 200); exp_bits = n_randint(state, 100) + 1; coeff_bits = n_randint(state, 100) + 1; for (v = 0; v < nvarsB; v++) { c[v] = n_randint(state, nvarsAC + 2) - 2; if (c[v] >= 0) fmpz_mpoly_gen(C[v], c[v], ctxAC); else fmpz_mpoly_zero(C[v], ctxAC); } fmpz_mpoly_randtest_bits(B, state, len, coeff_bits, exp_bits, ctxB); fmpz_mpoly_compose_fmpz_mpoly_gen(A, B, c, ctxB, ctxAC); if (!fmpz_mpoly_compose_fmpz_mpoly(A1, B, C, ctxB, ctxAC) || !fmpz_mpoly_compose_fmpz_mpoly_horner(A2, B, C, ctxB, ctxAC) || !fmpz_mpoly_compose_fmpz_mpoly_geobucket(A3, B, C, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition success with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(A, A1, ctxAC) || !fmpz_mpoly_equal(A, A2, ctxAC) || !fmpz_mpoly_equal(A, A3, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(A, ctxAC); fmpz_mpoly_assert_canonical(A1, ctxAC); fmpz_mpoly_assert_canonical(A2, ctxAC); fmpz_mpoly_assert_canonical(A3, ctxAC); } for (v = 0; v < nvarsB; v++) { fmpz_mpoly_clear(C[v], ctxAC); flint_free(C[v]); } flint_free(C); flint_free(c); fmpz_mpoly_clear(B, ctxB); fmpz_mpoly_clear(A, ctxAC); fmpz_mpoly_clear(A1, ctxAC); fmpz_mpoly_clear(A2, ctxAC); fmpz_mpoly_clear(A3, ctxAC); fmpz_mpoly_ctx_clear(ctxB); fmpz_mpoly_ctx_clear(ctxAC); } /* Check composition with identity */ for (i = 0; i < 20*flint_test_multiplier(); i++) { slong len1; flint_bitcnt_t exp_bits, coeff_bits; fmpz_mpoly_struct ** vals1; fmpz_mpoly_t f, g, g1, g2; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_ctx_init_rand(ctx, state, 10); vals1 = (fmpz_mpoly_struct **) flint_malloc(ctx->minfo->nvars* sizeof(fmpz_mpoly_struct *)); for (v = 0; v < ctx->minfo->nvars; v++) { vals1[v] = (fmpz_mpoly_struct *) flint_malloc(sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(vals1[v], ctx); fmpz_mpoly_gen(vals1[v], v, ctx); } fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(g1, ctx); fmpz_mpoly_init(g2, ctx); len1 = n_randint(state, 200); exp_bits = n_randint(state, 100) + 1; coeff_bits = n_randint(state, 100) + 1; fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx); if (!fmpz_mpoly_compose_fmpz_mpoly(g, f, vals1, ctx, ctx) || !fmpz_mpoly_compose_fmpz_mpoly_horner(g1, f, vals1, ctx, ctx) || !fmpz_mpoly_compose_fmpz_mpoly_geobucket(g2, f, vals1, ctx, ctx) || !fmpz_mpoly_equal(g, g1, ctx) || !fmpz_mpoly_equal(g, g2, ctx)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_assert_canonical(g1, ctx); fmpz_mpoly_assert_canonical(g2, ctx); if (!fmpz_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check composition with identity\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(g1, ctx); fmpz_mpoly_clear(g2, ctx); for (v = 0; v < ctx->minfo->nvars; v++) { fmpz_mpoly_clear(vals1[v], ctx); flint_free(vals1[v]); } flint_free(vals1); fmpz_mpoly_ctx_clear(ctx); } /* Check composition and evalall commute */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx1, ctx2; fmpz_mpoly_t f, g, g1, g2; fmpz_mpoly_struct ** vals1; fmpz_t fe, ge; fmpz ** vals2, ** vals3; slong nvars1, nvars2; slong len1, len2; slong exp_bound1, exp_bound2; slong coeff_bits1, coeff_bits2; fmpz_mpoly_ctx_init_rand(ctx1, state, 6); fmpz_mpoly_ctx_init_rand(ctx2, state, 6); nvars1 = ctx1->minfo->nvars; nvars2 = ctx2->minfo->nvars; fmpz_mpoly_init(f, ctx1); fmpz_mpoly_init(g, ctx2); fmpz_mpoly_init(g1, ctx2); fmpz_mpoly_init(g2, ctx2); fmpz_init(fe); fmpz_init(ge); len1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars1) + 1) + 1; len2 = n_randint(state, 10/FLINT_MAX(WORD(1), nvars2) + 1) + 1; exp_bound1 = n_randint(state, 15/FLINT_MAX(WORD(1), nvars1) + 2) + 2; exp_bound2 = n_randint(state, 15/FLINT_MAX(WORD(1), nvars2) + 2) + 3; coeff_bits1 = n_randint(state, 200); coeff_bits2 = n_randint(state, 8); vals1 = (fmpz_mpoly_struct **) flint_malloc(nvars1 * sizeof(fmpz_mpoly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpz_mpoly_struct *) flint_malloc( sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(vals1[v], ctx2); fmpz_mpoly_randtest_bound(vals1[v], state, len2, coeff_bits2, exp_bound2, ctx2); } vals2 = (fmpz **) flint_malloc(nvars2*sizeof(fmpz*)); for (v = 0; v < nvars2; v++) { vals2[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals2[v]); fmpz_randbits(vals2[v], state, 4); } vals3 = (fmpz **) flint_malloc(nvars1*sizeof(fmpz*)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals3[v]); if (!fmpz_mpoly_evaluate_all_fmpz(vals3[v], vals1[v], vals2, ctx2)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } } fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits1, exp_bound1, ctx1); if (!fmpz_mpoly_compose_fmpz_mpoly(g, f, vals1, ctx1, ctx2) || !fmpz_mpoly_compose_fmpz_mpoly_horner(g1, f, vals1, ctx1, ctx2) || !fmpz_mpoly_compose_fmpz_mpoly_geobucket(g2, f, vals1, ctx1, ctx2) || !fmpz_mpoly_equal(g, g1, ctx2) || !fmpz_mpoly_equal(g, g2, ctx2)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(g, ctx2); fmpz_mpoly_assert_canonical(g1, ctx2); fmpz_mpoly_assert_canonical(g2, ctx2); if (!fmpz_mpoly_evaluate_all_fmpz(fe, f, vals3, ctx1) || !fmpz_mpoly_evaluate_all_fmpz(ge, g, vals2, ctx2)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } if (!fmpz_equal(fe, ge)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } for (v = 0; v < nvars1; v++) { fmpz_mpoly_clear(vals1[v], ctx2); flint_free(vals1[v]); } flint_free(vals1); for (v = 0; v < nvars2; v++) { fmpz_clear(vals2[v]); flint_free(vals2[v]); } flint_free(vals2); for (v = 0; v < nvars1; v++) { fmpz_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); fmpz_mpoly_clear(f, ctx1); fmpz_mpoly_clear(g, ctx2); fmpz_mpoly_clear(g1, ctx2); fmpz_mpoly_clear(g2, ctx2); fmpz_clear(fe); fmpz_clear(ge); fmpz_mpoly_ctx_clear(ctx1); fmpz_mpoly_ctx_clear(ctx2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-compose_fmpz_poly.c000066400000000000000000000250251461254215100227520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_compose_fmpz_poly, state) { slong i, v; { fmpz_poly_t A; fmpz_mpoly_t B; fmpz_poly_struct * Cp[3]; fmpz_poly_struct C[3]; fmpz_mpoly_ctx_t ctxB; fmpz_mpoly_ctx_init(ctxB, 3, ORD_LEX); fmpz_mpoly_init(B, ctxB); fmpz_poly_init(A); for (i = 0; i < 3; i++) { Cp[i] = C + i; fmpz_poly_init(C + i); } fmpz_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB); fmpz_poly_zero(C + 0); fmpz_poly_zero(C + 1); fmpz_poly_zero(C + 2); fmpz_poly_set_coeff_si(C + 0, 1, 1); fmpz_poly_set_coeff_si(C + 1, 2, 2); fmpz_poly_set_coeff_si(C + 2, 3, 3); if (fmpz_mpoly_compose_fmpz_poly(A, B, Cp, ctxB)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } fmpz_poly_zero(C + 0); fmpz_poly_zero(C + 1); fmpz_poly_zero(C + 2); fmpz_poly_set_coeff_si(C + 0, 0, 1); fmpz_poly_set_coeff_si(C + 1, 0, 1); fmpz_poly_set_coeff_si(C + 2, 0, 1); if (!fmpz_mpoly_compose_fmpz_poly(A, B, Cp, ctxB)) { printf("FAIL\n"); flint_printf("Check example 2\n", i); fflush(stdout); flint_abort(); } fmpz_poly_zero(C + 0); fmpz_poly_set_coeff_si(C + 0, 0, 3); if (!fmpz_poly_equal(A, C + 0)) { printf("FAIL\n"); flint_printf("Check example 2 equality\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(B, ctxB); fmpz_poly_clear(A); for (i = 0; i < 3; i++) fmpz_poly_clear(C + i); fmpz_mpoly_ctx_clear(ctxB); } /* Check composition and evalall commute */ for (i = 0; i < 50*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx1; fmpz_mpoly_t f; fmpz_poly_t g; fmpz_poly_struct ** vals1; fmpz_t fe, ge; fmpz_t vals2; fmpz ** vals3; slong nvars1; slong len1, len2; slong exp_bound1; flint_bitcnt_t coeff_bits, coeff_bits2; fmpz_mpoly_ctx_init_rand(ctx1, state, 10); nvars1 = ctx1->minfo->nvars; fmpz_mpoly_init(f, ctx1); fmpz_poly_init(g); fmpz_init(fe); fmpz_init(ge); len1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars1) + 1); len2 = n_randint(state, 40); exp_bound1 = n_randint(state, 200/FLINT_MAX(WORD(1), nvars1) + 2) + 1; coeff_bits = n_randint(state, 100) + 1; coeff_bits2 = n_randint(state, 10) + 1; fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx1); vals1 = (fmpz_poly_struct **) flint_malloc(nvars1 * sizeof(fmpz_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpz_poly_struct *) flint_malloc( sizeof(fmpz_poly_struct)); fmpz_poly_init(vals1[v]); fmpz_poly_randtest(vals1[v], state, len2, coeff_bits2); } fmpz_init(vals2); fmpz_randbits(vals2, state, 10); vals3 = (fmpz **) flint_malloc(nvars1*sizeof(fmpz *)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals3[v]); fmpz_poly_evaluate_fmpz(vals3[v], vals1[v], vals2); } if (fmpz_mpoly_total_degree_si(f, ctx1) < 50) { if (!fmpz_mpoly_compose_fmpz_poly(g, f, vals1, ctx1) || !fmpz_mpoly_evaluate_all_fmpz(fe, f, vals3, ctx1)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_poly_evaluate_fmpz(ge, g, vals2); if (!fmpz_equal(fe, ge)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars1; v++) { fmpz_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); fmpz_clear(vals2); for (v = 0; v < nvars1; v++) { fmpz_poly_clear(vals1[v]); flint_free(vals1[v]); } flint_free(vals1); fmpz_clear(fe); fmpz_clear(ge); fmpz_mpoly_clear(f, ctx1); fmpz_poly_clear(g); fmpz_mpoly_ctx_clear(ctx1); } /* Check composition with constants matches evalall */ for (i = 0; i < 50*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx1; fmpz_mpoly_t f; fmpz_poly_t g; fmpz_poly_struct ** vals1; fmpz_t fe; fmpz ** vals3; slong nvars1; slong len1; slong exp_bound1; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx1, state, 10); nvars1 = ctx1->minfo->nvars; fmpz_mpoly_init(f, ctx1); fmpz_poly_init(g); fmpz_init(fe); len1 = n_randint(state, 50); exp_bound1 = n_randint(state, 200/FLINT_MAX(WORD(1), nvars1) + 2) + 1; coeff_bits = n_randint(state, 100) + 1; fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx1); vals3 = (fmpz **) flint_malloc(nvars1*sizeof(fmpz *)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals3[v]); fmpz_randtest(vals3[v], state, 20); } vals1 = (fmpz_poly_struct **) flint_malloc(nvars1 * sizeof(fmpz_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpz_poly_struct *) flint_malloc( sizeof(fmpz_poly_struct)); fmpz_poly_init(vals1[v]); fmpz_poly_set_fmpz(vals1[v], vals3[v]); } if (fmpz_mpoly_total_degree_si(f, ctx1) < 50) { fmpz_poly_t t; if (!fmpz_mpoly_compose_fmpz_poly(g, f, vals1, ctx1) || !fmpz_mpoly_evaluate_all_fmpz(fe, f, vals3, ctx1)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_poly_init(t); fmpz_poly_set_fmpz(t, fe); if (!fmpz_poly_equal(g, t)) { printf("FAIL\n"); flint_printf("Check composition with constants matches evalall\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_poly_clear(t); } for (v = 0; v < nvars1; v++) { fmpz_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); for (v = 0; v < nvars1; v++) { fmpz_poly_clear(vals1[v]); flint_free(vals1[v]); } flint_free(vals1); fmpz_clear(fe); fmpz_mpoly_clear(f, ctx1); fmpz_poly_clear(g); fmpz_mpoly_ctx_clear(ctx1); } /* Check multiprecision composition with constants matches evalall */ for (i = 0; i < 50*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx1; fmpz_mpoly_t f; fmpz_poly_t g; fmpz_poly_struct ** vals1; fmpz_t fe; fmpz ** vals3; slong nvars1; slong len1; flint_bitcnt_t exp_bits; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx1, state, 10); nvars1 = ctx1->minfo->nvars; fmpz_mpoly_init(f, ctx1); fmpz_poly_init(g); fmpz_init(fe); len1 = n_randint(state, 50); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 100) + 1; fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx1); vals3 = (fmpz **) flint_malloc(nvars1*sizeof(fmpz *)); for (v = 0; v < nvars1; v++) { vals3[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals3[v]); fmpz_set_si(vals3[v], n_randint(state, UWORD(3)) - WORD(1)); } vals1 = (fmpz_poly_struct **) flint_malloc(nvars1 * sizeof(fmpz_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fmpz_poly_struct *) flint_malloc( sizeof(fmpz_poly_struct)); fmpz_poly_init(vals1[v]); fmpz_poly_set_fmpz(vals1[v], vals3[v]); } { fmpz_poly_t t; if (!fmpz_mpoly_compose_fmpz_poly(g, f, vals1, ctx1) || !fmpz_mpoly_evaluate_all_fmpz(fe, f, vals3, ctx1)) { printf("FAIL\n"); flint_printf("Check evaluation success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_poly_init(t); fmpz_poly_set_fmpz(t, fe); if (!fmpz_poly_equal(g, t)) { printf("FAIL\n"); flint_printf("Check multiprecision composition with constants matches evalall\ni: %wd\n", i); fflush(stdout); flint_abort(); } fmpz_poly_clear(t); } for (v = 0; v < nvars1; v++) { fmpz_clear(vals3[v]); flint_free(vals3[v]); } flint_free(vals3); for (v = 0; v < nvars1; v++) { fmpz_poly_clear(vals1[v]); flint_free(vals1[v]); } flint_free(vals1); fmpz_clear(fe); fmpz_mpoly_clear(f, ctx1); fmpz_poly_clear(g); fmpz_mpoly_ctx_clear(ctx1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-content_vars.c000066400000000000000000000077731461254215100217250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_content_vars, state) { slong i, j; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, t; slong nvars, num_vars, len; ulong * exp_bounds; slong * vars; fmpz_mpoly_ctx_init_rand(ctx, state, 20); if (ctx->minfo->nvars < 1) { fmpz_mpoly_ctx_clear(ctx); fmpz_mpoly_ctx_init(ctx, 1, ORD_LEX); } nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(t, ctx); exp_bounds = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (j = 0; j < nvars; j++) exp_bounds[j] = 1 + n_randint(state, 5); len = n_randint(state, 20); fmpz_mpoly_randtest_bounds(f, state, len, 200, exp_bounds, ctx); vars = (slong *) flint_malloc(nvars*sizeof(slong)); for (j = 0; j < nvars; j++) vars[j] = j; for (j = 0; j < 2*nvars; j++) { slong k1 = n_randint(state, nvars); slong k2 = n_randint(state, nvars); FLINT_SWAP(slong, vars[k1], vars[k2]); } num_vars = 1 + n_randint(state, nvars); for (j = 0; j < num_vars; j++) exp_bounds[vars[j]] = 1; len = n_randint(state, 10); fmpz_mpoly_randtest_bounds(t, state, len, 200, exp_bounds, ctx); fmpz_mpoly_mul(f, f, t, ctx); fmpz_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); if (!fmpz_mpoly_content_vars(g, f, vars, num_vars, ctx)) { flint_printf("FAIL: check content could be computed\n"); fflush(stdout); flint_abort(); } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(f, ctx)) { flint_printf("FAIL: check zero content\n"); fflush(stdout); flint_abort(); } } else { for (j = 0; j < num_vars; j++) { if (fmpz_mpoly_degree_si(g, vars[j], ctx) != 0) { flint_printf("FAIL: content depends on a bad variable\n"); fflush(stdout); flint_abort(); } } if (!fmpz_mpoly_divides(t, f, g, ctx)) { flint_printf("FAIL: check content divides\n"); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_content_vars(t, t, vars, num_vars, ctx)) { flint_printf("FAIL: check cofactor content could be computed\n"); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(t, ctx)) { flint_printf("FAIL: check cofactor content is one\n"); fflush(stdout); flint_abort(); } } if (!fmpz_mpoly_content_vars(f, f, vars, num_vars, ctx)) { flint_printf("FAIL: check aliased content could be computed\n"); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check aliasing\n"); fflush(stdout); flint_abort(); } flint_free(exp_bounds); flint_free(vars); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-degree.c000066400000000000000000000142131461254215100204360ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" /* check various degree operations */ void _check_degrees(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; int fits_si; fmpz ** degs; slong * degs_si; slong nvars = ctx->minfo->nvars; degs = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); for (i = 0; i < nvars; i++) { degs[i] = flint_malloc(sizeof(fmpz)); fmpz_init(degs[i]); } fmpz_mpoly_degrees_fmpz(degs, A, ctx); fits_si = 1; for (i = 0; i < nvars; i++) { fits_si = fits_si && fmpz_fits_si(degs[i]); } if (fits_si != fmpz_mpoly_degrees_fit_si(A, ctx)) { printf("FAIL\n"); flint_printf("Check degrees_fit_si\n"); fflush(stdout); flint_abort(); } if (fits_si) { degs_si = (slong *) flint_malloc(nvars*sizeof(slong)); fmpz_mpoly_degrees_si(degs_si, A, ctx); for (i = 0; i < nvars; i++) { if (degs_si[i] != fmpz_get_si(degs[i])) { printf("FAIL\n"); flint_printf("Check degrees_si\n"); fflush(stdout); flint_abort(); } if (degs_si[i] != fmpz_mpoly_degree_si(A, i, ctx)) { printf("FAIL\n"); flint_printf("Check individual degree_si\n"); fflush(stdout); flint_abort(); } } flint_free(degs_si); } for (i = 0; i < nvars; i++) { fmpz_t degi; fmpz_init(degi); fmpz_mpoly_degree_fmpz(degi, A, i, ctx); if (!fmpz_equal(degi, degs[i])) { printf("FAIL\n"); flint_printf("Check individual degree_fmpz\n"); fflush(stdout); flint_abort(); } fmpz_clear(degi); } for (i = 0; i < nvars; i++) { fmpz_clear(degs[i]); flint_free(degs[i]); } flint_free(degs); } TEST_FUNCTION_START(fmpz_mpoly_degree, state) { int i, j; /* Check degree does not go up under addition */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 4); for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_add(h, f, g, ctx); _check_degrees(h, ctx); _check_degrees(f, ctx); _check_degrees(g, ctx); fmpz_mpoly_degree_fmpz(hdeg, h, j, ctx); fmpz_mpoly_degree_fmpz(fdeg, f, j, ctx); fmpz_mpoly_degree_fmpz(gdeg, g, j, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check degree adds under multiplication */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { int ok; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 4); for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_mul(h, f, g, ctx); _check_degrees(h, ctx); _check_degrees(f, ctx); _check_degrees(g, ctx); fmpz_mpoly_degree_fmpz(hdeg, h, j, ctx); fmpz_mpoly_degree_fmpz(fdeg, f, j, ctx); fmpz_mpoly_degree_fmpz(gdeg, g, j, ctx); if (fmpz_mpoly_is_zero(g, ctx) || fmpz_mpoly_is_zero(f, ctx)) { ok = (fmpz_cmp_si(hdeg, -WORD(1)) == 0); } else { fmpz_sub(hdeg, hdeg, fdeg); ok = (fmpz_cmp(hdeg, gdeg) == 0); } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-degrees_term_exp_fits_ui_si.c000066400000000000000000000210701461254215100247400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_degrees_term_exp_fits_ui_si, state) { slong i, j, k; int result; /* basic corner cases */ { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; const char * vars[] = {"x","y","z"}; fmpz_mpoly_ctx_init(ctx, 3, ORD_DEGLEX); fmpz_mpoly_init(f, ctx); if (FLINT_BITS == 64) { fmpz_mpoly_set_str_pretty(f, "x^9223372036854775807", vars, ctx); if (!fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 1\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "(x*y)^9223372036854775807", vars, ctx); if (!fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 2\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^9223372036854775808", vars, ctx); if (fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 3\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "(x*y)^9223372036854775808", vars, ctx); if (fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 4\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^18446744073709551615", vars, ctx); if (!fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 1\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "(x*y)^18446744073709551615", vars, ctx); if (!fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 2\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^18446744073709551616", vars, ctx); if (fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 3\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "(x*y)^18446744073709551616", vars, ctx); if (fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 4\n"); fflush(stdout); flint_abort(); } } else if (FLINT_BITS == 32) { fmpz_mpoly_set_str_pretty(f, "x^2147483647", vars, ctx); if (!fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 1\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^2147483647*y^2147483647", vars, ctx); if (!fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || !fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 2\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^2147483648", vars, ctx); if (fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 3\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^2147483648*y^2147483648", vars, ctx); if (fmpz_mpoly_term_exp_fits_si(f, 0, ctx) || fmpz_mpoly_degrees_fit_si(f, ctx)) { printf("FAIL\nsi test 4\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^4294967295", vars, ctx); if (!fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 1\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^4294967295*y^4294967295", vars, ctx); if (!fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 2\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^4294967296", vars, ctx); if (fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 3\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "x^4294967296*y^4294967296", vars, ctx); if (fmpz_mpoly_term_exp_fits_ui(f, 0, ctx)) { printf("FAIL\nui test 4\n"); fflush(stdout); flint_abort(); } } else { printf("FAIL\nFLINT_BITS is not 64 or 32\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check fit */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz ** exp, ** deg; slong nvars, len; flint_bitcnt_t coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); nvars = fmpz_mpoly_ctx_nvars(ctx); exp = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); deg = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); deg[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_init(deg[k]); fmpz_set_si(deg[k], -WORD(1)); } len = n_randint(state, 100); exp_bits = n_randint(state, FLINT_BITS + 10) + 1; coeff_bits = n_randint(state, 30); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < fmpz_mpoly_length(f, ctx); j++) { fmpz_mpoly_get_term_exp_fmpz(exp, f, j, ctx); for (k = 0; k < nvars; k++) if (fmpz_cmp(deg[k], exp[k]) < 0) fmpz_set(deg[k], exp[k]); result = 1; for (k = 0; k < nvars; k++) result = result && fmpz_fits_si(exp[k]); if (result != fmpz_mpoly_term_exp_fits_si(f, j, ctx)) { flint_printf("FAIL\nCheck monomial_fit_si\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } result = 1; for (k = 0; k < nvars; k++) result = result && fmpz_abs_fits_ui(exp[k]); if (result != fmpz_mpoly_term_exp_fits_ui(f, j, ctx)) { flint_printf("FAIL\nCheck monomial_fit_ui\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } result = 1; fmpz_mpoly_degrees_fmpz(exp, f, ctx); for (k = 0; k < nvars; k++) { if (!fmpz_equal(exp[k], deg[k])) { flint_printf("FAIL\nCheck degree computation\ni = %wd\n", i); fflush(stdout); flint_abort(); } result = result && fmpz_fits_si(exp[k]); } if (result != fmpz_mpoly_degrees_fit_si(f, ctx)) { flint_printf("FAIL\nCheck degrees_fit_si\ni = %wd\n", i); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { fmpz_clear(deg[k]); flint_free(deg[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(deg); flint_free(exp); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-derivative_integral.c000066400000000000000000000223751461254215100232420ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_derivative_integral, state) { int i, j, result; slong tmul = 5; /* randomized testing doesn't catch exponent overflow in integral */ { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; fmpz_t s; const char* vars[] = {"x","y","z","w","s","t","u","v"}; fmpz_mpoly_ctx_init(ctx, 7, ORD_DEGLEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_init(s); result = fmpz_mpoly_set_str_pretty(f, "-2*x^2*(y+z)+z*y^126", vars, ctx); if (result) { printf("FAIL\n"); flint_printf("set_str_pretty\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_integral(g, s, f, 1, ctx); fmpz_mpoly_derivative(g, g, 1, ctx); fmpz_mpoly_scalar_divexact_fmpz(g, g, s, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("manual integral check\n"); fflush(stdout); flint_abort(); } fmpz_clear(s); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } /* Check d(f*g) = df*g + f*dg */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, fp, gp, hp, t1, t2; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(fp, ctx); fmpz_mpoly_init(gp, ctx); fmpz_mpoly_init(hp, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(hp, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(fp, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(gp, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); idx = n_randint(state, nvars); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_derivative(hp, h, idx, ctx); fmpz_mpoly_assert_canonical(hp, ctx); fmpz_mpoly_derivative(fp, f, idx, ctx); fmpz_mpoly_assert_canonical(fp, ctx); fmpz_mpoly_derivative(gp, g, idx, ctx); fmpz_mpoly_assert_canonical(gp, ctx); fmpz_mpoly_mul_johnson(t1, f, gp, ctx); fmpz_mpoly_assert_canonical(t1, ctx); fmpz_mpoly_mul_johnson(t2, g, fp, ctx); fmpz_mpoly_assert_canonical(t2, ctx); fmpz_mpoly_add(t1, t1, t2, ctx); fmpz_mpoly_assert_canonical(t1, ctx); result = fmpz_mpoly_equal(hp, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(fp, ctx); fmpz_mpoly_clear(gp, ctx); fmpz_mpoly_clear(hp, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); } /* Check d(f*g) = df*g + f*dg with aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, fp, gp, t1, t2; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(fp, ctx); fmpz_mpoly_init(gp, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(fp, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(gp, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); idx = n_randint(state, nvars); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_derivative(h, h, idx, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_set(fp, f, ctx); fmpz_mpoly_derivative(fp, fp, idx, ctx); fmpz_mpoly_assert_canonical(fp, ctx); fmpz_mpoly_set(gp, g, ctx); fmpz_mpoly_derivative(gp, gp, idx, ctx); fmpz_mpoly_assert_canonical(gp, ctx); fmpz_mpoly_mul_johnson(t1, f, gp, ctx); fmpz_mpoly_assert_canonical(t1, ctx); fmpz_mpoly_mul_johnson(t2, g, fp, ctx); fmpz_mpoly_assert_canonical(t2, ctx); fmpz_mpoly_add(t1, t1, t2, ctx); fmpz_mpoly_assert_canonical(t1, ctx); result = fmpz_mpoly_equal(h, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg with aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(fp, ctx); fmpz_mpoly_clear(gp, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); } /* Check d(int(f)) = f with aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, f1; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_t s, s1; nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpz_init(s); fmpz_init(s1); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(f1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 20); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(f1, state, len1, coeff_bits, exp_bits1, ctx); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); idx = n_randint(state, nvars); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_integral(f1, s1, f, idx, ctx); fmpz_mpoly_assert_canonical(f1, ctx); fmpz_mpoly_integral(f, s, f, idx, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_equal(s, s1) && fmpz_mpoly_equal(f, f1, ctx); fmpz_mpoly_derivative(f, f, idx, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_scalar_mul_fmpz(g, g, s, ctx); result = result && fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(int(f)) = f with aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(s); fmpz_clear(s1); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(f1, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000313451461254215100230110ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_div_monagan_pearce, state) { slong i, j, tmul = 10; { fmpz_mpoly_t f, g, p, q; fmpz_mpoly_ctx_t ctx; const char * vars[] = {"x", "y", "z", "t", "u"}; fmpz_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(p, ctx); fmpz_mpoly_init(q, ctx); fmpz_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)^6", vars, ctx); fmpz_mpoly_set_str_pretty(g, "(1+u+t+2*z^2+3*y^3+5*x^5)^6", vars, ctx); fmpz_mpoly_mul(p, f, g, ctx); fmpz_mpoly_assert_canonical(p, ctx); fmpz_mpoly_div_monagan_pearce(q, p, f, ctx); fmpz_mpoly_assert_canonical(q, ctx); if (!fmpz_mpoly_equal(q, g, ctx)) { printf("FAIL\n"); flint_printf("Check example1\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_clear(q, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f*g/g = f */ for (i = 0; i < 10 * tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_div_monagan_pearce(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); if (!fmpz_mpoly_equal(f, k, ctx)) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check output agrees with divrem for random polys */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; coeff_bits = n_randint(state, 70); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 500/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bounds(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_div_monagan_pearce(k, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); if (!fmpz_mpoly_equal(k, h, ctx)) { printf("FAIL\n"); flint_printf("Check output agrees with divrem\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r, ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; coeff_bits = n_randint(state, 70); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 500/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_div_monagan_pearce(f, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (!fmpz_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r, ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; coeff_bits = n_randint(state, 70); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 500/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_div_monagan_pearce(g, f, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!fmpz_mpoly_equal(g, h, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-divides.c000066400000000000000000000273111461254215100206350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_divides, state) { int i, j, result, ret, max_threads = 5, tmul = 25; /* Check f*g/g = f sparse */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, hsave, gsave; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2, coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(hsave, ctx); fmpz_mpoly_init(gsave, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_set(hsave, h, ctx); fmpz_mpoly_set(gsave, g, ctx); ret = fmpz_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f sparse\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if ( !fmpz_mpoly_equal(h, hsave, ctx) || !fmpz_mpoly_equal(g, gsave, ctx)) { printf("FAIL\n"); flint_printf("Check f*g/g = f sparse input modification\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(hsave, ctx); fmpz_mpoly_clear(gsave, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check divisibility of random polys */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2, coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); coeff_bits = n_randint(state, 200) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 20/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2 + 1, coeff_bits, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bounds(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); ret = fmpz_mpoly_divides(h, f, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); if (ret == 0) continue; fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_mul(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check divisibility of random polys\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); coeff_bits = n_randint(state, 200) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2 + 1, coeff_bits, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bounds(k, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_set(h, f, ctx); fmpz_mpoly_mul(h, h, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ret = fmpz_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing first\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); coeff_bits = n_randint(state, 200) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2 + 1, coeff_bits, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bounds(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_set(h, g, ctx); fmpz_mpoly_mul(h, f, h, ctx); fmpz_mpoly_assert_canonical(h, ctx); ret = fmpz_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); fmpz_mpoly_assert_canonical(k, ctx); result = (ret == 1) && fmpz_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing second\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-divides_array.c000066400000000000000000000207721461254215100220370ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_divides_array, state) { int i, j, result, ok1, ok2; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divides_array(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = (ok1 == -1) || (ok1 && fmpz_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check random polys don't divide */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 30); len1 = n_randint(state, 30); len2 = n_randint(state, 30) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpz_mpoly_divides_array(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); if (ok1) { fmpz_mpoly_mul_johnson(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); } result = (ok1 == -1 || ok1 == 0) || (ok1 == 1 && fmpz_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check random polys don't divide\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check aliasing first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divides_array(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); ok2 = fmpz_mpoly_divides_array(h, h, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = (ok1 == -1 || ok2 == -1) || (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(h, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check aliasing second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divides_array(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); ok2 = fmpz_mpoly_divides_array(g, h, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = (ok1 == -1 && ok2 == -1) || (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(g, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-divides_heap_threaded.c000066400000000000000000000334701461254215100234750ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" #if defined(fmpz_mpoly_divides_heap_threaded) TEST_FUNCTION_START(fmpz_mpoly_divides_heap_threaded, state) { int result, result2; slong i, j, max_threads = 5, tmul = 15; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t p, f, g, h, h2; const char * vars[] = {"x","y","z","t","u"}; int aff[] = {0, 1, 2}; fmpz_mpoly_ctx_init(ctx, 5, ORD_DEGLEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(p, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(h2, ctx); fmpz_mpoly_set_str_pretty(g, "(1+x+y+2*z^2+3*t^3+5*u^5)^6", vars, ctx); fmpz_mpoly_set_str_pretty(f, "(1+u+t+2*z^2+3*y^3+5*x^5)^6", vars, ctx); fmpz_mpoly_mul(p, f, g, ctx); result = fmpz_mpoly_divides_monagan_pearce(h, p, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); flint_set_num_threads(2); flint_set_thread_affinity(aff, 2); result2 = fmpz_mpoly_divides_heap_threaded(h2, p, f, ctx); flint_restore_thread_affinity(); fmpz_mpoly_assert_canonical(h2, ctx); if (!result || !result2 || !fmpz_mpoly_equal(h, g, ctx) || !fmpz_mpoly_equal(h2, g, ctx)) { printf("FAIL\n"); flint_printf("Check simple example\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(h2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f*g/g = f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(k, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_divides_heap_threaded(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = result && fmpz_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f*g/g = f with divisor aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_divides_heap_threaded(g, h, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = result && fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f with divisor aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f*g/g = f with dividend aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_divides_heap_threaded(h, h, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = result && fmpz_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f with dividend aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check random polys don't divide */ for (i = 0; i < tmul*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, p, h1, h2; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bound3; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(p, ctx); fmpz_mpoly_init(h1, ctx); fmpz_mpoly_init(h2, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; len3 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bound3 = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(p, state, len3, coeff_bits, exp_bound3, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(f, f, g, ctx); fmpz_mpoly_add(f, f, p, ctx); result = fmpz_mpoly_divides_monagan_pearce(h1, f, g, ctx); fmpz_mpoly_assert_canonical(h1, ctx); result2 = fmpz_mpoly_divides_heap_threaded(h2, f, g, ctx); fmpz_mpoly_assert_canonical(h2, ctx); if (result != result2 || !fmpz_mpoly_equal(h1, h2, ctx)) { flint_printf("Check random polys don't divide\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_clear(h1, ctx); fmpz_mpoly_clear(h2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check random polys don't divide alias dividend */ for (i = 0; i < tmul*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, p, h1; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bound3; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(p, ctx); fmpz_mpoly_init(h1, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; len3 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bound3 = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(p, state, len3, coeff_bits, exp_bound3, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(f, f, g, ctx); fmpz_mpoly_add(f, f, p, ctx); result = fmpz_mpoly_divides_monagan_pearce(h1, f, g, ctx); fmpz_mpoly_assert_canonical(h1, ctx); result2 = fmpz_mpoly_divides_heap_threaded(f, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (result != result2 || !fmpz_mpoly_equal(h1, f, ctx)) { flint_printf("Check random polys don't divide alias dividend\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_clear(h1, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check random polys don't divide alias divisor */ for (i = 0; i < tmul*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, p, h1; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bound3; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(p, ctx); fmpz_mpoly_init(h1, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; len3 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bound3 = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(p, state, len3, coeff_bits, exp_bound3, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(f, f, g, ctx); fmpz_mpoly_add(f, f, p, ctx); result = fmpz_mpoly_divides_monagan_pearce(h1, f, g, ctx); fmpz_mpoly_assert_canonical(h1, ctx); result2 = fmpz_mpoly_divides_heap_threaded(g, f, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (result != result2 || !fmpz_mpoly_equal(h1, g, ctx)) { flint_printf("Check random polys don't divide alias divisor\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_clear(h1, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(fmpz_mpoly_divides_heap_threaded, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/fmpz_mpoly/test/t-divides_monagan_pearce.c000066400000000000000000000330741461254215100236570ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_divides_monagan_pearce, state) { int i, j, result, ok1, ok2; /* A bad case is hit when testing with multiplier 50. The following example illustrates this behaviour if the ordering is changed to ORD_DEGLEX */ { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, q, r; fmpz_mpoly_ctx_init(ctx, 2, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(q, ctx); fmpz_mpoly_init(r, ctx); fmpz_mpoly_set_str_pretty(f, "-x1^1918*x2^1075-x1^1891*x2^2001",NULL, ctx); fmpz_mpoly_set_str_pretty(g, "x1^22*x2^3-x1^19*x2^21-x1^16*x2^10-2*x1^14*x2^17-x1^14*x2^11-x1*x2^15-2*x2^17", NULL, ctx); ok1 = fmpz_mpoly_divides_monagan_pearce(q, f, g, ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(q, ctx); fmpz_mpoly_clear(r, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check f*g/g = f */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divides_monagan_pearce(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = (ok1 && fmpz_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check random polys don't divide */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 1000/n/n) + 1; exp_bound1 = n_randint(state, 1000/n/n) + 1; exp_bound2 = n_randint(state, 1000/n/n) + 1; coeff_bits = n_randint(state, 200); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); ok1 = fmpz_mpoly_divides_monagan_pearce(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); if (ok1 == 0) continue; fmpz_mpoly_mul_johnson(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check random polys don't divide\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing first argument, exact division */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divides_monagan_pearce(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); ok2 = fmpz_mpoly_divides_monagan_pearce(h, h, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(h, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument, exact division\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing, first argument, random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 1000/n/n) + 1; exp_bound1 = n_randint(state, 1000/n/n) + 1; exp_bound2 = n_randint(state, 1000/n/n) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpz_mpoly_divides_monagan_pearce(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok2 = fmpz_mpoly_divides_monagan_pearce(f, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = ((ok1 == ok2) && (ok1 == 0 || fmpz_mpoly_equal(f, h, ctx))); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing, first argument, random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing second argument, exact division */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divides_monagan_pearce(k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); ok2 = fmpz_mpoly_divides_monagan_pearce(g, h, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(g, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument, exact division\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing, second argument, random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 1000/n/n) + 1; exp_bound1 = n_randint(state, 1000/n/n) + 1; exp_bound2 = n_randint(state, 1000/n/n) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpz_mpoly_divides_monagan_pearce(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok2 = fmpz_mpoly_divides_monagan_pearce(g, f, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = ((ok1 == ok2) && (ok1 == 0 || fmpz_mpoly_equal(g, h, ctx))); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing, second argument, random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-divrem_array.c000066400000000000000000000347631461254215100217030ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_divrem_array, state) { int i, j, result, ok1, ok2; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divrem_array(k, r, h, g, ctx); if (ok1) fmpz_mpoly_remainder_test(r, g, ctx); result = (ok1 == 0) || (ok1 && fmpz_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r, ctx); } /* Check f = g*q + r for random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpz_mpoly_divrem_array(h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r, ctx); if (ok1) { fmpz_mpoly_remainder_test(r, g, ctx); fmpz_mpoly_mul_johnson(k, h, g, ctx); fmpz_mpoly_add(k, k, r, ctx); } result = (ok1 == 0) || (ok1 == 1 && fmpz_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r, ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r1, r2; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(r2, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r2, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpz_mpoly_divrem_array(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); if (ok1) fmpz_mpoly_remainder_test(r1, g, ctx); ok2 = fmpz_mpoly_divrem_array(f, r2, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_assert_canonical(r2, ctx); if (ok2) fmpz_mpoly_remainder_test(r2, g, ctx); result = (ok1 == 0 || ok2 == 0) || (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(h, f, ctx) && fmpz_mpoly_equal(r1, r2, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(r2, ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r1, r2; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(r2, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, exp_bound2, coeff_bits + 1, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r2, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpz_mpoly_divrem_array(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); if (ok1) fmpz_mpoly_remainder_test(r1, g, ctx); ok2 = fmpz_mpoly_divrem_array(g, r2, f, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_assert_canonical(r2, ctx); result = (ok1 == 0 || ok2 == 0) || (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(h, g, ctx) && fmpz_mpoly_equal(r1, r2, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(r2, ctx); } /* Check aliasing of remainder with first argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divrem_array(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); if (ok1) fmpz_mpoly_remainder_test(r1, g, ctx); ok2 = fmpz_mpoly_divrem_array(k, f, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (ok2) fmpz_mpoly_remainder_test(f, g, ctx); result = (ok1 == 0 || ok2 == 0) || (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(h, k, ctx) && fmpz_mpoly_equal(r1, f, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); } /* Check aliasing of remainder with second argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; exp_bound = n_randint(state, 1000/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); ok1 = fmpz_mpoly_divrem_array(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); if (ok1) fmpz_mpoly_remainder_test(r1, g, ctx); ok2 = fmpz_mpoly_divrem_array(k, g, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = (ok1 == 0 || ok2 == 0) || (ok1 == 1 && ok2 == 1 && fmpz_mpoly_equal(h, k, ctx) && fmpz_mpoly_equal(r1, g, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000222121461254215100246440ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_divrem_ideal_monagan_pearce, state) { int i, j, w, result; slong tmul = 10; /* Check f*g/g = f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r; slong len, len1, len2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_struct * qarr[1], * darr[1]; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(r, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); qarr[0] = k; darr[0] = g; fmpz_mpoly_divrem_ideal_monagan_pearce(qarr, r, h, darr, 1, ctx); result = fmpz_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r, ctx); } /* Check f = g1*q1 + ... + gn*qn + r for random polys */ for (i = 0; i < tmul*tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, r, k1, k2; fmpz_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; slong n; fmpz_mpoly_struct * qarr[5], * darr[5]; fmpz * shifts, * strides; num = n_randint(state, 5) + 1; g = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); q = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); fmpz_mpoly_ctx_init_rand(ctx, state, 9); for (w = 0; w < num; w++) { fmpz_mpoly_init(g + w, ctx); darr[w] = g + w; fmpz_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 2 + 175/n/n) + 1; exp_bound1 = n_randint(state, 2 + 175/n/n) + 1; exp_bound2 = n_randint(state, 2 + 175/n/n) + 1; coeff_bits = n_randint(state, 70); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_assert_canonical(f, ctx); for (w = 0; w < num; w++) { do { fmpz_mpoly_randtest_bound(darr[w], state, len2, coeff_bits + 1, exp_bound2, ctx); } while (darr[w]->length == 0); fmpz_mpoly_inflate(darr[w], darr[w], shifts, strides, ctx); fmpz_mpoly_assert_canonical(darr[w], ctx); fmpz_mpoly_randtest_bound(qarr[w], state, len, coeff_bits, exp_bound, ctx); } fmpz_mpoly_randtest_bound(k1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k2, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_divrem_ideal_monagan_pearce(qarr, r, f, darr, num, ctx); fmpz_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { fmpz_mpoly_assert_canonical(qarr[w], ctx); fmpz_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fmpz_mpoly_add(k2, k2, k1, ctx); } fmpz_mpoly_add(k2, k2, r, ctx); result = fmpz_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g1*q1 + ... + gn*qn + r for random polys" "\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); for (w = 0; w < num; w++) fmpz_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpz_mpoly_clear(darr[w], ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_clear(r, ctx); flint_free(g); flint_free(q); } /* Check aliasing */ for (i = 0; i < 2*tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, r, k1, k2; fmpz_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; slong n; fmpz_mpoly_struct * qarr[5], * darr[5]; num = n_randint(state, 5) + 1; g = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); q = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); fmpz_mpoly_ctx_init_rand(ctx, state, 10); for (w = 0; w < num; w++) { fmpz_mpoly_init(g + w, ctx); darr[w] = g + w; fmpz_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 3 + 200/n/n) + 1; exp_bound1 = n_randint(state, 3 + 200/n/n) + 1; exp_bound2 = n_randint(state, 3 + 200/n/n) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); for (w = 0; w < num; w++) { do { fmpz_mpoly_randtest_bound(darr[w], state, len2, coeff_bits + 1, exp_bound2, ctx); } while (darr[w]->length == 0); fmpz_mpoly_randtest_bound(qarr[w], state, len, coeff_bits, exp_bound, ctx); } fmpz_mpoly_randtest_bound(k1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k2, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_set(r, f, ctx); fmpz_mpoly_divrem_ideal_monagan_pearce(qarr, f, f, darr, num, ctx); fmpz_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { fmpz_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fmpz_mpoly_add(k2, k2, k1, ctx); } fmpz_mpoly_add(k2, k2, f, ctx); result = fmpz_mpoly_equal(r, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) fmpz_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpz_mpoly_clear(darr[w], ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_clear(r, ctx); flint_free(g); flint_free(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-divrem_monagan_pearce.c000066400000000000000000000325371461254215100235210ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_divrem_monagan_pearce, state) { int i, j, result; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r; slong len, len1, len2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(r, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_divrem_monagan_pearce(k, r, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(r, ctx); result = fmpz_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r, ctx); } /* Check f = g*q + r for random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 800/n/n) + 1; exp_bound1 = n_randint(state, 800/n/n) + 1; exp_bound2 = n_randint(state, 800/n/n) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r, ctx); fmpz_mpoly_remainder_test(r, g, ctx); fmpz_mpoly_mul_johnson(k, h, g, ctx); fmpz_mpoly_add(k, k, r, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r, ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r1, r2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(r2, ctx); len = n_randint(state, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 800/n/n) + 1; exp_bound1 = n_randint(state, 800/n/n) + 1; exp_bound2 = n_randint(state, 800/n/n) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r2, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_test(r1, g, ctx); fmpz_mpoly_divrem_monagan_pearce(f, r2, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r2, ctx); fmpz_mpoly_remainder_test(r2, g, ctx); result = fmpz_mpoly_equal(h, f, ctx) && fmpz_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(r2, ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r1, r2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(r2, ctx); len = n_randint(state, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 800/n/n) + 1; exp_bound1 = n_randint(state, 800/n/n) + 1; exp_bound2 = n_randint(state, 800/n/n) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r2, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_test(r1, g, ctx); fmpz_mpoly_divrem_monagan_pearce(g, r2, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r2, ctx); result = fmpz_mpoly_equal(h, g, ctx) && fmpz_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(r2, ctx); } /* Check aliasing of remainder with first argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); len = n_randint(state, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 800/n/n) + 1; exp_bound1 = n_randint(state, 800/n/n) + 1; exp_bound2 = n_randint(state, 800/n/n) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_test(r1, g, ctx); fmpz_mpoly_divrem_monagan_pearce(k, f, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_remainder_test(f, g, ctx); result = fmpz_mpoly_equal(h, k, ctx) && fmpz_mpoly_equal(r1, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); } /* Check aliasing of remainder with second argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); len = n_randint(state, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 800/n/n) + 1; exp_bound1 = n_randint(state, 800/n/n) + 1; exp_bound2 = n_randint(state, 800/n/n) + 1; coeff_bits = n_randint(state, 70); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_test(r1, g, ctx); fmpz_mpoly_divrem_monagan_pearce(k, g, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(h, k, ctx) && fmpz_mpoly_equal(r1, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-evaluate.c000066400000000000000000000305731461254215100210200ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_evaluate, state) { slong i, j, v; { fmpz_t A1; fmpz_mpoly_t A, B; fmpz * Cp[3]; fmpz C[3]; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_ctx_init(ctx, 3, ORD_LEX); fmpz_init(A1); fmpz_mpoly_init(B, ctx); fmpz_mpoly_init(A, ctx); for (i = 0; i < 3; i++) { Cp[i] = C + i; fmpz_init(C + i); } fmpz_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctx); fmpz_set_si(C + 0, 2); fmpz_set_si(C + 1, 2); fmpz_set_si(C + 2, 2); if (fmpz_mpoly_evaluate_all_fmpz(A1, B, Cp, ctx)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } if (fmpz_mpoly_evaluate_one_fmpz(A, B, 1, C + 1, ctx)) { printf("FAIL\n"); flint_printf("Check non-example 2\n", i); fflush(stdout); flint_abort(); } fmpz_set_si(C + 0, 1); fmpz_set_si(C + 1, 1); fmpz_set_si(C + 2, 1); if (!fmpz_mpoly_evaluate_all_fmpz(A1, B, Cp, ctx) || !fmpz_equal_si(A1, 3)) { printf("FAIL\n"); flint_printf("Check example 3\n", i); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_evaluate_one_fmpz(A, B, 1, C + 1, ctx)) { printf("FAIL\n"); flint_printf("Check example 4\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(B, "1 + x1 + x3^9", NULL, ctx); if (!fmpz_mpoly_equal(A, B, ctx)) { printf("FAIL\n"); flint_printf("Check example 4 equality\n", i); fflush(stdout); flint_abort(); } fmpz_clear(A1); fmpz_mpoly_clear(B, ctx); fmpz_mpoly_clear(A, ctx); for (i = 0; i < 3; i++) fmpz_clear(C + i); fmpz_mpoly_ctx_clear(ctx); } /* Check repeated evalone matches evalall */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_t fe; fmpz ** vals; slong * perm; slong nvars, len1, exp_bound1; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); fmpz_init(fe); perm = (slong *) flint_malloc(nvars*sizeof(slong)); len1 = n_randint(state, 50); exp_bound1 = n_randint(state, 10) + 1; coeff_bits = n_randint(state, 100) + 1; vals = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); for (v = 0; v < nvars; v++) { vals[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals[v]); fmpz_randbits(vals[v], state, 10); perm[v] = v; } for (j = 0; j < 2*nvars; j++) { slong a, b, c; a = n_randint(state, nvars); b = n_randint(state, nvars); c = perm[a]; perm[a] = perm[b]; perm[b] = c; } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); if (!fmpz_mpoly_evaluate_all_fmpz(fe, f, vals, ctx)) { printf("FAIL\n"); flint_printf("Check evaluations success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } for (v = 0; v < nvars; v++) { if (!fmpz_mpoly_evaluate_one_fmpz(f, f, perm[v], vals[perm[v]], ctx)) { printf("FAIL\n"); flint_printf("Check evaluations success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(f, ctx); } if (!fmpz_mpoly_equal_fmpz(f, fe, ctx)) { printf("FAIL\n"); flint_printf("Check repeated evalone matches evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpz_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpz_mpoly_clear(f, ctx); fmpz_clear(fe); flint_free(perm); } /* Check multiprecision repeated evalone matches evalall */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_t fe; fmpz ** vals; slong * perm; slong nvars, len1; flint_bitcnt_t exp_bits, coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); fmpz_init(fe); perm = (slong *) flint_malloc(nvars*sizeof(slong)); len1 = n_randint(state, 50); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200) + 1; vals = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); for (v = 0; v < nvars; v++) { /* only evaluate at 0, 1, or -1 */ vals[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals[v]); fmpz_set_si(vals[v], n_randint(state, UWORD(3)) - WORD(1)); perm[v] = v; } for (j = 0; j < 2*nvars; j++) { slong a, b, c; a = n_randint(state, nvars); b = n_randint(state, nvars); c = perm[a]; perm[a] = perm[b]; perm[b] = c; } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx); if (!fmpz_mpoly_evaluate_all_fmpz(fe, f, vals, ctx)) { printf("FAIL\n"); flint_printf("Check evaluations success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } for (v = 0; v < nvars; v++) { if (!fmpz_mpoly_evaluate_one_fmpz(f, f, perm[v], vals[perm[v]], ctx)) { printf("FAIL\n"); flint_printf("Check evaluations success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(f, ctx); } if (!fmpz_mpoly_equal_fmpz(f, fe, ctx)) { printf("FAIL\n"); flint_printf("Check multiprecision repeated evalone matches evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpz_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpz_mpoly_clear(f, ctx); fmpz_clear(fe); flint_free(perm); } /* Check addition commutes with evalall */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, fg; fmpz_t fe, ge, fge, t; fmpz ** vals; slong nvars, len1, len2, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(fg, ctx); fmpz_init(fe); fmpz_init(ge); fmpz_init(fge); fmpz_init(t); len1 = n_randint(state, 500); len2 = n_randint(state, 500); n = FLINT_MAX(WORD(1), nvars); exp_bound1 = n_randint(state, 5000/n/n) + 1; exp_bound2 = n_randint(state, 5000/n/n) + 1; coeff_bits = n_randint(state, 100); vals = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); for (v = 0; v < nvars; v++) { vals[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals[v]); fmpz_randbits(vals[v], state, 10); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_add(fg, f, g, ctx); if (!fmpz_mpoly_evaluate_all_fmpz(fe, f, vals, ctx) || !fmpz_mpoly_evaluate_all_fmpz(ge, g, vals, ctx) || !fmpz_mpoly_evaluate_all_fmpz(fge, fg, vals, ctx)) { printf("FAIL\n"); flint_printf("Check evaluations success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_add(t, fe, ge); if (!fmpz_equal(t, fge)) { printf("FAIL\n"); flint_printf("Check addition commutes with evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpz_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(fg, ctx); fmpz_clear(fe); fmpz_clear(ge); fmpz_clear(fge); fmpz_clear(t); } /* Check multiplication commutes with evalall */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, fg; fmpz_t fe, ge, fge, t; fmpz ** vals; slong nvars, len1, len2, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(fg, ctx); fmpz_init(fe); fmpz_init(ge); fmpz_init(fge); fmpz_init(t); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), nvars); exp_bound1 = n_randint(state, 1000/n/n) + 1; exp_bound2 = n_randint(state, 1000/n/n) + 1; coeff_bits = n_randint(state, 100); vals = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); for (v = 0; v < nvars; v++) { vals[v] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(vals[v]); fmpz_randbits(vals[v], state, 10); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_mul_johnson(fg, f, g, ctx); if (!fmpz_mpoly_evaluate_all_fmpz(fe, f, vals, ctx) || !fmpz_mpoly_evaluate_all_fmpz(ge, g, vals, ctx) || !fmpz_mpoly_evaluate_all_fmpz(fge, fg, vals, ctx)) { printf("FAIL\n"); flint_printf("Check evaluations success\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mul(t, fe, ge); if (!fmpz_equal(t, fge)) { printf("FAIL\n"); flint_printf("Check multiplication commutes with evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fmpz_clear(vals[v]); flint_free(vals[v]); } flint_free(vals); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(fg, ctx); fmpz_clear(fe); fmpz_clear(ge); fmpz_clear(fge); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-gcd.c000066400000000000000000000701561461254215100177500ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = fmpz_mpoly_gcd(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { printf("FAIL\n"); flint_printf("Check divisor of gcd\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { printf("FAIL\n"); flint_printf("Check gcd has positive lc\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if ((i + j % 11) == 0) { fmpz_mpoly_set(cg, b, ctx); fmpz_mpoly_gcd(cg, cg, a, ctx); if (!fmpz_mpoly_equal(cg, g, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing 1\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if ((i + j % 9) == 0) { fmpz_mpoly_set(cg, b, ctx); fmpz_mpoly_gcd(cg, a, cg, ctx); if (!fmpz_mpoly_equal(cg, g, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing 2\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check divisibility\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpz_mpoly_gcd(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mpoly_gcd, state) { const slong max_threads = 5; slong i, j, k, tmul = 10; for (i = 3; i <= 8; i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b, t; fmpz_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_one(g, ctx); fmpz_mpoly_one(a, ctx); fmpz_mpoly_one(b, ctx); for (j = 0; j < i; j++) { fmpz_mpoly_gen(t, j, ctx); fmpz_mpoly_add_ui(t, t, 1, ctx); fmpz_mpoly_mul(g, g, t, ctx); fmpz_mpoly_gen(t, j, ctx); fmpz_mpoly_sub_ui(t, t, 2, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_gen(t, j, ctx); fmpz_mpoly_add_ui(t, t, 2, ctx); fmpz_mpoly_mul(b, b, t, ctx); } fmpz_mpoly_sub_ui(g, g, 2, ctx); fmpz_mpoly_add_ui(a, a, 2, ctx); fmpz_mpoly_sub_ui(b, b, 2, ctx); fmpz_mpoly_mul(a, a, g, ctx); fmpz_mpoly_mul(b, b, g, ctx); fmpz_mpoly_set(t, g, ctx); gcd_check(g, a, b, t, ctx, i, 0, "dense examples"); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b, t; const char * vars[] = {"t" ,"x", "y", "z"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, 0, 0, "example"); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } { int success; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b; const char * vars[] = {"x" ,"y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_set_str_pretty(a, "x^3 + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "x^9999999999999999999999 + x^3333333333333333333333 + x", vars, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); success = fmpz_mpoly_gcd(g, a, b, ctx); if (success) { printf("FAIL\n"); flint_printf("Check non-example\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b, t; const char * vars[] = {"x" ,"y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_set_str_pretty(a, "(1 + x)^1*(2 + y)^1*(1 + z)^2", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(2 + x)^1*(1 + y)^1*(1 - z)^2", vars, ctx); fmpz_mpoly_set_str_pretty(t, "(1 - x)^1*(2 - y)^1*(1 - z)^2", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, 0, 0, "total dense example"); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bits(t, state, 1, coeff_bits + 1, exp_bits, ctx); } while (t->length != 1); fmpz_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(b, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "monomial"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t1, t2; slong len, len1; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bits(t1, state, 1, coeff_bits + 1, exp_bits1, ctx); } while (t1->length != 1); do { fmpz_mpoly_randtest_bits(t2, state, 1, coeff_bits + 1, exp_bits2, ctx); } while (t2->length != 1); fmpz_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul(b, a, t1, ctx); fmpz_mpoly_mul(t2, a, t2, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, t2, b, a, ctx, i, j, "monomial cofactors"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t c; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(c); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(t1, state, len1, coeff_bits + 1, exp_bound1, ctx); fmpz_mpoly_randtest_bound(t2, state, len2, coeff_bits + 1, exp_bound2, ctx); fmpz_mpoly_mul(b, t1, t2, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpz_mpoly_scalar_mul_fmpz(a, t2, c, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpz_mpoly_scalar_mul_fmpz(b, b, c, ctx); fmpz_mpoly_randtest_bound(g, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); if ((j%2) == 0) fmpz_mpoly_swap(a, b, ctx); gcd_check(g, a, b, t2, ctx, i, j, "one input divides the other"); } fmpz_clear(c); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 30/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "sparse inputs"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t coeff_bits, newbits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 30/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(b, b, newbits, ctx); } fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "sparse input with repacking"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 30/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpz_mpoly_inflate(a, a, shifts1, strides, ctx); fmpz_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpz_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mpoly_ctx_init_rand(ctx, state, 4); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); } bits4 = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); coeff_bits2 = n_randint(state, 200); coeff_bits3 = n_randint(state, 200); coeff_bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpz_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "dense input"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t newbits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mpoly_ctx_init_rand(ctx, state, 4); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); } bits4 = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); coeff_bits2 = n_randint(state, 200); coeff_bits3 = n_randint(state, 200); coeff_bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpz_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(b, b, newbits, ctx); } fmpz_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "dense input with repacking"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mpoly_ctx_init_rand(ctx, state, 4); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); } bits4 = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); coeff_bits2 = n_randint(state, 200); coeff_bits3 = n_randint(state, 200); coeff_bits4 = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpz_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpz_mpoly_inflate(a, a, shifts1, strides, ctx); fmpz_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpz_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mpoly/test/t-gcd_brown.c000066400000000000000000000117661461254215100211610ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_brown void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = fmpz_mpoly_gcd_brown(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { printf("FAIL\n"); flint_printf("Check gcd has positive lc\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check divisibility\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpz_mpoly_gcd_brown(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mpoly_gcd_brown, state) { slong tmul = 10; slong i, j; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b; const char * vars[] = {"x", "y", "z"}; fmpz_mpoly_ctx_init(ctx, 3, ORD_LEX); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_set_str_pretty(a, "(x+y+z^2)*(x-y^9+z^3)", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(x+y+z^2)*(x^9+y+z^2)", vars, ctx); gcd_check(g, a, b, ctx, 0, 0, "example"); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); len = n_randint(state, 40) + 1; len1 = n_randint(state, 80); len2 = n_randint(state, 80); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); degbound = 1 + 50/n/n; coeff_bits = n_randint(state, 300); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bound(g, state, len, coeff_bits + 1, degbound, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, g, ctx); fmpz_mpoly_mul(b, b, g, ctx); fmpz_mpoly_scalar_mul_ui(a, a, n_randint(state, 10) + 1, ctx); fmpz_mpoly_scalar_mul_ui(b, b, n_randint(state, 10) + 1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, ctx, i, j, "random dense"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mpoly/test/t-gcd_cofactors.c000066400000000000000000001052471461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_cofactors void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t abar, fmpz_mpoly_t bbar, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpz_mpoly_t ca, cb, cg, u, v, w; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_init(v, ctx); fmpz_mpoly_init(w, ctx); res = fmpz_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_assert_canonical(abar, ctx); fmpz_mpoly_assert_canonical(bbar, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { printf("FAIL\n"); flint_printf("Check divisor of gcd\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } fmpz_mpoly_mul(ca, g, abar, ctx); fmpz_mpoly_mul(cb, g, bbar, ctx); if (!fmpz_mpoly_equal(ca, a, ctx) || !fmpz_mpoly_equal(cb, b, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { printf("FAIL\n"); flint_printf("Check gcd has positive lc\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(u, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, a, u, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(v, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, a, v, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(w, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, a, w, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(u, a, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, u, b, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(v, a, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, v, b, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(w, a, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, w, b, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(u, a, ctx); fmpz_mpoly_set(v, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, u, v, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(v, a, ctx); fmpz_mpoly_set(u, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, v, u, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(u, a, ctx); fmpz_mpoly_set(w, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, u, w, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(w, a, ctx); fmpz_mpoly_set(u, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, w, u, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(v, a, ctx); fmpz_mpoly_set(w, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, v, w, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_set(w, a, ctx); fmpz_mpoly_set(v, b, ctx); fmpz_mpoly_gcd_cofactors(u, v, w, w, v, ctx); if (!fmpz_mpoly_equal(g, u, ctx) || !fmpz_mpoly_equal(abar, v, ctx) || !fmpz_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpz_mpoly_gcd_cofactors(cg, ca, cb, abar, bbar, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(ca, abar, ctx) || !fmpz_mpoly_equal(cb, bbar, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors of cofactors\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpz_mpoly_gcd_cofactors(cg, abar, bbar, abar, bbar, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!fmpz_mpoly_equal(ca, abar, ctx) || !fmpz_mpoly_equal(cb, bbar, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors of cofactors with aliasing\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); fmpz_mpoly_clear(u, ctx); fmpz_mpoly_clear(v, ctx); fmpz_mpoly_clear(w, ctx); } TEST_FUNCTION_START(fmpz_mpoly_gcd_cofactors, state) { const slong max_threads = 5; slong i, j, k, tmul = 2; for (i = 3; i <= 0*7; i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, abar, bbar, a, b, t; fmpz_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_one(g, ctx); fmpz_mpoly_one(a, ctx); fmpz_mpoly_one(b, ctx); for (j = 0; j < i; j++) { fmpz_mpoly_gen(t, j, ctx); fmpz_mpoly_add_ui(t, t, 1, ctx); fmpz_mpoly_mul(g, g, t, ctx); fmpz_mpoly_gen(t, j, ctx); fmpz_mpoly_sub_ui(t, t, 2, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_gen(t, j, ctx); fmpz_mpoly_add_ui(t, t, 2, ctx); fmpz_mpoly_mul(b, b, t, ctx); } fmpz_mpoly_sub_ui(g, g, 2, ctx); fmpz_mpoly_add_ui(a, a, 2, ctx); fmpz_mpoly_sub_ui(b, b, 2, ctx); fmpz_mpoly_mul(a, a, g, ctx); fmpz_mpoly_mul(b, b, g, ctx); fmpz_mpoly_set(t, g, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, 0, "dense examples"); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } if (0) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, abar, bbar, a, b, t; const char * vars[] = {"t" ,"x", "y", "z"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, 0, 0, "example"); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } { int success; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, abar, bbar, a, b; const char * vars[] = {"x" ,"y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_set_str_pretty(a, "x^3 + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "x^9999999999999999999999 + x^3333333333333333333333 + x", vars, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); success = fmpz_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); if (success) { flint_printf("FAIL\n"); flint_printf("Check non-example\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_ctx_clear(ctx); } { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, abar, bbar, a, b, t; const char * vars[] = {"x" ,"y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_set_str_pretty(a, "(1 + x)^1*(2 + y)^1*(1 + z)^2", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(2 + x)^1*(1 + y)^1*(1 - z)^2", vars, ctx); fmpz_mpoly_set_str_pretty(t, "(1 - x)^1*(2 - y)^1*(1 - z)^2", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, 0, 0, "total dense example"); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bits(t, state, 1, coeff_bits + 1, exp_bits, ctx); } while (t->length != 1); fmpz_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(b, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "monomial"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bits(t1, state, 1, coeff_bits + 1, exp_bits1, ctx); } while (t1->length != 1); do { fmpz_mpoly_randtest_bits(t2, state, 1, coeff_bits + 1, exp_bits2, ctx); } while (t2->length != 1); fmpz_mpoly_randtest_bits(a, state, len1, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul(b, a, t1, ctx); fmpz_mpoly_mul(t2, a, t2, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, t2, b, a, ctx, i, j, "monomial cofactors"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t c; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(c); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(t1, state, len1, coeff_bits + 1, exp_bound1, ctx); fmpz_mpoly_randtest_bound(t2, state, len2, coeff_bits + 1, exp_bound2, ctx); fmpz_mpoly_mul(b, t1, t2, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpz_mpoly_scalar_mul_fmpz(a, t2, c, ctx); fmpz_randtest(c, state, coeff_bits + 1); fmpz_mpoly_scalar_mul_fmpz(b, b, c, ctx); fmpz_mpoly_randtest_bound(g, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); if ((j%2) == 0) fmpz_mpoly_swap(a, b, ctx); gcd_check(g, abar, bbar, a, b, t2, ctx, i, j, "one input divides the other"); } fmpz_clear(c); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse inputs"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t coeff_bits, newbits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(b, b, newbits, ctx); } fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with repacking"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t; flint_bitcnt_t coeff_bits; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpz_mpoly_inflate(a, a, shifts1, strides, ctx); fmpz_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpz_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mpoly_ctx_init_rand(ctx, state, 4); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); coeff_bits2 = n_randint(state, 100); coeff_bits3 = n_randint(state, 100); coeff_bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpz_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mpoly_ctx_init_rand(ctx, state, 4); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); coeff_bits2 = n_randint(state, 100); coeff_bits3 = n_randint(state, 100); coeff_bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpz_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(b, b, newbits, ctx); } fmpz_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with repacking"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; flint_bitcnt_t coeff_bits1, coeff_bits2, coeff_bits3, coeff_bits4; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fmpz_mpoly_ctx_init_rand(ctx, state, 4); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); coeff_bits1 = n_randint(state, 100); coeff_bits2 = n_randint(state, 100); coeff_bits3 = n_randint(state, 100); coeff_bits4 = n_randint(state, 100); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bounds(t, state, len1, coeff_bits1 + 1, degbounds1, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bounds(a, state, len2, coeff_bits2, degbounds2, ctx); fmpz_mpoly_randtest_bounds(b, state, len3, coeff_bits3, degbounds3, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len4, coeff_bits4, bits4, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpz_mpoly_inflate(a, a, shifts1, strides, ctx); fmpz_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fmpz_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mpoly/test/t-gcd_hensel.c000066400000000000000000000131001461254215100212700ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_hensel void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, fmpz_mpoly_t t, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); if (!fmpz_mpoly_gcd_hensel(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(g, ctx); if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: check gcd is unit normal\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(t, ctx) && !fmpz_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_divides(ca, a, g, ctx) || !fmpz_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_gcd_hensel(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(cg, ctx); if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mpoly_gcd_hensel, state) { slong i, j, tmul = 20; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t1, t2, t3; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); fmpz_mpoly_init(t3, ctx); degbound = 42/(2*ctx->minfo->nvars - 1); degbounds = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); degbounds1 = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); degbounds2 = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 6; j++) { len = n_randint(state, 10) + 1; len1 = n_randint(state, 10); len2 = n_randint(state, 15); coeff_bits = n_randint(state, 200) + 10; fmpz_mpoly_randtest_bounds(t1, state, coeff_bits, len, degbounds, ctx); coeff_bits = n_randint(state, 200) + 10; fmpz_mpoly_randtest_bounds(t2, state, coeff_bits, len1, degbounds1, ctx); coeff_bits = n_randint(state, 200) + 10; fmpz_mpoly_randtest_bounds(t3, state, coeff_bits, len2, degbounds2, ctx); switch (n_randint(state, 4)) { case 3: fmpz_mpoly_mul(t3, t1, t2, ctx); break; case 2: fmpz_mpoly_mul(t3, t3, t1, ctx); break; case 1: fmpz_mpoly_mul(t3, t3, t2, ctx); break; default: break; } fmpz_mpoly_mul(a, t1, t3, ctx); fmpz_mpoly_mul(b, t2, t3, ctx); coeff_bits = n_randint(state, 300) + 10; fmpz_mpoly_randtest_bits(g, state, coeff_bits, len, FLINT_BITS, ctx); if (a->length < 4000 && b->length < 4000) gcd_check(g, a, b, t3, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_clear(t3, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mpoly/test/t-gcd_subresultant.c000066400000000000000000000130261461254215100225540ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_subresultant void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, fmpz_mpoly_t t, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); if (!fmpz_mpoly_gcd_subresultant(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(g, ctx); if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: check gcd is unit normal\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(t, ctx) && !fmpz_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_divides(ca, a, g, ctx) || !fmpz_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_gcd_subresultant(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fmpz_mpoly_assert_canonical(cg, ctx); if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mpoly_gcd_subresultant, state) { slong i, j; slong tmul = 10; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b, t; const char * vars[] = {"x", "y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, 0, 0, "example"); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 3); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 1 + 10/FLINT_MAX(WORD(1), ctx->minfo->nvars); for (j = 0; j < 4; j++) { coeff_bits = 1 + n_randint(state, 80); fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, degbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); coeff_bits = 1 + n_randint(state, 80); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); coeff_bits = 1 + n_randint(state, 80); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); coeff_bits = 1 + n_randint(state, 80); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random small"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mpoly/test/t-gcd_zippel.c000066400000000000000000000233061461254215100213260ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_gcd_zippel, state) { slong i, j; /* examples from Zippel's 1979 paper */ if (1) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t r, d, f, g; int success; const char* vars[] = {"x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"}; const char * example[][3] = {{ "x1^2 + x1 + 3", "2*x1^2 + 2*x1 + 1", "x1^2 + 2*x1 + 2" }, { "2*x1^2*x2^2 + x1*x2 + 2*x1", "x2^2 + 2*x1^2*x2 + x1^2 + 1", "x1^2*x2^2 + x1^2*x2 + x1*x2 + x1^2 + x1" }, { "x2^2*x3^2 + x2^2*x3 + 2*x1^2*x2*x3 + x1*x3", "x3^2 + x2^2*x3 + x1^2*x2*x3 + x1*x3 + x1^2*x2^2", "x2*x3 + 2*x1*x3 + x3 + x1" }, { "x1^2*x4^2 + x2^2*x3*x4 + x1^2*x2*x4 + x2*x4 + x1^2*x2*x3", "x1*x2*x3^2*x4^2 + x1*x3^2*x4^2 + x1*x4^2 + x4^2 + x1*x3*x4", "x1*x3^2*x4^2 + x3^2*x4^2 + x4^2 + x1*x2^2*x3*x4 + x1*x2^2" }, { "x1^3*x2^2*x3^2*x4*x5^2 + x1*x2^2*x5^2 + x1^3*x3*x4^2*x5" " + x1^3*x2*x3^2*x4*x5 + x1^2*x2*x3^2*x4^2" , "x1*x2^2*x5^2 + x1*x2*x3^2*x4*x5 + x1*x2*x3^2*x4^2" " + x1*x2^2*x4^2 + 1" , "x1*x3^2*x4*x5^2 + x2*x5^2 + x1*x2*x4*x5 + x2*x5 + x1*x2*x3*x4^2" }, { "x1*x2*x4^2*x5^2*x6^2 + x1*x2^2*x3^2*x4*x5^2*x6^2 + x1^2*x3*x6^2" " + x1^2*x2*x3^2*x4*x5^2*x6 + x1^2*x3*x5*x6" , "x1^2*x2*x4*x5^2*x6^2 + x1*x3*x5^2*x6^2 + x1*x2^2*x6^2" " + x1^2*x2^2*x3^2*x5*x6 + x1*x3^2*x4*x5" , "x2^2*x3^2*x4*x5^2*x6 + x1*x4^2*x5*x6 + x2^2*x3^2*x4*x5*x6" " + x1*x2^2*x3*x4^2*x6 + x1^2*x3*x5^2" }, { "x1*x2^2*x4^2*x6^2*x7^2 + x1^2*x3*x4*x6^2*x7^2 + x3^2*x4^2*x7^2" " + x1^2*x2*x4^2*x6 + x3*x4*x5^2" , "x1^2*x2*x4^2*x5*x6^2*x7^2 + x1*x2*x3*x6*x7 + x3*x4^2*x5^2*x7" " + x1*x4^2*x5^2*x7 + x1^2*x2*x3*x4^2+x5*x6" , "x1*x3*x5*x6^2*x7^2 + x2^2*x3^2*x4^2*x5*x6*x7^2 + x4*x6*x7^2" " + x1^2*x2*x3*x5*x6*x7 + x1^2*x3^2*x4*x5^2" }, { "x2^2*x4*x5*x6*x7*x8^2 + x1^2*x2*x3^2*x4^2*x6^2*x7^2*x8" " + x1^2*x3*x4^2*x6^2*x7^2 + x1^2*x2^2*x3^2*x4*x5^2*x6*x7^2" " + x2^2*x4*x6" , "x1^2*x2^2*x3*x4^2*x5*x6^2*x8^2 + x2*x5*x6^2*x8^2" " + x1^2*x2^2*x3^2*x4^2*x6^2*x7^2*x8 + x1^2*x3^2*x4*x5^2*x7^2*x8" " + x1*x2^2*x3^2*x5^2*x7" , "x1*x4^2*x5*x6*x7*x8^2 + x1*x2^2*x4^2*x5^2*x6^2*x8" " + x1^2*x2*x3*x4^2*x6^2*x8 + x1^2*x2^2*x3^2*x4*x5^2*x8" " + x1*x2*x4^2*x5^2" }, { "x1^2*x3^3*x4*x6*x8*x9^2 + x1*x2*x3*x4^2*x5^2*x8*x9" " + x2*x3*x4*x5^2*x8*x9 + x1*x3^3*x4^2*x5^2*x6^2*x7*x8^2" " + x2*x3*x4*x5^2*x6*x7*x8^2" , "x1^2*x2^2*x3*x7^2*x8*x9 + x2^2*x9 + x1^2*x3*x4^2*x5^2*x6*x7^2" " + x4^2*x5^2*x7^2 + x3*x4^2*x6*x7" , "x1^2*x2*x4*x5*x6*x7^2*x8^2*x9^2 + x1^2*x2*x3*x5*x6^2*x7^2*x8*x9^2" " + x1^2*x3*x4*x6*x7^2*x8*x9 + x1^2*x2^2*x6*x8^2" " + x2^2*x4*x5*x6^2*x7" }, { "x1*x2^2*x4^2*x8*x9^2*x10^2 + x2^2*x4*x5^2*x6*x7*x9*x10^2" " + x1^2*x2*x3*x5^2*x7^2*x9^2 + x1*x3^2*x4^2*x7^2*x9^2" " + x1^2*x3*x4*x7^2*x8^2" , "x1*x2*x3^2*x4*x6*x7*x8*x9^2*x10^2 + x2^2*x3^2*x4^2*x6^2*x9*x10^2" " + x1*x2^2*x3^2*x4*x5*x6*x7*x8^2*x9^2*x10" " + x1^2*x2*x4^2*x5^2*x8^2*x9^2*x10 + x3*x4^2*x5*x6*x7^2*x9*x10" , "x1*x2^2*x3^2*x5^2*x6^2*x7*x8*x9^2*x10^2 + x3*x8*x9^2*x10^2" " + x1*x2^2*x3*x4*x5^2*x6^2*x8^2*x9*x10 + x1*x3*x6*x7*x8*x10" " + x4^2*x5^2*x6^2*x7*x9^2" }}; for (i = 1; i <= 10; i++) { fmpz_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX); fmpz_mpoly_init(r, ctx); fmpz_mpoly_init(d, ctx); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_set_str_pretty(d, example[i - 1][0], vars, ctx); fmpz_mpoly_set_str_pretty(f, example[i - 1][1], vars, ctx); fmpz_mpoly_set_str_pretty(g, example[i - 1][2], vars, ctx); fmpz_mpoly_mul_johnson(f, f, d, ctx); fmpz_mpoly_mul_johnson(g, g, d, ctx); success = fmpz_mpoly_gcd_zippel(r, f, g, ctx); if (!success || !fmpz_mpoly_equal(r, d, ctx)) { flint_printf("FAIL\ncheck example %wd\n",i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(r, ctx); fmpz_mpoly_clear(d, ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } } for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, ca, cb, cg, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; ulong degbound; ulong * degbounds; int res; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 15); len2 = n_randint(state, 15); degbound = 100/(2*ctx->minfo->nvars - 1); degbounds = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) degbounds[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bounds(t, state, len, coeff_bits + 1, degbounds, ctx); } while (t->length == 0); fmpz_mpoly_randtest_bounds(a, state, len1, coeff_bits, degbounds, ctx); fmpz_mpoly_randtest_bounds(b, state, len2, coeff_bits, degbounds, ctx); fmpz_mpoly_mul_johnson(a, a, t, ctx); fmpz_mpoly_mul_johnson(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); res = fmpz_mpoly_gcd_zippel(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check that gcd could be computed\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } continue; } if (fmpz_sgn(g->coeffs + 0) <= 0) { printf("FAIL\n"); flint_printf("Check gcd has positive lc\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides_monagan_pearce(ca, a, g, ctx); res = res && fmpz_mpoly_divides_monagan_pearce(cb, b, g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check divisibility\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } res = fmpz_mpoly_gcd_zippel(cg, ca, cb, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check that cofactor gcd could be computed\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal_ui(cg, UWORD(1), ctx)) { printf("FAIL\n"); flint_printf("Check cofactors are relatively prime\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(degbounds); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-gcd_zippel2.c000066400000000000000000000210001461254215100213750ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_subresultant.c, t-gcd_zippel2.c */ #define gcd_check gcd_check_gcd_zippel2 void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = fmpz_mpoly_gcd_zippel2(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fmpz_mpoly_gcd_zippel2(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fmpz_mpoly_gcd_zippel2, state) { slong i, j, tmul = 20; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b, t; const char* vars[] = {"y", "t", "x", "z"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_set_str_pretty(t, "x+y+z+t", vars, ctx); fmpz_mpoly_set_str_pretty(a, "x^2+y^2+z^2+t^2", vars, ctx); fmpz_mpoly_set_str_pretty(b, "x^3+y^3+z^3+t^3", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 0, "example"); fmpz_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 0, "example"); fmpz_mpoly_set_str_pretty(t, "y + t^2 + x^3 + z^4", vars, ctx); fmpz_mpoly_set_str_pretty(a, "y*t + 1 + (x - z^5)*(y + t)", vars, ctx); fmpz_mpoly_set_str_pretty(b, "y*t + 1 + (x - z^5)*(y - t + x)", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 1, "trigger unlucky ksub"); fmpz_mpoly_set_str_pretty(t, "y + 33857*t^2 + 35153*x^3 + 40433*z^4", vars, ctx); fmpz_mpoly_set_str_pretty(a, "y^4 + t^3 + x^2 + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "y^3 + t^4 + x^2 + z", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 2, "trigger zipple no match"); fmpz_mpoly_set_str_pretty(t, "y + t + x^3 + z^3", vars, ctx); fmpz_mpoly_set_str_pretty(a, "(x - z^4)*y + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(x + z)*y + t", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 3, "trigger ksub lc kill"); fmpz_mpoly_set_str_pretty(t, "y + t + x^3 + z^3", vars, ctx); fmpz_mpoly_set_str_pretty(a, "(x - z^4 + 33857*(x*z))*y + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(x + z)*y + t", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 4, "trigger ksub lc kill mod p"); fmpz_mpoly_set_str_pretty(t, "(1 + x^10)*t*y + t + x + z", vars, ctx); fmpz_mpoly_set_str_pretty(a, "(1 + x + t)*(x - 33857*x^2 + 35153*z^4)*y*t + z + x*y", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(2*x - t^2)*(x - 33857*x^2 + 35153*z^4)*y^2*t + t*z + y", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 5, "trigger gcd lc terms vanish mod p"); if (FLINT_BITS == 64) { fmpz_mpoly_set_str_pretty(t, "t*y + t + x^9999999999 + z^9999999999", vars, ctx); fmpz_mpoly_set_str_pretty(a, "t + y + x^9999999999", vars, ctx); fmpz_mpoly_set_str_pretty(b, "t^2 + t*z^9999999999 + y + 1", vars, ctx); } else { fmpz_mpoly_set_str_pretty(t, "t*y + t + x^999999 + z^9999999", vars, ctx); fmpz_mpoly_set_str_pretty(a, "t + y + x^999999", vars, ctx); fmpz_mpoly_set_str_pretty(b, "t^2 + t*z^999999 + y + 1", vars, ctx); } fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 6, "trigger big p"); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 20); if (ctx->minfo->nvars < 3) { fmpz_mpoly_ctx_clear(ctx); continue; } fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 35) + 1; len1 = n_randint(state, 35) + 1; len2 = n_randint(state, 35) + 1; degbound = 2 + 100/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse"); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fmpz_mpoly/test/t-gen.c000066400000000000000000000046631461254215100177640ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_gen, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f1, f2; slong nvars, len, coeff_bits, exp_bits, k1, k2; nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpz_mpoly_init(f1, ctx); fmpz_mpoly_init(f2, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f1, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(f2, state, len, coeff_bits, exp_bits, ctx); k1 = n_randint(state, nvars); k2 = n_randint(state, nvars); fmpz_mpoly_gen(f1, k1, ctx); fmpz_mpoly_assert_canonical(f1, ctx); fmpz_mpoly_gen(f2, k2, ctx); fmpz_mpoly_assert_canonical(f2, ctx); result = 1; result = result && fmpz_mpoly_is_gen(f1, k1, ctx); result = result && fmpz_mpoly_is_gen(f1, -WORD(1), ctx); result = result && fmpz_mpoly_is_gen(f2, k2, ctx); result = result && fmpz_mpoly_is_gen(f2, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check one generator\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_mul_johnson(f1, f1, f2, ctx); result = 1; result = result && !fmpz_mpoly_is_gen(f1, k1, ctx); result = result && !fmpz_mpoly_is_gen(f1, k2, ctx); result = result && !fmpz_mpoly_is_gen(f1, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check product of two generators\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f1, ctx); fmpz_mpoly_clear(f2, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000121611461254215100226540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_coeff_vars_ui, state) { slong i, j1, j2; /* check simple example */ { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; /* get the coefficient of y^1*x^2*/ slong varl[2] = {1, 0}; ulong expl[2] = {1, 2}; const char * vars[] = {"x", "y", "z", "w"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_DEGREVLEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_set_str_pretty(f, "x^2*y*(z+w)+x+y+x*y^2+z^2+w^2", vars, ctx); fmpz_mpoly_set_str_pretty(g, "z+w", vars, ctx); fmpz_mpoly_get_coeff_vars_ui(f, f, varl, expl, 2, ctx); if (!fmpz_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\ncheck simple example\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } /* check 1 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, m; slong nvars, len; ulong exp_bound; flint_bitcnt_t coeff_bits; slong vars[1]; ulong exps[1]; slong var1; nvars = 1 + n_randint(state, 20); fmpz_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 20) + 1; coeff_bits = n_randint(state, 100); fmpz_mpoly_randtest_bound(f, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars); fmpz_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { vars[0] = var1; exps[0] = j1; fmpz_mpoly_get_coeff_vars_ui(g, f, vars, exps, 1, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_gen(m, var1, ctx); fmpz_mpoly_pow_ui(m, m, j1, ctx); fmpz_mpoly_mul(g, g, m, ctx); fmpz_mpoly_add(h, h, g, ctx); } if (!fmpz_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n" "check 1 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_ctx_clear(ctx); } /* check 2 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, m; slong nvars, len; ulong exp_bound; flint_bitcnt_t coeff_bits; slong vars[2]; ulong exps[2]; slong var1, var2; nvars = 2 + n_randint(state, 20); fmpz_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 12) + 1; coeff_bits = n_randint(state, 100); fmpz_mpoly_randtest_bound(f, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars - 1); var2 = 1 + var1 + n_randint(state, nvars - 1 - var1); fmpz_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { for (j2 = 0; j2 < exp_bound; j2++) { vars[0] = var1; exps[0] = j1; vars[1] = var2; exps[1] = j2; fmpz_mpoly_get_coeff_vars_ui(g, f, vars, exps, 2, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_gen(m, var1, ctx); fmpz_mpoly_pow_ui(m, m, j1, ctx); fmpz_mpoly_mul(g, g, m, ctx); fmpz_mpoly_gen(m, var2, ctx); fmpz_mpoly_pow_ui(m, m, j2, ctx); fmpz_mpoly_mul(g, g, m, ctx); fmpz_mpoly_add(h, h, g, ctx); } } if (!fmpz_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n" "check 2 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_coeff.c000066400000000000000000000073621461254215100220060ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_coeff, state) { int i, j, k, result; /* Check _fmpz_fmpz */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; flint_bitcnt_t coeff_bits, exp_bits, exp_bits2; slong len; fmpz_t c, d; fmpz_init(c); fmpz_init(d); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); len = n_randint(state, 100); coeff_bits = n_randint(state, 200); exp_bits = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 10; j++) { fmpz ** exp = (fmpz **) flint_malloc(ctx->minfo->nvars*sizeof(fmpz*)); fmpz_randtest_unsigned(c, state, 200); for (k = 0; k < fmpz_mpoly_ctx_nvars(ctx); k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_randtest_unsigned(exp[k], state, exp_bits2); } fmpz_mpoly_set_coeff_fmpz_fmpz(f, c, exp, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_get_coeff_fmpz_fmpz(d, f, exp, ctx); result = fmpz_equal(c, d); if (!result) { printf("FAIL\n"); flint_printf("Check _fmpz_fmpz\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } for (k = 0; k < fmpz_mpoly_ctx_nvars(ctx); k++) { fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp); } fmpz_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_ctx_clear(ctx); } /* Check _fmpz_ui */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; flint_bitcnt_t coeff_bits, exp_bits; slong len; fmpz_t c, d; fmpz_init(c); fmpz_init(d); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); len = n_randint(state, 100); coeff_bits = n_randint(state, 200); exp_bits = n_randint(state, 200) + 2; fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 10; j++) { ulong * exp = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); fmpz_randtest_unsigned(c, state, 200); for (k = 0; k < fmpz_mpoly_ctx_nvars(ctx); k++) exp[k] = n_randtest(state); fmpz_mpoly_set_coeff_fmpz_ui(f, c, exp, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_get_coeff_fmpz_ui(d, f, exp, ctx); result = fmpz_equal(c, d); if (!result) { printf("FAIL\n"); flint_printf("Check _fmpz_ui\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } flint_free(exp); } fmpz_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_coeff_fmpz_monomial.c000066400000000000000000000073371461254215100247370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_coeff_fmpz_monomial, state) { slong i, j, k; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, m; fmpz ** exp; fmpz_t cm, ce, q; slong len; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(m, ctx); fmpz_init(cm); fmpz_init(ce); fmpz_init(q); fmpz_one(q); /* anything nonzero is ok */ len = n_randint(state, 100); exp_bits = n_randint(state, FLINT_BITS + 10) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); /* check a random monomial - this also randomizes m->bits */ exp = (fmpz **) flint_malloc(ctx->minfo->nvars*sizeof(fmpz *)); for (k = 0; k < ctx->minfo->nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_randtest_unsigned(exp[k], state, exp_bits1); } fmpz_mpoly_zero(m, ctx); fmpz_mpoly_set_coeff_fmpz_fmpz(m, q, exp, ctx); fmpz_mpoly_get_coeff_fmpz_monomial(cm, f, m, ctx); fmpz_mpoly_get_coeff_fmpz_fmpz(ce, f, exp, ctx); if (!fmpz_equal(cm, ce)) { flint_printf("FAIL\ncheck a random monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } /* check all coeffs in f */ for (j = 0; j < fmpz_mpoly_length(f, ctx); j++) { fmpz_mpoly_get_term_exp_fmpz(exp, f, j, ctx); fmpz_mpoly_zero(m, ctx); fmpz_mpoly_set_coeff_fmpz_fmpz(m, q, exp, ctx); fmpz_mpoly_get_coeff_fmpz_monomial(cm, f, m, ctx); fmpz_mpoly_get_coeff_fmpz_fmpz(ce, f, exp, ctx); if (!fmpz_equal(cm, ce)) { flint_printf("FAIL\ncheck all coeffs in f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } /* set random coeff and check */ for (j = 0; j < 10; j++) { for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits2); } fmpz_randtest(cm, state, coeff_bits); fmpz_mpoly_zero(m, ctx); fmpz_mpoly_set_coeff_fmpz_fmpz(m, q, exp, ctx); fmpz_mpoly_set_coeff_fmpz_monomial(f, cm, m, ctx); fmpz_mpoly_get_coeff_fmpz_monomial(ce, f, m, ctx); if (!fmpz_equal(cm, ce)) { flint_printf("FAIL\nset random coeff and check\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp); fmpz_clear(q); fmpz_clear(cm); fmpz_clear(ce); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_is_fmpz.c000066400000000000000000000042471461254215100223720ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_is_fmpz, state) { slong i; /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_t c, d; slong len; flint_bitcnt_t coeff_bits, exp_bits; fmpz_init(c); fmpz_init(d); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); len = n_randint(state, 10); exp_bits = n_randint(state, 200); coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); if (fmpz_mpoly_is_fmpz(f, ctx)) { fmpz_mpoly_get_fmpz(c, f, ctx); if (!fmpz_mpoly_equal_fmpz(f, c, ctx)) { printf("FAIL\n"); flint_printf("Check is_fmpz and get_fmpz catch constants\ni = %wd\n", i); fflush(stdout); flint_abort(); } } fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mpoly_set_fmpz(f, c, ctx); if (!fmpz_mpoly_is_fmpz(f, ctx)) { printf("FAIL\n"); flint_printf("Check set_fmpz makes is_fmpz true\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_get_fmpz(d, f, ctx); if (!fmpz_equal(c, d)) { printf("FAIL\n"); flint_printf("Check get_fmpz matches set_fmpz true\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_str_pretty.c000066400000000000000000000034371461254215100231420ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_str_pretty, state) { slong i; { slong len1, exp_bits, coeff_bits; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, f1; char * str; const char * vars[] = {"x","xy","y","yx","z","zz"}; /* check that parsing inverts printing */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(f1, ctx); for (len1 = 3; len1 < 1000; len1 += len1/2) { coeff_bits = 100; exp_bits = 100; fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx); str = fmpz_mpoly_get_str_pretty(f, vars, ctx); fmpz_mpoly_set_str_pretty(f1, str, vars, ctx); fmpz_mpoly_assert_canonical(f1, ctx); flint_free(str); if (!fmpz_mpoly_equal(f, f1, ctx)) { flint_printf("FAIL\n"); flint_printf("check that parsing inverts printing\ni = %wd, len1 = %wd\n", i ,len1); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(f1, ctx); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_term_coeff_fmpz.c000066400000000000000000000042731461254215100240670ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_term_coeff_fmpz, state) { slong i, j; /* Set coeff and get coeff and compare */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_t c, d; slong len, index; flint_bitcnt_t coeff_bits, exp_bits; fmpz_init(c); fmpz_init(d); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); if (f->length > 0) { for (j = 0; j < 10; j++) { fmpz_randtest(c, state, n_randint(state, 200)); index = n_randint(state, f->length); fmpz_mpoly_set_term_coeff_fmpz(f, index, c, ctx); fmpz_mpoly_get_term_coeff_fmpz(d, f, index, ctx); if (!fmpz_equal(c, d)) { printf("FAIL\n"); flint_printf("check get and set match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } if (!fmpz_equal(fmpz_mpoly_term_coeff_ref(f, index, ctx), d)) { printf("FAIL\n"); flint_printf("check reference match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpz_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000055421461254215100236010ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_term_exp_fmpz, state) { slong i, j, k; int result; /* check fmpz */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; slong nvars, len, index; flint_bitcnt_t coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); nvars = fmpz_mpoly_ctx_nvars(ctx); do { len = n_randint(state, 50); exp_bits = n_randint(state, 100) + 1; coeff_bits = n_randint(state, 100); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); } while (f->length == 0); for (j = 0; j < 10; j++) { fmpz ** exp1 = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); fmpz ** exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); for (k = 0; k < nvars; k++) { exp1[k] = (fmpz *) flint_malloc(sizeof(fmpz)); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp1[k]); fmpz_init(exp2[k]); fmpz_randtest_unsigned(exp1[k], state, 200); } index = n_randint(state, f->length); fmpz_mpoly_set_term_exp_fmpz(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpz_mpoly_get_term_exp_fmpz(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && fmpz_equal(exp1[k], exp2[k]); fmpz_clear(exp1[k]); fmpz_clear(exp2[k]); flint_free(exp1[k]); flint_free(exp2[k]); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000052641461254215100232410ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_term_exp_si, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; slong nvars, len, index; flint_bitcnt_t coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); nvars = fmpz_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 100) + 2; do { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); } while (fmpz_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { slong * exp1 = (slong *) flint_malloc(nvars*sizeof(slong)); slong * exp2 = (slong *) flint_malloc(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS - 1) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); fmpz_mpoly_set_term_exp_ui(f, index, (ulong *) exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpz_mpoly_get_term_exp_si(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fmpz_mpoly_get_term_var_exp_si(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000052471461254215100232440ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_set_term_exp_ui, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; slong nvars, len, index; flint_bitcnt_t coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); nvars = fmpz_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100) + 2; do { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); } while (fmpz_mpoly_length(f, ctx) == 0); for (j = 0; j < 10; j++) { ulong * exp1 = (ulong *) flint_malloc(nvars*sizeof(ulong)); ulong * exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); fmpz_mpoly_set_term_exp_ui(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fmpz_mpoly_get_term_exp_ui(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fmpz_mpoly_get_term_var_exp_ui(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_term.c000066400000000000000000000040011461254215100210030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_term, state) { int i, j; /* Check a polynomial is the sum of its terms */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len3, coeff_bits, exp_bits3, ctx); fmpz_mpoly_zero(h, ctx); for (j = fmpz_mpoly_length(f, ctx) - 1; j >= 0; j--) { fmpz_mpoly_get_term(g, f, j, ctx); fmpz_mpoly_add(h, h, g, ctx); } if (!fmpz_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\nCheck a polynomial is the sum of its terms\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-get_term_monomial.c000066400000000000000000000046721461254215100227140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_get_term_monomial, state) { int i, j; /* Check getting a coeff by its monomial */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t c, d; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; flint_bitcnt_t coeff_bits; slong len1, len2, len3; fmpz_init(c); fmpz_init(d); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len3, coeff_bits, exp_bits3, ctx); fmpz_mpoly_repack_bits(h, f, f->bits + n_randint(state, 2*FLINT_BITS), ctx); for (j = fmpz_mpoly_length(f, ctx) - 1; j >= 0; j--) { fmpz_mpoly_get_term_monomial(g, f, j, ctx); fmpz_mpoly_repack_bits(g, g, g->bits + n_randint(state, FLINT_BITS), ctx); fmpz_mpoly_get_term_coeff_fmpz(d, f, j, ctx); fmpz_mpoly_get_coeff_fmpz_monomial(c, h, g, ctx); if (!fmpz_equal(c, d)) { flint_printf("FAIL\nCheck getting a coeff by its monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } } fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-inflate_deflate.c000066400000000000000000000154251461254215100223170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_inflate_deflate, state) { int i, j, success; /* Check deflate undoes inflate */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { slong k; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz * strides, * shifts; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; flint_bitcnt_t coeff_bits, stride_bits, shift_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); len3 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bits3 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(strides + k); fmpz_init(shifts + k); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len3, coeff_bits, exp_bits3, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts + k, state, shift_bits); fmpz_randtest_not_zero(strides + k, state, stride_bits); fmpz_abs(strides + k, strides + k); } fmpz_mpoly_inflate(h, f, shifts, strides, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_deflate(g, h, shifts, strides, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!fmpz_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check deflate undoes inflate\n" "i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mpoly_set(h, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_inflate(h, h, shifts, strides, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_deflate(h, h, shifts, strides, ctx); fmpz_mpoly_assert_canonical(h, ctx); if (!fmpz_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check deflate undoes inflate with aliasing\n" "i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(strides + k); fmpz_clear(shifts + k); } flint_free(strides); flint_free(shifts); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check deflating by deflation leaves trivial deflation */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { slong k; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz * strides, * shifts; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; flint_bitcnt_t coeff_bits, stride_bits, shift_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); len3 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bits3 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); stride_bits = n_randint(state, 10) + 2; shift_bits = n_randint(state, 10) + 2; strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(strides + k); fmpz_init(shifts + k); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len3, coeff_bits, exp_bits3, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fmpz_mpoly_inflate(h, f, shifts, strides, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_deflation(shifts, strides, h, ctx); fmpz_mpoly_deflate(g, h, shifts, strides, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_deflation(shifts, strides, g, ctx); fmpz_mpoly_deflate(f, g, shifts, strides, ctx); fmpz_mpoly_assert_canonical(f, ctx); success = fmpz_mpoly_equal(f, g, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (!fmpz_is_zero(shifts + k)) success = 0; if (fmpz_cmp_ui(strides + k, UWORD(1)) > 0) success = 0; } if (!success) { printf("FAIL\n"); flint_printf("Check deflating by deflation leaves trivial deflation\n" "i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(strides + k); fmpz_clear(shifts + k); } flint_free(strides); flint_free(shifts); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-init.c000066400000000000000000000020671461254215100201520ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_init, state) { int i; /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_clear(f, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-mul.c000066400000000000000000000223231461254215100200010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_mul, state) { int i, j, result, max_threads = 5; slong tmul = 10; #ifdef _WIN32 tmul = 2; #endif /* check fixed cases */ for (i = 0; i < 1 + tmul; i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; const char * vars[] = {"x", "y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); /* should trigger dense */ fmpz_mpoly_set_str_pretty(f, "((1-x)*(1+y)*(1+z))^20", vars, ctx); fmpz_mpoly_set_str_pretty(g, "((1+x)*(1-y)*(1-z))^20", vars, ctx); fmpz_mpoly_set_str_pretty(k, "((1-x^2)*(1-y^2)*(1-z^2))^20", vars, ctx); fmpz_mpoly_mul(h, f, g, ctx); if (!fmpz_mpoly_equal(h, k, ctx)) { printf("FAIL\n"); flint_printf("Check fixed case 1\n"); fflush(stdout); flint_abort(); } /* should trigger array */ fmpz_mpoly_set_str_pretty(f, "(1+x+y+z+t)^20", vars, ctx); fmpz_mpoly_set_str_pretty(g, "(1-x-y-z-t)^20", vars, ctx); fmpz_mpoly_set_str_pretty(k, "((1+x+y+z+t)*(1-x-y-z-t))^20", vars, ctx); fmpz_mpoly_mul(h, f, g, ctx); if (!fmpz_mpoly_equal(h, k, ctx)) { printf("FAIL\n"); flint_printf("Check fixed case 2\n"); fflush(stdout); flint_abort(); } /* should trigger heap */ fmpz_mpoly_set_str_pretty(f, "(1+x^10)^50", vars, ctx); fmpz_mpoly_set_str_pretty(g, "(1+y^10)^50", vars, ctx); fmpz_mpoly_set_str_pretty(k, "((1+x^10)*(1+y^10))^50", vars, ctx); fmpz_mpoly_mul(h, f, g, ctx); if (!fmpz_mpoly_equal(h, k, ctx)) { printf("FAIL\n"); flint_printf("Check fixed case 3\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); } /* Check f*(g + h) = f*g + f*h */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); coeff_bits = n_randint(state, 200); for (j = 0; j < 2; j++) { exp_bits = n_randint(state, 100) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; fmpz_mpoly_randtest_bits(k1, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k2, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_add(t1, g, h, ctx); fmpz_mpoly_assert_canonical(t1, ctx); fmpz_mpoly_mul(k1, f, t1, ctx); fmpz_mpoly_assert_canonical(k1, ctx); fmpz_mpoly_mul(t1, f, g, ctx); fmpz_mpoly_assert_canonical(t1, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(t2, f, h, ctx); fmpz_mpoly_assert_canonical(t2, ctx); fmpz_mpoly_add(k2, t1, t2, ctx); fmpz_mpoly_assert_canonical(k2, ctx); result = fmpz_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*(g + h) = f*g + f*h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, n; flint_bitcnt_t coeff_bits, exp_bound, exp_bound1, exp_bound2; fmpz_mpoly_ctx_init_rand(ctx, state, 4); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); exp_bound = 3 + n_randint(state, 1 + 100/n/n); exp_bound1 = 3 + n_randint(state, 1 + 100/n/n); exp_bound2 = 3 + n_randint(state, 1 + 100/n/n); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, n) + 2; j >= 0; j--) { len *= exp_bound + 1; len1 *= exp_bound1 + 1; len2 *= exp_bound2 + 1; len = FLINT_MIN(len, WORD(1000)); len1 = FLINT_MIN(len, WORD(1000)); len2 = FLINT_MIN(len, WORD(1000)); } coeff_bits = n_randint(state, 200); for (j = 0; j < 2; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(f, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, n; flint_bitcnt_t coeff_bits, exp_bound, exp_bound1, exp_bound2; fmpz_mpoly_ctx_init_rand(ctx, state, 4); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); exp_bound = 3 + n_randint(state, 1 + 100/n/n); exp_bound1 = 3 + n_randint(state, 1 + 100/n/n); exp_bound2 = 3 + n_randint(state, 1 + 100/n/n); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, n) + 2; j >= 0; j--) { len *= exp_bound + 1; len1 *= exp_bound1 + 1; len2 *= exp_bound2 + 1; len = FLINT_MIN(len, WORD(1000)); len1 = FLINT_MIN(len, WORD(1000)); len2 = FLINT_MIN(len, WORD(1000)); } coeff_bits = n_randint(state, 200); for (j = 0; j < 2; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul(g, f, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-mul_array.c000066400000000000000000000140741461254215100212030ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_mul_array, state) { int i, j, result; /* Check mul_array matches mul_johnson */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, max_bound; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); max_bound = ctx->minfo->ord == ORD_LEX ? 200 : 100; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = max_bound/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_mul_array(k, f, g, ctx); if (!result) { continue; } fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_array matches mul_johnson\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check aliasing first argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, max_bound; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_mul_array(f, f, g, ctx); if (!result) continue; fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } /* Check aliasing second argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, max_bound; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_mul_array(g, f, g, ctx); if (!result) continue; fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-mul_array_threaded.c000066400000000000000000000147311461254215100230430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_mul_array_threaded, state) { int i, j, result, max_threads = 5; int tmul = 20; #ifdef _WIN32 tmul = 1; #endif /* Check mul_array_threaded matches mul_johnson */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, max_bound; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); max_bound = ctx->minfo->ord == ORD_LEX ? 200 : 100; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = max_bound/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_mul_array_threaded(k, f, g, ctx); if (!result) { continue; } fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_array_threaded matches mul_johnson\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, max_bound; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_mul_array_threaded(f, f, g, ctx); if (!result) continue; fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, max_bound; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); result = fmpz_mpoly_mul_array_threaded(g, f, g, ctx); if (!result) continue; fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-mul_dense.c000066400000000000000000000141741461254215100211640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_mul_dense, state) { int i, j, result, success; /* Check mul_dense matches mul_johnson */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits; slong max_bound, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 20); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); success = fmpz_mpoly_mul_dense(k, f, g, ctx); if (!success) continue; fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_dense matches mul_johnson\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits; slong max_bound, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 20); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); success = fmpz_mpoly_mul_dense(f, f, g, ctx); if (!success) continue; fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits; slong max_bound, exp_bound, exp_bound1, exp_bound2; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; coeff_bits = n_randint(state, 20); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); success = fmpz_mpoly_mul_dense(g, f, g, ctx); if (!success) continue; fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-mul_heap_threaded.c000066400000000000000000000154611461254215100226430ustar00rootroot00000000000000/* Copyright (C) 2017-2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_mul_heap_threaded, state) { slong i, j, result, max_threads = 5; slong tmul = 10; #ifdef _WIN32 tmul = 2; #endif { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h1, h2; const char * vars[] = {"x", "y" ,"z", "t", "u"}; fmpz_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h1, ctx); fmpz_mpoly_init(h2, ctx); fmpz_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)^5", vars, ctx); fmpz_mpoly_set_str_pretty(g, "(1+u+t+2*z^2+3*y^3+5*x^5)^5", vars, ctx); flint_set_num_threads(1); fmpz_mpoly_mul_heap_threaded(h1, f, g, ctx); flint_set_num_threads(2); fmpz_mpoly_mul_heap_threaded(h2, f, g, ctx); if (!fmpz_mpoly_equal(h1, h2, ctx)) { printf("FAIL\n"); flint_printf("Check example\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h1, ctx); fmpz_mpoly_clear(h2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check mul_heap_threaded matches mul_johnson */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_mul_heap_threaded(k, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_heap_threaded matches mul_johnson\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* aliasing first input */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_mul_heap_threaded(f, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first input\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* aliasing second input */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_mul_heap_threaded(g, f, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second input\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-mul_johnson.c000066400000000000000000000175101461254215100215410ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_mul_johnson, state) { int i, j, result; /* Check mul_johnson matches mul_array */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong n, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; int ok1; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 800/n/n) + 1; exp_bound1 = n_randint(state, 800/n/n) + 1; exp_bound2 = n_randint(state, 800/n/n) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); ok1 = fmpz_mpoly_mul_array(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_mul_johnson(k, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = ok1 == 0 || fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_johnson matches mul_array\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check f*(g + h) = f*g + f*h */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(k1, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k2, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_add(t1, g, h, ctx); fmpz_mpoly_assert_canonical(t1, ctx); fmpz_mpoly_mul_johnson(k1, f, t1, ctx); fmpz_mpoly_assert_canonical(k1, ctx); fmpz_mpoly_mul_johnson(t1, f, g, ctx); fmpz_mpoly_assert_canonical(t1, ctx); fmpz_mpoly_mul_johnson(t2, f, h, ctx); fmpz_mpoly_assert_canonical(t2, ctx); fmpz_mpoly_add(k2, t1, t2, ctx); fmpz_mpoly_assert_canonical(k2, ctx); result = fmpz_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*(g + h) = f*g + f*h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_mul_johnson(f, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_mul_johnson(g, f, g, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-mul_monomial.c000066400000000000000000000071721461254215100217010ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_mul_monomial, state) { slong i, j; slong tmul = 200; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, c, d, bb, cc; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(c, ctx); fmpz_mpoly_init(d, ctx); fmpz_mpoly_init(bb, ctx); fmpz_mpoly_init(cc, ctx); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(a, state, 1 + n_randint(state, 50), 1 + n_randint(state, 200), 1 + n_randint(state, 192), ctx); fmpz_mpoly_randtest_bits(b, state, 1 + n_randint(state, 30), 1 + n_randint(state, 200), 1 + n_randint(state, 192), ctx); fmpz_mpoly_randtest_bits(c, state, 1, 1 + n_randint(state, 200), 1 + n_randint(state, 192), ctx); if (fmpz_mpoly_length(c, ctx) != 1 || n_randint(state, 50) == 0) fmpz_mpoly_set_ui(c, n_randtest_not_zero(state), ctx); fmpz_mpoly_mul_monomial(a, b, c, ctx); fmpz_mpoly_assert_canonical(a, ctx); fmpz_mpoly_mul_johnson(d, b, c, ctx); if (!fmpz_mpoly_equal(a, d, ctx)) { flint_printf("FAIL: check mul_monomial against mul_johnson\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set(bb, b, ctx); fmpz_mpoly_set(cc, c, ctx); fmpz_mpoly_mul_monomial(bb, bb, cc, ctx); fmpz_mpoly_assert_canonical(bb, ctx); if (!fmpz_mpoly_equal(bb, d, ctx) || !fmpz_mpoly_equal(cc, c, ctx)) { flint_printf("FAIL: check aliasing first input\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set(bb, b, ctx); fmpz_mpoly_set(cc, c, ctx); fmpz_mpoly_mul_monomial(cc, bb, cc, ctx); fmpz_mpoly_assert_canonical(cc, ctx); if (!fmpz_mpoly_equal(cc, d, ctx) || !fmpz_mpoly_equal(bb, b, ctx)) { flint_printf("FAIL: check aliasing second input\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set(cc, c, ctx); fmpz_mpoly_mul_monomial(cc, cc, cc, ctx); fmpz_mpoly_assert_canonical(cc, ctx); fmpz_mpoly_mul_johnson(d, c, c, ctx); if (!fmpz_mpoly_equal(cc, d, ctx)) { flint_printf("FAIL: check aliasing both inputs\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(c, ctx); fmpz_mpoly_clear(d, ctx); fmpz_mpoly_clear(bb, ctx); fmpz_mpoly_clear(cc, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-neg.c000066400000000000000000000046021461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_neg, state) { int i, result; /* Check -(-a) == a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_neg(h, f, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_neg(g, h, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check -(-a) == a\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_neg(g, f, ctx); fmpz_mpoly_neg(g, g, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-pow_fps.c000066400000000000000000000106711461254215100206640ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" /* Defined in t-pow_fps.c and t-pow_ui.c */ #ifndef fmpz_mpoly_pow_naive #define fmpz_mpoly_pow_naive fmpz_mpoly_pow_naive void fmpz_mpoly_pow_naive(fmpz_mpoly_t res, fmpz_mpoly_t f, slong n, fmpz_mpoly_ctx_t ctx) { if (n == 0) fmpz_mpoly_one(res, ctx); else if (f->length == 0) fmpz_mpoly_zero(res, ctx); else if (n == 1) fmpz_mpoly_set(res, f, ctx); else { slong i; fmpz_mpoly_t pow; fmpz_mpoly_init(pow, ctx); fmpz_mpoly_set(pow, f, ctx); for (i = 1; i < n - 1; i++) fmpz_mpoly_mul_johnson(pow, pow, f, ctx); fmpz_mpoly_mul_johnson(res, pow, f, ctx); fmpz_mpoly_clear(pow, ctx); } } #endif TEST_FUNCTION_START(fmpz_mpoly_pow_fps, state) { slong i, j, tmul = 5; /* Check pow_fps against pow_naive */ for (i = 0; i < 10*tmul*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1; ulong pow; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10) + 1; pow = n_randint(state, 1 + 50/(len1 + 2)) + 2; exp_bits = n_randint(state, 600) + 2; exp_bits1 = n_randint(state, 600) + 10; exp_bits1 = n_randint(state, exp_bits1) + 2; /* increase chances of lower values */ coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); if (fmpz_mpoly_is_zero(f, ctx)) continue; fmpz_mpoly_pow_fps(g, f, pow, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_pow_naive(h, f, pow, ctx); fmpz_mpoly_assert_canonical(h, ctx); if (!fmpz_mpoly_equal(g, h, ctx)) { flint_printf("FAIL: Check pow_fps against pow_naive\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len, len1; ulong pow; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); pow = n_randint(state, 8) + 2; len = n_randint(state, 10); len1 = n_randint(state, 10); exp_bits = n_randint(state, 400) + 2; exp_bits1 = n_randint(state, 400) + 10; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); if (fmpz_mpoly_is_zero(f, ctx)) continue; fmpz_mpoly_pow_fps(g, f, pow, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_pow_fps(f, f, pow, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (!fmpz_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-pow_ui.c000066400000000000000000000104271461254215100205100ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" /* Defined in t-pow_fps.c and t-pow_ui.c */ #ifndef fmpz_mpoly_pow_naive #define fmpz_mpoly_pow_naive fmpz_mpoly_pow_naive void fmpz_mpoly_pow_naive(fmpz_mpoly_t res, fmpz_mpoly_t f, slong n, fmpz_mpoly_ctx_t ctx) { if (n == 0) fmpz_mpoly_one(res, ctx); else if (f->length == 0) fmpz_mpoly_zero(res, ctx); else if (n == 1) fmpz_mpoly_set(res, f, ctx); else { slong i; fmpz_mpoly_t pow; fmpz_mpoly_init(pow, ctx); fmpz_mpoly_set(pow, f, ctx); for (i = 1; i < n - 1; i++) fmpz_mpoly_mul_johnson(pow, pow, f, ctx); fmpz_mpoly_mul_johnson(res, pow, f, ctx); fmpz_mpoly_clear(pow, ctx); } } #endif TEST_FUNCTION_START(fmpz_mpoly_pow_ui, state) { slong i, j, tmul = 20; /* Check pow_ui against pow_naive */ for (i = 0; i < 10 * tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, len1; ulong pow; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); pow = n_randint(state, 1 + 50/(len1 + 2)); exp_bits = n_randint(state, 600) + 2; exp_bits1 = n_randint(state, 600) + 10; exp_bits1 = n_randint(state, exp_bits1) + 2; /* increase chances of lower values */ coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_pow_ui(g, f, pow, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_pow_naive(h, f, pow, ctx); fmpz_mpoly_assert_canonical(h, ctx); if (!fmpz_mpoly_equal(g, h, ctx)) { flint_printf("FAIL: Check pow_ui against pow_naive\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len, len1; ulong pow; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); pow = n_randint(state, 8); len = n_randint(state, 10); len1 = n_randint(state, 10); exp_bits = n_randint(state, 600) + 2; exp_bits1 = n_randint(state, 600) + 10; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_pow_ui(g, f, pow, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_pow_ui(f, f, pow, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (!fmpz_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-push_term_fmpz_fmpz.c000066400000000000000000000107411461254215100233030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_push_term_fmpz_fmpz, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f1, f2, f3, m; flint_bitcnt_t coeff_bits, exp_bits; fmpz **exp, **exp2, *exp3; slong len, nvars; fmpz_t c, c2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f1, ctx); fmpz_mpoly_init(f2, ctx); fmpz_mpoly_init(f3, ctx); fmpz_mpoly_init(m, ctx); fmpz_init(c); fmpz_init(c2); nvars = fmpz_mpoly_ctx_nvars(ctx); exp = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); exp3 = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); fmpz_init(exp3+k); } len = n_randint(state, 20); coeff_bits = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200); fmpz_mpoly_zero(f1, ctx); fmpz_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fmpz_randtest(c, state, coeff_bits); for (k = 0; k < nvars; k++){ fmpz_randtest_unsigned(exp[k], state, exp_bits); fmpz_set(exp3 + k, exp[k]); } /* add it to f1 */ fmpz_mpoly_zero(m, ctx); fmpz_mpoly_set_coeff_fmpz_fmpz(m, c, exp, ctx); fmpz_mpoly_add(f1, f1, m, ctx); fmpz_mpoly_assert_canonical(f1, ctx); /* push it back on f2 */ fmpz_mpoly_push_term_fmpz_fmpz(f2, c, exp, ctx); /* push it on f3 */ fmpz_mpoly_push_term_fmpz_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ fmpz_mpoly_get_term_coeff_fmpz(c2, f2, fmpz_mpoly_length(f2, ctx) - 1, ctx); fmpz_mpoly_get_term_exp_fmpz(exp2, f2, fmpz_mpoly_length(f2, ctx) - 1, ctx); if (!fmpz_equal(c, c2)) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (!fmpz_equal(exp[k], exp2[k])) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpz_mpoly_sort_terms(f2, ctx); fmpz_mpoly_combine_like_terms(f2, ctx); fmpz_mpoly_assert_canonical(f2, ctx); fmpz_mpoly_sort_terms(f3, ctx); fmpz_mpoly_combine_like_terms(f3, ctx); fmpz_mpoly_assert_canonical(f3, ctx); if (!fmpz_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushed polynomial matches add\ni=%wd\n",i,j); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf( "Check pushed with ffmpz polynomial matches add\ni=%wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_clear(c2); fmpz_clear(c); fmpz_mpoly_clear(f1, ctx); fmpz_mpoly_clear(f2, ctx); fmpz_mpoly_clear(f3, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_ctx_clear(ctx); for (k = 0; k < nvars; k++) { fmpz_clear(exp3 + k); fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp3); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-push_term_fmpz_ui.c000066400000000000000000000064361461254215100227520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_push_term_fmpz_ui, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f1, f2, m; flint_bitcnt_t coeff_bits, exp_bits; ulong * exp, * exp2; slong len, nvars; fmpz_t c, c2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f1, ctx); fmpz_mpoly_init(f2, ctx); fmpz_mpoly_init(m, ctx); fmpz_init(c); fmpz_init(c2); nvars = fmpz_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 20); coeff_bits = n_randint(state, 100) + 1; exp_bits = n_randint(state, FLINT_BITS + 1); fmpz_mpoly_zero(f1, ctx); fmpz_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fmpz_randtest(c, state, coeff_bits); for (k = 0; k < nvars; k++) exp[k] = n_randtest_bits(state, n_randint(state, exp_bits) + 1); /* add it to f1 */ fmpz_mpoly_zero(m, ctx); fmpz_mpoly_set_coeff_fmpz_ui(m, c, exp, ctx); fmpz_mpoly_add(f1, f1, m, ctx); /* push it back on f2 */ fmpz_mpoly_push_term_fmpz_ui(f2, c, exp, ctx); /* make sure last term matches */ fmpz_mpoly_get_term_coeff_fmpz(c2, f2, fmpz_mpoly_length(f2, ctx) - 1, ctx); fmpz_mpoly_get_term_exp_ui(exp2, f2, fmpz_mpoly_length(f2, ctx) - 1, ctx); if (!fmpz_equal(c, c2)) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (exp[k] != exp2[k]) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } } } fmpz_mpoly_sort_terms(f2, ctx); fmpz_mpoly_combine_like_terms(f2, ctx); fmpz_mpoly_assert_canonical(f2, ctx); if (!fmpz_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushback matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } fmpz_clear(c2); fmpz_clear(c); fmpz_mpoly_clear(f1, ctx); fmpz_mpoly_clear(f2, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-quasidiv_heap.c000066400000000000000000000305421461254215100220300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_quasidiv_heap, state) { int result; slong i, j, tmul = 10; /* Check f*g/g = f */ for (i = 0; i < 10 * tmul * flint_test_multiplier(); i++) { fmpz_t s1; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul(h, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_quasidiv_heap(s1, k, h, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_equal_ui(s1, 1) && fmpz_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_clear(s1); } /* Check output agrees with divrem for random polys */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t s1, s2; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_init(s2); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; coeff_bits = n_randint(state, 70); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 200/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bounds(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); fmpz_mpoly_quasidivrem_heap(s1, h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_quasidiv_heap(s2, k, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); result = fmpz_equal(s1, s2) && fmpz_mpoly_equal(k, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check output agrees with divrem\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r, ctx); fmpz_clear(s1); fmpz_clear(s2); } /* Check aliasing of quotient with first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t s1, s2; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_init(s2); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; coeff_bits = n_randint(state, 70); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 200/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); fmpz_mpoly_quasidivrem_heap(s1, h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_quasidiv_heap(s2, f, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_equal(s1, s2) && fmpz_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r, ctx); fmpz_clear(s1); fmpz_clear(s2); } /* Check aliasing of quotient with second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t s1, s2; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; flint_bitcnt_t coeff_bits; fmpz * shifts, * strides; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_init(s2); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 16); len1 = n_randint(state, 16); len2 = n_randint(state, 16) + 1; coeff_bits = n_randint(state, 70); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 200/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bounds(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bounds(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bounds(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_inflate(g, g, shifts, strides, ctx); fmpz_mpoly_quasidivrem_heap(s1, h, r, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_quasidiv_heap(s2, g, f, g, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_equal(s1, s2) && fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(r, ctx); fmpz_clear(s1); fmpz_clear(s2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-quasidivrem_heap.c000066400000000000000000000334501461254215100225350ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_quasidivrem_heap, state) { int i, j, result; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, r1, q1; fmpz_t s1; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(q1, ctx); fmpz_mpoly_init(r1, ctx); fmpz_init(s1); len = n_randint(state, 100); len1 = n_randint(state, 10) + 50; len2 = n_randint(state, 10) + 50; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(q1, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(r1, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits + 1, exp_bits2, ctx); } while (g->length == 0); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_quasidivrem_heap(s1, q1, r1, h, g, ctx); fmpz_mpoly_assert_canonical(q1, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_strongtest(r1, g, ctx); result = fmpz_is_one(s1) && fmpz_mpoly_equal(q1, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni=%wd, j=%wd\n",i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(q1, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_clear(s1); } /* Check aliasing of quotient with first argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1, t1, t2; fmpz_t s1, s2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_init(s2); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 1 + 200/n/n) + 1; exp_bound1 = n_randint(state, 1 + 200/n/n) + 1; exp_bound2 = n_randint(state, 1 + 200/n/n) + 1; coeff_bits = n_randint(state, 50); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_quasidivrem_heap(s1, h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mpoly_mul_johnson(t1, h, g, ctx); fmpz_mpoly_add(t1, t1, r1, ctx); fmpz_mpoly_scalar_mul_fmpz(t2, f, s1, ctx); fmpz_mpoly_quasidivrem_heap(s2, f, k, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(t1, t2, ctx) && fmpz_mpoly_equal(h, f, ctx) && fmpz_mpoly_equal(r1, k, ctx); if (!result) { printf("FAIL\n"); printf("Check aliasing of quotient with first argument\n"); flint_printf("i = %wd j = %wd\n"); fflush(stdout); flint_abort(); } } fmpz_clear(s1); fmpz_clear(s2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1, t1, t2; fmpz_t s1, s2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_init(s2); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 1 + 200/n/n) + 1; exp_bound1 = n_randint(state, 1 + 200/n/n) + 1; exp_bound2 = n_randint(state, 1 + 200/n/n) + 1; coeff_bits = n_randint(state, 50); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_quasidivrem_heap(s1, h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mpoly_mul_johnson(t1, h, g, ctx); fmpz_mpoly_add(t1, t1, r1, ctx); fmpz_mpoly_scalar_mul_fmpz(t2, f, s1, ctx); fmpz_mpoly_quasidivrem_heap(s2, g, k, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(t1, t2, ctx) && fmpz_mpoly_equal(h, g, ctx) && fmpz_mpoly_equal(r1, k, ctx); if (!result) { printf("FAIL\n"); printf("Check aliasing of quotient with second argument\n"); flint_printf("i = %wd j = %wd\n"); fflush(stdout); flint_abort(); } } fmpz_clear(s1); fmpz_clear(s2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); } /* Check aliasing of remainder with first argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1, t1, t2; fmpz_t s1, s2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_init(s2); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 1 + 200/n/n) + 1; exp_bound1 = n_randint(state, 1 + 200/n/n) + 1; exp_bound2 = n_randint(state, 1 + 200/n/n) + 1; coeff_bits = n_randint(state, 50); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_quasidivrem_heap(s1, h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mpoly_mul_johnson(t1, h, g, ctx); fmpz_mpoly_add(t1, t1, r1, ctx); fmpz_mpoly_scalar_mul_fmpz(t2, f, s1, ctx); fmpz_mpoly_quasidivrem_heap(s2, k, f, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(f, ctx); result = fmpz_mpoly_equal(t1, t2, ctx) && fmpz_mpoly_equal(h, k, ctx) && fmpz_mpoly_equal(r1, f, ctx); if (!result) { printf("FAIL\n"); printf("Check aliasing of remainder with first argument\n"); flint_printf("i = %wd j = %wd\n"); fflush(stdout); flint_abort(); } } fmpz_clear(s1); fmpz_clear(s2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); } /* Check aliasing of remainder with second argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, r1, t1, t2; fmpz_t s1, s2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; slong n; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_init(s1); fmpz_init(s2); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(r1, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 1 + 200/n/n) + 1; exp_bound1 = n_randint(state, 1 + 200/n/n) + 1; exp_bound2 = n_randint(state, 1 + 200/n/n) + 1; coeff_bits = n_randint(state, 50); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); do { fmpz_mpoly_randtest_bound(g, state, len2, coeff_bits + 1, exp_bound2, ctx); } while (g->length == 0); fmpz_mpoly_randtest_bound(h, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(r1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_quasidivrem_heap(s1, h, r1, f, g, ctx); fmpz_mpoly_assert_canonical(h, ctx); fmpz_mpoly_assert_canonical(r1, ctx); fmpz_mpoly_remainder_strongtest(r1, g, ctx); fmpz_mpoly_mul_johnson(t1, h, g, ctx); fmpz_mpoly_add(t1, t1, r1, ctx); fmpz_mpoly_scalar_mul_fmpz(t2, f, s1, ctx); fmpz_mpoly_quasidivrem_heap(s2, k, g, f, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_assert_canonical(g, ctx); result = fmpz_mpoly_equal(t1, t2, ctx) && fmpz_mpoly_equal(h, k, ctx) && fmpz_mpoly_equal(r1, g, ctx); if (!result) { printf("FAIL\n"); printf("Check aliasing of remainder with second argument\n"); flint_printf("i = %wd j = %wd\n"); fflush(stdout); flint_abort(); } } fmpz_clear(s1); fmpz_clear(s2); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(r1, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-quasidivrem_ideal_heap.c000066400000000000000000000173651461254215100237020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_quasidivrem_ideal_heap, state) { int i, j, w, result; /* Check s*f = g1*q1 + ... + gn*qn + r for random polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t scale; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, r, k1, k2; fmpz_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; slong n; fmpz_mpoly_struct * qarr[5], * darr[5]; fmpz * shifts, * strides; num = n_randint(state, 5) + 1; g = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); q = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); fmpz_mpoly_ctx_init_rand(ctx, state, 10); for (w = 0; w < num; w++) { fmpz_mpoly_init(g + w, ctx); darr[w] = g + w; fmpz_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpz_init(scale); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 12); len2 = n_randint(state, 8) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 10/n + 1) + 2; exp_bound1 = n_randint(state, 25/n + 1) + 2; exp_bound2 = n_randint(state, 20/n + 1) + 1; coeff_bits = n_randint(state, 40); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_inflate(f, f, shifts, strides, ctx); fmpz_mpoly_assert_canonical(f, ctx); for (w = 0; w < num; w++) { do { fmpz_mpoly_randtest_bound(darr[w], state, len2, coeff_bits + 1, exp_bound2, ctx); } while (darr[w]->length == 0); fmpz_mpoly_inflate(darr[w], darr[w], shifts, strides, ctx); fmpz_mpoly_assert_canonical(darr[w], ctx); fmpz_mpoly_randtest_bound(qarr[w], state, len, coeff_bits, exp_bound, ctx); } fmpz_mpoly_randtest_bound(k1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k2, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_quasidivrem_ideal_heap(scale, qarr, r, f, darr, num, ctx); fmpz_mpoly_assert_canonical(r, ctx); fmpz_mpoly_set(k2, r, ctx); for (w = 0; w < num; w++) { fmpz_mpoly_assert_canonical(qarr[w], ctx); fmpz_mpoly_remainder_strongtest(r, darr[w], ctx); fmpz_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fmpz_mpoly_add(k2, k2, k1, ctx); } fmpz_mpoly_scalar_mul_fmpz(f, f, scale, ctx); result = fmpz_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check s*f = g1*q1 + ... + gn*qn + r\ni=%wd j=%wd\n",i,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); for (w = 0; w < num; w++) fmpz_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpz_mpoly_clear(darr[w], ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_clear(r, ctx); flint_free(g); flint_free(q); fmpz_clear(scale); } /* Check aliasing remainder */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t scale; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, r, k1, k2; fmpz_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; slong n; fmpz_mpoly_struct * qarr[5], * darr[5]; num = n_randint(state, 5) + 1; g = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); q = (fmpz_mpoly_struct *) flint_malloc(num*sizeof(fmpz_mpoly_struct)); fmpz_mpoly_ctx_init_rand(ctx, state, 10); for (w = 0; w < num; w++) { fmpz_mpoly_init(g + w, ctx); darr[w] = g + w; fmpz_mpoly_init(q + w, ctx); qarr[w] = q + w; } fmpz_init(scale); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(k1, ctx); fmpz_mpoly_init(k2, ctx); fmpz_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 12); len2 = n_randint(state, 8) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 10/n + 1) + 2; exp_bound1 = n_randint(state, 25/n + 1) + 2; exp_bound2 = n_randint(state, 20/n + 1) + 1; coeff_bits = n_randint(state, 40); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits, exp_bound1, ctx); for (w = 0; w < num; w++) { do { fmpz_mpoly_randtest_bound(darr[w], state, len2, coeff_bits + 1, exp_bound2, ctx); } while (darr[w]->length == 0); fmpz_mpoly_randtest_bound(qarr[w], state, len, coeff_bits, exp_bound, ctx); } fmpz_mpoly_randtest_bound(k1, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_randtest_bound(k2, state, len, coeff_bits, exp_bound, ctx); fmpz_mpoly_set(r, f, ctx); fmpz_mpoly_quasidivrem_ideal_heap(scale, qarr, r, r, darr, num, ctx); fmpz_mpoly_assert_canonical(r, ctx); fmpz_mpoly_set(k2, r, ctx); for (w = 0; w < num; w++) { fmpz_mpoly_assert_canonical(qarr[w], ctx); fmpz_mpoly_remainder_strongtest(r, darr[w], ctx); fmpz_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fmpz_mpoly_add(k2, k2, k1, ctx); } fmpz_mpoly_scalar_mul_fmpz(f, f, scale, ctx); result = fmpz_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing remainder\ni=%wd j=%wd\n",i,j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) fmpz_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fmpz_mpoly_clear(darr[w], ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(k1, ctx); fmpz_mpoly_clear(k2, ctx); fmpz_mpoly_clear(r, ctx); flint_free(g); flint_free(q); fmpz_clear(scale); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-repack_bits.c000066400000000000000000000152141461254215100214730ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_repack_bits, state) { int i, j, success; /* Check packing up */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2, newbits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fmpz_mpoly_repack_bits(f, g, newbits, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (!success || !fmpz_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check packing up\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fmpz_mpoly_repack_bits(g, g, newbits, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!success || !fmpz_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check packing up with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check repacking down up */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2, newbits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_randtest_bits(h, state, len2, coeff_bits, exp_bits2, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fmpz_mpoly_repack_bits(f, g, newbits, ctx); fmpz_mpoly_assert_canonical(f, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fmpz_mpoly_repack_bits(h, f, newbits, ctx); fmpz_mpoly_assert_canonical(h, ctx); if (!success || !fmpz_mpoly_equal(h, g, ctx)) { printf("FAIL\n"); flint_printf("Check repacking down\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fmpz_mpoly_repack_bits(f, f, newbits, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (!success || !fmpz_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check repacking down with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check packing down */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2, newbits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); if (g->bits <= MPOLY_MIN_BITS) continue; newbits = n_randint(state, g->bits - MPOLY_MIN_BITS) + MPOLY_MIN_BITS; newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fmpz_mpoly_repack_bits(f, g, newbits, ctx); fmpz_mpoly_assert_canonical(f, ctx); if (success && !fmpz_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check packing down\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fmpz_mpoly_set(f, g, ctx); newbits = n_randint(state, g->bits - MPOLY_MIN_BITS) + MPOLY_MIN_BITS; newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fmpz_mpoly_repack_bits(g, g, newbits, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (success && !fmpz_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check packing down with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-resize.c000066400000000000000000000061031461254215100205030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_resize, state) { slong i, j, k; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f1, f2, f3, m; flint_bitcnt_t coeff_bits, exp_bits; ulong * exp, * exp2; slong len, nvars; fmpz_t c; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f1, ctx); fmpz_mpoly_init(f2, ctx); fmpz_mpoly_init(f3, ctx); fmpz_mpoly_init(m, ctx); fmpz_init(c); nvars = fmpz_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 200); coeff_bits = n_randint(state, 100) + 1; exp_bits = n_randint(state, FLINT_BITS) + 1; fmpz_mpoly_zero(f1, ctx); fmpz_mpoly_zero(f2, ctx); fmpz_mpoly_zero(f3, ctx); for (j = 0; j < len; j++) { /* get random term */ fmpz_randtest(c, state, coeff_bits); for (k = 0; k < nvars; k++) exp[k] = n_randtest_bits(state, n_randint(state, exp_bits) + 1); /* add it to f1 */ fmpz_mpoly_zero(m, ctx); fmpz_mpoly_set_coeff_fmpz_ui(m, c, exp, ctx); fmpz_mpoly_add(f1, f1, m, ctx); /* push it back on f2 */ fmpz_mpoly_push_term_fmpz_ui(f2, c, exp, ctx); /* manually push it on f3 */ fmpz_mpoly_resize(f3, j + 1 + n_randint(state, 10), ctx); fmpz_mpoly_set_term_coeff_fmpz(f3, j, c, ctx); fmpz_mpoly_set_term_exp_ui(f3, j, exp, ctx); } fmpz_mpoly_sort_terms(f2, ctx); fmpz_mpoly_combine_like_terms(f2, ctx); fmpz_mpoly_assert_canonical(f2, ctx); fmpz_mpoly_sort_terms(f3, ctx); fmpz_mpoly_combine_like_terms(f3, ctx); fmpz_mpoly_assert_canonical(f3, ctx); if (!fmpz_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushback matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check resize+setterm matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_mpoly_clear(f1, ctx); fmpz_mpoly_clear(f2, ctx); fmpz_mpoly_clear(f3, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-resultant_discriminant.c000066400000000000000000000173421461254215100237760ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_resultant_discriminant, state) { slong i, j; /* Check quadratic polynomial */ { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, d, d1; const char * vars[] = {"x","a","b","c"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(d, ctx); fmpz_mpoly_init(d1, ctx); fmpz_mpoly_set_str_pretty(f, "a^10*x^2 + b^100*x + c^100000000000000000000", vars, ctx); fmpz_mpoly_set_str_pretty(d1, "b^200 - 4*a^10*c^100000000000000000000", vars, ctx); if (!fmpz_mpoly_discriminant(d, f, 0, ctx)) { flint_printf("FAIL: could not compute quadratic discriminant\n"); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(d, ctx); fmpz_mpoly_clear(d1, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check univariate resultant */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, r; fmpz_poly_t au, bu; fmpz_t ru; ordering_t ord; slong nvars, len1, len2, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(r, ctx); fmpz_poly_init(au); fmpz_poly_init(bu); fmpz_init(ru); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 50) + 1; exp_bound2 = n_randint(state, 50) + 1; coeff_bits = n_randint(state, 4); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_get_fmpz_poly(au, a, 0, ctx); fmpz_mpoly_get_fmpz_poly(bu, b, 0, ctx); fmpz_poly_resultant(ru, au, bu); if (!fmpz_mpoly_resultant(r, a, b, 0, ctx) || !fmpz_mpoly_equal_fmpz(r, ru, ctx)) { flint_printf("FAIL: Check univariate resultant \n"); flint_printf("i: %wd\n",i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(r, ctx); fmpz_poly_clear(au); fmpz_poly_clear(bu); fmpz_clear(ru); } /* Check res(a*b,c) = res(a,c)*res(b,c) */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, c, ab, ra, rb, rab, p; ordering_t ord; slong nvars, len1, len2, len3, exp_bound1, exp_bound2, exp_bound3; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 3) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(c, ctx); fmpz_mpoly_init(ab, ctx); fmpz_mpoly_init(ra, ctx); fmpz_mpoly_init(rb, ctx); fmpz_mpoly_init(rab, ctx); fmpz_mpoly_init(p, ctx); len1 = n_randint(state, 15); len2 = n_randint(state, 15); len3 = n_randint(state, 15); exp_bound1 = n_randint(state, 5) + 1; exp_bound2 = n_randint(state, 5) + 1; exp_bound3 = n_randint(state, 5) + 1; coeff_bits = n_randint(state, 3); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, exp_bound2, ctx); fmpz_mpoly_randtest_bound(c, state, len3, coeff_bits, exp_bound3, ctx); for (j = 0; j < nvars; j++) { fmpz_mpoly_mul(ab, a, b, ctx); if (!fmpz_mpoly_resultant(ra, a, c, j, ctx)) continue; fmpz_mpoly_assert_canonical(ra, ctx); if (!fmpz_mpoly_resultant(rb, b, c, j, ctx)) continue; fmpz_mpoly_assert_canonical(rb, ctx); if (!fmpz_mpoly_resultant(rab, ab, c, j, ctx)) continue; fmpz_mpoly_assert_canonical(rab, ctx); fmpz_mpoly_mul(p, ra, rb, ctx); if (!fmpz_mpoly_equal(p,rab,ctx)) { flint_printf("FAIL: Check res(a*b,c) = res(a,c)*res(b,c)\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(c, ctx); fmpz_mpoly_clear(ab, ctx); fmpz_mpoly_clear(ra, ctx); fmpz_mpoly_clear(rb, ctx); fmpz_mpoly_clear(rab, ctx); fmpz_mpoly_clear(p, ctx); } /* Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2 */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, ab, r, da, db, dab, p; ordering_t ord; slong nvars, len1, len2, exp_bound1, exp_bound2; slong coeff_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 3) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(ab, ctx); fmpz_mpoly_init(da, ctx); fmpz_mpoly_init(db, ctx); fmpz_mpoly_init(dab, ctx); fmpz_mpoly_init(r, ctx); fmpz_mpoly_init(p, ctx); len1 = n_randint(state, 15); len2 = n_randint(state, 15); exp_bound1 = n_randint(state, 5) + 1; exp_bound2 = n_randint(state, 5) + 1; coeff_bits = n_randint(state, 3); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, exp_bound1, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, exp_bound2, ctx); for (j = 0; j < nvars; j++) { if (fmpz_mpoly_degree_si(a, j, ctx) < 1) continue; if (fmpz_mpoly_degree_si(b, j, ctx) < 1) continue; fmpz_mpoly_mul(ab, a, b, ctx); if (!fmpz_mpoly_resultant(r, a, b, j, ctx)) continue; if (!fmpz_mpoly_discriminant(da, a, j, ctx)) continue; if (!fmpz_mpoly_discriminant(db, b, j, ctx)) continue; if (!fmpz_mpoly_discriminant(dab, ab, j, ctx)) continue; fmpz_mpoly_mul(p, da, db, ctx); fmpz_mpoly_mul(p, p, r, ctx); fmpz_mpoly_mul(p, p, r, ctx); if (!fmpz_mpoly_equal(dab, p, ctx)) { flint_printf("FAIL: Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(ab, ctx); fmpz_mpoly_clear(da, ctx); fmpz_mpoly_clear(db, ctx); fmpz_mpoly_clear(dab, ctx); fmpz_mpoly_clear(r, ctx); fmpz_mpoly_clear(p, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-reverse.c000066400000000000000000000046561461254215100206700ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_reverse, state) { int i, result; /* Check rev(rev(a)) == a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_reverse(h, f, ctx); fmpz_mpoly_reverse(g, h, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check rev(rev(a)) == a\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_reverse(g, f, ctx); fmpz_mpoly_reverse(g, g, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_divexact_fmpz.c000066400000000000000000000062651461254215100234030ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_divexact_fmpz, state) { int i, j, result; /* Check (f*a)/a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest_not_zero(c, state, n_randint(state, 200) + 1); fmpz_mpoly_scalar_mul_fmpz(g, f, c, ctx); fmpz_mpoly_scalar_divexact_fmpz(h, g, c, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)/a = f\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mpoly_scalar_mul_fmpz(f, f, c, ctx); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_scalar_divexact_fmpz(h, f, c, ctx); fmpz_mpoly_scalar_divexact_fmpz(g, g, c, ctx); result = fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_divexact_si.c000066400000000000000000000060711461254215100230350ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_divexact_si, state) { int i, j, result; /* Check (f*a)/a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = z_randtest_not_zero(state); fmpz_mpoly_scalar_mul_si(g, f, c, ctx); fmpz_mpoly_scalar_divexact_si(h, g, c, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)/a = f\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = z_randtest_not_zero(state); fmpz_mpoly_scalar_mul_si(f, f, c, ctx); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_scalar_divexact_si(h, f, c, ctx); fmpz_mpoly_scalar_divexact_si(g, g, c, ctx); result = fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_divexact_ui.c000066400000000000000000000060401461254215100230330ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_divexact_ui, state) { int i, j, result; /* Check (f*a)/a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; ulong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = n_randtest_not_zero(state); fmpz_mpoly_scalar_mul_ui(g, f, c, ctx); fmpz_mpoly_scalar_divexact_ui(h, g, c, ctx); result = fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)/a = f\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; ulong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = n_randtest_not_zero(state); fmpz_mpoly_scalar_mul_ui(f, f, c, ctx); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_scalar_divexact_ui(h, f, c, ctx); fmpz_mpoly_scalar_divexact_ui(g, g, c, ctx); result = fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_divides_fmpz.c000066400000000000000000000064161461254215100232210ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_divides_fmpz, state) { int i, j, result; /* Check (f*a)/a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest_not_zero(c, state, n_randint(state, 200) + 1); fmpz_mpoly_scalar_mul_fmpz(g, f, c, ctx); result = fmpz_mpoly_scalar_divides_fmpz(h, g, c, ctx); result = result && fmpz_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)/a = f\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mpoly_scalar_mul_fmpz(f, f, c, ctx); fmpz_mpoly_set(g, f, ctx); result = fmpz_mpoly_scalar_divides_fmpz(h, f, c, ctx); result = result && fmpz_mpoly_scalar_divides_fmpz(g, g, c, ctx); result = result && fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_fmma.c000066400000000000000000000074531461254215100214600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_fmma, state) { slong i, j; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, t1, t2; fmpz_t a, b; slong len, coeff_bits, exp_bits; fmpz_init(a); fmpz_init(b); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_randtest(a, state, n_randint(state, 200)); fmpz_randtest(b, state, n_randint(state, 200)); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(t1, state, len, coeff_bits, exp_bits, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(t2, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_scalar_fmma(f, g, a, h, b, ctx); fmpz_mpoly_assert_canonical(f, ctx); fmpz_mpoly_scalar_mul_fmpz(t1, g, a, ctx); fmpz_mpoly_scalar_mul_fmpz(t2, h, b, ctx); fmpz_mpoly_add(t1, t1, t2, ctx); if (!fmpz_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check fmma definition\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } fmpz_mpoly_set(t1, g, ctx); fmpz_mpoly_scalar_fmma(t1, t1, a, h, b, ctx); fmpz_mpoly_assert_canonical(t1, ctx); if (!fmpz_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check aliasing first argument\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } fmpz_mpoly_set(t1, h, ctx); fmpz_mpoly_scalar_fmma(t1, g, a, t1, b, ctx); fmpz_mpoly_assert_canonical(t1, ctx); if (!fmpz_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check aliasing second argument\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } fmpz_mpoly_scalar_fmma(f, g, a, g, b, ctx); fmpz_mpoly_set(t1, g, ctx); fmpz_mpoly_scalar_fmma(t1, t1, a, t1, b, ctx); fmpz_mpoly_assert_canonical(t1, ctx); if (!fmpz_mpoly_equal(f, t1, ctx)) { flint_printf("FAIL: check aliasing both arguments\n"); flint_printf("i = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_clear(a); fmpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_mul_fmpz.c000066400000000000000000000067461461254215100223750ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_mul_fmpz, state) { int i, j, result; /* Check (f*a)*b = f*(a*b) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; fmpz_t a, b, c; slong len, coeff_bits, exp_bits; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(a, state, n_randint(state, 200)); fmpz_randtest(b, state, n_randint(state, 200)); fmpz_mul(c, a, b); fmpz_mpoly_scalar_mul_fmpz(g, f, a, ctx); fmpz_mpoly_scalar_mul_fmpz(h, g, b, ctx); fmpz_mpoly_scalar_mul_fmpz(k, f, c, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b)\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t c; slong len, coeff_bits, exp_bits; fmpz_init(c); fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_scalar_mul_fmpz(h, f, c, ctx); fmpz_mpoly_scalar_mul_fmpz(g, g, c, ctx); result = fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_mul_si.c000066400000000000000000000067401461254215100220260ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_mul_si, state) { int i, j, result; /* Check (f*a)*b = f*(a*b) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong a, b, c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); a = (slong) n_randbits(state, n_randint(state, FLINT_BITS/2 - 1) + 1); b = (slong) n_randbits(state, n_randint(state, FLINT_BITS/2 - 1) + 1); if (n_randint(state, 2) == 0) a = -a; if (n_randint(state, 2) == 0) b = -b; c = a*b; fmpz_mpoly_scalar_mul_si(g, f, a, ctx); fmpz_mpoly_scalar_mul_si(h, g, b, ctx); fmpz_mpoly_scalar_mul_si(k, f, c, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b)\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = z_randtest(state); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_scalar_mul_si(h, f, c, ctx); fmpz_mpoly_scalar_mul_si(g, g, c, ctx); result = fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-scalar_mul_ui.c000066400000000000000000000065331461254215100220300ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_scalar_mul_ui, state) { int i, j, result; /* Check (f*a)*b = f*(a*b) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; ulong a, b, c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); a = n_randbits(state, n_randint(state, FLINT_BITS/2) + 1); b = n_randbits(state, n_randint(state, FLINT_BITS/2) + 1); c = a*b; fmpz_mpoly_scalar_mul_ui(g, f, a, ctx); fmpz_mpoly_scalar_mul_ui(h, g, b, ctx); fmpz_mpoly_scalar_mul_ui(k, f, c, ctx); result = fmpz_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b)\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; ulong c; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); c = n_randtest(state); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_scalar_mul_ui(h, f, c, ctx); fmpz_mpoly_scalar_mul_ui(g, g, c, ctx); result = fmpz_mpoly_equal(g, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-set_equal.c000066400000000000000000000065021461254215100211670ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_set_equal, state) { int i, result; /* Set b = a and check a == b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len, coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_set(g, f, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Set b = a and check a == b\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } /* Set b = a, alter b and check a == b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; ordering_t ord; slong nvars, len, coeff_bits, exp_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_add_ui(g, f, UWORD(1), ctx); result = !fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Set b = a, alter b and check a == b\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; ordering_t ord; slong nvars, len, coeff_bits, exp_bits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_set(g, f, ctx); fmpz_mpoly_set(g, g, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd\n", i); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-set_fmpz.c000066400000000000000000000034371461254215100210400ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_set_fmpz, state) { int i, result; /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_t c, d; slong nvars, len, coeff_bits, exp_bits, j; ulong * exp; fmpz_init(c); fmpz_init(d); fmpz_mpoly_ctx_init_rand(ctx, state, 20); nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_mpoly_set_fmpz(f, c, ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (j = 0; j < nvars; j++) exp[j] = 0; fmpz_mpoly_get_coeff_fmpz_ui(d, f, exp, ctx); result = fmpz_equal(c, d) && ((fmpz_is_zero(c) && f->length == 0) || f->length == 1); if (!result) { printf("FAIL\n"); flint_printf("Set to random integer and compare\ni = %wd\n", i); fflush(stdout); flint_abort(); } flint_free(exp); fmpz_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-set_gen_fmpz_poly.c000066400000000000000000000040411461254215100227240ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_set_gen_fmpz_poly, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t F, G, x, t; fmpz_poly_t f; slong nvars, i, j; fmpz_poly_init(f); fmpz_mpoly_ctx_init_rand(ctx, state, 4); nvars = ctx->minfo->nvars; if (nvars >= 1) { fmpz_mpoly_init(F, ctx); fmpz_mpoly_init(G, ctx); fmpz_mpoly_init(x, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_randtest_bound(F, state, 10, 100, 100, ctx); fmpz_poly_randtest(f, state, 10, 100); i = n_randint(state, nvars); fmpz_mpoly_set_gen_fmpz_poly(F, i, f, ctx); fmpz_mpoly_gen(x, i, ctx); for (j = 0; j < f->length; j++) { fmpz_mpoly_pow_ui(t, x, j, ctx); fmpz_mpoly_scalar_mul_fmpz(t, t, f->coeffs + j, ctx); fmpz_mpoly_add(G, G, t, ctx); } if (!fmpz_mpoly_equal(F, G, ctx)) { flint_printf("FAIL\n"); fmpz_mpoly_print_pretty(F, NULL, ctx); flint_printf("\n\n"); fmpz_mpoly_print_pretty(G, NULL, ctx); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_clear(F, ctx); fmpz_mpoly_clear(G, ctx); fmpz_mpoly_clear(x, ctx); fmpz_mpoly_clear(t, ctx); } fmpz_poly_clear(f); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-set_si.c000066400000000000000000000033241461254215100204720ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_set_si, state) { int i, result; /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; slong c, d; slong nvars, len, coeff_bits, exp_bits, j; ulong * exp; fmpz_mpoly_ctx_init_rand(ctx, state, 20); nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); c = z_randtest(state); fmpz_mpoly_set_si(f, c, ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (j = 0; j < nvars; j++) exp[j] = 0; d = fmpz_mpoly_get_coeff_si_ui(f, exp, ctx); result = c == d && ((c == 0 && f->length == 0) || f->length == 1); if (!result) { printf("FAIL\n"); flint_printf("Set to random integer and compare\ni = %wd\n", i); fflush(stdout); flint_abort(); } flint_free(exp); fmpz_mpoly_clear(f, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-set_ui.c000066400000000000000000000032571461254215100205010ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_set_ui, state) { int i, result; /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; ulong c, d; slong nvars, len, coeff_bits, exp_bits, j; ulong * exp; fmpz_mpoly_ctx_init_rand(ctx, state, 20); nvars = ctx->minfo->nvars; fmpz_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); c = n_randtest(state); fmpz_mpoly_set_ui(f, c, ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (j = 0; j < nvars; j++) exp[j] = 0; d = fmpz_mpoly_get_coeff_ui_ui(f, exp, ctx); result = c == d && ((c == 0 && f->length == 0) || f->length == 1); if (!result) { printf("FAIL\n"); flint_printf("Set to random integer and compare\ni = %wd\n", i); fflush(stdout); flint_abort(); } flint_free(exp); fmpz_mpoly_clear(f, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-sort_terms.c000066400000000000000000000037511461254215100214110ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_sort_terms, state) { int i, j, result; /* Check scramble and sort */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len; flint_bitcnt_t coeff_bits, exp_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 200); exp_bits = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 20); for (j = 0; j < 4; j++) { slong N, k; fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_set(g, f, ctx); N = mpoly_words_per_exp(f->bits, ctx->minfo); for (k = WORD(0); k < f->length; k++) { ulong a, b; a = n_randint(state, f->length); b = n_randint(state, f->length); fmpz_swap(f->coeffs + a, f->coeffs + b); mpoly_monomial_swap(f->exps + N*a, f->exps + N*b, N); } fmpz_mpoly_sort_terms(f, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check scramble and sort\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-sqrt_heap.c000066400000000000000000000260031461254215100211710ustar00rootroot00000000000000/* Copyright (C) 2017, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_sqrt_heap, state) { slong i, j, tmul = 10; { fmpz_mpoly_t f, g, p, q; fmpz_mpoly_ctx_t ctx; const char * vars[] = {"x", "y", "z", "t", "u"}; int sqr; fmpz_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(p, ctx); fmpz_mpoly_init(q, ctx); fmpz_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)^6", vars, ctx); fmpz_mpoly_mul(p, f, f, ctx); fmpz_mpoly_assert_canonical(p, ctx); sqr = fmpz_mpoly_sqrt_heap(q, p, ctx, 1); fmpz_mpoly_assert_canonical(q, ctx); if (!sqr) { flint_printf("FAIL\n"); flint_printf("Check example1: sqr\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_mul(g, q, q, ctx); if (!fmpz_mpoly_equal(p, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check example1\n"); fflush(stdout); flint_abort(); } /* D Coppersmith, J Davenport, Polynomials whose powers are sparse */ fmpz_mpoly_set_str_pretty(f, "(1+2*x-2*x^2+4*x^3-10*x^4+50*x^5+125*x^6)*(-1+110*x^6)", vars, ctx); fmpz_mpoly_mul(p, f, f, ctx); sqr = fmpz_mpoly_sqrt_heap(q, p, ctx, 1); fmpz_mpoly_assert_canonical(q, ctx); if (!sqr || !fmpz_mpoly_equal(q, f, ctx)) { flint_printf("FAIL\n"); flint_printf("Check example 2\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_clear(q, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check sqrt(f^2) = +-f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; flint_bitcnt_t coeff_bits, coeff_bits1; int sqr; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits1, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul(g, f, f, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (f->length > 0 && fmpz_sgn(f->coeffs + 0) < 0) fmpz_mpoly_neg(f, f, ctx); sqr = fmpz_mpoly_sqrt_heap(h, g, ctx, 1); fmpz_mpoly_assert_canonical(h, ctx); if (!sqr) { printf("FAIL\n"); flint_printf("Check sqrt(f^2) returns 1\n"); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(h, f, ctx)) { printf("FAIL\n"); flint_printf("Check sqrt(f^2) = +-f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } sqr = fmpz_mpoly_sqrt_heap(k, g, ctx, 0); fmpz_mpoly_assert_canonical(k, ctx); if (!sqr) { printf("FAIL\n"); flint_printf("Check sqrt(f^2) returns 1: nocheck\n"); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_equal(k, f, ctx)) { printf("FAIL\n"); flint_printf("Check sqrt(f)^2 = +-f\ni = %wd, j = %wd: nocheck\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check sqrt(f^2*(x^2+x)) returns 0 */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k, x; slong len, len1, nvars; flint_bitcnt_t exp_bits, exp_bits1; flint_bitcnt_t coeff_bits, coeff_bits1; int sqr; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); fmpz_mpoly_init(x, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); coeff_bits1 = n_randint(state, 200) + 1; nvars = fmpz_mpoly_ctx_nvars(ctx); for (j = 0; j < 4; j++) { do { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits1, exp_bits1, ctx); } while (fmpz_mpoly_is_zero(f, ctx)); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul(g, f, f, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (nvars < 1) continue; fmpz_mpoly_gen(x, n_randint(state, nvars), ctx); fmpz_mpoly_mul(k, x, x, ctx); fmpz_mpoly_add(k, k, x, ctx); fmpz_mpoly_assert_canonical(k, ctx); fmpz_mpoly_mul(g, g, k, ctx); fmpz_mpoly_assert_canonical(g, ctx); sqr = fmpz_mpoly_sqrt_heap(h, g, ctx, 1); fmpz_mpoly_assert_canonical(h, ctx); if (sqr) { printf("FAIL\n"); flint_printf("Check nonsquare returns 0\n"); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(h, ctx)) { printf("FAIL\n"); flint_printf("Nonsquare returns 0 sqrt\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_clear(x, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check sqrt(random) */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; flint_bitcnt_t coeff_bits, coeff_bits1; int sqr; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); coeff_bits1 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits1, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); sqr = fmpz_mpoly_sqrt_heap(g, f, ctx, 1); fmpz_mpoly_assert_canonical(g, ctx); if (sqr) { fmpz_mpoly_mul(g, g, g, ctx); if (!fmpz_mpoly_equal(g, f, ctx)) { flint_printf("FAIL\n"); flint_printf("Check sqrt(random)\n"); fflush(stdout); flint_abort(); } } else if (!fmpz_mpoly_is_zero(g, ctx)) { flint_printf("FAIL\n"); flint_printf("Nonsquare returns 0 sqrt\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check aliasing of square root with input */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h, k; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; flint_bitcnt_t coeff_bits, coeff_bits1; int sqr1, sqr2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 200); coeff_bits1 = n_randint(state, 200); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits1, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_randtest_bits(h, state, len, coeff_bits, exp_bits, ctx); fmpz_mpoly_mul(g, f, f, ctx); fmpz_mpoly_assert_canonical(g, ctx); fmpz_mpoly_set(k, g, ctx); fmpz_mpoly_assert_canonical(k, ctx); sqr1 = fmpz_mpoly_sqrt_heap(h, g, ctx, 1); fmpz_mpoly_assert_canonical(h, ctx); sqr2 = fmpz_mpoly_sqrt_heap(g, g, ctx, 1); fmpz_mpoly_assert_canonical(g, ctx); if (sqr1 != sqr2 || !fmpz_mpoly_equal(g, h, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing\n"); fflush(stdout); flint_abort(); } sqr2 = fmpz_mpoly_sqrt_heap(k, k, ctx, 0); fmpz_mpoly_assert_canonical(k, ctx); if (sqr1 != sqr2 || !fmpz_mpoly_equal(k, h, ctx)) { printf("FAIL\n"); flint_printf("Check aliasing: nocheck\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-symmetric.c000066400000000000000000000022661461254215100212240ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_symmetric, state) { slong iter; /* todo; this does noting useful right now except verifying that the function can be called */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t F; slong nvars, n, k; slong vars[10]; fmpz_mpoly_ctx_init_rand(ctx, state, 4); nvars = ctx->minfo->nvars; n = n_randint(state, nvars + 1); for (k = 0; k < n; k++) vars[k] = k; k = n_randint(state, 5); fmpz_mpoly_init(F, ctx); fmpz_mpoly_symmetric_gens(F, k, vars, n, ctx); fmpz_mpoly_clear(F, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-term_content.c000066400000000000000000000075041461254215100217110ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_term_content, state) { int i, j, result; /* Check division by content leaves trivial content */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, k; slong len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 20); fmpz_mpoly_randtest_bits(k, state, len, coeff_bits, exp_bits, ctx); for (j = 0; j < 10; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_scalar_mul_ui(g, g, 1 + n_randint(state, 10), ctx); fmpz_mpoly_term_content(f, g, ctx); if (fmpz_mpoly_is_zero(g, ctx)) { result = fmpz_mpoly_is_zero(f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check zero\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } else { result = fmpz_mpoly_length(f, ctx) == 1; if (!result) { printf("FAIL\n"); flint_printf("Check content is monomial\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } result = fmpz_sgn(f->coeffs + 0) > 0; if (!result) { printf("FAIL\n"); flint_printf("Check content has positive lc\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } result = fmpz_mpoly_divides(k, g, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check content divides\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fmpz_mpoly_term_content(k, k, ctx); result = fmpz_mpoly_is_one(k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check quotient is primitive\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_term_content(g, g, ctx); result = fmpz_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing \ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-total_degree.c000066400000000000000000000116341461254215100216450ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" /* foolproof way to check totdeg_check is correct */ void _check_total_degree(const fmpz_t totdeg_check, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { fmpz_t totdeg; fmpz_init(totdeg); mpoly_total_degree_fmpz_ref(totdeg, A->exps, A->length, A->bits, ctx->minfo); if (!fmpz_equal(totdeg_check, totdeg)) flint_throw(FLINT_ERROR, "Total degree is wrong"); fmpz_clear(totdeg); } TEST_FUNCTION_START(fmpz_mpoly_total_degree, state) { int i, j; /* Check total_degree does not go up under addition */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_add(h, f, g, ctx); fmpz_mpoly_total_degree_fmpz(hdeg, h, ctx); fmpz_mpoly_total_degree_fmpz(fdeg, f, ctx); fmpz_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } /* Check total_degree adds under multiplication */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { int ok; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_mul_johnson(h, f, g, ctx); fmpz_mpoly_total_degree_fmpz(hdeg, h, ctx); fmpz_mpoly_total_degree_fmpz(fdeg, f, ctx); fmpz_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if (fmpz_mpoly_is_zero(f, ctx) || fmpz_mpoly_is_zero(g, ctx)) { ok = fmpz_equal_si(hdeg, -WORD(1)) && (fmpz_equal_si(fdeg, -WORD(1)) || fmpz_equal_si(gdeg, -WORD(1))); } else { fmpz_add(gdeg, gdeg, fdeg); ok = fmpz_equal(hdeg, gdeg); } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-univar.c000066400000000000000000000066631461254215100205210ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_univar, state) { slong i, j, k; /* Check mpoly -> mpoly_univar -> mpoly */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; fmpz_mpoly_univar_t fx, gx; slong len1, len2, n; flint_bitcnt_t coeff_bits, exp_bits1, exp_bits2, bits; fmpz_mpoly_ctx_init_rand(ctx, state, 15); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); fmpz_mpoly_univar_init(fx, ctx); fmpz_mpoly_univar_init(gx, ctx); len1 = n_randint(state, 200); len2 = n_randint(state, 200); exp_bits1 = n_randint(state, (i%2) ? 4 : 3*FLINT_BITS) + 1; exp_bits2 = n_randint(state, (i%2) ? 4 : 3*FLINT_BITS) + 1; coeff_bits = n_randint(state, 200); for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_to_univar(fx, f, j, ctx); fmpz_mpoly_univar_assert_canonical(fx, ctx); fmpz_mpoly_from_univar(g, fx, j, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!fmpz_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: Check mpoly -> mpoly_univar -> mpoly\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } bits = mpoly_fix_bits(f->bits + n_randint(state, FLINT_BITS), ctx->minfo); _fmpz_mpoly_from_univar(h, bits, fx, j, ctx); fmpz_mpoly_assert_canonical(h, ctx); if (h->bits != bits || !fmpz_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check mpoly -> mpoly_univar -> mpoly with bits\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_univar_degree_fits_si(fx, ctx)) continue; n = fmpz_mpoly_univar_length(fx, ctx); fmpz_mpoly_univar_fit_length(gx, n, ctx); gx->length = n; for (k = 0; k < n; k++) { fmpz_mpoly_univar_swap_term_coeff(gx->coeffs + k, fx, k, ctx); fmpz_set_si(gx->exps + k, fmpz_mpoly_univar_get_term_exp_si(fx, k, ctx)); } fmpz_mpoly_from_univar(g, gx, j, ctx); if (!fmpz_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: Check construction\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_univar_clear(gx, ctx); fmpz_mpoly_univar_clear(fx, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-univar_resultant.c000066400000000000000000000130341461254215100226100ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_mpoly.h" void test_resultant( const fmpz_mpoly_t fx, const fmpz_mpoly_t gx, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_univar_t F, G; fmpz_poly_t f, g; fmpz_mpoly_t R; fmpz_t r; fmpz_mpoly_univar_init(F, ctx); fmpz_mpoly_univar_init(G, ctx); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_mpoly_init(R, ctx); fmpz_init(r); fmpz_mpoly_get_fmpz_poly(f, fx, 0, ctx); fmpz_mpoly_get_fmpz_poly(g, gx, 0, ctx); fmpz_poly_resultant(r, f, g); fmpz_mpoly_to_univar(F, fx, 0, ctx); fmpz_mpoly_to_univar(G, gx, 0, ctx); fmpz_mpoly_univar_resultant(R, F, G, ctx); if (!fmpz_mpoly_equal_fmpz(R, r, ctx)) { flint_printf("FAIL: Check resultant against univariate\n"); flint_printf("fx: "); fmpz_mpoly_print_pretty(fx, NULL, ctx); flint_printf("\n"); flint_printf("gx: "); fmpz_mpoly_print_pretty(gx, NULL, ctx); flint_printf("\n"); flint_printf("R: "); fmpz_mpoly_print_pretty(R, NULL, ctx); flint_printf("\n"); flint_printf("r: "); fmpz_print(r); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_univar_clear(F, ctx); fmpz_mpoly_univar_clear(G, ctx); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_mpoly_clear(R, ctx); fmpz_clear(r); } TEST_FUNCTION_START(fmpz_mpoly_univar_resultant, state) { slong i, j; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t t, s; fmpz_mpoly_univar_t f; const char * vars[] = {"a", "b", "c", "d"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(s, ctx); fmpz_mpoly_univar_init(f, ctx); fmpz_mpoly_univar_zero(f, ctx); fmpz_mpoly_set_str_pretty(t, "a", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fmpz_mpoly_set_str_pretty(t, "b", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fmpz_mpoly_set_str_pretty(t, "1", vars, ctx); fmpz_mpoly_univar_discriminant(s, f, ctx); if (!fmpz_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check linear discriminant\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_univar_zero(f, ctx); fmpz_mpoly_set_str_pretty(t, "a", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 2, t, ctx); fmpz_mpoly_set_str_pretty(t, "b", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fmpz_mpoly_set_str_pretty(t, "c", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fmpz_mpoly_set_str_pretty(t, "b^2-4*a*c", vars, ctx); fmpz_mpoly_univar_discriminant(s, f, ctx); if (!fmpz_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check quadratic discriminant\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_univar_zero(f, ctx); fmpz_mpoly_set_str_pretty(t, "a", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 3, t, ctx); fmpz_mpoly_set_str_pretty(t, "b", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 2, t, ctx); fmpz_mpoly_set_str_pretty(t, "c", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fmpz_mpoly_set_str_pretty(t, "d", vars, ctx); fmpz_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fmpz_mpoly_set_str_pretty(t, "b^2*c^2-4*a*c^3-4*b^3*d-27*a^2*d^2+18*a*b*c*d", vars, ctx); fmpz_mpoly_univar_discriminant(s, f, ctx); if (!fmpz_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check cubic discriminant\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(s, ctx); fmpz_mpoly_univar_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < 5 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, t; fmpz_mpoly_ctx_init_rand(ctx, state, 1); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(t, ctx); for (j = 0; j < 5; j++) { fmpz_mpoly_randtest_bound(f, state, 3, n_randint(state, 100) + 1, 3, ctx); if (fmpz_mpoly_is_zero(f, ctx)) fmpz_mpoly_one(f, ctx); fmpz_mpoly_zero(g, ctx); if (fmpz_mpoly_ctx_nvars(ctx) < 1) continue; while (fmpz_mpoly_degree_si(f, 0, ctx) < 100) { fmpz_mpoly_randtest_bound(t, state, 5, n_randint(state, 100) + 1, 10, ctx); fmpz_mpoly_mul(t, t, f, ctx); fmpz_mpoly_add(g, g, t, ctx); fmpz_mpoly_swap(f, g, ctx); } fmpz_mpoly_randtest_bound(f, state, 20, n_randint(state, 100) + 1, 50, ctx); fmpz_mpoly_randtest_bound(g, state, 20, n_randint(state, 100) + 1, 50, ctx); test_resultant(f, g, ctx); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-used_vars.c000066400000000000000000000045161461254215100212030ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_used_vars, state) { slong i, j, k; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_t one, fdeg; slong len, var; flint_bitcnt_t coeff_bits, exp_bits; int * used; fmpz_mpoly_ctx_init_rand(ctx, state, 20); fmpz_mpoly_init(f, ctx); fmpz_init(fdeg); fmpz_init_set_ui(one, 1); used = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, int); for (j = 0; j < ctx->minfo->nvars; j++) { len = n_randint(state, 200); exp_bits = n_randint(state, 200) + 2; coeff_bits = n_randint(state, 100); fmpz_mpoly_randtest_bits(f, state, len, coeff_bits, exp_bits, ctx); for (k = n_randint(state, ctx->minfo->nvars); k > 0; k--) { var = n_randint(state, ctx->minfo->nvars); if (!fmpz_mpoly_evaluate_one_fmpz(f, f, var, one, ctx)) { flint_printf("FAIL: check evaluation success\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_used_vars(used, f, ctx); for (var = 0; var < ctx->minfo->nvars; var++) { fmpz_mpoly_degree_fmpz(fdeg, f, var, ctx); if ((fmpz_sgn(fdeg) <= 0) != !used[var]) { flint_printf("FAIL: checked used matches degree\n"); flint_printf("var = %wd\n", var); flint_printf("deg: "); fmpz_print(fdeg); flint_printf("\n"); fflush(stdout); flint_abort(); } } } flint_free(used); fmpz_clear(one); fmpz_clear(fdeg); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/test/t-vec_autoreduction.c000066400000000000000000000027501461254215100227300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(fmpz_mpoly_vec_autoreduction, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_vec_t F, G; fmpz_mpoly_ctx_init_rand(ctx, state, 4); fmpz_mpoly_vec_init(F, 0, ctx); fmpz_mpoly_vec_init(G, 0, ctx); fmpz_mpoly_vec_randtest_not_zero(F, state, 1 + n_randint(state, 5), 1 + n_randint(state, 4), 1 + n_randint(state, 3), 1 + n_randint(state, 2), ctx); fmpz_mpoly_vec_autoreduction(G, F, ctx); if (!fmpz_mpoly_vec_is_autoreduced(G, ctx)) { flint_printf("FAIL\n\n"); mpoly_ordering_print(ctx->minfo->ord); printf("\n"); flint_printf("F = "); fmpz_mpoly_vec_print(F, ctx); flint_printf("\n"); flint_printf("G = "); fmpz_mpoly_vec_print(G, ctx); flint_printf("\n"); flint_abort(); } fmpz_mpoly_vec_clear(F, ctx); fmpz_mpoly_vec_clear(G, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly/to_from_fmpz_poly.c000066400000000000000000000141631461254215100215330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" /* assuming that the conversion can be done, set poly1 and poly1_shift so that poly2 is poly1 * X^poly1_shift TODO: handle multiprecision exponents */ void fmpz_mpoly_to_fmpz_poly(fmpz_poly_t poly1, slong * poly1_shift, const fmpz_mpoly_t poly2, slong var, const fmpz_mpoly_ctx_t ctx) { slong i, shift, off, bits, N; ulong k; slong _shift = 0, len = poly2->length; fmpz * coeff = poly2->coeffs; ulong * exp = poly2->exps; if (poly2->bits > FLINT_BITS) flint_throw(FLINT_EXPOF, "Bits too high in fmpz_mpoly_to_fmpz_poly"); bits = poly2->bits; N = mpoly_words_per_exp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo); fmpz_poly_zero(poly1); if (len > 0) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); _shift = (exp[N*(len - 1)] >> shift) & mask; for (i = 0; i < len; i++) { k = (exp[N*i + off] >> shift) & mask; k -= _shift; FLINT_ASSERT(((slong)k) >= 0); fmpz_poly_set_coeff_fmpz(poly1, k, coeff + i); } } *poly1_shift = _shift; } /* set poly1 to poly2 * X^shift2 in the variable var */ void fmpz_mpoly_from_fmpz_poly(fmpz_mpoly_t poly1, const fmpz_poly_t poly2, slong shift2, slong var, const fmpz_mpoly_ctx_t ctx) { flint_bitcnt_t bits; slong N; slong k; slong p_len; fmpz * p_coeff; ulong * p_exp; slong p_alloc; ulong * one; TMP_INIT; TMP_START; bits = 1 + FLINT_BIT_COUNT(FLINT_MAX(WORD(1), shift2 + fmpz_poly_degree(poly2))); if (bits > FLINT_BITS) flint_throw(FLINT_EXPOF, "Exponent overflow in fmpz_mpoly_from_fmpz_poly"); bits = mpoly_fix_bits(bits, ctx->minfo); N = mpoly_words_per_exp_sp(bits, ctx->minfo); one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_sp(one, var,bits, ctx->minfo); fmpz_mpoly_fit_bits(poly1, bits, ctx); poly1->bits = bits; p_coeff = poly1->coeffs; p_exp = poly1->exps; p_alloc = poly1->alloc; p_len = 0; for (k = fmpz_poly_degree(poly2); k >= 0; k--) { _fmpz_mpoly_fit_length(&p_coeff, &p_exp, &p_alloc, p_len + 1, N); mpoly_monomial_mul_ui(p_exp + N*p_len, one, N, k + shift2); fmpz_poly_get_coeff_fmpz(p_coeff + p_len, poly2, k); p_len += !fmpz_is_zero(p_coeff + p_len); } poly1->coeffs = p_coeff; poly1->exps = p_exp; poly1->alloc = p_alloc; _fmpz_mpoly_set_length(poly1, p_len, ctx); TMP_END; } /* set A(x_var^Bstride[var]) to B/xbar^Bshifts it is asserted that the conversion is correct */ void _fmpz_mpoly_to_fmpz_poly_deflate( fmpz_poly_t A, const fmpz_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const fmpz_mpoly_ctx_t ctx) { ulong mask; slong i, shift, off, N; slong len = B->length; fmpz * coeff = B->coeffs; ulong * exp = B->exps; ulong var_shift, var_stride; flint_bitcnt_t bits = B->bits; FLINT_ASSERT(len > 0); FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo); fmpz_poly_zero(A); mask = (-UWORD(1)) >> (FLINT_BITS - bits); var_shift = Bshift[var]; var_stride = Bstride[var]; for (i = 0; i < len; i++) { ulong k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT(k >= var_shift); k -= var_shift; if (k != 0) { k /= var_stride; } fmpz_poly_set_coeff_fmpz(A, k, coeff + i); } #if FLINT_WANT_ASSERT for (i = 0; i < len; i++) { slong v; for (v = 0; v < ctx->minfo->nvars; v++) { ulong k; mpoly_gen_offset_shift_sp(&off, &shift, v, bits, ctx->minfo); k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT( (v == var && k >= Bshift[v]) || (v != var && k == Bshift[v])); } } #endif } /* set A to B(x_var^Astride[var])*xbar^Ashift A must be packed into bits = Abits */ void _fmpz_mpoly_from_fmpz_poly_inflate( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const fmpz_mpoly_ctx_t ctx) { slong N; slong k; slong Alen; fmpz * Acoeff; ulong * Aexp; slong Aalloc; ulong * shiftexp; ulong * strideexp; slong Bdeg = fmpz_poly_degree(B); TMP_INIT; TMP_START; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(!fmpz_poly_is_zero(B)); /* must have at least space for the highest exponent of var */ FLINT_ASSERT(1 + FLINT_BIT_COUNT(Ashift[var] + Bdeg*Astride[var]) <= Abits); N = mpoly_words_per_exp(Abits, ctx->minfo); strideexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); shiftexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ui(shiftexp, Ashift, Abits, ctx->minfo); mpoly_gen_monomial_sp(strideexp, var, Abits, ctx->minfo); mpoly_monomial_mul_ui(strideexp, strideexp, N, Astride[var]); fmpz_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; Acoeff = A->coeffs; Aexp = A->exps; Aalloc = A->alloc; Alen = 0; for (k = Bdeg; k >= 0; k--) { _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N); fmpz_poly_get_coeff_fmpz(Acoeff + Alen, B, k); if (!fmpz_is_zero(Acoeff + Alen)) { mpoly_monomial_madd(Aexp + N*Alen, shiftexp, k, strideexp, N); Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; A->alloc = Aalloc; _fmpz_mpoly_set_length(A, Alen, ctx); TMP_END; } flint-3.1.3/src/fmpz_mpoly/univar.c000066400000000000000000000444661461254215100173040ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" void fmpz_mpoly_univar_init(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; } void fmpz_mpoly_univar_clear(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) { fmpz_mpoly_clear(A->coeffs + i, ctx); fmpz_clear(A->exps + i); } if (A->coeffs) flint_free(A->coeffs); if (A->exps) flint_free(A->exps); } void fmpz_mpoly_univar_fit_length(fmpz_mpoly_univar_t A, slong length, const fmpz_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { if (old_alloc == 0) { A->exps = (fmpz *) flint_malloc(new_alloc*sizeof(fmpz)); A->coeffs = (fmpz_mpoly_struct *) flint_malloc( new_alloc*sizeof(fmpz_mpoly_struct)); } else { A->exps = (fmpz *) flint_realloc(A->exps, new_alloc*sizeof(fmpz)); A->coeffs = (fmpz_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fmpz_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) { fmpz_init(A->exps + i); fmpz_mpoly_init(A->coeffs + i, ctx); } A->alloc = new_alloc; } } void fmpz_mpoly_univar_set_coeff_ui( fmpz_mpoly_univar_t A, ulong e, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx) { slong i, j; for (i = A->length; i >= 0; i--) { int cmp = i > 0 ? fmpz_cmp_ui(A->exps + i - 1, e) : 1; if (cmp > 0) { if (fmpz_mpoly_is_zero(c, ctx)) return; fmpz_mpoly_univar_fit_length(A, A->length + 1, ctx); for (j = A->length; j > i; j--) { fmpz_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } A->length++; fmpz_set_ui(A->exps + i, e); fmpz_mpoly_set(A->coeffs + i, c, ctx); return; } else if (cmp == 0) { fmpz_mpoly_set(A->coeffs + i, c, ctx); if (!fmpz_mpoly_is_zero(A->coeffs + i, ctx)) return; A->length--; for (j = i; j < A->length; j++) { fmpz_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } } } FLINT_ASSERT(0 && "unreachable"); return; } int fmpz_mpoly_univar_degree_fits_si(const fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) { return A->length == 0 || fmpz_fits_si(A->exps + 0); } slong fmpz_mpoly_univar_get_term_exp_si(fmpz_mpoly_univar_t A, slong i, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); return fmpz_get_si(A->exps + i); } void fmpz_mpoly_univar_assert_canonical(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i + 1 < A->length; i++) { if (fmpz_cmp(A->exps + i, A->exps + i + 1) <= 0 || fmpz_sgn(A->exps + i) < 0 || fmpz_sgn(A->exps + i + 1) < 0) { flint_throw(FLINT_ERROR, "Univariate polynomial exponents out of order"); } } for (i = 0; i < A->length; i++) fmpz_mpoly_assert_canonical(A->coeffs + i, ctx); } void fmpz_mpoly_univar_print_pretty(const fmpz_mpoly_univar_t A, const char ** x, const fmpz_mpoly_ctx_t ctx) { slong i; if (A->length == 0) flint_printf("0"); for (i = 0; i < A->length; i++) { if (i != 0) flint_printf("+"); flint_printf("("); fmpz_mpoly_print_pretty(A->coeffs + i,x,ctx); flint_printf(")*X^"); fmpz_print(A->exps + i); } } static void _tree_data_clear_sp( fmpz_mpoly_univar_t A, mpoly_rbtree_ui_t tree, slong idx, const fmpz_mpoly_ctx_t ctx) { mpoly_rbnode_ui_struct * nodes = tree->nodes + 2; fmpz_mpoly_struct * data = (fmpz_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_sp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set_ui(A->exps + A->length, nodes[idx].key); fmpz_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fmpz_mpoly_clear(data + idx, ctx); _tree_data_clear_sp(A, tree, nodes[idx].left, ctx); } static void _tree_data_clear_mp( fmpz_mpoly_univar_t A, mpoly_rbtree_fmpz_t tree, slong idx, const fmpz_mpoly_ctx_t ctx) { mpoly_rbnode_fmpz_struct * nodes = tree->nodes + 2; fmpz_mpoly_struct * data = (fmpz_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_mp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set(A->exps + A->length, nodes[idx].key); fmpz_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fmpz_mpoly_clear(data + idx, ctx); _tree_data_clear_mp(A, tree, nodes[idx].left, ctx); } /* the coefficients of A should be constructed with the same bits as B */ void fmpz_mpoly_to_univar(fmpz_mpoly_univar_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx) { flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong shift, off; slong Blen = B->length; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; slong i; int its_new; ulong * one; #define LUT_limit (48) fmpz_mpoly_struct LUT[LUT_limit]; if (B->length == 0) { A->length = 0; return; } one = FLINT_ARRAY_ALLOC(N, ulong); if (bits <= FLINT_BITS) { slong Alen; mpoly_rbtree_ui_t tree; fmpz_mpoly_struct * d; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); mpoly_rbtree_ui_init(tree, sizeof(fmpz_mpoly_struct)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); for (i = 0; i < LUT_limit; i++) fmpz_mpoly_init3(LUT + i, 4, bits, ctx); /* fill in tree/LUT from B */ for (i = 0; i < Blen; i++) { ulong k = (Bexp[N*i + off] >> shift) & mask; if (k < LUT_limit) { d = LUT + k; } else { d = mpoly_rbtree_ui_lookup(tree, &its_new, k); if (its_new) fmpz_mpoly_init3(d, 4, bits, ctx); } fmpz_mpoly_fit_length(d, d->length + 1, ctx); fmpz_set(d->coeffs + d->length, Bcoeff + i); mpoly_monomial_msub(d->exps + N*d->length, Bexp + N*i, k, one, N); d->length++; } /* clear out tree to A */ Alen = tree->length; for (i = LUT_limit - 1; i >= 0; i--) Alen += (LUT[i].length > 0); fmpz_mpoly_univar_fit_length(A, Alen, ctx); A->length = 0; _tree_data_clear_sp(A, tree, mpoly_rbtree_ui_head(tree), ctx); for (i = LUT_limit - 1; i >= 0; i--) { d = LUT + i; if (d->length > 0) { FLINT_ASSERT(A->length < A->alloc); fmpz_set_si(A->exps + A->length, i); fmpz_mpoly_swap(A->coeffs + A->length, d, ctx); A->length++; } fmpz_mpoly_clear(d, ctx); } mpoly_rbtree_ui_clear(tree); } else { mpoly_rbtree_fmpz_t tree; fmpz_mpoly_struct * d; fmpz_t k; fmpz_init(k); mpoly_rbtree_fmpz_init(tree, sizeof(fmpz_mpoly_struct)); off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); /* fill in tree from B */ for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexp + N*i + off, bits/FLINT_BITS); d = mpoly_rbtree_fmpz_lookup(tree, &its_new, k); if (its_new) fmpz_mpoly_init3(d, 4, bits, ctx); fmpz_mpoly_fit_length(d, d->length + 1, ctx); fmpz_set(d->coeffs + d->length, Bcoeff + i); mpoly_monomial_msub_ui_array(d->exps + N*d->length, Bexp + N*i, Bexp + N*i + off, bits/FLINT_BITS, one, N); d->length++; } /* clear out tree to A */ fmpz_mpoly_univar_fit_length(A, tree->length, ctx); A->length = 0; _tree_data_clear_mp(A, tree, mpoly_rbtree_fmpz_head(tree), ctx); fmpz_clear(k); mpoly_rbtree_fmpz_clear(tree); } flint_free(one); } /* Currently this function does not work if the coefficients depend on "var". The assertion x->next == NULL would need to be replaced by a loop. Other asserts would need to be removed as well. */ void _fmpz_mpoly_from_univar(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_univar_t B, slong var, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i; slong next_loc, heap_len = 1; ulong * cmpmask; slong total_len; mpoly_heap_s * heap; slong Alen; ulong ** Btexp; ulong * exp; ulong * one; mpoly_heap_t * chain, * x; TMP_INIT; if (B->length == 0) { fmpz_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; _fmpz_mpoly_set_length(A, 0, ctx); return; } TMP_START; /* pack everything into Abits */ one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); Btexp = (ulong **) TMP_ALLOC(B->length*sizeof(ulong*)); total_len = 0; for (i = 0; i < B->length; i++) { fmpz_mpoly_struct * Bi = B->coeffs + i; total_len += Bi->length; Btexp[i] = Bi->exps; if (Abits != Bi->bits) { Btexp[i] = (ulong *) flint_malloc(N*Bi->length*sizeof(ulong)); if (!mpoly_repack_monomials(Btexp[i], Abits, Bi->exps, Bi->bits, Bi->length, ctx->minfo)) { FLINT_ASSERT(0 && "repack does not fit"); } } } fmpz_mpoly_fit_length(A, total_len, ctx); fmpz_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; next_loc = B->length + 2; heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); exp = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); Alen = 0; if (Abits <= FLINT_BITS) { mpoly_gen_monomial_sp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { FLINT_ASSERT(fmpz_fits_si(B->exps + i)); x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + i), one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fmpz_set(A->coeffs + Alen, (B->coeffs + x->i)->coeffs + x->j); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { FLINT_ASSERT(fmpz_fits_si(B->exps + x->i)); x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + x->i), one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } else { mpoly_gen_monomial_offset_mp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + i, one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fmpz_set(A->coeffs + Alen, (B->coeffs + x->i)->coeffs + x->j); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + x->i, one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } _fmpz_mpoly_set_length(A, Alen, ctx); for (i = 0; i < B->length; i++) { if (Btexp[i] != (B->coeffs + i)->exps) flint_free(Btexp[i]); } TMP_END; } void fmpz_mpoly_from_univar(fmpz_mpoly_t A, const fmpz_mpoly_univar_t B, slong var, const fmpz_mpoly_ctx_t ctx) { slong n = ctx->minfo->nfields; flint_bitcnt_t bits; slong i; fmpz * gen_fields, * tmp_fields, * max_fields; TMP_INIT; if (B->length == 0) { fmpz_mpoly_zero(A, ctx); return; } TMP_START; /* find bits required to represent result */ gen_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); tmp_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(gen_fields + i); fmpz_init(tmp_fields + i); fmpz_init(max_fields + i); } mpoly_gen_fields_fmpz(gen_fields, var, ctx->minfo); for (i = 0; i < B->length; i++) { fmpz_mpoly_struct * Bi = B->coeffs + i; mpoly_max_fields_fmpz(tmp_fields, Bi->exps, Bi->length, Bi->bits, ctx->minfo); _fmpz_vec_scalar_addmul_fmpz(tmp_fields, gen_fields, n, B->exps + i); _fmpz_vec_max_inplace(max_fields, tmp_fields, n); } bits = _fmpz_vec_max_bits(max_fields, n); bits = FLINT_MAX(MPOLY_MIN_BITS, bits + 1); bits = mpoly_fix_bits(bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(gen_fields + i); fmpz_clear(tmp_fields + i); fmpz_clear(max_fields + i); } TMP_END; _fmpz_mpoly_from_univar(A, bits, B, var, ctx); } #define COEFF(A, i) ((void*)(A->coeffs + (i)*R->elem_size)) static void mpoly_univar_set_fmpz_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, const fmpz_mpoly_univar_t B, const fmpz_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); A->length = B->length; for (i = B->length - 1; i >= 0; i--) { fmpz_set(A->exps + i, B->exps + i); fmpz_mpoly_set(COEFF(A, i), B->coeffs + i, ctx); } } static void mpoly_univar_swap_fmpz_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, fmpz_mpoly_univar_t B, const fmpz_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); fmpz_mpoly_univar_fit_length(B, A->length, ctx); for (i = FLINT_MAX(A->length, B->length) - 1; i >= 0; i--) { fmpz_swap(A->exps + i, B->exps + i); fmpz_mpoly_swap(COEFF(A, i), B->coeffs + i, ctx); } FLINT_SWAP(slong, A->length, B->length); } int fmpz_mpoly_univar_pseudo_gcd( fmpz_mpoly_univar_t gx, const fmpz_mpoly_univar_t ax, const fmpz_mpoly_univar_t bx, const fmpz_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx, Gx; mpoly_void_ring_init_fmpz_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_init(Gx, R); mpoly_univar_set_fmpz_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_fmpz_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_pseudo_gcd_ducos(Gx, Ax, Bx, R); if (success) mpoly_univar_swap_fmpz_mpoly_univar(Gx, R, gx, ctx); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); mpoly_univar_clear(Gx, R); return success; } int fmpz_mpoly_univar_resultant( fmpz_mpoly_t d, const fmpz_mpoly_univar_t ax, const fmpz_mpoly_univar_t bx, const fmpz_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx; mpoly_void_ring_init_fmpz_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_set_fmpz_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_fmpz_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_resultant(d, Ax, Bx, R); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); return success; } int fmpz_mpoly_univar_discriminant( fmpz_mpoly_t d, const fmpz_mpoly_univar_t fx, const fmpz_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Fx; mpoly_void_ring_init_fmpz_mpoly_ctx(R, ctx); mpoly_univar_init(Fx, R); mpoly_univar_set_fmpz_mpoly_univar(Fx, R, fx, ctx); success = mpoly_univar_discriminant(d, Fx, R); mpoly_univar_clear(Fx, R); return success; } flint-3.1.3/src/fmpz_mpoly/vec.c000066400000000000000000000062771461254215100165530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_vec_init(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx) { if (len == 0) { vec->p = NULL; vec->length = 0; vec->alloc = 0; } else { slong i; vec->p = flint_malloc(sizeof(fmpz_mpoly_struct) * len); for (i = 0; i < len; i++) fmpz_mpoly_init(vec->p + i, ctx); vec->length = vec->alloc = len; } } void fmpz_mpoly_vec_print(const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) { slong i; flint_printf("["); for (i = 0; i < F->length; i++) { fmpz_mpoly_print_pretty(F->p + i, NULL, ctx); if (i < F->length - 1) flint_printf(", "); } flint_printf("]"); } void fmpz_mpoly_vec_swap(fmpz_mpoly_vec_t x, fmpz_mpoly_vec_t y, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_vec_t tmp; *tmp = *x; *x = *y; *y = *tmp; } void fmpz_mpoly_vec_fit_length(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx) { if (len > vec->alloc) { slong i; if (len < 2 * vec->alloc) len = 2 * vec->alloc; vec->p = flint_realloc(vec->p, len * sizeof(fmpz_mpoly_struct)); for (i = vec->alloc; i < len; i++) fmpz_mpoly_init(vec->p + i, ctx); vec->alloc = len; } } void fmpz_mpoly_vec_clear(fmpz_mpoly_vec_t vec, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < vec->alloc; i++) fmpz_mpoly_clear(vec->p + i, ctx); flint_free(vec->p); } void fmpz_mpoly_vec_set(fmpz_mpoly_vec_t dest, const fmpz_mpoly_vec_t src, const fmpz_mpoly_ctx_t ctx) { if (dest != src) { slong i; fmpz_mpoly_vec_fit_length(dest, src->length, ctx); for (i = 0; i < src->length; i++) fmpz_mpoly_set(dest->p + i, src->p + i, ctx); dest->length = src->length; } } void fmpz_mpoly_vec_append(fmpz_mpoly_vec_t vec, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_vec_fit_length(vec, vec->length + 1, ctx); fmpz_mpoly_set(vec->p + vec->length, f, ctx); vec->length++; } slong fmpz_mpoly_vec_insert_unique(fmpz_mpoly_vec_t vec, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < vec->length; i++) { if (fmpz_mpoly_equal(vec->p + i, f, ctx)) return i; } fmpz_mpoly_vec_append(vec, f, ctx); return vec->length - 1; } void fmpz_mpoly_vec_randtest_not_zero(fmpz_mpoly_vec_t vec, flint_rand_t state, slong len, slong poly_len, slong bits, ulong exp_bound, fmpz_mpoly_ctx_t ctx) { slong i; fmpz_mpoly_vec_set_length(vec, len, ctx); for (i = 0; i < len; i++) { do { fmpz_mpoly_randtest_bound(vec->p + i, state, poly_len, bits, exp_bound, ctx); } while (fmpz_mpoly_is_zero(vec->p + i, ctx)); } vec->length = len; } flint-3.1.3/src/fmpz_mpoly/vec_autoreduction.c000066400000000000000000000066121461254215100215110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_vec_autoreduction(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t Gin, const fmpz_mpoly_ctx_t ctx) { slong i, j; if (G != Gin) fmpz_mpoly_vec_set(G, Gin, ctx); /* Content removal */ for (i = 0; i < G->length; i++) fmpz_mpoly_primitive_part(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, i), ctx); /* Make sure there are no duplicate or zero entries */ for (i = 0; i < G->length; i++) { if (fmpz_mpoly_is_zero(fmpz_mpoly_vec_entry(G, i), ctx)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, G->length - 1), ctx); fmpz_mpoly_vec_set_length(G, G->length - 1, ctx); } else { for (j = i + 1; j < G->length; j++) { if (fmpz_mpoly_equal(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, j), ctx)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, j), fmpz_mpoly_vec_entry(G, G->length - 1), ctx); fmpz_mpoly_vec_set_length(G, G->length - 1, ctx); } } } } /* Now do inter-reduction */ if (G->length >= 2) { fmpz_t scale; fmpz_mpoly_struct ** Q, ** B; fmpz_mpoly_t h; slong alloc; int changed; alloc = G->length - 1; fmpz_init(scale); fmpz_mpoly_init(h, ctx); Q = flint_malloc(sizeof(fmpz_mpoly_struct *) * alloc); B = flint_malloc(sizeof(fmpz_mpoly_struct *) * alloc); for (i = 0; i < alloc; i++) { Q[i] = flint_malloc(sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(Q[i], ctx); } while (G->length >= 2) { changed = 0; for (i = 0; i < G->length; i++) { for (j = 0; j < i; j++) B[j] = fmpz_mpoly_vec_entry(G, j); for (j = i + 1; j < G->length; j++) B[j - 1] = fmpz_mpoly_vec_entry(G, j); fmpz_mpoly_quasidivrem_ideal(scale, Q, h, fmpz_mpoly_vec_entry(G, i), B, G->length - 1, ctx); fmpz_mpoly_primitive_part(h, h, ctx); if (!fmpz_mpoly_equal(h, fmpz_mpoly_vec_entry(G, i), ctx)) { changed = 1; fmpz_mpoly_swap(h, fmpz_mpoly_vec_entry(G, i), ctx); } if (fmpz_mpoly_is_zero(fmpz_mpoly_vec_entry(G, i), ctx)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, G->length - 1), ctx); fmpz_mpoly_vec_set_length(G, G->length - 1, ctx); i--; } } if (!changed) break; } for (i = 0; i < alloc; i++) { fmpz_mpoly_clear(Q[i], ctx); flint_free(Q[i]); } flint_free(Q); flint_free(B); fmpz_clear(scale); fmpz_mpoly_clear(h, ctx); } } flint-3.1.3/src/fmpz_mpoly/vec_autoreduction_groebner.c000066400000000000000000000101171461254215100233670ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" static int monomial_divides(const ulong * exp1, const ulong * exp2, slong nvars) { slong i; for (i = 0; i < nvars; i++) if (exp1[i] > exp2[i]) return 0; return 1; } void fmpz_mpoly_vec_autoreduction_groebner(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t Gin, const fmpz_mpoly_ctx_t ctx) { slong i, j, nvars; ulong * exp1, * exp2; if (G != Gin) fmpz_mpoly_vec_set(G, Gin, ctx); /* Content removal */ for (i = 0; i < G->length; i++) fmpz_mpoly_primitive_part(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, i), ctx); /* Make sure there are no duplicate or zero entries */ for (i = 0; i < G->length; i++) { if (fmpz_mpoly_is_zero(fmpz_mpoly_vec_entry(G, i), ctx)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, G->length - 1), ctx); fmpz_mpoly_vec_set_length(G, G->length - 1, ctx); } else { for (j = i + 1; j < G->length; j++) { if (fmpz_mpoly_equal(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, j), ctx)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, j), fmpz_mpoly_vec_entry(G, G->length - 1), ctx); fmpz_mpoly_vec_set_length(G, G->length - 1, ctx); } } } } if (G->length <= 1) return; /* First filter based on divisibility of leading terms */ nvars = ctx->minfo->nvars; exp1 = flint_malloc(nvars * sizeof(ulong)); exp2 = flint_malloc(nvars * sizeof(ulong)); for (i = 0; i < G->length; i++) { fmpz_mpoly_get_term_exp_ui(exp1, fmpz_mpoly_vec_entry(G, i), 0, ctx); for (j = 0; j < G->length; j++) { if (i != j) { fmpz_mpoly_get_term_exp_ui(exp2, fmpz_mpoly_vec_entry(G, j), 0, ctx); if (monomial_divides(exp2, exp1, nvars)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, G->length - 1), ctx); fmpz_mpoly_vec_set_length(G, G->length - 1, ctx); break; } } } } flint_free(exp1); flint_free(exp2); /* Now do inter-reduction */ if (G->length >= 2) { fmpz_t scale; fmpz_mpoly_struct ** Q, ** B; slong i, j, alloc; alloc = G->length - 1; fmpz_init(scale); Q = flint_malloc(sizeof(fmpz_mpoly_struct *) * alloc); B = flint_malloc(sizeof(fmpz_mpoly_struct *) * alloc); for (i = 0; i < alloc; i++) { Q[i] = flint_malloc(sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(Q[i], ctx); } for (i = 0; i < G->length; i++) { for (j = 0; j < i; j++) B[j] = fmpz_mpoly_vec_entry(G, j); for (j = i + 1; j < G->length; j++) B[j - 1] = fmpz_mpoly_vec_entry(G, j); fmpz_mpoly_quasidivrem_ideal(scale, Q, fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, i), B, G->length - 1, ctx); fmpz_mpoly_primitive_part(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, i), ctx); if (fmpz_mpoly_is_zero(fmpz_mpoly_vec_entry(G, i), ctx)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, G->length - 1), ctx); fmpz_mpoly_vec_set_length(G, G->length - 1, ctx); i--; } } for (i = 0; i < alloc; i++) { fmpz_mpoly_clear(Q[i], ctx); flint_free(Q[i]); } flint_free(Q); flint_free(B); fmpz_clear(scale); } } flint-3.1.3/src/fmpz_mpoly/vec_is_autoreduced.c000066400000000000000000000033351461254215100216220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly.h" int fmpz_mpoly_vec_is_autoreduced(const fmpz_mpoly_vec_t G, const fmpz_mpoly_ctx_t ctx) { slong i, j, len, alloc; fmpz_mpoly_t h; fmpz_t scale; fmpz_mpoly_struct ** Q, ** B; int result; len = G->length; alloc = len - 1; if (len == 0) return 1; fmpz_init(scale); Q = flint_malloc(sizeof(fmpz_mpoly_struct *) * alloc); B = flint_malloc(sizeof(fmpz_mpoly_struct *) * alloc); for (i = 0; i < alloc; i++) { Q[i] = flint_malloc(sizeof(fmpz_mpoly_struct)); fmpz_mpoly_init(Q[i], ctx); } fmpz_mpoly_init(h, ctx); result = 1; for (i = 0; i < len && result; i++) { for (j = 0; j < i; j++) B[j] = fmpz_mpoly_vec_entry(G, j); for (j = i + 1; j < G->length; j++) B[j - 1] = fmpz_mpoly_vec_entry(G, j); fmpz_mpoly_quasidivrem_ideal(scale, Q, h, fmpz_mpoly_vec_entry(G, i), B, G->length - 1, ctx); fmpz_mpoly_primitive_part(h, h, ctx); if (fmpz_mpoly_is_zero(h, ctx) || !fmpz_mpoly_equal(h, fmpz_mpoly_vec_entry(G, i), ctx)) result = 0; } for (i = 0; i < alloc; i++) { fmpz_mpoly_clear(Q[i], ctx); flint_free(Q[i]); } fmpz_mpoly_clear(h, ctx); flint_free(Q); flint_free(B); fmpz_clear(scale); return result; } flint-3.1.3/src/fmpz_mpoly/vec_is_groebner.c000066400000000000000000000025061461254215100211200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int fmpz_mpoly_vec_is_groebner(const fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) { slong i, j, len; fmpz_mpoly_t h; int result; len = G->length; if (len == 0) return 1; fmpz_mpoly_init(h, ctx); result = 1; for (i = 0; i < len && result; i++) { for (j = i + 1; j < len && result; j++) { fmpz_mpoly_spoly(h, fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, j), ctx); fmpz_mpoly_reduction_primitive_part(h, h, G, ctx); if (!fmpz_mpoly_is_zero(h, ctx)) result = 0; } } if (F != NULL) { for (i = 0; i < F->length && result; i++) { fmpz_mpoly_reduction_primitive_part(h, fmpz_mpoly_vec_entry(F, i), G, ctx); if (!fmpz_mpoly_is_zero(h, ctx)) result = 0; } } fmpz_mpoly_clear(h, ctx); return result; } flint-3.1.3/src/fmpz_mpoly/vec_set_length.c000066400000000000000000000015261461254215100207570ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_vec_set_length(fmpz_mpoly_vec_t vec, slong len, const fmpz_mpoly_ctx_t ctx) { slong i; if (len > vec->length) { fmpz_mpoly_vec_fit_length(vec, len, ctx); for (i = vec->length; i < len; i++) fmpz_mpoly_zero(vec->p + i, ctx); } else if (len < vec->length) { for (i = len; i < vec->length; i++) fmpz_mpoly_zero(vec->p + i, ctx); } vec->length = len; } flint-3.1.3/src/fmpz_mpoly/vec_set_primitive_unique.c000066400000000000000000000030161461254215100230700ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_vec_set_primitive_unique(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx) { slong i, j, len; fmpz_mpoly_vec_set(G, F, ctx); len = G->length; for (i = 0; i < len; i++) { /* skip zero */ if (fmpz_mpoly_is_zero(fmpz_mpoly_vec_entry(G, i), ctx)) { fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, len - 1), ctx); G->length--; len--; i--; } else { fmpz_mpoly_primitive_part(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, i), ctx); for (j = 0; j < i; j++) { if (fmpz_mpoly_equal(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, j), ctx)) { fmpz_mpoly_zero(fmpz_mpoly_vec_entry(G, i), ctx); fmpz_mpoly_swap(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, len - 1), ctx); G->length--; len--; i--; break; } } } } } flint-3.1.3/src/fmpz_mpoly/void_ring.c000066400000000000000000000071651461254215100177530ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" static void fmpz_mpoly_void_init(void * a, const void * ctx) { fmpz_mpoly_init(a, ctx); } static void fmpz_mpoly_void_clear(void * a, const void * ctx) { fmpz_mpoly_clear(a, ctx); } static int fmpz_mpoly_void_is_zero(const void * a, const void * ctx) { return fmpz_mpoly_is_zero(a, ctx); } static void fmpz_mpoly_void_zero(void * a, const void * ctx) { fmpz_mpoly_zero(a, ctx); } static void fmpz_mpoly_void_one(void * a, const void * ctx) { fmpz_mpoly_one(a, ctx); } static void fmpz_mpoly_void_set(void * a, const void * b, const void * ctx) { fmpz_mpoly_set(a, b, ctx); } static void fmpz_mpoly_void_set_fmpz(void * a, const fmpz_t b, const void * ctx) { fmpz_mpoly_set_fmpz(a, b, ctx); } static void fmpz_mpoly_void_swap(void * a, void * b, const void * ctx) { fmpz_mpoly_swap(a, b, ctx); } static void fmpz_mpoly_void_neg(void * a, const void * b, const void * ctx) { fmpz_mpoly_neg(a, b, ctx); } static void fmpz_mpoly_void_add(void * a, const void * b, const void * c, const void * ctx) { fmpz_mpoly_add(a, b, c, ctx); } static void fmpz_mpoly_void_sub(void * a, const void * b, const void * c, const void * ctx) { fmpz_mpoly_sub(a, b, c, ctx); } static void fmpz_mpoly_void_mul(void * a, const void * b, const void * c, const void * ctx) { fmpz_mpoly_mul(a, b, c, ctx); } static void fmpz_mpoly_void_mul_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { fmpz_mpoly_scalar_mul_fmpz(a, b, c, ctx); } static void fmpz_mpoly_void_divexact(void * a, const void * b, const void * c, const void * ctx) { if (!fmpz_mpoly_divides(a, b, c, ctx)) flint_throw(FLINT_ERROR, "fmpz_mpoly_void_divexact: nonexact"); } static int fmpz_mpoly_void_divides(void * a, const void * b, const void * c, const void * ctx) { return fmpz_mpoly_divides(a, b, c, ctx); } static int fmpz_mpoly_void_pow_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { return fmpz_mpoly_pow_fmpz(a, b, c, ctx); } static slong fmpz_mpoly_void_length(const void * a, const void * ctx) { return fmpz_mpoly_length(a, ctx); } void mpoly_void_ring_init_fmpz_mpoly_ctx( mpoly_void_ring_t R, const fmpz_mpoly_ctx_t ctx) { R->elem_size = sizeof(fmpz_mpoly_struct); R->ctx = ctx; R->init = fmpz_mpoly_void_init; R->clear = fmpz_mpoly_void_clear; R->is_zero = fmpz_mpoly_void_is_zero; R->zero = fmpz_mpoly_void_zero; R->one = fmpz_mpoly_void_one; R->set = fmpz_mpoly_void_set; R->set_fmpz = fmpz_mpoly_void_set_fmpz; R->swap = fmpz_mpoly_void_swap; R->neg = fmpz_mpoly_void_neg; R->add = fmpz_mpoly_void_add; R->sub = fmpz_mpoly_void_sub; R->mul = fmpz_mpoly_void_mul; R->mul_fmpz = fmpz_mpoly_void_mul_fmpz; R->divexact = fmpz_mpoly_void_divexact; R->divides = fmpz_mpoly_void_divides; R->pow_fmpz = fmpz_mpoly_void_pow_fmpz; R->length = fmpz_mpoly_void_length; } flint-3.1.3/src/fmpz_mpoly_factor.h000066400000000000000000000445311461254215100173340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MPOLY_FACTOR_H #define FMPZ_MPOLY_FACTOR_H #ifdef FMPZ_MPOLY_FACTOR_INLINES_C #define FMPZ_MPOLY_FACTOR_INLINE #else #define FMPZ_MPOLY_FACTOR_INLINE static inline #endif #include "fmpz_poly_factor.h" #include "fmpz_mpoly.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ void tuple_print(fmpz * alpha, slong n); void tuple_saturate(fmpz * alpha, slong n, slong m); void tuple_next(fmpz * alpha, slong n); /*****************************************************************************/ FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpoly_factor_init(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { *f->constant = 1; *f->constant_den = 1; f->poly = NULL; f->exp = NULL; f->num = 0; f->alloc = 0; } void fmpz_mpoly_factor_init2(fmpz_mpoly_factor_t f, slong alloc, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_realloc(fmpz_mpoly_factor_t f, slong alloc, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_fit_length(fmpz_mpoly_factor_t f, slong len, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_clear(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_FACTOR_INLINE slong fmpz_mpoly_factor_length(const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { return f->num; } void fmpz_mpoly_factor_get_constant_fmpz(fmpz_t c, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_get_constant_fmpq(fmpq_t c, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpoly_factor_get_base(fmpz_mpoly_t p, const fmpz_mpoly_factor_t f, slong i, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fmpz_mpoly_set(p, f->poly + i, ctx); } FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpoly_factor_swap_base(fmpz_mpoly_t p, fmpz_mpoly_factor_t f, slong i, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fmpz_mpoly_swap(p, f->poly + i, ctx); } slong fmpz_mpoly_factor_get_exp_si(fmpz_mpoly_factor_t f, slong i, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_set(fmpz_mpoly_factor_t f, const fmpz_mpoly_factor_t g, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_cmp(const fmpz_mpoly_factor_t f, const fmpz_mpoly_factor_t g, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_print_pretty(const fmpz_mpoly_factor_t f, const char ** vars, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_content(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_squarefree(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpoly_factor_swap(fmpz_mpoly_factor_t f, fmpz_mpoly_factor_t g, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_factor_struct t = *f; *f = *g; *g = t; } void fmpz_mpoly_factor_set_fmpz(fmpz_mpoly_factor_t f, const fmpz_t a, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_zero(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_one(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_sort(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_expand(fmpz_mpoly_t A, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_bound_si(fmpz_t B, const fmpz_t A, const slong * degs, slong nvars); FMPZ_MPOLY_FACTOR_INLINE int fmpz_mpoly_factor_matches(const fmpz_mpoly_t A, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { int matches; fmpz_mpoly_t T; fmpz_mpoly_init(T, ctx); matches = fmpz_mpoly_factor_expand(T, f, ctx); matches = matches && fmpz_mpoly_equal(T, A, ctx); fmpz_mpoly_clear(T, ctx); return matches; } void fmpz_mpoly_factor_append_fmpz_swap(fmpz_mpoly_factor_t f, fmpz_mpoly_t A, const fmpz_t e, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_factor_append_ui(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, ulong e, const fmpz_mpoly_ctx_t ctx); /*****************************************************************************/ void fmpz_mpoly_interp_lift_p(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, nmod_mpoly_t Ap, const nmod_mpoly_ctx_t ctxp); void fmpz_mpoly_interp_reduce_p(nmod_mpoly_t Ap, const nmod_mpoly_ctx_t ctxp, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_interp_mcrt_p(flint_bitcnt_t * coeffbits, fmpz_mpoly_t H, const fmpz_mpoly_ctx_t ctx, const fmpz_t m, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctxp); void fmpz_mpoly_interp_reduce_p_mpolyn(nmod_mpolyn_t E, const nmod_mpoly_ctx_t pctx, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_interp_lift_p_mpolyn(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t pctx); int fmpz_mpoly_interp_crt_p_mpolyn(fmpz_mpoly_t F, fmpz_mpoly_t T, const fmpz_mpoly_ctx_t ctx, fmpz_t modulus, const nmod_mpolyn_t A, const nmod_mpoly_ctx_t pctx); /*****************************************************************************/ typedef struct { fmpz_mpoly_struct * coeffs; slong alloc; slong length; } fmpz_mpolyv_struct; typedef fmpz_mpolyv_struct fmpz_mpolyv_t[1]; FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpolyv_init(fmpz_mpolyv_t A, const fmpz_mpoly_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpolyv_swap(fmpz_mpolyv_t A, fmpz_mpolyv_t B, const fmpz_mpoly_ctx_t ctx) { fmpz_mpolyv_struct t = *A; *A = *B; *B = t; } void fmpz_mpolyv_clear(fmpz_mpolyv_t A, const fmpz_mpoly_ctx_t ctx); void fmpz_mpolyv_print_pretty(const fmpz_mpolyv_t poly, const char ** x, const fmpz_mpoly_ctx_t ctx); void fmpz_mpolyv_fit_length(fmpz_mpolyv_t A, slong length, const fmpz_mpoly_ctx_t ctx); void fmpz_mpolyv_set_coeff(fmpz_mpolyv_t A, slong i, fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_to_mpolyv(fmpz_mpolyv_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t xalpha, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_from_mpolyv(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpolyv_t B, const fmpz_mpoly_t xalpha, const fmpz_mpoly_ctx_t ctx); int _fmpz_mpoly_vec_content_mpoly(fmpz_mpoly_t g, const fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_vec_divexact_mpoly(fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_vec_mul_mpoly(fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); /*****************************************************************************/ int _fmpz_mpoly_gcd_algo(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, unsigned int algo); void fmpz_mpoly_to_mpolyl_perm_deflate( fmpz_mpoly_t A, const fmpz_mpoly_ctx_t lctx, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride); void fmpz_mpoly_from_mpolyl_perm_inflate(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride); int fmpz_mpolyl_gcd_brown(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, fmpz_mpoly_t A, fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const mpoly_gcd_info_t I); int fmpz_mpolyl_gcd_brown_threaded_pool(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, fmpz_mpoly_t A, fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, const thread_pool_handle * handles, slong num_handles); int fmpz_mpolyl_gcd_zippel(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, flint_rand_t randstate); int fmpz_mpolyl_gcd_zippel2(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t Gamma, const fmpz_mpoly_ctx_t ctx); int fmpz_mpolyl_gcd_hensel(fmpz_mpoly_t G, slong Gdeg, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); /*****************************************************************************/ typedef struct { slong r; flint_bitcnt_t * bits; fmpz_poly_t a; fmpz_poly_t newa; fmpz_poly_t t; fmpz_poly_struct * b, * bprod; fmpz_t old_pk; fmpz_t pk; fmpz_t p; fmpz * halfpks; fmpz_mod_ctx_t ctxp; fmpz_mod_ctx_struct * ctxs; fmpz_mod_poly_t T; fmpz_mod_poly_t R; fmpz_mod_poly_t Q; fmpz_mod_poly_struct * B, * invBprod, * inwBprod, * B_inv; } fmpz_poly_pfrac_struct; typedef fmpz_poly_pfrac_struct fmpz_poly_pfrac_t[1]; void fmpz_poly_pfrac_init(fmpz_poly_pfrac_t I); void fmpz_poly_pfrac_clear(fmpz_poly_pfrac_t I); int fmpz_poly_pfrac_precompute(fmpz_poly_pfrac_t I, const fmpz_poly_struct * b, slong r); int fmpz_poly_pfrac_precomp(fmpz_poly_struct * c, const fmpz_poly_t A, fmpz_poly_pfrac_t I); typedef struct { flint_bitcnt_t bits; slong w; slong r; fmpz_mpoly_struct * prod_mbetas; fmpz_mpolyv_struct * prod_mbetas_coeffs; fmpz_mpoly_struct * mbetas; fmpz_mpoly_struct * deltas; fmpz_mpoly_struct * xalpha; fmpz_mpoly_struct * q; fmpz_mpoly_univar_struct * U; fmpz_mpoly_geobucket_struct * G; fmpz_mpoly_struct * qt; fmpz_mpoly_struct * newt; fmpz_mpolyv_struct * delta_coeffs; fmpz_poly_pfrac_t uni_pfrac; fmpz_poly_t uni_a; fmpz_poly_struct * uni_c; } fmpz_mpoly_pfrac_struct; typedef fmpz_mpoly_pfrac_struct fmpz_mpoly_pfrac_t[1]; int fmpz_mpoly_pfrac_init(fmpz_mpoly_pfrac_t I, flint_bitcnt_t bits, slong r, slong w, const fmpz_mpoly_struct * betas, const fmpz * alpha, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_pfrac_clear(fmpz_mpoly_pfrac_t I, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_pfrac(slong l, fmpz_mpoly_t t, const slong * degs, fmpz_mpoly_pfrac_t I, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_hlift(slong m, fmpz_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mpoly_t A, const slong * degs, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_get_lead0(fmpz_mpoly_t c, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_set_lead0(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); /*****************************************************************************/ typedef struct { fmpz_poly_struct * coeffs; slong alloc; slong length; } fmpz_bpoly_struct; typedef fmpz_bpoly_struct fmpz_bpoly_t[1]; FMPZ_MPOLY_FACTOR_INLINE void fmpz_bpoly_init(fmpz_bpoly_t A) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FMPZ_MPOLY_FACTOR_INLINE void fmpz_bpoly_swap(fmpz_bpoly_t A, fmpz_bpoly_t B) { fmpz_bpoly_struct t = *A; *A = *B; *B = t; } void fmpz_bpoly_clear(fmpz_bpoly_t A); void fmpz_bpoly_realloc(fmpz_bpoly_t A, slong len); FMPZ_MPOLY_FACTOR_INLINE void fmpz_bpoly_fit_length(fmpz_bpoly_t A, slong len) { if (A->alloc < len) fmpz_bpoly_realloc(A, len); } void fmpz_bpoly_print_pretty(fmpz_bpoly_t A, const char * var0, const char * var1); FMPZ_MPOLY_FACTOR_INLINE fmpz_poly_struct * fmpz_bpoly_lead(fmpz_bpoly_t A) { return A->coeffs + A->length - 1; } FMPZ_MPOLY_FACTOR_INLINE void fmpz_bpoly_zero(fmpz_bpoly_t A) { A->length = 0; } FMPZ_MPOLY_FACTOR_INLINE slong fmpz_bpoly_degree0(const fmpz_bpoly_t A) { return A->length - 1; } slong fmpz_bpoly_degree1(const fmpz_bpoly_t A); void fmpz_bpoly_set_coeff(fmpz_bpoly_t A, slong exp0, slong exp1, const fmpz_t c); void fmpz_mpoly_set_fmpz_bpoly( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_bpoly_t B, slong var0, slong var1, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_get_bpoly( fmpz_bpoly_t A, const fmpz_mpoly_t B, slong var0, slong var1, const fmpz_mpoly_ctx_t ctx); typedef struct { fmpz_bpoly_struct * coeffs; slong alloc; slong length; } fmpz_tpoly_struct; typedef fmpz_tpoly_struct fmpz_tpoly_t[1]; FMPZ_MPOLY_FACTOR_INLINE void fmpz_tpoly_init(fmpz_tpoly_t A) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FMPZ_MPOLY_FACTOR_INLINE void fmpz_tpoly_swap(fmpz_tpoly_t A, fmpz_tpoly_t B) { fmpz_tpoly_struct t = *A; *A = *B; *B = t; } void fmpz_tpoly_fit_length(fmpz_tpoly_t A, slong len); void fmpz_tpoly_clear(fmpz_tpoly_t A); void fmpz_bpoly_factor(fmpz_poly_t c, fmpz_tpoly_t F, fmpz_bpoly_t B); int fmpz_bpoly_factor_ordered( fmpz_poly_t c, fmpz_tpoly_t F, fmpz_bpoly_t B, const fmpz_t alpha, const fmpz_poly_factor_t Bevalf); /*****************************************************************************/ void fmpz_mpoly_unit_normalize(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); int _fmpz_mpoly_factor_squarefree(fmpz_mpoly_factor_t f, fmpz_mpoly_t A, const fmpz_t e, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_lcc_wang(fmpz_mpoly_struct * lc_divs, const fmpz_mpoly_factor_t lcAfac, const fmpz_t Auc, const fmpz_poly_struct * Auf, slong r, const fmpz * alpha, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_irred_zassenhaus(fmpz_mpolyv_t fac, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, zassenhaus_prune_t Z); int fmpz_mpoly_factor_irred_wang(fmpz_mpolyv_t fac, const fmpz_mpoly_t A, const fmpz_mpoly_factor_t lcAfac, int lcAfac_irred, const fmpz_mpoly_t lcA, const fmpz_mpoly_ctx_t ctx, flint_rand_t state, zassenhaus_prune_t Z, int allow_shift); int fmpz_mpoly_factor_irred_zippel(fmpz_mpolyv_t fac, const fmpz_mpoly_t A, const fmpz_mpoly_factor_t lcAfac, int lcAfac_irred, const fmpz_mpoly_t lcA, const fmpz_mpoly_ctx_t ctx, flint_rand_t state, zassenhaus_prune_t Z); int fmpz_mpoly_factor_irred(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx, unsigned int algo); int fmpz_mpoly_factor_zassenhaus(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_wang(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_zippel(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); int _fmpz_mpoly_evaluate_rest_fmpz(fmpz * E, slong * starts, slong * ends, slong * stops, ulong * es, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, slong var, const fmpz * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars); void _fmpz_mpoly_eval_rest_to_poly(fmpz_poly_t E, const fmpz_mpoly_t A, const fmpz * alphas, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_lcc_kaltofen_step( fmpz_mpoly_struct * divs, /* length r */ slong r, fmpz_mpoly_factor_t Af, /* squarefree factorization of A */ const fmpz_poly_struct * Au, slong v, /* minor bivar var*/ const fmpz * alphas, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_factor_lcc_kaltofen( fmpz_mpoly_struct * divs, const fmpz_mpoly_factor_t lcAf_, const fmpz_mpoly_t A, slong r, const fmpz * alpha, slong * degs, const fmpz_poly_factor_t uf, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_evaluate_rest_except_one( fmpz_poly_t e, const fmpz_mpoly_t A, const fmpz * alphas, slong v, const fmpz_mpoly_ctx_t ctx); /****************************************************************************/ void fmpz_mpoly_compression_do(fmpz_mpoly_t L, const fmpz_mpoly_ctx_t Lctx, fmpz * Acoeffs, slong Alen, mpoly_compression_t M); void fmpz_mpoly_compression_undo(fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t Actx, fmpz_mpoly_t L, const fmpz_mpoly_ctx_t Lctx, mpoly_compression_t M); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mpoly_factor/000077500000000000000000000000001461254215100171545ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly_factor/add.c000066400000000000000000000021051461254215100200460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_factor_add( fmpz_mpoly_factor_t A, const fmpz_mpoly_factor_t B, const fmpz_mpoly_factor_t C, const fmpz_mpoly_ctx_t ctx) { int success = 0; fmpz_mpoly_t b, c; fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(c, ctx); if (!fmpz_mpoly_factor_expand(b, B, ctx)) goto cleanup; if (!fmpz_mpoly_factor_expand(c, C, ctx)) goto cleanup; fmpz_mpoly_factor_fit_length(A, 1, ctx); fmpz_one(A->constant); fmpz_mpoly_add(A->poly + 0, b, c, ctx); fmpz_one(A->exp + 0); A->num = 1; success = 1; cleanup: fmpz_mpoly_clear(c, ctx); fmpz_mpoly_clear(b, ctx); return success; } flint-3.1.3/src/fmpz_mpoly_factor/bpoly.c000066400000000000000000000106551461254215100204540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" void fmpz_bpoly_clear(fmpz_bpoly_t A) { if (A->alloc > 0) { slong i; for (i = 0; i < A->alloc; i++) fmpz_poly_clear(A->coeffs + i); flint_free(A->coeffs); } } void fmpz_bpoly_print_pretty(fmpz_bpoly_t A, const char * var0, const char * var1) { slong i; int first = 1; for (i = A->length - 1; i >= 0; i--) { if (fmpz_poly_is_zero(A->coeffs + i)) continue; if (!first) flint_printf(" + "); first = 0; flint_printf("("); fmpz_poly_print_pretty(A->coeffs + i, var1); flint_printf(")*%s^%wd", var0, i); } if (first) flint_printf("0"); } void fmpz_bpoly_realloc(fmpz_bpoly_t A, slong len) { slong i; slong old_alloc = A->alloc; if (len <= old_alloc) return; len = FLINT_MAX(len, 2*old_alloc); if (A->alloc == 0) A->coeffs = (fmpz_poly_struct *) flint_malloc( len * sizeof(fmpz_poly_struct)); else A->coeffs = (fmpz_poly_struct *) flint_realloc(A->coeffs, len * sizeof(fmpz_poly_struct)); for (i = old_alloc; i < len; i++) fmpz_poly_init(A->coeffs + i); A->alloc = len; } slong fmpz_bpoly_degree1(const fmpz_bpoly_t A) { slong i, len = 0; for (i = 0; i < A->length; i++) len = FLINT_MAX(len, A->coeffs[i].length); return len - 1; } void fmpz_bpoly_set_coeff(fmpz_bpoly_t A, slong xi, slong yi, const fmpz_t c) { slong i; FLINT_ASSERT(!fmpz_is_zero(c)); if (xi >= A->length) { fmpz_bpoly_fit_length(A, xi + 1); for (i = A->length; i <= xi; i++) fmpz_poly_zero(A->coeffs + i); A->length = xi + 1; } fmpz_poly_set_coeff_fmpz(A->coeffs + xi, yi, c); } void fmpz_mpoly_set_fmpz_bpoly( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_bpoly_t B, slong varx, slong vary, const fmpz_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, j; slong NA; slong Alen; fmpz * Acoeff; ulong * Aexp; slong Aalloc; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); TMP_START; Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); for (i = 0; i < n; i++) Aexps[i] = 0; NA = mpoly_words_per_exp(Abits, ctx->minfo); fmpz_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; Acoeff = A->coeffs; Aexp = A->exps; Aalloc = A->alloc; Alen = 0; for (i = 0; i < B->length; i++) { fmpz_poly_struct * Bc = B->coeffs + i; _fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + Bc->length, NA); for (j = 0; j < Bc->length; j++) { if (fmpz_is_zero(Bc->coeffs + j)) continue; Aexps[varx] = i; Aexps[vary] = j; fmpz_set(Acoeff + Alen, Bc->coeffs + j); mpoly_set_monomial_ui(Aexp + NA*Alen, Aexps, Abits, ctx->minfo); Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; A->alloc = Aalloc; _fmpz_mpoly_set_length(A, Alen, ctx); fmpz_mpoly_sort_terms(A, ctx); TMP_END; } void fmpz_mpoly_get_bpoly( fmpz_bpoly_t A, const fmpz_mpoly_t B, slong varx, slong vary, const fmpz_mpoly_ctx_t ctx) { slong j; slong NB; ulong Bexpx, Bexpy; slong Boffx, Bshiftx, Boffy, Bshifty; ulong mask; FLINT_ASSERT(B->bits <= FLINT_BITS); NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); fmpz_bpoly_zero(A); for (j = 0; j < B->length; j++) { Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask; Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask; fmpz_bpoly_set_coeff(A, Bexpx, Bexpy, B->coeffs + j); } } flint-3.1.3/src/fmpz_mpoly_factor/bpoly_factor.c000066400000000000000000000734301461254215100220120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mpoly_factor.h" #include "fmpz_mod_mpoly_factor.h" void fmpz_tpoly_print(fmpz_tpoly_t A, const char * xvar, const char * yvar, const char * zvar) { slong i; int first; first = 1; for (i = A->length - 1; i >= 0; i--) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); fmpz_bpoly_print_pretty(A->coeffs + i, yvar, zvar); flint_printf(")*%s^%wd", xvar, i); } if (first) flint_printf("0"); } void fmpz_mod_bpoly_set_fmpz_bpoly( fmpz_mod_bpoly_t A, const fmpz_bpoly_t B, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_bpoly_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { fmpz_mod_poly_set_fmpz_poly(A->coeffs + i, B->coeffs + i, ctx); if (!fmpz_mod_poly_is_zero(A->coeffs + i, ctx)) A->length = i + 1; } } void fmpz_mod_bpoly_set_polyx( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_bpoly_fit_length(A, B->length, ctx); A->length = 0; for (i = 0; i < B->length; i++) { fmpz_mod_poly_set_fmpz(A->coeffs + i, B->coeffs + i, ctx); if (!fmpz_mod_poly_is_zero(A->coeffs + i, ctx)) A->length = i + 1; } } void fmpz_mod_bpoly_set_polyy( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) { fmpz_mod_bpoly_fit_length(A, 1, ctx); fmpz_mod_poly_set(A->coeffs + 0, B, ctx); A->length = !fmpz_mod_poly_is_zero(A->coeffs + 0, ctx); } void fmpz_mod_bpoly_add_poly_shift( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, slong yshift, const fmpz_mod_ctx_t ctx) { slong i; fmpz_t c; FLINT_ASSERT(A->length > B->length); fmpz_init(c); for (i = 0; i < B->length; i++) { fmpz_mod_poly_get_coeff_fmpz(c, A->coeffs + i, yshift, ctx); FLINT_ASSERT(fmpz_is_zero(c)); fmpz_mod_poly_set_coeff_fmpz(A->coeffs + i, yshift, B->coeffs + i, ctx); } fmpz_clear(c); } void fmpz_bpoly_set(fmpz_bpoly_t A, const fmpz_bpoly_t B) { slong i; FLINT_ASSERT(A != B); fmpz_bpoly_fit_length(A, B->length); A->length = B->length; for (i = 0; i < B->length; i++) fmpz_poly_set(A->coeffs + i, B->coeffs + i); } void fmpz_bpoly_make_primitive(fmpz_poly_t g, fmpz_bpoly_t A) { slong Alen = A->length; slong i; fmpz_poly_t q; fmpz_poly_init(q); fmpz_poly_zero(g); for (i = 0; i < Alen; i++) { fmpz_poly_gcd(q, g, A->coeffs + i); fmpz_poly_swap(g, q); } if (Alen > 0 && fmpz_sgn(A->coeffs[Alen - 1].coeffs + A->coeffs[Alen - 1].length - 1) < 0) fmpz_poly_neg(g, g); for (i = 0; i < A->length; i++) { fmpz_poly_divexact(q, A->coeffs + i, g); fmpz_poly_swap(A->coeffs + i, q); } fmpz_poly_clear(q); } int fmpz_bpoly_divides(fmpz_bpoly_t Q, fmpz_bpoly_t A, fmpz_bpoly_t B) { slong i, qoff; int divides; fmpz_poly_t q, t; fmpz_bpoly_t R; FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); fmpz_poly_init(q); fmpz_poly_init(t); fmpz_bpoly_init(R); fmpz_bpoly_set(R, A); Q->length = 0; while (R->length >= B->length) { divides = fmpz_poly_divides(q, R->coeffs + R->length - 1, B->coeffs + B->length - 1); if (!divides) goto cleanup; for (i = 0; i < B->length; i++) { fmpz_poly_mul(t, B->coeffs + i, q); fmpz_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { fmpz_bpoly_fit_length(Q, qoff + 1); for (i = Q->length; i <= qoff; i++) fmpz_poly_zero(Q->coeffs + i); Q->length = qoff + 1; } fmpz_poly_set(Q->coeffs + qoff, q); while (R->length > 0 && fmpz_poly_is_zero(R->coeffs + R->length - 1)) R->length--; } divides = (R->length == 0); cleanup: fmpz_poly_clear(q); fmpz_poly_clear(t); fmpz_bpoly_clear(R); return divides; } void fmpz_bpoly_set_fmpz_mod_bpoly( fmpz_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx) { slong i; fmpz_bpoly_fit_length(A, B->length); A->length = B->length; for (i = 0; i < B->length; i++) { fmpz_poly_fit_length(A->coeffs + i, (B->coeffs + i)->length); (A->coeffs + i)->length = (B->coeffs + i)->length; _fmpz_vec_scalar_smod_fmpz((A->coeffs + i)->coeffs, (B->coeffs + i)->coeffs, (B->coeffs + i)->length, fmpz_mod_ctx_modulus(ctx)); } } void fmpz_bpoly_eval(fmpz_poly_t E, const fmpz_bpoly_t A, const fmpz_t alpha) { slong i; fmpz_t t; fmpz_init(t); fmpz_poly_zero(E); for (i = A->length - 1; i >= 0; i--) { fmpz_poly_evaluate_fmpz(t, A->coeffs + i, alpha); fmpz_poly_set_coeff_fmpz(E, i, t); } fmpz_clear(t); } void fmpz_bpoly_taylor_shift(fmpz_bpoly_t A, const fmpz_t alpha) { slong i; for (i = A->length - 1; i >= 0; i--) _fmpz_poly_taylor_shift((A->coeffs + i)->coeffs, alpha, (A->coeffs + i)->length); } typedef struct { slong r; /* number of local factors */ ulong k; slong lifting_prec; fmpz_t p; fmpz_t pk; fmpz_mod_ctx_t ctxp; fmpz_mod_ctx_t ctxpk; fmpz_mod_bpoly_t Btilde; /* mod p^k */ fmpz_mod_bpoly_struct * newBitilde; /* mod p^k */ fmpz_mod_poly_struct * P; /* mod p^k */ fmpz_mod_poly_struct * d; /* mod p^k */ fmpz_mod_poly_struct * Bitilde; /* mod p^k */ fmpz_mod_poly_struct * d1; /* mod p */ fmpz_mod_poly_struct * Bitilde1; /* mod p */ } bpoly_info_struct; typedef bpoly_info_struct bpoly_info_t[1]; void bpoly_info_init(bpoly_info_t I, slong r, const fmpz_t p, ulong k) { slong i; FLINT_ASSERT(r >= 2); I->r = r; I->lifting_prec = 0; I->k = k; fmpz_init_set(I->p, p); fmpz_init(I->pk); fmpz_pow_ui(I->pk, p, k); fmpz_mod_ctx_init(I->ctxp, I->p); fmpz_mod_ctx_init(I->ctxpk, I->pk); fmpz_mod_bpoly_init(I->Btilde, I->ctxpk); I->newBitilde = FLINT_ARRAY_ALLOC(I->r, fmpz_mod_bpoly_struct); I->P = FLINT_ARRAY_ALLOC(I->r, fmpz_mod_poly_struct); I->d = FLINT_ARRAY_ALLOC(I->r, fmpz_mod_poly_struct); I->Bitilde = FLINT_ARRAY_ALLOC(I->r, fmpz_mod_poly_struct); I->d1 = FLINT_ARRAY_ALLOC(I->r, fmpz_mod_poly_struct); I->Bitilde1 = FLINT_ARRAY_ALLOC(I->r, fmpz_mod_poly_struct); for (i = 0; i < I->r; i++) { fmpz_mod_bpoly_init(I->newBitilde + i, I->ctxpk); fmpz_mod_poly_init(I->P + i, I->ctxpk); fmpz_mod_poly_init(I->d + i, I->ctxpk); fmpz_mod_poly_init(I->Bitilde + i, I->ctxpk); fmpz_mod_poly_init(I->d1 + i, I->ctxp); fmpz_mod_poly_init(I->Bitilde1 + i, I->ctxp); } } void bpoly_info_clear(bpoly_info_t I) { slong i; fmpz_clear(I->p); fmpz_clear(I->pk); fmpz_mod_bpoly_clear(I->Btilde, I->ctxpk); for (i = 0; i < I->r; i++) { fmpz_mod_bpoly_clear(I->newBitilde + i, I->ctxpk); fmpz_mod_poly_clear(I->P + i, I->ctxpk); fmpz_mod_poly_clear(I->d + i, I->ctxpk); fmpz_mod_poly_clear(I->Bitilde + i, I->ctxpk); fmpz_mod_poly_clear(I->d1 + i, I->ctxp); fmpz_mod_poly_clear(I->Bitilde1 + i, I->ctxp); } flint_free(I->newBitilde); flint_free(I->P); flint_free(I->d); flint_free(I->Bitilde); flint_free(I->d1); flint_free(I->Bitilde1); fmpz_mod_ctx_clear(I->ctxp); fmpz_mod_ctx_clear(I->ctxpk); } /* set out[i] so that 1/(f[0]*f[1]*...*f[n-1]) = out[0]/f[0] + ... + out[n-1]/f[n-1] */ int partial_fraction_coeffs( fmpz_mod_poly_struct * out, const fmpz_mod_poly_struct * f, slong n, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_t num, den, a, b, g, t; FLINT_ASSERT(n > 1); fmpz_mod_poly_init(num, ctx); fmpz_mod_poly_init(den, ctx); fmpz_mod_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx); fmpz_mod_poly_init(g, ctx); fmpz_mod_poly_init(t, ctx); fmpz_mod_poly_set_ui(num, 1, ctx); fmpz_mod_poly_mul(den, f + 0, f + 1, ctx); for (i = 2; i < n; i++) fmpz_mod_poly_mul(den, den, f + i, ctx); for (i = 0; i < n; i++) { fmpz_mod_poly_divrem(den, t, den, f + i, ctx); FLINT_ASSERT(fmpz_mod_poly_is_zero(t, ctx)); fmpz_mod_poly_xgcd(g, a, b, f + i, den, ctx); if (fmpz_mod_poly_degree(g, ctx) != 0) return 0; FLINT_ASSERT(fmpz_is_one(g->coeffs + 0)); fmpz_mod_poly_mul(t, b, num, ctx); fmpz_mod_poly_rem(out + i, t, f + i, ctx); fmpz_mod_poly_mul(t, a, num, ctx); fmpz_mod_poly_rem(num, t, den, ctx); } fmpz_mod_poly_clear(num, ctx); fmpz_mod_poly_clear(den, ctx); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_mod_poly_clear(g, ctx); fmpz_mod_poly_clear(t, ctx); return 1; } int bpoly_info_disolve(bpoly_info_t I) { slong i, j; fmpz_t pj, t1; fmpz_mod_poly_t error, t, s, s1, s2; if (!partial_fraction_coeffs(I->d1, I->Bitilde1, I->r, I->ctxp)) return 0; fmpz_init(pj); fmpz_init(t1); fmpz_mod_poly_init(error, I->ctxpk); fmpz_mod_poly_init(t, I->ctxpk); fmpz_mod_poly_init(s, I->ctxp); fmpz_mod_poly_init(s1, I->ctxp); fmpz_mod_poly_init(s2, I->ctxpk); for (i = 0; i < I->r; i++) { fmpz_mod_poly_set_ui(I->P + i, 1, I->ctxpk); for (j = 0; j < I->r; j++) { if (i == j) continue; fmpz_mod_poly_mul(I->P + i, I->P + i, I->Bitilde + j, I->ctxpk); } } fmpz_mod_poly_set_ui(error, 1, I->ctxpk); for (i = 0; i < I->r; i++) { fmpz_mod_poly_set(I->d + i, I->d1 + i, I->ctxpk); /* slight abuse because moduli are different */ fmpz_mod_poly_mul(t, I->d + i, I->P + i, I->ctxpk); fmpz_mod_poly_sub(error, error, t, I->ctxpk); } fmpz_one(pj); for (j = 1; j < I->k; j++) { fmpz_mul(pj, pj, I->p); fmpz_mod_poly_zero(s, I->ctxp); for (i = error->length - 1; i >= 0; i--) { FLINT_ASSERT(fmpz_divisible(error->coeffs + i, pj)); fmpz_divexact(t1, error->coeffs + i, pj); fmpz_mod(t1, t1, I->p); fmpz_mod_poly_set_coeff_fmpz(s, i, t1, I->ctxp); } for (i = 0; i < I->r; i++) { fmpz_mod_poly_mul(s1, s, I->d1 + i, I->ctxp); fmpz_mod_poly_rem(s2, s1, I->Bitilde1 + i, I->ctxp); fmpz_mod_poly_scalar_mul_fmpz(s2, s2, pj, I->ctxpk); fmpz_mod_poly_add(I->d + i, I->d + i, s2, I->ctxpk); } fmpz_mod_poly_set_ui(error, 1, I->ctxpk); for (i = 0; i < I->r; i++) { fmpz_mod_poly_mul(t, I->d + i, I->P + i, I->ctxpk); fmpz_mod_poly_sub(error, error, t, I->ctxpk); } } FLINT_ASSERT(fmpz_mod_poly_is_zero(error, I->ctxpk)); fmpz_clear(pj); fmpz_clear(t1); fmpz_mod_poly_clear(error, I->ctxpk); fmpz_mod_poly_clear(t, I->ctxpk); fmpz_mod_poly_clear(s, I->ctxp); fmpz_mod_poly_clear(s1, I->ctxp); fmpz_mod_poly_clear(s2, I->ctxpk); return 1; } static void _bivar_lift_quintic(bpoly_info_t I) { slong i, j, k; fmpz_mod_bpoly_t tp, tp1, error; fmpz_mod_poly_t ss, tt; fmpz_mod_poly_init(ss, I->ctxpk); fmpz_mod_poly_init(tt, I->ctxpk); fmpz_mod_bpoly_init(tp, I->ctxpk); fmpz_mod_bpoly_init(tp1, I->ctxpk); fmpz_mod_bpoly_init(error, I->ctxpk); fmpz_mod_bpoly_mul_series(tp, I->newBitilde + 0, I->newBitilde + 1, I->lifting_prec, I->ctxpk); for (i = 2; i < I->r; i++) { fmpz_mod_bpoly_mul_series(tp1, tp, I->newBitilde + i, I->lifting_prec, I->ctxpk); fmpz_mod_bpoly_swap(tp1, tp, I->ctxpk); } fmpz_mod_bpoly_sub(error, I->Btilde, tp, I->ctxpk); for (j = 1; j < I->lifting_prec; j++) { fmpz_mod_poly_zero(ss, I->ctxpk); for (i = error->length - 1; i >= 0; i--) { fmpz_t ct; fmpz_init(ct); fmpz_mod_bpoly_get_coeff(ct, error, i, j, I->ctxpk); fmpz_mod_poly_set_coeff_fmpz(ss, i, ct, I->ctxpk); for (k = 0; k < j; k++) { fmpz_mod_bpoly_get_coeff(ct, error, i, k, I->ctxpk); FLINT_ASSERT(fmpz_is_zero(ct)); } fmpz_clear(ct); } for (i = 0; i < I->r; i++) { fmpz_mod_poly_mul(tt, ss, I->d + i, I->ctxpk); fmpz_mod_poly_rem(tt, tt, I->Bitilde + i, I->ctxpk); fmpz_mod_bpoly_add_poly_shift(I->newBitilde + i, tt, j, I->ctxpk); } fmpz_mod_bpoly_mul_series(tp, I->newBitilde + 0, I->newBitilde + 1, I->lifting_prec, I->ctxpk); for (i = 2; i < I->r; i++) { fmpz_mod_bpoly_mul_series(tp1, tp, I->newBitilde + i, I->lifting_prec, I->ctxpk); fmpz_mod_bpoly_swap(tp1, tp, I->ctxpk); } fmpz_mod_bpoly_sub(error, I->Btilde, tp, I->ctxpk); } fmpz_mod_poly_clear(ss, I->ctxpk); fmpz_mod_poly_clear(tt, I->ctxpk); fmpz_mod_bpoly_clear(tp, I->ctxpk); fmpz_mod_bpoly_clear(tp1, I->ctxpk); fmpz_mod_bpoly_clear(error, I->ctxpk); } static void _bivar_lift_quartic2(bpoly_info_t I) { slong i, j, k; fmpz_mod_poly_t t, t1; fmpz_mod_bpoly_t btilde; fmpz_mod_bpoly_struct newbitilde[2]; FLINT_ASSERT(I->r == 2); fmpz_mod_poly_init(t, I->ctxpk); fmpz_mod_poly_init(t1, I->ctxpk); fmpz_mod_bpoly_init(btilde, I->ctxpk); fmpz_mod_bpoly_reverse_vars(btilde, I->Btilde, I->ctxpk); for (k = 0; k < I->r; k++) { fmpz_mod_bpoly_init(newbitilde + k, I->ctxpk); fmpz_mod_bpoly_reverse_vars(newbitilde + k, I->newBitilde + k, I->ctxpk); fmpz_mod_bpoly_fit_length(newbitilde + k, I->lifting_prec, I->ctxpk); FLINT_ASSERT((newbitilde + k)->length == 1); } for (j = 1; j < I->lifting_prec; j++) { if (j < btilde->length) fmpz_mod_poly_set(t, btilde->coeffs + j, I->ctxpk); else fmpz_mod_poly_zero(t, I->ctxpk); for (i = 1; i < j; i++) { fmpz_mod_poly_mul(t1, newbitilde[0].coeffs + i, newbitilde[1].coeffs + j - i, I->ctxpk); fmpz_mod_poly_sub(t, t, t1, I->ctxpk); } for (k = 0; k < I->r; k++) { fmpz_mod_poly_mul(t1, t, I->d + k, I->ctxpk); fmpz_mod_poly_rem(newbitilde[k].coeffs + j, t1, I->Bitilde + k, I->ctxpk); if (!fmpz_mod_poly_is_zero(newbitilde[k].coeffs + j, I->ctxpk)) newbitilde[k].length = j + 1; } } for (k = 0; k < I->r; k++) fmpz_mod_bpoly_reverse_vars(I->newBitilde + k, newbitilde + k, I->ctxpk); fmpz_mod_poly_clear(t, I->ctxpk); fmpz_mod_poly_clear(t1, I->ctxpk); fmpz_mod_bpoly_clear(btilde, I->ctxpk); for (k = 0; k < I->r; k++) fmpz_mod_bpoly_clear(newbitilde + k, I->ctxpk); } static void _bivar_lift_quartic(bpoly_info_t I) { slong i, j, k; fmpz_mod_poly_t t, t1; fmpz_mod_bpoly_t btilde; fmpz_mod_bpoly_struct * newbitilde, * U; FLINT_ASSERT(I->r > 2); newbitilde = (fmpz_mod_bpoly_struct *) flint_malloc(I->r*sizeof(fmpz_mod_bpoly_struct)); U = (fmpz_mod_bpoly_struct *) flint_malloc(I->r*sizeof(fmpz_mod_bpoly_struct)); fmpz_mod_poly_init(t, I->ctxpk); fmpz_mod_poly_init(t1, I->ctxpk); fmpz_mod_bpoly_init(btilde, I->ctxpk); fmpz_mod_bpoly_reverse_vars(btilde, I->Btilde, I->ctxpk); for (k = 0; k < I->r; k++) { fmpz_mod_bpoly_init(U + k, I->ctxpk); fmpz_mod_bpoly_fit_length(U + k, I->lifting_prec, I->ctxpk); for (i = 0; i < I->lifting_prec; i++) { fmpz_mod_poly_zero(U[k].coeffs + i, I->ctxpk); } fmpz_mod_bpoly_init(newbitilde + k, I->ctxpk); fmpz_mod_bpoly_reverse_vars(newbitilde + k, I->newBitilde + k, I->ctxpk); fmpz_mod_bpoly_fit_length(newbitilde + k, I->lifting_prec, I->ctxpk); FLINT_ASSERT(newbitilde[k].length == 1); for (i = 1; i < I->lifting_prec; i++) { fmpz_mod_poly_zero(newbitilde[k].coeffs + i, I->ctxpk); } } k = I->r - 2; fmpz_mod_poly_mul(U[k].coeffs + 0, newbitilde[k].coeffs + 0, newbitilde[k + 1].coeffs + 0, I->ctxpk); for (k--; k >= 1; k--) fmpz_mod_poly_mul(U[k].coeffs + 0, newbitilde[k].coeffs + 0, U[k + 1].coeffs + 0, I->ctxpk); for (j = 1; j < I->lifting_prec; j++) { k = I->r - 2; fmpz_mod_poly_zero(U[k].coeffs + j, I->ctxpk); for (i = 0; i <= j; i++) { fmpz_mod_poly_mul(t1, newbitilde[k].coeffs + i, newbitilde[k + 1].coeffs + j - i, I->ctxpk); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t1, I->ctxpk); } for (k--; k >= 1; k--) { fmpz_mod_poly_zero(U[k].coeffs + j, I->ctxpk); for (i = 0; i <= j; i++) { fmpz_mod_poly_mul(t1, newbitilde[k].coeffs + i, U[k + 1].coeffs + j - i, I->ctxpk); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t1, I->ctxpk); } } if (j < btilde->length) fmpz_mod_poly_set(t, btilde->coeffs + j, I->ctxpk); else fmpz_mod_poly_zero(t, I->ctxpk); for (i = 0; i <= j; i++) { fmpz_mod_poly_mul(t1, newbitilde[0].coeffs + i, U[1].coeffs + j - i, I->ctxpk); fmpz_mod_poly_sub(t, t, t1, I->ctxpk); } for (k = 0; k < I->r; k++) { fmpz_mod_poly_mul(t1, t, I->d + k, I->ctxpk); fmpz_mod_poly_rem(newbitilde[k].coeffs + j, t1, I->Bitilde + k, I->ctxpk); if (!fmpz_mod_poly_is_zero(newbitilde[k].coeffs + j, I->ctxpk)) newbitilde[k].length = j + 1; } k = I->r - 2; fmpz_mod_poly_mul(t, newbitilde[k].coeffs + 0, newbitilde[k + 1].coeffs + j, I->ctxpk); fmpz_mod_poly_mul(t1, newbitilde[k].coeffs + j, newbitilde[k + 1].coeffs + 0, I->ctxpk); fmpz_mod_poly_add(t, t, t1, I->ctxpk); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, I->ctxpk); for (k--; k >= 1; k--) { fmpz_mod_poly_mul(t1, newbitilde[k].coeffs + 0, t, I->ctxpk); fmpz_mod_poly_swap(t, t1, I->ctxpk); fmpz_mod_poly_mul(t1, newbitilde[k].coeffs + j, U[k + 1].coeffs + 0, I->ctxpk); fmpz_mod_poly_add(t, t, t1, I->ctxpk); fmpz_mod_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, I->ctxpk); } } for (k = 0; k < I->r; k++) fmpz_mod_bpoly_reverse_vars(I->newBitilde + k, newbitilde + k, I->ctxpk); fmpz_mod_poly_clear(t, I->ctxpk); fmpz_mod_poly_clear(t1, I->ctxpk); fmpz_mod_bpoly_clear(btilde, I->ctxpk); for (k = 0; k < I->r; k++) { fmpz_mod_bpoly_clear(U + k, I->ctxpk); fmpz_mod_bpoly_clear(newbitilde + k, I->ctxpk); } flint_free(newbitilde); flint_free(U); } static void _recombine_naive( fmpz_tpoly_t F, fmpz_bpoly_t B, fmpz_t alpha, bpoly_info_t I) { fmpz_poly_t g; fmpz_bpoly_t Q, R, trymez; fmpz_mod_bpoly_t tryme, trymet; fmpz_mod_poly_t leadB; slong i, k, len; slong * subset; fmpz_poly_init(g); fmpz_bpoly_init(Q); fmpz_bpoly_init(R); fmpz_bpoly_init(trymez); fmpz_mod_bpoly_init(tryme, I->ctxpk); fmpz_mod_bpoly_init(trymet, I->ctxpk); fmpz_mod_poly_init(leadB, I->ctxpk); F->length = 0; FLINT_ASSERT(B->length > 0); fmpz_mod_poly_set_fmpz_poly(leadB, B->coeffs + B->length - 1, I->ctxpk); len = I->r; subset = (slong *) flint_malloc(len * sizeof(slong)); for (k = 0; k < len; k++) subset[k] = k; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); while (1) { fmpz_mod_bpoly_set_polyy(tryme, leadB, I->ctxpk); for (i = 0; i < len; i++) { if (subset[i] >= 0) { fmpz_mod_bpoly_mul_series(trymet, tryme, I->newBitilde + subset[i], I->lifting_prec, I->ctxpk); fmpz_mod_bpoly_swap(trymet, tryme, I->ctxpk); } } fmpz_bpoly_set_fmpz_mod_bpoly(trymez, tryme, I->ctxpk); fmpz_bpoly_make_primitive(g, trymez); if (fmpz_bpoly_divides(Q, B, trymez)) { fmpz_neg(alpha, alpha); fmpz_bpoly_taylor_shift(trymez, alpha); fmpz_neg(alpha, alpha); fmpz_tpoly_fit_length(F, F->length + 1); fmpz_bpoly_swap(F->coeffs + F->length, trymez); F->length++; fmpz_bpoly_swap(B, Q); FLINT_ASSERT(B->length > 0); fmpz_mod_poly_set_fmpz_poly(leadB, B->coeffs + B->length - 1, I->ctxpk); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } fmpz_neg(alpha, alpha); fmpz_bpoly_taylor_shift(B, alpha); fmpz_neg(alpha, alpha); if (B->length > 1) { fmpz_tpoly_fit_length(F, F->length + 1); fmpz_bpoly_swap(F->coeffs + F->length, B); F->length++; } else { FLINT_ASSERT(B->length == 1); FLINT_ASSERT(fmpz_poly_is_one(B->coeffs + 0)); } fmpz_poly_clear(g); fmpz_bpoly_clear(Q); fmpz_bpoly_clear(R); fmpz_bpoly_clear(trymez); fmpz_mod_bpoly_clear(tryme, I->ctxpk); fmpz_mod_bpoly_clear(trymet, I->ctxpk); fmpz_mod_poly_clear(leadB, I->ctxpk); flint_free(subset); } void fmpz_bpoly_factor(fmpz_poly_t c, fmpz_tpoly_t F, fmpz_bpoly_t B) { slong i; fmpz_t alpha; fmpz_poly_t Beval; fmpz_poly_factor_t Bevalfac; slong Blengthx, Blengthy; flint_bitcnt_t Bbits; slong sumabs, maxabs; ulong pkbits; ulong k; fmpz_t p; bpoly_info_t I; k = 1; fmpz_init_set_ui(p, UWORD(1) << (FLINT_BITS - 1)); fmpz_init(alpha); fmpz_poly_init(Beval); fmpz_poly_factor_init(Bevalfac); bpoly_info_init(I, 2, p, k); Blengthx = B->length; FLINT_ASSERT(Blengthx > 1); fmpz_bpoly_make_primitive(c, B); fmpz_zero(alpha); goto got_alpha; next_alpha: fmpz_neg(alpha, alpha); fmpz_add_ui(alpha, alpha, fmpz_sgn(alpha) >= 0); got_alpha: fmpz_bpoly_eval(Beval, B, alpha); /* if killed leading coeff, get new alpha */ if (Beval->length != Blengthx) goto next_alpha; fmpz_one(&Bevalfac->c); fmpz_poly_factor(Bevalfac, Beval); /* if multiple factors, get new alpha */ for (i = 0; i < Bevalfac->num; i++) { if (Bevalfac->exp[i] != 1) goto next_alpha; } /* if one factor, B is irreducible */ if (Bevalfac->num < 2) { fmpz_tpoly_fit_length(F, 1); F->length = 1; fmpz_bpoly_swap(F->coeffs + 0, B); goto cleanup; } fmpz_bpoly_taylor_shift(B, alpha); Blengthy = 0; Bbits = 0; for (i = 0; i < B->length; i++) { slong this_bits; Blengthy = FLINT_MAX(Blengthy, B->coeffs[i].length); this_bits = _fmpz_vec_max_bits(B->coeffs[i].coeffs, B->coeffs[i].length); Bbits = FLINT_MAX(Bbits, FLINT_ABS(this_bits)); } pkbits = (FLINT_BIT_COUNT(Blengthx*Blengthy) + 1)/2; pkbits += Blengthx + Blengthy + Bbits - 3; next_prime: fmpz_nextprime(p, p, 1); FLINT_ASSERT(B->length > 0); FLINT_ASSERT((B->coeffs + B->length - 1)->length > 0); FLINT_ASSERT(!fmpz_is_zero((B->coeffs + B->length - 1)->coeffs + 0)); if (fmpz_divisible((B->coeffs + B->length - 1)->coeffs + 0, p)) goto next_prime; /* 2^pkbits is strict upperbound on the coefficient of any factor of B. An upperbound on the coefficient of any factor of B*lc_x(B) is needed. */ _fmpz_vec_sum_max_bits(&sumabs, &maxabs, B->coeffs[B->length - 1].coeffs, B->coeffs[B->length - 1].length); k = (pkbits + sumabs + fmpz_bits(p))/fmpz_bits(p); bpoly_info_clear(I); bpoly_info_init(I, Bevalfac->num, p, k); I->lifting_prec = Blengthy + (B->coeffs + B->length - 1)->length; fmpz_mod_bpoly_set_fmpz_bpoly(I->Btilde, B, I->ctxpk); fmpz_mod_bpoly_make_monic_series(I->Btilde, I->Btilde, I->lifting_prec, I->ctxpk); for (i = 0; i < I->r; i++) { fmpz_mod_poly_set_fmpz_poly(I->Bitilde1 + i, Bevalfac->p + i, I->ctxp); fmpz_mod_poly_make_monic(I->Bitilde1 + i, I->Bitilde1 + i, I->ctxp); fmpz_mod_poly_set_fmpz_poly(I->Bitilde + i, Bevalfac->p + i, I->ctxpk); fmpz_mod_poly_make_monic(I->Bitilde + i, I->Bitilde + i, I->ctxpk); fmpz_mod_bpoly_set_polyx(I->newBitilde + i, I->Bitilde + i, I->ctxpk); } FLINT_ASSERT(I->r > 1); if (!bpoly_info_disolve(I)) goto next_prime; if (I->r == 2) _bivar_lift_quartic2(I); else if (I->r < 20) _bivar_lift_quartic(I); else _bivar_lift_quintic(I); _recombine_naive(F, B, alpha, I); cleanup: bpoly_info_clear(I); fmpz_poly_factor_clear(Bevalfac); fmpz_poly_clear(Beval); fmpz_clear(alpha); fmpz_clear(p); } /* return 1: ok 0: lift failed -1: not primitive */ int fmpz_bpoly_factor_ordered( fmpz_poly_t c, fmpz_tpoly_t F, fmpz_bpoly_t B, const fmpz_t alpha, const fmpz_poly_factor_t Bevalf) { int success; slong i; slong Blengthx, Blengthy; flint_bitcnt_t Bbits; ulong pkbits; ulong k; slong sumabs, maxabs; fmpz_t p, malpha; bpoly_info_t I; fmpz_bpoly_t Q, trymez; fmpz_mod_bpoly_t tryme, trymet; fmpz_mod_poly_t Blead; fmpz_poly_t g; k = 1; fmpz_init_set_ui(p, UWORD(1) << (FLINT_BITS - 1)); bpoly_info_init(I, 2, p, k); fmpz_poly_init(g); fmpz_bpoly_init(Q); fmpz_bpoly_init(trymez); fmpz_mod_bpoly_init(tryme, I->ctxpk); fmpz_mod_bpoly_init(trymet, I->ctxpk); fmpz_mod_poly_init(Blead, I->ctxpk); Blengthx = B->length; FLINT_ASSERT(Blengthx > 1); fmpz_init(malpha); fmpz_bpoly_make_primitive(c, B); if (fmpz_poly_degree(c) > 0) { success = -1; goto cleanup; } fmpz_neg(malpha, alpha); fmpz_bpoly_taylor_shift(B, alpha); Blengthy = 0; Bbits = 0; for (i = 0; i < B->length; i++) { slong this_bits; Blengthy = FLINT_MAX(Blengthy, B->coeffs[i].length); this_bits = _fmpz_vec_max_bits(B->coeffs[i].coeffs, B->coeffs[i].length); Bbits = FLINT_MAX(Bbits, FLINT_ABS(this_bits)); } pkbits = (FLINT_BIT_COUNT(Blengthx*Blengthy) + 1)/2; pkbits += Blengthx + Blengthy + Bbits - 3; next_prime: fmpz_nextprime(p, p, 1); FLINT_ASSERT(B->length > 0); FLINT_ASSERT((B->coeffs + B->length - 1)->length > 0); FLINT_ASSERT(!fmpz_is_zero((B->coeffs + B->length - 1)->coeffs + 0)); if (fmpz_divisible((B->coeffs + B->length - 1)->coeffs + 0, p)) goto next_prime; _fmpz_vec_sum_max_bits(&sumabs, &maxabs, B->coeffs[B->length - 1].coeffs, B->coeffs[B->length - 1].length); k = (pkbits + sumabs + fmpz_bits(p))/fmpz_bits(p); bpoly_info_clear(I); bpoly_info_init(I, Bevalf->num, p, k); I->lifting_prec = Blengthy + (B->coeffs + B->length - 1)->length; fmpz_mod_bpoly_set_fmpz_bpoly(I->Btilde, B, I->ctxpk); fmpz_mod_bpoly_make_monic_series(I->Btilde, I->Btilde, I->lifting_prec, I->ctxpk); for (i = 0; i < I->r; i++) { fmpz_mod_poly_set_fmpz_poly(I->Bitilde1 + i, Bevalf->p + i, I->ctxp); fmpz_mod_poly_make_monic(I->Bitilde1 + i, I->Bitilde1 + i, I->ctxp); fmpz_mod_poly_set_fmpz_poly(I->Bitilde + i, Bevalf->p + i, I->ctxpk); fmpz_mod_poly_make_monic(I->Bitilde + i, I->Bitilde + i, I->ctxpk); fmpz_mod_bpoly_set_polyx(I->newBitilde + i, I->Bitilde + i, I->ctxpk); } FLINT_ASSERT(I->r > 1); if (!bpoly_info_disolve(I)) goto next_prime; if (I->r == 2) _bivar_lift_quartic2(I); else if (I->r < 20) _bivar_lift_quartic(I); else _bivar_lift_quintic(I); fmpz_tpoly_fit_length(F, I->r); F->length = 0; for (i = 0; i < I->r; i++) { fmpz_mod_poly_set_fmpz_poly(Blead, B->coeffs + B->length - 1, I->ctxpk); fmpz_mod_bpoly_set_polyy(tryme, Blead, I->ctxpk); fmpz_mod_bpoly_mul_series(trymet, tryme, I->newBitilde + i, I->lifting_prec, I->ctxpk); fmpz_mod_bpoly_swap(trymet, tryme, I->ctxpk); fmpz_bpoly_set_fmpz_mod_bpoly(trymez, tryme, I->ctxpk); fmpz_bpoly_make_primitive(g, trymez); if (!fmpz_bpoly_divides(Q, B, trymez)) { success = 0; goto cleanup; } fmpz_bpoly_swap(B, Q); fmpz_bpoly_taylor_shift(trymez, malpha); fmpz_bpoly_swap(F->coeffs + F->length, trymez); F->length++; } success = 1; cleanup: fmpz_poly_clear(g); fmpz_bpoly_clear(Q); fmpz_bpoly_clear(trymez); fmpz_mod_bpoly_clear(tryme, I->ctxpk); fmpz_mod_bpoly_clear(trymet, I->ctxpk); fmpz_mod_poly_clear(Blead, I->ctxpk); bpoly_info_clear(I); fmpz_clear(malpha); fmpz_clear(p); return success; } flint-3.1.3/src/fmpz_mpoly_factor/clear.c000066400000000000000000000014351461254215100204110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_factor_clear(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { if (f->alloc > 0) { slong i; for (i = 0; i < f->alloc; i++) { fmpz_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } flint_free(f->poly); flint_free(f->exp); } fmpz_clear(f->constant); } flint-3.1.3/src/fmpz_mpoly_factor/cmp.c000066400000000000000000000017511461254215100201030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_factor_cmp( const fmpz_mpoly_factor_t A, const fmpz_mpoly_factor_t B, const fmpz_mpoly_ctx_t ctx) { int cmp; slong i; cmp = fmpz_cmp(A->constant, B->constant); if (cmp != 0) return cmp; if (A->num != B->num) return A->num > B->num ? 1 : -1; for (i = 0; i < A->num; i++) { cmp = fmpz_cmp(A->exp + i, B->exp + i); if (cmp != 0) return cmp; cmp = fmpz_mpoly_cmp(A->poly + i, B->poly + i, ctx); if (cmp != 0) return cmp; } return 0; } flint-3.1.3/src/fmpz_mpoly_factor/compression.c000066400000000000000000000061541461254215100216670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_compression_do( fmpz_mpoly_t L, const fmpz_mpoly_ctx_t Lctx, fmpz * Acoeffs, slong Alen, mpoly_compression_t M) { slong i, max_deg; flint_bitcnt_t Lbits; slong mvars = Lctx->minfo->nvars; slong nvars = M->nvars; slong LN; FLINT_ASSERT(mvars == M->mvars); max_deg = M->degs[0]; for (i = 1; i < mvars; i++) max_deg = FLINT_MAX(max_deg, M->degs[i]); Lbits = mpoly_fix_bits(1 + FLINT_BIT_COUNT(max_deg), Lctx->minfo); fmpz_mpoly_fit_length_reset_bits(L, Alen, Lbits, Lctx); LN = mpoly_words_per_exp_sp(Lbits, Lctx->minfo); L->length = Alen; for (i = 0; i < Alen; i++) { fmpz_swap(L->coeffs + i, Acoeffs + i); mpoly_set_monomial_ui(L->exps + LN*i, (ulong *)M->exps + nvars*i, Lbits, Lctx->minfo); } fmpz_mpoly_sort_terms(L, Lctx); fmpz_mpoly_unit_normalize(L, Lctx); } void fmpz_mpoly_compression_undo( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t Actx, fmpz_mpoly_t L, const fmpz_mpoly_ctx_t Lctx, mpoly_compression_t M) { slong i, k, l; slong nvars = Actx->minfo->nvars; slong NA = mpoly_words_per_exp(Abits, Actx->minfo); slong mvars = Lctx->minfo->nvars; flint_bitcnt_t Lbits = L->bits; slong NL = mpoly_words_per_exp(Lbits, Lctx->minfo); slong * mins, * texps; TMP_INIT; FLINT_ASSERT(mvars == M->mvars); FLINT_ASSERT(fmpz_mpoly_degrees_fit_si(L, Lctx)); TMP_START; texps = (slong *) TMP_ALLOC(nvars*sizeof(slong)); mins = (slong *) TMP_ALLOC(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) mins[k] = WORD_MAX; _slong_array_fit_length(&M->exps, &M->exps_alloc, L->length*nvars); fmpz_mpoly_fit_length_reset_bits(A, L->length, Abits, Actx); _fmpz_mpoly_set_length(A, L->length, Actx); for (i = 0; i < L->length; i++) { fmpz_swap(A->coeffs + i, L->coeffs + i); mpoly_get_monomial_ui((ulong *)texps, L->exps + NL*i, Lbits, Lctx->minfo); for (k = 0; k < nvars; k++) { slong tot = M->deltas[k]; for (l = 0; l < mvars; l++) tot += M->umat[k*nvars + l]*texps[l]; M->exps[i*nvars + k] = tot; mins[k] = FLINT_MIN(mins[k], tot); } } for (i = 0; i < L->length; i++) { for (k = 0; k < nvars; k++) M->exps[i*nvars + k] -= mins[k]; mpoly_set_monomial_ui(A->exps + NA*i, (ulong *)M->exps + i*nvars, Abits, Actx->minfo); } TMP_END; fmpz_mpoly_sort_terms(A, Actx); fmpz_mpoly_unit_normalize(A, Actx); } flint-3.1.3/src/fmpz_mpoly_factor/eval.c000066400000000000000000000111221461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" /* only E and alphas are shifted by "var" so output is in E[0] and first relevant alpha is alphas[0] */ int _fmpz_mpoly_evaluate_rest_fmpz( fmpz * E, slong * starts, slong * ends, slong * stops, ulong * es, const fmpz * Acoeffs, const ulong * Aexps, slong Alen, slong var, const fmpz * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars) { slong v, stop; ulong next_e; FLINT_ASSERT(var < nvars); E -= var; alphas -= var; v = var; starts[v] = 0; ends[v] = Alen; fmpz_zero(E + v); if (Alen < 1) return 1; calculate: /* input: v starts[v] ends[v] */ FLINT_ASSERT(ends[v] > starts[v]); es[v] = mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]); fmpz_zero(E + v); next: FLINT_ASSERT(es[v] == (mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]))); stop = starts[v] + 1; while (stop < ends[v] && (mask & (Aexps[N*stop + offsets[v]] >> shifts[v])) == es[v]) { stop++; } stops[v] = stop; if (v + 1 < nvars) { starts[v + 1] = starts[v]; ends[v + 1] = stops[v]; v++; goto calculate; calculate_return: fmpz_add(E + v, E + v, E + v + 1); } else { fmpz_add(E + v, E + v, Acoeffs + starts[v]); } if (stops[v] < ends[v]) { next_e = mask & (Aexps[N*stops[v] + offsets[v]] >> shifts[v]); FLINT_ASSERT(next_e < es[v]); fmpz_pow_ui(E + v + 1, alphas + v, es[v] - next_e); fmpz_mul(E + v, E + v, E + v + 1); es[v] = next_e; starts[v] = stops[v]; goto next; } else { fmpz_pow_ui(E + v + 1, alphas + v, es[v]); fmpz_mul(E + v, E + v, E + v + 1); } if (v > var) { v--; goto calculate_return; } return 1; } void _fmpz_mpoly_eval_rest_to_poly( fmpz_poly_t E, const fmpz_mpoly_t A, const fmpz * alphas, const fmpz_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong * offsets, * shifts; slong offset, shift; slong start, stop; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * starts, * ends, * stops; ulong * es; fmpz * realE; FLINT_ASSERT(n > 1); E->length = 0; if (A->length < 1) return; starts = FLINT_ARRAY_ALLOC(n, slong); ends = FLINT_ARRAY_ALLOC(n, slong); stops = FLINT_ARRAY_ALLOC(n, slong); es = FLINT_ARRAY_ALLOC(n, ulong); realE = FLINT_ARRAY_ALLOC(n + 1, fmpz); for (i = 0; i < n + 1; i++) fmpz_init(realE + i); offsets = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); shifts = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); for (i = 0; i < ctx->minfo->nvars; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, A->bits, ctx->minfo); offset = offsets[0]; shift = shifts[0]; start = 0; e = mask & (A->exps[N*start + offset] >> shift); next: FLINT_ASSERT(start < A->length); FLINT_ASSERT(e == (mask & (A->exps[N*start + offset] >> shift))); stop = start + 1; while (stop < A->length && (mask & (A->exps[N*stop + offset] >> shift)) == e) stop++; fmpz_poly_fit_length(E, e + 1); while (E->length <= e) { fmpz_zero(E->coeffs + E->length); E->length++; } _fmpz_mpoly_evaluate_rest_fmpz(realE, starts, ends, stops, es, A->coeffs + start, A->exps + N*start, stop - start, 1, alphas, offsets, shifts, N, mask, ctx->minfo->nvars); fmpz_set(E->coeffs + e, realE + 0); if (stop < A->length) { FLINT_ASSERT(e > (mask & (A->exps[N*stop + offset] >> shift))); e = (mask & (A->exps[N*stop + offset] >> shift)); start = stop; goto next; } _fmpz_poly_normalise(E); for (i = 0; i < n + 1; i++) fmpz_clear(realE + i); flint_free(realE); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); } flint-3.1.3/src/fmpz_mpoly_factor/expand.c000066400000000000000000000021301461254215100205730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_factor_expand( fmpz_mpoly_t A, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { int success = 1; slong i; fmpz_mpoly_t t1, t2; fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); fmpz_mpoly_set_fmpz(A, f->constant, ctx); for (i = 0; i < f->num; i++) { if (fmpz_sgn(f->exp + i) < 0 || !fmpz_mpoly_pow_fmpz(t1, f->poly + i, f->exp + i, ctx)) { success = 0; goto cleanup; } fmpz_mpoly_mul(t2, A, t1, ctx); fmpz_mpoly_swap(A, t2, ctx); } cleanup: fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); return success; } flint-3.1.3/src/fmpz_mpoly_factor/factor.c000066400000000000000000000526611461254215100206100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" /* A has degree 2 wrt gen(0) */ static void _apply_quadratic( fmpz_mpolyv_t Af, fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; slong shift, off, N; flint_bitcnt_t bits = A->bits; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); fmpz_mpoly_t a_mock, b_mock, c_mock; fmpz_mpoly_t t0, t1, t2, t3; FLINT_ASSERT(A->length > 1 || fmpz_sgn(A->coeffs + 0) > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); fmpz_mpoly_init(t0, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); fmpz_mpoly_init(t3, ctx); mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo); N = mpoly_words_per_exp_sp(bits, ctx->minfo); i = 0; a_mock->exps = A->exps + N*i; a_mock->coeffs = A->coeffs + i; a_mock->bits = bits; while (i < A->length && (mask & (A->exps[N*i + off] >> shift)) == 2) i++; a_mock->length = i; a_mock->alloc = a_mock->length; b_mock->exps = A->exps + N*i; b_mock->coeffs = A->coeffs + i; b_mock->bits = bits; while (i < A->length && (mask & (A->exps[N*i + off] >> shift)) == 1) i++; b_mock->length = i - a_mock->length; b_mock->alloc = b_mock->length; c_mock->exps = A->exps + N*i; c_mock->coeffs = A->coeffs + i; c_mock->bits = bits; c_mock->length = A->length - i; c_mock->alloc = c_mock->length; FLINT_ASSERT(a_mock->length > 0); FLINT_ASSERT(c_mock->length > 0); fmpz_mpoly_mul(t0, b_mock, b_mock, ctx); fmpz_mpoly_mul(t1, a_mock, c_mock, ctx); fmpz_mpoly_scalar_mul_si(t1, t1, 4, ctx); fmpz_mpoly_sub(t2, t0, t1, ctx); if (!fmpz_mpoly_sqrt(t0, t2, ctx)) { fmpz_mpolyv_fit_length(Af, 1, ctx); Af->length = 1; fmpz_mpoly_swap(Af->coeffs + 0, A, ctx); goto cleanup; } fmpz_mpoly_add(t2, t0, b_mock, ctx); fmpz_mpoly_scalar_divides_si(t2, t2, 2, ctx); fmpz_mpoly_gcd_cofactors(t0, t1, t2, a_mock, t2, ctx); fmpz_mpoly_divides(t3, c_mock, t2, ctx); fmpz_mpolyv_fit_length(Af, 2, ctx); Af->length = 2; fmpz_mpoly_add(Af->coeffs + 0, t1, t2, ctx); fmpz_mpoly_add(Af->coeffs + 1, t0, t3, ctx); cleanup: fmpz_mpoly_clear(t0, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_clear(t3, ctx); } /* A is squarefree and primitive wrt gen(0) */ static int _factor_irred_compressed( fmpz_mpolyv_t Af, fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i; slong * Adegs; flint_bitcnt_t Abits; fmpz_poly_t u; fmpz_poly_factor_t uf; fmpz_mpoly_t lcA; fmpz_mpoly_factor_t lcAf; zassenhaus_prune_t Z; flint_rand_t state; FLINT_ASSERT(A->length > 1 || fmpz_sgn(A->coeffs + 0) > 0); FLINT_ASSERT(fmpz_mpoly_degrees_fit_si(A, ctx)); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(fmpz_mpoly_is_canonical(A, ctx)); if (A->bits > FLINT_BITS && !fmpz_mpoly_repack_bits_inplace(A, FLINT_BITS, ctx)) { return 0; } Abits = A->bits; flint_randinit(state); fmpz_poly_init(u); fmpz_poly_factor_init(uf); fmpz_mpoly_init(lcA, ctx); fmpz_mpoly_factor_init(lcAf, ctx); zassenhaus_prune_init(Z); Adegs = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); fmpz_mpoly_degrees_si(Adegs, A, ctx); /* init done */ if (Adegs[0] == 1) { fmpz_mpolyv_fit_length(Af, 1, ctx); Af->length = 1; fmpz_mpoly_swap(Af->coeffs + 0, A, ctx); success = 1; goto cleanup; } else if (Adegs[0] == 2) { _apply_quadratic(Af, A, ctx); success = 1; goto cleanup; } if (ctx->minfo->nvars < 2) { fmpz_mpoly_get_fmpz_poly(u, A, 0, ctx); fmpz_poly_factor(uf, u); FLINT_ASSERT(fmpz_is_pm1(&uf->c)); fmpz_mpolyv_fit_length(Af, uf->num, ctx); Af->length = uf->num; for (i = 0; i < uf->num; i++) { FLINT_ASSERT(uf->exp[i] == 1); _fmpz_mpoly_set_fmpz_poly(Af->coeffs + i, Abits, uf->p[i].coeffs, uf->p[i].length, 0, ctx); } success = 1; } else if (ctx->minfo->nvars == 2) { fmpz_bpoly_t b; fmpz_tpoly_t bf; fmpz_bpoly_init(b); fmpz_tpoly_init(bf); fmpz_mpoly_get_bpoly(b, A, 0, 1, ctx); fmpz_bpoly_factor(u, bf, b); FLINT_ASSERT(u->length == 1 && fmpz_is_pm1(u->coeffs + 0)); fmpz_mpolyv_fit_length(Af, bf->length, ctx); Af->length = bf->length; for (i = 0; i < bf->length; i++) { fmpz_mpoly_set_fmpz_bpoly(Af->coeffs + i, Abits, bf->coeffs + i, 0, 1, ctx); } fmpz_bpoly_clear(b); fmpz_tpoly_clear(bf); success = 1; } else { int zero_ok, trying_zero, image_count, sqrfree, irr_fac; ulong alpha_modulus; double density; fmpz * alpha; zassenhaus_prune_set_degree(Z, Adegs[0]); /* some simple checks */ alpha = _fmpz_vec_init(ctx->minfo->nvars - 1); zero_ok = 0; trying_zero = 1; alpha_modulus = 5; image_count = 0; goto got_alpha; next_alpha: trying_zero = 0; if (++alpha_modulus > 10) goto done_alpha; for (i = 0; i < ctx->minfo->nvars - 1; i++) { slong a = n_urandint(state, alpha_modulus); a -= alpha_modulus/2; fmpz_set_si(alpha + i, a); } got_alpha: _fmpz_mpoly_eval_rest_to_poly(u, A, alpha, ctx); if (fmpz_poly_degree(u) != Adegs[0]) goto next_alpha; fmpz_poly_factor(uf, u); zassenhaus_prune_start_add_factors(Z); sqrfree = 1; for (i = 0; i < uf->num; i++) { if (uf->exp[i] != 1) sqrfree = 0; zassenhaus_prune_add_factor(Z, fmpz_poly_degree(uf->p + i), uf->exp[i]); } zassenhaus_prune_end_add_factors(Z); if (!sqrfree) goto next_alpha; zero_ok = zero_ok || trying_zero; if (++image_count < 3) goto next_alpha; done_alpha: _fmpz_vec_clear(alpha, ctx->minfo->nvars - 1); /* simple check done */ if (zassenhaus_prune_must_be_irreducible(Z)) { fmpz_mpolyv_fit_length(Af, 1, ctx); Af->length = 1; fmpz_mpoly_swap(Af->coeffs + 0, A, ctx); success = 1; goto cleanup; } density = A->length; for (i = 0; i < ctx->minfo->nvars; i++) density /= Adegs[i] + 1; success = 0; if (!(algo & (MPOLY_FACTOR_USE_WANG | MPOLY_FACTOR_USE_ZIP))) goto try_zassenhaus; _fmpz_mpoly_get_lead0(lcA, A, ctx); if (!fmpz_mpoly_factor_squarefree(lcAf, lcA, ctx)) goto try_zassenhaus; irr_fac = 1; for (i = 0; i < lcAf->num; i++) irr_fac = irr_fac && lcAf->poly[i].length < 4; irr_fac = irr_fac && fmpz_mpoly_factor_irred(lcAf, ctx, algo); if (!(algo & MPOLY_FACTOR_USE_ZIP)) { success = fmpz_mpoly_factor_irred_wang(Af, A, lcAf, irr_fac, lcA, ctx, state, Z, 1); } else if (!(algo & MPOLY_FACTOR_USE_WANG)) { success = fmpz_mpoly_factor_irred_zippel(Af, A, lcAf, irr_fac, lcA, ctx, state, Z); } else { if (density > 0.002 && zero_ok) success = fmpz_mpoly_factor_irred_wang(Af, A, lcAf, irr_fac, lcA, ctx, state, Z, 0); if (success == 0 && density > 0.04) success = fmpz_mpoly_factor_irred_wang(Af, A, lcAf, irr_fac, lcA, ctx, state, Z, 1); if (success == 0) success = fmpz_mpoly_factor_irred_zippel(Af, A, lcAf, irr_fac, lcA, ctx, state, Z); if (success == 0) success = fmpz_mpoly_factor_irred_wang(Af, A, lcAf, irr_fac, lcA, ctx, state, Z, 1); } try_zassenhaus: if (algo & MPOLY_FACTOR_USE_ZAS) { if (success == 0) success = fmpz_mpoly_factor_irred_zassenhaus(Af, A, ctx, Z); } success = (success > 0); } cleanup: flint_randclear(state); fmpz_poly_clear(u); fmpz_poly_factor_clear(uf); fmpz_mpoly_clear(lcA, ctx); fmpz_mpoly_factor_clear(lcAf, ctx); zassenhaus_prune_clear(Z); flint_free(Adegs); FLINT_ASSERT(success == 0 || success == 1); return success; } /* replace f by a content factorization, f is already squarefree */ static int _refine_content_factors( fmpz_mpolyv_t f, fmpz_mpolyv_t g, /* temp */ flint_bitcnt_t bits, fmpz_mpoly_univar_t u, /* temp */ const fmpz_mpoly_ctx_t ctx) { int success; slong v, i, j; fmpz_mpoly_struct * c; for (v = 1; v < ctx->minfo->nvars; v++) { g->length = 0; for (j = 0; j < f->length; j++) { fmpz_mpoly_to_univar(u, f->coeffs + j, v, ctx); FLINT_ASSERT(u->length > 0); FLINT_ASSERT(fmpz_is_zero(u->exps + u->length - 1)); fmpz_mpolyv_fit_length(g, g->length + 1, ctx); c = g->coeffs + g->length; success = _fmpz_mpoly_vec_content_mpoly(c, u->coeffs, u->length, ctx); if (!success) return 0; if (fmpz_mpoly_is_fmpz(c, ctx)) { fmpz_mpoly_swap(c, f->coeffs + j, ctx); g->length++; } else { for (i = 0; i < u->length; i++) { success = fmpz_mpoly_divides(u->coeffs + i, u->coeffs + i, c, ctx); FLINT_ASSERT(success); } g->length++; if (u->length > 1) { fmpz_mpolyv_fit_length(g, g->length + 1, ctx); c = g->coeffs + g->length; _fmpz_mpoly_from_univar(c, bits, u, v, ctx); g->length++; } else { FLINT_ASSERT(fmpz_mpoly_is_one(u->coeffs + 0, ctx)); } } } fmpz_mpolyv_swap(f, g, ctx); } return 1; } /* A is primitive w.r.t to any variable appearing in A. A is squarefree with positive lead coeff. return 1 for success, 0 for failure */ static int _factor_irred( fmpz_mpolyv_t Af, fmpz_mpoly_t A, const fmpz_mpoly_ctx_t Actx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t Abits; mpoly_compression_t M; #if FLINT_WANT_ASSERT fmpz_mpoly_t Aorg; fmpz_mpoly_init(Aorg, Actx); fmpz_mpoly_set(Aorg, A, Actx); #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(fmpz_sgn(A->coeffs + 0) > 0); if (A->length < 2) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(!fmpz_mpoly_is_fmpz(A, Actx)); fmpz_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; fmpz_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; goto cleanup_less; } if (A->bits > FLINT_BITS && !fmpz_mpoly_repack_bits_inplace(A, FLINT_BITS, Actx)) { success = 0; goto cleanup_less; } Abits = A->bits; mpoly_compression_init(M); mpoly_compression_set(M, A->exps, A->bits, A->length, Actx->minfo); if (M->is_irred) { fmpz_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; fmpz_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; } else if (M->is_trivial) { success = _factor_irred_compressed(Af, A, Actx, algo); } else { fmpz_mpoly_ctx_t Lctx; fmpz_mpoly_t L; fmpz_mpoly_univar_t U; fmpz_mpoly_t t; fmpz_mpolyv_t Lf, tf, sf; fmpz_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX); fmpz_mpoly_init(L, Lctx); fmpz_mpolyv_init(Lf, Lctx); fmpz_mpoly_init(t, Lctx); fmpz_mpoly_univar_init(U, Lctx); fmpz_mpolyv_init(tf, Lctx); fmpz_mpolyv_init(sf, Lctx); fmpz_mpoly_compression_do(L, Lctx, A->coeffs, A->length, M); fmpz_mpoly_to_univar(U, L, 0, Lctx); success = _fmpz_mpoly_vec_content_mpoly(t, U->coeffs, U->length, Lctx); if (!success) goto cleanup_more; if (!fmpz_mpoly_is_fmpz(t, Lctx)) { success = fmpz_mpoly_divides(L, L, t, Lctx); FLINT_ASSERT(success); fmpz_mpoly_unit_normalize(L, Lctx); fmpz_mpolyv_fit_length(sf, 2, Lctx); sf->length = 2; fmpz_mpoly_swap(sf->coeffs + 0, L, Lctx); fmpz_mpoly_swap(sf->coeffs + 1, t, Lctx); success = _refine_content_factors(sf, tf, Abits, U, Lctx); if (!success) goto cleanup_more; Lf->length = 0; for (i = 0; i < sf->length; i++) { success = _factor_irred(tf, sf->coeffs + i, Lctx, algo); if (!success) goto cleanup_more; fmpz_mpolyv_fit_length(Lf, Lf->length + tf->length, Lctx); for (j = 0; j < tf->length; j++) fmpz_mpoly_swap(Lf->coeffs + Lf->length++, tf->coeffs + j, Lctx); } } else { success = _factor_irred_compressed(Lf, L, Lctx, algo); } cleanup_more: fmpz_mpoly_clear(t, Lctx); fmpz_mpoly_univar_clear(U, Lctx); fmpz_mpolyv_clear(tf, Lctx); fmpz_mpolyv_clear(sf, Lctx); if (success) { fmpz_mpolyv_fit_length(Af, Lf->length, Actx); Af->length = Lf->length; for (i = 0; i < Lf->length; i++) { fmpz_mpoly_compression_undo(Af->coeffs + i, Abits, Actx, Lf->coeffs + i, Lctx, M); } } fmpz_mpoly_clear(L, Lctx); fmpz_mpolyv_clear(Lf, Lctx); fmpz_mpoly_ctx_clear(Lctx); } mpoly_compression_clear(M); cleanup_less: #if FLINT_WANT_ASSERT if (success) { fmpz_mpoly_t prod; fmpz_mpoly_init(prod, Actx); fmpz_mpoly_one(prod, Actx); for (i = 0; i < Af->length; i++) fmpz_mpoly_mul(prod, prod, Af->coeffs + i, Actx); FLINT_ASSERT(fmpz_mpoly_equal(prod, Aorg, Actx)); fmpz_mpoly_clear(prod, Actx); fmpz_mpoly_clear(Aorg, Actx); } #endif FLINT_ASSERT(success == 0 || success == 1); return success; } /* for each factor A in f, assume A satisfies _factor_irred requirements: A is primitive w.r.t to any variable appearing in A. A is squarefree with positive lead coeff. Replace f by and irreducible factorization. */ int fmpz_mpoly_factor_irred( fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; fmpz_mpolyv_t t; fmpz_mpoly_factor_t g; fmpz_mpolyv_init(t, ctx); fmpz_mpoly_factor_init(g, ctx); fmpz_swap(g->constant, f->constant); g->num = 0; for (j = 0; j < f->num; j++) { success = _factor_irred(t, f->poly + j, ctx, algo); if (!success) goto cleanup; fmpz_mpoly_factor_fit_length(g, g->num + t->length, ctx); for (i = 0; i < t->length; i++) { fmpz_set(g->exp + g->num, f->exp + j); fmpz_mpoly_swap(g->poly + g->num, t->coeffs + i, ctx); g->num++; } } fmpz_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fmpz_mpolyv_clear(t, ctx); fmpz_mpoly_factor_clear(g, ctx); return success; } /* append factor(f)^e to g assumping f is compressed and content free */ static int _compressed_content_to_irred( fmpz_mpoly_factor_t g, fmpz_mpoly_t f, const fmpz_t e, const fmpz_mpoly_ctx_t ctx, unsigned int algo) { int success; slong j, k; fmpz_mpoly_factor_t h; fmpz_mpolyv_t v; fmpz_mpoly_factor_init(h, ctx); fmpz_mpolyv_init(v, ctx); success = _fmpz_mpoly_factor_squarefree(h, f, e, ctx); if (!success) goto cleanup; for (j = 0; j < h->num; j++) { success = h->num > 1 ? _factor_irred(v, h->poly + j, ctx, algo) : _factor_irred_compressed(v, h->poly + j, ctx, algo); if (!success) goto cleanup; fmpz_mpoly_factor_fit_length(g, g->num + v->length, ctx); for (k = 0; k < v->length; k++) { fmpz_set(g->exp + g->num, h->exp + j); fmpz_mpoly_swap(g->poly + g->num, v->coeffs + k, ctx); g->num++; } } cleanup: fmpz_mpoly_factor_clear(h, ctx); fmpz_mpolyv_clear(v, ctx); return success; } /* no assumptions on A, returned factors are irreducible */ static int _factor( fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t bits; fmpz_mpoly_factor_t g; mpoly_compression_t M; if (!fmpz_mpoly_factor_content(f, A, ctx)) return 0; fmpz_mpoly_factor_init(g, ctx); mpoly_compression_init(M); /* write into g */ fmpz_swap(g->constant, f->constant); g->num = 0; for (i = 0; i < f->num; i++) { if (f->poly[i].length < 2) { fmpz_mpoly_factor_fit_length(g, g->num + 1, ctx); fmpz_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; continue; } if (f->poly[i].bits > FLINT_BITS && !fmpz_mpoly_repack_bits_inplace(f->poly + i, FLINT_BITS, ctx)) { success = 0; goto cleanup; } bits = f->poly[i].bits; mpoly_compression_set(M, f->poly[i].exps, bits, f->poly[i].length, ctx->minfo); if (M->is_irred) { fmpz_mpoly_factor_fit_length(g, g->num + 1, ctx); fmpz_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; } else if (M->is_trivial) { success = _compressed_content_to_irred(g, f->poly + i, f->exp + i, ctx, algo); if (!success) goto cleanup; } else { fmpz_mpoly_ctx_t Lctx; fmpz_mpoly_t L; fmpz_mpoly_factor_t h; /* compression may have messed up the content factorization */ fmpz_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX); fmpz_mpoly_init(L, Lctx); fmpz_mpoly_factor_init(h, Lctx); fmpz_mpoly_compression_do(L, Lctx, f->poly[i].coeffs, f->poly[i].length, M); if (M->is_perm) { success = _compressed_content_to_irred(h, L, f->exp + i, Lctx, algo); fmpz_one(f->exp + i); } else { success = fmpz_mpoly_factor_squarefree(h, L, Lctx) && fmpz_mpoly_factor_irred(h, Lctx, algo); } if (success) { FLINT_ASSERT(fmpz_is_one(h->constant)); fmpz_mpoly_factor_fit_length(g, g->num + h->num, ctx); for (j = 0; j < h->num; j++) { fmpz_mul(g->exp + g->num, f->exp + i, h->exp + j); fmpz_mpoly_compression_undo(g->poly + g->num, bits, ctx, h->poly + j, Lctx, M); g->num++; } } fmpz_mpoly_factor_clear(h, Lctx); fmpz_mpoly_clear(L, Lctx); fmpz_mpoly_ctx_clear(Lctx); if (!success) goto cleanup; } } fmpz_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fmpz_mpoly_factor_clear(g, ctx); mpoly_compression_clear(M); FLINT_ASSERT(!success || fmpz_mpoly_factor_matches(A, f, ctx)); return success; } int fmpz_mpoly_factor( fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return _factor(f, A, ctx, MPOLY_FACTOR_USE_ALL); } int fmpz_mpoly_factor_zassenhaus( fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return _factor(f, A, ctx, MPOLY_FACTOR_USE_ZAS); } int fmpz_mpoly_factor_wang( fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return _factor(f, A, ctx, MPOLY_FACTOR_USE_WANG); } int fmpz_mpoly_factor_zippel( fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { return _factor(f, A, ctx, MPOLY_FACTOR_USE_ZIP); } flint-3.1.3/src/fmpz_mpoly_factor/factor_bound_si.c000066400000000000000000000025021461254215100224570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "fmpz.h" #include "fmpz_mpoly_factor.h" /* If |f|_infty <= A and degs hold the degrees of f, set B to a bound on |g|_infty for any divisor g of f. Return 1 for success, 0 for failure. */ int fmpz_mpoly_factor_bound_si(fmpz_t B, const fmpz_t A, const slong * degs, slong nvars) { slong i, n = 0; fmpz_t t; FLINT_ASSERT(nvars > 0); fmpz_init_set_ui(t, 1); for (i = 1; i < nvars; i++) { if (degs[i] < 0) { fmpz_clear(t); fmpz_zero(B); return 1; } fmpz_mul_ui(t, t, degs[i] + 1); if (z_add_checked(&n, n, degs[i])) { fmpz_clear(t); return 0; } } fmpz_cdiv_q_2exp(t, t, nvars); fmpz_sqrt(t, t); fmpz_add_ui(t, t, 1); fmpz_mul(B, A, t); fmpz_mul_2exp(B, B, n); fmpz_abs(B, B); fmpz_clear(t); return 1; } flint-3.1.3/src/fmpz_mpoly_factor/factor_content.c000066400000000000000000000122001461254215100223230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" /* either give a non-trivial split a = f*g or establish that a is primitive wrt all variables return: 1: split a = f*g 0: a is primitive wrt all variables (f & g undefined) -1: failed */ static int _split( fmpz_mpoly_t f, fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_t a_vars_left, const fmpz_mpoly_ctx_t ctx, fmpz_mpoly_univar_struct * u, /* temp */ slong * vars) { slong i, j, v; slong nvars = ctx->minfo->nvars; slong mvars = 0; for (v = 0; v < nvars; v++) { if (!fmpz_tstbit(a_vars_left, v)) continue; fmpz_mpoly_to_univar(u + v, a, v, ctx); vars[mvars] = v; mvars++; } if (mvars < 1) return 0; /* sort vars by decreasing length */ for (i = 1; i < mvars; i++) for (j = i; j > 0 && u[vars[j]].length > u[vars[j - 1]].length; j--) FLINT_SWAP(slong, vars[j], vars[j - 1]); for (i = 0; i < mvars; i++) { v = vars[i]; FLINT_ASSERT(fmpz_tstbit(a_vars_left, v)); fmpz_clrbit(a_vars_left, v); if (u[v].length < 2) { FLINT_ASSERT(u[v].length == 1); FLINT_ASSERT(fmpz_is_zero(u[v].exps + 0)); continue; } if (!_fmpz_mpoly_vec_content_mpoly(g, u[v].coeffs, u[v].length, ctx)) return -1; if (g->length < 2) { FLINT_ASSERT(fmpz_mpoly_is_one(g, ctx)); continue; } fmpz_mpoly_divides(f, a, g, ctx); FLINT_ASSERT(f->length > 1); return 1; } return 0; } /* return factors that are primitive wrt each variable */ int fmpz_mpoly_factor_content( fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { int success; slong nvars = ctx->minfo->nvars; slong v; fmpz_mpoly_univar_struct * u; fmpz_mpoly_factor_t g; /* exponents are bitsets */ slong * vars; f->num = 0; if (fmpz_mpoly_is_fmpz(A, ctx)) { fmpz_mpoly_get_fmpz(f->constant, A, ctx); return 1; } vars = FLINT_ARRAY_ALLOC(nvars, slong); fmpz_mpoly_factor_init(g, ctx); u = FLINT_ARRAY_ALLOC(nvars, fmpz_mpoly_univar_struct); for (v = 0; v < nvars; v++) fmpz_mpoly_univar_init(u + v, ctx); /* remove leading coefficient */ FLINT_ASSERT(A->length > 0); _fmpz_vec_content(f->constant, A->coeffs, A->length); if (fmpz_sgn(A->coeffs + 0) < 0) fmpz_neg(f->constant, f->constant); fmpz_mpoly_factor_fit_length(g, nvars, ctx); fmpz_mpoly_scalar_divexact_fmpz(g->poly + 0, A, f->constant, ctx); /* remove monomial divisors */ mpoly_remove_var_powers(g->exp, g->poly[0].exps, g->poly[0].bits, g->poly[0].length, ctx->minfo); for (v = 0; v < nvars; v++) { if (fmpz_is_zero(g->exp + v)) continue; fmpz_mpoly_factor_fit_length(f, f->num + 1, ctx); fmpz_mpoly_gen(f->poly + f->num, v, ctx); fmpz_swap(f->exp + f->num, g->exp + v); f->num++; } /* done if g->poly[0] is constant */ if (g->poly[0].length == 1) { FLINT_ASSERT(fmpz_mpoly_is_one(g->poly + 0, ctx)); success = 1; goto cleanup; } /* g has length one and no variable has been checked yet */ fmpz_one(g->exp + 0); fmpz_mul_2exp(g->exp + 0, g->exp + 0, nvars); fmpz_sub_ui(g->exp + 0, g->exp + 0, 1); g->num = 1; while (g->num > 0) { slong t = g->num - 1; fmpz_mpoly_factor_fit_length(g, t + 3, ctx); success = _split(g->poly + t + 2, g->poly + t + 1, g->poly + t, g->exp + t, ctx, u, vars); if (success < 0) { success = 0; goto cleanup; } else if (success == 0) { FLINT_ASSERT(!fmpz_mpoly_is_fmpz(g->poly + t, ctx)); fmpz_mpoly_factor_fit_length(f, f->num + 1, ctx); fmpz_mpoly_swap(f->poly + f->num, g->poly + t, ctx); fmpz_one(f->exp + f->num); f->num++; g->num = t; } else { FLINT_ASSERT(!fmpz_mpoly_is_fmpz(g->poly + t + 1, ctx)); FLINT_ASSERT(!fmpz_mpoly_is_fmpz(g->poly + t + 2, ctx)); fmpz_mpoly_swap(g->poly + t, g->poly + t + 2, ctx); fmpz_set(g->exp + t + 1, g->exp + t); g->num = t + 2; } } success = 1; cleanup: fmpz_mpoly_factor_clear(g, ctx); for (v = 0; v < nvars; v++) fmpz_mpoly_univar_clear(u + v, ctx); flint_free(u); flint_free(vars); FLINT_ASSERT(!success || fmpz_mpoly_factor_matches(A, f, ctx)); return success; } flint-3.1.3/src/fmpz_mpoly_factor/factor_squarefree.c000066400000000000000000000065251461254215100230300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" static void _fmpz_mpoly_factor_mul_mpoly_fmpz( fmpz_mpoly_factor_t f, fmpz_mpoly_t A, const fmpz_t e, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_fmpz(A, ctx)) { fmpz_t t; fmpz_init(t); fmpz_mpoly_get_fmpz(t, A, ctx); fmpz_pow_fmpz(t, t, e); fmpz_mul(f->constant, f->constant, t); fmpz_clear(t); } else { fmpz_mpoly_factor_append_fmpz_swap(f, A, e, ctx); } } /* append factor_squarefree(A)^e to f assuming is A is primitive wrt to each variable */ int _fmpz_mpoly_factor_squarefree( fmpz_mpoly_factor_t f, fmpz_mpoly_t A, const fmpz_t e, const fmpz_mpoly_ctx_t ctx) { int success; slong v; fmpz_t k, ke; fmpz_mpoly_t S, Sp, Sm, Ss, Y, Z; if (A->length < 2) { _fmpz_mpoly_factor_mul_mpoly_fmpz(f, A, e, ctx); return 1; } fmpz_init(k); fmpz_init(ke); fmpz_mpoly_init(S, ctx); fmpz_mpoly_init(Sp, ctx); fmpz_mpoly_init(Sm, ctx); fmpz_mpoly_init(Ss, ctx); fmpz_mpoly_init(Y, ctx); fmpz_mpoly_init(Z, ctx); for (v = 0; v < ctx->minfo->nvars; v++) { fmpz_mpoly_derivative(Sp, A, v, ctx); if (fmpz_mpoly_is_zero(Sp, ctx)) continue; success = fmpz_mpoly_gcd_cofactors(Sm, Ss, Y, A, Sp, ctx); if (!success) continue; for (fmpz_set_ui(k, 1); !(fmpz_mpoly_derivative(Sp, Ss, v, ctx), fmpz_mpoly_sub(Z, Y, Sp, ctx), fmpz_mpoly_is_zero(Z, ctx)); fmpz_add_ui(k, k, 1)) { success = fmpz_mpoly_gcd_cofactors(S, Ss, Y, Ss, Z, ctx); if (!success) continue; fmpz_mul(ke, k, e); _fmpz_mpoly_factor_mul_mpoly_fmpz(f, S, k, ctx); } fmpz_mul(ke, k, e); _fmpz_mpoly_factor_mul_mpoly_fmpz(f, Ss, k, ctx); success = 1; goto cleanup; } success = 0; cleanup: fmpz_clear(k); fmpz_mpoly_clear(S, ctx); fmpz_mpoly_clear(Sp, ctx); fmpz_mpoly_clear(Sm, ctx); fmpz_mpoly_clear(Ss, ctx); fmpz_mpoly_clear(Y, ctx); fmpz_mpoly_clear(Z, ctx); return success; } int fmpz_mpoly_factor_squarefree( fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { int success; slong i; fmpz_mpoly_factor_t g; fmpz_mpoly_factor_init(g, ctx); success = fmpz_mpoly_factor_content(g, A, ctx); if (!success) goto cleanup; fmpz_swap(f->constant, g->constant); f->num = 0; for (i = 0; i < g->num; i++) { success = _fmpz_mpoly_factor_squarefree(f, g->poly + i, g->exp + i, ctx); if (!success) goto cleanup; } success = 1; cleanup: fmpz_mpoly_factor_clear(g, ctx); FLINT_ASSERT(!success || fmpz_mpoly_factor_matches(A, f, ctx)); return success; } flint-3.1.3/src/fmpz_mpoly_factor/fit_length.c000066400000000000000000000012761461254215100214510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" void fmpz_mpoly_factor_fit_length(fmpz_mpoly_factor_t f, slong len, const fmpz_mpoly_ctx_t ctx) { if (len > f->alloc) { len = FLINT_MAX(len, f->alloc + f->alloc/2); fmpz_mpoly_factor_realloc(f, len, ctx); } } flint-3.1.3/src/fmpz_mpoly_factor/gcd_algo.c000066400000000000000000001574371461254215100211000ustar00rootroot00000000000000/* Copyright (C) 2018-2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" /* For each j, set out[j] to the evaluation of A at x_i = alpha[i] (i != j) i.e. if nvars = 3 out[0] = A(x, alpha[1], alpha[2]) out[1] = A(alpha[0], x, alpha[2]) out[2] = A(alpha[0], alpha[1], x) If ignore[j] is nonzero, then out[j] need not be calculated, probably because we shouldn't calculate it in dense form. */ void fmpz_mpoly_evals( nmod_poly_struct * out, const int * ignore, const fmpz_mpoly_t A, ulong * Amin_exp, ulong * Amax_exp, ulong * Astride, mp_limb_t * alpha, const fmpz_mpoly_ctx_t ctx) { slong i, j; slong nvars = ctx->minfo->nvars; slong total_limit, total_length; int use_direct_LUT; ulong varexp; ulong mask; slong * offsets, * shifts; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexp = A->exps; fmpz * Acoeff = A->coeffs; mp_limb_t meval; mp_limb_t t; FLINT_ASSERT(A->bits <= FLINT_BITS); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); offsets = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); shifts = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); for (j = 0; j < ctx->minfo->nvars; j++) { nmod_poly_zero(out + j); mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, ctx->minfo); } /* two cases: (1) the Amax_exp[j] are small enough to calculate a direct LUT (2) use a LUT for exponents that are powers of two */ total_limit = A->length/256; total_limit = FLINT_MAX(WORD(9999), total_limit); total_length = 0; use_direct_LUT = 1; for (j = 0; j < ctx->minfo->nvars; j++) { total_length += Amax_exp[j] + 1; if ((ulong) total_length > (ulong) total_limit) use_direct_LUT = 0; } if (use_direct_LUT) { slong off; mp_limb_t * LUT, ** LUTvalue, ** LUTvalueinv; /* value of powers of alpha[j] */ LUT = (mp_limb_t *) flint_malloc(2*total_length*sizeof(mp_limb_t)); /* pointers into LUT */ LUTvalue = (mp_limb_t **) flint_malloc(nvars*sizeof(mp_limb_t *)); LUTvalueinv = (mp_limb_t **) flint_malloc(nvars*sizeof(mp_limb_t *)); off = 0; for (j = 0; j < nvars; j++) { ulong k; mp_limb_t alphainvj = nmod_inv(alpha[j], (out + 0)->mod); LUTvalue[j] = LUT + off; LUTvalueinv[j] = LUT + total_length + off; LUTvalue[j][0] = 1; LUTvalueinv[j][0] = 1; for (k = 0; k < Amax_exp[j]; k++) { LUTvalue[j][k + 1] = nmod_mul(LUTvalue[j][k], alpha[j], (out + 0)->mod); LUTvalueinv[j][k + 1] = nmod_mul(LUTvalueinv[j][k], alphainvj, (out + 0)->mod); } off += Amax_exp[j] + 1; } FLINT_ASSERT(off == total_length); for (i = 0; i < A->length; i++) { meval = fmpz_get_nmod(Acoeff + i, out->mod); for (j = 0; j < nvars; j++) { varexp = ((Aexp + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT(varexp <= Amax_exp[j]); meval = nmod_mul(meval, LUTvalue[j][varexp], (out + 0)->mod); } for (j = 0; j < nvars; j++) { varexp = ((Aexp + N*i)[offsets[j]]>>shifts[j])&mask; if (ignore[j]) continue; t = nmod_mul(meval, LUTvalueinv[j][varexp], (out + j)->mod); FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexp = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; t = nmod_add(t, nmod_poly_get_coeff_ui(out + j, varexp), (out + j)->mod); nmod_poly_set_coeff_ui(out + j, varexp, t); } } flint_free(LUT); flint_free(LUTvalue); flint_free(LUTvalueinv); } else { slong LUTlen; ulong * LUTmask; slong * LUToffset, * LUTvar; mp_limb_t * LUTvalue, * LUTvalueinv; mp_limb_t * vieval; mp_limb_t t, xpoweval, xinvpoweval; LUToffset = (slong *) flint_malloc(N*FLINT_BITS*sizeof(slong)); LUTmask = (ulong *) flint_malloc(N*FLINT_BITS*sizeof(ulong)); LUTvalue = (mp_limb_t *) flint_malloc(N*FLINT_BITS*sizeof(mp_limb_t)); LUTvar = (slong *) flint_malloc(N*FLINT_BITS*sizeof(slong)); LUTvalueinv = (mp_limb_t *) flint_malloc(N*FLINT_BITS*sizeof(mp_limb_t)); vieval = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); LUTlen = 0; for (j = nvars - 1; j >= 0; j--) { flint_bitcnt_t bits = FLINT_BIT_COUNT(Amax_exp[j]); xpoweval = alpha[j]; /* xpoweval = alpha[j]^(2^i) */ xinvpoweval = nmod_inv(xpoweval, (out + 0)->mod); /* alpha[j]^(-2^i) */ for (i = 0; i < bits; i++) { LUToffset[LUTlen] = offsets[j]; LUTmask[LUTlen] = (UWORD(1) << (shifts[j] + i)); LUTvalue[LUTlen] = xpoweval; LUTvalueinv[LUTlen] = xinvpoweval; LUTvar[LUTlen] = j; LUTlen++; xpoweval = nmod_mul(xpoweval, xpoweval, (out + 0)->mod); xinvpoweval = nmod_mul(xinvpoweval, xinvpoweval, (out + 0)->mod); } vieval[j] = 1; } FLINT_ASSERT(LUTlen < N*FLINT_BITS); for (i = 0; i < A->length; i++) { meval = fmpz_get_nmod(Acoeff + i, (out + 0)->mod); for (j = 0; j < LUTlen; j++) { if (((Aexp + N*i)[LUToffset[j]] & LUTmask[j]) != 0) { meval = nmod_mul(meval, LUTvalue[j], (out + 0)->mod); vieval[LUTvar[j]] = nmod_mul(vieval[LUTvar[j]], LUTvalueinv[j], (out + 0)->mod); } } for (j = 0; j < nvars; j++) { varexp = ((Aexp + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexp = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; t = nmod_mul(meval, vieval[j], (out + j)->mod); t = nmod_add(t, nmod_poly_get_coeff_ui(out + j, varexp), (out + j)->mod); nmod_poly_set_coeff_ui(out + j, varexp, t); vieval[j] = 1; } } flint_free(LUToffset); flint_free(LUTmask); flint_free(LUTvalue); flint_free(LUTvar); flint_free(LUTvalueinv); flint_free(vieval); } flint_free(offsets); flint_free(shifts); } void _set_estimates( mpoly_gcd_info_t I, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int try_count = 0; slong i, j; nmod_poly_t Geval; nmod_poly_struct * Aevals, * Bevals; mp_limb_t p = UWORD(1) << (FLINT_BITS - 1); mp_limb_t * alpha; flint_rand_t randstate; slong ignore_limit; int * ignore; flint_randinit(randstate); ignore = (int *) flint_malloc(ctx->minfo->nvars*sizeof(int)); alpha = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); Aevals = (nmod_poly_struct *) flint_malloc( ctx->minfo->nvars*sizeof(nmod_poly_struct)); Bevals = (nmod_poly_struct *) flint_malloc( ctx->minfo->nvars*sizeof(nmod_poly_struct)); nmod_poly_init(Geval, p); for (j = 0; j < ctx->minfo->nvars; j++) { nmod_poly_init(Aevals + j, p); nmod_poly_init(Bevals + j, p); } ignore_limit = A->length/4096 + B->length/4096; ignore_limit = FLINT_MAX(WORD(9999), ignore_limit); I->Gdeflate_deg_bounds_are_nice = 1; for (j = 0; j < ctx->minfo->nvars; j++) { if ( I->Adeflate_deg[j] > ignore_limit || I->Bdeflate_deg[j] > ignore_limit) { ignore[j] = 1; I->Gdeflate_deg_bounds_are_nice = 0; } else { ignore[j] = 0; } } try_again: if (++try_count > 10) { I->Gdeflate_deg_bounds_are_nice = 0; for (j = 0; j < ctx->minfo->nvars; j++) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = (I->Gdeflate_deg_bound[j] + 1)/2; } goto cleanup; } p = n_nextprime(p, 1); nmod_init(&Geval->mod, p); for (j = 0; j < ctx->minfo->nvars; j++) { alpha[j] = n_urandint(randstate, p - 1) + 1; nmod_init(&(Aevals + j)->mod, p); nmod_init(&(Bevals + j)->mod, p); } fmpz_mpoly_evals(Aevals, ignore, A, I->Amin_exp, I->Amax_exp, I->Gstride, alpha, ctx); fmpz_mpoly_evals(Bevals, ignore, B, I->Bmin_exp, I->Bmax_exp, I->Gstride, alpha, ctx); for (j = 0; j < ctx->minfo->nvars; j++) { if (ignore[j]) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = (I->Gdeflate_deg_bound[j] + 1)/2; } else { if ( I->Adeflate_deg[j] != nmod_poly_degree(Aevals + j) || I->Bdeflate_deg[j] != nmod_poly_degree(Bevals + j)) { goto try_again; } nmod_poly_gcd(Geval, Aevals + j, Bevals + j); I->Gterm_count_est[j] = 0; I->Gdeflate_deg_bound[j] = nmod_poly_degree(Geval); for (i = I->Gdeflate_deg_bound[j]; i >= 0; i--) { I->Gterm_count_est[j] += (Geval->coeffs[i] != 0); } } } cleanup: nmod_poly_clear(Geval); for (j = 0; j < ctx->minfo->nvars; j++) { nmod_poly_clear(Aevals + j); nmod_poly_clear(Bevals + j); } flint_free(ignore); flint_free(alpha); flint_free(Aevals); flint_free(Bevals); flint_randclear(randstate); return; } /* (Abar, Bbar) = (A, B) */ static void _parallel_set( fmpz_mpoly_t Abar, /* could be NULL */ fmpz_mpoly_t Bbar, /* could be NULL */ const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { if (Abar == B && Bbar == A) { FLINT_ASSERT(Abar != NULL && Bbar != NULL); fmpz_mpoly_set(Abar, B, ctx); fmpz_mpoly_set(Bbar, A, ctx); fmpz_mpoly_swap(Abar, Bbar, ctx); } else if (Abar == B && Bbar != A) { FLINT_ASSERT(Abar != NULL); if (Bbar != NULL) fmpz_mpoly_set(Bbar, B, ctx); fmpz_mpoly_set(Abar, A, ctx); } else { if (Abar != NULL) fmpz_mpoly_set(Abar, A, ctx); if (Bbar != NULL) fmpz_mpoly_set(Bbar, B, ctx); } } /* The variables in ess(A) and ess(B) are disjoint. gcd is trivial to compute. */ static void _do_trivial( fmpz_mpoly_t G, fmpz_mpoly_t Abar, /* could be NULL */ fmpz_mpoly_t Bbar, /* could be NULL */ const fmpz_mpoly_t A, const fmpz_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mpoly_ctx_t ctx) { fmpz_t cG; fmpz_init(cG); _fmpz_vec_content(cG, A->coeffs, A->length); _fmpz_vec_content_chained(cG, B->coeffs, B->length, cG); _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) { _fmpz_vec_scalar_divexact_fmpz(Abar->coeffs, Abar->coeffs, Abar->length, cG); mpoly_monomials_shift_right_ui(Abar->exps, Abar->bits, Abar->length, I->Gmin_exp, ctx->minfo); } if (Bbar != NULL) { _fmpz_vec_scalar_divexact_fmpz(Bbar->coeffs, Bbar->coeffs, Bbar->length, cG); mpoly_monomials_shift_right_ui(Bbar->exps, Bbar->bits, Bbar->length, I->Gmin_exp, ctx->minfo); } fmpz_mpoly_fit_length_reset_bits(G, 1, I->Gbits, ctx); mpoly_set_monomial_ui(G->exps, I->Gmin_exp, I->Gbits, ctx->minfo); fmpz_swap(G->coeffs + 0, cG); _fmpz_mpoly_set_length(G, 1, ctx); fmpz_clear(cG); } /*********************** Easy when B is a monomial ***************************/ static int _do_monomial_gcd( fmpz_mpoly_t G, fmpz_mpoly_t Abar, /* could be NULL */ fmpz_mpoly_t Bbar, /* could be NULL */ const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz_t g; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); fmpz * minAfields, * minAdegs, * minBdegs; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length == 1); fmpz_init(g); /* compute the coefficient of G */ _fmpz_vec_content_chained(g, A->coeffs, A->length, B->coeffs + 0); fmpz_abs(g, g); if (B->exps[0] == 0 && mpoly_monomial_is_zero(B->exps, mpoly_words_per_exp(B->bits, ctx->minfo))) { _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL && !fmpz_is_one(g)) _fmpz_vec_scalar_divexact_fmpz(Abar->coeffs, Abar->coeffs, Abar->length, g); if (Bbar != NULL && !fmpz_is_one(g)) _fmpz_vec_scalar_divexact_fmpz(Bbar->coeffs, Bbar->coeffs, Bbar->length, g); fmpz_mpoly_fit_length(G, 1, ctx); mpoly_monomial_zero(G->exps, mpoly_words_per_exp(G->bits, ctx->minfo)); goto done; } TMP_START; /* get the field-wise minimum of A */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, A->bits, ctx->minfo); /* unpack to get the min degrees of each variable in A */ minAdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minAdegs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(minAdegs, minAfields, ctx->minfo); /* get the degree of each variable in B */ minBdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minBdegs + i); mpoly_get_monomial_ffmpz(minBdegs, B->exps, B->bits, ctx->minfo); /* compute the degree of each variable in G */ _fmpz_vec_min_inplace(minBdegs, minAdegs, ctx->minfo->nvars); _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) { _fmpz_vec_scalar_divexact_fmpz(Abar->coeffs, Abar->coeffs, Abar->length, g); mpoly_monomials_shift_right_ffmpz(Abar->exps, Abar->bits, Abar->length, minBdegs, ctx->minfo); } if (Bbar != NULL) { _fmpz_vec_scalar_divexact_fmpz(Bbar->coeffs, Bbar->coeffs, Bbar->length, g); mpoly_monomials_shift_right_ffmpz(Bbar->exps, Bbar->bits, Bbar->length, minBdegs, ctx->minfo); } /* write G */ fmpz_mpoly_fit_length_reset_bits(G, 1, Gbits, ctx); mpoly_set_monomial_ffmpz(G->exps, minBdegs, Gbits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(minAfields + i); } for (i = 0; i < ctx->minfo->nvars; i++) { fmpz_clear(minAdegs + i); fmpz_clear(minBdegs + i); } TMP_END; done: fmpz_swap(G->coeffs + 0, g); _fmpz_mpoly_set_length(G, 1, ctx); fmpz_clear(g); return 1; } /********************** See if cofactors are monomials ***********************/ static int _try_monomial_cofactors( fmpz_mpoly_t G, fmpz_mpoly_t Abar, /* could be NULL */ fmpz_mpoly_t Bbar, /* could be NULL */ const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int success; slong i, j; slong NA, NG; slong nvars = ctx->minfo->nvars; fmpz * Abarexps, * Bbarexps, * Texps; fmpz_t t1, t2; fmpz_t gA, gB; fmpz_mpoly_t T; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); flint_bitcnt_t Abarbits = A->bits; flint_bitcnt_t Bbarbits = B->bits; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (A->length != B->length) return 0; fmpz_init(t1); fmpz_init(t2); fmpz_init_set(gA, A->coeffs + 0); fmpz_init_set(gB, B->coeffs + 0); for (i = A->length - 1; i > 0; i--) { fmpz_mul(t1, A->coeffs + 0, B->coeffs + i); fmpz_mul(t2, B->coeffs + 0, A->coeffs + i); success = fmpz_equal(t1, t2); if (!success) goto cleanup; fmpz_gcd(gA, gA, A->coeffs + i); fmpz_gcd(gB, gB, B->coeffs + i); } TMP_START; Abarexps = (fmpz *) TMP_ALLOC(3*nvars*sizeof(fmpz)); Bbarexps = Abarexps + 1*nvars; Texps = Abarexps + 2*nvars; for (j = 0; j < nvars; j++) { fmpz_init(Abarexps + j); fmpz_init(Bbarexps + j); fmpz_init(Texps + j); } success = mpoly_monomial_cofactors(Abarexps, Bbarexps, A->exps, A->bits, B->exps, B->bits, A->length, ctx->minfo); if (!success) goto cleanup_more; /* put A's cofactor coefficient in t1 */ fmpz_gcd(t2, gA, gB); fmpz_divexact(t1, gA, t2); if (fmpz_sgn(A->coeffs + 0) < 0) fmpz_neg(t1, t1); /* put B's cofactor coefficient in t2 */ fmpz_divexact(gA, A->coeffs + 0, t1); fmpz_divexact(t2, B->coeffs + 0, gA); fmpz_mpoly_init3(T, A->length, Gbits, ctx); NG = mpoly_words_per_exp(Gbits, ctx->minfo); NA = mpoly_words_per_exp(A->bits, ctx->minfo); T->length = A->length; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ffmpz(Texps, A->exps + NA*i, A->bits, ctx->minfo); _fmpz_vec_sub(Texps, Texps, Abarexps, nvars); mpoly_set_monomial_ffmpz(T->exps + NG*i, Texps, Gbits, ctx->minfo); fmpz_divexact(T->coeffs + i, A->coeffs + i, t1); } fmpz_mpoly_swap(G, T, ctx); fmpz_mpoly_clear(T, ctx); if (Abar != NULL) { fmpz_mpoly_fit_length_reset_bits(Abar, 1, Abarbits, ctx); mpoly_set_monomial_ffmpz(Abar->exps, Abarexps, Abarbits, ctx->minfo); fmpz_swap(Abar->coeffs + 0, t1); _fmpz_mpoly_set_length(Abar, 1, ctx); } if (Bbar != NULL) { fmpz_mpoly_fit_length_reset_bits(Bbar, 1, Bbarbits, ctx); mpoly_set_monomial_ffmpz(Bbar->exps, Bbarexps, Bbarbits, ctx->minfo); fmpz_swap(Bbar->coeffs + 0, t2); _fmpz_mpoly_set_length(Bbar, 1, ctx); } success = 1; cleanup_more: for (j = 0; j < nvars; j++) { fmpz_clear(Abarexps + j); fmpz_clear(Bbarexps + j); fmpz_clear(Texps + j); } TMP_END; cleanup: fmpz_clear(t1); fmpz_clear(t2); fmpz_clear(gA); fmpz_clear(gB); return success; } /*** ess(A) and ess(B) depend on only one variable v_in_both ****************/ static int _do_univar( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, slong v_in_both, const mpoly_gcd_info_t I, const fmpz_mpoly_ctx_t ctx) { fmpz_poly_t a, b, g, t, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(g); fmpz_poly_init(t); fmpz_poly_init(r); _fmpz_mpoly_to_fmpz_poly_deflate(a, A, v_in_both, I->Amin_exp, I->Gstride, ctx); _fmpz_mpoly_to_fmpz_poly_deflate(b, B, v_in_both, I->Bmin_exp, I->Gstride, ctx); fmpz_poly_gcd(g, a, b); _fmpz_mpoly_from_fmpz_poly_inflate(G, I->Gbits, g, v_in_both, I->Gmin_exp, I->Gstride, ctx); if (Abar != NULL) { fmpz_poly_divrem(t, r, a, g); _fmpz_mpoly_from_fmpz_poly_inflate(Abar, I->Abarbits, t, v_in_both, I->Abarmin_exp, I->Gstride, ctx); } if (Bbar != NULL) { fmpz_poly_divrem(t, r, b, g); _fmpz_mpoly_from_fmpz_poly_inflate(Bbar, I->Bbarbits, t, v_in_both, I->Bbarmin_exp, I->Gstride, ctx); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(g); fmpz_poly_clear(t); fmpz_poly_clear(r); return 1; } /********* Assume B has length one when converted to univar format ***********/ static int _try_missing_var( fmpz_mpoly_t G, flint_bitcnt_t Gbits, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, slong var, const fmpz_mpoly_t A, ulong Ashift, const fmpz_mpoly_t B, ulong Bshift, const fmpz_mpoly_ctx_t ctx) { int success; fmpz_mpoly_t tG; fmpz_mpoly_univar_t Au; fmpz_mpoly_init(tG, ctx); fmpz_mpoly_univar_init(Au, ctx); #if FLINT_WANT_ASSERT fmpz_mpoly_to_univar(Au, B, var, ctx); FLINT_ASSERT(Au->length == 1); #endif fmpz_mpoly_to_univar(Au, A, var, ctx); fmpz_mpoly_univar_fit_length(Au, Au->length + 1, ctx); fmpz_mpoly_set(Au->coeffs + Au->length, B, ctx); Au->length++; if (Abar == NULL && Bbar == NULL) { success = _fmpz_mpoly_vec_content_mpoly(G, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; fmpz_mpoly_repack_bits_inplace(G, Gbits, ctx); _mpoly_gen_shift_left(G->exps, G->bits, G->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); } else { success = _fmpz_mpoly_vec_content_mpoly(tG, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; fmpz_mpoly_repack_bits_inplace(tG, Gbits, ctx); _mpoly_gen_shift_left(tG->exps, tG->bits, tG->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); if (Abar != NULL) { success = fmpz_mpoly_divides(Abar, A, tG, ctx); FLINT_ASSERT(success); } if (Bbar != NULL) { success = fmpz_mpoly_divides(Bbar, Au->coeffs + Au->length - 1, tG, ctx); FLINT_ASSERT(success); } fmpz_mpoly_swap(G, tG, ctx); } success = 1; cleanup: fmpz_mpoly_clear(tG, ctx); fmpz_mpoly_univar_clear(Au, ctx); return success; } /************************ See if B divides A ********************************/ static int _try_divides( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t BB, const fmpz_mpoly_ctx_t ctx) { int success = 0; fmpz_mpoly_t Q, B, M; fmpz_mpoly_init(Q, ctx); fmpz_mpoly_init(B, ctx); fmpz_mpoly_init(M, ctx); /* BB = M*B */ fmpz_mpoly_term_content(M, BB, ctx); fmpz_mpoly_divides(B, BB, M, ctx); success = fmpz_mpoly_divides(Q, A, B, ctx); if (success) { _do_monomial_gcd(G, Abar, Bbar, Q, M, ctx); fmpz_mpoly_mul(G, G, B, ctx); } fmpz_mpoly_clear(Q, ctx); fmpz_mpoly_clear(B, ctx); fmpz_mpoly_clear(M, ctx); return success; } /********************* Hit A and B with a prs ********************************/ static int _try_prs( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mpoly_ctx_t ctx) { int success; slong j, var = -WORD(1); ulong score, best_score = WORD(1) << 24; fmpz_mpoly_t Ac, Bc, Gc, s, t; fmpz_mpoly_univar_t Ax, Bx, Gx; /* Pick a main variable. TODO: (1) consider the expected degree of G, and (2) add a size limit to univar_pseudo_gcd to abort the calculation if things are getting too big. */ for (j = 0; j < ctx->minfo->nvars; j++) { if (I->Amax_exp[j] <= I->Amin_exp[j] || I->Bmax_exp[j] <= I->Bmin_exp[j] /* not needed */) { FLINT_ASSERT(I->Amax_exp[j] == I->Amin_exp[j]); FLINT_ASSERT(I->Bmax_exp[j] == I->Bmin_exp[j]); continue; } FLINT_ASSERT(I->Gstride[j] != UWORD(0)); FLINT_ASSERT((I->Amax_exp[j] - I->Amin_exp[j]) % I->Gstride[j] == 0); FLINT_ASSERT((I->Bmax_exp[j] - I->Bmin_exp[j]) % I->Gstride[j] == 0); score = FLINT_BIT_COUNT(I->Alead_count[j] - 1); score *= FLINT_BIT_COUNT(I->Blead_count[j] - 1); score *= FLINT_BIT_COUNT(I->Atail_count[j] - 1); score *= FLINT_BIT_COUNT(I->Btail_count[j] - 1); score = FLINT_MAX(score, 1); if (n_mul_checked(&score, score, I->Amax_exp[j])) continue; if (n_mul_checked(&score, score, I->Bmax_exp[j])) continue; if (score < best_score) { best_score = score; var = j; } } if (var < 0) return 0; fmpz_mpoly_init(Ac, ctx); fmpz_mpoly_init(Bc, ctx); fmpz_mpoly_init(Gc, ctx); fmpz_mpoly_init(s, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_univar_init(Ax, ctx); fmpz_mpoly_univar_init(Bx, ctx); fmpz_mpoly_univar_init(Gx, ctx); fmpz_mpoly_to_univar(Ax, A, var, ctx); fmpz_mpoly_to_univar(Bx, B, var, ctx); success = _fmpz_mpoly_vec_content_mpoly(Ac, Ax->coeffs, Ax->length, ctx) && _fmpz_mpoly_vec_content_mpoly(Bc, Bx->coeffs, Bx->length, ctx) && fmpz_mpoly_gcd(Gc, Ac, Bc, ctx); if (!success) goto cleanup; _fmpz_mpoly_vec_divexact_mpoly(Ax->coeffs, Ax->length, Ac, ctx); _fmpz_mpoly_vec_divexact_mpoly(Bx->coeffs, Bx->length, Bc, ctx); success = fmpz_cmp(Ax->exps + 0, Bx->exps + 0) > 0 ? fmpz_mpoly_univar_pseudo_gcd(Gx, Ax, Bx, ctx) : fmpz_mpoly_univar_pseudo_gcd(Gx, Bx, Ax, ctx); if (!success) goto cleanup; if (fmpz_mpoly_gcd(t, Ax->coeffs + 0, Bx->coeffs + 0, ctx) && t->length == 1) { fmpz_mpoly_term_content(s, Gx->coeffs + 0, ctx); fmpz_mpoly_divexact(t, Gx->coeffs + 0, s, ctx); _fmpz_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } else if (fmpz_mpoly_gcd(t, Ax->coeffs + Ax->length - 1, Bx->coeffs + Bx->length - 1, ctx) && t->length == 1) { fmpz_mpoly_term_content(s, Gx->coeffs + Gx->length - 1, ctx); fmpz_mpoly_divexact(t, Gx->coeffs + Gx->length - 1, s, ctx); _fmpz_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } success = _fmpz_mpoly_vec_content_mpoly(t, Gx->coeffs, Gx->length, ctx); if (!success) goto cleanup; _fmpz_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); _fmpz_mpoly_vec_mul_mpoly(Gx->coeffs, Gx->length, Gc, ctx); _fmpz_mpoly_from_univar(Gc, I->Gbits, Gx, var, ctx); if (Abar != NULL) fmpz_mpoly_divexact(s, A, Gc, ctx); if (Bbar != NULL) fmpz_mpoly_divexact(t, B, Gc, ctx); fmpz_mpoly_swap(G, Gc, ctx); if (Abar != NULL) fmpz_mpoly_swap(Abar, s, ctx); if (Bbar != NULL) fmpz_mpoly_swap(Bbar, t, ctx); success = 1; cleanup: fmpz_mpoly_clear(Ac, ctx); fmpz_mpoly_clear(Bc, ctx); fmpz_mpoly_clear(Gc, ctx); fmpz_mpoly_clear(s, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_univar_clear(Ax, ctx); fmpz_mpoly_univar_clear(Bx, ctx); fmpz_mpoly_univar_clear(Gx, ctx); return success; } /********************** Hit A and B with zippel ******************************/ static int _try_zippel( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mpoly_ctx_t ctx) { slong m = I->mvars; int success; flint_bitcnt_t wbits; flint_rand_t state; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL)) return 0; FLINT_ASSERT(m > 1); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); flint_randinit(state); fmpz_mpoly_ctx_init(lctx, m, ORD_LEX); wbits = FLINT_MAX(A->bits, B->bits); fmpz_mpoly_init3(Al, 0, wbits, lctx); fmpz_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mpoly_init3(Abarc, 0, wbits, lctx); fmpz_mpoly_init3(Bbarc, 0, wbits, lctx); fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->zippel_perm, I->Amin_exp, I->Gstride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->zippel_perm, I->Bmin_exp, I->Gstride); FLINT_ASSERT(Al->bits == wbits); FLINT_ASSERT(Bl->bits == wbits); FLINT_ASSERT(Al->length > 1); FLINT_ASSERT(Bl->length > 1); success = fmpz_mpolyl_content(Ac, Al, 1, lctx) && fmpz_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; fmpz_mpoly_repack_bits_inplace(Ac, wbits, lctx); fmpz_mpoly_repack_bits_inplace(Bc, wbits, lctx); success = _fmpz_mpoly_gcd_algo(Gc, Abar == NULL ? NULL : Abarc, Bbar == NULL ? NULL : Bbarc, Ac, Bc, lctx, MPOLY_GCD_USE_ALL); if (!success) goto cleanup; success = fmpz_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = fmpz_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fmpz_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mpoly_repack_bits_inplace(Bl, wbits, lctx); success = fmpz_mpolyl_gcd_zippel(Gl, Abarl, Bbarl, Al, Bl, lctx, state); if (!success) goto cleanup; fmpz_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mpoly_repack_bits_inplace(Gl, wbits, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->zippel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fmpz_mpoly_mul(Abarl, Abarl, Abarc, lctx); fmpz_mpoly_repack_bits_inplace(Abarl, wbits, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->zippel_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fmpz_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fmpz_mpoly_repack_bits_inplace(Bbarl, wbits, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->zippel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_clear(Ac, lctx); fmpz_mpoly_clear(Bc, lctx); fmpz_mpoly_clear(Gc, lctx); fmpz_mpoly_clear(Abarc, lctx); fmpz_mpoly_clear(Bbarc, lctx); fmpz_mpoly_ctx_clear(lctx); flint_randclear(state); return success; } /************************ Hit A and B with bma *******************************/ static int _try_bma( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mpoly_t Ac, Bc, Gc, Abarc, Bbarc, Gamma, lcAl, lcBl; slong max_deg; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL2)) return 0; FLINT_ASSERT(m >= 3); fmpz_mpoly_ctx_init(lctx, m, ORD_LEX); max_deg = 0; for (i = 0; i < m; i++) { k = I->zippel2_perm[i]; max_deg = FLINT_MAX(max_deg, I->Adeflate_deg[k]); max_deg = FLINT_MAX(max_deg, I->Bdeflate_deg[k]); } wbits = 1 + FLINT_BIT_COUNT(max_deg); wbits = FLINT_MAX(MPOLY_MIN_BITS, wbits); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fmpz_mpoly_init3(Al, A->length, wbits, lctx); fmpz_mpoly_init3(Bl, B->length, wbits, lctx); fmpz_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mpoly_init3(Abarc, 0, wbits, lctx); fmpz_mpoly_init3(Bbarc, 0, wbits, lctx); fmpz_mpoly_init3(Gamma, 0, wbits, lctx); fmpz_mpoly_init3(lcAl, 0, wbits, lctx); fmpz_mpoly_init3(lcBl, 0, wbits, lctx); fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->zippel2_perm, I->Amin_exp, I->Gstride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->zippel2_perm, I->Bmin_exp, I->Gstride); success = fmpz_mpolyl_content(Ac, Al, 2, lctx) && fmpz_mpolyl_content(Bc, Bl, 2, lctx); if (!success) goto cleanup; success = _fmpz_mpoly_gcd_algo(Gc, Abar == NULL ? NULL : Abarc, Bbar == NULL ? NULL : Bbarc, Ac, Bc, lctx, MPOLY_GCD_USE_ALL); if (!success) goto cleanup; success = fmpz_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = fmpz_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fmpz_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mpoly_repack_bits_inplace(Bl, wbits, lctx); fmpz_mpolyl_lead_coeff(lcAl, Al, 2, lctx); fmpz_mpolyl_lead_coeff(lcBl, Bl, 2, lctx); success = fmpz_mpoly_gcd(Gamma, lcAl, lcBl, lctx); if (!success) goto cleanup; fmpz_mpoly_repack_bits_inplace(Gamma, wbits, lctx); success = fmpz_mpolyl_gcd_zippel2(Gl, Abarl, Bbarl, Al, Bl, Gamma, lctx); if (!success) goto cleanup; fmpz_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mpoly_repack_bits_inplace(Gl, wbits, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->zippel2_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fmpz_mpoly_mul(Abarl, Abarl, Abarc, lctx); fmpz_mpoly_repack_bits_inplace(Abarl, wbits, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->zippel2_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fmpz_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fmpz_mpoly_repack_bits_inplace(Bbarl, wbits, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->zippel2_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_clear(Ac, lctx); fmpz_mpoly_clear(Bc, lctx); fmpz_mpoly_clear(Gc, lctx); fmpz_mpoly_clear(Abarc, lctx); fmpz_mpoly_clear(Bbarc, lctx); fmpz_mpoly_clear(Gamma, lctx); fmpz_mpoly_clear(lcAl, lctx); fmpz_mpoly_clear(lcBl, lctx); fmpz_mpoly_ctx_clear(lctx); return success; } /******************** Hit A and B with hensel lifting ************************/ static int _try_hensel( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const mpoly_gcd_info_t I, const fmpz_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; slong max_deg; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_HENSEL)) return 0; FLINT_ASSERT(m >= 2); fmpz_mpoly_ctx_init(lctx, m, ORD_LEX); max_deg = 0; for (i = 0; i < m; i++) { k = I->hensel_perm[i]; max_deg = FLINT_MAX(max_deg, I->Adeflate_deg[k]); max_deg = FLINT_MAX(max_deg, I->Bdeflate_deg[k]); } wbits = 1 + FLINT_BIT_COUNT(max_deg); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fmpz_mpoly_init3(Al, 0, wbits, lctx); fmpz_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mpoly_init3(Abarc, 0, wbits, lctx); fmpz_mpoly_init3(Bbarc, 0, wbits, lctx); fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->hensel_perm, I->Amin_exp, I->Gstride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->hensel_perm, I->Bmin_exp, I->Gstride); success = fmpz_mpolyl_content(Ac, Al, 1, lctx) && fmpz_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; success = _fmpz_mpoly_gcd_algo(Gc, Abar == NULL ? NULL : Abarc, Bbar == NULL ? NULL : Bbarc, Ac, Bc, lctx, MPOLY_GCD_USE_ALL); if (!success) goto cleanup; success = fmpz_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = fmpz_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fmpz_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mpoly_repack_bits_inplace(Bl, wbits, lctx); max_deg = I->Gdeflate_deg_bound[I->hensel_perm[0]]; success = fmpz_mpolyl_gcd_hensel(Gl, max_deg, Abarl, Bbarl, Al, Bl, lctx); if (!success) goto cleanup; fmpz_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->hensel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fmpz_mpoly_mul(Abarl, Abarl, Abarc, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->hensel_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fmpz_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->hensel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_clear(Ac, lctx); fmpz_mpoly_clear(Bc, lctx); fmpz_mpoly_clear(Gc, lctx); fmpz_mpoly_clear(Abarc, lctx); fmpz_mpoly_clear(Bbarc, lctx); fmpz_mpoly_ctx_clear(lctx); return success; } /*********************** Hit A and B with brown ******************************/ static int _try_brown( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, mpoly_gcd_info_t I, const fmpz_mpoly_ctx_t ctx) { int success; slong m = I->mvars; flint_bitcnt_t wbits; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; if (!(I->can_use & MPOLY_GCD_USE_BROWN)) return 0; FLINT_ASSERT(m >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); wbits = FLINT_MAX(A->bits, B->bits); fmpz_mpoly_ctx_init(lctx, m, ORD_LEX); fmpz_mpoly_init3(Al, 0, wbits, lctx); fmpz_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->brown_perm, I->Amin_exp, I->Gstride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->brown_perm, I->Bmin_exp, I->Gstride); FLINT_ASSERT(Al->bits == wbits); FLINT_ASSERT(Bl->bits == wbits); FLINT_ASSERT(Al->length > 1); FLINT_ASSERT(Bl->length > 1); success = fmpz_mpolyl_gcd_brown(Gl, Abarl, Bbarl, Al, Bl, lctx, I); if (!success) goto cleanup; fmpz_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->brown_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) fmpz_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->brown_perm, I->Abarmin_exp, I->Gstride); if (Bbar != NULL) fmpz_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->brown_perm, I->Bbarmin_exp, I->Gstride); success = 1; cleanup: fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_ctx_clear(lctx); return success; } /* Both A and B have to be packed into bits <= FLINT_BITS. return is 1 for success, 0 for failure. */ static int _fmpz_mpoly_gcd_algo_small( fmpz_mpoly_t G, fmpz_mpoly_t Abar, /* could be NULL */ fmpz_mpoly_t Bbar, /* could be NULL */ const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, unsigned int algo) { int success; slong v_in_both; slong v_in_either; slong v_in_A_only; slong v_in_B_only; slong j; slong nvars = ctx->minfo->nvars; mpoly_gcd_info_t I; #if FLINT_WANT_ASSERT fmpz_mpoly_t T, Asave, Bsave; #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); #if FLINT_WANT_ASSERT fmpz_mpoly_init(T, ctx); fmpz_mpoly_init(Asave, ctx); fmpz_mpoly_init(Bsave, ctx); fmpz_mpoly_set(Asave, A, ctx); fmpz_mpoly_set(Bsave, B, ctx); #endif mpoly_gcd_info_init(I, nvars); /* entries of I are all now invalid */ I->Gbits = FLINT_MIN(A->bits, B->bits); I->Abarbits = A->bits; I->Bbarbits = B->bits; mpoly_gcd_info_limits(I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, A->exps, A->bits, A->length, ctx->minfo); mpoly_gcd_info_limits(I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, B->exps, B->bits, B->length, ctx->minfo); /* set ess(p) := p/term_content(p) */ /* check if the cofactors could be monomials, i.e. ess(A) == ess(B) */ for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] - I->Amin_exp[j] != I->Bmax_exp[j] - I->Bmin_exp[j]) goto skip_monomial_cofactors; } if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) goto successful; skip_monomial_cofactors: mpoly_gcd_info_stride(I->Gstride, A->exps, A->bits, A->length, I->Amax_exp, I->Amin_exp, B->exps, B->bits, B->length, I->Bmax_exp, I->Bmin_exp, ctx->minfo); for (j = 0; j < nvars; j++) { ulong t = I->Gstride[j]; if (t == 0) { FLINT_ASSERT( I->Amax_exp[j] == I->Amin_exp[j] || I->Bmax_exp[j] == I->Bmin_exp[j]); } else { FLINT_ASSERT((I->Amax_exp[j] - I->Amin_exp[j]) % t == 0); FLINT_ASSERT((I->Bmax_exp[j] - I->Bmin_exp[j]) % t == 0); } I->Adeflate_deg[j] = t == 0 ? 0 : (I->Amax_exp[j] - I->Amin_exp[j])/t; I->Bdeflate_deg[j] = t == 0 ? 0 : (I->Bmax_exp[j] - I->Bmin_exp[j])/t; I->Gmin_exp[j] = FLINT_MIN(I->Amin_exp[j], I->Bmin_exp[j]); t = FLINT_MIN(I->Amin_exp[j], I->Bmin_exp[j]); I->Gmin_exp[j] = t; I->Abarmin_exp[j] = I->Amin_exp[j] - t; I->Bbarmin_exp[j] = I->Bmin_exp[j] - t; } /* The following are now valid: I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, I->Gstride I->Adeflate_deg I->Bdeflate_deg I->Gmin_exp */ /* check if ess(A) and ess(B) have a variable v_in_both in common */ v_in_both = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_both = j; break; } } if (v_in_both == -WORD(1)) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } /* check if ess(A) and ess(B) depend on another variable v_in_either */ FLINT_ASSERT(0 <= v_in_both && v_in_both < nvars); v_in_either = -WORD(1); for (j = 0; j < nvars; j++) { if (j == v_in_both) continue; if (I->Amax_exp[j] > I->Amin_exp[j] || I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_either = j; break; } } if (v_in_either == -WORD(1)) { _do_univar(G, Abar, Bbar, A, B, v_in_both, I, ctx); goto successful; } /* check if there is a variable in ess(A) that is not in ess(B) */ v_in_A_only = -WORD(1); v_in_B_only = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] == I->Bmin_exp[j]) { v_in_A_only = j; break; } if (I->Bmax_exp[j] > I->Bmin_exp[j] && I->Amax_exp[j] == I->Amin_exp[j]) { v_in_B_only = j; break; } } if (v_in_A_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Abar, Bbar, v_in_A_only, A, I->Amin_exp[v_in_A_only], B, I->Bmin_exp[v_in_A_only], ctx); goto cleanup; } if (v_in_B_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Bbar, Abar, v_in_B_only, B, I->Bmin_exp[v_in_B_only], A, I->Amin_exp[v_in_B_only], ctx); goto cleanup; } /* all variable are now either missing from both ess(A) and ess(B), or present in both ess(A) and ess(B) and there are at least two in the latter case */ mpoly_gcd_info_set_perm(I, A->length, B->length, ctx->minfo); /* _set_estimates will probably calculate the correct total degrees */ I->Adeflate_tdeg = I->Bdeflate_tdeg = -1; _set_estimates(I, A, B, ctx); /* everything in I is valid now */ /* check divisibility A/B and B/A */ { int gcd_is_trivial = 1; int try_a = I->Gdeflate_deg_bounds_are_nice; int try_b = I->Gdeflate_deg_bounds_are_nice; for (j = 0; j < nvars; j++) { if (I->Gdeflate_deg_bound[j] != 0) gcd_is_trivial = 0; if (I->Adeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_a = 0; if (I->Bdeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_b = 0; } if (gcd_is_trivial) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } if (try_a && _try_divides(G, Bbar, Abar, B, A, ctx)) goto successful; if (try_b && _try_divides(G, Abar, Bbar, A, B, ctx)) goto successful; } /* TODO: (1) the single-bit algo == MPOLY_GCD_USE_xxx is supposed to only use that one algorithm xxx, and (2) multi-bit algo is supposed to choose among the present bits. (2) is not implemented completely. */ if (algo == MPOLY_GCD_USE_HENSEL) { mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); success = _try_hensel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_PRS) { success = _try_prs(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL) { mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); success = _try_zippel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_bma(I, A->length, B->length, ctx->minfo); if (I->mvars < 3) { /* TODO: bivariate heuristic here */ if (_try_brown(G, Abar, Bbar, A, B, I, ctx)) goto successful; } else if (algo == MPOLY_GCD_USE_BROWN) { success = _try_brown(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL2) { success = _try_bma(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if ((I->can_use & MPOLY_GCD_USE_BROWN) && (I->can_use & MPOLY_GCD_USE_ZIPPEL2) && I->zippel2_time < I->brown_time && (I->mvars*(I->Adensity + I->Bdensity) < 1 || I->zippel2_time < 0.01*I->brown_time)) { if (_try_bma(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_brown(G, Abar, Bbar, A, B, I, ctx)) goto successful; } else { if (_try_brown(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_bma(G, Abar, Bbar, A, B, I, ctx)) goto successful; } mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); if (_try_zippel(G, Abar, Bbar, A, B, I, ctx)) goto successful; success = 0; goto cleanup; successful: success = 1; cleanup: mpoly_gcd_info_clear(I); if (success) { FLINT_ASSERT(G->length > 0); if (fmpz_sgn(G->coeffs + 0) < 0) { _fmpz_vec_neg(G->coeffs, G->coeffs, G->length); if (Abar != NULL) _fmpz_vec_neg(Abar->coeffs, Abar->coeffs, Abar->length); if (Bbar != NULL) _fmpz_vec_neg(Bbar->coeffs, Bbar->coeffs, Bbar->length); } FLINT_ASSERT(fmpz_mpoly_divides(T, Asave, G, ctx)); FLINT_ASSERT(Abar == NULL || fmpz_mpoly_equal(T, Abar, ctx)); FLINT_ASSERT(fmpz_mpoly_divides(T, Bsave, G, ctx)); FLINT_ASSERT(Bbar == NULL || fmpz_mpoly_equal(T, Bbar, ctx)); } #if FLINT_WANT_ASSERT fmpz_mpoly_clear(T, ctx); fmpz_mpoly_clear(Asave, ctx); fmpz_mpoly_clear(Bsave, ctx); #endif return success; } static int _fmpz_mpoly_gcd_algo_large( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, unsigned int algo) { int success; slong k; fmpz * Ashift, * Astride; fmpz * Bshift, * Bstride; fmpz * Gshift, * Gstride; fmpz_mpoly_t Anew, Bnew; const fmpz_mpoly_struct * Ause, * Buse; if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) return 1; fmpz_mpoly_init(Anew, ctx); fmpz_mpoly_init(Bnew, ctx); Ause = A; if (A->bits > FLINT_BITS) { if (!fmpz_mpoly_repack_bits(Anew, A, FLINT_BITS, ctx)) goto could_not_repack; Ause = Anew; } Buse = B; if (B->bits > FLINT_BITS) { if (!fmpz_mpoly_repack_bits(Bnew, B, FLINT_BITS, ctx)) goto could_not_repack; Buse = Bnew; } success = _fmpz_mpoly_gcd_algo_small(G, Abar, Bbar, Ause, Buse, ctx, algo); goto cleanup; could_not_repack: /* One of A or B could not be repacked into FLINT_BITS. See if they both fit into FLINT_BITS after deflation. */ Ashift = _fmpz_vec_init(ctx->minfo->nvars); Astride = _fmpz_vec_init(ctx->minfo->nvars); Bshift = _fmpz_vec_init(ctx->minfo->nvars); Bstride = _fmpz_vec_init(ctx->minfo->nvars); Gshift = _fmpz_vec_init(ctx->minfo->nvars); Gstride = _fmpz_vec_init(ctx->minfo->nvars); fmpz_mpoly_deflation(Ashift, Astride, A, ctx); fmpz_mpoly_deflation(Bshift, Bstride, B, ctx); _fmpz_vec_min(Gshift, Ashift, Bshift, ctx->minfo->nvars); for (k = 0; k < ctx->minfo->nvars; k++) fmpz_gcd(Gstride + k, Astride + k, Bstride + k); fmpz_mpoly_deflate(Anew, A, Ashift, Gstride, ctx); if (Anew->bits > FLINT_BITS) { success = fmpz_mpoly_repack_bits(Anew, Anew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } fmpz_mpoly_deflate(Bnew, B, Bshift, Gstride, ctx); if (Bnew->bits > FLINT_BITS) { success = fmpz_mpoly_repack_bits(Bnew, Bnew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } success = _fmpz_mpoly_gcd_algo_small(G, Abar, Bbar, Anew, Bnew, ctx, algo); if (!success) goto deflate_cleanup; for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_sub(Ashift + k, Ashift + k, Gshift + k); fmpz_sub(Bshift + k, Bshift + k, Gshift + k); FLINT_ASSERT(fmpz_sgn(Ashift + k) >= 0); FLINT_ASSERT(fmpz_sgn(Bshift + k) >= 0); } fmpz_mpoly_inflate(G, G, Gshift, Gstride, ctx); if (Abar != NULL) fmpz_mpoly_inflate(Abar, Abar, Ashift, Gstride, ctx); if (Bbar != NULL) fmpz_mpoly_inflate(Bbar, Bbar, Bshift, Gstride, ctx); FLINT_ASSERT(G->length > 0); if (fmpz_sgn(G->coeffs + 0) < 0) { _fmpz_vec_neg(G->coeffs, G->coeffs, G->length); if (Abar != NULL) _fmpz_vec_neg(Abar->coeffs, Abar->coeffs, Abar->length); if (Bbar != NULL) _fmpz_vec_neg(Bbar->coeffs, Bbar->coeffs, Bbar->length); } deflate_cleanup: _fmpz_vec_clear(Ashift, ctx->minfo->nvars); _fmpz_vec_clear(Astride, ctx->minfo->nvars); _fmpz_vec_clear(Bshift, ctx->minfo->nvars); _fmpz_vec_clear(Bstride, ctx->minfo->nvars); _fmpz_vec_clear(Gshift, ctx->minfo->nvars); _fmpz_vec_clear(Gstride, ctx->minfo->nvars); cleanup: fmpz_mpoly_clear(Anew, ctx); fmpz_mpoly_clear(Bnew, ctx); return success; } int _fmpz_mpoly_gcd_algo( fmpz_mpoly_t G, fmpz_mpoly_t Abar, /* could be NULL */ fmpz_mpoly_t Bbar, /* could be NULL */ const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, unsigned int algo) { FLINT_ASSERT(!fmpz_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!fmpz_mpoly_is_zero(B, ctx)); if (A->bits <= FLINT_BITS && B->bits <= FLINT_BITS) return _fmpz_mpoly_gcd_algo_small(G, Abar, Bbar, A, B, ctx, algo); else return _fmpz_mpoly_gcd_algo_large(G, Abar, Bbar, A, B, ctx, algo); } flint-3.1.3/src/fmpz_mpoly_factor/gcd_brown.c000066400000000000000000000174261461254215100212760ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #include "fmpz_mpoly_factor.h" /* max = max abs coeffs(A) */ void fmpz_mpoly_height( fmpz_t max, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz_t t; fmpz_init(t); fmpz_zero(max); for (i = 0; i < A->length; i++) { fmpz_abs(t, A->coeffs + i); if (fmpz_cmp(max, t) < 0) fmpz_set(max, t); } fmpz_clear(t); } /* max = max abs coeffs(A), sum = sum abs coeffs(A) */ void fmpz_mpoly_heights( fmpz_t max, fmpz_t sum, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz_t t; fmpz_init(t); fmpz_zero(max); fmpz_zero(sum); for (i = 0; i < A->length; i++) { fmpz_abs(t, A->coeffs + i); fmpz_add(sum, sum, t); if (fmpz_cmp(max, t) < 0) fmpz_set(max, t); } fmpz_clear(t); } /* The inputs A and B are modified */ int fmpz_mpolyl_gcd_brown( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, fmpz_mpoly_t A, fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const mpoly_gcd_info_t I) { int success; fmpz_t bound; slong offset, shift; mp_limb_t p, gammared; fmpz_t gamma, modulus; fmpz_t gnm, gns, anm, ans, bnm, bns; fmpz_t cA, cB, cG, cAbar, cBbar; fmpz_t temp; fmpz_mpoly_t T; nmod_mpolyn_t Gp, Abarp, Bbarp, Ap, Bp; nmod_mpoly_ctx_t pctx; flint_bitcnt_t bits = G->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); nmod_poly_stack_t Sp; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == G->bits); FLINT_ASSERT(bits == Abar->bits); FLINT_ASSERT(bits == Bbar->bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); mpoly_gen_offset_shift_sp(&offset, &shift, ctx->minfo->nvars - 1, bits, ctx->minfo); fmpz_init(gamma); fmpz_init(gnm); fmpz_init(gns); fmpz_init(anm); fmpz_init(ans); fmpz_init(bnm); fmpz_init(bns); fmpz_init(bound); fmpz_init(temp); fmpz_init_set_si(modulus, 1); /* compute contents of G, Abar, Bbar, A, B */ fmpz_init(cA); fmpz_init(cB); fmpz_init(cG); fmpz_init(cAbar); fmpz_init(cBbar); _fmpz_vec_content(cA, A->coeffs, A->length); _fmpz_vec_content(cB, B->coeffs, B->length); fmpz_gcd(cG, cA, cB); fmpz_divexact(cAbar, cA, cG); fmpz_divexact(cBbar, cB, cG); /* remove content from inputs */ fmpz_mpoly_scalar_divexact_fmpz(A, A, cA, ctx); fmpz_mpoly_scalar_divexact_fmpz(B, B, cB, ctx); fmpz_gcd(gamma, A->coeffs + 0, B->coeffs + 0); fmpz_mpoly_height(bound, A, ctx); fmpz_mpoly_height(temp, B, ctx); if (fmpz_cmp(bound, temp) < 0) fmpz_swap(bound, temp); fmpz_mul(bound, bound, gamma); fmpz_add(bound, bound, bound); fmpz_mpoly_init3(T, 0, bits, ctx); nmod_mpoly_ctx_init(pctx, ctx->minfo->nvars, ORD_LEX, 2); nmod_poly_stack_init(Sp, bits, pctx); nmod_mpolyn_init(Ap, bits, pctx); nmod_mpolyn_init(Bp, bits, pctx); nmod_mpolyn_init(Gp, bits, pctx); nmod_mpolyn_init(Abarp, bits, pctx); nmod_mpolyn_init(Bbarp, bits, pctx); p = UWORD(1) << (FLINT_BITS - 1); choose_prime: if (p >= UWORD_MAX_PRIME) { /* ran out of primes - absolute failure */ success = 0; goto cleanup; } p = n_nextprime(p, 1); /* make sure reduction does not kill both lc(A) and lc(B) */ gammared = fmpz_fdiv_ui(gamma, p); if (gammared == 0) { goto choose_prime; } nmod_mpoly_ctx_set_modulus(pctx, p); /* the unfortunate nmod poly's store their own context :( */ nmod_poly_stack_set_ctx(Sp, pctx); nmod_mpolyn_set_mod(Ap, pctx->mod); nmod_mpolyn_set_mod(Bp, pctx->mod); nmod_mpolyn_set_mod(Gp, pctx->mod); nmod_mpolyn_set_mod(Abarp, pctx->mod); nmod_mpolyn_set_mod(Bbarp, pctx->mod); /* reduction should kill neither A nor B */ fmpz_mpoly_interp_reduce_p_mpolyn(Ap, pctx, A, ctx); fmpz_mpoly_interp_reduce_p_mpolyn(Bp, pctx, B, ctx); FLINT_ASSERT(Ap->length > 0); FLINT_ASSERT(Bp->length > 0); success = nmod_mpolyn_gcd_brown_smprime(Gp, Abarp, Bbarp, Ap, Bp, ctx->minfo->nvars - 1, pctx, I, Sp); if (!success) { goto choose_prime; } if (nmod_mpolyn_is_nonzero_nmod(Gp, pctx)) { fmpz_mpoly_one(G, ctx); fmpz_mpoly_swap(Abar, A, ctx); fmpz_mpoly_swap(Bbar, B, ctx); goto successful_put_content; } if (!fmpz_is_one(modulus)) { int cmp; slong k; FLINT_ASSERT(G->length > 0); k = n_poly_degree(Gp->coeffs + 0); cmp = mpoly_monomial_cmp_nomask_extra(G->exps + N*0, Gp->exps + N*0, N, offset, k << shift); if (cmp < 0) { goto choose_prime; } else if (cmp > 0) { fmpz_one(modulus); } } FLINT_ASSERT(1 == nmod_mpolyn_leadcoeff(Gp, pctx)); nmod_mpolyn_scalar_mul_nmod(Gp, gammared, pctx); if (!fmpz_is_one(modulus)) { fmpz_mpoly_interp_crt_p_mpolyn(G, T, ctx, modulus, Gp, pctx); fmpz_mpoly_interp_crt_p_mpolyn(Abar, T, ctx, modulus, Abarp, pctx); fmpz_mpoly_interp_crt_p_mpolyn(Bbar, T, ctx, modulus, Bbarp, pctx); } else { fmpz_mpoly_interp_lift_p_mpolyn(G, ctx, Gp, pctx); fmpz_mpoly_interp_lift_p_mpolyn(Abar, ctx, Abarp, pctx); fmpz_mpoly_interp_lift_p_mpolyn(Bbar, ctx, Bbarp, pctx); } fmpz_mul_ui(modulus, modulus, p); if (fmpz_cmp(modulus, bound) <= 0) { goto choose_prime; } fmpz_mpoly_heights(gnm, gns, G, ctx); fmpz_mpoly_heights(anm, ans, Abar, ctx); fmpz_mpoly_heights(bnm, bns, Bbar, ctx); fmpz_mul(ans, ans, gnm); fmpz_mul(anm, anm, gns); fmpz_mul(bns, bns, gnm); fmpz_mul(bnm, bnm, gns); if (fmpz_cmp(ans, anm) > 0) fmpz_swap(ans, anm); if (fmpz_cmp(bns, bnm) > 0) fmpz_swap(bns, bnm); fmpz_add(ans, ans, ans); fmpz_add(bns, bns, bns); if (fmpz_cmp(ans, modulus) < 0 && fmpz_cmp(bns, modulus) < 0) { goto successful; } /* do not reset modulus to 1 */ goto choose_prime; successful: FLINT_ASSERT(fmpz_equal(gamma, G->coeffs + 0)); _fmpz_vec_content(temp, G->coeffs, G->length); fmpz_mpoly_scalar_divexact_fmpz(G, G, temp, ctx); fmpz_mpoly_scalar_divexact_fmpz(Abar, Abar, G->coeffs + 0, ctx); fmpz_mpoly_scalar_divexact_fmpz(Bbar, Bbar, G->coeffs + 0, ctx); successful_put_content: fmpz_mpoly_scalar_mul_fmpz(G, G, cG, ctx); fmpz_mpoly_scalar_mul_fmpz(Abar, Abar, cAbar, ctx); fmpz_mpoly_scalar_mul_fmpz(Bbar, Bbar, cBbar, ctx); success = 1; cleanup: fmpz_clear(cA); fmpz_clear(cB); fmpz_clear(cG); fmpz_clear(cAbar); fmpz_clear(cBbar); fmpz_clear(gamma); fmpz_clear(gnm); fmpz_clear(gns); fmpz_clear(anm); fmpz_clear(ans); fmpz_clear(bnm); fmpz_clear(bns); fmpz_clear(bound); fmpz_clear(temp); fmpz_clear(modulus); nmod_mpolyn_clear(Gp, pctx); nmod_mpolyn_clear(Abarp, pctx); nmod_mpolyn_clear(Bbarp, pctx); nmod_mpolyn_clear(Ap, pctx); nmod_mpolyn_clear(Bp, pctx); nmod_poly_stack_clear(Sp); nmod_mpoly_ctx_clear(pctx); fmpz_mpoly_clear(T, ctx); return success; } flint-3.1.3/src/fmpz_mpoly_factor/gcd_brown_threaded.c000066400000000000000000001053121461254215100231260ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_vec.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #include "fmpz_mpoly_factor.h" typedef struct { volatile int gcd_is_one; volatile mp_limb_t p; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif fmpz_t gamma; const fmpz_mpoly_ctx_struct * ctx; fmpz_mpoly_struct * A, * B; ulong num_threads; slong var; const mpoly_gcd_info_struct * I; } _splitbase_struct; typedef _splitbase_struct _splitbase_t[1]; typedef struct { slong idx; _splitbase_struct * base; fmpz_mpoly_t G, Abar, Bbar; fmpz_t modulus; slong image_count; slong required_images; thread_pool_handle master_handle; slong num_handles; thread_pool_handle * worker_handles; nmod_mpoly_ctx_t pctx; nmod_mpolyn_t Ap, Bp, Gp, Abarp, Bbarp; fmpz_mpoly_t T, T1, T2; } _splitworker_arg_struct; /* worker for reducing polynomial over ZZ to polynomial over Fp */ static void _reduce_Bp_worker(void * varg) { _splitworker_arg_struct * arg = (_splitworker_arg_struct *) varg; fmpz_mpoly_interp_reduce_p_mpolyn(arg->Bp, arg->pctx, arg->base->B, arg->base->ctx); } /* workers for crt'ing polynomials */ static void _join_Abar_worker(void * varg) { _splitworker_arg_struct * arg = (_splitworker_arg_struct *) varg; if (!fmpz_is_one(arg->modulus)) fmpz_mpoly_interp_crt_p_mpolyn(arg->Abar, arg->T1, arg->base->ctx, arg->modulus, arg->Abarp, arg->pctx); else fmpz_mpoly_interp_lift_p_mpolyn(arg->Abar, arg->base->ctx, arg->Abarp, arg->pctx); } static void _join_Bbar_worker(void * varg) { _splitworker_arg_struct * arg = (_splitworker_arg_struct *) varg; if (!fmpz_is_one(arg->modulus)) fmpz_mpoly_interp_crt_p_mpolyn(arg->Bbar, arg->T2, arg->base->ctx, arg->modulus, arg->Bbarp, arg->pctx); else fmpz_mpoly_interp_lift_p_mpolyn(arg->Bbar, arg->base->ctx, arg->Bbarp, arg->pctx); } static void _splitworker(void * varg) { _splitworker_arg_struct * arg = (_splitworker_arg_struct *) varg; _splitbase_struct * base = arg->base; const fmpz_mpoly_ctx_struct * ctx = base->ctx; flint_bitcnt_t bits = base->A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong offset, shift; int success; mp_limb_t p, gammared; nmod_poly_stack_t Sp; mpoly_gen_offset_shift_sp(&offset, &shift, ctx->minfo->nvars - 1, bits, ctx->minfo); fmpz_one(arg->modulus); arg->image_count = 0; nmod_mpoly_ctx_init(arg->pctx, ctx->minfo->nvars, ORD_LEX, 2); nmod_poly_stack_init(Sp, bits, arg->pctx); nmod_mpolyn_init(arg->Ap, bits, arg->pctx); nmod_mpolyn_init(arg->Bp, bits, arg->pctx); nmod_mpolyn_init(arg->Gp, bits, arg->pctx); nmod_mpolyn_init(arg->Abarp, bits, arg->pctx); nmod_mpolyn_init(arg->Bbarp, bits, arg->pctx); fmpz_mpoly_init3(arg->T, 0, bits, ctx); fmpz_mpoly_init3(arg->T1, 0, bits, ctx); fmpz_mpoly_init3(arg->T2, 0, bits, ctx); while (arg->image_count < arg->required_images) { /* get prime */ #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif p = base->p; if (p >= UWORD_MAX_PRIME) { #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif break; } p = n_nextprime(base->p, 1); base->p = p; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif /* make sure reduction does not kill both lc(A) and lc(B) */ gammared = fmpz_fdiv_ui(base->gamma, p); if (gammared == 0) { continue; } nmod_mpoly_ctx_set_modulus(arg->pctx, p); /* the unfortunate nmod poly's store their own context :( */ nmod_poly_stack_set_ctx(Sp, arg->pctx); nmod_mpolyn_set_mod(arg->Ap, arg->pctx->mod); nmod_mpolyn_set_mod(arg->Bp, arg->pctx->mod); nmod_mpolyn_set_mod(arg->Gp, arg->pctx->mod); nmod_mpolyn_set_mod(arg->Abarp, arg->pctx->mod); nmod_mpolyn_set_mod(arg->Bbarp, arg->pctx->mod); /* reduce to Fp and calculate an image gcd */ if (arg->num_handles > 0) { thread_pool_wake(global_thread_pool, arg->worker_handles[0], 0, _reduce_Bp_worker, arg); fmpz_mpoly_interp_reduce_p_mpolyn(arg->Ap, arg->pctx, base->A, ctx); thread_pool_wait(global_thread_pool, arg->worker_handles[0]); success = nmod_mpolyn_gcd_brown_smprime_threaded_pool( arg->Gp, arg->Abarp, arg->Bbarp, arg->Ap, arg->Bp, ctx->minfo->nvars - 1, arg->pctx, base->I, arg->worker_handles, arg->num_handles); } else { /* reduction should kill neither A nor B */ fmpz_mpoly_interp_reduce_p_mpolyn(arg->Ap, arg->pctx, base->A, ctx); fmpz_mpoly_interp_reduce_p_mpolyn(arg->Bp, arg->pctx, base->B, ctx); FLINT_ASSERT(arg->Ap->length > 0); FLINT_ASSERT(arg->Bp->length > 0); success = nmod_mpolyn_gcd_brown_smprime( arg->Gp, arg->Abarp, arg->Bbarp, arg->Ap, arg->Bp, ctx->minfo->nvars - 1, arg->pctx, base->I, Sp); } if (!success) { continue; } FLINT_ASSERT(arg->Gp->length > 0); FLINT_ASSERT(arg->Abarp->length > 0); FLINT_ASSERT(arg->Bbarp->length > 0); /* check up */ if (base->gcd_is_one) { break; } if (nmod_mpolyn_is_nonzero_nmod(arg->Gp, arg->pctx)) { base->gcd_is_one = 1; break; } if (!fmpz_is_one(arg->modulus)) { int cmp = 0; slong k; FLINT_ASSERT(arg->G->length > 0); k = n_poly_degree(arg->Gp->coeffs + 0); cmp = mpoly_monomial_cmp_nomask_extra(arg->G->exps + N*0, arg->Gp->exps + N*0, N, offset, k << shift); if (cmp < 0) { continue; } else if (cmp > 0) { fmpz_one(arg->modulus); arg->image_count = 0; } } FLINT_ASSERT(1 == nmod_mpolyn_leadcoeff(arg->Gp, arg->pctx)); nmod_mpolyn_scalar_mul_nmod(arg->Gp, gammared, arg->pctx); /* crt image gcd */ if (arg->num_handles > 0) { thread_pool_wake(global_thread_pool, arg->worker_handles[0], 0, _join_Abar_worker, arg); if (arg->num_handles > 1) { thread_pool_wake(global_thread_pool, arg->worker_handles[1], 0, _join_Bbar_worker, arg); } else { _join_Bbar_worker(arg); } if (!fmpz_is_one(arg->modulus)) fmpz_mpoly_interp_crt_p_mpolyn(arg->G, arg->T, ctx, arg->modulus, arg->Gp, arg->pctx); else fmpz_mpoly_interp_lift_p_mpolyn(arg->G, ctx, arg->Gp, arg->pctx); thread_pool_wait(global_thread_pool, arg->worker_handles[0]); if (arg->num_handles > 1) thread_pool_wait(global_thread_pool, arg->worker_handles[1]); } else { if (!fmpz_is_one(arg->modulus)) { fmpz_mpoly_interp_crt_p_mpolyn(arg->G, arg->T, ctx, arg->modulus, arg->Gp, arg->pctx); fmpz_mpoly_interp_crt_p_mpolyn(arg->Abar, arg->T, ctx, arg->modulus, arg->Abarp, arg->pctx); fmpz_mpoly_interp_crt_p_mpolyn(arg->Bbar, arg->T, ctx, arg->modulus, arg->Bbarp, arg->pctx); } else { fmpz_mpoly_interp_lift_p_mpolyn(arg->G, ctx, arg->Gp, arg->pctx); fmpz_mpoly_interp_lift_p_mpolyn(arg->Abar, ctx, arg->Abarp, arg->pctx); fmpz_mpoly_interp_lift_p_mpolyn(arg->Bbar, ctx, arg->Bbarp, arg->pctx); } } fmpz_mul_ui(arg->modulus, arg->modulus, p); arg->image_count++; } fmpz_mpoly_clear(arg->T, ctx); fmpz_mpoly_clear(arg->T1, ctx); fmpz_mpoly_clear(arg->T2, ctx); nmod_mpolyn_clear(arg->Ap, arg->pctx); nmod_mpolyn_clear(arg->Bp, arg->pctx); nmod_mpolyn_clear(arg->Gp, arg->pctx); nmod_mpolyn_clear(arg->Abarp, arg->pctx); nmod_mpolyn_clear(arg->Bbarp, arg->pctx); nmod_poly_stack_clear(Sp); nmod_mpoly_ctx_clear(arg->pctx); } typedef struct { slong hint_start, hint_stop; ulong * left_exp, * right_exp; fmpz_mpoly_t poly; fmpz_t maxcoeff, sumcoeff; slong thread_idx; slong final_idx; int GAB; /* 0 -> G, 1 -> A, 2 -> B */ } _joinworker_arg_struct; /* A = crt(B[0], ...., B[count-1]) wrt to P This function takes some preallocated temp space. */ static void _find_edge( slong * start, slong count, const ulong * exp_left, fmpz_mpoly_struct * const * B, slong N) { slong k; for (k = 0; k < count; k++) { slong Blength = B[k]->length; const ulong * Bexps = B[k]->exps; if (start[k] < Blength && mpoly_monomial_gt_nomask(Bexps + N*start[k], exp_left, N)) { /* go right */ do { start[k]++; } while (start[k] < Blength && mpoly_monomial_gt_nomask(Bexps + N*start[k], exp_left, N)); } else { /* go left */ while (start[k] > 0 && !mpoly_monomial_gt_nomask(Bexps + N*(start[k] - 1), exp_left, N)) { start[k]--; } } } } /* NOTE: Here `input' has to be an array of size `count'. It will be * overwritten, and its initial element values do not matter. It will contain * dangling pointers after returning, that is, the values `input[ix]' will be * invalid after returning. Hence, we silence warnings about dangling pointers. */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdangling-pointer" #endif static slong _fmpz_mpoly_crt( const fmpz_multi_CRT_t P, _joinworker_arg_struct * S, fmpz_mpoly_struct * const * B, slong count, fmpz * output, fmpz ** input, const fmpz_mpoly_ctx_t ctx) { int cmp; slong N = mpoly_words_per_exp_sp(S->poly->bits, ctx->minfo); slong lastdegree; slong Ai; slong j, k; slong * start, * stop; fmpz * ins; fmpz_t zero, max, sum; fmpz_mpoly_t A; const ulong * exp_left = S->left_exp; const ulong * exp_right = S->right_exp; TMP_INIT; FLINT_ASSERT(count > 0); FLINT_ASSERT(count == P->moduli_count); *A = *S->poly; TMP_START; ins = TMP_ARRAY_ALLOC(count, fmpz); start = TMP_ARRAY_ALLOC(2*count, slong); stop = start + count; for (k = 0; k < count; k++) { start[k] = exp_left ? FLINT_MIN(S->hint_start, B[k]->length) : 0; stop[k] = exp_right ? FLINT_MIN(S->hint_stop, B[k]->length) : B[k]->length; } if (exp_left) _find_edge(start, count, exp_left, B, N); if (exp_right) _find_edge(stop, count, exp_right, B, N); #if FLINT_WANT_ASSERT for (k = 0; k < count; k++) { FLINT_ASSERT(0 <= start[k]); FLINT_ASSERT(0 <= stop[k]); FLINT_ASSERT(start[k] <= B[k]->length); FLINT_ASSERT(stop[k] <= B[k]->length); FLINT_ASSERT(start[k] <= stop[k]); /* check start */ if (!exp_left) { FLINT_ASSERT(start[k] == 0); } else { FLINT_ASSERT(start[k] == B[k]->length || !mpoly_monomial_gt_nomask(B[k]->exps + N*start[k], exp_left, N)); FLINT_ASSERT(start[k] == 0 || mpoly_monomial_gt_nomask(B[k]->exps + N*(start[k] - 1), exp_left, N)); } /* check stop */ if (!exp_right) { FLINT_ASSERT(stop[k] == B[k]->length); } else { FLINT_ASSERT(stop[k] == B[k]->length || !mpoly_monomial_gt_nomask(B[k]->exps + N*stop[k], exp_right, N)); FLINT_ASSERT(stop[k] == 0 || mpoly_monomial_gt_nomask(B[k]->exps + N*(stop[k] - 1), exp_right, N)); } } #endif fmpz_init(zero); fmpz_init(max); fmpz_init(sum); Ai = 0; lastdegree = -WORD(1); while (1) { fmpz_mpoly_fit_length(A, Ai + 1, ctx); k = 0; do { input[k] = zero; if (start[k] < stop[k]) { goto found_max; } } while (++k < count); break; /* all B[k] have been scanned completely */ found_max: input[k] = B[k]->coeffs + start[k]; mpoly_monomial_set(A->exps + N*Ai, B[k]->exps + N*start[k], N); start[k]++; for (k++; k < count; k++) { input[k] = zero; if (start[k] >= stop[k]) { continue; } cmp = mpoly_monomial_cmp_nomask(B[k]->exps + N*start[k], A->exps + N*Ai, N); if (cmp == 0) { input[k] = B[k]->coeffs + start[k]; start[k]++; } else if (cmp > 0) { /* undo previous max's */ for (j = 0; j < k; j++) { start[j] -= (input[j] != zero); input[j] = zero; } goto found_max; } } k = 0; do { ins[k] = *input[k]; } while (++k < count); _fmpz_multi_CRT_precomp(output, P, ins, 1); fmpz_swap(A->coeffs + Ai, output + 0); cmp = fmpz_sgn(A->coeffs + Ai); if (cmp != 0) { if (fmpz_cmpabs(max, A->coeffs + Ai) < 0) fmpz_abs(max, A->coeffs + Ai); if (cmp > 0) fmpz_add(sum, sum, A->coeffs + Ai); else fmpz_sub(sum, sum, A->coeffs + Ai); Ai++; } } A->length = Ai; fmpz_swap(S->maxcoeff, max); fmpz_swap(S->sumcoeff, sum); fmpz_clear(zero); fmpz_clear(max); fmpz_clear(sum); TMP_END; *S->poly = *A; return lastdegree; } #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif typedef struct { volatile int idx; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif const fmpz_mpoly_ctx_struct * ctx; fmpz_multi_CRT_t CRT; fmpz_mpoly_struct ** gptrs, ** abarptrs, ** bbarptrs; fmpz_mpoly_struct * G, * Abar, * Bbar; _joinworker_arg_struct * chunks; slong chunks_length; ulong num_images; } _joinbase_struct; typedef _joinbase_struct _joinbase_t[1]; typedef struct { _joinbase_struct * base; slong thread_idx; } _njoinworker_arg_struct; static void _joinworker(void * varg) { _njoinworker_arg_struct * arg = (_njoinworker_arg_struct *) varg; _joinbase_struct * base = arg->base; fmpz ** input; fmpz * output; slong i, ls = base->CRT->localsize; TMP_INIT; TMP_START; input = (fmpz **) TMP_ALLOC(base->num_images * sizeof(fmpz *)); output = (fmpz *) TMP_ALLOC(ls*sizeof(fmpz)); for (i = 0; i < ls; i++) fmpz_init(output + i); while (1) { /* get exponent of either G, Abar, or Bbar to start working on */ #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif i = base->idx; base->idx = i + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif if (i >= base->chunks_length) { goto cleanup; } base->chunks[i].thread_idx = arg->thread_idx; if (base->chunks[i].GAB == 0) { _fmpz_mpoly_crt(base->CRT, base->chunks + i, base->gptrs, base->num_images, output, input, base->ctx); } else if (base->chunks[i].GAB == 1) { _fmpz_mpoly_crt(base->CRT, base->chunks + i, base->abarptrs, base->num_images, output, input, base->ctx); } else { FLINT_ASSERT(base->chunks[i].GAB == 2); _fmpz_mpoly_crt(base->CRT, base->chunks + i, base->bbarptrs, base->num_images, output, input, base->ctx); } } cleanup: for (i = 0; i < ls; i++) fmpz_clear(output + i); TMP_END; return; } static void _finaljoinworker(void * varg) { _njoinworker_arg_struct * arg = (_njoinworker_arg_struct *) varg; _joinbase_struct * base = arg->base; const fmpz_mpoly_ctx_struct * ctx = base->ctx; flint_bitcnt_t bits = base->G->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong i, j; slong source_len; ulong * source_exps; fmpz * source_coeffs; slong Ti; ulong * Texps; fmpz * Tcoeffs; for (i = base->chunks_length - 1; i >= 0; i--) { int type = base->chunks[i].GAB; FLINT_ASSERT(base->chunks[i].thread_idx >= 0); if (base->chunks[i].thread_idx != arg->thread_idx) continue; if (type == 0) { Texps = base->G->exps; Tcoeffs = base->G->coeffs; } else if (type == 1) { Texps = base->Abar->exps; Tcoeffs = base->Abar->coeffs; } else { FLINT_ASSERT(type == 2); Texps = base->Bbar->exps; Tcoeffs = base->Bbar->coeffs; } source_len = base->chunks[i].poly->length; source_exps = base->chunks[i].poly->exps + N*0; source_coeffs = base->chunks[i].poly->coeffs + 0; Ti = base->chunks[i].final_idx; mpoly_copy_monomials(Texps + N*Ti, source_exps, source_len, N); for (j = 0; j < source_len; j++) fmpz_swap(Tcoeffs + Ti + j, source_coeffs + j); } } /* Set 1 <= l <= min(n, m) and fractions v + 0, ..., v + l - 1 More comments in usage example operation on input n = 10, m = 16 gcd is 2: 5/8, 5/8 split first 5/8: 2/3, 5/8, 3/5, split first 5/8: 2/3, 2/3, 3/5, 3/5, split first 3/5: 2/3, 2/3, 2/3, 3/5, 1/2 split first 3/5: 2/3, 2/3, 2/3, 2/3, 1/2, 1/2 The maximum fraction is now 0.666 which is not much bigger than n/m */ static slong _divide_master_threads(fmpq * v, slong n, slong m) { slong l, i; double score_threashold; fmpq_t left, right; FLINT_ASSERT(n > 0); FLINT_ASSERT(m > 0); fmpq_init(left); fmpq_init(right); score_threashold = (double)(n)/(double)(m); score_threashold *= 1.1; /* initial choice for v */ l = n_gcd(n, m); for (i = 0; i < l; i++) { fmpq_set_si(v + i, n, m); } i = 0; while (i < l) { if (fmpz_cmp_ui(fmpq_denref(v + i), 2) >= 0) { fmpq_farey_neighbors(left, right, v + i, fmpq_denref(v + i)); FLINT_ASSERT(fmpz_get_ui(fmpq_denref(v + i)) == fmpz_get_ui(fmpq_denref(left)) + fmpz_get_ui(fmpq_denref(right))); if (fmpq_sgn(left) > 0 && fmpq_get_d(right) < score_threashold) { /* delete v + i, add left and right */ FLINT_ASSERT(l < m); fmpq_set(v + i, right); fmpq_set(v + l, left); l++; continue; } } i++; } fmpq_clear(left); fmpq_clear(right); return l; } /* inputs A and B are modified */ int fmpz_mpolyl_gcd_brown_threaded_pool( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, fmpz_mpoly_t A, fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, const thread_pool_handle * handles, slong num_handles) { slong i, j, k; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong num_threads = num_handles + 1; slong num_master_threads; slong num_images; int success; fmpz_t bound, modulus, temp, temp2; fmpz maxcoeff_Gs_Abars_Bbars[3]; fmpz sumcoeff_Gs_Abars_Bbars[3]; fmpz_t cA, cB, cG, cAbar, cBbar; fmpz * moduli; fmpz_mpoly_struct ** gptrs, ** abarptrs, ** bbarptrs; fmpq * qvec; _splitworker_arg_struct * splitargs; _splitbase_t splitbase; _njoinworker_arg_struct * joinargs; _joinbase_t joinbase; fmpz_init(bound); fmpz_init(modulus); fmpz_init(temp); fmpz_init(temp2); for (i = 0; i < 3; i++) { fmpz_init(maxcoeff_Gs_Abars_Bbars + i); fmpz_init(sumcoeff_Gs_Abars_Bbars + i); } /* compute contents of G, Abar, Bbar, A, B */ fmpz_init(cA); fmpz_init(cB); fmpz_init(cG); fmpz_init(cAbar); fmpz_init(cBbar); _fmpz_vec_content(cA, A->coeffs, A->length); _fmpz_vec_content(cB, B->coeffs, B->length); fmpz_gcd(cG, cA, cB); fmpz_divexact(cAbar, cA, cG); fmpz_divexact(cBbar, cB, cG); /* remove content from inputs */ fmpz_mpoly_scalar_divexact_fmpz(A, A, cA, ctx); fmpz_mpoly_scalar_divexact_fmpz(B, B, cB, ctx); /* init split info */ qvec = _fmpq_vec_init(num_threads); fmpz_init(splitbase->gamma); fmpz_gcd(splitbase->gamma, A->coeffs + 0, B->coeffs + 0); /* if compute_split is jumped back to, there could be as many as num_threads + 1 images that need to be joined. */ gptrs = FLINT_ARRAY_ALLOC(num_threads + 1, fmpz_mpoly_struct *); abarptrs = FLINT_ARRAY_ALLOC(num_threads + 1, fmpz_mpoly_struct *); bbarptrs =FLINT_ARRAY_ALLOC(num_threads + 1, fmpz_mpoly_struct *); moduli = FLINT_ARRAY_ALLOC(num_threads + 1, fmpz); /* shallow copies */ splitargs = FLINT_ARRAY_ALLOC(num_threads, _splitworker_arg_struct); for (i = 0; i < num_threads; i++) { fmpz_mpoly_init3(splitargs[i].G, 0, bits, ctx); fmpz_mpoly_init3(splitargs[i].Abar, 0, bits, ctx); fmpz_mpoly_init3(splitargs[i].Bbar, 0, bits, ctx); fmpz_init(splitargs[i].modulus); splitargs[i].worker_handles = (thread_pool_handle *) flint_malloc( num_threads*sizeof(thread_pool_handle)); } splitbase->num_threads = num_threads; splitbase->A = A; splitbase->B = B; splitbase->ctx = ctx; splitbase->p = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); splitbase->I = I; #if FLINT_USES_PTHREAD pthread_mutex_init(&splitbase->mutex, NULL); #endif /* initial bound on target modulus */ fmpz_mpoly_height(bound, A, ctx); fmpz_mpoly_height(temp, B, ctx); if (fmpz_cmp(bound, temp) < 0) fmpz_swap(bound, temp); fmpz_mul(bound, bound, splitbase->gamma); fmpz_add(bound, bound, bound); /* no images yet */ fmpz_one(modulus); compute_split: splitbase->gcd_is_one = 0; fmpz_cdiv_q(temp, bound, modulus); fmpz_add_ui(temp, temp, 2); /* n := fmpz_clog_ui(temp, splitbase->p) is the number of images we need. We have m := num_threads threads available for work. We can calculate images in parallel (parallel on p), but the calculation of each image can itself also be done in parallel. An integer l := num_master_threads with 1 <= l <= min(n, m) is selected and fractions a_i/b_i, 0 <= i < l are also selected with sum_i(a_i) = n and sum_i(b_i) = m. Then l jobs are spawned, each doing a_i images where each image uses b_i threads. */ num_master_threads = _divide_master_threads(qvec, fmpz_clog_ui(temp, splitbase->p), num_threads); FLINT_ASSERT(num_master_threads > 0); k = 0; for (i = 0; i < num_master_threads; i++) { splitargs[i].idx = i; splitargs[i].base = splitbase; FLINT_ASSERT(fmpz_fits_si(fmpq_numref(qvec + i))); FLINT_ASSERT(fmpz_fits_si(fmpq_denref(qvec + i))); splitargs[i].required_images = fmpz_get_si(fmpq_numref(qvec + i)); splitargs[i].num_handles = fmpz_get_si(fmpq_denref(qvec + i)) - 1; FLINT_ASSERT(splitargs[i].required_images > 0); FLINT_ASSERT(splitargs[i].num_handles >= 0); if (i == 0) { splitargs[i].master_handle = -1; } else { splitargs[i].master_handle = handles[k++]; } FLINT_ASSERT(splitargs[i].num_handles <= num_handles); for (j = 0; j < splitargs[i].num_handles; j++) { splitargs[i].worker_handles[j] = handles[k++]; } } /* all handles should have been distributed */ FLINT_ASSERT(k == num_handles); for (i = 1; i < num_master_threads; i++) { thread_pool_wake(global_thread_pool, splitargs[i].master_handle, 0, _splitworker, &splitargs[i]); } _splitworker(&splitargs[0]); for (i = 1; i < num_master_threads; i++) { thread_pool_wait(global_thread_pool, splitargs[i].master_handle); } if (splitbase->gcd_is_one) { fmpz_mpoly_one(G, ctx); fmpz_mpoly_swap(Abar, A, ctx); fmpz_mpoly_swap(Bbar, B, ctx); goto successful_put_content; } /* check each thread reached its goal */ for (i = 0; i < num_master_threads; i++) { if (splitargs[i].image_count < splitargs[i].required_images) { /* ran out of rational primes - must fail */ success = 0; goto cleanup_split; } } /* find images to join */ num_images = 0; if (!fmpz_is_one(modulus)) { gptrs[num_images] = G; abarptrs[num_images] = Abar; bbarptrs[num_images] = Bbar; moduli[num_images] = *modulus; num_images++; } i = 0; if (num_images == 0) { gptrs[num_images] = splitargs[i].G; abarptrs[num_images] = splitargs[i].Abar; bbarptrs[num_images] = splitargs[i].Bbar; moduli[num_images] = *splitargs[i].modulus; num_images++; i++; } FLINT_ASSERT(num_images <= num_master_threads + 1); for (; i < num_master_threads; i++) { int cmp = 0; cmp = mpoly_monomial_cmp_nomask(gptrs[0]->exps + N*0, splitargs[i].G->exps + N*0, N); if (cmp < 0) { /* splitarg[i] was unlucky - ignore it */ } else { if (cmp > 0) { /* splitarg[0], ..., splitarg[i - 1] were unlucky */ num_images = 0; } gptrs[num_images] = splitargs[i].G; abarptrs[num_images] = splitargs[i].Abar; bbarptrs[num_images] = splitargs[i].Bbar; moduli[num_images] = *splitargs[i].modulus; num_images++; } FLINT_ASSERT(num_images <= num_master_threads + 1); } /* now must join ptrs[0], ..., ptrs[num_images-1] where num_images > 0 */ FLINT_ASSERT(num_images > 0); fmpz_multi_CRT_init(joinbase->CRT); success = fmpz_multi_CRT_precompute(joinbase->CRT, moduli, num_images); FLINT_ASSERT(success); joinbase->num_images = num_images; joinbase->gptrs = gptrs; joinbase->abarptrs = abarptrs; joinbase->bbarptrs = bbarptrs; joinbase->G = G; joinbase->Abar = Abar; joinbase->Bbar = Bbar; joinbase->ctx = ctx; #if FLINT_USES_PTHREAD pthread_mutex_init(&joinbase->mutex, NULL); #endif joinargs = (_njoinworker_arg_struct *) flint_malloc( num_threads*sizeof(_njoinworker_arg_struct)); for (i = 0; i < num_threads; i++) { joinargs[i].base = joinbase; joinargs[i].thread_idx = i; } joinbase->chunks_length = 3*num_threads; joinbase->chunks = (_joinworker_arg_struct *) flint_malloc( joinbase->chunks_length*sizeof(_joinworker_arg_struct)); FLINT_ASSERT(joinbase->chunks_length >= 3); for (i = 0; i < 3; i++) { fmpz_mpoly_struct * poly = (i == 0) ? gptrs[0] : (i == 1) ? abarptrs[0] : bbarptrs[0]; for (j = 0; j < num_threads; j++) { _joinworker_arg_struct * d = joinbase->chunks + i*num_threads + j; fmpz_mpoly_init3(d->poly, 0, bits, ctx); fmpz_init(d->maxcoeff); fmpz_init(d->sumcoeff); d->GAB = i; d->thread_idx = -WORD(1); d->final_idx = -WORD(1); d->hint_start = poly->length * (j + 0) / num_threads; d->hint_stop = poly->length * (j + 1) / num_threads; d->left_exp = NULL; d->right_exp = NULL; FLINT_ASSERT(0 <= d->hint_start); FLINT_ASSERT(d->hint_start <= d->hint_stop); FLINT_ASSERT(d->hint_stop <= poly->length); FLINT_ASSERT(d->hint_start < poly->length); if (j > 0) { FLINT_ASSERT(d->hint_start < poly->length); d->left_exp = poly->exps + N*d->hint_start; } if (j + 1 < num_threads) { FLINT_ASSERT(d->hint_stop < poly->length); d->right_exp = poly->exps + N*d->hint_stop; } } } joinbase->idx = 0; for (i = 0; i + 1 < num_threads; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, _joinworker, joinargs + i); } _joinworker(joinargs + num_threads - 1); for (i = 0; i + 1 < num_threads; i++) { thread_pool_wait(global_thread_pool, handles[i]); } /* final trivial join */ for (i = 0; i < 3; i++) { fmpz_zero(maxcoeff_Gs_Abars_Bbars + i); fmpz_zero(sumcoeff_Gs_Abars_Bbars + i); } { slong idxs[3] = {0, 0, 0}; for (i = 0; i < joinbase->chunks_length; i++) { int type = joinbase->chunks[i].GAB; FLINT_ASSERT(0 <= type && type < 3); joinbase->chunks[i].final_idx = idxs[type]; idxs[type] += joinbase->chunks[i].poly->length; fmpz_add(sumcoeff_Gs_Abars_Bbars + type, sumcoeff_Gs_Abars_Bbars + type, joinbase->chunks[i].sumcoeff); if (fmpz_cmp(maxcoeff_Gs_Abars_Bbars + type, joinbase->chunks[i].maxcoeff) < 0) { fmpz_set(maxcoeff_Gs_Abars_Bbars + type, joinbase->chunks[i].maxcoeff); } } fmpz_mpoly_fit_length(G, idxs[0], ctx); fmpz_mpoly_fit_length(Abar, idxs[1], ctx); fmpz_mpoly_fit_length(Bbar, idxs[2], ctx); G->length = idxs[0]; Abar->length = idxs[1]; Bbar->length = idxs[2]; } joinbase->idx = 0; for (i = 0; i + 1 < num_threads; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, _finaljoinworker, joinargs + i); } _finaljoinworker(joinargs + num_threads - 1); for (i = 0; i + 1 < num_threads; i++) { thread_pool_wait(global_thread_pool, handles[i]); } FLINT_ASSERT(fmpz_mpoly_is_canonical(G, ctx)); FLINT_ASSERT(fmpz_mpoly_is_canonical(Abar, ctx)); FLINT_ASSERT(fmpz_mpoly_is_canonical(Bbar, ctx)); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&joinbase->mutex); #endif /* free join data */ fmpz_multi_CRT_clear(joinbase->CRT); for (i = 0; i < joinbase->chunks_length; i++) { fmpz_mpoly_clear(joinbase->chunks[i].poly, ctx); fmpz_clear(joinbase->chunks[i].maxcoeff); fmpz_clear(joinbase->chunks[i].sumcoeff); } flint_free(joinbase->chunks); flint_free(joinargs); /* update modulus - modulus could be one of the moduli[i] */ fmpz_one(temp); for (i = 0; i < num_images; i++) fmpz_mul(temp, temp, moduli + i); fmpz_swap(modulus, temp); for (i = 1; i < 3; i++) { fmpz_mul(temp, maxcoeff_Gs_Abars_Bbars + 0, sumcoeff_Gs_Abars_Bbars + i); fmpz_mul(temp2, sumcoeff_Gs_Abars_Bbars + 0, maxcoeff_Gs_Abars_Bbars + i); if (fmpz_cmp(temp, temp2) > 0) fmpz_swap(temp, temp2); fmpz_mul_2exp(temp, temp, 1); if (fmpz_cmp(temp, modulus) >= 0) { fmpz_mul_2exp(bound, modulus, 2*FLINT_BITS); goto compute_split; } } FLINT_ASSERT(fmpz_equal(splitbase->gamma, G->coeffs + 0)); _fmpz_vec_content(temp, G->coeffs, G->length); fmpz_mpoly_scalar_divexact_fmpz(G, G, temp, ctx); fmpz_mpoly_scalar_divexact_fmpz(Abar, Abar, G->coeffs + 0, ctx); fmpz_mpoly_scalar_divexact_fmpz(Bbar, Bbar, G->coeffs + 0, ctx); successful_put_content: fmpz_mpoly_scalar_mul_fmpz(G, G, cG, ctx); fmpz_mpoly_scalar_mul_fmpz(Abar, Abar, cAbar, ctx); fmpz_mpoly_scalar_mul_fmpz(Bbar, Bbar, cBbar, ctx); success = 1; cleanup_split: #if FLINT_USES_PTHREAD pthread_mutex_destroy(&splitbase->mutex); #endif fmpz_clear(splitbase->gamma); for (i = 0; i < num_threads; i++) { fmpz_mpoly_clear(splitargs[i].G, ctx); fmpz_mpoly_clear(splitargs[i].Abar, ctx); fmpz_mpoly_clear(splitargs[i].Bbar, ctx); fmpz_clear(splitargs[i].modulus); flint_free(splitargs[i].worker_handles); } flint_free(gptrs); flint_free(abarptrs); flint_free(bbarptrs); flint_free(moduli); /* they were just shallow copies */ flint_free(splitargs); _fmpq_vec_clear(qvec, num_threads); fmpz_clear(cA); fmpz_clear(cB); fmpz_clear(cG); fmpz_clear(cAbar); fmpz_clear(cBbar); fmpz_clear(bound); fmpz_clear(modulus); fmpz_clear(temp); fmpz_clear(temp2); for (i = 0; i < 3; i++) { fmpz_clear(maxcoeff_Gs_Abars_Bbars + i); fmpz_clear(sumcoeff_Gs_Abars_Bbars + i); } return success; } flint-3.1.3/src/fmpz_mpoly_factor/gcd_hensel.c000066400000000000000000000274511461254215100214240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq.h" #include "fmpz_mpoly_factor.h" int fmpz_mpolyl_gcd_hensel( fmpz_mpoly_t G, slong Gdeg, /* upperbound on deg_X(G) */ fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int success, alpha_bits, gamma_is_one; const slong n = ctx->minfo->nvars - 1; slong i, k; flint_bitcnt_t bits = A->bits; fmpz * alphas, * prev_alphas; fmpz_t q, mu1, mu2; fmpq_t mu; fmpz_mpoly_struct * Aevals, * Bevals, * Hevals; fmpz_mpoly_struct * H; /* points to A, B, or Hevals + n */ fmpz_mpoly_struct * Glcs, * Hlcs; fmpz_mpoly_struct Hfac[2], Htfac[2]; slong * Hdegs; slong Adegx, Bdegx, gdegx; fmpz_mpoly_t t1, t2, g, abar, bbar, hbar; flint_rand_t state; FLINT_ASSERT(n > 0); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); flint_randinit(state); Hdegs = FLINT_ARRAY_ALLOC(n + 1, slong); Glcs = FLINT_ARRAY_ALLOC(3*(n + 1), fmpz_mpoly_struct); Hlcs = Glcs + (n + 1); Hevals = Hlcs + (n + 1); for (i = 0; i < n + 1; i++) { fmpz_mpoly_init(Glcs + i, ctx); fmpz_mpoly_init(Hlcs + i, ctx); fmpz_mpoly_init(Hevals + i, ctx); } alphas = _fmpz_vec_init(2*n); prev_alphas = alphas + n; Aevals = FLINT_ARRAY_ALLOC(2*(n + 1), fmpz_mpoly_struct); Bevals = Aevals + (n + 1); for (i = 0; i < n; i++) { fmpz_mpoly_init(Aevals + i, ctx); fmpz_mpoly_init(Bevals + i, ctx); } fmpz_init(q); fmpq_init(mu); fmpz_init(mu1); fmpz_init(mu2); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(abar, ctx); fmpz_mpoly_init(bbar, ctx); fmpz_mpoly_init(hbar, ctx); fmpz_mpoly_init(Hfac + 0, ctx); fmpz_mpoly_init(Hfac + 1, ctx); fmpz_mpoly_init(Htfac + 0, ctx); fmpz_mpoly_init(Htfac + 1, ctx); /* init done */ alpha_bits = 0; /* try all zeros first */ for (i = 0; i < n; i++) { fmpz_zero(prev_alphas + i); fmpz_zero(alphas + i); } goto got_alpha; next_alpha: alpha_bits++; if (alpha_bits > FLINT_BITS/2) { success = 0; goto cleanup; } success = 0; for (i = 0; i < n; i++) { ulong l = n_randlimb(state); ulong mask = UWORD(1) << alpha_bits; if (l & mask) fmpz_neg_ui(alphas + i, l & (mask - 1)); else fmpz_set_ui(alphas + i, l & (mask - 1)); success = success || !fmpz_equal(alphas + i, prev_alphas + i); } if (!success) goto next_alpha; got_alpha: /* ensure deg_X do not drop under evaluation */ Adegx = fmpz_mpoly_degree_si(A, 0, ctx); Bdegx = fmpz_mpoly_degree_si(B, 0, ctx); for (i = n - 1; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alphas + i, ctx); fmpz_mpoly_evaluate_one_fmpz(Bevals + i, i == n - 1 ? B : Bevals + i + 1, i + 1, alphas + i, ctx); if (Adegx != fmpz_mpoly_degree_si(Aevals + i, 0, ctx) || Bdegx != fmpz_mpoly_degree_si(Bevals + i, 0, ctx)) { goto next_alpha; } } /* univariate gcd */ success = fmpz_mpoly_gcd_cofactors(g, abar, bbar, Aevals + 0, Bevals + 0, ctx) && fmpz_mpoly_gcd(t1, g, abar, ctx) && fmpz_mpoly_gcd(t2, g, bbar, ctx); if (!success) goto cleanup; gdegx = fmpz_mpoly_degree_si(g, 0, ctx); if (gdegx == 0) { /* G is trivial */ fmpz_mpoly_set(Abar, A, ctx); fmpz_mpoly_set(Bbar, B, ctx); fmpz_mpoly_one(G, ctx); success = 1; goto cleanup; } else if (gdegx > Gdeg) { goto next_alpha; } else if (gdegx < Gdeg) { Gdeg = gdegx; for (i = 0; i < n; i++) fmpz_set(prev_alphas + i, alphas + i); goto next_alpha; } /* the degbound gdegx (== Gdeg) has at least two witnesses now */ if (gdegx == Adegx) { if (fmpz_mpoly_divides(Bbar, B, A, ctx)) { fmpz_mpoly_set(G, A, ctx); fmpz_mpoly_one(Abar, ctx); success = 1; goto cleanup; } goto next_alpha; } else if (gdegx == Bdegx) { if (fmpz_mpoly_divides(Abar, A, B, ctx)) { fmpz_mpoly_set(G, B, ctx); fmpz_mpoly_one(Bbar, ctx); success = 1; goto cleanup; } goto next_alpha; } FLINT_ASSERT(0 < gdegx && gdegx < FLINT_MIN(Adegx, Bdegx)); /* set Hlcs[n], Glcs[n] (gamma), H, and Hevals */ if (fmpz_mpoly_is_one(t1, ctx)) { fmpz_one(mu1); fmpz_zero(mu2); fmpz_mpoly_swap(hbar, abar, ctx); fmpz_mpolyl_lead_coeff(Hlcs + n, A, 1, ctx); fmpz_mpolyl_lead_coeff(t2, B, 1, ctx); success = fmpz_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fmpz_mpoly_struct *) A; gamma_is_one = fmpz_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fmpz_mpoly_swap(Hevals + i, Aevals + i, ctx); } else if (fmpz_mpoly_is_one(t2, ctx)) { fmpz_zero(mu1); fmpz_one(mu2); fmpz_mpoly_swap(hbar, bbar, ctx); fmpz_mpolyl_lead_coeff(Hlcs + n, B, 1, ctx); fmpz_mpolyl_lead_coeff(t2, A, 1, ctx); success = fmpz_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fmpz_mpoly_struct *) B; gamma_is_one = fmpz_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fmpz_mpoly_swap(Hevals + i, Bevals + i, ctx); } else { int mu_tries_remaining = 10; next_mu: if (--mu_tries_remaining < 0) { success = 0; goto cleanup; } fmpq_next_signed_calkin_wilf(mu, mu); fmpz_set(mu1, fmpq_numref(mu)); fmpz_set(mu2, fmpq_denref(mu)); fmpz_mpoly_scalar_fmma(hbar, abar, mu1, bbar, mu2, ctx); /* make sure the linear combo did not drop degree */ if (fmpz_mpoly_degree_si(hbar, 0, ctx) != FLINT_MAX(Adegx, Bdegx) - gdegx) goto next_mu; /* make sure the linear combo is prime to g */ success = fmpz_mpoly_gcd(t1, hbar, g, ctx); if (!success) goto cleanup; if (!fmpz_mpoly_is_fmpz(t1, ctx)) goto next_mu; fmpz_mpolyl_lead_coeff(t1, A, 1, ctx); fmpz_mpolyl_lead_coeff(t2, B, 1, ctx); success = fmpz_mpoly_gcd(Glcs + n, t1, t2, ctx); if (!success) goto cleanup; H = Hevals + n; fmpz_mpoly_scalar_fmma(H, A, mu1, B, mu2, ctx); fmpz_mpolyl_lead_coeff(Hlcs + n, H, 1, ctx); gamma_is_one = fmpz_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fmpz_mpoly_scalar_fmma(Hevals + i, Aevals + i, mu1, Bevals + i, mu2, ctx); } if (!gamma_is_one) { fmpz_mpoly_mul(Hevals + n, H, Glcs + n, ctx); H = Hevals + n; for (i = n - 1; i >= 0; i--) fmpz_mpoly_evaluate_one_fmpz(Hevals + i, Hevals + i + 1, i + 1, alphas + i, ctx); } success = H->bits <= FLINT_BITS || fmpz_mpoly_repack_bits_inplace(H, FLINT_BITS, ctx); if (!success) goto cleanup; /* the evals should all fit in H->bits */ for (i = 0; i < n; i++) fmpz_mpoly_repack_bits_inplace(Hevals + i, H->bits, ctx); fmpz_mpoly_degrees_si(Hdegs, H, ctx); /* computed evaluated leading coeffs */ for (i = n - 1; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(Glcs + i, Glcs + i + 1, i + 1, alphas + i, ctx); fmpz_mpoly_evaluate_one_fmpz(Hlcs + i, Hlcs + i + 1, i + 1, alphas + i, ctx); /* evaluation could have killed gamma */ if (fmpz_mpoly_is_zero(Glcs + i, ctx) || fmpz_mpoly_is_zero(Hlcs + i, ctx)) { goto next_alpha; } } /* make the lcs match Glcs[0], Hlcs[0], g & hbar not nec primitive */ fmpz_mpoly_scalar_mul_fmpz(Hfac + 0, g, Glcs[0].coeffs + 0, ctx); success = fmpz_mpoly_scalar_divides_fmpz(Hfac + 0, Hfac + 0, g->coeffs + 0, ctx); FLINT_ASSERT(success); fmpz_mpoly_scalar_mul_fmpz(Hfac + 1, hbar, Hlcs[0].coeffs + 0, ctx); success = fmpz_mpoly_scalar_divides_fmpz(Hfac + 1, Hfac + 1, hbar->coeffs + 0, ctx); FLINT_ASSERT(success); for (k = 1; k <= n; k++) { _fmpz_mpoly_set_lead0(Htfac + 0, Hfac + 0, Glcs + k, ctx); _fmpz_mpoly_set_lead0(Htfac + 1, Hfac + 1, Hlcs + k, ctx); success = fmpz_mpoly_hlift(k, Htfac, 2, alphas, k < n ? Hevals + k : H, Hdegs, ctx); if (!success) goto next_alpha; fmpz_mpoly_swap(Hfac + 0, Htfac + 0, ctx); fmpz_mpoly_swap(Hfac + 1, Htfac + 1, ctx); } success = fmpz_mpolyl_content(t1, Hfac + 0, 1, ctx); if (!success) goto cleanup; success = fmpz_mpoly_divides(G, Hfac + 0, t1, ctx); FLINT_ASSERT(success); if (fmpz_is_zero(mu2)) { FLINT_ASSERT(fmpz_is_one(mu1)); /* the division by t1 should succeed, but let's be careful */ fmpz_mpolyl_lead_coeff(t1, G, 1, ctx); success = fmpz_mpoly_divides(Abar, Hfac + 1, t1, ctx) && fmpz_mpoly_divides(Bbar, B, G, ctx); } else if (fmpz_is_zero(mu1)) { FLINT_ASSERT(fmpz_is_one(mu2)); /* ditto */ fmpz_mpolyl_lead_coeff(t1, G, 1, ctx); success = fmpz_mpoly_divides(Bbar, Hfac + 1, t1, ctx) && fmpz_mpoly_divides(Abar, A, G, ctx); } else { success = fmpz_mpoly_divides(Abar, A, G, ctx) && fmpz_mpoly_divides(Bbar, B, G, ctx); } if (!success) goto next_alpha; success = 1; cleanup: flint_randclear(state); flint_free(Hdegs); for (i = 0; i < n + 1; i++) { fmpz_mpoly_clear(Glcs + i, ctx); fmpz_mpoly_clear(Hlcs + i, ctx); fmpz_mpoly_clear(Hevals + i, ctx); } flint_free(Glcs); _fmpz_vec_clear(alphas, 2*n); for (i = 0; i < n; i++) { fmpz_mpoly_clear(Aevals + i, ctx); fmpz_mpoly_clear(Bevals + i, ctx); } flint_free(Aevals); fmpz_clear(q); fmpq_clear(mu); fmpz_clear(mu1); fmpz_clear(mu2); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(abar, ctx); fmpz_mpoly_clear(bbar, ctx); fmpz_mpoly_clear(hbar, ctx); fmpz_mpoly_clear(Hfac + 0, ctx); fmpz_mpoly_clear(Hfac + 1, ctx); fmpz_mpoly_clear(Htfac + 0, ctx); fmpz_mpoly_clear(Htfac + 1, ctx); if (success) { fmpz_mpoly_repack_bits_inplace(G, bits, ctx); fmpz_mpoly_repack_bits_inplace(Abar, bits, ctx); fmpz_mpoly_repack_bits_inplace(Bbar, bits, ctx); FLINT_ASSERT(G->length > 0); FLINT_ASSERT(Abar->length > 0); FLINT_ASSERT(Bbar->length > 0); } return success; } flint-3.1.3/src/fmpz_mpoly_factor/gcd_zippel.c000066400000000000000000000166711461254215100214530ustar00rootroot00000000000000/* Copyright (C) 2018, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #include "fmpz_mpoly_factor.h" /* return an n with |gcd(A,B)|_infty < 2^n or return UWORD_MAX */ static flint_bitcnt_t fmpz_mpoly_gcd_bitbound( const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { flint_bitcnt_t bound = UWORD_MAX; fmpz_t norm, M; slong * degs; TMP_INIT; TMP_START; fmpz_init(norm); fmpz_init(M); degs = TMP_ARRAY_ALLOC(ctx->minfo->nvars, slong); fmpz_mpoly_degrees_si(degs, A, ctx); _fmpz_vec_height(norm, A->coeffs, A->length); if (fmpz_mpoly_factor_bound_si(M, norm, degs, ctx->minfo->nvars)) bound = FLINT_MIN(bound, fmpz_bits(M)); fmpz_mpoly_degrees_si(degs, B, ctx); _fmpz_vec_height(norm, B->coeffs, B->length); if (fmpz_mpoly_factor_bound_si(M, norm, degs, ctx->minfo->nvars)) bound = FLINT_MIN(bound, fmpz_bits(M)); fmpz_clear(norm); fmpz_clear(M); TMP_END; return bound; } int fmpz_mpolyl_gcd_zippel( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, flint_rand_t state) { flint_bitcnt_t coeffbitbound; flint_bitcnt_t coeffbits; flint_bitcnt_t bits = G->bits; int success, changed; slong i, j, Gdegbound, Gdeg, req_zip_images; mp_limb_t p, t, gammap; fmpz_t c, gamma, modulus; nmod_mpoly_t Ap, Bp, Gp, Abarp, Bbarp; nmod_mpoly_ctx_t ctxp; n_poly_t Amarks, Bmarks, Gmarks; slong * perm = NULL; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(ctx->minfo->nvars > 1); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == Abar->bits); FLINT_ASSERT(bits == Bbar->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == G->bits); fmpz_init(c); fmpz_init(gamma); fmpz_init(modulus); nmod_mpoly_ctx_init(ctxp, ctx->minfo->nvars, ORD_LEX, 2); nmod_mpoly_init3(Ap, 0, bits, ctxp); nmod_mpoly_init3(Bp, 0, bits, ctxp); nmod_mpoly_init3(Gp, 0, bits, ctxp); nmod_mpoly_init3(Abarp, 0, bits, ctxp); nmod_mpoly_init3(Bbarp, 0, bits, ctxp); n_poly_init(Amarks); n_poly_init(Bmarks); n_poly_init(Gmarks); fmpz_gcd(gamma, fmpz_mpoly_leadcoeff(A), fmpz_mpoly_leadcoeff(B)); Gdegbound = fmpz_mpoly_degree_si(A, 0, ctx); Gdeg = fmpz_mpoly_degree_si(B, 0, ctx); Gdegbound = FLINT_MIN(Gdegbound, Gdeg); coeffbitbound = fmpz_mpoly_gcd_bitbound(A, B, ctx); if (n_add_checked(&coeffbitbound, coeffbitbound, fmpz_bits(gamma))) coeffbitbound = UWORD_MAX; p = UWORD(1) << (FLINT_BITS - 1); outer_loop: if (p >= UWORD_MAX_PRIME) { /* ran out of primes: absolute failure */ success = 0; goto cleanup; } p = n_nextprime(p, 1); nmod_mpoly_ctx_set_modulus(ctxp, p); /* make sure mod p reduction does not kill both lc(A) and lc(B) */ gammap = fmpz_get_nmod(gamma, ctxp->mod); if (gammap == 0) goto outer_loop; /* make sure mod p reduction does not kill either A or B */ fmpz_mpoly_interp_reduce_p(Ap, ctxp, A, ctx); fmpz_mpoly_interp_reduce_p(Bp, ctxp, B, ctx); if (Ap->length == 0 || Bp->length == 0) goto outer_loop; success = nmod_mpolyl_gcdp_zippel_smprime(Gp, Abarp, Bbarp, Ap, Bp, ctx->minfo->nvars - 1, ctxp, state); if (!success) goto outer_loop; Gdeg = nmod_mpoly_degree_si(Gp, 0, ctxp); if (Gdeg > Gdegbound) goto outer_loop; if (Gdeg == 0 && nmod_mpoly_is_one(Gp, ctxp)) { fmpz_mpoly_one(G, ctx); fmpz_mpoly_set(Abar, A, ctx); fmpz_mpoly_set(Bbar, B, ctx); success = 1; goto cleanup; } Gdegbound = Gdeg; t = nmod_div(gammap, nmod_mpoly_leadcoeff(Gp, ctxp), ctxp->mod); nmod_mpoly_scalar_mul_nmod_invertible(Gp, Gp, t, ctxp); fmpz_mpoly_interp_lift_p(G, ctx, Gp, ctxp); fmpz_set_ui(modulus, p); /* TODO: a divisibility test here if coeffs are small */ mpoly1_fill_marks(&Gmarks->coeffs, &Gmarks->length, &Gmarks->alloc, G->exps, G->length, bits, ctx->minfo); perm = FLINT_ARRAY_REALLOC(perm, Gmarks->length, slong); for (i = 0; i < Gmarks->length; i++) perm[i] = i; #define length(k) Gmarks->coeffs[(k)+1] - Gmarks->coeffs[k] for (i = 1; i < Gmarks->length; i++) for (j = i; j > 0 && length(perm[j-1]) > length(perm[j]); j--) FLINT_SWAP(slong, perm[j-1], perm[j]); req_zip_images = Gmarks->length - 2; j = 0; for (i = 0; i < Gmarks->length; i++) { req_zip_images += length(i); j = FLINT_MAX(j, length(i)); } if (Gmarks->length > 1) req_zip_images = req_zip_images / (Gmarks->length - 1); req_zip_images = FLINT_MAX(req_zip_images, j); req_zip_images += 1; inner_loop: if (p >= UWORD_MAX_PRIME) { /* ran out of primes: absolute failure */ success = 0; goto cleanup; } p = n_nextprime(p, 1); nmod_mpoly_ctx_set_modulus(ctxp, p); /* make sure mod p reduction does not kill both lc(A) and lc(B) */ gammap = fmpz_get_nmod(gamma, ctxp->mod); if (gammap == 0) goto inner_loop; /* make sure mod p reduction does not kill either A or B */ fmpz_mpoly_interp_reduce_p(Ap, ctxp, A, ctx); fmpz_mpoly_interp_reduce_p(Bp, ctxp, B, ctx); if (Ap->length == 0 || Bp->length == 0) goto inner_loop; success = nmod_mpolyl_gcds_zippel(Gp, Gmarks->coeffs, Gmarks->length, Ap, Bp, perm, req_zip_images, ctx->minfo->nvars, ctxp, state, &Gdegbound, Amarks, Bmarks); if (success == 0) goto outer_loop; /* resets modulus */ if (success < 0 || nmod_mpoly_leadcoeff(Gp, ctxp) == 0) goto inner_loop; t = nmod_div(gammap, nmod_mpoly_leadcoeff(Gp, ctxp), ctxp->mod); nmod_mpoly_scalar_mul_nmod_invertible(Gp, Gp, t, ctxp); changed = fmpz_mpoly_interp_mcrt_p(&coeffbits, G, ctx, modulus, Gp, ctxp); fmpz_mul_ui(modulus, modulus, p); if (changed) { if (coeffbits > coeffbitbound) goto outer_loop; /* resets modulus */ goto inner_loop; } _fmpz_vec_content(c, G->coeffs, G->length); _fmpz_vec_scalar_divexact_fmpz(G->coeffs, G->coeffs, G->length, c); success = fmpz_mpoly_divides(Abar, A, G, ctx) && fmpz_mpoly_divides(Bbar, B, G, ctx); if (success) goto cleanup; /* restore interpolated state */ _fmpz_vec_scalar_mul_fmpz(G->coeffs, G->coeffs, G->length, c); goto inner_loop; cleanup: flint_free(perm); n_poly_clear(Amarks); n_poly_clear(Bmarks); n_poly_clear(Gmarks); nmod_mpoly_clear(Ap, ctxp); nmod_mpoly_clear(Bp, ctxp); nmod_mpoly_clear(Gp, ctxp); nmod_mpoly_clear(Abarp, ctxp); nmod_mpoly_clear(Bbarp, ctxp); nmod_mpoly_ctx_clear(ctxp); fmpz_clear(c); fmpz_clear(gamma); fmpz_clear(modulus); return success; } flint-3.1.3/src/fmpz_mpoly_factor/gcd_zippel2.c000066400000000000000000002170371461254215100215340ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "n_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" #include "nmod_mpoly_factor.h" #include "fmpz_mod_mpoly_factor.h" typedef struct { nmod_berlekamp_massey_struct * coeffs; ulong * exps; slong length; slong alloc; slong pointcount; } nmod_bma_mpoly_struct; typedef nmod_bma_mpoly_struct nmod_bma_mpoly_t[1]; typedef struct { fmpz_mod_berlekamp_massey_struct * coeffs; ulong * exps; slong length; slong alloc; slong pointcount; } fmpz_mod_bma_mpoly_struct; typedef fmpz_mod_bma_mpoly_struct fmpz_mod_bma_mpoly_t[1]; typedef struct { slong * degbounds; ulong * subdegs; fmpz_mod_discrete_log_pohlig_hellman_t dlogenv; nmod_discrete_log_pohlig_hellman_t dlogenv_sp; } mpoly_bma_interpolate_ctx_struct; typedef mpoly_bma_interpolate_ctx_struct mpoly_bma_interpolate_ctx_t[1]; static void mpoly_bma_interpolate_ctx_init(mpoly_bma_interpolate_ctx_t I, slong nvars) { I->degbounds = (slong *) flint_malloc(nvars*sizeof(slong)); I->subdegs = (ulong *) flint_malloc(nvars*sizeof(ulong)); fmpz_mod_discrete_log_pohlig_hellman_init(I->dlogenv); nmod_discrete_log_pohlig_hellman_init(I->dlogenv_sp); } static void mpoly_bma_interpolate_ctx_clear(mpoly_bma_interpolate_ctx_t I) { flint_free(I->degbounds); flint_free(I->subdegs); fmpz_mod_discrete_log_pohlig_hellman_clear(I->dlogenv); nmod_discrete_log_pohlig_hellman_clear(I->dlogenv_sp); } static void mpoly2_nmod_monomial_evals( n_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, ulong * Amarks, slong Amarkslen, n_poly_struct * caches, const mpoly_ctx_t mctx, nmod_t fpctx) { slong start, stop, i, j, k, n; slong e0, e1; slong nvars = mctx->nvars; mp_limb_t * p; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; TMP_INIT; FLINT_ASSERT(nvars > 2); FLINT_ASSERT(Amarkslen > 0); TMP_START; off = (slong *) TMP_ALLOC(2*nvars*sizeof(slong)); shift = off + nvars; for (k = 0; k < nvars; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k, Abits, mctx); n_polyun_fit_length(EH, Amarkslen); for (i = 0; i < Amarkslen; i++) { start = Amarks[i]; stop = Amarks[i + 1]; FLINT_ASSERT(start < stop); n = stop - start; e0 = (Aexps[N*start + off[0]] >> shift[0]) & mask; e1 = (Aexps[N*start + off[1]] >> shift[1]) & mask; EH->exps[i] = pack_exp2(e0, e1); n_poly_fit_length(EH->coeffs + i, n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; for (j = 0; j < n; j++) { p[j] = 1; for (k = 2; k < nvars; k++) { ulong ei = (Aexps[N*(start + j) + off[k]] >> shift[k]) & mask; p[j] = nmod_pow_cache_mulpow_ui(p[j], ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, fpctx); } } } EH->length = Amarkslen; TMP_END; } /* evaluation at gen(start) -> caches[0] gen(start+1) -> caches[1] ... gen(stop-1) -> caches[stop-start-1] the other gen are assumed to not appear in A */ static void mpoly_nmod_monomial_evals( n_poly_t EH, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, n_poly_struct * caches, slong start, slong stop, const mpoly_ctx_t mctx, nmod_t fpctx) { slong i, k; mp_limb_t * p; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; slong num = stop - start; TMP_INIT; TMP_START; off = TMP_ARRAY_ALLOC(2*num, slong); shift = off + num; for (k = 0; k < num; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k + start, Abits, mctx); n_poly_fit_length(EH, Alen); EH->length = Alen; p = EH->coeffs; for (i = 0; i < Alen; i++) { p[i] = 1; for (k = 0; k < num; k++) { ulong ei = (Aexps[N*i + off[k]] >> shift[k]) & mask; p[i] = nmod_pow_cache_mulpow_ui(p[i], ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, fpctx); } } TMP_END; } static void fmpz_mpoly2_nmod_coeffs( n_polyun_t EH, const fmpz * Acoeffs, ulong * Amarks, slong Amarkslen, nmod_t fpctx) { slong start, stop, i, n; n_polyun_fit_length(EH, Amarkslen); for (i = 0; i < Amarkslen; i++) { start = Amarks[i]; stop = Amarks[i + 1]; FLINT_ASSERT(start < stop); n = stop - start; EH->exps[i] = 0; n_poly_fit_length(EH->coeffs + i, n); EH->coeffs[i].length = n; _fmpz_vec_get_nmod_vec(EH->coeffs[i].coeffs, Acoeffs + start, n, fpctx); } EH->length = Amarkslen; } static void fmpz_mpoly2_fmpz_mod_coeffs( fmpz_mod_polyun_t EH, const fmpz * Acoeffs, ulong * Amarks, slong Amarkslen, const fmpz_mod_ctx_t fpctx) { slong start, stop, i, n; fmpz_mod_polyun_fit_length(EH, Amarkslen, fpctx); for (i = 0; i < Amarkslen; i++) { start = Amarks[i]; stop = Amarks[i + 1]; FLINT_ASSERT(start < stop); n = stop - start; EH->exps[i] = 0; fmpz_mod_poly_fit_length(EH->coeffs + i, n, fpctx); EH->coeffs[i].length = n; _fmpz_mod_vec_set_fmpz_vec(EH->coeffs[i].coeffs, Acoeffs + start, n, fpctx); } EH->length = Amarkslen; } static void fmpz_mpoly_nmod_coeffs( n_poly_t EH, const fmpz * Acoeffs, slong Alen, nmod_t fpctx) { n_poly_fit_length(EH, Alen); EH->length = Alen; _fmpz_vec_get_nmod_vec(EH->coeffs, Acoeffs, Alen, fpctx); } static void fmpz_mpoly_fmpz_mod_coeffs( fmpz_mod_poly_t EH, const fmpz * Acoeffs, slong Alen, const fmpz_mod_ctx_t fpctx) { fmpz_mod_poly_fit_length(EH, Alen, fpctx); EH->length = Alen; _fmpz_mod_vec_set_fmpz_vec(EH->coeffs, Acoeffs, Alen, fpctx); } mp_limb_t n_poly_mod_zip_eval_cur_inc_coeff( n_poly_t Acur, n_poly_t Ainc, n_poly_t Acoeff, nmod_t ctx) { return _nmod_zip_eval_step(Acur->coeffs, Ainc->coeffs, Acoeff->coeffs, Acur->length, ctx); } void fmpz_mod_poly_zip_eval_cur_inc_coeff( fmpz_t e, fmpz_mod_poly_t Acur, fmpz_mod_poly_t Ainc, fmpz_mod_poly_t Acoeff, const fmpz_mod_ctx_t ctx) { _fmpz_mod_zip_eval_step(e, Acur->coeffs, Ainc->coeffs, Acoeff->coeffs, Acur->length, ctx); } static void n_polyun_mod_zip_eval_cur_inc_coeff( n_polyun_t E, n_polyun_t Acur, const n_polyun_t Ainc, const n_polyun_t Acoeff, nmod_t ctx) { slong i, Ei; slong e0, e1; mp_limb_t c; n_poly_struct * Ec; FLINT_ASSERT(Acur->length > 0); FLINT_ASSERT(Acur->length == Ainc->length); FLINT_ASSERT(Acur->length == Acoeff->length); e0 = extract_exp(Acur->exps[0], 1, 2); e1 = extract_exp(Acur->exps[0], 0, 2); n_polyun_fit_length(E, 4); Ei = 0; E->exps[Ei] = e1; Ec = E->coeffs + Ei; n_poly_zero(Ec); for (i = 0; i < Acur->length; i++) { slong this_len = Acur->coeffs[i].length; FLINT_ASSERT(this_len == Ainc->coeffs[i].length); FLINT_ASSERT(this_len == Acoeff->coeffs[i].length); c = _nmod_zip_eval_step(Acur->coeffs[i].coeffs, Ainc->coeffs[i].coeffs, Acoeff->coeffs[i].coeffs, this_len, ctx); e0 = extract_exp(Acur->exps[i], 1, 2); e1 = extract_exp(Acur->exps[i], 0, 2); if (E->exps[Ei] != e0) { n_polyun_fit_length(E, Ei + 2); Ei += !n_poly_is_zero(E->coeffs + Ei); E->exps[Ei] = e0; Ec = E->coeffs + Ei; n_poly_zero(Ec); } n_poly_set_coeff(Ec, e1, c); } Ei += !n_poly_is_zero(E->coeffs + Ei); E->length = Ei; FLINT_ASSERT(n_polyun_mod_is_canonical(E, ctx)); } static void fmpz_mpoly2_eval_nmod( n_polyun_t E, n_polyun_t EHcur, n_polyun_t EHinc, n_polyun_t EHcoeffs, const fmpz_mpoly_t A, ulong * Amarks, slong Amarkslen, n_poly_struct * alpha_caches, const fmpz_mpoly_ctx_t ctx, nmod_t fpctx) { mpoly2_nmod_monomial_evals(EHcur, A->exps, A->bits, Amarks, Amarkslen, alpha_caches, ctx->minfo, fpctx); n_polyun_set(EHinc, EHcur); fmpz_mpoly2_nmod_coeffs(EHcoeffs, A->coeffs, Amarks, Amarkslen, fpctx); n_polyun_mod_zip_eval_cur_inc_coeff(E, EHcur, EHinc, EHcoeffs, fpctx); } static void fmpz_mpoly2_eval_fmpz_mod( fmpz_mod_polyun_t E, fmpz_mod_polyun_t EHcur, fmpz_mod_polyun_t EHinc, fmpz_mod_polyun_t EHcoeffs, const fmpz_mpoly_t A, ulong * Amarks, slong Amarkslen, fmpz_mod_poly_struct * alpha_caches, const fmpz_mpoly_ctx_t ctx, const fmpz_mod_ctx_t fpctx) { mpoly2_monomial_evals_fmpz_mod(EHcur, A->exps, A->bits, Amarks, Amarkslen, alpha_caches + 2, ctx->minfo->nvars, ctx->minfo, fpctx); fmpz_mod_polyun_set(EHinc, EHcur, fpctx); fmpz_mpoly2_fmpz_mod_coeffs(EHcoeffs, A->coeffs, Amarks, Amarkslen, fpctx); fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(E, EHcur, EHinc, EHcoeffs, fpctx); } /* set out to the evaluation of variables after ksub at alpha^w out[m+0] = alpha ^ (w * subdegs[n-1] * subdegs[n-2] * ... * * subdegs[m+1]) ... out[n-3] = alpha ^ (w * subdegs[n-1] * subdegs[n-2]) out[n-2] = alpha ^ (w * subdegs[n-1]) out[n-1] = alpha ^ (w) secret: subdegs[0] is not used */ void nmod_mpoly_bma_interpolate_alpha_powers( mp_limb_t * out, ulong w, slong m, const mpoly_bma_interpolate_ctx_t Ictx, const fmpz_mpoly_ctx_t ctx, nmod_t fpctx) { slong j = ctx->minfo->nvars - 1; out[j] = nmod_pow_ui(Ictx->dlogenv_sp->alpha, w, fpctx); for (; j > m; j--) out[j - 1] = nmod_pow_ui(out[j], Ictx->subdegs[j], fpctx); } void fmpz_mod_mpoly_bma_interpolate_alpha_powers( fmpz * out, const fmpz_t w, slong m, const mpoly_bma_interpolate_ctx_t Ictx, const fmpz_mpoly_ctx_t ctx, const fmpz_mod_ctx_t fpctx) { slong j = ctx->minfo->nvars - 1; fmpz_mod_pow_fmpz(out + j, Ictx->dlogenv->alpha, w, fpctx); for (; j > m; j--) fmpz_mod_pow_ui(out + j - 1, out + j, Ictx->subdegs[j], fpctx); } void nmod_bma_mpoly_init(nmod_bma_mpoly_t A) { A->length = 0; A->alloc = 0; A->exps = NULL; A->coeffs = NULL; A->pointcount = 0; } void nmod_bma_mpoly_reset_prime( nmod_bma_mpoly_t A, nmod_t fpctx) { slong i; for (i = 0; i < A->alloc; i++) nmod_berlekamp_massey_set_prime(A->coeffs + i, fpctx.n); } void nmod_bma_mpoly_clear(nmod_bma_mpoly_t A) { slong i; for (i = 0; i < A->alloc; i++) { nmod_berlekamp_massey_clear(A->coeffs + i); } if (A->exps) flint_free(A->exps); if (A->coeffs) flint_free(A->coeffs); } void nmod_bma_mpoly_fit_length( nmod_bma_mpoly_t A, slong length, nmod_t fpctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, A->alloc + A->alloc/2); if (length > old_alloc) { A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, ulong); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, nmod_berlekamp_massey_struct); for (i = old_alloc; i < new_alloc; i++) nmod_berlekamp_massey_init(A->coeffs + i, fpctx.n); A->alloc = new_alloc; } } void nmod_bma_mpoly_zero(nmod_bma_mpoly_t L) { L->length = 0; L->pointcount = 0; } int nmod_bma_mpoly_reduce(nmod_bma_mpoly_t L) { slong i; int changed; changed = 0; for (i = 0; i < L->length; i++) { FLINT_ASSERT(L->pointcount == nmod_berlekamp_massey_point_count(L->coeffs + i)); changed |= nmod_berlekamp_massey_reduce(L->coeffs + i); } return changed; } void nmod_bma_mpoly_add_point( nmod_bma_mpoly_t L, const n_polyun_t A, nmod_t fpctx) { slong j; slong Alen = A->length; slong Li, Ai, ai; nmod_berlekamp_massey_struct * Lcoeff; slong Llen; ulong * Lexp; ulong Aexp; if (L->length == 0) { slong tot = 0; for (Ai = 0; Ai < Alen; Ai++) for (ai = A->coeffs[Ai].length - 1; ai >= 0; ai--) tot += (0 != A->coeffs[Ai].coeffs[ai]); nmod_bma_mpoly_fit_length(L, tot, fpctx); } Lcoeff = L->coeffs; Llen = L->length; Lexp = L->exps; Li = 0; Ai = ai = 0; Aexp = 0; if (Ai < Alen) { ai = n_poly_degree(A->coeffs + Ai); Aexp = pack_exp2(A->exps[Ai], ai); } while (Li < Llen || Ai < Alen) { if (Li < Llen && Ai < Alen && Lexp[Li] == Aexp) { /* L term present, A term present */ add_same_exp: nmod_berlekamp_massey_add_point(Lcoeff + Li, A->coeffs[Ai].coeffs[ai]); Li++; do { ai--; } while (ai >= 0 && A->coeffs[Ai].coeffs[ai] == 0); if (ai < 0) { Ai++; if (Ai < Alen) { ai = n_poly_degree(A->coeffs + Ai); Aexp = pack_exp2(A->exps[Ai], ai); } } else { FLINT_ASSERT(Ai < A->length); Aexp = pack_exp2(A->exps[Ai], ai); } } else if (Li < Llen && (Ai >= Alen || Lexp[Li] > Aexp)) { /* L term present, A term missing */ nmod_berlekamp_massey_add_zeros(Lcoeff + Li, 1); Li++; } else { /* L term missing, A term present */ FLINT_ASSERT(Ai < Alen && (Li >= Llen || Lexp[Li] < Aexp)); { ulong texp; nmod_berlekamp_massey_struct tcoeff; nmod_bma_mpoly_fit_length(L, Llen + 1, fpctx); Lcoeff = L->coeffs; Lexp = L->exps; texp = Lexp[Llen]; tcoeff = Lcoeff[Llen]; for (j = Llen - 1; j >= Li; j--) { Lexp[j + 1] = Lexp[j]; Lcoeff[j + 1] = Lcoeff[j]; } Lexp[Li] = texp; Lcoeff[Li] = tcoeff; } nmod_berlekamp_massey_start_over(Lcoeff + Li); nmod_berlekamp_massey_add_zeros(Lcoeff + Li, L->pointcount); Lexp[Li] = Aexp; Llen++; L->length = Llen; goto add_same_exp; } } L->pointcount++; } static int n_polyu2n_add_zipun_must_match( n_polyun_t Z, const n_polyun_t A, slong cur_length) { slong i, Ai, ai; ulong Aexp; slong Alen = A->length; Ai = ai = 0; Aexp = 0; if (Ai < Alen) { ai = n_poly_degree(A->coeffs + Ai); Aexp = pack_exp2(A->exps[Ai], ai); } for (i = 0; i < Z->length; i++) { if (Ai < Alen && Z->exps[i] == Aexp) { /* Z present, A present */ Z->coeffs[i].coeffs[cur_length] = A->coeffs[Ai].coeffs[ai]; Z->coeffs[i].length = cur_length + 1; do { ai--; } while (ai >= 0 && A->coeffs[Ai].coeffs[ai] == 0); if (ai < 0) { Ai++; if (Ai < Alen) { ai = n_poly_degree(A->coeffs + Ai); Aexp = pack_exp2(A->exps[Ai], ai); } } else { FLINT_ASSERT(Ai < A->length); Aexp = pack_exp2(A->exps[Ai], ai); } } else if (Ai > Alen || Z->exps[i] > Aexp) { /* Z present, A missing */ Z->coeffs[i].coeffs[cur_length] = 0; Z->coeffs[i].length = cur_length + 1; } else { /* Z missing, A present */ return 0; } } return 1; } /* If I was formed from evaluations at alpha^alphashift, alpha^(alphashift + 1), ... construct the corresponding mpoly if possible with coeffs in (-p/2, p/2] The substitution degrees and degree bounds in Ictx are used. */ static int _nmod_mpoly_bma_get_fmpz_mpoly2( fmpz * Acoeffs, ulong * Aexps, flint_bitcnt_t Abits, ulong e0, ulong e1, const mpoly_ctx_t mctx, slong * shifts, slong * offsets, ulong alphashift, nmod_berlekamp_massey_t I, const mpoly_bma_interpolate_ctx_t Ictx, nmod_t fpctx) { int success; slong i, j, t; slong N = mpoly_words_per_exp_sp(Abits, mctx); ulong new_exp, this_exp; mp_limb_t * values, * roots; mp_limb_t T, S, V, V0, V1, V2, p0, p1, r; FLINT_ASSERT(mctx->ord == ORD_LEX); t = nmod_poly_degree(I->V1); FLINT_ASSERT(I->points->length >= t); if (t < 1) return 0; /* use the rt member of I as temp space for roots - slightly dirty */ nmod_poly_fit_length(I->rt, t); I->rt->length = t; roots = I->rt->coeffs; values = I->points->coeffs; success = nmod_poly_find_distinct_nonzero_roots(roots, I->V1); if (!success) return 0; for (i = 0; i < t; i++) { /* coeffs[i] is (coeffs(P).values)/P(roots[i]) =: V/S where P(x) = master(x)/(x-roots[i]) */ V0 = V1 = V2 = T = S = 0; r = roots[i]; for (j = t; j > 0; j--) { T = nmod_add(nmod_mul(r, T, fpctx), I->V1->coeffs[j], fpctx); S = nmod_add(nmod_mul(r, S, fpctx), T, fpctx); umul_ppmm(p1, p0, values[j - 1], T); add_sssaaaaaa(V2, V1, V0, V2, V1, V0, WORD(0), p1, p0); } /* roots[i] should be a root of master */ FLINT_ASSERT(nmod_add(nmod_mul(r, T, fpctx), I->V1->coeffs[0], fpctx) == 0); NMOD_RED3(V, V2, V1, V0, fpctx); S = nmod_mul(S, nmod_pow_ui(r, alphashift, fpctx), fpctx); V0 = nmod_mul(V, nmod_inv(S, fpctx), fpctx); if (V0 == 0) return 0; if (fpctx.n - V0 < V0) fmpz_neg_ui(Acoeffs + i, fpctx.n - V0); else fmpz_set_ui(Acoeffs + i, V0); mpoly_monomial_zero(Aexps + N*i, N); (Aexps + N*i)[offsets[0]] |= e0 << shifts[0]; (Aexps + N*i)[offsets[1]] |= e1 << shifts[1]; new_exp = nmod_discrete_log_pohlig_hellman_run(Ictx->dlogenv_sp, roots[i]); for (j = mctx->nvars - 1; j >= 2; j--) { this_exp = new_exp % Ictx->subdegs[j]; new_exp = new_exp / Ictx->subdegs[j]; if (this_exp > Ictx->degbounds[j]) return 0; (Aexps + N*i)[offsets[j]] |= this_exp << shifts[j]; } if (new_exp != 0) return 0; } return 1; } static int _fmpz_mod_bma_get_fmpz_mpoly2( fmpz * Acoeffs, ulong * Aexps, flint_bitcnt_t Abits, ulong e0, ulong e1, const mpoly_ctx_t mctx, slong * shifts, slong * offsets, const fmpz_t alphashift, fmpz_mod_berlekamp_massey_t I, const mpoly_bma_interpolate_ctx_t Ictx, const fmpz_mod_ctx_t fpctx) { int success; slong i, j, t; slong N = mpoly_words_per_exp_sp(Abits, mctx); ulong this_exp; fmpz_t new_exp; fmpz * values, * roots; fmpz_t T, S, V, temp, halfp; fmpz_init(halfp); fmpz_init(T); fmpz_init(S); fmpz_init(V); fmpz_init(temp); fmpz_init(new_exp); fmpz_tdiv_q_2exp(halfp, fmpz_mod_ctx_modulus(fpctx), 1); t = fmpz_mod_poly_degree(I->V1, fpctx); FLINT_ASSERT(I->points->length >= t); if (t < 1) { success = 0; goto cleanup; } fmpz_mod_poly_fit_length(I->rt, t, fpctx); I->rt->length = t; roots = I->rt->coeffs; values = I->points->coeffs; success = fmpz_mod_poly_find_distinct_nonzero_roots(roots, I->V1, fpctx); if (!success) goto cleanup; for (i = 0; i < t; i++) { /* coeffs[i] is (coeffs(P).values)/P(roots[i]) =: V/S where P(x) = master(x)/(x-roots[i]) */ fmpz_zero(V); fmpz_zero(T); fmpz_zero(S); for (j = t; j > 0; j--) { fmpz_mod_mul(temp, roots + i, T, fpctx); fmpz_mod_add(T, temp, I->V1->coeffs + j, fpctx); fmpz_mod_mul(temp, roots + i, S, fpctx); fmpz_mod_add(S, temp, T, fpctx); fmpz_mod_mul(temp, values + j - 1, T, fpctx); fmpz_mod_add(V, V, temp, fpctx); } /* roots[i] should be a root of master */ #if FLINT_WANT_ASSERT fmpz_mod_mul(temp, roots + i, T, fpctx); fmpz_mod_add(temp, temp, I->V1->coeffs + 0, fpctx); FLINT_ASSERT(fmpz_is_zero(temp)); #endif fmpz_mod_pow_fmpz(temp, roots + i, alphashift, fpctx); fmpz_mod_mul(S, S, temp, fpctx); fmpz_mod_inv(temp, S, fpctx); fmpz_mod_mul(Acoeffs + i, V, temp, fpctx); if (fmpz_is_zero(Acoeffs + i)) { success = 0; goto cleanup; } if (fmpz_cmp(Acoeffs + i, halfp) > 0) fmpz_sub(Acoeffs + i, Acoeffs + i, fmpz_mod_ctx_modulus(fpctx)); mpoly_monomial_zero(Aexps + N*i, N); (Aexps + N*i)[offsets[0]] |= e0 << shifts[0]; (Aexps + N*i)[offsets[1]] |= e1 << shifts[1]; fmpz_mod_discrete_log_pohlig_hellman_run(new_exp, Ictx->dlogenv, roots + i); for (j = mctx->nvars - 1; j >= 2; j--) { this_exp = fmpz_fdiv_ui(new_exp, Ictx->subdegs[j]); fmpz_fdiv_q_ui(new_exp, new_exp, Ictx->subdegs[j]); if (this_exp > Ictx->degbounds[j]) { success = 0; goto cleanup; } (Aexps + N*i)[offsets[j]] |= this_exp << shifts[j]; } if (!fmpz_is_zero(new_exp)) { success = 0; goto cleanup; } } success = 1; cleanup: fmpz_clear(T); fmpz_clear(S); fmpz_clear(V); fmpz_clear(temp); fmpz_clear(halfp); return success; } int nmod_bma_mpoly_get_fmpz_mpoly2( fmpz_mpoly_t A, n_poly_t Amarks, const fmpz_mpoly_ctx_t ctx, ulong alphashift, const nmod_bma_mpoly_t L, const mpoly_bma_interpolate_ctx_t Ictx, nmod_t fpctx) { int success; slong i, j, k; slong * shifts, * offsets; ulong * marks; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); TMP_INIT; if (L->length < 1) return 0; n_poly_fit_length(Amarks, L->length + 1); Amarks->length = L->length; marks = Amarks->coeffs; TMP_START; shifts = TMP_ARRAY_ALLOC(2*ctx->minfo->nvars, slong); offsets = shifts + ctx->minfo->nvars; for (j = 0; j < ctx->minfo->nvars; j++) mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, ctx->minfo); k = 0; for (i = 0; i < L->length; i++) { nmod_berlekamp_massey_reduce(L->coeffs + i); marks[i] = k; k += nmod_poly_degree(L->coeffs[i].V1); } marks[L->length] = k; fmpz_mpoly_fit_length(A, k, ctx); A->length = k; for (i = 0; i < L->length; i++) { ulong e0 = extract_exp(L->exps[i], 1, 2); ulong e1 = extract_exp(L->exps[i], 0, 2); success = _nmod_mpoly_bma_get_fmpz_mpoly2(A->coeffs + marks[i], A->exps + N*marks[i], A->bits, e0, e1, ctx->minfo, shifts, offsets, alphashift, L->coeffs + i, Ictx, fpctx); if (!success) goto cleanup; } fmpz_mpoly_sort_terms(A, ctx); success = 1; cleanup: TMP_END; return success; } int fmpz_mod_bma_mpoly_get_fmpz_mpoly2( fmpz_mpoly_t A, n_poly_t Amarks, const fmpz_mpoly_ctx_t ctx, const fmpz_t alphashift, const fmpz_mod_bma_mpoly_t L, const mpoly_bma_interpolate_ctx_t Ictx, const fmpz_mod_ctx_t fpctx) { int success; slong i, j, k; slong * shifts, * offsets; ulong * marks; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); TMP_INIT; if (L->length < 1) return 0; n_poly_fit_length(Amarks, L->length + 1); Amarks->length = L->length; marks = Amarks->coeffs; TMP_START; shifts = TMP_ARRAY_ALLOC(2*ctx->minfo->nvars, slong); offsets = shifts + ctx->minfo->nvars; for (j = 0; j < ctx->minfo->nvars; j++) mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, ctx->minfo); k = 0; for (i = 0; i < L->length; i++) { fmpz_mod_berlekamp_massey_reduce(L->coeffs + i, fpctx); marks[i] = k; k += fmpz_mod_poly_degree(L->coeffs[i].V1, fpctx); } marks[L->length] = k; fmpz_mpoly_fit_length(A, k, ctx); A->length = k; for (i = 0; i < L->length; i++) { ulong e0 = extract_exp(L->exps[i], 1, 2); ulong e1 = extract_exp(L->exps[i], 0, 2); success = _fmpz_mod_bma_get_fmpz_mpoly2(A->coeffs + marks[i], A->exps + N*marks[i], A->bits, e0, e1, ctx->minfo, shifts, offsets, alphashift, L->coeffs + i, Ictx, fpctx); if (!success) goto cleanup; } fmpz_mpoly_sort_terms(A, ctx); success = 1; cleanup: TMP_END; return success; } void fmpz_mod_bma_mpoly_init(fmpz_mod_bma_mpoly_t A) { A->length = 0; A->alloc = 0; A->exps = NULL; A->coeffs = NULL; A->pointcount = 0; } void fmpz_mod_bma_mpoly_clear( fmpz_mod_bma_mpoly_t A, const fmpz_mod_ctx_t fpctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mod_berlekamp_massey_clear(A->coeffs + i, fpctx); flint_free(A->exps); flint_free(A->coeffs); } void fmpz_mod_bma_mpoly_fit_length( fmpz_mod_bma_mpoly_t A, slong length, const fmpz_mod_ctx_t fpctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, A->alloc + A->alloc/2); if (length > old_alloc) { A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, ulong); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fmpz_mod_berlekamp_massey_struct); for (i = old_alloc; i < new_alloc; i++) fmpz_mod_berlekamp_massey_init(A->coeffs + i, fpctx); A->alloc = new_alloc; } } void fmpz_mod_bma_mpoly_zero(fmpz_mod_bma_mpoly_t L) { L->length = 0; L->pointcount = 0; } int fmpz_mod_bma_mpoly_reduce(fmpz_mod_bma_mpoly_t L, const fmpz_mod_ctx_t fpctx) { slong i; int changed; changed = 0; for (i = 0; i < L->length; i++) { FLINT_ASSERT(L->pointcount == fmpz_mod_berlekamp_massey_point_count(L->coeffs + i)); changed |= fmpz_mod_berlekamp_massey_reduce(L->coeffs + i, fpctx); } return changed; } static void fmpz_mod_bma_mpoly_add_point( fmpz_mod_bma_mpoly_t L, const fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx_mp) { slong j; slong Alen = A->length; fmpz_mod_poly_struct * Acoeff = A->coeffs; slong Li, Ai, ai; ulong Aexp; fmpz_mod_berlekamp_massey_struct * Lcoeff; slong Llen; ulong * Lexp; if (L->length == 0) { slong tot = 0; for (Ai = 0; Ai < Alen; Ai++) for (ai = Acoeff[Ai].length - 1; ai >= 0; ai--) tot += !fmpz_is_zero(Acoeff[Ai].coeffs + ai); fmpz_mod_bma_mpoly_fit_length(L, tot, ctx_mp); } Lcoeff = L->coeffs; Llen = L->length; Lexp = L->exps; Li = 0; Ai = ai = 0; Aexp = 0; if (Ai < Alen) { ai = fmpz_mod_poly_degree(A->coeffs + Ai, ctx_mp); Aexp = pack_exp2(A->exps[Ai], ai); } while (Li < Llen || Ai < Alen) { if (Li < Llen && Ai < Alen && Lexp[Li] == Aexp) { /* L term present, A term present */ add_same_exp: fmpz_mod_berlekamp_massey_add_point(Lcoeff + Li, Acoeff[Ai].coeffs + ai, ctx_mp); Li++; do { ai--; } while (ai >= 0 && fmpz_is_zero(Acoeff[Ai].coeffs + ai)); if (ai < 0) { Ai++; if (Ai < Alen) { ai = fmpz_mod_poly_degree(A->coeffs + Ai, ctx_mp); Aexp = pack_exp2(A->exps[Ai], ai); } } else { FLINT_ASSERT(Ai < Alen); Aexp = pack_exp2(A->exps[Ai], ai); } } else if (Li < Llen && (Ai >= Alen || Lexp[Li] > Aexp)) { /* L term present, A term missing */ fmpz_mod_berlekamp_massey_add_zeros(Lcoeff + Li, 1, ctx_mp); Li++; } else { /* L term missing, A term present */ FLINT_ASSERT(Ai < Alen && (Li >= Llen || Lexp[Li] < Aexp)); { ulong texp; fmpz_mod_berlekamp_massey_struct tcoeff; fmpz_mod_bma_mpoly_fit_length(L, Llen + 1, ctx_mp); Lcoeff = L->coeffs; Lexp = L->exps; texp = Lexp[Llen]; tcoeff = Lcoeff[Llen]; for (j = Llen - 1; j >= Li; j--) { Lexp[j + 1] = Lexp[j]; Lcoeff[j + 1] = Lcoeff[j]; } Lexp[Li] = texp; Lcoeff[Li] = tcoeff; } fmpz_mod_berlekamp_massey_start_over(Lcoeff + Li, ctx_mp); fmpz_mod_berlekamp_massey_add_zeros(Lcoeff + Li, L->pointcount, ctx_mp); Lexp[Li] = Aexp; Llen++; L->length = Llen; goto add_same_exp; } } L->pointcount++; } /* A is in ZZ[x_0, ..., x_(n-1)] After the substitutions x_0 = x ^ (sub[1] * sub[2] * ... * sub[n-1]) x_(n-2) = x ^ (sub[n-1]) x_(n-1) = x ^ (1) a univariate in ZZ[x] remains. Return the content of this poly. */ void _fmpz_mpoly_ksub_content( fmpz_t content, const fmpz * Acoeffs, const ulong * Aexps, slong Alength, flint_bitcnt_t Abits, const ulong * subdegs, const mpoly_ctx_t mctx) { slong i, j; slong nvars = mctx->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * offsets, * shifts; fmpz_mpoly_t T; fmpz_mpoly_ctx_t Tctx; fmpz_t e; TMP_INIT; TMP_START; fmpz_init(e); fmpz_mpoly_ctx_init(Tctx, 1, ORD_LEX); fmpz_mpoly_init(T, Tctx); offsets = TMP_ALLOC(2*nvars*sizeof(slong)); shifts = offsets + nvars; for (j = 2; j < nvars; j++) mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, Abits, mctx); for (i = 0; i < Alength; i++) { fmpz_zero(e); for (j = 2; j < mctx->nvars; j++) { fmpz_mul_ui(e, e, subdegs[j]); fmpz_add_ui(e, e, ((Aexps + N*i)[offsets[j]]>>shifts[j])&mask); } _fmpz_mpoly_push_exp_ffmpz(T, e, Tctx); fmpz_set(T->coeffs + T->length - 1, Acoeffs + i); } fmpz_mpoly_sort_terms(T, Tctx); fmpz_mpoly_combine_like_terms(T, Tctx); _fmpz_vec_content(content, T->coeffs, T->length); fmpz_mpoly_clear(T, Tctx); fmpz_mpoly_ctx_clear(Tctx); fmpz_clear(e); TMP_END; } /* return 1: good (or at least not bad) 0: no match -1: better degree bound is in GevaldegXY */ int static _random_check_sp( ulong * GevaldegXY, ulong GdegboundXY, int which_check, n_polyun_t Aeval_sp, n_polyun_t Acur_sp, n_polyun_t Ainc_sp, n_polyun_t Acoeff_sp, n_polyun_t Beval_sp, n_polyun_t Bcur_sp, n_polyun_t Binc_sp, n_polyun_t Bcoeff_sp, n_polyun_t Geval_sp, n_polyun_t Abareval_sp, n_polyun_t Bbareval_sp, mp_limb_t * alphas_sp, n_poly_struct * alpha_caches_sp, const fmpz_mpoly_t H, n_poly_t Hmarks, const fmpz_mpoly_t A, n_poly_t Amarks, ulong Abidegree, const fmpz_mpoly_t B, n_poly_t Bmarks, ulong Bbidegree, const fmpz_mpoly_t Gamma, const fmpz_mpoly_ctx_t ctx, nmod_t ctx_sp, flint_rand_t randstate, n_poly_polyun_stack_t St_sp) { mp_limb_t Gammaeval_sp; int success; int point_try_count; slong i; for (point_try_count = 0; point_try_count < 10; point_try_count++) { alphas_sp[0] = alphas_sp[1] = 0; for (i = 2; i < ctx->minfo->nvars; i++) { alphas_sp[i] = n_urandint(randstate, ctx_sp.n - 1) + 1; nmod_pow_cache_start(alphas_sp[i], alpha_caches_sp + 3*i, alpha_caches_sp + 3*i + 1, alpha_caches_sp + 3*i + 2); } fmpz_mpoly2_eval_nmod(Aeval_sp, Acur_sp, Ainc_sp, Acoeff_sp, A, Amarks->coeffs, Amarks->length, alpha_caches_sp, ctx, ctx_sp); fmpz_mpoly2_eval_nmod(Beval_sp, Bcur_sp, Binc_sp, Bcoeff_sp, B, Bmarks->coeffs, Bmarks->length, alpha_caches_sp, ctx, ctx_sp); if (Aeval_sp->length < 1 || Beval_sp->length < 1 || n_polyu1n_bidegree(Aeval_sp) != Abidegree || n_polyu1n_bidegree(Beval_sp) != Bbidegree) { continue; } Gammaeval_sp = fmpz_mpoly_evaluate_all_nmod(Gamma, alphas_sp, ctx, ctx_sp); FLINT_ASSERT(Gammaeval_sp != 0); success = n_polyu1n_mod_gcd_brown_smprime(Geval_sp, Abareval_sp, Bbareval_sp, Aeval_sp, Beval_sp, ctx_sp, St_sp); if (success) continue; _n_poly_vec_mul_nmod_intertible(Geval_sp->coeffs, Geval_sp->length, Gammaeval_sp, ctx_sp); FLINT_ASSERT(Geval_sp->length > 0); *GevaldegXY = n_polyu1n_bidegree(Geval_sp); if (GdegboundXY < *GevaldegXY) continue; else if (GdegboundXY > *GevaldegXY) return -1; if (which_check == 0) { fmpz_mpoly2_eval_nmod(Bbareval_sp, Bcur_sp, Binc_sp, Bcoeff_sp, H, Hmarks->coeffs, Hmarks->length, alpha_caches_sp, ctx, ctx_sp); return n_polyun_equal(Bbareval_sp, Geval_sp); } else { fmpz_mpoly2_eval_nmod(Geval_sp, Bcur_sp, Binc_sp, Bcoeff_sp, H, Hmarks->coeffs, Hmarks->length, alpha_caches_sp, ctx, ctx_sp); return n_polyun_equal(Geval_sp, which_check == 1 ? Abareval_sp : Bbareval_sp); } } return 1; /* Hmm */ } int static _random_check_mp( ulong * GevaldegXY, ulong GdegboundXY, int which_check, fmpz_mod_polyun_t Aeval_mp, fmpz_mod_polyun_t Acur_mp, fmpz_mod_polyun_t Ainc_mp, fmpz_mod_polyun_t Acoeff_mp, fmpz_mod_polyun_t Beval_mp, fmpz_mod_polyun_t Bcur_mp, fmpz_mod_polyun_t Binc_mp, fmpz_mod_polyun_t Bcoeff_mp, fmpz_mod_polyun_t Geval_mp, fmpz_mod_polyun_t Abareval_mp, fmpz_mod_polyun_t Bbareval_mp, fmpz_t Gammaeval_mp, fmpz * alphas_mp, fmpz_mod_poly_struct * alpha_caches_mp, const fmpz_mpoly_t H, n_poly_t Hmarks, const fmpz_mpoly_t A, n_poly_t Amarks, ulong Abidegree, const fmpz_mpoly_t B, n_poly_t Bmarks, ulong Bbidegree, const fmpz_mpoly_t Gamma, const fmpz_mpoly_ctx_t ctx, const fmpz_mod_ctx_t ctx_mp, flint_rand_t randstate, fmpz_mod_poly_polyun_stack_t St_mp) { int success; int point_try_count; slong i; /* try to test H at a random evaluation point */ for (point_try_count = 0; point_try_count < 10; point_try_count++) { for (i = 2; i < ctx->minfo->nvars; i++) { fmpz_randm(alphas_mp + i, randstate, fmpz_mod_ctx_modulus(ctx_mp)); fmpz_mod_pow_cache_start(alphas_mp + i, alpha_caches_mp + i, ctx_mp); } fmpz_mpoly2_eval_fmpz_mod(Aeval_mp, Acur_mp, Ainc_mp, Acoeff_mp, A, Amarks->coeffs, Amarks->length, alpha_caches_mp, ctx, ctx_mp); fmpz_mpoly2_eval_fmpz_mod(Beval_mp, Bcur_mp, Binc_mp, Bcoeff_mp, B, Bmarks->coeffs, Bmarks->length, alpha_caches_mp, ctx, ctx_mp); if (Aeval_mp->length < 1 || Beval_mp->length < 1 || fmpz_mod_polyu1n_bidegree(Aeval_mp) != Abidegree || fmpz_mod_polyu1n_bidegree(Beval_mp) != Bbidegree) { continue; } fmpz_mpoly_evaluate_all_fmpz_mod(Gammaeval_mp, Gamma, alphas_mp, ctx, ctx_mp); FLINT_ASSERT(!fmpz_is_zero(Gammaeval_mp)); success = fmpz_mod_polyu1n_gcd_brown_smprime(Geval_mp, Abareval_mp, Bbareval_mp, Aeval_mp, Beval_mp, ctx_mp, St_mp->poly_stack, St_mp->polyun_stack); if (!success) continue; _fmpz_mod_poly_vec_mul_fmpz_mod(Geval_mp->coeffs, Geval_mp->length, Gammaeval_mp, ctx_mp); FLINT_ASSERT(Geval_mp->length > 0); *GevaldegXY = fmpz_mod_polyu1n_bidegree(Geval_mp); if (GdegboundXY < *GevaldegXY) { continue; } else if (GdegboundXY > *GevaldegXY) { return -1; } if (which_check == 0) { fmpz_mpoly2_eval_fmpz_mod(Bbareval_mp, Bcur_mp, Binc_mp, Bcoeff_mp, H, Hmarks->coeffs, Hmarks->length, alpha_caches_mp, ctx, ctx_mp); return fmpz_mod_polyun_equal(Bbareval_mp, Geval_mp, ctx_mp); } else { fmpz_mpoly2_eval_fmpz_mod(Geval_mp, Bcur_mp, Binc_mp, Bcoeff_mp, H, Hmarks->coeffs, Hmarks->length, alpha_caches_mp, ctx, ctx_mp); return fmpz_mod_polyun_equal(Geval_mp, which_check == 1 ? Abareval_mp : Bbareval_mp, ctx_mp); } } return 1; /* Hmm */ } /* return -1: singular 0: inconsistent 1: success */ static int zip_solve( mp_limb_t * Acoeffs, n_polyun_t Z, n_polyun_t H, n_polyun_t M, const nmod_t fpctx) { int success; slong Ai, i, n; n_poly_t t; n_poly_init(t); FLINT_ASSERT(Z->length == H->length); FLINT_ASSERT(Z->length == M->length); Ai = 0; for (i = 0; i < H->length; i++) { n = H->coeffs[i].length; FLINT_ASSERT(M->coeffs[i].length == n + 1); FLINT_ASSERT(Z->coeffs[i].length >= n); n_poly_fit_length(t, n); success = _nmod_zip_vand_solve(Acoeffs + Ai, H->coeffs[i].coeffs, n, Z->coeffs[i].coeffs, Z->coeffs[i].length, M->coeffs[i].coeffs, t->coeffs, fpctx); if (success < 1) { n_poly_clear(t); return success; } Ai += n; } n_poly_clear(t); return 1; } int _fmpz_vec_crt_nmod( flint_bitcnt_t * maxbits_, fmpz * a, fmpz_t am, mp_limb_t * b, slong len, nmod_t mod) { int changed = 0; flint_bitcnt_t bits, maxbits = 0; slong i; fmpz_t t; fmpz_init(t); for (i = 0; i < len; i++) { fmpz_CRT_ui(t, a + i, am, b[i], mod.n, 1); changed |= !fmpz_equal(t, a + i); bits = fmpz_bits(t); maxbits = FLINT_MAX(maxbits, bits); fmpz_swap(a + i, t); } fmpz_clear(t); *maxbits_ = maxbits; return changed; } int fmpz_mpolyl_gcd_zippel2( fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t Gamma, const fmpz_mpoly_ctx_t ctx) { int which_check, changed, success, point_try_count; slong nvars = ctx->minfo->nvars; flint_bitcnt_t bits = A->bits; mpoly_bma_interpolate_ctx_t Ictx; n_poly_t Amarks, Bmarks, Hmarks; flint_bitcnt_t Hbitbound = UWORD_MAX; flint_bitcnt_t Hbits; /* coeff size */ fmpz_mpoly_t H; fmpz_mpoly_t Hcontent; fmpz_t p, pm1; /* multi precision workspace */ fmpz_mod_ctx_t ctx_mp; fmpz_mod_poly_polyun_stack_t St_mp; fmpz_mod_bma_mpoly_t GLambda_mp, AbarLambda_mp, BbarLambda_mp; fmpz_mod_polyun_t Aeval_mp, Beval_mp, Geval_mp, Abareval_mp, Bbareval_mp; fmpz_mod_poly_t Gammacur_mp, Gammainc_mp, Gammacoeff_mp; fmpz_mod_polyun_t Acur_mp, Ainc_mp, Acoeff_mp; fmpz_mod_polyun_t Bcur_mp, Binc_mp, Bcoeff_mp; fmpz_t sshift_mp, last_unlucky_sshift_plus_1_mp, image_count_mp; fmpz_t Gammaeval_mp; fmpz * alphas_mp; fmpz_mod_poly_struct * alpha_caches_mp; /* single precision workspace */ nmod_t ctx_sp; n_poly_polyun_stack_t St_sp; nmod_bma_mpoly_t GLambda_sp, AbarLambda_sp, BbarLambda_sp; n_polyun_t Aeval_sp, Beval_sp, Geval_sp, Abareval_sp, Bbareval_sp; n_poly_t Gammacur_sp, Gammainc_sp, Gammacoeff_sp; n_polyun_t Acur_sp, Ainc_sp, Acoeff_sp; n_polyun_t Bcur_sp, Binc_sp, Bcoeff_sp; mp_limb_t p_sp, sshift_sp, last_unlucky_sshift_plus_1_sp, image_count_sp; mp_limb_t Gammaeval_sp; mp_limb_t * alphas_sp; n_poly_struct * alpha_caches_sp; /* misc */ n_polyun_t HH, MH, ZH; n_poly_t Hn; slong i, j; ulong GdegboundXY, GevaldegXY; slong * Adegs, * Bdegs; flint_rand_t randstate; fmpz_t subprod, cAksub, cBksub; int unlucky_count; fmpz_t Hmodulus; slong cur_zip_image, req_zip_images; ulong ABtotal_length; ulong Abidegree, Bbidegree; FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == G->bits); FLINT_ASSERT(bits == Abar->bits); FLINT_ASSERT(bits == Bbar->bits); FLINT_ASSERT(bits == Gamma->bits); /* let's initialize everything at once to avoid complicated cleanup */ Abidegree = _mpoly_bidegree(A->exps, bits, ctx->minfo); Bbidegree = _mpoly_bidegree(B->exps, bits, ctx->minfo); ABtotal_length = FLINT_MAX(A->length + B->length, 100); n_poly_init(Amarks); n_poly_init(Bmarks); n_poly_init(Hmarks); mpoly2_fill_marks(&Amarks->coeffs, &Amarks->length, &Amarks->alloc, A->exps, A->length, bits, ctx->minfo); mpoly2_fill_marks(&Bmarks->coeffs, &Bmarks->length, &Bmarks->alloc, B->exps, B->length, bits, ctx->minfo); flint_randinit(randstate); fmpz_init(p); fmpz_init(pm1); /* p - 1 */ fmpz_init(subprod); fmpz_init(cAksub); fmpz_init(cBksub); fmpz_init(Hmodulus); fmpz_mpoly_init3(H, 0, bits, ctx); fmpz_mpoly_init3(Hcontent, 0, bits, ctx); mpoly_bma_interpolate_ctx_init(Ictx, ctx->minfo->nvars); /* multiprecision workspace */ fmpz_init(image_count_mp); fmpz_init(sshift_mp); fmpz_init(last_unlucky_sshift_plus_1_mp); fmpz_set_ui(p, 2); /* something positive */ fmpz_mod_ctx_init_ui(ctx_mp, 2); /* modulus no care */ fmpz_mod_poly_stack_init(St_mp->poly_stack); fmpz_mod_polyun_stack_init(St_mp->polyun_stack); fmpz_mod_bma_mpoly_init(GLambda_mp); fmpz_mod_bma_mpoly_init(AbarLambda_mp); fmpz_mod_bma_mpoly_init(BbarLambda_mp); fmpz_init(Gammaeval_mp); fmpz_mod_polyun_init(Aeval_mp, ctx_mp); fmpz_mod_polyun_init(Beval_mp, ctx_mp); fmpz_mod_polyun_init(Geval_mp, ctx_mp); fmpz_mod_polyun_init(Abareval_mp, ctx_mp); fmpz_mod_polyun_init(Bbareval_mp, ctx_mp); fmpz_mod_poly_init(Gammacur_mp, ctx_mp); fmpz_mod_poly_init(Gammainc_mp, ctx_mp); fmpz_mod_poly_init(Gammacoeff_mp, ctx_mp); fmpz_mod_polyun_init(Acur_mp, ctx_mp); fmpz_mod_polyun_init(Ainc_mp, ctx_mp); fmpz_mod_polyun_init(Acoeff_mp, ctx_mp); fmpz_mod_polyun_init(Bcur_mp, ctx_mp); fmpz_mod_polyun_init(Binc_mp, ctx_mp); fmpz_mod_polyun_init(Bcoeff_mp, ctx_mp); alphas_mp = _fmpz_vec_init(nvars); alpha_caches_mp = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_poly_struct); for (i = 0; i < nvars; i++) fmpz_mod_poly_init(alpha_caches_mp + i, ctx_mp); /* machine precision workspace "sp" */ nmod_init(&ctx_sp, 2); /* modulus no care */ n_poly_stack_init(St_sp->poly_stack); n_polyun_stack_init(St_sp->polyun_stack); nmod_bma_mpoly_init(GLambda_sp); nmod_bma_mpoly_init(AbarLambda_sp); nmod_bma_mpoly_init(BbarLambda_sp); n_polyun_init(Aeval_sp); n_polyun_init(Beval_sp); n_polyun_init(Geval_sp); n_polyun_init(Abareval_sp); n_polyun_init(Bbareval_sp); n_poly_init(Gammacur_sp); n_poly_init(Gammainc_sp); n_poly_init(Gammacoeff_sp); n_polyun_init(Acur_sp); n_polyun_init(Ainc_sp); n_polyun_init(Acoeff_sp); n_polyun_init(Bcur_sp); n_polyun_init(Binc_sp); n_polyun_init(Bcoeff_sp); alphas_sp = FLINT_ARRAY_ALLOC(nvars, mp_limb_t); alpha_caches_sp = FLINT_ARRAY_ALLOC(3*nvars, n_poly_struct); for (i = 0; i < 3*nvars; i++) n_poly_init(alpha_caches_sp + i); n_polyun_init(HH); n_polyun_init(MH); n_polyun_init(ZH); n_poly_init(Hn); Adegs = FLINT_ARRAY_ALLOC(2*nvars, slong); Bdegs = Adegs + nvars; fmpz_mpoly_degrees_si(Adegs, A, ctx); fmpz_mpoly_degrees_si(Bdegs, B, ctx); GdegboundXY = FLINT_MIN(A->exps[0], B->exps[0]); p_sp = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); for (point_try_count = 0; point_try_count < 10; point_try_count++) { p_sp = n_nextprime(p_sp, 1); nmod_init(&ctx_sp, p_sp); for (i = 2; i < ctx->minfo->nvars; i++) { alphas_sp[i] = n_urandint(randstate, p_sp - 1) + 1; nmod_pow_cache_start(alphas_sp[i], alpha_caches_sp + 3*i, alpha_caches_sp + 3*i + 1, alpha_caches_sp + 3*i + 2); } fmpz_mpoly2_eval_nmod(Aeval_sp, Acur_sp, Ainc_sp, Acoeff_sp, A, Amarks->coeffs, Amarks->length, alpha_caches_sp, ctx, ctx_sp); fmpz_mpoly2_eval_nmod(Beval_sp, Bcur_sp, Binc_sp, Bcoeff_sp, B, Bmarks->coeffs, Bmarks->length, alpha_caches_sp, ctx, ctx_sp); if (Aeval_sp->length < 1 || Beval_sp->length < 1 || n_polyu1n_bidegree(Aeval_sp) != Abidegree || n_polyu1n_bidegree(Beval_sp) != Bbidegree) { continue; } success = n_polyu1n_mod_gcd_brown_smprime(Geval_sp, Abareval_sp, Bbareval_sp, Aeval_sp, Beval_sp, ctx_sp, St_sp); if (success) { FLINT_ASSERT(Geval_sp->length > 0); GdegboundXY = n_polyu1n_bidegree(Geval_sp); break; } } Ictx->degbounds[0] = 0; Ictx->degbounds[1] = 0; for (i = 2; i < nvars; i++) { Ictx->degbounds[i] = FLINT_MAX(Adegs[i], Bdegs[i]); Ictx->subdegs[i] = Ictx->degbounds[i]; /* will increment */ } /* initialization done! */ if (GdegboundXY == 0) goto gcd_is_trivial; pick_ksub: fmpz_one(subprod); for (i = 2; i < nvars; i++) { if (n_add_checked(&Ictx->subdegs[i], Ictx->subdegs[i], 1)) { success = 0; goto cleanup; } fmpz_mul_ui(subprod, subprod, Ictx->subdegs[i]); } _fmpz_mpoly_ksub_content(cAksub, A->coeffs, A->exps, Amarks->coeffs[1], bits, Ictx->subdegs, ctx->minfo); _fmpz_mpoly_ksub_content(cBksub, B->coeffs, B->exps, Bmarks->coeffs[1], bits, Ictx->subdegs, ctx->minfo); if (fmpz_is_zero(cAksub) || fmpz_is_zero(cBksub)) { goto pick_ksub; } pick_bma_prime: if (fmpz_cmp_ui(p, ABtotal_length) < 0) fmpz_set_ui(p, ABtotal_length); if (fmpz_cmp(p, subprod) < 0) fmpz_set(p, subprod); success = fmpz_next_smooth_prime(p, p); fmpz_sub_ui(pm1, p, 1); if (!success) { success = 0; goto cleanup; } if (fmpz_divisible(cAksub, p) || fmpz_divisible(cBksub, p)) { goto pick_bma_prime; } for (i = 0; i < Gamma->length; i++) if (fmpz_divisible(Gamma->coeffs + i, p)) goto pick_bma_prime; if (fmpz_abs_fits_ui(p)) { p_sp = fmpz_get_ui(p); sshift_sp = 1; unlucky_count = 0; last_unlucky_sshift_plus_1_sp = 0; nmod_init(&ctx_sp, p_sp); nmod_discrete_log_pohlig_hellman_precompute_prime(Ictx->dlogenv_sp, p_sp); nmod_bma_mpoly_reset_prime(GLambda_sp, ctx_sp); nmod_bma_mpoly_reset_prime(AbarLambda_sp, ctx_sp); nmod_bma_mpoly_reset_prime(BbarLambda_sp, ctx_sp); nmod_bma_mpoly_zero(GLambda_sp); nmod_bma_mpoly_zero(AbarLambda_sp); nmod_bma_mpoly_zero(BbarLambda_sp); FLINT_ASSERT(sshift_sp == 1); nmod_mpoly_bma_interpolate_alpha_powers(alphas_sp, sshift_sp, 2, Ictx, ctx, ctx_sp); for (j = 2; j < nvars; j++) nmod_pow_cache_start(alphas_sp[j], alpha_caches_sp + 3*j + 0, alpha_caches_sp + 3*j + 1, alpha_caches_sp + 3*j + 2); mpoly2_nmod_monomial_evals(Ainc_sp, A->exps, bits, Amarks->coeffs, Amarks->length, alpha_caches_sp, ctx->minfo, ctx_sp); mpoly2_nmod_monomial_evals(Binc_sp, B->exps, bits, Bmarks->coeffs, Bmarks->length, alpha_caches_sp, ctx->minfo, ctx_sp); mpoly_nmod_monomial_evals(Gammainc_sp, Gamma->exps, Gamma->length, bits, alpha_caches_sp + 3*2, 2, nvars, ctx->minfo, ctx_sp); fmpz_mpoly2_nmod_coeffs(Acoeff_sp, A->coeffs, Amarks->coeffs, Amarks->length, ctx_sp); fmpz_mpoly2_nmod_coeffs(Bcoeff_sp, B->coeffs, Bmarks->coeffs, Bmarks->length, ctx_sp); fmpz_mpoly_nmod_coeffs(Gammacoeff_sp, Gamma->coeffs, Gamma->length, ctx_sp); n_polyun_set(Acur_sp, Ainc_sp); n_polyun_set(Bcur_sp, Binc_sp); n_poly_set(Gammacur_sp, Gammainc_sp); image_count_sp = 0; next_bma_image_sp: /* image count is also the current power of alpha we are evaluating */ image_count_sp++; FLINT_ASSERT(GLambda_sp->pointcount == AbarLambda_sp->pointcount); FLINT_ASSERT(GLambda_sp->pointcount == BbarLambda_sp->pointcount); FLINT_ASSERT(sshift_sp + GLambda_sp->pointcount == image_count_sp); if (image_count_sp >= p_sp - 1) goto pick_bma_prime; n_polyun_mod_zip_eval_cur_inc_coeff(Aeval_sp, Acur_sp, Ainc_sp, Acoeff_sp, ctx_sp); n_polyun_mod_zip_eval_cur_inc_coeff(Beval_sp, Bcur_sp, Binc_sp, Bcoeff_sp, ctx_sp); Gammaeval_sp = n_poly_mod_zip_eval_cur_inc_coeff(Gammacur_sp, Gammainc_sp, Gammacoeff_sp, ctx_sp); if (Aeval_sp->length < 1 || Beval_sp->length < 1 || n_polyu1n_bidegree(Aeval_sp) != Abidegree || n_polyu1n_bidegree(Beval_sp) != Bbidegree) { sshift_sp += GLambda_sp->pointcount + 1; nmod_bma_mpoly_zero(GLambda_sp); nmod_bma_mpoly_zero(AbarLambda_sp); nmod_bma_mpoly_zero(BbarLambda_sp); goto next_bma_image_sp; } /* the evaluation killed neither lc(A) nor lc(B) */ FLINT_ASSERT(Gammaeval_sp != 0); success = n_polyu1n_mod_gcd_brown_smprime(Geval_sp, Abareval_sp, Bbareval_sp, Aeval_sp, Beval_sp, ctx_sp, St_sp); if (!success) { sshift_sp += GLambda_sp->pointcount + 1; nmod_bma_mpoly_zero(GLambda_sp); nmod_bma_mpoly_zero(AbarLambda_sp); nmod_bma_mpoly_zero(BbarLambda_sp); goto next_bma_image_sp; } FLINT_ASSERT(Geval_sp->length > 0); GevaldegXY = n_polyu1n_bidegree(Geval_sp); _n_poly_vec_mul_nmod_intertible(Geval_sp->coeffs, Geval_sp->length, Gammaeval_sp, ctx_sp); if (GdegboundXY < GevaldegXY) { if (sshift_sp == last_unlucky_sshift_plus_1_sp) goto pick_ksub; if (++unlucky_count > 2) goto pick_bma_prime; last_unlucky_sshift_plus_1_sp = sshift_sp + 1; sshift_sp += GLambda_sp->pointcount + 1; nmod_bma_mpoly_zero(GLambda_sp); nmod_bma_mpoly_zero(AbarLambda_sp); nmod_bma_mpoly_zero(BbarLambda_sp); goto next_bma_image_sp; } else if (GdegboundXY > GevaldegXY) { /* new bound on deg_XY(G) */ GdegboundXY = GevaldegXY; if (GdegboundXY == 0) goto gcd_is_trivial; sshift_sp += GLambda_sp->pointcount; nmod_bma_mpoly_zero(GLambda_sp); nmod_bma_mpoly_zero(AbarLambda_sp); nmod_bma_mpoly_zero(BbarLambda_sp); nmod_bma_mpoly_add_point(GLambda_sp, Geval_sp, ctx_sp); nmod_bma_mpoly_add_point(AbarLambda_sp, Abareval_sp, ctx_sp); nmod_bma_mpoly_add_point(BbarLambda_sp, Bbareval_sp, ctx_sp); goto next_bma_image_sp; } nmod_bma_mpoly_add_point(GLambda_sp, Geval_sp, ctx_sp); nmod_bma_mpoly_add_point(AbarLambda_sp, Abareval_sp, ctx_sp); nmod_bma_mpoly_add_point(BbarLambda_sp, Bbareval_sp, ctx_sp); if ((GLambda_sp->pointcount & 7) != 0) { goto next_bma_image_sp; } if (GLambda_sp->pointcount/2 >= Gamma->length && !nmod_bma_mpoly_reduce(GLambda_sp) && nmod_bma_mpoly_get_fmpz_mpoly2(H, Hmarks, ctx, sshift_sp, GLambda_sp, Ictx, ctx_sp) && Hmarks->coeffs[1] == Gamma->length) { which_check = 0; goto check_sp; } if (AbarLambda_sp->pointcount/2 >= Amarks->coeffs[1] && !nmod_bma_mpoly_reduce(AbarLambda_sp) && nmod_bma_mpoly_get_fmpz_mpoly2(H, Hmarks, ctx, sshift_sp, AbarLambda_sp, Ictx, ctx_sp) && Hmarks->coeffs[1] == Amarks->coeffs[1]) { which_check = 1; goto check_sp; } if (BbarLambda_sp->pointcount/2 >= Bmarks->coeffs[1] && !nmod_bma_mpoly_reduce(BbarLambda_sp) && nmod_bma_mpoly_get_fmpz_mpoly2(H, Hmarks, ctx, sshift_sp, BbarLambda_sp, Ictx, ctx_sp) && Hmarks->coeffs[1] == Bmarks->coeffs[1]) { which_check = 2; goto check_sp; } if (GLambda_sp->pointcount/2 > ABtotal_length) { success = 0; goto cleanup; } goto next_bma_image_sp; check_sp: FLINT_ASSERT(0 <= which_check && which_check <= 2); FLINT_ASSERT(which_check != 0 || GdegboundXY == _mpoly_bidegree(H->exps, bits, ctx->minfo)); success = _random_check_sp( &GevaldegXY, GdegboundXY, which_check, Aeval_sp, Acur_sp, Ainc_sp, Acoeff_sp, Beval_sp, Bcur_sp, Binc_sp, Bcoeff_sp, Geval_sp, Abareval_sp, Bbareval_sp, alphas_sp, alpha_caches_sp, H, Hmarks, A, Amarks, Abidegree, B, Bmarks, Bbidegree, Gamma, ctx, ctx_sp, randstate, St_sp); if (success < 1) { if (success == 0) goto next_bma_image_sp; FLINT_ASSERT(GdegboundXY > GevaldegXY); GdegboundXY = GevaldegXY; if (GdegboundXY == 0) goto gcd_is_trivial; sshift_sp += GLambda_sp->pointcount; nmod_bma_mpoly_zero(GLambda_sp); nmod_bma_mpoly_zero(AbarLambda_sp); nmod_bma_mpoly_zero(BbarLambda_sp); goto next_bma_image_sp; } } else { fmpz_one(sshift_mp); unlucky_count = 0; fmpz_zero(last_unlucky_sshift_plus_1_mp); fmpz_mod_ctx_set_modulus(ctx_mp, p); fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(Ictx->dlogenv, p); fmpz_mod_bma_mpoly_zero(GLambda_mp); fmpz_mod_bma_mpoly_zero(AbarLambda_mp); fmpz_mod_bma_mpoly_zero(BbarLambda_mp); FLINT_ASSERT(fmpz_is_one(sshift_mp)); fmpz_mod_mpoly_bma_interpolate_alpha_powers(alphas_mp, sshift_mp, 2, Ictx, ctx, ctx_mp); for (j = 2; j < nvars; j++) fmpz_mod_pow_cache_start(alphas_mp + j, alpha_caches_mp + j, ctx_mp); mpoly2_monomial_evals_fmpz_mod(Ainc_mp, A->exps, bits, Amarks->coeffs, Amarks->length, alpha_caches_mp + 2, nvars, ctx->minfo, ctx_mp); mpoly2_monomial_evals_fmpz_mod(Binc_mp, B->exps, bits, Bmarks->coeffs, Bmarks->length, alpha_caches_mp + 2, nvars, ctx->minfo, ctx_mp); mpoly_monomial_evals_fmpz_mod(Gammainc_mp, Gamma->exps, Gamma->length, bits, alpha_caches_mp + 2, 2, nvars, ctx->minfo, ctx_mp); fmpz_mpoly2_fmpz_mod_coeffs(Acoeff_mp, A->coeffs, Amarks->coeffs, Amarks->length, ctx_mp); fmpz_mpoly2_fmpz_mod_coeffs(Bcoeff_mp, B->coeffs, Bmarks->coeffs, Bmarks->length, ctx_mp); fmpz_mpoly_fmpz_mod_coeffs(Gammacoeff_mp, Gamma->coeffs, Gamma->length, ctx_mp); fmpz_mod_polyun_set(Acur_mp, Ainc_mp, ctx_mp); fmpz_mod_polyun_set(Bcur_mp, Binc_mp, ctx_mp); fmpz_mod_poly_set(Gammacur_mp, Gammainc_mp, ctx_mp); fmpz_zero(image_count_mp); next_bma_image_mp: /* image count is also the current power of alpha we are evaluating */ fmpz_add_ui(image_count_mp, image_count_mp, 1); FLINT_ASSERT(GLambda_sp->pointcount == AbarLambda_sp->pointcount); FLINT_ASSERT(GLambda_sp->pointcount == BbarLambda_sp->pointcount); #if FLINT_WANT_ASSERT { fmpz_t t; fmpz_init(t); fmpz_add_ui(t, sshift_mp, GLambda_mp->pointcount); FLINT_ASSERT(fmpz_equal(t, image_count_mp)); fmpz_clear(t); } #endif if (fmpz_cmp(image_count_mp, pm1) >= 0) goto pick_bma_prime; fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(Aeval_mp, Acur_mp, Ainc_mp, Acoeff_mp, ctx_mp); fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(Beval_mp, Bcur_mp, Binc_mp, Bcoeff_mp, ctx_mp); fmpz_mod_poly_zip_eval_cur_inc_coeff(Gammaeval_mp, Gammacur_mp, Gammainc_mp, Gammacoeff_mp, ctx_mp); if (Aeval_mp->length < 1 || Beval_mp->length < 1 || fmpz_mod_polyu1n_bidegree(Aeval_mp) != Abidegree || fmpz_mod_polyu1n_bidegree(Beval_mp) != Bbidegree) { fmpz_add_ui(sshift_mp, sshift_mp, GLambda_mp->pointcount + 1); fmpz_mod_bma_mpoly_zero(GLambda_mp); fmpz_mod_bma_mpoly_zero(AbarLambda_mp); fmpz_mod_bma_mpoly_zero(BbarLambda_mp); goto next_bma_image_mp; } /* the evaluation killed neither lc(A) nor lc(B) */ FLINT_ASSERT(!fmpz_is_zero(Gammaeval_mp)); success = fmpz_mod_polyu1n_gcd_brown_smprime(Geval_mp, Abareval_mp, Bbareval_mp, Aeval_mp, Beval_mp, ctx_mp, St_mp->poly_stack, St_mp->polyun_stack); if (!success) { fmpz_add_ui(sshift_mp, sshift_mp, GLambda_mp->pointcount + 1); fmpz_mod_bma_mpoly_zero(GLambda_mp); fmpz_mod_bma_mpoly_zero(AbarLambda_mp); fmpz_mod_bma_mpoly_zero(BbarLambda_mp); goto next_bma_image_mp; } FLINT_ASSERT(Geval_mp->length > 0); GevaldegXY = fmpz_mod_polyu1n_bidegree(Geval_mp); _fmpz_mod_poly_vec_mul_fmpz_mod(Geval_mp->coeffs, Geval_mp->length, Gammaeval_mp, ctx_mp); FLINT_ASSERT(fmpz_equal(Gammaeval_mp, fmpz_mod_polyun_leadcoeff(Geval_mp))); if (GdegboundXY < GevaldegXY) { if (fmpz_equal(sshift_mp, last_unlucky_sshift_plus_1_mp)) goto pick_ksub; if (++unlucky_count > 2) goto pick_bma_prime; fmpz_add_ui(last_unlucky_sshift_plus_1_mp, sshift_mp, 1); fmpz_add_ui(sshift_mp, sshift_mp, GLambda_mp->pointcount + 1); fmpz_mod_bma_mpoly_zero(GLambda_mp); fmpz_mod_bma_mpoly_zero(AbarLambda_mp); fmpz_mod_bma_mpoly_zero(BbarLambda_mp); goto next_bma_image_mp; } else if (GdegboundXY > GevaldegXY) { GdegboundXY = GevaldegXY; if (GdegboundXY == 0) goto gcd_is_trivial; fmpz_add_ui(sshift_mp, sshift_mp, GLambda_mp->pointcount); fmpz_mod_bma_mpoly_zero(GLambda_mp); fmpz_mod_bma_mpoly_zero(AbarLambda_mp); fmpz_mod_bma_mpoly_zero(BbarLambda_mp); fmpz_mod_bma_mpoly_add_point(GLambda_mp, Geval_mp, ctx_mp); fmpz_mod_bma_mpoly_add_point(AbarLambda_mp, Abareval_mp, ctx_mp); fmpz_mod_bma_mpoly_add_point(BbarLambda_mp, Bbareval_mp, ctx_mp); goto next_bma_image_mp; } fmpz_mod_bma_mpoly_add_point(GLambda_mp, Geval_mp, ctx_mp); fmpz_mod_bma_mpoly_add_point(AbarLambda_mp, Abareval_mp, ctx_mp); fmpz_mod_bma_mpoly_add_point(BbarLambda_mp, Bbareval_mp, ctx_mp); if ((GLambda_mp->pointcount & 7) != 0) { goto next_bma_image_mp; } if (GLambda_mp->pointcount/2 >= Gamma->length && !fmpz_mod_bma_mpoly_reduce(GLambda_mp, ctx_mp) && fmpz_mod_bma_mpoly_get_fmpz_mpoly2(H, Hmarks, ctx, sshift_mp, GLambda_mp, Ictx, ctx_mp) && Hmarks->coeffs[1] == Gamma->length) { which_check = 0; goto check_mp; } if (AbarLambda_mp->pointcount/2 >= Bmarks->coeffs[1] && !fmpz_mod_bma_mpoly_reduce(AbarLambda_mp, ctx_mp) && fmpz_mod_bma_mpoly_get_fmpz_mpoly2(H, Hmarks, ctx, sshift_mp, AbarLambda_mp, Ictx, ctx_mp) && Hmarks->coeffs[1] == Amarks->coeffs[1]) { which_check = 1; goto check_mp; } if (BbarLambda_mp->pointcount/2 >= Bmarks->coeffs[1] && !fmpz_mod_bma_mpoly_reduce(BbarLambda_mp, ctx_mp) && fmpz_mod_bma_mpoly_get_fmpz_mpoly2(H, Hmarks, ctx, sshift_mp, BbarLambda_mp, Ictx, ctx_mp) && Hmarks->coeffs[1] == Bmarks->coeffs[1]) { which_check = 2; goto check_mp; } if (GLambda_mp->pointcount/2 > ABtotal_length) { success = 0; goto cleanup; } goto next_bma_image_mp; check_mp: FLINT_ASSERT(0 <= which_check && which_check <= 2); FLINT_ASSERT(which_check != 0 || GdegboundXY == _mpoly_bidegree(H->exps, bits, ctx->minfo)); success = _random_check_mp( &GevaldegXY, GdegboundXY, which_check, Aeval_mp, Acur_mp, Ainc_mp, Acoeff_mp, Beval_mp, Bcur_mp, Binc_mp, Bcoeff_mp, Geval_mp, Abareval_mp, Bbareval_mp, Gammaeval_mp, alphas_mp, alpha_caches_mp, H, Hmarks, A, Amarks, Abidegree, B, Bmarks, Bbidegree, Gamma, ctx, ctx_mp, randstate, St_mp); if (success < 1) { if (success == 0) goto next_bma_image_mp; FLINT_ASSERT(GdegboundXY > GevaldegXY); GdegboundXY = GevaldegXY; if (GdegboundXY == 0) goto gcd_is_trivial; fmpz_add_ui(sshift_mp, sshift_mp, GLambda_mp->pointcount); fmpz_mod_bma_mpoly_zero(GLambda_mp); fmpz_mod_bma_mpoly_zero(AbarLambda_mp); fmpz_mod_bma_mpoly_zero(BbarLambda_mp); goto next_bma_image_mp; } } /* assume that H is correct modulo Hmodulus = p */ FLINT_ASSERT(0 <= which_check && which_check <= 2); fmpz_set(Hmodulus, p); p_sp = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); pick_zip_prime: if (p_sp >= UWORD_MAX_PRIME) { success = 0; goto cleanup; } p_sp = n_nextprime(p_sp, 1); if (0 == fmpz_fdiv_ui(Hmodulus, p_sp)) goto pick_zip_prime; nmod_init(&ctx_sp, p_sp); FLINT_ASSERT(p_sp > 3); for (i = 2; i < ctx->minfo->nvars; i++) { alphas_sp[i] = n_urandint(randstate, p_sp - 3) + 2; nmod_pow_cache_start(alphas_sp[i], alpha_caches_sp + 3*i + 0, alpha_caches_sp + 3*i + 1, alpha_caches_sp + 3*i + 2); } mpoly2_nmod_monomial_evals(HH, H->exps, bits, Hmarks->coeffs, Hmarks->length, alpha_caches_sp, ctx->minfo, ctx_sp); req_zip_images = n_polyun_product_roots(MH, HH, ctx_sp); req_zip_images++; mpoly2_nmod_monomial_evals(Ainc_sp, A->exps, bits, Amarks->coeffs, Amarks->length, alpha_caches_sp, ctx->minfo, ctx_sp); mpoly2_nmod_monomial_evals(Binc_sp, B->exps, bits, Bmarks->coeffs, Bmarks->length, alpha_caches_sp, ctx->minfo, ctx_sp); mpoly_nmod_monomial_evals(Gammainc_sp, Gamma->exps, Gamma->length, bits, alpha_caches_sp + 3*2, 2, nvars, ctx->minfo, ctx_sp); fmpz_mpoly2_nmod_coeffs(Acoeff_sp, A->coeffs, Amarks->coeffs, Amarks->length, ctx_sp); fmpz_mpoly2_nmod_coeffs(Bcoeff_sp, B->coeffs, Bmarks->coeffs, Bmarks->length, ctx_sp); fmpz_mpoly_nmod_coeffs(Gammacoeff_sp, Gamma->coeffs, Gamma->length, ctx_sp); n_polyun_set(Acur_sp, Ainc_sp); n_polyun_set(Bcur_sp, Binc_sp); n_poly_set(Gammacur_sp, Gammainc_sp); n_polyun_zip_start(ZH, HH, req_zip_images); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { n_polyun_mod_zip_eval_cur_inc_coeff(Aeval_sp, Acur_sp, Ainc_sp, Acoeff_sp, ctx_sp); n_polyun_mod_zip_eval_cur_inc_coeff(Beval_sp, Bcur_sp, Binc_sp, Bcoeff_sp, ctx_sp); Gammaeval_sp = n_poly_mod_zip_eval_cur_inc_coeff(Gammacur_sp, Gammainc_sp, Gammacoeff_sp, ctx_sp); if (Aeval_sp->length < 1 || Beval_sp->length < 1 || n_polyu1n_bidegree(Aeval_sp) != Abidegree || n_polyu1n_bidegree(Beval_sp) != Bbidegree) { goto pick_zip_prime; } FLINT_ASSERT(Gammaeval_sp != 0); success = n_polyu1n_mod_gcd_brown_smprime(Geval_sp, Abareval_sp, Bbareval_sp, Aeval_sp, Beval_sp, ctx_sp, St_sp); if (!success) goto pick_zip_prime; FLINT_ASSERT(Geval_sp->length > 0); GevaldegXY = n_polyu1n_bidegree(Geval_sp); if (GevaldegXY > GdegboundXY) goto pick_zip_prime; if (GevaldegXY < GdegboundXY) { GdegboundXY = GevaldegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto pick_bma_prime; } _n_poly_vec_mul_nmod_intertible(Geval_sp->coeffs, Geval_sp->length, Gammaeval_sp, ctx_sp); success = n_polyu2n_add_zipun_must_match(ZH, which_check == 1 ? Abareval_sp : which_check == 2 ? Bbareval_sp : Geval_sp, cur_zip_image); if (!success) goto pick_bma_prime; } FLINT_ASSERT(H->length == Hmarks->coeffs[Hmarks->length]); n_poly_fit_length(Hn, H->length); success = zip_solve(Hn->coeffs, ZH, HH, MH, ctx_sp); if (success < 0) goto pick_zip_prime; /* singular */ if (success == 0) goto pick_bma_prime; /* no match */ changed = _fmpz_vec_crt_nmod(&Hbits, H->coeffs, Hmodulus, Hn->coeffs, H->length, ctx_sp); fmpz_mul_ui(Hmodulus, Hmodulus, ctx_sp.n); if (changed) { if (Hbits > Hbitbound) goto pick_bma_prime; goto pick_zip_prime; } success = fmpz_mpolyl_content(Hcontent, H, 2, ctx); if (!success) goto cleanup; if (which_check == 1) { success = fmpz_mpoly_divides(Abar, H, Hcontent, ctx); FLINT_ASSERT(success); if (!fmpz_mpoly_divides(G, A, Abar, ctx) || !fmpz_mpoly_divides(Bbar, B, G, ctx)) { goto pick_zip_prime; } } else if (which_check == 2) { success = fmpz_mpoly_divides(Bbar, H, Hcontent, ctx); FLINT_ASSERT(success); if (!fmpz_mpoly_divides(G, B, Bbar, ctx) || !fmpz_mpoly_divides(Abar, A, G, ctx)) { goto pick_zip_prime; } } else { FLINT_ASSERT(which_check == 0); success = fmpz_mpoly_divides(G, H, Hcontent, ctx); FLINT_ASSERT(success); if (!fmpz_mpoly_divides(Abar, A, G, ctx) || !fmpz_mpoly_divides(Bbar, B, G, ctx)) { goto pick_zip_prime; } } success = 1; cleanup: n_poly_clear(Amarks); n_poly_clear(Bmarks); n_poly_clear(Hmarks); n_polyun_clear(HH); n_polyun_clear(MH); n_polyun_clear(ZH); n_poly_clear(Hn); /* machine precision workspace */ flint_free(alphas_sp); for (i = 0; i < 3*nvars; i++) n_poly_clear(alpha_caches_sp + i); flint_free(alpha_caches_sp); n_polyun_clear(Aeval_sp); n_polyun_clear(Beval_sp); n_polyun_clear(Geval_sp); n_polyun_clear(Abareval_sp); n_polyun_clear(Bbareval_sp); n_poly_clear(Gammacur_sp); n_polyun_clear(Acur_sp); n_polyun_clear(Bcur_sp); n_poly_clear(Gammainc_sp); n_polyun_clear(Ainc_sp); n_polyun_clear(Binc_sp); n_poly_clear(Gammacoeff_sp); n_polyun_clear(Acoeff_sp); n_polyun_clear(Bcoeff_sp); nmod_bma_mpoly_clear(GLambda_sp); nmod_bma_mpoly_clear(AbarLambda_sp); nmod_bma_mpoly_clear(BbarLambda_sp); n_poly_stack_clear(St_sp->poly_stack); n_polyun_stack_clear(St_sp->polyun_stack); /* multiprecision workspace */ _fmpz_vec_clear(alphas_mp, ctx->minfo->nvars); for (i = 0; i < nvars; i++) fmpz_mod_poly_clear(alpha_caches_mp + i, ctx_mp); flint_free(alpha_caches_mp); fmpz_clear(Gammaeval_mp); fmpz_mod_polyun_clear(Aeval_mp, ctx_mp); fmpz_mod_polyun_clear(Beval_mp, ctx_mp); fmpz_mod_polyun_clear(Geval_mp, ctx_mp); fmpz_mod_polyun_clear(Abareval_mp, ctx_mp); fmpz_mod_polyun_clear(Bbareval_mp, ctx_mp); fmpz_mod_poly_clear(Gammacur_mp, ctx_mp); fmpz_mod_polyun_clear(Acur_mp, ctx_mp); fmpz_mod_polyun_clear(Bcur_mp, ctx_mp); fmpz_mod_poly_clear(Gammainc_mp, ctx_mp); fmpz_mod_polyun_clear(Ainc_mp, ctx_mp); fmpz_mod_polyun_clear(Binc_mp, ctx_mp); fmpz_mod_poly_clear(Gammacoeff_mp, ctx_mp); fmpz_mod_polyun_clear(Acoeff_mp, ctx_mp); fmpz_mod_polyun_clear(Bcoeff_mp, ctx_mp); fmpz_mod_poly_stack_clear(St_mp->poly_stack); fmpz_mod_polyun_stack_clear(St_mp->polyun_stack); fmpz_mod_bma_mpoly_clear(GLambda_mp, ctx_mp); fmpz_mod_bma_mpoly_clear(AbarLambda_mp, ctx_mp); fmpz_mod_bma_mpoly_clear(BbarLambda_mp, ctx_mp); fmpz_mod_ctx_clear(ctx_mp); fmpz_clear(last_unlucky_sshift_plus_1_mp); fmpz_clear(sshift_mp); fmpz_clear(image_count_mp); fmpz_mpoly_clear(Hcontent, ctx); fmpz_mpoly_clear(H, ctx); flint_free(Adegs); mpoly_bma_interpolate_ctx_clear(Ictx); fmpz_clear(Hmodulus); fmpz_clear(cBksub); fmpz_clear(cAksub); fmpz_clear(subprod); fmpz_clear(pm1); fmpz_clear(p); flint_randclear(randstate); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(Abar->bits == bits); FLINT_ASSERT(Bbar->bits == bits); return success; gcd_is_trivial: fmpz_mpoly_one(G, ctx); fmpz_mpoly_set(Abar, A, ctx); fmpz_mpoly_set(Bbar, B, ctx); success = 1; goto cleanup; } flint-3.1.3/src/fmpz_mpoly_factor/get_set_lead0.c000066400000000000000000000021661461254215100220240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" void _fmpz_mpoly_get_lead0( fmpz_mpoly_t c, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { fmpz_mpolyl_lead_coeff(c, A, 1, ctx); } void _fmpz_mpoly_set_lead0( fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx) { slong deg; fmpz_mpoly_t t, g; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(g, ctx); deg = fmpz_mpoly_degree_si(B, 0, ctx); FLINT_ASSERT(deg >= 0); fmpz_mpoly_gen(g, 0, ctx); fmpz_mpoly_pow_ui(g, g, deg, ctx); _fmpz_mpoly_get_lead0(t, B, ctx); fmpz_mpoly_sub(t, c, t, ctx); fmpz_mpoly_mul(t, t, g, ctx); fmpz_mpoly_add(A, B, t, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(g, ctx); } flint-3.1.3/src/fmpz_mpoly_factor/init.c000066400000000000000000000020761461254215100202700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_factor_init2(fmpz_mpoly_factor_t f, slong alloc, const fmpz_mpoly_ctx_t ctx) { fmpz_init_set_ui(f->constant, 1); if (alloc > 0) { slong i; f->exp = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); f->poly = (fmpz_mpoly_struct *) flint_malloc(alloc * sizeof(fmpz_mpoly_struct)); for (i = 0; i < alloc; i++) fmpz_mpoly_init(f->poly + i, ctx); f->alloc = alloc; } else { f->exp = NULL; f->poly = NULL; f->alloc = 0; } f->num = 0; } flint-3.1.3/src/fmpz_mpoly_factor/inlines.c000066400000000000000000000007001461254215100207560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MPOLY_FACTOR_INLINES_C #include "fmpz_mpoly_factor.h" flint-3.1.3/src/fmpz_mpoly_factor/interp.c000066400000000000000000000242621461254215100206270ustar00rootroot00000000000000/* Copyright (C) 2019, 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fmpz_mpoly_factor.h" /* interp_reduce: map from Z to Z/pZ interp_lift: map from Z/pZ to Z interp_crt: update element of Z with a new image in Z/pZ interp_mcrt: same as interp_crt, but monomial match, thus easier */ /*****************************************************************************/ /* Ap = A mod p Ap is in Fp[x_0, ..., x_(n-1)] A is in ZZ[x_0, ..., x_(n-1)], n = ctx->minfo->nvars */ void fmpz_mpoly_interp_reduce_p( nmod_mpoly_t Ap, const nmod_mpoly_ctx_t ctxp, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong i, k, N; FLINT_ASSERT(Ap->bits == A->bits); N = mpoly_words_per_exp(A->bits, ctx->minfo); nmod_mpoly_fit_length(Ap, A->length, ctxp); k = 0; for (i = 0; i < A->length; i++) { mpoly_monomial_set(Ap->exps + N*k, A->exps + N*i, N); Ap->coeffs[k] = fmpz_get_nmod(A->coeffs + i, ctxp->mod); k += (Ap->coeffs[k] != 0); } Ap->length = k; } /* Convert Ap to A using the symmetric range (-p/2, p/2] A is in ZZ[x_0, ..., x_(n-1)], n = ctx->minfo->nvars Ap is in Fp[x_0, ..., x_(n-1)] */ void fmpz_mpoly_interp_lift_p( fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, nmod_mpoly_t Ap, const nmod_mpoly_ctx_t ctxp) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); FLINT_ASSERT(Ap->bits == A->bits); fmpz_mpoly_fit_length(A, Ap->length, ctx); mpoly_copy_monomials(A->exps, Ap->exps, Ap->length, N); _fmpz_vec_set_nmod_vec(A->coeffs, Ap->coeffs, Ap->length, ctxp->mod); _fmpz_mpoly_set_length(A, Ap->length, ctx); } /* Update H so that it does not change mod m, and is now A mod p It is asserted that the monomials in H and A match H is in ZZ[x_0, ..., x_(n-1)], n = ctx->minfo->nvars A is in Fp[x_0, ..., x_(n-1)] */ int fmpz_mpoly_interp_mcrt_p( flint_bitcnt_t * coeffbits_, fmpz_mpoly_t H, const fmpz_mpoly_ctx_t ctx, const fmpz_t m, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctxp) { slong i; #if FLINT_WANT_ASSERT slong N = mpoly_words_per_exp(A->bits, ctx->minfo); #endif int changed = 0; flint_bitcnt_t coeffbits = 0; fmpz_t t; FLINT_ASSERT(H->length == A->length); FLINT_ASSERT(H->bits == A->bits); fmpz_init(t); for (i = 0; i < A->length; i++) { FLINT_ASSERT(mpoly_monomial_equal(H->exps + N*i, A->exps + N*i, N)); fmpz_CRT_ui(t, H->coeffs + i, m, A->coeffs[i], ctxp->mod.n, 1); coeffbits = FLINT_MAX(coeffbits, fmpz_bits(t)); changed |= !fmpz_equal(t, H->coeffs + i); fmpz_swap(t, H->coeffs + i); } fmpz_clear(t); *coeffbits_ = coeffbits; return changed; } /*****************************************************************************/ /* E = A mod p E is in Fp[x_0,...,x_(m-2)][x_(m-1)] A is in ZZ[x_0,...,x_(m-2), x_(m-1)], m = ctx->minfo->nvars */ void fmpz_mpoly_interp_reduce_p_mpolyn( nmod_mpolyn_t E, const nmod_mpoly_ctx_t pctx, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift, k; ulong mask; mp_limb_t v; fmpz * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong Alen = A->length; slong Ai; n_poly_struct * Ecoeff; ulong * Eexp; slong Ei; slong m = ctx->minfo->nvars; mpoly_gen_offset_shift_sp(&offset, &shift, m - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); Ecoeff = E->coeffs; Eexp = E->exps; Ei = 0; for (Ai = 0; Ai < Alen; Ai++) { v = fmpz_get_nmod(Acoeff + Ai, pctx->mod); k = ((Aexp + N*Ai)[offset] >> shift) & mask; if (v == 0) { continue; } if (Ei > 0 && mpoly_monomial_equal_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))) { n_poly_set_coeff(Ecoeff + Ei - 1, k, v); } else { FLINT_ASSERT(Ei == 0 || mpoly_monomial_gt_nomask_extra( Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Ei >= E->alloc) { nmod_mpolyn_fit_length(E, Ei + 1, pctx); Ecoeff = E->coeffs; Eexp = E->exps; } mpoly_monomial_set_extra(Eexp + N*Ei, Aexp + N*Ai, N, offset, -(k << shift)); n_poly_zero(Ecoeff + Ei); n_poly_set_coeff(Ecoeff + Ei, k, v); Ei++; } } E->length = Ei; } /* A = B using symmetric range A is in ZZ[x_0, ..., x_(var-2), x_(m-1)] B is in Fp[x_0, ..., x_(var-2)][x_(m-1)] */ void fmpz_mpoly_interp_lift_p_mpolyn( fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t pctx) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong offset, shift; slong vi; n_poly_struct * Bcoeff = B->coeffs; ulong * Bexp = B->exps; slong Blen = B->length; slong Bi; fmpz * Acoeff; ulong * Aexp; slong Ai; slong var = ctx->minfo->nvars; FLINT_ASSERT(var == pctx->minfo->nvars); fmpz_mpoly_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Ai = 0; for (Bi = 0; Bi < Blen; Bi++) { if (Ai + (Bcoeff + Bi)->length >= A->alloc) { fmpz_mpoly_fit_length(A, Ai + (Bcoeff + Bi)->length, ctx); Acoeff = A->coeffs; Aexp = A->exps; } for (vi = (Bcoeff + Bi)->length - 1; vi >= 0; vi--) { if ((Bcoeff + Bi)->coeffs[vi] != 0) { mpoly_monomial_set_extra(Aexp + N*Ai, Bexp + N*Bi, N, offset, vi << shift); fmpz_set_ui_smod(Acoeff + Ai, (Bcoeff + Bi)->coeffs[vi], pctx->mod.n); Ai++; } } } A->length = Ai; } /* F = F + modulus*((A - F(mod p))/(modulus (mod p))) no assumptions about matching monomials F is in ZZ[x_0, ..., x_(m-1), x_(m-1)] A is in Fp[x_0, ..., x_(m-2)][x_(m-1)] */ int fmpz_mpoly_interp_crt_p_mpolyn( fmpz_mpoly_t F, fmpz_mpoly_t T, const fmpz_mpoly_ctx_t ctx, fmpz_t modulus, const nmod_mpolyn_t A, const nmod_mpoly_ctx_t pctx) { int changed = 0; slong N = mpoly_words_per_exp_sp(T->bits, ctx->minfo); slong offset, shift; slong vi; fmpz * Tcoeff; ulong * Texp; slong Ti; n_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai; fmpz * Fcoeff = F->coeffs; slong Flen = F->length; ulong * Fexp = F->exps; slong Fi; fmpz_t zero; fmpz_init(zero); FLINT_ASSERT(T->bits == A->bits); FLINT_ASSERT(F->bits == A->bits); FLINT_ASSERT(pctx->minfo->nvars == ctx->minfo->nvars); FLINT_ASSERT(fmpz_mpoly_is_canonical(F, ctx)); FLINT_ASSERT(nmod_mpolyn_is_canonical(A, pctx)); mpoly_gen_offset_shift_sp(&offset, &shift, pctx->minfo->nvars - 1, A->bits, ctx->minfo); Flen = F->length; fmpz_mpoly_fit_length(T, FLINT_MAX(Flen, Alen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = 0; Fi = Ai = vi = 0; if (Ai < Alen) vi = n_poly_degree(A->coeffs + Ai); while (Fi < Flen || Ai < Alen) { if (Ti >= T->alloc) { fmpz_mpoly_fit_length(T, Ti + FLINT_MAX(Flen - Fi, Alen - Ai), ctx); Tcoeff = T->coeffs; Texp = T->exps; } if (Fi < Flen && Ai < Alen && mpoly_monomial_equal_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift)) { /* F term ok, A term ok */ fmpz_CRT_ui(Tcoeff + Ti, Fcoeff + Fi, modulus, (Acoeff + Ai)->coeffs[vi], pctx->mod.n, 1); changed |= !fmpz_equal(Tcoeff + Ti, Fcoeff + Fi); mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; do { vi--; } while (vi >= 0 && (Acoeff + Ai)->coeffs[vi] == 0); if (vi < 0) { Ai++; if (Ai < Alen) vi = n_poly_degree(A->coeffs + Ai); } } else if (Fi < Flen && (Ai >= Alen || mpoly_monomial_gt_nomask_extra( Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))) { /* F term ok, A term missing */ fmpz_CRT_ui(Tcoeff + Ti, Fcoeff + Fi, modulus, 0, pctx->mod.n, 1); changed |= !fmpz_equal(Tcoeff + Ti, Fcoeff + Fi); mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; } else { FLINT_ASSERT(Ai < Alen && (Fi >= Flen || mpoly_monomial_lt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))); /* F term missing, A term ok */ fmpz_CRT_ui(Tcoeff + Ti, zero, modulus, (Acoeff + Ai)->coeffs[vi], pctx->mod.n, 1); FLINT_ASSERT(!fmpz_is_zero(Tcoeff + Ti)); changed = 1; mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, vi << shift); do { vi--; } while (vi >= 0 && (Acoeff + Ai)->coeffs[vi] == 0); if (vi < 0) { Ai++; if (Ai < Alen) vi = n_poly_degree(A->coeffs + Ai); } } FLINT_ASSERT(!fmpz_is_zero(Tcoeff + Ti)); Ti++; } T->length = Ti; if (changed) { fmpz_mpoly_swap(F, T, ctx); } fmpz_clear(zero); return changed; } flint-3.1.3/src/fmpz_mpoly_factor/irred_wang.c000066400000000000000000000220711461254215100214430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_factor_irred_wang( fmpz_mpolyv_t fac, const fmpz_mpoly_t A, const fmpz_mpoly_factor_t lcAfac, int lcAfac_irred, const fmpz_mpoly_t lcA, const fmpz_mpoly_ctx_t ctx, flint_rand_t state, zassenhaus_prune_t zas, int allow_shift) { int success, kfails = 0; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; fmpz * alpha; slong alpha_modulus, alpha_count; fmpz_mpoly_struct * Aevals; slong * degs, * tdegs; fmpz_mpolyv_t tfac; fmpz_mpoly_t t, Acopy; fmpz_mpoly_struct * newA; fmpz_poly_t Au; fmpz_poly_factor_t Aufac; fmpz_mpoly_t m, mpow; fmpz_mpolyv_t new_lcs, lc_divs; fmpz_t q; FLINT_ASSERT(n > 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(fmpz_mpoly_factor_matches(lcA, lcAfac, ctx)); fmpz_init(q); fmpz_mpoly_init(Acopy, ctx); fmpz_mpoly_init(m, ctx); fmpz_mpoly_init(mpow, ctx); fmpz_mpolyv_init(new_lcs, ctx); fmpz_mpolyv_init(lc_divs, ctx); fmpz_poly_factor_init(Aufac); fmpz_poly_init(Au); degs = (slong *) flint_malloc(2*(n + 1)*sizeof(slong)); tdegs = degs + (n + 1); alpha = _fmpz_vec_init(n); Aevals = (fmpz_mpoly_struct *) flint_malloc(n*sizeof(fmpz_mpoly_struct)); for (i = 0; i < n; i++) fmpz_mpoly_init(Aevals + i, ctx); fmpz_mpolyv_init(tfac, ctx); fmpz_mpoly_init(t, ctx); /* init done */ fmpz_mpoly_degrees_si(degs, A, ctx); alpha_count = 0; alpha_modulus = 1; goto got_alpha; next_alpha: if (!allow_shift) { success = 0; goto cleanup; } alpha_count++; if (alpha_count >= alpha_modulus) { alpha_count = 0; alpha_modulus++; if (alpha_modulus/1024 > ctx->minfo->nvars) { success = 0; goto cleanup; } } for (i = 0; i < n; i++) fmpz_set_si(alpha + i, n_urandint(state, alpha_modulus) - alpha_modulus/2); got_alpha: #if FLINT_WANT_ASSERT fmpz_mpoly_degrees_si(tdegs, A, ctx); for (i = 0; i < n + 1; i++) FLINT_ASSERT(degs[i] == tdegs[i]); #endif /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fmpz_mpoly_degrees_si(tdegs, Aevals + i, ctx); for (j = 0; j <= i; j++) { if (tdegs[j] != degs[j]) goto next_alpha; } } /* make sure our univar is squarefree */ FLINT_ASSERT(fmpz_mpoly_is_fmpz_poly(Aevals + 0, 0, ctx)); success = fmpz_mpoly_get_fmpz_poly(Au, Aevals + 0, 0, ctx); FLINT_ASSERT(success); fmpz_poly_factor(Aufac, Au); r = Aufac->num; zassenhaus_prune_start_add_factors(zas); for (j = 0; j < r; j++) zassenhaus_prune_add_factor(zas, fmpz_poly_degree(Aufac->p + j), Aufac->exp[j]); zassenhaus_prune_end_add_factors(zas); if ((r < 2 && Aufac->exp[0] == 1) || zassenhaus_prune_must_be_irreducible(zas)) { fmpz_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } for (j = 0; j < r; j++) { if (Aufac->exp[j] != 1) goto next_alpha; } fmpz_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = 0; if (lcAfac_irred) success = fmpz_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, &Aufac->c, Aufac->p, r, alpha, ctx); if (!success) { success = fmpz_mpoly_factor_lcc_kaltofen(lc_divs->coeffs, lcAfac, A, r, alpha, degs, Aufac, ctx); if (success < 0 || (success == 0 && ++kfails < 4)) goto next_alpha; } } else { for (i = 0; i < r; i++) { FLINT_ASSERT(Aufac->p[i].length > 0); fmpz_mpoly_set_fmpz(lc_divs->coeffs + i, Aufac->p[i].coeffs + Aufac->p[i].length - 1, ctx); } } FLINT_ASSERT(r > 1); success = fmpz_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); if (!success) goto next_alpha; for (i = 1; i < r; i++) { success = fmpz_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); if (!success) goto next_alpha; } fmpz_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fmpz_mpoly_is_one(mpow, ctx)) { newA = (fmpz_mpoly_struct *) A; } else { newA = Acopy; fmpz_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = -1; goto cleanup; } fmpz_mpoly_degrees_si(tdegs, newA, ctx); fmpz_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(t, mpow, i + 1, alpha + i, ctx); fmpz_mpoly_swap(t, mpow, ctx); fmpz_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); } fmpz_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fmpz_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mpoly_evaluate_one_fmpz(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fmpz_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { FLINT_ASSERT(fmpz_mpoly_is_fmpz(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fmpz_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); FLINT_ASSERT(fmpz_divisible(new_lcs->coeffs[i].coeffs + 0, Aufac->p[i].coeffs + Aufac->p[i].length - 1)); fmpz_divexact(q, new_lcs->coeffs[i].coeffs + 0, Aufac->p[i].coeffs + Aufac->p[i].length - 1); _fmpz_mpoly_set_fmpz_poly(fac->coeffs + i, newA->bits, Aufac->p[i].coeffs, Aufac->p[i].length, 0, ctx); fmpz_mpoly_scalar_mul_fmpz(fac->coeffs + i, fac->coeffs + i, q, ctx); } fmpz_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _fmpz_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } success = fmpz_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, tdegs, ctx); if (!success) goto next_alpha; fmpz_mpolyv_swap(tfac, fac, ctx); } if (fmpz_mpoly_is_fmpz(m, ctx)) { for (i = 0; i < r; i++) { _fmpz_vec_content(q, fac->coeffs[i].coeffs, fac->coeffs[i].length); if (fmpz_sgn(fac->coeffs[i].coeffs + 0) < 0) fmpz_neg(q, q); fmpz_mpoly_scalar_divexact_fmpz(fac->coeffs + i, fac->coeffs + i, q, ctx); } } else { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!fmpz_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fmpz_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); fmpz_mpoly_unit_normalize(fac->coeffs + i, ctx); } } success = 1; cleanup: fmpz_clear(q); fmpz_mpolyv_clear(new_lcs, ctx); fmpz_mpolyv_clear(lc_divs, ctx); fmpz_poly_factor_clear(Aufac); _fmpz_vec_clear(alpha, n); for (i = 0; i < n; i++) fmpz_mpoly_clear(Aevals + i, ctx); flint_free(Aevals); flint_free(degs); /* and tdegs */ fmpz_mpolyv_clear(tfac, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(Acopy, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_clear(mpow, ctx); fmpz_poly_clear(Au); #if FLINT_WANT_ASSERT if (success) { fmpz_mpoly_t prod; fmpz_mpoly_init(prod, ctx); fmpz_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) fmpz_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(prod, A, ctx)); fmpz_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/fmpz_mpoly_factor/irred_zassenhaus.c000066400000000000000000000264341461254215100227020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mpoly_factor.h" /* return: 1: success 0: lift is impossible -1: failed, don't try again */ static int _try_lift( fmpz_mpolyv_t qfac, const fmpz_mpoly_t q, const fmpz_mpolyv_t pfac, const fmpz_mpoly_t p, slong m, fmpz * alpha, slong n, const fmpz_mpoly_ctx_t ctx) { int success; slong i; slong * newdeg; fmpz_mpoly_t lcq, lcp, t, newq; FLINT_ASSERT(pfac->length > 1); newdeg = (slong *) flint_malloc((n + 1)*sizeof(slong)); fmpz_mpoly_init(lcq, ctx); fmpz_mpoly_init(lcp, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(newq, ctx); #if FLINT_WANT_ASSERT fmpz_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fmpz_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(t, p, ctx)); #endif _fmpz_mpoly_get_lead0(lcq, q, ctx); fmpz_mpoly_evaluate_one_fmpz(lcp, lcq, m, alpha + m - 1, ctx); FLINT_ASSERT(lcp->length > 0); fmpz_mpoly_pow_ui(t, lcq, pfac->length - 1, ctx); fmpz_mpoly_mul(newq, q, t, ctx); if (newq->bits > FLINT_BITS) { success = -1; goto cleanup; } fmpz_mpoly_degrees_si(newdeg, newq, ctx); fmpz_mpolyv_fit_length(qfac, pfac->length, ctx); qfac->length = pfac->length; for (i = 0; i < pfac->length; i++) { _fmpz_mpoly_get_lead0(t, pfac->coeffs + i, ctx); success = fmpz_mpoly_divides(t, lcp, t, ctx); FLINT_ASSERT(success); fmpz_mpoly_mul(qfac->coeffs + i, pfac->coeffs + i, t, ctx); _fmpz_mpoly_set_lead0(qfac->coeffs + i, qfac->coeffs + i, lcq, ctx); } success = fmpz_mpoly_hlift(m, qfac->coeffs, qfac->length, alpha, newq, newdeg, ctx); if (!success) goto cleanup; for (i = 0; i < qfac->length; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(qfac->coeffs[i].bits <= FLINT_BITS); if (!fmpz_mpolyl_content(t, qfac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fmpz_mpoly_divides(qfac->coeffs + i, qfac->coeffs + i, t, ctx); FLINT_ASSERT(success); fmpz_mpoly_unit_normalize(qfac->coeffs + i, ctx); } success = 1; cleanup: flint_free(newdeg); fmpz_mpoly_clear(lcq, ctx); fmpz_mpoly_clear(lcp, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(newq, ctx); #if FLINT_WANT_ASSERT if (success > 0) { fmpz_mpoly_init(t, ctx); fmpz_mpoly_one(t, ctx); for (i = 0; i < qfac->length; i++) fmpz_mpoly_mul(t, t, qfac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(t, q, ctx)); fmpz_mpoly_clear(t, ctx); } #endif return success; } /* A is square free and primitive w.r.t all variables */ int fmpz_mpoly_factor_irred_zassenhaus( fmpz_mpolyv_t fac, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, zassenhaus_prune_t zas) { int success; const slong n = ctx->minfo->nvars - 1; slong i, j, k, m, len; slong * subset; fmpz * alpha, * alphait; fmpz_mpoly_struct * Aevals; slong * deg, * degeval; fmpz_mpolyv_t qfac, pfac, tfac, dfac; fmpz_mpoly_t t, p, q; fmpz_poly_t c; fmpz_bpoly_t B; fmpz_tpoly_t F; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(fmpz_sgn(A->coeffs + 0) > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); subset = (slong*) flint_malloc(4*sizeof(slong)); alphait = _fmpz_vec_init(n); alpha = _fmpz_vec_init(n); Aevals = (fmpz_mpoly_struct *) flint_malloc(n*sizeof(fmpz_mpoly_struct)); deg = (slong *) flint_malloc((n + 1)*sizeof(slong)); degeval = (slong *) flint_malloc((n + 1)*sizeof(slong)); for (i = 0; i < n; i++) fmpz_mpoly_init(Aevals + i, ctx); fmpz_mpolyv_init(pfac, ctx); fmpz_mpolyv_init(qfac, ctx); fmpz_mpolyv_init(tfac, ctx); fmpz_mpolyv_init(dfac, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(p, ctx); fmpz_mpoly_init(q, ctx); fmpz_poly_init(c); fmpz_bpoly_init(B); fmpz_tpoly_init(F); fmpz_mpoly_degrees_si(deg, A, ctx); goto got_alpha; next_alpha: tuple_next(alphait, n); for (i = 0; i < n; i++) { j = n - 1 - i; fmpz_cdiv_q_2exp(alpha + j, alphait + i, 1); if (fmpz_is_even(alphait + i)) fmpz_neg(alpha + j, alpha + j); } got_alpha: /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fmpz_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); fmpz_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) { if (degeval[j] != deg[j]) { tuple_saturate(alphait, n, n - i); goto next_alpha; } } } /* make sure univar is squarefree */ fmpz_mpoly_derivative(t, Aevals + 0, 0, ctx); success = fmpz_mpoly_gcd(t, t, Aevals + 0, ctx); if (!success) goto cleanup; if (!fmpz_mpoly_is_fmpz(t, ctx)) goto next_alpha; /* make evaluations primitive */ for (i = n - 1; i > 0; i--) { success = fmpz_mpolyl_content(t, Aevals + i, 1, ctx); if (!success) goto cleanup; success = fmpz_mpoly_divides(Aevals + i, Aevals + i, t, ctx); FLINT_ASSERT(success); fmpz_mpoly_unit_normalize(Aevals + i, ctx); fmpz_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); } fmpz_mpoly_get_bpoly(B, Aevals + 1, 0, 1, ctx); fmpz_bpoly_factor(c, F, B); FLINT_ASSERT(c->length == 1 && fmpz_is_pm1(c->coeffs + 0)); fmpz_mpolyv_fit_length(pfac, F->length, ctx); pfac->length = F->length; for (i = 0; i < F->length; i++) { fmpz_mpoly_set_fmpz_bpoly(pfac->coeffs + i, A->bits, F->coeffs + i, 0, 1, ctx); fmpz_mpoly_unit_normalize(pfac->coeffs + i, ctx); } /* number of of local factors can only decrease from here on */ subset = flint_realloc(subset, pfac->length*sizeof(slong)); for (m = 2; m <= n; m++) { fmpz_mpoly_set(q, m < n ? Aevals + m : A, ctx); fmpz_mpoly_set(p, Aevals + m - 1, ctx); #if FLINT_WANT_ASSERT fmpz_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fmpz_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(t, p, ctx)); #endif /* if one local factor, A must be irreducible */ if (pfac->length < 2) { fmpz_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } success = _try_lift(qfac, q, pfac, p, m, alpha, n, ctx); if (success > 0) { fmpz_mpolyv_swap(qfac, pfac, ctx); continue; } else if (success < 0) { success = 0; goto cleanup; } /* if we couldn't lift two local factors, A must be irreducible */ if (pfac->length == 2) { fmpz_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } qfac->length = 0; len = pfac->length; for (k = 0; k < len; k++) subset[k] = k; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); #if FLINT_WANT_ASSERT fmpz_mpoly_one(t, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fmpz_mpoly_mul(t, t, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } FLINT_ASSERT(fmpz_mpoly_equal(t, p, ctx)); #endif while (1) { fmpz_mpolyv_fit_length(dfac, 2, ctx); dfac->length = 2; fmpz_mpoly_one(dfac->coeffs + 0, ctx); fmpz_mpoly_one(dfac->coeffs + 1, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fmpz_mpoly_mul(dfac->coeffs + in, dfac->coeffs + in, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } success = _try_lift(tfac, q, dfac, p, m, alpha, n, ctx); if (success > 0) { fmpz_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fmpz_mpoly_swap(qfac->coeffs + qfac->length, tfac->coeffs + 1, ctx); qfac->length++; fmpz_mpoly_swap(q, tfac->coeffs + 0, ctx); fmpz_mpoly_swap(p, dfac->coeffs + 0, ctx); len -= k; if (k > len/2 || !zassenhaus_subset_next_disjoint(subset, len + k)) { break; } } else if (success < 0) { success = 0; goto cleanup; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } /* remnants are irreducible */ if (!fmpz_mpoly_is_fmpz(q, ctx)) { fmpz_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fmpz_mpoly_swap(qfac->coeffs + qfac->length, q, ctx); qfac->length++; } else { FLINT_ASSERT(fmpz_mpoly_is_one(q, ctx)); } fmpz_mpolyv_swap(qfac, pfac, ctx); } success = 1; fmpz_mpolyv_swap(fac, pfac, ctx); cleanup: flint_free(subset); _fmpz_vec_clear(alphait, n); _fmpz_vec_clear(alpha, n); for (i = 0; i < n; i++) fmpz_mpoly_clear(Aevals + i, ctx); flint_free(Aevals); flint_free(deg); flint_free(degeval); fmpz_mpolyv_clear(pfac, ctx); fmpz_mpolyv_clear(qfac, ctx); fmpz_mpolyv_clear(tfac, ctx); fmpz_mpolyv_clear(dfac, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_clear(q, ctx); fmpz_poly_clear(c); fmpz_bpoly_clear(B); fmpz_tpoly_clear(F); FLINT_ASSERT(success == 0 || success == 1); #if FLINT_WANT_ASSERT if (success) { fmpz_mpoly_init(t, ctx); fmpz_mpoly_one(t, ctx); for (i = 0; i < fac->length; i++) fmpz_mpoly_mul(t, t, fac->coeffs + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(t, A, ctx)); fmpz_mpoly_clear(t, ctx); } #endif return success; } flint-3.1.3/src/fmpz_mpoly_factor/irred_zippel.c000066400000000000000000000676411461254215100220260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "nmod_poly_factor.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #include "fmpz_mpoly_factor.h" static void nmod_mpoly_get_eval_helper2( n_polyun_t EH, const nmod_mpoly_t A, n_poly_struct * caches, const nmod_mpoly_ctx_t ctx) { slong start, Ai, j, k, n; slong e0, e1, EHi; mp_limb_t * p; flint_bitcnt_t bits = A->bits; slong Alen = A->length; const ulong * Aexps = A->exps; slong nvars = ctx->minfo->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong off0, off1, shift0, shift1; slong * off, * shift; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; mpoly_gen_offset_shift_sp(&off0, &shift0, 0, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, bits, ctx->minfo); off = (slong *) TMP_ALLOC(2*nvars*sizeof(slong)); shift = off + nvars; for (k = 2; k < nvars; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k, bits, ctx->minfo); Ai = 0; EHi = 0; while (Ai < Alen) { start = Ai; e0 = (Aexps[N*Ai + off0] >> shift0) & mask; e1 = (Aexps[N*Ai + off1] >> shift1) & mask; while (1) { Ai++; if (Ai >= Alen) break; if (((Aexps[N*Ai + off0] >> shift0) & mask) != e0) break; if (((Aexps[N*Ai + off1] >> shift1) & mask) != e1) break; } n = Ai - start; n_polyun_fit_length(EH, EHi + 1); EH->exps[EHi] = pack_exp2(e0, e1); n_poly_fit_length(EH->coeffs + EHi, 2*n); EH->coeffs[EHi].length = n; p = EH->coeffs[EHi].coeffs; EHi++; for (j = 0; j < n; j++) { mp_limb_t meval = 1; for (k = 2; k < nvars; k++) { ulong ei = (Aexps[N*(start + j) + off[k]] >> shift[k]) & mask; meval = nmod_pow_cache_mulpow_ui(meval, ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->mod); } /* set cur = monomial eval */ p[j] = meval; /* copy cur to inc */ p[j + n] = meval; } } EH->length = EHi; TMP_END; } static slong nmod_mpoly_set_eval_helper_and_zip_form2( slong * deg1_, /* degree of B wrt main var 1 */ n_polyun_t EH, n_polyun_t H, n_polyun_t M, const nmod_mpoly_t B, n_poly_struct * caches, const nmod_mpoly_ctx_t ctx) { slong start, Bi, j, k, n; slong e0, e1, Hi, EHi; mp_limb_t * p; slong zip_length = 0; flint_bitcnt_t bits = B->bits; slong Blen = B->length; const ulong * Bexps = B->exps; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong off0, off1, shift0, shift1; slong deg0, deg1 = -1; slong * off, * shift; TMP_INIT; TMP_START; FLINT_ASSERT(Blen > 0); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, bits, ctx->minfo); off = (slong *) TMP_ALLOC(2*ctx->minfo->nvars*sizeof(slong)); shift = off + ctx->minfo->nvars; for (k = 2; k < ctx->minfo->nvars; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k, bits, ctx->minfo); Bi = 0; deg0 = (Bexps[N*Bi + off0] >> shift0) & mask; EHi = 0; Hi = 0; while (Bi < Blen) { start = Bi; e0 = (Bexps[N*Bi + off0] >> shift0) & mask; e1 = (Bexps[N*Bi + off1] >> shift1) & mask; deg1 = FLINT_MAX(deg1, e1); while (1) { Bi++; if (Bi >= Blen) break; if (((Bexps[N*Bi + off0] >> shift0) & mask) != e0) break; if (((Bexps[N*Bi + off1] >> shift1) & mask) != e1) break; } n = Bi - start; n_polyun_fit_length(EH, EHi + 1); EH->exps[EHi] = pack_exp2(e0, e1); n_poly_fit_length(EH->coeffs + EHi, 2*n); EH->coeffs[EHi].length = n; p = EH->coeffs[EHi].coeffs; EHi++; for (j = 0; j < n; j++) { mp_limb_t meval = 1; for (k = 2; k < ctx->minfo->nvars; k++) { ulong ei = (Bexps[N*(start + j) + off[k]] >> shift[k]) & mask; meval = nmod_pow_cache_mulpow_ui(meval, ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->mod); } /* set cur = monomial eval */ p[j] = meval; /* copy cur to inc */ p[j + n] = meval; } if (e0 < deg0) { n_polyun_fit_length(H, Hi + 1); n_polyun_fit_length(M, Hi + 1); H->exps[Hi] = pack_exp2(e0, e1); M->exps[Hi] = pack_exp2(e0, e1); n_poly_fit_length(H->coeffs + Hi, n); zip_length = FLINT_MAX(zip_length, n); H->coeffs[Hi].length = n; flint_mpn_copyi(H->coeffs[Hi].coeffs, p, n); n_poly_mod_product_roots_nmod_vec(M->coeffs + Hi, p, n, ctx->mod); Hi++; } } TMP_END; EH->length = EHi; H->length = Hi; M->length = Hi; *deg1_ = deg1; return zip_length; } static int _fmpz_mpoly_modpk_update_zip( fmpz_t pk, fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, n_polyun_t Z, const n_polyun_t H, const n_polyun_t M, const nmod_mpoly_ctx_t ctxp) { slong i, j, Ai, n; int success; slong off, shift; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong start, mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); n_poly_t c, t; mp_limb_t * ccoeffs; mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); mask = mask << shift; Ai = 1; start = (A->exps + N*0)[off] & mask; while (Ai < A->length && start == ((A->exps + N*Ai)[off] & mask)) { Ai++; } FLINT_ASSERT(Ai < A->length); if (Ai >= A->length) return 1; n_poly_init(c); n_poly_init(t); FLINT_ASSERT(Z->length == H->length); FLINT_ASSERT(Z->length == M->length); for (i = 0; i < Z->length; i++) { n = H->coeffs[i].length; FLINT_ASSERT(M->coeffs[i].length == n + 1); FLINT_ASSERT(Z->coeffs[i].length >= n); n_poly_fit_length(c, n); n_poly_fit_length(t, n); ccoeffs = c->coeffs; success = _nmod_zip_vand_solve(c->coeffs, H->coeffs[i].coeffs, n, Z->coeffs[i].coeffs, Z->coeffs[i].length, M->coeffs[i].coeffs, t->coeffs, ctxp->mod); if (success < 1) { n_poly_clear(t); n_poly_clear(c); return success; } FLINT_ASSERT(Ai + n <= A->length); for (j = 0; j < n; j++) { if (ctxp->mod.n - ccoeffs[j] < ccoeffs[j]) fmpz_submul_ui(A->coeffs + Ai + j, pk, ctxp->mod.n - ccoeffs[j]); else fmpz_addmul_ui(A->coeffs + Ai + j, pk, ccoeffs[j]); } Ai += n; } FLINT_ASSERT(Ai == A->length); n_poly_clear(t); n_poly_clear(c); return 1; } static void _nmod_mpoly_set_fmpz_mpoly( nmod_mpoly_t Ap, const nmod_mpoly_ctx_t ctxp, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong Ap_len, i; FLINT_ASSERT(ctx->minfo->nvars == ctx->minfo->nvars); FLINT_ASSERT(ctx->minfo->ord == ctx->minfo->ord); nmod_mpoly_fit_length_reset_bits(Ap, A->length, A->bits, ctxp); Ap_len = 0; for (i = 0; i < A->length; i++) { Ap->coeffs[Ap_len] = fmpz_get_nmod(A->coeffs + i, ctxp->mod); if (Ap->coeffs[Ap_len] == 0) continue; mpoly_monomial_set(Ap->exps + N*Ap_len, A->exps + N*i, N); Ap_len++; } Ap->length = Ap_len; } static void _fmpz_mpoly_modpk_taylor_coeff( const fmpz_t pk, nmod_mpoly_t T, const nmod_mpoly_ctx_t ctxp, const fmpz_mpoly_t E, const fmpz_mpoly_ctx_t ctx) { slong i, Tlen; slong N = mpoly_words_per_exp(E->bits, ctx->minfo); fmpz_t t; fmpz_init(t); nmod_mpoly_fit_length_reset_bits(T, E->length, E->bits, ctxp); Tlen = 0; for (i = 0; i < E->length; i++) { FLINT_ASSERT(fmpz_divisible(E->coeffs + i, pk)); /* TODO !!! */ fmpz_divexact(t, E->coeffs + i, pk); T->coeffs[Tlen] = fmpz_get_nmod(t, ctxp->mod); if (T->coeffs[Tlen] == 0) continue; mpoly_monomial_set(T->exps + N*Tlen, E->exps + N*i, N); Tlen++; } T->length = Tlen; fmpz_clear(t); } static void _fmpz_mpoly_set_nmod_mpoly_smod( fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx, const nmod_mpoly_t Ap, const nmod_mpoly_ctx_t ctxp) { slong N = mpoly_words_per_exp(Ap->bits, ctxp->minfo); FLINT_ASSERT(ctx->minfo->ord == ctxp->minfo->ord); FLINT_ASSERT(ctx->minfo->nvars == ctxp->minfo->nvars); A->length = 0; fmpz_mpoly_fit_bits(A, Ap->bits, ctx); A->bits = Ap->bits; fmpz_mpoly_fit_length(A, Ap->length, ctx); A->length = Ap->length; mpoly_copy_monomials(A->exps, Ap->exps, Ap->length, N); _fmpz_vec_set_nmod_vec(A->coeffs, Ap->coeffs, Ap->length, ctxp->mod); } static void n_poly_eval_reset(n_poly_t A) { _nmod_vec_set(A->coeffs, A->coeffs + A->length, A->length); } static void n_polyun_eval_reset(n_polyun_t A) { slong Ai; for (Ai = 0; Ai < A->length; Ai++) n_poly_eval_reset(A->coeffs + Ai); } static void n_bpoly_mod_eval_step( n_bpoly_t E, n_polyun_t EH, const nmod_mpoly_t A, nmod_t ctx) { slong i, n, Ai; mp_limb_t * p; mp_limb_t c; ulong e0, e1; slong EHlen = EH->length; Ai = 0; n_bpoly_zero(E); for (i = 0; i < EHlen; i++) { n = EH->coeffs[i].length; p = EH->coeffs[i].coeffs; FLINT_ASSERT(EH->coeffs[i].alloc >= 2*n); FLINT_ASSERT(Ai + n <= A->length); c = _nmod_zip_eval_step(p + 0*n, p + 1*n, A->coeffs + Ai, n, ctx); Ai += n; e0 = extract_exp(EH->exps[i], 1, 2); e1 = extract_exp(EH->exps[i], 0, 2); if (c == 0) continue; n_bpoly_set_coeff_nonzero(E, e0, e1, c); } FLINT_ASSERT(Ai == A->length); } /* n_polyun_t Beh has all x0^i*x1^j*poly(x2, ...) with coeffs triples suitable for sequential eval at x2,... = beta^i n_polyun_t H has x0^i*x1^j*poly(x2, ...) with i < deg_x0(B[i]) with the monomial evals at beta in the coeffs n_polyun_t M has x0^i*x1^j*poly(x2, ...) with i < deg_x0(B[i]) the master poly of H[x0^i*x1^j] in the coeff n_polyun_t Z has x0^i*x1^j with i < deg_x0(B[i]) ready to collect images */ static int fmpz_mfactor_lift_prime_power_zippel( slong r, fmpz_mpoly_struct * B, flint_rand_t state, const nmod_mpoly_struct * Bp, const fmpz_mpoly_t A, const mp_limb_t * alphap, const fmpz_mpoly_ctx_t ctx, const nmod_mpoly_ctx_t ctxp, slong L) { slong req_zip_images, cur_zip_image, this_images; slong n = ctxp->minfo->nvars; int success; slong i, j, k; n_polyun_struct * H, * M, * Z, * Beh; n_bpoly_struct * Ceval, * Beval, Teval[1]; slong * Cdegs1; nmod_mpoly_t Tp; n_polyun_t Teh; fmpz_t pk; n_poly_struct * beta_caches; fmpz_mpoly_t e, t1, t2; FLINT_ASSERT(r > 1); FLINT_ASSERT(ctxp->mod.n > 3); fmpz_init(pk); fmpz_mpoly_init(e, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); nmod_mpoly_init(Tp, ctxp); n_polyun_init(Teh); Cdegs1 = FLINT_ARRAY_ALLOC(r, slong); beta_caches = FLINT_ARRAY_ALLOC(3*n, n_poly_struct); for (i = 0; i < 3*n; i++) n_poly_init(beta_caches + i); Beh = FLINT_ARRAY_ALLOC(r, n_polyun_struct); H = FLINT_ARRAY_ALLOC(r, n_polyun_struct); M = FLINT_ARRAY_ALLOC(r, n_polyun_struct); Z = FLINT_ARRAY_ALLOC(r, n_polyun_struct); Ceval = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); Beval = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); for (i = 0; i < r; i++) { n_polyun_init(Beh + i); n_polyun_init(H + i); n_polyun_init(M + i); n_polyun_init(Z + i); n_bpoly_init(Ceval + i); n_bpoly_init(Beval + i); } n_bpoly_init(Teval); /* init done */ /* choose betas */ for (i = 2; i < n; i++) { mp_limb_t bb = n_urandint(state, ctxp->mod.n - 3) + 2; nmod_pow_cache_start(bb, beta_caches + 3*i + 0, beta_caches + 3*i + 1, beta_caches + 3*i + 2); } req_zip_images = 1; for (i = 0; i < r; i++) { if (Bp[i].bits > FLINT_BITS) { success = 0; goto cleanup; } this_images = nmod_mpoly_set_eval_helper_and_zip_form2(Cdegs1 + i, Beh + i, H + i, M + i, Bp + i, beta_caches, ctxp); req_zip_images = FLINT_MAX(req_zip_images, this_images); } for (i = 0; i < r; i++) { n_polyun_fit_length(Z + i, H[i].length); Z[i].length = H[i].length; for (j = 0; j < H[i].length; j++) { Z[i].exps[j] = H[i].exps[j]; n_poly_fit_length(Z[i].coeffs + j, req_zip_images); Z[i].coeffs[j].length = 0; } } fmpz_one(pk); k = 1; next_power: fmpz_mul_ui(pk, pk, ctxp->mod.n); fmpz_mpoly_mul(t1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { fmpz_mpoly_mul(t2, t1, B + i, ctx); fmpz_mpoly_swap(t1, t2, ctx); } fmpz_mpoly_sub(e, A, t1, ctx); if (fmpz_mpoly_is_zero(e, ctx)) { success = 1; goto cleanup; } if (k > L || e->bits > FLINT_BITS) { success = 0; goto cleanup; } _fmpz_mpoly_modpk_taylor_coeff(pk, Tp, ctxp, e, ctx); nmod_mpoly_get_eval_helper2(Teh, Tp, beta_caches, ctxp); if (fmpz_cmp_ui(pk, ctxp->mod.n) > 0) { for (i = 0; i < r; i++) n_polyun_eval_reset(Beh + i); } cur_zip_image = 0; next_zip_image: n_bpoly_mod_eval_step(Teval, Teh, Tp, ctxp->mod); for (i = 0; i < r; i++) n_bpoly_mod_eval_step(Beval + i, Beh + i, Bp + i, ctxp->mod); success = n_bpoly_mod_pfrac(r, Ceval, Cdegs1, Teval, Beval, ctxp->mod); if (success < 1) { success = 0; goto cleanup; } for (i = 0; i < r; i++) { success = n_polyu2n_add_zip_must_match(Z + i, Ceval + i, cur_zip_image); if (!success) { success = 0; goto cleanup; } } cur_zip_image++; if (cur_zip_image < req_zip_images) goto next_zip_image; for (i = 0; i < r; i++) { success = _fmpz_mpoly_modpk_update_zip(pk, B + i, ctx, Z + i, H + i, M + i, ctxp); if (success < 1) { success = 0; goto cleanup; } } goto next_power; cleanup: fmpz_clear(pk); fmpz_mpoly_clear(e, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); nmod_mpoly_clear(Tp, ctxp); n_polyun_clear(Teh); flint_free(Cdegs1); for (i = 0; i < 3*n; i++) n_poly_clear(beta_caches + i); flint_free(beta_caches); for (i = 0; i < r; i++) { n_polyun_clear(Beh + i); n_polyun_clear(H + i); n_polyun_clear(M + i); n_polyun_clear(Z + i); n_bpoly_clear(Ceval + i); n_bpoly_clear(Beval + i); } flint_free(Beh); flint_free(H); flint_free(M); flint_free(Z); flint_free(Ceval); flint_free(Beval); n_bpoly_clear(Teval); FLINT_ASSERT(success == 0 || success == 1); return success; } /* return 1: success 0: failed -1: exception large exponents */ int fmpz_mpoly_factor_irred_zippel( fmpz_mpolyv_t fac, const fmpz_mpoly_t A, const fmpz_mpoly_factor_t lcAfac, int lcAfac_irred, const fmpz_mpoly_t lcA, const fmpz_mpoly_ctx_t ctx, flint_rand_t state, zassenhaus_prune_t zas) { int success, kfails_left = 4; const slong n = ctx->minfo->nvars - 1; slong i, j, k; fmpz * alpha; fmpz_mpoly_struct * Aevals; slong * degs, * tdegs; fmpz_mpolyv_t tfac; fmpz_mpoly_t t, Acopy; fmpz_mpoly_struct * newA; fmpz_poly_t Au; fmpz_poly_factor_t Aufac; slong alpha_bits, alpha_count; fmpz_mpoly_t m, mpow; fmpz_mpolyv_t Alc, lc_divs; fmpz_t q, facBound; mp_limb_t p; nmod_mpoly_ctx_t ctxp; nmod_mpolyv_t facp, tfacp; nmod_mpolyv_t Aevalp, Alcp; nmod_poly_t Aup; mp_limb_t * alphap; slong r, L; FLINT_ASSERT(n > 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(fmpz_mpoly_factor_matches(lcA, lcAfac, ctx)); fmpz_init(facBound); fmpz_init(q); fmpz_mpoly_init(Acopy, ctx); fmpz_mpoly_init(m, ctx); fmpz_mpoly_init(mpow, ctx); fmpz_mpolyv_init(Alc, ctx); fmpz_mpolyv_init(lc_divs, ctx); fmpz_poly_factor_init(Aufac); fmpz_poly_init(Au); alpha = _fmpz_vec_init(n); alphap = (mp_limb_t *) flint_malloc(n*sizeof(mp_limb_t)); degs = (slong *) flint_malloc(2*(n + 1)*sizeof(slong)); tdegs = degs + (n + 1); Aevals = (fmpz_mpoly_struct *) flint_malloc(n*sizeof(fmpz_mpoly_struct)); for (i = 0; i < n; i++) fmpz_mpoly_init(Aevals + i, ctx); fmpz_mpolyv_init(tfac, ctx); fmpz_mpoly_init(t, ctx); nmod_mpoly_ctx_init(ctxp, n + 1, ORD_LEX, 2); /* modulus no care */ nmod_mpolyv_init(facp, ctxp); nmod_mpolyv_init(tfacp, ctxp); nmod_mpolyv_init(Aevalp, ctxp); nmod_mpolyv_init(Alcp, ctxp); nmod_poly_init_mod(Aup, ctxp->mod); /* init done */ fmpz_mpoly_degrees_si(degs, A, ctx); alpha_count = 0; alpha_bits = 10; p = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); next_alpha: alpha_count++; if (alpha_count >= alpha_bits) { alpha_count = 0; alpha_bits++; if (alpha_bits > FLINT_BITS/2) { success = 0; goto cleanup; } } for (i = 0; i < n; i++) { ulong l = n_randlimb(state); ulong mask = UWORD(1) << alpha_bits; if (l & mask) fmpz_neg_ui(alpha + i, 1 + (l & (mask - 1))); else fmpz_set_ui(alpha + i, 1 + (l & (mask - 1))); } #if FLINT_WANT_ASSERT fmpz_mpoly_degrees_si(tdegs, A, ctx); for (i = 0; i < n + 1; i++) FLINT_ASSERT(degs[i] == tdegs[i]); #endif for (i = n - 1; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fmpz_mpoly_degrees_si(tdegs, Aevals + i, ctx); for (j = 0; j <= i; j++) { if (tdegs[j] != degs[j]) goto next_alpha; } } success = fmpz_mpoly_get_fmpz_poly(Au, Aevals + 0, 0, ctx); FLINT_ASSERT(success); fmpz_poly_factor(Aufac, Au); r = Aufac->num; zassenhaus_prune_start_add_factors(zas); for (j = 0; j < r; j++) zassenhaus_prune_add_factor(zas, fmpz_poly_degree(Aufac->p + j), Aufac->exp[j]); zassenhaus_prune_end_add_factors(zas); if ((r < 2 && Aufac->exp[0] == 1) || zassenhaus_prune_must_be_irreducible(zas)) { fmpz_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fmpz_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } for (j = 0; j < r; j++) { if (Aufac->exp[j] != 1) goto next_alpha; } fmpz_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = 0; if (lcAfac_irred) success = fmpz_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, &Aufac->c, Aufac->p, r, alpha, ctx); if (!success) { success = fmpz_mpoly_factor_lcc_kaltofen(lc_divs->coeffs, lcAfac, A, r, alpha, degs, Aufac, ctx); if (success < 0 || (success == 0 && --kfails_left >= 0)) goto next_alpha; } } else { for (i = 0; i < r; i++) { FLINT_ASSERT(Aufac->p[i].length > 0); fmpz_mpoly_set_fmpz(lc_divs->coeffs + i, Aufac->p[i].coeffs + Aufac->p[i].length - 1, ctx); } } FLINT_ASSERT(r > 1); if (!fmpz_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx)) goto next_alpha; for (i = 1; i < r; i++) { if (!fmpz_mpoly_divides(m, m, lc_divs->coeffs + i, ctx)) goto next_alpha; } fmpz_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fmpz_mpoly_is_one(mpow, ctx)) { newA = (fmpz_mpoly_struct *) A; } else { newA = Acopy; fmpz_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = -1; goto cleanup; } fmpz_mpoly_degrees_si(tdegs, newA, ctx); for (i = 0; i < n + 1; i++) { if (FLINT_BIT_COUNT(tdegs[i]) >= FLINT_BITS/3) { success = -1; goto cleanup; } } _fmpz_vec_height(facBound, newA->coeffs, newA->length); if (!fmpz_mpoly_factor_bound_si(facBound, facBound, tdegs, n + 1)) { success = -1; goto cleanup; } fmpz_mul_2exp(facBound, facBound, 1); fmpz_add_ui(facBound, facBound, 1); fmpz_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(t, mpow, i + 1, alpha + i, ctx); fmpz_mpoly_swap(t, mpow, ctx); fmpz_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); } fmpz_mpolyv_fit_length(Alc, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fmpz_mpoly_mul(Alc->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mpoly_evaluate_one_fmpz(Alc->coeffs + i*r + j, Alc->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fmpz_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { FLINT_ASSERT(fmpz_mpoly_is_fmpz(Alc->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fmpz_mpoly_length(Alc->coeffs + 0*r + i, ctx) == 1); FLINT_ASSERT(fmpz_divisible(Alc->coeffs[i].coeffs + 0, Aufac->p[i].coeffs + Aufac->p[i].length - 1)); fmpz_divexact(q, Alc->coeffs[i].coeffs + 0, Aufac->p[i].coeffs + Aufac->p[i].length - 1); _fmpz_mpoly_set_fmpz_poly(fac->coeffs + i, newA->bits, Aufac->p[i].coeffs, Aufac->p[i].length, 0, ctx); fmpz_mpoly_scalar_mul_fmpz(fac->coeffs + i, fac->coeffs + i, q, ctx); } next_zip_prime: if (p >= UWORD_MAX_PRIME) { success = 0; goto cleanup; } p = n_nextprime(p, 1); if ((p % 4) != 1 && p < UWORD_MAX_PRIME) { p = n_nextprime(p, 1); if ((p % 4) != 1 && p < UWORD_MAX_PRIME) { p = n_nextprime(p, 1); } } nmod_mpoly_ctx_set_modulus(ctxp, p); nmod_mpolyv_fit_length(facp, r, ctxp); nmod_mpolyv_fit_length(tfacp, r, ctxp); facp->length = r; tfacp->length = r; nmod_mpolyv_fit_length(Aevalp, n + 1, ctxp); nmod_mpolyv_fit_length(Alcp, (n + 1)*r, ctxp); for (i = 0; i < r; i++) { _nmod_mpoly_set_fmpz_mpoly(facp->coeffs + i, ctxp, fac->coeffs + i, ctx); if (facp->coeffs[i].length != fac->coeffs[i].length) goto next_zip_prime; } Aup->mod = ctxp->mod; fmpz_poly_get_nmod_poly(Aup, Au); if (Aup->length != Au->length || !nmod_poly_is_squarefree(Aup)) goto next_zip_prime; for (k = 0; k <= n; k++) { _nmod_mpoly_set_fmpz_mpoly(Aevalp->coeffs + k, ctxp, k < n ? Aevals + k : newA, ctx); if (Aevalp->coeffs[k].length != (k < n ? Aevals + k : newA)->length) goto next_zip_prime; for (i = 0; i < r; i++) { _nmod_mpoly_set_fmpz_mpoly(Alcp->coeffs + k*r + i, ctxp, Alc->coeffs + k*r + i, ctx); if (Alcp->coeffs[k*r + i].length != Alc->coeffs[k*r + i].length) goto next_zip_prime; } } for (i = 0; i < n; i++) { alphap[i] = fmpz_get_nmod(alpha + i, ctxp->mod); if (alphap[i] == 0) goto next_zip_prime; } for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _nmod_mpoly_set_lead0(tfacp->coeffs + i, facp->coeffs + i, Alcp->coeffs + k*r + i, ctxp); } if (k > 2) { success = nmod_mpoly_hlift_zippel(k, tfacp->coeffs, r, alphap, Aevalp->coeffs + k, tdegs, ctxp, state); } else { success = nmod_mpoly_hlift(k, tfacp->coeffs, r, alphap, Aevalp->coeffs + k, tdegs, ctxp); } if (!success) goto next_alpha; nmod_mpolyv_swap(tfacp, facp, ctxp); } fmpz_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { _fmpz_mpoly_set_nmod_mpoly_smod(fac->coeffs + i, ctx, facp->coeffs + i, ctxp); _fmpz_mpoly_set_lead0(fac->coeffs + i, fac->coeffs + i, Alc->coeffs + n*r + i, ctx); } L = fmpz_clog_ui(facBound, ctxp->mod.n); success = fmpz_mfactor_lift_prime_power_zippel(r, fac->coeffs, state, facp->coeffs, newA, alphap, ctx, ctxp, L); if (!success) goto next_alpha; if (fmpz_mpoly_is_fmpz(m, ctx)) { for (i = 0; i < r; i++) { _fmpz_vec_content(q, fac->coeffs[i].coeffs, fac->coeffs[i].length); if (fmpz_sgn(fac->coeffs[i].coeffs + 0) < 0) fmpz_neg(q, q); fmpz_mpoly_scalar_divexact_fmpz(fac->coeffs + i, fac->coeffs + i, q, ctx); } } else { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!fmpz_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fmpz_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); fmpz_mpoly_unit_normalize(fac->coeffs, ctx); } } success = 1; cleanup: fmpz_clear(facBound); fmpz_clear(q); fmpz_mpoly_clear(Acopy, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_clear(mpow, ctx); fmpz_mpolyv_clear(Alc, ctx); fmpz_mpolyv_clear(lc_divs, ctx); fmpz_poly_factor_clear(Aufac); fmpz_poly_clear(Au); _fmpz_vec_clear(alpha, n); flint_free(alphap); flint_free(degs); /* and tdegs */ for (i = 0; i < n; i++) fmpz_mpoly_clear(Aevals + i, ctx); flint_free(Aevals); fmpz_mpolyv_clear(tfac, ctx); fmpz_mpoly_clear(t, ctx); nmod_mpolyv_clear(facp, ctxp); nmod_mpolyv_clear(tfacp, ctxp); nmod_mpolyv_clear(Aevalp, ctxp); nmod_mpolyv_clear(Alcp, ctxp); nmod_poly_clear(Aup); nmod_mpoly_ctx_clear(ctxp); return success; } flint-3.1.3/src/fmpz_mpoly_factor/lcc_kaltofen.c000066400000000000000000000452171461254215100217550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" static void fmpz_mpoly_convert_perm( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t Actx, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t Bctx, const slong * perm) { slong n = Bctx->minfo->nvars; slong m = Actx->minfo->nvars; slong i, k, l; slong NA, NB; ulong * Aexps; ulong * Bexps; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(B->length > 0); TMP_START; Aexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, Actx->minfo); NB = mpoly_words_per_exp(B->bits, Bctx->minfo); fmpz_mpoly_fit_length_reset_bits(A, B->length, Abits, Actx); A->length = B->length; for (i = 0; i < B->length; i++) { fmpz_set(A->coeffs + i, B->coeffs + i); mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, Bctx->minfo); for (k = 0; k < m; k++) { l = perm[k]; Aexps[k] = l < 0 ? 0 : Bexps[l]; } mpoly_set_monomial_ui(A->exps + NA*i, Aexps, Abits, Actx->minfo); } TMP_END; fmpz_mpoly_sort_terms(A, Actx); } static int fmpz_mpoly_evaluate_except_two( fmpz_bpoly_t e, const fmpz_mpoly_t A, const fmpz * alphas, slong v, const fmpz_mpoly_ctx_t ctx) { int success; slong i; fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_set(t, A, ctx); for (i = 1; i < ctx->minfo->nvars; i++) { if (i == v) continue; if (!fmpz_mpoly_evaluate_one_fmpz(t, t, i, alphas + i - 1, ctx)) { success = 0; goto cleanup; } } fmpz_mpoly_get_bpoly(e, t, 0, v, ctx); success = 1; cleanup: fmpz_mpoly_clear(t, ctx); return success; } int fmpz_mpoly_evaluate_rest_except_one( fmpz_poly_t e, const fmpz_mpoly_t A, const fmpz * alphas, slong v, const fmpz_mpoly_ctx_t ctx) { int success; slong i; fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_set(t, A, ctx); for (i = 1; i < ctx->minfo->nvars; i++) { if (i == v) continue; if (!fmpz_mpoly_evaluate_one_fmpz(t, t, i, alphas + i - 1, ctx)) { success = 0; goto cleanup; } } success = fmpz_mpoly_is_fmpz_poly(t, v, ctx) && fmpz_mpoly_get_fmpz_poly(e, t, v, ctx); cleanup: fmpz_mpoly_clear(t, ctx); return success; } static void _make_bases_coprime( fmpz_poly_factor_t A, fmpz_poly_factor_t B) { slong i, j; slong Alen = A->num; slong Blen = B->num; fmpz_poly_t g; fmpz_poly_init(g); for (i = 0; i < Alen; i++) for (j = 0; j < Blen; j++) { fmpz_poly_gcd(g, A->p + i, B->p + j); if (fmpz_poly_degree(g) > 0) { fmpz_poly_divexact(A->p + i, A->p + i, g); fmpz_poly_divexact(B->p + j, B->p + j, g); fmpz_poly_factor_fit_length(A, A->num + 1); fmpz_poly_set(A->p + A->num, g); A->exp[A->num] = A->exp[i]; A->num++; fmpz_poly_factor_fit_length(B, B->num + 1); fmpz_poly_set(B->p + B->num, g); B->exp[B->num] = B->exp[j]; B->num++; } } for (i = 0; i < A->num; i++) { if (fmpz_poly_degree(A->p + i) > 0) continue; A->num--; fmpz_poly_swap(A->p + i, A->p + A->num); FLINT_SWAP(slong, A->exp[i], A->exp[A->num]); i--; } for (i = 0; i < B->num; i++) { if (fmpz_poly_degree(B->p + i) > 0) continue; B->num--; fmpz_poly_swap(B->p + i, B->p + B->num); FLINT_SWAP(slong, B->exp[i], B->exp[B->num]); i--; } fmpz_poly_clear(g); } void fmpz_poly_vector_insert_poly(fmpz_bpoly_t v, const fmpz_poly_t a) { slong i; for (i = 0; i < v->length; i++) if (fmpz_poly_equal(v->coeffs + i, a)) return; fmpz_bpoly_fit_length(v, v->length + 1); fmpz_poly_set(v->coeffs + v->length, a); v->length++; } void fmpz_poly_factor_print_pretty(fmpz_poly_factor_t f, const char * x) { slong i; fmpz_print(&f->c); for (i = 0; i < f->num; i++) { flint_printf("*("); fmpz_poly_print_pretty(f->p + i, x); flint_printf(")^%wd", f->exp[i]); } } static int _try_lift( fmpz_mpoly_struct * lifts, /* length r */ const fmpz_mpoly_t A, fmpz_poly_struct * Auf, /* length r */ slong r, const fmpz * alphas, slong v, const fmpz_mpoly_ctx_t Actx) { int success; slong i, k; slong mvars, nvars = Actx->minfo->nvars; slong * Adegs, * Bdegs, * perm, * iperm; fmpz * Balphas; slong dummyvars[1]; ulong dummydegs[1]; fmpz_mpoly_t lcA, At, newA; fmpz_mpoly_ctx_t Bctx; flint_bitcnt_t Bbits; fmpz_mpoly_t Bt; fmpz_mpolyv_t fac, tfac; fmpz_mpoly_struct * Bevals, * Blcevals; fmpz_mpoly_univar_t u; fmpz_t q; FLINT_ASSERT(0 < v && v < nvars); if (r < 2) { FLINT_ASSERT(r == 1); fmpz_mpoly_init(At, Actx); fmpz_mpoly_univar_init(u, Actx); fmpz_mpoly_to_univar(u, A, v, Actx); success = _fmpz_mpoly_vec_content_mpoly(At, u->coeffs, u->length, Actx); if (success) { success = fmpz_mpoly_divides(lifts + 0, A, At, Actx); FLINT_ASSERT(success); fmpz_mpoly_unit_normalize(lifts + 0, Actx); } fmpz_mpoly_clear(At, Actx); fmpz_mpoly_univar_clear(u, Actx); return success; } Adegs = FLINT_ARRAY_ALLOC(nvars, slong); Bdegs = FLINT_ARRAY_ALLOC(nvars, slong); perm = FLINT_ARRAY_ALLOC(nvars, slong); iperm = FLINT_ARRAY_ALLOC(nvars, slong); fmpz_init(q); fmpz_mpoly_init(lcA, Actx); fmpz_mpoly_init(At, Actx); fmpz_mpoly_init(newA, Actx); dummyvars[0] = v; dummydegs[0] = fmpz_mpoly_degree_si(A, v, Actx); fmpz_mpoly_get_coeff_vars_ui(lcA, A, dummyvars, dummydegs, 1, Actx); fmpz_mpoly_pow_ui(At, lcA, r - 1, Actx); fmpz_mpoly_mul(newA, A, At, Actx); if (newA->bits >= FLINT_BITS) { success = 0; goto cleanup_less; } fmpz_mpoly_degrees_si(Adegs, newA, Actx); perm[0] = v; mvars = 1; for (i = 0; i < nvars; i++) { if (i == v) continue; iperm[i] = -1; if (Adegs[i] > 0) { FLINT_ASSERT(i > 0); perm[mvars] = i; mvars++; } } /* TODO following code works if mvars = 1, but add special case? */ fmpz_mpoly_ctx_init(Bctx, mvars, ORD_LEX); fmpz_mpoly_init(Bt, Bctx); fmpz_mpolyv_init(fac, Bctx); fmpz_mpolyv_init(tfac, Bctx); fmpz_mpoly_univar_init(u, Bctx); Balphas = _fmpz_vec_init(nvars); Bevals = FLINT_ARRAY_ALLOC(mvars, fmpz_mpoly_struct); Blcevals = FLINT_ARRAY_ALLOC(mvars, fmpz_mpoly_struct); for (i = 0; i < mvars; i++) { fmpz_mpoly_init(Bevals + i, Bctx); fmpz_mpoly_init(Blcevals + i, Bctx); } Bbits = mpoly_fix_bits(newA->bits, Bctx->minfo); /* invert perm */ for (i = 0; i < mvars; i++) { iperm[perm[i]] = i; Bdegs[i] = Adegs[perm[i]]; if (i > 0) fmpz_set(Balphas + i - 1, alphas + perm[i] - 1); } fmpz_mpoly_convert_perm(Bevals + mvars - 1, Bbits, Bctx, newA, Actx, perm); fmpz_mpoly_convert_perm(Blcevals + mvars - 1, Bbits, Bctx, lcA, Actx, perm); for (i = mvars - 2; i >= 0; i--) { fmpz_mpoly_evaluate_one_fmpz(Bevals + i, Bevals + i + 1, i + 1, Balphas + i, Bctx); fmpz_mpoly_evaluate_one_fmpz(Blcevals + i, Blcevals + i + 1, i + 1, Balphas + i, Bctx); } fmpz_mpolyv_fit_length(fac, r, Bctx); fac->length = r; for (i = 0; i < r; i++) { FLINT_ASSERT(fmpz_mpoly_is_fmpz(Blcevals + 0, Bctx)); FLINT_ASSERT(fmpz_mpoly_length(Blcevals + 0, Bctx) == 1); FLINT_ASSERT(fmpz_divisible(Blcevals[0].coeffs + 0, Auf[i].coeffs + Auf[i].length - 1)); fmpz_divexact(q, Blcevals[0].coeffs + 0, Auf[i].coeffs + Auf[i].length - 1); _fmpz_mpoly_set_fmpz_poly(fac->coeffs + i, Bbits, Auf[i].coeffs, Auf[i].length, 0, Bctx); fmpz_mpoly_scalar_mul_fmpz(fac->coeffs + i, fac->coeffs + i, q, Bctx); } fmpz_mpolyv_fit_length(tfac, r, Bctx); tfac->length = r; for (k = 1; k <= mvars - 1; k++) { for (i = 0; i < r; i++) _fmpz_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, Blcevals + k, Bctx); success = fmpz_mpoly_hlift(k, tfac->coeffs, r, Balphas, Bevals + k, Bdegs, Bctx); if (!success) goto cleanup_more; fmpz_mpolyv_swap(tfac, fac, Bctx); } for (i = 0; i < r; i++) { fmpz_mpoly_to_univar(u, fac->coeffs + i, 0, Bctx); success = _fmpz_mpoly_vec_content_mpoly(Bt, u->coeffs, u->length, Bctx); if (!success) goto cleanup_more; success = fmpz_mpoly_divides(Bt, fac->coeffs + i, Bt, Bctx); FLINT_ASSERT(success); fmpz_mpoly_convert_perm(lifts + i, A->bits, Actx, Bt, Bctx, iperm); fmpz_mpoly_unit_normalize(lifts + i, Actx); } success = 1; cleanup_more: fmpz_mpoly_clear(Bt, Bctx); fmpz_mpolyv_clear(fac, Bctx); fmpz_mpolyv_clear(tfac, Bctx); fmpz_mpoly_univar_clear(u, Bctx); _fmpz_vec_clear(Balphas, nvars); for (i = 0; i < mvars; i++) { fmpz_mpoly_clear(Bevals + i, Bctx); fmpz_mpoly_clear(Blcevals + i, Bctx); } flint_free(Bevals); flint_free(Blcevals); fmpz_mpoly_ctx_clear(Bctx); cleanup_less: flint_free(Adegs); flint_free(Bdegs); flint_free(perm); flint_free(iperm); fmpz_clear(q); fmpz_mpoly_clear(lcA, Actx); fmpz_mpoly_clear(At, Actx); fmpz_mpoly_clear(newA, Actx); return success; } /* assume content(b) = 1 for now */ void fmpz_mpoly_factor_divexact_mpoly_pow_ui( fmpz_mpoly_factor_t A, const fmpz_mpoly_t b_in, ulong e, const fmpz_mpoly_ctx_t ctx) { int sgn; slong i; fmpz_mpoly_t b_copy; fmpz_mpoly_struct * b = (fmpz_mpoly_struct *) b_in; fmpz_mpoly_init(b_copy, ctx); i = 0; /* index strickly before which everything is coprime to b */ while (i < A->num && !fmpz_mpoly_is_fmpz(b, ctx)) { fmpz_mpoly_factor_fit_length(A, A->num + 1, ctx); fmpz_mpoly_gcd_cofactors(A->poly + A->num, A->poly + i, b_copy, A->poly + i, b, ctx); b = b_copy; if (fmpz_mpoly_is_fmpz(A->poly + A->num, ctx)) { i++; continue; } fmpz_sub_ui(A->exp + A->num, A->exp + i, e); sgn = fmpz_sgn(A->exp + A->num); if (sgn < 0) { flint_throw(FLINT_ERROR, "non-exact division fmpz_mpoly_factor_divexact_mpoly_pow_ui"); } else if (sgn > 0) { A->num++; } if (fmpz_mpoly_is_fmpz(A->poly + i, ctx)) { A->num--; fmpz_mpoly_swap(A->poly + i, A->poly + A->num, ctx); fmpz_swap(A->exp + i, A->exp + A->num); } else { i++; } } if (!fmpz_mpoly_is_fmpz(b, ctx)) { flint_throw(FLINT_ERROR, "non-exact division fmpz_mpoly_factor_divexact_mpoly_pow_ui"); } fmpz_mpoly_clear(b_copy, ctx); } int fmpz_mpoly_factor_lcc_kaltofen_step( fmpz_mpoly_struct * divs, /* length r */ slong r, fmpz_mpoly_factor_t Af, /* squarefree factorization of A */ const fmpz_poly_struct * Au, slong v, /* minor bivar var*/ const fmpz * alphas, const fmpz_mpoly_ctx_t ctx) { int success; slong i, j, k, Af_deg_v; fmpz_poly_factor_struct * Auf; fmpz_mpoly_t Afp, tt; fmpz_mpolyv_t lfp; fmpz_bpoly_t f; fmpz_poly_t t, fp; fmpz_mpoly_init(Afp, ctx); fmpz_mpoly_init(tt, ctx); fmpz_bpoly_init(f); fmpz_poly_init(fp); fmpz_poly_init(t); fmpz_mpolyv_init(lfp, ctx); Auf = FLINT_ARRAY_ALLOC(r, fmpz_poly_factor_struct); for (i = 0; i < r; i++) { fmpz_poly_factor_init(Auf + i); fmpz_poly_factor_squarefree(Auf + i, Au + i); } Af_deg_v = 0; fmpz_mpoly_one(Afp, ctx); for (i = 0; i < Af->num; i++) { slong this_degree = fmpz_mpoly_degree_si(Af->poly + i, v, ctx); Af_deg_v += this_degree; /* we don't need to introduce needless content into Afp */ if (this_degree != 0) fmpz_mpoly_mul(Afp, Afp, Af->poly + i, ctx); } if (!fmpz_mpoly_evaluate_rest_except_one(t, Afp, alphas, v, ctx) || fmpz_poly_degree(t) < 1 || fmpz_poly_degree(t) != Af_deg_v) { success = 0; goto cleanup; } for (i = 0; i < r - 1; i++) for (j = i + 1; j < r; j++) _make_bases_coprime(Auf + i, Auf + j); f->length = 0; for (i = 0; i < r; i++) for (j = 0; j < Auf[i].num; j++) fmpz_poly_vector_insert_poly(f, Auf[i].p + j); fmpz_poly_primitive_part(t, t); fmpz_poly_one(fp); for (i = 0; i < f->length; i++) fmpz_poly_mul(fp, fp, f->coeffs + i); success = fmpz_poly_equal(fp, t); if (!success) goto cleanup; fmpz_mpolyv_fit_length(lfp, f->length, ctx); lfp->length = f->length; success = _try_lift(lfp->coeffs, Afp, f->coeffs, f->length, alphas, v, ctx); if (!success) goto cleanup; for (i = 0; i < r; i++) { fmpz_poly_factor_struct * auf = Auf + i; for (j = 0; j < auf->num; j++) { for (k = 0; k < f->length; k++) { if (fmpz_poly_equal(f->coeffs + k, auf->p + j)) { fmpz_mpoly_factor_divexact_mpoly_pow_ui(Af, lfp->coeffs + k, auf->exp[j], ctx); fmpz_mpoly_pow_ui(tt, lfp->coeffs + k, auf->exp[j], ctx); fmpz_mpoly_mul(divs + i, divs + i, tt, ctx); } } } } success = 1; cleanup: fmpz_mpoly_clear(Afp, ctx); fmpz_mpoly_clear(tt, ctx); fmpz_bpoly_clear(f); fmpz_poly_clear(fp); fmpz_poly_clear(t); fmpz_mpolyv_clear(lfp, ctx); for (i = 0; i < r; i++) fmpz_poly_factor_clear(Auf + i); flint_free(Auf); return success; } /* return 1: lcc is probably correct and complete 0: lcc is incomplete -1: alphas are definitely bad */ int fmpz_mpoly_factor_lcc_kaltofen( fmpz_mpoly_struct * divs, const fmpz_mpoly_factor_t lcAf_, const fmpz_mpoly_t A, slong r, const fmpz * alphas, slong * degs, const fmpz_poly_factor_t uf, const fmpz_mpoly_ctx_t ctx) { int success; slong i, v, nvars = ctx->minfo->nvars; fmpz_mpoly_factor_t lcAf; fmpz_poly_struct * ulcs; fmpz_tpoly_struct * bfacs; fmpz_bpoly_t beval; fmpz_poly_t bcont, ut2; fmpz_t g1, g2, g3; fmpz * content_divs; FLINT_ASSERT(r > 1); fmpz_mpoly_factor_init(lcAf, ctx); fmpz_mpoly_factor_set(lcAf, lcAf_, ctx); fmpz_init(g1); fmpz_init(g2); fmpz_init(g3); content_divs = _fmpz_vec_init(r); fmpz_poly_init(ut2); fmpz_poly_init(bcont); fmpz_bpoly_init(beval); bfacs = FLINT_ARRAY_ALLOC(nvars, fmpz_tpoly_struct); for (i = 0; i < nvars; i++) fmpz_tpoly_init(bfacs + i); ulcs = FLINT_ARRAY_ALLOC(r, fmpz_poly_struct); for (i = 0; i < r; i++) { fmpz_poly_init(ulcs + i); fmpz_mpoly_one(divs + i, ctx); } for (v = 1; v < nvars; v++) { fmpz_mpoly_evaluate_except_two(beval, A, alphas, v, ctx); FLINT_ASSERT(fmpz_bpoly_degree0(beval) == degs[0]); if (fmpz_bpoly_degree1(beval) != degs[v]) { bfacs[v].length = 0; goto continue_outer; } success = fmpz_bpoly_factor_ordered(bcont, bfacs + v, beval, alphas + v - 1, uf); if (success < 1) { if (success == 0) { success = -1; goto cleanup; } bfacs[v].length = 0; goto continue_outer; } for (i = 0; i < r; i++) { fmpz_mpoly_evaluate_rest_except_one(ut2, divs + i, alphas, v, ctx); if (fmpz_poly_is_zero(ut2)) { bfacs[v].length = 0; goto continue_outer; } fmpz_poly_primitive_part(ut2, ut2); if (!fmpz_poly_divides(ulcs + i, fmpz_bpoly_lead(bfacs[v].coeffs + i), ut2)) { bfacs[v].length = 0; goto continue_outer; } } fmpz_mpoly_factor_lcc_kaltofen_step(divs, r, lcAf, ulcs, v, alphas, ctx); continue_outer:; } if (lcAf->num == 0) { for (i = 0; i < r; i++) fmpz_one(content_divs + i); for (v = 1; v < nvars; v++) { if (bfacs[v].length != r) continue; for (i = 0; i < r; i++) { fmpz_poly_struct * ut1 = fmpz_bpoly_lead(bfacs[v].coeffs + i); fmpz_mpoly_evaluate_rest_except_one(ut2, divs + i, alphas, v, ctx); _fmpz_vec_content(g1, ut1->coeffs, ut1->length); _fmpz_vec_content(g2, ut2->coeffs, ut2->length); fmpz_gcd(g3, g1, g2); fmpz_divexact(g1, g1, g3); fmpz_lcm(content_divs + i, content_divs + i, g1); } } for (i = 0; i < r; i++) { if (!fmpz_divisible(lcAf->constant, content_divs + i)) continue; fmpz_divexact(lcAf->constant, lcAf->constant, content_divs + i); fmpz_mpoly_scalar_mul_fmpz(divs + i, divs + i, content_divs + i, ctx); } success = 1; } else { success = 0; } cleanup: fmpz_mpoly_factor_clear(lcAf, ctx); fmpz_clear(g1); fmpz_clear(g2); fmpz_clear(g3); _fmpz_vec_clear(content_divs, r); fmpz_poly_clear(ut2); fmpz_poly_clear(bcont); fmpz_bpoly_clear(beval); for (i = 0; i < nvars; i++) fmpz_tpoly_clear(bfacs + i); flint_free(bfacs); for (i = 0; i < r; i++) fmpz_poly_clear(ulcs + i); flint_free(ulcs); return success; } flint-3.1.3/src/fmpz_mpoly_factor/lcc_wang.c000066400000000000000000000101611461254215100210740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_factor_lcc_wang( fmpz_mpoly_struct * lc_divs, const fmpz_mpoly_factor_t lcAfac, const fmpz_t Auc, const fmpz_poly_struct * Auf, slong r, const fmpz * alpha, const fmpz_mpoly_ctx_t ctx) { int success; slong i, j, k; const slong n = ctx->minfo->nvars - 1; fmpz * lcAfaceval = _fmpz_vec_init(lcAfac->num); fmpz * d = _fmpz_vec_init(1 + lcAfac->num); fmpz * dtilde = _fmpz_vec_init(r); fmpz_t Q, R; fmpz_mpoly_t t; slong N, * offsets, * shifts, * starts, * ends, * stops; ulong mask, * es; fmpz * T; fmpz_init(Q); fmpz_init(R); fmpz_mpoly_init(t, ctx); starts = FLINT_ARRAY_ALLOC(n + 1, slong); ends = FLINT_ARRAY_ALLOC(n + 1, slong); stops = FLINT_ARRAY_ALLOC(n + 1, slong); es = FLINT_ARRAY_ALLOC(n + 1, ulong); T = FLINT_ARRAY_ALLOC(n + 2, fmpz); for (i = 0; i < n + 2; i++) fmpz_init(T + i); offsets = FLINT_ARRAY_ALLOC(n + 1, slong); shifts = FLINT_ARRAY_ALLOC(n + 1, slong); for (j = 0; j < lcAfac->num; j++) { fmpz_mpoly_struct * P = lcAfac->poly + j; for (i = 0; i < n + 1; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, P->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - P->bits); N = mpoly_words_per_exp_sp(P->bits, ctx->minfo); _fmpz_mpoly_evaluate_rest_fmpz(T, starts, ends, stops, es, P->coeffs, P->exps, P->length, 1, alpha, offsets, shifts, N, mask, n + 1); fmpz_set(lcAfaceval + j, T + 0); } fmpz_mul(d + 0, Auc, lcAfac->constant); for (i = 0; i < lcAfac->num; i++) { fmpz_abs(Q, lcAfaceval + i); if (fmpz_is_one(Q) || fmpz_is_zero(Q)) { success = 0; goto cleanup; } for (j = i; j >= 0; j--) { fmpz_set(R, d + j); while (!fmpz_is_one(R)) { fmpz_gcd(R, R, Q); fmpz_divexact(Q, Q, R); if (fmpz_is_one(Q)) { success = 0; goto cleanup; } } } fmpz_set(d + i + 1, Q); } for (j = 0; j < r; j++) { fmpz_mpoly_one(lc_divs + j, ctx); fmpz_one(dtilde + j); fmpz_mul(R, Auf[j].coeffs + Auf[j].length - 1, Auc); for (i = lcAfac->num - 1; i >= 0; i--) { fmpz_abs(Q, lcAfaceval + i); if (fmpz_cmp_ui(Q, 2) < 0) continue; k = fmpz_remove(R, R, Q); fmpz_mpoly_pow_ui(t, lcAfac->poly + i, k, ctx); fmpz_mpoly_mul(lc_divs + j, lc_divs + j, t, ctx); fmpz_pow_ui(Q, lcAfaceval + i, k); fmpz_mul(dtilde + j, dtilde + j, Q); } } for (j = 0; j < r; j++) { FLINT_ASSERT(Auf[j].length > 0); fmpz_gcd(T + 0, Auf[j].coeffs + Auf[j].length - 1, dtilde + j); fmpz_fdiv_qr(Q, R, Auf[j].coeffs + Auf[j].length - 1, T + 0); if (!fmpz_is_zero(R)) { success = 0; goto cleanup; } fmpz_mpoly_scalar_mul_fmpz(lc_divs + j, lc_divs + j, Q, ctx); } success = 1; cleanup: fmpz_clear(Q); fmpz_clear(R); fmpz_mpoly_clear(t, ctx); _fmpz_vec_clear(lcAfaceval, lcAfac->num); _fmpz_vec_clear(d, 1 + lcAfac->num); _fmpz_vec_clear(dtilde, r); for (i = 0; i < n + 2; i++) fmpz_clear(T + i); flint_free(T); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); return success; } flint-3.1.3/src/fmpz_mpoly_factor/misc.c000066400000000000000000000041001461254215100202460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_factor_get_constant_fmpz(fmpz_t c, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { fmpz_set(c, f->constant); } void fmpz_mpoly_factor_get_constant_fmpq(fmpq_t c, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { fmpz_set(fmpq_numref(c), f->constant); fmpz_set(fmpq_denref(c), f->constant_den); } slong fmpz_mpoly_factor_get_exp_si(fmpz_mpoly_factor_t f, slong i, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); return fmpz_get_si(f->exp + i); } void fmpz_mpoly_factor_set_fmpz(fmpz_mpoly_factor_t f, const fmpz_t a, const fmpz_mpoly_ctx_t ctx) { f->num = 0; fmpz_set(f->constant, a); } void fmpz_mpoly_factor_zero(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { f->num = 0; fmpz_zero(f->constant); } void fmpz_mpoly_factor_one(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { f->num = 0; fmpz_one(f->constant); } void fmpz_mpoly_factor_append_fmpz_swap(fmpz_mpoly_factor_t f, fmpz_mpoly_t A, const fmpz_t e, const fmpz_mpoly_ctx_t ctx) { slong i = f->num; fmpz_mpoly_factor_fit_length(f, i + 1, ctx); fmpz_mpoly_swap(f->poly + i, A, ctx); fmpz_set(f->exp + i, e); f->num = i + 1; } void fmpz_mpoly_factor_append_ui(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, ulong e, const fmpz_mpoly_ctx_t ctx) { slong i = f->num; fmpz_mpoly_factor_fit_length(f, i + 1, ctx); fmpz_mpoly_set(f->poly + i, A, ctx); fmpz_set_ui(f->exp + i, e); f->num = i + 1; } void fmpz_mpoly_unit_normalize(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); if (fmpz_sgn(A->coeffs + 0) < 0) fmpz_mpoly_neg(A, A, ctx); } flint-3.1.3/src/fmpz_mpoly_factor/mpoly_hlift.c000066400000000000000000000331611461254215100216520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" static int _hlift_quartic2( slong m, fmpz_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mpoly_t A, const slong * degs, const fmpz_mpoly_ctx_t ctx) { int success, use_Au; slong i, j, Aui; fmpz_mpoly_t Aq, t, t2, t3, xalpha; fmpz_mpoly_univar_t Au; fmpz_mpoly_geobucket_t G; fmpz_mpoly_struct betas[2], * deltas; fmpz_mpoly_pfrac_t I; fmpz_mpolyv_struct B[2]; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r == 2); r = 2; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(t2, ctx); fmpz_mpoly_init(t3, ctx); fmpz_mpoly_init(xalpha, ctx); fmpz_mpoly_init(Aq, ctx); fmpz_mpoly_univar_init(Au, ctx); fmpz_mpoly_geobucket_init(G, ctx); fmpz_mpoly_gen(xalpha, m, ctx); fmpz_mpoly_sub_fmpz(xalpha, xalpha, alpha + m - 1, ctx); fmpz_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (i = 0; i < r; i++) { fmpz_mpolyv_init(B + i, ctx); fmpz_mpoly_repack_bits_inplace(f + i, bits, ctx); fmpz_mpoly_to_mpolyv(B + i, f + i, xalpha, ctx); fmpz_mpolyv_fit_length(B + i, degs[m] + 1, ctx); for (j = B[i].length; j <= degs[m]; j++) fmpz_mpoly_zero(B[i].coeffs + j, ctx); } for (i = 0; i < r; i++) betas[i] = B[i].coeffs[0]; success = fmpz_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; use_Au = fmpz_is_zero(alpha + m - 1); if (use_Au) { fmpz_mpoly_to_univar(Au, A, m, ctx); Aui = Au->length - 1; #if FLINT_WANT_ASSERT fmpz_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fmpz_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(Au->coeffs + Aui, t2, ctx)); #endif FLINT_ASSERT(fmpz_equal_si(Au->exps + Aui, 0)); Aui--; } else { fmpz_mpoly_divrem(t2, t, A, xalpha, ctx); fmpz_mpoly_swap(Aq, t2, ctx); #if FLINT_WANT_ASSERT fmpz_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fmpz_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(t, t2, ctx)); #endif Aui = -1; /* silence warning */ } for (j = 1; j <= degs[m]; j++) { if (use_Au) { if (Aui >= 0 && fmpz_equal_si(Au->exps + Aui, j)) { fmpz_mpoly_geobucket_set(G, Au->coeffs + Aui, ctx); Aui--; } else { G->length = 0; } } else { fmpz_mpoly_divrem(t2, t, Aq, xalpha, ctx); fmpz_mpoly_swap(Aq, t2, ctx); fmpz_mpoly_geobucket_set(G, t, ctx); } for (i = 0; i <= j; i++) { fmpz_mpoly_mul(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx); fmpz_mpoly_geobucket_sub(G, t, ctx); } fmpz_mpoly_geobucket_empty(t, G, ctx); if (fmpz_mpoly_is_zero(t, ctx)) continue; success = fmpz_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fmpz_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fmpz_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fmpz_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } } success = 1; cleanup: fmpz_mpoly_pfrac_clear(I, ctx); for (i = 0; i < r; i++) { if (success) fmpz_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); fmpz_mpolyv_clear(B + i, ctx); } fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_clear(t3, ctx); fmpz_mpoly_clear(xalpha, ctx); fmpz_mpoly_clear(Aq, ctx); fmpz_mpoly_univar_clear(Au, ctx); fmpz_mpoly_geobucket_clear(G, ctx); return success; } static int _hlift_quartic( slong m, fmpz_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mpoly_t A, const slong * degs, const fmpz_mpoly_ctx_t ctx) { int success, use_Au; slong i, j, k, Aui; fmpz_mpoly_t Aq, t, t1, t2, t3, xalpha; fmpz_mpoly_univar_t Au; fmpz_mpoly_geobucket_t G; fmpz_mpoly_struct * betas, * deltas; fmpz_mpoly_pfrac_t I; fmpz_mpolyv_struct * B, * U; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 2); B = FLINT_ARRAY_ALLOC(2*r, fmpz_mpolyv_struct); U = B + r; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); fmpz_mpoly_init(t3, ctx); fmpz_mpoly_init(xalpha, ctx); fmpz_mpoly_init(Aq, ctx); fmpz_mpoly_univar_init(Au, ctx); fmpz_mpoly_geobucket_init(G, ctx); fmpz_mpoly_gen(xalpha, m, ctx); fmpz_mpoly_sub_fmpz(xalpha, xalpha, alpha + m - 1, ctx); fmpz_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (k = 0; k < r; k++) { fmpz_mpolyv_init(U + k, ctx); fmpz_mpolyv_fit_length(U + k, degs[m] + 1, ctx); for (j = 0; j <= degs[m]; j++) fmpz_mpoly_zero(U[k].coeffs + j, ctx); fmpz_mpolyv_init(B + k, ctx); fmpz_mpoly_repack_bits_inplace(f + k, bits, ctx); fmpz_mpoly_to_mpolyv(B + k, f + k, xalpha, ctx); fmpz_mpolyv_fit_length(B + k, degs[m] + 1, ctx); for (j = B[k].length; j <= degs[m]; j++) fmpz_mpoly_zero(B[k].coeffs + j, ctx); } betas = FLINT_ARRAY_ALLOC(r, fmpz_mpoly_struct); for (i = 0; i < r; i++) betas[i] = B[i].coeffs[0]; success = fmpz_mpoly_pfrac_init(I, A->bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success); deltas = I->deltas + (m - 1)*I->r; k = r - 2; fmpz_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k >= 1; k--) fmpz_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx); use_Au = fmpz_is_zero(alpha + m - 1); if (use_Au) { fmpz_mpoly_to_univar(Au, A, m, ctx); Aui = Au->length - 1; #if FLINT_WANT_ASSERT fmpz_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fmpz_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(Au->coeffs + Aui, t2, ctx)); #endif FLINT_ASSERT(fmpz_equal_si(Au->exps + Aui, 0)); Aui--; } else { fmpz_mpoly_divrem(t2, t, A, xalpha, ctx); fmpz_mpoly_swap(Aq, t2, ctx); #if FLINT_WANT_ASSERT fmpz_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fmpz_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fmpz_mpoly_equal(t, t2, ctx)); #endif Aui = -1; /* silence warning */ } for (j = 1; j <= degs[m]; j++) { k = r - 2; G->length = 0; for (i = 0; i <= j; i++) { fmpz_mpoly_mul(t1, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fmpz_mpoly_geobucket_add(G, t1, ctx); } fmpz_mpoly_geobucket_empty(U[k].coeffs + j, G, ctx); for (k--; k >= 1; k--) { G->length = 0; for (i = 0; i <= j; i++) { fmpz_mpoly_mul(t1, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); fmpz_mpoly_geobucket_add(G, t1, ctx); } fmpz_mpoly_geobucket_empty(U[k].coeffs + j, G, ctx); } if (use_Au) { if (Aui >= 0 && fmpz_equal_si(Au->exps + Aui, j)) { fmpz_mpoly_geobucket_set(G, Au->coeffs + Aui, ctx); Aui--; } else { G->length = 0; } } else { fmpz_mpoly_divrem(t2, t, Aq, xalpha, ctx); fmpz_mpoly_swap(Aq, t2, ctx); fmpz_mpoly_geobucket_set(G, t, ctx); } for (i = 0; i <= j; i++) { fmpz_mpoly_mul(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx); fmpz_mpoly_geobucket_sub(G, t, ctx); } fmpz_mpoly_geobucket_empty(t, G, ctx); if (fmpz_mpoly_is_zero(t, ctx)) continue; success = fmpz_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fmpz_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fmpz_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fmpz_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } k = r - 2; fmpz_mpoly_mul(t, B[k].coeffs + 0, deltas + k + 1, ctx); fmpz_mpoly_mul(t1, deltas + k, B[k + 1].coeffs + 0, ctx); fmpz_mpoly_add(t, t, t1, ctx); fmpz_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); for (k--; k >= 1; k--) { fmpz_mpoly_mul(t1, B[k].coeffs + 0, t, ctx); fmpz_mpoly_swap(t, t1, ctx); fmpz_mpoly_mul(t1, deltas + k, U[k + 1].coeffs + 0, ctx); fmpz_mpoly_add(t, t, t1, ctx); fmpz_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } success = 1; cleanup: fmpz_mpoly_pfrac_clear(I, ctx); flint_free(betas); for (i = 0; i < r; i++) { if (success) fmpz_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); fmpz_mpolyv_clear(B + i, ctx); fmpz_mpolyv_clear(U + i, ctx); } flint_free(B); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_clear(t3, ctx); fmpz_mpoly_clear(xalpha, ctx); fmpz_mpoly_clear(Aq, ctx); fmpz_mpoly_univar_clear(Au, ctx); fmpz_mpoly_geobucket_clear(G, ctx); return success; } static int _hlift_quintic( slong m, fmpz_mpoly_struct * f, slong r, const fmpz * alpha, const fmpz_mpoly_t A, const slong * degs, const fmpz_mpoly_ctx_t ctx) { int success; slong i, j; fmpz_mpoly_t e, t, pow, xalpha, q; fmpz_mpoly_struct * betas, * deltas; fmpz_mpoly_pfrac_t I; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 1); fmpz_mpoly_init(e, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(pow, ctx); fmpz_mpoly_init(xalpha, ctx); fmpz_mpoly_init(q, ctx); betas = (fmpz_mpoly_struct *) flint_malloc(r*sizeof(fmpz_mpoly_struct)); for (i = 0; i < r; i++) { fmpz_mpoly_init(betas + i, ctx); fmpz_mpoly_repack_bits_inplace(f + i, bits, ctx); fmpz_mpoly_evaluate_one_fmpz(betas + i, f + i, m, alpha + m - 1, ctx); } fmpz_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fmpz_mpoly_mul(t, t, f + i, ctx); fmpz_mpoly_sub(e, A, t, ctx); fmpz_mpoly_one(pow, ctx); fmpz_mpoly_repack_bits_inplace(pow, bits, ctx); fmpz_mpoly_gen(xalpha, m, ctx); fmpz_mpoly_sub_fmpz(xalpha, xalpha, alpha + m - 1, ctx); fmpz_mpoly_repack_bits_inplace(xalpha, bits, ctx); fmpz_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); deltas = I->deltas + (m - 1)*I->r; for (j = 1; j <= degs[m]; j++) { if (fmpz_mpoly_is_zero(e, ctx)) { success = 1; goto cleanup; } fmpz_mpoly_mul(pow, pow, xalpha, ctx); success = fmpz_mpoly_divides(q, e, pow, ctx); FLINT_ASSERT(success); fmpz_mpoly_evaluate_one_fmpz(t, q, m, alpha + m - 1, ctx); success = fmpz_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } for (i = 0; i < r; i++) { fmpz_mpoly_mul(t, deltas + i, pow, ctx); fmpz_mpoly_add(f + i, f + i, t, ctx); } fmpz_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fmpz_mpoly_mul(t, t, f + i, ctx); fmpz_mpoly_sub(e, A, t, ctx); } success = fmpz_mpoly_is_zero(e, ctx); cleanup: fmpz_mpoly_pfrac_clear(I, ctx); fmpz_mpoly_clear(e, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(pow, ctx); fmpz_mpoly_clear(xalpha, ctx); fmpz_mpoly_clear(q, ctx); for (i = 0; i < r; i++) { if (success) fmpz_mpoly_repack_bits_inplace(f + i, bits, ctx); fmpz_mpoly_clear(betas + i, ctx); } flint_free(betas); return success; } /* should have A = prod_i f[i] mod (gen(m) - alpha[m-1]) */ int fmpz_mpoly_hlift( slong m, fmpz_mpoly_struct * f, /* length r */ slong r, const fmpz * alpha, const fmpz_mpoly_t A, const slong * degs, const fmpz_mpoly_ctx_t ctx) { FLINT_ASSERT(r >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (r == 2) return _hlift_quartic2(m, f, r, alpha, A, degs, ctx); else if (r < 20) return _hlift_quartic(m, f, r, alpha, A, degs, ctx); else return _hlift_quintic(m, f, r, alpha, A, degs, ctx); } flint-3.1.3/src/fmpz_mpoly_factor/mpoly_pfrac.c000066400000000000000000000202731461254215100216370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mpoly_factor.h" int fmpz_mpoly_pfrac_init( fmpz_mpoly_pfrac_t I, flint_bitcnt_t bits, slong r, slong w, const fmpz_mpoly_struct * betas, const fmpz * alpha, const fmpz_mpoly_ctx_t ctx) { slong success = 1; slong i, j, k; FLINT_ASSERT(bits <= FLINT_BITS); I->bits = bits; I->r = r; I->w = w; I->prod_mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mpoly_struct); I->prod_mbetas_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mpolyv_struct); I->mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mpoly_struct); I->deltas = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mpoly_struct); I->xalpha = FLINT_ARRAY_ALLOC(w + 1, fmpz_mpoly_struct); I->q = FLINT_ARRAY_ALLOC(w + 1, fmpz_mpoly_struct); I->U = FLINT_ARRAY_ALLOC(w + 1, fmpz_mpoly_univar_struct); I->G = FLINT_ARRAY_ALLOC(w + 1, fmpz_mpoly_geobucket_struct); I->qt = FLINT_ARRAY_ALLOC(w + 1, fmpz_mpoly_struct); I->newt = FLINT_ARRAY_ALLOC(w + 1, fmpz_mpoly_struct); I->delta_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, fmpz_mpolyv_struct); for (i = 0; i <= w; i++) { fmpz_mpoly_init(I->xalpha + i, ctx); fmpz_mpoly_init(I->q + i, ctx); fmpz_mpoly_univar_init(I->U + i, ctx); fmpz_mpoly_geobucket_init(I->G + i, ctx); fmpz_mpoly_init(I->qt + i, ctx); fmpz_mpoly_init(I->newt + i, ctx); for (j = 0; j < r; j++) { fmpz_mpoly_init(I->deltas + i*r + j, ctx); fmpz_mpolyv_init(I->delta_coeffs + i*r + j, ctx); } if (i < 1) continue; fmpz_mpoly_gen(I->xalpha + i, i, ctx); fmpz_mpoly_sub_fmpz(I->xalpha + i, I->xalpha + i, alpha + i - 1, ctx); fmpz_mpoly_repack_bits_inplace(I->xalpha + i, I->bits, ctx); } /* set betas */ i = w; for (j = 0; j < r; j++) { fmpz_mpoly_init(I->mbetas + i*r + j, ctx); fmpz_mpoly_set(I->mbetas + i*r + j, betas + j, ctx); } for (i--; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mpoly_init(I->mbetas + i*r + j, ctx); fmpz_mpoly_evaluate_one_fmpz(I->mbetas + i*r + j, I->mbetas + (i + 1)*r + j, i + 1, alpha + i, ctx); } } /* set product of betas */ for (i = w; i >= 0; i--) { for (j = 0; j < r; j++) { fmpz_mpoly_init(I->prod_mbetas + i*r + j, ctx); fmpz_mpoly_one(I->prod_mbetas + i*r + j, ctx); for (k = 0; k < r; k++) { if (k == j) continue; fmpz_mpoly_mul(I->prod_mbetas + i*r + j, I->prod_mbetas + i*r + j, I->mbetas + i*r + k, ctx); } fmpz_mpolyv_init(I->prod_mbetas_coeffs + i*r + j, ctx); if (i > 0) { fmpz_mpoly_to_mpolyv(I->prod_mbetas_coeffs + i*r + j, I->prod_mbetas + i*r + j, I->xalpha + i, ctx); } } } fmpz_poly_pfrac_init(I->uni_pfrac); fmpz_poly_init(I->uni_a); I->uni_c = FLINT_ARRAY_ALLOC(r, fmpz_poly_struct); for (j = 0; j < r; j++) { fmpz_poly_init(I->uni_c + j); fmpz_mpoly_get_fmpz_poly(I->uni_c + j, I->mbetas + 0*r + j, 0, ctx); success = success && (fmpz_poly_degree(I->uni_c + j) == fmpz_mpoly_degree_si(betas + j, 0, ctx)); } success = success && fmpz_poly_pfrac_precompute(I->uni_pfrac, I->uni_c, r); if (!success) flint_throw(FLINT_ERROR, "fmpz_mpoly_pfrac_init: internal error"); return success; } void fmpz_mpoly_pfrac_clear( fmpz_mpoly_pfrac_t I, const fmpz_mpoly_ctx_t ctx) { slong i, j; for (i = 0; i <= I->w; i++) { fmpz_mpoly_clear(I->xalpha + i, ctx); fmpz_mpoly_clear(I->q + i, ctx); fmpz_mpoly_univar_clear(I->U + i, ctx); fmpz_mpoly_geobucket_clear(I->G + i, ctx); fmpz_mpoly_clear(I->qt + i, ctx); fmpz_mpoly_clear(I->newt + i, ctx); for (j = 0; j < I->r; j++) fmpz_mpolyv_clear(I->delta_coeffs + i*I->r + j, ctx); } flint_free(I->xalpha); flint_free(I->q); flint_free(I->U); flint_free(I->G); flint_free(I->qt); flint_free(I->newt); flint_free(I->delta_coeffs); for (j = 0; j < I->r; j++) { for (i = 0; i <= I->w; i++) { fmpz_mpolyv_clear(I->prod_mbetas_coeffs + i*I->r + j, ctx); fmpz_mpoly_clear(I->prod_mbetas + i*I->r + j, ctx); fmpz_mpoly_clear(I->mbetas + i*I->r + j, ctx); fmpz_mpoly_clear(I->deltas + i*I->r + j, ctx); } } flint_free(I->prod_mbetas); flint_free(I->prod_mbetas_coeffs); flint_free(I->mbetas); flint_free(I->deltas); fmpz_poly_pfrac_clear(I->uni_pfrac); fmpz_poly_clear(I->uni_a); for (j = 0; j < I->r; j++) fmpz_poly_clear(I->uni_c + j); flint_free(I->uni_c); } int fmpz_mpoly_pfrac( slong l, fmpz_mpoly_t t, const slong * degs, fmpz_mpoly_pfrac_t I, const fmpz_mpoly_ctx_t ctx) { int success, use_U; slong i, j, k, Ui; fmpz_mpoly_struct * deltas = I->deltas + l*I->r; fmpz_mpoly_struct * newdeltas = I->deltas + (l - 1)*I->r; fmpz_mpoly_struct * q = I->q + l; fmpz_mpoly_struct * qt = I->qt + l; fmpz_mpoly_struct * newt = I->newt + l; fmpz_mpolyv_struct * delta_coeffs = I->delta_coeffs + l*I->r; fmpz_mpoly_geobucket_struct * G = I->G + l; fmpz_mpoly_univar_struct * U = I->U + l; FLINT_ASSERT(l >= 0); if (!fmpz_mpoly_repack_bits_inplace(t, I->bits, ctx)) return -1; if (l < 1) { fmpz_mpoly_get_fmpz_poly(I->uni_a, t, 0, ctx); if (!fmpz_poly_pfrac_precomp(I->uni_c, I->uni_a, I->uni_pfrac)) return 0; for (i = 0; i < I->r; i++) _fmpz_mpoly_set_fmpz_poly(deltas + i, I->bits, I->uni_c[i].coeffs, I->uni_c[i].length, 0, ctx); return 1; } for (i = 0; i < I->r; i++) delta_coeffs[i].length = 0; use_U = I->xalpha[l].length == 1; if (use_U) fmpz_mpoly_to_univar(U, t, l, ctx); Ui = U->length - 1; for (k = 0; k <= degs[l]; k++) { if (use_U) { if (Ui >= 0 && fmpz_equal_si(U->exps + Ui, k)) { fmpz_mpoly_geobucket_set(G, U->coeffs + Ui, ctx); Ui--; } else { G->length = 0; } } else { fmpz_mpoly_divrem(q, newt, t, I->xalpha + l, ctx); fmpz_mpoly_swap(t, q, ctx); fmpz_mpoly_geobucket_set(G, newt, ctx); } for (j = 0; j < k; j++) for (i = 0; i < I->r; i++) { if (j >= delta_coeffs[i].length) continue; if (k - j >= I->prod_mbetas_coeffs[l*I->r + i].length) continue; fmpz_mpoly_mul(qt, delta_coeffs[i].coeffs + j, I->prod_mbetas_coeffs[l*I->r + i].coeffs + k - j, ctx); fmpz_mpoly_geobucket_sub(G, qt, ctx); } fmpz_mpoly_geobucket_empty(newt, G, ctx); if (fmpz_mpoly_is_zero(newt, ctx)) continue; success = fmpz_mpoly_pfrac(l - 1, newt, degs, I, ctx); if (success < 1) return success; for (i = 0; i < I->r; i++) { if (fmpz_mpoly_is_zero(newdeltas + i, ctx)) continue; if (k + I->prod_mbetas_coeffs[l*I->r + i].length - 1 > degs[l]) return 0; fmpz_mpolyv_set_coeff(delta_coeffs + i, k, newdeltas + i, ctx); } } for (i = 0; i < I->r; i++) fmpz_mpoly_from_mpolyv(deltas + i, I->bits, delta_coeffs + i, I->xalpha + l, ctx); return 1; } flint-3.1.3/src/fmpz_mpoly_factor/mpolyl.c000066400000000000000000000034271461254215100206420ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_to_mpolyl_perm_deflate( fmpz_mpoly_t A, const fmpz_mpoly_ctx_t lctx, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { fmpz_mpoly_fit_length(A, B->length, ctx); mpoly_to_mpolyl_perm_deflate(A->exps, A->bits, lctx->minfo, B->exps, B->bits, ctx->minfo, B->length, perm, shift, stride); _fmpz_vec_set(A->coeffs, B->coeffs, B->length); _fmpz_mpoly_set_length(A, B->length, lctx); fmpz_mpoly_sort_terms(A, lctx); FLINT_ASSERT(fmpz_mpoly_is_canonical(A, lctx)); } void fmpz_mpoly_from_mpolyl_perm_inflate( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride) { fmpz_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); _fmpz_vec_set(A->coeffs, B->coeffs, B->length); mpoly_from_mpolyl_perm_inflate(A->exps, Abits, ctx->minfo, B->exps, B->bits, lctx->minfo, B->length, perm, shift, stride); _fmpz_mpoly_set_length(A, B->length, ctx); fmpz_mpoly_sort_terms(A, ctx); FLINT_ASSERT(fmpz_mpoly_is_canonical(A, ctx)); } flint-3.1.3/src/fmpz_mpoly_factor/mpolyv.c000066400000000000000000000111571461254215100206530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void fmpz_mpolyv_clear(fmpz_mpolyv_t A, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fmpz_mpoly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } void fmpz_mpolyv_print_pretty( const fmpz_mpolyv_t poly, const char ** x, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < poly->length; i++) { flint_printf("coeff[%wd]: ", i); fmpz_mpoly_print_pretty(poly->coeffs + i, x, ctx); flint_printf("\n"); } } void fmpz_mpolyv_fit_length( fmpz_mpolyv_t A, slong length, const fmpz_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length <= old_alloc) return; if (old_alloc > 0) { A->coeffs = (fmpz_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fmpz_mpoly_struct)); } else { A->coeffs = (fmpz_mpoly_struct *) flint_malloc( new_alloc*sizeof(fmpz_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) fmpz_mpoly_init(A->coeffs + i, ctx); A->alloc = new_alloc; } void fmpz_mpolyv_set_coeff( fmpz_mpolyv_t A, slong i, fmpz_mpoly_t c, /* clobbered */ const fmpz_mpoly_ctx_t ctx) { slong j; FLINT_ASSERT(!fmpz_mpoly_is_zero(c, ctx)); fmpz_mpolyv_fit_length(A, i + 1, ctx); for (j = A->length; j < i; j++) fmpz_mpoly_zero(A->coeffs + j, ctx); fmpz_mpoly_swap(A->coeffs + i, c, ctx); A->length = FLINT_MAX(A->length, i + 1); } void fmpz_mpoly_to_mpolyv( fmpz_mpolyv_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t xalpha, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_t Q, T; fmpz_mpoly_init(Q, ctx); fmpz_mpoly_init(T, ctx); fmpz_mpolyv_fit_length(A, 8, ctx); fmpz_mpoly_divrem(Q, A->coeffs + 0, B, xalpha, ctx); A->length = 1; while (!fmpz_mpoly_is_zero(Q, ctx)) { fmpz_mpolyv_fit_length(A, A->length + 1, ctx); fmpz_mpoly_divrem(T, A->coeffs + A->length, Q, xalpha, ctx); fmpz_mpoly_swap(Q, T, ctx); A->length++; } while (A->length > 0 && fmpz_mpoly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; fmpz_mpoly_clear(Q, ctx); fmpz_mpoly_clear(T, ctx); } void fmpz_mpoly_from_mpolyv( fmpz_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mpolyv_t B, const fmpz_mpoly_t xalpha, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz_mpoly_t T; fmpz_mpoly_init(T, ctx); fmpz_mpoly_zero(A, ctx); for (i = B->length - 1; i >= 0; i--) { fmpz_mpoly_mul(T, A, xalpha, ctx); fmpz_mpoly_add(A, T, B->coeffs + i, ctx); } fmpz_mpoly_clear(T, ctx); fmpz_mpoly_repack_bits_inplace(A, Abits, ctx); } int _fmpz_mpoly_vec_content_mpoly( fmpz_mpoly_t g, const fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_ctx_t ctx) { slong i, j1, j2; if (Alen <= 1) { if (Alen == 1 && A[0].length > 0) { if (fmpz_sgn(A[0].coeffs + 0) < 0) fmpz_mpoly_neg(g, A + 0, ctx); else fmpz_mpoly_set(g, A + 0, ctx); } else { fmpz_mpoly_zero(g, ctx); } return 1; } j1 = 0; j2 = 1; for (i = 2; i < Alen; i++) { if (A[i].length < A[j1].length) j1 = i; else if (A[i].length < A[j2].length) j2 = i; } FLINT_ASSERT(j1 != j2); if (!fmpz_mpoly_gcd(g, A + j1, A + j2, ctx)) return 0; for (i = 0; i < Alen; i++) { if (i == j1 || i == j2) continue; if (!fmpz_mpoly_gcd(g, g, A + i, ctx)) return 0; } return 1; } void _fmpz_mpoly_vec_divexact_mpoly( fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) fmpz_mpoly_divexact(A + i, A + i, c, ctx); } void _fmpz_mpoly_vec_mul_mpoly( fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) fmpz_mpoly_mul(A + i, A + i, c, ctx); } flint-3.1.3/src/fmpz_mpoly_factor/poly_pfrac.c000066400000000000000000000276151461254215100214710ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mpoly_factor.h" /* return n with ||a||_2 < 2^n */ static flint_bitcnt_t fmpz_poly_norm2_bits(const fmpz_poly_t a) { fmpz_t t; flint_bitcnt_t bits; fmpz_init(t); _fmpz_vec_dot(t, a->coeffs, a->coeffs, a->length); bits = fmpz_bits(t); fmpz_clear(t); return (bits + 1)/2; } /* reduce A mod B, return new length of A */ static slong _reduce_inplace( fmpz * Acoeffs, slong Alen, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx, fmpz_mod_poly_t Q, /* temps */ fmpz_mod_poly_t R) { slong Blen = B->length; fmpz * Bcoeffs = B->coeffs; fmpz * Qcoeffs, * Rcoeffs; if (Alen < Blen) return Alen; FLINT_ASSERT(Blen > 1); fmpz_mod_poly_fit_length(Q, Alen - Blen + 1, ctx); fmpz_mod_poly_fit_length(R, Blen - 1, ctx); Qcoeffs = Q->coeffs; Rcoeffs = R->coeffs; while (Alen >= Blen) { slong n = FLINT_MAX(0, (Alen-1) - 2*(Blen-1) + 1); slong Qlen = (Alen-1) - n - (Blen-1) + 1; FLINT_ASSERT(Qlen < Blen); _fmpz_mod_poly_div_newton_n_preinv(Qcoeffs + n, Acoeffs + n, Alen - n, Bcoeffs, Blen, Binv->coeffs, Binv->length, ctx); _fmpz_mod_poly_mullow(Rcoeffs, Bcoeffs, Blen - 1, Qcoeffs + n, Qlen, Blen - 1, ctx); _fmpz_mod_vec_sub(Acoeffs + n, Acoeffs + n, Rcoeffs, Blen - 1, ctx); Alen = n + Blen - 1; while (Alen > 0 && fmpz_is_zero(Acoeffs + Alen - 1)) Alen--; } return Alen; } void fmpz_poly_pfrac_init(fmpz_poly_pfrac_t I) { I->r = 0; I->bits = NULL; I->b = I->bprod = NULL; I->B = I->invBprod = I->inwBprod = I->B_inv = NULL; I->ctxs = NULL; I->halfpks = NULL; fmpz_poly_init(I->a); fmpz_poly_init(I->newa); fmpz_poly_init(I->t); fmpz_init(I->old_pk); fmpz_init(I->pk); fmpz_init(I->p); fmpz_mod_ctx_init_ui(I->ctxp, 2); fmpz_mod_poly_init(I->T, I->ctxp); fmpz_mod_poly_init(I->R, I->ctxp); fmpz_mod_poly_init(I->Q, I->ctxp); } static void _clear_arrays(fmpz_poly_pfrac_t I) { slong i; for (i = 0; i < I->r; i++) { fmpz_poly_clear(I->b + i); fmpz_poly_clear(I->bprod + i); fmpz_mod_poly_clear(I->B + i, I->ctxs + i); fmpz_mod_poly_clear(I->invBprod + i, I->ctxs + i); fmpz_mod_poly_clear(I->inwBprod + i, I->ctxs + i); fmpz_mod_poly_clear(I->B_inv + i, I->ctxs + i); fmpz_clear(I->halfpks + i); fmpz_mod_ctx_clear(I->ctxs + i); } flint_free(I->halfpks); flint_free(I->ctxs); flint_free(I->bits); flint_free(I->b); flint_free(I->B); I->r = 0; } void fmpz_poly_pfrac_clear(fmpz_poly_pfrac_t I) { _clear_arrays(I); fmpz_poly_clear(I->a); fmpz_poly_clear(I->newa); fmpz_poly_clear(I->t); fmpz_clear(I->old_pk); fmpz_clear(I->pk); fmpz_clear(I->p); fmpz_mod_poly_clear(I->T, I->ctxp); fmpz_mod_poly_clear(I->R, I->ctxp); fmpz_mod_poly_clear(I->Q, I->ctxp); fmpz_mod_ctx_clear(I->ctxp); } int fmpz_poly_pfrac_precompute( fmpz_poly_pfrac_t I, const fmpz_poly_struct * b, slong r) { slong i; if (r < 2) return 0; for (i = 0; i < r; i++) { if (fmpz_poly_degree(b + i) < 1) return 0; } _clear_arrays(I); I->r = r; I->bits = FLINT_ARRAY_ALLOC(r, flint_bitcnt_t); I->ctxs = FLINT_ARRAY_ALLOC(r, fmpz_mod_ctx_struct); I->halfpks = FLINT_ARRAY_ALLOC(r, fmpz); for (i = 0; i < r; i++) { fmpz_init(I->halfpks + i); fmpz_mod_ctx_init_ui(I->ctxs + i, 2); } I->b = FLINT_ARRAY_ALLOC(2*r, fmpz_poly_struct); I->bprod = I->b + r; for (i = 0; i < r; i++) { fmpz_poly_init(I->bprod + i); fmpz_poly_init(I->b + i); fmpz_poly_set(I->b + i, b + i); } I->B = FLINT_ARRAY_ALLOC(4*r, fmpz_mod_poly_struct); I->invBprod = I->B + r; I->inwBprod = I->invBprod + r; I->B_inv = I->inwBprod + r; for (i = 0; i < r; i++) { fmpz_mod_poly_init(I->B + i, I->ctxs + i); fmpz_mod_poly_init(I->invBprod + i, I->ctxs + i); fmpz_mod_poly_init(I->inwBprod + i, I->ctxs + i); fmpz_mod_poly_init(I->B_inv + i, I->ctxs + i); } /* init done */ fmpz_poly_one(I->bprod + r - 1); for (i = r - 2; i >= 0; i--) { fmpz_poly_mul(I->bprod + i, I->bprod + i + 1, I->b + i + 1); I->bits[i] = (fmpz_poly_degree(I->b + i) - 1)* fmpz_poly_norm2_bits(I->bprod + i); I->bits[i] += fmpz_poly_degree(I->bprod + i)* fmpz_poly_norm2_bits(I->b + i); fmpz_poly_resultant(I->pk, I->bprod + i, I->b + i); if (fmpz_is_zero(I->pk)) return 0; if (n_sub_checked(&I->bits[i], I->bits[i] + 2, fmpz_bits(I->pk))) I->bits[i] = 1; } fmpz_set_ui(I->p, UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX)); next_p: fmpz_nextprime(I->p, I->p, 1); fmpz_mod_ctx_set_modulus(I->ctxp, I->p); fmpz_set(I->pk, I->p); for (i = 0; i < r; i++) { /* B[i] = make_monic(b[i] mod p^k) */ fmpz_mod_poly_set_fmpz_poly(I->B + i, I->b + i, I->ctxp); if (I->B[i].length != I->b[i].length) goto next_p; fmpz_mod_poly_make_monic(I->B + i, I->B + i, I->ctxp); fmpz_mod_poly_reverse(I->B_inv + i, I->B + i, I->B[i].length, I->ctxp); fmpz_mod_poly_inv_series(I->B_inv + i, I->B_inv + i, I->B[i].length, I->ctxp); } for (i = 0; i < r; i++) { fmpz_mod_poly_set_fmpz_poly(I->T, I->bprod + i, I->ctxp); fmpz_mod_poly_xgcd(I->R, I->invBprod + i, I->inwBprod + i, I->T, I->B + i, I->ctxp); if (!fmpz_mod_poly_is_one(I->R, I->ctxp)) goto next_p; /* now 1 = invBprod[i]*bprod[i] + inwBprod[i]*B[i] mod p^k */ } /* set all ctx's to mod p*/ for (i = 0; i < r; i++) { fmpz_mod_ctx_set_modulus(I->ctxs + i, I->p); fmpz_fdiv_q_2exp(I->halfpks + i, fmpz_mod_ctx_modulus(I->ctxs + i), 1); } return 1; } /* set di = deg(Bi) when solving for the Ci given A and Bi in A/(B1*B2) = C1/B1 + C2/B2 the coefficients of C2 and C1 come from a sylvester system with B1 in the first d2 columns and B2 in the next d1 columns and the coefficients of A on the rhs. Therefore cramer + hadamard ||C2||_infty <= ||B1||_2^(d2-1) * ||B2||_2^d1 * ||A||_2 / |res(B1,B2)| ||C1||_infty <= ||B2||_2^(d1-1) * ||B1||_2^d2 * ||A||_2 / |res(B1,B2)| suppose ||B2||_2^(d1-1) * ||B1||_2^d2 / |res(B1,B2)| < 2^n and ||A||_2 < 2^a Assume fmpz_bits(p^k) > n + 1 + a. Then, p^k/2 >= 2^(n + a). If C1 (correct mod p^k with coeffs <= p^k/2 in abs) does not pass the divisibility test, then C1 does not exist. divisibility test is: C2 = (A - B2*C1)/B1 */ int fmpz_poly_pfrac_precomp( fmpz_poly_struct * c, const fmpz_poly_t A, fmpz_poly_pfrac_t I) { slong i, clen; const fmpz_poly_struct * a; again: a = A; for (i = 0; i + 1 < I->r; i++) { /* T = a mod B[i] */ fmpz_mod_poly_set_fmpz_poly(I->T, a, I->ctxs + i); I->T->length = _reduce_inplace(I->T->coeffs, I->T->length, I->B + i, I->B_inv + i, I->ctxs + i, I->Q, I->R); /* c = T*invBprod[i] */ if (I->T->length < 1) { clen = 0; } else { FLINT_ASSERT(I->invBprod[i].length > 0); clen = I->T->length + I->invBprod[i].length - 1; fmpz_poly_fit_length(c + i, clen); _fmpz_mod_poly_mul(c[i].coeffs, I->T->coeffs, I->T->length, I->invBprod[i].coeffs, I->invBprod[i].length, I->ctxs + i); while (clen > 0 && fmpz_is_zero(c[i].coeffs + clen - 1)) clen--; } /* c = c smod B[i] */ clen = _reduce_inplace(c[i].coeffs, clen, I->B + i, I->B_inv + i, I->ctxs + i, I->Q, I->R); c[i].length = clen; while (--clen >= 0) { if (fmpz_cmp(c[i].coeffs + clen, I->halfpks + i) > 0) { fmpz_sub(c[i].coeffs + clen, c[i].coeffs + clen, fmpz_mod_ctx_modulus(I->ctxs + i)); } } /* now divisibility test */ fmpz_poly_mul(I->t, c + i, I->bprod + i); fmpz_poly_sub(I->t, a, I->t); if (!fmpz_poly_divides(I->newa, I->t, I->b + i)) { flint_bitcnt_t abits = fmpz_poly_norm2_bits(a); flint_bitcnt_t pkbits = fmpz_bits(fmpz_mod_ctx_modulus(I->ctxs + i)); if (pkbits > abits && pkbits - abits > I->bits[i]) return 0; goto more_prec; } a = I->a; fmpz_poly_swap(I->a, I->newa); } FLINT_ASSERT(a == I->a); fmpz_poly_swap(c + i, I->a); return 1; more_prec: /* increase the precision of the i^th factor only */ fmpz_set(I->old_pk, fmpz_mod_ctx_modulus(I->ctxs + i)); fmpz_pow_ui(I->pk, I->p, 1 + fmpz_bits(I->old_pk)/512); fmpz_mul(I->halfpks + i, fmpz_mod_ctx_modulus(I->ctxs + i), I->pk); fmpz_mod_ctx_set_modulus(I->ctxs + i, I->halfpks + i); fmpz_fdiv_q_2exp(I->halfpks + i, fmpz_mod_ctx_modulus(I->ctxs + i), 1); fmpz_mod_poly_set_fmpz_poly(I->T, I->bprod + i, I->ctxs + i); /* lift_only_inverses wants monic bases */ fmpz_mod_poly_scalar_div_fmpz(I->T, I->T, fmpz_poly_lead(I->bprod + i), I->ctxs + i); fmpz_mod_poly_scalar_mul_fmpz(I->invBprod + i, I->invBprod + i, fmpz_poly_lead(I->bprod + i), I->ctxs + i); fmpz_mod_poly_set_fmpz_poly(I->B + i, I->b + i, I->ctxs + i); fmpz_mod_poly_make_monic(I->B + i, I->B + i, I->ctxs + i); fmpz_mod_poly_fit_length(I->invBprod + i, I->B[i].length - 1, I->ctxs + i); fmpz_mod_poly_fit_length(I->inwBprod + i, I->T->length - 1, I->ctxs + i); _fmpz_poly_hensel_lift_only_inverse( I->invBprod[i].coeffs, I->inwBprod[i].coeffs, I->T->coeffs, I->T->length, I->B[i].coeffs, I->B[i].length, I->invBprod[i].coeffs, I->invBprod[i].length, I->inwBprod[i].coeffs, I->inwBprod[i].length, I->old_pk, I->pk); I->invBprod[i].length = I->B[i].length - 1; _fmpz_mod_poly_normalise(I->invBprod + i); I->inwBprod[i].length = I->T->length - 1; _fmpz_mod_poly_normalise(I->inwBprod + i); /* correct monic bases */ fmpz_mod_poly_scalar_mul_fmpz(I->T, I->T, fmpz_poly_lead(I->bprod + i), I->ctxs + i); /* Need not be reduced after Hensel lifting, but we have to reduce it before subsequently calling fmpz_mod_poly functions */ if (!fmpz_mod_poly_is_canonical(I->invBprod + i, I->ctxs + i)) { _fmpz_mod_vec_set_fmpz_vec((I->invBprod + i)->coeffs, (I->invBprod + i)->coeffs, (I->invBprod + i)->length, I->ctxs + i); _fmpz_mod_poly_normalise(I->invBprod + i); } fmpz_mod_poly_scalar_div_fmpz(I->invBprod + i, I->invBprod + i, fmpz_poly_lead(I->bprod + i), I->ctxs + i); fmpz_mod_poly_reverse(I->B_inv + i, I->B + i, I->B[i].length, I->ctxs + i); fmpz_mod_poly_inv_series(I->B_inv + i, I->B_inv + i, I->B[i].length, I->ctxs + i); goto again; } flint-3.1.3/src/fmpz_mpoly_factor/print_pretty.c000066400000000000000000000014511461254215100220640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_factor_print_pretty(const fmpz_mpoly_factor_t f, const char ** vars, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz_print(f->constant); for (i = 0; i < f->num; i++) { flint_printf("*(", i); fmpz_mpoly_print_pretty(f->poly + i, vars, ctx); flint_printf(")^"); fmpz_print(f->exp + i); } } flint-3.1.3/src/fmpz_mpoly_factor/profile/000077500000000000000000000000001461254215100206145ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly_factor/profile/p-factor.c000066400000000000000000000167321461254215100225040ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "fmpz_mpoly_factor.h" slong check_omega(slong om, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { slong i; fmpz_mpoly_factor_t g; fmpz_t omega; timeit_t timer; fmpz_init(omega); fmpz_mpoly_factor_init(g, ctx); timeit_start(timer); if (!fmpz_mpoly_factor(g, p, ctx)) { flint_printf("oops! could not factor\n"); flint_abort(); } timeit_stop(timer); fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, om) != 0) { flint_printf("factorization has wrong number of factors\n"); flint_abort(); } fmpz_mpoly_factor_clear(g, ctx); fmpz_clear(omega); return timer->wall; } int main(int argc, char *argv[]) { slong i, j, k; slong time, total_time; flint_printf("\n------ 2 variables ------\n"); { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t p; const char * vars[] = {"a", "b"}; fmpz_mpoly_ctx_init(ctx, 2, ORD_LEX); fmpz_mpoly_init(p, ctx); fmpz_mpoly_set_str_pretty(p, "(800*a^21+2800*a^20+3360*a^19+1680*a^18*b+280*a^18+5040*a^17*b-5670*a^17+5768*a^16*b-13601*a^16+1232*a^15*b^2+2296*a^15*b-22337*a^15+3080*a^14*b^2-3367*a^14*b-30393*a^14+3332*a^13*b^2-9653*a^13*b-38185*a^13+280*a^12*b^3+2058*a^12*b^2-14553*a^12*b-40775*a^12+560*a^11*b^3+784*a^11*b^2-18011*a^11*b-33243*a^11+546*a^10*b^3+392*a^10*b^2-20027*a^10*b-22078*a^10-70*a^9*b^4+336*a^9*b^3+1372*a^9*b^2-16779*a^9*b-13223*a^9-105*a^8*b^4+371*a^8*b^3+1701*a^8*b^2-9933*a^8*b-4865*a^8-119*a^7*b^4+700*a^7*b^3+945*a^7*b^2-3507*a^7*b+2575*a^7-35*a^6*b^5-147*a^6*b^4+1029*a^6*b^3+1127*a^6*b^2+2450*a^6*b+8288*a^6-35*a^5*b^5-147*a^5*b^4+749*a^5*b^3+2401*a^5*b^2+7350*a^5*b+10318*a^5-35*a^4*b^5-147*a^4*b^4+469*a^4*b^3+3675*a^4*b^2+9128*a^4*b+5866*a^4-35*a^3*b^5-147*a^3*b^4+483*a^3*b^3+4067*a^3*b^2+7784*a^3*b+651*a^3-35*a^2*b^5-77*a^2*b^4+693*a^2*b^3+3087*a^2*b^2+3808*a^2*b-273*a^2-35*a*b^5-42*a*b^4+658*a*b^3+1526*a*b^2+434*a*b+105*a+b^7-35*b^5-28*b^4+329*b^3+434*b^2-329*b-79)*" "(800*a^21+2800*a^20+5712*a^19+1680*a^18*b+8512*a^18+5040*a^17*b+10304*a^17+9296*a^16*b+11340*a^16+1232*a^15*b^2+13272*a^15*b+11816*a^15+3080*a^14*b^2+16184*a^14*b+11208*a^14+5096*a^13*b^2+18816*a^13*b+8120*a^13+280*a^12*b^3+7056*a^12*b^2+20776*a^12*b+2884*a^12+560*a^11*b^3+8624*a^11*b^2+20062*a^11*b-2030*a^11+840*a^10*b^3+10339*a^10*b^2+15988*a^10*b-4977*a^10-70*a^9*b^4+1218*a^9*b^3+11662*a^9*b^2+10122*a^9*b-5824*a^9-105*a^8*b^4+1498*a^8*b^3+10913*a^8*b^2+4816*a^8*b-5600*a^8-119*a^7*b^4+1827*a^7*b^3+9030*a^7*b^2+952*a^7*b-5510*a^7-35*a^6*b^5-98*a^6*b^4+2058*a^6*b^3+6909*a^6*b^2-2009*a^6*b-4403*a^6-35*a^5*b^5-98*a^5*b^4+1778*a^5*b^3+4949*a^5*b^2-3969*a^5*b-2079*a^5-35*a^4*b^5-98*a^4*b^4+1498*a^4*b^3+3381*a^4*b^2-4935*a^4*b+35*a^4-35*a^3*b^5-98*a^3*b^4+1218*a^3*b^3+1666*a^3*b^2-4221*a^3*b+1190*a^3-35*a^2*b^5-28*a^2*b^4+840*a^2*b^3+343*a^2*b^2-2611*a^2*b+1001*a^2-35*a*b^5+7*a*b^4+560*a*b^3-140*a*b^2-1281*a*b+301*a+b^7-35*b^5+21*b^4+231*b^3-105*b^2-329*b+19)*" "(800*a^21+2800*a^20-952*a^19+1680*a^18*b-14028*a^18+5040*a^17*b-13804*a^17+476*a^16*b+11144*a^16+1232*a^15*b^2-12208*a^15*b+22106*a^15+3080*a^14*b^2-14294*a^14*b+4005*a^14+1862*a^13*b^2-5194*a^13*b+917*a^13+280*a^12*b^3-735*a^12*b^2-5978*a^12*b+26845*a^12+560*a^11*b^3-1176*a^11*b^2-15610*a^11*b+46137*a^11+889*a^10*b^3-1323*a^10*b^2-16254*a^10*b+32606*a^10-70*a^9*b^4+1267*a^9*b^3-3773*a^9*b^2-1050*a^9*b-2345*a^9-105*a^8*b^4+1596*a^8*b^3-7805*a^8*b^2+18046*a^8*b-15547*a^8+28*a^7*b^4+1631*a^7*b^3-11109*a^7*b^2+21434*a^7*b+1693*a^7-35*a^6*b^5+98*a^6*b^4+1715*a^6*b^3-10094*a^6*b^2+12397*a^6*b+2800*a^6-35*a^5*b^5+98*a^5*b^4+1435*a^5*b^3-7497*a^5*b^2+13181*a^5*b-19376*a^5-35*a^4*b^5+98*a^4*b^4+1155*a^4*b^3-7056*a^4*b^2+21133*a^4*b-25592*a^4-35*a^3*b^5+98*a^3*b^4+826*a^3*b^3-6909*a^3*b^2+18417*a^3*b-12285*a^3-35*a^2*b^5+168*a^2*b^4+448*a^2*b^3-4459*a^2*b^2+7777*a^2*b-2282*a^2-35*a*b^5+203*a*b^4+119*a*b^3-1659*a*b^2+1365*a*b-42*a+b^7-35*b^5+70*b^4+84*b^3-203*b^2+63*b+19)" , vars, ctx); time = check_omega(3, p, ctx); flint_printf("#%wd: %wd\n", 0, time); fmpz_mpoly_clear(p, ctx); fmpz_mpoly_ctx_clear(ctx); } flint_printf("\n------ 4 variables ------\n"); total_time = 0; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, c; const char * vars[] = {"x", "y", "z", "t"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(c, ctx); for (i = 0; i <= 20; i++) { fmpz_mpoly_set_str_pretty(a, "x", vars, ctx); fmpz_mpoly_set_str_pretty(b, "y", vars, ctx); fmpz_mpoly_set_str_pretty(c, "1+x+y+z+t", vars, ctx); fmpz_mpoly_pow_ui(c, c, i, ctx); fmpz_mpoly_add(a, a, c, ctx); fmpz_mpoly_add(b, b, c, ctx); fmpz_mpoly_mul(a, a, b, ctx); k = (i > 0); for (j = 1; j <= i; j++) if ((j%2) != 0 && (i%j) == 0) k++; k = 2; time = check_omega(k, a, ctx); flint_printf("#%wd: %wd\n", i, time); total_time += time; } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(c, ctx); fmpz_mpoly_ctx_clear(ctx); } flint_printf("total_time: %wd\n", total_time); flint_printf("\n------ 5 variables ------\n"); total_time = 0; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a; const char * vars[] = {"s0", "s1", "s2", "s3", "s4"}; const slong omegas[] = {2, 4, 1, 1}; const char * polys[] = {"s1^6*s2^3-6*s0*s1^5*s2^2*s3+12*s0^2*s1^4*s2*s3^2-8*s0^3*s1^3*s3^3+3*s0^2*s1^4*s2^2*s4-12*s0^3*s1^3*s2*s3*s4+12*s0^4*s1^2*s3^2*s4+3*s0^4*s1^2*s2*s4^2-6*s0^5*s1*s3*s4^2+s0^6*s4^3+4*s1^4*s2^2*s3^2-16*s0*s1^3*s2*s3^3+16*s0^2*s1^2*s3^4-4*s1^4*s2^3*s4+16*s0*s1^3*s2^2*s3*s4-8*s0^2*s1^2*s2*s3^2*s4-16*s0^3*s1*s3^3*s4-8*s0^2*s1^2*s2^2*s4^2+16*s0^3*s1*s2*s3*s4^2+4*s0^4*s3^2*s4^2-4*s0^4*s2*s4^3+3*s1^2*s2*s3^4-6*s0*s1*s3^5-6*s1^2*s2^2*s3^2*s4+12*s0*s1*s2*s3^3*s4+3*s0^2*s3^4*s4+3*s1^2*s2^3*s4^2-6*s0*s1*s2^2*s3*s4^2-6*s0^2*s2*s3^2*s4^2+3*s0^2*s2^2*s4^3-2*s3^6+6*s2*s3^4*s4-6*s2^2*s3^2*s4^2+2*s2^3*s4^3", "s3^8-4*s2*s3^6*s4+6*s2^2*s3^4*s4^2-4*s2^3*s3^2*s4^3+s2^4*s4^4", "s1^4*s2^2-4*s0*s1^3*s2*s3+4*s0^2*s1^2*s3^2+2*s0^2*s1^2*s2*s4-4*s0^3*s1*s3*s4+s0^4*s4^2+2*s1^2*s2*s3^2-4*s0*s1*s3^3-2*s1^2*s2^2*s4+4*s0*s1*s2*s3*s4+2*s0^2*s3^2*s4-2*s0^2*s2*s4^2-s3^4+2*s2*s3^2*s4-s2^2*s4^2", "s1^4-2*s1^2*s4-s4^2"}; fmpz_mpoly_ctx_init(ctx, 5, ORD_LEX); fmpz_mpoly_init(a, ctx); for (i = 0; i < 4; i++) { fmpz_mpoly_set_str_pretty(a, polys[i], vars, ctx); time = check_omega(omegas[i], a, ctx); flint_printf("#%wd: %wd ms\n", i, time); total_time += time; } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } flint_printf("total_time: %wd\n", total_time); flint_cleanup_master(); return 0; } flint-3.1.3/src/fmpz_mpoly_factor/realloc.c000066400000000000000000000036661461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_factor_realloc(fmpz_mpoly_factor_t f, slong alloc, const fmpz_mpoly_ctx_t ctx) { slong i; if (alloc <= 0) { fmpz_mpoly_factor_clear(f, ctx); fmpz_mpoly_factor_init(f, ctx); return; } if (f->alloc > 0) { if (f->alloc > alloc) { for (i = alloc; i < f->alloc; i++) { fmpz_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fmpz_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fmpz_mpoly_struct)); } else if (f->alloc < alloc) { f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fmpz_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fmpz_mpoly_struct)); for (i = f->alloc; i < alloc; i++) { fmpz_mpoly_init(f->poly + i, ctx); fmpz_init(f->exp + i); } } } else { f->exp = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); f->poly = (fmpz_mpoly_struct *) flint_malloc(alloc * sizeof(fmpz_mpoly_struct)); for (i = 0; i < alloc; i++) fmpz_mpoly_init(f->poly + i, ctx); } f->alloc = alloc; } flint-3.1.3/src/fmpz_mpoly_factor/set.c000066400000000000000000000015261461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void fmpz_mpoly_factor_set( fmpz_mpoly_factor_t A, const fmpz_mpoly_factor_t B, const fmpz_mpoly_ctx_t ctx) { slong i; if (A == B) return; fmpz_mpoly_factor_fit_length(A, B->num, ctx); fmpz_set(A->constant, B->constant); for (i = 0; i < B->num; i++) { fmpz_mpoly_set(A->poly + i, B->poly + i, ctx); fmpz_set(A->exp + i, B->exp + i); } A->num = B->num; } flint-3.1.3/src/fmpz_mpoly_factor/sort.c000066400000000000000000000034651461254215100203170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fmpz_mpoly_factor.h" typedef struct { slong idx; fmpz exp; const fmpz_mpoly_struct * polys; const fmpz_mpoly_ctx_struct * ctx; } sort_struct; static int _sort(const void * a_, const void * b_) { int cmp; const sort_struct * a = (const sort_struct *) a_; const sort_struct * b = (const sort_struct *) b_; const fmpz_mpoly_struct * apoly = a->polys + a->idx; const fmpz_mpoly_struct * bpoly = b->polys + b->idx; cmp = fmpz_cmp(&a->exp, &b->exp); if (cmp != 0) return cmp; return fmpz_mpoly_cmp(apoly, bpoly, a->ctx); } void fmpz_mpoly_factor_sort( fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { slong i; sort_struct * data; fmpz_mpoly_struct * fc; if (f->num < 1) return; data = (sort_struct *) flint_malloc(f->num*sizeof(sort_struct)); for (i = 0; i < f->num; i++) { data[i].idx = i; data[i].exp = f->exp[i]; data[i].polys = f->poly; data[i].ctx = ctx; } qsort(data, f->num, sizeof(sort_struct), _sort); /* we will not permute in place */ fc = (fmpz_mpoly_struct *) flint_malloc(f->num*sizeof(fmpz_mpoly_struct)); memcpy(fc, f->poly, f->num*sizeof(fmpz_mpoly_struct)); for (i = 0; i < f->num; i++) { f->exp[i] = data[i].exp; f->poly[i] = fc[data[i].idx]; } flint_free(fc); flint_free(data); } flint-3.1.3/src/fmpz_mpoly_factor/test/000077500000000000000000000000001461254215100201335ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly_factor/test/main.c000066400000000000000000000032411461254215100212230ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor.c" #include "t-factor_content.c" #include "t-factor_squarefree.c" #include "t-factor_wang.c" #include "t-factor_zassenhaus.c" #include "t-factor_zippel.c" #include "t-gcd_brown.c" #include "t-gcd_brown_threaded.c" #include "t-gcd_subresultant.c" #include "t-gcd_zippel2.c" #include "t-gcd_zippel.c" #include "t-lcc_kaltofen.c" #include "t-poly_pfrac.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mpoly_factor), TEST_FUNCTION(fmpz_mpoly_factor_content), TEST_FUNCTION(fmpz_mpoly_factor_squarefree), TEST_FUNCTION(fmpz_mpoly_factor_wang), TEST_FUNCTION(fmpz_mpoly_factor_zassenhaus), TEST_FUNCTION(fmpz_mpoly_factor_zippel), TEST_FUNCTION(fmpz_mpoly_factor_gcd_brown), TEST_FUNCTION(fmpz_mpoly_factor_gcd_brown_threaded), TEST_FUNCTION(fmpz_mpoly_factor_gcd_subresultant), TEST_FUNCTION(fmpz_mpoly_factor_gcd_zippel2), TEST_FUNCTION(fmpz_mpoly_factor_gcd_zippel), TEST_FUNCTION(fmpz_mpoly_factor_lcc_kaltofen), TEST_FUNCTION(fmpz_poly_pfrac) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mpoly_factor/test/t-factor.c000066400000000000000000000124151461254215100220210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mpoly_factor.h" /* Defined t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega void check_omega( slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx, int factor_fun(fmpz_mpoly_factor_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { slong i; fmpz_mpoly_t q; fmpz_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mpoly_factor_init(g, ctx); fmpz_mpoly_factor_init(h, ctx); fmpz_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("check factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { if (!fmpz_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || fmpz_sgn(g->poly[i].coeffs + 0) <= 0) { flint_printf("factorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("factorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_factor_expand(q, g, ctx); if (!fmpz_mpoly_equal(q, p, ctx)) { flint_printf("factorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { fmpz_mpoly_factor_sort(g, ctx); fmpz_mpoly_factor_sort(h, ctx); if (fmpz_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); return; } #endif TEST_FUNCTION_START(fmpz_mpoly_factor, state) { slong i, j, tmul = 25; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_mpoly_ctx_init(ctx, 8, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_set_str_pretty(f, "x1^809*x2^75*x3^384*x4^324*x5^74*x6^788*x7^83*x8^414+" "x1^805*x2^343*x3^595*x4^246*x5^32*x6^90*x7^473*x8^591+" "x1^718*x2^108*x3^680*x4^368*x5^358*x8^276+" "x1^683*x2^533*x4^649*x5^619*x6^136*x7^223*x8^610+" "x2^617*x3^777*x4^799*x5^443*x6^545*x7^166*x8^216+" "x1^485*x2^646*x3^424*x4^265*x5^416*x6^400*x7^278+" "x1^336*x2^149*x3^361*x4^691*x5^629*x6^282*x7^530*x8^259+" "x1^266*x3^258*x5^422*x6^637*x7^244*x8^236+" "x1^74*x2^812*x3^162*x4^417*x5^71*x6^188*x7^258*x8^637+" "x1^37*x2^604*x3^94*x4^474*x6^853*x7^521*x8^250", NULL, ctx); check_omega(1, 1, f, ctx, fmpz_mpoly_factor); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, t; flint_bitcnt_t coeff_bits; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 8); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (5 + n_randint(state, 5))/n; expbound = 3 + 40/nfacs/n; powbound = 1 + n_randint(state, 3); lower = 0; fmpz_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { do { len = 1 + n_randint(state, 7); coeff_bits = 10 + n_randint(state, 1000)/nfacs; fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, expbound, ctx); } while (t->length == 0); pow = 1 + n_randint(state, powbound); if (!fmpz_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mpoly_pow_ui(t, t, pow, ctx); fmpz_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mpoly_factor); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/test/t-factor_content.c000066400000000000000000000075761461254215100235670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" void check_content(const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { slong i, v; fmpz_mpoly_t q; fmpz_mpoly_factor_t g; fmpz_t deg; fmpz_mpoly_factor_init(g, ctx); fmpz_mpoly_init(q, ctx); fmpz_init(deg); if (!fmpz_mpoly_factor_content(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || fmpz_sgn(g->poly[i].coeffs + 0) < 0) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_factor_expand(q, g, ctx); if (!fmpz_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { for (v = 0; v < ctx->minfo->nvars; v++) { if (fmpz_mpoly_length(g->poly + i, ctx) < 2) { if (!fmpz_mpoly_is_gen(g->poly + i, -1, ctx)) { flint_printf("FAIL:\nmonomial is bad\n"); fflush(stdout); flint_abort(); } } else { if (!fmpz_mpoly_content_vars(q, g->poly + i, &v, 1, ctx)) { flint_printf("FAIL:\ncheck content could be computed\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_degree_fmpz(deg, g->poly + i, v, ctx); if (!fmpz_mpoly_is_one(q, ctx) && !fmpz_is_zero(deg)) { flint_printf("FAIL:\ncontent is bad\n"); fflush(stdout); flint_abort(); } } } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_clear(deg); } TEST_FUNCTION_START(fmpz_mpoly_factor_content, state) { slong i, j, k, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, t; slong n, nfacs, len; ulong * expbounds; flint_bitcnt_t coeffbits; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 5 + (8 + n_randint(state, 8))/n; expbounds = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); for (k = 0; k < ctx->minfo->nvars; k++) expbounds[k] = 3; fmpz_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 9); coeffbits = 2 + n_randint(state, 100); if (ctx->minfo->nvars > 0) { k = n_randint(state, ctx->minfo->nvars); expbounds[k] = 1; } fmpz_mpoly_randtest_bounds(t, state, len, coeffbits, expbounds, ctx); if (!fmpz_mpoly_is_zero(t, ctx)) { fmpz_mpoly_mul(t, a, t, ctx); if (t->length < 1500) fmpz_mpoly_swap(a, t, ctx); } } check_content(a, ctx); flint_free(expbounds); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000066011461254215100242430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" void check_it(const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { slong i, j; fmpz_mpoly_t q; fmpz_mpoly_factor_t g, h; fmpz_mpoly_factor_init(g, ctx); fmpz_mpoly_factor_init(h, ctx); fmpz_mpoly_init(q, ctx); if (!fmpz_mpoly_factor_squarefree(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || fmpz_sgn(g->poly[i].coeffs + 0) < 0) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_factor_expand(q, g, ctx); if (!fmpz_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { fmpz_mpoly_factor_squarefree(h, g->poly + i, ctx); for (j = 0; j < h->num; j++) { if (!fmpz_is_one(h->exp + j)) { flint_printf("FAIL:\nfactor has a square factor\n"); fflush(stdout); flint_abort(); } } } for (i = 1; i < g->num; i++) for (j = 0; j < i; j++) { if (!fmpz_mpoly_gcd(q, g->poly + i, g->poly + j, ctx)) { flint_printf("FAIL:\ncheck gcd could be computed\n"); } if (!fmpz_mpoly_is_one(q, ctx)) { flint_printf("FAIL:\nbases have a common factor\n"); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); } TEST_FUNCTION_START(fmpz_mpoly_factor_squarefree, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, t; flint_bitcnt_t coeff_bits; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (7 + n_randint(state, 7))/n; powbound = 1 + n_randint(state, 5); expbound = 2 + 50/nfacs/n/powbound; fmpz_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 60/powbound/n); coeff_bits = 10 + n_randint(state, 200)/nfacs; fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, expbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); fmpz_mpoly_pow_ui(t, t, pow, ctx); fmpz_mpoly_mul(a, a, t, ctx); } check_it(a, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/test/t-factor_wang.c000066400000000000000000000107261461254215100230400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" /* Defined t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega void check_omega( slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx, int factor_fun(fmpz_mpoly_factor_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { slong i; fmpz_mpoly_t q; fmpz_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mpoly_factor_init(g, ctx); fmpz_mpoly_factor_init(h, ctx); fmpz_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("check factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { if (!fmpz_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || fmpz_sgn(g->poly[i].coeffs + 0) <= 0) { flint_printf("factorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("factorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_factor_expand(q, g, ctx); if (!fmpz_mpoly_equal(q, p, ctx)) { flint_printf("factorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { fmpz_mpoly_factor_sort(g, ctx); fmpz_mpoly_factor_sort(h, ctx); if (fmpz_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); return; } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_wang, state) { slong i, j, tmul = 20; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, at, t; flint_bitcnt_t coeff_bits; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 6); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(at, ctx); fmpz_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (4 + n_randint(state, 5))/n; expbound = 2 + 25/nfacs/n; powbound = 1 + n_randint(state, 3); lower = 0; fmpz_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { do { len = 2 + n_randint(state, 10); coeff_bits = 100 + n_randint(state, 300)/nfacs; fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, expbound, ctx); } while (t->length == 0); pow = 1 + n_randint(state, powbound); fmpz_mpoly_pow_ui(t, t, pow, ctx); fmpz_mpoly_mul(at, a, t, ctx); if (t->length < 200) { fmpz_mpoly_swap(a, at, ctx); if (!fmpz_mpoly_is_fmpz(t, ctx)) lower += pow; } } check_omega(lower, WORD_MAX, a, ctx, fmpz_mpoly_factor_wang); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(at, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000136321461254215100242670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" /* Defined t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega void check_omega( slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx, int factor_fun(fmpz_mpoly_factor_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { slong i; fmpz_mpoly_t q; fmpz_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mpoly_factor_init(g, ctx); fmpz_mpoly_factor_init(h, ctx); fmpz_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("check factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { if (!fmpz_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || fmpz_sgn(g->poly[i].coeffs + 0) <= 0) { flint_printf("factorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("factorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_factor_expand(q, g, ctx); if (!fmpz_mpoly_equal(q, p, ctx)) { flint_printf("factorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { fmpz_mpoly_factor_sort(g, ctx); fmpz_mpoly_factor_sort(h, ctx); if (fmpz_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); return; } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_zassenhaus, state) { slong i, j, tmul = 20; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a; fmpz_mpoly_factor_t f; const char * vars[] = {"x", "y", "z", "w"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_factor_init(f, ctx); fmpz_mpoly_set_str_pretty(a, "(w^2+y^3+z^4+1)*(w^2+y^3+z^4+2)", vars, ctx); check_omega(2, 2, a, ctx, fmpz_mpoly_factor_zassenhaus); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_factor_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a; fmpz_mpoly_factor_t f; const char * vars[] = {"x", "y", "z", "w"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_factor_init(f, ctx); fmpz_mpoly_set_str_pretty(a, "((x^2+y^2+z^2+2+w)*(x+1)*(y+2)*(z+3+w^3)+x*y*z*w)" "*((x^2+y^2+z^2+3+w)*(x^2+1)*(y^2+2)*(z^2+3+w^3)+x*y*z+ w)" "*((x^2+y^2+z^2+x+y+z+5+w)*(7+x+y^2)*(8+x+z^2+w^3)+x*y*z+ w)" "*((x^2+y^2+z^2+x+y+z+13+w)*(10+y+z^2+w^3)+x*y*z*w)" , vars, ctx); check_omega(4, 4, a, ctx, fmpz_mpoly_factor_zassenhaus); fmpz_mpoly_set_str_pretty(a, "(((x+y+z+2)*(x+y^2+1+z^2)+z+w^4)*((x+2*y+z^2)*(x^2+y+2+z^3)+z+w^6)+x*y*z*w)" "*(((x+y+z+7)*(x+y^2+11+z^2)+z+w^4)*((x+2*y+z^2+13)*(x^2+y+2+z^3+17)+z+w^6)+x*y*z*w)" "*(x+y+z+w+19)" , vars, ctx); check_omega(3, 3, a, ctx, fmpz_mpoly_factor_zassenhaus); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_factor_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, t; flint_bitcnt_t coeff_bits; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (4 + n_randint(state, 5))/n; expbound = 2 + 20/nfacs/n; powbound = 1 + n_randint(state, 3); lower = 0; fmpz_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { do { len = 1 + n_randint(state, 10); coeff_bits = 10 + n_randint(state, 300)/nfacs; fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, expbound, ctx); } while (t->length == 0); pow = 1 + n_randint(state, powbound); if (!fmpz_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mpoly_pow_ui(t, t, pow, ctx); fmpz_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mpoly_factor_zassenhaus); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000104321461254215100234010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" /* Defined t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega void check_omega( slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx, int factor_fun(fmpz_mpoly_factor_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { slong i; fmpz_mpoly_t q; fmpz_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fmpz_mpoly_factor_init(g, ctx); fmpz_mpoly_factor_init(h, ctx); fmpz_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("check factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { if (!fmpz_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || fmpz_sgn(g->poly[i].coeffs + 0) <= 0) { flint_printf("factorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("factorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_factor_expand(q, g, ctx); if (!fmpz_mpoly_equal(q, p, ctx)) { flint_printf("factorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fmpz_mpoly_factor) { fmpz_mpoly_factor_sort(g, ctx); fmpz_mpoly_factor_sort(h, ctx); if (fmpz_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fmpz_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); return; } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_zippel, state) { slong i, j, tmul = 20; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, t; flint_bitcnt_t coeff_bits; slong n, nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 7); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (5 + n_randint(state, 5))/n; expbound = 3 + 40/nfacs/n; powbound = 1 + n_randint(state, 3); lower = 0; fmpz_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { do { len = 1 + n_randint(state, 7); coeff_bits = 10 + n_randint(state, 1000)/nfacs; fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, expbound, ctx); } while (t->length == 0); pow = 1 + n_randint(state, powbound); if (!fmpz_mpoly_is_fmpz(t, ctx)) lower += pow; fmpz_mpoly_pow_ui(t, t, pow, ctx); fmpz_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fmpz_mpoly_factor_zippel); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/test/t-gcd_brown.c000066400000000000000000000176561461254215100225230ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_brown int compute_gcd( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int success; slong * perm; ulong * shift, * stride; slong i; flint_bitcnt_t wbits; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; if (fmpz_mpoly_is_zero(A, ctx)) { if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_zero(G, ctx); return 1; } if (fmpz_sgn(B->coeffs + 0) < 0) { fmpz_mpoly_neg(G, B, ctx); return 1; } else { fmpz_mpoly_set(G, B, ctx); return 1; } } if (fmpz_mpoly_is_zero(B, ctx)) { if (fmpz_sgn(A->coeffs + 0) < 0) { fmpz_mpoly_neg(G, A, ctx); return 1; } else { fmpz_mpoly_set(G, A, ctx); return 1; } } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } perm = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); shift = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); stride = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } if (ctx->minfo->nvars == 1) { fmpz_poly_t a, b, g; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(g); _fmpz_mpoly_to_fmpz_poly_deflate(a, A, 0, shift, stride, ctx); _fmpz_mpoly_to_fmpz_poly_deflate(b, B, 0, shift, stride, ctx); fmpz_poly_gcd(g, a, b); _fmpz_mpoly_from_fmpz_poly_inflate(G, A->bits, g, 0, shift, stride, ctx); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(g); success = 1; goto cleanup1; } wbits = FLINT_MAX(A->bits, B->bits); fmpz_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX); fmpz_mpoly_init3(Al, 0, wbits, lctx); fmpz_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); success = fmpz_mpolyl_gcd_brown(Gl, Abarl, Bbarl, Al, Bl, lctx, NULL); if (!success) goto cleanup; fmpz_mpoly_from_mpolyl_perm_inflate(G, wbits, ctx, Gl, lctx, perm, shift, stride); if (fmpz_sgn(G->coeffs + 0) < 0) fmpz_mpoly_neg(G, G, ctx); cleanup: fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_ctx_clear(lctx); cleanup1: flint_free(perm); flint_free(shift); flint_free(stride); return success; } /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name, int compute_gcd_fun(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_gcd_brown, state) { slong i, j, tmul = 15; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); if (ctx->minfo->nvars < 1) { fmpz_mpoly_ctx_clear(ctx); fmpz_mpoly_ctx_init(ctx, 1, ORD_LEX); } fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 40) + 1; len1 = n_randint(state, 60); len2 = n_randint(state, 60); degbound = 1 + 50/ctx->minfo->nvars/ctx->minfo->nvars; coeff_bits = n_randint(state, 300); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_scalar_mul_ui(a, a, n_randint(state, 10) + 1, ctx); fmpz_mpoly_scalar_mul_ui(b, b, n_randint(state, 10) + 1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense", compute_gcd); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mpoly_factor/test/t-gcd_brown_threaded.c000066400000000000000000000225651461254215100243560ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly_factor.h" typedef struct { fmpz_mpoly_struct * Pl; const fmpz_mpoly_ctx_struct * lctx; const fmpz_mpoly_struct * P; const fmpz_mpoly_ctx_struct * ctx; const slong * perm; const ulong * shift; const ulong * stride; const thread_pool_handle * handles; slong num_handles; } _convertl_arg_struct; typedef _convertl_arg_struct _convertl_arg_t[1]; static void _worker_convertu(void * varg) { _convertl_arg_struct * arg = (_convertl_arg_struct *) varg; fmpz_mpoly_to_mpolyl_perm_deflate(arg->Pl, arg->lctx, arg->P, arg->ctx, arg->perm, arg->shift, arg->stride); } /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_brown_threaded int compute_gcd( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int success; slong * perm; ulong * shift, * stride; slong i; flint_bitcnt_t ABbits; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; thread_pool_handle * handles; slong num_handles; slong thread_limit = FLINT_MIN(A->length, B->length)/16; if (fmpz_mpoly_is_zero(A, ctx)) { if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_zero(G, ctx); return 1; } if (fmpz_sgn(B->coeffs + 0) < 0) { fmpz_mpoly_neg(G, B, ctx); return 1; } else { fmpz_mpoly_set(G, B, ctx); return 1; } } if (fmpz_mpoly_is_zero(B, ctx)) { if (fmpz_sgn(A->coeffs + 0) < 0) { fmpz_mpoly_neg(G, A, ctx); return 1; } else { fmpz_mpoly_set(G, A, ctx); return 1; } } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (ctx->minfo->nvars < 2) { return fmpz_mpoly_gcd(G, A, B, ctx); } perm = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); shift = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); stride = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } ABbits = FLINT_MAX(A->bits, B->bits); fmpz_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX); fmpz_mpoly_init3(Al, 0, ABbits, lctx); fmpz_mpoly_init3(Bl, 0, ABbits, lctx); fmpz_mpoly_init3(Gl, 0, ABbits, lctx); fmpz_mpoly_init3(Abarl, 0, ABbits, lctx); fmpz_mpoly_init3(Bbarl, 0, ABbits, lctx); num_handles = flint_request_threads(&handles, thread_limit); /* convert inputs */ if (num_handles > 0) { slong m = mpoly_divide_threads(num_handles, A->length, B->length); _convertl_arg_t arg; FLINT_ASSERT(m >= 0); FLINT_ASSERT(m < num_handles); arg->Pl = Bl; arg->lctx = lctx; arg->P = B; arg->ctx = ctx; arg->perm = perm; arg->shift = shift; arg->stride = stride; arg->handles = handles + (m + 1); arg->num_handles = num_handles - (m + 1); thread_pool_wake(global_thread_pool, handles[m], 0, _worker_convertu, arg); fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); thread_pool_wait(global_thread_pool, handles[m]); } else { fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); } /* calculate gcd */ success = fmpz_mpolyl_gcd_brown_threaded_pool(Gl, Abarl, Bbarl, Al, Bl, lctx, NULL, handles, num_handles); flint_give_back_threads(handles, num_handles); if (success) { fmpz_mpoly_from_mpolyl_perm_inflate(G, ABbits, ctx, Gl, lctx, perm, shift, stride); if (fmpz_sgn(G->coeffs + 0) < 0) fmpz_mpoly_neg(G, G, ctx); } fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_ctx_clear(lctx); flint_free(perm); flint_free(shift); flint_free(stride); return success; } /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name, int compute_gcd_fun(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_gcd_brown_threaded, state) { slong i, j, tmul = 12, max_threads = 5; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 5); if (ctx->minfo->nvars < 1) { fmpz_mpoly_ctx_clear(ctx); continue; } fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 50) + 1; len1 = n_randint(state, 80); len2 = n_randint(state, 80); degbound = 1 + 50/ctx->minfo->nvars/ctx->minfo->nvars; coeff_bits = n_randint(state, 300); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_scalar_mul_ui(a, a, n_randint(state, 10) + 1, ctx); fmpz_mpoly_scalar_mul_ui(b, b, n_randint(state, 10) + 1, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense", compute_gcd); flint_set_num_threads(n_randint(state, max_threads) + 1); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000171261461254215100241170ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_subresultant int compute_gcd( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { int success; slong var = 0; fmpz_mpoly_t Ac, Bc, Gc, s, t; fmpz_mpoly_univar_t Ax, Bx, Gx; if (fmpz_mpoly_is_zero(A, ctx) || fmpz_mpoly_is_zero(B, ctx)) return fmpz_mpoly_gcd(G, A, B, ctx); fmpz_mpoly_init(Ac, ctx); fmpz_mpoly_init(Bc, ctx); fmpz_mpoly_init(Gc, ctx); fmpz_mpoly_init(s, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_univar_init(Ax, ctx); fmpz_mpoly_univar_init(Bx, ctx); fmpz_mpoly_univar_init(Gx, ctx); fmpz_mpoly_to_univar(Ax, A, var, ctx); fmpz_mpoly_to_univar(Bx, B, var, ctx); success = _fmpz_mpoly_vec_content_mpoly(Ac, Ax->coeffs, Ax->length, ctx) && _fmpz_mpoly_vec_content_mpoly(Bc, Bx->coeffs, Bx->length, ctx) && fmpz_mpoly_gcd(Gc, Ac, Bc, ctx); if (!success) goto cleanup; _fmpz_mpoly_vec_divexact_mpoly(Ax->coeffs, Ax->length, Ac, ctx); _fmpz_mpoly_vec_divexact_mpoly(Bx->coeffs, Bx->length, Bc, ctx); success = fmpz_cmp(Ax->exps + 0, Bx->exps + 0) > 0 ? fmpz_mpoly_univar_pseudo_gcd(Gx, Ax, Bx, ctx) : fmpz_mpoly_univar_pseudo_gcd(Gx, Bx, Ax, ctx); if (!success) goto cleanup; if (fmpz_mpoly_gcd(t, Ax->coeffs + 0, Bx->coeffs + 0, ctx) && t->length == 1) { fmpz_mpoly_term_content(s, Gx->coeffs + 0, ctx); fmpz_mpoly_divexact(t, Gx->coeffs + 0, s, ctx); _fmpz_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } else if (fmpz_mpoly_gcd(t, Ax->coeffs + Ax->length - 1, Bx->coeffs + Bx->length - 1, ctx) && t->length == 1) { fmpz_mpoly_term_content(s, Gx->coeffs + Gx->length - 1, ctx); fmpz_mpoly_divexact(t, Gx->coeffs + Gx->length - 1, s, ctx); _fmpz_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } success = _fmpz_mpoly_vec_content_mpoly(t, Gx->coeffs, Gx->length, ctx); if (!success) goto cleanup; _fmpz_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); _fmpz_mpoly_vec_mul_mpoly(Gx->coeffs, Gx->length, Gc, ctx); _fmpz_mpoly_from_univar(G, FLINT_MIN(A->bits, B->bits), Gx, var, ctx); fmpz_mpoly_unit_normalize(G, ctx); success = 1; cleanup: fmpz_mpoly_clear(Ac, ctx); fmpz_mpoly_clear(Bc, ctx); fmpz_mpoly_clear(Gc, ctx); fmpz_mpoly_clear(s, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_univar_clear(Ax, ctx); fmpz_mpoly_univar_clear(Bx, ctx); fmpz_mpoly_univar_clear(Gx, ctx); return success; } /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name, int compute_gcd_fun(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_gcd_subresultant, state) { slong i, j, tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; flint_bitcnt_t coeff_bits; fmpz_mpoly_ctx_init_rand(ctx, state, 3); if (ctx->minfo->nvars < 1) { fmpz_mpoly_ctx_clear(ctx); continue; } fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 15); len2 = n_randint(state, 15); degbound = 1 + 10/ctx->minfo->nvars; for (j = 0; j < 4; j++) { coeff_bits = n_randint(state, 100) + 1; fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, degbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); coeff_bits = n_randint(state, 100) + 1; fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); coeff_bits = n_randint(state, 100) + 1; fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense", compute_gcd); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mpoly_factor/test/t-gcd_zippel.c000066400000000000000000000363551461254215100226740ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_zippel int compute_gcd( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t wbits; flint_rand_t state; int success = 0; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mpoly_t Ac, Bc, Gc; ulong * shift, * stride; slong * perm; if (fmpz_mpoly_is_zero(A, ctx)) { if (fmpz_mpoly_is_zero(B, ctx)) { fmpz_mpoly_zero(G, ctx); return 1; } if (fmpz_sgn(B->coeffs + 0) < 0) { fmpz_mpoly_neg(G, B, ctx); return 1; } else { fmpz_mpoly_set(G, B, ctx); return 1; } } if (fmpz_mpoly_is_zero(B, ctx)) { if (fmpz_sgn(A->coeffs + 0) < 0) { fmpz_mpoly_neg(G, A, ctx); return 1; } else { fmpz_mpoly_set(G, A, ctx); return 1; } } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (ctx->minfo->nvars < 2) { return fmpz_mpoly_gcd(G, A, B, ctx); } perm = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); shift = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); stride = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } flint_randinit(state); wbits = FLINT_MAX(A->bits, B->bits); fmpz_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX); fmpz_mpoly_init3(Al, 0, wbits, lctx); fmpz_mpoly_init3(Bl, 0, wbits, lctx); fmpz_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); success = fmpz_mpolyl_content(Ac, Al, 1, lctx) && fmpz_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; if (!fmpz_mpoly_divides(Al, Al, Ac, lctx) || !fmpz_mpoly_divides(Bl, Bl, Bc, lctx)) { flint_printf("FAIL: Check content divides\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mpoly_repack_bits_inplace(Bl, wbits, lctx); success = fmpz_mpolyl_gcd_zippel(Gl, Abarl, Bbarl, Al, Bl, lctx, state); if (!success) goto cleanup; success = fmpz_mpoly_gcd(Gc, Ac, Bc, lctx); if (!success) goto cleanup; fmpz_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mpoly_repack_bits_inplace(Gl, wbits, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(G, FLINT_MIN(A->bits, B->bits), ctx, Gl, lctx, perm, shift, stride); success = 1; if (fmpz_sgn(G->coeffs + 0) < 0) fmpz_mpoly_neg(G, G, ctx); cleanup: fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_clear(Ac, lctx); fmpz_mpoly_clear(Bc, lctx); fmpz_mpoly_clear(Gc, lctx); fmpz_mpoly_ctx_clear(lctx); flint_randclear(state); flint_free(perm); flint_free(shift); flint_free(stride); return success; } /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name, int compute_gcd_fun(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_gcd_zippel, state) { slong i, j, tmul = 25; /* examples from Zippel's 1979 paper */ { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t r, d, f, g; const char* vars[] = {"x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"}; const char * example[][3] = {{ "x1^2 + x1 + 3", "2*x1^2 + 2*x1 + 1", "x1^2 + 2*x1 + 2" }, { "2*x1^2*x2^2 + x1*x2 + 2*x1", "x2^2 + 2*x1^2*x2 + x1^2 + 1", "x1^2*x2^2 + x1^2*x2 + x1*x2 + x1^2 + x1" }, { "x2^2*x3^2 + x2^2*x3 + 2*x1^2*x2*x3 + x1*x3", "x3^2 + x2^2*x3 + x1^2*x2*x3 + x1*x3 + x1^2*x2^2", "x2*x3 + 2*x1*x3 + x3 + x1" }, { "x1^2*x4^2 + x2^2*x3*x4 + x1^2*x2*x4 + x2*x4 + x1^2*x2*x3", "x1*x2*x3^2*x4^2 + x1*x3^2*x4^2 + x1*x4^2 + x4^2 + x1*x3*x4", "x1*x3^2*x4^2 + x3^2*x4^2 + x4^2 + x1*x2^2*x3*x4 + x1*x2^2" }, { "x1^3*x2^2*x3^2*x4*x5^2 + x1*x2^2*x5^2 + x1^3*x3*x4^2*x5" " + x1^3*x2*x3^2*x4*x5 + x1^2*x2*x3^2*x4^2" , "x1*x2^2*x5^2 + x1*x2*x3^2*x4*x5 + x1*x2*x3^2*x4^2" " + x1*x2^2*x4^2 + 1" , "x1*x3^2*x4*x5^2 + x2*x5^2 + x1*x2*x4*x5 + x2*x5 + x1*x2*x3*x4^2" }, { "x1*x2*x4^2*x5^2*x6^2 + x1*x2^2*x3^2*x4*x5^2*x6^2 + x1^2*x3*x6^2" " + x1^2*x2*x3^2*x4*x5^2*x6 + x1^2*x3*x5*x6" , "x1^2*x2*x4*x5^2*x6^2 + x1*x3*x5^2*x6^2 + x1*x2^2*x6^2" " + x1^2*x2^2*x3^2*x5*x6 + x1*x3^2*x4*x5" , "x2^2*x3^2*x4*x5^2*x6 + x1*x4^2*x5*x6 + x2^2*x3^2*x4*x5*x6" " + x1*x2^2*x3*x4^2*x6 + x1^2*x3*x5^2" }, { "x1*x2^2*x4^2*x6^2*x7^2 + x1^2*x3*x4*x6^2*x7^2 + x3^2*x4^2*x7^2" " + x1^2*x2*x4^2*x6 + x3*x4*x5^2" , "x1^2*x2*x4^2*x5*x6^2*x7^2 + x1*x2*x3*x6*x7 + x3*x4^2*x5^2*x7" " + x1*x4^2*x5^2*x7 + x1^2*x2*x3*x4^2+x5*x6" , "x1*x3*x5*x6^2*x7^2 + x2^2*x3^2*x4^2*x5*x6*x7^2 + x4*x6*x7^2" " + x1^2*x2*x3*x5*x6*x7 + x1^2*x3^2*x4*x5^2" }, { "x2^2*x4*x5*x6*x7*x8^2 + x1^2*x2*x3^2*x4^2*x6^2*x7^2*x8" " + x1^2*x3*x4^2*x6^2*x7^2 + x1^2*x2^2*x3^2*x4*x5^2*x6*x7^2" " + x2^2*x4*x6" , "x1^2*x2^2*x3*x4^2*x5*x6^2*x8^2 + x2*x5*x6^2*x8^2" " + x1^2*x2^2*x3^2*x4^2*x6^2*x7^2*x8 + x1^2*x3^2*x4*x5^2*x7^2*x8" " + x1*x2^2*x3^2*x5^2*x7" , "x1*x4^2*x5*x6*x7*x8^2 + x1*x2^2*x4^2*x5^2*x6^2*x8" " + x1^2*x2*x3*x4^2*x6^2*x8 + x1^2*x2^2*x3^2*x4*x5^2*x8" " + x1*x2*x4^2*x5^2" }, { "x1^2*x3^3*x4*x6*x8*x9^2 + x1*x2*x3*x4^2*x5^2*x8*x9" " + x2*x3*x4*x5^2*x8*x9 + x1*x3^3*x4^2*x5^2*x6^2*x7*x8^2" " + x2*x3*x4*x5^2*x6*x7*x8^2" , "x1^2*x2^2*x3*x7^2*x8*x9 + x2^2*x9 + x1^2*x3*x4^2*x5^2*x6*x7^2" " + x4^2*x5^2*x7^2 + x3*x4^2*x6*x7" , "x1^2*x2*x4*x5*x6*x7^2*x8^2*x9^2 + x1^2*x2*x3*x5*x6^2*x7^2*x8*x9^2" " + x1^2*x3*x4*x6*x7^2*x8*x9 + x1^2*x2^2*x6*x8^2" " + x2^2*x4*x5*x6^2*x7" }, { "x1*x2^2*x4^2*x8*x9^2*x10^2 + x2^2*x4*x5^2*x6*x7*x9*x10^2" " + x1^2*x2*x3*x5^2*x7^2*x9^2 + x1*x3^2*x4^2*x7^2*x9^2" " + x1^2*x3*x4*x7^2*x8^2" , "x1*x2*x3^2*x4*x6*x7*x8*x9^2*x10^2 + x2^2*x3^2*x4^2*x6^2*x9*x10^2" " + x1*x2^2*x3^2*x4*x5*x6*x7*x8^2*x9^2*x10" " + x1^2*x2*x4^2*x5^2*x8^2*x9^2*x10 + x3*x4^2*x5*x6*x7^2*x9*x10" , "x1*x2^2*x3^2*x5^2*x6^2*x7*x8*x9^2*x10^2 + x3*x8*x9^2*x10^2" " + x1*x2^2*x3*x4*x5^2*x6^2*x8^2*x9*x10 + x1*x3*x6*x7*x8*x10" " + x4^2*x5^2*x6^2*x7*x9^2" }}; for (i = 1; i <= 10; i++) { fmpz_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX); fmpz_mpoly_init(r, ctx); fmpz_mpoly_init(d, ctx); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_set_str_pretty(d, example[i - 1][0], vars, ctx); fmpz_mpoly_set_str_pretty(f, example[i - 1][1], vars, ctx); fmpz_mpoly_set_str_pretty(g, example[i - 1][2], vars, ctx); fmpz_mpoly_mul(f, f, d, ctx); fmpz_mpoly_mul(g, g, d, ctx); fmpz_mpoly_randtest_bits(r, state, 10, 100, FLINT_BITS, ctx); gcd_check(r, f, g, d, ctx, -2, i, "example", compute_gcd); fmpz_mpoly_clear(r, ctx); fmpz_mpoly_clear(d, ctx); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } } { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b, c; const char * vars[] = {"t" ,"z", "y", "x"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_LEX); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(c, ctx); fmpz_mpoly_set_str_pretty(c, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mpoly_mul(a, a, c, ctx); fmpz_mpoly_mul(b, b, c, ctx); gcd_check(g, a, b, c, ctx, -1, 1, "example", compute_gcd); /* Main variable is t and c has content wrt t mod first chosen prime. However, this content doesn't depend on z and must be caught before it gets down to bivariate. Buggy code hangs on this example. */ fmpz_mpoly_set_str_pretty(c, "t*(y+x)+9223372036854775837", vars, ctx); fmpz_mpoly_set_str_pretty(a, "1+x^2+y^2+z^2+t^2", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1+x^3+y^3+z^3+t^3", vars, ctx); fmpz_mpoly_mul(a, a, c, ctx); fmpz_mpoly_mul(b, b, c, ctx); gcd_check(g, a, b, c, ctx, -1, 1, "bug check", compute_gcd); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(c, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 10); if (ctx->minfo->nvars < 1) { fmpz_mpoly_ctx_clear(ctx); continue; } fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 25) + 1; len1 = n_randint(state, 25) + 1; len2 = n_randint(state, 25) + 1; degbound = 2 + 100/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 300); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse", compute_gcd); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mpoly_factor/test/t-gcd_zippel2.c000066400000000000000000000327221461254215100227500ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_factor.h" /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #define compute_gcd compute_gcd_zippel2 int compute_gcd( fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx) { slong i, max_deg; flint_bitcnt_t wbits; int success = 0; fmpz_mpoly_ctx_t lctx; fmpz_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fmpz_mpoly_t Ac, Bc, Gc, Gamma, lcAl, lcBl; slong * Adegs, * Bdegs, * perm; ulong * shift, * stride; if (fmpz_mpoly_is_zero(A, ctx)) { if (fmpz_mpoly_is_zero(B, ctx)) fmpz_mpoly_zero(G, ctx); else if (fmpz_sgn(B->coeffs + 0) < 0) fmpz_mpoly_neg(G, B, ctx); else fmpz_mpoly_set(G, B, ctx); return 1; } if (fmpz_mpoly_is_zero(B, ctx)) { if (fmpz_sgn(A->coeffs + 0) < 0) fmpz_mpoly_neg(G, A, ctx); else fmpz_mpoly_set(G, A, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (ctx->minfo->nvars < 3) { return fmpz_mpoly_gcd_zippel(G, A, B, ctx); } FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->nvars >= 3); FLINT_ASSERT(!fmpz_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!fmpz_mpoly_is_zero(B, ctx)); Adegs = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); Bdegs = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); perm = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); shift = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); stride = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); mpoly_degrees_si(Adegs, A->exps, A->length, A->bits, ctx->minfo); mpoly_degrees_si(Bdegs, B->exps, B->length, B->bits, ctx->minfo); max_deg = 0; for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; max_deg = FLINT_MAX(max_deg, Adegs[i]); max_deg = FLINT_MAX(max_deg, Bdegs[i]); } fmpz_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX); wbits = 1 + FLINT_BIT_COUNT(max_deg); wbits = FLINT_MAX(MPOLY_MIN_BITS, wbits); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fmpz_mpoly_init3(Al, A->length, wbits, lctx); fmpz_mpoly_init3(Bl, B->length, wbits, lctx); fmpz_mpoly_init3(Gl, 0, wbits, lctx); fmpz_mpoly_init3(Abarl, 0, wbits, lctx); fmpz_mpoly_init3(Bbarl, 0, wbits, lctx); fmpz_mpoly_init3(Ac, 0, wbits, lctx); fmpz_mpoly_init3(Bc, 0, wbits, lctx); fmpz_mpoly_init3(Gc, 0, wbits, lctx); fmpz_mpoly_init3(Gamma, 0, wbits, lctx); fmpz_mpoly_init3(lcAl, 0, wbits, lctx); fmpz_mpoly_init3(lcBl, 0, wbits, lctx); if (FLINT_BIT_COUNT(FLINT_MAX(Adegs[0], Adegs[1])) >= FLINT_BITS/2 || FLINT_BIT_COUNT(FLINT_MAX(Bdegs[0], Bdegs[1])) >= FLINT_BITS/2) { success = 0; goto cleanup; } fmpz_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); fmpz_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); success = fmpz_mpolyl_content(Ac, Al, 2, lctx) && fmpz_mpolyl_content(Bc, Bl, 2, lctx); if (!success) goto cleanup; success = fmpz_mpoly_gcd(Gc, Ac, Bc, lctx); if (!success) goto cleanup; success = fmpz_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = fmpz_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fmpz_mpoly_repack_bits_inplace(Al, wbits, lctx); fmpz_mpoly_repack_bits_inplace(Bl, wbits, lctx); fmpz_mpolyl_lead_coeff(lcAl, Al, 2, lctx); fmpz_mpolyl_lead_coeff(lcBl, Bl, 2, lctx); success = fmpz_mpoly_gcd(Gamma, lcAl, lcBl, lctx); if (!success) goto cleanup; success = fmpz_mpolyl_gcd_zippel2(Gl, Abarl, Bbarl, Al, Bl, Gamma, lctx); if (!success) goto cleanup; fmpz_mpoly_mul(Gl, Gl, Gc, lctx); fmpz_mpoly_from_mpolyl_perm_inflate(G, FLINT_MIN(A->bits, B->bits), ctx, Gl, lctx, perm, shift, stride); if (fmpz_sgn(G->coeffs + 0) < 0) fmpz_mpoly_neg(G, G, ctx); success = 1; cleanup: flint_free(Adegs); flint_free(Bdegs); flint_free(perm); flint_free(shift); flint_free(stride); fmpz_mpoly_clear(Al, lctx); fmpz_mpoly_clear(Bl, lctx); fmpz_mpoly_clear(Gl, lctx); fmpz_mpoly_clear(Abarl, lctx); fmpz_mpoly_clear(Bbarl, lctx); fmpz_mpoly_clear(Ac, lctx); fmpz_mpoly_clear(Bc, lctx); fmpz_mpoly_clear(Gc, lctx); fmpz_mpoly_clear(Gamma, lctx); fmpz_mpoly_clear(lcAl, lctx); fmpz_mpoly_clear(lcBl, lctx); fmpz_mpoly_ctx_clear(lctx); return success; } /* Defined in t-gcd_brown.c, t-gcd_brown_threaded.c, t-gcd_subresultant.c, * t-gcd_zippel.c, t-gcd_zippel2.c */ #ifndef gcd_check #define gcd_check gcd_check void gcd_check( fmpz_mpoly_t g, fmpz_mpoly_t a, fmpz_mpoly_t b, const fmpz_mpoly_t gdiv, fmpz_mpoly_ctx_t ctx, slong i, slong j, const char * name, int compute_gcd_fun(fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_t, const fmpz_mpoly_ctx_t)) { int res; fmpz_mpoly_t ca, cb, cg; fmpz_mpoly_init(ca, ctx); fmpz_mpoly_init(cb, ctx); fmpz_mpoly_init(cg, ctx); res = compute_gcd_fun(g, a, b, ctx); fmpz_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_zero(gdiv, ctx)) { if (!fmpz_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(a, ctx) || !fmpz_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (fmpz_sgn(g->coeffs + 0) <= 0) { flint_printf("FAIL: Check gcd has positive lc\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fmpz_mpoly_divides(ca, a, g, ctx); res = res && fmpz_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd_fun(cg, ca, cb, ctx); fmpz_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fmpz_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } #endif TEST_FUNCTION_START(fmpz_mpoly_factor_gcd_zippel2, state) { slong i, j, tmul = 20; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t g, a, b, t; const char* vars[] = {"y", "t", "x", "z"}; fmpz_mpoly_ctx_init(ctx, 4, ORD_DEGLEX); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_set_str_pretty(t, "x+y+z+t", vars, ctx); fmpz_mpoly_set_str_pretty(a, "x^2+y^2+z^2+t^2", vars, ctx); fmpz_mpoly_set_str_pretty(b, "x^3+y^3+z^3+t^3", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 0, "example", compute_gcd); fmpz_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); fmpz_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); fmpz_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 0, "example", compute_gcd); fmpz_mpoly_set_str_pretty(t, "y + t^2 + x^3 + z^4", vars, ctx); fmpz_mpoly_set_str_pretty(a, "y*t + 1 + (x - z^5)*(y + t)", vars, ctx); fmpz_mpoly_set_str_pretty(b, "y*t + 1 + (x - z^5)*(y - t + x)", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 1, "trigger unlucky ksub", compute_gcd); fmpz_mpoly_set_str_pretty(t, "y + 33857*t^2 + 35153*x^3 + 40433*z^4", vars, ctx); fmpz_mpoly_set_str_pretty(a, "y^4 + t^3 + x^2 + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "y^3 + t^4 + x^2 + z", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 2, "trigger zipple no match", compute_gcd); fmpz_mpoly_set_str_pretty(t, "y + t + x^3 + z^3", vars, ctx); fmpz_mpoly_set_str_pretty(a, "(x - z^4)*y + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(x + z)*y + t", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 3, "trigger ksub lc kill", compute_gcd); fmpz_mpoly_set_str_pretty(t, "y + t + x^3 + z^3", vars, ctx); fmpz_mpoly_set_str_pretty(a, "(x - z^4 + 33857*(x*z))*y + 1", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(x + z)*y + t", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 4, "trigger ksub lc kill mod p", compute_gcd); fmpz_mpoly_set_str_pretty(t, "(1 + x^10)*t*y + t + x + z", vars, ctx); fmpz_mpoly_set_str_pretty(a, "(1 + x + t)*(x - 33857*x^2 + 35153*z^4)*y*t + z + x*y", vars, ctx); fmpz_mpoly_set_str_pretty(b, "(2*x - t^2)*(x - 33857*x^2 + 35153*z^4)*y^2*t + t*z + y", vars, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 5, "trigger gcd lc terms vanish mod p", compute_gcd); if (FLINT_BITS == 64) { fmpz_mpoly_set_str_pretty(t, "t*y + t + x^9999999999 + z^9999999999", vars, ctx); fmpz_mpoly_set_str_pretty(a, "t + y + x^9999999999", vars, ctx); fmpz_mpoly_set_str_pretty(b, "t^2 + t*z^9999999999 + y + 1", vars, ctx); } else { fmpz_mpoly_set_str_pretty(t, "t*y + t + x^999999 + z^9999999", vars, ctx); fmpz_mpoly_set_str_pretty(a, "t + y + x^999999", vars, ctx); fmpz_mpoly_set_str_pretty(b, "t^2 + t*z^999999 + y + 1", vars, ctx); } fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -1, 6, "trigger big p", compute_gcd); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, b, g, t; flint_bitcnt_t coeff_bits; slong len, len1, len2; slong degbound; fmpz_mpoly_ctx_init_rand(ctx, state, 20); if (ctx->minfo->nvars < 3) { fmpz_mpoly_ctx_clear(ctx); continue; } fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); len = n_randint(state, 35) + 1; len1 = n_randint(state, 35) + 1; len2 = n_randint(state, 35) + 1; degbound = 2 + 100/(2*ctx->minfo->nvars - 1); coeff_bits = n_randint(state, 100); for (j = 0; j < 4; j++) { fmpz_mpoly_randtest_bound(a, state, len1, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(b, state, len2, coeff_bits, degbound, ctx); fmpz_mpoly_randtest_bound(t, state, len, coeff_bits + 1, degbound, ctx); if (fmpz_mpoly_is_zero(t, ctx)) fmpz_mpoly_one(t, ctx); fmpz_mpoly_mul(a, a, t, ctx); fmpz_mpoly_mul(b, b, t, ctx); fmpz_mpoly_randtest_bits(g, state, len, coeff_bits, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse", compute_gcd); } fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd flint-3.1.3/src/fmpz_mpoly_factor/test/t-lcc_kaltofen.c000066400000000000000000000220251461254215100231650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mpoly_factor.h" #define FLINT_ARRAY_ALLOC(n, T) (T *) flint_malloc((n)*sizeof(T)) /* If BB and CC are squarefree factorizations, then A should be as well. */ int fmpz_mpoly_factor_mul( fmpz_mpoly_factor_t A, const fmpz_mpoly_factor_t BB, const fmpz_mpoly_factor_t CC, const fmpz_mpoly_ctx_t ctx) { int success = 0; slong i, j; fmpz_mpoly_factor_t B, C; fmpz_t t; fmpz_init(t); fmpz_mpoly_factor_init(B, ctx); fmpz_mpoly_factor_init(C, ctx); fmpz_mpoly_factor_set(B, BB, ctx); fmpz_mpoly_factor_set(C, CC, ctx); fmpz_mul(A->constant, B->constant, C->constant); A->num = 0; for (i = 0; i < B->num; i++) for (j = 0; j < C->num; j++) { fmpz_mpoly_factor_fit_length(A, A->num + 1, ctx); fmpz_add(A->exp + A->num, B->exp + i, C->exp + j); if (!fmpz_mpoly_gcd_cofactors(A->poly + A->num, B->poly + i, C->poly + j, B->poly + i, C->poly + j, ctx)) goto cleanup; if (fmpz_is_zero(A->exp + A->num)) continue; if (fmpz_mpoly_is_fmpz(A->poly + A->num, ctx)) { fmpz_mpoly_get_fmpz(t, A->poly + A->num, ctx); if (!fmpz_pow_fmpz(t, t, A->exp + A->num)) goto cleanup; fmpz_mul(A->constant, A->constant, t); } else { A->num++; } } fmpz_mpoly_factor_fit_length(A, A->num + B->num, ctx); for (i = 0; i < B->num; i++) { if (fmpz_is_zero(B->exp + i)) continue; if (fmpz_mpoly_is_fmpz(B->poly + i, ctx)) { fmpz_mpoly_get_fmpz(t, B->poly + i, ctx); if (!fmpz_pow_fmpz(t, t, B->exp + i)) goto cleanup; fmpz_mul(A->constant, A->constant, t); } else { fmpz_mpoly_swap(A->poly + A->num, B->poly + i, ctx); fmpz_swap(A->exp + A->num, B->exp + i); A->num++; } } fmpz_mpoly_factor_fit_length(A, A->num + C->num, ctx); for (j = 0; j < C->num; j++) { if (fmpz_is_zero(C->exp + j)) continue; if (fmpz_mpoly_is_fmpz(C->poly + j, ctx)) { fmpz_mpoly_get_fmpz(t, C->poly + j, ctx); if (!fmpz_pow_fmpz(t, t, C->exp + j)) goto cleanup; fmpz_mul(A->constant, A->constant, t); } else { fmpz_mpoly_swap(A->poly + A->num, C->poly + j, ctx); fmpz_swap(A->exp + A->num, C->exp + j); A->num++; } } success = 1; cleanup: fmpz_clear(t); fmpz_mpoly_factor_clear(B, ctx); fmpz_mpoly_factor_clear(C, ctx); return success; } TEST_FUNCTION_START(fmpz_mpoly_factor_lcc_kaltofen, state) { slong i, j, k, l; for (i = 0; i < 10*flint_test_multiplier(); i++) { int had_zero; slong r, v, nvars; ulong c, * bounds; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_struct A[1], t1[1], t2[1], * divs, * lcs; fmpz_mpoly_factor_t Af, tf; fmpz_poly_struct ut1[1], ut2[1], * ulcs; fmpz * alphas, * content_divs; fmpz_t g1, g2, g3; nvars = 3 + n_randint(state, 4); fmpz_mpoly_ctx_init(ctx, nvars, ORD_LEX); fmpz_mpoly_init(A, ctx); fmpz_mpoly_init(t1, ctx); fmpz_mpoly_init(t2, ctx); fmpz_mpoly_factor_init(Af, ctx); fmpz_mpoly_factor_init(tf, ctx); fmpz_poly_init(ut1); fmpz_poly_init(ut2); fmpz_init(g1); fmpz_init(g2); fmpz_init(g3); bounds = FLINT_ARRAY_ALLOC(nvars, ulong); alphas = _fmpz_vec_init(nvars - 1); fmpz_mpoly_factor_one(Af, ctx); r = 2 + n_randint(state, 4); divs = FLINT_ARRAY_ALLOC(r, fmpz_mpoly_struct); lcs = FLINT_ARRAY_ALLOC(r, fmpz_mpoly_struct); ulcs = FLINT_ARRAY_ALLOC(r, fmpz_poly_struct); content_divs = _fmpz_vec_init(r); for (j = 0; j < r; j++) { fmpz_mpoly_init(divs + j, ctx); fmpz_mpoly_one(divs + j, ctx); fmpz_mpoly_init(lcs + j, ctx); c = 1 + n_randint(state, 100); fmpz_mul_ui(Af->constant, Af->constant, c); fmpz_mpoly_set_ui(lcs + j, c, ctx); fmpz_poly_init(ulcs + j); } for (j = 0; j < 1 + 2*r/3; j++) { bounds[0] = 1; for (k = 1; k < nvars; k++) bounds[k] = 1 + n_randint(state, 4); fmpz_mpoly_randtest_bounds(t1, state, 2 + 15/r, 20, bounds, ctx); if (fmpz_mpoly_is_zero(t1, ctx)) fmpz_mpoly_one(t1, ctx); if (!fmpz_mpoly_factor_squarefree(tf, t1, ctx)) { flint_printf("FAIL:\ncheck factor_squarefree success\n"); fflush(stdout); flint_abort(); } for (k = n_randint(state, 3); k >= 0; k--) { l = n_randint(state, r); fmpz_mpoly_mul(lcs + l, lcs + l, t1, ctx); fmpz_mpoly_factor_mul(Af, Af, tf, ctx); } } fmpz_mpoly_one(A, ctx); for (j = 0; j < r; j++) fmpz_mpoly_mul(A, A, lcs + j, ctx); for (j = 0; j < nvars - 1; j++) { fmpz_set_ui(alphas + j, n_urandint(state, 100)); if (n_randint(state, 2)) fmpz_neg(alphas + j, alphas + j); } had_zero = 0; for (v = 1; v < nvars; v++) { int have_zero = 0; for (j = 0; j < r; j++) { fmpz_mpoly_evaluate_rest_except_one(ut1, lcs + j, alphas, v, ctx); fmpz_mpoly_evaluate_rest_except_one(ut2, divs + j, alphas, v, ctx); if (fmpz_poly_is_zero(ut1) || fmpz_poly_is_zero(ut2)) { have_zero = 1; had_zero = 1; } else { fmpz_poly_primitive_part(ut2, ut2); if (!fmpz_poly_divides(ulcs + j, ut1, ut2)) { flint_printf("FAIL:\nbad divisor\n"); fflush(stdout); flint_abort(); } } } if (have_zero) continue; fmpz_mpoly_factor_lcc_kaltofen_step(divs, r, Af, ulcs, v, alphas, ctx); } if (Af->num == 0 && !had_zero) { for (j = 0; j < r; j++) fmpz_one(content_divs + j); for (v = 1; v < nvars; v++) { for (j = 0; j < r; j++) { fmpz_mpoly_evaluate_rest_except_one(ut1, lcs + j, alphas, v, ctx); fmpz_mpoly_evaluate_rest_except_one(ut2, divs + j, alphas, v, ctx); _fmpz_vec_content(g1, ut1->coeffs, ut1->length); _fmpz_vec_content(g2, ut2->coeffs, ut2->length); fmpz_gcd(g3, g1, g2); fmpz_divexact(g1, g1, g3); fmpz_lcm(content_divs + j, content_divs + j, g1); } } for (j = 0; j < r; j++) { if (!fmpz_divisible(Af->constant, content_divs + j)) { flint_printf("FAIL:\nbad divisor\n"); fflush(stdout); flint_abort(); } fmpz_divexact(Af->constant, Af->constant, content_divs + j); fmpz_mpoly_scalar_mul_fmpz(divs + j, divs + j, content_divs + j, ctx); if (!fmpz_mpoly_divides(t1, lcs + j, divs + j, ctx)) { flint_printf("FAIL:\nbad divisor\n"); fflush(stdout); flint_abort(); } } } _fmpz_vec_clear(content_divs, r); fmpz_clear(g1); fmpz_clear(g2); fmpz_clear(g3); flint_free(bounds); _fmpz_vec_clear(alphas, nvars - 1); for (j = 0; j < r; j++) { fmpz_mpoly_clear(divs + j, ctx); fmpz_mpoly_clear(lcs + j, ctx); fmpz_poly_clear(ulcs + j); } flint_free(divs); flint_free(lcs); flint_free(ulcs); fmpz_mpoly_clear(A, ctx); fmpz_mpoly_clear(t1, ctx); fmpz_mpoly_clear(t2, ctx); fmpz_mpoly_factor_clear(Af, ctx); fmpz_mpoly_factor_clear(tf, ctx); fmpz_poly_clear(ut1); fmpz_poly_clear(ut2); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/test/t-poly_pfrac.c000066400000000000000000000124451461254215100227040ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_mpoly_factor.h" #include "fmpq_poly.h" void _test_pfrac( fmpz_poly_struct * c, fmpz_poly_pfrac_t I, const fmpz_poly_struct * b, slong r, flint_rand_t state) { slong i, j; int success, found_bad; fmpq_poly_struct * cQ, * bQ, * prod_bQ, * inv_prod_bQ; fmpq_poly_t aQ, pQ, G, S; fmpz_poly_t a, t, t1; cQ = FLINT_ARRAY_ALLOC(r, fmpq_poly_struct); bQ = FLINT_ARRAY_ALLOC(r, fmpq_poly_struct); prod_bQ = FLINT_ARRAY_ALLOC(r, fmpq_poly_struct); inv_prod_bQ = FLINT_ARRAY_ALLOC(r, fmpq_poly_struct); for (i = 0; i < r; i++) { fmpq_poly_init(cQ + i); fmpq_poly_init(bQ + i); fmpq_poly_init(prod_bQ + i); fmpq_poly_init(inv_prod_bQ + i); } fmpz_poly_init(a); fmpz_poly_init(t); fmpz_poly_init(t1); fmpq_poly_init(aQ); fmpq_poly_init(pQ); fmpq_poly_init(G); fmpq_poly_init(S); fmpq_poly_one(pQ); for (i = 0; i < r; i++) { fmpq_poly_set_fmpz_poly(bQ + i, b + i); fmpq_poly_mul(pQ, pQ, bQ + i); } success = 1; for (i = 0; i < r; i++) { fmpq_poly_divrem(prod_bQ + i, G, pQ, bQ + i); fmpq_poly_xgcd(G, S, inv_prod_bQ + i, bQ + i, prod_bQ + i); if (!fmpq_poly_is_one(G)) success = 0; } if (success != fmpz_poly_pfrac_precompute(I, b, r)) { flint_printf("FAIL: check precompute\n"); fflush(stdout); flint_abort(); } if (!success) goto cleanup; for (j = 0; j < 20; j++) { if (j % 6) { fmpz_poly_zero(a); fmpz_poly_one(t); for (i = 0; i < r; i++) { fmpz_poly_randtest(t1, state, fmpz_poly_degree(b + i), 2 + n_randint(state, 200)); fmpz_poly_mul(t1, t1, t); fmpz_poly_mul(a, a, b + i); fmpz_poly_add(a, a, t1); fmpz_poly_mul(t, t, b + i); } } else { fmpz_poly_randtest(a, state, n_randint(state, pQ->length), 2 + n_randint(state, 200)); } FLINT_ASSERT(a->length < pQ->length); fmpq_poly_set_fmpz_poly(aQ, a); found_bad = 0; for (i = 0; i < r; i++) { fmpq_poly_mul(S, aQ, inv_prod_bQ + i); fmpq_poly_rem(cQ + i, S, bQ + i); if (!fmpz_is_one(cQ[i].den)) found_bad = 1; } if (fmpz_poly_pfrac_precomp(c, a, I)) { if (found_bad) { flint_printf("FAIL: precomp should have failed"); fflush(stdout); flint_abort(); } for (i = 0; i < r; i++) { fmpq_poly_set_fmpz_poly(S, c + i); if (!fmpq_poly_equal(S, cQ + i)) { flint_printf("FAIL: precomp produced wrong answer\n"); fflush(stdout); flint_abort(); } } } else { if (!found_bad) { flint_printf("FAIL: precomp should not have failed\n"); fflush(stdout); flint_abort(); } } } cleanup: for (i = 0; i < r; i++) { fmpq_poly_clear(cQ + i); fmpq_poly_clear(bQ + i); fmpq_poly_clear(prod_bQ + i); fmpq_poly_clear(inv_prod_bQ + i); } flint_free(cQ); flint_free(bQ); flint_free(prod_bQ); flint_free(inv_prod_bQ); fmpz_poly_clear(a); fmpz_poly_clear(t); fmpz_poly_clear(t1); fmpq_poly_clear(aQ); fmpq_poly_clear(pQ); fmpq_poly_clear(G); fmpq_poly_clear(S); } TEST_FUNCTION_START(fmpz_poly_pfrac, state) { slong i, j, k, tmul = 10; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_pfrac_t I; fmpz_poly_pfrac_init(I); for (j = 0; j < tmul; j++) { fmpz_poly_struct * b, * c; slong n = 2 + n_randint(state, 5); b = FLINT_ARRAY_ALLOC(n, fmpz_poly_struct); c = FLINT_ARRAY_ALLOC(n, fmpz_poly_struct); for (k = 0; k < n; k++) { fmpz_poly_init(c + k); fmpz_poly_init(b + k); do { fmpz_poly_randtest(b + k, state, 2 + n_randint(state, 5), 2 + n_randint(state, 350)); } while (b[k].length < 2); } _test_pfrac(c, I, b, n, state); for (k = 0; k < n; k++) { fmpz_poly_clear(c + k); fmpz_poly_clear(b + k); } flint_free(c); flint_free(b); } fmpz_poly_pfrac_clear(I); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_factor/tpoly.c000066400000000000000000000022651461254215100204740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" void fmpz_tpoly_fit_length(fmpz_tpoly_t A, slong len) { slong i; if (len <= A->alloc) return; if (len < 2 * A->alloc) len = 2 * A->alloc; if (A->alloc > 0) A->coeffs = (fmpz_bpoly_struct *) flint_realloc(A->coeffs, len * sizeof(fmpz_bpoly_struct)); else A->coeffs = (fmpz_bpoly_struct *) flint_malloc( len * sizeof(fmpz_bpoly_struct)); for (i = A->alloc; i < len; i++) fmpz_bpoly_init(A->coeffs + i); A->alloc = len; } void fmpz_tpoly_clear(fmpz_tpoly_t A) { if (A->alloc > 0) { slong i; for (i = 0; i < A->alloc; i++) fmpz_bpoly_clear(A->coeffs + i); flint_free(A->coeffs); } } flint-3.1.3/src/fmpz_mpoly_factor/tuple.c000066400000000000000000000037151461254215100204570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mpoly_factor.h" void tuple_print(fmpz * alpha, slong n) { slong j; for (j = 0; j < n; j++) { fmpz_print(alpha + j); flint_printf(j + 1 < n ? ", " : "\n"); } } /* ensure that the first m values change upon the next call to tuple_next*/ void tuple_saturate(fmpz * alpha, slong n, slong m) { slong i; for (i = m + 1; i < n; i++) { fmpz_add(alpha + m, alpha + m, alpha + i); fmpz_zero(alpha + i); } if (m < n && fmpz_is_zero(alpha + m)) { for (i = 0; i < m; i++) if (!fmpz_is_zero(alpha + i)) return; fmpz_one(alpha + m); } } void tuple_next(fmpz * alpha, slong n) { slong i, t1, t2, t3; fmpz_t sum; fmpz_init(sum); for (i = 0; i < n; i++) fmpz_add(sum, sum, alpha + i); i = n - 1; while(i >= 0 && fmpz_is_zero(alpha + i)) i--; t1 = i; while(i >= 0 && fmpz_cmp(alpha + i, sum) != 0) i--; t2 = i; while(i >= 0 && fmpz_cmp(alpha + i, sum) == 0) i--; t3 = i; if (t1 > 0 && t1 != t2) { fmpz_swap(alpha + t1, alpha + n - 1); fmpz_sub_ui(alpha + n - 1, alpha + n - 1, 1); fmpz_add_ui(alpha + t1 - 1, alpha + t1 - 1, 1); } else if (t1 > 0 && t1 == t2 && t3 >= 0) { fmpz_add_ui(alpha + t3, alpha + t3, 1); fmpz_zero(alpha + t3 + 1); fmpz_sub_ui(alpha + n - 1, sum, 1); } else { fmpz_add_ui(alpha + n - 1, alpha + 0, 1); if (n > 1) fmpz_zero(alpha + 0); } fmpz_clear(sum); } flint-3.1.3/src/fmpz_mpoly_q.h000066400000000000000000000234241461254215100163140ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MPOLY_Q_H #define FMPZ_MPOLY_Q_H #ifdef FMPZ_MPOLY_Q_INLINES_C #define FMPZ_MPOLY_Q_INLINE #else #define FMPZ_MPOLY_Q_INLINE static inline #endif #ifdef __cplusplus extern "C" { #endif #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mpoly.h" #include "acb_types.h" #define fmpz_mpoly_q_numref(x) (&((x)->num)) #define fmpz_mpoly_q_denref(x) (&((x)->den)) /* Memory management */ void fmpz_mpoly_q_init(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_clear(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx); /* Assignment */ void fmpz_mpoly_q_swap(fmpz_mpoly_q_t x, fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_set(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_set_fmpq(fmpz_mpoly_q_t res, const fmpq_t x, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_set_fmpz(fmpz_mpoly_q_t res, const fmpz_t x, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_set_si(fmpz_mpoly_q_t res, slong x, const fmpz_mpoly_ctx_t ctx); /* Canonicalisation */ void fmpz_mpoly_q_canonicalise(fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_q_is_canonical(const fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx); /* Properties */ FMPZ_MPOLY_Q_INLINE int fmpz_mpoly_q_is_zero(const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_is_zero(fmpz_mpoly_q_numref(x), ctx); } FMPZ_MPOLY_Q_INLINE int fmpz_mpoly_q_is_one(const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_is_one(fmpz_mpoly_q_numref(x), ctx) && fmpz_mpoly_is_one(fmpz_mpoly_q_denref(x), ctx); } FMPZ_MPOLY_Q_INLINE int fmpz_mpoly_q_is_fmpz(const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_is_fmpz(fmpz_mpoly_q_numref(x), ctx) && fmpz_mpoly_is_one(fmpz_mpoly_q_denref(x), ctx); } FMPZ_MPOLY_Q_INLINE int fmpz_mpoly_q_is_fmpq(const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_is_fmpz(fmpz_mpoly_q_numref(x), ctx) && fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(x), ctx); } void fmpz_mpoly_q_used_vars(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_used_vars_num(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_used_vars_den(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx); /* Special values */ FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_zero(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_zero(fmpz_mpoly_q_numref(res), ctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_one(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_one(fmpz_mpoly_q_numref(res), ctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_gen(fmpz_mpoly_q_t res, slong i, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_gen(fmpz_mpoly_q_numref(res), i, ctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } /* Input and output */ void fmpz_mpoly_q_print_pretty(const fmpz_mpoly_q_t f, const char ** x, const fmpz_mpoly_ctx_t ctx); char * fmpz_mpoly_q_get_str_pretty(const fmpz_mpoly_q_t f, const char ** vars, const fmpz_mpoly_ctx_t ctx); int fmpz_mpoly_q_set_str_pretty(fmpz_mpoly_q_t res, const char * s, const char ** vars, fmpz_mpoly_ctx_t ctx); /* Random generation */ void fmpz_mpoly_q_randtest(fmpz_mpoly_q_t res, flint_rand_t state, slong length, mp_limb_t coeff_bits, slong exp_bound, const fmpz_mpoly_ctx_t ctx); /* Comparisons */ int fmpz_mpoly_q_equal(const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx); /* Arithmetic */ void fmpz_mpoly_q_neg(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_add(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_sub(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_mul(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_div(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_inv(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_q_add(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_q_sub(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_q_mul(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_q_div(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_q_add_fmpq(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx); void _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_add_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_add_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_sub_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_mul_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_div_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_q_div_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_add_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, c); fmpz_mpoly_q_add_fmpz(res, x, t, ctx); fmpz_clear(t); } FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_sub_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, c); fmpz_mpoly_q_sub_fmpz(res, x, t, ctx); fmpz_clear(t); } FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_mul_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, c); fmpz_mpoly_q_mul_fmpz(res, x, t, ctx); fmpz_clear(t); } FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_div_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, slong c, const fmpz_mpoly_ctx_t ctx) { fmpz_t t; fmpz_init_set_si(t, c); fmpz_mpoly_q_div_fmpz(res, x, t, ctx); fmpz_clear(t); } /* Polynomial helper functions */ FMPZ_MPOLY_Q_INLINE void _fmpz_vec_content2(fmpz_t res, const fmpz * vec, slong len, const fmpz_t inp) { if (fmpz_is_pm1(inp)) { fmpz_one(res); } else { slong i; fmpz_abs(res, inp); for (i = len - 1; i >= 0; i--) { fmpz_gcd(res, res, vec + i); if (fmpz_is_one(res)) break; } } } FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_gcd_assert_successful(fmpz_mpoly_t res, const fmpz_mpoly_t x, const fmpz_mpoly_t y, const fmpz_mpoly_ctx_t ctx) { if (!fmpz_mpoly_gcd(res, x, y, ctx)) { flint_throw(FLINT_ERROR, "fmpz_mpoly_gcd failed\n"); } } FMPZ_MPOLY_Q_INLINE void _fmpz_mpoly_q_mpoly_divexact(fmpz_mpoly_t res, const fmpz_mpoly_t x, const fmpz_mpoly_t y, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_fmpz(y, ctx)) fmpz_mpoly_scalar_divexact_fmpz(res, x, y->coeffs, ctx); else fmpz_mpoly_div(res, x, y, ctx); } /* Content */ FMPZ_MPOLY_Q_INLINE void _fmpz_mpoly_q_content(fmpz_t num, fmpz_t den, const fmpz_mpoly_t xnum, const fmpz_mpoly_t xden, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(xnum, ctx)) { fmpz_one(num); fmpz_one(den); } else { _fmpz_vec_content(den, xden->coeffs, xden->length); _fmpz_vec_content(num, xnum->coeffs, xnum->length); } } FMPZ_MPOLY_Q_INLINE void fmpz_mpoly_q_content(fmpq_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_content(fmpq_numref(res), fmpq_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), ctx); } /* Evaluation */ void fmpz_mpoly_q_evaluate_acb(acb_t res, const fmpz_mpoly_q_t f, acb_srcptr x, slong prec, const fmpz_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_mpoly_q/000077500000000000000000000000001461254215100161365ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly_q/add.c000066400000000000000000000351341461254215100170400ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" static void _fmpz_mpoly_q_add_fmpz_mpoly_den(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx) { fmpz_t g; fmpz_init(g); if (fmpz_mpoly_is_fmpz(y_num, ctx)) { if (res_num == x_num || res_num == y_num) { fmpz_t t, u; fmpz_init_set(t, y_num->coeffs); fmpz_init_set(u, y_den); _fmpz_mpoly_q_add_fmpq(res_num, res_den, x_num, x_den, t, u, ctx); fmpz_clear(t); fmpz_clear(u); } else { _fmpz_mpoly_q_add_fmpq(res_num, res_den, x_num, x_den, y_num->coeffs, y_den, ctx); } return; } if (fmpz_mpoly_is_fmpz(x_den, ctx)) { fmpz_gcd(g, x_den->coeffs, y_den); if (fmpz_is_one(g)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); /* todo: avoid one alloc? not helpful right now because fmpz_mpoly_add does not work inplace */ fmpz_mpoly_scalar_mul_fmpz(t, y_num, x_den->coeffs, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, y_den, ctx); fmpz_mpoly_add(res_num, t, u, ctx); fmpz_mul(g, x_den->coeffs, y_den); fmpz_mpoly_set_fmpz(res_den, g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_t a, b; fmpz_mpoly_t t, u; fmpz_init(a); fmpz_init(b); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_divexact(a, y_den, g); fmpz_divexact(b, x_den->coeffs, g); fmpz_mpoly_scalar_mul_fmpz(t, y_num, b, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, a, ctx); fmpz_mpoly_add(res_num, t, u, ctx); if (fmpz_mpoly_is_zero(res_num, ctx)) fmpz_one(a); else _fmpz_vec_content2(a, res_num->coeffs, res_num->length, g); if (fmpz_is_one(a)) { fmpz_mul(g, b, y_den); fmpz_mpoly_set_fmpz(res_den, g, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, a, ctx); fmpz_divexact(g, y_den, a); fmpz_mul(g, g, b); fmpz_mpoly_set_fmpz(res_den, g, ctx); } fmpz_clear(a); fmpz_clear(b); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } } else { _fmpz_vec_content2(g, x_den->coeffs, x_den->length, y_den); if (fmpz_is_one(g)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); /* todo: avoid one alloc? not helpful right now because fmpz_mpoly_add does not work inplace */ fmpz_mpoly_mul(t, y_num, x_den, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, y_den, ctx); fmpz_mpoly_add(res_num, t, u, ctx); fmpz_set(g, y_den); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_t a; fmpz_mpoly_t b, t, u; fmpz_init(a); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_divexact(a, y_den, g); fmpz_mpoly_scalar_divexact_fmpz(b, x_den, g, ctx); fmpz_mpoly_mul(t, y_num, b, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, a, ctx); fmpz_mpoly_add(res_num, t, u, ctx); if (fmpz_mpoly_is_zero(res_num, ctx)) fmpz_one(a); else _fmpz_vec_content2(a, res_num->coeffs, res_num->length, g); if (fmpz_is_one(a)) { fmpz_set(g, y_den); fmpz_mpoly_scalar_mul_fmpz(res_den, b, g, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, a, ctx); fmpz_divexact(g, y_den, a); fmpz_mpoly_scalar_mul_fmpz(res_den, b, g, ctx); } fmpz_clear(a); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } } fmpz_clear(g); } void _fmpz_mpoly_q_add(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(x_num, ctx)) { fmpz_mpoly_set(res_num, y_num, ctx); fmpz_mpoly_set(res_den, y_den, ctx); return; } if (fmpz_mpoly_is_zero(y_num, ctx)) { fmpz_mpoly_set(res_num, x_num, ctx); fmpz_mpoly_set(res_den, x_den, ctx); return; } if (fmpz_mpoly_equal(x_den, y_den, ctx)) { fmpz_mpoly_add(res_num, x_num, y_num, ctx); if (fmpz_mpoly_is_one(x_den, ctx) || fmpz_mpoly_is_zero(res_num, ctx)) { fmpz_mpoly_one(res_den, ctx); } else if (fmpz_mpoly_is_fmpz(x_den, ctx)) { fmpz_t t; fmpz_init(t); _fmpz_vec_content2(t, res_num->coeffs, res_num->length, x_den->coeffs); if (fmpz_is_one(t)) { fmpz_mpoly_set(res_den, x_den, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, t, ctx); fmpz_mpoly_scalar_divexact_fmpz(res_den, x_den, t, ctx); } fmpz_clear(t); } else { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_gcd_assert_successful(t, res_num, x_den, ctx); if (fmpz_mpoly_is_one(t, ctx)) { fmpz_mpoly_set(res_den, x_den, ctx); } else { _fmpz_mpoly_q_mpoly_divexact(res_num, res_num, t, ctx); _fmpz_mpoly_q_mpoly_divexact(res_den, x_den, t, ctx); } fmpz_mpoly_clear(t, ctx); } return; } if (fmpz_mpoly_is_one(x_den, ctx)) { if (res_num == y_num) { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_mul(t, x_num, y_den, ctx); fmpz_mpoly_add(res_num, t, y_num, ctx); fmpz_mpoly_clear(t, ctx); } else { fmpz_mpoly_mul(res_num, x_num, y_den, ctx); fmpz_mpoly_add(res_num, res_num, y_num, ctx); } fmpz_mpoly_set(res_den, y_den, ctx); return; } if (fmpz_mpoly_is_one(y_den, ctx)) { if (res_num == x_num) { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_mul(t, y_num, x_den, ctx); fmpz_mpoly_add(res_num, x_num, t, ctx); fmpz_mpoly_clear(t, ctx); } else { fmpz_mpoly_mul(res_num, y_num, x_den, ctx); fmpz_mpoly_add(res_num, x_num, res_num, ctx); } fmpz_mpoly_set(res_den, x_den, ctx); return; } if (fmpz_mpoly_is_fmpz(y_den, ctx)) { _fmpz_mpoly_q_add_fmpz_mpoly_den(res_num, res_den, x_num, x_den, y_num, y_den->coeffs, ctx); return; } if (fmpz_mpoly_is_fmpz(x_den, ctx)) { _fmpz_mpoly_q_add_fmpz_mpoly_den(res_num, res_den, y_num, y_den, x_num, x_den->coeffs, ctx); return; } { fmpz_mpoly_t g; fmpz_mpoly_init(g, ctx); fmpz_mpoly_gcd_assert_successful(g, x_den, y_den, ctx); if (fmpz_mpoly_is_one(g, ctx)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); /* todo: avoid one alloc? not helpful right now because fmpz_mpoly_add does not work inplace */ fmpz_mpoly_mul(t, x_num, y_den, ctx); fmpz_mpoly_mul(u, y_num, x_den, ctx); fmpz_mpoly_add(res_num, t, u, ctx); fmpz_mpoly_mul(res_den, x_den, y_den, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_mpoly_t a, b, t, u; fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); _fmpz_mpoly_q_mpoly_divexact(a, x_den, g, ctx); _fmpz_mpoly_q_mpoly_divexact(b, y_den, g, ctx); fmpz_mpoly_mul(t, x_num, b, ctx); fmpz_mpoly_mul(u, y_num, a, ctx); fmpz_mpoly_add(res_num, t, u, ctx); fmpz_mpoly_gcd_assert_successful(t, res_num, g, ctx); if (fmpz_mpoly_is_one(t, ctx)) { fmpz_mpoly_mul(res_den, x_den, b, ctx); } else { _fmpz_mpoly_q_mpoly_divexact(res_num, res_num, t, ctx); _fmpz_mpoly_q_mpoly_divexact(g, x_den, t, ctx); fmpz_mpoly_mul(res_den, g, b, ctx); } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } fmpz_mpoly_clear(g, ctx); } } void _fmpz_mpoly_q_add_fmpq(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(x_num, ctx)) { fmpz_mpoly_set_fmpz(res_num, y_num, ctx); fmpz_mpoly_set_fmpz(res_den, y_den, ctx); return; } if (fmpz_is_zero(y_num)) { fmpz_mpoly_set(res_num, x_num, ctx); fmpz_mpoly_set(res_den, x_den, ctx); return; } /* todo: special-case integer x_den */ if (fmpz_mpoly_equal_fmpz(x_den, y_den, ctx)) { fmpz_mpoly_add_fmpz(res_num, x_num, y_num, ctx); if (fmpz_is_one(y_den)) { fmpz_mpoly_one(res_den, ctx); } else { fmpz_t t; fmpz_init(t); _fmpz_vec_content2(t, res_num->coeffs, res_num->length, y_den); if (fmpz_is_one(t)) { fmpz_mpoly_set(res_den, x_den, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, t, ctx); fmpz_divexact(t, y_den, t); fmpz_mpoly_set_fmpz(res_den, t, ctx); } fmpz_clear(t); } return; } if (fmpz_mpoly_is_one(x_den, ctx)) { fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, y_den, ctx); fmpz_mpoly_add_fmpz(res_num, res_num, y_num, ctx); fmpz_mpoly_set_fmpz(res_den, y_den, ctx); return; } if (fmpz_is_one(y_den)) { if (res_num == x_num) { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_scalar_mul_fmpz(t, x_den, y_num, ctx); fmpz_mpoly_add(res_num, x_num, t, ctx); fmpz_mpoly_clear(t, ctx); } else { fmpz_mpoly_scalar_mul_fmpz(res_num, x_den, y_num, ctx); fmpz_mpoly_add(res_num, x_num, res_num, ctx); } fmpz_mpoly_set(res_den, x_den, ctx); return; } { fmpz_t g; fmpz_init(g); _fmpz_vec_content2(g, x_den->coeffs, x_den->length, y_den); if (fmpz_is_one(g)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_scalar_mul_fmpz(t, x_num, y_den, ctx); /* todo: avoid one alloc? */ fmpz_mpoly_scalar_mul_fmpz(u, x_den, y_num, ctx); fmpz_mpoly_add(res_num, t, u, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, y_den, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_mpoly_t t, u; fmpz_t b, c; fmpz_init(b); fmpz_init(c); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_scalar_divexact_fmpz(u, x_den, g, ctx); fmpz_divexact(b, y_den, g); fmpz_mpoly_scalar_mul_fmpz(t, x_num, b, ctx); fmpz_mpoly_scalar_mul_fmpz(u, u, y_num, ctx); fmpz_mpoly_add(res_num, t, u, ctx); _fmpz_vec_content2(c, res_num->coeffs, res_num->length, g); if (fmpz_is_one(c)) { fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, b, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, c, ctx); fmpz_mpoly_scalar_divexact_fmpz(res_den, x_den, c, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, res_den, b, ctx); } fmpz_clear(b); fmpz_clear(c); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } fmpz_clear(g); } } void fmpz_mpoly_q_add(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_add(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpz_mpoly_q_numref(y), fmpz_mpoly_q_denref(y), ctx); } void fmpz_mpoly_q_add_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_add_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpq_numref(y), fmpq_denref(y), ctx); } void fmpz_mpoly_q_add_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) { fmpz_t one; *one = 1; _fmpz_mpoly_q_add_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), y, one, ctx); } flint-3.1.3/src/fmpz_mpoly_q/canonicalise.c000066400000000000000000000050311461254215100207310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_canonicalise(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(res), ctx)) { return; } else if (fmpz_mpoly_is_zero(fmpz_mpoly_q_numref(res), ctx)) { fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); return; } else if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(res), ctx)) { fmpz_t g; fmpz_init(g); _fmpz_vec_content(g, fmpz_mpoly_q_numref(res)->coeffs, fmpz_mpoly_q_numref(res)->length); fmpz_gcd(g, g, fmpz_mpoly_q_denref(res)->coeffs); if (fmpz_sgn(fmpz_mpoly_q_denref(res)->coeffs) < 0) fmpz_neg(g, g); if (!fmpz_is_one(g)) { fmpz_mpoly_scalar_divexact_fmpz(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(res), g, ctx); fmpz_divexact(fmpz_mpoly_q_denref(res)->coeffs, fmpz_mpoly_q_denref(res)->coeffs, g); } fmpz_clear(g); } else if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_numref(res), ctx)) { fmpz_t g; fmpz_init(g); _fmpz_vec_content(g, fmpz_mpoly_q_denref(res)->coeffs, fmpz_mpoly_q_denref(res)->length); fmpz_gcd(g, g, fmpz_mpoly_q_numref(res)->coeffs); if (fmpz_sgn(fmpz_mpoly_q_denref(res)->coeffs) < 0) fmpz_neg(g, g); if (!fmpz_is_one(g)) { fmpz_mpoly_scalar_divexact_fmpz(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(res), g, ctx); fmpz_divexact(fmpz_mpoly_q_numref(res)->coeffs, fmpz_mpoly_q_numref(res)->coeffs, g); } fmpz_clear(g); } else { fmpz_mpoly_t g; fmpz_mpoly_init(g, ctx); fmpz_mpoly_gcd_assert_successful(g, fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), ctx); if (fmpz_sgn(fmpz_mpoly_q_denref(res)->coeffs) < 0) fmpz_mpoly_neg(g, g, ctx); if (!fmpz_mpoly_is_one(g, ctx)) { _fmpz_mpoly_q_mpoly_divexact(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(res), g, ctx); _fmpz_mpoly_q_mpoly_divexact(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(res), g, ctx); } fmpz_mpoly_clear(g, ctx); } } flint-3.1.3/src/fmpz_mpoly_q/clear.c000066400000000000000000000011201461254215100173620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_clear(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_clear(fmpz_mpoly_q_numref(res), ctx); fmpz_mpoly_clear(fmpz_mpoly_q_denref(res), ctx); } flint-3.1.3/src/fmpz_mpoly_q/div.c000066400000000000000000000075261461254215100170760ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_mpoly_q.h" void _fmpz_mpoly_q_div(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(y_num, ctx)) { flint_throw(FLINT_ERROR, "_fmpz_mpoly_q_div: division by zero\n"); } if (fmpz_mpoly_is_zero(x_num, ctx) || fmpz_mpoly_is_zero(y_num, ctx)) { fmpz_mpoly_zero(res_num, ctx); fmpz_mpoly_one(res_den, ctx); return; } if (res_num == y_num) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); _fmpz_mpoly_q_mul(t, u, x_num, x_den, y_den, y_num, ctx); fmpz_mpoly_swap(res_num, t, ctx); fmpz_mpoly_swap(res_den, u, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { _fmpz_mpoly_q_mul(res_num, res_den, x_num, x_den, y_den, y_num, ctx); } if (fmpz_sgn(res_den->coeffs) < 0) { fmpz_mpoly_neg(res_num, res_num, ctx); fmpz_mpoly_neg(res_den, res_den, ctx); } } void fmpz_mpoly_q_div(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_div(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpz_mpoly_q_numref(y), fmpz_mpoly_q_denref(y), ctx); } void fmpz_mpoly_q_div_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) { if (fmpq_is_zero(y)) { flint_throw(FLINT_ERROR, "fmpz_mpoly_q_div_fmpq: division by zero\n"); } else { if (fmpz_sgn(fmpq_numref(y)) > 0) { _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpq_denref(y), fmpq_numref(y), ctx); } else { fmpz_t t, u; fmpz_init(t); fmpz_init(u); fmpz_neg(t, fmpq_numref(y)); fmpz_neg(u, fmpq_denref(y)); _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), u, t, ctx); fmpz_clear(t); fmpz_clear(u); } } } void fmpz_mpoly_q_div_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) { if (fmpz_is_zero(y)) { flint_throw(FLINT_ERROR, "fmpz_mpoly_q_div_fmpz: division by zero\n"); } else { if (fmpz_sgn(y) > 0) { fmpz_t one; *one = 1; _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), one, y, ctx); } else { fmpz_t t; fmpz_t one; *one = -1; fmpz_init(t); fmpz_neg(t, y); _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), one, t, ctx); fmpz_clear(t); } } } flint-3.1.3/src/fmpz_mpoly_q/equal.c000066400000000000000000000012501461254215100174070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" int fmpz_mpoly_q_equal(const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) { return fmpz_mpoly_equal(fmpz_mpoly_q_numref(x), fmpz_mpoly_q_numref(y), ctx) && fmpz_mpoly_equal(fmpz_mpoly_q_denref(x), fmpz_mpoly_q_denref(y), ctx); } flint-3.1.3/src/fmpz_mpoly_q/evaluate_acb.c000066400000000000000000000031631461254215100207200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb.h" #include "fmpz_mpoly.h" #include "fmpz_mpoly_q.h" #include "gr.h" #include "gr_generic.h" void fmpz_mpoly_evaluate_acb(acb_t res, const fmpz_mpoly_t pol, acb_srcptr x, slong prec, const fmpz_mpoly_ctx_t ctx) { gr_ctx_t CC; gr_ctx_init_complex_acb(CC, prec); if (pol->length <= 6 && pol->bits <= FLINT_BITS) { if (gr_fmpz_mpoly_evaluate_iter(res, pol, x, ctx, CC) != GR_SUCCESS) acb_indeterminate(res); } else { if (gr_fmpz_mpoly_evaluate_horner(res, pol, x, ctx, CC) != GR_SUCCESS) acb_indeterminate(res); } } void fmpz_mpoly_q_evaluate_acb(acb_t res, const fmpz_mpoly_q_t f, acb_srcptr x, slong prec, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(f), ctx)) { fmpz_mpoly_evaluate_acb(res, fmpz_mpoly_q_numref(f), x, prec, ctx); } else { acb_t t; acb_init(t); fmpz_mpoly_evaluate_acb(t, fmpz_mpoly_q_denref(f), x, prec, ctx); if (acb_contains_zero(t)) { acb_indeterminate(res); } else { fmpz_mpoly_evaluate_acb(res, fmpz_mpoly_q_numref(f), x, prec, ctx); acb_div(res, res, t, prec); } acb_clear(t); } } flint-3.1.3/src/fmpz_mpoly_q/init.c000066400000000000000000000012001461254215100172360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_init(fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_init(fmpz_mpoly_q_numref(res), ctx); fmpz_mpoly_init(fmpz_mpoly_q_denref(res), ctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } flint-3.1.3/src/fmpz_mpoly_q/inlines.c000066400000000000000000000006701461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_MPOLY_Q_INLINES_C #include "fmpz_mpoly_q.h" flint-3.1.3/src/fmpz_mpoly_q/inv.c000066400000000000000000000017731461254215100171060ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_inv(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(fmpz_mpoly_q_numref(x), ctx)) { flint_throw(FLINT_ERROR, "fmpz_mpoly_q_inv: division by zero\n"); } if (res != x) fmpz_mpoly_q_set(res, x, ctx); fmpz_mpoly_swap(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), ctx); if (fmpz_sgn(fmpz_mpoly_q_denref(res)->coeffs) < 0) { fmpz_mpoly_neg(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(res), ctx); fmpz_mpoly_neg(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(res), ctx); } } flint-3.1.3/src/fmpz_mpoly_q/is_canonical.c000066400000000000000000000021201461254215100207170ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" int fmpz_mpoly_q_is_canonical(const fmpz_mpoly_q_t res, const fmpz_mpoly_ctx_t ctx) { if (!fmpz_mpoly_is_canonical(fmpz_mpoly_q_numref(res), ctx)) return 0; if (!fmpz_mpoly_is_canonical(fmpz_mpoly_q_denref(res), ctx)) return 0; if (fmpz_mpoly_is_zero(fmpz_mpoly_q_denref(res), ctx)) return 0; if (fmpz_sgn(fmpz_mpoly_q_denref(res)->coeffs) < 0) return 0; { int ans; fmpz_mpoly_t g; fmpz_mpoly_init(g, ctx); fmpz_mpoly_gcd_assert_successful(g, fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), ctx); ans = fmpz_mpoly_is_one(g, ctx); fmpz_mpoly_clear(g, ctx); return ans; } } flint-3.1.3/src/fmpz_mpoly_q/mul.c000066400000000000000000000212341461254215100171010ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void _fmpz_mpoly_q_mul(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(x_num, ctx) || fmpz_mpoly_is_zero(y_num, ctx)) { fmpz_mpoly_zero(res_num, ctx); fmpz_mpoly_one(res_den, ctx); return; } if (fmpz_mpoly_equal(x_den, y_den, ctx)) { fmpz_mpoly_mul(res_num, x_num, y_num, ctx); fmpz_mpoly_mul(res_den, x_den, y_den, ctx); return; } /* todo: special-case integer denominators; scalar multiplication */ if (fmpz_mpoly_is_one(x_den, ctx)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_gcd_assert_successful(t, x_num, y_den, ctx); if (fmpz_mpoly_is_one(t, ctx)) { fmpz_mpoly_mul(res_num, x_num, y_num, ctx); fmpz_mpoly_mul(res_den, x_den, y_den, ctx); } else { fmpz_mpoly_init(u, ctx); _fmpz_mpoly_q_mpoly_divexact(u, x_num, t, ctx); fmpz_mpoly_mul(res_num, u, y_num, ctx); _fmpz_mpoly_q_mpoly_divexact(u, y_den, t, ctx); fmpz_mpoly_mul(res_den, x_den, u, ctx); fmpz_mpoly_clear(u, ctx); } fmpz_mpoly_clear(t, ctx); return; } if (fmpz_mpoly_is_one(y_den, ctx)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_gcd_assert_successful(t, y_num, x_den, ctx); if (fmpz_mpoly_is_one(t, ctx)) { fmpz_mpoly_mul(res_num, x_num, y_num, ctx); fmpz_mpoly_mul(res_den, x_den, y_den, ctx); } else { fmpz_mpoly_init(u, ctx); _fmpz_mpoly_q_mpoly_divexact(u, y_num, t, ctx); fmpz_mpoly_mul(res_num, u, x_num, ctx); _fmpz_mpoly_q_mpoly_divexact(u, x_den, t, ctx); fmpz_mpoly_mul(res_den, y_den, u, ctx); fmpz_mpoly_clear(u, ctx); } fmpz_mpoly_clear(t, ctx); return; } { fmpz_mpoly_t t, u, x, y; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_init(x, ctx); fmpz_mpoly_init(y, ctx); fmpz_mpoly_gcd_assert_successful(t, x_num, y_den, ctx); if (fmpz_mpoly_is_one(t, ctx)) { fmpz_mpoly_gcd_assert_successful(u, x_den, y_num, ctx); if (fmpz_mpoly_is_one(u, ctx)) { fmpz_mpoly_mul(res_num, x_num, y_num, ctx); fmpz_mpoly_mul(res_den, x_den, y_den, ctx); } else { fmpz_mpoly_div(y, y_num, u, ctx); fmpz_mpoly_mul(res_num, x_num, y, ctx); fmpz_mpoly_div(x, x_den, u, ctx); fmpz_mpoly_mul(res_den, x, y_den, ctx); } } else { fmpz_mpoly_gcd_assert_successful(u, x_den, y_num, ctx); if (fmpz_mpoly_is_one(u, ctx)) { fmpz_mpoly_div(x, x_num, t, ctx); fmpz_mpoly_mul(res_num, x, y_num, ctx); fmpz_mpoly_div(y, y_den, t, ctx); fmpz_mpoly_mul(res_den, x_den, y, ctx); } else { fmpz_mpoly_div(x, x_num, t, ctx); fmpz_mpoly_div(y, y_num, u, ctx); fmpz_mpoly_mul(res_num, x, y, ctx); fmpz_mpoly_div(x, x_den, u, ctx); fmpz_mpoly_div(y, y_den, t, ctx); fmpz_mpoly_mul(res_den, x, y, ctx); } } fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); fmpz_mpoly_clear(x, ctx); fmpz_mpoly_clear(y, ctx); } } void _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(x_num, ctx) || fmpz_is_zero(y_num)) { fmpz_mpoly_zero(res_num, ctx); fmpz_mpoly_one(res_den, ctx); return; } if (fmpz_mpoly_equal_fmpz(x_den, y_den, ctx)) { fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, y_num, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, y_den, ctx); return; } if (fmpz_mpoly_is_one(x_den, ctx)) { fmpz_t t; fmpz_init(t); _fmpz_vec_content2(t, x_num->coeffs, x_num->length, y_den); if (fmpz_is_one(t)) { fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, y_num, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, y_den, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, x_num, t, ctx); fmpz_mpoly_scalar_mul_fmpz(res_num, res_num, y_num, ctx); fmpz_divexact(t, y_den, t); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, t, ctx); } fmpz_clear(t); return; } if (fmpz_is_one(y_den)) { fmpz_t t; fmpz_init(t); _fmpz_vec_content2(t, x_den->coeffs, x_den->length, y_num); if (fmpz_is_one(t)) { fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, y_num, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, y_den, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_den, x_den, t, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, res_den, y_den, ctx); fmpz_divexact(t, y_num, t); fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, t, ctx); } fmpz_clear(t); return; } { fmpz_t t, u; fmpz_init(t); fmpz_init(u); _fmpz_vec_content2(t, x_num->coeffs, x_num->length, y_den); _fmpz_vec_content2(u, x_den->coeffs, x_den->length, y_num); if (fmpz_is_one(t)) { if (fmpz_is_one(u)) { fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, y_num, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, y_den, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_den, x_den, u, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, res_den, y_den, ctx); fmpz_divexact(u, y_num, u); fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, u, ctx); } } else { if (fmpz_is_one(u)) { fmpz_mpoly_scalar_divexact_fmpz(res_num, x_num, t, ctx); fmpz_mpoly_scalar_mul_fmpz(res_num, res_num, y_num, ctx); fmpz_divexact(t, y_den, t); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, t, ctx); } else { fmpz_t v; fmpz_init(v); fmpz_mpoly_scalar_divexact_fmpz(res_num, x_num, t, ctx); fmpz_divexact(v, y_num, u); fmpz_mpoly_scalar_mul_fmpz(res_num, res_num, v, ctx); fmpz_mpoly_scalar_divexact_fmpz(res_den, x_den, u, ctx); fmpz_divexact(v, y_den, t); fmpz_mpoly_scalar_mul_fmpz(res_den, res_den, v, ctx); fmpz_clear(v); } } fmpz_clear(t); fmpz_clear(u); } } void fmpz_mpoly_q_mul(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_mul(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpz_mpoly_q_numref(y), fmpz_mpoly_q_denref(y), ctx); } void fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpq_numref(y), fmpq_denref(y), ctx); } void fmpz_mpoly_q_mul_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) { fmpz_t one; *one = 1; _fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), y, one, ctx); } flint-3.1.3/src/fmpz_mpoly_q/neg.c000066400000000000000000000012221461254215100170500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_neg(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_neg(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(x), ctx); fmpz_mpoly_set(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(x), ctx); } flint-3.1.3/src/fmpz_mpoly_q/print_pretty.c000066400000000000000000000036411461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" #include "gr.h" void fmpz_mpoly_q_print_pretty(const fmpz_mpoly_q_t f, const char ** x, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(f), ctx)) { fmpz_mpoly_print_pretty(fmpz_mpoly_q_numref(f), x, ctx); } else if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(f), ctx)) { flint_printf("("); fmpz_mpoly_print_pretty(fmpz_mpoly_q_numref(f), x, ctx); flint_printf(")/"); fmpz_mpoly_print_pretty(fmpz_mpoly_q_denref(f), x, ctx); } else { flint_printf("("); fmpz_mpoly_print_pretty(fmpz_mpoly_q_numref(f), x, ctx); flint_printf(")/("); fmpz_mpoly_print_pretty(fmpz_mpoly_q_denref(f), x, ctx); flint_printf(")"); } } char * fmpz_mpoly_q_get_str_pretty(const fmpz_mpoly_q_t f, const char ** vars, const fmpz_mpoly_ctx_t ctx) { gr_ctx_t grctx; char * s; gr_ctx_init_fmpz_mpoly_q(grctx, ctx->minfo->nvars, ctx->minfo->ord); if (vars != NULL) GR_MUST_SUCCEED(gr_ctx_set_gen_names(grctx, vars)); GR_MUST_SUCCEED(gr_get_str(&s, f, grctx)); gr_ctx_clear(grctx); return s; } int fmpz_mpoly_q_set_str_pretty(fmpz_mpoly_q_t res, const char * s, const char ** vars, fmpz_mpoly_ctx_t ctx) { gr_ctx_t grctx; int ret; gr_ctx_init_fmpz_mpoly_q(grctx, ctx->minfo->nvars, ctx->minfo->ord); if (vars != NULL) GR_MUST_SUCCEED(gr_ctx_set_gen_names(grctx, vars)); ret = (GR_SUCCESS == gr_set_str(res, s, grctx)) ? 0 : -1; gr_ctx_clear(grctx); return ret; } flint-3.1.3/src/fmpz_mpoly_q/randtest.c000066400000000000000000000022621461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_randtest(fmpz_mpoly_q_t res, flint_rand_t state, slong length, mp_limb_t coeff_bits, slong exp_bound, const fmpz_mpoly_ctx_t ctx) { length = n_randint(state, length + 1); fmpz_mpoly_randtest_bound(fmpz_mpoly_q_numref(res), state, length, coeff_bits, exp_bound, ctx); if (n_randint(state, 2)) { fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } else { if (n_randint(state, 2)) { length = 1; exp_bound = 1; } fmpz_mpoly_randtest_bound(fmpz_mpoly_q_denref(res), state, length, coeff_bits, exp_bound, ctx); if (fmpz_mpoly_is_zero(fmpz_mpoly_q_denref(res), ctx)) fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } fmpz_mpoly_q_canonicalise(res, ctx); } flint-3.1.3/src/fmpz_mpoly_q/set.c000066400000000000000000000024711461254215100171010ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_set(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_ctx_t ctx) { if (res != x) { fmpz_mpoly_set(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(x), ctx); fmpz_mpoly_set(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(x), ctx); } } void fmpz_mpoly_q_set_si(fmpz_mpoly_q_t res, slong x, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_set_si(fmpz_mpoly_q_numref(res), x, ctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } void fmpz_mpoly_q_set_fmpz(fmpz_mpoly_q_t res, const fmpz_t x, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_set_fmpz(fmpz_mpoly_q_numref(res), x, ctx); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), ctx); } void fmpz_mpoly_q_set_fmpq(fmpz_mpoly_q_t res, const fmpq_t x, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_set_fmpz(fmpz_mpoly_q_numref(res), fmpq_numref(x), ctx); fmpz_mpoly_set_fmpz(fmpz_mpoly_q_denref(res), fmpq_denref(x), ctx); } flint-3.1.3/src/fmpz_mpoly_q/sub.c000066400000000000000000000352771461254215100171110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" static void _fmpz_mpoly_q_sub_fmpz_mpoly_den(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx) { fmpz_t g; fmpz_init(g); if (fmpz_mpoly_is_fmpz(y_num, ctx)) { if (res_num == x_num || res_num == y_num) { fmpz_t t, u; fmpz_init_set(t, y_num->coeffs); fmpz_init_set(u, y_den); _fmpz_mpoly_q_sub_fmpq(res_num, res_den, x_num, x_den, t, u, ctx); fmpz_clear(t); fmpz_clear(u); } else { _fmpz_mpoly_q_sub_fmpq(res_num, res_den, x_num, x_den, y_num->coeffs, y_den, ctx); } return; } if (fmpz_mpoly_is_fmpz(x_den, ctx)) { fmpz_gcd(g, x_den->coeffs, y_den); if (fmpz_is_one(g)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); /* todo: avoid one alloc? not helpful right now because fmpz_mpoly_sub does not work inplace */ fmpz_mpoly_scalar_mul_fmpz(t, y_num, x_den->coeffs, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, y_den, ctx); fmpz_mpoly_sub(res_num, u, t, ctx); fmpz_mul(g, x_den->coeffs, y_den); fmpz_mpoly_set_fmpz(res_den, g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_t a, b; fmpz_mpoly_t t, u; fmpz_init(a); fmpz_init(b); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_divexact(a, y_den, g); fmpz_divexact(b, x_den->coeffs, g); fmpz_mpoly_scalar_mul_fmpz(t, y_num, b, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, a, ctx); fmpz_mpoly_sub(res_num, u, t, ctx); if (fmpz_mpoly_is_zero(res_num, ctx)) fmpz_one(a); else _fmpz_vec_content2(a, res_num->coeffs, res_num->length, g); if (fmpz_is_one(a)) { fmpz_mul(g, b, y_den); fmpz_mpoly_set_fmpz(res_den, g, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, a, ctx); fmpz_divexact(g, y_den, a); fmpz_mul(g, g, b); fmpz_mpoly_set_fmpz(res_den, g, ctx); } fmpz_clear(a); fmpz_clear(b); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } } else { _fmpz_vec_content2(g, x_den->coeffs, x_den->length, y_den); if (fmpz_is_one(g)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); /* todo: avoid one alloc? not helpful right now because fmpz_mpoly_sub does not work inplace */ fmpz_mpoly_mul(t, y_num, x_den, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, y_den, ctx); fmpz_mpoly_sub(res_num, u, t, ctx); fmpz_set(g, y_den); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, g, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_t a; fmpz_mpoly_t b, t, u; fmpz_init(a); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_divexact(a, y_den, g); fmpz_mpoly_scalar_divexact_fmpz(b, x_den, g, ctx); fmpz_mpoly_mul(t, y_num, b, ctx); fmpz_mpoly_scalar_mul_fmpz(u, x_num, a, ctx); fmpz_mpoly_sub(res_num, u, t, ctx); if (fmpz_mpoly_is_zero(res_num, ctx)) fmpz_one(a); else _fmpz_vec_content2(a, res_num->coeffs, res_num->length, g); if (fmpz_is_one(a)) { fmpz_set(g, y_den); fmpz_mpoly_scalar_mul_fmpz(res_den, b, g, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, a, ctx); fmpz_divexact(g, y_den, a); fmpz_mpoly_scalar_mul_fmpz(res_den, b, g, ctx); } fmpz_clear(a); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } } fmpz_clear(g); } void _fmpz_mpoly_q_sub(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_mpoly_t y_num, const fmpz_mpoly_t y_den, const fmpz_mpoly_ctx_t ctx) { if (fmpz_mpoly_is_zero(x_num, ctx)) { fmpz_mpoly_neg(res_num, y_num, ctx); fmpz_mpoly_set(res_den, y_den, ctx); return; } if (fmpz_mpoly_is_zero(y_num, ctx)) { fmpz_mpoly_set(res_num, x_num, ctx); fmpz_mpoly_set(res_den, x_den, ctx); return; } if (fmpz_mpoly_equal(x_den, y_den, ctx)) { fmpz_mpoly_sub(res_num, x_num, y_num, ctx); if (fmpz_mpoly_is_one(x_den, ctx) || fmpz_mpoly_is_zero(res_num, ctx)) { fmpz_mpoly_one(res_den, ctx); } else if (fmpz_mpoly_is_fmpz(x_den, ctx)) { fmpz_t t; fmpz_init(t); _fmpz_vec_content2(t, res_num->coeffs, res_num->length, x_den->coeffs); if (fmpz_is_one(t)) { fmpz_mpoly_set(res_den, x_den, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, t, ctx); fmpz_mpoly_scalar_divexact_fmpz(res_den, x_den, t, ctx); } fmpz_clear(t); } else { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_gcd_assert_successful(t, res_num, x_den, ctx); if (fmpz_mpoly_is_one(t, ctx)) { fmpz_mpoly_set(res_den, x_den, ctx); } else { _fmpz_mpoly_q_mpoly_divexact(res_num, res_num, t, ctx); _fmpz_mpoly_q_mpoly_divexact(res_den, x_den, t, ctx); } fmpz_mpoly_clear(t, ctx); } return; } if (fmpz_mpoly_is_one(x_den, ctx)) { if (res_num == y_num) { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_mul(t, x_num, y_den, ctx); fmpz_mpoly_sub(res_num, t, y_num, ctx); fmpz_mpoly_clear(t, ctx); } else { fmpz_mpoly_mul(res_num, x_num, y_den, ctx); fmpz_mpoly_sub(res_num, res_num, y_num, ctx); } fmpz_mpoly_set(res_den, y_den, ctx); return; } if (fmpz_mpoly_is_one(y_den, ctx)) { if (res_num == x_num) { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_mul(t, y_num, x_den, ctx); fmpz_mpoly_sub(res_num, x_num, t, ctx); fmpz_mpoly_clear(t, ctx); } else { fmpz_mpoly_mul(res_num, y_num, x_den, ctx); fmpz_mpoly_sub(res_num, x_num, res_num, ctx); } fmpz_mpoly_set(res_den, x_den, ctx); return; } if (fmpz_mpoly_is_fmpz(y_den, ctx)) { _fmpz_mpoly_q_sub_fmpz_mpoly_den(res_num, res_den, x_num, x_den, y_num, y_den->coeffs, ctx); return; } if (fmpz_mpoly_is_fmpz(x_den, ctx)) { _fmpz_mpoly_q_sub_fmpz_mpoly_den(res_num, res_den, y_num, y_den, x_num, x_den->coeffs, ctx); fmpz_mpoly_neg(res_num, res_num, ctx); return; } { fmpz_mpoly_t g; fmpz_mpoly_init(g, ctx); fmpz_mpoly_gcd_assert_successful(g, x_den, y_den, ctx); if (fmpz_mpoly_is_one(g, ctx)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); /* todo: avoid one alloc? not helpful right now because fmpz_mpoly_sub does not work inplace */ fmpz_mpoly_mul(t, x_num, y_den, ctx); fmpz_mpoly_mul(u, y_num, x_den, ctx); fmpz_mpoly_sub(res_num, t, u, ctx); fmpz_mpoly_mul(res_den, x_den, y_den, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_mpoly_t a, b, t, u; fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); _fmpz_mpoly_q_mpoly_divexact(a, x_den, g, ctx); _fmpz_mpoly_q_mpoly_divexact(b, y_den, g, ctx); fmpz_mpoly_mul(t, x_num, b, ctx); fmpz_mpoly_mul(u, y_num, a, ctx); fmpz_mpoly_sub(res_num, t, u, ctx); fmpz_mpoly_gcd_assert_successful(t, res_num, g, ctx); if (fmpz_mpoly_is_one(t, ctx)) { fmpz_mpoly_mul(res_den, x_den, b, ctx); } else { _fmpz_mpoly_q_mpoly_divexact(res_num, res_num, t, ctx); _fmpz_mpoly_q_mpoly_divexact(g, x_den, t, ctx); fmpz_mpoly_mul(res_den, g, b, ctx); } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } fmpz_mpoly_clear(g, ctx); } } void _fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_t res_num, fmpz_mpoly_t res_den, const fmpz_mpoly_t x_num, const fmpz_mpoly_t x_den, const fmpz_t y_num, const fmpz_t y_den, const fmpz_mpoly_ctx_t ctx) { if (fmpz_is_zero(y_num)) { fmpz_mpoly_set(res_num, x_num, ctx); fmpz_mpoly_set(res_den, x_den, ctx); return; } if (fmpz_mpoly_is_zero(x_num, ctx)) { fmpz_mpoly_set_fmpz(res_num, y_num, ctx); fmpz_neg(res_num->coeffs, res_num->coeffs); fmpz_mpoly_set_fmpz(res_den, y_den, ctx); return; } /* todo: special-case integer x_den */ if (fmpz_mpoly_equal_fmpz(x_den, y_den, ctx)) { fmpz_mpoly_sub_fmpz(res_num, x_num, y_num, ctx); if (fmpz_is_one(y_den)) { fmpz_mpoly_one(res_den, ctx); } else { fmpz_t t; fmpz_init(t); _fmpz_vec_content2(t, res_num->coeffs, res_num->length, y_den); if (fmpz_is_one(t)) { fmpz_mpoly_set(res_den, x_den, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, t, ctx); fmpz_divexact(t, y_den, t); fmpz_mpoly_set_fmpz(res_den, t, ctx); } fmpz_clear(t); } return; } if (fmpz_mpoly_is_one(x_den, ctx)) { fmpz_mpoly_scalar_mul_fmpz(res_num, x_num, y_den, ctx); fmpz_mpoly_sub_fmpz(res_num, res_num, y_num, ctx); fmpz_mpoly_set_fmpz(res_den, y_den, ctx); return; } if (fmpz_is_one(y_den)) { if (res_num == x_num) { fmpz_mpoly_t t; fmpz_mpoly_init(t, ctx); fmpz_mpoly_scalar_mul_fmpz(t, x_den, y_num, ctx); fmpz_mpoly_sub(res_num, x_num, t, ctx); fmpz_mpoly_clear(t, ctx); } else { fmpz_mpoly_scalar_mul_fmpz(res_num, x_den, y_num, ctx); fmpz_mpoly_sub(res_num, x_num, res_num, ctx); } fmpz_mpoly_set(res_den, x_den, ctx); return; } { fmpz_t g; fmpz_init(g); _fmpz_vec_content2(g, x_den->coeffs, x_den->length, y_den); if (fmpz_is_one(g)) { fmpz_mpoly_t t, u; fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_scalar_mul_fmpz(t, x_num, y_den, ctx); /* todo: avoid one alloc? */ fmpz_mpoly_scalar_mul_fmpz(u, x_den, y_num, ctx); fmpz_mpoly_sub(res_num, t, u, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, y_den, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } else { fmpz_mpoly_t t, u; fmpz_t b, c; fmpz_init(b); fmpz_init(c); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_scalar_divexact_fmpz(u, x_den, g, ctx); fmpz_divexact(b, y_den, g); fmpz_mpoly_scalar_mul_fmpz(t, x_num, b, ctx); fmpz_mpoly_scalar_mul_fmpz(u, u, y_num, ctx); fmpz_mpoly_sub(res_num, t, u, ctx); _fmpz_vec_content2(c, res_num->coeffs, res_num->length, g); if (fmpz_is_one(c)) { fmpz_mpoly_scalar_mul_fmpz(res_den, x_den, b, ctx); } else { fmpz_mpoly_scalar_divexact_fmpz(res_num, res_num, c, ctx); fmpz_mpoly_scalar_divexact_fmpz(res_den, x_den, c, ctx); fmpz_mpoly_scalar_mul_fmpz(res_den, res_den, b, ctx); } fmpz_clear(b); fmpz_clear(c); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); } fmpz_clear(g); } } void fmpz_mpoly_q_sub(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_sub(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpz_mpoly_q_numref(y), fmpz_mpoly_q_denref(y), ctx); } void fmpz_mpoly_q_sub_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpz_t y, const fmpz_mpoly_ctx_t ctx) { fmpz_t one; *one = 1; _fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), y, one, ctx); } void fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const fmpq_t y, const fmpz_mpoly_ctx_t ctx) { _fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(res), fmpz_mpoly_q_numref(x), fmpz_mpoly_q_denref(x), fmpq_numref(y), fmpq_denref(y), ctx); } flint-3.1.3/src/fmpz_mpoly_q/swap.c000066400000000000000000000012111461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_q.h" void fmpz_mpoly_q_swap(fmpz_mpoly_q_t x, fmpz_mpoly_q_t y, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_swap(fmpz_mpoly_q_numref(x), fmpz_mpoly_q_numref(y), ctx); fmpz_mpoly_swap(fmpz_mpoly_q_denref(x), fmpz_mpoly_q_denref(y), ctx); } flint-3.1.3/src/fmpz_mpoly_q/test/000077500000000000000000000000001461254215100171155ustar00rootroot00000000000000flint-3.1.3/src/fmpz_mpoly_q/test/main.c000066400000000000000000000031671461254215100202140ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_fmpq.c" #include "t-add_fmpz.c" #include "t-div.c" #include "t-div_fmpq.c" #include "t-div_fmpz.c" #include "t-get_set_str.c" #include "t-inv.c" #include "t-mul.c" #include "t-mul_fmpq.c" #include "t-mul_fmpz.c" #include "t-randtest.c" #include "t-sub.c" #include "t-sub_fmpq.c" #include "t-sub_fmpz.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_mpoly_q_add), TEST_FUNCTION(fmpz_mpoly_q_add_fmpq), TEST_FUNCTION(fmpz_mpoly_q_add_fmpz), TEST_FUNCTION(fmpz_mpoly_q_div), TEST_FUNCTION(fmpz_mpoly_q_div_fmpq), TEST_FUNCTION(fmpz_mpoly_q_div_fmpz), TEST_FUNCTION(fmpz_mpoly_q_get_set_str), TEST_FUNCTION(fmpz_mpoly_q_inv), TEST_FUNCTION(fmpz_mpoly_q_mul), TEST_FUNCTION(fmpz_mpoly_q_mul_fmpq), TEST_FUNCTION(fmpz_mpoly_q_mul_fmpz), TEST_FUNCTION(fmpz_mpoly_q_randtest), TEST_FUNCTION(fmpz_mpoly_q_sub), TEST_FUNCTION(fmpz_mpoly_q_sub_fmpq), TEST_FUNCTION(fmpz_mpoly_q_sub_fmpz) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_mpoly_q/test/t-add.c000066400000000000000000000060351461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_add, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C, D; fmpz_mpoly_t t, u; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_mpoly_q_init(D, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_q_randtest(A, state, 5, 2 + n_randint(state, 100), 5, ctx); fmpz_mpoly_q_randtest(B, state, 5, 2 + n_randint(state, 100), 5, ctx); fmpz_mpoly_q_add(C, A, B, ctx); fmpz_mpoly_mul(t, fmpz_mpoly_q_numref(A), fmpz_mpoly_q_denref(B), ctx); fmpz_mpoly_mul(u, fmpz_mpoly_q_numref(B), fmpz_mpoly_q_denref(A), ctx); fmpz_mpoly_add(fmpz_mpoly_q_numref(D), t, u, ctx); fmpz_mpoly_mul(fmpz_mpoly_q_denref(D), fmpz_mpoly_q_denref(A), fmpz_mpoly_q_denref(B), ctx); fmpz_mpoly_q_canonicalise(D, ctx); if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { fmpz_mpoly_q_set(C, A, ctx); fmpz_mpoly_q_add(C, C, B, ctx); } else { fmpz_mpoly_q_set(C, B, ctx); fmpz_mpoly_q_add(C, A, C, ctx); } if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_mpoly_q_clear(D, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-add_fmpq.c000066400000000000000000000034371461254215100213040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_add_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpq_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpq_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpq_randtest(c, state, 10); fmpz_mpoly_q_add_fmpq(B, A, c, ctx); fmpz_mpoly_q_set_fmpq(C, c, ctx); fmpz_mpoly_q_add(C, A, C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpq_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpq_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-add_fmpz.c000066400000000000000000000034151461254215100213110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_add_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpz_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_randtest(c, state, 10); fmpz_mpoly_q_add_fmpz(B, A, c, ctx); fmpz_mpoly_q_set_fmpz(C, c, ctx); fmpz_mpoly_q_add(C, A, C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-div.c000066400000000000000000000055071461254215100203130ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_div, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C, D; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_mpoly_q_init(D, ctx); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); do { fmpz_mpoly_q_randtest(B, state, 10, 2 + n_randint(state, 100), 5, ctx); } while (fmpz_mpoly_q_is_zero(B, ctx)); fmpz_mpoly_q_div(C, A, B, ctx); fmpz_mpoly_mul(fmpz_mpoly_q_numref(D), fmpz_mpoly_q_numref(A), fmpz_mpoly_q_denref(B), ctx); fmpz_mpoly_mul(fmpz_mpoly_q_denref(D), fmpz_mpoly_q_denref(A), fmpz_mpoly_q_numref(B), ctx); fmpz_mpoly_q_canonicalise(D, ctx); if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { fmpz_mpoly_q_set(C, A, ctx); fmpz_mpoly_q_div(C, C, B, ctx); } else { fmpz_mpoly_q_set(C, B, ctx); fmpz_mpoly_q_div(C, A, C, ctx); } if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_mpoly_q_clear(D, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-div_fmpq.c000066400000000000000000000037011461254215100213300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_div_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpq_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpq_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpq_randtest_not_zero(c, state, 10); fmpz_mpoly_q_div_fmpq(B, A, c, ctx); fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_q_numref(C), fmpz_mpoly_q_numref(A), fmpq_denref(c), ctx); fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_q_denref(C), fmpz_mpoly_q_denref(A), fmpq_numref(c), ctx); fmpz_mpoly_q_canonicalise(C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpq_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpq_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-div_fmpz.c000066400000000000000000000036301461254215100213420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_div_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpz_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_randtest_not_zero(c, state, 10); fmpz_mpoly_q_div_fmpz(B, A, c, ctx); fmpz_mpoly_set(fmpz_mpoly_q_numref(C), fmpz_mpoly_q_numref(A), ctx); fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_q_denref(C), fmpz_mpoly_q_denref(A), c, ctx); fmpz_mpoly_q_canonicalise(C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-get_set_str.c000066400000000000000000000033651461254215100220530ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_get_set_str, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B; char * s; char * vars[] = { "x", "y", "z", "t", "u" }; int use_vars, ok; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_mpoly_q_randtest(B, state, 10, 2 + n_randint(state, 100), 5, ctx); use_vars = n_randint(state, 2); s = fmpz_mpoly_q_get_str_pretty(A, use_vars ? (const char **) vars : NULL, ctx); ok = !fmpz_mpoly_q_set_str_pretty(B, s, use_vars ? (const char **) vars : NULL, ctx); ok = ok && fmpz_mpoly_q_equal(A, B, ctx); if (!ok) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_abort(); } flint_free(s); fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-inv.c000066400000000000000000000034711461254215100203230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_inv, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); do { fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); } while (fmpz_mpoly_q_is_zero(A, ctx)); fmpz_mpoly_q_inv(B, A, ctx); if (n_randint(state, 2)) { fmpz_mpoly_q_inv(C, B, ctx); } else { fmpz_mpoly_q_set(C, B, ctx); fmpz_mpoly_q_inv(C, C, ctx); } if (!fmpz_mpoly_q_is_canonical(B, ctx) || !fmpz_mpoly_q_equal(A, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-mul.c000066400000000000000000000054061461254215100203240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_mul, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C, D; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_mpoly_q_init(D, ctx); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_mpoly_q_randtest(B, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_mpoly_q_mul(C, A, B, ctx); fmpz_mpoly_mul(fmpz_mpoly_q_numref(D), fmpz_mpoly_q_numref(A), fmpz_mpoly_q_numref(B), ctx); fmpz_mpoly_mul(fmpz_mpoly_q_denref(D), fmpz_mpoly_q_denref(A), fmpz_mpoly_q_denref(B), ctx); fmpz_mpoly_q_canonicalise(D, ctx); if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { fmpz_mpoly_q_set(C, A, ctx); fmpz_mpoly_q_mul(C, C, B, ctx); } else { fmpz_mpoly_q_set(C, B, ctx); fmpz_mpoly_q_mul(C, A, C, ctx); } if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_mpoly_q_clear(D, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-mul_fmpq.c000066400000000000000000000036701461254215100213500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_mul_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpq_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpq_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpq_randtest(c, state, 10); fmpz_mpoly_q_mul_fmpq(B, A, c, ctx); fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_q_numref(C), fmpz_mpoly_q_numref(A), fmpq_numref(c), ctx); fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_q_denref(C), fmpz_mpoly_q_denref(A), fmpq_denref(c), ctx); fmpz_mpoly_q_canonicalise(C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpq_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpq_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-mul_fmpz.c000066400000000000000000000036171461254215100213620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_mul_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpz_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_randtest(c, state, 10); fmpz_mpoly_q_mul_fmpz(B, A, c, ctx); fmpz_mpoly_scalar_mul_fmpz(fmpz_mpoly_q_numref(C), fmpz_mpoly_q_numref(A), c, ctx); fmpz_mpoly_set(fmpz_mpoly_q_denref(C), fmpz_mpoly_q_denref(A), ctx); fmpz_mpoly_q_canonicalise(C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-randtest.c000066400000000000000000000023441461254215100213510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_randtest, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_randtest(A, state, 10, 10, 5, ctx); /* fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n"); */ if (!fmpz_mpoly_q_is_canonical(A, ctx)) { flint_printf("FAIL: not canonical\n"); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-sub.c000066400000000000000000000060371461254215100203210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_sub, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C, D; fmpz_mpoly_t t, u; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_mpoly_q_init(D, ctx); fmpz_mpoly_init(t, ctx); fmpz_mpoly_init(u, ctx); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_mpoly_q_randtest(B, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_mpoly_q_sub(C, A, B, ctx); fmpz_mpoly_mul(t, fmpz_mpoly_q_numref(A), fmpz_mpoly_q_denref(B), ctx); fmpz_mpoly_mul(u, fmpz_mpoly_q_numref(B), fmpz_mpoly_q_denref(A), ctx); fmpz_mpoly_sub(fmpz_mpoly_q_numref(D), t, u, ctx); fmpz_mpoly_mul(fmpz_mpoly_q_denref(D), fmpz_mpoly_q_denref(A), fmpz_mpoly_q_denref(B), ctx); fmpz_mpoly_q_canonicalise(D, ctx); if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { fmpz_mpoly_q_set(C, A, ctx); fmpz_mpoly_q_sub(C, C, B, ctx); } else { fmpz_mpoly_q_set(C, B, ctx); fmpz_mpoly_q_sub(C, A, C, ctx); } if (!fmpz_mpoly_q_equal(C, D, ctx)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("D = "); fmpz_mpoly_q_print_pretty(D, NULL, ctx); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_mpoly_q_clear(D, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(u, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-sub_fmpq.c000066400000000000000000000034151461254215100213410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_sub_fmpq, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpq_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpq_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpq_randtest(c, state, 10); fmpz_mpoly_q_sub_fmpq(B, A, c, ctx); fmpz_mpoly_q_set_fmpq(C, c, ctx); fmpz_mpoly_q_sub(C, A, C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpq_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpq_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/test/t-sub_fmpz.c000066400000000000000000000034151461254215100213520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly_q.h" TEST_FUNCTION_START(fmpz_mpoly_q_sub_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_q_t A, B, C; fmpz_t c; fmpz_mpoly_ctx_init(ctx, 1 + n_randint(state, 4), ORD_LEX); fmpz_mpoly_q_init(A, ctx); fmpz_mpoly_q_init(B, ctx); fmpz_mpoly_q_init(C, ctx); fmpz_init(c); fmpz_mpoly_q_randtest(A, state, 10, 2 + n_randint(state, 100), 5, ctx); fmpz_randtest(c, state, 10); fmpz_mpoly_q_sub_fmpz(B, A, c, ctx); fmpz_mpoly_q_set_fmpz(C, c, ctx); fmpz_mpoly_q_sub(C, A, C, ctx); if (!fmpz_mpoly_q_equal(B, C, ctx)) { flint_printf("FAIL\n"); flint_printf("A = "); fmpz_mpoly_q_print_pretty(A, NULL, ctx); flint_printf("\n\n"); flint_printf("B = "); fmpz_mpoly_q_print_pretty(B, NULL, ctx); flint_printf("\n\n"); flint_printf("C = "); fmpz_mpoly_q_print_pretty(C, NULL, ctx); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_q_clear(A, ctx); fmpz_mpoly_q_clear(B, ctx); fmpz_mpoly_q_clear(C, ctx); fmpz_clear(c); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_mpoly_q/used_vars.c000066400000000000000000000036661461254215100203100ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly_q.h" /* ANDs used without zeroing */ void _fmpz_mpoly_used_vars(int * used, const fmpz_mpoly_t f, const fmpz_mpoly_ctx_t ctx) { slong i, n; fmpz * max; TMP_INIT; n = ctx->minfo->nvars; if (fmpz_mpoly_is_fmpz(f, ctx)) return; /* The polynomial is not constant and has only one variable. */ if (n == 1) { used[0] = 1; return; } TMP_START; max = TMP_ALLOC(sizeof(fmpz) * n); for (i = 0; i < n; i++) fmpz_init(max + i); mpoly_degrees_ffmpz(max, f->exps, f->length, f->bits, ctx->minfo); for (i = 0; i < n; i++) used[i] |= !fmpz_is_zero(max + i); for (i = 0; i < n; i++) fmpz_clear(max + i); TMP_END; } void fmpz_mpoly_q_used_vars(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx) { slong i, n; n = ctx->minfo->nvars; for (i = 0; i < n; i++) used[i] = 0; _fmpz_mpoly_used_vars(used, fmpz_mpoly_q_numref(f), ctx); _fmpz_mpoly_used_vars(used, fmpz_mpoly_q_denref(f), ctx); } void fmpz_mpoly_q_used_vars_num(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx) { slong i, n; n = ctx->minfo->nvars; for (i = 0; i < n; i++) used[i] = 0; _fmpz_mpoly_used_vars(used, fmpz_mpoly_q_numref(f), ctx); } void fmpz_mpoly_q_used_vars_den(int * used, const fmpz_mpoly_q_t f, const fmpz_mpoly_ctx_t ctx) { slong i, n; n = ctx->minfo->nvars; for (i = 0; i < n; i++) used[i] = 0; _fmpz_mpoly_used_vars(used, fmpz_mpoly_q_denref(f), ctx); } flint-3.1.3/src/fmpz_poly.h000066400000000000000000001417571461254215100156310ustar00rootroot00000000000000/* Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 William Hart Copyright (C) 2009, 2011 Andy Novocin Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_POLY_H #define FMPZ_POLY_H #ifdef FMPZ_POLY_INLINES_C #define FMPZ_POLY_INLINE #else #define FMPZ_POLY_INLINE static inline #endif #include "fmpz_types.h" #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif #define FMPZ_POLY_INV_NEWTON_CUTOFF 32 #define FMPZ_POLY_SQRT_DIVCONQUER_CUTOFF 16 #define FMPZ_POLY_SQRTREM_DIVCONQUER_CUTOFF 16 /* Type definitions *********************************************************/ typedef struct { fmpz ** powers; slong len; } fmpz_poly_powers_precomp_struct; typedef fmpz_poly_powers_precomp_struct fmpz_poly_powers_precomp_t[1]; typedef struct { mp_limb_t ** jj; /* used by fft_convolution_precache */ slong n; slong len2; slong loglen; slong bits2; slong limbs; fmpz_poly_t poly2; } fmpz_poly_mul_precache_struct; typedef fmpz_poly_mul_precache_struct fmpz_poly_mul_precache_t[1]; /* Memory management ********************************************************/ void fmpz_poly_init(fmpz_poly_t poly); void fmpz_poly_init2(fmpz_poly_t poly, slong alloc); void fmpz_poly_realloc(fmpz_poly_t poly, slong alloc); void fmpz_poly_fit_length(fmpz_poly_t poly, slong len); void fmpz_poly_clear(fmpz_poly_t poly); void _fmpz_poly_normalise(fmpz_poly_t poly); void _fmpz_poly_set_length(fmpz_poly_t poly, slong newlen); FMPZ_POLY_INLINE void fmpz_poly_attach_truncate(fmpz_poly_t trunc, const fmpz_poly_t poly, slong n) { trunc->coeffs = poly->coeffs; trunc->alloc = poly->alloc; trunc->length = FLINT_MIN(poly->length, n); } FMPZ_POLY_INLINE void fmpz_poly_attach_shift(fmpz_poly_t trunc, const fmpz_poly_t poly, slong n) { trunc->coeffs = poly->coeffs + n; trunc->alloc = poly->alloc - n; trunc->length = FLINT_MAX(poly->length - n, 0); } /* Polynomial parameters ***************************************************/ FMPZ_POLY_INLINE slong fmpz_poly_length(const fmpz_poly_t poly) { return poly->length; } FMPZ_POLY_INLINE slong fmpz_poly_degree(const fmpz_poly_t poly) { return poly->length - 1; } /* Assignment and basic manipulation ***************************************/ void fmpz_poly_set(fmpz_poly_t poly1, const fmpz_poly_t poly2); void fmpz_poly_set_ui(fmpz_poly_t poly, ulong c); void fmpz_poly_set_si(fmpz_poly_t poly, slong c); void fmpz_poly_set_fmpz(fmpz_poly_t poly, const fmpz_t c); int _fmpz_poly_set_str(fmpz * poly, const char * str); int fmpz_poly_set_str(fmpz_poly_t poly, const char * str); char * _fmpz_poly_get_str(const fmpz * poly, slong len); char * fmpz_poly_get_str(const fmpz_poly_t poly); char * _fmpz_poly_get_str_pretty(const fmpz * poly, slong len, const char * x); char * fmpz_poly_get_str_pretty(const fmpz_poly_t poly, const char * x); FMPZ_POLY_INLINE void fmpz_poly_zero(fmpz_poly_t poly) { _fmpz_poly_set_length(poly, 0); } FMPZ_POLY_INLINE void fmpz_poly_one(fmpz_poly_t poly) { fmpz_poly_set_ui(poly, UWORD(1)); } void fmpz_poly_zero_coeffs(fmpz_poly_t poly, slong i, slong j); void fmpz_poly_swap(fmpz_poly_t poly1, fmpz_poly_t poly2); void _fmpz_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_poly_reverse(fmpz_poly_t res, const fmpz_poly_t poly, slong n); ulong _fmpz_poly_deflation(const fmpz* a, slong len); FMPZ_POLY_INLINE ulong fmpz_poly_deflation(const fmpz_poly_t input) { return _fmpz_poly_deflation(input->coeffs, input->length); } void fmpz_poly_deflate(fmpz_poly_t result, const fmpz_poly_t input, ulong deflation); void fmpz_poly_inflate(fmpz_poly_t result, const fmpz_poly_t input, ulong inflation); void fmpz_poly_truncate(fmpz_poly_t poly, slong newlen); void fmpz_poly_set_trunc(fmpz_poly_t res, const fmpz_poly_t poly, slong n); /* Randomisation ***********************************************************/ void fmpz_poly_randtest(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits); void fmpz_poly_randtest_unsigned(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits); void fmpz_poly_randtest_not_zero(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits); void fmpz_poly_randtest_no_real_root(fmpz_poly_t p, flint_rand_t state, slong len, flint_bitcnt_t bits); void fmpz_poly_randtest_irreducible1(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits); void fmpz_poly_randtest_irreducible2(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits); void fmpz_poly_randtest_irreducible(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits); /* Getting and setting coefficients ****************************************/ slong fmpz_poly_get_coeff_si(const fmpz_poly_t poly, slong n); void fmpz_poly_set_coeff_si(fmpz_poly_t poly, slong n, slong x); ulong fmpz_poly_get_coeff_ui(const fmpz_poly_t poly, slong n); void fmpz_poly_set_coeff_ui(fmpz_poly_t poly, slong n, ulong x); void fmpz_poly_set_coeff_fmpz(fmpz_poly_t poly, slong n, const fmpz_t x); void fmpz_poly_get_coeff_fmpz(fmpz_t x, const fmpz_poly_t poly, slong n); #define fmpz_poly_get_coeff_ptr(poly, n) \ ((n) < (poly)->length ? (poly)->coeffs + (n) : NULL) #define fmpz_poly_lead(poly) \ ((poly)->length ? (poly)->coeffs + (poly)->length - 1 : NULL) /* Comparison **************************************************************/ int fmpz_poly_equal(const fmpz_poly_t poly1, const fmpz_poly_t poly2); int fmpz_poly_equal_trunc(const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); #define fmpz_poly_is_zero(poly) \ ((poly)->length == 0) int _fmpz_poly_is_one(const fmpz *poly, slong len); FMPZ_POLY_INLINE int fmpz_poly_is_one(const fmpz_poly_t op) { return (op->length) == 1 && (*(op->coeffs) == WORD(1)); } FMPZ_POLY_INLINE int fmpz_poly_is_unit(const fmpz_poly_t op) { return (op->length == 1) && (*(op->coeffs) == WORD(1) || *(op->coeffs) == WORD(-1)); } FMPZ_POLY_INLINE int fmpz_poly_is_gen(const fmpz_poly_t op) { return (op->length) == 2 && (*(op->coeffs + 1) == WORD(1)) && (*(op->coeffs + 0) == WORD(0)); } int fmpz_poly_equal_fmpz(const fmpz_poly_t poly, const fmpz_t c); /* Addition and subtraction ************************************************/ void _fmpz_poly_add(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_add(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void fmpz_poly_add_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_sub(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_sub(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void fmpz_poly_sub_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void fmpz_poly_neg(fmpz_poly_t res, const fmpz_poly_t poly); void fmpz_poly_add_si(fmpz_poly_t res, const fmpz_poly_t poly, slong c); void fmpz_poly_sub_si(fmpz_poly_t res, const fmpz_poly_t poly, slong c); void fmpz_poly_si_sub(fmpz_poly_t res, slong c, const fmpz_poly_t poly); void fmpz_poly_add_fmpz(fmpz_poly_t res, const fmpz_poly_t poly, fmpz_t c); void fmpz_poly_sub_fmpz(fmpz_poly_t res, const fmpz_poly_t poly, fmpz_t c); void fmpz_poly_fmpz_sub(fmpz_poly_t res, fmpz_t c, const fmpz_poly_t poly); /* Scalar absolute value multiplication and division ***********************/ void fmpz_poly_scalar_abs(fmpz_poly_t res, const fmpz_poly_t poly); void fmpz_poly_scalar_mul_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); void fmpz_poly_scalar_mul_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); void fmpz_poly_scalar_mul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); void fmpz_poly_scalar_addmul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); void fmpz_poly_scalar_addmul_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); void fmpz_poly_scalar_addmul_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); void fmpz_poly_scalar_submul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); void fmpz_poly_scalar_fdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); void fmpz_poly_scalar_fdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); void fmpz_poly_scalar_fdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); void fmpz_poly_scalar_tdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); void fmpz_poly_scalar_tdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); void fmpz_poly_scalar_tdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); void fmpz_poly_scalar_divexact_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); void fmpz_poly_scalar_divexact_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); void fmpz_poly_scalar_divexact_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); void fmpz_poly_scalar_fdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp); void fmpz_poly_scalar_tdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp); void fmpz_poly_scalar_mul_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp); void fmpz_poly_scalar_mod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); void fmpz_poly_scalar_smod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); slong _fmpz_poly_remove_content_2exp(fmpz * pol, slong len); void _fmpz_poly_scale_2exp(fmpz * pol, slong len, slong k); /* Bit packing *************************************************************/ void _fmpz_poly_bit_pack(mp_ptr arr, const fmpz * poly, slong len, flint_bitcnt_t bit_size, int negate); int _fmpz_poly_bit_unpack(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size, int negate); void _fmpz_poly_bit_unpack_unsigned(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size); void fmpz_poly_bit_pack(fmpz_t f, const fmpz_poly_t poly, flint_bitcnt_t bit_size); void fmpz_poly_bit_unpack(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size); void fmpz_poly_bit_unpack_unsigned(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size); /* Multiplication **********************************************************/ void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_mul_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); void fmpz_poly_mullow_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start); void fmpz_poly_mulhigh_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong start); void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_mulmid_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void fmpz_poly_mul_karatsuba(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_mul_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void _fmpz_poly_mullow_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong n); void _fmpz_poly_mullow_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); void fmpz_poly_mullow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_mulhigh_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong len); void fmpz_poly_mulhigh_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong length); void _fmpz_poly_mul_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_mul_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_mullow_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); void fmpz_poly_mullow_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_mul_SS(fmpz * output, const fmpz * input1, slong length1, const fmpz * input2, slong length2); void fmpz_poly_mul_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_mullow_SS(fmpz * output, const fmpz * input1, slong length1, const fmpz * input2, slong length2, slong n); void fmpz_poly_mullow_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_mul(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_mul(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); void fmpz_poly_mullow(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void fmpz_poly_mulhigh_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_mulhigh(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start); /* FFT precached multiplication **********************************************/ void fmpz_poly_mul_SS_precache_init(fmpz_poly_mul_precache_t pre, slong len1, slong bits1, const fmpz_poly_t poly2); void fmpz_poly_mul_precache_clear(fmpz_poly_mul_precache_t pre); void _fmpz_poly_mullow_SS_precache(fmpz * output, const fmpz * input1, slong len1, fmpz_poly_mul_precache_t pre, slong trunc); void fmpz_poly_mullow_SS_precache(fmpz_poly_t res, const fmpz_poly_t poly1, fmpz_poly_mul_precache_t pre, slong n); FMPZ_POLY_INLINE void fmpz_poly_mul_SS_precache(fmpz_poly_t res, const fmpz_poly_t poly1, fmpz_poly_mul_precache_t pre) { fmpz_poly_mullow_SS_precache(res, poly1, pre, FLINT_MAX(poly1->length + pre->len2 - 1, 0)); } /* Squaring ******************************************************************/ void _fmpz_poly_sqr_KS(fmpz * rop, const fmpz * op, slong len); void fmpz_poly_sqr_KS(fmpz_poly_t rop, const fmpz_poly_t op); void fmpz_poly_sqr_karatsuba(fmpz_poly_t rop, const fmpz_poly_t op); void _fmpz_poly_sqr_karatsuba(fmpz * rop, const fmpz * op, slong len); void _fmpz_poly_sqr_classical(fmpz * rop, const fmpz * op, slong len); void fmpz_poly_sqr_classical(fmpz_poly_t rop, const fmpz_poly_t op); void _fmpz_poly_sqr(fmpz * rop, const fmpz * op, slong len); void fmpz_poly_sqr(fmpz_poly_t rop, const fmpz_poly_t op); void _fmpz_poly_sqrlow_KS(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_poly_sqrlow_KS(fmpz_poly_t res, const fmpz_poly_t poly, slong n); void _fmpz_poly_sqrlow_karatsuba_n(fmpz * res, const fmpz * poly, slong n); void _fmpz_poly_sqrlow_karatsuba(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_poly_sqrlow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly, slong n); void _fmpz_poly_sqrlow_classical(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_poly_sqrlow_classical(fmpz_poly_t res, const fmpz_poly_t poly, slong n); void _fmpz_poly_sqrlow(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_poly_sqrlow(fmpz_poly_t res, const fmpz_poly_t poly, slong n); /* Powering ****************************************************************/ void _fmpz_poly_pow_multinomial(fmpz * res, const fmpz * poly, slong len, ulong e); void fmpz_poly_pow_multinomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); void _fmpz_poly_pow_binomial(fmpz * res, const fmpz * poly, ulong e); void fmpz_poly_pow_binomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); void _fmpz_poly_pow_binexp(fmpz * res, const fmpz * poly, slong len, ulong e); void fmpz_poly_pow_binexp(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); void _fmpz_poly_pow_addchains(fmpz * res, const fmpz * poly, slong len, const int * a, int n); void fmpz_poly_pow_addchains(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); void _fmpz_poly_pow_small(fmpz * res, const fmpz * poly, slong len, ulong e); void _fmpz_poly_pow(fmpz * res, const fmpz * poly, slong len, ulong e); void fmpz_poly_pow(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); void _fmpz_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong n); void fmpz_poly_pow_trunc(fmpz_poly_t res, const fmpz_poly_t poly, ulong e, slong n); /* Shifting ****************************************************************/ void _fmpz_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n); void _fmpz_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_poly_shift_left(fmpz_poly_t res, const fmpz_poly_t poly, slong n); void fmpz_poly_shift_right(fmpz_poly_t res, const fmpz_poly_t poly, slong n); /* Norms *******************************************************************/ void _fmpz_poly_2norm(fmpz_t res, const fmpz * poly, slong len); void fmpz_poly_2norm(fmpz_t res, const fmpz_poly_t poly); flint_bitcnt_t _fmpz_poly_2norm_normalised_bits(const fmpz * poly, slong len); ulong fmpz_poly_max_limbs(const fmpz_poly_t poly); slong fmpz_poly_max_bits(const fmpz_poly_t poly); void fmpz_poly_height(fmpz_t res, const fmpz_poly_t poly); slong _fmpz_poly_hamming_weight(const fmpz * a, slong len); /* Greatest common divisor *************************************************/ void _fmpz_poly_gcd_subresultant(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_gcd_subresultant(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); int _fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); int fmpz_poly_gcd_heuristic(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_gcd_modular(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_gcd_modular(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_gcd(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_gcd(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_lcm(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_lcm(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_resultant_modular(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_resultant_modular(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_resultant(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_resultant_modular_div(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_t divisor, slong nbits); void fmpz_poly_resultant_modular_div(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t divisor, slong nbits); void _fmpz_poly_xgcd_modular(fmpz_t r, fmpz * s, fmpz * t, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_xgcd_modular(fmpz_t r, fmpz_poly_t s, fmpz_poly_t t, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FMPZ_POLY_INLINE void _fmpz_poly_xgcd(fmpz_t r, fmpz * s, fmpz * t, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { _fmpz_poly_xgcd_modular(r, s, t, poly1, len1, poly2, len2); } FMPZ_POLY_INLINE void fmpz_poly_xgcd(fmpz_t r, fmpz_poly_t s, fmpz_poly_t t, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { fmpz_poly_xgcd_modular(r, s, t, poly1, poly2); } /* Discriminant ********************************************************/ void _fmpz_poly_discriminant(fmpz_t res, const fmpz * poly, slong len); void fmpz_poly_discriminant(fmpz_t res, const fmpz_poly_t poly); /* Gaussian content ********************************************************/ void _fmpz_poly_content(fmpz_t res, const fmpz * poly, slong len); void fmpz_poly_content(fmpz_t res, const fmpz_poly_t poly); void _fmpz_poly_primitive_part(fmpz * res, const fmpz * poly, slong len); void fmpz_poly_primitive_part(fmpz_poly_t res, const fmpz_poly_t poly); /* Square-free *************************************************************/ int _fmpz_poly_is_squarefree(const fmpz * poly, slong len); int fmpz_poly_is_squarefree(const fmpz_poly_t poly); /* Euclidean division ******************************************************/ int _fmpz_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); void fmpz_poly_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); int _fmpz_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, int exact); int _fmpz_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); void fmpz_poly_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); int _fmpz_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); void fmpz_poly_divrem(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); int _fmpz_poly_div_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); void fmpz_poly_div_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B); int _fmpz_poly_divremlow_divconquer_recursive(fmpz * Q, fmpz * QB, const fmpz * A, const fmpz * B, slong lenB, int exact); int _fmpz_poly_div_divconquer_recursive(fmpz * Q, fmpz * temp, const fmpz * A, const fmpz * B, slong lenB, int exact); int _fmpz_poly_div_divconquer(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); void fmpz_poly_div_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B); int _fmpz_poly_div(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); void fmpz_poly_div(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B); void _fmpz_poly_preinvert(fmpz * B_inv, const fmpz * B, slong n); void fmpz_poly_preinvert(fmpz_poly_t B_inv, const fmpz_poly_t B); void _fmpz_poly_div_preinv(fmpz * Q, const fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2); void fmpz_poly_div_preinv(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv); void _fmpz_poly_divrem_preinv(fmpz * Q, fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2); void fmpz_poly_divrem_preinv(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv); void _fmpz_poly_divexact(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB); void fmpz_poly_divexact(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B); fmpz ** _fmpz_poly_powers_precompute(const fmpz * B, slong len); void fmpz_poly_powers_precompute(fmpz_poly_powers_precomp_t pinv, fmpz_poly_t poly); void _fmpz_poly_powers_clear(fmpz ** powers, slong len); void fmpz_poly_powers_clear(fmpz_poly_powers_precomp_t pinv); void _fmpz_poly_rem_powers_precomp(fmpz * A, slong m, const fmpz * B, slong n, fmpz ** const powers); void fmpz_poly_rem_powers_precomp(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_powers_precomp_t B_inv); void _fmpz_poly_rem_basecase(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB); void fmpz_poly_rem_basecase(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); void _fmpz_poly_rem(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB); void fmpz_poly_rem(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); void fmpz_poly_div_root(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_t c); void _fmpz_poly_div_root(fmpz * Q, const fmpz * A, slong len, const fmpz_t c); /* Power series division ***************************************************/ void _fmpz_poly_inv_series_basecase(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); void fmpz_poly_inv_series_basecase(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); void _fmpz_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); void fmpz_poly_inv_series_newton(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); void _fmpz_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); void fmpz_poly_inv_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); void _fmpz_poly_div_series_basecase(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n); void _fmpz_poly_div_series_divconquer(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n); void _fmpz_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n); void fmpz_poly_div_series_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n); void fmpz_poly_div_series_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n); void fmpz_poly_div_series(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n); /* Divisibility testing ***************************************************/ int _fmpz_poly_divides(fmpz * q, const fmpz * a, slong len1, const fmpz * b, slong len2); int fmpz_poly_divides(fmpz_poly_t q, const fmpz_poly_t a, const fmpz_poly_t b); slong fmpz_poly_remove(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); /* Pseudo division *********************************************************/ #ifdef FMPZ_H void _fmpz_poly_pseudo_divrem_basecase(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong A_len, const fmpz * B, slong B_len, const fmpz_preinvn_t inv); void _fmpz_poly_pseudo_divrem_divconquer(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv); FMPZ_POLY_INLINE void _fmpz_poly_pseudo_divrem(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong A_len, const fmpz * B, slong B_len, const fmpz_preinvn_t inv) { _fmpz_poly_pseudo_divrem_divconquer(Q, R, d, A, A_len, B, B_len, inv); } void _fmpz_poly_pseudo_div(fmpz * Q, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv); void _fmpz_poly_pseudo_rem(fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv); #endif void fmpz_poly_pseudo_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B); void fmpz_poly_pseudo_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B); void _fmpz_poly_pseudo_divrem_cohen(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB); void fmpz_poly_pseudo_divrem_cohen(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); void _fmpz_poly_pseudo_rem_cohen(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB); void fmpz_poly_pseudo_rem_cohen(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); FMPZ_POLY_INLINE void fmpz_poly_pseudo_divrem(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) { fmpz_poly_pseudo_divrem_divconquer(Q, R, d, A, B); } void fmpz_poly_pseudo_div(fmpz_poly_t Q, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B); void fmpz_poly_pseudo_rem(fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B); void fmpz_poly_divlow_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n); void fmpz_poly_divhigh_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n); /* Derivative **************************************************************/ void _fmpz_poly_derivative(fmpz * rpoly, const fmpz * poly, slong len); void fmpz_poly_derivative(fmpz_poly_t res, const fmpz_poly_t poly); void _fmpz_poly_nth_derivative(fmpz * rpoly, const fmpz * poly, ulong n, slong len); void fmpz_poly_nth_derivative(fmpz_poly_t res, const fmpz_poly_t poly, ulong n); /* Evaluation **************************************************************/ void _fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz * poly, slong len, const fmpz_t a); void fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz_poly_t poly, const fmpz_t a); void _fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a); void fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a); void _fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a); void fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a); void _fmpz_poly_evaluate_horner_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden); void fmpz_poly_evaluate_horner_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a); void _fmpz_poly_evaluate_divconquer_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden); void fmpz_poly_evaluate_divconquer_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a); void _fmpz_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden); void fmpz_poly_evaluate_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a); mp_limb_t _fmpz_poly_evaluate_mod(const fmpz * poly, slong len, mp_limb_t a, mp_limb_t n, mp_limb_t ninv); mp_limb_t fmpz_poly_evaluate_mod(const fmpz_poly_t poly, mp_limb_t a, mp_limb_t n); double _fmpz_poly_evaluate_horner_d(const fmpz * poly, slong n, double d); double fmpz_poly_evaluate_horner_d(const fmpz_poly_t poly, double d); double _fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz * poly, slong n, double d); double fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz_poly_t poly, double d); double _fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz * poly, slong n, double d, slong dexp); double fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz_poly_t poly, double d, slong dexp); /* Composition *************************************************************/ void _fmpz_poly_compose_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_compose_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_compose_divconquer(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_compose_divconquer(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); void _fmpz_poly_compose(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); void fmpz_poly_compose(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); /* Taylor shift ************************************************************/ void _fmpz_poly_taylor_shift_horner(fmpz * poly, const fmpz_t c, slong n); void fmpz_poly_taylor_shift_horner(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c); void _fmpz_poly_taylor_shift_divconquer(fmpz * poly, const fmpz_t c, slong n); void fmpz_poly_taylor_shift_divconquer(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c); void _fmpz_poly_taylor_shift_multi_mod(fmpz * poly, const fmpz_t c, slong n); FMPZ_POLY_INLINE void fmpz_poly_taylor_shift_multi_mod(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) { if (f != g) fmpz_poly_set(g, f); _fmpz_poly_taylor_shift_multi_mod(g->coeffs, c, g->length); } void _fmpz_poly_taylor_shift(fmpz * poly, const fmpz_t c, slong n); void fmpz_poly_taylor_shift(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c); /* Power series composition and compositional inverse **********************/ void _fmpz_poly_compose_series_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); void fmpz_poly_compose_series_brent_kung(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_compose_series_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); void fmpz_poly_compose_series_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_compose_series(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); void fmpz_poly_compose_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); void _fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); void fmpz_poly_revert_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); /* Square root *************************************************************/ int _fmpz_poly_sqrtrem_classical(fmpz * res, fmpz * r, const fmpz * poly, slong len); int fmpz_poly_sqrtrem_classical(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a); int _fmpz_poly_sqrtrem_divconquer(fmpz * res, fmpz * r, const fmpz * poly, slong len, fmpz * temp); int fmpz_poly_sqrtrem_divconquer(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a); int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, slong len, int exact); int fmpz_poly_sqrt_classical(fmpz_poly_t b, const fmpz_poly_t a); int _fmpz_poly_sqrt_divconquer(fmpz * res, const fmpz * poly, slong len, int exact); int fmpz_poly_sqrt_divconquer(fmpz_poly_t b, const fmpz_poly_t a); int _fmpz_poly_sqrt_KS(fmpz *rop, const fmpz *op, slong len); int fmpz_poly_sqrt_KS(fmpz_poly_t b, const fmpz_poly_t a); int _fmpz_poly_sqrt(fmpz * res, const fmpz * poly, slong len); int fmpz_poly_sqrt(fmpz_poly_t b, const fmpz_poly_t a); int _fmpz_poly_sqrt_series(fmpz * res, const fmpz * poly, slong len, slong n); int fmpz_poly_sqrt_series(fmpz_poly_t b, const fmpz_poly_t a, slong n); /* Power sums ****************************************************************/ void _fmpz_poly_power_sums_naive(fmpz * res, const fmpz * poly, slong len, slong n); void fmpz_poly_power_sums_naive(fmpz_poly_t res, const fmpz_poly_t poly, slong n); void fmpz_poly_power_sums(fmpz_poly_t res, const fmpz_poly_t poly, slong n); void _fmpz_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, slong len); void fmpz_poly_power_sums_to_poly(fmpz_poly_t res, const fmpz_poly_t Q); /* Signature ***************************************************************/ void _fmpz_poly_signature(slong * r1, slong * r2, const fmpz * poly, slong len); void fmpz_poly_signature(slong * r1, slong * r2, const fmpz_poly_t poly); /* Input and output ********************************************************/ #ifdef FLINT_HAVE_FILE int _fmpz_poly_fprint(FILE * file, const fmpz * poly, slong len); int fmpz_poly_fprint(FILE * file, const fmpz_poly_t poly); int _fmpz_poly_fprint_pretty(FILE * file, const fmpz * poly, slong len, const char * x); int fmpz_poly_fprint_pretty(FILE * file, const fmpz_poly_t poly, const char * x); int fmpz_poly_fread(FILE * file, fmpz_poly_t poly); int fmpz_poly_fread_pretty(FILE *file, fmpz_poly_t poly, char **x); #endif int _fmpz_poly_print_pretty(const fmpz * poly, slong len, const char * x); int fmpz_poly_print_pretty(const fmpz_poly_t poly, const char * x); int _fmpz_poly_print(const fmpz * poly, slong n); int fmpz_poly_print(const fmpz_poly_t poly); int fmpz_poly_read(fmpz_poly_t poly); int fmpz_poly_read_pretty(fmpz_poly_t poly, char **x); void fmpz_poly_debug(const fmpz_poly_t poly); /* CRT ********************************************************************/ void fmpz_poly_get_nmod_poly(nmod_poly_t res, const fmpz_poly_t poly); void fmpz_poly_set_nmod_poly(fmpz_poly_t res, const nmod_poly_t poly); void fmpz_poly_set_nmod_poly_unsigned(fmpz_poly_t res, const nmod_poly_t poly); void _fmpz_poly_CRT_ui_precomp(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2, mp_limb_t m2inv, fmpz_t m1m2, mp_limb_t c, int sign); void _fmpz_poly_CRT_ui(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2, mp_limb_t m2inv, int sign); void fmpz_poly_CRT_ui(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_t m1, const nmod_poly_t poly2, int sign); /* Products *****************************************************************/ void _fmpz_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n); void fmpz_poly_product_roots_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, slong n); void _fmpz_poly_product_roots_fmpq_vec(fmpz * poly, const fmpq * xs, slong n); void fmpz_poly_product_roots_fmpq_vec(fmpz_poly_t poly, const fmpq * xs, slong n); /* Newton basis *************************************************************/ void _fmpz_poly_monomial_to_newton(fmpz * poly, const fmpz * roots, slong n); void _fmpz_poly_newton_to_monomial(fmpz * poly, const fmpz * roots, slong n); /* Multipoint evaluation and interpolation *********************************/ void fmpz_poly_evaluate_fmpz_vec(fmpz * res, const fmpz_poly_t f, const fmpz * a, slong n); void fmpz_poly_interpolate_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n); /* Hensel lifting ************************************************************/ void fmpz_poly_hensel_build_tree(slong * link, fmpz_poly_t *v, fmpz_poly_t *w, const nmod_poly_factor_t fac); void fmpz_poly_hensel_lift(fmpz_poly_t Gout, fmpz_poly_t Hout, fmpz_poly_t Aout, fmpz_poly_t Bout, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1); void _fmpz_poly_hensel_lift_without_inverse(fmpz *G, fmpz *H, const fmpz *f, slong lenF, const fmpz *g, slong lenG, const fmpz *h, slong lenH, const fmpz *a, slong lenA, const fmpz *b, slong lenB, const fmpz_t p, const fmpz_t p1); void fmpz_poly_hensel_lift_without_inverse(fmpz_poly_t Gout, fmpz_poly_t Hout, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1); void _fmpz_poly_hensel_lift_only_inverse(fmpz *A, fmpz *B, const fmpz *G, slong lenG, const fmpz *H, slong lenH, const fmpz *a, slong lenA, const fmpz *b, slong lenB, const fmpz_t p, const fmpz_t p1); void fmpz_poly_hensel_lift_only_inverse(fmpz_poly_t Aout, fmpz_poly_t Bout, const fmpz_poly_t G, const fmpz_poly_t H, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1); void fmpz_poly_hensel_lift_tree_recursive(slong *link, fmpz_poly_t *v, fmpz_poly_t *w, fmpz_poly_t f, slong j, slong inv, const fmpz_t p0, const fmpz_t p1); void fmpz_poly_hensel_lift_tree(slong *link, fmpz_poly_t *v, fmpz_poly_t *w, fmpz_poly_t f, slong r, const fmpz_t p, slong e0, slong e1, slong inv); slong _fmpz_poly_hensel_start_lift(fmpz_poly_factor_t lifted_fac, slong *link, fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, slong target_exp); slong _fmpz_poly_hensel_continue_lift(fmpz_poly_factor_t lifted_fac, slong *link, fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f, slong prev, slong curr, slong N, const fmpz_t p); void fmpz_poly_hensel_lift_once(fmpz_poly_factor_t lifted_fac, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, slong N); /* Roots */ void _fmpz_poly_bound_roots(fmpz_t bound, const fmpz * poly, slong len); void fmpz_poly_bound_roots(fmpz_t bound, const fmpz_poly_t poly); void _fmpz_poly_num_real_roots_sturm(slong * n_neg, slong * n_pos, const fmpz * pol, slong len); slong fmpz_poly_num_real_roots_sturm(const fmpz_poly_t poly); slong _fmpz_poly_num_real_roots(const fmpz * pol, slong len); slong fmpz_poly_num_real_roots(const fmpz_poly_t poly); /* CLD bounds */ void fmpz_poly_CLD_bound(fmpz_t res, const fmpz_poly_t f, slong n); /* Special polynomials */ void _fmpz_poly_cyclotomic(fmpz * a, ulong n, mp_ptr factors, slong num_factors, ulong phi); void fmpz_poly_cyclotomic(fmpz_poly_t poly, ulong n); ulong _fmpz_poly_is_cyclotomic(const fmpz * poly, slong len); ulong fmpz_poly_is_cyclotomic(const fmpz_poly_t poly); void _fmpz_poly_cos_minpoly(fmpz * f, ulong n); void fmpz_poly_cos_minpoly(fmpz_poly_t f, ulong n); void _fmpz_poly_swinnerton_dyer(fmpz * T, ulong n); void fmpz_poly_swinnerton_dyer(fmpz_poly_t poly, ulong n); void _fmpz_poly_chebyshev_t(fmpz * coeffs, ulong n); void fmpz_poly_chebyshev_t(fmpz_poly_t poly, ulong n); void _fmpz_poly_chebyshev_u(fmpz * coeffs, ulong n); void fmpz_poly_chebyshev_u(fmpz_poly_t poly, ulong n); void _fmpz_poly_legendre_pt(fmpz * coeffs, ulong n); void fmpz_poly_legendre_pt(fmpz_poly_t poly, ulong n); void _fmpz_poly_hermite_h(fmpz * coeffs, ulong n); void fmpz_poly_hermite_h(fmpz_poly_t poly, ulong n); void _fmpz_poly_hermite_he(fmpz * coeffs, ulong n); void fmpz_poly_hermite_he(fmpz_poly_t poly, ulong n); void _fmpz_poly_fibonacci(fmpz * coeffs, ulong n); void fmpz_poly_fibonacci(fmpz_poly_t poly, ulong n); void _fmpz_poly_eta_qexp(fmpz * f, slong e, slong n); void fmpz_poly_eta_qexp(fmpz_poly_t f, slong e, slong n); void _fmpz_poly_theta_qexp(fmpz * f, slong e, slong n); void fmpz_poly_theta_qexp(fmpz_poly_t f, slong e, slong n); void fmpz_poly_eulerian_polynomial(fmpz_poly_t poly, ulong n); /* Declare some old functions dead */ #define fmpz_poly_scalar_mul_mpz _Pragma("GCC error \"'fmpz_poly_scalar_mul_mpz' is deprecated. Use 'fmpz_poly_scalar_mul_fmpz' instead.\"") #define fmpz_poly_scalar_divexact_mpz _Pragma("GCC error \"'fmpz_poly_scalar_divexact_mpz' is deprecated. Use 'fmpz_poly_scalar_divexact_fmpz' instead.\"") #define fmpz_poly_scalar_fdiv_mpz _Pragma("GCC error \"'fmpz_poly_scalar_fdiv_mpz' is deprecated. Use 'fmpz_poly_scalar_fdiv_fmpz' instead.\"") #define fmpz_poly_set_coeff_mpz _Pragma("GCC error \"'fmpz_poly_set_coeff_mpz' is deprecated. Use 'fmpz_poly_set_coeff_fmpz' instead.\"") #define fmpz_poly_get_coeff_mpz _Pragma("GCC error \"'fmpz_poly_get_coeff_mpz' is deprecated. Use 'fmpz_poly_get_coeff_fmpz' instead.\"") #define fmpz_poly_set_mpz _Pragma("GCC error \"'fmpz_poly_set_mpz' is deprecated. Use 'fmpz_poly_set_fmpz' instead.\"") #define fmpz_poly_evaluate_mpq _Pragma("GCC error \"'fmpz_poly_evaluate_mpq' is deprecated. Use 'fmpz_poly_evaluate_fmpq' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_poly/000077500000000000000000000000001461254215100154415ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly/2norm.c000066400000000000000000000012731461254215100166450ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_2norm(fmpz_t res, const fmpz * poly, slong len) { _fmpz_vec_dot(res, poly, poly, len); fmpz_sqrt(res, res); } void fmpz_poly_2norm(fmpz_t res, const fmpz_poly_t poly) { _fmpz_poly_2norm(res, poly->coeffs, poly->length); } flint-3.1.3/src/fmpz_poly/2norm_normalised_bits.c000066400000000000000000000012731461254215100221030ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" flint_bitcnt_t _fmpz_poly_2norm_normalised_bits(const fmpz * poly, slong len) { fmpz_t norm; flint_bitcnt_t bits; fmpz_init(norm); _fmpz_poly_2norm(norm, poly, len); bits = fmpz_bits(norm); fmpz_clear(norm); return bits - fmpz_bits(poly + len - 1) + 1; } flint-3.1.3/src/fmpz_poly/CLD_bound.c000066400000000000000000000204421461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2010, 2016, 2020 William Hart Copyright (C) 2010 Andy Novocin Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "double_extras.h" #define CLD_EPS 0.00000001 FLINT_FORCE_INLINE double _log2(double n) { return log(n)/log(2); } static int _d_cmp_2exp(double a, slong a_exp, double b, slong b_exp) { long t; if (a_exp == 0) { if (b_exp == 0) { if (a > 1.5*b) return 2; else if (b > 1.5*a) return -2; else if (a >= b) return 1; else return -1; } t = 1 + (long) _log2(a); if (t >= b_exp + 2) /* a, a_exp >= 2*(b, b_exp) */ return 2; else if (b_exp >= t + 2) /* b, b_exp >= 2*(a, a_exp) */ return -2; else /* divide both values by 4 and try again */ return _d_cmp_2exp(a/4, 0, b*pow(2.0, (double) b_exp - 2.0), 0); } else if (b_exp == 0) return -_d_cmp_2exp(b, b_exp, a, a_exp); else /* neither a_exp not b_exp is zero */ { if (a_exp >= b_exp + 2) /* a, a_exp >= 2*(b, b_exp) */ return 2; else if (b_exp >= a_exp + 2) /* b, b_exp >= 2*(a, a_exp) */ return -2; else if (a_exp >= b_exp) /* shift exponents so one is 0 */ return _d_cmp_2exp(a, a_exp - b_exp, b, 0); else return -_d_cmp_2exp(b, b_exp - a_exp, a, 0); } } double _fmpz_poly_evaluate_horner_d_2exp2_precomp(slong * exp, const double * poly, const slong * poly_exp, slong n, double d, slong dexp); void fmpz_poly_CLD_bound(fmpz_t res, const fmpz_poly_t f, slong n) { /* Given: f = a_0 + ... + a_N x^N and n in {0, 1, ..., N - 1} Let B_1(r) = 1/(r^{n+1})(|a_0| + ... + |a_n|r^n) Let B_2(r) = 1/(r^{n+1})(|a_{n + 1}|r^{n+1} + ... + |a_N|r^N) Find r > 0 such that Max{B_1(r), B_2(r)} is minimized Return N*Max{B_1(r), B_2(r)} */ /* We let hi(x) = 1/x^(n+1) * (|a_{n+1}|*x^(n+1) + ... + |a_N|*x^N) so that hi(r) = |a_{n+1}| + ... + |a_N|*r^(N-n-1) = B_2(r) and let lo(x) = |a_n|*x + ... + |a_0|*x^(n+1) so that lo(1/r) = |a_n|/r + ... + |a_0|/r^{n+1} = B_1(r) */ /* We notionally begin by letting lo_eval = B_1(0) which has the value +INF. And we let hi_eval = B_2(0) which has the value |a_{n+1}|. We see that lo_eval is too large, so we set step = 1 and add step to the power of the evaluation point for B_1. We keep adding step until lo_eval is not too large. We then halve step and switch its direction. We keep doing this until we have refined the value sufficiently. */ fmpz_poly_t lo, hi; double rpow = 0, hi_eval, lo_eval, max_eval; double step = 1.0; slong size_f = FLINT_ABS(fmpz_poly_max_bits(f)); slong hi_exp = 0, lo_exp = 0; slong rbits, max_exp, rexp = 0; int too_much = 0; double * hi_d, * hi_d_m, * lo_d, * lo_d_m; slong * hi_d_exp, * lo_d_exp; slong i; fmpz_poly_init(lo); fmpz_poly_init(hi); /* compute lo(x) and hi(x) */ fmpz_poly_set_trunc(lo, f, n + 1); fmpz_poly_scalar_abs(lo, lo); fmpz_poly_reverse(lo, lo, n + 2); fmpz_poly_shift_right(hi, f, n + 1); fmpz_poly_scalar_abs(hi, hi); lo_d = flint_malloc(sizeof(double) * (2 * lo->length + 2 * hi->length)); lo_d_m = lo_d + lo->length; hi_d = lo_d_m + lo->length; hi_d_m = hi_d + hi->length; lo_d_exp = flint_malloc(sizeof(slong) * (lo->length + hi->length)); hi_d_exp = lo_d_exp + lo->length; for (i = 0; i < lo->length; i++) { lo_d[i] = fmpz_get_d(lo->coeffs + i); lo_d_m[i] = fmpz_get_d_2exp(lo_d_exp + i, lo->coeffs + i); } for (i = 0; i < hi->length; i++) { hi_d[i] = fmpz_get_d(hi->coeffs + i); hi_d_m[i] = fmpz_get_d_2exp(hi_d_exp + i, hi->coeffs + i); } /* refine guess */ while (1) { /* compute approx max_exp that evaluation will use */ rbits = fabs(rpow); max_exp = rbits*hi->length + size_f + 1; if (rbits > 200 || rexp != 0) /* r itself has a large exponent */ { /* r is really 2^rpow * 2^rexp */ double r = pow(2.0, rpow); hi_eval = _fmpz_poly_evaluate_horner_d_2exp2_precomp(&hi_exp, hi_d_m, hi_d_exp, hi->length, r, rexp); lo_eval = _fmpz_poly_evaluate_horner_d_2exp2_precomp(&lo_exp, lo_d_m, lo_d_exp, lo->length, 1/r, -rexp); } /* if max exponent may overwhelm a double (with safety margin) */ else if (max_exp > 950 || too_much) /* result of eval has large exponent */ { double r = pow(2.0, rpow); hi_eval = _fmpz_poly_evaluate_horner_d_2exp2_precomp(&hi_exp, hi_d_m, hi_d_exp, hi->length, r, 0.0); lo_eval = _fmpz_poly_evaluate_horner_d_2exp2_precomp(&lo_exp, lo_d_m, lo_d_exp, lo->length, 1/r, 0.0); } else /* everything can be handled with doubles */ { double r = pow(2.0, rpow); hi_eval = d_polyval(hi_d, hi->length, r); lo_eval = d_polyval(lo_d, lo->length, 1/r); hi_exp = lo_exp = 0; } /* if doubles suffice */ if (hi_exp == 0 && lo_exp == 0) { if (1.5*lo_eval < hi_eval) { /* lo_eval is too small */ if (step >= 0.0) step = -step/2.0; rpow += step; } else if (lo_eval > 1.5*hi_eval) { /* lo_eval is too big */ if (step < 0.0) step = -step/2.0; rpow += step; } else if (hi_eval != hi_eval || lo_eval != lo_eval) { /* doubles were insufficient after all */ too_much = 1; } else /* we are done */ { if (hi_eval > lo_eval) max_eval = hi_eval; else max_eval = lo_eval; /* we adjust due to rounding errors in horner's evaluation */ fmpz_set_d(res, max_eval*(f->length - 1)*(1.0 + f->length*ldexp(2.0, -51))); goto cleanup; } } else { /* too big for doubles alone, so we represent in d*2^exp format _d_cmp_2exp will return 2 when 2*lo < hi, -2 when 2*hi < lo 1 when lo <= hi and -1 when lo > hi */ int cmp; /* just compare exponents, because it's probably not going to converge otherwise */ if (rbits > 200 || rexp != 0) { if ((hi_exp + _log2(hi_eval)) > 1.01 * (lo_exp + _log2(lo_eval))) cmp = 2; else if ((lo_exp + _log2(lo_eval)) > 1.01 * (hi_exp + _log2(hi_eval))) cmp = -2; else if ((hi_exp + _log2(hi_eval)) >= (lo_exp + _log2(lo_eval))) cmp = 1; else cmp = -1; } else { cmp = _d_cmp_2exp(hi_eval, hi_exp, lo_eval, lo_exp); } if (fabs(step) < CLD_EPS) /* give up if step is now very small */ { cmp = cmp == 2 ? 1 : -1; } switch (cmp) { case 2: if (step >= 0.0) step = -step/2.0; rpow += step; break; case -2: if (step < 0.0) step = -step/2.0; rpow += step; break; case 1: /* we adjust due to rounding errors in horner's evaluation */ fmpz_set_d_2exp(res, hi_eval*(f->length - 1)*(1.0 + f->length*ldexp(2.0, -51)), hi_exp); goto cleanup; case -1: /* we adjust due to rounding errors in horner's evaluation */ fmpz_set_d_2exp(res, lo_eval*(f->length - 1)*(1.0 + f->length*ldexp(2.0, -51)), lo_exp); goto cleanup; } } if (rpow > 1000.0) { rpow -= 1000.0; rexp += 1000; } else if (rpow < -1000.0) { rpow += 1000.0; rexp -= 1000; } } cleanup: flint_free(lo_d); flint_free(lo_d_exp); fmpz_poly_clear(lo); fmpz_poly_clear(hi); } flint-3.1.3/src/fmpz_poly/CRT_ui.c000066400000000000000000000047071461254215100167420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_CRT_ui_precomp(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2, mp_limb_t m2inv, fmpz_t m1m2, mp_limb_t c, int sign) { slong i; for (i = 0; i < FLINT_MIN(len1, len2); i++) { _fmpz_CRT_ui_precomp(res + i, poly1 + i, m1, poly2[i], m2, m2inv, m1m2, c, sign); } if (len2 > len1) { fmpz_t zero; fmpz_init(zero); for (i = len1; i < len2; i++) { _fmpz_CRT_ui_precomp(res + i, zero, m1, poly2[i], m2, m2inv, m1m2, c, sign); } fmpz_clear(zero); } for (i = len2; i < len1; i++) { _fmpz_CRT_ui_precomp(res + i, res + i, m1, 0, m2, m2inv, m1m2, c, sign); } } void _fmpz_poly_CRT_ui(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2, mp_limb_t m2inv, int sign) { mp_limb_t c; fmpz_t m1m2; c = fmpz_fdiv_ui(m1, m2); c = n_invmod(c, m2); if (c == 0) { flint_throw(FLINT_ERROR, "Exception (_fmpz_poly_CRT_ui): m1 not invertible modulo m2.\n"); } fmpz_init(m1m2); fmpz_mul_ui(m1m2, m1, m2); _fmpz_poly_CRT_ui_precomp(res, poly1, len1, m1, poly2, len2, m2, m2inv, m1m2, c, sign); fmpz_clear(m1m2); } void fmpz_poly_CRT_ui(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_t m1, const nmod_poly_t poly2, int sign) { slong len1 = poly1->length; slong len2 = poly2->length; slong len = FLINT_MAX(len1, len2); if (len == 0) { fmpz_poly_zero(res); return; } fmpz_poly_fit_length(res, len); _fmpz_poly_CRT_ui(res->coeffs, poly1->coeffs, poly1->length, m1, poly2->coeffs, poly2->length, poly2->mod.n, poly2->mod.ninv, sign); _fmpz_poly_set_length(res, len); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/add.c000066400000000000000000000041221461254215100163340ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_add(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) /* add up to the length of the shorter poly */ fmpz_add(res + i, poly1 + i, poly2 + i); if (poly1 != res) /* copy any remaining coefficients from poly1 */ for (i = min; i < len1; i++) fmpz_set(res + i, poly1 + i); if (poly2 != res) /* copy any remaining coefficients from poly2 */ for (i = min; i < len2; i++) fmpz_set(res + i, poly2 + i); } void fmpz_poly_add(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong max = FLINT_MAX(poly1->length, poly2->length); fmpz_poly_fit_length(res, max); _fmpz_poly_add(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); _fmpz_poly_set_length(res, max); _fmpz_poly_normalise(res); /* there may have been cancellation */ } void fmpz_poly_add_si(fmpz_poly_t res, const fmpz_poly_t poly, slong c) { if (poly->length == 0) fmpz_poly_set_si(res, c); else { fmpz_poly_set(res, poly); if (c < 0) fmpz_sub_ui(res->coeffs + 0, res->coeffs + 0, -c); else fmpz_add_ui(res->coeffs + 0, res->coeffs + 0, c); _fmpz_poly_normalise(res); } } void fmpz_poly_add_fmpz(fmpz_poly_t res, const fmpz_poly_t poly, fmpz_t c) { if (poly->length == 0) fmpz_poly_set_fmpz(res, c); else { fmpz_poly_set(res, poly); fmpz_add(res->coeffs + 0, res->coeffs + 0, c); _fmpz_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/add_series.c000066400000000000000000000016641461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_add_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); fmpz_poly_fit_length(res, max); _fmpz_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, max); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/bit_pack.c000066400000000000000000000034511461254215100173640ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_bit_pack(mp_ptr arr, const fmpz * poly, slong len, flint_bitcnt_t bit_size, int negate) { flint_bitcnt_t bits = 0; mp_size_t limbs = 0; flint_bitcnt_t b = bit_size % FLINT_BITS; mp_size_t l = bit_size / FLINT_BITS; int borrow = 0; slong i; for (i = 0; i < len; i++) { borrow = fmpz_bit_pack(arr + limbs, bits, bit_size, poly + i, negate, borrow); limbs += l; bits += b; if (bits >= FLINT_BITS) { bits -= FLINT_BITS; limbs++; } } } void fmpz_poly_bit_pack(fmpz_t f, const fmpz_poly_t poly, flint_bitcnt_t bit_size) { slong len; __mpz_struct * mpz; slong i, d; int negate; len = fmpz_poly_length(poly); if (len == 0 || bit_size == 0) { fmpz_zero(f); return; } mpz = _fmpz_promote(f); mpz_realloc2(mpz, len * bit_size); d = mpz->_mp_alloc; flint_mpn_zero(mpz->_mp_d, d); if (fmpz_sgn(fmpz_poly_lead(poly)) < 0) negate = -1; else negate = 0; _fmpz_poly_bit_pack(mpz->_mp_d, poly->coeffs, len, bit_size, negate); for (i = d - 1; i >= 0; i--) { if (mpz->_mp_d[i] != 0) break; } d = i + 1; mpz->_mp_size = d; _fmpz_demote_val(f); if (negate) fmpz_neg(f, f); } flint-3.1.3/src/fmpz_poly/bit_unpack.c000066400000000000000000000063711461254215100177330ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" int _fmpz_poly_bit_unpack(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size, int negate) { flint_bitcnt_t bits = 0; mp_size_t limbs = 0; flint_bitcnt_t b = bit_size % FLINT_BITS; mp_size_t l = bit_size / FLINT_BITS; int borrow = 0; slong i; for (i = 0; i < len; i++) { borrow = fmpz_bit_unpack(poly + i, arr + limbs, bits, bit_size, negate, borrow); limbs += l; bits += b; if (bits >= FLINT_BITS) { bits -= FLINT_BITS; limbs++; } } return borrow; } void _fmpz_poly_bit_unpack_unsigned(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size) { flint_bitcnt_t bits = 0; mp_size_t limbs = 0; flint_bitcnt_t b = bit_size % FLINT_BITS; mp_size_t l = bit_size / FLINT_BITS; slong i; for (i = 0; i < len; i++) { fmpz_bit_unpack_unsigned(poly + i, arr + limbs, bits, bit_size); limbs += l; bits += b; if (bits >= FLINT_BITS) { bits -= FLINT_BITS; limbs++; } } } void fmpz_poly_bit_unpack_unsigned(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size) { slong len; mpz_t tmp; if (fmpz_sgn(f) < 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_bit_unpack_unsigned). Expected an unsigned value.\n"); } if (bit_size == 0 || fmpz_is_zero(f)) { fmpz_poly_zero(poly); return; } len = (fmpz_bits(f) + bit_size - 1) / bit_size; mpz_init2(tmp, bit_size*len); flint_mpn_zero(tmp->_mp_d, tmp->_mp_alloc); fmpz_get_mpz(tmp, f); fmpz_poly_fit_length(poly, len); _fmpz_poly_bit_unpack_unsigned(poly->coeffs, len, tmp->_mp_d, bit_size); _fmpz_poly_set_length(poly, len); _fmpz_poly_normalise(poly); mpz_clear(tmp); } void fmpz_poly_bit_unpack(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size) { slong len; mpz_t tmp; int negate, borrow; if (bit_size == 0 || fmpz_is_zero(f)) { fmpz_poly_zero(poly); return; } /* Round up */ len = (fmpz_bits(f) + bit_size - 1) / bit_size; negate = (fmpz_sgn(f) < 0) ? -1 : 0; mpz_init2(tmp, bit_size*len); /* TODO: avoid all this wastefulness */ flint_mpn_zero(tmp->_mp_d, tmp->_mp_alloc); fmpz_get_mpz(tmp, f); fmpz_poly_fit_length(poly, len + 1); borrow = _fmpz_poly_bit_unpack(poly->coeffs, len, tmp->_mp_d, bit_size, negate); if (borrow) { fmpz_set_si(poly->coeffs + len, negate ? WORD(-1) : WORD(1)); _fmpz_poly_set_length(poly, len + 1); } else { _fmpz_poly_set_length(poly, len); _fmpz_poly_normalise(poly); } mpz_clear(tmp); } flint-3.1.3/src/fmpz_poly/bound_roots.c000066400000000000000000000031061461254215100201420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" /* quotient of absolute value, rounded up */ static inline void fmpz_cdiv_abs_q(fmpz_t q, const fmpz_t x, const fmpz_t y) { if (fmpz_sgn(x) == fmpz_sgn(y)) { fmpz_cdiv_q(q, x, y); } else { fmpz_fdiv_q(q, x, y); fmpz_neg(q, q); } } void _fmpz_poly_bound_roots(fmpz_t bound, const fmpz * poly, slong len) { if (len <= 1) { fmpz_zero(bound); } else if (len == 2) { fmpz_cdiv_abs_q(bound, poly + 0, poly + 1); } else { slong i; fmpz_t t; fmpz_init(t); fmpz_mul_2exp(t, poly + len - 1, 1); fmpz_cdiv_abs_q(bound, poly + 0, t); fmpz_root(bound, bound, len - 1); for (i = 1; i < len - 1; i++) { fmpz_cdiv_abs_q(t, poly + len - i - 1, poly + len - 1); fmpz_root(t, t, i); fmpz_add_ui(t, t, 1); if (fmpz_cmp(t, bound) > 0) fmpz_swap(t, bound); } fmpz_mul_2exp(bound, bound, 1); fmpz_clear(t); } } void fmpz_poly_bound_roots(fmpz_t bound, const fmpz_poly_t poly) { _fmpz_poly_bound_roots(bound, poly->coeffs, poly->length); } flint-3.1.3/src/fmpz_poly/chebyshev_t.c000066400000000000000000000024341461254215100201130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_chebyshev_t(fmpz * coeffs, ulong n) { slong k, i, d, m; if (n == 0) { fmpz_one(coeffs); return; } if (n == 1) { fmpz_zero(coeffs); fmpz_one(coeffs + 1); return; } d = n % 2; fmpz_zero(coeffs); fmpz_set_ui(coeffs + d, d ? n : 1); if (n % 4 >= 2) fmpz_neg(coeffs + d, coeffs + d); m = n / 2; for (k = 1; k <= m; k++) { i = 2 * k + d; fmpz_mul2_uiui(coeffs + i, coeffs + i - 2, 4*(m-k+1), n+k-m-1); fmpz_divexact2_uiui(coeffs + i, coeffs + i, n+2*k-2*m-1, n+2*k-2*m); fmpz_neg(coeffs + i, coeffs + i); fmpz_zero(coeffs + i - 1); } } void fmpz_poly_chebyshev_t(fmpz_poly_t poly, ulong n) { fmpz_poly_fit_length(poly, n + 1); _fmpz_poly_chebyshev_t(poly->coeffs, n); _fmpz_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpz_poly/chebyshev_u.c000066400000000000000000000024441461254215100201150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_chebyshev_u(fmpz * coeffs, ulong n) { slong k, i, d, m; if (n == 0) { fmpz_one(coeffs); return; } if (n == 1) { fmpz_zero(coeffs); fmpz_set_ui(coeffs + 1, 2); return; } d = n % 2; fmpz_zero(coeffs); fmpz_set_ui(coeffs + d, d ? n + 1 : 1); if (n % 4 >= 2) fmpz_neg(coeffs + d, coeffs + d); m = n / 2; for (k = 1; k <= m; k++) { i = 2 * k + d; fmpz_mul2_uiui(coeffs + i, coeffs + i - 2, 4*(m-k+1), n+k-m); fmpz_divexact2_uiui(coeffs + i, coeffs + i, n+2*k-2*m-1, n+2*k-2*m); fmpz_neg(coeffs + i, coeffs + i); fmpz_zero(coeffs + i - 1); } } void fmpz_poly_chebyshev_u(fmpz_poly_t poly, ulong n) { fmpz_poly_fit_length(poly, n + 1); _fmpz_poly_chebyshev_u(poly->coeffs, n); _fmpz_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpz_poly/clear.c000066400000000000000000000012521461254215100166730ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_clear(fmpz_poly_t poly) { if (poly->coeffs) { slong i; for (i = 0; i < poly->alloc; i++) _fmpz_demote(poly->coeffs + i); flint_free(poly->coeffs); } } flint-3.1.3/src/fmpz_poly/compose.c000066400000000000000000000053341461254215100172570ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2016 Shivin Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_compose(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if (len1 == 1) fmpz_set(res, poly1); else if (len2 == 1) _fmpz_poly_evaluate_fmpz(res, poly1, len1, poly2); else if (len1 <= 4) _fmpz_poly_compose_horner(res, poly1, len1, poly2, len2); else if (len2 == 2) { slong i; _fmpz_vec_set(res, poly1, len1); _fmpz_poly_taylor_shift(res, poly2, len1); if (fmpz_equal_si(poly2 + 1, -1)) { for (i = 1; i < len1; i += 2) fmpz_neg(res + i, res + i); return; } else if (!fmpz_is_one(poly2 + 1)) { fmpz_t temp; fmpz_init(temp); fmpz_one(temp); for (i = 0; i < len1; i++) { fmpz_mul(res + i, res + i, temp); /* no need to reverse signs manually as if poly2 + 1 negative then signs alternate automatically*/ fmpz_mul(temp, temp, poly2 + 1); } fmpz_clear(temp); } return; } else _fmpz_poly_compose_divconquer(res, poly1, len1, poly2, len2); } void fmpz_poly_compose(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; slong lenr; if (len1 == 0) { fmpz_poly_zero(res); return; } if (len1 == 1 || len2 == 0) { fmpz_poly_set_fmpz(res, poly1->coeffs); return; } lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { fmpz_poly_fit_length(res, lenr); _fmpz_poly_compose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, lenr); _fmpz_poly_normalise(res); } else { fmpz_poly_t t; fmpz_poly_init2(t, lenr); _fmpz_poly_compose(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(t, lenr); _fmpz_poly_normalise(t); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } flint-3.1.3/src/fmpz_poly/compose_divconquer.c000066400000000000000000000150221461254215100215110ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumptions. Suppose that $len1 \geq 3$ and $len2 \geq 2$. Definitions. Define a sequence $(n_i)$ by $n_1 = \ceil{len1 / 2}$, $n_2 = \ceil{n_1 / 2}$, etc. all the way to $n_K = \ceil{n_{K-1} / 2} = 2$. Thus, $K = \ceil{\log_2 len1} - 1$. Note that we can write $n_i = \ceil{len1 / 2^i}$. Rough description (of the allocation process, or the algorithm). Step 1. For $0 \leq i < n_1$, set h[i] to something of length at most len2. Set pow to $poly2^2$. Step n. For $0 \leq i < n_n$, set h[i] to something of length at most the length of $poly2^{2^n - 1}$. Set pow to $poly^{2^n}$. Step K. For $0 \leq i < n_K$, set h[i] to something of length at most the length of $poly2^{2^K - 1}$. Set pow to $poly^{2^K}$. Analysis of the space requirements. Let $S$ be the over all space we need, measured in number of coefficients. Then \begin{align*} S & = 2 \times \bigl[ (2^K - 1) (len2 - 1) + 1 \bigr] + \sum_{i=1}^{K-1} (n_i - n_{i+1}) \bigl[(2^i - 1) (len2 - 1) + 1\bigr] \\ & = 2 \times \bigl[ (2^K - 1) (len2 - 1) + 1 \bigr] + (len2 - 1) \sum_{i=1}^{K-1} (n_i - n_{i+1}) (2^i - 1) + n_1 - n_K. \end{align*} If $K = 1$, or equivalently $len1$ is 3 or 4, then $S = 2 \times len2$. Otherwise, we can bound $n_i - n_{i+1}$ from above as follows. For any non-negative integer $x$, \begin{equation*} \ceil{x / 2^i} - \ceil{x / 2^{i+1}} \leq x/2^i - x/2^{i+1} = x / 2^{i+1}. \end{equation*} Thus, \begin{align*} S & \leq 2 \times \bigl[ (2^K - 1) (len2 - 1) + 1 \bigr] + (len2 - 1) \times len1 \times \sum_{i=1}^{K-1} (1/2 - 1/2^{i+1}) \\ & \leq 2 \times \bigl[ (2^K - 1) (len2 - 1) + 1 \bigr] + (len2 - 1) \times len1 \times (K/2 + 1). \end{align*} */ void _fmpz_poly_compose_divconquer(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong i, j, k, n; slong *hlen, alloc, powlen; fmpz *v, **h, *pow, *temp; if (len1 <= 2 || len2 <= 1) { if (len1 == 1) fmpz_set(res, poly1); else if (len2 == 1) _fmpz_poly_evaluate_fmpz(res, poly1, len1, poly2); else /* len1 == 2 */ _fmpz_poly_compose_horner(res, poly1, len1, poly2, len2); return; } /* Initialisation */ hlen = (slong *) flint_malloc(((len1 + 1) / 2) * sizeof(slong)); k = FLINT_CLOG2(len1) - 1; hlen[0] = hlen[1] = ((1 << k) - 1) * (len2 - 1) + 1; for (i = k - 1; i > 0; i--) { slong hi = (len1 + (1 << i) - 1) / (1 << i); for (n = (hi + 1) / 2; n < hi; n++) hlen[n] = ((1 << i) - 1) * (len2 - 1) + 1; } powlen = (1 << k) * (len2 - 1) + 1; alloc = 0; for (i = 0; i < (len1 + 1) / 2; i++) alloc += hlen[i]; v = _fmpz_vec_init(alloc + 2 * powlen); h = (fmpz **) flint_malloc(((len1 + 1) / 2) * sizeof(fmpz *)); h[0] = v; for (i = 0; i < (len1 - 1) / 2; i++) { h[i + 1] = h[i] + hlen[i]; hlen[i] = 0; } hlen[(len1 - 1) / 2] = 0; pow = v + alloc; temp = pow + powlen; /* Let's start the actual work */ for (i = 0, j = 0; i < len1 / 2; i++, j += 2) { if (poly1[j + 1] != WORD(0)) { _fmpz_vec_scalar_mul_fmpz(h[i], poly2, len2, poly1 + j + 1); fmpz_add(h[i], h[i], poly1 + j); hlen[i] = len2; } else if (poly1[j] != WORD(0)) { fmpz_set(h[i], poly1 + j); hlen[i] = 1; } } if ((len1 & WORD(1))) { if (poly1[j] != WORD(0)) { fmpz_set(h[i], poly1 + j); hlen[i] = 1; } } _fmpz_poly_sqr(pow, poly2, len2); powlen = 2 * len2 - 1; for (n = (len1 + 1) / 2; n > 2; n = (n + 1) / 2) { if (hlen[1] > 0) { slong templen = powlen + hlen[1] - 1; _fmpz_poly_mul(temp, pow, powlen, h[1], hlen[1]); _fmpz_poly_add(h[0], temp, templen, h[0], hlen[0]); hlen[0] = FLINT_MAX(hlen[0], templen); } for (i = 1; i < n / 2; i++) { if (hlen[2*i + 1] > 0) { _fmpz_poly_mul(h[i], pow, powlen, h[2*i + 1], hlen[2*i + 1]); hlen[i] = hlen[2*i + 1] + powlen - 1; } else hlen[i] = 0; _fmpz_poly_add(h[i], h[i], hlen[i], h[2*i], hlen[2*i]); hlen[i] = FLINT_MAX(hlen[i], hlen[2*i]); } if ((n & WORD(1))) { _fmpz_vec_set(h[i], h[2*i], hlen[2*i]); hlen[i] = hlen[2*i]; } _fmpz_poly_sqr(temp, pow, powlen); powlen += powlen - 1; { fmpz * t = pow; pow = temp; temp = t; } } _fmpz_poly_mul(res, pow, powlen, h[1], hlen[1]); _fmpz_vec_add(res, res, h[0], hlen[0]); _fmpz_vec_clear(v, alloc + 2 * powlen); flint_free(h); flint_free(hlen); } void fmpz_poly_compose_divconquer(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; slong lenr; if (len1 == 0) { fmpz_poly_zero(res); return; } if (len1 == 1 || len2 == 0) { fmpz_poly_set_fmpz(res, poly1->coeffs); return; } lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { fmpz_poly_fit_length(res, lenr); _fmpz_poly_compose_divconquer(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, lenr); _fmpz_poly_normalise(res); } else { fmpz_poly_t t; fmpz_poly_init2(t, lenr); _fmpz_poly_compose_divconquer(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(t, lenr); _fmpz_poly_normalise(t); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } flint-3.1.3/src/fmpz_poly/compose_horner.c000066400000000000000000000046141461254215100206340ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_compose_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if (len1 == 1) { fmpz_set(res, poly1); } else { const slong alloc = (len1 - 1) * (len2 - 1) + 1; slong i = len1 - 1, lenr; fmpz * t = _fmpz_vec_init(alloc); /* Perform the first two steps as one, "res = a(m) * poly2 + a(m-1)". */ { lenr = len2; _fmpz_vec_scalar_mul_fmpz(res, poly2, len2, poly1 + i); i--; fmpz_add(res, res, poly1 + i); } while (i--) { _fmpz_poly_mul(t, res, lenr, poly2, len2); lenr += len2 - 1; _fmpz_poly_add(res, t, lenr, poly1 + i, 1); } _fmpz_vec_clear(t, alloc); } } void fmpz_poly_compose_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { fmpz_poly_zero(res); } else if (len1 == 1 || len2 == 0) { fmpz_poly_set_fmpz(res, poly1->coeffs); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if ((res != poly1) && (res != poly2)) { fmpz_poly_fit_length(res, lenr); _fmpz_poly_compose_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, lenr); } else { fmpz_poly_t t; fmpz_poly_init2(t, lenr); _fmpz_poly_compose_horner(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(t, lenr); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } _fmpz_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/compose_series.c000066400000000000000000000164031461254215100206300ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_poly.h" void _fmpz_poly_compose_series(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { if (len1 <= 10) _fmpz_poly_compose_series_horner(res, poly1, len1, poly2, len2, n); else _fmpz_poly_compose_series_brent_kung(res, poly1, len1, poly2, len2, n); } void fmpz_poly_compose_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !fmpz_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "(fmpz_poly_compose_series): " "Inner polynomial must have zero constant term.\n"); } if (len1 == 0 || n == 0) { fmpz_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { fmpz_poly_set_fmpz(res, poly1->coeffs); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { fmpz_poly_fit_length(res, lenr); _fmpz_poly_compose_series(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr); _fmpz_poly_set_length(res, lenr); _fmpz_poly_normalise(res); } else { fmpz_poly_t t; fmpz_poly_init2(t, lenr); _fmpz_poly_compose_series(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr); _fmpz_poly_set_length(t, lenr); _fmpz_poly_normalise(t); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } void _fmpz_poly_compose_series_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { fmpz_mat_t A, B, C; fmpz *t, *h; slong i, m; if (n == 1) { fmpz_set(res, poly1); return; } m = n_sqrt(n) + 1; fmpz_mat_init(A, m, n); fmpz_mat_init(B, m, m); fmpz_mat_init(C, m, n); h = _fmpz_vec_init(n); t = _fmpz_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _fmpz_vec_set(B->rows[i], poly1 + i*m, m); _fmpz_vec_set(B->rows[i], poly1 + i*m, len1 % m); /* Set rows of A to powers of poly2 */ fmpz_one(A->rows[0]); _fmpz_vec_set(A->rows[1], poly2, len2); for (i = 2; i < m; i++) _fmpz_poly_mullow(A->rows[i], A->rows[i-1], n, poly2, len2, n); fmpz_mat_mul(C, B, A); /* Evaluate block composition using the Horner scheme */ _fmpz_vec_set(res, C->rows[m - 1], n); _fmpz_poly_mullow(h, A->rows[m - 1], n, poly2, len2, n); for (i = m - 2; i >= 0; i--) { _fmpz_poly_mullow(t, res, n, h, n, n); _fmpz_poly_add(res, t, n, C->rows[i], n); } _fmpz_vec_clear(h, n); _fmpz_vec_clear(t, n); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } void fmpz_poly_compose_series_brent_kung(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !fmpz_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "(fmpz_poly_compose_series_brent_kung): " "Inner polynomial must have zero constant term.\n"); } if (len1 == 0 || n == 0) { fmpz_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { fmpz_poly_set_fmpz(res, poly1->coeffs); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { fmpz_poly_fit_length(res, lenr); _fmpz_poly_compose_series_brent_kung(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr); _fmpz_poly_set_length(res, lenr); _fmpz_poly_normalise(res); } else { fmpz_poly_t t; fmpz_poly_init2(t, lenr); _fmpz_poly_compose_series_brent_kung(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr); _fmpz_poly_set_length(t, lenr); _fmpz_poly_normalise(t); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } void _fmpz_poly_compose_series_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { if (n == 1) { fmpz_set(res, poly1); } else { slong i = len1 - 1; slong lenr; fmpz * t = _fmpz_vec_init(n); lenr = len2; _fmpz_vec_scalar_mul_fmpz(res, poly2, len2, poly1 + i); i--; fmpz_add(res, res, poly1 + i); while (i > 0) { i--; if (lenr + len2 - 1 < n) { _fmpz_poly_mul(t, res, lenr, poly2, len2); lenr = lenr + len2 - 1; } else { _fmpz_poly_mullow(t, res, lenr, poly2, len2, n); lenr = n; } _fmpz_poly_add(res, t, lenr, poly1 + i, 1); } _fmpz_vec_zero(res + lenr, n - lenr); _fmpz_vec_clear(t, n); } } void fmpz_poly_compose_series_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && !fmpz_is_zero(poly2->coeffs)) { flint_throw(FLINT_ERROR, "(fmpz_poly_compose_series_horner): " "Inner polynomial must have zero constant term.\n"); } if (len1 == 0 || n == 0) { fmpz_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { fmpz_poly_set_fmpz(res, poly1->coeffs); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { fmpz_poly_fit_length(res, lenr); _fmpz_poly_compose_series_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr); _fmpz_poly_set_length(res, lenr); _fmpz_poly_normalise(res); } else { fmpz_poly_t t; fmpz_poly_init2(t, lenr); _fmpz_poly_compose_series_horner(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr); _fmpz_poly_set_length(t, lenr); _fmpz_poly_normalise(t); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } flint-3.1.3/src/fmpz_poly/content.c000066400000000000000000000013771461254215100172670ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_content(fmpz_t res, const fmpz * poly, slong len) { fmpz_zero(res); while (len--) fmpz_gcd(res, res, poly + len); } void fmpz_poly_content(fmpz_t res, const fmpz_poly_t poly) { fmpz_t t; fmpz_init(t); _fmpz_poly_content(t, poly->coeffs, poly->length); fmpz_swap(res, t); fmpz_clear(t); } flint-3.1.3/src/fmpz_poly/cos_minpoly.c000066400000000000000000000171751461254215100201530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* todo: constructing from roots is sometimes faster (e.g. n = 3389) */ /* Use a lookup table for small n. We skip 53, 59 and 61, as the coefficients do not fit in 16 bits. */ #define MINPOLY_TAB_NUM 65 #define MINPOLY_TAB_MAX_LEN 24 static const char minpoly_len_tab[MINPOLY_TAB_NUM] = { 1, 2, 2, 2, 2, 3, 2, 4, 3, 4, 3, 6, 3, 7, 4, 5, 5, 9, 4, 10, 5, 7, 6, 12, 5, 11, 7, 10, 7, 15, 5, 16, 9, 11, 9, 13, 7, 19, 10, 13, 9, 21, 7, 22, 11, 13, 12, 24, 9, 22, 11, 17, 13, 27, 10, 21, 13, 19, 15, 30, 9, 31, 16, 19, 17 }; static const short minpoly_tab[MINPOLY_TAB_NUM][MINPOLY_TAB_MAX_LEN] = { {1}, {-2, 1}, {2, 1}, {1, 1}, {0, 1}, {-1, 1, 1}, {-1, 1}, {-1, -2, 1, 1}, {-2, 0, 1}, {1, -3, 0, 1}, {-1, -1, 1}, {1, 3, -3, -4, 1, 1}, {-3, 0, 1}, {-1, 3, 6, -4, -5, 1, 1}, {1, -2, -1, 1}, {1, 4, -4, -1, 1}, {2, 0, -4, 0, 1}, {1, -4, -10, 10, 15, -6, -7, 1, 1}, {-1, -3, 0, 1}, {1, 5, -10, -20, 15, 21, -7, -8, 1, 1}, {5, 0, -5, 0, 1}, {1, -8, 8, 6, -6, -1, 1}, {-1, 3, 3, -4, -1, 1}, {-1, -6, 15, 35, -35, -56, 28, 36, -9, -10, 1, 1}, {1, 0, -4, 0, 1}, {-1, 5, 25, -5, -50, 1, 35, 0, -10, 0, 1}, {-1, -3, 6, 4, -5, -1, 1}, {1, 9, 0, -30, 0, 27, 0, -9, 0, 1}, {-7, 0, 14, 0, -7, 0, 1}, {-1, 7, 28, -56, -126, 126, 210, -120, -165, 55, 66, -12, -13, 1, 1}, {1, -4, -4, 1, 1}, {-1, -8, 28, 84, -126, -252, 210, 330, -165, -220, 66, 78, -13, -14, 1, 1}, {2, 0, -16, 0, 20, 0, -8, 0, 1}, {1, -12, 12, 43, -43, -34, 34, 10, -10, -1, 1}, {1, 4, -10, -10, 15, 6, -7, -1, 1}, {1, 8, -40, -46, 110, 71, -113, -43, 54, 11, -12, -1, 1}, {-3, 0, 9, 0, -6, 0, 1}, {-1, 9, 45, -120, -330, 462, 924, -792, -1287, 715, 1001, -364, -455, 105, 120, -16, -17, 1, 1}, {-1, 5, 10, -20, -15, 21, 7, -8, -1, 1}, {1, 12, -12, -79, 79, 103, -103, -53, 53, 12, -12, -1, 1}, {1, 0, -12, 0, 19, 0, -8, 0, 1}, {1, -10, -55, 165, 495, -792, -1716, 1716, 3003, -2002, -3003, 1365, 1820, -560, -680, 136, 153, -18, -19, 1, 1}, {1, 8, 8, -6, -6, 1, 1}, {1, 11, -55, -220, 495, 1287, -1716, -3432, 3003, 5005, -3003, -4368, 1820, 2380, -680, -816, 153, 171, -19, -20, 1, 1}, {-11, 0, 55, 0, -77, 0, 44, 0, -11, 0, 1}, {1, -12, -36, 31, 105, -27, -112, 9, 54, -1, -12, 0, 1}, {1, -6, -15, 35, 35, -56, -28, 36, 9, -10, -1, 1}, {-1, -12, 66, 286, -715, -2002, 3003, 6435, -6435, -11440, 8008, 12376, -6188, -8568, 3060, 3876, -969, -1140, 190, 210, -21, -22, 1, 1}, {1, 0, -16, 0, 20, 0, -8, 0, 1}, {-1, 14, 49, -371, -196, 2072, 294, -5147, -210, 7007, 77, -5733, -14, 2940, 1, -952, 0, 189, 0, -21, 0, 1}, {-1, -5, 25, 5, -50, -1, 35, 0, -10, 0, 1}, {1, 16, -16, -188, 188, 526, -526, -596, 596, 339, -339, -103, 103, 16, -16, -1, 1}, {13, 0, -91, 0, 182, 0, -156, 0, 65, 0, -13, 0, 1}, {0}, {-1, 9, 0, -30, 0, 27, 0, -9, 0, 1}, {1, 12, -108, -151, 951, 877, -2891, -2058, 4489, 2442, -4080, -1639, 2289, 650, -801, -151, 170, 19, -20, -1, 1}, {1, 0, -24, 0, 86, 0, -104, 0, 53, 0, -12, 0, 1}, {1, -20, 20, 265, -265, -989, 989, 1519, -1519, -1198, 1198, 531, -531, -134, 134, 18, -18, -1, 1}, {-1, -7, 28, 56, -126, -126, 210, 120, -165, -55, 66, 12, -13, -1, 1}, {0}, {1, 0, -8, 0, 14, 0, -7, 0, 1}, {0}, {1, -8, -28, 84, 126, -252, -210, 330, 165, -220, -66, 78, 13, -14, -1, 1}, {1, 24, 72, -170, -534, 405, 1385, -459, -1782, 276, 1287, -90, -546, 15, 135, -1, -18, 0, 1}, {2, 0, -64, 0, 336, 0, -672, 0, 660, 0, -352, 0, 104, 0, -16, 0, 1}, }; /* Recurrence for coefficients in rescaled Chebyshev polynomials */ #define CHEB_NEXT(y, x, m, k) \ fmpz_mul2_uiui(y, x, m - 2*k + 1, m - 2*k + 2); \ fmpz_divexact2_uiui(y, y, k, m - k); \ fmpz_neg(y, y); \ /* Computes the monic integer polynomial n odd: 2 (T(s+1,x/2) - T(s,x/2)), s = (n - 1) / 2 n even: 2 (T(s+1,x/2) - T(s-1,x/2)), s = n / 2 */ static void chebyshev_sum(fmpz * a, ulong n) { ulong s, k, m; if (n == 1) { fmpz_set_si(a, -2); fmpz_one(a + 1); return; } if (n == 2) { fmpz_set_si(a, -4); fmpz_zero(a + 1); fmpz_one(a + 2); return; } s = n / 2; m = s + 1; fmpz_one(a + m); for (k = 1; k <= m / 2; k++) { CHEB_NEXT(a + m - 2 * k, a + m - 2 * k + 2, m, k); } if (n % 2 == 1) { m = s; fmpz_set_si(a + m, -1); for (k = 1; k <= m / 2; k++) { CHEB_NEXT(a + m - 2 * k, a + m - 2 * k + 2, m, k); } } else { m = s - 1; /* Use the top coefficient as scratch space. */ for (k = 1; k <= m / 2; k++) { CHEB_NEXT(a + m + 2, a + m + 2, m, k); fmpz_sub(a + m - 2*k, a + m - 2*k, a + m + 2); } for (k = 1 - (m % 2); k < m + 2; k += 2) fmpz_zero(a + k); fmpz_sub_ui(a + m, a + m, 1); /* Set the top coefficient again. */ fmpz_one(a + m + 2); } } #define MUL_TMP(P, Plen, T, Tlen) \ fmpz * swap; \ if (Plen >= Tlen) \ _fmpz_poly_mul(U, P, Plen, T, Tlen); \ else \ _fmpz_poly_mul(U, T, Tlen, P, Plen); \ Plen = Plen + Tlen - 1; \ swap = P; P = U; U = swap; \ void _fmpz_poly_cos_minpoly(fmpz * f, ulong n) { fmpz *P, *Q, *T, *U; int *mu; ulong Pdeg, Qdeg; ulong Plen, Qlen, Tlen; ulong d; if (n < MINPOLY_TAB_NUM && minpoly_len_tab[n] <= MINPOLY_TAB_MAX_LEN) { for (d = 0; d < minpoly_len_tab[n]; d++) fmpz_set_si(f + d, minpoly_tab[n][d]); return; } /* Compute values of the Moebius function. We do this as a precomputation as it allows us to bound in advance the degrees of the numerator and denominator. */ mu = flint_calloc(n + 1, sizeof(int)); Pdeg = Qdeg = 0; for (d = 1; d <= n; d++) { if (n % d == 0) { mu[d] = n_moebius_mu(n / d); if (mu[d] == 1) Pdeg += (d / 2 + 1); else if (mu[d] == -1) Qdeg += (d / 2 + 1); } } /* We use two extra arrays as scratch space (note that Qdeg < Pdeg). */ P = _fmpz_vec_init(Pdeg + 1); Q = _fmpz_vec_init(Pdeg + 1); T = _fmpz_vec_init(Pdeg + 1); U = _fmpz_vec_init(Pdeg + 1); Plen = Qlen = 1; fmpz_one(P); fmpz_one(Q); for (d = 1; d <= n; d++) { if (n % d == 0 && mu[d] != 0) { chebyshev_sum(T, d); Tlen = d / 2 + 2; if (mu[d] > 0) { MUL_TMP(P, Plen, T, Tlen); } else { MUL_TMP(Q, Qlen, T, Tlen); } } } _fmpz_poly_divexact(f, P, Plen, Q, Qlen); _fmpz_vec_clear(P, Pdeg + 1); _fmpz_vec_clear(Q, Pdeg + 1); _fmpz_vec_clear(T, Pdeg + 1); _fmpz_vec_clear(U, Pdeg + 1); flint_free(mu); } void fmpz_poly_cos_minpoly(fmpz_poly_t f, ulong n) { slong len = (n < MINPOLY_TAB_NUM) ? minpoly_len_tab[n] : n_euler_phi(n) / 2 + 1; fmpz_poly_fit_length(f, len); _fmpz_poly_cos_minpoly(f->coeffs, n); _fmpz_poly_set_length(f, len); } flint-3.1.3/src/fmpz_poly/cyclotomic.c000066400000000000000000000072221461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_cyclotomic(fmpz * a, ulong n, mp_ptr factors, slong num_factors, ulong phi) { slong i, k; int small; ulong D; D = phi / 2; /* Phi_p(x) = 1 + x + x^2 + ... + x^{p-1} */ if (num_factors == 1) { for (i = 0; i <= D; i++) fmpz_one(a + i); return; } /* Phi_{2n}(x) = Phi_n(-x)*/ if (factors[0] == 2) { _fmpz_poly_cyclotomic(a, n / 2, factors + 1, num_factors - 1, phi); for (i = 1; i <= D; i += 2) fmpz_neg(a + i, a + i); return; } fmpz_one(a); for (i = 1; i <= D; i++) fmpz_zero(a + i); /* Coefficients are guaranteed not to overflow an fmpz */ small = (num_factors == 2) || /* Always +1/0/-1*/ (n < 10163195) || /* At most 27 bits */ (FLINT_BITS == 64 && n < 169828113); /* At most 60 bits */ /* Iterate over all divisors of n */ for (k = 0; k < (WORD(1) << num_factors); k++) { int mu; ulong d; mu = (num_factors & 1) ? -1 : 1; d = WORD(1); for (i = 0; i < num_factors; i++) { if ((k >> i) & 1) { d *= factors[i]; mu = -mu; } } /* Multiply by (x^d - 1)^{\mu(n/d)} */ if (small) { if (mu == 1) for (i = D; i >= d; i--) a[i] -= a[i - d]; else for (i = d; i <= D; i++) a[i] += a[i - d]; } else { if (mu == 1) for (i = D; i >= d; i--) fmpz_sub(a + i, a + i, a + i - d); else for (i = d; i <= D; i++) fmpz_add(a + i, a + i, a + i - d); } } } void fmpz_poly_cyclotomic(fmpz_poly_t poly, ulong n) { n_factor_t factors; slong i, j; ulong s, phi; if (n <= 2) { if (n == 0) { fmpz_poly_one(poly); } else { fmpz_poly_fit_length(poly, 2); fmpz_set_si(poly->coeffs, (n == 1) ? -1 : 1); fmpz_set_si(poly->coeffs + 1, 1); _fmpz_poly_set_length(poly, 2); } return; } /* Write n = q * s where q is squarefree, compute the factors of q, and compute phi(s) which determines the degree of the polynomial. */ n_factor_init(&factors); n_factor(&factors, n, 1); s = phi = 1; for (i = 0; i < factors.num; i++) { phi *= factors.p[i] - 1; while (factors.exp[i] > 1) { s *= factors.p[i]; factors.exp[i]--; } } fmpz_poly_fit_length(poly, phi * s + 1); /* Evaluate lower half of Phi_s(x) */ _fmpz_poly_cyclotomic(poly->coeffs, n / s, factors.p, factors.num, phi); /* Palindromic extension */ for (i = 0; i < (phi + 1) / 2; i++) fmpz_set(poly->coeffs + phi - i, poly->coeffs + i); /* Stretch */ if (s != 1) { for (i = phi; i > 0; i--) { fmpz_set(poly->coeffs + i*s, poly->coeffs + i); for (j = 1; j < s; j++) fmpz_zero(poly->coeffs + i*s - j); } } _fmpz_poly_set_length(poly, phi * s + 1); } flint-3.1.3/src/fmpz_poly/deflate.c000066400000000000000000000017651461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_deflate(fmpz_poly_t result, const fmpz_poly_t input, ulong deflation) { slong res_length, i; if (deflation == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_deflate). Division by zero.\n"); } if (input->length <= 1 || deflation == 1) { fmpz_poly_set(result, input); return; } res_length = (input->length - 1) / deflation + 1; fmpz_poly_fit_length(result, res_length); for (i = 0; i < res_length; i++) fmpz_set(result->coeffs + i, input->coeffs + i*deflation); result->length = res_length; } flint-3.1.3/src/fmpz_poly/deflation.c000066400000000000000000000017751461254215100175640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" ulong _fmpz_poly_deflation(const fmpz* a, slong len) { ulong deflation; slong i, coeff; if (len <= 1) return len; coeff = 1; while (fmpz_is_zero(a + coeff)) coeff++; deflation = n_gcd(len - 1, coeff); while ((deflation > 1) && (coeff + deflation < len)) { for (i = 0; i < deflation - 1; i++) { coeff++; if (!fmpz_is_zero(a + coeff)) deflation = n_gcd(coeff, deflation); } if (i == deflation - 1) coeff++; } return deflation; } flint-3.1.3/src/fmpz_poly/derivative.c000066400000000000000000000017321461254215100177520ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2021, Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_derivative(fmpz * rpoly, const fmpz * poly, slong len) { slong i; for (i = 1; i < len; i++) fmpz_mul_ui(rpoly + (i - 1), poly + i, i); } void fmpz_poly_derivative(fmpz_poly_t res, const fmpz_poly_t poly) { const slong len = poly->length; if (len < 2) { fmpz_poly_zero(res); } else { fmpz_poly_fit_length(res, len - 1); _fmpz_poly_derivative(res->coeffs, poly->coeffs, len); _fmpz_poly_set_length(res, len - 1); } } flint-3.1.3/src/fmpz_poly/discriminant.c000066400000000000000000000020631461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_discriminant(fmpz_t res, const fmpz * poly, slong len) { fmpz * der = _fmpz_vec_init(len - 1); _fmpz_poly_derivative(der, poly, len); _fmpz_poly_resultant(res, poly, len, der, len - 1); if ((len & 3) == 0 || (len & 3) == 3) /* degree is not 0, 1 mod 4 */ fmpz_neg(res, res); if (!fmpz_is_one(poly + len - 1)) fmpz_divexact(res, res, poly + len - 1); _fmpz_vec_clear(der, len - 1); } void fmpz_poly_discriminant(fmpz_t res, const fmpz_poly_t poly) { slong len = poly->length; if (len <= 1) fmpz_zero(res); else _fmpz_poly_discriminant(res, poly->coeffs, len); } flint-3.1.3/src/fmpz_poly/div.c000066400000000000000000000027241461254215100163740ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int _fmpz_poly_div(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) { return _fmpz_poly_div_divconquer(Q, A, lenA, B, lenB, exact); } void fmpz_poly_div(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) { fmpz_poly_t tQ; fmpz *q; if (B->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_div). Division by zero.\n"); } if (A->length < B->length) { fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { fmpz_poly_init2(tQ, A->length - B->length + 1); q = tQ->coeffs; } else { fmpz_poly_fit_length(Q, A->length - B->length + 1); q = Q->coeffs; } _fmpz_poly_div(q, A->coeffs, A->length, B->coeffs, B->length, 0); if (Q == A || Q == B) { _fmpz_poly_set_length(tQ, A->length - B->length + 1); fmpz_poly_swap(tQ, Q); fmpz_poly_clear(tQ); } else _fmpz_poly_set_length(Q, A->length - B->length + 1); _fmpz_poly_normalise(Q); } flint-3.1.3/src/fmpz_poly/div_basecase.c000066400000000000000000000057751461254215100202330ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_div_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) { const fmpz * leadB = B + lenB - 1; slong B1, iQ = lenA - lenB; slong alloc; fmpz_t r; int res = 1; while (lenA >= lenB && fmpz_cmpabs(A + lenA - 1, leadB) < 0) { if (exact && !fmpz_is_zero(A + lenA - 1)) return 0; fmpz_zero(Q + iQ); iQ--; lenA--; } if (lenA < lenB) return 1; alloc = (R == NULL) ? lenA : 0; if (alloc) R = _fmpz_vec_init(alloc); if (R != A) _fmpz_vec_set(R + lenB - 1, A + lenB - 1, lenA - lenB + 1); B1 = lenB - 1; if (exact) fmpz_init(r); while (lenA >= lenB) { if (fmpz_cmpabs(R + lenA - 1, leadB) < 0) { if (exact && !fmpz_is_zero(R + lenA - 1)) { res = 0; goto cleanup; } fmpz_zero(Q + iQ); } else { if (exact) { fmpz_fdiv_qr(Q + iQ, r, R + lenA - 1, leadB); if (!fmpz_is_zero(r)) { res = 0; goto cleanup; } } else fmpz_fdiv_q(Q + iQ, R + lenA - 1, leadB); _fmpz_vec_scalar_submul_fmpz(R + lenA - B1 - 1, B, B1, Q + iQ); } if (B1 >= lenA - lenB + 1) { B++; B1--; } lenA--; iQ--; } cleanup: if (exact) fmpz_clear(r); if (alloc) _fmpz_vec_clear(R, alloc); return res; } void fmpz_poly_div_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenq; fmpz *q; if (B->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_div_basecase). Division by zero.\n"); } if (A->length < B->length) { fmpz_poly_zero(Q); return; } lenq = A->length - B->length + 1; if ((Q == A) || (Q == B)) q = _fmpz_vec_init(lenq); else { fmpz_poly_fit_length(Q, lenq); q = Q->coeffs; } _fmpz_poly_div_basecase(q, NULL, A->coeffs, A->length, B->coeffs, B->length, 0); if ((Q == A) || (Q == B)) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenq; Q->length = lenq; } else _fmpz_poly_set_length(Q, lenq); _fmpz_poly_normalise(Q); } flint-3.1.3/src/fmpz_poly/div_divconquer.c000066400000000000000000000074101461254215100206300ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" static int __fmpz_poly_div_divconquer(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) { int res; if (lenA < 2 * lenB - 1) { /* Convert unbalanced division into a 2 q1 - 1 by q1 division */ const slong q1 = lenA - lenB + 1; const slong q2 = lenB - q1; fmpz * temp = _fmpz_vec_init(2 * q1 - 1); res = _fmpz_poly_div_divconquer_recursive(Q, temp, A + q2, B + q2, q1, exact); _fmpz_vec_clear(temp, 2 * q1 - 1); } else /* lenA = 2 lenB - 1 */ { fmpz * temp = _fmpz_vec_init(lenA); res = _fmpz_poly_div_divconquer_recursive(Q, temp, A, B, lenB, exact); _fmpz_vec_clear(temp, lenA); } return res; } /* needed due to partial overlap */ static void _fmpz_vec_sub_dec(fmpz * a, const fmpz * b, const fmpz * c, slong n) { slong i; for (i = n - 1; i >= 0; i--) fmpz_sub(a + i, b + i, c + i); } int _fmpz_poly_div_divconquer(fmpz *Q, const fmpz *A, slong lenA, const fmpz *B, slong lenB, int exact) { if (lenA <= 2 * lenB - 1) { return __fmpz_poly_div_divconquer(Q, A, lenA, B, lenB, exact); } else /* lenA > 2 * lenB - 1 */ { fmpz *S, *T; slong shift, next, n = 2 * lenB - 1; int res = 1; S = _fmpz_vec_init(2 * n); T = S + n; /* To avoid copying all of A, we let S be a window of the remainder, taking up to n coefficients at a time */ shift = lenA - n; _fmpz_vec_set(S, A + shift, n); while (lenA >= n) { shift = lenA - n; if (!_fmpz_poly_divremlow_divconquer_recursive(Q + shift, T, S, B, lenB, exact)) { _fmpz_vec_clear(S, 2 * n); return 0; } next = FLINT_MIN(lenB, shift); _fmpz_vec_sub_dec(S + next, S, T, lenB - 1); _fmpz_vec_set(S, A + shift - next, next); lenA -= lenB; } if (lenA >= lenB) res = __fmpz_poly_div_divconquer(Q, S, lenA, B, lenB, exact); _fmpz_vec_clear(S, 2 * n); return res; } } void fmpz_poly_div_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) { const slong lenA = A->length; const slong lenB = B->length; fmpz_poly_t t; fmpz *q; if (lenB == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_div_divconquer). Division by zero.\n"); } if (lenA < lenB) { fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { fmpz_poly_init2(t, lenA - lenB + 1); q = t->coeffs; } else { fmpz_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } _fmpz_poly_div_divconquer(q, A->coeffs, lenA, B->coeffs, lenB, 0); if (Q == A || Q == B) { _fmpz_poly_set_length(t, lenA - lenB + 1); fmpz_poly_swap(t, Q); fmpz_poly_clear(t); } else _fmpz_poly_set_length(Q, lenA - lenB + 1); _fmpz_poly_normalise(Q); } flint-3.1.3/src/fmpz_poly/div_divconquer_recursive.c000066400000000000000000000053741461254215100227260ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #define FLINT_DIV_DIVCONQUER_CUTOFF 16 int _fmpz_poly_div_divconquer_recursive(fmpz * Q, fmpz * temp, const fmpz * A, const fmpz * B, slong lenB, int exact) { if (lenB <= FLINT_DIV_DIVCONQUER_CUTOFF) { return _fmpz_poly_div_basecase(Q, temp, A, 2 * lenB - 1, B, lenB, exact); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; fmpz * q0 = Q; fmpz * q1 = Q + n2; /* t is a vector of length lenB - 1, h points to the top n2 coeffs of t; r1 is vector of length lenB >= 2 n1 - 1 */ fmpz * t = temp; fmpz * h = temp + (n1 - 1); fmpz * r1 = temp + (lenB - 1); /* Set {q1, n1}, {r1, 2 n1 - 1} to the quotient and remainder of {A + 2 n2, 2 n1 - 1} divided by {B + n2, n1} */ if (!_fmpz_poly_divremlow_divconquer_recursive(q1, r1, A + 2 * n2, B + n2, n1, exact)) return 0; _fmpz_vec_sub(r1, A + 2 * n2, r1, n1 - 1); /* Set the top n2 coeffs of t to the top n2 coeffs of the product of {q1, n1} and {B, n2}; the bottom n1 - 1 coeffs may be arbitrary For sufficiently large polynomials, computing the full product using Kronecker segmentation is faster than computing the opposite short product via Karatsuba */ _fmpz_poly_mul(t, q1, n1, B, n2); /* If lenB is odd, set {h, n2} to {r1, n2} - {h, n2}, otherwise, to {A + lenB - 1, 1} + {x * r1, n2} - {h, n2} */ if (lenB & WORD(1)) { _fmpz_vec_sub(h, r1, h, n2); } else { _fmpz_vec_sub(h + 1, r1, h + 1, n2 - 1); fmpz_neg(h, h); fmpz_add(h, h, A + lenB - 1); } /* Set t to h shifted to the right by n2 - 1, and set q0 to the quotient of {t, 2 n2 - 1} and {B + n1, n2} Note the bottom n2 - 1 coefficients of t are irrelevant */ t += (lenB & WORD(1)); return _fmpz_poly_div_divconquer_recursive(q0, temp + lenB, t, B + n1, n2, exact); } } flint-3.1.3/src/fmpz_poly/div_preinv.c000066400000000000000000000044431461254215100177570ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_div_preinv(fmpz * Q, const fmpz * A, slong len1_in, const fmpz * B, const fmpz * B_inv, slong len2) { slong len1 = len1_in; slong n = len1 - len2 + 1; fmpz * A_rev; fmpz * a; if (n > len2) { a = _fmpz_vec_init(len1_in); _fmpz_vec_set(a, A, len1_in); do { slong start = n - len2; _fmpz_poly_divrem_preinv(Q + start, a + start, len1 - start, B, B_inv, len2); n -= len2; len1 -= len2; } while (n > len2); } else a = (fmpz *) A; A_rev = _fmpz_vec_init(len1); _fmpz_poly_reverse(A_rev, a, len1, len1); _fmpz_poly_mullow(Q, A_rev, len1, B_inv, len2, FLINT_MIN(len1 + len2 - 1, n)); if (len1 + len2 - 1 < n) _fmpz_vec_zero(Q + len1 + len2 - 1, n - (len1 + len2 - 1)); _fmpz_poly_reverse(Q, Q, n, n); _fmpz_vec_clear(A_rev, len1); if (a != A) _fmpz_vec_clear(a, len1_in); } void fmpz_poly_div_preinv(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv) { fmpz_poly_t tQ; fmpz *q; slong len1 = A->length, len2 = B_inv->length; slong qlen = len1 - len2 + 1; if (len1 < len2) { fmpz_poly_zero(Q); return; } if (Q == A || Q == B || Q == B_inv) { fmpz_poly_init2(tQ, qlen); q = tQ->coeffs; } else { fmpz_poly_fit_length(Q, qlen); q = Q->coeffs; } _fmpz_poly_div_preinv(q, A->coeffs, len1, B->coeffs, B_inv->coeffs, len2); if (Q == A || Q == B || Q == B_inv) { _fmpz_poly_set_length(tQ, qlen); fmpz_poly_swap(tQ, Q); fmpz_poly_clear(tQ); } else _fmpz_poly_set_length(Q, qlen); /* no need to normalise */ } flint-3.1.3/src/fmpz_poly/div_root.c000066400000000000000000000024101461254215100174270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_div_root(fmpz * Q, const fmpz * A, slong len, const fmpz_t c) { fmpz_t r, t; slong i; if (len < 2) return; fmpz_init(r); fmpz_init(t); fmpz_set(r, A + len - 1); for (i = len - 2; i > 0; i--) { fmpz_mul(t, r, c); fmpz_add(t, t, A + i); fmpz_swap(Q + i, r); fmpz_swap(r, t); } fmpz_swap(Q, r); fmpz_clear(r); fmpz_clear(t); } void fmpz_poly_div_root(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_t c) { slong len = A->length; if (len <= 1) { fmpz_poly_zero(Q); return; } if (fmpz_is_zero(c)) { fmpz_poly_shift_right(Q, A, 1); return; } fmpz_poly_fit_length(Q, len - 1); _fmpz_poly_div_root(Q->coeffs, A->coeffs, len, c); _fmpz_poly_set_length(Q, len - 1); } flint-3.1.3/src/fmpz_poly/div_series.c000066400000000000000000000036311461254215100177440ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Fredrik Johansson Copyright (C) 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n) { Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (n < 72 || Blen < 72 || Alen == 1) _fmpz_poly_div_series_basecase(Q, A, Alen, B, Blen, n); else if (fmpz_is_pm1(B + 0)) { fmpz * Binv = _fmpz_vec_init(n); _fmpz_poly_inv_series(Binv, B, Blen, n); _fmpz_poly_mullow(Q, Binv, n, A, Alen, n); _fmpz_vec_clear(Binv, n); } else _fmpz_poly_div_series_divconquer(Q, A, Alen, B, Blen, n); } void fmpz_poly_div_series(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n) { slong Alen = FLINT_MIN(A->length, n); slong Blen = FLINT_MIN(B->length, n); if (Blen == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_div_series). Division by zero.\n"); } if (Alen == 0) { fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_div_series(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, n); fmpz_poly_swap(Q, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(Q, n); _fmpz_poly_div_series(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, n); } _fmpz_poly_set_length(Q, n); _fmpz_poly_normalise(Q); } flint-3.1.3/src/fmpz_poly/div_series_basecase.c000066400000000000000000000162561461254215100216010ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014, 2021 Fredrik Johansson Copyright (C) 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" static void fmpz_divexact_checked(fmpz_t Q, const fmpz_t A, const fmpz_t B) { fmpz_t r; fmpz_init(r); fmpz_fdiv_qr(Q, r, A, B); if (!fmpz_is_zero(r)) { fmpz_clear(r); /* flint_throw */ flint_throw(FLINT_ERROR, "Not an exact division\n"); } /* no need to clear r */ } void _fmpz_poly_div_series_basecase(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n) { Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (Blen == 1) { if (fmpz_is_pm1(B + 0)) { if (fmpz_is_one(B + 0)) _fmpz_vec_set(Q, A, Alen); else _fmpz_vec_neg(Q, A, Alen); } else { slong i; for (i = 0; i < Alen; i++) fmpz_divexact_checked(Q + i, A + i, B); } _fmpz_vec_zero(Q + Alen, n - Alen); } else if (Alen == 1 && fmpz_is_pm1(B + 0)) { _fmpz_poly_inv_series_basecase(Q, B, Blen, n); if (!fmpz_is_one(A + 0)) _fmpz_vec_scalar_mul_fmpz(Q, Q, n, A + 0); } else { slong i, j, nsmall; char *Bbits; slong b, bits, Qbits; TMP_INIT; TMP_START; if (fmpz_is_pm1(B + 0)) { if (fmpz_is_one(B + 0)) fmpz_set(Q + 0, A + 0); else fmpz_neg(Q + 0, A + 0); } else { fmpz_divexact_checked(Q + 0, A + 0, B + 0); } /* Bbits[i] = max(bits(B[0]), ..., bits(B[i])), as long as coeffs are small */ Bbits = TMP_ALLOC(Blen); Bbits[0] = fmpz_bits(B + 0); /* Maximum bits of all Q coefficients encountered so far */ Qbits = fmpz_bits(Q + 0); /* We have small coefficients for i < nsmall */ for (nsmall = 0; nsmall < Blen; nsmall++) { b = B[nsmall]; if (COEFF_IS_MPZ(b)) break; b = FLINT_ABS(b); if (nsmall == 0 || (b >> Bbits[nsmall - 1]) != 0) Bbits[nsmall] = FLINT_BIT_COUNT(b); else Bbits[nsmall] = Bbits[nsmall - 1]; } for (i = 1; i < n; i++) { if (i >= nsmall || Qbits > SMALL_FMPZ_BITCOUNT_MAX || Bbits[i] > SMALL_FMPZ_BITCOUNT_MAX) { /* Can't use fast code. */ bits = WORD_MAX; } else { /* Can maybe use fast code; bound bits. */ b = FLINT_MIN(i, Blen - 1); bits = FLINT_BIT_COUNT(b); /* Bit size of product. */ bits += Bbits[i] + Qbits; /* Sign. */ bits += 1; } if (bits <= 3 * FLINT_BITS - 1) { if (bits <= FLINT_BITS - 1) { slong s, x, y; s = 0; for (j = 1; j < FLINT_MIN(i + 1, Blen); j++) { x = B[j]; y = Q[i - j]; s += x * y; } fmpz_set_si(Q + i, s); } else if (bits <= 2 * FLINT_BITS - 1) { mp_limb_t hi, lo, shi, slo; slong x, y; shi = slo = 0; for (j = 1; j < FLINT_MIN(i + 1, Blen); j++) { x = B[j]; y = Q[i - j]; smul_ppmm(hi, lo, x, y); add_ssaaaa(shi, slo, shi, slo, hi, lo); } fmpz_set_signed_uiui(Q + i, shi, slo); } else { mp_limb_t hi, lo, cy, shh, shi, slo; slong x, y; shh = shi = slo = 0; for (j = 1; j < FLINT_MIN(i + 1, Blen); j++) { x = B[j]; y = Q[i - j]; smul_ppmm(hi, lo, x, y); add_sssaaaaaa(cy, shi, slo, 0, shi, slo, 0, hi, lo); shh += (0 <= (slong) hi) ? cy : cy - 1; } fmpz_set_signed_uiuiui(Q + i, shh, shi, slo); } } else { slong l = FLINT_MIN(i, Blen - 1); /* todo: merge final subtraction */ _fmpz_vec_dot_general(Q + i, NULL, 0, B + 1, Q + i - l, 1, l); } if (i < Alen) { if (fmpz_is_pm1(B + 0)) { if (fmpz_is_one(B + 0)) fmpz_sub(Q + i, A + i, Q + i); else fmpz_sub(Q + i, Q + i, A + i); } else { fmpz_sub(Q + i, A + i, Q + i); fmpz_divexact_checked(Q + i, Q + i, B + 0); } } else { if (fmpz_is_pm1(B + 0)) { if (fmpz_is_one(B + 0)) fmpz_neg(Q + i, Q + i); } else { fmpz_neg(Q + i, Q + i); fmpz_divexact_checked(Q + i, Q + i, B + 0); } } if (COEFF_IS_MPZ(*(Q + i))) { /* Will no longer use fast code */ nsmall = i; } else { /* Update Qbits */ b = FLINT_ABS(*(Q + i)); b = FLINT_BIT_COUNT(b); Qbits = FLINT_MAX(Qbits, b); } } TMP_END; } } void fmpz_poly_div_series_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n) { slong Alen = FLINT_MIN(A->length, n); slong Blen = FLINT_MIN(B->length, n); if (Blen == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_div_series_basecase). Division by zero.\n"); } if (Alen == 0) { fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_div_series_basecase(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, n); fmpz_poly_swap(Q, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(Q, n); _fmpz_poly_div_series_basecase(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, n); } _fmpz_poly_set_length(Q, n); _fmpz_poly_normalise(Q); } flint-3.1.3/src/fmpz_poly/div_series_divconquer.c000066400000000000000000000037611461254215100222070ustar00rootroot00000000000000/* Copyright (C) 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_div_series_divconquer(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n) { fmpz * Arev = (fmpz *) _fmpz_vec_init(2*n - 1); fmpz * Brev = (fmpz *) _fmpz_vec_init(n); Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); _fmpz_poly_reverse(Arev, A, Alen, 2*n - 1); _fmpz_poly_reverse(Brev, B, Blen, n); if (!_fmpz_poly_div(Q, Arev, 2*n - 1, Brev, n, 1)) { _fmpz_vec_clear(Arev, 2*n - 1); /* flint_throw */ _fmpz_vec_clear(Brev, n); /* flint_throw */ flint_throw(FLINT_ERROR, "Not an exact division\n"); } _fmpz_poly_reverse(Q, Q, n, n); _fmpz_vec_clear(Arev, 2*n - 1); _fmpz_vec_clear(Brev, n); } void fmpz_poly_div_series_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n) { slong Alen = FLINT_MIN(A->length, n); slong Blen = FLINT_MIN(B->length, n); if (Blen == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_div_series_divconquer). Division by zero.\n"); } if (Alen == 0) { fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_div_series_divconquer(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, n); fmpz_poly_swap(Q, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(Q, n); _fmpz_poly_div_series_divconquer(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, n); } _fmpz_poly_set_length(Q, n); _fmpz_poly_normalise(Q); } flint-3.1.3/src/fmpz_poly/divexact.c000066400000000000000000000056301461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "gr.h" #include "gr_poly.h" void _fmpz_poly_divexact(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB) { slong lenQ = lenA - lenB + 1; if (lenQ == 1) { fmpz_divexact(Q, A + lenA - 1, B + lenB - 1); } else if (lenB == 1) { if (fmpz_is_pm1(B)) _fmpz_vec_scalar_mul_fmpz(Q, A, lenA, B); else _fmpz_vec_scalar_divexact_fmpz(Q, A, lenA, B); } else if (lenQ <= 100 || lenB <= 16) { gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); GR_MUST_SUCCEED(_gr_poly_divexact_basecase_bidirectional(Q, A, lenA, B, lenB, ctx)); } else { /* todo: the true cutoffs are sometimes higher, especially with unbalanced operands, possibly because divconquer division needs tuning */ slong A_bits, B_bits, B_cutoff, Q_cutoff; gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); A_bits = _fmpz_vec_max_bits(A, lenQ); B_bits = _fmpz_vec_max_bits(B, FLINT_MIN(lenB, lenQ)); A_bits = FLINT_ABS(A_bits); B_bits = FLINT_ABS(B_bits); B_cutoff = (B_bits > 3000) ? 20 : 60; Q_cutoff = (A_bits > 1000) ? 100 : 200; if (A_bits >= 100 * B_bits) { Q_cutoff *= 2; B_cutoff *= 2; } if (lenQ <= Q_cutoff || lenB <= B_cutoff) GR_MUST_SUCCEED(_gr_poly_divexact_basecase_bidirectional(Q, A, lenA, B, lenB, ctx)); else _fmpz_poly_div(Q, A, lenA, B, lenB, 0); } } void fmpz_poly_divexact(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B) { fmpz_poly_t T; slong lenA = A->length; slong lenB = B->length; slong lenQ = lenA - lenB + 1; if (lenB == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_divexact). Division by zero.\n"); } if (lenA < lenB) { fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { fmpz_poly_init2(T, lenQ); _fmpz_poly_divexact(T->coeffs, A->coeffs, lenA, B->coeffs, lenB); _fmpz_poly_set_length(T, lenQ); fmpz_poly_swap(T, Q); fmpz_poly_clear(T); } else { fmpz_poly_fit_length(Q, lenQ); _fmpz_poly_divexact(Q->coeffs, A->coeffs, lenA, B->coeffs, lenB); _fmpz_poly_set_length(Q, lenQ); } /* should not be needed, but produce something normalised in case this was called with invalid input */ _fmpz_poly_normalise(Q); } flint-3.1.3/src/fmpz_poly/divhigh_smodp.c000066400000000000000000000027511461254215100204360ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_divhigh_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n) { fmpz_t d, cinv; slong i = 0, k, start = 0, len_g = g->length; fmpz_poly_t tf; fmpz_init(d); fmpz_init(cinv); fmpz_poly_init2(tf, f->length); fmpz_poly_set(tf, f); fmpz_gcdinv(d, cinv, g->coeffs + len_g - 1, p); if (!fmpz_is_one(d)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_divhigh_smodp). Impossible inverse.\n"); } for (k = n - 1, i = f->length - len_g; k >= 0; i--, k--) { if (i < f->length - n) start++; fmpz_mul(res + k, tf->coeffs + i + len_g - 1, cinv); fmpz_smod(res + k, res + k, p); _fmpz_vec_scalar_submul_fmpz(tf->coeffs + i + start, g->coeffs + start, len_g - start, res + k); _fmpz_vec_scalar_smod_fmpz(tf->coeffs + i + start, tf->coeffs + i + start, len_g - start, p); } fmpz_poly_clear(tf); fmpz_clear(cinv); fmpz_clear(d); } flint-3.1.3/src/fmpz_poly/divides.c000066400000000000000000000046321461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_divides(fmpz * q, const fmpz * a, slong len1, const fmpz * b, slong len2) { fmpz * r; FLINT_ASSERT(len1 >= len2); FLINT_ASSERT(len2 > 0); if (!fmpz_divisible(a + 0, b + 0)) return 0; /* heuristic test: see if polys evaluated at 1 divide */ if (len1 > 1) { slong i; fmpz_t asum, bsum; int divisible = 0; fmpz_init(asum); fmpz_init(bsum); for (i = 0; i < len1; i++) fmpz_add(asum, asum, a + i); for (i = 0; i < len2; i++) fmpz_add(bsum, bsum, b + i); divisible = fmpz_divisible(asum, bsum); fmpz_clear(asum); fmpz_clear(bsum); if (!divisible) return 0; } r = _fmpz_vec_init(len1); if (!_fmpz_poly_divrem(q, r, a, len1, b, len2, 1)) { _fmpz_vec_clear(r, len1); return 0; } FMPZ_VEC_NORM(r, len1); _fmpz_vec_clear(r, len1); return (len1 == 0); } int fmpz_poly_divides(fmpz_poly_t q, const fmpz_poly_t a, const fmpz_poly_t b) { if (fmpz_poly_is_zero(b)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_divides). Division by zero.\n"); } if (fmpz_poly_is_zero(a)) { fmpz_poly_zero(q); return 1; } if (a->length < b->length) { return 0; } { const slong lenQ = a->length - b->length + 1; int res; if (q == a || q == b) { fmpz_poly_t t; fmpz_poly_init2(t, lenQ); res = _fmpz_poly_divides(t->coeffs, a->coeffs, a->length, b->coeffs, b->length); _fmpz_poly_set_length(t, lenQ); _fmpz_poly_normalise(t); fmpz_poly_swap(q, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(q, lenQ); res = _fmpz_poly_divides(q->coeffs, a->coeffs, a->length, b->coeffs, b->length); _fmpz_poly_set_length(q, lenQ); _fmpz_poly_normalise(q); } return res; } } flint-3.1.3/src/fmpz_poly/divlow_smodp.c000066400000000000000000000032461461254215100203200ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_divlow_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n) { fmpz_t d, cinv; slong i = 0, k, zeroes; fmpz_poly_t tf; fmpz_init(d); fmpz_init(cinv); while (fmpz_is_zero(g->coeffs + i)) i++; zeroes = i; fmpz_poly_init2(tf, n + zeroes); fmpz_poly_set(tf, f); if (fmpz_sgn(g->coeffs + zeroes) >= 0) fmpz_gcdinv(d, cinv, g->coeffs + zeroes, p); else { fmpz_t temp; fmpz_init(temp); fmpz_add(temp, g->coeffs + zeroes, p); fmpz_gcdinv(d, cinv, temp, p); fmpz_clear(temp); } if (!fmpz_is_one(d)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_divlow_smodp). Impossible inverse.\n"); } for (k = 0; k < n; i++, k++) { fmpz_mul(res + k, tf->coeffs + i, cinv); fmpz_smod(res + k, res + k, p); _fmpz_vec_scalar_submul_fmpz(tf->coeffs + i, g->coeffs + zeroes, FLINT_MIN(g->length - zeroes, n - k), res + k); _fmpz_vec_scalar_smod_fmpz(tf->coeffs + i, tf->coeffs + i, FLINT_MIN(g->length - zeroes, n - k), p); } fmpz_poly_clear(tf); fmpz_clear(cinv); fmpz_clear(d); } flint-3.1.3/src/fmpz_poly/divrem.c000066400000000000000000000041121461254215100170710ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) { int res; if (lenB < 6) res = _fmpz_poly_divrem_basecase(Q, R, A, lenA, B, lenB, exact); else res = _fmpz_poly_divrem_divconquer(Q, R, A, lenA, B, lenB, exact); return res; } void fmpz_poly_divrem(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) { const slong lenA = A->length, lenB = B->length; fmpz *q, *r; if (lenB == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_divrem). Division by zero.\n"); } if (lenA < lenB) { fmpz_poly_set(R, A); fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { q = _fmpz_vec_init(lenA - lenB + 1); } else { fmpz_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } if (R == A || R == B) { r = _fmpz_vec_init(lenA); } else { fmpz_poly_fit_length(R, lenA); r = R->coeffs; } _fmpz_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, 0); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenA - lenB + 1; Q->length = lenA - lenB + 1; } else { _fmpz_poly_set_length(Q, lenA - lenB + 1); } if (R == A || R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenA; R->length = lenA; } else { _fmpz_poly_set_length(R, lenA); } _fmpz_poly_normalise(Q); _fmpz_poly_normalise(R); } flint-3.1.3/src/fmpz_poly/divrem_basecase.c000066400000000000000000000057301461254215100207260ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) { const fmpz * leadB = B + (lenB - 1); slong iQ, iR; fmpz_t r; if (exact) fmpz_init(r); if (R != A) _fmpz_vec_set(R, A, lenA); for (iQ = lenA - lenB, iR = lenA - 1; iQ >= 0; iQ--, iR--) { if (fmpz_cmpabs(R + iR, leadB) < 0) { if (exact && !fmpz_is_zero(R + iR)) { fmpz_clear(r); return 0; } fmpz_zero(Q + iQ); } else { if (exact) { fmpz_fdiv_qr(Q + iQ, r, R + iR, leadB); if (!fmpz_is_zero(r)) { fmpz_clear(r); return 0; } } else fmpz_fdiv_q(Q + iQ, R + iR, leadB); _fmpz_vec_scalar_submul_fmpz(R + iQ, B, lenB, Q + iQ); } } if (exact) fmpz_clear(r); return 1; } void fmpz_poly_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenq, lenr; fmpz *q, *r; if (B->length == 0) { flint_throw(FLINT_ERROR, "(fmpz_poly_divrem_basecase). Division by zero.\n"); } if (Q == R) { flint_throw(FLINT_ERROR, "(fmpz_poly_divrem_basecase): Output arguments Q and R may not be aliased.\n"); } if (A->length < B->length) { fmpz_poly_set(R, A); fmpz_poly_zero(Q); return; } lenq = A->length - B->length + 1; lenr = A->length; if (Q == A || Q == B) q = _fmpz_vec_init(lenq); else { fmpz_poly_fit_length(Q, lenq); q = Q->coeffs; } if (R == B) r = _fmpz_vec_init(lenr); else { fmpz_poly_fit_length(R, lenr); r = R->coeffs; } _fmpz_poly_divrem_basecase(q, r, A->coeffs, A->length, B->coeffs, B->length, 0); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenq; Q->length = lenq; } else _fmpz_poly_set_length(Q, lenq); if (R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenr; R->length = lenr; } else _fmpz_poly_set_length(R, lenr); _fmpz_poly_normalise(Q); _fmpz_poly_normalise(R); } flint-3.1.3/src/fmpz_poly/divrem_divconquer.c000066400000000000000000000113361461254215100213360ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" static int __fmpz_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact) { if (lenA < 2 * lenB - 1) { /* Convert unbalanced division into a 2 n1 - 1 by n1 division */ const slong n1 = lenA - lenB + 1; const slong n2 = lenB - n1; const fmpz * p1 = A + n2; const fmpz * d1 = B + n2; const fmpz * d2 = B; fmpz * W = _fmpz_vec_init((2 * n1 - 1) + lenB - 1); fmpz * d1q1 = R + n2; fmpz * d2q1 = W + (2 * n1 - 1); if (!_fmpz_poly_divrem_divconquer_recursive(Q, d1q1, W, p1, d1, n1, exact)) { _fmpz_vec_clear(W, (2 * n1 - 1) + lenB - 1); return 0; } /* Compute d2q1 = Q d2, of length lenB - 1 */ if (n1 >= n2) _fmpz_poly_mul(d2q1, Q, n1, d2, n2); else _fmpz_poly_mul(d2q1, d2, n2, Q, n1); /* Compute BQ = d1q1 * x^n1 + d2q1, of length lenB - 1; then compute R = A - BQ */ _fmpz_vec_swap(R, d2q1, n2); _fmpz_vec_add(R + n2, R + n2, d2q1 + n2, n1 - 1); _fmpz_vec_sub(R, A, R, lenA); _fmpz_vec_clear(W, (2 * n1 - 1) + lenB - 1); } else /* lenA = 2 * lenB - 1 */ { fmpz * W = _fmpz_vec_init(lenA); if (!_fmpz_poly_divrem_divconquer_recursive(Q, R, W, A, B, lenB, exact)) { _fmpz_vec_clear(W, lenA); return 0; } _fmpz_vec_sub(R, A, R, lenA); _fmpz_vec_clear(W, lenA); } return 1; } int _fmpz_poly_divrem_divconquer(fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, int exact) { if (lenA <= 2 * lenB - 1) { if (!__fmpz_poly_divrem_divconquer(Q, R, A, lenA, B, lenB, exact)) return 0; } else /* lenA > 2 * lenB - 1 */ { slong shift, n = 2 * lenB - 1; fmpz *QB, *W; _fmpz_vec_set(R, A, lenA); W = _fmpz_vec_init(2 * n); QB = W + n; while (lenA >= n) { shift = lenA - n; if (!_fmpz_poly_divrem_divconquer_recursive(Q + shift, QB, W, R + shift, B, lenB, exact)) { _fmpz_vec_clear(W, 2 * n); return 0; } _fmpz_vec_sub(R + shift, R + shift, QB, n); lenA -= lenB; } if (lenA >= lenB) { if (!__fmpz_poly_divrem_divconquer(Q, W, R, lenA, B, lenB, exact)) { _fmpz_vec_clear(W, 2 * n); return 0; } _fmpz_vec_swap(W, R, lenA); } _fmpz_vec_clear(W, 2 * n); } return 1; } void fmpz_poly_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) { const slong lenA = A->length; const slong lenB = B->length; fmpz_poly_t tQ, tR; fmpz *q, *r; if (lenB == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_divrem_divconquer). Division by zero.\n"); } if (lenA < lenB) { fmpz_poly_set(R, A); fmpz_poly_zero(Q); return; } if (Q == A || Q == B) { fmpz_poly_init2(tQ, lenA - lenB + 1); q = tQ->coeffs; } else { fmpz_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } if (R == A || R == B) { fmpz_poly_init2(tR, lenA); r = tR->coeffs; } else { fmpz_poly_fit_length(R, lenA); r = R->coeffs; } _fmpz_poly_divrem_divconquer(q, r, A->coeffs, lenA, B->coeffs, lenB, 0); if (Q == A || Q == B) { _fmpz_poly_set_length(tQ, lenA - lenB + 1); fmpz_poly_swap(tQ, Q); fmpz_poly_clear(tQ); } else _fmpz_poly_set_length(Q, lenA - lenB + 1); if (R == A || R == B) { _fmpz_poly_set_length(tR, lenA); fmpz_poly_swap(tR, R); fmpz_poly_clear(tR); } else _fmpz_poly_set_length(R, lenA); _fmpz_poly_normalise(Q); _fmpz_poly_normalise(R); } flint-3.1.3/src/fmpz_poly/divrem_divconquer_recursive.c000066400000000000000000000070471461254215100234310ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2019 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #define FLINT_DIVREM_DIVCONQUER_CUTOFF 16 int _fmpz_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, int exact) { if (lenB <= FLINT_DIVREM_DIVCONQUER_CUTOFF) { _fmpz_vec_zero(BQ, lenB - 1); _fmpz_vec_set(BQ + (lenB - 1), A + (lenB - 1), lenB); if (!_fmpz_poly_divrem_basecase(Q, BQ, BQ, 2 * lenB - 1, B, lenB, exact)) return 0; _fmpz_vec_neg(BQ, BQ, lenB - 1); _fmpz_vec_sub(BQ + (lenB - 1), A + (lenB - 1), BQ + (lenB - 1), lenB); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; fmpz * W1 = W; fmpz * W2 = W + lenB; const fmpz * p1 = A + 2 * n2; const fmpz * p2; const fmpz * d1 = B + n2; const fmpz * d2 = B; const fmpz * d3 = B + n1; const fmpz * d4 = B; fmpz * q1 = Q + n2; fmpz * q2 = Q; fmpz * dq1 = BQ + n2; fmpz * d1q1 = BQ + 2 * n2; fmpz *d2q1, *d3q2, *d4q2, *t; /* Set q1 to p1 div d1, a 2 n1 - 1 by n1 division so q1 ends up being of length n1; d1q1 = d1 q1 is of length 2 n1 - 1 */ if (!_fmpz_poly_divrem_divconquer_recursive(q1, d1q1, W1, p1, d1, n1, exact)) return 0; /* Compute d2q1 = d2 q1, of length lenB - 1 */ d2q1 = W1; _fmpz_poly_mul(d2q1, q1, n1, d2, n2); /* Compute dq1 = d1 q1 x^n2 + d2 q1, of length 2 n1 + n2 - 1 */ _fmpz_vec_swap(dq1, d2q1, n2); _fmpz_vec_add(dq1 + n2, dq1 + n2, d2q1 + n2, n1 - 1); /* Compute t = A/x^n2 - dq1, which has length 2 n1 + n2 - 1, but we are not interested in the top n1 coeffs as they will be zero, so this has effective length n1 + n2 - 1 For the following division, we want to set {p2, 2 n2 - 1} to the top 2 n2 - 1 coeffs of this Since the bottom n2 - 1 coeffs of p2 are irrelevant for the division, we in fact set {t, n2} to the relevant coeffs */ t = BQ; _fmpz_vec_sub(t, A + n2 + (n1 - 1), dq1 + (n1 - 1), n2); p2 = t - (n2 - 1); /* Compute q2 = t div d3, a 2 n2 - 1 by n2 division, so q2 will have length n2; let d3q2 = d3 q2, of length 2 n2 - 1 */ d3q2 = W1; if (!_fmpz_poly_divrem_divconquer_recursive(q2, d3q2, W2, p2, d3, n2, exact)) return 0; /* Compute d4q2 = d4 q2, of length n1 + n2 - 1 = lenB - 1 */ d4q2 = W2; _fmpz_poly_mul(d4q2, d4, n1, q2, n2); /* Compute dq2 = d3q2 x^n1 + d4q2, of length n1 + 2 n2 - 1 */ _fmpz_vec_swap(BQ, d4q2, n2); _fmpz_vec_add(BQ + n2, BQ + n2, d4q2 + n2, n1 - 1); _fmpz_vec_add(BQ + n1, BQ + n1, d3q2, 2 * n2 - 1); /* Note Q = q1 x^n2 + q2, and BQ = dq1 x^n2 + dq2 */ } return 1; } flint-3.1.3/src/fmpz_poly/divrem_preinv.c000066400000000000000000000045241461254215100204630ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_divrem_preinv(fmpz * Q, fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2) { slong n = len1 - len2 + 1; fmpz * P = _fmpz_vec_init(len2 - 1); _fmpz_poly_div_preinv(Q, A, len1, B, B_inv, len2); if (len2 - 1 > 0) { if (len2 - 1 > n) _fmpz_poly_mullow(P, B, len2 - 1, Q, n, len2 - 1); else _fmpz_poly_mullow(P, Q, n, B, len2 - 1, len2 - 1); } _fmpz_poly_sub(A, A, len2 - 1, P, len2 - 1); _fmpz_vec_clear(P, len2 - 1); } void fmpz_poly_divrem_preinv(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv) { fmpz_poly_t tQ, tR; fmpz *q, *r; slong len1 = A->length, len2 = B->length; slong qlen = len1 - len2 + 1; if (len1 < len2) { fmpz_poly_zero(Q); fmpz_poly_set(R, A); return; } if (Q == A || Q == B || Q == B_inv) { fmpz_poly_init2(tQ, qlen); q = tQ->coeffs; } else { fmpz_poly_fit_length(Q, qlen); q = Q->coeffs; } if (R == B || R == B_inv) { fmpz_poly_init2(tR, len1); r = tR->coeffs; } else { fmpz_poly_fit_length(R, len1); r = R->coeffs; } if (R == B || R == B_inv || R != A) _fmpz_vec_set(r, A->coeffs, A->length); _fmpz_poly_divrem_preinv(q, r, len1, B->coeffs, B_inv->coeffs, len2); if (Q == A || Q == B || Q == B_inv) { _fmpz_poly_set_length(tQ, qlen); fmpz_poly_swap(tQ, Q); fmpz_poly_clear(tQ); } else _fmpz_poly_set_length(Q, qlen); if (R == B || R == B_inv) { _fmpz_poly_set_length(tR, len2 - 1); fmpz_poly_swap(tR, R); fmpz_poly_clear(tR); } else _fmpz_poly_set_length(R, len2 - 1); /* no need to normalise Q */ _fmpz_poly_normalise(R); } flint-3.1.3/src/fmpz_poly/divremlow_divconquer_recursive.c000066400000000000000000000073511461254215100241510ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #define FLINT_DIVREMLOW_DIVCONQUER_CUTOFF 16 int _fmpz_poly_divremlow_divconquer_recursive(fmpz * Q, fmpz * QB, const fmpz * A, const fmpz * B, slong lenB, int exact) { if (lenB <= FLINT_DIVREMLOW_DIVCONQUER_CUTOFF) { if (!_fmpz_poly_divrem_basecase(Q, QB, A, 2 * lenB - 1, B, lenB, exact)) return 0; _fmpz_vec_sub(QB, A, QB, lenB - 1); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; const fmpz * p1 = A + 2 * n2; const fmpz * p2; const fmpz * d1 = B + n2; const fmpz * d2 = B; fmpz * q1 = Q + n2; fmpz * q2 = Q; /* Think of the top lenB coefficients of QB as temporary space; this code will not depend on {QB, lenB - 1} and W being adjacent */ fmpz * W = QB + (lenB - 1); fmpz *d1q1, *d2q1, *t, *d3q2, *d4q2; /* Set q1 to p1 div d1, a 2 n1 - 1 by n1 division, so q1 has length at most n1; {W, n1 - 1} is d1 * q1 is truncated to length n1 - 1 */ if (!_fmpz_poly_divremlow_divconquer_recursive(q1, W, p1, d1, n1, exact)) return 0; /* W is of length lenB, but we only care about the bottom n1 - 1 coeffs, which we push up by n2 + 1, to the very top; we do this manually here instead of via _fmpz_vec_swap() because the source and destination arrays overlap */ d1q1 = W + (n2 + 1); { slong i; for (i = 0; i < n1 - 1; i++) fmpz_swap(d1q1 + i, W + i); } /* Compute d2q1 = d2 * q1, of length at most lenB - 1; we'll need the top n2 coeffs for t and the bottom n1 - 1 coeffs for QB */ d2q1 = QB; _fmpz_poly_mul(d2q1, q1, n1, d2, n2); /* Compute {t - (n2 - 1), 2 n2 - 1} to be the top 2 n2 - 1 coeffs of A / x^n2 - (d1q1 x^n2 + d2q1). Note that actually the bottom n2 - 1 coeffs may be arbitrary */ t = W + n1; if (n1 == n2) fmpz_zero(t); _fmpz_vec_add(t, t, d2q1 + (n1 - 1), n2); _fmpz_vec_neg(t, t, n2); _fmpz_vec_add(t, t, A + (n1 + n2 - 1), n2); p2 = t - (n2 - 1); /* Move {QB, n1 - 1} into the bottom coefficients of W, so that we can use {QB, 2 n2 - 1} as space in the next division */ _fmpz_vec_swap(QB, W, n1 - 1); /* Compute q2 = t div {B + n1}, a 2 n2 - 1 by n2 division */ d3q2 = QB; if (!_fmpz_poly_divremlow_divconquer_recursive(q2, d3q2, p2, B + n1, n2, exact)) return 0; _fmpz_vec_swap(QB + n1, d3q2, n2 - 1); if (lenB & WORD(1)) fmpz_zero(QB + n2); _fmpz_vec_add(QB + n2, QB + n2, W, n1 - 1); /* Compute {d4q2, lenB - 1} as {B, n1} * {q2, n2}; then move the bottom n2 coeffs of this into {QB, n2}, and add the top n1 - 1 coeffs to {QB + n2, n1 - 1} */ d4q2 = W; _fmpz_poly_mul(d4q2, B, n1, q2, n2); _fmpz_vec_swap(QB, d4q2, n2); _fmpz_vec_add(QB + n2, QB + n2, d4q2 + n2, n1 - 1); } return 1; } flint-3.1.3/src/fmpz_poly/equal.c000066400000000000000000000020431461254215100167130ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" int fmpz_poly_equal(const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong i; if (poly1 == poly2) return 1; /* same polynomial */ if (poly1->length != poly2->length) return 0; /* check if lengths the same */ for (i = 0; i < poly1->length; i++) /* check if coefficients the same */ if (!fmpz_equal(poly1->coeffs + i, poly2->coeffs + i)) return 0; return 1; } int fmpz_poly_equal_fmpz(const fmpz_poly_t poly, const fmpz_t c) { return ((poly->length == 0) && fmpz_is_zero(c)) || ((poly->length == 1) && fmpz_equal(poly->coeffs, c)); } flint-3.1.3/src/fmpz_poly/equal_trunc.c000066400000000000000000000023241461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" int fmpz_poly_equal_trunc(const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { slong i, len1, len2; if (poly1 == poly2) return 1; /* same polynomial */ if (n < 0) n = 0; len1 = FLINT_MIN(poly1->length, n); len2 = FLINT_MIN(poly2->length, n); if (len1 < len2) { for (i = len1; i < len2; i++) { if (!fmpz_is_zero(poly2->coeffs + i)) return 0; } } else if (len2 < len1) { for (i = len2; i < len1; i++) { if (!fmpz_is_zero(poly1->coeffs + i)) return 0; } } for (i = 0; i < FLINT_MIN(len1, len2); i++) /* check if coefficients the same */ if (!fmpz_equal(poly1->coeffs + i, poly2->coeffs + i)) return 0; return 1; } flint-3.1.3/src/fmpz_poly/eta_qexp.c000066400000000000000000000125731461254215100174230ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" static void _eta_one(fmpz * c, slong N) { slong k, n; int s; _fmpz_vec_zero(c, N); /* P */ for (k = 0, n = 0, s = 1; n < N; n += 3 * k + 1, k++, s = -s) { c[n] = s; } /* Q */ for (k = 1, n = 2, s = -1; n < N; n += 3 * k + 2, k++, s = -s) { c[n] = s; } } void _eta_two(fmpz * c, slong N) { slong k1, n1, k2, n2; int s, t; _fmpz_vec_zero(c, N); /* P^2 */ for (k1 = 0, n1 = 0; 2 * n1 < N; n1 += 3 * k1 + 1, k1++) { c[2 * n1] += 1; } for (k1 = 0, n1 = 0; n1 < N; n1 += 3 * k1 + 1, k1++) { for (k2 = k1 + 1, n2 = n1 + 3 * k1 + 1, s = -2; n1 + n2 < N; n2 += 3 * k2 + 1, k2++, s = -s) { c[n1 + n2] += s; } } /* Q^2 */ for (k1 = 1, n1 = 2; 2 * n1 < N; n1 += 3 * k1 + 2, k1++) { c[2 * n1] += 1; } for (k1 = 1, n1 = 2; n1 < N; n1 += 3 * k1 + 2, k1++) { for (k2 = k1 + 1, n2 = n1 + 3 * k1 + 2, s = -2; n1 + n2 < N; n2 += 3 * k2 + 2, k2++, s = -s) { c[n1 + n2] += s; } } /* 2PQ */ for (k1 = 0, n1 = 0, s = 2; n1 < N; n1 += 3 * k1 + 1, k1++, s = -s) { for (k2 = 1, n2 = 2, t = -s; n1 + n2 < N; n2 += 3 * k2 + 2, k2++, t = -t) { c[n1 + n2] += t; } } } /* R */ static void _eta_three(fmpz * c, slong N) { slong k, n; _fmpz_vec_zero(c, N); for (k = 0, n = 0; n < N; n += k + 1, k++) c[n] = (k % 2) ? -(2 * k + 1) : (2 * k + 1); } /* (P + Q) * R */ static void _eta_four(fmpz * c, slong N) { slong k1, n1, k2, n2; _fmpz_vec_zero(c, N); /* P * R */ for (k1 = 0, n1 = 0; n1 < N; n1 += 3 * k1 + 1, k1++) { for (k2 = 0, n2 = 0; n1 + n2 < N; n2 += k2 + 1, k2++) { if ((k1 + k2) % 2) fmpz_sub_ui(c + n1 + n2, c + n1 + n2, 2 * k2 + 1); else fmpz_add_ui(c + n1 + n2, c + n1 + n2, 2 * k2 + 1); } } /* Q * R */ for (k1 = 1, n1 = 2; n1 < N; n1 += 3 * k1 + 2, k1++) { for (k2 = 0, n2 = 0; n1 + n2 < N; n2 += k2 + 1, k2++) { if ((k1 + k2) % 2) fmpz_sub_ui(c + n1 + n2, c + n1 + n2, 2 * k2 + 1); else fmpz_add_ui(c + n1 + n2, c + n1 + n2, 2 * k2 + 1); } } } static void _eta_six(fmpz * c, slong N) { slong k1, n1, k2, n2; fmpz_t tmp; _fmpz_vec_zero(c, N); fmpz_init(tmp); /* R^2 */ for (k1 = 0, n1 = 0; 2 * n1 < N; n1 += k1 + 1, k1++) { fmpz_set_ui(c + 2 * n1, 2 * k1 + 1); fmpz_mul_ui(c + 2 * n1, c + 2 * n1, 2 * k1 + 1); } for (k1 = 0, n1 = 0; n1 < N; n1 += k1 + 1, k1++) { fmpz_set_ui(tmp, 2 * (2 * k1 + 1)); for (k2 = k1 + 1, n2 = n1 + k1 + 1; n1 + n2 < N; n2 += k2 + 1, k2++) { if ((k1 + k2) % 2) fmpz_submul_ui(c + n1 + n2, tmp, 2 * k2 + 1); else fmpz_addmul_ui(c + n1 + n2, tmp, 2 * k2 + 1); } } fmpz_clear(tmp); } void _fmpz_poly_eta_qexp(fmpz * f, slong e, slong len) { if (e < 0) { fmpz * t = _fmpz_vec_init(len); _fmpz_poly_eta_qexp(t, -e, len); _fmpz_poly_inv_series(f, t, len, len); _fmpz_vec_clear(t, len); return; } else if (e == 0) { _fmpz_vec_zero(f, len); if (len > 0) fmpz_set_ui(f, 1); } else if (e == 1) { _eta_one(f, len); } else if (e == 2) { _eta_two(f, len); } else if (e == 3) { _eta_three(f, len); } else if (e == 4) { _eta_four(f, len); } else if (e == 6) { _eta_six(f, len); } else { fmpz *t; t = _fmpz_vec_init(len); if (e % 6 == 0) { _eta_six(t, len); e /= 6; } else if (e % 4 == 0) { _eta_four(t, len); e /= 4; } else if (e % 3 == 0) { _eta_three(t, len); e /= 3; } else if (e % 2 == 0 && 0) { _eta_two(t, len); e /= 2; } else { _eta_one(t, len); } if (e == 2) { _fmpz_poly_sqrlow(f, t, len, len); } else if (e == 4) { _fmpz_poly_sqrlow(f, t, len, len); _fmpz_poly_sqrlow(t, f, len, len); _fmpz_vec_swap(f, t, len); } else { _fmpz_poly_pow_trunc(f, t, e, len); } _fmpz_vec_clear(t, len); } } void fmpz_poly_eta_qexp(fmpz_poly_t f, slong e, slong n) { if (n < 1) { fmpz_poly_zero(f); } else if (e == 0 || n == 1) { fmpz_poly_one(f); } else { fmpz_poly_fit_length(f, n); _fmpz_poly_eta_qexp(f->coeffs, e, n); _fmpz_poly_set_length(f, n); _fmpz_poly_normalise(f); } } flint-3.1.3/src/fmpz_poly/eulerian_polynomial.c000066400000000000000000000060401461254215100216540ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Up to this order the coefficients fit inside small fmpz */ #define SMALL_BOUND (FLINT_BITS == 64 ? 20 : 12) static void _fmpz_vec_powers(fmpz * res, ulong n, slong len) { slong ix; if (len != 0) fmpz_set_ui(res + 0, n == 0); for (ix = 1; ix < len; ix += 2) { fmpz_set_ui(res + ix, ix); fmpz_pow_ui(res + ix, res + ix, n); } for (ix = 2; ix < len; ix += 2) fmpz_mul_2exp(res + ix, res + ix / 2, n); } /* Only valid for when 1 <= len <= n / 2 */ static void _fmpz_vec_binomials(fmpz * res, ulong n, slong len) { slong ix, jx; fmpz_one(res + 0); fmpz_set_ui(res + 1, n); for (ix = 2, jx = 1; ix < len; ix++, jx++) { fmpz_mul_ui(res + ix, res + jx, n - jx); fmpz_divexact_si(res + ix, res + ix, ix); } } void _fmpz_poly_eulerian_polynomial_series(fmpz * res, ulong n) { slong ix, m; fmpz * tmp; m = (n + 1) / 2; tmp = _fmpz_vec_init(2 * m + 1); _fmpz_vec_binomials(tmp, n + 1, m); for (ix = 1; ix < m; ix += 2) fmpz_neg(tmp + ix, tmp + ix); _fmpz_vec_powers(tmp + m, n, m + 1); _fmpz_poly_mullow(res, tmp, m, tmp + m + 1, m, m); _fmpz_vec_clear(tmp, 2 * m + 1); } void _fmpz_poly_eulerian_polynomial_rec(fmpz * res, ulong n) { slong ix, jx; fmpz_one(res); for (ix = 1; ix <= FLINT_MIN(n / 2, SMALL_BOUND / 2); ix++) _fmpz_demote(res + ix); for (ix = 3; ix <= n; ix++) { if (ix <= SMALL_BOUND) { if (ix & 1) res[ix / 2] = (ix + 1) * res[ix / 2 - 1]; for (jx = ix / 2 - 1; jx >= 1; jx--) res[jx] = (ix - jx) * res[jx - 1] + (jx + 1) * res[jx]; } else { if (ix & 1) fmpz_mul_ui(res + ix / 2, res + ix / 2 - 1, ix + 1); for (jx = ix / 2 - 1; jx >= 1; jx--) { fmpz_mul_ui(res + jx, res + jx, jx + 1); fmpz_addmul_ui(res + jx, res + (jx - 1), ix - jx); } } } } void _fmpz_poly_eulerian_polynomial(fmpz * res, ulong n) { slong ix; if (n < 32) _fmpz_poly_eulerian_polynomial_rec(res, n); else _fmpz_poly_eulerian_polynomial_series(res, n); for (ix = 0; ix < n / 2; ix++) fmpz_set(res + (n - ix - 1), res + ix); } void fmpz_poly_eulerian_polynomial(fmpz_poly_t poly, ulong n) { /* A_0, A_1 = 1 */ if (n <= 1) { fmpz_poly_one(poly); return; } fmpz_poly_fit_length(poly, n); _fmpz_poly_eulerian_polynomial(poly->coeffs, n); _fmpz_poly_set_length(poly, n); } flint-3.1.3/src/fmpz_poly/evaluate_divconquer_fmpq.c000066400000000000000000000070361461254215100227030ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" void _fmpz_poly_evaluate_divconquer_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * poly, slong len, const fmpz_t xnum, const fmpz_t xden) { slong c, h, i, k = 1; fmpz *ynum, *yden, *Tnum, *Tden, *tnum = rnum, *tden = rden, *unum, *uden; fmpz_t d; h = FLINT_BIT_COUNT(len - 1); /* 2^{h-1} < len <= 2^h */ ynum = _fmpz_vec_init(2 * h + 2); /* x^{2^0}, x^{2^1}, ..., x^{2^{h-1}} */ yden = _fmpz_vec_init(2 * h + 2); /* x^{2^0}, x^{2^1}, ..., x^{2^{h-1}} */ fmpz_init(d); Tnum = ynum + h; Tden = yden + h; unum = ynum + 2 * h + 1; uden = yden + 2 * h + 1; *ynum = *xnum; *yden = *xden; for (i = 1; i < h; i++) { fmpz_mul(ynum + i, ynum + (i - 1), ynum + (i - 1)); fmpz_mul(yden + i, yden + (i - 1), yden + (i - 1)); } for (i = 0; i < len - 1; ) { /* t = poly[i] + y[0] * poly[i+1] */ fmpz_mul(tnum, ynum + 0, poly + i + 1); fmpz_addmul(tnum, yden + 0, poly + i); fmpz_set(tden, yden + 0); i += 2; c = flint_ctz(i); for (k = 1; k < c; k++) { /* t = T[k] + y[k] * t */ fmpz_mul(unum, ynum + k, tnum); fmpz_mul(uden, yden + k, tden); fmpz_mul(tnum, unum, Tden + k); fmpz_addmul(tnum, uden, Tnum + k); fmpz_mul(tden, Tden + k, uden); } fmpz_swap(Tnum + k, tnum); fmpz_swap(Tden + k, tden); } if (len & WORD(1)) { fmpz_set(tnum, poly + (len - 1)); fmpz_one(tden); c = flint_ctz(len + 1); for (k = 1; k < c; k++) { fmpz_mul(unum, ynum + k, tnum); fmpz_mul(uden, yden + k, tden); fmpz_mul(tnum, unum, Tden + k); fmpz_addmul(tnum, uden, Tnum + k); fmpz_mul(tden, Tden + k, uden); } fmpz_swap(Tnum + k, tnum); fmpz_swap(Tden + k, tden); } fmpz_swap(tnum, Tnum + k); fmpz_swap(tden, Tden + k); for ( ; k < h; k++) { if ((len - 1) & (WORD(1) << k)) { fmpz_mul(unum, ynum + k, tnum); fmpz_mul(uden, yden + k, tden); fmpz_mul(tnum, unum, Tden + k); fmpz_addmul(tnum, uden, Tnum + k); fmpz_mul(tden, Tden + k, uden); } } fmpz_gcd(d, rnum, rden); fmpz_divexact(rnum, rnum, d); fmpz_divexact(rden, rden, d); *ynum = WORD(0); *yden = WORD(0); _fmpz_vec_clear(ynum, 2 * h + 2); _fmpz_vec_clear(yden, 2 * h + 2); fmpz_clear(d); } void fmpz_poly_evaluate_divconquer_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a) { if (fmpz_poly_is_zero(f)) { fmpq_zero(res); return; } if (res == a) { fmpq_t t; fmpq_init(t); fmpz_poly_evaluate_divconquer_fmpq(t, f, a); fmpq_swap(res, t); fmpq_clear(t); } else { _fmpz_poly_evaluate_divconquer_fmpq(fmpq_numref(res), fmpq_denref(res), f->coeffs, f->length, fmpq_numref(a), fmpq_denref(a)); } } flint-3.1.3/src/fmpz_poly/evaluate_divconquer_fmpz.c000066400000000000000000000043121461254215100227060ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz * poly, slong len, const fmpz_t x) { slong c, h, i, k = 1; fmpz *y, *T, *t = res, *u; h = FLINT_BIT_COUNT(len - 1); /* 2^{h-1} < len <= 2^h */ y = _fmpz_vec_init(2 * h + 2); /* x^{2^0}, x^{2^1}, ..., x^{2^{h-1}} */ T = y + h; u = y + 2 * h + 1; *y = *x; for (i = 1; i < h; i++) fmpz_mul(y + i, y + (i - 1), y + (i - 1)); for (i = 0; i < len - 1; ) { fmpz_mul(u, y + 0, poly + i + 1); fmpz_add(t, poly + i, u); i += 2; c = flint_ctz(i); for (k = 1; k < c; k++) { fmpz_mul(u, y + k, t); fmpz_add(t, T + k, u); } fmpz_swap(T + k, t); } if (len & WORD(1)) { fmpz_set(t, poly + (len - 1)); c = flint_ctz(len + 1); for (k = 1; k < c; k++) { fmpz_mul(u, y + k, t); fmpz_add(t, T + k, u); } fmpz_swap(T + k, t); } fmpz_swap(t, T + k); for ( ; k < h; k++) { if ((len - 1) & (WORD(1) << k)) { fmpz_mul(u, y + k, t); fmpz_add(t, T + k, u); } } *y = WORD(0); _fmpz_vec_clear(y, 2 * h + 2); } void fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz_poly_t poly, const fmpz_t a) { if (fmpz_poly_is_zero(poly)) { fmpz_zero(res); return; } if (res == a) { fmpz_t t; fmpz_init(t); _fmpz_poly_evaluate_divconquer_fmpz(t, poly->coeffs, poly->length, a); fmpz_swap(res, t); fmpz_clear(t); } else _fmpz_poly_evaluate_divconquer_fmpz(res, poly->coeffs, poly->length, a); } flint-3.1.3/src/fmpz_poly/evaluate_fmpq.c000066400000000000000000000023161461254215100204400ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpq.h" void _fmpz_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden) { if (len < 40 || fmpz_bits(aden) > 0.003 * len * len) _fmpz_poly_evaluate_horner_fmpq(rnum, rden, f, len, anum, aden); else _fmpz_poly_evaluate_divconquer_fmpq(rnum, rden, f, len, anum, aden); } void fmpz_poly_evaluate_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a) { if (res == a) { fmpq_t t; fmpq_init(t); fmpz_poly_evaluate_fmpq(t, f, a); fmpq_swap(res, t); fmpq_clear(t); } else { _fmpz_poly_evaluate_fmpq(fmpq_numref(res), fmpq_denref(res), f->coeffs, f->length, fmpq_numref(a), fmpq_denref(a)); } } flint-3.1.3/src/fmpz_poly/evaluate_fmpz.c000066400000000000000000000017501461254215100204520ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a) { if (len <= 50) _fmpz_poly_evaluate_horner_fmpz(res, f, len, a); else _fmpz_poly_evaluate_divconquer_fmpz(res, f, len, a); } void fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a) { if (res == a) { fmpz_t t; fmpz_init(t); _fmpz_poly_evaluate_fmpz(t, f->coeffs, f->length, a); fmpz_swap(res, t); fmpz_clear(t); } else _fmpz_poly_evaluate_fmpz(res, f->coeffs, f->length, a); } flint-3.1.3/src/fmpz_poly/evaluate_fmpz_vec.c000066400000000000000000000011641461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_evaluate_fmpz_vec(fmpz * res, const fmpz_poly_t f, const fmpz * a, slong n) { slong i; for (i = 0; i < n; i++) fmpz_poly_evaluate_fmpz(res + i, f, a + i); } flint-3.1.3/src/fmpz_poly/evaluate_horner_d.c000066400000000000000000000015361461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" double _fmpz_poly_evaluate_horner_d(const fmpz * poly, slong n, double d) { slong i; double ans; ans = fmpz_get_d(poly + n - 1); for (i = n - 2; i >= 0L; i--) { ans *= d; ans += fmpz_get_d(poly + i); } return ans; } double fmpz_poly_evaluate_horner_d(const fmpz_poly_t poly, double d) { if (poly->length == 0) return 0.0; return _fmpz_poly_evaluate_horner_d(poly->coeffs, poly->length, d); } flint-3.1.3/src/fmpz_poly/evaluate_horner_d_2exp.c000066400000000000000000000103451461254215100222340ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart Copyright (C) 2021, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fmpz_poly.h" /* Naive double+exponent arithmetic; not designed to deal with underflow/overflow. */ typedef struct { double m; slong e; } dpe_t; /* Do up to ADJUSTMENT_DELAY steps without adjusting mantissa. This may cause the mantissa to drift from the normalized range [0.5, 1) by a factor about 2^ADJUSTMENT_DELAY. */ #define ADJUSTMENT_DELAY 16 /* Standardize nonzero mantissa to +/- [0.5, 1). */ #define DPE_ADJUST(x) \ do { \ int _e; \ (x).m = frexp((x).m, &_e); \ (x).e += _e; \ } while (0) FLINT_FORCE_INLINE dpe_t dpe_set_d_exp(double x, slong e) { dpe_t res; res.m = x; res.e = e; DPE_ADJUST(res); return res; } #if 0 FLINT_FORCE_INLINE dpe_t dpe_set_fmpz(const fmpz_t x) { dpe_t res; res.m = fmpz_get_d_2exp(&res.e, x); return res; } #endif FLINT_FORCE_INLINE dpe_t dpe_add(dpe_t x, dpe_t y) { dpe_t res; slong d; d = x.e - y.e; if (x.m == 0.0) return y; if (y.m == 0.0) return x; if (d >= 0) { if (d > 53 + ADJUSTMENT_DELAY) return x; res.m = x.m + d_mul_2exp_inrange(y.m, -d); res.e = x.e; } else { d = -d; if (d > 53 + ADJUSTMENT_DELAY) return y; res.m = y.m + d_mul_2exp_inrange(x.m, -d); res.e = y.e; } /* We delay adjustments */ /* DPE_ADJUST(res); */ return res; } FLINT_FORCE_INLINE dpe_t dpe_mul(dpe_t x, dpe_t y) { dpe_t res; res.m = x.m * y.m; res.e = x.e + y.e; /* We delay adjustments */ /* DPE_ADJUST(res); */ return res; } double _fmpz_poly_evaluate_horner_d_2exp2_precomp(slong * exp, const double * poly, const slong * poly_exp, slong n, double d, slong dexp) { dpe_t s, t, x; slong i; if (d == 0.0) { *exp = poly_exp[0]; return poly[0]; } x = dpe_set_d_exp(d, dexp); s.m = poly[n - 1]; s.e = poly_exp[n - 1]; for (i = n - 2; i >= 0; i--) { s = dpe_mul(s, x); if (poly[i] != 0.0) { t.m = poly[i]; t.e = poly_exp[i]; s = dpe_add(s, t); } /* Delayed adjustments. */ if (i % ADJUSTMENT_DELAY == 0) DPE_ADJUST(s); } DPE_ADJUST(s); *exp = s.e; return s.m; } double _fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz * poly, slong n, double d, slong dexp) { double * p; slong * p_exp; slong i; double v; TMP_INIT; if (d == 0.0) return fmpz_get_d_2exp(exp, poly + 0); TMP_START; p = TMP_ALLOC(n * sizeof(double)); p_exp = TMP_ALLOC(n * sizeof(slong)); for (i = 0; i < n; i++) { p[i] = fmpz_get_d_2exp(&p_exp[i], poly + i); } /* GCC really wants to complain about this one */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif v = _fmpz_poly_evaluate_horner_d_2exp2_precomp(exp, p, p_exp, n, d, dexp); #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif TMP_END; return v; } double _fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz * poly, slong n, double d) { return _fmpz_poly_evaluate_horner_d_2exp2(exp, poly, n, d, 0); } double fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz_poly_t poly, double d, slong dexp) { if (poly->length == 0) { *exp = 0; return 0.0; } return _fmpz_poly_evaluate_horner_d_2exp2(exp, poly->coeffs, poly->length, d, dexp); } double fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz_poly_t poly, double d) { if (poly->length == 0) { *exp = 0; return 0.0; } return _fmpz_poly_evaluate_horner_d_2exp(exp, poly->coeffs, poly->length, d); } flint-3.1.3/src/fmpz_poly/evaluate_horner_fmpq.c000066400000000000000000000033731461254215100220210ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpq.h" void _fmpz_poly_evaluate_horner_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden) { if (len == 0) { fmpz_zero(rnum); fmpz_one(rden); } else if (len == 1) { fmpz_set(rnum, f); fmpz_one(rden); } else { slong i = len - 1; fmpz_t d; fmpz_init(d); fmpz_set(rnum, f + i); fmpz_one(rden); do { --i; fmpz_mul(rnum, rnum, anum); fmpz_mul(rden, rden, aden); fmpz_addmul(rnum, rden, f + i); if (fmpz_is_zero(rnum)) fmpz_one(rden); } while (i); fmpz_gcd(d, rnum, rden); fmpz_divexact(rnum, rnum, d); fmpz_divexact(rden, rden, d); fmpz_clear(d); } } void fmpz_poly_evaluate_horner_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a) { if (res == a) { fmpq_t t; fmpq_init(t); fmpz_poly_evaluate_horner_fmpq(t, f, a); fmpq_swap(res, t); fmpq_clear(t); } else { _fmpz_poly_evaluate_horner_fmpq(fmpq_numref(res), fmpq_denref(res), f->coeffs, f->length, fmpq_numref(a), fmpq_denref(a)); } } flint-3.1.3/src/fmpz_poly/evaluate_horner_fmpz.c000066400000000000000000000024411461254215100220250ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a) { if (len == 0) { fmpz_zero(res); } else if (len == 1 || fmpz_is_zero(a)) { fmpz_set(res, f); } else { slong i = len - 1; fmpz_t t; fmpz_init(t); fmpz_set(res, f + i); for (i = len - 2; i >= 0; i--) { fmpz_mul(t, res, a); fmpz_add(res, f + i, t); } fmpz_clear(t); } } void fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a) { if (res == a) { fmpz_t t; fmpz_init(t); _fmpz_poly_evaluate_horner_fmpz(t, f->coeffs, f->length, a); fmpz_swap(res, t); fmpz_clear(t); } else _fmpz_poly_evaluate_horner_fmpz(res, f->coeffs, f->length, a); } flint-3.1.3/src/fmpz_poly/evaluate_mod.c000066400000000000000000000023571461254215100202610ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" mp_limb_t _fmpz_poly_evaluate_mod(const fmpz * poly, slong len, mp_limb_t a, mp_limb_t n, mp_limb_t ninv) { mp_limb_t c, res = 0; while (len--) { c = fmpz_fdiv_ui(poly + len, n); res = n_addmod(n_mulmod2_preinv(res, a, n, ninv), c, n); } return res; } mp_limb_t fmpz_poly_evaluate_mod(const fmpz_poly_t poly, mp_limb_t a, mp_limb_t n) { if (poly->length == 0) return 0; if (a == 0) { mp_limb_t res; res = fmpz_fdiv_ui(poly->coeffs, n); return res; } else { mp_limb_t ninv; ninv = n_preinvert_limb(n); return _fmpz_poly_evaluate_mod(poly->coeffs, poly->length, a, n, ninv); } } flint-3.1.3/src/fmpz_poly/fibonacci.c000066400000000000000000000030531461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2016 Shivin Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_fibonacci(fmpz * coeffs, ulong n) { fmpz * r; int even; slong k; ulong L; if (n == 0) return; if (n == 1) { fmpz_one(coeffs); return; } L = n / 2; even = 1 - (n % 2); /* set the first two coefficients of poly depending parity of n */ if (even) { fmpz_zero(coeffs); fmpz_one(coeffs + 1); fmpz_mul_ui(coeffs + 1, coeffs + 1, L); } else { fmpz_one(coeffs); fmpz_zero(coeffs + 1); } fmpz_one(coeffs + n - 1); r = coeffs + even; r += 2; /* calculate the coefficients of the polynomial*/ for (k = 2 + even; k < n - 2; k += 2) { fmpz_mul2_uiui(r, r - 2, L + k / 2, L + k / 2 - k + 1); fmpz_divexact2_uiui(r, r, k, k - 1); r += 2; } /* set the alternate coefficients to 0 again depending on the parity*/ for (k = 1 + even; k < n; k += 2) { fmpz_zero(coeffs + k); } } void fmpz_poly_fibonacci(fmpz_poly_t poly, ulong n) { fmpz_poly_fit_length(poly, n); _fmpz_poly_fibonacci(poly->coeffs, n); _fmpz_poly_set_length(poly, n); } flint-3.1.3/src/fmpz_poly/fit_length.c000066400000000000000000000012371461254215100177330ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_fit_length(fmpz_poly_t poly, slong len) { if (len > poly->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * poly->alloc) len = 2 * poly->alloc; fmpz_poly_realloc(poly, len); } } flint-3.1.3/src/fmpz_poly/gcd.c000066400000000000000000000056031461254215100163460ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_gcd(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { FLINT_ASSERT(len2 >= 1); FLINT_ASSERT(len1 >= len2); /* remove powers of x */ { slong val1 = 0, val2 = 0, d, rlen; while (val1 < len1 - 1 && fmpz_is_zero(poly1 + val1)) val1++; while (val2 < len2 - 1 && fmpz_is_zero(poly2 + val2)) val2++; if (val1 != 0 || val2 != 0) { d = FLINT_MIN(val1, val2); rlen = FLINT_MIN(len1 - val1, len2 - val2); if (len1 - val1 >= len2 - val2) _fmpz_poly_gcd(res + d, poly1 + val1, len1 - val1, poly2 + val2, len2 - val2); else _fmpz_poly_gcd(res + d, poly2 + val2, len2 - val2, poly1 + val1, len1 - val1); _fmpz_vec_zero(res, d); _fmpz_vec_zero(res + d + rlen, len2 - rlen - d); return; } } if (len1 < 6) { _fmpz_poly_gcd_subresultant(res, poly1, len1, poly2, len2); } else { slong b1, b2; b1 = _fmpz_vec_max_bits(poly1, len1); b2 = _fmpz_vec_max_bits(poly2, len2); b1 = FLINT_ABS(b1); b2 = FLINT_ABS(b2); if (b1 + b2 < 2 * FLINT_BITS) { if (_fmpz_poly_gcd_heuristic(res, poly1, len1, poly2, len2)) return; } _fmpz_poly_gcd_modular(res, poly1, len1, poly2, len2); } } void fmpz_poly_gcd(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { if (poly1->length < poly2->length) { fmpz_poly_gcd(res, poly2, poly1); } else /* len1 >= len2 >= 0 */ { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) /* len1 = len2 = 0 */ { fmpz_poly_zero(res); } else if (len2 == 0) /* len1 > len2 = 0 */ { if (fmpz_sgn(poly1->coeffs + (len1 - 1)) > 0) fmpz_poly_set(res, poly1); else fmpz_poly_neg(res, poly1); } else /* len1 >= len2 >= 1 */ { /* all current gcd functions automatically handle aliasing */ fmpz_poly_fit_length(res, len2); _fmpz_poly_gcd(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, len2); _fmpz_poly_normalise(res); } } } flint-3.1.3/src/fmpz_poly/gcd_heuristic.c000066400000000000000000000231271461254215100204260ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Divide (arrayg, limbsg) by the positive value gc in-place and return the number of limbs written */ mp_size_t flint_mpn_tdiv_q_fmpz_inplace(mp_ptr arrayg, mp_size_t limbsg, fmpz_t gc) { if (fmpz_size(gc) == 1) { mpn_divmod_1(arrayg, arrayg, limbsg, fmpz_get_ui(gc)); return limbsg - (arrayg[limbsg - 1] == 0); } else { mp_size_t tlimbs; __mpz_struct * mgc = COEFF_TO_PTR(*gc); mp_ptr temp = flint_malloc(limbsg*sizeof(mp_limb_t)); flint_mpn_copyi(temp, arrayg, limbsg); mpn_tdiv_q(arrayg, temp, limbsg, mgc->_mp_d, mgc->_mp_size); tlimbs = limbsg - mgc->_mp_size + 1; tlimbs -= (arrayg[tlimbs - 1] == 0); flint_free(temp); return tlimbs; } } /* Returns 1 if sign * (G, glen) * (Q, qlen) = (P, len), else returns 0. Temp requires space for glen + qlen - 1 coefficients */ int multiplies_out(fmpz * P, slong len, const fmpz * Q, slong qlen, const fmpz * G, slong glen, slong sign, fmpz * temp) { int divides = 0; /* multiply out */ if (qlen >= glen) _fmpz_poly_mul(temp, Q, qlen, G, glen); else _fmpz_poly_mul(temp, G, glen, Q, qlen); if (sign < WORD(0)) _fmpz_vec_neg(temp, temp, glen + qlen - 1); /* check if quotient really was exact */ divides = (glen + qlen - 1 == len && _fmpz_vec_equal(temp, P, len)); return divides; } /* Assumes len1 != 0 != len2 */ int _fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong bits1, bits2, max_bits, pack_bits, bound_bits, bits_G, bits_Q; ulong limbs1, limbs2, limbsg, pack_limbs, qlimbs, qlimbs2; ulong log_glen, log_length; slong sign1, sign2, glen, qlen, qlen2; fmpz_t ac, bc, d, gc; fmpz * A, * B, * G, * Q, * t; mp_ptr array1, array2, arrayg, q, temp; int divides; fmpz_init(ac); fmpz_init(bc); fmpz_init(d); /* compute gcd of content of poly1 and poly2 */ _fmpz_poly_content(ac, poly1, len1); _fmpz_poly_content(bc, poly2, len2); fmpz_gcd(d, ac, bc); /* special case, one of the polys is a constant */ if (len2 == 1) /* if len1 == 1 then so does len2 */ { fmpz_set(res, d); fmpz_clear(ac); fmpz_clear(bc); fmpz_clear(d); return 1; } /* divide poly1 and poly2 by their content */ A = _fmpz_vec_init(len1); B = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(A, poly1, len1, ac); _fmpz_vec_scalar_divexact_fmpz(B, poly2, len2, bc); fmpz_clear(ac); fmpz_clear(bc); /* special case, one of the polys is length 2 */ if (len2 == 2) /* if len1 == 2 then so does len2 */ { Q = _fmpz_vec_init(len1 - len2 + 1); if (_fmpz_poly_divides(Q, A, len1, B, 2)) { _fmpz_vec_scalar_mul_fmpz(res, B, 2, d); if (fmpz_sgn(res + 1) < 0) _fmpz_vec_neg(res, res, 2); } else { fmpz_set(res, d); fmpz_zero(res + 1); } fmpz_clear(d); _fmpz_vec_clear(A, len1); _fmpz_vec_clear(B, len2); _fmpz_vec_clear(Q, len1 - len2 + 1); return 1; } /* Determine how many bits (pack_bits) to pack into. The bound bound_bits ensures that if G | A and G | B with G primitive then G is the gcd of A and B. The bound is taken from https://arxiv.org/abs/cs/0206032v1 */ bits1 = FLINT_ABS(_fmpz_vec_max_bits(A, len1)); bits2 = FLINT_ABS(_fmpz_vec_max_bits(B, len2)); /* always extra bit for signs whether polys are signed or not, since we don't know if any purported gcds/quotients will be signed */ max_bits = FLINT_MAX(bits1, bits2) + 1; /* the +6 is chosen heuristically for performance; the theorem is satisfied with +3 (including a bit for signs) */ bound_bits = FLINT_MIN(bits1, bits2) + 6; pack_bits = FLINT_MAX(bound_bits, max_bits); /* need to pack original polys */ pack_limbs = (pack_bits - 1)/FLINT_BITS + 1; if (pack_bits >= 32) /* pack into multiples of limbs if >= 32 bits */ pack_bits = FLINT_BITS*pack_limbs; /* allocate space to pack into */ limbs1 = (pack_bits*len1 - 1)/FLINT_BITS + 1; limbs2 = (pack_bits*len2 - 1)/FLINT_BITS + 1; array1 = flint_calloc(limbs1, sizeof(mp_limb_t)); array2 = flint_calloc(limbs2, sizeof(mp_limb_t)); arrayg = flint_calloc(limbs2, sizeof(mp_limb_t)); /* pack first poly and normalise */ sign1 = (slong) fmpz_sgn(A + len1 - 1); _fmpz_poly_bit_pack(array1, A, len1, pack_bits, sign1); while (array1[limbs1 - 1] == 0) limbs1--; /* pack second poly and normalise */ sign2 = (slong) fmpz_sgn(B + len2 - 1); _fmpz_poly_bit_pack(array2, B, len2, pack_bits, sign2); while (array2[limbs2 - 1] == 0) limbs2--; /* compute integer GCD */ limbsg = flint_mpn_gcd_full(arrayg, array1, limbs1, array2, limbs2); /* Make space for unpacked gcd. May have one extra coeff due to 1 0 -x being packed as 0 -1 -x. */ glen = FLINT_MIN((limbsg*FLINT_BITS)/pack_bits + 1, len2); G = _fmpz_vec_init(glen); /* clear bits after g in arrayg so they are not inadvertently pulled into G after bit unpacking */ flint_mpn_zero(arrayg + limbsg, limbs2-limbsg); /* unpack gcd */ _fmpz_poly_bit_unpack(G, glen, arrayg, pack_bits, 0); while (G[glen - 1] == 0) glen--; /* divide by any content */ fmpz_init(gc); _fmpz_poly_content(gc, G, glen); if (!fmpz_is_one(gc)) limbsg = flint_mpn_tdiv_q_fmpz_inplace(arrayg, limbsg, gc); /* make space for quotient and remainder of both polys by gcd */ qlimbs = limbs1 - limbsg + 1; qlen = FLINT_MIN(len1, (qlimbs*FLINT_BITS)/pack_bits + 1); qlimbs2 = limbs2 - limbsg + 1; qlen2 = FLINT_MIN(len2, (qlimbs2*FLINT_BITS)/pack_bits + 1); qlimbs = (FLINT_MAX(qlen, qlen2)*pack_bits - 1)/FLINT_BITS + 1; q = flint_calloc(qlimbs, sizeof(mp_limb_t)); temp = flint_malloc(limbsg*sizeof(mp_limb_t)); divides = 0; if (flint_mpn_divides(q, array1, limbs1, arrayg, limbsg, temp)) { /* unpack quotient of first poly by gcd */ Q = _fmpz_vec_init(len1); t = _fmpz_vec_init(len1 + glen); _fmpz_poly_bit_unpack(Q, qlen, q, pack_bits, 0); while (Q[qlen - 1] == 0) qlen--; /* divide by content */ _fmpz_vec_scalar_divexact_fmpz(G, G, glen, gc); /* check if we really need to multiply out to check for exact quotient */ bits_G = FLINT_ABS(_fmpz_vec_max_bits(G, glen)); bits_Q = FLINT_ABS(_fmpz_vec_max_bits(Q, qlen)); log_glen = FLINT_BIT_COUNT(glen); log_length = FLINT_MIN(log_glen, FLINT_BIT_COUNT(qlen)); /* allow one bit for signs */ divides = (bits_G + bits_Q + log_length < pack_bits); if (!divides) /* need to multiply out to check exact quotient */ divides = multiplies_out(A, len1, Q, qlen, G, glen, sign1, t); if (divides) /* quotient really was exact */ { divides = 0; flint_mpn_zero(q, qlimbs); if (flint_mpn_divides(q, array2, limbs2, arrayg, limbsg, temp)) { /* unpack quotient of second poly by gcd */ _fmpz_poly_bit_unpack(Q, qlen2, q, pack_bits, 0); while (Q[qlen2 - 1] == 0) qlen2--; /* check if we really need to multiply out to check for exact quotient */ bits_Q = FLINT_ABS(_fmpz_vec_max_bits(Q, qlen2)); log_length = FLINT_MIN(log_glen, FLINT_BIT_COUNT(qlen2)); /* allow one bit for signs */ divides = (bits_G + bits_Q + log_length < pack_bits); if (!divides) /* we need to multiply out */ divides = multiplies_out(B, len2, Q, qlen2, G, glen, sign1, t); } } _fmpz_vec_clear(t, len1 + glen); _fmpz_vec_clear(Q, len1); } flint_free(q); flint_free(temp); flint_free(arrayg); flint_free(array1); flint_free(array2); fmpz_clear(gc); _fmpz_vec_clear(A, len1); _fmpz_vec_clear(B, len2); /* we found the gcd, so multiply by content */ if (divides) { _fmpz_vec_zero(res + glen, len2 - glen); _fmpz_vec_scalar_mul_fmpz(res, G, glen, d); } fmpz_clear(d); _fmpz_vec_clear(G, glen); return divides; } int fmpz_poly_gcd_heuristic(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { if (poly1->length < poly2->length) { return fmpz_poly_gcd_heuristic(res, poly2, poly1); } else /* len1 >= len2 >= 0 */ { const slong len1 = poly1->length; const slong len2 = poly2->length; int done = 1; /* len1 = 0 or len2 = 0 need done = 1 */ if (len1 == 0) /* len1 = len2 = 0 */ { fmpz_poly_zero(res); } else if (len2 == 0) /* len1 > len2 = 0 */ { if (fmpz_sgn(poly1->coeffs + (len1 - 1)) > 0) fmpz_poly_set(res, poly1); else fmpz_poly_neg(res, poly1); } else /* len1 >= len2 >= 1 */ { /* underscore function automatically takes care of aliasing */ fmpz_poly_fit_length(res, len2); done = _fmpz_poly_gcd_heuristic(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); if (done) { _fmpz_poly_set_length(res, len2); _fmpz_poly_normalise(res); } } return done; } } flint-3.1.3/src/fmpz_poly/gcd_modular.c000066400000000000000000000222461461254215100200730ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_gcd_modular(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { flint_bitcnt_t bits1, bits2, nb1, nb2, bits_small, pbits, curr_bits = 0, new_bits; fmpz_t ac, bc, hc, d, g, l, eval_A, eval_B, eval_GCD, modulus; fmpz * A, * B, * Q, * lead_A, * lead_B; mp_ptr a, b, h; mp_limb_t p, h_inv, g_mod; nmod_t mod; slong i, n, n0, unlucky, hlen, bound; int g_pm1; fmpz_init(ac); fmpz_init(bc); fmpz_init(d); /* compute gcd of content of poly1 and poly2 */ _fmpz_vec_content(ac, poly1, len1); _fmpz_vec_content(bc, poly2, len2); fmpz_gcd(d, ac, bc); /* special case, one of the polys is a constant */ if (len2 == 1) /* if len1 == 1 then so does len2 */ { fmpz_set(res, d); fmpz_clear(ac); fmpz_clear(bc); fmpz_clear(d); return; } /* divide poly1 and poly2 by their content */ A = _fmpz_vec_init(len1); B = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(A, poly1, len1, ac); _fmpz_vec_scalar_divexact_fmpz(B, poly2, len2, bc); fmpz_clear(ac); fmpz_clear(bc); /* get bound on size of gcd coefficients */ lead_A = A + len1 - 1; lead_B = B + len2 - 1; bits1 = _fmpz_vec_max_bits(A, len1); bits1 = FLINT_ABS(bits1); bits2 = _fmpz_vec_max_bits(B, len2); bits2 = FLINT_ABS(bits2); fmpz_init(l); if (len1 < 64 && len2 < 64) /* compute the squares of the 2-norms */ { _fmpz_vec_dot(l, A, A, len1); nb1 = fmpz_bits(l); _fmpz_vec_dot(l, B, B, len2); nb2 = fmpz_bits(l); } else /* approximate to save time */ { nb1 = 2*bits1 + FLINT_BIT_COUNT(len1); nb2 = 2*bits2 + FLINT_BIT_COUNT(len2); } /* get gcd of leading coefficients */ fmpz_init(g); fmpz_gcd(g, lead_A, lead_B); fmpz_mul(l, lead_A, lead_B); g_pm1 = fmpz_is_pm1(g); /* evaluate -A at -1 */ fmpz_init(eval_A); for (i = 0; i < len1; i++) { if (i & 1) fmpz_add(eval_A, eval_A, A + i); else fmpz_sub(eval_A, eval_A, A + i); } /* evaluate -B at -1 */ fmpz_init(eval_B); for (i = 0; i < len2; i++) { if (i & 1) fmpz_add(eval_B, eval_B, B + i); else fmpz_sub(eval_B, eval_B, B + i); } /* compute the gcd of eval(-A, -1) and eval(-B, -1) */ fmpz_init(eval_GCD); fmpz_gcd(eval_GCD, eval_A, eval_B); /* compute a heuristic bound after which we should begin checking if we're done */ bits_small = FLINT_MAX(fmpz_bits(eval_GCD), fmpz_bits(g)); if (bits_small < WORD(2)) bits_small = 2; fmpz_clear(eval_GCD); fmpz_clear(eval_A); fmpz_clear(eval_B); /* set size of first prime */ pbits = FLINT_BITS - 1; p = (UWORD(1)< n + 1) /* discard this prime */ { unlucky += pbits; continue; } /* scale new polynomial mod p appropriately */ if (g_pm1) _nmod_poly_make_monic(h, h, hlen, mod); else { h_inv = n_invmod(h[hlen - 1], mod.n); g_mod = fmpz_get_nmod(g, mod); h_inv = n_mulmod2_preinv(h_inv, g_mod, mod.n, mod.ninv); _nmod_vec_scalar_mul_nmod(h, h, hlen, h_inv, mod); } if (hlen <= n) /* we have a new bound on size of result */ { unlucky += fmpz_bits(modulus); _fmpz_vec_set_nmod_vec(res, h, hlen, mod); _fmpz_vec_zero(res + hlen, len2 - hlen); if (g_pm1) { /* are we done? */ if (_fmpz_poly_divides(Q, B, len2, res, hlen) && _fmpz_poly_divides(Q, A, len1, res, hlen)) break; } else { if (pbits + unlucky >= bound) /* if we reach the bound with one prime */ { _fmpz_vec_content(hc, res, hlen); /* divide by content */ _fmpz_vec_scalar_divexact_fmpz(res, res, hlen, hc); break; } if (pbits >= bits_small) /* if one prime is already big enough to check */ { /* divide by content */ _fmpz_vec_content(hc, res, hlen); /* correct sign of leading term */ if (fmpz_sgn(res + hlen - 1) < 0) fmpz_neg(hc, hc); _fmpz_vec_scalar_divexact_fmpz(res, res, hlen, hc); /* are we done? */ if (_fmpz_poly_divides(Q, B, len2, res, hlen) && _fmpz_poly_divides(Q, A, len1, res, hlen)) break; /* no, so multiply by content again */ _fmpz_vec_scalar_mul_fmpz(res, res, hlen, hc); } } curr_bits = FLINT_ABS(_fmpz_vec_max_bits(res, hlen)); fmpz_set_ui(modulus, p); n = hlen - 1; /* if we reach this we have a new bound on length of result */ continue; } _fmpz_poly_CRT_ui(res, res, hlen, modulus, h, hlen, mod.n, mod.ninv, 1); fmpz_mul_ui(modulus, modulus, mod.n); new_bits = _fmpz_vec_max_bits(res, hlen); new_bits = FLINT_ABS(new_bits); if (new_bits == curr_bits || fmpz_bits(modulus) >= bits_small) { if (!g_pm1) { _fmpz_vec_content(hc, res, hlen); /* correct sign of leading term */ if (fmpz_sgn(res + hlen - 1) < 0) fmpz_neg(hc, hc); /* divide by content */ _fmpz_vec_scalar_divexact_fmpz(res, res, hlen, hc); } if (fmpz_bits(modulus) + unlucky >= bound) break; /* are we done? */ if (_fmpz_poly_divides(Q, B, len2, res, hlen) && _fmpz_poly_divides(Q, A, len1, res, hlen)) break; if (!g_pm1) { /* no, so multiply by content again */ _fmpz_vec_scalar_mul_fmpz(res, res, hlen, hc); } } curr_bits = new_bits; } fmpz_clear(modulus); fmpz_clear(g); fmpz_clear(l); fmpz_clear(hc); _nmod_vec_clear(a); _nmod_vec_clear(b); _nmod_vec_clear(h); /* finally multiply by content */ _fmpz_vec_scalar_mul_fmpz(res, res, hlen, d); fmpz_clear(d); _fmpz_vec_clear(A, len1); _fmpz_vec_clear(B, len2); _fmpz_vec_clear(Q, len1); } void fmpz_poly_gcd_modular(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { if (poly1->length < poly2->length) { fmpz_poly_gcd_modular(res, poly2, poly1); } else /* len1 >= len2 >= 0 */ { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) /* len1 = len2 = 0 */ { fmpz_poly_zero(res); } else if (len2 == 0) /* len1 > len2 = 0 */ { if (fmpz_sgn(poly1->coeffs + (len1 - 1)) > 0) fmpz_poly_set(res, poly1); else fmpz_poly_neg(res, poly1); } else /* len1 >= len2 >= 1 */ { /* underscore function automatically aliases */ fmpz_poly_fit_length(res, len2); _fmpz_poly_gcd_modular(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, len2); _fmpz_poly_normalise(res); } } } flint-3.1.3/src/fmpz_poly/gcd_subresultant.c000066400000000000000000000077571461254215100211750ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_gcd_subresultant(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if (len2 == 1) { fmpz_t c; fmpz_init(c); _fmpz_poly_content(c, poly1, len1); fmpz_gcd(res, c, poly2); fmpz_clear(c); } else { fmpz_t a, b, d, g, h; fmpz *A, *B, *W; slong lenA, lenB; fmpz_init(a); fmpz_init(b); fmpz_init(d); fmpz_init(g); fmpz_init(h); A = W = _fmpz_vec_init(len1 + len2); B = W + len1; lenA = len1; lenB = len2; _fmpz_poly_content(a, poly1, lenA); _fmpz_poly_content(b, poly2, lenB); _fmpz_vec_scalar_divexact_fmpz(A, poly1, lenA, a); _fmpz_vec_scalar_divexact_fmpz(B, poly2, lenB, b); fmpz_gcd(d, a, b); fmpz_one(g); fmpz_one(h); while (1) { const slong delta = lenA - lenB; _fmpz_poly_pseudo_rem_cohen(A, A, lenA, B, lenB); FMPZ_VEC_NORM(A, lenA); if (lenA <= 1) break; /* Swap A and B */ FLINT_SWAP(fmpz *, A, B); FLINT_SWAP(slong, lenA, lenB); if (delta == 1) { fmpz_mul(b, g, h); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, b); fmpz_set(g, A + (lenA - 1)); fmpz_set(h, g); } else { fmpz_pow_ui(a, h, delta); fmpz_mul(b, g, a); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, b); fmpz_pow_ui(b, A + (lenA - 1), delta); fmpz_mul(g, h, b); fmpz_divexact(h, g, a); fmpz_set(g, A + (lenA - 1)); } } if (lenA == 1) { fmpz_set(res, d); _fmpz_vec_zero(res + 1, len2 - 1); } else { _fmpz_poly_content(b, B, lenB); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, b); if (fmpz_sgn(B + (lenB - 1)) < 0) fmpz_neg(d, d); _fmpz_vec_scalar_mul_fmpz(res, B, lenB, d); if (len2 >= lenB) _fmpz_vec_zero(res + lenB, len2 - lenB); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(d); fmpz_clear(g); fmpz_clear(h); _fmpz_vec_clear(W, len1 + len2); } } void fmpz_poly_gcd_subresultant(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { if (poly1->length < poly2->length) { fmpz_poly_gcd_subresultant(res, poly2, poly1); } else /* len1 >= len2 >= 0 */ { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) /* len1 = len2 = 0 */ { fmpz_poly_zero(res); } else if (len2 == 0) /* len1 > len2 = 0 */ { if (fmpz_sgn(poly1->coeffs + (len1 - 1)) > 0) fmpz_poly_set(res, poly1); else fmpz_poly_neg(res, poly1); } else /* len1 >= len2 >= 1 */ { /* underscore code automatically handles aliasing */ fmpz_poly_fit_length(res, len2); _fmpz_poly_gcd_subresultant(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, len2); _fmpz_poly_normalise(res); } } } flint-3.1.3/src/fmpz_poly/get_coeff.c000066400000000000000000000016321461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_get_coeff_fmpz(fmpz_t x, const fmpz_poly_t poly, slong n) { if (n < poly->length) fmpz_set(x, poly->coeffs + n); else fmpz_zero(x); } slong fmpz_poly_get_coeff_si(const fmpz_poly_t poly, slong n) { return (n < poly->length) ? fmpz_get_si(poly->coeffs + n) : WORD(0); } ulong fmpz_poly_get_coeff_ui(const fmpz_poly_t poly, slong n) { return (n < poly->length) ? fmpz_get_ui(poly->coeffs + n) : UWORD(0); } flint-3.1.3/src/fmpz_poly/get_nmod_poly.c000066400000000000000000000015151461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_get_nmod_poly(nmod_poly_t res, const fmpz_poly_t poly) { slong len = poly->length; if (len == 0) { nmod_poly_zero(res); } else { nmod_poly_fit_length(res, len); _fmpz_vec_get_nmod_vec(res->coeffs, poly->coeffs, len, res->mod); _nmod_poly_set_length(res, len); _nmod_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/get_str.c000066400000000000000000000067131461254215100172630ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fmpz_poly.h" char * _fmpz_poly_get_str(const fmpz * poly, slong len) { slong i, bound; char *str, *strbase; if (len == 0) { str = (char *) flint_malloc(2 * sizeof(char)); str[0] = '0'; str[1] = '\0'; return str; } bound = (slong) (ceil(log10((double) (len + 1)))); for (i = 0; i < len; i++) bound += fmpz_sizeinbase(poly + i, 10) + 1; bound += len + 2; strbase = (char *) flint_malloc(bound * sizeof(char)); str = strbase; str += flint_sprintf(str, "%wd ", len); do { if (!COEFF_IS_MPZ(*poly)) str += flint_sprintf(str, " %wd", *poly); else str += gmp_sprintf(str, " %Zd", COEFF_TO_PTR(*poly)); } while (poly++, --len); return strbase; } char * fmpz_poly_get_str(const fmpz_poly_t poly) { return _fmpz_poly_get_str(poly->coeffs, poly->length); } char * _fmpz_poly_get_str_pretty(const fmpz * poly, slong len, const char *x) { char *str; size_t off; slong i, bound, nz; if (len == 0) { str = flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } if (len == 1) { str = fmpz_get_str(NULL, 10, poly); return str; } nz = 0; bound = 1; for (i = 0; i < len; i++) if (!fmpz_is_zero(poly + i)) { bound += fmpz_sizeinbase(poly + i, 10) + 1; nz++; } bound += nz * (3 + strlen(x) + (slong) (ceil(log10(len)))); str = flint_malloc(bound); off = 0; i = len - 1; if (poly[i] == WORD(1)) { } else if (poly[i] == WORD(-1)) str[off++] = '-'; else if (!COEFF_IS_MPZ(poly[i])) off += flint_sprintf(str + off, "%wd*", poly[i]); else off += gmp_sprintf(str + off, "%Zd*", COEFF_TO_PTR(poly[i])); if (i > 1) off += flint_sprintf(str + off, "%s^%wd", x, i); else off += flint_sprintf(str + off, "%s", x); for (--i; i > 0; --i) { if (poly[i] == WORD(0)) continue; if (fmpz_sgn(poly + i) > 0) str[off++] = '+'; if (poly[i] == WORD(-1)) str[off++] = '-'; if (poly[i] != WORD(1) && poly[i] != WORD(-1)) { if (!COEFF_IS_MPZ(poly[i])) off += flint_sprintf(str + off, "%wd*", poly[i]); else off += gmp_sprintf(str + off, "%Zd*", COEFF_TO_PTR(poly[i])); } if (i > 1) off += flint_sprintf(str + off, "%s^%wd", x, i); else off += flint_sprintf(str + off, "%s", x); } if (poly[i] != WORD(0)) { if (fmpz_sgn(poly + i) > 0) str[off++] = '+'; if (!COEFF_IS_MPZ(poly[i])) off += flint_sprintf(str + off, "%wd", poly[i]); else off += gmp_sprintf(str + off, "%Zd", COEFF_TO_PTR(poly[i])); } return str; } char * fmpz_poly_get_str_pretty(const fmpz_poly_t poly, const char *x) { return _fmpz_poly_get_str_pretty(poly->coeffs, poly->length, x); } flint-3.1.3/src/fmpz_poly/hensel_build_tree.c000066400000000000000000000050211461254215100212570ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fmpz_poly.h" void fmpz_poly_hensel_build_tree(slong *link, fmpz_poly_t *v, fmpz_poly_t *w, const nmod_poly_factor_t fac) { const slong r = fac->num; const nmod_t mod = (fac->p + 0)->mod; slong i, j; nmod_poly_t d; nmod_poly_t *V = flint_malloc((2*r - 2)*sizeof(nmod_poly_t)); nmod_poly_t *W = flint_malloc((2*r - 2)*sizeof(nmod_poly_t)); nmod_poly_init_preinv(d, mod.n, mod.ninv); for (i = 0; i < 2*r - 2; i++) { nmod_poly_init_preinv(V[i], mod.n, mod.ninv); nmod_poly_init_preinv(W[i], mod.n, mod.ninv); } for (i = 0; i < r; i++) { nmod_poly_set(V[i], fac->p + i); link[i] = - i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s; slong minp, mind; slong tmp; minp = j; mind = nmod_poly_degree(V[j]); for (s = j+1; s < i; s++) { if (nmod_poly_degree(V[s]) < mind) { minp = s; mind = nmod_poly_degree(V[s]); } } nmod_poly_swap(V[j], V[minp]); /* Swap link[j] and V[minp] */ tmp = link[j]; link[j] = link[minp]; link[minp] = tmp; minp = j+1; mind = nmod_poly_degree(V[j+1]); for (s = j + 2; s < i; s++) { if (nmod_poly_degree(V[s]) < mind) { minp = s; mind = nmod_poly_degree(V[s]); } } nmod_poly_swap(V[j + 1], V[minp]); FLINT_SWAP(slong, link[j + 1], link[minp]); nmod_poly_mul(V[i], V[j], V[j+1]); link[i] = j; } for (j = 0; j < 2*r - 2; j += 2) { /* N.B. d == 1 */ nmod_poly_xgcd(d, W[j], W[j+1], V[j], V[j+1]); } for (j = 0; j < 2*r - 2; j++) { fmpz_poly_set_nmod_poly(v[j], V[j]); fmpz_poly_set_nmod_poly(w[j], W[j]); } for (i = 0; i < 2*r - 2; i++) { nmod_poly_clear(V[i]); nmod_poly_clear(W[i]); } nmod_poly_clear(d); flint_free(V); flint_free(W); } flint-3.1.3/src/fmpz_poly/hensel_continue_lift.c000066400000000000000000000047611461254215100220150ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" slong _fmpz_poly_hensel_continue_lift(fmpz_poly_factor_t lifted_fac, slong *link, fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f, slong prev, slong curr, slong N, const fmpz_t p) { const slong r = lifted_fac->num; slong i, new_prev; fmpz_t P; fmpz_poly_t monic_f; fmpz_init(P); fmpz_pow_ui(P, p, N); fmpz_poly_init(monic_f); if (fmpz_is_one(fmpz_poly_lead(f))) { fmpz_poly_set(monic_f, f); } else if (fmpz_cmp_si(fmpz_poly_lead(f), -1) == 0) { fmpz_poly_neg(monic_f, f); } else { fmpz_t t; fmpz_init(t); fmpz_mod(t, fmpz_poly_lead(f), P); if (fmpz_invmod(t, t, P) == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_continue_hensel_lift).\n"); } fmpz_poly_scalar_mul_fmpz(monic_f, f, t); fmpz_poly_scalar_mod_fmpz(monic_f, monic_f, P); fmpz_clear(t); } { slong *e, n = 3 + FLINT_FLOG2(N - prev); e = flint_malloc(n * sizeof(slong)); for (e[i = 0] = N; e[i] > curr; i++) e[i + 1] = (e[i] + 1) / 2; e[i] = curr; e[i+1] = prev; if (prev < curr) fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, p, e[i+1], e[i], -1); for (i--; i > 0; i--) fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, p, e[i+1], e[i], 1); fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, p, e[i+1], e[i], 0); new_prev = e[i+1]; flint_free(e); } /* Now everything is lifted to p^N, we just need to insert the factors into their correct places in lifted_fac. */ fmpz_poly_factor_fit_length(lifted_fac, r); for(i = 0; i < 2*r - 2; i++) { if (link[i] < 0) { fmpz_poly_scalar_smod_fmpz(lifted_fac->p + (- link[i] - 1), v[i], P); lifted_fac->exp[- link[i] - 1] = WORD(1); } } lifted_fac->num = r; fmpz_clear(P); fmpz_poly_clear(monic_f); return new_prev; } flint-3.1.3/src/fmpz_poly/hensel_lift.c000066400000000000000000000033751461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void _fmpz_poly_hensel_lift(fmpz *G, fmpz *H, fmpz *A, fmpz *B, const fmpz *f, slong lenF, const fmpz *g, slong lenG, const fmpz *h, slong lenH, const fmpz *a, slong lenA, const fmpz *b, slong lenB, const fmpz_t p, const fmpz_t p1) { _fmpz_poly_hensel_lift_without_inverse(G, H, f, lenF, g, lenG, h, lenH, a, lenA, b, lenB, p, p1); _fmpz_poly_hensel_lift_only_inverse(A, B, G, lenG, H, lenH, a, lenA, b, lenB, p, p1); } void fmpz_poly_hensel_lift(fmpz_poly_t G, fmpz_poly_t H, fmpz_poly_t A, fmpz_poly_t B, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1) { const slong lenG = g->length; const slong lenH = h->length; fmpz_poly_fit_length(G, lenG); fmpz_poly_fit_length(H, lenH); fmpz_poly_fit_length(A, lenH - 1); fmpz_poly_fit_length(B, lenG - 1); _fmpz_poly_hensel_lift(G->coeffs, H->coeffs, A->coeffs, B->coeffs, f->coeffs, f->length, g->coeffs, g->length, h->coeffs, h->length, a->coeffs, a->length, b->coeffs, b->length, p, p1); _fmpz_poly_set_length(G, lenG); _fmpz_poly_set_length(H, lenH); _fmpz_poly_set_length(A, lenH - 1); _fmpz_poly_set_length(B, lenG - 1); _fmpz_poly_normalise(A); _fmpz_poly_normalise(B); } flint-3.1.3/src/fmpz_poly/hensel_lift_once.c000066400000000000000000000023271461254215100211110ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_hensel_lift_once(fmpz_poly_factor_t lifted_fac, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, slong N) { const slong r = local_fac->num; slong i; slong *link; fmpz_poly_t *v, *w; link = flint_malloc((2*r - 2) * sizeof(slong)); v = flint_malloc(2*(2*r - 2) * sizeof(fmpz_poly_t)); w = v + (2*r - 2); for(i = 0; i < 2*r - 2; i++) { fmpz_poly_init(v[i]); fmpz_poly_init(w[i]); } _fmpz_poly_hensel_start_lift(lifted_fac, link, v, w, f, local_fac, N); for (i = 0; i < 2*r - 2; i++) { fmpz_poly_clear(v[i]); fmpz_poly_clear(w[i]); } flint_free(link); flint_free(v); } flint-3.1.3/src/fmpz_poly/hensel_lift_only_inverse.c000066400000000000000000000101611461254215100226740ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" /* Macro for the lift B := [{(1 - aG - bH)/p} * b mod g] p + b, of length at most lenG - 1. Assumes that {C, lenC} contains the inner part {(1 - aG - bH)/p} mod p1, where lenC = max(lenA + lenG - 1, lenB + lenH - 1). Requires temporary space M, D, E. We really only need lenM = max(lenG, lenH) lenE = max(lenG + lenB - 2, lenH + lenA - 2) lenD = max(lenC, lenE) Writes {B, lenG - 1}. The cofactor that is lifted is the polynomial {b, lenB}, which may be aliased with B. Although it suffices to have g modulo p, there is no harm in supplying {g, lenG} only reduced modulo p p1. */ #define liftinv(B, b, lenB, g, lenG) \ do { \ _fmpz_mod_vec_set_fmpz_vec(M, g, lenG, p1ctx); \ _fmpz_mod_poly_rem(D, C, lenC, M, lenG, one, p1ctx); \ _fmpz_mod_poly_mul(E, D, lenG - 1, b, lenB, p1ctx); \ if (lenB > 1) \ { \ _fmpz_mod_poly_rem(D, E, lenG + lenB - 2, M, lenG, one, p1ctx); \ _fmpz_vec_scalar_mul_fmpz(M, D, lenG - 1, p); \ } \ else \ { \ _fmpz_vec_scalar_mul_fmpz(M, E, lenG - 1, p); \ } \ _fmpz_poly_add(B, M, lenG - 1, b, lenB); \ } while (0) void _fmpz_poly_hensel_lift_only_inverse(fmpz *A, fmpz *B, const fmpz *G, slong lenG, const fmpz *H, slong lenH, const fmpz *a, slong lenA, const fmpz *b, slong lenB, const fmpz_t p, const fmpz_t p1) { const fmpz one[1] = {WORD(1)}; const slong lenC = FLINT_MAX(lenA + lenG - 1, lenB + lenH - 1); const slong lenM = FLINT_MAX(lenG, lenH); const slong lenE = FLINT_MAX(lenG + lenB - 2, lenH + lenA - 2); const slong lenD = FLINT_MAX(lenC, lenE); fmpz *C, *D, *E, *M; fmpz_mod_ctx_t p1ctx; C = _fmpz_vec_init(lenC + lenD + lenD + lenM); D = C + lenC; E = D + lenD; M = E + lenE; if (lenG >= lenA) _fmpz_poly_mul(C, G, lenG, a, lenA); else _fmpz_poly_mul(C, a, lenA, G, lenG); if (lenH >= lenB) _fmpz_poly_mul(D, H, lenH, b, lenB); else _fmpz_poly_mul(D, b, lenB, H, lenH); _fmpz_vec_add(C, C, D, lenC); fmpz_sub_ui(C, C, 1); _fmpz_vec_neg(C, C, lenC); _fmpz_vec_scalar_divexact_fmpz(D, C, lenC, p); fmpz_mod_ctx_init(p1ctx, p1); _fmpz_mod_vec_set_fmpz_vec(C, D, lenC, p1ctx); liftinv(B, b, lenB, G, lenG); liftinv(A, a, lenA, H, lenH); fmpz_mod_ctx_clear(p1ctx); _fmpz_vec_clear(C, lenC + lenD + lenD + lenM); } void fmpz_poly_hensel_lift_only_inverse(fmpz_poly_t Aout, fmpz_poly_t Bout, const fmpz_poly_t G, const fmpz_poly_t H, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1) { fmpz_poly_fit_length(Aout, H->length - 1); fmpz_poly_fit_length(Bout, G->length - 1); _fmpz_poly_hensel_lift_only_inverse(Aout->coeffs, Bout->coeffs, G->coeffs, G->length, H->coeffs, H->length, a->coeffs, a->length, b->coeffs, b->length, p, p1); _fmpz_poly_set_length(Aout, H->length - 1); _fmpz_poly_set_length(Bout, G->length - 1); _fmpz_poly_normalise(Aout); _fmpz_poly_normalise(Bout); } flint-3.1.3/src/fmpz_poly/hensel_lift_tree.c000066400000000000000000000015331461254215100211220ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_hensel_lift_tree(slong *link, fmpz_poly_t *v, fmpz_poly_t *w, fmpz_poly_t f, slong r, const fmpz_t p, slong e0, slong e1, slong inv) { fmpz_t p0, p1; fmpz_init(p0); fmpz_init(p1); fmpz_pow_ui(p0, p, e0); fmpz_pow_ui(p1, p, e1 - e0); fmpz_poly_hensel_lift_tree_recursive(link, v, w, f, 2*r - 4, inv, p0, p1); fmpz_clear(p0); fmpz_clear(p1); } flint-3.1.3/src/fmpz_poly/hensel_lift_tree_recursive.c000066400000000000000000000026111461254215100232070ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_hensel_lift_tree_recursive(slong *link, fmpz_poly_t *v, fmpz_poly_t *w, fmpz_poly_t f, slong j, slong inv, const fmpz_t p0, const fmpz_t p1) { if (j >= 0) { if (inv == 1) fmpz_poly_hensel_lift(v[j], v[j + 1], w[j], w[j + 1], f, v[j], v[j + 1], w[j], w[j + 1], p0, p1); else if (inv == -1) fmpz_poly_hensel_lift_only_inverse(w[j], w[j+1], v[j], v[j+1], w[j], w[j+1], p0, p1); else fmpz_poly_hensel_lift_without_inverse(v[j], v[j+1], f, v[j], v[j+1], w[j], w[j+1], p0, p1); fmpz_poly_hensel_lift_tree_recursive(link, v, w, v[j], link[j], inv, p0, p1); fmpz_poly_hensel_lift_tree_recursive(link, v, w, v[j+1], link[j+1], inv, p0, p1); } } flint-3.1.3/src/fmpz_poly/hensel_lift_without_inverse.c000066400000000000000000000072231461254215100234230ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" /* Macro for the lift G := [{(f - gh)/p} * b mod g] p + g. Assumes that {C, lenF} contains the inner part {f - gh}/p mod p1. Requires temporary space M, D, E. We really only need lenM = max(lenG, lenH) lenE = max(lenG + lenB - 2, lenH + lenA - 2) lenD = max(lenE, lenF) Only supports aliasing between G and g. */ #define lift(G, g, lenG, b, lenB) \ do { \ _fmpz_mod_vec_set_fmpz_vec(M, g, lenG, p1ctx); \ _fmpz_mod_poly_rem(D, C, lenF, M, lenG, one, p1ctx); \ _fmpz_mod_poly_mul(E, D, lenG - 1, b, lenB, p1ctx); \ if (lenB > 1) \ { \ _fmpz_mod_poly_rem(D, E, lenG + lenB - 2, M, lenG, one, p1ctx); \ _fmpz_vec_scalar_mul_fmpz(M, D, lenG - 1, p); \ } \ else \ { \ _fmpz_vec_scalar_mul_fmpz(M, E, lenG - 1, p); \ } \ _fmpz_vec_add(G, g, M, lenG - 1); \ fmpz_one(G + lenG - 1); \ } while (0) void _fmpz_poly_hensel_lift_without_inverse(fmpz *G, fmpz *H, const fmpz *f, slong lenF, const fmpz *g, slong lenG, const fmpz *h, slong lenH, const fmpz *a, slong lenA, const fmpz *b, slong lenB, const fmpz_t p, const fmpz_t p1) { const fmpz one[1] = {1l}; const slong lenM = FLINT_MAX(lenG, lenH); const slong lenE = FLINT_MAX(lenG + lenB - 2, lenH + lenA - 2); const slong lenD = FLINT_MAX(lenE, lenF); fmpz *C, *D, *E, *M; fmpz_mod_ctx_t p1ctx; C = _fmpz_vec_init(lenF + lenD + lenE + lenM); D = C + lenF; E = D + lenD; M = E + lenE; if (lenG >= lenH) _fmpz_poly_mul(C, g,lenG, h, lenH); else _fmpz_poly_mul(C, h, lenH, g, lenG); _fmpz_vec_sub(C, f, C, lenF); _fmpz_vec_scalar_divexact_fmpz(D, C, lenF, p); fmpz_mod_ctx_init(p1ctx, p1); _fmpz_mod_vec_set_fmpz_vec(C, D, lenF, p1ctx); lift(G, g, lenG, b, lenB); lift(H, h, lenH, a, lenA); fmpz_mod_ctx_clear(p1ctx); _fmpz_vec_clear(C, lenF + lenD + lenE + lenM); } void fmpz_poly_hensel_lift_without_inverse(fmpz_poly_t Gout, fmpz_poly_t Hout, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1) { fmpz_poly_fit_length(Gout, g->length); fmpz_poly_fit_length(Hout, h->length); _fmpz_poly_set_length(Gout, g->length); _fmpz_poly_set_length(Hout, h->length); _fmpz_poly_hensel_lift_without_inverse(Gout->coeffs, Hout->coeffs, f->coeffs, f->length, g->coeffs, g->length, h->coeffs, h->length, a->coeffs, a->length, b->coeffs, b->length, p, p1); } flint-3.1.3/src/fmpz_poly/hensel_start_lift.c000066400000000000000000000050441461254215100213210ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" slong _fmpz_poly_hensel_start_lift(fmpz_poly_factor_t lifted_fac, slong *link, fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, slong N) { const slong r = local_fac->num; slong i, preve; fmpz_t p, P; fmpz_poly_t monic_f; fmpz_init(p); fmpz_init(P); fmpz_poly_init(monic_f); fmpz_set_ui(p, (local_fac->p + 0)->mod.n); fmpz_pow_ui(P, p, N); if (fmpz_is_one(fmpz_poly_lead(f))) { fmpz_poly_set(monic_f, f); } else if (fmpz_cmp_si(fmpz_poly_lead(f), -1) == 0) { fmpz_poly_neg(monic_f, f); } else { fmpz_t t; fmpz_init(t); fmpz_mod(t, fmpz_poly_lead(f), P); if (fmpz_invmod(t, t, P) == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_start_hensel_lift).\n"); } fmpz_poly_scalar_mul_fmpz(monic_f, f, t); fmpz_poly_scalar_mod_fmpz(monic_f, monic_f, P); fmpz_clear(t); } fmpz_poly_hensel_build_tree(link, v, w, local_fac); { slong *e, n = FLINT_CLOG2(N) + 1; e = flint_malloc(n * sizeof(slong)); for (e[i = 0] = N; e[i] > 1; i++) e[i + 1] = (e[i] + 1) / 2; for (i--; i > 0; i--) { fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, p, e[i+1], e[i], 1); } if (N > 1) { fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, p, e[i+1], e[i], 0); } preve = e[i+1]; flint_free(e); } /* Now everything is lifted to p^N, we just need to insert the factors into their correct places in lifted_fac. */ fmpz_poly_factor_fit_length(lifted_fac, r); for (i = 0; i < 2*r - 2; i++) { if (link[i] < 0) { fmpz_poly_scalar_smod_fmpz(lifted_fac->p + (- link[i] - 1), v[i], P); lifted_fac->exp[- link[i] - 1] = WORD(1); } } lifted_fac->num = r; fmpz_clear(p); fmpz_clear(P); fmpz_poly_clear(monic_f); return preve; } flint-3.1.3/src/fmpz_poly/hermite_h.c000066400000000000000000000023461461254215100175560ustar00rootroot00000000000000/* Copyright (C) 2011 Ralf Stephan Copyright (C) 2021 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_hermite_h(fmpz * coeffs, ulong n) { long k; if (n == 0) { fmpz_one(coeffs); return; } if (n == 1) { fmpz_zero(coeffs); fmpz_set_ui(coeffs + 1, 2); return; } for (k = n & 1; k < n; k += 2) { fmpz_zero(coeffs + k); } fmpz_one(coeffs + n); fmpz_mul_2exp(coeffs + n, coeffs + n, n); for (k = n - 2; k >= 0; k -= 2) { fmpz_mul2_uiui(coeffs + k, coeffs + k+2, k+1, k+2); fmpz_divexact_ui(coeffs + k, coeffs + k, (n - k) << 1); fmpz_neg(coeffs + k, coeffs + k); } } void fmpz_poly_hermite_h(fmpz_poly_t poly, ulong n) { fmpz_poly_fit_length(poly, n + 1); _fmpz_poly_hermite_h(poly->coeffs, n); _fmpz_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpz_poly/hermite_he.c000066400000000000000000000022611461254215100177170ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan Copyright (C) 2021 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_hermite_he(fmpz * coeffs, ulong n) { long k; if (n == 0) { fmpz_one(coeffs); return; } if (n == 1) { fmpz_zero(coeffs); fmpz_one(coeffs + 1); return; } for (k = !(n & 1); k < n; k += 2) { fmpz_zero(coeffs + k); } fmpz_one(coeffs + n); for (k = n - 2; k >= 0; k -= 2) { fmpz_mul2_uiui(coeffs + k, coeffs + k+2, k+1, k+2); fmpz_divexact_ui(coeffs + k, coeffs + k, n - k); fmpz_neg(coeffs + k, coeffs + k); } } void fmpz_poly_hermite_he(fmpz_poly_t poly, ulong n) { fmpz_poly_fit_length(poly, n + 1); _fmpz_poly_hermite_he(poly->coeffs, n); _fmpz_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpz_poly/inflate.c000066400000000000000000000025001461254215100172240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_inflate(fmpz_poly_t result, const fmpz_poly_t input, ulong inflation) { if (input->length <= 1 || inflation == 1) { fmpz_poly_set(result, input); } else if (inflation == 0) { fmpz_t v; fmpz_init_set_ui(v, 1); fmpz_poly_evaluate_fmpz(v, input, v); fmpz_poly_zero(result); fmpz_poly_set_coeff_fmpz(result, 0, v); fmpz_clear(v); } else { slong i, j, res_length = (input->length - 1) * inflation + 1; fmpz_poly_fit_length(result, res_length); for (i = input->length - 1; i > 0; i--) { fmpz_set(result->coeffs + (i * inflation), input->coeffs + i); for (j = i * inflation - 1; j > (i - 1) * inflation; j--) fmpz_zero(result->coeffs + j); } fmpz_set(result->coeffs + 0, input->coeffs + 0); result->length = res_length; } } flint-3.1.3/src/fmpz_poly/init.c000066400000000000000000000014521461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_init(fmpz_poly_t poly) { poly->coeffs = NULL; poly->alloc = 0; poly->length = 0; } void fmpz_poly_init2(fmpz_poly_t poly, slong alloc) { if (alloc != 0) /* allocate space for alloc small coeffs */ poly->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); else poly->coeffs = NULL; poly->alloc = alloc; poly->length = 0; } flint-3.1.3/src/fmpz_poly/inlines.c000066400000000000000000000006561461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_INLINES_C #include "fmpz_poly.h" flint-3.1.3/src/fmpz_poly/interpolate_fmpz_vec.c000066400000000000000000000035761461254215100220370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" static void _fmpz_poly_interpolate_newton(fmpz * ys, const fmpz * xs, slong n) { fmpz_t p, q, t, r; slong i, j; fmpz_init(p); fmpz_init(q); fmpz_init(t); fmpz_init(r); for (i = 1; i < n; i++) { fmpz_set(t, ys + i - 1); for (j = i; j < n; j++) { fmpz_sub(p, ys + j, t); fmpz_sub(q, xs + j, xs + j - i); fmpz_set(t, ys + j); fmpz_fdiv_qr(ys + j, r, p, q); if (!fmpz_is_zero(r)) { fmpz_clear(r); fmpz_clear(t); fmpz_clear(q); fmpz_clear(p); flint_throw(FLINT_INEXACT, "Not an exact division in" "fmpz_poly_interpolate_newton"); } } } fmpz_clear(r); fmpz_clear(p); fmpz_clear(q); fmpz_clear(t); } void fmpz_poly_interpolate_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n) { if (n == 0) { fmpz_poly_zero(poly); return; } else if (n == 1) { fmpz_poly_set_fmpz(poly, ys); return; } else { fmpz_poly_fit_length(poly, n); _fmpz_vec_set(poly->coeffs, ys, n); _fmpz_poly_interpolate_newton(poly->coeffs, xs, n); _fmpz_poly_set_length(poly, n); _fmpz_poly_normalise(poly); _fmpz_poly_newton_to_monomial(poly->coeffs, xs, poly->length); } } flint-3.1.3/src/fmpz_poly/inv_series.c000066400000000000000000000212351461254215100177560ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2014, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { if (Qlen < 64 || n < 64) _fmpz_poly_inv_series_basecase(Qinv, Q, Qlen, n); else _fmpz_poly_inv_series_newton(Qinv, Q, Qlen, n); } void fmpz_poly_inv_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_inv_series). Division by zero.\n"); } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_inv_series(Qinv->coeffs, Q->coeffs, Qlen, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_inv_series(t->coeffs, Q->coeffs, Qlen, n); fmpz_poly_swap(Qinv, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(Qinv, n); _fmpz_poly_normalise(Qinv); } void _fmpz_poly_inv_series_basecase(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { int neg; Qlen = FLINT_MIN(Qlen, n); neg = fmpz_is_one(Q + 0); fmpz_set(Qinv + 0, Q + 0); if (Qlen == 1) { _fmpz_vec_zero(Qinv + 1, n - 1); } else if (Qlen == 2 || _fmpz_vec_is_zero(Q + 1, Qlen - 2)) { /* Special-case binomials */ slong i, j, step; step = Qlen - 1; if (neg) { fmpz_neg(Qinv + step, Q + step); for (i = 2 * step; i < n; i += step) fmpz_mul(Qinv + i, Qinv + i - step, Qinv + step); } else { fmpz_neg(Qinv + step, Q + step); for (i = 2 * step; i < n; i += step) fmpz_mul(Qinv + i, Qinv + i - step, Q + step); } for (i = 0; i < n; i += step) for (j = i + 1; j < FLINT_MIN(n, i + step); j++) fmpz_zero(Qinv + j); } else { slong i, j, nsmall; char * Qbits; slong b, bits, Qinvbits; TMP_INIT; TMP_START; /* Qbits[i] = max(bits(Q[0]), ..., bits(Q[i])), as long as coeffs are small */ Qbits = TMP_ALLOC(Qlen); Qbits[0] = 1; /* Maximum bits of all Qinv coefficients encountered so far */ Qinvbits = 1; /* We have small coefficients for i < nsmall */ for (nsmall = 1; nsmall < Qlen; nsmall++) { b = Q[nsmall]; if (COEFF_IS_MPZ(b)) break; b = FLINT_ABS(b); if ((b >> Qbits[nsmall - 1]) != 0) Qbits[nsmall] = FLINT_BIT_COUNT(b); else Qbits[nsmall] = Qbits[nsmall - 1]; } for (i = 1; i < n; i++) { if (i >= nsmall || Qinvbits > SMALL_FMPZ_BITCOUNT_MAX || Qbits[i] > SMALL_FMPZ_BITCOUNT_MAX) { /* Can't use fast code. */ bits = WORD_MAX; } else { /* Can maybe use fast code; bound bits. */ b = FLINT_MIN(i, Qlen - 1); bits = FLINT_BIT_COUNT(b); /* Bit size of product. */ bits += Qbits[i] + Qinvbits; /* Sign. */ bits += 1; } if (bits <= 3 * FLINT_BITS - 1) { if (bits <= FLINT_BITS - 1) { slong s, x, y; s = 0; for (j = 1; j < FLINT_MIN(i + 1, Qlen); j++) { x = Q[j]; y = Qinv[i - j]; s += x * y; } if (neg) s = -s; fmpz_set_si(Qinv + i, s); } else if (bits <= 2 * FLINT_BITS - 1) { mp_limb_t hi, lo, shi, slo; slong x, y; shi = slo = 0; for (j = 1; j < FLINT_MIN(i + 1, Qlen); j++) { x = Q[j]; y = Qinv[i - j]; smul_ppmm(hi, lo, x, y); add_ssaaaa(shi, slo, shi, slo, hi, lo); } if (neg) sub_ddmmss(shi, slo, 0, 0, shi, slo); fmpz_set_signed_uiui(Qinv + i, shi, slo); } else { mp_limb_t hi, lo, cy, shh, shi, slo; slong x, y; shh = shi = slo = 0; for (j = 1; j < FLINT_MIN(i + 1, Qlen); j++) { x = Q[j]; y = Qinv[i - j]; smul_ppmm(hi, lo, x, y); add_sssaaaaaa(cy, shi, slo, 0, shi, slo, 0, hi, lo); shh += (0 <= (slong) hi) ? cy : cy - 1; } if (neg) sub_dddmmmsss(shh, shi, slo, 0, 0, 0, shh, shi, slo); fmpz_set_signed_uiuiui(Qinv + i, shh, shi, slo); } if (COEFF_IS_MPZ(*(Qinv + i))) { /* Will no longer use fast code */ nsmall = i; } else { /* Update Qinvbits */ b = FLINT_ABS(*(Qinv + i)); b = FLINT_BIT_COUNT(b); Qinvbits = FLINT_MAX(Qinvbits, b); } } else { slong l = FLINT_MIN(i, Qlen - 1); _fmpz_vec_dot_general(Qinv + i, NULL, neg, Q + 1, Qinv + i - l, 1, l); } } TMP_END; } } void fmpz_poly_inv_series_basecase(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_inv_series_basecase). Division by zero.\n"); } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_inv_series_basecase(Qinv->coeffs, Q->coeffs, Qlen, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_inv_series_basecase(t->coeffs, Q->coeffs, Qlen, n); fmpz_poly_swap(Qinv, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(Qinv, n); _fmpz_poly_normalise(Qinv); } #define MULLOW(z, x, xn, y, yn, nn) \ if ((xn) >= (yn)) \ _fmpz_poly_mullow(z, x, xn, y, yn, nn); \ else \ _fmpz_poly_mullow(z, y, yn, x, xn, nn); \ void _fmpz_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { slong cutoff = 64; Qlen = FLINT_MIN(Qlen, n); if (Qlen < cutoff) { _fmpz_poly_inv_series_basecase(Qinv, Q, Qlen, n); } else { slong *a, i, m, Qnlen, Wlen, W2len; fmpz * W; W = _fmpz_vec_init(n); a = flint_malloc(sizeof(slong) * FLINT_BITS); a[i = 0] = n; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); _fmpz_poly_inv_series_basecase(Qinv, Q, Qlen, n); for (i--; i >= 0; i--) { m = n; n = a[i]; Qnlen = FLINT_MIN(Qlen, n); Wlen = FLINT_MIN(Qnlen + m - 1, n); W2len = Wlen - m; MULLOW(W, Q, Qnlen, Qinv, m, Wlen); MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m); _fmpz_vec_neg(Qinv + m, Qinv + m, n - m); } _fmpz_vec_clear(W, n); flint_free(a); } } void fmpz_poly_inv_series_newton(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_inv_series_newton). Division by zero.\n"); } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_inv_series_newton(Qinv->coeffs, Q->coeffs, Qlen, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_inv_series_newton(t->coeffs, Q->coeffs, Qlen, n); fmpz_poly_swap(Qinv, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(Qinv, n); _fmpz_poly_normalise(Qinv); } flint-3.1.3/src/fmpz_poly/io.c000066400000000000000000000262701461254215100162230ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* printing *******************************************************************/ int _fmpz_poly_fprint_pretty(FILE * file, const fmpz * poly, slong len, const char * x) { int r; slong i; FMPZ_VEC_NORM(poly, len); if (len == 0) { r = fputc('0', file); r = (r != EOF) ? 1 : EOF; return r; } else if (len == 1) { r = fmpz_fprint(file, poly + 0); return r; } else if (len == 2) { if (*(poly + 1) == WORD(1)) { r = flint_fprintf(file, "%s", x); } else if (*(poly + 1) == WORD(-1)) { r = flint_fprintf(file, "-%s", x); } else { r = fmpz_fprint(file, poly + 1); if (r > 0) r = flint_fprintf(file, "*%s", x); } if (r > 0) { if (fmpz_sgn(poly + 0) > 0) { r = flint_fprintf(file, "+"); if (r > 0) r = fmpz_fprint(file, poly + 0); } else if (fmpz_sgn(poly + 0) < 0) { r = fmpz_fprint(file, poly + 0); } } return r; } i = len - 1; /* i >= 2 */ r = 1; { if (*(poly + i) == 1) r = flint_fprintf(file, "%s^%wd", x, i); else if (*(poly + i) == -1) r = flint_fprintf(file, "-%s^%wd", x, i); else { r = fmpz_fprint(file, poly + i); if (r > 0) r = flint_fprintf(file, "*%s^%wd", x, i); } --i; } for (; (r > 0) && (i > 1); --i) { if (*(poly + i) == 0) continue; if (*(poly + i) == 1) r = flint_fprintf(file, "+%s^%wd", x, i); else if (*(poly + i) == -1) r = flint_fprintf(file, "-%s^%wd", x, i); else { if (fmpz_sgn(poly + i) > 0) { r = fputc('+', file); r = (r != EOF) ? 1 : EOF; } if (r > 0) r = fmpz_fprint(file, poly + i); if (r > 0) r = flint_fprintf(file, "*%s^%wd", x, i); } } if ((r > 0) && *(poly + 1)) { if (*(poly + 1) == 1) { r = fputc('+', file); r = (r != EOF) ? 1 : EOF; if (r > 0) { r = fputs(x, file); r = (r >= 0) ? 1 : -1; } } else if (*(poly + 1) == -1) { r = fputc('-', file); r = (r != EOF) ? 1 : EOF; if (r > 0) { r = fputs(x, file); r = (r >= 0) ? 1 : -1; } } else { if (fmpz_sgn(poly + 1) > 0) { r = fputc('+', file); r = (r != EOF) ? 1 : EOF; } if (r > 0) r = fmpz_fprint(file, poly + 1); if (r > 0) { r = fputc('*', file); r = (r != EOF) ? 1 : EOF; } if (r > 0) { r = fputs(x, file); r = (r >= 0) ? 1 : -1; } } } if ((r > 0) && *(poly)) { if (fmpz_sgn(poly) > 0) { r = fputc('+', file); r = (r != EOF) ? 1 : EOF; } if (r > 0) r = fmpz_fprint(file, poly); } return r; } int _fmpz_poly_fprint(FILE * file, const fmpz * poly, slong len) { return _fmpz_vec_fprint(file, poly, len); } int fmpz_poly_fprint(FILE * file, const fmpz_poly_t poly) { return _fmpz_vec_fprint(file, poly->coeffs, poly->length); } int fmpz_poly_fprint_pretty(FILE * file, const fmpz_poly_t poly, const char * x) { return _fmpz_poly_fprint_pretty(file, poly->coeffs, poly->length, x); } int _fmpz_poly_print(const fmpz * poly, slong n) { return _fmpz_poly_fprint(stdout, poly, n); } int fmpz_poly_print(const fmpz_poly_t poly) { return fmpz_poly_fprint(stdout, poly); } int _fmpz_poly_print_pretty(const fmpz * poly, slong len, const char * x) { return _fmpz_poly_fprint_pretty(stdout, poly, len, x); } int fmpz_poly_print_pretty(const fmpz_poly_t poly, const char * x) { return fmpz_poly_fprint_pretty(stdout, poly, x); } /* reading ********************************************************************/ int fmpz_poly_fread(FILE * file, fmpz_poly_t poly) { int r; slong i, len; mpz_t t; mpz_init(t); r = mpz_inp_str(t, file, 10); if (r == 0) { mpz_clear(t); return 0; } if (!mpz_fits_slong_p(t)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_fread). Length does not fit into a slong.\n"); } len = flint_mpz_get_si(t); mpz_clear(t); fmpz_poly_fit_length(poly, len); for (i = 0; i < len; i++) { r = fmpz_fread(file, poly->coeffs + i); if (r <= 0) return r; } _fmpz_poly_set_length(poly, len); _fmpz_poly_normalise(poly); return 1; } static inline int is_varsymbol0(char c) { return isalpha((unsigned char) c); } static inline int is_varsymbol1(char c) { return isalnum((unsigned char) c) || (c == '_'); } #define next_event() \ do { \ c = fgetc(file); \ if (c == EOF && !feof(file)) \ goto s_ioe; \ ++r; \ if (i == N) \ { \ buf = flint_realloc(buf, N = 2*N); \ } \ buf[i++] = c; \ } while (0) #define add_coeff() \ do { \ fmpz_set_mpz(f_coeff, z_coeff); \ fmpz_poly_fit_length(poly, exp + 1); \ fmpz_add(poly->coeffs + exp, poly->coeffs + exp, f_coeff); \ if (poly->length < exp + 1) \ poly->length = exp + 1; \ } while (0) int fmpz_poly_fread_pretty(FILE *file, fmpz_poly_t poly, char **x) { /* var - variable name buf - buffer of size N, at write position i, with c == buf[i-1] z_coeff - mpz_t for the coefficient, f_coeff is the fmpz_t version z_exp - mpz_t for the exponent, exp is the slong version r - return value */ char *var = NULL; char c, *buf; int i, N; fmpz_t f_coeff; mpz_t z_coeff, z_exp; slong exp; int r = 0; fmpz_poly_zero(poly); if (poly->alloc) flint_mpn_zero((mp_ptr) poly->coeffs, poly->alloc); i = 0; N = 80; buf = flint_malloc(N); fmpz_init(f_coeff); mpz_init(z_coeff); mpz_init(z_exp); /* s_0 : */ next_event(); if (c == '-') goto s_1; if (isdigit((unsigned char) c)) goto s_2; if (is_varsymbol0(c)) { flint_mpz_set_si(z_coeff, 1); goto s_3; } goto s_parse_error; s_1 : next_event(); if (isdigit((unsigned char) c)) goto s_2; if (is_varsymbol0(c)) { if (i == 1) flint_mpz_set_si(z_coeff, 1); else /* i == 2 */ { flint_mpz_set_si(z_coeff, -1); buf[0] = c; i = 1; } goto s_3; } goto s_parse_error; s_2 : next_event(); if (isdigit((unsigned char) c)) goto s_2; if (c == '*') { buf[i-1] = '\0'; mpz_set_str(z_coeff, buf, 10); i = 0; goto s_4; } { buf[i-1] = '\0'; mpz_set_str(z_coeff, buf, 10); exp = 0; add_coeff(); if (c == '+' || c == '-') { i = 0; if (c == '-') buf[i++] = '-'; goto s_1; } else goto s_end; } s_3 : next_event(); if (is_varsymbol1(c)) goto s_3; { buf[i-1] = '\0'; if (var) { if (strcmp(buf, var)) /* Parse error */ goto s_parse_error; } else { var = flint_malloc(i); strcpy(var, buf); } if (c == '^') { i = 0; goto s_5; } else if (c == '+' || c == '-') { exp = 1; add_coeff(); i = 0; if (c == '-') buf[i++] = '-'; goto s_1; } else { exp = 1; add_coeff(); goto s_end; } } s_4 : next_event(); if (is_varsymbol0(c)) goto s_3; goto s_parse_error; s_5 : next_event(); if (isdigit((unsigned char) c)) goto s_6; goto s_parse_error; s_6 : next_event(); if (isdigit((unsigned char) c)) goto s_6; { buf[i-1] = '\0'; mpz_set_str(z_exp, buf, 10); if (!mpz_fits_slong_p(z_exp)) { goto s_parse_error; } exp = flint_mpz_get_si(z_exp); add_coeff(); if (c == '+' || c == '-') { i = 0; if (c == '-') buf[i++] = '-'; goto s_1; } else goto s_end; } s_parse_error : r = -2; goto s_end; s_ioe : r = -1; goto s_end; s_end : _fmpz_poly_normalise(poly); if (var) *x = var; else { *x = flint_malloc(1); **x = '\0'; } fmpz_clear(f_coeff); mpz_clear(z_coeff); mpz_clear(z_exp); flint_free(buf); return r; } #undef next_event #undef add_coeff int fmpz_poly_read(fmpz_poly_t poly) { return fmpz_poly_fread(stdin, poly); } int fmpz_poly_read_pretty(fmpz_poly_t poly, char **x) { return fmpz_poly_fread_pretty(stdin, poly, x); } /* debugging ******************************************************************/ void fmpz_poly_debug(const fmpz_poly_t poly) { flint_printf("(alloc = %wd, length = %wd, vec = ", poly->alloc, poly->length); if (poly->coeffs) { flint_printf("{"); _fmpz_vec_print(poly->coeffs, poly->alloc); flint_printf("}"); } else { flint_printf("NULL"); } flint_printf(")"); fflush(stdout); } flint-3.1.3/src/fmpz_poly/is_cyclotomic.c000066400000000000000000000047251461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" ulong _fmpz_poly_is_cyclotomic(const fmpz * poly, slong len) { ulong * phi; ulong p, q, N1, N2; slong i, d; ulong res; double U; fmpz_poly_t tmp; d = len - 1; if (d < 1) return 0; if (d == 1) { if (fmpz_is_one(poly + 1)) { if (fmpz_is_one(poly)) return 2; if (fmpz_equal_si(poly, -1)) return 1; } return 0; } if (d % 2 != 0) return 0; if (!fmpz_is_one(poly)) return 0; /* Rule out non-palindromes */ for (i = 0; i < d / 2; i++) { if (!fmpz_equal(poly + i, poly + d - i)) return 0; } /* Compute inverse image of the totient function to find candidate indices of the cyclotomic polynomial */ /* Determine lower and upper bounds [N1, N2) */ U = d; for (p = 2; p <= d; p++) if (d % (p - 1) == 0 && n_is_prime(p)) U = (U * p) / (p - 1); N1 = d + 1; N2 = U + 3; /* +3 as safety for possible floating-point rounding */ res = 0; phi = flint_malloc(N2 * sizeof(ulong)); fmpz_poly_init(tmp); for (i = 0; i < N2; i++) phi[i] = i; for (p = 2; p < N2; p++) { if (phi[p] == p) { phi[p] = p - 1; for (q = 2 * p; q < N2; q += p) phi[q] = (phi[q] / p) * (p - 1); } } for (i = N1; i < N2 && !res; i++) { if (phi[i] == d) { /* todo: we could avoid O(len) overhead by computing the factorisation of phi and calling _fmpz_poly_cyclotomic, checking only the deflated polynomial */ fmpz_poly_cyclotomic(tmp, i); if (tmp->length == len && _fmpz_vec_equal(poly, tmp->coeffs, len)) res = i; } } flint_free(phi); fmpz_poly_clear(tmp); return res; } ulong fmpz_poly_is_cyclotomic(const fmpz_poly_t poly) { return _fmpz_poly_is_cyclotomic(poly->coeffs, poly->length); } flint-3.1.3/src/fmpz_poly/is_one.c000066400000000000000000000011321461254215100170560ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_is_one(const fmpz *poly, slong len) { return (len > 0 && fmpz_is_one(poly) && _fmpz_vec_is_zero(poly + 1, len - 1)); } flint-3.1.3/src/fmpz_poly/is_squarefree.c000066400000000000000000000024651461254215100204510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_is_squarefree(const fmpz * poly, slong len) { if (len < 3) { return 1; } else if (len == 3) { int ans; fmpz_t lhs, rhs; fmpz_init(lhs); fmpz_init(rhs); fmpz_mul(lhs, poly + 1, poly + 1); fmpz_mul(rhs, poly, poly + 2); fmpz_mul_ui(rhs, rhs, 4); ans = !fmpz_equal(lhs, rhs); fmpz_clear(lhs); fmpz_clear(rhs); return ans; } else { int ans; fmpz * w = _fmpz_vec_init(2 * len); _fmpz_poly_derivative(w, poly, len); _fmpz_poly_gcd(w + len, poly, len, w, len - WORD(1)); ans = _fmpz_vec_is_zero(w + len + 1, len - 2); _fmpz_vec_clear(w, 2 * len); return ans; } } int fmpz_poly_is_squarefree(const fmpz_poly_t poly) { return _fmpz_poly_is_squarefree(poly->coeffs, poly->length); } flint-3.1.3/src/fmpz_poly/lcm.c000066400000000000000000000043561461254215100163700ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_lcm(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { fmpz *W; slong lenW = len2; W = _fmpz_vec_init(len2); _fmpz_poly_mul(res, poly1, len1, poly2, len2); _fmpz_poly_gcd(W, poly1, len1, poly2, len2); FMPZ_VEC_NORM(W, lenW); if (lenW == 1) { if (fmpz_sgn(res + (len1 + len2 - 1 - 1)) < 0) fmpz_neg(W + 0, W + 0); _fmpz_vec_scalar_divexact_fmpz(res, res, len1 + len2 - 1, W + 0); } else { fmpz *V; slong lenV = len1 + len2 - lenW; V = _fmpz_vec_init(lenV); _fmpz_poly_divexact(V, res, len1 + len2 - 1, W, lenW); if (fmpz_sgn(V + (lenV - 1)) > 0) _fmpz_vec_set(res, V, lenV); else _fmpz_vec_neg(res, V, lenV); _fmpz_vec_zero(res + lenV, len1 + len2 - 1 - lenV); _fmpz_vec_clear(V, lenV); } _fmpz_vec_clear(W, len2); } void fmpz_poly_lcm(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong len1 = poly1->length; slong len2 = poly2->length; if (len1 == 0 || len2 == 0) { fmpz_poly_zero(res); return; } if (res == poly1 || res == poly2) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_lcm(t, poly1, poly2); fmpz_poly_swap(res, t); fmpz_poly_clear(t); return; } fmpz_poly_fit_length(res, len1 + len2 - 1); _fmpz_poly_set_length(res, len1 + len2 - 1); if (len1 >= len2) { _fmpz_poly_lcm(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); } else { _fmpz_poly_lcm(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1); } _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/legendre_pt.c000066400000000000000000000023511461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_legendre_pt(fmpz * coeffs, ulong n) { fmpz_t c; ulong k, facnp, facnm; if (n == 0) { fmpz_one(coeffs); return; } if (n == 1) { fmpz_set_si(coeffs, -1); fmpz_set_ui(coeffs + 1, 2); return; } fmpz_init(c); fmpz_one(c); if (n%2 == 1) fmpz_neg(c, c); facnp = n; facnm = n+1; fmpz_set(coeffs, c); for (k = 1; k<=n; k++) { ++facnp; --facnm; fmpz_mul2_uiui(c, c, facnp, facnm); fmpz_divexact2_uiui(c, c, k, k); fmpz_neg(c, c); fmpz_set(coeffs + k, c); } fmpz_clear(c); } void fmpz_poly_legendre_pt(fmpz_poly_t poly, ulong n) { fmpz_poly_fit_length(poly, n + 1); _fmpz_poly_legendre_pt(poly->coeffs, n); _fmpz_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpz_poly/monomial_to_newton.c000066400000000000000000000012141461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_monomial_to_newton(fmpz * poly, const fmpz * roots, slong n) { slong i, j; for (i = 0; i < n - 1; i++) for (j = n - 2; j >= i; j--) fmpz_addmul(poly + j, poly + j + 1, roots + i); } flint-3.1.3/src/fmpz_poly/mul.c000066400000000000000000000137571461254215100164170ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #ifdef FLINT_HAVE_FFT_SMALL #include "fft_small.h" #endif void _fmpz_poly_mul_tiny1(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong i, j, c; _fmpz_vec_zero(res, len1 + len2 - 1); for (i = 0; i < len1; i++) { c = poly1[i]; if (c != 0) { for (j = 0; j < len2; j++) res[i + j] += c * poly2[j]; } } } void _fmpz_poly_mul_tiny2(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong i, j, k, c, d; mp_limb_t hi, lo; mp_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(2 * (len1 + len2 - 1) * sizeof(mp_limb_t)); flint_mpn_zero(tmp, 2 * (len1 + len2 - 1)); for (i = 0; i < len1; i++) { c = poly1[i]; if (c != 0) { for (j = 0; j < len2; j++) { k = i + j; d = poly2[j]; if (d != 0) { smul_ppmm(hi, lo, c, d); add_ssaaaa(tmp[2 * k + 1], tmp[2 * k], tmp[2 * k + 1], tmp[2 * k], hi, lo); } } } } for (i = 0; i < len1 + len2 - 1; i++) { lo = tmp[2 * i]; hi = tmp[2 * i + 1]; if (((mp_limb_signed_t) hi) >= 0) { fmpz_set_uiui(res + i, hi, lo); } else { sub_ddmmss(hi, lo, 0, 0, hi, lo); fmpz_neg_uiui(res + i, hi, lo); } } TMP_END; return; } void _fmpz_poly_mul(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong bits1, bits2, rbits; if (len2 == 1) { _fmpz_vec_scalar_mul_fmpz(res, poly1, len1, poly2); return; } if (poly1 == poly2 && len1 == len2) { _fmpz_poly_sqr(res, poly1, len1); return; } bits1 = _fmpz_vec_max_bits(poly1, len1); bits2 = _fmpz_vec_max_bits(poly2, len2); bits1 = FLINT_ABS(bits1); bits2 = FLINT_ABS(bits2); #ifdef FLINT_HAVE_FFT_SMALL if (len2 >= 80 && (bits1 + bits2 <= 40 || bits1 + bits2 >= 128 || len2 >= 100)) if (_fmpz_poly_mul_mid_default_mpn_ctx(res, 0, len1 + len2 - 1, poly1, len1, poly2, len2)) return; #endif if (bits1 <= SMALL_FMPZ_BITCOUNT_MAX && bits2 <= SMALL_FMPZ_BITCOUNT_MAX && (len2 < 40 + (bits1 + bits2) / 2 || len1 < 70 + (bits1 + bits2) / 2)) { rbits = bits1 + bits2 + FLINT_BIT_COUNT(len2); if (rbits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_poly_mul_tiny1(res, poly1, len1, poly2, len2); return; } else if (rbits <= 2 * FLINT_BITS - 1) { _fmpz_poly_mul_tiny2(res, poly1, len1, poly2, len2); return; } } #ifdef FLINT_HAVE_FFT_SMALL if (len2 <= 6 && FLINT_MIN(bits1, bits2) <= 5000) _fmpz_poly_mul_classical(res, poly1, len1, poly2, len2); else if (len2 <= 4 || (len2 <= 8 && bits1 + bits2 >= 1500 && bits1 + bits2 <= 10000)) _fmpz_poly_mul_karatsuba(res, poly1, len1, poly2, len2); else if /* The fft_small-based KS is so efficient that SS currently only wins in a specific medium-size region and for huge products when using many threads. */ ((len2 >= 8 && len2 <= 75 && bits1 + bits2 >= 800 && bits1 + bits2 <= 4000) || (len1 + len2 >= 5000 && bits1 + bits2 >= 5000 + (len1 + len2) / 10 && flint_get_num_threads() >= 4)) _fmpz_poly_mul_SS(res, poly1, len1, poly2, len2); else _fmpz_poly_mul_KS(res, poly1, len1, poly2, len2); #else if (len2 < 7) { _fmpz_poly_mul_classical(res, poly1, len1, poly2, len2); } else { mp_size_t limbs1, limbs2; limbs1 = (bits1 + FLINT_BITS - 1) / FLINT_BITS; limbs2 = (bits2 + FLINT_BITS - 1) / FLINT_BITS; if (len1 < 16 && (limbs1 > 12 || limbs2 > 12)) _fmpz_poly_mul_karatsuba(res, poly1, len1, poly2, len2); else if (limbs1 + limbs2 <= 8) _fmpz_poly_mul_KS(res, poly1, len1, poly2, len2); else if ((limbs1+limbs2)/2048 > len1 + len2) _fmpz_poly_mul_KS(res, poly1, len1, poly2, len2); else if ((limbs1 + limbs2)*FLINT_BITS*4 < len1 + len2) _fmpz_poly_mul_KS(res, poly1, len1, poly2, len2); else _fmpz_poly_mul_SS(res, poly1, len1, poly2, len2); } #endif } void fmpz_poly_mul(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong len1 = poly1->length; slong len2 = poly2->length; slong rlen; if (len1 == 0 || len2 == 0) { fmpz_poly_zero(res); return; } rlen = len1 + len2 - 1; if (res == poly1 || res == poly2) { fmpz_poly_t t; fmpz_poly_init2(t, rlen); if (len1 >= len2) _fmpz_poly_mul(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); else _fmpz_poly_mul(t->coeffs, poly2->coeffs, len2, poly1->coeffs, len1); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(res, rlen); if (len1 >= len2) _fmpz_poly_mul(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); else _fmpz_poly_mul(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1); } _fmpz_poly_set_length(res, rlen); } flint-3.1.3/src/fmpz_poly/mul_KS.c000066400000000000000000000066171461254215100170110ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_mul_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { const slong in1_len = len1, in2_len = len2; int neg1, neg2; slong limbs1, limbs2, loglen; slong bits1, bits2, bits; mp_limb_t *arr1, *arr2, *arr3; slong sign = 0; FMPZ_VEC_NORM(poly1, len1); FMPZ_VEC_NORM(poly2, len2); if (!len1 | !len2) { if (in1_len + in2_len - 1 > 0) _fmpz_vec_zero(res, in1_len + in2_len - 1); return; } neg1 = (fmpz_sgn(poly1 + len1 - 1) > 0) ? 0 : -1; neg2 = (fmpz_sgn(poly2 + len2 - 1) > 0) ? 0 : -1; bits1 = _fmpz_vec_max_bits(poly1, len1); if (bits1 < 0) { sign = 1; bits1 = -bits1; } if (poly1 != poly2) { bits2 = _fmpz_vec_max_bits(poly2, len2); if (bits2 < 0) { sign = 1; bits2 = -bits2; } } else bits2 = bits1; loglen = FLINT_BIT_COUNT(FLINT_MIN(len1, len2)); bits = bits1 + bits2 + loglen + sign; limbs1 = (bits * len1 - 1) / FLINT_BITS + 1; limbs2 = (bits * len2 - 1) / FLINT_BITS + 1; if (poly1 == poly2) { arr1 = (mp_limb_t *) flint_calloc(limbs1, sizeof(mp_limb_t)); arr2 = arr1; _fmpz_poly_bit_pack(arr1, poly1, len1, bits, neg1); } else { arr1 = (mp_limb_t *) flint_calloc(limbs1 + limbs2, sizeof(mp_limb_t)); arr2 = arr1 + limbs1; _fmpz_poly_bit_pack(arr1, poly1, len1, bits, neg1); _fmpz_poly_bit_pack(arr2, poly2, len2, bits, neg2); } arr3 = (mp_limb_t *) flint_malloc((limbs1 + limbs2) * sizeof(mp_limb_t)); if (arr1 == arr2 && limbs1 == limbs2) flint_mpn_sqr(arr3, arr1, limbs1); else if (limbs1 > limbs2) flint_mpn_mul(arr3, arr1, limbs1, arr2, limbs2); else flint_mpn_mul(arr3, arr2, limbs2, arr1, limbs1); if (sign) _fmpz_poly_bit_unpack(res, len1 + len2 - 1, arr3, bits, neg1 ^ neg2); else _fmpz_poly_bit_unpack_unsigned(res, len1 + len2 - 1, arr3, bits); if ((len1 < in1_len) | (len2 < in2_len)) _fmpz_vec_zero(res + (len1 + len2 - 1), (in1_len - len1) + (in2_len - len2)); flint_free(arr1); flint_free(arr3); } void fmpz_poly_mul_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; const slong rlen = len1 + len2 - 1; if (len1 == 0 || len2 == 0) { fmpz_poly_zero(res); } else { fmpz_poly_fit_length(res, rlen); if (len1 >= len2) _fmpz_poly_mul_KS(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); else _fmpz_poly_mul_KS(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1); _fmpz_poly_set_length(res, rlen); } } flint-3.1.3/src/fmpz_poly/mul_SS.c000066400000000000000000000026051461254215100170120ustar00rootroot00000000000000/* Copyright (C) 2008-2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fft.h" #include "fft_tuning.h" void _fmpz_poly_mul_SS(fmpz *output, const fmpz *input1, slong len1, const fmpz *input2, slong len2) { const slong rlen = len1 + len2 - 1; _fmpz_poly_mullow_SS(output, input1, len1, input2, len2, rlen); } void fmpz_poly_mul_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { const slong len1 = poly1->length, len2 = poly2->length; slong rlen; if (len1 == 0 || len2 == 0) { fmpz_poly_zero(res); return; } if (len1 <= 2 || len2 <= 2) { fmpz_poly_mul_classical(res, poly1, poly2); return; } rlen = len1 + len2 - 1; fmpz_poly_fit_length(res, rlen); if (len1 >= len2) _fmpz_poly_mul_SS(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); else _fmpz_poly_mul_SS(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1); _fmpz_poly_set_length(res, rlen); } flint-3.1.3/src/fmpz_poly/mul_classical.c000066400000000000000000000042771461254215100204320ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong i, top1, top2; if (len1 == 1 && len2 == 1) { fmpz_mul(res, poly1, poly2); return; } if (len1 == 1) { _fmpz_vec_scalar_mul_fmpz(res, poly2, len2, poly1); return; } if (len2 == 1) { _fmpz_vec_scalar_mul_fmpz(res, poly1, len1, poly2); return; } fmpz_mul(res, poly1, poly2); for (i = 1; i < len1 + len2 - 2; i++) { top1 = FLINT_MIN(len1 - 1, i); top2 = FLINT_MIN(len2 - 1, i); _fmpz_vec_dot_general(res + i, NULL, 0, poly1 + i - top2, poly2 + i - top1, 1, top1 + top2 - i + 1); } fmpz_mul(res + len1 + len2 - 2, poly1 + len1 - 1, poly2 + len2 - 1); } void fmpz_poly_mul_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { fmpz_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { fmpz_poly_t temp; fmpz_poly_init2(temp, len_out); _fmpz_poly_mul_classical(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); fmpz_poly_swap(res, temp); fmpz_poly_clear(temp); } else { fmpz_poly_fit_length(res, len_out); _fmpz_poly_mul_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); } _fmpz_poly_set_length(res, len_out); } flint-3.1.3/src/fmpz_poly/mul_karatsuba.c000066400000000000000000000120541461254215100204410ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Implements karatsuba multiplication. There is no basecase crossover, so this is only efficient when the coefficients are large (the main usage case). The algorithm is the "odd/even" Karatsuba algorithm. Let f(x) = f1(x^2) + x*f2(x^2), g(x) = g1(x^2) + x*g2(x^2), then f(x)*g(x) = f1(x^2)*g1(x^2) + x^2*f2(x^2)*g2(x^2) + x*((f1(x^2) + f2(x^2))*(g1(x^2) + g2(x^2)) - f1(x^2)*g1(x^2) - f2(x^2)*g2(x^2)). Thus only three multiplications are performed (and numerous additions and subtractions). Instead of working with polynomials with the usual ordering, reverse binary ordering is used, i.e. for length 2^3 (zero padded) terms of degree 110 and 011 in binary are swapped, etc. The advantage of working in this format is that the first half of the coefficients of f will be the coefficients of f1, and the second half, those of f2, etc. This applies right down the recursion. The only tricky bit is when multiplying by x. One must undo the revbin to shift by one term to the left. */ void _fmpz_poly_mul_kara_recursive(fmpz * out, fmpz * rev1, fmpz * rev2, fmpz * temp, slong bits); /* Switches the coefficients of poly in of length len into a poly out of length 2^bits. */ void revbin1(fmpz * out, const fmpz * in, slong len, slong bits) { slong i; for (i = 0; i < len; i++) out[n_revbin(i, bits)] = in[i]; } /* Switches the coefficients of poly in of length 2^bits into a poly out of length len. */ void revbin2(fmpz * out, const fmpz * in, slong len, slong bits) { slong i; for (i = 0; i < len; i++) out[i] = in[n_revbin(i, bits)]; } /* in1 += x*in2 assuming both in1 and in2 are revbin'd. */ void _fmpz_vec_add_rev(fmpz * in1, fmpz * in2, slong bits) { slong i; for (i = 0; i < (WORD(1) << bits) - 1; i++) { slong j = n_revbin(n_revbin(i, bits) + 1, bits); fmpz_add(in1 + j, in1 + j, in2 + i); } } /* Recursive Karatsuba assuming polynomials are in revbin format. Assumes rev1 and rev2 are both of length 2^bits and that temp has space for 2^bits coefficients. */ void _fmpz_poly_mul_kara_recursive(fmpz * out, fmpz * rev1, fmpz * rev2, fmpz * temp, slong bits) { slong length = (WORD(1) << bits); slong m = length / 2; if (length == 1) { fmpz_mul(out, rev1, rev2); fmpz_zero(out + 1); return; } _fmpz_vec_add(temp, rev1, rev1 + m, m); _fmpz_vec_add(temp + m, rev2, rev2 + m, m); _fmpz_poly_mul_kara_recursive(out, rev1, rev2, temp + 2 * m, bits - 1); _fmpz_poly_mul_kara_recursive(out + length, temp, temp + m, temp + 2 * m, bits - 1); _fmpz_poly_mul_kara_recursive(temp, rev1 + m, rev2 + m, temp + 2 * m, bits - 1); _fmpz_vec_sub(out + length, out + length, out, length); _fmpz_vec_sub(out + length, out + length, temp, length); _fmpz_vec_add_rev(out, temp, bits); } /* Assumes poly1 and poly2 are not length 0 and len1 >= len2. */ void _fmpz_poly_mul_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { fmpz *rev1, *rev2, *out, *temp; slong length, loglen = 0; if (len1 == 1) { fmpz_mul(res, poly1, poly2); return; } while ((WORD(1) << loglen) < len1) loglen++; length = (WORD(1) << loglen); rev1 = (fmpz *) flint_calloc(4 * length, sizeof(fmpz *)); rev2 = rev1 + length; out = rev1 + 2 * length; temp = _fmpz_vec_init(2 * length); revbin1(rev1, poly1, len1, loglen); revbin1(rev2, poly2, len2, loglen); _fmpz_poly_mul_kara_recursive(out, rev1, rev2, temp, loglen); _fmpz_vec_zero(res, len1 + len2 - 1); revbin2(res, out, len1 + len2 - 1, loglen + 1); _fmpz_vec_clear(temp, 2 * length); flint_free(rev1); } void fmpz_poly_mul_karatsuba(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { fmpz_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; fmpz_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _fmpz_poly_mul_karatsuba(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); else _fmpz_poly_mul_karatsuba(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length); _fmpz_poly_set_length(res, len_out); } flint-3.1.3/src/fmpz_poly/mulhigh.c000066400000000000000000000025711461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_mulhigh(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start) { mp_size_t limbs1 = _fmpz_vec_max_limbs(poly1, len1); mp_size_t limbs2 = _fmpz_vec_max_limbs(poly2, len2); mp_size_t limbsx = FLINT_MAX(limbs1, limbs2); if (start < 5) { _fmpz_poly_mulhigh_classical(res, poly1, len1, poly2, len2, start); return; } if (limbsx > 4 && start < 17 && len1 == start + 1 && len2 == start + 1) _fmpz_poly_mulhigh_karatsuba_n(res, poly1, poly2, start + 1); else if (limbs1 + limbs2 <= 8) _fmpz_poly_mul_KS(res, poly1, len1, poly2, len2); else if ((limbs1 + limbs2)/2048 > len1 + len2) _fmpz_poly_mul_KS(res, poly1, len1, poly2, len2); else if ((limbs1 + limbs2)*FLINT_BITS*4 < len1 + len2) _fmpz_poly_mul_KS(res, poly1, len1, poly2, len2); else _fmpz_poly_mul_SS(res, poly1, len1, poly2, len2); } flint-3.1.3/src/fmpz_poly/mulhigh_classical.c000066400000000000000000000052231461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start) { _fmpz_vec_zero(res, start); if (len1 == 1 && len2 == 1) /* Special case if the length of both inputs is 1 */ { if (start == 0) fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { slong i, m, n; /* Set res[i] = poly1[i]*poly2[0] */ if (start < len1) _fmpz_vec_scalar_mul_fmpz(res + start, poly1 + start, len1 - start, poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ m = FLINT_MAX(len1 - 1, start); _fmpz_vec_scalar_mul_fmpz(res + m, poly2 + m - len1 + 1, len2 - 1 + len1 - m, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ m = FLINT_MAX(start, len2 - 1); for (i = m - len2 + 1; i < len1 - 1; i++) { n = FLINT_MAX(i + 1, start); _fmpz_vec_scalar_addmul_fmpz(res + n, poly2 + n - i, len2 + i - n, poly1 + i); } } } void fmpz_poly_mulhigh_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong start) { slong len_out = poly1->length + poly2->length - 1; if (poly1->length == 0 || poly2->length == 0 || start >= len_out) { fmpz_poly_zero(res); return; } if (res == poly1 || res == poly2) { fmpz_poly_t temp; fmpz_poly_init2(temp, len_out); _fmpz_poly_mulhigh_classical(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, start); fmpz_poly_swap(res, temp); fmpz_poly_clear(temp); } else { fmpz_poly_fit_length(res, len_out); _fmpz_poly_mulhigh_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, start); } _fmpz_poly_set_length(res, len_out); } flint-3.1.3/src/fmpz_poly/mulhigh_karatsuba_n.c000066400000000000000000000100571461254215100216170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_mulhigh_kara_recursive(fmpz * out, const fmpz * pol1, const fmpz * pol2, fmpz * temp, slong length); /* Multiplication using truncated karatsuba. Below length 7, classical truncated multiplication is always theoretically faster, so we switch to that as the basecase. Above that we use the ordinary (left/right) karatsuba identity and recursively do one full karatsuba multiplication and two truncated karatsuba multiplications. */ void _fmpz_poly_mulhigh_kara_recursive(fmpz * out, const fmpz * pol1, const fmpz * pol2, fmpz * temp, slong length) { slong m1 = length / 2; slong m2 = length - m1; int odd = (length & 1); if (length <= 6) { _fmpz_poly_mulhigh_classical(out, pol1, length, pol2, length, length - 1); return; } _fmpz_vec_add(out, pol1, pol1 + m1, m1); if (odd) fmpz_set(out + m1, pol1 + 2 * m1); _fmpz_vec_add(out + m2, pol2, pol2 + m1, m1); if (odd) fmpz_set(out + m2 + m1, pol2 + 2 * m1); _fmpz_poly_mulhigh_kara_recursive(temp, out, out + m2, temp + 2 * m2, m2); _fmpz_poly_mul_karatsuba(out + 2 * m1, pol1 + m1, m2, pol2 + m1, m2); fmpz_zero(out + 2 * m1 - 1); _fmpz_poly_mulhigh_kara_recursive(out, pol1, pol2, temp + 2 * m2, m1); _fmpz_vec_sub(temp + m2 - 1, temp + m2 - 1, out + m2 - 1, 2 * m1 - m2); _fmpz_vec_sub(temp + m2 - 1, temp + m2 - 1, out + 2 * m1 + m2 - 1, m2); _fmpz_vec_add(out + length - 1, out + length - 1, temp + m2 - 1, m2); _fmpz_vec_zero(out, length - 1); } /* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mulhigh_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong len) { fmpz *temp; slong length, loglen = 0; if (len == 1) { fmpz_mul(res, poly1, poly2); return; } while ((WORD(1) << loglen) < len) loglen++; length = (WORD(1) << loglen); temp = _fmpz_vec_init(2 * length); _fmpz_poly_mulhigh_kara_recursive(res, poly1, poly2, temp, len); _fmpz_vec_clear(temp, 2 * length); } void fmpz_poly_mulhigh_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong len) { slong lenr = poly1->length + poly2->length - 1; int clear1 = 0, clear2 = 0; fmpz *pol1, *pol2; if (poly1->length == 0 || poly2->length == 0 || len - 1 >= lenr) { fmpz_poly_zero(res); return; } if (poly1->length < len) { pol1 = (fmpz *) flint_calloc(len, sizeof(fmpz)); memcpy(pol1, poly1->coeffs, poly1->length * sizeof(fmpz)); clear1 = 1; } else pol1 = poly1->coeffs; if (poly2->length < len) { pol2 = (fmpz *) flint_calloc(len, sizeof(fmpz)); memcpy(pol2, poly2->coeffs, poly2->length * sizeof(fmpz)); clear2 = 1; } else pol2 = poly2->coeffs; if (res != poly1 && res != poly2) { fmpz_poly_fit_length(res, 2 * len - 1); _fmpz_poly_mulhigh_karatsuba_n(res->coeffs, pol1, pol2, len); _fmpz_poly_set_length(res, lenr); } else { fmpz_poly_t temp; fmpz_poly_init2(temp, 2 * len - 1); _fmpz_poly_mulhigh_karatsuba_n(temp->coeffs, pol1, pol2, len); _fmpz_poly_set_length(temp, lenr); fmpz_poly_swap(temp, res); fmpz_poly_clear(temp); } if (clear1) flint_free(pol1); if (clear2) flint_free(pol2); } flint-3.1.3/src/fmpz_poly/mulhigh_n.c000066400000000000000000000027041461254215100175620ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_mulhigh_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { mp_size_t limbs1 = _fmpz_vec_max_limbs(poly1->coeffs, poly1->length); mp_size_t limbs2 = _fmpz_vec_max_limbs(poly2->coeffs, poly2->length); mp_size_t len1 = poly1->length; mp_size_t len2 = poly2->length; mp_size_t limbsx = FLINT_MAX(limbs1, limbs2); if (n == 0) { fmpz_poly_zero(res); return; } if (n < 4) { fmpz_poly_mulhigh_classical(res, poly1, poly2, n - 1); return; } if ((limbsx > 4) && (n < 16) && poly1->length <= n && poly2->length <= n) fmpz_poly_mulhigh_karatsuba_n(res, poly1, poly2, n); else if (limbs1 + limbs2 <= 8) fmpz_poly_mul_KS(res, poly1, poly2); else if ((limbs1+limbs2)/2048 > len1 + len2) fmpz_poly_mul_KS(res, poly1, poly2); else if ((limbs1 + limbs2)*FLINT_BITS*4 < len1 + len2) fmpz_poly_mul_KS(res, poly1, poly2); else fmpz_poly_mul_SS(res, poly1, poly2); } flint-3.1.3/src/fmpz_poly/mullow.c000066400000000000000000000140001461254215100171170ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #ifdef FLINT_HAVE_FFT_SMALL #include "fft_small.h" #endif void _fmpz_poly_mullow_tiny1(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { slong i, j, c; _fmpz_vec_zero(res, n); for (i = 0; i < len1; i++) { c = poly1[i]; if (c != 0) { for (j = 0; j < FLINT_MIN(len2, n - i); j++) res[i + j] += c * poly2[j]; } } } void _fmpz_poly_mullow_tiny2(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { slong i, j, k, c, d; mp_limb_t hi, lo; mp_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(2 * n * sizeof(mp_limb_t)); flint_mpn_zero(tmp, 2 * n); for (i = 0; i < len1; i++) { c = poly1[i]; if (c != 0) { for (j = 0; j < FLINT_MIN(len2, n - i); j++) { k = i + j; d = poly2[j]; if (d != 0) { smul_ppmm(hi, lo, c, d); add_ssaaaa(tmp[2 * k + 1], tmp[2 * k], tmp[2 * k + 1], tmp[2 * k], hi, lo); } } } } for (i = 0; i < n; i++) { lo = tmp[2 * i]; hi = tmp[2 * i + 1]; if (((mp_limb_signed_t) hi) >= 0) { fmpz_set_uiui(res + i, hi, lo); } else { sub_ddmmss(hi, lo, 0, 0, hi, lo); fmpz_neg_uiui(res + i, hi, lo); } } TMP_END; return; } void _fmpz_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { slong bits1, bits2, rbits; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); FLINT_ASSERT(n > 0); FLINT_ASSERT(len1 > 0); FLINT_ASSERT(len2 > 0); FLINT_ASSERT(n <= len1 + len2 - 1); if (len2 == 1) { _fmpz_vec_scalar_mul_fmpz(res, poly1, len1, poly2); return; } if (len1 < len2) { _fmpz_poly_mullow(res, poly2, len2, poly1, len1, n); return; } if (poly1 == poly2 && len1 == len2) { _fmpz_poly_sqrlow(res, poly1, len1, n); return; } bits1 = _fmpz_vec_max_bits(poly1, len1); bits2 = _fmpz_vec_max_bits(poly2, len2); bits1 = FLINT_ABS(bits1); bits2 = FLINT_ABS(bits2); #ifdef FLINT_HAVE_FFT_SMALL if (len2 >= 100 && (bits1 + bits2 <= 40 || bits1 + bits2 >= 128 || len2 >= 200)) if (_fmpz_poly_mul_mid_default_mpn_ctx(res, 0, n, poly1, len1, poly2, len2)) return; #endif if (bits1 <= SMALL_FMPZ_BITCOUNT_MAX && bits2 <= SMALL_FMPZ_BITCOUNT_MAX && (len2 < 50 || (4 * len2 >= 3 * n && n < 150 + bits1 + bits2))) { rbits = bits1 + bits2 + FLINT_BIT_COUNT(len2); if (rbits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_poly_mullow_tiny1(res, poly1, len1, poly2, len2, n); return; } else if (rbits <= 2 * FLINT_BITS - 1) { _fmpz_poly_mullow_tiny2(res, poly1, len1, poly2, len2, n); return; } } #ifdef FLINT_HAVE_FFT_SMALL /* same as in mul.c */ if (len2 <= 6 && FLINT_MIN(bits1, bits2) <= 5000) _fmpz_poly_mullow_classical(res, poly1, len1, poly2, len2, n); else if (len2 <= 4 || (len2 <= 8 && bits1 + bits2 >= 1500 && bits1 + bits2 <= 10000)) _fmpz_poly_mullow_karatsuba(res, poly1, len1, poly2, len2, n); else if ((len2 >= 8 && len2 <= 75 && bits1 + bits2 >= 800 && bits1 + bits2 <= 4000) || (len1 + len2 >= 5000 && bits1 + bits2 >= 5000 + (len1 + len2) / 10 && flint_get_num_threads() >= 4)) _fmpz_poly_mullow_SS(res, poly1, len1, poly2, len2, n); else _fmpz_poly_mullow_KS(res, poly1, len1, poly2, len2, n); #else if (len2 < 7) { _fmpz_poly_mullow_classical(res, poly1, len1, poly2, len2, n); } else { mp_size_t limbs1, limbs2; limbs1 = (bits1 + FLINT_BITS - 1) / FLINT_BITS; limbs2 = (bits2 + FLINT_BITS - 1) / FLINT_BITS; if (n < 16 && (limbs1 > 12 || limbs2 > 12)) _fmpz_poly_mullow_karatsuba(res, poly1, len1, poly2, len2, n); else if (limbs1 + limbs2 <= 8) _fmpz_poly_mullow_KS(res, poly1, len1, poly2, len2, n); else if ((limbs1+limbs2)/2048 > len1 + len2) _fmpz_poly_mullow_KS(res, poly1, len1, poly2, len2, n); else if ((limbs1 + limbs2)*FLINT_BITS*4 < len1 + len2) _fmpz_poly_mullow_KS(res, poly1, len1, poly2, len2, n); else _fmpz_poly_mullow_SS(res, poly1, len1, poly2, len2, n); } #endif } void fmpz_poly_mullow(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0 || len2 == 0 || n == 0) { fmpz_poly_zero(res); return; } if (res == poly1 || res == poly2) { fmpz_poly_t t; fmpz_poly_init2(t, n); fmpz_poly_mullow(t, poly1, poly2, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); return; } n = FLINT_MIN(n, len1 + len2 - 1); fmpz_poly_fit_length(res, n); if (len1 >= len2) _fmpz_poly_mullow(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n); else _fmpz_poly_mullow(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, n); _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/mullow_KS.c000066400000000000000000000066571461254215100175370ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_mullow_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { int neg1, neg2; slong limbs1, limbs2, loglen; slong bits1, bits2, bits; mp_limb_t *arr1, *arr2, *arr3; slong sign = 0; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); FMPZ_VEC_NORM(poly1, len1); FMPZ_VEC_NORM(poly2, len2); if (!len1 | !len2) { _fmpz_vec_zero(res, n); return; } neg1 = (fmpz_sgn(poly1 + len1 - 1) > 0) ? 0 : -1; neg2 = (fmpz_sgn(poly2 + len2 - 1) > 0) ? 0 : -1; if (n > len1 + len2 - 1) { _fmpz_vec_zero(res + len1 + len2 - 1, n - (len1 + len2 - 1)); n = len1 + len2 - 1; } bits1 = _fmpz_vec_max_bits(poly1, len1); if (bits1 < 0) { sign = 1; bits1 = -bits1; } if (poly1 != poly2) { bits2 = _fmpz_vec_max_bits(poly2, len2); if (bits2 < 0) { sign = 1; bits2 = -bits2; } } else bits2 = bits1; loglen = FLINT_BIT_COUNT(FLINT_MIN(len1, len2)); bits = bits1 + bits2 + loglen + sign; limbs1 = (bits * len1 - 1) / FLINT_BITS + 1; limbs2 = (bits * len2 - 1) / FLINT_BITS + 1; if (poly1 == poly2) { arr1 = (mp_ptr) flint_calloc(limbs1, sizeof(mp_limb_t)); arr2 = arr1; _fmpz_poly_bit_pack(arr1, poly1, len1, bits, neg1); } else { arr1 = (mp_ptr) flint_calloc(limbs1 + limbs2, sizeof(mp_limb_t)); arr2 = arr1 + limbs1; _fmpz_poly_bit_pack(arr1, poly1, len1, bits, neg1); _fmpz_poly_bit_pack(arr2, poly2, len2, bits, neg2); } arr3 = (mp_ptr) flint_malloc((limbs1 + limbs2) * sizeof(mp_limb_t)); if (arr1 == arr2 && limbs1 == limbs2) flint_mpn_sqr(arr3, arr1, limbs1); else if (limbs1 > limbs2) flint_mpn_mul(arr3, arr1, limbs1, arr2, limbs2); else flint_mpn_mul(arr3, arr2, limbs2, arr1, limbs1); if (sign) _fmpz_poly_bit_unpack(res, n, arr3, bits, neg1 ^ neg2); else _fmpz_poly_bit_unpack_unsigned(res, n, arr3, bits); flint_free(arr1); flint_free(arr3); } void fmpz_poly_mullow_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0 || len2 == 0 || n == 0) { fmpz_poly_zero(res); } else { n = FLINT_MIN(n, len1 + len2 - 1); fmpz_poly_fit_length(res, n); if (len1 >= len2) _fmpz_poly_mullow_KS(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n); else _fmpz_poly_mullow_KS(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, n); _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/mullow_SS.c000066400000000000000000000111161461254215100175310ustar00rootroot00000000000000/* Copyright (C) 2008-2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fft.h" #include "fft_tuning.h" void _fmpz_poly_mullow_SS(fmpz * output, const fmpz * input1, slong len1, const fmpz * input2, slong len2, slong trunc) { slong len_out, loglen, loglen2, n; slong output_bits, limbs, size, i; mp_limb_t * ptr, ** t1, ** t2, ** tt, ** s1, ** ii, ** jj; slong bits1, bits2; ulong size1, size2; int sign = 0; int N; TMP_INIT; TMP_START; len1 = FLINT_MIN(len1, trunc); len2 = FLINT_MIN(len2, trunc); len_out = len1 + len2 - 1; loglen = FLINT_CLOG2(len_out); loglen2 = FLINT_CLOG2(len2); n = (WORD(1) << (loglen - 2)); bits1 = _fmpz_vec_max_bits(input1, len1); if (input1 == input2 && len1 == len2) bits2 = bits1; else bits2 = _fmpz_vec_max_bits(input2, len2); size1 = (FLINT_ABS(bits1) + FLINT_BITS - 1) / FLINT_BITS; size2 = (FLINT_ABS(bits2) + FLINT_BITS - 1) / FLINT_BITS; /* Start with an upper bound on the number of bits needed */ output_bits = FLINT_BITS * (size1 + size2) + loglen2 + 1; /* round up for sqrt2 trick */ output_bits = (((output_bits - 1) >> (loglen - 2)) + 1) << (loglen - 2); limbs = (output_bits - 1) / FLINT_BITS + 1; /* initial size of FFT coeffs */ if (limbs > FFT_MULMOD_2EXPP1_CUTOFF) /* can't be worse than next power of 2 limbs */ limbs = (WORD(1) << FLINT_CLOG2(limbs)); size = limbs + 1; /* allocate space for ffts */ N = flint_get_num_threads(); ii = flint_malloc((4*(n + n*size) + 5*size*N)*sizeof(mp_limb_t)); for (i = 0, ptr = (mp_limb_t *) ii + 4*n; i < 4*n; i++, ptr += size) ii[i] = ptr; t1 = TMP_ALLOC(N*sizeof(mp_limb_t *)); t2 = TMP_ALLOC(N*sizeof(mp_limb_t *)); s1 = TMP_ALLOC(N*sizeof(mp_limb_t *)); tt = TMP_ALLOC(N*sizeof(mp_limb_t *)); t1[0] = ptr; t2[0] = t1[0] + size*N; s1[0] = t2[0] + size*N; tt[0] = s1[0] + size*N; for (i = 1; i < N; i++) { t1[i] = t1[i - 1] + size; t2[i] = t2[i - 1] + size; s1[i] = s1[i - 1] + size; tt[i] = tt[i - 1] + 2*size; } if (input1 != input2) { jj = flint_malloc(4*(n + n*size)*sizeof(mp_limb_t)); for (i = 0, ptr = (mp_limb_t *) jj + 4*n; i < 4*n; i++, ptr += size) jj[i] = ptr; } else jj = ii; /* put coefficients into FFT vecs */ _fmpz_vec_get_fft(ii, input1, limbs, len1); for (i = len1; i < 4*n; i++) flint_mpn_zero(ii[i], limbs + 1); if (input1 != input2) { _fmpz_vec_get_fft(jj, input2, limbs, len2); for (i = len2; i < 4*n; i++) flint_mpn_zero(jj[i], limbs + 1); } if (bits1 < WORD(0) || bits2 < WORD(0)) { sign = 1; bits1 = FLINT_ABS(bits1); bits2 = FLINT_ABS(bits2); } /* Recompute the number of bits/limbs now that we know how large everything is */ output_bits = bits1 + bits2 + loglen2 + sign; /* round up output bits for sqrt2 */ output_bits = (((output_bits - 1) >> (loglen - 2)) + 1) << (loglen - 2); limbs = (output_bits - 1) / FLINT_BITS + 1; limbs = fft_adjust_limbs(limbs); /* round up limbs for Nussbaumer */ fft_convolution(ii, jj, loglen - 2, limbs, len_out, t1, t2, s1, tt); _fmpz_vec_set_fft(output, trunc, ii, limbs, sign); /* write output */ flint_free(ii); if (input1 != input2) flint_free(jj); TMP_END; } void fmpz_poly_mullow_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0 || len2 == 0 || n == 0) { fmpz_poly_zero(res); return; } if (len1 <= 2 || len2 <= 2 || n <= 2) { fmpz_poly_mullow_classical(res, poly1, poly2, n); return; } n = FLINT_MIN(n, len1 + len2 - 1); fmpz_poly_fit_length(res, n); if (len1 >= len2) _fmpz_poly_mullow_SS(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n); else _fmpz_poly_mullow_SS(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, n); _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/mullow_SS_precache.c000077500000000000000000000123761461254215100213770ustar00rootroot00000000000000/* Copyright (C) 2008-2011, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fft.h" #include "fft_tuning.h" void fmpz_poly_mul_SS_precache_init(fmpz_poly_mul_precache_t pre, slong len1, slong bits1, const fmpz_poly_t poly2) { slong i, len_out, loglen2; slong output_bits, size; ulong size1, size2; mp_limb_t * ptr; mp_limb_t ** t1, ** t2, ** s1; int N; pre->len2 = poly2->length; pre->bits2 = _fmpz_vec_max_bits(poly2->coeffs, pre->len2); pre->bits2 = FLINT_ABS(pre->bits2); len_out = len1 + pre->len2 - 1; pre->loglen = FLINT_CLOG2(len_out); loglen2 = FLINT_CLOG2(FLINT_MIN(len1, pre->len2)); pre->n = (WORD(1) << (pre->loglen - 2)); size1 = FLINT_ABS(bits1); size1 = (size1 + FLINT_BITS - 1)/FLINT_BITS; size2 = (pre->bits2 + FLINT_BITS - 1)/FLINT_BITS; /* Start with an upper bound on the number of bits needed */ output_bits = FLINT_BITS*(size1 + size2) + loglen2 + 1; /* round up for sqrt2 trick */ output_bits = (((output_bits - 1) >> (pre->loglen - 2)) + 1) << (pre->loglen - 2); pre->limbs = (output_bits - 1) / FLINT_BITS + 1; /* initial size of FFT coeffs */ if (pre->limbs > FFT_MULMOD_2EXPP1_CUTOFF) /* can't be worse than next power of 2 limbs */ pre->limbs = (WORD(1) << FLINT_CLOG2(pre->limbs)); size = pre->limbs + 1; /* allocate space for ffts */ N = flint_get_num_threads(); pre->jj = (mp_limb_t **) flint_malloc((4*(pre->n + pre->n*size) + 3*size*N + 3*N)*sizeof(mp_limb_t)); for (i = 0, ptr = (mp_limb_t *) pre->jj + 4*pre->n; i < 4*pre->n; i++, ptr += size) pre->jj[i] = ptr; t1 = (mp_limb_t **) ptr; t2 = (mp_limb_t **) t1 + N; s1 = (mp_limb_t **) t2 + N; ptr += 3*N; t1[0] = ptr; t2[0] = t1[0] + size*N; s1[0] = t2[0] + size*N; for (i = 1; i < N; i++) { t1[i] = t1[i - 1] + size; t2[i] = t2[i - 1] + size; s1[i] = s1[i - 1] + size; } /* put coefficients into FFT vecs */ _fmpz_vec_get_fft(pre->jj, poly2->coeffs, pre->limbs, pre->len2); for (i = pre->len2; i < 4*pre->n; i++) flint_mpn_zero(pre->jj[i], size); /* Recompute the number of bits/limbs now that we know how large everything is */ output_bits = bits1 + pre->bits2 + loglen2 + 1; /* round up output bits for sqrt2 */ output_bits = (((output_bits - 1) >> (pre->loglen - 2)) + 1) << (pre->loglen - 2); pre->limbs = (output_bits - 1) / FLINT_BITS + 1; pre->limbs = fft_adjust_limbs(pre->limbs); /* round up limbs for Nussbaumer */ fft_precache(pre->jj, pre->loglen - 2, pre->limbs, len_out, t1, t2, s1); fmpz_poly_init(pre->poly2); fmpz_poly_set(pre->poly2, poly2); } void fmpz_poly_mul_precache_clear(fmpz_poly_mul_precache_t pre) { flint_free(pre->jj); fmpz_poly_clear(pre->poly2); } void _fmpz_poly_mullow_SS_precache(fmpz * output, const fmpz * input1, slong len1, fmpz_poly_mul_precache_t pre, slong trunc) { slong len_out; slong size, i; mp_limb_t ** ii, ** t1, ** t2, ** s1, ** tt; mp_limb_t * ptr; int N; len_out = FLINT_MAX(len1 + pre->len2 - 1, 2*pre->n + 1); size = pre->limbs + 1; /* allocate space for ffts */ N = flint_get_num_threads(); ii = (mp_limb_t **) flint_malloc((4*(pre->n + pre->n*size) + 5*size*N + 4*N)*sizeof(mp_limb_t)); for (i = 0, ptr = (mp_limb_t *) ii + 4*pre->n; i < 4*pre->n; i++, ptr += size) ii[i] = ptr; t1 = (mp_limb_t **) ptr; t2 = (mp_limb_t **) t1 + N; s1 = (mp_limb_t **) t2 + N; tt = (mp_limb_t **) s1 + N; ptr += 4*N; t1[0] = ptr; t2[0] = t1[0] + size*N; s1[0] = t2[0] + size*N; tt[0] = s1[0] + size*N; for (i = 1; i < N; i++) { t1[i] = t1[i - 1] + size; t2[i] = t2[i - 1] + size; s1[i] = s1[i - 1] + size; tt[i] = tt[i - 1] + 2*size; } /* put coefficients into FFT vecs */ _fmpz_vec_get_fft(ii, input1, pre->limbs, len1); for (i = len1; i < 4*pre->n; i++) flint_mpn_zero(ii[i], size); fft_convolution_precache(ii, pre->jj, pre->loglen - 2, pre->limbs, len_out, t1, t2, s1, tt); _fmpz_vec_set_fft(output, trunc, ii, pre->limbs, 1); /* write output */ flint_free(ii); } void fmpz_poly_mullow_SS_precache(fmpz_poly_t res, const fmpz_poly_t poly1, fmpz_poly_mul_precache_t pre, slong n) { const slong len1 = poly1->length; if (pre->len2 == 0 || len1 == 0 || n == 0) { fmpz_poly_zero(res); return; } if (pre->len2 <= 2 || len1 <= 2 || n <= 2) { fmpz_poly_mullow_classical(res, poly1, pre->poly2, n); return; } n = FLINT_MIN(n, len1 + pre->len2 - 1); fmpz_poly_fit_length(res, n); _fmpz_poly_mullow_SS_precache(res->coeffs, poly1->coeffs, len1, pre, n); _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/mullow_classical.c000066400000000000000000000044541461254215100211510ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumes poly1 and poly2 are not length 0 and 0 < n <= len1 + len2 - 1. */ void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { slong i, top1, top2; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) { fmpz_mul(res, poly1, poly2); return; } if (len1 == 1) { _fmpz_vec_scalar_mul_fmpz(res, poly2, n, poly1); return; } if (len2 == 1) { _fmpz_vec_scalar_mul_fmpz(res, poly1, n, poly2); return; } fmpz_mul(res, poly1, poly2); for (i = 1; i < n; i++) { top1 = FLINT_MIN(len1 - 1, i); top2 = FLINT_MIN(len2 - 1, i); _fmpz_vec_dot_general(res + i, NULL, 0, poly1 + i - top2, poly2 + i - top1, 1, top1 + top2 - i + 1); } } void fmpz_poly_mullow_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { slong len_out; if (poly1->length == 0 || poly2->length == 0 || n == 0) { fmpz_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (n > len_out) n = len_out; if (res == poly1 || res == poly2) { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_mullow_classical(t->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(res, n); _fmpz_poly_mullow_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n); } _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/mullow_karatsuba_n.c000066400000000000000000000104351461254215100215010ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_mullow_kara_recursive(fmpz * out, const fmpz * pol1, const fmpz * pol2, fmpz * temp, slong len); /* Multiplication using truncated karatsuba. Below length 7, classical truncated multiplication is always theoretically faster, so we switch to that as the basecase. Above that we use the ordinary (left/right) karatsuba identity and recursively do one full karatsuba multiplication and two truncated karatsuba multiplications. */ void _fmpz_poly_mullow_kara_recursive(fmpz * out, const fmpz * pol1, const fmpz * pol2, fmpz * temp, slong len) { slong m1 = len / 2; slong m2 = len - m1; int odd = (len & 1); if (len <= 6) { _fmpz_poly_mullow_classical(out, pol1, len, pol2, len, len); return; } _fmpz_vec_add(temp + m2, pol1, pol1 + m1, m1); if (odd) fmpz_set(temp + m2 + m1, pol1 + 2 * m1); _fmpz_vec_add(temp + 2 * m2, pol2, pol2 + m1, m1); if (odd) fmpz_set(temp + 2 * m2 + m1, pol2 + 2 * m1); _fmpz_poly_mul_karatsuba(out, pol1, m1, pol2, m1); fmpz_zero(out + 2 * m1 - 1); _fmpz_poly_mullow_kara_recursive(temp, temp + m2, temp + 2 * m2, temp + 3 * m2, m2); _fmpz_poly_mullow_kara_recursive(temp + m2, pol1 + m1, pol2 + m1, temp + 2 * m2, m2); _fmpz_vec_sub(temp, temp, out, m2); _fmpz_vec_sub(temp, temp, temp + m2, m2); if (odd) fmpz_set(out + 2 * m1, temp + m2); _fmpz_vec_add(out + m1, out + m1, temp, m2); } /* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mullow_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong n) { fmpz *temp; slong len, loglen = 0; if (n == 1) { fmpz_mul(res, poly1, poly2); return; } while ((WORD(1) << loglen) < n) loglen++; len = (WORD(1) << loglen); temp = _fmpz_vec_init(3 * len); _fmpz_poly_mullow_kara_recursive(res, poly1, poly2, temp, n); _fmpz_vec_clear(temp, 3 * len); } void _fmpz_poly_mullow_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n) { int clear = 0; slong i; fmpz *copy1, *copy2; if (len1 >= n) copy1 = (fmpz *) poly1; else { copy1 = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < len1; i++) copy1[i] = poly1[i]; flint_mpn_zero((mp_ptr) copy1 + len1, n - len1); clear |= 1; } if (len2 >= n) copy2 = (fmpz *) poly2; else { copy2 = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < len2; i++) copy2[i] = poly2[i]; flint_mpn_zero((mp_ptr) copy2 + len2, n - len2); clear |= 2; } _fmpz_poly_mullow_karatsuba_n(res, copy1, copy2, n); if (clear & 1) flint_free(copy1); if (clear & 2) flint_free(copy2); } void fmpz_poly_mullow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { const slong len1 = FLINT_MIN(poly1->length, n); const slong len2 = FLINT_MIN(poly2->length, n); slong lenr; if (len1 == 0 || len2 == 0) { fmpz_poly_zero(res); return; } lenr = len1 + len2 - 1; n = FLINT_MIN(n, lenr); if (res != poly1 && res != poly2) { fmpz_poly_fit_length(res, n); _fmpz_poly_mullow_karatsuba(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_mullow_karatsuba(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/mulmid_classical.c000066400000000000000000000046411461254215100211170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumes poly1 and poly2 are not length 0 and len1 >= len2. */ void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if ((len1 == 1) && (len2 == 1)) /* Special case if the length of both inputs is 1 */ { fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { slong i; /* Set res[i] = poly1[i]*poly2[0] */ _fmpz_vec_scalar_mul_fmpz(res, poly1 + len2 - 1, len1 - len2 + 1, poly2); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len2 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res, poly2 + len2 - i - 1, FLINT_MIN(i + 1, len1 - len2 + 1), poly1 + i); for (; i < len1 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i - len2 + 2, poly2 + 1, FLINT_MIN(len2 - 1, len1 - i - 1), poly1 + i); } } void fmpz_poly_mulmid_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong len_out; if (poly1->length == 0 || poly2->length == 0) { fmpz_poly_zero(res); return; } len_out = poly1->length - poly2->length + 1; if (res == poly1 || res == poly2) { fmpz_poly_t temp; fmpz_poly_init2(temp, len_out); _fmpz_poly_mulmid_classical(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); fmpz_poly_swap(res, temp); fmpz_poly_clear(temp); } else { fmpz_poly_fit_length(res, len_out); _fmpz_poly_mulmid_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); } _fmpz_poly_set_length(res, len_out); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/neg.c000066400000000000000000000012601461254215100163550ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_neg(fmpz_poly_t res, const fmpz_poly_t poly) { slong i; fmpz_poly_fit_length(res, poly->length); for (i = 0; i < poly->length; i++) fmpz_neg(res->coeffs + i, poly->coeffs + i); _fmpz_poly_set_length(res, poly->length); } flint-3.1.3/src/fmpz_poly/newton_to_monomial.c000066400000000000000000000012141461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_newton_to_monomial(fmpz * poly, const fmpz * roots, slong n) { slong i, j; for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) fmpz_submul(poly + j, poly + j + 1, roots + i); } flint-3.1.3/src/fmpz_poly/normalise.c000066400000000000000000000010631461254215100175760ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void _fmpz_poly_normalise(fmpz_poly_t poly) { slong i; for (i = poly->length - 1; (i >= 0) && !poly->coeffs[i]; i--) ; poly->length = i + 1; } flint-3.1.3/src/fmpz_poly/norms.c000066400000000000000000000016761461254215100167550ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" ulong fmpz_poly_max_limbs(const fmpz_poly_t poly) { return _fmpz_vec_max_limbs(poly->coeffs, poly->length); } slong fmpz_poly_max_bits(const fmpz_poly_t poly) { return _fmpz_vec_max_bits(poly->coeffs, poly->length); } void fmpz_poly_height(fmpz_t res, const fmpz_poly_t poly) { _fmpz_vec_height(res, poly->coeffs, poly->length); } slong _fmpz_poly_hamming_weight(const fmpz * a, slong len) { slong i, sum = 0; for (i = 0; i < len; i++) sum += !fmpz_is_zero(a + i); return sum; } flint-3.1.3/src/fmpz_poly/nth_derivative.c000066400000000000000000000024611461254215100206230ustar00rootroot00000000000000/* Copyright (C) 2021, Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_nth_derivative(fmpz * rpoly, const fmpz * poly, ulong n, slong len) { slong i; fmpz_t c; fmpz_init(c); fmpz_fac_ui(c, n); fmpz_mul(rpoly, poly + n, c); for (i = n + 1; i < len; i ++) { fmpz_divexact_ui(c, c, i - n); fmpz_mul_ui(c, c, i); fmpz_mul(rpoly + i - n, poly + i, c); } fmpz_clear(c); } void fmpz_poly_nth_derivative(fmpz_poly_t res, const fmpz_poly_t poly, ulong n) { const slong len = poly->length; if (len <= n) { fmpz_poly_zero(res); return; } fmpz_poly_fit_length(res, len - n); if (n == 0) { fmpz_poly_set(res, poly); } else if (n == 1) { _fmpz_poly_derivative(res->coeffs, poly->coeffs, len); } else { _fmpz_poly_nth_derivative(res->coeffs, poly->coeffs, n, len); } _fmpz_poly_set_length(res, len - n); } flint-3.1.3/src/fmpz_poly/num_real_roots.c000066400000000000000000000073451461254215100206460ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" static inline slong _fmpz_poly_num_real_roots_quadratic(const fmpz * pol, slong len) { if ((fmpz_sgn(pol) * fmpz_sgn(pol + 2) < 0) || (2*fmpz_bits(pol + 1) > fmpz_bits(pol) + fmpz_bits(pol + 2) + 3)) { return 2; } else { fmpz_t b2, ac; int s; fmpz_init(b2); fmpz_init(ac); fmpz_mul(b2, pol + 1, pol + 1); fmpz_mul(ac, pol, pol + 2); fmpz_mul_2exp(ac, ac, 2); s = fmpz_cmp(b2, ac); fmpz_clear(b2); fmpz_clear(ac); if (s > 0) return 2; else return 0; } } static inline slong _num_roots_quartic_positive_discriminant(const fmpz * p) { /* more delicate quartic case */ fmpz_t d, a; slong res = 0; fmpz_init(a); fmpz_init(d); /* P = 8ac - 3b^2 */ fmpz_mul(d, p + 4, p + 2); fmpz_mul_ui(d, d, 8); fmpz_mul(a, p + 3, p + 3); fmpz_mul_ui(a, a, 3); fmpz_sub(d, d, a); if (fmpz_sgn(d) < 0) { /* D = 64 a^3 e - 16 a^2 c^2 + 16 a b^2 c - 16 a^2 b d - 3 b^4 */ fmpz_mul(d, p + 4, p + 4); fmpz_mul(d, d, p + 4); fmpz_mul(d, d, p); fmpz_mul_ui(d, d, 64); fmpz_mul(a, p + 4, p + 4); fmpz_mul(a, a, p + 2); fmpz_mul(a, a, p + 2); fmpz_mul_ui(a, a, 16); fmpz_sub(d, d, a); fmpz_mul(a, p + 4, p + 3); fmpz_mul(a, a, p + 3); fmpz_mul(a, a, p + 2); fmpz_mul_ui(a, a, 16); fmpz_add(d, d, a); fmpz_mul(a, p + 4, p + 4); fmpz_mul(a, a, p + 3); fmpz_mul(a, a, p + 1); fmpz_mul_ui(a, a, 16); fmpz_sub(d, d, a); fmpz_mul(a, p + 3, p + 3); fmpz_mul(a, a, p + 3); fmpz_mul(a, a, p + 3); fmpz_mul_ui(a, a, 3); fmpz_sub(d, d, a); if (fmpz_sgn(d) < 0) res = 4; else res = 0; } fmpz_clear(a); fmpz_clear(d); return res; } slong _fmpz_poly_num_real_roots(const fmpz * pol, slong len) { slong i = 0; while (i < len && fmpz_is_zero(pol + i)) i++; pol = pol + i; len = len - i; if (len == 1) return i; if (len == 2) return i + 1; if (len == 3) return i + _fmpz_poly_num_real_roots_quadratic(pol, len); if (len <= 5) { int s; fmpz_t disc; fmpz_init(disc); _fmpz_poly_discriminant(disc, pol, len); s = fmpz_sgn(disc); fmpz_clear(disc); if (s == 0) flint_throw(FLINT_ERROR, "non-squarefree polynomial in %s\n", __func__); else if (s > 0) { if (len == 5) return i + _num_roots_quartic_positive_discriminant(pol); else return i + len - 1; } else return i + len - 3; } else { slong n_zero, n_neg, n_pos; if (fmpz_is_zero(pol)) n_zero = 1; else n_zero = 0; _fmpz_poly_num_real_roots_sturm(&n_neg, &n_pos, pol + n_zero, len - n_zero); return i + n_zero + n_neg + n_pos; } /* unreachable! */ return -1; } slong fmpz_poly_num_real_roots(const fmpz_poly_t pol) { if (fmpz_poly_is_zero(pol)) flint_throw(FLINT_ERROR, "zero polynomial in %s\n", __func__); return _fmpz_poly_num_real_roots(pol->coeffs, pol->length); } flint-3.1.3/src/fmpz_poly/num_real_roots_sturm.c000066400000000000000000000074121461254215100220730ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_num_real_roots_sturm(slong * n_neg, slong * n_pos, const fmpz * pol, slong len) { fmpz_t a, b, g, h; fmpz *A, *B, *W; slong lenA, lenB; int s, s0a, s0, s0b; fmpz_init(a); fmpz_init(b); fmpz_init(g); fmpz_init(h); A = W = _fmpz_vec_init(2*len - 1); B = W + len; lenA = len; lenB = len - 1; _fmpz_poly_content(a, pol, lenA); _fmpz_vec_scalar_divexact_fmpz(A, pol, lenA, a); _fmpz_poly_derivative(B, A, lenA); _fmpz_poly_content(b, B, lenB); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, b); fmpz_one(g); fmpz_one(h); s0a = s0b = fmpz_sgn(A + (lenA - 1)); if (lenA % 2 == 0) s0b = -s0b; s0 = fmpz_sgn(A); (*n_neg) = (*n_pos) = 0; while (1) { const slong delta = lenA - lenB; /* sign change at + infinity */ s = fmpz_sgn(B + (lenB - 1)); if (s != s0a) { (*n_pos)--; s0a = s; } /* sign change at - infinity */ if (lenB % 2 == 0) s = -s; if (s != s0b) { (*n_neg)++; s0b = s; } /* sign change at 0 */ s = fmpz_sgn(B); if (s && (s != s0)) { (*n_neg)--; (*n_pos)++; s0 = s; } /* now compute the next element of the remainder sequence */ _fmpz_poly_pseudo_rem_cohen(A, A, lenA, B, lenB); if ((fmpz_sgn(B + (lenB - 1)) > 0) || ((lenA ^ lenB) & 1)) { _fmpz_vec_neg(A, A, lenA); } FMPZ_VEC_NORM(A, lenA); if (lenA <= 1) break; { fmpz *T; slong len; T = A, A = B, B = T, len = lenA, lenA = lenB, lenB = len; } if (delta == 1) { fmpz_mul(b, g, h); if (fmpz_sgn(b) < 0) fmpz_neg(b, b); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, b); fmpz_set(g, A + (lenA - 1)); fmpz_set(h, g); } else { fmpz_pow_ui(a, h, delta); fmpz_mul(b, g, a); if (fmpz_sgn(b) < 0) fmpz_neg(b, b); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, b); fmpz_pow_ui(b, A + (lenA - 1), delta); fmpz_mul(g, h, b); fmpz_divexact(h, g, a); fmpz_set(g, A + (lenA - 1)); } } if (lenA) { /* sign change at + infinity */ s = fmpz_sgn(A); if (s != s0a) (*n_pos)--; /* sign change at - infinity */ if (s != s0b) (*n_neg)++; /* sign change at 0 */ if (s != s0) { (*n_neg)--; (*n_pos)++; } } fmpz_clear(a); fmpz_clear(b); fmpz_clear(g); fmpz_clear(h); _fmpz_vec_clear(W, 2*len - 1); } slong fmpz_poly_num_real_roots_sturm(const fmpz_poly_t pol) { slong i, len; slong n_neg = 0; slong n_pos = 0; if (fmpz_poly_is_zero(pol)) flint_throw(FLINT_ERROR, "Zero polynomial in %s\n", __func__); for (i = 0; (i < pol->length) && fmpz_is_zero(pol->coeffs + i); i++); len = pol->length - i; if (len == 1) return i; else if (len == 2) return i + 1; else { _fmpz_poly_num_real_roots_sturm(&n_neg, &n_pos, i + pol->coeffs, len); return i + n_neg + n_pos; } } flint-3.1.3/src/fmpz_poly/pow.c000066400000000000000000000037751461254215100164260ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pow(fmpz * res, const fmpz * poly, slong len, ulong e) { if (e < UWORD(5)) _fmpz_poly_pow_small(res, poly, len, e); else if (len == 2) _fmpz_poly_pow_binomial(res, poly, e); else { ulong limbs = (ulong) _fmpz_vec_max_limbs(poly, len); if (limbs < ((UWORD(3) * e) / UWORD(2) + UWORD(150)) / (ulong) len) _fmpz_poly_pow_multinomial(res, poly, len, e); else _fmpz_poly_pow_binexp(res, poly, len, e); } } void fmpz_poly_pow(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) { const slong len = poly->length; slong rlen; if ((len < 2) | (e < UWORD(3))) { if (e == UWORD(0)) fmpz_poly_set_ui(res, 1); else if (len == 0) fmpz_poly_zero(res); else if (len == 1) { fmpz_poly_fit_length(res, 1); fmpz_pow_ui(res->coeffs, poly->coeffs, e); _fmpz_poly_set_length(res, 1); } else if (e == UWORD(1)) fmpz_poly_set(res, poly); else /* e == UWORD(2) */ fmpz_poly_sqr(res, poly); return; } rlen = (slong) e * (len - 1) + 1; if (res != poly) { fmpz_poly_fit_length(res, rlen); _fmpz_poly_set_length(res, rlen); _fmpz_poly_pow(res->coeffs, poly->coeffs, len, e); } else { fmpz_poly_t t; fmpz_poly_init2(t, rlen); _fmpz_poly_set_length(t, rlen); _fmpz_poly_pow(t->coeffs, poly->coeffs, len, e); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } flint-3.1.3/src/fmpz_poly/pow_addchains.c000066400000000000000000000126641461254215100204210ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pow_addchains(fmpz * res, const fmpz * poly, slong len, const int * a, int n) { int *b; slong lenm1 = len - 1, lenv; fmpz *v; /* Compute partial sums */ { int i; b = (int *) flint_malloc(n * sizeof(int)); b[0] = 0; for (i = 1; i < n; i++) b[i] = b[i-1] + a[i]; } /* Allocate memory for the polynomials f^{a[1]}, ..., f^{a[n-1]} */ lenv = lenm1 * b[n-1] + n - 1; v = _fmpz_vec_init(lenv); /* Compute f^{a[1]}, ..., f^{a[n-1]} */ { int d, i, j; _fmpz_poly_sqr(v, poly, len); for (i = 1; i < n-1; i++) { d = a[i+1] - a[i]; if (d == 1) { _fmpz_poly_mul(v + lenm1 * b[i] + (i), v + lenm1 * b[i-1], lenm1 * a[i] + 1, poly, len); } else { for (j = i; a[j] != d; j--) ; _fmpz_poly_mul(v + lenm1 * b[i] + (i), v + lenm1 * b[i-1], lenm1 * a[i] + 1, v + lenm1 * b[j-1] + (j-1), lenm1 * a[j] + 1); } } /* Deal with the final product stored in res, i == n-1 */ { d = a[i+1] - a[i]; if (d == 1) { _fmpz_poly_mul(res, v + lenm1 * b[i-1], lenm1 * a[i] + 1, poly, len); } else { for (j = i; a[j] != d; j--) ; _fmpz_poly_mul(res, v + lenm1 * b[i-1], lenm1 * a[i] + 1, v + lenm1 * b[j-1] + (j-1), lenm1 * a[j] + 1); } } } flint_free(b); _fmpz_vec_clear(v, lenv); } void fmpz_poly_pow_addchains(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) { const slong len = poly->length; if ((len < 2) | (e < UWORD(3))) { if (e == UWORD(0)) fmpz_poly_set_ui(res, 1); else if (len == 0) fmpz_poly_zero(res); else if (len == 1) { fmpz_poly_fit_length(res, 1); fmpz_pow_ui(res->coeffs, poly->coeffs, e); _fmpz_poly_set_length(res, 1); } else if (e == UWORD(1)) fmpz_poly_set(res, poly); else /* e == UWORD(2) */ fmpz_poly_sqr(res, poly); return; } if (e <= UWORD(148)) { /* An array storing a tree with shortest addition chains (star chains, in fact) for all integers up to and including 148. Let A denote the array. The entry A[0] is present to provide 1-based indexing. The integer 1 is the root of the tree and the entry A[1] is irrelevant. For integers i >= 2, A[i] is the parent of i. We can iterate through an addition chain for n, where 0 < n < 148, in the array shortest_addchains_148 as follows: Visit n while ((n = shortest_addchains_148[n])) { Visit n } */ static const int shortest_addchains_148[149] = { 0, 0, 1, 2, 2, 3, 3, 5, 4, 8, 5, 10, 6, 9, 7, 12, 8, 9, 16, 18, 10, 15, 11, 20, 12, 17, 13, 24, 14, 25, 15, 28, 16, 32, 17, 26, 18, 36, 19, 27, 20, 40, 21, 34, 22, 30, 23, 46, 24, 33, 25, 48, 26, 37, 27, 54, 28, 49, 29, 56, 30, 52, 31, 51, 32, 64, 33, 66, 34, 68, 35, 70, 36, 72, 66, 60, 38, 43, 39, 78, 40, 65, 41, 80, 42, 80, 43, 86, 44, 88, 45, 90, 46, 92, 47, 92, 48, 96, 49, 96, 50,100, 51,102, 52,102, 53, 74, 54,108, 55,108, 56,104, 57,112, 58,104, 59,112, 60,120, 61,120, 62,100, 63,126, 64,128, 65,130,128,132, 67, 90, 68,136, 69,138, 70,140, 71,117, 72,144, 73, 99, 74 }; int a[11], i = 11, n = (int) e; slong rlen = (slong) e * (len - 1) + 1; /* Copy the addition chain into 1 = a[0] < a[1] < ... < a[n] */ a[--i] = n; while ((n = shortest_addchains_148[n])) a[--i] = n; n = 10 - i; if (res != poly) { fmpz_poly_fit_length(res, rlen); _fmpz_poly_pow_addchains(res->coeffs, poly->coeffs, len, a + i, n); _fmpz_poly_set_length(res, rlen); } else { fmpz_poly_t t; fmpz_poly_init2(t, rlen); _fmpz_poly_pow_addchains(t->coeffs, poly->coeffs, len, a + i, n); _fmpz_poly_set_length(t, rlen); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } else { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_addchains). Powering via chains not implemented for e > 148.\n"); } } flint-3.1.3/src/fmpz_poly/pow_binexp.c000066400000000000000000000062131461254215100177610ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pow_binexp(fmpz * res, const fmpz * poly, slong len, ulong e) { ulong bit = ~((~UWORD(0)) >> 1); slong rlen; slong alloc = (slong) e * (len - 1) + 1; fmpz *v = _fmpz_vec_init(alloc); fmpz *R, *S, *T; /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, len} */ _fmpz_poly_sqr(R, poly, len); rlen = 2 * len - 1; if ((bit & e)) { _fmpz_poly_mul(S, R, rlen, poly, len); rlen += len - 1; T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _fmpz_poly_sqr(S, R, rlen); rlen += rlen - 1; _fmpz_poly_mul(R, S, rlen, poly, len); rlen += len - 1; } else { _fmpz_poly_sqr(S, R, rlen); rlen += rlen - 1; T = R; R = S; S = T; } } _fmpz_vec_clear(v, alloc); } void fmpz_poly_pow_binexp(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) { const slong len = poly->length; slong rlen; if ((len < 2) | (e < UWORD(3))) { if (e == UWORD(0)) fmpz_poly_set_ui(res, 1); else if (len == 0) fmpz_poly_zero(res); else if (len == 1) { fmpz_poly_fit_length(res, 1); fmpz_pow_ui(res->coeffs, poly->coeffs, e); _fmpz_poly_set_length(res, 1); } else if (e == UWORD(1)) fmpz_poly_set(res, poly); else /* e == UWORD(2) */ fmpz_poly_sqr(res, poly); return; } rlen = (slong) e * (len - 1) + 1; if (res != poly) { fmpz_poly_fit_length(res, rlen); _fmpz_poly_pow_binexp(res->coeffs, poly->coeffs, len, e); _fmpz_poly_set_length(res, rlen); } else { fmpz_poly_t t; fmpz_poly_init2(t, rlen); _fmpz_poly_pow_binexp(t->coeffs, poly->coeffs, len, e); _fmpz_poly_set_length(t, rlen); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } flint-3.1.3/src/fmpz_poly/pow_binomial.c000066400000000000000000000046031461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_pow_binomial(fmpz * res, const fmpz * poly, ulong e) { ulong i, f; fmpz_t a, b, c; *a = WORD(1); *b = WORD(1); *c = WORD(1); fmpz_one(res); fmpz_one(res + e); for (i = UWORD(1), f = e - UWORD(1); i <= (e - UWORD(1)) >> 1; i++, f--) { fmpz_mul(a, a, poly); fmpz_mul(b, b, poly + 1); fmpz_mul_ui(c, c, f + UWORD(1)); fmpz_divexact_ui(c, c, i); fmpz_mul(res + i, b, c); fmpz_mul(res + f, a, c); } if ((e & UWORD(1)) == UWORD(0)) { fmpz_mul(a, a, poly); fmpz_mul(b, b, poly + 1); fmpz_mul_ui(c, c, f + UWORD(1)); fmpz_divexact_ui(c, c, i); fmpz_mul(res + i, b, c); fmpz_mul(res + i, res + i, a); i++, f--; } for ( ; i <= e; i++, f--) { fmpz_mul(a, a, poly); fmpz_mul(b, b, poly + 1); fmpz_mul(res + i, res + i, b); fmpz_mul(res + f, res + f, a); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } void fmpz_poly_pow_binomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) { const slong len = poly->length; slong rlen; if (len != 2) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_pow_binomial). poly->length not equal to 2.\n"); } if (e < UWORD(3)) { if (e == UWORD(0)) fmpz_poly_set_ui(res, UWORD(1)); else if (e == UWORD(1)) fmpz_poly_set(res, poly); else /* e == UWORD(2) */ fmpz_poly_sqr(res, poly); return; } rlen = (slong) e + 1; if (res != poly) { fmpz_poly_fit_length(res, rlen); _fmpz_poly_set_length(res, rlen); _fmpz_poly_pow_binomial(res->coeffs, poly->coeffs, e); } else { fmpz_poly_t t; fmpz_poly_init2(t, rlen); _fmpz_poly_set_length(t, rlen); _fmpz_poly_pow_binomial(t->coeffs, poly->coeffs, e); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } flint-3.1.3/src/fmpz_poly/pow_multinomial.c000066400000000000000000000050671461254215100210340ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pow_multinomial(fmpz * res, const fmpz * poly, slong len, ulong e) { slong k, low, rlen; fmpz_t d, t; fmpz * P; rlen = (slong) e * (len - WORD(1)) + WORD(1); _fmpz_vec_zero(res, rlen); for (low = WORD(0); poly[low] == WORD(0); low++) ; if (low == WORD(0)) { P = (fmpz *) poly; } else { P = (fmpz *) poly + low; len -= low; res += (slong) e * low; rlen -= (slong) e * low; } fmpz_init(d); fmpz_init(t); fmpz_pow_ui(res, P, e); for (k = 1; k < rlen; k++) { slong i, u = -k; for (i = 1; i <= FLINT_MIN(k, len - 1); i++) { fmpz_mul(t, P + i, res + (k - i)); u += (slong) e + 1; if (u >= 0) fmpz_addmul_ui(res + k, t, (ulong) u); else fmpz_submul_ui(res + k, t, - ((ulong) u)); } fmpz_add(d, d, P); fmpz_divexact(res + k, res + k, d); } fmpz_clear(d); fmpz_clear(t); } void fmpz_poly_pow_multinomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e) { const slong len = poly->length; slong rlen; if ((len < 2) | (e < UWORD(3))) { if (e == UWORD(0)) fmpz_poly_set_ui(res, 1); else if (len == 0) fmpz_poly_zero(res); else if (len == 1) { fmpz_poly_fit_length(res, 1); fmpz_pow_ui(res->coeffs, poly->coeffs, e); _fmpz_poly_set_length(res, 1); } else if (e == UWORD(1)) fmpz_poly_set(res, poly); else /* e == UWORD(2) */ fmpz_poly_sqr(res, poly); return; } rlen = (slong) e * (len - 1) + 1; if (res != poly) { fmpz_poly_fit_length(res, rlen); _fmpz_poly_pow_multinomial(res->coeffs, poly->coeffs, len, e); _fmpz_poly_set_length(res, rlen); } else { fmpz_poly_t t; fmpz_poly_init2(t, rlen); _fmpz_poly_pow_multinomial(t->coeffs, poly->coeffs, len, e); _fmpz_poly_set_length(t, rlen); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } } flint-3.1.3/src/fmpz_poly/pow_small.c000066400000000000000000000024401461254215100176020ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pow_small(fmpz * res, const fmpz * poly, slong len, ulong e) { switch (e) { case 0: fmpz_one(res); break; case 1: _fmpz_vec_set(res, poly, len); break; case 2: _fmpz_poly_sqr(res, poly, len); break; case 3: { slong alloc = 2 * len - 1; fmpz *t = _fmpz_vec_init(alloc); _fmpz_poly_sqr(t, poly, len); _fmpz_poly_mul(res, t, alloc, poly, len); _fmpz_vec_clear(t, alloc); break; } case 4: { slong alloc = 2 * len - 1; fmpz *t = _fmpz_vec_init(alloc); _fmpz_poly_sqr(t, poly, len); _fmpz_poly_sqr(res, t, alloc); _fmpz_vec_clear(t, alloc); break; } } } flint-3.1.3/src/fmpz_poly/pow_trunc.c000066400000000000000000000073301461254215100176300ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong n) { ulong bit = ~((~UWORD(0)) >> 1); fmpz *v = _fmpz_vec_init(n); fmpz *R, *S, *T; /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, n} */ _fmpz_poly_sqrlow(R, poly, n, n); if ((bit & e)) { _fmpz_poly_mullow(S, R, n, poly, n, n); T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _fmpz_poly_sqrlow(S, R, n, n); _fmpz_poly_mullow(R, S, n, poly, n, n); } else { _fmpz_poly_sqrlow(S, R, n, n); T = R; R = S; S = T; } } _fmpz_vec_clear(v, n); } void fmpz_poly_pow_trunc(fmpz_poly_t res, const fmpz_poly_t poly, ulong e, slong n) { fmpz * copy; int clear; slong i, len; if (n == 0) { fmpz_poly_zero(res); return; } if (e == 0) { fmpz_poly_set_ui(res, 1); return; } /* Set len to the length of poly mod x^n */ len = FLINT_MIN(n, poly->length); for (--len; (len >= 0) && !poly->coeffs[len]; --len) ; ++len; if ((len < 2) | (e < 3)) { if (len == 0) fmpz_poly_zero(res); else if (len == 1) { fmpz_poly_fit_length(res, 1); fmpz_pow_ui(res->coeffs, poly->coeffs, e); _fmpz_poly_set_length(res, 1); } else if (e == 1) { if (res != poly) { fmpz_poly_fit_length(res, len); _fmpz_vec_set(res->coeffs, poly->coeffs, len); _fmpz_poly_set_length(res, len); } else fmpz_poly_truncate(res, len); } else /* e == 2 */ fmpz_poly_sqrlow(res, poly, n); return; } if (poly->length >= n) { copy = poly->coeffs; clear = 0; } else { copy = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < poly->length; i++) copy[i] = poly->coeffs[i]; flint_mpn_zero((mp_ptr) copy + poly->length, n - poly->length); clear = 1; } if (res != poly) { fmpz_poly_fit_length(res, n); _fmpz_poly_pow_trunc(res->coeffs, copy, e, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_pow_trunc(t->coeffs, copy, e, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); if (clear) flint_free(copy); } flint-3.1.3/src/fmpz_poly/power_sums.c000066400000000000000000000026711461254215100200160ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_power_sums(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { slong len = poly->length; if (len == 0) { flint_throw(FLINT_ERROR, "(fmpz_poly_power_sums): Zero polynomial.\n"); } else if (n <= 0 || len == 1) { fmpz_poly_zero(res); } else { size_t i = 0; while (fmpz_is_zero(poly->coeffs + i)) i++; if (poly == res) { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_power_sums_naive(t->coeffs, poly->coeffs + i, len - i, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(res, n); _fmpz_poly_power_sums_naive(res->coeffs, poly->coeffs + i, len - i, n); } _fmpz_poly_set_length(res, n); if (i) fmpz_set_si(res->coeffs, len - 1); _fmpz_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/power_sums_naive.c000066400000000000000000000034431461254215100211760ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_power_sums_naive(fmpz * res, const fmpz * poly, slong len, slong n) { slong k; fmpz_set_ui(res, len - 1); for (k = 1; k < FLINT_MIN(n, len); k++) { fmpz_mul_si(res + k, poly + len - 1 - k, -k); _fmpz_vec_dot_general(res + k, res + k, 1, poly + len - 1 - k + 1, res + 1, 0, k - 1); } for (k = len; k < n; k++) _fmpz_vec_dot_general(res + k, NULL, 1, poly, res + k - len + 1, 0, len - 1); } void fmpz_poly_power_sums_naive(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { if (poly->length == 0) { flint_throw(FLINT_ERROR, "(fmpz_poly_power_sums_naive): Zero polynomial.\n"); } else if (n <= 0 || poly->length == 1) { fmpz_poly_zero(res); } else { if (poly == res) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_fit_length(t, n); _fmpz_poly_power_sums_naive(t->coeffs, poly->coeffs, poly->length, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(res, n); _fmpz_poly_power_sums_naive(res->coeffs, poly->coeffs, poly->length, n); } _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/power_sums_to_poly.c000066400000000000000000000034311461254215100215560ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, slong len) { slong k; slong d = fmpz_get_ui(poly); fmpz_one(res + d); for (k = 1; k < FLINT_MIN(d + 1, len); k++) { _fmpz_vec_dot_general(res + d - k, poly + k, 0, res + d - k + 1, poly + 1, 0, k - 1); fmpz_divexact_si(res + d - k, res + d - k, -k); } for (k = len; k <= d; k++) { _fmpz_vec_dot_general(res + d - k, NULL, 0, res + d - k + 1, poly + 1, 0, len - 1); fmpz_divexact_si(res + d - k, res + d - k, -k); } } void fmpz_poly_power_sums_to_poly(fmpz_poly_t res, const fmpz_poly_t Q) { if (Q->length == 0) { fmpz_poly_fit_length(res, 1); fmpz_one(res->coeffs); _fmpz_poly_set_length(res, 1); } else { slong d; d = fmpz_get_ui(Q->coeffs); if (Q == res) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_fit_length(t, d + 1); _fmpz_poly_power_sums_to_poly(t->coeffs, Q->coeffs, Q->length); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(res, d + 1); _fmpz_poly_power_sums_to_poly(res->coeffs, Q->coeffs, Q->length); } _fmpz_poly_set_length(res, d + 1); _fmpz_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/powers_clear.c000066400000000000000000000013151461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_powers_clear(fmpz ** powers, slong len) { slong i; for (i = 0; i < 2*len - 1; i++) _fmpz_vec_clear(powers[i], len - 1); flint_free(powers); } void fmpz_poly_powers_clear(fmpz_poly_powers_precomp_t pinv) { _fmpz_poly_powers_clear(pinv->powers, pinv->len); } flint-3.1.3/src/fmpz_poly/powers_precompute.c000066400000000000000000000032151461254215100213700ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" fmpz ** _fmpz_poly_powers_precompute(const fmpz * B, slong len) { slong i; fmpz ** powers = flint_malloc(sizeof(fmpz *)*(2*len - 1)); fmpz_poly_t pow, p; fmpz_poly_init2(pow, len); fmpz_poly_one(pow); fmpz_poly_init2(p, len - 1); for (i = 0; i < 2*len - 1; i++) { powers[i] = _fmpz_vec_init(len - 1); if (pow->length == len) /* reduce pow mod B */ { _fmpz_vec_scalar_mul_fmpz(p->coeffs, B, len - 1, pow->coeffs + pow->length - 1); _fmpz_poly_set_length(p, len - 1); _fmpz_poly_normalise(p); fmpz_poly_sub(pow, pow, p); _fmpz_poly_set_length(pow, len - 1); _fmpz_poly_normalise(pow); } _fmpz_vec_set(powers[i], pow->coeffs, len - 1); fmpz_poly_shift_left(pow, pow, 1); } fmpz_poly_clear(pow); fmpz_poly_clear(p); return powers; } void fmpz_poly_powers_precompute(fmpz_poly_powers_precomp_t pinv, fmpz_poly_t poly) { if (poly->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_powers_precompute). Division by zero.\n"); } pinv->powers = _fmpz_poly_powers_precompute(poly->coeffs, poly->length); pinv->len = poly->length; } flint-3.1.3/src/fmpz_poly/preinvert.c000066400000000000000000000051421461254215100176250ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_preinvert(fmpz * Binv, const fmpz * B, slong len) { if (len == 1) /* B is +-1 */ { fmpz_set(Binv, B); } else { const slong alloc = len + FLINT_MAX(len, 3 * FMPZ_POLY_INV_NEWTON_CUTOFF); slong *a, i, m, n = len; fmpz *T, *W; T = _fmpz_vec_init(alloc); W = T + len; for (i = 1; (WORD(1) << i) < n; i++) ; a = (slong *) flint_malloc(i * sizeof(slong)); a[i = 0] = n; while (n >= FMPZ_POLY_INV_NEWTON_CUTOFF) a[++i] = (n = (n + 1) / 2); if (len != n) _fmpz_poly_reverse(T, B, len, len); /* only reverse if it ... */ /* Base case */ { fmpz *Brev = W + 2 * FMPZ_POLY_INV_NEWTON_CUTOFF; if (len != n) _fmpz_poly_reverse(Brev, T, n, n); /* ... won't be undone */ else Brev = (fmpz *) B; _fmpz_vec_zero(W, 2*n - 2); fmpz_one(W + (2*n - 2)); _fmpz_poly_div_basecase(Binv, W, W, 2*n - 1, Brev, n, 0); _fmpz_poly_reverse(Binv, Binv, n, n); } for (i--; i >= 0; i--) { m = n; n = a[i]; _fmpz_poly_mullow(W, T, n, Binv, m, n); _fmpz_poly_mullow(Binv + m, Binv, m, W + m, n - m, n - m); _fmpz_vec_neg(Binv + m, Binv + m, n - m); } _fmpz_vec_clear(T, alloc); flint_free(a); } } void fmpz_poly_preinvert(fmpz_poly_t B_inv, const fmpz_poly_t B) { slong n = B->length; fmpz_poly_t temp; fmpz * Binv_coeffs; if (n == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_preinvert). Division by zero.\n"); } if (B == B_inv) { fmpz_poly_init2(temp, n); Binv_coeffs = temp->coeffs; } else { fmpz_poly_fit_length(B_inv, n); Binv_coeffs = B_inv->coeffs; } _fmpz_poly_preinvert(Binv_coeffs, B->coeffs, n); if (B == B_inv) { _fmpz_poly_set_length(temp, n); fmpz_poly_swap(B_inv, temp); fmpz_poly_clear(temp); } else _fmpz_poly_set_length(B_inv, n); /* no need to normalise */ } flint-3.1.3/src/fmpz_poly/primitive_part.c000066400000000000000000000020331461254215100206410ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_primitive_part(fmpz * res, const fmpz * poly, slong len) { fmpz_t x; fmpz_init(x); _fmpz_poly_content(x, poly, len); if (fmpz_sgn(poly + (len - 1)) < 0) fmpz_neg(x, x); _fmpz_vec_scalar_divexact_fmpz(res, poly, len, x); fmpz_clear(x); } void fmpz_poly_primitive_part(fmpz_poly_t res, const fmpz_poly_t poly) { slong len = poly->length; if (len == 0) { fmpz_poly_zero(res); return; } fmpz_poly_fit_length(res, len); _fmpz_poly_set_length(res, len); _fmpz_poly_primitive_part(res->coeffs, poly->coeffs, len); } flint-3.1.3/src/fmpz_poly/product_roots_fmpq_vec.c000066400000000000000000000035761461254215100224060ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_product_roots_fmpq_vec(fmpz * poly, const fmpq * xs, slong n) { if (n == 0) { fmpz_one(poly); } else if (n < 20) { slong i,j; fmpz_set(poly + n, fmpq_denref(xs)); fmpz_set(poly + n - 1, fmpq_numref(xs)); fmpz_neg(poly + n - 1, poly + n - 1); for (i = 1; i < n; i++) { fmpz_mul(poly + n - i - 1, poly + n - i, fmpq_numref(xs + i)); fmpz_neg(poly + n - i - 1, poly + n - i - 1); for (j = 0; j < i; j++) { fmpz_mul(poly + n - i + j, poly + n - i + j, fmpq_denref(xs + i)); fmpz_submul(poly + n - i + j, poly + n - i + j + 1, fmpq_numref(xs + i)); } fmpz_mul(poly + n, poly + n, fmpq_denref(xs + i)); } } else { slong m; fmpz * tmp; m = (n + 1) / 2; tmp = _fmpz_vec_init(n + 2); _fmpz_poly_product_roots_fmpq_vec(tmp, xs, m); _fmpz_poly_product_roots_fmpq_vec(tmp + m + 1, xs + m, n - m); _fmpz_poly_mul(poly, tmp, m + 1, tmp + m + 1, n - m + 1); _fmpz_vec_clear(tmp, n + 2); } } void fmpz_poly_product_roots_fmpq_vec(fmpz_poly_t poly, const fmpq * xs, slong n) { fmpz_poly_fit_length(poly, n + 1); _fmpz_poly_product_roots_fmpq_vec(poly->coeffs, xs, n); _fmpz_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpz_poly/product_roots_fmpz_vec.c000066400000000000000000000031321461254215100224030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n) { if (n == 0) { fmpz_one(poly); } else if (n < 20) { slong i, j; fmpz_one(poly + n); fmpz_neg(poly + n - 1, xs); for (i = 1; i < n; i++) { fmpz_mul(poly + n - i - 1, poly + n - i, xs + i); fmpz_neg(poly + n - i - 1, poly + n - i - 1); for (j = 0; j < i - 1; j++) fmpz_submul(poly + n - i + j, poly + n - i + j + 1, xs + i); fmpz_sub(poly + n - 1, poly + n - 1, xs + i); } } else { slong m; fmpz * tmp; m = (n + 1) / 2; tmp = _fmpz_vec_init(n + 2); _fmpz_poly_product_roots_fmpz_vec(tmp, xs, m); _fmpz_poly_product_roots_fmpz_vec(tmp + m + 1, xs + m, n - m); _fmpz_poly_mul(poly, tmp, m + 1, tmp + m + 1, n - m + 1); _fmpz_vec_clear(tmp, n + 2); } } void fmpz_poly_product_roots_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, slong n) { fmpz_poly_fit_length(poly, n + 1); _fmpz_poly_product_roots_fmpz_vec(poly->coeffs, xs, n); _fmpz_poly_set_length(poly, n + 1); } flint-3.1.3/src/fmpz_poly/profile/000077500000000000000000000000001461254215100171015ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly/profile/bm-div_divconquer.c000066400000000000000000000062221461254215100226640ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_gmprand(fmpz_poly_t rop, gmp_randstate_t state, slong len, slong bits) { slong i; mpz_t c; fmpz_t d; mpz_init(c); fmpz_init(d); fmpz_poly_zero(rop); fmpz_poly_fit_length(rop, len); for (i = 0; i < len; i++) { mpz_urandomb(c, state, bits); if (rand() & WORD(1)) mpz_neg(c, c); fmpz_set_mpz(d, c); fmpz_poly_set_coeff_fmpz(rop, i, d); } mpz_clear(c); fmpz_clear(d); } #define lenlo 1 #define lenhi 100 #define lenh 5 #define bitslo 16 #define bitshi 80 #define bitsh 32 #define cols ((lenhi + 1 - lenlo + (lenh - 1)) / lenh) #define rows ((bitshi + 1 - bitslo + (bitsh - 1)) / bitsh) #define cpumin 10 #define ncases 100 int main(void) { int i, j, len, bits; double X[rows][cols]; fmpz_poly_t f, g, q, r; gmp_randstate_t state; gmp_randinit_default(state); gmp_randseed_ui(state, UWORD(362436069)); srand(UWORD(521288629)); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_fit_length(f, 2 * lenhi - 1); fmpz_poly_fit_length(g, lenhi); fmpz_poly_fit_length(q, lenhi); fmpz_poly_fit_length(r, 2 * lenhi - 1); flint_printf("3 2 1"); for (len = lenlo, j = 0; len <= lenhi; len += lenh, j++) { for (bits = bitslo, i = 0; bits <= bitshi; bits += bitsh, i++) { int n, reps = 0; slong s = WORD(0); for (n = 0; n < ncases; n++) { clock_t c0, c1; int l, loops = 1; /* Construct random polynomials f and g */ { fmpz_poly_gmprand(f, state, 2*len - 1, bits); fmpz_poly_gmprand(g, state, len, bits); } loop: c0 = clock(); for (l = 0; l < loops; l++) { fmpz_poly_div_divconquer(q, f, g); } c1 = clock(); if (c1 - c0 <= cpumin) { loops *= 10; goto loop; } s += c1 - c0; reps += loops; } X[i][j] = (double) s / (double) reps; flint_printf(" ."); fflush(stdout); } } flint_printf("\n"); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) flint_printf("%8.3f", X[i][j]); flint_printf("\n"); } gmp_randclear(state); return 0; } flint-3.1.3/src/fmpz_poly/profile/p-compose.c000066400000000000000000000100741461254215100211510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" #include "profiler.h" /* Definitions for the parameters of the timing process. len1lo Minimum length len1hi Maximum length len1h Step size for the length len2lo Minimum length len2hi Maximum length len2h Step size for the length bits Bit size of the coefficients cols Number of different lengths rows Number of different bit sizes cpumin Minimum number of ms spent on each test case ncases Number of test cases per point (length, bit size) nalgs Number of algorithms img Whether an RGB coloured image should be produced imgname File name for image */ #define len1lo 1 #define len1hi 30 #define len1h 1 #define len2lo 1 #define len2hi 30 #define len2h 1 #define bits 112 #define cols ((len1hi + 1 - len1lo + (len1h - 1)) / len1h) #define rows ((len2hi + 1 - len2lo + (len2h - 1)) / len2h) #define cpumin 10 #define ncases 1 #define nalgs 2 int main(void) { int i, j, len1, len2; int X[rows][cols]; fmpz_poly_t f, g, h; FLINT_TEST_INIT(state); fmpz_poly_init2(f, len1hi); fmpz_poly_init2(g, len2hi); fmpz_poly_init2(h, (len1hi-1) * (len2hi-1) + 1); for (len1 = len1lo, j = 0; len1 <= len1hi; len1 += len1h, j++) { slong s[nalgs]; for (len2 = len2lo, i = 0; len2 <= len2hi; len2 += len2h, i++) { int c, n, reps = 0; for (c = 0; c < nalgs; c++) s[c] = WORD(0); for (n = 0; n < ncases; n++) { timeit_t t[nalgs]; int l, loops = 1; /* Construct random polynomials f and g */ { slong k; for (k = 0; k < len1; k++) fmpz_randbits(f->coeffs + k, state, bits); if ((f->coeffs)[len1-1] == WORD(0)) fmpz_randtest_not_zero(f->coeffs + (len1 - 1), state, bits); f->length = len1; } { slong k; for (k = 0; k < len2; k++) fmpz_randbits(g->coeffs + k, state, bits); if ((g->coeffs)[len2-1] == WORD(0)) fmpz_randtest_not_zero(g->coeffs + (len2 - 1), state, bits); g->length = len2; } loop: timeit_start(t[0]); for (l = 0; l < loops; l++) fmpz_poly_compose_horner(h, f, g); timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) fmpz_poly_compose_divconquer(h, f, g); timeit_stop(t[1]); for (c = 0; c < nalgs; c++) if (t[c]->cpu <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]->cpu; reps += loops; } if (s[0] <= s[1]) X[i][j] = 0; else X[i][j] = 1; } flint_printf("len1 = %d, time = %wdms\n", len1, s[0] + s[1]), fflush(stdout); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); /* Print 2-D ASCII image of the winning algorithms */ for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) flint_printf("%d", X[i][j]); flint_printf("\n"); } flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_poly/profile/p-div_preinv.c000066400000000000000000000060051461254215100216500ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #define BITS 10 typedef struct { int algo; slong length; } info_t; void random_fmpz_poly(fmpz_poly_t pol, flint_rand_t state, slong length) { fmpz * arr; slong i; fmpz_poly_fit_length(pol, length); arr = pol->coeffs; for (i = 0; i < length; i++) fmpz_randbits(arr + i, state, BITS); _fmpz_poly_set_length(pol, length); _fmpz_poly_normalise(pol); } void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong length = info->length, i, j; int algo = info->algo; int scale; fmpz_poly_t p1, p2, b, q, r, pinv; FLINT_TEST_INIT(state); scale = 100; if (length >= 50) scale = 10; if (length >= 500) scale = 4; fmpz_poly_init(pinv); fmpz_poly_init(p1); fmpz_poly_init(p2); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); for (i = 0; i < count; i++) { random_fmpz_poly(p1, state, 2*length - 1); random_fmpz_poly(p2, state, length); fmpz_set_ui(p2->coeffs + p2->length - 1, 1); /* p2 must be monic */ fmpz_poly_preinvert(pinv, p2); if (algo) { prof_start(); for (j = 0; j < scale; j++) { fmpz_poly_div_preinv(r, p1, p2, pinv); } prof_stop(); } else { prof_start(); for (j = 0; j < scale; j++) { fmpz_poly_div(r, p1, p2); } prof_stop(); } } fmpz_poly_clear(pinv); fmpz_poly_clear(p1); fmpz_poly_clear(p2); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("fmpz_poly_rem with precomputed powers\n"); flint_printf("bits = %wd\n", BITS); for (k = 1; k <= 1000; k = (slong) ceil(1.1*k)) { info.length = k; info.algo = 0; scale = 100; if (k >= 50) scale = 10; if (k >= 500) scale = 4; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("Standard: length %wd, min %.3g ms, max %.3g ms\n", info.length, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); info.algo = 1; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("With powers: length %wd, min %.3g ms, max %.3g ms\n\n", info.length, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); } return 0; } flint-3.1.3/src/fmpz_poly/profile/p-gcd.c000066400000000000000000000044171461254215100202450ustar00rootroot00000000000000/* Copyright 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #define LENGTH 100 typedef struct { slong bits; } info_t; void random_fmpz_poly(fmpz_poly_t pol, flint_rand_t state, slong bits) { fmpz * arr; slong i; fmpz_poly_fit_length(pol, LENGTH); arr = pol->coeffs; for (i = 0; i < LENGTH; i++) fmpz_randbits(arr + i, state, bits); _fmpz_poly_set_length(pol, LENGTH); _fmpz_poly_normalise(pol); } void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong bits = info->bits, i, j; int scale; fmpz_poly_t p1, p2, a, b, c, g; FLINT_TEST_INIT(state); scale = 100; if (bits >= 50) scale = 10; if (bits >= 500) scale = 4; fmpz_poly_init(p1); fmpz_poly_init(p2); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(g); for (i = 0; i < count; i++) { random_fmpz_poly(a, state, bits); random_fmpz_poly(b, state, bits); random_fmpz_poly(c, state, bits); fmpz_poly_mul(p1, a, c); fmpz_poly_mul(p2, b, c); prof_start(); for (j = 0; j < scale; j++) { fmpz_poly_gcd(g, p1, p2); } prof_stop(); } fmpz_poly_clear(p1); fmpz_poly_clear(p2); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(g); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("fmpz_poly_gcd\n"); flint_printf("length = %wd\n", LENGTH); for (k = 31; k <= 1000; k += 31) { info.bits = k; scale = 100; if (k >= 50) scale = 10; if (k >= 500) scale = 4; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("bits %wd, min %.3g ms, max %.3g ms\n", info.bits, (min/scale)/1000.0, (max/scale)/1000.0 ); } return 0; } flint-3.1.3/src/fmpz_poly/profile/p-mul.c000066400000000000000000000136261461254215100203070ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" #include "profiler.h" /* Definitions for the parameters of the timing process. lenlo Minimum length lenhi Maximum length lenh Step size for the length bitslo Minimum bit size bitshi Maximum bit size bitsh Step size for the bit size cols Number of different lengths rows Number of different bit sizes cpumin Minimum number of ms spent on each test case ncases Number of test cases per point (length, bit size) nalgs Number of algorithms img Whether an RGB coloured image should be produced imgname File name for image */ #define lenlo 1 #define lenhi 60 #define lenh 1 #define bitslo 16 #define bitshi 2048 #define bitsh 32 #define cols ((lenhi + 1 - lenlo + (lenh - 1)) / lenh) #define rows ((bitshi + 1 - bitslo + (bitsh - 1)) / bitsh) #define cpumin 10 #define ncases 1 #define nalgs 3 #define img 1 #define imgname "out.ppm" /* Write a binary 24-bit ppm image. */ int write_rgb_ppm(const char* file_name, unsigned char* pixels, unsigned int width, unsigned int height) { FILE* file = fopen(file_name, "wb"); if (file == NULL) return -1; flint_fprintf(file, "P6\n%d %d\n255\n", width, height); fwrite(pixels, sizeof(unsigned char), width * height * 3, file); fclose(file); return 0; } int main(void) { int i, j, len, bits; int X[rows][cols]; double T[rows][cols][nalgs]; fmpz_poly_t f, g, h; FLINT_TEST_INIT(state); fmpz_poly_init2(f, lenhi); fmpz_poly_init2(g, lenhi); fmpz_poly_init2(h, 2*lenhi - 1); for (len = lenlo, j = 0; len <= lenhi; len += lenh, j++) { slong s[nalgs]; for (bits = bitslo, i = 0; bits <= bitshi; bits += bitsh, i++) { int c, n, reps = 0; for (c = 0; c < nalgs; c++) s[c] = WORD(0); for (n = 0; n < ncases; n++) { timeit_t t[nalgs]; int l, loops = 1; /* Construct random polynomials f and g */ { slong k; for (k = 0; k < len; k++) { fmpz_randbits(f->coeffs + k, state, bits); fmpz_randbits(g->coeffs + k, state, bits); } if ((f->coeffs)[len-1] == WORD(0)) fmpz_randtest_not_zero(f->coeffs + (len - 1), state, bits); if ((g->coeffs)[len-1] == WORD(0)) fmpz_randtest_not_zero(g->coeffs + (len - 1), state, bits); f->length = len; g->length = len; } loop: timeit_start(t[0]); for (l = 0; l < loops; l++) fmpz_poly_mul_classical(h, f, g); timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) fmpz_poly_mul_karatsuba(h, f, g); timeit_stop(t[1]); timeit_start(t[2]); for (l = 0; l < loops; l++) fmpz_poly_mul_KS(h, f, g); timeit_stop(t[2]); for (c = 0; c < nalgs; c++) if (t[c]->cpu <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]->cpu; reps += loops; } for (c = 0; c < nalgs; c++) T[i][j][c] = s[c] / (double) reps; if (s[0] <= s[1] && s[0] <= s[2]) X[i][j] = 0; else if (s[1] <= s[2]) X[i][j] = 1; else X[i][j] = 2; } { slong sum = 0, c; for (c = 0; c < nalgs; c++) sum += s[c]; flint_printf("len = %d, time = %wdms\n", len, sum), fflush(stdout); } } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); /* Print 2-D ASCII image of the winning algorithms */ for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) flint_printf("%d", X[i][j]); flint_printf("\n"); } /* Print 2-D coloured image to file */ if (img) { unsigned char * PIXELS; int k; PIXELS = (unsigned char *) flint_malloc(3 * rows * cols * sizeof(unsigned char)); k = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { double max = DBL_MIN, v[nalgs]; int m; for (m = 0; m < nalgs; m++) { v[m] = T[i][j][m] - T[i][j][X[i][j]]; if (v[m] > max) max = v[m]; } for (m = 0; m < nalgs; m++) { v[m] = (max - v[m]) / max; PIXELS[k++] = (unsigned char) (v[m] * 255); } for (; m < 3; m++) PIXELS[k++] = (unsigned char) 0; } } k = write_rgb_ppm(imgname, PIXELS, cols, rows); flint_free(PIXELS); if (k) { flint_printf("Exception: writing ppm image failed\n"); } } flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_poly/profile/p-mul_triangle.c000066400000000000000000000157451461254215100222000ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" #include "profiler.h" /* Definitions for the parameters of the timing process. lenlo Minimum length lenhi Maximum length lenh Factor by which length increases at each step bitslo Minimum bit size bitshi Maximum bit size bitsh Factor by which bitsize increases at each step cutoff Maximum product of length*bits cols Number of different lengths rows Number of different bit sizes cpumin Minimum number of ms spent on each test case ncases Number of test cases per point (length, bit size) nalgs Number of algorithms img Whether an RGB coloured image should be produced imgname File name for image */ #define lenlo 16 #define lenhi 131072 #define lenh 2 #define bitslo 256 #define bitshi 67108864 #define bitsh 2 #define cutoff WORD(22000000000) #define cols ((slong)(log((double)lenhi/(double)lenlo)/log(lenh) + 1.5)) #define rows ((slong)(log((double)bitshi/(double)bitslo)/log(bitsh) + 1.5)) #define cpumin 100 #define ncases 1 #define nalgs 2 #define img 1 #define imgname "out.ppm" /* Write a binary 24-bit ppm image. */ int write_rgb_ppm(const char* file_name, unsigned char* pixels, unsigned int width, unsigned int height) { FILE* file = fopen(file_name, "wb"); if (file == NULL) return -1; flint_fprintf(file, "P6\n%d %d\n255\n", width, height); fwrite(pixels, sizeof(unsigned char), width * height * 3, file); fclose(file); return 0; } int main(void) { slong i, j, k, len, bits; int X[rows][cols]; double T[rows][cols][nalgs]; fmpz_poly_t f, g, h; FLINT_TEST_INIT(state); fmpz_poly_init2(f, lenhi); fmpz_poly_init2(g, lenhi); fmpz_poly_init2(h, 2*lenhi - 1); for (len = lenlo, j = 0; len <= lenhi; len *= lenh, j++) { slong s[nalgs], sum; for (i = 0; i < nalgs; i++) s[i] = 0; sum = 0; for (bits = bitslo, i = 0; bits <= bitshi; bits *= bitsh, i++) { int c, n, reps = 0, none = 0; for (c = 0; c < nalgs; c++) s[c] = WORD(0); for (n = 0; n < ncases; n++) { timeit_t t[nalgs]; int l, loops = 1; if (bits*len <= cutoff) { /* Construct random polynomials f and g */ { slong k; for (k = 0; k < len; k++) { fmpz_randbits(f->coeffs + k, state, bits); fmpz_randbits(g->coeffs + k, state, bits); } if ((f->coeffs)[len-1] == WORD(0)) fmpz_randtest_not_zero(f->coeffs + (len - 1), state, bits); if ((g->coeffs)[len-1] == WORD(0)) fmpz_randtest_not_zero(g->coeffs + (len - 1), state, bits); f->length = len; g->length = len; } loop: timeit_start(t[0]); for (l = 0; l < loops; l++) fmpz_poly_mul_KS(h, f, g); timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) fmpz_poly_mul_SS(h, f, g); timeit_stop(t[1]); for (c = 0; c < nalgs; c++) if (t[c]->cpu <= cpumin) { loops *= 2; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]->cpu; reps += loops; } else none = 1; } for (c = 0; c < nalgs; c++) T[i][j][c] = s[c] / (double) reps; if (none) X[i][j] = -1; else if (s[0] <= s[1]) /* && s[0] <= s[2]) */ X[i][j] = 0; /* else if (s[1] <= s[2]) */ /* X[i][j] = 1; */ else X[i][j] = 1; /* X[i][j] = 2; */ if (s[0] != 0) { sum = 0; for (c = 0; c < nalgs; c++) sum += s[c]; } } flint_printf("len = %wd, time = %wdms\n", len, sum), fflush(stdout); for (k = 0; k < rows; k++) { if (X[k][j] == -1) flint_printf(" "); else flint_printf("%d", X[k][j]); } flint_printf("\n"); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); /* Print 2-D ASCII image of the winning algorithms */ for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { if (X[i][j] == -1) flint_printf(" "); else flint_printf("%d", X[i][j]); } flint_printf("\n"); } /* Print 2-D coloured image to file */ if (img) { unsigned char * PIXELS; int k; PIXELS = (unsigned char *) flint_malloc(3 * rows * cols * sizeof(unsigned char)); k = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { double max = DBL_MIN, v[nalgs]; int m; if (X[i][j] == -1) { for (m = 0; m < 3; m++) PIXELS[k++] = (unsigned char) 0; } else { for (m = 0; m < nalgs; m++) { v[m] = T[i][j][m] - T[i][j][X[i][j]]; if (v[m] > max) max = v[m]; } for (m = 0; m < nalgs; m++) { v[m] = (max - v[m]) / max; PIXELS[k++] = (unsigned char) (v[m] * 255); } for (; m < 3; m++) PIXELS[k++] = (unsigned char) 0; } } } k = write_rgb_ppm(imgname, PIXELS, cols, rows); flint_free(PIXELS); if (k) { flint_printf("Exception: writing ppm image failed\n"); } } flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_poly/profile/p-pow.c000066400000000000000000000065751461254215100203240ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" #include "profiler.h" #define lenlo 1 #define lenhi 100 #define lenh 5 #define bitslo 16 #define bitshi 512 #define bitsh 32 #define explo 2 #define exphi 140 #define exph 5 #define cols ((lenhi + 1 - lenlo + (lenh - 1)) / lenh) #define rows ((bitshi + 1 - bitslo + (bitsh - 1)) / bitsh) #define height ((exphi + 1 - explo + (exph - 1)) / exph) #define cpumin 10 #define img 1 int main(void) { int k, exp; fmpz_poly_t f, g; FLINT_TEST_INIT(state); fmpz_poly_init2(f, lenhi); fmpz_poly_init2(g, exphi * (lenhi - 1) + 1); flint_printf("Comparative timing for fmpz_poly_pow\n"); flint_printf("\n"); flint_printf("Length: [%d..%d] with step size %d\n", lenlo, lenhi, lenh); flint_printf("Bit size: [%d..%d] with step size %d\n", bitslo, bitshi, bitsh); flint_printf("Exponents: [%d..%d] with step size %d\n", explo, exphi, exph); flint_printf("\n"); flint_printf("exp len bits (Binary exponentiation) Multinomials\n"); flint_printf("\n"); for (exp = explo, k = 0; exp <= exphi; exp += exph, k++) { int i, j, len, bits; for (len = lenlo, j = 0; len <= lenhi; len += lenh, j++) { for (bits = bitslo, i = 0; bits <= bitshi; bits += bitsh, i++) { timeit_t t[2]; int l, loops = 1, r = 0; slong s[2] = {WORD(0), WORD(0)}; double T[2]; /* Construct random polynomial f of length len */ { slong ell; for (ell = 0; ell < len; ell++) fmpz_randbits(f->coeffs + ell, state, bits); if ((f->coeffs)[len - 1] == WORD(0)) fmpz_randtest_not_zero(f->coeffs + (len - 1), state, bits); f->length = len; } /* Run tests */ loop: timeit_start(t[0]); for (l = 0; l < loops; l++) fmpz_poly_pow_binexp(g, f, exp); timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) fmpz_poly_pow_multinomial(g, f, exp); timeit_stop(t[1]); if (t[0]->cpu <= cpumin || t[1]->cpu <= cpumin) { loops *= 10; goto loop; } s[0] += t[0]->cpu; s[1] += t[1]->cpu; r += loops; T[0] = s[0] / (double) r; T[1] = s[1] / (double) r; flint_printf("%d %d %d %f %f\n", exp, len, bits, T[0], T[1]); fflush(stdout); } } } fmpz_poly_clear(f); fmpz_poly_clear(g); flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_poly/profile/p-pow_binomial.c000066400000000000000000000036331461254215100221660ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" #include "profiler.h" #define lenlo 2 #define lenhi 2 #define lenh 1 #define bits 16 #define elo 26 #define ehi 50 #define eh 1 #define cpumin 100 int main(void) { int len, e; fmpz_poly_t f, g; FLINT_TEST_INIT(state); fmpz_poly_init2(f, lenhi); fmpz_poly_init2(g, ehi * (lenhi - 1) + 1); flint_printf("| len | exp | binomial |\n"); for (len = lenlo; len <= lenhi; len += lenh) { /* Construct random polynomial f of length len */ { slong k; for (k = 0; k < len; k++) fmpz_randbits(f->coeffs + k, state, bits); if ((f->coeffs)[len-1] == WORD(0)) fmpz_randtest_not_zero(f->coeffs + (len-1), state, bits); f->length = len; } for (e = elo; e <= ehi; e += eh) { timeit_t t[1]; int l, loops = 1, r = 0; slong s[1] = {0}; loop: timeit_start(t[0]); for (l = 0; l < loops; l++) fmpz_poly_pow_binomial(g, f, e); timeit_stop(t[0]); if (t[0]->cpu <= cpumin) { loops *= 10; goto loop; } s[0] += t[0]->cpu; r += loops; flint_printf("%d %d %lf\n", len, e, s[0] / (double) r); } } fmpz_poly_clear(f); fmpz_poly_clear(g); flint_randclear(state); return 0; } flint-3.1.3/src/fmpz_poly/profile/p-rem_powers_precomp.c000066400000000000000000000060451461254215100234160ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #define BITS 100 typedef struct { int algo; slong length; } info_t; void random_fmpz_poly(fmpz_poly_t pol, flint_rand_t state, slong length) { fmpz * arr; slong i; fmpz_poly_fit_length(pol, length); arr = pol->coeffs; for (i = 0; i < length; i++) fmpz_randbits(arr + i, state, BITS); _fmpz_poly_set_length(pol, length); _fmpz_poly_normalise(pol); } void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong length = info->length, i, j; int algo = info->algo; int scale; fmpz_poly_t p1, p2, b, q, r; fmpz_poly_powers_precomp_t pinv; FLINT_TEST_INIT(state); scale = 100; if (length >= 50) scale = 10; if (length >= 500) scale = 4; fmpz_poly_init(p1); fmpz_poly_init(p2); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); for (i = 0; i < count; i++) { random_fmpz_poly(p1, state, 2*length - 1); random_fmpz_poly(p2, state, length); fmpz_set_ui(p2->coeffs + p2->length - 1, 1); /* p2 must be monic */ fmpz_poly_powers_precompute(pinv, p2); if (algo) { prof_start(); for (j = 0; j < scale; j++) { fmpz_poly_rem_powers_precomp(r, p1, p2, pinv); } prof_stop(); } else { prof_start(); for (j = 0; j < scale; j++) { fmpz_poly_rem(r, p1, p2); } prof_stop(); } fmpz_poly_powers_clear(pinv); } fmpz_poly_clear(p1); fmpz_poly_clear(p2); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("fmpz_poly_rem with precomputed powers\n"); flint_printf("bits = %wd\n", BITS); for (k = 1; k <= 1000; k = (slong) ceil(1.1*k)) { info.length = k; info.algo = 0; scale = 100; if (k >= 50) scale = 10; if (k >= 500) scale = 4; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("Standard: length %wd, min %.3g ms, max %.3g ms\n", info.length, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); info.algo = 1; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("With powers: length %wd, min %.3g ms, max %.3g ms\n\n", info.length, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); } return 0; } flint-3.1.3/src/fmpz_poly/profile/p-taylor_shift.c000066400000000000000000000075441461254215100222230ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz.h" #include "fmpz_poly.h" #include "profiler.h" int main(int argc, char * argv[]) { fmpz_poly_t f, g, h; fmpz_t c, d; slong bits, len, k, nthreads, minlen, maxlen, minbits, maxbits; double incbits, inclen; flint_rand_t state; flint_randinit(state); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_init(c); fmpz_init(d); fmpz_one(d); nthreads = 1; minlen = 32; maxlen = 100000; inclen = 1.5; minbits = 32; maxbits = 400000; incbits = 2.0; for (k = 0; k < argc - 1; k++) { if (strcmp(argv[k], "-len") == 0) { minlen = maxlen = atoi(argv[k + 1]); if (k + 2 < argc && isdigit(argv[k + 2][0])) maxlen = atoi(argv[k + 2]); if (k + 3 < argc && isdigit(argv[k + 3][0])) inclen = atof(argv[k + 3]); } if (strcmp(argv[k], "-bits") == 0) { minbits = maxbits = atoi(argv[k + 1]); if (k + 2 < argc && isdigit(argv[k + 2][0])) maxbits = atoi(argv[k + 2]); if (k + 3 < argc && isdigit(argv[k + 3][0])) incbits = atof(argv[k + 3]); } if (strcmp(argv[k], "-threads") == 0) nthreads = atoi(argv[k + 1]); } flint_printf("len sizes: "); for (len = minlen; len <= maxlen; len = FLINT_MAX(len + 1, len * inclen)) flint_printf("%wd ", len); flint_printf("\nbit sizes: "); for (bits = minbits; bits <= maxbits; bits = FLINT_MAX(bits + 1, bits * incbits)) flint_printf("%wd ", bits); flint_printf("\nusing up to %wd threads\n\n", nthreads); for (len = minlen; len <= maxlen; len = FLINT_MAX(len + 1, len * inclen)) { for (bits = minbits; bits <= maxbits; bits = FLINT_MAX(bits + 1, bits * incbits)) { fmpz_poly_zero(f); for (k = 0; k < len; k++) { fmpz_randbits(c, state, bits); fmpz_poly_set_coeff_fmpz(f, k, c); } flint_printf("%wd %wd default ", len, bits); TIMEIT_START fmpz_poly_taylor_shift(g, f, d); TIMEIT_STOP /* flint_printf("%wd %wd compose ", len, bits); TIMEIT_START fmpz_poly_one(h); fmpz_poly_set_coeff_si(h, 1, 1); fmpz_poly_compose_divconquer(h, f, h); TIMEIT_STOP */ flint_printf("%wd %wd horner ", len, bits); TIMEIT_START fmpz_poly_taylor_shift_horner(g, f, d); TIMEIT_STOP for (k = 1; k <= nthreads; k *= 2) { flint_printf("%wd %wd dc%wd ", len, bits, k); flint_set_num_threads(k); TIMEIT_START fmpz_poly_taylor_shift_divconquer(g, f, d); TIMEIT_STOP flint_set_num_threads(1); } for (k = 1; k <= nthreads; k *= 2) { flint_printf("%wd %wd mm%wd ", len, bits, k); flint_set_num_threads(k); TIMEIT_START fmpz_poly_taylor_shift_multi_mod(g, f, d); TIMEIT_STOP flint_set_num_threads(1); } flint_printf("\n"); } } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_clear(c); fmpz_clear(d); flint_randclear(state); flint_cleanup(); return 0; } flint-3.1.3/src/fmpz_poly/pseudo_div.c000066400000000000000000000031671461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pseudo_div(fmpz * Q, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) { fmpz * R = _fmpz_vec_init(lenA); _fmpz_poly_pseudo_divrem(Q, R, d, A, lenA, B, lenB, inv); _fmpz_vec_clear(R, lenA); } void fmpz_poly_pseudo_div(fmpz_poly_t Q, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenq; fmpz * q; if (B->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_pseudo_div). Division by zero.\n"); } if (A->length < B->length) { fmpz_poly_zero(Q); *d = 0; return; } lenq = A->length - B->length + 1; if (Q == A || Q == B) q = _fmpz_vec_init(lenq); else { fmpz_poly_fit_length(Q, lenq); q = Q->coeffs; } _fmpz_poly_pseudo_div(q, d, A->coeffs, A->length, B->coeffs, B->length, NULL); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenq; Q->length = lenq; } else _fmpz_poly_set_length(Q, lenq); } flint-3.1.3/src/fmpz_poly/pseudo_divrem_basecase.c000066400000000000000000000061661461254215100223110ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pseudo_divrem_basecase(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) { const fmpz * leadB = B + (lenB - 1); slong iQ = lenA - lenB, iR = lenA - 1; fmpz_t rem; fmpz_init(rem); *d = 0; _fmpz_vec_zero(Q, lenA - lenB + 1); if (R != A) _fmpz_vec_set(R, A, lenA); while (iR >= lenB - 1) { if (inv != NULL) fmpz_fdiv_qr_preinvn(Q + iQ, rem, R + iR, leadB, inv); else fmpz_fdiv_qr(Q + iQ, rem, R + iR, leadB); if (!fmpz_is_zero(rem)) { _fmpz_vec_scalar_mul_fmpz(Q, Q, lenA - lenB + 1, leadB); fmpz_set(Q + iQ, R + iR); _fmpz_vec_scalar_mul_fmpz(R, R, lenA, leadB); (*d)++; } if (lenB > 1) _fmpz_vec_scalar_submul_fmpz(R + (iR - lenB + 1), B, lenB - 1, Q + iQ); fmpz_zero(R + iR); iR--; iQ--; } fmpz_clear(rem); } void fmpz_poly_pseudo_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenq, lenr; fmpz *q, *r; if (B->length == 0) { flint_throw(FLINT_ERROR, "(fmpz_poly_pseudo_divrem_basecase): Division by zero.\n"); } if (Q == R) { flint_throw(FLINT_ERROR, "(fmpz_poly_pseudo_divrem_basecase): " "Output arguments Q and R may not be aliased.\n"); } if (A->length < B->length) { fmpz_poly_zero(Q); fmpz_poly_set(R, A); *d = 0; return; } lenq = A->length - B->length + 1; lenr = A->length; if (Q == A || Q == B) q = _fmpz_vec_init(lenq); else { fmpz_poly_fit_length(Q, lenq); q = Q->coeffs; } if (R == B) r = _fmpz_vec_init(lenr); else { fmpz_poly_fit_length(R, lenr); r = R->coeffs; } _fmpz_poly_pseudo_divrem_basecase(q, r, d, A->coeffs, A->length, B->coeffs, B->length, NULL); for (lenr = B->length - 2; (lenr >= 0) && !r[lenr]; lenr--) ; lenr++; if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenq; Q->length = lenq; } else _fmpz_poly_set_length(Q, lenq); if (R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = A->length; R->length = lenr; } else _fmpz_poly_set_length(R, lenr); } flint-3.1.3/src/fmpz_poly/pseudo_divrem_cohen.c000066400000000000000000000066031461254215100216330ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pseudo_divrem_cohen(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) { const fmpz * leadB = B + (lenB - 1); slong e, lenQ; fmpz_t pow; if (lenB == 1) { fmpz_init(pow); fmpz_pow_ui(pow, leadB, lenA - 1); _fmpz_vec_scalar_mul_fmpz(Q, A, lenA, pow); _fmpz_vec_zero(R, lenA); fmpz_clear(pow); return; } lenQ = lenA - lenB + 1; _fmpz_vec_zero(Q, lenQ); if (R != A) _fmpz_vec_set(R, A, lenA); e = lenA - lenB; /* Unroll the first run of the while loop */ { fmpz_set(Q + (lenQ - 1), R + (lenA - 1)); _fmpz_vec_scalar_mul_fmpz(R, R, lenA - 1, leadB); _fmpz_vec_scalar_submul_fmpz(R + (lenA - lenB), B, lenB - 1, R + (lenA - 1)); fmpz_zero(R + (lenA - 1)); lenA--; FMPZ_VEC_NORM(R, lenA); } while (lenA >= lenB) { _fmpz_vec_scalar_mul_fmpz(Q, Q, lenQ, leadB); fmpz_add(Q + (lenA - lenB), Q + (lenA - lenB), R + (lenA - 1)); _fmpz_vec_scalar_mul_fmpz(R, R, lenA - 1, leadB); _fmpz_vec_scalar_submul_fmpz(R + lenA - lenB, B, lenB - 1, R + (lenA - 1)); fmpz_zero(R + (lenA - 1)); lenA--; FMPZ_VEC_NORM(R, lenA); e--; } fmpz_init(pow); fmpz_pow_ui(pow, leadB, e); _fmpz_vec_scalar_mul_fmpz(Q, Q, lenQ, pow); _fmpz_vec_scalar_mul_fmpz(R, R, lenA, pow); fmpz_clear(pow); } void fmpz_poly_pseudo_divrem_cohen(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenq, lenr; fmpz *q, *r; if (B->length == 0) { flint_throw(FLINT_ERROR, "(fmpz_poly_pseudo_divrem_cohen): Division by zero.\n"); } if (Q == R) { flint_throw(FLINT_ERROR, "(fmpz_poly_pseudo_divrem_cohen): " "Output arguments Q and R may not be aliased.\n"); } if (A->length < B->length) { fmpz_poly_zero(Q); fmpz_poly_set(R, A); return; } lenq = A->length - B->length + 1; lenr = A->length; if ((Q == A) || (Q == B)) q = _fmpz_vec_init(lenq); else { fmpz_poly_fit_length(Q, lenq); q = Q->coeffs; } if (R == B) r = _fmpz_vec_init(lenr); else { fmpz_poly_fit_length(R, lenr); r = R->coeffs; } _fmpz_poly_pseudo_divrem_cohen(q, r, A->coeffs, A->length, B->coeffs, B->length); for (lenr = B->length - 1; (lenr >= 0) && r[lenr] == WORD(0); lenr--) ; lenr++; if ((Q == A) || (Q == B)) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenq; Q->length = lenq; } else _fmpz_poly_set_length(Q, lenq); if (R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = A->length; R->length = lenr; } else _fmpz_poly_set_length(R, lenr); } flint-3.1.3/src/fmpz_poly/pseudo_divrem_divconquer.c000066400000000000000000000241351461254215100227160ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" static void __fmpz_poly_pseudo_divrem_divconquer(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) { if (lenB <= 16 || (lenA > 2 * lenB - 1 && lenA < 128)) { _fmpz_poly_pseudo_divrem_basecase(Q, R, d, A, lenA, B, lenB, inv); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; const fmpz * d1 = B + n2; const fmpz * d2 = B; const fmpz * d3 = B + n1; const fmpz * d4 = B; if (lenA <= lenB + n2 - 1) { fmpz *p1, *r1, *d2q1; fmpz *f; /* Shift A right by n1, zero the bottom n2 - 1 coeffs; call this p1 */ p1 = (fmpz *) flint_malloc((lenA - n1) * sizeof(fmpz)); { slong i; flint_mpn_zero((mp_ptr) p1, n2 - 1); for (i = n2 - 1; i < lenA - n1; i++) p1[i] = (A + n1)[i]; } /* Compute p1 div d3, at most a 2 n2 - 1 by n2 division, leaving lenA - lenB + 1 <= n2 terms in the quotient */ r1 = R + n1; _fmpz_poly_pseudo_divrem_divconquer(Q, r1, d, p1, lenA - n1, d3, n2, inv); flint_free(p1); /* Push the relevant {n2 - 1} terms of the remainder to the top of {R, lenA} */ { slong i; for (i = n2 - 2; i >= 0; i--) fmpz_swap(R + lenA - (n2 - 1) + i, r1 + i); r1 = R + lenA - (n2 - 1); } /* Compute d2q1 = Q d4 of length lenA - n2, which is at most n1 + n2 - 1 terms */ d2q1 = R; _fmpz_poly_mul(d2q1, d4, n1, Q, lenA - lenB + 1); /* Compute R = L^d R', where R' is the terms of A we have not dealt, of which there are at most n1 + n2 - 1; that is, Set R to {A, n1 + n2 - 1} * f + r1 x^n1 - d2q1 */ _fmpz_vec_neg(R, R, lenA - n2); _fmpz_vec_add(R + n1, R + n1, R + lenA - n2 + 1, lenA - lenB); _fmpz_vec_swap(R + lenA - n2, R + 2 * lenA - lenB + 1 - n2, n2 - (lenA - lenB + 1)); f = R + lenB - 1; fmpz_pow_ui(f, B + (lenB - 1), *d); _fmpz_vec_scalar_addmul_fmpz(R, A, n1 + n2 - 1, f); } else if (lenA > 2 * lenB - 1) { /* XXX: In this case, we expect A to be modifiable */ ulong s1, s2; const slong shift = lenA - 2 * lenB + 1; fmpz * q1 = Q + shift; fmpz * q2 = Q; fmpz * r1 = R; fmpz *p1, *t; fmpz_t f; fmpz_init(f); /* Shift A right until it is of length 2 lenB - 1, call this p1; zero the bottom lenB - 1 coeffs */ p1 = (fmpz *) flint_malloc((2 * lenB - 1) * sizeof(fmpz)); { slong i; flint_mpn_zero((mp_ptr) p1, lenB - 1); for (i = lenB - 1; i < 2*lenB - 1; i++) p1[i] = (A + shift)[i]; } /* Set q1 to p1 div B, a 2 lenB - 1 by lenB division, so q1 ends up being at most length lenB; r1 is of length at most lenB - 1 */ _fmpz_poly_pseudo_divrem_divconquer(q1, r1, &s1, p1, 2 * lenB - 1, B, lenB, inv); flint_free(p1); /* Compute t = L^s1 a2 + r1 x^shift, of length at most lenA - lenB since r1 is of length at most lenB - 1. Here a2 is what remains of A after the first lenR coefficients are removed */ t = (fmpz *) A; fmpz_pow_ui(f, B + (lenB - 1), s1); _fmpz_vec_scalar_mul_fmpz(t, A, lenA - lenB, f); _fmpz_vec_add(t + shift, t + shift, r1, lenB - 1); /* Compute q2 = t div B; it is a smaller division than the original since len(t) <= lenA - lenB, and r2 has length at most lenB - 1 */ _fmpz_poly_pseudo_divrem_divconquer(q2, R, &s2, t, lenA - lenB, B, lenB, inv); /* Write out Q = L^s2 q1 x^shift + q2, of length at most lenB + shift. Note q2 has length at most shift since it is at most an lenA - lenB by lenB division; q1 cannot have length zero since we are doing pseudo division */ fmpz_pow_ui(f, B + (lenB - 1), s2); _fmpz_vec_scalar_mul_fmpz(q1, q1, lenB, f); *d = s1 + s2; fmpz_clear(f); } else /* n1 + 2 n2 - 1 < lenA <= 2 lenB - 1 */ { fmpz * q1 = Q + n2; fmpz * q2 = Q; fmpz * r1 = R; fmpz * d2q1 = R + (n1 - 1); fmpz *p1, *t; fmpz_t f; ulong s1, s2; fmpz_init(f); /* Set p1 to the top lenA - 2 n2 coeffs of A, clearing the bottom n1 - 1 coeffs */ p1 = (fmpz *) flint_malloc((lenA - 2 * n2) * sizeof(fmpz)); { slong i; flint_mpn_zero((mp_ptr) p1, n1 - 1); for (i = n1 - 1; i < lenA - 2 * n2; i++) p1[i] = (A + 2 * n2)[i]; } /* Set q1 to p1 div d1, at most a 2 n1 - 1 by n1 division, so q1 ends up being of length at most n1; r1 is of length n1 - 1 */ _fmpz_poly_pseudo_divrem_divconquer(q1, r1, &s1, p1, lenA - 2 * n2, d1, n1, inv); flint_free(p1); /* Compute d2q1 = d2q1, of length lenA - lenB Note lenA - lenB <= lenB - 1 <= 2 n2 and lenA - (n1 - 1) > 2 n2, so we can store d2q1 in the top 2 n2 coeffs of R */ if (n2 >= lenA - n1 - 2 * n2 + 1) _fmpz_poly_mul(d2q1, d2, n2, q1, lenA - (n1 + 2 * n2 - 1)); else _fmpz_poly_mul(d2q1, q1, lenA - (n1 + 2 * n2 - 1), d2, n2); /* Compute t = L^s1 * (a2 x^{n1 + n2 - 1} + a3) + r1 x^{2 n2} - d2q1 x^n2 of length at most lenB + n2 - 1, since r1 is of length at most n1 - 1 and d2q1 is of length at most n1 + n2 - 1 */ t = _fmpz_vec_init(n1 + 2 * n2 - 1); fmpz_pow_ui(f, B + (lenB - 1), s1); _fmpz_vec_scalar_mul_fmpz(t, A, n1 + 2 * n2 - 1, f); _fmpz_vec_add(t + 2 * n2, t + 2 * n2, r1, n1 - 1); _fmpz_vec_sub(t + n2, t + n2, d2q1, lenA - lenB); /* Compute q2 = t div B and set R to the remainder, at most a lenB + n2 - 1 by lenB division, so q2 is of length at most n2 */ _fmpz_poly_pseudo_divrem_divconquer(q2, R, &s2, t, lenB + n2 - 1, B, lenB, inv); _fmpz_vec_clear(t, n1 + 2 * n2 - 1); /* Write Q = L^s2 q1 x^n2 + q2; note len(q1) is non-zero since we are performing pseudo division */ fmpz_pow_ui(f, B + (lenB - 1), s2); _fmpz_vec_scalar_mul_fmpz(q1, q1, lenA - lenB + 1 - n2, f); *d = s1 + s2; fmpz_clear(f); } } } void _fmpz_poly_pseudo_divrem_divconquer(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) { if (lenA <= 2 * lenB - 1) { __fmpz_poly_pseudo_divrem_divconquer(Q, R, d, A, lenA, B, lenB, inv); } else /* lenA > 2 * lenB - 1 */ { fmpz *S = _fmpz_vec_init(lenA); _fmpz_vec_set(S, A, lenA); __fmpz_poly_pseudo_divrem_divconquer(Q, R, d, S, lenA, B, lenB, inv); _fmpz_vec_clear(S, lenA); } } void fmpz_poly_pseudo_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenq, lenr; fmpz *q, *r; if (B->length == 0) { flint_throw(FLINT_ERROR, "(fmpz_poly_pseudo_divrem_divconquer): Division by zero.\n"); } if (Q == R) { flint_throw(FLINT_ERROR, "(fmpz_poly_pseudo_divrem_divconquer): " "Output arguments Q and R may not be aliased.\n"); } if (A->length < B->length) { fmpz_poly_zero(Q); fmpz_poly_set(R, A); *d = 0; return; } lenq = A->length - B->length + 1; lenr = A->length; if (Q == A || Q == B) q = _fmpz_vec_init(lenq); else { fmpz_poly_fit_length(Q, lenq); q = Q->coeffs; } if (R == A || R == B) r = _fmpz_vec_init(lenr); else { fmpz_poly_fit_length(R, lenr); r = R->coeffs; } _fmpz_poly_pseudo_divrem_divconquer(q, r, d, A->coeffs, A->length, B->coeffs, B->length, NULL); lenr = B->length - 1; FMPZ_VEC_NORM(r, lenr); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenq; Q->length = lenq; } else _fmpz_poly_set_length(Q, lenq); if (R == A || R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = A->length; R->length = lenr; } else _fmpz_poly_set_length(R, lenr); } flint-3.1.3/src/fmpz_poly/pseudo_rem.c000066400000000000000000000033231461254215100177500ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pseudo_rem(fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv) { fmpz * Q = _fmpz_vec_init(lenA + lenB - 1); _fmpz_poly_pseudo_divrem(Q, R, d, A, lenA, B, lenB, inv); _fmpz_vec_clear(Q, lenA + lenB - 1); } void fmpz_poly_pseudo_rem(fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenr; fmpz * r; if (B->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_pseudo_rem). Division by zero.\n"); } if (A->length < B->length) { fmpz_poly_set(R, A); *d = 0; return; } lenr = A->length; if (R == B || R == A) r = _fmpz_vec_init(lenr); else { fmpz_poly_fit_length(R, lenr); r = R->coeffs; } _fmpz_poly_pseudo_rem(r, d, A->coeffs, A->length, B->coeffs, B->length, NULL); for (lenr = B->length - 2; (lenr >= 0) && !r[lenr]; lenr--) ; lenr++; if (R == B || R == A) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = A->length; R->length = lenr; } else _fmpz_poly_set_length(R, lenr); } flint-3.1.3/src/fmpz_poly/pseudo_rem_cohen.c000066400000000000000000000040451461254215100211260ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_pseudo_rem_cohen(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) { const fmpz * leadB = B + (lenB - 1); slong e; fmpz_t pow; if (lenB == 1) { _fmpz_vec_zero(R, lenA); return; } if (R != A) _fmpz_vec_set(R, A, lenA); e = lenA - lenB + 1; while (lenA >= lenB) { _fmpz_vec_scalar_mul_fmpz(R, R, lenA - 1, leadB); _fmpz_vec_scalar_submul_fmpz(R + (lenA - lenB), B, lenB - 1, R + (lenA - 1)); fmpz_zero(R + (lenA - 1)); lenA--; FMPZ_VEC_NORM(R, lenA); e--; } fmpz_init(pow); fmpz_pow_ui(pow, leadB, e); _fmpz_vec_scalar_mul_fmpz(R, R, lenA, pow); fmpz_clear(pow); } void fmpz_poly_pseudo_rem_cohen(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenr; fmpz *r; if (B->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_pseudo_rem_cohen). Division by zero.\n"); } if (A->length < B->length) { fmpz_poly_set(R, A); return; } lenr = A->length; if (R == B) r = _fmpz_vec_init(lenr); else { fmpz_poly_fit_length(R, lenr); r = R->coeffs; } _fmpz_poly_pseudo_rem_cohen(r, A->coeffs, A->length, B->coeffs, B->length); for (lenr = B->length - 1; (lenr >= 0) && (r[lenr] == WORD(0)); lenr--) ; lenr++; if (R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = A->length; R->length = lenr; } else _fmpz_poly_set_length(R, lenr); } flint-3.1.3/src/fmpz_poly/randtest.c000066400000000000000000000066041461254215100174370ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2016 Vincent Delecroix Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" void fmpz_poly_randtest_irreducible1(fmpz_poly_t p, flint_rand_t state, slong len, mp_bitcnt_t bits) { slong i; fmpz_t c; fmpz_mod_ctx_t ctx; fmpz_mod_poly_t q; len = 1 + n_randint(state, len); fmpz_init(c); if (bits == 1) fmpz_set_ui(c, 2); else fmpz_randprime(c, state, bits, 0); fmpz_mod_ctx_init(ctx, c); fmpz_mod_poly_init(q, ctx); fmpz_mod_poly_randtest_irreducible(q, state, len, ctx); fmpz_mod_poly_get_fmpz_poly(p, q, ctx); /* After lifting, the coefficients belong to {0, ..., c-1}. We now */ /* randomly subtract c so that some of them become negative. */ for (i = 0; i < p->length; i++) { if (n_randint(state, 3) == 0 && !(bits == 1 && fmpz_is_zero(p->coeffs + i))) fmpz_sub(p->coeffs + i, p->coeffs + i, c); } fmpz_poly_content(c, p); fmpz_poly_scalar_divexact_fmpz(p, p, c); fmpz_mod_poly_clear(q, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(c); } void fmpz_poly_randtest_irreducible2(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits) { while (1) { slong i; fmpz_poly_factor_t fac; do { fmpz_poly_randtest(pol, state, len, bits); } while (fmpz_poly_degree(pol) < 1); fmpz_poly_factor_init(fac); fmpz_poly_factor(fac, pol); i = n_randint(state, fac->num); if (FLINT_ABS(fmpz_poly_max_bits(fac->p + i)) <= bits) { fmpz_poly_set(pol, fac->p + i); fmpz_poly_factor_clear(fac); break; } fmpz_poly_factor_clear(fac); } } void fmpz_poly_randtest_irreducible(fmpz_poly_t pol, flint_rand_t state, slong len, mp_bitcnt_t bits) { if (n_randint(state, 2)) fmpz_poly_randtest_irreducible1(pol, state, len, bits); else fmpz_poly_randtest_irreducible2(pol, state, len, bits); } void fmpz_poly_randtest(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) { fmpz_poly_fit_length(f, len); _fmpz_vec_randtest(f->coeffs, state, len, bits); _fmpz_poly_set_length(f, len); _fmpz_poly_normalise(f); } void fmpz_poly_randtest_unsigned(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) { fmpz_poly_fit_length(f, len); _fmpz_vec_randtest_unsigned(f->coeffs, state, len, bits); _fmpz_poly_set_length(f, len); _fmpz_poly_normalise(f); } void fmpz_poly_randtest_not_zero(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits) { if ((bits == 0) || (len == 0)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_randtest_not_zero). bits or len is zero.\n"); } fmpz_poly_randtest(f, state, len, bits); if (fmpz_poly_is_zero(f)) fmpz_poly_set_ui(f, 1); } flint-3.1.3/src/fmpz_poly/randtest_no_real_root.c000066400000000000000000000054111461254215100221740ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _quadratic(fmpz_poly_t p, flint_rand_t state, flint_bitcnt_t bits) { fmpz *a, *b, *c; fmpz_poly_fit_length(p, 3); a = p->coeffs + 2; b = p->coeffs + 1; c = p->coeffs + 0; fmpz_randtest_not_zero(a, state, bits); fmpz_randtest_not_zero(c, state, bits); if (fmpz_sgn(a) != fmpz_sgn(c)) fmpz_neg(a, a); /* now choose b so that b^2 < 4ac */ fmpz_randtest(b, state, (fmpz_bits(a) + fmpz_bits(c))/2); _fmpz_poly_set_length(p, 3); } void _even(fmpz_poly_t p, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong n, i; /* make len odd (= 2n + 1) */ if (len % 2 == 0) len -= 1; n = len / 2; fmpz_poly_fit_length(p, len); /* fill entries from 0 to n included with non-negative coeffs */ /* set the remaining ones to zero */ _fmpz_vec_randtest(p->coeffs, state, n + 1, bits); for (i = 0; i <= n; i++) { if (fmpz_sgn(p->coeffs + i) == -1) fmpz_neg(p->coeffs + i, p->coeffs + i); } for (i = n + 1; i < len; i++) fmpz_zero(p->coeffs + i); /* swap the entries k with len-k for odd k */ for(i = 1; i <= n; i += 2) fmpz_swap(p->coeffs + i, p->coeffs + len - i); /* possibly sets the 0-th coefficient to 1 */ if (fmpz_is_zero(p->coeffs)) fmpz_one(p->coeffs); /* clean */ _fmpz_poly_set_length(p, len); _fmpz_poly_normalise(p); } void fmpz_poly_randtest_no_real_root(fmpz_poly_t p, flint_rand_t state, slong len, flint_bitcnt_t bits) { if (len <= 0) flint_throw(FLINT_ERROR, "got non-positive length in %s\n", __func__); else if (len < 3) { fmpz_poly_one(p); } else if (len <= 4) { /* degree 2 polynomial */ _quadratic(p, state, bits); } else if (bits < 3) { /* polynomial with only even degrees and non-negative coeffs */ _even(p, state, len, bits); } else { /* we make a product of a quadratic and a polynomial of the */ /* form a0 + a2 X^2 + a4 X^4 + ... with a0 > 0 and a{2i} >= 0 */ fmpz_poly_t q; flint_bitcnt_t bits1; fmpz_poly_init(q); bits1 = 1 + n_randint(state, bits - 2); _quadratic(q, state, bits1); _even(p, state, (len-2)/2, bits - bits1 - 1); fmpz_poly_mul(p, p, q); fmpz_poly_clear(q); } } flint-3.1.3/src/fmpz_poly/realloc.c000066400000000000000000000021441461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_realloc(fmpz_poly_t poly, slong alloc) { if (alloc == 0) /* Clear up, reinitialise */ { fmpz_poly_clear(poly); fmpz_poly_init(poly); return; } if (poly->alloc) /* Realloc */ { fmpz_poly_truncate(poly, alloc); poly->coeffs = (fmpz *) flint_realloc(poly->coeffs, alloc * sizeof(fmpz)); if (alloc > poly->alloc) flint_mpn_zero((mp_ptr) (poly->coeffs + poly->alloc), alloc - poly->alloc); } else /* Nothing allocated already so do it now */ { poly->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); } poly->alloc = alloc; } flint-3.1.3/src/fmpz_poly/rem.c000066400000000000000000000030061461254215100163670ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_rem(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) { if (lenA < 15) { _fmpz_poly_rem_basecase(R, A, lenA, B, lenB); } else { fmpz *Q = _fmpz_vec_init(lenA - lenB + 1); _fmpz_poly_divrem(Q, R, A, lenA, B, lenB, 0); _fmpz_vec_clear(Q, lenA - lenB + 1); } } void fmpz_poly_rem(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) { const slong lenA = A->length, lenB = B->length; fmpz *r; if (lenB == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_rem). Division by zero.\n"); } if (lenA < lenB) { fmpz_poly_set(R, A); return; } if (R == A || R == B) { r = _fmpz_vec_init(lenA); } else { fmpz_poly_fit_length(R, lenA); r = R->coeffs; } _fmpz_poly_rem(r, A->coeffs, lenA, B->coeffs, lenB); if (R == A || R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenB - 1; } _fmpz_poly_set_length(R, lenA); _fmpz_poly_normalise(R); } flint-3.1.3/src/fmpz_poly/rem_basecase.c000066400000000000000000000035031461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_rem_basecase(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB) { const fmpz * leadB = B + (lenB - 1); fmpz_t q; fmpz_init(q); if (R != A) _fmpz_vec_set(R, A, lenA); for ( ; lenA >= lenB; lenA--) { if (fmpz_cmpabs(R + lenA - 1, leadB) >= 0) { fmpz_fdiv_q(q, R + lenA - 1, leadB); _fmpz_vec_scalar_submul_fmpz(R + lenA - lenB, B, lenB, q); } } fmpz_clear(q); } void fmpz_poly_rem_basecase(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B) { slong lenr; fmpz *r; if (B->length == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_rem_basecase). Division by zero.\n"); } if (A->length < B->length) { fmpz_poly_set(R, A); return; } lenr = A->length; if (R == B) r = _fmpz_vec_init(lenr); else { fmpz_poly_fit_length(R, lenr); r = R->coeffs; } _fmpz_poly_rem_basecase(r, A->coeffs, A->length, B->coeffs, B->length); if (R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenr; R->length = lenr; } else _fmpz_poly_set_length(R, lenr); _fmpz_poly_normalise(R); } flint-3.1.3/src/fmpz_poly/rem_powers_precomp.c000066400000000000000000000035131461254215100215160ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_rem_powers_precomp(fmpz * A, slong m, const fmpz * B, slong n, fmpz ** const powers) { slong i; fmpz * prod; if (m >= 2*n) { _fmpz_poly_rem_powers_precomp(A + n, m - n, B, n, powers); m = 2*n - 1; while (m && fmpz_is_zero(A + m - 1)) m--; } if (m < n) return; prod = _fmpz_vec_init(n - 1); for (i = n - 1; i < m; i++) { _fmpz_vec_scalar_mul_fmpz(prod, powers[i], n - 1, A + i); _fmpz_poly_add(A, A, n - 1, prod, n - 1); } _fmpz_vec_clear(prod, n - 1); } void fmpz_poly_rem_powers_precomp(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_powers_precomp_t B_inv) { fmpz_poly_t tR; fmpz *r; slong len1 = A->length, len2 = B->length; if (len1 < len2) { fmpz_poly_set(R, A); return; } if (R == B) { fmpz_poly_init2(tR, len1); r = tR->coeffs; } else { fmpz_poly_fit_length(R, len1); r = R->coeffs; } if (R == B || R != A) _fmpz_vec_set(r, A->coeffs, len1); _fmpz_poly_rem_powers_precomp(r, len1, B->coeffs, len2, B_inv->powers); if (R == B) { _fmpz_poly_set_length(tR, len2 - 1); fmpz_poly_swap(tR, R); fmpz_poly_clear(tR); } else _fmpz_poly_set_length(R, len2 - 1); _fmpz_poly_normalise(R); } flint-3.1.3/src/fmpz_poly/remove.c000066400000000000000000000043331461254215100171050ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" slong fmpz_poly_remove(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { fmpz_poly_t p, q; fmpz_t p1sum, p2sum, qsum; slong i; if (poly2->length == 0) { flint_throw(FLINT_ERROR, "(fmpz_poly_remove): Division by zero.\n"); } if (poly2->length == 1 && fmpz_is_pm1(poly2->coeffs + 0)) { flint_throw(FLINT_ERROR, "(fmpz_poly_remove): Divisor must not be a unit.\n"); } if (poly2->length > poly1->length) { fmpz_poly_set(res, poly1); return 0; } fmpz_init(p1sum); fmpz_init(p2sum); fmpz_init(qsum); for (i = 0; i < poly1->length; i++) fmpz_add(p1sum, p1sum, poly1->coeffs + i); for (i = 0; i < poly2->length; i++) fmpz_add(p2sum, p2sum, poly2->coeffs + i); fmpz_abs(p1sum, p1sum); fmpz_abs(p2sum, p2sum); if (fmpz_is_zero(p2sum)) { if (!fmpz_is_zero(p1sum)) { fmpz_poly_set(res, poly1); i = 0; goto cleanup; } else i = (poly1->length - 1)/(poly2->length - 1); } else if (fmpz_is_zero(p1sum) || fmpz_is_one(p2sum)) i = (poly1->length - 1)/(poly2->length - 1); else i = fmpz_remove(qsum, p1sum, p2sum); if (i > 0) { fmpz_poly_init(q); fmpz_poly_init(p); fmpz_poly_pow(p, poly2, i); while (i > 0 && !fmpz_poly_divides(q, poly1, p)) { fmpz_poly_divexact(p, p, poly2); i--; } if (i == 0) fmpz_poly_set(res, poly1); else fmpz_poly_set(res, q); fmpz_poly_clear(p); fmpz_poly_clear(q); } else fmpz_poly_set(res, poly1); cleanup: fmpz_clear(qsum); fmpz_clear(p1sum); fmpz_clear(p2sum); return i; } flint-3.1.3/src/fmpz_poly/remove_content_2exp.c000066400000000000000000000017741461254215100216030ustar00rootroot00000000000000/* Copyright (C) 2016 Elias Tsigaridas Copyright (C) 2017 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" slong _fmpz_poly_remove_content_2exp(fmpz * pol, slong len) { slong cont, i, z; i = 0; while (i < len && fmpz_is_zero(pol + i)) i++; if (i == len) return 0; cont = fmpz_val2(pol + i); for ( ; (i < len) && cont; i++) { if (!fmpz_is_zero(pol + i)) { z = fmpz_val2(pol + i); if (z < cont) cont = z; } } if (cont == 0) return 0; for (i = 0; i < len; i++) fmpz_fdiv_q_2exp(pol + i, pol + i, cont); return cont; } flint-3.1.3/src/fmpz_poly/resultant.c000066400000000000000000000027271461254215100176360ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong bits1 = FLINT_ABS(_fmpz_vec_max_bits(poly1, len1)); slong bits2 = FLINT_ABS(_fmpz_vec_max_bits(poly2, len2)); if (len2 > 144 || len2*len2*len2*(bits1 + bits2) > WORD(6000000)) _fmpz_poly_resultant_modular(res, poly1, len1, poly2, len2); else _fmpz_poly_resultant_euclidean(res, poly1, len1, poly2, len2); } void fmpz_poly_resultant(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong len1 = poly1->length; slong len2 = poly2->length; if (len1 == 0 || len2 == 0) fmpz_zero(res); else if (len1 >= len2) _fmpz_poly_resultant(res, poly1->coeffs, len1, poly2->coeffs, len2); else { _fmpz_poly_resultant(res, poly2->coeffs, len2, poly1->coeffs, len1); if ((len1 > 1) && (!(len1 & WORD(1)) & !(len2 & WORD(1)))) fmpz_neg(res, res); } } flint-3.1.3/src/fmpz_poly/resultant_euclidean.c000066400000000000000000000061511461254215100216420ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if (len2 == 1) { fmpz_pow_ui(res, poly2, len1 - 1); } else { fmpz_t a, b, g, h, t; fmpz *A, *B, *W; const slong alloc = len1 + len2; slong sgn = 1; fmpz_init(a); fmpz_init(b); fmpz_init(g); fmpz_init(h); fmpz_init(t); A = W = _fmpz_vec_init(alloc); B = W + len1; _fmpz_poly_content(a, poly1, len1); _fmpz_poly_content(b, poly2, len2); _fmpz_vec_scalar_divexact_fmpz(A, poly1, len1, a); _fmpz_vec_scalar_divexact_fmpz(B, poly2, len2, b); fmpz_one(g); fmpz_one(h); fmpz_pow_ui(a, a, len2 - 1); fmpz_pow_ui(b, b, len1 - 1); fmpz_mul(t, a, b); do { const slong d = len1 - len2; if (!(len1 & WORD(1)) & !(len2 & WORD(1))) sgn = -sgn; _fmpz_poly_pseudo_rem_cohen(A, A, len1, B, len2); FMPZ_VEC_NORM(A, len1); if (len1 == 0) { fmpz_zero(res); goto cleanup; } { fmpz * T; slong len; T = A, A = B, B = T; len = len1, len1 = len2, len2 = len; } fmpz_pow_ui(a, h, d); fmpz_mul(b, g, a); _fmpz_vec_scalar_divexact_fmpz(B, B, len2, b); fmpz_pow_ui(g, A + (len1 - 1), d); fmpz_mul(b, h, g); fmpz_divexact(h, b, a); fmpz_set(g, A + (len1 - 1)); } while (len2 > 1); fmpz_pow_ui(g, h, len1 - 1); fmpz_pow_ui(b, B + (len2 - 1), len1 - 1); fmpz_mul(a, h, b); fmpz_divexact(h, a, g); fmpz_mul(res, t, h); if (sgn < 0) fmpz_neg(res, res); cleanup: fmpz_clear(a); fmpz_clear(b); fmpz_clear(g); fmpz_clear(h); fmpz_clear(t); _fmpz_vec_clear(W, alloc); } } void fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { const slong len1 = poly1->length, len2 = poly2->length; if (len1 == 0 || len2 == 0) { fmpz_zero(res); return; } if (len1 >= len2) _fmpz_poly_resultant_euclidean(res, poly1->coeffs, len1, poly2->coeffs, len2); else { _fmpz_poly_resultant_euclidean(res, poly2->coeffs, len2, poly1->coeffs, len1); if ((len1 > 1) && (!(len1 & WORD(1)) & !(len2 & WORD(1)))) fmpz_neg(res, res); } } flint-3.1.3/src/fmpz_poly/resultant_modular.c000066400000000000000000000103721461254215100213540ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_resultant_modular(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { flint_bitcnt_t bound, pbits, curr_bits = 0; slong i, num_primes; fmpz_comb_t comb; fmpz_comb_temp_t comb_temp; fmpz_t ac, bc, l, modulus; fmpz * A, * B, * lead_A, * lead_B; mp_ptr a, b, rarr, parr; mp_limb_t p; nmod_t mod; /* special case, one of the polys is a constant */ if (len2 == 1) /* if len1 == 1 then so does len2 */ { fmpz_pow_ui(res, poly2, len1 - 1); return; } fmpz_init(ac); fmpz_init(bc); /* compute content of poly1 and poly2 */ _fmpz_vec_content(ac, poly1, len1); _fmpz_vec_content(bc, poly2, len2); /* divide poly1 and poly2 by their content */ A = _fmpz_vec_init(len1); B = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(A, poly1, len1, ac); _fmpz_vec_scalar_divexact_fmpz(B, poly2, len2, bc); /* get product of leading coefficients */ fmpz_init(l); lead_A = A + len1 - 1; lead_B = B + len2 - 1; fmpz_mul(l, lead_A, lead_B); /* set size of first prime */ pbits = FLINT_BITS - 1; p = (UWORD(1)<length; slong len2 = poly2->length; if (len1 == 0 || len2 == 0) fmpz_zero(res); else if (len1 >= len2) _fmpz_poly_resultant_modular(res, poly1->coeffs, len1, poly2->coeffs, len2); else { _fmpz_poly_resultant_modular(res, poly2->coeffs, len2, poly1->coeffs, len1); if ((len1 > 1) && (!(len1 & WORD(1)) & !(len2 & WORD(1)))) fmpz_neg(res, res); } } flint-3.1.3/src/fmpz_poly/resultant_modular_div.c000066400000000000000000000126001461254215100222120ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart Copyright (C) 2015 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_resultant_modular_div(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_t divisor, slong nbits) { flint_bitcnt_t pbits; slong i, num_primes; fmpz_comb_t comb; fmpz_comb_temp_t comb_temp; fmpz_t ac, bc, l, modulus, div, la, lb; fmpz * A, * B, * lead_A, * lead_B; mp_ptr a, b, rarr, parr; mp_limb_t p, d; nmod_t mod; if (fmpz_is_zero(divisor)) { fmpz_zero(res); return; } /* special case, one of the polys is a constant */ if (len2 == 1) /* if len1 == 1 then so does len2 */ { fmpz_pow_ui(res, poly2, len1 - 1); fmpz_divexact(res, res, divisor); return; } fmpz_init(ac); fmpz_init(bc); /* compute content of poly1 and poly2 */ _fmpz_vec_content(ac, poly1, len1); _fmpz_vec_content(bc, poly2, len2); /* divide poly1 and poly2 by their content */ A = _fmpz_vec_init(len1); B = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(A, poly1, len1, ac); _fmpz_vec_scalar_divexact_fmpz(B, poly2, len2, bc); fmpz_init(l); /* we have, originally // res(p1, p2) = r d // with nbits(r) <= nbits // Now // res(p1, p2) = ac^(len2-1) bc^(len1-1) res(A, B) // So we need to split ac^(len2-1) bc^(len1-1) = xy // such that d mod x == 0 and gcd(ac^... /x, y) = 1 // Then we need to compute res(A,B)/(d/x) // res(p1, p2) = x y res(A,B) = r d // and // r = x y res(A,B)/d = y res(A, B)/(d/x) // The length of res(A, B) shrinks by length(y) */ if (!fmpz_is_one(ac)) { fmpz_pow_ui(l, ac, len2 - 1); fmpz_init(div); fmpz_init(la); fmpz_gcd(div, l, divisor); /* div = gcd(ac^(len2-1), divisor) */ fmpz_divexact(la, l, div); /* la = ac^(len2 -1)/gcd */ fmpz_divexact(div, divisor, div); /*div /= gcd */ nbits = nbits - fmpz_bits(la) + 1; } else { fmpz_init_set(div, divisor); } if (!fmpz_is_one(bc)) { fmpz_init(lb); fmpz_pow_ui(lb, bc, len1 - 1); fmpz_gcd(l, lb, div); fmpz_divexact(lb, lb, l); fmpz_divexact(div, div, l); nbits = nbits - fmpz_bits(lb) + 1; } /* get product of leading coefficients */ lead_A = A + len1 - 1; lead_B = B + len2 - 1; fmpz_mul(l, lead_A, lead_B); fmpz_init(modulus); fmpz_set_ui(modulus, 1); fmpz_zero(res); /* make space for polynomials mod p */ a = _nmod_vec_init(len1); b = _nmod_vec_init(len2); pbits = FLINT_BITS - 1; p = (UWORD(1)<length; slong len2 = poly2->length; if (len1 == 0 || len2 == 0 || fmpz_is_zero(divisor)) fmpz_zero(res); else if (len1 >= len2) _fmpz_poly_resultant_modular_div(res, poly1->coeffs, len1, poly2->coeffs, len2, divisor, nbits); else { _fmpz_poly_resultant_modular_div(res, poly2->coeffs, len2, poly1->coeffs, len1, divisor, nbits); if ((len1 > 1) && (!(len1 & WORD(1)) & !(len2 & WORD(1)))) fmpz_neg(res, res); } } flint-3.1.3/src/fmpz_poly/reverse.c000066400000000000000000000025051461254215100172620ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n) { if (res == poly) { slong i; for (i = 0; i < n / 2; i++) { fmpz t = res[i]; res[i] = res[n - 1 - i]; res[n - 1 - i] = t; } for (i = 0; i < n - len; i++) fmpz_zero(res + i); } else { slong i; for (i = 0; i < n - len; i++) fmpz_zero(res + i); for (i = 0; i < len; i++) fmpz_set(res + (n - len) + i, poly + (len - 1) - i); } } void fmpz_poly_reverse(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { slong len = FLINT_MIN(n, poly->length); if (len == 0) { fmpz_poly_zero(res); return; } fmpz_poly_fit_length(res, n); _fmpz_poly_reverse(res->coeffs, poly->coeffs, len, n); _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/revert_series.c000066400000000000000000000026571461254215100205000ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { gr_ctx_t ctx; gr_ctx_init_fmpz(ctx); GR_MUST_SUCCEED(_gr_poly_revert_series(Qinv, Q, Qlen, n, ctx)); } void fmpz_poly_revert_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) { slong Qlen = Q->length; if (Qlen < 2 || !fmpz_is_zero(Q->coeffs) || !fmpz_is_pm1(Q->coeffs + 1)) { flint_throw(FLINT_ERROR, "(fmpz_poly_revert_series): " "Input must have zero constant term and +1 or -1 as coefficient of x^1\n."); } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_revert_series(Qinv->coeffs, Q->coeffs, Qlen, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_revert_series(t->coeffs, Q->coeffs, Qlen, n); fmpz_poly_swap(Qinv, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(Qinv, n); _fmpz_poly_normalise(Qinv); } flint-3.1.3/src/fmpz_poly/scalar.c000066400000000000000000000264641461254215100170660ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2016 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_scalar_abs(fmpz_poly_t res, const fmpz_poly_t poly) { fmpz_poly_fit_length(res, poly->length); _fmpz_vec_scalar_abs(res->coeffs, poly->coeffs, poly->length); _fmpz_poly_set_length(res, poly->length); } void fmpz_poly_scalar_addmul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { if (!fmpz_is_zero(x) && !fmpz_poly_is_zero(poly2)) { fmpz_poly_fit_length(poly1, poly2->length); if (poly2->length > poly1->length) _fmpz_vec_zero(poly1->coeffs + poly1->length, poly2->length - poly1->length); _fmpz_vec_scalar_addmul_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, FLINT_MAX(poly1->length, poly2->length)); _fmpz_poly_normalise(poly1); } } void fmpz_poly_scalar_addmul_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { if (x != 0 && !fmpz_poly_is_zero(poly2)) { fmpz_poly_fit_length(poly1, poly2->length); if (poly2->length > poly1->length) _fmpz_vec_zero(poly1->coeffs + poly1->length, poly2->length - poly1->length); _fmpz_vec_scalar_addmul_si(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, FLINT_MAX(poly1->length, poly2->length)); _fmpz_poly_normalise(poly1); } } void fmpz_poly_scalar_addmul_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { if (x != 0 && !fmpz_poly_is_zero(poly2)) { fmpz_poly_fit_length(poly1, poly2->length); if (poly2->length > poly1->length) _fmpz_vec_zero(poly1->coeffs + poly1->length, poly2->length - poly1->length); _fmpz_vec_scalar_addmul_ui(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, FLINT_MAX(poly1->length, poly2->length)); _fmpz_poly_normalise(poly1); } } void fmpz_poly_scalar_divexact_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { if (fmpz_is_zero(x)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_divexact_fmpz). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_divexact_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_divexact_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { if (x == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_divexact_si). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_divexact_si(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_divexact_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { if (x == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_divexact_ui). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_divexact_ui(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_fdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp) { if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_fdiv_q_2exp(poly1->coeffs, poly2->coeffs, poly2->length, exp); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_fdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { if (fmpz_is_zero(x)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_fdiv_fmpz). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_fdiv_q_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_fdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { if (x == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_fdiv_si). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_fdiv_q_si(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_fdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { if (x == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_fdiv_ui). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_fdiv_q_ui(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_mod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { if (poly2->length == 0) { fmpz_poly_zero(poly1); } else { fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_mod_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); _fmpz_poly_normalise(poly1); } } void fmpz_poly_scalar_smod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { if (poly2->length == 0) { fmpz_poly_zero(poly1); } else { fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_smod_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); _fmpz_poly_normalise(poly1); } } void fmpz_poly_scalar_mul_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp) { if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_mul_2exp(poly1->coeffs, poly2->coeffs, poly2->length, exp); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_mul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { /* Either scalar or input poly is zero */ if ((*x == 0) || (poly2->length == 0)) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_mul_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_mul_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { slong i; /* Either scalar or input poly is zero */ if ((x == WORD(0)) || (poly2->length == 0)) { fmpz_poly_zero(poly1); return; } /* Special case, multiply by 1 */ if (x == WORD(1)) { fmpz_poly_set(poly1, poly2); return; } /* Special case, multiply by -1 */ if (x == WORD(-1)) { fmpz_poly_neg(poly1, poly2); return; } fmpz_poly_fit_length(poly1, poly2->length); for (i = 0; i < poly2->length; i++) fmpz_mul_si(poly1->coeffs + i, poly2->coeffs + i, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_mul_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { slong i; /* Either scalar or input poly is zero */ if ((x == 0) || (poly2->length == 0)) { fmpz_poly_zero(poly1); return; } /* Special case, multiply by 1 */ if (x == 1) { fmpz_poly_set(poly1, poly2); return; } fmpz_poly_fit_length(poly1, poly2->length); for (i = 0; i < poly2->length; i++) fmpz_mul_ui(poly1->coeffs + i, poly2->coeffs + i, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_submul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { if (!fmpz_is_zero(x) && !fmpz_poly_is_zero(poly2)) { fmpz_poly_fit_length(poly1, poly2->length); if (poly2->length > poly1->length) _fmpz_vec_zero(poly1->coeffs + poly1->length, poly2->length - poly1->length); _fmpz_vec_scalar_submul_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, FLINT_MAX(poly1->length, poly2->length)); _fmpz_poly_normalise(poly1); } } void fmpz_poly_scalar_tdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp) { if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_tdiv_q_2exp(poly1->coeffs, poly2->coeffs, poly2->length, exp); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_tdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { if (fmpz_is_zero(x)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_tdiv_fmpz). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_tdiv_q_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_tdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { if (x == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_tdiv_si). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_tdiv_q_si(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } void fmpz_poly_scalar_tdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { if (x == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_scalar_tdiv_ui). Division by zero.\n"); } if (poly2->length == 0) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_tdiv_q_ui(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); } flint-3.1.3/src/fmpz_poly/scale_2exp.c000066400000000000000000000027461461254215100176430ustar00rootroot00000000000000/* Copyright (C) 2015, Elias Tsigaridas Copyright (C) 2016, Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_scale_2exp(fmpz * pol, slong len, slong k) { slong i; ulong p, z; if (k == 0 || len <= 1) return; else if (k > 0) { if (fmpz_is_zero(pol)) z = ULONG_MAX; else z = fmpz_val2(pol); p = k; for (i = 1; i < len; i++, p += k) { if (!fmpz_is_zero(pol + i)) { z = FLINT_MIN(z, fmpz_val2(pol + i) + p); fmpz_mul_2exp(pol + i, pol + i, p); } } } else { if (fmpz_is_zero(pol + len - 1)) z = ULONG_MAX; else z = fmpz_val2(pol + len - 1); p = -k; for (i = len - 2; i >= 0; i--, p -= k) { if (!fmpz_is_zero(pol + i)) { z = FLINT_MIN(z, fmpz_val2(pol + i) + p); fmpz_mul_2exp(pol + i, pol + i, p); } } } if (z) { for (i = 0; i < len; i++) fmpz_fdiv_q_2exp(pol + i, pol + i, z); } } flint-3.1.3/src/fmpz_poly/set.c000066400000000000000000000045171461254215100164070ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_set(fmpz_poly_t poly1, const fmpz_poly_t poly2) { if (poly1 != poly2) /* Aliasing is trivial */ { slong i, len = poly2->length; fmpz_poly_fit_length(poly1, len); for (i = 0; i < len; i++) fmpz_set(poly1->coeffs + i, poly2->coeffs + i); _fmpz_poly_set_length(poly1, len); } } void fmpz_poly_set_nmod_poly(fmpz_poly_t res, const nmod_poly_t poly) { slong len = poly->length; if (len == 0) { fmpz_poly_zero(res); } else { slong i; fmpz_poly_fit_length(res, len); for (i = 0; i < len; i++) fmpz_set_ui_smod(res->coeffs + i, poly->coeffs[i], poly->mod.n); _fmpz_poly_set_length(res, len); } } void fmpz_poly_set_nmod_poly_unsigned(fmpz_poly_t res, const nmod_poly_t poly) { slong len = poly->length; if (len == 0) { fmpz_poly_zero(res); } else { slong i; fmpz_poly_fit_length(res, len); for (i = 0; i < len; i++) fmpz_set_ui(res->coeffs + i, poly->coeffs[i]); _fmpz_poly_set_length(res, len); } } void fmpz_poly_set_fmpz(fmpz_poly_t poly, const fmpz_t c) { if (fmpz_is_zero(c)) fmpz_poly_zero(poly); else { fmpz_poly_fit_length(poly, 1); fmpz_set(poly->coeffs, c); _fmpz_poly_set_length(poly, 1); } } void fmpz_poly_set_si(fmpz_poly_t poly, slong c) { if (c == 0) fmpz_poly_zero(poly); else { fmpz_poly_fit_length(poly, 1); fmpz_set_si(poly->coeffs, c); _fmpz_poly_set_length(poly, 1); } } void fmpz_poly_set_ui(fmpz_poly_t poly, ulong c) { if (c == UWORD(0)) fmpz_poly_zero(poly); else { fmpz_poly_fit_length(poly, 1); fmpz_set_ui(poly->coeffs, c); _fmpz_poly_set_length(poly, 1); } } flint-3.1.3/src/fmpz_poly/set_coeff.c000066400000000000000000000043601461254215100175450ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_set_coeff_fmpz(fmpz_poly_t poly, slong n, const fmpz_t x) { if (fmpz_is_zero(x)) { if (n >= poly->length) return; fmpz_zero(poly->coeffs + n); if (n == poly->length - 1) /* only necessary when setting leading coefficient */ _fmpz_poly_normalise(poly); } else { fmpz_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { slong i; for (i = poly->length; i < n; i++) fmpz_zero(poly->coeffs + i); poly->length = n + 1; } fmpz_set(poly->coeffs + n, x); } } void fmpz_poly_set_coeff_si(fmpz_poly_t poly, slong n, slong x) { if (x == 0) { if (n >= poly->length) return; fmpz_zero(poly->coeffs + n); if (n == poly->length - 1) /* only necessary when setting leading coefficient */ _fmpz_poly_normalise(poly); } else { fmpz_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { slong i; for (i = poly->length; i < n; i++) fmpz_zero(poly->coeffs + i); poly->length = n + 1; } fmpz_set_si(poly->coeffs + n, x); } } void fmpz_poly_set_coeff_ui(fmpz_poly_t poly, slong n, ulong x) { if (x == 0) { if (n >= poly->length) return; fmpz_zero(poly->coeffs + n); if (n == poly->length - 1) /* only necessary when setting leading coefficient */ _fmpz_poly_normalise(poly); } else { fmpz_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { slong i; for (i = poly->length; i < n; i++) fmpz_zero(poly->coeffs + i); poly->length = n + 1; } fmpz_set_ui(poly->coeffs + n, x); } } flint-3.1.3/src/fmpz_poly/set_length.c000066400000000000000000000012271461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_set_length(fmpz_poly_t poly, slong newlen) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); } poly->length = newlen; } flint-3.1.3/src/fmpz_poly/set_str.c000066400000000000000000000041041461254215100172670ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_set_str(fmpz * poly, const char *str) { char * w; slong i, len; if (!isdigit((unsigned char) str[0])) return -1; len = atol(str); if (len < 0) return -1; if (len == 0) return 0; while (*str++ != ' ') ; /* Find maximal gap between spaces and allocate w */ { const char * s = str; slong max; for (max = 0; *s != '\0';) { slong cur; for (s++, cur = 1; *s != ' ' && *s != '\0'; s++, cur++) ; if (max < cur) max = cur; } w = flint_malloc(max + 1); } for (i = 0; i < len; i++) { char * v; int ans; for (str++, v = w; *str != ' ' && *str != '\0';) *v++ = *str++; *v = '\0'; ans = fmpz_set_str(poly++, w, 10); if (ans) { flint_free(w); return -1; } } flint_free(w); return 0; } int fmpz_poly_set_str(fmpz_poly_t poly, const char * str) { int ans; slong len; if (!isdigit((unsigned char) str[0])) return -1; len = atol(str); if (len < 0) return -1; if (len == 0) { fmpz_poly_zero(poly); return 0; } fmpz_poly_fit_length(poly, len); ans = _fmpz_poly_set_str(poly->coeffs, str); if (ans == 0) { _fmpz_poly_set_length(poly, len); _fmpz_poly_normalise(poly); } else { _fmpz_vec_zero(poly->coeffs, len); _fmpz_poly_set_length(poly, 0); } return ans; } flint-3.1.3/src/fmpz_poly/set_trunc.c000066400000000000000000000016121461254215100176130ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_set_trunc(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { if (poly == res) { fmpz_poly_truncate(res, n); } else { slong rlen; rlen = FLINT_MIN(n, poly->length); while (rlen > 0 && fmpz_is_zero(poly->coeffs + rlen - 1)) rlen--; fmpz_poly_fit_length(res, rlen); _fmpz_vec_set(res->coeffs, poly->coeffs, rlen); _fmpz_poly_set_length(res, rlen); } } flint-3.1.3/src/fmpz_poly/shift_left.c000066400000000000000000000024351461254215100177400ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n) { slong i; /* Copy in reverse to avoid writing over unshifted coefficients */ if (res != poly) { for (i = len; i--; ) fmpz_set(res + n + i, poly + i); } else { for (i = len; i--; ) fmpz_swap(res + n + i, res + i); } for (i = 0; i < n; i++) fmpz_zero(res + i); } void fmpz_poly_shift_left(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { if (n == 0) { fmpz_poly_set(res, poly); return; } if (poly->length == 0) { fmpz_poly_zero(res); return; } fmpz_poly_fit_length(res, poly->length + n); _fmpz_poly_shift_left(res->coeffs, poly->coeffs, poly->length, n); _fmpz_poly_set_length(res, poly->length + n); } flint-3.1.3/src/fmpz_poly/shift_right.c000066400000000000000000000024001461254215100201130ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n) { slong i; /* Copy in forward order to avoid writing over unshifted coefficients */ if (res != poly) { for (i = 0; i < len - n; i++) fmpz_set(res + i, poly + n + i); } else { for (i = 0; i < len - n; i++) fmpz_swap(res + i, res + n + i); } } void fmpz_poly_shift_right(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { if (n == 0) { fmpz_poly_set(res, poly); return; } if (poly->length <= n) { fmpz_poly_zero(res); return; } fmpz_poly_fit_length(res, poly->length - n); _fmpz_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n); _fmpz_poly_set_length(res, poly->length - n); } flint-3.1.3/src/fmpz_poly/signature.c000066400000000000000000000055071461254215100176150ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_signature(slong * r1, slong * r2, const fmpz * poly, slong len) { fmpz *A, *B, *f, *g, *h, *w; slong lenA, lenB; int s, t; if (len <= 2) { *r1 = (len == 2); *r2 = 0; return; } w = _fmpz_vec_init(2 * len + 2); A = w; B = w + len; lenA = len; lenB = lenA - 1; f = w + 2 * len - 1; g = w + 2 * len; h = w + 2 * len + 1; _fmpz_poly_primitive_part(A, poly, lenA); _fmpz_poly_derivative(B, A, lenA); _fmpz_poly_primitive_part(B, B, lenB); fmpz_one(g); fmpz_one(h); s = 1; t = (lenA & WORD(1)) ? -s : s; *r1 = 1; while (1) { slong delta = lenA - lenB; int sgnA; _fmpz_poly_pseudo_rem_cohen(A, A, lenA, B, lenB); lenA = lenB; FMPZ_VEC_NORM(A, lenA); if (lenA == 0) { _fmpz_vec_clear(w, 2 * len + 2); flint_throw(FLINT_ERROR, "(fmpz_poly_signature): Non-squarefree polynomial detected.\n"); } if ((fmpz_sgn(B + (lenB - 1)) > 0) || (delta & WORD(1))) _fmpz_vec_neg(A, A, lenA); sgnA = fmpz_sgn(A + (lenA - 1)); if (sgnA != s) { s = -s; (*r1)--; } if (sgnA != ((lenA & WORD(1)) ? t : -t)) { t = -t; (*r1)++; } if (lenA == 1) { *r2 = ((len - 1) - *r1) / 2; _fmpz_vec_clear(w, 2 * len + 2); return; } else { { fmpz * temp = A; A = B; B = temp; } { slong temp = lenA; lenA = lenB; lenB = temp; } if (delta == 1) { fmpz_mul(f, g, h); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, f); fmpz_abs(g, A + (lenA - 1)); fmpz_set(h, g); } else { fmpz_pow_ui(f, h, delta); fmpz_mul(f, f, g); _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, f); fmpz_pow_ui(f, h, delta - 1); fmpz_pow_ui(g, A + (lenA - 1), delta); fmpz_abs(g, g); fmpz_divexact(h, g, f); fmpz_abs(g, A + (lenA - 1)); } } } } void fmpz_poly_signature(slong * r1, slong * r2, const fmpz_poly_t poly) { _fmpz_poly_signature(r1, r2, poly->coeffs, poly->length); } flint-3.1.3/src/fmpz_poly/sqr.c000066400000000000000000000113441461254215100164150ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #ifdef FLINT_HAVE_FFT_SMALL #include "fft_small.h" #endif void _fmpz_poly_sqr_tiny1(fmpz * res, const fmpz * poly, slong len) { slong i, j, c; _fmpz_vec_zero(res, 2 * len - 1); for (i = 0; i < len; i++) { c = poly[i]; if (c != 0) { res[2 * i] += c * c; c *= 2; for (j = i + 1; j < len; j++) res[i + j] += poly[j] * c; } } } void _fmpz_poly_sqr_tiny2(fmpz * res, const fmpz * poly, slong len) { slong i, j, k, c, d; mp_limb_t hi, lo; mp_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(2 * (2 * len - 1) * sizeof(mp_limb_t)); flint_mpn_zero(tmp, 2 * (2 * len - 1)); for (i = 0; i < len; i++) { c = poly[i]; if (c != 0) { smul_ppmm(hi, lo, c, c); add_ssaaaa(tmp[4 * i + 1], tmp[4 * i], tmp[4 * i + 1], tmp[4 * i], hi, lo); c *= 2; /* does not overflow */ for (j = i + 1; j < len; j++) { k = i + j; d = poly[j]; if (d != 0) { smul_ppmm(hi, lo, c, d); add_ssaaaa(tmp[2 * k + 1], tmp[2 * k], tmp[2 * k + 1], tmp[2 * k], hi, lo); } } } } for (i = 0; i < 2 * len - 1; i++) { lo = tmp[2 * i]; hi = tmp[2 * i + 1]; if (((mp_limb_signed_t) hi) >= 0) { fmpz_set_uiui(res + i, hi, lo); } else { sub_ddmmss(hi, lo, 0, 0, hi, lo); fmpz_neg_uiui(res + i, hi, lo); } } TMP_END; return; } void _fmpz_poly_sqr(fmpz * res, const fmpz * poly, slong len) { slong bits, rbits; if (len == 1) { fmpz_mul(res, poly, poly); return; } bits = _fmpz_vec_max_bits(poly, len); bits = FLINT_ABS(bits); #ifdef FLINT_HAVE_FFT_SMALL if (len >= 80 && (bits + bits <= 40 || bits + bits >= 128 || len >= 160)) if (_fmpz_poly_mul_mid_default_mpn_ctx(res, 0, len + len - 1, poly, len, poly, len)) return; #endif if (bits <= SMALL_FMPZ_BITCOUNT_MAX && len < 50 + 3 * bits) { rbits = 2 * bits + FLINT_BIT_COUNT(len); if (rbits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_poly_sqr_tiny1(res, poly, len); return; } else if (rbits <= 2 * FLINT_BITS - 1) { _fmpz_poly_sqr_tiny2(res, poly, len); return; } } #ifdef FLINT_HAVE_FFT_SMALL /* same as in mul.c */ if (len <= 6 && bits <= 5000) _fmpz_poly_sqr_classical(res, poly, len); else if (len <= 4 || (len <= 8 && 2 * bits >= 1500 && 2 * bits <= 10000)) _fmpz_poly_sqr_karatsuba(res, poly, len); else if ((len >= 8 && len <= 75 && 2 * bits >= 800 && 2 * bits <= 4000) || (len >= 5000 && 2 * bits >= 5000 + (2 * len) / 10 && flint_get_num_threads() >= 4)) _fmpz_poly_mul_SS(res, poly, len, poly, len); else _fmpz_poly_mul_KS(res, poly, len, poly, len); #else if (len < 7) { _fmpz_poly_sqr_classical(res, poly, len); } else { mp_size_t limbs; limbs = (bits + FLINT_BITS - 1) / FLINT_BITS; if (len < 16 && limbs > 12) _fmpz_poly_sqr_karatsuba(res, poly, len); else if (limbs <= 4) _fmpz_poly_sqr_KS(res, poly, len); else if (limbs/2048 > len) _fmpz_poly_sqr_KS(res, poly, len); else if (limbs*FLINT_BITS*4 < len) _fmpz_poly_sqr_KS(res, poly, len); else _fmpz_poly_mul_SS(res, poly, len, poly, len); } #endif } void fmpz_poly_sqr(fmpz_poly_t res, const fmpz_poly_t poly) { slong len = poly->length; slong rlen; if (len == 0) { fmpz_poly_zero(res); return; } rlen = 2 * len - 1; if (res == poly) { fmpz_poly_t t; fmpz_poly_init2(t, rlen); _fmpz_poly_sqr(t->coeffs, poly->coeffs, len); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(res, rlen); _fmpz_poly_sqr(res->coeffs, poly->coeffs, len); } _fmpz_poly_set_length(res, rlen); } flint-3.1.3/src/fmpz_poly/sqr_KS.c000066400000000000000000000042131461254215100170070ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_sqr_KS(fmpz *rop, const fmpz *op, slong len) { const slong in_len = len; int neg; slong bits, limbs, loglen; mp_limb_t *arr, *arr3; slong sign = 0; FMPZ_VEC_NORM(op, len); if (!len) { if (2 * in_len - 1 > 0) _fmpz_vec_zero(rop, 2 * in_len - 1); return; } neg = (fmpz_sgn(op + len - 1) > 0) ? 0 : -1; bits = _fmpz_vec_max_bits(op, len); if (bits < 0) { sign = 1; bits = - bits; } loglen = FLINT_BIT_COUNT(len); bits = 2 * bits + loglen + sign; limbs = (bits * len - 1) / FLINT_BITS + 1; arr = (mp_limb_t *) flint_calloc(limbs, sizeof(mp_limb_t)); _fmpz_poly_bit_pack(arr, op, len, bits, neg); arr3 = (mp_limb_t *) flint_malloc((2 * limbs) * sizeof(mp_limb_t)); flint_mpn_sqr(arr3, arr, limbs); if (sign) _fmpz_poly_bit_unpack(rop, 2 * len - 1, arr3, bits, 0); else _fmpz_poly_bit_unpack_unsigned(rop, 2 * len - 1, arr3, bits); if (len < in_len) _fmpz_vec_zero(rop + (2 * len - 1), 2 * (in_len - len)); flint_free(arr); flint_free(arr3); } void fmpz_poly_sqr_KS(fmpz_poly_t rop, const fmpz_poly_t op) { slong len; if (op->length == 0) { fmpz_poly_zero(rop); return; } len = 2 * op->length - 1; if (rop == op) { fmpz_poly_t t; fmpz_poly_init2(t, len); fmpz_poly_sqr_KS(t, op); fmpz_poly_swap(rop, t); fmpz_poly_clear(t); return; } fmpz_poly_fit_length(rop, len); _fmpz_poly_sqr_KS(rop->coeffs, op->coeffs, op->length); _fmpz_poly_set_length(rop, len); } flint-3.1.3/src/fmpz_poly/sqr_classical.c000066400000000000000000000037551461254215100204420ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumes len > 0. */ void _fmpz_poly_sqr_classical(fmpz *res, const fmpz *op, slong len) { slong i, start, stop; if (len == 1) { fmpz_mul(res, op, op); return; } fmpz_mul(res, op, op); fmpz_mul(res + 1, op, op + 1); fmpz_mul_2exp(res + 1, res + 1, 1); for (i = 2; i < 2 * len - 3; i++) { start = FLINT_MAX(0, i - len + 1); stop = FLINT_MIN(len - 1, (i + 1) / 2 - 1); _fmpz_vec_dot_general(res + i, NULL, 0, op + start, op + i - stop, 1, stop - start + 1); fmpz_mul_2exp(res + i, res + i, 1); if (i % 2 == 0 && i / 2 < len) fmpz_addmul(res + i, op + i / 2, op + i / 2); } if (len > 2) { fmpz_mul(res + 2 * len - 3, op + len - 1, op + len - 2); fmpz_mul_2exp(res + 2 * len - 3, res + 2 * len - 3, 1); } fmpz_mul(res + 2 * len - 2, op + len - 1, op + len - 1); } void fmpz_poly_sqr_classical(fmpz_poly_t rop, const fmpz_poly_t op) { slong len; if (op->length == 0) { fmpz_poly_zero(rop); return; } len = 2 * op->length - 1; if (rop == op) { fmpz_poly_t t; fmpz_poly_init2(t, len); _fmpz_poly_sqr_classical(t->coeffs, op->coeffs, op->length); fmpz_poly_swap(rop, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(rop, len); _fmpz_poly_sqr_classical(rop->coeffs, op->coeffs, op->length); } _fmpz_poly_set_length(rop, len); } flint-3.1.3/src/fmpz_poly/sqr_karatsuba.c000066400000000000000000000046651461254215100204620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* For documentation, see fmpz_poly/mul_karatsuba.c */ extern void revbin1(fmpz * out, const fmpz * in, slong len, slong bits); extern void revbin2(fmpz * out, const fmpz * in, slong len, slong bits); extern void _fmpz_vec_add_rev(fmpz * in1, fmpz * in2, slong bits); void _fmpz_poly_sqr_kara_recursive(fmpz * out, fmpz * rev, fmpz * temp, slong bits) { slong len = (WORD(1) << bits); slong m = len / 2; if (len == 1) { fmpz_mul(out, rev, rev); fmpz_zero(out + 1); return; } _fmpz_vec_add(temp, rev, rev + m, m); _fmpz_poly_sqr_kara_recursive(out, rev, temp + 2 * m, bits - 1); _fmpz_poly_sqr_kara_recursive(out + len, temp, temp + 2 * m, bits - 1); _fmpz_poly_sqr_kara_recursive(temp, rev + m, temp + 2 * m, bits - 1); _fmpz_vec_sub(out + len, out + len, out, len); _fmpz_vec_sub(out + len, out + len, temp, len); _fmpz_vec_add_rev(out, temp, bits); } void _fmpz_poly_sqr_karatsuba(fmpz * res, const fmpz * poly, slong len) { fmpz *rev, *out, *temp; slong length, loglen = 0; if (len == 1) { fmpz_mul(res, poly, poly); return; } while ((WORD(1) << loglen) < len) loglen++; length = (WORD(1) << loglen); rev = flint_calloc(3 * length, sizeof(fmpz)); out = rev + length; temp = _fmpz_vec_init(2 * length); revbin1(rev, poly, len, loglen); _fmpz_poly_sqr_kara_recursive(out, rev, temp, loglen); _fmpz_vec_zero(res, 2 * len - 1); revbin2(res, out, 2 * len - 1, loglen + 1); _fmpz_vec_clear(temp, 2 * length); flint_free(rev); } void fmpz_poly_sqr_karatsuba(fmpz_poly_t res, const fmpz_poly_t poly) { slong len; if (poly->length == 0) { fmpz_poly_zero(res); return; } len = 2 * poly->length - 1; fmpz_poly_fit_length(res, len); _fmpz_poly_sqr_karatsuba(res->coeffs, poly->coeffs, poly->length); _fmpz_poly_set_length(res, len); } flint-3.1.3/src/fmpz_poly/sqrlow.c000066400000000000000000000120521461254215100171340ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #ifdef FLINT_HAVE_FFT_SMALL #include "fft_small.h" #endif void _fmpz_poly_sqrlow_tiny1(fmpz * res, const fmpz * poly, slong len, slong n) { slong i, j, c; _fmpz_vec_zero(res, n); for (i = 0; i < len; i++) { c = poly[i]; if (c != 0) { if (2 * i < n) res[2 * i] += c * c; c *= 2; for (j = i + 1; j < FLINT_MIN(len, n - i); j++) res[i + j] += poly[j] * c; } } } void _fmpz_poly_sqrlow_tiny2(fmpz * res, const fmpz * poly, slong len, slong n) { slong i, j, k, c, d; mp_limb_t hi, lo; mp_ptr tmp; TMP_INIT; TMP_START; tmp = TMP_ALLOC(2 * n * sizeof(mp_limb_t)); flint_mpn_zero(tmp, 2 * n); for (i = 0; i < len; i++) { c = poly[i]; if (c != 0) { if (2 * i < n) { smul_ppmm(hi, lo, c, c); add_ssaaaa(tmp[4 * i + 1], tmp[4 * i], tmp[4 * i + 1], tmp[4 * i], hi, lo); } c *= 2; /* does not overflow */ for (j = i + 1; j < FLINT_MIN(len, n - i); j++) { k = i + j; d = poly[j]; if (d != 0) { smul_ppmm(hi, lo, c, d); add_ssaaaa(tmp[2 * k + 1], tmp[2 * k], tmp[2 * k + 1], tmp[2 * k], hi, lo); } } } } for (i = 0; i < n; i++) { lo = tmp[2 * i]; hi = tmp[2 * i + 1]; if (((mp_limb_signed_t) hi) >= 0) { fmpz_set_uiui(res + i, hi, lo); } else { sub_ddmmss(hi, lo, 0, 0, hi, lo); fmpz_neg_uiui(res + i, hi, lo); } } TMP_END; return; } void _fmpz_poly_sqrlow(fmpz * res, const fmpz * poly, slong len, slong n) { slong bits, rbits; len = FLINT_MIN(len, n); if (len == 1) { fmpz_mul(res, poly, poly); return; } bits = _fmpz_vec_max_bits(poly, len); bits = FLINT_ABS(bits); #ifdef FLINT_HAVE_FFT_SMALL if (len >= 100 && (bits + bits <= 40 || bits + bits >= 128 || len >= 240)) if (_fmpz_poly_mul_mid_default_mpn_ctx(res, 0, n, poly, len, poly, len)) return; #endif if (bits <= SMALL_FMPZ_BITCOUNT_MAX && (len < 50 + 2 * bits || (4 * len >= 3 * n && n < 140 + 6 * bits))) { rbits = 2 * bits + FLINT_BIT_COUNT(len); if (rbits <= SMALL_FMPZ_BITCOUNT_MAX) { _fmpz_poly_sqrlow_tiny1(res, poly, len, n); return; } else if (rbits <= 2 * FLINT_BITS - 1) { _fmpz_poly_sqrlow_tiny2(res, poly, len, n); return; } } #ifdef FLINT_HAVE_FFT_SMALL /* same as in mul.c */ if (len <= 6 && bits <= 5000) _fmpz_poly_sqrlow_classical(res, poly, len, n); else if (len <= 4 || (len <= 8 && 2 * bits >= 1500 && 2 * bits <= 10000)) _fmpz_poly_sqrlow_karatsuba(res, poly, len, n); else if ((len >= 8 && len <= 75 && 2 * bits >= 800 && 2 * bits <= 4000) || (len >= 5000 && 2 * bits >= 5000 + (2 * len) / 10 && flint_get_num_threads() >= 4)) _fmpz_poly_mullow_SS(res, poly, len, poly, len, n); else _fmpz_poly_sqrlow_KS(res, poly, len, n); #else if (n < 7) { _fmpz_poly_sqrlow_classical(res, poly, len, n); } else { mp_size_t limbs; limbs = (bits + FLINT_BITS - 1) / FLINT_BITS; if (n < 16 && limbs > 12) _fmpz_poly_sqrlow_karatsuba(res, poly, len, n); else if (limbs <= 4) _fmpz_poly_sqrlow_KS(res, poly, len, n); else if (limbs/2048 > len) _fmpz_poly_sqrlow_KS(res, poly, len, n); else if (limbs*FLINT_BITS*4 < len) _fmpz_poly_sqrlow_KS(res, poly, len, n); else _fmpz_poly_mullow_SS(res, poly, len, poly, len, n); } #endif } void fmpz_poly_sqrlow(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { const slong len = poly->length; if (len == 0 || n == 0) { fmpz_poly_zero(res); return; } if (res == poly) { fmpz_poly_t t; fmpz_poly_init2(t, n); fmpz_poly_sqrlow(t, poly, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); return; } n = FLINT_MIN(2 * len - 1, n); fmpz_poly_fit_length(res, n); _fmpz_poly_sqrlow(res->coeffs, poly->coeffs, len, n); _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/sqrlow_KS.c000066400000000000000000000043161461254215100175350ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_sqrlow_KS(fmpz * res, const fmpz * poly, slong len, slong n) { int neg; slong bits, limbs, loglen, sign = 0; mp_limb_t *arr_in, *arr_out; len = FLINT_MIN(len, n); FMPZ_VEC_NORM(poly, len); if (len == 0) { _fmpz_vec_zero(res, n); return; } neg = (fmpz_sgn(poly + len - 1) > 0) ? 0 : -1; if (n > 2 * len - 1) { _fmpz_vec_zero(res + 2 * len - 1, n - (2 * len - 1)); n = 2 * len - 1; } bits = _fmpz_vec_max_bits(poly, len); if (bits < 0) { sign = 1; bits = - bits; } loglen = FLINT_BIT_COUNT(len); bits = 2 * bits + loglen + sign; limbs = (bits * len - 1) / FLINT_BITS + 1; arr_in = flint_calloc(limbs, sizeof(mp_limb_t)); arr_out = flint_malloc((2 * limbs) * sizeof(mp_limb_t)); _fmpz_poly_bit_pack(arr_in, poly, len, bits, neg); flint_mpn_sqr(arr_out, arr_in, limbs); if (sign) _fmpz_poly_bit_unpack(res, n, arr_out, bits, 0); else _fmpz_poly_bit_unpack_unsigned(res, n, arr_out, bits); flint_free(arr_in); flint_free(arr_out); } void fmpz_poly_sqrlow_KS(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { const slong len = poly->length; if (len == 0 || n == 0) { fmpz_poly_zero(res); return; } if (res == poly) { fmpz_poly_t t; fmpz_poly_init2(t, n); fmpz_poly_sqrlow_KS(t, poly, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); return; } n = FLINT_MIN(n, 2 * len - 1); fmpz_poly_fit_length(res, n); _fmpz_poly_sqrlow_KS(res->coeffs, poly->coeffs, len, n); _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/sqrlow_classical.c000066400000000000000000000042131461254215100211520ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumes len > 0 and 0 < n <= 2 * len - 1. */ void _fmpz_poly_sqrlow_classical(fmpz *res, const fmpz *op, slong len, slong n) { slong i, start, stop; len = FLINT_MIN(len, n); if (n == 1) { fmpz_mul(res, op, op); return; } fmpz_mul(res, op, op); fmpz_mul(res + 1, op, op + 1); fmpz_mul_2exp(res + 1, res + 1, 1); for (i = 2; i < FLINT_MIN(n, 2 * len - 3); i++) { start = FLINT_MAX(0, i - len + 1); stop = FLINT_MIN(len - 1, (i + 1) / 2 - 1); _fmpz_vec_dot_general(res + i, NULL, 0, op + start, op + i - stop, 1, stop - start + 1); fmpz_mul_2exp(res + i, res + i, 1); if (i % 2 == 0 && i / 2 < len) fmpz_addmul(res + i, op + i / 2, op + i / 2); } if (len > 2 && n >= 2 * len - 2) { fmpz_mul(res + 2 * len - 3, op + len - 1, op + len - 2); fmpz_mul_2exp(res + 2 * len - 3, res + 2 * len - 3, 1); } if (n >= 2 * len - 1) fmpz_mul(res + 2 * len - 2, op + len - 1, op + len - 1); } void fmpz_poly_sqrlow_classical(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { slong len = poly->length; if (len == 0 || n == 0) { fmpz_poly_zero(res); return; } n = FLINT_MIN(2 * len - 1, n); if (res == poly) { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_sqrlow_classical(t->coeffs, poly->coeffs, len, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } else { fmpz_poly_fit_length(res, n); _fmpz_poly_sqrlow_classical(res->coeffs, poly->coeffs, len, n); } _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/sqrlow_karatsuba_n.c000066400000000000000000000062271461254215100215150ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* For documentation, see fmpz_poly/mullow_karatsuba_n.c */ void _fmpz_poly_sqrlow_kara_recursive(fmpz * out, const fmpz * pol, fmpz * temp, slong len) { slong m1 = len / 2; slong m2 = len - m1; int odd = (len & 1); if (len <= 6) { _fmpz_poly_sqrlow_classical(out, pol, len, len); return; } _fmpz_vec_add(temp + m2, pol, pol + m1, m1); if (odd) fmpz_set(temp + m2 + m1, pol + 2 * m1); _fmpz_poly_sqrlow_kara_recursive(temp, temp + m2, temp + 2 * m2, m2); _fmpz_poly_sqrlow_kara_recursive(temp + m2, pol + m1, temp + 2 * m2, m2); _fmpz_poly_sqr_karatsuba(out, pol, m1); fmpz_zero(out + 2 * m1 - 1); _fmpz_vec_sub(temp, temp, out, m2); _fmpz_vec_sub(temp, temp, temp + m2, m2); if (odd) fmpz_set(out + 2 * m1, temp + m2); _fmpz_vec_add(out + m1, out + m1, temp, m2); } /* Assumes poly1 and poly2 are not length 0. We almost get away with temporary space of length 2 * len, but in the recursion we might need 4 * \ceil{len/2}, which exceeds 2 * len by at most 2. */ void _fmpz_poly_sqrlow_karatsuba_n(fmpz * res, const fmpz * poly, slong n) { fmpz *temp; slong len, loglen = 0; if (n == 1) { fmpz_mul(res, poly, poly); return; } while ((WORD(1) << loglen) < n) loglen++; len = (WORD(1) << loglen); temp = _fmpz_vec_init(2 * len + 2); _fmpz_poly_sqrlow_kara_recursive(res, poly, temp, n); _fmpz_vec_clear(temp, 2 * len + 2); } void _fmpz_poly_sqrlow_karatsuba(fmpz * res, const fmpz * poly, slong len, slong n) { int clear = 0; slong i; fmpz *copy; if (len >= n) copy = (fmpz *) poly; else { copy = flint_malloc(n * sizeof(fmpz)); for (i = 0; i < len; i++) copy[i] = poly[i]; flint_mpn_zero((mp_ptr) copy + len, n - len); clear = 1; } _fmpz_poly_sqrlow_karatsuba_n(res, copy, n); if (clear) flint_free(copy); } void fmpz_poly_sqrlow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { const slong len = FLINT_MIN(poly->length, n); slong lenr; if (len == 0) { fmpz_poly_zero(res); return; } lenr = 2 * len - 1; n = FLINT_MIN(n, lenr); if (res != poly) { fmpz_poly_fit_length(res, n); _fmpz_poly_sqrlow_karatsuba(res->coeffs, poly->coeffs, len, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_sqrlow_karatsuba(t->coeffs, poly->coeffs, len, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/sqrt.c000066400000000000000000000024671461254215100166070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int _fmpz_poly_sqrt(fmpz * res, const fmpz * poly, slong len) { /* KS is heuristic but fast */ int result = _fmpz_poly_sqrt_KS(res, poly, len); /* KS failed, so use fallback */ if (result == -1) result = _fmpz_poly_sqrt_divconquer(res, poly, len, 1); return result; } int fmpz_poly_sqrt(fmpz_poly_t b, const fmpz_poly_t a) { slong blen, len = a->length; int result; if (len % 2 == 0) { fmpz_poly_zero(b); return len == 0; } if (b == a) { fmpz_poly_t tmp; fmpz_poly_init(tmp); result = fmpz_poly_sqrt(tmp, a); fmpz_poly_swap(b, tmp); fmpz_poly_clear(tmp); return result; } blen = len / 2 + 1; fmpz_poly_fit_length(b, blen); _fmpz_poly_set_length(b, blen); result = _fmpz_poly_sqrt(b->coeffs, a->coeffs, len); if (!result) _fmpz_poly_set_length(b, 0); return result; } flint-3.1.3/src/fmpz_poly/sqrt_KS.c000066400000000000000000000060361461254215100172000ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2018 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #define FMPZ_POLY_SQRT_KS_HEURISTIC_BITS 3 int _fmpz_poly_sqrt_KS(fmpz *rop, const fmpz *op, slong len) { slong i, len2, m, rlimbs; int result = 1; slong bits, bits2, limbs, limbs2, loglen; mp_limb_t *arr, *arr2, *arr3; /* the degree must be even */ if (len % 2 == 0) return 0; /* valuation must be even, and then can be reduced to 0 */ while (fmpz_is_zero(op)) { if (!fmpz_is_zero(op + 1)) return 0; fmpz_zero(rop); op += 2; len -= 2; rop++; } /* check whether a square root exists modulo 2 */ m = (len + 1) / 2; for (i = ((m - 1) | 1); i < len; i += 2) if (!fmpz_is_even(op + i)) return 0; for (i = 1; i < ((m - 1) | 1); i += 2) if (!fmpz_is_even(op + i)) return 0; /* check endpoints */ if (!fmpz_is_square(op)) return 0; if (len > 1 && !fmpz_is_square(op + len - 1)) return 0; bits = FLINT_ABS(_fmpz_vec_max_bits(op, len)); len2 = (len + 1) / 2; bits += FMPZ_POLY_SQRT_KS_HEURISTIC_BITS + FLINT_BIT_COUNT(len); limbs = (bits * len - 1) / FLINT_BITS + 1; arr = (mp_limb_t *) flint_calloc(limbs, sizeof(mp_limb_t)); _fmpz_poly_bit_pack(arr, op, len, bits, 0); limbs2 = (bits * len2 - 1) / FLINT_BITS + 1; arr2 = (mp_limb_t *) flint_calloc(limbs2, sizeof(mp_limb_t)); arr3 = (mp_limb_t *) flint_calloc(limbs, sizeof(mp_limb_t)); while (limbs != 0 && arr[limbs - 1] == 0) limbs--; rlimbs = mpn_sqrtrem(arr2, arr3, arr, limbs); loglen = FLINT_BIT_COUNT(len2); if (rlimbs != 0) result = 0; else { _fmpz_poly_bit_unpack(rop, len2, arr2, bits, 0); bits2 = _fmpz_vec_max_bits(rop, len2); if (2*FLINT_ABS(bits2) + loglen + 1 > bits) result = -1; } flint_free(arr); flint_free(arr2); flint_free(arr3); return result; } int fmpz_poly_sqrt_KS(fmpz_poly_t b, const fmpz_poly_t a) { slong blen, len = a->length; int result; if (len % 2 == 0) { fmpz_poly_zero(b); return len == 0; } if (b == a) { fmpz_poly_t tmp; fmpz_poly_init(tmp); result = fmpz_poly_sqrt_KS(tmp, a); fmpz_poly_swap(b, tmp); fmpz_poly_clear(tmp); return result; } blen = len / 2 + 1; fmpz_poly_fit_length(b, blen); _fmpz_poly_set_length(b, blen); result = _fmpz_poly_sqrt_KS(b->coeffs, a->coeffs, len); if (result <= 0) _fmpz_poly_set_length(b, 0); return result; } flint-3.1.3/src/fmpz_poly/sqrt_classical.c000066400000000000000000000104461461254215100206210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, slong len, int exact) { slong i, m; int result; /* the degree must be even */ if (len % 2 == 0) return 0; if (exact) { /* valuation must be even, and then can be reduced to 0 */ while (fmpz_is_zero(poly)) { if (!fmpz_is_zero(poly + 1)) return 0; fmpz_zero(res); poly += 2; len -= 2; res++; } } /* check whether a square root exists modulo 2 */ m = (len + 1) / 2; for (i = ((m - 1) | 1); i < len; i += 2) if (!fmpz_is_even(poly + i)) return 0; if (exact) { for (i = 1; i < ((m - 1) | 1); i += 2) if (!fmpz_is_even(poly + i)) return 0; } /* check endpoints */ if (exact && !fmpz_is_square(poly)) return 0; if ((len > 1 || !exact) && !fmpz_is_square(poly + len - 1)) return 0; /* square root of leading coefficient */ fmpz_sqrt(res + m - 1, poly + len - 1); result = 1; /* do division style 'square root with remainder' from top to bottom */ if (len > 1) { fmpz_t t, u; fmpz * r; fmpz_init(t); fmpz_init(u); r = _fmpz_vec_init(len); _fmpz_vec_set(r, poly, len); fmpz_mul_ui(u, res + m - 1, 2); for (i = 1; i < (m + 1)/2; i++) { fmpz_fdiv_qr(res + m - i - 1, t, r + len - i - 1, u); if (!fmpz_is_zero(t)) { result = 0; break; } fmpz_mul_si(t, res + m - i - 1, -2); _fmpz_vec_scalar_addmul_fmpz(r + len - 2*i, res + m - i, i - 1, t); fmpz_submul(r + len - 2*i - 1, res + m - i - 1, res + m - i - 1); } if (exact) { for (i = (m + 1)/2; i < m; i++) { fmpz_fdiv_qr(res + m - i - 1, t, r + len - i - 1, u); if (!fmpz_is_zero(t)) { result = 0; break; } fmpz_mul_si(t, res + m - i - 1, -2); _fmpz_vec_scalar_addmul_fmpz(r + len - 2*i, res + m - i, i - 1, t); fmpz_submul(r + len - 2*i - 1, res + m - i - 1, res + m - i - 1); } for (i = m; i < len && result; i++) if (!fmpz_is_zero(r + len - 1 - i)) result = 0; } else { for (i = (m + 1)/2; i < m - 1; i++) { fmpz_fdiv_qr(res + m - i - 1, t, r + len - i - 1, u); if (!fmpz_is_zero(t)) { result = 0; break; } fmpz_mul_si(t, res + m - i - 1, -2); _fmpz_vec_scalar_addmul_fmpz(r + len - m, res + i, m - i - 1, t); } if (m > 1) { fmpz_fdiv_qr(res + 0, t, r + len - m, u); if (!fmpz_is_zero(t)) result = 0; } } _fmpz_vec_clear(r, len); fmpz_clear(t); fmpz_clear(u); } return result; } int fmpz_poly_sqrt_classical(fmpz_poly_t b, const fmpz_poly_t a) { slong blen, len = a->length; int result; if (len % 2 == 0) { fmpz_poly_zero(b); return len == 0; } if (b == a) { fmpz_poly_t tmp; fmpz_poly_init(tmp); result = fmpz_poly_sqrt_classical(tmp, a); fmpz_poly_swap(b, tmp); fmpz_poly_clear(tmp); return result; } blen = len / 2 + 1; fmpz_poly_fit_length(b, blen); _fmpz_poly_set_length(b, blen); result = _fmpz_poly_sqrt_classical(b->coeffs, a->coeffs, len, 1); if (!result) _fmpz_poly_set_length(b, 0); return result; } flint-3.1.3/src/fmpz_poly/sqrt_divconquer.c000066400000000000000000000067131461254215100210440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018, 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Implements the square root with remainder function of "speeding up the division and square root of power series", by Hanrot, Quercia and Zimmermann (see https://hal.inria.fr/inria-00072675/document), but omitting the remainder in the power series case. TODO: implement middle product so that we can implement their Sqrt function (their specialised square root Divide function requires it). */ int _fmpz_poly_sqrt_divconquer(fmpz * res, const fmpz * poly, slong len, int exact) { slong i, n, n2; fmpz * r, * temp; int result; if (len < FMPZ_POLY_SQRT_DIVCONQUER_CUTOFF) return _fmpz_poly_sqrt_classical(res, poly, len, exact); /* the degree must be even */ if (len % 2 == 0) return 0; n = (len + 1)/2; /* check whether a square root exists modulo 2 */ n2 = (n + 1)/2; /* only check coeffs that won't be checked recursively */ for (i = ((n - 1) | 1); i < len - n2; i += 2) if (!fmpz_is_even(poly + i)) return 0; if (exact) { for (i = 1; i < ((n - 1) | 1); i += 2) if (!fmpz_is_even(poly + i)) return 0; } /* check endpoints */ if (exact && !fmpz_is_square(poly)) return 0; r = _fmpz_vec_init(len); temp = _fmpz_vec_init(len); _fmpz_vec_set(r, poly, len); result = _fmpz_poly_sqrtrem_divconquer(res + n - n2, r + len - 2*n2 + 1, r + len - 2*n2 + 1, 2*n2 - 1, temp); if (result) { _fmpz_vec_scalar_mul_ui(temp, res + n - n2, n2, 2); _fmpz_vec_set(temp + n, r + n2, 2*n - 2*n2 - 1); if (!_fmpz_poly_divrem(res, r + n2, temp + n, 2*n - 2*n2 - 1, temp + 2*n2 - n, n - n2, 1)) result = 0; if (exact && result) { _fmpz_poly_mul(temp + 2*n2 - n, res, n - n2, res, n - n2); _fmpz_vec_sub(r, r, temp + 2*n2 - n, 2*n - 2*n2 - 1); if (2*n2 > n) _fmpz_vec_scalar_submul_fmpz(r + n - n2, res, n2 - 1, temp); for (i = n; i < len && result; i++) { if (!fmpz_is_zero(r + len - 1 - i)) { result = 0; break; } } } } _fmpz_vec_clear(r, len); _fmpz_vec_clear(temp, len); return result; } int fmpz_poly_sqrt_divconquer(fmpz_poly_t b, const fmpz_poly_t a) { slong blen, len = a->length; int result; if (len % 2 == 0) { fmpz_poly_zero(b); return len == 0; } if (b == a) { fmpz_poly_t tmp; fmpz_poly_init(tmp); result = fmpz_poly_sqrt_divconquer(tmp, a); fmpz_poly_swap(b, tmp); fmpz_poly_clear(tmp); return result; } blen = len / 2 + 1; fmpz_poly_fit_length(b, blen); _fmpz_poly_set_length(b, blen); result = _fmpz_poly_sqrt_divconquer(b->coeffs, a->coeffs, len, 1); if (!result) _fmpz_poly_set_length(b, 0); return result; } flint-3.1.3/src/fmpz_poly/sqrt_series.c000066400000000000000000000036201461254215100201510ustar00rootroot00000000000000/* Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_sqrt_series(fmpz * res, const fmpz * poly, slong len, slong n) { int result; slong i; fmpz * rev; while (len > 0 && n > 0 && fmpz_is_zero(poly)) { if (len > 1 && !fmpz_is_zero(poly + 1)) return 0; fmpz_zero(res); fmpz_zero(res + n - 1); poly += 2; len -= 2; n -= 2; res++; } if (len <= 0) { for (i = 0; i < n; i++) fmpz_zero(res + i); return 1; } if (n <= 0) return 1; rev = _fmpz_vec_init(2*n - 1); _fmpz_poly_reverse(rev, poly, FLINT_MIN(2*n - 1, len), 2*n - 1); result = _fmpz_poly_sqrt_divconquer(res, rev, 2*n - 1, 0); if (result) _fmpz_poly_reverse(res, res, n, n); _fmpz_vec_clear(rev, 2*n - 1); return result; } int fmpz_poly_sqrt_series(fmpz_poly_t b, const fmpz_poly_t a, slong n) { slong len = a->length; int result; if (n == 0 || len == 0) { fmpz_poly_zero(b); return 1; } if (b == a) { fmpz_poly_t tmp; fmpz_poly_init(tmp); result = fmpz_poly_sqrt_series(tmp, a, n); fmpz_poly_swap(b, tmp); fmpz_poly_clear(tmp); return result; } fmpz_poly_fit_length(b, n); _fmpz_poly_set_length(b, n); result = _fmpz_poly_sqrt_series(b->coeffs, a->coeffs, len, n); if (result) _fmpz_poly_normalise(b); else _fmpz_poly_set_length(b, 0); return result; } flint-3.1.3/src/fmpz_poly/sqrtrem_classical.c000066400000000000000000000052201461254215100213170ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" int _fmpz_poly_sqrtrem_classical(fmpz * res, fmpz * r, const fmpz * poly, slong len) { slong i, m; int result; /* the degree must be even */ if (len % 2 == 0) return 0; /* check whether a square root exists modulo 2 */ m = (len + 1) / 2; for (i = ((m - 1) | 1); i < len; i += 2) if (!fmpz_is_even(poly + i)) return 0; /* check leading coefficient */ if (!fmpz_is_square(poly + len - 1)) return 0; /* square root of leading coefficient */ fmpz_sqrt(res + m - 1, poly + len - 1); result = 1; /* do division style 'square root with remainder' from top to bottom */ if (len > 1) { fmpz_t t, u; fmpz_init(t); fmpz_init(u); if (r != poly) _fmpz_vec_set(r, poly, len); fmpz_mul_ui(u, res + m - 1, 2); for (i = 1; i < m; i++) { fmpz_fdiv_qr(res + m - i - 1, t, r + len - i - 1, u); if (!fmpz_is_zero(t)) { result = 0; break; } fmpz_mul_si(t, res + m - i - 1, -2); _fmpz_vec_scalar_addmul_fmpz(r + len - 2*i, res + m - i, i - 1, t); fmpz_submul(r + len - 2*i - 1, res + m - i - 1, res + m - i - 1); } fmpz_clear(t); fmpz_clear(u); } return result; } int fmpz_poly_sqrtrem_classical(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a) { slong blen, len = a->length; int result; if (len % 2 == 0) { fmpz_poly_zero(b); fmpz_poly_zero(r); return len == 0; } if (b == a) { fmpz_poly_t tmp; fmpz_poly_init(tmp); result = fmpz_poly_sqrtrem_classical(tmp, r, a); fmpz_poly_swap(b, tmp); fmpz_poly_clear(tmp); return result; } blen = len / 2 + 1; fmpz_poly_fit_length(r, len); fmpz_poly_fit_length(b, blen); _fmpz_poly_set_length(b, blen); result = _fmpz_poly_sqrtrem_classical(b->coeffs, r->coeffs, a->coeffs, len); if (!result) _fmpz_poly_set_length(b, 0); else { _fmpz_poly_set_length(r, blen - 1); _fmpz_poly_normalise(r); } return result; } flint-3.1.3/src/fmpz_poly/sqrtrem_divconquer.c000066400000000000000000000057131461254215100215470ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018, 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Implements the square root with remainder function of "speeding up the division and square root of power series", by Hanrot, Quercia and Zimmermann (see https://hal.inria.fr/inria-00072675/document). TODO: implement middle product so that we can implement their Sqrt function (their specialised square root Divide function requires it). */ int _fmpz_poly_sqrtrem_divconquer(fmpz * res, fmpz * r, const fmpz * poly, slong len, fmpz * temp) { slong i, n, n2; if (len < FMPZ_POLY_SQRTREM_DIVCONQUER_CUTOFF) return _fmpz_poly_sqrtrem_classical(res, r, poly, len); /* the degree must be even */ if (len % 2 == 0) return 0; n = (len + 1)/2; /* check whether a square root exists modulo 2 */ n2 = (n + 1)/2; /* only check coeffs that won't be checked recursively */ for (i = ((n - 1) | 1); i < len - n2; i += 2) if (!fmpz_is_even(poly + i)) return 0; if (r != poly) _fmpz_vec_set(r, poly, len); if (!_fmpz_poly_sqrtrem_divconquer(res + n - n2, r + len - 2*n2 + 1, r + len - 2*n2 + 1, 2*n2 - 1, temp)) return 0; _fmpz_vec_scalar_mul_ui(temp, res + n - n2, n2, 2); _fmpz_vec_set(temp + n, r + n2, 2*n - 2*n2 - 1); if (!_fmpz_poly_divrem(res, r + n2, temp + n, 2*n - 2*n2 - 1, temp + 2*n2 - n, n - n2, 1)) return 0; _fmpz_poly_mul(temp + 2*n2 - n, res, n - n2, res, n - n2); _fmpz_vec_sub(r, r, temp + 2*n2 - n, 2*n - 2*n2 - 1); if (2*n2 > n) _fmpz_vec_scalar_submul_fmpz(r + n - n2, res, n2 - 1, temp); return 1; } int fmpz_poly_sqrtrem_divconquer(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a) { slong blen, len = a->length; fmpz * temp; int result; if (len % 2 == 0) { fmpz_poly_zero(b); fmpz_poly_zero(r); return len == 0; } if (b == a) { fmpz_poly_t tmp; fmpz_poly_init(tmp); result = fmpz_poly_sqrtrem_divconquer(tmp, r, a); fmpz_poly_swap(b, tmp); fmpz_poly_clear(tmp); return result; } blen = len / 2 + 1; fmpz_poly_fit_length(r, len); fmpz_poly_fit_length(b, blen); _fmpz_poly_set_length(b, blen); temp = _fmpz_vec_init(len); result = _fmpz_poly_sqrtrem_divconquer(b->coeffs, r->coeffs, a->coeffs, len, temp); if (!result) _fmpz_poly_set_length(b, 0); else { _fmpz_poly_set_length(r, blen - 1); _fmpz_poly_normalise(r); } _fmpz_vec_clear(temp, len); return result; } flint-3.1.3/src/fmpz_poly/sub.c000066400000000000000000000055341461254215100164050ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_sub(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { slong i, min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) /* subtract up to the length of the shorter poly */ fmpz_sub(res + i, poly1 + i, poly2 + i); if (poly1 != res) /* copy any remaining coefficients from poly1 */ for (i = min; i < len1; i++) fmpz_set(res + i, poly1 + i); /* careful, it is *always* necessary to negate coeffs from poly2, even if this is already res */ for (i = min; i < len2; i++) fmpz_neg(res + i, poly2 + i); } void fmpz_poly_sub(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { slong max = FLINT_MAX(poly1->length, poly2->length); fmpz_poly_fit_length(res, max); _fmpz_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); _fmpz_poly_set_length(res, max); _fmpz_poly_normalise(res); /* there may have been cancellation */ } void fmpz_poly_sub_si(fmpz_poly_t res, const fmpz_poly_t poly, slong c) { if (poly->length == 0) { fmpz_poly_set_si(res, c); fmpz_poly_neg(res, res); } else { fmpz_poly_set(res, poly); if (c < 0) fmpz_add_ui(res->coeffs + 0, res->coeffs + 0, -c); else fmpz_sub_ui(res->coeffs + 0, res->coeffs + 0, c); _fmpz_poly_normalise(res); } } void fmpz_poly_si_sub(fmpz_poly_t res, slong c, const fmpz_poly_t poly) { if (poly->length == 0) fmpz_poly_set_si(res, c); else { fmpz_poly_neg(res, poly); if (c < 0) fmpz_sub_ui(res->coeffs + 0, res->coeffs + 0, -c); else fmpz_add_ui(res->coeffs + 0, res->coeffs + 0, c); _fmpz_poly_normalise(res); } } void fmpz_poly_sub_fmpz(fmpz_poly_t res, const fmpz_poly_t poly, fmpz_t c) { if (poly->length == 0) { fmpz_poly_set_fmpz(res, c); fmpz_neg(res->coeffs + 0, res->coeffs + 0); } else { fmpz_poly_set(res, poly); fmpz_sub(res->coeffs + 0, res->coeffs + 0, c); _fmpz_poly_normalise(res); } } void fmpz_poly_fmpz_sub(fmpz_poly_t res, fmpz_t c, const fmpz_poly_t poly) { if (poly->length == 0) fmpz_poly_set_fmpz(res, c); else { fmpz_poly_neg(res, poly); fmpz_add(res->coeffs + 0, res->coeffs + 0, c); _fmpz_poly_normalise(res); } } flint-3.1.3/src/fmpz_poly/sub_series.c000066400000000000000000000016641461254215100177570ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_sub_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); fmpz_poly_fit_length(res, max); _fmpz_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2); _fmpz_poly_set_length(res, max); _fmpz_poly_normalise(res); } flint-3.1.3/src/fmpz_poly/swap.c000066400000000000000000000010101461254215100165470ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void fmpz_poly_swap(fmpz_poly_t poly1, fmpz_poly_t poly2) { FLINT_SWAP(fmpz_poly_struct, *poly1, *poly2); } flint-3.1.3/src/fmpz_poly/swinnerton_dyer.c000066400000000000000000000020301461254215100210310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "arb_poly.h" void _fmpz_poly_swinnerton_dyer(fmpz * T, ulong n) { if (n == 0) { fmpz_zero(T); fmpz_one(T + 1); } else { arb_poly_t t; arb_poly_init(t); arb_poly_swinnerton_dyer_ui(t, n, 0); if (!_arb_vec_get_unique_fmpz_vec(T, t->coeffs, t->length)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); arb_poly_clear(t); } } void fmpz_poly_swinnerton_dyer(fmpz_poly_t poly, ulong n) { slong N = (WORD(1) << n); fmpz_poly_fit_length(poly, N + 1); _fmpz_poly_swinnerton_dyer(poly->coeffs, n); _fmpz_poly_set_length(poly, N + 1); } flint-3.1.3/src/fmpz_poly/taylor_shift.c000066400000000000000000000014521461254215100203160ustar00rootroot00000000000000/* Copyright (C) 2012, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void _fmpz_poly_taylor_shift(fmpz * poly, const fmpz_t c, slong len) { if (len < 64) _fmpz_poly_taylor_shift_horner(poly, c, len); else _fmpz_poly_taylor_shift_divconquer(poly, c, len); } void fmpz_poly_taylor_shift(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) { if (f != g) fmpz_poly_set(g, f); _fmpz_poly_taylor_shift(g->coeffs, c, g->length); } flint-3.1.3/src/fmpz_poly/taylor_shift_divconquer.c000066400000000000000000000077631461254215100225700ustar00rootroot00000000000000/* Copyright (C) 2012, 2016 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" typedef struct { fmpz * poly; const fmpz * c; slong len; } worker_t; static void _fmpz_poly_taylor_shift_divconquer_worker(void * arg_ptr) { worker_t * data = (worker_t *) arg_ptr; _fmpz_poly_taylor_shift_divconquer(data->poly, data->c, data->len); } void _fmpz_poly_taylor_shift_divconquer(fmpz * poly, const fmpz_t c, slong len) { fmpz *tmp, *tmp2; slong k, len1, len2; slong bits, cutoff; slong nt, nw; thread_pool_handle * threads; worker_t args[2]; if (len < 50 || fmpz_is_zero(c)) { _fmpz_poly_taylor_shift_horner(poly, c, len); return; } bits = _fmpz_vec_max_bits(poly, len); bits = FLINT_ABS(bits); nt = flint_get_num_threads(); cutoff = 100 + 10 * n_sqrt(FLINT_MAX(bits - FLINT_BITS, 0)); /* Parallel cutoff is set lower since shift_horner is serial. */ if (nt == 1) cutoff = FLINT_MIN(cutoff, 1000); else cutoff = FLINT_MIN(cutoff, 300); if (len < cutoff) { _fmpz_poly_taylor_shift_horner(poly, c, len); return; } len1 = len / 2; len2 = len - len1; nw = flint_request_threads(&threads, FLINT_MIN(nt, 2)); /* request one extra worker */ if (len < 200 || len + bits < 2000 || nw == 0) { _fmpz_poly_taylor_shift_divconquer(poly, c, len1); _fmpz_poly_taylor_shift_divconquer(poly + len1, c, len2); } else { slong nw_save; args[0].poly = poly; args[0].c = c; args[0].len = len1; args[1].poly = poly + len1; args[1].c = c; args[1].len = len2; FLINT_ASSERT(nt >= 2); nw_save = flint_set_num_workers(nt - nt/2 - 1); thread_pool_wake(global_thread_pool, threads[0], nt/2 - 1, _fmpz_poly_taylor_shift_divconquer_worker, &args[1]); _fmpz_poly_taylor_shift_divconquer_worker(&args[0]); flint_reset_num_workers(nw_save); thread_pool_wait(global_thread_pool, threads[0]); } flint_give_back_threads(threads, nw); tmp = _fmpz_vec_init(len1 + 1); tmp2 = _fmpz_vec_init(len); /* Now we generate (x+c)^len1 using binomial expansion. It's redundant to do this in all branches of the tree, but since it's just O(d), it's going to be cheap compared to the actual multiplications anyway. */ fmpz_one(tmp); for (k = 1; k <= len1; k++) { if (k > len1 - k) { fmpz_set(tmp + k, tmp + len1 - k); } else { fmpz_mul_ui(tmp + k, tmp + k - 1, len1 + 1 - k); fmpz_divexact_ui(tmp + k, tmp + k, k); } } if (!fmpz_is_one(c)) { if (fmpz_cmp_si(c, -1) == 0) { for (k = len1 - 1; k >= 0; k -= 2) fmpz_neg(tmp + k, tmp + k); } else { fmpz_set(tmp2, c); for (k = len1 - 1; k >= 0; k--) { fmpz_mul(tmp + k, tmp + k, tmp2); fmpz_mul(tmp2, tmp2, c); } } } _fmpz_poly_mul(tmp2, tmp, len1 + 1, poly + len1, len2); _fmpz_vec_add(poly, poly, tmp2, len1); _fmpz_vec_set(poly + len1, tmp2 + len1, len2); _fmpz_vec_clear(tmp, len1 + 1); _fmpz_vec_clear(tmp2, len); } void fmpz_poly_taylor_shift_divconquer(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) { if (f != g) fmpz_poly_set(g, f); _fmpz_poly_taylor_shift_divconquer(g->coeffs, c, g->length); } flint-3.1.3/src/fmpz_poly/taylor_shift_horner.c000066400000000000000000000126351461254215100217000ustar00rootroot00000000000000/* Copyright (C) 2012, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Improve cache locality with huge coefficients */ #define BLOCK_SIZE 32 void _fmpz_poly_taylor_shift_horner(fmpz * poly, const fmpz_t c, slong n) { slong i, j, bits, out_bits; if (n <= 1 || fmpz_is_zero(c)) return; if (!fmpz_is_one(c)) { if (n <= 4 || (*c != WORD(-1) && n <= 10)) { if (*c == WORD(-1)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) fmpz_sub(poly + j, poly + j, poly + j + 1); } else { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) fmpz_addmul(poly + j, poly + j + 1, c); } } else { slong i; fmpz_t d, one; *one = 1; if (*c == WORD(-1)) { for (i = 1; i < n; i += 2) fmpz_neg(poly + i, poly + i); _fmpz_poly_taylor_shift_horner(poly, one, n); for (i = 1; i < n; i += 2) fmpz_neg(poly + i, poly + i); } else { fmpz_init(d); for (i = 1; i < n; i++) { if (i == 1) fmpz_set(d, c); else fmpz_mul(d, d, c); fmpz_mul(poly + i, poly + i, d); } _fmpz_poly_taylor_shift_horner(poly, one, n); for (i = n - 1; i >= 1; i--) { fmpz_divexact(poly + i, poly + i, d); if (i >= 3) fmpz_divexact(d, d, c); else if (i == 2) fmpz_set(d, c); } fmpz_clear(d); } } return; } bits = _fmpz_vec_max_bits(poly, n); bits = FLINT_ABS(bits); out_bits = bits + n + 1; if (out_bits <= SMALL_FMPZ_BITCOUNT_MAX) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) poly[j] += poly[j + 1]; } else if (n >= 5 && out_bits < 2 * FLINT_BITS) { mp_ptr t; TMP_INIT; TMP_START; t = TMP_ALLOC(2 * n * sizeof(mp_limb_t)); for (i = 0; i < n; i++) fmpz_get_signed_uiui(t + 2*i + 1, t + 2*i + 0, poly + i); for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) add_ssaaaa(t[2*j + 1], t[2*j], t[2*j + 1], t[2*j], t[2*(j + 1) + 1], t[2*(j + 1)]); for (i = 0; i < n; i++) fmpz_set_signed_uiui(poly + i, t[2*i + 1], t[2*i]); TMP_END; } else if (n >= 3 + FLINT_BIT_COUNT(bits) && bits <= 100 * FLINT_BITS) { slong B = BLOCK_SIZE, ii, jj, d; mp_ptr t; TMP_INIT; TMP_START; d = (out_bits + FLINT_BITS - 1) / FLINT_BITS; t = TMP_ALLOC(d * n * sizeof(mp_limb_t)); for (i = 0; i < n; i++) fmpz_get_signed_ui_array(t + d * i, d, poly + i); if (d == 3) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) add_sssaaaaaa(t[3 * j + 2], t[3 * j + 1], t[3 * j], t[3 * j + 2], t[3 * j + 1], t[3 * j], t[3 * (j + 1) + 2], t[3 * (j + 1) + 1], t[3 * (j + 1)]); } else if (n < 2 * B) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) mpn_add_n(t + d * j, t + d * j, t + d * (j + 1), d); } else { for (ii = n - 2; ii >= 0; ii -= B) for (jj = 0; jj < n - ii - 1; jj += B) for (i = ii; i >= FLINT_MAX(ii - B + 1, 0); i--) for (j = jj; j < FLINT_MIN(jj + B, n - i - 1); j++) mpn_add_n(t + d * (i + j), t + d * (i + j), t + d * (i + j + 1), d); } for (i = 0; i < n; i++) fmpz_set_signed_ui_array(poly + i, t + d * i, d); TMP_END; } else { slong B = BLOCK_SIZE, ii, jj; if (n < 2 * B) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) fmpz_add(poly + j, poly + j, poly + j + 1); } else { for (ii = n - 2; ii >= 0; ii -= B) for (jj = 0; jj < n - ii - 1; jj += B) for (i = ii; i >= FLINT_MAX(ii - B + 1, 0); i--) for (j = jj; j < FLINT_MIN(jj + B, n - i - 1); j++) fmpz_add(poly + i + j, poly + i + j, poly + i + j + 1); } } } void fmpz_poly_taylor_shift_horner(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) { if (f != g) fmpz_poly_set(g, f); _fmpz_poly_taylor_shift_horner(g->coeffs, c, g->length); } flint-3.1.3/src/fmpz_poly/taylor_shift_multi_mod_threaded.c000066400000000000000000000142241461254215100242300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" typedef struct { fmpz * vec; mp_ptr * residues; slong n0; slong n1; mp_srcptr primes; slong num_primes; int crt; /* reduce if 0, lift if 1 */ } mod_ui_arg_t; void _fmpz_vec_multi_mod_ui_worker(void * arg_ptr) { mod_ui_arg_t arg = *((mod_ui_arg_t *) arg_ptr); mp_ptr tmp; slong i, j; fmpz_comb_t comb; fmpz_comb_temp_t comb_temp; tmp = flint_malloc(sizeof(mp_limb_t) * arg.num_primes); fmpz_comb_init(comb, arg.primes, arg.num_primes); fmpz_comb_temp_init(comb_temp, comb); for (i = arg.n0; i < arg.n1; i++) { if (arg.crt) { for (j = 0; j < arg.num_primes; j++) tmp[j] = arg.residues[j][i]; fmpz_multi_CRT_ui(arg.vec + i, tmp, comb, comb_temp, 1); } else { fmpz_multi_mod_ui(tmp, arg.vec + i, comb, comb_temp); for (j = 0; j < arg.num_primes; j++) arg.residues[j][i] = tmp[j]; } } flint_free(tmp); fmpz_comb_clear(comb); fmpz_comb_temp_clear(comb_temp); } void _fmpz_vec_multi_mod_ui_threaded(mp_ptr * residues, fmpz * vec, slong len, mp_srcptr primes, slong num_primes, int crt) { mod_ui_arg_t * args; slong i, num_threads; thread_pool_handle * threads; num_threads = flint_request_threads(&threads, flint_get_num_threads()); args = (mod_ui_arg_t *) flint_malloc(sizeof(mod_ui_arg_t)*(num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].vec = vec; args[i].residues = residues; args[i].n0 = (len * i) / (num_threads + 1); args[i].n1 = (len * (i + 1)) / (num_threads + 1); args[i].primes = (mp_ptr) primes; args[i].num_primes = num_primes; args[i].crt = crt; } for (i = 0; i < num_threads; i++) thread_pool_wake(global_thread_pool, threads[i], 0, _fmpz_vec_multi_mod_ui_worker, &args[i]); _fmpz_vec_multi_mod_ui_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) thread_pool_wait(global_thread_pool, threads[i]); flint_give_back_threads(threads, num_threads); flint_free(args); } typedef struct { mp_ptr * residues; slong len; mp_srcptr primes; slong num_primes; slong p0; slong p1; fmpz * c; } taylor_shift_arg_t; void _fmpz_poly_multi_taylor_shift_worker(void * arg_ptr) { taylor_shift_arg_t arg = *((taylor_shift_arg_t *) arg_ptr); slong i; for (i = arg.p0; i < arg.p1; i++) { nmod_t mod; mp_limb_t p, cm; p = arg.primes[i]; nmod_init(&mod, p); cm = fmpz_fdiv_ui(arg.c, p); _nmod_poly_taylor_shift(arg.residues[i], cm, arg.len, mod); } } void _fmpz_poly_multi_taylor_shift_threaded(mp_ptr * residues, slong len, const fmpz_t c, mp_srcptr primes, slong num_primes) { taylor_shift_arg_t * args; slong i, num_threads; thread_pool_handle * threads; num_threads = flint_request_threads(&threads, flint_get_num_threads()); args = (taylor_shift_arg_t *) flint_malloc(sizeof(taylor_shift_arg_t)*(num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].residues = residues; args[i].len = len; args[i].p0 = (num_primes * i) / (num_threads + 1); args[i].p1 = (num_primes * (i + 1)) / (num_threads + 1); args[i].primes = (mp_ptr) primes; args[i].num_primes = num_primes; args[i].c = (fmpz *) c; } for (i = 0; i < num_threads; i++) thread_pool_wake(global_thread_pool, threads[i], 0, _fmpz_poly_multi_taylor_shift_worker, &args[i]); _fmpz_poly_multi_taylor_shift_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) thread_pool_wait(global_thread_pool, threads[i]); flint_give_back_threads(threads, num_threads); flint_free(args); } void _fmpz_poly_taylor_shift_multi_mod(fmpz * poly, const fmpz_t c, slong len) { slong xbits, ybits, num_primes, i; mp_ptr primes; mp_ptr * residues; if (len <= 1 || fmpz_is_zero(c)) return; xbits = _fmpz_vec_max_bits(poly, len); if (xbits == 0) return; /* If poly has degree D and coefficients at most |C|, the output has coefficient at most D * |C| * 2^D * c^D */ xbits = FLINT_ABS(xbits) + 1; ybits = xbits + len + FLINT_BIT_COUNT(len); if (!fmpz_is_pm1(c)) { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, c, len); ybits += fmpz_bits(t); fmpz_clear(t); } /* Use primes greater than 2^(FLINT_BITS-1) */ num_primes = (ybits + (FLINT_BITS - 1) - 1) / (FLINT_BITS - 1); primes = flint_malloc(sizeof(mp_limb_t) * num_primes); primes[0] = n_nextprime(UWORD(1) << (FLINT_BITS - 1), 1); for (i = 1; i < num_primes; i++) primes[i] = n_nextprime(primes[i-1], 1); /* Space for poly reduced modulo the primes */ residues = flint_malloc(sizeof(mp_ptr) * num_primes); for (i = 0; i < num_primes; i++) residues[i] = flint_malloc(sizeof(mp_limb_t) * len); _fmpz_vec_multi_mod_ui_threaded(residues, poly, len, primes, num_primes, 0); _fmpz_poly_multi_taylor_shift_threaded(residues, len, c, primes, num_primes); _fmpz_vec_multi_mod_ui_threaded(residues, poly, len, primes, num_primes, 1); for (i = 0; i < num_primes; i++) flint_free(residues[i]); flint_free(residues); flint_free(primes); } flint-3.1.3/src/fmpz_poly/test/000077500000000000000000000000001461254215100164205ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly/test/main.c000066400000000000000000000323531461254215100175160ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Try to get fdopen declared for fmpz_poly_[print/read] */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #include #include #include #include /* Include functions *********************************************************/ #include "t-2norm_normalised_bits.c" #include "t-add.c" #include "t-add_series.c" #include "t-add_sub_fmpz.c" #include "t-add_sub_si.c" #include "t-bit_pack.c" #include "t-bound_roots.c" #include "t-chebyshev_t.c" #include "t-chebyshev_u.c" #include "t-CLD_bound.c" #include "t-compose.c" #include "t-compose_divconquer.c" #include "t-compose_horner.c" #include "t-compose_series_brent_kung.c" #include "t-compose_series.c" #include "t-compose_series_horner.c" #include "t-content.c" #include "t-cos_minpoly.c" #include "t-CRT_ui.c" #include "t-CRT_ui_unsigned.c" #include "t-cyclotomic.c" #include "t-deflate.c" #include "t-derivative.c" #include "t-discriminant.c" #include "t-div_basecase.c" #include "t-div_divconquer.c" #include "t-divexact.c" #include "t-divhigh_smodp.c" #include "t-divides.c" #include "t-divlow_smodp.c" #include "t-div_preinv.c" #include "t-divrem_basecase.c" #include "t-divrem.c" #include "t-divrem_divconquer.c" #include "t-divrem_preinv.c" #include "t-div_root.c" #include "t-div_series_basecase.c" #include "t-div_series.c" #include "t-div_series_divconquer.c" #include "t-equal_fmpz.c" #include "t-equal_trunc.c" #include "t-eta_qexp.c" #include "t-eulerian_polynomial.c" #include "t-evaluate_divconquer_fmpq.c" #include "t-evaluate_divconquer_fmpz.c" #include "t-evaluate_fmpq.c" #include "t-evaluate_fmpz.c" #include "t-evaluate_horner_d_2exp.c" #include "t-evaluate_horner_fmpq.c" #include "t-evaluate_horner_fmpz.c" #include "t-evaluate_mod.c" #include "t-fibonacci.c" #include "t-gcd.c" #include "t-gcd_heuristic.c" #include "t-gcd_modular.c" #include "t-gcd_subresultant.c" #include "t-get_coeff_ptr.c" #include "t-get_nmod_poly.c" #include "t-get_set_coeff_fmpz.c" #include "t-get_set_coeff_si.c" #include "t-get_set_coeff_ui.c" #include "t-get_set_str.c" #include "t-get_str.c" #include "t-get_str_pretty.c" #include "t-hensel_lift.c" #include "t-hensel_lift_once.c" #include "t-hensel_lift_without_only_inverse.c" #include "t-hensel_start_continue_lift.c" #include "t-hermite_h.c" #include "t-hermite_he.c" #include "t-inflate.c" #include "t-init_realloc_clear.c" #include "t-interpolate_fmpz_vec.c" #include "t-inv_series_basecase.c" #include "t-inv_series.c" #include "t-inv_series_newton.c" #include "t-is_cyclotomic.c" #include "t-is_squarefree.c" #include "t-lcm.c" #include "t-legendre_pt.c" #include "t-mul.c" #include "t-mul_classical.c" #include "t-mulhigh_classical.c" #include "t-mulhigh_karatsuba_n.c" #include "t-mulhigh_n.c" #include "t-mul_karatsuba.c" #include "t-mul_KS.c" #include "t-mullow.c" #include "t-mullow_classical.c" #include "t-mullow_karatsuba_n.c" #include "t-mullow_KS.c" #include "t-mullow_SS.c" #include "t-mullow_SS_precache.c" #include "t-mulmid_classical.c" #include "t-mul_SS.c" #include "t-mul_SS_precache.c" #include "t-neg.c" #include "t-newton_to_monomial.c" #include "t-nth_derivative.c" #include "t-num_real_roots.c" #include "t-num_real_roots_sturm.c" #include "t-pow_addchains.c" #include "t-pow_binexp.c" #include "t-pow_binomial.c" #include "t-pow.c" #include "t-power_sums.c" #include "t-pow_multinomial.c" #include "t-pow_trunc.c" #include "t-primitive_part.c" #include "t-print_read.c" #include "t-print_read_pretty.c" #include "t-product_roots_fmpq_vec.c" #include "t-product_roots_fmpz_vec.c" #include "t-pseudo_div.c" #include "t-pseudo_divrem_basecase.c" #include "t-pseudo_divrem_cohen.c" #include "t-pseudo_divrem_divconquer.c" #include "t-pseudo_rem.c" #include "t-pseudo_rem_cohen.c" #include "t-randtest_no_real_root.c" #include "t-rem_basecase.c" #include "t-remove.c" #include "t-remove_content_2exp.c" #include "t-rem_powers_precomp.c" #include "t-resultant.c" #include "t-resultant_euclidean.c" #include "t-resultant_modular.c" #include "t-resultant_modular_div.c" #include "t-reverse.c" #include "t-revert_series.c" #include "t-scalar_abs.c" #include "t-scalar_addmul_fmpz.c" #include "t-scalar_addmul_si.c" #include "t-scalar_addmul_ui.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_si.c" #include "t-scalar_mul_ui.c" #include "t-scalar_submul_fmpz.c" #include "t-scale_2exp.c" #include "t-set_equal.c" #include "t-set_fmpz_equal.c" #include "t-set_si_equal.c" #include "t-set_trunc.c" #include "t-set_ui_equal.c" #include "t-shift_left_right.c" #include "t-signature.c" #include "t-sqr.c" #include "t-sqr_classical.c" #include "t-sqr_karatsuba.c" #include "t-sqr_KS.c" #include "t-sqrlow.c" #include "t-sqrlow_classical.c" #include "t-sqrlow_karatsuba_n.c" #include "t-sqrlow_KS.c" #include "t-sqrt.c" #include "t-sqrt_classical.c" #include "t-sqrt_divconquer.c" #include "t-sqrt_KS.c" #include "t-sqrtrem_classical.c" #include "t-sqrtrem_divconquer.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-swap.c" #include "t-swinnerton_dyer.c" #include "t-taylor_shift.c" #include "t-taylor_shift_divconquer.c" #include "t-taylor_shift_horner.c" #include "t-taylor_shift_multi_mod_threaded.c" #include "t-theta_qexp.c" #include "t-xgcd_modular.c" #include "t-zero.c" #include "t-zero_coeffs.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_poly_2norm_normalised_bits), TEST_FUNCTION(fmpz_poly_add), TEST_FUNCTION(fmpz_poly_add_series), TEST_FUNCTION(fmpz_poly_add_sub_fmpz), TEST_FUNCTION(fmpz_poly_add_sub_si), TEST_FUNCTION(fmpz_poly_bit_pack), TEST_FUNCTION(fmpz_poly_bound_roots), TEST_FUNCTION(fmpz_poly_chebyshev_t), TEST_FUNCTION(fmpz_poly_chebyshev_u), TEST_FUNCTION(fmpz_poly_CLD_bound), TEST_FUNCTION(fmpz_poly_compose), TEST_FUNCTION(fmpz_poly_compose_divconquer), TEST_FUNCTION(fmpz_poly_compose_horner), TEST_FUNCTION(fmpz_poly_compose_series_brent_kung), TEST_FUNCTION(fmpz_poly_compose_series), TEST_FUNCTION(fmpz_poly_compose_series_horner), TEST_FUNCTION(fmpz_poly_content), TEST_FUNCTION(fmpz_poly_cos_minpoly), TEST_FUNCTION(fmpz_poly_CRT_ui), TEST_FUNCTION(fmpz_poly_CRT_ui_unsigned), TEST_FUNCTION(fmpz_poly_cyclotomic), TEST_FUNCTION(fmpz_poly_deflate), TEST_FUNCTION(fmpz_poly_derivative), TEST_FUNCTION(fmpz_poly_discriminant), TEST_FUNCTION(fmpz_poly_div_basecase), TEST_FUNCTION(fmpz_poly_div_divconquer), TEST_FUNCTION(fmpz_poly_divexact), TEST_FUNCTION(fmpz_poly_divhigh_smodp), TEST_FUNCTION(fmpz_poly_divides), TEST_FUNCTION(fmpz_poly_divlow_smodp), TEST_FUNCTION(fmpz_poly_div_preinv), TEST_FUNCTION(fmpz_poly_divrem_basecase), TEST_FUNCTION(fmpz_poly_divrem), TEST_FUNCTION(fmpz_poly_divrem_divconquer), TEST_FUNCTION(fmpz_poly_divrem_preinv), TEST_FUNCTION(fmpz_poly_div_root), TEST_FUNCTION(fmpz_poly_div_series_basecase), TEST_FUNCTION(fmpz_poly_div_series), TEST_FUNCTION(fmpz_poly_div_series_divconquer), TEST_FUNCTION(fmpz_poly_equal_fmpz), TEST_FUNCTION(fmpz_poly_equal_trunc), TEST_FUNCTION(fmpz_poly_eta_qexp), TEST_FUNCTION(fmpz_poly_eulerian_polynomial), TEST_FUNCTION(fmpz_poly_evaluate_divconquer_fmpq), TEST_FUNCTION(fmpz_poly_evaluate_divconquer_fmpz), TEST_FUNCTION(fmpz_poly_evaluate_fmpq), TEST_FUNCTION(fmpz_poly_evaluate_fmpz), TEST_FUNCTION(fmpz_poly_evaluate_horner_d_2exp), TEST_FUNCTION(fmpz_poly_evaluate_horner_fmpq), TEST_FUNCTION(fmpz_poly_evaluate_horner_fmpz), TEST_FUNCTION(fmpz_poly_evaluate_mod), TEST_FUNCTION(fmpz_poly_fibonacci), TEST_FUNCTION(fmpz_poly_gcd), TEST_FUNCTION(fmpz_poly_gcd_heuristic), TEST_FUNCTION(fmpz_poly_gcd_modular), TEST_FUNCTION(fmpz_poly_gcd_subresultant), TEST_FUNCTION(fmpz_poly_get_coeff_ptr), TEST_FUNCTION(fmpz_poly_get_nmod_poly), TEST_FUNCTION(fmpz_poly_get_set_coeff_fmpz), TEST_FUNCTION(fmpz_poly_get_set_coeff_si), TEST_FUNCTION(fmpz_poly_get_set_coeff_ui), TEST_FUNCTION(fmpz_poly_get_set_str), TEST_FUNCTION(fmpz_poly_get_str), TEST_FUNCTION(fmpz_poly_get_str_pretty), TEST_FUNCTION(fmpz_poly_hensel_lift), TEST_FUNCTION(fmpz_poly_hensel_lift_once), TEST_FUNCTION(fmpz_poly_hensel_lift_without_only_inverse), TEST_FUNCTION(fmpz_poly_hensel_start_continue_lift), TEST_FUNCTION(fmpz_poly_hermite_h), TEST_FUNCTION(fmpz_poly_hermite_he), TEST_FUNCTION(fmpz_poly_inflate), TEST_FUNCTION(fmpz_poly_init_realloc_clear), TEST_FUNCTION(fmpz_poly_interpolate_fmpz_vec), TEST_FUNCTION(fmpz_poly_inv_series_basecase), TEST_FUNCTION(fmpz_poly_inv_series), TEST_FUNCTION(fmpz_poly_inv_series_newton), TEST_FUNCTION(fmpz_poly_is_cyclotomic), TEST_FUNCTION(fmpz_poly_is_squarefree), TEST_FUNCTION(fmpz_poly_lcm), TEST_FUNCTION(fmpz_poly_legendre_pt), TEST_FUNCTION(fmpz_poly_mul), TEST_FUNCTION(fmpz_poly_mul_classical), TEST_FUNCTION(fmpz_poly_mulhigh_classical), TEST_FUNCTION(fmpz_poly_mulhigh_karatsuba_n), TEST_FUNCTION(fmpz_poly_mulhigh_n), TEST_FUNCTION(fmpz_poly_mul_karatsuba), TEST_FUNCTION(fmpz_poly_mul_KS), TEST_FUNCTION(fmpz_poly_mullow), TEST_FUNCTION(fmpz_poly_mullow_classical), TEST_FUNCTION(fmpz_poly_mullow_karatsuba_n), TEST_FUNCTION(fmpz_poly_mullow_KS), TEST_FUNCTION(fmpz_poly_mullow_SS), TEST_FUNCTION(fmpz_poly_mullow_SS_precache), TEST_FUNCTION(fmpz_poly_mulmid_classical), TEST_FUNCTION(fmpz_poly_mul_SS), TEST_FUNCTION(fmpz_poly_mul_SS_precache), TEST_FUNCTION(fmpz_poly_neg), TEST_FUNCTION(fmpz_poly_newton_to_monomial), TEST_FUNCTION(fmpz_poly_nth_derivative), TEST_FUNCTION(fmpz_poly_num_real_roots), TEST_FUNCTION(fmpz_poly_num_real_roots_sturm), TEST_FUNCTION(fmpz_poly_pow_addchains), TEST_FUNCTION(fmpz_poly_pow_binexp), TEST_FUNCTION(fmpz_poly_pow_binomial), TEST_FUNCTION(fmpz_poly_pow), TEST_FUNCTION(fmpz_poly_power_sums), TEST_FUNCTION(fmpz_poly_pow_multinomial), TEST_FUNCTION(fmpz_poly_pow_trunc), TEST_FUNCTION(fmpz_poly_primitive_part), TEST_FUNCTION(fmpz_poly_print_read), TEST_FUNCTION(fmpz_poly_print_read_pretty), TEST_FUNCTION(fmpz_poly_product_roots_fmpq_vec), TEST_FUNCTION(fmpz_poly_product_roots_fmpz_vec), TEST_FUNCTION(fmpz_poly_pseudo_div), TEST_FUNCTION(fmpz_poly_pseudo_divrem_basecase), TEST_FUNCTION(fmpz_poly_pseudo_divrem_cohen), TEST_FUNCTION(fmpz_poly_pseudo_divrem_divconquer), TEST_FUNCTION(fmpz_poly_pseudo_rem), TEST_FUNCTION(fmpz_poly_pseudo_rem_cohen), TEST_FUNCTION(fmpz_poly_randtest_no_real_root), TEST_FUNCTION(fmpz_poly_rem_basecase), TEST_FUNCTION(fmpz_poly_remove), TEST_FUNCTION(fmpz_poly_remove_content_2exp), TEST_FUNCTION(fmpz_poly_rem_powers_precomp), TEST_FUNCTION(fmpz_poly_resultant), TEST_FUNCTION(fmpz_poly_resultant_euclidean), TEST_FUNCTION(fmpz_poly_resultant_modular), TEST_FUNCTION(fmpz_poly_resultant_modular_div), TEST_FUNCTION(fmpz_poly_reverse), TEST_FUNCTION(fmpz_poly_revert_series), TEST_FUNCTION(fmpz_poly_scalar_abs), TEST_FUNCTION(fmpz_poly_scalar_addmul_fmpz), TEST_FUNCTION(fmpz_poly_scalar_addmul_si), TEST_FUNCTION(fmpz_poly_scalar_addmul_ui), TEST_FUNCTION(fmpz_poly_scalar_mul_fmpz), TEST_FUNCTION(fmpz_poly_scalar_mul_si), TEST_FUNCTION(fmpz_poly_scalar_mul_ui), TEST_FUNCTION(fmpz_poly_scalar_submul_fmpz), TEST_FUNCTION(fmpz_poly_scale_2exp), TEST_FUNCTION(fmpz_poly_set_equal), TEST_FUNCTION(fmpz_poly_set_fmpz_equal), TEST_FUNCTION(fmpz_poly_set_si_equal), TEST_FUNCTION(fmpz_poly_set_trunc), TEST_FUNCTION(fmpz_poly_set_ui_equal), TEST_FUNCTION(fmpz_poly_shift_left_right), TEST_FUNCTION(fmpz_poly_signature), TEST_FUNCTION(fmpz_poly_sqr), TEST_FUNCTION(fmpz_poly_sqr_classical), TEST_FUNCTION(fmpz_poly_sqr_karatsuba), TEST_FUNCTION(fmpz_poly_sqr_KS), TEST_FUNCTION(fmpz_poly_sqrlow), TEST_FUNCTION(fmpz_poly_sqrlow_classical), TEST_FUNCTION(fmpz_poly_sqrlow_karatsuba_n), TEST_FUNCTION(fmpz_poly_sqrlow_KS), TEST_FUNCTION(fmpz_poly_sqrt), TEST_FUNCTION(fmpz_poly_sqrt_classical), TEST_FUNCTION(fmpz_poly_sqrt_divconquer), TEST_FUNCTION(fmpz_poly_sqrt_KS), TEST_FUNCTION(fmpz_poly_sqrtrem_classical), TEST_FUNCTION(fmpz_poly_sqrtrem_divconquer), TEST_FUNCTION(fmpz_poly_sqrt_series), TEST_FUNCTION(fmpz_poly_sub), TEST_FUNCTION(fmpz_poly_sub_series), TEST_FUNCTION(fmpz_poly_swap), TEST_FUNCTION(fmpz_poly_swinnerton_dyer), TEST_FUNCTION(fmpz_poly_taylor_shift), TEST_FUNCTION(fmpz_poly_taylor_shift_divconquer), TEST_FUNCTION(fmpz_poly_taylor_shift_horner), TEST_FUNCTION(fmpz_poly_taylor_shift_multi_mod_threaded), TEST_FUNCTION(fmpz_poly_theta_qexp), TEST_FUNCTION(fmpz_poly_xgcd_modular), TEST_FUNCTION(fmpz_poly_zero), TEST_FUNCTION(fmpz_poly_zero_coeffs) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_poly/test/t-2norm_normalised_bits.c000066400000000000000000000032411461254215100233200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_2norm_normalised_bits, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; fmpz_poly_t f; flint_bitcnt_t b1, b2; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_poly_init(f); do { fmpz_poly_randtest(f, state, n_randint(state, 100) + 1, 200); } while (f->length == 0); fmpz_poly_2norm(a, f); fmpz_abs(b, fmpz_poly_lead(f)); fmpz_fdiv_q(c, a, b); b1 = fmpz_bits(c); b2 = _fmpz_poly_2norm_normalised_bits(f->coeffs, f->length); result = (b1 == b2 || b1 + 1 == b2); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fmpz_print(c), flint_printf("\n\n"); flint_printf("b1 = %wd, b2 = %wd\n", b1, b2); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-CLD_bound.c000066400000000000000000000106651461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2010, 2016 William Hart Copyright (C) 2010, Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_CLD_bound, state) { int i, result = 1; /* test that CLD_bound is between the absolute value of the n-th coeff of f' and the sum of the absolute values of the coeffs of f' */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, g; fmpz_t sum, bound; slong xpow, j; slong bits = n_randint(state, 200) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(g); fmpz_init(sum); fmpz_init(bound); do { fmpz_poly_randtest(a, state, n_randint(state, 200), bits); if (!fmpz_poly_is_zero(a)) { xpow = 0; while (fmpz_is_zero(a->coeffs + xpow)) xpow++; fmpz_poly_shift_right(a, a, xpow); } fmpz_poly_derivative(b, a); fmpz_poly_gcd(g, a, b); } while (!fmpz_poly_is_one(g)); fmpz_poly_scalar_abs(b, b); for (j = 0; j < b->length && result; j++) { fmpz_poly_CLD_bound(bound, a, j); result &= (fmpz_cmp(b->coeffs + j, bound) <= 0); fmpz_add(sum, b->coeffs + j, b->coeffs + j); } result &= (fmpz_cmp(bound, sum) <= 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("length = %wd, bits = %wd, j = %wd\n", a->length, bits, j - 1); fmpz_print(b->coeffs + j - 1), flint_printf("\n\n"); fmpz_print(bound), flint_printf("\n\n"); fmpz_print(sum), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(g); fmpz_clear(sum); fmpz_clear(bound); } /* let f have a factor g (by setting f = g*h) then check that the bounds for f*g'/g are valid */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d, g; fmpz_t bound; slong xpow, j; slong bits = n_randint(state, 200) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_init(g); fmpz_init(bound); do { do { fmpz_poly_randtest(a, state, n_randint(state, 100) + 2, bits); if (!fmpz_poly_is_zero(a)) { xpow = 0; while (fmpz_is_zero(a->coeffs + xpow)) xpow++; fmpz_poly_shift_right(a, a, xpow); } } while (a->length < 2); do { fmpz_poly_randtest(b, state, n_randint(state, 100) + 1, bits); if (!fmpz_poly_is_zero(b)) { xpow = 0; while (fmpz_is_zero(b->coeffs + xpow)) xpow++; fmpz_poly_shift_right(b, b, xpow); } } while (fmpz_poly_is_zero(b)); fmpz_poly_mul(c, a, b); fmpz_poly_derivative(d, c); fmpz_poly_gcd(g, c, d); } while (!fmpz_poly_is_one(g)); fmpz_poly_derivative(g, a); fmpz_poly_mul(b, b, g); for (j = 0; j < b->length && result; j++) { fmpz_poly_CLD_bound(bound, c, j); result &= (fmpz_cmp(b->coeffs + j, bound) <= 0); } if (!result) { flint_printf("FAIL:\n"); flint_printf("length = %wd, bits = %wd, j = %wd\n", a->length, bits, j - 1); fmpz_print(b->coeffs + j - 1), flint_printf("\n\n"); fmpz_print(bound), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); fmpz_poly_clear(g); fmpz_clear(bound); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-CRT_ui.c000066400000000000000000000050651461254215100201600ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_CRT_ui, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong bits, prime_bits, length, num_primes, j; fmpz_t mod; fmpz_poly_t A, B, C; nmod_poly_t Amod; mp_limb_t primes[1000]; bits = n_randint(state, 500) + 1; length = n_randint(state, 30) + 1; prime_bits = 1 + n_randint(state, FLINT_BITS - 1); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_init(C); fmpz_poly_randtest(A, state, length, bits); fmpz_init(mod); num_primes = 0; primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); fmpz_set_ui(mod, primes[0]); /* + 1 for sign */ while (fmpz_bits(mod) <= bits + 1) { primes[num_primes + 1] = n_nextprime(primes[num_primes], 0); fmpz_mul_ui(mod, mod, primes[num_primes + 1]); num_primes++; } num_primes++; nmod_poly_init(Amod, primes[0]); fmpz_poly_get_nmod_poly(Amod, A); fmpz_poly_set_nmod_poly(B, Amod); fmpz_set_ui(mod, primes[0]); for (j = 1; j < num_primes; j++) { nmod_poly_clear(Amod); nmod_poly_init(Amod, primes[j]); fmpz_poly_get_nmod_poly(Amod, A); fmpz_poly_CRT_ui(B, B, mod, Amod, 1); fmpz_mul_ui(mod, mod, primes[j]); } if (!fmpz_poly_equal(B, A)) { flint_printf("FAIL!\n"); flint_printf("primes: "); for (j = 0; j < num_primes; j++) flint_printf("%wu ", primes[j]); flint_printf("\nA: \n"); fmpz_poly_print(A); flint_printf("\nB: \n"); fmpz_poly_print(B); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(Amod); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(C); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-CRT_ui_unsigned.c000066400000000000000000000050611461254215100220500ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" TEST_FUNCTION_START(fmpz_poly_CRT_ui_unsigned, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong bits, prime_bits, length, num_primes, j; fmpz_t mod; fmpz_poly_t A, B, C; nmod_poly_t Amod; mp_limb_t primes[1000]; bits = n_randint(state, 500) + 1; length = n_randint(state, 30) + 1; prime_bits = 1 + n_randint(state, FLINT_BITS - 1); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_init(C); fmpz_poly_randtest_unsigned(A, state, length, bits); fmpz_init(mod); num_primes = 0; primes[0] = n_nextprime(UWORD(1) << prime_bits, 0); fmpz_set_ui(mod, primes[0]); while (fmpz_bits(mod) <= bits) { primes[num_primes + 1] = n_nextprime(primes[num_primes], 0); fmpz_mul_ui(mod, mod, primes[num_primes + 1]); num_primes++; } num_primes++; nmod_poly_init(Amod, primes[0]); fmpz_poly_get_nmod_poly(Amod, A); fmpz_poly_set_nmod_poly_unsigned(B, Amod); fmpz_set_ui(mod, primes[0]); for (j = 1; j < num_primes; j++) { nmod_poly_clear(Amod); nmod_poly_init(Amod, primes[j]); fmpz_poly_get_nmod_poly(Amod, A); fmpz_poly_CRT_ui(B, B, mod, Amod, 0); fmpz_mul_ui(mod, mod, primes[j]); } if (!fmpz_poly_equal(B, A)) { flint_printf("FAIL!\n"); flint_printf("primes: "); for (j = 0; j < num_primes; j++) flint_printf("%wu ", primes[j]); flint_printf("\nA: \n"); fmpz_poly_print(A); flint_printf("\nB: \n"); fmpz_poly_print(B); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(Amod); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(C); fmpz_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-add.c000066400000000000000000000043541461254215100175630ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_add, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_add(c, a, b); fmpz_poly_add(a, a, b); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_add(c, a, b); fmpz_poly_add(b, a, b); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-add_series.c000066400000000000000000000067211461254215100211350ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_add_series, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); fmpz_poly_add_series(c, a, b, n); fmpz_poly_add_series(a, a, b, n); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); fmpz_poly_add_series(c, a, b, n); fmpz_poly_add_series(b, a, b, n); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check truncate(a + b, n) = add_series(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); fmpz_poly_add(c, a, b); fmpz_poly_truncate(c, n); fmpz_poly_add_series(d, a, b, n); result = (fmpz_poly_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-add_sub_fmpz.c000066400000000000000000000045371461254215100214730ustar00rootroot00000000000000/* Copyright (C) 2020 Vincent Delecroix Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_add_sub_fmpz, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, s, t; fmpz_t c; int op, alias; fmpz_poly_init(a); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_init(c); fmpz_poly_randtest(a, state, 1 + n_randint(state, 4), 1 + n_randint(state, 200)); fmpz_poly_randtest(s, state, 4, 200); fmpz_poly_randtest(t, state, 4, 200); fmpz_randtest(c, state, 1 + n_randint(state, 200)); op = n_randint(state, 3); alias = n_randint(state, 3); fmpz_poly_set_fmpz(s, c); if (op == 0) fmpz_poly_add(s, a, s); else if (op == 1) fmpz_poly_sub(s, a, s); else fmpz_poly_sub(s, s, a); if (alias) { if (op == 0) fmpz_poly_add_fmpz(t, a, c); else if (op == 1) fmpz_poly_sub_fmpz(t, a, c); else fmpz_poly_fmpz_sub(t, c, a); } else { fmpz_poly_set(t, a); if (op == 0) fmpz_poly_add_fmpz(t, t, c); else if (op == 1) fmpz_poly_sub_fmpz(t, t, c); else fmpz_poly_fmpz_sub(t, c, t); } if (!fmpz_poly_equal(s, t)) { printf("FAIL (op = %d, alias = %d):\n", op, alias); printf("a = "); fmpz_poly_print(a); printf("\n"); printf("s = "); fmpz_poly_print(s); printf("\n"); printf("t = "); fmpz_poly_print(t); printf("\n"); printf("c = "); fmpz_print(c); printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(s); fmpz_poly_clear(t); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-add_sub_si.c000066400000000000000000000043751461254215100211320ustar00rootroot00000000000000/* Copyright (C) 2020 Vincent Delecroix Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_add_sub_si, state) { int i; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_poly_t a, s, t; slong c; int op, alias; fmpz_poly_init(a); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_poly_randtest(a, state, 1 + n_randint(state, 4), 1 + n_randint(state, 200)); fmpz_poly_randtest(s, state, 4, 200); fmpz_poly_randtest(t, state, 4, 200); c = n_randtest(state); op = n_randint(state, 3); alias = n_randint(state, 3); fmpz_poly_set_si(s, c); if (op == 0) fmpz_poly_add(s, a, s); else if (op == 1) fmpz_poly_sub(s, a, s); else fmpz_poly_sub(s, s, a); if (alias) { if (op == 0) fmpz_poly_add_si(t, a, c); else if (op == 1) fmpz_poly_sub_si(t, a, c); else fmpz_poly_si_sub(t, c, a); } else { fmpz_poly_set(t, a); if (op == 0) fmpz_poly_add_si(t, t, c); else if (op == 1) fmpz_poly_sub_si(t, t, c); else fmpz_poly_si_sub(t, c, t); } if (!fmpz_poly_equal(s, t)) { printf("FAIL (op = %d, alias = %d):\n", op, alias); printf("a = "); fmpz_poly_print(a); printf("\n"); printf("s = "); fmpz_poly_print(s); printf("\n"); printf("t = "); fmpz_poly_print(t); printf("\n"); printf("c = "); flint_printf("%wd", c); printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(s); fmpz_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-bit_pack.c000066400000000000000000000121061461254215100206010ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_bit_pack, state) { int i, result; for (i = 0; i < 2000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong length = n_randint(state, 100) + 1; flint_bitcnt_t bits = n_randint(state, 300) + 2; mp_ptr arr = (mp_ptr) flint_calloc((length * bits - 1) / FLINT_BITS + 1, sizeof(mp_limb_t)); int negate; fmpz_poly_init(a); fmpz_poly_init(b); /* -1 bit to handle signs */ fmpz_poly_randtest_not_zero(a, state, length, bits - 1); negate = fmpz_sgn(a->coeffs + a->length - 1); if (negate > 0) negate = 0; _fmpz_poly_bit_pack(arr, a->coeffs, a->length, bits, negate); fmpz_poly_fit_length(b, a->length); _fmpz_poly_bit_unpack(b->coeffs, a->length, arr, bits, negate); _fmpz_poly_set_length(b, a->length); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } flint_free(arr); fmpz_poly_clear(a); fmpz_poly_clear(b); } for (i = 0; i < 2000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong length = n_randint(state, 100) + 1; flint_bitcnt_t bits = n_randint(state, 300) + 1; mp_ptr arr = (mp_ptr) flint_calloc((length * bits - 1) / FLINT_BITS + 1, sizeof(mp_limb_t)); fmpz_poly_init(a); fmpz_poly_init(b); do fmpz_poly_randtest_unsigned(a, state, length, bits); while (a->length == 0); _fmpz_poly_bit_pack(arr, a->coeffs, a->length, bits, 0); fmpz_poly_fit_length(b, a->length); _fmpz_poly_bit_unpack_unsigned(b->coeffs, a->length, arr, bits); _fmpz_poly_set_length(b, a->length); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } flint_free(arr); fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Test fmpz functions */ for (i = 0; i < 2000 * flint_test_multiplier(); i++) { fmpz_t f; fmpz_poly_t A, B; slong b; fmpz_init(f); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_randtest(A, state, 1+n_randint(state,100), 1+n_randint(state,300)); b = FLINT_ABS(fmpz_poly_max_bits(A)) + 1; fmpz_poly_bit_pack(f, A, b); fmpz_poly_bit_unpack(B, f, b); if (!fmpz_poly_equal(A, B)) { mpz_t zz; flint_printf("FAIL:\n"); flint_printf("BITS: %wd (signed)\n", b); flint_printf("INPUT: "); fmpz_poly_print_pretty(A, "x"); flint_printf("\n"); mpz_init(zz); fmpz_get_mpz(zz, f); flint_printf("PACKED: "); mpz_out_str(stdout, 2, zz); flint_printf("\n"); flint_printf("OUTPUT: "); fmpz_poly_print_pretty(B, "x"); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(f); fmpz_poly_clear(A); fmpz_poly_clear(B); } for (i = 0; i < 2000 * flint_test_multiplier(); i++) { fmpz_t f; fmpz_poly_t A, B; slong b; fmpz_init(f); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_randtest_unsigned(A, state, 1+n_randint(state,100), 1+n_randint(state,300)); b = FLINT_ABS(fmpz_poly_max_bits(A)); fmpz_poly_bit_pack(f, A, b); fmpz_poly_bit_unpack_unsigned(B, f, b); if (!fmpz_poly_equal(A, B)) { mpz_t zz; flint_printf("FAIL:\n"); flint_printf("BITS: %wd (unsigned)\n", b); flint_printf("INPUT: "); fmpz_poly_print_pretty(A, "x"); flint_printf("\n"); mpz_init(zz); fmpz_get_mpz(zz, f); flint_printf("PACKED: "); mpz_out_str(stdout, 2, zz); flint_printf("\n"); flint_printf("OUTPUT: "); fmpz_poly_print_pretty(B, "x"); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(f); fmpz_poly_clear(A); fmpz_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-bound_roots.c000066400000000000000000000044541461254215100213710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_bound_roots, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { fmpz_poly_t f, g; fmpz_t t, p, q, bound, nbound; slong i, num_roots; fmpz_init(t); fmpz_init(p); fmpz_init(q); fmpz_init(bound); fmpz_init(nbound); fmpz_poly_init(f); fmpz_poly_init(g); /* start with a constant */ fmpz_poly_randtest(f, state, 1, 1 + n_randint(state, 200)); fmpz_zero(bound); num_roots = n_randint(state, 10); if (fmpz_poly_is_zero(f)) num_roots = 0; for (i = 0; i < num_roots; i++) { fmpz_randtest(p, state, 1 + n_randint(state, 200)); fmpz_randtest_not_zero(q, state, 1 + n_randint(state, 200)); fmpz_abs(p, p); fmpz_abs(q, q); fmpz_cdiv_q(t, p, q); if (fmpz_cmp(t, bound) > 0) fmpz_set(bound, t); if (n_randint(state, 2)) fmpz_neg(p, p); fmpz_poly_set_coeff_fmpz(g, 0, p); fmpz_poly_set_coeff_fmpz(g, 1, q); fmpz_poly_mul(f, f, g); } fmpz_poly_bound_roots(nbound, f); if (fmpz_cmp(nbound, bound) < 0) { flint_printf("FAIL\n"); flint_printf("f = "); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("bound = "); fmpz_print(bound); flint_printf("\n\n"); flint_printf("computed bound = "); fmpz_print(nbound); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(t); fmpz_clear(p); fmpz_clear(q); fmpz_clear(bound); fmpz_clear(nbound); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-chebyshev_t.c000066400000000000000000000027071461254215100213360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_chebyshev_t, state) { fmpz_poly_t T0, T1, T2, t; slong n; fmpz_poly_init(T0); fmpz_poly_init(T1); fmpz_poly_init(T2); fmpz_poly_init(t); fmpz_poly_chebyshev_t(T0, 0); fmpz_poly_chebyshev_t(T1, 1); for (n = 2; n <= 500; n++) { fmpz_poly_chebyshev_t(T2, n); /* Verify T_{n+1} = 2 x T_n - T_{n-1} */ fmpz_poly_scalar_mul_ui(t, T1, UWORD(2)); fmpz_poly_shift_left(t, t, 1); fmpz_poly_sub(t, t, T0); if (!fmpz_poly_equal(t, T2)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("t: "); fmpz_poly_print_pretty(t, "x"); flint_printf("\n"); flint_printf("T2: "); fmpz_poly_print_pretty(T2, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_swap(T0, T1); fmpz_poly_swap(T1, T2); } fmpz_poly_clear(T0); fmpz_poly_clear(T1); fmpz_poly_clear(T2); fmpz_poly_clear(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-chebyshev_u.c000066400000000000000000000022461461254215100213350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_chebyshev_u, state) { fmpz_poly_t T, U; slong n; fmpz_poly_init(T); fmpz_poly_init(U); for (n = 0; n <= 500; n++) { fmpz_poly_chebyshev_u(U, n); fmpz_poly_chebyshev_t(T, n + 1); fmpz_poly_derivative(T, T); fmpz_poly_scalar_divexact_ui(T, T, n + 1); if (!fmpz_poly_equal(T, U)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("T: "); fmpz_poly_print_pretty(T, "x"); flint_printf("\n"); flint_printf("U: "); fmpz_poly_print_pretty(U, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(T); fmpz_poly_clear(U); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-compose.c000066400000000000000000000142531461254215100204770ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2016 Shivin Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_compose, state) { int i, result; /* Bill's bug */ { fmpz_poly_t f, g, h, s, t; slong k; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_poly_set_str(g, "21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6"); fmpz_poly_set_str(h, "8 -2411740686 -274861162464 -4294966273 -35167058005888 4261511676 -1 8589869056 -70334401183747"); fmpz_poly_set_ui(t, 1); for (k = 0; k < g->length; k++) { fmpz_poly_scalar_addmul_fmpz(s, t, g->coeffs + k); fmpz_poly_mul(t, t, h); } fmpz_poly_compose(f, g, h); result = (fmpz_poly_equal(f, s)); if (!result) { flint_printf("FAIL (Bill's bug):\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpz_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose(f, g, h); fmpz_poly_compose(g, g, h); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose(f, g, h); fmpz_poly_compose(h, g, h); result = (fmpz_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Compare with the naive method for g(h(t)) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h, s, t; slong k; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_ui(t, 1); for (k = 0; k < g->length; k++) { fmpz_poly_scalar_addmul_fmpz(s, t, g->coeffs + k); fmpz_poly_mul(t, t, h); } fmpz_poly_compose(f, g, h); result = (fmpz_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpz_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } /* Testing linear composition*/ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h, s, t; fmpz_t c; slong k; fmpz_init(c); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(s); fmpz_poly_init(t); /* h is a linear polynomial*/ for (k = 0; k < 2; k++) { fmpz_randtest(c, state, 50); fmpz_poly_set_coeff_fmpz(h, k, c); } fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_set_ui(t, 1); for (k = 0; k < g->length; k++) { fmpz_poly_scalar_addmul_fmpz(s, t, g->coeffs + k); fmpz_poly_mul(t, t, h); } fmpz_poly_compose(f, g, h); result = (fmpz_poly_equal(f, s)); if (!result) { flint_printf("FAIL (linear composition):\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpz_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-compose_divconquer.c000066400000000000000000000061011461254215100227270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_compose_divconquer, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose_divconquer(f, g, h); fmpz_poly_compose_divconquer(g, g, h); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose_divconquer(f, g, h); fmpz_poly_compose_divconquer(h, g, h); result = (fmpz_poly_equal(f, h)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Compare with the default method */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f1, f2, g, h; fmpz_poly_init(f1); fmpz_poly_init(f2); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose_divconquer(f1, g, h); fmpz_poly_compose(f2, g, h); result = (fmpz_poly_equal(f1, f2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f1), flint_printf("\n\n"); fmpz_poly_print(f2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f1); fmpz_poly_clear(f2); fmpz_poly_clear(g); fmpz_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-compose_horner.c000066400000000000000000000060431461254215100220520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_compose_horner, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 8 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose_horner(f, g, h); fmpz_poly_compose_horner(g, g, h); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 8 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose_horner(f, g, h); fmpz_poly_compose_horner(h, g, h); result = (fmpz_poly_equal(f, h)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Compare with the default method */ for (i = 0; i < 8 * flint_test_multiplier(); i++) { fmpz_poly_t f1, f2, g, h; fmpz_poly_init(f1); fmpz_poly_init(f2); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_compose_horner(f1, g, h); fmpz_poly_compose(f2, g, h); result = (fmpz_poly_equal(f1, f2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f1), flint_printf("\n\n"); fmpz_poly_print(f2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f1); fmpz_poly_clear(f2); fmpz_poly_clear(g); fmpz_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-compose_series.c000066400000000000000000000073141461254215100220510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_compose_series, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpz_poly_compose_series(f, g, h, n); fmpz_poly_compose_series(g, g, h, n); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpz_poly_compose_series(f, g, h, n); fmpz_poly_compose_series(h, g, h, n); result = (fmpz_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Compare with compose */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h, s, t; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 10); fmpz_poly_compose(s, g, h); fmpz_poly_truncate(s, n); fmpz_poly_compose_series(f, g, h, n); result = (fmpz_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("n = %wd\n", n); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpz_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-compose_series_brent_kung.c000066400000000000000000000074431461254215100242720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_compose_series_brent_kung, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpz_poly_compose_series_brent_kung(f, g, h, n); fmpz_poly_compose_series_brent_kung(g, g, h, n); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpz_poly_compose_series_brent_kung(f, g, h, n); fmpz_poly_compose_series_brent_kung(h, g, h, n); result = (fmpz_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Compare with Horner */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h, s, t; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_poly_randtest(g, state, n_randint(state, 50), n_randint(state, 100)); fmpz_poly_randtest(h, state, n_randint(state, 50), n_randint(state, 100)); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 50); fmpz_poly_compose_series_brent_kung(s, g, h, n); fmpz_poly_compose_series_horner(f, g, h, n); result = (fmpz_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("n = %wd\n", n); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpz_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-compose_series_horner.c000066400000000000000000000073661461254215100234350ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_compose_series_horner, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpz_poly_compose_series_horner(f, g, h, n); fmpz_poly_compose_series_horner(g, g, h, n); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpz_poly_compose_series_horner(f, g, h, n); fmpz_poly_compose_series_horner(h, g, h, n); result = (fmpz_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } /* Compare with compose */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h, s, t; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_randtest(h, state, n_randint(state, 20), 50); fmpz_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); fmpz_poly_compose(s, g, h); fmpz_poly_truncate(s, n); fmpz_poly_compose_series_horner(f, g, h, n); result = (fmpz_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("n = %wd\n", n); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), fmpz_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-content.c000066400000000000000000000027501461254215100205030ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_content, state) { int i, result; /* Check that content(a f) = abs(a) content(f) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, c, d; fmpz_poly_t f; fmpz_init(a); fmpz_init(c); fmpz_init(d); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_randtest(a, state, 100); fmpz_poly_content(c, f); fmpz_poly_scalar_mul_fmpz(f, f, a); fmpz_abs(a, a); fmpz_mul(c, a, c); fmpz_poly_content(d, f); result = (fmpz_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(c), flint_printf("\n\n"); fmpz_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-cos_minpoly.c000066400000000000000000000064611461254215100213670ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" /* Generated with Mathematica: Table[Mod[MinimalPolynomial[2 Cos[2 Pi/n]][1337], 31337], {n,1,300}] */ static const short testdata[] = { 1, 1335, 1339, 1338, 1337, 2696, 1336, 30796, 1358, 28101, 22, 16072, 1357, 27681, 28078, 31189, 26616, 22997, 28099, 20964, 25259, 17018, 22796, 30688, 26615, 22301, 20150, 29305, 17687, 9574, 22041, 8475, 7232, 10663, 7961, 13573, 11608, 29844, 21343, 18774, 11954, 567, 3486, 29805, 11421, 18574, 29135, 11600, 7231, 20430, 10970, 11026, 8358, 23296, 29303, 29465, 7825, 18111, 6414, 7407, 17482, 24400, 23824, 15398, 369, 22359, 21281, 11824, 5620, 15124, 14927, 18872, 19778, 26463, 11425, 15476, 22320, 19336, 26824, 2803, 24475, 13995, 26790, 674, 13858, 20896, 2448, 18877, 500, 29090, 20982, 29875, 18862, 28199, 5071, 17613, 368, 11772, 14214, 22871, 23416, 4199, 13435, 30768, 28568, 14665, 10308, 5414, 27939, 12535, 553, 23997, 4593, 19403, 14479, 16270, 11719, 478, 1838, 14679, 24868, 7207, 15155, 17797, 5274, 12718, 17266, 24266, 10811, 3642, 14826, 4303, 15580, 23409, 13321, 22900, 6391, 21282, 26640, 9512, 15545, 12204, 23111, 25241, 29067, 3513, 15817, 4995, 14499, 6958, 1947, 291, 1200, 10431, 713, 25007, 4203, 19018, 23045, 20460, 10443, 7161, 13993, 15648, 16029, 1937, 17704, 14407, 26439, 11237, 3102, 27729, 2590, 26643, 30727, 7383, 26725, 10074, 10529, 12963, 14061, 15546, 9796, 10285, 24968, 11937, 16138, 7408, 8463, 21869, 18111, 24123, 10810, 3396, 14512, 1151, 20074, 1947, 26128, 29704, 8563, 5705, 19865, 6008, 14178, 512, 6704, 22538, 13703, 15666, 28703, 24657, 20780, 10454, 5940, 18964, 7590, 22848, 1181, 9240, 17694, 1587, 13900, 12588, 29985, 19185, 24610, 8093, 23116, 8123, 17443, 18050, 27235, 30794, 20569, 31185, 25668, 165, 3984, 26063, 1309, 24253, 8622, 16958, 28598, 27709, 14446, 27388, 27031, 7724, 16401, 29876, 8203, 26109, 19861, 17381, 22046, 3554, 8667, 12029, 30411, 21643, 18480, 29179, 3346, 14467, 20617, 4657, 23663, 25078, 23617, 20420, 4932, 8553, 24377, 30730, 19167, 10860, 26527, 570, 12845, 6218, 13958, 17211, 19509, 446, 29828, 26270, 9090, 7617, 8895, 25810, 6364, 21910, 26031, 3113, 21469, 30799, 9950, 8422, 17632, -1 }; TEST_FUNCTION_START(fmpz_poly_cos_minpoly, state) { fmpz_poly_t p; slong n; fmpz_poly_init(p); for (n = 0; testdata[n] != -1; n++) { mp_limb_t y; fmpz_poly_randtest(p, state, 20, 1 + n_randint(state, 100)); fmpz_poly_cos_minpoly(p, n); y = fmpz_poly_evaluate_mod(p, 1337, 31337); if (y != testdata[n]) { flint_printf("FAIL\nn = %wd\n", n); flint_printf("y = %wu\n", y); flint_printf("p = "); fmpz_poly_print(p); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(p); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-cyclotomic.c000066400000000000000000000061451461254215100212000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" void cyclotomic_naive(fmpz_poly_t poly, ulong n) { fmpz_poly_t t; slong d; fmpz_poly_init(t); fmpz_poly_set_ui(poly, UWORD(1)); for (d = 1; d <= n; d++) { if (n % d == 0) { if (n_moebius_mu(n / d) == 1) { fmpz_poly_zero(t); fmpz_poly_set_coeff_si(t, d, 1); fmpz_poly_set_coeff_si(t, 0, -1); fmpz_poly_mul(poly, poly, t); } } } for (d = 1; d <= n; d++) { if (n % d == 0) { if (n_moebius_mu(n / d) == -1) { fmpz_poly_zero(t); fmpz_poly_set_coeff_si(t, d, 1); fmpz_poly_set_coeff_si(t, 0, -1); fmpz_poly_div(poly, poly, t); } } } fmpz_poly_clear(t); } TEST_FUNCTION_START(fmpz_poly_cyclotomic, state) { fmpz_poly_t A, B; slong n; for (n = 0; n <= 1000; n++) { fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_cyclotomic(A, n); cyclotomic_naive(B, n); if (!fmpz_poly_equal(A, B)) { flint_printf("FAIL: wrong value of Phi_%wd(x)\n", n); flint_printf("Computed:\n"); fmpz_poly_print_pretty(A, "x"); flint_printf("\n\nExpected:\n"); fmpz_poly_print_pretty(B, "x"); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(A); fmpz_poly_clear(B); } /* We verify the first value that does not fit on 32 bits. This exercises the slow path at least on a 32 bit system. Testing the 64 bit value is a bit too much to do by default as it requires ~2 GB of memory and takes a few minutes. */ { fmpz_t h, ref; const ulong nn = UWORD(10163195); /* const ulong nn = UWORD(169828113); 64-bit case */ fmpz_init(h); fmpz_init(ref); fmpz_set_str(ref, "1376877780831", 10); /* fmpz_set_str(ref, "31484567640915734941", 10); 64-bit case */ fmpz_poly_init(A); fmpz_poly_cyclotomic(A, UWORD(10163195)); fmpz_poly_height(h, A); if (!fmpz_equal(h, ref)) { flint_printf("Bad computation of Phi_%wd(x)\n", nn); flint_printf("Computed height:\n"); fmpz_print(h); flint_printf("\nExpected height:\n"); fmpz_print(ref); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(A); fmpz_clear(h); fmpz_clear(ref); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-deflate.c000066400000000000000000000064111461254215100204330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_deflate, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t poly1, poly2, poly3; ulong infl1, infl, deflation; fmpz_poly_init(poly1); fmpz_poly_init(poly2); fmpz_poly_init(poly3); fmpz_poly_randtest(poly1, state, n_randint(state, 20), n_randint(state, 200)); if (fmpz_poly_length(poly1) <= 1) { if (fmpz_poly_deflation(poly1) != fmpz_poly_length(poly1)) { flint_printf("FAIL: wrong deflation for constant polynomial\n"); fflush(stdout); flint_abort(); } fmpz_poly_deflate(poly2, poly1, n_randint(state, 5) + 1); if (!fmpz_poly_equal(poly2, poly1)) { flint_printf("FAIL: constant polynomial changed on deflation\n"); fflush(stdout); flint_abort(); } } else { infl = n_randint(state, 15) + 1; infl1 = fmpz_poly_deflation(poly1); fmpz_poly_inflate(poly2, poly1, infl); deflation = fmpz_poly_deflation(poly2); if (deflation != infl * infl1) { flint_printf("FAIL: deflation = %wu, inflation: %wu, %wu\n", deflation, infl, infl1); flint_printf("poly1:\n"); fmpz_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); fmpz_poly_print(poly2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_deflate(poly3, poly2, infl); if (!fmpz_poly_equal(poly3, poly1)) { flint_printf("FAIL: deflation = %wu, inflation: %wu, %wu\n", deflation, infl, infl1); flint_printf("Deflated polynomial not equal to input:\n"); flint_printf("poly1:\n"); fmpz_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); fmpz_poly_print(poly2); flint_printf("\n\n"); flint_printf("poly3:\n"); fmpz_poly_print(poly3); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_deflate(poly2, poly2, infl); if (!fmpz_poly_equal(poly3, poly2)) { flint_printf("FAIL: aliasing\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(poly1); fmpz_poly_clear(poly2); fmpz_poly_clear(poly3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-derivative.c000066400000000000000000000057711461254215100212010ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_derivative, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_derivative(b, a); fmpz_poly_derivative(a, a); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check constants have derivative zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 2), 200); fmpz_poly_derivative(b, a); result = (b->length == UWORD(0)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check (f g)' = f' g + f g' */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d, lhs, rhs; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_init(lhs); fmpz_poly_init(rhs); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_mul(lhs, a, b); fmpz_poly_derivative(lhs, lhs); fmpz_poly_derivative(c, a); fmpz_poly_derivative(d, b); fmpz_poly_mul(c, c, b); fmpz_poly_mul(d, a, d); fmpz_poly_add(rhs, c, d); result = fmpz_poly_equal(lhs, rhs); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); fmpz_poly_clear(lhs); fmpz_poly_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-discriminant.c000066400000000000000000000056341461254215100215210ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_discriminant, state) { int i, result; /* Check that disc(fg) = disc(f) * disc(g) * R(f, g)^2 */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d, r; fmpz_poly_t f, g, p; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_init(r); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(p); do { fmpz_poly_randtest(f, state, n_randint(state, 30), 100); } while (f->length < 2); do { fmpz_poly_randtest(g, state, n_randint(state, 30), 100); } while (g->length < 2); fmpz_poly_discriminant(a, f); fmpz_poly_discriminant(b, g); fmpz_mul(c, a, b); fmpz_poly_mul(p, f, g); fmpz_poly_discriminant(d, p); fmpz_poly_resultant(r, f, g); fmpz_mul(r, r, r); fmpz_mul(c, c, r); result = (fmpz_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("disc(f) = "), fmpz_print(a), flint_printf("\n\n"); flint_printf("disc(g) = "), fmpz_print(b), flint_printf("\n\n"); flint_printf("disc(fg) = "), fmpz_print(d), flint_printf("\n\n"); flint_printf("disc(f)*disc(g)*res(f,g) = "), fmpz_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(r); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(p); } /* Check that disc(f) = 0 for degree < 1 */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t a; fmpz_poly_t f; fmpz_init(a); fmpz_poly_init(f); fmpz_poly_randtest(f, state, 1, 100); fmpz_poly_discriminant(a, f); result = (fmpz_is_zero(a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("disc(f) = "), fmpz_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-div_basecase.c000066400000000000000000000064341461254215100214440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_div_basecase, state) { int i, result; /* Compare with full division, no aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, q2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(q2); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, a->length + 1) + 1, 100); fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_div_basecase(q2, a, b); result = (fmpz_poly_equal(q, q2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fmpz_poly_print(q2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(q2); } /* Check q and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_poly_div_basecase(q, a, b); fmpz_poly_div_basecase(a, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check q and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_poly_div_basecase(q, a, b); fmpz_poly_div_basecase(b, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-div_divconquer.c000066400000000000000000000064571461254215100220620ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_div_divconquer, state) { int i, result; /* Compare with full division, no aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, q2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(q2); fmpz_poly_randtest(a, state, n_randint(state, 200), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, a->length + 1) + 1, 100); fmpz_poly_divrem_divconquer(q, r, a, b); fmpz_poly_div_divconquer(q2, a, b); result = (fmpz_poly_equal(q, q2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fmpz_poly_print(q2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(q2); } /* Check q and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_div_divconquer(q, a, b); fmpz_poly_div_divconquer(a, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check q and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_div_divconquer(q, a, b); fmpz_poly_div_divconquer(b, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-div_preinv.c000066400000000000000000000075211461254215100211770ustar00rootroot00000000000000/* Copyright (C) 2009, 2013 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_div_preinv, state) { int i, result; /* Compare with full division, no aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q, r, q2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(q2); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, a->length + 1) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_div_preinv(q2, a, b, b_inv); result = (fmpz_poly_equal(q, q2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fmpz_poly_print(q2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(q2); } /* Check q and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_div_basecase(q, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_div_preinv(a, a, b, b_inv); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); } /* Check q and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_div_basecase(q, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_div_preinv(b, a, b, b_inv); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-div_root.c000066400000000000000000000055211461254215100206550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_div_root, state) { int i, result; /* Compare with standard divrem */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t P, Q, D, DQ; fmpz_t c; slong n, b; n = n_randint(state, 100); b = n_randint(state, 200); fmpz_init(c); fmpz_poly_init(P); fmpz_poly_init(Q); fmpz_poly_init(D); fmpz_poly_init(DQ); fmpz_poly_randtest(P, state, n, b); fmpz_randtest(c, state, b); fmpz_poly_div_root(Q, P, c); fmpz_poly_set_coeff_fmpz(D, 0, c); fmpz_poly_neg(D, D); fmpz_poly_set_coeff_ui(D, 1, UWORD(1)); fmpz_poly_div_basecase(DQ, P, D); result = fmpz_poly_equal(Q, DQ); if (!result) { flint_printf("FAIL!\n"); flint_printf("P:\n"); fmpz_poly_print(P); flint_printf("\n\n"); flint_printf("Q:\n"); fmpz_poly_print(Q); flint_printf("\n\n"); flint_printf("D:\n"); fmpz_poly_print(D); flint_printf("\n\n"); flint_printf("DQ:\n"); fmpz_poly_print(DQ); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_poly_clear(P); fmpz_poly_clear(Q); fmpz_poly_clear(D); fmpz_poly_clear(DQ); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t P, Q1, Q2; fmpz_t c; slong n, b; n = n_randint(state, 100); b = n_randint(state, 200); fmpz_init(c); fmpz_poly_init(P); fmpz_poly_init(Q1); fmpz_poly_init(Q2); fmpz_randtest(c, state, b); fmpz_poly_randtest(P, state, n, b); fmpz_poly_set(Q2, P); fmpz_poly_div_root(Q1, P, c); fmpz_poly_div_root(Q2, Q2, c); result = fmpz_poly_equal(Q1, Q2); if (!result) { flint_printf("FAIL (aliasing)!\n"); flint_printf("P:\n"); fmpz_poly_print(P); flint_printf("\n\n"); flint_printf("Q1:\n"); fmpz_poly_print(Q1); flint_printf("\n\n"); flint_printf("Q2:\n"); fmpz_poly_print(Q2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_poly_clear(P); fmpz_poly_clear(Q1); fmpz_poly_clear(Q2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-div_series.c000066400000000000000000000124701461254215100211650ustar00rootroot00000000000000/* Copyright (C) 2009, 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_div_series, state) { int i, result; /* Check aliasing q and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series(q, a, b, n); fmpz_poly_div_series(a, a, b, n); result = (fmpz_poly_equal(q, a)); if (!result) { flint_printf("FAIL (alias q and a):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check aliasing q and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series(q, a, b, n); fmpz_poly_div_series(b, a, b, n); result = (fmpz_poly_equal(q, b)); if (!result) { flint_printf("FAIL (alias q and b):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check that Q * B == A */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong n = n_randint(state, 90) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 90) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 90) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series(q, a, b, n); fmpz_poly_mullow(p, q, b, n); fmpz_poly_truncate(a, n); result = (fmpz_poly_equal(p, a)); if (!result) { flint_printf("FAIL (check Q * B = A):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("p = "), fmpz_poly_print(p), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } /* Check that (A * B)/B == A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong n = n_randint(state, 80) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 80) + 1, 2 + n_randint(state, 100)) ; fmpz_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 2 + n_randint(state, 100)); while (fmpz_is_zero(b->coeffs + 0)) fmpz_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 2 + n_randint(state, 100)); fmpz_poly_mullow(p, a, b, n); fmpz_poly_div_series(q, p, b, n); fmpz_poly_truncate(a, n); result = (fmpz_poly_equal(q, a)); if (!result) { flint_printf("FAIL (check (A * B)/B = A):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("p = "), fmpz_poly_print(p), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-div_series_basecase.c000066400000000000000000000125611461254215100230140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_div_series_basecase, state) { int i, result; /* Check aliasing q and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series_basecase(q, a, b, n); fmpz_poly_div_series_basecase(a, a, b, n); result = (fmpz_poly_equal(q, a)); if (!result) { flint_printf("FAIL (alias q and a):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check aliasing q and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series_basecase(q, a, b, n); fmpz_poly_div_series_basecase(b, a, b, n); result = (fmpz_poly_equal(q, b)); if (!result) { flint_printf("FAIL (alias q and b):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check that Q * B == A */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series_basecase(q, a, b, n); fmpz_poly_mullow(p, q, b, n); fmpz_poly_truncate(a, n); result = (fmpz_poly_equal(p, a)); if (!result) { flint_printf("FAIL (check Q * B = A):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("p = "), fmpz_poly_print(p), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } /* Check that (A * B)/B == A */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)) ; fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); while (fmpz_is_zero(b->coeffs + 0)) fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_mullow(p, a, b, n); fmpz_poly_div_series_basecase(q, p, b, n); fmpz_poly_truncate(a, n); result = (fmpz_poly_equal(q, a)); if (!result) { flint_printf("FAIL (check (A * B)/B = A):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("p = "), fmpz_poly_print(p), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-div_series_divconquer.c000066400000000000000000000126051461254215100234240ustar00rootroot00000000000000/* Copyright (C) 2009, 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_div_series_divconquer, state) { int i, result; /* Check aliasing q and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series_divconquer(q, a, b, n); fmpz_poly_div_series_divconquer(a, a, b, n); result = (fmpz_poly_equal(q, a)); if (!result) { flint_printf("FAIL (alias q and a):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check aliasing q and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series_divconquer(q, a, b, n); fmpz_poly_div_series_divconquer(b, a, b, n); result = (fmpz_poly_equal(q, b)); if (!result) { flint_printf("FAIL (alias q and b):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check that Q * B == A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_set_coeff_si(b, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_div_series_divconquer(q, a, b, n); fmpz_poly_mullow(p, q, b, n); fmpz_poly_truncate(a, n); result = (fmpz_poly_equal(p, a)); if (!result) { flint_printf("FAIL (check Q * B = A):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("p = "), fmpz_poly_print(p), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } /* Check that (A * B)/B == A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong n = n_randint(state, 50) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)) ; fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); while (fmpz_is_zero(b->coeffs + 0)) fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 2 + n_randint(state, 100)); fmpz_poly_mullow(p, a, b, n); fmpz_poly_div_series_divconquer(q, p, b, n); fmpz_poly_truncate(a, n); result = (fmpz_poly_equal(q, a)); if (!result) { flint_printf("FAIL (check (A * B)/B = A):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("p = "), fmpz_poly_print(p), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divexact.c000066400000000000000000000036241461254215100206410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_divexact, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, q; int aliasing; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(q); fmpz_poly_randtest(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); fmpz_poly_randtest_not_zero(b, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); fmpz_poly_mul(c, a, b); aliasing = n_randint(state, 3); if (aliasing == 0) { fmpz_poly_divexact(q, c, b); } else if (aliasing == 1) { fmpz_poly_set(q, c); fmpz_poly_divexact(q, q, b); } else { fmpz_poly_set(q, b); fmpz_poly_divexact(q, c, q); } result = fmpz_poly_equal(q, a); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divhigh_smodp.c000066400000000000000000000055371461254215100216630ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_divhigh_smodp, state) { int i, result; /* Check a*b/a has correct coefficients */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong j, n; ulong p; fmpz_poly_t a, b, c, d; fmpz_t t, P, d1, d2; fmpz * vec; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_init(P); fmpz_init(t); fmpz_init(d1); fmpz_init(d2); p = n_randprime(state, n_randint(state, 7) + 2, 0); fmpz_set_ui(P, p); fmpz_pow_ui(P, P, n_randint(state, 4) + 1); n = n_randint(state, 40) + 2; vec = _fmpz_vec_init(n); do { fmpz_poly_randtest(a, state, n_randint(state, 100) + 2*n, 200); if (a->length > 1) { fmpz_gcd(d1, P, a->coeffs + 0); fmpz_gcd(d2, P, a->coeffs + a->length - 1); } } while (a->length <= n || !fmpz_is_one(d1) || !fmpz_is_one(d2)); do { fmpz_poly_randtest(b, state, n_randint(state, 50), 200); if (b->length > 1) { fmpz_gcd(d1, P, b->coeffs + 0); fmpz_gcd(d2, P, b->coeffs + b->length - 1); } } while (b->length < 2 || !fmpz_is_one(d1) || !fmpz_is_one(d2)); fmpz_poly_mulhigh_n(c, a, b, n); fmpz_poly_scalar_mod_fmpz(d, b, P); fmpz_poly_divhigh_smodp(vec, c, d, P, n); result = 1; for (j = 0; j < n && result; j++) { fmpz_smod(t, a->coeffs + a->length - j - 1, P); result = fmpz_equal(t, vec + n - j - 1); } if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, j = %wd\n\n", n, j); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fmpz_print(P); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(d1); fmpz_clear(d2); fmpz_clear(t); fmpz_clear(P); _fmpz_vec_clear(vec, n); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divides.c000066400000000000000000000106361461254215100204620ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_divides, state) { int i, result; /* Check that b divides a*b and that the quotient is a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_mul(p, a, b); result = (fmpz_poly_divides(q, p, b) && fmpz_poly_equal(q, a)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } /* Check aliasing of q with a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_mul(p, a, b); result = (fmpz_poly_divides(p, p, b) && fmpz_poly_equal(p, a)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); } /* Check aliasing of q with b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_mul(p, a, b); result = (fmpz_poly_divides(b, p, b) && fmpz_poly_equal(b, a)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); } /* Check when not divisible */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q, g, s; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_init(s); fmpz_poly_init(g); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); do { fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); } while (b->length < 2); fmpz_poly_mul(p, a, b); do { fmpz_poly_randtest_not_zero(s, state, b->length, 200); fmpz_poly_gcd(g, s, b); } while (g->length == b->length); fmpz_poly_add(p, p, s); result = (!fmpz_poly_divides(q, p, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); fmpz_poly_clear(s); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divlow_smodp.c000066400000000000000000000054721461254215100215430ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_divlow_smodp, state) { int i, result; /* Check a*b/a has correct coefficients */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong j, n; ulong p; fmpz_poly_t a, b, c, d; fmpz_t t, P, d1, d2; fmpz * vec; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_init(P); fmpz_init(t); fmpz_init(d1); fmpz_init(d2); p = n_randprime(state, n_randint(state, 7) + 2, 0); fmpz_set_ui(P, p); fmpz_pow_ui(P, P, n_randint(state, 4) + 1); n = n_randint(state, 40) + 2; vec = _fmpz_vec_init(n); do { fmpz_poly_randtest(a, state, n_randint(state, 100) + n, 200); if (a->length > 1) { fmpz_gcd(d1, P, a->coeffs + 0); fmpz_gcd(d2, P, a->coeffs + a->length - 1); } } while (a->length <= n || !fmpz_is_one(d1) || !fmpz_is_one(d2)); do { fmpz_poly_randtest(b, state, n_randint(state, 50), 200); if (b->length > 1) { fmpz_gcd(d1, P, b->coeffs + 0); fmpz_gcd(d2, P, b->coeffs + b->length - 1); } } while (b->length < 2 || !fmpz_is_one(d1) || !fmpz_is_one(d2)); fmpz_poly_mul(c, a, b); fmpz_poly_scalar_mod_fmpz(d, b, P); fmpz_poly_divlow_smodp(vec, c, d, P, n); result = 1; for (j = 0; j < n && result; j++) { fmpz_smod(t, a->coeffs + j, P); result = fmpz_equal(t, vec + j); } if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, j = %wd\n\n", n, j); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fmpz_print(P); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(d1); fmpz_clear(d2); fmpz_clear(t); fmpz_clear(P); _fmpz_vec_clear(vec, n); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divrem.c000066400000000000000000000123421461254215100203150ustar00rootroot00000000000000/* Copyright (C) 2009, 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_divrem, state) { int i, result; slong tmul = 100; /* Check q*b + r = a, no aliasing */ for (i = 0; i < 2 * tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, prod; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem(q, r, a, b); fmpz_poly_mul(prod, q, b); fmpz_poly_add(prod, prod, r); result = (fmpz_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(prod), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check r and a alias */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem(q, r, a, b); fmpz_poly_divrem(q, a, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem(q, r, a, b); fmpz_poly_divrem(q, b, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and a alias */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem(q, r, a, b); fmpz_poly_divrem(a, r, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and b alias */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem(q, r, a, b); fmpz_poly_divrem(b, r, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divrem_basecase.c000066400000000000000000000124271461254215100221470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_divrem_basecase, state) { int i, result; /* Check q*b + r = a, no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, prod; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_mul(prod, q, b); fmpz_poly_add(prod, prod, r); result = (fmpz_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(prod), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check r and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_divrem_basecase(q, a, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_divrem_basecase(q, b, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_divrem_basecase(a, r, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_divrem_basecase(b, r, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divrem_divconquer.c000066400000000000000000000124531461254215100225570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_divrem_divconquer, state) { int i, result; /* Check q*b + r = a, no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, prod; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_divconquer(q, r, a, b); fmpz_poly_mul(prod, q, b); fmpz_poly_add(prod, prod, r); result = (fmpz_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(prod), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check r and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_divconquer(q, r, a, b); fmpz_poly_divrem_divconquer(q, a, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_divconquer(q, r, a, b); fmpz_poly_divrem_divconquer(q, b, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_divconquer(q, r, a, b); fmpz_poly_divrem_divconquer(a, r, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_poly_divrem_divconquer(q, r, a, b); fmpz_poly_divrem_divconquer(b, r, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-divrem_preinv.c000066400000000000000000000143021461254215100216760ustar00rootroot00000000000000/* Copyright (C) 2009, 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_divrem_preinv, state) { int i, result; /* Check q*b + r = a, no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q, r, prod; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_preinvert(b_inv, b); fmpz_poly_divrem_preinv(q, r, a, b, b_inv); fmpz_poly_mul(prod, q, b); fmpz_poly_add(prod, prod, r); result = (fmpz_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(prod), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check r and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_divrem_preinv(q, a, a, b, b_inv); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_divrem_preinv(q, b, a, b, b_inv); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_divrem_preinv(a, r, a, b, b_inv); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_divrem_preinv(b, r, a, b, b_inv); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-equal_fmpz.c000066400000000000000000000027631461254215100212000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_equal_fmpz, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_t c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_init(c); fmpz_randtest(c, state, 1 + n_randint(state, 200)); fmpz_poly_set_fmpz(b, c); fmpz_poly_randtest(a, state, n_randint(state, 6), 1 + n_randint(state, 200)); if (n_randint(state, 2)) fmpz_poly_set_coeff_fmpz(a, 0, c); result = fmpz_poly_equal(a, b) == fmpz_poly_equal_fmpz(a, c); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-equal_trunc.c000066400000000000000000000052251461254215100213530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_equal_trunc, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_t c; slong n, j; fmpz_init(c); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); for (j = 0; j < n; j++) { fmpz_poly_get_coeff_fmpz(c, a, j); fmpz_poly_set_coeff_fmpz(b, j, c); } result = (fmpz_poly_equal_trunc(a, b, n)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_poly_clear(a); fmpz_poly_clear(b); } /* unequal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_t c; slong m, n, j; fmpz_init(c); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100) + 1; m = n_randint(state, n); for (j = 0; j < n; j++) { fmpz_poly_get_coeff_fmpz(c, a, j); fmpz_poly_set_coeff_fmpz(b, j, c); } fmpz_poly_get_coeff_fmpz(c, b, m); fmpz_add_ui(c, c, 1); fmpz_poly_set_coeff_fmpz(b, m, c); result = (!fmpz_poly_equal_trunc(a, b, n)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd\n", n); flint_printf("m = %wd\n", m); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-eta_qexp.c000066400000000000000000000032361461254215100206370ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_eta_qexp, state) { int i; for (i = 0; i < 2000; i++) { fmpz_poly_t a, b; slong e, n; fmpz_poly_init(a); fmpz_poly_init(b); e = n_randint(state, 100) - 50; n = n_randint(state, 250); fmpz_poly_randtest(a, state, n_randint(state, 250), 1 + n_randint(state, 100)); fmpz_poly_eta_qexp(a, e, n); fmpz_poly_eta_qexp(b, 1, n + n_randint(state, 10)); if (n == 0) { fmpz_poly_zero(b); } else { if (e >= 0) { fmpz_poly_pow_trunc(b, b, e, n); } else { fmpz_poly_inv_series(b, b, n); fmpz_poly_pow_trunc(b, b, -e, n); } } if (!fmpz_poly_equal(a, b)) { flint_printf("FAIL (powering):\n"); flint_printf("e = %wd, n = %wd\n\n", e, n); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-eulerian_polynomial.c000066400000000000000000000051231461254215100230750ustar00rootroot00000000000000/* Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_eulerian_polynomial, state) { ulong n, ix, mx; fmpz_t sum, fac; fmpz_poly_t poly; fmpz_poly_init(poly); fmpz_init(sum); fmpz_init(fac); for (ix = 0; ix < 100; ix++) { n = n_randint(state, 1000) + 1; /* Don't want n = 0. */ fmpz_poly_eulerian_polynomial(poly, n); if (!fmpz_is_one(poly->coeffs)) { flint_printf("The first coefficient is not 1 for n = %u. Received:\n", n); fmpz_poly_print_pretty(poly, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } if (!fmpz_is_one(poly->coeffs + (n - 1))) { flint_printf("The last coefficient is not 1 for n = %u. Received:\n", n); fmpz_poly_print_pretty(poly, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } for (mx = 0; mx <= n / 2; mx++) { if (!fmpz_equal(poly->coeffs + mx, poly->coeffs + (n - mx - 1))) { flint_printf("A(n, m) is not equal to A(n, n - m - 1)" "for n = %u and m = %u.\n", n, mx); fflush(stdout); flint_abort(); } if (fmpz_cmp_si(poly->coeffs + mx, 0) <= 0) { flint_printf("Negative coefficients for A(n, m)" "where n = %u and m = %u.\n", n, mx); fflush(stdout); flint_abort(); } } fmpz_zero(sum); for (mx = 0; mx < n; mx++) fmpz_add(sum, sum, poly->coeffs + mx); fmpz_fac_ui(fac, n); if (!fmpz_equal(sum, fac)) { flint_printf("The sum of the coefficients of the %u'th polynomial" "was not equal to %u!.\n", n, n); flint_printf("Expected: "), fmpz_print(fac), flint_printf("\n"); flint_printf("Got: "), fmpz_print(sum), flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(poly); fmpz_clear(sum); fmpz_clear(fac); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_divconquer_fmpq.c000066400000000000000000000104441461254215100241200ustar00rootroot00000000000000/* Copyright (C) 1509 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_divconquer_fmpq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 150); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_divconquer_fmpq(y, f, x); fmpz_poly_evaluate_divconquer_fmpq(x, f, x); result = (fmpq_equal(x, y)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fmpz_poly_print(f), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpz_poly_clear(f); } /* Check that (f+g)(a) = f(a) + g(a) */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 100), 150); fmpz_poly_randtest(g, state, n_randint(state, 100), 150); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_divconquer_fmpq(y, f, x); fmpz_poly_evaluate_divconquer_fmpq(z, g, x); fmpq_add(y, y, z); fmpz_poly_add(f, f, g); fmpz_poly_evaluate_divconquer_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check that (f*g)(a) = f(a) * g(a) */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_divconquer_fmpq(y, f, x); fmpz_poly_evaluate_divconquer_fmpq(z, g, x); fmpq_mul(y, y, z); fmpz_poly_mul(f, f, g); fmpz_poly_evaluate_divconquer_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_divconquer_fmpz.c000066400000000000000000000043511461254215100241310ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_divconquer_fmpz, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_randtest(a, state, 100); fmpz_poly_evaluate_divconquer_fmpz(b, f, a); fmpz_poly_evaluate_divconquer_fmpz(a, f, a); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL (alias):\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_poly_clear(f); } /* Check that the result agrees with Horner's method */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_randtest(a, state, 100); fmpz_poly_evaluate_divconquer_fmpz(b, f, a); fmpz_poly_evaluate_horner_fmpz(c, f, a); result = (fmpz_equal(b, c)); if (!result) { flint_printf("FAIL (cmp with Horner):\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fmpz_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_fmpq.c000066400000000000000000000103011461254215100216510ustar00rootroot00000000000000/* Copyright (C) 1509 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_fmpq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 150); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_fmpq(y, f, x); fmpz_poly_evaluate_fmpq(x, f, x); result = (fmpq_equal(x, y)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fmpz_poly_print(f), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpz_poly_clear(f); } /* Check that (f+g)(a) = f(a) + g(a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 100), 150); fmpz_poly_randtest(g, state, n_randint(state, 100), 150); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_fmpq(y, f, x); fmpz_poly_evaluate_fmpq(z, g, x); fmpq_add(y, y, z); fmpz_poly_add(f, f, g); fmpz_poly_evaluate_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check that (f*g)(a) = f(a) * g(a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_fmpq(y, f, x); fmpz_poly_evaluate_fmpq(z, g, x); fmpq_mul(y, y, z); fmpz_poly_mul(f, f, g); fmpz_poly_evaluate_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_fmpz.c000066400000000000000000000025241461254215100216720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_fmpz, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_randtest(a, state, 100); fmpz_poly_evaluate_fmpz(b, f, a); fmpz_poly_evaluate_fmpz(a, f, a); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_horner_d_2exp.c000066400000000000000000000067111461254215100234560ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "double_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_horner_d_2exp, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f; double x, y, z, t; slong xexp, yexp; x = d_randtest(state); xexp = n_randint(state, 20) - 10; fmpz_poly_init(f); fmpz_poly_randtest(f, state, 1 + n_randint(state, 40), 1 + n_randint(state, 100)); fmpz_poly_scalar_abs(f, f); y = fmpz_poly_evaluate_horner_d_2exp2(&yexp, f, x, xexp); z = fmpz_poly_evaluate_horner_d(f, ldexp(x, xexp)); t = ldexp(y, yexp); if (fabs(t - z) > 1e-13 * fabs(z)) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("x, xexp = %.20g %wd\n\n", x, xexp); flint_printf("y, yexp = %.20g %wd\n\n", y, yexp); flint_printf("z = %.20g\n\n", z); flint_printf("y = %.20g\n\n", t); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f; double x, y; slong xexp, yexp, i; mpfr_t z, s, t, u, v, w, e; x = d_randtest(state); xexp = n_randint(state, 2000) - 1000; fmpz_poly_init(f); fmpz_poly_randtest(f, state, 1 + n_randint(state, 100), 1 + n_randint(state, 1000)); fmpz_poly_scalar_abs(f, f); mpfr_init2(z, 64); mpfr_init2(s, 64); mpfr_init2(t, 64); mpfr_init2(u, 64); mpfr_init2(v, 64); mpfr_init2(w, 64); mpfr_init2(e, 64); y = fmpz_poly_evaluate_horner_d_2exp2(&yexp, f, x, xexp); mpfr_set_d(z, x, MPFR_RNDN); mpfr_mul_2si(z, z, xexp, MPFR_RNDN); mpfr_set_ui(s, 0, MPFR_RNDN); mpfr_set_ui(t, 1, MPFR_RNDN); for (i = 0; i < f->length; i++) { fmpz_get_mpfr(u, f->coeffs + i, MPFR_RNDN); mpfr_mul(u, u, t, MPFR_RNDN); mpfr_add(s, s, u, MPFR_RNDN); mpfr_mul(t, t, z, MPFR_RNDN); } mpfr_set_d(v, y, MPFR_RNDN); mpfr_mul_2si(v, v, yexp, MPFR_RNDN); mpfr_sub(e, s, v, MPFR_RNDN); mpfr_abs(e, e, MPFR_RNDN); mpfr_abs(w, s, MPFR_RNDN); mpfr_mul_ui(w, w, f->length + 1, MPFR_RNDN); mpfr_mul_2si(w, w, -51, MPFR_RNDN); if (mpfr_cmp(e, w) > 0) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); mpfr_printf("%.17Rg\n", s); mpfr_printf("%.17Rg\n", v); mpfr_printf("%.17Rg\n", e); mpfr_printf("%.17Rg\n\n", w); fflush(stdout); flint_abort(); } mpfr_clear(z); mpfr_clear(s); mpfr_clear(t); mpfr_clear(u); mpfr_clear(v); mpfr_clear(w); mpfr_clear(e); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_horner_fmpq.c000066400000000000000000000103751461254215100232410ustar00rootroot00000000000000/* Copyright (C) 1509 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_horner_fmpq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 75 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 150); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_horner_fmpq(y, f, x); fmpz_poly_evaluate_horner_fmpq(x, f, x); result = (fmpq_equal(x, y)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fmpz_poly_print(f), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpz_poly_clear(f); } /* Check that (f+g)(a) = f(a) + g(a) */ for (i = 0; i < 75 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 100), 150); fmpz_poly_randtest(g, state, n_randint(state, 100), 150); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_horner_fmpq(y, f, x); fmpz_poly_evaluate_horner_fmpq(z, g, x); fmpq_add(y, y, z); fmpz_poly_add(f, f, g); fmpz_poly_evaluate_horner_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check that (f*g)(a) = f(a) * g(a) */ for (i = 0; i < 75 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpq_init(x); fmpq_init(y); fmpq_init(z); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_randtest(a, state, 100); fmpz_randtest_not_zero(b, state, 100); fmpz_set(fmpq_numref(x), a); fmpz_set(fmpq_denref(x), b); fmpq_canonicalise(x); fmpz_poly_evaluate_horner_fmpq(y, f, x); fmpz_poly_evaluate_horner_fmpq(z, g, x); fmpq_mul(y, y, z); fmpz_poly_mul(f, f, g); fmpz_poly_evaluate_horner_fmpq(z, f, x); result = (fmpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_horner_fmpz.c000066400000000000000000000046121461254215100232470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_horner_fmpz, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_randtest(a, state, 100); fmpz_poly_evaluate_horner_fmpz(b, f, a); fmpz_poly_evaluate_horner_fmpz(a, f, a); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_poly_clear(f); } /* Check that (f+g)(a) = f(a) + g(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_poly_randtest(g, state, n_randint(state, 100), 200); fmpz_randtest(a, state, 100); fmpz_poly_evaluate_horner_fmpz(b, f, a); fmpz_poly_evaluate_horner_fmpz(c, g, a); fmpz_add(b, b, c); fmpz_poly_add(f, f, g); fmpz_poly_evaluate_horner_fmpz(c, f, a); result = (fmpz_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(b), flint_printf("\n\n"); fmpz_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-evaluate_mod.c000066400000000000000000000031541461254215100214750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_evaluate_mod, state) { int i, result; /* Compare with evaluation over the integers */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t b, s; fmpz_poly_t f; mp_limb_t a, n, r; fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 10), 20); n = n_randtest_not_zero(state); a = n_randint(state, n); fmpz_init(b); fmpz_init(s); fmpz_set_ui(b, a); r = fmpz_poly_evaluate_mod(f, a, n); fmpz_poly_evaluate_fmpz(s, f, b); result = (r == fmpz_mod_ui(s, s, n)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); gmp_printf("a = %Mu\n\n", a); gmp_printf("n = %Mu\n\n", n); gmp_printf("r = %Mu\n\n", r); flint_printf("s = "), fmpz_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_clear(b); fmpz_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-fibonacci.c000066400000000000000000000026211461254215100207430ustar00rootroot00000000000000/* Copyright (C) 2016 Shivin Srivastava This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_fibonacci, state) { fmpz_poly_t Pn, Pn1, Pn2, R; slong n; fmpz_poly_init(Pn); fmpz_poly_init(Pn1); fmpz_poly_init(Pn2); fmpz_poly_init(R); fmpz_poly_set_ui(Pn, UWORD(0)); fmpz_poly_set_ui(Pn1, UWORD(1)); for (n = 0; n <= 500; n++) { fmpz_poly_fibonacci(R, n); if (!fmpz_poly_equal(Pn, R)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("Direct: "); fmpz_poly_print_pretty(R, "x"); flint_printf("\n"); flint_printf("Recur.: "); fmpz_poly_print_pretty(Pn, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_shift_left(Pn2, Pn1, 1); fmpz_poly_add(Pn2, Pn2, Pn); fmpz_poly_swap(Pn, Pn1); fmpz_poly_swap(Pn1, Pn2); } fmpz_poly_clear(Pn); fmpz_poly_clear(Pn1); fmpz_poly_clear(Pn2); fmpz_poly_clear(R); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-gcd.c000066400000000000000000000065621461254215100175730ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_gcd, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_gcd(a, b, c); fmpz_poly_gcd(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing a and b):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_gcd(a, b, c); fmpz_poly_gcd(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL (aliasing a and c):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that a divides GCD(af, ag) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, d, f, g, q, r; fmpz_poly_init(a); fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 24) + 1, 24); fmpz_poly_randtest(f, state, n_randint(state, 40), 80); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_mul(f, a, f); fmpz_poly_mul(g, a, g); fmpz_poly_gcd(d, f, g); fmpz_poly_divrem_divconquer(q, r, d, a); result = (r->length == WORD(0)); if (!result) { flint_printf("FAIL (check a | gcd(af, ag)):\n"); fmpz_poly_print(f), flint_printf("\n"); fmpz_poly_print(g), flint_printf("\n"); fmpz_poly_print(a), flint_printf("\n"); fmpz_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-gcd_heuristic.c000066400000000000000000000232471461254215100216510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" /* Tests whether the polynomial is suitably normalised for the result of a GCD operation, that is, whether it's leading coefficient is non-negative. */ #ifndef _t_gcd_is_canonical #define _t_gcd_is_canonical _t_gcd_is_canonical static int _t_gcd_is_canonical(const fmpz_poly_t poly) { return fmpz_poly_is_zero(poly) || (fmpz_sgn(fmpz_poly_lead(poly)) > 0); } #endif TEST_FUNCTION_START(fmpz_poly_gcd_heuristic, state) { int i, result, d1, d2; /* Check aliasing of a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); d1 = fmpz_poly_gcd_heuristic(a, b, c); d2 = fmpz_poly_gcd_heuristic(b, b, c); result = ((d1 == 0 && d2 == 0) || (fmpz_poly_equal(a, b) && _t_gcd_is_canonical(a))); if (!result) { flint_printf("FAIL (aliasing a and b):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); d1 = fmpz_poly_gcd_heuristic(a, b, c); d2 = fmpz_poly_gcd_heuristic(c, b, c); result = ((d1 == 0 && d2 == 0) || (fmpz_poly_equal(a, c) && _t_gcd_is_canonical(a))); if (!result) { flint_printf("FAIL (aliasing a and c):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that a divides GCD(af, ag) */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_poly_t a, d, f, g, q, r; fmpz_poly_init(a); fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 100) + 1, 40); fmpz_poly_randtest(f, state, n_randint(state, 100), 40); fmpz_poly_randtest(g, state, n_randint(state, 100), 40); fmpz_poly_mul(f, a, f); fmpz_poly_mul(g, a, g); d1 = fmpz_poly_gcd_heuristic(d, f, g); if (d1) { fmpz_poly_divrem_divconquer(q, r, d, a); result = fmpz_poly_is_zero(r) && _t_gcd_is_canonical(d); if (!result) { flint_printf("FAIL (check a | gcd(af, ag)):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("d = "), fmpz_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(a); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check that a == GCD(af, ag) when GCD(f, g) = 1 */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_poly_t a, d, f, g, q, r; fmpz_poly_init(a); fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 100) + 1, 200); do { fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_poly_randtest(g, state, n_randint(state, 100), 200); fmpz_poly_gcd_heuristic(d, f, g); } while (!(d->length == 1 && fmpz_is_one(d->coeffs))); fmpz_poly_mul(f, a, f); fmpz_poly_mul(g, a, g); d1 = fmpz_poly_gcd_heuristic(d, f, g); if (d1) { if (!_t_gcd_is_canonical(a)) fmpz_poly_neg(a, a); result = fmpz_poly_equal(d, a) && _t_gcd_is_canonical(d); if (!result) { flint_printf("FAIL (check a == gcd(af, ag) when gcd(f, g) = 1):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("d = "), fmpz_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(a); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check that gcd(f, ga) divides f and ga for small generic f, g and a small linear factor a. Exercises a bug found by Anton Mellit. */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, d, f, g, q, r; fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(a); fmpz_poly_randtest(f, state, n_randint(state, 10), 8); fmpz_poly_randtest(g, state, n_randint(state, 10), 4); /* multiply by small linear factor */ fmpz_poly_set_coeff_si(a, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_set_coeff_si(a, 1, 1); fmpz_poly_mul(g, g, a); d1 = fmpz_poly_gcd_heuristic(d, f, g); if (d1) { if (fmpz_poly_is_zero(d)) result = fmpz_poly_is_zero(f) && fmpz_poly_is_zero(g); else { fmpz_poly_divrem_divconquer(q, r, f, d); result = fmpz_poly_is_zero(r); fmpz_poly_divrem_divconquer(q, r, g, d); result &= fmpz_poly_is_zero(r); } if (!result) { flint_printf("FAIL (gcd(f, g) | f and g):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("d = "), fmpz_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(a); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Sebastian's test case */ { fmpz_poly_t a, b, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(d); fmpz_poly_set_coeff_ui(b, 2, 1); fmpz_poly_set_coeff_si(a, 0, -32); fmpz_poly_set_coeff_si(a, 1, 24); fmpz_poly_gcd_heuristic(d, a, b); result = (d->length == 1 && fmpz_is_one(d->coeffs)); if (!result) { flint_printf("FAIL (check 1 == gcd(x^2, 24*x - 32):\n"); fmpz_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(d); } /* Anton Mellit's test case */ { fmpz_poly_t a, b, d; int heuristic; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(d); /* b = 3*q^12 - 8*q^11 - 24*q^10 - 48*q^9 - 84*q^8 - 92*q^7 - 92*q^6 - 70*q^5 - 50*q^4 - 27*q^3 - 13*q^2 - 4*q - 1 a = q^13 - 2*q^12 + 2*q^10 - q^9 */ fmpz_poly_set_str(b, "13 -1 -4 -13 -27 -50 -70 -92 -92 -84 -48 -24 -8 3"); fmpz_poly_set_str(a, "14 0 0 0 0 0 0 0 0 0 -1 2 0 -2 1"); heuristic = fmpz_poly_gcd_heuristic(d, a, b); result = (heuristic == 0 || (d->length == 1 && fmpz_is_one(d->coeffs))); if (!result) { flint_printf("FAIL Mellit test case:\n"); fmpz_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(d); } /* Daniel's test case */ { fmpz_poly_t a, b, g; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(g); fmpz_poly_set_str(a, "40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7609399 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 44"); fmpz_poly_set_str(b, "40 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 54909036 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -59769402"); fmpz_poly_gcd(g, a, b); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-gcd_modular.c000066400000000000000000000160121461254215100213050ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" /* Tests whether the polynomial is suitably normalised for the result of a GCD operation, that is, whether it's leading coefficient is non-negative. */ #ifndef _t_gcd_is_canonical #define _t_gcd_is_canonical _t_gcd_is_canonical static int _t_gcd_is_canonical(const fmpz_poly_t poly) { return fmpz_poly_is_zero(poly) || (fmpz_sgn(fmpz_poly_lead(poly)) > 0); } #endif TEST_FUNCTION_START(fmpz_poly_gcd_modular, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_gcd_modular(a, b, c); fmpz_poly_gcd_modular(b, b, c); result = (fmpz_poly_equal(a, b) && _t_gcd_is_canonical(a)); if (!result) { flint_printf("FAIL (aliasing a and b):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_gcd_modular(a, b, c); fmpz_poly_gcd_modular(c, b, c); result = (fmpz_poly_equal(a, c) && _t_gcd_is_canonical(a)); if (!result) { flint_printf("FAIL (aliasing a and c):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that a divides GCD(af, ag) */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_poly_t a, d, f, g, q, r; fmpz_poly_init(a); fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 100) + 1, 40); fmpz_poly_randtest(f, state, n_randint(state, 100), 40); fmpz_poly_randtest(g, state, n_randint(state, 100), 40); fmpz_poly_mul(f, a, f); fmpz_poly_mul(g, a, g); fmpz_poly_gcd_modular(d, f, g); fmpz_poly_divrem_divconquer(q, r, d, a); result = fmpz_poly_is_zero(r) && _t_gcd_is_canonical(d); if (!result) { flint_printf("FAIL (check a | gcd(af, ag)):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("d = "), fmpz_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check that a == GCD(af, ag) when GCD(f, g) = 1 */ for (i = 0; i < 300 * flint_test_multiplier(); i++) { fmpz_poly_t a, d, f, g, q, r; fmpz_poly_init(a); fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 100) + 1, 200); do { fmpz_poly_randtest(f, state, n_randint(state, 100), 200); fmpz_poly_randtest(g, state, n_randint(state, 100), 200); fmpz_poly_gcd_heuristic(d, f, g); } while (!(d->length == 1 && fmpz_is_one(d->coeffs))); fmpz_poly_mul(f, a, f); fmpz_poly_mul(g, a, g); fmpz_poly_gcd_modular(d, f, g); if (!_t_gcd_is_canonical(a)) fmpz_poly_neg(a, a); result = fmpz_poly_equal(d, a) && _t_gcd_is_canonical(d); if (!result) { flint_printf("FAIL (check a == gcd(af, ag) when gcd(f, g) = 1):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("d = "), fmpz_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Sebastian's test case */ { fmpz_poly_t a, b, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(d); fmpz_poly_set_coeff_ui(b, 2, 1); fmpz_poly_set_coeff_si(a, 0, -32); fmpz_poly_set_coeff_si(a, 1, 24); fmpz_poly_gcd_modular(d, a, b); result = (d->length == 1 && fmpz_is_one(d->coeffs)); if (!result) { flint_printf("FAIL (check 1 == gcd(x^2, 24*x - 32):\n"); fmpz_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(d); } /* another test case */ { fmpz_poly_t a, b, d, e; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(d); fmpz_poly_init(e); fmpz_poly_set_str(a, "12 0 0 0 0 0 0 0 0 0 8582594367 -9297159048333985579007 33822867456"); fmpz_poly_set_str(b, "8 0 0 -258272396248218664896 0 -2762 -549690802047 -3771028 8796059467776"); fmpz_poly_set_str(e, "3 0 0 1"); fmpz_poly_gcd_modular(d, a, b); result = fmpz_poly_equal(d, e); if (!result) { flint_printf("FAIL (check special #2):\n"); fmpz_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(d); fmpz_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-gcd_subresultant.c000066400000000000000000000066141461254215100224040ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_gcd_subresultant, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_gcd_subresultant(a, b, c); fmpz_poly_gcd_subresultant(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing a and b):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_gcd_subresultant(a, b, c); fmpz_poly_gcd_subresultant(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL (aliasing a and c):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that a divides GCD(af, ag) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, d, f, g, q, r; fmpz_poly_init(a); fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 24) + 1, 24); fmpz_poly_randtest(f, state, n_randint(state, 40), 80); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_mul(f, a, f); fmpz_poly_mul(g, a, g); fmpz_poly_gcd_subresultant(d, f, g); fmpz_poly_divrem_divconquer(q, r, d, a); result = (r->length == WORD(0)); if (!result) { flint_printf("FAIL (check a | gcd(af, ag)):\n"); fmpz_poly_print(f), flint_printf("\n"); fmpz_poly_print(g), flint_printf("\n"); fmpz_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_coeff_ptr.c000066400000000000000000000026121461254215100216340ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_get_coeff_ptr, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t A; fmpz_t a; slong n = n_randint(state, 100); fmpz_poly_init(A); fmpz_poly_randtest(A, state, n_randint(state, 100), 100); fmpz_init(a); fmpz_poly_get_coeff_fmpz(a, A, n); result = n < fmpz_poly_length(A) ? fmpz_equal(a, fmpz_poly_get_coeff_ptr(A, n)) : fmpz_poly_get_coeff_ptr(A, n) == NULL; if (!result) { flint_printf("FAIL:\n"); flint_printf("A = "), fmpz_poly_print(A), flint_printf("\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n\n"); flint_printf("n = %wd\n\n", n); fflush(stdout); flint_abort(); } fmpz_poly_clear(A); fmpz_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_nmod_poly.c000066400000000000000000000027051461254215100216700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_get_nmod_poly, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t A; nmod_poly_t M, M2; slong length; mp_limb_t mod; length = n_randint(state, 50); mod = n_randtest_prime(state, 0); nmod_poly_init(M, mod); nmod_poly_init(M2, mod); fmpz_poly_init(A); nmod_poly_randtest(M, state, length); if (i % 2 == 0) fmpz_poly_set_nmod_poly(A, M); else fmpz_poly_set_nmod_poly_unsigned(A, M); fmpz_poly_scalar_mul_ui(A, A, UWORD(2)); nmod_poly_add(M, M, M); fmpz_poly_get_nmod_poly(M2, A); if (!nmod_poly_equal(M, M2)) { flint_printf("FAIL!\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(A); nmod_poly_clear(M); nmod_poly_clear(M2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_set_coeff_fmpz.c000066400000000000000000000030651461254215100226610ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_get_set_coeff_fmpz, state) { int i, j, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a; fmpz_t x1, x2; slong coeff, len; fmpz_poly_init(a); fmpz_init(x1); fmpz_init(x2); len = n_randint(state, 100) + 1; for (j = 0; j < 1000; j++) { fmpz_randtest(x1, state, 200); coeff = n_randint(state, len); fmpz_poly_set_coeff_fmpz(a, coeff, x1); fmpz_poly_get_coeff_fmpz(x2, a, coeff); result = (fmpz_equal(x1, x2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x1 = "), fmpz_print(x1), flint_printf("\n"); flint_printf("x2 = "), fmpz_print(x2), flint_printf("\n"); flint_printf("coeff = %wd, length = %wd\n", coeff, len); fflush(stdout); flint_abort(); } } fmpz_clear(x1); fmpz_clear(x2); fmpz_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_set_coeff_si.c000066400000000000000000000025011461254215100223120ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_get_set_coeff_si, state) { int i, j, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a; slong coeff, len; slong n1, n2; fmpz_poly_init(a); len = n_randint(state, 100) + 1; for (j = 0; j < 1000; j++) { n1 = z_randtest(state); coeff = n_randint(state, len); fmpz_poly_set_coeff_si(a, coeff, n1); n2 = fmpz_poly_get_coeff_si(a, coeff); result = (n1 == n2); if (!result) { flint_printf("FAIL: n1 = %wd, n2 = %wd, coeff = %wd, length = %wd\n", n1, n2, coeff, len); fflush(stdout); flint_abort(); } } fmpz_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_set_coeff_ui.c000066400000000000000000000024501461254215100223170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_get_set_coeff_ui, state) { int i, j, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a; ulong n1, n2; slong coeff, len; fmpz_poly_init(a); len = n_randint(state, 100) + 1; for (j = 0; j < 1000; j++) { n1 = n_randtest(state); coeff = n_randint(state, len); fmpz_poly_set_coeff_ui(a, coeff, n1); n2 = fmpz_poly_get_coeff_ui(a, coeff); result = (n1 == n2); if (!result) { flint_printf("FAIL: n1 = %wu, n2 = %wu, coeff = %wd, length = %wd\n", n1, n2, coeff, len); fflush(stdout); flint_abort(); } } fmpz_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_set_str.c000066400000000000000000000025561461254215100213570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_get_set_str, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; char * str; int ans; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), n_randint(state, 200)); str = fmpz_poly_get_str(a); ans = fmpz_poly_set_str(b, str); result = (ans == 0 && fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); flint_free(str); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_str.c000066400000000000000000000033131461254215100204740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_get_str, state) { int result; char *str; fmpz_poly_t a; fmpz_poly_init(a); str = fmpz_poly_get_str(a); result = strcmp(str, "0") == 0; if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("str(a) = {%s}\n", str); fflush(stdout); flint_abort(); } flint_free(str); fmpz_poly_set_si(a, -2); str = fmpz_poly_get_str(a); result = strcmp(str, "1 -2") == 0; if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("str(a) = {%s}\n", str); fflush(stdout); flint_abort(); } flint_free(str); fmpz_poly_set_coeff_si(a, 3, 1); str = fmpz_poly_get_str(a); result = strcmp(str, "4 -2 0 0 1") == 0; if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("str(a) = {%s}\n", str); fflush(stdout); flint_abort(); } flint_free(str); fmpz_poly_clear(a); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-get_str_pretty.c000066400000000000000000000033551461254215100221110ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_get_str_pretty, state) { int result; char *str; fmpz_poly_t a; fmpz_poly_init(a); str = fmpz_poly_get_str_pretty(a, "t"); result = strcmp(str, "0") == 0; if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("str(a) = {%s}\n", str); fflush(stdout); flint_abort(); } flint_free(str); fmpz_poly_set_si(a, -2); str = fmpz_poly_get_str_pretty(a, "t"); result = strcmp(str, "-2") == 0; if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("str(a) = {%s}\n", str); fflush(stdout); flint_abort(); } flint_free(str); fmpz_poly_set_coeff_si(a, 3, 1); str = fmpz_poly_get_str_pretty(a, "t"); result = strcmp(str, "t^3-2") == 0; if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n"); flint_printf("str(a) = {%s}\n", str); fflush(stdout); flint_abort(); } flint_free(str); fmpz_poly_clear(a); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-hensel_lift.c000066400000000000000000000126111461254215100213220ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_hensel_lift, state) { int i, result; /* We check that lifting local factors of F_poly yields factors */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t F_poly, F_poly2, F_poly3, A, B, G, H, A_out, B_out, G_out, H_out, Prod_1, Prod_2; nmod_poly_t a, b, d, g, h, prod; fmpz_t p, p1, big_P, p1_2, big_P_2; slong bits, length, nbits, n, exp, part_exp; bits = n_randint(state, 200) + 1; nbits = n_randint(state, FLINT_BITS - 6) + 6; fmpz_init(p); fmpz_init(p1); fmpz_init(big_P); fmpz_init(p1_2); fmpz_init(big_P_2); fmpz_poly_init(F_poly); fmpz_poly_init(F_poly2); fmpz_poly_init(F_poly3); fmpz_poly_init(Prod_1); fmpz_poly_init(Prod_2); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_init(G); fmpz_poly_init(H); fmpz_poly_init(A_out); fmpz_poly_init(B_out); fmpz_poly_init(G_out); fmpz_poly_init(H_out); n = n_randprime(state, nbits, 0); exp = bits/(FLINT_BIT_COUNT(n) - 1) + 1; part_exp = n_randint(state, exp); nmod_poly_init(g, n); nmod_poly_init(h, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(d, n); nmod_poly_init(prod, n); do { length = n_randint(state, 200) + 2; do { fmpz_poly_randtest(F_poly2, state, length, bits); } while (F_poly2->length < 2); fmpz_set_ui(F_poly2->coeffs, n_randbits(state, FLINT_MIN(bits, SMALL_FMPZ_BITCOUNT_MAX))); fmpz_set_ui(F_poly2->coeffs + F_poly2->length - 1, 1); length = n_randint(state, 200) + 2; do { fmpz_poly_randtest(F_poly3, state, length, bits); } while (F_poly3->length < 2); fmpz_set_ui(F_poly3->coeffs, n_randbits(state, FLINT_MIN(bits, SMALL_FMPZ_BITCOUNT_MAX))); fmpz_set_ui(F_poly3->coeffs + F_poly3->length - 1, 1); fmpz_poly_mul(F_poly, F_poly2, F_poly3); fmpz_poly_get_nmod_poly(prod, F_poly); } while (!nmod_poly_is_squarefree(prod)); fmpz_poly_get_nmod_poly(g, F_poly2); fmpz_poly_get_nmod_poly(h, F_poly3); nmod_poly_xgcd(d, a, b, g, h); nmod_poly_clear(prod); nmod_poly_clear(d); fmpz_poly_set_nmod_poly(A, a); fmpz_poly_set_nmod_poly(B, b); fmpz_poly_set_nmod_poly(G, g); fmpz_poly_set_nmod_poly(H, h); fmpz_set_ui(p, n); fmpz_set_ui(p1, n); fmpz_set_ui(big_P, n); fmpz_set_ui(p1_2, n); fmpz_set_ui(big_P_2, n); part_exp = 1; while (part_exp < exp) { fmpz_set(p, big_P); fmpz_set_ui(p1, n); fmpz_set_ui(big_P, n); if (exp - part_exp <= part_exp) { fmpz_pow_ui(p1, p1, exp - part_exp); fmpz_pow_ui(big_P, big_P, exp); part_exp = exp; } else { fmpz_set(p1, p); fmpz_pow_ui(big_P, big_P, 2*part_exp); part_exp = 2*part_exp; } fmpz_poly_hensel_lift(G_out, H_out, A_out, B_out, F_poly, G, H, A, B, p, p1); fmpz_poly_set(G, G_out); fmpz_poly_set(H, H_out); fmpz_poly_set(A, A_out); fmpz_poly_set(B, B_out); } fmpz_poly_mul(Prod_1, A, G); fmpz_poly_mul(Prod_2, B, H); fmpz_poly_add(Prod_1, Prod_1, Prod_2); fmpz_poly_scalar_smod_fmpz(Prod_1, Prod_1, big_P); result = (Prod_1->length == 1 && fmpz_is_one(Prod_1->coeffs)); if (!result) { flint_printf("FAIL:\n"); flint_printf("length = %wd, bits = %wd, n = %wd, exp = %wd\n", length, bits, n, exp); fmpz_poly_print(F_poly); flint_printf("\n\n"); fmpz_poly_print(F_poly2); flint_printf("\n\n"); fmpz_poly_print(F_poly3); flint_printf("\n\n"); fmpz_poly_print(Prod_1); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(a); nmod_poly_clear(b); fmpz_poly_clear(Prod_1); fmpz_poly_clear(Prod_2); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(G); fmpz_poly_clear(H); fmpz_poly_clear(A_out); fmpz_poly_clear(B_out); fmpz_poly_clear(G_out); fmpz_poly_clear(H_out); fmpz_clear(p); fmpz_clear(p1); fmpz_clear(big_P); fmpz_clear(p1_2); fmpz_clear(big_P_2); fmpz_poly_clear(F_poly3); fmpz_poly_clear(F_poly2); fmpz_poly_clear(F_poly); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-hensel_lift_once.c000066400000000000000000000062501461254215100223300ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" TEST_FUNCTION_START(fmpz_poly_hensel_lift_once, state) { int i, result; /* We check that lifting local factors of F yields factors */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t F, G, H, R; fmpz_poly_factor_t F_fac; nmod_poly_factor_t f_fac; slong bits, nbits, n, exp, j; bits = n_randint(state, 200) + 1; nbits = n_randint(state, FLINT_BITS - 6) + 6; fmpz_poly_init(F); fmpz_poly_init(G); fmpz_poly_init(H); fmpz_poly_init(R); nmod_poly_factor_init(f_fac); fmpz_poly_factor_init(F_fac); n = n_randprime(state, nbits, 0); exp = bits / (FLINT_BIT_COUNT(n) - 1) + 1; /* Produce F as the product of random G and H */ { nmod_poly_t f; nmod_poly_init(f, n); do { do { fmpz_poly_randtest(G, state, n_randint(state, 200) + 2, bits); } while (G->length < 2); fmpz_randtest_not_zero(G->coeffs, state, bits); fmpz_one(fmpz_poly_lead(G)); do { fmpz_poly_randtest(H, state, n_randint(state, 200) + 2, bits); } while (H->length < 2); fmpz_randtest_not_zero(H->coeffs, state, bits); fmpz_one(fmpz_poly_lead(H)); fmpz_poly_mul(F, G, H); fmpz_poly_get_nmod_poly(f, F); } while (!nmod_poly_is_squarefree(f)); fmpz_poly_get_nmod_poly(f, G); nmod_poly_factor_insert(f_fac, f, 1); fmpz_poly_get_nmod_poly(f, H); nmod_poly_factor_insert(f_fac, f, 1); nmod_poly_clear(f); } fmpz_poly_hensel_lift_once(F_fac, F, f_fac, exp); result = 1; for (j = 0; j < F_fac->num; j++) { fmpz_poly_rem(R, F, F_fac->p + j); result &= (R->length == 0); } if (!result) { flint_printf("FAIL:\n"); flint_printf("bits = %wd, n = %wd, exp = %wd\n", bits, n, exp); fmpz_poly_print(F); flint_printf("\n\n"); fmpz_poly_print(G); flint_printf("\n\n"); fmpz_poly_print(H); flint_printf("\n\n"); fmpz_poly_factor_print(F_fac); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_factor_clear(f_fac); fmpz_poly_factor_clear(F_fac); fmpz_poly_clear(F); fmpz_poly_clear(G); fmpz_poly_clear(H); fmpz_poly_clear(R); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-hensel_lift_without_only_inverse.c000066400000000000000000000130531461254215100257020ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" TEST_FUNCTION_START(fmpz_poly_hensel_lift_without_only_inverse, state) { int i, result; /* We check that lifting local factors of F_poly yields factors */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t F_poly, F_poly2, F_poly3, A, B, G, H, A_out, B_out, G_out, H_out, Prod_1, Prod_2; nmod_poly_t a, b, d, g, h, prod; fmpz_t p, p1, big_P, p1_2, big_P_2; slong bits, length, nbits, n, exp, part_exp; bits = n_randint(state, 200) + 1; nbits = n_randint(state, FLINT_BITS - 6) + 6; fmpz_init(p); fmpz_init(p1); fmpz_init(big_P); fmpz_init(p1_2); fmpz_init(big_P_2); fmpz_poly_init(F_poly); fmpz_poly_init(F_poly2); fmpz_poly_init(F_poly3); fmpz_poly_init(Prod_1); fmpz_poly_init(Prod_2); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_init(G); fmpz_poly_init(H); fmpz_poly_init(A_out); fmpz_poly_init(B_out); fmpz_poly_init(G_out); fmpz_poly_init(H_out); n = n_randprime(state, nbits, 0); exp = bits/(FLINT_BIT_COUNT(n) - 1) + 1; part_exp = n_randint(state, exp); nmod_poly_init(g, n); nmod_poly_init(h, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(d, n); nmod_poly_init(prod, n); do { length = n_randint(state, 200) + 2; do { fmpz_poly_randtest(F_poly2, state, length, bits); } while (F_poly2->length < 2); fmpz_set_ui(F_poly2->coeffs, n_randbits(state, FLINT_MIN(bits, SMALL_FMPZ_BITCOUNT_MAX))); fmpz_set_ui(F_poly2->coeffs + F_poly2->length - 1, 1); length = n_randint(state, 200) + 2; do { fmpz_poly_randtest(F_poly3, state, length, bits); } while (F_poly3->length < 2); fmpz_set_ui(F_poly3->coeffs, n_randbits(state, FLINT_MIN(bits, SMALL_FMPZ_BITCOUNT_MAX))); fmpz_set_ui(F_poly3->coeffs + F_poly3->length - 1, 1); fmpz_poly_mul(F_poly, F_poly2, F_poly3); fmpz_poly_get_nmod_poly(prod, F_poly); } while (!nmod_poly_is_squarefree(prod)); fmpz_poly_get_nmod_poly(g, F_poly2); fmpz_poly_get_nmod_poly(h, F_poly3); nmod_poly_xgcd(d, a, b, g, h); nmod_poly_clear(prod); nmod_poly_clear(d); fmpz_poly_set_nmod_poly(A, a); fmpz_poly_set_nmod_poly(B, b); fmpz_poly_set_nmod_poly(G, g); fmpz_poly_set_nmod_poly(H, h); fmpz_set_ui(p, n); fmpz_set_ui(p1, n); fmpz_set_ui(big_P, n); fmpz_set_ui(p1_2, n); fmpz_set_ui(big_P_2, n); part_exp = 1; while (part_exp < exp) { fmpz_set(p, big_P); fmpz_set_ui(p1, n); fmpz_set_ui(big_P, n); if (exp - part_exp <= part_exp) { fmpz_pow_ui(p1, p1, exp - part_exp); fmpz_pow_ui(big_P, big_P, exp); part_exp = exp; } else { fmpz_set(p1, p); fmpz_pow_ui(big_P, big_P, 2*part_exp); part_exp = 2*part_exp; } fmpz_poly_hensel_lift_without_inverse(G_out, H_out, F_poly, G, H, A, B, p, p1); fmpz_poly_hensel_lift_only_inverse(A_out, B_out, G_out, H_out, A, B, p, p1); fmpz_poly_set(G, G_out); fmpz_poly_set(H, H_out); fmpz_poly_set(A, A_out); fmpz_poly_set(B, B_out); } fmpz_poly_mul(Prod_1, A, G); fmpz_poly_mul(Prod_2, B, H); fmpz_poly_add(Prod_1, Prod_1, Prod_2); fmpz_poly_scalar_smod_fmpz(Prod_1, Prod_1, big_P); result = (Prod_1->length == 1 && fmpz_is_one(Prod_1->coeffs)); if (!result) { flint_printf("FAIL:\n"); flint_printf("length = %wd, bits = %wd, n = %wd, exp = %wd\n", length, bits, n, exp); fmpz_poly_print(F_poly); flint_printf("\n\n"); fmpz_poly_print(F_poly2); flint_printf("\n\n"); fmpz_poly_print(F_poly3); flint_printf("\n\n"); fmpz_poly_print(Prod_1); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(a); nmod_poly_clear(b); fmpz_poly_clear(Prod_1); fmpz_poly_clear(Prod_2); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(G); fmpz_poly_clear(H); fmpz_poly_clear(A_out); fmpz_poly_clear(B_out); fmpz_poly_clear(G_out); fmpz_poly_clear(H_out); fmpz_clear(p); fmpz_clear(p1); fmpz_clear(big_P); fmpz_clear(p1_2); fmpz_clear(big_P_2); fmpz_poly_clear(F_poly3); fmpz_poly_clear(F_poly2); fmpz_poly_clear(F_poly); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-hensel_start_continue_lift.c000066400000000000000000000103431461254215100244430ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" TEST_FUNCTION_START(fmpz_poly_hensel_start_continue_lift, state) { int i, result; /* We check that lifting local factors of F yields factors */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t F, G, H, R; nmod_poly_factor_t f_fac; fmpz_poly_factor_t F_fac; slong bits, nbits, n, exp, j, part_exp; slong r; fmpz_poly_t *v, *w; slong *link; slong prev_exp; bits = n_randint(state, 200) + 1; nbits = n_randint(state, FLINT_BITS - 6) + 6; fmpz_poly_init(F); fmpz_poly_init(G); fmpz_poly_init(H); fmpz_poly_init(R); nmod_poly_factor_init(f_fac); fmpz_poly_factor_init(F_fac); n = n_randprime(state, nbits, 0); exp = bits / (FLINT_BIT_COUNT(n) - 1) + 1; part_exp = n_randint(state, exp); /* Produce F as the product of random G and H */ { nmod_poly_t f; nmod_poly_init(f, n); do { do { fmpz_poly_randtest(G, state, n_randint(state, 200) + 2, bits); } while (G->length < 2); fmpz_randtest_not_zero(G->coeffs, state, bits); fmpz_one(fmpz_poly_lead(G)); do { fmpz_poly_randtest(H, state, n_randint(state, 200) + 2, bits); } while (H->length < 2); fmpz_randtest_not_zero(H->coeffs, state, bits); fmpz_one(fmpz_poly_lead(H)); fmpz_poly_mul(F, G, H); fmpz_poly_get_nmod_poly(f, F); } while (!nmod_poly_is_squarefree(f)); fmpz_poly_get_nmod_poly(f, G); nmod_poly_factor_insert(f_fac, f, 1); fmpz_poly_get_nmod_poly(f, H); nmod_poly_factor_insert(f_fac, f, 1); nmod_poly_clear(f); } r = f_fac->num; v = flint_malloc((2*r - 2)*sizeof(fmpz_poly_t)); w = flint_malloc((2*r - 2)*sizeof(fmpz_poly_t)); link = flint_malloc((2*r - 2)*sizeof(slong)); for (j = 0; j < 2*r - 2; j++) { fmpz_poly_init(v[j]); fmpz_poly_init(w[j]); } if (part_exp < 1) { _fmpz_poly_hensel_start_lift(F_fac, link, v, w, F, f_fac, exp); } else { fmpz_t nn; fmpz_init_set_ui(nn, n); prev_exp = _fmpz_poly_hensel_start_lift(F_fac, link, v, w, F, f_fac, part_exp); _fmpz_poly_hensel_continue_lift(F_fac, link, v, w, F, prev_exp, part_exp, exp, nn); fmpz_clear(nn); } result = 1; for (j = 0; j < F_fac->num; j++) { fmpz_poly_rem(R, F, F_fac->p + j); result &= (R->length == 0); } for (j = 0; j < 2*r - 2; j++) { fmpz_poly_clear(v[j]); fmpz_poly_clear(w[j]); } flint_free(link); flint_free(v); flint_free(w); if (!result) { flint_printf("FAIL:\n"); flint_printf("bits = %wd, n = %wd, exp = %wd\n", bits, n, exp); fmpz_poly_print(F); flint_printf("\n\n"); fmpz_poly_print(G); flint_printf("\n\n"); fmpz_poly_print(H); flint_printf("\n\n"); fmpz_poly_factor_print(F_fac); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_factor_clear(f_fac); fmpz_poly_factor_clear(F_fac); fmpz_poly_clear(F); fmpz_poly_clear(H); fmpz_poly_clear(G); fmpz_poly_clear(R); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-hermite_h.c000066400000000000000000000027751461254215100210040ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_hermite_h, state) { fmpz_poly_t T0, T1, t1, t2; slong n; fmpz_poly_init(T0); fmpz_poly_init(T1); fmpz_poly_init(t1); fmpz_poly_init(t2); fmpz_poly_hermite_h(T0, 0); for (n = 1; n <= 500; n++) { fmpz_poly_hermite_h(T1, n); /* Verify H_{n+1} = 2 x H_n - diff(H_n) */ fmpz_poly_scalar_mul_ui(t1, T0, UWORD(2)); fmpz_poly_shift_left(t1, t1, 1); fmpz_poly_set(t2, T0); fmpz_poly_derivative(t2, t2); fmpz_poly_sub(t1, t1, t2); if (!fmpz_poly_equal(t1, T1)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("t1: "); fmpz_poly_print_pretty(t1, "x"); flint_printf("\n"); flint_printf("T1: "); fmpz_poly_print_pretty(T1, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_swap(T0, T1); } fmpz_poly_clear(T0); fmpz_poly_clear(T1); fmpz_poly_clear(t1); fmpz_poly_clear(t2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-hermite_he.c000066400000000000000000000027561461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_hermite_he, state) { fmpz_poly_t T0, T1, t1, t2; slong n; fmpz_poly_init(T0); fmpz_poly_init(T1); fmpz_poly_init(t1); fmpz_poly_init(t2); fmpz_poly_hermite_he(T0, 0); fmpz_poly_hermite_he(t1, 0); for (n = 1; n <= 500; n++) { fmpz_poly_hermite_he(T1, n); /* Verify H_{n+1} = 2 x H_n - diff(H_n) */ fmpz_poly_shift_left(t1, t1, 1); fmpz_poly_set(t2, T0); fmpz_poly_derivative(t2, t2); fmpz_poly_sub(t1, t1, t2); if (!fmpz_poly_equal(t1, T1)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("t1: "); fmpz_poly_print_pretty(t1, "x"); flint_printf("\n"); flint_printf("T1: "); fmpz_poly_print_pretty(T1, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_swap(T0, T1); } fmpz_poly_clear(T0); fmpz_poly_clear(T1); fmpz_poly_clear(t1); fmpz_poly_clear(t2); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-inflate.c000066400000000000000000000043731461254215100204560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_inflate, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t poly1, poly2, poly3, xp; fmpz_t one; ulong inflation; fmpz_poly_init(poly1); fmpz_poly_init(poly2); fmpz_poly_init(poly3); fmpz_poly_init(xp); fmpz_poly_randtest(poly1, state, n_randint(state, 20), n_randint(state, 200)); inflation = n_randint(state, 10); fmpz_poly_inflate(poly2, poly1, inflation); fmpz_init(one); fmpz_one(one); fmpz_poly_set_coeff_fmpz(xp, inflation, one); fmpz_poly_compose(poly3, poly1, xp); fmpz_clear(one); if (!fmpz_poly_equal(poly2, poly3)) { flint_printf("FAIL: not equal to compose (inflation = %wu)\n", inflation); flint_printf("poly1:\n"); fmpz_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); fmpz_poly_print(poly2); flint_printf("\n\n"); flint_printf("poly3:\n"); fmpz_poly_print(poly3); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_inflate(poly1, poly1, inflation); if (!fmpz_poly_equal(poly1, poly2)) { flint_printf("FAIL: aliasing (inflation = %wu)\n", inflation); flint_printf("poly1:\n"); fmpz_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); fmpz_poly_print(poly2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(poly1); fmpz_poly_clear(poly2); fmpz_poly_clear(poly3); fmpz_poly_clear(xp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-init_realloc_clear.c000066400000000000000000000022451461254215100226420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_init_realloc_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a; fmpz_poly_init2(a, n_randint(state, 100)); fmpz_poly_clear(a); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a; fmpz_poly_init2(a, n_randint(state, 100)); fmpz_poly_realloc(a, n_randint(state, 100)); fmpz_poly_clear(a); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a; fmpz_poly_init(a); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-interpolate_fmpz_vec.c000066400000000000000000000031771461254215100232540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_interpolate_fmpz_vec, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t P, Q; fmpz *x, *y; slong j, n, npoints, bits; npoints = n_randint(state, 50); n = n_randint(state, npoints + 1); bits = n_randint(state, 100); x = _fmpz_vec_init(npoints); y = _fmpz_vec_init(npoints); fmpz_poly_init(P); fmpz_poly_init(Q); fmpz_poly_randtest(P, state, n, bits); for (j = 0; j < npoints; j++) fmpz_set_si(x + j, -npoints/2 + j); fmpz_poly_evaluate_fmpz_vec(y, P, x, npoints); fmpz_poly_interpolate_fmpz_vec(Q, x, y, npoints); result = (fmpz_poly_equal(P, Q)); if (!result) { flint_printf("FAIL (P != Q):\n"); fmpz_poly_print(P), flint_printf("\n\n"); fmpz_poly_print(Q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(P); fmpz_poly_clear(Q); _fmpz_vec_clear(x, npoints); _fmpz_vec_clear(y, npoints); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-inv_series.c000066400000000000000000000050031461254215100211710ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_inv_series, state) { int i, result; /* Check Q^{-1} * Q is congruent 1 mod t^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, one; slong n = n_randint(state, 80) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(one); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 80) + 1, 100); fmpz_poly_set_coeff_si(a, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_set_ui(one, 1); fmpz_poly_inv_series(b, a, n); fmpz_poly_mullow(c, a, b, n); result = (fmpz_poly_equal(c, one)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } /* Verify bug fix for the case Q = -1 mod (x) */ { fmpz_poly_t a, b, c, one; slong n = 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(one); fmpz_poly_set_si(a, -1); fmpz_poly_set_ui(one, 1); fmpz_poly_inv_series(b, a, n); fmpz_poly_mullow(c, a, b, n); result = (fmpz_poly_equal(c, one)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-inv_series_basecase.c000066400000000000000000000052501461254215100230230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_inv_series_basecase, state) { int i, result; /* Check Q^{-1} * Q is congruent 1 mod t^n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, one; slong bits, n; bits = 1 + n_randint(state, 80); n = n_randint(state, 80) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(one); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 100) + 1, bits); fmpz_poly_set_coeff_si(a, 0, n_randint(state, 2) ? 1 : -1); if (n_randint(state, 2)) fmpz_poly_inv_series(a, a, n); fmpz_poly_set_ui(one, 1); fmpz_poly_inv_series_basecase(b, a, n); fmpz_poly_mullow(c, a, b, n); result = (fmpz_poly_equal(c, one)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } /* Verify bug fix for the case Q = -1 mod (x) */ { fmpz_poly_t a, b, c, one; slong n = 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(one); fmpz_poly_set_si(a, -1); fmpz_poly_set_ui(one, 1); fmpz_poly_inv_series_basecase(b, a, n); fmpz_poly_mullow(c, a, b, n); result = (fmpz_poly_equal(c, one)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-inv_series_newton.c000066400000000000000000000050301461254215100225630ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_inv_series_newton, state) { int i, result; /* Check Q^{-1} * Q is congruent 1 mod t^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, one; slong n = n_randint(state, 80) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(one); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 80) + 1, 100); fmpz_poly_set_coeff_si(a, 0, n_randint(state, 2) ? 1 : -1); fmpz_poly_set_ui(one, 1); fmpz_poly_inv_series_newton(b, a, n); fmpz_poly_mullow(c, a, b, n); result = (fmpz_poly_equal(c, one)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } /* Verify bug fix for the case Q = -1 mod (x) */ { fmpz_poly_t a, b, c, one; slong n = 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(one); fmpz_poly_set_si(a, -1); fmpz_poly_set_ui(one, 1); fmpz_poly_inv_series_newton(b, a, n); fmpz_poly_mullow(c, a, b, n); result = (fmpz_poly_equal(c, one)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-is_cyclotomic.c000066400000000000000000000047001461254215100216660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_is_cyclotomic, state) { int i; /* Check detection of small cyclotomics */ for (i = 0; i < 250; i++) { fmpz_poly_t f; ulong n, r; n = i; fmpz_poly_init(f); fmpz_poly_cyclotomic(f, n); r = fmpz_poly_is_cyclotomic(f); if (r != n) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("%wu %wu\n\n", n, r); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); } /* Check detection of large cyclotomics */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t f; ulong n, r; n = n_randtest(state) % 10000; fmpz_poly_init(f); fmpz_poly_cyclotomic(f, n); r = fmpz_poly_is_cyclotomic(f); if (r != n) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("%wu %wu\n\n", n, r); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); } /* Check cyclotomic + random polynomial */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; ulong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_cyclotomic(f, 1 + n_randint(state, 100)); fmpz_poly_randtest(g, state, 1 + n_randint(state, 50), 1); fmpz_poly_add(f, f, g); n = fmpz_poly_is_cyclotomic(f); if (n != 0) { fmpz_poly_cyclotomic(g, n); if (!fmpz_poly_equal(f, g)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n\n"); fmpz_poly_print(g); flint_printf("\n\n"); flint_printf("%wu\n\n", n); fflush(stdout); flint_abort(); } } fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-is_squarefree.c000066400000000000000000000055521461254215100216710ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_is_squarefree, state) { int i, result; /* Check that polynomials of degree <= 1 are square-free */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t f; fmpz_poly_init(f); fmpz_poly_randtest(f, state, n_randint(state, 2), 100); result = (fmpz_poly_is_squarefree(f)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_debug(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); } /* Check that a^2 f is not square-free */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_t a, f; fmpz_poly_init(a); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1, 40); if (a->length < 2) { fmpz_poly_clear(a); continue; } fmpz_poly_init(f); fmpz_poly_randtest_not_zero(f, state, n_randint(state, 20) + 1, 40); fmpz_poly_mul(a, a, a); fmpz_poly_mul(f, a, f); result = (!fmpz_poly_is_squarefree(f)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_debug(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(f); } /* Check that f + N*(x^M + 1) is square-free, for N >> f, M > deg(f) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_t a, f; fmpz_t N; fmpz_poly_init(a); fmpz_poly_set_coeff_si(a, 0, WORD(1)); fmpz_poly_set_coeff_si(a, n_randint(state, 20), WORD(1)); if (a->length < 2) { fmpz_poly_clear(a); continue; } fmpz_poly_init(f); fmpz_poly_randtest(f, state, a->length - 2, 40); fmpz_init_set_ui(N, UWORD(1)); fmpz_mul_2exp(N, N, 45 + a->length); fmpz_poly_scalar_mul_fmpz(a, a, N); fmpz_poly_add(f, a, f); result = fmpz_poly_is_squarefree(f); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_debug(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(f); fmpz_clear(N); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-lcm.c000066400000000000000000000070621461254215100176050ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_lcm, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_lcm(a, b, c); fmpz_poly_lcm(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing a and b):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 40), 80); fmpz_poly_randtest(c, state, n_randint(state, 40), 80); fmpz_poly_lcm(a, b, c); fmpz_poly_lcm(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL (aliasing a and c):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that GCD(f, g) LCM(f, g) == f g */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, gcd, lcm, lhs, rhs; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(gcd); fmpz_poly_init(lcm); fmpz_poly_init(lhs); fmpz_poly_init(rhs); fmpz_poly_randtest(f, state, n_randint(state, 40), 80); fmpz_poly_randtest(g, state, n_randint(state, 40), 80); fmpz_poly_gcd(gcd, f, g); fmpz_poly_lcm(lcm, f, g); fmpz_poly_mul(lhs, gcd, lcm); fmpz_poly_mul(rhs, f, g); if (!fmpz_poly_is_zero(rhs) && fmpz_sgn(fmpz_poly_lead(rhs)) < 0) fmpz_poly_neg(rhs, rhs); result = (fmpz_poly_equal(lhs, rhs)); if (!result) { flint_printf("FAIL (GCD(f, g) * LCM(f, g) == f * g):\n"); fmpz_poly_print(f), flint_printf("\n"); fmpz_poly_print(g), flint_printf("\n"); fmpz_poly_print(gcd), flint_printf("\n"); fmpz_poly_print(lcm), flint_printf("\n"); fmpz_poly_print(lhs), flint_printf("\n"); fmpz_poly_print(rhs), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(gcd); fmpz_poly_clear(lcm); fmpz_poly_clear(lhs); fmpz_poly_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-legendre_pt.c000066400000000000000000000033071461254215100213200ustar00rootroot00000000000000/* Copyright (C) 2016 Ralf Stephan This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_legendre_pt, state) { fmpz_poly_t T0, T1, T2, t, tt; slong n; fmpz_poly_init(T0); fmpz_poly_init(T1); fmpz_poly_init(T2); fmpz_poly_init(t); fmpz_poly_init(tt); fmpz_poly_legendre_pt(T0, 0); fmpz_poly_legendre_pt(T1, 1); for (n = 1; n <= 500; n++) { fmpz_poly_legendre_pt(T2, n+1); fmpz_poly_set(t, T1); /* Verify (n+1)P_{n+1} = (2n+1)(2x-1) P_n - nP_{n-1} */ fmpz_poly_shift_left(t, t, 1); fmpz_poly_scalar_mul_ui(t, t, 2); fmpz_poly_sub(t, t, T1); fmpz_poly_scalar_mul_ui(t, t, 2*n+1); fmpz_poly_scalar_mul_ui(tt, T0, n); fmpz_poly_sub(t, t, tt); fmpz_poly_scalar_mul_ui(tt, T2, n+1); if (!fmpz_poly_equal(t, tt)) { flint_printf("FAIL: n = %wd\n", n); flint_printf("t: "); fmpz_poly_print_pretty(t, "x"); flint_printf("\n"); flint_printf("tt: "); fmpz_poly_print_pretty(tt, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_swap(T0, T1); fmpz_poly_swap(T1, T2); } fmpz_poly_clear(T0); fmpz_poly_clear(T1); fmpz_poly_clear(T2); fmpz_poly_clear(t); fmpz_poly_clear(tt); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mul.c000066400000000000000000000130721461254215100176250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mul, state) { int i, result; int tmul = 200; #ifdef _WIN32 tmul = 1; #endif /* Check aliasing of a and b */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 500); fmpz_poly_randtest(c, state, n_randint(state, 50), 500); fmpz_poly_mul(a, b, c); fmpz_poly_mul(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 500); fmpz_poly_randtest(c, state, n_randint(state, 50), 500); fmpz_poly_mul(a, b, c); fmpz_poly_mul(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 500); fmpz_poly_set(c, b); fmpz_poly_mul(a, b, c); fmpz_poly_mul(d, b, b); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Check (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t a1, a2, b, c, d; fmpz_poly_init(a1); fmpz_poly_init(a2); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 100), 500); fmpz_poly_randtest(c, state, n_randint(state, 100), 500); fmpz_poly_randtest(d, state, n_randint(state, 100), 500); fmpz_poly_mul(a1, b, c); fmpz_poly_mul(a2, b, d); fmpz_poly_add(a1, a1, a2); fmpz_poly_add(c, c, d); fmpz_poly_mul(a2, b, c); result = (fmpz_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a1), flint_printf("\n\n"); fmpz_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a1); fmpz_poly_clear(a2); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Check _fmpz_poly_mul directly */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong len1, len2; fmpz_poly_t a, b, out1, out2; len1 = n_randint(state, 100) + 1; len2 = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len1, 200); fmpz_poly_randtest(b, state, len2, 200); fmpz_poly_mul(out1, a, b); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); fmpz_poly_fit_length(b, b->alloc + n_randint(state, 10)); a->length = a->alloc; b->length = b->alloc; fmpz_poly_fit_length(out2, a->length + b->length - 1); if (a->length >= b->length) _fmpz_poly_mul(out2->coeffs, a->coeffs, a->length, b->coeffs, b->length); else _fmpz_poly_mul(out2->coeffs, b->coeffs, b->length, a->coeffs, a->length); _fmpz_poly_set_length(out2, a->length + b->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mul_KS.c000066400000000000000000000136721461254215100202300ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mul_KS, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_KS(a, b, c); fmpz_poly_mul_KS(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_KS(a, b, c); fmpz_poly_mul_KS(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_set(c, b); fmpz_poly_mul_KS(a, b, b); fmpz_poly_mul_KS(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_KS(a, b, c); fmpz_poly_mul_classical(d, b, c); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Compare with mul_classical unsigned */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest_unsigned(b, state, n_randint(state, 50), 200); fmpz_poly_randtest_unsigned(c, state, n_randint(state, 50), 200); fmpz_poly_mul_KS(a, b, c); fmpz_poly_mul_classical(d, b, c); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Check _fmpz_poly_mul_KS directly */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len1, len2; fmpz_poly_t a, b, out1, out2; len1 = n_randint(state, 100) + 1; len2 = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len1, 200); fmpz_poly_randtest(b, state, len2, 200); fmpz_poly_mul_KS(out1, a, b); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); fmpz_poly_fit_length(b, b->alloc + n_randint(state, 10)); a->length = a->alloc; b->length = b->alloc; fmpz_poly_fit_length(out2, a->length + b->length - 1); _fmpz_poly_mul_KS(out2->coeffs, a->coeffs, a->length, b->coeffs, b->length); _fmpz_poly_set_length(out2, a->length + b->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mul_SS.c000066400000000000000000000127711461254215100202370ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mul_SS, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_SS(a, b, c); fmpz_poly_mul_SS(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_SS(a, b, c); fmpz_poly_mul_SS(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_set(c, b); fmpz_poly_mul_SS(a, b, b); fmpz_poly_mul_SS(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_KS */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 300), n_randint(state, 500) + 1); fmpz_poly_randtest(c, state, n_randint(state, 300), n_randint(state, 500) + 1); fmpz_poly_mul_SS(a, b, c); fmpz_poly_mul_KS(d, b, c); result = fmpz_poly_equal(a, d); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Compare with mul_KS large */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 300), n_randint(state, 20000) + 1); fmpz_poly_randtest(c, state, n_randint(state, 300), n_randint(state, 20000) + 1); fmpz_poly_mul_SS(a, b, c); fmpz_poly_mul_KS(d, b, c); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Compare with mul_KS unsigned */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest_unsigned(b, state, n_randint(state, 300), n_randint(state, 500) + 1); fmpz_poly_randtest_unsigned(c, state, n_randint(state, 300), n_randint(state, 500) + 1); fmpz_poly_mul_SS(a, b, c); fmpz_poly_mul_KS(d, b, c); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mul_SS_precache.c000066400000000000000000000047711461254215100220720ustar00rootroot00000000000000/* Copyright (C) 2010, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mul_SS_precache, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_mul_precache_t pre; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_SS_precache_init(pre, 50, 200, c); fmpz_poly_mul_SS(a, b, c); fmpz_poly_mul_SS_precache(b, b, pre); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_mul_precache_clear(pre); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_KS */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_mul_precache_t pre; int k; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_SS_precache_init(pre, 50, 200, c); for (k = 0; k < 3; k++) { fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_mul_KS(a, b, c); fmpz_poly_mul_SS_precache(d, b, pre); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_poly_mul_precache_clear(pre); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mul_classical.c000066400000000000000000000112341461254215100216410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mul_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_classical(a, b, c); fmpz_poly_mul_classical(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_classical(a, b, c); fmpz_poly_mul_classical(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a1, a2, b, c, d; fmpz_poly_init(a1); fmpz_poly_init(a2); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_randtest(c, state, n_randint(state, 100), 200); fmpz_poly_randtest(d, state, n_randint(state, 100), 200); fmpz_poly_mul_classical(a1, b, c); fmpz_poly_mul_classical(a2, b, d); fmpz_poly_add(a1, a1, a2); fmpz_poly_add(c, c, d); fmpz_poly_mul_classical(a2, b, c); result = (fmpz_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a1), flint_printf("\n\n"); fmpz_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a1); fmpz_poly_clear(a2); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Check _fmpz_poly_mul_classical directly */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len1, len2; fmpz_poly_t a, b, out1, out2; len1 = n_randint(state, 100) + 1; len2 = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len1, 200); fmpz_poly_randtest(b, state, len2, 200); fmpz_poly_mul_classical(out1, a, b); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); fmpz_poly_fit_length(b, b->alloc + n_randint(state, 10)); a->length = a->alloc; b->length = b->alloc; fmpz_poly_fit_length(out2, a->length + b->length - 1); _fmpz_poly_mul_classical(out2->coeffs, a->coeffs, a->length, b->coeffs, b->length); _fmpz_poly_set_length(out2, a->length + b->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mul_karatsuba.c000066400000000000000000000111561461254215100216630ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mul_karatsuba, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_karatsuba(a, b, c); fmpz_poly_mul_karatsuba(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_karatsuba(a, b, c); fmpz_poly_mul_karatsuba(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_karatsuba(a, b, c); fmpz_poly_mul_classical(d, b, c); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Check _fmpz_poly_mul_karatsuba directly */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len1, len2; fmpz_poly_t a, b, out1, out2; len1 = n_randint(state, 100) + 1; len2 = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len1, 200); fmpz_poly_randtest(b, state, len2, 200); fmpz_poly_mul_karatsuba(out1, a, b); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); fmpz_poly_fit_length(b, b->alloc + n_randint(state, 10)); a->length = a->alloc; b->length = b->alloc; fmpz_poly_fit_length(out2, a->length + b->length - 1); if (a->length >= b->length) _fmpz_poly_mul_karatsuba(out2->coeffs, a->coeffs, a->length, b->coeffs, b->length); else _fmpz_poly_mul_karatsuba(out2->coeffs, b->coeffs, b->length, a->coeffs, a->length); _fmpz_poly_set_length(out2, a->length + b->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mulhigh_classical.c000066400000000000000000000070551461254215100225070ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mulhigh_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, start; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; start = (len <= 0) ? 0 : n_randint(state, b->length + c->length); fmpz_poly_mulhigh_classical(a, b, c, start); fmpz_poly_mulhigh_classical(b, b, c, start); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, start; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; start = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mulhigh_classical(a, b, c, start); fmpz_poly_mulhigh_classical(c, b, c, start); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_basecase */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong len, start; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; start = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mul_classical(a, b, c); if (a->length >= start) _fmpz_vec_zero(a->coeffs, start); fmpz_poly_mulhigh_classical(d, b, c, start); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mulhigh_karatsuba_n.c000066400000000000000000000063461461254215100230450ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mulhigh_karatsuba_n, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); len = n_randint(state, 50); fmpz_poly_randtest(b, state, len, 200); fmpz_poly_randtest(c, state, len, 200); fmpz_poly_mulhigh_karatsuba_n(a, b, c, len); fmpz_poly_mulhigh_karatsuba_n(b, b, c, len); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); len = n_randint(state, 50); fmpz_poly_randtest(b, state, len, 200); fmpz_poly_randtest(c, state, len, 200); fmpz_poly_mulhigh_karatsuba_n(a, b, c, len); fmpz_poly_mulhigh_karatsuba_n(c, b, c, len); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_basecase */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); len = n_randint(state, 50); fmpz_poly_randtest(b, state, len, 200); fmpz_poly_randtest(c, state, len, 200); fmpz_poly_mul_classical(a, b, c); if (len) _fmpz_vec_zero(a->coeffs, FLINT_MIN(len - 1, a->length)); _fmpz_poly_normalise(a); fmpz_poly_mulhigh_karatsuba_n(d, b, c, len); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mulhigh_n.c000066400000000000000000000032041461254215100207760ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mulhigh_n, state) { int i, result; /* Compare with left truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong j, n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); n = n_randint(state, 50); fmpz_poly_randtest(b, state, n, 200); fmpz_poly_randtest(c, state, n, 200); fmpz_poly_mulhigh_n(a, b, c, n); fmpz_poly_mul(b, b, c); for (j = 0; j + 1 < n; j++) { if (j < a->length) fmpz_zero(a->coeffs + j); if (j < b->length) fmpz_zero(b->coeffs + j); } _fmpz_poly_normalise(a); _fmpz_poly_normalise(b); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mullow.c000066400000000000000000000044251461254215100203510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mullow, state) { int i, result; /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); trunc = n_randint(state, 50); fmpz_poly_randtest(b, state, trunc, 200); fmpz_poly_randtest(c, state, trunc, 200); fmpz_poly_mullow(a, b, c, trunc); fmpz_poly_mul(b, b, c); fmpz_poly_truncate(b, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 500); fmpz_poly_set(c, b); trunc = n_randint(state, 50); fmpz_poly_mullow(a, b, c, trunc); fmpz_poly_mullow(d, b, b, trunc); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mullow_KS.c000066400000000000000000000067061461254215100207520ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mullow_KS, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length); fmpz_poly_mullow_KS(a, b, c, trunc); fmpz_poly_mullow_KS(b, b, c, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len; ulong trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mullow_KS(a, b, c, trunc); fmpz_poly_mullow_KS(c, b, c, trunc); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_basecase */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mul_KS(a, b, c); fmpz_poly_truncate(a, trunc); fmpz_poly_mullow_KS(d, b, c, trunc); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mullow_SS.c000066400000000000000000000067001461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mullow_SS, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length); fmpz_poly_mullow_SS(a, b, c, trunc); fmpz_poly_mullow_SS(b, b, c, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len; ulong trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mullow_SS(a, b, c, trunc); fmpz_poly_mullow_SS(c, b, c, trunc); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_KS */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mul_KS(a, b, c); fmpz_poly_truncate(a, trunc); fmpz_poly_mullow_SS(d, b, c, trunc); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mullow_SS_precache.c000066400000000000000000000055421461254215100226110ustar00rootroot00000000000000/* Copyright (C) 2010, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mullow_SS_precache, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_mul_precache_t pre; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length); fmpz_poly_mul_SS_precache_init(pre, 50, 200, c); fmpz_poly_mullow_SS(a, b, c, trunc); fmpz_poly_mullow_SS_precache(b, b, pre, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_mul_precache_clear(pre); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_KS */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_mul_precache_t pre; slong len, trunc; int k; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_SS_precache_init(pre, 50, 200, c); for (k = 0; k < 3; k++) { fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mul_KS(a, b, c); fmpz_poly_truncate(a, trunc); fmpz_poly_mullow_SS_precache(d, b, pre, trunc); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_poly_mul_precache_clear(pre); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mullow_classical.c000066400000000000000000000067671461254215100224020ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mullow_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length); fmpz_poly_mullow_classical(a, b, c, trunc); fmpz_poly_mullow_classical(b, b, c, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len; ulong trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mullow_classical(a, b, c, trunc); fmpz_poly_mullow_classical(c, b, c, trunc); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_basecase */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); len = b->length + c->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, b->length + c->length - 1); fmpz_poly_mul_classical(a, b, c); fmpz_poly_truncate(a, trunc); fmpz_poly_mullow_classical(d, b, c, trunc); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mullow_karatsuba_n.c000066400000000000000000000061671461254215100227300ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mullow_karatsuba_n, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); len = n_randint(state, 50); fmpz_poly_randtest(b, state, len, 200); fmpz_poly_randtest(c, state, len, 200); fmpz_poly_mullow_karatsuba_n(a, b, c, len); fmpz_poly_mullow_karatsuba_n(b, b, c, len); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); len = n_randint(state, 50); fmpz_poly_randtest(b, state, len, 200); fmpz_poly_randtest(c, state, len, 200); fmpz_poly_mullow_karatsuba_n(a, b, c, len); fmpz_poly_mullow_karatsuba_n(c, b, c, len); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_karatsuba */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); len = n_randint(state, 50); fmpz_poly_randtest(b, state, len, 200); fmpz_poly_randtest(c, state, len, 200); fmpz_poly_mullow_karatsuba_n(a, b, c, len); fmpz_poly_mul_karatsuba(d, b, c); fmpz_poly_truncate(d, len); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-mulmid_classical.c000066400000000000000000000071321461254215100223350ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_mulmid_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); if (b->length == 0) fmpz_poly_zero(c); else fmpz_poly_randtest(c, state, n_randint(state, b->length), 200); fmpz_poly_mulmid_classical(a, b, c); fmpz_poly_mulmid_classical(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); if (b->length == 0) fmpz_poly_zero(c); else fmpz_poly_randtest(c, state, n_randint(state, b->length), 200); fmpz_poly_mulmid_classical(a, b, c); fmpz_poly_mulmid_classical(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_basecase */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, b->length + 1), 200); fmpz_poly_mulmid_classical(d, b, c); if (b->length == 0 || c->length == 0) { result = (d->length == 0); } else { fmpz_poly_mul_classical(a, b, c); fmpz_poly_truncate(a, b->length); fmpz_poly_shift_right(a, a, c->length - 1); result = (fmpz_poly_equal(a, d)); } if (!result) { flint_printf("FAIL:\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("d = "), fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-neg.c000066400000000000000000000024211461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_neg, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_neg(b, a); fmpz_poly_neg(c, b); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-newton_to_monomial.c000066400000000000000000000030501461254215100227320ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_newton_to_monomial, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; fmpz * r; slong k, n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); n = fmpz_poly_length(f); r = _fmpz_vec_init(n); for (k = 0; k < n; k++) fmpz_randtest(r + k, state, n_randint(state, 200)); fmpz_poly_set(g, f); _fmpz_poly_newton_to_monomial(g->coeffs, r, n); _fmpz_poly_monomial_to_newton(g->coeffs, r, n); if (!fmpz_poly_equal(f, g)) { flint_printf("FAIL: roundtrip\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); _fmpz_vec_clear(r, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-nth_derivative.c000066400000000000000000000037661461254215100220540ustar00rootroot00000000000000/* Copyright (C) 2021 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_nth_derivative, state) { ulong nth; int i, j, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); nth = n_randint(state, 100); fmpz_poly_nth_derivative(b, a, nth); fmpz_poly_nth_derivative(a, a, nth); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check if derivative is correct */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); nth = n_randint(state, 100); fmpz_poly_nth_derivative(b, a, nth); for (j = 0; j < nth; j ++) { fmpz_poly_derivative(a, a); } result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-num_real_roots.c000066400000000000000000000036771461254215100220720ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_num_real_roots, state) { int iter; /* call with random nonzero polynomials */ for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { slong k; fmpz_poly_t p; fmpz_poly_init(p); fmpz_poly_randtest_not_zero(p, state, 20, 10 + n_randint(state, 100)); k = fmpz_poly_num_real_roots(p); if (k < 0 || k > fmpz_poly_degree(p)) { printf("ERROR:\n"); flint_printf("got k in wrong range k = %wd\n", k); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(p); } for (iter = 0; iter < 5000 * flint_test_multiplier(); iter++) { slong k1, k2; fmpz_poly_t p; fmpz_poly_init(p); /* currently the code of num_real_roots only has a special branch */ /* for length <= 5. We only test these cases. */ do { fmpz_poly_randtest_not_zero(p, state, 1 + n_randint(state, 5), 100); } while (!fmpz_poly_is_squarefree(p)); k1 = fmpz_poly_num_real_roots_sturm(p); k2 = fmpz_poly_num_real_roots(p); if (k1 != k2) { printf("ERROR:\n"); flint_printf("found k1=%wd and k2=%wd\n", k1, k2); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-num_real_roots_sturm.c000066400000000000000000000060571461254215100233170ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_vec.h" TEST_FUNCTION_START(fmpz_poly_num_real_roots_sturm, state) { int iter; /* call with random nonzero polynomials */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { slong k; fmpz_poly_t p; fmpz_poly_init(p); fmpz_poly_randtest_not_zero(p, state, 20, 10 + n_randint(state, 100)); k = fmpz_poly_num_real_roots_sturm(p); if (k < 0 || k > fmpz_poly_degree(p)) { printf("ERROR:\n"); flint_printf("got k in wrong range k = %wd\n", k); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(p); } /* we check on products of the form */ /* Prod (X - r_i) x R */ /* where r_i are rationals and R has no real root */ for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { slong k, k_neg, k_pos, n; fmpz_poly_t p,q; fmpq * vec; n = 1 + n_randint(state, 10); vec = _fmpq_vec_init(n); _fmpq_vec_randtest_uniq_sorted(vec, state, n, 80); fmpz_poly_init(p); fmpz_poly_init(q); fmpz_poly_product_roots_fmpq_vec(p, vec, n); fmpz_poly_randtest_no_real_root(q, state, 1 + n_randint(state, 5), 80); /* note: here there is no need to check that q is squarefree (Sturm test remains valid) */ fmpz_poly_mul(p, p, q); k = fmpz_poly_num_real_roots_sturm(p); if (k != n) { printf("ERROR:\n"); flint_printf("found k = %wd instead of n = %wd\n", k, n); printf("vec = "); _fmpq_vec_print(vec, n); printf("\n"); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } if (!fmpz_is_zero(p->coeffs)) { _fmpz_poly_num_real_roots_sturm(&k_neg, &k_pos, p->coeffs, p->length); for (k = 0; (k < n) && (fmpq_sgn(vec + k) < 0); k++); if ((k_neg + k_pos != n) || (k != k_neg)) { printf("ERROR:\n"); flint_printf("found k_neg = %wd and k_pos = %wd instead of %wd and %wd\n", k_neg, k_pos, k, n - k); printf("vec = "); _fmpq_vec_print(vec, n); printf("\n"); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } } _fmpq_vec_clear(vec, n); fmpz_poly_clear(p); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pow.c000066400000000000000000000047561461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pow, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); exp = n_randtest(state) % UWORD(20); fmpz_poly_pow(a, b, exp); fmpz_poly_pow(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with repeated multiplications by the case */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); exp = n_randtest(state) % UWORD(20); fmpz_poly_pow(a, b, exp); if (exp == UWORD(0)) { fmpz_poly_set_ui(c, 1); } else { ulong j; fmpz_poly_set(c, b); for (j = 1; j < exp; j++) fmpz_poly_mul(c, c, b); } result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pow_addchains.c000066400000000000000000000044671461254215100216430ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pow_addchains, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); exp = n_randtest(state) % UWORD(20); fmpz_poly_pow_addchains(a, b, exp); fmpz_poly_pow_addchains(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with fmpz_poly_pow */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); for (exp = UWORD(0); exp < UWORD(149); exp++) { fmpz_poly_pow_addchains(a, b, exp); fmpz_poly_pow(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pow_binexp.c000066400000000000000000000043451461254215100212050ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pow_binexp, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); exp = n_randtest(state) % UWORD(20); fmpz_poly_pow_binexp(a, b, exp); fmpz_poly_pow_binexp(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL(1):\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with fmpz_poly_pow */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); exp = n_randtest(state) % UWORD(20); fmpz_poly_pow_binexp(a, b, exp); fmpz_poly_pow(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL(2):\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pow_binomial.c000066400000000000000000000046231461254215100215110ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pow_binomial, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init2(b, 2); fmpz_randtest(b->coeffs, state, 100); fmpz_randtest_not_zero(b->coeffs + 1, state, 100); _fmpz_poly_set_length(b, 2); exp = n_randtest(state) % UWORD(100); fmpz_poly_pow_binomial(a, b, exp); fmpz_poly_pow_binomial(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL(1):\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with fmpz_poly_pow */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init2(b, 2); fmpz_randtest(b->coeffs, state, 100); fmpz_randtest_not_zero(b->coeffs + 1, state, 100); _fmpz_poly_set_length(b, 2); exp = n_randtest(state) % UWORD(100); fmpz_poly_pow_binomial(a, b, exp); fmpz_poly_pow(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL(2):\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pow_multinomial.c000066400000000000000000000043711461254215100222510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pow_multinomial, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); exp = n_randtest(state) % UWORD(20); fmpz_poly_pow_multinomial(a, b, exp); fmpz_poly_pow_multinomial(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL(1):\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with fmpz_poly_pow */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong exp; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 10), 100); exp = n_randtest(state) % UWORD(20); fmpz_poly_pow_multinomial(a, b, exp); fmpz_poly_pow(b, b, exp); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL(2):\n"); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pow_trunc.c000066400000000000000000000051171461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pow_trunc, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong n; ulong exp; n = n_randtest(state) % 10; exp = n_randtest(state) % 100; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 100), n); fmpz_poly_pow_trunc(a, b, exp, n); fmpz_poly_pow_trunc(b, b, exp, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); flint_printf("exp = %wu\n", exp); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with powering followed truncating */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n; ulong exp; n = n_randtest(state) % 10; exp = n_randtest(state) % 50; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), n); fmpz_poly_pow(a, b, exp); fmpz_poly_truncate(a, n); fmpz_poly_pow_trunc(c, b, exp, n); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); flint_printf("exp = %wu\n", exp); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-power_sums.c000066400000000000000000000161361461254215100212370ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_power_sums, state) { int i, j, k, l, result; fmpz_t il, jl, kl, tot; slong n; fmpz_poly_t a, b, c, d, e, f; /* Check that it is valid in degree 3 with integer roots, ie */ /* for polynomials of the form (x-i)(x-j)(x-k) */ for (i = -5; i < 5; i++) for (j = i; j < 5; j++) for (k = j; k < 5; k++) { fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_set_coeff_si(a, 0, -i * j * k); fmpz_poly_set_coeff_si(a, 1, i * j + i * k + j * k); fmpz_poly_set_coeff_si(a, 2, -i - j - k); fmpz_poly_set_coeff_si(a, 3, 1); fmpz_poly_power_sums(b, a, 20); fmpz_poly_power_sums_naive(c, a, 20); result = fmpz_poly_equal(b, c); if (!result) { flint_printf("FAIL:\n"); flint_printf("%d %d %d\n\n", i, j, k); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_init(il); fmpz_init(jl); fmpz_init(kl); fmpz_set_ui(il, 1); fmpz_set_ui(jl, 1); fmpz_set_ui(kl, 1); fmpz_init(tot); for (l = 0; l < FLINT_MIN(20, fmpz_poly_length(b)); l++) { fmpz_set(tot, il); fmpz_add(tot, tot, jl); fmpz_add(tot, tot, kl); result = fmpz_equal(fmpz_poly_get_coeff_ptr(b, l), tot); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("%d %d %d %d\n", i, j, k, l); fflush(stdout); flint_abort(); } fmpz_mul_si(il, il, i); fmpz_mul_si(jl, jl, j); fmpz_mul_si(kl, kl, k); } fmpz_poly_power_sums(b, a, 4); fmpz_poly_power_sums_to_poly(c, b); result = fmpz_poly_equal(a, c); if (!result) { flint_printf("FAIL: newton series to poly\n\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); } fmpz_clear(il); fmpz_clear(jl); fmpz_clear(kl); fmpz_clear(tot); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that the various implementations coincide and that */ /* power_sums_to_poly gives back the original polynomial */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_init(e); fmpz_poly_init(f); fmpz_poly_randtest_not_zero(a, state, 1 + n_randint(state, 50), 100); fmpz_poly_set_coeff_ui(a, fmpz_poly_degree(a), 1); for (n = -1; n < 3 * fmpz_poly_degree(a); n += 1 + n_randint(state, fmpz_poly_degree(a))) { fmpz_poly_power_sums(b, a, n); fmpz_poly_power_sums_naive(c, a, n); result = fmpz_poly_equal(b, c); if (!result) { flint_printf ("FAIL: equality power_sums, power_sums_naive\n"); flint_printf("%ld", n); fmpz_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (n >= 1) { /* use the formula PowerSums(p) = rev(poly') / rev(poly) */ fmpz_poly_reverse(e, a, fmpz_poly_length(a)); fmpz_poly_derivative(f, a); fmpz_poly_reverse(f, f, fmpz_poly_length(f)); fmpz_poly_div_series(d, f, e, n); result = fmpz_poly_equal(b, d); if (!result) { flint_printf("FAIL: equality with schoenhage formula\n"); flint_printf("%ld", n); fmpz_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } } fmpz_poly_power_sums(b, a, fmpz_poly_length(a)); fmpz_poly_power_sums_to_poly(c, b); result = fmpz_poly_equal(a, c); if (!result) { flint_printf("FAIL: power_sums_to_poly\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); fmpz_poly_clear(e); fmpz_poly_clear(f); } /* Check that the product of polynomials correspond to the sum of Power sums series */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_init(e); fmpz_poly_init(f); fmpz_poly_randtest_not_zero(a, state, 1 + n_randint(state, 5), 20); fmpz_poly_set_coeff_ui(a, fmpz_poly_degree(a), 1); fmpz_poly_randtest_not_zero(b, state, 1 + n_randint(state, 5), 20); fmpz_poly_set_coeff_ui(b, fmpz_poly_degree(b), 1); fmpz_poly_power_sums(c, a, 20); fmpz_poly_power_sums(d, b, 20); fmpz_poly_add(f, c, d); fmpz_poly_mul(e, a, b); fmpz_poly_power_sums(e, e, 20); result = fmpz_poly_equal(e, f); if (!result) { flint_printf("FAIL: PowerSums(p1 p2) = PowerSums(p1) + PowerSums(p2)\n"); fmpz_poly_print(a), flint_printf("\n"); fmpz_poly_print(b), flint_printf("\n"); fmpz_poly_print(c), flint_printf("\n"); fmpz_poly_print(d), flint_printf("\n"); fmpz_poly_print(e), flint_printf("\n"); fmpz_poly_print(f), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); fmpz_poly_clear(e); fmpz_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-primitive_part.c000066400000000000000000000042101461254215100220600ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_primitive_part, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(g, state, n_randint(state, 100), 200); fmpz_poly_primitive_part(f, g); fmpz_poly_primitive_part(g, g); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check that content(f) primitive_part(f) = sgn(lead(f)) f */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(c); fmpz_poly_randtest_not_zero(f, state, n_randint(state, 100) + 1, 200); fmpz_poly_content(c, f); if (fmpz_sgn(f->coeffs + f->length - 1) < 0) fmpz_neg(c, c); fmpz_poly_primitive_part(g, f); fmpz_poly_scalar_mul_fmpz(g, g, c); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-print_read.c000066400000000000000000000152471461254215100211650ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) # include # include # include #endif #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) TEST_FUNCTION_START(fmpz_poly_print_read, state) { int i, j, n = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; fflush(stdout); /* Ensure buffer does not flow into child process */ /* Randomise n polynomials, write to and read from a pipe */ { fmpz_poly_t *a; a = flint_malloc(n * sizeof(fmpz_poly_t)); for (i = 0; i < n; i++) { fmpz_poly_init(a[i]); fmpz_poly_randtest(a[i], state, 100, 100); } if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if ((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if (childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } for (j = 0; j < n; j++) { r = fmpz_poly_fprint(out, a[j]); if ((j < n - 1) && (r > 0)) r = flint_fprintf(out, "\n"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } } fclose(out); for (i = 0; i < n; ++i) fmpz_poly_clear(a[i]); flint_free(a); exit(0); } else /* Parent process */ { int r; fmpz_poly_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_poly_init(t); i = 0; while (!feof(in)) { r = fmpz_poly_fread(in, t); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Read error.\n"); fflush(stdout); flint_abort(); } result = fmpz_poly_equal(t, a[i]); if (!result) { flint_printf("FAIL:\n"); flint_printf("a[i] = "), fmpz_poly_print(a[i]), flint_printf("\n"); flint_printf("t = "), fmpz_poly_print(t), flint_printf("\n"); fflush(stdout); flint_abort(); } ++i; } fmpz_poly_clear(t); fclose(in); waitpid(childpid, NULL, 0); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); fflush(stdout); flint_abort(); } for (i = 0; i < n; i++) fmpz_poly_clear(a[i]); flint_free(a); } /* Write bad data to a pipe and read it */ { char str[5] = {'b', 'l', 'a', 'h', '\0'}; if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } fclose(out); exit(0); } else /* Parent process */ { int r; fmpz_poly_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_poly_init(t); i = 0; while (!feof(in)) { r = fmpz_poly_fread(in, t); if (r > 0) { flint_printf("FAIL:\n"); flint_printf("r = %d\n", r); fflush(stdout); flint_abort(); } ++i; } fmpz_poly_clear(t); fclose(in); waitpid(childpid, NULL, 0); } /* For {'b','l','a','h','\0'} we expect 5 reads */ if (i != 5) { flint_printf("FAIL:\n"); flint_printf("Carried out %d reads, but \"%s\" has only 4 characters.\n", i, str); fflush(stdout); flint_abort(); } } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(fmpz_poly_print_read, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/fmpz_poly/test/t-print_read_pretty.c000066400000000000000000000161421461254215100225670ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ # undef __STRICT_ANSI__ #endif #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) # include # include # include #endif #include #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) TEST_FUNCTION_START(fmpz_poly_print_read_pretty, state) { int i, j, n = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; fflush(stdout); /* Ensure buffer does not flow into child process */ /* Randomise n polynomials, write to and read from a pipe */ { fmpz_poly_t *a; char *var = "x"; a = flint_malloc(n * sizeof(fmpz_poly_t)); for (i = 0; i < n; i++) { fmpz_poly_init(a[i]); fmpz_poly_randtest(a[i], state, 100, 100); } if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } for (j = 0; j < n; j++) { r = fmpz_poly_fprint_pretty(out, a[j], var); if ((j < n - 1) && (r > 0)) r = flint_fprintf(out, "\n"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } } fclose(out); for (i = 0; i < n; ++i) fmpz_poly_clear(a[i]); flint_free(a); exit(0); } else /* Parent process */ { int r; fmpz_poly_t t; char *rvar; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_poly_init(t); i = 0; while (!feof(in)) { r = fmpz_poly_fread_pretty(in, t, &rvar); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Read error.\n"); fflush(stdout); flint_abort(); } result = fmpz_poly_equal(t, a[i]) && (t->length <= 1 || (strcmp(var, rvar) == 0)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a[i] = "), fmpz_poly_print_pretty(a[i], var), flint_printf("\n"); flint_printf("t = "), fmpz_poly_print_pretty(t, rvar), flint_printf("\n"); flint_printf("rvar = %s\n", rvar); fflush(stdout); flint_abort(); } flint_free(rvar); ++i; } fmpz_poly_clear(t); fclose(in); waitpid(childpid, NULL, 0); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); fflush(stdout); flint_abort(); } for (i = 0; i < n; i++) fmpz_poly_clear(a[i]); flint_free(a); } /* Write "blah" to the pipe and see it read as a variable */ { char str[5] = {'b', 'l', 'a', 'h', '\0'}; if (pipe(fd)) { flint_printf("FAIL:\n"); flint_printf("Failed to set-up the pipe.\n"); fflush(stdout); flint_abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); fflush(stdout); flint_abort(); } if(childpid == 0) /* Child process */ { int r; close(fd[0]); out = fdopen(fd[1], "w"); if (out == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open output file at the pipe.\n"); fflush(stdout); flint_abort(); } r = fputs(str, out); if (r == EOF) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); fflush(stdout); flint_abort(); } fclose(out); exit(0); } else /* Parent process */ { char *rvar = NULL; int r; fmpz_poly_t t; close(fd[1]); in = fdopen(fd[0], "r"); if (in == NULL) { flint_printf("FAIL:\n"); flint_printf("Could not open input file at the pipe.\n"); fflush(stdout); flint_abort(); } fmpz_poly_init(t); while (!feof(in)) { r = fmpz_poly_fread_pretty(in, t, &rvar); result = (r > 0) && rvar && (strcmp(str, rvar) == 0) && (t->length == 2) && (t->coeffs[0] == WORD(0)) && (t->coeffs[1] == WORD(1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("r = %d\n", r); flint_printf("str = {%s}\n", str); flint_printf("rvar = {%s}\n", rvar); flint_printf("t = "), fmpz_poly_print(t), flint_printf("\n"); fflush(stdout); flint_abort(); } if (rvar) flint_free(rvar); } fmpz_poly_clear(t); fclose(in); waitpid(childpid, NULL, 0); } } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(fmpz_poly_print_read_pretty, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/fmpz_poly/test/t-product_roots_fmpq_vec.c000066400000000000000000000036541461254215100236230ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_vec.h" TEST_FUNCTION_START(fmpz_poly_product_roots_fmpq_vec, state) { slong iter; for (iter = 0; iter < 100; iter++) { fmpq * vec; fmpz_poly_t p; fmpq_t res; slong i, n; n = n_randint(state, 100); vec = _fmpq_vec_init(n); _fmpq_vec_randtest(vec, state, n, 100); fmpz_poly_init(p); fmpz_poly_product_roots_fmpq_vec(p, vec, n); if (fmpz_poly_degree(p) != n) { printf("ERROR:\n"); flint_printf("expected degree %wd and got %wd", n, fmpz_poly_degree(p)); printf("vec = "); _fmpq_vec_print(vec, n); printf("\n"); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpq_init(res); for (i = 0; i < n; i++) { fmpz_poly_evaluate_fmpq(res, p, vec + i); if (!fmpq_is_zero(res)) { printf("ERROR:\n"); flint_printf("evaluation at the %wd-th root ", i); fmpq_print(vec + i); printf(" is not zero"); printf("vec = "); _fmpq_vec_print(vec, n); printf("\n"); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } } fmpq_clear(res); _fmpq_vec_clear(vec, n); fmpz_poly_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-product_roots_fmpz_vec.c000066400000000000000000000032701461254215100236260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_product_roots_fmpz_vec, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t P, Q, tmp; fmpz * x; slong j, n, bits; n = n_randint(state, 100); bits = n_randint(state, 10); x = _fmpz_vec_init(n); _fmpz_vec_randtest(x, state, n, bits); fmpz_poly_init(P); fmpz_poly_init(Q); fmpz_poly_init(tmp); fmpz_poly_product_roots_fmpz_vec(P, x, n); fmpz_poly_set_ui(Q, UWORD(1)); for (j = 0; j < n; j++) { fmpz_poly_zero(tmp); fmpz_poly_set_coeff_si(tmp, 1, WORD(-1)); fmpz_poly_set_coeff_fmpz(tmp, 0, x + j); fmpz_poly_neg(tmp, tmp); fmpz_poly_mul(Q, Q, tmp); } result = (fmpz_poly_equal(P, Q)); if (!result) { flint_printf("FAIL (P != Q):\n"); fmpz_poly_print(P), flint_printf("\n\n"); fmpz_poly_print(Q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(P); fmpz_poly_clear(Q); fmpz_poly_clear(tmp); _fmpz_vec_clear(x, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pseudo_div.c000066400000000000000000000067041461254215100211750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pseudo_div, state) { int i, result; /* Check r = a - q * b has small degree, no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, prod; fmpz_t p; ulong d; fmpz_init(p); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_div(q, &d, a, b); fmpz_poly_mul(prod, q, b); fmpz_pow_ui(p, b->coeffs + b->length - 1, d); fmpz_poly_scalar_mul_fmpz(a, a, p); fmpz_poly_sub(r, a, prod); result = (fmpz_poly_length(r) < fmpz_poly_length(b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(prod), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check q and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_div(q, &d, a, b); fmpz_poly_pseudo_div(a, &d, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } /* Check q and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_div(q, &d, a, b); fmpz_poly_pseudo_div(b, &d, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pseudo_divrem_basecase.c000066400000000000000000000131501461254215100235200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pseudo_divrem_basecase, state) { int i, result; /* Check q*b + r = a, no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, prod; fmpz_t p; ulong d; fmpz_init(p); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_basecase(q, r, &d, a, b); fmpz_poly_mul(prod, q, b); fmpz_poly_add(prod, prod, r); fmpz_pow_ui(p, b->coeffs + b->length - 1, d); fmpz_poly_scalar_mul_fmpz(a, a, p); result = (fmpz_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(prod), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check r and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_basecase(q, r, &d, a, b); fmpz_poly_pseudo_divrem_basecase(q, a, &d, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_basecase(q, r, &d, a, b); fmpz_poly_pseudo_divrem_basecase(q, b, &d, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_basecase(q, r, &d, a, b); fmpz_poly_pseudo_divrem_basecase(a, r, &d, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_basecase(q, r, &d, a, b); fmpz_poly_pseudo_divrem_basecase(b, r, &d, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pseudo_divrem_cohen.c000066400000000000000000000134501461254215100230510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pseudo_divrem_cohen, state) { int i, result; /* Check q*b + r = a, no aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, prod; slong d; fmpz_t p; fmpz_init(p); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 80), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 100); fmpz_poly_pseudo_divrem_cohen(q, r, a, b); fmpz_poly_mul(prod, q, b); fmpz_poly_add(prod, prod, r); d = a->length - b->length + 1; d = FLINT_MAX(d, 0); fmpz_pow_ui(p, b->coeffs + b->length - 1, d); fmpz_poly_scalar_mul_fmpz(a, a, p); result = (fmpz_poly_equal(a, prod)); if (!result) { flint_printf("FAIL (correctness):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("prod = "), fmpz_poly_print(prod), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); flint_printf("r = "), fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check r and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 80), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 100); fmpz_poly_pseudo_divrem_cohen(q, r, a, b); fmpz_poly_pseudo_divrem_cohen(q, a, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL (aliasing r, a):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 80), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 100); fmpz_poly_pseudo_divrem_cohen(q, r, a, b); fmpz_poly_pseudo_divrem_cohen(q, b, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL (aliasing r, b):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 80), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 100); fmpz_poly_pseudo_divrem_cohen(q, r, a, b); fmpz_poly_pseudo_divrem_cohen(a, r, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL (aliasing q, a):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 80), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 80) + 1, 100); fmpz_poly_pseudo_divrem_cohen(q, r, a, b); fmpz_poly_pseudo_divrem_cohen(b, r, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL (aliasing q, b):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pseudo_divrem_divconquer.c000066400000000000000000000134761461254215100241440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pseudo_divrem_divconquer, state) { int i, result; /* Check q*b + r = l(b)^d a, no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, prod; fmpz_t p; ulong d; fmpz_init(p); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(prod); fmpz_poly_randtest(a, state, n_randint(state, 200), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_divconquer(q, r, &d, a, b); fmpz_poly_mul(prod, q, b); fmpz_poly_add(prod, prod, r); fmpz_pow_ui(p, b->coeffs + b->length - 1, d); fmpz_poly_scalar_mul_fmpz(a, a, p); result = (fmpz_poly_equal(a, prod)); if (!result) { flint_printf("FAIL (check qb + r = l(b)^d a):\n"); flint_printf("l^d a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("qb + r = "), fmpz_poly_print(prod), flint_printf("\n\n"); flint_printf("q = "), fmpz_poly_print(q), flint_printf("\n\n"); flint_printf("r = "), fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(p); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(prod); } /* Check r and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_divconquer(q, r, &d, a, b); fmpz_poly_pseudo_divrem_divconquer(q, a, &d, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL (alias r and a):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_divconquer(q, r, &d, a, b); fmpz_poly_pseudo_divrem_divconquer(q, b, &d, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL (alias r and b):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_divconquer(q, r, &d, a, b); fmpz_poly_pseudo_divrem_divconquer(a, r, &d, a, b); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL (alias q and a):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } /* Check q and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem_divconquer(q, r, &d, a, b); fmpz_poly_pseudo_divrem_divconquer(b, r, &d, a, b); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL (alias q and b):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pseudo_rem.c000066400000000000000000000065231461254215100211750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pseudo_rem, state) { int i, result; /* Compare with divrem */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, r2; ulong d, d2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(r2); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_divrem(q, r, &d, a, b); fmpz_poly_pseudo_rem(r2, &d2, a, b); result = (fmpz_poly_equal(r, r2) && d == d2); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fmpz_poly_print(r2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(r2); } /* Check r and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_rem(r, &d, a, b); fmpz_poly_pseudo_rem(a, &d, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, r; ulong d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 50); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 50); fmpz_poly_pseudo_rem(r, &d, a, b); fmpz_poly_pseudo_rem(b, &d, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-pseudo_rem_cohen.c000066400000000000000000000065361461254215100223550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_pseudo_rem_cohen, state) { int i, result; /* Compare with q*b + r = a, no aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r1, r2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r1); fmpz_poly_init(r2); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_pseudo_divrem_cohen(q, r1, a, b); fmpz_poly_pseudo_rem_cohen(r2, a, b); result = (fmpz_poly_equal(r1, r2)); if (!result) { flint_printf("FAIL (correctness):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("r1 = "), fmpz_poly_print(r1), flint_printf("\n\n"); flint_printf("r2 = "), fmpz_poly_print(r2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r1); fmpz_poly_clear(r2); } /* Check r and a alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_pseudo_rem_cohen(r, a, b); fmpz_poly_pseudo_rem_cohen(a, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL (aliasing r, a):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 100) + 1, 200); fmpz_poly_pseudo_rem_cohen(r, a, b); fmpz_poly_pseudo_rem_cohen(b, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL (aliasing r, b):\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-randtest_no_real_root.c000066400000000000000000000040711461254215100234150ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_randtest_no_real_root, state) { int iter; for (iter = 0; iter < 5000 * flint_test_multiplier(); iter++) { fmpz_poly_t p; slong len, i; flint_bitcnt_t bits; bits = 1 + n_randint(state, 30); len = 1 + n_randint(state, 20); fmpz_poly_init(p); fmpz_poly_randtest(p, state, 2*len, 2*bits); fmpz_poly_randtest_no_real_root(p, state, len, bits); if (fmpz_poly_length(p) > len) { printf("ERROR:\n"); flint_printf("got length (= %wd) above the requested limit %wd\n", fmpz_poly_length(p), len); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } /* check bit size */ for (i = 0; i < fmpz_poly_length(p); i++) { if (fmpz_bits(p->coeffs + i) > bits) { printf("ERROR:\n"); flint_printf("%wd-th coefficient exceed requested bit size\n", i); printf("p = "); fmpz_poly_print(p); printf("\n"); flint_printf("bits = %wu\n", bits); fflush(stdout); flint_abort(); } } /* check real roots */ if (fmpz_poly_num_real_roots_sturm(p)) { printf("ERROR:\n"); flint_printf("polynomial has real root\n"); printf("p = "); fmpz_poly_print(p); printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-rem_basecase.c000066400000000000000000000064341461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_rem_basecase, state) { int i, result; /* Compare with full division, no aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, r2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(r2); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, a->length + 1) + 1, 100); fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_rem_basecase(r2, a, b); result = (fmpz_poly_equal(r, r2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fmpz_poly_print(r2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(r2); } /* Check r and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_poly_rem_basecase(r, a, b); fmpz_poly_rem_basecase(a, a, b); result = (fmpz_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } /* Check r and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, r; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(r); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_poly_rem_basecase(r, a, b); fmpz_poly_rem_basecase(b, a, b); result = (fmpz_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-rem_powers_precomp.c000066400000000000000000000075641461254215100227500ustar00rootroot00000000000000/* Copyright (C) 2009, 2013 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_rem_powers_precomp, state) { int i, result; /* Compare with full division, no aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, q, r, r2; fmpz_poly_powers_precomp_t b_inv; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(q); fmpz_poly_init(r); fmpz_poly_init(r2); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, a->length + 1) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_divrem_basecase(q, r, a, b); fmpz_poly_powers_precompute(b_inv, b); fmpz_poly_rem_powers_precomp(r2, a, b, b_inv); result = (fmpz_poly_equal(r, r2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fmpz_poly_print(r), flint_printf("\n\n"); fmpz_poly_print(r2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_powers_clear(b_inv); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); fmpz_poly_clear(r2); } /* Check q and a alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_div_basecase(q, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_div_preinv(a, a, b, b_inv); result = (fmpz_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); } /* Check q and b alias */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, b_inv, q; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(b_inv); fmpz_poly_init(q); fmpz_poly_randtest(a, state, n_randint(state, 50), 100); fmpz_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, 100); fmpz_set_ui(b->coeffs + b->length - 1, 1); /* b must be monic */ fmpz_poly_div_basecase(q, a, b); fmpz_poly_preinvert(b_inv, b); fmpz_poly_div_preinv(b, a, b, b_inv); result = (fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-remove.c000066400000000000000000000106701461254215100203260ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_remove, state) { int i, result; /* Check that b divides a*b and that the quotient is a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong e1, e2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); while (b->length == 0 || (b->length == 1 && fmpz_is_pm1(b->coeffs + 0))) fmpz_poly_randtest_not_zero(b, state, n_randint(state, 10) + 1, 100); while (!fmpz_poly_is_one(p)) { fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_gcd(p, a, b); } e1 = n_randint(state, 10); fmpz_poly_pow(p, b, e1); fmpz_poly_mul(p, p, a); e2 = fmpz_poly_remove(q, p, b); result = (e2 == e1 && (e2 == 0 || fmpz_poly_equal(q, a))); if (!result) { flint_printf("FAIL:\n"); flint_printf("e1 = %wd, e2 = %wd\n", e1, e2); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } /* Check aliasing of q with a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong e1, e2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); while (b->length == 0 || (b->length == 1 && fmpz_is_pm1(b->coeffs + 0))) fmpz_poly_randtest_not_zero(b, state, n_randint(state, 10) + 1, 100); while (!fmpz_poly_is_one(p)) { fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_gcd(p, a, b); } e1 = n_randint(state, 10); fmpz_poly_pow(p, b, e1); fmpz_poly_mul(p, p, a); e1 = fmpz_poly_remove(q, p, b); e2 = fmpz_poly_remove(p, p, b); result = (e1 == e2 && fmpz_poly_equal(p, q)); if (!result) { flint_printf("FAIL:\n"); flint_printf("e1 = %wd, e2 = %wd\n", e1, e2); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } /* Check aliasing of q with b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, p, q; slong e1, e2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(p); fmpz_poly_init(q); while (b->length == 0 || (b->length == 1 && fmpz_is_pm1(b->coeffs + 0))) fmpz_poly_randtest_not_zero(b, state, n_randint(state, 10) + 1, 100); while (!fmpz_poly_is_one(p)) { fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_gcd(p, a, b); } e1 = n_randint(state, 10); fmpz_poly_pow(p, b, e1); fmpz_poly_mul(p, p, a); e1 = fmpz_poly_remove(q, p, b); e2 = fmpz_poly_remove(b, p, b); result = (e1 == e2 && fmpz_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); flint_printf("e1 = %wd, e2 = %wd\n", e1, e2); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(p), flint_printf("\n\n"); fmpz_poly_print(q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-remove_content_2exp.c000066400000000000000000000035121461254215100230130ustar00rootroot00000000000000/* Copyright (C) 2016, Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_remove_content_2exp, state) { int iter; for (iter = 0; iter < 1000; iter++) { fmpz_poly_t f, g1, g2, g3; fmpz_poly_init(f); fmpz_poly_init(g1); fmpz_poly_init(g2); fmpz_poly_init(g3); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); _fmpz_poly_remove_content_2exp(f->coeffs, f->length); fmpz_poly_scalar_mul_ui(g1, f, 2); _fmpz_poly_remove_content_2exp(g1->coeffs, g1->length); fmpz_poly_scalar_mul_ui(g2, f, 4); _fmpz_poly_remove_content_2exp(g2->coeffs, g2->length); fmpz_poly_scalar_mul_ui(g3, f, 256); _fmpz_poly_remove_content_2exp(g3->coeffs, g3->length); if ( ! (fmpz_poly_equal(f, g1) && fmpz_poly_equal(f, g2) && fmpz_poly_equal(f, g3)) ) { flint_printf("FAIL:\n"); flint_printf("f = "); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("g1 = "); fmpz_poly_print(g1); flint_printf("\n\n"); flint_printf("g2 = "); fmpz_poly_print(g2); flint_printf("\n\n"); flint_printf("g3 = "); fmpz_poly_print(g3); flint_printf("\n\n"); flint_printf("ERROR \n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g1); fmpz_poly_clear(g2); fmpz_poly_clear(g3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-resultant.c000066400000000000000000000060431461254215100210510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_resultant, state) { int i, result; /* Just one specific test */ { fmpz_poly_t f, g; fmpz_t a, b; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(a); fmpz_init(b); fmpz_poly_set_str(f, "11 -15 -2 -2 17 0 0 6 0 -5 1 -1"); fmpz_poly_set_str(g, "9 2 1 1 1 1 1 0 -1 -2"); fmpz_poly_resultant(a, f, g); fmpz_set_str(b, "-44081924855067", 10); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("res(f, h) = "), fmpz_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(a); fmpz_clear(b); } /* Check that R(fg, h) = R(f, h) R(g, h) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d; fmpz_poly_t f, g, h, p; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(p); fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_randtest(h, state, n_randint(state, 10), 100); fmpz_poly_resultant(a, f, h); fmpz_poly_resultant(b, g, h); fmpz_mul(c, a, b); fmpz_poly_mul(p, f, g); fmpz_poly_resultant(d, p, h); result = (fmpz_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("res(f, h) = "), fmpz_print(a), flint_printf("\n\n"); flint_printf("res(g, h) = "), fmpz_print(b), flint_printf("\n\n"); flint_printf("res(fg, h) = "), fmpz_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-resultant_euclidean.c000066400000000000000000000061251461254215100230630ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_resultant_euclidean, state) { int i, result; /* Just one specific test */ { fmpz_poly_t f, g; fmpz_t a, b; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(a); fmpz_init(b); fmpz_poly_set_str(f, "11 -15 -2 -2 17 0 0 6 0 -5 1 -1"); fmpz_poly_set_str(g, "9 2 1 1 1 1 1 0 -1 -2"); fmpz_poly_resultant_euclidean(a, f, g); fmpz_set_str(b, "-44081924855067", 10); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("res(f, h) = "), fmpz_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(a); fmpz_clear(b); } /* Check that R(fg, h) = R(f, h) R(g, h) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d; fmpz_poly_t f, g, h, p; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(p); fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_randtest(h, state, n_randint(state, 10), 100); fmpz_poly_resultant_euclidean(a, f, h); fmpz_poly_resultant_euclidean(b, g, h); fmpz_mul(c, a, b); fmpz_poly_mul(p, f, g); fmpz_poly_resultant_euclidean(d, p, h); result = (fmpz_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("res(f, h) = "), fmpz_print(a), flint_printf("\n\n"); flint_printf("res(g, h) = "), fmpz_print(b), flint_printf("\n\n"); flint_printf("res(fg, h) = "), fmpz_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-resultant_modular.c000066400000000000000000000061701461254215100225750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_resultant_modular, state) { int i, result; /* Just one specific test */ { fmpz_poly_t f, g; fmpz_t a, b; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(a); fmpz_init(b); fmpz_poly_set_str(f, "11 -15 -2 -2 17 0 0 6 0 -5 1 -1"); fmpz_poly_set_str(g, "9 2 1 1 1 1 1 0 -1 -2"); fmpz_poly_resultant_modular(a, f, g); fmpz_set_str(b, "-44081924855067", 10); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n"); flint_printf("res(f, h) = "), fmpz_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(a); fmpz_clear(b); } /* Check that R(fg, h) = R(f, h) R(g, h) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d; fmpz_poly_t f, g, h, p; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(p); fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_randtest(h, state, n_randint(state, 10), 100); fmpz_poly_resultant_modular(a, f, h); fmpz_poly_resultant_modular(b, g, h); fmpz_mul(c, a, b); fmpz_poly_mul(p, f, g); fmpz_poly_resultant_modular(d, p, h); result = (fmpz_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f(x) = "), fmpz_poly_print_pretty(f, "x"), flint_printf("\n\n"); flint_printf("g(x) = "), fmpz_poly_print_pretty(g, "x"), flint_printf("\n\n"); flint_printf("h(x) = "), fmpz_poly_print_pretty(h, "x"), flint_printf("\n\n"); flint_printf("res(f, h) = "), fmpz_print(a), flint_printf("\n\n"); flint_printf("res(g, h) = "), fmpz_print(b), flint_printf("\n\n"); flint_printf("res(fg, h) = "), fmpz_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-resultant_modular_div.c000066400000000000000000000102211461254215100234270ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_resultant_modular_div, state) { int i, result; /* Just one specific test */ { fmpz_poly_t f, g; fmpz_t a, b, div; slong nbits; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(a); fmpz_init(b); fmpz_init(div); fmpz_poly_set_str(f, "11 -15 -2 -2 17 0 0 6 0 -5 1 -1"); fmpz_poly_set_str(g, "9 2 1 1 1 1 1 0 -1 -2"); fmpz_set_str(div, "11", 10); nbits = 42; fmpz_poly_resultant_modular_div(a, f, g, div, nbits); /* The result is -44081924855067 = -4007447714097 * 11 * We supply 11 and the missing divisor is less then 2^35 */ fmpz_set_str(b, "-4007447714097", 10); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f(x) = "), fmpz_poly_print_pretty(f, "x"), flint_printf("\n\n"); flint_printf("g(x) = "), fmpz_poly_print_pretty(g, "x"), flint_printf("\n\n"); flint_printf("res(f, h)/div = "), fmpz_print(b), flint_printf("\n\n"); flint_printf("res_mod_div(f, h) = "), fmpz_print(a), flint_printf("\n\n"); flint_printf("divr = "), fmpz_print(div), flint_printf("\n\n"); flint_printf("bitsbound = %wd", nbits), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(a); fmpz_clear(b); fmpz_clear(div); } /* Check that R(fg, h) = R(f, h) R(g, h) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d; fmpz_poly_t f, g, h, p; slong nbits; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(p); fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_randtest(h, state, n_randint(state, 50), 100); fmpz_poly_resultant_modular(a, f, h); fmpz_poly_resultant_modular(b, g, h); if (fmpz_is_zero(b) || fmpz_is_zero(a)) { fmpz_clear(b); fmpz_clear(a); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); continue; } fmpz_mul(c, a, b); fmpz_poly_mul(p, f, g); nbits = (slong)fmpz_bits(a) + 1; /* for sign */ fmpz_poly_resultant_modular_div(d, p, h, b, nbits); result = (fmpz_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); flint_printf("p(x) = "), fmpz_poly_print_pretty(p, "x"), flint_printf("\n\n"); flint_printf("h(x) = "), fmpz_poly_print_pretty(h, "x"), flint_printf("\n\n"); flint_printf("res(p, h) = "), fmpz_print(c), flint_printf("\n\n"); flint_printf("res(p, h) = "), fmpz_print(a), flint_printf(" * "), fmpz_print(b), flint_printf("\n\n"); flint_printf("supplied divisor = "), fmpz_print(b), flint_printf("\n\n"); flint_printf("result should be = "), fmpz_print(a), flint_printf("\n\n"); flint_printf("res(p, h)/div = "), fmpz_print(d), flint_printf("\n\n"); flint_printf("bitsbound for result = %wd", nbits), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-reverse.c000066400000000000000000000046601461254215100205060ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_reverse, state) { int i, result; /* Aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 150); fmpz_poly_reverse(a, b, n); fmpz_poly_reverse(b, b, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Correctness (?) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong j, len, n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 150); len = FLINT_MIN(n, b->length); if (len) { fmpz_poly_fit_length(a, n); for (j = 0; j < len; j++) fmpz_set(a->coeffs + (n - len) + j, b->coeffs + (len - 1 - j)); _fmpz_poly_set_length(a, n); _fmpz_poly_normalise(a); } fmpz_poly_reverse(b, b, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-revert_series.c000066400000000000000000000052471461254215100217160ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_revert_series, state) { int i, result; /* Check aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100)); fmpz_poly_set_coeff_ui(g, 0, 0); fmpz_poly_set_coeff_ui(g, 1, 1); if (n_randlimb(state) % 2) fmpz_poly_neg(g, g); /* get -x term */ n = n_randint(state, 50); fmpz_poly_revert_series(f, g, n); fmpz_poly_revert_series(g, g, n); result = (fmpz_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check f(f^(-1)) = id */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h; slong n; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_randtest(g, state, n_randint(state, 50), 10); fmpz_poly_set_coeff_ui(g, 0, 0); fmpz_poly_set_coeff_ui(g, 1, 1); if (n_randlimb(state) % 2) fmpz_poly_neg(g, g); /* get -x term */ n = n_randint(state, 50); fmpz_poly_revert_series(f, g, n); fmpz_poly_compose_series(h, g, f, n); result = ((n <= 1 && fmpz_poly_is_zero(h)) || (h->length == 2 && fmpz_is_zero(h->coeffs + 0) && fmpz_is_one(h->coeffs + 1))); if (!result) { flint_printf("FAIL (comparison):\n"); fmpz_poly_print(f), flint_printf("\n\n"); fmpz_poly_print(g), flint_printf("\n\n"); fmpz_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_abs.c000066400000000000000000000025031461254215100211170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_abs, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_abs(b, a); fmpz_poly_neg(c, a); fmpz_poly_scalar_abs(c, c); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_addmul_fmpz.c000066400000000000000000000065641461254215100226670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_addmul_fmpz, state) { int i, result; /* check dirty entries */ { fmpz_poly_t a, b; fmpz_t two; fmpz_init(two); fmpz_set_ui(two, 2); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_one(a); fmpz_poly_zero(a); fmpz_poly_one(b); fmpz_poly_scalar_addmul_fmpz(a, b, two); fmpz_poly_set_fmpz(b, two); if (!fmpz_poly_equal(a, b)) { flint_printf("FAIL: dirty\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_clear(two); } /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t x; fmpz_init(x); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_randtest(x, state, n_randint(state, 100)); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_set(b, a); fmpz_poly_set(c, a); fmpz_poly_scalar_addmul_fmpz(b, a, x); fmpz_poly_scalar_addmul_fmpz(a, a, x); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL (1):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that b += x*a is the same as c = b + x*a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t x; fmpz_init(x); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_randtest(x, state, n_randint(state, 100)); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_fmpz(c, a, x); fmpz_poly_add(c, b, c); fmpz_poly_scalar_addmul_fmpz(b, a, x); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL (2):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_addmul_si.c000066400000000000000000000065611461254215100223230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_addmul_si, state) { int i, result; /* check dirty entries */ { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_one(a); fmpz_poly_zero(a); fmpz_poly_one(b); fmpz_poly_scalar_addmul_si(a, b, 2); fmpz_poly_set_si(b, 2); if (!fmpz_poly_equal(a, b)) { flint_printf("FAIL: dirty\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong x; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); x = n_randtest_bits(state, FLINT_BITS - 1); if (n_randint(state, 2) == 1) x *= -1; fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_set(b, a); fmpz_poly_set(c, a); fmpz_poly_scalar_addmul_si(b, a, x); fmpz_poly_scalar_addmul_si(a, a, x); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL (1):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = %d", x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that b += x*a is the same as c = b + x*a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong x; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); x = n_randtest_bits(state, FLINT_BITS - 1); if (n_randint(state, 2) == 1) x *= -1; fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_si(c, a, x); fmpz_poly_add(c, b, c); fmpz_poly_scalar_addmul_si(b, a, x); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL (2):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = %d", x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_addmul_ui.c000066400000000000000000000063631461254215100223250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_addmul_ui, state) { int i, result; /* check dirty entries */ { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_one(a); fmpz_poly_zero(a); fmpz_poly_one(b); fmpz_poly_scalar_addmul_ui(a, b, 2); fmpz_poly_set_ui(b, 2); if (!fmpz_poly_equal(a, b)) { flint_printf("FAIL: dirty\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; ulong x; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); x = n_randtest_bits(state, FLINT_BITS); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_set(b, a); fmpz_poly_set(c, a); fmpz_poly_scalar_addmul_ui(b, a, x); fmpz_poly_scalar_addmul_ui(a, a, x); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL (1):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = %u", x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that b += x*a is the same as c = b + x*a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; ulong x; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); x = n_randtest_bits(state, FLINT_BITS); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_ui(c, a, x); fmpz_poly_add(c, b, c); fmpz_poly_scalar_addmul_ui(b, a, x); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL (2):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = %u", x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_mul_fmpz.c000066400000000000000000000043441461254215100222100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_mul_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_t n; fmpz_init(n); fmpz_randtest(n, state, 200); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_fmpz(b, a, n); fmpz_poly_scalar_mul_fmpz(a, a, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n); fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with fmpz_poly_scalar_mul_si */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_t n1; slong n; fmpz_init(n1); n = (slong) n_randbits(state, FLINT_BITS - 1); if (n_randint(state, 2)) n = -n; fmpz_set_si(n1, n); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_fmpz(b, a, n1); fmpz_poly_scalar_mul_si(a, a, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n1); fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_mul_si.c000066400000000000000000000061741461254215100216520ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_mul_si, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong n = z_randtest(state); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_si(b, a, n); fmpz_poly_scalar_mul_si(a, a, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with fmpz_poly_scalar_mul_ui */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong n = n_randbits(state, FLINT_BITS - 1); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_ui(b, a, n); fmpz_poly_scalar_mul_si(a, a, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check (a*n1)*n2 = a*(n1*n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n1 = (slong) n_randbits(state, (SMALL_FMPZ_BITCOUNT_MAX) / 2); slong n2 = (slong) n_randbits(state, (SMALL_FMPZ_BITCOUNT_MAX) / 2); if (n_randint(state, 2)) n1 = -n1; if (n_randint(state, 2)) n2 = -n2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_si(b, a, n1); fmpz_poly_scalar_mul_si(c, b, n2); fmpz_poly_scalar_mul_si(b, a, n1 * n2); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL n1 = %wd, n2 = %wd:\n", n1, n2); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_mul_ui.c000066400000000000000000000043401461254215100216450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_mul_ui, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong n = n_randtest(state); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_ui(b, a, n); fmpz_poly_scalar_mul_ui(a, a, n); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check (a*n1)*n2 = a*(n1*n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; ulong n1 = n_randbits(state, FLINT_BITS / 2); ulong n2 = n_randbits(state, FLINT_BITS / 2); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_ui(b, a, n1); fmpz_poly_scalar_mul_ui(c, b, n2); fmpz_poly_scalar_mul_ui(b, a, n1 * n2); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL n1 = %wu, n2 = %wu:\n", n1, n2); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scalar_submul_fmpz.c000066400000000000000000000055521461254215100227240ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_scalar_submul_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t x; fmpz_init(x); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_randtest(x, state, n_randint(state, 100)); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_set(b, a); fmpz_poly_set(c, a); fmpz_poly_scalar_submul_fmpz(b, a, x); fmpz_poly_scalar_submul_fmpz(a, a, x); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL (1):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check that b += x*a is the same as c = b + x*a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t x; fmpz_init(x); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_randtest(x, state, n_randint(state, 100)); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_scalar_mul_fmpz(c, a, x); fmpz_poly_sub(c, b, c); fmpz_poly_scalar_submul_fmpz(b, a, x); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL (2):\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_print(c), flint_printf("\n\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-scale_2exp.c000066400000000000000000000063371461254215100210630ustar00rootroot00000000000000/* Copyright (C) 2016, Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_scale_2exp, state) { int iter; /* Check that scale(k) followed by scale(-k) is identity */ for (iter = 0; iter < 1000; iter++) { fmpz_poly_t f, g; slong k; k = n_randint(state, 200); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_randtest(f, state, n_randint(state, 100), 200); _fmpz_poly_remove_content_2exp(f->coeffs, f->length); fmpz_poly_set(g, f); _fmpz_poly_scale_2exp(f->coeffs, f->length, k); _fmpz_poly_scale_2exp(f->coeffs, f->length, -k); if ( !fmpz_poly_equal(f, g) ) { flint_printf("FAIL:\n"); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("ERROR\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check consistency with polynomial evaluation */ for (iter = 0; iter < 1000; iter++) { slong k; fmpz_poly_t f, g; fmpz_t a1,a2,res1,res2; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(a1); fmpz_init(a2); fmpz_init(res1); fmpz_init(res2); k = n_randint(state, 30); fmpz_randtest(a2, state, 100); fmpz_mul_2exp(a1, a2, k); /* positive case k */ fmpz_poly_set(g, f); _fmpz_poly_scale_2exp(g->coeffs, g->length, k); fmpz_poly_evaluate_fmpz(res1, f, a1); fmpz_fdiv_q_2exp(res1, res1, fmpz_val2(res1)); fmpz_poly_evaluate_fmpz(res2, g, a2); fmpz_fdiv_q_2exp(res2, res2, fmpz_val2(res2)); if ( !fmpz_equal(res1, res2) ) { flint_printf("FAIL:\n"); flint_printf("f = "); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("g = "); fmpz_poly_print(g); flint_printf("\n\n"); flint_printf("ERROR\n"); fflush(stdout); flint_abort(); } /* negative case -k */ fmpz_poly_set(g, f); _fmpz_poly_scale_2exp(g->coeffs, g->length, -k); fmpz_poly_evaluate_fmpz(res1, f, a2); fmpz_fdiv_q_2exp(res2, res2, fmpz_val2(res2)); fmpz_poly_evaluate_fmpz(res1, g, a1); fmpz_fdiv_q_2exp(res1, res1, fmpz_val2(res1)); if ( !fmpz_equal(res1, res2) ) { flint_printf("FAIL:\n"); flint_printf("f = "); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("g = "); fmpz_poly_print(g); flint_printf("\n\n"); flint_printf("ERROR\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(a1); fmpz_clear(a2); fmpz_clear(res1); fmpz_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-set_equal.c000066400000000000000000000041201461254215100210040ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_set_equal, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_set(b, a); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong coeff = n_randint(state, 100); fmpz_t x1, x2; fmpz_init(x1); fmpz_init(x2); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_set(b, a); fmpz_poly_get_coeff_fmpz(x2, b, coeff); do fmpz_randtest(x1, state, 200); while (fmpz_equal(x1, x2)); fmpz_poly_set_coeff_fmpz(b, coeff, x1); result = (!fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x1); fmpz_clear(x2); fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-set_fmpz_equal.c000066400000000000000000000045331461254215100220500ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_set_fmpz_equal, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_t n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_init(n); fmpz_randtest(n, state, 200); fmpz_poly_set_fmpz(a, n); fmpz_poly_set(b, a); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = "), fmpz_print(n), flint_printf("\n\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_clear(n); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_t m, n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_init(m); fmpz_init(n); fmpz_randtest(m, state, 200); fmpz_randtest(n, state, 200); while (fmpz_equal(m, n)) fmpz_randtest(n, state, 200); fmpz_poly_set_fmpz(a, m); fmpz_poly_set_fmpz(b, n); result = (!fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("m = "), fmpz_print(m), flint_printf("\n\n"); flint_printf("n = "), fmpz_print(n), flint_printf("\n\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_clear(m); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-set_si_equal.c000066400000000000000000000041541461254215100215060ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_set_si_equal, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong n; fmpz_poly_init(a); fmpz_poly_init(b); n = z_randtest(state); fmpz_poly_set_si(a, n); fmpz_poly_set(b, a); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n\n", n); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong m, n; fmpz_poly_init(a); fmpz_poly_init(b); m = z_randtest(state); n = z_randtest(state); while (m == n) n = z_randtest(state); fmpz_poly_set_si(a, m); fmpz_poly_set_si(b, n); result = (!fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("m = %wd\n\n", m); flint_printf("n = %wd\n\n", n); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-set_trunc.c000066400000000000000000000034131461254215100210340ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_set_trunc, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 50); fmpz_poly_set_trunc(b, a, n); fmpz_poly_set(c, a); fmpz_poly_truncate(c, n); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_set_trunc(a, a, n); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL (aliasing):\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-set_ui_equal.c000066400000000000000000000041231461254215100215040ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_set_ui_equal, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong n; fmpz_poly_init(a); fmpz_poly_init(b); n = n_randtest(state); fmpz_poly_set_ui(a, n); fmpz_poly_set(b, a); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wu\n\n", n); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; ulong m, n; fmpz_poly_init(a); fmpz_poly_init(b); m = n_randtest(state); n = n_randtest(state); while (m == n) n = n_randtest(state); fmpz_poly_set_ui(a, m); fmpz_poly_set_ui(b, n); result = (!fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("m = %wu\n\n", m); flint_printf("n = %wu\n\n", n); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-shift_left_right.c000066400000000000000000000056131461254215100223560ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_shift_left_right, state) { int i, result; /* Check aliasing of a and b for left shift */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong shift = n_randint(state, 100); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_shift_left(b, a, shift); fmpz_poly_shift_left(a, a, shift); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check aliasing of a and b for right shift */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong shift; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest_not_zero(a, state, n_randint(state, 100) + 1, 200); shift = n_randint(state, a->length); fmpz_poly_shift_right(b, a, shift); fmpz_poly_shift_right(a, a, shift); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Check shift left then right does nothing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong shift = n_randint(state, 100); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_shift_left(b, a, shift); fmpz_poly_shift_right(c, b, shift); result = (fmpz_poly_equal(c, a)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-signature.c000066400000000000000000000107611461254215100210330ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_signature, state) { int i, j, result; for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t poly, linear, quadratic, rem; fmpz_t lhs, rhs; slong nreal, ncomplex, nreal_max, ncomplex_max, r1, r2; slong len = n_randint(state, 20) + 1; flint_bitcnt_t bits = n_randint(state, 50) + 1; fmpz_poly_init2(poly, len); fmpz_poly_init2(linear, 2); fmpz_poly_init2(quadratic, 3); fmpz_poly_init2(rem, len); linear->length = 2; quadratic->length = 3; fmpz_init(lhs); fmpz_init(rhs); ncomplex_max = n_randint(state, len) / 2; nreal_max = len - 2 * ncomplex_max; ncomplex = 0; nreal = 0; fmpz_poly_set_coeff_si(poly, 0, 1); for (j = 0; j < ncomplex_max; j++) { fmpz * a = quadratic->coeffs + 2; fmpz * b = quadratic->coeffs + 1; fmpz * c = quadratic->coeffs; /* Form a quadratic polynomial with complex roots: b^2 < 4ac */ fmpz_randtest_not_zero(c, state, bits); fmpz_randtest(b, state, bits); fmpz_randtest_unsigned(a, state, bits); if (fmpz_sgn(c) < 0) { fmpz_neg(c, c); fmpz_neg(b, b); } fmpz_mul_ui(rhs, c, 4); fmpz_mul(lhs, b, b); fmpz_add(lhs, lhs, rhs); fmpz_fdiv_q(lhs, lhs, rhs); fmpz_add(a, a, lhs); /* If quadratic does not divide poly over Q, set poly *= complex */ fmpz_poly_pseudo_rem_cohen(rem, poly, quadratic); if (rem->length > 0) { fmpz_poly_mul(poly, poly, quadratic); ncomplex++; } } for (j = 0; j < nreal_max; j++) { /* Form a linear polynomial */ fmpz_randtest(linear->coeffs, state, bits); fmpz_randtest_not_zero(linear->coeffs + 1, state, bits); /* If linear does not divide poly over Q, set poly *= linear */ fmpz_poly_pseudo_rem_cohen(rem, poly, linear); if (rem->length > 0) { fmpz_poly_mul(poly, poly, linear); nreal++; } } fmpz_poly_signature(&r1, &r2, poly); result = ((r1 == nreal) && (r2 == ncomplex)); if (!result) { flint_printf("FAIL:\n"); flint_printf("poly = "), fmpz_poly_print(poly), flint_printf("\n\n"); flint_printf("r1 r2 = %wd %wd\n\n", r1, r2); fflush(stdout); flint_abort(); } fmpz_poly_clear(poly); fmpz_poly_clear(linear); fmpz_poly_clear(quadratic); fmpz_poly_clear(rem); fmpz_clear(lhs); fmpz_clear(rhs); } { fmpz_poly_t poly; slong r1, r2; fmpz_poly_init(poly); fmpz_poly_set_str(poly, "6 1 1 1 10 5 1"); fmpz_poly_signature(&r1, &r2, poly); result = ((r1 == 1) && (r2 == 2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("poly = "), fmpz_poly_print(poly), flint_printf("\n\n"); flint_printf("r1 r2 = %wd %wd\n\n", r1, r2); fflush(stdout); flint_abort(); } fmpz_poly_clear(poly); } for (i = 0; i < 50; i++) { slong r, s; fmpz_poly_t poly; fmpz_poly_init(poly); fmpz_poly_cyclotomic(poly, i + 3); fmpz_poly_signature(&r, &s, poly); result = (r == 0 && s == (fmpz_poly_length(poly) - 1)/2); if (!result) { flint_printf("FAIL:\n"); flint_printf("Cyclotomic(%ld) has signature (%ld, %ld)\n", i + 3, r, s); flint_printf("Expected signature (%ld, %ld)\n", 0, (fmpz_poly_length(poly) - 1)/2); fflush(stdout); flint_abort(); } fmpz_poly_clear(poly); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqr.c000066400000000000000000000062351461254215100176400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqr, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 50), 500); fmpz_poly_set(b, a); fmpz_poly_sqr(c, b); fmpz_poly_sqr(b, b); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 500); fmpz_poly_sqr(b, a); fmpz_poly_mul(c, a, a); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check _fmpz_poly_sqr directly */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; fmpz_poly_t a, out1, out2; len = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len, 200); fmpz_poly_sqr(out1, a); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); a->length = a->alloc; fmpz_poly_fit_length(out2, 2 * a->length - 1); _fmpz_poly_sqr(out2->coeffs, a->coeffs, a->length); _fmpz_poly_set_length(out2, 2 * a->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqr_KS.c000066400000000000000000000077361461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqr_KS, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 50), 200); fmpz_poly_set(b, a); fmpz_poly_sqr_KS(c, b); fmpz_poly_sqr_KS(b, b); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 50), 200); fmpz_poly_sqr_KS(b, a); fmpz_poly_sqr_classical(c, a); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_classical unsigned */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest_unsigned(a, state, n_randint(state, 50), 200); fmpz_poly_sqr_KS(b, a); fmpz_poly_sqr_classical(c, a); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check _fmpz_poly_sqr_KS directly */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; fmpz_poly_t a, out1, out2; len = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len, 200); fmpz_poly_sqr_KS(out1, a); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); a->length = a->alloc; fmpz_poly_fit_length(out2, 2 * a->length - 1); _fmpz_poly_sqr_KS(out2->coeffs, a->coeffs, a->length); _fmpz_poly_set_length(out2, 2 * a->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqr_classical.c000066400000000000000000000041011461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqr_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_sqr_classical(a, b); fmpz_poly_sqr_classical(b, b); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with mul_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 50), 200); fmpz_poly_set(b, a); fmpz_poly_sqr_classical(c, b); fmpz_poly_mul_classical(b, b, b); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqr_karatsuba.c000066400000000000000000000063661461254215100217020ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqr_karatsuba, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 50), 200); fmpz_poly_set(b, a); fmpz_poly_sqr_karatsuba(c, b); fmpz_poly_sqr_karatsuba(b, b); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_karatsuba */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 50), 200); fmpz_poly_sqr_karatsuba(b, a); fmpz_poly_mul_karatsuba(c, a, a); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check _fmpz_poly_sqr_karatsuba directly */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; fmpz_poly_t a, out1, out2; len = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len, 200); fmpz_poly_sqr_karatsuba(out1, a); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); a->length = a->alloc; fmpz_poly_fit_length(out2, 2 * a->length - 1); _fmpz_poly_sqr_karatsuba(out2->coeffs, a->coeffs, a->length); _fmpz_poly_set_length(out2, 2 * a->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrlow.c000066400000000000000000000044331461254215100203600ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrlow, state) { int i, result; /* Check aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length); fmpz_poly_sqrlow(a, b, trunc); fmpz_poly_sqrlow(b, b, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with sqr */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length - 1); fmpz_poly_sqr(a, b); fmpz_poly_truncate(a, trunc); fmpz_poly_sqrlow(c, b, trunc); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrlow_KS.c000066400000000000000000000044551461254215100207610ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrlow_KS, state) { int i, result; /* Check aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length); fmpz_poly_sqrlow_KS(a, b, trunc); fmpz_poly_sqrlow_KS(b, b, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with sqr_KS */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length - 1); fmpz_poly_sqr_KS(a, b); fmpz_poly_truncate(a, trunc); fmpz_poly_sqrlow_KS(c, b, trunc); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrlow_classical.c000066400000000000000000000045321461254215100223760ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrlow_classical, state) { int i, result; /* Check aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length); fmpz_poly_sqrlow_classical(a, b, trunc); fmpz_poly_sqrlow_classical(b, b, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with sqr_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length - 1); fmpz_poly_mul_classical(a, b, b); fmpz_poly_truncate(a, trunc); fmpz_poly_sqrlow_classical(c, b, trunc); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrlow_karatsuba_n.c000066400000000000000000000045371461254215100227370ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrlow_karatsuba_n, state) { int i, result; /* Check aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length); fmpz_poly_sqrlow_karatsuba_n(a, b, trunc); fmpz_poly_sqrlow_karatsuba_n(b, b, trunc); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Compare with sqr_karatsuba */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong len, trunc; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); len = 2 * b->length - 1; trunc = (len <= 0) ? 0 : n_randint(state, 2 * b->length - 1); fmpz_poly_sqr_karatsuba(a, b); fmpz_poly_truncate(a, trunc); fmpz_poly_sqrlow_karatsuba_n(c, b, trunc); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrt.c000066400000000000000000000107221461254215100200200ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrt, state) { int i; /* Test aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; int square1, square2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); if (n_randint(state, 2)) fmpz_poly_sqr(a, a); square1 = fmpz_poly_sqrt(b, a); square2 = fmpz_poly_sqrt(a, a); if ((square1 != square2) || (square1 && !fmpz_poly_equal(a, b))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); square = fmpz_poly_sqrt(c, b); if (!square) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (!fmpz_poly_is_zero(c) && fmpz_sgn(fmpz_poly_get_coeff_ptr(c, fmpz_poly_degree(c))) < 0) { flint_printf("FAIL: leading coefficient not positive:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_sqr(c, c); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Test "almost" squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t t; slong j; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_init(t); fmpz_poly_randtest_not_zero(a, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); j = n_randint(state, fmpz_poly_length(b)); fmpz_randtest_not_zero(t, state, 1 + n_randint(state, 100)); fmpz_add(b->coeffs + j, b->coeffs + j, t); _fmpz_poly_normalise(b); square = fmpz_poly_sqrt(c, b); if (square) { fmpz_poly_sqr(c, c); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrt_KS.c000066400000000000000000000111211461254215100204070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrt_KS, state) { int i; /* Test aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; int square1, square2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); if (n_randint(state, 2)) fmpz_poly_sqr(a, a); square1 = fmpz_poly_sqrt_KS(b, a); square2 = fmpz_poly_sqrt_KS(a, a); if ((square1 != square2) || (square1 == 1 && !fmpz_poly_equal(a, b))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); square = fmpz_poly_sqrt_KS(c, b); if (square == 0) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (square == 1 && !fmpz_poly_is_zero(c) && fmpz_sgn(fmpz_poly_get_coeff_ptr(c, fmpz_poly_degree(c))) < 0) { flint_printf("FAIL: leading coefficient not positive:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (square == 1) fmpz_poly_sqr(c, c); if (square == 1 && !fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Test "almost" squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t t; slong j; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_init(t); fmpz_poly_randtest_not_zero(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); j = n_randint(state, fmpz_poly_length(b)); fmpz_randtest_not_zero(t, state, 1 + n_randint(state, 100)); fmpz_add(b->coeffs + j, b->coeffs + j, t); _fmpz_poly_normalise(b); square = fmpz_poly_sqrt_KS(c, b); if (square == 1) { fmpz_poly_sqr(c, c); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrt_classical.c000066400000000000000000000110501461254215100220310ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrt_classical, state) { int i; /* Test aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; int square1, square2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); if (n_randint(state, 2)) fmpz_poly_sqr(a, a); square1 = fmpz_poly_sqrt_classical(b, a); square2 = fmpz_poly_sqrt_classical(a, a); if ((square1 != square2) || (square1 && !fmpz_poly_equal(a, b))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); square = fmpz_poly_sqrt_classical(c, b); if (!square) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (!fmpz_poly_is_zero(c) && fmpz_sgn(fmpz_poly_get_coeff_ptr(c, fmpz_poly_degree(c))) < 0) { flint_printf("FAIL: leading coefficient not positive:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_sqr(c, c); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Test "almost" squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t t; slong j; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_init(t); fmpz_poly_randtest_not_zero(a, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); j = n_randint(state, fmpz_poly_length(b)); fmpz_randtest_not_zero(t, state, 1 + n_randint(state, 100)); fmpz_add(b->coeffs + j, b->coeffs + j, t); _fmpz_poly_normalise(b); square = fmpz_poly_sqrt_classical(c, b); if (square) { fmpz_poly_sqr(c, c); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrt_divconquer.c000066400000000000000000000110601461254215100222530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrt_divconquer, state) { int i; /* Test aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; int square1, square2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); if (n_randint(state, 2)) fmpz_poly_sqr(a, a); square1 = fmpz_poly_sqrt_divconquer(b, a); square2 = fmpz_poly_sqrt_divconquer(a, a); if ((square1 != square2) || (square1 && !fmpz_poly_equal(a, b))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); square = fmpz_poly_sqrt_divconquer(c, b); if (!square) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (!fmpz_poly_is_zero(c) && fmpz_sgn(fmpz_poly_get_coeff_ptr(c, fmpz_poly_degree(c))) < 0) { flint_printf("FAIL: leading coefficient not positive:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_sqr(c, c); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Test "almost" squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t t; slong j; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_init(t); fmpz_poly_randtest_not_zero(a, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); fmpz_poly_sqr(b, a); j = n_randint(state, fmpz_poly_length(b)); fmpz_randtest_not_zero(t, state, 1 + n_randint(state, 100)); fmpz_add(b->coeffs + j, b->coeffs + j, t); _fmpz_poly_normalise(b); square = fmpz_poly_sqrt_divconquer(c, b); if (square) { fmpz_poly_sqr(c, c); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrt_series.c000066400000000000000000000104761461254215100214000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrt_series, state) { int i; /* Test aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; slong n; int square1, square2; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_randtest(a, state, 1 + n_randint(state, 150), 1 + n_randint(state, 200)); if (n_randint(state, 2)) fmpz_poly_sqr(a, a); n = n_randint(state, 20); square1 = fmpz_poly_sqrt_series(b, a, n); square2 = fmpz_poly_sqrt_series(a, a, n); if ((square1 != square2) || (square1 && !fmpz_poly_equal(a, b))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, 1 + n_randint(state, 150), 1 + n_randint(state, 200)); n = n_randint(state, fmpz_poly_length(a)); fmpz_poly_mullow(b, a, a, n); square = fmpz_poly_sqrt_series(c, b, n); if (!square) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_mullow(c, c, c, n); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Test "almost" squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t t; slong j, n; int square; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_init(t); do { fmpz_poly_randtest_not_zero(a, state, 1 + n_randint(state, 150), 1 + n_randint(state, 200)); n = n_randint(state, fmpz_poly_length(a) + 1); fmpz_poly_mullow(b, a, a, n); } while (fmpz_poly_length(b) == 0); j = n_randint(state, fmpz_poly_length(b)); fmpz_randtest_not_zero(t, state, 1 + n_randint(state, 100)); fmpz_add(b->coeffs + j, b->coeffs + j, t); _fmpz_poly_normalise(b); square = fmpz_poly_sqrt_series(c, b, n); if (square) { fmpz_poly_mullow(c, c, c, n); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrtrem_classical.c000066400000000000000000000150101461254215100225350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrtrem_classical, state) { int i; /* Test aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, r1, r2; int sqrtrem1, sqrtrem2; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(r1); fmpz_poly_init(r2); len = n_randint(state, 20); do { fmpz_poly_randtest(a, state, len + 1, 1 + n_randint(state, 200)); fmpz_poly_randtest(c, state, len, 1 + n_randint(state, 200)); } while (fmpz_poly_length(a) == fmpz_poly_length(c)); if (fmpz_poly_length(a) < fmpz_poly_length(c)) fmpz_poly_swap(a, c); if (n_randint(state, 2)) { fmpz_poly_sqr(a, a); fmpz_poly_add(a, a, c); } sqrtrem1 = fmpz_poly_sqrtrem_classical(b, r1, a); sqrtrem2 = fmpz_poly_sqrtrem_classical(a, r2, a); if ((sqrtrem1 != sqrtrem2) || (sqrtrem1 && (!fmpz_poly_equal(a, b) || !fmpz_poly_equal(r1, r2)))) { flint_printf("FAIL: aliasing:\n"); flint_printf("sqrtrem1 = %d, sqrtrem2 = %d\n\n", sqrtrem1, sqrtrem2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r1); fmpz_poly_clear(r2); } /* Test aliasing of a and r */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, r; int sqrtrem1, sqrtrem2; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(r); len = n_randint(state, 20); do { fmpz_poly_randtest(a, state, len + 1, 1 + n_randint(state, 200)); fmpz_poly_randtest(c, state, len, 1 + n_randint(state, 200)); } while (fmpz_poly_length(a) == fmpz_poly_length(c)); if (fmpz_poly_length(a) < fmpz_poly_length(c)) fmpz_poly_swap(a, c); if (n_randint(state, 2)) { fmpz_poly_sqr(a, a); fmpz_poly_add(a, a, c); } sqrtrem1 = fmpz_poly_sqrtrem_classical(b, r, a); sqrtrem2 = fmpz_poly_sqrtrem_classical(c, a, a); if ((sqrtrem1 != sqrtrem2) || (sqrtrem1 && (!fmpz_poly_equal(a, r) || !fmpz_poly_equal(b, c)))) { flint_printf("FAIL: aliasing2:\n"); flint_printf("sqrtrem1 = %d, sqrtrem2 = %d\n\n", sqrtrem1, sqrtrem2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r: "); fmpz_poly_print(r); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r); } /* Test random squares with remainder */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, r1, r2; int sqrtrem; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(r1); fmpz_poly_init(r2); len = n_randint(state, 20); do { fmpz_poly_randtest(a, state, len + 1, 1 + n_randint(state, 200)); fmpz_poly_randtest(r1, state, len, 1 + n_randint(state, 200)); } while (fmpz_poly_length(a) == fmpz_poly_length(r1)); if (fmpz_poly_length(a) < fmpz_poly_length(r1)) fmpz_poly_swap(a, r1); fmpz_poly_sqr(b, a); fmpz_poly_add(b, b, r1); sqrtrem = fmpz_poly_sqrtrem_classical(c, r2, b); if (!sqrtrem) { flint_printf("FAIL: sqrtrem returns false:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (!fmpz_poly_is_zero(c) && fmpz_sgn(fmpz_poly_get_coeff_ptr(c, fmpz_poly_degree(c))) < 0) { flint_printf("FAIL: leading coefficient not positive:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_sqr(c, c); fmpz_poly_add(c, c, r2); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 + r != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r1); fmpz_poly_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sqrtrem_divconquer.c000066400000000000000000000150211461254215100227600ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2018 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sqrtrem_divconquer, state) { int i; /* Test aliasing of a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, r1, r2; int sqrtrem1, sqrtrem2; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(r1); fmpz_poly_init(r2); len = n_randint(state, 150); do { fmpz_poly_randtest(a, state, len + 1, 1 + n_randint(state, 200)); fmpz_poly_randtest(c, state, len, 1 + n_randint(state, 200)); } while (fmpz_poly_length(a) == fmpz_poly_length(c)); if (fmpz_poly_length(a) < fmpz_poly_length(c)) fmpz_poly_swap(a, c); if (n_randint(state, 2)) { fmpz_poly_sqr(a, a); fmpz_poly_add(a, a, c); } sqrtrem1 = fmpz_poly_sqrtrem_divconquer(b, r1, a); sqrtrem2 = fmpz_poly_sqrtrem_divconquer(a, r2, a); if ((sqrtrem1 != sqrtrem2) || (sqrtrem1 && (!fmpz_poly_equal(a, b) || !fmpz_poly_equal(r1, r2)))) { flint_printf("FAIL: aliasing:\n"); flint_printf("sqrtrem1 = %d, sqrtrem2 = %d\n\n", sqrtrem1, sqrtrem2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r1); fmpz_poly_clear(r2); } /* Test aliasing of a and r */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, r; int sqrtrem1, sqrtrem2; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(r); len = n_randint(state, 150); do { fmpz_poly_randtest(a, state, len + 1, 1 + n_randint(state, 200)); fmpz_poly_randtest(c, state, len, 1 + n_randint(state, 200)); } while (fmpz_poly_length(a) == fmpz_poly_length(c)); if (fmpz_poly_length(a) < fmpz_poly_length(c)) fmpz_poly_swap(a, c); if (n_randint(state, 2)) { fmpz_poly_sqr(a, a); fmpz_poly_add(a, a, c); } sqrtrem1 = fmpz_poly_sqrtrem_divconquer(b, r, a); sqrtrem2 = fmpz_poly_sqrtrem_divconquer(c, a, a); if ((sqrtrem1 != sqrtrem2) || (sqrtrem1 && (!fmpz_poly_equal(a, r) || !fmpz_poly_equal(b, c)))) { flint_printf("FAIL: aliasing2:\n"); flint_printf("sqrtrem1 = %d, sqrtrem2 = %d\n\n", sqrtrem1, sqrtrem2); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r: "); fmpz_poly_print(r); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r); } /* Test random squares with remainder */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, r1, r2; int sqrtrem; slong len; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(r1); fmpz_poly_init(r2); len = n_randint(state, 150); do { fmpz_poly_randtest(a, state, len + 1, 1 + n_randint(state, 200)); fmpz_poly_randtest(r1, state, len, 1 + n_randint(state, 200)); } while (fmpz_poly_length(a) == fmpz_poly_length(r1)); if (fmpz_poly_length(a) < fmpz_poly_length(r1)) fmpz_poly_swap(a, r1); fmpz_poly_sqr(b, a); fmpz_poly_add(b, b, r1); sqrtrem = fmpz_poly_sqrtrem_divconquer(c, r2, b); if (!sqrtrem) { flint_printf("FAIL: sqrtrem returns false:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (!fmpz_poly_is_zero(c) && fmpz_sgn(fmpz_poly_get_coeff_ptr(c, fmpz_poly_degree(c))) < 0) { flint_printf("FAIL: leading coefficient not positive:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_sqr(c, c); fmpz_poly_add(c, c, r2); if (!fmpz_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 + r != b:\n"); flint_printf("a: "); fmpz_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); fmpz_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); fmpz_poly_print(c); flint_printf("\n\n"); flint_printf("r1: "); fmpz_poly_print(r1); flint_printf("\n\n"); flint_printf("r2: "); fmpz_poly_print(r2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r1); fmpz_poly_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sub.c000066400000000000000000000062231461254215100176210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sub, state) { int i, result; /* Check a - b = a + neg(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_sub(c, a, b); fmpz_poly_neg(b, b); fmpz_poly_add(d, a, b); result = (fmpz_poly_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_sub(c, a, b); fmpz_poly_sub(a, a, b); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_sub(c, a, b); fmpz_poly_sub(b, a, b); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-sub_series.c000066400000000000000000000067211461254215100211760ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_sub_series, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); fmpz_poly_sub_series(c, a, b, n); fmpz_poly_sub_series(a, a, b, n); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); fmpz_poly_sub_series(c, a, b, n); fmpz_poly_sub_series(b, a, b, n); result = (fmpz_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check truncate(a + b, n) = add_series(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; slong n; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); n = n_randint(state, 100); fmpz_poly_sub(c, a, b); fmpz_poly_truncate(c, n); fmpz_poly_sub_series(d, a, b, n); result = (fmpz_poly_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-swap.c000066400000000000000000000025251461254215100200030ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_swap, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); fmpz_poly_randtest(b, state, n_randint(state, 100), 200); fmpz_poly_set(c, b); fmpz_poly_swap(a, b); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-swinnerton_dyer.c000066400000000000000000000023561461254215100222640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" static const mp_limb_t known_values[] = { UWORD(2147483629), UWORD(1073742093), UWORD(1342248677), UWORD(3319936736), UWORD(2947821228), UWORD(1019513834), UWORD(3324951530), UWORD(1995039408), UWORD(3505683295), UWORD(3567639420), UWORD(394942914) }; TEST_FUNCTION_START(fmpz_poly_swinnerton_dyer, state) { fmpz_poly_t S; mp_limb_t r; slong n; for (n = 0; n <= 10; n++) { fmpz_poly_init(S); fmpz_poly_swinnerton_dyer(S, n); r = fmpz_poly_evaluate_mod(S, UWORD(2147483629), UWORD(4294967291)); if (r != known_values[n]) { flint_printf("ERROR: wrong evaluation of S_%wd\n", n); fflush(stdout); flint_abort(); } fmpz_poly_clear(S); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-taylor_shift.c000066400000000000000000000047431461254215100215440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_taylor_shift, state) { int i; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(c); fmpz_poly_randtest(f, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_poly_taylor_shift(g, f, c); fmpz_poly_taylor_shift(f, f, c); if (!fmpz_poly_equal(g, f)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(c); } /* Compare with composition */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h1, h2; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h1); fmpz_poly_init(h2); fmpz_init(c); fmpz_poly_randtest(f, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_poly_set_coeff_ui(g, 1, 1); fmpz_poly_set_coeff_fmpz(g, 0, c); fmpz_poly_taylor_shift(h1, f, c); fmpz_poly_compose(h2, f, g); if (!fmpz_poly_equal(h1, h2)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fmpz_poly_print(h1); flint_printf("\n"); fmpz_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-taylor_shift_divconquer.c000066400000000000000000000037531461254215100240030ustar00rootroot00000000000000/* Copyright (C) 2012, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_taylor_shift_divconquer, state) { int i; /* Compare with composition */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h1, h2; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h1); fmpz_poly_init(h2); fmpz_init(c); fmpz_poly_randtest(f, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 400)); fmpz_randtest(c, state, n_randint(state, 10)); fmpz_poly_set_coeff_ui(g, 1, 1); fmpz_poly_set_coeff_fmpz(g, 0, c); flint_set_num_threads(1 + n_randint(state, 3)); if (n_randint(state, 2)) { fmpz_poly_taylor_shift_divconquer(h1, f, c); } else { fmpz_poly_set(h1, f); fmpz_poly_taylor_shift_divconquer(h1, h1, c); } flint_set_num_threads(1); fmpz_poly_compose_divconquer(h2, f, g); if (!fmpz_poly_equal(h1, h2)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fmpz_poly_print(h1); flint_printf("\n"); fmpz_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-taylor_shift_horner.c000066400000000000000000000077771461254215100231330ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" static void _taylor_simple(fmpz * poly, const fmpz_t c, slong n) { slong i, j; for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) fmpz_addmul(poly + j, poly + j + 1, c); } static void taylor_simple(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c) { if (f != g) fmpz_poly_set(g, f); _taylor_simple(g->coeffs, c, g->length); } TEST_FUNCTION_START(fmpz_poly_taylor_shift_horner, state) { int i; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(c); fmpz_poly_randtest(f, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_poly_taylor_shift_horner(g, f, c); fmpz_poly_taylor_shift_horner(f, f, c); if (!fmpz_poly_equal(g, f)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(c); } /* Compare with composition */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h1, h2; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h1); fmpz_poly_init(h2); fmpz_init(c); fmpz_poly_randtest(f, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_poly_set_coeff_ui(g, 1, 1); fmpz_poly_set_coeff_fmpz(g, 0, c); fmpz_poly_taylor_shift_horner(h1, f, c); fmpz_poly_compose(h2, f, g); if (!fmpz_poly_equal(h1, h2)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fmpz_poly_print(h1); flint_printf("\n"); fmpz_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } /* Shift by 1 and -1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t f, h1, h2; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(h1); fmpz_poly_init(h2); fmpz_init(c); if (n_randint(state, 30)) fmpz_poly_randtest(f, state, 1 + n_randint(state, 100), 1 + n_randint(state, 10000)); else fmpz_poly_randtest(f, state, 1 + n_randint(state, 100), 1 + n_randint(state, 200)); fmpz_set_si(c, n_randint(state, 2) ? 1 : -1); fmpz_poly_taylor_shift_horner(h1, f, c); fmpz_neg(c, c); taylor_simple(h2, h1, c); if (!fmpz_poly_equal(f, h2)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(h1); flint_printf("\n"); fmpz_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-taylor_shift_multi_mod_threaded.c000066400000000000000000000055611461254215100254540ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_taylor_shift_multi_mod_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; #endif #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t f, g; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_init(c); fmpz_poly_randtest(f, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_randtest(c, state, n_randint(state, 200)); flint_set_num_threads(1 + n_randint(state, 3)); fmpz_poly_taylor_shift_multi_mod(g, f, c); flint_set_num_threads(1 + n_randint(state, 3)); fmpz_poly_taylor_shift_multi_mod(f, f, c); if (!fmpz_poly_equal(g, f)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(c); } /* Compare with composition */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t f, g, h1, h2; fmpz_t c; fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h1); fmpz_poly_init(h2); fmpz_init(c); fmpz_poly_randtest(f, state, 1 + n_randint(state, 20), 1 + n_randint(state, 200)); fmpz_randtest(c, state, n_randint(state, 200)); fmpz_poly_set_coeff_ui(g, 1, 1); fmpz_poly_set_coeff_fmpz(g, 0, c); flint_set_num_threads(1 + n_randint(state, 3)); fmpz_poly_taylor_shift_multi_mod(h1, f, c); fmpz_poly_compose(h2, f, g); if (!fmpz_poly_equal(h1, h2)) { flint_printf("FAIL\n"); fmpz_poly_print(f); flint_printf("\n"); fmpz_poly_print(g); flint_printf("\n"); fmpz_poly_print(h1); flint_printf("\n"); fmpz_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/fmpz_poly/test/t-theta_qexp.c000066400000000000000000000032441461254215100211720ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_FUNCTION_START(fmpz_poly_theta_qexp, state) { int i; for (i = 0; i < 2000; i++) { fmpz_poly_t a, b; slong e, n; fmpz_poly_init(a); fmpz_poly_init(b); e = n_randint(state, 100) - 50; n = n_randint(state, 250); fmpz_poly_randtest(a, state, n_randint(state, 250), 1 + n_randint(state, 100)); fmpz_poly_theta_qexp(a, e, n); fmpz_poly_theta_qexp(b, 1, n + n_randint(state, 10)); if (n == 0) { fmpz_poly_zero(b); } else { if (e >= 0) { fmpz_poly_pow_trunc(b, b, e, n); } else { fmpz_poly_inv_series(b, b, n); fmpz_poly_pow_trunc(b, b, -e, n); } } if (!fmpz_poly_equal(a, b)) { flint_printf("FAIL (powering):\n"); flint_printf("e = %wd, n = %wd\n\n", e, n); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-xgcd_modular.c000066400000000000000000000211001461254215100214670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_xgcd_modular, state) { int i, result; /* Check s*f + t*g == r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t d, f, g, s, t; fmpz_t r; fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_init(r); do { fmpz_poly_randtest(f, state, n_randint(state, 50), 150); fmpz_poly_randtest(g, state, n_randint(state, 50), 150); fmpz_poly_primitive_part(f, f); fmpz_poly_primitive_part(g, g); fmpz_poly_gcd_modular(d, f, g); } while (d->length != 1); fmpz_poly_xgcd_modular(r, s, t, f, g); fmpz_poly_mul(s, s, f); fmpz_poly_mul(t, t, g); fmpz_poly_add(s, s, t); result = fmpz_poly_equal_fmpz(s, r); if (!result) { flint_printf("FAIL (check s*f + t*g == r):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("s = "), fmpz_poly_print(s); flint_printf("\n"); flint_printf("t = "), fmpz_poly_print(t); flint_printf("\n"); flint_printf("d = "), fmpz_poly_print(d); flint_printf("\n"); flint_printf("r = "), fmpz_print(r); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(r); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(s); fmpz_poly_clear(t); } /* Check s*f + t*g == r with smaller polynomials */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_t d, f, g, s, t; fmpz_t r; fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_init(r); do { fmpz_poly_randtest(f, state, n_randint(state, 30), 50); fmpz_poly_randtest(g, state, n_randint(state, 30), 50); fmpz_poly_primitive_part(f, f); fmpz_poly_primitive_part(g, g); fmpz_poly_gcd_modular(d, f, g); } while (d->length != 1); fmpz_poly_xgcd_modular(r, s, t, f, g); fmpz_poly_mul(s, s, f); fmpz_poly_mul(t, t, g); fmpz_poly_add(s, s, t); result = fmpz_poly_equal_fmpz(s, r); if (!result) { flint_printf("FAIL (check small s*f + t*g == r):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("s = "), fmpz_poly_print(s); flint_printf("\n"); flint_printf("t = "), fmpz_poly_print(t); flint_printf("\n"); flint_printf("d = "), fmpz_poly_print(d); flint_printf("\n"); flint_printf("r = "), fmpz_print(r); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(r); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(s); fmpz_poly_clear(t); } /* Check aliasing of s and f */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_t d, f, g, s, t; fmpz_t r; fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_init(r); do { fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_primitive_part(f, f); fmpz_poly_primitive_part(g, g); fmpz_poly_gcd_modular(d, f, g); } while (d->length != 1); fmpz_poly_xgcd_modular(r, s, t, f, g); fmpz_poly_xgcd_modular(r, f, t, f, g); result = (fmpz_poly_equal(s, f) || fmpz_is_zero(r)); if (!result) { flint_printf("FAIL (alias s and f):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("s = "), fmpz_poly_print(s); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(r); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(s); fmpz_poly_clear(t); } /* Check aliasing of s and g */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_t d, f, g, s, t; fmpz_t r; fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_init(r); do { fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_primitive_part(f, f); fmpz_poly_primitive_part(g, g); fmpz_poly_gcd_modular(d, f, g); } while (d->length != 1); fmpz_poly_xgcd_modular(r, s, t, f, g); fmpz_poly_xgcd_modular(r, g, t, f, g); result = (fmpz_poly_equal(s, g) || fmpz_is_zero(r)); if (!result) { flint_printf("FAIL (alias s and g):\n"); flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("s = "), fmpz_poly_print(s); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(r); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(s); fmpz_poly_clear(t); } /* Check aliasing of t and f */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_t d, f, g, s, t; fmpz_t r; fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_init(r); do { fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_primitive_part(f, f); fmpz_poly_primitive_part(g, g); fmpz_poly_gcd_modular(d, f, g); } while (d->length != 1); fmpz_poly_xgcd_modular(r, s, t, f, g); fmpz_poly_xgcd_modular(r, s, f, f, g); result = (fmpz_poly_equal(t, f) || fmpz_is_zero(r)); if (!result) { flint_printf("FAIL (alias t and f):\n"); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n"); flint_printf("t = "), fmpz_poly_print(t); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(r); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(s); fmpz_poly_clear(t); } /* Check aliasing of t and g */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_poly_t d, f, g, s, t; fmpz_t r; fmpz_poly_init(d); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(s); fmpz_poly_init(t); fmpz_init(r); do { fmpz_poly_randtest(f, state, n_randint(state, 50), 100); fmpz_poly_randtest(g, state, n_randint(state, 50), 100); fmpz_poly_primitive_part(f, f); fmpz_poly_primitive_part(g, g); fmpz_poly_gcd_modular(d, f, g); } while (d->length != 1); fmpz_poly_xgcd_modular(r, s, t, f, g); fmpz_poly_xgcd_modular(r, s, g, f, g); result = (fmpz_poly_equal(t, g) || fmpz_is_zero(r)); if (!result) { flint_printf("FAIL (alias t and g):\n"); flint_printf("f = "), fmpz_poly_print(g), flint_printf("\n"); flint_printf("t = "), fmpz_poly_print(t); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(r); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(s); fmpz_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-zero.c000066400000000000000000000021211461254215100200000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_zero, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a; fmpz_poly_init(a); fmpz_poly_randtest(a, state, n_randint(state, 100), 100); fmpz_poly_zero(a); result = (fmpz_poly_is_zero(a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/test/t-zero_coeffs.c000066400000000000000000000023771461254215100213420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_poly_zero_coeffs, state) { int i, result; /* Check that zeroing [0,len/2) and [len/2,len) sets a to zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a; slong len; fmpz_poly_init(a); fmpz_poly_randtest(a, state, n_randint(state, 100), 200); len = a->length; fmpz_poly_zero_coeffs(a, -23, len/2); fmpz_poly_zero_coeffs(a, len/2, len + 42); result = (fmpz_poly_length(a) == 0); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly/theta_qexp.c000066400000000000000000000046531461254215100177570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" static void theta_one(fmpz * r, slong n) { slong i, j; _fmpz_vec_zero(r, n); for (i = j = 0; j < n; i++) { fmpz_set_ui(r + j, i == 0 ? 1 : 2); j += 1 + 2*i; } } static void theta_two(fmpz * r, slong n) { slong i, j, x, y; _fmpz_vec_zero(r, n); for (x = i = 0; x < n; i++) { for (y = j = 0; x + y < n; j++) { fmpz_add_ui(r + x + y, r + x + y, (x ? 2 : 1) * (y ? 2 : 1)); y += 2 * j + 1; } x += 2 * i + 1; } } void _fmpz_poly_theta_qexp(fmpz * f, slong k, slong n) { if (k < 0) { fmpz * t = _fmpz_vec_init(n); _fmpz_poly_theta_qexp(t, -k, n); _fmpz_poly_inv_series(f, t, n, n); _fmpz_vec_clear(t, n); return; } else if (k == 0) { _fmpz_vec_zero(f, n); if (n > 0) fmpz_set_ui(f, 1); } else if (k == 1) { theta_one(f, n); } else if (k == 2) { theta_two(f, n); } else if (k % 2 == 0) { fmpz * t = _fmpz_vec_init(n); theta_two(t, n); _fmpz_poly_pow_trunc(f, t, k / 2, n); _fmpz_vec_clear(t, n); } else { fmpz *t, *u; t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); theta_two(t, n); if (k == 3) { theta_one(u, n); _fmpz_poly_mullow(f, t, n, u, n, n); } else { _fmpz_poly_pow_trunc(u, t, (k - 1) / 2, n); theta_one(t, n); _fmpz_poly_mullow(f, t, n, u, n, n); } _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); } } void fmpz_poly_theta_qexp(fmpz_poly_t f, slong e, slong n) { if (n < 1) { fmpz_poly_zero(f); } else if (e == 0 || n == 1) { fmpz_poly_one(f); } else { fmpz_poly_fit_length(f, n); _fmpz_poly_theta_qexp(f->coeffs, e, n); _fmpz_poly_set_length(f, n); _fmpz_poly_normalise(f); } } flint-3.1.3/src/fmpz_poly/truncate.c000066400000000000000000000012751461254215100174370ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_truncate(fmpz_poly_t poly, slong newlen) { if (poly->length > newlen) { slong i; for (i = newlen; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); poly->length = newlen; _fmpz_poly_normalise(poly); } } flint-3.1.3/src/fmpz_poly/xgcd_modular.c000066400000000000000000000147271461254215100202700ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _fmpz_poly_xgcd_modular(fmpz_t r, fmpz * s, fmpz * t, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { mp_ptr G, S, T, A, B, T1, T2; fmpz_t prod; int stabilised = 0, first; mp_limb_t p; flint_bitcnt_t s_bits = 0, t_bits = 0; /* Compute resultant of input polys */ _fmpz_poly_resultant(r, poly1, len1, poly2, len2); if (fmpz_is_zero(r)) return; fmpz_init(prod); fmpz_one(prod); _fmpz_vec_zero(s, len2); _fmpz_vec_zero(t, len1); p = (UWORD(1) << (FLINT_BITS - 1)); G = _nmod_vec_init(4 * len1 + 5 * len2 - 2); S = G + len2; T = S + len2; A = T + len1; B = A + len1; T1 = B + len2; T2 = T1 + (len1 + len2 - 1); _nmod_vec_zero(S, len2 + len1); /* S = T = 0 */ first = 1; for (;;) { mp_limb_t R; nmod_t mod; /* Get next prime */ p = n_nextprime(p, 0); /* Resultant mod p */ R = fmpz_fdiv_ui(r, p); /* If p divides resultant or either leading coeff, discard p */ if ((fmpz_fdiv_ui(poly1 + len1 - 1, p) == WORD(0)) || (fmpz_fdiv_ui(poly2 + len2 - 1, p) == WORD(0)) || (R == 0)) continue; nmod_init(&mod, p); /* Reduce polynomials modulo p */ _fmpz_vec_get_nmod_vec(A, poly1, len1, mod); _fmpz_vec_get_nmod_vec(B, poly2, len2, mod); if (stabilised) /* CRT has stabilised, probably don't need more xgcds */ { slong tlen; /* Multiply out A*S + B*T to see if it is R mod p */ _fmpz_vec_get_nmod_vec(S, s, len2, mod); _fmpz_vec_get_nmod_vec(T, t, len1, mod); _nmod_poly_mul(T1, A, len1, S, len2, mod); _nmod_poly_mul(T2, T, len1, B, len2, mod); _nmod_vec_add(T1, T1, T2, len1 + len2 - 1, mod); tlen = len1 + len2 - 1; FMPZ_VEC_NORM(T1, tlen); if (tlen == 1 && T1[0] == R) /* It is, so this prime is good */ fmpz_mul_ui(prod, prod, p); else stabilised = 0; /* It's not, keep going with xgcds */ } if (!stabilised) /* Need to keep computing xgcds mod p */ { mp_limb_t RGinv; /* Compute xgcd mod p */ _nmod_poly_xgcd(G, S, T, A, len1, B, len2, mod); RGinv = n_invmod(G[0], mod.n); RGinv = n_mulmod2_preinv(RGinv, R, mod.n, mod.ninv); /* Scale appropriately */ _nmod_vec_scalar_mul_nmod(S, S, len2, RGinv, mod); _nmod_vec_scalar_mul_nmod(T, T, len1, RGinv, mod); if (first) /* First time around set s and t to S and T */ { _fmpz_vec_set_nmod_vec(s, S, len2, mod); _fmpz_vec_set_nmod_vec(t, T, len1, mod); fmpz_set_ui(prod, p); stabilised = 1; /* Optimise the case where one prime is enough */ first = 0; } else /* Otherwise do CRT */ { flint_bitcnt_t new_s_bits, new_t_bits; _fmpz_poly_CRT_ui(s, s, len2, prod, S, len2, mod.n, mod.ninv, 1); _fmpz_poly_CRT_ui(t, t, len1, prod, T, len1, mod.n, mod.ninv, 1); fmpz_mul_ui(prod, prod, p); /* Check to see if CRT has stabilised */ new_s_bits = FLINT_ABS(_fmpz_vec_max_bits(s, len2)); new_t_bits = FLINT_ABS(_fmpz_vec_max_bits(t, len1)); stabilised = (s_bits == new_s_bits && t_bits == new_t_bits); s_bits = new_s_bits; t_bits = new_t_bits; } } if (stabilised) { slong bound1, bound2, bound; bound1 = FLINT_BIT_COUNT(len2) + FLINT_ABS(_fmpz_vec_max_bits(poly1, len1)) + FLINT_ABS(_fmpz_vec_max_bits(s, len2)); bound2 = FLINT_BIT_COUNT(len2) + FLINT_ABS(_fmpz_vec_max_bits(poly2, len2)) + FLINT_ABS(_fmpz_vec_max_bits(t, len1)); bound = 4 + FLINT_MAX(fmpz_bits(r), FLINT_MAX(bound1, bound2)); if (fmpz_bits(prod) > bound) break; } } _nmod_vec_clear(G); fmpz_clear(prod); } void fmpz_poly_xgcd_modular(fmpz_t r, fmpz_poly_t s, fmpz_poly_t t, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { if (poly1->length < poly2->length) { fmpz_poly_xgcd_modular(r, t, s, poly2, poly1); } else /* len1 >= len2 >= 0 */ { const slong len1 = poly1->length; const slong len2 = poly2->length; fmpz *S, *T; fmpz_poly_t temp1, temp2; if (len1 == 0 || len2 == 0) { fmpz_zero(r); } else /* len1 >= len2 >= 1 */ { if (s == poly1 || s == poly2) { fmpz_poly_init2(temp1, len2); S = temp1->coeffs; } else { fmpz_poly_fit_length(s, len2); S = s->coeffs; } if (t == poly1 || t == poly2) { fmpz_poly_init2(temp2, len1); T = temp2->coeffs; } else { fmpz_poly_fit_length(t, len1); T = t->coeffs; } _fmpz_poly_xgcd_modular(r, S, T, poly1->coeffs, len1, poly2->coeffs, len2); if (s == poly1 || s == poly2) { fmpz_poly_swap(s, temp1); fmpz_poly_clear(temp1); } if (t == poly1 || t == poly2) { fmpz_poly_swap(t, temp2); fmpz_poly_clear(temp2); } _fmpz_poly_set_length(s, len2); _fmpz_poly_normalise(s); _fmpz_poly_set_length(t, len1); _fmpz_poly_normalise(t); } } } flint-3.1.3/src/fmpz_poly/zero_coeffs.c000066400000000000000000000013451461254215100201140ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_zero_coeffs(fmpz_poly_t poly, slong i, slong j) { if (i < 0) i = 0; if (j > poly->length) j = poly->length; _fmpz_vec_zero(poly->coeffs + i, j - i); if (j == poly->length) { _fmpz_poly_set_length(poly, i); _fmpz_poly_normalise(poly); } } flint-3.1.3/src/fmpz_poly_factor.h000066400000000000000000000117351461254215100171570ustar00rootroot00000000000000/* Copyright (C) 2006, 2007, 2008, 2009, 2010, 2016 William Hart Copyright (C) 2009, 2011 Andy Novocin Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_POLY_FACTOR_H #define FMPZ_POLY_FACTOR_H #ifdef FMPZ_POLY_FACTOR_INLINES_C #define FMPZ_POLY_FACTOR_INLINE #else #define FMPZ_POLY_FACTOR_INLINE static inline #endif #include "nmod_types.h" #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif void fmpz_poly_factor_init(fmpz_poly_factor_t fac); void fmpz_poly_factor_init2(fmpz_poly_factor_t fac, slong alloc); void fmpz_poly_factor_realloc(fmpz_poly_factor_t fac, slong alloc); void fmpz_poly_factor_fit_length(fmpz_poly_factor_t fac, slong len); void fmpz_poly_factor_clear(fmpz_poly_factor_t fac); void fmpz_poly_factor_set(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac); void fmpz_poly_factor_insert(fmpz_poly_factor_t fac, const fmpz_poly_t p, slong exp); void fmpz_poly_factor_concat(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac); void fmpz_poly_factor_print(const fmpz_poly_factor_t fac); void fmpz_poly_factor_zassenhaus_recombination( fmpz_poly_factor_t final_fac, const fmpz_poly_factor_t lifted_fac, const fmpz_poly_t F, const fmpz_t P, slong exp); void fmpz_poly_factor_squarefree(fmpz_poly_factor_t fac, const fmpz_poly_t F); void fmpz_poly_factor_mignotte(fmpz_t B, const fmpz_poly_t f); void _fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t final_fac, slong exp, const fmpz_poly_t f, slong cutoff, int use_van_hoeij); void fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t fac, const fmpz_poly_t G); void _fmpz_poly_factor_quadratic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp); void _fmpz_poly_factor_cubic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp); slong _fmpz_poly_factor_CLD_mat(fmpz_mat_t res, const fmpz_poly_t f, fmpz_poly_factor_t lifted_fac, fmpz_t P, ulong k); int fmpz_poly_factor_van_hoeij_check_if_solved(fmpz_mat_t M, fmpz_poly_factor_t final_fac, fmpz_poly_factor_t lifted_fac, const fmpz_poly_t f, fmpz_t P, slong exp, fmpz_t lc); void fmpz_poly_factor_van_hoeij(fmpz_poly_factor_t final_fac, const nmod_poly_factor_t fac, const fmpz_poly_t f, slong exp, ulong p); void fmpz_poly_factor(fmpz_poly_factor_t fac, const fmpz_poly_t G); /* Inlines *******************************************************************/ void fmpz_poly_factor_get_fmpz_poly(fmpz_poly_t z, const fmpz_poly_factor_t F, slong i); void fmpz_poly_factor_get_fmpz(fmpz_t z, const fmpz_poly_factor_t F); /* zassenhaus ****************************************************************/ void zassenhaus_subset_first(slong * s, slong r, slong m); int zassenhaus_subset_next(slong * s, slong r); slong zassenhaus_subset_next_disjoint(slong * s, slong r); typedef struct { slong deg; unsigned char * pos_degs; /* possible degrees: entries are 0 or 1*/ slong new_length; slong new_total; slong * new_degs; slong alloc; } zassenhaus_prune_struct; typedef zassenhaus_prune_struct zassenhaus_prune_t[1]; FMPZ_POLY_FACTOR_INLINE void zassenhaus_prune_init(zassenhaus_prune_t Z) { Z->deg = 0; Z->pos_degs = NULL; Z->new_length = 0; Z->new_total = 0; Z->new_degs = NULL; Z->alloc = 0; } void zassenhaus_prune_clear(zassenhaus_prune_t Z); void zassenhaus_prune_set_degree(zassenhaus_prune_t Z, slong d); FMPZ_POLY_FACTOR_INLINE void zassenhaus_prune_start_add_factors(zassenhaus_prune_t Z) { Z->new_length = 0; Z->new_total = 0; } void zassenhaus_prune_add_factor(zassenhaus_prune_t Z, slong deg, slong exp); void zassenhaus_prune_end_add_factors(zassenhaus_prune_t Z); int zassenhaus_prune_must_be_irreducible(const zassenhaus_prune_t Z); FMPZ_POLY_FACTOR_INLINE int zassenhaus_prune_degree_is_possible(const zassenhaus_prune_t Z, slong d) { if (d <= 0) return d == 0; if (d >= Z->deg) return d == Z->deg; return Z->pos_degs[d]; } void fmpz_poly_factor_zassenhaus_recombination_with_prune( fmpz_poly_factor_t final_fac, const fmpz_poly_factor_t lifted_fac, const fmpz_poly_t F, const fmpz_t P, slong exp, const zassenhaus_prune_t Z); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_poly_factor/000077500000000000000000000000001461254215100167775ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly_factor/CLD_mat.c000066400000000000000000000073511461254215100204140ustar00rootroot00000000000000/* Copyright (C) 2011, 2016 William Hart Copyright (C) 2011 Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif slong _fmpz_poly_factor_CLD_mat(fmpz_mat_t res, const fmpz_poly_t f, fmpz_poly_factor_t lifted_fac, fmpz_t P, ulong k) { /* The product of the lifted factors g is equal to f modulo P. Here P = p^a. We will compute the top k and bottom k coefficients of each logarithmic derivative fg'/g. The results are stored in res, along with an extra row for the CLD bounds for that column. The matrix res is required to be initialised to be of size (r + 1, 2k). */ slong i, zeroes, bound, lo_n, hi_n, r = lifted_fac->num; slong bit_r = FLINT_MAX(r, 20); fmpz_poly_t gd, gcld, temp; fmpz_poly_t trunc_f, trunc_fac; /* don't initialise trunc_f, trunc_fac */ fmpz_t t; /* insert CLD bounds in last row of matrix */ for (i = 0; i < k; i++) { fmpz_poly_CLD_bound(res->rows[r] + i, f, i); fmpz_poly_CLD_bound(res->rows[r] + 2*k - i - 1, f, f->length - i - 2); } /* we exclude columns in the middle for which CLD bounds are too large */ fmpz_init(t); bound = fmpz_bits(P) - bit_r - bit_r/2; /* log_2(p^a / 2^{1.5r}) */ for (lo_n = 0; lo_n < k; lo_n++) { fmpz_mul_ui(t, res->rows[r] + lo_n, (slong) sqrt(f->length)); if (fmpz_bits(t) > bound) break; } fmpz_zero(t); for (hi_n = 0; hi_n < k; hi_n++) { fmpz_mul_ui(t, res->rows[r] + 2*k - hi_n - 1, (slong) sqrt(f->length)); if (fmpz_bits(t) > bound) break; } fmpz_clear(t); /* now insert data into matrix */ fmpz_poly_init(gd); fmpz_poly_init(gcld); /* do not initialise trunc_f */ /* do not initialise trunc_fac */ if (lo_n > 0) { for (i = 0; i < r; i++) { zeroes = 0; while (fmpz_is_zero(lifted_fac->p[i].coeffs + zeroes)) zeroes++; fmpz_poly_attach_truncate(trunc_fac, lifted_fac->p + i, lo_n + zeroes + 1); fmpz_poly_derivative(gd, trunc_fac); fmpz_poly_mullow(gcld, f, gd, lo_n + zeroes); fmpz_poly_divlow_smodp(res->rows[i], gcld, trunc_fac, P, lo_n); } } if (hi_n > 0) { fmpz_poly_init(temp); fmpz_poly_attach_shift(trunc_f, f, f->length - hi_n); for (i = 0; i < r; i++) { slong len = lifted_fac->p[i].length - hi_n - 1; if (len < 0) { fmpz_poly_shift_left(temp, lifted_fac->p + i, -len); fmpz_poly_derivative(gd, temp); fmpz_poly_mulhigh_n(gcld, trunc_f, gd, hi_n); fmpz_poly_divhigh_smodp(res->rows[i] + lo_n, gcld, temp, P, hi_n); } else { fmpz_poly_attach_shift(trunc_fac, lifted_fac->p + i, len); fmpz_poly_derivative(gd, trunc_fac); fmpz_poly_mulhigh_n(gcld, trunc_f, gd, hi_n); fmpz_poly_divhigh_smodp(res->rows[i] + lo_n, gcld, trunc_fac, P, hi_n); } } fmpz_poly_clear(temp); } if (hi_n > 0) { /* move bounds into correct columns */ for (i = 0; i < hi_n; i++) fmpz_set(res->rows[r] + lo_n + i, res->rows[r] + 2*k - hi_n + i); } /* do not clear trunc_fac */ /* do not clear trunc_f */ fmpz_poly_clear(gd); fmpz_poly_clear(gcld); return lo_n + hi_n; } flint-3.1.3/src/fmpz_poly_factor/clear.c000066400000000000000000000014411461254215100202310ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_clear(fmpz_poly_factor_t fac) { if (fac->alloc) { slong i; for (i = 0; i < fac->alloc; i++) { fmpz_poly_clear(fac->p + i); } flint_free(fac->p); flint_free(fac->exp); fac->p = NULL; fac->exp = NULL; } fmpz_clear(&(fac->c)); } flint-3.1.3/src/fmpz_poly_factor/concat.c000066400000000000000000000015261461254215100204160ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_concat(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac) { slong i; fmpz_mul(&(res->c), &(res->c), &(fac->c)); for (i = 0; i < fac->num; i++) fmpz_poly_factor_insert(res, fac->p + i, fac->exp[i]); } flint-3.1.3/src/fmpz_poly_factor/factor.c000066400000000000000000000063531461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_deflation(fmpz_poly_factor_t fac, const fmpz_poly_t G, int deflation) { const slong lenG = G->length; fmpz_poly_t g; fac->num = 0; if (lenG <= 1) { if (lenG < 1) fmpz_zero(&fac->c); else fmpz_set(&fac->c, G->coeffs + 0); return; } fmpz_poly_init(g); if (lenG < 5) { fmpz_poly_content(&fac->c, G); if (fmpz_sgn(fmpz_poly_lead(G)) < 0) fmpz_neg(&fac->c, &fac->c); fmpz_poly_scalar_divexact_fmpz(g, G, &fac->c); if (lenG < 3) fmpz_poly_factor_insert(fac, g, 1); else if (lenG == 3) _fmpz_poly_factor_quadratic(fac, g, 1); else _fmpz_poly_factor_cubic(fac, g, 1); } else { slong i, j, k, d; fmpz_poly_factor_t sq_fr_fac; /* Does a presearch for a factor of form x^k */ for (k = 0; fmpz_is_zero(G->coeffs + k); k++) ; if (k != 0) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_set_coeff_ui(t, 1, 1); fmpz_poly_factor_insert(fac, t, k); fmpz_poly_clear(t); } fmpz_poly_shift_right(g, G, k); if (deflation && (d = fmpz_poly_deflation(G)) > 1) { fmpz_poly_factor_t gfac; fmpz_poly_factor_init(gfac); fmpz_poly_deflate(g, g, d); fmpz_poly_factor(gfac, g); fmpz_set(&fac->c, &gfac->c); for (i = 0; i < gfac->num; i++) { fmpz_poly_factor_t hfac; fmpz_poly_factor_init(hfac); fmpz_poly_inflate(gfac->p + i, gfac->p + i, d); fmpz_poly_factor_deflation(hfac, gfac->p + i, 0); for (j = 0; j < hfac->num; j++) fmpz_poly_factor_insert(fac, hfac->p + j, gfac->exp[i] * hfac->exp[j]); fmpz_poly_factor_clear(hfac); } fmpz_poly_factor_clear(gfac); } else { /* Could make other tests for x-1 or simple things maybe take advantage of the composition algorithm */ fmpz_poly_factor_init(sq_fr_fac); fmpz_poly_factor_squarefree(sq_fr_fac, g); fmpz_set(&fac->c, &sq_fr_fac->c); /* Factor each square-free part */ for (j = 0; j < sq_fr_fac->num; j++) { _fmpz_poly_factor_zassenhaus(fac, sq_fr_fac->exp[j], sq_fr_fac->p + j, 8, 1); } fmpz_poly_factor_clear(sq_fr_fac); } } fmpz_poly_clear(g); } void fmpz_poly_factor(fmpz_poly_factor_t fac, const fmpz_poly_t G) { fmpz_poly_factor_deflation(fac, G, 1); } flint-3.1.3/src/fmpz_poly_factor/factor_cubic.c000066400000000000000000000475411461254215100216010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" /* z = sqrt(x) clobber x return absolute precision (>= 0) of z if z exists, otherwise return negative if x is not a square */ static slong binary_sqrt(fmpz_t z, fmpz_t x, slong p) { slong e, new_p, n; fmpz_t t, tx, s; fmpz two = 2; #if FLINT_WANT_ASSERT fmpz_t x_org; #endif FLINT_ASSERT(p > 0); fmpz_fdiv_r_2exp(x, x, p); if (fmpz_is_zero(x)) { fmpz_zero(z); return p/2; } e = fmpz_remove(x, x, &two); if ((e % 2) != 0) { fmpz_zero(z); return -WORD(1); } /* new precision after power of 2 removal */ new_p = p - e; if (new_p < 4) { fmpz_one(z); fmpz_mul_2exp(z, z, e/2); return e/2 + 1; } if (fmpz_fdiv_ui(x, 8) != 1) { fmpz_zero(z); return -WORD(1); } #if FLINT_WANT_ASSERT fmpz_init_set(x_org, x); fmpz_mul_2exp(x_org, x_org, e); #endif fmpz_init(t); fmpz_init(tx); fmpz_init(s); /* n is the current precision of z = 1/sqrt(x) as measured by 2^n divides x*z^2 - 1 */ n = 4; fmpz_fdiv_r_2exp(z, x, n + 1); fmpz_sub_ui(z, z, 3); fmpz_neg(z, z); fmpz_fdiv_r_2exp(z, z, n + 1); fmpz_fdiv_q_2exp(z, z, 1); #if FLINT_WANT_ASSERT fmpz_mul(t, z, z); fmpz_mul(t, t, x); fmpz_sub_ui(t, t, 1); fmpz_fdiv_r_2exp(t, t, n); FLINT_ASSERT(fmpz_is_zero(t)); #endif /* iterate z <- z*(3 - x*z^2)/2 */ while (n < new_p - 1) { n = 2*n - 2; fmpz_mul(t, z, z); fmpz_fdiv_r_2exp(tx, x, n + 1); fmpz_mul(s, tx, t); fmpz_sub_ui(s, s, 3); fmpz_neg(s, s); fmpz_fdiv_r_2exp(s, s, n + 1); fmpz_fdiv_q_2exp(s, s, 1); fmpz_mul(t, z, s); fmpz_fdiv_r_2exp(t, t, n); fmpz_swap(z, t); #if FLINT_WANT_ASSERT fmpz_mul(t, z, z); fmpz_mul(t, t, x); fmpz_sub_ui(t, t, 1); fmpz_fdiv_r_2exp(t, t, n); FLINT_ASSERT(fmpz_is_zero(t)); #endif } fmpz_mul(t, z, x); fmpz_fdiv_r_2exp(t, t, new_p - 1); fmpz_mul_2exp(t, t, e/2); fmpz_swap(z, t); #if FLINT_WANT_ASSERT fmpz_submul(x_org, z, z); fmpz_fdiv_r_2exp(t, x_org, new_p + e/2); FLINT_ASSERT(fmpz_is_zero(t)); fmpz_clear(x_org); #endif fmpz_clear(t); fmpz_clear(tx); fmpz_clear(s); return new_p - 1 + e/2; } static mp_limb_t fmpz_fdiv_r_2exp_flint_bits(const fmpz_t a) { if (COEFF_IS_MPZ(*a)) { const __mpz_struct * A = COEFF_TO_PTR(*a); return A->_mp_size > 0 ? A->_mp_d[0] : -A->_mp_d[0]; } else { return *a; } } static void binary_cubic_lift_fac( fmpz_t r, fmpz_t s, const fmpz_t a, const fmpz_t b, const fmpz_t inv, const fmpz_t r2, /* old r^2 */ slong e, slong n, fmpz_t c, fmpz_t d, fmpz_t t) /* temp */ { fmpz_mul_2exp(c, r2, e); fmpz_add(c, c, a); fmpz_sub(c, c, s); fmpz_fdiv_q_2exp(c, c, n); fmpz_set(d, b); fmpz_submul(d, r, s); fmpz_fdiv_q_2exp(d, d, n); fmpz_mul(t, d, r); fmpz_mul_2exp(t, t, e + 1); fmpz_addmul(t, c, s); fmpz_fdiv_r_2exp(t, t, n); fmpz_mul(t, t, inv); fmpz_fdiv_r_2exp(t, t, n); fmpz_mul_2exp(t, t, n); fmpz_add(s, s, t); fmpz_submul(d, c, r); fmpz_fdiv_r_2exp(d, d, n); fmpz_mul(d, d, inv); fmpz_fdiv_r_2exp(d, d, n); fmpz_mul_2exp(d, d, n); fmpz_add(r, r, d); } static void binary_cubic_lift_inv( fmpz_t inv, fmpz_t r2, /* r^2 */ const fmpz_t r, const fmpz_t s, slong e, slong n, fmpz_t t, fmpz_t t2) /* temp */ { fmpz_mul(r2, r, r); fmpz_mul(t, inv, inv); fmpz_mul_2exp(t2, r2, e + 1); fmpz_add(t2, t2, s); fmpz_mul_2exp(inv, inv, 1); fmpz_submul(inv, t, t2); fmpz_fdiv_r_2exp(inv, inv, n); } /* factor 2^e*y^3 + a*y + b = (y + r)*(2^e*y^2 - r*y + s) mod 2^p assuming: a and b are both odd and e > 0, or a is even and b is odd and e = 0. */ static slong binary_cubic_lift( fmpz_t r, fmpz_t s, fmpz_t inv, const fmpz_t a, const fmpz_t b, slong e, slong p) { slong n; fmpz_t r2, c, d, t; mp_limb_t A, B, C, D, INV, R, R2, S, E; /* start with a factorization mod 2^n */ n = 1; A = fmpz_fdiv_r_2exp_flint_bits(a); B = fmpz_fdiv_r_2exp_flint_bits(b); R = 1; S = 1; INV = 1; R2 = R*R; E = (e < FLINT_BITS) ? (UWORD(1) << e) : 0; while (n <= FLINT_BITS/2) { mp_limb_t mask = (UWORD(1) << n); C = (A - (S - R2*E)) >> n; D = (B - (R*S)) >> n; R += (((D - C*R)*INV) % mask) << n; S += (((2*E*D*R + C*S)*INV) % mask) << n; n *= 2; R2 = R*R; INV = 2*INV - (INV*INV)*(2*R2*E + S); } fmpz_set_ui(r, R); fmpz_set_ui(s, S); fmpz_set_ui(inv, INV); if (n >= p) return n; fmpz_init(t); fmpz_init(c); fmpz_init(d); fmpz_init_set_ui(r2, R); fmpz_mul_ui(r2, r2, R); while (n < p) { binary_cubic_lift_fac(r, s, a, b, inv, r2, e, n, c, d, t); n *= 2; if (n < p) binary_cubic_lift_inv(inv, r2, r, s, e, n, t, d); } #if FLINT_WANT_ASSERT fmpz_mul(r2, r, r); fmpz_mul_2exp(c, r2, e); fmpz_add(c, c, a); fmpz_sub(c, c, s); fmpz_fdiv_r_2exp(t, c, n); FLINT_ASSERT(fmpz_is_zero(t)); fmpz_set(d, b); fmpz_submul(d, r, s); fmpz_fdiv_r_2exp(t, d, n); FLINT_ASSERT(fmpz_is_zero(t)); #endif fmpz_clear(t); fmpz_clear(c); fmpz_clear(d); fmpz_clear(r2); return n; } /* on input n is even 0 <= s < 2^n 0 <= r < 2^n a = s - r^2*t mod 2^n b = r*s mod 2^n inv = (s + 2*r^2*2^e)^-1 mod 2^(n/2) on return 0 <= s < 2^(2n) 0 <= r < 2^(2n) 0 <= inv < 2^n a = s - r^2*t mod 2^(2n) b = r*s mod 2^(2n) inv = (s + 2*r^2*2^e)^-1 mod 2^n */ static slong binary_cubic_lift_continue( fmpz_t r, fmpz_t s, fmpz_t inv, const fmpz_t a, const fmpz_t b, slong e, slong n) { fmpz_t r2, t, c, d; fmpz_init(r2); fmpz_init(t); fmpz_init(c); fmpz_init(d); binary_cubic_lift_inv(inv, r2, r, s, e, n, t, d); binary_cubic_lift_fac(r, s, a, b, inv, r2, e, n, c, d, t); n *= 2; #if FLINT_WANT_ASSERT fmpz_mul(r2, r, r); fmpz_mul_2exp(c, r2, e); fmpz_add(c, c, a); fmpz_sub(c, c, s); fmpz_fdiv_r_2exp(t, c, n); FLINT_ASSERT(fmpz_is_zero(t)); fmpz_set(d, b); fmpz_submul(d, r, s); fmpz_fdiv_r_2exp(t, d, n); FLINT_ASSERT(fmpz_is_zero(t)); #endif fmpz_clear(r2); fmpz_clear(t); fmpz_clear(c); fmpz_clear(d); return n; } /* return f(0)*...*f(largest_prime - 1) mod prime_product */ static mp_limb_t eval_product_mod_n( const fmpz_t a, const fmpz_t b, mp_limb_t prime_product, mp_limb_t largest_prime) { nmod_t ctx; ulong A, B, F, G, H, P, i; nmod_init(&ctx, prime_product); A = fmpz_get_nmod(a, ctx); B = fmpz_get_nmod(b, ctx); A = nmod_add(A, nmod_add(A, A, ctx), ctx); /* f(x) = B + A*x - x^3 g(x) = f(x + 1) - f(x) = A - 1 - 3*x - 3*x^2 h(x) = g(x) - g(x + 1) = 6 + 6*x */ F = B; G = nmod_sub(A, 1, ctx); H = 6; P = F; for (i = 1; i < largest_prime; i++) { FLINT_ASSERT(H < prime_product); F = nmod_add(F, G, ctx); G = nmod_sub(G, H, ctx); H += 6; P = nmod_mul(P, F, ctx); } return P; } /* signed remainder mod 2^prec */ static void _fmpz_map_from_ZZ2(fmpz_t x, slong prec) { FLINT_ASSERT(prec > 0); fmpz_fdiv_r_2exp(x, x, prec); if (fmpz_bits(x) >= prec) { fmpz_neg(x, x); fmpz_fdiv_r_2exp(x, x, prec); fmpz_neg(x, x); } } /* write the integer roots of f(X) = X^3 - 3*a*X - b to x return 0: irreducible cubic 1: (X - x[0])*(irreducible quadratic) 2: (X - x[0])*(X - x[1])*(X - x[2]) 3: (X - x[0])*(X - x[1])^2 4: (X - x[0])^3 a and b are clobbered! */ static int _fmpz_cubic_roots(fmpz * x, fmpz_t a, fmpz_t b) { slong i; int ret, sign_a, sign_b, sign_d; fmpz_t d, t1, t2, t3, t4, ta, tb, r, s, inv, z; slong prec; slong cubic_prec, sqrt_prec; ulong alpha, beta, alpha2, beta3; fmpz two = 2; FLINT_ASSERT(a != b); sign_a = fmpz_sgn(a); sign_b = fmpz_sgn(b); if (fmpz_is_pm1(b)) { if (sign_a == 0) { fmpz_swap(x + 0, b); return 1; } else { return 0; } } if (fmpz_is_zero(b)) { fmpz_zero(x + 0); if (sign_a <= 0) return sign_a == 0 ? 4 : 1; fmpz_mul_ui(a, a, 3); if (fmpz_is_square(a)) { fmpz_sqrt(x + 1, a); fmpz_neg(x + 2, x + 1); return 2; } else { return 1; } } if (sign_b < 0) fmpz_neg(b, b); /* b >= 2 now, and sign_b has the sign of the original b */ /* check irreducibility mod 2 */ if (fmpz_is_odd(b) && fmpz_is_odd(a)) return 0; /* check irreducibility mod some p */ FLINT_ASSERT(FLINT_BITS >= 32); if (0 != eval_product_mod_n(a, b, UWORD(5)*7*11*13*17*19*23*29, 29)) return 0; fmpz_init(d); fmpz_init(t1); fmpz_init(t2); fmpz_init(t3); fmpz_init(t4); fmpz_init(ta); fmpz_init(tb); fmpz_init(r); fmpz_init(s); fmpz_init(inv); fmpz_init(z); /* d = b^2 - 4*a^3 = discriminant/-27 */ fmpz_mul(d, b, b); fmpz_mul(t1, a, a); fmpz_mul(t2, t1, a); fmpz_submul_ui(d, t2, 4); sign_d = fmpz_sgn(d); if (sign_d == 0) { FLINT_ASSERT(fmpz_divisible(b, a)); fmpz_divexact(x + 0, b, a); FLINT_ASSERT(fmpz_is_even(x + 0)); fmpz_divexact_si(x + 1, x + 0, -2); ret = 3; goto cleanup; } if (sign_d > 0) { /* The real root is (cbrt(4*b + 4*sqrt(d)) + cbrt(4*b - 4*sqrt(d)))/2 which is calculated by rounding intermediates to zero. */ fmpz_sqrt(t3, d); fmpz_add(t4, b, t3); fmpz_mul_ui(t4, t4, 4); fmpz_root(t1, t4, 3); fmpz_sub(t4, b, t3); fmpz_mul_ui(t4, t4, 4); fmpz_root(t2, t4, 3); fmpz_add(t1, t1, t2); fmpz_fdiv_q_2exp(x + 0, t1, 1); /* If x is the actual real root in RR, then, experimentally, x[0] - 1 < x < x[0] + 2, so that x[0] - 1 cannot be a root. Test all three numbers x[0] - 1, x[0], x[0] + 1 anyways since these follow from easily-proven bounds. */ fmpz_mul(t2, x + 0, x + 0); fmpz_sub(t3, t2, a); fmpz_submul_ui(t2, a, 3); fmpz_mul(t1, t2, x + 0); if (fmpz_equal(t1, b)) { ret = 1; goto cleanup; } fmpz_submul_ui(b, x + 0, 3); fmpz_mul_ui(t3, t3, 3); fmpz_add_ui(t3, t3, 1); fmpz_sub(t2, b, t3); if (fmpz_equal(t1, t2)) { fmpz_add_ui(x + 0, x + 0, 1); ret = 1; goto cleanup; } fmpz_add(t2, b, t3); if (fmpz_equal(t1, t2)) { fmpz_sub_ui(x + 0, x + 0, 1); ret = 1; goto cleanup; } ret = 0; goto cleanup; } /* Three real roots. The observations f(-2*sqrt(a)) < 0, f(-sqrt(a)) > 0 f(-b/(2*a)) > 0, f(-b/(3*a)) < 0 f(sqrt(a)) < 0, f(2*sqrt(a)) > 0 give intervals bounding the roots. They are sought in ZZ_2 here. */ /* check irreducibility mod some more p */ FLINT_ASSERT(FLINT_BITS >= 32); if (0 != eval_product_mod_n(a, b, UWORD(31)*37*41*43*47, 47)) { ret = 0; goto cleanup; } /* 2*sqrt(a) is bound on absolute value of roots */ prec = fmpz_bits(a)/2 + 3; fmpz_mul_si(ta, a, -3); fmpz_mul_si(tb, b, -1); FLINT_ASSERT(!fmpz_is_zero(ta)); FLINT_ASSERT(!fmpz_is_zero(tb)); alpha = fmpz_remove(ta, ta, &two); beta = fmpz_remove(tb, tb, &two); if (3*alpha == 2*beta) { ret = 0; goto cleanup; } else if (3*alpha > 2*beta) { /* only one root, which has valuation beta/3 */ beta3 = beta/3; if ((beta % 3) != 0) { ret = 0; goto cleanup; } fmpz_mul_2exp(ta, ta, alpha - 2*beta3); binary_cubic_lift(r, s, inv, ta, tb, 0, prec); fmpz_mul_2exp(x + 0, r, beta3); fmpz_neg(x + 0, x + 0); _fmpz_map_from_ZZ2(x + 0, prec); fmpz_mul(t1, x + 0, x + 0); fmpz_submul_ui(t1, a, 3); fmpz_mul(t2, t1, x + 0); ret = fmpz_equal(t2, b) ? 1 : 0; goto cleanup; } else { /* there is a root with valuation beta - alpha */ alpha2 = alpha/2; if ((alpha % 2) != 0) { /* there are no other roots */ binary_cubic_lift(r, s, inv, ta, tb, 2*beta - 3*alpha, prec); fmpz_mul_2exp(x + 0, r, beta - alpha); fmpz_neg(x + 0, x + 0); _fmpz_map_from_ZZ2(x + 0, prec); fmpz_mul(t1, x + 0, x + 0); fmpz_submul_ui(t1, a, 3); fmpz_mul(t2, t1, x + 0); ret = fmpz_equal(t2, b) ? 1 : 0; goto cleanup; } cubic_prec = binary_cubic_lift(r, s, inv, ta, tb, 2*beta - 3*alpha, prec); fmpz_mul_2exp(x + 0, r, beta - alpha); fmpz_neg(x + 0, x + 0); _fmpz_map_from_ZZ2(x + 0, prec); fmpz_mul(t1, x + 0, x + 0); fmpz_submul_ui(t1, a, 3); fmpz_mul(t2, t1, x + 0); /* there are two roots with valuation alpha/2 */ if (fmpz_equal(t2, b)) { fmpz_mul_ui(a, a, 4); fmpz_submul(a, x + 0, x + 0); fmpz_mul_ui(a, a, 3); if (fmpz_is_square(a)) { fmpz_sqrt(t1, a); fmpz_sub(x + 1, t1, x + 0); fmpz_add(x + 2, t1, x + 0); FLINT_ASSERT(fmpz_is_even(x + 1)); FLINT_ASSERT(fmpz_is_even(x + 2)); fmpz_divexact_ui(x + 1, x + 1, 2); fmpz_divexact_si(x + 2, x + 2, -2); ret = 2; goto cleanup; } else { ret = 1; goto cleanup; } } /* The root with valuation beta - alpha is irrational. We have already found it as -2^(beta-alpha)*r so factor it out and find the roots of the remaining quadratic with the quadratic formula: 2^(beta-alpha-1)*r +- 2^(alpha/2)*sqrt(2^(2*beta-3*alpha-2)*r^2 - s) r and s are calculated to precision O(2^cubic_prec), where cubic_prec >= prec. This formula might lose precision in the relatively common cases (1) alpha = 0, or (2) alpha > 0 and 2*beta-3*alpha-2 = 0 Since binary_cubic_lift_continue doubles cubic_prec, and binary_sqrt outputs a sqrt_prec with sqrt_prec >= cubic_prec/2 - 1, at most two jumps to try_again are required. */ try_again: FLINT_ASSERT(2*beta - 3*alpha >= 2); fmpz_mul(d, r, r); fmpz_mul_2exp(d, d, 2*beta - 3*alpha - 2); fmpz_sub(d, d, s); sqrt_prec = binary_sqrt(z, d, cubic_prec); if (sqrt_prec < 0) { /* roots with valuation alpha/2 are irrational */ ret = 0; goto cleanup; } if (sqrt_prec + alpha2 < prec) { cubic_prec = binary_cubic_lift_continue(r, s, inv, ta, tb, 2*beta - 3*alpha, cubic_prec); goto try_again; } fmpz_mul_2exp(r, r, beta - alpha - 1); fmpz_mul_2exp(z, z, alpha2); fmpz_add(x + 1, r, z); fmpz_sub(x + 2, r, z); for (i = 1; i <= 2; i++) { _fmpz_map_from_ZZ2(x + i, prec); fmpz_mul(t1, x + i, x + i); fmpz_submul_ui(t1, a, 3); fmpz_mul(t2, t1, x + i); if (fmpz_equal(t2, b)) { fmpz_swap(x + i, x + 0); ret = 1; goto cleanup; } } ret = 0; goto cleanup; } cleanup: if (sign_b < 0) { fmpz_neg(x + 0, x + 0); fmpz_neg(x + 1, x + 1); fmpz_neg(x + 2, x + 2); } fmpz_clear(d); fmpz_clear(t1); fmpz_clear(t2); fmpz_clear(t3); fmpz_clear(t4); fmpz_clear(ta); fmpz_clear(tb); fmpz_clear(r); fmpz_clear(s); fmpz_clear(inv); fmpz_clear(z); return ret; } /* roots of depressed cubic back to original */ static void _raise_linear_factor( fmpz_poly_t p, const fmpz_t a, const fmpz_t b, const fmpz_t root, fmpz_t T) { FLINT_ASSERT(p->alloc >= 2); fmpz_mul_ui(p->coeffs + 1, a, 3); fmpz_sub(p->coeffs + 0, b, root); fmpz_gcd(T, p->coeffs + 0, p->coeffs + 1); fmpz_divexact(p->coeffs + 0, p->coeffs + 0, T); fmpz_divexact(p->coeffs + 1, p->coeffs + 1, T); _fmpz_poly_set_length(p, 2); } void _fmpz_poly_factor_cubic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp) { fmpz_t A, B, b2, T, ac; fmpz r[3]; const fmpz *a, *b, *c, *d; fmpz_poly_t p; FLINT_ASSERT(f->length == 4); FLINT_ASSERT(fmpz_sgn(f->coeffs + 3) > 0); d = f->coeffs; c = f->coeffs + 1; b = f->coeffs + 2; a = f->coeffs + 3; /* depress the cubic to X^3 - 3*A*X - B */ fmpz_init(A); fmpz_init(B); fmpz_init(b2); fmpz_init(T); fmpz_init(ac); fmpz_init(r + 0); fmpz_init(r + 1); fmpz_init(r + 2); fmpz_poly_init2(p, 3); /* A = b^2 - 3*a*c */ fmpz_mul(ac, a, c); fmpz_mul(b2, b, b); fmpz_set(A, b2); fmpz_submul_ui(A, ac, 3); /* B = (9*a*c-2*b^2)*b - 27*a^2*d */ fmpz_mul_ui(b2, b2, 2); fmpz_mul_ui(ac, ac, 9); fmpz_sub(B, ac, b2); fmpz_mul(B, B, b); fmpz_mul(T, a, a); fmpz_mul(T, T, d); fmpz_submul_ui(B, T, 27); switch (_fmpz_cubic_roots(r, A, B)) { case 4: _raise_linear_factor(p, a, b, r + 0, T); fmpz_poly_factor_insert(fac, p, 3*exp); break; case 3: _raise_linear_factor(p, a, b, r + 0, T); fmpz_poly_factor_insert(fac, p, 1*exp); _raise_linear_factor(p, a, b, r + 1, T); fmpz_poly_factor_insert(fac, p, 2*exp); break; case 2: _raise_linear_factor(p, a, b, r + 0, T); fmpz_poly_factor_insert(fac, p, 1*exp); _raise_linear_factor(p, a, b, r + 1, T); fmpz_poly_factor_insert(fac, p, 1*exp); _raise_linear_factor(p, a, b, r + 2, T); fmpz_poly_factor_insert(fac, p, 1*exp); break; case 1: _raise_linear_factor(p, a, b, r + 0, T); fmpz_poly_factor_insert(fac, p, 1*exp); fmpz_poly_divides(p, f, p); fmpz_poly_factor_insert(fac, p, 1*exp); break; default: fmpz_poly_factor_insert(fac, f, exp); } fmpz_clear(A); fmpz_clear(B); fmpz_clear(b2); fmpz_clear(T); fmpz_clear(ac); fmpz_clear(r + 0); fmpz_clear(r + 1); fmpz_clear(r + 2); fmpz_poly_clear(p); } flint-3.1.3/src/fmpz_poly_factor/factor_quadratic.c000066400000000000000000000032411461254215100224560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void _fmpz_poly_factor_quadratic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp) { fmpz_t D; const fmpz *a, *b, *c; c = f->coeffs; b = f->coeffs + 1; a = f->coeffs + 2; fmpz_init(D); fmpz_mul(D, a, c); fmpz_mul_2exp(D, D, 2); fmpz_submul(D, b, b); fmpz_neg(D, D); if (fmpz_is_square(D)) { fmpz_poly_t t; fmpz_t g; fmpz_poly_init2(t, 2); fmpz_init(g); _fmpz_poly_set_length(t, 2); fmpz_sqrt(D, D); fmpz_mul_2exp(t->coeffs + 1, a, 1); fmpz_sub(t->coeffs, b, D); fmpz_poly_content(g, t); fmpz_poly_scalar_divexact_fmpz(t, t, g); if (fmpz_is_zero(D)) { fmpz_poly_factor_insert(fac, t, 2 * exp); } else { fmpz_poly_factor_insert(fac, t, exp); fmpz_mul_2exp(t->coeffs + 1, a, 1); fmpz_add(t->coeffs, b, D); fmpz_poly_content(g, t); fmpz_poly_scalar_divexact_fmpz(t, t, g); fmpz_poly_factor_insert(fac, t, exp); } fmpz_poly_clear(t); fmpz_clear(g); } else { fmpz_poly_factor_insert(fac, f, exp); } fmpz_clear(D); } flint-3.1.3/src/fmpz_poly_factor/factor_squarefree.c000066400000000000000000000040651461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_squarefree(fmpz_poly_factor_t fac, const fmpz_poly_t F) { fmpz_poly_content(&(fac->c), F); if (F->length != 0 && fmpz_sgn(fmpz_poly_lead(F)) < 0) fmpz_neg(&(fac->c), &(fac->c)); if (F->length > 1) { fmpz_poly_t f, d, t1; fmpz_poly_init(f); fmpz_poly_init(d); fmpz_poly_init(t1); fmpz_poly_scalar_divexact_fmpz(f, F, &(fac->c)); fmpz_poly_derivative(t1, f); fmpz_poly_gcd(d, f, t1); if (d->length == 1) { fmpz_poly_factor_insert(fac, f, 1); } else { fmpz_poly_t v, w, s; slong i; fmpz_poly_init(v); fmpz_poly_init(w); fmpz_poly_init(s); fmpz_poly_divexact(v, f, d); fmpz_poly_divexact(w, t1, d); for (i = 1; ; i++) { fmpz_poly_derivative(t1, v); fmpz_poly_sub(s, w, t1); if (s->length == 0) { if (v->length > 1) fmpz_poly_factor_insert(fac, v, i); break; } fmpz_poly_gcd(d, v, s); fmpz_poly_divexact(v, v, d); fmpz_poly_divexact(w, s, d); if (d->length > 1) fmpz_poly_factor_insert(fac, d, i); } fmpz_poly_clear(v); fmpz_poly_clear(w); fmpz_poly_clear(s); } fmpz_poly_clear(f); fmpz_poly_clear(d); fmpz_poly_clear(t1); } } flint-3.1.3/src/fmpz_poly_factor/factor_van_hoeij.c000066400000000000000000000152401461254215100224450ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "fmpz_lll.h" #ifdef __GNUC__ # define log __builtin_log # define sqrt __builtin_sqrt #else # include #endif slong _heuristic_van_hoeij_starting_precision(const fmpz_poly_t f, slong r, ulong p) { fmpz_t lead_b, trail_b; slong min_b, a; fmpz_init(lead_b); fmpz_init(trail_b); fmpz_poly_CLD_bound(lead_b, f, f->length - 2); fmpz_poly_CLD_bound(trail_b, f, 0); min_b = FLINT_MIN(fmpz_bits(lead_b), fmpz_bits(trail_b)); a = (slong) ((2.5*r + min_b)*log(2) + log(f->length)/2.0)/log(p); fmpz_clear(trail_b); fmpz_clear(lead_b); return a; } /* resize the matrix M to num_rows, where num_rows <= M->r the algorithm assumes rows have been permuted in memory by LLL */ void fmpz_mat_van_hoeij_resize_matrix(fmpz_mat_t M, slong num_rows) { slong i, j; fmpz ** empty_rows; slong num_empty = 0; fmpz * end; TMP_INIT; if (M->r == num_rows) return; /* nothing to be done */ TMP_START; /* space to record empty rows within bounds of new matrix */ empty_rows = (fmpz **) TMP_ALLOC(M->r*sizeof(fmpz *)); /* end of new matrix in memory */ end = M->entries + num_rows*M->c; /* clear rows that aren't needed */ for (i = num_rows; i < M->r; i++) { _fmpz_vec_zero(M->rows[i], M->c); /* this row can be repopulated */ if (M->rows[i] < end) empty_rows[num_empty++] = M->rows[i]; } for (i = 0; i < num_rows; i++) { if (M->rows[i] >= end) /* this row must be moved back to empty spot */ { fmpz * old_row = M->rows[i]; fmpz * new_row = empty_rows[--num_empty]; for (j = 0; j < M->c; j++) fmpz_swap(old_row + j, new_row + j); M->rows[i] = new_row; } } M->r = num_rows; TMP_END; } void fmpz_poly_factor_van_hoeij(fmpz_poly_factor_t final_fac, const nmod_poly_factor_t fac, const fmpz_poly_t f, slong exp, ulong p) { fmpz_poly_factor_t lifted_fac; fmpz_mat_t M; fmpz_t fp, P, B, lc, bound_sum; slong i, r = fac->num; slong bit_r = FLINT_MAX(r, 20); slong U_exp, a, next_col, num_data_cols, num_coeffs; slong prev_num_coeffs, prev_exp, N, worst_exp, num_rows; ulong sqN; fmpz_poly_t * v, * w; fmpz_mat_t col, data; slong * link; int hensel_loops, do_lll; fmpz_lll_t fl; /* set to identity */ fmpz_mat_init(M, r, r); for (i = 0; i < r; i++) fmpz_set_ui(M->rows[i] + i, 1); /* we prescale the identity matrix by 2^U_exp */ U_exp = (slong) FLINT_BIT_COUNT(bit_r); fmpz_mat_scalar_mul_2exp(M, M, U_exp); /* compute Mignotte bound */ fmpz_init(B); fmpz_poly_factor_mignotte(B, f); /* bound adjustment, we multiply true factors (which might be monic) by the leading coefficient of f in the implementation below */ fmpz_mul(B, B, f->coeffs + f->length - 1); fmpz_abs(B, B); fmpz_mul_ui(B, B, 2); fmpz_add_ui(B, B, 1); a = fmpz_clog_ui(B, p); /* compute heuristic starting precision */ a = FLINT_MIN(a, _heuristic_van_hoeij_starting_precision(f, r, p)); /* start Hensel lift */ fmpz_poly_factor_init(lifted_fac); v = flint_malloc((2*r - 2)*sizeof(fmpz_poly_t)); w = flint_malloc((2*r - 2)*sizeof(fmpz_poly_t)); link = flint_malloc((2*r - 2)*sizeof(slong)); for (i = 0; i < 2*r - 2; i++) { fmpz_poly_init(v[i]); fmpz_poly_init(w[i]); } prev_exp = _fmpz_poly_hensel_start_lift(lifted_fac, link, v, w, f, fac, a); /* compute bound */ fmpz_set_ui(B, r + 1); fmpz_mul_2exp(B, B, 2*U_exp); /* compute leading coefficient */ N = f->length - 1; sqN = (ulong) sqrt(N); fmpz_init(lc); fmpz_set(lc, f->coeffs + N); /* main hensel loop */ hensel_loops = 0; fmpz_init(P); fmpz_init(fp); fmpz_set_ui(fp, p); fmpz_pow_ui(P, fp, a); fmpz_init(bound_sum); fmpz_mat_init(col, r, 1); fmpz_lll_context_init_default(fl); while (!fmpz_poly_factor_van_hoeij_check_if_solved(M, final_fac, lifted_fac, f, P, exp, lc)) { if (hensel_loops < 3 && 3*r > N + 1) num_coeffs = r > 200 ? 50 : 30; else num_coeffs = 10; num_coeffs = FLINT_MIN(num_coeffs, (N + 1)/2); prev_num_coeffs = 0; do { fmpz_mat_init(data, r + 1, 2*num_coeffs); num_data_cols = _fmpz_poly_factor_CLD_mat(data, f, lifted_fac, P, num_coeffs); for (next_col = prev_num_coeffs; next_col < num_data_cols - prev_num_coeffs; next_col++) { /* we alternate taking columns from the right and left */ slong alt_col, diff = next_col - prev_num_coeffs; if ((diff % 2) == 0) alt_col = prev_num_coeffs + diff/2; else alt_col = num_data_cols - prev_num_coeffs - (diff + 1)/2; fmpz_mul_ui(bound_sum, data->rows[r] + alt_col, sqN); worst_exp = fmpz_bits(bound_sum); for (i = 0; i < r; i++) fmpz_set(col->rows[i], data->rows[i] + alt_col); do_lll = fmpz_mat_next_col_van_hoeij(M, P, col, worst_exp, U_exp); if (do_lll) { num_rows = fmpz_lll_wrapper_with_removal_knapsack(M, NULL, B, fl); fmpz_mat_van_hoeij_resize_matrix(M, num_rows); if (fmpz_poly_factor_van_hoeij_check_if_solved(M, final_fac, lifted_fac, f, P, exp, lc)) { fmpz_mat_clear(data); goto cleanup; } } } prev_num_coeffs = num_coeffs; num_coeffs = FLINT_MIN(2*num_coeffs, (N + 1)/2); fmpz_mat_clear(data); } while (num_coeffs != prev_num_coeffs); hensel_loops++; prev_exp = _fmpz_poly_hensel_continue_lift(lifted_fac, link, v, w, f, prev_exp, a, 2*a, fp); a = 2*a; fmpz_pow_ui(P, fp, a); } cleanup: fmpz_clear(lc); fmpz_clear(fp); fmpz_clear(P); fmpz_clear(B); fmpz_mat_clear(col); fmpz_mat_clear(M); fmpz_clear(bound_sum); fmpz_poly_factor_clear(lifted_fac); for (i = 0; i < 2*r - 2; i++) { fmpz_poly_clear(v[i]); fmpz_poly_clear(w[i]); } flint_free(v); flint_free(w); flint_free(link); } flint-3.1.3/src/fmpz_poly_factor/factor_zassenhaus.c000066400000000000000000000203521461254215100226670ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #define TRACE_ZASSENHAUS 0 /* Let $f$ be a polynomial of degree $m = \deg(f) \geq 2$. If another polynomial $g$ divides $f$ then, for all $0 \leq j \leq \deg(g)$, \begin{equation*} \abs{b_j} \leq \binom{n-1}{j} \abs{f} + \binom{n-1}{j-1} \abs{a_m} \end{equation*} where $\abs{f}$ denotes the $2$-norm of $f$. This bound is due to Mignotte, see [Coh1996] page 133. This function sets $B$ such that, for all $0 \leq j \leq \deg(g)$, $\abs{b_j} \leq B$. Consequently, when proceeding with Hensel lifting, we proceed to choose an $a$ such that $p^a \geq 2 B + 1$, e.g., $a = \ceil{\log_p(2B + 1)}$. Note that the formula degenerates for $j = 0$ and $j = n$ and so in this case we use that the leading (resp.\ constant) term of $g$ divides the leading (resp.\ constant) term of $f$. [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996 */ void _fmpz_poly_factor_mignotte(fmpz_t B, const fmpz *f, slong m) { slong j; fmpz_t b, f2, lc, s, t; fmpz_init(b); fmpz_init(f2); fmpz_init(lc); fmpz_init(s); fmpz_init(t); for (j = 0; j <= m; j++) fmpz_addmul(f2, f + j, f + j); fmpz_sqrt(f2, f2); fmpz_add_ui(f2, f2, 1); fmpz_abs(lc, f + m); fmpz_abs(B, f + 0); /* We have $b = \binom{m-1}{j-1}$ on loop entry and $b = \binom{m-1}{j}$ on exit. */ fmpz_set_ui(b, m-1); for (j = 1; j < m; j++) { fmpz_mul(t, b, lc); fmpz_mul_ui(b, b, m - j); fmpz_divexact_ui(b, b, j); fmpz_mul(s, b, f2); fmpz_add(s, s, t); if (fmpz_cmp(B, s) < 0) fmpz_set(B, s); } if (fmpz_cmp(B, lc) < 0) fmpz_set(B, lc); fmpz_clear(b); fmpz_clear(f2); fmpz_clear(lc); fmpz_clear(s); fmpz_clear(t); } void fmpz_poly_factor_mignotte(fmpz_t B, const fmpz_poly_t f) { _fmpz_poly_factor_mignotte(B, f->coeffs, f->length - 1); } void _fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t final_fac, slong exp, const fmpz_poly_t f, slong cutoff, int use_van_hoeij) { const slong lenF = f->length; #if TRACE_ZASSENHAUS == 1 flint_printf("\n[Zassenhaus]\n"); flint_printf("|f = "), fmpz_poly_print(f), flint_printf("\n"); #endif if (lenF < 5) { if (lenF < 3) fmpz_poly_factor_insert(final_fac, f, exp); else if (lenF == 3) _fmpz_poly_factor_quadratic(final_fac, f, exp); else _fmpz_poly_factor_cubic(final_fac, f, exp); return; } else { slong i, j; slong r = lenF; mp_limb_t p = 2; nmod_poly_t d, g, t; nmod_poly_factor_t fac; zassenhaus_prune_t Z; zassenhaus_prune_init(Z); nmod_poly_factor_init(fac); nmod_poly_init_preinv(t, 1, 0); nmod_poly_init_preinv(d, 1, 0); nmod_poly_init_preinv(g, 1, 0); zassenhaus_prune_set_degree(Z, lenF - 1); for (i = 0; i < 3; i++) { for ( ; ; p = n_nextprime(p, 0)) { nmod_t mod; nmod_init(&mod, p); d->mod = mod; g->mod = mod; t->mod = mod; fmpz_poly_get_nmod_poly(t, f); if (t->length == lenF && t->coeffs[0] != 0) { nmod_poly_derivative(d, t); nmod_poly_gcd(g, t, d); if (nmod_poly_is_one(g)) { nmod_poly_factor_t temp_fac; nmod_poly_factor_init(temp_fac); nmod_poly_factor(temp_fac, t); zassenhaus_prune_start_add_factors(Z); for (j = 0; j < temp_fac->num; j++) zassenhaus_prune_add_factor(Z, temp_fac->p[j].length - 1, temp_fac->exp[j]); zassenhaus_prune_end_add_factors(Z); if (temp_fac->num <= r) { r = temp_fac->num; nmod_poly_factor_set(fac, temp_fac); } nmod_poly_factor_clear(temp_fac); break; } } } p = n_nextprime(p, 0); } nmod_poly_clear(d); nmod_poly_clear(g); nmod_poly_clear(t); p = (fac->p + 0)->mod.n; if (r == 1 && r <= cutoff) { fmpz_poly_factor_insert(final_fac, f, exp); } else if (r > cutoff && use_van_hoeij) { fmpz_poly_factor_van_hoeij(final_fac, fac, f, exp, p); } else { slong a; fmpz_t T; fmpz_poly_factor_t lifted_fac; fmpz_poly_factor_init(lifted_fac); fmpz_init(T); fmpz_poly_factor_mignotte(T, f); /* bound adjustment, we multiply true factors (which might be monic) by the leading coefficient of f in the implementation below */ fmpz_mul(T, T, f->coeffs + f->length - 1); fmpz_abs(T, T); fmpz_mul_ui(T, T, 2); fmpz_add_ui(T, T, 1); a = fmpz_clog_ui(T, p); fmpz_poly_hensel_lift_once(lifted_fac, f, fac, a); #if TRACE_ZASSENHAUS == 1 flint_printf("|p = %wd, a = %wd\n", p, a); flint_printf("|Pre hensel lift factorisation (nmod_poly):\n"); nmod_poly_factor_print(fac); flint_printf("|Post hensel lift factorisation (fmpz_poly):\n"); fmpz_poly_factor_print(lifted_fac); #endif fmpz_set_ui(T, p); fmpz_pow_ui(T, T, a); fmpz_poly_factor_zassenhaus_recombination_with_prune( final_fac, lifted_fac, f, T, exp, Z); fmpz_poly_factor_clear(lifted_fac); fmpz_clear(T); } nmod_poly_factor_clear(fac); zassenhaus_prune_clear(Z); } } void fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t fac, const fmpz_poly_t G) { const slong lenG = G->length; fmpz_poly_t g; if (lenG == 0) { fmpz_set_ui(&fac->c, 0); return; } if (lenG == 1) { fmpz_set(&fac->c, G->coeffs); return; } fmpz_poly_init(g); if (lenG == 2) { fmpz_poly_content(&fac->c, G); if (fmpz_sgn(fmpz_poly_lead(G)) < 0) fmpz_neg(&fac->c, &fac->c); fmpz_poly_scalar_divexact_fmpz(g, G, &fac->c); fmpz_poly_factor_insert(fac, g, 1); } else { slong j, k; fmpz_poly_factor_t sq_fr_fac; /* Does a presearch for a factor of form x^k */ for (k = 0; fmpz_is_zero(G->coeffs + k); k++) ; if (k != 0) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_set_coeff_ui(t, 1, 1); fmpz_poly_factor_insert(fac, t, k); fmpz_poly_clear(t); } fmpz_poly_shift_right(g, G, k); /* Could make other tests for x-1 or simple things maybe take advantage of the composition algorithm */ fmpz_poly_factor_init(sq_fr_fac); fmpz_poly_factor_squarefree(sq_fr_fac, g); fmpz_set(&fac->c, &sq_fr_fac->c); /* Factor each square-free part */ for (j = 0; j < sq_fr_fac->num; j++) { _fmpz_poly_factor_zassenhaus(fac, sq_fr_fac->exp[j], sq_fr_fac->p + j, WORD_MAX, 0); } fmpz_poly_factor_clear(sq_fr_fac); } fmpz_poly_clear(g); } #undef TRACE_ZASSENHAUS flint-3.1.3/src/fmpz_poly_factor/factor_zassenhaus_recombination.c000066400000000000000000000144771461254215100256130ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_factor.h" static void _fmpz_poly_product( fmpz_poly_t res, const fmpz_poly_struct * lifted_fac, const slong * subset, slong len, const fmpz_t P, const fmpz_t leadf, fmpz_poly_struct ** stack, fmpz_poly_struct * tmp) { slong i, j, k; fmpz_poly_struct * t; k = 0; for (i = 0; i < len; i++) { if (subset[i] < 0) continue; stack[k] = (fmpz_poly_struct *) lifted_fac + subset[i]; k++; for (j = k - 1; j > 0 && stack[j - 1]->length < stack[j]->length; j--) { t = stack[j - 1]; stack[j - 1] = stack[j]; stack[j] = t; } } while (k > 1) { for (j = 1; j < k; j++) FLINT_ASSERT(stack[j - 1]->length >= stack[j]->length); fmpz_poly_mul(res, stack[k - 2], stack[k - 1]); fmpz_poly_scalar_smod_fmpz(res, res, P); k--; stack[k - 1] = tmp + k - 1; /* make sure stack[k - 1] is writeable */ fmpz_poly_swap(res, stack[k - 1]); for (j = k - 1; j > 0 && stack[j - 1]->length < stack[j]->length; j--) { t = stack[j - 1]; stack[j - 1] = stack[j]; stack[j] = t; } } if (k == 1) { fmpz_poly_scalar_mul_fmpz(res, stack[0], leadf); fmpz_poly_scalar_smod_fmpz(res, res, P); } else { FLINT_ASSERT(0); fmpz_poly_one(res); } } void fmpz_poly_factor_zassenhaus_recombination( fmpz_poly_factor_t final_fac, const fmpz_poly_factor_t lifted_fac, const fmpz_poly_t F, const fmpz_t P, slong exp) { const slong r = lifted_fac->num; slong * subset; slong k, len; fmpz_poly_t Fcopy, Q, tryme; fmpz_poly_struct * tmp; fmpz_poly_struct ** stack; fmpz_poly_struct * f; subset = (slong *) flint_malloc(r*sizeof(slong)); for (k = 0; k < r; k++) subset[k] = k; stack = (fmpz_poly_struct **) flint_malloc(r*sizeof(fmpz_poly_struct *)); tmp = (fmpz_poly_struct *) flint_malloc(r*sizeof(fmpz_poly_struct)); for (k = 0; k < r; k++) fmpz_poly_init(tmp + k); fmpz_poly_init(Q); fmpz_poly_init(tryme); fmpz_poly_init(Fcopy); f = (fmpz_poly_struct *) F; len = r; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); while (1) { _fmpz_poly_product(tryme, lifted_fac->p, subset, len, P, fmpz_poly_lead(f), stack, tmp); fmpz_poly_primitive_part(tryme, tryme); if (fmpz_poly_divides(Q, f, tryme)) { fmpz_poly_factor_insert(final_fac, tryme, exp); f = Fcopy; /* make sure f is writeable */ fmpz_poly_swap(f, Q); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (fmpz_poly_degree(f) > 0) { fmpz_poly_factor_insert(final_fac, f, exp); } else { FLINT_ASSERT(fmpz_poly_is_one(f)); } fmpz_poly_clear(Fcopy); fmpz_poly_clear(tryme); fmpz_poly_clear(Q); flint_free(stack); for (k = 0; k < r; k++) fmpz_poly_clear(tmp + k); flint_free(tmp); flint_free(subset); } void fmpz_poly_factor_zassenhaus_recombination_with_prune( fmpz_poly_factor_t final_fac, const fmpz_poly_factor_t lifted_fac, const fmpz_poly_t F, const fmpz_t P, slong exp, const zassenhaus_prune_t Z) { const slong r = lifted_fac->num; slong * subset; slong i, k, len, total; fmpz_poly_t Fcopy, Q, tryme; fmpz_poly_struct * tmp; fmpz_poly_struct ** stack; fmpz_poly_struct * f; subset = (slong *) flint_malloc(r*sizeof(slong)); for (k = 0; k < r; k++) subset[k] = k; stack = (fmpz_poly_struct **) flint_malloc(r*sizeof(fmpz_poly_struct *)); tmp = (fmpz_poly_struct *) flint_malloc(r*sizeof(fmpz_poly_struct)); for (k = 0; k < r; k++) fmpz_poly_init(tmp + k); fmpz_poly_init(Q); fmpz_poly_init(tryme); fmpz_poly_init(Fcopy); f = (fmpz_poly_struct *) F; len = r; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); while (1) { total = 0; for (i = 0; i < len; i++) if (subset[i] >= 0) total += fmpz_poly_degree(lifted_fac->p + subset[i]); if (!zassenhaus_prune_degree_is_possible(Z, total)) { if (!zassenhaus_subset_next(subset, len)) break; continue; } _fmpz_poly_product(tryme, lifted_fac->p, subset, len, P, fmpz_poly_lead(f), stack, tmp); fmpz_poly_primitive_part(tryme, tryme); if (fmpz_poly_divides(Q, f, tryme)) { fmpz_poly_factor_insert(final_fac, tryme, exp); f = Fcopy; /* make sure f is writeable */ fmpz_poly_swap(f, Q); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (fmpz_poly_degree(f) > 0) { fmpz_poly_factor_insert(final_fac, f, exp); } else { FLINT_ASSERT(fmpz_poly_is_one(f)); } fmpz_poly_clear(Fcopy); fmpz_poly_clear(tryme); fmpz_poly_clear(Q); flint_free(stack); for (k = 0; k < r; k++) fmpz_poly_clear(tmp + k); flint_free(tmp); flint_free(subset); } flint-3.1.3/src/fmpz_poly_factor/fit_length.c000066400000000000000000000013401461254215100212640ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" void fmpz_poly_factor_fit_length(fmpz_poly_factor_t fac, slong len) { if (len > fac->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * fac->alloc) len = 2 * fac->alloc; fmpz_poly_factor_realloc(fac, len); } } flint-3.1.3/src/fmpz_poly_factor/init.c000066400000000000000000000022041461254215100201040ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_init(fmpz_poly_factor_t fac) { fmpz_init_set_ui(&(fac->c), 1); fac->p = NULL; fac->exp = NULL; fac->num = 0; fac->alloc = 0; } void fmpz_poly_factor_init2(fmpz_poly_factor_t fac, slong alloc) { fmpz_init_set_ui(&(fac->c), 1); if (alloc) { slong i; fac->p = flint_malloc(alloc * sizeof(fmpz_poly_struct)); fac->exp = flint_malloc(alloc * sizeof(slong)); for (i = 0; i < alloc; i++) { fmpz_poly_init(fac->p + i); fac->exp[i] = WORD(0); } } else { fac->p = NULL; fac->exp = NULL; } fac->num = 0; fac->alloc = alloc; } flint-3.1.3/src/fmpz_poly_factor/inlines.c000066400000000000000000000013071461254215100206050ustar00rootroot00000000000000/* Copyright (C) 2017 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_FACTOR_INLINES_C #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_get_fmpz_poly(fmpz_poly_t z, const fmpz_poly_factor_t F, slong i) { fmpz_poly_set(z, F->p + i); } void fmpz_poly_factor_get_fmpz(fmpz_t z, const fmpz_poly_factor_t F) { fmpz_set(z, &(F->c)); } flint-3.1.3/src/fmpz_poly_factor/insert.c000066400000000000000000000017541461254215100204560ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_insert(fmpz_poly_factor_t fac, const fmpz_poly_t p, slong exp) { slong i; for (i = 0; i < fac->num; i++) { if (fmpz_poly_equal(p, fac->p + i)) { fac->exp[i] += exp; return; } } fmpz_poly_factor_fit_length(fac, i + 1); fmpz_poly_set(fac->p + i, p); fac->exp[i] = exp; fac->num = i + 1; } flint-3.1.3/src/fmpz_poly_factor/print.c000066400000000000000000000015701461254215100203020ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_print(const fmpz_poly_factor_t fac) { slong i; fmpz_print(&(fac->c)); flint_printf("\n"); for (i = 0; i < fac->num; i++) { fmpz_poly_print(fac->p + i); flint_printf(" ^ %wd\n", fac->exp[i]); } } flint-3.1.3/src/fmpz_poly_factor/profile/000077500000000000000000000000001461254215100204375ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly_factor/profile/C1_flint000066400000000000000000000333741461254215100220330ustar00rootroot000000000000001025 1 0 0 0 0 0 0 0 -1316593840 0 0 0 0 0 0 0 1254239907737033936 0 0 0 0 0 0 0 -1020500154868410158128259880 0 0 0 0 0 0 0 742657645113910721858495922505609288 0 0 0 0 0 0 0 -488851428152742328213334784814350395516520960 0 0 0 0 0 0 0 287814046590098536056537417927970868680931874624839972 0 0 0 0 0 0 0 -144731432788491934782720809053881299753255348063430296359463560 0 0 0 0 0 0 0 52667418446964455183555119787670793060682682657537813854472928617806356 0 0 0 0 0 0 0 -6627372146457374840476684171598633576102247456530952583168212566763674899080 0 0 0 0 0 0 0 229808850679653576215220762470947999111032180953859275098084786754118572707929408 0 0 0 0 0 0 0 47244447534423196727705721422913104255453865886015290840067262460660337554236681038680 0 0 0 0 0 0 0 -8598781279258932570943204125327149003097070415673151850246519910810714143570100274286748702 0 0 0 0 0 0 0 540701870204849447390226082954705836726722861074416261309121908402549511726244938504093747464120 0 0 0 0 0 0 0 30722682940581202352438291542486365134326454366699360707706667539312670299047066359657762413342965644 0 0 0 0 0 0 0 -10091249799704011701023139981079139597965800532808795363420077405279553345534029151131003234276688814706320 0 0 0 0 0 0 0 918854935715631662119487597903572632508236291734752388205157260039596655041407319588793267016427474581423827906 0 0 0 0 0 0 0 184683888599830925569838236218486017226349050180930626801417764157419922118806842745116335861703061673468951582720 0 0 0 0 0 0 0 13842363407336159924692947011620784296637244031515736813921285210411537345747604922653148099415836121720351511925108 0 0 0 0 0 0 0 -1058739682767542904517937750831982923025094134407798499065928299726409117391203782300287325011261537008384833677659600 0 0 0 0 0 0 0 -407542738934829659626614158410104545029716335746556910645965352195238540893456402145893421251610543862639471887617605448 0 0 0 0 0 0 0 -44889924527494986885728274555606181914473709099244648210778261610312708286920150136460334229335393800934091608922081355880 0 0 0 0 0 0 0 165417349118320753388592638510911804774504682990824901290000522105912383403100338190546796897583521863755885957200555663012 0 0 0 0 0 0 0 814412405263708371325588177235203431851941789505034023749589208830541984698894407942481613187277620340133907001400009204491520 0 0 0 0 0 0 0 123992527471432355160564250589830197691956102938592732030049632797499125856155573232226921154701080890746377691681553451697576671 0 0 0 0 0 0 0 4995378323406758931783045841002345498286261966641299704198046527783410717273853620526178991326503752120571659351121834410612924720 0 0 0 0 0 0 0 140404954012452700166032754112751928352146404977929750660562280585349441106457120658706160548084409690211168777015792605041999566604 0 0 0 0 0 0 0 3291958748356854814839201303157050704640505995802279716587412350138091954559656554050867468505907346150930414615677766933007107089120 0 0 0 0 0 0 0 68358068735718516094251777113158906503228424130736744644043641684736893009605404041996051022355485846242655399789381771096948472299642 0 0 0 0 0 0 0 1282306386020184808737647643430622466149755000723025386040637669197236598496794036041936715504886451665448809642377539617721547714704680 0 0 0 0 0 0 0 21670065179274072025590493783683657522136220939796197760878531190746040699892379265300410217321591478228854128907906097025008510978671260 0 0 0 0 0 0 0 320320892673865449140520806497828968812336027240346697743148253565570509773737848486512447709152756461760493393141110229512743345385272520 0 0 0 0 0 0 0 3770681492372589535772443418801792439601892744613610596885631884422304624590160838337719248912539399511791537828356826069607489092106765475 0 0 0 0 0 0 0 25578146281021022549714196244283852592377664968529282406009008504855974900214806612705262695934419688811125549909721430622090490564099109520 0 0 0 0 0 0 0 136532451550610274794572531886957325613115017164695108559892878606862140665461546639945604456179070121664107458980516889433942932107657304360 0 0 0 0 0 0 0 634354500600985650208961597367566323354754616527871965664244652489852835419595006992861388926689773896908331356062622301528448302400386714880 0 0 0 0 0 0 0 2652350342316948247509721732335736766450204880030919559449731909079217487320624432693341853097593824307800900993067602066467872178227316861100 0 0 0 0 0 0 0 10016805754795508549555492679815715688592055427939697906411175119280739379488315088149111507610542314998832232103935126619818232623476295908400 0 0 0 0 0 0 0 33492490360852407086505215597449499396287490285314596680997803553567655056225097476860319502453027166244974620341886638179910509121189771417440 0 0 0 0 0 0 0 93270889329796625252696195707129081208400203135825963629048516265147424086808048973491743106503752774649557065474591823729856744685751572005520 0 0 0 0 0 0 0 179360783435407659471746353648252923543348732113461558072268449720427607112453607603311589849530306742653286910020598786765831248123472613612686 0 0 0 0 0 0 0 67519322208583245541123300989202759025170069426989907956026708408762857944837588581306512315557581416065388801707677140612580715423352242897840 0 0 0 0 0 0 0 -151504820634729506015764983850359316249349869553893492519711651557225516840726173073213980888651573883349578610581533815473605142033370939104384 0 0 0 0 0 0 0 -313076423795317093101478492505267023306706219679931941626810097764385044334229566057999948506420142296074930260468553514711913245333739003794400 0 0 0 0 0 0 0 -222849643995828550305670629616667966457242510069508988784951065966041864100356120536296121570571742758977181766980901314230412670681131174063552 0 0 0 0 0 0 0 140609175462680958727584698888441722937221041186958820642533190885923307058675395030263152070266403613261570753056578070210019205618560862417120 0 0 0 0 0 0 0 533118189907130535370987175598659272183982500490260517432129126090825064207689223214625332298640672348701388460213338945234878735401033527579912 0 0 0 0 0 0 0 595539555697449750524871578123050094331388103507278348244949773102359574983204969741318800275350896499737864172963430803654793792978612447795280 0 0 0 0 0 0 0 217269783864194126882256725113353625739827856178389389423003099118245095965828957995566248431759773108082728584364251675689384937763489939790641 0 0 0 0 0 0 0 -172656619651759380208260995517028829992248330397670635260364417716030064953551312848787994206183577215328176656024348784643716222191875133659840 0 0 0 0 0 0 0 47102899306335665527423393903434389208790454002656409210278268009012546481658758375640120112452523685502661697080158096252742077298462329528120 0 0 0 0 0 0 0 -6575384075660829739879455978508946422399851727060710613351317690226313955301422709143620254199535254030882819339982320251256911043486661537480 0 0 0 0 0 0 0 94646289983763022194451385289262778180135982468932803496667105046572909398689843122236944677234731674848118751453338734008956568612724562620 0 0 0 0 0 0 0 172279933357640825734899067347870509257563015147752245808702877228370887567566027079106049242771073027124960113185611855478392986238493120560 0 0 0 0 0 0 0 -37763601566790690683081469289590517118000569861247651322246177354508656950685819778105729873061842174488506745029372130516397759321061838780 0 0 0 0 0 0 0 2235616776623738130109787007380039531997578891766526321954706384647043446790486712836734373441976884160929786200719306320140291792511663640 0 0 0 0 0 0 0 793664203179892643499956494355129152448512395887047323794449765989078049641049155054645512157205132285188600653749825608778929834785795190 0 0 0 0 0 0 0 -215802123061430663992460938671656374568218184290991538449388465585980840213305288232389356476824969855114403176864381843338886209225396120 0 0 0 0 0 0 0 33596191901940459180743646973641307473268813184661518588627722614392831515143157486393815915723527412543632124443361666209350815761157600 0 0 0 0 0 0 0 -4116784903346242780865114574283031704029652043622481798996191584343287407244851588245692966145994757298389873840069842060952845481519400 0 0 0 0 0 0 0 435456705125138504284062365126984912970621208321694876027105097874340168633100977381962195714908893583648146179359809529105819851556906 0 0 0 0 0 0 0 -41211058988045978728428621468362715847611410346997709361006693859199724416708626891010095071039539836757031540209296595649384830936760 0 0 0 0 0 0 0 3519657711316422320088106359899521053405946474421542253704770602905803469837293795940188931356393525916874252705485170453123653526396 0 0 0 0 0 0 0 -267682140338354204701729274907978539771795610080794464286539641745007766619745748037689776365742499996057162276726285915765208969840 0 0 0 0 0 0 0 17486767463327764961045258701964777848725763340661679067187673857103693210235814820616091643070855195700177041079584122216243728033 0 0 0 0 0 0 0 -936226024552376077332732801974495152912828735135458204793983877583636491893839275172317948176767935332870690905786208772117266720 0 0 0 0 0 0 0 43980625538306036531916366125566374095750905418435136086308829961380862248442592097129213136954040613537506421361887908302432612 0 0 0 0 0 0 0 -1847888686484404015504460460903708698385674581106131975310422507187427611006955521935708154059993006934790819636689320951305720 0 0 0 0 0 0 0 69311351930157471828783280351855283144584625031222533883732880618107015500753796928626282023849674069543909945678153651235976 0 0 0 0 0 0 0 -2238962309599340594612039124287772049435949896937490259596021300682934389779464703388983103688054964155172262512387385338360 0 0 0 0 0 0 0 55859930050486805831423010863502804739451723099262127194996955914684367190124785926287186367288567413459034163303711729616 0 0 0 0 0 0 0 -655855774962382890607107927269584141103256010635684812792331524729613596308402059553046721986568490518750808534252529640 0 0 0 0 0 0 0 -25053450870766921769751541306230130275319318316382888001579133134278556161745265417905576517700531601415107919053079919 0 0 0 0 0 0 0 1550256920763329664652962415253082082952640952421308071388853542127441807321351356020108019038330031155968382585812760 0 0 0 0 0 0 0 -17179563116769713974306461170386105618477254074245597996454513601919945016610714241641890478771539109259477941801132 0 0 0 0 0 0 0 -503980570874305053962281395108370840508521018857040418386394136001670429968785206008573056364222133487845503869480 0 0 0 0 0 0 0 36270002682418879306332121435240535657302844640603910146763474593398176883631295537466848408827915248314886354652 0 0 0 0 0 0 0 -1005066768795370063122191685094790077178711508213445206615659736148095121514604818035239517323783677323602661200 0 0 0 0 0 0 0 14228874597153260054998962366633053425371991921715966023767267725696303046549865617811016878613412368498277336 0 0 0 0 0 0 0 -5862509566587541337167738216442724121225083462131438439905621575600658466285725973197899891444782618533640 0 0 0 0 0 0 0 -2931532303346894960609087241175052939264265787576733651692477497331495631967608546529160184194481268864342 0 0 0 0 0 0 0 -7468246143699566034295187371803225132340168033207643526273526159877183127763711431907101554753517953040 0 0 0 0 0 0 0 1209711582800893039825283175898228042966056146144319276960495326666881829985858434130008103960619840548 0 0 0 0 0 0 0 32019147617280543932196717157984390913752948822244954909266314873528910627006140559115175267170232120 0 0 0 0 0 0 0 447521737534317492444288088258381885475797786076457763040208483311063281731737021274403177398478644 0 0 0 0 0 0 0 3619933202240649653033346008369295165422562102182651547937259578668252789900922988788021687137240 0 0 0 0 0 0 0 8050064488018729151462339856111631046517780827312137836271346836930611307404484829702478692976 0 0 0 0 0 0 0 -308530499238464308428693550682603776882399246778071636865835094591256132711388278469610197000 0 0 0 0 0 0 0 -2640091714889015672034836755870686530031446397197408663415583374251654189131253216403734277 0 0 0 0 0 0 0 -2831819528157978596920038315177980095186714412079621478868752275793484688975868478063400 0 0 0 0 0 0 0 314230569868678700635974730317815999844275368325820942451233927801611638014432808871852 0 0 0 0 0 0 0 6294254752656533725277244671347978337047682974969578829368107730542619991547227136680 0 0 0 0 0 0 0 85695066323593813323703205501996317534563203818376637717785651588791512963743361592 0 0 0 0 0 0 0 974239405315581540687308811447321641811068025585255561095556332776436693667752640 0 0 0 0 0 0 0 9675871904559028604265143300516813216001262793658542967856231029595010364120416 0 0 0 0 0 0 0 83701863898665774320081877611824807427174277563855175612570936305723229339720 0 0 0 0 0 0 0 617537379809090078104381576087417066453917551770876232906907331076117850994 0 0 0 0 0 0 0 3574235591053361200017317766465265449092582815103807557135838412864037120 0 0 0 0 0 0 0 18742283361460351971507129663307001972952523266753007979587467990897212 0 0 0 0 0 0 0 79926801233558336101632363032409541162633886233717940961935444754840 0 0 0 0 0 0 0 278317044424014125290972505330443426361661443725207489681051756836 0 0 0 0 0 0 0 595556753766118721166827707508804100930378696237185378102164440 0 0 0 0 0 0 0 -1123929866449700005822134634786062280516045736903185986641664 0 0 0 0 0 0 0 -15543988167802923071382996954183921355820597625467509809000 0 0 0 0 0 0 0 18734698177337190630021423706284300262258726233007820163 0 0 0 0 0 0 0 1641926785967755443096319015903094464473958105208672040 0 0 0 0 0 0 0 18974289853233275490741934421425615066686880662863172 0 0 0 0 0 0 0 93589393564548981309025997454464543434373784295560 0 0 0 0 0 0 0 438587492515171875814674508645656652173531183036 0 0 0 0 0 0 0 969728826997938263721058988822080116694944960 0 0 0 0 0 0 0 568202163107714805611747513052169229966376 0 0 0 0 0 0 0 -2900386702931095260622675125256164425160 0 0 0 0 0 0 0 -498134498450281204667589814085773329 0 0 0 0 0 0 0 31407379805272625008005333378660000 0 0 0 0 0 0 0 -165630541583192857898167021769652 0 0 0 0 0 0 0 1256384343756041675324239811760 0 0 0 0 0 0 0 65311855794655369986497822712 0 0 0 0 0 0 0 76959810858457422980573640 0 0 0 0 0 0 0 1347337116472878007460196 0 0 0 0 0 0 0 1330221808950339863760 0 0 0 0 0 0 0 -1262875376901921329 0 0 0 0 0 0 0 236113639631600 0 0 0 0 0 0 0 139700339276 0 0 0 0 0 0 0 -7175816880 0 0 0 0 0 0 0 206926258 0 0 0 0 0 0 0 -2070360 0 0 0 0 0 0 0 52292 0 0 0 0 0 0 0 -40 0 0 0 0 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/H1_flint000066400000000000000000006077341461254215100220470ustar00rootroot00000000000000961 0 -960 460320 -146995520 35168678160 -6724251264192 1070276659550560 -145863419030176320 17375979791969754120 -1837992529106133991360 174793089517993342578336 -15095766822008515949947200 1193823559507173469708324400 -87057287262523111483345502400 5888803645543527612480585055200 -371387216578945141427108897481280 21935057479193947415538619257488100 -1218040838844652138839320975239339200 63811806168361498162526648869483159200 -3163722179505080593110531749213322945600 148853128545714041905850518800486844590480 -6662949563474819018642832746307506376907200 284386801822857048113891815853761294905266400 -11598035656949561353514370576992525853093038400 452806642106739124510123551276749863514507374200 -16953080680476312821659025759801514889983156090048 609658862932513557240430349439016016235932728622880 -21089680665887691202317109125038554043124487723472960 702738287902614853277209386202177532936969537357152560 -22584554631904725629460660273807912437836400304029868480 700874012076776652034262490497172215987522956101726918496 -21026220362303299561027874714915166479625688683051807554880 610417459893117665381090487817380926861633274579847788077610 -17165678872145854347686423414985742428108959963942386282909760 468017185719976675891332779579170095025206055487488002478157280 -12382397542191382910724975825437471656952594496611825436993532608 318158825736861922011683406625823924518920830815720514700528268400 -7945371756239470701048526154655710979877914801992587988737516756800 192988898184448196238626043177558453537560930585241018779071788592800 -4562455490411826588000338764351510106708491743579287674725748438014400 105050537666732307188707800049193520206963022395913098710560357785281560 -2357231576912042014966126245006293624156243429371708556432086077133147200 51578471885289681232235000456209139061894945514109527699073502497270530400 -1101140399783626217934691405088371852530687441440756893668592448662659230400 22948766968217846405593454965137204290241826904572137988502256259628602597200 -467134900953056606833857883290348425108033632101957297721512594084884443978560 9291922486348843375064781808927582803779364638549802769895304860601505787834400 -180698237287720060527855544114038525162858282545415313440091673246590984895332800 3437031055076841984623585662002441114035200249249253774391743701544532691863309300 -63970863718981222244422655586657679510206176067659580453985107261400281938353838400 1165549136959837869293380784788902920675956527952757555871608654302713136916806935648 -20797053228106911001117186552115718780688636087000183840062036772852332443025378655680 363548488160561194231067741843715160993191734674676290588776758202360965205962869192560 -6228340136788482346449236030077233324185247077068039091596401819768750120887061985412160 104613046371613953485730686653334270834000353683346508445887712046856599252677133717941280 -1723262182048768033783127311053106352283714917038398848217713947535492344053190602699178176 27849147763466697688816611008983236586013607141424124243518412902136081631573883847192075880 -441677711897787626503337128984576243399233348348200145897204302868965224472680543822133975360 6876465066270728047112300473673661168784615751007322961123715267080613753428112604679085857760 -105128330335189774550767712326332921597351244193366191710738833405198535688002670668144668537280 1578677093866766447837361813433766039320224516970382312189594814968064677581506771199972439201488 -23291957122624423000879108722793269432593476479890886573289103827397675570874690066884839266907200 337733378278054133512747076480502406772605408958417855312692005497266295777683005969830169370154400 -4814040852280835109435664677452240655266661226105702128107895570421351327116814910490595112609502400 67471791320248579580684237744916560433971798747137731389262223854186752194121608979844747125167557075 -930072692660657343142970415683772894597518948883621651150445424205405076398968640706782975756155863680 12612349392898307910802401849045102131284537261376384511812858403997538536016317173220769140935749969600 -168290154585837123466527570940989870229378750920455041097920827062295514196993844072527874805918813027200 2210045706546361047876604718386822854629929773117152230888872037744557267322286805246579297083610294607200 -28570445945497884850810600127551391106230396487253620144244548661857175107992461308405054101428701199849600 363660961963408791458174924480689849652161189573471079264598469395924900303161186082698617205328182415228480 -4558566987992025695743319475884703749160893784794214937260459686793988186898781064980306610038620878162723200 56285639615623761715497375195298633791722702426139681655896509188331326363236338427326285782282416120648068400 -684680109296902745251529714704454613795202188416603250827891783003263257678820116759804681844750486508705270400 8206908877653415338352795364092584357247896501696311938977567723295871750825857345485766929679644345043534795200 -96950950208012346530407689234480396540288484006705765039121666704535231616422794774671859995948865196114291047296 1128968301764354298413300065427830933396780372972823711310824671493601052375449649678744685479141390770541415484960 -12961142581294664932433211140755877209386413632571118971412584540264199094803863510597536389137155707028033912840320 146726780760040886350493915862659481742156451763593564766119386526324202573228352305866982456514211401355819808179520 -1638139501650076731153615617605894467045341651335310431945788593876176540121359578908540234514500436151845988238156160 18040011261921470001829191988884912818336824935330106131802996890061394148086472362730299332590936053122203945472694712 -195990245808529550637156653706403991112795135099882634518353546459926257411309823200032881638024984280833820642172485760 2100919830069481402561715836682062294977401509180449216361375211442380247128552860888157353168584892473816199322800182720 -22224188081939815318664897645865671023977813554944992915244426935498913939504450745298821157614669103518200277173717595520 232031106522157357553203752802668970095577886758175699841301933600387470535064325043179358990810295283160257655730361086560 -2391285286040115826077723381825153150632073280001904859540946986281640284573133514562648452658233160800569243604938780139136 24329937503315131951372185570895453567477489767461241303468937360423665686063858433050202279952953670936024280864202704904000 -244417992849395693396543565390375016298566966169668102290021278770233147237009336442366399915849212740207876108911645564208000 2424737588153664094717983324838606695780101834842275605672597458709244744748967621752112126437913212752289498216816665654018000 -23756979515393203265102038868081629648542121348117576720747247011173723791248311979413952519706295747415690364551282387082064000 229914768421194222710043065045545549154224307713448992486342801630359038024191997045217251607379817733322958972490743990538641600 -2198086247543285425909202929556314590815111513304402455638661949652883110780736675047681416466158697010889827539197222766688112000 20762358142555598207772797236787362819764477228929627542934752546177776339874567071917773379446651170678948479690895506350564884000 -193782009330518916605879440876682052984468454136676523734057690430992579172162626004565884874835410926336852477115024725938605584000 1787329809463403198907419949362588722739724997196793043376893804294367724917712731339985342409386183756745224443177940823284798312000 -16292922263108496528987638696294756146237914184972871321730421415988657366091991845688708489752930896140435414397811544768048793033600 146806018308217182266399036169739209025997872604182642638508484633647798142391384859590967121211304428765381598480281106503772978896500 -1307632987817522118331636775779945119571774865257874260202797223953316470051816046584397892708521309551064842279247039958961441791408000 11515176209046138654287780994878496308065731721607607005663408206854205241374665797983014095994427450434377131499899953924323716999848000 -100263453456543146666626941591770341591441017616421790291735938124326514323888504220821799502496933962368010983362765255381485293473424000 863268334260836492799657967105142641102307161677391614411846427250451288328680021341275693716498601415988574566753408848834588376806180640 -7350601658062568156511939125845769023247367911312443449447405222132555524382819983697991055407809873443071030964434966435621247564884310400 61903596316428882808272114795112897950681265057033224736032559664822207798478846725456610947012830208701941329396565060472535800570937476800 -515662967373747392713567713535988994579461411834315600228310060120557808651406315441182254296475808922973453015750027396945977833882178204800 4249261183070206880341610870195601618794215672519312205727516553108827327060146272433588383962305463913348550331709360376756759650356026168400 -34641595930553305614975418141785095101789034435014583315264325423439582780604621040030015777826033115331679610323268690309559869149569127620480 279420420005878078309471533124776002943675702282428950325952813556989087522801424426657202736238285977439491196475421983157298944555486831278400 -2230140548458129709124193357836997257139243455599946949330501895118398885462359032339862160156518656305918929736355237136601245781779306111324800 17613980442914672610027193835508876484627543218766247664619612190148094900920298653573170579754726053971748583936213122940007987517201371416296800 -137679920526268817098561184842693236375253824058613238626201005376203457390679765622425149852761711908109447646914253034356759682244546499510870400 1065141930616861485007959711828472219594009129762544237008155050683174020358804368588034568406365607580010363159309357565796386269000991555306824640 -8156492261480470831142033829317129609503673516199663076188574712438719975720573993692156604913610508495574853021738323702044399357214800198295504000 61829124374972497639639167152591455700612667993334945997179463668397082673096136791470008549746922515292348662637998543062818705841744333646007883000 -463992013008643168127557643764580127735571172197770214208921992838944478821110831851031568585711418521839926247053298801037789934104417654263846768000 3447379254546673363193344949724555861333585814486941854692604631005140118960358548928278408702610276210512434484685474425254456791109138185627001864000 -25360720429099875350100607195364993553810553035269154861477769720263900353395333325159335076194854727600813213687338359684915395176333312217742987625600 184739730711977540265819078276581203042844114782779619465075132876060308608784971204824466718833209007092130737636214775290978525206910765724076073652000 -1332652416418026016960267539020807994599661819458683750671140274764058978340295005956169657356369473521245797799700557866201588677560963130522394924464000 9520559212206745188961911316902891012267075540709071201828569929034760328312446525602127297893385306596696674111420087128880841145626202703647278994264000 -67363956778807390328621254864136422120410736178798638251593746892834186524698151046697404914506138051717803357998451372794266119702666072911521083303952000 472109063758141793886420627839489425027211909386413789746586176140612923893926208585604312775830517512455605200639146704333148388916184727654910258821863600 -3277451351709414106318953118885711710932710775905682507331672627753015339428909216627335725055352352979030647673858539104461526005699133646529955515788144000 22539194131837692091816407104468132176004461811351373964354699464629343194925039612707661256733119870077104208183338641874124756711324369913431415391362728000 -153559712865690942869448367101986136288550723560263832375034456515116988596318562564626179944246784155484661190712502291792817448163331886076874195918389968000 1036528061843413864368776477938406419947717384031780868531482581477039673025150297311226714623665793049521463037309390469601517775102490231018900822449132284000 -6932299677608751924898377084452062136610333864404550448738555504918441333192205188417484267403076823915199544793525203460694950879885454665054408700539796715392 45940239927010379819763054488233903841822450609347616069021379734975385025519772478798407645091818634676123967480901149918097491942098052740638343372624843312320 -301686299993123281651042420812496659874645069355873321272156147235980087490421183049747023433122651506455806211646232748281049671493777763666869121045426136397440 1963317874173997606369674504193825919340463615417519348591453676934151663121256605315931800935868505506856926361728999057172768565268100602613296701803437278273965 -12662639312502062081392009205343125309234618046723845721147980303947396772999112369169420607586376717687635370022934319500525142994597362026157076402329145856774720 80943486682224719920282766535693362553645904590980890725184397173694513218171249067536834806955992710757115326838910919268741490988541598797973311464119386207536864 -512848045391194790334616001714698403965848097790184269480175951558522488328871272717981472441018885113957295582261802007580575858935034557269601897062741149253859520 3220841133555306675662095950162764976421879341424717874235347453348599566853290038509141217072762543632353015437083589880941646871645027636185605853522821308571587440 -20051552320178901710136958246126085717874557103005010525314794671974740160560331969064428028092085609981866893097031672341501380524226187088433696591856361229302815040 123750998274536953091666152757808006631957154658098087346532352191963508304353690585196134173374289548171671049188396962883743594727873557627870649861680677139055433120 -757172774627907579657157349466291951688863775908066815912857206744902650810341840173125976497830838272517039160219376972903497846260915248893490050264801772717479909312 4593143669617821714832020686100668089289063346501140611236082320327534462636264839285506842725812070403136450788095485313569012670332757943655362437268098988911183273400 -27625915209964124766580912739758762814410132828590801924514830890145170782571403120958084951869117854103536025178034159842196105404045201062569479184736595378560693556800 164754552302901990455768776701604795625069125492248043361418158134706344594610614264844231270929594158892827164648710967754546338750211597641265807022016072438807614472800 -974303899230111051472244132724598143912279288882215047791983640192292196091869963494258691400749110781366215319001729607872209283832186570223888441525879219746042151774400 5713596437628008380419374521192107686799866401230703958837275489984799235653037428777045611714392999653583305549288714343307741585901608386812945789233905995796432904334160 -33228007651453665758467284449486016334580783326306221604585573771542804065499933982958704975927675600822257521634161317457534383691058999128983088987034063237965070791163200 191646044130567269409751450451613009704377898198907010522222429006292651617214407972135066023132157162488935987453367035195215917204065635821388379439302097126009809703962400 -1096268979711916268371864940345590503064203641445496046204041586903128594565604095952492895153301430481929717746411568075452353987922557273439830030638805003140391778586302400 6219803864059969383748705946266301673635099826812293539921541503471222651111795461063796495418383810442615134714015632761420647278699508975002368993277108941428472799340340700 -35002482434985758738889269325195187349560285921922976059144674943672535746946379973986606484561387512559820344321632802298753435720129650507599538610442213077280233132839434560 195390569756941050494484619863247107465011185112104284165773356706117237217543148484925234828202265909152421785083087218311534589807573049066394684708975367520434178104548898400 -1081958665184693980289186942644103030452510916198999233407751784753601572075374985487953341157528193537755587299711789086432579293220166407755410022810244552119955244742195940800 5943462126994298689021006651146322728093860641012070113246636493274851879035674751362878826763989333420238462666660030589660047063432400604764515868545465005902186580914900674800 -32389874141740741848893002689468550706122247251689939140646099547242816951523274483937299378069525763337138467686764730461771531647698720074287160303751124730151513447670465422400 175121252859678277596348167874393297484434283474136937620426578218759496984569170709820998637429235960442795315293107976029978081108557746534979246708947747707685849373738316383776 -939392151101585462602927258134162721605243507377820658758579657994670149387424028310960323816673384953368637121770976560160809574158488574128034369763229640021361178759788319674560 4999791120007780521353737840990379222227907878083269164050598311300579939831750255944519091892689265968915969944162631823487466746672481950457761875910873544587376273793873359320520 -26404125653374422622573988075295597461177448140465892055901198925038356806431726841850793635616293639888131396829303310544953419158897813176273670560365920418474509994937579570790720 138364476638137396470241612836126929553053250969843992786443295665623077550587036112815522493132136151881311930137972542920632527670328150865278260663735699855252789389056017620961760 -719495278518314461645256386747860033675876905043188762489505137461240003263052587786640716964287107989782822036717457223187289143885706384499446955451425639247314504823091291629001152 3712780123123353471951483277769405943006928901024147139769561767027552580940752135693883186899045653408815203458702263235036972825820472048218299994476907946115949848606336472829140560 -19013217955357810136617786976602562918328476665117288537418647520319441242524616032470586511253711498985270213890424328923374051923309933291512822901652445787753017059105060663405280320 96630468469318490757620778115264924198846625076513814528779582017826020998400421987809373218586900846108683428822852760287780782876062509070156941709031101060542232268742808308319241120 -487406513914424085456678390241776535896069140323044523597995124391801690822120367510837215857274808041378390628402062350633963445701900202982804196544924170129275913707746743794163719360 2440078860284085577817496191147893782829696133742241646262463091486457214678240089851128811885482007757150568083437824642861279500045137891182663508953026626709687542999407136119532120046 -12124615454827754423937869272784565380520229235986293894471866293100408520140323427831695959679413703141120835197206582076329339130659070266746154081754169573712733132916308750904507428800 59799800916094912251397268820709060117504093577487955689401365235723619799951348264429167109776861412405898440262765796783871246699978994710680105625441861045657245513581053654152477997600 -292762215527875705378006260852305705360541513342548396565290119374892322701602306227082670880993468755214153100182129483641283772187627225638789719565046657143769827729065526478611518049600 1422752962047054495038237743288339312026534061792750439405708689888958421909616085749907857878974357304302926956372909746720141258741090846549484185935013327704783857927226979289349877350800 -6863705198723971988184468143378897529534067352648662725860267376676429720242753965193494878010082354025606847619835370656904439042169141296081147951541033993048533035818622275844378802249920 32871359234852757413293085385459177927587852682865583536499473279866033901162586761017038723000093201508177372637163371519512223123641369460147666394428445930563757611300028369254705709570400 -156286582230377780755417423928470582482064401378414810347189112480321143218701161007470232012347748514955046909424597107703549132695636211684773934833390335741722296666899536078971475050292800 737709879218390357970512006995697451834982561268350860745958132124373015312083456422166035629712884359281858328414913728624490846593092356345391251921896049066582031290781738753716545921917800 -3457196593733521677589618399648475632268083955766472672844963554097653420870828979209204143306110085281368235479908944811068619825454018616719230009006755448880076738356799627768896475563070400 16086132386136562629255224436011436618376790641242822848355095125242610917110739544438120455030194573279778083909458678503266342834906639563675946688966726823906710000236638268030571248061109920 -74316050204958388755038756166368625312968798868899590936845176309600366225248445848573772862420197151409501089406271087822107665728516054124584782949027568367756145615128328840609071847767700800 340903276812280050742590573344563054487978966904428937495179326210899354370471068456538992956101950886407536974078766792393272954998832364559868568295248554896276737734513089856049753999352999600 -1552784867792350751359314287835350791540620959079132963850874618810339255745267063258686280054383452592422769569792301921421382014676762446665759721483559891666277857426568293679579226309191697600 7023228108922873800688392784634603867485452268938377256038151293124925254434052751635552312659768834426647814088658285127348434744543747388080189085100928935295176286176489926010510638536401528800 -31544327392076450327663295592701706513391802762203225847119925236549664285629516930203109244289018879196258182135345212057690684052636488268748734976510457960811477491055549039110064925083494866496 140694869333977349472816403637902497801207756638235978920392848356201627637608924944371822481629998978233310641910488587870949926030225245971407709980458576700210283127719352248303414580628087898860 -623190833660103062071683957356585075006479554826988742788632729442158621852459870940042422743491068920536246007106344931586580463320319733568269178670505786061948372723909447246722469102895033405120 2741339453684610660686115385450596144550974670952428009008423748051742701744247634528388859596368016656066745076203753266473553386403428940359296443252842867901716718218096051652717378132397815484320 -11976131021124947132159453806828861368932191020585467614774231122773535155106154470397765855890278150977900528768666676281465467866857438164027764349853201802788505439366207331801256925695726769322560 51963101819436576167869630128518559606311339928206945595214858371589616422988370229892528519168373532854112849824048189865691835577864773367253799762418614488765681934138932922982120327602014482449552 -223929389056135521607393986189196002723330636154703964443467345468728733756524468394012001353322272683017723883219655182846627799727815045450043998976168614923962607229990981657050021301268349703373760 958467000410602040286592940886723550117992118486342792865170670989778481298530554279864555243066211099290147829824787843063313494439384178052660852760633796844872917759137223685944871393890353950154720 -4074794132893160586573602776010223617441518405368167720486900448251626548908506946610571715732817006749987623014227786567777365566523720713251202969659962261996235683150867541134782021554353526629619520 17207146963358618346563529113912737775826411961799273471838704610279966459249510312589207734371732686112719473272037990017190288289070277142370569062096688465060190901131652605770247993194199403213121560 -72177005640898853172612424823763700075898895580303979535928836635552724175014162176049865956067376023910650331130278271639673857904424513851240873471281244588576800752854932011230878068749722902126390976 300737523503745221552551770099015416982912064917933248066370152648136350729225675733541108150280733432961043046376159465165307741268435474380170306130338519119070003136895550046795325286457178758859962400 -1244763867336357227174732994955283062806277744633584673814815498126510884836474187260753035873354479556747846619760146663304535784715342551712576561202577613893904718866081046717751774180309392296030004800 5118098241760660301096109601598052167815173918094473153504533936445706989247843333790223918777143684560457901261035071120927692348856169108903306818136130295425469934486599197408628305539250852366123370800 -20905671125075289695482521758908445891816477591370017325425926978497808442853624622677528387809285314712558199859889285213524753932893981757001867003180384063854300473141029525923074348551860624479615038400 84833012828594991343247496190096904118897390647085701883702051054851633207579708337286180984215573566544117747852498099471724133064532947024465470839221453227535082446272282970982580645965708113019911550560 -341996962712136876095814513436516315034298381142701520682987326242072029161446991726232247946837652598109794062023159877451453311307279419941562369351835177932994834992825433966788414122479556267148334523200 1369769085029339883946257087670213782611330495305924319818839863959132241797670503320169784745407056499720998092165676800834206231225509760078445114747714853283713688070222701669064012813472806090818069001775 -5450687343536440574459717322957120129769439483911657396999321323941002910365859826683369920644935851770910500180224040326635597852752287542695574342623031126020166385688761838766016382594544637708540295302400 21549882435528092374281459725299541956356495279176501152054017811663655836343373644670849119250854630455094606382638345002729399758046415181688172787586932338440554731047836754296569925000081119187888693283200 -84652358695459070557433836664509995582405514788970255807555782788381335234046278009322412437672587932967192146097953703959439590844428482200887899257905590621771614994782784378416269551538780191271398661820160 330403338785847902941004515552806870512960300069195131085613131801590415581864299373120640381732294738366846896759870324127404525489733616753465525164784575641098395260249132905553296974118198195523571307614400 -1281361171738009126126535278590580959755846036816574010910702704042716129464692003660224209399205447614783101670682948871235213489716530371571815539217743227359386669943301205786003649178813722951167555731052800 4937770575939903854719931401841481173200558212581040254165990723154507104957373731276520564502998770353936901892581262569456908548756124613683309375874434759975818329124943535427882749108256922281519419307036800 -18907443109880435865811998634186978160697614864255038561178316236400675447123209965993510905282839512611557383126366442602644041779659130430284832886514167271867203853232195849226365099600461179791546721165638400 71942821033095058469414654803081451901454424558490421725283493279504570076303813920605308994601204345486975842795824314103060578971602991287233789133186406469454710661548505206306319203979754789106835274035254112 -272022606891304698690324067912148773358733147584341893090624153693649120686521883480895695700979678122239311644402121784668288756310538673523869053438913775705400896033715741078571157189177182287170123424212901120 1022104745695545872801762215570895638511279500081759885424671943829107339609257968128712044737839483637522958109411932844372431515048014124775329760198690870100986535096981423161561922309829115623574869697908871040 -3816529050429673751644018519225314748726846606216620655920696223755977159723239112520018373947203589148977350970119433970612330484760565057042856937096589554367230510362127678603270626161824973609210597197117853440 14162316133212073676443735387517466984246190592676381551627289418545464264267117687145362299402123122479293405315590252528203598906685037981281581869520187709098007335020248297562136588257360318736139323912834387520 -52227858520528427801909580258357097756537171161284607087952345367904248701394834007228750723648805271191930802041884053225960589138799457140726223870035423941844358757440525429058415905963728785192786970137086814464 191417636810674577623503558713881596146531865178494555103903013362950037716277182890571392215314796018203435706512730389250486625241716456996350966125615267359672285737221343198733514606808811809808515351716022062720 -697241053890090007382230353962641176301860030650168572697308560752001586657357468113482269228731189360992224747394196683550081717064029993117143132650791843426052673651521221120024492819004077799978843358424544131840 2524146699900181613263555079489753873823560591728735265582083395414698051697068141776212253505935507638592044398018413955351978523794300888544272975413683933172200304132670574535473284099567647035500331965835008323440 -9082097216865725230498533108977487622561328062105305835969984274410779592709068146486658443236667472460388599939281566002031999281786192670743030035938231185385141764152001301677875165755382155840651912145014001240320 32479309570791236419544754118295681926397892260195641346730753286107121305354810371483240432717796532465484945497145028892981102193435384265371502652331483905829721261324537988381353568963295233506331362004311975864192 -115447782834566006230609315586359058980087294763728582986009786561992137341308567671148958884067997153313335114326344889430027614431642361132837094735775416726882895478641722707516659605319769787344779722764142094304000 407879195014575182390218761198976109321157470651097682342081745919491089003019420687219670774372310697319283021841661897090050392496698719285353697910829184568090984497654010886462160586719375333590754775237464286008000 -1432364497046489372900862128529737698461153934493056649727122750928541476874453176873428703001082105171806684039143488727809191049706716629227439277170423615290760828188944601610674629666037994129229505032289311201568000 4999889155578166175499738364540719910048981257319221109094208854876731230024376276282482435242095011978222397089907411587259185580051015523518210934795824488888777283444586997211093216637992437451095515229533249848464000 -17348452604936334729873510790452916525100186130047157894810603747618797663247370707473171612514431995050018177809632228112071406710316546886253885383059000319586176062556566976369653672613685387621010485401078159939321600 59836098104988747100721136754108438940739067902245984405712499036925945644070792486423670607978017760704923807723037083071727768514749201066014558381384052028202320215762233321274962898598127841563207461221311246087012000 -205152336359961418631043897442657504939676804236271946533871425269460385065385574239166870655924632322416881626478984284817352349193425832226335628736173892668122240739756228530085587080907866885359568438473067129441184000 699211861997483183682869797247222597110916814438303010434249857684445257355878356237160481180513769796127261690247180383574737593810621070386088863077877074552361581970820540357126565142727271081753024540300407693462384000 -2369019185397865398596755203458626333590412220608314309325175316903462926749140366794397612036261265701947160612618300660330846094098086001034145828327784426108914583663693337648346627104582808870597005520104577664607712000 7979287347180992092546343662558373241774979343048913196408885953752118312368695508157493775085770899477922027336137094496841622526030371485301372994504037544303207756794530741806476594020435733514147186774534054770337793600 -26717975732642235965992281947028037099156039429213555499287672424328359959967577719622377346441042830831051132256748642206619007553223868321823601882049718474137437737683044112836165970928155849775877457978077830452714784000 88939567866768524229136470084926664037280689811661340153034188835939900947819999706310526391981669603532192733052870480138249759377623597701926314373129468253998047243908872069305975912233816094524204691197295120290793808000 -294338121460426775251581681267604834347592596775811968757575028524321286544803407099807930391401220481644655771269140871488916244038951637237765112140670616912334344690604249269721122077258099900263959919747102236657425248000 968424979983636309644712942384931977295427427784702772206842839385824947247857638538207342403851337031125496890291771528068443177931729270733182534141402877966028625165068445141894941834550087618279189557382206912573760749000 -3167825712302028106215594335979155267953042608220183290418828132390965160775214319840536017818820373577370514272243305976259440795367789970042765978346988969702209191651068336108598565289906064386904371174370241278463501827840 10302442028946861318886999278516279300643744765671835037424064943837873421105232411870769792463862719377731539779198362356418977807943918707882446876482464127128866176387324013450530732248145828868914658465319147520666698422400 -33312742067167384176489239957845590337764355321599678050525390611352418903485641367018260033781829233582620925982077524095204976700576371504782889900167967706222853627613637999439161046123960521540895856006802882291494963180800 107097543575586371058625495127635165427988037064616508820329435605795276562521820710633265810360003632526583941863433443692040561059309124179850255687820703195883121530880687077144320380740627466181915186197309266314323719348800 -342337999551655998318401145997506292983787087909603862255376187176603242112515164891631225210408395890871001945170451007784164588189582003928604310757575348206927707251548746464932936762891438014171012734918909969179410316870400 1088039468140263194655440164018161305091949396790958362211652142722160739061950371894706198386124075635768271399650433420392279625941671499442651092016467737127235452177748407242895551189885396471126131779242274728131082354922880 -3438393124425939965794248137373410184922610647867530755041151793018083720845124551875045561999439719541605359834393144575265645571157663180056862758320439169276544935453490637607418841422581555947714615579423638751236753762310400 10804261153907371702862098673039724244864582596100991036314653694440444105586619820331500925420653256663061669479623286186933860436956622664920055822481035148287074387696528770757794549125267044335706701540516520041601696089328800 -33757519828517453217526213879712099786529682961208246671403724847865421926468065361379110187580410175324930881464230696755741847202164898283527041368095251450442017829369411781595169235035169134233452698375519427426120320828460800 104879132116804224312570758506626908311141365439309381752609008394863939062146510759498346608422898279748823721472203916843693687675102055778308372113697640190048491290391292159058495871241743421315043212474370186917903731804662400 -324009574114041986599686683726855895463355877910377068733592085509239233017524965154875743139212868728075089454420510823951155818094145074447029268742742496927554062454570545138197736180942577548403069669176139385967651528894403840 995368395053730679172766295347332729707343269004336334033280771161857813295362710751207261762412414524806948535825721810866898169992606690568204321349526738442697861354083242479632875979590545434712819958274157011976895586645944000 -3040703451556544353253513914900712642650280703625061206076351385321455935974019420185122605552686025805739370210708112198597612974998511577938311935261845395073895576457199441161410135903896856095915956328229914247558111412369888000 9237094938972191459673489749887458994269550204709744756273958199947111939954689247032956486615932759065334305303957836636916278071108923827098317349555942103522800427640988218318065244783686667888013598425673226894892918282115248000 -27904529480911808509975981587526131355073703965692199640292041089379978329068140737898722106011311514833353005980993966744157124549542439343786548645938871124449631417392441395923192915204275205921112209470025396728504966525887904000 83829857315572558065386178019193086279200585663600316419377340106012351563575539466770744326808981675811864655467902708427238695000917078195292089890508025336367434383083126026919258716092843431121341262616201296005217003604854911600 -250446046751918015797004349268958598012549467542706339510172966291821133301968416664211352345653389238940010588949750830156065810791121561413320766477866299760101878654854152445567909857206835146918529913210227938272847479649359072000 744093833118301873380355897208186908971169699021511810362869267619088408446757403229619679076548706044619287658904424987116575694044695878744535665692503593088897730383636924001501352013767415167910838874372536725694947677140037904000 -2198598239419509239041545408211844447083538452252862056956955284569981387920871668801921520892847617037187854070343115805554326536313134324850109497807479752419047614878400458572337328172366271977613095933331199049584248692125708704000 6460634990425361165544213351179887166224987992890582355894003848510969898111741748077777583935130087769113489214901696854846115272690644716875116843967061403624824343720545609821171574998305807409625367968026515239966829148582512872000 -18880876135283912630733292895693058004151393481263905987020843900138181416522477924994647959581849562623205135828039244685999259327536741295030953715430269244879078490220043496456974888566477380021599034551457081272719386409735017209600 54877343238731697280383351302522505987675798126437775531381721091865039482981998847037289801223668444209722244378244146140201099264995000105476145961514806951579435449216793089295679046036712710225379307741023630528432362938863972784000 -158633291791313489304427987165996231883402914422172355179783598621828494699794118124634108980055462628201383329903102511514589412450228461843360195208589360985537315428100365448409371817288311235226400104158262640474901648333396261408000 456070713900026281750230463102239166664783378963745521141877846037756922261908089608323063317659455056078977073471419720604444560794406827799660561224694412833419781855788550664176943974703894801275900299455005091365342238958514251548000 -1304105816453087199221542529031302356085645645872236188967939864975433448395496224100907715189451935742683661350649200164941223001147058881097824576674628200551786685467154409931301141003972582724933498045027966365671179414210691353824000 3708876941992579994586066952565023900707576216860639721424820975990132727236791261342981541998801305252192332881246325269092838215262235457842213096062642602369281333468587141844620445015298025269710868440059536343968834254015206210275456 -10491245533126421498629910503271581551802307226976311562596107143239020861904867711368593206450792536769149626875238609326915996545164092330948092821531777879211911341684051277727810820561201585424281739412120600813617021196616718762133760 29517036043597749375113518042934727461221570729865892451907301446652642028137107965715605489577825034005266212121207039733267625200481513740643642105023930620481131512912668079004039173721793349467522830330132960225612968366671641279177920 -82601033671411883626799884483785719535750482516778861090712922625415298640004238892200192437237549897532523629177132743601397148782375145171445449052794240629646802810838612647963872470336085736849826734678791050749936686180251075200229120 229917050416095282378533536732427179967620437556545885004464709827435496608200775184195023831208455817147614983575719880811762929878500896205558789292620189469134998375050784024056920616250443369893021659125611310551989122556840591206936960 -636554657230444193565665399737621917871137368293809391424125824071252786687802930509967399313071254144730259523154738179816096582330280912631860804865058250059644348442297464788173278255187502035860679573892868961763546355000507676047441152 1753011849013527954936695729746185359762311893152873519351596507696223494589457289099714908264512633484511066264937853190509172228683000169552585419647914321453317443952420752639305317069949956778444449607790908664231641329200616842240023485 -4802024675896979300682621765530406588609601450504369484916435569720394319809252651852915546374384801451734593970880344926530962058337868168735486908296232226860449340632312100615062035864765640358073511766088714784510021384269393995863721920 13084586616882079257286368609177813301521510929087487394946721726796268243511258194777517942252684168296780695974918149160276226073688067141942043785008725796445332893273315529970498493073373043301262320820001420517482732686594511546868978720 -35464786892089651114343748122173069257405794101233266993253276649463244428358699817505087241163645892449189376735106334789628998856096614415611253811104731695384647455899102324476022942615860526631220653342243232445069028362893232069119780160 95618521582134020889057567052474313651697929480632769854886718966437439785690186815657946754060445271564929819581959771875115108454322025789782649698401603532556299486866425882529584933745070112186483376895817330553820726470723675694049868816 -256448142174305803150729107037287431249764561825451873174025683051747922796870232838929359110506941341361880742173838468630576919226151027022405573903759089934059040769373556006784327408511682293220453501253149928688408078657113306459137579200 684187982365800596955571167248335551311394766091568165452839513180045030667985850207677946634520427471801353583127912555621272009691143388888020977705067190320256753808366853621153606330342236347179759531969281679974035293821840462652431938400 -1815829702248398542490451234750335417548872801262032621620083574903693655537087921843951356467282351236948079091343281231268623052336190438949956815354132695222582563339315832043974209956573691902401034803477409173467211540257203965518621646400 4794065539648234030741835267503726462240774024544078550262114589802554840565720763353159452491271965197548526994947981129523599498023957333136817804173600335492954722149633086873674334620196451727172429007665735582979721377118451378660906392200 -12591206096585550510929499419556957047998410268236523286726157564160672335976383589787920675222359576518844433164089791947729906606130846429672547893225757862275835798551489164015386176964742378875894379582397554587750513503677140224709399430080 32898076079424652650736849987188290031424417806106705579979998146961155163547318025949642365712556036393221357327227087983730395079928339355723386412751510204066563458621372063874787191693593809468972157179572558039423334154344407729973806781600 -85510355052886550335623123187672933639732381863063871432607186194723002559931980187299819482413909697591369370730695127568198105563559054355325955694567595811319082547877274203479783936462000388657178565852521929885242673794438273275662254331200 221114462879292460382786658093497548553487091907101727249241716540832241694152471155965577989973281419517981245956610908226721220729650838314331669016176656333000463454025936653027948761075247273654569948267901856009228257237110908134455008401200 -568814900789852723363897276582529009661758615612321171957157129539984800194622713903078735944466582685154063279561244418189186188642819256927574405052766714432848775874297205070242901645591342428880901130860178752261657821591378246948114742801600 1455744801651067525349825993031583502504722975511533073416279913007887025683275167803805209398616328279412806393247481085069361690193289283470199681079488146937401867144960624827917944581865250438358158079349568584491872424887564328300545508429280 -3706508904572828754580737768235397109698372151671431072535915645665837814470331608061349057140388437316586112218969601286707968879089924743890914317139656167478993683874622993104292921629103405175155457840410340676381520196208189618182200741019200 9388914100186319896713707067331575766846244163608882385945756911263831816801685580714226104300469240114440556319375203259344818226812346134341323398930967277180245030108879567091389055156074434432654817838392370316275247849953833260763001141772900 -23661439197539150508934177517670784350147311298765242056888940494320572490694357800481273112669314421973388654753590255833074120659512432748816228932104415702197833628992341180069141648158898208387056830303347805046144214361788414957527270276702400 59326309228866410217656131221313243972814608986320150704681394597073844164624174485148301563517587620057364984728892356778547156544105990140280106848013626231423035412838461279954380701770668135627401614665693219221536771045797960130734433139031200 -147992175021826754215680385519348674055821170053147721394223406158518753079753395261133581354811145844943099561905527842727575815960933488131753284719044900344568008338935216138358927859689739421965081846038783812312633545226972365998850258666819648 367299419891127995064279217683890730899411237269587641866097946444149803839243028093755446478426213419514576811251038305320251572221882026703807971132412162087061904754241387879622701390896635884224931393248430838529543400291579966337726185459316880 -906977628900835915609989115147224765109015473979775982080906120461366302621091087422847384083911660573819388227060325634798021932851145509983410296947905844287185353255960683428382410654777252508338819758057497088643349046207367137093879822578240960 2228293958774355864610153113832929908523228664489881279716758562140694908957572707589225767371624691265894396255691375570385068273875296342872910909407984502331466173646838657487716498119470731881997891707745577379652544599135366023867337837485390560 -5446940788115092113491485389369384220834558957641932017085409818566143110785177729662551875797304800872186301958356695838719055780584057727022671111886184339032472868914494496081084773180928455711550401952266966928039553464553116947231270269408732480 13247738131094206176027505536287680908529766607693413227268443165869798065873950121072135097921302033549853112977288963807741703523491940400365853668551755481718264370467038399397209751915043851212735084748192158849981913962002402289516053762383381496 -32058583377736869038073678877849192234164559762389754428977015490361077170086427339249294898884289618554804686208386104588129389309517862890565055140979337108784411999706712140890044951253486899731885614337262163765080788235450653227298635439219570880 77190702530082744953375985666878019599282752051995188855586501836720465952087532494149898001214300180846497808281894202182056224614051875541466923548670106017250410453194530296682058588301835478432447986294329819845708706425074445182041749869610243360 -184930375672777742326462608770824372043511328237642183901369781785499914895813947106125904045311998313123411710300792470245350248368647249530440191399287391801045152958536719226679984886461641181544875387659207130231061847901768458775350906048041501760 440837550459403280123292908936084858709356229636914642609955430523885360508683247150870552953085291753466724393921255289986275063892866858915873273159568888201787213214539996184726583690614546056006621962835504321008552362779919882362368180966634143280 -1045635733721251288994196513827345138552718635910716836506420600119812293697789035347328048408019849913485984878213223073792006818216063146060106430371468661138274232045715920775000598508264677662668338410094038319304496130663950317463020667836648003008 2467846574342114056192596667249853036794003773565503023223195472310745798062963632375686827536410484935674964310468271240593023084950498683883118323429165546392780093114888973857081832143631669308745204289557607921435436672021561063942443883880200706400 -5795570003855696424647422138419515494073723147676477483109525255531159121583405882303877776165646922810609498067092734551079085572322773912673246515648981108950291925991063304458791480365183780885345880457009852749294370442308474414972847309182074132800 13543120182621123936762899649848381692748665549952324118516355892265521141755667218022603275553751316151181222913727119280820224271434815427878801753582514883067869674277727791322106480158919043527214505373498718403733025373866678059988632774581721845050 -31491269075160537320085358355356790648882710206117514905339069756409793104705219275125222841426023821638732808989704581857132147786865729991469047676150346025680305955413955279475624756632503796713799818723152729298645650696326670091046232610792100622400 72864281204940415661300949849808298363449305338982250005112123470865417838817938391755256988265041325239964533903764739400467831603403120083709417209299593735280983779595737905269462798966931198603309235735294763308245626266328260796869041661522412129760 -167763121674605080732204936080314638843680531192845730252320009365910068563601438908852309904252844288353182947476021908585269577918488283354245049932064356710097110420375066654744123970130047776852980027294321276345445256352027267126811882863299024491200 384361398631201366472072267937433196528843408794567786091787966663677520099484118595966422349127235715439312985826913208368305985025577608095855953440243337804982763257640135589122667589099321790118642596780482650257201631847624115437798457655983038988400 -876291516333250896939741552840291383212516713565772290475475637308315984390632734546435392932481206341001573633216307246382349481218723010948913914327926790627059678689773414926737003240676952067574243189929564540518125222096289792192659964894869181038400 1988049120388701864825876244028824328580777714110102441316810374437574019008680387559429956074710764045741665351548560997744990149567647103071175445090908739279757842469656012775964561773916758602285783019329998464372753480061990787049334001989380080791200 -4488273607386018447369605350926091535033213415584163477684731218221777276812817417337560511002567352049030336014004547879654791320718823629306450326883204136814639739270477642402686095394673088912279089799572132126346623110919613098897818458728566555277760 10083452530107102255070228237722469158098266626227934840068737365261763138785552643680668039921308409164206667058489947094494716987425735518543207660058549834397754819644823081749277883234654067995491874042957661702771974218788995644483274577886813375877400 -22543476363606450832884281312618584245714643231701510888234483537150877859103053721898867267702857857525364400427061699901496606328790196580177407024508003670168717845939941165931045503258620542589247826143178071955018824516080448174871698046184660207348800 50155452446547237926853283591497051526539625713483562815098867735339033626125250394694459726466425367581599320413227875955343120791905705814287318312915457829939127288114701318833164995504917515894870163533312287604622418302554822617248106726914193682792800 -111046520132489202366477838587194140838024188034535513657509867694964683145467945689925526217126333088090363712754370748770692795867028686451699681348327869844213051052615158103904866980014232092048174074444992422723277728817027734356582764726478917117086400 244672499358584542547472837687117756979779960969426581758713408487905518530514373670135909431735020570759101380435463549791426460227019872481911631237482406556749422485928731688937056912631358042812810210693799971400288595826851108032337358280675214047980368 -536491194606863116549275989612949234573603901128975229105484550172816087143320553562424253239020310886049856847466464926452961673587485434677945769490825210390214680533930109351157666320055469462646029033414976681475715857959208409639012147725068575653378880 1170687739224909913264810851506402468821208512728459191988458008489688084196848492707409214849385380377175018749935100617657290539384612256466113450643886800156130710171721662458320867897074683363853420970266455738716876656937477953483804653479537057468796960 -2542285585511520537716981981159118232621634327971373426826420361670675773602397056770545423666322047155713407054314508932074248102029950048695388285556691467005722796346511068968894822033911358592130531347971379128962722245098549483143047729338400606648410560 5494347466056148004210714347439278548790834715385501123108415057952743365976233112823185339963071003227972725114094185422278884878400253888134441130298507545469604859209400566817644401566709745378387365446109197657001672746808378323766389336103056574236860980 -11817350615517485543482716760393989272153401879648815530357771403334425075673471875449211747592703534811639697294576346350868683541739562461036699611396134261731346844725792694532376155500857681863023317156221749714731466629200971083248365260601983976063543616 25295309324065205983598625745287787494315288337156778341125294997333491583549425092873312727690264102292888894535776166208558783398168017686206007338119176279196183605540503970322569875336803207909412656004330869487415394255315804116103526946713397072946474080 -53886424423252914375483717385727078245218887858307925195752257095296754057463596126186145029020953494786805658066441735180447701441048480673546347879902088881414671263920161552413552763746805530855882335592287910895015204700249302579582106264334077152140045760 114246218014234263270100219002856435370545239517776218028656571049444092206245871007790755532307411143168130177653852120366338795587677460648784951836285922206375910179674887966643019333528129907950945341369363655241704313861242839559958166852630364871257954160 -241063217298643170395162921650040116056943353286699333833929075482969411386641773129707354715418873997882268206570587645562630727259435936385138474424784534882061791058731478816347082865567445631016234183083576385817447290089094923602241827792605171184660796480 506232756327150657829842135465084243719581041902068601051251058514235763911947723572385444902379635395552763233798234055681524527244815466408790796292047523252329761223336105514328874017691635825134091784475510410216639309187099339564707838364470859487787672608 -1058042738304334172313174881197121409703304428412683571328981312007245165732366624829744498992111778157907704507938431306086787597135466408892971117652189357279788890016618870046024977850480910888543921736042063558330596626918374825456784871179762246517884203200 2200864542177925890484777236849140368261040301409716787796502793245840104359954934341359550788078666745134936620679621530930529328656787497985699536398304143828791633399953995704712213541545228098285273098369548876142811573301363018337991607037390057660598871400 -4556422438758134111930145844978412008412632956273151688473270958540908586662143122853677280864776281312611625975081133393108571900861336417555058465131313371249383317709808911235314742411889162324884527053493506938468184982425825034770027352588590279118428334400 9388551967759594810250969304780358501410743702894041854911485064254674699268810829574296817578058133787451343967762717532933904521838486185216951678152738061141245243816071227927543434205389452306370347145255729264932852495635378335975183748805152581495615071200 -19253982765627613483879765621867020926702668038316035042135934449233396367389370780650780140175954141037122438740237192146905721654310038335397304076465615198403950563508514327749819233322798686317191251605826035254433722895810966365206249846755963706813229638080 39300059758955097142729268437038697777605129382005831019549613037201078028373873903543522754473070952433367003124851230806184147047563211159276142814304815832185278840072758675312131030041788457830975814195436052971866301480373649701133009972017710730678902267600 -79839869037120134258415296130766313466175720258712161440346847936774429811586040359249301747257595247214789747673199345864929308197573211314113047231584546990307001807592607529656190483744201157233906701393882706983854568307131326206718165369020207288824015963200 161437219468139139396732815761266476599845874611169559138814538438194837637892528147790254790838470892953175496081343331418709261544149606525077639528015294700526421893968700130719907173105413031765415122629769121354146186860017115568930126831069161278974346743200 -324898730089483785243581403507000244442323045455708015570905748204768293929551733764518318419179618536915168239762452723419471303797316762975234622498388147955291419611059264839881443276281113374273970246797215598461949379197902784311138374374753609846713262097600 650812768710497207316048998899959864648528350428465118690470576872676488777633316697050756583419173381758196380274163111599628455419000140834766853192083758872943124908403089882387516062800605227842546650615672495669092350205799014823249056169428324724197503139255 -1297570629204729634524209842043533686526660885589463164990346321490694557064440257589135464839215797396651855711450044833095832434480249501975859146551195033266927102621115194781084144175054166186352740985651185038094140511313742584071275376786399152098088479779200 2574992646154727442425372947409372750591727658048655162822457451653893857031606598134961372770990355703293589439803039280584586725567948545846503088963396354837162790605256551133890584248011217990929818291400954159447688778662986059694239024119593348418256330990400 -5086208384664755753149807865161547414481493021161120724088940724938651024105774023560697696061584665444895696788217767990752217742762697127709191859933891251969380372774469596357344250000715656588895430557008695831974072572095929121005958196248608533408196715702400 9999736855035337699865517315147857108100960044690228090261281610450372538133882879654828495034658740396291848315107154969472724389320487871452948193758915825631158325485608434813667553242147756935575275508686849521504580951929342129878998058673961838830312678711200 -19568715814776845468044520038258575756160647964378415585865154166912113643855844650647602839513978335052435740087409694032568162189562554726904846311478986046465897523104144506281515581113864533572387308380076419371313579955160189521855516200974276090757165734339456 38116977123875143779779970013172379156938685452086791095166788024506724428983010285770637432795632646497842622562899250646260070522614178685842261987083301041428972169236600495364301822108294413553576505586958669634307126599775215786436358244229034716658896445722560 -73902640662192174790154437273245530230884179133403747872586371888493159902064919025010960649518137914004991506742746559356969066395527184363376128745598816086440270199681971602632927691794063174902041298293981029199237670532897513176148780204407363946060368032379520 142623083960876971470023654859647623890700260339770037815082845748220031152460651654975421009588357620625486657829751744124882375086489962506149663097451373727794789745117951294105619600322079236929854090914908510619260504412573554391774932528627626152000649282000720 -273975042745514425437856990490265344373624816214998978416815679370440910906854504091016614219026875429286649142092410645249014167339397131622755583822459781750657468446548769659193773821895301148144886885891252822830919874737831265579336648504840911027551399228645760 523873490825513946822084124240477067575021997065649561760638465705297620552197551761913586582442298169332956389879730658036751332094423000163511434521127643286863219969006889863488700853381621286301283712113274336988819518059307662365337652141074590479954342161440832 -997100601873334702410613287829306805354271474777520313925082276115823265703578421782494137604044253313231910953547523608952124891901771873422997594405771647343576521391161149891232270506436318460331748455079646019042164037393848420816201573561561909372722766047455360 1889085176440745565711673970013957772794689029021265895960472143604978416046839841268641001665493479921755638523437928765153272762066911169828510502654308331864788048057350491812003307676350735878158643910376799234872051745544369447871659005331995304203140421216413920 -3562599071485850496297090850356653097042236367043108056045575093645424760592839100050169816954744460633220843821979036830379145028762823467424338125125842739973233916456504831405219451113358144538989875002152041800299244733338930970760966532578057210329045599170894720 6687873107250384015503820249022818837860725156095894464492741268609824326023084178836696033624625080290507392444254060157627915967168533874476227558245219754380891214425833920033151484575076516844151651575896198229903073197016496163674029987803718176276382008024404160 -12497339000414150428971317838472491320897952082734417715738674728805223964449106555079915573280642687348828739313740422861716642971485081210215278959586589749977426567852453832658963669683575819535638608616450806244535294989051721189432664992134709189101537722457543296 23246538319222750053890100145968175820122678725324437715287713409235907671966344038467104861013100236883982029973475488954086017432077904036858777826611960100404439300320784658963846111762603830981470626146671886615579045738563469474391117916917241795203753203976085000 -43044035344792273096817277421614663833105494138286199211690009398703876520198809139476182294576185601826720435321806246609346216254055228839762247370343807426268160603561334205321780337507017182588835818146953285602733900714728798077210853353579699941267483677391920000 79338562188773923489104035010845963219008055763764207422730401939031109680721473650572963223434803638869961039069483111353913292089575170317076568377882224930665869988221039082590145414990744688617883771318200878492613077352887695864208170530414654033756338257441320000 -145571049207720886165848701406330941363489707035579165241705929221467109797665948704001130162172412576333674826847252198413374830913615799224842553188916648692844162633255121856551830230454994679410984382772628160538068832193203972942588442684123642504414284354361360000 265881239876454912673506010509798572313903259026749004750292300136856103483383982779955005384438435911480035492565128280043252264698104150937138898618580114230165367633092443155643195803272210870335945005005300257923943367035234315286315949726002299986003737011936484000 -483420436139008932133647291835997404207096834594089099545986000248829279060698150509009100698978974384509155441027505963715004117632916638067525270215600207691209759332895351192078537824131292491519900009100545923498078849154971482338756272229095090883643158203520880000 874962719210662365469963958030650272526879943315032609996974661269079893972433202237066179335286506269038500637415281261811659499458407599309351293168001545499587254465094217508469634248939386117692450601266777563290382478441308033823655358215818307768933084584735160000 -1576463441609881463149964215926944222803532959092391116554315861995018584475112883330923903292148865522640797066829865363847246561706402030242504662326020277314125140698041476443831585906252305016717010121232852869135441316841773658609384872820337359187173895840718160000 2827552161259583903382348608217804027528429755116294531726781647822460658782397235509244326544348401242643522646029148050853927699339680385638445862369635206694230266891545322575128164256272302893355800130234506454234207245614460312098809495727174856449088063179427630000 -5048614873437401984010222442499035596978297765656920091431007232054016712492628107459984072902372797581067854927402768693698607138531139471168935220926653006735205346102005561467475215019894894441470066319491176741473251197966688557254685940196926700210545643242108464000 8973694066947983295278285555308979457056800941846837734768986843101792711511463254589278048655951648879643730579054054180996079162418065823031488904248241616017778288591715087579471841726113757460994482041870155190768929152455241221709918650928063354420478527728025160000 -15878524948432454591645150809682171143034224144939361294375094875113834941982819706967771532780271793694816284079363657830350410967506318199830934257084784876757682620159403641999411270374160942596687642575528170856288537462845873516224467007694037174680616184510107920000 27969930440773260530685280018204514111149366094390311705321647007025232239757093334400126291937662671077363167070833109913806902077820037518667708906876359567392124845280788599269077898676323729344165301433329795215243889266449771452429880102633462034710395750300851020000 -49047557105310130214267597051980408699207484383286162646581226270198974586622753927372141233999568924639960625350572674118194338314114220519841369200596939986372436691437944477801362962721805508190914511395982334302949169716525100655836924420663836003560923206831291760000 85623021118127113031192862282171513472045065594822415363031797860261638492647150427498223697067818894157188405969142582532047830599782253536065933090184943804781596624195954502676093629208637615727567904179843446454576979133705247144903888060073153709073497369639769329600 -148803540974522902988682752114315165863098262144848072283331614514984613904600460856905744886642078420045256204105917308673929278250333830931624556082657594646486535443759351130006886364151763377760160745155853283012227798494473506434163452184172717272179012522735781456000 257447035379217181591215329652323681848371709222194534149286798976209175761084320062089768852173368630135116557671885343700065143336515065447043621177097940737813352514913195562994868737978476980272550834658848435666041844554358992665924836307276093235105166552119576439500 -443421522692815995488552182517316709812492915600833645220301342145992008109742964866148950317624385629241220586585003651472066875775074107058930656305029880930851326711238591791220623775328368283302297188307591639900717964558216055356607083498084602512589068735662046672000 760330125069320082659749081322065657785828247937022662849499758990443923510208982129244104075700570838840172022760161628371594897162344584702742679031506038771262020660231144681556267320972654090295181901985051201750666114369596456501300846563099869280060917295330119576000 -1297915650118332310117768854313159967938625121830523193483934799854109908865314487803723738224998720924893364072655374498008976077972903713605245249276317350691224745127042461062036895764815291207658817556628002896509587789599930852506445952161235269813287086988648035107200 2205727439105592830396770103537813990457494940189512730499383578403754199054818160452957476477877039774046306921226128009256827323521367266098801617449921340360086996634440137479023376229531604439981979274606577956146911833449320690355055620948166680441119909067786688876000 -3731818972604420362912182472091987815788030655110548149080189583629881053863053694435816010623635103707350054286892384643112391326069764226116739991427878122065805450888520568732017140735678120677168390705496843376786371841466077582561494664013144747861166456798160112272000 6285717431509680108480575504668906851732353310144303167305458991421280099104528988113958252530871417697016990879877396479879251311787898961867022946455336613423689069513346097612866859954228789855677484903392727810620620727385599950515590174301470064134869758238241753352000 -10540395247266928761296118255740061071707177417010781355760129005113121503233778414608921637948703602934830720082691344515006432561828175975052779425532347190197941002359427160899570611956673346777487035966134880618366611916117357020084638676683802168827831739441285614256000 17596604287798400515386019643610490844711148965620776652255104255758294509565280075499894178908807959343981285471381939037552405471274260447240890096513724059191562617827821454724005382738779670592415857265686286810106482671073698802974632901908236398515352431678368483799600 -29246433719332521632220531263618544340240136784965279754440616491565032425870271593628632984335968907496921804107560009480696518788821485507879595728277657716107860306639038428904164071033982832009555441438813773091589721890981216847049251360512304263460419554036069502160000 48393960767624807894199166372672674198353154514348625892016379222230537080376499128683842976843219269587447957625492943864467444073215662484032811716127947436322122441096088450037553255661203636391501959728865884204039346443916433401609120345157100148654119648805540419320000 -79723384405067865346366670773714212591226408814271290036985660536897689184752469638988810193256873617667476249752189477771216340374057758031547166408387086961213854599932399154607319137425343731576083118231024238991778317282264537669868468227008115396405409228610780084720000 130755111235784383548848633109635672848797159511318571846374833353098682536530836193616262871907564697108470662368288786344549876932177147101191369081887612406166679110328687624452114079788269801513520938417366677687064987410747057661844712998691881570478102498573175029060000 -213506976154869842726339137899569482240775635804783202247779179940950177511705146223000801840155913861579858944579452374414662264798842684033726180747411005463220111643166843353899890387818654251238516381634932986031481458895356839360162873828000990180835476956574280321424000 347094674350129935579704336202852027140058752196300561031225716024222283113291153012801849986045816250382557573838180772614000129932544800546631359411774721996218487507334075944181515794404642840128189199652418378930960295198735845407915054447160079665565871008638515823080000 -561782660937267525161701296197531618858841686116083196873427998142746692559386770816360487443354808863017000541852532367664076504577470331129970102154207588190064799943750520737994060986039122199008567805431979610585804946452449842431339352429463453191678821196542992912560000 905263907434238158752415403927000679302426956159884064527018486137632577955750964929624372429101634934155112286191716559849992845691412789021935517873492119012794636865880594558778473273698911586989349751687945405101582427299735751526587597800738662344199839591168464122685000 -1452347515450051463364308723915404883867308287389299095392940227082597523441204800103896012135577690734471074453727631987618416706366711032793999530030101177386380555622225777720316683409294730784546599059618600758320153921304725108140216417067851729289339580048703877400080000 2319830761164811932022449880632444017204268102289393960478993714069770638793924423949736603167909230335330824330143325688331038576926287082111496546615648096852299752358744417926235567283495097009910919038471873103154624236462412267326670006721892897324323491375091869036344000 -3689218730693366684348370430116285633828889973991219505883035825609608293499771994960497562989397428296078669419904480205162568087295173526808040330197391852137080468710671715839565996488577108452418981759294892536014092451517043767446725886700584391971296118359310519491760000 5841262990264497250218253181017452253562409125486097550981473390548546464707972325354121141399879261468791226581515426991507399471550691417446063856145870432550377408791896883412646161106913755049663387785550246515355646381568652631790649320609258620621218854068908322528620000 -9208210826475936683990168553453785321969695886825269061600821323438459306295677553105156115665225216470909493914024319225218098898852028293453848652583838644342149909838164523985619149412507474448262927661939798796324718692660503344484991422300922436796988434832488186720720000 14452459238345922014711842087907411721915003972102761869410914750958223563624499261157023101324832091092042440982706618677013433298465616599618741067023297551414016034959899934704701713115352640377353846357108721640220882012277314072761203114680859546523615538092702047072360000 -22584376303121894134989705236036648717445846207072582547932789450830717355423884178768041433003604281013164987775642876119279658434402270206337552707401739640342969057297336964631880543694924392696344943907375229016451831624518682791034840067207956518034236547526195732225074560 35137925897144436353640897774152764626877180933876225506757132523233961842880245331327936804008267298916759355980720964174943085596078000188051777483590472578725098134358888628483112016121092472679153702621847098336766812500913376150945163402437911071941564841230916232318267600 -54431163723958490266647968965796325045348206008975373198796194677900885188970990115372719081010154118215881867089498788005747379278805178010138562467949167071552937163038702809109117818076175077041447645440739271694089704245446715310747945429771193809055368348219774747145539200 83950710188010052448295677002802268522322762177864133796026935177820677421084886871064273079970687436295923620405232257691404026771278885661139634705858106885490376629766041634155067957509021348981915283841140199464693908928823902185624476681366682515024549595270181686735051200 -128916394009028629353319482890846755356179017381311150050890966420822253981718744482742498502751820812464980335292467477510282700741119555289665613189470760441570974138585319870918864251372692414531595501835207377542089327167745411799560542027850683967663028666087719635039049600 197106381366435878037575314630478854899842129206688889946230661817099288324680501432824714816049494452742509407381377906403879602975238056903409792797585557411980884143468607486852263500125090244323307859384882858820931313380158116461959670837319072066347946460518329231467599520 -300056958510584801212056909411227653128368595642728493881401007490597341806600238401675418880075345886064712483677688151480971574083039561690230130767978013908002395808954835544289534987067066513668027712449427974058110660788692145795109210198543469287353829257481971008533353600 454798374286985863617227619238483798851637216955863345438039746955643614937229157158560386208281741539349394052485291726982938590036858393242521585640469293331762793647604318796187541250030972542968031532744028264344623226692808252396251918075802797689470856387649374905604219200 -686353682344328535693883978902985994089415956659240244551402020209822478939212670594380948376989155639018145593567881509650492180264501700506990800261595957038534973180979885807301302460882250991737655942365661453762903981797501749047085140072621454476538263686844226358849187200 1031317902897597825769195457882872183827065122375993804963955639742363464447723205554577622951882142718003828144501738622573786427116191357272223155601408508362590311264128630496908467499815257349564134059231736090680196868482183617708771160994537966752506713925284163044416617225 -1542958732646795708163783334390998384115297429840447874439580385692471053303606665972562885247491205728753779249955847913253249303945262913737144253575094287835979270878280756275894226701022307099607639527577870099303359470768150035844810879825594464544010044729775786788529796160 2298448889305459927964185018846694484109575186938491004670359382832048848833092831435812588127739490399050318830892778627255487952768202526940046491724557553123544250660651385644142954282610949695011380125277915303366403356714213136297321906475950303401051232434251495863742572000 -3409068895248925061114837728211893110798181285019880714937432262908516897235646731897045027352254437956214167981737609643526227609532166021869733039405416112384791730954041073280976888264130969315081478532065951896982727459312553850735562724333838434501817590225478962857333944000 5034527002519675412419592830580965856926180093598947550667908986202526242567076230353110311012478847806470923333854768880774557784180234872503497504070369671124963045970787461314432363338523312931808472162045851641678100088108488032142983095472395420024591441235050117827969974000 -7402954872599625542169684059363271131521272528376858609208339177655128562335135228179894853211151416311828709889369994343966701934578648707125965481563628411011513784820798015094743732209859472999985722562185673879279879821074691913588139667378432339984746283769790918759894152000 10838685210908682524561255379221609784868324650520990425276824796002765151521441577668512720983506304395010752171359658385653812319601047209663913564032902109455318900340194016972047874594435279699979096366687230218125157379060638673484173718136115041362282379570642601568973232800 -15800640844547184242966535974824341630114948979020369673677212618213749709379083629849238493505367246816256083728069067211822693151336564985955065809459729417876040340649387697376131172682424832299202263245554274231026444261034690649324754525160065405566498609604261593080088856000 22935113878947315903693772881824108131467872370057628429393709132050060164889537207612797711236107049587881917452222702151854878579363534380123552157098433772376191208748728570936272033817091146883280836190613219483301139756450864743535166644938972489202392114451083791996353467000 -33147950847944212298468353681618558317236008921610007501006683936398051332461214081231727989776358280320399310719751895222019264715212436457786711514585013696462281441652106433312474593404854380228253218718239971161615896645455702733658968586069558203223813539461108381307706792000 47702761753259818206171463293090666410844713346580899119469009624207347983516518741264948655338058743506767535985023666474327215973414851450672754895354575547954602988367371440832926635686681303526445621861020466113289881720744628045646282203810760155400767200188955462440278556000 -68353830765430524315678603098453967565919260137126047852201163157724959389038859765964458073218585440062861836373476949935365074027728622585014631065242252557322291877002360089902370824806738272901185372084398946380055881149218884743888090449004785437865403127359364029724551044800 97525036319364258177672754420773968875617126205748022819428427232612631451532716585277572755981062559685648832199531506852225421276936039799326430686519880542644179066935185481805150292969209909568610442494155062385685790023506742121961543191130565081802911027671819890894877122000 -138549421874361313884653484869814907924050526901868727632638873952628524278751768650117257013534809278747370129371626624344219490176805860067556944350622701828844627188290792472891951549709406521402257656339303413565558653836921417019612872442815210846692296774828479643487936264000 195988252550918139992612844175140183822212177501889682555717804108868992886776999371899536931206275437022033625216647712326119530074225374919684823289951208868441017856803306940296906337905517265199676031454843773460827945000469240658397103480665737956501917297056366932873638484000 -276053628906305751067289269239169882977652239990130329815321819321264095244031763526334686103603826555404468414465553920619747308024347520563566091952262103719458275778254281956007171333089976699353929648314842608233045877419207301378494165804847480530210720603873880241290688792000 387165214541093815871873200107935760876157266586157787565988851598072893579754548345684397260304366743954766951287939373669195599504147397590401443963047600466540231779001630443300057794658692320843886331761566758046846843080438240183338067541298591443620535646933117038410191030780 -540679601354145977277428907881406548854483963312340052461231313952420998515367947814422100912145749068864512450676424062979425276115517562719762615010739791175218278793618237028049956022466004238584978418420143103506818533977669362849549421005304766105804239307437769430198770516800 751840540191461694771350148024144927387205312168154451059274389301998353656941997085228742313157894849490702636637117042799748082956652531244645029330854585241161735934409439051442600538702727286987569492280746255871421792272430780678851060552152647395882014360342569929057494325600 -1041009978726639269683407897264200668689976586078983086082072231341228489678842765194932104741295546714679434419959085136184266576401518889415662348304260194949300865139951530994305139207434545474290480835465648661975814789300288773247639929995288281009682789114320481440233453681600 1435253856808757606964500492020197456584942966450479155811173843705604625621572822310834609754706979010090210326527748566471872482811005003476544376251170615313763816541962878128287035986487727299949994617213777981981507023862031798759741190612315773570280479051179475649034736882800 -1970373196013998097462375984106740212003032813201151631187685573087200424310109849888454427218807605752123844300122044945576200248007206868970268328878150276825809091351435457381055782737005373774746165449804593970325229395721702913852879264149253259518706040376434045582378552362560 2693490452679233852442410520145913343994293623957239298791048012471419299241652627310571938685808426582336782232925455529051209698630541409552953011151166018813606023891740588291837338470536902573852516809461944959434734765087549549724995053208954578898723774406209101719753932416800 -3666323613720627897427752894744068777820242426713293787543588695108516687419841659779009469365940708419200435766684772390895258410420933515705985179797901657058323678712590383080289644994293474265145686271356062672056125454197794718790288106824965200761407791206486099146790365009600 4969306270557615753131243506846740279741652112677577118900991540183847372899932445729882932743542185676024120046511468461188916423928373123003455403010391216552090672372702161380882778631971302128984226735440937886389797490616128626203503242828935676522202226806830423598468313358600 -6706740981290474072685688058140343849431276200973160316951949462546415036285483398637886011917934685802360181578665844964734185491463232185569455702840430199356366873226727611448037393165887918765768442929005862379675227909095606361037490929196998761467617675299194116934852100180800 9013205562661100522072717365939827953747885821307832523513473546007499231690978908901159006260443931407562097682548489208703746843405465693289683151866041560598434505238846131482606350327815227414483931838737146759026952629052875865686969517042795896508920339243551118124642700486880 -12061467297964976367737213020114124998932693921458170043631168978842152256520774695609823487696457815752212052859858075583423505508206827570095683049942391382795958583652957110256529179270798966126438351609015646514512953639851780355542173319643644143746730380982854294327380742744000 16072197928598961227882839679715181127218565443884794548430853809185295118519187640509206540644066361281467031602092435668202680883508612465977014549559157449405294326275421003715617765581719981561686055906188325088513620262812202464059837748748448143002317910581521863072165115938000 -21325821948843173735786431342576075684541825334743020369346508202018260835226428152540060978869124372838363034668151706407203557201362517267204367973749196809380390534622108256746146575154437166817927260621286203749407902915305295279188356141196488092894116743338193658507376473448000 28176871029027091868297531266640370530058885164503459280271835716193209364417527051786022597684567710006242946771688365711933202389239847693625094883190363900316602952749500522802275788911780507848807274299139017997406093948483083376125678283175070016456719465231864568124480509604000 -37071256823732029301422776076109981468463015180286478956694993496485523645715589807891971899604274625694960599849016500430639827721746883953540486280052864312223771595665607916747090556014053391049274148836939527292972836857522321743047277934008646334904503200039995311315581586129600 48566910983014317233835127311249855529596979022250314979323969845155313430084126070435395878087330939912869055090658636381487274298923201333364338996703872716735469999129221910161452771701103601254457719029163563400649509825359772475867227101044981376257101548129320780449499914520750 -63358272361534265168360453854484224000241622513439259829142061380730193059869939046323394143116326214178898719350883209092395868629770315408513670058050136110081764219487522108220216565480576400677278175424136639064636290995193564093217677561075467310992477798998442456989275667864000 82305124144289727240238580007140989550553112499515593510105596482623193376816691153477519185914270656218043073223754982146342001593218376236418475697419195951613392275554364843932003815923332501358282414486378456966740445000933266274203825157090858253274917332191756588864059061364000 -106466294239152821394294296811146578368495911634218261772022036500195157064999156575620084483927290443126919679444570883826533090366406586921572348038189031517361476404177722542747365317972425335885892765278322490873444680645598640383337644952609177024522685427322033582731074012552000 137138726627099229462650510892453092612753067128838284806342670825251380886106056446215394537630152689837294158522649638452748575924347532201358667353953014406887044606333685465776963421483528825510161871465648732291746600545878248684251585522289439929206601943288619448232169144739600 -175902404699842242066107543662528907389279468526300887875118865191533837716145535584219270903373592523781802483615750130081910287408901822776089502069203391400757729423800926725699668046558445524407333516844300036668748608776185877172199183330252488270241247148161174589181404603704000 224671554818044948989649208611618675551710032075062034513481204592978053386261714881265846011654896612128889902058979431550117641974876972692683037003082056789119469572105922997990808239561616439942068164879331089489231042962948312312358672547407798999194389129997329629309898297148000 -285752473976615088785889537193973634626052002970173462336295243666719131730044450605487057102293934698168659024368158236817880121471592934535847456046473159698690956571614625467893746649844325401155632795993097224929565723673915347574583843570934741989519104850918589457609279630888000 361908204069439393108544060078216608005164918856092333194789023228840032403381768809307900150782648426690023339824766446158494399127937277938089820511688883863672272827728900651554108374920761180237204743981823607988624513237954107659319632069792350114084337983356798440415526324969000 -456430111485222387543952038122174357390043285898507036688016274001548840866382654310091845837222351898131417670931940741508124701017822072881920338339447627649243148789794566468783534326958889394369745277115899891486829974342455062836224288916255763908586365080186456386029934376902080 573216219822990557126794226280195495783270323839674330112884287771898192167874929708683421415290981843897437685325324640156917171466044152562975072797193616883439165733662190283566175739255882220628670711870907140717028254162472907552535198521588811481440622811971253912032898806672800 -716855881464817230692524863778979847185635486956407710258267469953615069362166773921398002425680056919534500524505206927034645830358003694305921987994616841723083172135305877310127254905767309381301428946461509164269070463050961434737830904005921370798803963891317680536359643940897600 892720057992400897100737739238776305023232977915339508335646171694572037313165632009591437600204369948859553223274007691844547260702841049217421541124137328594400305486257085528733240338256953037929115954355103702232277001883557113820709980923261894008790917649701690948317033225463600 -1107056109212021625309073373601466187115058145107134308705276837625902852798610993541031806068318705857326998402754713501308389610009117571523702237477951186042473106104169625877123738601288342695054288316356445616754245606065390173782325663988753677418826965477019346350826717193348800 1367085567422287169858413863679950105483943895469507716098841862277568406595494040861134625633202867000559618957820355509755243913755445187160664856048353673926867951956544351955238849296009558072264714176709936331387219574001679493670732389716344657463714229461156448633230201929460960 -1681102901934599071983664379931261150595105022271088374785118763357566718087266453959167869108114894455444543033978627424989047040116904754513114556161548601348584720503407207740780951570498992525058697247462334699849713165245684760198348414268358859526145108154090296463136907245044800 2058572766489358585831848280054715621909283696253254051530851448648501837657786930889814358236557359182708711261515495156988902509772783831336661111595970393781021567468292622441835933751837886679990858434971238556065968204664276014224366460990652399743821208827578163956017185029233100 -2510222680615199384109043630182193645191920996816901014337851189114108476404876442285963004962822830596928867311963467535543049711685981207726921632615871519437365791277733267088428113212402780986224418599687792049891065154879301929585370649891603850034036023697370139881702248719249600 3048127540747027823560981550935520854875904067563379803124533586781417435634492822775812220311999151439127910307384210578873703221332977180811261982462129702173944175122961824321662708900774805483272508299620890346296293402353438057353664360582661817898472314489663741284924159159088800 -3685781807891808356765692634004790734861438021927213279180470498039139244008605114436959144561175985418347772003871482217212799757289990797946491500632368329525275025550983723202746172142086316515405377851955375453222644435949214754409258514175816359114014798670260064174414040730300480 4438154699869723365371533561588337467436364590623364613692080301537954364918618543760099887372975670515212340142276440743203485946278085249820889995027507736240296762418042327251013165996778248097678493973111403928765798919434260885469864036564916487465270113077721407549466448127082000 -5321723255679027559392868618472056825942002392417947500170823977130178689284567773295863480511302634668126467355956189815649031203317429452874476790376233532700035477132847092630505489662040736849390230759520310431746633029252981015986747723478298030736387961676718575642838486999064000 6354477768767423318635776912011154611798327057613211284450550091413432544511024989574741096592263191624269731568870062268457633149166702291902628678919566524205750124521641619739165230806500697196874636272212608118272806105706185094431664519130479155422673296705305513838366503882444000 -7555893838944407681840263207448343296944707799713203395178102842181803617846822424961309458818135275689906150065945723244043017093086602725223626811836022154066973952164685479507617882644631808512001275931879228787559008626830589110007582867849909155195069386970773298914868599149512000 8946865204750082732360857116092242858427710826478588565654071774492544738404987462283732336464201087805547964055358458659423663421586636408730703565833108050611121429722275306416974811040575391442619692637520632268905098851315311196168069713976824249674161705935847474396923954902035800 -10549591624648623629994661452081556204948774670677700803038814790784860009003613334212110691522413981085906896391805892296826088388265421615736884023204571851060732751599961812555163042496823590816694422157620700181021885266857056285731057259110994580114657793847257792939683574941176000 12387416409938089737482419216358207399023561208329698454246934109541498517359446426371234047285368452904039998251916873534055972564501705471872042552133875092082625108779140680353234432253057564782498654071957337995362801930992787810620856826874674631401600441191689580397501754286132000 -14484608804397134275430910054342102556871793918543530020993029049080126934519623586592097599308850696623685596150096931130115110131855267346342478650124937466588712881145812353099267349677390109610235446522062982125503231151815494550567954483794766273286747242747844701232293247675432000 16866087278993960406301307428141592391672787062808569866786927969311769426005958095198455988384404977825327597318919174311417819680561200941574462752510343851861181440433299519261984729241465510514621004170960724682173807444794168204152325378652914782182991721848278627335800921279726000 -19557080979687378808205560972856318368771141852604993373622595128460388817570953656454838853946860603500829303857443357179082235854313662215398702877068173994517684546659736071773447461322688097585493119443181424575284684587671439985039550326707649500239154446008341060011850057034468800 22582728037082959834587138791526914708334390255810698626492458500352242692935069805099197331351195539916876886741218226339074779069442905921368457358049573110261451886838036047002971844352431323445132189491565994745003615611324644825774368650794707382563149192139676336112338070342492000 -25967611210426490727019662950435870604214489018985904013461126776691393163688201073425027803835602925094574317192362792703097173247636809046047845821112931943343146017527406103265162255027180537473820906932136289259355387973648473021136522341182280972343308019596853773516200823615304000 29735233372653548533395283691012503615986680506115555265414192045630992618241176675596069784302822099494456751606433287180109039901869828215675323451408335015479986399534730649497830885778891999384085101018272134799217218818039434508578205270148460131277046906368718718334399603827345875 -33907437609796474051444065144317153343842272648399029612231773557601488241736041108920239932211681325035995226776155552419188927460484080281571861040358725006516153756262320918803762613627600676357798600715713436563918075801416905274815236299144791953705674868732258315784437855589312000 38503779152457773867306482863880145241563114051848675848556525084298578870060260014796094678578153682429763468628034416191567870960683033386407157759162907729621676821000102198908272656808230990264077966590510146853693637187831196878734634997473308196319110795382631109701883876013640960 -43540858908544267566133716764032980206645650036458591314332212401313248833105837267286049414800129441328557359202433597023724199977712521124318515426104396767421408378514527985461683048718842139766473975523636751431006108571605122856218766848584007051269947906086789059751576001700569600 49031630939046531396376242993125634790227070505658015440254637416523105433740865418249113168436428950522645344765572347090875260594370958522739213167891898129684727576690032620796452813712147453852069145003387403713234755006519928172157859128162078736938945761500388565074230497490243200 -54984698713102953530594109140193868594780026085815169632780034895350414040486445104791499976966238205001112218854107621020230976560574938034330066863772812913642034456862111636566441565928854098359494758635145256261199239609960537552883427013479770415816742708260921393063375480629235200 61403617285337439295178883995767161624567121642088746704448188748772378675168783409976410767228816673866880825900952783826557500255972452826884017400733075214133285175394472686650189149616583761824369697418543270758652014278083684007294928404921241411495789764511645696658879666693881600 -68286220541496141282111022641446557762705414397575617214177546168964447493704185506479261204874244476871739995397543095859863945339608925561325962208287771556816356700548578416362627933419761282380507839326995373634896525768594162874046667632725600338938174990863500489031633211751877120 75623994240034103832162426390198490504750513751701067309560659682734749965615380878886023922064678642149624337008243998704454588588821288176468444989441501395158465205651386184787559443809165455267886971184501455450927073493728184761827998145891289849043373619267692427545997306874337600 -83401516623582468996520487747614965458193126763363977951900596236538980268424840181528569051905028524383830778669923359621542916080450611030503492942403756462056600576910937936833544769540086191367647775660806856777390032912120361312825625963958884209885908761730671736287051734495987200 91595988780921357871724465801419929313255770222646464868572052198644338591741691291067402255694823903417176597534872161331083158926783094647037678930194518559856921594293016991762604845149919987462722338771584823054644512128376728690723340305395892483782995867140890575005211839413715200 -100176876618785450221363141246868855153059687694484804714647429637733023906436446684348226432154251850796127782053389596924191167279401118764298289374635399383547221438638550173997445821928670661669469747414674468787432560105544918960224655410258688511675520534432956576585220791689945600 109105685186981544697615073401481079199310659858558450352257309235878793428531869106214046614150609080975782649584235191432651684362999914132420528210200728459037299871212855732984174688665791307600879007510330236657616766549734792171896852957694789009455295190762850532324338297036223360 -118335884150739202491990318222864511062159067091711985197676040385985676169774261503485950774566821129040979012564246411532160178267895785393080833199783870346027440207389214460937282742587626147072536884501442772947523607971512789774291597567998686561231339686293764134842015506546880000 127813000413893640786803395656297383160210767270052555440779965698283230321899040022163397048720441003011793349068309435832354824579393932708111116378121539616163836933955017350666026165695293176167090704255887324027736537614252991552752180057210702584533416674157117539580445319841760000 -137474890293993592034185941764224831131285015335823266975180179088002265011459442615631472419574038055075319844138268032493547953867253085288637874635646925980236697177342545660111622096147421170045812463756872326924001718643408185298640573798036565630880435213240268973458016780304960000 147252199301971584571100028139697717828122096167896904497121872859347253686843411594760434897690295071923349057191205198597614941965570653854424620029992504767624220899006993950593698667640664486018898263980960229485407013288305750201345614606948648962387017890043994999587574008214580000 -157069012588769690209173363349010899016663569245756698130263331049970403932632972367744463890869648076718238994337285545170789271429942030778052928031992005085465835625607460213966611912150042118420158148246357578117767480840859466881435322247411892226546152416046927999560078942095552000 166843693629701709556954538321374238225855078919848853164120920321320493447753908416380921944164111154453923395272438508282276157420217393208446779776472194243145039988574448081359383898099293666562185157471989272893336701751556729841867992516027653759957822845371736823567036644500640000 -176489902897371829809712081222181742363110083482666666944487654472660222190985933099983245054426276039186805475941294696127289982367424822794374109656482363931720877418320722381566457485355569745785266526319406211583101350460961508654995264031943599480554956071977811543559135122876480000 185917782325650239521769350518238459369686476831099715392376952254319422094350566278401153444085799331878408332562090352971696498519530849653047940300525225252859813177846401995966375086069008300581488028793733466475361037985585520869471506768692723384430755007446711732851823964910480000 -195035285510063790713668487110817317718306495950748528727184350765725278614969037545785431757974868382269033901109911415057728522967183748463325344622299383420910507640725863074659822051910345594639855245557605256942169788249270951530447721386347163976844203547257531284782723647624640000 203749628054130470724279206747683623403592530876207505542654289842491727233935739223363078708863107182327863075414822350624137669738057915947856902573508504807802253726800848446080792824442509972272699841635711023741713544745514972769042194044035015984320221152560527363464504916986592000 -211968827487311954681309578145148567872102632971001438887262424676902221538489410232373478911556098767177607021132193103621714348559763012344904208622121374428499159928094300931166854530736369185591556098516981744444670142091937020502825212487424963550566684426230697257107446728924480000 219603297968846495421949965493596715443767346446651914440405350989417767653223138990742862685912992154978495409605174634896225246707042612365801182237748627321051036450928205837585999715106111296089557059692381510664075634497790684376867645988031371136074382805989006268486316632296760000 -226567461752213720435331042623414793100546437771598592488198332521851734914953259677552890043817209665178659111812526896045154165735807177239980923746345306834403606317236711308122553617276495375246731173636114539543486066881441551746112920173698327937429807207870264395393916525498560000 232781337285502282388198771640512667172924293659849186796946388055151466041312737263646112766537934824772166640195570882645548689268645770708587995494662794152646743199355017736404395805092095459377970636204193630290459313441481087975436692245972754653013325127073457300752821409109280000 -238172062991061282611925480036398223675876224670919378491191462304849710518058926968698970114815655420714258920284310418875235079967498620135523717495591827280392246726076923410300076550052122933174092061463659166991922581752757492118025752487458439497609423182647789996138676220688652800 242675316282909079972234995415237685888235228918898946571907267264395188237938192394577732154801665712282385664575400321753128180218984938583464291986054697964265209374259050113436002367174957190313938339936711546199753050735477696800929600748775931000715483705008777622116088166037808000 -246236589268192861020045571867872201194771175674522201553046367622572895402855524358439459880343828521477305370344850640940281004666642998478819113881028246990994468212036436593088103030844191362918126114317334147506667665735788690255031293002950839841396843004662994484495150256524736000 248812285808655129440757345632180487818147443202498375209458986530758804350584138629971253393736546393040875510202014350573547542372361021475459481181039002712657590264463595971676890719451348176337771784969189107208620256381560538479456306528086308877394717931490013255253467727827296000 -250370609101819984113663967838645083775254838462639283613693593962057920035452097744563975231275606182558876818199104210806784792115820485075514551000544466195200330913301572564401380640449999626293958247087994049424958170304618328908346429533481421459090300716029616678564032243867968000 250892214537448775747234101104975594366453286042769782121222122282812207368859289614865150179674097028772541144903685677912632260432728444419421872981795600499773664936037617507243883516784270458848737326769427370361260166492752950426905484595009507753796738842521345046644373977709359600 -250370609101819984113663967838645083775254838462639283613693593962057920035452097744563975231275606182558876818199104210806784792115820485075514551000544466195200330913301572564401380640449999626293958247087994049424958170304618328908346429533481421459090300716029616678564032243867968000 248812285808655129440757345632180487818147443202498375209458986530758804350584138629971253393736546393040875510202014350573547542372361021475459481181039002712657590264463595971676890719451348176337771784969189107208620256381560538479456306528086308877394717931490013255253467727827296000 -246236589268192861020045571867872201194771175674522201553046367622572895402855524358439459880343828521477305370344850640940281004666642998478819113881028246990994468212036436593088103030844191362918126114317334147506667665735788690255031293002950839841396843004662994484495150256524736000 242675316282909079972234995415237685888235228918898946571907267264395188237938192394577732154801665712282385664575400321753128180218984938583464291986054697964265209374259050113436002367174957190313938339936711546199753050735477696800929600748775931000715483705008777622116088166037808000 -238172062991061282611925480036398223675876224670919378491191462304849710518058926968698970114815655420714258920284310418875235079967498620135523717495591827280392246726076923410300076550052122933174092061463659166991922581752757492118025752487458439497609423182647789996138676220688652800 232781337285502282388198771640512667172924293659849186796946388055151466041312737263646112766537934824772166640195570882645548689268645770708587995494662794152646743199355017736404395805092095459377970636204193630290459313441481087975436692245972754653013325127073457300752821409109280000 -226567461752213720435331042623414793100546437771598592488198332521851734914953259677552890043817209665178659111812526896045154165735807177239980923746345306834403606317236711308122553617276495375246731173636114539543486066881441551746112920173698327937429807207870264395393916525498560000 219603297968846495421949965493596715443767346446651914440405350989417767653223138990742862685912992154978495409605174634896225246707042612365801182237748627321051036450928205837585999715106111296089557059692381510664075634497790684376867645988031371136074382805989006268486316632296760000 -211968827487311954681309578145148567872102632971001438887262424676902221538489410232373478911556098767177607021132193103621714348559763012344904208622121374428499159928094300931166854530736369185591556098516981744444670142091937020502825212487424963550566684426230697257107446728924480000 203749628054130470724279206747683623403592530876207505542654289842491727233935739223363078708863107182327863075414822350624137669738057915947856902573508504807802253726800848446080792824442509972272699841635711023741713544745514972769042194044035015984320221152560527363464504916986592000 -195035285510063790713668487110817317718306495950748528727184350765725278614969037545785431757974868382269033901109911415057728522967183748463325344622299383420910507640725863074659822051910345594639855245557605256942169788249270951530447721386347163976844203547257531284782723647624640000 185917782325650239521769350518238459369686476831099715392376952254319422094350566278401153444085799331878408332562090352971696498519530849653047940300525225252859813177846401995966375086069008300581488028793733466475361037985585520869471506768692723384430755007446711732851823964910480000 -176489902897371829809712081222181742363110083482666666944487654472660222190985933099983245054426276039186805475941294696127289982367424822794374109656482363931720877418320722381566457485355569745785266526319406211583101350460961508654995264031943599480554956071977811543559135122876480000 166843693629701709556954538321374238225855078919848853164120920321320493447753908416380921944164111154453923395272438508282276157420217393208446779776472194243145039988574448081359383898099293666562185157471989272893336701751556729841867992516027653759957822845371736823567036644500640000 -157069012588769690209173363349010899016663569245756698130263331049970403932632972367744463890869648076718238994337285545170789271429942030778052928031992005085465835625607460213966611912150042118420158148246357578117767480840859466881435322247411892226546152416046927999560078942095552000 147252199301971584571100028139697717828122096167896904497121872859347253686843411594760434897690295071923349057191205198597614941965570653854424620029992504767624220899006993950593698667640664486018898263980960229485407013288305750201345614606948648962387017890043994999587574008214580000 -137474890293993592034185941764224831131285015335823266975180179088002265011459442615631472419574038055075319844138268032493547953867253085288637874635646925980236697177342545660111622096147421170045812463756872326924001718643408185298640573798036565630880435213240268973458016780304960000 127813000413893640786803395656297383160210767270052555440779965698283230321899040022163397048720441003011793349068309435832354824579393932708111116378121539616163836933955017350666026165695293176167090704255887324027736537614252991552752180057210702584533416674157117539580445319841760000 -118335884150739202491990318222864511062159067091711985197676040385985676169774261503485950774566821129040979012564246411532160178267895785393080833199783870346027440207389214460937282742587626147072536884501442772947523607971512789774291597567998686561231339686293764134842015506546880000 109105685186981544697615073401481079199310659858558450352257309235878793428531869106214046614150609080975782649584235191432651684362999914132420528210200728459037299871212855732984174688665791307600879007510330236657616766549734792171896852957694789009455295190762850532324338297036223360 -100176876618785450221363141246868855153059687694484804714647429637733023906436446684348226432154251850796127782053389596924191167279401118764298289374635399383547221438638550173997445821928670661669469747414674468787432560105544918960224655410258688511675520534432956576585220791689945600 91595988780921357871724465801419929313255770222646464868572052198644338591741691291067402255694823903417176597534872161331083158926783094647037678930194518559856921594293016991762604845149919987462722338771584823054644512128376728690723340305395892483782995867140890575005211839413715200 -83401516623582468996520487747614965458193126763363977951900596236538980268424840181528569051905028524383830778669923359621542916080450611030503492942403756462056600576910937936833544769540086191367647775660806856777390032912120361312825625963958884209885908761730671736287051734495987200 75623994240034103832162426390198490504750513751701067309560659682734749965615380878886023922064678642149624337008243998704454588588821288176468444989441501395158465205651386184787559443809165455267886971184501455450927073493728184761827998145891289849043373619267692427545997306874337600 -68286220541496141282111022641446557762705414397575617214177546168964447493704185506479261204874244476871739995397543095859863945339608925561325962208287771556816356700548578416362627933419761282380507839326995373634896525768594162874046667632725600338938174990863500489031633211751877120 61403617285337439295178883995767161624567121642088746704448188748772378675168783409976410767228816673866880825900952783826557500255972452826884017400733075214133285175394472686650189149616583761824369697418543270758652014278083684007294928404921241411495789764511645696658879666693881600 -54984698713102953530594109140193868594780026085815169632780034895350414040486445104791499976966238205001112218854107621020230976560574938034330066863772812913642034456862111636566441565928854098359494758635145256261199239609960537552883427013479770415816742708260921393063375480629235200 49031630939046531396376242993125634790227070505658015440254637416523105433740865418249113168436428950522645344765572347090875260594370958522739213167891898129684727576690032620796452813712147453852069145003387403713234755006519928172157859128162078736938945761500388565074230497490243200 -43540858908544267566133716764032980206645650036458591314332212401313248833105837267286049414800129441328557359202433597023724199977712521124318515426104396767421408378514527985461683048718842139766473975523636751431006108571605122856218766848584007051269947906086789059751576001700569600 38503779152457773867306482863880145241563114051848675848556525084298578870060260014796094678578153682429763468628034416191567870960683033386407157759162907729621676821000102198908272656808230990264077966590510146853693637187831196878734634997473308196319110795382631109701883876013640960 -33907437609796474051444065144317153343842272648399029612231773557601488241736041108920239932211681325035995226776155552419188927460484080281571861040358725006516153756262320918803762613627600676357798600715713436563918075801416905274815236299144791953705674868732258315784437855589312000 29735233372653548533395283691012503615986680506115555265414192045630992618241176675596069784302822099494456751606433287180109039901869828215675323451408335015479986399534730649497830885778891999384085101018272134799217218818039434508578205270148460131277046906368718718334399603827345875 -25967611210426490727019662950435870604214489018985904013461126776691393163688201073425027803835602925094574317192362792703097173247636809046047845821112931943343146017527406103265162255027180537473820906932136289259355387973648473021136522341182280972343308019596853773516200823615304000 22582728037082959834587138791526914708334390255810698626492458500352242692935069805099197331351195539916876886741218226339074779069442905921368457358049573110261451886838036047002971844352431323445132189491565994745003615611324644825774368650794707382563149192139676336112338070342492000 -19557080979687378808205560972856318368771141852604993373622595128460388817570953656454838853946860603500829303857443357179082235854313662215398702877068173994517684546659736071773447461322688097585493119443181424575284684587671439985039550326707649500239154446008341060011850057034468800 16866087278993960406301307428141592391672787062808569866786927969311769426005958095198455988384404977825327597318919174311417819680561200941574462752510343851861181440433299519261984729241465510514621004170960724682173807444794168204152325378652914782182991721848278627335800921279726000 -14484608804397134275430910054342102556871793918543530020993029049080126934519623586592097599308850696623685596150096931130115110131855267346342478650124937466588712881145812353099267349677390109610235446522062982125503231151815494550567954483794766273286747242747844701232293247675432000 12387416409938089737482419216358207399023561208329698454246934109541498517359446426371234047285368452904039998251916873534055972564501705471872042552133875092082625108779140680353234432253057564782498654071957337995362801930992787810620856826874674631401600441191689580397501754286132000 -10549591624648623629994661452081556204948774670677700803038814790784860009003613334212110691522413981085906896391805892296826088388265421615736884023204571851060732751599961812555163042496823590816694422157620700181021885266857056285731057259110994580114657793847257792939683574941176000 8946865204750082732360857116092242858427710826478588565654071774492544738404987462283732336464201087805547964055358458659423663421586636408730703565833108050611121429722275306416974811040575391442619692637520632268905098851315311196168069713976824249674161705935847474396923954902035800 -7555893838944407681840263207448343296944707799713203395178102842181803617846822424961309458818135275689906150065945723244043017093086602725223626811836022154066973952164685479507617882644631808512001275931879228787559008626830589110007582867849909155195069386970773298914868599149512000 6354477768767423318635776912011154611798327057613211284450550091413432544511024989574741096592263191624269731568870062268457633149166702291902628678919566524205750124521641619739165230806500697196874636272212608118272806105706185094431664519130479155422673296705305513838366503882444000 -5321723255679027559392868618472056825942002392417947500170823977130178689284567773295863480511302634668126467355956189815649031203317429452874476790376233532700035477132847092630505489662040736849390230759520310431746633029252981015986747723478298030736387961676718575642838486999064000 4438154699869723365371533561588337467436364590623364613692080301537954364918618543760099887372975670515212340142276440743203485946278085249820889995027507736240296762418042327251013165996778248097678493973111403928765798919434260885469864036564916487465270113077721407549466448127082000 -3685781807891808356765692634004790734861438021927213279180470498039139244008605114436959144561175985418347772003871482217212799757289990797946491500632368329525275025550983723202746172142086316515405377851955375453222644435949214754409258514175816359114014798670260064174414040730300480 3048127540747027823560981550935520854875904067563379803124533586781417435634492822775812220311999151439127910307384210578873703221332977180811261982462129702173944175122961824321662708900774805483272508299620890346296293402353438057353664360582661817898472314489663741284924159159088800 -2510222680615199384109043630182193645191920996816901014337851189114108476404876442285963004962822830596928867311963467535543049711685981207726921632615871519437365791277733267088428113212402780986224418599687792049891065154879301929585370649891603850034036023697370139881702248719249600 2058572766489358585831848280054715621909283696253254051530851448648501837657786930889814358236557359182708711261515495156988902509772783831336661111595970393781021567468292622441835933751837886679990858434971238556065968204664276014224366460990652399743821208827578163956017185029233100 -1681102901934599071983664379931261150595105022271088374785118763357566718087266453959167869108114894455444543033978627424989047040116904754513114556161548601348584720503407207740780951570498992525058697247462334699849713165245684760198348414268358859526145108154090296463136907245044800 1367085567422287169858413863679950105483943895469507716098841862277568406595494040861134625633202867000559618957820355509755243913755445187160664856048353673926867951956544351955238849296009558072264714176709936331387219574001679493670732389716344657463714229461156448633230201929460960 -1107056109212021625309073373601466187115058145107134308705276837625902852798610993541031806068318705857326998402754713501308389610009117571523702237477951186042473106104169625877123738601288342695054288316356445616754245606065390173782325663988753677418826965477019346350826717193348800 892720057992400897100737739238776305023232977915339508335646171694572037313165632009591437600204369948859553223274007691844547260702841049217421541124137328594400305486257085528733240338256953037929115954355103702232277001883557113820709980923261894008790917649701690948317033225463600 -716855881464817230692524863778979847185635486956407710258267469953615069362166773921398002425680056919534500524505206927034645830358003694305921987994616841723083172135305877310127254905767309381301428946461509164269070463050961434737830904005921370798803963891317680536359643940897600 573216219822990557126794226280195495783270323839674330112884287771898192167874929708683421415290981843897437685325324640156917171466044152562975072797193616883439165733662190283566175739255882220628670711870907140717028254162472907552535198521588811481440622811971253912032898806672800 -456430111485222387543952038122174357390043285898507036688016274001548840866382654310091845837222351898131417670931940741508124701017822072881920338339447627649243148789794566468783534326958889394369745277115899891486829974342455062836224288916255763908586365080186456386029934376902080 361908204069439393108544060078216608005164918856092333194789023228840032403381768809307900150782648426690023339824766446158494399127937277938089820511688883863672272827728900651554108374920761180237204743981823607988624513237954107659319632069792350114084337983356798440415526324969000 -285752473976615088785889537193973634626052002970173462336295243666719131730044450605487057102293934698168659024368158236817880121471592934535847456046473159698690956571614625467893746649844325401155632795993097224929565723673915347574583843570934741989519104850918589457609279630888000 224671554818044948989649208611618675551710032075062034513481204592978053386261714881265846011654896612128889902058979431550117641974876972692683037003082056789119469572105922997990808239561616439942068164879331089489231042962948312312358672547407798999194389129997329629309898297148000 -175902404699842242066107543662528907389279468526300887875118865191533837716145535584219270903373592523781802483615750130081910287408901822776089502069203391400757729423800926725699668046558445524407333516844300036668748608776185877172199183330252488270241247148161174589181404603704000 137138726627099229462650510892453092612753067128838284806342670825251380886106056446215394537630152689837294158522649638452748575924347532201358667353953014406887044606333685465776963421483528825510161871465648732291746600545878248684251585522289439929206601943288619448232169144739600 -106466294239152821394294296811146578368495911634218261772022036500195157064999156575620084483927290443126919679444570883826533090366406586921572348038189031517361476404177722542747365317972425335885892765278322490873444680645598640383337644952609177024522685427322033582731074012552000 82305124144289727240238580007140989550553112499515593510105596482623193376816691153477519185914270656218043073223754982146342001593218376236418475697419195951613392275554364843932003815923332501358282414486378456966740445000933266274203825157090858253274917332191756588864059061364000 -63358272361534265168360453854484224000241622513439259829142061380730193059869939046323394143116326214178898719350883209092395868629770315408513670058050136110081764219487522108220216565480576400677278175424136639064636290995193564093217677561075467310992477798998442456989275667864000 48566910983014317233835127311249855529596979022250314979323969845155313430084126070435395878087330939912869055090658636381487274298923201333364338996703872716735469999129221910161452771701103601254457719029163563400649509825359772475867227101044981376257101548129320780449499914520750 -37071256823732029301422776076109981468463015180286478956694993496485523645715589807891971899604274625694960599849016500430639827721746883953540486280052864312223771595665607916747090556014053391049274148836939527292972836857522321743047277934008646334904503200039995311315581586129600 28176871029027091868297531266640370530058885164503459280271835716193209364417527051786022597684567710006242946771688365711933202389239847693625094883190363900316602952749500522802275788911780507848807274299139017997406093948483083376125678283175070016456719465231864568124480509604000 -21325821948843173735786431342576075684541825334743020369346508202018260835226428152540060978869124372838363034668151706407203557201362517267204367973749196809380390534622108256746146575154437166817927260621286203749407902915305295279188356141196488092894116743338193658507376473448000 16072197928598961227882839679715181127218565443884794548430853809185295118519187640509206540644066361281467031602092435668202680883508612465977014549559157449405294326275421003715617765581719981561686055906188325088513620262812202464059837748748448143002317910581521863072165115938000 -12061467297964976367737213020114124998932693921458170043631168978842152256520774695609823487696457815752212052859858075583423505508206827570095683049942391382795958583652957110256529179270798966126438351609015646514512953639851780355542173319643644143746730380982854294327380742744000 9013205562661100522072717365939827953747885821307832523513473546007499231690978908901159006260443931407562097682548489208703746843405465693289683151866041560598434505238846131482606350327815227414483931838737146759026952629052875865686969517042795896508920339243551118124642700486880 -6706740981290474072685688058140343849431276200973160316951949462546415036285483398637886011917934685802360181578665844964734185491463232185569455702840430199356366873226727611448037393165887918765768442929005862379675227909095606361037490929196998761467617675299194116934852100180800 4969306270557615753131243506846740279741652112677577118900991540183847372899932445729882932743542185676024120046511468461188916423928373123003455403010391216552090672372702161380882778631971302128984226735440937886389797490616128626203503242828935676522202226806830423598468313358600 -3666323613720627897427752894744068777820242426713293787543588695108516687419841659779009469365940708419200435766684772390895258410420933515705985179797901657058323678712590383080289644994293474265145686271356062672056125454197794718790288106824965200761407791206486099146790365009600 2693490452679233852442410520145913343994293623957239298791048012471419299241652627310571938685808426582336782232925455529051209698630541409552953011151166018813606023891740588291837338470536902573852516809461944959434734765087549549724995053208954578898723774406209101719753932416800 -1970373196013998097462375984106740212003032813201151631187685573087200424310109849888454427218807605752123844300122044945576200248007206868970268328878150276825809091351435457381055782737005373774746165449804593970325229395721702913852879264149253259518706040376434045582378552362560 1435253856808757606964500492020197456584942966450479155811173843705604625621572822310834609754706979010090210326527748566471872482811005003476544376251170615313763816541962878128287035986487727299949994617213777981981507023862031798759741190612315773570280479051179475649034736882800 -1041009978726639269683407897264200668689976586078983086082072231341228489678842765194932104741295546714679434419959085136184266576401518889415662348304260194949300865139951530994305139207434545474290480835465648661975814789300288773247639929995288281009682789114320481440233453681600 751840540191461694771350148024144927387205312168154451059274389301998353656941997085228742313157894849490702636637117042799748082956652531244645029330854585241161735934409439051442600538702727286987569492280746255871421792272430780678851060552152647395882014360342569929057494325600 -540679601354145977277428907881406548854483963312340052461231313952420998515367947814422100912145749068864512450676424062979425276115517562719762615010739791175218278793618237028049956022466004238584978418420143103506818533977669362849549421005304766105804239307437769430198770516800 387165214541093815871873200107935760876157266586157787565988851598072893579754548345684397260304366743954766951287939373669195599504147397590401443963047600466540231779001630443300057794658692320843886331761566758046846843080438240183338067541298591443620535646933117038410191030780 -276053628906305751067289269239169882977652239990130329815321819321264095244031763526334686103603826555404468414465553920619747308024347520563566091952262103719458275778254281956007171333089976699353929648314842608233045877419207301378494165804847480530210720603873880241290688792000 195988252550918139992612844175140183822212177501889682555717804108868992886776999371899536931206275437022033625216647712326119530074225374919684823289951208868441017856803306940296906337905517265199676031454843773460827945000469240658397103480665737956501917297056366932873638484000 -138549421874361313884653484869814907924050526901868727632638873952628524278751768650117257013534809278747370129371626624344219490176805860067556944350622701828844627188290792472891951549709406521402257656339303413565558653836921417019612872442815210846692296774828479643487936264000 97525036319364258177672754420773968875617126205748022819428427232612631451532716585277572755981062559685648832199531506852225421276936039799326430686519880542644179066935185481805150292969209909568610442494155062385685790023506742121961543191130565081802911027671819890894877122000 -68353830765430524315678603098453967565919260137126047852201163157724959389038859765964458073218585440062861836373476949935365074027728622585014631065242252557322291877002360089902370824806738272901185372084398946380055881149218884743888090449004785437865403127359364029724551044800 47702761753259818206171463293090666410844713346580899119469009624207347983516518741264948655338058743506767535985023666474327215973414851450672754895354575547954602988367371440832926635686681303526445621861020466113289881720744628045646282203810760155400767200188955462440278556000 -33147950847944212298468353681618558317236008921610007501006683936398051332461214081231727989776358280320399310719751895222019264715212436457786711514585013696462281441652106433312474593404854380228253218718239971161615896645455702733658968586069558203223813539461108381307706792000 22935113878947315903693772881824108131467872370057628429393709132050060164889537207612797711236107049587881917452222702151854878579363534380123552157098433772376191208748728570936272033817091146883280836190613219483301139756450864743535166644938972489202392114451083791996353467000 -15800640844547184242966535974824341630114948979020369673677212618213749709379083629849238493505367246816256083728069067211822693151336564985955065809459729417876040340649387697376131172682424832299202263245554274231026444261034690649324754525160065405566498609604261593080088856000 10838685210908682524561255379221609784868324650520990425276824796002765151521441577668512720983506304395010752171359658385653812319601047209663913564032902109455318900340194016972047874594435279699979096366687230218125157379060638673484173718136115041362282379570642601568973232800 -7402954872599625542169684059363271131521272528376858609208339177655128562335135228179894853211151416311828709889369994343966701934578648707125965481563628411011513784820798015094743732209859472999985722562185673879279879821074691913588139667378432339984746283769790918759894152000 5034527002519675412419592830580965856926180093598947550667908986202526242567076230353110311012478847806470923333854768880774557784180234872503497504070369671124963045970787461314432363338523312931808472162045851641678100088108488032142983095472395420024591441235050117827969974000 -3409068895248925061114837728211893110798181285019880714937432262908516897235646731897045027352254437956214167981737609643526227609532166021869733039405416112384791730954041073280976888264130969315081478532065951896982727459312553850735562724333838434501817590225478962857333944000 2298448889305459927964185018846694484109575186938491004670359382832048848833092831435812588127739490399050318830892778627255487952768202526940046491724557553123544250660651385644142954282610949695011380125277915303366403356714213136297321906475950303401051232434251495863742572000 -1542958732646795708163783334390998384115297429840447874439580385692471053303606665972562885247491205728753779249955847913253249303945262913737144253575094287835979270878280756275894226701022307099607639527577870099303359470768150035844810879825594464544010044729775786788529796160 1031317902897597825769195457882872183827065122375993804963955639742363464447723205554577622951882142718003828144501738622573786427116191357272223155601408508362590311264128630496908467499815257349564134059231736090680196868482183617708771160994537966752506713925284163044416617225 -686353682344328535693883978902985994089415956659240244551402020209822478939212670594380948376989155639018145593567881509650492180264501700506990800261595957038534973180979885807301302460882250991737655942365661453762903981797501749047085140072621454476538263686844226358849187200 454798374286985863617227619238483798851637216955863345438039746955643614937229157158560386208281741539349394052485291726982938590036858393242521585640469293331762793647604318796187541250030972542968031532744028264344623226692808252396251918075802797689470856387649374905604219200 -300056958510584801212056909411227653128368595642728493881401007490597341806600238401675418880075345886064712483677688151480971574083039561690230130767978013908002395808954835544289534987067066513668027712449427974058110660788692145795109210198543469287353829257481971008533353600 197106381366435878037575314630478854899842129206688889946230661817099288324680501432824714816049494452742509407381377906403879602975238056903409792797585557411980884143468607486852263500125090244323307859384882858820931313380158116461959670837319072066347946460518329231467599520 -128916394009028629353319482890846755356179017381311150050890966420822253981718744482742498502751820812464980335292467477510282700741119555289665613189470760441570974138585319870918864251372692414531595501835207377542089327167745411799560542027850683967663028666087719635039049600 83950710188010052448295677002802268522322762177864133796026935177820677421084886871064273079970687436295923620405232257691404026771278885661139634705858106885490376629766041634155067957509021348981915283841140199464693908928823902185624476681366682515024549595270181686735051200 -54431163723958490266647968965796325045348206008975373198796194677900885188970990115372719081010154118215881867089498788005747379278805178010138562467949167071552937163038702809109117818076175077041447645440739271694089704245446715310747945429771193809055368348219774747145539200 35137925897144436353640897774152764626877180933876225506757132523233961842880245331327936804008267298916759355980720964174943085596078000188051777483590472578725098134358888628483112016121092472679153702621847098336766812500913376150945163402437911071941564841230916232318267600 -22584376303121894134989705236036648717445846207072582547932789450830717355423884178768041433003604281013164987775642876119279658434402270206337552707401739640342969057297336964631880543694924392696344943907375229016451831624518682791034840067207956518034236547526195732225074560 14452459238345922014711842087907411721915003972102761869410914750958223563624499261157023101324832091092042440982706618677013433298465616599618741067023297551414016034959899934704701713115352640377353846357108721640220882012277314072761203114680859546523615538092702047072360000 -9208210826475936683990168553453785321969695886825269061600821323438459306295677553105156115665225216470909493914024319225218098898852028293453848652583838644342149909838164523985619149412507474448262927661939798796324718692660503344484991422300922436796988434832488186720720000 5841262990264497250218253181017452253562409125486097550981473390548546464707972325354121141399879261468791226581515426991507399471550691417446063856145870432550377408791896883412646161106913755049663387785550246515355646381568652631790649320609258620621218854068908322528620000 -3689218730693366684348370430116285633828889973991219505883035825609608293499771994960497562989397428296078669419904480205162568087295173526808040330197391852137080468710671715839565996488577108452418981759294892536014092451517043767446725886700584391971296118359310519491760000 2319830761164811932022449880632444017204268102289393960478993714069770638793924423949736603167909230335330824330143325688331038576926287082111496546615648096852299752358744417926235567283495097009910919038471873103154624236462412267326670006721892897324323491375091869036344000 -1452347515450051463364308723915404883867308287389299095392940227082597523441204800103896012135577690734471074453727631987618416706366711032793999530030101177386380555622225777720316683409294730784546599059618600758320153921304725108140216417067851729289339580048703877400080000 905263907434238158752415403927000679302426956159884064527018486137632577955750964929624372429101634934155112286191716559849992845691412789021935517873492119012794636865880594558778473273698911586989349751687945405101582427299735751526587597800738662344199839591168464122685000 -561782660937267525161701296197531618858841686116083196873427998142746692559386770816360487443354808863017000541852532367664076504577470331129970102154207588190064799943750520737994060986039122199008567805431979610585804946452449842431339352429463453191678821196542992912560000 347094674350129935579704336202852027140058752196300561031225716024222283113291153012801849986045816250382557573838180772614000129932544800546631359411774721996218487507334075944181515794404642840128189199652418378930960295198735845407915054447160079665565871008638515823080000 -213506976154869842726339137899569482240775635804783202247779179940950177511705146223000801840155913861579858944579452374414662264798842684033726180747411005463220111643166843353899890387818654251238516381634932986031481458895356839360162873828000990180835476956574280321424000 130755111235784383548848633109635672848797159511318571846374833353098682536530836193616262871907564697108470662368288786344549876932177147101191369081887612406166679110328687624452114079788269801513520938417366677687064987410747057661844712998691881570478102498573175029060000 -79723384405067865346366670773714212591226408814271290036985660536897689184752469638988810193256873617667476249752189477771216340374057758031547166408387086961213854599932399154607319137425343731576083118231024238991778317282264537669868468227008115396405409228610780084720000 48393960767624807894199166372672674198353154514348625892016379222230537080376499128683842976843219269587447957625492943864467444073215662484032811716127947436322122441096088450037553255661203636391501959728865884204039346443916433401609120345157100148654119648805540419320000 -29246433719332521632220531263618544340240136784965279754440616491565032425870271593628632984335968907496921804107560009480696518788821485507879595728277657716107860306639038428904164071033982832009555441438813773091589721890981216847049251360512304263460419554036069502160000 17596604287798400515386019643610490844711148965620776652255104255758294509565280075499894178908807959343981285471381939037552405471274260447240890096513724059191562617827821454724005382738779670592415857265686286810106482671073698802974632901908236398515352431678368483799600 -10540395247266928761296118255740061071707177417010781355760129005113121503233778414608921637948703602934830720082691344515006432561828175975052779425532347190197941002359427160899570611956673346777487035966134880618366611916117357020084638676683802168827831739441285614256000 6285717431509680108480575504668906851732353310144303167305458991421280099104528988113958252530871417697016990879877396479879251311787898961867022946455336613423689069513346097612866859954228789855677484903392727810620620727385599950515590174301470064134869758238241753352000 -3731818972604420362912182472091987815788030655110548149080189583629881053863053694435816010623635103707350054286892384643112391326069764226116739991427878122065805450888520568732017140735678120677168390705496843376786371841466077582561494664013144747861166456798160112272000 2205727439105592830396770103537813990457494940189512730499383578403754199054818160452957476477877039774046306921226128009256827323521367266098801617449921340360086996634440137479023376229531604439981979274606577956146911833449320690355055620948166680441119909067786688876000 -1297915650118332310117768854313159967938625121830523193483934799854109908865314487803723738224998720924893364072655374498008976077972903713605245249276317350691224745127042461062036895764815291207658817556628002896509587789599930852506445952161235269813287086988648035107200 760330125069320082659749081322065657785828247937022662849499758990443923510208982129244104075700570838840172022760161628371594897162344584702742679031506038771262020660231144681556267320972654090295181901985051201750666114369596456501300846563099869280060917295330119576000 -443421522692815995488552182517316709812492915600833645220301342145992008109742964866148950317624385629241220586585003651472066875775074107058930656305029880930851326711238591791220623775328368283302297188307591639900717964558216055356607083498084602512589068735662046672000 257447035379217181591215329652323681848371709222194534149286798976209175761084320062089768852173368630135116557671885343700065143336515065447043621177097940737813352514913195562994868737978476980272550834658848435666041844554358992665924836307276093235105166552119576439500 -148803540974522902988682752114315165863098262144848072283331614514984613904600460856905744886642078420045256204105917308673929278250333830931624556082657594646486535443759351130006886364151763377760160745155853283012227798494473506434163452184172717272179012522735781456000 85623021118127113031192862282171513472045065594822415363031797860261638492647150427498223697067818894157188405969142582532047830599782253536065933090184943804781596624195954502676093629208637615727567904179843446454576979133705247144903888060073153709073497369639769329600 -49047557105310130214267597051980408699207484383286162646581226270198974586622753927372141233999568924639960625350572674118194338314114220519841369200596939986372436691437944477801362962721805508190914511395982334302949169716525100655836924420663836003560923206831291760000 27969930440773260530685280018204514111149366094390311705321647007025232239757093334400126291937662671077363167070833109913806902077820037518667708906876359567392124845280788599269077898676323729344165301433329795215243889266449771452429880102633462034710395750300851020000 -15878524948432454591645150809682171143034224144939361294375094875113834941982819706967771532780271793694816284079363657830350410967506318199830934257084784876757682620159403641999411270374160942596687642575528170856288537462845873516224467007694037174680616184510107920000 8973694066947983295278285555308979457056800941846837734768986843101792711511463254589278048655951648879643730579054054180996079162418065823031488904248241616017778288591715087579471841726113757460994482041870155190768929152455241221709918650928063354420478527728025160000 -5048614873437401984010222442499035596978297765656920091431007232054016712492628107459984072902372797581067854927402768693698607138531139471168935220926653006735205346102005561467475215019894894441470066319491176741473251197966688557254685940196926700210545643242108464000 2827552161259583903382348608217804027528429755116294531726781647822460658782397235509244326544348401242643522646029148050853927699339680385638445862369635206694230266891545322575128164256272302893355800130234506454234207245614460312098809495727174856449088063179427630000 -1576463441609881463149964215926944222803532959092391116554315861995018584475112883330923903292148865522640797066829865363847246561706402030242504662326020277314125140698041476443831585906252305016717010121232852869135441316841773658609384872820337359187173895840718160000 874962719210662365469963958030650272526879943315032609996974661269079893972433202237066179335286506269038500637415281261811659499458407599309351293168001545499587254465094217508469634248939386117692450601266777563290382478441308033823655358215818307768933084584735160000 -483420436139008932133647291835997404207096834594089099545986000248829279060698150509009100698978974384509155441027505963715004117632916638067525270215600207691209759332895351192078537824131292491519900009100545923498078849154971482338756272229095090883643158203520880000 265881239876454912673506010509798572313903259026749004750292300136856103483383982779955005384438435911480035492565128280043252264698104150937138898618580114230165367633092443155643195803272210870335945005005300257923943367035234315286315949726002299986003737011936484000 -145571049207720886165848701406330941363489707035579165241705929221467109797665948704001130162172412576333674826847252198413374830913615799224842553188916648692844162633255121856551830230454994679410984382772628160538068832193203972942588442684123642504414284354361360000 79338562188773923489104035010845963219008055763764207422730401939031109680721473650572963223434803638869961039069483111353913292089575170317076568377882224930665869988221039082590145414990744688617883771318200878492613077352887695864208170530414654033756338257441320000 -43044035344792273096817277421614663833105494138286199211690009398703876520198809139476182294576185601826720435321806246609346216254055228839762247370343807426268160603561334205321780337507017182588835818146953285602733900714728798077210853353579699941267483677391920000 23246538319222750053890100145968175820122678725324437715287713409235907671966344038467104861013100236883982029973475488954086017432077904036858777826611960100404439300320784658963846111762603830981470626146671886615579045738563469474391117916917241795203753203976085000 -12497339000414150428971317838472491320897952082734417715738674728805223964449106555079915573280642687348828739313740422861716642971485081210215278959586589749977426567852453832658963669683575819535638608616450806244535294989051721189432664992134709189101537722457543296 6687873107250384015503820249022818837860725156095894464492741268609824326023084178836696033624625080290507392444254060157627915967168533874476227558245219754380891214425833920033151484575076516844151651575896198229903073197016496163674029987803718176276382008024404160 -3562599071485850496297090850356653097042236367043108056045575093645424760592839100050169816954744460633220843821979036830379145028762823467424338125125842739973233916456504831405219451113358144538989875002152041800299244733338930970760966532578057210329045599170894720 1889085176440745565711673970013957772794689029021265895960472143604978416046839841268641001665493479921755638523437928765153272762066911169828510502654308331864788048057350491812003307676350735878158643910376799234872051745544369447871659005331995304203140421216413920 -997100601873334702410613287829306805354271474777520313925082276115823265703578421782494137604044253313231910953547523608952124891901771873422997594405771647343576521391161149891232270506436318460331748455079646019042164037393848420816201573561561909372722766047455360 523873490825513946822084124240477067575021997065649561760638465705297620552197551761913586582442298169332956389879730658036751332094423000163511434521127643286863219969006889863488700853381621286301283712113274336988819518059307662365337652141074590479954342161440832 -273975042745514425437856990490265344373624816214998978416815679370440910906854504091016614219026875429286649142092410645249014167339397131622755583822459781750657468446548769659193773821895301148144886885891252822830919874737831265579336648504840911027551399228645760 142623083960876971470023654859647623890700260339770037815082845748220031152460651654975421009588357620625486657829751744124882375086489962506149663097451373727794789745117951294105619600322079236929854090914908510619260504412573554391774932528627626152000649282000720 -73902640662192174790154437273245530230884179133403747872586371888493159902064919025010960649518137914004991506742746559356969066395527184363376128745598816086440270199681971602632927691794063174902041298293981029199237670532897513176148780204407363946060368032379520 38116977123875143779779970013172379156938685452086791095166788024506724428983010285770637432795632646497842622562899250646260070522614178685842261987083301041428972169236600495364301822108294413553576505586958669634307126599775215786436358244229034716658896445722560 -19568715814776845468044520038258575756160647964378415585865154166912113643855844650647602839513978335052435740087409694032568162189562554726904846311478986046465897523104144506281515581113864533572387308380076419371313579955160189521855516200974276090757165734339456 9999736855035337699865517315147857108100960044690228090261281610450372538133882879654828495034658740396291848315107154969472724389320487871452948193758915825631158325485608434813667553242147756935575275508686849521504580951929342129878998058673961838830312678711200 -5086208384664755753149807865161547414481493021161120724088940724938651024105774023560697696061584665444895696788217767990752217742762697127709191859933891251969380372774469596357344250000715656588895430557008695831974072572095929121005958196248608533408196715702400 2574992646154727442425372947409372750591727658048655162822457451653893857031606598134961372770990355703293589439803039280584586725567948545846503088963396354837162790605256551133890584248011217990929818291400954159447688778662986059694239024119593348418256330990400 -1297570629204729634524209842043533686526660885589463164990346321490694557064440257589135464839215797396651855711450044833095832434480249501975859146551195033266927102621115194781084144175054166186352740985651185038094140511313742584071275376786399152098088479779200 650812768710497207316048998899959864648528350428465118690470576872676488777633316697050756583419173381758196380274163111599628455419000140834766853192083758872943124908403089882387516062800605227842546650615672495669092350205799014823249056169428324724197503139255 -324898730089483785243581403507000244442323045455708015570905748204768293929551733764518318419179618536915168239762452723419471303797316762975234622498388147955291419611059264839881443276281113374273970246797215598461949379197902784311138374374753609846713262097600 161437219468139139396732815761266476599845874611169559138814538438194837637892528147790254790838470892953175496081343331418709261544149606525077639528015294700526421893968700130719907173105413031765415122629769121354146186860017115568930126831069161278974346743200 -79839869037120134258415296130766313466175720258712161440346847936774429811586040359249301747257595247214789747673199345864929308197573211314113047231584546990307001807592607529656190483744201157233906701393882706983854568307131326206718165369020207288824015963200 39300059758955097142729268437038697777605129382005831019549613037201078028373873903543522754473070952433367003124851230806184147047563211159276142814304815832185278840072758675312131030041788457830975814195436052971866301480373649701133009972017710730678902267600 -19253982765627613483879765621867020926702668038316035042135934449233396367389370780650780140175954141037122438740237192146905721654310038335397304076465615198403950563508514327749819233322798686317191251605826035254433722895810966365206249846755963706813229638080 9388551967759594810250969304780358501410743702894041854911485064254674699268810829574296817578058133787451343967762717532933904521838486185216951678152738061141245243816071227927543434205389452306370347145255729264932852495635378335975183748805152581495615071200 -4556422438758134111930145844978412008412632956273151688473270958540908586662143122853677280864776281312611625975081133393108571900861336417555058465131313371249383317709808911235314742411889162324884527053493506938468184982425825034770027352588590279118428334400 2200864542177925890484777236849140368261040301409716787796502793245840104359954934341359550788078666745134936620679621530930529328656787497985699536398304143828791633399953995704712213541545228098285273098369548876142811573301363018337991607037390057660598871400 -1058042738304334172313174881197121409703304428412683571328981312007245165732366624829744498992111778157907704507938431306086787597135466408892971117652189357279788890016618870046024977850480910888543921736042063558330596626918374825456784871179762246517884203200 506232756327150657829842135465084243719581041902068601051251058514235763911947723572385444902379635395552763233798234055681524527244815466408790796292047523252329761223336105514328874017691635825134091784475510410216639309187099339564707838364470859487787672608 -241063217298643170395162921650040116056943353286699333833929075482969411386641773129707354715418873997882268206570587645562630727259435936385138474424784534882061791058731478816347082865567445631016234183083576385817447290089094923602241827792605171184660796480 114246218014234263270100219002856435370545239517776218028656571049444092206245871007790755532307411143168130177653852120366338795587677460648784951836285922206375910179674887966643019333528129907950945341369363655241704313861242839559958166852630364871257954160 -53886424423252914375483717385727078245218887858307925195752257095296754057463596126186145029020953494786805658066441735180447701441048480673546347879902088881414671263920161552413552763746805530855882335592287910895015204700249302579582106264334077152140045760 25295309324065205983598625745287787494315288337156778341125294997333491583549425092873312727690264102292888894535776166208558783398168017686206007338119176279196183605540503970322569875336803207909412656004330869487415394255315804116103526946713397072946474080 -11817350615517485543482716760393989272153401879648815530357771403334425075673471875449211747592703534811639697294576346350868683541739562461036699611396134261731346844725792694532376155500857681863023317156221749714731466629200971083248365260601983976063543616 5494347466056148004210714347439278548790834715385501123108415057952743365976233112823185339963071003227972725114094185422278884878400253888134441130298507545469604859209400566817644401566709745378387365446109197657001672746808378323766389336103056574236860980 -2542285585511520537716981981159118232621634327971373426826420361670675773602397056770545423666322047155713407054314508932074248102029950048695388285556691467005722796346511068968894822033911358592130531347971379128962722245098549483143047729338400606648410560 1170687739224909913264810851506402468821208512728459191988458008489688084196848492707409214849385380377175018749935100617657290539384612256466113450643886800156130710171721662458320867897074683363853420970266455738716876656937477953483804653479537057468796960 -536491194606863116549275989612949234573603901128975229105484550172816087143320553562424253239020310886049856847466464926452961673587485434677945769490825210390214680533930109351157666320055469462646029033414976681475715857959208409639012147725068575653378880 244672499358584542547472837687117756979779960969426581758713408487905518530514373670135909431735020570759101380435463549791426460227019872481911631237482406556749422485928731688937056912631358042812810210693799971400288595826851108032337358280675214047980368 -111046520132489202366477838587194140838024188034535513657509867694964683145467945689925526217126333088090363712754370748770692795867028686451699681348327869844213051052615158103904866980014232092048174074444992422723277728817027734356582764726478917117086400 50155452446547237926853283591497051526539625713483562815098867735339033626125250394694459726466425367581599320413227875955343120791905705814287318312915457829939127288114701318833164995504917515894870163533312287604622418302554822617248106726914193682792800 -22543476363606450832884281312618584245714643231701510888234483537150877859103053721898867267702857857525364400427061699901496606328790196580177407024508003670168717845939941165931045503258620542589247826143178071955018824516080448174871698046184660207348800 10083452530107102255070228237722469158098266626227934840068737365261763138785552643680668039921308409164206667058489947094494716987425735518543207660058549834397754819644823081749277883234654067995491874042957661702771974218788995644483274577886813375877400 -4488273607386018447369605350926091535033213415584163477684731218221777276812817417337560511002567352049030336014004547879654791320718823629306450326883204136814639739270477642402686095394673088912279089799572132126346623110919613098897818458728566555277760 1988049120388701864825876244028824328580777714110102441316810374437574019008680387559429956074710764045741665351548560997744990149567647103071175445090908739279757842469656012775964561773916758602285783019329998464372753480061990787049334001989380080791200 -876291516333250896939741552840291383212516713565772290475475637308315984390632734546435392932481206341001573633216307246382349481218723010948913914327926790627059678689773414926737003240676952067574243189929564540518125222096289792192659964894869181038400 384361398631201366472072267937433196528843408794567786091787966663677520099484118595966422349127235715439312985826913208368305985025577608095855953440243337804982763257640135589122667589099321790118642596780482650257201631847624115437798457655983038988400 -167763121674605080732204936080314638843680531192845730252320009365910068563601438908852309904252844288353182947476021908585269577918488283354245049932064356710097110420375066654744123970130047776852980027294321276345445256352027267126811882863299024491200 72864281204940415661300949849808298363449305338982250005112123470865417838817938391755256988265041325239964533903764739400467831603403120083709417209299593735280983779595737905269462798966931198603309235735294763308245626266328260796869041661522412129760 -31491269075160537320085358355356790648882710206117514905339069756409793104705219275125222841426023821638732808989704581857132147786865729991469047676150346025680305955413955279475624756632503796713799818723152729298645650696326670091046232610792100622400 13543120182621123936762899649848381692748665549952324118516355892265521141755667218022603275553751316151181222913727119280820224271434815427878801753582514883067869674277727791322106480158919043527214505373498718403733025373866678059988632774581721845050 -5795570003855696424647422138419515494073723147676477483109525255531159121583405882303877776165646922810609498067092734551079085572322773912673246515648981108950291925991063304458791480365183780885345880457009852749294370442308474414972847309182074132800 2467846574342114056192596667249853036794003773565503023223195472310745798062963632375686827536410484935674964310468271240593023084950498683883118323429165546392780093114888973857081832143631669308745204289557607921435436672021561063942443883880200706400 -1045635733721251288994196513827345138552718635910716836506420600119812293697789035347328048408019849913485984878213223073792006818216063146060106430371468661138274232045715920775000598508264677662668338410094038319304496130663950317463020667836648003008 440837550459403280123292908936084858709356229636914642609955430523885360508683247150870552953085291753466724393921255289986275063892866858915873273159568888201787213214539996184726583690614546056006621962835504321008552362779919882362368180966634143280 -184930375672777742326462608770824372043511328237642183901369781785499914895813947106125904045311998313123411710300792470245350248368647249530440191399287391801045152958536719226679984886461641181544875387659207130231061847901768458775350906048041501760 77190702530082744953375985666878019599282752051995188855586501836720465952087532494149898001214300180846497808281894202182056224614051875541466923548670106017250410453194530296682058588301835478432447986294329819845708706425074445182041749869610243360 -32058583377736869038073678877849192234164559762389754428977015490361077170086427339249294898884289618554804686208386104588129389309517862890565055140979337108784411999706712140890044951253486899731885614337262163765080788235450653227298635439219570880 13247738131094206176027505536287680908529766607693413227268443165869798065873950121072135097921302033549853112977288963807741703523491940400365853668551755481718264370467038399397209751915043851212735084748192158849981913962002402289516053762383381496 -5446940788115092113491485389369384220834558957641932017085409818566143110785177729662551875797304800872186301958356695838719055780584057727022671111886184339032472868914494496081084773180928455711550401952266966928039553464553116947231270269408732480 2228293958774355864610153113832929908523228664489881279716758562140694908957572707589225767371624691265894396255691375570385068273875296342872910909407984502331466173646838657487716498119470731881997891707745577379652544599135366023867337837485390560 -906977628900835915609989115147224765109015473979775982080906120461366302621091087422847384083911660573819388227060325634798021932851145509983410296947905844287185353255960683428382410654777252508338819758057497088643349046207367137093879822578240960 367299419891127995064279217683890730899411237269587641866097946444149803839243028093755446478426213419514576811251038305320251572221882026703807971132412162087061904754241387879622701390896635884224931393248430838529543400291579966337726185459316880 -147992175021826754215680385519348674055821170053147721394223406158518753079753395261133581354811145844943099561905527842727575815960933488131753284719044900344568008338935216138358927859689739421965081846038783812312633545226972365998850258666819648 59326309228866410217656131221313243972814608986320150704681394597073844164624174485148301563517587620057364984728892356778547156544105990140280106848013626231423035412838461279954380701770668135627401614665693219221536771045797960130734433139031200 -23661439197539150508934177517670784350147311298765242056888940494320572490694357800481273112669314421973388654753590255833074120659512432748816228932104415702197833628992341180069141648158898208387056830303347805046144214361788414957527270276702400 9388914100186319896713707067331575766846244163608882385945756911263831816801685580714226104300469240114440556319375203259344818226812346134341323398930967277180245030108879567091389055156074434432654817838392370316275247849953833260763001141772900 -3706508904572828754580737768235397109698372151671431072535915645665837814470331608061349057140388437316586112218969601286707968879089924743890914317139656167478993683874622993104292921629103405175155457840410340676381520196208189618182200741019200 1455744801651067525349825993031583502504722975511533073416279913007887025683275167803805209398616328279412806393247481085069361690193289283470199681079488146937401867144960624827917944581865250438358158079349568584491872424887564328300545508429280 -568814900789852723363897276582529009661758615612321171957157129539984800194622713903078735944466582685154063279561244418189186188642819256927574405052766714432848775874297205070242901645591342428880901130860178752261657821591378246948114742801600 221114462879292460382786658093497548553487091907101727249241716540832241694152471155965577989973281419517981245956610908226721220729650838314331669016176656333000463454025936653027948761075247273654569948267901856009228257237110908134455008401200 -85510355052886550335623123187672933639732381863063871432607186194723002559931980187299819482413909697591369370730695127568198105563559054355325955694567595811319082547877274203479783936462000388657178565852521929885242673794438273275662254331200 32898076079424652650736849987188290031424417806106705579979998146961155163547318025949642365712556036393221357327227087983730395079928339355723386412751510204066563458621372063874787191693593809468972157179572558039423334154344407729973806781600 -12591206096585550510929499419556957047998410268236523286726157564160672335976383589787920675222359576518844433164089791947729906606130846429672547893225757862275835798551489164015386176964742378875894379582397554587750513503677140224709399430080 4794065539648234030741835267503726462240774024544078550262114589802554840565720763353159452491271965197548526994947981129523599498023957333136817804173600335492954722149633086873674334620196451727172429007665735582979721377118451378660906392200 -1815829702248398542490451234750335417548872801262032621620083574903693655537087921843951356467282351236948079091343281231268623052336190438949956815354132695222582563339315832043974209956573691902401034803477409173467211540257203965518621646400 684187982365800596955571167248335551311394766091568165452839513180045030667985850207677946634520427471801353583127912555621272009691143388888020977705067190320256753808366853621153606330342236347179759531969281679974035293821840462652431938400 -256448142174305803150729107037287431249764561825451873174025683051747922796870232838929359110506941341361880742173838468630576919226151027022405573903759089934059040769373556006784327408511682293220453501253149928688408078657113306459137579200 95618521582134020889057567052474313651697929480632769854886718966437439785690186815657946754060445271564929819581959771875115108454322025789782649698401603532556299486866425882529584933745070112186483376895817330553820726470723675694049868816 -35464786892089651114343748122173069257405794101233266993253276649463244428358699817505087241163645892449189376735106334789628998856096614415611253811104731695384647455899102324476022942615860526631220653342243232445069028362893232069119780160 13084586616882079257286368609177813301521510929087487394946721726796268243511258194777517942252684168296780695974918149160276226073688067141942043785008725796445332893273315529970498493073373043301262320820001420517482732686594511546868978720 -4802024675896979300682621765530406588609601450504369484916435569720394319809252651852915546374384801451734593970880344926530962058337868168735486908296232226860449340632312100615062035864765640358073511766088714784510021384269393995863721920 1753011849013527954936695729746185359762311893152873519351596507696223494589457289099714908264512633484511066264937853190509172228683000169552585419647914321453317443952420752639305317069949956778444449607790908664231641329200616842240023485 -636554657230444193565665399737621917871137368293809391424125824071252786687802930509967399313071254144730259523154738179816096582330280912631860804865058250059644348442297464788173278255187502035860679573892868961763546355000507676047441152 229917050416095282378533536732427179967620437556545885004464709827435496608200775184195023831208455817147614983575719880811762929878500896205558789292620189469134998375050784024056920616250443369893021659125611310551989122556840591206936960 -82601033671411883626799884483785719535750482516778861090712922625415298640004238892200192437237549897532523629177132743601397148782375145171445449052794240629646802810838612647963872470336085736849826734678791050749936686180251075200229120 29517036043597749375113518042934727461221570729865892451907301446652642028137107965715605489577825034005266212121207039733267625200481513740643642105023930620481131512912668079004039173721793349467522830330132960225612968366671641279177920 -10491245533126421498629910503271581551802307226976311562596107143239020861904867711368593206450792536769149626875238609326915996545164092330948092821531777879211911341684051277727810820561201585424281739412120600813617021196616718762133760 3708876941992579994586066952565023900707576216860639721424820975990132727236791261342981541998801305252192332881246325269092838215262235457842213096062642602369281333468587141844620445015298025269710868440059536343968834254015206210275456 -1304105816453087199221542529031302356085645645872236188967939864975433448395496224100907715189451935742683661350649200164941223001147058881097824576674628200551786685467154409931301141003972582724933498045027966365671179414210691353824000 456070713900026281750230463102239166664783378963745521141877846037756922261908089608323063317659455056078977073471419720604444560794406827799660561224694412833419781855788550664176943974703894801275900299455005091365342238958514251548000 -158633291791313489304427987165996231883402914422172355179783598621828494699794118124634108980055462628201383329903102511514589412450228461843360195208589360985537315428100365448409371817288311235226400104158262640474901648333396261408000 54877343238731697280383351302522505987675798126437775531381721091865039482981998847037289801223668444209722244378244146140201099264995000105476145961514806951579435449216793089295679046036712710225379307741023630528432362938863972784000 -18880876135283912630733292895693058004151393481263905987020843900138181416522477924994647959581849562623205135828039244685999259327536741295030953715430269244879078490220043496456974888566477380021599034551457081272719386409735017209600 6460634990425361165544213351179887166224987992890582355894003848510969898111741748077777583935130087769113489214901696854846115272690644716875116843967061403624824343720545609821171574998305807409625367968026515239966829148582512872000 -2198598239419509239041545408211844447083538452252862056956955284569981387920871668801921520892847617037187854070343115805554326536313134324850109497807479752419047614878400458572337328172366271977613095933331199049584248692125708704000 744093833118301873380355897208186908971169699021511810362869267619088408446757403229619679076548706044619287658904424987116575694044695878744535665692503593088897730383636924001501352013767415167910838874372536725694947677140037904000 -250446046751918015797004349268958598012549467542706339510172966291821133301968416664211352345653389238940010588949750830156065810791121561413320766477866299760101878654854152445567909857206835146918529913210227938272847479649359072000 83829857315572558065386178019193086279200585663600316419377340106012351563575539466770744326808981675811864655467902708427238695000917078195292089890508025336367434383083126026919258716092843431121341262616201296005217003604854911600 -27904529480911808509975981587526131355073703965692199640292041089379978329068140737898722106011311514833353005980993966744157124549542439343786548645938871124449631417392441395923192915204275205921112209470025396728504966525887904000 9237094938972191459673489749887458994269550204709744756273958199947111939954689247032956486615932759065334305303957836636916278071108923827098317349555942103522800427640988218318065244783686667888013598425673226894892918282115248000 -3040703451556544353253513914900712642650280703625061206076351385321455935974019420185122605552686025805739370210708112198597612974998511577938311935261845395073895576457199441161410135903896856095915956328229914247558111412369888000 995368395053730679172766295347332729707343269004336334033280771161857813295362710751207261762412414524806948535825721810866898169992606690568204321349526738442697861354083242479632875979590545434712819958274157011976895586645944000 -324009574114041986599686683726855895463355877910377068733592085509239233017524965154875743139212868728075089454420510823951155818094145074447029268742742496927554062454570545138197736180942577548403069669176139385967651528894403840 104879132116804224312570758506626908311141365439309381752609008394863939062146510759498346608422898279748823721472203916843693687675102055778308372113697640190048491290391292159058495871241743421315043212474370186917903731804662400 -33757519828517453217526213879712099786529682961208246671403724847865421926468065361379110187580410175324930881464230696755741847202164898283527041368095251450442017829369411781595169235035169134233452698375519427426120320828460800 10804261153907371702862098673039724244864582596100991036314653694440444105586619820331500925420653256663061669479623286186933860436956622664920055822481035148287074387696528770757794549125267044335706701540516520041601696089328800 -3438393124425939965794248137373410184922610647867530755041151793018083720845124551875045561999439719541605359834393144575265645571157663180056862758320439169276544935453490637607418841422581555947714615579423638751236753762310400 1088039468140263194655440164018161305091949396790958362211652142722160739061950371894706198386124075635768271399650433420392279625941671499442651092016467737127235452177748407242895551189885396471126131779242274728131082354922880 -342337999551655998318401145997506292983787087909603862255376187176603242112515164891631225210408395890871001945170451007784164588189582003928604310757575348206927707251548746464932936762891438014171012734918909969179410316870400 107097543575586371058625495127635165427988037064616508820329435605795276562521820710633265810360003632526583941863433443692040561059309124179850255687820703195883121530880687077144320380740627466181915186197309266314323719348800 -33312742067167384176489239957845590337764355321599678050525390611352418903485641367018260033781829233582620925982077524095204976700576371504782889900167967706222853627613637999439161046123960521540895856006802882291494963180800 10302442028946861318886999278516279300643744765671835037424064943837873421105232411870769792463862719377731539779198362356418977807943918707882446876482464127128866176387324013450530732248145828868914658465319147520666698422400 -3167825712302028106215594335979155267953042608220183290418828132390965160775214319840536017818820373577370514272243305976259440795367789970042765978346988969702209191651068336108598565289906064386904371174370241278463501827840 968424979983636309644712942384931977295427427784702772206842839385824947247857638538207342403851337031125496890291771528068443177931729270733182534141402877966028625165068445141894941834550087618279189557382206912573760749000 -294338121460426775251581681267604834347592596775811968757575028524321286544803407099807930391401220481644655771269140871488916244038951637237765112140670616912334344690604249269721122077258099900263959919747102236657425248000 88939567866768524229136470084926664037280689811661340153034188835939900947819999706310526391981669603532192733052870480138249759377623597701926314373129468253998047243908872069305975912233816094524204691197295120290793808000 -26717975732642235965992281947028037099156039429213555499287672424328359959967577719622377346441042830831051132256748642206619007553223868321823601882049718474137437737683044112836165970928155849775877457978077830452714784000 7979287347180992092546343662558373241774979343048913196408885953752118312368695508157493775085770899477922027336137094496841622526030371485301372994504037544303207756794530741806476594020435733514147186774534054770337793600 -2369019185397865398596755203458626333590412220608314309325175316903462926749140366794397612036261265701947160612618300660330846094098086001034145828327784426108914583663693337648346627104582808870597005520104577664607712000 699211861997483183682869797247222597110916814438303010434249857684445257355878356237160481180513769796127261690247180383574737593810621070386088863077877074552361581970820540357126565142727271081753024540300407693462384000 -205152336359961418631043897442657504939676804236271946533871425269460385065385574239166870655924632322416881626478984284817352349193425832226335628736173892668122240739756228530085587080907866885359568438473067129441184000 59836098104988747100721136754108438940739067902245984405712499036925945644070792486423670607978017760704923807723037083071727768514749201066014558381384052028202320215762233321274962898598127841563207461221311246087012000 -17348452604936334729873510790452916525100186130047157894810603747618797663247370707473171612514431995050018177809632228112071406710316546886253885383059000319586176062556566976369653672613685387621010485401078159939321600 4999889155578166175499738364540719910048981257319221109094208854876731230024376276282482435242095011978222397089907411587259185580051015523518210934795824488888777283444586997211093216637992437451095515229533249848464000 -1432364497046489372900862128529737698461153934493056649727122750928541476874453176873428703001082105171806684039143488727809191049706716629227439277170423615290760828188944601610674629666037994129229505032289311201568000 407879195014575182390218761198976109321157470651097682342081745919491089003019420687219670774372310697319283021841661897090050392496698719285353697910829184568090984497654010886462160586719375333590754775237464286008000 -115447782834566006230609315586359058980087294763728582986009786561992137341308567671148958884067997153313335114326344889430027614431642361132837094735775416726882895478641722707516659605319769787344779722764142094304000 32479309570791236419544754118295681926397892260195641346730753286107121305354810371483240432717796532465484945497145028892981102193435384265371502652331483905829721261324537988381353568963295233506331362004311975864192 -9082097216865725230498533108977487622561328062105305835969984274410779592709068146486658443236667472460388599939281566002031999281786192670743030035938231185385141764152001301677875165755382155840651912145014001240320 2524146699900181613263555079489753873823560591728735265582083395414698051697068141776212253505935507638592044398018413955351978523794300888544272975413683933172200304132670574535473284099567647035500331965835008323440 -697241053890090007382230353962641176301860030650168572697308560752001586657357468113482269228731189360992224747394196683550081717064029993117143132650791843426052673651521221120024492819004077799978843358424544131840 191417636810674577623503558713881596146531865178494555103903013362950037716277182890571392215314796018203435706512730389250486625241716456996350966125615267359672285737221343198733514606808811809808515351716022062720 -52227858520528427801909580258357097756537171161284607087952345367904248701394834007228750723648805271191930802041884053225960589138799457140726223870035423941844358757440525429058415905963728785192786970137086814464 14162316133212073676443735387517466984246190592676381551627289418545464264267117687145362299402123122479293405315590252528203598906685037981281581869520187709098007335020248297562136588257360318736139323912834387520 -3816529050429673751644018519225314748726846606216620655920696223755977159723239112520018373947203589148977350970119433970612330484760565057042856937096589554367230510362127678603270626161824973609210597197117853440 1022104745695545872801762215570895638511279500081759885424671943829107339609257968128712044737839483637522958109411932844372431515048014124775329760198690870100986535096981423161561922309829115623574869697908871040 -272022606891304698690324067912148773358733147584341893090624153693649120686521883480895695700979678122239311644402121784668288756310538673523869053438913775705400896033715741078571157189177182287170123424212901120 71942821033095058469414654803081451901454424558490421725283493279504570076303813920605308994601204345486975842795824314103060578971602991287233789133186406469454710661548505206306319203979754789106835274035254112 -18907443109880435865811998634186978160697614864255038561178316236400675447123209965993510905282839512611557383126366442602644041779659130430284832886514167271867203853232195849226365099600461179791546721165638400 4937770575939903854719931401841481173200558212581040254165990723154507104957373731276520564502998770353936901892581262569456908548756124613683309375874434759975818329124943535427882749108256922281519419307036800 -1281361171738009126126535278590580959755846036816574010910702704042716129464692003660224209399205447614783101670682948871235213489716530371571815539217743227359386669943301205786003649178813722951167555731052800 330403338785847902941004515552806870512960300069195131085613131801590415581864299373120640381732294738366846896759870324127404525489733616753465525164784575641098395260249132905553296974118198195523571307614400 -84652358695459070557433836664509995582405514788970255807555782788381335234046278009322412437672587932967192146097953703959439590844428482200887899257905590621771614994782784378416269551538780191271398661820160 21549882435528092374281459725299541956356495279176501152054017811663655836343373644670849119250854630455094606382638345002729399758046415181688172787586932338440554731047836754296569925000081119187888693283200 -5450687343536440574459717322957120129769439483911657396999321323941002910365859826683369920644935851770910500180224040326635597852752287542695574342623031126020166385688761838766016382594544637708540295302400 1369769085029339883946257087670213782611330495305924319818839863959132241797670503320169784745407056499720998092165676800834206231225509760078445114747714853283713688070222701669064012813472806090818069001775 -341996962712136876095814513436516315034298381142701520682987326242072029161446991726232247946837652598109794062023159877451453311307279419941562369351835177932994834992825433966788414122479556267148334523200 84833012828594991343247496190096904118897390647085701883702051054851633207579708337286180984215573566544117747852498099471724133064532947024465470839221453227535082446272282970982580645965708113019911550560 -20905671125075289695482521758908445891816477591370017325425926978497808442853624622677528387809285314712558199859889285213524753932893981757001867003180384063854300473141029525923074348551860624479615038400 5118098241760660301096109601598052167815173918094473153504533936445706989247843333790223918777143684560457901261035071120927692348856169108903306818136130295425469934486599197408628305539250852366123370800 -1244763867336357227174732994955283062806277744633584673814815498126510884836474187260753035873354479556747846619760146663304535784715342551712576561202577613893904718866081046717751774180309392296030004800 300737523503745221552551770099015416982912064917933248066370152648136350729225675733541108150280733432961043046376159465165307741268435474380170306130338519119070003136895550046795325286457178758859962400 -72177005640898853172612424823763700075898895580303979535928836635552724175014162176049865956067376023910650331130278271639673857904424513851240873471281244588576800752854932011230878068749722902126390976 17207146963358618346563529113912737775826411961799273471838704610279966459249510312589207734371732686112719473272037990017190288289070277142370569062096688465060190901131652605770247993194199403213121560 -4074794132893160586573602776010223617441518405368167720486900448251626548908506946610571715732817006749987623014227786567777365566523720713251202969659962261996235683150867541134782021554353526629619520 958467000410602040286592940886723550117992118486342792865170670989778481298530554279864555243066211099290147829824787843063313494439384178052660852760633796844872917759137223685944871393890353950154720 -223929389056135521607393986189196002723330636154703964443467345468728733756524468394012001353322272683017723883219655182846627799727815045450043998976168614923962607229990981657050021301268349703373760 51963101819436576167869630128518559606311339928206945595214858371589616422988370229892528519168373532854112849824048189865691835577864773367253799762418614488765681934138932922982120327602014482449552 -11976131021124947132159453806828861368932191020585467614774231122773535155106154470397765855890278150977900528768666676281465467866857438164027764349853201802788505439366207331801256925695726769322560 2741339453684610660686115385450596144550974670952428009008423748051742701744247634528388859596368016656066745076203753266473553386403428940359296443252842867901716718218096051652717378132397815484320 -623190833660103062071683957356585075006479554826988742788632729442158621852459870940042422743491068920536246007106344931586580463320319733568269178670505786061948372723909447246722469102895033405120 140694869333977349472816403637902497801207756638235978920392848356201627637608924944371822481629998978233310641910488587870949926030225245971407709980458576700210283127719352248303414580628087898860 -31544327392076450327663295592701706513391802762203225847119925236549664285629516930203109244289018879196258182135345212057690684052636488268748734976510457960811477491055549039110064925083494866496 7023228108922873800688392784634603867485452268938377256038151293124925254434052751635552312659768834426647814088658285127348434744543747388080189085100928935295176286176489926010510638536401528800 -1552784867792350751359314287835350791540620959079132963850874618810339255745267063258686280054383452592422769569792301921421382014676762446665759721483559891666277857426568293679579226309191697600 340903276812280050742590573344563054487978966904428937495179326210899354370471068456538992956101950886407536974078766792393272954998832364559868568295248554896276737734513089856049753999352999600 -74316050204958388755038756166368625312968798868899590936845176309600366225248445848573772862420197151409501089406271087822107665728516054124584782949027568367756145615128328840609071847767700800 16086132386136562629255224436011436618376790641242822848355095125242610917110739544438120455030194573279778083909458678503266342834906639563675946688966726823906710000236638268030571248061109920 -3457196593733521677589618399648475632268083955766472672844963554097653420870828979209204143306110085281368235479908944811068619825454018616719230009006755448880076738356799627768896475563070400 737709879218390357970512006995697451834982561268350860745958132124373015312083456422166035629712884359281858328414913728624490846593092356345391251921896049066582031290781738753716545921917800 -156286582230377780755417423928470582482064401378414810347189112480321143218701161007470232012347748514955046909424597107703549132695636211684773934833390335741722296666899536078971475050292800 32871359234852757413293085385459177927587852682865583536499473279866033901162586761017038723000093201508177372637163371519512223123641369460147666394428445930563757611300028369254705709570400 -6863705198723971988184468143378897529534067352648662725860267376676429720242753965193494878010082354025606847619835370656904439042169141296081147951541033993048533035818622275844378802249920 1422752962047054495038237743288339312026534061792750439405708689888958421909616085749907857878974357304302926956372909746720141258741090846549484185935013327704783857927226979289349877350800 -292762215527875705378006260852305705360541513342548396565290119374892322701602306227082670880993468755214153100182129483641283772187627225638789719565046657143769827729065526478611518049600 59799800916094912251397268820709060117504093577487955689401365235723619799951348264429167109776861412405898440262765796783871246699978994710680105625441861045657245513581053654152477997600 -12124615454827754423937869272784565380520229235986293894471866293100408520140323427831695959679413703141120835197206582076329339130659070266746154081754169573712733132916308750904507428800 2440078860284085577817496191147893782829696133742241646262463091486457214678240089851128811885482007757150568083437824642861279500045137891182663508953026626709687542999407136119532120046 -487406513914424085456678390241776535896069140323044523597995124391801690822120367510837215857274808041378390628402062350633963445701900202982804196544924170129275913707746743794163719360 96630468469318490757620778115264924198846625076513814528779582017826020998400421987809373218586900846108683428822852760287780782876062509070156941709031101060542232268742808308319241120 -19013217955357810136617786976602562918328476665117288537418647520319441242524616032470586511253711498985270213890424328923374051923309933291512822901652445787753017059105060663405280320 3712780123123353471951483277769405943006928901024147139769561767027552580940752135693883186899045653408815203458702263235036972825820472048218299994476907946115949848606336472829140560 -719495278518314461645256386747860033675876905043188762489505137461240003263052587786640716964287107989782822036717457223187289143885706384499446955451425639247314504823091291629001152 138364476638137396470241612836126929553053250969843992786443295665623077550587036112815522493132136151881311930137972542920632527670328150865278260663735699855252789389056017620961760 -26404125653374422622573988075295597461177448140465892055901198925038356806431726841850793635616293639888131396829303310544953419158897813176273670560365920418474509994937579570790720 4999791120007780521353737840990379222227907878083269164050598311300579939831750255944519091892689265968915969944162631823487466746672481950457761875910873544587376273793873359320520 -939392151101585462602927258134162721605243507377820658758579657994670149387424028310960323816673384953368637121770976560160809574158488574128034369763229640021361178759788319674560 175121252859678277596348167874393297484434283474136937620426578218759496984569170709820998637429235960442795315293107976029978081108557746534979246708947747707685849373738316383776 -32389874141740741848893002689468550706122247251689939140646099547242816951523274483937299378069525763337138467686764730461771531647698720074287160303751124730151513447670465422400 5943462126994298689021006651146322728093860641012070113246636493274851879035674751362878826763989333420238462666660030589660047063432400604764515868545465005902186580914900674800 -1081958665184693980289186942644103030452510916198999233407751784753601572075374985487953341157528193537755587299711789086432579293220166407755410022810244552119955244742195940800 195390569756941050494484619863247107465011185112104284165773356706117237217543148484925234828202265909152421785083087218311534589807573049066394684708975367520434178104548898400 -35002482434985758738889269325195187349560285921922976059144674943672535746946379973986606484561387512559820344321632802298753435720129650507599538610442213077280233132839434560 6219803864059969383748705946266301673635099826812293539921541503471222651111795461063796495418383810442615134714015632761420647278699508975002368993277108941428472799340340700 -1096268979711916268371864940345590503064203641445496046204041586903128594565604095952492895153301430481929717746411568075452353987922557273439830030638805003140391778586302400 191646044130567269409751450451613009704377898198907010522222429006292651617214407972135066023132157162488935987453367035195215917204065635821388379439302097126009809703962400 -33228007651453665758467284449486016334580783326306221604585573771542804065499933982958704975927675600822257521634161317457534383691058999128983088987034063237965070791163200 5713596437628008380419374521192107686799866401230703958837275489984799235653037428777045611714392999653583305549288714343307741585901608386812945789233905995796432904334160 -974303899230111051472244132724598143912279288882215047791983640192292196091869963494258691400749110781366215319001729607872209283832186570223888441525879219746042151774400 164754552302901990455768776701604795625069125492248043361418158134706344594610614264844231270929594158892827164648710967754546338750211597641265807022016072438807614472800 -27625915209964124766580912739758762814410132828590801924514830890145170782571403120958084951869117854103536025178034159842196105404045201062569479184736595378560693556800 4593143669617821714832020686100668089289063346501140611236082320327534462636264839285506842725812070403136450788095485313569012670332757943655362437268098988911183273400 -757172774627907579657157349466291951688863775908066815912857206744902650810341840173125976497830838272517039160219376972903497846260915248893490050264801772717479909312 123750998274536953091666152757808006631957154658098087346532352191963508304353690585196134173374289548171671049188396962883743594727873557627870649861680677139055433120 -20051552320178901710136958246126085717874557103005010525314794671974740160560331969064428028092085609981866893097031672341501380524226187088433696591856361229302815040 3220841133555306675662095950162764976421879341424717874235347453348599566853290038509141217072762543632353015437083589880941646871645027636185605853522821308571587440 -512848045391194790334616001714698403965848097790184269480175951558522488328871272717981472441018885113957295582261802007580575858935034557269601897062741149253859520 80943486682224719920282766535693362553645904590980890725184397173694513218171249067536834806955992710757115326838910919268741490988541598797973311464119386207536864 -12662639312502062081392009205343125309234618046723845721147980303947396772999112369169420607586376717687635370022934319500525142994597362026157076402329145856774720 1963317874173997606369674504193825919340463615417519348591453676934151663121256605315931800935868505506856926361728999057172768565268100602613296701803437278273965 -301686299993123281651042420812496659874645069355873321272156147235980087490421183049747023433122651506455806211646232748281049671493777763666869121045426136397440 45940239927010379819763054488233903841822450609347616069021379734975385025519772478798407645091818634676123967480901149918097491942098052740638343372624843312320 -6932299677608751924898377084452062136610333864404550448738555504918441333192205188417484267403076823915199544793525203460694950879885454665054408700539796715392 1036528061843413864368776477938406419947717384031780868531482581477039673025150297311226714623665793049521463037309390469601517775102490231018900822449132284000 -153559712865690942869448367101986136288550723560263832375034456515116988596318562564626179944246784155484661190712502291792817448163331886076874195918389968000 22539194131837692091816407104468132176004461811351373964354699464629343194925039612707661256733119870077104208183338641874124756711324369913431415391362728000 -3277451351709414106318953118885711710932710775905682507331672627753015339428909216627335725055352352979030647673858539104461526005699133646529955515788144000 472109063758141793886420627839489425027211909386413789746586176140612923893926208585604312775830517512455605200639146704333148388916184727654910258821863600 -67363956778807390328621254864136422120410736178798638251593746892834186524698151046697404914506138051717803357998451372794266119702666072911521083303952000 9520559212206745188961911316902891012267075540709071201828569929034760328312446525602127297893385306596696674111420087128880841145626202703647278994264000 -1332652416418026016960267539020807994599661819458683750671140274764058978340295005956169657356369473521245797799700557866201588677560963130522394924464000 184739730711977540265819078276581203042844114782779619465075132876060308608784971204824466718833209007092130737636214775290978525206910765724076073652000 -25360720429099875350100607195364993553810553035269154861477769720263900353395333325159335076194854727600813213687338359684915395176333312217742987625600 3447379254546673363193344949724555861333585814486941854692604631005140118960358548928278408702610276210512434484685474425254456791109138185627001864000 -463992013008643168127557643764580127735571172197770214208921992838944478821110831851031568585711418521839926247053298801037789934104417654263846768000 61829124374972497639639167152591455700612667993334945997179463668397082673096136791470008549746922515292348662637998543062818705841744333646007883000 -8156492261480470831142033829317129609503673516199663076188574712438719975720573993692156604913610508495574853021738323702044399357214800198295504000 1065141930616861485007959711828472219594009129762544237008155050683174020358804368588034568406365607580010363159309357565796386269000991555306824640 -137679920526268817098561184842693236375253824058613238626201005376203457390679765622425149852761711908109447646914253034356759682244546499510870400 17613980442914672610027193835508876484627543218766247664619612190148094900920298653573170579754726053971748583936213122940007987517201371416296800 -2230140548458129709124193357836997257139243455599946949330501895118398885462359032339862160156518656305918929736355237136601245781779306111324800 279420420005878078309471533124776002943675702282428950325952813556989087522801424426657202736238285977439491196475421983157298944555486831278400 -34641595930553305614975418141785095101789034435014583315264325423439582780604621040030015777826033115331679610323268690309559869149569127620480 4249261183070206880341610870195601618794215672519312205727516553108827327060146272433588383962305463913348550331709360376756759650356026168400 -515662967373747392713567713535988994579461411834315600228310060120557808651406315441182254296475808922973453015750027396945977833882178204800 61903596316428882808272114795112897950681265057033224736032559664822207798478846725456610947012830208701941329396565060472535800570937476800 -7350601658062568156511939125845769023247367911312443449447405222132555524382819983697991055407809873443071030964434966435621247564884310400 863268334260836492799657967105142641102307161677391614411846427250451288328680021341275693716498601415988574566753408848834588376806180640 -100263453456543146666626941591770341591441017616421790291735938124326514323888504220821799502496933962368010983362765255381485293473424000 11515176209046138654287780994878496308065731721607607005663408206854205241374665797983014095994427450434377131499899953924323716999848000 -1307632987817522118331636775779945119571774865257874260202797223953316470051816046584397892708521309551064842279247039958961441791408000 146806018308217182266399036169739209025997872604182642638508484633647798142391384859590967121211304428765381598480281106503772978896500 -16292922263108496528987638696294756146237914184972871321730421415988657366091991845688708489752930896140435414397811544768048793033600 1787329809463403198907419949362588722739724997196793043376893804294367724917712731339985342409386183756745224443177940823284798312000 -193782009330518916605879440876682052984468454136676523734057690430992579172162626004565884874835410926336852477115024725938605584000 20762358142555598207772797236787362819764477228929627542934752546177776339874567071917773379446651170678948479690895506350564884000 -2198086247543285425909202929556314590815111513304402455638661949652883110780736675047681416466158697010889827539197222766688112000 229914768421194222710043065045545549154224307713448992486342801630359038024191997045217251607379817733322958972490743990538641600 -23756979515393203265102038868081629648542121348117576720747247011173723791248311979413952519706295747415690364551282387082064000 2424737588153664094717983324838606695780101834842275605672597458709244744748967621752112126437913212752289498216816665654018000 -244417992849395693396543565390375016298566966169668102290021278770233147237009336442366399915849212740207876108911645564208000 24329937503315131951372185570895453567477489767461241303468937360423665686063858433050202279952953670936024280864202704904000 -2391285286040115826077723381825153150632073280001904859540946986281640284573133514562648452658233160800569243604938780139136 232031106522157357553203752802668970095577886758175699841301933600387470535064325043179358990810295283160257655730361086560 -22224188081939815318664897645865671023977813554944992915244426935498913939504450745298821157614669103518200277173717595520 2100919830069481402561715836682062294977401509180449216361375211442380247128552860888157353168584892473816199322800182720 -195990245808529550637156653706403991112795135099882634518353546459926257411309823200032881638024984280833820642172485760 18040011261921470001829191988884912818336824935330106131802996890061394148086472362730299332590936053122203945472694712 -1638139501650076731153615617605894467045341651335310431945788593876176540121359578908540234514500436151845988238156160 146726780760040886350493915862659481742156451763593564766119386526324202573228352305866982456514211401355819808179520 -12961142581294664932433211140755877209386413632571118971412584540264199094803863510597536389137155707028033912840320 1128968301764354298413300065427830933396780372972823711310824671493601052375449649678744685479141390770541415484960 -96950950208012346530407689234480396540288484006705765039121666704535231616422794774671859995948865196114291047296 8206908877653415338352795364092584357247896501696311938977567723295871750825857345485766929679644345043534795200 -684680109296902745251529714704454613795202188416603250827891783003263257678820116759804681844750486508705270400 56285639615623761715497375195298633791722702426139681655896509188331326363236338427326285782282416120648068400 -4558566987992025695743319475884703749160893784794214937260459686793988186898781064980306610038620878162723200 363660961963408791458174924480689849652161189573471079264598469395924900303161186082698617205328182415228480 -28570445945497884850810600127551391106230396487253620144244548661857175107992461308405054101428701199849600 2210045706546361047876604718386822854629929773117152230888872037744557267322286805246579297083610294607200 -168290154585837123466527570940989870229378750920455041097920827062295514196993844072527874805918813027200 12612349392898307910802401849045102131284537261376384511812858403997538536016317173220769140935749969600 -930072692660657343142970415683772894597518948883621651150445424205405076398968640706782975756155863680 67471791320248579580684237744916560433971798747137731389262223854186752194121608979844747125167557075 -4814040852280835109435664677452240655266661226105702128107895570421351327116814910490595112609502400 337733378278054133512747076480502406772605408958417855312692005497266295777683005969830169370154400 -23291957122624423000879108722793269432593476479890886573289103827397675570874690066884839266907200 1578677093866766447837361813433766039320224516970382312189594814968064677581506771199972439201488 -105128330335189774550767712326332921597351244193366191710738833405198535688002670668144668537280 6876465066270728047112300473673661168784615751007322961123715267080613753428112604679085857760 -441677711897787626503337128984576243399233348348200145897204302868965224472680543822133975360 27849147763466697688816611008983236586013607141424124243518412902136081631573883847192075880 -1723262182048768033783127311053106352283714917038398848217713947535492344053190602699178176 104613046371613953485730686653334270834000353683346508445887712046856599252677133717941280 -6228340136788482346449236030077233324185247077068039091596401819768750120887061985412160 363548488160561194231067741843715160993191734674676290588776758202360965205962869192560 -20797053228106911001117186552115718780688636087000183840062036772852332443025378655680 1165549136959837869293380784788902920675956527952757555871608654302713136916806935648 -63970863718981222244422655586657679510206176067659580453985107261400281938353838400 3437031055076841984623585662002441114035200249249253774391743701544532691863309300 -180698237287720060527855544114038525162858282545415313440091673246590984895332800 9291922486348843375064781808927582803779364638549802769895304860601505787834400 -467134900953056606833857883290348425108033632101957297721512594084884443978560 22948766968217846405593454965137204290241826904572137988502256259628602597200 -1101140399783626217934691405088371852530687441440756893668592448662659230400 51578471885289681232235000456209139061894945514109527699073502497270530400 -2357231576912042014966126245006293624156243429371708556432086077133147200 105050537666732307188707800049193520206963022395913098710560357785281560 -4562455490411826588000338764351510106708491743579287674725748438014400 192988898184448196238626043177558453537560930585241018779071788592800 -7945371756239470701048526154655710979877914801992587988737516756800 318158825736861922011683406625823924518920830815720514700528268400 -12382397542191382910724975825437471656952594496611825436993532608 468017185719976675891332779579170095025206055487488002478157280 -17165678872145854347686423414985742428108959963942386282909760 610417459893117665381090487817380926861633274579847788077610 -21026220362303299561027874714915166479625688683051807554880 700874012076776652034262490497172215987522956101726918496 -22584554631904725629460660273807912437836400304029868480 702738287902614853277209386202177532936969537357152560 -21089680665887691202317109125038554043124487723472960 609658862932513557240430349439016016235932728622880 -16953080680476312821659025759801514889983156090048 452806642106739124510123551276749863514507374200 -11598035656949561353514370576992525853093038400 284386801822857048113891815853761294905266400 -6662949563474819018642832746307506376907200 148853128545714041905850518800486844590480 -3163722179505080593110531749213322945600 63811806168361498162526648869483159200 -1218040838844652138839320975239339200 21935057479193947415538619257488100 -371387216578945141427108897481280 5888803645543527612480585055200 -87057287262523111483345502400 1193823559507173469708324400 -15095766822008515949947200 174793089517993342578336 -1837992529106133991360 17375979791969754120 -145863419030176320 1070276659550560 -6724251264192 35168678160 -146995520 460320 -960 1 flint-3.1.3/src/fmpz_poly_factor/profile/H2_flint000066400000000000000000000200551461254215100220310ustar00rootroot000000000000004097 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/M12_5_flint000066400000000000000000023534211461254215100223530ustar00rootroot00000000000000793 685281826631262302694237088053912352859167422396878659740879908335400310940095615356427400433533360276935654787975944328976474171759293121115027955153489485744502768540224673949445541241818235223908340142457785435378548612672934292701234231539956058603351374958503848854737837585371061776068951189734782310194211094150912823595991424616888891256588486904594084337639968879542948883783770749988699615430808439398093038210405170364524756000845207303455707147314102706959892657293852132345780035200125330975833013831924080125956437522863560669845938170632368185915976343224035905200703838515591341448240258283303710990634256308096697713526452995273797932651891781580126609608494794534866263522590715941648330944491691328441395166046445943732803536667675205990205098832238531886146062296761018663050549586833838698070256020389062568763760053209067419685391209956837672004013285767447260823831261583758866985374920333958027609868913409276734583921675317130666423223002585218875213021760307852137117379243136383593082427978515625 -53726095207890964531228187703426728464158725915915286923684984813495384377703496243943908193989015445711755335377314035391755575065928580695418191684033575682369017053553614437636530433358549641554413867168690378133678211233558048547776763752732554994502747796746701750211446466693091243243805773275206933119226149781431565369925727689964089074516537373320176212070973560156167192488647626799114049849775381648810494195695765356578740870466264252590927440349425652225655584331838007175909154759689825948505308284422847881874984701792503156515921552577577665775812545308764414967735180939622361169542036249411010941665725694554781100740473914829465757919908315675881926193305991891533515060171112129825229146048148600149805381018041361988651797274745736149632079748447500899873851284066063863183163087607772953928708071998502505391078788171590885703334670860616073485114641604167865248588370908166695171653393754182309364613722811287295991379459344863044247580683402681159816700906008135607550002532661892473697662353515625000 -1944500888702739409140951622094737379484944744399591134587941557499865090298740110486169877278159580453010459173977501552357324991850429417026314123307129485589741495788258316825030712184484078812544393321026815328595339259431704514225606156679256115408181593472253841202295708905242095210831170379896239500822277863875098155210097587178914566718394963361523806189740164495080708316714125178507934932777227562960876957782788879012746285647518292627701638144646712713052834612924451302573797765481059629150545693408361215839003910599875810671901246477932757374900301193425066361725101155864760743186210697684039946010144514959350541696085580903149307109858395968069240857296296149388573720070621608298745972021614063978279027611560111294260704691365261750501326772038453478997577174688305325676779195463632753982548312862974372820118544426181792984705691266076726031064827778630846951532837681369147460248341043946012582503555239177090919916569432145864608589223734295610262794453505308736596113305949984351173043251037597656250 296962092465929403526605941245560608701388069495741471563144822386458056973478331782777180118623213185368515440659288590205250584273915432317170503226481148431228657948366447862509884050369033388816699066633182165315356660912627387692284760495992112478719338766902732776714082260982313252570337090806136902827355284969278771488702371700032997287003858775571725715280731496183331963563974494598651857286907283757729358789751357971108704588830751080672391672100718130665199744012144029618588063572960418182865171764962875833729094319242964300588322030457851983895488813691792733693505638383997173301720095099921399311387858796452838113865140795111856549471858970492518460141397138110447592535744223343608022236214828596021134634996155415663825872742551304803936414402212165307373052234368607183860983057535250213345136206855144234338295062935921669059297326565959330677697606152114213398422066251660985502171008691677226367539022125628561088385348555423478946520322103697740268588291744598917087927247848710976541042327880859375000 -6300647623687176691554521939949293461965090098504405126961959641194979466261483515669086779603427101167497072263258921851866300188176629596430918809961079861232430784130639661658326341867800161951732822179532603416704019709753479304501206720684485443730234222475292591644064289591784500345799751285565029542878391907502455840524837513008575615820182592510050822991543165879061189690307065748899425646505700380933361831568209311502426997703106904100271069833294824686609332057267007519766664989107493798977503836665308716121095877908203044181901433077761916551551807077854691483099445481543686667053439516207808636971504971380803570835331710759488062013181012415495322320170531486804748230272343532052429204650935440926765522404264347218462724201462763838830848336951167086116370916731045403954924601141510677159919799652789303504838118133685772558338750943643121583604522582967939197767536948660722175778728660239516867112334608904537050707931665945359777306834652098563966666883632254539740480403509081952506676316261291503906250 -130060737019777533733113313641460096024363726657545968281809806077111775432388105238713899924871168222640777792876001426912762551795530338999614420845586754189590657606721492547940620901478668706282368439603733352231046544583000082819909546896419913021221025112267565526751676426921588933629385173841450949817683959285515483624763689066552602651156850312781263572485736294101618264023576444840625945352558029035117565618652739122604523857528185810964953955748223809775652130475791852130932894273267953132830236897995213456261233399189830798899241787228994893987708331672741597225580950210636952812510611839877577936253241399402110614710560857041278655329309698292902114645380525841261062367796836293245289559934884470730444944477753580549211389278290065118967109365671779419242291332683757906958226133666323355228174012568896265009453880690994887933710678994691585613288452216147565933100045610849347400972134550827895860932227722203026454936585365947221856345409206633073934711409083177235945782967974082566797733306884765625000000 5670027593236067333622813134273779131083433164507705874495478483891924424779345096034751158564354161699833357211638044996006007017650454209622949045715725040415023303158751551178452968348953246760650997149931662353663707709360773972797439429395837606944493674872792850005224116140125057795332895556379696530763013397108191240141957677350616854843356560567937913748466569432922271489423692035124759429359288060974618474008129309948325661258888087000643596369095264317924693555251183866208570107443279368099751689065118463000448810786374800273373878180444184530288417039032224886683500701391101241449121812202263868964214185416383317858537784177281616805811316669908294028739805240525079883969252299399691855808099814187004922443518661295077931798871799026587953250638451575399485509002352088854408069011742182388361630157647128300410080896344082049963378718196677229909595305607946323002441374643775529060771599845076930130751317755804896144948887322848689968715631917708023738703318496326205230828598757852887501940131187438964843750 -5280751705161850909362752141999287455205051497126415937242482520705922179700922026969460596111005809600993042165641843146397174330221666677877496219970860868138903928613580542898403944923710969469881623077782986498014563923887176581116151218186708593983804658740137883859577484192684149654617072015911188282504422993976367255710197887612461657536673818865293186911365217973511238968545627281503444985821101463819620257036772497954209581280334732038952958172492979933198449694127570541707414402470062435881352736682974113910366865291338881534119721671798236246997149709922750103182986715172612266773907633221471212019329189813156950121596265188374383982362902957600778205686865243889431642780679949807251431209518191407289476537026353395860010111541841966481774184082345586479413797394164531381735428463628443583359820101362472059670462982784977895510889574220484621232348907315850439278194101937326133080413011234022378806481901130233849058286841331352277346816381482898546740221259250969848553225460818794090300798416137695312500000 -2187197525914701447335725521629171916756368925851664445639276690417612570124270424756261158958327793946946353170716846412810466644420225988638640976366717780277857700065031100127476528395547322875913411105983361902100571440110491702994638315389131072315139797142437781870663827072176018781875258864707383629982543161104246356258756489179154507368426956525426797026843059783211332810196153274378103347772144607903501462580390930062298659188820620765285055563922840938367210606936524357132551539087086662238174111176423862143829453092378647186742896650642326970961323669799495131984202920745309252094786951287591692213042533038983731391954660921572472568020016040285895340671765632158472464323655483948516401806837674981017615881463408312808925992348980477497554606953792750012463930085208928823384168434160292572839773529458422746107255949524510173445160011249963785243462698648334792656903495880736325752775724640603630835680055676829678090150456364646659112504555351192732331444741964467172218485047086034001040388830006122589111328125 25204551157343271507796299439516892404067173707634613659050132016173337937425020083798902714292954372740519197058111272080474315415244711951780007493786890817570529717733856238211706549718045061744446109179402102586197102014323620231048248558548042247874365375618600824832335924454078706638495206397065330046227032662980787531586963374377111175565922181539332998206462600637685810993828195203818210386743035913479025346266187226709479802220541664337815439910760924430599875264223831479692266857419091387524896362531892252213289867375779654004906974189650960669926203856076920910019771505953836752449460476613630025702932421146537196819942284853994067468309007609582532670646870829734592043186224152430069617227069944192571820712021101082013593089129469379362825326659789739619519949783811706807620827809243624034485880404276595261764305936394561947105800140829154777287501147409941226914646807365641493552590396293783300811809765860730533483704683946842575104171796915408425902369737093397972400865558739724292536266148090362548828125000 233188471442585490199997113718558845972980159226310944037427320486194807050054169362418205741441750140928495074061023939336585587429811799724795654384977931758919057236008884535999623999916881748301405626236832509512803366850075329249666345051840272612874430330935294375844168790798332557758037285760028384513516410051400911028731810494111758743911335642610517776201939693549965061209150792563080776131754018187971983059356129849792758897605935942141451803578613769328562078691026392085901606771492958079381883760210348815742839920897554480640133261452074776634598698114314330747294508509242451212115695891444033039335859819930253491676056973131842187976103804273755124091075447623115129707781293980520848217270346704397080613345222985691853225682252040643498092737736414725161048025319915052777567319542141645024254227445504557095796438512872433593266811114071844595101353868258797642955935699031379394260924604492083951834069492302388144767816676483906165071395338203480459252302962894562313525548269410592183703556656837463378906250000 -7948295193080678533861973644868447956198361487381745610142026282665580658693664584418672224973808465705275377508449154917414829484404626030547602755296582121052464536283822134111863781654082109367415481806128642856203329034289962732879968614879708998579026225116157742009456530954441724775065693132984654652512830664607854022147815075611510863382035141056191500204913657343365055734941054310146437236070674778777636170481366809371282251354328891015258772912904636032285972223732356665553892531778263646543673273629957684681277055968308784791685268185597117345021223213693110696632027701437084573794695436456845525290747410320582342963250696560415150063374691795780022899492334227018762813952728531688242460991549497114773291891424255417655378331193513965302042341877540592099626766888527356395943338383094657755456957492961206262459861111541609020056049590249175149215262811124718514814181397119538973166268582758664201141214589146635337285241107663268068654414872714318954007297470228025516457599775055342661289614625275135040283203125000 86015406942006098708966317904854047960637264055920198064359902912383446403501675915432330944744901245515404319903709768915096269195859242244115443141984878796079646198841164748719599175639362105598560003742500223468924074006169856953604455417106737221591203442429075242677942854122605043361262529108333915269770038620512589905573522507349081928118701458806347989575234285823053400731230785413446425605111935303548767679311965527463639669545314555458775771848632762456208831311242199929476464478055866823463116646581892342481436677293943322292832812031517382350927592018885060050495906417887989685413461963153791799301009918437138294432548491898904116523978326482506630041894930247129453227915996307242242238911964709936360186668930593590484540400675827133611628869252624715399522964176311233573008010269972385414101704556290192087307820447955017708332258820676564596297889785628591844058420934119769891271644767755269971219045894802758283020919014102929866168831253981220428022363584908468150849302630289727744639094453305006027221679687500 1065615178430989594615586527614267427402801837426371793272046094782224122891730632795929479477208798559872220029772231361417871519449741247370154658499148854011977032525217735296910868651244997216651347115086842803731798827060482353314505354816814707789380693693739256764815618949906955478976317769757378559918221667593145320899914738218931384334071776280091086406300833143032112147016505135160164030634249904253798611786281244697183581904273126006701990800637932140658047009614177513916952238029069084304601467633612817836739700997095354345350694771290854846381737947177492638153486890482575437979457500310343520803927697444798318084955399404051368309096780095871453805505745754144301414185897887520153357550395750860006960876735553388130947940642494754365612214116257993450771283079207128421843864420928366390637681402465823114317278568375491084543951293332288290033031389159581269211303337111547263694514105351819310903343759270747138065555657689749879776244741058431290526161325541573749839017147544861785490866168402135372161865234375000 -33854846976049097702328838731794046461143464328057745996936064133006451475117348107314861728962531803991147282835445455717294780405614869059087327768284590208960138001550058128701539592298360660595485851166659426281699640517026193639825110925826765128149459342680324119134750422978720057369448347099642346325195940669021507081781218619933292535061015846581600022668427218098741974501231774237889444700918434596233925308149062041329151698230824840779540509642394188570760470273452163533812609779394716410563337104844934635612198774027047093234154432584421652373508213525371828174357336515630228682844015221039781487181503205970125117857161853539097494556255102448332373030096888408632045193905211925652204888597152187075876304089715580038471864519341066898429487278933828833317290758710448535023949341471418655862154848393449098360197441684308264835458510455472230147949466874822551160392801272190920505888966881165689309246362556339457554274983056585319726757473398104248821063936106851675349977228747511137640913148061372339725494384765625000 -134050194738255378500315324465312951813607196526222467639008045868509235816439115407902649709948918915003396003757647324597081950718507753812842304247667268108906025215456892222868138599616424439209987087677326986975087132749012494974175765542979750939882021010520072445304264634036467243347516509395665025149764749140636136024568054749117887283059843669728798334692061254145986179828051043771715966618717396825424715176101325515193569423727406980393653243708694397795689775739741905394975931818094641850372692026720110123382260952279893768622878051094126843794616838944224430964033993044130877139687125884979036471767205062716608917908155725060431282443095881640964388472869362865291234029439407890834528230277490292876952941273279019206000421828578451393763594399031607176330387254847481494902084742150522912508693493017358405624879414228536971942428169872056826862062555617345986341360085007313397712923938767849004889728880744027090592274671613692277566068573440120589128638926635680265530965152472042678510888435994274914264678955078125000 5454678124479170176802383656726119635193422927028210939189966983684148716986283784507011379676634181484498965834159912424206964966524076889978992100898195690337715029973354270942202036807328612971110052509423643684173213709187676369302860685441181082978813846994423473686642927009559862678695672901248333493415712974181798941297851030200406786310782848536691167152911477769770157368699668671324606264329509511662632967092318447689805442806060775178370619840859374817028651439959900097037431384872364838383267769467597359483748204494699791827676871569040111336208491555748132896425876237801744617560550929867948328300314370576350996078341837366659328792533781003528371627909821416806939921595102220892360819208020967871373026046778557355370579071096033942877493778837573788959822194391289624754143761129128265794953795250559265703471132869244421777752068939275834441600327003193076967757900368886851674192136353354281417828803174127415264645897968728649545857076929689171746919178205622338029631529138815775048509948419450665824115276336669921875 36367984834184071677358467855322457500744234028462715104525808405579687716490026157425376313825380530584647435747037711007046481237432278787504668218358175764815586585276423364484757088437579952184141809006177876492599035828081439670314156951708495468211192278093351091200555384030485068645631389190311650605068516629110455125089527199876518004994470838362649311298540177911383740593527705362810238697170553532813409260265357040213993222828615571727374208738218538227044476894794062090805638322330826009000565063800705361874633797415704182536835663233457972761685838525909949931066000466356785163156176861561571025341534388539577159222907854178430346530096468813499470758510062552036987547191574600866936159274294253326596375155576006818766915690705957925163675700759298300749695201189012026187550433210981252553993675900286677782383586403028340583442088055083217612128775120864716310359730752037151339600843398929909470975392618796960506264906283188173008445790513754187373244749212793074666738801998047692087823179463157430291175842285156250000 -367872286445407079500264339299011205710042215853470690550061490132250472036280847593476127279822155584093708321711709453012553567911157398829048740826821754247075466971084162367511734938957409985852833498193406671980823424370198541377499068263026466698867793676655009216764073199843953317262636758573622470140688653900370972706110891202319703211470253663697146809741056856178072053971613204180572081520349517994242464086561962649005233635114380542130931544078926271042217208947102994215626766691297606431094845838413729872879969822654607341318390152058181899732358803530077659290423642117600680328005462874954670985037396669692928958127316193350426386945997192500458811878338027328830110320261111982321801678314768699368767699930699258753625681640635791122159839507911899929859355678448953329435024464071333575656601102602468686703297366212045934788126785756547017952156661073317878725653028185202852590309085607283528241306342946133140858830859958806118497460987217902062822421098098114057799022939327813694343483064130850834771990776062011718750 -6329234317963951217754412706492562850509434789790315305303740608205387800346648187070350485891316843961277240518075269789836747286348317898146042568810930702440543854153732658911169501068180310276611962066737741679948264176915311410997041126384365302271584186173074348813724475620904279663385080520369203006986791425988135037022166505011417929619034050752642664634152141939455524749510782031816706445957436560598094663367391521283810671954075677662918726003798393607890396394433935905740788154596918450583675426057876915273055462736666940331521401336695744217316440916944243078422223929128377583218526782180537626145441502425931881036972983126330493839848633614203518123168507902805309277347768332611047449459699460381069340420691548360012531823295707547240794881495883291442292329557184156436340003668732499445361824495890740614927960120535332876727546703744101047039238650734324116043843259384721089636282312760434047437562232573440067155726298427827057397181815857689917690998599579465601759935348665300769432917604717658832669258117675781250000 -18803443157865112655812983713478491999583032666654802389390620428069713283750496369777872386019299510011954400640205370641200980754534978250105212022199984363629222460975318571864682913920570641192903080848506279205943628261844537897056383374681905496697547380462228193079244635127779506009769847760451701816055136639169042696241407126824482133311771136349180888265478547196247260277881468083382287333775576927246472738092805416683439916530112963519696389961813420600113850162670431346284963575807664486321851244403654736085651039519716681143481949350349590352909031218315329917362824108639130008195379822090347734832299923084650515186966928328660468249898761626595124629222446116193973658285500456839273587577746327998654459470448420500099806757052737644812571945953793851061134472179304223424782857508034642210520270339529125407591829961369090454804866232660995262023669703591041896749278519038941281294346082405363741443057841315432638235861803884901173030504424019925614362781363991449783288225382948044214770355608834506710991263389587402343750 446159145835472358182687936341120506611492615256367908954786127015897385953576750527922092572317482052278090699652936677963064522432794413266375536266085817097925448346753078253624125705443657349383207543421060198772356581435957275987366024356122664514928808802159999776159901104933251420362002026646218420102538439605030328907884052572043053793037475708250227239538326368275913449291016112429065005498988135294316695009423379773643423984604373273263394062601186954470825921686004385665606838241046401712843366983165129674944767703494902364552361329631343111500688802287604319447761671977600497473059980528496586781200609378277231475578185577543529956899063094262110253170462333755414943772395059033464077168447979291585327674717304194926076203345340253441829519853569394364975558734381208932105202262778795839570805445362050205049543280995603360919156878413836477426887391281730477442918135688773526583868098779066270895447242136551043137691060691962364279935733227582835953237846308036329263010795229496031899518726504538790322840213775634765625000 5900291322403226741625514368990284762801142782975555256248267936175219493213314159572188578624062443207962377278429579843980479238755097636276967460663036420794563807949306300001752775411794583383944755295912403661532447285174514230266267380234238143404149851688897073314016386548137920935993184286207986306836533984731794841222270538068273821906642465280410341980986438264621780691700356000704147538188675814568531456966546848229188980480660465957362576300207363316757647664673878933685014560548969664035442860622312118656206394743620499025230634617463166384992248162986270803508030604676256171722103895749210049752275931738145118540320500699299865166322630210367031723592314986286998366889094534356424097808006646298736186512115454475011519257350142064561886359128259155852958193845020033436850175195932675643409140509293363742848560908389429039771624764528487350400541898890333379988977172774721581414621390829809197250948781653894865952060157044728223243270736616073329568409020215146150298833688068578630717131439098466216819360852241516113281250 20765009462654120981449674804158847503196696616695756049786406291214357907268348602897015246711891235865647582046512814923728365564700655818206946634945952817703394702597083334402294530054144895387887741464111499236078114604649491891705902682421068324422402936885920578198410105536160408319142069376371111040351749915139134045427683641593180000520398935540199065793579278090622959222772622867098632095094096185131313908601783159501382534394228286747138177992735812106868814077616997670549663745346511793503656687620434040836211218142298200812138206343590038556654495385092362913806928737605852171311866803555534062556169297760115725716460780123552457600810892765685603401362036706520348386946138225117776419434964847028326225014649646739626812433191236752093648670645099248709279073814576691180195818808196701274418825043972608238240989645296234047599213189572056434787080600890113464834192660115825269766293798369551110674539233277267421407689418262574911253794879155960620168553598727095844605738479538947598157516694072910468094050884246826171875000 -239369658081525863488751296077632873890541013629865975830901465326209534097146099636339408110178682776326737773311943406375133412626646651762859049459726483074000271049962607695025504761821499237674447510153633601769564307771186502140245041445054410319188307026859451584066922163417197070586739556597484672099253050884794082204770197609196891485849138216103952496445979605572643555706255801781868440581274919290771095344854851254893051212389929062249558798209845965966981161351437320078107670795076452041845432356126632142745338009261395504569313655386013003962978530309863518327211230876087775156544470746406334996056177904495001108285060848533910075878232726794740568510133588844818805338812535666566209722223777147341419985609363840780342019198870247192428220301604690325305331199901431104048486760350202045519193027018271646823041144871831656500017445383842091624273193248988366903583346572313253373580527386965095946652538800776936802130219701918553942175827758996262819588820233088794285279212969527292873515855742283520157798193395137786865234375 -4037452222455789112267116735538194177672741257762289926625004575980840478126193412367751538723906653215704411413254525039831114426536927017185222004003608630460562476519304303242623783402775382494140317191848958095336698207435434128347854808105641411323612073247840791817323030239227431493208569612973585566618923748086182488438196271737535750494744648690591202867379603208382698447361725227745460855298705487507952466410556464384717443575419061656684592574987619545711182970899295188204543799964912968504826517686846164893987886166609002703127873254159682333705784842238746322769001405164441986834178782942806280242092124717087751044116188545549914297176588982631390746720132539532386539477570558607494701311591885642257196212513830119817402565831982454612228849748706966882761868257442340290437225299914365504152133196106310010123083485266801157615949070527630314643619509486004338191978751266924249777796307354651864303901427296928577720164158905568604731922533018846366314474263463164671127672012507041614942648877217834524344652891159057617187500000 -26173884097352350940866661597281857564368748155446278088990604693653017104894735110467288212436004043410448075646936654545550667248241351275037030172844705278907349471957414194540094794453530967049855956019020443876837395944144727435012708645591686800116088505207869445007190815909760170389326849348182866121168514052435858231824668510710341779592381087112079548603028250656801449248354476917991759563899960115209005597336083109974118004356276612491318247169579808494389543712996547748697146202499809271355482238195294395340928197063192047985924167348928004810301847857749800666622920560244156575106132794297359840714898706559795191870928060383966503112871846545683184240260487911576982172662791494263813316218476705918984283308087613516464795912521804338834504363188866993632502773964695104304439917276674925703536845044525446956569471356290284824223497388143389404358795350869917625748114694959946252655937452484792196957147943614920439940724414237356439849929898541877766749923474863497949057405757197205739550405212412442779168486595153808593750000000 7145825208410760973159598951344721156617557902855371514047016885357033324231356128489887444609874811087494672697067146486832165656204718266061161620316125665944623556442218973811669708144525844112937314944308438336429845690920451968934312591637493805507808569319347939362783939269226796022609430257757046087260024100524696656979871851106833215207187787431863092628316461985038648085757845359458828636966195394618955807433682602066166071205190199907734655184051256823137756648931178271545349131147709945915793593974951490827741274630277198116679453395415565008702735056890845879989634525239372076517708485592232381729827623312632753820077870071864523387145277198232653552062240310386376628162911943796205674689239889451639045623982604725765457826756489515547779655429091780796756980425725690480526507238252333681925687848204420169541998532924957419353312850379211670657694263092999729536560268376640686903540234233191401764154110830148813956510176035352095823549188829337414597329142622759241957228633640583029956738769783441966865211725234985351562500000 2150136923035697408008526548354325203508976580297977013186783620333438756184387569747182457099377031966970685141047994820507576802118363298336883537627848399999183317122886922919103449475475381296276115296376200642986711001072302510158850426848456360673693742639366544885511870189472655430607007872373092224581308972222928204111665518274986715808780100132892548149492549881860979212301532940086364758462490896637184154139011227922144230827383911664434641044543317518003016863109115371627427207172034457793773538431725560217339321457466171042073965806818910799757612164602596039792559145244673446709293263607504179237073828329387348449349281024224644392293829149001773165282393275818336286475137574843165020206813473867594373317504916900493981151807095615280131130539171332284255603849619081359374716473669395393405506601031331419088729405679002316984838902163967294822431500010111165654752123640086517954447650008511211310442634934296929725356636600789633965487124505915841980298486766842711688761003569694428474295966324802975577767938375473022460937500000 27806894692918909927098099338135480295127334261999250701373835042913843241236955790882438731238777329994380036362703580241711404405381126938058606356694348712855449083444656610914538509427100968008274572736279152456550746237545153964300235307330337240130551754000346006603513995698296343841293920952622897072180064992930182615054292373443965613834384868437402672015301043881528387193117447135912389284995001395631517224500245866009914614750118851434726044942393996506379184142335598464147738146105952104489987204911409383737955282089171823575870026231974501089922072420249746560649445145842479208977625093090625695059480747066604034158963402503675677140632402136297501396660017711571505970127798201287033384913385585156334254756068592743396654817018807676325841649543611978540459852836342295413151149574352674395728432506637132381462367195121614451876926013302258388568289577198025600522453445094810206321164552907077520144122111139870417123985087457573460295561146233692710118768880062571579708857908841305799866466808012432920804712921380996704101562500000 214426263111382347088006937205971392314340116846803603764458482145485511380824826515336787165154591206655493274661037414100364400826229294069610263691107813339910938717999521980666915956947199807871351853681648452648686467584808762339596651508631129423166046083557258787200200639338626900316931131460762786085706268454889603115701434147883171897785616920643987138125949097560029358174796184886551988053663129405760262238797703551158696353527223065317743681936429722336170570168539997450077621224568631990680098641240214037875607013186994184899563861647439652204895614413241439039110645594875283789589241377150998252050992413196744355329959347683983814274760402710408593686949022338948770914820075918260642361210026945832877310145507949655973124462668896291912656155278823813688905697597436040092698150622970187117158799649380557196349401475585957069062398790739609924023371463616937435026397403309936320651160348890308395645811822126695424193691037662917161658431753862072538604785776691974483452024007244380015158730090618632857513148337602615356445312500000 925074074704580356180448885649312975695382914689354251782951603182155232832371256390566865662068148301981446851056626401161578944106070136894686003915958223053772935701091095009214581598567899036129561533746691512818576123719827666470138729337639722665960511610945530490089514563827675319590821235381278781175434624830109037214446381418289054008707347096895690656683259262703668827016927264543940834839888657206508417032826856190017358150636856822419003199360432624943576929794853257715906186156403856326131304910152712141322559838045472368201080685315167622069678380976801163751013030474886859170158709939481934936584328759860375365546402593059436675055318853810052349780861809275645153593872393627295887620532352369540500403513544657869306125811657857196437189994296142172415366610461807469160447905491062866260840077794174859601745030900687731341990243458927669409167488786250348873868701333867433313328143055058278426346675082996760411505019578044353112059589723580615562390792678331323865843285710814116980845595028526417991088237613439559936523437500000 -1654034262513237379863470277903989738400083457326994061108187720838968908947000071693904639256054967951981533151925772298576876005284495764633223136288817990647298583758307582537684725636208096942499847393493720677088723214063395541868769281662177934541993561905605453200023459261601256549716954018899244452883622960382993368667081604963479386290027397416886963905771779014125026575471187401462917311457642671273899785170059151360876620179540436667996129311961843617442912854631503984750748210179784904967435118988520319410540805131503000067038342075671926738707598409264639531259715167940511784725931462986342383570943843498705583683732574164597156723517883165709470067610762717114559665151968764633922972977305812475507088656811743067623000881232331159593429923269384540102485807308501185545587097223156853239853504996049244490328829029827924148559215665457042420121429842474696985001922293493548770339200357686775055260630184654460256405981547588871175847711377226098057885071373362636708239947762995595822036799284193708814427736797370016574859619140625000 -69644805741754446451774023650546226966484662671701914770988220091675474844912397395861492368117132252577442108100951352878515503475716213815936566234959377936561470870456952859453641147404153345652484450910450736513835669585185997664636378142751957917989426123473831471119628066849598709219682807298116832382221850551546741563187995605256184944438183393929735170902272475701329645420179113241899239167615195785806068443968294137518982913450023388841815227269999919011457639058815995381614180952884877671604636005512108090432676858008450241979800653823029596630889780125438647567872264522974662059698078805466600744272405431868319799639486367268988261913305647835356214445665905331959735021187842642594089703282617778391918894069687967249475188148626650989730880707731696480806574342419270873386896195676976393907744164259654608136942404749391537464984608871893416370347057538545994629462225852133766716914582422189746116060547710902762136116580164293345529769777342741358079974933738158100073220917050419413497918969674360667454493523109704256057739257812500000 -602639702716540516326941485413273401362177347116334795676321814945393428997248741759846230077956855386804240847755429818867873940538224730825889137307100843419676327004255038658944315538744651971845472693321932579854584468919570118803826403617797783225288951117267546683937195712578872399790429825526306754117918085509774601634356222518095704220150037964585615237467982998077813338467047535678129111866290548363365182294726674066667790210482055066780130271261939701467745001377482311768964645353379451582658237288647017330271447216557634352715734734712768218025211624361201837123495892242520347732282487131761428146022303579553858028168236472847899794173873334095064229420049342572406417133990690366353389801886884922859122142281143925580155861578761433592032894336046498645708503570370525589162004190724881150401873202080548910449056879465795804247950366804545740651938909261797396207180408245942901492137517524506283585821030348206197572981314065957135947598312373391078716445945583398707831133661270394970684651002670872976807459053816273808479309082031250000 -863966269206278696741845728527012097107726014912614816106233991756846187687291571805601272175626385636449142044994213424712841315125864892319172626266107028522944806290871130633596261211786533161640995288761763356956362050701586401409650117711232517332735779790934751523630523788157937015306480725226284313893547903932052432171365131808598288250921843545242638470649043282882556579281725270929865296521705035790239014578451736241061934108764538573156576878495172078931653735551142141516733288583427885005763769871971536648484486775097639540963701297587097950351102934291530859751021453521235543551685352397607012544972126293308549179981278644876714495711832908673152920779432821178870244575974721787029989121738147153372122784479896152426556603536672763816517692234614877870396115769241525041708212140593549514594029375397066945496745860789056839626953494654662570169660324749243339722275587568756785144123640554194798772035133645261293347449868011361989381499115621963701078092599936086698890881598721025219637839175773619260212399240117520093917846679687500000 55465941019337655180933706777247131211652406356044613981897341557692384750078351078948514458661067379789332453089102976859210200980778579939384499498357387838797038024396156668150843541022704166663473343903241033605929399452568405577543279398178516601990489039733926447280093238483046989363131941489163441631943205635459312033896563519472203492275854614335920567355638824204952902996904733334471733226780055004294178163204128565771254551755596164696207702787320465383087600946297074632288763665953599808711468965565353959162935121090551933390498635468587836629599066149630755063013193454099679879820511618836267402129647762578464155367770284641570089281852519066501466325708669168343843981551835360272820420081452315988835675072402828553840824732226715360861216708862748193808392850636335853843375280110034754750532266513059850162149395277361175903020498664633601470073268842372193257152949576138385561157557515020964016654088048322961825259543525037532248591778257739013546589518545343356743947105437888799687390833708863779882847211410989984869956970214843750000 1075652826156736777279065353435831640844178489330750717884995713669593278792555257006077392006517735611724260675168273071382228536094842606869732531672676460838523857525549201637484248384183904495899089488517385919849460665297807761811934463930261495465320962909452362509908512609068221081003698512010473005203305310500573482858108471691418276979078352294099511537483328949720225023837170270766770218746762322816744128660836964011087774170264878939738161001573479612638273044075990473861581047896661160790789050946987855335051659065197496555147455536084707851163457149457565360738463211973054184968977128256877747894677254278991334643117259448806618230480512790289355039304536268538920403443654303179661304428368441866768522427330315451464310908958466501237063534188772499894791796656996934110217470215454001351952648993315652624714397260834142408704327964016272694708126117411650637175245161824362960014194056152922532364438990414056015999147038564716137151526905564896482776085620715854985339648892845773427404130800823928160170339651813264936208724975585937500000 13544138148693301024628651978677683531485426503394574355340694538655839010871823711418871215856369538851105762260020372021222018286676514029187633972575793359640008058140005964012390509646266737627919656915300752311389609539416635615393506315503648254302729597663157399735957360121295364478314183901848940936544728611925197760558885130909964142963171070134461953140363654511117028833526142360231072084261958118733194484025310395978165745871839923535395103082241666484196987264638347485802647572485954612612074636327496315106111000493395206495756593637189022246781562402726399288271117347803433104007525053464037049680547572951996072979295845760546698853470463728596817731626765594231126719292179345993252136723199662328524288015045336646217510583771709594938693822743441629149253206947101957872773945942088861189742800945771204986964598814494985025658329002619611254966772509593375320678832342843331851567033987185183822386074728860043370631081471353809056991424637191282844256555778365986452807084780526750955841216815913122251124889316997723653912544250488281250000 138595132014734425933813381873424814125060636130999094366642893068374642585024741862168202388893884354377645131842261589881401799606069966765862727604211312364331592865420730811864517325923911567462038162955473719349293440133161920632559802963535202835423350970391260549218353514516508181463682620356984545903166366046162035612413271123955062733468428931827224477571952366602215167722336179819436727296287298432867292598450144782660637374088179941699501234155321284396502837373587308605945807409522052510789009292659169174232168223512076499145935498389882971539691696826324452122678227951637524492718335186052561981597483074096077585987831425363552080593783795705881074008930190974635023651309647374282092870081673274980389692619767869020281361930211244222566799250021593255226647396457278599841317074395909001333629186271212597714153434600988699700588003117189900329701052726677464403787826575045016756339513449973417980011419809953498523441473589430262308557932685539251197594265163935749868845452175942955269170136481295813046799025869404431432485580444335937500000 1236741622843955892079262954572186255830204152819152464109995784521172062838822339704315124112808198947261364047077824358032932570743812358997046928433733392415921269822052006797846318698697285150095315150817512737357522022350881179628127637088183212886872270965346089335280104930720062830148350957339517668825457405124355580553247451069660478854205818521543989913808167277144874352926903160540902780904294136917786594275046368264836794186443735677900481836729570110719397398588180057060585408874000239073512481807594121583157658990955541999619687040140701215736641907458791195816252184603391595872568205770366217966252977238583938412731162063140454358168872235149054593248459600418769469306917201453447107753432172232965595218614580716021858812978295943277282757218320589046099352163690723111209833335859784563177973133850401553808207368808929980228792617356560523481807148220505390873718909148050728249810871290038948872776509627277382721156508220329090303939562246354653758485268398678298313558281920978930380652457100766790365486968994446215219795703887939453125000 9945835132380042719901996109432038386128215291592433023167525391689106055462470214190259608146394617297212998583468214330422270951230308919492143819966340837754783643355496456070729173480692293566772136485979432965977885977959874334151903526496527796694906741109353542933405837958119216362635431042696616951739045468647998038542769708233229920140394789006498131812904469303226807503109176994762972389773786215547430418967662300115809587795473059625803995193284072057674113212103068051231750983041600734785829377419660892273971958320129859884333551966616788630264712575288487945133292006618358530782153644464912360785363779690628988871512493870145950750269252675750309853136372313170165509775163169297757841287883944084159602853914682312470588168530373406697157689894189562888137833022644373655547618687567612418643966308694011568920072749286372125920645204281260895417104310971089660563522734968885098352617524133032965055703997925215313466122549267060451002346839338157068839131482913159151814024035409232564590347622994048054634319555589172523468732833862304687500000 73430933184507648814084074787839033628856620786229126441930885707686406880297364411108238853347425831116538170547201074383240332870343231253043485504694895062222861206040404965646069670893681760914267682401102491934636804997941996399324614734128633176104680625763709060543558420839330273449746410168364999412841782151774597788677730324857867202421298710735879183395399021101152873380159058250662123978750909233335871214420629059983451584054234960836683495832330868541454187105293721388089884222021325161219748168725431203597023494933613771722800868238174763092488713205582562172566152887394634121068679429785073431543193910216401122919991937505387183515108610399591645188443259955034133458460672731176429314522530404459186393983600806756826217489540856911084855599318491045725773358437824823134590128503106423887487465183684518042974715819215607897550448967546139946713004661944042079674364263013151817283182076718473792197876260271317263005336355432311791815317052637796700383428870282799440929199713935708208532388733354081405968472040513006504625082015991210937500000 503535311491003543688248091127780580263549969431937376447337238281187366592927159055850203927260448997312546169240318736648521228558093596896177650003537864488850019740922301328552868943057030529557847845052456561190912061028299378911538545477608051950113127942518447322456982404821446377553360464118182157110993468588784914394605668818995795258314139263858239335442774236718960572192672942451842391147933116529118045775173433450577434165207247192186972977130044538805300184267779495519546994616319857016278201534720744078062024732343830380862347792471475877573514703955847854193650813561101482342178651543904281325148507891723745345495136700612815731240725196619147588143313869746255401878446419021027226375661626148083778697058827647025903238758592050074653358979428296944858949685413944631184663629726788503273480023192305514549154044834468392481668507479828737270762743695390644609099238965815196550650190570852588637334432878775295019131532856147189766017710660940656255432724365750032784026880510748659621925807213990971406003538390905305277556180953979492187500000 3232017273050829568744277054818956162175363451010813303759144095314812691618901854455926702432464250201520652335860952058059779155597348338532536927106509888371393704815808621783509320290023560806168360333732963082354021055787110299560144847761977108274344079759680425494396882236125504075366607317212914432465016215071114881852107324329824344917054170301602202161145328187386457333623273222767955696266014104187412437024620170578282384440713730914814263402317156849513380389008666241445166113654025000973763819228742656718929494613740398661418512207747433195102445370915507661759796654652267399954683035786309623763379986567675780650737518167877897223711883979731620940754349880904826491911149276015191627261872524490169690545823831782581570627451907623542143092080858907796821219286039477416482903764051105874149783063300938361209156156991865118096565264301471773448218063892121305887736617388453544411394917208568050993633051456741035022554100628331552367413338831995929358913702683792396764675903594914358362349101605188843311378121825327980332076549530029296875000000 19525051253315296741611691374473592901800320237041279891208132532119338672498761919191771330294076663804999677681268477022825680425836548532253698281344623945300008036160132747467427611380839480712578133222956588241974690273823001786682799381240221637116735460607258686675611365636472453721182169710846365736810156561511220572854711727997198095060795963414518912855034337466799792328866151127699434897655462566758106836750076186855544932362768911587204650829251267618207267251442769517240461016238901015286731458185374463017021910274278311451934617902081268464078895086005254475326822144227178326430056061850465858442328342617993382683311331658870184211565310412809738417524169178032722687263856492540752238136713302089619630655256239337067053546183004965659423505885994520466315078796807302869222461058344481651424845843414875182830612852472290426583875764812146286156146034881681619697900426481084697745041208707748045733251333153874373322151453131919009415479867196981279795352599747448164488151397977981837790713072059215187764591448171813681256026029586791992187500000 111463118552704353487327481848301121618975515671644764122551187372491485517338983018446129614017199614363806937247347272826711216594351542412445872499577733471994446184226876062966323809628301856346184229711275838410536956539390957238905303033886465117038393468032949113425119297568236788722934603825608380680361312503781809497528497408276576462791187322357499040119080845927005653212319109290786109368005891941938926090889677853298073024934134107612529867408357162847522294217788174631672555378955633394638321239719816727146667293264914153156716416052010056710856200906828539368208739756522919419732045091167523053235003286036977197432287737382186574322451328458812409499324886199537662358261523595138457359200139359677298804497886249679553614582232059891340548693518727613661078585092889148960210357735727164845053806069396994518809772942651972959043770816503978850859379016118969527720211196715415266859379342740659853563199359238729072149149195013376829932475603005119630391227382972568026523404930224048107926689649501859544211690433712647063657641410827636718750000000 603134925118965281508865987083671852358347226975857390275998515438388459611413083223945570242351276853621965923337627067520035934106884982540763131396707201175790568316225198850528040913466653506188221401521875612170001455932236536661707304691483248087203692161063384250528935662314137072911118652053385605576491533682008489228291890971421229653118783413864726714163895376967753166442802833434313204038546940838512356456490214468906441389521608743508459864263781367126951055735796898789177988824849269838290138365720076215944521551272589263011684647936208522258406967271023363365707971509392685513602464533035563063005365191031266057713306146612021097341699348005222997364713976017919141898514366094834722669503591361173170658900579472532868962599521211317688722116754989598732623692561852189048340696070783246696238608531462005713755883171282083105350656502044295385307586116353801136325185472044848589914060060681748982226116674455965687672195304880418573413789792564422456955725719559750761997906006638037394381922193992205758622526801104868354741483926773071289062500000 3100827376327541246571418141683005247607878004259444900075588111348896738342271796395567671389934948708245575526181984555335251493377718747747352545670846298180202953424581780592828873287615051254195927066001902342144776878013331978786841648327740108918531051047173804647221081013929098006127579321151360075575445319542107261038765255575553091346705015839360670322478428860413054006263076889498840538775371568444057122441697873875333487479590871540113057068342612894539792054136315245320277920224849354028708253681200207497635489686816494675959250301030025136040263073507750600645869462932552933975053066823416648747629826851391736891363132823287291785428514871233724052822023979826416293999577134966861519535575615713444328284062761793788719874810467011666903645443028649072794854773694877251796592027311367045948278498561581437091211058052732863759017031683619813638689777099838122022796491782708574696750348613184382661474517372582740661761395020209493074286850605231095022094589194672916897136769423044271199650743618570167292082528920360573465586639940738677978515625000 15175889123250611364350049185565082901443422766114028273163496539675182199049435479434232416320402341652511034721541216537831824124926957747012349236528640495329330606827126562229480532710985774243384272799575840056287014168765557163828497618235101091856945159648503022111427573177717694654700054896530828062392157211702729619638082903533368673793407092809036598341463913259312057606163289112592626673417485450579335150056650017735349254948465590196922198908685583121790257897061069548469498764741500165785081812848328404209307517138570464477849148337373470348950634315271461117467080371463932514101948729524928022802681719683026581523589735374250765201395957936452167171604465545375548628569952297917696656977686603503162351235059592885637349170087847679537414289675663035695729623675259777003312927946809431909035336549339311280766401914714726555726725008646816202569585816506796065494835037308140783210617159953261709930433331884977694665092791437441532947703752373933542457592270129160954057583658069829698184586411718466488710715944776552532857749611139297485351562500000 70816212255762997517167294753058804637364121155443668078513961351861023862080359511076313325652200540521094339825613126662824453989584211012366359471529364974655915780413132024419275187366396475290645821527119236627005995902485802624899522498030845644133926786569240223221257290405726414464478910732765022283859559987922234571676731236939920611737035157104252316187425056964886874700915902153137021239306768729895036360588832810609190127513996932218462269004262580791646942230379417774127158564828702731892540868891954010288093941974870691702715425435864438501218898495071844490797692542308775301793091991913623988733263535819735631562439376309389915724054871277790504657600364795692992477486819212179251815007073046700803651652370110981156840033241851338261077019410534088070613468558372005942612152685715226679855674462205913530869315730168430279832438362095716978686694383786906192807320182850235791952890921119924452792590315177279188343084484313438846696487313005830066327907182205418510300591092416585707520637415890949888401181833152975286793662235140800476074218750000 315496622386442092839535864922395125320642450158137472924548965810387670911591888178201468224611707735293618587409251415650682632095536461596348503111679371029027968757501781978428457199412223817261552548593187481070462712240968279145599837953626123251885245572230326586377758145386573724710642809835388307910783654675367700568295180984958501001519012608757792627631995001268018901246367974576575289217607243184853339310993493851765973028305431188250673328502510261726891798026270033004256888030442701975174381224097229966252722726337922878351694656048191630267464060195565736122673762048081980232990747090322411917346064026599455121901071482707868668213278775562964233263318108909709111145862151795452120542751383836949710523846591195563321624756560788689596328633601672842989284256099831200753156559427244492350016266614457793522745056157173291313511651665359538896167785035628946789336367750657218597544879970980368051269505843150929310799943482052899075543445429322826567989295435294149095147166522260488119359694234752145090405067717753695433202665299177169799804687500000 1343508131377032453065491967882509094934785539351786953073183348422073665243047891442554283783421520374105346902054470904778706834831892099540355625936195775465539645212846058126430246443331794844997759692918630970313542361346222530532416754978142699424014729031845993842643822577964052471289223119450895612028357953142502340995878366207080185646487655105864885323579526460872519232484290564983508974856863335913480782747533637217003922978282408686022937759991741933010435381966968762647796765361715161127597867532302691572091303080252269092171410947401497485307010834504261321361614041555679245979104820272177339264143664086389364802676218282344645003014022315176511538200385513060021388877706600086866563936690881045947010738870960228876682243130312991371930294780222123837719021256128061208689470486142346056187974114739009622908083543962943990801560702022809397095450002810866266752573185659662247874252490961932836617913591147619492925872210498870361517659274334481833679550232729955196295630989001334584979710202423331203287456062089866293263185070827603340148925781250000 5474011781283514381868357745359629296793463200749457844898427069485242717773589586092362406040116547257338912880051942736205243862989463867738808164926945149367673562742617657864717436128886936802415209443556166212326376554296299477895531243801329994129854574848597545216055694986488176842158300596338656237381781468000487831659211118085569544271374660665955915046672105374510796320964070125774096354668976775158442371683448909781665876238584819311401097739683764421642675536853559368291844342711569791155122601053753345968632850020980443057712908849423301853479829655091540656882509537777359560705400932325624246555870974335005334284853145791032309225820493739862112212920482330704912248131413114071903662583172491190354483075088665443870162305251968310350501626777012767086892801132070951340082842134527633088796276160752928709005285467534212387658128980643445932793002790597173158434399094186106735802549062280481266780309635691170558736617238538545909184981582045489208191818160123020468642534713875845544402223053511021272756007644000320055965858045965433120727539062500000 21358742500433686931693857492680130482050265568813245646418736330605351050116686589512728369266512654593302494689370623720842067001734809933269804942632350263935992182823518301583153603729118900622238511732384334696487405171785527987986982127079811120734663145503038357917293496333952114996843037735117502968920603467021049041714953067752557998190103357834733604456661768606531105249881910829816264546586881022833751024880268979273922246521248085798407783217213604526190138079952764520779779444402816246107954483990125380797043811923381279076835859814598314604505220755025760086699756379674597819259066291264917137225507504069581451794846265517744851613260643195903544241502088420006767802491685693231298131623855763479200243696550666611965344901535965031834261819058866794963403473859197718686281065399834118030352446269484555084428304611960409387212912440244694016120137816914076725596075532798858479573063692604714256147076330670697439412716597901211955876699408017339867701762048710753099156102332523922164769693192279234723141923338318726166562555590644478797912597656250000 79871517394656110600177605243341025497278511478002991470273469942383305754735235992591537815569406465042736541511490470136871013492829198348012900307588851002466260248154730436601403210303934070035901830086818703551676503661965991794126162184571737090803186612556057422899521643325902095614497509045005592528649599268366578661893483055434644013560413006818063104294259769077661207309516491300995951473531246062000149449398074057016159774183922464466730114946765100917313584027104788322911837590195866540429941053989795815530575883402775231965146266562127962440080984490798391078491360832574707698640233770758505418682832499492365980565445380932144853326011851942840781842079525290187602728833355918292950857862596075766121899404310014634798950938999057565892580693445158553344456591079993685463805184126856156823527436451870920816568121935937632623323012712000858846307705479174615868106588658056125552741873803890470576936753487325348622692587878173151832741340871812664693767260885941192116285962235354531316060242404781528427145948639820360881458327639847993850708007812500000 286457208019524495434268235468331300469640344443442090765726997233084243633670282741540248566735759505843725085479212312825295508302983569159780129139467152445276988273295259927468157977317226972022677240226554021237503813852699884494390749664647164946304611413513231101308231489564348242566883185147409017672275143250828902074206660898940720664110719162055166430677465201551568946962060509094679580798018126449205588347164499066145674105576542956022285906332734703645912816968301135828990162230530193526658907709661358278035832037438501409368831801874915391225230311316848085997531021936355507467791232222442853262736687193433026445041401352442681792281172253338616235436097849210291680776161335814382691742141181112388824180428491974434780716463294123178763959181691145109092411521057005163748477440882494778575522548287560182491270737108328707764850247541717314211665084437280824291642727328137647561947496301560400512879551365433211556459317400831826433142035127488312968551205092147894191309852076918742878845428303725128859038499655464971027640785905532538890838623046875000 985945166076906871722724830370825598514951789313461105881616716664243183570613804373786537751328057030256099389235967227857904514650428583063217404214971598470774035148335416253164828086400272440822628651505674663574516319835757159176685779651141502832950947933824408818945777352994160290439169584802243851437557003393776530519629571117957371887927603921632972730534841006483914332412534165779309528483520234749646291474450319209802778406094619001087487929768032444503774648128196942790657009795983890224415922995154633478716920115128789552690417987921785642274289681366293008604909910411005556668412104202989428019369181033430884376302118896444587048671948368202728559199032199464844633736904658382518512987686783168520998176601954605843926530596200856559460053061642698877210102759060440726266583271583135319043337529977902462027264866287666298548675388555814920600803131959770952604489172258612747144443051880131477055954801019820578507462828352968683537424244039508738143960271561264986839638219620739146224271496974137917505235251952599995206583116669207811355590820312500000 3258493419514085499143496356231696193325134465412212958750545484993756242786927917104761841937701947194621413581569867165712373574248363092545866146555251684834772199114505292111737452442633605031872809105901310366175166905614230409460836877185868651713462244340772745969433527862598294680080180360517800002500614742090473938640616470701070076400030760596363151863244489031864781564463182216473866909800735905060599859791666907947113478200007190861273293411566514930012999874731849873580603090474008638253626337087452690930791898912492884688543993218561504098801577808226738629213585205828852878170386942864058533295815895487624019325876437150906185142888271591995239961258209168929393263265896887038224752973570126009591992014915476031564347156967452399593843476455345868521325553763189166219757854874054194818999399769377037943221325391130916353713638339751861860469039420503999142556850859594629668153783312715146951403884714008226076196114526389329489800935182260231704663182980070684352324081988352575200985275237751099887235852088640530865859545883722603321075439453125000000 10346023175727345519860749736830404047331396231976868748643679194505604646603267011916147708883928733393165256077522801555365095882184181762175093459590961511853154266582942146605640624839255254059652603398894468196444077611962756329943810296977227467607687109432810408008737670831986639891046036832107908702475783287045064324612248399223091209832057076006330914485997164883497602396830862959552797400307828979875589225264881264375432790524270895368695828207947253923652176620375270794566984804845964287690844792335297472860179189176146472364973594928310666172379059325883504250912285717834749354580875363439037128026811353721079932146583170340780651554033029998630658001182467755895479000675009580178692066645818043156005330894994561448997194830592921715888672719339252206466165382090307263137246722802272752405059731766596250841755585368266773753922926724793064860362895335283085987562723088945984383086148466327259383571971280608128002465073732526160947076110545093434125824783819850223571519087097035946425279091674967364280873750263106680691294059215579181909561157226562500000 31573476126450227004514775229177665229892475091331040341219640498456586635893637706486391182380331839524951527648211221623349999707585031804201581880419507098701295623919784748538344119307065755185263945032384536364497322954387738999808565641123964603222434739747230057291761025521866247493403038809300304145299420819802085150431981646667691426253631705684587830243535021715156163635681510451608278567821900699757900437960968125473116475476641549599123899343779571130056641825517454377803206859595505259776352550916287740735206096824835181360097682086121898765196819800428811501489893457604476230984231391520238213349508981577860372443637152348903712908701316667053282980712436824722892796448979635588068147050037322655694156443359386693313131637176388684128904768802554976409886629132155210388463344384860552905706501142793519243352081107196808048690945961414985579164736880722439671705164568639213641657497080075181207635171502351189729846594419674169803818075038402591510138256773163765652480167935517142634991159561903149645410748044133120160381622554268687963485717773437500000 92649809249244649491014290115784292360066234958418342222848994823964038632955210906952616951612935401996193377542839277068496076436999019088576321184852176307236031383496163841983869337090633223159322428344993246347441505452888992704798166773134920585402140047168591359765217286757051190074408042426313555492567054976307491356224491346303825511778668487446678487079999998324196960121167379941254279645670040448896181293783869817924841722877038809268409132558320545661602722236892493626689672451753650368701164254308887112856069774381900900819854136697927404477871712513773024858707261656832440288236577501107441387968591142448174377215191229140510422243069359485426322417661801415963638872349626297488730453758351613211790140452931839816193894287308135819777963585407451833374628755971187374285883604659607195590214728692634922922595534270994066799427462549180145357533756485543742938226135860842137043607009162514207773916715997281791974631326518496768467782500748942027117762949582732458797672310294603417883235996443300354255958944330734405880889426043722778558731079101562500000 261519454542116828772744658737421439102623680067752747359366557409552214388015265491063208194672492090985177031917897224734180108258513371295079185076776686254625722246174077206515308015311837913272371641076943368985581434622011535980006184014265511893517309137030344109915477292570178325706660576012767716848521867582418862828189415417565693258375328073609678957383051139744739215295871883434184190875464943162066582449898625336943226275189888530723478700045405464814365027009253834263468242967570043172014596699094798942465234061961426336095001474175216889624471934864619294207214744415011130638308577469529218020949989412052201558264394511666586473104698925429300775944623419656836573636970012506793826740719255943498325242853460196152470086643933235337296772204243203430249113141371378448089265737308483954174983820595170549702592748099023474796027315743296939059455828997504537346391271939209417793528059681163167338756474613313863526494717196390013940042946102521217910310931932540186278952049960349298937057094798293734933549131282254363028982879768591374158859252929687500000 710314121512791001323330776187706007213339585691810619481387016033804049766077793443493818040556579092973254396607718284434838351772282646619561549580821037988235126021053819914893575773351897632013403852148470557240597972027568911798367838946617807643611660568940412371716306724538902481873436439150158499328820459273324687788002674822599885574569606887994391801387742907946105053779127804222246823155714237518274598556301308703716460164888939574915558608620161362946524636896581922935423402783264416742894272473148645491722618600029060040863162185856027238168164205773799965137102129745973244070286730795154575299529197871459754581968496316993328321966695894551988160512544258508728491617489151997572081569536006945045915857621480761311446797865205276324951351590466692326596959553114545975264245169556648437599809443402638013432348951519368927871141532029585883064560103342391233863183105945547711729775173737352325851811032055848685158959642565641355440624369155746298396392153956541413916716345362115663981676836240845497136686800734167723803125227277632802724838256835937500000 1857038215527163984735515454950577100313295180194754511596531140035054156987955898751421867429380974176248956901800976591103397775170022808518947844330746978087509593358125085557676198686972358012020762701601262037157448416526372510726091645397107912621520729636890659369595930687682206713833545223553999515260104791871110090115341175098730001304002676082753067790675738035197956028367135661389596054820297073181723156801334121564003140206783159738428345344576862182101605599799189730315981656198841027766360301451883971832070276911318743274816427640745701584886873559464904414831168230495992961324389975249246560281738695527638421681669492644282840931247609336792339420709953736480350306157586094311734403177412361619234084376768657330409741253961926193946647735326901696727620120248912697127198925019309801019036364789350537303136607255147078607024425154231212965533191808450836791292220226044161739653295332127624221341816782226558096057753231969109694621999005284146767026112526990436879630690150933522958652546043251371913655870602018974763192105115194863174110651016235351562500 4674562837893036949734289508117259901340207279501269212552539211650556418076657002854077824075628766294889454571080570855273291975301864784031033017573275757105308363274115824691029218697958883646968842581800082861041237602083714221037977609813346348508323461538664290096028363749560406028886714600848321693907305609003436756322368236569579432282384775782430938844570726359672785843862621186985979371915095037256313049955447841980489594392165099060917964084731254140889925606040011485106645670299208017459043419505722534397526045706498703019056541963704316432799763281463648715999845918119709923525936043373870725880460281732098498647961168484643722907831265530395863255870342553721506621952909368290612587126263853291713335542341951747106850515250777891253289044438597891138056278396120004666065167545110628859894258773315067494937774277397915420964382634219040953729173851780378240055831170118610906706290236999809594760838977682299008685978215535355014272567774107520141950615397084824466257147906566821380244380171672985869058686292376592064101714640855789184570312500000000000000 11332523589971883944983604375628568374413017379142986888178372463175612651467851303022266435425996200121968393021107702468269588813558605379458883698017927313710285034140072681229813000535434510745634170356679268293002841727703044686292990605491299038075471494061751079470386995693575116102612221689149381602315211775921140493018278686177437788285886538066364963363367907630121515179636784284418872075530615123019664172926577964963189811817016023935512081518400568595523123684283099288597030878624236805217875716662273593193275675111080391567376648201266207017798910480179935517727976867533894432077265080193503539359715331170098965606423916610467442392468746820114189492947555300329087085032103908220270887772262861134356801258859789645803046084022834110635342815843818150692027945742900625037756685837863209381137533523843481390504435006825849043385074805700853561127335347234276876083139739928476694664430667518683256065900543806493476043167585549780179784425162157014877315675696950419770988382922154485721909016920855495946379271778969681505611077909634332172572612762451171875000 26465716123225456921376110553689001844618305469134901402872146845879277857548465867242092451304018251230806939616215600730015138128871219221963920425497615592961615038390417371050621851388718475353769746499375217367678607949169612536815542050761292196835701161620522669732942220445323099628749277797100874380339528013226587425596304131041881534062137170099994348690135192507021529656255311665830511895152922416335064001894751266498424778688672251374273736862748526142290277826969456943176381437655252450851971439814556325832026381616869087653510637381357887476685903590964792644380864809831772563442819393115819060888178062354286414120138046689276429259798717086267780303713643235132021327562613250672418835408678178366103575361463051695920965684264878526861644974834789305682335925845430696929575656999916764935535057977951676565685686432898879306844701747593803085969229846071429554743469208830898090109199851280787113458292886163975442804976485078336533057934182797249476778022769869821348948710201234552236064376191582842098839461618571544665456940492731519043445587158203125000000 59553545914414946451866760697392202013172045515096923797886386833159421826486002331300775998997528462581543075855599612850799421366188891694320416133578161826987991143412845250067571355997913843777764355876042330875159289140208431229469480455316786883180560767202879685829253740344437367198665320570826981150880883845577347479980799689403933992430261358755243044003737972976198347495277830057463708861009994422535241938042509589851381256673698513256654677131275278059241954475029601553439241382162124824487054350267923915030236582316183416252572974716065646639900204189346638152209052561822470625772109788234294665009275964270285991749264290322246413638137767416214469596576015229509380575404155170609280415831235867435871240905924749454065014842493383577212290043254984556358134618335357428308464279441031252543922232123158000389683208666192171692001141283373897007344237380204425706769188575324407474430633599512774265500277989678123334144732468259408931110331808740006160112236198666373955814279445308899805214859634705394443517690279753067084111961548842373304069042205810546875000 129146302289924201055948002869800079972547854739950571000482366959462902095058036445038078787581834141045785552915886903301341675916723119321008463916950558741328666339309841307432468578939053464251129475151529391205542854699318245147432188318849391248986804334817998826000731144500300057997204496522827389291026309101786589838046406312994766877717927152088783216171493366956454710213325121811831075789406041438701414619933967609846334392501645803464462000326755610044109870866356791041213603170389057140429875867337692110949631366315459790675606991045007503327261537535692258378494707119490443934099070169971181391515593027208086680276594969005492719347717972968553464990705336061355275488193193284804572564995647746874037748509374299204153461648180924210207688973775998066470184617758199132752208343158926637913014732581564458554919585332449540493986138004445900503996392031811952278637227907309373048865031328452906670718213086280971326828911125254108417509510991403740392618725732819499883256856759039925412957306959323376944029087719147813606568320210499223321676254272460937500000 269944570586589876241013676845641559761338898277530788526785024289915491859578638326885829142503813256377308538194123565844279324877277695038431605489974336413911292081059152977828789268772578243016807859863097619273350475931758242272322325238117336236670633778887509739137872110271079672060643711678548084271562272990865796385654856187581774647445465678772133371202844456068735014129183798670432427887106125031945506847599314838200261005113090864037693118395446890983467286817023851612222506965663470506412346589738827932498456304766581786191355091084106354033908584092700857929907684387450069592078189870796232591847900322060896290079799055908294491765356076171860696600683645797117010402031086104541922204381510121860100301761594996469131776111214930025217148102464659420255753748896186308838645855586182407330348777663945152015220120748001626087190125402302720923910357202683955845449075583707765327653083965201181045134751712479380203012511042891792805246178026516448859689597365935990619458135702489836404974136082164022369462617355665400020736655051223351620137691497802734375000 543916765943432683211441614399136899956765976901715963127928253187001578584670865778355275441907317865905344430111903525153333081197579556604771132589324237524667045666718370057554170382356648081039881020617748127849445155630137032720188720388451413142422614794849817407678741667841861044311441336484417234508725481346548488978659587102269980734018543761096687697494506570144715508911968411959317104498266954658221012807363731623338200256012452169517839325192607206900081887779203615150066628711381994148264385837401426061631143669157440287673508887587278720298638754355136857604179116756863733345500762862439230770550509666656264122299265125249354738050432364576089180762967054892404611193634125324997906714795265024283998283807072796712358088847344601023588239072242994027161921410855925945371526556441417979273339362171487514067228239112317348260194526001467753727776376595958158207542973847380752269647748986043752202430833259127305105814519921185347897710890812661511851968653344532181763187642881494644284941457663134746331022566906681497966857818937569390982389450073242187500000 1056509821446547160008563468406875257856208684307906180125047320281363089073975922817554865589814572132459428975602779263831961756896595857122762793028244685613621904274283536861800096704905197092621718184905373200494166049376850016235825309306216459624602531690409549051200382297928081815191119683555697214009899923116691130156351144566613392648364947379403231310969796269585601767065426492945013849435218917605928185911930033349851359392415365244670631525261913624978514698630586539762776217114462549161550985579894781129371555639617706438287327867108248524267456886146068577531710961067963147077322346661443701657973547145870428026949300738824934089766167910695354900947007924707615423304884250771354626373037805555526527918404427427359539912089085763919648020487824796016073336741836936872817479376263092608752770945409815108575258452941081441033027912282021898363561779920312655176657558187203124122731793648951085881875821370867576559479963873989609149823340668072308282553842490290817668670146493819592817263579439423095985296409658217835908500248365271545480936765670776367187500 1978224679088473764030389783047313082850110910032196124377646417120087176862346007903912593458450024856325727803826221407446673125053057492275381328712503002592574871277120203793322883601761245611845253408058037467599595782805321167603399676731104318641151264576327217724629332160609318472390769826671366626685848588902598203217059737560434124663366814639567621427125470384139344381147845420313445326759816271403345047218833913084254438661525390720340063429853309768425313410350237522155064826044491855401650919253197723922220278780494910333158468225897999237989722849600184551917707687279878841840372637534494183180368958856063680704481469795559303315542054705310234858740431213670460472169055128113539010552061300057143708570763569770786996694375875011328046611910054021376859065488919229926397704680064460572414727246834754610922211742245293145862497026772722253181144291350813911113132403976895553946891044709844087329919174906918873814522337770060219385585165384739558852970941658175515150477786960876636020107707253782320932826717494075474679249282417003996670246124267578125000000 3569935631407154014159877514286285518448952876167118526304458541570093348421910815316276152077062750308588408362603356595148771883824381849697089148357562019108659763172434746890359040119898140900225951804502437125298007678290825424791385155976487948959453396891707887106569167121361974812310667661295624064020664910727454118165980301062061968784280514601516743144263726675452437359534538680339732714550765224427465236828877149559888339555918749512092784424958765413145101273270629085467270494736108421156158281630747825768606597184836196881289644904185052195205664223563680651293158954959082078410102642525145266858271241118054991103576255447280576043899554533501544860037327216997158767019671680059881974982289423185517542271639085657373744272148354465924436443187653904211718663434946579890606529181480941057797098984695969485551485616469607398969307251178717773251746945597753501630300436737284273268570089176688624682830593134662108037354046635894790131366392576491118114325401171278559906539158471902536282592671685705423883800371700602410696134825229819398373365402221679687500000 6206857501061582218461375196516690134533060487736474596231407082229649931824347583691368269076710207933786065714471851933817325316392142850901737871377533844416846066200003057758298744927275441126822316885453148250102509672628171172553302753652040377401170466918978030860527670654560497125938267797888146593390392191317165633475124042736391988744595950093470949192648228954675966020800139840000387259755292248812685527869804412030745321401815916912464818130901926811662279169539683489675780319041911125766981325262712765601588440948849138355763962590469451504292594819219411822111715655317571388148364269204921956117849239374102081064388262963293692441894499939487945471084931615784032930068411603197368598766629794255237649937897726455902185415420264680888514109004177695422784266334346372780869507667025817039132017152663970603395928567383767266700600698265036727978530710477599685002311390603935694054002188086087188655721108227534188422645836055850570956859036705655638499341214826266516333282483071533485964656826331752081352210965786361795970549337653210386633872985839843750000000 10390714663870707262411449231064243968856569267957557386646525915834982860909135301113817580480778392995907042025551682552506307255849678199837839963321089452341067060627511599227859010342567490887940478448043775167316488527502636517576254468681162259098007082587150787321460943019045342094641035387997642015808947981464451606798932832636129068349064177766160498765497653011015148656658283327021653910843796952713038146200068291209671785960504245549319174483896325623761897425872581373375602297016099663071526295303457057615322104456847012617720639323745864564760437091391844767706665391735695040584921018448093201143871767166877561112996091079075020694250654462706148499718005057480704172947804331598647716437328600979872025572825089617152062432369334993900660869844737618196923365807880228903616767272931782763372339691748357601215295371966309688200986523881438526770584419692556712588236976970647356607201118983566324070766098154059126558426784354035749942657147697100169321744968777444411799549299954567269721960239783408080970025968151797604588360002253466518595814704895019531250000 16732653221699693723089921980247258263566996154006581864845926484027777813427934103834371038476386911361725650954608713634643668909112270694707832970385685558910054803859737513851959070131477944940021047927460552701750007718053074533255894504326714220306307767600833204832806297486677969284346977521370277233229800901185014368374539184008259165460188938950185701396245747468753427711308093965820955544372053959969242988836572587094937869551461264663972032220634946249752401215732020044539764072824667287793641508865658215788862946437027818681455278770786556854326707189552175362924887469275193943092948448672577740681288226124715060202521838415252336069366891114091003103774484131364053644913713396078364670067218448869328191224851709138599828831666769711734965320158776553815267841146110603143778794954475621000536132255426946959211307337362692570582216711028244117252261352977968454616667505784979971280478611623707602490147851495749177514415831344367809049242974731063234300063912571096709838506903338849210853634093160404130717639880482350278612102556508034467697143554687500000000000 25881876570271257230989716198086457804200159157739144444411248581206528229895121287390321137591025219106401531517138191768451523321987234711564787621494232770798802618029200214611776198765015110932678988969074767632507914816917006674395661749319237302063804618297085236131614082852997564111216051414787867179423803496995222482523336778199637294064282513269893331160813458531996903470835689893967721915701253718760814997975993662901046264030088763376162334051599819567687676502384129594946804729195839965228494764728477729911840065040358227611576481183253410641858451312943788974920776872021642072357412392625665188862147904907890023744447612461565144022924469269417544744545781523903924214957908662503541604837846868295750208266381444501119883276508449000643134891144805961796723337849252652540953033808421598115379998855134843381117881379408208153561721073580533445780440359659300927191383307720393466289574344472075330407232398259030525235786186019404463159916844338058148215138901196035304365862198173569494792902255013188964230098691417843864703840495167241897433996200561523437500000 38369243332240561100083942193099846177778436333899891651330377499319498746708930873884990464473953178558406485131762421917228912574540254823404531360198729450664800048202535723906646702376589736343458692720216947584261110564736598529730859977573278501838890213578862958498548817071889291861522853378370732510097810918539613285557012581696532273293758133246520314672381855289771240863842969972523105433703308629019174972867612593268483220104947396836915979877094342780869529047881824970518405002866601654683703885548554232537587871610877788916598977196814945452916302804663803480385075633822712635576233354525981893338544711571204159403250330593572704252790979287278730349348047507968999036755282645318007516230381171250464283406117187083180169911186203413095812120082050181545247106415983852885294314278591332861526538462789365856573591479277663570915389614103899493095012915533331319810709420723868318661598996742999483153558039415019167073630686641680858933759781065095833731075019754227156306273628980832774506363828881811049103823588733198912681388037526630796492099761962890625000000 54334961306421403069929759093164145462096334680681128987263744461774082705119690367604389742316694494399769638054550050830061882902498248328151796706320192061806444981686041187235519070280630084392201741284567218356496710621709173532867046901556529941750175394698267698486996250616964603070259386008521718865647073720450765778264816227156246602766175929174480110248997905079037762075776648339787668191260814072676547099857398435285687115602388667218173634383760423833550626088819815626892192774623182215410019677797034518479402693100965727129273018554567028535749257129927353209607207247799394637148262397024998228779999654768310508074082319460318240072864258857199303640378511502469713158138432281285416164452000957391271008394789967490830528553705555775464441887536830024533381372694140898763820286097517752232412608142154735701607214096087677336679197580103211783951137153607281285597305930157360237987995580606692195662825302227645363662138495035735448540686078383792985688223338597847687458930919107632466511734829582346577764157010622953890982556046651552605908364057540893554687500 73119791851991172305543623849698282817338380021238024031093412168176154501653912396264326436983121254121245408006488753921348027946959301873809097942611681114003537746054918610124504189686695576301253656700708538861017084438176954798103040739232788396852756703999466553001565047278819372001962018371176357327896780049532381607720221552192801156487788767310260055930832828782591988953534198241194900950389209625381749655433343701332070463137490096840792896494418203236632873967896566217291195525854590996762737312789269780532851475117797482742598257316546752662991243714774008405399649645789377786175266258351983614914216359820175961292530717093725715735350731795038913414920836105531745257944628601222163329302349477783056294660498468843460367271371297030370366211478333266084500336916889941823206880974394066426790180683339400284873882199707003030994241499881891319091885789169799836570403532318423359855182927917686254415031581876316991000207696065772818231690431889712541596322923908839169914761451088941065005731915052272030484689428438734720705483027813897933810949325561523437500000 92724763068636591147874737881284977724468531335393166678886995037763075858513949149139419665385944267134899617172432679609793117990638216906805622593398450848983488709806555416772875271058808725362717665473765038809040553099358775991147580915273889463082046952019082454669622784116634751332142717690156978926851985260326404265880414974838717964452980583586452855617975541557641479674399508136567743917407483290897470474844879058297251306150876051052143985815852459996653937204500372562567725146938675138945299724495464025437744656734354106466168791469659922414855320385949986598065768037288798926990906338723399314741916509995758502667264261045152657014348414721437831311361410032720277131155980563328413536396552373660923477226486830406360066854208443808633739480610417102875695671225636695697892357199737786302466390359882508177721494999576144390852076394806183982295362444968365968331828384167599739067445630244828467200560534545160815615896134499934053095474070205173378843155365067183122407533051069195404799268257811718795971249057824505220015698370161771890707314014434814453125000 109188208926350878801486857490556609443112876942485408096027342441998448649103869267003903666231183837454283531037322137069040550493735956286749889153132934343489546023362597225971990480586522154521659081670525551895578607440351167517240156345279915711630696962663812168657060858079705362561432215637839402609556241408826669002896703834964004361153931195706163467117558501980735305812291678918857976729938761658306127834555824532354734823501620062691139027113088858870349949807951639656593145815541800165980368167411122998520526795206088428865127634704322437894772322562914178177200744668206302771174671861382561715056517045671424218897129276470966907169452878065243247202065043253338142555297737187631468351558067693977397311559170790686201529775231757566628736256190915552076041256769614353914136456670376288706627877693574487840193906088280367310931872869355777967156784881560681735505794926531392593393288520296975867887385467585206539256853487223333306234769794850528049968462585620788243597283927709520679170128391541803737503821146632727173697574585276015568524599075317382812500000 115989464514104645151760257405298586735260241396951470152422289748732284083584703015119358549557869782660655970585711177517213927800834594655128219997646958499192646674291505648565816770024659695783371476385091324716525805468753168629163032055689872783118575340648263849649850326000843276764443280889852676834867239673228360605668493696773827966627324349632912453582227247464426615939186236158734910538031006034797250035133855526669011558807339276463000637740826989613157392674308980401840945315788507848611900731916255146891568177514628773234774390256327932531415382680572046718778704165015861144843926615016905927943134012329108194344941398150291691118974513520139584456373444671515514371314513540651180431220335334928432631442167483316669340783571160899055168594125508220054364671140799712336363318433208474852861173841043206049469500944115516136301415841563589703464347117525711859873611270865940977529992425419975018959879614205156777620444024278964470269616724756451606921645824148611098384557342572826807197223123912721451568665793693401096231543334624802810139954090118408203125000 103658976669105860252528045077109806943443545821774831221757048020091008813227993490889641235572199889116170141982744987559476776560269679036114670113468765139759299409142541895761858081099044207069073988349137733028209125440707338143564458115389901451409814742835163292415898296262315728348729648438843621116975502585710897019987805584061641813928800449281924698271162871668974583212904480137505662288657513032215355485464749017190554224474553986921582070855373690111114502635540401646591574240085960319918234010270352454149452149237307575488685742466337167349957722605354030619710644095211806852486634133832454799401314387507400912379749342540362331656008195835761266417090114933829467815367478236333616734971716103848766845184713617066631439289132099503423698660355570146755954440998954028934694286175087621701539011949336725532258819027496286321792445940403987513145930405903468116349122564263698134205048744088030761446930748945146612814917617112096790829525910868209960979379834731279524238113660941508728031600369461123198572013954848677896869446612981846556067466735839843750000000 59836708722950001582030886107303620529839442404999521365723765045025919815997439393517378687619497664390669030099119252218596519745172213442048824752862350301437928190253587853133000397002551631760515859457445879451502770978916414329803782256572099848111748065377195618221094978385302590268312991234835099903367886803384707648879685278968185616358876987941280818876255719362538766177688632424120416843397938516373230957200515705452074042267494049408793602417811929922456677652478063524503314423593533870370521042676417075473288902637942621175785381327407882970773946203882503047241873808147706308895063699122059308896674572067080364802751952078792843860137824345394294886815953333816352749503633812871326750920135335579036466177313697767283786561561623394066159308514592650994317473912622586365307821396712564211319754541220328152296322552294400130605647360602394583697231940754890783198479181020136173482586645314547971665347722840874426817155093853769061562364399310253413026675323303618115770587934275205566097882161913582044465362498025643757382230347730001085437834262847900390625000 -29945929214367933742020090866478709176821228234582299903864917122300776769118075693549693647854787777184029864860381627511132591339359681653047119151786073079178334822464249907475593670502844787181050170455186124141665806347816357894830581315580981244152899597679450606155874987034778014921406274848478991933543254676960747486466146743636147707551622381733578485380729022492224903495365160896215601375637840015138276570339307534668961013144958630774072661720884658727769362249788972440007186241452608082044825833056805790605880457505777786264408050546551509554924822823242531540392439493344016662019099698545163457512547227676460803891244124144545461998399244674374570390162640743288748157286646887853443041282022409504455516584404709617802453222796937444507434134106507240901490754821712207994660353711161216843924082097640200266241996633671001023996533928741391347529033693457530869090232406762915015306329423872656333332137706811624825381779027084821903866915467172687190901757780015639214297032628454837646295752611417447510917625518142744234229013500225846655666828155517578125000000 -180510030914838801968713063472906558888887851140246041564446488511745703536834750068010014926338617078413777255147878398703631589867490025860863363250363148368689210089594532557089228750981519243746801653359612797723189287766588559809963270524523884313378522617385442076113830733049256544073028679879509980483988591971242922214907970130473584794134640083600680196749575903556529336147711287014202995066328386935635929666028196922377096800977051429168468587721246960510842895826692338435329270886114631180144885033288691044691983050284758077114129959680221034687717801969093455278276632767959598921629311302740346506772436757327844626305223710291379979143119322484740959924067080837321709400059116801120703296426624970227786633281063948842179862642706505396607844120363322347888506364425842211592078915406973076979696713383532121917949448304956945001050297057249636303789475708233357087970082582752879715175961933394340485256990135273365544942394129783017332008748590134440223064830869088328866344555161005294061563264626691602297795430048591694329601642365901170705910772085189819335937500 -404159569572602168379863474389300760227542316844944573721370819880236683711130009588196354779292648385623764441154041036881791998599365276530432731127305474639082870190893420808595807190217505571942462954094629563771229095414779493006890887535605919644692754875530149631629222817524710589760000557065545515613365195303346777726697349957189784572580063551767621016234153161411069227224899939545493897153519910016697974158123378803447169855246759197986799367966308349127412702745188658802753577726785898908458063301548964056539546507991778247306311580626923206103842218118727369682293245545772328750863556792978817143283850103281656615267731153766484656433317029020646557173487376975872985398818859870431360117790388442629347916612046175840368033413397136297646187066070828124262841373374525351755827244498972531568278831459592587132223062045706804140343781624170968058063256146536268865147475990693816099593534622836741127054181632574022334732278072440892660625972363869282170119960957222480839061026445456745191107781633274004289995810756117630008210639402932429220527410507202148437500000 -706754100943488708882599160815830030892434358527538056884633236344041010171016080325626451488736077623252558472700855054992161669177185400052248078727669302697339467586352730712693006277924562802258042416732871224186687044508149729261934771761213430288713203614903166419857750641112106314406938233615433247078493204373865418891116569224653915322643005841847770408473208670160147507734676234478802179472294230412562169542742824564302001432930221497434215610486901575000067223739356437787593953638776252217131880402368726519297361829172140628247094937441535449988291976648470050000834391145513529373062021330800306173083062373975587466118041950070775640778400570489970608004052020265038694884949835363943777561788527502098683663497460472863966663163038715270313671805916586693589668268848874862784831514693096015473804274115058873984132507841212978127553711041778453846256069503161557568040200807481653475337802972231874399867750019499044171874350219220803435437975086388494291029558995696521895100519890153197139377960898280423669393261808073514185224439643207006156444549560546875000000000 -1083070218391114775818889831813792499016502856951604919887186362802812020271087462196011313418017107417070303670540001061262187186458655613594858704540113907081345914742212715715100783187900171415050879425007062293658801896861474011417995368554374205887909587721562153511552420884111400233862984921087575149749458016566828841563961206059194881807753476392130005962576241031260205808984506104296744073885849115400439043487001469709040324249970351487972785419791987231286989613126395014378039147345051727537397590971289830730545899664343826871276444165579303939526325215013795777417222083381092489241516755005079700272065626307561610763769036945383815452388536506233604436509164984089826263328581606891294517434113764220633136970158823800657642242516274581333396689412016080521723726809345071201251574199154125781807654438947405809056222654772685175909771491417252980344446600492075946798284679325829534538060833071009068521883740465229212553624606902906773699132479810637497990972713406491030133396344706495285441486708493024378930090766271876045329092264069004158955067396163940429687500000 -1512126362416658750197625965569332096163038244789069595236025771327126312084602152180172655207804700911915777109652502211615795323057353951420210907824357547497342002376673940189860394969068469511345143516933881083659998409965252086743399034951084536249164949567529516081479882866441601770667768310409466052959854857111268631768396546768996156782883085511794951865030587176590055904602401348681504788789989301355317221715190568852844728521382182802461224038721666456009379969552741784992289424376236212868188712926429423856169877724557970350138066820609880687845696410765103386283526418389379566854076367852490598180635265940179119789394551579831554182090717622180281390888111193553692653686394790506218569869085271172415885025909488699845475529545735455879964639238261967650570515650815608387746858449927540249586037430045752716599816088072989222415794464298231957461676010872782681988657180232585812986574871886244393085470617391191779119708184339514433533801980521098844527992685058503013311160120265689695306412234553587002471103312407571268166650568787190422881394624710083007812500000 -1953427957310542130959778307880867493267973596789542178398309059885149238030831504211161760390345749170330401886059901538494771653823334631339470156202837773893314278539979555386323247137259397030755246304485371525497363434923400901973627923604311730322481361389745976132683195950019346659589959386788876325957120857986977483901853869125675596819320594770670276273439741631803746096684351272861750012093746394723805699023229444099967076650546895362391371878460582802781978080768707561619957815368185489458783821804278824401696772597321949503483024750377759976024671638429613202473209125763464486677512565658765910203886784377417406024917500780571412898495977342270828421203324208940226953598230719800004161362544153298755868484707179054473035530316055116059373453448646960496830645793445139026521215135867886151658450994975646256036034849446551208839383460845911374954714593448927191362834495815976510157980725096196908432956327031378351060594785276807427512170713314841217375599107682112078963567815462161564410710628089565761639996051240552709521436369755065243225544691085815429687500000 -2345289873018259077009933482564892847619600868182144553484858713620792967291794791716047428281201828573020912792562745144080365961723164973007601658426723996211764570942850284208708440607632363131223795930111770996672945821826239161306090653934534512050605239495653919778112860782452206890504184183196017281464503044014517883349004778776057847000481397478533420545713538530517018467141303127223547936724415203311207069738486534107878470464539003995755300244917779979441852843044235270922345915228220094595104270121439728903255259444679974186727491206506546359348171619039879161922431157072330762488739837356915707117690480076260726427241447103711822293260363971185394175215510733448859345605720034355371929936236080308800138831360363888333717575825156348067807886596972416318674181775155662092412785102423265139771147380147112642766723772602452733383282723525834575667196217665439756841768989796419707485480898745541532023288071702398092273847623704242850526951840649805713348782225212177718018943292118800808723838307419142568457336496657954488104236290269000164698809385299682617187500000 -2606354464658387738177469033752090185485817875355262912938405237719205322985412553462556971027484490171656693378630581064064371135841239940740166103982635203416852717136536633136407030785830984090025648541271103953013094492162586485940454422961682069106727502478267448150566402123232252806875720883691127319756712891373162701201904851009566405934138532330349390941310623244373047962686487470770608988580655967886757205493136235843837906532057827902773750853860624901504070526276733605545068789476084250045265100737722497745945627208294846198490617018929668167620573781975515149852480733487311284113907194567047385870436256101783473137286672288872599027237312277246558063598867315550994526015137896494934774759566781294303653417799003675630182201585612629591742750153151712714227202812153016828449094421943813017836995931123848610452423375196896219528494784423083283634264966995841528051687016073754215351852741966694794071846406938284608839698261198794526273081668966952681457780163008927344511714449218457379977169691329581675720258952416469745011484704377835441846400499343872070312500000 -2641037668539741693471810093523359353660524415961961677531377193450640079033356004276485580905921364167701140119507781948392950519066223133791020898496511573728829256690474483142617795482334465214064853473950968885230784387708769989974300820097433079878501072216833200544596470440062863531969774709625959315049343857066181216112111998671923608299655378401018134489051723772837420870461484698659062568616230638050673529675091378431121977558693380583109471831166390885604721442347654389266955223986263916262177481895376987473110646789638839969044723198911888212036306203601930674607856801420092054063852448970116374345759637202762337560039255772284100366168997158952387289550702892319708107633313080543335919283001766931945103285747305391210689164422231571434822476102223366325240602078148067078614340647886721224514088381977435201439320135993941435000203000328023672357497860612526824741158722187405026583235921747459654810075925608387866502798375796784092485396576565102772720531564257594504692747605468589729290789892824106045403120247753197993682838795592715541715733706951141357421875000 -2349207269256095270638637593644030509175351643686985453203074246863680712124448720586673855828198972910644534294795444214306656766556353784629018202018577094056935118984124590956576970496794553748683780826738955548882784836703168652416702630497685327974271115986959668002394901369215473095332814004583163847738785327809708251362914506041513229363023426363910134906189466166540056013496797671514993455446080587837242263957463583462203572910838704813039456783863569334988545078442596394811869211771526518114002026117816481700875789268207658267640882298900295872487439816213732803885527070041449937945229798555531172109025388061080520524536538170540216133993193202939732884632194463023335791116338579500110515158369463828188188759179987806137343388197637283837773367908473558045105681035385975524760377428049228772243350631561943057596987559132546973386515795778470280884205784631488398960218664219256932200804635908802756022065724314080747162154346432157216292555423422686673390499372156576149466063036006288612252416507259110723685689843386753278969836244982616335619240999221801757812500000 -1639294299296418357090532150678479531802423660349440546843603352861940863296929501375035332186131233349418451290349308986048489635511717785470536393073994500644530114016532291881506087026938411698210950020672262841802268838266605137800913838027788071300651923735340372967021704051718863843148043208752163203669500012659187861869483907100287673485404654605803974166898097114512420528180357876305740334685282278360910441907131913183879952329916262084890896666478869490198410970329004912092015889948399161119362436707744396190007505909997307933431303933460277706431714745995190297614458058275564435198328984210268660326228191144261989081160221512227757707710270160851771141267495521806488392980820008634954925490309673085494033994243109053553015072135778016741834943801702498731227419028792262327244989626396727334245535239384250730628338446452127133658098703053059289568150877120627123505292772049702736760574815331383444475068186876771517019493372865808133929690526679582070020446814592290249586440281344401089355495448464490548156457441199648382076925479111650929553434252738952636718750000 -443377013030685235645996739799146186663998692606249183198717656156838271124484126217065738823067156881013002870735339984231703477375854959456123999373681568511663191139552059377000825742050593564498540766437395519740189524078850205058292894861974790065625859154745678045964512967498865458540902851451346915003841848075778540647996460886422342182476606582016837438526695476662769493179450146840863974252789164937363995173047244679401834820634192397551784357293195475992201971329852612589819059143454967248771500068523460487964486605724289244909175222393584271942871860847752616798679910560407210246871022810728057575329773146722590708993546979987461141454302664679234214624251064387050602919753526574677866871256942997291483973372004696521669016250824992540589686395317814587078655264024631086982915517558029444321354867652350696189428603245765928361797398625068966043088591362514023395443584754294282386203732959254861438383141209687384787925526232266921222866670610462796706996320968841122046837038793248373386746933048264151118070132367814367019276389214610389899462461471557617187500000 1268023383971564666901139033980005285657564342223410671719480220910202109834549198003152370959067240033278574255670742914558670494963028742291877409302433371740304193289105535230760986017805251925303147771587827103617566555057665358695649636489128730518100350777174310757738400855225725690652258832828800659564758007684196806193639596020341384851885783322322537598963624454484064719367927463186883914791718189496737613879443166729667863472489227233059607456124806356792499130572695158047209783975578766921514277121722371197187658922235542017935986470194046703260492645869524312375416211331759985502967872121233970267524098695437654399112405786372629132762204035059852767173128999506577750247597642329299217473306620530016175964250232213215992103683655165180635347552975005941954773967338833115653871126594262694866311962340250344162222397149147292627262716583355616404146582170907956989552606104161523995698114492914418907590024330567295090842150078340329202732906922099862693600815117600859285322124647678641781642382912523048623292868040789019637437640142252348596230149269104003906250000 3474501523977042384680074501142046903433648735840875060154784025571351548311253075228002415634805910509225412376266555639967148792241475285124238331200968207623728907859436193079852636519364636236950744840937289783383805654873738000142114747550953959952862667369198347082521295622098648119362926156516308267325374972269229781179312254738621434969604104111877632287115869542992955186309121664102831664593801659943375070079924285467972492472764329465410608947151984638512676221186562074510349981643452995851265431744891134442794328197519633856341573160687300523367331839821213111534434065211176241904103596736047686180154143682068432292662870978750351728726425430891479331495112964734631253692540225675822059541077049238135177481286231349434647762863707142858010749155314060821463796563430088861028182671174310780429865887177123349375542885813547599795211160530691828903030536006118281619150600305655332147213054779720287731107691077791600054745346525659097081597842267756539957318817451020226400475335803161890060021420714913850010726195013932831451297644775877415668219327926635742187500000 6099788986338291777028315440721264175221866329011540068737259320098814339048932202877368336526334045612544075018301397056677558162727702714590808991460813337251721179688678485382638221360094636348914727409477560291511869446311427102967651739682251596116541128603788677086546003397256165685111087305962892510207542600445637654578818248114265258597943245916763451646690605862831577581846818213371144127666084715129921549353000886997192152850212628967131144036295828271332325448031551514525123727792753784383980632885437582982642685464284477009940608114758637224181011352018438410905876655180864700115667391765863093369192752889858443987803434431475296537336344764056327114149657490262161794170219586999179281231436573069345316063080209658301174000493097883539056654855349531340449075040826245037449048954580577929634482597104106777967727296621205765594150109027300829500733827289959483187853172777501801624429347233462318707938233745218685099445125322903722145602241138090347861192140748626926035900300498779890442261941788858340603215412597078648113124721419353591045364737510681152343750000 9013986109303453500485515502259882025761094243089653083913528488115607111699737827751173084366984801977775898220280486044575789763196808404848560126334791495337218572470848161201364635284480451624831551534818185933827252511767468019226686543285478633968635642102071578917958979911192895443231859653387733045898778186762172629430941585671347510562716271209025703839415815056582305926034144518341113563822181368910635000246850029633477065169230871790934212572009390722694415311186285251537846412059040681451716196205469291295611940268156224167026651312911476059176682592902774804434331851365324580851210002536694788556189467901993958199598653672151771875694088098601406407008956688213772461522850932334774285297760131054512302095883623278574000183235400735546029054817174494296317339025617514611587953530009219801485722080755905384867053157916999216307183321396000615431038526064837106582979272030499074333002626676018629233578084724924568933376865317692995737294183493215340742431272660905977609808565912381648891320933452577369733267274663063555600883702823011844884604215621948242187500000 12043239962661404694545267624257910159294552424821652054392683771805582251649911817125706568792710050515154253895419304079512902345772795988927493802139504491732919524450498215426110454994438810779825751145106687268320553917860499174794151500131001429872343781007969058930319290171306225943541507202940924742097010324317769329708838993713994807481652335056120968690543523290094022022236424027143482186695522390128153060534271069121376612145958285155298188007380709224088461329997673232182325023482450888370523828745530699639181171555967769963574431660524053976239616842078362353866576360834806399322290098472653049956545403365938889369098932989183949092472364994205784779583740218431907496784522717814292705434010135321166388372263431228357694659294811618639747587516312856653702422502451972295195197923120744978748344180248471641071185391764431988995197057937472890273742083055791413528944103256644417745802792395286863522790855610548058885866850728194091082537457566384353947707859918186781976330693041957928820997603472968842859855262265007607401512412792499162605963647365570068359375000 14989169504323782603367369586532598706450997922365349785532523490784822394458900211255195937223674527034083239791876336504059990149078080615617593742251812060378354045075476322916233178600847752000728219657893622136480574776185984171599450221216289540866438638875731077148475841874985818517371067064728354290505110039540851256650402149525696128880984260185862044413680166544178550250682826343962744193049070511261805121429129383101996610848167249177270359765332758671920993718588206555124649820421714288790011052067003831404301382294251101299907886697700030265093422202424092337824057050649597145691470855441243616933701373078990307720761394842357830481503632866072577349067145942403310056669284683453744780400006622984912839985317145892527925841943647464555561761079210479424344863872677588299538714162496123581025737171685410607210959948555269822748987448303104701034059057849862929796437653246099315274189086505260707943485119167772008382692367911570194316417906814847117111617473574804197588217578379421421483981294637950932585180906398021876552162368056997365783900022506713867187500000 17648434288012005316442509735567900751986277950582985085383906848842343538567495770236222212301625105324524046803936923194405134877986795676209036854532211079040820415806183299946564672052835857931440996873726446264055647853316016928491908430313805558408860526633622843907670221089612348585939521636178777682899197694434893681206442242675902981187448477937193904061724870521641103737760604906481101818883375499640472635511796658078192926234055065579343127487399757472425115374020023439007651934668684960303556676545407713081505632462236539032039796102379333684472311594776941448169688223777144219313734849236675048455247206488200946361688062891771968371078754084303794833691494321073931226157960366304266840927868644083049258621229251913183702365896224976438382881001878931879190532508600988522920379464331105397974148561107720928109780306163966698275693736393773443794189893450561062007060680331934026221348866788036353308215712555045587471902439933725431022469187788981506097587080992192136066754049415966876920680987641084700435467401477410750304519737596820050384849309921264648437500000 19843083433466015701496612624654268104355355562162145724288415944160668113489498229973871859853152446772819227038311542185047887104780060608918734201643649787239841615822617598729760377837230239359782711944344994108911695256026893362277024371073711348985666353879862445413266605458574281151033588750840445962411148678751955534127285582559369557295652687111122278848529702032273914960352245101452651889616203928184079382107265555579411792341536856122944950898076840913833460724035584516884966116771090007079589382473648293720940445708512014851790481661851075228609175223987637284740932488652270906495251675387032242052464992266014580523150133268177233331119840011872473857153236320061784859351070784129332781405483480224420449661217789780607974912886544160951486252945726262926149994449873531803723895956110091145335317875407695783217873292619123798121428033013072008796966805859455124728201418655059906378684544474212117395573689914252764724044669617051326764039562049251516114935262653870382511241130460914296924131140117539867751954246390285168527567449814341671299189329147338867187500000 21432458883718471324430734064184651262688780560441626364992626881303885571061790458149484140932574109839363342014753917586186218454381033867810521163965932291359654851893054102521947307355272471796433092714935086909307148718880328302698309842574296657432421615365882581756593961659026281249112217485404150449224281146502825805490599091518187140626330591966466875186738525806482471358639835508896024637804129419255203763350132838691987566428400755758407719360346213680840255918277274590671520161567040972972620667929783393920107985335923739976457101823809749783925202061869662435303762784437734552464186908436366120961417699541369854952363388760824644828091862602761391201439109685421264166818571125759976287649236992623783303221808902408364323975214944469984087161413372368345474566306006665121982848633811279723929494388575285536911952039856162348689639633685281566488502527320856504143055458406830681235457201864412911520886433225263537565149738664960041390709193398241035194159743284847514150751158485335880818635754788538465530508398787208970692752529885183321312069892883300781250000000 22342647009180192140665096645282678436905452765906645812160521217593993106750313606628302939074237273589881150523145520283686061874282589145984980830754597040269351251768058667894873498405577535409034203402159312065969901943449897550823035036064295642989742881116304422124000464529978313359108572446737642448300274811400961377419399516549504245152669521800557957481796050724846886139896303092196067960386269740879135911676405517714348695700745266106203422091712596617628599780690918983397337648272453906481680251587162133434821230338709364923423917360797569918043584657469856428375541732353028114711843888396390034798095963756131539462067219393161851931679476424414459849057883130257881763184755381965760350731291272576890636617392647001229675195164149797617063785495400429466422366106883140216899502324124449875985567490396042879572632316953680145652311753388618104699630363203915423771905860793135585160585982492357151475172788661238168032409228258278733918253978219213011799214241109572187251617767937953989822196216024339666214338095803413047207852670794636651407927274703979492187500000 22552548350054780746340078693089722098229595532315537911075960265459800364924354377462949952813611892720097744821959504702469674153833370893447153408390298365476605573053812780466384942880548359356204732902285798431179816561728972054743976102071130486646982118175236111819756835334874975077788079515563111877079715647180670924216130397828601439217844148036000174661906012804104820699777795703581891744756029561295365972647033803586195345998157389582497861932873478862431491717752471003621130523131274446159518963367691050544854096238867031665372288040207777131658813890875512031095624802762708001333449244245127928403377810363548812103957701587233440495388777153859530810284348972959649246484541822387474104026678610297147714242669744071683913308968570056868051503016956019412665134315737461924349795569533105448248467644523232079632006159577048411845374979534920800897662631217175718456688102991876468010072100266259796446656907201184194565164078803570413956664955127112885921238124229096261532974801196362778410922574745525034484430204492983254582760821449483046308159828186035156250000000 22118986287231321130184030240629355197431200237441050270541837878435985244504598103239507393730956834721820135671629073491911402953107042565734873776757732898250692048468376590319481449909199850668160429952964715606152128016639979616427405260420355469101415578963367938423806200348986377835107264933454865678818304204485691329176241796545518956503636103320499085604041043829949657748845181865617344652291199401405572172281334257461858780045145763120089615923961512509128765038090837172387142565711644794699326724706874305279843962877191822211748664803427754103492326150171004665999479094914066733512149065901728497222710377369332508108282135572566738942016260618761256261845588347432087292659356492570999068625938279957917208711189438434265442482129580854797343867654349181070414180668022566332872223741386516582961708635989899265088450155788248298739700328146720928797277031424129370394825613867915380759795962569488598673683626830356137707966150621471167527104408947122529266559935472354474141488086139648813858932824810350816768916757121407005298729941955571121070533990859985351562500000 21123177940154219699048245502196085762801225787870257361504915240704613167500665215749405832174451864023015243774288199710801858268545540799160423440206416934633590002130103927023310304333242536846773366242649174947782358371666944474860502092812553067059394875575693494159091809774369723080524870981402562002709449738176899871546564977393092355926242053012346700197870190984248759104082221409888339115062498644923078175654449738920223438531477868212805039803102246630775849836894630190958070677613908904675982089911405970360533823266457251735057479056551339490301656776377190801143446796311919541787011268972693004531420669339715746852155158043084576344095936208548759987200518938141889923297284892658484137044856162589878919659591498962964820537953238845457588253318213392037624721196192327884746124963401081983158622460062317179535973249556860553131381843936381165309558794530425125678017810706269226903082633907710515310372447994042526669474680881382685354984255788794955888794075202780211246424612074275530146814878807145273417638085405799680364935522192126882146112620830535888671875000 19714281639327057600169140079562606714342810947236048752422363306583187544652485221374623993127093584614108384602760591475448547579505896402370494385801379395436404787798727918275194550542818573028401232591966891662452563868275991671698338542019715794849549596085387644546491159022228488395061227083847115240418534962789559800788359120101525675092313352960509827385784275886150425592530203577076789963303321766294066265316063095343782126690474712180046745832545017746367281096108207674833407219562537456011079187198031412210586015004897083266399023879153406373895928913771669710470898011295817883735893770958712873589379440840424224677985374630024120580468348841752093317682940035655112577352143008934058784403790564285836668750959503445368275294656722041144411797983920609455060868841251400907928997482679101865491907784569206177494801371881626981692465055408953547859901024709176351187546854701120904711283737251451977246278597108203969880168115878910316390817913138234133181386435141856953877788527710662690837739987716558850504597763104140412809828220019880973268300294876098632812500000 18000402265976959262807713859096664525455192403433268070655473795190376472255681654583874638588958143619212512776635413310986203500204845931061025682669358982983007894095207746006138763752539176235589707219489259629897151678840583489006840859111065933553214679943853062060413930158083415570381510153134260807443915292908414590746253460307507365280797366142379714543032569157374100534537920091671804477207502699251759976032546327932049221810986649168739561692504031118580802345308875342953863909019185979971244637484785768860960444680031427682148565595292651336824298806993390459036240642512768998839638256710239721834957338515493854269508712506293876484675593097025610875072905860929543255847499109877016246781588948381931970597435037233260166459990270535271138671590792402981366795218342845940681967044534557101582427263532840592349156237085705986230491047576369175675639556361241866020952869617159079736260785325490369660435712891288270759112729793876081638824570630051177244902023579994513534230373203323439416914644733580603385406551168566738688192607753535412484779953956604003906250000 16154882809597057526507013695634831330048928157538739482035369462486979909076481413095169149569081605298018738492104047075531421533546201837306760956847969869509243277258946704265151802372939145093407853820074417728339061789158972715511665968666476975519283794074616665465622520634309417324876832662197233124594520563848854548650425698983180696010764503218962680190047276904934606267426294749244235601674323802627460549792852361906637107037862292790779676927797320366408440475293181228137191482073379666603273292802318174345498224330581954043612396850924971105923199817354236446566807938307439113328953763476094151407179029115718550614108233414238598132906304798612788029282440305188014557182742855336085328578573334219229931990333691568085308891476222182051192299524014910292501314729269015917755540541408405153413173983648946766524794380420763289790017338323597402796511903980275855181881517259789417889279762305031300463874643858840177071762235421749158266701489751765355563389551230941765879503124792226042879539559965889308590687198969486956107166619744930358137935400009155273437500000 14239615031975780488667350707653386143257997084529612251508875437910250184966377795513597899418664007565594543908037695897054366847505810178164002957742972484303680617008622078896259911789318303673146774304414787639591419594630337041759945133153677374877223904704759632020450458714355404881824516082023170081165988907361040656872931975406806593403229105286698632707823969250433852620049783404947413916355377658058102752081797025254539662992415463870221034397501181991119754123521299923361153454067652892958119624441409336895617856111223861410197136543572902625245762050511971838017975357158417290368695692001037460380342165613001203307210819714303927923643264675731069068541089768595893214719168129787691379109195674938975569435635502707252409241821451122731658836864360325350128216410597404806443881076867207602799838076694619952718339463188969511874750374484378557687448843168907216176932571251887671288424571498078779099230628872497026082205986649435731340008260201340394352398653592673836760914535823684738546502056017545240853045097547557472014712054431129217846319079399108886718750000 12397169797113616281696719300265951470524439917169906850915441779911602993587286004222956431640817796766169181388364017835286788613930482571846678377409923711172739748370060434407132647241765728782902603868743571127907811564615065028930425944574810887263158385658074705115251532168970669067545462105282110103738155828281226415647616290252551807527972643481206110556159306755404885282733431400331856986286951957534265456025774366855244983090761144301184461054378184777812037588162862018935527408675928429216115250090870812600903983027537772825911090094488778280336823500808659572269550106606925222325641286302147355096255380648315877823352892897108625414613140588203333785252182804206389511644045573746047616945316991815747764244951980657084845869851054412962993564716071230773370977860819137633445581399341180848588653619306361270486006510089070957193870686028966906050269491291528061778744336336281198257682065664536001407937133032364183619791296208178853301489881456695649153658249391322423339179520215739787665658673259136065687928808099328801400895727624629216734319925308227539062500000 10624682537389131918227900157005125610082980822117116192527710052081370288144954162224321565350780847910867628681555810972470552805957113098991262885772742974924950792455365795208685130510039376700428077246509072270756854488521104206222460663843853511938486815425544320817553652981723385150558263092856348323087527457545175981860946779758734470922668599982616480162977954466464199261459463792489853439425865853212257854412065640124708265285100982195133304815042794043023849981602913623040019509172185718201081914294021687686217319001752139712676435481744076014062848435587010073640996797463777696912462395361519773657775895231686696003487733436961690191787545806760414868132702513720632286545579720720701877249832189145139202516519538140850813887073775738108751494557209497018530528415416837693445997816038268078077914044724077917839759814935485948420269211669120834195863200552173841673757599428344746985296520317987672352364648159043989267338160598023753518350334159212263046418276754054540211259935255443417377809131959204418281239012171538729431552461335286352550610899925231933593750000 9010118575204970439938907817388621447041417539835904528072579727978937124706314202452868341616543456575552738539340854297464186405332720000383386445192239276691078127058539871795254984395607582878080573421373849399764394106850962835450892634945428325669745011862745849258421518372990719264583280965925122289280309881099393551745940892175223160327816323760727058502948126669204175106732982697896931603346937498351999721439858513389470288002881157662604387111649818084135710840163972955760342244364016185019204735560239933851912055608843477577549026936876849779596821373871280009450045610386418902100187090224602848879260232009011668598321919665378097021473633589895796348674212418607870713327503593178788418839033790291155883120637242168942210308497318579849557287587611811232230026671580798879689073512883254285558524962548106595094664052489886117837317568783631772841478755672760143746968466764615421257812610311644363246399161689695734061505573826751007552850448878961079264596067489217375261349993510526031284107599667799457653052057648252349403295013985371042508631944656372070312500000 7524663502638380990892252058544922131733365525536007611188297017793693971094927100708294016879903725905475181219630629542543766725892157994862758970232792808583793310986258694867704317350773845562884860865262796024654638726717647257248803259958562778263154407288310491710002078916309701631311790547248217237242037272833111625251566744811525405055249761382209271645050017698919869791856293942713499497741997913747623891919115851301567001179737865812533351578503740009138622938442463079071709993907579021087151430033882814437957664929639254276207489122046936336243067702417044176943893449764058967345086973413344702068124522603846669642735916808462693308771365821561866343324099039191325295832268533026374916101618468108504793358324790728544878830834388257951617151390997406492172747722794036658241929637288564182420220151538022870162652979247463166894857660028506102000237333586327739337602575292128234836690829660936034671735023256166179290140560724071072285237569416007545579313489817144590100622522705655624263340957012269893918023752272099279915507086258230629027821123600006103515625000 6194673855740130250122638927078710982585720495073927379751508043889325933433598430673211229300820803000017470285468080964207705923582497820981732865428939450046940484521298562279944743212748720610748347739322843403184092211463995723777994243524029893228357758571912368092904286625360759422801785813166486206749812747079448974472551148094417302744281616753910971908072472656265172857187143204495236678840212402712198411269770722422225392722309318184754506592963593618889889728699652472782637970842639291402650087174631148195882517746091988103611658330012642990463437513804323996440020562207079388227753958415986354082135571506860970055829514717429766898879270132285088659057392530559445018757784706211690908043409672229940888703908631973633852926216495032102290658389352095598152725753131442569530946394306582869167617024623719999213581556213990600785564144020681001562073186444817915821379659144846253494650111704965160935420926068037627572716521683985010380630495245519192998868932859620628579629091873671467039331870640056047292228670035510538355305598656741494778543710708618164062500000 5027224249547045141888479765840028791978753678951287886037635044404578567367019618601994340697479621298222696335878106401334416885306356173745166125992541038005974242131824153835431243403537565777075907042485727458474805774769756459838725369775908474688779654333921236278154772116998478279164404912544541331704268319268465557707999449217373169204719516234608727635583777187222529028892902540910036814439694182802880594608651014995714945207827351828780910292099627439831777016067147761017083698209579030201681125302197885810987767650348837737033215899684334292614258384328431916490220845080403240236953386971807168381408932118668367643691632728035499665450740857463348938772221902399746915437343776127392249580941907087570385853553521842505407939961459486344114310268274777158183859528550691156561730647718366905770261549002960941486976517184523253285364813160170948425744924789730029430203848561831590844354498082358118958026491499381403729347569873625077590734818762297545082250022161640841015277991152231178647043585898860346818956280540483493035619488864540471695363521575927734375000000 3972638604000876714275293890965337122362654005466324951823916133741083609285938730426218263550489049402443948612558584528189553920995736244918795595573262342846271735433664511244692834724812244061572020111115600346553052515915818343475405371189700366072522155809342300299643593175972141002728745351147037032216987333823790974088463557645182220008087787090615502640631859438115927482489760133596006583714126174730954329616643221615629752882329081688829130567192515156675833685607261660518363706847548558570382485207764730168819771312392232625892681463199213006072018636943239866393585676626335663280329244918336585616062822447978648146115635318743068572370387565622878005871583820690224541805887675590575537827660044628670490645804141063030760409659530418967828961161853288378235037373735569462456101805496843492846980634124999255458579254758538011276113157991994100503098718277707657484464593713256582632735689060531335803217211293810685785821443343889325562091951952762931705489485812495941364103227480653513399124404275898164805861067926551644796662188241498370189219713211059570312500000 3121554138272613635162855587337689867734050273857247969447677794099996706871973088771654995072914249009489509428074575862042056617008251557203837562959540534470814888660540293573416676831051166447591495523801645860937433441993396442374369936618237567921499961064133447609196649471599067441850994374844582532322298295298378269439843495179885315589716596331247006264767095904596120317953352486449039710442682504624361156764416910240997865317993754378163992649309279611196636773702215064075335782157126814008830260644545724159164663213555991861985043297224213803297200793556883392144889935815998148493423343027946730777714097111513654773216430175644675484535632364602949180464531547355806378513909914149954917828589194837202976629226375110977388533105931232490913708643152731134167173416404353851938151696663268759600989279987900062944216256213026407443627372038838081576300921268797721799950760098208252085121203847901969368418350704059953443429199868505536693085291699533793239987964315560025958303330370068224741254562117401526716148021113855347968835118876995693426579236984252929687500000 2328077407815226642554995056015355033956069234789509045417397252046768771856461376283187340200179688531992836061333176516234065731483972841864538208007996729553531884032824723366410164200099225471549132079576130987248873482568508789022663659863775781669175516530872857702515376795294553499108375955802741431401939990085086999827284319204718898840401853909722689141321129081916687044946275870600536100907809465822839908890745072965229284467194584904256060744744717610682215725228177874555282611838971519386519916679083586580967822492796514161112953994124089049676690562348380831880313780768979743161603831153277683326899821526264863148357759152207226368932816550810925993969840548046150712067894459942202185222809412619232349124414698672066418681328898505601747130908622295999680886828915091678063562580584018794413739557043095537618727793849958221089512670677454451398019084698092215851861970056321801548419589968187073976750008072971775402786671848168644827355330155412884947456961739135368946816883325990644240842822393784676932983925572086692651341266468989488203078508377075195312500000 1775630001391515839465759305687163697157284866453868784166385242971587878858789253079768573138897600401787381905346572025997966938576239259509752906283789218732676362929900135578819677415969975080326968629590659022680397033947231825632189278050779088680235420272765194503305443932288969113546409785759717487674958544712220844502560128524865671059291324039868930448315081320445347157086689039353139159959509550250255525581978445892570284289930419567992375074017988277161374997488368711136703125236477755447275894153799280339878033043207138600959234176314410426756956230935021164931372801106595763354629074702306904303329828712447584549728528517915380307169001285430316332046582817506830613875586408698999183263619272399461296157063294891289138354558508316796599609769187432377328349856286543105112246950982458274625151195796029498823926005648687904000597010321711831273785597107558949094567019926580514364579424467606342063932337736838984010840918573690048159107524247970982278449512061992769513243975889536861555844888024692429540377349473929523976378774818840611260384321212768554687500000 1226123846973497801582356518193144300990062424386658642668035339502126215636541566954423873161193065716121191392653045428131390357108995102783882284760877105286173277584965421232079352307074006494181165700776618081975940424289606546495311637464449957058025029168319307365361831449740324492142218254877201117522900978498857648940629492754814142570273138747368478454927592833188039316094222325288333414353484810401328777856524482097372696482689688702787780558405200900179459435121309452504820829754013802532651092653190031028890552791648924739754144457434529917455409287673873399698597138275238038476345453893348151281232723688507813406207927554497123490272666572079988295437788021204638750242703376161042238793262875371059891876915591693545656510505511816916512155276238482084550951929667074653352553582863450097231008308053122265746639970300248052194691529047372051138471788685028721085395934063343217281989957451503224883852266906671765779483279820840419925093806631303451227233675398318680325614657808908611753472721225130225015274977242048497910742455019317276310175657272338867187500000 922205319770249353614009655470041700730884550454662584113960745197862845880980401517161559902149545110251213129830535909033983676941254333919660562942192866968701352009161255214126364615435002175421563712573359561098968623488324340935003217908654507275884492018131392571760988870908324943702166286891116092051978721730502145004769698070370693088218711520492031181681016777805578769972079381444230790712593447381374333378313907976824066227433148162670984497306799971955783015892364311666027239670422617791674985528894328815825150726651021726408048670102403728257927330827535230351549659902015463102519259989647596189000263385272628441444965155167750961265836968531642089332209175525957954079214368355640275595426002459181793657421675220208461629149205368609794082339514800365589810921767906879324335338693906592960579731005065849657137142651984303179823765167076683116516124314693520946341440511822466794660619433684069841378954119138408133658679827177032346609067780969807556467081216466762329008497552373726719757244528110686585679594135120195176960611327388050995068624615669250488281250 581417253509665407372972651379300025274707351276373107336255465618112119028022411710545986527332351871282466694297857303630653294898402204864911920523279533749458254471238662672048771264874714048498774590195563226789094252219622769164426080581476091062002693400474998688791335423054119295849893761740513781696622901176159512970912784871175427346887416216327850670367993714438390471641096562844797487148023742116005421039957091341021439995970344912197275317008932100557620737788505689102361043240102023934682827262209052881756904982469266474486724960088223651083888921959304035908289606775587234642022100351003019172536831433276555429975176971565655436894358247989162726471772498629848356899403879685805079057160943539011698043985148365268449096868168265959987144079707109820680047972347293208414677077220985379990649569826975625753736882684131378682523692143008305591927046759054306973228829787596272146363166268467711437129878147966025103276774645141235556658652844779478532760356799857373765448494604317422345313325782409458893392024910379322147346847771132161142304539680480957031250000 442560541307145194329615792398919393497564523073297974680028163866912610381619241643023506670251758123190298347818021236888179261102495289006168013862215434633369501459571593990909653886245843874227781427389908038411280055685368585100384966766114489028849409650489141265239658938818916422383190445499245779652835815989490673620827851736469821425647649549550912404875697274249963727725398821853233831518005356434696571243429370683436186829277288543328722257490619666885537187938309874646606105024826324607576815056005598774343402252482448124174071922923498262102740237133320592973974883777569235678183601118018197017531753172669801805510030413820174779647894033716049764588572823188449728138982399142219327852789372353599822535141369379333689844626455417265518974898961223236871541072105296698721397846965470379244883276629574070458429560113737051097355827001755881217891375905010228541946131471119319819445920429930114327498206484284063966812020225837201293549986000174539123353437662401504444903183280409794926376092708870085726758056022355880109592218829561716120224446058273315429687500 262567591086465131552885302054364812025195904409167692684139754087036800332911620521115927746606056032626486805720937971626951392375890719964897437438919481965021132911131956821694030238102791012734259096313119792345926115564126914480415853455202301502627401672790595344789559422664731931728455716437650456482917338788319639945221220366038057569705127979406159349191287556323400995375208519080112693335580314766436773228584510744868453492241012084262315486924651606534890599374632644362197813823216372341972308696626134912812186113208804922874388731049879219298500320942447374759660681362181267757149939321587994347039286162253336065114748931507882787122301809180738745252699966704548359904490551895205968942303801318467244851582194336490702177600551267007627508734864380766848662771973981209837497951167248555092598095175662883709238706672112352160375602387574938141616311573383039764912539964670772584964871286255417752759073081128167155369304554636372279838825864888541605634411199648877966148924663976074826692058253907214377416680539152485721055008127677865559235215187072753906250000 194637741759023954251528861589067420530331420386882199589564203038490691354970562170594237186821715769861799355828472214996396863917519179627259410608863963997514613534870048013443602296253514954307271183756128939488700209893971345962576554661125016115135698966014422280354465774278298557284396193677483858126705550024694052581186263469678869881800163592621547927378357342925310171807061829879187367492052801879578339605903758532678105126150109597986530821122939462565530349194246706669115337741917434401161646725451978213946554985425202949422053147789898667507671855639218858294328904655228846508315320581399723380516636031902221215453647355265404402302001936323728764665273836294890103198264795182058767805348403402441303657665335400775206699498825626040927411496475623300243115902379085868159624763268943875489309161026302485354570943631090527911828147842373680704482332411686690721810685381121661751504573182243030550483432251021079793282637996789884633102358846846454160412615126094652018730489686195745568558085802778816528977494103990082945782047474381215579342097043991088867187500 134894128941636884620902390196596559760267400136852141522461832919653748826131317909789370180146936768122808533415077466635769851326499494152149443959008845497965307221021678806952314036410555415390608582753857702353545198272422854125066122927274123611649563929468796587009800584546398815837028911349659091050039038680619627621353627648364732482203909094876922677119079199007109747451350937748890838376771276400507369486728402528799337686014184390886751331482943453996530026389931904518283592902635235344944329688771535859356251505309986742533911419738698434664498085550236848261670411344868030477479439462544882201857495796692297239715975535195561558450251651457460015710037010075302390752893075555341579892359689809410303232052173567065103062301381961462686004839376641206328043058578769790431013649123220999991763409379688802100157990344825060147284027640296725193417966626026720204925868234307032717153875603901217648019654333558742948969012027140162110693838693652143847059775053210541222475795089893454275976650680438852412501285914952272454447879113104136195033788681030273437500000 64586735785966153848252082749208202736443228398041801231153714936497637595141116977775723340008145516161942901579423358054138640982684508644736769679741701101056618022482165487080909927432509585143906853925363223645863387674153592668104133454956060834947853131607597946456982865939280771642848825621143975298741201820696494774902520162376768505122486278713018549708805092174413897048137293215568230795731318143819514622340956341481717074773146861786198203720965672225116124430710319814330879730399283781547521524875782124026565416478594033513385206347853757536211053882995122556621758948226071758797771020809600335247489627446833184261311781521982175086986253669534696006048810434269294415917701755993576619680359327985060518840113958501322833287653704415208623227335586391492680770263639056404305169240374682862447700916884685613053163800950380161620839647369327107634202079285627547360415009768363461953985404107438135068282196861205981557989577383438843465505137565179798261099669584624104030137037138946367423245309662155007470725355483802659212200225624656013678759336471557617187500 94877492033787520917455306526918251208906508962219791514883285591211508215494634569457429391326445225913085845637588852811730724647117598049420270268985779585515146862727774223146704548001871017304006188781891339737692249278113769381759369152473365154072119867720739637624538698463090262780637616614421031376007098805252035929445738334660106360145896660543821973756065849879848280006260264570746419988889017862816083096150296714485506071080185561298074933887201203171126854567136060844103377829497466843275162149750151193821115597781360252671010839535343252544630881185377149523636572957612944062681438323306208762909697500525623692651298248427522047017306429600757046168862498637682034526788473454653674236624263103448298300719590643235102103022908504243777106224607354882265690168708110345345185413731680942020039109859134686304900536599264830055006400754922414213978716649146791337437344310282771977938007874368048654541720367051690447647823320884316777695340845892000508763893469108386163114383922810089317558562749787566160463203678943153868141635598476568702608346939086914062500000 -5510416508535199351369194697670400455017488575135950414476800906347961825728266172172249748175586098913795048859811579213088514184221605169787556540608768372534639607355540189396608960266732722520759873625798981269237908991665962196538864827805507514105422525601458491315772173381211623878444531644082005534107366781428471578006736615552294200939260138494611789287729693710138284856648011962539236823175856077409666016394022939256142345081479581166933194819662034669247677522410154830130661520886190565086500846187588700073895749561061372593815807161305540006984502901936704796673222299646099802718452347156915931139929818579069937453679336003032762861494021393552882905445370777783253887425761367891816584246918088978825591527800540905116732774288026748728978984039678734974406717894384569945108201257590500268550471926777540271507232541587355185409835736638442143363026536916953526254320365172209758524282034492981008412603216503628598223784033982894874749298028744624204256127541726836620761888143176271474280728358459262826717029315843140871780669876045521959895268082618713378906250 78532654258754009477134289529896211855001094412532525034945237950270662595881554690506249076658850918188850099287287436530768270946107112916367161311737840875435079639306350453072939689736146899652129731900953180248186068654874194601578072505091574881497774863125912192822808701365098833908570197615754890755681732247525657321062370832618119852778306491730831687769569750553925972949404577174206877244914882276427299161668394540233331330922515077549211349527931595528777016288585985507789875331762013357223036119078619767276349621004386251176048536869793848939476425325074874298506534358635647159337863234362622030802479712142363863468291049003849197590288328830926962382889642544024619085192596632567714134052705608463953111454324874048625302694895451419092895418260528716595173495096882646641559146493453452031703384719597126137788897956846591804934681793858385606278021192361725254244909774255093306170045361247627973468376281331026933321911602234240208156123850319528068507453080314417090333232642964798418047122129099947711557092038550621435066823039505834458395838737487792968750000 -33250303689549135068795671084924825963015696917168317660432493708370917758892139135656636847864450678955424460390888779041416415656568607249616232522487679696735016613713134966133445278767021577404602842755840758996779335982813750572536869820734987719858920857188108482420394954459764706887852861354805392871756801038124292746882420792226514394320040338843875383660058367933099504751469823847663106778752755724376926267721676518834927016307428587370103161963883423479356445627709104510322266950556036917726617314784314489030548439783018068948021145006605037561212046431396145146932996821814907587364796548774155950752131360133514280510627413983058506568451728802217103177861412823400236481143920736409833431841408999406477682079006555538468671805226498157543686317321018133140679299146765928806519153809725466310416249697874245008828490749770991412409107214379941350338965220538995456850809504755651196716295960514916910915177692052902503546026287290668292729825748916842361424475810474115642768598370853101106423611924016755805688711197039449107837327801462379284203052520751953125000000 56893543077763454758820168624428634510567455651526282098005199986951174101530086556100232359946305987296663571612354685838762073963998477368074383354801793634718515417559372688677563826682412793654635465478674223814679289288049603618200335506468984718116821860139547976125725386897893632667392616672158327852741793254698219697218189438887204375754650599676855650180905386827863855044592164367295084740901839957900594360985288871287210559797781103763060548388735548236652155589964409181122404331048339726033539453505109973513126847467824090234093977059583708826581845015137149897843848181501585949838796308696220085018983163062484366193456335360670816432177100961146298724510997289659244140594725399748790494513507869670415139057232604930782949910246606859643592971001003136237818238384059453153283425141617222752357500720025179502930855310180442209353267276275344977381681878579170811203433827757958268959635219470654397268004414175473514464051430601698603442846957241260035858967761962032297058233291746208238696801751459768582284349796321593420445061894952232250943779945373535156250000 -27766153552475294093690258395099180383583893081691308370006759151285886139064140791417699790865815308824089705299423173586053454615590186068471206513615997955378320577777904742807585542283050142159834235608367649572047377984880641633199596956862175555426137713020038594047716534268819768001406766649536996604187487557117694356565333653839700943299754240237540180339562734186047381772801950694435975046063804229746420561070786187714701180436961985154972858337316459050956506986681232065615810447413726318787138327370869663944499299364958917422220129191769986755372398136907735522026824450013180670687985129086385207814825999312181172916763471193232787955392300448926496515546830521387000872441358668696356794641295878380528025338619803731934981464960272612411849722716023485429817020077185615296932051789503994858387267562032199619084985312960564593170072813336142256606797007051946830341034949416611546759891993942875218401477505071722392915719829726878440417370884294271527271292815244363194101693068185860942098012020535656886842527129018805449878204427704986301250755786895751953125000 26057711675985553045218666095148610489970693079957493983590058348702946188183712271618442013571597476193994159245041739256072254122559031210687186217054361330715626801956230039218806193083516219879304705823900972825790832310798849673420841419998390326522386572359749911812013844215952758892546422882727189279564509037167431124405819611526758029069080679658578976845627085467940852073681855347069966101425178954736411585409038823385072855903560288924317810225720862492985100956508296893355497507888851636997289594020147849320364656141122362046272782600262141316062542582693547379846634193892754129789990534858130261154406327842640222209340657897603467607359766274904639440320830358017191993812253910989660743451111949407888699671045311279081853021206921416348621642216162994252535921873085240665407802291694766721998363975507676494353241620916817780989613716287032612781227750782452568635941768892908908845909519520185746423420119021243058654890613523624026481626940254171544810835451784254557249154708440103445268352892792103307371628414238666840430092008773499401286244392395019531250000 -3902003961275653175565556927799033884274735495939456281467535487711178657081116876327210459915152881516349291843491659386161301624985261334147380146612240259561526274581511820430670843354970750493047984086906325723584496371848796539976452523590399389716910291177819598626606298289346115055097637157409786308931713367280046611926913166460540489196965752551580018054402636889955212337079117182497161480211487073753542958846628281955920911767022856964166981502144772385237346530058038501128361254435594094065118843202436560484175935003285312259652792708430359400625708731027782759576729722750068660017792712767010127038487853049103191941408534579813912771670744312324195626271589314244607752559179103599822405342071006244848707292728337015065781267100588549053365360491871162483803340484065983722112957847382071682110560932051310212924800435470291501690549783917329983192501364426665860937245369928056015046226823716506575097690140247230391124815283396021396336879671858329971330863045964610076206353889031460875824257573384940840659718353590533837516041160142776789143681526184082031250000 -6008310722546133181944763664138357908062344657386908304655427474110511432146685391995162876604481330514464873053473912023465657803443696308667388809321339557151569543057933083798508603972853627073913148361723682720574265674576766472597142078216903212805805485835808839588946608963796717804119282610707865551011480225008143528582612988805655884881917550575458983549953655743287772622658449413575542517287328522693821160792522830493259045068674829651635223321105243703686201277802712768080832767052951415113551934623737169764692020373361919564885923024699744292162100925558200647666510944755141527847909074616312659950376398621834258199485726451604972226449698756837747993168992107848582551150635005354965116981435886944565424135041002801522650174414294066156894334051217766913043128065908557870180718454206319080003085026239177051559379853776924236253483234264019581605505989275509009577755602532641194106243479204799662832305601538452519177097824974776628969762733374703248017291455510962941959171433259436382816302741884218273900627407829331746991208262897998793050646781921386718750000 21418740413441148586484396622892765994849249762799564039604526423949180712280769569366219510640687358191869793466653118714196983403921003382684516249238153459251710057395011595675522025137722394052098333140097917015782715850547982203579465099069958000328340001095322448116797381010570747186257411692060260137096639492792913812883102891920942309504618726076006664474306024321923911405328536881539645328081245258945604637908743816219597268200826307950052620015365594058827037559391425729752987030495304343895468815694580395811726465375318048521161662294280164593071285984546109992991908419474089072998290898317548229980792383675527567827086345215024913366413218654951097894073606481358430030892302733431993833146329156427581419814518217897495454131765254436093510257489931540901959811580474363443273892995635798258995980992158103903189270618972065105587064783104081878862443471760646494639961878342435226182655687476446559301849533688133745593351706169697249608291942486789958122521983462768036426179626795362728300359236773192216646328370088266232137974576232863910263404250144958496093750 -28579793784400762862448648050997029788648002914282437647404939116544073035631818148969646977893249538800045296262915327463072464521160120537607383477441469080703368764290813513198220257396744666824304080235864407394861129668584806488925256277116441554151096509895835607989721739261561698869469094276992102989876001116136464953100773156037085743272983089204918947626820823531406574227255252464870641811941158210332762182357609734561769452179673455299793703401463526387318487196236887952092343376666815086246751964712897064859763820438671603938284608817489602421857288602612666975138564900232235350686277157467573732846662231425628986099105144661395795169276246673619037594145785317105949540746169207718289127068100057971421914480033677165425179086283291519150055926151702421031902773148100750581788113394625074233756254386232315620647363027874218244013330308408804250284187025510225300652708292069433147936176009665612112505544032197557589560230258553525384025495366883466742624997376733669731997646215391652775736992795744576273417081967013510246378160672975354827940464019775390625000000 34270262296060167839956878241172436527915541943533534451340606986198411136306344739664196947524080368268621561010881371867450562334791061627658286497928877485741230413521040277109016925747630538119447187687508718961262655900862504650625899048898135547307167217535820548510757106102782512239418017687510620653217816767978488343384793875819660444089765069098579907875781628792695035245396986862701588288941731640308674061756815635862549263163044920863311744853428828977656123609016264325674332184314287238721693438367047186391555217588277777128343697508278148927923098347112906130687901234242627347282329611294077577005153221438039616723083726791645416482439918328048362418877601155747402005290473223473600717933926100832172864994249529679259638562866205967841810742989679069443554561311609462438439210558571505953891926003268375509512961531396277118038413501042341670786649329952413228327073875275898385034221636036278409694749259998273229223067545866672268961087839308791000833177258542158767707646294253128667143985565030161068715265536799524734995481267674222181085497140884399414062500 -32891380503105940809811520603119848198190234429549063414570027883395913478749284438502774930275837923146444303651784498668369672424927851527948383944633479764794306647025469386508217638294941172865139720533445494948882740824046243091461205604753495205326545418210723577666546648509689141945899582454797868947684688192156022920333537220956125595095436713922664962627820343321138519685712108355263382549318112112904773906697746910382108976475048228810813092047877698104133262516164679087119854776488504478743553615643093312159611004930830427954108353048923662355141333147091689711610724362009687643310345212731246252630015689726030875860096687668317041126379896688732727730498948864238934081899959673435756195511674232035373618614946971813714457107976388944163384985873757534746149629711253700945652664819297760799655267785235089100358540020022912075022067882291809948927362687720253857501561505748380658715919345989648673092191965150326204618497671946015934150868106116982084241489463277418550684682780660467317572366473151651698595680065636930045069874495311523787677288055419921875000000 27934267922517718631241543188325218854789719370288737068821440322492365623220147454595690666272531224640984999709108224156351640035904500110594210669405664459605479316265226452790816145489467017840491497783997545515973080963946668226833967623003162589779668987441258110727624660168729081611075787136854469205247857188119317359402406125606284245258135064961228559877434207430956304315218322827190506451105336060521291329048105459428385783931868861879547106216948156358789386087526197099084014193364938009469205418811869698759060945721047592361260736948008549158203468999859651566741411001591724396317772415956185675832644072794442274611983361480991821572094000482366276562153141590867757887724505395882859181921952306019487682392629759285334673455342234806759829690537881159173890874587987811727317649252651446261415990884505480084759348529326791885477529784287244530988331141303421842515109682178444508970721659358274535554950269503072413558040787751223071094588860806893418944897034381864229395968391291191759701284426340607392925896642109980395202173397706246760208159685134887695312500 -18612901055731065409013287090150550051768936645316095950390177021859259727460715871150496384919176992234551266118140540776152761540693933840794595191132539475082496721208795117325261175848191557716917961327846973989446424298341880361730034423451188900835205522814759372310132407756387486249547003346606995407984407143953967194423196342237553468818827109108652932945976423942487188743467156472448874598310133772896059945348309503505259171567919211754945733035401042164409874290433508159780645696189361777698705589882454972593179642269833142914692086064683160663458494179606955500221027433818270966350627628135184231696215693462677392972191699249314544524342813000196862265586533784426805712698380545354342210514579217549011731180170691672882464601766884001143872497658266655173777404792985175847383751519202240274648412716564970495224760836282690018356408121291486331547830482138670293530205625117517487700336904041902869932818404321507487378945852000724100149180496119651900405760871833854224910869654089072031713726877474244628378586251666844744723228188831853913143277168273925781250000 7934542307487117941747570544142091948254288833013523704552716557324856829307837937669791519083792246043514453642143045908274775288743670395788473100790830310901062635700520249225323449169255785361438262062039958293639683969329013020384936287110193583947800966543800176136458590438046048212240775535932770691563317914166684821161973813357082920323804208146879289457336486571574882943891627859340385044766346740120351776185455319303400100825186268404598685479699111782303242512726823391512305776649824394140920972414017665743042448830960058289824857419249066552076318342931019650790366846151800652175369253362099380230207286634114850332197038203767932451254435089670129689465750574809132704435880555934179982890477462324008677572383288884814895110011791926482050393686615777555267813953119757833761382418625957462640002161556124407509160497761640368538908822371920856897479856609541046806689617094007609382893191109172865573828043802146975290102457631959140649327782056893557418848347910846146062000172786782207686589215174253519483196237070817772446540416808602458331733942031860351562500 2561459290737173773828213013985829772483019667834610481987407144920659113736591550587358962563007731075935141304815803103123742201579022100271740462765197678783293680548482922517749208875558882246593885513520479291379075673481036947722949511802459587742022909447239853712823479965761069017541808133062725388762736283016548269271686142597639170298053244593927263712885730309395440339975336122665135286972767005325310369154339984001075927029568376475141867785885802069995170060349788583679756183451447658597858973644755766126577279282794513707559972062941975275751682213459619116163474087797034587847744324935429912477866322146617300680908884986956274561162671453874681086729630433683850803910284108396412800364964727191969652482064615522103972141323481441371666121592837756414520414851904286340599475925726430693331884232091650159435033261371974420949890074220277758356506287787810589678240807916907153749069290767182446978327398519843040312166180194897648170294632293451801807023537153070466733370495787207724242821370834988220678612932539085569882963966392708243802189826965332031250000 -10624445832710200027695522334787324440923744193123586359650315206688167563489180853162067740451333473526747426504258376860003183511280641794232134917465159949881079729221507929273811695473872905141691432288112168709237541885188248471185686746438508785833739938945902342544434522309524948978155440955382804197019149400181986862645477122018904438989859549324636257600641740491030354768338862141810678364048622104657708152885262835659713498073857091915226256916956379713003007692498033347283983722509200528102547143351542763951464103369097788421351766483555789648601753308844568461137116597693877506584701117518252802772482021171004534840279574936637358393668838394245553119941547023037755805885236941086764589737090728875144809028479311805889144714486421853589822142916186687111448808168516737323558639546641015736247063486054930726017973044647838027109470064972220186253002567782008840736713532287135544845891647194271869727933295497455663266862449197116739230320845184830884951315834954154533695017737658527653951056137630233933335456359444407990408332231879739993019029498100280761718750 15214733311941166096166382422087218348811244248697851795392219197456409558640940742616592983465054617272801704928961139742987598455871882833965290771563082064020222563210326138317205188619297910908018028148312886814301381360523171232483599351771310334670257170680252264963837646703219496174711530596722654867815302503143109055099525887548307871580915489375608036392551406379305541874429697561489896705097748054454018626408295294069034766659393935314885692209166200952620046559822845368621782192967904780741657364571377571604968578769531253598596769937462834839437604019677804453582854464354628839201262730039901006520922476537719569967554740009667068657591591928565440329299790702324707018098642505363042865847037012771910548953551301020521170008734079822073878660964795641332930466712450177249637313805299387527121739934855656037413658236267980889491756044517426307910507873526421481284825504871392475203542488477646453688574917400553397177396691032090576793829342119512513924250335858586612571316393698817058140897892736264629086776382991662986965408776995900552719831466674804687500000 -15968274849920014048225964135361800735686600921312255079871025152449737815172006611938586089773123154721072910505982762758834352115766946551945850034980722205425546764116031505631631162173454777848785608694491181003606927039566898695101751578259803203685375968852052006585421087868655062700858099264085506226670748652560220088965222442891566231944307303006459736240425072942552321647999410457039619552915077342037364276967377634330611023357762965408210065932018116644330678821008269698810201685016686201950242051639850390801186529094962978141647541187746031111869438210433083792736403874451200604436470807068997277415616643107221945381557638368137316016732887479095912818647015048308299995070225848388786934398077203748624734508386025125980129515254851668306166520335830258835941210802662270364419223254429628207495324146827635967080498146497089092584351459333234738692359923901825326944277715594037587148890008123327601883065152493752646055776387988654256131125985767725011422451856125138025490082469045701432175199510682381949273539104147343059558750155702000483870506286621093750000000 13570180984520843066985169736012760957372873532015506509936220028992360515345758864966020602747364182976638425734238836597183888142054643411212442616674095219130895375235580713830908553191488791905229328688158135981121385228334218953872007630895047728115369140511950914762387780828976728117556389621095458685492977077571884750207838866029796393428912554239483222369119307933651677518910899024533945365410907649288031984326232705314685036939373848241298519410350746265635350489926257534600827164466139157808918401158624787450525488434771151884075725647990902471355143595005546345423467169242376702620209286536755437754192135030954594611966881503728545145993801365054043236948763264782928958381495752394518472881850793190458390541152937216611563079592038126654792878954901783224089764856419864881508872919100078532521380573519766034391037196835857874604335121786598969114806035037925924466900569432827499011666972427493274468903174471496478063911150575632280970746197736309208473079891643152331622542966325548421146798411589902876983905703875323695006827051656728144735097885131835937500000 -9205731196255383545928623777071321492124288147310524545144506368304241022654129702436595634872539157246150502241060305004916983267367350623002872451074524975392806980056026764313768243379961787097115159136378858317732288975655241000958527152780947408221867180991147329830629673789188015516919140771790670248825812545036720631528784674120398184111767642550237153718363396057117534858536061587827934688280517076071693265116298300600820629239006066781715943303299404009600548201434779958344222086653909461444462132055345640178533045845987180426144789686717890237380301404741304693667875520008946519892744534316623917464121802228407609457213890388289640517715338090466756644716757932485846741549952960707421723903717321251083967267942047901439724363756405343532412397610692009504578728343236211735049986250391236076909991268800650414628375193247402293075835506834624322578742363768188720168281063451298997039558826544268565602186869411219511121855389003139172084674961541851879358164056645672233097903245502819759198573425580504056705312647260804753690521806674951221793889999389648437500000 4297917136881674600725043519884712030075198065308311315501348884844279522303527940178211819540849943719072590324282722560900549255540998056077160758181719913182242286047669838288761099020802057024906524021992797517089467950187975719427177780538840883520899325433332681704806746313013308676856928161735528842426103270970802615653735279076352975559614410358643850894549903476881788549449357978647915080445465042814638218343823188584188313391042028333392507269798942626167367998092903692928449115442357876817767068969252630738139560193562470175463625459125017548784377741218095385321422721016120907347081722172228793051416394140033819903402383513755942730245823707401300610982398893849134973255819883316015888773505320518092063530407871787533218518983886155451074761336376064888013823822267886381710269884757623688249066646691667195014933776858032744342343478743066950963839759292261808051662339446279475261060187812937624355353241153733870348356098907754888874163630441106074445130786643871640440652677409209335417246982352584265747267286189494533976684920162369962781667709350585937500000 -20619827939503492375538477011684968171667318538757866703998820470076246416179445225393263338779088940219240088299414377637246731345786479514067251663650354181607747589719512213527305998886491961160795353276454125008635950633930106294983928796229977775218411091459947916007157713791190741277707698193114859149532466663585126050548663936940542419983250246336035079514412944587353912444140757092472752959865067272821013957625141008652930563256436820504783809280951128091462454921043423730091606137008504152677335122754592736006831799592139743760999980835143726400353292746923883791506108979174219735767973746281223069328617474642711568156602113857388108216100249243715331990778458689158345422156464956290274462253357287772938330068725282840319189076051135033434026536493740695371010009125440438345402445969256743601534408296326385559329935049558816516395192521523130217914686250299570800115761710737221272486824294363328429042920795936610574672635599932070345147369800983664534216630475531389822737244173033418865687492146763127538768995132990174967702046160411555320024490356445312500000 -2891469562579571185712659736492464501722506655620651385714781712306650340408786829296833743790438653222130768443530787466412914971897390160754575481001511626045830087992768869269788137623057414487790922428953134232680718218559323577956885192560028880122946290594741909540245599101289150560545558909504302293080740285173621656895750996211162788843974974010095961152948014908056205649709967708810468804698803307711497135552069704379774744590028798108517955603218985422195176571326637967262374178065420880768094634892660186117051591304735794595103002343821852466043340911561785624322955415454693852558808034326807084411373742562578707603096465817175497040525521981830905024205589543362432108312344553981585464551515950012126529565368066939966841382807349833565509792224176185879030827389155401474975164683272291747319452050065984084158459601667397698754833894434416848747570526316976856542706548397039974329354775992641687425401173871791121499818153541805298949985414791748632032102136405217892006133979202164542820230569815748187105248859522701326829619006275606807321310043334960937500000 4236638181183297035424490617854666016088242802087200214357437732812454719340000404049133320189007314605161967447769461544337380754989719589242083027591542785225194787189188110400522797769735540194291391393508758372119528902907392634509971906585164227105662591050695669176276925583423982762761513464800520084995454472503119415016033573086463140755582279458239115098638478723337213897381687731008947642395338844037051084137914823990803813730514220224927461037900728551579295727870600308929800928580480419133945031275511982404582564259976343369544720813920063927239884726166400671819110278536694199473333954761417253683964404376743041276502586698891814600225639715822845234876375216678689700708767706843809792722696143963012909164414516956915359524384510430938182557777372229269537306472131453479939763342224432965713635645717481874825396609874308782595434474098860812226754025966525057341856373326371977892832347539037017668746525789866399421945679571237661656229640250359455064447064907356381556732352765751295499409727019357758992436156409333754269130878356008906848728656768798828125000 -4236299687185263133354064180038061197099276531794802116930429321045513504369316147452046504215923068560167487880415334695630296737311461964194530186661560053188693412751093259780294466399552049005748702779635120448155394394066649816232919170797110218439158626570839156541756686248132585590849358159571889860712292288396504616160643509849204994758698944081601865216526910162283639229059886157343525983004199053779309014229251335857293248363381596980234186783867800825134817006856332445721465208043219666859542409341564683092276538216067413607761117823012830058197023785869757850216172145105920018087179712051487935611348342504523291545199424265532602676883747559639469814390285811148764238398216932538740801777138751887066860699107873336175440308586952698180500975060934752548470474470688093787709828686952233704426833147753187643322012916851626935367602403213397343024692813749638671118171632318209141815045917951744341505351681734107247400376793623614830603677387718413363046022830091543262944090520397687919447164415968414257324766720297620076207678607715934049338102340698242187500000 3356044191141412370044737790022227472390821719831255406899126783421431087063040563490116852999260002635133316123149160538332704422080698081136136162985892070218569335089494520722019794454265107359030426942612007799552184122666824431334986437398535701650795358058776719557407350848009543853680705674129056056691079329816642467283417310953461699882165582544769187998872910110752907693038251162095054116143323272727911645667302134257002306979511994732162802755250581039970197570405715551472243529362980510960176291739735147755922511785948423087594041539249055451657465519097088633579107226962738167670709033000918626301874709843217202729738962103621543120239164342189907445130174059118034027891011094051419067410478159687097514348588737144797616930080516548161170065374622453580008108044253928945517040721481324839782334587512781412335124974526024192026624185520923299304611723956077603355576897349046270548733753639287015709366910855337217703533609206915765592347441755939888187278595980928598449977216367683683652392298444494591852361638093177678698886268193746218457818031311035156250000 -2109542268320542382637330806583483806533589294839778838277841780176107993082264021183974312836638193789717946803403733391924028598092613459775238646229885809686171125117871593604669756569784816047939251964376556589494953825133765429389568183206639930174651030308465054727036232397571889208706207554097994391909242225076135670152997322375765920589484291913331925285555743825014504177884929110910489033648170206637558116991360112633172108981921063824360200981759683220116043513053827670182378721325725969343052883247731790241169623037551940429462744514989428768701996721871182569351762811489562193779756350810468160520852319293143327640446521237430819203367267568716218746367919290815599107825862258959450915736346217933492294030235030237026485885550589637300764511003774660169498794099437310327225352817171736876381255373525885074523346270634545803445557011496812173997434648830603212632423168181331469963392025543754025947875825216680215945656624457703773148165400967973128019062777038565440142716946987530391192859778458334595414345987503691032260988436064508277922868728637695312500000 913502198547279624096443529972264493476837151719151932543111929398459305223601200564588868810280877785619284007775644414149359658803964961231531471273262531628318194472711333009344540197486558181626605821432298441811766999778082265290798480872481162445382600805886883318472179056893028385009722775971180861486207813544742880696245558334327798073795008646465146507276666536196722800053056538241885468934829410551963400819517241826268739725177158837627161000340353561725240318587152196884096957739983462033844293614975845996671033982029504843658814260616831116155385319479291101553389277443833949982829928585322815064170750457380440981846816231685318520366177381073949599103387620933939765535920568353415419071705523090549741534198113393730412670082895279694618163642403529499028939453768431148699157703475927829763315443351249014812996846052742677148030358999960212489145830208990339996997127120871386007201602783426388183313568157133615951732691070926898722884506447133933029929120017408938896307174679841843131953419983609455902809772209456976033159492089907871559262275695800781250000 -16996297992703706145732045931664222431482204055239135914553357007947430878552771188063914654250338381319180982870331233489208277023464279099732347653768456599612742892235817447854099392439588340813191275709342214491050576347842891819632973998505249903465788363017482192757427422632837881146270969946066563893485965962372304820709810048944324162606069928797403755519866423421419691093290817655028177051299900919557893978314136103471718038181887276696834866572189925564486373139181768806877719482220650244452477668882093093935858003165201441466690898823984641494560596229111898220998256996656327220129356395286315171234881716304500592354728719002421544210578923759457331988537289264694285043668292812528361975711124131515524903138806171376938378045316938556627192090886183970792208177608627481437036268784397481014370969525782304251599216862832793714811200381790167875705906403641497788776048624367933889868460245749957198320761765030223740136247218166606418494575028854980272113250254616081559597367950321228448590274352172938734778462018578520931200159793661441653966903686523437500000 -499096549007706860497853998896964493618423900918280944664700880721211615427493337215248606560402159507137061781045730068124730134057534860941925566102137125844610658184854134725394942198257106099837665937865202833454286858549892593849355482456789768392659205589944352649866673039135927469956646119331538113325068455603151944251860209217664637956645702500681244118752732328952092321493290850221675954046275546683243615147323386965549374711575428174076216884144715889717413690605201674629545805030406232629402892936299981983499867747224776877660971437550607458074511816935337530498442544330042646434690615749693021204809276960588294762430978456790790990172230758643278634245088751017914945344841855148521851032696662692826460426081204436343894405426750963360598793110209249334650507145390901040420095514587357707013350858124409602586060624907782644725425009207167848076612454846792120240625092217725802540101177772533467188435037203233719141736924272166220151848758824740728247271505959512932341918023944503212314644645543330444782794013850813277799467471140815177932381629943847656250000 677766220158612440595625654503151835753852177039996158886092277310799135043886886537248238969061220878437414422345390293025240777802657574085600886879631052189365868299244996678575326294348993531240167960734214193419772069326947893043449695970093162635442528433659181907567270532051259927358635295709256500470897834465661278003761435049781963764724949113512315363888363010028662557344179742071446518518866995363659896127537742427596082111065221084975657450708002794971410416901618870801887938900728208782311152105418793433097405072629396216305248679696352350315908631744736896552127817669135070449090421276459311145263167895401011392754101542173516206345420886752858171112414609242010462211715534882872580340404067645242834316029931884355680144868339891891676867199451940709252658386905988329916855323058580338923159261292631366123526135965181780621916283611475393343823495400303632357103588742466750827959022463914858770328351984066691560880683770061755400305049085430567595080925402131074297172213304216918292812307463176816173638668911686361306934145432023797184228897094726562500000 -625240236015624515683717598764539953452491459953291066224053594004801705398382529367929542139445625479620632697319657181707573895978409592333078466592400377297733889564554802908488337667069362291718925134438974092818988197953965956263650651545718682707249033752335944736934749227843832462122217576805008212692177170554715110040962852584356195702276021241094317945289734632782957444050214664779524787507591636176897411221676392767398959250986361364046985593464961844340475030293245773648091847347643707621529655097396686684790988784762317313000275451826249965132666655992679925199558753058532960310979511047462946479820109489384311328787375293554689710781671941380782280052222556393172699637825988708643514643931779568869850488223276678891152264233157206594972058774076143674487196882704013624690850805794223933315025387332791562286257779412575623457169370114783752779400333178081477949775728241523052741620474784143872752901317043823341932720042158462650444052430014557185639685988647827612670480501530645268441652448139651319679355705380961218120550171306604170240461826324462890625000 457796353923452296938084259441300056090633077039968975534379237894861820777763600187218776738547249550107992402399501262419951420616362205457779300284988611914029259298686815417005792116898736937920287695399245748670417312605655047962038493326649278616564994572425198419806477496008576123838336778412650533819560684870649690404105601417643123663355734155679147018672741177901074149712849947748976471738655324585762080358158631786374828515507678248288627503823505433484065027163742782372083111685972726245414874666742707881887520408995357874422679105694661253997154123621275695533495590162402534015991643077063336141620889201298810315127149577408548335148967112944298939458540794448101134717470603462978457352966770795076172369726538624823905528827044412639137847633554014536724341644764236471151975041670121416379663766234676995050226291898006039245364191522328434897072959997208087031603101054479920772198646085671597015112446243593443063591838307645243287352645513946622165905007110360142241312683250543097557019662404962925631628739662083021899618984207336325198411941528320312500000 -267811197455565545569226276877672055616037683816916394331078869438418647568457557763278000900677804029069818093003591324331714854356582718005022601790994837806489081463721314536192918812814773426800694929798539383496399958042058455371820249237578898611599328593272552654726247248782740429496201638923533463805740782559715821332629260871858846404556280272784935934386287316612273834418303081944483526775981722969469987980084618405268389736479758768456155589802191096011217488885014751061735110182551968594401062046852069545845430578968358403967237913712829553405219027391053590276931147983883000197406065628166589699366503942267708249693780895138253340791943261840465752164802261361190839908984511588741065938384180370340140998744647930777787976130682736078168425103631835598727318527671269322704297676256682476854402409144335764328195594306164415411639779390311583496063868805135629676385912977206571157578230005823643672994584363428540745867632559039177751604525522832739592388427385832874101147639118954790404266044010355913512956678391909587366725986612436827272176742553710937500000 110739549126836957155158662405744718781929677511716443345873420903231750909170267796128036320693836999793447110772370659614000359467587537623349409347826487673732409074331035253970560360507662339141213289652224874112831245054732352634313025168976561113968694723690955935408288394527813386147992256910336048958803720361476783555053955947784626926431408644472062617712426035088644779973822005138992387104923077917220631339876329893964629257303572795253193104878904595051381955457357565527803411889334647434788167622052310978749489793217509452519016815062354917103616721003074064131459873494761406181601494004354147838585433061354344193220569433116206988050574842667157915361778128708763840946464477889003894942303445224852739456538003582301617445295688581746410935593835179039690546216550439358742517468547669231885018862069925639680397745897129854881127457598205261061428051222402365926377373318983865069768011508459678262007976535193776757270017625966838669866930535510244980599294638576422956541089129196361850104147789027620895403244288563576747108641029626596719026565551757812500000 -7736526611938893828756692228285423338812513427761180014804525876624464474591416305132011551634740677733785652916838685376170845800599254881799734077729773587898980787881043266576342010642329610149879835163792983277485389188728884763537758230316360233583526270565314666683783274783866077438402633378994028008242240258744357004436263886289603921690821768986079042568113360277302858106351718400336280186098359713601174576071327470294283925403285580215766753448087033081122689360574747297541835595154094622544332118739290922422170460665797144368574683543975201146593067548518761888254839336132588241960775754418019784291433975686694210449932209574989526093270261135400395888582134938728606821149129373444334902250445736921374899343934112526369216205661887165482236641354937433500973934283782134375917435453795589218658656640237321579034097723406301679500950306636812023297119093778828971297591780653321277155395755796829678106711854342938744482755225086064353547634217027908232082972593015101676640477549878349803388598987238446474687004615795882234152713863295502960681915283203125000000 -43696670280304105493545647671849444956984877365861760460037973984935031739645988741860961990995536769964713095762123058559954697376466893781988961338553227263082986731410280324423342943883401789474843795640817696149757952367222864203808382930593661011957305760416870081376366389888515314163744914811455379058811579435087907885276479448485581422075459238877084544562263439447929299881965973527221444341175583761264591998056474068700599839831951001822630365151129105289835863591223455156394621675334383215906421808309082927048504539848245486193654237768771752834410090286524419010298146224939738811484835657669750142951993218885860657136387520532342603498712851765647454386682543644480924970755142597038260031594963716665574731720670924158146366624868419255757708864395638492662693178153932187262200544784398950881484294637870023143102005190951372681788482190794923422067077874357268600846703681840161815976584445748842362725889449678654518944176398970164284116108641397641695815500171830648082180903512271255035497047428123621920813977523561505433846718915447127074003219604492187500000 57664094515987171581318307243606222266385480444309348360341843057525378952688030063444226812332340186248211457352292579680220451226328240208384640047031094196312326924808079328996580275979725249406460451119303066874292929234986570112146412331861284272716984518572764182995466052068651720378694439902220095942986940674593422127575374021509040264629756210898964005517738646825604873920297434523756378936284857443563852297847777119530125710903838810539922728191550154591972149510204475792800074733210378113582006534692934175685023588784227033608479856208958936920776581213915714792627014945940840211057139257193462566785273970056926023975893347371985394080239183470628243949634777462883219532490956553701613313777157149486974962317576428453367665876607812601572070273657483443563593886786311915668807365653875494780698658922683263557257983333082589775753003005555722282314920206611293478260995952058510941374688882473901363172899278102029946648053407369582600795836237836435563226176353685570980944111389321376541502994353214839778009969230646025728503900609211996197700500488281250000000 -50471618858202569482597277384550659762827911109120859008820526770530287284008101575295717821568503052545263547810429700203853251937538891003431380619745815614833942519056262496396778975634699407590854095053757120866652061844368065847025238246782633092460480803706865956367183744553247231342271252295771580136059829500821016476039136601528315739741069078612132203111146116889089210024516700230262122990349974376249396203169416771003861676022968187778562560148875453903428284924322458563609140897419164587368696377206592672112292269870426191027742586176703905121732286156741391496883079646640303248887590876173197087141145020362484519718498183832309302307935831492422844093260572769883516146620750868241620144295059923776868910590171972158697356632014184811934413623623534532933897818161023226426456141111556559074580326118010526334772870446137362288622439207877122474218927609679592007863740636648550607638535427191169077027262185724458414466051500702659739979745728786745855544759214351165916204160976494361459668547648956990343341345048398111083898243123257998377084732055664062500000 35253751496979432971935399854475671438249352215940821011873662093211685078514473578382177485868827101823204648660486314591602104988251052817798297403798697944057204865091652655373346682268896258576263766983102875828956552981083468279705271438338806784238902734917199792060434420445409624576636113866503883330465019881095043929288095525002382919355005318183743701521121867570653680292696660658981580861361436627846727828739757802665749925568228510777550815237344009701294184468712135825792385081387680661256862944107302237395187765069698455874479382761649949638120936071892977030269308172722949953656656322260534427853027290315724715711465584901747357754179860531790602107879932977385937548878834199792117501380425249499021407928378061365434564590551088440694483116905280944818227597883344254764504631276572342948470466387927655180699685270424164038539354330167540233408271926505594524084549254437929544411893797352242539037783697045446767650487387439979620709497253474561555034843512091345809209046309888799933450921707607652094913030548016356913176849730007234029471874237060546875000 -20171861485792320088736741486596403104209514698620625505783794098772099952639759895639571162058559217711374000859268364005373131577830386950689010951980591403191424238179008857501366360758331537201596793554410420378300781671351772805667923104011452111642422094812570966668430983254266396121464916021907672088479296076644200012519706925135785160129109855669000898611360668510510852975013234318224995307132089881069176228021452761874427263506000227901790770734135106192517975796584737946276650008010632981518884711272772246779799345373682583233330045351306697877418889101316718683583105118333100660886923732463345962854779153653614161336692668370117229749936454557711988193221521706939744103564577200142316097889854458308441753011301143200338892127336693647153684664285440736204974962941165835538241377543005570379083672305931965967058217936771622031033678208315419887555558945636619591812174060382931074462405410195553642770815745065624628814914070702266848160182688253512330816862647320484520585504450250431069978035824844655114079014902959269273097220320778433233499526977539062500000 8899916737282774730524745953270768755826679664577731323757195658747750368754078976763262463535316189262377440500455539545064261919307682315724159219513841574162389735560527653214533454782782135392430662305894106953271059097374150434665088502716688390189075829771315244549991853953333862935353713890810817157527905806256411810911188175989918449135160188831267671197450416523987990465567033027473276892040111805682287775897509370180173562415165981401149345601150757945340227593385081699907967570392963280806672063007617448502813264349690604621392222368384629791930484383574034403471810940507669603071799763597460417236877411453961323444898991366072345226187774569441277215822828323670478240184078373721956278900793172302695605353921119062924761880917946212293682135311805216758705338987186712515541197593252999693503377173221560114373717860553298992511599075443037310766405622944062695131878533630428557053393783115240704392402643706673988245048757119401741290469544112847550210046522601856176252797232069783922681966172280928459061367024685376692083593752613523975014686584472656250000 -2083441932162445658432185398468825949837121774503203603303504840462442367052631193624907413587374506908519400070414537878980593233940374287311660573375144052935616820512120628944777819593958553336681374409162827513235201044697924064133904687549473503077282374030235952303093110987776214135778899609037490477891096374276699905799538199677288603435156124600709443629637164342093144925144475242023383805457036426671025484270920666967039638257337966100161817149816365867340101391037857645668421108297495846745921248361291977185809395322310382458981321503028469643944402952074797178948027476150333308542542645416414177024645800379506038687791088013203367049484191824839404824782696335396949570043097915161408578882426031429726159470656768610249088847588521088883455315969101524144088673182584976131253959418401529778142896316778800127007715222456152209275989418199429650267198957400269486417266296727850385501114934418071184379567228046057586206507185834523913667054421948514207152174059745551367477798066910581548423009993678716799291336474447139393006978025368880480527877807617187500000 -1155239241269826897994385608754664274112979005552104735165780284129065787745987550987439901480102255408883040161055883766576789609108309013608811645164693071124756649393896551456167508334252046672855894639294754854451669460115682479115019045518701869621496699787970083733825632453847476575780613401420642445611558517950076467056451769613895243508645946288456515861767506414981343277566029862612270683763654302584222456554105964134222207989257545332530700678815500447460636736368875707288305538352449244249580638507211954867341709200925907407858074835973829333439420558204689718817439745166831136086317348665658799163961009917272111610253017387704641497495441385353665541612551326508380154389214610369663265711157020415666106347545724262855516265840659673388464973653240457614716326188392067741970541103955754308704364038454729283061764629042616672145134014675714378836890587444199257892213243392327580930656966413975709892991741663970650328397007441199584286388708312442672457599921405993719574983219802456536910103592105884182063695481698997746811130582500481978058815002441406250000 2120119268382022786772892103003816473973308774741269091009368319871497413565917387692014697527979159412001307503689830157140446802825961489197724434612717572066827471467272242400229319797975047517112542418415092879123775893644077985038276586722415180007675617584594994337968257375836036581151439661259110005914163111936064195404670508329038914578635301285782794505940271232216110534525077679543399302721959394308762876112314422498461441042371971926205550926055055695827103939133277725685919633332301158097548445357086690646233857070712205608754397814801756114585139181524993497800799704368292418805807531647301640209670795683414889692787158188030899044732435324197738357992398249316414256357099863617170590803300898396038032204209699045225676767927823449219888567108698927567652237777621599274297194230195428112254523334017138665026725382662600810077636275204083584024615752645684717301632025981787887711025217003293803683766021498164798810728480584743487672377382766930715064266432128769834728842402744800142800074186296079404104556896584060643462521511537488549947738647460937500000 -1943165145414429750314869961352790235117919169941574798784822326416555841765353824160160678026984011451006421971401850708952475780659775220960103303039180499780332926732241378854533020544405508337452981205264996085105079369956963995799139731670619584558542086780791555764732801261513756421796652033614800970991448063613354402818690798089924849023760984307634172594915701820786005935733772287089697964968103113293182481700360001816969001676408063337223518911427473804547663376627538596614868695935617348842477735995656571597227266207010546675313649373636866551698267819911140135739639032106064016097360959979908243447297765027090065712113737609646396749083095701738844656778885945383516589946048314641429355260160054257607159680483941561123825149918079149278068102851549272549415029903004035286742979155790343825705484708611482771611439182280379741866964615196165527699284383386978423385544358570764426571148257839379676186272661471557127190378184469527628958157586922803078532365104193207591513843502355504109442900341901151085187492655427868304407468258432345464825630187988281250000 1377387146874105409691930167499133224710946933214075573885449045381268422088628905540609684249857104013196054761459650626243901062392206433518860007293438068360795672976338123454317932043735272128921850202892999747282940447696945323999930106171847681686000640097378700387366647597795752627832760661141358957966202313195844088200971328131647639935562728933000581910946938128583603558298472304063660494385056487249465933779397683791487935328541029964512192199806020099198036901176647393105606188345263310880629166187355063495431964030283534130143259103714409738537228236799823738230623264126925956079251324329756590061000319366862600594251466200089193225417829265573398401161724124853046982934708759026484938594781640422425298673910953136499903045353744840472393263434986326410310077452817269147435474076960843857254761195466156919053671488203994899908598656319946551529853629793315323660930240693213528543657432410688040306032345459758698383443513025787862204046173347268859350528099301862863423109606807371564223431769052334019681449971388847997033622050366830080747604370117187500000 -817484380108367490762736577995187283193590524611793212715423071776563767367017518133879701827348911069750296182310424833864612305917733218398132501755489609394961235247582927460407837187482233119084941326680697328221578703109635088460055444212625869020464053235370868494690295050581743334608605012593228477022158902631492148136404043461814659899497488428911245534160648484357943364516133469142425187058206809202946182842163915648701731221433796863388988210164846198904654018382280353045765068456825936647407113450790780622822703470844876276563952116956272769758293296755998347822317074418449881571264961158640467931018986669470022957659206817978778692673118504713823853657336933066395239156621535616732294577269327169120311537674280747987981954834420449687144046029296167441626002458941889435340413096981916580916186590902473876807248752875805946355461884930391038632987795572669221230592229678994225031204695351732984084405607199035759849671869382445236323080655597907392087064203519497685219915090087698770233910974746484626145064553647510974254686288986704312264919281005859375000 409526034407427830704146601359391410098068436050363190930546409020479822808304035566600985481087232971906536916576747079138430544232698906749611889774168563522723221714678529752670374205027969415928502490769807934607686457802270504869107006088871945792210196935371616381218459546497394160747895515622629451423023013199081777013938251760226875645780437854197150286248055384833340741255581270097507968435458252458222597864412998025309900647912161781605628753628565681046603708712798614671549840936314751754153911394931524107074634075546218996950486416844635015582577354303790831248792023144185972910057109064747888153320801684280078618599416205700646268448434759109925338339810850362017018145539141397401105137192010864963275675903747920607143851267460730282704278199728150436160814633438263458622061132473529097706968573309761550451648505455586975771233935411656992521897754880939874068126865990117805675549219975994900816743191366450699649986300255243517634688578448730134534441510292221507913135656487247548076663316225630724792679769868247730002508433244656771421432495117187500000 -164827064990106242984458790236798686545366081731502965918059200286073682064986983349929358322469377858673937052085547904475559482684074328614162954083609323773653990828944903269127473309435394838289386035417864009914991511456348954608407045969320238248819773541474165547975402167229749235531304192104380207783274229883578197010036743285830597124292013817514441635668894368815233877543140195144901570909886652898742128556677912128965861800411462529550538866705143896869630139671357018981993841866857566098447890142651497755463267674145946477018532142873287448447523559333765888054509322604552308031140471820420747113880681955553012745113862989802809412919817034976653498585022917894197718251304316260285323193246605629700139534418425974913794718948084582812888453458852148504636945679514029402912997208071874848986296018696026849752331230273235983412333837474511721556958994102651586341231689995810793904828638451981894245942644393188454038920680103194526700649296948392193962617172464813077960797066681026121545652931119946105846586791900121315990190851152874529361724853515625000000 42068199452322987862570654698415929131864337733000311781211456976398988631716323066838107486436367964261725400544762888323404374698640250333316417192035346748738912588464125237974774595269568182995989953101581845968244786139256678055122107679416798528586001038020723448969633749854618985906300207385628430042355200943142442474014667927776362728616168933681382899811415068071150653345147375600513349637989185749001839201280291330925186964843875911924255232620177684115437574209352263762782576073441752150772650730773406574917034824713660197654576440909446418739684021906554930546762289591189065995193322135524809365746438504212810058577256866022428840260359117856967456357756029064590381428999416963801513492611706980856917806935038864508660313410533294797595607727481661598801980562207491605299136593628161255492543441895552897168540620541711582283125077543662192601159868587388439602839575861971902702860668703214526087209988415374729979334029585465262226443426127017563116145236325398230056515057866593850519124790941123145585445826290932336277705871907528489828109741210937500000 7046757321550838023739250030432634589004740543319899243339343982416467477956102590183359149468589256435048829250433236616476871055999558446571806027078560686733441258441208128393537396003419658498347190376134524973508135186834461167572292940945433370843402858329664993889387732571925437959627630438371450448159124054389184647772750226313765049413508330460961914556064542439186170976812636177880406535920605318275403754707457615830240409320993498726133904453019476973064863105393765531328069840410304615139131463282657101818057167476524968982220507415891618425001717421810126230610032621819118028649803129408819098926431732835636133300224687086763193658460160600896954763168909777285100178015107940645727971222262258683636261463406509935379607900180193863589794965295665463450876193265458917321851034986649996104362144205970710982422484936624366985630056708437266319350679106272991644488661071618134013609713908890888798897130843500662395712570100709174841349245886384053626299063859760161066594817084547728090631141592676339285038265933952539299411910178605467081069946289062500000 -19336857023678507168373779196202245495016613951045806966493373178318415408807108540237109073435781606933223138600627354952635031893101106313882358501753832327137210890204283082926888640571105100807998209282479870226644486694006268004167367699091882644560222038486136485664331097237006908826990083763573095801518671598076151654604156713984121549704862976117129685864493908051167607105549238911302026415439491228099587473839048868424056654500577380189062847451664077086331781902368643474003272975818098953041003317128618000395187991944116731207194981409074936595426488919141509199299278641891367883563170961582581739825736360401945294984794341637894531995165710951117423953509233371519042884375287622351121500906421667539679658698124014000064300997581167659551773661257826748692927269086475388732750759246312232142704777825495760763595363621192780875775063034347568575047389619717783486682015211651414877081501867083634808807293803600857018599270646880050993360862117100382835680369562086315849516135241027940025164493899930067855509488537052442680419517273548990488052368164062500000 17091083900888250328294469155763292615274931790083815126359860065207083911476533283025608383114220332847298324629782366180761653345738455838552967444764108002353464350087697903835582998317215051959585558565947854236966756932081057021924771300642476622854213354481043433242599400120683597782755526891427256048930998706172895861754412669406840197124265958211434961963002280787034247838517866184769293524136224315911682582291817163450731917945263331881047944531745241601548140475907853713677621752672143664492950149548274300427317902311682232203383781316956793726642507821859401634140942917877124884532080423656721749968570287055429584072278071533613476535679615449436434231648321427943431870508099776309055781473566181846996704903144687802213536140513143899613609949882571351489157722925764479737095040688592098955753065475753183670098636332333341641180547204962941295978243018478019837521071488862532056518741238321527243311706763679881533425723566316844884113712252758717166313918006795799155370642577331528829810373129053664527730448541992247513121583324391394853591918945312500000 -11360525346703157723331238874763508625132553134822556801492015204510511257636658412168716171168694670962630453054795239742679090640519119695527780185121190587154985407563809768828697551023820461577556565304106775206758613983884709755716248603257034134827243996449824642295418113097066125436555981763124911528612455924893495230907468753467055455949468927370903698989361855601727507740465568334656988212586386059140899286318192532768678031108279987054019471029762570427185240732212032169398135187900184866318303949325779392931365158090151855919843291500563683102230466646905603060524642304651243706866717342581200058335359657608632781930969707515884763917477118100854465224826964433843824740554478415950219868100776832471063721917377979777773963034598562201135110827641680431451286776370942750989866605938385641778149648274377533651077108473396985756817958734076996919081697746969161964196526678574655273089509365619614554665238198898086871121365494496288906855177788371130056809317082592401483301971178930263486844005847125059268210402804027969736466729955282062292098999023437500000 6412899207042038959967614544259395398014214989061591061243142394077844178471607836296127684038532773783869367995150459283427566244855767350878090426566268583750917527598375009875863623173072131330110698842041960222691269765423193147420444757638740828600033885299872762010760208556921534865039755466672343506034102481759959861913120859124998434460346508001056314434016621937391098525514783345530826107494957604312472171597240181122670965346358621586472911422035341883896114815019834132699670425571377707552252317540943535952109928070366513477062832929455207831916433344727802661708220817770185589154777353379258492974503349481396397549562934031549988721459714171837415402427650547760337504769522926331088462880264075934419675720687699447930799620741296647163645089588626947350364770195898486336042393345528023245083878298868738528112859132829178508179529705019720130040617763596656924275152465164292096485340758567180986107789899859003706950525800729296117770079909688967497222756475130969864220395760660267038563810737480265630678316981800463070229056938842404633760452270507812500 -3200665304728002597464163721294680600849727703778159027051735914969561795117153597803268997250906215406678814850802309012384526914503684602313766996202157560071067739081627464812322902774346129309179159071256910179323804662377799878439644963459872334555187662227336773781593338807829581656433060230733321830380940435837187974678510060445596849205921964909872030742824599460660877364494365153516762268835734454521687696113712677023711929317031380184665664071046335111279269804906813212440423517701426302524077783443934414961324367734706892530708591404976587020845941363286968105815381797215846245075016744684005411542151891206689154122777393666698288615661602195453406524525440731657376955888864848225325611116195738759673697925847760151962105932471272825192156459807399462909677721035559613571058304866151285117775043634164081949385322297598052096985569096169612555357958107562719540500468974279777090964683256911112852236199579735294628877026753161431151592326911530275296034385761501835510062809321119975171950278826423569475290056667027283054949293727986514568328857421875000000 1435873909055303209331594546122830426828840281015488166858863101851969915309941506990889651562541530099510691384898084402376987588004662856789592736425012402503033223652116055940589022687215060763493780988712998892520284225152609444038581537628907438344340273529261658401998394008179964550153125154834510662609375027112091332526561683679582900531808988036875421591028470268047896713780735620308377169923693153507176687628031372940801346019581408461036791095856859214515944811421241279648088728434996969769726761895589850398754187098423945832613409725873316022431231686039206027175859128105856866076978472607199809497747439809550773801615649675121173345941686113876632991129059125824610793241409174754323168153709354772822171829738835047487674990606430346606463564492361503569752396342506347057576405665131938613997399192487765251557984739053559401068270159422934262027647858137009811852037784938559539047857413929032929622485503389441918771423088193664482302911791478670501943482398449036957021034831353053561058168092413770863365732647319583659140107556595467031002044677734375000 -583128741501143383607850980891503299977915575298460410954870941199427636579204024792840100525041992995044283939051486957341390335534648620663759387608773702714861733347348267562470446901650869144942036011437611305135547219434726580149901396546614306119931967713364923962526746946523658773880023900980958063367533814787046912337642437147676689234410316598127227174022833146302541478818629115608670013868035293407370494309978218686738321695841454882383576876939789233478512170202744681826303157148565487810443289435706185129142679609037587608690132930464813344322270890970379155196274219680202542022174958564909796696281692016883949239011841750306487103385743478416073012268162538485120965767961937748639162209921938123011785702096756362139486868368642599387300939585794477429517303939465738345063183392829321874813212048701705730409401847355663915467219871890766499898342333937722626976181196146103803202237355947829783550580823939330403528065263138979218402355144427310307861025695771256456096409504578824772606305907523009242842369770354338243123493157327175140380859375000000000 215308113580232294765419402298834896080065915825944296850739567343347662957252311935113511646365025060298959620834592893737166259275692138650265631989323209297730302353214216064971995317093864289745140828058526091570666988056982790045165190052984128199389074889691803704437252692903668417503899801124941615751975972926897505062653270388453600261769186326003757935468819272318888084156765338427312487986786334578988917845787022646887655531400606702747196602536299573954906642014780456318426894613630238959356695010858299700754186495993641446191369991376690498705560154610807735201529312702890483753142508892685437576641786924831324891449082258865394238466386803049412659565062922406766178204099733017478950771430621742790162516779236860733402270338947203765077213303740764746760027743636984636596740274183677650827260114921898668510250731050054029261074029762426028027365294853251809487571138870778215177038295651465605372308786390186290825384401270524321770741600136737808231377800165322432930291636091275766352765910816807313170120354549330610183233147836290299892425537109375000 -72908032220785675646306017197444662331746105961893390087127396342292843707268850022877876272155648960409176172052759569683010218130094613389687941409922623326191029788308006148482316360475884388917590043530143367019445888524692598586304768282160952600876557757393901281150266920527943515158981604411645952656496071947482216525010757246737230321786707424758324484004548540243241290767935875962825786238563687259077865412705357309123916718918743583693149478746512162981957065294203493833669806840778350135845301381220716225799949142332647725153100028910572986954127070471120696306587583192753516453049812692348708705394547483508871889697334793036805307562605440993934320264535815924159006803433523459828057567819923314547090811833691302947486156267229082730314193648683153853751623647043573578640806128168190582295749059745639187900530587544226072985326971620876961428671815949334234176316615353696426446372702171880040877371913529655301958148412765235031462064033606732465948751317220773643268390263386758268790359835824057081970041901269885542546944634523242712020874023437500000 23242104819329038389739293166692853179455094786233546850686729238182099264227460386649268413274858961677809955352236861745777573955283052081528291552127942875110631023607988558132138138783941404861717538285995696935829040967353257364950539315861071725885578982748705905015115587740341988052874451851474366626166124491737659096428203676010882766414510817578271724141792877400894085502413179620295016759292255508687940801772451222397573915811641444889213404453915155202801586252512079195771378657606960861689227333924776160942818122580793340256757556236068035594479753138106144003004079463001684740038082162089155083216047954248534132051767390240540403057421778432872169181923861414198538669845556785058532358832763458112270732364061832149758377129892857972775327130750972912219691711021372227098172513738217711557344551217082063342465011751706495082610441671006162470888019478396215541314466717053754205284929278473110502285992822244651805568870322472380946156532713777686077506686272020089144585415924860544371889524562185624820978102449131608153720662812702357769012451171875000 -7425614909410876280691065207099223625875129991494901612147124571840646051383299100351867100846175786492434368211383114768679977322714545645958007262908892787273922558757083445866731079904727286817355087073912056357489564429495847961584761178473167265277227481528515912354593964075081153073971382918441719641314268305225998126062559145164616797954427562150332541600263155966725627211549804857916684812541131126246255748244392046409588788932634270886111466432380074751284469263433468967512468326982085331822235108451489403861571994985593197854504659290410974517392946574271215558922001905052687412443857892086325767193895238289294841618923655779698275587826458095220521818975488061140409931314294276556989492331959390469103983531701712689957980330623256821680964833261812968085227385924308185651038458227048143285061770669315334086449205784291895872585903192362917943685716826152912806157914204158248500059806917909098145417798488787565613974263356572480896986627703805037843372555367124223783328489921605646346558122341995472434790764165724041845351166557520627975463867187500000 2600769535596251193761568020148742440777282099936631202171088938497502192641401249828231867416149976288260459153547011675164095876596075075835287051317400057568086634340549079036014123933649636277434102205041077860395975473715443887920476074609446669210065036282208009402697237835871519993331023110644212414007979163671029311831798240712902051343035540522936609473790327150858546285205914505075596596322076878756621784066633205415480134999528885662016833171124974435381242608352044183728148936709602907406002892578606050250012638020664303337977499248948615674176548153550012255059545817798722370465109902697229761757149725020830782851377612859518757082096215418484814293779643172076970340707340163145873677122096716533841566754168491534180765113891292613699413802389118872473014287931649187465313518295604002213480239563040013437810223361830611280491918072858134377124906242108911065859380611194268095869850628065228069964205603373585163732588869294448091179425104546329241218165450366222180439636858626124243536888243799171954304583122968841379929472168441861867904663085937500 -1025330396051886984987371130322049003629049606011787811809989302058261769960060999359811926348348677048135046979689132647503086992397785481011151372316890538129506080000137877345649698044851575101467935341421355165682152031804681253419112775983511741090260472266482680886335932524160104099043931219358315322959096924852966800781629448451471174387508570983156792155723129161383408015660087725022876842188865334255656362295059428382746743649967487378764794140701181462869342210404044328373627598559420169351081706125795804230818286898047554709946940551732778450997774322991572468182562289799516623197091330864211454540348468479120049585254898245749898217051364659403903455194101943621944209386590677523042591763298920497538871894978170350814005539163884934061154467276222792119346022682534499013264090116468981726488095105749053124266543717288139840116150723313993967013066777851121983061121925462972219691665499598973136569603464474970515733901171278300188657453818571399527699196518811404587905630642387011636742212736927620705387406707664865734841441735625267028808593750000000 410676883191241203285899249401072180146841603327978810660641197555521717011096387740799276608839472231876918664789581107529267598162726168509333346754021968577637338434470675484190597679944928552499119287771391315218683947742267480058205828100716889093784759149036992353150659583844840434039242892360243856799441858002567287148210225760281833635975825179515011341492507101766144392184962047787185237056298669807327110928871305297674723812315769997318243706347725871106887002601540258802803164995344428195656788298461088938610898524491211281751683138530169563830616520336899616358745904486723691465283068447438063117246533737142699509961988960321362763856964098415705949369866223539720417634077929318217300119109222989989246487196183776884023206890613244791779649878647931088417140154151592052785013070299475333224279340470308062276152691652740191438931342872749131399423275069254562810994008829977573372651475899819869620938635703111995935318838368203609134229570639497717921796133792919243668579380352125376313304537267535997016685428429028092978114727884531021118164062500000 -139388505502975947607492188204051594175777621372828185871438487200533804589504956395385094749020429690742128798112637998733927289371630750124814931569207799243702650925145199513499817782419087126318633222583704625879876699234240072929135907536447023462773407918874629753382121777365435164699684085928125723611326276432951384739142696623277766060907926941051865441709772274408294318576828825516473118339234828475558132080464330009313053848987261696529280446289637023007589435704581388497942255787777187292365986839990587052769420003236579298069215903066562212178180825991830469357037702629355160626701672690690305069216323598953407847772933830849218221526772065031923716025636915942103125351656077662457404405147637046976107879013861579765694874428535781907028876853286740766376978496925469289992190255863628952712978462034834795766653692484562670619820495033996215048747704592324333507337932059284265987835316104085490683608077536324205868301242281619666526525097994948653361772932632807480495403814933881321623283052954554047634001812117077179209445603191852569580078125000000 26076846538090675698847803852153819172488574579450770906308783710578754949205794376246278764659763112706769671977888712470074531035039477954604074216362246437578552137831823938646925957025945091122416615102590547945922615525813261473071528459327747393851738542637152012919585248256263410833867812980615673731360749553634829576916356945193175297248919068773429438277651484544636569330525858812359642617362734844901444898825317303696406463959225433145117422115519401096770558115403672266021032466520769658135734054771464940241821274911144859718302155780215079034174134737992641793946458582255357733536562778125069188610339775325389063454249404451232397893015747092822767430004723113222359977313535574021624581909392683805966791554062119917645325310876783622264387830391934127480612363091713192858436186393132361988551840706887174482159231585215030163973826524390975251884343744379716358091775076450614194682824421164748479068157594723055337428423320152503577158403950109010408921395705699283509882224090030712520058318855512480874099881522631960706348763778805732727050781250000 10493632406057902490835245430780596878402612924251659036021193228789597834708069029985411451582501553868430275517724837681236338770947116451548347807191618529957614937012717622507899935139569660050980715082898625748515852355882601813365990101008717282276815128371214497151383333291178757179986447652158168854164307979045511228209964298118864877514467220814900431146402880098197707374317891417826201972617855091059430738354606335201680986226933925548274020892320238702472377070442679023336705944756776508017625788090699603247925757945607279401239790599262554506666019096010403604323247580045209941446054449476394894773778386636289188985232939188690040898743186769641583502828229274550299434354201176103849357459064582387408170916742390332186211811813907143890836248931872460268595326944600138064551076478563295919583479686986258060170535286572627695340285119698724577671357441297754008649685631128133503296396033336266132414755676069523873792795022932735189861594867672483370007350880212237019610461935852454832764744792213717811298068216530054996837861835956573486328125000000 -15082893625595299421087551931046841213971844925205182518403087266036697664217782731572305480626170440155603254138955260281255109731688459028724342962193607629783258368614665107269407048094470473904121364390449986311140575119867887135289484338161354771038407734662377593315144894326689583715368261887141594776936346415143913425538567097244498093251336679010871583110562325665969109606988954372047653178402674228121322804596456758915322115809665063566590062708287132299430565810796951046898151670478107029443401491396810538960676161772085581823891595088370897392032904672612685702967681704578695829047265779620766260780961148328042818584501291707821686861835821298910842544939280029688536219074898599232650235290974345805435907012135374647794789830660948697464181600757717200544312387713302460502634508624656890489724314227684137006601013471248400164268911665655656955641026535480965760327756411064029962242158918050170109019862843272233232299751939706434912402665908503542665555291056725769565564348331436834855538791923398440301008066599663948181841988116502761840820312500000 10404744493355789458842856731335446040295326229948090624070728358903136748077139598269230898301305357069349592028358962301699891553329750762250423853283489451971034697285263201515059582524149206703276541073831402401392475437364741229892896460237426981199725897933257574802043613850118793060262380456149150184182929042536764385086606155985990887884283017964050568783323187032036553894214232643116971947770143355561869600179255292751893293070810405057053017928292181861528574455248467966745658463364714054020800406521728164963246546578068647494326305394788987726959551526382197854624504450505876732041592056967820596229436552158113948530800840704697089722048221180704142209355795675881200097991499420617788589080155369202429454280316941899425663773588970048871687819945445856295081086498793599762845475524177056300067389275090103649677119323553511969971791186688094182483801895776524679385578148064172781128597339426627374771290111715720157292625588701957872233571556712890928335446076962297072986560073305883157525042931706147665560369119930328452028334140777587890625000000000 -5446847337561566185236283199657885435241192886436812459954420092673292343235501775440506766382497042935138430138174332259744102910806712554608159133979940869917191009448950469443866236509150818973497957319074166652231439110755981139806976825341081160332268608986207137968319906844766050586586368605764353111008379937086293029269541431044584035411869562747485643484285534325558879320142351793448751633035849732289481628283702305516337736487737136691123600936654652741321406311395803045104982339275200245308976704685743626286007387351530797478626656391167867888038097014244856774464862673239347030500681159118962731247566799666272436325219736675427296725469846236079086147957409793861938162990603834761418143493099852174095928824428122646488846652799947094570274723725828119219366249138337500865874394457570388848308302529324515983677019325309195400138574987606849069285392295045489441863898227370298057159258322735065679016239098948027446806599953886470971293137435543030560837541410675409294660419285091023840793554515730225488447883291920348369785642717033624649047851562500 2367462689601829289739050539051309255435572011464521103096727448431140499151991480655824343152381228513903448892213688647975033255429940435910119329078830056045390815279740488127359775820575241938352364009276461411660525562801937152142923224284156570144279110629137179442973033474594477307209365610538657962539783178559269206989594379048479596349422361870357100498937878098566672217990059545116082824502995957173837163085309289838889489924700186534877912545290557532052657545646217449232135617962402948714653596232122870263654223133659073339340241036051190641280057203445889848332972700733076888022980322722970572247471981293110018668869633540578242422702609416022148629366924864160744238822743341434114444056656937775549002884166047366634441626864213182649824591068426806313633080599138665457129512672904251185200084514757983445136939862676822298986298527686151192219319349868109622526288864389692362375064259614890293283430524676855181406250991146998621117557712943458143458954939794490314777895084710934636658722379525612866408429413311864664137829095125198364257812500000 -880754411183458869593320802505751977833372725956902265908369001987676955308801854481615717761000425590497555691877438976712859859082604456471666813329969395667699254468049540635254122762706865869732448083217613283254641028250552108446848491032490901155754577585433233097062160827759095519544215277191974466045382478348034233780169212027598608607353235138876701288460397380071854582011714828370863150574529961126842282584211985260700901531055987227728412948183794920219090537166010978493205536655967039474573005851100636720456985098917775765430116971935208968755408140947236264819649278366457278606011742736314710001458299048163669854975510625101789865831086845265421330031230481173936006716065183344697998854512931430720764068307396078492894351832895079982002572334680344732498261477845014347123703876521359665444116594032165724162197255885007623432860380828089459546422338345746219719183848888140129653287585736769877121833655810124711233665743461461741038688112729964521413120886439953381072408933282893593707226507087987925326798277492201805216609500348567962646484375000 284376220862812569641845867597756612847957172513361267954851132894399109691905383486107197133332829625342766027240395073754654984290074300067910179009795734798899721473374164858364078538806004403207658926835948388243956354245900892186009938389117551588405647133794504064230953337391135918642815915243768522161670525161342359693706460140532860105066140638715485404133125243825437518515681293570075591348800867998944741159472865616737309760344843390831303218103964328105759500032790960448215851088334274639943651400646094900550413327800589552015926822684944502668378000217906640019644085974319194592923467205300277047986982005565248480464884091608907634186427069556901094717860479741455123446514386272522907797841989313432939627678224192631670109414098101493335187570158405031426679791843779566688343401947520207447959155688859778971673497944713994754218220556282845417179200103769353851046179521892242710676825924065722315813222468978852554894589852604301168086290953360420988121163523731713240622037066277466836116095603373009250564029670726995391305536031723022460937500000 -81267959600412435553303616023797719720530934454199797938750484532747809447527530211252088862618346767681333737200664815775959490379033587507491096649552117792779492417352287730141630494144729692453905617607145245956048794186851625682737058225922811238317233380321406802117282921461292469943808358803327171643419589807795776870104951221727186790704171491423345181450077718338390775769180962439756232391714785444357932420167612367849658453052431772774453648818653691334228314292847437035028272191100254201202770883604096921797615448466157825314450525299727278530502011370806789296113444307338208694792036321456513351858492385317304306065862067486080819024555163273251060530227763167574955858377115699109857883274955052663308840320631477074493576299986996129256203233968115374616534642955213385076959904296424595396959805139604179342806370710922888866328412940329237384348816927870911542848725824268449875381564593660894797493722541403415938998749163349168460804236367900375927607303553455064760491128891594841323894699363917428088475991554417987572378478944301605224609375000 21911565966951119583258944294710601730065800282287665401517058316644388528986533649877425646043555644220165128095170728314781736453509040450109359768564320379043679385267648029961719432499832747133118625739120566388702667340610200441457175719443533967329926108970281104002399382110145526105017632551185794139000932350500299854967524414455782923932524188888639286579291799143217121832351896314115368937897155806165769667205113038659354068603543290859518120313923507110871730171573079557251137686747083877684857566101857346024902158819238885271309922924726005921215737516929811707359800478539034332641577782113755167138117702762810840236363588066683406094871967343486405219708686352326892521657960346672536502093869868381423783349053623092709076777285506474415371008710206560342966831193497444769562856533681477131654335923141935766976637522642396137584018862362190342058158444718981611905270002985986963167634993391269569925435494959609902613495082041548179940006994519981684553766671652937597171861361705405075058666836544424456889590402397516299970448017120361328125000000 -6530393428301878352977004190937913697397250985453519721876229352675887624869386244986841978015552690361651827486182916846584805267425515391894534098413283018233579795129457372557355523292019245327669048086816860936673905195369027164071482783267327168991863017100011541316152800569912564558540261409580820032396913534610324355604412891560001798726596407130905544543064111316904074667085812687993695891155149931700777044251567280753199168086609995133960586609996950134641055929087683980123897073029434340960896111890208451174983481201664183129908918454668708936577952244695505140043670588190313861931256099869263609901642218586498531950880822503933149421917514765576941725329243628206732456957929203588809341876005266154589698013982414146867235085924182004736064150620252057675960532662821632674783199358459325165712182633236762937737610402647310214871887224942682710827964266366788267822066122992762110974562913103651794250471341793688307963497360785790234434799525950228690615531859336935814344157251953401520546870994886483915813080169954218945349566638469696044921875000 2497167635635708297824883793549747067644899084731779411404890820638669946451045127227629209261204049219974042385219532546260610405662090331025466935814950298269928598850190742995450481473236773685826528724295478868912916657192233666090201093721687460689362925113265157371226211097587358639622222298758668041324642871146326879785927466798195876719470573089683601382921577781133597296154209805414248634675463925036451272521382169883651687395513299059115704220978442690048450587185496535664158107226340749794037011329172942830047393433380945862311300834166394870598761359048270734876857624793603486114836568453300845085292744695979335936167829917776018617827824033819523301998064457544360359388333009966479156352671927613375172923754331330888888594176970911267962598314421629393679531203966646208319375171021299616783475787672707357601256566394929278511706783011815441782485441609080727467093638182924980654566454407675914198994000416744447346409490100947115505703351073268432969944141738283751437552702591941067948423380512329092240086936271836748346686363220214843750000000 -1115816953027039240543280664373234656472633651470474246436887736071398426655152051444725264712707899870982390077157107725748204081009982652319159260874637424873236408432142415373709431103124766212514859794740833247405994369551812315611180770169547558184534774850455750435462745587269450614437124237262285015972077542739884312870665664932554172686044574610203138874619777961953359231224560262948652999316784915746415809605097121211107973569623921332487445087043762885822528271300403133006602982540252535661841214926453208350535077269325193916565364819090405607823190250630382634287128186699327061287556954870083574476237491862659965782140845171442421772319087095076773811339840391778687011703656095569640332124578239676761034403859492549192431063951740306130363200442519305728882205265318125767157546862015931588429350146483303395376085181142768481701241444786797679858158954173473912298448588237550731978769291245928084226442867435271195068767302269754618988161731683193206949754586765744024876173738930962839762266505542233081382103021539364817726891487836837768554687500 482928485704344745832172250471225633343175964216537813731786169191136050552851710849952504203171178361808676332894607112926199395888656626991253654260369346940524959066360050539051336564158349735408843882321130062721846488242646567103490567516678765840811621340301276079673289296640700770045611254048873657803065229318452922454424674177345178658436283824804499627000033866681553573947288146713699274293408142515753856676884885541594370852910720590558136193916537187190480872933041603356593977412362834887000506233465063103311177340692683480381991177479545403159580023455332336826248955111471983671818589263912106457140674249685186342426772395512393011046416272758694557349715213071079969384328328549920434447882194742376298598712509920595910525510579480532392023087297762949288401245866808873705493105882672084618813401325996818356300918061037228077983141214149293014110276170141679455810013515235966325444392406385639028883624113823000158053272360783645569318045055592173331704648337219873266166385440870656842430899342887614528185835638396383728832006454467773437500000 -183594323622976849540060208423981851178708491135738529277273599350480274361452253541825656259298722051994280365351557405000636784323215159757785468736119180817840510990726043883479531683293691626672314443618290461555790407383053576159047595721963749378693583198134355553124622381305145341969182823193989250224965012271523262539228718030545312876772882822877350490810567949336233899817296491693030736777662698434529686361807386557866148665577676487448197459618290848479371443037921741806894596823629462238066916486196218164765145842664619551685805063125245088467222345762148519571860107181634251704684545286930906811687689975382002432984730805719271546385900589748448747181020118014432928153471492636246305706263619566579517903516844360337249898569570326302797073993091621213408729267810441138903089481458366475714268309781711087670481829711869677103412659856796733620128556285783351773976430679778085773994147128776647098856670377524444705626359206324133073396836858668848893836685084033158630900820880480763193107994750864070399032357272517401725053787231445312500000000 59126492233809354445079934190290954775981712313613152093320044478425601528257158676731908160204631617148762501621605269188139940233877788165708042586403629329174953517310845519234582063521807416603176141427363219752602636864010477138925006058974902228548508890420324577005504134778449940784675323514542371621695872047458139122928920812083631503556797967818638286799847812168986279809262386426137792341690693493497358764574277706594433118237507259535723733027932072026985821925704767876316682766666823642754221418879418950438306704192127194947971653303838888975808743629775545745808413878136921505603479390820032181696818521148536707742627285254753520842684442494642260417523780394327588792348515721345506513108214782444061842446879671792485668436966734844159543151500295821534472323255600787968681838759064734093837552303652107989337606249342424551067299694382557753122756676571323892331529109425325445458500291796745312587434355151462606981373164853385714044153976899453622491254382106020546319196404830171931366416598278411970168733091668400447815656661987304687500000 -15848794175659705160460783803643696251496367358555552951893000625738617797228290349872764111591608257226388500627712237569613193745738104445341380714827434938542767144184678477427684421984791484789133960191117772196950672154499351714577633320352132401613475695260322869827828567937381752387647545449560578426225696905472838460370111268272349176496992056462522043379352653207346604673490361754217451704336071052762721648721136868890746185802054814467811582551122720263533052737206397902764154972021047180133949149409843619512264139805417455411106015387806329077835065912932076716892767606132053102240599010593266130182005993619344654976994680526799289583541921480106723987841354285776214230229480426820497563525870447177277154940607095003591308243573671912693251926730087675096222046742286312714718141544093278511869078149615626860545534084098556075983133651678736551131308606086354338200053189118386757313968066017172667077733404129145966174437593633273224206032154643127743576814300286647775836264654941838467045555568525876805052732265721715521067380905151367187500000 3542199867349957273939577572202421454239487356317688327705570401020019650068645592366113099202163015868949772279068901928271705666408333659354479595863270631790988481507509149722968199252211849346005828037824806623298246235619543079023215624306202528750049213503847561847629306278473898039343468914006451265029041196482901428930880799889788874078650438341643581004496596728089373582424419545369737322458442431698416412054291551373507755274323506032978712771374139634027971499687402892873497832659674216940575962690874782773767844702308858169512234302468590612378094576633862350968113752101170997028190498503026791770984241613271303422633807985486527757055624684022527974112421226050197441052501247612400438025659058282393240729202972039372936749516102559589280666537482490176863237470487558588754468398291883073675220773525005826478246276427723349308852219117204512465015828728994437837402202841634538013645120341746652478517076446013964337490328729876427731428695841271665384605529861003375113770557842603142040545311029341862818498043452564161270856857299804687500000 -740165939248532099856128967582919933276429160121304675321000211621518991714449380831533862735962825988685355520703029627787369343563919379579348523705949947509552214668216261848878759753012988982627229208595323108767595674530945180739650205879847569165549442014448702270009828179931689545256421265828671621681854153092003982380171009557569197012449573017493685896417739280780266096989084662859815696471884150186397660733265910630880475056145541946832535871840646384290968154093493839076379708295320718076152988384377941467812535804264648191598648461779361182570046284967812644009616965309060253046242603057139805023607512082159434183146645920534082906351526030157224577926579277145001114249941406919079762113251588870224749157356143193657033440004240719707919283266079602822642318723352985357924127440850362182320567512508634948035492540789961720525838291416540234751112385741039128756803795785843428047977761544101295083186259532912756275144490595376685837954308360415532948505246662587921737281876525601242870926683222344150125948658569541294127702713012695312500000 216588085271764037320482358618363208700267854750638084015898254762426147114832522153168121804740849341726295652878765520029791433374070982814151042105715064544752456057889127488294040562555739597376170242448199981352880213775375987383663710123773532751099807186906056779837337570558906498344794581280666934860872648539081748060188819589091684423827678109545799929352260940907003149015367695040963091123181408902490645914336988346666910878967902795925349253159642551948030474879333142073224626553994243003362397453042790659506051171884006017880467290051684194159936447434685892641916473019431111633859554549321680870503620326115851890141736198869976751248010867338074527131448151062575255316970992161662874246256484072540460165883602851083337060547947194964872593221583526377692450177254498025909502212258284834308137186657858383126619123547427944540042414193032019820660867282509489362329625873051520968852529798850073124901467390109019390604131037851135718819063087521150794304601544708747723686719160153082093536580220605874957939818159502465277910232543945312500000 -101144482916162548881490507573067569277782458733795464598603448434066171285939424809334164772574713383605249302293913606389993871434219946636345873079505572901302598503930442749038819309228780487361958571170238302591208899250435247106609605325544111727203394115559421939088907835023065450809865549153632311795909937645793613696742982331589001283020239513657371439650326929960504249807458092971846969360245577351632581399237274782315123951019023150903485474810560226200119413143108515447696009350434612736705650184862400281162699662038597890230635919858122784442179913909555502528464148897117909957012457937608248418296695381469242501988443181861571784953918961227247567302428733021459824277355172329252374153077017429250477084042495522173618087671890896565572067291315205536848888619323040052441678124231014900586473025653500775347249733293466261898938094783628128876988375810944882268996703762859020479683756961731206973142778143061000816650947798026285288003233816698014368223523820091216153544377395182747760314979188650021113549115625573904253542423248291015625000 48534422507253368896968598172510113056021907002688346428227177384205027162075469347153068403949630691825664510499637297754867368017467420078132099524199076696657626230152132032230369938892590237283862754740814020895160016194444550167674126680386445507295729579560444791920926861339799672323497049990220215316406022472457701195207067275249996373682804454501930843739596850672364193256470390178367808361629687584835615264081070389196586602010612221875409064707857384262705812771946870930932102861209677989814674712536996439854361996917907656217103696336378916860262053380533410969127963927205856934795837784463898684437353321277604723010601725818415115470593561020720945148155984006694507270986762890359977692905185780329850460178115640561670022118681187370234496512968819977506453843513496760926055738393653774033611447041485964972874293377287140622939069776236190324820709127045043231117940258282436356650424917648048613970620114670504503275973543838648528714473134409266369500185410591341851914445902431084047104434015407897762273137232114095240831375122070312500000 -19214491297691206962534555614765253987178488051336547415364420640031484261577638424147338007380155634783342136525817337371648464707859930429668282858737977249458729326204836681052122453928602673601576543254027480463510045997454684118505657435242220587439562732284567785752652519073722119028450062358718608379346806740576450786958266960007670596301647565448936499185631986025463968656132990458299293266483142299157574149919147295167305305761860163854185113588677109821628797738478687968120027796047188836826885747117835116405697851804357014840740588446005130183730281020191216950054583234843753619909470245537125280528889083891281438327701100579616616344858912449540450021377176500531694962055314386742877463069306180276936402548393960684769932423651898915577902238194505768372333794217165450411233157830925668096798197816105901883784125062454846536213472493225387399091149778170877310202738527630902136695020167993999972065395427611312287056398371283437443852887288042110630304489323938672747163877955090033265246198765927379548124065422598505392670631408691406250000 5975360034903950250089031831476015057439619852415444016083975476934290295840224589360404327786565495668071270109226711879462761284364722746682800588673877806426367500449455361952671436847803634834565737821851225673421599991291873877097992313511385066409633860472571401865598182885168807266467490429287975459118251119323861474657637560128925898263452256699023057179419099821139086314561075139228919451375988921095164335057708040823943912599305988596534393702763517454335895148526102767052698669458911957658358042432685623588750831094367146744557876869459900250604768350871226788295435459763804437823590166197878881165130891564541229132158593987945728492033393419526783037837113882914094749889483207597251548043728638332632345754285312885168962118213611937321239232832484356779450687735778258357428073891865985727677558645564411973335020703900991374253365345800366848650561745168200634034051029003676839428667765930810402908607049904293920169720062019053496953335471752536780327732924714628528441735058164469029652397346740605454940009622077923268079757690429687500000 -1391179390773958364310569372130919861017140005132631845943552011439657277135748158743560912154487963943414036715265877489651904095247025706120480736689159519118171654354664216878027381209286460195801789783917808190882343946786934295840907662238534676600659633064749068439264255392390898996140424513253808179837094472959207581426098047120130788613895687956989204998087520812794429567956712244868255165248550270722475961443170611722606986104441990233645859393748385640389618509335254265622840869728439120273260114673886469123964998634555437819834521623025502199632446579984034554022886010835744842679247363663697814903576710668105482350354859942912443924590151094352024459014164264873838467571326959130428739361250914443820535242009779668270750061430842807183023352883442634969465500660410422400618992936379115082204226165978520503711858702487148601470416047856813768866395855892761222170317987366771235138662541684554793438689032239825584979541753015395360614933332671726267288656876222219022036308902977246216666943847599727246411305259243817999958992004394531250000 206672812234152092644529467925439587524683836024395245954152405151081959380623557364287515076170148164894933684741535417642248597535613199845577896288382817370627778047600458295404519052698306165369599800492260534146343916461364393234350765598076128580520176379432284455106107868238288161999799393706347468872506652497905662615252201588815881469450793058659061138768221017701974642922907569166137670543988114587450123277820215619357175327282089283821842618413402388185473082623574049046483681062409803076698667851043752250442458376144751071469770696856076168730741625444597247152516921394072094602040547290073591356857751438251158055394537541162281165160303224388447928059628899798205718585937046467669958980383968221423653387190047116835841441745313429075168451726335996933286244841135474752072970508995115888854886184272842975039963218007059792554649034453039897484008191922788437875963392250415607669515962891630524566546084986062609539747913846056907917055656829175695828338804653800919744759264094173345121745026271159462183391042344737797975540161132812500000 -4591642721822372407696801133853000580563786074490810628175850691889885546116115640198125712760747582269904336242981895136272509352822810686582702255412525647448189174080322857575926101374745858970211648027985554193160016965671152716708854909077211317771911974503252089339780828230259570993500682537131069234939210143322488194458576418605196206808730392708895863742736295520346153878848376594225946539746655790231810562451163274065670036860089243607529299819600976765969504177302698169703082363796546157118093436286155863897434334231338056084699738006051185015214975910350520899757212117276147544073970306039580920824070351048507943645845438424785674560232003404423353292545568764921758644899484139597667267732162076290145557436106880596424923932956802678466621894728421282068536170493839669199709621501928093725558396480204939593625823526581077090054477043022000852102579818739090130344746297277424924183899626238235723819150836568030915970014499926746989623810943494207097498378160789325209073033876143480201566904981211325598167150019435212016105651855468750000 -4608810991183109211620489369455435162161107979150682435109163459955617345113194799379206017502367222563550629220084305071241157119171932719634286824656891021966424077558351956106118639873527114983624025981160856312696638811291355284865261845543815346269565167876204526731814606882206782832750699563372027123499492810580101351096103372081658098620667078847864661707940490878805074161985276553975366296963922708038954667358808861964247027230547087320054634400189487857488281024135022312502040118257169890956366997590283372943037285991530924862092061662547877351588791147531456101126735604928996456496808449912166680985382257654100689138731553048098124539724326500766197245529569619024087682693702362403931560643114572589806522130106211585701300571114908215237178076166961870637160293051355315884556990083097487244586495622776542919011609939604945029671164834226950534070105001401673710445702895616240680628551083475717928953197933647507470244637424989719499315364895447149938719538328380913145113808357186089771372918249409122992688025988172739744186401367187500000 -1105621394798411892303462091622168385215835608169478602528005197097719341024295666320749863514421126515959478159717220391910099101429939415632288690759014058221754800721441834713134262408908292728321216680611647363667846491396354018642487401694245385860975582772815711213634183849645599621233352194768813393298278630645350492147366067411645398598012356058544927616511015022917432896001325415827402933464906319281119119140386810659758005508433577661137960466894238789120315571416175717035798916723263549592726325134378019905057932429323359507489411993197089302061686808767368412583590384265751286696906958963841800897072789472336209628494527488560959283043602103583764968319161356480695729723346783638080726009876589561211888261097767959730149738876524588079384474129270862307358873439595066587825035012161519123296422102490842056695077895360437622217444573730906601459736211491968722399404674327236384930219828805188568278558358357489977615942952520379916940823472405284740452742341461097625367856797217315989744995208092503968799746871809475123882293701171875000 1851496584170503322662647742692075270543120670118095498992116369412762269394271595486045330323457292582419569781210913997436931295228043781038932168772946000214873576426424653365456898057918937491087698353641927244471591966299954335291346211172190349355540856742489577539058264589076902027370994729704539365564754005010315754170929247390424585560562703668547578737438606973797808639324308630003788250484532065826173181426429056447518377463039282035933401483512523775580856094826261186875097318268904299971448080633996879232599943380471382762494014923924327585101466940359632039047683442774272547199071477426600316972269480138848172869640807498054473676918686220695402771463435574973723291384931845476431406830422281897847119830127563773143672180809214713514953945067269473586422320480044365731172179102354680846378355759479193369893837506432582160329462342307425658972889368368008732901925965952655846028388426649501495636748903927121147678111446174331716330238369638829408469841408005579678080431401705790111227479134009543670913444657344371080398559570312500000 -942942551954006952924436582915835308498142326467644986001342473687450896950551825807903091053525278180656893995338035654946569327297236115672536808582339744881245901245440195989099622063447296308457636353468488293931209233710995599406536643326340104055771918462467876507891786423339363352102106468520503594455910879260285585889773188186138111744110391913959144576071548219348727906825740440046579044141228084223933423855946084954652588195401282656370024656216807922131276990678475517010110621390518157120030578877650160338897779358789608615861328433874310672861083004416660284123080789300459981416005370125910561116692882870909766983834028769990314204086063608030815084786399312048460301989922498097669429189749484577083770102472230075547756380471315471639661567983391965420015301012305173178139078452794443721875569426226009721558417456696936728699255404335265975838327951937897601761387195595841473315171420211693386475850513954800846335032314506262459667585699693566764272977792114696845675544624055751410852033080750578264428440888877958059310913085937500000 300098650158398373451557175236067392045798881946455813874770878882315791541455559622994471336559075905065743895000299210614221959836489391040101048074239373603214534124399795125699957042071654878678067983919581175811363082366866380971641123184047755361251772943421357558129214598944552358947476276416272568309644439746070028611693088611412483554324824254938276616794078581975385692232955669895349247053119118614183383382801441733340781077697265336071752149880326017905817376008783873730083633262686617753794629460065990790811952985411028217049026634646314422758287811679075375393393380859849342956864448756104078413789761673074797093327597423037118795382862160938298840508616907943528757938813782897514582305805540312595231089716091513807247631704339664101630585678941180146732724826700136171375697487606897203601838073237273396187012563325171202809553543048247489479111148316652465456635075729273813520277021564860051461800000351044195728750257656207957647456015492222610445249062790322016253418749294763981953694954168954112105893727857619524002075195312500000 -59990069210395855216075927647658156354132256788476337809822520457805470510862407587067366258536869585807977148071505664474033863593356899202420635502125324510342644703612803622930423039905468513536000110718955636484896142276233271320656361355043288093518823776479810578465369855267410446132327027511706309278655676765766071452391016845133018747747079602922466620099937445404229624359915322244047659753855573265919012667955783526280380638712342651686549614989838887500928801958008718832125221904083199863587361402322082238011116114251857545083576148282940103628599151557288949669907905291681612731511192170451971032700701023866547605458377059585918618649299011040974761845076296212549518094799590562598642432831791271277497915702143282854691960374340173121499916409907190395745278071750534489996037217865118198161214806858720079160596342316749633805459379690739638832161715041162522397800144710898753672529611611409208053598272048058790509897519368403765393521874660620390135289583956757397780640866305667146163218411691886444714327808469533920288085937500000000 3080977756616124423588816395979050819240820009782359859065834357981880553208485383136820436344742076739360950955693888772359317090152455607240799266470120292600074647541813320782304205598073494563803927935054367388339452884564336866998894400006711408700990116913757668383313366802439822477414740051418282185069664854380242862166146722031110150165315355648283766617879032084081906645218604352204371787267401010715473988153315497886384211530433690857436201059172052730468288030917327108118985017961258093846602599109280191990025120569562229759260579090059627912759400916329412368653011170982089889474354221938334918733149326954803561644360103425382603302441785468319253558657854090820429873138098000829569667193575594400769299599363697602892613345142884752536699282600153575654419832814448677817606439309463422752659102611764417189473740066073544249710097976234038200143819089200848101082520340116859408882748684832561761171611074076236391178972140455858100380522676513231093387277198751982627190636974791576332369669871669159988414321560412645339965820312500000 2952860801468110507137057861290251699602874117119260463452761169312292062078889335943527242508161848138693000274472533410114576863781007142035725385314159089023884472026878753446745996879209922145825230489723243093949645569848463555483450324113231443668657054090575539593539362901823180779422099792215800751656549292103033957614736947798228592182551572283632304771586681059360990826565942402298821305197155166150089072888154851490992619099685669250863704614152093589298023382656161348975243455093397304590326650568060051159223691129255051823500095349557953043922436367152449584619551935548588805465481965623171743602785201611936852932121349035033218859117033268970055746251318296175908504757751944951689473752484465481170318869025755222370582370369052716396631307181740418949299657232888566812370249281304642952885602517006602332714460937839514794976335243401034905288659342444638635890631308826780863760574653157053503069775193947615302241265853409499886111615554813965525869167362137731504644717228875286022101928629091105449333554133772850036621093750000000 -1307022125801786049517389150948325667469504284935071436389461970583392874356306222835015141922895257491384873297149700029990745808798434884841405363465516283090533066179849897464375840079929769550503163686646311745140454547331806060177077814073607579682117702307744732311171872956791789579392555019131538370972402100521067350380497078763967623105472572976413685989885873492558413333122720388554690845029774577980690416247219237994188792323684055994746378985046272777737470447786954507711040094747606905926085546276001764368067763179228825054493947224752242644952006780095648721037621732960854079936886651355945831285290388004957320795444303368649671814971665567597200797170559228847125957651018567137732864515049007540223467447282254376036156521663763664092646227860218543377088798473630788701307230755558462915804490043408388458300497267870173726485063755297839312852616625115070947571060969731355193265662065351508356376213270378265622655505409287396935628942462439538584334628635962564466438447242263494518842246311374211131806077901273965835571289062500000 266261128531793988719573223557131229155126430106069370994621585782382984395183000815821188690311792541388478424781681899331240592640330084364674239713041051008226697926526428351454651582353060707724962651554265471297814034375375320749132234434109708310266929167731621458557440730945851689868010601502406863869881474871498118109240508883120944366283878595074903542321132386309864095003458168149475716142436068691035767824501361093406174288565947933141657298226803414612902769640302188920047462681009929590174253406475227361258811789490463417681462064919174777530649124198758709846927401046192820734379689954328513872361864104102286861967023190827441694707448587530654913853633287268389166411706053376975223113144160525660961001592209237255594146201500128465383048412821308497959519084113411900982484623153024200568097203325844785981945786290352886997383982334154723470849431734248159809640731100960790817149400400316505321306357472887066073050257066940118441067869152133623912183305111508017497528071356951049364369422944864851388047100044786930084228515625000 -11430255428672013446097932899767174529508677843580246967150479825335316556880451949582302331048197021690494274461039739971559252976844605848891159572985844515679310331580395827729642605357801097775944069618258371554858250073016467806093334798148631241578208985563488033294052293566803564981943654587678715462255785002292817658678612850891063727343762429483729873361664760743530995511479775417111887470322903668535934847620000306288411968303897110715258074007865949821348946593929851208776307561655468065033325254225476844432921384346114123165098973160148870517485043287307022010598013556401625290181090860368612427471248077680782838753198093201611552402724603465372646287780661833211614667001275126735109869515591056545694590330773638025722668032175080051409438755432724524570096945732554605231470733053102495258246085269546022234215786137642107241406682126847481412037298388285656252810276304635077959221112532982256739798900813364179334471201918024443931496751418772062599529751496460982815910394925450730991417502835361119650769978761672973632812500000 -21160428462125465624196123179850070988992316179725374252194005185622452849078082190421347993507973323143162983429191974265044292779791580908721955838930674381752559955918223264579604579389784962705053956942783913351950911786509220936668799129700473403105594640334814363772423666226737998094511044060694794127864426933793142077754684800660267193095696815743292856354406949229228730501865663604433538955372002360148348858615638836661155159675330265977478188264567297743922916664093432009659941879044733614100345985323813218807993584847316702869855817202036597881430059261070929914466390694843140904599535552996388280239252904477978321626460896917602780556179183078844423455312417979639342138910931569727946625478504006420126330633233653201867354326620711546250930277954341822189424386797890361142901366251514436224923390793265646351680852394722844959141926482266313518227038594730562877995664398786216802581327074605657590259255624756008694385563718866304362050680693385321556924579453047668159713026293248595480602294860439371859683888033032417297363281250000 8470085000880290985903570033331250705863011108066304605410755080952070877551610729628750140304558737726290199480446215050594485610519649639543185343345973490956799881261688988177742918297490329425675669557872665593834081555644100297646608584319374380275876887420848641961085766594696324170417367246543338801874368366316794814923365622067671988884787745437174445685766316265457514521521413428629224949198442930509687058196289171603680883930891146725837347368971710179874822515778662464718612877376122888896053752117636014552818093407411702340957450928516847616247700898438699548547556200896909194501911614123471794349629101141763095076808903410940109446069106930755071420939788444084758551223180327015050978194315324537196983609573116523154062004777128479165850946410725086438948038968654848576859066556992986408820506853778185572992640276351275293774550864974765461699754129361925671278406399488808699242956780074850172335712850246498334661263077360957079241251455137914800008947678510384905257016385585245069837073694785090083314571529626846313476562500000 -1772285815923630536835069684414582837937788175945172415905524459764173717478301060804829918670354529231392979546851082215540934582816102507666228805342040165463618430597075962066393703968147016542756750811504961626327817822843126567234895087765825241675519456256805877543805380137008643128874033253131984429941705709239616058351372681098065528762812876285065839162185132849767736747469583703862381387752024559288283399580129094079644525828420477836496065394873776333386794554726488919171916417103162191781654460076948312354032010253695320556658029493391929474025202682437944740762158130270859356506120863691449312311126076534240753043104995526820452022516488444890238793368096460645043063445587126483625032275618986918764206459478364151577970420185721186438830919482613021069305892332406553669050680657560598252469104455527324594060730447052236391753968865361586858417596943203804443122102706101479864360512247521128365343966698173165339864682203049547951849296948269096510402504091444701821297687681877073764954641510449562247231369838118553161621093750000 76492021955952390073811721293678437836823383194124954281296751803807814582330799529880421793035064802281932576467596642583658785646250199839510213034130180878717694097337477306658212776258176837764216930018552943823753213704700016823485142061104556419183174012246335955375904728165043591415142861198041579630441594755887754596628678696316403332926188468574962746800219352769835217323193938856844689166010032103176169764858164259293488948687304842177491475714129007789966925726260104807027509647304577655813642332745296062770680405525438698506700061409164197413508900985675672307984973927748196891205788775130133223322831005705090055204901195641853904467930690142554477866256715630198563985880258887275769404819428312102729800208974257933329880887817962851969465668646083820541578493017455980714055856168306885396796489584705074474513902189373338020875082081661302058339926187436930893841549783455838788958894900574137799118529065348281742448898238649051127942883955517482780479077214358838481568415682540008123518893157211095967795699834823608398437500000 97331980019978317559829055190497505793678634783582023055610666004158829019600485769750758139900106569399212448222569856550027995072017233234000820917375377090539035959383885477966314515975377465683613217108136070589583164148345173635993203896706260416465899760447810255978239539701891624316565158709950469549507635687867745971635075869344182956169072586085737292563614821427870041746075762897978980568831955724496941082337342174839398997514391187529092496196190130780255460355131315124436081602999943076945607077996428622158289877119098787015441413064687884905090997759983188860494141633868461712191989832053340180549965479273420754379751547096729455325286636783804005701561863116074206604492527627228332966859479193760302235179194661901712141866744174222697201317137643479724960112919895210626403324920848504192649941646084195200073744598885591241986732430224746590553965906832774058831563869789729209081357519616221048043729087099714328984606480760971647094162574713132456317215252927418108824222346573486240942085778726777789415791630744934082031250000 -43277364315252103065122107537560873574478497000034153624476437489170049604977284127271437115285959638770330758598981773250882757459046465450833829749328094186862796153559278975432116088223217928573867471487412282827031603125429657039317439952366435425253121872953374790622521359285154990993003169030866979730022060554604667487138550175740261999553441200515799374011953299140141545595196314713959492768469054901204092382936221596591775956637488841357698913312315758047581592418427720293935064673672703427112397010290333283640683658233249630428741873923421728444880095739904665227692008464020445229059693171617760872032533615013341408577879106331697249903301344885322387429451126156103392328218417194131637081639299037434910212314974494173154065199432256893729005154728254846065838800069742327879643903996233274481562523429040434351801494284908491861631724056399585446722010973781761851012067288236263504299986016550213004042436057274741681769660902804617744223271523949725446307221038601513933988931748877992695262451050552954257000237703323364257812500000 10103824881529560763169794221749948330852517547528447188613693490219345416387244573999875472381445700508446212616684625324427909592584652788123660490138421964546116610478696604617842528215564351428850419345323971461382617522246366063362066889622053464719882914237985856337414607731775219653502923614949171734394065528823059085416183539796898725101727678485247025076948385570409840361679887560333886905321140430879983166750080045890505626994437572688089969221607189041006168714226072744707200121598017329419327097448315766397396219841036459489013877452401502230156013898940277529604586244255864977799150323056608208388441693927661347097526407574274158261187485915135503048442648790872513509397125242050582334458698579426891718361517849755521950305130878231409309813577187524892510182099832127753654589605036495658457485934003566385758604812310960425363809557547771697443847351543690425736948429630876328887380341991025902372710959838413393689142303439597996832492679558630679103413603751047492838018519314705816018740147654852989944629371166229248046875000 -1019507186168177547636861349292549936455819363461594212925604440262545156830540434196098277415824237249310977133343259599329123535359429038491756067948792546315656987383079212424981223341669761036130963286689119256862958023663934561118503149813361920341396113942269257130319198812706573170934594801983365511839144694452159631186019890139417946597122228279682880549249288773002362337441640008278209134354463725039830002089837616990951222802590467029933583647420095700325151111572129256133239205177365027964989521076506079199688531067065029677224390776489826276932855149602420942190822076043231491933997419290040554629259955131383671787625691534120800027309619235951415744988395927610416482632598004110760247753510701349040319685309813777042974552260464365628375153197282452369492571290184316679864207914181156703186617569822094245985146671180756780294353651609203088457051399556240418174768527404607062983856715975729605499627384615110206599762418976817785597560273981570218485930451453665753532943526411867849607029157255055906716734170913696289062500000 -251822589217032593462987354116682840239078204665072878373046283650088839620648860276722311706363849978638635190997668429105845368580864167373964573265566772464872021580809438957595678760015767402702980230101069061735415797635814253562200250443044279995029094545849273322285183888478409441972893774109393969741545070851681487387286034311609217962749789724834563497382551838745747213249851692014711330326672022079134155174321048972797354321846661272892735001090239090357102735192864393697168125245756637342518132238925096314451455739742485029049276398221378571005564803146068068358242218099816061174853911798012419168047683177013944114777685480986663623455932299763100860325448141714329668173189513210842957055546531873154552317754607884824042575566312439147735750309373015756631537896347306874539887189735558973157578483632095045053597431774907785233293561945099662116056319710942064017036824490803062520294972550849802461926692398845591767785494883533235347990580036580270451324693793110869676862011262946476619628555226881871931254863739013671875000000 152850069004352151327406854501011765940121302887363118089166294922627827805318927973365663056028573807223425653117875839878894968154301878536533013747370823490684682648689242570374190080119387114089545567626513985265891432186221754433453697454845250363931731333600790034087659103049174450172379777964265651390732237141652358761012699872032449632504298399775764821013436927222992681138374658548829501265286025662498725211861290980996864451557142194416317144324438029975496774687826033541346259688831803440715079274274197019374785071798972271736517050885416578016671701132780519758508637958922082790179361640322920172534197985532985083309010122202095458957297841467397790099207920880937118851245126550001311017119333877440745884482035551219000675180580475188637611627243869332708582254933052706877841063250812029932895848235112195717345506567897956020499140527690190162857695676046617272755205013401036309639628729704825061656709327131038508343351940699314813953648221103801617346345779459129874635819785761835926107821137520659249275922775268554687500000 -39727290860149555922293747992925861093347747828718117891745982723587075506488817710613116799176209626805799499087214076047284348913415092956189834965745028099861117845306059222050885414246673971892619725570231837715415397243090665629063879431868712505056138998507500842046612557309514889875843410724778239900692525659527063063078729281938753933131964562723773363107698192315485239645787417571724824168098847235597778317867537581724480544815717110963727438433188051498842726876810987059683473306928171250338892076123032018192066979961301023476059415937587467629002756419333747373926989593715606775226032117242773716029355538390326187757554273942012571434912348232850918111321933663079615099841040862421380267158813540398429607865144489836455928614471190342995857916367201527806858854171505752723540901558822397081844040312605257479519080421534749685572417592330698466024551804320072112468393580817892608293119954938131380712561441247844027143726278505710536099682182553642810770792795586225133954900029249323462066101342315960209816694259643554687500000 5200275885921450526735726419214728438611975285657399957303646877458730740160721612146003564277670830401941453711016663752509604201443962370373587945342147969295116439360099339179672257916589492545307449426804286243681061243191155520550300846272835362826272008628725349129735201474075928942960531421248805741656656853561947865545686692187159805173928897496142800620324572053296109377177408147267482964464021374529493792537139514723579770526767616127486374253925793989535525268739070630147640802210897378740096056197680919171443683529228778627929623047184471800898119545664204969996049451919697360135693269758417777683516160607410274068312608018914481815089923894184080869859787634719839909033153196577772354008520221499359526059093651024960701919350551546352981719848792712277000473898950912664220413397529265641050280692753865463793833004153796573790538144759475891772903872728619361672735545270226597938049588129718427584817418609709909009415993512962305874766753647107688618886974589954661966141736650481169901283351464371662586927413940429687500000 418269684405190940323167697294831873638890421218068786188852456081923756179161306120847039918529090373822768911556240572053408990108749392363112310261144838109096240591130361122614168971511393281762317615290074660026854170740700493210144199348736949821287374209037775086427344228468665875625503240371630285164940200890507502630549832684449987398991635668930610458461217774536637882263143610002688824678705988584448096841378944637361160861840077163542875131382926989628760250739374029569294361618966482746085842669950859763830441717452985746186804623925790526916158224498883169271622714052079488095918266515466201347704436539525338919853467605429649723356583320534486420686045680180611150582510136773525253762032072757377316615249750113440106460448429808817443575681673565959462288141683519877298754042307349185987464412200310364552879741613492841670397416715576229180724101820589271352386137983463980298954589895555139057593492922163334983301190857026435286563227001826855553843498276682125010799736923323283166453734338574577122926712036132812500000 -424561560216960281846729927633412725319161078511657523201260555589172349104205477548383110654091075881212162874561079471704781219691195838792226350026475622632631314799457827400661317561464990900009418110586594449944078926757331092503344577089243306127267723182531428468003460351885151765533621371729520346054235472968151105992656121674678528612746582842331324085207520254589712223947465981592106940566431562518793522794727946467070146586428451066678581562026217105924766803087920872827713974932247161265428090429234256793270946150185343437942475162998632137778247746956484946844708875532340243298975266058686624964837970024180138784531317518597890754844247994954870644347003296241995562926844988573170969861694109680977943834789499669909805118686566460303024415360467722844913904441762437562152157319867243256018812949105658520260984057710497536381670616208819275240286848042911750300834046130203284217954823599191073555142914779533318558504733219587862290945296403307977358689656664313669011662714231330334468950127302377950400114059448242187500000 119543910345921171721831582095659306088181345198597823509169069313402188023691408228176585907294790942460046066337267395857670611267525605863647491247589925714003113483664376622624042789299044111788220922544654604464043304821889315821656980955907299485265478063936024891454616164262343371188228769628336193523190341520444530781763601901143977056349677092523721744025570426262918050740950223210444151231581477964821587136798117853718829141704145935349853296108676142816537025150414613554510098452689192553534629275165077125119892838136668526059754113067095707102165487445076153263407740544781920010562929205204039410621505005971191979436157611802426279323930710795735342944254144388727466668927237820677740238757445268144422195273202575750190138864371538918961878433034951718529486809153361869318211583684388725933325899178541543860507272468915596129682664781101533893302399937717585640712748626966945830247803807932199339967925304192261628297452109310128214583158974127799824135922578770912916182059468542925838308033092971527366898953914642333984375 -17189200563457900123764166296156290174840593193607154264397080015387268070388928405830705137883189473800903352735041094031673098975659323321308027906516061262026879971796017777771783962194985975680044213812537425528624909900663712147319086030253886618445114311031843233800425044140921150875068952773281478120189975469166589360172539073330453041389974229206800246493046133030471561396379266304135626685979160738654115297930550006853584956926505891734295660327410267826789997325502160333149239717265644533297716368509915660405536481877538366880989007628146020600195513289692163224129353280172819245629506137731951162729987717654041275983330808383122811273953305361628840508008954987680595226628851622114745735208709533435262909072657990699931022025808430175016404806437716956320417513346360928989172835079708451312815976228545313345923353985725839472850962892649295220368923095039333416580669453355509292365634681371656597133470365338086398153857349120131661030762640699393649452677460607041423856613515381945578308631183972465805709362030029296875000 -555318338108892730984743254521143179833197237542706147756858559423086384398991317063069169419429702091814343428318320037560756996630640996196572580860084758464283933247017472502125152723831665870396069157477468888452212497851399908135517514553604487031147542742890386744216033625327257591296967835138948771900831658274102464545575862165906257114196938469370299894544795356536550346252998155384972194572646555774774146319103516778984065220504203327301454736200938880841940356345381390123326226453252888021663402536198705680454562733256243253596178550294613198032524777788867142276269552388700516721899639136805968783571573046085118895181880887280931631137620821559274253955533955435479004180906335451027095837899015298859193263760865655410577077311689746486371219035681184677297952818361017629317623333698222994187906128051825943193120673230072714292794988556937347491467554798135055663105907929980518896554092996548576304057999623323664467942532642939714371209750474665543815936222384904885159974420718925411377675516177987447008490562438964843750 1050780623344418236928863035198902223796011435834859695386300037178231503080337589396604392682366646999319249567331262296196818965564777248777004401958454347878719734776288157147038175238806755652293098860187839814873093858836282524883602446913923911176910832014055544206327500396986239869310745239120072060257607905030959508096878720057791098965939282959438812145138015149325001680096835587146619807403088061326332096534231229327917861062753444595388406909965586279513611287180490760450866701401853218689971628077183726070771350113527092376453517780389757963463404064833610485980100850052916985360682416069156812986638130803980019039170815487045620557862116156559769222833764322852100001041283831210647211006257682199739577677528164886116172773346411899393532860681622809347587482855038615584203388891269636711301584415215212562783870947903781286064771178270480229144884179508988966793393564975268913029515919704937363725102217855612395742210129794012530372496204255543596342127881415690290714690929428816457136264261862379498779773712158203125000 -307822783917317537774095250967059006789151711056925036748034375193734399301343771255625151667457175563664052896315343248440756045396172259806383571571172358473401029205142093211904605635739747486433504727013897933815831911509481162065537394796478905704714935605877444644956184068295351511453459397896621346507020853442771842500062707825273208562230928442475032244183879359424110917091372150910308112990221886439349873642503581829062813518145587637258424503820143225402417197574499672142240281770523586462351780640110791733703311055737997006892526656889923686787448548349252418845856064951168341784203278864627330929268493619658315872677939079322201998794759426729281570368693174380255413567092401488364195225233973326088315728248772695872105323652755757664570002103630985114181084925090896981446528126207350305250413214176210076276402844578980339479512682239622002881501050659242620083920597281779648583115406139869287260147021630594374417796963469808689562663494011068400573086699505225581925979958566310865086812498248036717996001243591308593750 45711628721143092669419987735920527283133655215803320195552964580331338306623072162798161798950643437108828012825002487689281583035383863517028495737128540938758709163882462343257088192720521895074278181561007278128500486544344995099754379239460891258262895281138063197167969578089696806870369469610403032557481781277520492333863348205595474349052648651072131783331080392429944098044771159434995329851989473794718828337068377600897053291825088303158061020136634197588778913197393207733702375732700110312710069668199025291440776981719545089100208121773016265428004320471844070288120499697858549512683445013221674309830982098711207413856750196705228514588183265664577883947822588800606715644555198189914301696014911284458504086133557853317502145773728169754017367521132957628062475071404782341173634625370849413431229639901657333300245717151324242783529607740932931561078559559579855690026914532487199266716144709918205349018160994344434368687008892123359652444010411320771653964812845812945626238746246045030474647319351788610219955444335937500000 571325564345487268005733473573786141829392117058572301231472454146517912742288165385116047532334500628032542959742452430545559577607383911115426663554688339486883583761802068075754278028738026985752185455362349016618331194191393859061372816649695628559887609120285741576395352647196999843874068051153906700626668941042388206089291566186186963971488767127664355453322842222570106795380797106047796985670949363117299460472279543610774869597066825645739649689450353372281639085324826849409922165631179030376017043187922301003529225045842423123430765190634752132223844934529339680876879476319934560481494391531766494105428465146057072462819831139774280853723251804983864534134794416338850862700055859009455939523412557236335444906100634227080111945724852367845963891403470259228889061596702515339473991252205659430230315589314847128765013780167889047201438516835840562011354188124929287362486790046030811115164240368065209266728621799958261433024936550054422162732173837155146210040561966913923906987278706140487294362628745147958397865295410156250 -2354509775120031337605390006470262820261822922178560822651561341463731419912087596936020446216777641885075225915105003901128554211547961618084202231800415529205195406560195544446862711618377489034175591901841101964348426915657902355828724236362986579146908346229390698214542298854829521520657308446784388816190491483716457632908527684868476732337183404368974072402397229077620404312296030483258808103825177045853909861206846276464226597132942074119022290404298720150256104586578432518012546027069746321187407233874089893565309745173906879366242554194498884392311817884720964399536102493101428168011511520098117958256805531327314219603232464603407104238275576801535878321797400296162005661695869815409401039334730364694075571347993572496694725835676434183599321992668463313984907987009797541057573436032673483258501854079541869096367906436286668196909159046252141876061491279108410282345789537687142051516246994876034766411062464612051365337418888594321337931148820406031811932341822964450625768769408130420828229034668765962123870849609375000000 697305899589521260712566893468076806232234537636372525346130633017823950608273861760311015282435138939573050733663184562045511139803594720891245159584406340212047643498839194506988985587681737054196409081949392262588867247482140856003194633404031399591352243110003081900182166594627635020826050094118250076437313338040573905906413321153435972204043367264769549798232263162587858691130179376474004442096622791676597118952070625934249276834229212726772277122996397470290462020014338170239784658657335950809696514242261253799602703362289402356479337156107606162988622737149952479489206931372832869096513929456045976222844415496154088400016088907981556831852889889023978348566349612140672832167288918379350004459041791390721884042568206418541498854616787918574851131610553784554080019155082982915184393759815596959431605984881171963921270795432645059897231346564626605578935999037647061754051942001175792972743037187457252907087249643823693843879628780857638612088499482135203095588714147193059823928005147748721004319349958677776157855987548828125 -103684608478788883265369719075135040968732204404068437112383605098133369075871803708756843197460919021675156176027205219378328159610513883929921553462554539316978701683307181957743981165619951225378376037008178116379111502165141415211631106399235213047794940444142757993640436237627213840191453556491750312199931461107262361193265732174813148031701854811027218500141064836493938033432083928757146277894957310302688377104681976586616573973522938471609845227968742840512458876617146151962067457763805868790488379950221374520253307650882953249449603404671838019531908313131568642863518428009269238150850970317280549245795762793208150425477327925551306503482573904673434829094995687387450704768062191284917304920076725498235257723750341027534794061890651110616549477093617605268709146883000157103983848692293714388055980880789916080097908158120633762521971324636059821057734263389246593380404394221610054280853953417258761081370985271575102746480322905662882531678676986319096296240739156572038636352898512138498432477717869915068149566650390625000 -495074481231282436010231280922389321291680700627212384611956372807091868908156035042732612546309269231184225656155549789055205834414698807409023990238645249015720174860804317789253564634494647180201989478877047265372557213483379804775297817125081329637277763915140678755943521295332419012026581337965024567229686910288137638639084434318534867261351399102490536181634168770519569958516965556150774397153595190563985972680220441856678083628289973853665327474427065596028408985480292675945222263614229966237857198717085036904817372236528071715674373426532088891460609615722050696722619487540751226331051646220339588299494254089873071950734044575965569154577743628027554343402882699217851887126582289860213758150256018005013139400528766921095226572223465169874820059855638121535591566304851112307371727845094812028790729046572698984333780673195082351204013765590350495162436937483943655081882204835930988865110026852372879616130655026798478647677727218215307391578016769415147827360693218533114226499389221025637652928708121180534362792968750000 4846387207007162493664179715871826319730628926869864538094209320227220198857742497276201505733155831639923644280797253741626287436351269720523172428658256759368428001885989243911405076047673129630685543690147764029107304095967912598137954311927339182024536118664893743462583231814876718057645890139067966121373251412400077833674861717486425851114840931089533808801151522489812541140625691422477246492143925771384992424776455659881688461314075967659895588947694064755725709400143393216532139054729928339405876109689183651484767656074439923457590209929902477916415933387582894316308012035521166302664142122292550364728149750262538827172767966338937721306039621200061256416238456327201729054650840362520385262770823431338214833603166756221289534679867964975843353308925653481779822422431530117475161074451286672601902051237190057894693385285874870610102379920132181838016699078975758965723969594330687202733650701543860148323321602437522026807178687367536422872488273713381085660099922057904976054596747625513586399392806924879550933837890625000 -1435718160663106331321898719965885380025963594751317368234469540557419057740064081891877940279272217602762580650059547030988777968300701825179078251853034489254140426997294193210696706898646291055943933936548289395406960456432992121306515748042264237557040985739801800057410772926285825663305810985074632400818540198398462018362304525856982337264272464117639834255693013146399719423318259064262464708916483095175820739680792594128239127256453949391274863085868164885474800573463318950973514714135842734627020101246865707251231139202071958448139243279952533292281702689846220566172457364099950479440811131857465862691077520308847043169382475014425135403739207229227388881756762240202216330607177787353695005057971790203168214134132900521709538609756631204181801441990795723544661026912897096600037764950242714659052596866686210332919195902888935063791752219297960996579460192630662530722416980154295597545379552258227465234138521993639502602734652956947754902548888010043577880836265962582110895090752727965011104060977231711149215698242187500 216511196102483322028897590957523286666494118855950630216626171797426287587488104225780824033124871223525216252669024615275521037982415540590742138117999712424533602451601204933591064359237216886881992490786605640718608569221512433640840699004247633701972614313401105486869457528667898402140526945392757296349839953669295832982777843329329020574129982712492895521009247276595339956790539663375910863241608565118991600367568140953723993752242963696010987265343750228798123914791569649712321789423036584584489496105433374659654404469191845464516017475735456086897501243033385649360604840976950608602671237227398169903570590758176329136698693343665706816246222381330412630594460693466213864781256459254448439587185110352549373296331531645885876749591806474188371284519454926319877851933414024952789073813041364343731646850092090918158583178768114646228623957650904205927004562657263312221707880468832786964324787241343539502310542986287078869732823897927131650634784422582169683445975832810277784197701411716963093567756004631519317626953125000 -2350100892573825001859095369745861279856643836176602487734597712366408334562976658578790504822655172128734975234509137286199124718481552572514929622046861724719404412001856678862490465542309830551461632966847638876635773175650040697960190883364170271679940693954267209647014450828278034389484106670630132577546476468430941729721432718860385960486985108255223160528430306315681963123612561053610524838277159852069420433272629283025452202296392117132902516406455303817452973275932834740531080074470174448863394534562582230317783239569166121922800532141591880407686342401334208100206496241402398945056986575090437489056328760082207980144959867893628208357556387157191359943927179703109904259631406052972021608600791009303173396235820263514267691115961089804441992993556817772772027076059497277621239817787686006444296121443586824563930201308877591211748277260352456820293404913040913683894415689486308997883492376833242280296732068072968042028620498862979540863887773765639971687184656028756497120855983862242055693059228360652923583984375000 -8493149162626554978380648443225354506461470703826099015535087177657278405395494959275942920235059258686812253497051668093310261638321805108979683270539610453414691752262063320972888583045150976082564988361185460927059341846557066967826899586717187903818361537087167347867604318855877000465778147992934997876059226950541295975969689400313176378723577389311279497844693503997012430106407206858207993489887237599024878283017810138342410790298417489255834731672502366547996031943081155388977587318858930303843308609659360344396621232551589181949727761733562573336194762320345869765149955034738913580495017279701277545670611455961739628132574805425889473068358492847528601268405676304754445328898910779366431556399604993535911149289671591340914245643875954738670431141779672275290849174846888355174869021782010834661390465472743454962145021476966693529455714444518090299635259104804907750496838030034383009033677998250682847867379934198295401508663655322730541568873313143430326737034387027754748513384830399530756039894185960292816162109375000 2589455868215757163073761906426368655775130172996712448074389501419340995077004336500475431759117834687220444615185539927748428617230283075341321530276144330294234807549370382972096901716083496696564190323381640141167239971818396038742663245262492540367140776002630242719316882085300321504450209116861972982188884890111709140796570173881439683161206425391088551656934688744532766619691923595810035582995408447587273814311420354217235427924117361457492928242083135040170191598628052259704974301086810504083475818172492363797725855913446538278059974554114214161922937987425461529642331198567295453299237179025558708248992058007898585327076724304444493584417950176754337589925508189740595231540804136178812399462270135997799144670902999179045776919346057465229990721796536010333802477498364837222949376911591252112926328111528703785279970030633174403057907688809584327134539896289316590337625118697379844669368060648894953261210716291304134077906421842493365085166679516301116811699322689909623224882757874798500097313080914318561553955078125 -407228420911324446117055218304108951434823668545869662644010216788488808537263011948119662919325546997469891486302385863990152823476995811879528025737386645306714509455116590145657967564705203104224027896879519210832936108326874854573496389772311801179925744687349259256584083838799502511732091897710474233224404305343180089853740812126417112233150222096493985927132469915881966789288713280511894781726025745218025804585664288444430211665417819519177855908948944115021771919540266411224331790419808753875297528618852074597785142444515943856951361440932543682189141290916658122282734763709528734437152956409762099698431172929298847806165554200032157169757960453615184931047117053718936492520991068055412336384088411961276859163333420700421475048739317038025993670877655262663579372443900086625296655806225512862626214831991222051423483072328426883425814307073067874849555066240582976089358608323005333937878003524298409289285530484043734330032169420230504646222320038693141301069932271017147050115592143981757544679567217826843261718750000 14050848446027426627504530417023493906877592377596105509944286686361632347911152655512569078506847796666022028362744998059693993742074878827394397191634873834480493828796548409903681510237015169007783420415052166987095753415996318230156382753123926373522783925679327980311519645989071117975589212995047225187361126081277949176683446367730125044573716199681589077659583460302417150264552506636286879092644443155012946925917965091151037485209192199224926851758270834073823011736081806365036699431075953974055202493584135947909474134737291882174074048292907442853050081821031720518740779697496042620861750193834950572253610662523505626650073837335406750827047975157937076375729379161414123490234195269225288743957655441052928631918645707740033193326115999783346052397331087668007002760849531031123517132924779835914950578422804677326942100378358408957735005514105318863930941945811353307279074436101639772119900342278106963979787249476103562528344380454057180589813243908306478723704138138693285229804952329857314907712861895561218261718750 11917989429527703180424804069390388287619338165642061448759010587877810525215900956288549254755155722940255503739576808867070525777300467662948471367326888969755068470202524293200695502651292235963463642896940061804809867976423681611829799730747847291251393356174343620285806657276292136226509661694163540170339677622754660694367103426332305790791012223428098009889769181532181025683108647717218766133555509896717589406638716879461947681625032822302338339292717750357572971142878417466958374342495738132981749555955709053965893889532085938279826581077265042194464759228458075594021180151894864357468448930011270758092692429838892856082626190344704232564798917159138539275564696026784899795386460824959881057973717207557284854749147456114391161932660633288331635043211482514793789997880238451758655003167824426369088217050035616877844686332538485703856083233708750314134018739411794816361838217059695329689293437896209900374742220340736641901421279047016646151465411130665799544422862049365121825394986387891549384221434593200683593750000 -3915314523446532216166951093470015873453179320934323300866330815430239430511483737516766669065702993401885150124154928588666299299999427302317631116996224959231949417167056662613733873990391555534448794138836946829068133098482205684790771971627051715561037277991535591673154540592964571537290186613088908635085171383360663272453913957612960103266121277002522512473184022379829744958377774239446301548440335362603800781705827737996239040967726485498227199399473308795223720996545045474284715694313786516855622331573317248826333458787954122997389514704251734890158745240322945770377425696064915282468387526942789585844021660453538772048131829656205872914976490940421152898153064227171606786061879001715876458273055207030816610012132846936899184415603783911148220104255593141411399985153447550886327726935927142914045331866452736890842674794030169699060961439561432880344085719755021384284109407571438171887916571240431002431235932421510955541441608177836958560022340214501067397549634102082348691489799286102879705140367150306701660156250 651010770637259805115483444313503485465476022012705644744200014101730707003227327261000871758068038335578250166487815941970769960498724394711114955990273639038561110733606182632102805665854367170689689505979473448227117845580103591558078919488666796020147250596601178291703832401211668592336780236184658348099248620201915059497272862690978013823346112482468748747374395897957009096245595763238017319039403083173711154911929487068265637272220680501649299410299249695825803073668776440756161909791116607680885623379620704426664525905587666521638115873218885408025793190671810683212608621575542203780586260272741175255827790005743946679335630473286106111482581823756928924269113362434803373435077140694701125485070530164009060267589914550144773560735620477378028269161876969843665737295190879939419889074541502416703443829083334953797394293616052539973099129312983034575778533491989023449595753239762381471368261961107221865422647420181628842712188022259814285154869008265382637375969484538613778201732174011340248398482799530029296875000 -36602918826527832780910414574196430707788264657501020349886732146217685677178019143805334662072303245388021737545339650924433147056744241726236595008982692065804154937251160571339886970297745951978429483805336701838212197014970524891563316960242061020118943843078740006951161614928111915838285819054254602307524648054623131187408881073734822231269269334474780631087170680726113290422037403514033694595592057667821810305508835399193638343846900616545113152993936264509376433523152640443880729232443382780501250059871940615525908777708246030697353418656262354248426418090161370517184977680811635834074011761571116899508810457499238367903606119902616991790605384888026257221681970052685307867992946581688981289058236260052978823671333176737211866737049109533647234378302231348945197064818038424535527513969063395904032625732254756465242114074827057978938140212297080695921077546464744298603419720845643970204858220290364130288448298891453986146106864377200036888739153299902505582006507210587583148186929804523970233276486396789550781250 -13552312757953176313163637098037970654959697474358679775992340897416343787874784178158805141301971679557905374613293857498533582607931140785003498688495808740809567041693815568177046998659212215299638967996313897185959042966958375732984778664429130943857764257369784857162360632989710925912785374029525945490711074039703115633043507156673720424004247259010329897904993425355652927862812375006638755185099660370196120931181720515778435456463423012885230853263514797849882713381400294519316033200792820000952829327500291484744029414529592078887996621849604007985168653536402291757687335895219692975730669465944475203703403949956861929235964071158594901369534093836988145479609249313670956147620039270034763976796901002034212280006774998927027207427583923509970663663334191813841136898662819018892693100169451093499380215528937844119295423102058449775261854316157442950440487138112869079958764480976600344033543971326453710792903001268158695388898074778531045551416602640226543847215301633198601682916972777093178592622280120849609375000 5041589724364436058242047647876587685897827270268054900982433052046334811800975336145216678587692382861615544926721202891573504996343101317572990569659328236044901223091261409267560321334713620088727006129433834316951099159157157477851476248734824272758548656469754060828580544233426685802856857649891819254755426320263717278855476272899829293511165236326226083242928101362533120682261785079633647478557784629511558805458867796529708459599588992771094545450832677924437842663048136620047021835247023716683078077281042078345250051867815291237967411678100102456402722629934187856041125203916564702685742745831261314174473676370660586924671093105547009412043138640236974851502816814471244219300684615537998842762952680838180374175542370166338188224974300787086453184190951905458129570132263550697494724160413945808158499996941888309726655123591912652809769957271112910981377681275364435179732850953555687368659757072959057820045906053893573636058856467080838045924478599393623507064212749335572159858909202512222691439092159271240234375 -904448311368948938776640414614693313187820130132747285838687029237784001006372936757830167191917566859527291780225989141155042411903105910571632462221855654573149763165096359511131999970991395005872716561265385996151145013685962861841448500568719082124388670669350491010956069461522365949181653154181571258228278612630310763743627691122590605208763112997628463170438689935332554752860495824507009232591079996153476228306170539232306426479999927111732017680934341352446545214989308445595846776158489715095951555769187006992675267541354464221634378514605283546227667729394899824629568566219613153257116595167952056056596241752598220788749147753981053296484661518432258607788394863060721901117865663886204630959413638035890301726834970046692263173651743591134774940097657573363777961036771631665096771923284652809149374041182110274735544232171839927520815155233637140019176322385524892139829170257453624622254899219212590221335091331589531701578598446300733018136382146571511003595273086967665232549506981740705668926239013671875000000 72530947131427105020349688768223396587470997108711144111178856563580914373811289294389103059111932669737924997332741925370206977327656954098102719976450642666255029336519102848384119725410902898424867660420982196610232775526937477673759802692135016378017867691876232136454849441671970157197626849771048089882969224207041342519856298486720820886599205567708821540353893224399211451022071270102008169704205298485485963971831527281398234095489587786715427278998299096822077772790748326674653248694001427352712367648543993109565600080606038288943662125491199648640016720623662583925989417409743883151122686261598677922064347243795479289713437549182867068721634886419882483589591164781724813108815292472802843277654234332240345683232388351120247299934252023301823773283367691463973207313995250333678993589602475614626645834882266969694131041666370488399167527148564480632725509035428332315908101794691551755253159282627319274181835915209324768941776444145673733392112933771905912987327819801963713075565465260297060012817382812500000000 10878054556936135650306873366332027198356250236461970638629387615431332602040305062382699959848882699996067978674910353809565391833901286965878567887278422128255807741211166326099624831832514627268659998699694378061057726960400559732781555097979109632000131675147444452226033283391740966097273436827794370222839661655165351552948142510319271101835467629237631778692394363968565577682900210056225628806054185397102015834975498736569109829695911708458783497880467905005033382914776152433865876127367425275753287448839780312864905144016192378046725737513371679808943969746508496121544382301868799562476162200584652639437215485456887987960945885476772864681348189228979508630188166322547539028034675561287649366784737810134759598903231798830284164390380876232984869548476592145714721920675138377070803411933510499962832312220895942255691717266505327702439790410033869182582885782288343203109468763058973973849109771814802581750938321798299262500011165569319750221196557044563955102237811679855017388263149769045412540435791015625000000 -5305738049026355820219418270778932922052566917005972039409288831968507991921889304428362703204049994890991426100667900834589481020575983527410484493495889118120113172820632505120661816372432742873984539529766676249766707972939725283401273642834106281983108425788341187230332415183392019537330134779260534542675821262017294878963829226942647994315909379086054077285329836541955483815546891214898956854745008787479330315946589928340184310307753235840775561004293577186273044862228559296800202279424840396578079131938990117821888471869419462485041081517436555305478922301145239352834044075332055250830354049638558288653555777384968017821793319698740409131689792425995564080894141618294150982791902156874528633445739952806079216447331028979283625296699932573103382697528271227051889943610855780317892956050738260233805784150970159623557298409012662426273871158374975568069285204450681244112815702518089027113748498063549917191900710822188771740294187402174672372544453280076964726345010482655428774023675941862165927886962890625000000 1060816317061719421386870136285992818146721958422286609412503688941616477387862903506585284503494464820406077524638127079294932724428163502720456157679906763344849130485820942920976385209741985403914947705908005655943055644241448865950155594258512343086733029244065777411326509392128028140038515146177814353161347655161063268795013291522163692200742733353975762900057968539622081158226422253353771183470940139234938093483093147740755902477943879275444025763162585993289321300574109683231194457220463997610308091726693576852112984290749975312953322918428207425365042688537122319280647943607019430061918141504283758634971756534687554322222160051384862788313792703018599428883752491917193108673540616168989353795460207196690860269779648440515136957769293116270768822469580437535216980883886154350346705103381221997749410689129896585751126536590132809268525461069280022616265236190692465675107240230922073085031485064665002735684768708140750709058259408391290690482108481326895962093570004169951204175958991982042789459228515625000000 -113042747113049560570073278649361761350279091223827143299860990205523064701599204791737913785074192698719169258258805374828851137017222183870381118553332651867554668649845292093695217440078296850445753803792352841212789639485955887640752641793236567941229745532938521050475886686791218324404003574612983996765232065919383190842104831966535055358317793831973546659549569899144334253687494863535932357479959607259724014861470660802377780971249586218488132599062714584142026636074166526717643482588517771394893556602605133722811713532571095998262113285350100808254135864977771015595103639819028408617002149506123303425572288437976608040365303567360558917781225314158637427465563893405115906460680251481516753632703245528327478375262672132757617177169274377952638002631500703489424812416742568960545785140778544209648716666400589502607380956367491989991007596685187251484065972536473477671404312029878874420372663604453748373481233276617250013946238608052703926507493616036267520530140921752870752925446140579879283905029296875000000 -2934159712020129374548185311087966907601221533591753295232460482528022469739406328757869584053263298313148688401680962305868646584976398897516092410822683635097200089175917753761352436239741121397922454464521816606717499268652854491416025975455965977457211384538827080119381732563799589405860460674459672146073168311951047151422595113706060117360494036138810383896754353897043914564767777290227695584872377578512157899492305875222570792924995074024908855460436166590356190184973220258274582828499173130706036806983095628137022389276346112484183488914889162704117381866078191309708137649757215704498506193144922423317517549128411207652257063646541809740026562859974564498802614945986720565925499084951244558790684809840518137081668990336485697156839272130637272874868914137603008340487774732743163737213691531038930818582414410695818473063315813591072333472986162079395968958800526441489528771272549026183976196882503723347368138135852941769650548129353209706500782897127047925086608393119291804396198131144046783447265625000000 4120147582991994043550360144041037944292418654208836101323195440952611616145482938009129152485978559544459826652455790668355637863431758486440660264127230641147895511797244099590404998880877976739875830525079250396782711556645883453146445747134393007311262920411465346982536497274241482885917400743665465880939038198062829457371639753135327512761253441506081134413920957005433848671662934744691204192903695883311712381427825537581880228806141705632765024895412593312692845943250581745169101521314770334510467568009045846114171043653095485003188224072704972210233330814281181697045415538826136994817098125185074977964728322177382270303893136420672972450090901143841542836614165205051188978979933869237675441361545415053493658875419400467862872321428214974062053163539017842400975222908992118291298994117845488310177361493893740393845446332774093053689364433442422323448562047132661158870507403972495545001046573373223674034971887452583883846167190246449657109213880933668612063656066721306636679855728289112448692321777343750000 -966262993404831781797902222078536476549923901319717795311032623682674803254681619797907416851159128077924523083626048422716024252529799671345443974454035981208629401022800641503197835961050952166335221668469065854723525399342156778297132196836956962804207635619172288371671279341828900862982942329605745603646850261600014049102820424669062104481956880661860522193574531682942663695040254745520936575030045519224313072482554063766411285437157984609284672820841102712489017657983561880543229667174395852221477133175238181734833613988357045147495646138904381620311024778165176145673227716977068242292214513777267307924350934809590767804919822360058835100126016135119567352572937519716625972008115902141151320942817992202520531032771603899623828697066469375894922797564518575406383738754419627764787386422426602232680644534732586488136568166699441890698168072573987963690933364249827394432277110381717009091741432237312873043970367523584592141274305558244850490895709086620276958190696448003365048862178809940814971923828125000000 127668574104664084665694265071563803650450245610034136639390618439231079978680843552701027694076905723083003205517839901509235882213364978867085052865571326675278831102119391907772550981545443310005329142368636357648835532569909851404692152118920611649702863556285392004067246888643293505585956770935980783416506935035561058994083351255996711763188768345308635806610998709397111387322069235771073100161731484179944792530183896199268116930136070023857907134972303099202948723454556914572113269315184219915297968249135175658949896967345103210226451686515984454256737120965238440353369514965440953525725936833329750701576848599673203421076829727283681957630396953856734887919510156187477166224502708750821467921360614377354513312034674059924642682095922401994196832984392052251484693640227825382028276052803248408809160937880207078582173753610905171467649915139027180789376821880708416818756081304357039094819338406292079548929584937279533096081479151851982367881564481193501908718162390909967029983818065375089645385742187500000 -5369313841389814885430636525983502016297593139065681778175679330012317153354024405971025617352234145274568003808277021055098071655961111057620002833456696043701093577529590984951150435189604177985159274553458107340123309727872449361040456592933336761867416037353742320077766133676572291698446906563536138769922463920503215006347889892395235791190190161871235639475536514744051756782212741353890283365750706560910609239257485251895553695716316424202735336967666492562186628800838777515501799368132712405045495893405864217364598356797860477687112727373677809725668753312330831539493861055763413484069813893667620911943171251538947567155892106109055926208256534084857620809093323341772120451883033102114685466566062302010704296875949131050835199979395861062356239394118809151665680674720640783998227223585081682311997125436943813805321941888245750319047620110427021719862925214554090144520731422090955418189040479909902640090900446201749088041432642082518754385313215564123291083202527129714098919066600501537322998046875000000 -2069536631389454406865082936629921179042361621252704342590338684808699587906696340167855040000382646345207864980275792243164300493482364236138561824265500940093835163021650590860675995668120118830925518495394842141360285285099276879747263267378513210752350244895411065818623016181958244915775555827099487517728830801351246522501602095343285599404823492921343463014677970302417804465950458330444308030535733889799556716810743748742518542509567075210128071399975545141895938759838857919447589906183849496348229520948407949661700213523574183528387978342062487773268273421128639565099014598461090990447212010628091702582918062980907279577302233773037826806393542934152442699402419320584466966908799430094015044368638237434896563435736069748998935582305516959386483135493074487903944710905979285125428737369410537884846340549962390747245036310445849154130971004009354109580213254904396237914393551506661918669270061135727127023917317104989862203672295379452851396673364052155632815486324682652252704428974539041519165039062500000 639850530102522668503588692587659661154923535175561397744478722137403492607918619419304858943980435205240923368491547427036637113612280473024029322075275440160948190383193352341792284378981744664859167718341422005716281106552529517142261704040212388728775105288446824154283576313820357773747983342037043045390647014925142889095442448412701189681889861479858302544055845791990038575759551886949747841420430628775571600712692914886266218155405663311937292964267358801515811440462431924752810638867153583944670260037733657751305183314583799201154878242013941650786713253870916183037949343567733724885829075937005181271274726375450190335888601701689975014193937024928900321803387097130222100764301442625057081309590998220178668820248812140116306022194809376019714924363594498631183108867163723006493241510828977478454155941362075780063416981940759960836222807247914112853644602903900118201783622891084153343973519007063918536355646045891958960794371623499000487505796387447892597209742060471171498647890985012054443359375000000 -101141378201898888632309057918656100658750301884884787975623625102982967089075144823367262384568352315291184700943478493673148652738122667453132636245817361705351408722067784139873930982191049718280104072468992544671416703701285243806917645497111024045844148547050388018281063023930767450002095343715654104297656181167307203913701597443402956138750613208231123657470102744175951449633245979297314590837928839776403623785681492185311222851847427433697321015431153485898407192985913889219028457027346831025883984634502226030081243761510751416236343788860718115574156371544950979922769876851411781129689316153823358596072584287350255661028865945328353549215650036797000698040822711855144101313082888024282737991784717153621975785169540584044582975811321943341975237744842907539020166801828443770238099874411350755011986229310519644226726067872438216098673463998392391026578562969616210463340472307381759815060057959526439372000565339163281275942984666713754171505122630793527683645133263823367997247260063886642456054687500000 8297997839261096361288173596651407395014141659708779972091783168555942965839922924406350780881841057166067008363714513799283243647689809414545266084576400954664459806882345593456468864919636215640481684024386858962090540127721594621307629745746050903120368414048495152268346892695743242452647049365544050186727670498426395199995976185430063068016924727565763678331330125057208286848660701962670392444421294843182505494791395992885124928933813665742232872640828031189988876733831183444899028662641513766189467061840749524557615297189394477266742757445030406614671144428386300668618396497600722369831967522910512865439820131524528939113188734513474419109460278997729256758170290309538514029583882235021662545979600265837085252832701519666918302309153522691548860850442652534761541695331171906074279710217256597294100599330818667984700490793818692039620573256059739316641102976584000286836079300748572163143747529215030475094121442323283189947309237662467340956192250213318216921221104342976104817353188991546630859375000000 454740763563717190082262589338554833105419633389346891425032290413250102282698325896884687046048815197622836830489938502654026520998926278966156920255842549019616592786657933941336030166627546100720283845384379421832770253940004104445449273522520215878559207053909932288720141666078033893543203053583910684287005029996492743513294414273740156351686246777579394651396260017391327396533190599428468658073004539460662801092641372114043704791143235697522219171730258863216209854647793138806468344115280328940480917003379412876235362370256509783500360451445716496742150184660080840259593742366003060659017904782231691783957980466711506228498326401336020493883986538709285853951532161760232860932690340593262819629815426253429498541212975855042531358703190524364776763874792759952989074905902191758276392135816821475134474755772215513901381563230742561963251766152962440288443199620941563111649726585072749828649489714803315073766711761235679204581731585546454757482653523859608387172603904957668419228866696357727050781250000 -293528601215699554369179034941712217048532371946610261635656443433875457991536924478343256124721359479735076449524573198377431867796996741299400144583256408602372166657721741411942129850067329935080783117057646264854498037596805655672276367086351227209176550912531092133782719755439741373082360104099807502065689424861805967204579212324992481667560857114167409948249136373400415455315364647902460168650715735874109744848464377869887112287530328557198554957025197934636192315409167760466570059654580340470445213085008857006263699708724919816740298681703637361149662850062807883216165993733853979746171314322127801174810356444000188943827360983005786492612640297992319444353684077655340311347709688432896099742240970527874563872859914542379121872119847605118951027277857508926217828156477839026349586931117654184105326761197753798102391846060714680794097844347229997431384646973697361707972601973874996496615851549398911679474358031520746216549650061986838321213665039266797925077145947625467670150101184844970703125000000 56079616539674138445819524403366886898592327972766896195204554149371784624064256262348247956135434980315546009131660106251826944308371115223428244377685618060374598293895760246413154714336583883512451682864453581669180684603138004654655900879450994449141658103728807886230153289760203150034040861313767620070065387680244391306035361118716438419812429859106663915330976105723851415035059949187208117772429534374423696942774826155419168922068719374693852897103842874968035736477147467060292028155741272796668554454508041824441526159614484390847244214838810874568980741511654185371321593475413354020538172181924506542542755684226578086937045913569562093666065449290540585964018305832604543954704761131345790124472151836207397714678850717119176980348956854991666359855007264518047665559555877558015600231875811256089652633391102339897569072842070673748221887719636327318054535267791863199886404840036882433659627214259466594661902960563275672463456759435249685064457820992344337651669405886423191986978054046630859375000000 -6145210538304963079053187152845655119929757330146166422157551952791077469116272511599939586270338045192971229599288357496172111325561692122619181377801416682938279461733459649102250359876167722029667978781795782134892704707430846904047253254565306193344007879176611247971390799620792233975955162436118165455464948374802229390525507943520756424157573358748104623597332447754253163435556502309152419335865252273532989384990001437955692090412705566739878558487977153973444841460930521571998364140541482026843618942533085974799645288865554132540112323296480638264461300670425639152932590723120388209394769310611481310306793760371123166395017231654802471768484894509913570538057583284809327810556705953450292006952997998827210449241128793120273507377503576477466765380744815387048900990871185090952209016062519156510321868236429763542505464614052710962471655632305696465980449517664661885266831940767618714008832477675186606888632087607130705019795072628211756815157732687410381544612647530811955220997333526611328125000000 175903440289127037707085409026188899155724734493746234679439008856083085406100138871222472243693135222314635588573526836124153944390739258882185741036014780599110706956994358475780190405132765161295989930615868057995602731357504676221444729039566382154147017974275204823527578170285718375134445195049035356733535365350494848752296449009024858374233584135123254964974372249229184272977484240860073471215566007232850317291324879933656768157844131309735117658423903876623363392754458404863411019834101282292438592765816400587134236763631106805851023907204034658226985448475865739576942051325726437878437049426991494171562213991910854544229348979537605216951948423626977034813691657257437583689510805891718023825843392594798348048094482868784632978765843233369406220148611141496649986652627517588885977970182861796765861409296453619239776428937535800536493224030071456749250761996172872126529699915243131179013512491614050446410442125688050756571581432473173030323528720627809796006602027773624286055564880371093750000000 86169042201589567977924341236812782308397739029722789473101248757622062951519512836433963287237221003114430167698615078471069520575405392884825446794982787192424720429427420482968223912230268719429998703366535591147517316437785747821486836853132219366519505282167511060839740405911841683528554324768413353479067257791644125215937595000880588624241619009498458433996835892938340698748189896326884612451325763179578885788779923947185800993855378426828397197344361424592776532452200617259039388716457314686876242268670665056985795954107857945466021743679471617099491727928775557285506741196853870676176551620651824125134643325361626954095060996655916220738707906140844861046995049138226528875828964816767672967347551714390449947508723893069631966138226603618021021537543708629765717149043528522307516125937811248498676049863669639781777560825320550494868972998689434696041383379042642016307816035685690153312650086606670924249803480548037243856870679651446629599316416841907340096184952926705591380596160888671875000000 -21715356012373022703399812916957325432602173669681608632382151347590633977836539142180011225632865464486725664706578838543089742320712488544925055582530409999285770738667491509696088288064928696962598251523569410317486984801280475819235953005791746172475741548756608018679021150936490001136742292181389277202758669574665204805187645261333940327344228113178969295964840647051388942141530259750300335224766361166320274664603116808851233616001405962905661679860359461852691148837006712106819005484287384040884845256987142049531818235904348277661954554324510364516720505927626786860602124262078693094610964400881972142180999503032007449891093328764589261582999928208024040629448413939829437702291748950089715382663103933558494397626219747587153428564076838254431144811023825178788453108264717842632761800554323180277214758548317774669182250748652235594122510125612311264056832045541871557518440441643517912946343972253977523146922263840671379335556728816002023829728935239852249949876750179100781679153442382812500000000 2900729466301568069430198316874987686182963922096398445410527510659958463798686055562471062543110445401969314322239522639023850199452340693561168448935733700263366246778380727538666581338873523436911026877447460188598155894460466032261551453971324800230907479196716497206884041389992492805414312973545084053544377073517393928509438981301311375727513371242524258244487694223638919814134002117577696033950548656253916563068465164715238195015877717610194576292717618704359159698180790656026625628175315139086760117374696051684233695610856961696655099312213920129243424462347328829870548434166880859136462838274163275599351714349892786934953087771917243316849043534476507054969270159086000727520715696548190224628115619818018886171485170821602135619587545564849629175631813461690570619905369736658569071410034853717891410059548391140175267666872457019449941956201872013738343294999241954382435201058643994275935169499751265482344761828776053261472669885782122332646893098952178835503445952781476080417633056640625000000 -197344450718371415570157550433717067490677975897072656534212184006060225711481221854944719185461887004162980831356806762652034290851514709381662266775663354497085822196498080930079603978268029412412707479320469658486726472229996205200106503427338601112115130105384061534368603607146091136869577799321642744111824880467313529422125178177299735663170105951021250718623793708419496015094466086971675959155549316109821042113201861261320845572775717304211009295724467388519212385493740104783463726459404283159864225307571883390075544007655832138144936639497517427077606554339159845867372534348809385154682649890967968607853434781880099796319534208210678097551221074396386584860428533165540995779666195624919196443383622794752968096281569425614972868635025970410272993599829162760136036709532178820001063416845088767041781380876483208521279524196068613546902453476123635213027080969420123086421692927577342216617473168117830973763947713762584155179288183224776220672896492316569783120883130322908982634544372558593750000 -11736334064765451420660550856303170562491743090787946762603759616412575453068669236391354654614416277998014496671172972852527445112433033800484445995086767732156242634091829045655259427752328035453378836170916629180922699341687533663206852247860528817816985884704208024448948310469106322133937555470680720020399773737295111564333754134071825386181357690621397893764490539262938154201728380164416936985283438595472956563381400852588347204785803807211321636167982256492251098133566651453074060432984163595979598741018032406970706062841799337333079280672294101443769452789086418457959397269353204600358095289685755981108813290800862842793695899638221494672754628378605895684488240828278890070398391639709894565681007835788071536926661544506388080805016552429470306212482302624937117349045269297546513006661801036580329490808701420986794227174826862307423900097907481470243790958966106381617049214048438067703794037191573057500482713928980058348068467814767922867530392481982826069497605203650891780853271484375000000 5755776161801136373148718266211049947777360878805764642492187990641051336061732596473852157429470111140703053059409968404113161726963315979654523281308852997199301060707126472103005988773567995293306258198734024870727980957280401745396150083732306798899630789162955730035279439446512189045225107840930550888683656015092412871215411893108382893262524142649259093480369234709477457087315750670663548009299985595224546104641199872344336926889049209537725986774912595145662084574422310449501840811400970498733399419679990236986643009375173240880018420176650760123277892571354806168396171819406536273765166229922688213671803219650528802640585189922888688185672207653226817013276457474636696093951062852886357379862258512165971728915081042261213350907749468348784767630410484645972341382535470225735703575278125824217695138897989282526348173694924582970984068285618362942721444248173151063776033268933154301849097715481134522829450873465718472774399965652774144726304655483167804774780051957350224256515502929687500000 -935382655533215715728035460064755346293416263747271051464795042430363462624755211597131745045259247540824822716565400333396479455443636673172023508496013996388837381605799084597667844011187411837988576657174719556544360526045548929802822648046851526181974941070404445614744554512571628284395069532348384803070282953544171261821938432288585902392956074925106435391990133899928377298606985657026414279676828166483132727778957320117646562953697048475942000570310225996896451935388491233268056634989851990173195030560534928908497811122526701635970753454163856379956577688658448705373759067343559866378175481087944231762483203401295698210726931542376226398949499186929940931461290824230763887544497779047751512870346580603762936710759750928793193103005303126534547611242690393050255494482691156969910109287332290720489309913364224909590475275866705716559573927932386467805941950117854352704654945211652419537927427212531522581748375174871931381817327192032265259765484895215781335764404502697288990020751953125000000 87648859277101704168066090331338066560453358995136367316432029372272424737704844702638451352270047171392079970977153830108454783118153252923383142382889621366777651690360933692540219493175316237617197990363927816501386416318833620378345629420919223734399292922077899579909318043000109502422209541035538167090027855208875552288449769592343490737219890146186286786128657732116934255321124237894681016689587252235134186773355662368941709921977172747725442535300886344987300077137051091886785933686674432728033759651660697671841179675524432417651400870714452095108875945743643804709548047457354413268490022153450349017223737037631393517698312494007912311967691535086881554998736020377948556299661779168544386361767850966521254700840963905855741503928337334930692840290314329588208069925355271975470865450802908988074047063011037760471017607179998459404661495582348112007563139853710366891970530252353317301492273673347343637102600587114614648939355487483267859883794437952930778124027710873633623123168945312500000 -1967417583213882986955349548459583985502962947881537991664129732638093030986649070958844870976504284357983160197585831034501736377510610536739690655913072798602174384184434849391359489277207686071692356295062836307123868573758099395803316298150035483521607786044923188485148257759347522327007014605579439467695625578012662735403273031358058166435189485815727859802744768881103135374673540561830195851974932085059406017953431222151041989678042914374730301303611788942095352071467416152477511162095378117994296072266415194556115244254421161308063841789958260296531217713228598121660086441991142124267207975466317908817663645771888158905161801977558666800431743302343302135813350246259356597178506855332883428325361422931917565418867503467244059306853014140299798282977935617327148333470459292229540428920455992069872957668326083535181336837965535230261135182744624876977697226762805191140206823554749873845908952804932674216438237357785016933811636434265078020116289392316133444182923994958400726318359375000000 -974856344755053532049936941066442793137105293451762590050205202790206716902676428886926079784835863012479548855352212164203489072901921998689768444176368266592035747425191502254152179773777731552747075226617429232510525899349141049236600727814466823178222599986716637767570431235251908452618192496113048996214282863182511215454157429555489376504188416902839785810119917949137709824828545732984365490993636548954430250999842236857739911001567515987950643816018762768062616674295879720891828694874208373779942738704361529590832662924650870352204492032982903526896035024988412320097372585281580346697687954302094042623318320323431969813032189557664956594692568568667372531971994140394952176138588467821199770684312957297592441890487333570713323618151055912625509322432128701618851961940622746805886220924845609641528125200268542123845639757201912611662808109842974835389995316321534619119055275095223910305798376790207334516159216409057489403255181956438083953322883828951361806502973195165395736694335937500000 210486175911053808951337143260110888549241083127365110041856864423789076457997139953366276023676185965659094333715862843342845037800938012225449015582697882335023851967887904781844204800593281129286054655350418737384408416027107458081051407521459015902461622329478168055743784982653593220919466247166462420093160808214253221805148781802033498324070282805156592377311748423612994019666111776500547900800801374981123752560699264698522525133243506040867285729084655665400522860571104481692521553975547060906057677964720672391673817304246362559781016217430733021527152065657890329409723459164390983175527834286334398816559778076626185109700447705249305032501884938699553675304081469128935589445507628263025208395781690480921175307383908932005127186286462690877863512207212052737741082067957269778174191447534940720774261930571619998869263839986529177546765078754553353482855033091124778686713098245897877699631947682260199794079614135688738765485621148425205548704482183541841777696390636265277862548828125000000 -24426261157714165642036509414763747857845232169792582332652362493997610820963399579652384309934148807973325198400713359107907091324447739274577278700032778061236440861665996641454878231231477447735284950555660083883610273110086769599132466553583466065837129817448961161664704644694389216136685661380350374742750537080664796327980017276152041170464733536479783196443131897172292937641351540858717006026136194940720142005947375976455212739475395748779144861661654462573915612072873609040694225891282865725856857898961364679368179133597037071457352153026940359142473810406677238820271007808166670715132158059786117115480861268260640389433345000203187674319412733251404055086861570850894447149686227805465024744694487677038147244252892111336813167799122052190568148905621600404695430989845731098241010493800817228331459414019758014267226863626918875284319370748007085654536574731157574548736964489592046708494491363760702146262332717716493056604051039939411421841571406265991583950381027534604072570800781250000 1443484532151204682491521840786583902681420990591597759817578428838940009116207449440128651495899138499983479650260722485962251255852222610523855652811223031019990568306757922304732231152299312573999815327782680518514072105969025483792000299510734612878483471141697232823303726038976987643848773358524249573865163580919611205081534677511936423566691797503321862230009619307462791283901164925344624666757385948407372029679452933639125978168693190578280896468566155865899559762654220332615088353890925605272247634844436168189272541140091848502771981681377514855716027491112161388150880017124064210278430896803562326524949370520483552647392151198399096046583873132194620211335461512681309265958715289894285641660417512049322572005432799683284262071426306488108666607540212859803367916220600746513739015503089453738885269247043559740926710506659056691983521383013154050717370840160033145316194710339178228711464064704589281197419574821867323049742909351279539502573012743624758513760752975940704345703125000000 78213277811657136959667875791677025782315151709345686932209102782178702602849475957518417225756509279644110913619856111585483568421422668907139701137222711710283863778055854333405932115815033399129950094880017816232690725524293312729183179852834651317334852228268907528172483632164958974095250526235374731037443891127687455529113197985291546876547912576323212721265453005107433587829534740075756590807280781636945318248155908063707846579605446379572472053712677757080165905362887812704806711585347276382934641654375001262859694762359772191322312331578659838330865866632072889772036632662895368144056228283979810358831486771452019430375871783430149666810185444673585632202054432713072778310392602706043292778448439802766908810842870301639531591085461003746947057178086879996279983463653754084917737839634199739528168618072645113673536197842126935637569829836141259773445119526515509206651485378461240328710716162681793046183732110424547746941320162310744669789674965443282417254522442817687988281250000000 -33025353628856021097666036144177832367202067870302066925408851114377117566763613590028528625489242365593925693923590917759395850107815288993802325088916392459786416829279906019919636906517586870387536728263607720042816828209520787503747611965552077492419893921275352799001716179793664727889352401286740266179606425118940021406374833920711661497570308729334875118093270687459730844439945959753486846043120817119525880174351486539053982236098839427075891145394541091422060397789451942147372916780401218041485999225436548168074680234160976928550136605945040029545064289775521304043677615621616099969657414741183577568532701984800530420366335562900145031805958479178408846791605594738498404797531313457449588148947601482058221723292054143168145692238469282724894775736568217133491609720065265562637116533973341739479606112633940301920178155757256209136478652983317515638717951248464957217096438603662501106385379952837814958602548989548938839803525987123721994152825143231666515930555760860443115234375000000 4697749684939687807759905441897376144347515697165483153246139020035880838719626337058279708591083024634052231148570737743285277815763107224499253813295535206135212198805841026960719955730013984041990078551371447644416590106426118295625971861163759002929600257257427970877702675929986013690829554232562729094275939031898831897241991523512162721411115365847118635433234087099577903168841465332250565570286778364746134185681038721671084350014150967047281323740160882192056045212566428429226442789208894353909495102090296218975989362477881379316789280763084295338931129641434638053766257966418224667777682508128762750582540743024049401254106875666806300797930601221261564782244170444671848341048709396928097026462413645425838414304927844951796166956784663848761020495886783554178595796981969906278297367790715759490169522047807924648804321978716979344418359632637599175501044801424092797028990160453375476965903643545253471888827914338823122491952872134446015338349322831845711334608495235443115234375000000 -382639930305175231536021853370232760616849150628749827837728771905437471763719002512978195053789043208207416391817334373975148083080409866238946886499024045158186220036907983384386252098706162581071137579306545729690062166224400290325492368420912050318900762355389554127880387970491136873945114546609227837770143234362930960288662304052712279503927112857813307996139529955197082674984573501012911934174391440479544640117151145698035287171381584736494826402254136116138360947958429942394737764176190675317732002026241463921712082590452132877212535977785749881738082464905961217466513790447607382788464895130639649288206001094202553948070275190919559940480615558210850030962462706864057882499248277218987631839796184454113301445188267200796207412143127043576799832914267460701359431248045788067015461379129464189901455088197322337643984574499991801373401517437275339944408160998232529631571207881361057457268424119531141471256409906456512791942654137049262784431302719667655765078961849212646484375000000 6343161168897434133606408883727292085410667700308149525749443093263915556523575863421479035287774765390059927171113527199007573916593765910905147833618303873928312214567532073387227400278549534713677809447236521617306914018469596601048010035990914414436223252263038232852945989870215307585663733287529683811607795127502685843368527729588522839345915480597659474796386742630530507707205062797379793851491498695199924622090869101551472335130705374806074607628894744068730045786431763399868271952276452846634029726180208040631590784262937276878993168420908589387815987456869690182019171645912635085648025231310963519803815344210414189398330267171971709634231747529993103683074792076647630667142002141197003877122286449923155779045009847973147279302794613764863596934827940699286022194104604217731863058262417778855812414580293773081533266215338263495929590358488342011361766285841250707751328148384902061583091126392250145325280914826936688062189509046471906639208526712536695413291454315185546875000000 3535259444557191925784045953459847559820613872993516423451553150571741067048845869311474009223997020411356422775138005151025970349091475775542643751732171777727114327171646533376177392443501522432258861949548557652523959127398388988152753959921771469122284969325694846356054576983285938716639439903511664203411837411734486759947618745536534143513399543402913003155521483073195140017051091691354177305612579550101479091487346218921673351542729502576143677464575742202152111885204907901210499722773936907448086849762787182156167630434749170397684116006728547302901449870132111960705376835622994268965720054078522007605342599711352033697016738592408506850967012390504976437079655277315986961208061736721796093305560851444151596761441828149708053789295676229941698680585552774634137535621705169900559405072709460531677046171998116429618569273568805763995838867239901820212756914217200185978983622598327611178145841380872633370427449688653034986542588865242840723279726944383583031594753265380859375000000 -647332073888999667169191534100592602590941693871014460751678688037902284255889360543052381997016228632719241787418377936631201254626916900153666873627731258849353455261038620431774892207062161843159853279438445354094139975571605416918039101840753949504638272019212881161244599641279936719238865755890028849931297061039912186818946309718693289160194677526165481716526207495941047093635142490385208902835541994600926808705500357404908751194172988018606514342971344795741140466036286168431552647894404021462169094230691787999814121760014467250803902378445388280488896495089099021260553469423253197386015539416755790462279675104799118523937778391966894934079415853255971883170103780463231048316825995826816199759152213617193534222454196160246384054913063863442874678701732398528007627011302471143324671677530381547189514008884821501520620630338074534762471206980785431322999696860150114576875731212968092963752290439708000816334131752799916332826574706831089349445829128626428428106009960174560546875000 63205531763437296308780892336882113208707123338795540001429210910578432806657898949210657807507066894075199554578689621291825852228957387697134336033251887949156845807831305259326547492769041633120963394414412124197978685185546118826834904385134299478739416888361370640206031621499076678948728382644746097597041028991148634333442659390304172063322835141735480910200084370177036962421509306308344985175336998371871341318288735424690269577318192905509326170591632886579321659445854727736568761437191246844518240609580217823080454635508652041323899089599761163127744616296161727459713711139035709684917904545799200074910268357541617666116470331779095764347592287572622433773128841472288305151038683710293276824634565887963587314022057067519100340915618954625964374709749322019299584037173074862184758817512391413634093858458371522734326329121334897398436946963509371414829894312229701520985837012577690638195309786181818068220823717886595912409613379993184034688624706177506595849990844726562500000000 -2788745603630686928224881919396698388958628063430845668881846325962235371853364293108228504389699034916829126821074089820399559990349682754770212496297908681145142298407251229856487564595242046128985891995988614161825351951082952504993989346248920317710799273303857793509983230960612062562561282044226926641746865011335192102066770082297056398372257354682766721363326631620021591862656408606963525132679197651043474316914042151319513916386107319678441338906486994387741009172190970882597099872445623963348750369178903706918277117778801336609515809775122836016780850130745255975212632469981320610181562628953619020376943871855237429548807333487003508843826326154345697471470644535209395409781526022883608091452993981861498621780344958431015127739675696303259870027756295408536283943191565483257939588347150619910855167204771648235406490004032374768435562793517087160758429438847459612748380865809000890266088404847251402495263732507269357747420831687224299089145063135219970718026161193847656250000 -244023755687874624688861131980062121578204662873658788589942127168743774411158199317019522173638149860149359850941980187076045007160430252215570345997774260544320744308764699279891405536060007349448109993578663946518268979884445016621038468097546071010414677039758544938196850583657748298204085176249054701354139447330172905769849516419974526152281443046118599564354661252866238357729683945368992892061406064773523755069235171990504188528427725045006458878813391771250203228211588402305922312655795690417552119358594880875430949898027469161636366740688826637248813445796740792431007816778198234526477423292493790810109896349495660560490838646220547112560848545182055470834948268884554576139875374311232334695408893981199354747851440711118948202042970829919743351942996135281994210347813883099927069134869312246684422653913828411588623140007499669385743425402843608792730630771296718124686036039753059399091929032155303701213252076981120651839879268432675907263273984426632523536682128906250000000 65416685688193145538612499127635451601116263522064610493016932111871776006463763980063807160464709716631458860221995679250716228892036359553364706611932275196762084903003169015160234250391475638144334609622594116746671015962519081415259838439905064390711198273984172743752228344910500268282272147991051065457552415622488556358049613524127424915713523760592762148622718416146126719916649683347191644229837097230584666233539590107379427196315338254877254874491432804212991423452815145900697710781238502698726686311276374535671231441738217830242777282385827664121425689400330790144028892697272332360719468607518090335976290825823295986907863837034531393000166112692326969475187886067364999342756838311747058753436138092427714412300890029539648785375929366314898647092876190499149983838457706453948452175128932954929790886551789954372876601069907140559226618950811507848436883355700210780231615998388373500193180531521347753733538136005147035435365940455806899045398949965601786971092224121093750000 -7203718196892995311977605855123481507475234212241135467316596801253748155490010486299302979467220937509130233462595137374784494837282514862773344961106051750906979278033877633684404118665113926135592006408696013559098437944435692715119607596510279624089462018317841729682831509707398671188034495807554343195984944496841182665376817169401322016958872684477961927915572623989749738353388096770116414290308590938921542894873851939953641557593585152996604119261130158881074917011454818319317690616465417869266092377755424588593297148984374030676724909275785134873980288975304584406478354750575301124558914529190325780884100543965032551292549112132374453050546579369329859270687405493038382353656679409627082226511870851300260267720231359688446825509982883541555247362130377002135342021438945330475071794042318388833357260525638098551641381890809642957744410442643462167987954027021401540158588622164190166688975636636605207451643220356191733839048966549223340649632518761791288852691650390625000000 407823628951057584840403366495263253489814434017292571125332943548723921254687482578912305760471861696052808212241761565132602388010602526214078528274852982267000683124285286329617571080712185051008001242465481324066636936368697772334080236783695482037019833019627248647132587402875729710088340686053326973985452398132759163186137045573846902612791742342899234560907674228831611639067709196968098156161971081493567840349205177798361702049678622341909546984603678819589795454413780868111355644380724352918990160800417094289237827162604963512646178218051057746420101029466648561146146697214980181237804426780116484703358427570389541372131644697224674218665857914985075781447885216074960911046185139906635448440114454561824901483280794232166699653586765967766213535098318409294063494724684589081953379481787048012773151458969148343736213153436139629444105153157851443658888107493415019276552326484801722381294880734496074242385617939615989070131139805283626564857968332944437861442565917968750000 9657797577861737336552773857798666719070205731069236753297319638942793216482306425512932588192871117332188214544830787835789222303615914816256101948507674670925724291846870690050189570963449382034015547975251162155750808262445960842079098545565078477691374273232920277375765230097986466020701458072969996450340839592710226644633820025594222993802614089968609644040468724231803059602443217424199670256934980688610012066197969554937222924759560076286313491679359339219144921095134123250294958006144069177663990771956148305236810316866213824187338651870245514511092573535923861073553407703353447793137221725245556952263200339233997301318996238830696463039036568069627901260544036468362816537990536837295383752184027846801445089058320194570971583285029941003411467466842335872605198201007145742698953119328397171804871523750510651270156491007400682636290023277480227930673575646871109097103120440605546491911675888633300452075956621963103772654057714575071003082484821788966655731201171875000000 -5008267247348079116081728788880039077758154451889401141681713265155041758688829526533414968733068070554285059507575103205331025154474958370906008684580822238125398213946669712526485605946135712223672101855881051095568996126801980021016085825637242243893490969140838795238988838748972015603036092784782750028216548291036294425155057958233266189244032171985684679171737288538948458606436299469712259881931321550843764835544622992886307873501776754325909573394458849368078552916905995771332035548466242269937102556963097899340041797968536923216835834867349871944581454308342505671633998702772515994334006367157474880499701659527441908600100063851116754493297650676395942272484026986335273616365659976932334103666848627251060602064833112524504201030351913771067385328614574349723146423821495431092002081338924064303711313129624036116064190604466963128299045900073885747211350728061763254463794405336535505222211003119034279174269220845672380835992437177195402142615421325899660587310791015625000 590442238571972061687271143031649723739768689045301013492338971984543801930648221884480214510757895939519342107405434852623527010112810904224636758426937552093603439015902079743944178243443191251553970214839193585088388286642098385135044934444954000827717952047507930749122631604316790488900719462701639278334254164281176217198195850548120310782637169814205766500842686110682072043379798442986017520161578657712130377618042808456591728247577858553175691294059522639797753534500250154455706521035092544300737686540274534303905119948585458062696410472342970539595641595811003526169208565341535924760391459765746924535730757008872087337892345123916554183817963624553931525016799830816525329244055927751937723573417123637345202407106356971843627632809497845816400567891625952023135539204865603692132100480216611066384593684709578208603650499701326483500162300116184686071683895095146606090352566435351787059661588046585282713324453834803493050510311834777610329183517023921012878417968750000000 -35452618948294887812547303521995458942229578694189638618597811549238708684967951423705380927695165651161216785871898063882735136792678501154616268946666224307555942458020810580085035724857604405750824489210349605927482791466514330931775534297106603467267824670950823938887686552552050337068219918389354683405456211439435757635271146077833248214921422018254183694144899626815735161179522895522607280365352020855851380907419318517695599680400846278777838362236162209329186388255811812699144109386957439858138383548712023604404990326357736665981689331206799570181423571488732673512187692098150060796461933839646573534242080286933213608831461436434979217091870914012188363376559172912727909965008639615332953357501517788912472599255863107109162887491079819307316704331538005542786511298958778439598077258205190176473075571175185836064594873096367995532916675540095248456975152656404707082674492020952671938472549528823772781760711744312638348084094908063690354538266547024250030517578125000000 -261794018767755077149395406321294599364878569119879333742567543707168793270197523503927646501808494787840761545602185840324380838244735066228097620991120260850907293411912715105970781296075570201827990305407381809339419156907456573017713496165313107988046520703904236168044495388250125280524598400980412644076351592676578357719911353119467617760795861529487517446480219049616370491073608228153960061813396588408068740681024814269924512038894045692998084051037616402907549430005850708085411348717298638522220778218750557966909870116411020663170785706617453541991663533116335918300642906812532982279088662415690609972274136912869138995854319934148966479940979596097761470869248458778033598417579772727945904116159042892069878934904081293847646328698078452075379423401118119844885785729649461692685844959394369702302980263615382723360567574393211891253347963446313042378512855784993358421341674964038805341102330401700445145484553449716095055443965122776717180386185646057128906250000000000 312156438121565372781832361391194779467154077781312475455488260858562093627104119165823486464358406403937475342838044239416194379566375271469718415694529797233693041983365844569507159455372956065747569851082695467079051470559361504403584662838228922438177588385764142660516300546307272969775953669435416381442685753002212168962665231187515707953393685320133447290550276109514790257646470925548620035496478183807899957970644100084507475793916843284983291758010773305390268410143119914192970158014051892346635366636253913498619702855901665379261793588731759234513432770646877899206321697766755333410692053392082643252670071527114331849468418058189526332695609458097178095218110708056233581429644017347594559348260349182428870522710215003433961771587593226390172557968720562393164210841184067117649140318127867761753573325521548781356257380840984123420212972815590518599686992927105019071030179531173108742926178707072490811206059484399353740839005988405574498756323009729385375976562500000 -36010656483636485652498799867683627395466945866879257900784799033963485473017682706134018973831481497974616661531212527418648794944727083847168189332385265044286731099718234991804326458749414402635584659173672136107249374753561570057213183934617060036236212673711710602312085021835844047317643773565340501104505359611484571133759230903296698962122925617782768309457214319671269069333573183808610281582270470804019926552879255766300867798908252953180072991709487293757707470534226980513633043909485909968646396456640251859449754377976547922110844789520998003937169207108949511523395951784329498364266996539683668099501863597017882065355765891767930212220797371149775186662880995129186778284070038881858987748229215065012175603328175121835407944217869880864640981948487244810599571571778378070331670539434151315461728389932526137859058199942304886763632301999405189991073787453471318975635099646780614698753613092600256503929036652927907821014619216271057666745036840438842773437500000000 1953025121892632715796156489859921046777438133265528435455794767835336604091113010275144675489579070662438379117279552860463841932881512574281310782134759867470350171441721561552059133822014950969442425758660299511087034284400159960059564946319376154208870277773778945481839598873615756025165394563181175856590666135349121234408100476591349549429935290680873890729973669431066765474933359334711747789295990763600276960448494326153647364269900376045008861419712116510570164782919954976255316821548280869466371013041843588288868173108506143652011317150186991434195858796262478161022000208305743739747857299052975462245056574665904032153655858486275935742834667974914107519376174274705999540512531316133053800310936277291773762198805615953046886390115687745033989892380430333162362201909197359405904732365974809075163973021363462838669826625195266149574479893761151050190249362118290360448797385111942612563354361587350302414403331665527434150841923354846585425548255443572998046875000000 35095037516643283773298905494167054927171296975522170371538600307339088595134527196798373735182912763264412942538124411492387469740336932071922453168184903494344192163528290117568413315674371207114003805085780005256212752699785723287458650919411478300205827972616726113836348534678472667734135624418395543283139028417848735105539653233253692466811566354884328792543886722618881723575601106709419064246154084731019715686793320451752941281536188305118779017762169427969422989258428173276946950348275567375260910694784007465002184778026322788167488344972216378596130392413989835803613673866837408538574278455722969717972889407343859278583369241673942488040089198274096187553111759546645559527885129643326792959863732178954130552792010352964494092734636414561322090527553735876153751725778047433707692340832859609470194570697203476061792630844856281801670115208075770196971155036679870736234886413125666270620296742884542460056785847919867335487076331901334924623370170593261718750000000 -17819278433193492864415561763082239902649641395001667551801189079120441052561336954750769082716758025496519180834709164828236446012188228099189504188798212912963642508569530045814038516460557614717754489374002687487893237750718219885524210829186878080878755311917701311193777995131385305247020417782983490174758638378657934071953240707500098322910400723221008082747738992190586543372552539926837175551814132877375636089899683729072840543642131441221020331704786205123905234530120404322162135749435268189364235879075334915525528640064946093051921022522652131196920485171324922244618798540780045062219398470533715616430919672540604202994832417584288620581706439656596146600587181119241300853292051073547899404780212056677626330243215559240591509166126363549138118937703344477829514677332574563162990184184389187211584542759408342278855558532129957372891828337992783863508507556365971712999024384531706645867781105415161645808183438807653143666487327578806798555888235569000244140625000 1720213398269939418786097174250264785804065266006957077262611922778226402360712475275637455098177180048034919030231302757668635991248623560335421298401751725945300418409277370751720327196192880799215024080437982075638327534497881320115587623313343354869145243527042213301829159646191912931624634035449183027495369361014824337764726788992704362082898699827041417858541460051490080507215375283018247189006792253855084907034410240750072634479450604962406686915009136945205373712023285374510104625999943495347372313817670831135646897306857679883843319607335591877021113282780693411668755050267025597150299182978598252044001040420039310058513710400171572634710047018726297606212323326105932736157045984845746451261083439312597886754458633629385770553294101713077160296004974271714752166025849716869648855345214051085188505321445531864574098209902137081755066830492239679491190287123126071635396687212960838668869055427557923006500519499408462242850959000861621461808681488037109375000000 -62713802038241663909565688000504642079235480969141080208131158911135432575437539881861464487329409589336316404851515684009544651373852719410514155400396015236160014491955426814192202420420722886655638001866040079218709022712921870606618354921876718857766062360411419351822344551532844451466970998518819291864107861769142599875269019527672583922366500215820414903452790344985568843327685350074606639992217848559603938914470083402342163228214814247074599341225550165247646935022489112078343759539362136424943229199130164503496313442778499996119562716807082277220441858218606357572448410778288149933247193135386521437428076353434945992043640275505809677636403854011517928098227025436550156589434358092829732037240376547870149928389329852737946650906201988221350211451901925071119341949103059716611575043879879342782332430059291661466130822698910200075868554548322347746708589003186468070908528970177766254860870927802059399090206880366662675618805167232494568452239036560058593750000 -5208213326679576835768406255244403156823173910420674604494511838629310530950916488897453739031497788632889277170861040246599225621205347111985238432197030018029790278716186482609674396700353229909096408063257061195256607511578615335439526695683797925893274520705268010351816834445179828315132906148314752228756401780875445657514810630418539741656534413783971062867949600003989672336129991233110296175715970969562693852234315088363647937679550430920530862023382897145954686430367370271995816093771733074693524372884381451137719284406056422858919557593075602072943328055925956512855886845073689277303437180190738453557022380572783518999712194991748087067211145819878991334674035769918882078794603612325774189685218619521669738043625303275753991072059327475619445707619322586016848175272195479752605470571246622421177842832643604107442410442823723709383267616692257217349990678145163207193582648491106456776944922125905516002007490726326277563629219002905301749706268310546875000000 990189297706255985486370279396146302767136361090622943114760022211957624354172962864121862424323830939406871174021312329305097244927165025861673994367798968070351729085945821093757195608795100848019250583426021007384352788061396695139312247248777599914054373550011982322346708662843733272743279240149112657463105703298253935039832650760371383693777307959821613277062820899477454475750273937019349363734429785720858957011734634757296648481513220784430321707053043048983943085094946100120782075550676499409395628377509308790194096156839554928724065471848941926180467400072345159170107623819517714534592628489812319649576222503578609354687923525087924421701984175312599849884608452029532393905083514623803953967586785542909386696991434322879025992998320026495945499475042503069082686059104487766294556804089710075515018466420738664528404988742024745433291242125860950003194588033012401281325284139703768811017460462144826218394464643077559906636508912924909964203834533691406250000 -69095837258394669540007556625827915153529204387687004924695276066095051573247819274987838157273279091233044971489198556674659910366292672032246222204090791745297566768123827989238039821937652868961809818114925095977731152920669916684478110744330024977288468998217624637278789534907264085344919099621942989851464309114600853202406261103377239919704312681176192193170978372854473902164285142665695221521629520146998186232813891957570422810302548194520790175194159724281919675593615963809357565784442319038023924943077905709029420612653465482792352547633813929043663226435477826200670318776811823281937306944511270407493557181934576821015738949024097278634129322885449245380492162600667488730979898086059275506026583908821223733356225875836771772274745075812860497617329621075812534728793320116501872026433311485199346604854282174550758824481590635249703466631522874172869041562574621306883000111546291718822776820705491384225324820456126673207108979113399982452392578125000000000 475649072976644029871997454425301830714723904009409237746545941817262797468122462707969682132767742777377059175680485963955375238188562072151101489108937130614525371087644646534800453728547605498592294721731174773863742351776700151856527879398809719343357780099076993619983659608178671850732645406156804746481509714845805204615894622410829802654861175657880753581184814143807432088252197379659112787788110090245126525402948033575337560178255767612269480630221963973599007221208381220547433545844398908156713160437957817342377632541153963980779106818846696028232672989327545710661233004035806739476102359551112203437642054182205834091977795197870224300366079268138958596286000900397741741472899457980647904625925496094299535695534776278868617866687798129166204786085393354572979930909096805981010085387943385628944998428858152138375512762855421213424952967220555761460435208392750454326044120982687355872291097175272130766807387710140564429650567035423591732978820800781250000 428000179173557082968297343318801784722530221682621242343476682513371731869801126573268533359614142298956607342573165159182018567176267994027213139264468121402868230220051195114114600231171739496949823037773827812318817592096142468299826089450574201328422621859306739102497341227139396305123889992835291620499921886171617581839018016246390538536967272170678910564260703346800508179585140518785720510631934440677192577635114124418719936631410796763965999567797300804302554053148614049791897803804137763600187229760144167825732124653780959380451620917329614419218180499284438861887709879605806071761407023276269631956269281360792912700694848026567241510248539926705320935389268875777387383925837371135427889429414215116619128869002902326681445114219609610711766967028615557519299933844961839992875139194077427106057937318448344553729934996621668871220527579367081816832979250741054065680759690805650769038354057193082774280162893301704407633678783895447850227355957031250000000 -49199852234673786000994102459818727498706099040991653435447606235418915786074295213702017123038627518640736024113314384471423962066002400167298952261816637900037682928899343850464855302715441179243166664930448622258221826667437048306942357195957179616909517573715128043107692331348812667260943346044451271210968691504170139017522394308904882722671625936854072506609676914670254794782849209078537490856524656932850537268760668636831402263869852488734708042432129344900885405934900014937007691745370870349787284228931163504440961858824981040750011222770193546157549844386116559685132681507238333066559572389000870639053420804235984519622756613862968682153751127857426270240680179929822618130164509267023922575252349981229921509985726274741018385289860884263130499091405804550401985020503032816456365992412512327392712589032442297478478644447987185786733490185900014296572083991870994936447492667214178511171832902192956511712849834543070937087350102956406772136688232421875000 2394627168395081321811336465437568414820202089046052392342211294356278080428441737225176473612307309873245575927567359485384189882302041018278096880851811217338680691394876366637843439508914093484844138860258658298731517335811005338437799867185244293775769974786896394526507310775878615693496427782169078010890156677408473915891445223066947638299439474355852028765471445739827784780316066108688328082706050517988562947271408746648909261514657721449386418026779925009705624632252056370889740398188228558228251162666344748621346982909271049394169068444435619095084074235046889590651683378150734202945754896926884862266949418089936620819490395374378402158300044633733169846685582416306971624651956485740811990369811505403891374972138390647809994373554563477081242929878623644023632961319010873165299270284475941266607993757075540723274270372707151373392552273382663076312133966003831216541418281901238744397406609457429146298559387295856737409849301911890506744384765625000000 68055356475370086397436014384679015030386411313333105373306536460702639912770227931774038995580341091832678209888964757166521841145565342721936246281708993166648026072483035277810520873280041422843348989261785127938030116762018541463500856719765074698461612575687461397707274149068721611834934155524045420238765118932377000574289566450376451051060139372609851952744608855413878614952619914015842556831721096143787944944693267961904884887647126398534347126725825831364015714373586608316269735895054406244394076753860756355622199002410581981803078629218206670092153849781402146732599296985021078437620742977473475404995120278861044660333250298172014415945339734592151947201743740335031576603907162472230599321961996572801812810190557464271120649613212482368883761452660304224249319657196060059515774568468087444935567998047211825257120781747250126080231897415618204463812194924371810161227283645985563859885886193391477637371078657224643393419682979583740234375000000000000 -22527156208320830587926343463528879350315826414731882430512335803205555102852313881481950861863735657519314132894243700950771229228470362990992189086397193418909189023610465672818150600064730817745566678017792277075467011312117428208336076908602653937954692634758895472089377809370521419256632257863337813175107822584650859942632983619912825871634273770653659170502073055320095321292520518076019060499553390229190959071534869865399055166237194206570457752790491444569743257038612986012993912164756478959846034107287243080537216856368485487118572751724846348966717201398765632388098722957627011593147440630760604607601129695196853874414137681484921444863052006956636587153806406780956058539980598646592902782392056030275404401488890365138355442289691127270281116024262908455637657053943586172858772072543014960660012565670947117045385957462558457261005519135494929787129566606387318165574149916554547045742354545459842308434243729475809914220008067786693572998046875000000 1930911710058736689985248707005312707940323163813891691874391082350704935840853770874718036569781865329421874119019959093326432504938330067984138984749607460034199423316264798498263735037061177722089219640744369183936672686894263503727386766187519379316842298894702944500358303343743908065955776193783943724288681532159848176758787374356395632193341532448587370759693957775261096577797184537629552257713428355289201539280876174156213955792861098183896819258051733802557554946585702950278883343368132573742113011223901804649737266523118210920631786873541230331607666754842044162682795293458149494772752781268444566191363503369895980412822798338726961400571817407512193006672045021598154619301552011400295552235205224157762583220105886943046434811398621686759322058429288706997614100372838453797066483455690740913312534166544856036064664700934218768225675907777459801929207758376332682893703924200150143753647753049394500640505156763282457177410833537578582763671875000000 -62858974291169360231420198363962805034598884502301468226093105709483105744531857736790082889095401465852424342489837237148616153242756827811132108157678637047280437722594306353748004536710524774986009454631805477781584590327031684145178175955733282826520430469321239635825554439629490246121535316402129335037013229432429519762280938072127765962271466740905749212332705638181246775591930921280420447465555708849129226611533284906750882437948091728885255036269237958658349669530880917595615161972002244099725210170990744296746755329913596773243567803968778347756472432573403089856836661740327732930611188859688951198713528259696427297712711494700305574534526853025639905678304013936780502537732742087408588740889192482754112322111183878616777510227939835444772356147906811176778365047149145148639626430452571109546583044652454747769191284534501381081185159463138305418259399774581269786672635420274307513195583863359423219645261138310843307408504188060760498046875000000 -4955461125446856427562958382851841933702635579448729129101800915459461177081847955021872630830859358701772911221226723512962566071251908488608046120347810020485321142368040893864542947056323837419126844862704107774711839779378544222984984681706443379506268219170358093388660898792435281900606022439149974823239981443366531721471311641936166579239804020646325151230360320029705401151469416286100313680826933733193537410689262696442066825280234287089669081866372136198198859474191383133388541749245331039412691915547874883579934699263828566316503248504958593985832920430655787342359407270428302561647432167445924816024162469292952183016990831920264987624652936799595032078224580747362516090317666288215050954155480442527565838818448049614336955422747982540367235357758302249398577896709361774541960649582562760596336315904503468504797879054825915595598436761373233720801853016268675449089429102190973309041490327487967481982777950832996793906204402446746826171875000000 851945913168428195284063922607343510009929039935624079978348106203839419208934029378637516562206897534087496584214951531537555066102152568678790431942367848993919385681168706581912021568260026538269923348221273831318466429848036822417976928062739861552046344146670208296909503562616215878789709961379905101443945543585196623058528217163034379985397930610475755959747008209520654906637502971612987923624633125153298309008081929286869508549049684946644770573477854646437324482752673874208564217090699152270809301076341809161576776694065928263167850156520791054273086122591787259965304932072755420461885079772257377812719292362306062856917492199479578038422405351173428788836601954969299081141163879702857902884382460676903046793424206729591271035904055640677204282783398466603032495324220817286661701291144188216091492865990217696956207349546107226010376109151543653859869763145188145753050751819439575639779175536631865110759331827239293488673865795135498046875000000 -55730756677697934800232967485399237032253636554928797247090452975967944130073784989585086720026618236674940743460901394608965813463361952084329436394720218966544551530641521418614174284595350335314838016880678587224641450355434742057303902931843353590993713732406679799528112896992385069663923898809504735631896541206075323769835332197705361722857216038310102924779353074728582122062243857060435075023289556792102138539106726921830501892577387346147467550413510407379120611085374437269761490430021834232266082743529167844148060725376843783325497931019354229340726087299070249071205029675962282685096795082682456742122138316361611447108201823767886460343367791368015091067347380588065198865199806998448457154119053999833216784176969256558799976144670911150804177480702618453579822631806324316925396276596374570402148073425362890988556287928208138155178966550315947463224538637259483234266252181735508446360679187755901532394520181412644888041540980339050292968750000 717162957810477455963804677297560902432520722559517163810399177831528971006498057001358906675462629123101763005456277093620519552551297385302032116282902040996201982403834834437965209198343760461279385047759334828180514015796400044181198748509940383831523979769081095806200055486152756130656451572606969674826441055937231404593105013878267081133885980818556015892539506111708241468529000843700317390106032590937157142361372282247823397763150846504376755759159619171093646800572713480001758238067196647540901206868463688379568289287207378725242956641663476064878949223117044101711118299517884649507336598173493087502476226604312501370647748284975998238405839770367820065698434231199851002076473472225260046458399088811225158001617596897197293206129101637285211203741325105127323966416872115647143349064423079506799760403434128229426138755681310904550420667028558892920456359459462383960608379613751389442990266206881359856151192389006610028445720672607421875000000 230131344287291762805143550482213812110858296421924075783405449365461063904047836198481909944887253496762180431540808066184356258632457526511431175532514617617467818030394178516581610046592836101467295528477705981511614155619030017656177524378570532936424072644179598675195811594752561549315161257183522211143620060224409748759638628378173892434971206846450168825758062043718079109881680443218153987964635770374772496003146633224896848097366016602559317459773162450410328734325480350500291114451863836117955082665053005835009122378323817732883739635368069009860413208738658074503175009850113949033969895795849498897227064575547925995947829959320342333282500700799951163037761444003829276527040298685417674280562886758541084170630189479452944879888622546423910853346333940979228979829718433761347674078980894829675500328361086468105270852771167408799245299401014498147375058472731725981515930463537197657147316972551121666556994682650838512927293777465820312500000 -25239217576530168041529524517508805112270668068759999192976004023432218905316234776450420712110924624511497570911587818485134895166785964682393184716036289320542676353251530218377327641541908844829730643403929195974304537080375341229279950569264050761824424536242332625106640743137418597135328895362876811135484539722414647400662667631777845446197660915931982963289945125324328360097492496657496908804468460366327362067359492139439117874638972507237864649059656190195677183101777714305488057135225002048783504036194626441899640538338062409351804331854549092467572970622592170371197405855468267724277156389731965706686602583324760466185542500183771893624877203120531643532930984396248441023680757385196930263142679648120502450120696647543514379913994493221607733786928834119693223871556811902208575120619661837226729102919008239344313238141549449953967187915608358781604166920661822268266910556752867936602031351494938860025030180622707121074199676513671875000000 1129261384654065069673089619214258783435667829064218223518653130408617042461571363445692153014765873052702572422687360495090041881748465443312582987630198733821454702202870518054804181839560072382922622772751156718910962856834199991649194946475552671192947238179617929865121791016378623217219672497291668786378633252104388143693437789992057293838004509063923528086277082801525715562890116753491309327550746480517146497734982254938740200776326850929380017637949181419105128769910700936743365286339362691760955132174881323563561632178266953697313380248381030568050236856381671843570912997321587934546095807949338876975010687854682671676943237686220450650371464695999677767152561448796286543140656830789444719175693363007630542510362324339188996153877305618419243492402820573515992249510334343697518151296681681060663045824127338545754170525112069697336370250913297358860680441689726401232487394233951512454066464961281029966144728859944734722375869750976562500000 26693942070339411257836937612213318701011600173129738807417988903169297329325346270290637100127184005603075787872853024497955178316595453671396191904060281771651018112666285837491484399684316395667287748731277446514673119979929272060526578933712178483644065835235990141430553225162421726618090111769029832689166730687833326368687065387215669686728246257857044466865391995320815875215858017739617290972761200870307616277133245107586692094007186717614903414682230059180497517633594101723717887450174453104421754627579022055234123355554007892286335988815514782964774065925472770047563668186014539076814716824295202218508671457499159887764240483690843995318120666524120132222745101187571001534267248743881562215547087068639012766692818732939187288439240264547404444465223718782891297276889533203531633426999605977910258465593549238959740577033912860317165448310164290908735983491495222449345945882316882036674866407292838754727881678263656795024871826171875000000 -8152329413748851821828053074236351508473614952105034206858617336634267778576162758925461835147032135524992821409373234591126030618942251257103675652226333473141277453829501575303579187841594530589498503211593192455946284159637256846671243013279348905775233361771382397860280259128855972535753981528064193569032263277120454068794589255263766033522155137596327728732756561118735201459745543212048770856057312114815285682281319976479366462763056478506860362666440982350312545808947814271631845886397257856563686014889434352048646069490342984934270185346399473768558591279109855065247256605212181288987289444113885749504234014665589761011688083035572095830458110393579962583712112848253247504292077856757411436937490141753259242699218192698120358258713510815290205807441962300280304301184291036190571032742104161836264275154244222063178239272988533686393759947346559924363672404625370007771717201265614284490952352966314231608180307375732809305191040039062500000 597627114344148753911737023369088840449407052934904134056703909953793145288341048670624772383617535003854524155414972759926572431838471650385046201964457483359220205021793178996659629532025729898699178925928952954341356614776213433385614957817231992905624181196452383914021254602158694929447594393948395059098521085965106355849477010724356414066851102329227475833857719270582926830715803477737083112518230946907761571624653572821096546057190065070735743973508234820171643296908313737781301043544099171929049784535148157715060562933980349704759929046703841373816187973987160053842523411744686417883746036020974700566439392402251567541906833946058077480848279217086654492331014881050331291349436657277469630251844630247748209573107766508483143722903541382940093305194644721295208201617565390000965062436455222849639546902467523899619412543712185291844106619965011939483904723084765169990474632292701377240409332629311744966571495751850306987762451171875000000 -12832920201201399776120462367488390289871302784132004780763060390719601503697362114744542352269523097799128366310063759428878427946765865234958771124255142598002400864921025397487135230333694296982802663213196859207676881763401539705776224090155172055229193535094047313455045937210239833059580152464323484858007550461263768542029209173288146409618455532637056271296064937181252427921638505442156146115937169467278687892018942897974081799305172990461117404534152413978418434676834465434269717549880436586508476963455498212486205722958981002045043412183876518858351434656280002471772595576215129952762963732780862623831133178809924614495700456133870194674637326152724062969085358192902677080286555498305877552242358677347981069065299339066657669691492790826256558757897069646681718186285278944044637965545998168024045986728048328830820352055333817600551986461843037836384001477940145199935553673754969919752890817124524325265610968926921486854553222656250000 -1779740510917505137578814340353389274953395093154289966070218297545838918732111055244629432788273980357131470845780781174785482212061781438533004085721965481787436468540696891397797446114884746017275701903179804688507843075236873540323416775045657259470771646270906296821694282368963805282074326983334751563844495444641255778502802793058568106630585563850506486705444550891231867450821646649532788685297165620070009368805181321303170629938612570404172983067650899108855014038540461593966177287885096264835473794133038883098468570766996237143608233008972346871848330575570495390718775067388667989560540195506565641312157946196219054570194099321657427378024890340270749434661343291417342643465348978882333316417862657466158572394949803294760677491174747658808673706464141560593348868373214137663943611139745678094389809998884933764234485884349182057292162607764337068848014950015733468356626651297866627940880319969085832099153776653110980987548828125000000 216084723042709683294019318295796797322724655883045828278182432013122213299977577793147644623329894319967838470155419273501708549188437914861260146749775269268099102681886466334382895488431809525304623591647937430964354392424247527306606680243289666893600325027347930716069528983565920118576532972400295694162294523292658022965113743084335873127178624442752451765545864708375373987846118929728524292254423868032066910082630949346602416354221363409518284424396361767463995896837091648605852955551360851645074082839909386043489741474187925291010996944639422502741548028326985215616987130908983240747819978552925364526862033473447560990486244391040042205370822583750066523267872137524922061469629217203409959283199496195889725724401662448754735524843928795628214366254845307895530771460239978110771110245251021438556760758772429116240133305842964875725295111407345087062959376537593722616589949043654610093246302982006312731755315326154232025146484375000000 -10141283063830946852029430928116541127655918310457445230043523579296120364960141727146238619105090581419679522506484605625656000323855478923022359396937138223154399900911831782072771676109490947608643009060715620549552825526788506236213764086497003598996002399334428806592404331151030562341976378382440769345088989022749041332532021945139129485088602344230655579802630348036052466330446657420412598081490937470755743683475924500640669816749008910340086154777974259151753766363191363173403373035507758528719096215295551570662104365504446375243831871709117946099295700661795500378725886890820201420718395903190387642576788222840941979765738091966283094422028804890787926268701082601914080717177681980987579721889894597608033087815227329158495807904776271019757791008943276657408845773709491082187088976463144465573915456486171723751644144387796369591834910638129614773634942569920327573844971469851769239650836340604911356422235257923603057861328125000000 -145080873422303454354492002382093658699932675923580266240802980772438416727692912698796857096555155077813046985470795020187399556032893781142499363767732806811451942029058994528876085626669422032549806139172000344672943871625298203194897608597485556554006521051012509219190088473718324349139016864002682814620940281087628718105011456624295178195522606295872804227570279856897240889150455473744202379394592665369133907540544954191927975648206906295006099775464110407546843529280287540889276106049735945303235533486793212511630247896361794601381633927627782348656428524593571810147535945600540837521460639229584255209328700751686451332522761069033630559499272906631720688425100591376353497027865217171764294775976078815088567061786647851639695089966969274785197778914712354700116017980034181976208617568534481643512937997566625467177857493981813249748646488154531125766219377600325247689893415771880474333249688712044189742300659418106079101562500000000 58580383310990446901878801614053718814796504617950061851477788434540509315110914980812102993312821686091374205725849908953568822134875320673783461686659836123454162262828635530949755182121900297364451952507675495590803543175747464089867217631021100279450758701954513021061755387074872013656850131392407838633901184716238574544060476294389645620596284003026050618008520932247667407748654490578784036365253587347756827237843578097009351595630735021105623614508551502863713698318403418693124012902243510809856352192222632515809549202139396561294505026854686469583151925566282761802350182033572733949708281605807059446772296288281702740711377855501948976219993564638769041032185150210548110742396945851679379960854885800066984450896279547465912137107831674149175072829479341197733739196218332014137589872251004863021667090447794728530391736030810813030299332019393462063213729790537000268681110581740743045546515599397707774187438189983367919921875000000 -4181645571447236523568428286031662670654881923572447722635964308558124726799747117991875364155137810992237883611041922407933105773077775139938878387746379692666640014899097363707921839331873269118135912528532828370669736010846627454876478096099193671345414590671768862162839216195143451115022562095407961551778204949196234299802082824107452898689019406625122317206007015232609562556632272020610968289785872634186244401863426755007179471163152140961047258614686832715176235742760531715919760579006593492325254529989048398062047683749947782974029683627214636221775181071294489974219726466799947603547136653856502614854974442011314076537167340737784984057873421595624481369209003460386377131235288923254190617438464563524914986913790498936384247072242322807710736831170806124511446619839643523943006993069651939367872217505805489324450311892487893593085043501263582396578591853995654835095583634010268144626243369543772132601588964462280273437500000000 78310937870221065424500517174514468806823522506294960081129501229986682322116769237790552473211300787052717696767713537925129780665523622925883845213068141036430253530812330321927309561041284883982502898159069318495853396073911390417462971237600632945821915799440216119771427759196444995848810901726254265853422273286901191269916703621064377538175580164025548170177699787638241287519996092871136259376669922396408349940737405167734448653848013502173183654659135470391125322518726221379491658009844466925148471002305571150477257720374173924858554092758890820130590883199255888002588302071125847383478287683241976143762229980026023352865219057763542432005410096018272188039369009978775809881327141790635564063030687345797106830242738832802302784707495132314725879183713024814819850923304584303944643111941984808038538493687159271979226636785674721834426767255635465008638187765078478494843716986034015160866861293698093504644930362701416015625000000 12419354467313227621965234302711070462708278290073587877140995679208387063307050601106269290163951212367850988898840715919214678378754143512156999676297912176194482599490082554144767732488542095479555718033629961955522003954858578245615496878653451053087212818086521589790611077461544183441761435154849024662671955901952294303922492835041086177439779407912213644636081745614780469198062876293387270796920074895259146808934946698444894458045325101760522862732342257149648476947808765075835324089391620679016150660835241181704552615097841302236583902727818778699947475998835266311449969111111519585454223618861540386584178529197715539572499418904943490621965687798467635339968714687578862926842893020679583493878732594110420086997535301510938889391152839768685917221659987225485283248532256303968150109052882905125779389451652921456877968504553055793231509130740650687335186238856795007345830292782234245338446321227365842787548899650573730468750000 -1355570616727054184965113202100657856553980283729318978562795078003441454965074631169104885508174258977888432000832426650962353356212683941144040045374025198885109185710852558355943577251627621639990390956930862626320132341217237883038609659239376140104664779175012040263124921102630052617159336691474225741539310950660468601321136786398602490880661875538107959892011431464184665987422822412628576885492244848465529929728962613207162823803907198067501771361332117376062053783437114639311605588701363937105727037891593653585660329428812703601077306531687153041934648913222051142143486728265578659063172815675251296875651416155924785812276168542909491887501129346981308351436755861291243976449364339731548557690376503113618408244891231179686424142625967599208471380758116382826347453323567355037006322774350661788123429031797893322145676393811746374094590124579906127534065083215293062595801187503771582931744177358268643729388713836669921875000000 54213314564168543277897856437791462444273555658445001079732361382745475473695688086662661493648614852264074534408275106051991188553393398366318888621131561191355456954144221158747483338588086811402571530528997152700576476624777464683603970902056953308984281073582859517912423731561925516483208378704442880235121516930731127426466044957022326810297939456746096771737912811399273726779720130009914736302088867027313146294556349767567965458068318924226435571858039627415343932254752384640322421733011268422610644636624754330881597711220619007758229781989087587653569982896331291315439685209932919865333307628977777806924831496672655882793066652750985195190486237213006867083559305520809871427029765642882181990827538387112693040094957477091399812492740892656927527608605627166186574058361729055493005692469854392085080889962472255990187764342463334033764098824290491175825544714204710882784539668357518676922168765486276242882013320922851562500000 1569114965225508161342343800413261874763563136042986590016324273401094662466938855816165346836464639029328506032581409713936094310358118721781538840184848294935737726132418559289323724132079168461006323166395254820783356558409409540088948534131157162672237784425792633106729125585905166263427762109240717736728519700264536173860476041099964596929163338576115938465527563465669252327977377214500117244869644523086126699677186793976327927965746934840242487073687063020967545087901817378504834265880524982857109783200112729493299876898473252337334546930504479800021381282440385436488472663849955275515431238916526788549235009694000280018579930213543313738513172411579358839250742637611250394616667129941126412889620925994754738490965910222895153532689829202688893757635729517183518181462664565041375953551169569914338653574275184317468334344349334074611967686206251993526424435813171837024201956518019984709866321281879208981990814208984375000000 -355191058840627119604595713551187027231756645349156039891185117816401353001194545670097627296581328547740482521226106774642136867123179433657496227256202318736199911307954790744255855168754093624797594198513088271394758353126610569444195807469895864513691539345908717151245163066338408367483996798605039295398021043052405179009850851858413865745485579517777995584591935547830080463106539653634132887875335953572103824660131754046587357227594631280923143456905855869431466283578088749206232518311592564511822518764010526308725281280736968803835822145761483955885975347771280369992431893657303440764430140055307348937218982330082400595662165198759172736678155697060717158989862687716753105377462847596121808519748590633937121327439174979862496751543571029601531502154956554496372807845662637323998389469578343121759693409393994291040072557766608649112448487521805467105386880729002482333850296031697163501306135913182515650987625122070312500000 21018054108202902234260014641762812023197532999612741458742319782139736476177456676489648726122250194018518836327882420659720331733889764802602403489468707646649063723954957611368725760220854230281695079950551707528170028391076854479002442211094675766665771799565733129307141386394923963019446807555418246929296452960555532016427780026269072840547193572142033599289636788627928013953858100721060095924547470984429609815310959811934757801259945157039917189658846162930284630342671816367410682890035326652915661882735974198864596312558125578445301038854019160692070364155906134129880241913701969044842817494494231922669103223497774516558350090337036081644205865037377027842693650421066770735627489001239963562960707042744424159625487002789303364235351807204255727617954725705771255064151108113968554146026271210259608053791829754694590384979092627224158162676462540519321299507721827909103567825523095624618008514516986906528472900390625000000 -134318867915388971655563776440473146691271879071266300690657956661965416404085370981905862699875618265302173224091139101988129746110651049814850785214171878469514424023785568976472521266366201750958906466154084145678292043199171475144470675620486856192265900533668587687632908965910942917548316275517124994792240581022640557457380013416223825024099206222089454491457365622245193688134796152637234948696648418832587047391596447292092045765713880269141374291450156791826102053278940081127810062504861180276640141205239785626895281367490770390967049565740830414433365347452637811664547168961950618009376468447220221436651968141178160477311155727279757700548279046038773378687146194891287497324951390713331729269701498580116229254482621987174304706338698421207658457536489302542872970188663865724271946446677871060632803398873382167585472004147162540919379557327382829345557575438452183427884072900587719701093192270491272211074829101562500000 -77619651967598792170566405358400784298410349498499960393835459832083266438094087223418824797253640729511459600223557096189401795303185633954202410592474634009080252131074832561533629051474781878031122645911936672372430664711478119027583496407034033234365686270302243026791171978166982394185351065055961222406670736229561991105503899688513008608903728281000406820913686210120577791846647432674064027759662406136190788213695403883498477688268499447113639317313464807714304457913638591941532078671224790561719650605737547166856984677466271918186188451008497600001041234830599875976039833857646816797549890545136052632012412189017271499208595996217130414095381244912475698164720794837290171021539237231477353692980494200668938413443015017144384455828733444395786734136178294178379445869975190105530484364299970428690485713038356354165879475635934224709538989541875846553603124122692301669514526422932743088267670827917754650115966796875000000 6492415470858726599359725904585040854801866456521373609689729733724063750965893670972021649644503911982536237386600334456325985673502540698947274786362356835545535709287129982167185364706038985304888129907591534508011768338438363574833594255618082501228484445797266338929298201364934511348079381488232579424380851732443831384635831828910276432076236642836796624270976958292568485605758706113325193037208329565849749473172145675981380542825913860914924607325238363238099015411615999280366160543894391636703475124761985956349530449884599015551468401193638333887829170348842092706107356303123673540420248088227953010311912029920477803344458318401135259861631510274386324663855606694571646670783373430057652569348737950576779118220940684120963812819733021496053567662514215477774962611074403212827139834694498229632657562605580233332707537475644581261756007255559503313825186019371776957948618489227521344275828596437349915504455566406250000 -169221211132446160004377995193892890729821922075258443967919547036465487209397568654308465681199535942230058617046628288808805081056017471853754644385461784306075721333986171228967543240561486399367381326198155558840365383704805424976739991905770725260691819018514294000264516632881855766572780222910384332604200872054630251815237135292144024923375487525310317611327581516898838914092359048012361169742811614732644572343361680635999642133165305883929353952475383061626749100892536229898477317202381851563203532160868664506237277224688959817106626825772803697028555761541346810789284563120930668125170870653108656966412525531748461970956056637517289378198967385614285356724439913019243846372409228834724883059477671417018370323054929466966255822374349719558905995521712387545119879325695253010730511020214347364831092831486748161900828467304000849332001191106894662559348359996467695831059117883565789952626801095902919769287109375000000 -13792982438695824270085579611785490524457131925087762619458022555104654949586109711010986162066751250178348742944009622624370432147868176071391624819467431170111675658590974833810665350891257662466099299720823298535279465672761187619477657783472858869019808636969449212282994155170779634678104259518022349501805113354965986498051937918985402095402846871986130311696521063792357613099788650188924658381298859870735921698608230521176256208660100080851115758759122092405898822253575102259259295098700476931854830843507319339239246328999954893651969088920951558306380486719472126509541928317664979218958173791351455569331862937544482177317351760064102105160591968627876320335779156290699953894186519046108333025773042276335827331788413251895100876350597543801883350106212756575381637222025075192087287518933273912830080897332677277039416498897774259936676255258909698357514779593118872067511807011364055597368860617280006408691406250000000 1721159329517676088524383030178770264715043257698779133351572267768433241320104482767542423672831952809098258104999463498757549297491792578297191315204030406811018871256127252282441604435853535110277561413841584044389107051792362268803118287456849531983147559080231833720232607729652314280622616620527492681237532957678611922513737137379467162645517686071493759184596586303506664729855082325803998571605858150741881529591502856719634651821568379297036479029117712779772330469539497908011185579975115927384427587281729230811069658070662085281091793802713712527580701663434984365717811092816916574180732935858270613943803177082771816387855167837082280237295731356740529393912726090215383145283104316319058681376273273744070022969326945846022475000902003223581627385352388321034068709641151775894057988770213927361242510458828155009263611850885485431180768101244511552277749721817815423759341630915997711781528778374195098876953125000000 -73330283500270221112404678120186465106761866465543460152992092580818950300953899996244035360732808747037099112775406122506917639979608835034429671924581685818783449641116863258893663530133550284851966708659792025823029545467238388405372652506380671110417203278399702428252415701340354605538959402493148823918499407265028610653511477007572402517751535793392103116452016412656579213867897434593028406066699577062143715933679376522093209409965511472098503135479508458021131295731338937679082766438001294892966639437246871761980214139120487118014251674051294977066219715433738084087346989138392687241093716322037795892362388809185775700551135693317868333205911519766671915501701259479991367204202127633012727966771324886848430526861205508283469553270525952905173436484250012771227906939173570075028419805144314911823339708179226795828970727420577684883421065522640657324481577742960380157828670366626511167851276695728302001953125000000 -1324061209901813468663234150321632524679380131634277054598903264331846083611229257806881882536816788258452423813539295448141050511045981747135404890592509164433089970051472839862506840073129346501019350432927286990730353347445240629186431257418863758743602092493724860597407474598057643872531931863781273689317993263987674778539243909302595849782563585918334258063921735256039358727645579279470801761065953921278123593891876611575141470597886724310839270784481068990685230845502229701557558806858488295752428415081092776209329646410229653828852044062266604470503124433410720471680482292653504601991665105183366788185638545216661283531693186471437572633348576305544660847461750727552401928517795032668802160075582699757001358584644945831335876238683635354213007741180868612926414007374615146865253196206162408012313255672743156836096761148094892848808142512776579726754439933834566335384141932962620558100752532482147216796875000000 379262316997522723817788287774608210698528838277393120705760911144501023274794978572752294915745504188525904521939196401762491830775713624750716687753185797388879522851076090344527298770506251396240636470658955319982564494881316854457159254170319297487931453875354190745881444266788766372402622725524354218219395070272376370433247337741814143809655054450868101233292694819792272136495754465238849034865067977767262802599891663982642277162092205970665936626141610874593090970053774665983834668013564027412122888981482658240513865770584852001212778858278763263798528132142621609940344601137552740947877117024851001333956490039202109809529166818506233552818870620802275082259649683392929948354359238526785333168284764488683591470413497238874112827248917849708164164935358145398177764661535385670404441795944910876073934804856859123912506232557923033835580768311476842491074738917836909994629746023520056041888892650604248046875000000 -22583294847853634893275633588243123349945018599864848416592476114780707465020857529741590365084789222950046560683790146072292652024393556048663698897177750295884149786870102817457849248720323426139977526134349733522646891352208090574673231946441475776984183702709701664442782338077432671004337251916269726165858598924448821833507482101802505341562406486648845142974829291772281621319497264288464580631695665374658354647969588172361658011604074522628649394372345760473034486592449214273424694963763291097593991417155075265604881827612907970047941529335708363915044881700207921751205760028976226059722337844980468918009022502151440424012982789753767131775454668619239158038067203900623128687592871672102585888761286013423049952952846155682963220609227540657467905325666774114292879355256928258446988494265202200839195075326677988895840975168146607924967438213591969192910526095734277847448812082120639388449490070343017578125000000 137020497611695494926053950875783147453870083773591310546523146129351980771648385618309108632973580920661708163234030935102579021117732494245041571388839345423231234444100756992041085447547916826701124939470782717352290004032032837345390200231131908328241105291122360802435789877260709420839754482022877995503569830387257622464280381294715617486683495397938997563775559640395685433690492581059398955995480304864321743769645831465702226519546658655791683437020347935908895136271893309441812660698083763560611411642847692214497216048778472670386293209884005997153374451809164043763899272889475287830954939722797153071692547651817759558813663777374289214596413118950010743823921779266064395037555495282306443477780237920765922467614267663003488091471415868504544364756538694215902009660799289500277004727054074494017264610218624856079348646042982027362137022578286970870917973754021747159054234188602094945963472127914428710937500 77885096171076752213737367902678264406936889602900704541930901916424779960700425990103621452758984375412308461314910650479644479762550446939127623411402115203721264147208989430618802668703611952648261802866044040724960814861896507278628504651503322312468289729022774930314462702026002798010109714739752323258339358340851002855058336551442258336327708285479122389354427485434122024706545094855477088912415200108227686053229631283605208843730508455472361880399655675542348623957654332714941735143531361438072202806693144299892566699457845505721656200045370265781198201755231837906720798121180052305230840912404973136894377362847399545274501459845482151860204884247247112572318491635866456584531337655309501136699574599462883450784404453970856410872076392340483395622878662431596770033161919171459929913990363082227604930764400714670313804441276340463027672927293962936477014350259134162213214835901453625410795211791992187500000 -5981881461099072481919120142507992714847279198404798782687638198420065927998638481287202899001932745480473162833613008672787481866775166626317890330240343793982446477986369890958772317932762898182334398626810227506102548619617255428706735873824611253993561463973720601008751399448596921260963529307443469663573444124075074770234566700278970829466533404658495890661405814560640437006915846505549417133108554487655350859967218837486803516756556125579856216044862292076786440877091678520158266368906032560634943447112977612809943931311893205108278929558201246900027189175401377696540022069352270685830265919522266965999825108079780441116967031054883508293132973834013971823744593765390656309696595610455669329667864367812210426638693952331554791509243345808304584389412464390958732637473643085824748327008044229010454640156701170760574029837126851999684386645069240410867046069758024527673878623090786277316510677337646484375000 157667904117001173693028291615741375798861982129148131557943170418893785010643980701619015530659452423768094010456077242358084175366289675784003661704650683596563700955300764775359593083892962669793289058446413000616138355388850866161044754659014608567076153769685655777941104632099752796131020449578767810937093402258568892836251578707650774257801916135230209620488017853946979326186901251563187511420389089533324763188598971949326020639692075694151640090770685137336369031049479943017796361745728183357469395947125512864144480390053592709797630828796315879927849635465951296478367410139161505314528078871248914996686352171533757132802336023972250026237183244336642769403809151434545469187181717934547368720884165566249852307395927850392202230562551168777030705787286179676882639258862667084112020054741453530488582930268285667247472304513763496024437434385235869729216321691225161094607187806104775518178939819335937500000 12032290569385303657687833656953352358967950427038711591967179677382038736645460890972781433281190562435968975121432051856675438057034324363875641317951928400854473132126657432952708437774160991921273099390401872313474262860763017236214600401196851645766628468243754021414008718183459109891197954438640987427351272469799490306949744218504675573223981146424821805900287147585524593008731641125140339565648237688109982747783631354330855904058889431294066667965139568643880971640663119567245264649577001904776749826911528740229342270982079161304373418394543452665418288849471183268274716551925676363386276959538688407740713959233483826098752469556105765346434350738842537737483350430170560770275606738907336427375022072835837259001425964412879490987709808279608492514083437321228818017490985650949443422158973867763707242840365599481590629814075715338549035821020715498437395749226942742726720325663336552679538726806640625000 -1278902948103272418471057770311471948319098203218075199900483502968911196331210903639635120437441646945271064029361179303177303648310757002999818820409076918170722291260642553121402949828515917986328785805288197571634527432521416237289240232638233189406615374291194488320416311115146051188392371293857923579537929927978541458361501947605359003838727240194045124347480383682866829017691097299349836504584693419941421466381165205104156273812031174726428322819398533075596874907269919423433570338610552608070754040805939054079699090681864065170451209601016600183146651439135451905055222426505910956263144574290058427643184553326569876363958106302917317653926257094698480629739988886585157322574987339859481949616449674804728370553495020288315389331067444946776426914214437988094697584868072872901082864123770006241948822339047753304080031323410076034617926021635951899465917709110274191885991967865265905857086181640625000000 51851002270786088436517378513141333136569237519154770504096949701019144709013174331205551649140996026791901476855809057475152248200662153841510957740468670499018935784288557290528522618741615656938265591156668495574094353557449884571090448466504627188180885474498075066858128729096815957887097457924342046773529020507251144298094277192724616236193645127980624820413830598288000441508318308038087807075556546761668765597687370206405190044157625349053228815241284943856992773701917884370721951061961278172497616298948094042406102381048557241993548735588329482005930014285319911089662683048123504447269331721308332537004407144996301067102063035929855251694083629818668479757544854407095197726773852714422331140469750228010473228138441938601051602609478654708651844809699161057143011146466806152750416788647948338653260635049783357113519105947226408353331705268575273680577882571586523230422471897327341139316558837890625000 1233240479468200293548008608216557253546793129325776124539446403613131923227334832811377861075472440682944275268429409778569319934026867433664193296763643692013292332712201757339380071067588826025944456303540447499968680204301398593613003890854675915888683495171535814196077534917930970917125201363875370345733034731899318468702604992979550113827390522911362870425925123935025099956644109837810872989155533166723534562454535819679203065153627196202785470193751035044195312765144558075971449210996978529666466331540749359705731172588709569865384510565771507487287971852724591283543573701077520856983948103323865613600372694807079516385525423835203179202924790331442931461444083041399029457136700723934997845099383577401312872216459162812484214858978633837659117143453456525370192113617851444573984280775774677959419033934534836333459993439622770887692428333344501225376827098501042456746290554292500019073486328125000000 -299951869725225801370088941206938631920771524898418980376163906221226987192437425087457532846451816997978317342999379641549277998958295538521333345221119284726030576988830850698165479584588799822961551877455073984425235567675762533242554351443988647024757636245701465776699479309700199070502604083387898922912818678243448726331545529062493740605060825864688422091526784307497606146279443196276395578033328840629102012331240278247272365290286240364211032798316376582910623658027730997738989630048786474557051448475187122675085476646881192487646962061325906589135162225879164015408739657271793190956588915614511473590074969557332230957556901404368855324062494864993710447966630899071972352618583917269135646957569847134537680194944632661145425219624511846527012497638368706797935547896540373386999932676608368509090453945296012963140830512538900744839173694806821837536424293479270231088662512775044888257980346679687500 11378549642378355601526748899487037154438829331233576453664146422748770660220300887133231639250970918248839552853499058699769926264214694135853697230159270182136235763955126595018902739543947553782438946340845234460661346888333566075731859018175843455885918649376017726845096420861424851308414736122993386879973682580362222050927106101127172261646504734554525994322671917362440799874336715477053972758996885344836126859166300441386802276782329158184770052042102036222889668289207608336692046872552333493852153299307079273203189992783319421761765039616765151856224870630985079751202400269089345078296664720046619923016846058848098070686331421526320374642635209347977678681548818259563358718558184701644195626188268514199854195995120685217839966182679732529287625692221107315882353599050790734040954094764526480161004033229925328726713889489210250142908516761852878237005082945332290478290815372020006179809570312500000 -279309745053625771899197148759952653096368055416289199121506571905406940797260822765236394862724578608901662390400598406217515923929828400991602075206464154711129358935715378741992067273553113477653754441775573205968075102239668060076477714340413319995850515348133624733589713948766229507029015102714167895450357579663274530107011662540769937925964310991003930842962257862391987702535856445415922891411490224464125663211673462099465713377762694027908357808747295131426294982944938139971454604134498106300265097091966019293619741902746350463896198468927261366835166288712465792742932353613927583024446035524969007546212906932195093551983056657190657148351823019741720650664605894201320495255239247630424443187859296432134683740223454863458922225257459514635895429821906791105719763671240832951773685019378444450234309455962428257765226868664223282408600052718211387975388859672420949209481477737426757812500000000000 -61350960861637421245691639860391939136726493577505817120413022216786621991907081163992088317138452744203026765249064866876851548187693463046750760801577856693031966936470663667063251491127720282548630495941037659046646897081751199433872262431587295933553693082919642396787207911531774370481706637912037391276019522037535951148038526283674456811467047924935783779929529430400334350372269477963588735808758513877891671392921868832628071394466213784911916137885241397003064422094345588044673282240556384267916284602252836705501745844681673823575849798276854512832611712329003681962682956647082690751577672759466468854366083884416201430609551373753481441082062788586928606519445368522964514553492548554667255202504819603524413797390233689960891647397416667894731298075855842887218420047046682268080983989705201655722806958773194752224741050016210945474058978830753478003832285248009270617330912500619888305664062500000 2022000845714499637332566696716730535548455979452041763470773074349706096106358410028329391192835228708613040107736443839780120101080865649009647447812314133071932823949093189946152410167974000265038892341620960123632600893298307298226730540369019844379501332604012821628101616475535177497707703965910949553393869247858529717069447138140962668513510324329641173800681543330957684676022272518178475796883811669908349220356353913357748834947991441911483117780311951969934337054256717552736554139046673805139049082297158641240051629591607782634068332850739646890549179159214934112480521299701456654752262052689432103313235811398770756628263677413224775966156395680054223623544097449680104369044462149740708828660737849265470278920643720416631870757875336523860698284061762579800259950117717801401596298555046648285068887985655478024823565465972155639474706020661030041055475359179638417117530480027198791503906250000 -88280834798442152309176051150457926145774035310428422526866306399957382416159460509107542114199380258624812566185498200994820966467943355600879952282099213813002311848731215380072110390674119919365260132189838592555850697705357806814667873146075474309311152250538929888967171563927042675384087837010851011010129087591334422015449241311404210036079879606528065220653413252830677453904957511040139531524583899190230491840435403485932933492773073984446901746276668827550900609164783142105732583215842304899577863070963163263764549271309549692103501127285737044972178698117446921877572015967801758065169712429728407461470287765142954317340042157435934775197340729261612468458453910272356905196205094931817050934511449089233141703023109596370587484354995252790898668118249073197282595602995237801280053043619253349354640890405173531884909494202270159094511866168613321587815834234902467869687825441360473632812500000 -5643226611174529975613449328273487461735531614146495375199694113132694766352905520729343314300543328082371958169416606379644332175466258591677578984429020408898254571772549421819699959954930060503094746669662514194243097046277632397504293163633395289246229918270141245985159435046948796430426179253203182505078045593125720472291980936465185466809343190884931524105830679088175597473592496765130898145355723684106010199305036939397155850864063030102125784270546059165793703479999567667616062539691373997727357748656585283937709346419237592204064688214081995581205291147359869979307972514855421543593187433610541137081601877098317455415498349771488758008422771034590897934798562459139821751043046556723855412216259346164789092820569607856988676837102614703929192633189714075809526041090545653204190906126934004596513098741712675433167044352759184376804253837114075994380035794506511592771857976913452148437500000 969153779761775014779326926700914898122412115311074052431935221490228255637687217498226969108465022177978689159343930230457250281592686383116906568418590449954322193169027692173873910924324252391732881421601290621787067394762109572585058734547882502912088458431700906359717970331889181231059469101471050367039946214502131104619034991999555650834154161275878133615714377018040452247731395849859224495612005172771485218612753002907046015130631979111423239472735305262037235931129169095254798561748310015977732450575800271574738871727871938041591696537464963414917822022592954300325539263695200858735548142991728497353209379753899209547627705176480366150422109158721263673976335162618483300855074826926850031652192809149119971277798101392324625209801929051251650308022291452101569056549584040450567505072192778483113592281066287952172190100854784168008160305663584426633105906034870713483542203903198242187500000 22827254182076033440435245707903358518133695335576966792770475163232581224258163723949827761475920995371443897123081950987881485943644816241034065044214339744634251565975437051613318491200012010767778208684529656349262686850418574324374270918493222132114867871474102439216340337376722214736314727362233075003249738034502841987472454558959277255152519734210899363902748179812627359754768207769976636936449454296625235203575454898279602016892505812368061325438638063403271315520749217129214412007969732058578979956357061798541969467056004168905526170063048426742158731790570908492397884881839011785051574128221210686862888230527241381419396052083613512443039577605907239537534400253761453413556513557350510289598691839749483568446593421439092396955522060322439216527834993280076419646309612650593530896509742791899858242501275162567274795642187178528251656787861998288563514236670926038641482591629028320312500 2963804384728895515227455683495441146641197950294449667936594014624233785595085426428772479776681630802748896910497757723388788135563106867918379721588523933707457101188984282604754311164178284713335127253249455355182547572882218630177079695540428504135113685755370613434132374490354621919987945643747330246456873285821550380628981768059412927657997935058236929165662995969886005262707714034274219732537023642685819821156121868220600297752917126065654729995374473248251680374671337643777306912627051099081120277195165938042825208588543076845630741615806384440007485257580528062946649487571635119250907058104686015298589497764579983583677370650431682810801592438458779615557254387929932713750906433985192227476167549725837166536646179357764952275646486853774438335152555443960138274505198071960703341062011760520902621689972419438468899366170996872803974062950127521531840102397836744785308837890625000000000 360213969229701761077317229333545161920959085190525008173794098825459762072408361079561038607431097174520701386565402232200664338062153114510966063884367090037519521962838482126217953879126687399236231766730594475076358806280150889210870011325787594034981240544581370186131246215568221345844006012674380660257977618853833815845826863366841964533861279343300949045282232117331920669372935690816892766407017805585687110725264251635817287166417137002299373031499543490550076174060142863612922787890666686512084187295414907465742221004036894506403612586593658846302588858019683987364297826922047815998649959556764512208563669972537130480603875231710823698764540654427898021221733359624614941385162788552626211556846499949879079368186959102381874569926680374023254731691580668724960009687895622084870281262406458393570661195554266499525128397395550974493805299490238429338528902690086397342383861541748046875000 11516557708831966086394220545003570076579707951302664776840174651464155976833573571177987847571932626933153076343965872667951736663795622054876589904104627060682516914150577516675296593714496574629537256770325958522096209257334250699354308117944866639971081789819011477221152976908190441351927288188144758868175935263381455900033001746760137923028630630029898913555686090025228475460330193111700543310058408268437246365528591286196347589805579294353908744909573041464768489245933043167644325767111938307270919546798372594470226169264841744131888855898180450740522225105023106072477321945590507332672662480097071290266628321202046421280630781396447505433905254602267234802127698689872793530535308217565351652114324281598052739967828766266178575528083250820567036762714494398188951859031262283133845785068546127793357072143751513306935228628136796618245470298635968475764457252807915210723876953125000000000 624223384330436203266145548219196068868462076320939596607636570518456080123167262345020778570442435742608513242269607251281686455608846351663285434806136655938141419731059858103954970849200004458801664711764634841159934500254600722074468092483222113880104460823237653486791675839776304438071375996690816729891073276969691747666340839360145658384652486528436882151996216004228157211718555091048748013278897404074528303843915265533440051088930721639188756904440049903293413212026233263856496183567799587863871734449399122607610774552184034180133791268124711017839346658078878526214021364364773370137688499184761095208899893242499699902665914677747471487667689958659281086111536155904343594240388098070521459266224372732308733021734478111956632443202426144113715105535583990601629959143788440980890896218298285004298351132329606402436252742629975841632082922730805074618132266550674103200435638427734375000 20801675374454358497940137289931095626501989955658753471460666940321128364589298738005859773218742118144821132027006513795848830286810076493106345277985683490107258280587604897013673236850748700589310680414806143187005094900531965858229794341973698892018921767138045033168636945209451441737766332211436858126232953956460310520641927961587595479732765779684326774972893323338979865513807839316523333198965850834817478166910947579138441457250386794429524441348636051122769370753289603405630331033700844581586269538343207319271470167996948503500788481396134495485033731610797430113613262826862938298931998103943889281392742124520786570381665198013215884362791818409692026760107548787079737621471067051464006259773760730128464029539855037292512065782099866892878193162536931496053382749919728477695669961542039813875695567220353789841991941372786864653710470641351237830463105638045817613601684570312500000 -3514375600327745871871942261979010837726160877487144527557258871966911746147161082563714060282896116807475481093462194129635445447452041323533251209322490466634412735383382668140899253316900729251691392205989125888988374763187752528517505391823510634717798996940600708854121807636557858763552370014790854863374799487534556073173129267600220276271855521210077039264409260773988775582174893487516995336167899522231066722346865166357010221830389822861977806789934043794658836096782947654893079468617747611017964899163982438474150183888332830508128595062359790993926238595587770952826306114576543876637818607471254715656906652117674090938051857748625830904719851618142522216932978922732580822168220292429786042792588917682779179092005055516066391839350982973943582515508793152173415441813050061719680481155907647150962262536872158273811077704466247516951478532983010882873031732742674648761749267578125000 -373278984594166893503889606744138522081683521753524661663557550467805038397626671616079818497117691900205976654449552433873287338381537799821008769610111001053640918467934550242556131839159030055376137462417839954019864339891015872536714474393769189275608884968972966893699237569359612500428531660268840197210036866362377547052762002338827871980602187506989978434561026378273895216351747873307302054135592808615160057413505756120762966514937610809251422953537449886447181327653691292974255942814819129363654650884104010245483461627790907613746288189976221315460373443722162013163710860527693265628097810461852061909010671409757037121181501785621116736245080617742226674108970798591675363883506359778234520896072123412431879032677553978294446465430562931319159752779793959667460604509201580930283966136170711518396265438703310480640100827416345266418593474427867207054987375158816576004028320312500000 -33444209696444453459724122544470559899686381860665499615270000266169498742784473816903015720578496891441410071225832761893064480723210423375718728474394785756154250875707886566221272624820678072014809510606227996663538512154275545894620261024409519931346322672790232652129590560431554783992468158499344031173655185372761781584119087190401427110118016520421492795676448244754634494204256778708754114229920999368385157210976756444856030714338499791899007546947709437273070537394753014574725130503392021957341065805389718252731030784030510140712544242656590237035103019739642500803280377867168628993567333591336497858259433679002900253629382541080349782220069510054314843620164012281116544991901732915218320347549126792969080033418779234695497201773604501089338594115993614055054879400382337871147751551131667032025311866328687814989630945386220481601204492037165971751733195560518652200698852539062500 -2753017280286803803720543078345085128562947144531974060612460981889136049141402699066012950740297973318945785118033356545935052434418605556564474550680924037246372640117951815840302761662096363099131432054116161607283927999080651921181629905412211659033022272698899284897814589446438622342619148160401278240409248350530374052395419566395925401034119666443595435682332491042413265397442209213575722318341621221777645737523879183021721295726252185398564592632707179262533915977930961794512078921045362249547876905873422177662291873815708581582813745714061778526871131040336355660288435162287010219294106616952545918876059859839549437167724165846701722609988251819171253922784212385426349987814943929755398682768152015245953324407642147393677792249959931906217217331594232159737101996942173317125651487981812004478109801862415178516698130212757398240148477841504615071244188584387302398681640625000000 -161268735723141591672387272438832469564220452927588705904208760174861318604623432479907846699528612375536203954412122479716271961051863819980734854942899818080374948138658071291183873205923722916621147694480601184816359981536084733834742161007490013899708407016003906794225148051209050577379115319180342642909039519974123890717673126279242656423797375690109983607482127145986690629700719494785957607598264078984606185536439187645665276036131782695454322382526686967789764579597487493928855241937388404281284943315017107317031668656601971075223948957610971030786423716273441715223911981416174872950815041091275700831484630654647816153754472673620339481199255580869868302052128785224590444104078547487139300293730101968112262375935528447629298529525753971523153655477608353390847594217864737695477753634810895939099575416471513897270462423210887704851795865224062254128511995077133178710937500000000 -7802941976767879104817234614149444019774151737622590464149047554356072469072078679609595954523298217891431303150091967238029635993644418290333688565528083805816073356800670079310661758808033242655420657365675387050318085951817676183589238235826698143205638249939541833777516330490844708444524099114693848576505991352028010006657277762309686475834343615437501047871428576796072229514992936265055492867862825534111857284600073699071052616103507399939921057953190652281534655668931817001068951685855676964328616362564693680828125737301222951916652943738981830896719356948650648842906649323124691988792300905810356983552465972184429186102009808594616973208999076231539859751545231490438242220306435337402810886455017720755992648258946282089494702402086267375215254159003611504276209386169515394446001723380650828714512188036627706181555191274446949098626824525837264445726759731769561767578125000000 -244823310070540930958553462738466261668972658187919825155944152145099767335001756209211856263963114356908590448701315341463087816139878780082166817942312352265437694634566852090258218067778081604595614178140675055211491980186767989049175190369686545778440650228159256339460702321775706412178965272486615846200033816776597451931119017358057790865012201500358202346620955804567958643208343364702639412910260590569234089299640694726720748999943478612699276152535272051602686870874869554928449895359564697157537312100476353113972708341520763161277043329575775280115666456880562969264322306107364255029188979894982814739349890560098774052290572733547741532866066698361292961082348530748758879897014738496471097713297552497222448981090758849658611315296054006928986365919644577012197078847407975907693163813244319002994172363719638948088723120103963530429236339358567420276813209056854248046875000000 9591652472695939775851916994231712885647014813244406070525506631199586329423325315086229878409555526594009186129241639426746845805816095200036746913200494899021302924511353996761683596811862983169657281335469570396983177039036935409590083004411456064408316659636029098274983479125960189148568454734087303085787318987581026880508041738335843889727805533175603364227604250626312649003352313672973999327403746503456092157864176616450240178577329464081510707777214308108642280410607833384392657208020911076322138236609149007296643079724005820558428208914752388593877051427298999387342087446047269825608706601174792024456612434657168461252944569646698090021921369512932148412076454367751884159959135945504243598129709996193526872597361263233821897829439466807972876158539390644684015758731214930325876923577741320517811844451568033875228170031360694185174065040655477787367999553680419921875000000 2195451486481798370492056197582871050799310630424615047745257114205099049943174602540876457992023487511280129629794875590333379429757380642721481235830365972897794955387581125748896772803369731553644821176500080660459136370979804229535254265283784536461165377411959400159358126846689367176485602061390746493191373830456424367856690773105740812377329689723293244647064773302387395725921104126080057732113562557109711681066763036039089366437812305385005420369864858156913375343575291448888773753176269448233365939121426946150172089217296221169203645528461402454304634746564520111669200510186619216548668171807532665414106428727505772850097946018228743751861269562181524955989351792534710719889517031833763413576135399890142252973311601726803066929585645180269331304362689120672231391757307266980597601664594618642428507770668769576444689055130256825909551565700894570909440517425537109375000000 224886129487099585801144136357759703087244012880724726697783501219277225078478851797156399200583857600358340454526009959641762701755606876740565287204570053151526429076477691864747451002698532734227693864681846540328799214574847341200606700987697915627580135084880534972790086531789071102830369260993915776534134927861448784881881541931070579595091497081704334876358292869278755161817854882812345428625236275188040591312847183897340707182308921964216311972394193924509798958312894220357481211966231659444087532411117979680008364074946046871192404307488272944281350018782857043098613568381097129078166966724473476983282552190021901170554957940697303373866979783362370085866920802132174687283637000608009038236855362247204329845466319996477742701938080429059595083672905935218640601243882610657964714331154288192320263308120451031137639577825210364381280925272221793420612812042236328125000000 18007288876386630593484564120620306984743790142992429844712983548488138251359400340846145495266858826388388061733299059488984730942223891097838480704794048357235578264484218027554397422315494294849565208356625427549890488321253569100367343021674556254682397154935013561505034722008591451623452066059202786822551467532126331165706995284902800825636495061689674979724227256082437947460692502182241088913052573666781329132438507707974287978749564783093875524295844077734993660127463382151871032111641801663905600569354510026333612930987057080380770982542077469193381557303496686127539824804184777455123774233536694908389496745617554118868419647554224840099097584398810623167373910526089267812135696760888490730261627061264843199062421825012830431131762682484428328425695918116077647815903109000315807270043806676512236724494911013364271605068182022582612411554237041855230927467346191406250000 1177558932625422091954378140345686083248461969951064102232772535384030363177843871185719035193475379128285689450406692230315723528360867899287609976924702970997298217913231903979854201633255474459692743833649638587313907800335163036335989852209807635574126609325207062417379825784647513744444275247209654136053992211063160778913465252505412083919787575761992789093935830638142370008412452193027952637326839551869994077182768829595809553351415165504929520218732006613043063692850489031242017390496058795499834290234487188727441964399422134195452143645146459467378310802680133248887524613627281831162416753770201506144208851517314658561321868443063554350547856809368825159639638626503303031271235477112649808351915865909108049000899025771923515716242395806426018241219209967020477478683539322469975585033234146065259805142135376991487244005573677141374133725548745132982730865478515625000000 63587046212381051823233648002715589556493567651009732255072806487385279550003448663989283811261408795406396708922494539162501447828721092134360048161646526311127284028714052451945641177705918063303936917451030046246553079579752813273234354447148917092060667863613536509135107396096324307587687585137537615021717035952663532147031107925106944282773827465459817397694056816457977389628628755905938168583410311143180302952016258911132074830595919070400120722576139758929595174228857578336914123003824317409555739014696498775274017539734901740425420241283959192343196019048800242501260948245054675889323089329615763259493197805675338777519355500224119459239600910358690249708357481386164253174068285747241580736198484058823354901898746669014530552881770283225461726481545007704130485309707310099789523568060535271443792575067172650327885017999558076029487097002856899052858352661132812500000 2595805807811983938819640312410737188503166188941288673544838364317852206855149377548846984276239710154450233633890836210861121508864434908672705432255441979190025981028919541851966991212010496044994790408966224605603907038097253397030676076955729968754274978348914759837058251581991806724755593437811630221195157064809638579090741680383953283898769710108075635445822241907256330855959599989541931502279943804769912552245707319011571924626414449247494250624128723535551806520308210631626543838316677911554505005447160720158385033085853578311459489598071932478068323140592041482567381885377617089168600101004622494254018282980262664675764779132469653437110217002730217242833721553189797772416728827030980561152377693640214262304282817594687828463283069091134214760069925351005033613570805637078131679936924194385640895807469075862925939903423644405933146117604337632656097412109375000000 37817840378025620189174209072828203313595013936465894794919072688032353180480363115465092291759355155647536433383001214357511993795475392168286729990658048152214741355241245098786329142105261419711330762308956971083216663141728257009959938953543432829644516456973702796737746393462310848505069288548725991333516523955462469351605031374486333796934228938743698692520581177941867679980229576304547686843076424543138482590732286688903224412311266776771418286203058961698947971872840717764678628428722618410565002459967510240716264276060566607743436166378651309382757718954283362730677933555436629135132562724665797096273561879393861958562053825487326551187960870667918612321418042179408517369670678241239011406372034716602003455312870518251508539835777009425522606330406349848802899371589762097503967180876611944529019789343354599416091121975164179858097668329719454050064086914062500000 -6343441452692981641108084840022769149479823378022978170314996731612488671822992286780114527529147938998620198449202312889789820589147277629022428611185744864559603146043262134829262411947020227625176795963387950912202108783259483920373100037641108617440725315335866297017114887466287579145884766777198871925219957808074456388978368148526269050607468391888783827388327475711915435202287603555712472773140892842186045714433408520244495535119059914425132336052325381303064829046663693452913878805702363331122795326899491429179574297997963616784514203922077283544568899823892315993735987209363463823507649435842755909225519651643657084075567267616005844491197679494844855069588433621892380591360986962524970289561570210204014449389676929537631838909558777758051044491624076985991739567432853345239840798204511343315002749692535465463437828297077469841269703465513885021209716796875000000 -897332555232912919347904109132324473805911395350026763245563268015364941791784960911946362482781221743999819120633040212656734430279779677012232483189271402545554131847596964743645275024124069704830646980489068895283365305115471048890877899696886227850956324737160648753126806299745976970589342977589390985243635201066661622536003338925226452907842950835072416147953326352118581315731833698845216657922085226100753835765461690811880937999128455107021194148004789184346301678640980653905408279342522953021847486897456862204887440140861341660310994947399465906291179303072706353332142156830230334607058793985044767931688707452751698255468687070117697648248579992807718180742880514068538377222562441880064161405934949680527153006715461957584195786780728352371129995938653415382422889260251880376609160574595844800415895683515373644106351020549583452634578861761838197708129882812500000 -78999668542458582921409057911458460800061535458984041743246578545218572975833983031327501397564572592989167895487327398703560180150267546814876023344608461708936840238794944068204950532216466701065453861862068298116657587427751448088962900654422004401796877742030665497202590412537017787166487714061744388630782262972480345170857851946923625355637306969318214094964686726790265647167673804836474194033014574928285540365960880826842597744345249981368379632170827990837017558975609408680603183205795989972550136719537483017313038322718618356791593373752783164063153252852494738920495537781461552305650402038475544132378125936669892967729899384350171231401932479049514730800002710320796564286467076970231341730724892236937876169280969359495354221991830905173606379931609508683492063598239347709957835701487475448684074714758332337894981660386672928098050761036574840545654296875000000 -5558449454795609212824972115039166338293788604483196913387935870103625192134179502948335228035063887765618493419678466112575799533910733075815915522041018679878440953304183731116501698032212176446494224917846345839036850288916115099436963564005213158452159991457988040984962254196790024266186770254359515477220307399616786288888036035862623946736615771546226885747393877522920165502216485095385484623723809626163697823745202301640391966332481108629832318451135839561949151710950194767788997843703753806481171692182082321408484073097704592548122106252554203021916050098236380194577385643287067462605397351196721537772070205849567533558294353054064327674116341781991201074472970578131745442278108827622310590575108102797248155851573821951604483577076904229544173636242529648129253287499790672721958420052860930428625243778943131376892765674324614622037188382819294929504394531250000 -328121126784864905874882627474855491969752948957645955701101676382814119867098679818746417112363360903965943441327219330584185429204502364814510879631913525575439108389373355815472680658097847586501372401854170365073937969961228226564183664007518831232662437032898100629737071806820993892880665472551679211820019828535906993998189045218540281445513982745043562419364576306723170683863582895686276024645838775627038709314462976662365957941291918973531616617096751604013854176792451632082591368999052091009476486629001125886951046440747907951966724724973895772365062362231342053502296731552991309128932316560159669017536008562630277411065655917367155880207860285987642405189436767847148234783747788300652201235001008219110940147641329986899022930954736840128845898739030398670117366089490690819767970740601301716258178995097289946058193021993787397150299511849880218505859375000000 -15937324900015839813919477922367255766340062790374356985586484723380881551566391384664586236267194557919181445185612459142615446883964052496270324518822232118777545808780238563722837041263741127550464859226016278123141637787761295033326148900950984177954701264942803648591703525727524039953688683057790527463608573283982155477470275673219082261936796685479393464126226926172699150550407776329676468128804185277237981114946080041016781310096894446797527481255824731218045644530180086915016679916794361430806049367235588655563261378918208814053673728931772717167672201620346194218868505301475179525234097287406247761264695413494162531933054930145411276666927746668304666874690922885635858147645865530637764296585723369782388785276086113889074518893034089198838610789686463154875556366694989750708923648610900487741819516340065099216198596376870000312919728457927703857421875000000 -554990220224349878850680457741511606291246059292902423681723011895513735112492314839977522526499708957646513217405227930049471051262651546175605591767190225123399143573891562465433180135566498673873827577811711175832821358965396240122066950791570839482601870203466064605958418117254152703542623957177730326432246382014545380594594503226662846449961208019852449289360797919937747362998799728435718485147743736150149656647711464015781325583280957200602818703053003081080030739209692567209905383792295343576061199577192336457371050731133457300337764610885279399790253279967454531694740194644425895238101079079263295197695406855027875855925899763118148169238845825102216753288688383294102814518600118962289305347129243251702190074896364805916926791020696747954866872694764174264191651617901671637684804266286981136502762043804319581040418452033691210090182721614837646484375000000 -2647076711853126996705014470500681206856904648334908927877459545009623662650224738466904057278603195470725244462768685800389385863274024956491046303839639399462783898665174992661583944388043881860322827938392029497219799003863886755487594148663379217353413935361547003754892731892886614437071537472966612048836809633222984643518215008713080940201112880116032535739543882474565497453658272611265488339058221681757150977863739531736459539003902920238874685405072911255776326101743629974491516419564126498690022382277887571291949215904861799424782341526257676809267736665238833267618876958040379268635329397987896340959646780293560284782785091346757693127694397119298081366557316358384826206544153544568001965674361814444830687374900075502706173388053770188679703339784413574985330964295683720776604369828573595522930858934255353778763897310000174911692738533020019531250000000 1750236417743158279359368149001678626326101037734813055670320322114283193178096735718206097757172692215352896601389098193602530690000186609324650113274038710969234475717148315153744173719599605387233686007922357267564952267030501801437256896248010644977234884044141738043226311627786215237817903299186946633425460817678576097799036987288173541274397116309733453819754621588403284510180354508217119850563200378559943625848893647520685227177372203407669710669333103131309963588341453058425965092118096417970733332071558845653895424146511269783085758552490737929468714438229054079379092872580515721899735096555316849795312873655095710444333695285989522704721277068897411303856119736021946474369487399774783154283092770733054346177564390058402406953738479349110209309976940599826523653960520279158254664632418817670209558508766949959378766976669794530607759952545166015625000000 203172734673333857771700183340632301116319494991114804582215586994081604453248249133598286081548995381166974014426130562271921426477209112494273547836360819399782637468398194985074657894706740664207769558941957540009444493863839930376691419386632673261612401352831230524794788498400942809554374161289398724112517785601669262424711075486558908831228173896476371018486204569643075190287258621414323009255262597913546726879341439790626607966007607900304120977125879110651857870768352516123917830642085219423203559980493745587554052506219579201779806833016979386277341043713372742832382256006115840003391568291768472508096899437434373835878918029871192345825656150509929155925338997448479018561816064471087995709732521838866764632792567577378316448026116984840157123015695652535568781314411393359536089436467420222588650442904160270396474174958711955696344375610351562500000000 16050047659112264878559860273108092169204599332304997808007424317266981634896038104248769433254679943302108819774379076203035784896185442567917335101940610238144263470998541947177684223044240412049334397632491513414302846153084403351255496275370964313527434617315101109096331076849246030326342471675749556943955425998246187544926237165372545917711565574004627648527158421827923723764092999208662597203327952313546014356639951006944852922627019666670074128295714107706790278531926765873392081854816243928441171604663416309862788590435025290269327253820928109156352910504057756540743755284364280186792184481540144529097805189213354853142241014829585384825747489208255357893872779677273078068777324029520718335080668608773141391401103895299636278672480245516425022636588959430009680890849984315426254895185462292974860980447160234418912949649893562309443950653076171875000000 1034369503095310171068845288921667660740130869229566449823961474751216428951416178549512761845685782594830584888290645998789442356295208210658415795122396877478921134608883099407652349107688870103868015228044788415666411198473594751013915631387999909498561304186968623791409694661916484452406075861096590830075343077928662936101268511022924767373294119153179454297967485730222633036942419973579918760623459034361263323133376321440702090121709343918825549182564374835618370051132183549677699811837147620470955921780401668542805638645450354909930132437838826740986409670274811903469104528321703950451810371107483245259587392558432592523541801722349090759006533692248144786501582111998420718472677042194810289310877416356226253605234460437478114284180968561681784902533928153141910249065798518140814881090535162089054584612406650565019639032016129931434988975524902343750000 56318111938131743424473663436659057930822976089582473019858578590168804682130547966986741130836629862500152656415571511742363204355503290344379676698009921313426941039718389845042959616742767775738945724587446480583929518400556686653461425527879292224321733209245655990048859162771160741087577641354963838790178168966218868452755585933950818980675810785591075513677121643845535544177979288645158106862191877201483384917672219949306863538144042279571927943407179186048098617926024544278130903570863719687385156824273692422632767882023679641551222129834722218530016638487461657710614100124804507987078699748990701302949858781894849670018959539419207178607864158185177489008487950859192659607943367065962833944950662416445161135711612992909890573502310962758064318445399562813885504981347164465940879951928612179315768710807614538804699577667634002864360809326171875000000 2522616198132663913623946743606298750331227453144742887035699330008788039101847812894650979130373964473415937092671667795542880383032226928012459613743733290122403511436175762008622105041453205694570990769435567979395585076391501207328688968507599238257781343411547153759618305374422327096544475715820313038565055023471743653707244907784874943917328782643854739502385900505003025169363466872117860222936575896904143172097129128473544428209878853729626290487309725618843083125679878357035243800261165912990391787340788274457336810872928620954000985830225385134678387948945281526926116648850348520718567539900180163711747706864930285521212080126213207021904199520871270817521482443622080209512404508837851481841265332550176283049505659778605311018080708629872910559243977448467589805369100399632670008839188780069884771907213344421805345518805552273988723754882812500000 80080912322098942498827324739168103373979802120547308916460968288807860102725361893108613020198245083040016579806499976023592030093255051221576168139532858192862182951945399468908501202631292817212133500961057635633340437582375873664900779592979217127967315589929944056296280072585081484913552511335493758734981628600898999826747213793924223057405041011906202353025752286208892645637124756882275447812356556146809960322627961812038196861412253265445992971328318450708785997973988596013198455096227157052307811751390748036158754853834608211234560196495394816430534594908544576531420460077822472447720268478148619928425666739038039066001904716878087373343692513349366517720752381961178951953879444640407652424044049319260415191457327648779737860801611260132751814148457669816572028297456483540317248710566321362109136494135397388305364074767567217350006103515625000000 159127542991233483733681535829437957018443817511357135231486294815953239602206942050267775536834109215729221041725796295759504429011168096118279341418912154845764711115450384014765183625778671286260592690371319858634655677830682918173643184301464391761340762963544317660169694889773639391935043821961249031077723803202156970504845195258793902974764961491583232210788652036459218613864274216772481412553093525365376376049710162044129953494013215916409339053367176659108381431258276627188793775820221188356159622034612956532872469792217221838779267904328164884225105545041466234796237496121240971165749474383463425999629938567297371597061409303858541349337627889434389361901270779014954631131827705977118711101431697376239213699708187201703685575798816106990307825272956235728967919716321377452889984354569434470078124598674262912822996440809220075607299804687500000 -241908740247107516866473653930617141346021356301718217001923328054338921574747784796049225090973813183195820371848285317188134696646542770952899220302828863514726944778903581437363791124774272311137768867801888914037435996741074265436277716033358013701315502979419583471091825934153811995075619580067783663703212772003581826673864108449057482737599639884925440395552079966143473222749707531379799525398666700315949817336268371007289237718489329267025734878616252345842135405591414905826633826927469886219236394448967362539835772610458718141505560642156624203414591398576600887750736203629934952375360244032288607240635756382515349627859020203513359392122066667195214007963146032040735816225021224556193377890683262715174109587157030259086013614675285676279299196862845412307182517793228825224731221069637794161510360897715532502161295269615948200225830078125000000 -25583515175299544335224167884482251726731804069531046626657596789908060678825139760791519427028488046974309974894966122838603049138048952791422568827488890663756035218482415362446227480177234726304687995882916686602139786117294335331638900711388334483214849529145722334218291335945386112562271703710175167852508183169509240030440230750259272336934043913865010887469006333440018606159545774277279091749289433483178627874545688397951486983370748580708807313990279404869717039844050388434588948732742792721763566635449232406298074128823757133028429520059151905942254879316127905690812622830548876427598635313465960024009971389493307619603533650649729838017881988369371323368929267167015917761524094161892868651794758952058818681867183121636799296237257460818437498685207260683967284140069581839412332604726031035916793219403553294455377908889204263687133789062500000 -1874809652102580133587775727802731584683717304722691532014432890168842318611379872215366370968888018344057658331058274947012171971817761319480502585043936294263152986293563513749066787892816815902185840545582105734443554348202072196991484538768537688401166224986048642450974063585060575916819686624788143186081416951939638703895657239374841694215081941520279835846589400959491002865806787486661973353528488400055375294143128813305524166241671583713551273706985171695154836404111199648077522284922333506489189895277220313591651161123600795777084259715765421113098779849892555490086922325197527913306008267978413045396423338440027130499739968655880137119493910981886001878489608845252519185230067714724823245474556215573048199063858643133542662936644074873862378464810478225934021958543771404918536370885047775982864583232956334768459782935678958892822265625000000 -112566773296327153931061482990167758240335820239932756459769127161593261220242983341857478428376383726743315941749283108234218338202871883510213563478701627796485441421260482531717879446855524069243630477267076170688308326728461898598355434554500353216927484804167452501490113402491457468490310509227610125602489792886342201321227492651736306261194239857055207116436031197342835008206883808371976059353721056157672980063385980671871788750487043634255801965004407547412451921334702018379478310397907172657626819265595006470659547617590365273601589797096475030959597046957574415892225240365205324466291553732303442404137401488447537032973338353434546376196507702420988124218840027539708158667272257418476446546278035380471390524669112871600743207117727756449406935875666466589179142569413533866956603320615543338951937066272357412799465237185359001159667968750000 -5716604938054866843239800653129273689284644031008088653496886194202745928037093050559531650611496368932687810631830438236554422031203232778306373759217337499021006135305268258964615818703521241185082945082922128237479209350079525588793226795665797151862356554166822849925954021653235229929994263796678020554317974030979584719077334864811525640188940451989479127203070125582820655533212148738288151556524103770049576736827684609830822798052690897246752983445887676780521091863203122014858737821671380275903655567820828135882299210810252486118402072507466588223467109369118690233472551936171415799517768073125750682624315145557362797545034344859875013702516552022309284663344794106630617246677952896514524595726880154985483405296004498524594027527291614682181072684218498741704165345105536217568566268683108241182612430097975675380439497530460357666015625000000 -238521839981603742897593862123129011194009048579289290480115884649461681585558021679050554788018326578240971260646704495647311568082802505085443933757995962084845713893369005342774192167532383948183244297321139498536387055654846452768629124596824556810629413647384703114923786830686829447504435149158114548864891826358032538422856536873520347675284520641337478115721572261946796111812276637772765779946783362209190538241438942231187223334019010083620179135777367942241646308772790602475201602794778885487100444999007911932919883848293655225697293661076709643441706164696865026239740758770285123644047139952286956028447562248757890911496929055493235555372440374938414468967948260948190028027023078497676129270323323784685583194060446930993498443205028445205876581857642749340349826762605730464435276101144834228276470078355941950576379895210266113281250000000 -6986741911678336848294269302726689251902538241172626978346376382355485882230594654151009320595362986327355007520851904640882055469604148107957780453165561409107139260079490412245632913325360164038765982635631645625772579838538331027770418097269772669497530217674255635566370302110500031768090927512122791001794334538276329931162852611604235219901648478126486220965485791808236957813827699644150059148095153985252410139636190706636482740083136447868623988612515596303584863267124442036243055302007310798024275172302331142552479621894302956393839398165862181020285056056323921796721929741944991875854395674675794503286069389622913222778207578187310993809656829580859853831164900261769737876715557602341792703865004078810687849872959689457270477193281375223724982206825140605893953359827567968551582989419708913554629692299613452632911503314971923828125000000 -1126826324295919228787050484940101464919844328301863045170488791308145063045492934787627337566866407327324146498759777909888746521900323631974498117139749036314844327957223474771291245915256036474379466304937418260575099672086382044569701566946405236746116667464658109766848837449506165863917735596361018535399775361454118272425521811842778486726610421483800582153690140227923132861302892790529089555690156390473823447357735582249083914167260070402154608029080084617390946744605864675966638042182562552313334898288159237349724109630528666695895271070935361875232227423281974530627361006252641771338234144519997538398930471689784061544674776010321649349823128810501519101413178474295826194102415463478471819442823080879799802874279653514971568279425431276296802600438046569770651117108791393506409142540969185730670432121769408695399761199951171875000000 19809313461356024891737830717480396517518922147704782253809715524228388310789783553326362175481685412273631663393472094363016203828479569828029656107189320921423618599628934848491426381739095015298131759858573587097739140704866550400946296000682216279857995248208919943914523408094367719587619295854055593586224809247212561712255671899304442327563622915945281737034162432455845285089981046877312118444219391397661090380575297823389993115859289894612670765869395348937877712050477177116375175926842181211972208991594523907698516257415711588810067219575948368724856223015785825072444156684832838093466366913057939114911851226872392684855408225138884817777909946568040694014492267277177032129224278669797202253785387276439331534672956161927626340053223716023686525904787010278471967791782793308901708082228501454913338619689966435544192790985107421875000000 1934637722315637902657932221526674202757442550597348730623521155503296367862862035826157911905992347828037304059153840135421444802324120714044685089932889700579132579200919300047776212173740746495386586617205735789540226489832532171422206353039843316599907794814069340534699239840203697736121293597757537233261364931746435507755767949392250686168203209997289503306687267600328409288280154092430786557111313709670569396656706770846112240127001697045850784100756725187473035986499948202335339043512962634599375773729235463383901801126063568905518736935980887531592443139588499536887500933347153902644657331195321834427745426054631533260206085848032131384227998335390484951444913434976147656269273969119412574812946308945007769408900155262790219263872437380194823702040657053661552679286852279681466915077351666207849945067209773696959018707275390625000000 132415392109973756861152831940129913678530819667366600559083346346558474085510846464577658835289224616332671508461947698570846310445226112531040784151090710898835207892902928376236508276448230131726921668684415154494850885556666488061072828508155266862560849048307810873892271724571089597111616922380923373150505873174691477984685555941377940880038523258399287375226618935095881138369247734184003768806114923094667753600718432973825150851947302797091206091816718426416854430735591928372688792070502299135049359736965211544389607155877482661567149244695922070075261041498455887908533335484661585908119881165992898073954745506710700656143595306238160460712392862903218749135099013210791920950975366346504526216990696554524612507748726444997238683810104310833028599248029029940365695476122449812950546786248680330988491959942621178925037384033203125000000 7445154918683194900780077738758330571939324455170125470237469059826889996784985006382592852712253618761028194958200820972734862038018116808341046542345908258896138798959143114313021870534251409124672308465878475308567396983262587773519629625617376694404584556225877448403947742787318432114072364044167150786860530460506733685714693313096357317644466792926634847450635186444239030374219382355733462659229751138858243685002277876841953682395564523893139575893935428356856038289627289109245104702925441240361411114565271197530902548446027783519707527517951844305232220569209554942379673793230610920546776823287913419591924480881653369044378212918550990876032279775925937634248291910671689533430035449945358583187056941152832168577960797458115438155047602311906309306476948955773869044033864120316822120631519883737770015841306303627789020538330078125000 354135933623841723060831031725111024990900964660811936061026027411145002829893748848923658802746087023025050418920747279701084227886198014212705439447318560151948185762494787521124123941181725428320458316311650292569524624981438754098902993573630468466253891011773220460888820647279704184904177302762958721288940119309157651665686722952578410506259021684337522317587118217965351370554621610470082410479222797314842908939225626343661339705152355958048468292431779357886725542225391861956444601701472588315664584922107570595623611302753922609268595289850855697871768300144542617422142814197779637316016452771186541050147270977747357907754297162007940177236342756661311894867485447194132135241211054814964257513769585018777591820933838183871621505014977001262640811596454374712648165020384767267367119364038230422409014863660559058189392089843750000000 13803747458526172944472827909560439450227394849220358367633685953873829362068910615897932077449695195608903350007383545018912052656558032333761738136950104460088434063160239906628436633888374622175397360250098600310604216599326968608217907384383276273882221948973172358405497750458801488151097524453158667932021307825748585726232092493841370203923724483183069587231071595818808305169977425384496520135268875232218896472771095997258593003538596273168929190804204665307615535295816975310384692801431093667601082376446626891932119871577723698148138937612415278005528469925217167886455243742152615146852279842989512266969075529006249442088397755001720493400315583326363746829605595335506884135101449030880421442720658415564193151911124497673948474019671116827725445477944965133100130541123779248513841810602417736753011467953911051154136657714843750000 372456130175735443369445018054141767770470893572606267521884236598818542688199227388703258771630471896834347184159889391120545822548714900319456308865811310676361857728417793948877974602805379485018147583013522412045734568053089471392365924371928727782031772136768246625606194792214340079525215269973216992745273891014990730325555434864871376770229783718763162208772004180880619469756215194929457628040286934256457086595878045074383995662831795566366338047933326497253506450028122399410349845087368261302593069608336632188864117585929328667829081818318609339818625241098696442922549380800763174543246710856541808867596505114789183036094741772102096689915467415406272921174791002780934353732495724837411273288193076211208279550147252188333236654364372694968476590975782866598052523965965810498945833678652306275580485817044973373413085937500000000 -805225920920924892597971102711959070247025572205788103259222499364110168908830007410470816460531657552641851299308555279919164765488569439405907383115968211123954958440162682158546025260517686185133208287089180229246302746644469817498452358420629487032890605084797395316220546126091297003391229205662327903089996734567545774308947925935044627995403846949202688858339020389851339565015749038022813377341970662749562857849004848234839254487046590157075142114165839095931306141027222096871267075140661434116938533322106979821719258902969842953549780462648636482623584886959700718110842108680384633891856740881181130733984559748843341431947039182659475078324423228966334131344897905881219781228004827079027595054375560505751225383587042242477004395414342229802663455489589584198831028974866007625910699699312012000973481917753815650939941406250000 -1022399156235313014918276145164296601811658614537476221458244633240647354718410745252384562373076292357576969691652935059791120529091272126470615637855018462976999829880079481878298579127955212067776384899496394635826605627581151259866509612758733067616456997008751204959398400719134661600651636314071292042171226691613640215366883820330468399338300957769616558792594181287638835210078024099725928875369967698398450021121466060206723622288891037837851949694390697899267055922163883484336206292660174687423109264879805663864057545423444158047000666629295027940828250847300353501734924578366320775465752296040619302654227766883298145160161721383980727292933861699097822631196328767046618734300908469778170628411196237433120137852979425581839802831216672044558471740494236950377342498559075541694480919463483559184169280342757701873779296875000000 -92229536643436019589408012271699170022785605581832704798591441590694277288588590159735717472767143001729627672239904902645538480495010508244680223292904692196234710920081534486205149868119670156934763817120798126118004518499835548911622038080647412285901268488042702386592166296286057597442789338863325084607894224881959086317461843568380384480819553912640675199308752105669090811254861581266711820066437716824839994797296306105923307606269887360079578724095030177506699236249034960921693104275438646231830721646018275291318292292298707669696043892126531851117081288489035790462295310846652580918964284633722115362135062246926773753599629214121649074082902623682238010836516888913805665580874626180845694021851676279025770235358829086246718960653471679191892088147765794477079292720658102432297999542787358961959398584440350532531738281250000 -5914090188177037597171470585396076552674799278517289262698850513628733271678027329236878413877464912596934885649577619464644006693489754449379994676643757806263375916710769572573055846857765992162996443618106358534752935397906610631816246951940234546452312066597358436146446784007217085889229160738816366023949700753119104712741555749756478895084753757201176190545188548934563295520001367784527024482080029902349457958368047766444333991099394037736259353849330721903581366560931886593378405619409325168197968773197563030615343888230895890229720887471546994779284335350860118740598225632158104628972152091400272377365086076527999572875407745836073961546808369339187888669366915261928463763471910656269694801569930034698904649513519948601493786959266602022718803131070114745443885352270762555452164599412157031110837124288082122802734375000000 -312675159853926028425830997327226085530970608556892903252752079819352771636727327475405644864446540508062282088038316929482462943548452019941903160876508488488943735076058753431722207431188524600547035527076052523791410492782904293253441610519801567981608605321657421971977539437968699234565087539898740001438336981787619088660285699553302184741871322955985907860770657115675762802773683433062547907184233272028515615321975227377908801796459733496951092689919795388697368904999038030659867879210957301192874265877643194079497789066912561275985842157343782234518274469539660031362565267880735113671077025212381109891601353078981286962075713167677955773967384572976032773802956079614397059394685144045028936702329663285240192764045714095094634453616729039652430599123003456943310177242151043616237050815076514709289767779409885406494140625000 -14001284831260390827921757538977322292045848013658328528246833753857635922897837990291749999059626296225085399289866043618296690669505373936497104385976797163947840953591523921532743642965848862962933249999478033912210393666636141016735128655639662523545951564339612112104810273662049549518324623718352359094568136015311798025059387006619892969779162460070733812711998016392599129019195244552298079098025097389737057148870202192025332031270386596837047607842180101688748817452655094043888529008198039600917513379892749954051442481272060154721010517430290413324537187173759498561679406397274266836907560766431662306626665404422507358451763227234763133866759424573415362686244804226992480363901001149284233394043023112955072611671778761349069592284981297696237387973737724227019685461747004924515369594928415608592331409454345703125000000000 -513410282556141385959124983801025395726983865322456409466304717943309786369150862496514685162607748877682924941398717550909035214668228086383370904189084026620358119924602986745252679856528444652684637821088557569936045310687468647720225117742635071220130328349839096025227327388651314663992868584848217768242851020632577464568313551972614374512728494154450093730786205834002839681745127605946431784149644785533264134903394652581076066650127897490099163761242412639204838184562162628220577552324440270466219036287009873619259196402234706813550972059085202018176274570503231648613576650921520454806463987261008320198630598784441186254970316497128316400917489237911603788583271216557727097934471107290177407842315944038023029819208103822318170783894374644877399326155577058085313943277137242564289731916460368665866553783416748046875000000 -12939852060499668345716385505430275361852369805178306970358372321780483798071379103201327312279465191638686491516558465378698000214738611195665672166299759499521028393970007456753303488272250251658692493589051062486559556886735677155467373778649663016586187560453917813264155942718986706481555578351344441213238780964629376290068962727214398956065150028244511984399984405402178804941208705822651228422714801967249045009530434918348762352052361196400248940180665824005906825574584337324164012168369336100140141126616095437991706352582196815791928938226832282297244926558437819925987463550290383234485414683497467103968587048697988600386382346398660110810996491672489049511135113531956655828965292336649330556381807869687240300026615034906541566630573407951857410930608524537708340750307182617784285127982002450153231620788574218750000000 41871921631239412549375834060983724456097081059271677273353020312464019465441607908609451076489024336960273048136630729027483357353741072747627664524570982439432833693733948572487966426145236123404126253260713604275751381197134286651773836784583607143810968404721880684592471726195907784066035735321518219239969170565425109224413958629712750675132789170621423647936470107515715548009809606771197356906074224968252830372617336367988529303040507955946135176273243201478081268426391376250937911163803342475462666937762915154037567970206097254695605158869088642946227186848095580087745770640076789905487106357598536970443164364881244891408391063560385062277642202973601642715695903299760333140528994792934172768249526797677734990899008486650497201111207872399388780536016475353952337930014005601409010637325991410762071609497070312500000 33238924765552354653619896945919902957838405167681017188913634135931403713467723599546035979924950652410371027448928638372276323628658117343807296070108559026943828486102415663288008853835885744204717972689806721130447629355926856730973498225340640113112471199942779118078465055379390134391799227915080793612271238916688078825809213922881005305746367316191313114489591237723867788815219703643116579972255007616208980696078834221185679938557207369519277382290422444379195037596940353718304658006722342757699412290472539558526857021680242677735751500951565827787024938316312785616855587934111774567776147352851897187689868683653419921919253410588391219358293754017986369924940252660526915113403545293979091819361827409233297087871255247437963885947562208603032165061263640089821778635581148164668263689236482605338096618652343750000000 2813483274616149275445025470700454812332980101219843951007761311662491595650204100876954748128621047926268601912811508357422375796575732724722758582433211812195476931715555264073556583345372760759211380451271214503822093947055497288943118320889260628624101165834908075371552968291313355477657476801638876478243116513232632668324919717757498222723777229122463531726577317161556894581042108453513931604269911364155800349560244346602086022013660935780636355493061157745916720911317040773695427972935544978917257298309635785625071373600689823405859063317672077168302131310908575361373256267615071545976525210618342107329656774137375833225681940309915633601398179266849974390170950832462120846795035464995467210229337248463322590509566506380389644337088212937937175422743322389382642637121849371606430167958023957908153533935546875000000 170720583038516332707904054513195645034045410402295069760809729529961293288310983421408281025814823041853398431750487833324357658070254968408958469250227738672338827568960829900103515193434435455462871998199395765064107113958556714877727127745294687453483388311485918684598627487556301294076529114667647761432695785694762391398044049764506837170744556487400002927461092699820052597316282066326439426038582524701358039010942143857507710969948107182057612918716011531003791868544510380673946715197398546631888910913663744920660797977003722163792647208637334097187768326969088680520618868731669521022610129369361635524739989532512513225464414372466829591134100191731443700220486914317014540324622864047628430360105670053158025575843776946333145417268138984752542321058949112502066576806808440025520212657283991575241088867187500000000 8584200078997704535967039022651502264905029810694202981452034829913203873221834859180324759319327950053067367488188712086786566774370963769315244194006260515101049624670713129915648397218468232591057645512320689002281298126503113997956915281753672489473544410923043927118228131140091163434086793343054240675108362123135272676132336977817871551568969808876693694629954043180262625041177645638892918755396482636734074815142249376273085500048812330388807452593966661360782668780016090965466316009719383207807654088203565913520745151659431664536179848547590250156315176042558863813530638904226717483831972370151258454299188236005202192514050424599186483278953888378401040481665746302435817734587929259469084929394187191305086928559003226232593099481351721333254924450843208758628725645717892633879131381036131642758846282958984375000 368374597648782985255131715615321542343298088522084987060519742339022865552756844934110963842491436950691031694025284175670681835097272484207768083355486711129041341106131319515747909826365996083446969294707748980772178887649724088418959087058943429587301074152334746617204889394604588878193559473604825328409003341033443770620283911047732238264423428344474866666812904446389436836428954489498589245357935122294793930167417232999158304796032282176501191592138730402388865722640068616577032598967390495810034298017868604946741057817586915102241356882609007622448836071823607402732058572218704837754398130737930825450137547974591358130631160519992649912528727217712275299473334052051994951014332805932694959864727727471903146284186441392210605813069267162044739519141343436623957916832561299003145904862321913242340087890625000000 13180301259333353430093023525204299157968988801028395336326463736059835124045173588485644931050167850726778561608093227184020062836086518535306398220497903332934753893592632987507533848908898201956442006946991661600377268229164147220358142309860848884768841766014750007630555048269101941303636549107161866780833696043001524398996033707944394896952788565344655546411160070128038398347967065625546412370141835714250951712555117053587736661704753846700807212251529924147570801958149459609088056300024389219948814146140544878595821341743671461650027551501835615982312437229591611502027216186026099301403481269200175379791416510631760980295668943979296643044440185540524124149964816293348634818589119867626453833330705489781703799900293737552273247480453071527010687249172791774257156244623545582328461023280397057533264160156250000 347486026898250510814449871957210084148645569933178983203266666134035400612824985025622177974687809754717958616677052164650498630803204362800039169342640931782011597175361664524819278343030568532815708393180111557420088943423032960055778054651486675002237771557811502236967292438295907118158152551695004768290374868991113874028370888793438004225350873945183365577233019663410892642126708574321735539159136374824106448392242671489337383914443363035158655871610217998254363394979769404981960302567039217738446582582428239116136976821313931858458685420289670522316830459146063381664184511039596604670685340236513183309643480116273332317061043027304373700876544553971468587623738941370798364027098260610775951485406244019935805372531078352381480257598102692894535163376685576571627038500178485946889850310981273651123046875000000 2257494693585395217912081435231520805501284423743017721625933893881662953992776127038045971144438085240811695677793497086164106310939670649027775780448240028990647345119009459012686513735544286247691177425809604356416917365591992190385239898730354493003857358539427616027965151407177603430907474801700027520048075289278423797864649126502001133478277673109406636859681833099298923508166076760390539386765764137782532673926127800765228658771148487819438178104039929100118343248800406503768693872697189621004133398697604220962041790774815122164899669084575176996109378923840315233150022724507590823293719438026897167918783099597719339767953209060566518319590780392695436265062936362285269472604914024289196889299336014481054265195737262284479844184175607487621822954325032857975661185201410319223214173689484596252441406250000 -504203321556396392254809491977876432470960245370193819520572131323408753053191285372411501598065587652381239217026609707947366535814460132905998699774088790544504897302626837335882611119354121550060044126194648071669603899423752311378866967616720497375974057740731820246232397795327945530847260630076134870969991487264529784797316632141106879754494000173047816340945800453298223972564165303219688199137774936916643148734542294022852469683163525846931560708545357148744323266162167713158848491144816950013436631730417593802157713894209236931843828470549811411703921210722969440787600202733452142127030721338323384389850752484441644609080808985138759747073584478180848114738942686750996953932112740098261980357419113023477460373590545517166802571783848810872123764196612905096397949655795400758506730198860168457031250000000 -45728989476341282412419798619295155799842514363730109492395420752185793520663494990770849599677705164407915909511434100304448956657964395841739736370781604967036855114399753630867251828542074544753059392616662934914804660162157227668041551928990724625162633126843583352471719873382433624958944016067157232476816066187355960732334498181915730120324247169171360156446393934264903595935334006634871133440965971552543364786151218231644266531167217966963463237938493555727897488100993962101733649056189924248264545044036410514312563678017137925248388250338003573281494001888018329392432739362695206422528867698309566128877015026317166652060979504242146393635848970148095161630949683119992779805845192701766505807502049296599874063830308752831939671910515226625028404322594737673899831231771884176851017400622367858886718750000 -2754402060275646250819095707826960685825190553533389619487222956638847911964567394182108660716495721188434382212123192622369166241353988290911089628628958574633967266878249362052149380063284328964382909957815367020380622055273079259227281299212398943825499290399934191043890433510280654809135478573230870658415302158428395133880803203724631431014949728669063181876021516810429716427948083619550589537383508497972981271613792805350676534369063249578995513192061896963138244956930176518901116731182829310986294996220349754361061019578301883503950789511973420760561171958364744257815398929999104914058034865746488649640310553287624361694690405187214580305051570496388191113862387094334975180255693596060243915132792948096688678402197969677073797277612877043732062789645697285789704977787550888024270534515380859375000000000 -136587660480481714596275847123694978370202223039154309272698283711515442971512474999344860304825166693196476773998038763523135535335603779107053852555936575967791573747170980251171121978858560617169183771483699781064561984770955989083976886822436648405935900512659491828410775317161000417053201745367475896280947183511749558954091746898690403363742510335089443945542441211496831640246030635939751419587679631014359193794780085199940344460320661206352609404379441795960797945862934589518355485739310359532116061210511073946152765844529044897135400605826940678666954212161899458113879173714130872656881129385295957423511942355258359963690240218352820454157830707461354547396441916413830293028632815770606349811819206368915660420237286039155751117880609390711755671544420148093117173271338060658308677375316619873046875000 -5888808031782427014514710616942597317697794586683189811400485287953129451458324017055388980005358912698153352510938075823754301220256390667969341287681932125645041918081491709800229089503075060976745014327144880761410287701219925578741234406029219192003500857000168135666257390330149986207366465408955563021975184676838686003735079483819314514749005065698777750498647760965318255736880128955261570642935209765336844086454686509316726949389984761832400375445302612321809053031849417866902602905523409483075898339672118859990646199542937227552505124800703666285644552115932959031057254578048172995680315518946158329278005562321212653217775098464326118858492979084826030644771873468962553430571296757511958227165910389990206912019994225495045929408312341160295065856970721414331837451072715339250862598419189453125000000 -223416530951751666057290436581467376165525317219244190607208063090077624934701476492834719057325887462936954756694376476354498642669510113269874605034037106609771626417804200604996694916012007703139290747052351734959726315481915782633547497641028812552248539346684278484617002585974622036522799946562707090618349965519974567254234266079500456327741991872127314123710963513711185534773522932896376663378354984155366437338841603170231171299578193358497602699225955827419615467241277157336411812204927600154137036954028912934198082720316365796745755848434541175238842446005032775024717992211226201374391257026719407843773318779497628138296916899778043321733184750061702926009095769947417736450723115455344381991080742420818524793222277059343364574194805599335888695949024762565926494062296114861965179443359375000000000 -7339399784059147357455887517636984290177164591257623602973450754541036660933010758610269681951272023763292755047375000243013626400370224754528980048640861886847054318803792115310782447154820977226660569615777992490177338179923833456599293525520935661198086703493784095136868503949692417912908617842383853859021396933824463776043753385675996424522371439284771665939270199461333099643483200694836326021961022042154610795690792235598245670064569630823250413054676469308101804590270155825186378021218994175086610326987756939201588196842668582432898953666966519690831912106016578345892548349708376568091840116801102010434367896610028233701545122837308218991834933723124363685036558481835528130687335848013351230169678320258984076938945745477881388973559210887049659936668712101326406127554946579039096832275390625000000 -194947235373464063321073647221201684062641486754742087396652777052701644320581530191462757054909973396843949556653627933731494761727485198732912709694212678121768478860336262477977998067718974604449917624944340609012232601042075724850250608699993268144611911619854025102600570802497314456486697031222758151888669678561976222453478847458235382292626272669279797065908016414957500301002232177605802593510636824396748406988811717576563267735373721628627575418771763050482264173614971021985281971942516137501942816257489247696905622018504751185132046460687504322524903580129542476680353169987636540595983778814524772492492173299073043854257110120169524936978076963128645717816138678878579147071350922830387229265599299011742455109387418014959306289676910380744356298169349395177363248876645229756832122802734375000000 -3041843294316366236837437732395805712662166914574914788370649828552350133875956591444547516809517786223088009882921225343941456473089277866210539999004871534260767493430678835368061265069876966604580907939526759626376843966044636503237610557766405479336359310168008108388944424283255703080653929884870976275686240377426606822781985376320715125845287441092679917534127250490678997814345270948968448963786942674906009185257554619148460196854531842965338255940647328932270885443209206784976318353530408324171622362922366607043668371159180380669645180824756354780671785020194371561281412757631366360126794106040665407978576675008463145451279342471912733240043041395562306612361193566255493263841417068089908711208795586768497627679752448712960474655692149747527580475915665036978907664888538420200347900390625000000 76607992958880326763778575434810679790340075934810274844469489029788389648649574923189738444701419251844748605644784933430692125463221511379966012061437316917184929349787084634530280588211141726201487699997836363103074218670895449596456764349918635344244404889095543529754231837287267977231764479791129662369048174738377178722124538605868204010936680385260197494691479710645081566724610433721908473773455209375860319715323595558868289585747736408640543905746820792949851773055080822180420179600782512157579468567986151099838274122566023754374903076979397554830971291892855522998609666012157879880693861620194594906520412949614885530857827925153999436791729903083048942001982016388173040125957378959132459435453863493891600371106373683404485531220877174266815023105647863843614686629734933376312255859375000000 10532988251610198318412963652495593951323738717937076738651883044800393135191227418972541685512285980088488835819331645286382123354946688752388167632060129145119941410988356708174654493581699639290488171051453495619928961485171782443124680988927675128995056738451311953643550668243544582297859149949417962380702324605637288239183777418856745676809843931949443586259262312003835250958722803260478344298235400909728653288550480535169813602045740587036038742633526914647122219964931910303012366785514024939192874569784868743626752367966903262202574826228938196188640535088166252948094328251686482715677565732053870159433213251472838406782274757711310391556618596265576629983376888693966035774429088901859094998289940727933856757043664363459714024152174602144555457840235934696693220757879316806793212890625000000 684018404327809961277977785806843832922758585229815641144617309277274469566844153443315271986450939495812430429710635709581148468282388367713090180364514193795893161846968745736480987763138647364900135941220775665155705441176353033771267032840705815463910147727489209980712486574003647714643507744689814867473839526789252949116880007333170311156829410301502234049096200152795820880338194067914635128457643420788770969788940928645331427066385546608698932029487062627316479707394967079338322035194036317661142004348055950540942420749785028430606348932985415769189455991010224101203054336383845299221136168267401666541664213914138184478698121310823769102152687865913671939215324778396976782267311537289232501202388619567631601108251395726493085956610615686772288194725244458993529406143352389335632324218750000 36316090272495358998713367521413183461468646408598416611538980359918521038662378494614638580607615490296536110500834265200803657737937857243365320663181105409679314212714800772310650666067780005653401250744683103604860747561205290268205933184772512492968581893650438230575149221289032437717050325309982482234896292839734198720141038078275154798494406878667971430094151912441024240182648964625215362311547242354097040046093966407565434291976646774527346838167112969026389193633668400508403510645424551776031094965300202135273650260619961652326393545352473513511420808724812467681620116393293608991047640347274209879614628135029106738967603726695021489538576970178495774446337684912802625395105702663889402308926577338726824369749682151751791983751074057267514173796829624052406870760023593902587890625000000 1761596150884492053691264003530423131068084722291784298019420733603458049765138517941892881467928025003499159257776862305825549855044913404714827216130251844407106239510662899672729874538300300772666503942970712443111473137440640680425668560441655543097181567345496148832642044520359373527554472458843296848066450274260616755300148016561014073785494324700364814627939278258599747241970822543119391745284544485516339916978943525091626773054505234899755210178412599662584276108683072242111367257868900966583467607747706009010462119476253590271486130724933043269198665341065784601526745476525116347858404849425926972010393333047137623806578561034544744165120604873960553097625358593164449279709655404993214175713435445582375522713984642806388960384304020094579489724706533593234780710190534591674804687500000 81615144166738090386774158744507096129041499088461147382870061614499369822155863573128391518151235972768294312526356067925938184764503025832547499019682236354639103958778610516174998376320979094938335352947762621365283528492843490245848518427492839153992557341695738616168286249517938321802331827024536072611273043568842600270500438087122430324151634870250783527484606321980077538590320839642259454395675050908406260099854938796739011057315526454235034865466315269667640470320370391605476821628899092320191384365413562442239219843455811016453826496259676199469434673084773616677505632518136958816224914193764129869158566755802523629520562869971278568749435755234412745256409022877921270849865884887100847791979333275720999762718213898558231527303113167644797731892225556293851695954799652099609375000000 3685244623791871938230827308426887503804983861074207066416791502384198536706830347692386941756331387831470114401751048745964409789464552225536350833399597398368367651126285190454738470710303216041922826969277135650933732064827284102905593588333328942648707826216667091033952617401893771204301904101880945907379366165506344988236480923912790971334886894642512588547328035087441575764699997214519463982518485486380157796317628790134317790640849283014757011892981373577833620110475821343762470832584848358358157445031032744686184820669396748318321852571044431170651238798641141801780625533368380623531028492927853334935119484941706319790200207041278780357399957845114090576435917302056535545502440190696403848015526718769394380174846922054230496095487250860552735920450118101143743842840194702148437500000 163376829559135283195886332153432415854805332883968538729611339064540031625900629183977455071457716965659573679674696622466241332055020813575742399248332427911249811524987008481949780733702249324328803582645907851990764331551107696602132643867511510980066977157411847489773415504803127573950079488148852687522534302475694405109652670313401028323216055480640651310460218607333569930878576115807913068846572819111424540660626646530146386057482629669450350392240458577054015748726894749482022905313467706123052558672760604675681568354315740292078567806610842347148032681845230376506495113137277075873614626263133842716454814746844391442554151288821164282640955240211893324134528540419560750439333020365125799970493864102810390529393252076948050037706098810454113934298447929904796183109283447265625000000 7113016225446385343768403520667794814437224558720430695010839443046968059285402708551852739713019402018015004399185422386274150239554128526750406084155578726442380900703474229380214469385672526092182927467232940790048226304760266601756824965582603147571830703789335222443062106376476855474442863278955459960841809551336415705879689618351565254162936786021013240886417771705159227715691438787468968679341726354692134486265979171545970270376286123347453748607986034411128462369731521113610888794647749634233727789998293022997894503221997971474588910890705712955614774450691076423379019713899666877970042759795659423135409564823498194438990680323366932964891241652242761542305858979038600690969439944126839077485065579589419360529488241678677087657642656107898071482509294582996517419815063476562500000 303305943568234918671384273360526104626396084183135953866826337954561172648013636436421315430739600037559262300209128346613995646254958897987442429294714739617745321479559435688565129613582044085213696653944755002591558325461802316135267050094709055834161423373655451314650535357077267283910267732087658602132600965216347119544251081955493646889367461434073560363641782618316113630032943498549780620137359610341721826568002095235726604744493153289797804366707741907799669340967049614614879629658641277662954412858416688325025217128822190528215898459489611466175649159118631896859114298976570621934437604453599340914621373556531007551092511319805673862885748187548365039931481772787775208903668137678053856514500358756791545593353289660230096537476781638764666837460026727057993412017822265625000000 12630695994042705006836303656774776224258661796875958193468257560997407357789802576510226581130913500868901003861733970660621135380011914656538395265305728023381673122849601382733522746849179088519389299256994889561757314109026838085868327820377520143704489317176879024447793244863272261919696698478897606774633456475810441087174608805875868472222909524978975722020765822308150264399854605380860424748620256811479350876198986023298214757425504107929959297857914238280295799846910088723890497881020683010679616240978610975213835954349923227429218564713238819570151836390814247499124324169473211811934398630797812061034061882370494971970696705714892835649166424350985620308600630139507298337008105693634943557109767180214184207851120027749767196597387728176919985401127632940188050270080566406250000 512874339384141704557248898132705828150536014987092300274485884320380602632862945606192660548377086615332302157874999133848775177240730413907874233477400757002320808565286327606871671428891762074468870531478297118806068531833883167723952163427611741619653094910926914249994540833359941424941611734509624031393756065837567457131647964964636377984567528028062916369770959176388038932541629329530253324127260662951175888203389351339142315300622192220674206612687331631295230880358736760242061286235185722610067530741043628389531807317731516842444082875108135429015300638235989544086403036513472635888513334490212760935921457128626368398189229121825113837840267974229083086468350968900474399821888485705709192388522855439480844442112149255777698038231450505808339812574558891355991363525390625000000 20309787439896137617016034544197296890405337510761927439551746914935695580553333749118409234015485486511102361003070238921377480789614212953724213800220393317338042206794176581683620119354459089041786980884080281920121329785287623780503914564190465340628405064657297574811804108465544556533138836058613084832259630497553533487447085391916136804704969794047947302135003890575085687532856130903287622854818700509662062126739787908856742514216381845742495604599000166674902366842666751755467843069982416872349706200507357300831635292469921292031568239068941895418563949892827835543878190218267218105100641034876953765250276010320509889464490461196065574655208858024259919849721080920872558234051467217816818456812100652246471854535650602588131512335652140155417555433814413845539093017578125000000 785731850200059823602011054623185060133596258719134606005247691836898414835020416746997912889721137007145577881608853691678723263608547016595565986173844619882486426949658055814636012927028869655588299212074786287108318686176786416819531644443410981641553658772751291678124400635856045696547591571229173347600216772292772263192408372652069122875190790394257321599756585178063399913972130308778581549601239140488794993556776595854231684682677123523222472379992270156956900440265526658021231041291447580109108014382215881467798470155678441190767442817315388485617403256350083678310693245672090405382020264056674697224153835102500219070967838741874403640338299064180343546599683990870472097134634399302575523917071900971516871246230800500756708882633960744357182193198241293430328369140625000000 29783502846041684956104471845112231669945905348952143602537328727235063562837424824139264386713046851657762274145332227293346040082583121550427012239752620524447136115215030127195596876216814226569701826129159461494620856667906874870457736824852783393190918844304825749199877643444359642593057372735912763862704259463354347256958288359810370611580537867241123576784885702418109861459722308060549408703030305137787200775606783446754678920152557713991865466520945049456853789818338140838295989832392179723131058596509608418659703808092140740934239724814480951472091307201614806968367266638232740600692709168745390159794113107908062142777447207579264435825926328921109382602735174060650236851547251314798808172575225051821419336779349330227711911689425505755934864282608032226562500000000000000 1109944748369265894914654395757851647131601046063547756080813692674292083940996197267745961515824425656258643985875362358367547796062187537764484984366191228383670120918389692990410706475591435360318524003036473184127447504822224858444918722903301414051065635136064570221976877617061254783309140966997617162073450264385812271304196910018294003348476982480418511159756222522111307228681790396910515193500969284101067964500949280962531836692115046129929643076720526932680232083961112339125545079047583652353197624644009495741911618708289996081723365093640316049463567822610960813745732838804980041625976529084582932471206319724384509204392184844913975624633698444092731762593552030754730123819285231668050704326410183515249207697603921646910111499517714861440254026092588901519775390625000000 40803685641671347121325560099499023335791979515360132304976093884685151997784669586649620963956899160990181874725770718860857850318104930642430979499773493576993535815942474608652839853385066437359082084357814382162866073549764613958929475752227790731038078341128215241269803995513545632012139582195392921857691923891866803141622443544516639163299684848552851075957058178048857131389574209094404427599530665601742722261810558040472096533788565596593423779221328092758613217843885127472395285676260685716499414143999290065127261293192320753301777634530598551580297241623599978797822512607950493299819209746695250450031699139093960518276939586883762834553120201647787899847389728301669550145997936463961259779008442684049028899411351203180536167947067838213115464895963668823242187500000000 1483659111450638652177223715574104392466138284073153622707082987951398187773959583298506750880445856275926466564085642702756772702121986823211218303066593863043554234354021633032733642754460757722159297616594095935160957172348214399531642771628518412955367140548594048114026743395074793827387504760891887520884351049889441909631673861927192854081246357518119507510994763544781255500760264038655229102412394823798962240161199085109168386711684678712453328498685800801582955519162779465808716631387996072327160566942753557800623912888897731827651760976249047473950913566818276814676834701978416837740067605247448705824587965409290323874328813887218431267707902052287359473541394413085272642808197696477110192477710199285305682613399209953774886272537258946613292209804058074951171875000000 53449405651980844755705545646221223361428526130495589313120244124029640338009218335616538565663660958937958231900132122586152690924942540571826668050808857678037440046781639126521394945856647906376931922220683142953689935044353213749812696694854326873979133676359690079557903517034719885825437117103617716464356824393481929956357722313421560321523733345345327088537649410632048717689648004850675216126154874957241136885819310912690250977944953509321820389341458928672088791767400830401737327161801940431573371597366311246448151746658699030796961961971087613862558172111973416339382049693397070470243270163328993604489137482756887202014301721849817937694576877962961832001084142626337110533346059803307636811230491582526465527667171144938747587294081142772483872249722480773925781250000 1909111829821471410239550915028943699980275541274303402058628064311226897356385885931098462442801252133195781024292111087693538169570848152405320251735436746390432139027315745039746453759253720635930750475494275908954469709967802855454821418824544545936920796570977914428685610398516019134970126369724090046281363147111517804431989158211271785971514987251124624505960547367931065137943301022641911067546516231238621554061394999209990945489178974863709625502692308197268186084708339629529603550006155275251032151412612725328492528413926869071387751500029335575197184582403184877043592093821728216718937881432580402494329093963407211904960268003963044538976902085449196981657643054672622345513894148767083935960909849403564039036783586320532302149644010569318197667598724365234375000000 67608236220953344182309394755507992980437394624740849517181234082608645211705291175566160784892560801102942385872867337061502997070579074852612186673683311011795656198212864792291822273486706888958821801490028670256947604450296044241185537420295664883775313567861835576743537740094128322639797109362673573332838217312800258849565623396494870034820631895315229799673658427513056152314036923837020303983301079638083264781871090982905616353827083973013401401309596654737594173963557822894209204788418633113719275315043282722157134477628104458098232767710195847590852821971952420984662234434551902061458986602958914644615611649440999707982568965564739780139402539760373022566906427105726794130518782370657421504425868298853220153563134528409278578564567396824713796377182006835937500000 2373236026245824304686315020407555107563403197254637611553572266506407706938222852574928389836677255911327489028241654864592285408810978702415797128428960856325514482655992005547347585681851508992643093231211273233781591503307859814199373429271952338661853471559107693169680726788827125925216008554519500823962949048559558567981250228804799933221182775111543319306619593829788990759465835386612913033344785926562868410227744908655331240445276152258261697148272914353255297499428935208049968398741755459638442125997643685299703457540753428778246785069251854461481713106006794810479765846958911210248121481235790905982087873480561609481296483231703996228190987462493800263117749420996655819332254518973492821378510948505990182462978212336868200083017654833383858203887939453125000000 82572441385548053552667589482623239517712070387847210105788312308442537058001602749664530237804908363737937086823143589613533261734828062959485683996617952884183759341570562738922812983367259544575375252245746228924922296149474260390569192869237217384216607053023011037198624511306850444993974930323297258956649533524051330520350026954666473245853840507329346869208441475609104342179492317576770173951353285396621526329525330837844440815209146889301643438605484125507700183023988834473203087723772383922973007726478317938924247324206519371642301886899797057276113123401784791409721748078823101876094387132430275465527742598816079405367568268831787977818906444429299312429814700763232498943942674628103437902131070797096867820530450166743863249507739965338259935379028320312500000 2848846612887232759341708787192346431260495921992341004672829588270021552423452589198752205826734052208255998244599304073728588602073457894265830423612379522851151665278854601813689722346347109175565642840336832810868092759323541216280858593113840236967991357101155793478690946369656175082765674461190854290131424269555065983332632488322615833842320321794189843917045200677119508788692384110227677953462602045943851831417405803913656952855746844432488176343715022648247218602907609737905746286923242337952815824862513281005169396595300073763237804012838939118603809598487103865871983986669052361522520884433679329167933552127172311993646713850340429052164659967137697154572098389766510537126520615640226067552886994926814927684625804171769658523771795444190502166748046875000000 97555200360711227701022888405605239300927059587747206880826253003074980261445256598580880415439173354032824492053839580844892840599705622604434845583149621451503535232141013470602868482776653543806797095530586006807877122532588041025974611775819684328779857463682278324499656920170225724749666052686936788432539321742966594933996930518712651991942851579347786604737911818872763360923767731926787335836383841713356552318808152731428580795554249397050354290632166774136825785092769450124688738593698654503068941993960285087680366457566387502813838848329224721909521941821917758053361052840653755527599928400598255653358617141265637341114666265488065422936675300451577327985030151365023672384702200187836029423366043370301727793265315208381949219074158463627099990844726562500000 3319825141667214580971302412645206747075662131085018047397804162240876636153118169139981841233013220136545724584224735330949799281826714689333899390870114577306459035665026749170682777773434750463159563545231825359056203360571112311049344678347295058071569011495758046230294166174749479948621789777865786954193988868213959128879893352005914183550089842281891996642089936587778560039828297769450382420735715367641827093193665661867788349891176972061988208576220115345827055020555367600088892355686359687007126039459875078991634169923734299823267010999617388854471360754412295206758878933596366600305275109233500166624487661665525249525150811399051713679119570343794323886417336964410359776434131056853859429532502942522973341985502437889721250030561350286006927490234375000000 112398849306975625125142085266813861873738829524964445261571203808406573934901901852332420111037616081328053237882499610378139322079133728767816779947769768824356419870758349264963684854705985557312475498310336449011279389772104295683395946015027474266436598120588527264212200399462939367422989556078427621075211034886948040192458001003366938391851843100955094118521509356906452914540166577939903818789403153823924193602716087264990815878651364817005986567179346940170406332399260245602400255998071927087537119052929358396636638490291013999827127714150667104443058760720964111835565411973998083323386882150308133016392784001922527050906773250297701954627936015373979032271097290299508422814997217223314237067482712980987101563301253093207776601047953590750694274902343750000 3788514009516531570421416585238594001838674189478742321740635352687162491756376476482503409699819931609366914464483967794423066924822522926991872972956599621275020926438406465250520001034452309003125828214557427603477885971849433155374829163328426655954858047187012797457933050293664203349193170809278194239952202409288614531471497424628425784380245688842452721267791753489448117111227011971829134024927572619942352853164037541946623550581147191325523791419352040572230075182711309881235538477434415659982638748192988509614645489484627366160392810272418043528858490334135038262456928775108188711686682065802307596429876547035466186563768218800462463640074760693333644159652703081856076482538936939310599124699082962084109474192039623829941774602048099040985107421875000000 127104512399617098771366504068499456388512447873131249807344837798701272642923425786202458698197075216532719015087612799315740635859084958542446765549497730633505227169052792516058959782063228915963304149825531326054596932107504308550480080721746125890846132563532025413659315364185483287556431512149153893920242792111916204392308702805506246787505028683023409301034229368227984699259251339706427094488779192384569535230554323877049634666383587864976281867220703781139125918174470860121394824331394732228453825211565253559154437631251773418280511523718537549873286360232941681838266744475307727020624417047336626715147319661924013569464845950500555102712816548223629880817876206811738473695492543430870221767128101301834322903183682740291260415688157081604003906250000000 4240048841504034547772572429588198615002353077812399358692626535125277074095918515243422824699944846462862412034930807139619955051586754661182798787506618295795376569929609986850979028698516372237634406476689541545240690214583942000765669750350192997132838535850852944322633043641717859349140575226086464001878839173096526299905989655553415949264193774261086134015299434791536901060732888376109279246695630668624114218433284103480688234327203219632590466730238974186825656371691732989240092028655023448273765008202921374206265265238236837441071684901454679967971096474143600705317490639369217623300578531557051597848332082800930444914795659118357466385196947090299822601745551842108060221076527984719702323426766446857485125254694224850027239881455898284912109375000000 140380078661218017423007598761037313358749916959672739350749312802585143873177647172439639028296932736728799704466547718858839418655531194919772305425999298043191319074605094072941062456865494878505171018770612460708297014376477642984389434815056647843841683409323826914417476191459755124869424664357179679470119156947226807788538762357183402868303967871273529054290784486697401153947062467463521020875744410677494063662689394919209659533603727192136287505880596789955305351372806083728150407666024081885453192241794298900458436335823423410050645399918251132380082826094587099987918664033688901923734116664444867782289227799662659161924117577107044344542359846264847182554226300552823503737659487924324667077330349267681210145841674830080592073500156402587890625000000 4602394479183862594274859683405076049985109876226792268147052400507863155231428818351572900816541189756741261355337762398419649971855465530155910232761586605389891506751798164104853130513955847912966742727053195447433411027287737208054823142634567317903677802578409215482632668111906500471290188697239525975165018122143535776285113825598519605636097276414992276047245015824496191425405938118958097073637388382854368500133961247938795561517201802511972998976118234755901499207522286191276610043377400516325830133975642695420443648040744979522604451657131347270008202916855550197445207394324500617464401240496964355659599050724474327461193021511335664377860330679623157729611059638720014030185455486588375444138127476844356278373737723086378537118434906005859375000000 149071796611112377809108333012297202008631845496354602539429726641104740930763835290544740509761679922663292204444817174921112576533721021868351371437141522479527938918204810310283485603111558060199298284558734609712106574601462253856244524136153437748315850877632992418352063058451637105663862068785775488856628091487366671312571984392907059296815906777098652111247194638139956453305657449647546140412880507512597479092080071589772459634213052600421951710344392765587662014327056603784783315492280123131643679554625210614008942077885845301996085645826774290682215053235524673442247098835823946634236913328177250652442621744490569308941277366922782865561880080418088848380453043541814800396334129122280060349080865766437098418606410632492043077945709228515625000000 4760308724235373491052333625169471691393437604198913956251830447303878128043635964115348382938795805363918828640047164616110458146773298510834051415188874480329855693910223471644227236851305199540587272299203794687495966666661325840377891634594058067347728932251778004101996361371449886865436319727520260307854560098693874468170771178404727075219412118767776724183761450249886240797234888074575510295875746297907433169644970612588562832307144846533424290915637704236141342512168925312697118513073096330279373209528228822241577092689123448754907520131461255904954818301513233289226102735373790902243839883643041324788962630426514592914065483997915741563546549541520484310708461481639150758514304639511856224313017548789572774836642565787769854068756103515625000000 149620369335413841397037508802011777439679974067112444532767087604644715187617742082954712464318778711779006962483112302617572958269973748827806843531471905251364778408353831056336773542140779238520853994267182160829599818074414043374339108450726328298386669046890291889368629621816397391353625786519658095731914484977337036683588071394947935436211609203248005714212504391226864840811410256050976838047063346156759093965797684243310915066888445866785466593503116470870128445469345259616781786313268475080897298156676238168684157928490891005033932304354368237904329401989594762887285004297414273872933286828771637872339051771693889105340285559924502507283684953841912494560782063328911668890626334819976866005244311462799543244184263812712742947041988372802734375 4623633074706382062388506072290869017084068739648505222362055928499377972121702565732937416814114616903982479200637717776118308678991883403815090726681983984290311040116494739020775573913237593052142170699530878261906734566880783860345164369304010997223519749736593912231504264922601231830851390378604508383225850387303230488011645262127684892917953564164541198342883184027769054130797399150578454791723179430552246850194185257121721786346365140317001194350341877731594610735671575644982048131680825892497380966517292351451501401990516133192104920671353606927971765575009629440708589566025880457483618959766094366611269677936947947323344398051856952898940783538716927067877882960196427002773872414331012856039847453738789173627310447045601904392242431640625000 140400464500665994081751209591155773659871991832878488609291013348380565873459190839597435082695859572011695826217771964900851330935229213138668109153351863006274321270239454849977482422663916823791386591916655119318524612770193596901147166181371257790367661192486355089149445540442647877377067666802376928416157745933470137461397675107204236506346015051310337887433857519475103311028030375889795684845786757524350248329231099290113809782201234078981812437026339985407099843914190361977469988484835357781491650325061573258342606645190023105457260213384272576145738139133651848350080420964945817615046153384930834065724934213228644161960802239993211095539193813738085007651084375173113498881724933585401307562692520486749558905614776449510827660560607910156250 4189014622400338196307406454240384849101259552720663246380066863529229484175580531631944291649141050964547808822790165772253469558989296604372947894811892692076639426314402305520584839470014430549988898599680173314791936054186989620337284742627837837578157127458761567296752460658709838210796404611314409393947259471543658692648253458056442620049775817067194905939313392531441753030667575116843967380553750032404044350722938268685085197730174422932913041757108165986641323297392430781961205309066219916670338268782577909381861980221526616018337070759514339411074053047977985014548174063664207888196545476070726767645562747634850633466611576620157595579221607644091513870350865777196651440827125440672626982522457929347670102515621692873537540435791015625000 122842800502113005879901522764288812741440671616337519989668928939461015430184234865181849516773939405134853275288252729123946003705134486490823461472964760533569143231357352313885431992309940908872805017159380651512288699328470618977015129733434219682358365012448495271168821106119941526499516171026711213070498671420915727647849555733709701681635632022421917045468385547372906770160624063906690421840913718290935425753822958267794889016779946180697580088236857688309848466494168626883658556999203962182841595555974403032365718129327373182844645989499454280933952203657890576416796013293850290779321476887593305738174261887253443284168359987934379131966225827764021112481238660647222188232367439623733194933435106457886298869652819121256470680236816406250 3542763256623556206704569485412559452869043843297490248679940165555713271553423059162478018651566083928293271575161726457077100945748509715994867438943252771490696590817557519759079258780107019494101185742959584892332072162907581559253030022054258019288793353587301228511152293006801985346218122030858901873989876634191871660605899805001615786085446219233840982684475034074192675667459174479174125979113852044820079657651270259190419378187152408896625826715180240665282744119337213652950323836443139264934405920350196610184409327038462084059611501195463711307305160908391288283358089686752306483150126133407815410743002943839639816800994250475148344435364258576099187232526227650142340031010299092012434197043746486599502532044425606727600097656250000000 100559491841025319810550434553516310513717357287305613454392983611806210403868592301587890720033554835038194216212059958534033221450594149072115014882305659052341014474234084576776993505849367317174220529250163376435463695458304831664793036142022130589731941309757463505483470897106102727922294017925352249308053869778523268855424470911865248540116599364479946611154549607850555042615048674765626071353904013902760813415426015542804503015521365441664212662703710582178213027437325930121055993635283512443752956250775231434949021609492409252572315756826407415404398542813207959865169956029101364648775646151214151948488982573684757079804757935243881439822397148225529190736925771007322477588579460541102841977323736899485595586156705394387245178222656250 2811583424000104192245775873979337823223450128755386839092778712978700296995734394749002182205305495455897072740612136822538348811027608831260811760131354888807257564423694921243806597247618162968218037538962760183947432315388748912283099900155638721060225420577291136557150157126543116827228384463480364323434675455421513316383814905240110301769380719580705579641807520822218104474998907712932189873576382775769077457979819163863069039242271227901538014260016792138610533880539658087110026513194976813704945442630695585221674850606547077478163680386590925579707223934260910395840451141066226401067371099318461386710338354809036675924942915628172053614274600488283527201083167630841920800063569747620788232683741725281834078487008810043334960937500000 77493159353217927445088791120437369862811406151803222890210749458923926512545415094088580820149751897034105993042097397412114628989480050799799605635094138766465753588049446011614447515786205200596885758912563344317927603793837336411354636999046363741090683717297564291555751407206375465582906653238637426831383116974052773587702602186522365235609929142977113354044326416571290057313980942724680658305756047193804655077888986498822489884183866560617101894365802554901080767185316040761545097231102851309091552181699833555623124179485718981504826629555957163998280222521059007307506897072635721425714737396204164732391407077224057756545485830507957983851012756651302805410930421560070120000477555675747813016158993537629839920555241405963897705078125 2106874359969880357262216202112168638491775621703355008212240700423611785097832116464315512634140329185982381374328141921907439700992912636569568581732160610503104627676637602193702012977243549415789453564959713473613707998683780426217214117165379154537769585311807797758912118286957845611830077312448498528148034364247187670159617516010847245482370448446502855498615985417160555712040973969137434562173897264674073448038101091799976282738257668094555522498720775716016034073744093969346716914422971694482795492744264759178201381720438677109158619216275394159300565115098174673856443114081353057698819073091408641297301329756241429221495223735587351152433996032245435275727983884950284284014626534758669700042599259859343874268233776092529296875000 56528608694585174317000571466147758730967862177210426264914005488737019328876291783708446542458676789993505793976784709467264379517523001863900584676444475845148733248122949682571210052234441442121898101901323360145351061645148574675663552952457298903875197329579814758474661850822464089571014254436929154596035000740643997792553621591273574628299163732651887447589520089424555796187343219796050817180406429834844252403092486078381479641379122414198341754509362005571803643974738625638318996536190313413872921300192221128864509435935944570751765325319342613475150695674034094268096336354386446162531815245105900317442226120257504974038230760710587889137490971337064101622620770700291274002297346360597016245996826455666450783610343933105468750000 1497069527961851559090485878787706031593185354771172260481065731125309159448121478822238662799217350477409654942665650591293821584140337061548416347298682070626961432823600160215043909182318869294270570362492479333940440280317951527735609412752584931433595686476074673795729939732099244272823115418311835048664513648837931704676345252000253546787195612209546568846797491572236912287756074119395549788119354688972868082015364892843998188731168239849322510093005092568441365662141311043246074576354594403718029809861669326681897244374052969216917120005188655878497131655991269572603680766407406998366675779190936802447920359919226075521639451583216810456893795822793339648079202963135268994422756997958630365008758644762565381824970245361328125000 39133233393841985379733609165603727662204209048827409390875068185451221615986611793178297374566384422328942740316474656671185585234837596964624811267394954033734579925860826730600583907638257262174570048671875785377634887649626458281464206458913803177703714487255292671901033317035043980095863776773439481755671469094888620001467960884275893633043490823379828090671532411729130770614328577225655768616027155954524694710726474918101780438178912431354463293674066187126130439028840915460145564072214427050524307940887488958834940301722698012725962868529406732635298673478937463569687571446464485667335906630524155473752824490722013928885864085869352173392515884363201171418328165688951879878872083557295874500780996640969533473253250122070312500 1009420987683246682049145458393151879148081327006087773160681058630585634313683234042921642831459732960125007422237311786405129720797169001918630617928492382727689091967086423244152398156263671905320815059019983280480762119573823639554885004140731350184032683043329161703986648673116888424395411696476129835513162759843971516674548011609814087833492288789213335839424635079426904429557932712007297411380675804495355199740778294960451175281430959948988032809290357585745871942036606237969839270407721552300735899911734818181041798359144235501343656302123905889183842200722910850014625383816374417784457028753419246807422146694290551364137543499527531034684977065193190224676164159957484128127478393600890971271155649446882307529449462890625000 25682668822120055655785904752077634047591023197193851042872599891097083979304906123896638373906689412885527781941581582498747756660114500547916226403366305483674545539784242996836981664137783501590322393175693256851072023841224452911212132766534213339107127412297351903034601009924618251994718977183082511394164470797107882741985697897429105286786786329303472268382590236592120015617198883562448299440027892040818862163773263854237376747757605370455476654186367197451602121248043317113431130078745773968369916921018324528932798681724806578222816457221509116130890611366127627269802274237705366707328744489411931748988810647033321314523173914531114573306733202085634534763619226233795389316744866604891317507508574635721743106842041015625000 644194285004082702191243978134010348738207737244781909687288748430508978274369831031609371127528653488170079476942925003534357604965045210946480318741472599870160557655172440334285567378242876778173575096705723472053243140349178252084281555325809714909108927130489774669333454202951770547319800541192617140375313819190722563049943711152297825722530778320656813877319259289639136802892171306580564859072915855399713804903514534019353161975295858361155515402681252578779175854300882422370034254918690123655042213755794452116359519004209520691490174154325358981666856567946313696306791441633467761368890442769839545704928699987539142665273918772370141344689531719827620902788015070801691581116256608841030839585073408670723438262939453125000 15920024430322365444464583661164153873570575880999469795385043752248889295743319335630674257799361953265762619127518185473928110469625434485233745495702322057324398513125460141459963008719872893759257656894785017921686409261230562712409766186508729779527595186310383429387735361915597035452474140744592762712089719291847485732572584102808851877218432269077883219842634216790008100486576964899668836322182226787272456584431152154526473697094868330011983290725180631199747695762270747718215257333226233993773113097959753123558707289195732350192656967438534275460279334752641704175892451029865301927831905987522060319500701052127473877607902500645362035149535307056869321842553993386321357715230029490627305932548551936633884906768798828125 387398002405322046311619697484131809827810030311560150948166265956498507642947447204540924596710722011566056119642812262002250647702413957026589115367848334138051734591760791628091506281325123885410906609943395964894704064452914056428068503576297008818188059936543404491064041638987159473133120235654171278076897639621483704433521716279956382200799568852203280854063348490929740966715100559717175099199092475778839652931797418760180797784292975450715138159070619748623312765456048744655260571430951013065376049597850276841602735302605932768385212127265857423845705760863395956865014060134710101586352162311146436666698903618320440930128461547628148038530442290464272580253228467591534929818572474680138384428573772311210632324218750000 9276992952961806078896960485761876723689169378073166625643266955096790241194702026749579430657470609523425775071974004463116157822149144055253757297232531006584396577871087316868358585782307122827354585089271990405561003886310142011767043224649085341369774879125913426481274979129081805322151438448197379900069203367746312156318029459701139715086111575482803708151596468216371856647343639322898001808418232999838113136878717299225896699305820822534447310696476261577118970450900139222724918578093439590388686006769421188842419241173602758441181075002080867195111899014009430779236552082287810388047969039251878931231024494662156879117889798346985060267693246469159344858946638459013184148686456675925171566632343456149101257324218750 218508201696965124559370909257071370978981831759081523560539581235056583318227460818686436018375621499431580314137461585589657411854970246329678577080502463907684581282689068600705731657250689349193379568565972921778234239064845846356862010511419978963209143219386767426534482028417458204955554288642299728484727866347156179686222575598406465125768929452231082551160334788787364170984869181231573430730742847185177393979922802969598775516305787015170180499183397268114556043795685969102735521242221122585432650529631115763460533973032944893957229576948407567006900441819984051737383638483302524384583403905413041015626272984088888421311968375013084991466430656913336433841422078609364890514066281923533097142353653907775878906250000 5059945020537761248936167123713514536756881801549727850275662870374538391650034049767755561071684880050461426935457906842391162678156245193240826801410328196413559772756494990183922840071370343168130899542880070115560117429737363421682039965329399870113313522272432902369228714773841396230480633493086850929629482138185894828998039707033834613995514339885473974063983006719131640003370793678131379970015081184744096081790782054563921947817574728948363222682969117068575075288687179344754557208289028694678964064379019366171502319375345216373241065418009855349644266581759712326854197009341778271125383933854549656523921205838058528283898316841771339771197443791603980526422102369668527604637531247533388523152098059654235839843750 115155294200137051433286449847360586300478315735593311981198472310499696203814377558149689432127141426879698541574897486072197932249116166425202058013271494271373072559035033674986444654176218931429922401251672707234007148670831530156908172444928894662853311605881566808893337349021968425860344507550516852942599646573268789921394265815491568616802054647163620430079346506110093774621047741690468779665432939552735226124263327712238870986671235607893763173065281221999884778430568378894648859920329120316167662205530337057202018749011267294101800717318293650348006339536808601185038208997296940932405436296244036674281519080258460581938239704098402819626231650525221746341619435491528643245029428499037749134004116058349609375000 2574899889193462669301191731235551717667090112008626400782555131782021802221785424800038597037542004925771052059500031989325872310400333059709825055187789676313236771407001712696480903804281497850346424398122495607068255690300964046917546709913152730906796539370820947479084139132725542097012374067158386262977918132839484515350835746714514375038334785369163601067827668842323557003311090052419904661913209449149260057025295699959405965285268434893427739893351730059016745484404852530188979703106078420092555381307637629400923544621873377128139702426888636540200031783962476095870533179241160392890662210773508854303957690492991753322262948879057771747928190543534318285618443745212417447798536329628404928371310234069824218750 56557098170908867151492639702394935419910131939979665436581346748724503057470917199064684069459621774168672918337702194853866567350310517513964964191982817961578160836651299361468455754452729354898209927158460203629700722650126219833225180115454235144269752060170580403324387180635026022864561620980439095761727828675781300730358783572224710154960940061068076059840004096257505721325871932790997969635629115624832437631229194705421722000727756403137088711130185183366294635741353417985650313859956750126615145173301413383470394210630187491501969768311331207670750321587633490555644512581332075979376436126397650539680284298397383796070854989438310802780952899294634013527501408273752414590518355907988734543323516845703125000 1220131502934032130751905729769666031225344648130252366302591430291731049858510907481207254035707188533288105530919968398426957780241618133049906830063902462090391149487020205450282724311291849203917503418591375148321768993864514888090707524871351149800728850920726592256221772748176842203765922647293345732581457548635344718129754219983164001066184236340169037802039686542143152501235684898239444349156732655718502932178561922530084860326101050154560354424646687660062390494711385532595659843836905264422323084691689313874001897114879433041661091409999799625483747397939820362201591410409211501850655135028998598348069236669251223600920323688527740308886358321247289602949259840181626957100746722062467597424983978271484375 25851622734255522668996877620511006305716936632247754080069901318883542007596873603622938636338494820565447807827543063369950147651430930495131999405310366713614892667639601834992640894619613115995047530645233235950915333156562349350590544831301062425568414896047223159294130118173703584281873709521736501457753066777150159750478886907237662912320536424150496286923523893718522425966633835020535774772541938144633583837934508967903719627819560378493146444722913015763570536559075835959595849362306098038974050890419410364331784579454808178993408726644696197341080085555360816023570331926830083240924379072199839318584579536081090139936517164027071017566690986735939937773856665131910759214406425599008798599243164062500000 537925191475127615622802590450655379487684313934556061045759204946440591715900361041271288950067853752622883296487900092163375379158443537633316010695154128006417851101221439700921327352765270287274488879180205228346145809437308708839562315973982250936727618763643556669744977734891947629023819414484154369839145135810362886629798301370937392115425901802779058925500089574281691617270863885885622263410532700187951699943177495216103383617908180254613179229981636529115643536873824047803689442946732283260244776634483478798451349325238974015340904187996322909717417695660039181412375083394888631645756993925626194870654080771547305904202926031745379040165043748505317966175989785604372173111187294125556945800781250000000 10993057630189520627549249464107487171063186188084713398687448914701931672219840255263743421344583054844724872452223004085383912411310639666670511723905073336317668647016137376761027118201453342483394005919134271292861753669969012789012397877086114467561269368556559293194316826274815116320427723946765165777998483151922590117476531340522440242601166177258665151044956894024604627291724717245341912800938129484675252074015226462644048480571028344102886829667680889873052974643980862212997061655514028001775457435499433453091643380616874855242027212751075374506436635837773144877576235909782157570605418529379890994939890341833111828627291813909075220038937899815459436566895262687992840255901683121919631958007812500000 220649038376323134164815634973792937573730345824867510254327967355664270000612503623347652374691487313241952373321813722810017689505550899707999418116675099801060492954451543747188595944513802493326314562956548068887548327165979147858934602908801536857237258932260487407608067833955657159045809221802654172544999854183641139669645776141962536331922161427157278772086262433386121218360422718099322233664757845243428394723366025702445765474480528608453914127376690287354732750605896700444143869749762449371872886665442192570464981237452209836723993819593080538924536247749781271354793064130819456553017443968493164193547710800271841696940943975933326518342483667155569805173181974211615852254908531904220581054687500000 4350190838102229003783827016567251701719353499279882374395062916496615411109069076213220349558464687090775114888687171574739771383606742620142934289662172476308142713090737096646050304145646700091188600634219106804816340084060792023803438059106813265938584159295647434773621574775120729940604587734487728550470607369104587890117154441472127290710760300059828951724603158427944164629381202736441055202083948952995409797096147380819208710783590182158896568734488601985488436500609713128048027333601589276187374405600665646255131109940142691707743868639509035444961822077823287099251234211063309334423361591987784777798613852780926376304435695628570636828945942868451118596545557082322375208605080842971801757812500000 84252299456792006471440091510783527979578318205395082632826409567000336306204246242790793442717034311361125026916066154850961366845492034029720950085266807321725877590589082202739529499341185296232864847153982496163727892999323921720239175107428423019624256006723569130983394506269154890339978333940698533203745884744401821007556863715474925469890923725938533952214198023563728796378026320387943887610092689941656815658324826860130052818540188382263215712867112459260091273941974151548236193054863579827799127871654774801070294269691447419405169781132663747972304258572895865488031286458324825129067577863715559361386665848081981054318245874842680490433213513248834284491417534468382655177265405654907226562500000 1603145918359546043957398992468861006074129437937368710835037802183463200733731741941312093641787013720693654353331525451518441797407132584190898547102767533845990777732411724581811913220593574232685028874734548847602533958365767564795348692205957317640160694998360784009753423551892087268718110818752677776806436630481152112807620517138824925098190829900182480343709717206617899041725756387549802369322310275347462484647943535675878658702726927448936913118227790362968410678785135778635885385762802021213865101944854233971459488525089605828823996416453751586154554926006211658440762931892092591123058355969027448418871554615753563489026688248963023294614109019197694533387377191502309869974851608276367187500000 29973469498798165992315261472731346396291298233134334608215192015624319240189749421389385689224779435102546121572347846678518240909635431924094633041421975565648863891613879664784684133433412888481270446307983341167783877667172295243934185375207402950855210954332699350525210149441695002225121500777157869964519151615729804985229357966638473677313758679997778269873481735189543361379221262407658641386499465020715266121116236152368871790665876096093216940164735422876148592291076410226039025427267329154971611214532123743905570086074377290956252935136901454269898734264867100970796945157729418299907487285321783783505323256922671164171585417944515349761327455480118368835729114607602241449058055877685546875000 550720170442930693891830474757425394800795089503706825878440825326631363996061338135265675666401415648197508318249789376576933600328388021399274932902737076745396312641018366512721087945703698351914159272557009431957209466457683974243282640187252304249769390276131183618165054358958034361758717781328537979574972804851924887520071968541321997310896347422821297187475140286956983833618913023580741703562554840410794468021917854833098276885225259548810362250919804564554863175967018984239765871455907912479405358880389757864548972816589384457215240443319034131068911306530234617291524617152288397765911009577014180143231069661359337449176549498724047781230674038135258774318003816006239503622055053710937500000 9945197292359376019742628301235042546148122018886447461047819242368987545133444142552174609561697269815375088225776915990428919423997949958839009853478761511673690785317942253820274870623258701063027642026419846267682220611643965028774296032144516527608748101508510397154804077680972869406412308335799947955027621584187619949070210047027148492799014858207731234522854785074769439068213379261831739833835411478635164318578270747525284042128254630591337661867147150571408056472277483097125669257885327612587784251926711921691630313601427594283018596263139477269173067137044579262171226800989905146052593070814623324005537587347448352668396446451828247634456423497892330054526155436178669333457946777343750000 176539837110640542526795729018316497598676035232769579046567839356546711134678722357676618959007967719579718549397763836285437933965800928692021248865477147311676826272815736235193080183976146884800259471113290453442147952760335647291297812792353644530616108258864311964410247243620693367924294420859729130866426114802028018269277811334018149556578700958982535028075663314209700189685192157306629553886380055611125706852287696067762206939285553936440568663333956784816626573572368169641183482224443702660460558210965163075983336435812691540148981309266872067412146622617287083540091203903760883167319492384347544513501297313264192176629638467055693704686541393306109526406544318888336420059204101562500000 3080891997316911345310486908896901660558374634454265354347929847035111017926970209152720916807823943252807810231928470276089132135877214220082708869563878542886717922721890973551259845823786351966849872740974591333119295869052956309895574836463407974520076348593806054154960792939766436763136059584010492571062479908725518498380900677890415775724157599753116749008379779324273777627035819771664135902472691395896314215282721111062917329313898468706776436909984736471150398499035027235065848719126516234595343922246668264863040138528445336564847076120340227188013471855515649600653381755878011553023337198117592154563130634700478193289998865875748796445461217749506310781271167797967791557312011718750000 52865283169846458122239404579921935167978580998142654907855696414607138943499643391938526983908853564096077000873495616500269354797576158390518764385320417183907809096810835026895250361810108333764995327452734827363602953831762027345586993705987688802376757430417872223521707247629955066453514452337685121458148797152992383498966879293516174143491197638524228663683440233930156774385157379977142336515300413652021356965218232442944553322488863538381251076631706306186739699547794883594904270555352448703768599951278481783647562137090563483340601661534225269839570422685112795296756537176296044322398532358424153746320718546950541710911624875106166851392985178703654014498169999569654464721679687500000 892028399380669490627191284619459158817696048705452161769457459470195036341492701521121867726661957907921910928163967530112499348373623630010794208590841030809693095473618694825582563939416266363274523551672216512663251754362534106386878036878363039568025122274230463454026744488892376092430180239273249245573040441617070382750031869015959447818012551845347251023958436092844500861662773722981748802187509377972697914771945143761921371240494633613758187035187958698140722031303875698432580723724771501230016043735429543241701819972433856198311954127096405386219539114841303254122960262786583106789980455472493255756759239534154913291548811828546406912801916555544323728099698200821876525878906250000 14803072318672216013947908465291021899489486359476920259656896041139978428635426329929064991021664608151393725071448500978187093668561694786367646886907361929418731124410412918052972848542422038860636608138880649338766932037902949867385125365589753787638337822924202901633298761565874019106647216036129655431937437452679697491524248924173933971788777164078867359148037255508108176829307510926903173121932636733215781583975882047997415692376301718080122223337730802820557579057333421937493696871028664924779925276710754346210556750464280870553313415593749207360551683633856533743597573289876273754876011137451347706107202631364880020396327870178423524293725987988068482081871479749679565429687500000 241622913748455222075986551359318310108041886070105093708356845160520860756483470829409984773520227401581457682949365556862365243126182611835711117961076313746420197359533022394994634751875776903245324966767135747376859424523670289760842463236687310813819032822456482372465155550842579217284745085291284631750047972329441423684400136642004877668095626216079686409424298250121461652696598085197539859371565721924562231919523963233661783880405294152532430996780107609191273489593264094277503617914866151717107588303344176559208897715794768007723641321808231578247813059249783195842839331093322125165519210454283679229343549296204606803874598129782511773434861002129991902620531618595123291015625000 3879557330324496436432088515125348413618141789567234473117508545756270313469015100767382103777266673818380845427934487547242265608629405859974456127643020861435322535838386296514797710069544907386188623220073054466764266085122727942797931713216947202358090191729894314558228822877865558078021516147522877266170355410687200002367273029864885156169192133769586434042118237600207232699267890077575795226956478786309134934937173023171791289348680467318553647825331326862739067723608084117117402699235429705472086599364401640118303490597374230706871591667078378103029392904447066334611171736643431342887507778869857325072427491132387154608418535676019663765989875514605955686420202255249023437500000 61280916424908573405509806420297965411082354818426789900886499922277333721413810465805079303050936498939887274601449869527845442367593914563543288809053763700772627195916386900656796516665883713335598936815282123813246377547201656011679702518878965468790619077896734147285844376442164509633315419050021217533975743183147811704017038538554516497956862166206302164931521471137024583301102957881372432615098908453096530460590423009402077580808912693315286666696623214232606488886399984676151601344870245161441327649873975192357429754343965445309334457436166517333250936382225976749359194545327598104339072706862162436299151651204828088052647249307346849489519513554114382714033126831054687500000 952368237035587245175555044235277337049024917365781064185477247786091957919140278691045643146340099944265043187433744902579374440022245733044523415234946048611085117726937278488315347903974208852366435198896669180894984099808725390637522382029287227914325607346996624719826772477412350144100038112065865877651599785377623275162087170697539249364879591607569107272028511736220803883073929999437134494631428738980978391183039254519870134358921810231733614408116873448228992353102374618100632008939047838335515846765023609514650739026339720744295012669810933778450967477473701145430458098713209652169346162868838052753795390138983774365401690652124105929132724668306764215230941772460937500000 14563135520982740477974099316653643860571045700908587139095335489302346065981881619728752955456084557805730538397136522100924303843309376819151435620298841768397908500633697095552621132616998066429403096924840890702690704182493224993331543705855526720213095963243459863913081375475044078856706802636269613035954000263103784075256647435681436564082100844501250350716527014449376394757864280419754903608794064859721981062976749938625705147980346767472043115692714881072869355611233983733082943959451910564501826252151311583744333964454923791279318555688462584537453599908486352356718039561582680004491769063161304133338319423182065203884217609829609951788143007433973252773284912109375000000 219131642878624873245195419484144235406169150768353243445836923725881220331450698347862600772895671293194505589427197884277871509894546004980659116752090350946336543457609934740095761062243265852721086850897781691950956054079717450928238963170313539328583995456141663778483138690715737507400883226932557879604959057959554734195651427766628469929727163162183710821732733786187502078897710957968377010379746176110865376256456126969188375827126433692968449309395829907602774401412913455998867090093056280816847370086983368291023852947610897813856250364094639524216880171091866285273220012526595413560989174566048976237823376362844301850825738577771550907868913782294839620590209960937500000 3244751446846845793830315748423876570619251665197952311727462261790732967258308250319244112754838815826995684192101673726672334490016970354788767218799502622001730476760043102562529848866736039001176754570438921926119697304066594840666551159755209513977691463265665583821805985159192619560944237052689839163610922775247990210415681081305723433906407766086223272799886152768050093144506390797966005472823563067402095468879872938487862549175574007321031688613048421249706757667269817635640310540317867103990059889622530826870684350869816405448707954959123596278467976087469311258961706093406515006539047959481055062292382310001951389080146123666814617081399774178862571716308593750000000 47283086474486757918092621911150783236827423574265972984626339753051157015445037013147001896714680142952901430391462227821418114582274628880135006546505679910396736055750834143913530509224027267390355931910508757432914032901604539975050167033470857433612772368570512344700452059368258047138113339969731616310665298543054341660736694488432010541205873234995070992254152399494920933926890305632868648413249700530792685691497943531621541266894267516194738637079490022472238623343480901638223446557188608029864087810768707710803471488622041579129140433562473594880216386441783272410596704312457866984953602721910799756346133044520156831901514654648011060089629609137773513793945312500000 678103666237474475627862003488669673802808718147283266291318036034028930611502642836430615271441129147334668710615999383803604763276807821935697524733669186107334694792753888375528840165026132641080967393211863962314833879801373757656328948585865697930917999714237645238881002581452126024620567071507918467695573464288009415053075343154284816677751657379852162094430382574916531120277107171822188778463874027134729771154917392858786104402380762613398020195536669835885730872674829713283264021590338782630588591416764511533173287400341260844570156010289693100201979796519589929929093658099712480696228078670167622261148108298530958157096688865284050962145556695759296417236328125000 9571191569620961909460519571670834275291764913871567389716037276314022494635193068886487906993576163058268438927975699180503914109155419781967646407123248421068832548070456129497586834152799993008018418493796755011776300706169507462254791104594421488887774532676134905638407015243406220816240771377023413431331316864260661590848050320181278052054197170408489677391203731067007933186824856587011555668420707302686013722020108161076700483219707504085522997899619390751523329030361192532682665651159533318038064825690810549377656233663126835133678478116618506959848316205563057305304679712919587883620795161895690680007146674183867243474593822227802775159943848848342895507812500000 132961279954509031964574454412332942963256289984634071417780213030230549118116661738419216048060878268652734332896125078407423557087502132574984744412079942707520992375081725166330493366156543406999075028316679126131202122488862520673995357975828611627093770927865708589025519470257345768938967744961106945893764061862002744782950968446813134121119017836621281927464452995332132681086540035335780090583765353204180596008574430683757549368767636440009004743466473791016608874995989746042104907581946599560505265094758056773105461116992183135428481350587401722187085989170992132420559662739944241692420616752250026023294140935364788516301337573111140955006703734397888183593750000 1817938073343904214612187010258943685957849113255201349617551595903581235611141882326925312490320038718961556777739613559861668285460358806151150915158150690218991292380293230732274403049039197008655480984290975483637355320675108969374922913862850556057275938875364493012921865046840002523599661488654096986723831838739029426658527627603184176092385808064286530149456697566029163524069316184621880488569466904530583300572464794599969213064362857181912188793573356772812130180486839862352238660177464391895408115002480472139140474401230734495861333477234673632987892316873826039873722156135839747472031834779840250501551048455844191570340839803066046442836523056030273437500000 24464084433460074069512137003817490482910834775424051703759061780206022448216334730665836601715341123952627619677324507935838580707159613282633764554911024285641815885679736762755504877366651624999245648146542961543436536852128658410369476544168915111741732181297590113113231440512873504864085095472183851265190639927971725591450527996131314885183237814476758656030190185282058246821889422637906101003231702699817268515850981363183068930316761761826239771180089288122655821778921423308042251429386029226402853470116639713994878152109652364299542972886050824890016127806087665286231008774508768382315657915952448999438105973434085319007103009880665922537446022033691406250000 324020039917257836117278783637612295891420874174831318106317954607597031901894398230563901628666499061395765655513636978007428449321799470697774551891896045106270703815108375395079729516486901590758953692059011661038299146791689984341702943528881765195951551998604140462120015440614322378867488752190570665389607027834810922077786225416490848246664494844245843497931151799015908045263548869488068760527061997065890936334541537004553447103543197644548565823493818065010569363029892637141714243634557870275513832601499440111176936362244734262888609799758426177932081822098317563369638524220979453812481459105573319816857832183654847257869846544053871184587478637695312500000 4223773089257042926470817013662693051197445385859652808674913462211747465217142999284294432234381563636998978146515278979967513261743438932840969815380451405630588098532649909578643328714195020025227694183541691845607751723333733893643687377163789725378944852758243699862666002861697058773290426483793838190293120579484265569974080486731867961374176929693880687942211358141843585325063926756415930913328516040217935057204766533039899654910716578508064289844265344910494021700108820734033194593777042756635546547330917288698712617764980247878167732556586588142313623078679629272107757441953131264102635022952100720301132804864255310128839937533484771847724914550781250000 54188057125088149585098751481700327803582823978219366047309385579386955098682550204081487992755434369388909803498051693635888957609186753349687459673504333002250221712202659667838786015504288752665030018653229389747435604791629277969686527897162082410939424128639859934856319618747796754555409513249578215434491613146578854446698949239256355446169226146441414403444087644554179398561304504610069842841807477191402793324132049351865456012477423187687443177010789730020674736241621990756613958782023052944752630629727350472034329636669420635092757808264601552770439779843170842586635774548716136349567266156245381373690996138631215117698047833982855081558227539062500000 684171596825592540455851320640614302534442383687006073169525798509516781029878910461416505087348603691019859451042432035794775481319953489140550412137114178465378783108218437254577909942618998714825833653737190479590797939367121527721955784677859430043334660591991115641087886359338545971921210527349000607234894189762068239688407401859908751742937078565506049922603148538518953905645496146398994717676580720023185383163002598804037860691410262431438936858726070581036068694665168370133464787904732401554860555582259198962704442887087091565107354402462283897877215078626082146981783838456876364887111911174004530826418791177034872674767029820941388607025146484375000 8500897353019188689311926482940403968075786203743949933993817493613931269702445091451781678423796995564611754786400372048442597376957810724983621825137854040538214807341732649203069713662039197572388404334982596147858438512755827109094723528107324371682026088712711759509373794607427989627146014816814804939278435711815188834506360811597029755340930146032668242098604012943666361535243112682539173744281875176119888102911240653920387504657596328942274577037321495356327135763905929464997934552475413798078834615582495706023007954268672802303484819732981950859523227569352435793573451515539316047974695927534720159420792567894764601987844798713922500610351562500000 103938921155820359153637677549643322353530593223850433841542407257643702264324493728280839526364788239344146584125152374999772948042802096570574679917575794386959578108457641509154014677264023535333556299878828359240184339526573064551081560862604025777302464015331053338167026766732731406009966397316920058194957678760541627306528099649432289092291162037598876803116222242367233273352301210303357890395467720521322355715116557153364960725441740203368351753546009093961013306844790719750314259063454288662733938617586106551964638628529206577648122846959427744036885367605815371180530485216978791137927809364448436557117061429522664184332825243473052978515625000000 1250478901198811600767643474131154046273142001057006198335056490301365449763739006975867741916560987660530491448458523401816174178836833215748638949884651510513570852384533453725432265814341725154457618738157297613413022094173525034281101931897945338186134555495287357685432371876957544005864123875735655012657755652512074665225773092529486822176433197799422439052499281045444048939442360757662947295787928816484131412250097938896675608487810443505562807652964760618479679250130269389297888861648696647401598085363828522279596683041127468962395857310745138714771741930041416340313541090597043160028063725650435318321324063006727556057740002870559692382812500000 14802187045294930198859233659504491682440824694377516383873412322977558151138396959003508339100556082045839227976584186267755289651609230198242987638847310306295635584039550579006197034163583467919435082130250276023729773354872553773152372387589431939282009602074012906903220656730154981845531230099916715106676831400646149967166885483688448122832541361136380770970074860021070658325575978238242852193120878560945345779623153489678411068352325276253393691500631732443619082833319064956898284177663524054376970888199190183235967008022174379829727345554198509171465030122020141660216976746947255895236378698180494933173134697312889329623430967330932617187500000 172380840492370372866021572926686615774850117230139312025050568828812751971027920336918712640481410455092949528635144791283988591179230135438635671040267266204326278403516082017046799906992290573241539274885718036618474223129882490495017254848648117878475102092444291082916448307088876190304312079815102363934942371057272460484938337503194294509520746668680815656101584502395337455188480131410001114542516212967388878451360884865309028432085175199321485215546166578717857164262793586208647471165028225101217216339390473228399180263793957037602472910673411588532803449627623368732118587840557772302602263161258339813075579627366096246987581253051757812500000 1974802026475194016270517047804134563542224948447604484170511932532165208503600693986711672736189180327855307153209737972317502106517091819329760796993288344122195147802576580999019664033071240897906338221069466432487222430307794317999312497301155973553004681513275818523823952868003003459688425109370905695501787401979957691175772365807717593742194445725821946761245279856624822733204816625349518596899231350954333793446264653288370975926923179461400369539177052338975318725422128643671648562504289670617910131385479325363726514251780277354229429382015578239884483137887776662830856786930447027441145440294131135905431051469349768012762069702148437500000 22252724877908511235937729327539410415069918245351799385464248814358596822559292759583251599111484026124889817727987655999786106657627962139701123559049665823229800102133962164444318872714481348118745119191260142753529364536974452773741152088533311283196210828790098668297334150298660022534391239259169053074895866627333759984146704120216122309542376440712934355945100529245490492120130535461056973555768472402287333011371938204617820018900995839916311923232749087582283623741959753725613349519803940063825728421342514550509535962583929387657696104779728865920896510948728017536598204424702525385171849009024319654415080549370031803846359252929687500000 246613783079048350255753031187317559671034816800016023493117535965944179329287230938356616466955356801470375581852100778004068999744124209946527788703794874906519733827198191247442519191876173110280833766637560349730515885378741274589197779837103799134955807626298617689967007017847964424480639409324316831137114566508717144523904175499238407743510277463917045099267931624325404151929510720673554110803382405877220192516144226157071640406441596825070289627110111979495152855022093986020443977724673824265793975521128545783146379332253765659303621543082477973162708509917689523878306955714145312729624970945075529416001813842740375548601150512695312500 2687642462687661400635167376442155568795449610982013679264915453642750578906756716048995841348659801446940374744980044379273458524902560771009557859194962812490046600986739661727420983638776403524199770603413969515967204265437343383444832009336840292454808329709431441060936472046465491276784260778991148276896006268129866036075658833937025934806052081567436930912340724217947922353530042318461802627043822903327356206424405710603311093230460815621171252664796305744858900626641692379260102397373730719088956249459465445789962205791115110810141874568388483661160983574180492161634351602263795105480104902229143704062153119593858718872070312500000000 28799666191017507031958131909644502086581853319846743992493571815712401868659185048958351054776718227799112447636982251925239251859080299068730283625809060706890745130640802602972945817524146324885664276030675192133272932358591797716556778765730845081063383937049758743657391664756632798027453886627599502293091977771903821072120180442883577027704716813531789126769406193282237084601139455261914625336526145382146086589212259632091664966694167434790282939700610400264665765998779111562378581427169036051513925718799861806834454250509193417715515800844465412224618568504980283033430242222168637036076844180898515190847319900058209896087646484375000 303391736188801941617200010407193117238260195318973622188138763830578707602479869580609401211577765537635622172087847991384120576242837154834598793877247789664435663398412834685631476917555069692749545170835744270950391016109127973383521327402066607144526300868035479632017005703629300717224932985621037576337405761082518176002597636312733562157227867184912961278016716477427832468781094386025403832672275876028642722330794059943214300159891536618243156206398634477795966839126001270258251287704843787107531786583033928063534973571916796039580295324863948385862848628053325415618640930921273422588187174131491019579698331654071807861328125000000 3141638025362364782067746088609082994753605806582051865436255649945258229678830881357303430745452338316578317163364855625565674560545031292520088602759059924971516927490551794097538312878045327160465390199722446071419481234516709159244578889351138539863331606727490145374913428468092264355657339946431748835636531596425124931636822699952286755739062532135060136896599140074706645203392856109379705998615238813745277258436760264620110136054289088111009976007291936741727762479013329043642155374553688834518693272959235044994456932408412394063588106913782399234278245756599107618300232911160026387314102291892226048730663023889064788818359375000 31972631951509291660686192629794763212120083676520323952539713519985944943768316780596921770926602575643538887604768417600125168337129325558697639644481810496910910451232196024795998933375316785696129934199678155749114738764836285069116952684679347146754341934159616093462653280116198169964430845738894229103169889491215246035649217188038282247050384771585612383886085544434884385121954616720695912667821483532571209096976986768247206913336593565415277986073696418013343785339244736365741542601319379985297512144071073459781725743053176105734639113422121435165957162637293525350583693370245814534963413322543601680081337690353393554687500000 319744544865902430985946297762477812585666403219246257742929517814633022366303714202936823684766825004449855546185964731463628023566745720485425491774895777256106153448102849353203015422305308569592324662876719309391086892063359557599011630110511455365478791633309438248788457182682516091424313261219851986549170795098235615418456639094109864178303177079896233857947985997230454637381372435634863308080792693402521718117446398807215113998532690457444269416579300630242749577259770667124648545116010270427339527231517667707912980237655158768052095398904066242551433783575043861209051339668195108704995544002258611726574599742889404296875000 3141689388561074855658111271819148849176498582621611237931463570966662953928938952978021922834170363796235634264550324563201229512448924988053615961009536710833339839827843334577322916667120157485014683240976188718146447419905130721926715968822103789044541588877382168668954373517286158410647331155065306222854457005362964612544188911417981897384120632604079816261694758754605707977757174090300160229112010611214574998521258537882460100247237413276173151147686056310853482919966035358313692496518908632790104061573334456167213579370111747983524789899645448767347249733910357527193110378034481694475843482905474957078695297241210937500000 30324475432123866967827932546945805283374953135467836631365745242188283075944318754460977920925139804147539939225923316091978653115476154090520620580814980129584291741569245587149659527297110209027966130381984218002571035236760246555893299170043258634286493616514192321317531683422400140610514928035697426480780088742498109829011420118217109322404524446317723668429608048856027737739307277203340533756247254814784659599731206230172746159507395390264868337452311718605002817347642550526115160821933696371590563997280131849749924786359544402339628698831222855954648575079610055926775086047040338316227447990058863069862127304077148437500 287495936535749191158905652489082533668241691494451968191468712938016594735559441226315649495814272094100132279039342783767173046229926134516660158845492878890590243841247485440340129968458155983627527099725248352506690470893110111716080078436246571016589159702015376134126710947208913146987367218888040619100507592300520097249584406021581644036568042392798021954353214036086351516497576132224823444311662754311322390882506435871011876102980584263336653918697367618912392310362967778079750793339706647657731405596248902385117174747410422823964673595107922623263286528684305194696039132025433548989212795277126133441925048828125000000 2676845226237024125321621742211124714601033471586660439994659107173959844277903597359044633251138537449566547574824582247071568007411148538146874646279711815480442848099544146182464592013490094558818767893818160737244716913676370849265661701136903737032607939186139652030850605078462450068035349621677930093238542437517495381174606473035230611878789679035793572081609898204362070630058388389197936329569362432333060120362646945305253433767310714317169986202166960437968433207539953311867727203982555465473559965371550310062462166800715520766475148846932207283503453436428170269383052578410220334603764058556407690048217773437500000 24474974353440188575737735813387837844509647621783002641952310332259360021148664453859765730893322921108558085870786922652011378165284245347942056811977400655625964674041887263197376273569351810068652356197706465038294979469981021707584893423139744196542166942383272173890391203398527510979096012590682523416047872473848481196483062816201707745686091290926558951868811914342191891198775601959502063015200506340168166816154675866348367318708422858718969711570777401919975725434151465919585437884748518460834330541062550045248718882599608487108579076774333722712848162347391476977411309268184425036452012136578559875488281250000000 219733522410530820575692052180984422472814735933197210343464485261765927126493164432087718201507724204706143930373967983641566549023397585422321429290934168459255424368336485856417742204735517673889701445636451197576966984166014323650979834431915684534808013784338302469029643912682413806394166904848432982800271823236169290334750838103220499655620546884475784898348295750019548384856383514697726979497933012948225184801414653963823891805018593867777754854007799366234942820938114611252190767319846024795679956113037260210972397050991982380606134449388751560380248482078887362767142046870993965512752765789628028869628906250000 1937006338117009872262839178234027284039663750958079886744979394578761340204121445864737124236874047240483753324520702969614867480627349024412319237265719425377417352099147297026160812701138172767602259293695910999808399178271359823323018514166052690527997389681633842418143344830711059204249347244811286346897572315737667183958271486841393044640703736878099439661346630414982737611098374933929264803769348887578169685659632502398061864304852231474793336147795372022128565811036441967270843464787573980319893806569683254246987315469579142579862841371235132389440266683165562961593808566362895362544804811477661132812500000000 16766218976310423542148035668392306580841176514791162303256563557043857171492391731345028947136561184417299802046135331525767810932542237335859290809840503220641613110686614794041360455425006359558566634081737155414320983432185630898117825939636440441423666497768797113084288006371874087182744973512432021024208257065641918229854737484896998349135118069412244042171719053623891288587725313698790665273810940493177132526586860010817035748303170721951994264259191088619547889780497960521524451006097643693195375127103731153509477034362612773030442450352601026917474656279106570277298571269852800469379872083663940429687500000 142510300855180040968147895181212871209105739333983722490243450229524269254133519432926765100252364678625727693732716347356070969339347932790952485046204149046993634505171741282415880464435728671242633584724804721026563919733575697531691117791427419937272466649888880756813628263425356243945160332485949611574739283157558617330870669878868995519834449092927499909519447494916386165048602264505993037187149564050325619224219943724442129451402914634378210161296459768127404418844500614781878394948476350900512889677417252135958212876924968390180031356593123354080086294797002390011275707593085826374590396881103515625000000 1189698835222829992435841704258079375706921571038408119457742720870249629637576498618716357883679609523821711595204420562704732979566515234520804598849336665884876752235964968858147354964431613763192000688967903381909708011296792921412780530542236120136341060991840089311325795634702854444677173877187845541048505367790077030755641852637742969654383766055200991069315346844921820022097766021174430584026080037926639214229927904674622831882829257281325845122506971176505955084773279941978728929960422783814014827623547083567747487026061382393886295994336075192589348168996832202232161179722425004001706838607788085937500 9757098679673133734304806282953859708975001279143436797210761682813158283546268531616905807291584168820747319918112776004756394775824590854665674216755812729197969679389560751844706553799728068082983321406820312820126339002738660872155719192751875581815548487348241925027136607425595393769306868256890044248722735688105795024948368904442955313887926881973188201671828717313529447686754775464083166088675394021421284419321697032007010764914275944004093162209587493853460211126273938707876872355322732223560393065452422542497979730133673561053293328042915626698929210797433392299282672865956556051969528198242187500000 78642143098621242871749848345403118164945929158109918485949231123916904471099500540240187146980363315547337913167107551885333838984164915672953733170254423793390917485195063558312448774273704686547008160262757692816879632598346919468292327337734912987964341895658839174521205987071712070712326495331301627903901203472262682480582882758668173635885324297338483035014121062967210753224574454227864863998541052288636488694001616028351863313515977012444723830773910318630660383084955964407709336060152182429273924119933913576782790577922556400530330640438288983072514455098002417177127654213109053671360015869140625000 623225800607788039651716708782661961920647202655806198932434710684374604829745112607473177711588091381360659790621736371212261585831027117868851197488028158183054391256204361717884389248127836444775314416541138180691417607660790813551286270804838548450662474733558136870939631638627840663157971233244973603123751909022357372712689493515382126170370663194750570006139648894527492989492123508682928046840205599752462440409676076078275716098145379045321171981694909892567364943653724437089091558921471435819530803954656828343825043834650738615479068279829563848825539715964305642614817770663648843765258789062500000 4858906773430020454068796208242602482499724295923172020278550913754193311327054810607344656199852452186633986316033195624869473501087625480110269415090489064276510102685884990177367453129633476705592409891870387743782055280340777996095725432299719163738067747241423952597274030687378918604148780042420783911915072921558793821763245888500036162738745252764942417808372859957083514365432817415264818175165029703427936831713861699783316194160545438926013671957202814699911353153845631869061526027704644356417133840393724396605765398935339348386413649418052627553099424330407263283859720104373991489410400390625000 37291980872986776929165009740324368250774512772223359093539972223741131698599417437215495525705986116622241243085911063454284896883694266507007179919992123129859544652316935651113217668082498338813018186640630714503281970085364493029539989508197947443738322587772746393659475483790017250046388993958273193924470526889549069429064575029259910977806738790565271424973942455076307943673028626725102559204647164541894575913532544109705370602579622445721773576285733187942735684093996200765164917360063411311142743040755076040673604490230548021622498638528773155656828586224094124190742149949073791503906250000000 281949129910258023408607491963772300546060656750559417364367556860683149708286281320689223303647741628147554217527373477335697214372462158103240370274243685851295617643961605653572983780439365540173239987943065594483803755709757212422990797822890419485277816410966316163451801504834242254532667319623534886783569607202049378153570813405784370038449625951122204667656861619334903012172509587253989224815327067590913876011380530058280909368587546154811538235628846016936217325179360311473457095789700208208911633845303644476228171201136903979757375270244234408589974194558891440465231426060199737548828125000 2101279299315208237737465424935397818629915202969442127788835181808431336865612003288126508117463408137863069608883435903426135690732429723379976087575446639914419463030328089578611259386967399848098062291443916283090581150928474127790495023713974466906564639800081028549078233078736856712603488619235122735211439183258393594277879173704809316876008504865926301881447211244631564473353249060477610918698854705155296922395692372071130046365111739023654476810989217067677620367829413396874204032713983368001467208237548356296711309513301740517045408148720064649139782630982153932563960552215576171875000000 15444691932233742528693561185703139642015126618039227737124179242509665310186087115340829695563699488925993681070335296839570326371783096728210014070246548994451880216546763550333298040311464083276711257778654892311794562632268621427089377508975469995937017161744744369318465945394476898418170887799603519474904504308261714186562607191012930864820539952954557057975123421181943460791564861191349395768747999047844753522814655675829718827639804566563057459132654317231710656958605170235631667970084548676007943616928573278699196674265901724243816366218620694545499150152068068564403802156448364257812500 111990559468668416685363207027260631288389202380416362833032567589917820915978610468064747581632472187727197061336309004788419032015519770688542666749808950670609931502913930292320879340395689042834821659693051191306149561411836075350364783963132367611529721778731319655124425791516707273069673940290597141560323449653174175797213161285314609911468127388646443161209364031116837873488047733887522309744189880810945759918673132613431168428253103240910130840611180563859154769197138805542165494523500833517922477080357329022901882601603161627450458021082197596074436773960769642144441604614257812500000 801064621085848769912766523766602152534399279657491204791991813772737940601378889574919817432572996052437327419987432135241399598609205615508456833254064814148403739299353076284167374094570688026080338316675052765544094287107668624631997301840029041601512008341817241770805842888153640062262840538378837060756875598310241266863099344740198123239266901820028946226702324433866737640939539048651525346459964788852003124423859588958904673933561136461820977755825823516694749309606555410564710433208531609573947676332909557191549307544471882823084742629438093075577853596769273281097412109375000000000 5649750870916440160783690977266309144402682197656170381362900755896089579774063297264301227578417178060043184384995417792831622893425612471231285763600744432495299151128769421593751330893126193775999707082135586521021809430488835657056173152622887682889812191516509489172029945264767825678604986392367199274190871991133026803512870201244122782081274514178469163508029044194033667669425565984770685954292139459938188198923304275615444604846515202791431127186497537849275686208659485293011460743592396490976920691394194362775409877652846192591327425473052281645891525840852409601211547851562500000 39251001384416989160641917198361074391063059408233871227505622587089892094909757183702560509602114501677714377361535563095068013225068921067596613077381288761409865293807602558141705721706059474032045043453179941784264006585626194851566198892017521842943823339891628574911957161732449354530624319079773084162948245162731498382830133337285025501510815057135494311516911858468504407730036665852496203675958507357673176139106173607738460966564305616728253622064191618083267868463399081627367963344123219488208751993755290075518914323527468928665422245177785143255277944263070821762084960937500000 268231895707419800129251882387812965802057310377520946749506435607403362837485545475004145505267207350870241367428785773126676769844230938076766146518287053783429089548532742071483772868729411716442703840146708512217727903520458328497602399726506845151000411924087843247561667299524606815388196499831548444706218219559174176742471845617714056710107724675519878636713158868859414853950001076075556344241652587518765248514649669973408296981052462560444186044583195486168994313686137486482646286179550995903749897942976967319557624400091996377251072486425087504358089063316583633422851562500000 1799745300858843585745974616309731038002698939604966335544102274195713436095967197470790099937330634166239768428929093752314904605694533169070967707284803630195188674465023827674529581954757710999934679488798044604101674903019834129351325616950763880350639430608066627977105096503443661371180329847877252642582429365771871962296623608548028830315194941121483300242158599817422826517306605707549819972670340123328335979855082185618089880576764793361750804026858948864167179544420243874821396550778136160611397671023806037542826479310995937152626439337055330724979285150766372680664062500000 11831448184100623228172624207536004561507303628061000669297283364747985455595316013147259100473023164330199771265196657653240694288793772620553017667759477047171744073383161425749414099469004545695859220072946956084051203854785920873456445788536339193479804975188312527939759021274934606534178356640738345979175033083165206292140600460843971764309360071854757316923828463883820106767832492654826030354333402479506914680311885869390039523975981416231779340497748086826901352513912951343177896942270863815722753213830762487908509217418290130393460080071577067428734153509140014648437500000 76040766545453339451584009120866892842093826724793534823099964744129308859314269186649455656197744665701639943531864830083452848933621907789006952921500840624813224007903503509033124310614501012770475711805602673398635325437454885359350846732449715096625779314952164563514386662435845842812322355020039242702662588408693763290742383866851394954864843029914439277108766638291218212592681886537461549910258136017106846948791362544954810053689565347405099574000955151680795571692732763182792968905561771191276310821710588683503433008880291661159278593373755938955582678318023681640625000 476852248481772740211400670623263814539164581508091375737341964373120139616736782049654723844403636415505962018189709333483593976817486460380623790031917161072064217803990831871954726983351647604387928214314053082091025173411091631006143757729254817011367142922984911953448523800313936133545608147052102911019045439575011014092787707026361364868453091524074656951895465328829753144030214736495289893716715409393408962843344961427868486083932171655403058247923562631682061192123655588292625188356714668571614234036927074219441890784042161616218535868938488420099020004272460937500000 2913771830169034633344968887036664299519579867993468369083654532406757229347331671625118129525205939332392164226860675779616370420225101841943635325535165713579581629530926107085414094254678308452324008724977968673907018609094147097806733115989818685743556817061115456416962432701007320010580062563571314157201456375929341060303502010972687920934513591296809594356972226052990554728935647112477475746378248297608955300072339297742238303147205610940202834415906006286061572550098056946077350968720716161518481037572261150513010342580225500719315334663406247273087501525878906250000 17344368668768761977312172193327532840275153454013769049042650217016411005707531880380236840853270892836847375458879616584858489563189760474141682549488547030638524829449566704951267614811711220541298772119231733153480614825133698937663100406365324683903757228410774620303329040141051750309945527059871949675374582541951779941666907784593844534216211928535865285751839081487667748652195380896500654842653300652345067903165912726579125512457503472665195758223517586224419853294364292117880439477496874424423977268765721209203260636064897193264755514974240213632583618164062500000 100739202330958797466874350277968551743286782464802223806498984732726764357650853884432648024715436627371571031860024555405202159456258547073433817370687314033958923481704311529571658100916160141813077540059292809732210124254675832143274564111557395650459534963642207715368693340714503068538447243699076909405886205426369071319170946735907497021447500328981697962015976698005693973763634355045832581874830423236494920292700516264303852272272155289458722055950226007292400208821467125274824548702572832708400072524328151396810364414172167535355129075469449162483215332031250000 573426299248807922072297294998399345302190760728698859355827521855506729074165277173228210627836025836172459824595488454365601046661124979861911237340819608147123389072520847895786855074800395379039598289776652771743143677638365368097484476479095252894631913256628028229382152312398852622541298860845213993652469476208674393298714267814448379656051961305242986951182463745444668898558315661579933326807809544372731941304516901712259084841038441447148225921836376894065688687873608822759018661423742409567966941004589515158641668118866263625932333525270223617553710937500000 3224221603794890261500374377577658040239256479586670296792163451343755901718169009382808503756820462954506234882271527719626670967025253185004798848988624459252191815794835693850331544582442267754948082590674804574481982158025445427501208112472986356872508338136511898054344194097785395482407663904971783577659633799463014529438215262926615255998944366249550104284251664828546364943309250359204600675983895478713689393289073750609530747201154305280133244290502980440327027960117696262017775030697898718957778700359780314001504827881028347746905637905001640319824218750000 18110432717149630379756711414234607752252083677208115732989015550125328350661078112990367243792530583811322343190788004859480307571994952083611630412143731595275202543011963542406471917442579953893859832401764011607651902842437059310595212452840196748292036380792864985125286160348553438985748457832010234135500853423432790605534356870148909623702421455945837152854099298355806456590125941248589058045708949712990175493684236728227211667759857004694611134825311092428875306876444052333397926902563311740361853247814821006502622458000928418186958879232406616210937500000 102884537484594312001598035120036572839653477585939538772182503924982419585322423974032573654148985534763996545965098185994725047367178690069455673996045554760911210639311515959727199548223281447299575212872209340970292699317490554729584960168468329013890727394297554817644903540909986627926154633361210422324268688966428483851219369301480826855758002435140460356085009562395569380830644258318388513532563646631120620016522819059256973654691013243197356870002767631947592204586997210437827326677738989604603250174896884243207206832693145770463161170482635498046875000 596252688329599129969627536669051676137592947041684857238602572707410916282960944774644143993460518950452709569723570091873686001962317564282333157167818877225197100853683136515975663591258243376643306563548082305614386735538976277243109708539929186047186528167152924988608599295386943375362324960134149758863672974928161631795737723867571547253866606805593629426126477995963796559149957553138764113589915185792238985945484384480303921987980362545051242976626112242845639231641500663027453721866348857540600763528970598009726344912451168056577444076538085937500000 3524232756266019927829807415431592563131807139431008357930068171430143136737256515597448114935975908330160959296342304410560196096557249791861217425281588296629034645700743851719516968825332397197883722214269640055415438140278177888523834126755909363686446111184625202671828519319302485085410558043401546086113651304129395991560660204864650638647460287768705315789866063252559934178562235529718123424167747921966753262611741553087338022509268882605493499623646660095449040526191271168184161180086869809450834266004431299945665045925125014036893844604492187500000 21023874263027260666304420765017519977329895439648523637940539787273452116868022271536881188255212354658187923557240593390343876832347613154542535566919372867334007132254013127506118345776809726131724226116757942395456923654359041855421054434559546657005205028675601542404899674713914417089047515506270422402466846415011782025202817933274729913425677215986596582970004968049740136512304699654087988225314350362449588495049735414714710605961145673764589580174798964690138023503902786402958786125116834846076651949122598983521470472624059766530990600585937500000 124463185297865121334219051708807044786272733774303120688452210065668378263857381718861875928515799363901205743228484960036095288307319766531831503426187242830337444731999454410066614824250516847213830552768957691050549216000248100173725030432234869018579020291004773715215701342322436733213241999651076924061005991179094547423044038155838163269429300818111631232268137718643360947875699725144248480619340976348754454735015862145707645613594528392645831208847682803014794097239210954060368453101196242083253300572676103286084980936720967292785644531250000000 718543645755920389698342659698380469389905500056337416327124770746664145413094075447368196873507821450823403533760663410656511732122185201867865517877338609888816778286993577955084884967267459926885190960982387827412328268942330543847835212561733654551607181095908474264722931338794612307702250667214399845756256152039922477621512210313743682598488148825370628883634279124783546562848688192769869716677063395997059859607909936525942329647780475154833126707631718283694996282336702131129143647096391270559458033101440932455261645372956991195678710937500000 3990967461663553724681452588243582035826253900548639614340371060904819024414969303898661438873401387636719548742284220244552533947186753411959415112568015693981505933887777659337163151314688211429470061768987411527878128018137678661201396940956159741455795042014953160627481156867070563132053527495119124987000828419710253782882561463382978909680436933012715960296919915510921856246866166392918777797557756689744079884694436560231863059605689877151175091450861549898505312975499443926351060623928353258667647840418624127778457477688789367675781250000000 21188337728339966893501080950593683040299118563113706275328738416690822138133125739841012174214702250345514332665324523349738041652845521445225870045478291433335723983988946043877564631600118349487984015565718696215561157060681323400688063524360283376979460309131979818566675557233476891464432042651468528882949497999395545810504216100082997067017115846932648801149164926834539535491588522934268073632906272865342134375308714206684419438715838639182215630345701620848382048923990824518881533591791665679677364453326049442694056779146194458007812500000 107935172880327009116426576074348319363758904478058278203239033975638017519906473930686211264089446326209323404375852996080401940398254424504536448562575797612837619680436527453633810907577906720614448198963253471066311275759518413154077278578203713659229954017401055209046325716559246302688524759106843716163448359340242287644276560559980027203770706467560112933511211878139073373272889452932394766836629930397968646533488190622910989009049927327247726296463693757561645293863170601597497403668180510224149093456702530602342449128627777099609375000 537428948010796537369795895598683613295916508855287386523359260442065227256126329327538420563021512663581275950792018292601467565701660301114147862727168835790556875228265559225773461076951427593769274182935757771592793160460183947797784691035728336182758058866036628075764267168860669263077788549889564409724631883244402219367903441687469540508290476827815899760337421683717155271708961763643273719504154331483727275798707271233528178023552707912685796603726127774718572281437625772976426140186431788109411300524698162917047739028930664062500000 2708015918568374750052631475041092659242728565324950477691722986079887554067395927178336179418114857509825299436194772582077402741987920201593356389527726364362294508281109239773063577686808347551641381781905623924764116675014510814282393097680072134037510860955544939549560663655597502269681967947506453554638371107593785221465566262376468690816579347912423284545988049796514676624323213556716154381118101548907804740764754856908851997513197044680490507924644722474154279415636428293780866775306058816252807730506901862099766731262207031250000 14334773267521759613874008814719817778891910643399197550263859459201019024928236607930753407407261322290622852269311405511508523340716248642043644334678363930700927643556833509477453596886845511976160778086085451956169584088955580657461260326812773585934267783472689735038592795642588976533031093521550754725466625886266707048699969640510327199343099457599373379967858454015483485771223614120545244953226195015661907555461036369858959066728968447780167245695725595257611503039997491125622813997169541222476141228980850428342819213867187500000 80399722598293359594442009126464734523291302246100621694812830095566298524072618942516340783984293072969854289831568212125317861939843661027187220981401324702185697502778198483463689373894916975480890332170193663154588456190925282531034859012833840110331818016157418394506635801202028536677100361309065480419159133826533358946070506967669738168297991545460042379292089235846638893209537010056374557047914315476154496776520228393517079577808434525338691672815757582464141473739889093080831708590036632777753311529522761702537536621093750000 460519868607863895954472023866512893889540042131120021543255993418229990975157025246958344719086646672568095417578810604221800170666279047310665052274340355694634163460598581867195076389141531421949427567068895993493558854550860460766103499685121841837291110384871415684037160098134353607975532260149153147914245556645935517615864899156892752282028588156469500173084085034193900592251445967279238138889857353017381124355064868877036437959542728144954455457379260800926139971352478227652465104374757132177364837843924760818481445312500000 2531805691150533341257932442681596261091878934118838460376210023466679438034983516992702554921702656509501148696876506901896875411060978851382607258253993344906133116176621308795562740444419682069818101628958611905466260155286327394877378876739029404789739627559760241253414862395434726500437710696452013252578462067127840177479714443272490272703038231731062797768588386648229076568335888441040059569454870735864467946515943938391572378503960386277704553694982613253651127816998764031409347927126241017958818702027201652526855468750000 12509144387692724621024656585605238135601686290139070482930260834001517236250141443530309616664770008267394987109474651275485491234590235205636433854995751051610778879804926416506642992978794388080059006674332682533019834651954852001009494905317529080940374214460472363757189976035988186615474870327899127723863090204494682406882813789351313256172587463524916180306294131000313881037399203920649809059019002995476626118068996349182538762710423101950515783957058541653712065208257899417369080063977548888942692428827285766601562500000 51272134155996506456845115600814656796300613503428429869873928035239025241932634559716689460871248408045910568801625410419289321487117180262806752089846616349487175639440818802060061281416742375635455123397435065984403220550431820161920466440734443150807343881411668026263972050470441367498363665915163345005703105507453359148027905470382888002235240029991072803386033666765243864108920928417051484871817858496324691965428633744624999020079583976283978040667610726681672462203913953377072687533910766433109529316425323486328125000 145926069356494401809336711222169935526316173967905923514831048560220638884232505582245289212967690014195571550112813308792012850102706772143691659460082456618557033628161174164834820167102611727147149529302140653684410326008224443487345606930733084158049142479329316777645211092412678055228733292215098383217573788263166805995667069972763189568035270154012384923019312724038942139643760636458178187920977871818688543189044290027449807286986607652072444989294178631492830439712285895553778303224135015625506639480590820312500000 41297912433751940916101759131971867878865758741392173414755864787954288914237386970625488288305485090248148429845624966030508623970493115268230111887492590476349145904032342594633468766130888965871376303596398602815049052525615059480750039685169977580711207507818827041244208248884229003487007972444714771008093705538489606850488772781627827707786747686436195654527398209198555848507480646988535140324409150670257104136891337221188991845250328846247636215331036477922081802285729501544864206152851693332195281982421875000000 -2638502863238856346689388487939730634252503494833818423763652074890031973576116027444694023736599588744355788808607745060117396211112712324781239642450121665779183952346678087570334428661995848035732209143338082305445823154748076870177277453436425407501650319469743953952105287409510594431380073565402988676935552741965998115712551955977575862716136099681814810308866550679811588165739587265245796616552952663098625619565439779359731787303949216321029849779681322875155511373853473022776938705646898597478866577148437500000 -17599182729316317699459971933751088117199938760253636955984765112949555392421092580608340756129414090272988787652171281774208200405539484239003164588411279366402241029387252213102676478924907370196557346605177025435101766414174104246418174077889933055703633030324721230287011357243112686263798538667748497135109256084508887191576276269217320504136120209444983497034028123402462107426897749301943946511544094664760761450200755391575673045465146246110318629538566445619686558991118241479512107616756111383438110351562500000 -43710349937793089224307365300236319199191949961233153820735993976497951242351586273757700525367839415219089881821590003569509767573727835435577104846609626979922533458703298494069856797782652375835483574142289762845164948037005179103309478809717080652416157578855756982746409148944834000756136891526795110450275709797018566645371672566964024035464913143916086850810618790286142048198002914206020706431140014190297909830365268027530234709596831316660655265804424898138204943348616993148425535764545202255249023437500000 258561314517551772972259580782196096555878898755443160823151608304824987286253183206592917627285262772380667412827193732084816049714931730620307352041779893783942524201413122065488455694654426046135611608220517778032370505831331855316178292247105159716579911956371890352874474869537290283636405940252781440207746421595661186319973914607796408522093156792255559210655807788118477198359371363133803377172754511175569961906046592003440074915645466470411905954020477308959776591157364578066335525363683700561523437500000 3754781807431887186739811090128127740163503739175730438881573753457052840694999537298311461869369394140637808856458807445393107008659857383616618179817672009498281229086615119571144021619143550610832736006454492292496963038156054841171766786435952505254078189175847586659812455349926172292192275077771010316334950499716059703507053026198539558252587459566158939540028699595239598261907708718127902547771498499561148060738270403624337231644558869869443909464508010145802202606191144695912953466176986694335937500000 23751079042714997188810942765612836143434975499504542257120393712946930256055045430724858670800047478398258546928248175444195272635499847992352922670646533987997952206861433834253898660865709170487100202746712042945212581847744429309828632178639672727746025477772960350934744633313642055446254048259139564414475610487941926815538590796252052527322636854089963467467487054430981562544545406162051108444547471152820806111160384296023763957863166256907481853346291497658783822832795351587265031412243843078613281250 80373902992315456262968198286327989753142419534846312999756927714993823558278962504327634906848540168740173170411273308232774899971285471842471373167788745939713985916529740283441390827677568488681644369850563252742240300810212295513961759470131113169608738411623464748678021098993286063623187748162844626819261858792999584981725104223833608947168502200362180840766182859616798446726407593363482852401358742378808327813026769692251764970820395481909997856176370136307984815005056589143350720405578613281250000 -89012462766728418329512629806839216921006711681318144098527047311503082061172355829600867892664296891584093727477311160870430341627040455216646148403262545384214935386098270782174383724672674763686831119537604041202489115074865145980070515717396726837144334110496035308887833830074204053893633322879572972456627048630783378527530661766252972389087995926427603802944016924657545520771606449123675050046187905564985541809977837684350183239698284312432179516843850242829860874849146057385951280593872070312500 -3468086246967210936346771763064163521017373200774523718339517136798369082098812097439016751602187611423495879432624346018372674852547805512461304505115973721083746724021167188868071856899617955314144210343098038893733152656702396346124003716051480937853217598673947017737505039658106609066171050134533514524856935083246728416402908815277424636728811676679027879794422641936941426127529366800429935044071029820784239769862295193420518079450692038422108514353825112208618008935445686802268028259277343750000 -28335107250872090310180425033877317686845933178982897925194139188881036910130731810533233186923972557580334264975148987760865015113024418857887609458339719476624783000599713956225812849149410365052157621519326640462707438964990310444085942349785471200849201124287087977287206605878844325094296334127290931845465481300235605822694513817249299505786818775056855328316021002849062904408446459656731098918881682962505873025226301775761766293817474278998406768935187233227068759333633352071046829223632812500 -147881219769737523104674702284140910956845929262130664122963857037708930416652921780026890354390510798430880610431628620612055610993632239197133643260386878053409763641419082437558627510756930086308019369370184642765075218101872776648388154527938590829075900942919284174744407850816756984141854819076871960736018770873864901350297560576406082096852667263446340105817759695849753886243346126048875111288434920095536152177395490622482992158350201233349776892139759709721147373784333467483520507812500000 -498486821501140775776348020847004078639663366108503377851603815526519339784790174474736518112719295194070234881967512571413266672502017558254700468133848561877271316956785416909239310022113184302005232268041728489404222320930103156824308895943588545279481512541969415987348852930455941291648922262272670987978030859860528365032312426509206306858502914239724760889077349856948255008884879817403307923782979651662801876112268397979792818784333882183117646075959372709007766388822346925735473632812500 -429318509675151534963577074511119667159485370433645121497579309216516066600254835006505866321840420570720077120886573641487687654761180120946457298047577005727611272639154367836660915424325326793119511950241746680662748060118010943076152352248046779977590457232645369681672079041557542334004318567606030229733901524707987765151028921291059015006382688736729222419905973912843723845661971594966134751436857914118328136795606122542951381653227031938695884560885929204232525080442428588867187500000 7712617889929561019037079595433705810166668386581144212574318410217581957294102762003138031568845103927246811126609407885709676700852673111327403605685250216240778552280202278726909008421929300705800449244852926770479319289299189546128435154184395505461878384730482390184254575790796765993450695458377161472179325741116724610830412359111893009657076423094541078321795173086836364778354071610184384111000669112849782076700122496231177548907016540581790473019019316325284307822585105895996093750 66098309231736592770378935337323240618295971451614786106769409902267935142376683721136200921604092799267597424835375829239641554057469827257320351435157809813596303482553486520203292422679370608821610021262390482054648626338111363858585443151711253098803891932168852331526956073209194010269530069169706367365894832326367360135996528662510069540782248609687033034239681811364747610079644459721155567278492600497245792870374845411617745148223911381621387128859623771859332919120788574218750000 323005759493038298959313167897054172387116104459313981635527415738754330256401895364927579083411925386347242260146334281548456643600506147229246443013629878152271791251298203388822095144899162019181916309289640246308697082577384413148195779220199468863600031722639401063059080180279122600059169469666152479442774197340473795059861435578974296256261548197532920915570131170475167749153400624020015486366271025537898208211744895623314016277279232813857134942736593075096607208251953125000000 980267239949135377296129448501394463682180019659417403999731039981315676711915496018139177539175184918800139957288563329173716960536754081519822573057554332503692241557885101130971690155512409773364861530438331696174703397347903490728159661495988671059238736813150015433906184467273306510771771712367640972327498510556430423999516595635756972337370712262224829865134413537803048714254025504006942261460107807574399488832394134276707209097465392511061565983254695311188697814941406250000 1554534827093013002216562574488474929921881065400049487854791615566971056342161950575514886955928467266776127818995831129800373942294394796513081174944850600499062466634800988141235738407240486824719291510455297937598390551774543329182465722693625518929681194809033603754909606037262719571572768614459677361487491377344100707922301550127112211508999333089773055142602649468000133761553564780035417738662975128720265887061629276258985273419070682887621615009265951812267303466796875000 -6680498499240934891700882717156156898673974616203458598993159652411457299145567981425794570109301070144454813149051520095254726960426338170544913439521765709092232128468995960694167189050200060012237944691565405499326746593479389915216399520319016107061725320843208203672693478142456229616181833744546744743273216019911449229543483292097243035788418364303340668591778338822690402358990237007590283072674143938829128954575342453963484072240741618031734105898067355155944824218750000 -56590607812332335742228276829466211466606398964215062775734017918896878789814865885878628837494284200632053173834149667444844474300557069705105602553903278529196195363782357323545654259816479544413806570644059826550873998930071249922010154755012049225120226741344292138946549569153301840078778010031676790723269981247817232920240000103554422089976110381887527816163814421447463555388517841545548955007902665656397272634103369813525540379939293700317648472264409065246582031250000 -135630561789554579258735481702076724427615360092282194329781872668064277936361569359437217018186069288932975841356536078076807601431027187789929068609595587569532951429744073013553916879315903409574604544402420116234008254562690816190626741271406000123873910395690265284209457910883737109368932877345634392646736115798340299841580119326786211166898593250842841570265091207278120453840318432444586646719765690693308833386455160172024900222531584859098074957728385925292968750000 -1547178765012802296311862996550678525198015564993192927708597198366560206356020908316347411342731866943162573701659869768504642331278586264783571905196837021679943514154678170328046035954751952082793353615131182553255375289884960870749978451445461133327105011549384437779818125547313935009372682407113227525390974265585562606902253510876799857412383372842248727707663967619780949549124816083599535787729027146011821218277614977889980810155101664804533356800675392150878906250 2150095731134513811177835268872998055959985877637907815495517677109321459502701842595411647672435821347169846996515665348717351329648660793671870659575919286276064643173240201377497784331689061755256763050045978545602320092373663557009583717509361549777084153544584403871919527634343950276234413167743993836169232855118504721226505547522526428855277276970050346543759695289570058221676925032876806719929568972548536348178929190899655310431626276113092899322509765625000000 -24211094042562547438545080906821050062604172021159163404796269459057442529851559908443538226732226056585004818952638841552259723975605792704882710801790890176567365513050171876764261201469549914368730820716152551713796582358694827375116476629058986605471566085121861314781800731408141732846259041859597356131543815874148002587293098034619786366347743995807872041808837447717259272237571936046357653807500659902768816507789958938218211059734130685683339834213256835937500 -164577250556195042960104965544032779435423193144809184997651182439365281685949365172779866247766401158455861112367440282419740114420351787710010943813451656257556169563181019144484245954074895480272819355124064145743219539533530339485315893603193331125789094602906785755771954675706362812511731991672338148279652709917158658494423929682828800594995891141777370248308330076258149055001850084415187078901645418019837740640672063552329973390442319214344024658203125000000 1867189154619726783407736274010497803925975508158647330565305973571811901049144730045158051120089248473305853939619757794267044748944603989328482916224738613645109015120339716725874981059319603735186370887921200244980162030276577739107284214703416043966247320957183289087679593169639805239033466942795837505601652452968792243791186614295960765465880722766649615245268434029011341455005176916163470078873693550008871335562244536676601569524791557341814041137695312500 -15716102701038081456743939152116111486771146981352822393903456494116604269215701411444834396252920609142467891525928725737028630144467347249121837909278319110025385164544228110557767324623781036810761237389680159220802581945996351414688613362698929579424523542404811177543194015855685847389832952127988560841485949593945461647371381816658410945627531251308546621700654326587079448826448479717174756118378545789461667213718354396689846907975152134895324707031250000 91115575349149898725183846022984842550390330903755511936461345459839350416998026528645833496437838719892200194101999050091171051110939351551897061021517192929938026498353807438154663107361627859835696197723585368325740235144119769695644765191194109858854342771606423588126984470544979285882400806221221204386961626372944136348139307769769044850776906677112706726017402095927603314606395441565890960174583933863847742210678726237915725505445152521133422851562500 -128209319651792617948042265274126911524466048150289970517214915137741763270372103576757350209365303466369192452420370127563139418641444995428610921343898834981468364902805912104999350187578798061784382320530828703776753053462095600267941103804913012096154736654518381539635288448794211433075365555405730251581658925522897385466387732408706417514952515163316769896592657754188767320946951175915035548009897217145184808440028234599594725295901298522949218750000 -2189446330674351467698831798241256308841858835931455197824846747124777251646606568197168038413715785937055632865818904308162329023002394742763636294579848822876623447628215935893125255773632527191825886889775699954823810047175244469110171957599393011959378753728621627331792829224294414063882894311441132041413591312790331434411054313992382555021972073552063625686640304907258075176784628636787145253313271314065833680895245549891114933416247367858886718750 29853855424808127549430722847299391102413971682120323932691163441412881617144388461473737280790178179907671964386958731284499040349331426489794012648116040232284725804202110682513189568445981018796956346542499135259178936595910515163187231681677202368064525302627761247947205271629516635820454292506360136457644832108468702002107616783406957743317306700335595967120438190048167578864240823685631794938930298668328111588721185398753732442855834960937500000 -202781602492047327236490414722612507309363814747253005889416830474430487319943255708232128689903654315704122996653328721611195670504867696180571201002717874360457747438897951309765640787126136851508702521544178598149757012090918030442617106612777298102675459806669231644495038521323517143027660809625845790170041853021150979247697237238676838843032320899917753020086008296836324250615895806772487216612611479749084253398905275389552116394042968750000000 769500696337295988413991801300328862372123723268375728743359180003334072749550816638936356865869785021444212470667400272587199879531986759819223170383348681889294609602905974196201058601072329624115287900062795157150116723453228803902747331049897561560452169897520209491653997027963814767848012525634132178642789890890418378600200735165546756717957285033315681078968514218520949353740506596158973001166585942156572741623676847666501998901367187500000 314081457452310956539892649940984217228802121257353294801522122200239699347569677627917733283292393225885481238204765334606910970656916356830243633832928566638723648958854674752621490803408561079360186265064882439398588722439010724976901804121979220263303336065152455445151074288010453312840984836756909900591129255983618615730748801661209545931210921945943072368584567077496137810656378734126604774113539209068335367192048579454421997070312500000 -29508825400545642942458972519793891506323331132211115001822565826592503846734090002137478494788456232384121701436701447994389804331257968456600648575397714776647267419814819334981976550405146592456775027437912499143913393179341590012496578210345191038687344969516120227852094079906766427321897976750856648213542945289047181277017005010812119508343239545466550376946350050621341130743549138056162396432507977195314197160769253969192504882812500000 245603740073041608066268058481642878396500952525758292091178910360152579233320063147358827320443158301410815174454429554346265161899327007557453956487385790532180407377952664769205658750270079010257735277776458852487474088479371246771978602406839166265388531788337720509937307775832734000544138543985493679430090080910644485324886174503114796055443335541611845477313754402003528468788695399311076874443449113982751441653817892074584960937500000 -1158709109711941512157621213033315518430041060235024598221493720050097532010975061146755619499491604610167732830600487626661053395951918048803048964025035606775336040724771049201884738206130254372307423433808237300952196050826207512685787490957357611298362337201070320247296695517485269840193924660011814104724350652498426154458893776998729105428085640372423968125396763594224642335054845894762570041036653378796472679823637008666992187500000 2162856793804923700251288618458264068774935483916830989781953869571582172207134709802727091359687990103562651230296479830862465932482403694857325758657052549599271019416124737350006849519046387196173332348697237643749710550603007130216015767941415340720932864012426719946218939277604376145898234651533580666420637510891168388210002956609619231266790136902190020525598673648121385622813319318130144408574011549717397429049015045166015625000 16427081444310090863324859325996878775421121116815660619626349344190939422540536752630380116135789631357375496374653709229613680933937743292211900322975229948126383869583889880882153842368139013789710733803058833925570548447177385192093238846788781656777462422725390803688213655297857996611893359964740227863568312563211082205233886502121964459453600963897087349631034248897689113397335496872392335276913399866316467523574829101562500000 -193995500801957455473976907644525800042074646000229527615595837389492429280181062501273742169432452236917072037097639488930796954970822948836538902551436711961979095736218770209881019573321233544708146887477327725351677597060125429568229535848190434288796294176497611484703209922417702862780909468751849153997915336679692494827381437667478049501960238043834367315168880110002328748615749815994990790102292521623894572257995605468750000 1051458594585612591146392214418790322304269498602366148671485879304892440330279402681615443722491414222996459721302443427965240691089573173648550914586126814300160889416982936241437707343254821005361856427552819280541307814623427982395549307999894118494096421531932468839790855625160468701468011182992729777171261533538499269860665086722943618521238268157646254668660128272364890352570578752056107418866304215043783187866210937500000 -2485837990378255021839599513979824416504237013530514984536826298002255250916281212633119566847196894803026826937869636930941529863033060750472389715641382380286251884940738065766349786976831567087722140610868353030518738526608685602378643491204143196661730825767450572906899847888886974938902380805753740403870753400192830249790942610123260119534956443714194845537072530184894880760570687328048222752840956673026084899902343750000 -11841584827404487771968444448184098921291110162489301115401337527155465429423193524555091507681396728261172886214899998713539703389820809962291998980368797893367209293438082504022665314768456633798573077845595218478245074107946316408904888267654171854420734382618059138747547200781890178626089053459129696077240549401126724865114145208687375994029443042386875800265062887652580618080139229775227249774616211652755737304687500000 160645770952757672875155812160778600565957624934038098330360860900189849565567394001087316610686778998465180987238598370192609212235730946119219454975651467288801086362076038648531029835328509491993368968833494875593270502429731910347314323639608841949685231128668464871127846103746452412225842871079567464460971660323101321196819875547045651791098388081179515100237506290371873552899617543232579919276759028434753417968750000 -825188117484430202087010888246921114495132802561810605788181791330407741243594570216160840602358869632950256974282783713302674049725394794640729249958028509134906839335933752692143940723456187342688947256610632309638431819478741046464316320247666096024232628005036554812291345503548972439204092576011204830614523574533818204314464685558444212846318098071923871070736813595071067889419325069866317790001630783081054687500000 1278802672178164314052587589517966835611007654323464512567906393316554718532430757754649965661131082360125157829655541658658610613317993666213288387413676156867994867760738930665063323122544201411809123709540185807994572230736790151706485009175689822935008671078869211595349935099493548137969088771703475518793910591246455337323642583660434796437725015550146767064844395054667818001359336221867124550044536590576171875000 14093077598396033158762059164992869902540088451737740343583951549528092367129777657040783460380197724665034230126175143606506243157099540038641068451966893812649782426018638127981325920933087557439689114997589436679117390339427795232547978694018358392273474300594989543264762623055208292758011231176849909319162354436515026988595392079806061903208374968369579484304695649130728662967726450006011873483657836914062500000 -129374366621731148709909408765536486956113281121390025560142444854419010363763145189297350712536777117197778576420917706185681623851960247040102250301627711161743753752184139786866728531589517868265124618347082892387413521022774339788946803705119158512576753282950561975283885388779785082034356292975971211800218021282703574305324031880432768831030637631211185722896253851715853144810353114735335111618041992187500000 483819025524639026563208598289236839938910696037329170902418185144062830959192867319733535532692930964800912816736013548241274765435193079384228450131543699406539547782227983751212062106095867690691364726307888585768263690269917319928523824835773830107539714157441522418700214434127118490744649946550927782800315432768323074277622440638499304523564808959360982150226752201982449719253054354339838027954101562500000 108665476397978014692411734714627661954221383062144094681924813518500104464946637064718636946680928995614797308556610956356473806962727015434068540827145446778406659973514159023499358728136716751081774935495868191939095613204117905529209706818988265667805448215576822113173427509708284253269816468717268861623145734869702452782108697176607092303076173607498115434265295586868660393520258367061614990234375000000 -11898714671790210327916081293541285642640141127751020579173924505701516135529114017044861934990483128829094244160868305971201593018293491159149916162053594397873071636256988644192724991063913364730117501969738626620212736729729429710988481160430217246221074097749427314218762111060835026166353093942495991672321389728047627551370649375081274310907252196193075453097692806281315824890043586492538452148437500000 66883401234410061433947584176106728382754167211196243720926334302545407849629065439571856503766316503805762768936466548082954418584345805962058472994618896661353697555390205399100557079432010426572905324616235833768786180207641366178246720511094154742323554761377668130520705528845774123670294715530503527051584363783994032712468221555425042224513985877166555651940349491724191466346383094787597656250000000 -119634414138148955160273296283217999495247488553371190185548357621636180813123141422349300602016139132667097552001279114909254389335076535713630632001321223420284871256993318038661743973307775206360389242205558580932074515468393132279656323589201177805049548457572838585856067033658704767183215449504205302913586157255457803354540111692992714144830774436651949638177327983612485695630311965942382812500000 -764556677770857106433982572069967104198091959353671471489563859441635482879570639782448146856524817983952623980712498152291650146264111080014579718835128120865221186609675256561600708444837178252191887562335193613727812927561040670822785576373982206630000706971222178603490366771984617528458163726964281288057694191376784941788212235574558946664272421770759159687091965906802215613424777984619140625000 6782913078996732497136515245710536404324763527908225489892095319033636133518835033220351194706451931042998947020053098915961085736050942318514413121100259533982416135252612028827999415538916508586989731276229276784903104074331142102822806628503885843952511190768404969797123545773210828938530411682512188765168148677170771058114734264416300351260081028231113675630581383302342146635055541992187500000 -22409322903350184621979314366551434784594243469658507837394170490754019494488556161232881036866483887778954797364426135586822441840115251857939251012332791909772981841312301290775147827328677465724915468242100150200880996642599792401459581201496951733459101759896375789625417630595009596216959677167459735510080654561123656074120580707708522975488374352412423995417611877201125025749206542968750000 -5023115433324025553552832249954457826070711228240712672354222346662534293425925968456604456993594791194671683260187833955087795458706345540914317275964461969292930786111520887848884922887023965820555096161542931808406896130104076627616518720015762866763590978116500332386185477405181095202628408764028441185388525554548508648361802019315365063314212518141843588637129869312047958374023437500000 412260759786368521814895022950451536014513467353660816543892036187602611278617124561047752857086956025738562494776722195608782585244760351991312416259707577606165949831235992326257042107391538977754155406382411561689917265509636902000505443916353285375979687416840463405499807980492595805812668755719604808326880975145267079954331209576138042165486738421797952014458132907748222351074218750000 -1935914905612495180100866373394517798390659163438862254872016059985147975510278795658828667559626189215823022301471378168247945064197577502365521796727495501966317137356359102250307533515667855094034040650455020457919945164975743714918179671446144823322380444896803261486584540526359535854915165870609699119851297839956495788862537887386969248388474129640712817490566521883010864257812500000 2540362604864904396510415597157108612859513521730631556671097923286414813648757030527649782074260726558622414468084114767132257183804047236108914894130284068331027322927623620911685159957380657218112219139465337593746691016991631074458117874378156208557690675131207455958654049198946118010355100723164374908847614082955665233473534802787055291925510935868715023389086127281188964843750000 19375791103378916947021188521782552741266212388085941347325551307698411047790480569516709376073064564014257496381015253982591892176042702834884001265425686876184151392269081934829855263470053230677983336191380175676232672074576729579032724095017479819988801381527559675905251117654033957432258999795957485296603904361354753951525102874419489301649477397404552903026342391967773437500000 -135759455421919379849123011121862825555018848464559837113142917292575159365547786536123419126776157696527910020206200927933919141653510437702883200586963718901868690503858631716133606421617535461896986896218536928860273161645760052657289201505617450628097424278908038017899654847337506940163249911877526134275412610592824430978651216946648076777659497338390792720019817352294921875000 373492920863071852703023883572852828347379708753604348525254494301996474452311557468152383455293189014330093157693573967439090145082190901004875382700740634851367477203337418316156622281220285728656596953959317285747742612019545885675309166003908248088976953228707864273899664827976359600771482147187406698194595158578646068203578769258837999345246316806878894567489624023437500000 103441415049457541193506163340166238936107980487676080949414846970844854981508034275157528838597052352063176355493438204528606156206004314129765663455531011823519680909877647167609476969204116802264952138553225420472055345024917642033083958023274338177529978242239099557340111815833578003238541615536687793460579849205954601658384410522995011660896125249564647674560546875000000 -5213086560756361946639359416694915546903601171816692466140819622805633552548843962416588876637223776569015039924002068797632623009732994062231403748081301961679081004101372209349866150966091841290578850445081340556109963535197522001695645253018669559480788526412591506096020274409667114627417941750626160695246775671187008446155492641382878105105191934853792190551757812500000 20940774555555683973961933113602602733285191722878754373832751539142997269707440725601873475486010658771410940962417534910502473413518093972971244156702163222581630586740719090642454691167802807336197505297056425620794314916355595679412271389943509347592059374641672127820452474384175034587723610484307968691413145246269418575397330828380404454946983605623245239257812500000 -23845361223891035568097592693034734347506669463423389340729487718227181220404820883170703352914081699634086833341928698164014447683898629973484583539725835704818397989864414901176713889713666808206882092097547167243155679930666445260429901956065231399736767770257133729891644976642280894062121471180487738525757571168585933780309504825822841667104512453079223632812500000 -158728136554633095208211247502047045838476163959203880914061302599328878055121037752197828646760524226127157202877134831206906360547588763920008632859728497679519283235773020413908792040949601179937411177480884808118393483560237461641157493349249958371774693265118017640426842603666378210740713706956055175892547886943044401636404572286664915736764669418334960937500000 991090885879253377635549078938663664914783562703307083850273968545423172665752192119505343543939156415059406820129668068896779639449355066665487144441285106786203609030775641755461209160089981511236678039180211218420993157346003780808303858487019410924344337518521271078226031856535151482363035034062165501382273584331673160763287455665704328566789627075195312500000 -2535510989267063453963403595793834627027719142403380246865947044297828072347625498257112601821410455430328750476894448866877968580124268644727224975698537558128572123939392850120169775124080730496014557537166026615938945567327472470961875752949018645107910345017381214474692201341697881241787407195489686533061011063561098616281341833200713153928518295288085937500 277961371552965016145351254588485182681399611815323563620751437758161478134823565975176898261957950455686275978438062630961389722247978372580712989306813318058541068829175669435852034449686865629778920304846492653272877202477512517458694512635901856544249790589779034926335179258997459363815901964136541304206955323163885651638338458724319934844970703125000000 24164929650296813688089597918158194201305281921996515975977116007426684829246919779593997520027717521850376058291302027159081221351426213273948519484643605783685817545119680661965960415365273439632578133371653385467085496634449229482685352975179450052244506453609308188139422303088407382792544262155805223018262164851044371260968546266667544841766357421875000 -98053289879883049324046344435564284199653464599837386376977261769769912483389285924782427752698584487486939893588023752753599023000687986088274604690748800166597307868368651330825291781159356534501964297052886445022802648185037891234322521567706426892502132631459765271307953179343607971397746469987366328951300387117839818529319018125534057617187500000000 147675966078664225086138840572156547714672946951991175019155281604837740009946885590592329337764086923366485389234793094196213741742529681398825509790576021273371490182429752850866578244303015972301787500196523631980812098648993511370401381475055378925982083559731680811176313160445187123798775070609673755179895582312354918030905537307262420654296875000 387311055942142732639689202937823823624314840170068301257713894295342597533981791441840477640554032995117012974760263579540264070475724881897586839805894835117620482820873269832691174070302939561609000313575353733566692803371972990454516118180822643192678598275782315325561703065433195601859890305736840599576398247450015333015471696853637695312500000 -3062877354106356422628510036699923572942566439196266592630837114668762444433382400926979004665369482793540243840542661938664780923435011365999034973530209788228055903735392451487174548652694961850870916594614395360654683002236679081593263847979306282808553094516677877023293790751098294815243828858493933299522726798613803111948072910308837890625000 9007594552505042209306999777849563839674554553568775747592309223077158068315669462002174715767017781614097705012514678391255702413504859486531841418845356664746983498916963133520316225577075220006969421970529561606769252699503966037610299856382261593204780168800181676930618545026887396200846555192279924151321779390855226665735244750976562500000 -9172881383728853303488221296935450232024725478008592797736006836600325039399300256683765162733985119645379390535913816405161975755416861453249583186064670811410255552593842656541135301037750764684964704195326116487664681535141019287526359097523921581542193677735053925300765564899590062047411813666176333414981058922421652823686599731445312500 -40415753474600418123517540429242364726393281510884037188037185409604472845684046674874868950737768571845848095307431661639164727622378710143648558325358431467196841205781630890340218001123720168365545627544965641861712058795309721677370496699071968515584967330743510629268533300567494779550548403279641718199854949489235877990722656250000000 230935316873845941274491372611101532971396799703205316915655188617364945345517318534462004431031216679422487669293460021997295758459597891958661078528050220601157050944752950937571535160792197175099863356621143856041030238576465389555128450194545476136369202973768760652276453650696241562065031543982129846881434787064790725708007812500000 -545415895576775786854642001538336411620274575640037122831402427444025761850921883387331849093841454988812850078189039308970106812002475740712194334943047092424176098464149583329578444952190765338369054080239480399129953468742568367550416446914551467438674621529523693547970494695794764603187509965920298782293684780597686767578125000000 173626323425190326106591969213981251223526351793188574695852130284369510273234727691959656645626371166374250247462265773604905476720283823969906575322935173457039942227796186471650180610437831803024826986336884083136925712282405199268543615318988676866482947680361502890438086835106680375431786877982176520163193345069885253906250000 3877860992595237180730961290494395339669805480805579859810224771722390307553450711178010628967063420801875323114601181597918585535198444510107365937892839519831482111753430380420110842198199079069496010989130417991093023478348067183005993228154799390262705013859606941364907070279800967160799274324745056219398975372314453125000000 -16902742244641913652890475876720758207567451079552581123359078794670132283542854900054114384290327917064315606566346455772140108199380163434831754549539814251432685489453367107141115253080098869879504402778822800836049602375528261413142720753145997268837150683269007606256187100474911583214421284537820611149072647094726562500000 36908252329791258918730555884405945288749754697192638621522715184053132069464965139249100257203387720340118549418516004830801769630564999354553156853849169672305008457932593665234102790469109504078368726367978568339675087369441115651675592919423321953073965221045045934080092251555749172098330745939165353775024414062500000000 -18261014209183319120558455997296721611539788767072066972501179409032673991758136974095161304365752128199174447947006614540565500718111940787731877233935682850218704535380266902042907830529873125564885338877665610740265625491861735399634195146289734389621961667345455259744205743239336969807595778547693043947219848632812500 -197393866926642209432461591635773803118627945441859979097834781963493350009716390505062130467799569939860190025558145644811328362698092938176396089418300057248537539791549758923971790921142669022971182861498725248917968174811681426867396052206724331359046122049901742693080782670156381186643557157367467880249023437500000 897865508865628045919133459542904295421490251353667869641010569663511115466712876221025924732757312529677846077179846090060148701817335148508627023825745085052224819705762856791317507200192784901100018740958371859642049928426830347402331440398447312469150022098876599561706642049774274028095533140003681182861328125000 -2140645846030033082974614624774608468034983190194091056965220608662916274637964564059020010363428065531153503786917293952758568146245413765148684764601842053496039318688778583992311120914422752367056412265087094450467863617912219563710166083223670521610457792752175824619459421072065197222400456666946411132812500000 2424323748545447267635903517404693226908631119456456530988408514975048779641630239786363637028202937395170221214002755074277739625166313676138564695328131968231209975193917440088857222162608960111303427608661244703371466507439825952316409585650321922966199407556032595530137729866737572592683136463165283203125000 3769568078518311927688956610083230987819268394492048501713954983077313296874276827909685305264244317374607580216137217440518327350065057260762020556926091857325657501775854011313646891447881075729634871347495729357927315645933491695020052866022086390974855606953060338515371086032246239483356475830078125000000 -27002682244835409065706920568734932628061504065441696815267795247097755825776628693884030709530513927240567071671799970930252313244954760307097719936568449114652577086250445180622630112786684915394525840458333150538813462062880289374448463255561547895416680585361189625981381823294213972985744476318359375000 73795844892135949840814919726812883814470847792821466556654180717958178060235186466670805369186847881991948027496086228792549257512062051233880110417998864293752942223832845296646090785311804060798294892178691258658822398633487129855803336999203793546148058904443622907365352148190140724182128906250000000 -113696155038425171995519336278073134793394744221046253381093228785524852083676137780523993760094683292709498359094164637276932672103914080849228682538661480424639387428819512034357438350685416739154908994063578150591655654468164955270572462345880500636452687442806697148967032262589782476425170898437500 22401806591389953708166215115708690955929692145700855165417301476478586268526623954333533430803122509442075325741260197048869228656893441299291447557647147938881463047514529980712944351650516869198325095826605524354933678886441777272393712533212735491926909103810316992166917771100997924804687500000 439106987038669376115891829147061550953028810055693835711140307497919556180498526919403865522271318416627256980215849610793198090916301732608077554501076244799097950676956880005943818668164442844269460913733440328839355481676737456375058216491598633152149133707098371814936399459838867187500000000 -1447609800568489554830305020220563308733129190839006523189008677856278525867411020540869727004304804839805450322470811793470538806377023861393587541645444686907090287000277882660007303982276176901882047391263088037965150047950936874807351166225043246488235482161144318524748086929321289062500000 2561673323014296538135867338333220309235497482432014058850202729530575732893759245154027255391190741711663257717572608498906538388540510818738336546447060313744400331531732789534338457767269434545980442423559199722212525494778766760425217512457066876274680566893948707729578018188476562500000 -1941878379528216046227888004320778796501800504333440013553658890685060591003904781902175454801323862224028013521401156956752569647966079608413213075513356908643854821117562371293054200054784005719695257744514013101362311869030258725361794884620852963408310642989818006753921508789062500000 -3640457877777110286611482239682181339487803674189774728190171754406169530492258514278308703485905232035150051637856031378106651140847683603828659908323498634649401556503990387032056515005581267075483066603978557767270332233602655362508500411916623207275733875576406717300415039062500000 16179471795345340183274226484710004619213423224666473715106617565024643361897618954320494206784661934768565645813328619634289829953872783704559615236465189467167248192912466118084852749414649717836888786283637786591888735415621852863478444956024659973081725183874368667602539062500000 -30317688965345088703727725283398085221889017353768125508372516182777253756100066266386576194035671737451130747296770828983567946659598146668900763799131010440000697362461468412596258820748940156525674814429429139943703246501971445422897628863001528998211142607033252716064453125000 27461500357110661703015296463640157494507060902365365334177143201976467672982799037110141244359850478725278135595412744588864172804056642990634384767250206747320921294139088017371182625954283127044407771304781100126623888301153708722118773621900800208095461130142211914062500000 19108474231297035841849723937007632676217588489465810496914487226448720098878515666740204501154010410880724234084821686300566702538120481043004759560980556195402725476645705729219284343723012269689364110377558583326310735186272541860641460687020298792049288749694824218750000 -116342828654927625537689858048937483822849987751595032244817500060263575635113732061806939494609548658609708157758195499936243217140348862439298116808812827119324596414498796186836000388266601220012741168352057086040498159551590667826204139601031783968210220336914062500000 207896072729096190402614429124113810579728240534630016160809939379257539415504419012409316210723047987723225899773832306494469762152809316791090670575530780949541550069041586469894074124036636627674783194234832995583077489823095596044311150762951001524925231933593750000 -162668934115106257347626509776945407867211961968433691071248568005697769460071434331230936167338904940066947635180459212170525413994568036407251585427728090240350078981907497567742250289008533967590691399575361448949885941755999496649565116968005895614624023437500000 -134943623228048533135196166821494213651169550823434649020358464942972911849216448883677587498897986073257100385875774359939993822173122683332189786222759517828829058514190349102821424651005411134098720389534589830354263315093099606656323885545134544372558593750000 595826501322533036246403622584342590221627193426565069034632383080490501895425891284726445978078538928184412124002561603527270370460670222752860264644213637960723177375666534122729356526280050635748549192636072983301348537921171555353794246912002563476562500000 -816141513694659273148044513687476104693098246586508604733588218201124567388170792511334079529428977269283860508640775268123141962436035027332747596292699814867763751437213809007894946481801691168764222412894434439088742205825610653846524655818939208984375000 316104668578229601225696687700805568550704970141666476842764421189846900887886510672940200605888432683720993961315740733995214596774787955192026535549488495066375887064736654212792382911204047243762263714550540122383281982365588191896677017211914062500000 875151972185107365025308236945742558079231824671528568731416642937847100503818808977662340106004906500149429795250925553572920451323679142555550514210095927478423862192154468239516334983342123410452564381562662321201173654117155820131301879882812500000 -1852716382593900992444161572829694328787884693320309078877347107563118052940040289527512947643884510114948374481008592976450125756199019192569253617477126019976226456637951435724468279616464531305083539205330600552201758546289056539535522460937500000 1408454688560812658989790592616883755436397175519688287173565512499033380468593159424447396382057458948084601045303507947445417506401026797724635376082320083394213635796809432438127333745901219308731960877523192721127998083829879760742187500000000 614622680770597495859276552589156750050641747223538032014435465988933245219717974296354507218073405192385090464356564024355201434787863129213149334225306100784100485096763923368343293254464423122727240178519991786743048578500747680664062500000 -2615644920275087231852330950537921105987292603892690771663215615968104662671839554727064032154517829117136772206026087264557892887347208838736510344873963672549974717785040419453988516527536941150278160250763903604820370674133300781250000000 2483565716636344385023762606017113398024925329342247237518020466447384848963547184521573404764092860051715845358745625244009484615929982947101556255680857855831365169669822025731554529885669862360186854743915318977087736129760742187500000 44269207359048114692655885477384673299345867618426257035516605030197007528236422633856104816312109930245274606283153787319643882690631652820812990850578615788007854089488435370343059289195870864563886470932629890739917755126953125000 -2644279273981817036870728858792740411019365078116155857766811054722282803560565818360502939174502042595223659389104276903633205443089521433357032303588931065588563159692504501196956343770511077551077505631837993860244750976562500000 2682925113973992991660767061391413165071602006848523684203532651503332782461629745519718677307545635935581051903676209334189902943755633189516038357063070168186525781437773461281785297369295584246629005065187811851501464843750000 -191171964328889021685964489519754882615037879052954769386100544594196354146402072644580762235855117591539688513812448838779745663316088006166582175256049451582679231470541520690863829257111206061381381005048751831054687500000 -2114318848474778075515450648133689466117156170308683286494020515533591469107956343272109657077369053218417960323433951846725889226986486701961988688002194624227654025557414779173323604588574653462274000048637390136718750000 1968126563231811972485854198535439045655619040077743108227408041091679132232817299126749683170360827589108862785416225486033314299633451849150332283317140441962845034342360269902227898342061962466686964035034179687500000 -8260413612316884654981000230665095137659278749185408823712626018168367807665625570419723536525598202856911078783709834336780562376800051340162455391164774182323055672697713069929648099787300452589988708496093750000 -1374428580209737791984611260364310871447156049627237844768949469082442815963652567804887931304440425563754893068058915966646944424223242190612510867055375195041620474201049129092666589713189750909805297851562500000 991307612389523718569483107846039582070156207867229865425126192213290984974538231858202355732349206774193518540588560905536944097390253896435514905475065261292415466765729714637700453749857842922210693359375000 177085345177739313761341103891608279389206187400560337605819650213555759423030442925755925059613547838233354523186056363634094923852664772899786544182317988589191366243014158499136101454496383666992187500000 -686387781000529975599380144352324156256580665630355874193316759337373132877756245853331604038761963987638479263433822307392825556829892417837632187002325427826672676786756710498593747615814208984375000000 318396862406151732222085150324033378040737980554352582066232584207858786190898302983175532734410406920042705661800950224664069657393144799933690908224497705336378848528511298354715108871459960937500000 166344381587911586839927154720871193771158421985134454309930662663745064548500510362531426707137557152994168273634624095574129290097894255588547216361756712089084089711832348257303237915039062500000 -240600792397155981290857459496688725404217922112217529164640999259661443938144848257394503440745926837714407600415030554211791340842661659580685972743707685532995128596667200326919555664062500000 48834764643565114234349476000532698928937987334984103967203602398195024406084394155513260718797769262086094599430679371266033387380978306635689508243027906730458198580890893936157226562500000 76128926655916111388556357607604181988894282559085094331397677092301455348950112755057585399457439907452235159223432534158727753514186664690394319161805727089813444763422012329101562500000 -53662242048792296018600044213672591028194141464832947508786243427132684180044949623963180215666869503688643951491487959220468214119411329143302784718688663042485131882131099700927734375 -4161912555773269357645041680502160022540314215765496610657112420852455926939435756851892782417574007642513868722336194454856114262082033534520591142554956604726612567901611328125000 19629180776537387096860790930310178439822098169576860305367775235213315116876179887636499005433215684531341389101447641819717999728442420758841801339698577066883444786071777343750 -6302122221124917611247671183384125270935354478691067824615501422601558174749629993334666065207243729497728301257792615049061465332474921627935867388849146664142608642578125000 -3322349013095458111098863616493942148043765308637886269334746019532080851443573127361894329587999746998976555876756526304915818266700219785552681699628010392189025878906250 2811241036398550936672888806395204423322088568466826367709162302077786594197639521177818994547323496955200553582583220239197023759622158142078544944524765014648437500000 -106986482935015971253418715388807905849507628863069618628147836773545472743243713238515733060862076029501443367273879170692941583490019937005499377846717834472656250 -590669087463176939479718994478183444791366186011558309877976932194631982561550780105429369426314068638276098133671880998960232899557348782658576965332031250000000 189045343621407492915212287167317031481944527106887587993045379950886421964768793679079875405578798101346146979749000536865925174117487627379596233367919921875 58554932165361710406998434197143811820450131463284841416671020337286541445450493158441590681766819915123629622368358201835199227479177820682525634765625000 -45626089430941057724924834772372980854523556235734475366688417853663035303132272387316145692614810798532728163326661793729277287527558326721191406250000 1570725258152595701939311518538350728659987151923759818595146329390093534582082690546892301639316001867736521044675579583012201917171478271484375000 5679677626905888088734129762522697332262556948531244958467519653834373866085003439424685161550484714305972797865890192170748854679489135742187500 -1212306095897882657956342128110227340066427146264070631711750288103359257320036141999633558198979356968545752896092065545813234405517578125000 -383015573948403773143720775365974652913482432689698655513581052124796097643982849742065912034987456035909469015228587588786041259765625000 158428603775012046465985727362087117005009315842164240794514875476551915342087379304837165194747583113667032236985750086380615234375000 11227773284432889616109387240392957763904495292184712804019507916100083292282880393299808603882558272309055326535377311004638671875 -11202498407376057011965205876368766336737900159111825098943907509245274155040237519109324105399310954862439761127008347656250000 122852484835460133763064890406356319765656288404728324786209081456725582524567910768014674531579052769930710364095800781250 498620316968573536903192929222700936217108053261017822029395483554245028576011341930004438877078090519654730113281250000 -14304234708245534461573824272413304624982939040185151980487559371954457933675466894042977131708523169635375582343750 -14531127884171582538596964016040535915950424046168383761849510740993493556365049713211202528607627744373955875000 -35060812459287772688078654707682866710662672488267922664744317355375176223714281382710016472292099474118750 235263606436972938820285474273361267769591092185954373892040153735975087428464889054531331407738225735000 15684240429131529254685698284890751184639406145730291592802676915731672495230992603635422093849215049 flint-3.1.3/src/fmpz_poly_factor/profile/M12_6_flint000066400000000000000000036011261461254215100223530ustar00rootroot00000000000000925 85334412394258575684915107641464918197602970569927191146869631810682289553018248679381134914415526755385573129519301786624826048846578478504057457281556014103945459647016204953337817012240391212136194887329221108974508589214029633405520984419575551123467439692402830663063850603024585609841329932752518492129619475221507144072751111570103559671033936037584949304710496816875876615469088269966111237656966047987573322516307351648711682226566196203607157224159274360330096621476120145843674065100029678075887736658815496238239415876019530461679324982089582378835389577698368423739619283866088021623124043634639246812396691289517733549147458297163147776845146233079481557468035333935269940430687006894053276599578190303228561450934682065384281056922131953628323476146374804640108908912135613261203336323310370586919830767226814699167630872252235556858888306959144030507444624115140466090152450524661360072224948932442168372900492534380390345510234944638928857479224703237360028515183735779284222580739516224707903600419817071909199712255288713555675059695806729061578539326103408315730327657268104408796868661169585222463831718345083636059318398577199326640944889202122704452794779743823539148517186086213096884342440447317451388553953508548215624294321904976598273209164301268404339344600587506499508790145313963256261349711251805483035453520969767966231994181868674822556176950971718042637803591787815093994140625 1979758367546798955890030497281986102184388917222310834607375458007829117630023369361642330014440220724945296604847801449695964333240620701294133008932099527211534663810775954917437354683977076121559721386037929728208599269765487495008086838534152786064444600863745671383081333990170386148318854439858429017407171825138965742487825788426402584367987316071970823869283526151520337478882847863213780713641612313311701082378330558250111027656335751923686047600495165159658241618245987383573238310320688531360595490484519512727154448323653106710960339584478311188981038202602147430759167385693242101656477812323630526047603237916811418340221032494185028422807392607443972133258419747298262617991938559942036017110214015034902625661684623916915320520593461324177104646595895467650526686761546227659917402700800597616540073799662101020689036236251864919126208721452141507772715279471258813291536852172143553675618815232658306251291426797625056015837450715623149493518013115106752661552262670079393963873156776413223363529739756068293433324322698154491661384942716114228622112365599072924943601648620022284087352939134377161160895865605940356576186846991024378069921429489246743304838890056706108245598717200143847716744618377764872214451721398318602483628268195457079938452611789426980672794733630150788603931371283947545263313301041887206422521686498616816582265019353255883303305262543858589197043329477310180664062500 -158433371936838610567545443353038256908229952972408853801842343325232606792429813619315772190078360687319749858352615236759096639227017302971854746600185051171233369820740073601574169810504925755337393024845448905213590598085937584302238196842709752745529421559853681698864014953346058875938146360555142276813312998999014062211205394160617902707891815844654478374233271294955729539708341537972633527391705927296173211874252516080387126547449987436670231588341253980617599197133102642487932117928260860838027307504922045468649092529137278198889960317867203421195651792811358306799234979725175064094672666395239195282639595229885319619457636069779130233891570970909067658470565838406099432154565077090820648672445020693123484012486867172996806973628232014628729224306539638491387866203067833167543511396577324294197687591454807362413328827726852174210012747134549287975058620157554215815180226327215515150030111347073340783290417487999237810344383178351660961943820218385259606477791991081568803045718406838278248683642799764487085787688104718668824895712285419374158199895135727298971283182250730564009861181215888508726265331717725152179725182802243228549727161922710970446657157260506274077426021590138353025975339361441453035133708633552367576659825628845079942169742923026621820343557915734907102411138496461707328132073665020091580124431014440274022526081154982564234675115888428820198896573856472969055175781250 -7345931597985126221346376563787363917900979957018298514438898100536536767795256150260103073463095751929958812342282989033944140140670535117500024104786644772616868911110711869890599229760715536810460007451038533856873318426627312138524306508248563854010672285898749106997248718014732986881955528016453417035761950163746567480937049973893438790825871370026673515969897479073072209807557503247783185377490480708874294586966356431643870535776994684166370725319493110217889742796526319743856945376474677944890273596580681339674503719290001148548165676891030761262287138050636747183929934740697605151333714243398991459113085808074144046404670687676617366868616279714539689037324915372637192726419639098804328765161268690086220244846931487183083067103635662928309921957984358974949883070350208210720072054645858213583557708289138252425090488585959555542516513853221172307264147854905149975957157580585005368419425524473933062673860139896927950758189828339024529866912269569566846016072027189925629523541161938511243575704854048700768073649482646028200205835624653657943615335707908285708747359036585348144294442447822367282132625529088360549691368792438983450719209557225483502645668703828074211543767520819501275244003085924855070286776295745102758645244373447090905442631918896410627219770108335193328022507605508495021301845080922748087131657458240258733325867899227456725365532907989774002999183721840381622314453125000 -48651578479264131439523105505316662724364565237148995318411387885235340817093884442225709137843303417509523124070915072226409616226713901859377805538480257150389780563759513949957203304311969888786356664002870098110872044135095056880250000810952914610623350324634226088410200494521112066965464495915176619977639635697687147664832008232436293468181395263342729042571801040242419981031199115278484857152118131220218917228198692916207341011701506524095792462429035884669778631756051371825497178726173099228855874689807043349780999992224842797946811706528817624434429198055618259513670329851397956854084923713541680279687715811253303171249205156164058773817002392869511314165854161673398842484284803322980969208685128460986957069918294830744117247233285389396077005468067754023580962300669059933084848561339674838414543963838380512120495321371700083368615626897550763203341767203215201862357839452554801501419615366983075389216081621947679123638268022274419183504819016774430814781595047255378748828952372181514402485257208533535981857101300314330539791496253515433638067174132564082323124559275275281683732398829996700918445045050140611763783801837450808613923735291459723565241062056038276327446314396968938360810048541317454895995455529492311590680342175215706923189691852470992849890156836257277876117889245950376487452402340444360200047451967356668904167146627910838332489230385891065822079326608218252658843994140625 3085404142734193356218998316457623126048038051053890931855847689498610559662201167793925891173599687717938904258207263332377428249405513280068649942283096744923919072065691278059124614889515033253995625516096376876472819778256863522496808084141149300909016627511076764285340842703919112431132311935779607062225858067154855794157906856385746276859809221093308604837902162183185490536500016678308203573119195502901645689449394732419841643801047762303233524389480840777911536498015621754665802014666028191148405642132824160574129070626237700467486210817638968219779754578655822338530703591642270516355211177982254236488140850962991969586780363096083766167673790432002396960315871524678996329683994636628695727967338671000076286361480419867330362971946059468311460156139444278446708798687986346457746461279201149070296083762622441959583274734268605686080022623337671009895263985484354183379998764145737294466720183110250984894286094764161881983382942478588019427597275156604660842858962126974656035302541656012250119721449477434390865878793587229739744705700627620024100611624593482519368650196542249859240269647224593604215338914704544819087028952288606032957329542760345425220095751234253500864295787203418274155171039720195376252152274417995508458378801132603097772132750222532222206074981242633104254565070923620806058799288131397420524564687711792510725823064263332142042174730672821070243116992060095071792602539062500 66645519882218416419881879969666864309734339663608489778844110824177192729192007605902532017434062483042594501851560972169426107522251787265530321271611593842012712220382223769906225268305191865408392818366004554175160103124732927262357341373768047307285837541892955262639509303063137142462998251223924770425570648282414377858331370409335977186477013109169216486953197684690624548367531062416231079859795356528129734619996314325543805250476886304490531188160857730490485053495328755805699823241095724204044503029508720471178289494713808352104630857689459930245822881291823330352181542632297509780512771150533093239637285218796954561722209658009395555145350274712927352916923033990134744568837084246557861305809565474293732876487738176437540389485279731123446608121092697114303955026182031057112058005879436924426758107578795258175448057203444710424484108571955861904964298525838277523289805300896403441403492540256041263283565763426976005818459901951678031833152761663800206008698775872466948411774828725765618130241737818404582733723436926144366851048748844407456928522452738023311269070447296006679860769082468811408634946864140783859190126823148935100273953827801539747723564348560627147399566707337981817536088800910435830658622103966076800520333184746092398330420819682242537191415191804603913156001996276530664728854517916810941014267044393785072547902962592386124957184734274306947554578073322772979736328125000000 -255052044792770684746706712768188842351692644752430810471190396745743293062129075659991561403450201500382702104070642644699441253248470712430155718580522589694490178408888898898538495554856506961677436389425222502564532923993954406396671068909273701203326424638833654749627500364386666532492935510898882180933701281059957857328374856994455146348491529677268537118460318040305952137991258816275868316079022996929772010161736030278914925133754412612837510753133094114414854738075711636820356485270453188770290141885965127830987609113267364046202525363481031437945456387119132055415111099038189789217516995792191667003431844904140672838395330144905498039077686021010123054581692248796352224433369505000336232073269895670627915540018478423445946942933776405421137884628486257026636083518696011371782302973967895004113319942701459097720521554123861329172927655024234848720231562988005718930679876589854220306583049861453511577868606657906311287889621335437882609558832034492820673854695307690804349366029312072375166009369262503884566342860738651672713565399359683255358762286399462965661068486240157440783012029362088470616498894640320298103519985131585130359606100005584557812109268778134558063068908807611768444068407947136002737315783423575549069453345276567808505069414247803643914112489187910362357159105633129902769671490593470935974519782483904300873607745737047071259478092045830388556737489125225692987442016601562500 -25145180606048820811594353785294150331661415067192568363042199525675168723086107428692388957901522032359297688478613652902398484339552610190402905816705583661848502424924275986032674212729526356032659327545980401114935129832381943893434472267962068423363381474596545327758008530173616262696053676976895760027586275475451731088364233163774596809504949538880099712437022220287858676396114018679436927019251079950052673023781736460408987763468268048178708068300209176811804031173880610188538333253622957280754881263604580999210554085994847562416976215393917223711152008156221185288463612734895222868291056315331601774474267281813769308315024983573438619372288223064783064898316570567506364952616474498108580282548588978178522232782610262943858197915766559780904077535882594845421278406160843947835035059086954073709446118801429592913004552037375638762714724560287584419594805319836611007941206844355744516710858999062735654033939454825443358411936243385975234182581753803401781222142103300175534013089850796901040155987957711626402089078791727259789137895792090407773336765472876983386866375472777452646189261482016489742758902685016203109664169201096844764382957030019803792545353186313354270365548608143824390344883490252205176031607119915544087871613861751036790535859121166015021427195949898256063253486690881032269419129810435262203996364662678561912206161567100551569399763198494994476117625481492723338305950164794921875 -266979812477576839727949421101611856618820943585497163322474299091827873259083484255789867556889608195467137177132369899110026215912222805177949839936139625280701718043676932567788832130863965809805955420784862806890004736371835509324837814601745266119735796508219196518729243202474373269050582910799878727258274322360428507967958378154536547699581600216221922744810530124667312228634655125072788686417790716975208732871286946763683694897158802921469643503394631184552172939507865658667626072507706087519043364240902065761198163755569679945134877357683260333435106919369833632278514280426168298471006631031876889129492811728213056519767818954266679835937732444789240511526322203395982993909632447428802362520559838826920464213993110192679254983907837126203446432086452966696556744209245002841106029010019759893833566261972955439077219765368364903856144880058147334486324284090165081837467893958660592042062583733999117299720623912190108911696839811959673477660260076115565259857532247807103258543884259320556184279210967297460991932504333734067355416306312354392094740193518701278375345822825829145191789030807333342195106307436554910029226838171459892537532819488221419000082180764854586183928107273614938675408228173405027494139441145594741966310590820079530009437943483552961848984096116617722208153533145622228671739419336532866918931182814769429824713314092967828405970933378955900483475716100656427443027496337890625000 2176276974131559849595833692438039420700931119720184680953729502801679007842489817235627087716686823366983802228396463679630406274374315137387602398412933514894523097631511942860928599032703104694606671528080629311586261938959959308438921476314923307638831972509435342999635612694887434325411817454574546208893348214380375228660728851252647711097801209092655986330402087593956771148084249955353558628906122471224591101315316584638462415150407304266869087171773893845603170456985281167626334921208910230924500579771651788835876908955531302248798097122393377948727192278009261967139661208459921349769684174654030120048517209990394332703748011283501936233864279756692213769177602121896808542896897247664007714363865572639402727691127095313132366065312965762949609410940038342091415541803694205892138000204949017259004008500347173080078520226289381495874945597367035576107087845073855168242644018291896471251458595182874969978460237164654977020086083902867030924007997228058349253196868928273142449506191413289713272246459380517659504774645219817648589173940593585981942214182337005291614251600376334198487871970305633903531797764542591125813413966306203063602263797024382056031107453167159204594446301326877589475407395916116538302056576871755515085452362990561018555593222953089591765482021210783313790342791028930475255226272290525996739793819432572896618507348941743432286257933289857005587641936017462285235524177551269531250 74775135528328973689053248560914051344228521030667630334540497186409745494942342157922570872078102544208391929926819985734003670950467287559961756428831314606339861900743071405110929284347901931134564758642175445190344297336227392491714211083787202804231803522289295918327780144914589092108943052736744344617013036786914014617718711399561928169423421283318270072031228220517854238635911989322929023101456042946107977279028340503595518217049032770911485890169955019346866416270802497393958312620088349391552021648635763084570445275016608406179025915003445993000128822454233623547637845020183326416687250604051545731252272136386385588485182582417514294030911450416232961670471814369600792894675645801677637527073362061604370629119797089016147022902156677402024624179057042514554610223921675275263914006595580726562670500959661301032263200568093158325504794653797399204045039670857425371652499757406209497888645787131343496505700266399471769021825219701246869611123894903868671257677607733748119148683796552408349634715786306052394709826238188475783737661332405374393683863656104466138522984871362282722110926407477738124219949031833218129094316644570761691511823001120641256150865898440551344970916410211524659502417123056727364257002837978610713505529488849188254780014032769164121023813945490591451924538992499957366274058989685194836205376228214209338137605136518073085371897461791617506277063398556492757052183151245117187500 506049524916238156696409571046508074322803689049848517846872535273244945705600717570824779006973766682772807947325317964257106446109535306794245149989543844383587580621670544763298792224963185672000234726862470201583698713696152547926781591675691425964518448490142618645768972832243271917769990399029756725478425503773068355968295378768923318693383281775638572354714929210251696861581725976840175933346610047663049352100579486292991170403268753087500748037190928417492322438186952026855874754144825746532209685029602268224659946265251950219607781616522361918768975590318075820583523214168614894611778178595083876046512774733750057565352485784219618313681185608002217439749124937711439314978174152041726483241414102087658367086108176277563445242182304781740020492653395847157691638180122065079263458160402488176156610496131049757926958271798423938202879326021792511709150247882056435062265175390976713450890968968308875883914309926732344055048458734721809701268879601333663055100139398782393153522266042680897284597973191581970437365007749897993035819387487929518838334337903491020173310123251634279220126150033140923046057612091301800636919920693978249215403612928091702192370256699653398676193084455415913278323896376703851587052351307901029075530237875054098642780331971539136886409274974800361085842159370691657105784164802077228224773352331651472468802964147563073382091686540772026807466499320753428037278354167938232421875 -4209014725119170377236701204875270489798287336488713091491023979328319094137689733099536540142882232312590375315972938349800435161325943730212172073302452678011675099373817926932464824509504765626987569464250471808751033027788705671466879837302163448005783203749771631372412635665538315118519454609548220863848057726405567281400842581288389982294454290682691993901862550623258134720868964239694143136283620834924656076933536695023076664762660424458705443351752363131483094581556598428344080149370194409794004672643781933791145440832845443080306040632460010410257710603624983679481288817408799958359971288657575661329867543514521232059044554309260593696578593967758161401437092266803946408718853786995388628504673132326001134241788032008375081421065870221881082238791235659341507864011537878675261441574988649194779448942083839511422411043403339613053775386394825144090867706567425711871318927529878851140270804098910446795926327443317264740991592727760874800534044649434548373620548220049677013536711471956388962557906880387993967006492112174579157641009764745592021752781022077940301395765881842098669738721359935060564278784598322749096493445364163162833294145396823881784069242976252898825282337131104146147718814280737024963693684728343106951613243104060628258332604525692902860639983603640508446128481801069752882070025501635067742559861369879619357394657103445071705569052494984305656799961070646531879901885986328125000000 -95959416145708226181610772323686358652590712687221852483207907769243123556771351440692745247721187358976050815821401087342735861806387363593580723181395214205016208097142206110082942374692383877447973758120544774424667648336635779045062091722036418632605138450902004335747580841349528939470290580974625932726303701174273250669729020798960633214901994881167838275884441514626658755308743493084646877169562812336002049595598989816676214171726727723803022608429351187862492038807339327394635173403145219843470928706467673671568449392976376404478012735745610183103078561039240870563417159186559046615788055477236062553408662926550701465968689673795549931497149690135400519462698703435500169464106285180681541518998768196384012779284493667317562004212222584868859487900658244237724505323985746971704460887921536281613227367734821450152486187318841519112999686414254389099214750779803267846552325635191175568012983483390895046433102314989155530027039481373041364873290758750601053916460107763219617903416256554848748016254805883565480830568332612593247755588506762181794190866628298059335843769227093145083611105158904463717842504099300854869979953183897322995586039339517798617473594742939895192530481072831040395416102784318757484556732068452380280622592210669855873772863204177394718895681495909420295682182312815114554542152324398042106962840043065475657574960315863533732680054531242064969065452828544948715716600418090820312500000 -513504436451988670269015311387862978960827747103522924891569682083209925267234919890831351491693992492876727398538320545544166433403641844166878378515798424373366433991480914273231642441875272651590112173080226414275375763923340935500476040959099448666010089784386472983017767821700352798380378318127432577994527340938302551210178010000805885977404609236815027358524565999157272090371799352230049749749296015410943315530245687608585544201527647335773182778250971924175104943120005093987548025452312058065677247464002851204432371041570103639101031757816023962344463023825065214532943678049676057678809196193735920021255457370431281859823659881541046737572925229229266835673745284832070094721272961389127736724163824000088625530296750049909431278857796918055414499987754910530526138436190620180816223314760360177925012604598223663074350697470266509904741537948084214226249104138424527482607950476190285635574397047610874963770039281383462888520157704495200396333639019519031493964921858695972084429734159359835949473717058472438936246441078514149731929459377987108452515448356041406348178445915716056373203020972263419363636303214252593161791460413973525810512082613695995114583138691726972646955450399122667536557537792471069174125586130174591879861064950066167821406248680448423689157193053123771290985425360352266546301901086705948878574626363656804762146753809536641205236261791748468563678642340164515189826488494873046875000000 2874049873618691080469196877789927781302191024327696691241438470759220018847891519600324751780430193323481931327063393085477961475786546591039501548342451824288802615828621154303711451849667106731728893471884891654122870945319501961623195472127997578886696231748860906063323529804348019563446905754387086120267669990427790970154451496759987025893183773589590569236290832356755090302335908190527382222650590534574151794608462645798533740443338472746417204264149491960502404655301765688748951915552114531964531034396290970348468663978370159760891193609846341791419690007813090197520211001384227171011533757339198557016141637852793751980919018593057934065731121117534885448393725248309645795410822776901288705512095512611590993218787039840328709099873804737452328110293854248667393978233663736192583363936872192839544921678024755749251077520430988147857051696475652540253353387203549861379560284423623450593388823926457450867871777848565392075887561292122064602805848912099359445671137525574304876401973253773426939537690489667092940974978582492967019628078655049928845170422476857984988702502269866803764730140471715753789344617516638729898639910016185061715888475562379205129945459949915661139431207645097192008327027412741425380910433583330442147317320105742697119293674124331263824609120856741778033144780414829216047503266219045763392171409690269375906249541806150313459822954020182053723291015767671296998742036521434783935546875 58170854686648690408240209854102654876094651808367418470062579229469854146563303452046542407545255660135998250927971567338078780290433712161501427723362293428478404875544605006398665812246028025094260077172311571419720891348839567073145013381225375349276907622190218240527899479164796067741084740711700932469130862624478980264034950317163702504113197034485795091601011361783099759319073660904737446684720684895637049555157337303121129562636978675258154225427524792856938428468773030191203819404302056899381325635691191765493076440166633338149073226661234480147672749081656279842432500936480045866772528645126179327384357524557849232946969672216513484992637091512973905482860207910542987441471486009353133804531497221107892421670835379339628941461102226941108001909531253793280183948893443021594690938065070521223829433875162328971344275839120043757055194698528365058626293771031122874948997238986983060828947329387079603663704985425953752374580088997678075981393481755320681939344327789599944397540186931145741955383213516903608713465169763774516866808863527406342640691039893640465471612743851833289788413289881918657112197295654067059074179579812163601039061056765754208266913103402150223611767915120472568407128567070277576424301334087968747737943037864230746684837178972786165742316688454627646977916657590020703182291067003141294663312676807114342858438000747431224278240557938020403438289518405213129881303757429122924804687500 308685521395497613912054380824473270207298760600283710166810533072156730031172023637645975168757380259162143917015444767860673678144021642612352837021940329017371078367555517254251171206206017942511172681737117957914835408302346617143654322687467005484660826931086874422373548291409301572259951729026298086485123758339850090385252532438075792227522790245917432752663274740328355855651943407926592359640025693444794264476122940402737236492272601874384704574314991298755663636701578099987524631860605303344139706637968879396719523655482474326993682311145650667019720394483461679400834747507196411450305762008767501415420105699645539309326998726761952716245414258764699933739397071688441171042955236888000700095368370582377736954872116903331126323737210580705651772594119093733144885861415344591684695092688518390603367391232709196113050677846166345382863393489705865414438675076804240913554913056596665464844226277446015217863776398403495936009519998689296316174343905790791804925083625221749248110361377180354806742944689967662298854285016434413574158048802111975500450651681658632343244344454212231373555601592019206063429536758526316053961128280754240126231793055259632732457960099712715495295847222849152490839553369019176699163256144157609119464495838387500270797289514865508778919066380756896021956960574252467862579097549430986155913307430678843550996726564789543452863426722059795350968161575799797446961747482419013977050781250 -393889868800739648451520368432902858126403544277780532475505256919611024450631361460961998822501114542146589083869258889761710685964193388383258385697855366034217696263906378278176659521004602429063544867123046866781078310277200121933458119763811713071462441954437288711887681799349983443725344189868925754831219716223690682153052066722028670820132819651782534037914288810642164961649634817549569600579936139709783932821908246064600395330092027954294208370093202847122400810971277695165323634425512466997167019581869343750529781023256081876332474852156701678383107420557094092644491927034233041811297210647882638869601705679508921133125155266959992732854008987827703068611463004729369511507577864941334153834190844690737257557236157047938233951127386648254466958212527419479854777216137235425622758386711670517797439383999739714935205628924709222499535382128219485843862275029221941500084086871857818754425285153399325107164775714234121828988765399761887339526189255056209930638832514656720548068831272965607400267951086266063030165440496003744193320647851673884649314091040878366611212950183321592150340038103272180360401733820306632522550196173068521982312234844112998410754078924288824800998520617312108270373017110166199840299718262674854697666149629559413984927340033662992001319526299640144950275926409111311552028592578657858904089995212564193032146728461116690412941548182885220818517935104097205112338997423648834228515625000 -15531746847342672541282551783710137381166907405837733032287724585114536187908132541465497612141900418375462067433921348428072379572067404349082532998556454400708080540625995849872019994536490204252885171531630897399772845852578305698912885475927395084634418377106019658379654810735996817572081770479017569800725437812258569866534174626380052840580664387342284204747396152656242054114642373499600660705213238730577397168817273432270661894202493651669038528114128300236817553663886165856283798767209848721307894858190200508459109027366521834027200135670787746597226668406640447955919426715164463131210185717709634661214293763771428292109202071267726187606782895148173118570039769668580069979300846484770439674844407251633274148310618510626342033875889454754372077865985586068091238482726972574202779534645268613475697237304285380367642225957184570926507786696756707686223705570573340821255830611026132164787045028310457159450634762047169528333782703475822107519637596099458885684091359632021488937668423967888939324658501643334447970515127448347348998070330760866982625517093346841673447617937232088785339348421139277271465351004048008074016786290559316329786488822347687213404564552966421667018369118968643609813769975860914511421009624434022557676772873794993820207601446506885967987735435559033990007147390544920062479972537515929469796109711460510152613793859937341857260636499964731716859410275144437463268332066945731639862060546875 -98037649372612066390390038623014452502922038971115036941363805457946305640128608485333090443118243667662617488373611465312940759774328548190279278096130766745818110624111474838390149631189918013906812125350656995114180944762574587694851787547189519391670906680508847743589213150215036515603295302849042788270060917995511568035293487442226362066272798299755171563890498265391554325189024955006903234200558629111476600956138103568757203151969363221346681912918710317994431650459462424194915554868991613817489590077309028059130943271284994450465090086556753425793478389456306750645073078028423006051488927133888792873314294860883907723807594548230524627698683330558507307909633944535491334365396853346119834959696865630470159535471644936113402356430974556336204618263919544328315247527227593327928309678963697952381455402510332629017383563927626749832984695434284401994938782959802396928137958191157587031200445694882459995301002901192115734949743544521705590957191108320095239353559352251056082878749370995392738677657044241387057216973280461264231777974301342895383418054110204177779880450833260725079579966165833762951207433907524851849818422624766350741636349439808826290426089656807520678330415267429658303889079667373017636522311150810343414834353970799731449837652188433205704222024630849611954304890709024274783695119527920860645931971555753040563400965338816155190239974971088903606347784297492253813288698438555002212524414062500 -223379769201309497522548716746954077039384525171786911412955016402862041080722828137663740526848324232066191884020560978930682814838610322944184258311110903553690869428034486142999140882302623629689185841840159259623802325379296919481548903210176390959851561057063852872041556511500295376765818875679852421385406820065907707801586597189829509838923895844750239892330166212667162483224426575265536679777555815997542209104911941243616083618484094873486684195867642922070340154657483788906103488673680458059065722863494957957404781986588021528106709383337465640696808450855867526180332386161027003919094635571296268718409804860909457049730670949280625593050953714265548284466120114085356748975027927837615673563156953403732666051672092695358270678840780436978277130835501324626704786352263693036555544863577083998657889120541584099964831316513650431707262015563907546407039113181012610959572542070425704952878676333242364137491288273730874296152819184547765705160210265958500784610403085654777419280547512444195794671906027288806919285056195121253407613658054974410923542872156127588652491886858795134814878177579280981391518035298715877541832173287426677282175699321734830691681275609052961425315795322252963401463026599030313105961116745505866199570015436305875126010130029947601578841185454394267614953487435091155766241112346459567811677289823394101121376574298904131133335238201433064911607950797645116836065426468849182128906250000000 957806909697561394403437029769242300454501045664643231850324769074861733156165576819433792158016603041507072272631733939438353174235683628993133745831032288620750857041032523474060930601736028567268617122781151995419073938831542550505499386088850065002302123762572615899066754030335820512387158991020530601338366245148618867979484046991491526170917849925544588844898534839609959283550954050186186196937868828553655536437817044955065797866316219097106920013416963608051848088484947898306320679743202070627231211230935653822454749122721559287676208680043607878529596190205190036752513594800111409838464755240017115245896183306749090647219371542504538078453269767057707797864003539204281776900579958230872485260732776811790925712627113687261179453976684921325324072672133796017914897594214984961742531246758137312796718111413191723160420102462435567300929624900851783646890292717808133951350081719039018858288545804063392954577631862182695305260570850906880496974142926475069461263670444847544017850154685288032810165634781544385166845498648588674744937732849912585593934699748578745879314361991479762144685355195305624601672261307165012214354732676108740860574426295644739158807047546843957672362516673913516083820426566397197360967511737475493751941402057890769953503675613239388409191571054322021543094449424518715609897459543406875995271909138025676615076840400342118217399530918676969880461938983140512959835177753120660781860351562500 10956271303562889974711296801110942478388223584709604150875569682662215096127939733306370040772022031134287153622256506180575420024260212197256151753934360917265743310733962980217147732178616350328180031771927342379953499123060563159005527218598211778318476278799956943199064389211005252292745163878059892678864238991118551444438512909174117202117587770434976248518583773343769645879306574509663999390537584399245824597711852249148661304136283748460291106858310966267810574603322404231815585868316852068761336972107758700992068824894472350362766233268199010708674670508338634365508214827694637644759874682733847329689750942450600664607547810903769562484458156233995421568159767751459375211831996877122002573605412955059154303801765229617401145292592959851783060640946314981905326269463958634935543254122369457757699400034753570082709331145865161936621581397016488955497005125358513908349765727831358977106796064260263613124487908800268569270660347684631145925414978861088587980204302963141688938393942805309088132532560252275294022660753186598131865361294775788139194533344605681529959276338070447671237793760335271073829797568826554336108393712160191457545553120534479143639317974485438287309794173905703085027396274538500290998868263863464706233127173627681253113048173313757195226618754570704577567738219496099902417952280742732151876376069720617233857156144443742342519381253720484423340558711133796432335429926752112805843353271484375 48897650445534579996404540197387383491506128967629003780015878004846120159693540544292857018463996461613222358659156863009830224828565275036876017189273167054441181582950100744647675897168231631304582499266055748862326904077677514265962872071202802483536191063332487387531221994594929462825813181257296142913051344480577585469857572511407187758996879300518621054965613638547910292017934707312140584331433296404753369600776945215846642958118833546535726810869792227914500451343044647273209459361058250007982288331585921139351251033254606890858394484204486668802475639928442546949558933402358491758068480105065633993015784180072796777686685275342732309310392802046002636131018473397605601118606564641772597679922448017007125687598702506939320916060851731987406163645045301189155043131388619606679693681216125425964486750239405847115814815556076382827463552201526808921954666076500757694556702626288905165351867352927139951107819906446072043345036196321018605438343922324683310362109010307839070003560881652301471062529063704509044021183212515827297570410007049898966621926756595568948989930143012760251205794305352328784097631582206353291316742222748517488309737344024523544834458494230391282320783020477771005008253547009376756411737135545577016246399019134772826426782799721419421236557969375894143906495748138717339314277547363175673903188388210843610641380106810726489840851312318631666814397300491190634375016088597476482391357421875000 88922685195817280489890268370767602128508181264086054627595728109531425554799760126260755687636699603968757898320184163321901769493960603958373725069124842102747082027189491224366201463799931976819354188961040940805332024213447147355406908385986751165302531148037624623539547676993403361555343306776299199469329222930623935622160931976695688798800184429372371277554610433725522197385890274427120161861156022796238117328908649313342664547613175065717152482239426121629021993266977860567822480789640683991074027648112544785411839932895999146479443042561476408209263893695895609213956355472287880415624557781206854109187064123612025707766385781390677326122661467628813067637400146876119107406394359514012814837274332154180293603407633409423008143982084703800054334346010944754559068978457855444508230716117750257130467104590657595487974036923081055361350797438516476524733785358420402004989748908858841611795563914988054689845287012082267577789200991786213569098390713283119903205280585546776896933214566940790085501017087410171927983787470954246067920769660439151926636037275809346849876585163895418450685153597738196582126618598370302856336400832806452233994813694258396378390721251975559605609167578942226592099169403671014084882350944338353310395634340145436423555219705754799761664645011456951567850356446558330049798730799521681739264537733808199732048690221210338698911196946195376261185054590427401244312477501807734370231628417968750 -377148809178977904663876191303433607978700254660898724579372922595966374549706265313973979089245161483029886714863584616825964048166906936614060073803936247373024922301314516961045313677873426945738980394043007860804663506302118472936978182189004014041406431369804091786272802024398842362607327576773605081930934555257797106026994487670053390810248908979376746793050290549600913451366397888393624500299980057606469579041046581976007045323484384557948734967503196062270012206450564429414118288424454855016455367748907930857358555094025773053856123312895398505668017518578899478832452037506365761981448992086625364403479636532900553126648093212661322188693141419189549835142407946835980203176710700409965284096439982564721300363560515034188367084314880138717204969029291632170014223571631848963977003142720563071319357490856506285339879763109955051366937047164278576425882310672319301364057791164677052739073403632304247616747529243286249742793434241842801095580406986811745733214977583710232872857750014855730441352938712351995503067707863470350946000639288399482886343332443116856873004824933450231216908532861506789563093166041671104036386446435272091538769409706559251372161502388821780044346153473739830139102618311908116817642057894970444241776570029605803431713917158720405730227924639844803405906051904070891050266274961140317394301491159919606282532907794779930709776923314213759504640065874786492017278760613407939672470092773437500 -3612763441270530138126986680856153803820665605894988387715100577255181562982428635977238789357019264706502710380140797718294485345294229331975512404884509937364081048223944861880126794475281956663894614523849941534054228635590392478944271624322661425704617426426887663333577148459882155426717627199410786960743572197228569418275607971552078979070099048904869719198031021120047682160516798471173452784482030118790769745689737165698479538904936805792016609015024524184624732144660558631725885509012618399627809208257876525843171580738915214771630096661247337871909543414668628155642608439792743010954340672072447617005997255424671971873323713814100084849134617087394203430482276421746775462125714519054188165686519256340282373182646046865983510608668991075136664635690549594769613730529586686370012300198294647705925672131398672864812724987061436747550650909483043372430070018569017069556957633804119383402834676482672559486219428469393713065416831616082884934281827976619780316329599392235367422148082986615450901390110633531189875347821469274365227969182467273311567376038070672069219992901223250582403000938195728444174836827279624647135207701685449668490092935430437102467554481955488722870384691174976550549837887605710933485303257398168593786012344799428750672280542832644201208262332769616969136482778792948250985902739743414379574489092115620606137177720765253031427862573139246487847827215395511701867548026712029241025447845458984375 -11444732616939334861455323984511948405810571393381947988440704705811784184177577578267287033738572614428987787603296715996226988172544664188126853530711864152370852650575217621764796655061276055067909384597439725537409116219311175924080083561234661648402271840399126603521632925729403182260666029409256663853869633583427004074024386331454966667726987804955258192074220452883512866378926089196904834501645933064021013235050964197427924136268933491356808079356407291353455588211166526161264892829529511664341619091355857271445639118427594640265414418926250655247683814045624442641393125967721827543345539437273251786282741818228392153468380996574515562998531077228224381206571884665067011043660005063448156652867950528434511190672883623210327517735254573680454357982775640470349655932874542771075402635950306302020348165688810183676804937598013705772526707428435302814576894053547563379231225746609684060374162229789982750541780183390884629180125419541041712304947503376016100477247071129887890161006728957382404953901398125173383508668864286630330771662836951794880405620129005351579550515341696561463778629636973309396199499089597339127541853689395359066890232543168688611712788373789952008511123312546697687688802336628518767885606356335556690172107432225193783277186718187048264675642036557170003014506150467480279671203778356431293280120932916901171457528208962950641619874846138748624937596029549347065312758786603808403015136718750000000 8190509697670585637876008347402579085816333368093364849117047448001084975685695024828033139240077525143565371519804089005261232897268260403591898391010764813629323853071319193064374046406956641750225993526909973763871817943519178180800995544281134081945860372760906129093618138032173026229500578658526226296403430269643433639394145572503126645254391106173236256642466963555033197201835764764082425116696212466849582609878452693223666809634766741447365206967990637873304398568957685933344285962452639328996577050842215526800401959692154042465361259766680185228402082722081029101255380375848669542128794839012435796091519396173259004261057267772408041561746161416374866667119037578131189265084875286146150414914359440826288325066619590376325561203190891938655499773166074886670626359976851722439292742895267252978363213308837473426357072059804881004859084035318490984231476528817580438349700386935689816793963648965039260808265318117745213012864882697066626724191852045414737496162774023004711265752463398621920013727321832285407544117680753574513911207852932756845760880305539098693021953920923671938410023051150854059025167246814375849986987604366761778755779152435396334307558276336596544724093880504986472451634865129570488612121468325293114583594905020615634589161752748873802405107823924528102800046747717217749557410327366525299867748850597435518715235883669689005744193467487055804589300006535168563459592405706644058227539062500000000 224958552736139683089261390712665615787585725573964337456412554776162643819615443424926107285232991820886505191956919411661745460043896032314701854593714662921880624046863012382818104808869558700499822040706853647207685910376817774285725236243343014068671064061058986665690578369463318119537702867555069325113084456202826658781585822572690638193687449643690866810613846339561493888197045740750692433978607032970496856163578350537369981627523498438083538335694944015710500199350502198945122636584326285292340893970335649755852542106463960234835997388979469676856598241491592587212188055984964769625397150632367825783792157854275739544821384866866677443505885303142673625374588752718787884999406844260698597474060684383823047893961945923645276844574017996011538444297649454339363612328471168314164244066035498113701784896880088890103054069126601480897235083537351810790466207587774175542769457244898729834768403026682475341266288547876737429509180117612023650381093521974125488168232521222823726728404209676565827276926123699386658403071226175980547821206566802046251207932595564770521396959640246292013753497444771934884982718728281917736186946377696498414743965278874739386409767177245343359857695960925782925942093943633697068238851221635661597831116323941581839321118092328173332465684237630593017259055617235208781135958346312935405969858589263166744770167330975920720774231535691767403488264612243519025014393264427781105041503906250000000 845981147387695275837620263358510089238231204946008890500137205725725138574103083600339989789942139717481362847955339825847153680557490061020020605246555418868153964101826702489156030695682800049709451919977404067149174331925181976128845529131674122732504107309112556145505439980538114119909988850288215847122829135026549045729000769435012167341046094366059379495523368593426879149091290738521158837877246397805745851908462607164287476737499265034281440392410967775502601229027759156186470863869159451672793183487331258232249286587013873873794723974373896660295841928133454611136300105305777226924345931956332140460501293926690595490652344396716302896760412810526522077756067763849235412042851670094138454404615455774694756020594806589164162773506315489508231113552751989828314265490162730506203783712536331156525391036459596997090030499672673686239227387225454471388372956518423945595929366857579695204593799468827302742852983670214962375826844634598817920095543445015983598108720657686819297625686243299059837471660411560036923808495788746031241366697595128744310241823423117442859233994424145815370089544011839802883300692995404959454518320093709932285931448960627392285293498256725577653638512222970405635081125146856823929949453672133134753778845753082490385605916304094354989999646591477534973062956461519466216206755472193214195203236448531707152174042422525835142510206093152292568249592545539389254471984713745769113302230834960937500 371711304958418300720426724841605516752909759543186479959281830819475494676768809575650088042831326088028272149837974819641184056177975299638326664499084291647413624494064679605713844846035277202687948337649123272061720540932668178289726930472591405112675279608387065435118416918417227006029397347997163949477271249302923883253972384596763326407710509534895986899844873960615972987052762542665504960875279204259626905789263948986330981071844226038804705918543895195770330144659271911614644865004334456990944661317730347574390960363771629907665938506476144309904284509986101996035613358695552704854331966704520818699460037749525527133770045058756694834802522322634214010502322715534400993703807532300594581690948642744330095684860724119815830772540794554815466274395021299288000848220822577365455363936016500533111083049728251444000877324036715281673256724215644734467749292847843035107912527203912610342055124141922642471568752907485352493775033145132285275084139983342508095910219831441610642225148376741143856785905679800928568776363196893306819966175102524537503980960971901038794694659431168100400563567008864225024712083512718847896375095049685278735147130007402957831630632770310555314657941952030672946350775464914591467368900491748251297772431282420293937325353444106957051545504606021237814172294643231599766638248948187276182264519354789940823704701563448328644340121378244800720468463258935876147859289631014689803123474121093750000 -8922771473149204650854442930507204483008629684361135168951149962652505779421891667788475990503789581092976509020565579984579164755784902778601283971408587148836161115722390987762418492882339959892420321538273104691696173439753078255489186374049888579049565044728025345167550176600630975275540669138459699195316963971575534658375497011129668257800478081243035036516030421127401777986346204383514146915105755208817606046188551298019861477863028079995324556845702084827830820796436269142039434084569698603368055268917545852360514107178578433224531705651288533212028441529660302634262176728973052179336210142193937970396942837440356861223301568035155606161356229757130275863725348716991263928290243715899797417306333533545705967237693508783082372962336565538290553752246172454853086048274156975319102660220396376035903583366073218458381418791942317401418324764801729610795133185315005401681798516589215515809304885438223851795296489224296178761557900902747190518526473388015312809414052136729681216063611109357285688226925214231201655939718135503016130124826536038758243280035931107764680245186916961423692589668639258158604152549924111813176594811444618137458204549979675535170761041741392438892926965605029164021453157438142444783121564653986081176102168037327719569239374791312999798310824213017401203497620128901816780396572144498868998518918932487168937037810453544319392755182287023425243934737749983143739740398814319632947444915771484375000 -35224140929078742649602494284227639915775549698569593114083641888062495255632667616353976323884606551890451637090082432300327751798798293341856360630950128039082845004421622018152088541557412931767241098423263761832266516120223531220230616744507116958283286511434735465859686719170771583646775814709132430305836758556782051907347986094369916462373719502255030387361174252497386672216327191899133843385444893462201002396986224514070032368101616491467902938149919264252588159037299883597168831035276862781281168769638893788831185854424821374599661625792930482037920078441342413917946505822792561300891579427136412891872760951734490232186519064291882382148433436363582616587416952536460146435332187729229926709253065037440587205514674365829289002882270563812756051851412390389187446036439612526133948260697071766541053288737240709642143355039981278025659070707260796851896066177251056551812061934982668861807301950790687203828835948044513881221493491106538275064849852151317865054658609844548058308764388639985788554261693622682498917873247076783580921406974256812744806641576324693360788786402709990251500289619613037753920920849688501976743192634485829382710415694620390032676540802860031312141088244642965823042664066548396381668971182532467001143676715004651222420769278037627111848935739875987137164172460098027985808638487444935077388900265416038840764614167924115644365936923871468862614322523334892123259010077163111418485641479492187500000 -21670077581351730953962540406567863195896132579728818848810037049371126260762348970239577118612274251644424740386977174671400753236006787108430388814642115275126171231705210461391836317923516888885430717010992129972356342557064502703312520079912028983797158932621580314344620727920699548901596633043506221731348051938111706043476087819431007372876996339945341034052084366748899156346729946063320843594186878755986567932791913936460429891068811448602081405046128289622452026328910645448014443328646959924129224681677368798035597208147750449357625935382403278457198796929760171509309511833524983229964244708374009405283035288981317838850494365567465118351633548041489350504900013447479982906156930172982780584855731493472609535858488853221938346067132164731878711242998616042555518287719246925618689705485446772543211568076297783193885778508567921473859924077448445171177378092929684217434222720050696768512248316591418108028700065905069343872602018608035442840295525790976536171590548955516731913943178772727216625900633623437955985244068248335804904433440727409536372069571936343294805096287040710106876218640535419019949437144549185948081065476541436957393994306037148566676654246398991639917936513692751226797754126586369920241752869099711774486537643290497696239405797051709032761065760143748877971951842180590367235377116700546757556859691952438265405644421182590019634562371765485643817523529611798055460880618738883640617132186889648437500 285163887073520863800008026714786706859429311530733837521886129648126855470300505521631435889850418943506888737626617457151930006909715824138532034503920373983198723578069826714310883710125358083200383393150062789333208432872307317901260818652651387095539393366675885690680005481265151909891503792754091485687158252382102778843638265442162958648908472080025446102428712879141388325348987307699890107269161242016005492171377028334121672459050077404851142837741279684869421545850405320542190078391743585102145352296229784299448139753982416766090340459839767342052621810967615989983888751453168507956055599187693736603135907684748767975490671218173411790551210555401704762074671776959717877597856411047633332345243130174687355557111870647598859051805623284389459885261703919193427472473296272903812593058854643258277030800495244621468703601875621029241408798332774212549340926892474805306515637445456445577191828831577350695278337066011533618216233850184925508484853007296601352595096745108685727600723802248939693754978899486797074610678019047717610683494052238626511517684678347717342054711475907870035826459313818514940149277976140598067418767800687859912558514320230588288348736802940467910201715857474497780220956240365907715785378214767200453694760386403645364346782525183128163540321877347634064547917344207602805646701085888270473149968469488499332124065324161920072808387186306563656965520594166116352674578138248762115836143493652343750000 1086114812746844791432369020223975775568844797041306373485395340290812482179418864006492860511774880506524650441339166894100948736325571366014668580435823553293218870166138196083524804809205033077836132909507147353038502675575943912042465112083923274565322182620065378446708112417286360585795295854796478738988492891060916533050792052153241157212166778378502874801703313588990771842282219956772324965487934582526469547775010452294661110018312733818472041645160532779126450125073331650247602509838537878547629038987702129794488634105798128823155888915343731617207899130158392540698362608754249625789431740702624261735356365982416246303170483978554063780044821451604951992069216501330770082520298904066428910621874317396197049503704308563947101549763941206869943535986726768965291137677375714819018906097224983253697949619091427163338606201187059062526404239337909739530176653740868933627726188230404943375500884162673227356076147820211284175143862588068407389444739133787571337360968654037727508409987974771950380766353898993967244279200027123879914986533796119878062130675917058170330074378334640867893435099389591653008228023735822044870830482976202881194281822300667289868822280383764010348446826779183895705346615922934770922097348549386928238359580619151985398353560638363760955006559176399610648669685351748915172523455702618813458895234737217122331966492525507401096543479599048560317163880455625102339212162405601702630519866943359375000000 713838383920560867945137232122936338496399912771398794026285719900045733225982365127584426911179702290041303398891969460057840376580545804264121298897242919934145071437521152981444071574256238187503260649207559193025797094565805045879464769184186686172303851286084636412005368084234023875301837595820827844027161984146184013535111228444573182401189130548819439819737550648348567396094846572507476595589615216856180550081924618217827999623886357787041995486731927865213617844603030281078028286299432263666555895679247969846451043594892326985383474389073103386148945816991382798814912820697090890377957211217858424027657276040733135610497166993865430046018167368690802598439418832971017238129495842544419055784855100204606112106754010933321086074909034382591519828846983263214830946195431135678979544946536109409531204010479340218627931333565010268898373768907245046260986757452141765227337506626967788917581685875714691640697436012901882743976625269740780525223292661395947509426099324713747691292642589121100984771629699925797917733062844592700705411634290281862580170323009250776008682869546512091462684304614332815220021087545255596489861633043711351409622714109181546454788360773819194849725696803173323507709230937259931567721156612551670297911292844483670086486185086872361429712687756945670186029140349046144964506988894165546817789577258554982663448864320402268620117528766032811535586781768536815406811513184948125854134559631347656250000 -6930149775103295396020191260123235613046809447387363393527551483744059385404354333584648374860677527635799218309382618597456518871814910133604821227542864961070523412023400290935687475170831611103336398903153162339894211707901525555338150968631447023348661729958524586553865227683263333662540695027829254565897990892108298391336038364810870405054206848933630780188178258927386952106278921519897767510568209652867134019002286615377521733242989989190715739017227180298766658094190392023839153820298299198714796647184756282410383016982221105717608124578323735694205911895367029874304504243747408751222093776674559125946172070137301288906125638160375683763696178806044961925759736066857167063451586142294866024655022841394090709516290400575371869334248575912192419831512306016651318017428476533662396260466044499002385865538365771489686635200709878577152126261853694267618889872668301147954997758210634898485828260220320440207515951181517961110380229910446231589600460119419993734651893619714555628010542166047643759300727220616080854814317722725296331555999120197882069652247546954967468531746940820915025544210719648125537858861355384396365202023062670654680694327405926145330641448876271734272827674031623581370670947070742909286731285640096557171660124144869435249569028505940167685585788540880408149420853427878514979141857655458826612117100775704009314380222299834183454746745991089315999602887338065532879527452791990072000771760940551757812500 -24612002510525705057365022202392060405643713392991305941275886538669839458405265738765639607445144197380961620235487012809940228391403290396241991193357026441029724534549672883790140286004939918468234524387759774736353177400008351650999428565221654251016071399496711971292191467434695097053282997537946429107198490813500858849695369604761530834838693029817406063540637357761886755031101917658546373535780873376172979084988405285206333035937681917935678939664141308562264431827136127314705136825422425953405703869966138250261562117160550686520466498037921609956039209184722799367675147806796797568941655101247513059775063783362224631253514874033554343892698518956443185816820817987509891912165066103015742950190396371330372217719958343879736498465593150164377551373037107119586946103359255886663516238814700130576420074736097596506815712824478794653889731196638999988553632879601920185987021993767451231978151103517480483358162251537113205108214602338818164966473931321815395706349745369178870369443892218001010654177258366079153637738456855592645957974432194387409863368048421653567018685153527454197767103016456926191135703311095177178314377993884033666183590362070032718377668734450980204061282612089454255505809041909563804265230753034000802953240160939323361018937967588099571920136605511029062715064341224659072147464764144243359230583579655179090632480720633108916798028748642914287005220475999713730663742694559914525598287582397460937500000 -14783515758307103453421674074587164293719807793191067296957148665717753604388538512651961332584364845042581124262231546471572048429444466526242261351250446409961245737170906082644340673324703990626731327608419236298916260642303525204371940895279507128740990269659954806548213274230688115605787975799342423533446088150411921772846664579071320935669065256832762341160872405887143516698836557106300042434171650890786495264577240068510233205452246937917887944991581870863425452503272113868877802941708764430854346998880759236436652720203199210414582042808740186963274621778090722646509098494684258159592206772061883469122443353715954269147107867004872488733070559908111735723539182866880024764707912803289604123560089152266853916619150231991764740745935338926977822864248573567591584812119265365717636278262300092930072289272402705077705737973685506448305266141961815175624934133679132306275715563093780926165083033547948423508264165339384005097440344969448291740079105693425309645875741596881137062598469494347400067462844903439326352603412343558646347555924152529112180568967538539912075771262406520909328599764716086598344752730979660626429435993654489574905263801854729400793971049483324324755465669056805415681767672415528044025339642134966062830472348466443035101308101176305022592013449255467019647877456481690872740148389146120660999068020842117488171646785873890495010718242518925136587865692942172536616940448084278614260256290435791015625000 132962210799680015107155526990681867782049535569826029582953060055246333321668473542564133438396639119648620596287876218273880827595881454970827702659807254539514711918200083076928049390638527192956370472133132887395340882082185558924681757953215522202502090922260459456583317315597404535539537961199586502715730700251138770614181803945910882568615113433388254935213594530403524446300954922952191495477638659304311322874270894167536393936691914739206417421003979568525087792233728136485637067486428431966858454083582936444699178621590745002208674312440256863813189658200993240979137353340700653113293910123001771463892736137108746272123085236898009005805514532062032247446516575697006007444352018589798020957982915390539398291734240937961446994148020105388293600689372285847231013868319209714824510411572758089557563135541608523959343366202976182729054545638022497236101039091645715794050225519242016641526487838087956807137573781818336076786988257995042929067645358781512036334118271986853949727944384381124377574748041604199912451968706900344756204156865487933380483104273129977186693929114346685054997034318603592348642668627373710434677283804956408434892006754603376647764256516760579622757202682682832348978828489601513792996631988766364827986240737097460138162524719138218870228910641578761949596177723517127369961322838745212895298473089748079949386665565454734814719108679496480753701039126862858477662321377010812284424901008605957031250000 438038637847876579087129629676238136099402461736452959594631059782340019871238432123907018015580286850834061945237622497387771746212661809890723679310412736602700979587314831983545667961592029239219113292473503393097592599531348218537537299783179684729300112081287848338261251272068242113959037215572652195736526804754822691696647772879489149885575765921827118494914148003976826977660299399600316375871876831682157948525425004148611286825311778412400625927795218390173404226077576979631883251489774113288915250915107798211417779817290215599467573507677346131640289265018837663415137489313021319076280771929245607631360678946885756137268572688680273386461197891916492937844840914795024395400097788026620475200991304661793992187652273973237196020725370854392028076667050820481142170316123189024745912641702267492478044460336011172240000151914947509217636363018633073745495077794305705519879071324684873731729531856177554036766848086143085159630686965698757722223530142900903137354899908831223206743038592843153642534706186142818190444305892918785235374826151999621864474103013059275816497374690743060369814745141894083458821767128069290026926251907589853658204507010143080190553639395173519593185036840273091177155755468712013428495191251810910731032949414594712718304839688251138338157557641005019967742119386527694994437152107457775484708519086550685908304716462018110142065602135400017368040952156988461930336997696144862857181578874588012695312500 267184686317548410546751094709211530247471834553228326287682444610282083055864225118823827142937192493718167458346021417346928370353578069988774305353852455334695618314630995035230909986183384575539062463461813001753997451907348058546735498294175015992104886929773383858870311733692017455255771263289359416575098175223575753314376455899443166226518807030187034728800033503022611303927007215663042297080012037840915021813671163340915378940677355582575657121102809790777562765739430727168417333363710843904467507675490429463921051876490569040185845200008503775203584601786897272083613610146390364322062948344760961688660810803566514125562634038265958812608750102082100788908504438480767299180829719696078499072819772082984963444131732205129971078462223378977510855623454019426447054568364740950069785350757612424637971421586490307953135455660389578147285459050996731451612311934128323987512646199721948991602305947870114600347599323369902480620510908069087822746260273327540412158150892824281223500606080301820920285556182544566562471475177661986643325839880219678514824733583793294667428810361448750083021850030014074100119211977653209504726042670286006933282351809393262829745182026748742996913926704661842468537707117597589480561926163410917902288047390082118220600655114471425142825785639968475242664291317715467963262169306040042377851997545212192084724208572571330399894931671327992080537270315780326579435666189965559169650077819824218750000000 -1930244185429661110994758502819393348245952187784366672783536313993583433229039514636732064682029691793069186661607671775348469553190122121908032506552343750479647585401455611096459336754211658433379873374216807205500937575785726337519909847462613859929709150247376308211171714547245655080822833473211968488082590355152064258841260490504679524451293044825636869466430538353239028753577297314455942172567758013017270791126084580133914474045040657989115563357476453704913020018067620074057092334436035814030070459414477907520208585526120335349787603504218777336084669895104938289654307506324579522126713242541557680184932665216981986827140821653301568267498354483926750758301893505665869371012502389611927021800030542689284060818567175436322093176976995963357377336070898683139412262640107328661028281748831300164947770966606043988994384485395847535605646731556492625195345096318143526609386982915130527004165834977454323926743153116049260705516186845777304140618684545478744651265662790773661626403514813462488959545173443461158320527402594106696485339490625273231675807881815400100091046245489428342335297407028005666128149850445900580200528943340126576741037730364635426044857062637279578607435204486327944170667287763410443219333915980541492030704355134304068858165652215522050302662884279251134479847534718903368175105121330882015456424627290691236275386274845794930540108075100135688359702634933666789973649713374470593407750129699707031250000000 -6057098645545262018948151472360465071047641952214716104810355467024581169290870815322078557594786339827945269615009127217751496629099974942064325565820810791315570426977200176910362762625782430374561678568050976995504918279017053513611133779559000951451058693529939582909467360753716182878696352113930621381970895566146585511081836392818913369786949260819730048434087351040150910151929087390225785143809127767919265926164567057984225239354189361754968541116558069624314276212564923851149591038522761222801508359927144563723669568251326751682705832172244183820249400422914013707372599304277842951317207987722175060139523730350967834491324897583774897511736157182277944989419679446261045001676728782366756329703675751215959547441410163326396954729635877744377693953922813816845490654126534296254064406755421379169168343887783170131125262244904616229506524280025352165349045929883241569757238169874398112603978454847770252094762188375522773321161906813421769652605947911800237473854934827053755945075964862634690196885382935777738178049798004338747443425126277075939850858017430499698525268588281843928155089667053250628018209535392479867238356552973938534969941505884990330739004151445447533592998496628924782622189503076889087506856908168957124959186257954578423518153480062372662769620715917723823189334916457937344758582326680610011473861505585335206181067049321239834715116393037478836006010554079753357981097394713287940248847007751464843750000000 -3781824005729165821664134093248711897672867209276005316817388394964219218292826067921204887907448215483316534452169619206504575194694044904617289720759582809250291803817033062466782226156952333319838018686730307027987133692630340793673258403465285115887383056465586550333767923426461114269411156496989163821748761930428155609911947073326505463737679594160398467800888978396520190820490736654645988899151321359393443807401055605422154765144837080297076472556697255206918394504811207817383265158788170227789379193660141742378948918663692478979881923287797976389395941916789782595527085296236825761213264865611910951429157719806784191713653283049670105650666173673509802055149071088674906279959846283148672291050996018961286507182438516986904881936304257754129056776522539686458614890417766435798937614754580255522425018465568667221594927363943931647648155049329605686102732414034721139039526445478511352963756271951257863640200257038236988543803534548747019062496999074025353949473325937372346800019244725342542853430859685463837983431495729590305798088157650934529882039513486875152548115719977478741439635267694328725431406987693063701221239449207399323291465618918826593185334623371862763787791329153692228266086754417309499867991782379554946398524417966133583242566966725992256612972637014639574987614168137503504069729504106289654157440659048030196208102375538569153598682502895299623623354981622139822563383182441043572907801717519760131835937500 21474109257927683183295415842856652642491398371205746512163504860581215177552724517577067831832894097002343172443242733022897589815232739336117730427716143857596133057103587093988790853836763368764474441120104305583819045181581507067763758114728861483335058903029961678577298015652257122792232827683883658413822217492786098036340666356857656531549704664541141813720849536461624223746444732005039576390222586942887477850102312530928722222687706409163340438388296690234390027126293641769001812754593483871288290936853512919558950162413981741749596977128068375627191966368999120999974116939185105639852652157225288417341494443373478397757728688214842680857020417822128083322919985021625945230265740437873524751010880853077376928346568942388536253165388896776831114773496997203304311693046057429960262581804717811638505456872269511820679267612763644476906785720974411142953563644147051842386740023651677458681884318694357280303821606703954470479766769994445740680185661098542011725417166592990499115566836073519420039348029873191175098878528074808178597627570820066670054011504445792053071387008342796217248524084240979794960477638450200646866974042043630364945452987738527592660859230884605873052391776833740043492462560496703043562233242076984369501118547272683360735987047309032346197461620347890551753368152208883550301492036425411197914932650048431806994216101946606445380970642272129590669019520865224434982843071395564038539305329322814941406250000 64347408207949659097466413909094623582529976648619035194652667732810691082286519042456220021768445278357865466866001966613689331360166820610144624022539449188696041233099377277295360901290442564494800729622084849629674549108761661774805240503609419559055631190868714792933317938694418919104368123814259378119248018499492442543519120558946067876114057763644564623491902269204165691251036695586340170403671862938707303085598821541727336493852169449776456533937521596537628132900266591144213459549302152870686737717460756236821383581504373681004401369906042058162145055039059875652180756266694551663355278824899541257907788891237869503250907738913027131812957098551977431668453263186214830055217637535241375871573845703788151106600462704876320463752471882938925088374051883285812474466234869333205805106337826414877582400926636383577665897083684652354767884301859738336516986360650582702393515567389299284109638016659100785909278506301946343876368299401265939104409695400413880951199883883293005139202945387589231020350655347726598473511676875710232578056661155464023997608287904625740772254454988993207596555709044692023910414819635280925980620590902856334428078878383105258065242846908729988187910351587193473544579379308720967817909746753093465759688037136380032399582390624265800229228096528455410639158821529655492416072283987937136013696002558332895099053941709697650866148357740987575193517409721601671250545972924328452791087329387664794921875000 44012636157867227096276004862201753128752348543695960557150614130190969754737998744114642618921654741511755282992668021999871572161405990997513114364699923191499574425526308828314505864030984754271910349572810336345241905404653160484005683729499253121744889829400781060097872225310590436885098607401390713287419648715828398755253658574337316362253400459127702415078623667732542068634946363018254740007179160317357134926874070096268961934226751320366567562377061773264565202467941578492198784520391194453912548161068403321044525324804430679545248002154853409690981419901094708595741258211887318611168499761261954991315750673821965434497883960801403351916414086443321789685700769057720123099186003420575821120787816586203815239427728845709320474436859748389571653347984299235518563878009909458803431624440688293216462485701206617390852125842676718735523344819012136425080800687203295350000206032888455200949984772752129458643503391666999431521534466170771935970360736137010376686049803038363064799295506508504492124198673595488972897014269360836505269267980957941985994695136894170177490615002339921978001822556050353642287309791375558982724540276918366074844645221600310362576479063639215292289974769484988022583230973687321949695241836439371481655698773683927272756483960338515513227004410622190399028487697707051711808157248425623851853529441464819326861626181621933630506505101819260794061575166071485516045003194562923454213887453079223632812500000 -169116770242440753297209999409650114651297789605168278927652192490210746733660913943574392408632910352491676048649177748078138679356786346699137102184732803885087369349065042549772302613729296713600801247411650872573936413046669309253694722534833927763732083864723707223237182092925880456519790417135079829716295012468207582573243679266521824949154621586543341807083272022432962209737969622976917716239238893900535552543866742729919068304604960221994161389846375233737626011510660530617859572865472467564397058754283035208830008875527657021608569298011849346451725435394888550179570377163100428566823171676995078652280978039775716850157430819108539634224074786788729723688625159390540187134462757050845957443733577630916383859566241928530971156898773897217340776802894548385819876166796940770875589025623356879961761019993252525790456353773337732414685333438797825932252993396797282449425333851361168755110093685590660801584258050972885614520759793978840659412829841727465891389892515256564894657979280527745704886883830578353970405331631627256090893606895710188310070745923709137920715523387034464654586054093539038197283897518517014643772342482840318559654376012091300129872019250029588576017564312133668924489013358083864673003778683850153915649142608813271123804596301286467855253465178292488113630085854706209092148011919859950158936240552575642071317637010218138913264032381378244187758012853190480730917327756301915542280767112970352172851562500 -504253322523552631849600136068766769061326050467117333858693352783869647649402300349199891300624509660366570520779480561773955617531296934923466625334851693984566523460117733731081154233039345357525571974125234788777293871901358031527554765221040304054855186262306874171374397841863183364780311651411505743500745755075994623128929554510560683523172869969814774100527717871623662119967395655393707968489323275089946712478757187892635372042339057985730542508183160489574236635232930685642221350310142203712455354012210890694282822456025281896412707609747800644723928397271628905916896200889684891565171925773596118258913408837577180717626775928120765131158712053366983219816115481238459208867782044181590436539646485582209542306179881372387693570301720011849238642648276494950941237004436675174800241973467509242540120917079334258964564482880784917874578927531077009205713203139687787744969902477528056504643312872675670730502928447030073226495408890762642710231965448433876293209169812713618079106689944865332874466681049705174485796211567521830758671750090985155364997714643385025936950352703730407993847279934473729119116932541775250161896688528548769770314013998488200089356542710498340178521972293457900255390163633520742007984965481730597843665724651988222563822312595023807037052099899564724186171106062313522154880943954105830719110116233971440778316556570402807880048532650154968140933607082458900406837787322444910387275740504264831542968750000 -381961148345685633846459359274693658053914499308554447730870876896644643985000104020923298830277880483840356725041617420148914896841270945834737816580002561448936190888802990319042001283585046498394892055217390106276372026814843081316063763337506017773030929307689218199786221216173375382569774229838683388121720728183375556471910539485411743225520780783451839369041152078066696991591161837207305831051694981936787126352802186102334978060424520653539743593036272542914600489737168969657783442909547330001943236391252698823395883846220028718024028542777435099541418715772564984259830726081470847649222581547126702047566212585849135120483597624896541530856522854498399928281024468113803930110564291993395713710141247773229635735495274689088173593598159080842055125182639455592661530930595706016299136634357633763999233285740528829014139504749023570666939714485065715748052934584951366555501677690658655417690762813395719542570873108820800737469636295012204281242877954932137314144896586151543357384815314109472741888074611901437176094949900155700886297528969450477211386723162855873799045352397441431232165680389420650140823880327227315417342397670942085438907192453250863302773497658042675365210376381297747426080741198829065635383129299334699525894283007052112923733439372508534589892760000741730438149697984215649380089661374478411319924031242303924343545806275898632060313280231503946135636639776448210230330726489000880974344909191131591796875000000 854913827820886009556838597840960736129545052840954252125890704027051101492006397951826424157024169745525158799435823962406356804492361042198286460173063981885699977362012714609304940745049936912674378082648350919574644321816633542815875671604569410211949516679213698753110314443079617563807680825139304340528768232746934907054653994918800121495104412050631786225972258194690559130162293438749230783617194825003380431702441628532367577873749246302563790856903172459375848305882197274332331383247162604823850757276732866427197081771369412809303126937792609739134702568481750645248125830229288179592313205848580156378711312134351914535404272263760402336321689921307828572415811187845746655178615886600975787354131110750672587605930016166754822500742245899025499952580085571269431808850593003985896197846278042916708881724482075136926323591708322756229043407575908802953922711493185294737638822094939150217074223748233008569240769393589664766950168299473721169387259822024058572902591495697214488243807678194170693061384057375092454520911768918124745528576748857213984673666595899894355502126138382353513773184422712840539495204595679018210273057187427444971034061612798168410059907406502744701853083494259425843460320041060990250176714804869345186948814452427008009543432043311137808621425617709227757079147391639235791258982901646381602247028627000126783324374176444748057748901363352605424072943956445715758471481926505930459825322031974792480468750000 2457337958750969128944942707930115605914014529225303372942754699577308858127839181524343417965093785245227064355765699585252203906033662766174804506212147236602669677559663486912891066088617300114020245732797688883512012816744955228675891165386152715842836099591362843752708604334876029223291812880830427388824586539424245024005009792189051129119751134756137398195197548935668770910966294926498706742876233632458182098902023177104578124264555955728271107259120086901067519485915774857122640368081766810468464399417162869245734565565184007973274502059917340263346864691481979648229654660135809697988225284276721208166881952705431015024344541120287897994462927391632713027024535466428552317419823809254132265304078208928123836524849358094508742851634482364201391317839940697956459964347157934424593942793429368387326770935853266813800026478794317896993926359123218072256407349183464181778198316210560696108331730109815943418230690648210675909882636208149588497620616078674626563981616677483625274976286704484652874061691688025886121725129636006166888308037864020532273085843981231895329026666103473234616231436034972642659451954495576189523414756152077966879074188484429185397706224829585866932323818307454814933717212908915359697550704781827266164794166062695475509518273588384103890823245848074929102714135865166658473794469175870105956864131642375730576616851049266000304242067740046858241155453699139004427199478586274494773533660918474197387695312500 2077168900708278523351566292173823388056742061247391310401955961453455883063795634566481354529326428428249037851381217629315554052070866149895419529947637953324379308159627987438062220259529282213863567815712625942065246597674991350998523974568516165006172503525464887927572446903980584768598773941818982477234478527767010258397500392356725228844165879708319339086334271083234026982777938480353076371834084103463368750491832359551618737364394029083000314551428731284096749956244734909953298248192155933780691945739854829881018892531862171943795594017088072109877551894377190620821961789003754511233374077350674865260190736099659709073897691950421164626325348724121669010113512115244604367252688927714729837354341185474684462560126507917020035818779446046004283878869586330572109562527025199513383324025359943723100965478583514984172224111349507266688267118366346608348360010413934669209650670117585536235426897435427518449339127706087878229113798581007462936113993694462850911208204052604972552828396340779718547965268424646126095422565896589056224613502682626072931685954438142973949350407233445644964601799588335085661045455080288112585778417961472496239613946380131213779937333878187442752231368397420447865340988357462027872175734827949160896406653614058511184464164541541187592339354214694789080688081749861348082082540815726472143751916708880507214111668573154855725931112150887272031149881140983453568088501484112384787295013666152954101562500000 -1419236170965865056562508784814553419497185105033688431764800921582792226605862409825379824847336404139111108224206648692527100329730105967700388541092670848126722886397710472849026902314579192520708141542403984984842520895104679865021942008017884395974618676672122861523514266824909855153692438069928411638643361108081692322299510868146523098101135203629552085605078684414946257368972651302474074713264110880091796197605260082551014105942391607198429026869425464496553216449945616860036870868814735135038999132714644593101632319441281506064109217468781914028262043208200231993533586095079668543471825529633761253429206899705998949714183407185032163007439155235796839227928761887752732657328990693729769959163856130500426288450473470218198349319306707195431982720713693848577485825300063798352833168739410260334264551266903059056504753804563804151407087541629399395107431357529588606892124133124203729609583624796254444821105772038796169322672865184647512262971707525130228063033837974796774333743123312690171484856690015743209034103655479031505623943742988799162067934712290571105552725843201250806402202385243964685943068615615034519879601294414446664111712255934336935904284501581254797402944140914163430318346016127470233540326500891597192792458107839590107254795194464108028719055756480469274708696600323060681117700146421169469950956665406054667921462069789640948094184482437411468926287330030121451129691834136536954247276298701763153076171875000 -6028218631735310399853845087099433215449726200515966424928415892358447151271996859690893456824097751330773646934625850634966475117359869364454825846642840733141540124802573320809713155744469334427416723327066579693300881860304164699923233576302980184053224190910356233491958013657201971563755680404098595684061088968644751439311456936035757488052506137504807345101119556855034055519538803397733561495827421517924541544057638898578643506547398906516789707067013212838330687879024505185201326776648938941746358216290890656795038020939641190360463321287965991690273502750932335601746290655819592542404198687775450517899904691555416480811871042798836301318219826919294670995669867528903963066106784111227454123259558385992791166960665987891927459087191353465878498690281547044986287563511571230835457612567111420167135164628745005796902727791519077947154215684134646156026812389712905838399855478610247197848250007238065558501620412634449081503545922707614842329764746660111011072335593921656287630069585458824751629615624802829810174258322205109153774365969952005520669133461078571656311211139472172545380750302909230610367948027767568223409533757894638725789911152486569582356472023004041441062392740666002152049041123571845407815381605988506276769597233051816147309114175845813758932095678649096255032946254285416103148225691329475468522455057469621555119867563303362701456143892700032332810377034341531283069895441606433905690209940075874328613281250000 -5839637087437540567812032495250624500331433600331901242349555448932433017397723372505399233668066019174874060665553304683332241429106072762461521615673254087108686968347714927878419536419612551918892484626425892364828312811778923707534017614821862385463453533151380998278441296383129691586396940593340606537183878268499581386873453655387414589963468301808639524043157413718224199611709558018234859551749679734877276377755309275783579679991936172806100069663094211518766106604460547206821815920315816756788866485151074495883172766345033338811014091680663481469587418479480426129215609716423105040953891820921394086474677626582002306127121945744347921866686315596638005645316093140602278032269255320516032599313680860282653172404613941341052509160232395766379817262947994984101330072075902067455046146309718370113329301670774264995415527684734805494410662753831074655000499243275748058757089466663879824584102241421893929578871683340348337056942658606340515880904597835765100558342101103055787239601909923614575358111632057410174518399125560143982397220916753751296683235103342708592187328396646472756619811120999736824636471103863810884461836535170122948175953645408551490528947792819581310750054175471517079419492961847389218820783119024669388493086849007892578733723158092025820254746239029815161730117402985868113052112537640410723040002901654525177248639447071977691035405492585306012327289853319050472884883112856257980638474691659212112426757812500 -2201584772758813549954341586174100691402959942236760374769154679366606598196508143604305760858884998448765767504397256040057602566475815678165978779047051560511045438557624126544048746242610015514012687373071873822842882219657326742297465029164821176165008929126115413855049715582166260098315034361631532618568636412140391525615413488979231569854584537196462414329677578673226055444338622456676131976537632134524963386097085021751058429863652205889164133476773428229965186750041617810461708529015133825039512030771840174183389617762066214054753086410933617645123616652727126015387811830261668831251165551794711386574085835442713873831103101800154974397341678159236315231176215508988529997758709912959609717506763858390147688473705388728443529014122127440758663344935642680556976762126133733997741890825404709502704279214816681268601857763509682242886557069388245832555005124502229745325985865382551520554791193082947696978774092066765856201805619271743239123936201953043440681531613435733949794933061089307552726101356315179300197402731113742782269463149876260594495332633543152254098918459431826845364918965906854338264832972880240142354272417778713323441283959953489876279354080195889595193411340563120339367326765357898046996718630009120836523964411821775400212933832787248361405142931201758246672790843842116456912063150392048201543805770131082737239040962343936198231792561113404514463421613225266532457014001522566104540601372718811035156250000000 -21514276513803459068096848820921220552937590042036022693759151418723849129226112903666934014513938448978100401095510656397050093865129220498008102216100799736869828030633971932086708955974832549924270272704115474944732548747419054256455368537581513315263972140480431559491922989441769204029369661892091415339386566513117232490049063691401675213375601726980912007811539893275429674228791997402274848604633939002881874070714617944334020880398261372264477186293612581288499325098170361216613466847542969861842876961867387653334945274749664739991500843372552569597677877844625218248867977170345305013249297220878635950764675520437852111168688108803629619358440271213035654489174206917347916509976771588288849803680303624473968333462264223670869116430339344246950343051909150160337038124483021234222492157720440162034668911915596137011104757968541760214305262496453915891533848246686517022962075850187669318626044461349433773625331399393606862321320092739065363520540311525088514634450997350190136405707550539010729445357186181949557235405891649042258748842831703319215365419515797868538975104393790189864390877344990280644956514529872057191424620425649480264943941716303525567650183855058698260871545234496485442843134135992652101342416281928058550216281213661255759489095801921837789099069506067322757247128691271403030388872992946864238764295101157422729392727060108793225389628614255802388624843470955416788875647071677121857646852731704711914062500000000 -3873448103270162139918079001540329074141343177071161625744834609024542050623825071049976565721518296772644550598839944093668138509382546693855761545697602484908879612936561087609434645754488108467314977521748737257708289562635903956450653577476466087946558647972513397157761626877754171478969945875644016065758171807831237477732149200040938968351325990914596102130633551247479072004164071188469210095302384193326611358721221534526059650209465866687906368093552620633043565415578049860571570697924959140543871686626856019128587228659011622977161448862401595384564068045688487415715583428589925217128220030395457597805796684140315303442416939487272678914008096528533644415300570634817050404952550133975528306003200419974746931227967975635524054725971430762194668754008998437421786335688864806777765025687857384261111600067760949552180864628503518599215570481719344203744774732809590167718814583775360971657179339361878278612165680061472187801783874684479110771223609040090784180680724593834235079940880861139564275088572050571701134111117220615169806679710024767543530758995637088452974887508833378866148748824121111053742355374853571004136911618017137720631882643625965276058181904194331902408661059981417975717418429641596581896189897394784020581211934005729433600685062874121637361978259998778114538299126895261342308985649680459576684570549567720817520886243021746812442648957280019532047499630957591203531120704894874506862834095954895019531250000000 115114012060472670647631142385929808804866154038537455221996156723879248316546780779268204340123406851600173364928825482367171074180549290568300431549129362351406354443846690309792880961869979561730419282116871886576007790660717955259551724916755680579970871875254513596610331016081021967526301091542031592943615140255777598351969666403537306443563889161249709440962659418217783932162673236772123742220211793362487165275935646855584366775487461721961818782132855888148096225852435575347671516231530337727506208626308321320129729982089687904058784592982454276528552520628129235767762321779193817144126747080827342378776196233029006023957975393845969391048056216008739883343688918790967247126574685285705613146187054579241150675553994643393342107013407274203487461296038687459659051954604173040782004873836710972079426201906788863278969836905913850035243822911856069502319452554620070057485409521520370324574910871490107522344143606189001915365049835965683814511287940053761957546796820122495125157044703331768626431013767625512447751192163129693986633323123239139704617386873215476318014175292824742132225343952216177704710327939358861935328899810670148529022032350667393568094185822889444508354554358324860133333714042568762731031273621683218665374339344319318332708015808236476480091388093150013670788378468439365719494147096641651079949085961502020233330231501570997555141760579670445032361148855104489763836713225875207911030884133651852607727050781250 -14142311054461754251574836793277462767002592543663219644969817345422198400335437500377744545489624707689355311855425801777958363843466299934502094291333310601399661492947962083947961431653844894340475148705637732617199761985231527185296718209098319375019139876486766439561306877165201769435155288794906638509094133051565188250089762452328219913947117316936826553686201886779384658568058752938271560429215995516045443038908724007558424109967790163591505417428060508444791535604656247932571125216449372065084398593135693759818555708643516073373634049385767034057539260760197891470841690406171625346673986735805404568339775919448036950679511646974208199327914024961197268662837246392583176425472499298566237100831448116235052729316406415688430367246834252692722265282797416014330825619896335948000777281337057234501877487864120710316387221335086510147688215008555970287003960090893200765103222432091294862118427712338058947450516640617579952656732594158131273544695901632111072962946674261200425185400555179325766418695044636905201757754419464688725281276641418317677520918270070511200526440770749952082634729826715964667147778277092217192524344326885918386693680308911394793764796098662771151752366054538145941082491221725506405537309134176289480997843647215695677676573101410766595257297332387695901793038057164367829807629062966415202350482879605817419704675113332849887549371761593113205943715768243960199143476053063039898916031233966350555419921875000 35064869621149048615126851134498349995930912327467779702655063383486363332343485855490311111549144512316680485496169066619921211359267516045232251767682399711746773350459989260644653584759761161166856103458379942484770893322441147229592058707879833023933123696496614934201846428375197255048496802972893140356635597305869311147523506281279020279332220571744841421835467104858754366582715105013009133577180253757490449941823096666068662393252630499136237422446739585469783075023985323520414152462718640700251381683723925850079489681534782920151223374395924389527477722106241014913714141177697620361262324188899121158826184934098398779198977906773047528709997695967077050044068460401171230461521522065741723361516454205285579275012758916445942398428347025927441517693873817370184218952361484616201103743827474853710073024359197945609834418890099133784509230584781989852266802324220561616207837454967827850199949463062903593241090905112743074099808385961997037081590854917153135637827030741662054038741286717221932798070734539754367151255821712727318245141406822961929213016817303575078757082709409012472240232624755391495382859836262027750021580241101319985938718163718966065341152210934276544771809706216748305293511146804065417752644664243133573149490594435788622009151157122697123616597229462325580337198352894351955364503200067903773753248422967174815817583289956051982250030688991261644073089351941768656380129381977539537729171570390462875366210937500 431987967456664670496756218442440506453131581478939327880926447541684886027365117339787194369324197701157187436061931755613157825658092035666593817004970230652582938238213513563102648206885544752884290099091218960536812166078363714712445137602353563225199980593203268669348783616210519529521389465851226152736051041804389431603670141945781175734978465748753824879003968946970445213454535210287684497396832718531801504133127067779472329853552406140328284039435270861776437104390295621943635247602800437970880008034089076442741414777469449462362989984370480534067223413161349278681376892452990602734065093828399114406564274222502817078751104235769708733607068425641033141799717124835581494361614010452208585108580113330133917362954242967035198971483624405361412484874646315512135646461208957984562557158560208098915562912158278184418494033248721154171932090452781178797047411489195906191835994022605493513098498747959416271176375357756045588295199574246140715289000476038546298339861239127025158728789493053461255480630335364704177025685420236497557608716835293140216769310776319029062868443039008313901657135039309718816557174797769907338586039800810377680774835864603913301803718835700327468239926185762248987375848701483546379413139193096883498881535248024704529314585154190561912773833883656890084371574887430921796627892208360639512435276094576764319735693625381174521680773013395659756094652607811338983342594466385833129606908187270164489746093750000 -1528391488998512976602440731624161409260097887281930988133314468270772998277495470617881588020991712578104717275758374990045605915543266209712560447000137721451124320829461186232006413536640985909428961530008249820311110186524181245877989742498514180289994839965566196817146796225663807314787663857337874052930579099403668556088175966151752919275590182244099105862094059449981952864140586740604506746440861110920072965971827501992517419505135923601480325961002774778713271258770495206952821679938166146759230353040668042792630243988997317758531799768931507426931022042208412151896821808153870848564367371962641652589683757361321826474102346708563354926789967809525728382047193949211053357242667572891297196175383626384040371343377313216657915609445032134723374722436074377197230487545754529014570388085978334025143569053792192315068130444263514191491066418116822028429935241934189851804543782885853360178529418980964354734668514074276723877740125459439829737126435553008734093521858587805398439694325668234452181334096071879935178973336329667528939847793705083114740201986152387703927381259382222540620894224569621401309326424189061002906976048848309187300106379534331020209094889908083863203963495105976036528500585016639549832558980523483730346353393133749757191255542215610910640647318444225234801576961738757315005053662995844317639173620188529856047943216435749378913581957943751706117689695731369627324463091391781865979737631278112530708312988281250 463033949742650180051278725052466435005770423130217127177104173521132400305192755782938229063733741725386144583930232412043431843547856640157668784385497852770343102835380085836425045740777865613400791741268431350280688249451026263608803334180366607762691317542479295475114952402263271969794690068848349964947016608666990053177565764820249853730031462793529301495955548259776252312014438337832817421658916542104644586537607308070776453043218994592388403884369313596903429225653084888278874666908398257815598891813888625403934783692227227801976422179624539709658477201192967730259414393093878937948170171305868251981919397068204875120093914108331744747427693440561307879918933754205810872556805113582346473143943074779657169589049066190393932349782073908984761615343163417018889318199296328231368504579186269059152077636039818165776779952099930681382879504317576452244632053791908687336497464594371780862710433399250861934905332709174592928119751468133146824927942032317589562409075000856190267352637329014313100387131989888537692289374625782095061524722384868758908071727736479469381880592852297072465236442145057828596735854009189617375499898030104742110031353646820512942354551330529242848142428301143824977278637282885697090878464412904887305204286684638364687914774868083876025236843318255045935343642706679501110572645153252651877343887704992410421847481925689435154246954461808094042075870164191434195347270297293817975514684803783893585205078125000 3848726855984479150879671505567551521827339278249131423706458514355989638887421253545321364212956458089856989318756591485610599118040055355398498593698928784510296720889688197474812728707432624775908977595162941878839459269781643632596959983427531090301227873523607906496160415999820657651536853777494693375838818807857546437124523626033720909876044897418931019129953660967713058043955188509734964907858902169989976057153275025356539017002846427926695656081662157001398413402241785997876741598543916201225950078571377115789505145179123172950720194132226616724017897936573181804887707090150270997549157956646625688787282200423671584116017703659773153647644983858537056611527240649331982921319022906269510829211602253718193792952227441242045526568097736098768713913220756334177116864702904360297437069986921139376836484823846280482341737263669294350860248664566226421069383412979448578426112180373463620575909154874272995698371290099081082126858523881816869030704617492547307390695134202684795356531779170888692331058861017094940898648743575893425831910024039180159184334448785522733668302228720936667340472662051996241931679396554222489186913702041348381969537518430869232536828842369256224316375323845285097764038095946570485589194231385930276305905194239069188316725916015596387924231328807674935504398430690477530426834022815768418232606280579736756899280222686068838707293089871653450091571721922800874038546325994758490196545608341693878173828125000000 -11171678049118470968602343697699256425302248266542584460943246377736415717283549959243238533765596299458548594281940315462612725305036431368761570618140764833293867160049096520459893256484991879409749904049055745996121688059544493063478987056874590249196597739463133540695773930558203751493826407880562363931632005570933822852057226787237001832351832001806180532020306037205639864645930502619162748418064906260053108098305983095528743269570888083971655416387060974437195674965089503646139788927152655630949810672621972545599755193503903908079083726882210464003613188365507662810453405485086949174162027734378087912231694553791387012804124671206327070546442950511493967746621241571016909996994167759529463859549442010060849407158554949173516222507684206668575677394277620589681362454218826810138076061408080872958704432471778373371705198403969482950121063035195556189810335272699236750659720995928738106467956060597476589472060890026585068267237709125127868541107300830085390500993413308976484410352998683305813294654399612783443885789259801145786159047613034017189754232262994041921711097784173363021621521789634445488476568699258076453702806639760050104387087140480355352804375197939002774084466649587678915939419626305473640350345979031587785006365387064256739589034831644313745069030694087583019088145028406436412279370692104281099745995814932155837323636033391653348687954654056682169591470968195389905540317217191859100466899690218269824981689453125000 11888604351202858645768553506432637108993829705716886535377422123487002114214116132245129889095547187038019325017542695139928065073685606068312602658989231515878780311275670695031563762684531784701132524886200026659347198784586732563928672920484550000878355284317919254281995150877930678345939641751297665283484676252765205706937760948608539600577221773171971259188646590163951299027334163855967283148281402655015716471947054635418700733129360880878558313574731400303376299771894797782898002085426825238581569397343134944639100798505762167533268638080797884662328367314632330897517612788414469357844967959267461573764140138364301010073943974376460047683772921949566109977391666514914115293620917727416984786343620780586183011351913010826979546567171979000387200420162248427911048939795479478017569925606138327190169484604235948242374519904421599284592894248467117251760324008254648826674894786795861488470555940928688323031390697268641892558722355222022565840438498750716344757208486794348573358830856342918445091986309008376417220389928864563134930015207330827349449363892113562423510558613431116893380323643955380007226103116629670306525212927575483736404006043767138298472485846098158651385414935103680267813900373466225543979427998489444910787071735116461560071552517349212488118431428723006371556105495921481094836140951624290849935290757088926426097105761389801201420343055707563249558240266426900371157061387164532995086574373999610543251037597656250 14847774346360706170176095803838891476576342087811041076943563759311028961023123156523179421129799082394747114884827416952304726393824078024483010940082738086429639557904079312746555500794281225025275758413792782033726988696133513933462342054039918545018661447319687455039604002007403467785907644828881558284776468136299210569561086857072608682165046933311615745849834260431296107691373518407737852287789081199450088668773265397995201723635871042255483608898920864399701903935993559925022351147455762216514255742673834802238600279706229172839323191364989555376005970453011241105328603389686443174917651517184481288189459469197701779376395105038758891577149225178339034801653372727371559476250257366883914044829725851928883871846321726223929960037672772031120366654356966617831778259167022043090589759898951369761454744079054524215424091826312019942407579092586095321197363747217132259168945579922077032129156679925547277484688439042660273117986463624283393513215899922849765641881704712630991997436781323220308921232329189131571623953753263260864769078555303973922159125691919279046954156309306404277450543644400200065319158051107706522634163508119067564699492056714793984153680907734216636801590470872414188439921197988285112744903304313739721573766909148578469405567371516358742279508373112589800895400277114944894604459147666886146038469507156196016415412693700578797417957378293784792942563441773890538770029265402961016206972999498248100280761718750000 -70268260424389699179856912996513175158734844647066358641485307599342690877123943540210571866534715047185912882831436877116986552352272104924693220409143917188701824714623285757774431128376503434540764198276108707083195367664641972308616247446601241790460939369114177698185887460476918144661872322900922736248137296358607776102568790146199666724905219863952387228575711861080644889213866905492435676081733090882352332774279772733562814470714324090614341993572782932256131862520773135114325424386588001867668528504619223630806509688135677560291520433581420243682380946115142112288434718596137308756701139674287359978359549574290696189748477644087072267341052615495954358970573102302213407622114796709369964921059570938139658440515728246257561996306405213639093850973913873242776950752377951618911268048785605598318701414260927408668510548769854114719281419612089778876407706042443589652048578011677526854595320116043747371016487894463736047638009078398133993461939203340119096174323815781022180352746131340894821843095136582807869992595973911654118382898737544143021821631522242574058221748525082394142112371602702167421847079039181132750337531769675376679096895529838881287839670678687508415045960766658657492851128685754858495102885680789248857007247005844375630567321015337436457735178402416620900531606053694140178854863055258409384134146127526860698610515183251953222505126245577487298559526124939134414706107863851647366004726791288703680038452148437500 110700400293601640613589997262854627332839313755419002895442293852930308153732450249267035609129201377049904028621526634464165841552614694219208175729301709547599464076786682070480083298989764866230937246880463758984633157025650439311832190527480264926108157897402269752026849027077431888878704370506061942256490409184936433037945814250899744006004111535361839983109598464991328591862159384110078798844221748012150360877252553786671026961969970333950916516165788347059915747950434040945965394250856236636493863881241110122577181168013775949245924210179541547440610885535160863020726927365995151010735682438570549582979531227404496254319189907425190486515953621341358450695951521449883318871819048510770857218024885091239565992307973237559948910270377656007611156578315662025760457951655893684300406073981114506353583976225065366472216396098329908172238097876470112631679621389082484232453275451920866443296128163470484752548327018001459053383150463259927115733113323194840219571153433034224932802367269551885097631462736735117066643660626697582786041825095042511092916099782872329492783872875453640221193387841824169683498778752227456896695178256323433263726996051699698271850003115941612707111004001037615974412782410020102723462165262437185771168400151747717034817013188882161556590599511968537484455850283456777316565824592013894921890214389466814763492495800535322142192437454248843907265212444462664157285628450944070522155016078613698482513427734375000 -30609502010656286679539596152830336296806726457108297682513804781401473170534653628833417843445896246325741978541016596650742130310500617498632259512881019339775525890120558311688934521729211413723475749339132806397565008365802344772646736525203698145496060174107493758683590755770314856581521265978547335634877883203516753430745342647253771416140677748767794117916746067189145597396256928279267401703765890902933913176506740897381673084040256339655938575478540164599992489614732035402975075159639906487657245873219948505218631046860701350429773422701686819487472149699835687661104433299233723076400050234810532519872638240563195613970988427092437451943916445305087175445351887759896723975198102537798490802254025314963131733370587082835103439994093133717892719434239968937491565339808539870587551326027538777642789722357548492319890601193272762474466467990042687468988221224614065221966941244109138622129188656557290897586344034045183622481596142665659665939358051083838070324397416499538606960684541146858719931348485883177031866951750016124355998994116208498330428349926520103657282690054699695850552834954462271709677513380154960090584944266700794593341978830216715791281266188207763376088876991953110865168560904768952695822807390648812835090098990297880972278236107375275471729438506557986565202615168346266895663730334611333082256660050903570792100377337722892768614449691202279972104569208740808871768241056568471414323084900388494133949279785156250 -278284862032010197120114418662392039602429289651335653386586565149431533973960782217684224133286569598467730837690371231701475287709333907813883822291557037224232327686744333919043130124168986825992259228762336025703069068166354840244641692613040721326608379906005417173239779796123431645591493654918164339662498247790803969602441669473908449435051092118308451772460118731629693421251100061362148803836967064519418759847346994064573048061367444791699922571571217931610611018976237790199300137762324056098576752969948516993259319339361165183001067313897313019160371681605591166823483933002830727996092872007239718254260162813416266865660941130052468895377408043338271979376005599297025081775471876045596554033879826606032852252505440093850086959344490627006300965306733755103107677472862397223966811531694448907400394175875756710491990814841260079522468771596517919137243449069639585654002138203601381591966290228976236879275321910900780785029514203217591725106420651051475715388417572400521385265789629925531807110386047821596667952826315777003292139501170985048969619823846366827241111031855393669760667641239216762990049558823955977094340700927263144665503339429685246275201884949810978115340125242023938837312548092906595842991518160189092056597409021067011684640183361149757588974601384768620633053148067140951242573085891638432435407125742011000315868082086395186234038789689556338674776822502494282431193678428726911988633219152688980102539062500000000 729143122107277074774968852988679498592625120783848766239420751169039294820732022708137094860458915786112695807759041341171609696020950081186918634090160583533793155313657203945104382086864253974287682199594491188748622985188773522464766157147449703555111002053351302483872090744163127736656771822441473287332669495063050881001161382877027001733590309271153049046360501897063480829902824993814782634170341713110171087221467059456833485678246657638652440098826114832702751988909342649233350002129131142583345139176581333893878621107901605017085396178187393220877814219504261711995920766022618696093659419399240377357769296195939206962857569695502540564586965263369131446534930934288023073545656686225097776233353320715188527107649690150188495860056633555664972933232805489337836961921874115090585075541264766753814407474923720818324683237646162484708373497553893261195533732411677550452408695621282081038296881605209004537234786559561910339940157330422472960096749516040306924420035605871875414914744219635035240857360811098049386557502323340491146737039402803513674268336782101358213950729470694540136349626311488796605388573472421783142115951175363848406601061462549911772424745247314042714939738860147355535746204997858494090050079781909311642936582229772858747423015461773736135511618962074248997839841075615190044718161844960948365477646886885419675303633274939548016101379646807375767194323212347482700865057558825554906434263102710247039794921875000000 -870885638604192549241712161330116372476681398454454640875286695776337107732824487330988819551914104353576383552873452590786681414049872973436246063259360615503405540058349900718159189017921541727258883067093356848917752305713615869178814989323574019741343564390360222509411283219924308282080251128140384439488869930149675671798772943805292788872669345152868588907965521681849941836350679862297103562816482916556878342787688839519990856885835660571657713120292839036589402086223792557003480379438507587045881977444561934522086637773996985470216573286719491345597166234410613119608670088633257206511095718713081017229801879785477108967159062778387673846945956944031495897511301776677901878619685718768227225139727959090166874075214285088036765258217393304686642740915436368916649498223819085660292773399336038660438959903704936537242920247299690407189618449085346274536339424991166639657555903434760959975028317105763688199745719462409463159505748705159663105382982483321838702249291257703077490322044884037825501859902819173569435326251394136456542799857886966155496765641039068254572579693061983343907815690745687313306301993325979378290739816388524250802393457526637605733351459373644811178160258099406654495688648352615921763892393869042659711299223525244659661425979927622509234410672569622677741474995449061881651792896027885951000955368439972073131248213778260428207959994726904514994370978138463124573667023531342579190095420926809310913085937500000000 -7740349920450115344747079328203745705795756752370437631397102079847033806652668289849209815137190281050825350118124292673345139360185995576058699664226927540943104522805100647366962036975851826461450521757453323079104036868996029386476131391315231270115892175217768365774577944779665614790326249736972052283363025666324475733977951619656190715826585515918192913586841997805746451112579546996454820037455570716403402468068044234696719532358451846305712945345024378488005323572742673415478034001826124065137193997384848257259300549981998663077859466083453884322519026564102616767477336559268790059158758854851829600374687600826929459278245539545904099540094542447148653410589642077013022821305216138618043087389966067323670112456657130870269475935481823598977781934828909457554396128983228245460425188625757570772295025773687617636198909989114155905997028511522142708464862290904017836065758156109663185264657559003968836140801868292597904240069409676087751947359574831318300358411689497568987184267526579860913044106263615991329571762214805553186710441971843186583337906891551840661666786204938476160167605848077269675529253371127896825300420172559171456459286118816864627911073819599388901424625624816174646459863870450403959148050135585180388576886439137833615372980227171833996598252521686963800490804924914190105959602104512872707080509869712288226302212793241150447736727354350807418605340018392387277540060220096251875077086879173293709754943847656250 2259023177580172973035466543952969759160554477958315575213043609005585327308595887356047365888198164276137613006609929389542840029050779518276793592275725518501384803474705931707261713307758759584325897240966473752303881854311160600545279457494356836080679712423824669015752247291005889982169612609032099434656773846358427832282448808634580369718048763833260334984468237084514795984218814386197659911846213339197054002411030883251391958348251906965491563995652829302904847621555748078666765813138167243925823301346260010350673696873174709773135228087431184353146779808988557444522446314445783038461350085268855553646591520049704433832583969159398947408617260812128654836267106602676727637657296728875423921785681198151267978827837484424261231888063454203611462746047815443234831532842851895356334058356701701795397164103127540817102953956437851231740714462529029371770743278443732517628614013586042964035061321395650433415584535264050058769264394683608573400443237053957145542440358524116924661624072985498024806683634328321739274256963673039214649376205382006163439212411874722402556505973046417499646853050576007944827523955011256481191535754238239869772119169986632123702038690789282791139090631147189101466067740717515930143989305364963763820251909704712654929681405270869361514308078508828282009011781453407193710981630162069423704804874007648739906346145367089981170976402429876877160989621931484904487460649812058388619107063277624547481536865234375000 -4847869151692619215674131146386015137832356308940233380042344735758295629554262773102605987462192066086233521970696505163465546685657783667428908564903534074575439196013186907869201689563136850673057971234162343168133468131457089674020359889120727663515533368311380543296706820398942657443795053019888408001600453571808067152469358346845689133972362547334181932352538909559326849673019349354148378494247110011964397345301901775801512760575399568523441443839393565854030679655070975409534313811775910046488987016307148783099256752055378879392806773607233883211519142558692843483227742445433233749325299635292313255812392196673707914333390110724928572717115000830477691083540398871836388308766286770773093172153838336561337326168640694410271693309434050801925612626397729741837589638464805998857816915671721692117242772418327944700519975944769393793789302173794554778403216566771544471473866908269077670767034908689499182060442483244013048462560946251364656347186131680634918981285012988415481254760396383936106140997427469248907606064784702094637424130921117306811775506514831804532748450557568601962743888674526190234233425548205844501828291685211410763321507782872094282889864621466143389625033259834156277647648477381335658101897624502313863490066506889140236222523178660340838445983627765762123665896336258321762740906931828806082779938265544345700746455549047242631594097580489554780396217908090917659377900824409918234536576164828147739171981811523437500 4774377788977096162905957226380040639107422513954184833038384484199320097297095819369583400881246417529807140553571976946508221396521247476467573055007573531569745371070363045419179803937353332913515303794192432694093060586143257876525446081656542884721230802126474648925093287273602482506231253429271171872552964047452192351775367371777827575774937377299177432085332870256935181487274306219099035454437037214156410111360488839953333241656389402485121373460472517790961371612372497777206683820346017448903941387585356703858907354697942010771542752884182671141933321783141534660553507113312072305935774768510486716577638912030523674540799363862608416332312208393370868069533473170798873396930453800538559233020062236269514590069872237696961518347136258331294636676880958856611714647683260406933193040617838438577462348390630401966925659322871047445347827817856580267264405996429658210383793963609469671645636494213645541743909322020642432866957386927487240905319372637107093987036259387725476190435038573008328852521415025386799118310632891292213005680415865469851944646224926717248990207710663841034838315216632111386774122602136487426329138380640171362856186552147940370417212218184125563098347260453884445631858521152201729222403072870462714859476503182571451919999798605095163267145560629604032418713046412025714722549232517636686827662489260983497770475937413781786192682964559964409416492814820795693888359377196617394645272725028917193412780761718750000 1981355140042582370614575855199656944146479100845271560665159707010154770076008246199865527070806321426834166407770613753210089134387588484307367180660405413306846885310864802013922204384393409294415762553575098105419623355373732864184441095056697757510349329765419297399669202705808982945241113328732753406033406728805706720018811606009954872339332069103584103861576511629389230589489418075290925871677244132792311090504774005706273106865712537412992553217381971528428407953518905475145170666080873365502020333543481417332550750246921414224365707801183300005834305763140152495303167028367698625931215780197585975122435504066837190688773269853312993631645422018365649525100380362408735200555046704269400016369223138292573662596086780413085809883720160562714503328453555899908369641231075161687034014655695712334914604042834877919759592681456934884570761389528717351862299277085470318170302705138544555188040418662109805896645338149920587789282673759363086433767930111209149177080216368222240694126919963961009612945070438682172120969142904629303719723121337740446100075167507909354931545457300809001001913447886237782412095323616627389984940728233100537361073401234172580528329615601713379917978521434175311970624857272571616213230827946075898858964224927654764996571107313890719811753229196986386366970333410032978821569181160051834162153081652524071895200646034433756819400212430922177259478355747426827921599305987535033501956149848410859704017639160156250 -17553195342354402296647832779780192407634081670980520127583308710556957856310833239902059832811055713582555375420443676212810192283864056060144953639465382690474329254028944911772346062088015074695797483308244184664287108095841880735545840322682224589977536516940627857764255127592943435254358366408179442561639006014487149560922204947297270628271906618287402470249053519144908105500956712654559335810451291121442977097343248251922672073716592626078299686642598093500513778911772383572902714304986588476937459361011773517643654860307928472283626507017974437047011594580313317528140154964036802495709041863155626531563864173666941475079156848214205426354165041332695623532403586485641587559299187769721646171474524364153831624883587007873527088379441106615830881485488114333119014758293126110450800997197566108945587877010308381997670472605113703880246630955962923692548583587230343258327289045821623122034386346024354525216312071053311461725611749072105806226367252567285565791627198902530456330878291450509745222120424703691089633976100192046840479587458426178126377795431343530017303317094660331815631161734629297175776293141862336362988001304843165112482426686949231766087041844334890902569127264589087733961251274509577656627257788503105023951524781876891520551721054209614866732714620396927215762498368930247408320378603835851319937581580918671819763090622486338630317614648252562716123480102358478303010549189007438730669719006982631981372833251953125000 38363715954057138839417817199730503874446911934235224365029015966181568189595195783099509515871839489986629432522968156143738631340512908439747746117836283470560228753045477520544581444451023007078307487811443156856921957420306702624459365724364200118269853869484562915851317140844255546812741743534733986135301438244806905792061193995963342408041025518064679807377477230347793929396071872092865234683219854909337513667468437491172615700459088619502157951840017563223858344960238906349124668598297796384590983710170670910036595952525832864077655880882144057961811648809982501066458825894685229234747646497582186593253299697291374154530574057957282617564673863625649533096922717157504464736474115488884061703914777070532041534729239301139274773099843268043384927464728281182275965507853415361279151573338576561264828995759345226646684404452787432463706168725367784464170323107365621497940264520047337736007967822289163426322523193180113227778512370210110772928124117340059699468151479564261147142440183117758294303944432554406715506444386014525978127443855304786147267084724087317842178836545953976675396412099480370158149069461059918781601166029572292568724711064369263622390924271143190412180430593918905822559369493732576092544485213514394271680787360553791199041736355230870351857175839955910190333519817197139418405028388857892550133457041378982078453194469108491941816990363684732115514713462219876448402165226847504442275749170221388339996337890625000000 -53434507848662438530794922539984752564530659794421788524915016951155736561594742447489827722444158299843863685679964890820093189252976909111539007771652827978498108752180594701551455730762160816341294218772438223253782031740638282513445329162504604321905055642710523333786119212333482323667569616489881729152675891751038773833475170602007845802280102440183238474278552080658009227114658800847488686191477376133279021323443448515317490379768010433817123768089561306727276636138963819533474847226574693596358646956271280836743949702414329583948644031161873859360411582012020706728747041988305814048129759372971969998724716071747229276674092190068017822030706975961394353820471136694952180666009913912159760457895238134028673379539862403696299184958496432181087114258306356023251763336241634334491322767918674421621635165646554686345677497426280125001495426629958655805299378897487155432741513943057882829359812495476128035962803617410037240465469065044907996801412509425786037312780576888640024994917250360183432324887344924859060841347938233112340087480398358542040127165509416983299064688451190655223336237908479733406653612704007746713323412739245875264382303096588047141481718974369709658852589931143227776930257310640707550287296969870561893627265299734102197657404259121984225159291109556031062202511228197982694957728404445466523603968715361660842032365326855059966852616252774160378613868825989136277194457044607822648885075977887026965618133544921875000 48724613808436744590655286946200000423184485841377291067305191716539729994490036882616996836296067066118314887065028939315702023354249344819024664529201418710269343242375064558237380560954300482238034233142907233668563531116753603922214770634364188891701547751052922486569077844302825664771418313765835106314325370482076587683277951875917138381214362838169012214940143725740378370569961792379007110298057014559908640868426515658293010341531382845208427306402373422190184516251583833471732588212911266094890295341144100046069202655652345339091665517098190425019863545048115862897217266759022685455394224087785928014601698382570650060902347077065534232706262666052811210560126430351788409415669253927100939391076822904453032691082128451229047836393956048518654161678318937281394389647351995997667389559017735822133505003633685207042910526173629153237097485535732187935278436090349689380338033581113287214276817168387097330760102006164674324483474574589643689803010598378295358513748519750210761010380314746658699370094335046485363663611445402144645107786812450370867153727823129534727238022706372190120512920141950060002530597395466198804643049665943042701223933826052038662569706373009446987046344577737388246187695760981005964791795908844311504605558664492255491411735236034070532262590940853864024414039010467312334357928421243238839103505265582769930047068667394760248922456653604652398076042264690319217841564281316554807510499358613742515444755554199218750 -19803226442878446272769868209339910085794403875714649885898332201050989551173283155041933849232420986001209128650169040685410135519656580662458202509128337879960730778325227715816665028624413264640887282403159159981304625984222302912333018615496606810566306022988278630815416001560358525711436721053326677022332161005332736056771907706738469641975789744076071922533888943300722036760088894332497189054701867698751705197459907989391444216267026203831222318788396055958162965125236062755109505999138666114244611030238245177273824770152107727115891860448243931604257416693318992750376740785017868817846714708285278952181777372436050857017618671274775937780718849852446299147432474770466392374000341741138376217051417249664547434720854764118160961155702132400416052498746101074349690149682683124626820444727843154219643584504393186698234769760695024489241203735644618517720371678043126243325542926856915587952689855068665006844981254169401126915780694770940074312678621444511585412351141967634909384308229920512735280874846275995291709996789013155270699143166204828266456283997545681809559973534058728344574972798737430154463771851352504667466852386154806055466739466016820454964515466510800454267242495062651429000357407228842421629276293408220892494970607049828448963678668586097915047750476803160414883734826729722323101523673054601076678510239472865910628749481778381901017741791987256429606001181013474204108479196154157797593597933882847428321838378906250000 -9411792228567405064701364306644971872980497398754718062527167323648884675802512068137546299792053062373119793284711876038363705145727448113873058478841497188925261436185075780584961374016725614659836338429697329877905916696744685491355329109006671381988433211967177805606136800871179105237304333258601602555049063522000087703144621502423441398007951321992520731988743803846544993651246838816521046531822498065682793725468165166175434271414559812000747336374099565066582243816399077825714647080342704203625359745635716261348360950837985915545953603898455574322473135519690500052984956891303840881508220954755844879032326561753165010703595093257467265130432378394099068568992977823771198711602282869815217353057007934649174533568588364300719458643417515784794645825452093500008299996131951273371091566776352191440305702481335536099797299619976850338727314533546323938897172209645693391965823890664990946440429915616121994168235012141811938743304542096065511116233147976375824737224274810494451971029287318231956237945172718376631110365267225329500562477527120903715869431324503224233241296145223082954024691068958362644532153114536547311572780747443327475208217075063352310190821971776104881904777237189834025844676185856387689412496493996634376711453865609873639359875647582052016657871955264100604699228699023010285644707339035835678020573444019478682052161327556434676475591581064836782306690406702471858674503380013526276925972524622920900583267211914062500 -29026975440464806965896011275181818750954646886694469254835004112180934934168926762275753770824165986092927375870693768725852836466229480821343501572293965123957448306252398091192619323471462257845583404857738337083785381822326389296936506669127624004678902455348511961260562634248572555757423025201861420828220389126158181693260877758058770867073420257379685894371212624579670980432957937077520007671521730605284633216767900468205963025386567790334372543287582360676667849706403627156006821707072163016418588595458294686261686370839305117195529073485898303228231328913731533431047402770681762679971080838967049698528905114627838553784683284022387398354487265168057704887776920100725107458286741079651960275685489920443936026101354654025540663178570631100009508310763600644655463512450360612759320863862038824742173362160026367981587238097997026714468006965948531265904862127250967516307108182113559361805430536669299636346322122942391716390093053083982714737347877353444770874517970043217338334906537295031525201572975184960472819706526896572743446079881971123919368986134555762846277640848299476258677615129494971238313459800337005475284277904535309309011322903334035725304432979065932271583619710458890457114388302526890675699202606708012828213413202203629459381844434847541292456950189562418649833812158643448888493228781542656375584793300961713281321962513855462410119130755468652172740549719361101421679475262198344420738749249721877276897430419921875000 245811048676253860369523686876840198811576631021466318430581248849506048681877220201226161462134129175443891607074725002004128801049473880642988443329229796739565126564316996554099920813360592620015002771020447029478103650835099382258388668165130122461330875367401903538097053537038977414484472795973912564915793785170537162436353258475716360298749698282293364385075231144929863242317184317736237616658413443751124233191889032838015980664074147519866388922793100703082822790607424314650949926247389739921154989907460180532955794044246042044911144199558357572052558814847469753560861593088290467434758144052901022325349774774198281751995805759547169597674417000832784658590334794838295694827404152208271967396022784066058989526561248653601594495361868364626666659645836872809834704764285429053605881709432985697452930649220233099073224829668213737482133394891818054956806008378121421430602957136665991218044427852214532617929684314375496274165729784384260839054681919512515536186481225915734544332854502869750463280496511737431596744296110815419557044915202356999375022518614056210879500376349818104685562103293349095693946200931976067088436048143277643032667974259202099038576143409688665414514574498518606817199440024127452751996955350040607211030556444933037591762856158022497142622431431169811278062342999130597149148932224730803302268401130695754760268838177451557171166534804429970505246760237148022427795076070124527523041990662022726610302925109863281250 -765500970601247807065258671918123034969856009621302730535972923544249003038028450228462977262146686350614510100362327516072870498187728185348580272027915794961655984657814371724467177738622893280257849409540767640008974467732435668909517291533175523476255802111577781095171327666942202363215168547674356452331089243561393049557151220859588775434403522159363994297134575711049600809947186274895092150609578809073092127092552451460013865868977900612423573221593666171220009280304830641690119268572990454822054274081190021979218861769280091127379103006034536098866152977480573790861349271620634213229868143998481245798412835557546212005659170357948861585944894393262351890052490119667813455006813163387651214823659667331410326310233118480404531990961075455358936849980091563666490218343521309833183759732042404690670872575859351382120717653122921910440154755405994043614906738996572116431448892870901042841153631298740447415020756244436078079556482253450130998640322863423756132413725902811390840993557814349639630018231313442960942729656651341496485378289495538688374530938037708027159045233770197817038979936334817816031183197392121614774014593089196264273054449821544413369422529088235237700334877795935479642771103677763896539218422627033203146189746938613532179891130092319039106702076143374028327422086980057586005050391602835875000445493347896689832150078039480606971506536346640451068365504648666888281623036163758833083647914463654160499572753906250000000 1674871372530220636563879554664748541718433144577859260878351078387456619520885864661501901674880569117014812837788805814707606281212133887126080452442887448385582421550261193360901227031908810156471342879516138345331886806295346158998986981846720102170257666172657870996329037342564359308160145308883702980813186862819932919480037094306448301313751410195026222094877648440308598034621653903688804316334191121687348209507539056185528995445830110302336225055059465644610722012960776091813546061166034304244716648671479721565265203725994897412460906260159774343179975173233352957376706317536497468802255842507536010529812956057166187666709564998514923011981253956455297580977673511692998004009877540426837411886206424194208346844156138558931877826120836199282769682257005987009699416107462719005772342928499045430669960679020831914419375317884371593312694305905789707004082406439871466994255731318482905388880384055716750180803123662120517047411414737370760321530218044801948292131500194416573435906844703507571046551916096101535012432617326988267118946706581271307543087067567828989448775143442864006803139290114267040140351142236527858038887552679258945610337174874804454916492592448505362050489406643409517105598724624186148838922314297121572328547762072395379368412662705121849651165051240572447844070630012567582369641877514424202331110600547597532216709917527845402501413363771944816004896797179175308197668619464293371379426389466971158981323242187500000000 -2978859322044385310426603282727453720480626832969165166476391503673648285906963921195457560660787659891758139978592845693537927304549773260598635870795606183371977961259587951882427196322284043114672090544676890039536009528980650017518995646550577213194164009612695440860292678230403659526860860021413654257725780608801406800495595038000642563078298268063600552940984995752478376258238039562637555463973883762258070381047454478907223336410646131985759400474776664695271023485653688875721473907897455216701498721254701784095118567400551059850698956936880817249735326484300313558308482949472313269755812600542716574837082503483263187315949948580606975886121220754508064060331763989833083483857135826263774965981151459700178349658460183357182208645132773948910867991529989065436685034100414598223709610980714770833722390831306444222509048572477228796062985281573221107278459718916949656705874234725332161491831771590875561926043227357031744378092069009776310886352696421440460548616585069351559531517716566078198587840798220841085724640494819216249813265257966635940649356287820516611532155779433932649503668065225525535266914453608274296080954943299365048742353333641288210571039102696955033388793668169360842849203529755373532497658477375992546356274844613136466014894512192566919516904264548166331868418257695167514517815969424863247578985277033672504093397873721025074278228969702121202881592854161414036005757531924698078285018709721043705940246582031250000000 4617994283890640857763145750889256515950200917803661381786675194588005997914298361600841751071230155142199523412795494283626498754831436823106176391140913545931803518695616136538335134338869729222171511270498746515948225005556446877998954161452947126721461221052392622511018391692014758382320461535916500449147605715623702724128329499428861396046671306748014723055304977663575286252595695272589537029060599074487744204724282107611662388136329067439468196870530128663220585508394294240618962564035829449718509915360643260729928951423882203483683538935759688739919491913315661333415317831696724824025588632558938561597196683590367662218852764474092111827254101244096339226757534414769514572811737420519305749865677148074143019488466474504332109610269148429963617503280578025957769252689628641780309871746776449708374083267887162815820757438269847870772468965491609591038600284349469046392144585423670898969402676460271355878418205303281611838098332800099999881499120768530240051981441535740585715177826323833704851335717032139599775073132651270475846652442262670657547108274556088325145622739172734969888632901293678673171029983605885161515506286652197749587459289960929405346330255084122572500508191096359165911817765167644276645161823077694827107728212777150842834633744646004888962883926419866858168191044354066615533424505584150970333915090599665532348009933932683423083147091725476862300339896697163476381979941383284365974404295229760464280843734741210937500 -6603903614065954717825831979658562281821012098995902118472869949778710227920337859191686872602064034753837623124575912059890153167830090866303044805908179723118114937151180830028193803244956820876510804053090868534459750709746485207557002871278328858691694830684142606903340791987311171653149257150330558411613422682825467715994772680531228836045976042066995883292932457260618268614499241136323638559506081571690052751514450499568301278630530474601418700633637318689421817017092729992246371048348694790489591578156771555821055904782590965435752238112574476669161945753266104216769801172702440450384824896240272868133242335503470765384390406720531689977864210746017862309712572723652204980543691737182544540049725316869196937921836990906828564111795179870688677846102675201266704819863044426100309681646101391292153638720512207934122828373321407026406592965653154605818814312366575416432569113181585028731181485677347471040201199156693586181085625616302005635079942580154591552531338681189071306077381029676825564046788012681519175003516280409632524361284271531867635394074606030059705891402971332319363924631042441071611695125822570944657567106907819652935697800616227912377643047143421862706014995093154949612618404171267402151152708653663294204913184003989452397888968068883475881003991511384694298131755745340795823637822301348995810966874134008365789905901776777664569170345238796961802562875683651475837663424742554618696033230662578716874122619628906250000 9295998627785454741731426202294851229440290914817795030471870596211498622968070529342507217135494566151758733373413435428663807543581302083965507044236335813658923748088282689107665691259679520021123358764989037120751362253339912291251132660811438880171345146417721526930903614794326198741185751014483471206766633544305043676607216226955553693741898042766612693343740024184813741112924318534772118420756980586871901340807693754290494316333720418742378585877986368697026180186469218878999626568154536034112764236242736515337618953109296912025132953442956006807734377962780136687897561259451856061405007324783667377494537023217332936076324579162729506746767905212242028664166906629050472026351995636392847972030169320603242205534889146149900860169127909210889485599543413179684290157169450992802491884875564683513163314609452096418903113962544274948279005111586657630892074698652256769423637446501881942280470106025955340132930101822952750290302578755724171432664484305510173092846459290038744830171872308664442906997459724493515538029955694158295894008058109423817808650232847357463557414530062236811552869624956028356340448639848710185041043765886609414901796586526993781615913013543972767090076612270963022267820947599550464470415160421863284431684412936437932968277304299684766920256328649430070626206176170498608338810506283764623799488549265695745906888836234621542572237968300254960581002035824960581460901345497195580325211494709947146475315093994140625000 -13772066537174152035046494329835779124752671803589380892380547516591593499355091310788473448149738340353465010574489067024737538024005860352058607955895757339164719065170440346968898880974689958179850356315494212158598955870493430921730409112014134364802474725355260666025306374208393813604258777073212542556558286445575865164411364742126635179427048256242947925559979331168452187241554167143416964322458428256760331941333569620278243327793894721384234077952111160488917493672743918877147576279442436940535194091063624323465623521318912262179283148674865395037410414738743604212430286942640387401378606841833369106174106532165293061073339630251805054942592118827314856240172817068543222506985320111392381488694448718224006527160231700441054487576796995232661270744287532661129420528268755200106438045451162884360056842386736627439259399635925944775072430863332799325691796794598427931164147017545644788847973080249126872081893325525878031426179695968562706984521964634966667236764542164949944165386636729187681762523584945060019750503655516758639277466218128324697151490939987917484258089756613788565333175199628406279388866240398384214229458941693950693114146441178257348093978006346223470081298769854984092327773148059050577022552360931109703343022329047285068864027941783180678745236365764672988256064733669329010183394930550232979122698165377457743799206522263675724051165659332871221479039336463759755813924905414741273190770698420237749814987182617187500000 22162488773153290292402587508096582820465530426770489910292176003270520823681634929240556474181045938541464523424369085209783805841859303526549417741862315719350683196384597864597549886520269270428394822345113690766406002380368001997023769800885424090080982608558039755200344344620490964309211975818319476510104689612257977975043243057524608182976588990850166571643678644273916766727192391716493218728083412488511044048617285693820597384926684807500543731599277732125893106161870100513922269842485600566908879395978168918283961748375818027868899165787570179447046129823342017997722172808833125302534664956634253343878636716190525329653258961175639326159678869003109099485085321071669563772601806913838608083893730464689546149241175065206871174408901926900801217143952122968560510837058422338907103294140650351577191127887172152302696200518491041285863916560888279301810802909851338573848699132701499776907952229783341040113820571022579455890309836907956504370299003526069996790016316426566389097455411577473255068498670887817464543250510138785894771620420579319729716011275386066927427753876826639386442608972707864120389974380536789071697264771537781980693483763131711243864055960565262540054986273660132743275671946202027470285955558865683037146803066712677768209741543304173841150262581204206859426361910386664200290758501440512096962778370622067925719207763946987341235130039328140186942716812708141776757620997376999755212878540078236255794763565063476562500 -37769893454930936814388008135128918286005062941565746548203394652117021260928017829436600934191642129072403378030632059997392404795576091722190115668664390471501101401047309876039265299143959244412873431692993636976739388671424218937525973483907559274881885708182249730974815850890116070372198919480068149193268697004657274516959408589620390975622561861575644870880714694321917522721812438598424255423180418192162789355188310279001703431507130799293459649157475212050056732394432568819779735136903923088636042545287883148418649256491236703327613603787664187926334972041217537567655423496213450382673067828540263355014159397310449298073225222826369354750916358909264987615909302996698023739391910058466579650637955210053768920605697569387112813106692183355943525893761954928095100526825831333539106460193597257487049403130541076042282814315970822480347155920824703936902005543752657421071785793994496563038065948426915036249814916121229499878051774091574941763390632416544835351625378579136935332435821142547168472602048510129239437490251892663402375373336117020242769063808372988378418223913980135739735550477197716020698102773819612859286958142662159618964128597530693145193053349634715216139522367661532431856344638860921863745228842909435772375360617200165941953305570689753758133559620243157760681272802805095010678180537950766172085158538451176646549041216576184759839029859845375631778606093637945707278383338173846639485020659776637330651283264160156250000 64839054291708133780080344176074466554976559257022767520578614430292267427984001483547750300443135535196576435191682961330856278093259761440063157804151352296797509656176192843050564396446268746235971492600681520511864882852753729747965250358567246523097675375306057068499386993122242233488120016265642599899228183562689450489303819815613503559480676356705104424836900166611171635304891672278185569409420714421148679070393561820013704936614484848380776972646405048647183404721571070612863238356487568072747494606672053026347002619988939021610896958718019256907506463836831725872916816613287518167051994255026615920062626339381855904617543701422343108120686702169482008679221972917417942082204677225107934148719752530182429309484981865661396086610389269537600408426271793763073257753570168609785555927330376130364903897178702808151686952176549869072099958509353334184823504630396460665258626182625143192567231483071222766184492657076630422698797716969176847568259735552609946507587176477492016947266189273994070498453484295202291191863723732623722591838011301631629169944615302131565573345302484917732667374421306331289179227476742406119403686598660424377687926383208231908734190940310554981658144568979252796827856340008156818041433549909676658809379355345330714283691212158852966500919365776773890021194960474797195764489555071085639324176640947473294266126078893691604707371026206409952711246643926520077049784258373110734652300379821099340915679931640625000000 -108012991491640711501951413102473003848947239234534142032083943525253729145204938185761202237247959874694304854902981598859497095364827713587955655524099679919106860217807385556931766974051312002135777204760754905068500430978841891443213680975013670794866864572273776862407866587702883220303669586577398611557536078345868662542563665568659301492785719157553151521240632134309320907365483153326635812293640745168923698614487879943236794131424284001201709320232780011194975422399478537237480748146920620526500262209017052500418395608004986593909746985425296388809618204836151740623698947265201397159434760910023589700943290155229345548306723226671188587778764363527121191765074117424620852768870549689532955835890134605933699814292232804511304219147889974068650995369002550574870156771196170349922046455138478752505473257598648533841037865292734525427526213172957513247520813944898043453371979262706878024862710072787480146470669362668755102804471821365099435160574855365452740815218561488146989623342683590103150070875026501948677947694228558827998026482263583215307095640950306071536830781819971405910708693762015762442905634998898031171846738585331040680330510962550282250957106283053311804897906682275971724221690551777239107052309744716810845552764434633450107582551408412577793231455322079740988307110794122936793798980889540484688782137408079381745466473455606526187512342648473334844136319429810394791942711054588341368365433936560293659567832946777343750000 171798076356113510837362792807290621508288784527562052830964978072576877154438492522159227636679406532152813520098272771601422140025499707775004510635370018973067770819467178817329152680641212095023447551195658184387618388024550531707520125798812360301155361486177875422216280749728846696822361778055139465428425503734717455171048238202745784812405860091769266647363518053535021487958536645383716056468176415141483796360673791748023643077831780340255457459641278388288950082793223403437035500981672833023290713826528581722832596575485501394155069824456530067741087842229267666882585922732763992166868546800016536633164757217033181558994777079631901724652221804924537498261480992031611775072133666641710041090644969945169906179327340301634862793742538560747737375259990920923232600094446811311949565142559125056471322539854512381899833918139929106791838513256784469087645334155761959126191738462046789263648904605931954769393555416259325443196510812039085920419223546916979102265303000666240033663954203822062170298665103848567175257397420404741248774931845863933419500579882747776079691847270865294444564768797648187553033512432439705423046887560938633057215652591257076728969241662822043395594040456044173249866867367145483416358548918955532125307192087827992542403829651740515634785212048327392587633650250029142254989691525516498432978737469279108365248415979446662886459244598313230613986758360249381579333789622765753940525357279511808883398771286010742187500 -260682969540037698141485799456588903078396690990752491451311595654601745891678109557963520138340306259967508179430441826015269424501693036115999423876413141641531882029132981998078897421605484588054208398164539237422024424957493329015133701546903221621814481482622329293324306565355870889441109327281709538638607840747219431201890906944075036009211997909995980994778863927255774068458887132003946455741751573851484291253243558402127709944980555693167262234836367149984472692676807626947581235738395057985494343067641738132911253804732619238854783957940857924862963058812363924929376056994941848546136630998009762930617649242765010687738893795863461251892234884224967989430160220837329150871191518646384103915025217264940705724071840062347297162382488981507225560747040180186266842092504607705603252329427887191625203967159827987612136482376311349631473597053381672324318592840428970233893017638929483722854354847992541846693205523518020748135235934378503925928286422029410041929767475826343249780422975577296710758568521229897061076712773392129513095415934086742771491739885003253364782568136414665629561419765308388119059590768259684576418375790914916997309681357323637066712989516087012120361103862836032358074910328281046837849802574635175749826945027074571967028522917798844498774956818370745184933860724043674906221996076298574830029708695151240168831040912799105151490087307449978770406757255877015011151020347415080413711052642611321061849594116210937500000 380772268918382022539572956006107489106276085796557133652744614846374508824905712283523030203280728220547074760979847322436518414081501076346256575704103620306020273719801446110319831929784982703280757263681437901558723098065727060946040421693471344252507441803006504780815358904297556873952146328296859799389171896994790302598126546084666765978905871014525928451031945086179777117916846586357434658674725552690600899526735666544568195358989922419407780951758371474047308319084604919874175681103339580409750714418199489949146796083724331478072316217769095001583342514546317094174975974617050002380214096460284939280668785343517124480892107099196044635740016588069059599469744207063199304403300907690752613825159969235907490889103811127388490175164508173502541408620031559779131761599643118304636450394861833509584360329662556781184662130893827543479982970041004477024285616669235908010392754548090788122219568555456784147233606507397028030479640084334910024690830942362962493856238812656823605662768076993521862846623364659112869306965106755675439633092062343272543148956081764361220122763084424684880129055453948772426016328254821635676407966638393960229336201178996888255829061532839276095539774194719679912118628389671287091583255785507111479972304058309702434900948238672967934745770430284434948611545751593215774037845048259313640110185091653373921493012902986405027218970392310022166443723147183457756187923963649664960140484026851481758058071136474609375000 -543743412614719194057639622910362303416921972239035030818956683055009022357340647245837050981659537925363809001035780382103270653034024890735334616781288925779116482842158984068464034008495782756512513433796309776928312726935527835711752686320048038101789352566499441080350241784133783339324143287479176540350415237724630840623672295372901253087097984205032068014052829428066776330249031319277443402658315438944104639912253304262673197290433100270240635149027509350071954956743297231505519205910180546417277765341095277743108697306367464437142012319369317967053269547984953078583727641386375485136295858191211887476673544098284021685935933093513759646082747765492037121529412853780032596950529696829042315844417470724359999921045734639587818357262521364257730709930449250907380318555091828058076749163805659266423074327225924915046197323501409303531331134483443993029933865265602931311134461021775608017514835035590392255582278620599160009167642381118631901973538572652286022194457150344337336310427786634355378532139493455108981466848421671300428419283492317324666109891337354960015094536215065966937974077168164924462924172808035896348755208871539497127855512360291155997281368894581547045786594591040057946391885735314532730130749572745916890426476144201685337769635141073790943875187380970412725248612974330313580139295128175547174454952724192305464458359465829639537226149905202486546223809445696809162111068678508926654835420322342542931437492370605468750000 773495606282584317311758090662515039197780783030456582873458423617612907571511147142179543433893227584831657067117607214233736552633168403906998689952222827615725667381060075805579918391001441066118761172433335721080447759060533153545903626433954334828537411711843793688333859084874122941506345351277650646728369764109132144662330681203808603334010861077323121483973421604596694306216389148862564404332652173424972013007853065625047372145703855557749448046115996306160677018940077363143219528677408674938113064785762974337234629042909975417710519197160988916529211039716077121777313246348603562126035020662971757294587076822784257450379755534059840899783319582292884176046620969639909655587724866649713749428957158202381640274516443494555661438653627539282700192643554688194341927397306023921872406500027743770800484079995560271148396204526075772129855565276946523796088428402631166307273164684890626332301207611818187290076922545694657925927949892231279630908893803203734577646515999708771074203701358111074862117917057778668816674724458691600416100847584462589140552074014151114294257528000086290955890932325668924837173619358885127556240197404576477462906661629536029829249083904669901623970592216709376005264449185461345250753183808955640416154245929415959870642047027469400300206080193919424119661761194433351408227559651643354278715498451698815921001331229731086395087200998041113050887111259414656474928519403714156227325204895350907463580369949340820312500 -1115024519683542776914705624197349905603650142499320913236298173525444182486511833653138655847087665604379051936002512451669957662035888561488639060689369985544048106194009951338685133334614011239629101404286162787700221326775302789836702268938913737170142811219571068406246593108444813170009146565506183955110696210859809690118464523959882442455242568475855213833875756147097646921735311326823516721444688861272630729503706763784315655210885678202909910851841673190797586760017735867597460160820822006471514925964657986645158000016687166598793961834706842494549456371543000627245070259855083650789920890825123937652076606397289038033317944870163183227854479312259789981049185141299120739820089306104242904589141416889091010499703721485805764626599540036270206379794698530270613475701910293434392998079688569244006019898237459399858469271730355993773373380965046523814848746945711647395893433353278266658903139033555393072135423608206688672968500228030926595894344357794838459005833832572979814101893161620697355877986014343917222625217471930499765679474716419713730025124925005413955006529875362654880200058167232692398221707130328015701121679297401476591075442749463348509479325901807954529345184030143938052403518310528215122397257137545431821550863479008976644113725306205726603178243308320013754666637144222888922416479859802418690076942643762534398735377900007000816443577671987935712930238754027168101184600652528433606391899957088753581047058105468750000000 1643972413986036280488306067649334020873599580764181276738886531998707848841363233354216444526503182269484007897034756390593488495055608685227236797539258696691622615792793587762845897995247207025918084412161179758921824527289042224592407425089225213539918240077256239860113200445812473664861493310482300843362571704025243530879822333775497143455075438668146427285238441842763832736798200941293670042752356062797061722740143555092606551407292649200449336324988887177917827147638030617311989423321066235760072194076646262434096424630004511251017312163395488813888637903350095388522236253672091057450853756094557199803632047536296582337599846366243864750679028641751712927923107381988604934979199712957561200339710808836057329537536593573489772912597047497573747934265059495925081426950812037586864129509540248436308829047566286971309051060831059699950348377775831995839764398608512382365427387138420408214890784537541154105098023865383910394665573435233059614286763849075053167390425114218613534608763951190818100215732985889151460200839806651941764519297994572470499716321161959723969055956558091199423223338102173130820771557421307129628680038676751284121932518888275251720741663396504251975117466740480748007569425235166399569990015935414214453715754225458200986828870010399977888651072807728805757282581690678599994415864675102167490949066196390750684866311430289697980605268051860053071281591496712593131659111344786139419227311009308323264122009277343750000000 -2474263483305516597672089855284860564157396580553481229105560855362202839382743970877042138757734216818406892692079949494210359153572818400770082181791372038371753286354450710826381381738476067260065083252933900710311621732687255353155168242423117433946787380429744386553600293064904441560254378053171004089807184911568311916054850019600666548560158644824985062092479918484881628685555328803146526812527152338237725407387784285964572738027204261093830944877719662345771228031966620198103872932217697356399223590513955330296028514615383619503348012646927869487990401598458704129018572049354128065376743941482733023834300901845852364794527382526103941206140976315098979477705636005061139467172333601634133616183730403083964022250084441374277727071473817065156158961477845577859632535130228192454362464917732449407460486737730564910855179422585556351460427256194900141314473783119484904913773655481724154822139191405714615022041560306836632817515872023146654246756583054499838415009689011685318610934509196787203300786886963774165058892943643156427215138238238843757918199334752010217196974854794742422123898209656888499198027169974010680437603872809424198856504658392211165086335552676629122160079788939735981381558613484437137670362906095557863405975551182010723500238830738653892758029004604771530321517634784339654809604822954128347779022399303640969344005334564497164745818082794727630365874572179370928641352827626401222893548492720583453774452209472656250000000 3760612305497089575009103659929018506453334098007431818415006586829230055445442078581332175340406227404856991883835947853101123520614713796099143702354691104980674871093024771907386326132385249903907819419883391728255806486267967173957886948800589354197698898701277655558132143791470862508709626786235683098312068910875129273014250862610973278393999272456614769553889260533216701943506249185321604835626447228860409726803704463336287541814894442253028325072666639108317665875889934076842365668861405406543784573182601627297861268646575706365542195996941362511818470741626981666515907116129009475699070593510735998231391259873187159803498218971037438289678300331546231558632880017491280886310410641881968049118330509105548007620941932337909036914987040276413738465409583604915751681453563667751824334061987229186056787593771125885597108332016281703382730666116374705585997797158137737813092924055802071857103083693472536402902517630663201992185586051754073675528385980727265593043029607591256159023993674602396878918338948868025008658100076865348973365344750196557756289571032043288177136077935551561552612454072749566484494318267341806901509198784934939931638187232236860298579987025529388361473823756213019841268341940427334192623867791090653285496354275608887614185748555585641414449250630795454542188747730539025096728279214771385188140176550915180172512601377801844424899026203832214634560065785372123945990420740943197680516973946396319661289453506469726562500 -5692830217163764191802999436813225293443567069975684883410280842611124096223524145246244266396934213428109961755632650956730703611101566774284389645373899981415140899630574629673193985816535102151934404105566707432827015190244813870746960306300664222088763786250409445880133106684444967958538366482632504090478246904424840981070888203835238358911140725841118295310020458600417541331320294645805235462821254987753293716412684499974003749751674110591441675092000314550025728710661915776819986286222733279920035044400325075274363903587191911545362497262631976047578389397109751474373767548585651071325809647951858833785952063638859609742663029440510252428707723960584881211356329903743485781867186863716377035074591048413036090894540567574609892518663793717981429714075507802152970355641136582415380407728014799183409162703330604520932455289332799423954652451987723349639597797676467252212911544437617242189448043943050408940237893994336552308510722470563235540936528882472286632343093527482727651805830355876364734104981399080523577612393335687608347824481861315019719859661946075580439620744866818143404125875713550868334365592832036580520153042283596891359586302798751280745699375652445224602375143779033559778811093371507435369694445387063844278477023186936682670005351330497212063013929843699589439609590023157644162849985360166638924445106960477338015919170562249756780103736114864119254618410117172360288336019563037657120752044193068286404013633728027343750000 8479931435134924324283761949221208266314361707728947345850519338375432969721311150402414061684613668638513340175236432735253269455110508872827312503513442212217281675134457285123523433477653720420875281735070607164499070757672921959473443466741785821950934044076958878959402677553645225529984137081400540336808956950794150678273286154317701691912855282729061533861603420287630442528720155426237815239274561086106631440481278238353985387462012357542206108622113772983965932974974151303807033779231665634695181235110317369210593120740650091595331784215813217941607565115713533007078641481610956980945450461626912532513970134030102643870609722799791646284969991787536811901871584871612819369908769168083030821243442782509571732207776846997275296828883059980217100613369582746893652885360242870117926630339037658729313457307226406862799742066168241519889451620316614269628715074105642425388619620381564253501797214981087800690716308094196555149207184440818642520671688470342219705335062002037709102219325378702654874882483829559213766100772691895377534553477677765293536258258690238109295937497209883155784642658156645061566629827445185748508886685975667192616099247331012757634043381953946803622532658719753320753307419146345943646897001786926124260859005464542821084503307194172634837095951702087021815367550987209855302475986932375283240584429211086305260448955689762597773988046667316223495568815933711671401814897040707767750244983062657411210238933563232421875000 -12323984078437409729647913918730849370149049456998377825716685347785962320552593340890353834857645731542045403616025722903181367192684257501019284324268068032070263586580501278851431312839356981378757480220360220698973363417143224407132796110732830937111997688399103108754930553924261631145012635522547757735411885467381737827606420239538519989454229276546792438741760181057135622309922377446278795612755464891558265163397150776901841602535536938579019293065771144739971878974580124164262345705174249081958505975790377470940533221101387471171696120119672110815249583346756508048913417769544507312608134171589165487873545373695146153085841431192798092770880023742907159425559357635952363175532961371541953626498780310502101352544643905369109287697078037014859763626913776579211666371175689282073991823349666018085751664966884207765239037917917985695937453159891342828952178683834338824296479126144590725962945766424803010343730047532995115375355082255034189536791150057106826570646165761051488725605719562355053018311332536669408900935944551014980111563033170634225901630257081385032874044236302736705519893446115945317066430520618047308141634207814705926772034225476772856370630732172666067381950926539737571030680140000763929638905180598885550467738873963399405623549093220357021542561616539468348442771231838552057112226607675614089490333659236804187032775828507221311225367193377275657722084961229160359138915928941659244655326688189234118908643722534179687500000 17386107168742989838832080844042804167477732395371352763907368863371182770762105596341878294800614904072804998919657078079696357102025771296483558778727287268809894921558297813818279773779060127939757222654461946095156995235915001004232388182445925325538140720390124032068255953854038436179270390644701685761221176890414099320507274743201032553170772152584728099497751600324837117143264736528716310995237776314203742354238313388271309412215401743433726896605228675625000975024835763390557215729645699094596545545256716172053232105590267212069422990771589539480916085392816247186232492408867911437399238257977605732750346279800834490735944723655957102197143407845965803020775895875427968360703626897489861052220751951155295704866510099817582863725712123639222025306217487791068187272625691397718285046822801674637417274161832887157348897347417077725523925314664586724628109558291093820863930380379948055255030441504772605385947343686016135555393292629304835414893829290254624550547880409651020357183062252087415414353482161427346601899595970139032119967215271928574904202413873827540452780420462126670391670935956497892524824056122252566496200330979828154795984728622496100085556505377367152021376333665067773284083092351447975080771449404843062788293648391984986284497469575930506157606998288129100024684181935275131426928335801456814418197521589019446268474304888507874806828516322675871921618245724761150218051829531866383365956707507393730338662862777709960937500 -23749413539046968391459160800168011874381517379855921627607643707237608762210443701658895464641110457927170797235681745933255972385450865269036174970237809845979018969408871677836899178517555474758367102822427509750646576485993518466507078721019617672909232167500349829149965813679657736458421588875667427323686612680935285271024974279601522436683113583363603788541812686785332949484507399653971182981892284144387682224111785380272543565292650551078942478248365356731643593424986399269390805166383059487960138064891241074723774970997118782588505244118744998977481663792745748752764991811545085871599056737850369900549335107633983460298220304713465883251643102607912976981385146589937357532824789578423636019631523087231696662720783861477070887508350776029402293968058603329810919931879126531435087453094542499189063946147475320924169099245262932150550656433200381405598505059995981541069436845543613760951241431742389175982339493811893648354245099750784083071033461416130364210680627660870531151310201829047842573302426867500820295475501255079240780289286124395601625177093004033360308837875073411979693051325430284902261085893103133928756741270416575055465453820406317647540982496919100560731335822751131335677926313607761215205506803902479880584505558749626020573288973755905425676472944286894054609984216346756778122646339827769054291489631649209103771318071658844595013118612950843944796862356403068593517580641484880296654402798139926744624972343444824218750000 31385396525780420980314846015468805631740171099235084100174916755740385462982356564767629807619366253151135061398145737678648869590518871506832859272999210835966823601188379923554396057445332903605923626400460497090529792464966154318333341488201364370896560748840114913122228938549909204306044684733997646200231851782270544729606742800844856932947027793805176616504275973570087185374181019579736150782387063539585207933519548680566232019186378125599366175841290133561128640759783931330885691495399885147410689931246602660533227173184205090755313735611215226536572623387151007664816769698143734736695635414242444143028813404072652072926687565318443950490856868096835991615277411521744272879302754434703886646067416220439896419541432582297240691852948835974447817195945012004503306553706151402337183186088600692177076342376512126208450787710452526602192479560629368376357534539766207090186223720440282147520610110059404890459175659714559777890164993665352396219858337693393158661408965867406798303860527774861810051507761704761912421408654661966620492182056429961846578434810517229129692151882142626395813567844070545677651136579850459610121277121787215245841371763701288487536762873298379003563551435933796466753985481779314422117222285267317551821225765408393381419358904621433339952726275099613920070206444414493489145651776638168663727233487704268430301450879593621275216564462609492119111758776110891286246775568990856342121986699567059986293315887451171875000000 -40130717751535711528696678830231888143604827708423958221920198661625689181462666056105966101512710420069220775811870307788132984724424164879585600490667731959132738853166432128055938555421724528325608457981934763597826221837630226907401782328716029508367680631663853751182278373639010921943503564657886398375243409010554215554919211527941858564312137600919166050327594561936805654283958720009276758250647404831083778560653780217584583583542593461048924213143386277648489066891940952843426941309126837081036257587528710014703137477919516647933725058171627097232151257861726307130544265935012309905398564267805330193298896790943157483282635326165183714244291203364498239216191742675573359104814171971483260344541022042053263260107351067003108686968181746093163339311957641748026012089310685822977018876850177939119534562749925160753430279889514077808615607973692029797740524567184813233263604181656036518653074098606353413646195749411947259124444927503559040888125195523958813172652579141612958501409935298105133113558645696781348746060385270861496787562400282651837576890551538621344034938344110320981191538409331833081716117504813105705014712783633344086500088113233294472210396978875721433728077667451307082405962946606447992171233051323951351305506191262221549916791209172342575400359741334228152791503092485431037412134946122046573570588498318597583651092192334021429854950844210182321286904249206986155347980908017187576253270719917054520919919013977050781250000 49680307051797170129715832596635618515153702067221892902236996702630328626837104798226884509904813524864575369190290619330317426555256092845005527826858047729450200999599235072306128811138789876041131649890250802977988571573723867355946471078643695069543152731931565603841053572150985474239208415432786656737507717289969583843199299284378855873163397932484389872805001810287813524871407836092491983691546928961726423523403823819834183766668582701809536482321745429392783006986152702273825119958444061818574933134820893473730556198721753067679996651178847116656551772791696060558340101237720225905463981744071310143881593958984970096928914030762710047387654280687644294296290092735944135740901415539800112843461600722290662657781765503014349005002070859934764814963894903928655671100280947856054406815580197927921385901903762892535590907306854531137805943836974601748284962325251882339144003588663921572090154841063467948737103272573505620340589386580404033291344489889050910799880310690586579079628512979359076141972668613083914481032915377945696207212290965455875478425811310478719841014795021858068871317243280917974181929307383720663177243783023250209414376521188725292195081707774777833378318955426734509468340790026316222616279139185701517986291620428524130712496834449098285020458334792725979673176768960930482444091884255286027245571443172936153335735230788718811130670180204123372215201917420128860698447501797689069419350360590215132106095552444458007812500 -59600232515539880515218461545784267844870098604570483090947374775166078084761539091307675460941143510506534860164820083164427995535078265339932213628252909019796926557893239096518440364553873205838850358073505916637138540916999163808625673294601403367950442281833186164096133900624474152521238367828938265313089334816948816004974826247932984500267142019367840804320336611801952124075577865135566063551670748907240673858582821684102395984025651446709562280508417378902793115900985373373964789126906099893162915513111725180667716578819417690779298356991392653920115662083728479353577451450213987450541646271128113063234394365580910832681199883491453764402462518366607307636028430756094932249976270460895596299652151917101518723095602022732730586491298358347811010766699351364840510761088583289016032450508739802656275409919551300130123959711460086282858750008292753941536866152926794905176444505160891896071935146002571552965761269978862827365207945670448102248195224661728279404139670354996402658412797180859034622624025920864064883862426233248133576065184327171684068752736200157757104791542131483810845532230424431945806139182299880972756772256476127991871462094163406807002958753265169097635126010143203563858360862738917527612781155549471780805863060778121002293385375169906250304749240478554588273614038383376357919071591646812440626012349909351547041675640530693348858741446597305036036241307698715002675056785547049592599577749751915689557790756225585937500000 69360398468617776826171510787561868499746204529021971399600930723569459671182690743872154469139280660787175221088244421382952242021258741101853652212115474752269933737325110878623890465495653304813822053601783063128600279040294050325840774267811903768713776757427404287147155405943719867571565630287166418037614822365776928850478329761115472433040885540644741678809836185345452296677491561595092917771450614743263692462667826544309525278322594014823772658581069608984219951430838215142802237451966755801341545461775747489557068058936366740609369075022131065151656154880265938077780205220645772733858861940246255751897477975490273740543159953412565741280460016723238934511123519148028777082706155327856523504757561285315092507760309691461875613197401790104909654992613475418580498404140560351303751369399209654769485909061363343635858505421623845171883509742749933234530205483432363517974520303210025460769097698087875810529366135558476654092945850129179677197169639994334501374131121055400729424534808675596663018586779105577669810391338134926359645467781776639182112867992730970530972324315734321051779000233578125684021805376631394402962549515687085627749217904455029416651769643794667730410649443495462501385927973055521330294953411995891492873663045244142547691294247929844655999777839290465299046227897883879465906823423207463167224492819755728140184755073466582358966955252135173218530290062186608039371347359688360807716822620250241016037762165069580078125000 -78383495814664659285964821855035308616620401765964893880061247820355026899144492578248093953134005961577274238288218701773058579792601135799139447012303899101843189432635176360354434394223841814084805931657129469262317943345318623343470033210503255893270570708492741748115086136072033251115974502089502716439717542789416325006439415588377589015592945984620795735416203163748275823278444405086040286428624827817122198973004117194541172959240043736181220401492544643276896865310576349764058826091431008857343054967524764825569543603784939147335806533457629659536695755586514203881055257057478036502369780714733093870530106742031366402004732208581648915296757092069731159039698939033991345334024292325435687113458211413683361687882327622543322785196031637274049071235675410618353435298542821246260359449600693906315041630129267847712074226200591526966579777042448907872562465164731643731030029669807208456196009844712405912284892104092243191440593079392314780176641165008769069103007999067190790813202358737928097722809844087164546487724092055710921948888213778689387817423374583153833754013462458205786115779953850452713369500802710837225123712722031085661207902110820477317496580542326290046068917027044282592427648032845381228462661043954364947462687916315428139867909603611082035573161706568801562774443315400453825923394772515984547097405825558703893599077991614952499963749120239960328487895770443335079175814229915418909766522403970157029107213020324707031250000 86103551899734676243826065159903312792375183158946331043144594439511288217025318303817533157821148112741609251564752441763231712770084268024478315992384899449214242384885842008247344240058312040127539185534038135995082162599899544088527446774510027571994216572800316139536186079972357542030619228942073933981152474320208637695264863766064070952921694794323051096124579428937032023062669875982236874100191983103304394633221606214677445148298854650464402444892622372874507397945034489855872594462796928798187152397760957961724223120430225141568983050806493591621802054892345808215515747761862914240917041686632432141512410589453406973107436696619734881474194210597788649698889658672962541063773469768761023140005469521570005410524787050689508619826924885586584567851558715921155437843672611139602306295165991082459693607992739556076623054343345628074135975356866519477265871725316635563954570965644480969006438468238293054063324651473145619810675266119368231390411308257215572275395292878556069036809707028943882579760691316520155736710394633125961864027171023908585135230847954918723213459817050608535347802566632365189210657110309849075568719142550141413312386582445375778777271624809108865154474076947449603721878571675126824128595720559578730602166598294976540016762257600367574612745155750170756023881797018705943853764227960517190614697738987273095997984823580455944328649783652097613064344239214393249836508546328224088933778190835255372803658246994018554687500 -92025572837645210725992078892186004840186788969038645002790041538456235182664345154472128995522443841676919742696867052665279128212255128170809453665665895943602867594796901549422743196815729012161133036181232165489867854763141639156676868583804455706716011318994422754134390184539067039139974132656839850381071175512099160137654462706380651668757263579471342925098520171357955569938396319247255148734861248059462100093501111888036351820673294495374294234430451415164239376543287170414979415822338095807837044220114542862243028626035837036185834132604351731673768664231638598906944447471951564270983089239113350908454130088936753306960867170187272818715277127631606481688247139153634825692423623158980246704712412281947440652482431854803729241131862300885458748400459821322783242057917253688401232146680376931006477415742372024334344137364196542300813837012512275067996083517702357488654078810767491275261242854425401195356081982158504445054577547263974652570966676660718528309324229598207247324190253326581124676293743973636583128293591139474309087911942392547181769989357126166449680201125990119158481859779096040436939276871801753435503364993290609391402745559298718210334991450351731345705768344025607710226400165903803208204227965495587822750446114380093814619066230801635157902212186266939241555538966912633006379078276728902996671388758072325935022819264722822804934046394061565834531618444592310724526649476666048665940422779385698959231376647949218750000000 95777522168650582619714330063842871772339730539211099451608148907215758627980400641050375869798626367546737937716186248919430628991179707171358777065613723406229284668301541234153984506493140420949569203072270448395743083742671899985301642416773417922741496210340850007987540126825866397623968372701079217160639196227919766851035700496841942720179744303391687827418135795484362087783042690230224506605196136313984471279880762443318110255028166297376151843365004610364171440010849606902735733365243586408665071690580094774466670681548415873754326121427532538297917813046172960427492879520035463169480937270591761563278120815180252189025163317741355866563484309523822489685708961263225579020503665284449300422853110016761899081298687170964736586394714140139896216558754711423795502617322617303330323850385009313674462931695137363523226762468384337513968927150864284131123191075783298585318359583810075059612043155189324144216473655918156235080918413939326735835517400618098407227197355691478801018060616144983566348727642640082979533579129998510030870978709750505630905192194630936306829804362641085577652129699300086507961497108116015085979958413875815264045172837866061256224473225837968329367849997159142482586642066936293478268794478756774965563572800695438547397256458738095322821458462622010512585259261676678262785344393963702941504691415043467396711413461789123352243987612985018712099664045889304567629443838434194491426865170069504529237747192382812500000000 -97147250343158866751038864461303277943142947203526008056268849218177801564587485569517816450077850579310778083340532271154198550544061369903528859803747917163470881959112726500042287653843863791395976940398658693605518583526204043185505940810457037110481865293663364210724320743508897726830170182528062229280495820902765439543635843451577242925040868139003382366877078598382445709230719935558326252927182045109290639536370952233936584391416497848099125805270107208001244081752007550729951480604929016921898283130077086129206848873708334684491998046533543914948760641974857665421559158148030570803497216770124275065149468688019679710675801822234716415856891183560383873027482639482333945560361559911933692948293275157811534172383518969011897565463029525756024149981788524992342189169120967418420243145231643833942111919257517826890506832858781506716018591883650570292233205700758810184301333926478405851849526280662020746926752713893929958811896260547950333860371409819695315451667823688771419093618598653336521683619511865796546308524282660395250203409226342998366234047929369996046948885011961484174140958094695285900858122224413250145252025403231752910699873574175339472821279111114295986291319456221976920919019330117691340259528215836647531093418853453114263460762306866617572441135518389193728132602572554008572237190509579154326722704583487621812743707304248111659067351769306352556359780882903363325620387343705894322987148825632175430655479431152343750000000 96099640985446644442443150087102821534455634107363758846974318038356939345524553519754847866930936334350025479468090009597921294593256306585785340752305061013659027154308430456835659520401849112652614896032815349716150927928330689266398580438315207633897274733647256264612499009291319080490337802805497983854612485355378876304582103211029310614361963760599068124973065194399945328346869660683202919815427592517125372030012080911471851649769073547896115856047698095685251110687171412725139774579372339776551297019221855667955504958141592049780380141369408553430065062138999446130410003153931105384819868903073655339211068291164798376399078921412107968716349719990239316004878689753437543243302585111196609113631381555775932240272477034588362231050753685927228487171102310083682469868335643892521175168895298250643061261306056769944090863372280608652859637566226084103717716772004741683090474683429542954551134498026573197631368372827667580318107004485959035276738394232735515733617517061761639264381534900164443894008692526216734198952287199637014417549039589892540970120063661362391889791917324993444541836706764896695149629618583292082593445168964621976918298807737422134304198005439413210272214850306054616202484874209027440621697887086738183472544753617015848847773757678597180900423769797989303046882482377068343883059910049657893976202305498099003546400598591135686357735416637133754182431107491196177591727331063922268143684402019744084100238978862762451171875 -92772580891703825063412876973274266083084343180557203409618191481922103087228488933901197473785748415583898151833776733065107301162475870449601939686895034978351819861060660593348582528140239955172187160065049874108948112843904642909713607301147282035972768545397838375528425883672878071447089299119074823884929946959492123464521224244246501852377059701790077677349186824265307836395641575593606217234083931489508637517197822833480965889257590253549871041802586883017710751685670381599693559346971137307830786710240972466591481059229295293682384076065274645314079250719948490126107709039196437868265699179338551529650088365722311217091054002516325826111530008297936882002250639342238652986965468750420721043105100163304014440329821531662536837092666762992104533997817744459967853207329308049495425170132574795287099340409491515740358701409007789327532950730371642242680260852772742769086838644635234844670063619485439852919478232931200645676271765743410557776761205785851371791212535027830876555143247445019851062531066404166277272202156981384690639683919896171697331015231565068152298336634542515948993648793431787872923035864227354791545630233641884968289161756251529875420695137161493110998757076617196315768901375991757528568326190956547645914420915255625610915705066242586291740492003714329613672951441399416437934925464057504536571209832083728156447013907328604847413918705698414418980510706300953411104298104983810219908990646331403695512562990188598632812500 87453701486391996550169258764701322530695095800186656049941082033509222685041726295868139491102837260739143538614291480773791632740055525672516976696142508866696069043871810407588187784060617343855824901694741988016934246397862146185841163953800048912217144308612965117351198594373531613898347940329984177539196376626601896878707569358231919866307593156486298275724460492010548248253825326262710092449462764264899625543213384731357266681944516339260515179984710825064760509829931134170280878696178508734942590026674033701276832252311198047383754350734044985524417623576639931610513090515483809780940874426227640762803855472260276684235861015427474144893811077179374534641031925544164862180463399938466353979461333259285699676786062374895637093280098684804506249668428055557419303051134609611873049143112666877218856400530475684258534321393919183396219550371132757827332938255817662716013745667829546249094417053107887816023207703821464308900717656080207891365449090139388090354029695733174953614829706504066651474685703237176877642981705804264133187959668682752722302315063411832741233457882622878462871985592791212223248698677286251624414143860756240146790444124617778730396434591491701169775917341484014772925677850027429086860382017770153939797914808494107333168223340551414397683112571279093447441225663595300503180260940524000145904823190364881461427580077120388651684070961598703123841872245050822546667546501957983063127444189888137771049514412879943847656250 -80542554393431995539372048038545856137336992645174883026341432605126970403648257459073111461978484172451073751193368326152331506931991780786545695549088742395617041475004012829920469568068024852101825066445257732537576253954659591577394095610657227230502222503502609310728996451745393152750066474869128014777529720026002358296685811391948404007728260141562404675803270530148774476293511117420351197604320850077082776503390089088801856742903460422841175457912048760229490684904401754158149112132290445886426770548436737154970700469469446455413208561684606441087240685929948309771533400005103085278936278318519574476149489131230957629680661344442644284137702997819425173457239860128995510991228212075761035285330010792147925210253860392911622449993124355488804909941871938304346377464563039134443754118406130146063483382536176531203173367085126343978883974372045145576565474562042733430556511870091319089117045529790464271481338779036561528748962852998418788609797277040222083453766939648101256841548193196023996807550751367777696111129972488494193429243106676846794179607961926149459947738464508879985954226490327430598327197314507806621436352656738300540650420609436182934144965725513127393111177254089053104604712620144304349041067767628426307586155894242516804019706244495517062128872966498047159777310267269221987425110662880166990587573126593725819286423784980551116904736289389312639159296028406632551925004313546504162990569142266394919715821743011474609375000 72504540904709868767343946006481052695778837611676931888267997621507207329770143396163026545374186938701318673894946468285105385657409260416715675524751667490647932362473314121242402416446476326480568010281178440111549433753394086319142549012827915714062487240901094463058328475715974281365865481451533072175793078284632349136635372990741572145355864578408034541092221361769817805431200724203820480625438166841581239082370173621524898323688371141415688349694361420514679141551854234102438744939764670538273366726989243277888587568196640398658410572417193737860418658223165400064512559809839913221774777978560900044400757107910595081197660184071186652356462458831934956415941535839732216350844795116404152105687659627972716043306028812801089064446361159433216113557672691354820699403568789090993421199926604514916411545159942491092581439686370596474375948927907703541341699481167083985134812358809903995835983324058889264312200244653031613287601614542038526967705034988675383211627457303927290576944061805751157491677663147758139822589564310164645190190383668247240394236715165876804487328503339209104105069105979711744979205856978119194751589748639322074543684942564658158973691073851083962602871386202080128964863356244303754276952962695012458715971639731331038610644180849284726356238730733636388474387641924490582216304317331154764563971322601529074263654605467664026611413741534209010073693601072017119156853701962444952618114246689628998865373432636260986328125 -63823344708120053317001148535692893207669692724789555703671435832768895864823821374390234091924654913777777020222459649010799158821052757481528893583835149676093391303503596945638022150444754937228761175152607134100494722003169543552576181187929392091733504085849346022646559600820489103388623275769101260004192535174888852723399988871872139235434434384824224689071770309733876940200444597844608208258569134271868797384196135052790948282980063448650557964443673678562837317855227149340383290664447334673843932810146589560992423029095277512743218860171033148951146324543215789657341919302404782503439730066521201342922583629794236591605517130248468255554295208107076455621840443689351198812370597136177835714300365943897360187171915517574152519061756060807708481238923014830028877180678985926466440065871580404036551914062815134294124958683884232845746970910976986860102018638716947502766609543086790256621223538471501666935968178051834998936969662720958883533959470241021119926308574958767823824542301081462787402183638243508245466446258107766865800951963772827871506778557938992705461385123988401412361473214861355849017603800739377287512548188378006020893601702334485276694856924647911600564358017748412431806590595404665285649482508051673097371981890650214520118531877210994577052375939910363601076449546447571172676778908299145442244872864203492975330938849812192023649375432578920761821165275984340842384175551450797587299534896487784862983971834182739257812500 54957911308783431241776885032878491084776726433400625207772695347908096271255867119029368564963157050239132076943196852253914556073357374491107342352773624989902597433905821833588270889980410219185072881631600829719738071917430301198684090955043426849019465828621010648479329480776194416106087233759829894775366971689846708391700649494637183134843911087779983895240623659811032074285919606297470432451635421500748694224718259633961962576350871000436811343155815124604284575751832776004497175472927947175015245082132095685706548125320701729728888698092370913784310257250979757880227310264797746808515107518969749403057267132098352820189274310697609441105476403512457375911253771995840707259467088650301485881002948118769161468681308986459601862439926895043348614554950372403052294618443475628570360723620633231031664131262455677756170294830108623185896377912292508162448167999146126427697789635332215171515441994782244683644004981110604240749523413373513909295537367667986676069381060024274873189809185446100314715789949197535184507822517504202142055018236586573327554610370162677565124145158365568558408346514273606238013001555996134546332592877203552680746499569070964653503378196593331059605285729537158803006150513783086714423531270126165589864447569930681771443313369286700756525311565842483384127371285312994819605215543678762573216986350526170941851100917744344259656731428182685146886111290067695112586698441992788533028146957803983241319656372070312500000000 -46308471095262697183908687121871862132551452081661481745771216616880071077347182177042574392803598682625891543755961232835449549499937922304520208785349364982153206096057494135732515145279252397092609368358165499648183875733749749199278747729239240272014344964150646521860895521474309727590899591450142932967307657304226873180635920121500968980343618357327544660286896984166477326623952008400700536268524622558320092338532017922724284172650006179655634726806940214682924610108064499112632767380398151028454407758306191519551073688716387486758895832357913301167775196611871495724809194762143747149344857198269824199557839456142776269213219370352380304847686110171816899762443421352622983120301066401803777561706583402132395913921042107176136130105816347898810726806288457592831096959044641593496130345855549964775649924872473513858829405735071208106173205424307518291140247678905998414840978309355251708334487129711449410432945376483291405610895704530993760286690878815702067812436381467383885035439240427727674957949564256091799399655609094206191387568116506855202488659375775746233455688805685286367534549821509914739659175923748936094209872932414201714544050674765246941121754435987244617730552758933544780421378987347902669970730848123962783406073467299766930630653194099403514934908445171835113956983304870455066784160100344079040817079527062369056637311317427815699620955337860650365514978371069570229266266656914421539353865497901097114663571119308471679687500 38194120076193523525688342281990692148627320939388896094005077625163977316074391994660202580457463294432377651437071989885222411848893163378735053387502476170112517124565097081155051846182135392829558926923783885435726005005447894970315807394520623616050745919772775792231775510130784841632694050067978211980353252675343656963774764448500177188365572725304230786275454510459158465143738683271476380073589778866885402307631172163906303575331433481822164052353897597926153436479821449773418488623271571447597134680417092519289621900316495056714593159115054270457108268070177094397058212220799487071578098913223352666245923954567512637868486668670609331211531554192138039819233551270476006784343081348399936173966401461302293609859833287959128971208126739317941461797383442129178383397656180002330306310500613342704007572764053477233887247825636989735089946938994336543444437166151656418725428418384151949190329227054762801877367100146940515764578810864246658339526233656618329646531085596934538332774611389249479339346400519469863668536786909160960633158858855045732890808185897387977368452632809160331258582763433628119775546000481443078719143828875104229557403546826907550658426094080214098069690738494380751442901623374614595025470323803367526126143538033940839313760590959296180706221362947565476682691095795883246015943219199986491258604037545263865395886828412503600368591812238943195701027702237270143614096938201383341603134535802155369310639798641204833984375 -30842465485856994171170871968719452998189318524280640171965770818559942614045983748503609673236269014919753351481193929119073552448221396380026175406917082146844848225366440264620452715414766043942343811682572526210962974465534322162458786183744561369226986177303733120149952064065861388451912292463562243964442095348784206966980867361471373468905162433027132281596135665652720588429146750815112403293354121618052476804169250411334574503809407634048217561068612485666141183812226307488608293176142743337848688829494047866463392902051218140065245790985907201964516960977821236098475933391866152423383031514320077610916772769400530306525755938189970886004620488177811903109441024269899716492359000245724170867457029848278246948092033361445145393661601783630355770156897974431201224125962760959762044608226203803943277114612215444912194632601310282123566736493785274741478332102571272705574354898177366754139615593077039548695463279655647799098880720856188062805052878266394920728202617741000313020307746182712764680679699196133528407789146867370204134022525125216732345453653792273592357243388967102017383185741793588255454941880856490544837366758635029232085553088488115439170944889050802596165080224290329297243822116100015994839927959450215115241174497071957678637311968496620507851785161154512123490004281658835153685887585516707241567211216007674634130591506487651761532536419211876327305706288621598467595030238351419375752993090600284631364047527313232421875000 24390150383777815908432458126382695969626892940257153873925948532525865108643417891254446387370310799517880433614679198574360795038907134452925004277197667467150487167793148874573053715401474040974928211810580727386178434903409130246349416789346999309553062816610520756505648962502799773797082420050577215129964667314534212336589396528144232365449438547129372171616504081693836320794377421669315609971625170825755530129379677854104428829737823669392772043774287789713164928985550503322116581730413827737326431847736970807017939026750378665011065894560017448473970317595958751503763341372906608830952871516466542972605124562495951794178693565201489459335075274078213250507448969438386621445142361337038670238367689074451756822948783692167006923051834019391735305582831740457528775404252518877025304461282587691753174872166639509437091404415110901993352310282412563574332775070117451808001124012456740034777296344829754008149454941730119229494580986832751024805672989252702673112059077405071262221422450141900408075869503790351452303270888456686121185841828985633419210155984234481398826294897381289766775712044776317670150158425104746654002209973207326073413607765521117244371508653939084286285302456699366329635321359412363884808035087913942274358230603383245525616954772241329527387651095427948747078629146683746337697538919204524451745766112552385229840754132164366920487800371376218899354516887373593477904653712922100053037133271516267996048554778099060058593750 -18891904158933702055325658244824013287344335045742571218916578770508961753478216134377938535794515445252731299141311584415741675935985404922559418746651415093634371803912757488284535762782078453191665163791545485787082822845760986288499738423133438564089945568504444871289345111442608730618534843988527929870464399061693450241743603909928092687788980117771383355627252440367289746643634602686787927382715623345947157233468513984367590010570144242951342820665411574469975243434124040801044777614313005873634106387318116586965325126522569244864440038590222623974931894858283868269400321226036525071036423439176402328165538166616343029920128363894555692305735785052563661826633714438030805471178853867242689390062881503030882521363143440286512036836063231221035538191241040557341195783034371679323058342040648176167301587915848805177978362080354591652070249947422406758382129176527978597467395673456452808682618561173653939688540458015181417758869429924328593111930264139446667964541679608195151014559628656697257751748853100981071724737053387596344971627620892116695609087920966412526939537255352186713113291729571433206553530174972562057810132349131458386246808549812077218762867324507784465905329637792654988812125444396789083992375100821480384419353179308751759858214619255218395062132646235604319440128310133051655770269111120344825058067632826814423574912189325830873619176790365558248546589730787494857261844216285461613841212269448988081421703100204467773437500 14335197347833620607116567485777886154101401261488582873281665161389967825289978797006264994613185516332744209420499454012995395134736644796409904277624655360985248696305783093927552313236698854935793386123499817312050241318719571266838337186251997902955256909795676206169993246375880896755165333823349316534837029158915897615943286814771243731650807735677355440346174127218373463005386057683805482725244689306850288632218711630370763239276023451472494372510402043411624945990084321592559555819022776663774507711949640744416556933319261888884262532282325305266737020186344358965084566070130493602695580523019921238089948074932079504816600410546399303240768295772294551562003080833740181826162244181188013973862703208788890163699167476203048914680315655722329378023595965049867973862820706005813252703640636410131017088850477442787006731772495446188710076999880792973619148434268339852454785587730221468944522742785996837679086483692821265136598166253873600497777323989984864115220274501264497133497481868835087565892759799398528564343278920170884173311737280024599158331208382237267079198571976793036776590112251325434785732403167266649282783563090729366970462221893968901818197460559780440448475457872728265860554356763875545618856441493305508860995779482380862921603245089911551597280187065607624433811128818080175492243233489373131820946554334632131921034432687764641531568659431376517169048332283401967227490605752732882351152543520811377675272524356842041015625 -10657560929811875035252742605367125233853065642335005299504967505298523285653148867535516521111570120940358342641706001563504638258460134728214432024658154379543153902345533817377674782308286326930565108334368178326006324165450142173841092495279323668187839697922808760115199193757534672843893212011731969892965622884927260432041439386525027836270655420067832998597749816800938792791859742152835720159916863330023320149708099809367107780358387889213624597550273140941456239362284165242865607394283339332828672639158672101675043414919070041108038778726262121121380417542337640012857625291247218387096030197528103917774854901991806584940887839201286417039849390941690141644693366695337336272120491777350957220825786299697751128867400916573360042840786428620580166019482872055629664763113092540802448518894015679441610973406816825909393934883651402054305156979001112606668759462960270008081561489977357922464915842219053877279173234099396852845677059139950753110080360336824522473429774990980615855662967925103144008826727992237067504579992669858032776280212241772066189164553202403476165815609481954334717795386411385047914426846329136278021504781109769956081065775534290839863448380535127584363518378988863690816493930963856238963580319741072266874967882774512297075281853207591264549182907195965494054316322501944709880998523919620968126171069444414960208438141666831403634241064671521496794078427207491102209791988754579439291347853213665075600147247314453125000000 7764030712181502516236848362821173732043638987260846378439302435831025926255896698223239046011813772708783199530902114666708054086746866614700264223373950923765108127443542539874239453631179513382223411904194418796055294393247482675144899742368222059456091691175070751750079385233267366295409719442119968946996925863854453496505379431379263102119356726073166254100332731076998180718445794897120171555055089033834510690258945493511906791301551759852695094580582198268799155501152707504122469559652136298521092573147007527871008455657690592347321364491942084913602428394778482107740899494608995137637593314480270319943759330196806442150025151555522143937464278759840269376519866218619148848905321933082210821837603712743007162636142827789473785518083945211275801499752108168976697340011850532057095739812793628369765138036034116948039858490356077446631291580677258970147815491836301830499400325755483657005122113503504174696862863450078351922133535153794360851337662185262097714485116860337823591159782375175977189084503162871412719084410684808182216143700801558894915088994602392017680193720386659427784430861401843267049974882379928016854368411803018791126118016153075261346042509502340846979263875810954088041615500260022252037049351943062271204184504566377647574131228151250320173487577529212650963337064879525000817801396205514052801896592933320668095579338057350007862764802116238584048596084173963005248232900417596630271432900372019503265619277954101562500000 -5542827178630342928991306804149321207568301324601326464571743880157962031769476795359715868608266777926834258977790505472152078767969843804619488321957285203131844038645097497699750863929670793914251868373841777927586299633428663064542285634668080715769766213949222810072542696329991141246474355837374649927188333720703102693023739963931634474247492776768259328764780688099750895052826847280647168973026487518022895882294758109162835439133873269476479694155002188363265130560370288875422853289369107818511226006716313722601558562458753212761597620701276853937399712376700162686515715402256610624829334884084143145985772012654246480531708398024677663170286452338560341115757818055625702289610787142660032908759927049253955659130916561014952414565214676332861515892880415756727370152507230107693942189070832898162459152228344360496182704443230513231009791808669685351436644043768342469460279970361867562015460617445034127276748675365164670595431454854293364994523348826485661906249695145508600828280840811897040598277044877403987508775663741015306607033342769010579327200532940632604077034070526634000002683646569183890655474149010295840430178002396096512458073641383082827367533349673558851022048007014556267753241139404953129333624062407179016708678332754554670011968143928633456053306515281454298919117949435320170880314013329679341990922557955088316209176685166208881238955326965821626225304797451410558155116532308252785821167663016240112483501434326171875000000 3878113978441736238040331779877651770955327473374440289299593421355986587227120103495099027352536525454563746038058443025941372309011433013698346100627821438622905443065890168477226153859587519104962103993558240881033663766267253210518950126380649114494194025191393017888020067956031209824272008773043532106234248349053344927337745216167494366221829990919497938834795833389389573768069444740755174953368445548807052779449254096083457631981491013375470102025595042891323306844923417313968241552879473080427142238133603898215664947192138680728159735942428672305749810967527101038254323393000650481505089161735641861920155375432478796411627413300393975895697087017443897205353001809563840318415391914400736489251725555547824923730396992953147901506295702774775349275037643115215008678091162132299479264194181568145282845838448819381753017533367956494808835960455322922789115315226723672908536315696995394806807299350306026774885729690187433660684316914510657385069927483609845162457974952522812099948147567533095696569638186335719978612046307185531289435701483427344819837013033213632451240969349929233836196353855271825393365660760612493974764978050457352658838731150277451851134070389071473414338718801851301498152754776263806746401519868935523740817231310652126773281403102396282543571216376277007737913580346553037949325325450740728222905938335465364002498818971760487636021118133854833346278396735276109038011583196324028911805559260983500280417501926422119140625 -2659360133815122049879333355540537385830655217032267387995055176755988391471438795683254037215273195735775703645981517156217988975902378628021972313782135406025159861764728873168746731562961782260644489694623876475958525229844873410402345021239007805223942321852422751021945408106555645646483143328139465022156085522134258011841980881270509259929191916726318146253184344305992354319345730217616886146629161832255544562562586831755787146976030370730491166651251890366718116643310077832773030848406688327376063521975881799744335953175205532645699895871805639043291830372746709137067968587568555633538369006655372458253427097206794888118193499985054634378027811476762419341135744424362119798649778312412939380079555684064197952521723357056721773886875242394020465566334504805065449303018414489432445492766344714169370305595427181972595403585889051400601367601146611967907229997161092304607969738120884865916934110197818336684233485608130990456323222990158795489546286264079131758251232611046022674988602935606095253068936857066483719568236780652287667462502274295677275270847451552220789548446684218217684604660569694319625566681769912410235407645985476867557087949268966051907817886900299858072193825347063186533678811733808645082363913918042839874655188710828108268201718796917074041935838777814468558275998669244059350487852119622698583506985824915903152263775927877653992855397870349019705267560672210012701910579521866109103944708635935967322438955307006835937500 1787375121793793325187178559576767634374089096179786273136904211088032190969454117987877485827233754396637682267484362188111500712232441481506456952241662515438680639923491912441383413367397822337688910224384519299986360879728593660288728314909631406299912394398784306538828828123583281418132657780262049032448946953107089212244316556349291071743630506933564138004097671906427185987120933990196514319655692627420435470609212637233752886056511309754855158564243403753660724123762168523285036324801534470314151704715834087979075136764905199925823349957436834898779205308246576106618644002974296537010450555215409784733515909630226989608009983858632428593434890644480164427643315258911061298250649558210894883772229591390987153127299957312243389282859329736796469829254843618079176805270915527817217813251994342944455304288171459208171874270934691704634989375457024400165432871462833244019543654120109565857446475892339370669052272270995145396772033850119653634716983299417201276563939603796550811222607257512291157774429821354875018278676096669602011610475439413969335943762168778236162309202624272086018942770727136301648043238255610983809960113010336549318150108678172096375166016206562754785307227573234820902566314879863306695645547481238217491016962498876645583511522852353429058795476351106657075118743542076115335335898688300631237189226941640763191162647168858679293320793794347056020293539428995694537344589641149122591357034650627610972151160240173339843750 -1177453778960659363467193885067666774740641410031604941414786315033253220651136722417216183901566548095631719188641062624335813326051429033073739050507500487180975150259397071486358121104373895286797854365316938545014034232187747388826793320529705597075837405651918978551228495028335877640400287375436631334069287973445376706784805314060091477823786867753285635604297025928673092256105170489024586854413315661690985578111959333710197540312463250475401695467779805715459708443020888112550764636091667130305372776669316392293198512336100855998887842141576196841010763220139666980912500820758048687318867050692787348411416196724396887747568503676234020366976699491851157504472502469552377312422472848358288036820988876329874302144989304454927457302274965356002214095041563670987020404017243217776446761324936328143762626079788308578932251382583168548100990003278316010429724559614287299438543457820290785957107816006950852717583825891511845425687259229338633459698601764686407322528478328733793150311181469940603158248809754989702958606356866858153119917637828402283450242512375081754544484236535377525868574740555540144927300276305091747686517140325316074463054429644354266695997524600328983264253356683628357824518488335030619749073349664769196769330253866722603928815343092624842515254610541919566268804815672643443020202424484255033476073293979870661317901317290768322815166461578213294397816063603361441268765174084152784483858766861885669641196727752685546875000 760261295952332600568432408682161524146376404540954685293063989557316776980354564121170532611088750508972183889720131227812826959241368038883120532241661791145880754676548877097883514938898772897815192691543345242045786098411273784702811483599606374952996338617331478183976429219594114243667597207951229699868925881632926722498622400379076888202786670100143764869892820289845587704053073108338215252477076827724035967264332342568735021241177062841835334326444996877541126396202324671040554304748759621964660772626332163994079368794306890271788069006680304105812383443762325907493838872693381638220624261125606381495995041933117058482411964577825585729842430814085182226608256925153392834209375517325366546605700330692890692170530585195633301586130821332066420196456980690120192557749292781245663387698286083941076365163280656295351030046832007294498210150258432453819522610820896211672652717163678190771376648438871441937353660497658044835454171142266090986539174349364977319017532122077370798234427724091032809737366938308102274405492798742209993607879344335707550558894148326529945378447764415846470712705847419082703193276843162247287535355780839702430083914145147427921162578586021874404644927190112611727337544520939151420428565526743560264040580855504156857121266513784566495046532742646648304788038496322736473587051595391050192767967555329772046100015120307756447568493468505147476127890634053928477332824978013130733101032632248461595736443996429443359375 -481136379591971351921786683093500024460194007614252284428515812815151732804246195315511512979728940886946609065755199957044948577128704662613467403404151522288446520246475004034706217211613457720192823464932130018323723990383968534553624378131382617199674721529612103408643194206316086721655747368776058668977882302461295485037513149428245294730689205176024871312065960734520326152269298470998772517228863926154925251635761297339801137359605077240357195856436951178277729452504377669707695395675332085977058784615124664374992016711732127850375377570634859391231832911880742409438028986220855527555507226857597824852566679133684019068369257179253450024685165410144200807596904626035365536631040096808049482999918287538278689487928815975902426268821061243685631602571899629952804471035085922189490020632792527605396073384094497947444571882562979868162260423414790209631725627402996494435430852039714458023991304312982819371073450474122550190673868537838387131987472143810994328522444964837643428915864871175577730785419371308792560582018091818364817023419930452723827100125272784904935145916635736100145130626208492123894682094651719443304631150016462265362659779632586795326389517271718228322674349373332823664540915859868357726170464337830751830652772199141052846264448941556379126984088512191481147878955832411389929695258079795565157031735154124658876033861908107191167595147091269061622175119985304577079249407709621560308432819397239654790610074996948242187500 298435183502257202346667405461788802540036362419559571629121457627785333787225412168432922565996320515596162374700974133402088957163949409917993814301665741508081892195230610316450872334702860324296675589099802593134542954437421746426837654866864342043505161780354512887383369576497311456155411916326860046405251616310421596891452599660615051214518039385164805227116507735139159923085756046757118425885854675166403367737624475981481124661190082922384023455250929284284008981312121681473865776538660495966384965574781568115849776712009516874396808716517946972223855278595976690400949116502439463564939817281859196824501358424816052232599821318016330799202989317338444927198055896604139334951717452201575864301375308919127250034421560966249934929464568037498982242312582362912306707394048206672716406505895540684600680312651980132210748470221547994644993254428404596864493004978304611701394518341522338822035135357535738727826514973615749916790749880832701109317078390862525268375820372703562833683754089302873375282301934594263653268125517793357222234284615399575284942500224007193554462649377234923381518213214776028727235456267261564630555671295598669347793841414322507307061010191081819742330746363978406295399565789364822531935638806164511918803803872193515850924712308539996961643186509523512977893348487078325727336815036629743142221449134004765556165088433463550905374120056341936738937938601087564035055650743695487836504298684303648769855499267578125000000 -181423650939923209276492372865648772373902391954893771694374708078001011338265983599106112827253556983070921909534515318848960664562527613820211563173766926630581131501843297008212745056018825219228246146637867503313838671872321161293240142543668784236284397793454077450732470453331885047136189451414842020427163177596541055156460596144924954081396028302285860444217190350355928028785309469435968077054647885181781951111203894928985445496547127104780009315443095860006294406881691240780963206800196713035502888343796845526152527716595041882910364274508342015722004816709340536041048857399536961139781112700331524026320826682696753815644515628059622219363182632104558634175708122586027140159259888512320592063368717627356146025739696409305305168489035232245858834438645552106614426518757652615999571696503409825368296482624335652318678793737941236807895622429290094006791244716559524960856572625936079377279317833183193073849509862500037753625702274341343236548710309047295990585653851581560078942431878668909314720479399890890616996350332637087849668634454485064952897052618338080709164216317937791381714064069107111783400503140288985160483239567585186113985904487949615408659843603876170757725803309526060406936046238044694197483924263921107489432996316765467214289699415643340819603207410085362878248175994154346907324173452271309591166181930701030623667587857238207571001664376767024911374684621262154591230721162244555327847095327342685777693986892700195312500 108088944417952956948731876353578052179484538531156831791273116451861155938295660422875319322960494755359631027485921820684646440049635388007705428122376340800929247025010060110804340780725445154683209272867501356083699707753083608267611667871221451996564023083887678016153681895080986839496577022785985011045711839896706833385522074913695843147722823299554054117288489850537955066297885889810850603599912338902111672680782192906191145851749041227091410064533638275615824772559402575877850541430932635849522606585748187355797865743250883210959122535834349104961033559854708915735824125601264426292654206366602224626017808149399971305102080383033444867739609735694515001295799947595269698338015591785259997280904909792434005865839354759410776149773866298408045994712107824377210389375663323690020153039493999059857432201593575118094805308438450661884163197171252029253277723649950161440732189961791089797098082611882304446301968935684652436143579895117410340976098505231403141100254393200878509687880774462059196391786363816159853013516297290335847334715333777772387154466555735586717125942681829628385516550943539115839486358579073362373143414577799827562091667163265173101781921405958259966145318596225997635612170920041681445260155658359763073970559132074386323205037924087435021818246050833862317494192161746037909322388532706352547142702276643077426606953428665692105217959249596434645848144918360417314761129843703820092859491097669888404197990894317626953125 -63108819059690930606476718223890275096225193909231073443031113396216348566615615815014761965493403523059844944458661089286432420151627751447346170802296769897428306973855314777025596744378797181273791008225531046609014090402348716732100139056570566256025830418723697872218222413580255530009774220331266735760902152193747180949536979631157431399865492169302545885038136265284995873273837378831968236203075248530925159709895366266250505386674544637906957115706039357387472199230396941871300017499261344354746478165926015394416855714247819941968591463241950372653742834742152939840127852261221415510683351307532780007995320953501561242218262707169795883762064016516329113396463518948863548327036484886317384052620505880606401101835158463891265542263255707109642070742974559397460811653857702569417804787235649578306456551038718221815556736227769876195495837672564073206536977758581430791216340454296317871863572531433440466971528229176602594871832167941982668889451494019685324022378355051729695708034121500803534020716897212239029391274350813570522877152568891691633018983784094760840053992809447582623201427994337358325045567584072198405726663225594305041865833481521827947946603962908775598193672700040846579087133894477757825431953010081532021142534406335317261832120246475636398503010050621970574427988596175902003883212422723147944418786711615013691259212189160564050554397453189067861798992701381566965726334087947134443563612649086280725896358489990234375000 36107316263191869976019977162766883368453075442542036621700242625323236253196949467921463286284337480238636929369453848980595715222989556459632256721050405827505436318071558696307199368824727664622596364182398368203154818295300953100008634955400339597264523677798795768709977421321782705209370223215972493764571803829891214225893971446524194288880997253055573186953806614840810596740115553821905367076809555828697700956183451037430659743732816755179652580309687040899599031866222144365574075379933850790920499927728745214683795083678752174447775388572006000751284335583095305013903949682983599914392340726083057328768409449650587996838412231952322070656260343067471571477602367046381018295774240299638281279629124540331561933228333832318635244606433579810745629162783230415691804744377886101096665158304298885920411410380613806374644481180556528829497401628625347590587195178146033967667953071132545898604374887224203910588851427799790249828098039870863941809758425396983573788607096477754267360330760967306512318745489350557482184194110740141131767909547249313260017459118175012873913228927473101419867563876581423019524360579105292267369732211760344408077600234846836344105861755482309155892467762782282663598964416640343832452283715441932539680277304415029761713445760083854628871892151804088962782612855200494566586008723402963147989180670951529319087263979041169278442524224792216134825135824214890672046038444265589686943407343733269954100251197814941406250 -20242744644672656744737935530054137972448937811615802308127973637321044155279103296156874818641895908546631564242339550793596280600970965619152534584642488887206431714384794521346024225014406774834550432595690885310042104944060049642284178268785733068823986486036439909491813638691190508297570036420267748101691045985544788596851645054385659335062615607973285699337212077561700315035014130104314565619073705002480642533203067144854406531643237276580800726723736921340535600271726201566635796042626514902000270161959721055591092884848808015096253225667513597486180407596328623158390574240911188432760906791480670374684401721801949681208617856414185906306688039525939284438647200001171626489858453028946891407846856028408862567542375379300038785154941033617210624612416353132365820019709449684578924665802693021473607274535880570435609632282708250361234941398874250366012907539190495023263212389134409496606389520379134918663751121322866699801822151930336820482950094499505568476238630424182958525255820110654228409715569075814656168028348540581173950130475402536335815755376700341353351514707219970611546543701966219544866352044202468563667647863298030242313880354881483640991559568616477845697333432851273223482736997858905593092421851551851533687174150112873170334852055847092769142694498708700457014627807243683322973887010321300509780554410547249933916460963455876803254774396903252548934559620203989553956127902493034725894816006075416225939989089965820312500 11119457277951171179828294584210765895872338781499626734028763469601252670731781083008435433371326656853557371539603895190213167232862183187485305465904027616650032940023080924972894651382200438869153776193964972216379213746567745004442144090412456175190381164077267023300067101103923431901715094673593536297502272079735396224995445137605704096257747971855559152087704350458732724410781003742195716539221514911293408282204615664105344243829397552546059256650689279029887702367896277593621791416526571779272013090992558587436225038717762728771367284957957941980078373309474126105805640640973580707630909927202577264949399496725764089798618152399287336225579029387106138454926850613240339482003110755948000453724446330469319316073215337493620434085755730325862570797452095959520328042941817014320278106795386917183597049814059844825449353882103903388605956050086998874234765134762462643487382808464017919128249348765458656024486253026309878603358821193391176348104744495981200831109331094579693075633745134347983891910155490659455030887130447872911904082170219406330508788288714475921259297936193920262607940031176807612245777333050504229141264342009488336845803381514740040304664586206523004799215424039442582643922426611178195255709662275186539983387633896987459540112541649704402308163952088690097387376964619898707960516300500511325523723825048510981261824977721178295834688259206809568825634026622258070588743524614232065228502932541232439689338207244873046875 -5984223273118964987469533565427213782854339452840437519352108322408094721997166279430874974872755847819726999309995070084611245713846350182157343043609036457045131202783557977673731454837875341507045450839308752687447190645184745207649930452227540331078085217026033203883329086083452856642832707688873461955603969658448036610603015950000337851415625725866135284327127206350061932093253229851810849465053528308455836754264156239491464632306565864620039677793635055607035099468382333430447221773850250242726734625126283555242342641861771371644135551496248206216079164554856605438433766874337251752832897484405844084666103072905181808510124109107841316592233459021906623947795935424256155907580054191500076560651186638275121470569690692067337136102718445495091258698210147070957329573675525912895900926478919989338570359736574505613157915441260045183512037197579669287319938465597017634276118562272324617132169587960849324205784063352136195235766520115458083235333882271897295703889840468875756555700542397052005798448808773136789974246694410445500501669719210518432456338546417552097544473397981184774251391841671120565740188009593970459630305252490916115106942527823716930963414331752973477139747434993306448700244485374016621762102883156843549307230225059383482906950004471757162652527023154380389188276204404994861897530190417577947675313072544281226429986006693799196612297543732384025424328169973421798386004847453145671920538006816059350967407226562500000000 3155090079099729491823775438759918841604339003616444538757457632560845575977286532079998685840218731861603537688255060378997783870467381570249852682404273244429909239435167989316512975938031837454477032278161609595285796027217871478069776813635995414989928435033498443455950145381439620291225487029567154756479303133053976803453462740896497989883055952030424591015648659187746414231509870813266505505805866960295244606135923635990453603623554867589897387989193000072161765619760408860442241773029508479004669694012410779070571822874378194704520244919185766102900362418102058246119611855926352097738336630726008491906062861530153854756410775636199538956085297050610288960751545222139936373032698181842302848354390166380065710055222665068967160459922564006702914562893628745998109953177095983323226692064998113836920021745448273297275309364533991134688256476454667619907751759006959583043249886534859802433731186216701650657571537555893338319621722385552391863561627072758401205153982624632973166708912415573952956215575522932336182289007753101618031649664552101929382888690700817696919347551374416855301812862718453450789967619895025230055813840996091217163961204071664239432327134957101790937085564508946491933274450269110594666175790876949016949819560321201174980440505712811957182091731071534647242651129944934920881115918110680863916514016419354841262373871562219436480850405286995199868177419626363428199300291410178687101506511680781841278076171875000000000 -1629543247448309985420846995486870634405879817868599949244314939932648983416116230527968217599627713985847522495213006232212559770925519565383530703945483097947125827983576457303886602742169674623962866593859407649991601846421614612205772382068450755786209469125945497203712949105132304550979918061407175880426332024491250986746421151268359656262078238988420487469320431412168095740912911109051712469303977280458224294330930041682974678559060071328861951486671699327144947261505989154801147862592890797228743007682887240782252500456017979436198623959504115563879658458279071503710040060580773953755760148028375221668471959457389515429949333493021211193219392952948668969711749948299949665521818728929595184912552509986147011200462410887299533484117269745615496783548416486999119429312135738863603793648747420171440761443991156358405934932246777160678960715309391044898523964556510318626136266505814607113035823101543700171843553822386519329198172039816569766216487874277541653957055134867552230074447429095806481386959823598230276356414544107083280668684994876921609802275008462427106743676597405202772100070057367150791567707710567738682074228809218895861760109303073965769448293699071354938569160349409425492646170049330454760665684985029824142070905856460918951753226514165493716884655483524915340643532277520543796396901912022228779961783022245262215810263643807516125700481936063223974748824150095970529985873326284107065475836861878633499145507812500000000 824407785663835566750847209810668476573330458119015408712303415945105853876110560114106263062602851205854038722737305585340008914374639429284640656749003764730541519210260496920779023756498332616322423797969967524412725440195672354520844688150321669586139081206478088563416417373951061417101835465710072648583962703430272257281804987968452608858808317232665017321709836356478023658495693965383776667544999211368597425347149099907227837620016910927037396383548763977700573441770974119455683783709229942457441415019179826526711123560727848002581784388938309484860150486196689693357509725614243238898024236494579628586570372091210162308467609964888984677420314973066378573518955795966504302566090815111290637112496016168215669524104717177256586324580566010377321161342464009086343355649593815074557403629694219845164163821778722930415675075709203695156623874158627180140550820586610206297727232750160154287640474754644293651620817721053451818763163833103050515210283811882910417545785873715468345964353599917709851829824189280379096289357347495677229679703822998972449553562394062865440965082043288166164805154261437142431702104641665172777190261761619606902316795963294566709012657776599656834444224758223997298051407808360198365157633629638891458261000799439181837090535306938596160399330375175831452765362896332823763534801800040857153654832839511288323757916706377705321865069839636846542858546738412579204811743102156162965599150993512012064456939697265625000 -408521425041563319418391372875824412594929106935984106830824824695882669245843177600136626084415907536556991248861733711497679426929872367099011212528104276142598296951335459413206028546801455430475715026687618517980015468825246450733760185116360812982754671951080089507907793873677844460393967455854985227149054075744283881868673687356221289347087666535903021683884101103936971410081378262755334298094582781439353516089663596712666677860770988948169805295415561355570368299197684311983029458871895558108269182885113689879129702334382089513274672187641865522207081278448720588331156949222681106125624823333773537776158864220183699178216105418669005385889783796542443041129426343491224550031003871912400506822053503549380288340889972820316355332578309654902459743139569307529212221121597198973676543129044030968615602275086560571397141466947804350587406345803231566445855937354994974371153334131602707987974401957294344332974271824543790721470676259816310997703201566710323036787175012766924651094313448455432625585709677820909598330538037738610796077188476260303870890812015852989434202595420473405812434019189367424520813910345923270202377728928692883391177968162384542033672880743174747513154231585653481822792689289183679517828331922882059744266544954812360981736918671521094884997683350759505669732793100216526509111774882486685979679351134198481543486654761734530369167601578526377567429626176220458697245887288301835482684509770479053258895874023437500000 198272472276723633833656413549992149663784947873363443360952066986455376578229480216959819266096531765852661251243861605027124666940698649684880725555309544967936858678357208023272825712492789520181952819215741147981843043083325489680272783584205913206227062417230884622672461345339525601065906355088941592313279181337456440727632834657046178144699065758305516972921802461681672539532221746225380785501044222480149905493294622977866265988782754352016675814165716693643195256027177526078892253641387738680628401538804676754265921867373810021208549580998681803622822829591170436836313089874836460062591027568934269193548181441048639385333531661414267900192520256135237848475279324105529205701404750484278117163690490936047762633162710433901983844321551861424528034959809673840041275751208182516532595513266542104716383445191315888793578725058833404814420803056337050457682854744980393331753349628051600778411632346132011180693670359253042626844799335301828496372913607120026621341881688239549482806897012817139310844835754579367863652275505274081642167820815901915031349431428680723661258043708349699043615285800199327494875380374450702198182412095449579250556127276825603476941038859806099900284800975340419441949318318111935389197717280409326549184583602943234040106785390632334272229693863194927307581344589726335825754819730885316478571050530760123204772172742541104318480954423638006191580323149480280532941806883803770311658354330575093626976013183593750000 -94247154945003026193796707091788735856966754380791913053726675994512954086382116747674261661450768843616647462880032858508653608973736080562264978531117007055151038600977349738723337796942743811537911529940486850470172087158061282497053697086919969221958999858470427735752287463130002743018748146023097615894313041944308767338314098865788091075006818899527164672679923532460812140296735368788782126295867090251079073196910814389354167713104738550312045107474366615271004687550403800498991975603191635423872962165924711257122012222569385568764488229501978660907467569446807765524704250928249242939766983826512831805849240459136806357200778320519217282225415938580129119580787260817515421383043409814085708510939016052297725146551742888311027278361813162035415670529015027158179645805199803440663102418762869954867129687558327831470576160916159668559532837403566201483426547394466638308201563268067879996827958183907435986507988469863127735450645020826695076415977009619932349932368658637942398051156748154493187669516896857354670152434248017679878452361024755502357797166029377014186550841659077446457343842222163531032196208460183491823048680640120830713756878991184830834750539165823733460090749514567550196953112605620224597980033388609880337166977879270390625769543700127406969409362678954958743126517211936859367124463858473451504556211945537016458162938606324699306737528812356064204631653606797460393746453284624653434775609639473259449005126953125000000 43875537156734380466542336012804613918593742402088625825805656235850683518459794697623945205234534886944341865971732223074245038173094659256026635727688836240293185440578237647232246491470168399075287212798336261925869012241972235565262836209996285097976107835438760471878282741042841364158384963582480279507812642762781912224109564007480535868310079585885329266206603420180806521511092962223334748501442529410280889998709487284533153441985549444662111206227716009462203532254603448549497261346206698200657337360046112033371190790979743373480970310694219964168144477540309526100216513725325682365036525073534504735540003048552287368290538655566197084892295672296461970165380650474217838676843856636941617119855673859407617165163277234640994029830729929811472341024659901648438988087635416824479737145602049661039352766656033707748123480563714687983158061005709978444680718072217404662101128662357267072064593125577659303455239165707625614655977643603851879803843515719657001063326622640972273640689421742777275130674829667320865650962456088095483968083050987780349110020115222543630756234297545333229801701112631830763511360434612477793573256254620139047351587717373905260924210361801588167293190292317066259211872918839682594043250393814333633547174933087963099243138131677266996444164167472496864652190769477212257380097359390723070108344471404382000158252485829445722655169971043114300949652097955470691174675325861576080654913312173448503017425537109375000 -20004313747296731819816034367305163818841109533925324005481616453136818005177363840886291155134394275054676295310809327471313187150540411240363097146750335547536654081074009447927184089921197539045924871438155931756695014866680176044671201352170111365451972537061134960313938726547118266282689010061466973594394179838908039248160155522892247076278060113404883401026576895376632878026078940332821469295057396561755732847390638621994744613638867077428684584043113647834974390794173307288668031867549477680860583715145363697870942257775887491652478916164890043221106453885020913430732894456531855538480608928041657297852982624451134691266072273832776898427000972782533860221014699494239415738298967725432362687684831164068101808506042232219125473783868718442239876993477715540382463754312875791193040802948325515177076211896133520454658154225909998710347114303376613749940598079689511071894315020853364306447578456372681984801680069063843748085782135763276931257309656515077666744931302991889753513819267809342829809428388452245303223609909361697892870915189159867463945448013513188135450228867591415212092339495173794540048222233245567792531594744072418276373722639305373108736271873683078887764421175681476163542018107340034986829631283029511676115817555858855438823722058135714608874074796631731896992974373553454175777544572182907240379895667898156246041817724235694512226735767805009373712310905453062157703430969796221106093980779405683279037475585937500000 8932666048642160146086395149285423003026860504172564395413099004295885540026939752603488404711854882395864505323730918628171102600558496261872721889935636805232576789347880103972155516551851767931214852807324736209170287066863922611903510757677704128122524502281522773744125517870905788682159936875702804938025338577962186431236458894244929770694133034493400044635008728824245004757963353082584111396927233988226862526911907359232522129111404273708244596501651535114955158837690906079224020213410660300915433623086039227310368378028645559333888685258561236009250889578648933897565982926413364394660292312521665909645921154288040831593047334690217739475056101139310645684581269229873421427026386782463369903150500353711569467845071718855364483574824559862708797011941573343245705599105522578501859622566483530238622777000573066064603833392435941622917944531828194053345092069590666137781829768260175940832036099574939095158354280207289557317760566479665259085904958665171144143970158427639298627921251087927002872868962289520925247033510179165499441462204781134371941166479898368899834477046105993227204670483637064480517209754244029540576747030145588101285462941341766954205178841495872192372597100657020297893201419431875428503896162189778800525040914121051055420473138185047073839015911039906040187264153281924475693429553145627549625039341616173941122122472129759349459511039193223611850141817872728256601276911053055584943649591878056526184082031250000000 -3906761356301287210315821500510209755435409834601848810370688207614103260638787889789671657350531861101980665811773140229959627215764287989170093030726153613773248904247742219150804274377443667242088506123227774891987767175785632463941311783595742567087738099428220466868679539354455667690414371539655366520197860712332908564493696737617011310358528617899967102946189554997171850030144055743290957716805404016500278836171932342265166523565363353019580537859095868979194843901804349391840339834875971038713378734065823579763670725072589527029170295906642111083429724017115217891211713681812128099333451050773779231847347610187529817595656008767415502654136570628105793159880676519168231834769061199200953138279058433505690681048894711885535943104524734879243291151577152480445945380017566736454408148297938956409596553265345491172522593199662510388770603685651525395589548126986157021063482469748527333992113025550199973811547208270330600885413561950291312345544307588480778169090557052683630367826913184579263674108139415102215796724497434064405806863196365530168241214917364775447838541623679662605709257804035854866889596432587445705839843317141949937348627005135691515810381208682558315858315458312697344763419389583159347073912801958957007984019605428740510329072705227802441109846287011533171424509982006662546700363341667060895227036021939246516952773224529367178834259416687893389770719007578886959457817405066970550819860363844782114028930664062500000 1673665307392472776978254791480207610457134836078293179662313156220707966615251986881473446720177168724005856408816307254480390600565890038538178773558676019528867724684750419775275227685739533356058330913344563139009546108203726949108620528504962569115292578631888612004671740620963270910467209473729814056497062986349919124312235861397772887727499877817047097952888172992145818963256420486495239894504848838730904687058170100920288768143322055549024756436662281574474418825166694189205220684918132957753069615045520473784383479447669296974889457575386224125883495909091158691248439465163440030929898734557155863728670837423664794560906430697686025024518750460919794161917426389426030250742703764961085061103023622517454820559208362508989317787817545998026691762702238167826537802735234105563057302129331729282355718580916125847307431156328865500209728636455808812388063606175869964186920406105697608316661593863961672055407205029111150970617853356290583760743865292271680811557426069336281839900123239546748946875557953129988061282864788355683561945245624442891669635081171405012750540528197374163290082519700126477834607751829019114614630214634025283208205296706800950791769557596778754263458418159498649651853241884800469943781638962267448183768395149640473156301433765276970169954963645199120178784408948245718878353250269131269546361204121214733912460034189335289560925836535747472783365908989329247734317092539957361196911733713932335376739501953125000 -702412429975399838522377675745942602686118629149311675364427646075666274065020873528638105016288371793284559212836825181038534389471319896127873949507519391575166453149622742212865914247638758703294717306531629445229318604781442406656568664957788227263920886689622267635752787936618933179967830742684140859662335153184629901690099657509138844995331605986946964712803899766370818020302523395195412089709241485357760362603029064977510648933566457389299286684773088102360966458435403411744862901844935825461121200087814546370590122577942982374142347698684235782013727582627783346393423600540449764920498784067674077232060627150445281442626986367553208484898928805939494648040464894928217907629226371632418823271188994829717793441991796212213800588281754457582038174274506744030504888511371240226079940294652122851427249956473742659258017117427218078162485269691875372058155494553366343211055487651958538331485223659400941970990256204500122162287543447216491395187358701822193953549369058185943747059279198394590621238189266451498707638607628941732406864524778209751744105643320416778418824377409314499589790941753275500795604197898447083799018628104372811875726639634752385828747096419385399100004561359372506034584005307469535242042600291048697624671053476701229594352412596198288631715742634082977993801432221885695473949545753174917161352590749236908193490353140360000364949898123699624754936310161940413526412453626424081676304922439157962799072265625000000 288844932002289730651462989173780106130845595896773411993423207954070092117047128816620417870310366526498909006700130530155483981844536032247951895864277057334337353682694613741832299793921472735823818949402445155734006696584306964641509041509252847896751692287985800861649307471541279943968079296878166825108246451526997333773767995895674098299763516105300945356552126370540546393596767578431657585084239194722467571342826021949948755995070776217968038222161143199839312054055256585946747874582495080728906687280146408180207124248765284776833153942513716606352056982518204404347323742499626815353400039055991625703638067045182793622242327860026203682192815594486870474977217614154247049369177905361681394895225937202230900254434057609321644459240952582566453874964697591260223220246228242755829006690254128691903007630894560892225018470843639385276086540239595167015470443939124443614558073534116639911093231270684057504260235619638060298283151814530428433382362905050394020896339722895618127188619075492099282288240002283664276087216241215871271947715278842721527246920043742638873945082680488978790390323686483574960607832091964045732812369631231240628221127902580467668115872791224454179799196099154473423082204742459128764808550656094419076343029121817178836533343239605249184274089763814393962086041536768029903078038726635793293391190541966452564268320109424266755661062827621341328890854398977331702046697850527756656902056420221924781799316406250000 -116409287874017078728609512202125933372341586145789699528009902728724830823380859161179184246511137229662712482467671772512341404825314136018960213825820151960478603101637647019797514362695441778721342936871553901898591560683136722827919898577426553085666199411667286965249115893302383235602397507457654092332374807593402588114898988263638017428245637240377515695070112367471417139752404200166714818363021633251818305811659153727798534524873715968774075803053365504612345129190013486679783661966207182542270998171829431990726785309664691466666165714234492719763306797424640836451631543843125643741322256284632766131519494082268438772885669101131865614202449187076273368835800035669115069258126506325564759683335784666772441113817282570526355765304530500167404866489530251705588779203377824047229167786908356698489708199885349314307269839049972460985330478022602128144082311587731775805917167535137750464708187519409253803733901552923161228540795064347331898614596431054582534963942300182172875301349685969508911429027457571853500878221240466279487771903802822338150534552260619122822638195184879878186808038274737241547100785920896766187855169383001386148668195060723125563919453051661385063838522366258955929582871030217712485495393869852944606653754913124238973727835926384651650158015717060960630072591376575318054063283591800782907325343931689616216500561601605847684722014128910512888881340157474954023774944139590914460313797462731599807739257812500000 45992711254864713894233026602410019005055076004093921188225507164361182065535455678691154848677667595224493529125991310995192585685163083852303421792823836704769029106416727445296801877006074386570451892181344059018864433975947430626943306767383678607225716341889541479270952291786189699074415996309857109067123860612425964433209304589421342651460421509439262243555082459236185347708551698673037656117219413477360265050038300093336204390202764898004375708371954866917036851183001709894459248289895911523330440287379389430991771895696035309171920503515144851265612137718698128652727616461678089747140251960133288371032094312934759526732497638935158339579197842674589129933096795792541465195980927685877726275656903611446035957983735253578250812303860720785065352082064499794469503314922937268612136542519541471439799716697500132117027749510646105749849123556951371431007743063756335062985386676024915918939621353426509663794343912968894027514297346237657243644930510737269833984582424142436671168039725890086961723076867712217165778365534038498316703523771044832655045627381636248419353617278236098321163212635784161797882816843718381382315736385281436493205920578475201607318631238444830107087714124928636561675506889881830537179160007841560387389994482986095271990275432608945042313713565244150548090880689490940010718918987909022681475140609958131670792426455333135287679100107514701854713608855562712144865000589433190469890178064815700054168701171875000 -17820749775159520471999601717094168260505395657350947161462641445904634329878830202729620929359087235282097147926669493383331158451306659365584740728399620091891854900868323319857476952739844760152320003463683957766195308947134126630184705677256336803862605442126780659421556285491767985137161684268539129252064156254849112282324412243927090907263188760385759733907606885491022896684032504713724813383170127115665435439575908482617882076236245730582301581953502675356661699791300255425728488444985426300928942336444156537153275021805781048667498659090104896403028518144993502014515706502421898408070641990750566153896026612803862707739707967499470356908440801219025514077599534177913397576820994371429559164010782548282540687905795727646401162173767898313447452860339590666669074401294226013034246630936039147519162279237937409174192884203143324853646353679882981992282871532708426175050356186287684814202933389229612742287273636037093743522292648737429726459174599285585020528986352912890568561127041596612459756657323803346983002890628519599591190278670086755274180534655001199378335282526604314663800211673185452401557850353733417196879805309936423741247520041531084098374138950400833744984734066264319768376692349713892600890425253704889537514740570780180736831382983620123332965439377511161857163503622166662349181345510898709556602518171270149926837068675324066139904970961774325191205861870520446869816527657448546051455195993185043334960937500000000 6774627438504688110025844143185891334685665928588284677119487227751506440947470297088388578188984749604841082214241561419072425152994281321125365122931573436982360847154205638287571001900112297714666980952543903666934967601746934000392147188510035979740401122401885697060659568859458666433187983629068418723742671600035191787533486051991468441135692701212741037650850183325277994415013533336874837384636061220106693751389258796357042308616771839101916832376539053360702558009857028263534300408603948258134521976893414587927033561274724990158089873948914895237469149262138011894832807763925557330273743276328295824827327304887676763723544134690540062916907817107686427734277907665847688298463586033863317145700519846678854773710866094793463056264515442466207046865698949859406806613368444236840574987640081032888500500255719331860600979805110906743430899279568146540820173975563019979947788933450708479478089600889788999047347620979722672994852726516920564216595140793348437553837266577605145886400311077902279616745927373807459418732891528649452039758578170327149539172116035152677231467297728050573015796809506109343490202740645428077747769480860570813316012072684259028956123190648698465804356738237554799407124399925550437335720728176601827054714567054406560779081631409347592804818076494559663115143520596762818587692098291644758013407192345493791817431302530615114294123699973376183068369786101008231827408367919929332856554538011550903320312500000000 -2528035854540928410036322896063062278756818300309279240291078681304482191259171565037457963917734094321368137383592031728264639554442781902266759043849770405481306228988547118630008664216710213669256474620441440867763883911183541092059815395824287492662298842061432217895827176969387027186075740023014940048664155153765226155119767420159467026838134416787036816732748970099217483218106818677021230588894104329548621533535316510109925781532995655651315404758334781875877636691969229536160790470172010910236645497330260169501105913094796924287867092107868492106965473011061265040883979294551590267154902941581977060289371015901354458309516583685993646020879358696968764990405208407851749767585459742425940774129130051815278040237918580931401077791962666156857573029122930594543180074294653440420523245916840133160498106247637159097528339369457861058021078004999766035170277087929846460938281398124209792741304298314699179882909040081012464661559838511073211455261039123901923812408219512297509761042060887194298461986867257112918171855662376062790772882717065237100202320232404394328966995966080465935793610756274560028563254396325842390822906890302742834164164787333665020282131794240514351230229054129666492005876084299466622742335956763881837507107389090497230641759477553460648377460096503514698760246077854468109641147721373213539947494190924114000537271440459796845960417023138239294367582402470668635503098231609442336775828152894973754882812500000000 926533081790281557060105182821685448258925841865208690908642115723418042802970947717236243732781386099358608348485833622927017154219137648628777199740367004650874761908377889295092085472214409665682952096907295104540029683058655254524918199536418754589043828771878821507791732253705572253328824714465558566794960271440628557057040321320455458065308116999560680658703830336564379062243483843781663529613174138144958211975454709055470906592594497388198939410310065318867093615642832047806625573854641238402957319001459209908172205145923591222629980056266449499668665727385037495166053923277957652498791285179578868261449202873703698578015411689269178242890719767532585580061713175879015622598082324985348714719486839671793615074595970347618364295891106236401976122137785046132016575093460539756191295815981816415452781216703803472840186143241857241100744397328289596255600365647255415240691546579024728721870542816360520466017238188513837972216595458686897102075028083208319663854591479752940676565106489503652734618087021810779069408807205531539069407596241845300048751448326812634607104551302102387929610150097496849892894139556245986021499865574016130267777004435482117857227772356051298707789517972634878511945081457408373870680064219081590305989647398347383582992180359468100801868893043789009526519462128988764945310547196088840346656228939865470463220152519631460126067474497437769365658134999001474961153289322535187011453672312200069427490234375000 -333717563802413527965474178060880034151032739549701281758378665172313758845463448432565671091460482100472435499601359188432755046804449423259296953956164158013607488759383923283575675596149526418620593053535420895613117514989510206447754320506957475283915612153154182125460458760997880701649493708931148751096486413325576675471386387927023610599481653386038527045719998599479123237139019031724140854365243670323853565750278352892718495313622280890237694377482153939802814090142607346328288617130608389283263945708494196211317453822944982245206814514004034942939547190923857148761140031109440847071968592530327805695138379874241676447432292653832570294776140672085585310133652107143828346767300090401281475924071252787048348902907097870279458658578001962577403759860810786526591387752647056961353681274192323289461055400931100956950630774189186201893694093677369130149055299833732460034962143184187174547974616708422787778003232346198006870068929010681948698375395076196849725008908495475551783665226054167316181392046246621109266231327383849283620760056469821767728472504463005533363151486987505287845786107211486949618103922882122935859784154537948248146854880235613225505260872805477579564712315724243321982390637709009884659415249415556016550136251728269943496629250772811046100864656379655487114896333389582174468454904050913795781522823877996777646285876543057793981805510900224799323694150262734158635894582412007025595812592655420303344726562500000 118197056262541055002429592061251855767905999727741868791549594023878245617718689743410898606906693654945744045824942362014618917444098868367014640463230556460918863997107079098943548876660506011019203051101158101354247248229152647624244986357932238952002701184682175915877845384913252936037416888528802960664281364921376302456662276247035875296858476637599086114689229790414998989080487544025365936465032824474936383335570871272493618395402951763475799917938322447988462366670705035088447257055128831645389791814873422532185833171528459210938547549819404271111750330489364539393525377118850482018692928390642375853479442868734509182331072748198580824735947224166445948322702247733333414276404137862418322967177989590237734167327039105504656358941202731689633489788429068616686646713934059649329166811463738888872207240514743750532664843726374411110094954973771789941546274505299139249540762847185045395087667318148846720583614956860945732407700052961672296347756872177918723646640988554206299475466202879159877999465427242862000462581717738233776035104435863032351613701924046255300762940177367761423352755866557703460046101882501989423576938027091055807964088734758535215773627716966724834072044927484160110476988166171766778389726235958992710145500446187276015534386042259861506526999308468968475848876290521413147001012147589466370739942790877382630688935720710546706560843613866583295518830889496632335260509205632217799575300887227058410644531250000 -41191388744666410952481251383859026777216399422472455150393714733875942460082225600163985416355725376596587998391819746864391636753200359767683569377977329508539290656204893559484181475140301510305673988491594827702624953516733069040022241118249197266238954608466262091076144397335411747882347510117919065660893548119034854214550003163591764973742880439920552898442165582427109961614400597898300962319148149807541578789873342190804593158445967724496325842838329870747204035671477015497957036601115704742287039529960146255791774307754654028801701917022259437757435414706262870739914191724147074067770007095485753131531037182874254873646471524436704356719853617730901713994541762947856849801466029208311994929689284903792963886442217111594107375031200927941666029708750925048027967732103425216230029550133462017366518486157486199193613773789812264414370016370147572858915113492784838750741689976394489133564245819707017502854915097146125043293668837003870699320499782200569165975065000156507864054351165053217530023584785635674495099168323404785320785371034386817560868871206439326112535623799684610627980829282835065541158983663074185424515357134576106551847673053730253499686981508951021668550088210204600085330718389081703129091397598077828462229138040402562856288562912368336010038259734066418942321715927426392090342333769884221193450256247636532933624873625597301201218535729823510588063540922633239062429499899309348620590753853321075439453125000000 14132400720916518379451628881041112317589322124901806905255732591824434785538110886903385233684225055332278093130121979921775968165044712792391664979057860469185003753717513498062431228601295148867696746986187613079823483844777499423824269542421828412591373667006661690781799780408852717211517292255817101297370051395277198252547543997763937455520441244727197110316335545632700534650380043226352807570535395160640531968008614312541377879955108640271645355152497096914050500622743955421145994836216992714847218649784732117696127722450764209416599611176404842123663123429977078547340263016179217367217930182543966735427403470700254497043253141370059405448881456918922579602176642907242574787696739027110077094371461061363250482459034169019015163577184606847983083275329124634058689187196249322927974621732562779335173812746219341014102789428633247527197846366639260747121384760908864930969452928483026485755327633004928273976645948335358509129956084880664886416413392770118085494784548334656921393044777207612122541728573754359742436098747778741773210095566767782919752368463174052409503334028767249125251642745540076344114295780040336195814706788616999686466925382151027873197148580539537755838655107426809786679762178803130778799712379851929594216772707286122365457061395793460026145923880963031973036251184627146399651716973704949768151895887688686915683856198913262177082321270200227978955076198416634147337657412268896450768806971609592437744140625000 -4775574700118649192595041705762514198623758545935812871898174911220789138269784461875559855183829723301896727321663146888445109667100148398714095710450504533470110431465353174965454406060533166984669746248452854306380938957244329687341260706242913813463578680350146767984633330990701013432939182937429122703726264763188282898178915559212334539421717740770390108410300658905034849318460026638417687893691492832135318508878157461428849044115137568860449145186582067622214763732378185432648187902239810815989524761819676358774747380688293891486074419729905909516339779500875826767311213569781674492488780924806790896171692795483317629991242320076239796520003037832072425533921862778879090631821689772120933466998570093993272920811408085709690769349065027232104005433449517486385268992233766837823834463302871830214499648610459496835038123131964782000905785589933198776541727544796899259357835562705549099359289043162371020090397970468764044640878894396978480726343508222984413500759040051407074994307050395958482304540173017261892852540443738910329254072617726582803012457237076979762327248473155923065363714573907895256874220939807279348721145671671882450058144468229658072262506412605072963741417357279240792405359456199549354972177748238491218200249109846620201676266051935354529637983403792523507720501221629263270087943894389134516626308338786182536216785512739926343386305575267997402391087655324339495983149150859503606625366955995559692382812500000 1589847916836561862027644478806754485667667769304298777216567689957460372266656603838287263584501427449037719091917004903400044627755250868144303876476297604631369023065320939513643367820166940290701822440780491362360862039618228368275039902653058357598693940675371947563240125181753809094082746975707134550560201630305738255530542040213974689267178398426934457222627098244283130525590351802970997466399709630748176627473551398627271274767064910703002594721488979106499335512060783348571143528426126488872725392473843244967845295602316143384460035599250353805617782012162395838287380007916206230709970723587162346564013049896453286252587966556614413248431590287772319414592013042310891127469548800277952318741255500984309677805839656950811715151411346046721218349283401820974169327512596875527436344846296761988712570211922320536419033794814454022389488746200316625064111804369221247488541632664973958607430899293456294315854093832691516521932504728133009953182111282318228278092587327064504348561762692170987606660111544723613357436726227895177641734451136687520128332672759901780157522409295485160635293168815513236930652763925029210767498489896402301513268831469962637480104395883840880032803137526236249915856635033422736712437924385650404364877811505724510929992192852082101701834887748173993675714528144589427055903087259712733710681709191825910426296430509040341832371003543543580792416106141736386811458281442810402950271964073181152343750000000 -521474511627790252550136596038713492847110365904363020506973758409471779899934367668603680481571402393194430151472389820188377079667469920598649599761025625328430818608022058551722074771334390390750402001106370118950203382392199830494260133436676383801381524443041799229304354322712078779751429978059182210305966899983312327814566320968772866352354828562347802674819025497975545718859575647570761794521709572779659503723781835232470387217860908030518009773992972973086099912590288104799368022591053674407108209426206241621926555405933604742229576012279882675380497992979132762102923876536257482783097952964661395927270452299663560213312761474648117668288784470017579369177987088903384460591595389005920152560790859299313914202260944184827933025466320883554821180345459655337977651219918340357792397604490107426781632714650775007112191745597813838190492678032609314392058089097819285400877133903811289362322798424789756885009979556883088062015566340802657376251942051762495856209967893753309966117052453884704121438305612654533081265578265538378461616487540537669905278374720670003248210929963155111639918860410340938819222840946387384011097986545358682405483672142696908128052503847261880777098113111326577485512796624052119037729386418998237355368709080435106420361098009266045944564114874789793155977947588886800119838021807380417438097015814279303310291888731162450647159327808597449082314730758071208687604025655559780716430395841598510742187500000 168489916076431401030565170539506506721642723741251718961989742636992862389421627899562600422710430071162864525898833569615702785202872181580714211426006879660751602529218318228961324325661543366118714124402563025222071703918845003867482974319935222863670169840701428846317186123640991364928700954698332834367549514102849495899786413200954419708936353598620909980696976401474748358152956261251332235722293083041762023373733196549957726277086283515989925333074939527829627814423014086050333688943240596993124034074327987479972360088741065790583814005703264307831632055127124170662952809052908809637065427240043314924423001737998486277846105077060999095944441370878432693077673080397406117982700805217379450106821953101014263950036359171293577597851520409982688748613203050470615938888237694626462161892463545177004655096213202571541458766108892500973694371914206353292666316837340227001040228279364865222176159393115216179988307283907977869121489300183993227911529657970092918391953340503653413348756110784190466693977585230222749482064153793953256681669849946930925459896226483151652590245436643962998348686394406749936475794419444129377112474208374048910831785414918971743500093207120868156444484804519455358934555870974202084556383661472897496775851260561733755365923008806014037509204189023312929746613144970297856432752503098689431412554690720494762190352446214160198367601718889089055929311312444974948858422703068526971037499606609344482421875000 -53600506963924224224856355225952183199008545243307657434344133012452096779380290216061348592424600121220546360531786379949384195938059933065590041594926371476300947677796946810343142502229602281225419666879465545699665075335395338422090574998530434668415586249101811044749099625613544917099165282960831661161994055899027727978922123700827048108865009665952992782140061396891484963001053172628650293629904428770381480386018771604762465768803316857003775479658603409391826277726882300016471573300402396085045012905645246124081220487435153553357364613583660957065174850700309586859638328666703015771193979765105726888043845452754969429102746903813462133073042320415846527476306943878603781875190814994177541113852458978484488344744934299752351103569351454829183952871817462362243689575234082099144868956782281667359966945707523641683254095660029156712552718286523093732271184901876737343173533733198556762008377507675823244982359287215418130009479575657675895177474214590090451446383709567057478223938364179117153823179519657227857862549327770483229852512055261986720309450692895861816531426545765160513216136928038536301764618485629051686918653138704263767262241045964674024254777602642281341689619647903208319468033482923970613613097325106488270576219182824709069435540644410102344677529475749556095261898489630924950382130551573086363783283627284467181786121644966292889375837792165271521341876365891244461681086619364577927626669406890869140625000000 16775554715285230186627064449523953210653186392854317048315697904172298743835687448115478459178554426109536920460342943883925229943489308550665404663085689011067445923834483663170814654632419735179475915666853062577945086076832670343291387595771230009207172099544073167238762783014553946897845885871861846791956180433051549412294000408601823140565667519138367372638415682799088982829349038410018022803472966030516617811896176935586321353312199876063435571713230401192845533522537762625200747159565914800801494690492655801966142388984028231376620925504632826932283559230221587703729088805792915540963474013445505421094934905195587625079697339773461752428402529180812743127346711818156986773170055385678165265496579247878044443864078940579497295321758306197524745185537919343038552455008123684821999157628673071548605286448775076459301895639628485464630236794648626386559482248599097473068354858274534666394973981487167986070991691730366651886058613861873556774963877683644056464416061758965972660493864532169468875182466390652897610288182844395558175955846557758427495299201178139689363269482079776490447038517973060156406757533813860375468173731670926896462012337453058824949138529123166287360635849000698488236850300755942669345266828533977652616997952810900311027184450372053315794668207962642425259640221124630868070141666147760652575529897041548349403656825753713736777687540148669974481379539495037823623735384614974464057013392448425292968750000 -5159685671825127397223218684199447609139454782632071103710203325053833512065891800720846715237608980068916016944416420605944363824815754201892362724855505723618668048528731120845445273024331685927444021969866035407911593454631513772074302027053131112652794558306278084837904215869104975374458422331738199360483425240837248039889239662051700782052474691507108076734271475215994719095299242280416729778957897736357415741587051421073767610160376867575480610790911818424897876412309832663681988010449316971899977842117362293792549015253425471477229653624708361931078393582983396221052624761080380147253313919103742556412796233877280591417614178293784935445411401106821672806342824170402868384032906283887808451589518314048760384211669335295407456225259456792161060711783394653333927939464935857440538748339829945163538318208126143845733455587053738082841114710937985678241262493484009143456328336219904329256220793137456606885998380924935187649117244469943540448679686664909078106345491331809577472698678061814701251960628556407272011413619243867421464707884373469272050198165233068737192296465027896803470096544912294291355939347752489131002427832329246482661397673791100391949673339523599609104301477049089764461695665015173000249761600038421517361768781089967570277216502911575106255542659731486506369824347646131216375468147387602356455335333097357787001717564804705388401387120684312301836796872834135351676421166189356881659477949142456054687500000 1557404000000378156734918559257795750276343094274558808556084733988382289904623138021863443287875337062188632982144037255846492545349620787445937977412983499613291282658192147865194164684564963494506180674464959758304344299844338810184480017626210788167903256551279154360566280427116455992344917919348323690993949748402526743176621435677872196896010722307463826671877396557438296675493071654772822571549606660994556018109110492101234697552244128357367571547864016666508048572629300550094436206383040224757604053260527885499993312324619568316520809769978258798452013722953461108069427010246409016643717673931260386690147295279007678402830865752344016774131209675166279489961096859992856257714078783143482150337375938451148496653750788613234996627800147698544121584586644508718033180626263353910312243696685718327576761953491988466617764941823955192430875407805611675376691774269939314640227905628267595653644664376766896640745693366743299761547876977160328377468459707422316244058010261964157951002205131579508328943285206949589172917478562528415622231654570119895607703497300883534319336470508027908303417368053176800830698199917145892342014538771108857235661562057603935481272800109583888037592793715474348544361696412762752154632429638137629706890652565113730308040718421737390007219510184742138738812416545808670902479659058264405063522143810438331669695116032085381781847086508919469749565034736663309174187208583362007630057632923126220703125000 -460545585832474965060536558012961601253881978016842757273487501496492026172925893008458150396152949078544766605474189431217375786987435431560122210190310161237487018185980200791311844579842794782558990777113155801020428133520843507314548340020338565632557436724216011669217863440763261574270128305696950199134135780059641948476016140718449939734524530723815144952532156928776103724091191651223115373896451319967332980129293990088842819298676987869772124730839519473264950667946976574496353291015168051432224917163762729486764903622608046995498320690805214794338744950525400200538718009162020788299923589956359040450617148818440202614130150248570286346125219678990480871205156335601767556362967194652749937242108521528754194139439526684884347470597824009825679323514009072218934984200961828382267291107969813181922694382814544032236389253293582477700775267313025719081911806466687903639219439652459857009367363871437062696535178861778558622201618170446274946796455844930596563981923279177966363788638616613567424730642678226108734929946543836211982635793084780132819798572093958015815220776331270293270982706223482913947530634729845396610334293958205141228373620081705219957272645946265144837631044020094146540522318360199085384867579916259980584514351392760272828949887883924951127177869303208556138763588294158673265232855440832093207563850206282861341587970795577860231376114808358318836813012880481571498236803563486319035291671752929687500000000 133156009930879632588459723015409494172103208132810306590352356805871078292279659126115697306975122218994056022749437916916552493456798384206756046585201302495827432720480399621229515498930856039608665192140975016456076243857334518079683728975123636332316925753938023950524528309050495501680619690113620436534727045219133801913459414534173228431312795406828835854506265622063081471353636897422866391620594587716331852846131198737568166198983778501947925982063504222858185296189224673174318272993791389778622425670828255941203069842192418612048063735591858359598983980359910645856855904489065153643232310229801405059314590154884619019065348122720179295402659335728429213003484125566603834424541250935011751330265229317131274969147802070752734997836015824968602887756351879761861943669506745264139484288393470992214592798685120173229961974416727557667567205994632269792425857512213160227329147571382837695181303033926700330469774448475875271924831975761917713940829953044752863887574453523695726682298386849616448636795757663557804897952180997522698080207848881686853015755698837845703511182021127418744050660925684177699222388442070080261950875939632268218301976400904685959640688877736417909144832752874729626869322725177457974204481739881368572380080390381189325309377593963600206740627227617853461270492954218360520632253525458463773923340412991023646446743209030993392261660652270829473990006977697497791979230896686203777790069580078125000000000 -37551805755946910600546977614523159884561993020489485888874341933614598102697247862040493031185167352644032901020804120263730616889800814134029748484410922388037022090453646835645879340308200312796246789799168717061956569765773963099950466954802641990490771020440343565535942675237007250511565029045898112420366265108776993031081518628614914576858324663704172849514810913565659535603441643616822611513053691178466933080018792588811254505290104998586625060349217448027993980137504018198753879116804925262530987202793147377701176694264039016313812134270489524402454044613909055093404894339747531419185796464872719208309200428667772646926027592588922737131611945408232427137878676853784969444005323282841718972128679055770720423218972045070876865468841162919977831367173384259946933850359062519740139720884490897211577363210202062295244592129136666456249688078453489814890015622737925586775338587024726941211224991723522815484154578906009610195863371970445537872730924595149519695154197850015200191421236843520078348647707995023706126367996248442511328870998940080281045915469569427309815026029847167428324773668889556212442578938726497457925622331153572219830631188964165602157221699764019209145222139753592085596887459919656627749259766072085268180459117055166023431326232198576985390542875280858025909413419018592555032793212531529057323038288558287634558771034939931767085017604462448813363259784905284766054478495789226144552230834960937500000000 10300186854171553171505679305668359234444516308866560689516050954903211826934835143778016838545456162836498991458943750243503848479114146167719565962254766820194856018705887653408957246760612836721105807562023566799985989736275260375610261987837035377614233769105921949071375945653483981722477908414986632046256316149033952100734524881022579989991883546885774065236145461852558247484526963969724991688109028026186850414848534937754724214930277226214881785656198548230300404744847565805213572018368355184184447443949876164851744488140599610267804820153633378266374672183400072350991173696855508050413234920808752574413652116716142735672771513536342264226585959268935105437466693186288305319295416183231555885268550361110255988467049060308195483499745848456145872918897045502857435401285868969426050503551590152748537447421158474502012149398323269779245947671686681606348210798724796295656640546847860453660271153274705988087507378493944322377496706867903052645791527813831895557810161749775614748168737396322004905826075233452704807263367838572777775797660963960008982742168303824467831059260407299038128810285818106117838999616749876053973738028709461554575321059256389888423915946192254520681875455886557511175786420090125219858771292577372123340515248171773024534872314504332139630035129876623563415260649213661853799107211347967542916901096004153764709014567121157120923102763847924535859416584722078342323259292356851801741868257522583007812500 -2738283910634958741805534308353579537885193449437074052014420802275584462522054616006019654801664059396300603980315723699329075210254278408347719600826839296731717786942894018333688720956614172050636100975560979939135584018742604369218900827360887572237434310065301604688246006283893204489142354017227064728247583574942988507265420411336619081171528971913427772551611341977373865296919024614513176855508161168861340478078434989633037411533623021592046087273453045313767049126608762449233186458864013385510577160829944642974258464838366823985139343174235756420382955071278532592428102995845046425067794928243632510870977698799782434104101715762192358618358999608191373187853669732497459472742347238068257644550871522215439629330413113315875026191290056555600450576292959156423340519169155286168283288860257300242548145635674382606284374440479323866997316599274562448014759096684262684400178383736456825907296310083703923918576170588409821680827619552770102392331619672003009044964936380671813611984415823890869803983969963319938277175750299534943309651904973143859140087884704432625803384267198054041344624467824684578851290440668633970954080626167310917335777284767985514151180824803747450120094912155297546057254211117345278404803811174195897912330275724467193053746333211566454947610453498041013215196465174846107864190335281602789648872097431284754218788944256414291266192252407315901844013255917202262490484088175435317680239677429199218750000 702365332964155478490222675390655022754834851617832269729763527905752165182550021052354089069866816624503506844581560971346722466128473977717808998929923362902530642793362979994819356027037423397284996877806689987635670125713296816162748031531712046616241615524232804334531271304909677320684605858634552401757947964289867133748684282228342235280801700203728019857087990297717039018029357786162456882062924648279181184689684480718953047311612237166826923447965508995244484987702896191751939233025483334047494292724648224719336700943616225043827823164321185022122203664923137528276613085054121368192012104935900776305603305023291623170057938094050363785486508614549382925795209984139402590497150602929011542439162250447924832758139269148439089873227473207743945150796130242942463086030415484866711663198593588033546452021945152856753757405335405051465900690149609909286775721240784619100373669162422470669934654220935755645149114117434622330728187371596466383717055567642714689283389352173806761797250824486232164143399139772814868521083155520473522158681173999624663792925133955534326798229879800143886187784018010899057777636594506982165482264992760134914207439547707130777635970556734413970787954932145236365133927338320375897393728998604506995343209330245602903479502642974568988937717184944804708235459472958675626173114242296084412529282284293666506318868956523337316308634345080490493464745000383973871915799236376187764108180999755859375000 -172742390532391142696453378765131497627862222288400176795916956455460918342836940206627175404139145146885046566642269285031716314847782529268650887556441911954514774272106628204381810869275394840748915125222360047371415714714620236879555533808358493706694328856788385806171211328133731020389665140977322582656816316023327120146785982733844415699250670747568430814811964649235801369248366921570675846316304699693628445561749552493479432013468588937821336905896143894426225342539880976706041648020355388116524872380130057068115587869121000559963327005380489349773486992070053402438723876898265026288430843855866851158765229451569158151283173483566426097640545439246127559566629762178673037851982605743638406111905907507309191358072273726873512224017536718986879351626303432469826322542368322438682964097276561319869627798848324290764241789438481464283927689985962714724065854430218158386887270282860038857593546591423568790822473481181461240987592404150755780344953633300498428032769965854773476329282568271784212634600768632681092945655935410656491913016087204578645377236112500329525891508089060887035456218415415431905170304582401815183603078867603354657563018890807826105864500908269455800748956768786438843549379159364707294160308556908986572306832344601762066416525959373794389690978643592244612100921021530447675912608059065624053407908525466324086073018577047573088516707993430198968595627782938312089200394439103547483682632446289062500000 40362873576900186054401501786248156067153716066176160720209299566576515118912615827095654257449071237791232703062692711396285163733712306547188984536998947523817700794374094777621520281486750524776257121918891582224196562869807927692299409124546850607879406212839652298862891641137351077972753257319666372016678547736486048285381350611175746228519750471324619851468883675904447454883883888935204925580440608894558750359782544479487081390292442544184618229049043820512743136930432041555549966845657432604067691610732701158958707593683108922842801419730503877189913023689370411382538076152852178741648538359311984734280400705617182517521888512832518471753230335266780441544645331468477282564570529551243414706995154727705703953711225798028836615582577852622959145938374151921046897504806332194487830928707053156541375070430918469967835788214283630368377495931623468809383316151752717261929921889343875501593933982120791725926084890208293557220818786494035289459189916316658046329393847072371892194513032472822793664907275773351518365964221345592321486480150894269232618271143545822400247735848301164408650009175920563312692616059386035537695236777820141259899669545881133367922270928400693658907864135759587651568348183382500011704143972739528664311210022881761941218728727700930000038616011393261590875699085509677198266161913502519319354127770346190729341074169374417527232612322932336231610303364954455557223056416660256218165159225463867187500 -8825788060687942933846772359891663828296362855060969843650328841669725941998283590802754763811156073344940518668412512276629889625603386551918745938154649051626404330963645619832158250917230042385521552634487112473369061098519499658428052388456021140402208178409647172326937340933428964803432280715022129435427127992449283598042567121477282282463060334306919505385735276781354751398354979615252530280682242764155884826427999821814878810101288226035123507027384840369947048617816865962260824464087192728748708718722266768190443299557531446035973838733136928521103639718954817287618689252547244498055139209027593354795706481893443872902869298005862982256733901604034563087914521356668675502219335006115972464570181980596515853603387383054068622589972776812957459685699368466355256538855179308305059773229116113700558122217729899347757312053791082413260202915605539567671523182763324818849833005838661218284344011348093645124925776578000721052295661961954817083800549724716895540478264784358822808114546212626799989683389754521723526830687530608724510810183622118101665688139128684560333633340165849207995172373627361986783421912207324388016763064981706362270978915259231398462205331639211298245956688531336007618410597873473017431815813610355004860893483523611109382697131400096805808629348901774236911263463010176460060920622004117498918564834594291030220962534519728388392008957981515019288462560757488328810893563058925792574882507324218750000 1755497126055493850158418586576127617353366686969552056994690412705953409458377336043551443957308893288411027344677425257330705190073052226198017136393443815385404727664404200337279529401554739627128341417139533705438913371938356643786666943562336101690422815198312008437554678519283596496258977357598822678663363743403165013510912592219186098388388926121955093270673902166807178577519045819813845154669108251511888518526904927019313632167584131682809190040046007359605800781303470097133695550442573569426839242583897107493638298169967365236971324304145686255130558514731437958409733781447089167459028874149692962568810561536315481914203012900049723230193742857930891122680846418959945040835275685567599956450672043985711919467489747642539781900507286756765594520419785013928340784071661069292877113097344290755540797304374284915585654986367122136498343144056390073203388951251406609557095540322603652194302349599442344612593252465667714703459403458625553994652044374329196786242753247612145116862118604481993167921958140041702132621239030144348021895636188028351696821405796860654380339887455426540150176691041273161862482987374862076776119725025742203115644202485047377894713257272326427226740401745282852685099962523422641778869153263177351874180289995678901088248507724654305684904561258774398651657181961798311365584446049939815434488401314074020893477199928050597833618229111480312783455338607185858279535750625655055046081542968750000000 -297389577428734025830727490105746979623197735914827269823007993146030887757881581581655009768911912280384156369353783928893652904954891211346557402600941723169089407109772894137441878023176348125998925340056140256721305791833696598157781232521270837479330850681477541602291155074212143937352932983019891821980498229619134448732323136323814800045140003708187223793590998290836499856058647633165981240012395288863935265093756883976833901580964862067391147749530960041552181730873350934049488187309786627296115552924854437080155502660418861327661197054124085661823820340972114836202215048185604179120336298109613719634690737468562419061533852238493869083585111070011103110279402874015725506522364748548034599407251312862941742551822076074621594302658124103441645033869021271070255821636304900804692253284815760536418156440609844268940137647522318618451105080223727073513201282382385810483746239632058039416593272441795302751845094135870504910450969329624652364579109468312450943001824153372135156967315437945836449091667912189959655619497288464511881892419325316328426620408977521490412387917396919828013812568820670474269842572257927914082937815391730765006278841767245634960697371855544650986548850659583784803960751528367702708590341873384586816328268161249740566531158874251048517131886761907313704032782920541328150527254819908661940807301258894746370032434675654147152537279452025514980422648452298983734465309680672362446784973144531250000 33917773207650823462631041421968767309331825733159503034114076177039276391959746512553180926992161532724974276524954277949516314150782506225152774352163191014171402896090730964215384291465655136641365243920541977424141533522217830204680876529627050690487208235166074587655735223468187286022139830775206809729259445761188218331552799739672942659002176967561091555623995783505059057751060411622006066577357327015441599377335761788961897598828740346936906390935420448472054987969868942684860414184059652996297151364985662383311446649628594741928096546590988092615106885200928695620478975147927199458554929575108144093606957257091720387943438155262042376656231804616941386613472576972795450065139925684644398727830038093392892484325601841303409165961175678162849025756219151317320898200684636496834077193182938439349662295902253167268275091359272192211296315547169696903484918542493406451383781276032301053950156410993003725805115367639156331864564840942419599718270192588005997613485869988446653542996829844275795068541839069914970009255839515986995381198709023853022702322387302132240357995503802358432535292725466029908010372070612408291311724736694941283911430612030085555217630048343325835938892933291174467304959336082168139769755260678531832020529861763738366793996503788826894541827377818893680604735115562074527187110059263797411123059660190979132412333762723504667557767641841588499396340959050194507895525930507574230432510375976562500 2175740525660418227070847206944944150919659080722257395236593704335434942017229968717273932505134683996357326754121275286744288226812615606537408701455786059015620453489799973788213248982312825121002513453135779870596377647077672667866448704778818072551010715909948635743078351902194053213620046339647453972600276575316264826138484315592771083779429323812587964300354305892623714680036109083336037679758627609458002021052654900907990097071419018903010972869379249524776281714634524892678633503877503208826297699231449178211097921938313422258050648945382592766114189516649370441030130939067206871961592398669300664528351713912100139353984663351377258708279643968540327276109814425631470890176369694595042745399548809245240999541969287621120170501465987745893943501337867636153606466370955559526737382053217647966432241385475181340160658411776004605953240140048648877664925956493710209527929968831073896570016675917771765651952133629591259696857256350534168742018267961627895240739634389965164448968005996521648046123436328227212005047851946404444261544373681009999252767561843445362571896183154877052837541452967585194855846944662309573785560458681296547040111135687405946471277333665175208546841394949803805513138895894521830968033560088166718088855210885440348264474386998176065651632679236615152412825025381953841616999268402438036262096423714796136123366002922729033535207404286959045581161236587730556379938207101076841354370117187500000 -3137101295791215269261418050121928698296666148543343105399732766117939271381565074795837682114452524589719528853778800274010933748725826983657289834206184034625553104237499901325793493885650231765711423336192003624918310566101912414962472632216869985531777687155905203156397680008940134424053132912663640273048991089381125401768661180514503195130222319990876651780524778092787328415636508757178074789812632197911547407489315856121265437925248010349893905587493895702907068574506531606920203432854560656787583177581614955152755393841366186657903306910318059061626522664129736098959084747270020833902664820772333360930151027990945190226490085747903502564332462613231333192787881154657828913866277071827164046604796442080991808125170690110813008999159761755764192885446769020632418724453411468774563298861788175042582670001191414209522771398874240361388839194582451084298621073923734823043954178373739523762065009089862314307336777557880342503446898672852654676834085176000770085212795149763500628824583571872490898552174693874889448487314550784415032692656142641764773639564665748426197329790142158589365016564344434198613046307291212228758769136562665799424105351295726566530721992974707936986347623349497120023105374125615894181496594560780731364678954038287005461705205217370595018288639810335443912428763932631059028423880923654135859256108693537832623570215181801010614411683910752346790884784698272280678565948619507253170013427734375000 1361858762719173498882093266164698730086501889232447223290102272590519213394499750269765673094321769745315270230820462518785258627140794434358065247444020112699708953117195774146970751674577011476018448819473301480911103323970431855159651783724870290638898058357375036987969259254418182561279347442634695195150445692527587019051571285572263976590209415148821153536145055814172265301058785368355439287472172289329086151018411593076988167421205221931347689932326610775318352441085854255731972928117497984640852449522196346701754763131751403416312863354433955078058284200602501761814901460260019786582743593537719129371295970097807249570956700574741439987581650875696936123218338995851267512575600703912913288565635313652565286551166338119471569986868954166047157334440911241297036804972734993383455327564177150861407744311892320791260588299150990004376141865226691205257285976925011396192486819912571224713276059422979490519858825460330641070575101692733556950973534592730645271564302953696283485785971328767921649139531934633268060873584633191192273282107229286173106317499357471587477157891560851269562788775275907148563863046781890978616274035090958697923576486248560211466958015036805502340812709167769724163180193781237489312669295497353556648053840838423474706550520420532363672604668595147233734478519864545283883760902067009458130112156828865574708834782399690458684163183218761122732952872568801261365933896740898489952087402343750000 -455269262941324458209549881157969227093680806161167448741152117315627106429966240622669768518259554911563116567871208821698645897508640951162753831177539804757267667586969580511870232776634210771280525492735981118747473638270400537697480510494184107565216652167671483793181801570177049649318599441980862561102017038248227375030868118556906835446922229725182953236643335870344149829857623404694351640410680357445129353662116374733766137959985934703721900160838170692542815698744593288676070591743860384148736651156059884034694525727935066055587646580844409634079127401994315346835226445782420051667847398861937665126374880501842447706778667679917488067876578018502278244074063003549569806615235402715192447544643851438556329847122104205345629609325662176458323485067788420401051622656639971694855378450119260952048362154376766380141457679716681964436381247231850189262083791061632724632777270315037903082434493880434122471396812649135835600283936408457781192999083082413431780249095775380431595058124916989085268298259852996822474998077454184821281682576523919310104476447482770523062556280105123702962745291733683466109817408399258276179697062542671150225271768225337244016751049381096628084733804144172151516913954060057101063519695587368460729995304533127756315676273251634322288312425401414746901246877538519559317572272268422396321652869834041579811396786438517911484937900375879622263151707498712861266199070087168365716934204101562500 132861803034137932379706707243690341146774267894567802905012026837128034170230016141011279031253899739220276787251761121745704137548009565462837796770223647221198141629823857584635988371567962842857575416937302079540250755351256997803919925488749055636190962265637337760737673768387193603300980440053459481866643321694364701016250027530489760805539994351518105358248909969723779490188865281550785471525369656867133717154672747410574423493087937998276051991706129260116511309931490368470029773282804373871167123905715031588134024507601725122959497210892975605160649809607422210797016099158600732709013520750336017868047261887449046255375831640378510014093811620919871268522052898570722383703757252011467114016746282710500699352014495413099307397696405923214400772524776962606345177819647341245242087955253055171806488128523398301576735174058780399845998767725955139708663406209797532559108162078533500755070314150658584725247831326414731790570498671384692206367128888239514025077474602160441774211473849249648554761212149900745385613110040468259071941811677155115812882573858950582329048317536098969985892646674448430318119750986369619443748872724109858522257606281478119362381511184111301889108089832412431702161332983067865385042863679504017546709793808250400715495208913660458938334633510509440507718220508373844278544407433937226990551411632458053840159260359969201386539235822533230229128276000949426816077902913093566894531250000000000 -35250590085753960674409430688422247449554453540272001250113010704767795482839160018324301056184348988057830616954976108099252853138430730195670798988805797093052515786165246157245639832884168002943375057528327229231633786666558135778759012927980302374964436142518715631583508731609008203695011817783690800081779000189632180193375504670496819201210563303507422105650361753130566877324189728789250869646750673198512901166075478393776428888535924093637581431927833563197167359483850814128303378190595698905793506342935834669954255044035799412606602914783640760888649538374564668591279784039149479466879725916352361162036702498897198884308778927365409213131956367876448235606431754677508935099756153807549822149614900477138007614107351538049995898481290940975060827803643522284390381075603065092223072878978432068052487920844045299687769704906238199507742239740602498540462004302174915255031838366672218101508227002536802262902011280795573211804966923012723459314137924859945691291007544535478946684057916267300812692182057710398376129240613216039281496438270498586648929202445204423257970424215811930555982365455279027053074598709298067736092518329760234748298446117368335700515481967122420136177095870097652080983317519302109460659807021602214332774515491187817440496090899985491560098322996011102744157955907217367733389509272131017954932367344585769044310462584126114611651618996982801248389963189033835533336969092488288879394531250000000 8634655873955715371466600163351127680925604213645186611162870627028896733913978543830310588440873249906738008625930092597589487682253479120756835864823433594107218273418021586040468656524800521100911659443413407606964022856403199958609625088136672042249472903159326693797148940538233058012328726303501760300027209105465940005909553290442061072868075417033772786979301684760256720530963963773001826004812949877938677360483546611424965210436688335938694312719946596808787752289697181630075259931665454299097267002041872792503617323432032896091613846894774915821111999634982074402707793104848515308296178277097002406564836438258607260521185737820416057972596917643925341401730951699709451819103863063544094930001357598344129527109492378102443888439883478687927647612630575017111317482906918555340607538892768397588703894678776909081614908023851216251786242483573030672564990270527327636763609360132883900201049288327819471578764372457945172205244363704696849989999390846636910428266077174091221800679930216492161367345230740631720477959873448612783825524654166790692714653492067647333325684675831874002447503650288236808008046679801610331402102175357453277762360532111287480496119161791359800112508229407585304409919248751737850070922060367695453267370121185378819783082667843227782542296349826578174544009006743993963643999697407410889617797494269846885518321592728583055634185542412064760450784994816331163747236132621765136718750000000000 -1959089986859363685020069367339929732092993904494610101654809773816762417676270209533707663398462556927439276566870873843458903931215160367187024397494172820277651168373034793067770352756965905514398157271245190487271311386796953594479020246816472981616139029695900484635638906433886271482593066534679082778000871069415381073647903322083294199610200533345296503535986633291494189292600086257227282067341906377144143140189666597509001345248823909589039723379676546481845597426183990115985706033932417524473891856372426759394149030460565246743383221355033789662861029386241835324547204742958304120105325176561394398606332578975091553156097105697773904012175169533070636200878870555349815952115180461380402722223690316060814451881083088143648934259927394734250917511054968888501021776586210947087424624617228645514702019376331809578075421192398552182209731935210328883071829858466806197631061181725666500587678643176624182410323207535560020071840929350053973205757556835161503891305034397075718861378290828889090372595141035261569698647968790593272324993365407511169173992226489637099977714463129177680358432647919665141981299560162523212422699776506881164732539437582488230334642802033862633601727790767005907556611885998347134764231171959494866694029671039614413812003653587703631126183162879253535852149062917714687087401762890549566677619595256079907648130740071179036828169777171151228770606348567051568920760473702102899551391601562500 409059838522952378124873061449013825942005095508739481763644966935111144613250488016609742231533989224487643141243906274758892708374644492090733683692539599738826239356276109127454828258447915432083017341968859635301621862643187833457456885037836895283936000967235674323410181246712525804440000413039489923186962716461358991992551827484377985213402843470593970938080981623219628854069177274659349261213775870861002166004571875876996119004308752574824130005579079535675373454530761257817644861364033776626720991121634631530173887095120166005406993053641010578196270642668611720942450879304176792417567927237467891035431985461779820360765796730047077443344188619716353822809837271194678222650367229555231286314417799043223224744747331600834774106579338062304941361074639550621144923826554871989493071443260497260710195174348933348206133134000556101020781531417263591575686321858298708769027563429800276519245890483139471843760694771389342173937218444905220250743233728974522669979758518424130258336992700680907916744961105840661773395956883987008038111465081222291109611687661438331536343083631753662012088923494155354932607014248187575948727978255077569108712757436568854433044613650845294354328587087024783824541987263752797709780963959116972530613114949241877857549007894911555678414031450051721927906282605285006681019145635823596038036340044508072779007289966654924142216967104037025508350353120157194553030421957373619079589843750000 -77019985400694800257178827546057703850095691072646489374523915956495238166234645892066548375715062651689910009934928695298242243688591425653318437371664666434174208023176799113823938861392725904768057285730318429551248776220811851974419524743662776241229177084515237068167017954554250209951724201725745640155509051571795723005195584667984008775758612568228686159811419893502586418964014658195470265034198076517919067491145850299930308901396491644648104342268107182098015649666757590644952360364645458389192030991364550968353648113002408779529272830163325896409164639568121481765767440217221726949862800274025108072983397578714941326127891770851493062181048723474035574577555163579516374469610118016892150913193842605445202312721764845912680421689811515017133826741744093561858818125502868276006956543367033208943984619767900910340671071819279300624511386347410640840190396306054290322332885988093763260093779153012849360222417537870155321888491655688944143198751975176585914302374178915885228219491091166540047939440158275485030459494980114846695892975604638793119077844817140615462294679334364904080437237018135881009438470941750607525492924226819578034843986356894464475400745591076149545098279764603083034667710788634434893135867335549647429305573014204756828142185405595110030431278421903774431810847049098173157553625728795863271587080212985982276752374762281678489055347154273423082213555213026978663037880323827266693115234375000 12406282609035119327315600900869616657854654374049725586855018643825977106751697809239164087325186082974523514719002722270685255963555786382578393299331024713201109738574900327778395604285942963634062622986598254295609889267976857735071238075697658383928174312091302056537579217415648848064700163440009583311271718638661154493180567898448011009398813075298134156299777207780456576900654061899193197104129347080848390056472751074612584027491109745424975911234216111685546492165631990699651191398097611869372588736825176238268452752918648195489132030564765776216154859122466169462443780337249305491989336309149753938267238779873797552249631131826319973895807820196225649297240273575119623393171217173275126205515906244587386255227696148675289975732390682207344807036509936364090285068974425366738474931303980809589694308565499051531903568877293149676041565859859937219110578073804159858674725100974515528214346952692656763977247357026863384157133523208389772601484894953850168354867553036272034331165923877855556163555538880922319955723044404018021123754452082474287689225667244351259910839989832252810086471774744829887480639346068490834214889350355567361294893117144006138168733329742334542009463917414415496034025630804146806799516263701836359479132570719436061025681841120773412955868600941446764020619098918396037321858610434434328334284798463601798567688476601543538587034669081413790475004743640852211683522909879684448242187500000 -1430881704621089465279983090873631417026430566117866006091683790149480718241112285835049969039701085365203913064448120075293181028993738647916221349516116053509071062329404281746919041232548420872703266791741422288920576198378291910051471615895938913760732974660604987109369279184209873276225011419345637590117146879842183153586298274450728529739559439902601537108610268637855856131938344246765536823194491320266078861672305133253455722653159029564798905368091107492649736696829174091663328579910265803688124000285731054893802889712326637494275095791695933167302521386095434187120858008927746014325988564075852935282543095666030135010671628852977716764526367987044983492654695362951879161019804584643124713670134098034633391808297100921736894835290695961215720437689406574657314337910423136688084057639581488627015349138475979630206775752593207805654293013967855401419601314256069417007388452378705871855255913117409392422895351150555843973972070450288061079259327105625382517014343075475316268738593261255254456440981958455657414383084916609194441810142891385123479863395954839796253003270919852021763388243472999398039366851078417172433663363630326987717306029282624483885674168668459728942176341091761660074283115872831161462600941658299693871257812194734967332373453163319236635758431229513262209962946390749776176691553843509712900610058473152905704780802829349473608441918684747562841904494623790355944947805255651473999023437500 -12424853760655188296570357283323020532613233147672719266537606337185048590154494150938349666890801132726916197698623026902876188186971658728022040685488403781141063828472014130128748729614980406010170562544510604092433206225331811874552275291263617622263112630496452974482438423994811551220062201121832716056737066346937707020572667632604520998328163162753184041385557241720087735352687285904135010603137683997750103720691180130048793939958211707858612296668883218312081542427195351742047833464432029746333176383079120101771992915687439906914217643409351801562662300099000934838427136089520944694924284551287381853807127164811906796083169369006917670811375702522354895792443309188902454030080824603785515361690890160519411156987793598754196894000239986606428794889837447029066615360004675273382076059009154345822976754230921793204219697793590438734290380197939099229942202432786390166145186211510456803026049892700403275063101348146458552585343033753992806391886394113305397736556228748321570513981911278398118511866955163300709106512490573433529822218812659208793409823525770206108181654548482350604892136549540150212612882499766500199483008762671819616867910583957059508582612298253313527439307192623640087731869754908210935394275937443530305114608319518690183852187370411114954180225423684083654456624914056457123713361190222180894412329818789435264157686917612942097401042131462933814159410594868404587032273411750793457031250000 77098085168741644536824924921431980964605245699545128507904426920054402507114210471943489280934589765296966897738889447307220763362374862150681591099998847570466807095713319965780324599086224906781473799405307800891955831302721805502405088068886155821320405545135441931059549494180921058139094526465222009360052894599909964081700718118178206827494120897225377206698987900917645472802353615633734332242641785163908283011818161402733291391825580307101709623968937624342801071827052653900815883514526293602801684106805272680506544893211505372608133183892717053684990768101429222222853834903784827471382402455525124040111943983914482434777054123426998415007341688686793957799366397997688683378600841237170703465228967479531119097010740378296545157962180432196810341141349936135104151104120745640355759401993441052240992403413909368641617462377712502552078021747627060885430355361356072679800945361180078853195755116928552400840267001516547420676409103581881964893994550385168134549583041411332540627040407410771346375827579385157914293865738506167426536094353309435542397245030077895078870878819224049969044072687640849111877977880859058433557543116329850883756419893089423839501061651534816274183431597376904166095852878393450765415102575523131522995689208563771600165424719084084681016749338903819448489404295690100612268824837195641236296966183824764756985474949025587483175207380319991432027215694233746035024523735046386718750000000 -32239054243953489055745933085591740996922559830885228051328592770437741652005608074384229818565675871900172539317023561648685303841995286518920390669405352143310392757124670749156077669328993321995082439363555024675898876295272710407309471243335910115847061965221549994271538559442393286191890715880379235184688843277034139113736361532528087023204929756966195943755734699942294895239703513420385372302595757206841689329041469839657862122797283841436711304666996847926400564576565255234604581036794179615512074626304007963289519566527524734970517131745484423827164349631873528855413255138573689479826944361977482767898709385302709787576607967746859818414522815352237825830511036044440907143287102521625973484588130432244686215184795108485894137607535170675556410984917610213985176284786492032280332106000511116303708083527195578399720211914783932268498620034580703353164926947154633252860752421327014293818677106592828076834306577591220597222421010347242365660898735381993116768009203793650240551245691088512905843553080572470160890566687385086531227176042257960015026133803709022368852694988578976276578614029696063369542316353989301327767297575445111874229960593333816463292346260252963196499667485272409488687643565922592720725466211157375362244450790447742337580765255062848157421674319809338352616198238713099377413033009639002630252272984427885319932582343163008008286259102342946212746421785766415268881246447563171386718750000 9882964840449036796852208504109179880203982570835805168863440174045351135467199538127112817159014578892330449656676669604250734844072169939617808361094450037051094487502357675177644835037565238503545150866377582036774643490511466403381882762468849526314765916667715678044924456960497426912860471487128333829336781952796730312416868995989485736743204735261289509237833480039568044694771813292847724212929481332573782596204230427682974094460761387963852638082162573439772372931654786876067547244149703153801073605081091815923421388882750955884020585738657366054180175037761065380595541890030203517297789238707726368503426902424475650194593974083208677236316314090770157293208907292243907548330039796169846175869348965198164327894900232127536560417613382620046322842311991285473894126748745169975457327685057664103643303255069751385344465025499508926616995351864217541307862063294092690282820401499303692625300964091829803778820625885621160552964806873125480027245369128198723307342138072913399201199433425900419575179787164537727518386952096236576475997764355460419018062633256018144382921540162649712661443047717381336915612359034449341838046828464723277552560837201805985877094498195697428780606758462570152413203208203416005838108316716857865427280285942917517077479477700162519863581131799280536529247304427665574864623358568323940347653448271576501054168555027875809869492588353733799038519647339740004099439829587936401367187500 -2603845513211570593198872086713649030734889690918541579410173541663013071454092796715326687886349450133614053535546443650496293383259869221321821713782599809569818905241854480206544025655031496478148612514493132644551877731910299889458163262218047311656882595693747065130202294488491699580665398554781170141517566005706833055927557019283345815698534485528311384761194798786077099212925149539371148248491276244033127440778903328946867852412475731637679045578824023231204968877119054893130819318831525020090083583273945088861603962186853381588168400117521075307154068991161404403975105710151476633252714243202293489905919333222223174672664046872608466122426694186925455590881999108931991381641429756162614524079302055588033390662549983791360962164779119335642968985833748969164585176614653049017921556706694882760208829304149979606216773548118798416794349812948473983211623936457522487667909321264903572073176467886796338219472484956095360682474112415184266917783092863312355690707325668983572261847357386217110126227621010549531620698231794553219504728607330068908501463923705815685628336071247409017272121085845488246437572889001801168913310002764842433051379098543950208347703274346206749000030908823015022157664689791684636019155600223856273160372513791791563770273934353737752283237359632472464541820035425146784509030726922079146866898536164142011938423774178679125093586551796759429727723400560535083059221506118774414062500000 618772327973891110588599803585185673822936358568306247875086184816075459785409626044355643149300769880173675978902114224864950815984451197375439812525308268969984577423898854957995601730155892853265547990805508163284877045973341238141499361044728314657767617964615183578406826367184725030175105573112220738888311597644315856266773659983045700766003099529631508599815750824402766944202748066506201764556768230566636343332072988925697720388206788103613817143817574584775402297082719815850577510795059663777329601803784597368089843624566772151755767306500203839136013655005861391058145999281120955755150547697578640098962642306155991818140267930224662302273181445525898561518449936531111857275622843034796282507886163237290223779893743651971435729756601876345562919648385837894297908225056949445270387320944216960929220403316993544688308043361535838471021270145266879613507187389632793347658023588208514557391235260129482878397344661527558052705050170347237822577457670807175192137233724405865520395833421784043735911106732000999677618675952223981621578921824505322573682170648508651091994176716559749771983311552482424138035587059762938279757021910229743969034825143648007313484261413084698480509897012364190955152928284242558460066093544546844789676142347394475675154803382086780591169833395556822614667389892620820587825509384256561403015306266986463232305823897357679495916855070763800371336227357232928625307977199554443359375000 -135066163481876603084439978524727111431338247960091523411665975236882766374322358874833022275006756556608902787996851762204324609037484579741856524617473851796292139964179895019220360408329517276178150130141547147664927629923886689801725562329938789838486566743985567509485024541661910932748975664079224555294318975534968026560987290961545412324493755468002843308477947653930346461690404115923208628095198516379909550252379737430118159891447573964780131589806156087527934441396627279509163663086747121792333898247350451373647942135085004311019654841900643242682689642529198041052715179965391814230106957512349276570993441517699151365007195870545443081900766350630531902892314079298314730183074422757439092913910748444173405334518038025959490510848745643584844816298615938638267648023407782051566236116083929059114763531151850979334081506097966692445676863065410684469657112414530141601961450211293206004191682931682559399824839187513971982887930406356895767118107391885048587913741391070427996680427357206199592765449317055552207534722183266520667188098853343356813410470448869046716670370683965028542914850492767007702804499494199246852632949160444353432420361256075333441807029727272523656954500820095657417916905128333885809919370770042623005577662948084673857618170738580328399517698476954027117657155328063410485958942338577274367107215140484328678805559919124150980033805695602498395113677531753637595102190971374511718750000 27206726343090458604932562440364173260562918465636496866341334074345192528032265033171715599368797309297404342577422978541526341873163581862904336165883191057981375351763595020141099193302910776187692670691233340022535018432394686782197147584590588297863343142574891321549222982197792286237240882586095964510471531945408997036579311600648752769443516818969626259757709146819746121472593249360948917105934347135329213746444728961115390042704373026302773345245956597922670742329032544952757101859433844846711267078113323007215986936534220545139611512931469887923967594749377980157055287665271043113619813114640581978003806875395793623447375099896348996900919090145277144886387596324927513327451655659196281577147102620104660125483110686355380663885176707462033756730125700340616188789996343579748705642606074447708095510388685125787448672628377946646691554637250502552593119555565146318279712438623841667152496227201988440758099599686412489371506399179338488629539704783527657587391603456730143146908229914166819252543004972069097919035754211284915834031480767168710007050115687817351763005105563166743393448913540516997775573202406683550364357199514354348664905925917449874218319595959676567909904151477255269311204228055231627623612144784838394319357522280534355270216593595838976485818546123606909042003238930812398021224615146630767090695817020364751987394035416536031273195715247611731896215658821347460616379976272583007812500 -5028922245414272778938195160999773328700783383605037451398100580972011436385502378123077125291497493899502229637908279772847378169558000806582154890033796174169955120277184347559784435255137299083935392164563529305108337125561914038284965091220969610591422679343800457565122870320233221449963746671580954537096419899840951408741880431301849975960797122426096634371199521939411086966064228852595812082540647239313671506172912567246440554928709604352247118728731423164970614776962079032659397755998122494886343120737962602270871411540281148799447281739655570471352421862365030696655462001721084100353822575016628379076201725412109761427493098320253431575057170402710421123809865723323269006459554650410676638305127725160885985183830647225325254320304227831033441412945289627288204485716317718978792875203075162370473271448211795515554688637045131571596150770452287322815618059741172007423124425904235653358255651981231831254903096468200852801212497417491716483712647053719522915662824021437587180285429700447088074362921904012108042945619421092859146213382555162667428577783174945389113579639639781724798792610112534702889129565438758084945853951317388372771949272698918700780816994279030048228715489138520763450316415903468310378689521853102828406511940866746490036725359096809130743558863182688931047922293921882134610716757130842968402586640117098743010886843321854824689756192131889767082952857890632003545761108398437500000000 836461564353605882974775395799592764091386824656732108839909249819637702103284656862773521211295539854215106939158524009507024084897207269812941099392307595352223696392393715078703123692091011411997300032942950260070877967876408133598078361967463455348231279130696743575195017217891412390144906375133434328480556436504104309731138250069037898717403369190166060524822323949806230870570022368224924518573442550411327926124862321409297505866602164055617508840090586970491753456511293042752228627536965690458524603986026618390994776272005583989208503185017903487592235623612379846980937609750326793796184906292507718195861514731725825185172162555552985488846941198086767617636868099613761805113691836968068795605329846565773649117353372249066735200669625868177584211027145361585276517266436935894136998274292066093651893741608784832282602182840222058079701588558668109719363546007080231734502408977298502480221103290459142801093573318883450475567710151232793981535833175875594732534529839233070233921430019239566627688755911397187904817364621651517887773475043916976999316165906533300712501972726356051063016575966148108276141984161149927588654905590963201071656181355709478837013961467895654598627872650573461701671568192369354441390600087861066010051311807818058929264204280149659855461180371286935795589391202558737852037967413631667510343931023352655399798018689737669690949174901295481987517632660456001758575439453125000000000 -118972319547242449999984384662004647505668215446860519522327531099840863087192133671683119894808433487144516515594260890955065270299106238305140335512303671022325015602229795889934467913445194502807957002870463742004253871129361126117464228433880143884010114904399982416089671758663947715669586964908555731821950761511921869201744141534882810976063726019276920999532891835019925072307317485858655916196398734111794774017245574751563844757873504639188841288366235533963895892645059623496518559421575740844603210115683685068114060190909353392823665260752645660098396588633530412071671920467805119987696272205429874390211096164796523083346350912041268361429314986340499668587667635965421698815333731773129405278527479675104429601974227170179545691503451281212498433387879591717485946829751281777996190540535467571847514384208292523079286247375297941909067054019111833977835828496155419491974699652965360362917379178062719936571202126636669332500258840124463148288884729089730750755508832160286112440498018042384051293811721404104401482025191506170456801636297056787871642681499512697148387448678994185688035548169548043467561329412574784278187802993866000749191049026603664840675563204697342873052176460599160479356246208822202134035097778078312306690299652424060688893594449083966795257076634034306886346614633123828483123964852554948728359016731689929892219647006694677435899461497709195256788916594814509153366088867187500000000 12211870073926871769306877355073856328165085933462640839702508788952923848860278455653445665314813997756418393100385133867471982079293755198705693443472101669066454971981456583732997755848285161009973255145524693431692869034854323675634412075523021279004494409259215798635899199954432490584858645231121881974680450068963543373362258638540894536252496799948516509811104152362058317616834292057014700255438031591675766593870035873944945439907142666559174807215709885714032250004352173649562737034298376623698049883370836909204076185642161795714745380133610351324228822251937308419197289582054371405902123633257062032136739802064546000375558796750063148654473899227838064940400283848922018411451337538132603606074159628128944490030815331931225704732466928874881345074694697698644126211738546476886314314531643306855239452030242745326094089162382185994562166547034221605778648319443513316572335735524760405172862760583766025943185454706141793346507891273940960306397587520226312409176952290374679154781509823314700125966554850994690062458723320835908454732257325106646717342767511720525609918231267474121913613407503693805504048578768257613257355755652093352637343297152371934925962075054127140105737611461974942978505619618273454225114395566506732755301323030609338791544467274541055528171882963649962960249210503893805114276336371130413402719479430865488016028227470459297820605767720576750878791472132434137165546417236328125000 9610277578667873036064242512926387021851071996482058801868639858005965772594021618434011821379021511681749761200722524184473568596147187955953920762927817370332312597835283281085727164222023065898876167285569026869296385906887636838761541604876264949921571581763847769479984420563233307573022560651693285902295651303982338553399871122503260587703612024912173836223362028336185673342979117240351703220263586814326750687558450353124861803227744475514569377475901814138297989866075356299667744022419629875120245631445352733476699885036679575111264375921015383148067141992300027314978715673916445745375217348370021977655465660385772273423790048475643930473481441604557048043648531093171503637910653914702103639050130165252495473034692555887322173703514136533649268082979920930361692532839241267817260624807228867840460087664898682845927968738538292996380639938754395885015712667184890215476204770241792053765802162676607071612266233928958365285563358489553977208328047220769893626662443174098592813373153490107505294495631157994937314554091179320460543953971857977707948662354685629118226350736407905078951237198407395356209960266685641012481331189823638792157569211781618726810459902373657653094783509349625490447218552980275524568509693157848903449923826569944250629009017956432570430590017814011735175922666711161232936002346866259449855801627883121895391981972197353017741381937116829092815351032186299562454223632812500000 -465729069605943866008799407071047343626101970808885550438384184138868969970760638582540162170450452424990438520031295756096167204203315166462998940252147628620196029552329988249787120513004458604659200034128907540556587580351681529257530499199398280103509598440673381208334812537288359789382329745944413787830797027271487963088824367080708444636045172424238578112679477207356054995725760321415497136978149077568459991763061267213239916487627539298141197155479569052664939321265796917111842507311475492356462696309973781642012299855541010700155373842498370441736784150976023906002570315180235508013530706373139129713527767282856389226605865465720711952686634099583587852759793375789814504416428870620991029557808261708282253050763787257183739832325921608976764144138870146227022694911800027695818611600879906703664913154783843681722245324535268254737754796569537188514886724914927853092489754056171564186498924056477569242646104448375244003190677575615925421528160840658544176551512829488617470524948365128375888663178572160879029519017976727988050258428038913257866790743065349652382543456682606107846623906693090515196934978663415823138613040012689683655185655032406686942302799017091778303173998310361858127036450169432837663204510417632963968790981734447749122235749517273968717425988268551596605963682515287866823978357516182248831066523463343231071894698414630647699823958298240289543912240333156660199165344238281250000 170548576417321420086034269467775314753038173107691414094122484202405879875116193727013082490065033803406048745867050318284702278832498746857611616493839883432468833546220321651749466029199829370733226071524456212349203126022503934081188311904312184381155369245635655086927913345106844129651139286822104837477830855745886309124454028032145782382286228299730629253452156686896476013596721399088947088800353951907645321698234987643407509537087151206937810830944935460975051872990697418949259920607821266585336431610630003356091204936880488550829341419999368563698080200060400099712758345740843845089969688584649951563224341658353900853536626060012297512503939017834660107007088362760474789892889897679626501114413339341968030103331176133036175634380953047981900396483102202785580012791009122116952009122052007590707374205702486054634343340678877792218034981426626994009147991353738425229204867879917509584811647442964110559803433526794463844523412968664990739972736659250149212381289134684306089072076171665285356675940900560952218465116243299235425626802834828839180043549345321679241138705086046904437348706167421659349540500874853364301918339527767096430424428560549664704834169976339390412421803351999211594763670584668079346057657077103004512443146815753954973516487350800825349679489486692969950444886311909597763708374242720946189138913307491869212225586198719757031016359093145151604176135151647031307220458984375000000 -44931748740639089358255465618886495750489809686773141129088050773581159339843429786862708658113114094781192608352415467930462390391505353133490762554162937444123419460089838609185223819554134296406129768123931392701880100277795605536447297865240229581910638619971017595362857570568618114594680178157587361882044775928941779952631581477047030948592778676783992164945254314856889422237661820988843854804924272120448566521725720961963215337571326093076271822212776929156706069190535502544250337593391682510480621542708499104255489261585320858992424243619209727825034670645466741408390410210322930305288507619166989808559259232164564352967355587782839937203703202843908907876299613389647857306794906796517761581138575997283469592823571965564684532235669040884750906823220627049817490214093924521091397093900186706250013043551196290137169370868746442567857755580391434287407721155005936235506133991951631577432944996122660390931766603012492648677780835727292495882623816610141205808780015744686713396520064326804400614741377698207130997097877892032260448861363576002984984592556549509429388642338748932106496837280874244441271685797553524231601585240007275839149376802704895034232765310566739062465867369836921660624915261521191090451510705759526953341090771409048166131116447310677293322920923606602037961083428760657309071001067550309475508987041195053550911577189689413216589942566721316286049159316462464630603790283203125000 10029235292498935490485540901380138682622169781831829506415841704643408272086036654331733986441758160544619791554276755825768129703525439316400731607970667689958738187999723911067451335126240376401900662078675896527967742626885257835530650318650917139638236235605765554128886464741531114042669893301810144527019825767329299319848502854323543021370630345969710844618264302810622712899517247120783289729543147055223359149157892182765090280027591635632821484158201397946512169679470541281026790730528276247450789457539938358791395805933118503020233462121693834725058971833290697411766659783078090509841643096096685611997408270915536949991852289672863957322440975978943223822934078044929202897580274201755552771502841224906030789361456069423939170325859850633906885555291819953766716631642163182089551539587156354478315632332143654480452606076217130226784864896590974873363004602561329641546537940625582650456699004641182274256337745393957913184506930850906214151162592879536777345449649504584392695010225219463464958057404855175302285292648453452280909659906959345523701758518292711728785304562014396977540518621466746168523970981062387120616111322151100725890472520988588563297793217554629202498983007604305343004647266527013456465903662699877306375647918814101641814424989548495933259109882834685780082461780879332373602028205089578302621159242862779093822653705753510721393050465072294130663976829964667558670043945312500000 -1982257490015948587821558523334932498808416796027492231123420311554527372330331532543066431587898596592786939590138423560047280923858268004010380711993153910330192382109580192466772207123372329199898121447526670964304958514600201019058344245457929243213872823494345962682113570326436768848742409583293446399277137235738142860209307765576687540142242807074928336888919942871022215760238504849099323125463782995627271614752060624164279903059530097380387190213275907991474359118514281217630416653420359642047378089110501777879606946775661153070854720329432039440485407645805976535136484566486144239622200389188232085648048176475179691145080449963757309667214025145279877372993750479971781264002222987852031332487160477705265670838095811070405315465834121066665141493577750834778526365121776006833792801264115542118272957303771956969389669058399652163566626141702434583440342585209616058225549502049324259567391752018895988492051369517807279086389891579658431048902425529993524348682529856067031482538876680207074801525707813976043698883859210997101292256774244143512540407140041855093572730322011286458112052980072066186546095639255727092541003549940213369254904070255055524016747970528530587558641378004520617462502327777178843938057166006445502245484934259031480646166049456920157328802023854249306405717617134900598327131844083406244257295494130013441621639079167055476788381410124806336625624680891633033752441406250000000 349716603477349344880750022992089685515909173230587149931371712172911871432399601034726208050072856372189495704311135504665985221049025209919100543286189646835455314683392579408826516833303470040905970231749709270473288590410200644847579749566293332041448225832007344739192843272793293133436424607393049693895596680401952762656767283766499360209879037609528714411810710522757077883873329670290604605482885949136690118934186091744548719058326711316571223475426518823689112905933841131984731849418375018377803501178762085806504304670735830399069587655596812655871376758457569306808775456130784625362381975916172866966611982288979673425143622958241293503325999110222773009918527861914535376061805797325812736974113397720018856696309124314965369164431827423160511908450812830776191697877152041798882707232758858465479688554940561615367853830103078621300989630127306906098377561844267564148675096010009452878823129257534917671111054095567658996700596503127351540915868811178032524468381241882200050866184526328104008683847622037558078531273033563269440160272387538240129166784568582651067367289466079653705703388164705939820890465512035173745980530535158381723130023685957949728535432557986871912280207746427274024421985871458459050156231686145982668406612100788147433029010395415794369737389713395058537582210002517645050378701214409402509356034815523963159223606303301653753970012344920448299490089993923902511596679687500000 -54084716680665394960294611259951304150446638130700204725621265481592577573421110251662361255521374094918826362273371758390284516920370211966990392085988538225123168682874721436128887793737044505862858550135798973372959297528593009448422829122735090004175818078360900995015957081728482617534151342338605517142370462832323896599732372944329550641434005728550958862712455865278612499960774317687597684849702855025009235011906226659529424332481705714962998038084543751333298139394930875371269807183065349633046174796067674119696507664526767924605110783114261234458410721042138377824273521473385736596484217645283878684606152875781949460438654065593681279847294865007509330725383269651179836202883246699687835348233347957996864632512728975767386079706708395024504618268607399955661991125063273363993105132536880533119668359518019580768735168703206507126279359911685853078572519180887549886579811439140485851828565357137941999858360041931745630683329648826138431630742612122823113123325711419955572549832347437976793103182193075282519329089475240385492890198141914055526082667377623058504800802421733006502467765032992470052322348942757517123028358705643566345086020289623963604691134696544857793325191927598324160964760788900116359844666105387056751527204653500504785141131897116215302530673113383983219083982651272533674221347179933246582454507332025937493064935161138385562467115717788512796460054232738912105560302734375000 6856335740860139509670179278434392540159176776391388717167876183081815981029877985716320084087057704128898951789394534092899849266912634885477794764090901606788055420591182021029444303720732801914733038452511882748411367817425619668447327195602562218569973525450655829748978078696242294434387091167355172080317466227174825061785353109888049882525984786077129847817703066872858280493653108292774097095036668110578596332856580533609160679749453166756125622226086870025273740099596362389648803491663329966390231668711065339390746098722162170095666995156836791150971941976259468807488747009112073329729801271806321763163262021138071938946034467163033072646760553220542003925979534639227813330643221707254480629746312404660712885533584220742984888508582321566737723681873754259161701932978422708347559904518271078283278533428949662478227423688338604746510468362251411116639991640189453002702815765458194977787228417597007725093995442862354202601044153073695358338624595940112274628194988087437744562103638097477512739559239138108933196653486577548852562445268443073628190878869933215938930479371216267529260322052156257957078270230497602700799982876987030096746851407061008874972625870858234345575710828489558179532326679970072643400983116031865942871912157658378716387359678980436254098292869385903280042257251239739359361381670598119388965499713206224424279508389731348333667564076687739316184888593852519989013671875000000 -534508405001318296443189506057035574272907506659573590137132568839651542448184985790679351313027822260961874579446348190499866833782302854407392592728195352497042777205996738432796719879570759974778549500377526447394409699135644506926566273863503706410501244453498317751362685805725157289662499381199438714676402872019397760949846418401330680155791038691345311707990438883856672131389330177218826336459359923897450412184939232808073623275553012241907357345564360960027645718389705721057852243096180992852135597804546005256033897993199075524064256170240938772240076179750422576169670650916778986549786683669530364234211681149879351928269804577438320516969372432204311578494972294073886222615446410818508820065757149522134767770221957126630777280756182666200409854564279462305463208921883238930384905923484639872275094183859042315152134138609972950911839020441386972177437284141498290899188573383698927866611292222890697651081429670788556710001018870942939546449142748970277943742275877347358250391376037902863585557879381307000508098715804039288674299330162302600498758319436192735689724234251701346648366063423096489078385372604459612315386333435147662710188006216009408724385270628893242313653949630209690554683664920746249884962185023692775065427033363910152882433196978293890841645684108267428540386418566007996760513952338273414903951074510717604916397691188110552414384721298112879139807773754000663757324218750000 -48032891316198739180790035991210643076358353099393662083603468698457900281229940486525063697792312115639346665136276966211272474744886245540926189369420568791162252396537786111561071522965429927247757488206692898128226836488329545179330785826927720130245589313278648661412223672383445575277792958462079597732274385666501448363438817570328307453879892233725069396838480062166586936465748344987050097134406941655249374295122264258425421334039848824211601618933951694968552660251075387949737091755025510412594419300903557663070381097459146706286389598997754811963476034444664826378584894055104581846850031325060230166828714812384540383239512075619155251607680547961548751569188958213150527159257870461356867079626553799415523433615346845498307232811691114229659406008829512345983388461970452843396251190882964488203910329302720786157409396520456877549829789714131083447869645150452410850879220901591754047680769446160625497802115777670892260768219825412932969576802332033413200080531271491014203843378218224487458252276940269233599423236973045836455586500337730307464127816310370592160690423322905249864227013467561516916903275641685778509448531947311985682200336748709177843535598376525366427630902263297134966069337738426655606203920435598497254446715996810766971501343059218244797464708790470382964371773886528018307014512259131399427976729115421327651802094619320680996075317858995390452037099748849868774414062500000 34673377450469584847543650892333970070829128675979327546299884538045210481988874972216135227422280894506663720153385509975135614435552107433518873388670219869728054301581881842116603164353422848006139032004963612455001115007775948627455783531332068296378168630834649203903931396090151711307569185513439855339801084343439232309344353491089845807834690952350895155524834578499473781857214070792863882982758658175781168923467376303146343679769985009620710650030644445682281213971229322224339455251526226417497880075267983996214292296640403960153124978571738403149514502892978244537840008115197545876354530356510166404568509039267956868703414610159320202126179400614191853911274617049565432808608487087957416141737392327586194792345583546973352901922035982944267855591120370809263221425843245116685298300829805269874722054486061401713958612042424796909007306519318717493001911811458064532141932063665661398372054937874056718284225554249005632913996623213050853153057187480867361420605408759898811805939430584950360240263617011511355558992039445001035949563185446651940881993346000178190868137162357479319325167625285631995553717725211999935717605940775894131224760989303555082231368140444552593950725353445685686466474833594197977081751758654329881656521139043037188134381634108845839842190831529404037423263798874289786211169760696790716966158434541721757446502256406762262365937876662513872361159883439540863037109375000 -10321361606474848666400135204469982302181382942649193865825649784986687280381388230621093570688771012971269121052056030262949656717041568549459656693689044436663256278216430628605245954672765521214833733921986418845543527495226994630372074017189977820885472957062528644236346613220035929901273461146771497785398205241240860985630758754066716464030133131257522803608068564066686152824135573508099026577485882615885949116222644206592253630937240216964942503323315350137135444718773213279570090497297090632439923848791921658916313981759042142342352352349477715582571717722568272314068034556685624573492093102220604529859048646967065857809510211397412854487459400597882226818284325749640363362219381591547389887985167104083862746001248470815215949919818287806200306315529814044582268768573987584881778352007094254302125593783893096540951988872000883272693458917696066789488644427141031393819003169566699775652081709559958524164759440269969902627005169990993874638504812852092460874193280560687327651387174091115317704265434819970546809319214234694456993111234741602854144685115145449878410898819328934796701375427535480484092034117490459736354222066207634932747952008354656937126988657534895732866002583681534217262949019206235618772765413620629774270068249829934328542719696479184937002897826186800669423804121311956509535301020670308405707975974521699469228266327868175512155746176290449511725455522537231445312500000000 2383140686113668890427849438910844444680821797981016643367971703978734957578605955212508849359169632925331258016855666127405601370736624300572077824087944681417060379213342463949414665499649639661375331217529250378131934188150882716121083730387626987428607480120932108315578742921301625267129882037698473670288133488121839408768764405688755242134153967197747673329016808340458335673813054082807481660464625594638942102825589762572998198770708395647330460951942807737065890529596574469068983327746058046793138395282578250999659665789161189400551656645141637071989427125197865736552916319376455685004695876579706763279683646530078463597070838016631759191692712277978560953743700930464128609985474847667908316664795779389485794946846235526183110532866616812150147366626928324159400949222756551386269309249859714986025870149560697521724589575235728341991637037279368185170748330596664428840501631503307591269580980751886844378307301558676423089467248397990315685572538597787967678619551881256098195915258943683520878071815688705934589585730551280273832578784059076801091556903101719500887831932895287446012684012072480328436531497677112047835442391340292309929667832927583864309303395310742893148053716743085101739702803125727383751710719331055084042569610471928866619047846356046173928168037709682528784030265084317691850111620176189381971907329515793619675988008041651617513467797948578663635998964309692382812500000000 -472608224227012682930934584028605408801557872404050675510926042961583705007539313797788338701380316407576872055864701560966367883974698244514169921352629304475268491173443484327609445197327653196877864373367803605749057520866153370077464756215035264615074247379334105615369900561321936770867749289181822460316609202645534478339001191927603562358898320067547754811406390740983708059713236418578383369614422263505069614566936684405122994211941986003319138902431085325918398523910925048569740170768620443037361029906001632243999742561743233171054647642062958813322129943921649692290493500091202350092336417203966590291163780887378254799108038497133262162900799764325713150701039302178862862652998453510284098808986431689268712622457650736031896230781033925401595898832669875052983435051417645414818228477092632699414153702370494513297017292851911832258732987073081989685925067140730914448392234789359509839623851892369071724741784189736640888776184986946162426612104221791388127205352628692312428892253843185044676637819100336389429057244565433245545123755546720715758314306048850066084345802758720995084170302252808693212253679474014488933265667602968263879664235865423580164416649804347930809063597591724496338883382816458102867880171554719187048870816402416969999451827411876053432627709078736134690939554896762538435140676993103915280481576662231351919505748674710850915081650214233377482742071151733398437500000000 82627794826676816467830284008251001149930509021269377137810733703457165744661601741838906818872838128867218468588326601233689258365527023860547120771486962718205337231096368179419865900079472274738808157692409795802699642207150160254369435867164532516410752369117054692607678006594992669813884988202432684314690990083793017614011003271809637073346790752587863312489420167879322346976575339573773723411153346879686416072548290339205865254349431432563092565773265912914020575881498513394702199576384369670284896516253020964554584796923091525953525308051172886355748046442062149561089088604180548830776660190308976551676775066872180540158710530519350408288841596634068901530391302647504310450498038145772630017932719876118753648450950928178344257147482463938705438336961776402382824633392146343618306562743956744200313967694111598713378329032741677116786995539713293214829608485909714797879098152207222812207938800614096782867691722050665931860315589314445384682900876035936547685015988985819980123961284885217986708223567402416614561071126194683493652323276515416284657334453577241013372712393531911290101254656392024541498913110009491842279452944204938125644001433835554287362037989843207969737393037469962938558064149859427084391311386131985175716325754589490617459524412605813686459500340053937917152085617030950364305797271276884077790651895780224911008104529743995068750972432525259137037210166454315185546875000 -12637368956428496098441521226130938250335916745667731637141768602984345086376501596231561656847976529985310814816881912200758628156654375863343200109675092999708560213532470463271152148922038046845075679775940623995076992738559938003877288325248074610007383849323873228692020613854632460480805575693750477439828706854834931667840726589259748735025281409490697018563362981964826966459165714059915292836842156953208928030421909218342457110722135311069674099709160451639591375019717240130367465585133460775098380127634631566359220236669542269221707808299759113784490952600675658223600408663638641172834500327957944767411320990309346014448567891557143360269514876038968862444820913901482236583735688784689829046517041761508957748009868807655390250816459333147789564801151328367334821718043248492311687994895331498799288253926529179783605846067425797540122601660377398058137878280683668279238624241851237673285313632575960153978182556263825919188412616482247177037031403329640706594647451971512811617724556729402107724156530586421575711975958685230314586128644717122057682986794194652430514999545744983030954577648513499175258435742548843941701360959429735548548407052346991333135408455262680861136713837216783067404673470967098706370015585451792405204132952623218994616711434567247536349362897962514487524997015602706698869739469575878126563879211114610731613865234942561000669458692868829530198127031326293945312500000 1605216244511390105685759228731660900433500699890538424079691181323692622801079162594020945215281510355029157178016794812612084596466154712389790439701229270253183013129577481450810718835422465383758380302325038192223645994223834493171957492358362378128384024277562194654340212834946245718385425483368981768197101317256147424484335340038168151341510155843891541373617717691706021542072273989927896501222315468762070222721105184167188687992501057319474332855697754066630505504574000363188930690048001746041830416662479446215683044506773509811215700822381132805315427264603307356148767764498837922426333268994731416042724413017031730123969364787983224015042745205820718539693080199018167924636416848828092203462270311517389017738659104430755720400839986944507757371190322653874223384861132923421065863706734620058002972483440785867985104115358486157517562533030925407536253476551514253115965960083552981985522863835461256210927610648376910534515185123044355153915453877931378693349923495192283716333090122630390254163983033810620134642467757005098126219849107897542267960520251962505561135789668340511922968995099534047077443516226551902326525201134723595972507418843613676244160903462778909204279194669855863301841044706901538194156472689612343594522832616046692314225321893632662860085785843172304092301698136548468353992071638666603805582841159962520219172989544492236371753257628824940184131264686584472656250000 -137160719144886757963369367129805438309010674382901675149458251573325621786750113710645213829112417722724006219997707355228192282143322148597903425975616488411015032611701035963315115272180207568501627247126828527722963570750024328926043177865377099168085851508407726629682392282033081109388454419193592746950100490887569921821576730179868764362612312615473088915601903469011191486125861442594749562148941068347208556822315147818555093260132216767188487315358172384139618132269056948318107278881024167752144322705172966620137237116419162392018052769190247393296585370442022241512294217558269743409223685695643848572896577146492697933468484718966809822491310044417008215077181628424413643157712424951544786623431347083019687966939801398973872045277005087119134543204714235946553795985779059492948933010500335214543758933345272792439996425227440818397563700100030061571435888115863166399690555408499279094671458450631896108238853338050614623645373101965542427631233765897590347079181939867887640164773092203736469489718632984031781532371496598018184029953218433756458714081267710392179446358237012537907910720889028182020630233996877612641158012066603814332611537812369267963075375446908008384927521978875943776653955580062634591744621574820803369048475466033018715694776559215991556453342101291596543458132696494074916667451029049100338210455796135885104643779399736548685329040608849027194082736968994140625000000 -4503952910480453209465625636277293356938217902121698183849469427008633792726373636137389127810624072032943393958641150871116808142153189483622595928435798810162548355111304575963086607537672524023543951377948313389162768541300003339677552045086236455541168464360056994683800329522973637046611692762793189284554893712057955633470761369203904231781625798161693183756648424393295374139311442883013120683487882133128607766425576319327446856849761712403709247936293278507389054630289474184190785350536128069890546764861303725997387638357576997112315840478214195846157266848951686950263166952050323432934501396575684691794476258298175031393388345330709533409776712449034056571485936510140299486619425912582804405383029890020008425419870026782223492908437257881268931078980699258567388507066041829739876300275875398510376555674516523905705507415881461240902838377517441489802059903497017790903432748081026327636452673626911435591353805936851138666536157616161879580626176428618371533505607962243241234881003277260575338317173956273845426411067720245925637060166930605166844221850406782769848000486170002811953737749083646603597298106812337367017987174180310895073170745309302402413628595339124041428287065176230796693034849658528748443258684635759330186889526895593186606432165873524985004742821101885946440446444487512578398709479392428059252476040594466370681389298026467242486159392456102068535983562469482421875000 5700930080409432655883888245283456429478253601427945367271917985860613623654482638845964634049768452991927363674097459782069840080578660403841769614922884346485462261561558161602211610704120578173880198142614178833584370099413987024773757321371671889923224979200040506463429736052671675306250462047474511055929580153371064116559289395567846950924243802209874960877645533733440611652674875722233258542505853650959893583680741258994661281346944465386367463915079521923526669068176136331313881369082354333001987206305547744191834578236586958231993094657564434664237729637138446049182962699041313306886031169560584586350296096754392941209524711813909856316611645996739120631201319722633253495002712491590673410789444462361162879558479279684572314953215298630227807153360425243099419312330525327019968469327843400994016109927359125317326037875469673132170267735926476418741580524533625953525103048857936780287821092116829078107535378637117777154446095017407334074661524832794596601980999601581318452875350561375693073714631676258588335308956117910220011170009486455907978844951758127103846318429296861531274297007215361366674868937099139063808408085028923421312623170101225796172464283696553713665761047795892284218442725321355741100892606361748796345676208121867427751136583591369712813745196890666642244150158969600908955251853164037739817008703411041355647186099975861489630446499177196528762578964233398437500000 -1729122280809684449878563570448937991550053958651343871711871785488700559949719649617634848688429384366559180902204058034440527854560980461666526470390260485154660471145619404776803921718097550527052903274528322183307653015118481730415292547416471080929519338473750723300882161970918594762017063496582248072072317376658595635991993572633942974730808140285514357440733626423449302646333382080431727639461590179580020619655582067215922740773780537981150336455815876678844652622602764093671725009006274989317401762335945753760126855248852747073941795469263601917139165321989091065106832219928771431036843884366483474463556985467220851231132805885692485272858234953231543123521450397463555497898193357243945457379788355973116693355025678334006858773412820682999665101681651171807561476018365785861820288026897585689689043116624860142184439913718949269338486550746384920182198371837022755467459134247899349791003497646841614291842960944852988195904975897815347861835323128026482821777348451907113814351520996302415739554758789205738468025655825004917019191264315609232630581407167229950082113083345943376569651034931071687684885870692750988859339426800927853282876784448560057019727566392928664534238283313856844581052775563782369669223125409937780517360809530536698112711594566132754664464476384328644089134193831299682305912469535048733004337223952771000870140652742532050289980816160095855593681335449218750000000 391305701828087350971927380753032718630219365436145951202412373947456799210783850872468481822715944284231369620121471974042197066954700320686804073750295140911376159271587861588602592110761919694982174422893860762683543109202764125703958656827767589700799044956029759482411777421345265562221019550139132354062296348843798898886363078137453002487281152220375063481882605850569966846016571181479737910518575989828775674681651008528457159247624027529401539809054622757620690700914515344055806455788461885352877149167040285014617915831548525894643355204372664868208580796253011555002972653214924871035170853800098160614369330913835151273136411289456557720846265803613655740590998390278409168571731403758589388281257686565170325176562252947776250427046486006823558164954780422989932916647610800764923343406472113782447049390314239551684014198657209530645888662733727796343459344622252688536429655472006829368770107170496252398990124259159132346045543418819872971688376905196773754620810779599084164771030173232275819204961180909503564240292456971299095538336535260944018864694286585096369288879499952311060924624710315844737861069616409998265433016941545995311440039799514170134645419059350482452309990531986774570208881626299051819477156303890262624180220563976066554501694671944984736877576723852514022878075047081689505884072769032886845470678062956130478637955182833613188009280747792217880487442016601562500000 -75198325642922504209011092995494444445949620866105867066136716929399657915872795206598600172465131408247919199280394688207431758298211041252969601345062142470676829387775665100078992138655822061886889703617410959816030117270765713979853293843155701658740806976435015934669289633625617488459800441634546648989870410985551652935122569022551607934427014871279855547470251834561899840130015826998006019474688520867086926813387994631990555478402561663122042522113181276009271639536626760440203721576576906954257883226595989046800478578114862246541360688356933432156599383419880532862042014339223808525881745965027899078615483843611797228926581981865240945224616933854041081184901783242804001818553007732875829351347578825512811340810278410339050337398867164930322984767249426077039178960487193252553839033323180915032268692192966353702957682109863381649071444280187807787379660010394639977020146491907984912272339169385158789998966399610090570535488845148233545503908921571268492697333153804842349903817776276095265311559675300272729097170383777781979750785581632394542415489426275658364495391833287438407661674899581201494008127613540878312179956859200621041220056884518596057760656720893338288149178294378380624223062454500832394897766627459139190261312176466024918306805546744751744573197953367762937281224926630103329774934402132205173131912683453785921654697094900811349393876525937230326235294342041015625000 12685071665793899651857341885546000938505983016837242508162143944561794418059740024399433942675943484610481319846006777411611186094888722334158933897914402544096421238184567194774061052625918471116727826655938564821574834722706811135948141518868373603078125896772710998965372950879277064943306357690941643886811686704936227531480489985843851839435113817419803124652132749665778664355659181948661601895294458786290007752108562445307848321088045307675563124759075741887253623363965204424472683156731095961529565415884977436461482620731259851327312242874008693995719593495844427765378677520131537638077040498552147689666305945718097600229423742599073307436032649345446757352108371573727399087152438363213622918913224835381710947200279665476269200418655687663676774541162848326504259099195418702635413068326009869306157625074668499141294045850016727712252240554809520787057029769026608352904558927720103388733179892405435147505173158192570643724729110809854986437397968835594836889977800351068728819797161161928594369382935537418070127980467181153303190231852157231498146062442714698848413627244501250296388659661920969831380713611208184145123717913859037322896536204697485430129156462205556151201309597740469063070807725086215454564229501580209877669808480680919197453136174725422614983708926634554330488902994343862598193286624404816525164940347285383592352439141408282363698845074395649135112762451171875000000 -1870329835751657630673734291468283612122618619115666094268385819564167725652209685238577048715833161783959221618045769100216553595729084225504945992697982555798715492364560473040750787807524545068405393159082186775866578114855022671354881960967873578230915664350174462537894838831616915493822329411222477406509479451092045315096787143879693759907201946748133845873155323998620947803817696423217218325968217158387672147129761851443246693952830056803611719212406393905085152877746907740996573705991091084899358431261663333110852472491278738771997474975995588149013276103043564858507722158679129402307318354497850743809445389317037660401532870645881073859974427931657002800247757435722133109001530131954484254758248543615826822254076169088927636868751398249971765745539368489931677190780010572817693788666973788590332399154693035371211085365581623947717504300997684854923895438002510415975741948790888893845043568753596553985369171867104983088991614356751066168714362116886582906868303245409771497786962136862723291412281761934354604281564954159796025030226213019458080578435585413279288056426302856729949765778704549792038546611414882369798074305849156808536872214392377126254504106897062386005742334224752930704405075555782003203056083734794104844214252879537472776664854460235589909102743589421139154251217602090570333026776298127600795865176623177147362349148152285693846863523503998294472694396972656250000 229824240260307702090409937200882760563318924317380437636755893357852430794093946456063689462520335491529235517454924950736394653547323403918976453011984680716400170395881519242700924910206169698461242029633309628991558152684255622713820665600552763484659668781379181386868760401968443268301624283194566148152899433897061716173226168429793151298709095359554333904111070085289021906195581537622561211701999234210226177876767757730744783568819449496964913208975088835660762455800908043757956928474615800873739754487119733560267792791583288245906301984356292405330379908521041092251940339244212288897538671553751321128691584066463533779753392488891286107913600542334156861901835852594019776489243596997512922005049125421241184946404469551193791385343886486304199063201838452504800161381467688462169494011587119150185307222744315488514983210090055169423145998012239925552801172707724145789555033903012111725869948803600944739300284765823642223424304545985323046675758437660905005225832540446047620010028075448892216826441954757726343569852038402844658410682391623439090819362573288569590647157440520790927892712448724355352389216706635439171903627695488316294973934152755824708120191003367388587364258352165216959428500384359896580899792545780203190789079024142946472642008640634508818079712262515913637425999960346696799640894988472149443262888086728390590485085562960643201790844614151865243911743164062500000 -19404498213792947653231528752791551939058280684023033692103345233122796542424870318353727173197269173099219332909595227523330852229816516929861906074948370980130267941435034140075298317541239169859091910807768771082552936761189835769059795482899210362948222775329269461894677446350601441265595681305322898991039895242061787494030425781893735571096305517248081113335202673520516473575365572363151543814233211066113946315575189703193381858965535507287142516058809230871252252789517716613329270941189206543694938130756661304199695948348088535279508411927428916075325533732296484839215386854651637689294433940111370693335496145361875145151393861543858302656027796673998148759558021480121334144784313362654203309836708801363065879912319676751201012153639035590920060077620959701259487832847157842578923998241197346790685130876112703655411392714759853564559269804089356272013466018320061766609778376830859497877165335227764445474075494148926827343017776865204468982075717245195316604789496858680322091333742138896905746770867608834324819231844422939256073615551762312187313886739888003954188489420316870703241279152910524191737303934574688436914215017950570502972042580285255795416109620152964454496913240270788351664279050217028897447859724060500811082200066721923531511679546428650339929415481073096482102768900793449685386221881325329919724024674696140495651751497162285087227928670472465455532073974609375000 -386934213917037745209469763542387641003736571516992612417690803567668225859179579858010046103415828631405713691993788705072403374114564830650343575214631273510043556612512665346476513871783666057195732420804736323686537587923358636730804206035042319696076191191930379174282495297568866517955608570979889080868227663575251719003341366813909862474731278925200862203689867889867592311682701687404497405033283963171401340801125413157105415506431910357362392527181827803343409012406394308443221463931858594695131370215338533776437205638232791196589422371273434757825593911188876802277701675853440166723117553185427370121337580319526910466823226095436666463117947327964218211657248252163019203633571662791506405366573832094590759702426068063494761812455791708964570874236486686176569858407907192494862681188261407648150106373288413254715827557196862286650323207685493491028848601131083873592204773797223933746936213614192964737472973678376983082668782562226685771643670900368478525722104140735214725236713366421748945853652460552879562426021362388455555590429448669526383119335544726065113042168209079206833584946935912337133996159750048451507162480502626411223731589834306966070265438783959268019326685602670980357683949683073057080923188680281273855868135847368555402434888605651144276751103684453409581827819633032437717956628015956885894619701771115264602330513499239827979181427508592605590820312500000000 667318692632201181420705355514339448104611960869585479659135364678592942873808945637313891668550907103871745184649185202091418762213502287671913369290331505016169729046992511745194135886406118038418708633353478320106552212549276727604367953932036849880989859715907250417582644270920954018901178626527505712820558137085432742633769954213207577812158848762857326967118503684581931991959125421241523025940565374814967130748580532592160110854384761086516086543250859608905180966961932023608626462400377129476682465667528847955891509623371155769378683636292497867789061229094273389905745880161319818204059930808268927311326359652779436185268977552943711836479959153542156886546684687550140374264530871184110605322443922561137225741762273816973537838069317466976690946007306558607399789402769528365060335318123163172300962766505801148899456473778910184790599475519711292045270515034173401582807007046250760257178504332497760834482895218270271464844556535084317387617073860009823389051795610896781766611459429390578617636965007506049943058157760785698101303944187216217499767902795465827757813796488198380832580762721497036660884856158914265335086933486965088437144781887753890958409409847126858431074280248897083901521010958557678809864304426133003344850089343043249789068413227423663499531679524387913255713424794039351482110781275167885909636058897226012077801005073496298791724257171154022216796875000000000 -198419641466946863444953753450439920383529875089735633756763879648168709901107422144160159643526541741440427200344742928431809740562945550303381969444449890297841318426050167440467436206730984971553621797844021916692339827768377911367157558225247182683437128654108305794004446395345795196762309624059216339031907841307103013850218610997150155293483285228938822302153658336018948909688553508263390942901929189825399203310802785318009954735922786985776495291539713525950779434958881379264611995653649958798727277826198528421087657146410192283615625223903269677874029850621402322569600155080542799727920129002190836593493345465321958098514722892428732702380226417585977047647469883274072801409991992820198380233744864697833955805896777754593349794953635198401210177426052883540501905128521190681543570517642253471212698179114730796874104699904185791345752050535210925221972126916896167212591349751920540580802223190665962663875097298238834913595590090705460470160904521968923439647350211997477463292440755591363884936302159201982184465264290048973660247720457920207344663485988182259390222474397786808012540068454995052953590718822179085937368453830841365613492626786171728293176909953487679081853847912613634311132012136285072917077404089697360291189331052313218590192446250708648723880329391086614962745050937053477524255064542514671592645855351490323927130671188834298845904413610696792602539062500000000 43548412944719101766421181285347095988077705663499872957130940041809458898194327273185090532796510497562864938611972372951989087387526857896923014364266817876610370804046435513941763872226953140928402578351411064882591562703636570156588042836124736991394172111632531860290201134587893288208371547933581756702526695008059532596924283239438220673221915867098671270011506552818736866016878821282769401819524240512190815667575400733823614132037433446790890783642016056529693477192501739739644241331578779159514458146477665254519059578363001047461816818112879530400775999634507172872160396734981235990013378761295276184423961829374190835521476538337768387145068193311847205354608210165649401120939360358612214064236740018862574511561050158806689454113816096838309136489924491095900631760405327102771048846332331180833567091077584073430412601182996914622772378413714401520667775090591627750484086002766139821958721614251652484834438009605049125378539134819931176535525493879319440562029297256172556062254872886390271329439087824367419135246989033577050238795837536811463181236775483473185654010349093339403751706208325858467128025152763151618140968686172320821758464392646149623133838042499602575614860276037149067193233715259521039208202322885768921383182360065757611953612728191620419556067159140581496027897818962634185382831184900531722174757417579079329221039573218077212146681631566025316715240478515625 -8124331584205206207383075125938758686842640848350293592685400804713979160181159492713133486887355635928409570385751504081211493387644003842825989674362550989474079359701326581283421428133102712300970204666995477282988118258809362091813084193983444892418782948083838325603006302103162233307307366925657846804304105938131095916158901891840577010908996502301520655384611693935751481080470948322678991844215601198976206558935117412703880567864811165868684304961129753701760510791543293971788979404047564205240581503624226129151685058597040830097860189589286519960300585737890140962603326911006858757340692472185387719937827488732519650207721550486520546914231008875335790406150726417485874129188253580700761674636585315774457492021300639827311448135314623162344081879301041898691639277944324006079450278993115735446992080717994810728762836976146351014516586894018939306172187396629824041863187324000079230535293468042730148345360670203904955108639420184206586042371432299016309557081713566346683293518254760008298055540639304820467829993590421528276196797799655923936812701840226202773721338548405752837109854473906331168597145883060983148665992163580082953520714830809004067089765882045488777867023493519694859703100580857761057618440590073059308873082549929681755634923500168508887061510751254115107145279384458776640040281249279148685419980214944999545349996802195979839211759099271148443222045898437500 1339697004778058101513123980850106113152820573664726007671075242556069638478062754121993062830038448468718019040050373907598459346315646560160986085175675400972690226655559380525295857861621604457288549490861811263873371583747320035641910561421472888870353500967195859236051853413555970098860820108021369713532712581885250550264231140201420956445100766257453020169738008560682329069026770805385606236198708832132590138047987516616393337078711363526464003641843045912587663778995990579520920943883516163319437056478437340870986209618871523729381309181326435787064957702391338504227438295668198422528175263417261723327430756697238872299051342736286489956956250656246270564229435609455190568384317675283077640743531711138431962182249334284104410414314539657803240845632482749623694041743529276368519336331131166755349293588776981600802640285184449057393550505833662944556763970568464908691857010333545734265494311078764303248091332129471054243798268502853704835423282404140448950462800784306585093941246842810852669534697482848644371478555427573086847859784661170942300617702665834620786283119848176474730504069899761505341078386150433529279234236925175880660837930182386592015954972235267670450648066272337651115919538112905788529769850023822989840463072770730399259611947604672225082965632540557374628184749800699994647576712859394849189953382737149041109358344955881925386620423523709177970886230468750 -196181596831302251416629456127078879703166461560413729985715414986296098648411490241261502995953475679669887865573572587633678978671233820442038359736994687466391904612483770708364078328735649373214951108866731631719056108792579120218517218645233480329298823558206252940039664963065089471754655747861497823810035349623637695046281213719517239167084741414075948352197553273449552844938195029201588952857427890849898060077829323150915612747213279797834821281304219085432936801153981033085211582846925114474741314046529781319065454643661998571874579951264634200929545023057852106273223812004440554525729416562465956620345697719564666613130292284717864950007732966729727343599721614529416590186955487767659923032539361114552793452401765378757721823440953972230550371393493355597756269379572378805782325780590442351443969859092024048303233709758933419004184537220717812562441998581238456196594884889019152543361100595285932818407786625953646424028045405040297604484404909402192496984025929605313936785278505036236962757693734381839421752558928506363472300469260413366256335237282331656738019978335297178714845494121501112191549347068039618625071341913992833964694689978302106054385278645287713157556320809685150138956435653961754594469375717897531094125848334734339179312182139634808149077532979959191626797015547811423649490119865885121088807281780690555740326481981572470658647944219410419464111328125000 24909077305577012986609039198477746958284057970361668030552086201672907893036164916782485777695453831921771085893585345005200201109049136123979753002187529575047213681008673599704403210329292586294722447939448266671626862134854871866104534079520496749135292870526749391028761264023297119649596567069136108753622873516784666993035127876291221916189456277132591648133857962001167632922403914609639437288212239259006336571917129752807244286362607651420717212260076182887181957470477413038852672540518646096060595191136509921368245609746080919234655542650448341518428590827407819660511259269655795310439507133413711715316046547394084219622574178235337620935176304881001028027817838067067616207705714821857815478162939661244699164036247197481983516678179925311638861553418694835080304815942563558562769199685260104537216066887500863862749187895258577374102277504345504158105618179610448203740303492598701085869556973032633380561202192320903062453904488059550008769940673081965570001044567164354153573704314872624990909840757360209076766605218212483871554525390793380165170190234990990890911636250745900382676362257973938295140665587050604016712939990520611797426988409047113874627854417465054486619616534359455388602283830554222197755135562501432040487061486708858756565150013211191583253798211482177237062592609446530026896948762474143848133301815498496072030765700888732538942349492572247982025146484375 -2512141999124720041842014750094331495313968916561042683128935405680892040734889329226461022503572059380886997710881578167285022143791176774895425709842209523553653808692942674294563939579963572736134385445141507714966974331980339073283925140455316064863902874505133136617186685771271610237136715236657288148486488115628548448778040219077036538215950309540858625928102334738400732533840547647746964130386662344234927796609350820000963808606257167999087871970396233574701452908807379294055135784017135690240841339095755035477290169778761977819139207752587066551126333812466286510082329805464353592106594677467784231704885770120896827901109567590045830886305669468251736218453294661122274075086957094667872993568943724146660895085112304077096468548250630394086553565620152912250681864748925639967832021035842061737183967197503970864797500813461438933363886728188540253489566415054841932863621494130352600548848547420640303724034823328370587347951747288359224278152278265574131009491353117577982237848972399543371869897750818770560090185968227063623691176568323354678050561909652566531946835709721278170514477384632583169342671875962476653446967678639431833387062596745343186903846768151748049305529127904603381454977470019238175393905507293164544298961740851503790090250469087125885336008948545572601396374024087027199685753663866212670115446538183516131078395344777831610372231807559728622436523437500 127575472509096642933380479206255310716113761809518041724063036264738277492129379012901706320598458571273403959620353312724865076988085498908712360762646539757003539077452235119621048204576714281620063079978424359140839544219031150496463650082135717230927543058309424820451185060807613514908159121186575591772612905550877938535028766913318598433018625885911074608866699281595650246786950826405685110006533006275626284456020355180694403468204568659921355623430662745518636800476723518146308149517968678413611311518076117503106990338320026413156003355980095910439344820614354400884796339363458636980114817983032628250381378560793847458213781284724039955570726929994965211728230007486435112068467802687098368455138443733688045986129445734183106281904078070746210876817838013561728678297832239325605304061133967687809902482371239268373881760751594854992790634116358676170671173524092750956823702236800599812803337808439565062728921259575036621985587453067542366243932797699998234473427299350394448777487554587534881385133188141817161510715351445484293089688253992875953884339950081166187559947847504876438244631174217034347168201971380972519874767679404525662207364604773907488593185385861539960532184175975851348697741757868926057662516137699580160753265604263698336675450004143894261378747486279865642696035382754895343164795890090172827916531896635834834874412280214528436772525310516357421875000000 24072285674723717615669978224647269432125996583843120167960202331563992287037575533901588151433961965366907999833250091769675119564475191877009078541686564668580843480597174091534875750783159645433872225176025571033362653627298777117442764649243838026930727316634754038195312758926761383060509035543942713849029333630378575501668018568349401140380662926804562906656074264112322380305698661925023675278434524555726185485369951227088880354059497835993345436187951142752166953776920426936526302190928871150480388056268616458865341557390719850103461515082971114198793207408759134755142176300780635265730408621155042006314467844710399776709592265873335576241535852146525792874627163304616407011324751982683199842425310932017031525685448672297286944491941758435084367438499950355025583303707209515474674365024837058973750713342029348420263369662809097244054277926903357384744231476820587706971099606593198853019993117435765573936210553214326121393871033946069779504528532760711734298846293701013251039123947263195026991792916970791783454201052139582895924402805521658922406041536557651554134364635619733127831888707534259602383354902676012845052846249530738557606675317947637760093041857128983361026346439537441193804062447557451108083979449449653063233710047528717476832668624421782441370143550325776205964779983788818358531530267113062709687803420323467683186041687903866659326013177633285522460937500 -10185825122799973510594264129625921707001238347115717729287077106884079313622013644500706920789015702769276490626084635951285927733725008810474131815109266615249652494813826938414240485774522673739845869207407468007496548777489804288824896871457463745400538614878363485072111488036211430952781665364426057407675299719454543473890403948350361971276416144771184033389578957448778048946509245179751978249338967215535499332044308850723869870471845495889993937055771675985619497223592986530826622242186186838792439676207332449264067715437959106454815111003735912053292401850550092815248277452132748762320453133811548238721446474238341444540726953798029272364238105826543010029279933826117827513027000791546349485923554832629438022238151956881727529710336200367308634101047463690352488482559359385604687804284707727465310537532652644811755762757697011247937347368083573401955779325160611623091977276509414536092378611959894502530802876788280497092831326369779015518658045551307514896934477725292947069421493304557123207267289100212054720540724311693143654614550897751271189087128789111261679713205382792582323489680223594012081087414529127346215683897855414974924725230939146258418067656079629323535116000509843885887530843310945642539457820110825381766650592159773366375939948675674746912388076764581902442149493096829092264247935822842954535236850785346552554326560180442129421862773597240447998046875 2406273021559847409524517715904986074833125690530500349667478118751950501328065218206803518969575549962065884171054585132942314084776226876771179083767655102656975474449435321263550113457369140334790675500835003551236982506856216644780020691192370710009221413745761135224290241080604823521746649033282946106977867278236190325599728211436830098604229402923568521333750248657306859634017871121190776980013151345305033151991972678215481751740198935077586256277565767298804412131039707642881416226808580292995008566417933916944291556601628358815861948779247175437781174028043349247364277924556400205537916305464218112354827861969229034172705922552365284706474640269594937078080571472595554496238092914288724354154700742103876949170253986365527781815939306684656456653186286722851659544568990997289844622107712673170355566015635217715898089765995463973406632822139116000461782016561798900590304491797518540748212966523268621704757347135509699954685614818360593743178200422441421357587702771131395610638521351186793498989237653167555393920757741020371889637311660008043159083352566450569536883368932737219925778343872640755215142017139189087132557300796268024496011938382362158018371629502837111341930229898731100624309056576949854408652454679400608381950101045469157638650106444467067585013963115936163978443446384589790498283042738665703495833498125667008170347482831630259170196950435638427734375000 -459568235929181698494536496657186659987426056163563884962421369415719955797599912502542986576966395257532124838622335755919778825857985354257445320319865626797523144369366204686127721910206508907804678676475271624177122362566283803018374041760454976357655603405944459044920933361716176369854523441467867025965753557059084350976063301442941373003688959259646997817575915918234303393880212691426870374227115769561920225829852794700743247861915348293387664693871753743270440695251071391654607381286271546362188260928336863383650507727151182496819016628299497112765347381842944285034660977313982340670396013285406897471553234458667656855053072878702339811621610538298278460603054893275867592973961668453696895605777984336369124231972311978940208329614947984430413980092897831911085232183706127933922507723418817255262901584895275284331682471763095416907215871579277959746055711059122971005414650587271666875684088383106552900939395794512804977607265957584335389686473523820562156522075214041838606980702261995118412015385927616190344749714227700230222065724238926911205564720952728214076122506032945669441187907025060575883238944961767694611817237749123184582163274207930796926903436308950705517466445227619887279547398813174411981533413963863568446083948051085612019594968868884223391811516619328400155280491475640381476767636836076601176178041829053724396866864587707368627889081835746765136718750 76967938813203593329822452158269136659614528752300042370532222778648133281554872335028388672853483352568420103160173479445437988626016867805624853918901578258622752092550964244795226550643043312255601316798550284749279949610832593074325995281292536147779704031961777314223524033079264817899848509153697909622353362680513525212769019493231199817341307259004710438770401589415542451776581902456191063403986314284889037345572567499841513061535540433407983457900385891085674519692131704605771905833099520260015505102669636941541246014039556852562707540559982126183791832335467429678040848194531114747367765740927040725239259145772350773613174177208609214646056101989893846094897882232130865548735098943717863030042208037518758580467388140462712549445674763173080314721034499690423562166385182562575461587696471589503216450891347123590937652057060623502446010671757945576495166767017532413375469553049524157803507119306943531208774426003177713885179756469247743414676760870278912049605012222938933838430290588694058052306098401124508149855002238381650941000344780827707382330496621275227143102077412269581873079472235915753200141488781983288172286770914481923520597128328893020621201674667879096315635147468856885452466662261566033262126601371990623790085628997874190711291839416772244016492023777818413873283840486328584714403485756115325184993403036498148955812936833353887777775526046752929687500 -11588848574697761162964620838103838137563638037244779595658797072775777115287223685253976706913011268270802158868852630343861097070421362953484785361268607485953783851082018323566289202883766534094201429667634842067395046382330997223464149689044867583816161525432459486217135408268043882142257830864538588239054660985980414000338760766604469443117726321786302744863004290379708623245622580379709883930773188190633413854434195721371934624755539392780328542600924175052008631894949260525721563799392693003789791282017691621764875999813859000149022945464223232510797848415470558570655127188210380528857306271195257597955880425751990817220285105453282548224502257550815899873831167649185976500361280163238782661003753488784214335918246792390080527637165961445261331227709482175191718768161455328006515325245809080295672581323042371495732034478727705769077304349881187148200710571496310440003807715938681252720875710733015344225572702059706563594454480946958221035226105220942687298279561944339285549813376539788726777712001884626544827862330790439574225029739481066281611287962743692316852968260625132065518089399507352744834047238979387079434525977365754942409141563914304650683368108115820992417697496585719464573258426250321223362899949723292684363757065648707342444509000018631796334760195591829503656767198136282332180125845664050430348465122253230554123792916954016618547029793262481689453125 1577172188371708188729561711976902295201037413118676106740832068289314939861149371333200121035715278158414016834908815555727523770325556476946585252534769356956919420132605959509753143274045714798126532166035393937037275313251175959139917984253059525025883220247371688190056081162335351385539861942558238738090692314113312205422877620781219368801777722592456939436358394814383247860322187716957314170358895034208284943989078253754927113226171446166358114387299100651274599267263429823128530384866971780171754139941937521994129342327392013398780572873913579359019225037596881007289932417642281711705468905716868536306250269243483612119289651897666592793837808413462677875645912282974516887530185374635591238941454311448939499788991549932529681386860440800763982843669677151094037898737706325350934096329915480132669733299101786105396639878704251359022729462918243235552909946933515438130602344545794038085253761836236052236682894725375387062942771162250519541620018111280970262479060638090737766995198092520210110159571293680553096106621114643833432311273924559284744987761096269480490109937388467521211282428080069400975417274446295432866318179782774707309405771402124329478152336337166866398632780813038294001905231018757320643559901199782090443178078333689250459452599965768589257948603027280090260934122111812211784862220863498215201470241376112413345111917806207202374935150146484375000000 -190691125997169226120206983959294565283896006084189957917964277491183729042803209795839117910855847413990214607345330795469233294202678572656693841087325566062364414987312700476944446037909623427138823476428805277188530973494148847934383719922421408487532783546695081907183522180075056119109754239326291555880873347183702068827685111816767180640186183656472181279840657460521430200788756557389154229104067100520841659936755829740027780860471079067760662856390220162493357625337184268585454361568392900715418456985533099276511179393788157311879624180260977267455505527766399507760311962731583396052080787079850902024564194698991906708956975090989520831154303163441570607977086280202281471086809096052836323901921969045502164659098959300743893578313956949866054491063828987898034003776807614597808459297178460355644073889888308625954712250199193637468741206663742507151742772626745184011445554622083522725634052815425984670604226457817262018516736836800165044896481213674413027272983153847933052808753196796151624658230603396103642849027084105280239004478813726838776834287607170636565582901648364819846784968923895956390007668780692603362174152019965944168091606144712240725014024565918321516457081124068243408548555178284118218270408821415365949131370405477795021386339293369624126945915691795279502728667113330411969358939022751763229614420565045246336310924561985302716493606567382812500000 19537873535631792410314204986457717843170168447386308066468590096748716371399873856731634404955804999618179586054175759768673330798142397825686811654551318574431582262059695967307808942114331326142749328528208151381408075529976024325206776680614170586476470456216765401336895825042916227892480828502800901987233980390543353369668021598975987235200228092423028801351853464867679887844587629447117427431767572453578606162340522949026709232609580985855246665949155188474878112449280949863565169925807362512899211034060239373646651575457642881368160634035353631869710052975590980602282041288664237670926560710096675509337539022148414159975338017316937305952535744434446803604001551042107898494314638172876805555583259386605868465354788456405989013340252155991012901698776876530263709368158287505553640730926126721691525705183875633623692013289931157756331650401994480916047084462419627692231369682012170852358924913490739430384021277155841836697243871211170568743144340683606768354232220758013976253590687704966498172218702725003940870055804261699453745618171103351263812025753347024207278670468979992910496658555640130157371769415592595959210881956422120240885183680245568686027143431422495444683021186783850111529915917843368581256022243729358208899607196009135989547639816169356805295814265345892008722605329354325318376840745791975938975499672324576128090711790719069540500640869140625000000 -1407821491901066049631292431821141320005282495810661770884461667059883747716675566410099361084805699556977079158202145818092481234124709103916785057878738925045249897942969267360554401985862600113822078945703340782396853223581743203917699533184879197893267680041378436002849095849968164261702903192447026230943231267788426256094518986716651695285066888181857583848621107476212079503443080114542150876157274144659675695151416329814592526864853999772119763658381023587507246887141816567313488682120381741136561355096042699662848088758111597086737658039709109465920462544563962265787004473073591201800846867560936826830215597172822780915339605760492504866836707165746737273930646176438492384222694998696178138195738271863247080413174970156086489756767901544948843247621979046327684820146195817940586941766698061230130187884599450984965048716015556973360566163498161784557898953967690444022884736010335667204342878267967300653372665450301488662756456270249922346506399584487674416972350110825102740926332809928426827585741124922939682765663107357860780574711452948826998679225891068504891336162715591402649042315090896940470197682226717022674252781433955718672683939792640498747009893718552911941867391732495116028829561931081584231919618620155922232111381542621308630868501668234971973999642086610749812930707906309870256982057359667064827252770992560733376297577024161000736057758331298828125 -11912038824642682459899250362163543807482764498291165210532084840626838874436058769056254739975949567836746460712642438223642372684520163333976473779226659204176212806131854485857299594842866196886664276593278330938223784862934567628209288354532682804483461530466104519576251473818061602645318722986332221336581652099304534121740831926000909031809595322947998389207856801335424042346939357702175480103897278053096479577536879683864283213098445010425815560378518570019806428919696246325280801790205633766825886250298239859522688269029976494445772159919703591759149099189444658960017718042200578382623609207538862337161260699893410034126357579014503911002163585719082375021599739425844240285822675386155106722065840585017002461388585115597249930509934579824070337269042137899266098583613483919364554194881604703506152296896059855893084074229604177158584518091732480562920417219183803776565821096247418835303596900526091994379390138869649107211305364913165593148102477015425388959175519036762201637476728214297295044155171776930362072326391273201227612649273524313982627296661680911185375507716936471349003893012012422844736308641022840977397323724150182512460332396535704581362864891208103460425294716133568172768686494629045520245484204128558502369998315666822419419943127298772470861023332180801121900035866782595004988257662092106830259176906711832133467510175250936299562454223632812500 31510674505392337610702680694356769206072247939078001735050239825829408114240464586796144447404924336657414007408816326976535124018749175424731242215329527944566726967103302244542052094873588844196242380564790363232995988555790120061559993209618416659341066283527932034625186274823872211944153636716190020884840128998400652156821943992446298509163082395433415626335818011983041873535800453653889103800901736041576398898926878724052379788799717439784106810406003601180801941931704834979253776657656179809749888374027188618884584816031778606467089241743172312813011753131446225436628411324941283894832743409425121464216928084351631411219335279170087564378218858330347171706889898785545176381566207472187100150001340197672249275552313791663010530549102492774421391933270755976395682611192826081075077700034714734744161405620075636906618810002142676217116881479579798507810580272278499377864387090644841768481173341189614218788029380925358357880760055486804364957599595991970493296792300732180561286543444019515195737373101271868361011458341622948826269798525509406171461308444626169086579800395807265070258512407667244114459166937780055095697073739458564861342515854598196500435627073723170585520699825655446951432900143357364005858773533622383348136736958778577756060765248569454553675024723012576160525343646753567707529201136394565740700592630001500293879246328287990763783454895019531250 -8140747562033940157815831681848128915587714166460456890442953070391209084648548821560280428913681950458884305670012861730698052319757745427937655514514174494660763554785009283646213723834070839419071903738692616812046703788327043777562723623523225340100028687271527219917506785760739501986085351109096629721981817459886536572551805613246318732475657114627704142363974531142381367655905844652748732838667923310980281952435784546686407277691550311396370243304496538881983251329488001256897259419797087433052793291100147408790279266701048847529242914467724100854568616171595106197938403845124939847409991378369167294736585638642561983589124080081651516174932278272663489870318168502211346942363104040735747063746529027148412340215816229980470042512042071107428895219607646056660935620681976167373376111872031150515389444932724565050300652330804334069482564031749995415483141139426737180481963900046310623217960867827130482447779623394994854998070533455992435175314953102102968679777436019018942450571086150826667232307407404203967454702750342300819891342276975480743028216052428313454454262652918785449705328122574023740706720316722356529586982613887575378030072442743738152791580740123134772628932992777475797004390922556403441477256984077383440420124560386336448473190851211774454035595784834388372099498790772202856881503592822704125077666451916480472306147930794395506381988525390625000 1574393233209843168158828881402263732409793563962001554257732179191945417029721887275106001604281065883332256871146367901977397764733610555220965224660362553440844839939670520075987593034670889919855693957871165585783320845062187816065322209535615564216863334633255857197280584299233417805457903472799054343205069878007265211085272499559721210544047981795815621829085919780080519556691964395903776905825079641264290544152762341015748885760239077232491965243398640245235826668466859330624436559876471205484072698973442685224488370582939544658395166531884887402810377454853090502925912719396983696580514087329228841406905415334467530697421069477464708308060270663744962039610667311471855061161913405833965877643273064703303915696293907589825736759520668923635115182443886488662513613885159564613293610470761948015381043682262381309586491755379416550533222217489890552860902158820888036785436797842632824399690708162905263178179700022900527549090784023763918093978598297886610411045594349342800446579756159407446075435230264108201480701256246443650893557122876124684249576261224410094482523020873708345403136717520390512784268134785074694094825043341018149113289925357116742164023932951069498011731538939293936811352669148666000046839824984402743252339477059352648583260759850233872845270064688359055424059311289999870865903343803817556009548206852506624375820365457911975681781768798828125 -261185903752373146089951431398816601051674625784026851070528393445088207410542618365029830835559684079482570727124764422509534112681796959767102496370421588224477927098567107736109966231651413631388581466701112878551395332932453975806825396542290641978403368086599989019366162524297949131026837930455860559827917199465298055246104533711320801000479004701428114981866075781460761709473293872719681926410171754754909568874827382527310938806738651284094116734468175968267249410301344216551189419121070262114211925172668247083538192959686602174188955888954940737768440013583621490535760678311903637435767888126820242393823522120307325067599471719605248829054862030592952206137997156325332346032822853482104914691410528095471768968084707980642505479956737858005251068387911727783617220405635579727689031037367275831195550025875341003493557200133635171203133113775060473471003159410620241487936946900397245706361933160143959874214837278080829632727259657596572997069619668958549510057360587627799705608757375673518114075713460574765923411874412421881002747559382194850456731235193121862585419731310889554616257760781333408232680496180761280951465841459997333399142488523408955726938664068000168216254406569601973703954065619107444261663257569048637603705311200321085311849273476912224736140249615882209549257162806363785491502757402973228761392454014972352993595450243446975946426391601562500 39936080260933593553567290973217887331332846318224108257580815280899097403950339037276360727420103387584635393811182266407727090847724282808544599315863168996494482901784593487290302036718801942521078086569280198878954133590163800613923184104220516409496211735416245809364792714871044875225245762893840668069124354102498517736070046168321832768835091611614733495665127485659380164216422371462247904587099582210220607629524002799834342786973672467653055107519429069380333266577952824047144568110671922434315600286715648558542565004192251664606224541602576836281951469513245316907097045040953541733717517246079502180902957143114324517184608015810063375676637462989991018524755222562256517109785435276507170115867158160139754631647859839732242989845740291550828845548086278447095555161551102481404977502991064864909566473560767631998853218707779401149312402173328462873198539010551656236864664355120321300269682965106554155693354258740089785406385974671272578147962572501181777178905281625503615664657256619391818479082322526454484509333827940158960628045821773624464634137607155011794687248435513966541329233566522010665421099703775219674104306840374794277605405803853138589399409836474962264943774568276099007160957343666234727880805011099069722769807822184422188030121731186059864824450387774472479110354536065846636269054443512085592581095649933331515057943761348724365234375000000000 -5686552288322914452583307293134271154509654018355428014145982493951593649848056764239593149439430218305180464006348207569098893391528469183871965170291765467823611989948854634444016208941705320072188964442628368905865473284379356408153702044424716511016717117662014327405756307568289358513855717742658070156891562905594945148030252012701687666419752174877400977182408367898195986088079167997752358675768172135936929149755851517392498765152834294617664321680679440950260424521322911418753594179725156297211378507036953882670779571011295741136515420173053672313325774855948160771124051587379475039551528334331814685450569900003174972752548240648290834440607019808502771749014387566185033142017849466075304107305142555771835175742251240190802460375547911151699136746761247749701795327612654582558758141584011623984558179398896561737840123668284996290320787843630649325816819349656902745614432683383203479119019130804650340820309246568229685566761747892373081325780742343181676872705786517224572985227833708459324311316947662713616984807654958606186987586575266836143698832272559539272062325399196133210225046394610762203724605003925157664825729064003575112881317251876442738024045141115406934606922263065954073782981952331409463625781889156137996109112114845414298247656588827562974018130786034122836744292615019997685783330383938733810262765224624592619306895358022302389144897460937500 779694950138028690978599589804907796884379878921019706057144690250797009576165911779371210047127217109935216996016012811833558270762164110356356364821155060275142066244423862369382019123791551074713524879081032056683692762546769771124355968268803104832232240324762926617771587033798561262334414470354342393416417561614127095910639221140617536128984192228868605000552301732741470753609895588601771351228603694179854466267181902752856106142181348866131712996081060355109463656511852476590348305075051407734919089151444710040516113087694159458077315982423701303300052166210941528230310649032484400205056776769873056484009708181194738088561739199972587137612257115701150271855760864562713186420630076485258360995408258906740774797915408055501756601978616641835834216153230788462346660990977563692546171179934282762888978516808390992681432097481279175495604031867711892880596574779994643881548993089617703114829831792373962095823623958847603357911501456914594076885375466038558568774243381818824039032406113661452444499103879981435528043044355274843335296374985753198669540985325510682540961973805577129471963409476835680394646560870678247518347213348394737242569981153631425581438196922423572048306926776117398420466085413521502089779554889530357520371605464273525306583693388336332401896873219851344062881124245265555137229126031122309047286119375319568547411108738742768764495849609375 -102114511262382150291729277781778630516905023140446334442094068725049986628099570768050315034343715608218224733705941587144973041728985644920441174839637708972655720414428107901301379085830601012778473530455206172932304447425486809138343158158884866202675271194246552831326966230333962919643320163709968754522334972084869134422122168391035717589519812093954222125379528159421906502952797808609755176629881816389371141311432168147577525442181656338151650172060267878267714712730569679915248409047295900575440946978165936800056121560154601144385990947514814428865956527946824008789917883981642067829922778845763512951012109630356982978901773777357052467291406770958335733073726505324703411731559127237262599024478865133824709205160409402213387196547514758578858927449764297148965225358982113702720299517755006151365265908591555063254342042743544907293371031579603833636415144340295611454258579680244700144537672711324774434520608674999555993411381340414187320950495268534479009225582956361687532770337534736975526232294068624026903745247853097641480004863026095181664924306772030789803570117299412878827442324940124635628922505090328103184654611427532510099289562410659070041138959496429176198584080055591465823331212808796382558586808862584376116338601016233318480387830885463110783589875291555361113382243883691947122349745690168318273190369016578671335082617588341236114501953125000 13411942381618423772229820309119009037559503874793797618019914060993725051493639287410289107820441257967519092485234078203626223829165351425221333764142563518167407330439191793875094936737986751263627264251524318626893308335469287922228800317980007097424274357215597155559080746200236554488534672876806271952801330592619450598788943693507188401934492114202311851640409665084923293521642471506625971876552208421605383793952673900424179570602969495287128885028918046379073721549820371113876380242863392916313387936854214560322411840015582675670605913765935572206487665041903334904866720011982144296731211452873900856871019530884712439365523827939734170525861526369990603505749873102719682198667220550667693669614402853088580042030508135807455257787251282612510648457883588754339168931685341072686321818593934006054071404078658459244289757501833618811762543263920125183817818892905202982853147896418483584305952418989216413512983069716033360632615767016752375470735569301388220896099917735772777024971568685301494555121800647858549040575997614411654073033985409737848441517569945092354469083933586750453271986549033295331550347743429053682163375241653281145094717216077474042211078585861330804915741047006731241272493592879452833882037286920590530461924315466561074934654871171267285817824520482512026635773636248322249084246771975205814972668602602645648858015192672610282897949218750 -1690612436930596121802769575157057374639847538020371598860671595885791361901921725016712952374859402067044288051429099765324426511387520240394301539202874511276518866732345654193160745304697344556378021330477568979686506145760109776015045751347854231653620239805802443145848122820567921870349645990017348424125732269512380087757401553116713774980739409649821448078447710889921898525915952469205564205222443452840443718161233453281871951994570933416405209412095732069835433374545618537244530101009123008319750594605751636425337468496590214234876001321065871000558303914374494604439923922685476918439144702140456804847592182823548675821832907909876861783507004188493804085158013217889774095371759977793419213225443921133109789609552618120998716214388099397098397194271594601199190073725193634683760570055534269355939531606022458893387994599333973232924643680294332609481330977902242348268474995101807396878403327266111112877250771799936110072324027964711613903083252698281004424896719560142680113195155623036832558932577920430874683859143278629866009120718404806991802197115862208353143640326838425013844178734588521817227208699848413623956802224797942164645881946433657174552940592254373707207649045821208827254800181609473636594871386666173631772335774452080423776183554049099400085021368494893877564264117796396587288648219142196258335444220000098880518635269254446029663085937500 220828645531836718926316045074358070546109004434847495144749761143683460843882238911980462899273071894108409943292812887470608631705227578285303020104923505047592302465746057953460532293733693347919016748180880522959356627450964075663862242221936404576689305738183384662995661441509326637424564241593463956015598341040986503656468205350710197656316589922354011648274071414193738888234404083210656459940397266873915929825504793363505693056772643061125843922023402892863451912683407738375338514895104808991445675237432289042578246183381590832886171595743570005242264326473859416977820176116213863797967434890404667590247793069511608413416051883261642515571938489181344884549357782322495237946287492555774419618060713865752408313188152830683390066746578910581975371063024465778585381364736834276838309264860777523307563333808848349997290104311433523968343518109909039666030924194122095702757718044764396981252995117544833241670746511264701254660954143240220838536695733606994847092197745222294755962082190153384943106207310683837755778697747647437260793701643553930987618120723861451254357672892105705837900671261500357386300361169172213069541438867318612773744732020446818244968432716170014555473201303378317662986192138297832278969420464166516030323198078591208863887447921440879286237760257924762889948136138658281497066743091327122757426028309968302210108959116041660308837890625 -28291769734688070114320275991869008339732920280229895470529070093413540332245294375086926585570709948508523115747833220424145568900199538984922575555497008921686201015942908513856677751932067676593288804555148541765439384186781678340303021663585489633420689510562244859697686539793783262496162289493832595755658387772690309160861507019399322552005242562893996216037130926437614079840188475321743639184474487814294951212797709770075634599308107593849093744034249901324297449340934670427569412655262821601214739802731315192155499594957449674462247731756075756641493146507446020047376920768382033800351991435175192401580864070376977784485156968951228040673602283638143904569022004989155076817484678916868359444701134579580199391128621166772191690648221940489541174608208588212764499226154266569000236754582516240877666823016985380379137049500814144583827850132446299649291588134788637068808133558175931551394377977542138098166093663034181132005376178696470894091762684887350817815137736643145378163754797705129897273444901466775251857375306279340369199326517981567484100227191072662492783215410911628511030829960244604345523630507681719702536814139066126991423822044966735177859861919860129910422205379539243556062764987871539644162072504390958343825833576906163573379929880089983611567548137868271961801815737895383840271675677824911657176620849440951133146882057189941406250000000 3633219260210329701529392740847527887061221516581662067899072074709117134463862425453329269106618063233298128246074207840363217973571975771189893890693484641205973321143774191784948917972334346789959486284699748755350659805899452064980714467962488060851372745875495613460135881991642911760970837187146319538420905897357575705096075948408567847111532068700013569151428138648035694339589609908062917576594804396226298539106411545833256937710769900240523230596382985081893279648939831313198095436782108928806226035893903996408812194526502772291962925289801999150191640506213913420097223948226328076667750149526653428893486452325501051618758715139073470386725300364753818697129363935320354508685807647626613477673230139021923825241102254469899328371470402611256766173089455527547841700983990707376710428118956586430565268866965602988452346109905485828262560416220373238158542800907262423758489280180683018084560470184378037240909951228093900065098789378072597332991540627979453514149412305384471020312096305017296152303759929724384443235045648800838510792340281440495688004973717077099421870310726464933161142410533892670746588752725716383809553947790625234504858507943132126990508548760609735309663638172090440744078763831753360875856650159884155204767159858883059599264936191592364871355428036338142215999863509048854543319701730207799128535839372489135712385177612304687500000000 -477921213720868280261082619613501566267753621152273097364627586959622737407781888536347546384519165230317331901493355886379312924983942377294385326226061183947429218804914693910618726048756051538544418646910505993226794389087612494540018339629105899624131706824925924324081849504848487025827191076772578087781879955727241314261764598090182526617795403245078040670747245760754003932983095882413728207479377386674692307483551762773638974741547006663980295910311080731924104933207850498630403393051469392130460614810851029381020211971694696543897115039985708461735555403999293383939783848547912821416574666210477799456631450898994985585033276672412631082632957896609621882416797848426185650395940984789537215102682071994475767285047507955765727748707036163129989247463429933938031271367843865607793797097860333892888820495145438162181735012570533764162585681866790343184267242315371050141371204762110379909978370138815462484925051475295379723258374394937002493176714872281944266202555646231876846980718279690263837027517255775710251054199927862589010872521096709849820402665434036936616716507171792829002371318082660501505766822878553691227552157949289917323772246616614420961221094465681844660051963596765960813551806364156000146261956067437566806767229459940549372555487449051103639476300163997203728706047743660537575289090655343907099172895414085360243916511535644531250000000 61072376212504810483241443719011531451543570475656009547980874739388681683052905598605395838477192175736510490905007925472998514442401908790866893385931120869316515543359238571766398553981593574060024700317279719296898307500023404624122523785474808844136730554295632401009835596307067518202530209193622170653096152787651728206026437026783900405086439483421513920095934479308677617081382512513163426540791284136117034312188505489831794480612678671216609914869502749018608224194639325166397827677168315181357773437460969479404523106332344553596586910823867247521254346092156932438677369770277540102367250779980094723175357359068589863007760298448206976462487878245696280331833685419838998384931559659750828804059093599710863283969239830516553166596313146106206673412791735105926870803165432528511089801264323005759951082870306638304473128077229043275038032278057423930467787744068166510343380702833987026840242077563673957509172364181121335284027665829743514184334569105663318423407005838413103649135531761026291006978357874022778011178023991406044307064284135434546610031500809448938418063508049411515603873332378560954269387356005789379596839631187210854927565847500115129897457806408255195766784046867354928171833769130200696020548931981805707269623252415856822098058838948221714475234066394112572656240953990216729456687594797790769735046367827635549474507570266723632812500 -7575193078367074955997693602019356081901113769935296875673833461393602632512061432162342026282329054481012099277646112323475058335160954694512366408408265491538943998313394444740252379438820940778523715428638411690373477582993293393610236101948953426132057766178853320553795149124376831157629528852291878293910562554315283637741338481927635155069820651171587491831058350429243347064008067512896647744477735751231311949835974831930038747710199881750952155319966116293055806172105654061900931360143160195710836000438066359761203595781854723432534176918801681913997699714643190070035157047121114873868418943934963298804680711817460246785904518150314084188948021543719362343521666196951840674349791737628661961592391301676758907355436371368496541606056390707420056282087266750204612742991038975548600034038718146273252011267075923493650478738952446021369051085733456931113849879028075323128886542064798901355694191989185786949421655135985559565118631045387478219192373054968709142530389307015708651921577263116486669666601257937584453583937115118286925005353542121269543357522180779724316222419328779011523417530509106927195991696557700835333557219762570559287025627349596235720490961332384143540989802755382200876107698531391197405208011372055751402708839478367082600467925936182677082096481091754055225910900902902598093357674889245997884579253422998590394854545593261718750000 983731377221261743425053605251569125099169081302977776720186006279529936423000382525980413134746271143907315214791402766062168325495375691540432945302799209925972048797448422701827248406875504165875941307994580258920764850229752504987406412680298521607374345549757688216311126364634150498018064097041594949546938745953397258310701798919762613435999544309669224898786376263757704463266472748643385961491195864015354870078999997888461933131174360190766771788167268320527245012266742326136072298969245875276678347542429101712934680801728008063203663238284938203591529191116950403745304471174740061479944134046527739299054992391212208685112071578192632622021974371945161285850489040628802172486821883793682262217415086410262750656054719747446419860473383732602792646157512247087389914693647967230010993701661530069687339892369694274088440807757702950099697214154357378170579377571436812333483711601814617486455084563945655172729462631587991693162905453083605364072720500115721545786081041999860176584659742007459386297644920732081758124571860574132170192426779692527562114569457753427428045488326608052034548038860227834199503027013929384743776667339753421935729440022571341871164846997559939519296233205604340766709333369139534952547983163606246095260186881735638751359634709565560516393874240318300369125278784011400303293494101829035070050366584837320260703563690185546875000 -121014201015037088873465353624198463628448147062278682345373246119862609818790359639054505587968855544989184103638969247749141834840939390653091281702690665702775165756513410193410988408588381946156511298466613573399754861145962645672388385908507534966588582099101892336160976678971536158513949871014848885858813666146323312764709968764528862595366644194476581182365231441739378102813849470589278911866850143053706997120136684959052922311694529969436028945444655869840564676724802815261432082085165622210433233368527047467153323758155064740486068032347833313375534364353508574790886062670160132386328722352108872488487240372756649818564821522465599458377820091468020227503880981137526974198128442701216106104642892435720866927799226347210785284888756762532229874905412188825220126318688891904190127750812772826515843749929844785922113717481455405562882449432872693910594501302726625990614976736472235854853072528074590876400139336419685780497739146203082900635141218160023195627534175359838965411183581466350399840792618322578602881044302458106596507538498415601916945794651471929146407089536038294499655372797209467918173598400328408289032318465482811385708782346498881220671364674063001628074022217787946882247998194286186872158065096981336760398852843360520220938237378803590375796175824640377923424941041310078692535853012949426110722583871392998844385147094726562500000 12415142809818408367670045287838150897621282359886019239938316831325653042397314741089144151002796558534938400986871106313817688576731678525609343682533988630956331588306567100408943652985520260647575586525054431153830792490886653841371173220722936785531884949289481027162720927742459675529349818999319644646487741204893430797113419832856788536238358154303649820547976848478735975449429320040405850323317015517950636941592114339715286778842827198356945457247518035432972409757885784510842402384618342492745046434483910551232992484527369245387188007512963890654187064748231251310495368110972935978461600042015420503727699278689917295159662187105943985885841653444235896160677373028697453027736114180704520037372952226084086347077254988353567195425669343315876551096002238052417915563715189127168976694032360993087614733136191305180726064179518835657164059918990633230392873473876294263605400187903768897188834813990634490195066021224746406191824986249838595010237100136000272211238420432960470114073781644522250084878877880367209176754690350482589376002070647551646504988718992967765978796600187843032600838654344219803292814590683461288020909526210473644438531259442443051986938302109281302363742945712360118544796570863787785804821170684355312393555121960679846141497890248912818002081852094578102055627057048394632786860709925801787845145440769556444138288497924804687500 -2176548110977893020871489755578543761659662629895504952472820895478536763324395108708750291230790928718258878083302718195293155481294581234120921236916045000902345057978490260548338743215386290562118077869349954080083066389686965416489059722734518770849450786649390256804706623961322236044488631884511927795308093343657189589031752483494780736027317569345207974054313613706927577682830494341178963744122730638191653933561969347135247241341675442891989814610344606777554819521586042066248175544308108319780464289505518210356818141332121533413095047612647044407250793225574791224415430243953822024638351148920850277497512527408074201305713170686248441604258147341580603359962634117441895202693201766068641498198666691618002359464093555987785649711831989373621284732006201338819806745036452807342687812153206188604889241239437219868159090775335400731072019831403277203588798306690224875501502456245576981228878005735610140816080874536296323866474667955161962219811315819419012669655286798907250060001285451325717533106492748508553287790658736928312445479654726493514506830466521005282066348128017479546475444968729629947087297276249939481408581441659244641424380866682557864351484548543227793367038342574011672308232069814276726956613001016281522515826715723724614261862293966737101697320382321286692879535279268460721135833361951014697233119932207046076655387878417968750000 130316978216429443588194506397022776859026245986743390735602885524444629281207430349682651759547204859906587285321686231751273529751420849511268694368950328101961717489828004569095249150233358456242651992159297431109078894224435173525279581712737658309253489051059312882561652925756069378024574464988942213542124397191710759679447693227558552252009011600348389026471964202448294025233608055633186199974332023945981703790060411206914844222774054137033111285426419822352456341765736551952607675238833559883418898020623095263392814114567697502667482509594561590027971348810142843142152375117528648498674404526250687336904659793972460065396715132040338784266107452078856251066694190869700783866391310034876844680666746404843736197224599548666108281406691987362538359666705232307881403793256701832554014283628222620158139467353986548272877786261717768348884422324559173286254530002793867784267116857479782562231491685694487617444569441591024337832714412022430495568651516636224891598091442139899940320593308267994895522025675662392347549997806705547101948038439061957614741037066560298703772903049749561296569942224576229973117626782034234243310814952198433551389843072277979908978316976393234408587896871915375052653918506654485172833337753615403687558140492514477652987783980801388274745639401332287059837333631722247061053500567784357855316557106561958789825439453125000000 -31099743149548891196400159997390962430620405226155684943484372726717607233043804275559337128848140302525003310375107774677871780416940277957006722269053347399102110649126243847854295317365875042501188690680674248055554962018542682232755809567512947128490533953049783959561387576586083483071584159220673240170091598337708806533654928334026084962239554043867094721100530891797207294562947299568064346784072249452282189683685198820664651993101388056169666348715187755269449147346937545926552486911541178786608620216497083772961628632387486380735958712567562961616038579218523618421034952090037766509961485898576838086699304926872191710616975228977382020356959142482766815354655122000648328504878450083873190625878744888844656015310662735205443647469400008952078644423290313764645384249408777232634046848769679925188547510007950469762502127179162277618117566031953271979528823943344880232253693248601466057846235682524261223500275216642424557224511509327781568093599728002011244557654314543156734125429276643237169372574141083908533090652735161527801400100011867569276022243983694969746504144434340605778633056912360875359379406526995662686425504389587775125467632889455478509837584197470517856556451324306669464645055830986986666189279213935248830714627683344397986895329129510182944907566709074591096357789133160534488144476116325276571217273158254101872444152832031250000 2918610400247231753513111272706450122333490277833011998017040652070420099001229654812584394646282355540802013573986758563871400307074383268543618576948449599106454754357707875331669417946933441384185105445524013425456442489862337563686145949053298043208925666144512502962819782514192597739697321574215272879771595112227962115730487774684624537718782134696763996260124739343220380318589177385588857951416553958864186390316528858958433313025075477235818115705045207342879617419511370052102451684089856306600505820249371612132155392344390839111211323384693071066314614529781276473364312909504581860639751168577427173029581545601451542671753372682781041492749016903136034874360721944776616623488393534749561058096188212513555277156390611078163488217085235341784273226713997474864306117031716436874079560808874123207669914284243372272806443811693026257674675667662025279676805382683787465108100445844047564269933979697155319098841735145613742892283737617307784838045782380257006020194600524434179320833470233330239562928563713558825480981855574875098471304391116546683053855926732448996612708865609720601148507029379789398649590143432076961624220221904474869321541996276144956044358005117135238365911945452982838240353993770850979569949486626314920734174178179954494501953800150195800316627028001856240045517150332355702064799122478350179576978007389698177576065063476562500 -237302494536092261774215023888979022957982104081982985506720829503304315680612231770876825101400945941987386288932827942306691561654196379413622630995022597450063887999496608668201075103529323826343058473910182740114464802383217522727431287407860662644597055713434380828775981503836951139068607370199306100478178238124268895851748754483183428361781764535330929004764886208682183244815787597528126884584978835194025535533139191743060916071771234705236051002938317648764769954977720936374495990221462682303882540917625442600079493355723101181837467131989496717483562651807466082029326944428872126201139020375205899286909294546141776164227403535368839918310820547886604525329613976219143858553009174640016148089259899836504135845507963881229345158202444542766993916847638860425070644416995836123254596485519778382085384027073678349166581051696838592115932313744926798577221262308010596313175772154757210247338401701642545217867903259038570645787571434539089335062766163737220420491717537299620254148880261491312366768382659218557814406675315130489008516006023556926267180628788181862398746324694681586145313559495990097291072374372962254738813444622686155803076768278712194611984214734400360189179733439075306309037269162981178429342992273294364893600253226543151536343563760017284771551477076317218933208471858486734308417171607219486872963898349553346633911132812500000 54852625151804482928944302082937752688432947850037852743661098551333766265315757261578603166753528426429786154221759558570124735990441292156997515401965981106279547681941466632826309103313806974115927063748962108944094620222182787667926327135036907532028614685235454993767002366700902235817089426799723526154742810756716110543183712172011137297760360208635620484814355314654221056487703388544019650340348881989111332645305295732442444518245802999723183123439630494798150523190941946890010836429998978910137188367195495885461283676551182523539348371640150534762556690136371831426601842445446223535521876950057701238081541877247178227688355734633323736924831015032805094061236905431416168390125010247239029630938709589217137040324243501889229555489369164100834580760975174472937666534985102252200519829533489439249841103091881369251758955626675823731314159648037437890564879076598126607832996348009383848918383430225482205445902167653447809413395420893065018151452681946347536272575002682532097693794660430378401100432346477601675682779782226814472649074431824520560121833572404580303233804980369191848841907130956202309951929279736706128592299380889377657870233296104528175883168469958161816957859663394276961849918170662541952710623442970905587712486276390486975344534469501700595180489863490656583493716159956723778855854252445301000307154026813805103302001953125000 -6100338351543464441936943596741305653934498400202970170932110206646201198750453381726844564991773694314668906820553001127919027934683122579733943183497102522215403114686097428510314210369785881043539793980090749317245810498198541813617911205159410416788254015538562078532744190685570362747439953040278474500048192877143460303328136460792711446392165241228140104859777985083614486976584498078215236551608372591754116209434139536251305003702499722311289237551196252842113466661182493684140165373428595812212091226673207013967335332305443798327610977989087734069470688829954655053645025303068600906108587407683983755029496425074285813916014636525355707445016249098843493806785793973638139937495566932763976289165386653850416307726864420379587336589147654375949069759143055667237580639669095477205943848317494152622423660245614700846072433513901786622038157301713593771347552822108253890188028154115088185575532551008188702738808642732822639998026547042768884301078744666247173317618196195422570072707189547810430678427181839408309728980199730977940553669260526170005265072323380140492650214016292480551739635658373432460939601609441869479637651491170769210040957905794451313143509589372156115686738629536156360144647227008525917898041494063656744583947802038296043936856426714392798383628091458755475246031072703540603692365720811530138689704472199082374572753906250000 -213406255466658065782602259411691435680824459051691980781735677646355609489174729206570276699433575377389735977819247516803919267685115484251902627698748138760980177329713134353261841264670052457293153181625048412111565953818758171303728630740261167895355200968261177311412804500857816537230937274383652173799300771733989643185846693209477719963020172348876672686172995623290374353198899287843705677209398801305919699247264155713701478722077320889117982770313492529486587651424140599035584276130212753684373678468500074934231152654227068750251813137730425511849722494178256989922993977057128865884403952455051806424954728287443723945218498482379810314207265798066225029760207091765170755032443150435434677486025006853694294707023778232748383917393699566215015467598296219637053184402288304679650051192793943197459910198113963940423460426269655005965165280679385708618170932138915458641782069846866072507118172398615743981053469740945186227907427351338695929746162066137026899469662849535415341877691825605698475551847866265119118731841246137866767639363144241580696022582963429058534093814614485707166396001095969265991332273871512403778557421698810856949919474645124806344451685895460591934361185192705725670489733838271489385727390062096466720812644842301008307960190313102513261089306606040361246019573534205592632454016183141121132393891457468271255493164062500 -188507712525006002410134339267326891429742601165844629343687408415199215874059157829401194643241162462820431029085845149911658580962525647763707961614083805310409515072801426235518387259138314535441250788276767737826905474527557404657756043046170748896797378548459101762889894666250067723745472665844767738938169117837678760455492150875034203348093469209103319008690468551154662518010048717282016473594087534360883871485305545321917389209488014904942055880174517234092091290948058532141600104703629376114366172714905248922919725818818559802965652780265170828617344806991132892588075627407377952320561417570365413940364687265670993018552903199496788096000607734530280842985927450013893404401610561377645933948811875873566897363086691930636325019556720962314837932639646152379819980909642021194695002967988541203579387205153033601949795415309755217000833912017550710167713371245827238600652070466273058016467304639636972622544691468341485957339880938572919263961263391583216246224030157345838882977332529275989604970079759569197581493945985093174004086039402757090726330456730096026241999600072099424476071855799423346117810745964957477087455828178279036514574154291936519323245550032204060012260981265676043385232578541509996462564561226831641675409623232201870224565306321526711948445275094226404727900481798015438475099592174899498786544427275657653808593750000000 2605190073719978098813223688436754772582664411525900642485212113409191443171167273728493450833143624937072557855016726652553581861611952734492555261653655197520978389672688026598714315457160896539930831117227761446485326473155575886905561238431697143692560897301172008442966608771822888100109285508167584303622544247963361078810186210531718363015853425312366530852495230297991481339065183733743896983647858527444343024589574234478014930910690544346707580970669467999919298901253478256428477882708454140654040603348668455671441721233682151571222851661020128423492249213316923201396732773010958245777504536686526524993699713223392557790078317437885524430312552062368439132803053827346835719602144240131974842864816018679439545870260819258772656716642124649728266490184740528077901937237861903754108856755927761012780754795671634632286018868291019541461616793834619657785673716643620357011269265419713528028885287432921916699162418092799275042715203704465707566396812856722320720484786502711752687544709063214413716389749486136246287815357450541279404357305199120520645333753296273335903896392481134817781490805104697689819586911371058328497811474572162078699611278765336428219215709845075244997037741477009660443218578938534507107769870182595651765272052302027990925963257431317090797184026465777420046608217882229971765206677503101673210039734840393066406250000000 3223262674230162827817069435753417339462993054438454384495377815448604373015345096179070646098522571451452247977195105976150975768160628631876986919585610662408832428569951059045568339941431573055039546290479235577733854672386428865032719821267064681356166664804768866773359691251631490074242116197607841300776304760608166439560136551150423373480724793159808703507247707696483120293307065955844176731556428454380493076337897592050665530011744216824958259249951736348699598034393185950669517293782570375622189491936714063274937038918167332790338576845909719002495952676183496843146479187901984879475666114872738721129580168986791295254943146321291573475693894626126140353682633888072147025253686296106285657778150709136140555245129048944442104211441468251893649360050242383638001378090587066749482414869578886304102929799179676081012589657112204396310285859605388770468609908724033923667816443105467521388440540300324516737939041961965472885523314887421872871430636687215028411936760191408775973970912697583877317073279047822517753792997953490732783631503525550891655023285790164063924042436685086853061821156437115105466955455051589447354638278515654042656743707346380731062924545382874691309316715994705172279732523112641261810824011878609373274523875730735409373532034627380594548128838508984827861488359038876936810136264455195487244054675102233886718750000000 1327296365911551406481201515974614508572652300447209444908554427264014017967198322851342519595144206442283132237280293552938482723436474193178426154590719655197465062720075872201206685493502077231952766647631327460586063872020905686169003133840688904698722188927681612179046585492976511253245867253524115217886334839752439383590688600303922780537698803437425943043747051925087478021823258379364968066805500858073583823897014891869486142525669679335837127825015666551733624673585423317388799303942417072701329261253738143254738567600460095373059008159130168799173691151250624523634048534425802284167907189351941270998363795247381292033286645099104027604947966355506866271057281528398012539437523193987007211705024562591581256703325333647585950720379706775776803587698731199638747414856918252180837181285718544258196546085071659545835121279678057523227205344410621032733092437892361426558874427835375783606494861632182162516728850910919703389093780610315262631236508917435987878134106421424469578312205860061628912321176332986769541851802152334123876199011989608138145053909677773457809359459588651897608490794677947726840501216202083358869947342549717471282470170314610409352871185416776335649716300062720262001376894110976712727633425948534794786541721991806279272496116819679875861289426451244225952241688467959244621379583106701716133102308958768844604492187500 228833505162913088231022826233460260825422183859995039314506419372014776695238176595018117756054015052677107748263446000974689215194234947514577886985810682388130617333719059755584907692583650552244615204659681157287008027503662712355383029644656554330666869450663332760175827804863629170177843262019534671920922699896983585576617708484029655709115242294996420120588888599267840160587850078473705574332457675316410851572123262748534898138141321782713189331662340593925787460079186789290712001634925130696794498257288238631017333797583850659052597704762091831783167355092885338254013484898402819658856284910904703859766791675275169987350499154064883878621289643829255465437058842029829232783684076901248434663397968011949046875315107683781562483264578806156756809610646965490860922444576511210758717076438415322595740016795654868399748235181760592561465206238279052603171437587445995775506257341081463369493922714427206492973471480977177151869093531267432604884289066458637808780704530088514465897462087486555798793776189779418382747929453981217805433240289737350991974734040997070389302929870339671963848892268260766474113870640348057577279428658753657648579009714453905279983013179008838750116107203643808528190213098462227871783044815751976052695820988653152781810735793124593052588353676813594809964567415615162597128384724953775730682536959648132324218750000 30939075819232640294344848596788260149349026012013029090485000076820944191895087342770846488915203870714793164620687327439336413260340069533289772431013400921842333335559667485094776887720983414611764767848691279994781838228157626716210770496379504092143323828787980593931528385648158870677997615801025980467716399541120865423028164225076365766400797882907272865779515651319751723587910419298046550415489319330027244369450957868849561972321826532943471955118476125936895814992050560459297668805242517225481386368935744730466707429624868307354782518431586052526946394252749193706238336114337498214350790891507802232972860874434170244991537425569031341664467884130432511808022254607673914491162655928536571342864408309722864144279747654233519187232709220608030593755753470528437222819297243097971512443104967952501453660969405489840233024952690880663103081301256010932077605262179539343123171177850830079271943119315587015078463563767700670711213896571377478385695243057822363320599194969048590352593694838897775130028740780143365218180727411031987911418273001917392281548027032389310844382799917920364260436920176710452267376757145399127618362841969468996707841335504462024904270045130353343228637714941140195372328255383020458517369241988046170290249522953590315319410978144331661314079252813338156999995019500612433195618766745838001952506601810455322265625000 2173631368080143421941207885840914815870691856238045244672289640731931814554662471462062381019203538874043517102797059751251677183999782010089627630971194541004054255058825017768625576440132493793983098411478610358846264439026870244741264764138920224494152562622208387781808789322538679478864456903480246017800077064057918640592884732353292351645441245569267626399860926983718737913582728045285738464647410705525725119247364418090746273719822345257010687801896145174515112048162042749360407747210801712188220493106733219454952579931512889991256723989809644011308795692564434466843877654286227300632019926116122181070269595343884187667419441194423806375453164702341937027796596170300631515073892963117377647009528115011306299598807870060474790556781144181757687022545990377694584999383725629772240267233047999789482282768996713657580626261352721647756093388681334140716943718932416674337889239076410811011439617159851115833585982562929054401110470422002365713403244414328738560896314682193329821326374229841997625393257614666139777698905126503983964345343939900019891214709097594673079941974214218503652885325782579221741635524245784917072628059342326914248713693127662954286629547248316966498437222639747756312495876158544571995924487955568839628474824180889113185217557186278787263894105465195032623908752443043276153522569416054466273635625839233398437500000 -35195097668533632115810202565236183311458520307322020381530265709729054316927430169862992229987431503619064888899995567662805700949091587416315525249428258493665105117355823073548792434442753678528382414187441583788396332908189617258930286507633790868734152672881096792691659770628915501585749055983329116433525959993349590692497990513889892782696768640256232769170388511034969164109979639287945755221460984615848494256449283566048277404732452243697294951369978016116219613443962725132220175293310113316378026945220233514563916295196501139660541976144105688688703789451848290096769486715330614007811176740189778468991424039158743900818508874442012518618689766729945058690585634580181346551866019410848285102603867240199502611968936471829117626377934376672429866102058905380940809568013347415310050287700955739846127961647918880546855299392702273077532977024996019342539684011216746887080378587588887338253769275961339469010296227792307766812158307418516881877306531599466852767360064487971074510991321089262608082742913979256648377297801544675878681945640022537052157182038776595334102822401907643061305451598093768496983324892738404686022760465637115404324214147109695511772062952029380150672461852665736592807267574940479078991986773152820567383946151539538349283451462370187800596778626429477369159045987787460662427063695645301777403801679611206054687500 -46295392458547462710450467677778903199361457319071734448682715508516859359692568111557764400926185093424455327898842096328591796438102408828740389407059007546022986245523202639076005439719774168059264603878011048678678195552759480187032520452880117007210150906733180643729830278230317656003097240281113186084044996856370970350575931538757685567743703493744301618768430683130223320922774849960632272590843408627623186074942448618119145626543194800032011767631246757984407527980360720895168163282834998139721359855882603725164663305660684504744856481691499721013456503065069407784382402588370885580486933677332586852658040165166720573435885296989688448651336884125243814875978362929870395793269062430004505759302548800276404614732441419438773889777942415498489496146894695577842548427419756867514716267059939353045905827646669144983921104889184085099110804009107744569846757240188263429436551728281353340611942633357599330961597765399802793381171937767048071634413801338437722266619687661931224922139882212311221721055855305370607552457622488914980568446254539488266436255411806057688357922710883732388981807225011613326869884332413034125216961868817970420153521726465495987430062877850539679020802608815026525756338225110890649161126755445047069696047719288155957138214428584427551183566234675690946941703001268767284082095159192249411717057228088378906250000 -8041677973779976406502962419974331472022392681857102957891252881646135531564099344938950040671077239684628781994437285080122238141472761179996942687391633757575186051573863117546665336051500283650172476173068273589840699934174584693035600743368342490030604860840062142919897941829391939637617892184888382501041650655458765554660837066255366764916283314314468455628058659923329012120186763664598667041120312346712109836027646570318574370437156255395454312636001058842690843731556207741057642128592402821883022922638034050789051403597301414851578228649964216852538879237558607385777109880828710191759750514408144490834161665123235567119930431255985778336008557258989126480838145880597342208476482841791406390676240597265486369476974330042132608718862192981895110468235605644636067352869596271365074608906174113589289808419563471461988448477584746621505139663036822986620516070009719161472275502563390084534101137749244641041481152259533415740136350716595812651062866152928910224347197535949820198268852159279618636805612741776949415106102002691316604812144102015798116701768799485495948052788765503366770903004912126463797439074381900995826433404794232922684902883297703034495366428800054599083340413505627116300776378293425882655634284757840844519650611274742391636774742061676408296323717890551485302719488348389964560425369199947454035282135009765625000000 -1053570500305481499290159898057402740218437785969264679455540813381108607955919942610691201390798660585022092894009751623077003305829242340309611886035115361306570184622931817580213919757869963546297246906220382805304196021531044432149959711317586218715635770711413232446000770491657302861217619660361491134645175582333148709188504566881317048437995453308727554451166309323248563556902300139339863323298389324763278950463524784733464808918646774385699090454353477148019328016596731689775504057663160391260899398408933547293288825732275173445632332178233154450603272688552148433780814105977870252269903792630590223105791874263035825264225435477595159478184041035072434380588343181369378292562355259485473756955538788374207117143589069140692895829216483124229654563270869247848390728085339510633735768853710168927162603536716381907930641146294247534729358900443470995190220935967075851213455119362744995803041425229596076932778671092108570518201839528907062821327929339729002351770503661407794824894660966947069302558714487728111207588999635406861695501611781705659267677892773486340296277809317535357590210521243413149990414043040183893462903365625404339191937216598027270379651170233688325075387929310969150005002309867396333734913970596882897961923294715661927779388582623538254580166750113962135611223315095332994650867419750284170731902122497558593750000 -144311090760330105516346017191784485678026050321638863869467073327420953682750225831487856948759598243731772746349813209522522465333690773079487100307099823437519324311521787856587650304720220355149481609228806550804137815099681312849425631807512912478354403198934826289910809794513847312714414826562175109603740504612808309272304242441327458080679264123351709794127682936993739559020262485539802993747392327610686262537659807634633344144200018210736750137356094233565285556596844311908971808976463404616233485588214959380726999635429298801861257036076466105118687463881462703458202662967978096239548596263806149325581931052663487353011827289081024336256158502168974547403985195811042126540977100065591068161156867683843030924967760309674455131052076605816404144260133547773642524725781609447453523914839643139262937456633883825176626315780081466548991918846760901366458493176944901640602089741827653159307653882681112105179438320832651360903184923315832053882636154635682502861701656707704874978431301652780349627964807880571257097428171204331593643948342320167603540036158164526105142630290872896552895152731056076796689795101745565905174206438130249571947166159006252507836768045886152999836237800472406547829778861491340889050520957388208457607907178076032023214802931818277753028362521319683788163158116391125013189267178859154228121042251586914062500 -30079965065862340970222070203236201921852547283746192834703293802117498811700434599387138340656214152296393709984628010695230826360069588861505722595868789104378200227541254008503492068675349534514148891792214238349372380691973990551199191291606334966466449404917177251628778250243278392992914509897844647853541586938190165059672823142198307978765791347484394898454438011319004878974176463750974810842948013084773146143607163625085143751241363100691952118995374387338107885007313505793910711978811639964070552625914572318774315702658206176195470957203405161632099262824110471038263496041018941073208596875208783672341616839499695711008957658481823216738938089491378641998524291261937972349318376117318586950778661285841554393134575563487773889781695989284902738886992364348074382063090455305288487565044070477421500600208482249269649586655949171428274505072963296535604443979944175200143475099192912264540612890475158738389670136150794143496017782033161509807055367435732326889248101026068242177509519436932383732012584488622254529935606462729100867159603689454668496883164704937279138760049002228525552068932948996635836917376277674869139263947286998251353816227245888046628660163914015411027125597675297709353473906178437639800336780504956807772409099727111233473401321510951831209492194609051087783738794457361054313082604494411498308181762695312500000 -6821803910018913965165149511573118011593103244967769375749906203683784166751445372424725539742750027371774715228854161922725546850068256920040425484244762697954649475056772576573243628723282711877552713433779174111797738170744178332271729938222633235817321650851041586014560289780918147630783463242789450882744488087615291624153066560702732685325874309315032758419995087345923460621230670820069549898466891583374093121548280547769598196618664417165414860966581779190706804914779107891719120066600855415443893889120645368261557946225916245478855298670730707068692942166695457003183670964453531273068383574491399917497820014935945243520541798348137260407037250158738440445347258826057688482355921472322236807200496116089633529062710368649150122785490066328425195228463005674950174720189976468285659477295077273340571894330331744110251464401749537203020116775151167222763612520513310220307260091942284293401817685453714749305556165599489747516830778455763671802321944820414243590759979446533813493891079830820364996721693752097882707215252064430358900388754493105293922760354629344898561340774119740430703366607589652193511263571573360984104248650768424656834419326787270669409834217593502551421282349728523387224975244888750573259330009339766945979224924261851624003303264708657888636542827944515098720907787127089305645455397097975946962833404541015625000 -1287206362712192451804366223942764757642599172181233843723797636226528666065450102379899163976146546690097859859354249412982937777550944788602818228385607147477321780724517244129914153488108237834599099148488432991245076932215374265983998577458798442477910647709506556620096381756486286137759263082904470305446893462294979551900941243286168182963985163661257982233403701923050039423101565077536763937668846187142557831212025032143375516699168620763258858851866292123053368161177712733443662068873977669347714511885697505884532218456309532595891656598751806396858873008714198213600126275095154046935620224312235323713776733384259351644615151420607169497415199800101652033079009872860982933688556640876476268639160108038186504539583025845279356437992258817061954182427011311047172220551139956966022943665249409513947713503750588083181472322879418029023048155361795308605465948231502035735712175979177153235599791161004452265790093294719859554021517784111134260957029231414108827945951375345850214111212396692937140896686998524685522588537877565519038315500742834280620131542382547935171741459977190391757001513401781421485258187908564359064122321766908234874860445668414305890465676250562421298079565292005014522957536717333448569006832104424439689128295126333595795049516575975392326914463009414498227387817002806413846371924591949209570884704589843750000 -179577023980375787423200478783220887675986405732884400655523644716302037489743559811963127760468269173351519311786859293892727501555665571776099332526485416279047370132066743043651905424826465534868543685367969451040007073771354579493227521949818466842235215356642002401978137639710437730867353792923459614927042178253538801269081039046835850241503907887792911473251578628217787362419525408786826995649613566749266108844832638869688808611419680097760781228780562833221412509440357092684340470959989793488644450883931387466375712647776654399284039022378946882523567799674327298990082830401495661118980849871465995187265896372072771642146327085131999181544278416410053909510446840274490314356400977293372362219623922880622460330865082359264698671142696643910014274251731618563909306860419819943083872933244393218580902009627216186149940435522906368585013991737095285853949224478983066173071084382722980788766805217441290475642389318600423736853741097534508492721215288583388781486862579355650499504025927438382498037727571511687233981038132437006503894578583594583543773117970956807989686028147307140120243809693292436865087564160973946075175889456102395740975308583761896900041157056771290108622621580129654741953827949169247207221813335738312969311601219239689832901558892918244061305855010155501572183428559466994434146158710063900798559188842773437500 -15001956831446153029560773211723885569508332579574393545449355236670106760291631022013359260040689674822042399298101733395029699812257553460495551225421331814011841720971776376881217360137735844964346313919077247955248905681262807648200341554889188509358568814978509752289234390955004267993795134374712757074437726750916427280804295749469503007019973889162308766656595439047748724567362645567536194795181827233202345596098476285277380941004769345249918021923272744115298244659779543923118532517458412245672617455027055985222832947590993082312941072597128051519355652041214399275192475921318866662977916048976053207230856650240929071205761413467176718382323241977771208132643154113001932383263953073789299946871486651021010979244910078326395958634021238409523485266426523599973968073531168730749615835380154063591239316611590357939320612144332238759288839893773129533448588896904518029679799369517578373039493886908328669417489060503156128017162023548839891940415071787507830915968187886099773453592277729980428319991582587625613072421837273596037676796044555981092751310204230417264634852620504269330264392398657797942639270302262393032523561891234605589278952389887970676588957267166069886630286120665349446524590296699995584635739031397086275971110003961581986976663851338064587307913117754148469190937295603127665799547685310244560241699218750000000 489449268528895383965362149974952670461618375838549408413309306896710362131311508429445314140706086517569109254429012226124524428348010517266677101536632946164751973538609625299427172560790205327043312334921627963876669903474699400097847709656455054645879440070761101072986225706487769659562681437525373531744299272520246467692663378226221723075429015020139271003337167897572354237041664467588072203484919804404408258518239890759829345240817399429697651834506771850767373432874686741245439793937105441580184388236981913839618197969995219865798230460976651920421834030188488101956615417762097015633076863021432145744132724882316339876221375869420682896937138012290118947874014980768633707945593467761282658888694021171503858122610334229322826587925509415402668796199506800114625633561176299778295509481138032448018756803554504493283835356491228156572470564976971332358600437887954570125169843156674188057762429583537180162686910779130342591993552066939387632663546962792285823460438559841709290803068155108267911388909930461088642314286241474179728015298339486984571505434393816449254249058860949204279976566531000661870832815671711668461296732441192657182551220149927146414089921458941811730908907424927994058307622538082687631489008676168564327891711505056475105944998689397972117195452540706160110984407340950497200537938624620437622070312500000000 463670827111272827200620432262250371297780663340760599804808394729287750550188548994259110959805879546097221945234096738442325179535953296687391487604890312998702167578120640422563422547298362414321387804604801733956159146448208666440292322737481585252053385993230409562624862336473007257386053266192739225476668253386676817014142333759654625209144103098493652299760545718050765894104493953844283803154656065441788392416621641624630832644504841405292011851884723100958245443413675029561250055383902922062844846666376537957431306570700784502891798665340461128021473162156904546903420888778852452176137548323040188578140546276469351497960578272983234166243624143619079608000233927603771482687281286022913967481302731337008699502460418266348884050602058884738812035616019783427869458563969371933394662358862728056944065404835028904614724890284495486140976743988890616414874614414578012108187585264875504126118401060298236922591837224023721176256086234167286671049527256493607773916780994573785384845999346899732838309540937556647228320253592979651028856511872367373379192015799380413789787677658229223141999917757354635817303846912310715496535944919491712325419667418394387446261911147642002390161160838732936054108930876945880930623691565263979463867334845136562706201979395633904166412091720006361791417762163725058144336799159646034240722656250000000 103216899299373047088246686003490473322182094762219983319777280329747155792380735537458764394239309907968801893010073906161193907516007970013607674012189484139890528350617597888067212430911079267605387713291373838185990959307446367915477343071626103041168060224906429919761852759167582499014147508319518264049143462270684840543932916056700830718508546695652881182724459235788855026114822543081167519231570180107529673380622947513349923997849398286395317203661760253351240324532482812053921724286907441392764175803742749337253727633080561803981629948065588398120158808747625961027288266317623433403279156836335183149331789382353656869125791173931612343519829294423308563159924131566444681019916923399778285101471028943257087830654840098448462763103099434629917966826748285301123809469800412041307108112476197645736591108078997526189688290327846491508542435442347537979325096025571014347082841918612115601274952968627162355119293583643357881455459887883545498115763686672729564466614597714777758127190278795648551095167268243190774066208371311171063251149123053047432316391483069430389372868548581062455298809496387876195498150736540033069275323471056612225615965971575771966935034207939024147435466718149526116086801048520714570368555044317978526619445287141729590278318993750831284321923423200435446461207004628657379896594648016616702079772949218750 15597401673527933184266153624126655956093524442115853025878267166793976038479349391769693258213920578841120617499064275959435805625498741688374951015718571823101671255564694799110942539780947721940485644169545665951646325764221892296404444768623185083500845344269618639564218046425222352766259586835066977703019350098025455403968759577742119389500425051260283125379563089180277525099734755413830936190347614854285862835447872365913211362311799477482094479531535855953993944768774859190061303983205224337075595122472431460369027219370996221314816953972696638811225518062600899835655322913286693902219293864329563549757114549406970730194800717977556753614244192049767654814033797907738405503938773860366538292370010653367454248962253358829254908379392130505262848397819400246954204794251633019593230198985415496541827037865437919822341465406421167322421471658120567578104525478260939640720020919883384449608491428235312820341784462509483754383981168921547031993038587242403841085604943481303290176566581258033220822142672331336290930298001660035638384462498052257151934345766042884459793152903433194340931460303096491910319316113133824974154740134693270205122812796087745233030529864178420942255334236116422527410921756438514643860145448626301178413283817156927879361332360961323310865193750702546033787862338193530575836120988242328166961669921875000 1801454570617809896020410653699355254099844452717254054264542114303726759784827808339915018909941115588917430035189355902783600607662635104509029962065123375802190449196636104087549856332542926634714062487351753065435204292724378536131641450673436104578668733065597790825042858549569989570830465851905546826204966275222360691163222734245587916320225710465749520347067036328356483838265592728122658518452457884540220425996064236140130933884421318021460325690128365301955989277561095186884725103331686507145346202652678495519226455547335248213586685267204036622096586471208002064160732583415702233895526334157392941993092836088240066146968317343767641512164955490283202269473316205824710195279566236639983972623736150652934908566763647551003499251633037507973981533272933107807693775559809429318802036495113767045115952483759792651886873182952643363966051607084629801715184131027449307734487298425037628260740417862836693512762142521390332045404991381790589596998722865201527811136600484777474911221748775051971992079957701427000478580377446710137527694797900551551502669285294296391912986533571827206964293053773856909929385102308401495501367376573886012185923791665384531793439239879275363101323265525810629188343147704157857973562318535502737672345251792029971914331499373829983910998186002458214273176748815297187888972985092550516128540039062500 161311950664689461469725746500731777583891681285764527295131929811577002123146815105240043514772386332541790810677926259904880845532900154442012929393312664660263642735571530330365444206930835131819244256266773411397894811247089878679775877219020762659259684089335643053624687740505796688984757608043055357137589506772902590753276145614271442513689895595762221304296953068434676533762631870643623068115549957847572013391188685790597110276884235843965718331032472451389999178504624545341318311674398997251035234557738730256886274430693582926656941090461511116673144131991711628223408262606697274897427276135323988944238645865204816695175497325525274271014826982412829989889308441671305226883745819309173861614487256414641769257543356814156196369238013955741975429038579149747050895659640569397540442390432384973815181550021921668582003097929287900416856521482902398654888302296464264318606192177664092554742058413687653647437751291549569271235903855499480449379875135610969999151359891114014775805428185209091979188288341260609950098426829260642866281377322505251120421413023409474817353023458637705947658061496420420196678835365880311411504188960666036185372339366301942800096920685595610059304318517490286996383773084370807120948172714133319645120887273494721984316739154782765577046690616321666071489651650416874417715007439255714416503906250000 10571121542317156411839875247458649930220459413689715951374723750029172968198248257134520098486340780125049550935991207771497889867603470128000148780186008956845565564056795554855089537569104438174051686022724687623003071236180401962212413678534497997233495391448247769333672986425634126050183945252251419697407224131516370800786127525970049644333645612628885815134773711055093267467649524397555662273428911443886670112312572446492250167276801709681587133035379394260941598477618348841393990871757024052754004495201832998962572728571042899709856418430545134203875126734298548256105704042897869733272973303610032187946217258879806859591245330380551776305100568131778733709498223187862442490387871194874271211183054253229725565625016413567049898920200225317568483340570118958438425161049498534228303690161112184942103494081204095241346497134245812276291081810213141800887201091520811516494865174897991322406134924887652765482072320066808036761267737039252074305129974364471168683410491055830727115374418777811732397230718003030802101681786922391257070179821009142357279926676698175232473832428719050871479668345951571842165232894696868107706652234414761153287201306174908585278671312296653327742035671433436116062585064768339085510480380896694187533878245312017352031622392177878687051476987345855125690176692931920854334748582914471626281738281250 286394281460149974150335052399678185507313614766853412799830660783397890408491935308930978103613942758554460605745791858879563800018910167371327437407625196598591872177876450733507767850496391668875253307445742669293150353826928807512070899828086403212958092579580335963138046607036470709456491553830032931156212788522347273525428227248539602536348972082802426119063365201915867295691089597213127270018703383693412268874169516330256367463133601782927259639570060375209900441364816696270402303090300440345648749299043467264680633519188276505243403476748667096338843383946423811709655439916311399672091392952551667371363744539574950454243132472197740897307749969630933036882394303192448036551433129329813038639382380597057050627554716022309295552905375068885765882660216694384259535443027468060461323538873758012723003371480766358855047410982261942898444411374090500315038325154052769116257998179669525966588997320677639443226615982466594526684692000542584645794660043808498939266492150431750279654933999528999945173422056879042344629081313376155820637200336278535331365020878017307856802992543670797233928337807300411484612399719203827322172497713683400175718401826073484900726183905136040544355951217034596659429672395696859201413717664219074132965386744390599184237546658481496622060665814764299805066094517513874961878173053264617919921875000 -82513371678778714816274208178420545164302933344781292531768817308093062758857896510283447597488540971233502246643305711587908002080380119965524884835375838909467272687623807284007778591708866169095900485768846176436233257311002370566023732689586454803868267079570577050598603426981986055578979322258854003415591110033173991303622489433435442694881801947256282391192459895653913782350307737265006594539744383022625559870752311120567819919641746855618366150097038621825110103754135913416913017592439305928918017630065750648308941163908429500972438228917892229139567866594121075979443998109643640442600390410000035043042204072933112797523474384761639078745794063158600398541449132550291568206835601866374463582020379102532059619336546789395811641741598332353562816794224109760661347815622660422448283668867211191178837811646840757619774261880400777715931809726061694765886422534896530821320936509420028179356229402151502928361423864745425357209767649810485329796116205537364441594433273316973873650115842689026280089047110824703874450202109771057820771659726566657604753872207850289895887470057820107808321170031276461529164134697457001028987040931329573962655311107604672068660656751071617174444541985753978635417025492809765896898598769848300092768531638280309432551129219167732494192387979900179563463868959161118254996836185455322265625000000 -30321496411509777015259028094455209657423884696022027216438260175618951907099377643762552575992016639818523480971048088108645120447890092637314790840099083424108552754211831580217039520093427424513257959506378648961144763026776182765771508437413713455497878546265127274946170284776431247210708450395035016577732790341578403299378323193706231355471197352859111603847482499624360720148453177380613492330980221299633967858491341130890879689929557840697981986133615239713200380834772345701428038255624513648141462695845478156312242066303961708331123890931151982088110223662486407274875207933476159863347499474474684881214410877266718686965446677735174617893342146234091070910859490208252565052746220065425256173839181483710866983379675622711118997978616938538882399893764970648772282295635722129498881091949752072036053907211816748532060331006481408252843695276235701936981346836039963539437750870476452461835434131930580825581888948652091404204518116249625755660144939438289661786156851277796650364911283679762331134311876541315295168114588359935521910577663677580500904330257262970853157921059558702582881384579653731818120168030544156202861741884466090003015379808608139093997192765219576179188856465042033772711066922052403504250282887830410961235236433551350935922927347844387458395066598473667550221744004801394112291745841503143310546875000 -7539952518412896468283091669167504415158665765369177508834181932641072432852717966178643907975034183694507566798040576705151867976932194237656939368202876241603198523368486893566776951985685961166579257063058500124563232858499200949885575564439757917511865156102074484830426551639988488430759915306284733398145890038459739188801628263121831063295926711256510660816980717667501026187440936829007210112681678794132582061665094557245178028041200603128635839712553571419445315060572813540847552165147441166219599742192055397092027315230546050063903293484815918746423672022453108474016187669217683557698009033125211398836296947902104172760020545535752423919552636348542853296821842649908151073006861418298597729044715494092918579116343005404956487465778333458685408235957274463969518345538180024143489011120346218494973069338367424988052144877461222629106456867720738494014172497340579637590687952705553052094895911883314833286042179236490162949791421522044660818146496032813098583963584839867734672298472274873028447280765216639982044754847781408467599427729047582206588419138162089328267861383011633112042435043134756967298098756910841476117204814249381270590321595764969955503657267744545103923064795159736238800019178662524041869817709945774044791466545063223624539708731347172361726332847068339466445677232719901894597569480538368225097656250 -1495221976505905725305821077399596566492130151083107714968816539356147106390569297538013381438413790372358656648873710613491380908044598769078529702984151726373354114546804189480906912211108182123726661635731597231963455656515601596746440303656079561572468100675455457243795740543864923384325714057230329259968956836165884842390404343783058969723932562176139022681512683629763373161444156176360975700765143591294849868584856380451086705509801659828394055329163931173180054351626782200367260592420681057546286116723149771785819692332913594470029511138924770462251938285853756766642250243835511279705063706455905710638127384027531630698500563438532485914538841649646525189876372421513721322649075758994432784793814518797861439700771728627638988433199023629045900790878701471734127360721357671162563622962337861260183787928877280084344814446790002230690432006535328699567298509217250831044679800253034880974227088365317942955251902947074867800745667030213258956241304058381477525782514242286905745503541519376182944519719176487487356035997121256730854115300545565656073683976586426982520897270635556112460310512123884983439042703305781188705810693077015458757782811005463478935322527640226687441905211378077658338156451006010579894707324617672805342806262546708273100447053153782233101082799262541598792064512224442296428605914115905761718750000 -237634770988780988770323449428524376428854502271336012290731739228910414333596779211050081253668771496221269967305377342914805152548948534096395368493326836410027730168666309742981230094093796241205083794491544278165967060967877890791760581619174014535102652556504870662393911652566744048029464194713076535333553240661152196124409458674353705976580304723678696480049430151840354833964792333942450937067531194496617993967758465189589805406986969153010662331208303065930889346265644325488578692051636963611530191933097559550343989859633364172457006989394291354720625717371802391869990402739819275626356361131127669861017215990844642536995122234004980315526625388996443775395867080393275202835266794883438360710688506149592304658799327306415261505136048877385299085051674815608078931659251684522496632734488387281388592081098673340370309904769245819215395547006406427415185644846734738520031776570625738075424481405193468674574714115075149646424253390015312854574933324567705354425874759021518766268149175658690358530812734660100232171473602631073268434055795335227017656443411953016109171451738993148594193191959984918712860380527595712671802309869759933013366485530791256721081925446784254328981365415357138074801959549608963955646054584580734889609257230237025522511576923920705419790542698724666263038196589718609175179153680801391601562500 -29809852883813707901390953895428922254674298911703546382300173141606271637926802889183820348118524071785193898136193998704322147931659070559456759504175066559826340510757052704675480805320189549170861342591831331984731004230760675829843690801335081072492462295059954987050736471454277881868103465124997384267833841512554703589169078674386332846725279622318758596143396454732583573101934087354842650090260812062891275688081751941810261367055782863517585719862790193196491617410762874496474799448609094060256428635840103756699057618193826595683616263146477992757775281275739241190704909730251022220066401188583603278140325154124287536395481782325683788557404402214785152928567383582973229086852536244692627657603539171850930678639903606054131994584166534785009721832928172546031869914948599173926674059134038818819956148204302127373108645547084201419849601670575496841506593229286807798253647132472065277175397718821287765910191507629134524132013254297180033788922758357761033978957170702667128411173931229716895173424929421032162690014613746564461982043213305101885573675482552483185813669902213159778202504840717905745052362495024618713964604693648074037464665047829676103738248040224659147495112756815450561480937732430453982574934157761773078437237660511043926165265157474523728959064664150216926452596766239366843365132808685302734375000 -2821827898512171081681541371721225197754524235032022143259619398234880842569769895551485146289217999919172346450469600070127263015743324225447742118360009845735471487864584771617305612698872951078330384202193874522610473447217806779302632442725461738723387108036808326129485192573726094556614386471321504989569428692704264655327797406160903505357642256876420952224063206093426093705808977986591501122180900605104266354114111746377178167286556589748552573695242610237307935541156101217471422061786522470035362202546489834492165678467576953573531265754938861873933827506978110344716783692579340204366741700621271466631470639235197083060596943291044704520119209782941150573809155409340762282152601853134218376777338303904094005658116585824875710380982409251267519611568621743006588031820024067615372336752589587983119254971853435864596349013463134132761040765285760762684221606142254156812467702915433990618846268097302001527535816811814092219590284723033460265638502529093662103062034772206313880110683863171790027324263503596987821354645799937127679391606594273839659306530253283669761532074193576758627419360808622863153738737786728846547207985164277384043906501375261653413410457329142107727016992721268545926156212959468103790755535941389824955906907108251015286395328490214568919480778274574755623560484707468276610597968101501464843750 -177721778893126753223157581981572991438832532771789692500646565154049279536446953280836873997217721910849443327020422301493582568611614638974325188006194421655854909461786716205426366266999320134145028731602808717772247315508894539216000115332746945879084451546131009381455587514000348773794806422423993289701825730599925968613610537979035783394893505882730611773770351311670491008703767165714756486531358097647517140086898134922918630755456753742383391517274924586156054346172340020830598686214564439534593399061907888530541044985437631472858459908467075418788923877092404689329374385487366692132600987262545589150809207217313754666871169960429055617248706786141021120654293409162518242736519569210607835376461830963282854270498447310993137265823774137155566342358405399380449492135352956917237872608892498122000845226826947574739263772517622228444192940288504902078541790542940897819883597806003866826245542411188448241831159298767954845151265675025768451685826485600072987231823938815274821498141763709899701663429111629509401688105732108738490328314826975310602328263681535898063217073460983308404122858670586844258100270137002551341987694599074090822600172753046180057019968306030225120277298433881130415318833908857479305404168586312297227172393066826146143518688204223722213702656592265727297785815608222037553787231445312500000000 -4342294536379903256891088907835474142265680200051801543665253379649955715170774740978398024938812513272019773859663104901015193396044014702088095137648386947894161506954421375841290187786289500463661044487953846871142300736717032604813120850984346379990352148593095501012224588163001506011186577937697562172696713167822531753050220191673859326635819572516015586216308097603953291186113056340915559817280133937535014854777202298047624608548713289880783036873475399308697095940180692334319641219189311122181639798461608412839300189198819331339777785762045264049902688053960987991831480723920186156964994658633838425880479053005206442796014712882499361287648280259782676606514420454397748546045291720896360728918991086314691219659459914193799571082598465195457910344397486743738070237776054212495658885262608967693414141207281299678192552897309895944459381750393983238394106266718569227167779900808391898646554815229133721644371092830538298525410006009277870363444916922373779034971412310246074106551869366740526336495949258826036348519248346974073565347732895790259470115642903672668360456140236533900115312920037228523660025673306297431417323028692350161868597446356364829034673134128792132601355770253879628852856826458858507245311307250239036262195879793777550025507308373838369446232987418354820619015299598686397075653076171875000000 243385494545225120793974371461517294952555326431323579194180633700000723897501839142778706641525324926901587862814017030794191891760713455420415637874636788239122272739492801018434123432961649003921215285405543037518502568853371960723145022191315854548033409151210750520727107527436352282956236212426420120730758601834066370745142061125083187700666543212862378403269525653159843879326409581059372080581912759604710294147791879889574160846859521231946992428029361689005092719436548713989779720942646812560682295241997520590886799309816056846161316360253366823986339358961111834244748525859170529137304628008981876503958388562456354035184815061997073953936764043524762462322197901354157327919702827913499037268885679179912695151893337219455710165166299970819826778620670094866225524756982867227325202848238159955966532452401698161254567022560863206045799452667111837380947483106823800408443766799415392574146116898466935838226129159434471711888725577541851372942484417380837556763574179457961792694683011228032159427699649931571735007585331435997571102150786665121552935045213191031291785454093708865742017311403298183389245844913128431110670897164995829385894562858327560942991500489637274974606214526628593777268459214313631001066648438816979491106474544855486640213672017513232919653110714053312335636292118579149246215820312500000000 29333632989388467190566708428847150751604469876591968938287559210357987185837722877464036198485648707574436572215316108537861206272493321398590843883585212932464286542149248440563223064073728267272460073714981888058050295612776097258824972021459370072567824512693626806865497488289684317187654573383886694621688400681324988954746038682937230325475779966307935476805316658204342325920246319576636386686737238099439849482860950438541458188806202548502182766708437186340026579301360220093081164801882091447605693287162014739078676922093131312175418045233890460049834436222274657392025893246012989490031997538513113012886385551668290143575870169920384401306682134039856121508999450023455534028180349798173047309179982826836174276830877843366583502623644168939899442356933985762074657661722808218076160512707147342556521599096328697100796216960518649925862370314548609208658684101527427899280010029246305050025321421896150224558717580961040930279200244388302202889657513796602050830902867166171997623529614618812828033742449267176249355069047323366474390792673338844480998925581262538849672785065863030784361972098856539298599354285432773366218028562649486500528589664807761886609405038789459718913650608296772166977941563192905789416273283996666582908005448136893861082406292920240555310946794576390517228503540536621585488319396972656250 26698167049240413571678186772615130077529182738090833496657325461002077723001894939329169951312526992005353390822590390240602266574773359532440454711574645223184914438286203303059509797844916882907049288080160916822712065848105727641010377591215369092184358756118823708243556548167603894953612064408877917005118267502769343802463348087388059383926571934617381280650029832693262568115595476902600668307367916687156851384286481873615055067558240890634941074920220840337580732025932578958768286097571983660991553636510054482103045854925007011948340218247504015228767495360591271262997916183484327536507179882808001561893921260139529795748354759768198099131113505104033073997715061977260557856896171186706595518248285652480011526270677117378603369837522134902474499295724126756536607260750361751579730801470949748525303107856411256967604410819204650471940822586196068593737711707281062784723730019407814982036183997361135085925034028932471894021936767101326761629245010437189896488687923348146885954279839530146568523103490354387634919013507694100181648212696103815784445915884809217585639141515039844834877572686560767668236958300832372458164250786913116501024142028203896233662026256465766418740544976812751328501421535497867139181379975818223618320458064389266601052922575569047331122386431702386833109130748198367655277252197265625000 13940506257086430299238231622845135555892653091484005711806489307472262701375960750181334840055503430656388732420642189295782953760200653326324530829809561032098282121723247063817197240917656000913710920138234074412066768771109997384147133121101464223080723385465302764998469263123688989006444374451816655468264006596493317465091348443130492720607508637463396966595887479402810111338040596976325130884359729252906446556391432450053915080688109998237358222757243102346087299394060467715455628495210438520698288918329649570164519844826992284371855093430916571407169758628293359948251064966461504062355028697706137296057692577793217329879726798707589018779107283395172613951481480335983538137030129720409575554288374080663189841788609762621941915595309196971273926281828279250585771750625684532711129319495776027419451496503364436277894392405271482656409393959882866080549331983875883650922210996724950514529869319921128014668315396073141279285619596755896423333079806365736141056962552370872710576670800011948509346607664617139577442701554635570601178290605789372146305227217234778475148442161421032882936782288484706001288114627680108877756688413661296413037892890171845250467571442538362885993080752654358812380523163963183441198668702650149880546158763449086156684668321959625435898674457920604075056303372548427432775497436523437500 4140192133456006615668095993553261071245458838032238372702117798687821850744633527882536095392436641934659716533411308380497615744467481161330509201974706335104150916201881945310220507638464994348906479102929071091294875147035684116455229751132098132035739565863842566471226570340824775766131568432566161515702571101440248012497358408982477837416566857395879747750264092575963858227338176985225149226434467149967611948012304827797319287414500257911346238122257080369416040259911869291485679782411840279547148071944724469733450655295093070109996982717051050469464107012155976048927457819715066289184866447627437238134467950501430180330708504845266066841295837540721937941913452842790482455692116513435950957365915241267835831180309913559088814177791807907187437667560617828116064470794205452380846281878847799035169977899621699875459134628567109694974563951791731246573731640062404333569571421573525968258773558076335329933261814520761130248298228734285175885404498347163158596686353738247238684126495999626278173671579344819731354834017277542414510714496261808769819739598458689784625418040265906430849864569379124973509961899289667349296901236342617611284219232387656637334695864988711401892307579716793016843542948924363793973183163177717728367062101204535349797670186614521259470240001701601961769938498036935925483703613281250000 855054516484104973434459947216900023781037339099429831452920723686544543102742327093941007108397487127820926483812279611538119817576123408552220363854711972716525096280841647145259640698732362052726370010786687878706554652397498845773997078604189460570798807919952164899573641232174645695978572670535895524798558871279261415738061507336874425413572218186225232961616126556649204051602340270610289035844742041104329192859035395694821686002476783703133178006778886594978260280561774578139007197951332984058870412566161732407907706202126992699919232541115286495599806623941891194624535795116803220978146905351749232482007256121772128299718413883416582425392254561273168586962821395131991914952047837459549499239077910947944879156024703446006601160108422762317981433808441344955302015394748797010525940512357114359718986734416024036291844702745679334600319392010529838686970878966043186474413163436852685719281656976307658158476784320220383609703616945768852505264913260086568355533858406257477084998121829842135861782948131018271543754050794126973184493317475041772195190378723067525634637699024515571613163490289661227191532534520265877697341690449314005372145975786132489424460220789797369870370483545814587696016448044059516295087450364994821314029273195544793407423742518508043907183565962223936729458273475756868720054626464843750 130035122661968125530544301314523687214751576115935389924137604573714046906272835584659981779507345925065314153845636776905225815437982569733498941244047384993352787918171018791994923076121034202306062853594043931179374813173749692362651577541796051379407429769536982100360054658724113362171030451898406069705098960423805045413851499407679982869335040607912644942562523496759656313802701502099777653874476904890868280115319038769108725861916205925525264555411279956803831284741203238944474195847143079709827707055610825203649172351972945151982224381474150008226289329643333046279864571525377098633049691951053066655039858036075761670928632317333400565272509144269262305109800505090966234610883964450153749492765411979063195632361552083779367349783772748484369054838396724229416280305961683089626605124842200775971286633839955191106957845861589655356847161383541498101478713252027136880186405206175056338363105502219853109708249942148893929047669109646694161651643603849877537154553345543548386718122358294163144728427281807420194942263368504433141299466861418855029885179704596589171212073901253572685351631647269274236935948749604666266730313846752906612250649192658693734174648538598874881285931992171390044955964304413645532698652232876755842043721772255995877570763656158315750742339618473142337506942567415535449981689453125000 13695025199883945279619218545262792614199524069883624760034198284253633248941821902025374862068871424734689938362757124701768795116216549043665953406975346972790829991713030752416133900776899375310485421359463529867907329601783822647524487046900771970087695710500532090517947975011498554512641316922008295592264336534228104218018555925584238581955342466242635119219337131217780382155153178632343321230961551528502473498312350249239973094833166357165645617979240519442011348194250148951754398617504271910517109483512769757640402746539354674922021389189348260241850021668710674012263249610558056614776829090889499287034459721945807578791556839538276214343660233254141908513602910991786496127853003040052541445163817272426001519024929887098877102300705719323460935868760099102906274559797720597084414756638209040827873506122768129385098467196180983086317389232800363840274124775443739589297368485204050945938387130989972316186802320830862654962156733767369565701716298408934908717883773292031276146681605012309129058647065205686659853514647130943205285608370311920955083728837749152909948853440146006594928413579364260749545384468157031810417487644223673349491249779980911514724057200480134074615635127833932922128945846770636022350968987026934614833927294811709847644132703789881467452797803030506429422530345618724822998046875000000 548884416805077640214008471999666677181120981650980110703152931157905406144913541665706584048510448416711065833698358865273045914063725978823407395759870464478859517381570265846576381828736213114866135759907329445746107243826854456826731377508387429215090066937315557179547864940871196521179369879276230373707930001418865153137054873052531958389507238683080343265026894266725354633768532711684797354276362375548181848979945619679853717486595274884943525026219792181439461629099957535580803014508177004696468965406053100860062406846417157375977903466115368423150189253356637184624498167006259915212990308197805192985324744125287834203558969347604343474564067444630158643919515960165253872975387270495949975620200672844404340474265397063766352490549539628023957367050037902848353065347001518090967997336058773828153887833405541673761755335748194504377972996608489100449635027544100147180084702490173669743374861307029402572471277849399930961606813337316101245669154145760544611039818300843992616457736057947559803384589879600217150687070477150214433678096981699725129069956636548125034149568444559952427449312610184959794102968974604141128558476998645707669253126399064419427715017877732180010648253620624634855283570601191932538584901344940697334190532224334229166967542648808779027938369032835197458553011529147624969482421875000 -153617472731155423431147635184966723251288342322677186326902134477665966524665822613955873178378432356373867870362464095842392486844670834625947870797425171320522937740075389906822901430126937022291861445521170211526389380356452751684826730721981452485407693103569554386764729483010658835108611930589649606822500410401813598726284845068493980959793336285069868600747991061262224400930469627291190404426909914653539516579431577739797447627241274940634910988808594184362403161630403240601401798579944845812486474966536356009181550409379546459682948886227970711342842699800858301179742876387713726717706501267629655202261651201738646261780943339196241348520525216461602029821153844758049460258171658374310613245334602191106846321152982050196491096042220928722977701894306152763852796635788143044781573190239063014555783626461005902585709744872992478087403890205109589804950709950250815770259492026456009577895281021557654826985271278862283219327073590214448138376138982407561556898844668384261918739078944019317574874553084023876440114211995309351506702086802720715531569276189646186074713101088478786078807909869647735415914828232845235375322590083384900723014514146767055926553114649387181178828998649760800456246056925443092423999406400656542752146823445992723330080557681285405724757068754438016355834406567737460136413574218750 -47217791835741694344141519227201882432610703039070137507539307835872643201831642710766839696988028308408299769391608350015039241441641103215753739221528045888050882350722837925360065138022079252110677409910526029619692326152927828558386496202218162641593092127874035256831989533252496473154334662078992015730866923708520101900085207102348441299553853013645663236576541995824482866891747651739899745873063328264110250626285108449649650883989422639212518122719092369697354201236719457803951713024764215525911366734461215632448827360616602868350815718288314322543953365607454426177424644218108331891012077072717844464521132416390902758118244220592868602267273649571490773887188267867678067505327995102485178813089116084815192686810413116414552853934109462499304522328032799857113647708540337008858022576678375722904812437554916047618469343366249371499062340063273365670770121968129863995355524085035913000291165983330711429481205710370683454499094649490783438694592453159012834432047064628727736387788120549264607281401209010806351417531082989858357738067616592707407715959944274135388820976727392019678070927749372610983221252142195722596663969619303534831002474458275674216197613204682818660095678651031532933231273764524166839525539136126605653577539875019319628124688553898849642650667468579683827556436881422996520996093750000 -7979095588788958920330926569638892684787513307957384642928605399334535364378055345817192581826189849909627792243680405332084018667311702627831009689879766899376372899382159920712280013636720639593169603919606394228233282238252515143774666806375371508781198296918353746803640684733473819692672990453552939939999827940887938651693076772214441053525463889560810908287066742406469730062037869656470025909147613432937463488924604695064868255653205642829253141996672636502802675607805863633357979835101725193460844761454095773775753517841730539925410668559282115220701382213648397654729529194170618585447701793565530115639883944711174383763134240225385473047164668863317284419960228987315703720227006762585538446105591177995944705781496935305970111471400654962953362190143992369627006298390362779993456995262085174065947071735204353864133621337546632157194339951847147528746509200634708818486051850397799881023797141958067088089994746602167068247155125356814799467823756911122483212771454702388911530610609803703981950726444851635291009504944270326348205202021402725154398921160077839156003239651168836563400008203087525355416227242312512660627024466130486791264588732025316496815187575020569711463014915569250560574022292342690675177217197599234238991712954702138657161649190996001802572614586273047621034493204206228256225585937500 -944430326726439583407082395684201016892512700027835083770333614768335632551015591872471838194196211267252790295003968125540065112140190549883490041277365131401268916348328107455302203801105091422180123962453788244978551419128625705973120360724291081366873749277619657647629352462552892865053104968933198545815397572843083029390594955618319059585419557795297274775661702535856448659702709073100253172842349820007697392653645306177644081791816269207540782630321926901314961285599719480766375217671871885748962160406467671660709932020100911959456033507684867234055958864086416366361905028755697356251221335333619824938244522744623507556336012776145856899402000766166685092248015658533256565214780430931435961351177068865771724295124571184866333880032110356366825190562561280567204219296451336083242239135811973458238404811383232597260965746241585140631180858611488677704109547387543006848366014826179354147593800903950226121443808182178073527848103997339056118330927175792126923954817682078569406380804926382720429809086860480184311701569839637912192960829983328651206643417200533661242430412070520653507576110236341100288056355147640702653541382617777672205359673192371157571654925779575769127009991239120924095370521217711220758595924637830959632124524944905062761843402435246321133428815119970067826216109097003936767578125000 -70154503125166142802602972235736637580653581611568201005547931385055729761236818907506162188055361070935278017501839307072095020149074041368180081444713772193137523209020704223640206797467136670845136911567781581712251339213204230348456840481933049358903704319033861129093462923654856571348649763345737866754454083184276247335481922607331507349285861576559203572182559188088743777042430479972939052612691141067558794974571546074926219129131509144220445642285575001718120786791545749526073254475000194475562276027179583316563389195752229720510277234297842698425655173572393112807520794109051817005932684425822919998685610619065467694335604509373804542210438799747618872666463629678092299941685264704816544720844334960820618359501534086715780204277427604235564161873956300235733971696923115918623730551913633717841492460599450977195901462728720836779547294746390387964187131404152167144370333552840795278742865287631352093968998825940932223790750436979723942678857629253067839713632725419113129304510947617285189455613408546925454407980582099294691253734975170449263112821786543335423467284839357649065231108678480558696784568486319504947019928102335370078774361811646795130365776944191055127948060095926550479084495489719825865135688762943666907341813922358599241818447942146725633929052468040765688783721998333930969238281250 534334682081297279347781445103309708057296652088395992292005207891170962656127063574055457994444689545509290145013589296599450821607317485502406181868856173293031153688789839114660960480101036342701315229173109118801356181640439778463505461312805641303927627172793912321668844532702091343700699448951813352125449133848320136915879793736501033732209896376430152511739630975235157685768866547287505846195073262223610696562494584458405071197556080026425204714196438332132620065363176937549585673634266202823801038940983209917889388666375369588790157757011258090474843992445379413960708235637044892511650540183134823698745968485884099703357869997190718998300168460353729878729011521245669613897094580696322283221406474965529263395519358430232392412040567225794103247562775025945621123560160468223504770702028412223280113564401499604749881032698004041578366465385966712190882035273861018669238677178970815028406851404557760072179307113587718201114142348838063569195113139962395334430029223463632614477842964424302911585010981432030505150772401439060914887790773322511449507374235159550987864555614668290362356365380661149958193440865762083366382631006503731249175260252899728126220560787926560786871667443625359483840992103517177429049220802328238015098971312628983503675688255781309199399231602001236751675605773925781250000000 1234330226789364457024181933558368748800011320135981309784680039397511891010304779518473580872844427440356357395686126605455958991022147874186718193664931811923878889071424397086172194962197381763015736032343214693938433606645907377780266368485800102294576749990608394325535209987675418785917578065040901449123024051178312327126126368623822751900483616384413088206491899926464346490254257904125038976010339452189445681848846068061798068517458011561893647637124990979289804428693614195608550806342419098532686721564938995816460303322443054146454476904375581506363263123703807446596981441225768601992579521218461314507589631936648563076931882762920251464306165794789681411213041533040027891200973495871810894799848576994107168469093971110697789678297341203797713394473494035227883286490743864625663272617096446486534895190914373488041091113137056503756860101119710506407224582425531317102160320788514707305978051855958453119931042725041756784120090942275093132955648914025015528847952475817729274387330335193995770633573594974901955972610729103666429596280707763391658796175364866878649937789550099952367036586374183682543770537841277275200140461509098160817463675920173545019577572130807557984123813652908830291074298730793865030694299216241350592111652876158650294503178192987574712802256726718042045831680297851562500000000 248357709349545054376448365818515494361251419672819720473456785997416849542065697449028595615555489338655082272391827201819118190205253482693385437869266120577686720623571836205637581122514292950233897647848205962093605097397524257031401529259877082500327668802502034822637131922789100974642070937606171262416723896970686752246201049499460224163514032358349556053943144991072067537771777076091720113719618917918437885351874065457006665618249821500609844618407397008948443830678953350430368366168775767766168014439097789194998375355724387435064364267517027736859901900787872554505297330309677353755012954137270673716008054579007180357063946460278479003205315891578471772502115258003887321110710292359520553800058529805082328258033908357468890188604944696778125554646634359753769301850597606141848394639070399866655222286562639260796383612948632350545851726532096613344837372144250520972656761077891106656711794210719372107967726624724619238920727555465386898987161687930504991084029822294779099757771218217943806082434730460915999157520979389799426134205585738321404029874785311938296184818360434383548151260236762275959755103780203249724125546883195973892929633246796215334558344039237051587306120869207449238777737441990106749187055198762264096061588993466019517214149562320604780474297967884922400116920471191406250000000 32332049981914745886318123879037310891670271067784729693728067532737639461865842930484926122634505022028175405552918665520601763726189959224873740866412813698138932954282481328478794647860505150787417798301145899630445324181178586219434198401790622713642308430800471777227229277022811800017403928051644705745698331045764529437622746734700758026996503601346680454246144466177451075902646524963725376344182131057953839911087305528538882707403940195126785619365538588390207743334813544728663506251073018409214714259194733364660566880537599489793160349198768939719555989884062618673299578477846110072041805561461341927180445432777667932903872686201034011220206206777764911883916137692350980362281349124382552577785743600587597861655049166771468888010682793741284744322759929469465401922758666116359776414910117255249779245950154984781605748427270661187317044596955484667149653667190376215132953185995049651684903144251104197790795607401388732556863373348113274353483470887113720730976136520011474869989734228061003162367316290363517001056001070347518076302082397262143423149299706273146782854752194365009158796381508591854076461624145518949471063936668831104587102374080135217202647448915219724515959182108619157785409034612155929145012842864548263305827810561217189348715814402768654184372465465457935351878404617309570312500 2908100067470274839323970727130295075133169860691871949083934812784518308750343520081718617848946987613305742496528146917900609391389497577018985443083529885722487501749269156650139723527749114737345027691887515401069072881623042668665487443355879779796116604225016520529601961109888727899920723310000879904710083288365699548513892528784039969159800412427678028127763752054822755267370598925620341772452827217413165925031986989623978438595363585736036246671820837840997345796265205473730279169007951232420577518445420561182117856239488375895490448130402588629115848790597578966253241735881592537229336840082836318751190608173888394325367387523625026351851566640835282938101699856371173734424750155967679664020284217918944781226095234622110746250260776396795315230597721085260799365321765403075548099053055092120811421910111355402656497155041757495802121322339858032918843327567919240179821867869520088104736366693239761315306405311130954355481101318415656963963161441323687599262968456085333338687088639885419159955552516070814876334181704555933426519171126621914998438199149054816193494232897680065388833318641755685658463122452194273705155345682528318151248268667158401516684261501805413735913874005952112498602263401170899161253728797020738186983628882197115866777010459486366156234282698278548195958137512207031250000 121507369339495476821352364543960362204630226751492004592888716446603355349222337380753604756856329220103556438766340420313956739092443367198277193759319908834941276133627264844656137319382946099994772551535380025897334498345756438166374946037483721137966436174433325391607476212671516495894482759680032074140485224705686512449718932106505121360436814886345896187084960434392284202533059767723423563521105156375126416499402900455514989666488883840173808969937854496516793475582895759345806583012782929915489439431795704531026080999723026492896557284957454023077910572665934100968924032199839836160928837166863337639185318148049995448507311843756455924257445157817056802514141557662339705555183269828363555800722306618545840600710879040343647122850447444263980926288038585492805507911206938075879422511666759416711759665761699940987240463680447412705242675115183457414702286321589314863332978239625645883729050600475258746016559283795913848878357163101046431498998776810509222123965395276130103334743225221040114567116567987692981980351354313564544570933070074715464728144014286116753733545741225840890380444514687128847217501773536649558342974663587896483600965362474955091343247338436277398814382396826783679356393876919268994281129961920467452545306915571577588365758008990928640269402194462600164115428924560546875000 -16077409494350716421968412605364916183528884756355783333802671971411707576944360164413670144689594676828222161379121929667189820565499836671253340608113234025343111230976432594545464179984273765009856661722832480076232217785428527730347266137349627264758315039150213673832043166870765731973644772723245122183071289253044062767358965492924069083356801418251581907873052415668179840706383047511048476256948458078095785388134194661413172803824609840714061388768152847929311115544391913141850529828118805844228793687788315488363138270631163883898542596456463789701789702665407371023401744943383673895732792938344895218097937971261560191226752311186634004190497213853304120305501957255010726199052917082785422662077187621733718107889315080982450786261247013810415813598978401364356474595078537681003709916097124552493026610469893410204657180321208235452463519166318423846571754759080008367809803172419912588479601994220292457845137963838707136697468332032383023297636920215157695304276009649577513740542512218359157861527223104303736263243345549309003661172261688664363768447134426480683970750740618352420214837726126855740785978181360853591503562583738755880548048573749846456740686062364014747768654917942581854687438923492223179536277418718491113302054416599500801128315842589838746690134030359331518411636352539062500000 -4726489065287687159408783425931461700296857244449781731621467607022294140453836355919496615439528840335067359818491138572342066116450813285535754968897949348066712739098674222090846826902042137463298874962436948811950196558230397108845471015185472998347670071005157134562375286679609542020278709156738518517258692435796093522502634482215287650415820858578340423785856090100492230857110715562397789399060835722902276466962917661556688493971629135497821103469278498245603705988018203573165948982189482381167773438276244416287652800552899445493591353602706914267031899322742115612828460938804522763435998164109364455701282494411612335514309479927318530469878431760975043863481354844603447564877889752166368499852100251068704111007437912263588226925587763734481021107928565931163544265567545922294520154480124721046337762159854265973109489782272524104249584912193771435201352942611300469313548386642513678174958395044996381506589058168638044937134604226611636867522474163121167268449131724878236275743101842998828935163055964210875746274535374461019147831535919135486206182707915917198582267037883612417103118622767826756998664705037845455083528963654588153950578924417640152986866075810847251339675576799786609301482859192347310143858732714584010965659744879596107056025560213836228529160621292248833924531936645507812500 -692188237535740483720104935714116872032534237878211605039997681071908445510137056092942843489163090798474496170324305874019554522802085099296376780480189314652960596948060524121204474266256719543313259311419522079261558223478574346021856767550164981849880514111674295419052594524757860794980839920541333923102973774574512623222916057736359158200753020808957424588815644739006131931315814246655636654425799503051241076011086468858375133673881444115212422294946733064642206831236183038446919384029412506346306670557973557592531862139364800261151691646353194853179196546436814339262004298762562900161363664583966926259061380269811685775339178291236355769206446457656850091630990711217125954794087423818176548498777932986999899650360295635046621564641906078033328990008997642061422387684695629551131882458301879413215515428405680927977635671881017450967509637776394910889764183215876104205238790685886159142397797478019760614384975219987455214821016571858857358375555831281158403030838707545259755347586856427252984322671842988549885967583747004827988798760535755443992179796131222351273888086876349973264778045777137838790965965455935375246257386956631883298797296970408578341936485095930647959063318879036346955974297901505371325019995351401616009260183105219005765973444175773177100552402407629415392875671386718750000 -70437330193027804987609456923800034089540756258738380862231140775994650009361118697834888681723671473609772914458568435637010702772673708878435474881883781788840749261335116450163927771818656333560421942575548156072074250959475575026123532572540055357726473166593710705828713948701966160582388437716603709669301723899385188358814138350762435159981972145544011795021548188039492583292526904089200063116049933558600980793419832219683971489057785625303547022697648704587472433661201888977550588817674984895858537748746486115775818253931701273759575051541394470005086409681159343274553621083626455834556973182669518461979585148886238387504747823324716670284958960214941928114316275896829426307980056766130798151025779384462822084183722285668752998366190667288996145777267131960684385982983898484795870932144363712099280217831750905458410615264107160961331478196643909225975113562304011044058248900743763635688315224549999748809470736289545785408274947637622908586770867017833677195773522985469159051318936749420182385863261285202112980281496122204057231641572348938732479406916798231418994333576118627749641253459974184776834277315099070635869894044193849335663719684060841646796000771909414782239836119861313516436315558191550578811228826060428738533417405139640221398253557005819658343170885927975177764892578125000000 -4545517571061252442052116190077626762428688577066087260626431102780888704744094391443237393408639429045885192920439230751486983244135577013859544675010282204300143749842317051385483695138996106967044269119331532311780512489299506810822849211440048836440191464248833335143533683896727121963227829232812505733107574768252404003153037991260069663333560938815617820322822026120384606691897247142613666431748300530507780173816754817762988523187691224025536656484114652015186842702943187809552183532698491056844961105238008965336083555560208829386266895957620671816741642876371686696777374704230325368535248509577137732626346683544167727923209322509714155848330031613863605719547319983703930560819700831367741923630909604296705844241924127939131734711713920227571884375704142772328906004829204425573397009664755221844695154934202662055824447249630247555456952825217836051624970485133493108840500209004367764746038392459022627578559382215614018705639856760332210305860437604912656266427068937366902316273660665009178388505029210520595784020959900250693918804972710382874829225043004092300061454510106238902447286980879092560732078479986710710316517451463463631524461821344693248490554918818310527399323886795607090909828329380069444928887791117929769899754785765733141343001829162706606268784526037052273750305175781250000 14264226727130298376834602990673911578750907335862397026360298946445211351890659858010539588619782569416706124586945765313631106101225258625453778172656319810522125773548530701355090924539039644422213744011359494774041096423200456244717914063117726488140935501270603413834920314415689895328577053922209498390629145400443676885160903505201883246553692280129101659388555443371583209521878859414090016742961433006223886961134772067691410363325221670120618821328786516845234417614925540889360812289569865099162360437688054494216305932219017208411042794590756509513130591455279424933140687718720742531838702741643665282195651307938995509468756775473541030907061988938027015696157390368450141734995777454864790585345673118070542316082223591503666800976850033359079862373950485806108647001636426045973277026941254042066496426684093001889627196241139305916763515951956206698072048231317872556222790073971463739483277516377180091897791285140340704804204922132162473309736440663116485616639438852297645713281705848303226583956604554473297738368659223779171506964425705899851926806261761339493221763446475599410701155159145518817677476082578242334170655822013538923226699684389048511973622580086337418832398326971145109023262217277798637609354654082434357669654019429096848671728679086578850387923012021929025650024414062500 56122930592396465140127098015577312012826310839683697023260278286242807925512524658987073709283239926844384745220438491174147083733404156635851655260052289121410288473691557571962882963559212831343700320781365662025364374927391567385214393481533170488965362184579504047856116529782710907450457992502754050427309533686407708482235469904276587889239821834015871716500966462566195001441799469222089169942858486900391009540522197164238358421553587547458244049685360070431311715569479419667980472448289076744920744277068983305701463463140647428466353963673582340472841589499922845977495990036441653221543558179739679578531642407398936067087425894787891657024416682713782381389476968409564596028397899719387833601896332391005393597128010924947093169128525599719747763502857145747284729692838916901304733566705276855705430843867209358426495736476765023515943277383594243729255801181338609943322501825432695557393348242901819736520768753134932677893518581866195937013667625304589221663125939186128394788429970491113096471016841010238752868839445055766197790613376451852962743690820953953623301458697663607391754090414781507170610854772970140083367225903140741540565365961048317182139490071425755417166421746995525999615650220950532966325914450384917595039016950293194909815241294692711448988120537251234054565429687500000 9911823188417549577607953135646946181486508948706653444729915444003724044016088215155055712772391259039666161543483079668040335834542624343719736036419594004231693520228762004327076180071358481768776764411531342234573834658085433292323520129986594943563751460470568697975652731598463163371845131052818791017856049995645530609847111949734024188751887194790616645113538984287856661476946125600211379332134948151544161739500267280253103352630571764004098442809275350845085210950453849920668279946081821883261007068657746487671626603559459527541551744302401227456043629161616005745925992965619503375569642581066816663764638394465396851228263131147789695846951033494423298981366703334306902407956508166243668902925170262915337524002499610788635119690786190015181751969305693730546646817684247772908349180777233151600825388509878546165035958944642232322627978271768763811253152991015790393362131772016739098236109458454447497941796421806394503093210833926300059870774704524235205105154718829829217457206871457000286807536315905896066654448512731991344418904170979759667580354661139201410834929792833230209637486087811845094380025841094706591833459781949890466127154855081841046791062214342988203964004237994249491526944149260384731350639133257843473534877915261462584401168547654226159693280351348221302032470703125000 1128446078731388918985837571505142932761386936011149544908135757289842851365771809372680392200718733198317964657188089556853666288778185032748888682164057323889911795337191102755527905160149976961966367111217728483133830045727341036143471563388746750066154597988558006318966486908395347003166087677612294151377312661969593001104002104180224973487353293089055654427230526646851403631520544058164390809377772059693366875341430379210852918776653689270733262975186816008890571872546792314812572314137966652073212238453510993786778510889595532443719844275067751772687963765890530312138271665022288325661235043730523687960801235086889344443436141865807904465914423458706093810536673764622663878990178113900947871195651690390670193820692088907453750551952708325256995172648475273172664216290318178792274833310557841618882424471234165844554546078717404810928275153478752218701432229639061944789409471258569198830066259065543438058538063065671334803647450392291734457138735398022349246868906374864497491983150445891579012625377720968442700503219575528175757585673143470627954965850454855440358785204769799642250067540102664440421048100509628539679744224491582202905273704421612889226259602164717600294895398077671802105477886998528803860726997274061967322640718927901695836429549202328814772045006975531578063964843750000 89141086460865321439959853288637659796948869456112458622773428552542345376499038544832036473649148636717641457438057419343562451038425773123735638691392218309070060435788705483054137719395470841287696582660630584948814435832509513576727148687653771178135906017638618954573027003735059294456609826993442331520863772390903746678309563493159739421984687347657305366878401646971749085544317711093878017911457760645481438384317597768892445468982062118607529154935592653422252605140641124164898146334928616711835453234698553439532317503605669269892838771877880482518302595551840218423689178888653901653153837325643180477217762642601710232526112124630787062681353149589665657129372859677227900834704721715356697750188163405557221901092122062276390167466635538389762663835165091610943071891731714612214091832450146570414149675615262878991377233523861625420588174676894143258219197685034899456784429689300265163686293730305755802633414520521832841412068623893594025768851677190591673985030854874808666417951250090789610531760797932853774540681951596218431467930391656330240426082539964237360285801659581312123459991237230950805205753983117333498002782703389438232215693811021717302586615241129007033960028246428274913317786575299330997891426574610439309159881556704373583471020386914673849787504877895116806030273437500 3347234528812321891590708851365891025917905030251309044711136271583198936270951293722694545896480306791843519420153975736442490812962122479329876030826849914182726339408536602486989780779031446545406336280073100086899697678851570620787800709095017185687316734514779824042163087192499070322018755875287482297566529689467628260715397360988331867920419179644985287258262661695489509214379167931385449432192529307497877719774333929608246733337908708659642429767399804620707436287338583601680465711115704778353872707754342355458247770225781182349394515221890921147207023975204673018974370575969319999225111880716161429923098961178165303505224963492072831417291406136502046375134069684283683496634351883062335435654104656961328963374028477064189479296135939030311195657581971558014359345982016347432560118069085022461661470365218262389273816281114809955376998067909275185730556305849811851194963052330392061465908295167829232308623479334120889734839169648329755877505511593304606569043730393206212255806250031630681061860655485329211220750415510956154270765498321100683923651761259148148080226682250946347174317062210059879087616461876517635351772045083363067090269312744015653610482379303529779096456761427106573420944989989954665228917091566611500087612449005116657327341123107089515542611479759216308593750000000 -362292180256185206546431555509032225392858492397078460775837136910527099783909511396267835784551190172686412408708868058427462407496297929964047048903275813846319137482650149082411120306809185973713289410498972758530061768770635895213068692328683031516517085707230833415879934612222033744646519353072897557827742941209796685497091952595196241363511443551028139990912492596417903287766780781183947260959197111985787274316419343574144852480966270988385016473084964137782656840224344935368423640238161700846966579533083938256353720846691956645609139548733620780687469246042382167698510627470233193125369186381095811749441238400937182020328071649061366605669060685588409554914061142035590231320548177691344437677399306135988389118364225475521297509982896174956254676387691184301331935165819217001579558473242942815933888727805980678555944937110300636047183897341928892459569849712623645718433294175553245637060332074797887508454524785466702814226957015393809114704693235020538376379911351236246739829202982200546095276927839883000821680282294733591368638147562297568885885824853689896807570818167802746114015380001208004442355434855062910894720072704194065259136463656327436119071157378877355813743668964871074378621844572396854948412351962249516599161374492461427584966138226718612713739275932312011718750000000 -95957381992094573160781827099235810033967993245991015445076012822852063890464125081273590753518408049522504248241244031634477761881815618781477341855392787806043585466735734741652028544500448762005452290423385338933067175391594102443112899020494265867759174335715220756156742585956320783843821293848719151498174218330738510462751816692311087279684948126939180809274585296319028194341036615429372427982198232638763140858724013856452579232704747711822319535785465190842553341663372289713792630261796874794826243160805156850862833588230634586825835905616021678733708021184854562201094715250976627798163233830416117412725917537237933715086452513531261442413324126299668155708615464599588737530282737022640581550239652002151691714160162290983322051176790921297811283881751355258465746861689906234114365288752048645257914770503521119429027600606961134839806477591753410530540854578410548613380430817805694633405104794380333322342772806488649136685863008394955147044328282699653001720896351521199325493549071619046172038862145409832633931986072134446191277686938142226652957941970213412488135030115012944288236712158832790836374348461152221927970476306812616597134328858634968688500665494464943028467107687794510665057034815411584665820946049791589040044532590557858561797210938948410330340266227722167968750000000 -12477426005846768744387078987572020077582778490524367755952751090538844899262685641410749275596182876347034920657189197641673744628244059971121489000073505390818648479374321418113473166706248201164752637606593187839949850845726159626358641537390004892759657692381969922397249199336476224743654262403513876936581794101896230545836402928244443503030812259359230349125113023896603797903796489462181774049362473369756510782756187617941285103027365255150205460022164970009837969761309069300890003230570126319801027219290188676329587190938958635560754811547365684052655427420315543654254902476278700334464932451206164276410412300052306023822963012198259757221690227548654961947152726523957836490295995622533273391474080880085971087422109873043172572557146723747076685517709676104607461896895226394028899123467377532654885582486121193509832519814248700052877903819382291674456947329471343761556881820649516722514200212489809877210131239657768871079896613346550825419107346326293485178916173980594455591078468035851926916807122321693091322792587565435155754146402615948323743500411337033664506766637524828654079764403462868625796291406895025632931352006193843786777467667878719417941916278422218822245937717419836083197334087480237243649954588081682745001697046819697314596481207971123694733250886201858520507812500 -1129121672192050304774796874913386239315741497833207586032720879315545863367232957560358537814377939447903771885620226410967838018892996527793633975031757315125322921023116912602129840530435910081593742599859546821942014582417716015736078932920482758904112220674245276299127461073603205769004715498382362380818783271704711573610674062512684939466662914492070736427725315749199549190504346756945963634555237145558225728205714914752549802111305450886656704205718348878794656612976823972664253686704716117520311199670724139864643878363975751461665552106783397273876834183938394271628018880653014853657296937270167221884398677780215871605534309962826706503522549065065177882768195394725943339201858041518296363113753657008383648860400304140751366246989442317154209918952027896407384636317635114815225988988096231756915162318643996435417831857190479527730516977402016499211391705284066593924729002604657139159391581477552877814511342974929597628854673497913264131906319723962972933591605588343525895107070647257502203014313144117278819129952990870652981150928773937240216567477788152906459218492512653594139322568987569543766437055064530940224935815953301147280165090344381344882139417159306784940135700981968493996489605626084492912909287938455341795617983337193497919703766285692836390808224678039550781250000 -65433912951397504125721219256905530306419124307591656657920599043417584232166195681652974622267610101910103658821567412111540968494361487458267127055728849242910900633551117866652259030694156150463854019872822827639302912187522205130280953042600614824998850301571281103145342476852191837767468892004673747566112967377554017256481472127035036218103526646080400930090510738699021316861726837977957080056361857791604355282218470712255821959698690362708220815033821200279385806362110491608664874852645545324802128052673177958886595034853671857496470275707364059507919583823950340364353163897017577705325959457349024179593443502004314616571148539183463355614457005407731820081444092436464179719134358441809098212492392282064956773200080432539986398310899559042371188181132756032465767622934841955613436024520626411037034523061444470636223946363645731518687205168960333809814061625571897541940575383983583731706612244758129468189097478585656332636238236606805486909344567686833383665927505858050037058786943585008706757794914079915378561964229357317095746892046820848154685398141044071477988281413607529196708550061159756762257826181813810615395458606482605448990231407085926384211475481998350121688194562314708110544707161654732032857870888697695888771194659615736653746065343284499249421060085296630859375000 3376431528713297110222179490966568036920505166971898377012809675581370429513892477168497018660119643050062287791527518031047128137150796188928520518986959110368588410535439494273829662525706385984899912953918804585295248169005754859349587785413896887053505713171834899514941498570389222894347889452411714920355941251555759594582372567926497471644543705340691471093452118421637391952375545707298056979172196081426053838657996218747183354653569940195381189655279199119748528431258300590333698723007123169995539215830686623957877057270421081568907813579705198697784205529745249817076662500603205510181285600919806433324241984777119040046637910913141277770074683870242745580088206404916869927010941138033088681925411348320864031039081611463544292930171435050051591413170801430533287674338725934670004904841831383691549621166696642719080237934079886464632658676148047343599015820809586670417249458692307786343899807477636339014502463628684009108596952949686057345789654378011173078634782235501868484647987250802177038917053433633150544274683991400581252949601587405303224624584506099657730865773885142030498614402677425314680131370713509359917707758090652711765820810220128536609374559518699153931147150265674019432572527694885145542356833390385407048281775962278450364806303696241229772567749023437500000 604213248483089526664614065284722158284087761056957301294315660890145615954125555843734901093242533708789621714433188535693875908718354409076949018512729984812973585556038865124778814886203096067163566044232752470004727488325139966399530951792235522953807136191301761224984637598647744069665438584661417387144175187686856345683867933149502759139109997056417297433183161184789061624923663681430250565140075335156950781454269297536519851324940340553506585228016484100963141275837283533450319336570341165361367338537526481642883970281396041554864306202996347987523086263856599636549733141199250830053282407159974501899988270214829019537832692953698944336814185359786146354305945324394119343325136362963645151577682294076344112008400210118920772032434830322684421990518204126552320880979631269389046005355201152591647831518109511792517603553722228258226832742733211728820815774693551684397789270176338369744513632776934574936391211328678814211657060943010876901858606512302599933602633877525752103074554269267547102865779549379216627147464223511542964469183307300761135406463255553414370007478442819294726215960698243884140653967749395331264613878918336262016529863506570458670253705745097526758705511569289229930874635343160824515810480657625484272648899238434151010013195559622545260936021804809570312500 96098140479118375162921201897237635342632726200769683841522780127549104166778770198281016081902495291893670200782510956155936039619938182389296482247278180606790544089555387653063291689784855773775811501907430782677428383776774526253420352686534914086239181156476581852582089201224276508959869456310319993411727443305220775925954521979822162095935379631526340275823735206480811083940884295210632007559075918721742829907595071944419805932066004103509465628964615489343752100328360804278736743106784650686989226689478685782635048651956608222716019618328408612512119035261813799712725224774028615376527009962648399273192937132985608220414614449826212056899336799032281097299047146945018970858653199885535346916968184285576434490709079956359530709520243676283698756379885824680883483005884206235894189390963392248815032744890134349421256217287922963930668941455762811726974947381120632584504413404373231352880568562878296663452334786451787211916811667291853092413948058315569482544800507817549860812721233955560763170735933700304880850406722606968135568291395888394029728065367785215032469753886627989139384221098935252887863132520462302837593238336899922911017980019088028725098326581874704687902739879259610070752935187662285946011575138116782613118858289704901642913625892106210812926292419433593750000 9783029596928728051235246416400645157542166132440578514693231450909289560579145887730977509025490779612273180811364398482310848114559605447023300281791009122030318877253133141504164878241209490975964064201977405593747369142173327957073008841546337748300722742058723457400275460138714862845972860636600345960943872963754471592300269026333313272892075251780179928436400045072315714396624121185772596350511353166168482316036847480762951359403258568744726221462144554154892870416762418183835673104136855748576226881352370932193469060321831120836458266377606769352345470051965548684726338952973066994834127702623943141443393403727189479528878453286504025671704569858222854520087872284531066972660040011978899492137826111723501030135071630363581916153714244696776642903514064601210914306097559222500307315521852562602588313104266662152494482735971289553417752283411386563676244374706249677063708454797365167693448545383302152516074426704666616499894822011635142370936847437163999307737130654263363388712596686900611034851651998147256178483193234026071175048970015624423398564421933185776957046824176104576073125885262282892727030300848648457622447333308379166414040611829159092394222239982050286782864357065056836208633963115679894176993546548540280395159251559944468823459828854538500308990478515625000000 691673189524904538613742001628648507392538460441154261855634517385753727912529315584171960753026139503445175656024855486356641901734177987662069532968160157607550538787675841225528888341958336498760735506608894218542687677075444259932349083213877852004545966088634339302015765967885606196889492300986814569319119045482470744979513934139888590763577085230584015006889533916402907896873143143371898973083036816409555030331362385074112892250417176831453313222567982231483951310558003265189385051842502524901777859755973063367168557845404982856592633486367291032940262202304044166601940575144005725091393907900789044247062840951790577575460949059935290121396008129916384790014693293521285640140536640319985790960785502780509866618870365706605032038316408441585099305199844993021051055146944872862859988641325243357772790631040945139756496223435377028056126832231934445222143336106299841882011120234650902087137958508492780608155798321052567742164348433798266855482442232206769858064107218149437453402034041835715739016937097802684694182464314181923230215660216493562949047483513198286383071499939042420774106819095159797942558885099716004322725122870651075208117367078879259580895757061203829717619060903270815735560830320958364819405056126566453079282473801261965640208018157863989472389221191406250000 23714520954603977516806144662203545988204636936941270094116386233509502434891882236102466414366686427428777942269058429922656760145723600032868121626073982443252165826121662804026634657528118377550701886618088821735605634759021170954759779517469347514843909040940402153494634946837460762492115508060036558243010975100490528715272865352910251320247754821069177256609851327663518110258624538485007495020915373730073923502554453577775618647279829200120065967833033593528307450182774975033704130430847139255938266857071972313399033135181234207545621949792575554165945500274182392329317038452728165929421722395495405085133426132872361951786205645375416208606307537529628458299323133653713027089633911858422402311711493251084242387615195502667669257339434241973335097540397052913167930645484073265834103454824133287803371496164461544507964758796338305948967074605150736430620714070748302195359493513316042392899173723782620493097376480031291093534381277836524697514774834511780668419315253552618799815592243996221270501487195052535723027108949921458459706829208860045477152759582254190622372612594014451836810009156353631617867951762725410964134523169994245017436901385828453081008452411680225731739426458010101659317068196279896894867153926439744499188147280801380878401118934561964124441146850585937500 -2109256990432793284829921476269412501808105250699842040211985103626882111272166734267650802931739325887144064540029893468255925170752050447754332917524626063818304297692811210480789617743273139543126903214303706287309715963145171685953521955195725269897024809588233632389348769549704129979074823185287511392403762754018617015721694937819134689400613549027616563662655503633062454288566031976202919713685525715148424788725490181369718736366034193666898340224380243397681947925098861605164625721273733748765598148353290546172742874243904093916564903296021785764241979960167218195668034597443519850630227066659043732431322583701670055959631676184536157822175081354106287790016434570333653404610765653271639423843988162089722999298079853513930980558066251683089103027462069846937214615173572623114212133501349531283763216152551347031404322589643333685460124087834757448790593528310693946953115859883293107231317167051904897010166567303862750504893256099222293295175968463817117284969599867348081266507713429981012463263868792748619608164013491920795540422459236566407279344636905940328352993691937850541734160908325400837451453805252180714131000665661222786644252702101710807623354428784885127286346121477879864018777994071165539559861604471083384501194513821475950976491731125861406326293945312500000 -508352152811793490852183321390495402898960760978614428604998505271210407740614416595801828112293771666092772132390706762272945339348855415076098491046259322841184129391518037178692329213159438908869498577004813460976435699651475015156091444316329794516048287553924931950821823733394528531431172945286140778517476745433129658870325578627527804783524549192266555229523281838001101190211765221943248815203408761958225697181136885595161312513381466194855738034070682311937948107294937733079772793751306183321726672805968358656046649046116161497503997078745475659942078891267248085555614338676916383041229054394686450549704311529280312799302357336006813319477886921317552806683336471048672084984281411373079777320425664142804740015953354280751230125415985978022727416964368029127145829429827736660237262001166437813317192459805540519601332553441208988466263865531665830587475487547577436336495827658951527471966989176239760120729238679669998695479417449115118575717479651562507683940137033450119170650573094842550020210321490826632411546625939308252515363230753051059431011322729002682302160842935495983475739012928028201426872509976202616004880803674860317180255848051296978940174906236780810252429665942400632202826513531134328738816547921998188113565570779572855286687627085484564304351806640625000 -58804376698152347081434034850586688337705905371640821817985189947754572228953135240247138142364956549117954531737293153043947636100406996451172212514622024704321454344738913465559529854964260230864423132627435003929501942111207457378222321519640583982828236882167431852668134703825017209790290613188280193995467196693474887744745650418878293378858131786567515053659530857042907281881083986614062966954085853190218097901640305514844050725326459518417942764938325996057718444354622114988481189145693311775506040307001629750142232570800584903369411265896395694931750785684734201118719132903020648272423325932034471185309594105348405661345365707332060367990038101086944446166155000333732082092095292799892609394449333249036832338912212470731371346236220831729571255998987086422032030113990825025067804441401593636876893688094678452541193862992564454922310865445321260131463232285429370653485893875279754378982283472277207650177613931371302228021870871689461435037635495072263825311427488035946174245886432369720601196500837207754138068895558896818064313103620106713197246515586996257648141851516800517935674390958166444260439373240320986740911111286498969440315339470410032526583177327635153389443616720255502460265375166314606522520066692761316097390810950229500519981229444965720176696777343750000 -4702547233205228655204758600194929859429043053565574899733092085164972066751732285686163149056050050657032364387017132413767587890673486613813331737633691044971585793926670753529449751577572768778392285871777884544809217970229195368648869133235110679925374621343206041620343079049693461584181971600467873503407788823057192841163775687418110975015916118064336490714566216813281273372672615790953843600133481329755782920380544030940996781350772426829730801819814236210583093871025688267594288430386773318304386602721510545087435681311843881207687845134670882591770943848512344140797041391523341125515602802178377785194495685949375681730063559353107458217189960339315974812224794657219454719640746111023056847320031276768562911904031567457140324895484741791824532633945183984664080136441226319908586427342001379162782384970080656600478274781884836683527613896435980924149382211143531332402529212894858670660783247708896400175443602465025384895896124552237572183757345984035993955514511532682768166159729134638666868778630939228418319096985760391921206719357365298475211090170069071642763557672006419047004591664059589870371910333006449554155054685570058968287977737153332858342789132992002829959361507052595677707853742462274844522467598537688204393886811510716583484281727578490972518920898437500 -238241969755748808238180681068056571030083152871018747650435075613585581762564842487325508442460826541830956537750191328886960638810676360185168369172596966942589098280828855212432756069660679873700804356922710639954074276665743462343077480390126294177194099606614248586311181188864496233828556871095054580356643034991063904058033620299895829115324790900278973001117059012516520055060315495080543705905223275004171656128919540252652553571600965952664275671497990935741900412468050788285590113575543054829984579399324240074355291520271869998134884789359599799336958782305967313364637619174403124555499565408559270068815472888014414883714705088158229701121219773582175713229135404602718797522632982624359269082137570480438353610961806628412308994206770124297592593610723982846635952709422975591694722945593642363565975074406690302184664508604481044688537963212704518811229928932721884922896448713478425680251741267396148626635061564525610973623463934628428520633118163104798458870755446763935848011387060480898568616981066426263367200296120160494730937266587847619486878510671873340890136965276137330702292622349188314738663894887692455757525944939970201700483529156016070130062473426655602778755351826309725744441285276107809198478146016210666097503989568906490603694692254066467285156250000000 487848055127587327493410609870290807844010766846711648045828699191249040617227845652346100235077513510970543776704485727848875206854038391515248276159548726302091746040804687360266748854478702649776352186929915476679691700060534885389451277721449847052166405216598289451173794730120428768210905522188933712539427417028260581125202907717094697450978926190376977659630288209528828543154515607476996593447713100068321781282375088895056354817066456918765690351104602087991582158876415487698243145638239620027138841877825664600583163157686951547896227487159110847566207377763284883739402440888327247485856038545474839998661235468945166740228562556780447537759656931400857568298024877932612374101613902329388084514143296231679811145577734696228393407992799023228951976939043721350633397550588508626965230699818320930071388413832727834412609008278007978339287048805804059108976990425158889943660449998920553383870994536266804602372071847714506841813082750686422591471023911881980447991865940637420801107945987913154546436407661631322327090680173875520053163923003751588881346710310520906179545231599209348803313989343842625528862975204770559162943314547855327780661806627928062558705522995682948208761361041133402545224071633164741997635315298405874612219790265044139232486486434936523437500000000 1775405556055454992412662403800401034932279887701666431074831199136911378278372678463427638258133111971856883474491783439031130110121716809455565950189041415680495064177247588166978303675686959889439960119712613686061584102341711235891858599071647858989423611051654045016982216685421689694143961771957741769666054803543957454909093059314347373639096649913025127096677470043842257143919177006519752947543537143043800576074410223450758784433856148669301341209996097924908143571871061419685360650190738187460048409811051403055704088815693848609487005228078211728257935119101032862510896765004822353801001140432505513186123807731966525020013253136420454013583844649894435583278688336696237751925471335304620095390124051131822754270255640198689723034780840258531553682187273638630692622124851432838343233656627000371921017597415199497281704177893598460011374722189536886069988094453224292614842235205833119836102777352082963921017893481434697436334399027601514949750831418894514367569519634152934830300488364220274094814662102694858811967951133287155298063395720720292580825504164264011416365466519428330215403838864355573428583819996776508230847755364862880731155739519665177704496944459303017805297699858364351058228388109986509283670183940274196407460571833780704764649271965026855468750000000 243620266216176772627510048051374412378009017831409317594572528183671695985929830265644612756740907185734617751498794640272455750157656956591043620445866714502794792834994919819444498452292781218577728609331815929330078142697894049986649804712341113968874484521630465240796950550030867556049408281934333091465043248804805388337119298422074026981024164600412644655144486943169086628681029966947216103993769469916709144319461713191695782423534278976389707462582000486333017919926958952372107932405871464623819734235678128986069799327664384995468780203282759457597037975235273241884827308612229202001985179536445936666157842561748368916149737992894535315014971227689103039733858637788641358731600122077743855872695538353067476318909763140540769855484088697303592180179049041586649226449241639475793446063296037251815648831843823157390018735541728291632022437683954692544008190613667900766019697270797280760705554268245680260477286158333077066655057487652931142626751565334047091408147961231163726232226984366092703759839903911961662898926454816051917183775800893405083879593385421013361260710453098147424303412345536528852646365543617821713325476990285242201206458078544813856434725257350589010360970068423724386956048914373622192251364735251607251151177713222040210894192568957805633544921875 21348486891072530409806522030680499392402801868258539674076372264609169195033759904618014959537351135444276338681520588554719936164248820786946210824312411384183959112023623184091098857355521084939762949231356335169231735347946763901661575321021901347171965630075503860986713201803342025109705636002314029530751564663869162071525050829981992260983816530573856861497525644345621322382078970405824470912191380788136099618432170702922141418429926151052759083236896965332578638693624508399256239990323530717134000585657026792285655672884067511050548868740397468884386330882086846187436644299548506241114877674860653241429487990376666890050413015926356399645223685823395993405791141772587673052059022370982910558719207568746667043816729283832418315219165068997848160260148121900374286850258335595136590440749411246601185674043908258298782036487992372414709068232889268985263627178382311046996798876490908478657201425625728224950693204993763065943098249850834028663112714202399112366867939640185217270604744844220907027397632788320803163155407138668095281462656993994835534837180498930998065251540984219237097935412863898249251476909153182632183901018750121733645519362288060230487165096895394673946974085333063417550564406372294897561583702426449271876557345350988725840579718351364135742187500 1273563239942874114365413103531462569865693447155741673605404143580204747161123375735317159948678817340528923761595748101198586860503534699411803710197990711744738264423546931233216642592878867846792570538520097314246553520558243868874668235006495222412220246118699673238083356666450843265374473497799439407790477554773036755862249147359737956646943124082485627693547001835280308690394054727555180581520026925884319720652107876018522696336370562020944912859217287326033452136588213678126771162600019989803419037358740176619852183146160107371760348943408055751676212827767789288444978245339404735326520904898399164522727145669959090170116034446839752324781720810559933004756810334158671323673209337262148146214991947939915614893402580967974282050946326049572225880888699940522110745796556565889752137176168725923126962822254017742378880375588921810389431690469602628296769199275587288815042985130414381884265992996605902889427229700667335529008838521846039168958948373079178425483669401151033081604469087602901144280952566568536858601955431030169276630199660605799300010835033552742430494138242207208589790250854873468537204135870431461170710972226182066043479016965097325251154796676311454853542606880702252882501600518821396437981430360879498081896898931120176712283864617347717285156250 32078847765010015464033102714360772857792191798004734302507765278669434322417106924279995888329775354670759274929111391738186945222864507615914529721391620196589290656153594634208414578801833991090536780082406040166571800553217706226650997507221385389582114370099793638119720914365727043612561809782792807897575341089031910339156109831974112411015880393758345856289094010363621643858736225905861776452729839464481008871856734426068175893890063064854360020654816268701933970993207215881846330948476847802830041871781833224537569903083712671861220042764478029796941936623646335442019908457368754903805618713642802097128129140480668904816146405286334939767979321674918129561209998708292372017296657481222188685109946881051678278778776749719011842455342274710197127033911483377387936550606695305760514185188605172998253345569678026579187897850576558536163452176572330225566429608503128467526460852064173536328956634346214465748828799009598966505056183241770352241167296632746444864940427234267583120701519451540046706442619702719593969893752830239179295173729152657032376102231683498107237635603086038000361245497328588380257999741538470168485401360551960285780184173817925406891768244495249231796531248737191176726331499411078582110167846204646681373962024963475414551794528961181640625000 -3780273265429713211751743969724076171292924285176594273218581344674607980933475754943392951674840906421544054612810557155826509229697292646745919884952482531560569499473984729764678712259325944060596839894923754990441124628715238296834275458297905454104547661143934929792429377047589548119897721193169319747366608026707566928137955906289564182352426977046843168663488476694202082642435050216100113973357719594650466464197706046862852875828322384725581331494530947712981109779790508375939697086416816569264900108760408151644608685817448077370815090527662474457290122706822787683024961109430349850809164602934930131129056453992787175837720661605062686123556758632786023260067107926809770531295894835393010119878114314945804108013452189869209070461696142278205624230203865589274222858014298384416275761330167273825987763808415085536903466146860022787393504176346202585866800183177582991057901491111616070203537563213359488567030311867607132756408687681196735020301470757659996581784840878165022751377199313064634154053429349368328050973006093457014833747416091762503940794320531716499657221290091003319817314352544504809690006226067786295792852254051200459088649564832450033754317230701443152624255828837588033207133614409275074732614322293021316516437035915032538468949496746063232421875 -684927901797489211398978288671067845578675249704437248085151919851833135379650476416725628436158760397004337587668613207408801245044891548831472496641840652986905577064347278773717810187992567831019840785584735019545449103870857440434027250925486331896956526194109636760958961201311799283459493521037658471743997532781981532144417768677967723822817198118424882853555505594624875302185396074116103365249260104504562089462917038001912953301502614195778116607354033412498735028001831842140183939364006535077794448577352753847276725168587830391279679305902940392129052884979061893248019801183857981741132515806574730104410348235575526467608259874994497898375664882089231232916996055156793236534812661079917678618929225146337332193501462916773186526807234026260366827182730258209992286441846766773806631235310511180101712955798313906590331592204653537804636710512791231965091617730314336969138106784585801343241019758788870431405334340228928795750633339070542381815353447121700671093674935258123467697839112049822808065913489604265198329439569391433910929010665058167414387959102488759546793040878670173340332292708821302989618661639292606659819967767530024115693718943208876442277130428226880482763653867230607935247822725906745394272981621215396624835491934391029644757509231567382812500 -64819944027352105280774219196671136710136754886774457857601577759216379789552442921127782707566487946502556661165895392050948600422822481016654520750203965682022833350587347260826537844330180278690599617394318115276060692298051294674051431702577138527414857714078499170142242813248582458013022812763324179287980876097105976478741116721842921339580130573082352797122404926498425755012103088249975257787218351597628894965215885802967381501292210065668210463990114070214171768186894805283027086511567361830636474934755060003069898767950648240593850362361003375119079864223323077806548405326535967529734052408330272067678820528674557238950623957260137807218149298093239988414279498972020705399148571329971600219565765545688940980504313829799453387661229748368777515178347285770139850395525745233416468854797872949775530421522921864369952327503644131573263555072673982059306361718547959949685282741874561800661224625337872755414425899997441501519062545999385642254198514677293347161498158226407279492350912800476570326537566658519527739658743001555240508288150001305300972387892481892639840401458191802459000896279427578664749380240080478078781831805642917430144444785879075999220769704382181870611829079057331378929550790177026692979821544463026050664211652474477887153625488281250000000 -4178727745888643459220327969399480856062613248727431603317607580461824512768850445706153911015635068226739512384844765471783281527732342119964109950601991209129933693400880739218565908798282493706630602629282763944619147622597520865349246075400719983868031562923420859996093375046325644753771747686879336913103120806427445957077428481429764853136507716440452284679908068827557788600489066542695636605442611701134870925528921478407437201718684520510863548380516478891510974859503923640423939960338345021918670259993153348954582169811256061678531221659069514286409083049316089907811677234341863371253009228875277394169701306041813434358018790334292769640435703973754920031322443265129160668294373837763169474013618400605362327280998340302244016027301018724263530808679248235012188148733062944864690434815362548789156093801528274555414613010097431459194544004187525512011482754947317015849959859026944992931690656203208093522549214368327701106302572918802010236287721484262918598101726606212657594162933140851046066338096700376458177095273138285111184890942438421797236898319168718609347119594618308837721170037692232307523065922836295622838138677837381443788595471470607543170919242429552184536586578854462331710978704221641833206913971699835580464466033845383208245038986206054687500 -152713473159087384470984457798738560245444394295378690058455306898191875378406881078293219852911863624227250683727034569332718150851572307899825393906363893621108315010308337001600792416445264465343047762048380194639196927280132799686803259615489306320276921571763079896638458484720501539107955242887603573753147270167144159294663449094226705332600807276446256481406488909551206516888895870045718345775795814725167496593517233652787217589384026631954954352664829223155728292852090392101093698417020218797332529435111188569970670904943929075436680830497870938519194369291009473846162704589081006406839160898113924655688211216996091745350066295399820070466464127180227881556423651179734618455289972612307984516790218854947973839983615129681026117588872650532068687946409965549200525872516005354731542809830060009145065447030767681906299002907109030234234735505671413388744549776999272768173378805292058647382155783212576043495737623176247507782251997208142947380692826273859131637935710493481357148234867820343871117384032220933227898109051580202769508922878920092096923956806108295930368464212257719439711602351041410286256539894470519259990163664794846823430984443823391397842182735809085458379465637999207004697640916125151710589807042502998035704564472325728274881839752197265625 4151022422716328530206292269165354720067469353897143300463202995106786757155022878775566217243473100080651844229340175728171464078351925047204239270187722949208283578695292986690908807224429425595261430083935988526345628916989552564920629259342175617880725237657097655960927728274067279482784135802141211956326254820789579231703345010373081497762775943503881214985934547388931167562204539747221455914963821299756261336112703137592286191434471729849032663778316723341326085495161965664444320305208418497298539878888526746306997397410770440338319729686969773222168648043372900838900625233292351760893893355768079031565885633241907398543651001923001430382944680269795203315361568904466803509295607921684997734385809369828441880650931069015000789245330065325514690014018431665685055615734415410347113297160070416809281054280274875602941281549799177022227840080900104866749474946827371131428191070711933537379587801651718500330929901551520018391757191597792710643809563835862769027847875144750241962174626689941044762379761785525375791339017150048046211383924722112152992189904784956579930598640979236120270789953582157389010337989296673096076563457954682150444254886351673092192994570311700342567099678562225206586558735642212384019960236432311706522568783839233219623565673828125000 1295569246222141251150222047805421084193641538978558957152546350785149406431502938713642681419381155025638712860255487719824168606069248889535494159780959208321566110978379694114279216194391213327331169471055999812635567550363553869706686956005236509333726432037431478490082408598636233335673629853717055563031111009328195026354065824596997184681224637294413137858079688893797186738952643530514838267621235757828665136004575454909329967567721566266442271930863368671107986480165143794635653859346550081565756956653247861069709998690442828822573995834635321685861227856466644052082520475389439267227439901042566490251963061592756586657507815890169218189103396988201990261488730833146300645636774439134121990844445759275340668056479174211336120667261164958223516720996326217338479302504130517567297071717797641921377115711922330061098580440589791919396696354492139862714428760646924422564302442177061128504386252459341347801665628495301911753828066424568930950615073074158162432638522360795138327454186949599659570111517625728610214945664982377929186259846529644246765792190060099340889403026008592051560665020563282869461705943916248780538731938270069932874060695987003376939665141191257571182104867476645406078016185528718355586137023346612884289186240494018420577049255371093750 130061540783470033991129626727038276847341667865939770655487516764426704582912899688683201387230895355669427691491503396417018182190143495317235464065413009211396983792647780515173044621927509292124501356629042224924472023462362060494944591999432396270791076600574653757629592863111359054404421632475139818816302227609834320408863320211712789317310799940869555393210775378490546752816150115863834083978382294545383062269139602833503758354405965932228036414999463907362804783615299928620360610231221282099511659095715318883325300957077986629063566256681334082043616174747195628452803066334566604546255964180622772906090468835955925091862307860435012318560838792410292888954079494082974594677962463108863368296294735146309189031697045351844586225687524237187865380553154426763465072321936965915323509059657829243347445076607985435948921689955605902588071026105327122130034566539321858601552280550580275932104046765462750281758181510769231736263043124942581683980192792208923140196122210809579174358829104514722087568127964634235788578019428720180728771088566662166939404672103264740122604571348703178954809572195209934453057435982619073997144505443024202508374690015859152332166592165638803340494007431158519148753507163769698878388327793059753290094704425428062677383422851562500 8500326371794168309401240132556033243705748591264949004472287608730539109049471086171551368596764366201080105801091941165283287748361593881777886091071119007480275538977999746672930794697103324825446527952599693695100168928373609820908820976072586303020094780647120832611513901285410778607259645610995182908185008361962265633073312923918491319330178751342806393928335383377362542594141943040654583525412342431964114605285463175902734378472317831580086290111660244110838878509875571866422864124304471691976212434385887603636235212946707764341370981053628313980755937963852574294258979873683790939312748002373341566361537162849067192970304029622518125425444804959061178170094107774602241531291561445168436750390240677399171183538124007264281136311163992520248898157729771381132045410511388831758255748399816588578936440449675927234765305661874052750411383127890552704790286384663625535655818937829457131118356425057150228445105518524181195341678265294472941079515450841474449227396498130825122110636166224506637053933441768532074641176309645541146901338979029798577637869622027569012435590764814966984420871368310700407671876859288182729749135781938750278235509470879352238781586525763057426289745924540440131749132211048269325968075268463997051782143898890353739261627197265625 332830443370943167298091241189649704635086945108143596962347718950692966751154993469325929064656383038415856607377593680744020191782833961348314794245813072472174390674842370587624817139674618253578925480205390038472359895856299767574655118213559284756872416823820883628153003087612941904171650642759603065036959693520646835080342681127790688397882364415695474207181376568914394228833219374274806479224599512859777369715300272430247204097499045962995726502727257267374279598959588741971573105951201402950279178050325379812578419835483774486049097622999756952718372802500124998772002236873194120796218921103154613296377990684338992064232962205966769178367334640598841294845134648320226216576665651712015570616271683338710663186879031188421297618308761439953084051284466542000958735795233899714076222803316850147565305158794919917729088556200887742271363367038230989881224003356059285072083802744803624654752334700737755166335493593277585891776967411923953052166071575583819829943474660706060573533023012067920995428169401376727517034480663500932935408857078467042778971184402582531302957778046968415633122372957838906702741878289877336884205788934024926578332115269831146726024977162413974658578080082978170095261024095673667798876704804200699072680436074733734130859375000000 -2696923855753081244469228288949562575820705314483621120080652075243084177638645699486810207608242341864993727173540570148743356890890801542708050733025130239835227366118348614554532320034413256525015569492241701221068860685165638452965296249518306914005039543334119863753856558423994136677011146580520724799967022015207890285952534753359205505016908773811698330067709373920411417757386102163413168618568928966279623936300760104115653054958584841020522047678781552614760953105657840308248131074698307694983578626724461329990754848641963650882529633820929917461064860260317759226187377286397847732873406160909859494002420331242346559047994693617880804199230085597626347605568496655231573654724678388296012773005796357896430416853226679682337852617461286486271636013510126673490655186145724956535834055060722157804003036751829937120886128574982421670252178652663681874420339634755378640843085469208200487817435666885643284725997853487967504736328563220556925426052062782985862856743022989422609145450205508144561080031326493582670131746081310850398432078390347251074213564277750119489370019245004801736637774381734073692423739063278911263121224320880796450259662573134523498825603781272460613615860475735019202251560331290543488010763573115013969072606414556503295898437500000 -1775556327961967251597137305972587944826455217236832126959092906492432247612528521031136108851599341554046239113182624929429006655948219625584228333369983799990585762446700911233472123469706576850232487246607539960185930421071807334014026747738026803164995923666413165925831486571364554592579946328790749783087343875481620963974597395663013231585119499759628432493713600472816755507155962323692957664317345452417592957582055652126091854816740207559259053868431508704987471082830273432787413500094876872415258268884858033830885618001381236983815078993765824799376374049849349887381564255600292859543801779257563785017066794110786105611307583250496856303997543008722750935566631925443009634130976955493472916271873249680936260465290096723784217272723213502257810521149829769583381760836379735707775296702972281636862213216696854383910904369717796206371774649303827090321232150678009258402535605354052267069120140058619661734597224538425460255766762346178193500070095375737413070026149326075231631209956015613481212356709343438166969338080188580524046054670889941098724186032356918730074103857244646561883295415880733852759776228430521241908230673745297921503216380413394008348784777670565548074996450574220876567056016744178248943641929002978940843604505062103271484375000000 -174453176958930396154313950523568671064692896448201878662995782359468960487310698195595536468472947023188919549084268414800841894860203397548233111891563120314297090676541010284318459349158031873562764019435314627784247753692734932894403384499703725518856481269084636542277166725254940759047138839712141227938540100532168129290438157024789251819195472280334826747580955633094316461383649076699736410003611826058560090438484684846843722136253395211679087461531104954883032255149877863945306012396394985622504666764132624316622483387728031120233230382368394848906486176328007262212539003477296886104671732325122855330656976813220671386510097471980088860456310838656066981398250842468140845817247290998819220089398406454736625676745060515043474265197937187199150402555800783735028514180306460275537550328880770106338803522892788298624661210484147259255119121646338327682101238615251255872444187294175098380713107848265167268943664584660773646842150494104632517939246116169513310837985054877756624069172665308894950890650035593707019503126697864722843638076399568799493571665550552181029483099579397754350190675996795075515401237324635022142576276855957650972825030387108841435212988552098104164046532487783725772615446896698047709608168920336623841649270616471767425537109375 -10401858424172104823185912361911571240202368497425198494051316785234860541609621357636195693702696777859304645308145298427835007882437018641083203700732007175450195474930347625719896985176370038370156851870876648794844430383573711715227793320144521444988004859853995288392405791268054668513220256602572915099332523170210048999534887776849952532364454101500633801692742878108803570559014762445482484626171054033902561955409772875041656879971662961732171014757034485256508728548760286368264280270033388773614468532313394154132397004811875994371976077985911138439673181936076821270141408511790925853362002729796049525411142470545105912094435157586987277019204668461432993970224877522802615665702278016134677513140617049025481609570827776253190852698168946197520198841118928662712042059769143212210386317510823232135696444995589652361795972745195113602914070825044757556258976229210070995926162749543511765346275519769882851113326966994490066292540294732486198997659086946875203261747212202487426171544149327878905370761435366453795443893754108277561837745902080712662195342611333722966596889784431535034352736832772679740736455222874347391475978939539991453430163614274514729773363450601015900136078772953918447149695626771549337909877896990451517922338098287582397460937500 -326497529505091435980802009590324193279945287786445163089370520970663072555798987009345461763648403665984611852159674038796554579767446555880618610432645594786603738803798709297897148998841472615724130895428702212109728364862379339390768175776570283174626798668159286554512835894413472596606927623419151242789535952836257329435810979370683670526114926329001858001426885139860548241174091788228513154382168011265311101327326267583016032248768534900472476864569306120773162682892854677739902750583886902681858264438242335347564280762587905782677503562041690155393411200119765771982510889130582197502700532225616917784936721102447815104624158110235642435016038863251637231274432836885719899369440384503520360474042117421826682405592038783781590594133422287274196219049786714328245491309936492843563213075398026510746480665622460369336258603376307228072437535036206989822450105826766216872552674906665064312875591460075056882610542460777093549582959468972430256101132917346003886550232774768886640617113741081711328147645854482075330850597514793601121249711066488645253241927729950053263803050782210125549812442868496160028879797508483855973863242371290990485582586629526358315065767075773551726531558584854736123100349394930485636204253729886204382637515664100646972656250 9716909194397387899198424967641756050985990296945849735058524301900224555362587429781577542001352679560832534752009828982924890813510291948827294296115772981808091603199702407829275414139491068728818315463693183234419035711342596859623428331462556011559155519627476474776060002909694554729563703860005671140081208278245381854045423173410029774683587591272427489117863649682511017141679381270997573508637247741104565986835588083925509274129101164872428286264890456569106207934945221594883750435123837954168973355537188976434334012421971669245898138928476317547988017461928429854466472504044426310090061716163443433053034528820394064000468869130207629866993863189247877608211815007544504606855464378324837871698822992654115840675953804491795028940843206275772120681906489352479847830367703377387481156642148812576581788983878335543073775337790838144765742055716182463230232891339716679392982300914164301785512772968912892637968625562650239014032347491609673614770749169367971556963698108182355398594271352937256214088228430962313781646340902731439910405521545304324931368137912838561052309372491011358491578502596358627118051970725727696010013781426359566173180312123828275470386316704096912490677217952934422400613374623122749096371109089886886067688465118408203125000 2218729813649203876437157244961235724698232463036201895936502130047329628145735276320610766109917094411696259289020053859270652457928346527584454590327895318128473545705133082559008338187292772891597909355058921143906604087901617390214337162096115087114749397096203051206910329538406482016054898513321006441040861439013620420218809508198177085049631727922698357322619848989158686542706990565809317134487028461550403626920262267951594254301016984595135925576095830483347634566552936623704738783999190075207014168357980156528005318199721031684680717280535873949728060197468716706723296915897585758293896798619682717029392807804450832292002464594634556559698751048437863938506852353217348638913138930993519174660331863386857239379872632433537112067592741816495496358665316069748024139545135118975069468378492166385614952735413369249035122355047788147739944952929547288754035401417536437610577911297995777251307738251691667987765871040984972069843334064386729099507608524853283908396222585987367106047472429836913819807530545100708503393711760854056744840477932578977429262692387937633758906984525425790282022549237076523214348691447270381344027815262057339672715884267623574013536910992422715822244581530801882225958310815693160476802514580185743398033082485198974609375 171362726811028295221006584073498660498731670035567279956204806470362112906332459317717583959435730688497772927213703274505314450454203268299987806442456917919888245860270858755730085893949634106483922869746009728843733728008895533548617981355405631456084360258392192577130603628231844420734049528030581244935228543827522991105488772862003491178888461245167168148199604582873838297067709085950314459040318388852805983004221488465941560508999699790548352350015054136960865893055686983456530367856626966860207811719855069412623459178619043758222648157297567507845711055026107315653180150213425151402562668490360239127327328062082496141922426774542706655638926946055287457351769656945502301298899172435607161530513120049689401470920382598833528402492329309405599148456372100021804171327477842413912977429074613165096734774752562133576216863078201150293770075824953276413773929054735728635720492630970470484398017498455878843753654053830587423163033386576162203082181904178918107521586359957076016976383076370659755647707888735937171568730759300503262862004971262291017188497562283666472524890103840661995361435126624913301540843283638228391717474371671415565491858099735201234477739782224458955652729363952315458589292618111783045309337580874853301793336868286132812500 7345952203600453759427047029502637672800047804150547130740606629054847845201136251734299657028771429483248384712092116012065567962737678436221425887768993355113753594228263969508150437078426841321442180087959366348680676615616594749964384400159362488610882642835782376147696112105770363274333776290453569362252318036879845624350253273505326619504266545126352021553020309939136227513449252060018517746557371541041154963272798596270750974204949609835551203311566211106762504917890998601647779641110081456713789584807301151238397261366258430059124638926811267024257031171516075429475949865109414981365435505765740678960139614048948408333012141404454096706541375928593211520017587581351077409829743906809109667960333730057792352018193558311711158991392637580528351597811042567812755593308183230962747594576581132975042090516011703715330031344423332846051509703561548865191696393986061840591447110914492161723132908940557781283233269970928868142865188641358900300631010876630436125149877828609606475202914554538121333980058749117912129043400012647319205357340679226278614043953287580788253057943172768222538396750223417472419792219839688145614303514847863007982574487163164710915940892968387441790524584449273660139592234501193512841155097703449428081512451171875000000 14062883477831842173621907972655774480941844736641434718397273108929853854466661592980461694313838596867958896984800339463905949451269331159348888732772709182461253655242392628153135022074916780544317149808306724584686623736974798467159546954638845171788508880913264291000718894016405231492381984049267524818881735979592822049813702258529488080107568551958714934618668275073628178436505798620316144614598609823299685889851014589267379224143907954240718653544828359393626926446821523657985323669599925510932234445849675629325832776939397702770917767220541395961985295134153747839706988549705780233566384679010123538893625176950228106229069940988747045212485486115942671573123786462168477224928713948290283366622568097547665722674734452126339904824094210487460705470251611780163081079320910162302074388384772809926988170304541458622753775455649468499455558822914085106825122342535590654603073175489295386390054222345651013626336616703003142709828997433225493399002116899331659678089336828969030800738959288996659924828079337232178963733755016782655231464230067944000093163851445620001113777974557152773770975972041918129084229421461839090417800413476539760813076430431595871053228567597763405501396872595109339547764487187569981685442144225817173719406127929687500 -27154115214123943620906767777877660523052044115082337810459874486695239954540308773351053379199751092501369880948812632785325290267622063654438939349252828685205212345746237948905168087157144356065147366135775465034250948737525963755436729889169868176770174016743352509595580977975956429030268262770075959498437698604405865617723076160354927157901758272940954843073474096788462967559644642875450693076652111418484269394018722906458418611287980048595141041499654426955363494857568241266754592718733736603543287788926645379336288380760675871887573866777141429848565913830894687898705125061817417168006015146910861832494185032228688999169646676021805457231854309948413428783235954941324956634563684139084476853221863294685681940443418405780305724922904435436819338283615498309415454295104718741099502230459873935701380396697676630297719229607270543819834767768927254525605002848232807494398870954370600584554790086634812186918157262621234136930576959726492491307149427686435392125591070513016476472799606532886184695135201378458862992959502435800428710926767077773713285559434134844790338967056057063515422102928550495157972706087177319201150653587861267100419082817812057564509363965875521419304038768484128374020750452673238217737861077694105915725231170654296875 -2538371734692297643510364214083456879052260457008208125529870579562495428398630554975139800405923285742956490871936984337392515364839726798277983511455871841502328740103293407949195087138810277977659329532434584826049275408448245292039422547884056896528066640512761715912934323408407841484969477927580794777831672100187260401774841844293669717488212893237951383519627111722510400018625729407557027708399502738223256084149318424098473667126311700935735091932325717456822760574361435560739265865177168920201712619835966700288960945991356541759019483046381237846719684289549100685150511398952409064446975219219510177220641283477549574966269363957952644589433144593010365622144677309456831665648810717490346237017463011771332971677955089572072607912392695953498118243574628852421385569960557489468038005101715808769259034098826606531442445615015271021028861354082531942600918111204525882888636273821509036534608358551748783817162161752979808668090987173633639988540994824422249575885385137875118782386640410236359753177289706826818581510497226955163293566131738653633756843279507811415221313565842184327055700850830800677249012837522326874789045401243956551236504298939389098966388789619881720414175307428872853867467241327504634540446204482577741146087646484375000 -127249458256992073120552724481589696143860459895977022857968874019477855014668670131746589526250739957906461015244518647510821326457046932000867547410341400397091367617038326295210066376231703732697885623952684524648798057955687655123372924980915855556908376846375217645129660845174427205621351515381132372961136941640114327025570758089906666017879875044747548880864376820931703648514455204903038518239872233909057919843545420296893748543545000834658298081558115234754444590463477277982616660836954777436095137698126189522310802098232195541298791459874675399545392746035629631833450085008795769226748975399785611083555539479984505765408912196021552320353852995081692730089599232326252217980023688266078552965132634428792907446177335238637985856576587894993841433649837495712875146330236152676929999911019455788266160249523977112904957062084863744292765247075844092835761129177518587513437021577563945791397123268655888521650512395608295780315493317670023392858247106953004053929459084341431149841814390843731795400807659198352611318625284457324310010085586248657770432194537668185327789140562543304170148319945162557425034551051408528046434608204861851743792526366252241922025586505251894228911629871965631626405142514876778214727437443798407912254333496093750 -1929480807206175652071031763829854627060821350313554240294698731661157457608677865816393304257234580748866052733347226299404686918504853577126455853273518116620691174651739064439995131791599791344237813409548287709412451425117967252697569706045815894047414571991133334914483070802876760340517194864896945424863371044019059062476314767424877248413291610375149361184274403702563164988105712945983167498513691356890150890842401441337904081294318150577115013933833420790041053504653239026639483547654145135775407770455296643094003324219356154168800397024287282818830590351095472462832477740578326351694013729289755388740324377935161963476551466850365056666751587611322618857658011689387119643052188013153728997321025208811465017123247828700735657546234442413368828537211260665457124178783595498646530502059534829305536461225205733004029379672768179875187745967932700775186413256287956312758944185437038372674376052643523390111840298314527897406131903552793997971480618280992812432059497150948072117394521332990462197413252237502767904450005062985030292791152337647848133037067027982696704238846883345914027899030142436444701993979647159616359086709149482348930685875225211587314511500457258695997220258952883104103172718507552829692031082231551408767700195312500 298229048528495709725959636400207276246294698491673269017529006763195444158713162904482067240716761396547421408064302516829472486478831900942282846790465206034735863796712632427759770521635436222678598010944824911739568184685434820986939127553710045083141352358944695221046725770941145790411810469373076033427028546859431358041130368731050684908629580466098703301660322367083150195564094532310898651149298468648851543981088089723482770279634903203015028144713345532153588631320700260155405262230810085724201952600654913650240536385566803936959522858819739879390142474309105125250981458503652596918726323536466742022160204361815480440106474522958982957813380657948438292842424955233114863324794136810016889874886675673902913596847562579708246576061683831071961851646873583503625521439415540856775852985884882638865820154170742744656321499653056392824533674163828653202899402891982107786318962478233782999769613313657260015450965680984167796620231907440572225731634997935804982871734579446169218838010519609401908263018095909418620858100905743243884826217064768040811118118942958325340342906193941424130716449542647336942073733352361553096729450869106530446745807864070782328461346820384138876466232536410641257076654768443102483388429391197860240936279296875 33251389746904257567379440822466762019836022891022771616479337869069886584340321541708416377632838995778323126563641884958893204011278915703428804398462314387930116594442504132798664830593052650959468768923941497208712511124530484843171120900580362392964958818530783589846065333493214106942709683410893476645326795924676242040255511563862920796570208638647844326039618429486774264696538418169088441048624374068928829424129890440948994500494473202147429145673418748343318149296634868895169446622946805596933305901708200133711669053913945060010807315653096376007258328173741943454750831466896719451814458580337409731938393880347468647114534362809060454799003488911321320963165571825995060068908204829573948582627789297851997514153479766455616379651231069649377506403946805574226660878996738256536133426851987309685254890611651206878102236129922914410408419584886328686894673556405414767327894256560980404160008108632399391220172025622964317842517404669983491231548762711119380454885663376429398546102374939651774981820540942690012484102406682434727383005748370694995984449417143588851660310116466908464438813267475255749308907808641878607513045845095213800905030209259742506952967576020127104103108116070854939627654545120094553567469120025634765625000000000 1819844998514564670386245790247281452207256016521521016941379809831204654724462758011644097428328144669926908828722606244802596676168458883172821615375166306455760291443084395242388590080901417088717434447980360746980098117434014855091196788464340924385425505654216672218500728580621181493912451403594341911756186141449425054892759986969388136103177784267997523144187978374022052354047450142218176226672135694844869393337310648564219639442822502500665295139442713137677173772234926975381357319554035563026085786637388170574279507633364226157969368712596619499215426301455556622878189811939078009150349502850106390769527607213804856558332923696883126500159578562871574695605470313951019551987557243369681958201312427477587867066517508920324704482230999095846399531176594235597248005790531314719952417472426940981536704606369785300258085206983711567699582683051557420027049577362717080862247599327739513865487586982333776041557605202710978748331283123509019448810093115891104147822358017339729449167534629523537994492502555758374091443888828176529711583391731681466794304786535229384029150388817435708451423358165680881394946980046257040127353348260158122915689801221844314650269467535542619219005142946034639384045306087500648573040962219238281250000000000 38280641252830589861666494814952892620793980577046999218878420396987457848348185100122490654014221926523388579839831498732584954723490951846359331498963550518500325620173933468986156876453059178768487283099598436538041836600771683298829624784100454511497096743779195513537775094506109112115254799172648028995764349963450248415022619654519557019512153550075708504116820936594958976856758866136406330044227574822774656919372347409857926726196045143089510464073468315264773897365482055336486323492373277144870108329846657800939835156257706614305000786653211843228080474320283368086625301801609836798586030517793158091063243166230451045371204587893659193502615614062576995690914393051997232398477175618898005148722379025381347032323720986327547627438197820781529155307447018904050128815852438432740111536748964893317458758680026842211454712924939081834368514876429772154432671783415916875827123224222108680642132633767035404406451566403188509533527771842869480371601249559271721208667653740377856792868242755387681795790820288828438775981166604785335370420314103586807194217200820548375582455108277637914668780300937770673088533647910159732346640526629520439825272150941909691433605097953348372109609883237775485032017286357586272060871124267578125000000000 -3184161459412863322667833133928226395088085268244955946659081764411358420981748235225357946147558596800601372973727350544237233781875741657372134130545618461305219705847249785230300435445442900646033685115534641196621158892823878568791889685655062934737858680728175847049770556946592923517043761991772230815520897645028724585715894122529996941689486005647650311248972137328020750742105053773508911970215438563870432798436880445714298521498849323658945274744613903639500437823857406104468706728378170449572867594034890277577465210807591443673310930027448772324210835190460857680129250365316391542462445902738406900100291845846226352600146082035788377790813934791277933945704343357361593256020349041854368094322749264032944500704818239843981233422042048242670349297282174710826067208347388336425174659837402796870310535729824182589806653679326358013067972643784067282009638279154098392400734983112976503949011744686530532639485420195338539174159316145923177615865200847600778457390057091342789277222819833232743482852475193276484976007231668298470886472830896506220354707114182071784547235843529758030420165216587031259122900025073642012997935883429840575496201450626607856517870880198830227485923215954415630216112198525024723494425415992736816406250000 -408893061411590602974855686967225176405927738719737558954436303299593910255775347911784831540600392212166582732855607358617215461166584123899355684688415406135839783437261114381834014768195971715436120966754508048127840025733450204938622826676138101184225784252435274730100548176976553726566234966774684605880633792429078546656170095529177891336347251007170445063044097292391189841173482466540983639060122054655503006700702049131342597241618449466007251386116394168351864998323113926047205712935835270992705941258602163591971021200619946379826144116397565545003227945196977542155880544916808932487584972589251308998427531579038079756138001619814889531618557665688378022612953692039854098551470506205539138187425502206225717007605704395383210945177683711549457194625827932681294639624666658100323668434973063203168670748196048236672286724728128695519204438045784691495912645175003294032388214893654664041416491135948849805468756744955959555863180253956085335952027813416481801522913421514223705107730021033848140054883475621288921235521853304121690544961872848454934601129117986129485073775082779116576223053874515313916174365565568628065330839196369872234613668789874480688697941863695355555968107943488366873285855263020494021475315093994140625000000 -23894788690464398746689865103613806094049453045072481678246303486195953542799106688723080463501822490778480734801462952879710839427763371224278926024790143198494519113229289366493575801624318693255041299646088533208224901991440307248439017923250082445257671312416910438846335538463057582976177397398821705561601414837205705254740175322262420768804351357787356204960136539478580868485675666060583425382264970371837843729691451277728579645281526685304995945986660777322190137531864615704533247501360618165286120210816051868989133052969752603104503940020861733588978546006610517159782073051806879959642252303637127694686392220895747875980459548292743300717638158319401863789642967959105146784423672200680798702512336620652266434137874473173480976281069072355737149601841952491150871332254771327189166398621955038773089847464783748962856214194847757792928976667355844395088728093823629634905665465162348125490936748870886731831472357006492879598344954730403618357662806647935522692994303121524739008497468668477381011571938805684845254130490373205744079433164927232731508751333693167887385297818907899298788445037654449248441746118208883614937062559425161347012805887552601865437020101116793801640475544548810477030187371383362915366888046264648437500000 -630073624430096623008940520046375633078616866933720693812820397882180361370303497168435431864128374390886239006452845849338086398685996959772366605873519213900448658403333486471187169376925082991765042028792087095108517544848867340609181828439152812822745204389529995309034274819857936224497751981093593221231668833059669391991223960204497369914513857169017656266094699047882436653110627867703953909779997421095183617972527531377076323175292467295206658720733791854184450977022156212946503045519533377362370033267323915304902440600709772291384078263750584463244219433387107709236766312534024422382514684342682800199392758221018901532145154194385511013771112581324281953332490649798345851591471739230694772819903518095698647548302730174288361242431895600677037588195262482882844874611351613062033921935774994707589816123033855369902506544068472135087770665144334934659034111679039281144443094579240549692204300705211162227298590181411952118359406191297020804340436034596645579642739371521014592751544086980174181698171360048673510935590417835686754833345273286543233292559220622320722594770185701994971189115776265735658104079952082529522298894004943249591486035507843291246906267737310047942336977853591828413470921077532693743705749511718750000000 27277339592311787847876148004012838993351630217303509589991528604753427841245661107071885092115654624706875439156818927178641361916234784718789378478465735169529455789536035863235333897569166197200568427481448656029866750155955043709668181462674276592520990935980399757544618594564486664335838889985250422675575022571338197744445027078893264703898929857982012240736018890858860775093265178999901727536116710675715125600635174323544945212336556077914647103505853711520600901610568437128088747442332426794648293324861610702049612016358411652855963597261691163592001369210499768712862726550444577988233616245062719563308126004342824540800795424017418863312061143467204742638519050506599566141019782284868616293318023578589093133877186240391563436360871835697378010215784559414628119307130023745691918821835199256108357954613663779009159000616091794863168575603933615141801683322656903204585061493909936805756974003330949162984866863240301378588567213978098352054355394805357546681488150629761743276628273447266036865495523213153596425477211909787881514435196972518122699375637426264283942826376473159520600113000143983293492947744259120027257557368352058589398665579008375436418465825466860427072927696790297091844479382416466251015663146972656250000 4361773928565278041198666759443747945604736392165629807349471034200386432940461130824036969075557920662615361615786556993309888777196183209191964842164323120023303699018226043211436605484508946349093638268355180876742626572302476305513672137643623374670028906294895652479431630030122964200146784803522691878752154811614086507931530942909193196217627420061855144083330886034315635282594982376491471584202834221793615919788087057276922131688585657680582700144081379092379869526069132395257301748773911802793909838942236363932794546365377178967280035612373296825547751176945302834765248539891942950360295696501416511978687678745802198272473864936884150908665502345421083084219077361285506891056744002898816498262470546709172200940744872134636241045439603041411698902209644478326285437863496535313431100384281088925494724991411953308637474498640809036395948414206412288853522391580024846513462117023381001670501089492030548691106259816112634611691662593947409167664057456782090675992742459281526988889660908306690474824683396064457989384901644562122997173628378666139965898347684791337895699722206216751895628262976934250763507929031151478191364742985956274347392532517057769365494064031846185578700204020508035540615310310386121273040771484375000000 273013470969980331800465078330528358602648523537048092261966180135155427115391273639296764537775400447586836200112416981057675744490560304856258206676237171037715825469360803863352089067290525171413728697959231162520352398538685647933090825463190626978092455506474209974784286620425942745843043449963189255585667962436827700020296544498009473649857712499514216196185053516640735867767050312184263219415624874097766083961115152573174653269584152468756139458793455057501014507051844267171957944683947376402092806953689254548930942410115181868157415538426621941684433266571812080184915051654429161476454590299915455813429418209082895367650583291546169614199222763239078709004276416172000845093458925678166727108544370703592245075684700722358595305032361066132734730736624604460869404287614369929837145795096805814766684394156879482196158639897410295506438800421859232924060820571145769944375304929423774856337441281292160665993364581123570298136879074922400051530296645098698189582637480923675715954037457695960133870192501818131308975849342606270923745951502608675196836445456162762054282457786611190229876530774164796849975126476022496580985779131795031507728657196592341131671181787419434051640120680870538194540131371468305587768554687500000000 8553456561202393298936873291276929726067865750944690596106679824742585996653752806924198922532692684943372691121058823028659248127048887313264334466398487833484852744246388915369361575011689918936117938245308328004535828257694279870740756113750347285061108736806359257362386202828127774979266451825964220500782715512406472872386509916149183546980830289032569339446899662456274580098525515063741247638235999803740998572837214455672946525701421564210775551588613171718099521203939998836167264820524730285304865309837917574937308752052439450942479697459554081203125972615950030462950715421494002006624610470332916867116625220536812696551108708460145503211827204069534070698269002845173027729263693682853490861524989067241746633081264782708622762784372072420596880226570020198312446966020461724731597700567210503321842006279641130791837745075951610614929040053441199620881336434233297994581839130233588572707127492755882526996157371206249439260727614997116674392317549948447811768916018427456287399814265402703005945261024366806479253468356461878467162790428385329457283714650540872227057475413250159571852726878413686932962376290441685469546994254833177459308860497639957785245656573059093450017036953936244714213898987509310245513916015625000000 -154088425062666961401343356651171236205990623039336815451737441884392722908778133402313716850654358854968732366740998398050372873099918283238604926583278908330634723090480963790336152460005743625641256314540501549726019348471410431001967733794301212582815866147793331964944062906365162898436688682068443108329886367740877180943849520212326998947759057817103715733096552890895650217814632412071410939140357528087582270955520132619362890734568156038531645159149478298617532886346102478958234062546977767267369340030629804224737817233522777099808429586296893794688844785557674952053312592228119276421255983578123836261210870208905187230736008162484031113209076604670594794085549603215571188266131374761880687273779013351726913847277524231424512741378754913847529045485746752093771670947669271711734649798661126243513708616485561745850185661341700524677899053172148994484707807439489001062080608312328322041518912560663232025680971973114437468699980878278959513759288166452817752357176865074438102038323414246549031745252845803926532082433502544145286473755514986176127775797367966048406803361503403488753935899409853115406286707909236447083695302617819504220281906920026162327757736485189543250239442920279664406280062394216656684875488281250000 -38368162646297924931450628201721761033941386799128241166011244057775858447666569653498298756822185418610462333024841964676065557926022770835267562927092529811308194355032402416524485525333825316595843439949666174480669907664847606239295138749843476322222048568140239647648160051542621260675214159490081732087868500123293081992733609023422313302036326890318247359258304031280027551166615967271000472722918280517909671026123627592512405808070860449054590206046011043596939307155207254752544471690580269608255443932509290450893956458850666901346491420364965826356787166000953891445693107123676702930685412482361743326560026861872667410857100893961246710165501761627373330719337704414760862713193017178975582039548560504882483423695168221932317709580795788670258260290892279384737957779399828083850693935054764850678725609627719462585516764658187039140633721259368780916929333077170507505301493062152717108326904499520453233451270006897574788287536124331377202387022803931866054708500547074209821755026874736993566149395243337231541071098858680691924125860644795814080499247398715731308753943924769439370875557706097403750389662466418183318280085219993065685430393822906382045776482283559561612664920438042770456377184018492698669433593750000000 -2581981064379271749032365739296508111167770378814701403840877148696576483225564714136906276616285352216699825533511695974737499855495917049424194162163330038487650452210697051345799133335429082814777948112421583675671215506404000890670548533547949992023034031800778895170255701735278276164063546775256958929017624677195857951928188396728463141530318928112629728975694658702025081893410232938945011500757794099145502217077136866536825118305219107578278581404219514125957782722750772709333649714218545349565238605953086169615674196520972809116463032179352624730325605326668005343990299813446219422482732037463859888220088298715492782139337072188935071004129283433653651816040902396778796702230307999485672344338238201643425554354623210818881048965856450061739015541565813213253719157034711951064632382117620760782238110536116570226932563337808349592484076811280133500097989051771158190727794168253865973704649505747291234892965539703154142033762787541329226465817637346737971657426810115305710019366456997950956475215443537482348238677732079656318780046418183175643500322736790347145471778470943011645352328310869169738762312881641966133710136386891021994411969680708255824373728704722661559669508873904320012115931604057550430297851562500000 -90203240438732671518522965797758711015720481355250642827486637751544205286510324705321254753996683084628751352111842440451120390149121029098591713024937524246164911967693814636776408608048107782475251559817002980529927600949223342836701105321690443935517915205116549235335853576092083265357411137581099183380607522296550921897831282128030609593949206850161284719756312387734894886586481339149024423626657318561246611093993882059140817551291701570307366574426709502789324264548028863733111404413826388115758268082155814912144638408407324118776141426575505343915619789950404520258906274224847315329815353592751963227952592133850618334298870403037232555236066667166408420454404670962156524823168867853341310665986990539158644252436503004528785056963959046586939044702612115801695868573011535706235047289927320756156826725656573647520008730329271661826774729369940587433395842365920593119928692292458468033732425990670672403002762910654454159930816724330006865299583922575086320785932227003751460831607873642665146171800520263524881988529600984248347829037700672634964719068728256522002219146924009110848887493454914885106612458023454343682212493272465138085807272419787952457682776247718627114606515515760065682115964591503143310546875000000 415350678889857802016144905104926363817270159002199266022990405369473043322225438793739059743247755226929166052547016863609751009222373593169160732728988717468384757899661878903076068440677033367836182541371082180837535458523327833208822187019604094882927855628403692415943269531186594982952017901257828342354349626750040549039697880465576023829800578655055933317777963582788004802714213488087688165966232778782321172956851996584284412657434516522801164878240778360756352407072385101437952004508281912752333051058610731550622003295159325639749913685654648987484267193267857055992498463033848396588363206105307776441902942300383245480773165807647926584455129934529275388277793940995242864559429155175060688241932014481205360290135978271344849118303449697778649873767802732667022843476903210820964459460280464925024508338356953612057593146291582572406615033962352055186494774088870160872812350567247686605079506480330595784383364126419268401862413165978510063754267217761014011584521011326408960933753634500289759780410574505175791259122165289008227170541022467965427483118077206564573422443802754756169011890788272335143471659381205052155388493665394808384931335590144059663433065636554036891350816240731091966154053807258605957031250000 285921052482445935054572255427993377943207691568667437330494974654840356027105925188259992529882455888031417470958982576155850476101872609283986142429892240390925941121498307981682276271901370005797407497273144828753433123424062354580765867180684708097670500382467139452936319468235580976283763574690609726311414927243574397646155173567836916851181165592929782411115509559555862927510536222813313789087824559960926182821976406514378172124681716460277135847379501693956748208425693550110227829760353131606031666648001465337482488961813326156249241330834552958074671185319596573201477580232018583537168982411421683802924758409478070149986704364628907893412385712657985883146653251858869312532683837779443127487864131996195961735080276713286102860778737235358682285832480067382359423833368505837522607859660032239427768193622430944015270599370225322076188586628620267001421010143817053679748639274666024869175350160659127365694459678551998399020456009375036723150653989336297808649903630182572671978559072602494358438530794358634186799163667564871082052741090053588975969833691400821363034212224993634509455073933407582140290581932844904753016905795991893961604583412101775098721508959281022155263229933552793227136135101318359375000000000 20531805795761935776867594460427471950507389440812608202118035751403588605893948664342301843810388547275822118133727825674371935622152832706533454154893280971885884827604829266588586189545350086065363843784925926048882480025192817092342730280997074868672743438149015031954410919916516242592578107558133459017658665579422982161399565049712212802288628802344629004636148959980527013218100283507222490280524951639213202410786189860141506297354638195713923781961138579831737723265121923645442760129635227018682212555972396215661890983345650716329853317938798564036939429432503068711507440396278342442288389137639280001946944741067312972768663597744482988949736903734413466837638893993186036630182877129013317046457454608590964186811942902814489324795978787192364126452764648878140258857959908117215782715400998327593968458291128908863796770911606706505565867751602700881118119434283707649182138006251197857634998181035536259142536398214993746452392493035191042692024650691673951609551504601427510956237004024175168993904973481677832334886394168775651000789930148890375541409285398196370072615015886011596454834274185678149673180432033220803508561303493664020718321899388290540610980361674146876804769590307842008769512176513671875000000000 761543934554866941609767759726730580694650064839316280514201862731898349871597472739905696778260109355581226558995829478889553621746675157466263030932953355608785530589169102162686703702947470816570094904895045226662795637365385607797310254537912820360481641263111802044495174283340020044450398209926446979838987330901279112302034067119567977044714651765815324854322214519516119090447708288498294197323328657139453159417625769865578412763532517639233956998282720619959274289082879945800752210677289916374486431812951526612216832855852604425430564414884151682890812637140254730699411664750836745197669777292034669296659100004371087132266746430134582144750335475191336316654238755325207652072453787496542159766588152499031892567243807940570662617768558537937525632486195688088173823293703851823782329929705077972806811281999638435948127063206002636321492258833780725878322871322693969067128976729010060177425837630825156594978550005059870328621821407866651449360686207178319608838093261454275812673524033810389799444690609582730484067462150050553861132689974523898864091906370061814845828055772750924174114049747859734922378889253207799118593447289931892983828586444881442387365197530142701953792538915877230465412139892578125000000000 1345488260862574689446945740814562868088743466126643828529686166986648116724456632433269267745758792520503457740109539181469783029840567145633540620010013635409536434911775743009432132762871585191962391521923141342522851961232309028827436913411765319645582304855676657948636992224879191021514111252062245955340332679309072971055696825626424866591059784026729060774093003381556056960040992444032376086641125178075793501232173451474804271410768190587964931351721189631698897310667643845477922899076827412714866832569935552779326927360562883078393418512548541083330368170434275493581391543816642161066722860694770284140382891371788093034797314626108788776166669715641186895175503815300403629419326198517805627127597637359982317391900919396762492877657660904770841396434508793442496829610670987582058799747178518897448726099602497922840389627711164115632285011689384126319976715922291862248739879640246922732675319778899786765077889907223844689461144612675439998024690408490884402104022600116663407765295897822349374919342041794624865418173726405537994449696910539911854043530536997722647183933389648044020803534174784436951284117676487928343239715874781450748914149115152758904205048453303975031225547809299314394593238830566406250000 -1942146172241341855883437923258525470232742171192423119910441701906519152293129397346505187567310934721658848326764899677568134765938818956443352367555414773072304515103353719925246002120307778283843623343040529740043847136020343387057481972460953089081299289842943195160967141770158051142460312006804376395661425075555777837653611878997557157914712873365261199077548679152203920768207275658628283818382822079960616307333010821601143043493092461414081231451937603352829166627473325563672085519469143027904502499900430606316976689576422967395573023003552802535644203357862991332620607152383861932768448921742795051784910008878446810435630196980570528122991301697695128543131369774719174965024059737929672364728097005842155942792306767919268763790971791161423815643377864096615094701834806585909262366240101077963257579652069488400973511648109325770491415431036634543564365732072901730136957138359475162942507263479363229685732798177330404023432626507903732830486812145286476471693227955977307368716155517532449706870690431519804367782097341050922275421935564814156605100635078848310213410143333100971389718145569198322353677283094713593306454919764789334839256221154340448988375689653128330913745003272197209298610687255859375000000 -148307330042684306510751137053714387471918779542853775554541617833936080173992285970810359394424320809738925239760977321654905871804816287080835642784173071428865651747801442682400290681092163327419143805901491249693203906176797810566685633662339645312060252316772903736516217752005534200548797906369888105596723218591799104874732828466305693077157357247117828788588343983702306888560333085472504946722050834040973317914047029247000590148687830945990341978957499558586204313512917892881117705763989279208384788855297403513974616005497259390725791337470530770693137434021724135024955058721554232622362234215573051867757933064072332286677107813549179447251355813100102191066747564701310340932109681911604317732026540170556530000637419548769035030347018872912324680811304090737673890746224697362127194261778153131092915609265943553937531838790328585710368483202673103717778352134860035339326879105306599840948570359536216845695935223204715170906600498901263351027459147927915540735146564958581723215898477027912409447769044667982809071731637416090717619682795557169638192328044681945854427504738128131421057971327280080282111088463115063478189921298263709453798614441532035106788470050793310450742978900962043553590774536132812500000 -5989911436135943845507415477149246393049714698799835950840036991151938505748063478586756756232779511109324443009271882592852078540854507686943055343027769100943052010649833933263251029479702837217509078749494416952578289348315646873631901355017722617379184085931329129307719354383900695199195928702894231481051976481408956669585289224112180966527323090611246276523986502861082203500212981540398008091520667648504891137075510368612387640207762439554612516627173915375902782628414369789030397632073992927176409257945345192271764230955010405573688909800650311341394069226816539435154422492709424689528594755974628389460423893428564384349138033449399035454159326816028244897399836590725854148934494890203120075771994185007956488114818707526093299813505256050281943628005539205668495024677751456726875375418646364223656699295213093090403641909366682991239542753462197279476292736371989323310396337205259760203148910094124124471993848433807905965963773628992024437354443130116423829563862491806541093068011191137678854950019199000541330628853619708361389123935188261816165575816453288907817365890992164688336971254911634088820674386597302078166605997342883976928916133585973801430594630132442368619649641914293169975280761718750000000 -69673809783848584676072016211708409773654149562621455816379810860789841752461343728160191112840350453654073703224393995553824008466121982267067912740985714081298394714233380667220318848621313042692776547062575719627317190289000457170342371454470362935329398162277791576120072845849455460319805071364444403806550929042248649587715516283588267052156885421401094514029330776026789086230258936239731732902884096183657296161610058329011991375997720883593820245287379988574558902462976464643216346693777096926249580563336445625201438254159763560360638695326306081365320575152272261072735813083464376702677797984733777888911805661191676192365391078281068526836745639762602232862797080851029911387263076457076993777463222393194099257226232706929345341588385764446865230634284405362911316793350425762627255939717443323220453206395908720820730114057063812904420168840018417469184434842728693261185116221171578092279126180023912014542832839339837102160846299446594966137995217451416498076167687697273163771552823802663971865013508308820163239978841050834676726575391795425946216889554929443355247179468885655600997829368904914024665236441041684629514697350420682960357009447785001213366125544582119211156623350689187645912170410156250000 9266675164197614691899032754104481178611162217843339157187851725940813348975277751480845058789713129348810780735709789109929351517844092813234656198355599269215956575921169510775983120186179001259033007303745003131252649566636078789649382000875946567166790930789801705416460638725242428994424467737176971999840861985537593659789593691642417803539262450744284043715237692815342833824179365662337694841011548322995617198362447158483026036016897565604506033586034487187341934523113224052802227814344310752387045602238728843324129191854007605834674090180159453115287128287651050584777439467224223976484477419807626552341533159658491935127572207401025782745356193696866284869935598218530682703144873721430388138202514590427440223257545552093837677344418416339016506361767286383326931769832714740163260477702944234443892644986296143742206270275744206365178573492817234818155393312537047780653463127425925988776076715740359248374844720751972987654237038123308143001464396179429197570769160823554105016396405931014795288367491884166069796082241513255019303842926934722965937549219267964486521628751982773300328005587232123868917964260783215532548060378438882645454645035450947115855256826233432576600534957833588123321533203125000000 803226887594604227368345505761380676323582548223384981554267135015262166315285072934793394926619484927283625960050999051298171215557496327977075736751777930329160252231446076045709277669568894841227072585943535347981669750931844119943083114522163065219331515517653508412949287513882938016638116102842200456726784982066758348516545071914894986487469893750484376282442777337476098238778842852645465060560449493902513198332652063335519723167104076300638654052326978626249726623989262589163018400280616184457208909674290331148273360203526353733485518430070892559629375463467086149669422070485754989993513556134386971675999422299189413325642867260705918681033638641316030146321573730921884116021954418065922443770119714078579745401718330032282198464379731642033444633809307623490959342625748990228805634276910548132641559872708786481554655766589108752577487897194249789877750683878725167791995037630034352276357737296226401010247791610323390186458564999926384998409088097785368919931106689819812633847610583053542731219821533460280942856903788418179921976872467040689875005357955507910018719618148077241070665970845410439856766960274894710218998464624918838781011016316147803492057205554388588097936008125543594360351562500000000 33756334338581083941385495407893140813641576002505400491208982042127399783767937907728891284103337478359050647838236568110788206392014239593090529428785071738564465640286889909657561564969125000257594553632234365973098389931513665911286860985557207726038814719603635245164016603213848878853440452294343015474787328223091117409732618847191087774156949875297175025375605762746072886616902039118176479534325890135194777288839716864476278799023823892232114882132772986144375866411388682996178592473201773022458823480113080533349408228481552569146238295113804732590083200306213508480615555825609114842863211429477954168470183006131269122828276278800859394141968768915535364521405534551726817182562138733746475015753832281801837796064254802167821709199602963220695655117195520482157921904541077172629359493222213075803098118482002041818625696129678461749937892864240525395121191508732903301138882730646310491740401814043577347482102103589590943435697331017292053114955619091985054332512041310993490399007996100655885432986750194256346805691372997007384020040541258540753811737532100944090021425464809052934622872775323401991180870977589601440765964462250876741365825050332584702432285606032991154279443435370922088623046875000000 478659554073772156763125593798988717742269281447447124094361397328026390101548792846372483456067023234753108950393541066951998028606907448036078743108475231813339844750132539515732823931038664673277167973649029117755159173329421130770392287045311508113140181866019376136272444268880797756029040950194055095443215865865047066115493335899050277030324728669331843925010190758655290272606302826121459215211439263885090970351650608884855376759911396354269271881553493594941394143625380016612652584400184608125582412697643919318098717685612020239046339847567514503992636807658067248871732242950790860980461525332016744269257692502142602476892260489627140391479272098161049802562052070453331751650330914975864967753836998905559378633473304695882502751962690656212629181321030138208118963081907102629384806160237965099270744622943388776516394873843602837475320549937690913094179568612840205524666039209187406895116608171431759588201523902659815915731908932369148688977459022337387479006967859981834169886088461152874481694035914268234142139741543615821199609504299535516154626159307792291704530462107756133361718708630148069230092027991763713486100656025452339022639911060346898922417471777812636446469696238636970520019531250000 -42257266283363845617155264759580834844647874486000838720758871500859929135220778661776191951696275888264235459837512075866809001565258774172331560265871288076939231186920144662068627305557609317878312027273286154647816182500582434172911599599165540605982046709780430956387067949182980354306649656382520926953145406942789934665765697947357542308433355040522476551560713748792417925899130735390270896008257096075568202939169416728026445660970904564094315129368473609166119890083750704226528427164483082094092070162944486870151286987515448393216166967179315743253846479148972085651434952728322861522439431367855252457419268863084736709598329144430954083365156481957522040780645911485485428410510728019478701272405324757404320889253559685670719585930026210763454909089351083473964146289959793620608747783215391710068912277281747774713706658539209531771040113333745560865617044180228064909750065071215454512916874303080618352280833101108756375051506663094445328446100428679468622463305380203589714157340210154865453434144900210592171117206358360513074941831562518174052482383177540581948361392977986009109082487399600994617904101853822456758654046220505861311336904168015369881103437954550372523954138159751892089843750000000 -3791164795471376620782733055298936446301789230147842606248302238654294393865339746912723731772242880385639912101712729694676834402665016741569394858988370929340484366484131886804014925070733937475232374655031797453335161047085796589400270765409504450619286867589768467756006725583266937928589449818386374961694044038256472207445487861864532559262079644581366645387564952090228931689014727803740149411859573363057808890317457227829795029765993662390376854108474551843657405047534558296972296648676602601337351274248970721513532364263556996248217655635017782478800880403061784861844447650868033900748598723473155639721556008073827633206806931549563624803890216023387521361441617091049354352992151691993855127179621103925513264810520124571953136404390795976743723864454011561435350684950344590853022095350735643395800933313951686480284284110196592974849584500325642425385763805428649580050081531822990627906327659329906042727915815346977612064208490980756347072357394563276788216128349494323553783214393302091139838331749107654217253558542420751589019127061297575728662031700579320709416809434079060347564115749674331557806724933328979326912275572310054711130162971936356775242565886330226021527778357267379760742187500000 -153700094278406499509230702544935824718586311080703613018868130952138964348106313488312352525849809758708961284088495143823566118172230470788817728523661703337569636070101067011800529414327675416678810841296636320552033795598424775786837694772077049762267503655234451180456020430152934789008288102551870311195965520025907151804115010645262985301949109001808201293844402701149060649737399552202262697986333885647515157993939267367203344106987365962260707266341976151887186920570587661744049680439168088344639393003618791642025175855914160640173715638477945003378546067368283820944516318265189515833810502680463661566081126872626016762942653198799158155323575169908822404263381283030417537998097227759224090671815453764750764156873420251068938751158672462858687864044116230082422327730241964418737000886554228942100023355176861931947268779093916574396803420055978833828580860578540063041397502743193710245497091124769514831024456001679760364824127798795204984410766390053212208607763341703613465165276248688661344630659978949242575126171556594550708134009095228647555141476182403506996437909476342075728116685415589879129641648662549267192677357365435594603198212299859548753133697829298398573882877826690673828125000000 -1688889420292656647214095903950276072491465689505609743977845349672003042691192131319164105390062355576514395349141390472069429392653236606739487848406766126470670174147209379570460356143285421908029142263572888725795049013080260086535981762364381497953548483347884303961249315555424226874706707558457514670654846399159801765464848999137840875185046465658229697387332612178382059555985262908824443359025083978342494572912472191813256031221373066356759253240987661336212408948633163946795734114923514675854224358410669984220427357048756098361357116751518003620005065902408763530713947613616637864469627549159051508755951085814654518319346650234416035610656520255538214096653743306415427928708864833487764940702970260722454248797654846398652616572463468544200304704583813469644574989064906842296641502592860915332754516583751233633453357231108358148375305632875087587265445791758530194101348808897192374936747247584430490534267642416345782318287901249361203477609992517943518002243393186715432185985698169227506291085740501372476106789029636401382859650125735100547800353755120033666306524095708004786168994496807756009664461780810194102975254541292337810603156758279438627926016813773912872420623898506164550781250000 227122695051871721575676899310053488222469771143486932037347587546014316012751783242549992382604889557442865009368530261589258079751389111999482366259323601883362553406985592731735177707590820880548843450423808331306301971166188847931558430416526272963514272034104238693848691753082478716455674702482428611266372569477209493976732696808428357834368360210205688603530151031632408953388078806474406175504217359657783980852026143428242093323605073696661503789563887486718372662231108626894694783941081832055427866588396817389346676905264580529951039969409709932670633589335377151695423952442280952008638793869305423252338408937128507049899588900071769369197743934826633839672386537540923971490315694742715184453018874548219718627206422120164044213064975398004102488062124997598237175851424948692748338661388910189556093310573806886787099436389831435778300672957683528167751728352434210519149113736080434957334412443310062632011546955458920687589750168567133977265713559815445760783164576572412342109429388945101101800334281901912918421246541395924410995580953842582889099596848867022717802653975756828962641405334098761338230300006709333021708205430366519181251515747781144494155114443856291472911834716796875000000000 18739649622031519866100204339876664516892126918564314904027559235390345717387668383187247607842967341289402192273584827141558160915060817527912738965597887813281635719099732913529756899756459189762150855446989506974692119598706730186563965106157770751639898095940545408730818931464811213949760504246072706550608803119516887366618868171222075098349944159053661838233896078817080542600510881224309931216773279186289974739805157569403735001029586651982479860214047593919304673603563329860945832263410690030081659693329252992446570574926087465687455652400711339992420465895684244762391429309505255665698293001488756787589225123454895934980073928540265669095045395650869264046664085189807470923105114101170342508683528103875067542949484250408451004292594607789928939733426786722025414470543809225652380821311679084192898066601001245174846805482430716735840914821088223716954726465293967499650043778923009903686931383876374188739128959661881677262874293499242471023518104573190859248319689217223978454799803341890898318652091801007236980777462251300126914854838165828846425522706926808885671188158612738746881539204015748094906920820535611406212323709439433429333707629635408231649762456072494387626647949218750000000000 763294583273077001492722759272117840834856196228170032616379762004884390272515222697871246305722381354972615346903579890681952833033316151690863031291735952045963303766934113646739732588837219025373692506718474770198097029968207809758342981510557239959240463816714790192879221554874795734607288829160912533811958767231174259953021826469881507778286914824301966188974928247181626385765341141724682207872657787436158250340503170395470494456830472214603097497563885498906702701466616109079083539040456743600683480294047031021103609305358587853744219776297933959262831054632623013295318260232681531041412271763862649121789455739294157276211395667536865550459394818467857523129131911676578145747697485405788851239236095847813679963506600733213752112680523557284143065717261836749651946483791551861177228344957855483519209270309418336057208998074189565604517316404705650144698905498012590477350972562642361038445860145486383918827369296417133093465106106555397889766574663426528949061768566383925197270287830974119368005776546631996024026545357836369965346780487611541822713624349808266808650818612625007211626648448630828410348926834374710253509346392497573449142391453781097965247681713663041591644287109375000000000 12347939532816232777267188917147342797581157137915893362850471600252976650067016899079366973818173554902370931828160060387830936445939142637916169296474231655882408830017451388892730124480818945394011188376714330655715645634952131875632340502183039858437762642721727375347288932284160205623283713483466984194212996198125553524526433637163053407074391148408264072972680989575093039485591482502182501170291732281810418863600206250585971653075522672476846489906476828613386270732139750011197280480344298353067201281369812044617790979220112270045532970120817272105972939310093318763006079488440793181950502971869076195819520390382766590057182617443775031974426221089475395957264912618536852168896942607835268052248718047654696644910445611404303093992955490381863656886105659529503282745774495862290894530379282231132353656712452023384631606030761940721812318229255024060856962753960090497816222347231211149229418548978792143654718816884346109123294056043603195120667112235298744677771867104674696868326821473095236234987232918749072681947085583613811290852166300792466296410903055262534798486875469759402643257313941169864513251375511961318489062686280934808169231081133830618679070312282419763505458831787109375000 -637705808914717579528701882704270476403755223098825902044749999659930407746994046178708051374725672599861455761927744026334048153183607128936068210267149639732599292120809218084744514714492477294214789563500558479126186657964538322591965294178756188812735207833659692635479065050269842629207700309404959339033569021459261849167740871930305582728553224692628985633323117765234167631282844683608933711631205735318632458147969457945990449340977349344457845051394291811639852852180222426461166537871248155593549826765518495864160092620847995798470565444939925508934376654344422612903924353689659884166954824142221181972316449037516636919113932458887169529276014717274573994810850803120713307948629221732360757983525808918620730916091084412273050722307473854673777666520393993897953011393548306524628889423120789619674143652410888578998119765934778912419296658072391931813932626408156883755156101367547997451045414737596948266784772535209078172018835779345057517412069822496063841804253318051565327570675091026913783049850713674628620853881562239491015733409845832105277561513287607410152639144448812489463300082745072480806701609740570145698694090018640866966412371428379879390035966935101896524429321289062500000 -58427243955816958859008046182016383248548232287281306244757342495950695897964499675777080371649834526681626743866472988020077012685415246890204645632395730891951732732197100267006236296128707420152845977388956284295209641927702632680438841405747226460768806040514908358194555788222668192927277736171967997505835548300468406460438601351565286343691678019370509768127445856733915486288887975373151229212235519049849158469951393471696043097881196645966844774154979767509344737874346555617156135111198282475996279222357849774681033995279889008592008084405587426945260541917588888247625995577636756223544962583915160435213410293235341766326701196564971366248292003168383884227808848128836071716153769778706295600104727744918149158028090750347559989782383745084590340227870038176980012518929087079400775022891582676736324145020610784701893706590163774833156911179888940913253431960128278846651979107845616675508547102302423064196480898126239817242035655925855413165868823490590445007473843876107841236947122042771369276780726153430659216482293057547044393508409288609172390840971812394548352288808526521116298811304255054599945682783169684831307819327895676543012615190494929429121384600875899195671081542968750000 -2124025307490011179982263251134217822721776473648784320463547696540889955255573630312639833680825573724219363608259720736907228484273619695882082766868040973194867725649495779768887049671301336191206422199980625801468056724234741103458684553852554252094209559642468614570790798552238781887210124960892850952236328916889646725309767114423551015502450811276961648001363381153448163652219145354314664135655829875633186823062367939355020096065809878548020058724288203027390541884754650366621897720213442861600876927356097773019716010176785463592408429815568880935122759838830540327776683005192277808672197392570577089670161664132199515375854514650141176524205892580214040861012338466391157443221878278927757127730483392083465087254883705337141131897294891018071649885855766383738486798812070614274985295249893561319363727440165989599794492910720099341794401130536292189347832948444391600826923099028199342716057611251342872044210744711272684949602654071041214487987565502873092155398342091169113225682249131986926424674640092382987856627463840018590899736359634417034979259658952089225623534983138601547998035908214430420373328251655710318135521490454547332852523570945191266901019844226539134979248046875000000 -8639513090953758075003111199624051717011820778802856418074023209120235636271647085108555648665572111867000134097731750040508158892270097992644909291440257998898479258654201093713727651078162187607010063419181762502986615268002044916365418550327902878589672887862900828888260558196606394846054352528151530310244594664633887045991609364193505551366661427159946060659222454226936694755433524582152060696659446388321250761034313283396583348785356036783622718426781390509629085649630136825279228011178174834498993031075733649737401049750234074974444595272387078266721540792782833118413221021978847115185980960626637942219132573650071052385248708987154992370902843542509329359927796258419252418573519689804051971379393801460946907392526006542919985387278287377200530032796374155748976864755059298640907734513017974698995125257878320626148714931948369105959266455451554361207045698903352447033621207492424720698564636263689814651406530155881583778696337662470843208592980968444636396987024873525975318353715963272840577357134066106614636227288632393552442042448521379778465610410012416100696685336678545284739920486200190704807792526936599559803365655628630125168420338110930600805659196339547634124755859375000 3839392811684435618398616625365049987452841876566268902556817626262565357024346769309288340367957997954123697841749467261315675378501412661455862494301730554542816894205034897848506330137455639164293548404694210238629689761183158951055384788659341414369783305076588513516912686278295733508889816984630532001567472106314707189285181364652919524179588171270615949701471219529022885998676054490448454356135299454248644095971263300215045611385905942108484685846581649310858055188685098410578177771963550151736161399197121702499513443974820623049996825148687890921341080835033936185676452581206943904371256565085646832756062655384253803428336913690053550803361367789170080577032754928058893981861567452881286113095034257322799647031312509263774537781399293663754099244023858092223515761028319317031199013957222307777945133902876597119679657353391144795031272801816522431345571166585703106565266608980656491207987016411670743503395011387069126356221207870271988181832794768465407943815682516732144793336629686258667445270592721323981630676624534335302608971947836655080260032036463995976595913940050193207579005963473795353713531921003409106661761222374803439614989603034800325076503213495016098022460937500000 261549397733374955283784674508898648546423356484985057458384870864125900904945193842811255729982064660064125874909129550568557822766933386419267050678275411019026040184343890007936503033703218624280450198665175521628808731959209084970864571845044441716450922402119262687574260322084956746166279469607901129037000019095659265981202319050991214909532144863476576018565781571931122954015771953950303658097210906786885091728152049119389334948816599614074989674948676569252991448477230399236716216320402579652254239394222161432258744014034582209726159614363194866879516923563061294966303997267371213837888325890154417930744807497383140497422629820572912431350968103220812183567365825059659901007750673853230378891524590246464268631653579632045665054101921485100667854006815341200323313482432311878267142690895230506590256992890377787531141455743955516596104157962412508019072467372427472171869945653525306177497978284579873187253931250961166860170885242154481091333940384161386364376747639868479542150781043147651357882168996600226281874452248416203476951258435689459784412897479530016762194580691301742141594413765941444497867307244045215448006185109170080877599717794623757072258740663528442382812500000000 9251370474207928652312039669973013842611113684954139965166716057742525726659719405215002807057265871348206298430369021499325800239897264451118846827965430357487428577474860802817278244554753675169465786566561251915122637979190555845071849921343789565705003738958631269892233399606763229519791113108325526552109052000299479201928289377434398619968663876962301289799586613472344453155089893771442964470190165883913400507810852469987505900366239811215257963350623786362030485527498056523621929722341300368560394922180305941272574546905414092555633428806661133572968300124012803903292120447058272067989089973000256802828917804292061832155802122628838281121762862231961640726002976811658157836967217158564385789283140423313761740083850287208401633519924597152000848446795716610675004930698621254307444796031112683614994036763263349286600183733940863409126874920597317654437303005753058101966783306359250725337380925097404752996889492480750987506006696266922818478018073847934483752633422170860128303902765819392917965553116995421628005222685672770490371987571044158853062348244318826291888382573704843967006874306663132563695980985973387599414938233723843289627725150481296623183880001306533813476562500000 109637984167496308473219452670336372295830427945884168585135752893157821529307889001907277120290453553399753362392563347579330565959274799941764963710577044076017975530342860373858985062195563008686375263016742137875291099826524810893330480043366145028132506928319603511265145908768872343016720593045628868202574985598287881399139237995475422836946154356397373124573926480259421904341402404103850020378910187219107954078228925216954167787422404502493255315665923242648371965828248762711495242635501143578952392334851970279486680202185222007044935780806832446347138773107704635682226555276877820464193933308526111947456468294649734828958834226902302063235682424726170321020115490358443183579646959590064175387600230982728552396645679774575195337638305409313191527941132598246219772431966043816403226482339222062275076556455944746194749788341994097761921452506059174747752930134035306303736789401353772647293788863295580725970672216952194272829896467200847668568756644047748207317708983507193889892163744706442211237077282910467483539923734941811210129803653356822343005472831090306275744650588901570826975666950185970722719235845616650151466380175178523775740557777425010499428026378154754638671875000 -8344599183187575849597470225050739679893637954021975993194418599779380702661816275709085909245824678300018746638200690711414222073352271309386416710594194355614313303826660646489605583280081420382336399369563662748304482855399433488165621611109305172427594743367796445381974992336921369976098123116210371571309265891789217125156224720344514535849697073421585803781477243604016030529979481315317170777703612517081800378196190973811373220781206074696893327721880158799517810211233010586614806769712186721506173849857095969001289314526698314483210770422881224036958794122792494408086626138512887367648412300169175693423500381484773096809829465917355514241850636464206210117522124615513603874495640247655595228820897918570286859526002370710378667469324444296482161171030255789243305161632391944537910432082992458357400938611434470372437351446931610098148524095517652459864365654115043356046496969613200981366484612748427118925359204072998464162766252183485507476838963788715689735776137575190246019369078690653648381455057741395463585975672918759886556537482518508135973219286704322918797343076891378177345346232700532982669870297608529826778277129284227230099357797143966308794915676116943359375000000 -603554123796162284560752665819022406751708085382374712835611478448534886142088811768826564184025531643176498793951083848667343216148915147889153132485586317194520873084555348749965517311208868771637800824307027391060849905780849648164515113682053948422938967487528915496598627601294862121936698099875485229288169602485909492020990003977301474520663080986775013251367415033367937830425523851581227509101757947398484607189249335928184570970075075968707029667161099040567236545967312323371387224773333795355346549289769168818028829381431336319306803191671307610476034970491573410552571215721371965899023699226056184969069013243771497006559332965766746637270750331413767820280510039721061675946116606590494178856306824498312997753511492117949866011216040631920322391974213329774612610684421927183526707561689066895510222842712827567320025601131807666755109488166291096959139101327906936845374289023429346122587095027446932193335686663008932889004734863972805233158813656102320313909526813036198054640914703877070528211834348096989564854574969472598430655434540371827394072765865920702783883804640687508775122321656175434719572465669899997502358912193615560551340770700790017144754528999328613281250000 -17479832718191088795439195669996075353266299798207029307517178060578388259998097457156104856236891063255574341988452487098938981417426242579285596603524370384521508609380524649972444663307436028930339575026263999098141380295613876043583187589324789582999578361035944848506092993769039133681607766546537821051325326255921520750822860544015477956102656770762104090696726300755205082750367175214390667617233697098831571880844327503406530324263297060575265775716300252975445512130543898145493230867755498188921967952168653210784704480777402550150722070504337555722490415077334986878558064666526172032474622395383880310262268730782849126036959539203379981711639075836008857076719996957926528044356505502128692643549289460002305689542244828243383650221430127938109772047217730292146316609070051547959014975424918826632046539120927708498071679423787338291248891573902864479942500562042980028679867096044598026578898907156163285190208356453814868674827940252800665753936970387214342463639862203111877294951841686843842382203261332571751315767274798431273234971522827230653441161652326909782069313060476773560525046386297596414439251699946089379468357794835103175001833619717217516154050827026367187500000 134466270241321342154247827637408142518879608574801899253380631598172299678075977467426123843813218193705669196045649559005368553460134457479847511392435475009390506017839831237282203680286408390285442127896441439591316738745506934643750664474476744679706508597954752749554429022381099677854271158347597498964953230884376398501475499986631857404193132308267770851758780961224560727620829855290117432625771628139258260963007521160336877914504327134779410951605055827570362744565804574227321805702119169176017034766535416018604662662322381060600290432957516166715217339377737916489634341950040024229820204531902062429612804763513461804232105440099894448304737490760106164870210661720875771408817979160406593780138977968327023188465127267229121461614325665712141266959240456866730970074238051872884639063033843437491371801106005935710344009479599583361372602165461526650575396039410134807608419409197307966568612392963542946238122010851270912129922105696390953014565208895106507087126594044593819981579409806062937917328889894384652966712074120036898293990847114007023628699842044370665706363230751413236141355285087823983811357261886942481386079020874886602587849893097882159054279327392578125000 40899123830817765307717761689429195556296996373690367010779712291787811265310463926079664421421088374515263534156405839780592181396923319274077627534672872074254124024691053746966028638952112794889339555534419194790589315500770017680465810119744473423050977401348330508308054217603000988175603785319157931782662851691170784330710022435374660505795489239453607650394716268405804660374189895823742357906522419257327152235072556523265941869483596462335281475881921063566857576847900896984200522037692858858692707250101202840464011782566873260966192809566302427225784264304558412841935570089157018240463366814447319922354280951751141499337037795955576641525413462795653082016701376573459326179873306701833506412402291167869907748753009805219497761638936855567066554080443901892263264681281224261037945112529547713283294695360520355629289610842035279299213619385858792186734139853617162580890217615825607259253770139024312730336933801954368699650713737972031545910825329179767118165480608615633179780119294381028575709212031856790839831963832497541158582249854888239157860294848635197019155927956981985055691371664450696104987297332882511120529314685434485454607056453824043273925781250000000000000 2239052507379002839338767772684173488389736935941461686958339222403915812236177172282699655520006184961534117485464034704303634368295603343480210977303783193401349567971341230382823850711360634830633917715661847883232969350219382279059514434867196396679287364454750816171488866271915467206837798718137763864192608712537180458595496694857952189434540102862761549209125805739074473060336299022367467851809779696054588298243052142930883786112825222431135913545760694276937197240881483971369805135564686748688070420942932133879557667060281289631276106723781215413793434292213768887875234347124966896250783052684184992677697125483273433367845648856378602639360912049692985761167473903166684584109862409234602045863485255001036803230517216512422700753166911674112937067126290480319856813482382877949663998995694637230221785336426296851831841571455814676715588689907646698897526717477870797575445743141212220803336530264261166664509826747080928884622908640046179397728442253781179148565841087097966271409942875772038423885073405260405192920561019041647189299922168725127814815001828522564018735111715231777837729248443949701165827509202817329209275146878477258383099979255348443984985351562500000000 65438598129308424492348418703086712890075194197904587217247539666860498024496742281727463074273741399224421654650249343648947490235077310838524204055476595318806598439505685995145645822323380471822943288855070711664942904801232028288745296191591157476881563842157328813292886748164801581080966056510652690852260562705873254929136035896599456809272782783125772240631546029449287456598703833317987772650435870811723443576116090437225506991173754339736450361411073701706972122956641435174720835260308574173908331600161924544742418852106997217545908495306083883561254822887293460547096912142651229184741386903115711875766849522801826398939260473528922626440661540473044931226722202517534921887797290722933610259843665868591852398004815688351196418622298968907306486528710243027621223490049958817660712180047276341253271512576832569006863377347256446878741791017374067498774623765787460129424348185320971614806032222438900368539094083126989919441141980755250473457320526687627389064768973785013087648190871009645721134739250970865343731142131996065853731599767821182652576471757816315230649484731171176089106194663121113767979675732612017792846903496695176727371290326118469238281250000000000000 344233651817782635914874438751764844848331797951492862088654416891321087175874502316610877040161838575886513141876862871053743496857944211148409629164634816024039695405669967967442441421533205479130731847414890085353770851188497752688001701054660466380048662010764167038859338297295615175306934165369849597350280271064003580163777279965777554954734418709165493380502479260734875462709324429542700627521975368036501148065299254170462407461131077465035292036108942918580128626088459710021943822597425073090603609002330665007627936415545295515136743508371241386790956388807009066213463915392102462028339723601669279819808780194594462218834189926655729787660127976345871782067739294005441974806574026650640880077155783598917179362470725804106550941732673704223081643415655569578831283390049412794584676001366639199977911810831375195418480664267774933405113861543581508225473013860889945107477553687545108394415647725986669942369592347779253535052600590582760839717286934771472658143044080754160179152843289103521121068361958129624711594782909747294459632616568611857980489471595633588904208289870723617884521869529824829398557074590430572752348362293439709702624895726330578327178955078125000 -71597394813710699706118945464303924646978763973455992043590361336129078312952207184511405491146305795094832504784701387157254067885777889604753803688035821095000099264022628966287133340907257974498670899307577340305987093690834436274516736365874338131966272966803230099480956902477984291559865411774618915026228536344254548995370436788287397708196482133041578355493790927893320018945503949678144174560189223316814118423938365453953148208182464760116288617333965836187424817686707806803940273634326520581824380732082803551374149553264240845417357600785766628239320740156764106254573832874091200645016053331492373750834252721286550020247386272577044405090873654624292278586245107539667058869684246536719125067977889628169444104365034816484899431306977804034497626305403823276631312830750931140440125339340467513884862624239319894008101598919832937640955459886706132909844482302128046197472735625398673516867169923711644816139093428034825702092095243275471526928125830706029946731068875583946249400122743549312378397504558418213893389382757574374495170443357500336756494998127931022467355906295712864503910589998274954913543174962979182098302393527644582604807510506361722946166992187500000 -3955452305710529148097348670711545244887994108361930918039463385160318229820793236808181771036429724176721502496037823110626300501353530313206353969057538488366011993846941933567774014250738442381805491482178534710056385942525376254210966249026708756384572817326269500598508765847846008402324344667343979998662948306851656446908760090065642943418617567554928726844161491162680117365476713113722732603649280884070708721675464447938950404309484017868518389626706978672261441427651378042446723316274520361240799145425431224765833736234148405702209065396937081556015742782613575503397330719351583315715841715247881813813290685194380882782187244524448950762017589371953268786990350596315949799480469792951462650552692405032144062077412914744196241891105443885353024828042204478010901205381427541989960630676285468806415796422002786745188519779577414724846285541646605333031414014462570901309844940543946562748986785971876214822244756114695342581381430404532176376029601176632166409237474921914027570894698603328769413689077583688430812230942519935621075143455803780808009795278378897917764460902093209657508641647205911328978190111014256623631459366952078937629266874864697456359863281250000 -87499464331100955340675169387028044105841513112765474990398306776822638996743166631179304663733498578731204572748979274634118793247874312405111712887280179406326341868733445140534846640934946554588287723053395872299661214145833163692867548464905507804834375856216305255128498095646796624440570655447034065807571847917487701362278134923599696739431319584601127557859662821893247132290037645996900176654013431987115659133674491465552344863538739409813696180092982093933631873600538653088702076233577259036900577507877542627914959442691472118075472168069431023757781045061012626164538420898172893844193015760621935719072403360157774347604637420537569757016627729810914909801908793408367926963031404683257134226561018558627571140143374618700060216203143485026280786320742214944615879531638470156357839692318559000145700466054235112052488682308177599902761868019815179457547370801293357021098116064091318322373429692972947146542774527700484375579367856495504994880338932937163430803811992340426874100059510571308400052326186262414896251280272064615668059078472693271871862543867752721089008428141944537636880737713001940728360419171851617716438587191163378520286642014980316162109375000000 1839420142182665746457832972852010110663562989020535007333236915611133693886648784289022800218970922003355196507586312076021506040501000521979778217404512553104873995355276722550072945929228394838341194044688694463435539844667169281716558423071243182224305145357914505142853786182931665375217613001174613377670132289579365016415741209925498191626778412006619710743571672527432057324267045876569578223501378055575413472888527575812686935069827763577701882974075378081332148519045148393743501368668211954071097339918555833404528402874985141620146409300724882228174358178402951937042022278816118999537001885006737221782657819176490245568165416932932932612150702947034700328543817926689518714643390244785778124339652796847129192925842245044879360421750779726015825913638416885418050305561939621773261273791125313810754410804197579490974495264967916848876872783727896083524796423491619285483953722933022936118539711217904429685046777449005824989230104287865536718674441068624185987781984241440629444601047852308837569442072784082021632325745124645514103569103929956533522228906869333583894323563774528856503469391167331270984736727136853192787584176937087931946734897792339324951171875000 248339585186894156659884782309929547853562653268850490063735154098263722402763313537093805655369718228859309250122819253444532487996173157608867735845905385024838090446189558814078217025593481976179142569339354400976681862186693536916532738639948428483806464014906515006938074348187170820017778847198094011645550113542810283613213643833155890363705899352310324153674018119894452667175719435552885194554729558576393672982483774452982246066750215072892168554965598397653823446847534134203222747661664035206747767447555493956501276879254822080399766483055961722813665491733423356561880025341301112114271436992735162298448264078165837509493820583364012274317660544710180080279278013779488371508626859501025520470613971264426266377476183008251825952506584432211364906520249992723331941637433279497131090801743872341357465269582736121383579501030419834626268723116550475694572785575949277499594797369573316827427060247422368928728739749567896255362521025146492449495200762961196780426274388127534845347664552238995157725384325288735462584432201011481336634809325957117785822844739452354504784707727491339969233925964380182812417970133709590411369427798149445152375847101211547851562500000 11233461095533419606493175761217245564854862538735603368324439013426040040132764122272549080609655743815327778955620983915191340546689431248812825269535675080076748763641388188015084609743601097612226451354236317194954741552040330259759484489195082568387348169061359943347645136547453157583587436999621612924153910559672320429486293110833650244197481608493662788617979206761236446520526524104105722207966864334641759106823731734831627930963571292443783019454422363434230774213773735653787195115289905371604670108755390347099838249503142956037972686593658938193225987589818800555236850902574327313255530053984033134024649411230761940182033673696750068761242531012725405949801848314992965237108865867215867812927868466883646134055107949209678449859378234292671197007177744515664700160334026500508297110087604519881866662566994771105310891339701202934590525994581797192032539916186030451101315077471885371407405878383887364390829187703105802304329570864225368671296629647868308210184705360803053747826580811759274813139076619431070668504499848612617299871447673303489859606052351822514439575332575740541659730084210107027693392263607580910944605534496076870709657669067382812500000000 263841065002914202451833508761356380120242659233782299411573479786145102679714131999146398894631939320233539049102395925004376186925055821932051986567982705407445484677230668876768567206229618477782680981471273693687405974062523487372040677631803888953865659934571815052870302887244610080592209427462615513437019414944222439388734969257807035956339398821691876315900797615398237091197599253356640893333597569714633194312640979683658410688812660107008176157246436114942020555737049710655597663709721497692202413282067813913076027164546925175457282190679117261094004010364210031482101559577257732438097574231490377371092330409636614385413115583493674899025785624389013104960647858188732518624426390550770317218594071603217167986557291443897738836618021814453182029424332703197519233852114924743904889225819477678526732483123133199244670821268814105450559039696900051761274134958818605181814767601483832421574652311691857857073376622032151919860187743110975997853925677933421107615791389780536554869080051541499476383633049737954286788173643626261660860767874237624315985484360402275215280508475937350800530719188942745555141948053787161881933442941772227641195058822631835937500000 -949924510182662768139117509136297718261207477513510869683497804552099353333772175426431363092856275496919528385980731755643627972184874446774403429059134485582627134465385437965002021059369106830231672901843753191167145341486158289328960713190657867259056733611751280429219101075996907623635619807919762995580243656841692996502835458806232569823085028719530354986378051627354881695665195683388292249373678046395010262027711659161771655197984396843566914663568451655174699416461935415310836489629117013584470722903096005755618726315861102601217320254946783053019171400799543835489548280407522446425797969499393884883556148974473382862616217546906930593693624704217148297620031944992303457140279553006603977353185904270845030104146939723041877954128848351640726848632991601313829530101340025298006936767663684802363891380377880407979800910467714838288174288238445232480011068456124462714136967644979055184442096304503894687131972797960939120081532717447305168241934321526275105578765946064194565090109404731647677562128612511114544943901222371401572859731247183096455821357355020239524764322217909792328011938659078102684484067050134890874968363050356856547296047210693359375000 -373662483724121778778037883850100754642139367888639362930627416751278271879478970937867564690883589792807284319330633975361927844903110529407181265144358024292760351404461454663573025450236591665247550920052128139301646025492934806175006828379220841218472737572248131677715478799957594758694692756975946702850354821576299918385108796449810083994444400323920620601840414124689105736398321546111050340592267134057852301201858923227083679581201682109131903703974597135616023331419726819678431670508490556626551628100215098625970644046516090656259804362038462679108409395324493889282456530889106693324539207088009296772309146602730829376976662055989626263733340610662742514813160454784320158196733709503999295907156822887203956822733288681730941568422051339898957055775238127254445548233751549474967248649387908847519245143415632778960628751255415786818686108121448525592542498080354959366910823081291184485751326899257314161156006488748898074486980912329657421579386007121826809685197993336487596426294366601553366775225820666075199528144652218467284843351230542466304459090882205157577811884461760720233535016878679507385179215934838115042992967573809437453746795654296875000000 -16445807131731395035897333897797175174018950571785223344841907075545776213865193739155220960549245082396867052764231766796771692438174801695420884958472365821850393096704443801457436440652740675260186938193393923694369428048665195562636780684300452108154165589506705483293174708021746850495337357847266510847749210053328252910227876126454861218121722953764594906625207377243856462652290515758962306313666651577954279709839368760233977889292698680542657813237212390162059691528028881796853314147343004244755999901464086235783889540952315766925724072639830792496656102833211401974353258128696311607961195609027986699572656471413592091378060865752964763301501492885358979575440291689449502970084788542285853280944685045475395556512929259327512300061552301969264886732306186351961742626945172108028312551448444859204413175766626111733073876030126364307771673146425329197678583036543771188339595631779655230309102647565646126270381685194156126667247456004830501297977715609965856360837063312886533579200795512342036103096722456059350845915950798946461394637866440822555983497665175295913664300392078915282085924511118168237635080744475299385776168037409661337733268737792968750000 -287197164340032281735547183908621620157346571857285981172389723718068440704932587309028066164613799455019053521665305871192067889085839143295293140544799021548405642465810954083820838292200983596019230040366201065500308443302380702088161016242742441689302830777980041335961774580937845119911327403371489560505504780079726784778173872932723031445902044215396914488334262059918935275144909101931989570146839921556576906477790041282694486608874566384218378951340738219299177510245905477890890823805599092517069492008189155105274997643922434397734330475966068817453310650934120042193247030650342068543576518017707800460741986324733979013781969930433148504742108622268292824830540817926853586880439449589689553561899683658063797520928848237862650786554553603163310713888339270914700135133872690238006440609353993832281850528547288698175811678652968499709878194483287057774422533086424047379091987024941366615739614343592444106925091702389813990772269327925294592061477008786233154787332391932365061333825790369062479882957404547557874625466063071582872641031817649276224689217438853970651286705903718324060156691493597238810574440257689099453841663489583879709243774414062500000 8897628140605536384063355050503950616364009232908645328203911421285767531662216586982362118355992693441811164703048463490806219272070726252526995950663614585633620111088945507263052320224428913812903624319983514284072767960040739699699175060186049699021319708138858076878010965848454611249410568656307344543142900641991967870663441113374516195058507163572958935308469614691274610724995158916553574537213042710261386707568845711128075597318495594267942058582568004376284700027220920771756186722374641683727328505492638940662908911177980073105971243656816735182319927999232713254223778433806881185914526148369903455582876198990891364602374885622479177360702060333436471050813095153538077084658534609800793940157580573269088172256113406732311490807115034595740366413062461945813533136350144581712765374641248461533247722481263596666841408529354063722963718900951488560482801944566210817814812954658954580670020083288427549407418984730515382714712176616805183979100069765357639228657737534694768071575727646600785678697804666681323981516422512075344841906685966785037635632739205018970567024409699632654230073669243550522168234736229697201537192086107097566127777099609375000 880018739405452188925247129246046338791215694205382719247733200552904793219375009882204333697317619176215384185349471256628821066152585394215822763000424793973287225597356387672439472850644359150495769448677086604298810503355889323801922952282429574072401987385395834972229550888418680363846008136442730110029814743646436274002050886100011996104774596456328011330247341985666404200461811795153804482486596079176733645353064854605699436529696644757042748538033903962113117316077537890786131799519694096197121490041449186801183460557097335857297237530470967621131775609031306106656148391312398261901071566129580426164108013181195438629378689432492969203465681592852628427601041840934319395474997127185737610658479440704993780330592583128550072850224954922365251353512561347769100810248352420370485185575322814381872773412434527116970691929657296781039178535161212056241954895714347038056062275763891199292854490267188910528223196655904081421051947556248258596670382455767634729830440495369871171582297201573257111712992849568223638398054581905458240477877057622870696244762764483260131344094898329736617435442864228545083692123451868383199325762689113616943359375000000000 34568552060860337798175195215463624233527895116404069757792035219417891126764884898541995205892330488839995981928307615373793236505605164600282827139005059696099809408514878190614860215367674597452068419698241824859678782521618657809793663947134711634414790301939886572294253361112103255081592954546370734169028696407305031469086423305773356535422931257681166761495369406765331289908032097240089554538634333619417918094307172418945736385281022879651402893397154915297317590424408581154430734954029849164821704043644392552329512540305730631584651786820904884107832910502625934767788103521800893220467887414951948401524789628921919830196069302817891365701962195246432329192810636700608924531749866002411498348378762710119622192906404157183789734878918220919326473890899504565697699867617292155078991970872744369802251953262764985417474121844783748296251167681476121249105413004993248793911137720746672326196277076982425985236430812966600986983671219425387639410020262923427312264188302673310221484325701964514390458996202717697341888444810214355746198753526474431780875842056388967331690333643030847318391821364083025007116201088308571343077346682548522949218750000000000 670347876632489021253880775548715293340821967020395902358225079313163256284536621157707599647463193888071000451630901563321613092764297474243494326644196886107797880984598077248694512223139720322229961812587236881726684051281721757312820558008040718198233090077398508760126861733223721957730065702364881303846448904470749664756039895420466364439474567700470904109516001033694012375174803021286087381831405684838453279913102813106950550843213075450176893744747191131093789988585621420602429550799014177991777738910674106569315762267568515067210545209357370371250638315847165398610236947182695237012269233892836264825133837490797793744365173018313463492424482906660554543524522455028457287091425486239704002926509429501740842528374133610827487160961092454959791233279777864042323577492057153244630282004836688666500311809174514039848150896780396641352886749138904554123074334679805053752929740547486576383499880119604299161580631551644487465868650523689866875978608107791791900694396670783159340483212130607543351005596010585380959090074243123854308331302088179698419066724892336287330215130007918040872554746413544755727353940955026700976304709911346435546875000000000 -7975554791663186982357666123574332434834575928794346872619936200263030030812049727133307007529594166676530809637384988466399123587932658844004680162456421281387363167656764633792140978619442438885029025235435742764610658233333464354978916443707687568721320188730666240123071137652241462613209208067025723813723079384149329776051009983900463327455008324697331387569983189622156725438611566300687776179138924385667427493958768327114182217477254233577793579822952689428480908180331830419340036632522520667722941171245141838160390643996798735583877961229974948140610883478246835077810355982257959880594818120240246467550585020107370458856146056038223893825293255051906272532660828475626716614447403254744439724558471075937570390148445607379075226423405518768222398602387960495035769997047292220046567507098037850000710874647779436059556725553026605613634981058070656457227559311490610480059714632406860498902506001094759328166545660707244100441972182153725051384699335316785133277569752618411103302508143617451268442245047011583699342220835365427737309397821795934783002924185901568176593259859362693363550997778053128982019351345122970542433904483914375305175781250000 -1161325077814802209579489098380123665490134406722465489055040834291521047784971578541740468225778149090148559252205744355173612611348633103665387997263391121532031163695672934071082737014193588014317320141539243321909291148764334208055573767849485828692654552853721608512037871616432634763607316115582394244578548040164059458111706157489931878767910664516697547465526609126091657879230867553043712143020517579276322063310484003621689560210474544808727185758735302993947936636470732659338814014717509550023521243542483869088533159073559962348397547718246112126689139630526349764207272062201037841773575815508841058918678629444921325579052585079452430299807860978169839370633796863296543816409103754316386041266505245625155123570924665148370342161993463543839322485165634695728381682437126175061069192877739748470299300584559162865742272122433830284535043096656360641771877367760194877649764161133271158182625431859327454794205367149741984663712796606944744866785289360523924506053525935704626380993294636299312804132165582323573945040045441002901000701494918712351688986685934169146619824110755272107651380780951190616230583874113335696165449917316436767578125000000 -45832370076593619617528987236170363409730889953496059269933000115739604521272053457879366927100816441023395582834531219845807615764327646776633828749402453255831140764556513920885601894590721708689492260360694871301057498672155223830418580063564071065853835338641836917185778100904516204006959958624994672946559167868803816483392274670351182633879242531041637899551618442589769016874132324753896844791840096061070850882704824208879911336121606737084072690159936443498484738790989029460666869156830106959410648926742065670542657514084145486476738424009685798004969807851638935640634431470419799071193891485976331292256535431779034002125342108722511624318846162597662801869090160893031611274455949349176465351044439063123633456863244095763669758241673775069104342838405038629101331730519422231287443774338396476041562044666542031264652331419453453928623718774140751720963634184545563441049756252598940442494472404941994021775670069258210127970655824636491420762411343062824763212604724593117882313550657583437131782893545397232430205487014464714173624590561147651505008158577756875701478994647592045269059184187255401570632029617513580888044089078903198242187500000 -817374404420628349420672424763112104203878124532093840457932136159459506596720591433216794614777977469836598679263016789311954698001757181573782393425714645396204754547758541037155202237428251284924219048009735565252032810552539710531891515010537657036935539014017478962478899502220865834190078385540343113505532461294556867103560661527695962087993017194512307084946093078393030489656861683122655680629205684487565952458970936465731091243645217750524676997756502052069640832178729839240368095952908337851885255182642105377769094200457167361769796683132633532545247185305051356231494015437075653273032518480130505210593665468440645526763610343174182378282396259231724096353026827299676393389711665942352583404329972413449920700271019035879549027085017491402823156384459077427615251886634871087818609745471569975998090666528120233775345745129701654102273662716754316707406040808214896519325167354195802869765540492977701667766230654145301108595469933426052523904543098015138034517030091462763952137181543058801992270803712375193964798659888139857674268744989865999700953785429414149428935605937218506404064038848222492616990564329171320423483848571777343750000000 14813795679360202693628078144420410391491114468870177024946001611084645870305248995279238923914345608268211357622718455158079453119715469264445503779616729588766796635191015090014372989833229798740271047912158941024162231004160317453167483403677844391458467725439231248518102251185641407051067872045266827790881898334763216652729779473961113397462391080191799525524358794305884002167194592993210999602829134743559256476054752204374629565454653258554710068458471741915875484605059986421143635639654325648376859538012680881791326554795656871774163454042213914677662020087946895522399098000722440608813462795243140454009903048382675212569436821456883975701793112399694660284655526653593457723503659161023614759089156699506671741544941494545498786543065035351464393507515318801463910843334325385732396901390918882236285907288307033067334258870056758518250118956386457047849972254042233090289071833927930047660700842237050473687865566878796064642721059667477597332685290627386366476397210750293456265014567832020029918949468431987569937096615144456020894239583924534274264257650329794420759973519445240042149272778989515034209212274163292022421956062316894531250000 1671532714289339929287682012918096745027173026406323967526915716097285483607886572564018023596416734309220403483047745324717879005607931583103320053566012247877425507720705477070398094568252113183672178148741132271278477420699337429862389326559096410305714772722670870541491590059342398679231920141079682137081960936909617991415192056889585403810398617942474073462985273543344592237073816045233129874606881903547284970318839331077321482023436852295868529228512816996964140005525378428925686621706264455381982215207207792103177437203773892920346292087101000915145618935306244315783608577848855961138202756538257170625472322927281591639469438065909939328305977163928769293002958565800207602627239721912463017209538246264934040237486541825886815137608610302635630851699691845526846321634297065054867233969509467692429617821358509235696844181277012291107755202603539334080920565398652911776176050805283994999218829447763697406100414871377581826721248108643952444334039683510542346418746208333548507489698114833841228717870898013463033216345958328747348844850695530810379662055056695684748333908858089745082631550894373961835270847586798481643199920654296875000000 63638190386172037337987239046405683905433393115295668148412664867324621620265840150349211374043691585783666969667603122449246390891919749799437675539187971656910841140819549926763121788052513184068002337972288029435434005473122315792210636792148579595639974656708402189137236342173529548879280860136005737444412069628022390527639046993833602989765473801748805738001847018905140022415807898571225908251138460139659215409313646872581264400941688100547323067709158935092771649778870188363534732003896367480546690798886507446338271096860277451810318004403732134195695975587639663949783946983254089281059445070286439184772479756593541886989490915121171066238041472862399142120303037185152862467544305539665109561029538307447444108976161774641651310583850847979975052072424140718034693537307568770435032451892796071409961105118744613123550306517458317951706675131046195955380808225730063471468639387816626500741176434523980562873323783996891069717605454544581696117384688135340896551989890492072255479602517840873980444491594736210251357445760034182149402859944541797922214272128077017795742850013324395101679961054413903198678781336639076471328735351562500000000 1174690633401513250934380951415624015926343321247434817532651800632022759139110848136299161200746499712871727932526723462379480725273363776779148491261035664493330353782218420929830980218381799125668917793866904438156068149807984415383892261203107528602355607483529666662843721283535514574836635657865978851738790790837987346536614709104125319375146191910442152872576833866257474713035843575793240344232169712910076615559569415099150297307327523189057449523288762878476224267080965849169366904191115130298375907105904248185583550145519764629114221506824305751886955193188907777767453246614532156947615087768856179340638884036032845894893032286929755526811447422805892031425836540412832651840488876318754514694565794318078746904057446584517784291150522111809272622783195075837024192811257176776943685089091353233939244114226786366688194752522705431956154110738689517932114997541503412872842346884541701277823476991047553201140990176338727470647273002351796382761573633468515738675143050722500650797496867810667868257159402084109016945371006280962786924978329706197769645195683473966733512215592448188816040934197293399421369031188078224658966064453125000000 -14131527486829302492917824575951182350323995445795369908796570662477516021435431162026316484573950683811714597752435690828497869934630011422782756155505834639047913609022759312756233580002202570424367632195842891774297283839224132111762996025025326324927968196450854824445262950994214838212728788235390721873804596017880820745347581138710284815753875396764986765911905523319810114359967409522559791507509697614644939234763327038157788619703177836688631125833190324764763205016591394231215391205995271977293024868303720032455920257638741097183192825715655190284088492366077168163204059384676017699478649049904548390740892967538091452732866710987047372526512899168375861398458682265131455918245771682787206930291234845020511820016456475126935632008669715246412813893364640537390942091301400707181709219474864311560494875300886412819377177028217856816711980902536993271542439802967375499560894503721801549769024071578819706392967595225423624347606554209992616603288936587312028970477240482908649008584376223905818900704466929040175231147417773585277211678815365505426642969743506094698446555276658256826750756579916257216211761260638013482093811035156250000 -1943837395796906188649304822460007751387105629267712368149126408404638086217802873846754136361336688243690214268356894782587623600261498194120120306183630156207115480850141643858125051631299315344694806616959160289163081778829263301652540027806909587468532461864101086388516080239046779976705434989899240887938579619762307828411005946785213695502521788731874565674846722275759946306571678467826763947057929875238486569792179917062817511561980930074671531210658594281228369352707434223777166913170244662128991406612140211250640213460614821400574487129315215078946689107551065098764502301447830306580696543535292582517272901372094823766411664966797838683537806725786738480610511453971977242598031549030335342900291804688831184308392295021637153719554762540846911867934698533663570172233521344041768813154731999323616534868099701791382602142648931017219794469285380062380185279324560456747722096714457648455744343799181594999192492104629899283117893582222965728004113442890221480870205263130591663234614814868684346191282599379888454708487658321139519837447892222446359154727485356944250008933280755363189355386377421552879241062328219413757324218750000000 -77005568387831758820210055273197586645151833905799521326615388399872661477140098354862664446531694989574701623383577002264874050739932653481830270825784038957296957407870918183053819022213633811586164523770251965040764468579675955585911400336740605697070357231307292192606710387532044800476236313146957982243710865922765426054047807872915897297511403550081658931734655252795908844953342829506556594989715475858582820018304191801855603179523147911602324257685583815828427151010911627518782189638405355338072473332106521483916324423686188264779822621546715177839134122583330362949485125734436111034422646922637472754968033228716216558476902303313413195048261078011303047451914162862824551233452649972235605226657515870462695455356402510705237437876706282629387191580068582443690117546518924348757211000200902355436415970293183370110805138712369364390831104843786052752568065382785423745248505430503838521715178565752797463915229917062016003839363942418004347668443064653536829619013861772061939476366921203185675580616382892886865573829117600139226493435394153334804511622092586812979246742038866580411769508646147031072359823156148195266723632812500000 -1613471915031065530810701002668069764846381465524677026454549471730059000107099147426708298759818305596487086574863821601688192440084995683096620414205236578344133761073238125666173731725681153659467832995891077015002439049283902371371268602049077544081476971032606004137785837274806294690395103740975105416079271153820281098389816648151700374181949368202200088807032055111172681042964503534881747204254714606182673700778201245938989401901075465007900532338486248584976616364197205810085374453933701064787560068833194203542536671574429354862881022360737735625655996806487902399759009501623364582370397277650543223610108427281878024806099969280738588580587361679740676041198653509712834109443336452220234138192786404823750661445657327435426887186992626024760540416111333290862455932425246910462744056484169833123490609759995107921409892509859156970389776147154693194304080595584536916916295316347077381264576995176608140811111293645051596927734900937070865359583319830351143397545991064732503911800140108748866120536968130767184275596886921589422476732359970995011353189436394235981874643705218254404062071249992271759765571914613246917724609375000000 1788460664338492217748084420161026711943151515020033992570855217920508827325442079608704206961561201640443590974890886154773693519336683077415393019599097473660950949830586831569499849887260406210136755576067203473528976163043070068595828783493117111397036864853522575792934887168884978221448119094810546055663458629654085183244291139708946952866334581294208769593796482179392356709853357432309122604501098646293228618910269511078273257550706793662710937767544712318983276189383116887535504804173869109176832611294351629866204757177851109328249057180771922371694639959674098588093298913092632443723592040348671500665094813593465110039751956045242149977897690012864819412026167105480960078652186629434603906114167414799887934610656699361432131263129058882813654958716423234481360324851359891891555773178771307932340263144557943914776693033786011674424189556708746960698432225165871076792692914266706391173939336340504095385908495742258948377064470852730418711787246604381161812832444174084454739837148125238578062096849378662900676866666446828725302690167686503825050404533077846522070464641875827289116754337250370099354768171906471252441406250000 1619624828528839879093546838014670709041600665682242988329189092112472171858065625975759397069708940547220097018651734941123658350958736603195782572294094600916714107946980437037317126454351132224141242506443485835312344471957267114855070748720777499630679728095846482943465761212763338243476441333107946485442694791779562940958537280760879105344346146717240998344716037708629620283422598580416765108957913794563906977854250365537633654003247309230087785118099550471985444079117274710556291805917487256421836164490364377598456747245807212390923610044139024268822479274949173732456623690095540059160564366058461914195219104072580578127191966990369702132041776986092961671664366711964382902291160984073723281000933072400510985762979238723373432671859860729407650526817649656366292169356492463753245617156900168805087196424625994790398420654335812210315120173635300188523589709958773757558847079036197229351269940048464538997479078170952787309754951061300482716700318082349253669405290442263877902421587331923593386092771835824861755724306332271205292446209878021716470740322813254126612672453565150605669931138663741876371204853057861328125000000000 69866114733429139605699596104523972461740068297574346087859122514506535180536465785827917452674426761717646022822447927313280816962253985346135795038983625031288793197767268239664641399444224343820754015213450675333687067508971040763357295890093535169944484646587108693760304431361049149004929907352670313032114460054895538482163128538974211609423736234368047903500390900849980884873880029642134068512824571060267680418051244694265147034461226857398225532141500821021632386079323060147770477604800526100864760061344719312256751336887236440518632761203807051425186944705310691771221796463893875851985307410737723261068312287531218773996534991551022811544027105294453439615633354091567533843513826151052110450065633945183613101965749205482465444497360666195898894920467559379227243455194416945477684238323808311202644294673228148686035044859962642396188431773795447917929371638900777566124516644644228479185689426019070268925746057329119630216462573970094720763192577737530512676323079960442975364754910201555245698511454200925760302098779051843435953404980653714911179172274224984269256088465177394197791471697200904600322246551513671875000000000 1556702279860041135879469368884494469084308611205767113428883577752209390526397852276355452127946109485545000676687814368673011542809837391285130813308758935616837228826334920176047335640026859685764296241768606810943571842193966541834472683180628458777739684106295830558914997228425484360275919915169717384775865843624349719607485236355637407528552283445627143021675995852609240445167595317350130763637089927215428259390966088403406354373429731927301157957998938700722882135213488194791082582573794719939051962552247530497802950915538973042743646507349220848592168589883263911567916308903184433861664475278713547806489377180376466030401550819840314064527075872559868962159398500055071918739983756770692151680873413372334524677640860788525725053517556581139994883671816640097213053410519012294703487001202670857843402367132065186215842230734726716674199856622137817586316558020259535729065251644976821940133513435927020019467180477904566748479576589366326948975831124323162577889309365593460563149116239659902170656922763346525335457718388335248373439290749751284397094149986067980225202359869339507891794482929981313645839691162109375000000000 3618214710140402746596057773116489893748568382495896131688065819284484718731488538863032353991943787999077343650058317233028206160683994997065553261763372193848553148823796164536695061635488555809054698257660127027402286698423499739116696918886525665973288677666200457535837001802015170802488165012596494633625728659239419631387366918226083843361347701816200412589615414470810377499664242536866110888975988298097150730296034717609929995787989555051226015197289726683247699178853472402355529709584274685172377177212661617254029828054430912751293013612162325457534175796420624893345308336204995291684605809308817071254803192642753106986654802372202494410505153424146283315283072567040780874279898635147866693951263068641648703072172342023145338248584425130404952435839878336424293841828935471895949755368488804166767174848172449501132087255153957149966118660742021719275749541383122825734842737758148621504759449864515600381682606761669035276407822566908942997536742525565680510504269793864857372475522133351361196795461987169859092029992713950499936399547501129096376745232582083242881498792660509636331944705034402431920170783996582031250000 -1257249675691231852744196543714180254443598462311573951134832830518460088037224122014171239670393998582369826441334012016937117974944092294338404728858384396714181183963185020866809280530682779130324985153596211820547448308373521607438431008332219027149815647639135779708954765242843907720931897900886545146719744813302675584112826687052048189683134951466507933979799018897708651016744606066288460783377705041020899701560925802905821878814303101260340527307109178634372472877233715264250193434077603171599042796708268889506130954532344529680456360093858650962809352772214538232660721471179732551658038787188460042756935242988255679065055234247958436632646601165250569297549324582676023548372759517414062050929601124139873762128442142151361936816408839897562800210682535335472504715335401008598211276925547829356163007908863716793444670888941622413990620215008065136535696889302472746697132855677786252149735153938336356251188343047882033844315590591042004429893660229491508238904496029972829261136400376081299293954593592414932416610098857572036012230311092319484721782932965138890512395887922962589566822089182096533477306365966796875000000 -57580101824153032211737258233780482122862904427147415616370535924077231115051730870202633509047292612074889998865020296438779188736549503626771992608057606487001319393874540594999698980242595613522360045544086418785103421966680405644053850751379688589330764348057510543915190349780123691465894838620988181410768745583029442277463756925586860427062082756759634885993984993046445292877784587442677082887721014673738453020411905225726173393053347991908361881194169349482037690941140362690411430719634524531624318459269117701312588782781755275715949218063197258423678903036271343808982141919086882855539308959875386446475444902756769305261236077495336359965172304582043560756544025865680670032312729398335218392854166200628969036347546735064386381206989771169536883152831052374160878112122801757412411981722773938038976345724366662753159774456621960583554459756419253140870925322067635005769511004413901475677186972430422772823049614442079422452336445027076376522598910215510561110575581168694749290849060487879430673966657599744889938729302999566076351077158287919571685190190566868746546823484237093149218367216235492378473281860351562500000 -1369021790257392731025190526096167345582576630322411404467067859014902122811136008957617598397991599448525528240916139313774603267702462522495057374463861457579110210237966470168579026835687415734145958121443959119704270584156131039147944678370439957781082427134872353675345395820481281590735791933386182697039064568429959358287656031331611217529767469073220170005286937313412065778201214221428274771026700052121969319500878468058869639576219057534974532813023689803363617041573975584329367319039904362925328670762900049816019212894868350877574574254603047290510892471991805755410747360361153969621458372269146398019362378801335606306442909224736730643129889670425939736563629603646134393760336182177845307770501241619379917846887055495902698343384367137531012640836944102509566480976153231452395274374986867394502610432114738487452624715989182701844474120454805657723939560766991454284257580004503657617469970262087862536374955804175611462251729392324890921657202920987985127633271633868872526852067845893103613502170723441013237734208866601379930221169996780907271696058247540913977916129593004335163186624413356184959411621093750000000 -8796893965735464890176774813166574899259894880051279514903980925769450285464760965981150750704193409054148377264610602835263209458564170314303846538707535037249950077133220415468109859951909660940454390818015800376115669314146615107743722745538655819949490039425370162307922811494142312583462025696183939023409711901112272299381598740178593758053579895666360288508925192298442651664937525416791673124376601204984390908000254495004396520291447824522305135510914708616945891931468820739813236787668364876903930325262781467502294331610850994358806776929653151925438210717724942978109105653410202167056420247453687847479976734091750988711362914870077109479736146217470072251339144750344041973695607443899277951402397828409950873680765305778189905801422435713021082783853994926412445121173947831631548021121378402331347304918939127158088411829467388542033870382251004303689794991380523671211616430536057688704254393052834171311175097176330667899072044175841832315395892613877778521472011960621392149538004096280125877469782506152848662521000696679010345441837849044454923630399212378801590187351114313862865401461021974682807922363281250000 781305673064753264471524848429948198506733076943114790668967979119690664301028926889158676224614062122686543131315303808201351477880250513810450149854811683562111808111186204669888910935743022478850188154410450780985449162270077666362661221017273096007945549063545891384557309990405864573990084188503401216928319445360712642040480659996828353403305804627822643280330267001921663777579914536180948657356418873088315454519067051173191026364921314500601781992177780175608999515816061516141949379038285568612905069137865150801221430839898845203342214066370241983816883720750687382517706500260809581874609569804587528079680068118858929714629361526556009869030453719973638810752317887831896436212270399745808404563299773692198725089123505417010399860265010928930530437550615588992263229404494439260230879408286405557120366600859854320254107396166592585368401017308179624509063267111291192343719454843174819319327462598318682483863308602748731204199684279131406403652534510696336647647261575393450212622492764320974093391322600385540904550427372614862962554118964958242943524994878888885390202413694371585961562232114374637603759765625000000 39900963483601918703706635470059474566857102974271850945385335122752225859784203877185675421453669300168200265927711310026037564000786520824244135931191334974861759116792124118051598973101994434960107124590017389785498735875872731523161320140656962215138015326519985244271663618035072612230038320958519532576237373746952248217505703209883633874536123048788020919814285610839731674667688467947280573275501633662788475934764527009823180813827924892791235401434728598051897422906123449396183825048446735203749850179080971789574213010048105076802700295343869762981940490293369268779797187945009508913150043561818672060256052060958473436984445519623471825256437247467744053584872949591624795819801057795866968682761490604943812100543192307314646530809689471768447113414212396619530150737566023371959327261994023847065850901967779560634350821295701112889330040380599609465572672976797004745487249906478902323427496946359291693316127041860784205828301451819248585699502656994885175541803993532674098624395806722705262041613019667409218053700058502524750250453987169320568689913393173734630203081108490437145519535988569259643554687500000000 1019958358122463782412640985831127862366455379273018671540118365194520833455533669891165396221716080275660325039257066536893561554447555608671496151738237918445390149438585505187893192721235145467521422614392727559401902646991270122650372519772208411499278872885578366573802627413039473068377168167492166148986143006990159908008260873178042751873261885118389508714682123045195116355524724707958501635876849437114938913836324135661315744914461013608346894463033172935831216264105566487973426938705188740316664934615546537568543789181958003697112350770422976853074100500201797410995268376793864133129206083433200306062991724797103455243447022293757640633210233075425072679803745822003158815615972702532095182966927294072110342714057995700770583279923619805392842128394086226195229154119605558897413289095479474495968073284001593189859615118234782385891043107968457899452321707873174016057497395920097097993244739306465079568140434790240423652928406141784618536437717741126280275868422989922711171032803290696893826056743679073804726726284306853424582168100036878235132543331503009769920496674355803179423674009740352630615234375000000 10205664377905853907455124120981369447860293091314101913320436642450571463646021583306623365542593770019792619257570045275338023679731069187160070124663379801419758630684323599214899407662800172820332677054407494060653212943588287336494393791469952654475077096354471561662092466596009863538540593479286543728195560383111490912154072047103560881392003479949264008720250680191429924395571636959108396573500652244610931569340761854311964262871152491455037108981659367912131517818294106531484923923657747735149281010440053924984503727129341545352843215509607435326270369873343511780502814220448648257114723354273616671049282326917803051960981721240360884267592636229805525774860599734899878356750465310267188147280750605352586189971883202663167970080604983117745608632742518281975404561546422202187530042794985171041605648020142663814304145769281717915325982537474918428071984849573699046835933694321170718944330351879853101397187590456177088065900148971336567106911275906230794662909602617425934966296423488581692904260380515409196752818873652650724938691955163516670156187626229463794947163735038486720441142097115516662597656250000 -377181648381379628074119141806080010873562741013701213627597905580990885742288152572186236802688151034707671699665691925889941551670542858370490710764163773211282915200894717794980372177383232229140666481098291960799836010031336458776887075565128967224841428162768603186494474093930002480628782487061003713211434377110344898972454107609042751903623617855016530490979129449768035214634573828143874278427634697091140028346855332820342953887617981135025640718319166788187717799940658856931426347010881112879316362124146693123223174979272634926027286842374964504605708118790070702938386994703995616608449602809368010063680848378920373173428113847038322148885439905960982823855271494877472286759413874996221854917568915275925389629046915364535006436450946802584919532387195124928159753767520177331448350049972171137129630539797978986648432717475861361443143626737138218925149224786158021082372112858889466627311300965337655988063475295586036373828179857845792397161302120443479964145664022158135790785006273751636185184760434918480547891548192006590487131048728790828911256206151385609801063303336832177592441439628601074218750000000 -22886660698793351817489980154081538135826650661897348525526472396132223897727544801814563707133091310936132987783620212111076000895015771380866050031858132855638992361606716112198059955337479666147019202837781448731239750481205188358745865569961437481026351647357051720633195452432608156196623592319978463077455264741847315300774907685220476621110435897287256445566546180118424867326051026380480052984265299079060638116002199000064182397904403071100737558727747845277487916423904993572502027117923108091072806361218095378367155349572997980392143894043779029068332839935034775492488906089872430613585555731386265264967490216691840552085608568176635347775967594487418479317459828605775385356152739085610520128699286901061109738385295565291422337695292885411507448083616296614198410966147779872038152109025521634564726212639968672872782486971556073467397534414079727391258791029540655419781792606269810570047865607866337911692864058032959113301638703739399943143707754513573178769013067445965069985887467665552637429595420037113172421454922702735697876070509423088918240893053166471523413028066329388821031898260116577148437500000 -626626793304264649501208740573570200685973615904409455568861211551279417050379906662029808131067979179687771371925016249802399194174699494296535935507484852652645680879233506170399795781200018392375031960496216857330483106800606780268473256855750530923122789218350887965683775536639593983131740007643369693498044966035385709971961941587877640313612463682215296003685907988747991181381403396611999183669578591023977774696849675495213863364898985853139993302778043293222900940395142786910647331354890516843596405422442127670346584942403236592707892175904610721921049831109637223996524436274520449227410960831061419957951661989943628611508068000190564021859289860846360800053320066577895804921815971667331712521199855323841363542429694124568273586052075088367200296053859779829899811023100450178605155786245365673519966481438639833713981739387509469812711419807423375318685788959366072885150184952175796449216285757199585607257907766966204477002504806846003459078479702094732664569926919144481552461545786345413862021590149030707588537515349691899970923818396698089569087406926054840961004543942181044258177280426025390625000000 -7807541180715574386460300072210167396743042739227984603743405570901032016087014828467473137015079447550075703626377639966173115187767317024951315194082568265243969086724025692855497975331344079554496570595088540807000055804598890498281783927479279696002284915239213364562997849761949296204501552072389214925996557434254872152146222234150617984952635641980224440956172794034031584033260963654169901680852186807494194076253022309901672077972012915735706188554683322042227712686781291458113627015618685719908614707369338843140887654816118212689933915832303574245443876149979333743925406189472903441905620217979175379610397212843577935613678646871522201698043153348075365066487167687013261348586466063727422646232097890321758582856878989693702431749305120465389779878171581306185534437211946772811716550043994814871761245367940696562388266757663843715768212881429743754514026871316477710241358123045720678286809987024864338307977405289401926962137788946180416693924308264199243857022589128311527691296759543175354052824141420040135240904709272939880271686755459697321605741616399329677045137998447899008169770240783691406250000 150182174774911160550942830040300906420089575566728514193187399515585682928644067037103661356038018829899221212337883268795173060080238523633513983541513468890769609872639694217005845250426262313020006620371081068471779755186964034149015513690530923695239883152210875304518601741818415760740255236739762581428664871112012086680857236660814656091843635379084200420076831320471015740974081674748135434973284246041981807537232111183161980337849784749911187378007456094636033544664557314395103838069545606722411181245540313005551195327819581093284595565466730767196687857635921227999432130460445192549813742599709716270000157032027027430840475679744170974165759538681044394919855379650848921674963480691403505998068650732306421368289475902037831546864852877375548267226946023494257838372470583947773278857907824344322212150265239938953376446583907982198021180477258790119308001526807539762257750990757657939008221274769043499948610157205946492090648018947776569949540263384901151656614831280708679077017080684962689896955768876104778196714707897365474133926648143508909385751733112090988697673310525715351104736328125000000000 11423352198310545369339559505091298061223464640256573916837252925459873854715762660551288190080071111452977023810376036815628897055717771985436124070378655754546048878354624183726407515310530034993199329876243685442034467301910925269434505268004991965512465107019221435458426572480934598437048659063203727509588021973594934001159177473987975806694886018408604706728806189284562213306365198439610219118473015447862577272402016946456183480570635904436388843406165825539847509563464729778633618567974490764448837704727459189740609049202327914884791355673163938843218808009645673020722064049959531040771683383044233343512354963333334045097475469640839062747798539523302234795221222028307284375450612204010246366944640667676884709324225959541860735579252576136534881648947392602856571626604151407784395317532701305904097151584133092568353554876714977077736446077949268708045297606767277250016926732474378127438079096641838005919442756720554884933068762659577516992876953291117427429696685839092162825692718899494813725907571781079068409949868281755509360942169461431502393679651707891764544910984113812446594238281250000000000 333955770054898558145630147922491467759896416468048484657183095758711191887158670603031162810917939619179875728222251663995436338717181204699403109214658300882873653302569919050561865694925236762105964230928174075668935411804431497873088203047211003662647796862346254315598656915600304483735555113992669591592165483238024898642981452465905894359224120064959543966006678128301457750437943414774692858379115732247837731260746070144932844366738711056500374008934326637200387357087756909929854044731127333061230241604617353133672686382766770474782441173995896164495506391803270793130079137430350945036873959482798095400454498872733600186023748783714149238350867247474985537301377021001677130943746915991982686636532113982320345643672782365511790560445300456360401829529713608904620281487401418380851661353653400950072754449750804492414813827182884686227163596921414703079933753154509409948367068731225650106784651910549716630215958187825046120280570252232741152863303219366897049331062689320755633118362764606802933507251115765657184910087714727757056878464635738356825638874225692376285223872400820255279541015625000000000 4792356039836003975024376424755643973557859582753430739382549632973109825254852929367221887733764703998401501142934179733184288205925890282569794644888605135291116950371224530206300517629697372781340295102929489359339304460223688183975652581323670912280859712125741909124452077315125822262425346596512608048450961187819397712833427559711214768961973288711892676004359881037826030514597639748154957887474765235506707461540224910136593937536440080981063406007564856702137726080247085557387158476817905649390713575473389044032822788608316411590530020453744180783861009215793853189530427173371857456277304830521235287498830757083709889127471645436679234788205360236081986175369530841101457979311134185046295514159036788312518168345658579206011242625675317292659000536937878136282121621594223975319550726238646813368478411934199644535467518938869218270245939692589923375136528001785744667843789102923550353929099895039169261107829705465560573373823906132590694582401186709797039659079920669278561890683801368275825322466771215160295190046164157401639186275989098023719791727802609464237360015204103547148406505584716796875 -49608897836274396367531251213829947274887603680025418836303719425047258808392459802819134117982865330597251694644389738709028068920937689817996934060022922422805953313363553623723246136811988130959418266363263081505112286602279595921181736557253621515505470206129939982077585015806857580357834533757129109174093902067610909789606586623734863979082382245830100597626324734374893701437525848709032337403934208627084013472900022680020701581236165567681979310159047500180091775140609572971332352044838699638539364115438947156481494431379546779457073051529017071485440598506102877394555903502005853580545699108405019232555574182425997381867593818355165455489282934610038333637068530424999715510717799119923153502790272651142882171957467418170733049335192896237963429337360047992502932691028094943618133755340289112422605834540430241008356797131144994602770245983006015561146709679991540750436700881786281587238966061900426631796116956346749103449208404578866588234033339667906899856777228434473468051027169417638344008384109570947715262964938015433136272342807315552908093315032794778929314816195983439683914184570312500 -5234739086963375707145977641315009856557649639685386316822910493909963189616094248391895112762774571933172819588547433998784904901018623462267883623728116352971971554746386514296915383979898451106804363094771123342619329636754697099443642164660438039068722611996918578359745776948256710898535530997367434900052953231970742266756355095906949530951467729126225803014146007447443454240731276973499973977343019337241451155664859458806881293158717751216793491707203677915368360309515721438674361596754249011410266431933971648557919943771226830050640070078052289437297403859275940048204548689244517043625502344159617740090515219590703830774890604150441967526775955392863578407605198798602454430722553015230251807942117160778952322525684724842137944121141184687589923107257519073957394061030224979918594411854754667489101378912722452784399817234327482754622199205898512434898617385590869990081409812587213238143690460882751024533090161225806246856944680190900364821897869906802758707643519193801610794057932258820645216913592816433038740279460354522725963699490610670453032653290023623604554359189933165907859802246093750 -167076090304460444144608887908555684146306573450228208642458603727307926471736494925097639309685918320496344460160890081507623785770695261182574743711948580725459892539332523815183632492364153542769961461243553576890053386219941212463037570414888226526696820236918074804898630411861300399760270816202545948522431888120782979671120361994313842631497154639357852008449093162148372249560271195983304430298389065633677201296438689079946167429566129906480584755876074537265245579710606783462468113901285939180529947623931040655360026899209308583028960328737012725319973424635291627380966798907649783458974280933438227747947603051574960908779641631767865838465207583647288741518366861842364913182626470907869111882287784913558790392750732146771296531681304916205845442885765994221370305990621068234663944720256838604542549762159654324689796974505356267902152272775435419123145876848050683585052459142773451237674660153254821416436549436191850983424140801979440263230381860174917102331615329294848499691074366020268437295976635652977716652081760269674577356281037563407492938481746502787927965982817113399505615234375000 -2859662101431426935498364948245885934375921366605433690310549472754935251295520210842130753010392685660568736251847839368113134624906104805592213188603791839802120736285759621941013681052614672277572668379608336593182904329316485595284910901943693494507181798360503217692462095425852000780980427521561679490550371967626847507846257258081799423045804239960855622974084278646990566158230168635407843796287624937212423122540573328785386734242424849577356573988397017061621844904894580691108156995650366698876214541315623639883844866899545397458051068552692613289063073705618623999295760285962366025248485888156032792647907965415973262120248450936440613660692985945916525715887037597705019711123462585374797761405358989991016719592463649047277894404913696629296845215267702091375033270125967273095310705808308538737022311235494592286205531181993965600920884136054598308953472665765500764533281074801653787618530587737674567899111276503301224021301710450263617662017553913834773370411930369141086638467665505060088397490338178855018023576437917480911426608384915535935501674884295919554233478265814483165740966796875 2369591178429377322967092130524810146633867243725567311080971750377364725679115404029908969439738676120711628560553359061582667216113544074965501265507502831915798393979367984497008532370393918112553466474757924730992617107385204444311322906690389739014429543879173730991877914101158113278632243303314117699095642509665960574126893163083204386941363214835611570403445375543332916532312442108381107500479095398072895938574735877094064582667020393552217647125665664020164262742286270355669932303395703011622546627031322269369306143407363656190197186098362088312422852269672260034050948816394629575025120806628465316516686666066244817417819101838527876020809331479462361537110803932808897271292251332518096068090938936840843980806365165007351015664425408799604694449828531315921056960158736404579395162951256915779519830582103801578116280411101470114488033413032015333368625383162139454261649456634032007918330989072006212197823280008711334280266640007942448951183820907385123188373491681790915562429367570785130125398267920679654550772950704389795139052731905489757990163068868127993482630699872970581054687500 1980464796285059514627369157536451074849135258661498339879447140385716598280530085419410796262303717331292707905063387198911274682885231582504617042897666635851965172032817960577171895407142610282260478767383430491982773583593942858471215349575650676033494681741561794023516189632595417595449683911240890253019564681040999578608398098230533451068648405279115228176401680687474623998071890435543559914813611060859143043332154931855896551648671848788820836738484229374493713096444447861324761125043213934490229991884660128246925845303475829487209906230485967408264135274811915730295160364635775428302269117808895478011901273620834309995487226327809088021016371393241950234653133266679334650869482031112574844413944159354673473210373557839594066383760904669390938318885183585890565614278511641004097075481581873722018868100817965827652885721008331147853061147860862295915511192416382677008192957346689603933822358751037480152021431431210908688728143584943260343923973987758196198297414522263990072398833537950932712716418384120156726673524037893726096609102132572836907353774904549936763942241668701171875000000 73918879609005245961066585410134693569585932642545916863037818482434041128007601652132940098395352030264189374940919969384490208333483928436361467073778359377812521120331810112015819427271724608812496671108335735880191349372337654667044624142352010528441487434542069861854111227054024011396848788486005188507480895309718828484409294420204581866032255276704764456793606933345279956849412419649486184403906797230643053569420203356075075267471458148498841328788809646539702228303111200447600158042444227820202489741173215010693233820723557547742474724277110599545685673288556865932826539685141603330620677319562191650210787396303581192207361439298183579355839743803247072215672407674278320464322302982156570331932750001556813382031063614964276043638149053247979078072467272126643365378571836511785993369996926159806126815254612187188586016569321267689714793777073966969099263337757771909340716066242022216748272885083168348358166496498595454080688335069632989293860494939881046180827500425891090726288107492456591667541983293515732976331033991380996410845974989311819164372607815494120586663484573364257812500 1531311038586870122478211021342267830107884222306771907774115710163955925202135777377030812516408503226961217777575161962092364433956612981354006416471367473610401541160845792375486195640723497610754488573004227069624962186574572444108610386439593481910436001944183758114179057232106018728945857733437127081665148875792950148929604305090639939691578768320325356834399064445953361798828473757340242067804438769998080207732050119105944933722794102426894298885952904425589924504400965440050436444989443349623360569092046529699653569685752365953431032799374463500411521772084622373185109771887313879765444332488451361154082022932285268365501567569019241618129385321232124648981629269915447510322758945296327390041803583667588815102161070168700648685285866783944717884260107770491250592323320779906469142424088794496308692076305335673542829838218731175700076852874205929092599120497956382980714729497814620408827065177305536045957363014420808266759738460832960844100595280375392459101956553181614430392838619789111643227552611815609538597181280163149867358947955504346570554385920104323304258286952972412109375 10730182805524449942419159559256437165030211980437903250327399546192982079672204763334436166730292097854075842257970518087938453749093470401320164185341331225665436731158295605806089971766227697266709422501181344278159343760891359905339598733928400811245364621761651675010954677429841332649515212590611492557005076150310408356731297091258639421280511197686657982811366049904220419766336663040009155195924968428838584046456451394445087437434231533186084621993202136283221588040272476741616507075212040875711057533085459379016232474929967677740543785032899059321987459732327511080134926455827923068753050786527063313194602246711091874830747136229550255702933390223789443928926528914623477195347369106347713311938622317744585842883957251333601431231128787567781085198766562805271453831613301298790908071639683332532685441542494624881767226307887793144928139541994306192985659713077883827340728417116672174261824153848989366113028373441066025591902581788403733937835768748360530862046262182514354223652765623526376403096415933333670382349932410271948082028991362964209788088965069619007408618927001953125000 -576871201663464737328647483448584304741930446667014780891542953957709254512963110517244053111352404232527738362706683988173997300232422095650328633783176992199981699797228550196948749237669110147458795386805403818464261283264176390501858632060758510642985310170671213729955435599166351306984807317339385258064333705391595560135447514284225772762323920054506197530630651684827861182797103588096147301470632880687437381690525336808311625407099270118418767020942118511618231325078335703265762287918112781660256699820301598378370284265028253725968019520318339077727252875786935945796234705566249507772672425247904790015746168494368299583545559671471492530794912051737292464920913450033577072798916751760002895977830732407889234179541843554524613809345850762380073105712850895145204907607660060176043379626325837760990226631088230481193741895236243730433426638895577043366386793863543230296976479314665869517569803631002133291923455892519011311255668488863678113517620938012765794948004722470928855674990553741965664882211878842689044506994930966749986885628572819487147604888832574943080544471740722656250 -29405588839982069813545356156830810631829715778932112898778513298185569196375356046916766556872039637807499286184364552898714658521276589760293332144424314682640639820957546409961941437098683199262862140407079977657125004994947529045944398709028103737495486188165977398844769609615053032700907951989884411486756049566323576893432793285593721211554018936138968633204331341845134679206086661977948553598267842492015499772128088964776304020092776607676732334561750502382946799516127162990451424115184986025211285739627620560067790284293971023904559287287531374693539014996913540574046128082051402867386856435634625712628953686595715922240057164155729526892678127942359673082664335232743120492078070632863405360372395946401729165354679452589342587247312166890196157419459796366442063334697436702390271716685504858264517990490503874900906331338106854747749416573886632757324346238417927754694243536295392125405506307365114712437907264510923999973189107000296814097285263175168927890924362224384544226573566595097336584935658174560623173941921255588880746886218300190085628287306462880223989486694335937500 -789074134146944609834137327364850207142913328666695184172511272639263759052914943097855575672736287535525742750899522202340146484918267899412744973611973359787007249366997725287318651306840484257037315638875426937067959923474634649750819195948666156458496667654471356475191419906867897190039452249236503040409094349010567567539523295071262624437126091120146164121350151683740335967593998448432917219557732703868235733217491300208266143748907579487736482025666808818675200514490107063063023536616431342071821511612396098265190720241455779105832094932314957195524077804258362203945412412546885002084599845302137145536459696693132812395443142818935131529964575348947567224614486678381185308028915220104596707926859662876332141364047644994989630906516898788521045064953175703262289050301762786910867193361133176467349719774894798478968760895329000510195766511113043639048183353497996862735583661268863857365631982665782122557115819948863540800335361994554808647152147300676735416568557974773338798296604295155707707135881539852352748775096287950533052555721221475726334659839267260394990444183349609375 -12849711048328348320262589419706113392250225066309483837030188552244953407502029418917186028435524987269852096908842363041799327172623088254485277382527106568930779013128730320311957899268795467871692300496649925345668354648392251125698100551683587411778992556792203773487185245371518899705106757811462321947106799506390864972257724820205316832014958526055087005837231189655128557250062702766381273475187375290191165504820219017290784264999972977845437477970177208546542038905057569327992275681129977030013539717408625662210656490850163436399156707069061048280742241691723320072621111279054850092822560140924614566218679025362840334513181379128850807291088366584944252621360176495420211516154619397369200565670124582378963807036029254989194492417899481025383780208545149311130771243305852634070227649488873505511052926224839610689287512701133198005274095295040943199922436334016697431115012441788089435003589718781487685712942341293619839326176417194368989143987582186331537317816622535375689733443610493644872776445389424160588001949392422573040565235424903534067198052071034908294677734375000000 -31228244777160765427820043433342868386129628562408484645777442162571507333392595234116966767441446870946903116998601820731525413559492643960439361739194104524999331272467831643980574474819962796755431987933315020452025988856197568397378863412240070155561218574845776203846290847839907415145099780242152013504304148525141968181735030704631342442105531161946267104517455004317077476894302338407621728951846239607743954959038903230217352607039547618173981938180803651774888423421323676439909755693174950203736697726381275947855556198535133845282604824121330717762963520773367435579259168350536513775786418925067408318220561582826623231253543840808365106712804552643086938825596433079966340266602915149927690305253329490931986468417457056391207813177478489005138012387194651929750939523773651605488874415968095118899110938452470100439523218661708609668062204422307070146161356225490629311232111964137688428126517523846604785121301794714355847616588683253605444094479881200361353092200022693574686636321783500499188435084541884966938862681454484977944859730447646484208235051482915878295898437500000 6166261183952602525384799247022807451860269609487961115197580869652525236280940457590583741134924499482026429244605521634838574233615821779833902272005907700668150015313009530678644749251722251825490497522747135577132181028379097129152927672318685287851156523536971496545663236186949981827872784085721609374104457169203311974387974093852834305940552249344094291001108544895962541521186063978649351443821871520751297863514266105673652387529343503629662403177226660320175965956887873648475215973397947161170442977242841561818753548549400961932250301558728737640326770291006925495921031785115311142328936911431505564031286234267705847755891407509923333513703090593898390284762619194183199798071245282934108778227722127781279207057140861461355354002750567119083612422521491605619710735927023788766069122952501213358860183526857794129348037039500464032223824775708465628785929242636479692405885766634007953450528768740580111086910572465953943697550889247536738600641899399066122443553702835595648533254479990665202349963572088119992216165480446564569304290781559529932565055787563323974609375000000 251973260746010250489857765046314796976989367776664680190483807817104876836459767221705603028294700511361214412694681423431859373684102133318662797416609853939725280953202390168102780606644561137187772889295287339927454035372801096456785531644722300935977771718050392303922793173323896142174189041839773013615033090911224435431817197676889976819869692689258251285387742214395182898774980626647242601956699908452660983596854235171523181448991424235018411191177874020421594397629624390653390497425227509362353557455425672453767507428878320733281647065590473689304365628553905318496456665430546006480815720323900810431845950308682916980046859492373762607029958615047807621539625458945816655379022929466951096826897240253269894885011733240592529957519298918535502364359037250909299262681848760249316881609396216958619845523736447208516631806816270728602636320843126169586283095430805554152666948212328827365144572007857441426700281889246476953057992779586197381268670861734736912849310361558546558212723680455910336890701509865491613032755080356983181191256326858507463839487172663211822509765625 6168615951049687832328040142115462481073116879939920400056060063269012959284524530818453020428228284236127012432660535090552725481086423831737585406434681700201216202005079196045090733518824387978865961768035093923931721233819772609455435288325529625640193417007756477738574402067822780751747751183734706320366313725517617250062550769785098302787204435069320347069399021578626433516789817775314272034679937225395734902707997929902874678336073470895277221504210115234769425960753067732782098113230952690491953982160873885215269031395416296374356025915960007339341976883290516100246840423370899044345422866524789387055088380939023850910694228652906301753371995858291307426196812072215338421941401356872458465918372874405819719308278011360829207062267944563728387819917713828248928348804053576372639786633535266805303865989392794706116547759311092852950534193796483122173411818555923804201567953761470007558116058260474308718795252303718759780897586288741659945055822185052985919066129888757045430330293018737155037789160906389495107835838856679517520215094705804403929505497217178344726562500 98314924701566014550822153076102481471902592227652376892023317594298370130275009037035866388682386066817757409832412697620825941451081072857010439886238432863968298527238425568241504126220336632296499115462021955154482249877968283148061896590482752931460682324312342034085263876909183494240138370114880791286282899031318522831137303176662375000983829788905837860874729829532803201708346745510431968442032351432440076664324115616068491899855099757294790407268355483728467033470934171104324742560009145825209635616139172436890954668279833507566333317085262189202543245242109749376989694901351152913763556751660283466158250991771098072118014813538561328381901322577057844552626756681010277029170405551887573072264080139223496100750870684820119043150319564501492658879968973580851500640798317285933039976812612068931621385603946072321398210152866360593195042496500664031833848123951655333853768027440838556508283650219892545668422522463095158256921639011853668244788902808126783737960598737261193767616317222016123620199065312416667008779962922190983828918398046425863867625594139099121093750 504003883221405750683091064935218578474777983006495376405295439823805801194090956238445458438431881946620660132109440606549266872791275242366932903617710284073776130717897787267289437305568470472779006942218682951997908943283048995084067163046291890191337548687756739721991335807159897128167061624643108215038512745917405915538521326794171195585386169973384749118750222530191624276011880034572261341111260809737297091564388771776785369371381699981182328903561814917055567591384593501531881090182431299034053961278985769752046805395524571013223825894475483933104861207288904895609845533638115122627868353935512992095513202357190672556879934895742897161973994044096986939920906707633434428746850054505738462458859142246976433916176490678203784900400145372722421888643166180246954605232178733395526542892899030580151351153905202863239818058995554476917145524743405406549225024376026347239640732256914485546140816778174070107656121427932065792700782126461864742379267194793279544236648383482080244443092027528196412756034509834599136583135569581078094802961686582420952618122100830078125000 -29667171372990789933451036135496072166483856954551188398767153464919538478808466558746622437164448263148190927023040898867464169248630197981160029240804044273838517658635098571434140544938495701396945050313094304217903273581751946706264585543369629527780030510032663836326595402723532284631846458542878149010223997291943835201776456049102398107160202722109493759978594617138314596536038822363672325641528882112173022388595501688467573684710805851601200540398636575310878049549655574263304148506282256733312512835943607150031364634023208676528429244466543009319711989617635385132445272744782255746962800243581855227434376624081079679019691150757282587952452219452039695510436335303347880293890156561474588007893145816880655846918107845621304735802741858384331905376960618444494086470106533351648918800274154649676139458263977374938094898216272536083178484548428931857091646696468516110578854138887270084636914908102760992319318110776854215892880585080372290829486953645398275555026753515884423820991450302088784704748820076035708946613913164860355797802782262806431390345096588134765625 -1298861504162945420161827602101184643339130016831646322179629029488679706715013976158044039968363964321347682300785807319497083811004827668967134131623167064848628183565040229399631920132097800042045334044914549999541829466674078547030528347672958252604185864731226370715862051153114624875017490396334141714426353555308272624015932899960302378354377086416994835004494891789312292881852518636378703130675969133830221980642715205287286894588498625578923898607796996938196380271411917066607259720778605978762265911029082283644992743677388212265473421286362158304490574789381156610812501891559344215643920050741377535761802911978906632974007093235051375107991352380972574371571820553925145763732339022712411220797084152469743905830726878324038061620682014101068536891889755100265762495128943785460569264801796809709685417320558499507324361493116257220025340858949631529196222003995326838562131091068682203966847820964997564399237422710679543013130353247432570788263211035122180898290125128236527867558949490281118521569433077027920611504645850408506957407439585949759930372238159179687500 -32236464347583968717315767278621806824679158137801898786981278112827451669980204030066026500723993230757000182182323248695284082087109916701788440936267776237749159340348707381695120949517746421961669051147749023623272206396483199470921391280105571399142393728395225516536031289420404392191352577690671175854788199744083699032405764085273309989665658148751647047097935310000564942346368448452968240322127515180960469805389794837845800439391218894258731197809543663422702740224553557802649169050701069337253229746289613219031181992210235231842539848898278636749126154541368203460536882044836058333208413302119071726125213047393207970198482557138386589562068853760828055925879003330482734928673658218854708062675714546358864000443153170348417330600589156031506971438884356802341499077577377352435356477405922214110950499139224973574544269629777876835322090556705214566287385307160153502071058849498644855535882842495317196140657200455086684811006240692227382266035906205967787176377723573607893949879639704753287227731715563013092045287558140564954101137118414044380187988281250000000 -545008897326866970054643959657330944091566673061915552009131574457838598456727195182784319892172602960699406852322638374492506255912355461850347517297023401019604214238542693504861255628861436251673327796566119628102698800299172910385556053687621151874862774937314502980857724140346623528679178862511623001810138348281114895952286810732070364492293753149796170824595281351207300582537428072191318323067997213782084780251844699700767005975042636452040777287817505247567091540848032670730452984296828415648311203176491942940978461670676226515062546572721313951528583168523146760585031890942460742668884737391096556875829657304359709361066823730617219613064464446470279109950279778323540896621501065453781255099459076367141905364328691075448990682907031815650172913454267510539641364772063664414350673609393710025535728141215382616156573980820173547339088389966366132146190334286517139509185353034977411805712234725444038056209049443092775834128151805136916947253592745513433557706308451465695316929670642555284019822783038049916102387251488209374272742024913895875215530395507812500 -4812845401284857325799768991552609559275103749235722489000338002105531882807912665568913764941185172171602428513261098066293445487813887691158308195599367970332350736358782190034806670461640697245874505832002960473151504390191217463394299332751513934161454886827296021897838117911826342774064905708595319480123846527375102389766027982696054710123804729397374153111428131634707829732796765594803103646500559962875247345561154961075858991544652165780587557643500213460871091587757382644810639249374476455719954838952939315168795137963914694062497031322184235666172215581856761050649632485536911113348846596521213083707272716016314332460381004326607513229053370422719692233898638213092149211819187889420339287093797343555508772945265101953333834962754203721318771209219498250685064194048864536352311650687557478840460548164948206954548762484905440515830905608702809462754422663643989893263755374222806158728908361978287954448988972918701697633396512602268281927063090359500193771479811434641954526595108040958600092195998196896206253850877647415540394604249740950763225555419921875 65345766976682523741471240479077808090672350084863566740953600287710648235878262425208697380834171805726112239333104336109201625419670967268319946401168259695143022292804535150575410072742687920122763841219655118288324378180030845286983195202634494760016582165509898329656441915922103512860480473830442729477435146844985167190178899097074886991718120266073306575610795505377605273199602447342027425906607330961974534581427455278369054417638922002086977151559267188461618179520623081716063098345236709212529620040888531069535358941919962221615435894823705614466681664162951979307066013527470061295091618836369549988085939833721461070514974619441116425482604834348358303396143578378502879785258122835436773529190906462405227992853029315862293102118158414284179790200333689396295682433406976922038909645664880777313427076964795559781708834212056069991356186898460476583474884689469962830600678316456916180301375546786168243756759721264053717125652601622438224698627177713644391480427300464026272073851771158157682399256187906602788410294346821416411330574192106723785400390625000 4150870620641190303272541262047277127945536865696893247804392882776699158395286230259228971254024987225599124106575487441844491245438019039616208720591887445042159158217136221350072420578520615103823280778272587749014425501465152858800888801417536311898170825137819855009513894395248060619017865437048294039279017919144680454189372624673995273743584206913842538572949213734686683914316244243350556647070087261562046043996251724796256437202514194238762875016358077625489584764184440495990524805232535366542814093811127165089241536698175566409170391288047721507907205702103190394246571857760295022416485961067520493470539368972252248423627436675991985831440832546552706214624286113775195154856094833600844828314750588035379580605940094134006266686298840189209368242881153206318279223028161535666606468532060452095350769545990671257360462304606188457257347036626444270935408320151489204512729605801161595267679487307105472285028378100067878671064914391633538813671728437480409970122179352116638795746677462595984252207151843055085591255651267239557000721106305718421936035156250 111328347743794968315079620799481506262389315954716169583614209381349260093691131655191089047484755361196537140218905796138283275148364160710012829677579937035902577923614082926159757539580021317510686435030115447564408009063820000532276634217698668629344082381094173595257338734645889885117039239618846958848345324817763296693381682386085205101894699732133155449861959499357756622811951834618765084094997909964726817167087409805945950895777188735082323780451882258268056889483393833043816736866493739993654424263629102171412516391868604763509794727937715447238372059912275966800574643439644519320110179136956671021753936751438291522818511894237724223263616937934405469561747697481049301009283137548386692352769365013814763608912419908713383379008970395903774145124166991120934621962430533611977866599961500832011875680083942515203089572406018469457716105527976776150610014251755958807292330449890565530097108382838493890672530848791641237930412953712234401308927127634815148189246179214196102512386479648423066788587534836145974664195490433371560357045382261276245117187500 2032694259083415832166956334355675927323850164894598399097378630734196701594257283618061083016649563874447397890598984999068653757215911734900959380393611975946527659449561506025355996659170272624209624224444252197545763083111222126669805605993099482587391029480916807355265609378487151266313717368915827877304027335644269292899291935434250215155952723599642212688275960636106357090544403816459606619920588202389697123656535240629480632101172295832210378468972343458506701788452550588970020699621326395633064294461397475374215237912405600717415280400289537640598447575005053751255269085667714127849001380157816455400511611096876032493780634199703077025745221634179725240681633977750631200024393267526488145977251795522093667066479854798511434844805239365893096573032261735994033403870280046425173825436603938053227480422438671900979257817572740883400781033823805622933768553669212991826438796582178789836254405659322904588699936885300558072816480837818585340356869731096910310790900242924027574087519807039495483981674410783421660768588434820003385539166629314422607421875 23701520320227540510819241561597336740960851146455330423611127498435465680314400626902062123575913528449831418238163377921142098637140160034553399232186530801969408666766707029005917100415345308299610758326185881959308838570696118754393804202856527017674471727305915796913084755340054354108538596590862116147689161862214369282783968073307130743171950129300523030266030190077374478604597886795741439938847517627695468163280172129388434672346843456912885570418490987336298938227440269640750125342773558422545597501157348533558593227189677366743509007403033455221097866349322618765037136206138288599055857156704066812848847890121499588633561701095300519674730492311894913309465486379967630778101237902597588613964910459546069752199276101027195477152552040961846446176836242336579719198540609931496472115061750145036542182179670540036623933167915278273011325823049667846283740229428924691057400597072451871866869018486075518793824675889205042538530372363124726735406224264799606924035662230948419099804758092732857057104563182001188970104976760921999812126159667968750000000 10420371212517559950000216479264990795519297806143334441239622547149482801821642959824807858202532583027057635910028135786650238791634918067816260171159276908647031097478702027698272233365886480388422855282278940328337399783148823512385703649461122037571719243352919395696581974909102126587359504554998316153795509095359454705382359924690813091313376187950361059797670622406884620895739336198382296156348419529506267454459228772376277574605231466438547666112066805926125088035780367270129158222433181045639614131238498320622525456450037973743463465648130446890521700738467580942509020567671972795996919748722495758092744537832979983101771776006954958755214783580496275001839699865074268193352920589260920575743514422592958320871607991895686631547201167143157448927545630238628363384874903460218062323731387398961234918226986531196031780037837471129891371949102674924785522868339553800064322764511099840962204022777866481902985482679192269293344576302406152396463245629275750359282595966283383563299601736339336465993806596364024130707548465579748153686523437500000000 -8142108140968656049778784497423596195150844920973251718954980984775119321084567789502636787442832617774713009133745080261496478056603506802250853135984630890561617761207202452605031046261798902421331259862049886028257454256462598741571102014055971468377513766745398313868454682546529190565607255563136827735284457263367080821442842393090343772445074936079619013084053861793306644324322467696535493092187211395028555952549130736752697809818966741324442461212642342951702625587218145793577977485075105187925354504914290372724119367514168235357131018962816474533277708226343089195478430123908373787894117570000691003899024014328433789671168053402309348382956582399860935388747549944209261695082378664351313445530738474504877229047988378939465415270559479969648463561279007469849195013827429265606061528610419396519403849994101639625737451367310930812207200310596675916469456785171696443826264633652130121539393065217520297747839797433032690818496176903945142475710179660556574772146097872168083439262617072608629602590646703874632805764122167602181434631347656250000000 -257141246103862094380169167754703839249373185476172811008050530621083852056190831847680177530589237042077104896163157589449870710417359581814802397944287049086488080051047014651706758154186725101995997461524250586652094124753563981610957431654821731398859302705763571478548627500258292538232922311608060851110553061136342675508625936178954610681741230015133626823313195636377415858768265724749919033627133747621698178953830110726668284734365450997981672847237482908128931841709232916241842168446008061433303668423665723320567928395134249465088474176030511257681480839075622361532241342321446052512581834302533127428879302174336257280168687820774277232259767902177709275106740782291697012071569692039820495730850273635454815319857137986124035731225813313155796135367284820916084512126062389891045593322338521764184494681625597483624983745316889246144485072551076651711701013147278498757828812743559746950885986312170740758426695313702879542510702249437603666557289019462109003258826783994018305068069325472088925673448537353310561215380403154995292425155639648437500 -5144796622137879151044467100114468853917617680676803094178206578043285800597053091627631758857482598021323618804504186015828000213185352308878555134810020642921337917810866863040248258500610936458889372175392843507639060656690309268014987228825933748165142855002744002400021102667693259279956709551436795384460010478543987023359828295754041980842784696876933193645963113675105997101695386315086909926384784114256635436157138130226572930676653720716275119509875400888624986988832672786768407567804043598514073547188552698280028013414493525472807403881982659269037552672937403921180674443468583900282085423345618973710186304323790294082801839208805818181676729898642980758220492438936036540724279323852200450506597069421677689084477477675952362738845379594510394223011874113716264207829922508318392899172951354907551916868283308963404782235281605232326295320740856096268418005332159274509994882630345148526952451781362539904385321572186217301856515183040212583829929661126973368736906673985196335976526989355953796027648081135019708653999259695410728454589843750000 -71161191339686383746367493563991083538726040195800407018245806065368028777781240335753812868098168702757129342269886073051330287903519651419468495977735407259224848742688010518773120807308312812642183552215024849631501414287724472719877383329301099872080780955746179921278723193385523441331329472597078525517939632159585868756405594076620601092355701960006872070686569618798637193132561197671787062962848814985994815477049946701963311920054003250055223009799818567890048892936966250278244906999460748590645631245636170938922502525234602278110077627939628509036191246078291047542803318040587235201640917831190971018576036011126045272158553448706665686837356746522696396417835866624586383575649084655835351724529691780864498900449511873847103226340635189079569014331318517807441940103505924600058895201674186871675970154966391972163653588719795601429184885098036953714509448562371710715165193956072611510647173562222792935485508268326024444014351293847138593696851009311390284254400657319280273026265919656292518484714572368776686062119551934301853179931640625000 -472419725422362783811739438590157314156777040695351457715696226239652792262839306487649638140671495838828973076719470326482665262784328458829821173012586014729752514216659921079220193187204539303016218458454132562204359006005585917281031066881333005665454200713559086341598439965227824329228931266403405598122726089693363665368750930375300960355336285845590471971577542972783469029146129412109577590495254790588189992393199158180092580472938126149716435210489925209156115489935201096572048960701378014326864121648843228647143350124761095647705431750456741993999477017701650106035068871966598651735844831278074332563832035100203894272261376220813243941526829249476815409834495205947046123595882602579464751199166220794874828176604820380498064770390193417000425600724518546983266526967418658044298030437235186730749001667043539305338015276919062200171325511586292315787158294196713440485955925140686689553105183072991718286282401446675543900418047369263773731427833218191450347298398470538192123025295236614413019616415256862751448352355509996414184570312500000 8498315779414339362021449899074854080755679523255453265409720999952695161934519627956705507118568766932969996377837538913349989161929721955243907551832785263444902142337987105245135414754159036124976286152426134606090985522524612168706643471518299127665866002400666926496464799460967050086985803588428197835533008178794627307369056161827726906726754003576643748289366637070845990239781431080226003059774337888725594588877832001130374348155761886060182790477116906230323742266713633535370630276298676177255483554486922850529356518694501606541091680831596565541188983270039972036673569084464714197349907378368128844979476268055182768220108243537049592567791929297466621388735052039258458185342878284718990885923068115814098486881890236354638881456623059756527763797300810693528219185430415775788199246166261417255972203970302455816692662399229620810445146685771842916871743950791247537903852298274580625235821068026360254444356885135642286164627955688138651404949848829144696471874338442260426559148907140067413909425425577737200910632964223623275756835937500 396587875723201746902857836565187684465858442568945138747137248737722454316399281054120139431950635999555449386341422876437891447552214755190767508246493781710644885267476356654461292939407090793278387335395778765121732288242816097358570683150358154865315098389096979446702723380471580868675497140949076304823150622842739116800304124870103790937966437952625707482536279999956660649148213833657957554608600644169510136576572347814639144389228256055300327189187160409103673126521508091801405085695832170466561956008798848661982220538458070877503081465767186638511561274423547122525288416462412495556077154942952109026041182915743889269785912861960128557736856098226396986027100507819128599384145858184823905083154720588313553332954164935188208627788184758332344897816223683115887133758157321960482400525625403167363488812167655640981786072056919324894785137193451751108112634731800522131671600929733913658546365491966554716438382955665497366179071400428757151357231383028474729976897837343027217503990639364824669424458569721991807455196976661682128906250000 8974945936298377976153724933342391676799243021186675333614145779527059049473555347815074377707405675319362413956697348920514440591897443535780811506268794753765143952741071872556467468848506053557051362959015327949342670955374196530573730496365536032393699286599957719241570548034709370346916670133259272588702420779213706634390650486194184181726018557130388872228899380133100696203049053990804076857568479986034042934677760790758926082459090396402023344072548033531138385193907382385658057329333825478787436809459651873587029258420752041527251783053856483107240350774335401766555192227860705699869836420516988195114159677503893851333328340870215733270999522656305778109614126001977284167774311511458103622759692721891145479964488068319520169878749631104154168303025052513252659088292316370883178592398703659965892230963117854097239482344280453130612618112121060076148722009178377472892217278237941448787986127629282856550701859476481502904315296033852337111655414970272460353310381694645177787319804152432224653157533111880184151232242584228515625000000 141056609400369575081190349923320936014127396981000327598312886827464931783285640890958408460790675379284811028764893528968862462584242588897231041896419419326312832297124673962080728066894094202845825712548470414165459184770111099138160644654431873229187747801939344804415562869324700957176857755466424801534031859457149964321458340987234529648600616320731626606669406546223395191008314979425235964117607037521683422071495036792822955404194074890664342925141856263279190574972534512485525375763710534141612359094495385978861864403527145161055783284379870557850930582292837535454616148612138566878140151521249983527289200507786099573419532267475649088303636689005835059974346537109699871175029849205175713741625726194131007464122211733463740204598828471753071232248302765797666495545982319345128935453538114173744932232476908978686090085554482048778085026257088901442408793535365682020819335390999248042865413402472122776451430179187656361798767315123857032513782538437092762349331594153511067736177347209510987702252293729543453082442283630371093750000 1419020543138642948697328549114841249175634712336710339805845764447406752500622781503794276117784511459789964124898597632080942596051320547094688114224673806013149172251671604370791010302424664314956106229805484193222660413121002650158756965882810131194179751529707811661568947145029628132723085358493711340356637062668077027762353430440197008125778385397260853175743750561002653124299940082543261610910248080405737365276527847899646856784696509050980700666631013898429848117460507479692275686054092965972075413932578027567541272495261478947239215004266326228530204107750637883989636001611030566679490787824177565592274944891326708787244167695363993005663251781871782739639978360023942583566817881140345004701755286068452835178605664131412391787926518082621681236626088097500690581440073644273162374775353779258824410770280174930179311788663788702933461518487877071933593747817461587144294581629622051862667964807986371718483304479176111081216901926660614947269011459220726015450237285856896116306030595458510107365057706374500412493944168090820312500 12687509156805326146538176331477296429301469779240936773593639368197278870294124029974605647464995234873019766688288667947880551965390728425189236349615611519429723894031936622250996420553228518911131499872687124646696372683232061119193217181659297981920935500544734183742759601630614851877263775875786605753341062701129065158707780489663127616074082945003029578192352799975842931518133233739265972922770441737616147029214768904045469756152621308038939667636675562615947634260967816382516701544976259935215052793852223351531178094201846734078908546587874444717235669865584944090353263896594533784514936808249350355352048734501935332529308794264988391943850180784173469423560931784238493002631654481474516474659363729367291033769786663613603665703161262224561322571333939103264451322834274722131926868395488274635952764196767626890792466308230384480449333044618467093074783293531396083207551949015005304456601105051772249254660966742727539875390307814969759014152619649832386839009147057393851026061478565187812250769638922065496444702148437500000 -393406287165115573556214235149886160939870258087974524981493262442444322825736731671622106373631875820857045733818177611148228052888368324666069260016515718008328409279721354920273009315447414572007074899779634454167955033283820718202681485593383593138192162083146760289830240810661740509244606728669899265181091895634216848823000555771398952087550952226233883220848802181351748430345249736428297389215316397277844212941401274631069019162281711546690734806991529064354700208421002246144389367511264331246688922024726006680560360733074679125308049378945910461134715218110891732184718753411061570919492244539495676663207929452296574816604757316834819643578199016970588847647510232056968873911473305734591622486732742930840508346631547580640694183477885141359808855735156428139952195078682816338562950814705293959105028781060820490229536517336862052768146008695675047984924854893799321050220752103829306275234878211773450564213660216984399728272085147664039276591582883683558292296354654076935149924998890401395268412443328998051583766937255859375000 -10861733184617788583616637546717138102911808750189999841474154861738495598876066469766181775763166108084404414409151782324069655093130324544902196534366545857526697810693712047045236220170823389071680571091678148214594520041390332216352712613461518385922411313325043993021243365137873814359693609242817852364685327327819237863727119205886005978260930972956979537578154474484279236822141867571711944349949021967419203869575318520449767188345345828250231405407448818722780993296601111963953513638698370995683079039117848688199159078096794339785895703083154618641037877908809966319181212541812055706862657190570267394589458947225960850949511977365919372824869518563213978866264129525830287879996298797557616621351722025873395997175069298059655575736188905721076733002119508056957396151386943857058037001729810163707674284408509976027386115792220438164467919295685524722020617757515314025580662247324581874701762490563237714715359545749815075084811803096943846544100588583673080213007458072975080447237052408415713955491810338571667671203613281250000 -192045162811495312294912214617145390623657577958093362659830465733976642263419538720080436606073958282940009309882258965316907405009847215259712960553152463360640891005880095870013604680613419682715248688845909292675893236933255166335731230939386012974095314086841010399722204067743516149536793266023056530288984430332209784983661221524976720991083350001212024801849669319488650267674811297045354779418226436358198452419806141722545696757645371414569795474369253167199303820955375455462646791095775758437321273563831008170933032240436300351952998127967202332264378453809874295975250678072501958593777971520649849006755514024321698915108125505715078540206993667756874658107445974820077478165032778735841746180085806238212430518373997157330503340694464822163402116724207530480722965460408529806264032331115800003127524331614061000482223172796835655257730527157292032933912791380862024103180480817261768694558471601917793676736209234271089192992661944476198204511006962791799094684517377119270356508617687146811547904690087307244539260864257812500 -2363070849901438991974813294061765457461955786754908478752633587345415741425285154746064771574035458000897104968807387156089563973601793159094672471392401073619510576023523741409463440176246155121790199151349603133452516114004908550353589863507181958423173877847456892886110275253534298696148352253784816574254640633718904023532909633050182316520106071083485637529307572946723488662790132833066400270651987479042967512301789495965871435660693779483877226618416799692903737384579130647304260170452387141334087989060313816593102278853496279411426805487891124771181716672389728987123002509791477309847733782507384716104556087864908410160504586299351118899919695519652698030528747251133348560369952085278330049930562700424272762896587916477933348225180284970398840890264503778996337814539629483077028408899431231678892596582521267539868123720980026326164846780421408054767539856864291904324195964468829020144053956678695723936447851482003368856927030373171492771459140323684507871033208873349514651460157033113773650256916880607604980468750000000 -14275038731359475109548351856521233344532678605074689769710327509514870661259859134910061090023980276959189570335449859537431380100897232011851143995640260379815692945373866601279671915917865000153918986190743830904799476617787233699477045996335594457972329982909167055436076233694512988543561684946279088125550410317570877204011697543039057870086067322090341844509792695117161025615521840556822550549112719323783860192953541251349086156509368374645104385402588662806957588415145320442963592936535512685082454796189883737781176598745305186743307066059133343550415035467721092604115104125740245667888252515342897197884625987276944979509674314882263847561371478968854851069329315281888922150307931039902299579768652800531325034122291342490072436671588214359463666467496553024662203374728987898423101384383717196165242779623341681270516555792119760162698275352609987906283306001992443274213193892073852635322325359565466322922015025572776039578141524248599369572869019960358746312030612666594707113598694547818013234063982963562011718750000000 211020409032077859414148222642175817263240029886368037459222573132201062237721736185263565625927377843438930379636372757180221043435077016593979245417628627563728439938889542452688492249006410872758620189444421747082793709951165632350446020118536046883234307270208074103719686239345950387870204298708622500339509874024609459089569721008224289788173813230974817044009388820512273731145082079923764200433269051592668935274742957916743307668414050092378002503473336730231840858915760897391189739948996893656803086216472347778813843666525255171305986955323612285609303696836742468485218480838854222875308045173880315559668343779524747747611530713794960997457694993846281745078662838431210640368668416352724731923051009789867850676197658226608415748402475460971965071245576876188340944601311378905798988120961435751479731206822698363766219888349094768146074525474341716663997552793989143742453584296492208083355773576266440041703469973225914296412293958805692993532372269223287230914925829793190800720559252567909425124526023864746093750000000 8991584361175939615917080933895333150597074656922206504336942646473674769334895149519441942774861781902927084710559134664099305177666093975856190496080810172555997575042812002721422833831132393376015613985437519318755242881746782857539645321336484218606744514739780399392451355324069492090773238210900730693872856730057219362389328955676689500514300945743011586570281081908451956916353031231030403273687384537448548408853606221561449124411358097538925479123248188492556163591426320887449759263044831602602307601310312070100888464561188660363707501907028115564577453970734769321000532701317030501731885969638600166715553747083800666223228864102729843654530418581055399477356689970049763288562801518482741398599797512520533484392857577182163338572384533406178015756838854139116400624943745791838314797651333743846256760534127604531284959062078719807039816237500644372576746390529330274825073207681391694570185744267681374472427230524399537007776549166702706776116241555475186032231766103784244888869059408875727967824786901473999023437500 182120609326986193001689268207362764796656630569092836766172873761013905383799007688701133550166339705384856388296349096824753935659845289295635088042672777970277895495817813027584195075209510340364106841572832473197122967360471535538115031115628182104157066993034004559191953415119671860048827272935323934690381343681814757111135260488204192370265350511124848519114282706618307800772729282232740987810518646873886462542773605963968781366548445651435954326650891154362739280395174349213824313992188454553822806681808052152057260389828375661565103580579352490034506262455233475559673437755856715568535005770954503064315953021065767047839799203999035720417747659777207203847177297780624140851111603669192692353588138460728286299355315700397085504666464104556506624962812328954435340640176719898760206743607107092387237294683354749679004171777446843110348416560205737567715928345136234478250808277042831149541365131468572157640633069164644151471668744561968783566473540950733140664901041214573593207681767580652376636862754821777343750000 2559480421991021098406129375176858970544864108902074178368222122231321108686963910855225606353179740658706709875615837977725453608546737107351085197051801895580499216259531624189935413518066796101185755824363119450790255354457274821150671495271163429139251653872457683557696461247368154992446646910425370803506649502120198330927344754109734278516367989051764150193705518924226060670851834661870293695108361437475167913761334742778384928363158443697388282564205114773067682702574182186850033031837280898627655664597438627184390824398743088042181120688994467720836417556299049841287437842292270993483523629195289909318653906386519381774613132759658297984801167306058126388212337716359527268450406076806162990938149512776839733294694411641532071245120137231198881061273737004734988668998532241874368518735780766065327430816791974916147549480453446088736805609261981266548399343656603177509411732753536100159298421608792796666145607674138730308109041890993422015214683609144859611624947583479079693535851447450113482773303985595703125000 23187748908815328732938667013389101366125652600234258705265065397302024138848259697047065170908144039075228738016854287926175710674529569455067166018456470261985865997886135844931729009048740883382918940680099958144120342134643210482000059589103052397257455291984684151075661979363183064577425824654576525404664528763423773223311585211756177739520824641188778860958939255530084343653042565227792413078666976398068843106154596440100925017639102452504079408291204359751843279857089051106112526462365689787577948049951347724698735825955558400160153563707443712594031627405581748597152381597771123842533118269553638732002043640783877960435462259846982481684197319864472596034744584985652928336461052494231737945551904364448337176878002209762901527801982687650157942158034387672404071944617372194157232983415960200583028078863687616155794865942445070117720468760171791861985471862018097125679961172442290956563773168684802431616930336264740686190062956555157707110367261582553721768516850464808554121987071994226425886154174804687500000 9429452218146876441874409890316381760016847736803651773679095813470907983740958333639515554421643196641941771441186562521535144805123109196299947088074210422929189730411518681527953453554039933443016155362032229551939276548672291428075174830040946350079097537747773029105775180114564428653919808637168177311860873237432627995037313589226714771552092653239766536421668707648288612605664535919563859912669754125589421988406606431006967840593243809554398760902967021817429225256337745715374169988845006238793638254217965666173037640242456580492884816132624913299915343652646710904227514518264026215712685865770163634193511390494561834002097527812906839392100247988919105757647136245058251813729909895208008530814765038214643097048081155897665572419691847773615080448545541428756709661664962414847540504656749584332776252620551206006613515090270006031450782749499464406873196009106702750457453257722449940484101627457644975859092894976815455671521057933239455061314145355878996300948039020056734571539891476277261972427368164062500 -4807746434545590259864949516417830334921124433791915772316038101569670837906744970155378351626579184981310985710884825765462904093208381239398074478036096769451958219022978275232745315081584233681628436974232963263623260258122768767185626548852292612216906127579768567623047807008905862348442887122455070576463820994667818777257241789532706701397964096855255023783342787997459247140656083273819813155581374727387537560735690258183921890993206753742012274271794645434277334336987847236218927785049115334721683621320391675277839091600498441400805719800837117008112054007233227301687204241457430701111781083675429413033703259490110264523204560425711410640744008523639775422999983972731903096308203780126879331879444129418678077852853842020013199863377645470402993882729113732730181543166508679721599823935828778726498929853412473894714284374754946649179421949951713594324528379559981734992889631266487171884703250751475867112836625340801335773205619554557933964024210854401274054995387222111169478466763393953442573547363281250000 -119201324927361597378439840478450640562112336280972610500976271431213142286388980393620026756506622852798388452116466149413190178747895396016826156235637327350176984034031088211656011084643909403573666383533181083629704160950733343486423762460882663218539297643868638129426984161484719065561867446990297828719842983219890099878619064655575529989210791048243170503644430523571621618215268690933306871520683206669080889794805153914405941124826310683404949966013874932394786630048166094656502857336871146675756323410893348578058285785294772608618848408915431893672776898384945721780762126750035927209492947672856539386358029914501338874007611118764904355992367189063378709084414150412347177821296247059622850660045695651423140431012706370678350031885466591398742810822939376562227043099447719002558642582253365511893482885122680805714797705759461117662951710945709405983882683639852678503091222001524214985831585870542118064942319531630807514247580433609657613051977875395444461778700351306525817562942393124103546142578125000000 -1874227879728757329862642404729746808164719425419152971309737726964004877754166221190625228424784421388455609250666886808633865552885885179982433299129129578561050759262055397287076798578562075930192350587298362887130903942122151267496368139429498316083249375096374390090783071609653450795886645723674725063046947583152575880983502573495344840786230116470388604206465231773789873738276422114914476428027501256343566811167437299257208992394662475554594612411150861776081929950823059760771916553075933425711867163484397039830499666493021033286676306325066747585713676461749386663356122996779044456341006164136622749806048372729840171868402235614104201479510899072005877071550913523214902863588857415293292476745382507579492736073637643716459822389885252593127792411019441519690903268351039755521485720465328950257046775407763760662621386512818150234819475467293310205798441945455857891017842554216878314991490183233697055676978138856831792777110264567031980246338773213611138545057685500516697629791451618075370788574218750000 -20476551548307168267136441871327068943390857602159516580295844766635050379255799036155329323186725139021737436415878997817417483695738309882815922366799784010368903115099312128558055136145681007040041726974368642427111638249320287640192882778517608056710316475123090235499846401262915778549591945464809077001411425150107709912062011771811834487183007834826164374536863519010100851945083848864077706062239375272880836420036389119280610620120559238222791462815435745985450354566537649622860313110417972478349959000549814592531196961747500950644994977007522009375082579828760357241092515952122461847307090499250371017296408774018671729034328549972190126131787791972501024808660712017932403928106092309908043795135726686127787536746870341628704524462410151190307975439571842031027430681975439998650327196261112315896181002341457460609677044183011553397783129577420491553092292686739267027720686410794223952537361086206354002303878159098712018743149187793278312741259765458462533554723911111139500462741125375032424926757812500 -111443365162391214002061445632652801813589401116063850949504173804028408201725861822878137242688068128227270446252743834339802824796455623717311537078835635220618532739546637309262076749420742592672462927692010064226355031156215242029495449088714607552739586841470720100960176524162091735643353633026641044937352389905542494817940926934765273288166216511099152260334952276686294965945130900104438087981028161036394516620694802149722724247422600468251375818705963760803946301187197867658392952377511441902331738800985404845167198746514930480951551398579162076410194189412618316753055202523342663262820965104326421025025058651993967267328715551165414050889161953374919100627761014774759434832867024443722973839428235881707346130360247927547014988967290191836129517018533257745971100237647759673876051920830836839245457141060636517445778672879871369950158792962097973135157814779891657715612547417861041733768072811792665705059167668030653253764804400999067995636681451661570505656806417960069666150957345962524414062500000 1347599202319855206388547233333860402923855465008819930050429305350832147854399213915179663111803203882873890748536116334275897585194968668072755835092334522795940802650787933020324193561444621308326325139459657719052977966640755673755276469899267909182416618014915805330372022913070298947239887096710269439708438258536603663407823568447252814187961849440813432336912241822551988969647250917848298326681041158017368728846529547029333435159409566759337202432753284385937476853090830349991322394728447053348627586147573660521465412935607487108383897641999694282532432513117527524280356270655810198781335561823110901903410300403622994222209587602664558075738038302329817136475532019363055356256873782127760289528977810191191128341775251336446405324883466695969789239151793737736118909950732781386947150159980689829686220694527096504223381347038024833028902850616407610461358114249671434562332205681093801502284893739103575323643027440440885300961491474537338141179439581979269784095532003220796468667685985565185546875000 51604485917091379162468423374040010341620942435732897229378685661679948068023972868850599773010832949013746565752115408068745177815477335331661815157023470307681810797177285339286734985315509273849476410433453622074603265002278823508072987915695855311471801388316895360687427811420946018031778856767563417854275219490949872501918683241244369209926043075747197841501957612488249747736749227535568100538027012632271786342341798969059744612825394289088261860232306445068991290475333161229821800958407250764809435115511741850469161024172960515594856994332814555313193142943080617498831176698752068203053937936712893358695767506766791190326783003038264114849922947904562646247547796596237118918368532501486968226856132922437504090621636167041706516389608979636746452409794486948146891868476455285010777693753905303018755925135841140131673539289031524717372952068802153753361563450616130631213008837301836179491591372775503269436637391857421031736925738255700632603250943764754479770040518360474379733204841613769531250000 917976014168621630352923957335894527187835985880702338901503914059322548036342054452452413358529554476365709094041764133547510585502992383697598589660827880065301323248170690223387989046966406702591130923948198508547403188177945371808997250735487392902363385540613890202173532711223878007989677769850486039795736324387358154041354672502289879970347612725960766827760626744991902357578666622001995773423038124162938998241280531241236829958856580456509914324149224604873218069136136321486545582129377275954148075212752775397356893925428419746178423116261231770677796240758869417853772713153133682894081077747503275657218477527543429418951912269780858736804358831525327226623834959731379832984046857781929719112726617085310890083087607684203144363146734010716807844028801386634193567417403998559415199348019516076126060607957206936080741444411374188967764034614273376802223176353050614538397977715232294356103353439318824005993469493862473387254517285381080240126510506979296694085590502254490274935960769653320312500 11282250039537652969266255307547010199570451966787482085019855398219076684731796119966894529040921465564931351457756749846967591457249990325547795819377424314958996753521683851157901876091570553435014207223171246522321111441148078160785514798260816523055058524474497885189654671316096029019428094154582702276246194286396056382488411118997000895429312981411086923372625657432372167235176388817549602840254456370558021538435250318720405299156147431190748153453746029621344066465575701930949054581120591486164611148620487330283957978747819819618082435000110070371685134681724898598705056345347412174178505211501162553548739160423055735398929919363846520533055456274696524114061708510626193003342525713803617268270897398862279076108787320316566620365675571937577328049733041850459939821941672896901039279248064580323575518786561940082294712960456334931961764435275476039214528026793398157445051644172766740932223196829390548715143343563852665172811438637649874306567590945271639668590069049969315528869628906250000000 89715900739908879896665492632007250599437841097725735978467558976549035895484165243638958865378586606020442521743475791962751949945411320690066875441280075244922212655458949460594011931946742065727125036917995142440988554250200952531915741791654495397785203963003524875079796216948903538218708151306884508753934347818624702567554514600919799042287406157776243590882859511293812304413958555739223922007540998554208573778023929926628928327559705456268806554614471589164982685600304743396461813788121453359870115215148638057361446027708340397766016869700361992998020988744711633762033133974978568684612996533861389231755347985852181269723543307069881736716822448158615026351882713336011324124441513895404366716225988379463933957340191877180980266541563347458744089945608583497166867246018067535053939089674496946977071372206202662547553628647998429283240358829133836014212318807148263257558538678077335633171150658806554975743368326254956640264096192346474449021923730507310779103136155754327774047851562500000000 62140022187339006826964287352119856529366767059758183081679178069025271410634451848173480536447797427915861457610917267499875399721559496502123235928592284910235446271554357173158133795689720481797894465108709882743303500857871262134734344246614676188726054935509067420309029942714772990147627847367295926198924036169821336912016954708211445998946896504216760523949498664592504501863404389435390764001051496756538137786468803487003384601171759738724866343792973505213129003130369502024370434594879188717655961623649069710428682092959297297541398003515417546378317476807474176150194048374070153067656574882609613718442904654418311694884363285063478413916807901926807055654707318920481195985554560900204190324042101166082989501997158977014553845723632553123646264022115508936792939752683439704630633547219199284461427904549069954781327704001443335736622048577171018451369555323207793779948499504064823680231356994908025186038097019447343403505970771729815545604894144737784245080547407269477844238281250000000 -13053698446102509068674281273039557974743271196783550415991461744605017214293099253742090472735586857999945003188114500741274308566448529233625353917211963427883235298966349408117001596531471466490406510095856059502832160938234627302315915049292190192040129475758757447726946497748449552496266911792697673884396279815393927454417387805530578750934786879404656724169219145401160988470901253314109338679887955497005492880276205674240027009622626592874964661589070254867091776299185561468379417878026869389186132614753793146418133648024219619020198901739541196029947925398673215379606869795059649344056547713036519251078474665775473169630242937476008863356374986305069625052090074238310044292109184388192598142287047228148875316015551380147789312662402232695480425179533939689037912525265841429143015087858633522863652530823335528629856338705396838117230585569086249174953989525201339990599432549668465503609732300097910907846735604353969718977905090128883375212906882770202976473683520453050732612609863281250 -281169319470665136574783525039354288974419700408668991575309146317090169950124039019394589014116043647879022564357724258572335191893201904593177910490043629950567505402767157390248465791678513088069059443874637450139137187215860861230924196922826767092109772738410088814075291037474916778025036230754930314850503441506237625668995356923029178035955102086052548750377811810661496930140161723632881693492867222430955556862061501149223776124287441643175209129201433130215932183397054470934723799722339682949646392939273237934419892693689655177886389210466579205150349695945367286200586345623583604973164403285339095211112635680776502578864371806006528603874486039250795443137814895584047275337745886759546983401882740623637013362647956966122199700550154208305425122925113635472932403770421689788358848665105451641050396701059030793316663650823120374813939315738011804883936094729452938110733544390615009615594104354119184646815659740499494274524100186931777482540924240073110240700771100819110870361328125000 -3800770582143350370034960636789878535239591177762341537468666258955378573707587652119386673101268400890941177016782833327408440846039719573072188513264126918425674127154613722666686244929877924850944472240467552755430997438037313825648043666577341617334963520768679081226685454629658403510481669372154602023366974146516679642660830877913195709513828230417934993080311533666881210369232689022379008238392707670415932565962144373032958766073095061394686117614157832109677258913390964678210126877508053516339439497683738986360874009837707887914662108134070241340853563132931892024969152391310737008307063297028405933258164606357484094267014029457275112771947326924656286484321697110386335756449585758968357592402683986650893377303962206762209325431197273483654335704889500145629857283486985578127496077052503182810711614453511776849766236200190152599515152829153652216180905173043355527430557396993457722791291404800265951681981845753992692933665106901794306559685260316072685782273765653371810913085937500 -35986834280358624974720403012526702323988473552560599667638527162603733936205558448177082116641484557613611648054201823798181080705707375912438152229869151797460279742821124999558901985262148534269945966743218491553715073523504342120114975245408742721442268617706227107086401738047128839658911919599678475700907049215946903242642289717910152018896002053758032045795360608962549040371722025022448522540131807947200703540962913995440085377629668412348053936276825310175343657848541182709897934045594820478575009161420882726425245421136176028090682198114335477036425503238546797166220204831174274535697456737017698569941506580257044574834229621048000530580229426130026848152105057169381091186786373508936270548092163308854615298865487111718226575448200181250562541290132081944040521076999117778999700685192947629292696535323939471946655711484249243144404732605079436274283594655202818995005518028198241103829274353245309976635376497949931355714189907349804522715408516830848384415730834007263183593750000 -187326219844410512073570555654059781693236941814908247787446315636429018219301744270660013688532635578881714572541630422490289015245797315912974899356951442889553961520495745639934266930732418959756269102275576304897104696668971792801329616363534824923110579657885289517275191916683202609509886151624129808328960666030103947575041735010993741028808050096514293678423948575218291782899265257113019246645415634646025935231662460986629732857729315531911821086518241653248852589635786185379398394531268144453859436364203538626169711241021977141375633661718976619249514026292954091745243764768419110756152915500686233126586949305537965271117749022182185310781237878093029715002888502100722554641001693861658252732291396786945054905675302152087491323474961477500952135934388206748646329021767736767505198070579665072684021535400171823810681151890361213371873360983436141124426881654739213857990819163224469138613572924771803767403533229205165872362858966840743228307597512127813388360664248466491699218750 1070924457782681229757703616088481368930837505252894611632072615351818411524642564350969211165194154844786213481608773073125559192414670159961979865644836890006190882889211657017284431644274265752659678389505779741511166343625542507741721324111096004652021020698780227207972804726621108776068257848515780127631230760118710136027373499058679337695779364665762644356724108699653109047329781125187988954136895883627431547018540382798476539197868209898320335347890823612923475445803513388327906022170839635868050274825918482475162057586570640688835409951236988073050818211852632933750685624304613300120272318514373161042577896614177734733069956415596489907166997905259635307285525007908864316427953652223926498068809027164670211564986495322450681524710724126072762808537482227399279285512064815076726737695676642331711874304417458260775582496057389601748303866409704183530836466718830334992839361421505901479125516769763731770402084654511563140189679446917341010259150380079518072307109832763671875000 42752425064278687916669172534019345096138467701959090992439952494869906052084392098163194621886489704948665202169884914465008402921909800094970170675945601507266813782964969332926106117882384132003030695114410420701575698189514894712735866142070341706146544133632996110500063218281410994581868759253035220398701468555691294645640795831038929343158866952224962042188593902297179919575424752339357049867590450224238060162027591539512354799180258388382496123859818168469331120120381636705627363144619137998611092096826252719516758229689662490176404608337799204279637895709998722920131782372883068976287686041367788614285968204004526507978402915085843318446957365929714522640506540431012397559469412254964221808763287227518392710433894119663743236659767309730721166040060063781438647655438798089444934727101330341873788358160238368175429641390283352634370972872446338355012328477176494273312328167677302841350693850283644991383444295109684666422470637574260177160567764076404273509979248046875000000 649499129056257959342607460416454056269049244287414055439184088521075100177516485627598927074164072815996674903376700481925190700438399581779084928067609589223930653445493949270667781838804914916752269860487753964561613886176962115473266004989561565831571351203474496133285666830572027426035009001070077717390843373679365015666321489665692106491046904490100503049154160811474698515296487855517680565562384334396520920992732999937113611518111164318393297976320018951925289538361517306508006132097142148727473516597494196669417178233788999996058739096152439298467630679257599154729094854074805509580149359711654085201305803213542354266097658975797961885303241869300023633470079511863211976430182805613869121803542185482591655439143409526967741616981052468746053855311472426245084490322201965945527824443549545463533216806224058241878946350713813060048717026021167983585106753049494513246122850515932149976859214700894074887392010824579825724617518638466517888474527353537268936634063720703125000 6833318905025014741717859588258955848180964339573533273626585490756414483128906845090660618849004962631944356369126658234803047261412991856625994397970848763605853648743181829978098518750172855216925269790523142738699602454022504901175181375890356370521315580152364957417746591613487439579533923137374804607628980347114627010508159614138307454794197736793387897477369172853794632973091258651849308700910600268430943673166353207195405810008801044279609465253070230760676843086783046220535435787418038294359306863893119563082930328267000668630658234367042927893235782184581140167152929658066469522764918749189512641326258190172286002031595175209862554858185204327866698698561693839712648191247747240307912863497744007775554345504118605233211210825783932373189271918678172148024269379850744330006670689417048609938403542925285946478280008562421412459398448635390314229437557370334521589039385084400588828720348258847398479537382671630770355586123550100871582024808503774693235754966735839843750 52939320486485867281824092442254108766143838652712400868841745932405132337160753176444575558032086573102978266801219147061831604819460078580278503963283887365532836056712631076869437938464293303343806758786423200814681160661254176195730071747419595059251444055415305027459457798103449993110435921057449809622823604376945816951965809932012204452917486877003111499154518880661448001783548481179339016746890659342767579479084366480563617426953223051945622679629605749491171008883665668934850179833509377329616674760102319116057148882550828270211641379770165880756384748052876786089768298652871038573098445746007725324904543366701782682356898994595607420304926709581215405941266560538230314284594106784908056482106159458021005940499935639600353758470837112331440838936093514688128649566944412525725952384438910414621939647667412364120827513472683554730626184232780534216623213287688368729266942997784515626177749432389780708860582270933035681817176512642397767649526940658688545227050781250000 285204514070400746717766450629061630171862333993033247529049988296384479806226656947666107179759215586411337668280540605452669526859441698730256175188659704262626750828502237700851284645879088509248349623991398824011135222268921825352274087627515413269138561868218049176353002061444859178090121073028005717847634607622939901297504941002175178489419230027882652362391698553859200973665839125481555578680514499855804691272030864738378099647124013052151659108469949501134852613909973644610509130536711954470446747811977611440186859663408230938235486632386417021511832513652361320718408977870532300214073540020021911209905473254945004182120041518754535608593120976784225946316574261181887576443990530795205988105691309203769648635893820600440884500408337881712016747305508986039240864915999652285490320295660523698150475385351838821293431000561547425919785197249324626962172119550838204954868394973827105682829074334112959328577621467950622663847012189242136059874610509723424911499023437500 873935292670258216157575248351991594561021595457824724455002743829290470485330117912744690022995646401443168153118670237600929897950159641999859853008928775922308891589595698195021086608586023272666189028929937006502554845660026820860546051015544859161103335611326451508886914597456210148185214424835230021020991926417484721752175981369586127215309318257989869679768585431455168575961910212146454705409961017435488576489374425687466506008422045454356888407113860272309209453961000817670643238593416075677382128940228902726309756949767241229724411946945221683550553133698523987178226052704708000284705988257076571257025352587417824845048501208230322063835975880128284686120704523524861275640745276939848889638543464250904095154141614772688017173401576795670409116508336021947143130366171607942230542879169275174287924767948661029729410425696178102402957666452620935801391270932892125793035799542700474274007021708702024840799370253012720599107565622176707620383240282535552978515625000 1536327019566986174353918643975458919388615634528844125188086925373056532931876490578732272061484816791651939410870487177810633895417331509051799172873575328368471691984177333655361159051948292602273527081367107003509622067019484797223964594590320554755473084750844514866902126998614086543939786993770981887200411832059661427001522862353638443946304372793142796686431430453687903714443536516920280057570429485104825384757709853332756660437460378364613567965668793395270160835400238569783294188378329969716696667589931502200507234113254684099033815634147535523742832014632856356839446674111563347307307831639809899922399737599342936886189511501800499862309043182887744902521278736929092273053603339078509694772943514915869758221135988901430484607134542794865805051277417097595810791672173143149416715578538668126643331442638231003554430318267455446303859545932640121120864601463091212396993601116173421221494015198141524888664877250021471377997017704331028653541579842567443847656250 20395412273727938030675945214603122170409833616621514914667779560625403823976655635374410135865683163435007225030777655128645097852719092140511273974100832506926350966412953907036119677387395862996131384885930391996513431858259937133024308158183460305113233270575669483623923364969661103017298983308113331408946010060390993411009336011089837955468385262763359715841764246822130971298550319927841796266040889572545689873351811732688459094694124835274543416191598506384564440641076990720027079166639660950901838411811119707328709212727406811510497232875272086421635176213799067217616254181708131488494605413624824197404439824231953950587003125847572463271889221666387057127887720867471889735618932232306439646822119419456063806081162700513326243937894934918273011047962143523466508022620387387111598465091868308454596503824454664630858492783417385365412450376488111954414744303343262127434162795798687833437420778334641810521409629065187063545749879267532378435134887695312500000000 -582206511190208800794850981332213420045867693729114100167906175020333633680399675245418478277490216054508799710575247250827475669277925614708226339873864693719129132785855280405726694121323607003432306708676229574191271212480494433454885368507835234088176996926280084661297235874089063915706415860165519035554860985223217465568144542165519279370594164821849454160381434450973925420532693025456254689667809382555239459953367122025124284483668128453576155732018830664947721426322704195263164321670357141206050203202112080253337967963514406618124029521778213845793143640785643667731126708532030005624956578487829438089012215583213914276720504842382035553333899909469511635665423624365184310265683949648011440719365225498577041789000270117879070862953875983376477028986521205898812102781878372432854607753906026037860327840209525260365636869403948821530134783864819447938913634637269605903798379162568059940049144168329605924471129951673631364172933899681083858013153076171875000000 -38125751621868316140532415784747295833409233353371555179097116449821995708236049674858867694556936803251311555392656402427429798820212375777287731204655330980731608747197003070187312060558325324727366939002207265640282084259077891900450036481422775115674385707705407934425334662403776143903127063211080812363721825224268353842680422862310816303735133463516738185451772837266100041465936551711869396270547221060616014135876257108105192937365030671501591365155172522445412400097429239314461149212612844149371046109693460444002652724055364992324872345687295693790655201777314694215495395041483052293697952011389500097210029600115666627420093526599670707243669697137014489184352484476933166107548230122987725188687789894439456928467510958686291902661701058112576949152549190892551298434779516113461133993097947570351733220628414609839140124005285634890285865508493561415589638126945450657017650328190768088563248799627438263703139032650968331950025458354502916336059570312500000000 -968563877749881383029988241635091150754316351754743225331935033754979035198487351917342797848947903652326808134075123354952229642606416484547229394944703984570514216209527181854262091787474976076650793678421519109260366608220017214128541061174320442687732171389033454467327490277729545102764747048213394814509727592594418706925803119142210671489882249187739729541521091509319922252283073991051939099575620378765553904067725791076641918572749746674805202257755371856791662506652279450809928466988773283410440584716140747922175880722620133352756357485005586447782805713176469463401143925258218175115004689983512191553450157769201080390393359160707078616273779754088434700121643845510536895118739672603052971507204075177034040722056684607354021078813900244081928201588936915913995213484635779625135897309767835690437132262593568744943007299103768240260124519406365901830422766043293664462382523340000100324020545287706014362467783019921760412351829927501967176795005798339843750 -16371088666051364021295954642552321333499980087142301727101785221301331001713883281913611691816967355631373514559514566296316064517093539855526755175636051204141962696934196004973895940972602172347231467949976542134516224604046865113647450335636729810002807790023369211237014081904899924547496480089758625642367118000091452268931026421776697224744709136300482446428133728949174084652178740115028955869171708177917981206546653590569007023169671152056529564925447796929195393075351369052903521036513835098432912363033472606561908804179078725756942547493201758717503458520903649123612530915103171598957066059680123757996607125637803482932413917624822758437478330343791681308664522031572834758375198553110700235240743226495083850390456780481753743906448851536734277815441810597195067699911005674309163088261602100144642110245482120960987356842686305556274039627859452138520734349685731816387509447832305395025576892857112410494530691483505702166212358861230313777923583984375000 -208808271340730499541969490784691144375624390378591065460345216075897186896760004322906807400820081018333863656221981981350249596323262217973677683547422175431849880628432717248004105132599254578512230900723245226487875201781925830141702095103645220439505052745117826584547130092646962935388229505246813078419172202194914654353025956241467587367438718133759652301790532289894711423208291562256053580538527392081841269767032993784608519973323259223311369334684043201659787084110266924584087772870308260590791864005341287703529859873568174253632943798047283409621952437647504769654660160866114640502526279448935886234403028253188555698267072941034919530780675617644471765800214482487620713505081974282390244084522849237825926648399757566788125529131441665907690902029926397747498263845262756641597725576658475571711531678469869813193128411200643239750832018555571971595848578582049676714171661443704663617510122898121606493483453596132770613280627003405243158340454101562500 -2102148367502050737243364154601429859358675465131516367894554165361199243404953312457782047242549230101376397723230474383054190778647111151069829583768180390034685535591942079113140887602422113030133283628354261007325519030852451978121384027464450579740301440365950143719492474703122853450660448842353761543807494003785581277983258036540651461631843813566020031588940708974309973863381127837747567508769349575099150337778545931410993835609085788454955462807412967603143272183576646933417588656630202659594973050044128810233243549549190334072856214781387235674611412130452929456134129595035818813421373403820612575213940245702472401380024893578181656526809359407087055699045746352809416967980110571607286287471201325397598202447683498313491501049154795716134227161694725315282833312950781253002656236292125229264748560889969499062940076168756313439971287700156089312791572510794472195172718964721771566593991562005250890477229749886411980241973651573061943054199218750000 -16960798197644246921608890106696836506848618171740394360999941426916129615497729432524816869153383074735468414027538670773200906160040367163325338115405606453234863548469005852678408416138218703608907403531529438357508621399623659972383657847650909180020350952941072741739741137560400367215064548598763145534750131317221536838355722782429088354501087630520628699762342849315908336006080541357396150017562012192095681908997550803762615474953069946137973100421756545126045753894918599441401192144652885207929456218921923531072892404896471391750771899878835325661294343678685084081548035487897732457357973542926085911357098974345343689379220229815929560930181722742544342181295650530826800391919350035637526404445962911693091290394320054422332045403845993875709894522130554331902944607408614150613826171371168452270467593299053085403007521476144425448758948021616104828157792887596508174146364599916373674567737258835516478899319361972608533051243284717202186584472656250 -109131038781546690681558259569347623397296039867759144834307088983685400600578357247352391087422483265274419562269591028194275537686512891257103117037756951006653986839284875359745920745738598945599549939966900643021271592704731773800058726812082097868896101380894997662147178051903870888877179346520240993413168913775504799629482524975759224911035328241967723943381837241259744836603628065711812112476661621756873243567419581426522805266578900779526538362916440586117025963872438749252310980101667957336816697701439081605432849243017207159592179704429505174225116646323536579208922098700702831951061996101920362897410393149829477258860663568021848280709768866918956213560163520891041379621351256770854689525045904632615555580096210867459165597709544962679652281338446155833599760556555887057630836606524609460004416627144034930083661368375809968978234814589778736959946091501850189281441608819834091785172178375887825220284799154768506923574022948741912841796875000 -475162298982307151603126195291890953665909546697841896303377727934332272534687615075089851844915925618326273586956169654211739587293195178890617809617666318953602306044091222505547536610967936508672325795849695308421459765889114723705954311826996012103201671927727477907046264303365804160421574366203636481647083136050766838390283675971833965928250003601210731778615383741250787649560572590464814047057989681073644145310846676672362443185773439018806521636143904677076251291189379906814905792043362453467331195024977213147347379051568178565431068202241652571905893768593974548700245268599979315803164706387414180536495487400363989206284836200675493454927080467824860809890268637233296648574135285051025308822818841070929220477195751317284405479101618313125730767863809023616555824679227208979212426571993954408656148772640462454798949521730646631132376879250158064984818625661667214842344840724294354502455777988453346216690675873906002379953861236572265625000000 2638772599888600100373427268818922569934061154555162007132438529450427989786964825065720731190375810728577524214174013886631171576765658815618761139007828685462062700108761289759829232321898225676914612986403184377727828966378124279663536497178975031713280109728287513078897114216081321489645136695157517346217906088740320325054472378857960758106927348399320524979631722059504018963513096981555895786016511871484751847892945703090664662130139273682115423359650687031984616634667163883039510848483916963813811718706313227938990060223935940453438353765747818026800646180410259610841657213929727247611884885136812341996110156520116418864675892264308063846308244178134055480390676401662295731072220300205740605188631985035793430506232247055002815452625959958411423125692994951098544613821400179178531800554374061402891376024996473986996100392537121507633621603502937735217697740459785757526074774170425669833974615109922594313740518146005342714488506317138671875000 155839904253619092482028994589318475605315576736483198312053917597720014783979583724980702112130694966609878369295516104675314460883401357782434569007159247311906332616907005372537216517567932743476796183854695798073446795587323661228954765772915748459964266404009146443225893838755837432982265000189209761865118531135999677438248116495318485240045162983160453411163295398238975544016709574559000914441690585712928333481650884384558126870575380546702937614077399218884986062349636371294892860191615484810964112267693863173593823387456293773013270778639787648509624447582660595526719348490615093510531773804930319075160493793967473269480268351479167225937072274186549828321693167935960235338596093016780492157312182754145050312773750003388891415609842209668211991401694081014872671803581414462615459271502888126124431814076984812643182273606914893509541830357313108005021487206887192410511552317461733207449433398825546295829447274172707693651318550109863281250 3804907753020026808108329377289443626403354492300444084272555985697425662312735736459012321320595245772163670773602759815055263822907169218983662520168461016980211758640844338611411836605183617147433729956757801228060930483789246148241242460267691612929782703376196779258904685747985039195531632735080902164474749954638296235057351461114817209055601344848640806939552368780187847413169534859140713090849620851384900065494741242582995603731507240638856150850516017406842468504517057492333433419147419607243701633458989613608580343331490051204200586954345937355057669719052099796832062567327439303415780630502718278644685368689475449865747188183232141188449176660674319948913524526512491433000134411040055545896919052216685873798111998792881804751736678626073959307097962448297907171009136174130461621232013067473280186180261885438637886787726034156692907944923537127985037946399611814432962039235229527993465645794093910048161433223867788910865783691406250000 67986218595346384367034615653412178305298925162498880273570528980271997843736333214106288785786286539810843073327806776018856031278105760885531938812187109302088546158685422123715180379444749742025503336615340030552373145970306045689483364095836126673716546673438144386141203512703250714979698054840066982882118619614242667881489748278861167731804506650255788583455359432227814378786141586186249861098115413216304395908537432276606890495021025904564657801093437651099058585627614472837853060567417577079631984944213593192507493358012190745237370584482537794411591479263742086020209845665994085509595490965578724718918053429944678837072119064514786944928657200388285113793854551492457943906190301710751962666918023945594086548672525298085777836656609847814232128642656944737273105843567268576570711300106709758423827747472705562430775207818546289567100584836578880356486257903192854964996547842794898020761096681194995960950677726941648870706558227539062500 941824125451888733026047303299005827887265962630330420317304267003166066342221061833207223296909105154190147310981186652493754175046914283029612335789442867101270418742859185607224420098802688936129346896692151672727954669499919374221394102726640518812649603422739742944660177482928485813020511224176615121289789643460118270469739231575402061303275158287678345050264927404887910298998312494036597591546511198824632882828691651106599731574242428724556499651915804871869984688482689513541306973429679203713012821132485122661771353531557780759212918894449835995299736900360914749556355885719467304487680713050860355723659234997606598368121237082024362654244481107990309345320569206796556433509262663179379020060091397481957774832303250546296496815677939970113911427783449466166235438205983351552253965794797855894346780054091508521554903753963226909502265546683228342259537848010021813196633545522899995552682200598837436444910053978674113750457763671875000 9972139508798022591846730386895514269079380656113078148179168795428772691327955720178689656479472750338289950345049402831861098920900604272126419341257885308751832138729270524054784611527075519655138577322454872467497813287423204380808218101673142079871925767001286415759113096030178967033213949414686821797138510652748816828835222319966029230771203441286463863797999504175707241256651543746400843922801792185058800576950776887341327801414052119454971861308300546204818195241203325308908605092194775414460283436051220550425183902496892731019181761004147712925146035780752943814978978010426690967751659142712454441928852715961933272784696567006859817023128538841956327291479501117706463126768428417560280078202942551714121634767026566345920521073006096489231550074522602936336055581854183633821810581471049881496079171524426042573400945933817448123563186831576848671975798643590537724853718458713907395260799297262432894228822988225147128105163574218750 71674932387998469118662318739577973768891330354623261349384116641808220527640493676324406584709065077369473599820347418699425738409666534940641052964942669274244430726427949649470792877790611949404281346669483664516042522520680499265301505499872184948148449444001988324560714117906124584959189177259143948241968299579667140309877401763679711744230269493070200907109842785299641996678715326508394367338596763496837152083193847984334088195442956826587888512076231316641954911683404086295367965264198239387630133695360081272763084191612467620587056113244265952179145942106201345626489492737508107851990012069655197099777955046649272233174314790075562072653566368194387127427916611525843294265781974077445357613879203104410665993752766180249597005447308031022437378639456523773562886640170401455723418808802277763520264344650704456321118560270733168425201775414067494155676032013510398270917290655666241844592989629347812297055497765541076660156250000000 121055684085969043536818821486431350912941650806293211357064839796735387486535197498207147300627149366084808774088827917399969619430430412812623702497428601275724469643259973857453391466609584575266568048979625902408706706582137783255342392272073070504403105830761552011951880669500654515124565529158870624652515023394178390619113656839133789365925623352070539441547268380903128017980097183090150238060603924531217405459315533490158291970805441291334890515609926793817132195358085354527802542640969800785865714969551832840689466630494668905919057101081502029287220719051422440037401812236029666516190292978673556821095453762740750040158049575787356148941300583683209178915920959973930254590744586455590799570609900272640683415815104526963740061543356892943854425100055595289789641482131099814841628316098914551818768632229364768794237309180608372952187873340673274665766334119081836586210345779485598322056105757837940473109483718872070312500000000 -5936704009606016376713177401598679976005432506856521679717929469049827849525104290214057459151893665732326755245744674203273916630353782204575499621442432462326395864228393089306649619894603139853663812917137782771785885882041055463231387784923617005936131131548768513862293604200770196935211563219120522833460530381177982634433497888149558204569189606415340865095619274100940411065604138926383454175075815510711022604801447690326818697430757794009308897699540248193626990920668432711150005493315308840715773600930774591922036104475332661339510789578981751915770005418630200006035227864344749889689308748847413602877023282523334136507934146773293740200421356439414016513598507963393491427682257490224404619016467621394120209474761054079068124964490563591765840324647038965224958638223149976234653490721059427759791752402084194405420531246046891740214005017870059233184654440894944090414783471903624120780129658214718801900744438171386718750000000 -113702035037213859564232462957057820432229852736469164894275508424237691889959498928613767310984068551413695088370647081204212071665281790762925418279803426815550148687323703657041993913587827558733059866489914159059713685798134775521890834598927658538801343493100624284013358138076841710701838204551827067355629392338220358603320968194400678093169394899451664469150553411949541818521683975862350286845779393046130043338344557296302359568542420801928174568648765444426922273908666408260048204563614543983736641275879168961863141538133930664372972872591802230626837438083857500165502427077192918185595488063235827495431788547725248583179762752427770985308897661348967029864528220338585097127113256211759585995962565568681628759692728287348974296694480901287073191692016612794108443815275880650293475755257276737100987033984865933647572484962578349129888215155819345247545898796937729302950388124902566296808847923216490016784518957138061523437500 -1304024131454325445282255207483228073550500016704203278843816329412749559197513337461921969773435775308688525671037059539274467090676360017780353021992668617890036505996197310561412636577557654825824391661468717896639660084642604206891321963330302151120136487413002807650741033418691868216959959322242094165069618247744482610679826920853469683441954486552603346897540593575846104603486763601301994076905211453833499296152011041365661206696867886858404833815973900131160375567808192576487154061676111429895112449628456940038532272106923338994777569546250900313408222388017965528032056424889000110442691177588256131598035630299112313678755246386436694994149572792539292845176692012793994449017056452555251253301439048364612390479036407862193625698234401039473644950769115423015867235475018953046329037608506145745154659396140128413958596355123208985582707525954352974929124687742120753900866799611856991503167080281855305656790733337402343750000 -11057492786123717141400184534176330165242520442871959505111856060739855595876426551350578173669195565550312810274795878645586301088758869393566398380858702402773101062481754498417681546806206225695425241464277202658239865217169095161690673500816223627354438450223944881721260271423985299107771117220607717576275745761262008618639209462441852696302720961978685334800466531445800303001245117201228980977866931184997753187693589944757007628802986810067704280270371592489183014002457503450785878557807993068744889141580090454528665370060567547642821342623801554555751796460963003059771459581690593565532250882840244462187561508817889233122012967941021373973118164020361187216326765954835909611856796344751785832711608465083976335096215641731997368824599346262239093881740952055218528927044307080858525489651419726542440811187899132394886312551812479959169526314903504430752898698881433211998817430659659832858920935905189253389835357666015625000 -78010802095120104135115402473113346917009883318776620710176318385644167109102972405192669047260014974859663888960192004106975276913534586280660625048650949445353949812530132218677236748359582794959988043855643077571937280841341680080528732406335708883449344699493738723478753503659658233090380332641146623265608055873761642164653678361078806155589893277362022710395344453699276860361403237066334606327895905551112513926927653364584649798581053376716213633823163519608596395352989496358555060405734320924510122471700384147300697009247567441972517675465383423651501589825111276403676598928918339356104969883704070380337997563110808917139529276963776501311205319293543571826724051360648754356078155850267199080893250893687087442001476245786865177811891573483410707687639061906414862211164206020297900745512975078174950924961985495227107305012797378584912100804028363929547281129972645971611220228753014183098457579035311937332153320312500000 -598821117872187784454256303250845174195117923112379848962242102683607237641800744469299307789869463538485933705469158374604884226081764117697468711531080572902304504921450658918495390266054375943990731583943390179965705068383893692133159564439436042373988307836709733001828202469394924018351641013864839212325995979308316746202703996505723212696128277289815584163055031725431864238557960274438622543655783145813318128597691108960364646704522144270291278984673462325986318372621666008618905123985041769615981558608881288382546227809811159424684990454464347555035656946419533067583152638750405979439920262932020508815655580592901740972118209755691756718624693951542517518940202081113091511827776674367509652155641696261611976076352334596570110974622545972528450589591461902666516769739753420162709309359379563988331424450091640676903966785454339937139686531087125092209639558678152239956162547571821841430050881172064691781997680664062500 -6994891510290131886569637288291132990345662856803727160491533761444384061691324579184079043753323399391662894844778995257781150377182803611994981703565928897986589840816748542581160771710677857900648438625945836794760390864546858360142145518691244812956655075354781364059800421806263434864294529937215766955423066547004753403088707681148703650280791787270317531972064444789652151383169248932443755170037623615448180223639035312697387775459279175476966472959766040461927726577598422407596058409393793536035687252067883519757081617498079683361000005945738826761005021375689539865650373766534427682471788367535862721849309355802432402117493942551649420067776787687838506763395313385439128210903748832138327530701983403131303715939125957946328268707730931903406995776724516275863866079910471558054547505873637612746668945601976955614594835691578455626430910014375432000664992967799724734792718092157848275292053585872054100036621093750000 -85424813957446066111951938269118876284828432967488419644783938020793236086243759044946854987505289780692943763104815628998651382955700801783549462581208936506803636212921186649647046681719906786583670569588957157445968524536439995987025466331714528641054823976834724706573161199244974415734254717943470013426005147809445767726161711376081153384025020799563483157876633243841557278231376126643892966028324784241963330130444622080929911052095191597668928944719655454937959284275695304725423661018385357886433481032400992303159184777940850746838840855606275118821697720043576947636333339784122584888145833919486248420985985526606958499232939976548147477800832326702854474522465912853387177909845428187575458909079020847550222128058199931524218495357735958892062505168412138377435038442810528303865005323362684133984082815823575900258274666436357905724341939110479491144640118254061016502855230303481448572711087763309478759765625000000 -786855738467116670777190140423893072729710185823258412144473737178254417063406633424604113498549462345394986211525955119238266159786064073025730927116206272752704387453554011240191388796248095859171899775672404713410729540422784387058948921610801468569703774730645974759078142589569379913138800746908752043794186445177468049487405825557866043949616400085759814162988817720615675840129576554576541355104248873868760873984717785037466208388364408924685111724806921660195721438084247580018115416543722702402733513538999092035539823914570862946714895394659542034141059422442801501255116477362922686165626493692540814866463239109846843869895419803553088967565014720185896927845833649009480815446401774051490513684834528667498555219729843144288105813074993107882129952732330875086538144517786379596482193851999147936764111880396556659036552707991584458074282126781783596474507766873883902189815153782603829313302412629127502441406250000 -957104820871937677172892023957799515999405200706571467519269634884771742427667294239290603300425531552720272021427173914381864101828659576673596956004288710171888204114223269812130270033616957826107286826675709751034944717140841953573672254576283872050319506957744963912454311120060949583443096244239208768293132492576546916622224084707669169324063052326999314953898402430587003608381256202406594358030094759503977539964674726073546836526594825003793186533956288283138969611506390325603343766989182424637122987912552492652378793285936259313807740072469417883641662904223281913036819619866244380285605333272025780122197914601671219240597370391874823522289787745631303298399724845337939477240433468508736968586599965091595946318881899291418372598821408321005515251658866189239174692721941456139757122378798962848481344016371463116649139019438470936636673349477987862728359472243412707070236988826650303963106125593185424804687500 94576492705026118314341255538556397410756958056020014753870489711050796227769851515204273193719686783726873795799730012352845425255295030235864249204107335948433998056836955482733827236445649104767946682751700203964644140156688661288781732722447057218748879659945642920837337159947555491398472935992586669053957555634387601370981162918831902041649600207675097344802012848716509370634934338927205453036888909252533896519370145474036887154036883278927646879708691258998538235050198636312246619381290936022673688883245919619435692644420856144738910192891580777462011638971261270996513201365511247676104445889442018598955072296797228121772409493167585135838923331135502697487793712480286166444761852824337470144660423370929324798726875061870303565638347217270357082216176088959868384835667735589350997797320445163154709579510464117550241360919648028925023015440035012905076337471862221034646367456844018306583166122436523437500000 2153895510701899610824173138202791432744497403774309108099396148685143322227623350569135639149147932736828453258708690981103964776448920851387126448870848821246215833100070594078654920417806870254130495107295406288013945243332850674719480464084445604600998549508595692428928582017769149096062959567498661914679335900554050200852524574476761413345073917170632889775368661101821827510920179409015827461785187736982812834947941272119227780532033160116931226371524690389262344610283458513742859378812703868212587292510581991274697744439297418365443166453967577257862342799699032856558527772471050797746108564386923421432358619545660711411241258047685151404475677203927596278431657708393402806795211296639651136602269605476313247413218270479116758575753166684138892209940956814620903783698185481327111544341674324325205259749629738715362747299204712065178172684878976329501497076319657154874764870555736706592142581939697265625000 25489240200882153041098330133104433348235190733920745291481219863269226223308751673308492107352645378830429695860115580274629094811199735817697106460309994949150425390581340949617879307759701549263563292602151183551703506806692009081300452167607317758711541784186719586768418491972730587372588383406943167765437339803510336130545441775944743979589747594739301529375048716251803623064126940391314984568037498621753290187911996644986234740103168925096930264867462027634980505210141278896029243608800139911124314852372070124110521219830215276954804161238568896631673761621253442987341312108747665294318991246870687970712219008617239010758857965246779316302096305002156382332649365710974914094840807665688517483824072086102438008455743433636496812650600842145052362334329118143471651826330520480035005621591384012502976249323396402540998582646265748113172972240963406550293633543889312842445349360787076875567436218261718750000 236551205135046633554815667253515789019798689018376283849851277679338201547150827954377306221128931009797232400086474062316505276692443342943975097722920052829098893345250900759913070393914478723562315701363875052608330027228597498689934287081493616757890482431568005075178253335226520341853446260634614832846835582873856086343681375080619383553252443487512765315843315924914783528531738666747013922004259625938095531487139789252551816942499358314387715655098098324142060287659047086802484008601181417470972227268988177503130345752997144042505427527883613552871181591736291145832698126048487081500375993009245544354840280640231644279561545468284168971593806120992061632845860837949263177645983703330350378434792535496464263988896900243135777993474635462758057965948056030511865945252093879085997196961753679356184206787185152951487130343897724028117695658388422200966572327130148928331365709709643851965665817260742187500 919121534135827044780421167928110611009756971665607850331710509376571403857975621779585933311496611037154165310212810560718495106894542135374259315917500721547838977425457873423234981830652073205470640548392850284076954282481549024856612979864620255445866412020737729417867160376962106012771719699493618304607775649777733558448569540466105425536097341780090814112000298166153337803947420941531820898267954191179994529404846457474044413132214318493682136303355657836761813044030794210191003353856545678631330055473645745090492683974630827122304837211297804516650888233457699333154213998476794008668603986808135057960174906489665908229706517492452559710304698834280329994070649666801892700954501605561944825044731072038543097909770729839939343108963910364790918478644647381511038670084980331479444687965010869127417528928121303724271293587658094775797095841477824418075696574770283575617213500663638114929199218750000000 1188602500896618916989590299969822115071439115242137442648797591817162316824252696194705791836246489919144079262589227317073743520848480448736501869110694700683497484000079292511425398252466963958305403438079977825066083080129431785757614406207562763227426219212790538891214219806047649222060055001379245480651662682966278593406944910331646073910726730921311229772483267886211633069653994806455235522337059835264200005121132788953500746059522068206669713378318595875513950836985052107932663636268037646521965687052328874849950433204825036732021861726393424438347266756797038470990674321948424394389037624589543358717395031608057457537331287658577444416138071467851409907562047773804305771227918716766110626368930830647508281906975117909926418173831159672596862520271039374192361980028932049223032364682993267735893428685371525522865606733275926539313378049856406633863828425923259146657073870301246643066406250000000 -137608839097461697755974405559542289289887242028417691133435224717237617668539350129814748077661713242666466938969868707814112371248322053914418798073468752606558271172037985777152255254716182625459274077708273510225476902893212280021837038066406239583350906513881844887616464213718238904479624169391363968514497927849626733564764686663091626509552798329931836281602285322861537990195133128503662925156565609865186058181169121149308509129058921812353971005033684745593969838215303381690265017378545156185741568855435754184776084036655561877976834089957134700883492052125029400994206043891696297529629386866748269586406846934019849642821627633258146242519709466691344182567847461755170566505349089332421945906818400825851082942669754258734159116033631938165033488993331199729594576284428935607218142538781772103626896874900688305674656563943407645950072890390574424776190531893860224954551085829734802246093750000000 -249255262206909286491308410560250831264886246935153241810602683075095463750992895777769020487263574257942130884492878468605235262755146174842903111407271349566243724678761000931189555828442490535337805779134396598904007874320338945784858347633638557522659616375759281418879647699555012597069124094604862266169838056612130491882510020205835840713373973238841483337384517921238311829320782032832937385245104448068532440989811384417664788910350626520196584882119405450448282611344111028709220672555442774787248079019182297510762655119116961840913443344507606534085662443823609428750955625947201252197651331089692208846352461841939321984578933759499925877964721258411770652255784214064147496855892409941169358638131636351279587937632471885152293674021779349768782773436981393840565051118842334901688326435501671499451972428446565434765854619850375623276744431122304073106341754106907160348782781511545181274414062500 -11400163932700806416470859714441624809696111751712894394280850273344632729939498833828006702578446529543940830434466979521426289964563078129478076504758350180775390896611655223535552494253986749174622622810532296943093602996875228664779390263870425767976647412390020440803740036760416705223333253450201318151064150784888113288907890901342053665570343040948329993503297454684198559420177098753835175429635637252270364114510776579922851981598411452365023339670507513305628035534195747583317814752978203580018614676957249497657833414096460206384484541769252385005127957909433867258327153030789152850447823021064104850052796625410258104581022211052558431270349363699845256151289700934268028773198525798773362101990921453348353382733542359558960166006361527656279737815487011464475271149615337710147653699751518840140876097748714499198916176646125669028402858344132137511164892806903026212239637970924377441406250000 164011602723338718319127971658939335049172645583941877751926076813121491353889098621389986989876942736798538082242060872421021671620858401702710423250372341535599149356706585231894191195054467121177502739111732124392882910481278395017432124036414848856018363552629307611160271036960549351926174968526822352689184847385332269567392218509155816279766902003818356620624033260099482525587409503422491182526971312428333187208789819757260370661628720812809452713412682594162781989306766689352999929130128829245897249726099263386854007614895068265757250748042636306115510583036057352830585965212072426579054241534877607126578382225827620422188761328223206241638950383901119096419078967330082577214005755888696687673628283236597094170545341714958893018594439480469431111266208125655997960935320714578505003646856070901276086808022567087629734252344544953655630012105077282676124372784443039563484489917755126953125000 -1135270732480681224490245909039090091458248898234435230851530831729574241846751916300729930928349984774037683545022951794092843350901612564422796600223024886323507091062524868366461692843213243420549323903933642909748944841223514509723700932300900499752329701931228585656049381659514602046332616076666296409104683205695650910221815978581375256020527925093433144564271571869334588220608675567402945442678599254992940550054693871665638502821543941796247705998466852744379362109684068722199497543482196011831083522827520016585168340314341606421804058399505676645870741859086796163560801479656173367505561117811624811268767529745878859774708198485791006698623142749035442077213644466383685993571294127500401902655902295079160804368082530106152606932490829520369964804472732950809421682631787306366701711472606520607378216553431750263364075704585325978910095191126445463014604797535866964608430862426757812500000 22340518406378296849980111003991696561256278854250140957916062860738427044742023323214455446705920109194970906593685592396490018417890900825981246273903574448033143504983817817167739114875700264112207164089397817495723795145587698284649148778078679724966362870063976577241311672858508257086604503851287122638814026130863890184271661805543879081120887445581117407829929270726775133941689492837820300668915833329494351993484354254934090557925184725888550029622951174932037076277810157543826452414878315022727045824247940849733892648372624346439969689014434136472487028179465562020939712639324966028711348304109419681595423045496245406017083416996205816424025124716020930301810555212866508152259520902330987496970151017162153260812713771825490392556657971513271637909662218777929631780473471668151278794876548522597342624913339842740727231942050949558613914641658996368400735832437931094318628311157226562500 -380885031702637695153568400901191682571547825373007173469692869402691376059044610608326231165740705007731045664096689780914144987273602704924187701002493146999054686961713434469693765136962000037775658287221767178124261521443829023730848313957008972017031747018033641798132719694763441505500323792249584454605977954895882139325572469050487381006480392061694463737100442822623114431763182341543132297573892608587217771340195687182785472332310147399389732524392317785729448707082871169894217489950711485221435500760816905754948762301759369581274093481800985374093103942550471277772232395866011151405798823009456095261497259168581448273235354489799221241566425471330257096038263844328068080320133207017328926127069698966284862194671527544231770738842086894072236174776777510936526091800332053374199887750428439024865517406406020387890803775885328179588116957092827630226850033068330958485603332519531250000 2553630678719050596093040984817371381632121968861548508217908911401283310211223902138501275545110258716229442275910682780961208309086095757319258071695343197914472357722069901544945970194832780204084964158477882161988339713274429079609339136977323655545040192452948614734072271652328619501934621649256664750012311864611614696989701272515749607290248930250190857614629578248553965110727248044640771806528980529095552628728880349880865981137625212840180769361286897297703904030444788384136816622699263146365121544035499708920108029825250892061825730086560574959047439545374333226267473223986542430646443409630628596189663892886157210921776307935119913521148828644034310622568260806819823820281838281532589750874642827242575738748586861237681285399390192771243349915850417903323199845166586536538934901622569093938889907167887100419191889533469542156350552859767066848917238530702888965606689453125000000 -68240993380559138165230536701357745097376628757476517642688188659105401685650728434021025848949334918586178644255765870777212719270397034479307824081339216319366743386893476110366246507148872150326192905326222988836406118291999402067382348905215829729621666887715426202072223493677660516043515531853517370529205608739697214273268804870474989026167101215792957111478907102506367310863240523005691571439205769420324788989527631517481192597597614620460514245682263273881600107794401773915403573902433929877531667615744363956301697529118719574623849266378321507771888822650881732926711537326363594956778719544834912594144821040621941109935881530833042436025975127809703049185474298293973142461397875960865026408909699869711905442679008519831442073866581030528206939094567317414511770135960309066601956916759448568921550544831314468075331831820866339379975202758532581981398834614083170890808105468750000 622800239722976308355120576689423695708739307622034819765986557811059749356840098640213621038170227651909511342013768091992835302370071573306021482415551175867157756448125436422241424954514417280787015362963104860902969496132784843721144796673406669194891136433631793480524119070819728052183173703980868959790879257917808516084030683548430654320128602721848966164519791361129133552778320018794027880616341398477307710824716728222276797418200402544016241621719206478773254355720013363041501451237864878597648023613910618502400681032681203749673223513332790892049962122240523601219837047515525640022430598178607402429371512269726675668861119163296989413478897130739604910101230213829544272798330525917786379507703113769288537050460417568084143258718053252943397840081659948301251515654582304482211427372071733349064827582903231658866301364969096499776552832566833828309427190106362104415893554687500 -9712999623968326017248913561529019342287975964740853093939424232643058044213134156772007385131165603866762505129980304150198016146392168084860938625580113704543750167813799220800711369150158270764080344436959488719188297367793623890215527264005284911947315306156818675123176904145742559171323588604565310373498022977375970283654929968284085307979766790326428347258440614007838712225226014715820207625333864468871678328752249093322863884567177874105192590358838718093155683918356525106128716154354768703673323523504547126486965715353830355394822792119378608268661593858677688434355051628896430523495722712400319943855497263835314670465721882302464297238183459436980687487457729537860667980768166777238165607686888829245511458502817120704812083063730815350495253300112231319810079854713204120060373213039901834533642916490410055121070020512243234844188682908239229618629906326532363891601562500000 126332049189482049380317570762261993858031275205443553879653103090296454830762117198915257587883540623817723029157827182620717830671660396498005241981643683698221704215300008897269216230983682356519873699707225140875840263390390870716909591836957890388738841498297166722772318564668121937055834319155143359873870568164963393685310363414229249448104686222800185243786044470802818624564950065779090363837455685524831109879218838851322217443175335174471966569148923629442457564959157379801868572336120060025882483275713109838502484034998976434712192344776420029796487638637358771929558939412658533904955741088385542441382001802337534184717046475234416717075791397841601433658193150264311097836918696157978473321929056681213655630753672905538153921739713761347229845464751013607130929174725145622541767824160677087395893813829316263366348335213811511566588119404030976511421613395214080810546875000 -1556505666901538774563019023784468346462577544887968490716217255876998479929828033976216264232943345433604039595786840175206368404265877706972204447425220707807259847169886047039518023507604735204975799870139209061067315802829187082770663997228940206862763106181070888450030868685949122639272502409513233981716463986784037330644415981093103402221742290007942507897030021376624720516268601242562859006970210816067971568157026064884371785388532069122358699448630683320543881186296970084329653105459718381664283266612891565500216328362661625718199788157637329940099326222124466613858561653843562611790469249823344377333703944305305776958712523924239506025117629436035068714666867866590644865296099432198810842596583176094260627369524242645422767021592744042540478405048820275022580279901932368926181101598360193531679916893062167896404201475085460641342716137103252549422904849052429199218750000 20078062419266589493580746370448229888867584133689105529373522596882654850232203417118161227138143758321679835239446531252728529265774129017491336649788875765735440895794132562133499654517171561304410591408188512244022877592348069387941275210456927834046524085357624781952624196956326385978105422801436083689632859278947851644368496416009478144091361192887948238667751642859174914890375944264681644878552918320327253450551644114677620581844603808607370614645828605674462508550207139099906230423110968751965563985117319368464033410183803598339486678897998793244288608591891424982152960703381120155290400352574104939225028249527306626851756062213731168760556140297308022286707817770840912328897224018394671195238407648461879883028872440872135533999146959575241014158822756381235096375865358151970587907479352868472731567705373700892206190281878881460225771959926532872486859560012817382812500 -251393053440471236604643357580845607264695201805416136962585713439159377821132773447705023636304126616212857797096783351575536927945164079203877913753731875419535304407353287446490251191248902531469971738538862542716120937871113776086241938722151890507878015268193794648974897786147247430214107890638644852325543426171817833303272231829988963779078200315436760009919308223255100969954645578874763344680280580669600390902637074057720422288065073089713057099035776216650458576310482884986421089232410022870113584326852798436783110367624478628540550013101593196631815854205300737204198936312384137387210365220578257134452052779736355757289795995569677029385562914285345621755405933686233751381300016971704053472395397510913749720319814446393381417950349687948959552068585206199222612624206241350456656165571876503582042026680878594184688777689665184489342664164723828434944152832031250000000 3057796331012700361977348240465715525728268728133736811558432521111336827645642344398793008944099860379026576799070402765964821984431373447979927622155170037674409006674764646805002657837640552668307804790728022761321881960092340599883802910968232365659688444101843103984231740991028417124901170345217155131263154630194508522259244592991185841927577483932813385665219482704841840780369300377022535073788308633853642078498054779601170905349529954205830847174051052190883735020460653688563253688572608974684303167133373733082707738758297169856124622311653515510926080869481318143574847573013138706580521693249307674070400236360925129710009424897185313789600309726489316616303224023987830256563079589071730671541571052006391548018928285223722638162792090171752511715310442974995833480840227259443645040902455150155935478909669342816755259039512848673325606796424835920333862304687500000000 -38097549747141739427892901066635341411909868146026946592985544859322770475843571431856497039960144819584386302607194451543456102243706312107209168991289596526033304986596554689794437602096232765775322706117034735502332401203415921507023945816181067369105589255451558289713512669928969295729089598930342539384484130428793059056106329025089526901344621879630780489178469490121480309597803738020179490675460391681279099124853750150583043008129894835914804158089089890347395120142728485941411054868498563765592576693517263002138021516689032605443428522316371643227211493354158742705610806260495783681636739086745729019253021605762547629434711115668905039221005484695231824822591598505859470515791453235117773707653945958471237962860201411486235254291049063763273387423630746234915275836742075897360802366374361771181755254206874926633212422380503348051661305362358689308166503906250000000 475786725970867872785994487193705301967265378742152111891875686034037948364084604583207339021483654719561696532993702610397214350783256867439442413297011446047311266487382152397302324633915298415743577530364885414151546231127436688665936585575442077882335290562679304590624173013875981316410017545149612180242686556177104364249328406202852263342527096195203105761363764288583871389929582806739825607847196324018394803146096549950769955297675619129155420087413297862476378654730156650345363365294090798973915210773106131562281887053213626162423527572637000234261530174420824148690740969477448657216616405570130107466817037142391441206592653197775968232943306098821818740453615853999111602427310546535681224399220164295664530490534106998995025733705835367096061447537301675771157851459151609441230339189377371218081073156466984301794868658500893554563759835218661464750766754150390625 -5828018946115380168000133455937098477576575551377514995779815342320726063118922414585825686728270652827602694543679386405894269734093132593844733848258002441144365152521749577665045899695784905358086676249396035160222357849981219401911776741540402594120477801804595720962837984933705186327824828441464089525326086144277808789417506594408032291470307669958424890677287368408289627168818529670252899094253343167344263417914039606160851464936863426749796640523656951967058257062261751346956552132146022184877518384503537589108164313852198622946574012925615799054490305172372701090077602468427949198421733178251769102382374685687015298497327981743678592695138664176851182853292426536301554017807018003789343383725271871019886647065059998952117855403826394548328511946493499617221871149466717981424329806104993790972157535595990163533108103979113456816207872179802507162094116210937500 73975610349767116455999013581547803254528826592304567596566711448626452289808939954705100119738321277044542315282594661994447052262614074474462138041386610044261604515191458208803216767253790814605164069055062619164189061466164914778179193182717337629810847436080595211067855430449485425889570616830664721180457973060245469372812773946116453892947112418320151304445606358694018948204908670276757645939826094552040295993114980119090302826488752776327842999425464965049535271270897571980752675514018753814157126468384433134020272943807470339786577867189740458897260006745654930664882918845489888067280814830654615504839570570069267851123513627243432454168083527300541178993128940998630318451845344867421877660045083450521780487918350796897584276534978835366822451329289042728252751376457498287998358954794926207020570676224205808855122505282575495755281735910102725028991699218750 -901165016223858363507259760763241451087519994203989611833395982259175650382584058374224600560578884382910144561792082666812800864286582272629903017709745833487751103073504889052508330077827580825462555661922589342039964870094016471224736889683592138027314482019423216714671512522052509502342905336305001867044757849559976006670720513077874834471894442195984256175818986581124161999276101543845150998578575655902736780386549850427323148920009738230773427015757827968030102728738599537959481985101086525482109172276631083956163762132663881794288719032822063945687538392908501805168353361330383948828516504086134436906401713303661711229305917638365550486361160362332070235149030746328768716351265978443866979306763421502870356733408132088108922581980146657584321010590599361451165374931188038096287162850065520060910679041651083273222096192700547589993220753967761993408203125000 11009347113620503279493244131007275845764181794893040363625268607686449552234794824693226516147524699214806487513537388486372305681579076509953294933374353185481798185026450592583084268253135830661925577460459371080483335908151117025556677217004071070525870370058007551918878725560895097148846918798957101061524699776977467710821428227074917819531541842791977338246638495074381993967726338858724343639113289733315387811061809966635147939166395848647127213842962350034295219910120729152063969350126545507546441497277321199086864128108485530618257160254538818724610737455367625912357147105899391522264932790041343416622333726294843330970045284753200293637611974130504272575034011183339445061678077416092581120862801313690963382601878347383244773415671386130004149962288130412022344108814328384154558192832875438219240067765044399950859731196484148085801280103623867034912109375 -128471224313184533225931764201211027470286448205999428688494944374922394459039464015396366895099055736348570215465094077641494983983568783728462036969883471567028077003099874520118777199349253429952795562149845332961544280464914763330144148080926382165583057712867886231834598039230432354174132065789673275332117193964731435405580846390999701096089278426793115217622613713012298218634894235449982998936415359772383463099484691069975172779808441451902205419682319384062691182850302305966280997848582948568161831066716920685617906599331469679034462287804469882413719223366052777922598579048334234705370390366956760718143664840634796435163169445149541331632545621947453495539966880284602416729240194431252468429897322048094266359920750733550800608968795372745224924101990354979077640647780783221649880270863133379883931665382908648889020986061382245679851621389389038085937500 1443584615845992718166143405415035677061875739352102170512986713090924000160218693532315343673869617814231939300804910200506300032372093534491599077226137594779027558731458384209955952017506675691620209796827223897745594742712786284532416859000670411945819804410021091851700468344137189652559122796467178845257174176020250339451861677141184318538304427543574202335685783923578726379783935657021372751302699268573720737148792343338986131334003877537574939154656870363458831906026670362011652109648676750300844987939237153042553186020164183594665002681101292018576148223097462276397935731852885997207673406626125579974707508241247224967548528239303261312217297843307436744413654014373629704087922050788953395975860958419189230278651719074921416750005057317132811691625944011178640653496899016064688955984948516388292099796829270896836305837496183812618255615234375000000000 -15105897226537426271770471016537894592892997857415152605893504283829272434232195527395019795877678448931217863617169753551272610148906816581199649822944865029329725523940512220465745656655606182181931185511359832271568594813291930102650403747146056282683105873258369113371210221914492094331762204727232310866549253597628294499411998908399975830209615893072937723560692874941464163917276199132222518452370645103162664206980016744005523605273740846982851244087255716309622475475358112724391994000674392978843598357862768649604047217418799266504818084614941430345061024240434453408748964670904008219057786641534839449433750434556589321459478211993819770221759378055694082320887127066572310231515915436912928243615920861486575316603194537711587325230918837044652991097893608705052608568071206179300304552279297855297574279359563379637743096850499568972736597061157226562500 145690082249289206487743320288993838023344901353518407799998666604117893940836441843197353506814360506273392524405103278344125585154144994560698119254488804380869405299499781029727212872850348210933990116593222925648031204136733044605642475177091961984821210847450909196418570231262995278686181614391566358047569921761839651938367404654566903367506552330693955777571034403373355627352292099658734088353098794695540356946396136484791111964261588425571748054226808535126890047494733418526804195391615672945413667884141703831844660420119491844529520773273046555172926879461984093547312793280344458337927242585318716016694738425971286814621932719733964512680096840062124857582323348236944638970214959152484878875832368646320153030006223708712006661529115654697026552964283842970959689437141385301622797207674424892416646555649601020576699994535374571569263935089111328125 -1205316340914781565070180022840568542619903666861518938214489356146702888034482291902166090098105063226693391073664840039012898583511047199992453294004165188216170081164602227665598312927873761158110055519219879959842758697153573996871263982000789646486151868721074981538727884667271828890900092771712633712312835826568014925048230619133624152627295366368638135869628897830461421163401672300331009735911097343552710239120139800015766008807832095599481731823293723352912348571929036104780439414758005353985914258082650907421706876343884064153084735608334137364358981418856807882395431255211397498508486043886216156385801396314256563381434300979805014343171135055794494118840736340323323300774972586171571700071023682082072005079933071369728881066800014127718306529126445473043187661397455235290254314578939844897199117957665992495464024614193476736545562744140625000 7464735759005782634755033932477512417803699271442154754097089724643570171888488428973865916462448528528055894927639544769857626505219618062272606542591463627164935086285877317639518886826115576330857965454601327555157666234144045891175503884190758854183978841235913202264668293001183159820830391498295650025901548946918356406424960770064250022074773548142890039730934103403886778952117061334691682373375562554820242707458565629899806775883385283184687478023473955618161820285949335720953515344967341784007817831661210577888288570633781560724661866347462103962779031979609921912536873902233916449970511679977272143020695804361356395474175410976142051729559392457058105770661687074445160954253552900459728162233925088821910183608081383073596770261092606262385300597242574565776438277471848102847330384640121141880603406653163500727998780348571017384529113769531250 -4515052683458553824418030501268719438035880145420963522448867599113490020426280197598860903077491507264814679269409035649123623044703134063700022767675435568035241410762086261151721806727590900827112857278925454068714667328091982730759742314962346309502847547435219974903635713770906784929515643487342252382140335159952422661069993419495345913867490678350856537497173060941720011247150085045531581204141913834232040905419261203624387652393307179363554139392986489864537311353821695596962872187993555245357677471456802701850662242524994903138169184663405239439851024296396861191195904314201557624720519854958125662550785962235608155974315083798911659131729595159589425849379263032819331432796514479166713918320506171549886868812113684938363620508769754278157396410133788447308731330764175030193047301785933823486962352539153542352323711384087800979614257812500 -853776694103976960097253379923523242703716864630944535670706946826643062952159275307555435498178784258482397982897732493846056649069614901968446937582515355494826224142206895224114153137777623297988770021865086363434990380625664628739911516044281662404973081641680247123042512058627830551828211803492598834369751591912430991572387086661548745691816671703650759935193545793296390384477752122678708502079266485614640221909282368292181976079389648026517307023026062742183110200552939070168104331867110239304560223461641800082160607583796379519752075293043232713764342426231174415005188595041085335030211480352603852721226024149767999356303162078859070630100366663257298215123475953185229766667672289174637552381477096475133849225967283714734229361083007125158826642371414022891378946882755060270704745433284594672665207722161984094100262154825031757354736328125 18958063843219735945860221186813987603580490704320375013840375431713405386253795748971402968634011921847391857043128478066182829845108528869441407296427348189154280663012658203653656242271440062509442132332512825727650561085729357990442692322813474588082286445278629267354124331419166600344063468195469566471637968930645129390907558085955546513942811650036421787181556089916659151631006213890360804946610115187253461925148191262536897725602556339495029573242092522924898041943394302983849704310134536512954246809634322217972784800307655807941863922801160731319786391492304346441278120904688186500185168637347275788621384391071410230162312543791084423758523402144113116718466720482643345539985799566733156645807018975865918149442027454665230563608894378294363608569518288922779396988478691789345505492242333609766158364351440468453802168369293212890625000000 -296051423151799289778228946788337122081733454399214673811035598581056426357058781383127567764088084796425261308846269079709906611957314297226777446492242485766637790436032546558510020475758612726834199612501808260005776661146893929025065843017725537346351404613508922806323203331809314736651882857031396017044647096521035990818654621232392445674696413206196716050335292024481142205531082365612574786525012149557867492360492674197953180240853155988056728039160923742331745174450074255549840926450054787378603463358239279480123214979470751858382641713186751391790406247591495427288164232017913328449223601745385300654171887037265638616625110536115080019391751108623294850623879555020242738323584771142166270666284266839154133895800706975506603026383866156828789595408872160224317945740382179693437528278600519033442184380078288086224347352981567382812500000 3917741371392926005214459379966691538697013884670690751098665991318816633095367418498203142586238292279194843991961202073467147336606560077947345766244720821092480874458421767711070450167584663875487178696694899135525718836035705996312624466230558564639647748236880181733225136725329100189931409120594632622632876356328005274458349145406295239729810652869616327906255788521410586739832048850675967086653739776742244447675931705625645833349570228862614793584156132741112411602659495632641358906036813067810545751653767620609341656998399218231953677757957193196063672071153229553728467339625704205505995282781680361003915640506898378009253100402781731264866440632894741133636152229959213975973325403140786133838451970599107145887935468528703202682987023253501409879467974281060170309297605389380091857405206089148830272961276932619512081146240234375000000 -46059256527747988356858026613257570685951322261681660549526009410061067852974420963761887878302158740132369517039423066226793897902920053905554096344878684150314740772769027141414795287473884881731970873396132428783152844532363884303219079997736658633412239899243877748824402971929230646132667103752218436166151325725109473959550117381451524356832374203764296344041748661644141199447021746721767789104404696441310475041179329787091064380300360513867778748558212381806387675418742132034519696990705831920241759765010034640407525151334645101479399877028857521404081707102027057625756475011850100069885791234040651348993018125776366787337709473411841520008710043319391113537514414906216867948459860820112677872542409938230878697402317642832982257853898393651604047581206170876287731158601969094212507593233670651240718729724221702781505882740020751953125 489447905421691019448689216570595585002999996880301643104295477778357571327236750078294561360172489988986404610462021708264256442159704943843891369106378973802648743947298768898919478310237248266516487404994672436822279427719569290888205225735079296654315661110660947305581355329042988476582441543904096202944469380884996705565337900413085385859397873585590670777882746913524735102582900287306785078529349913295557598997642214336502319019894598300191863437195582999462063953534540120040756566019334242597740516940440438288071860139092183333476039835405086058933653258679257456109305023182046485852265843084528489164612866225675373282669308722236334125977093517639547145374533481034678453869400409365098987318693725494049453403304423252678515049853193037642891996345543118930032315481505722841014304514979226662374500733676541130989789962768554687500 -4675914962873714557076218045351245655656218700877824295094584766372021483532454462170091690844006799529351022124347401419981803420531474536375791372722618557155171797754435622295435021225086351107638413739116479337697713431309239610330122873739560063017516587475028322833084281134262595126123624828910637094956002493938858991516638054781578591538439263913781751462965883911414878171251261090517048156400667576744807565431101730200812481502174134896025611058025058949974933481826403015083289149665946368607303706145837920650488984981103296002326446556019602165383317826162847221757630346832637282466827723157424789870549439313748971194709848762845812395559280635880493029028576364942714509492700915344475214614609282355073948612226381357771037198225850448609906016273751135540737837857836050133425279828501205936497342463553650304675102233886718750 39172517668970896682250413787323984117457389532144338949826137504142537227168699912020780768283586134720950605540426664647251791475526139305324931487641620476966699163616429766903278119060374425705486659209649324198267955525432180329263108145012258758650171996350724872235302817567289949716192968212871025887252140302918440780793050601930199963109523834361698655383766807835049933745863122699247380788301661962766596315391351821378781027292646050414899156766994937633332263891820060318361682726463149275287689878273933238365391410498098936310671175837961480925927259124594605837369775829825325538357703532156672268950978556638779663877669006384975090132385314358944552768240274666276167954375458395820656540765506248039423420843871759851073175207663733445121703547193461774707680054524052194484264022809882899167632785975001752376556396484375000 -265309488006329833543694320426476038144017860359791394708206170028877218795669023782896307773760671113717701600591338965063200051348797940203521160936022941853851512449820777437823157347532170222345111392034162497682171124358216671403715236831667314064095231791507482310926587716112395238662665214543954274599913934382053609476727132198455256245185034418848759050898077735190495800316977839308962648242928842571591888522114162793528590662369420391752124060064959746701360049306958933538250617225774482461635787268891670474033829238582049839161456586321583122587672202066844366635970896444679574503937532346235772923613541358774812040213919462833524735116702643518459969089785062735338102647027126860625920353639712007860547506369316407075221973950099549235636170264621260288078009646841637830884903857635304103013140775146894156932830810546875 1003214676946654438198480599889190129639423452912148979502929081867160599450179666665680857097026425202778057463543311774805543163260922981753644822155448728264357302727005877257029476629794121821835620163288332229945037641319865391649757287804796347873987561908822365284116059516043463910583360411609564252112145019880123861532220622591967900623087922317419691979875816843509578745323224669467707350999835413173952747775219003020644136907927512080555214153416970196412909548528459659704253991618728681475671303717141957708287048665899920570087575904938720852414971305251463470323259040778317420050041966059885543971212995710907704375804736499292754892586969762842488628418910670271273688269971529332074112590736703064302943742308718336144997568227824017540260373249744398249240790847011090608975527466162347423050960060209035873413085937500 8506750919721234911174171649903349909223166818954264117304501873927521224305423145716454336283570275476946719038015067978405130130931124910397557053540494540630537847612580662469732293401380290819579632190450818300935699230825077989951864711017324647058038966849552111101116162049993169198189550616661739006252678673308323830618825916960995218977975673066100476126040366520607149367093240835744915577317001472870958214939376421822803245971072411835684674647640465586227012833808265129554885292803525264327471865107687035006530618210787678389416028737492711394731448716145051185745537538681381035538405426903250183895696100080360608966382944694798281149133027442603001912446903642264773375480893971822025361220772354339939554303823458094723960545533156087755449548618518452449922257820283280453643737217817033524625003337860107421875000000 -268015985721716535711801383082083529852491349087808375395749675994928760700249521298859222851507057601315058446185642188388448983441867170371321176147809801093010198891511606108012531815083944522515611381681314919994474104396764572309605459410969561183522159563110894543150495871229292623659000367098359725751031072986866932383084795488013923367867019216827833479152037597326525750485033419150111957524752058402218987653216022862693077006302362844910557516380682983127736188918998054635632383008344369435325391442638597793750881958235400169375106086625504467732537635541405271324876010512220886503358342099836157924543139392085155873789230187031992559625269343981563674980147310177465930921065562573435805614461439342298031388449038808948708685685269679961940209579752611662643649543277052577690960921685814355441834777593612670898437500 4252008626772673403209161458114287737616878763749534431013229847204730941071126556171796606057259687240215476514902816405928958097382132658174604777147925757925641334325422746135311999501747297438163957316773068565654763034732948167099973349532433173093946283753655733007551716626773392449232708084660052190014785887144212298899303808998366017548396168347185534396137421688064562863988610991492702523540286953299982212179531716785183142104788088489750567967376817704710825121503123553092871667704625773312589286204781359761510617623262713516181054587486941054189792793688675423548812427568288913943209489124502388630645327881360986098723940164623151580391294261432912410779395642876581653941712807572513047660044973737906462859027045683496901678735420654435143249971751242356610460384940537010255157124305469551472924649715423583984375 -53581484815832682425057659001239637880354641526296660337810483766704701208957223090048095157532831886661625947512725322119749350197940656689153904891051021523292597857795013727106736610157845254570266322508414716675225970327940145014256778118427922562491463117106360853160232283433776494657888229521329454501948880862301284810572997342634801731334464469334078889939586213544550170108472274957566522927321509985816198444710849785284717699498524341433143427982993373331990872841388624903305710648845197116145681357464633900611888330478133142168288778737500496559464263727716395599664972370909328529407603122184576225991475895173379984844110661395296233139471753146327005976936248221137008364458362296254057281762432946917307169852168557960710366944471701411513387201589456938273913127874473368017493868364908848889172077178955078125000 585440884394950820721458006498074990707655981998763717340226182916540368818067252167711960101941562162782860608766948106114861938624378151079902528152948724421800909872554254029017159383692347239074301824168234845081211821024700141496136379321055635476383122768773083058660646543473402988641899006671403360309801459511983175273610843549932503548642518040081368133630057485551127910089741201343122775129894199909034862348464336809625980649699144559733723363539561694980035120556003822907372143817193171060017654331087277974343997554167962973774703011459647370919302392364258541506032243209268395982718004086381068960062365343857867242757142136832463250673198502881803376607234927029818586772651634017556158937225494872686078549924974899837012029720463108242447557898684564945333245061944533668696344363979733316227793693542480468750 -5680467569381942609447088437836303399285265182995180252795673972635003815902305780739909934119472465908161878417002057543473879034315381692855043650963773163627068996046051147526320488910267668917237943218720708816103317732860143708659604470321390335896908175834608669947161856679613658655137373852792232215802500785850519298820151170160016819406800685269415186606424175642949106131696813321561399232782387455827929782531734645781568451998438314693396668261165182421917486799355784247117896721283595769011968377548846435091087685806925597461673434768245630378913137009023104031644380697746743498389428719903784607067875282917584339678648070730901727876130971435228643519022569584309248315443247306743610408038997543412242050108300374123310983844703699690047893354465342264962922704007227542311042611800075974315404891967773437500 48717922426792250298849634189303862367194601856824890854151026797327507832572969395562522556652622827857572495712727183105596112661421085181917164710183745274422890996452286513544233801940820238907258451414809532549777162941280292454229662491098598738679325367489561984318272268258752088973283910494709967806911331936171245885898122698384528214938775059283663492001944204519364286472064374719366571483780340394866323773198293093818104817907810148896822289783595313487699962016481412923246791645561598375794025304625038072322595080960298027852610650678710183316121551357151254544718351975646174067216608103405090761903979909901637488300193599913693334650074569568346072971325792984724602168375387342254826040350748154882451735981975369550268101052039933991144833351089458233269431438488585028867561277365894056856632232666015625 -355157565469383839181436337091145486594451037323610886391130955320963630435269189877994237007274807756671581192820746521957866279361042883827074048436121744245524092689901455636799177995915549992970821960560318100045209246473625815187338250323386968429005501669629856418313851798850901704043647045049197392797206206921330870596757000553881518703119398332478599459387881840242306551331233202413074174902687825624807704695402355616709899455053904874879834875903448917479155298204775576630803019901412832548155977151788689382164921239705048583175452677318152201151737359616077040402471778326749227873997015216500153517941626197103867039635813954374325630271121975672918531704680755642353219525914135048200896467333847966053077701146426400898124254702372922059072485891016443071508540407776877145806793123483657836914062500000000 1911127592129593463753742596177626324425839619141108646821509720890430129156669520750940620848315487255602174657441466714634418035058735576051583258646428324905056881087964803680291841694101601001704728018057651335793239285017056305956074056117033327131437862282211495774666413188940910657684483686552765837367035375174974822654772064730466338441729978580641052163452878045586762064003706880545270800582312024196074463760426364529831488056486541168948427323105867851667140280634683171086751196870892579068699473639282357455661075098250317641241149009485819950342509091594770208309786929682447808233888198302192640548227838625251809318127070914575729815292538832218521439939116619973130670483010081124424175398758244000246940280251989274160410870442008092489589921121994199430804695083452315884642302989959716796875000000000 -1773019484022508983760998556411569994509924234011480134487192555980693357766162841263432959015242603813106792238378779693119225529345784222159426009480662753077168299447116479490557064446249447661078479407624564680619540591704892693786293837322173171981655617171591088880631806021013285135650462786252983094859120363234460742833871626689443718909869730271183319059516213625330122238334339735182375748551074014763749319798427281317467907315622468153993594611035255124085403033475588708532512553629006008209580796328794545869244294818314219926373927784133285227321449691400949434896614503504141992523937741902124007564859235198699844287873497061742010969037156244211812823384422801956631129257083285139481823071139313644943731347544908015549286599578558913607939556359848354977204465399154287297278642654418945312500000000 -142265231342345019911594642963583498087852882431200486984300694078976466597388885895418045828416951014359136955560213900650202019623179192223099613098134235658372059671825558553923611249956064232922030937119686061487553631748237685493437268936433635525654519581441201233627439804782716829319125648322055781844204504530035760289093515381769578529248630377121143689787641743563114120837720015293486145261906348693030758999982209027524767248065902691090082899435623129703496274987490508101714732017596156999944475132741502386648295906566325732659028945648765433926395795258651677497280281436126634210516521607193396157162056015278047069739413533393331879622529090583395941029985220255233735083440240155931335786184276560334465855820726442652138361409413381829542857827662592231331151193529649390256963670253753662109375000 2695952111596116863894030606218802180866923111687833263228186442419797078929600892966490547369647970560289339531057030159793005812208908098931924924113366303432341752349976034143666041022541891069456640109302765384008140532853839219438562713389796584613399177528251578399227691201579830624394043697761957903335047256964694234726721671058311234181349146147467472005636528656842549128058610135738377316476492513501522706174264774384380457627447135377267152502176058654757449316869273442154656088034177475254985644230154820062183073005333561674623344119943335623937564045288143256441675060948900486233626050000345631098092637004416280558803919403956296377564013555889909178994393870599426210848441890283680331940061581014397137102200281633605675994497426268590013872737383513605857743300475704018026590347290039062500000 -35103831793302751350322364166155835434309394382087125675803432454469355003919620654069065913202157380319737008187558644446956011833129821047195667079053901678498567153677113576669883714675362861124472003242069782807193534190261574341547829698919373382933781715759879166751469997420245382961600042327328847561036811492033148856488593231433608988461773363093025976928498184292311850688436083150564846763665741173936517759673490829191423247835266935260436787079806896108437963660222233753592900429527253750380332472879613010804354318012558835360219137970024417010218976620491323422334295194484086828916845055598424298254203503066915162847290583343148021583216131652771695246632143890031066336344820927817653596939933408716121245078035223585064372933809621367229825972391477409417781530009960988536477088928222656250000 380933556022165494810909212576242596070254532934238742702879179592145809924830960272065375433858367429740308316448194454821568916488260041198486154200145259234588168211344287265600256818645543284205538627436087087974571629090643367507365310948808118761186048614852309532912868678840502252573907844412372060787411258036198580332454443939791906350475242031491920032553591896792588887637328625006808747665892727513727977088619786528975333348731179365442325961255856068109345456213260030200108829377704742367790928911465608588865365358119856499937690659844104740919749216564315792664739835770901503132640749060259953448861091711521815504411169951876481453225684725970930755599970980583865923441599029574851988032146304993563296142989098545886842515733950696892323530581662971439271814233507029712200164794921875000000 -3613137249677931068079087064999215589117170704685498919579225014603089773325092472900454325437887064828388081374864521286843554955702483340980993176948973196527115798570171838069761597047493405869041300452434227895439343862807050265035133336324288808917730494730903849563690602822772092003565341848581192170791652734296700970880157367747927605339030266772332513420556540062876269618640773736742206867629288688777318261376964217741711344877319044965618823573423857256269225435606502148427046536121848287964812598141244254848829452614427466848869844276119260920714626630794305256220059891342036432944861680391279951690197197746815913988122866914044746804467847659908022263208393648761578893191327067678781985417517780871505439264267324027908997532961334318574325255601399631277814705754281021654605865478515625000 30082397610819583372551926990678707144388778535059218121869778055306134540851970860967039164128590016470310564831622643587786313461483635558790307506667839204048074197909209268118174875744853512157349006760468528467145444644730672919907968955545705498228047037989380364777289525041861408824374122068211850607997448461573922538455019334212292286557970743020979722250854377623764312626466744674316555765420056397725775427626365597843147624485103318549930307094344869645927580590117881024452894789576868733043526371539042378772488516780316453447100980019802264483481042459507790306272892985429220696115158856170745266616889745199898088857895439559858316869015913901049297172109633721904151866969154305971120962135934157780749274192377698727160136977336075794028545041941535842511257214937359094619750976562500000 -212687497170778072184406742685008328838228372050518939738671502307233876241179702644848624576518740360942260275970374633280790460802274599691683351190731338430962080795969552047774083001304564649025019087918533545291289535547503003896684850902279734011670259788979948014588807116364381523763992739160095432064514267098415234785641960274301746501110904841889208368352824981730990737600786641522933690090803258650741649839682271831041554417512388529651530815288925393530619706573878586982780905779721629576067052231327263826205427865646630988091229396961759454718552533584635612779895451538792719095369353426858577343617210982470060512284624749137896720641732873084571580307842046315998024829324293173658696851444838696003835214155377923707231616254033410815275570437954399949376238510012626647949218750000000 1121971824715700595346269410600854772157142001025300803446328882534317730938200274313105686205642823332699048594038462862827523599496258339086449892222641748340526266952960274210443576633759910007400291693331679794423079096266857880166086070261042299730452917944630734106214405375235206151315142617469634928466050508432526502700443363221274261718555210153993736530322183077709242624016392681012054617651272646329815528784414119880603156647297839345994130096350738827868121955845982531341430039279669940094591998816542545985159786897718200155966922054412187717628711439118783239597612497996495674654615909953699066134577414081683394985300861265879963057853356036432155835720827716172320755044422489205113319701880086367049711153656130998621175159662463961839692222488551465175987686961889266967773437500000 -1418241078316799339128587197509488325072534663228876668505384797012178006305552446988458780302486123317001449680087152777900506451211102647391506007061380074588221729406101926448896499331698363525655495575109845045561237157496272390890169607389605511550477531861609108044102702228615033739889639641381213289887406730628715983157509739854461815714971750934215276999513505261194067534542545662651750426189577536701638948826958318228127968631547586209169794564505668974824509561093658838429167038256419271402992379006310044448214058143263030018488273573143200487009261566463984357259246649036522045836191582660232496176583921405158935450600206130589930885807539102083378129137852010489148772169594022668947075881214007575913936795981797186317755982593297504087796745420035904317046515643596649169921875000 -69104440508726705168746838504175649830692047855966167187463261671389319652275816246622426909740413730382483680953254216890557303371843183883757770555873183293059241344588169760354975594310171671658946967229337852780402428750299159044313920708801552047853050868045361116805045160091399965194426094292123454075005995587201992355419139363712403028407894598086832056858267417800615035958408451761324714816823594367653476730090921284612783102425045644289941049619833802708823737256538172519806045012091327594902777885691884141556545933757520098050064986639419274810270186540912385787446955761182755990806475036052687433570176724923740885476233538680935874503640823868126106272827673047863892402638944798705100804421479078088652555172892176319102626160518197152848873798802742385305464267730712890625000000 1293986455178067348177664245524872993825943169692427460667388979580878033751092763453282149645618781587435069822689657033989846599202104621333349002689151653376091331541384488103493618289767864141063845341903047356829340497946878360540829951478769779006237520359015927880311324828702252862417266580626804779640017995532855066672187750321382273481065706668019522220038500969350025648432814317250005965320288244331344482364789590459732834205566283915560231767532142082715357042128512233944014080211961516769241656107554114617381861505768751000525683898700349528945083996229539600090244354424324627634856627631293092563637079610756029552945456319599853281286428998784536537563027870553907439337174251378595958786885372364355152485846898878941065688108615983412108541017460083821788430213928222656250000 -16299445575255868051955020389914986326539671967771689137651459112637405925306046361922643931323478620951623296389569897475747693920272152382822105858826829301191237147092435497431189247751714048948485314549988393400432565579471905455133695490420974914629100769948431379487718624666695367741754748998459565991736804677825568368971468815303156716663850579845787581475519887896965059931987020216834184528178262703312807618943671524072763623992938736755028660257009963611382440011305260747537488299790347637193313531318987012540375969879150040031263821366727654521530184414727054560503254617095249923261230331842650710700082611637046961323227474652304428443277390003018985180938944613887093049438929800735263002478066370919431822618611830652123252179575441794812107332290906924754381179809570312500000 170514891120051465567020209389446025077252370128607240097300921279955342311981112012860078148106356249621712302228432301361846333171458910926523851586493339097469635341405876448190024980315038764256644748147326925286494733638133882727525160599007859345225498211701648353621352683907669489035709074562159037258918160852164008626429661701983188509499672380662923540580877793630889000777936703442583310017779473753923330237388769626094612870811029490850535183916401602329361944534669051062849144844630955455625580504001341270917124405549181601227084098372001088242631817217609537234713789730719238488600669060400747983172534972376820172313530714066400901612026552698353910462396638214466151311708212184452450181858701474949742885735416784372569320730387947004924598104480537585914134979248046875000 -1560477126430431337674683168812124549560105258934362255741095925218622648294084342753088510641124779418093156394984072862035650700342212257281011117539919160662147206680414999448040873040768251791748287014952163870162926369921126427424723897514319586731424665865690811600719377393054378728686216788776582584388854103958536899145206145124474352282493426300535677027413579493887184744765382623022889184319096242562331639235626842918367687524980062286674893198514158777686230858417103789325215272874085187528109838146338631294444533795070486647776496585068499674216282416045022142513002819882323941133730532213116609089862308066908334943963114378753724217553267536790731773535393335626076436817901254552360569420717589177870858715475271666577419035076834674669044034089893102645874023437500000000 12590001914007482874317660594215488668921773332253667026179210208444876896253223876270882042952012015407738681486535359893567005286038560049452529221845503715279192585454085631413329041753153462336661729722726732298452500676871050112477796920802296888724649897937899823379134447244463619002606295427016515085349062223112996489316392284758620026485290565840890775219734808814359180395680395351935688491849580641486166223755473129087338147491902644507340779448961344232275583134925208830200607941526075252971758896487330360346334987313720781032123127810548871886817717339956533953423253609665728656455741033153848528080931344990138704450130936076665456951803022365757582830742939645186593332307936329928924745646132315771938624243232459890180514189284011195013590622693300247192382812500000000 -87243502249188588872733228028687122810068046678994076596173476743381403900392828616516572368520228383660086264139859105471967669767743179585059797819676003455716405936032603965764109779652204368187684142442244777222956603266184322811514801035631268523245236193646921921375478347467355013059030487960935075558941137693448679892116996364840833876947226622950093861737775206286078868780942142798592743876136531095842712375515179011761019963726080807925889161858449255660997029161673626151145122451481798677710184405902196505529353271457101596388488874613333813574835887863419381371958839546451099133478576536256673056391632258006932952133263046866210583120573335717279815141974110962099701298197151671096000555056682917830139763990302541774458228163169337676663417369127273559570312500000000 468934545486995900172375013050389467371213515528299784042902567228588413017950443244455108350377821571112519286784095420591732998253174904089240789542570115053617785701079873102904019427736187968918151455286011578239379789128773759103363634012371320646976777079142376741796574585105913239024074820882735954927074908127896467393999543255717886883851523443055310088166420137554307536559890796018871756944323036230015346370058906584677213493339319210788056788281127974390024577395637020591820594600203398087549480399503103975935768969930379636898555669985033256547748890451956001952980378915309195468589895149096472568062294843336243903696940257788904226865646929065585618334448481328143420815138672346800438909604274443234699681897221964412144322442710375753449625335633754730224609375000 -1039381045124365502535027122363160474737563884605217561501435832282804776549199532748320012899770568353728719524959770004787231635960981073441926363298715271901676341026910412064593497573469716408060119053142764907466645711767065235262452129588673357570508757498156998537766522227553935645272332673260403009686714522044519945516775169676544328334919444591263188564448507542622144755032304821188176069350489618639144298411034256662639435628411455414535784200433426703820072382607408237038654316540989330664200003018505246101277815128033255450806506559880173480927516894455798068277220518950479430095541570108111934643438147149717313492129807896358309556069063450037132201174794200216810518471261793909220353781243034875339587920153233745277493449421513105335179716348648071289062500000 -18505915905359460318778085979719226826183071796256235852713396134931279281768984731282423169969325850320043879002421412844048858714179184975806746992887027387804767175674588494203134892849480324101089182146199731464523425775549919719128454331537647365178395999249954092415525038880021611288757103650817895684332737482578847354733983474475745197947485845121721533682139583156062791462229616464242195264215125703164654946374127532316514490000683473177485669258175088082718785127788270875814663720485485824862242742057664227211374449309242167127054769456501333859108228023058555913159687551672726305011558186827970744946861375272469777120395819183539229769599209436790455743700218080120762741687944141317685116260907871207589472426445069723130454342197026562644168734550476074218750000 379811494680478237716792765580336396224196692892343902825523679183162744274796498634005492344945032205833906610791887753753298502651140661459108324630907880028401205502277226828328187147927373370100599840625422982081483586213243708621747431490707439912435996989381490424018846348303312827554422865092898957889883316811527509690164296877132361948221445065292034894146603328336327117857196505464859569895683389982723116386397897276846070211361376848133786135560500075797406254940725330474984415715349673197442040561216476997041812963057762031611399366122063678366138152205087137508941207754921338718494673251355488208685843208895138468904272770478546893838292175522740953342833706137668874313421143778347583700706567591158772230375165017413063850426624412648379802703857421875000000 -4793696891926517521304479140776701155149073701704906340618678168857663711377278785350321233183815586342999026890118260616191579474222498048089970172133341319206099792066723764550687309566767392909077261061837370354900890307393747550364072676005895553882872112750908968416613539623474169404903131876254867108530853977146561499641701387301280205332685126380247392213334591174822257914292798948478597827731885391033574196019196118282932082066046878254125543898896115006242162007310734971621204342294894813880599377168461523375611803774582174010162990483091577494477414106623218820598613056407002653881985171979646220321743383172665453541920495938187470767389481817662616914214515089306208643175793649884989518834206041534292137815367516005815584634319748147390782833099365234375000 49594354872344850614656644036014223365682794264082876593961844770870137129622592058091101705188309428289784045318948522165034250365903642427636336755439043553096707357947168523072082630443465755260446754570469746865810593903654007555011699588806707420136933720009036455292891327225876867995242676170716124387521257420934622507981049759509884371165561198729590817527368278478377961236963655819047862431654884022423422501292924162841466443376507463479109361890691067592036853808178449977214561278572542700295874717280488205708704486179383076940519627292687005316841223104672529238814545709554402671374622988294731286813759762870242706494815053120801931675610560745926924728761080378835376249657127757728995279492126070701302842445423041395358154659334104508161544799804687500000 -449775757539435698636413592635039796687651080743397787820429004431421430610613215081359956382837829946409893065186142110431173696319509142251776540732396770347451391366972654854376109298117690930790615922600979662691769278564273020925803189066655550455689558413925410341823516942528177674818321829594498610599052269138995808741906888995103811240353030198305126802536147338384994839082424809749496516945483810069382493295832946596788527179733360295046535949688908208941140125924487613137857225439579988934135106107415543696426886903479003269739650658923139401335331160712052480143446866295581647218549247919694067460651537297204515957892278880502180345263026682881612039095181215355819237275855428687870203523437983402099871752324866669425773579860106110572814941406250000000 3641025990978525732892049817462726919663865871104896674543055967792568052889040644689084617703396274626375659613115481843196258307520815588268528883225109320824128422683065863593157754686957254136632237624614907783721050717400481354417410167920516279110101718702548842960423915044678691708596026094556113712625154410334963846084018840553834274587252425715258057198235108218616526378321748134947882277641818713447606043987789610786671773693887410367882149542568773619112516399481071490646180479435283376502211923482795808263503762369195301792315024400256429995895237408206719937547848617444337707762953971824454461256489076145416542658168218472824814753470677092732872548927804990123942491396789212913757849059006540068162999668893720084383858193177729845046997070312500000 -26099324259689711379540733732567927628542667860668981125190286390001394914040644930536672143438542014211482831997580426492234974809901188768009456328728647830463485482906946860669284974699101000939873358906217151388481927206983005492193619906330475588579018244078884099920221853161559616244687187065571005973697119873604918201095197177752381455127533210698615202179191128455515009467429040437761772604883638772862952360388782428786761172252651969234035234086276672152662851627469297510468938425697783367549990355528113963247889549281731841012558237018921279336383074114951043918860918784934604805320075168055022910691593246326317863270123585578717585169117278270407215886540529447463288494169776305232929621468839385448103555982524159873037206125445663928985595703125000 158505385530857648084388133902762850627093629437811455558221711815455629544861574778681529032870119137880902892434132167089259163093669482375510754262341213147000629232286027046340422822556192953670487280856403787908895247994437160224109397700240587302015171099392735070120850053910118211130417899181305567719402564009994073848119565461172140876934803597456678816297139191052940702675321806838755724471123048531187776112653621646731903534135560796405274527718742367503183290358421363089903893447530201425644455640294464052926110538763514000586180052294528855822009730870332361949140678592408993121048946065853477105928524508072970153934908086238318446642429555950381672149670461894125839889095833898213736797342361399174547054169437387827201746404170989990234375000000 -692547001273664887364391093547572542652790513336021686020588675334291520230598979269606906803121433736847011245223037737203792538151845164383487391093725358468821159149243979532952165605218901679402589736255854616280216929873265496679095033141706339147985434761309525109096716418820424242878142967106194632957467283503620471893439347110220383343541041925127186200050473076934705254512765620185435348193071852321030020377204990172143680522528953575039547408783954630066306146987046504363666762944578476483936515402812000741571142520103137943728067394345578740474501384126688610683634786101703380164455328877337703400217182708915701781729476923747895894624750914169944916927534050995435376520505039513014607930657739136683440084318874596647219732403755187988281250000 22865032407430488283040490853564186459117331123245865633992077364226083370509510590279010900738035129943328950060065646251113144759829692167233659332545429593509360740653484779621771581621145237676423249533862909740295557733452743488965687112504584244079002187959323704036831613003966260712897316560431313282050498680384596111738515076514714609464329964041377524965642353021801043274963737409029935935034586066524206866868632367408861805669008777107227268763734851287220123305555367020414654254279083435574677200514917951486797148530380828092212772131615194783716566662881901264876515816215880771256747247967283336803019346386149523212702923559753004546305683024688373312614882124094682510493945016131857240285218686032253643247713625896722078323364257812500000 46487698647201517985075160995783760760269992927564373775549716151110869925362246917499090111853020525539288936405169632897895278068849939296842679602766978556075105669316098975772053399637968372666189291301535368115935818299629281579935672994157498020397249301251397300280154452249015100184451298821467641673670227916940266596829562771825991011171708925333775381584251109043146898726571664803413600775883449325094002379498909439962231212641916190911234308781507490447296142662984770621223294136559862384037169783440878527240061155162058796010093133910931290986836048142193483079215881310402378847888678885740551750926937168324046482987605683484988073094178319121920648971093018590899681041647503692593451051931640227894704242572743169148452579975128173828125000 -724639132907812401753262807835901015123483181473530370379405558503521602937025279313136377941170552347048042511792063573911536531650830709158878683029945292478693099670049098187439436401512668857291572348192451420120037200981370618193938202741701397382041715798187683336732950778280412478144256036185010313022232944638775636603420634577024013570753100022439901489752676545014036384964844345952837043259611059491414921599261996848069216252175385958349472267383899958541918843963386459169235787129988453280290761196249383544691946905950774535299029108559994398816645582818116907665709048935385834180556324635676748151649037812579578285416606222715986244827774493666621274915143267814139265005206523541842892125169200978618277986242901533842086791992187500000000 8151580603092757426218498957113432476122870130075109013601724053572367827623967819278211722350758941267400116793777323022612561760105783135338359473513021882864038930044435204348707275660258337350665235754713776086291297031624176041386530989775008149900639264345688412724888059510635716865212500880646464763359165187163378353748838214418023685267611127848185210768142786054958851101189763138873674619926221988911422926943141652078875276516437789499370769319836104576607466103679333086709920382817731788019554918961102668263437470773057433565183474385938866817138901406922028562045035816543949273263145955059885609115343801182933233559801636153506131900312194990689155851171238577817822106845661389635217188194549198243521459517069160938262939453125000000000 -78413482272762971656474679820017540341207225692070175079770155342932888104107926074659378507004804570814018926798360333245340430575925892664388791350570884397109079217607330266903806421144081433050714942529821871659343084234277260594845049362313113602952167734544381636567133746352748138641564729270906123521288798630466686079918695522638664035886476443374646962725107456789396112620441211129763280295620333082274199590824226202194490295857025881294139178283031301608820554219962847853526240518006571046205435618963252583846996193877804252052365054695893092379005773166024417167442297645002053840983812995514212112104448846649132194815990964175914616642355791247146050838865877346041507991467792427693649700420897019625954271759837865829467773437500000000 678753514075250956287301478861702487419393098499162955419641189430364973942507059107443635006608682868511253896666126095988070497385900499477694537356496526222022882688675873119253285824101092416359664413679013259271364004322083221153295039177213632424164350978865926702399580120240524529607570907151490329286148388928784059226003864361809552560203751027395594721025023282616546183181223390675034582975649004773598985027684185655165683199304778751537424055886638606951091445695313244607888818550797978485627640692094292066532432349810432647785440402709884045036217340459168096531096699802396921789092854747168843127744676383392102079030461135959133808920717723962869020523188715236425340872724477609929359678015564627528988239646423608064651489257812500 -5391409870626713377961938862429100013240960434977635482996768902369580430748041862800238571221177680179948406419842877718902389376849715132293585208932294763322231444109369824137045862894664351878323661882133216462664714089935186738498257326328273987638995627089691346722716236022522356085014056804539008241296881399364115200776121351987353453545300324108396795359245943186317928001781731030649829300714930543224646495603055135891865240243839950632974611210382732794940989244946302401974904298020698763933381598080863813327916347123199510691959942033874533646928655067773889798167874026444763488087834664506339176878382365993153581515521675610531959968572527516974124988763051096651133196250963241439034838095589741158164542866870760917663574218750000 39519064147037760024380113379764987376039974605694063223471620193664324518091867826600692263619615994775008255437266935581483916188891689570640944801774296802666682399161953707823963325982821923915753501920236094318557368278942885889831313842864872326584013858544290818778293538441830862053022661869606466305311844951603930059928078470884507668875270017503624370467346649017595110153112793405331926712285851113215425440295410248642778270565606870140492976104404047724114456228648379255219263299237223072441465965828295450463084096157103557709995599233415719768765721823859688046325846030293130296230216656862978954041167673765790117406978457088115904594053487964563903738544713726904204112292067515620013450072800509360604337416589260101318359375000 -266079223555521147776621175728229412447079155499081013450964913175788460399639472549899849975827151149132799714317592726454547215261490316236495428083664529840283141079739247145447609621748327069433737572344250785071265371292833250566935741291606963367138587786876156519536005141333435291833608780560379630669702071736195014755603528180082944829725173376184021760830326318260358014432923478748838796489411668507359346894700172535867623699624242734392352417881112562789986572811592231079201125143454891869330517187469054764258673614823103831761225102075114026310227831783744552351492353942168382689651617948022258252120425699766446026190141009628744194176586235249883173593743845467215849657658626305298948944155768003838602453470230102539062500000 1615857222146667183921016389999965990248173293486399878719390426708081842717609711806917529922028451575018908106833256623956033833859810270003886387742158097726221262382523778466467180040080694464030244831028197935046937314179054244868939852006412584322068458332392239987198731972068624465481453837738586303009763241963041136925996491759874372354628457685722226323486088798921092189955129404768823533338618454789844020636806560615505680482089584634585553640653420049860073562505723922450094368825504437523099968014092157368686977245856453234279102468132363252426552236313274452000466970796045612656279237785710044977310591619206052539162516159156123559275160424677308022306233479211632439840282250513841394434777498645416926592588424682617187500 -8433697292466094603233456865354099404275180413989523302029764789118416106467427953785396572815126384398010894961983984835989970090638036254150933484614761485801667896423676272266874763640620335130829166304589300594467343125635564639077001805888311755678557081206486863340361260862315975311852681341797783808441024610778623489871613641558121514742272300239426048208873770717457824146869563361798628672510663366081850930647908050212047948252500199574139160794850990651083414402180761830168057052731927731023572899463800668875276084644137241171062437551349181015516498391619910920819693744387051424169764009538500720208766451086045273513151680093870744782233396660001464467988821121663451924846155753276444322352745075477287173271179199218750000 32270024162455692677803689302463351028153000228754502427965805556834722625190226430066624182997638625184502993656760403713909904245211239167533380051640727744438070985682680458310629717076756228125933361720877306792325832788716718839009775748396064150809985268392582795920418381884645130781288445067924520406164777061117787547585722189686970311075197139244553173030539956146846023544466310237910799834591606349763136515790921883549373627531518906158598477030287402569235385591040767496783219845755013109806783573001047562958378002685313342073452659148084407042690825354311552770120560668479758229545553023861855722362243603929089299385853966451128325619377969994206136397973906835183118701647006498767211724043590947985649108886718750000000 -8320836092232935276346257697347515411511763535488411391550816543650744150899154871881923975883231704957504699298913684487288495119402863165243410852713526537648720552134838093829629336953546244953324600981349263410862203323907479472992728955091291790150059324160132351647937961235259564549038768897778701970499745470179071965422574888764260776404883087938949753232127499208120128793395802093091341832005495040549957656421163295586196167768269192941037105734944967326767861720506615353846254447910944635536910808165493107478724090480166798339779685834028136431170897257630310164480301623463248294076998972606487385176580428797379637502076827390299257052761959520098675926287094949427393587209136893712013716140063479542732238769531250000 -1533202062366855537478415547767810508189780848525913753196035627662670470568849285353248566248161375789020019661437258414013650652781784748014164385823319577522646382513868117361961896825529789432119821270057631529677490113963348848989370279578550067634862971545269450478825578897992131312061612210127981647368453943902504283846613492673458357442297584357627831227984309350131203327801340976808696887010500679067688486569556871404776315543662395490885226602154027775960408360197679539999570472099782371574509982848190033769745362767758592657136287415813865804566861196362152875208892880227867458234399375311216685203119999859016213117315966615445478152921376686682902094616583527998879102371195676246529160380305256694555282592773437500 21269501758026290158407560361223052987656204110812876849830233869823538315619086331648968257080802520503215362354366363297467559568587023916364141453055992646416130795579104008845913183346413620658197894825204770137271349013936250505288075479970528993963847453593799313829160080861939607451766869455098997626134393404977017039477090387079363330934187384108971597175436416254255137927491097222848891052500710909574233421726739972348877792115568604301436091132907430023782092387868832619863946590817982356751524949358576736468857247772409812148167849065368719430116837876352220770899746404975480251129956351473367068611524855836224079513422658854173581253694324864365583099080520233612075480661429693896025128196924924850463867187500000 -211270597842445129205215122605732143880180765724304169426338423425968028762023762194393886273452263920171510879018418636527428960423702699729118728105806388522032277342861632249585318291802147086563446396012256630159332111497185329113437201793730358578077473582208770662726792420714752118034253443439697310289749343769422289905010879632137212629865805634378194636834984581043798982753989911601735862340873900331324178384295921172196296686981432944224136826016715403022582986955500883810528240097243946267127458686071540029473296473887511125289695242297887907364336347783558615452481070120195117283043465594373665121100713759779638223330051267387287267358265860212758382976137015325169741207511631131410467787645757198333740234375000 1795322420558103021327096633366988654355430428482629485001847886020173797277282296267392728313681438437146832331129513055242693052379481542330168705083885420636252346802379717352012036841853587277092737304897896069301075903046728368940981669870424387962561712949389618708346746729557930665297619009358380935759736179994092878888041753225788099870511859228199735039648749531625220250576745993133792610804675815403682652873049288728603283906963197564081553611739869643482064835691195991452255962719895856291753297127973081298585467819361252549704975294351611872227153147648870306932122975288287307278771907577279198967521291527315655004481895772914760785952847610529104542527422567896799518449846289058768888935446739196777343750000 -13757197734197588986373211437503887280174607700387521871782857006216921653250446854682713994614264909417398375867989109791659442161415350687223858066775867950787503558961639810182883329290708375372101582803986183523084652319832177661009204690752546644003144637056159347796256383270980639942362932828969058455174729544032523501693610382048381744128622798548780465885165669491462985126010154099098289901494135814443280438382592032798320570000475590140611680960756270291719263753487896723974320758310810008757469549459413138272331907952273375206041276038607736450204936316808026452297374462288710659240260979293994735403205058428230667055975996933938963733388641036704716069297730589445719756591657301214581821113824844360351562500 97015384915679750382650414699453187528924720138109001105129151597692971042213199138147212628357151083652878045639144015238315835811621789798982537008178097895322761299476378595345473871305958637263582364033732205788889338104769067624379642618747842634239583351459315259884701302584628516808884571393050398189110567381954385938978506510616678872478292969802625677072414132252319216852430655180845967895668261202479230249598083914676831554808216553721238807988058587245609270874644112232481397412803038056212903290340353709508921154592014487028895965177138525490679897469915578726612390155694889904815891598451722603213964852179310351718897525373577882261667108064825405902868379892645123163674725219607353210449218750000000000 -633697437970055109054824157591377634815447342748678296479462035310107804659046375997393013497682380889956419192653275417599143967769504348013880036768808607594920301603078232874268715484869249326670892480071210936456362988591147255779252211137892092101938507475762215171782213792541888106605115955674428227584087484323537752698412886545578501651627465368128153779765426385177952998854335302270214450031006338362566160539004358196234860925114430956809585118938864614912798371556421679217953470008820416236750180692457426795856958133595480742520036342365249321629428195131535399495990693479191145371434576871552495566785223561635207391738825102096909816485280327396807117614667761995583816769794793799519538879394531250000000 3821516019198383598942237348467639020158464865642075016441972738556844012515462248265756058282464442958896687183022447130071942016837221073881275093759925379731417907327836176938957428966297267413432131843152406137009450466223289623798564795955617300043626774579291858493779552705162321277913242048525919211109818302303806187127098788075341386265431320718849422906192518161413983091499127059382217143402998158149511865044106340073830345601022410534589840565981924792072737690254189064663211660361182771149062220656568595317632907255755113320213611723031017800704343446656114107351912971188132380183069943079316132674265109204522812954856738727053687923405388044465039220146107545872382615925744175910949707031250000000000 -20951921369688206108776388588038403904639162605522231741581271873842798329412933046983981868480143612479368287624492877679198517006923973041056296688480579078999505505339421016757771771039644654506531263538823641259426821448300951133788426381067747259266899766131857457498757369154708702353777626816239462079633449461919203779217152041147074900490054768809568610335889867762400851606976668687086684306473094116609009378502716309272737260290800992842810238281314008269496328717642657291684328777956192391844222858992473619379948638214315615747060951367143244395501292648893133505629086597900108255495674217618514338784508751298103190646502477595083283272636497287635379902089819564858785838623589370399713516235351562500 100278441918150485781233184230744111261753412571663439855402577147109516260956006376896892474462183122401199723347624508649018609266242038078281851278304475863049531668180667533457935177131824145327863416099751956438050475473303693361868214435709262787507073634840320478470642178016624734772687823848481693257279019912478459924317432689485382542568598776639971155527428217094057168732781456511605202964057059469589408966879907496856691234302660990517415604454612580125782897437096044227598034700204912395628044349657514224512862936240363028127024216418756722094219290958917916527516810511293500468964312082134382042450026407553198514594300076024523868165595229693246498220079998553444511344423517584800720214843750000 -369593251450817291130384797951903463917906186737075994297644304464550865953438089832162698351378849681971399775196164428696021905516725304628890165577017937614739864653908329887499691074746135441667390941201070299935272800480030375086039825534241249448894377329931738425639352643078927218335894494375503097590149435344955311987226954433222493452505061047597572386738420285632149323522238498389371697403598953234093836790938745553329457871468836398255334561227401656846864191067239099186342287986766836052822383383480118130083532908182715891572066709356811100374428548557485428927935008317586886061260282193288999526223944119797251038693522087306981988003034884934260343412881777425127438618801534175872802734375000 410130978567247398567098621062085823209542065073906389705428468701033100020736878747514633565059439469377290121822086176609910042828733115877464223105793477456614679832303154511790092461638117338627047951871585944815678928541697662487335776234804583539718594629941370772032188782771994511534599061402996062005119110908766762257863798678550590233555135469441875658739857547109133352958643109823615072760240121553562493378685920182252557737656541184590866451140608760559429014284586318986920440680003897189364311348424138005759412939156729475450935536854887403965271048081641513161489127686885828702159449600765548441044554568712395792822191344381234812341292473778214117130502813779457937926054000854492187500000 10229697412840806489772585339572025066043898665337729252749751687791941940351393664644489645167469450511493437922176534556166277889182643650147662909924218332082854145429130639844861313811824589535104421120235767180196305559529076760252747899022310729414136900036943103991861249938887722886599581158734523764899310357918637316478067023515877127587366966034661594360892414064057788718347753924780328242337268245479312980915870266741746875673802000099219871229731664327533898300106062412888708522304322963206211221375233229336125929764381684857393977367325794393078426362138400650568250207933305290172687046684281359202626236390923592168259628978223942498621449726620927928033566445265023503452539443969726562500 -143509675459109994642999141856291604577332992390328069669570313240128783169236831967399301601756387887669297302583933343144689933642569336867197501941626961989641326578839344476585375654300839327964152206857725733602967659092261192949548825983790885971568599395917020138227399720708949662637138653767975291216305889762200236047615744654417441434026987915675748534382650141009622892153236926426616034482273416689595120943729216411535673163313780743694867455901632082305028952689051205804636006283279669502202205203118656347488712866533445602260152139977900478898687101950440404935767075001348958476389847494958855856746564670951891115388829101630451338831809547690390727048281860334100201725959777832031250000 1355425163223800146575357873308032935412426905633311268144144664459700862730148371133438521666717219645798853813250000715117031555296988669205354743558894427494134639841080129255088927626948939868415155361374175532253065135449304466173263364379105425654337068229800140397209800491322530420989928694738707022395696736425567744248721521509939709318235659760966963379345048184837329111184460867114281017668886158964816688459197826493553007744490608289317498961342353255938152664977032189958577851572492868851317216465563924725388464972262991594807553288304680823410013831377952624165639898754411781102434901558668203927874722073982601806353631778190371774223078535359654495096037862822413444519042968750000000 -10903072452978508094019159869929574912499345342175065158173119330306651210148314632323571746861735918285639468240996737069886946028515223959625772408671213290119352346543927641019813056494579097554361519030166615480098314987328977345055775122340384979721293729221271163862350712418781057996350634803877435659066535384751956160803999758635677292037328315025968525794914041263038068536216235808506829625283129488037971259000884162197814979707476669546060606273265073785485348465095016135520728090347838809522037117084544897637555119445708213460425763645038801488983650337937332159864178253266134269990925313634730257080887578886052578993996130559863029355261885774974750518140353960916399955749511718750000 79780630487526426278621448680415189517040784393467223945206354041521497376295177322832929924980327495546799397652507434433649026231931999292540577784149976251458512858037070120858756563739459614665470283758602875721098470220407564777262239437583090669552017616799432657279647439061299357889672104300636660748844967120260081971669559241063751855915377234610941582087954159985371680869495031059821865364129477085172200178491380957583738474266232992050163083414142622731177353619725244508447752634128764163690958845623819208235698999161929521614526881527283062888523645465327509336676877070462115396592907322641080695893556886387067818556192117646841127072225834798713250961554876994341611862182617187500 -546303891960115743893812795235438772884613815589817403513717243782495752532106452078144413907894884029477908180539648877370272058369005450372877421352549532815121021868108827025843358934123694466827329776078883887678319037033982921603640651500819273367168900138777265411451532286966534790446070491904466848764742023738360257180429791052018375378880185767916693924155741819393701726438573955183883810352665228037701096654688438814628806402943158871668050021490797114449772830464817085125159514505576132117499740216061158063776132865507337292401301034928844138987078690394648916066625335896428321363923250325149403323059436429657030477960053952565226567748141173197495845670346170663833618164062500000 3554008150922114046782125287005501345275572089862599054086439539811454314450831185177595585844180294194912061216789907682742900836121223782058914421115951303834400226300047707479667309584879239911890270537614643340661696413918284335884152538935777619366578589549113876944912051132790307930855173534201899118153722793261255506975216963145025298637003474183566393753821475240611500312304532788702773310081995487113964479560082892052698633911200401675874968738940275585248908002878469817568555769283817097768348169588154971487871759452944823136538718829945680097638416146704391198206837744620524851012510069175367696854326239349633810802203643948481417091066203450822058584890328347682952880859375000 -22169393348306801268216148468896998382491318238943576787479886019306240443504023597057553203885358402049097540080193340534717343142097404034899543002261457114479284646054245238256708604672694800645648383527158514270665938446252142698031334234660953567663933456886837143911464010255637798505648160203159995874974397199507575447068225970806257554447233748449256439064550628456966605605653322919235567676652525132468090795849522512191986027771812326511323287385498849391398143849523305993089062388440479017834540427295864065603958330143534891311864738536323250530050705916763795555952045963673917060814421881483259490996867844515777603471717262282827563477094479083007172448560595512390136718750000 133425985841322342510319917654326889705934651271242723409048805815586574841620237996537102622842922901339039527138416227882826935775482491326231919100103114317649196367828603045445091898449740175162441230157123405312177438704068857976406146424206461222892120194750062610087919983599206495715197852109760032239696272886773869900621544306740641819185645394471147450374584608429182955904260617456878501734080852660106476997101810943554550213321138554654450414069329814313783345240667164099781959068767190801824928229022580789050691034101194175350369025211600203399225398221250630685923880720894809639633764572053208931740311937472739675219182197932904238718565537169524759519845247268676757812500 -778298378318038169707840549194632887168011663177117766967736177050328931367845187937859104588762245099557504348149851988915440310596020408093134322938327761823967061830853859289158114178314158451079727554153708177880286677508397667680723563118005445828231743225884704374064408163784321803505089334687243377686147300609815864068201247447799086112556261171050865042369893963459636002836166410498638891091424535452757632906788576669427679144077347301515237728097154518917003782805134010457138403521744221015579162186522385136270467166664230183339104484291802128700986121033794235463254535893396500768616327425294276853126119617353595895636647530174689890714034845586866140365600585937500000000 4415664365800762188910772355193298081643293453986403544045889158268306709287223598569398530175011939253786681139029410167331065619216528615981079981668884851519847433856623144324086294622454064343419871384190112315774040405560475773502607713844369391163953889297415630958758587894300236418228254660375757610961195547159407332498078406022281409508025269712542586267621407586213080212553741466751560556374965052788537624764633140216866941489190289680291820248020220453159436844293970210878021473610941146152457294008056558096885734210107520794465359118362603444684316320362877859525345074759272960923241604326000342993958615905273266979383546548820760335729573853313922882080078125000000000 -24435874679548375795247083073268791780684468145224446683505751156701268487914643905788533027611893361975308974283790976273838964075583837678711853840452715731126849047512890799563241920251937662598355370761114421166362264161292008232536340384835978563188140501767217898499714284746844840929629483778311961319588035513888042800427615496386590056630631800248127610611252892648123649017393551647922021633671449095841418191053521593689166684411578530550339049751404391775128712869666831631865001185232445250379956460862981121264672830683207100494805372558950522961515764094004422679824694165716400503800724439483750633021245557687355200247435876859114500803116243332624435424804687500000000 132213722646008960559045888843663295047023768228820694154964175840522545432681292308743756955893079797507254335447187011034748839893575780851253798877282611901523473129171131278818526449509445077428747855613222565650883461216242600858489071613439180130785754071075507516130758155499172288164395356342310338925709764457497351211409725336519493116046561294634891167111949466807874864908589455895290944422316985484293429362825376742029679303943945823310501727979563541452070303825727150638867496646627882343062802852871145433606680677008706770456328575728782517245249905759170744765932265710423960174691150727608947193143151861122448419456486441714293533777890843339264392852783203125000 -700839345839726274779316211040399622716354138392678779242692110461014572372089799651449321629129311009699394956871183498388076215872858875845762952264484318402516169661221607254414736761319674309181743713026702039604456870586573964554638523605641092896973728966103724787248598142212478569414092251096270363204782498214505681671146478162431254819622441817138468708212617460252696997760028524900088787567331498348258944293712236593453726101208796066202486035342453026273961386792987740061903783460125831879126855963122287136412583076600916216797672488669518992867832538366389805421107435420004918165051660389978816504227568992763286361957070225159327492292504757642745971679687500000 3645793807001506719141596087217116470708705145587842418471969681301369916200698214954832738485031607475642318674673475023657221451589337633728983389016849220395868874386554254838796013887256505167530005719983104672603944324819077856376075385353596799165503005494169707792755561558941094667684473530871271149014416206033278310235546869078140948182544484104611128453306972426698469221659218749050482972737203918421952056420814568023027255151927439553433618840610602741374091124143668334120658432130386319483007681902064750712560042919207994849600866829514446979461748306768017821997250677505157703104885334124116448266260237934303461938487234128558611701009795069694519042968750000 -18638205379942306915890826212338795676270170700405374882517514542564719341389408847593475610534193898832083598949650456183990188913106995629385142203860348853958991055111976370220266826412602507827337761064109167758158134426504361582758574081622958474739761909481232024198635814791844252795105998984378497387193123240372413512662154500522955207519829870105531897557657062988711726545221595660880562597829319829189073112291736930362843683479024138343627664163959323963864008716441726470230694752409906601473667288922176607816522457452285868448359463946746788183674205795208913977332153343635121566336598958372989659439670611981569071924358382830178015865385532379150390625000000 93740894276104700391149562962137495944675205734978840420195966588977550854021548141269275786767146621758264922239306218292582070330451694951898970407976683284909882180760791463617098368487126091317213971798860664066671708081452911841083433675840832308359355172604545420348966078910919915072871659043411203040608075272476126527451503475619145842929474297922239604292697045881067927011162434799879535994757774678566149173911675559975119403112700940066400798883154491309609718500557009265672671954641581769580038933250694775031675017160621405362046781833676629948205170189676051406062655261954718375362307175151249023214601272465415320034320956210649455897510051727294921875000 -464203325165256282729755136109761904111538247774736286306136734086852819102725720390745053706498306239581931483628598368106401138299764306050152274986488155181506035819519398911732364270356692793218364857874698265277150842454091296185356946288991130544632079509444053556768396837761400533015487361806094917837784838443726930924569355568563619867631577382372258477172538695868225181776677355212124685298315162576437763765032871145549526212766393879341529715983106827598433270097301071288465641138749500824239369361517583744978932169476166368858393992076256441614676965418871228901353399011503328799121902332633255246851701643611559644497788212902378290891647338867187500000 2264387380158222618019183507856757979136793699602488320648550024655821431172829557371802469805040679264852819078715857467815246522427325199482914564073648797681111433220622894043527429189723565900865651546075403740283733914246170118830934093864633115220491383322973231259664960606744989295557985309057035150168624423746717967528385875022622312231297648174712090162158367076834620139645015916241162166504257962102181708264827531199804777387747876867327530396547256882731892504927587497845556613860608220421293947903538510109886784431746303029069101610886616932420392303938399852224059413858398415726408836432750856198749733402819650507353799184784293174743652343750000000 -10882803034864848226531074706282807400691522534274944733719432164928887118692743655928029929129783776815434501676219488538342394800041972033110389793871858950091716264052914286494683340007472900330335903689120217481937480773376897922266772858527041131683259483522060426500190324868538841542957157264897001649643190214150936965759064675617757365477734570047037000488007943035058737020079603693775993232805619304882083373386573214452270714551579049245847300756870302292547518052315328790138246696839353107313440251582487938424223501740021517046376935587429455663142810108709662808259665776707603100661266056092444877246097362927246265940084413159638643264770507812500000 51528921434882478828279324822682678720826965056377650995364416292109954246410458631906476104725366982318553988080392962583943445098759541095651948052601706352477668781994916061576323793269987385676266846634549604106563530322036239813765479702042358656833717648752099605118870263763790917395816957262888545064482350222449189027669579115512904431859647520671217166806586279706485141888627177894249974559030232171171726411529751857904919118734510998462795690461587954995069478126338729537605489705783545390035470444590761590429322115418364647519869072566694458901053689820027829326014140395642084366321466528920728625276699054469364824626609333790838718414306640625000 -240304290978804438304296915194105583087096208378500680772683627223369983055497919380345928064339668371902352773122579537852884552136651621724732137633406363120162744628082813452826188817483759335280936110300449717748315938014694965360308861354318289078424164263343520890730094481729773903824035734799780417970872258814983902219416434610419272661432100552655966757515488566479550040604737733846879377460928325620532445091447863322798646047905752037280782134118664006134637087167609290982594583832855764452497946406227428875428680003132915993526494999279278022405281275289674994175045040847609229747779563701869058188649586060847695989650674164295196533203125000000 1103269811154576426200546516164185346403113713106657000309013756050164975290402842144605647845362453419042518425924534587531216281631835266229251253161600657961981325823738804670553003252854976097798116247003115017014392928890496185760616838157507234824229768509487302957032382632128789620367522566574897520007325880280699568830681592610148306284595191660224030979155722649163263720024953854492418936699834797023653075064152434417611957376532669409486790454789296454081339495553505859417088738373816590012648725995924777969964082904821520940236512831241425670755264439284459321789763380429873795473844503295548737835732322487558576540322974324226379394531250000 -4983955103280353289378206538555879153796665686903443248488427249441581551664968659224010806475485099217075379309210014696026096700431701110379750044441741462501561194120018741167649766278899494740752390795269425775801849387210200969551759015311322406456452663036625095204907009740090254343851623711438194356757354208523289151776867101088496234587667330007586938762057572320074940918826000688998226600416887577848057638605885940682733464617647453846727874014820779489509669383207865211515066898407534808837954115227208451115806267194747085524017979896567933107903871392619320051768267346194569776964744908994699949117412884902478253934532403945922851562500000 22139916059465610531164484155191893414823763845755896930095118635650640378738577064950045978476113441720675781838628700668475195824896641500894263140379220653043641883822079379349833793056418328303949155408343960776304426760811943163561836536153305728981194787136417490094276594056011184457000984981064478331277166193336268869414572871314035634407903846440713030986871185061577227041088352695827540888486338623844506380951936201601500809262260894380115684861996104454676778965402652651867923850833942592847127317375266195094122277790972188892589760983091583617722258536030095275234270691318275521848874505003216227316809039393774583004415035247802734375000 -96653648254773231258158593329825499497214375959980001021529755550694086604821590126066614174839260575689935217819738404123898705743321265485747124337942718725742263163519562913449418924481857227247870485741683135068264083341017440738692065193458103248874854792729939696403270961820321142912137204955028925938857951062031288162186416702619045847701069392430729762313619042338939071025462346813713864509109997040072760938328391518920112167063110383811218094218564199313597429371217719975150034106628627643201621693710585703261514407610838809699497900480208538526119017093215376649732182460822899797697066188312264856108413368929177522659301757812500000000 414419728310236451931369800516568087796865619439598488534736486256119975194522472205812052459914411842675885416317811153400225859549620405869764127269740703887119306130674285722900960553098210808348999420712028178227777017560811253605294017266428179486990726787696685297903228316254590721757897726521625395587882692978308441251951796070002696116760899788330942190187026216292288986261513782831400024131716846278233994828681457524679617573494060579620415605688452108316818138318200889276052491092996202665456478359130539664981540261397684650001795154565633159460372878659822559459129879484020069278879961488515348833061580080538988113403320312500000000 -1744218786262622345532966122268627080831509318214253650009199444161466140120771225860886905600965414797501654968391097201501291044970650784436752214142559875771419342989433692066401646191435010203960437068755816328854740673381093744443938432794852852349416108645165948968364945961325520165415956961694022105838618850744525579164964513810999490151289824918133715693081544880165256976778090380436900298063213531531906603151172888079348179136668608168668286499216772878046652238286373999193533806091085847219230754013891723071460744288950446463292793712545141490038524748870192708025457862760173589325354143175772492213582154363393783569335937500000000 7202511859626336200020228964067053955540766329683091236730091459010450169092581800537894907249679047293274977328879590962067753151119181323204013559308661282467992080110866447044789351037492491331462754558212954347771315881943692113811702299622553238558738528703682982791541500371560783949142866072718345083825464880631282882937154587398046337893322509054033770480054001953825568583202189635712615727103691310947643611948232256588432589473795694971831302710384772010572254886725504050147609238800268770932309095506951957335812793115288745142622121200282331058538068966433110410030353913296953154434226589131196050175276468507945537567138671875000 -29167726923933630183861283427929181854400156536156091798918635350643938006316984749291347999934219482585617227092696657824071839558753462373956066675394691634581489309852800542128999840670134625311983378689075998003126543109844226010973433930440196621178534751584191736110164012954079641270406956871956572372672446076660187712622344201894663500704348594318988723522863420372132181054664948598004506756152951531303813845265488021684594710921873551605363056579024336979346120512803712189482574592800037646839269061333691388846479379394669024164236171513386018559246623457652229886837161179501735051595306957850084472738672047853469848632812500000 115797634417250863817229446081484970715937313674411366140152688745222263806111026630708531865811968875683213249314727730303322815928438249643553902496319909810830406024515192516715735910688676624693608999302937641103166262501417925587940757731382867244912174784298090973665998552884801960131526620006931088944652195914090910198472098446378709273937848483864910182276884761502327063226915052616660307839342332241602251291008961751740422167471020129509534006850279173741289186887411042802546212047742457998480836505494979888001592444335632335334731478463976674162436900849989833487659849409204872736425806500903945561731234192848205566406250000 -450554266402178136035222431638170971374110134425417635406024142304148872817431414158195484066298719156800051667818735440319074248940202192026579777290247254695798163383008847458883757390391266219383737229732160240933824663619374574786979075220917221249616582551341825295686034363472658793902528302657061408003381172951544597353853807503352765761571259783781359622032432825154344383651075198304827188301856112901371876579352278767526592618923501851759470067487060376481070391572096598219478292400568159858575126420171256537797740283020451610765561534675416550221553342673130349221716215284160890475195770932259620167315006256103515625000000 1717684967053105525148148771552943426126661361254784073401570158082349085504515604350221884694591119135259032483483354424120365788273304706772370382777030330248001604587452987035594612754938330398353405798988543417175267790109296141328476350046636133639926079447124616320630567252643906513058873022552799456569777601980189161974176145626295929274819598751769603087731714920630961448948882738083759237075857252154135265383154758187768029563733814684975855667444898833125490415183976413914752895911479748367376827255026919069363827031719121085613717806205413075025682894348620097335551833338186840383077225169472512789070606231689453125000 -6415223136374992903233861169155885162210513850829245478114051767481178149236679491135723399260928395041464128219616500019071230089356148892164874714498997302208459299926530694268766760782851345188655309491881375035417735647187223016402861197328919213483032021538228153565078875241390496876565103757607491392414262414127193388660584614761745064252118674429118987376322550923796671522955983428661236795102143770780867807207418782541414044823488559791928886999800451060107690566487033400884362178719754209941387842488536336673622350836495639844979562593171496154436443497254257772973938241199004517412163295375648885965347290039062500000 23469074531448289889542197795752260459038003233196430205884615849008046817667713210368912848081124974813407773010249128146941826401738948885779528457044487674271919776596846070399148448902694899912098975905313620985815787475619815127318770228988919641446381160123982351854204287160436377800513242248219711216354270759399113404969017687858023153512138002328872331771142462090560708673021105748263535807109284342792241106290744897253296047034442766272420944071211854909705322273921116412355131208874205391947402584489131386628024398314241259008387219474613136036379221588703780616787285609459168256307748379185795783996582031250000000 -84092740551006794132684896521756625475353991136916073166423802638906874489065205261100891634750393017092069618637587800241446706943796808173893719603365226821173433547954899717378593834219238646930667054700703642379349601981486914085521221691701724760651105441446705888182666978877148934893985392784648770470595173383889118725010990696201570028754338405983648993730872146799498762449199795680105036419610315287299718154595187352632177033212581478771670983910993190200179654552140158891119656927567729634100156782197656668394756282179384856437442150981803170912300594491535152783261066605779987526148033794015645980834960937500000 295105482488718983471990387001653748318288181216982256887922765478943632080160365246081854823743390573423740165141387499384696606383573084144548924207263397126601155305463167606474762061643051263682442683771692689175810176740194743166548422489221038871145823256471122469354822035553515935104158776951485173349188343526822686433163159855241162889481474750298212303093386991816687471651679066068384205953527608829769176686807517870401210850249849352814625469261587048039323798101545308378174208049976488888484975350997301458545544466009829030436250036654148647355014034007234950389582904539675922706010169349610805511474609375000 -1014245438277087071654278315766406985854339440025046928388922525313459827754193613319861337235185534554292217082293176709685982372580056158510124542918743057321007639941416726624553020793183691418938113895312076974497562624567691743702964382512908386420361739313246533501288725013177783447411200306966626851497151682675227205366514041557727767504370291131495756616187220664890427405709587713691764998673949811960191277846073954299889107348199919765956898291295352451005707209419056467486521369674326982287901428605799610367647269632832268206862720775988306967513512215090185357609098293352190012228675186634063720703125000000 3413950490663579164880972629212384209009063465327025556693060139694400846966308000411063218931993348372416987692812032378455108318754891015325963930114582810143029263124198695883546637853658847891339833137792180968157564932353809535975889720627439968750181033501455861189074477904252375089922107116746984435553501197893031008314266323959308058718224528613782562992397714296142961149837671759765523502453880403623596036658247718399356231449051709788661628998482822959120827053053686620527946480920490547353869722577970945668464964874278117117795638220964408822047304877669247338486946397040355805074796080589294433593750000 -11254588423314542965971658689582774597507388986436056412695481392893365417135937192209463016910443178581309491755843202752108657766727741016151036802356727130334220741352091794806854042088870043005619815454987087571638333546382036238565482143355855741684427508901482941541710428806880751282248281696146028325713264224817200665669651254063088651148949226678918352074601827017527529786266607727781030428672519147682691726300103735625395980456782566922432118304587112251451070025375275426336331220280554348267723349315735113501763002302901330322993851576565037946506730069868348204087382669058570172637701034545898437500000 36339324214111282793269663129728820608483189825109030266143984507764974183009325236814612179380752567505419072886060823351087361661815863253771138712321940904014163992782604772434360383353225876527382535098506428520092766374529385196152781719210974809309741133551667362904005843014268123203136896280462021876306840236145145342838523242511446164501540451349534217057965123142957357829603051123284568672992931312072123989393250477612799401629664219273125939282678119109026994650093474319638846532746532441787158044899446389255465762953113637109779013973461480037528760589729016905469194398392573930323123931884765625000 -114926620383153550216229768705936860191109631980333055257517839694443984005530629215793511151125710025316374255685338376423834612333426143463524710668830756843161484217280711637980930790774326821005061759436352019482964967073701164267728766868639731297420455195356893038831138636015705954925011770645551895779480407529351857757527306671318247325279958844723315071927773801460215429643209101944369302909818625644390537796858831879709991691017064871359808531815388354891768479513218941870168276042304199078078812891749198463657083298980626072270466233384826432570486893364192226840714283753186464309692382812500000000 356029914874021053583825106371327840959990747405052129129592484147282069482101089817073366186816598817707219835479673881942311757846949593182846273285751290633819078948876843974339296270082762993747389032764108110474201142542621929437295893613122116934559856089551511607490179770655120208782339989442482215346250147880540346334085241525864882978685547670985411734630932371561371880814228203525647508239962915250010631780217074737388119215760755919239781051000251466011562229986637143375151413572870260319761768510917549492376970280016986323425522873709423763810381913241798201852361671626567840576171875000000000 -1080444589080569640459816537481071446385219368635259935369641732303295187227164452317711726912405939976225057309129684531678474561331937074025246664342207008062333275601250450862225011762488601524959840719072147433600012532912489013088872128319673474545187352879761994626714407581583261833024911137372856599399119451940375101138651128454509156619592551010037167857972159559793820761617426902831276994575982871669082046667456965407216705712420904239814028177810127335191715581252970550076993316729005369322486808301692516902326051111618161863183431522720418795861091476595561289286706596612930297851562500000000 3212168236687666880422241682586570027757672905601497902031572489703966208624839850796961300120261369879072135704878661003468343788305857689905181457596718759993898987255092931866374433677801055681792123173327376652360799550756725083302655371719738728114969265734370365936278344292521263367875679070234761796854093919448152406290309886757675125813926031198043141801883555366793470235107436077825308945719381263542803734129912557833392873012844677635480470022610040025293476501763297870001457515824418151558318726607856744921548433852470778905013538440916116826863500703648224288144774618558585643768310546875 -9356298566827576465360606923889531369546605816572575125577161425355723439271861495652150418287006759772236400219862852974149337053749318975696544389346317440603480880767137080962265216359755527755696762186073726122318330570079777224085731156001789360686924487272354380421893080308210411079066738979381474410632558020832597432743983909614641144964475455451559463273839545145313281726722163588775946333160823386354228609572194965429168367491775852171982493783646769591528076728962319067153615906166354766177674317046160471730521079314951736849142043531978785088788069801424285287794191390275955200195312500 26702373602816756807849380518706510935241686052911502700181481285180816347144744550408676708518988259782723593754731920300435537010853586593719578082542315765793983973894431968104337948842254560324036003278000454849312660967834582373078335448170720087978931506209745633561704536750492700867440553630870896812368798662507325221452533449476225517460778230307889786842434193884972630557830191183533572059341007056363768329350368253554580943087376941889226704116107437486876725098985699401914179101695625694782822288128333161067430807293449814559502552154178581797841496303647090826416388154029846191406250 -74673188198472358384789656993145999406960848101391564165181605154492693099157144832502817457235640399242529192765762919946162262019451483121592013254352053024751429502937863946404254498644369743706389017759725464464296004343468149988704827555476444066373927935691398842503737247814438707472100939348790065912475696946250162270447187707541859340858733324610084245652686859931023394452037081133640903337657234415269293020201952177257760823811097228615006255964066492776264984335776280033033722362354840168458143770030785071183196970347176614075066785158169523073379281186134903691709041595458984375000 204633107295176772393780771051771371137878128753588303637382462217587638291939966308000897413648661088991377572339717672328990530681319246203218887164843827025207475092199850417204905107968116248894881752633048431127944800310435401173328734921950818193629549033683039236219770667275336793574314708391066796413623072218306565487233257481002274239309646920710766076260517216276290257917194495669050844974336018460529279144758524984622569462587529971816123465860627007904092203662590733720833954605869968630485146238429332205434667315536062126142945038698097055818170275642842170782387256622314453125 -549551640139887702197481022328415488969256227856650048827195648977343651976866305965027994818748269809589438893623238804311197904579694938945591599127722476805602487930519608021740463611176155919182337861638711500671182415133069589031610486458057786459533637584072798669979376417731530353759058285453344829198739921003152681522001484000715443969601688526079754152075739688091977325374883054827282351464690769507275175503322415079416692946728764434058845014111134778486593415384526327537031869998254622966042111032236264496458065584938282227919549322459752405123367680062074214220046997070312500 1446387336772736380763976998376450210833512222564963131050350651925446290565757602934901993350052325708015772599164489687302344435200247408633316941596181896438630187705879650697460882349241882669862820843634412577077501400354728699740988934654633569538395635452280581030151662053502627849082711869841179905508534618417195387958283523671926633994623441046520209733649600928072555900601643050789274726718374768802355971188992156951188232879773557414826432672338059499467959057786992036210105748514737541366046144932894504709523103664572321540413187002105388501149718649685382843017578125000000 -3730978679045699377711271562818380870656882588597623183069859970913345324984270890345060309455969056272045431218060493918895964768622263480196734778223101970317139975513304937839617250209882985081650665057593060094652442043807785528162387141310247530494355378098771691565579027519121952139207125394108685738993136710743391212060943133259506681829373631948560400056305257043676553099001038069537084063365949357719455588383212051770666844916787775117378158444311064022872340658226653879731657111911273670445969085442347986853561679195385762700619674409052706209877214860171079635620117187500 9432730696796847903616373034011388714072779399606095483135361691888238498170781820895072329559055963402498542883586940725901628180106429997499298303118237195519960040114734628744567009351562484221394796183155012371272047280703705557657762808220925006864918756427057031572838880580045635878684627295439643336619108676377591551931843062925900608415568961017093209946115825484760439762618018952213559052478415534135055341331095750077302057225083678285026324430424873004226469917655411805422445575443067931915283365377601226704716074560237920867077597575356406878199777565896511077880859375 -23374288737819491688248866339452731260437986539650955645861797607425500098895496004624270508960589659474074172380589573300026861243342672597430069693429501476367307578429998035979124080173033382980096658914592446134337427124384764319911752536460597650521585571895982078174684624630403032249474374403740738458616015521530948039136987904486822567685575075284436503551370679047573883358255868058116892657688428950086780383502409785981603145541410384529082926086444986141104603886798520852360130915907149767706926424569106851803956777733009965263011320502073431271128356456756591796875000 56771481549254830836711907061202374453483357963433467345978417975441893480546603022057885479310112385784594786660517787621611164880561066622190666898893257878720707609001179150813946170657446016617141508574708862446930470510968363112003155537703238802693872804287438001671447674793695488588356927582747616948232444723223997975849797779466512703501766118217109622043906480866951641501552034317843595796232379445072343745382341217314726972203980154994997181170193001498659440259657274631174161525121152208832036426213649382542652583685409200739413471126226795604452490806579589843750 -135148632587604654582000677739361203232561301091636296027146951835367392271685765418064321457782182773994306940859549403195585246270558399987681412769947906298757174107527420103346039147820371794948956658175288994784291884577121239702178995751256264629296827970335321036140008386547041449482882989553712622898442514500761346884787667011388788530262502711570348162405585631620027181021758022348725349182465543902691447420606299632982907180169470257960356896085589233141409686243414917794431411284862853285768561462336231716550964100599565437255122901660797651857137680053710937500 315337088521888936812769901701539024433729660559556575042544404944829856036565865484725105579111073814496692757885363967907449957425075308548876552386974335831387022904447643952115127712182593138515028829314036400140619944439080052381910384790471345834346283086131205026309144493715233727008033465608491106894584616919066489538362502794945627637366839596544453780482401193131402312160647191874355286516071662197288472179122108179102873791214876015907212544257929121135478588552384813637261034672304509665122043249591458209260151626857938966796979229911812581121921539306640625 -721117118024094803558264349338151682496099163868537400412659962983284243553653942661879667405938887842830052486423849313897791656095318179234803366108236304599793057178658025395231346512370422098029423744766089397738347969622456024344324173823176702582352797191612023866263882375644791937262035050007854302275088312707748003399057195566267574638854428018170239521708677202732466463830319977994816452931796149681380041340118712721742671435114449069273947772172600911972672524649037820863415255218120812178208819948932441101677008610248975628564949147403240203857421875000000 1616150104193540457744925237985865279126864137861997656008012952780979559273274838667562027566971664791254185590833535657845896830129792194049597210286727479535553819264422647374767800391481435456069548059538678069947284033015041325546765532918035861185337795164444542806758615467270731367840423752175349928000773978393445938244720383311499519218196372514376670525232505707609610409826150684825897146038667899611677088688537209789700175070319751311087932499473975824292214525514792502807778606159509172265167702752106344626318451540569753888121340423822402954101562500000 -3549541488575566791687719204131409018174095359434593241279489598199138028057315896111163339245500468379852051237003565417334688538378520028233341583142862516760996049901778314238212976224760744046681432414604487762537440070753657643902484775565675728533620329888494439607823795229339728763709372125356691867583982352867522210023976178628175611280144723060140452652751086257715929959568016202010013371684962518739471153220099014381970167695839963151583237835602062937480951385236787152439276430780807162447628927601274710819378999104856120538897812366485595703125000000 7639027814061324699110817065226780562105788493670157863952275830644469862569328457355404641994077897759285555869662297750815853778431995530676613372721391506365811731382791925880949386111955995686376624009039402843472276185722732697227737798923913516111253645861318620837968857479426614029705757701282673482799537606233162184916786244161578128746304534059836205757165417926734260791019560318676396771782548477896148023255662762765921554274687009270224666945969050645576964281470575665401738063703270665693776609441809828681714533704649738865555264055728912353515625 -16107573863569844970474952194013127296072040355757986217226794446153316129647195328319095699965140149534192661671650776547657506627523173878373172333439543849641370038369191508608241636569025969818409099326701568527401863008900481468631642306572276391724652088627788708562440774307680877920980581292651493914769397298435086200091796035386611918982597378058794233075222918652118296203082321511201136502057545622530672274939647328922372998631709622671811961744492526802479229475359695855752730327446342242207389770898768362877850890413355955388396978378295898437500 33272762389237252628071064001764517531141049048847745928358455986700335611542300558110081882435345822548886534555288107208170376176305093794637216007621898972574621318623095765688439506466568601731899197628387585025262241280792112807497463237170149280506466196001175391569522214439299768986506628430084541137756264506804133735673255692129298738008343019724995660089859997579611231094275100824446016736331669134266531967559692451765050819993707109580607216212746914134981206683691693998775009865237523187027134245660189501569981018747057532891631126403808593750 -67319898202298450877835161281680737496407192861464143511606349252316666953179947622426837389849697667976613384141235978012432576957660476657758257996001404305859138829172641246208878725484788610044535053744310673068377367621198469150577589810016375147474680646213173270015425324673797561483091347810675251114133670837564988277499127669006437165121472601017920217530814218601788786091993424314134066455162738141041304938726855483456659306140143884113166052221871764503224170938122690499172396787584692152978991619254045541964615040342323482036590576171875000 133386186088645218620491174260954425722065588459251047771077320341443604739953020422001095879032470890907047065451981196747578279491841426999071105879742887458258310723303993620124431496857445105303132384171690663978978952963865367820412209674403106320406246654021767157810146564979696056253903072749720773667114792929505365294401806071346750612558470888714418724632940705336670618991047851161089643992936887001542847875095880427140348722148490632298040362463737710528930687658026357065458774478759882275299571119907271476989762959419749677181243896484375 -258758587161417645571891505732977352664358091455146390359740825186619792110382245574408293564845441002647216807237375904710831980756771885020412605221247044618664145018368288840467547640216003089022582821149152699952389430025700896889832122258141072614001972142680860000949466223837408565400497988381207713723298909606554846766337148202808150910960030232797765929882141866533940324303699178079158587936429051732597259824416567475699041172464649817013920036367024529806619859867026394816739950614068249455732972225119326026288035791367292404174804687500 491342724897106699861560174044991544733108661950623541058924600918256548901585544730716535815422138506964129577946526850960511018430171336862753956784107092721339642887917849416448222400158518308461031066310641043653076294711710104851661951147059677544601642791547882949884188280103371420740078504588219148119021351643618317596336488002586541797033603104294865285292685573479731964245188917904317160971386154741725630233518982709862855426075681126910101649779858103704633487403275266365092216248628299163359045564902771729975938796997070312500000000 -912964422530321072557986303260713852184399715121269736614027561620790144565677757193803609610039493427155195870465139238841933425440288195401305851748120452323753012818791627354414588552562674733347701751682392677265585028621760004988008308259380501548263961091019690237135369475382494869219481262462306832638622156450004964238600234577621684434308596745247741569803057484073832110493256900559550924215760477327687646356288615716108051876394264471703239220383934898693907849719215994969285267122848144278474125101752179034519940614700317382812500 1659432087004937305976570896733248598139961454624894292496084489154362938899739734690612278691919986112356865000927589865282736065782591429886375834138200714764374595608308734290812794199658843722349514873874195306087213332508432836673301329746834016986706268307609609580850574331465138777418445260953910546410709721931181368318188376779365865511137977027323433087391668308226000276878187016772876732572397764690923913093406643215592962661389694313899962779807152764552146510160971409185283453504767170634537354345638959784992039203643798828125 -2949440627294434514589283186814505512837171784223850554656124124271265249497451271448742080285091434753680545664464352230846768866731002822055566738410245870173951888953963839346122744897837073713123765367053137948898276073851300910465695443080649640787344510923495749457324778990342493844351056724922480249621292594306111847803966010542548722959194105173504025312450446230268957515574244280799178633861758333984333975972684273473087180737396203361968130120533675488551990304026414727086365203333716278333298532743356190621852874755859375000 5124039129154382525108367824051759095156746198439820826262588557075205373029310219633816822485610279897600616426378831985390508585878424615304986093861270685799747480497526013754245977540155441373989002254569876616598639241732536008125841841977006084831291719493482894283470751377599078679051314840199007197019117055525235816276710164112049059182902233755175428410013238024705465474702901125006407464057904713616327019501692375613824450522875896582422045195594980203516265604455247419751532479215497262181600035546580329537391662597656250 -8697087972669960977924100081952422610902234362365734439015899121985397683095355203934756016807937795180061468907034191642014115425206928081682845201768518016646206855572274547119878360355113911697704955575959657019340490406505817076034947947718159773467790661544474872532379065571209109341310834149051089547412716319338930948128082725582477744546064486100917452106405177897781333579676648349341769598234346638766855742881901860664391864478781448000142354300542473456821654975363628826041950421049664399220091581810265779495239257812500 14414380175850761700117450799086534098178075623532907095455928933379468306634166387939959186750556791115045867594670909827031052439338871231757944068461265227136256476109226295604443844707769273384775193708501527909897453563493499772989661401763823304834148795404224143163237227032357821769318635870378447175540662501552044084866376346662080948240030794218308955867072407878479080270453939552628676828976511348739344815036154009873710114318022982625769460259879631819161146871480712453839306656788732396989871631376445293426513671875 -23314424655499468022444225024867281500131438738670689649194896586088019587929133948570475419201617244477951754908859953293198392695667480439332619705631463424623912612336564579448403084313483960573602590678338322930666913471775381612190222987216175369194694943037572699275492699179269640937024247244626459071247297396863553629175140163104182902544829477919503762699577575037966200388818395243543664397796754957768895807305172565389807237409372266593095496558315738551197862542724075982092379888399591436609625816345214843750000000 36777124481093371911899678046709662561923016800715338366856453487327867459907223005779541563844382588369169771063048021465894508672541964629405460557764649020459217137332779152987431358206823091560524667406599997206153559780646583747070068787333389424863380629686805874443899001782289285131913964620392145472705838281729090866974658016111041248520484788598729925431965335793922819806078252786487723967585749246613931568556262097288982536546368528984996115043242109045612592461722140102509115422435570508241653442382812500000000 -56538292009425643593361161471623806423720356547968682053755122646432412521176877602797229852596080375028695517669049022031851119336570609064314380666818357481761710254910204752349403729982349178823484020821121096984527958414131113093063863583076283430199192408608192389281726929937458361063746240584823953558544346618519362705203452356827562744099798434808331626084886691417412348569934379448157575888442193747601393507131123027581614188167970559861628564708567865318725539523422862764334695384604856371879577636718750000000 84639912324275248078090804098594718487501170137859471731796477303385088009321312843294914652398916733587123049103207875242423287840183309763029552598000545586454647863399585202974678624118174425935505798918220133718770439512955242207868481008412731888578627036144835421026192946282205811611044860344269257066964274912231132358975049339316938991925771944105149825776772567221445713530350693040826797267532602205896214119859257852827338115750458548124353882458822776007215824771012097071931634673092048615217208862304687500 -123281738177750710990644329082157984131681073213493239987149049560954711386121204777212691770046838922914561771803566964377745182149995568173451372305096697774312804167782056270479198509070879497442811840170560228387620992701703934000810117155119803983798968297174475258714021331634228513416612614743825265372281714934234209374579802256555802399618346719262827121201868178105408686619283546644228434253044693853739693086381560766765382852813039159002266802384904106324625032778397049071372748585417866706848144531250000 174544304665989702456164633478518272336328742497849280115450689553558196794816307208564404249977389246697211703908604584178449704130720683850209421508647255698055412835519838943121973094527122584662764065468498531443791865950880242051457685744107983635392612866521762415882865800028628160347043148974381686025565693710859236327407692291939262010323306943900346127320654231004035529072463769529190693300353276051823361832815032575223493069086244927650750021992277141922558954256761154510968481190502643585205078125000 -239972811507143090063872745047558561858897105568799532003170662669768501220789604387322542376264087049259922234925626554058585637167462603727124094173357157320266621683294718631237979332966134100675044792764534926008595923781981897333849304133186770002005483957700541498828141669836971354232536751717563329123417202099765013460007484090399689856686666816696219762860745046605273982992349953075661046830025205440038811152489155994990614585739976400975140295344823924885563348752270940167363733053207397460937500000 320050374478641803017474642026418481771982284705462736283150473458695851520169978481525992515429335483288547121162101431225411454801789609246364872442041252462209124430597815542134937981814530061100163012725568257328657320548622729250995916518195565332506220606132725463461105568810733254613495157030081905612259053754408653659332049841643375060054363865658970858351905741753034033108470767124705237606664870180203568111503532931215939607924035310635274763465072539198735812604468264908064156770706176757812500 -413648047097118259974506970607615764738440640040064001799864817342578777020447450572047744640584010248346767727392803168006609705717698542733744874359501440564198511298312471577523369299850555908330455424281739838104651583164843178467488461478811098841490256143525587949817318443408458495518930155412576730150531920925258503543518536577938170501455425188024050500030709511223417985204551159982993984805959610199998181194031119962297743311288097190538537722433566970470231183298892574384808540344238281250000 517608802738583074954883919855313479690701105616119969593521199574410052702077935312803914515607679770338329384588116782990422570526192462764691757290136116146431204233870660814844574719731280289726344408753068134368542296016698090651764536460296226398734054590000737637930986661950245633232385390499132372105690346443056489027246053727935803835533062188858571476784003894063520672177505544109751628230805052244855940016993705389824693795210981055638870917783023184455259979586116969585418701171875000000 -626681545863129056995066343413379629389489309640806784658860858208829051920076874144193187505347468768324221725312435863412698651460351564610924945481105842750646484785867332276343814411696396513723958085483376761194075713688331582198089450424389541246490980607268681029462274928847071583107092160257673043914358803507604113363071986350951804484247101838084960826142450642456864458767647643645448325502344840829455421292317256583292557362129100398676957326890568644728318759007379412651062011718750000 734034295146615096998018004667984006352639990316087826688533981280232347035818350893029281410018137625492934262142586208748589138362632050907730375960217237907570130376676805263925512112877828251173333386043408269140728206331705152976056941511950217355356930785697540195045507200925804361266410994792896352425588376107074426242343733918266822381352824594451897692632734247654635697899895044405180705379060025517062647153535565696447312995823047797445905140317767845203889010008424520492553710937500 -832501663873542109796096807652254236543251746121922709397791203943050591754932886784082493835470224351556811497579385580425861485593463533811379126200175786645574250834043904742181082801494026574184446673593374939232367295168927921416142568966279104362286218587520363148579735512952785335237966235086999688530207826386936705203207050571667140354464244031669352451313881557301631112787698443742226019594623123763418110561070321116966626992346210765338215820108302978042047470808029174804687500000 916529198266017634249905482900286459199415053752131819067932463518014615854441083130489847763288736409625935012575227198727733496442705645320620102756184292106702933764290433824829389024356750609274960859188786878413118021291252524248677641342275791480097756674483252471780945564373978378572651556481851519051080429639750452628281582037416926831413623461351745114836873698825691053903646390836998854300087932031882735911726317521353387219360558837814856314452072183485142886638641357421875000 -984469302321644693120694776946328928089452018770037837662573131258313295430020766940125724840399684728070240270164238737299083076513807317413577990083353131056574788819221171172493959898319612395791774526177421042533461568243361388582017306177583918024521068501416925647086158227937886269031706256486099833245549951991767990196348070422873109162140146499996855593850519077374661910358223684765359753072296714809020201058616505213422000969885955132254728994212200632318854331970214843750000 1040524935813566652774243000797087379714583592451628740834572866689975784560101633681324561504827769992743795708359654422828651283308613224838438150138510483598207031717708637955389020358400343415535794487079481807514459841036148516693940532739524964496998863371973134506690804685325690646605094369195929529674905151669993011812853283076574095439698255814423208545636812745166701175065593367187107257342395486750352274270831185262725213310256670157238900742413534317165613174438476562500 -1095367516992481742013860474508868173396777191243432996472023206058229987236741515600770934783067361510914311960879504579292010324403755281078861650797248496860437335169957368391304660320499720392403430371490343502072891418440999399731870384385773774695933344347060533745065924528558547785299995055333297019036904830637141684103108106100464100463413388498853753218385521535255662151840490132046680589170738860254356709407765258768426225657877104424642311641946434974670410156250000000 1164470311759221930634248942102517988545196738055559224661166833179126662425453052828157658946875715263580612122845580504189843713188056892688001662273574824209926447755212545416866063907560810559138315817154646207552862843223055907597299113286735269696280307828069601441177052774193516678141884402044633807998780433250214388967812943309560268709047853754858712109065877126947055971810718051799667602295544636706597795263263533108643796309955575907224556431174278259277343750000000 -1263683442869352500725561129409207739340498406174241356550433549662108812854254433387062895784736060924371799416699176250873275297020492863646790150541221049531228901285195210137094651041544159180450979167613755252470319952860548769665402328764462926317962181277970878585086254029803501718508914952218896189040679087408007550201665706385947309905648566040952396119326887804914734537474809566212048995581655950277650776374717297946201344238659203256247565150260925292968750000000 1402593142714251731492159741255378976244633904149165930326923592532682333381667946297192095873823146535701740835173261723658813470330513239663520444527955749642966089510393114441403997795657896062454779257230525276162782174678051151670027999547838611291835551743071218462453013379403758862665399735502835385944282783165908899459157414060900292942168898125218828716559663434052151882488544070273919108484490294599819021704551051416432622120922246722329873591661453247070312500 -1577567139588025058422510804739541880920702135896732551203310974900725607944769120614523350418669560625765699680797475497907933029770631612644814194404548100814959259729804109295405146801532145924887408497642633020117767735189207806192989815621303447662269193730331368918024468399781827460971257983998883739273696493153218457008769273228547204812319404056660808260293726442796608616399024855746318011289049512411461662232382797618757130919675546465441584587097167968750000 1767580237813818700118769104909917593652626681214151782225483762654741274560583157776328952024390954876683593273882637213651455814280865212589442754085262277752943780384054240849695223298984182399655888479301933177405397097303483245606372529584962215656168165161933323099508182319375985029677233560641970216748011392338928903456216245505847499137207371557050201736724370239523321488186274271655260038586458899318099290357149920571711021466398960910737514495849609375000 -1936183290248416251019604722776206185983846994342605012423099278770545107541398693709928127874019612153802885014470786984025543483095165296428815657879972513546823071097722678538718207989370322021355949731114851147081081018195743264927534357404953680949003558259454516339271980623169359889349909512223038983345907986325690059011158204595844938121524610396597109834024599864273385777807593937689650824402731189337766492999243217454363730212207883596420288085937500000 2041606724517170160514977568534041176701161037472268260283859487010548506974307873457818812371356392083981312401771528941538621072231464136774309388478614631238560086792414308897561228324370312684331069170994256928372297314239884112948918721371348004711266243152870034432306559486560323265971252887556908962342483882386607271913446481783535952078478299513936725359996955134647971108268016393566946242273914221584879883069491013358742748096119612455368041992187500 -2053760362787226364842208864682868238083801730357039745466215228115369513428482607794908245571420001141470285186741892019347129334025862148290836180105180422814519826518947774399974260572115297252354360035772178014429988008124238584440284084323003319907117828499642908015232931324753737796847356690061482053453080904162019105825849807169787398694213819396745563240004395634117604169854946412649533891150576208429806221444913205687043955549597740173339843750000 1972560934768294677204019273627192571471235121773733443826104161440987050416955576502524974138286019713112516502999962878724564891226190712963404895099858169137415069746054899628136639968207394154811840256657733460305799514704209408318724906450727579613184558788823276593871271678187569840463278014430079688376339918812990936679184681927563726686159443809514767639471578380248294369140843245402134059304595698793038938134714044281281530857086181640625000000 -1838482492464983296958681606374836636582958291229321767754547783262731405678998016929986677160024451675077512412560103444756538212810602467434824644344317032413388595149265574783710778549145431972628892291439000051958438894281563481586723603361408661434702628501976096440699021669865761431641014970759873906096673718537565026670848648849492056472925897139484463412611456239505137809680777877005498955175763009864398078718750184634700417518615722656250000 1726045540372566023084419194283449578375965118035262425707432736877783327780025574070485357607607760635354596843219464155665957471278808149821001470908751333706492647558388925416557141157804514135217821906142415001884548418348096368483024353540770384950002030315243581273873689406207391302369547349954537687427187540357435795448518061609185038018637082403085314764804491518702960660377987833756242129405018229798551843146015016827732324600219726562500 -1716140404375461327529221292479694619322823281499536267075120102353270618807380245066076341191133142530223964071888953284965622649191791941758948744721679440194845820218451529309965982551372784463424013077986215095554173420579140061321724710137861130799306265843666684607086545129136165454533806265462000244696815403453501066272603200752802452077108872370405020322007955455711724079020244248173505247339470924927695705264341086149215698242187500000 1853402470991530357430740795009593618295529577185059183711599317880831495016573300862747191029689950846679970543861375847229388031251287368886251293772804469427054928647644617665755641428563557416167210207347340653441043029863077298719630541850252306132571020876912735215023066495054764140148403613092461133620968954598421221628979851414628498644290257457239669886398406594727539533285191956154476012642862148283029455342330038547515869140625000 -2106659738940266425164772403843775162615487508775595656048474177071730528892278184569249390229793955020348489164855613815241073548642439311860944900350760974974417086790232466043201041968524674169974771651742170462749628587902692248773778055796753048943658845489001230272971786416417832821940497853911563314537843412434330471233221257326667894537017108370032787526036206932278058576342407037541035533245725730466801906004548072814941406250000 2357040490247600722547710193310471573178926956902927761066257192456363715870772237736696674145112513189482473913205056521516293049803790798605674135839335489148781164808598667619064631344165377310055146155871564635797817413892123141308277592220847311647476644102587366788694979864463509652388183465023499166349319594261698728218674420685083786366338478804316367790404981431025553724902617680079987966257348830367845948785543441772460937500 -2432672404572913179997342657788900254513737249930735769533183883616751649422498090229221445630770859630838634808613014983822523917836256185471690051279566299446925364082595838335969906991250036057865490792549866501111120666298930732882836911260655998082719107082817249813015514746958794133006564378067362867641268880552804048850012057661296904322627198509581010117121637267245762602441887592630287429074087413027882575988769531250000000 2188442180675878512270655598631132405884771259231803450012983509947739808739158836286360680615913901515109956292343313550501618653162614307451624009220611576395744109503436520307198138704717678603866255969185956250806290093559446748921730360531450341696505638560019132452268941556667377584439799179069217179940988071541325817328380090392590602640061013756132392991547757994166111667182911260098876482516061514616012573242187500000000 -1600366108956817833172076181460813749402758609395228415404132267980427222717767381425726762011958210839741710792763413915531328414111815369772081767807603213753912711950487157450759217084430713028357504019239167258238640816076361548862136616296550346188004460402087207564516647518441613611120840098257508060914513266781682706679553866100253214738960447285832396582443376009634571641507272410365203541005030274391174316406250000000 822233150036912770534956774493078330460433867314263900787832244605208936450665567005183895260287780844716448108260798325229244406364119248114616161635042610335176543940323966894163747396303091091679957173122673954869079981687887017810793156366980969821959347152543795906042027034461183857171888017283540074433545148813119456258751525573796539367967115490846742711359729192666253948630974979217000964126782491803169250488281250 -155351464181849724997371366439305231583705836233779337604189155960363924811004777774770651835410322883270350063148248707675587292868394129447208990673888573728008989815569274361038774033279448871354057532792221116837029560207738945864464135505442611106833478446371556561978867460739649623438178282162116160842713660237945915227675183202514549201989381317366099114119581314620121940961450235363372485153377056121826171875000 -80594587956692066532158569994683862015605824395242227486111447276360849424418480040623612535495325752680075566209459999715282216520300671225334379768556028472164758473702197853680820662345021566368868722372797260579994402299430483663392713020849802043275942347512145534636465358015830307351352153616699571935468682208645796518947822629551655109411169479055414175227089320036142489067643168709764722734689712524414062500 -271324795382958627509158013912357023938399482414159884691328312332466743155941088605343389336006650614580483110264344150199661855423940860761924456925358207452082608093860163535237421463100087572037089019670235839918622106274761681265634832706050917308984058220297947414146222445200225508607378018303703323244244921323371365118940305889306985580045641087796460476565344474911278815909554396057501435279846191406250000 1068124603620192158863535135480909472860167152640649364057634885053915845532287446171425963406705077419855175361223903869047427475117707870041932230031693251379699322527712700185162899201766478379912729659267490596941299071241434421632011510781621894051601230424459243279182768337945758300396419174985582901576235089936122823635722690619093076616222698393290461615943927635094534700499480095459148287773132324218750 -1874197307829170693783006702028812467031571495932753629432075194798316785137150972848675230759925606445069330530346396526933116990355343136607009979512265487398112308093359433228463663549651426153481264731462215469693211506070358569932986841354614536917786544305042874416361332467760337087042413053206121289888508613746312133026002069516011508278847022415640169291472898194239604663380305282771587371826171875000 2152950999022754828244763141995137087708425817535665199930173796681666133789398238216924274604232011190092375785882332581355295475606764962071342343134523963659938948420456747257238430329708647731831731794376828380102441145566428654235200317056592018830921671811176669354441035495586046017334140723524320854560374698291801110859010471261061148196050455571847457615641818762242110096849501132965087890625000000 -1576121332714304510333922906313377004970791443005930683952859519135355657279437211503717400049666751361298899452485306321626769085390226300448209167199038101561921536770984712053865004496171496721874543036855038359695306266631359969513431052104700313858338459434572145989662380047884247543751890797888632518586175342100308032734656282789504177777220585763729853064074593049781469744630157947540283203125000 284653002988606638345169337433331351716565115402351118868056791673014817525190128456856119024869292715128356984222790258295006167454965107902478153640678868674970671405273299311769903893603328516067863153060956153825283201949467924602745138734682357633686758035088236591607992166078449702976845016539555756719297970984590613975716535674420684889329575333966277153607826733150432119145989418029785156250 1097463809546209167927755123391419395944445357285131702269998026294481367023685394554847667661224064092299671652923372196718117241417196599461852926259529472470669101531440844035705992673251341103055283040950866439804532783433467889758884531945941516939668635899961690143921001121780416283634180455213463078123725313970572990688820190157269197355480102066757619461156991746975108981132507324218750000 -1782971078554053421311474506278686063070691982814388720973923860951589196966482571874865950418748940640897849015601360384284808462852490965044597825881947689582303027343908078355970287601995941778581019447653447495135931614254542568176537564364696648976087615432042513335529211946232145831842896306274031259583177428995133465514498798471561759512942315405309434694913761632051318883895874023437500 1329333895904328489513157983192562405322909262134860837162457376195765496900543414865628962373106980906068809673728395295310594081680969500489746761181776980115243775978330273776431260884516622411076279590932793979835874519338295095654245612686442134359134239139212533738212694702209343147434669704706483564526436274093182159775965232579200510221856777748339339950689463876187801361083984375000 -7287758438272710567314542389910620023925930531550284560904655627871723701385932182881990790668638722277877609309176951588178554621647966497016257505848884749791941695735489637710791548533727640702448513850798878150397743855302014009538591681807133246387037396836542096036808539355993807947062442397973852400671145781917695668633594243314647583920420914616045138245681300759315490722656250 -1311941548221715407009239432595983052155681031058437136997365139601220106718927594709504152334554402965651921812149859285663408423056157744064944620217559160275878552675422401457084107940335059260872234316887234777131784653540125878508882476433288390828727209302203948506954563716383207219604817398742943786109975601125936166328013757155415003330389822622237261384725570678710937500000000 1757462728219169815554892031240402698285293636198172388123287895794509812844333997678613645343824931805982907149375756468359099382797548487342409107993305434056180682208103968351153015502159081549949300392273718201720208862191572499759334560037395588306064632485453940437211613234578230059151296423082079161187894743012555811393608586642826885348966925448621623218059539794921875000000 -1073205537887614743547718653137162191567952374393562428048335009523429362614385691524881958059921889720829710065998345281581129901207321324523101345006834001068865917991297181663156180513875843222410493803249707882681344858877807780462059174051888067223809348074408265579552177108818120441198603502464164196712507448290410295067712296429585094870162720326334238052368164062500000000 -188872865480061903541083167446409772278472787529083122005299748260371137716357109954224872026812390905554984517337948610898548444149832827339554428541549963606018056792171851028342827516938236845367694813894424481506222196429326999362735139401133410982371449367266686438982642801392444615271706830530676247702929611656944143327364595214348796936576491134474053978919982910156250 1092905166818511908471575569496658618548126898430820964010158524629389387941174003778125617426748120791861687329902516032200111096888768645666242268540359413399966504606984987051988062143329033923442897998539547582930663265811573645076018432265080026308894031895122459231855986385505063052722543338881448304135439279196657255013142538702108907955334871076047420501708984375000 -1109973148100394242495666808439258127886284242746899821166951579045890786973500938809896113445058496630703139018874076964191537891749224072866210625252898909988716768226618514110512514871658714808552458431425116994370288665218411621687278660454888233925121025983791845354493065015731916686944248608768850607976844142778493033788585891974420860606187488883733749389648437500 375262019784828749097125694621291532114146869891743004613134319198884537570014704585372558960379471863093490992779262423027571616254747733400092847955280503574475851644796516940051257820237375649871160608523720429954620765522345302994262990646922972891446659731846416151432032618453267278689276326065811931452956208304683497975484662845246930373832583427429199218750000 480755332314014536950581491427867854561202356780897625453567622156035497911071420361094125645090023878572916331360874698469028212099232905570305182011819390424273602106111487685921681693760377983092227855023177158078282312935576039785751442815998616177685207537107534948466558143684744028978836148949359431711132681448516790548297628049567720154300332069396972656250 -722822445339865160547939777242253394729294749479161948369467223537893587544235218636298670128670732491050671418955041551161603019328093671938535600843583349995167150013822104366293647169371352847103889938520106857939053333851094309954317376284972208714485784625724179139493576390576393766885066578505525351174846587364204719694527057072264142334461212158203125000 398428403719697762068954397008408475669947924372060902110908581551266312108933728132592186342524956043839457558873581370842597963405577572506374592138269943636969324931492638581717437039693895035051281393590385283381462020179091898867291655643940679419565901767598652424695615511914384915484633448329030395109362668037977783797032316215336322784423828125000000 76694817529959772255336582686140862455632493160034652430891355857153840019419961066318793859191641199959679432942554682094787577229684365721376607316378215259546391757205797640320387028223330054235017098871661944010282791958300371468857269895682411336410559402279165151541742704984707825005691654394333156457880425194151285950283636339008808135986328125000 -405049198412285951353350127174043045301278988124689931093687750700288307358728076359320677994548175695292351750686959805640925631347172872532842421477655700490874858694114219937120160887286882824476261746282128923008585487105468173740039044944167427639792487142705907351983702616827122292356130306545843739585545731363147581305383937433362007141113281250 183174409123912555439091180146400452649004877743256856745435085089830423476468068477997506045716925429465093279634861811075693638357088853822987098369333034627449735828486241448139519972724139184040215876885469890735966371317010062747153761744545851325418347856730348402368684889200497676746457321080968063883864793695011030649766325950622558593750000 23789502514809141069908908486681893138337269389397990670686391454534036639745922618239921364905948068637376302696674858444952170865371144498555183462348058802736789970671569150183427786298137481293442101381449476132641177722363318442190622359312406689704793149095846732112973426900990274733543303489703615166694916638334689196199178695678710937500 -15351594825490467648213434359466921602805426960279547010855728716632829337457392436554684527556804698262007711267261508334980340629352732114997857511217338521251349342257426814958579629322555328821812668678337536884670402712750855756329452498464368670770847780075790430852989050945324661718049375175136617155402518619666807353496551513671875000 199931529163357915833369815238698894615728814171052280656275760381654974812187918195094068521314367427461789393179301851157639937906206057606422984363260034835894755493883964317105402003274120067390247153417143782772883478721622804849657443910546792608518842275411991160089405509235578379387884563308033780693051539856242015957832336425781250 -10763928923125495729211379174640494588970303243950710958909969995506432509284820121990277934020835664032520781971324842662947388163657810108046538384147803316115239577898619526250572699920831197418649893528750592477394657627812199176075387271082477476396592079157141688363584018871261491255911235676023807172896340489387512207031250000000 -95657672256009233836862170956471220500934991078608174217791520130400687712062075777517582795469146955635990516649963145379250394593539705653559296670009307410661117961673714493321648361340649556740318548612054197315361704836197174556865739099712348040139129453804594717970632497442784545477190150108981470111757516860961914062500000000 -15662044652164931125415949840217784858230755270693051913958854145399373173863077390062773044975583844883180843915971235199851645966567808328833556183209588760694640379031976892137466857083323066298184418423968531786974114543616534205549850238980205986248722222545874987434615303833829527691001715083984890952706336975097656250000000 -66468960321723489254800846789814032177265101056517602284854741437816815246036431728482468135285560154716467410005030874418812943999181195336492948132202397542206311449063012711798740697795731271092549300102085199299646228011428913093957483341682186694863791146697206005172473587581602211954434622498411044944077730178833007812500 -109784746974901609167163755013168593400874168197070500077647475244339205358691636621396481628354328906434195222512123677243626489135295685187513606395059422665917546769752902927038050496369026779703273890649709740631298624369929112443752528502113412405213723118963199136755916237835964399671695446158992126584053039550781250000 -41354965623007175653376675359342448025129987690166088260193542999511919006263897629462242943313961565475628325193115181401344274405313071577870745641647650022254593101491162717170352606674665839234617395626616998695760582101611879439688247246956471601965401298663400730325925380541363107766983375768177211284637451171875000 96842231323357700735054395538383412599308960836587792612114364793788826818072268048475166501725421719544734317859254884484229922415582531990059732806504681358115134529716430401443492884320092296592903143835991725339196928537787885805233617382287262136692556736311286552621683393349272250816284213215112686157226562500000 183306492570639927224529834428448289059653998986373139746204453965349137770145199559365947071902230568473404838756937895081807889508929544997039559515598623137132627559933408999622347715841290359734622571588288687669645109348611513630446935595445147339135774539686300349799075865009356789414596278220415115356445312500 102036436409514136274297773764675156883127157348325108653749342706399678938342219776749086228952340636973830649554789756974010145629220908257764519801357027762848533929010563682966051370319690297809536584851695258048274004046950760248273759392049694131629580174003860083484229726025205309269949793815612792968750000 -72941067332451712468785148816567294603153335400174026445272600727216063932773505804075606639349868406974147655648998955029900287184399486357554263626293705514765864135199412891213408139518545540672688771082274815413485887126944317096695821857359493049658922265011777585907992715874570421874523162841796875000000 -154071274359099165153099325479810898645939799752025087980716810803887319969128530843625015582417151631367630987933991234884459786445730476174150178198938394399333477187735508778334851894052492702257483791557973624984012978292812254271547738413503542159749134875896744989454134611150948330760002136230468750000 -82676020620269259412748000063089943986172680748758605971489439229989541903877623212032979553226821757991842577446691710917893573601632899622881953748515406811143339569097738947076476306036874300669531999564144681179775122607414098187459886430657516334642439875205616184317136685422156006097793579101562500 34426292406826635527498568467508297452179871334087258968941773853100657940622398248104163285702565390491715897080285696566504044943125058369298458816666592031092901933972340374203855540611751167662902487524839615038664213866724652218088430354063678234474450007285284414138004649430513381958007812500000 80531152286085939687842146248921302911223576066116263446189458193048990358361524950523304911452195970267402730342831685257254573897586177482505992505059856683979658489559419214274031535441132125945282914863321262804768579300823983386405769877502319717996019654560058143033529631793498992919921875000 42999954429109710712648235329669110781787401959538829767472411698438449247883861815224450863066776703737892787008264711672181572937840460756891714165774293989081067060491946848504870996091224648918905755519568444662437128508588783221709009261464652521325668921292617596918717026710510253906250000 -12116414828818687177302884467857962843524394458060078574381936798132633501940580153577974687557955461160640332531334579506619634936528155725418580184941505994388750443600607453692250148211689236210757003053290830978580511753062990133175020672418509184303792025616530736442655324935913085937500 -31049702889323939986771317374417302423510209626864241697735853778117485265024699860545129764124949015930879908749369931605145456867084679134289686409139284752265066490782840846102832815501861119038290126398098842370481437106726185503812815357979615349393043288728222250938415527343750000000 -15831608357381367856563816373737547830832497612965090907946266785500809676003419654114498469411490686243875723505985094214867254709279895698312079553381548228101244140537735276043825165898556291833000401820359983777660437374767188936755578712589631606988405110314488410949707031250000000 3506261721536669460580572640405796794707470929359352635903333741635817375897959128733112312488425919828851640288114268664980497437906038611839312635939134466744106763429386905722518067936822595524959232409935897817122668157188723948467987123756017808773322030901908874511718750000000 9197402019453678925893403680200627205026732250799149921050877761297122121535085580120491211195778564935214909366927043035962103248607594881295566684592532948434171301895367380149358599302276556648055997372943405221762878197710916143147331230922603140243154484778642654418945312500 4466845800190612932606429345064727073514606422834565904570906318535543006718420395974268783274630401604478796210055862291698436875973108357110953263588165065199689211797721937166868010085020896407753623933381305968949939144680929452649320587909187452169135212898254394531250000 -794640039510591530795326773999359460970774668880097667822258309188310588604910400827179179831713830479284431072259482747734350893631802044454012704582756208821743728567441098437848552566000589588716972672360931300206130572521428558074862991134068579412996768951416015625000 -2116701652531781497003480227253168220611267235570459302221631486465905311627029270677845888328685863187621720992197800373247492418680948896337211754276035804831320517196827232583431103428657827240525065115781205837730689336886186202590920402144547551870346069335937500000 -953619891756825438895173602301822410802825394022768102237853292853238033807987369672401200180024894233072873721011617127072123885080830817000189503219585828940795893667899825398260885649842866307439148567827032324281131072957889971419831454113591462373733520507812500 157163814231370436836525389465555687383975709630243855916210128208175559716589793179224812557157514722466316715658889742897248803312634426846390401069744985889031109289674730130050642334531597985011250741792127145563190762644900644318113336339592933654785156250000 382603010450569067717178603054365632365373114642221753466055198197345579814658867384862071176409850343888533572441216692264947486674986275202052139402816827554193231378310522663283508539667550057501356330956496037097591678133312598220072686672210693359375000000 160726376822256856835234056911761621513734142102438589666741188389282039624166152771549345613093076108515040472773693798524798709337315049187864925079672965671607703710692967301226675109456958551405508789152197296132285053715804679086431860923767089843750000 -19542183077115398776960719023140157924599855291784785102557411796177697659879217970009142297879767410661693985409242364178304712105487243682067349614440921423694912600556453250279538295135302768307226081743522335537610601363667228724807500839233398437500 -50824487041987403119874290206804415964883304967103687085330066671415459363172924341881424736472889371403713937442734267184020173255507436713230029306672030319409141854179338180314132498959806520653430760275232058731376127980183809995651245117187500000 -20599294513556098734565527886971884035117382008306420910414696418850475223762850130117575794052145346196869609943952977270929726121837601495773635233110143044759033729026697480111073669871743852334151892412295037360081551014445722103118896484375000 1373024633505134790684956176795622271487336891050329917125964372279900620496044319139767663491565650593392277418555106580300384008462045129333076127361113554612467989599783336280086245255852057020043086033034285264875506982207298278808593750000 4999806847302345093301623423020437310101356738988246075488170480035534187207590590742505952728639162598078817280764414338744665298884346767606995098595016492885557285617820173884069959447402450110255894832889111967233475297689437866210937500 2127232864803173782864278451260561506281765256140066120468478576869431116195854946142546433580432662120637796711394336365872028180908624763958258713384570181918488500712947659051133913365034158737820746409852290526032447814941406250000000 123920579654937974709873713296346428504587603136944461568173538998446916029978597783517442926374565928876827303236921125120050919297728827665019129102569855424590181726065960533265312365355237389508147316519170999526977539062500000000 -277049991219032481555705271758173331107729131221260666391933677602207669878385388975972622252681348081549358189970698140214617548672814261496609095527784083622015026654005351567985402848459663971425470663234591484069824218750000000 -139930375054667474878145374073701946349986492743892375760039222991545165976901061547716516588492162492030855056468881157039954713084499784063356932598543415208900137013005157016023317488061239455277018350898288190364837646484375 -23372501489342319585221489268975778377882664485662163211827617314750687521847215882885672728515474440660257546713612453119495706257357103184324471557771043887839662193533700065418444319353952209894487168639898300170898437500 8817084573911060321479258623870039906260496986829929407062984065944641276755808104338538015777078808371516877922884832844192856071225934351845726068837376953244749181273539139303495804078636410849867388606071472167968750 7757475492233072083890203851528459651348729369060788625621253603497337018559007286775323194225760782674303345187651805999539743736480495402747338170461248189377629939422874298663270309361905674450099468231201171875000 2781090881847303942307580808937794473525079350366495925924883965184982160553368012837893267182538442174680971138796193155823994338366301700381825467894179160339609320372408324271159330010050325654447078704833984375 389000672119391992155271545193807404963761922234363678431741787992463669722224438373510226671992819349299541923989525569352596127753292838585449186281108711592492400934002898580388318805489689111709594726562500 -145156405914210189345486192519719039336706053349460323443983543602834143187051931897639785577491397950167782025325826692412067965498925313176004236527768463171316423926180994749302044510841369628906250000000 -101930754987081200499820145532641569965593326748009545430839742551982292395817898906818618456321704124047617134227078381471874553273375044517644446429739394744389056970536244079994503408670425415039062500 -25837627769319101666299764177643078407516920911314254881298123933743918454205781510394101103679493741643908178022240090474865321165327566172624334045997039082926926555703348640236072242259979248046875 -1048400277157044975625876748159286330223277395739364477355017476608757202419819939857882099472272425197612512211247122424103601615076969487715664255286189094260212277658865787088871002197265625000 1314584656551791681302962173256844477578414517170748212378735386946924860459747364099186238786181550612937221609586191278649918992951520532308455101440610544382582574646221473813056945800781250 396367216363715718266087547275497467939678216829470631266578345152213251072339674256467768366290764289446504345841885530738407611582535560093869722003449150751757051330059766769409179687500 31333330871157171947045236406378022238039613794143623762481776713403345899432351047444733440961346068478485701385248964742522583514849359018844876518834516242087516002357006072998046875 -8957286125810325301363379818038509260295615240180850537006224076182573283979097607577434409726520410646858067285488019968313592496660110051771939146345804981887340545654296875000000 -2678180396092997702555986235150377776724128789809013963926975489693925127623229658962975317103137889815572197862141151053558500032400769005745707366590355120897293090820312500000 -187954469528065478746300582448637798664616894665611178560494017869040636021368291284971574171670069440814109414965929174963208569828748775191116106182400226593017578125000000 36156402853304102616148382869170011435762888644086770508939830677771227037531262992777580347350068524763771704824633165603301063573719893512281904722830951213836669921875 8548095916960466982478132447674898122524665131254536484753812153416462427467781456438651015835484416125920639121454045823371222550634359841645493817472457885742187500 398057973368994198163435023538670643892797376739273207773708643375827585047163670140559260130690733774930995521765403493764045088633038558154197938728332519531250 -78132292423057306090851784497302938735911112932469032905892574793999997697562559790011627013139946269056343899557174940536785906183331993563918609619140625000 -11774077363590347518921453669804912676884498665365985023570856997664163770370335543071475918070962998829161083355118965029237302662087778553025360107421875 -191082501521399471973989018084897124093277992228207629494903920299449672605492464678284844882404780928145874245112968539471187699377771463500976562500 79888276384597220986845200741834871398671570275130319692907639607030325770430531819200030033346076402544998876434436920655282918487474328125000000 5917579920715911915117561670534050557803262487728627481292930749030364404136967187640269092599983922465337905260309401487814397662593164062500 -149296281771320753708850335527729775878870097858060623177861028106221813779764429589269017876674859902279891121503148557529385317656640625 -36067739070560956057435198307139473547344386099073461030361704850982923064866698065211475398178767495860889182439632340504638763125000 -1244625478550196511374825767235400624039320643628903490104370029329258010606204903825889497697998714155686352854439623614093141250 24884229129241958334464529733951714755014485638563858035534196965870654976933497791907724107834436272423075930098259775494500 1716153733051169540307898602341497569311343837142335036933392894197976205305758468407429248816168018787798340006776536241 flint-3.1.3/src/fmpz_poly_factor/profile/P1_flint000066400000000000000000000144251461254215100220440ustar00rootroot00000000000000157 2757808487144838302895430769948248417729237108863869417509479459915767341323330697211864790593685466362642868685686280572196434680273380283012145961103760692626213505149801403142032630867205290294889677921852958863296316098679545758264555461523658710938789459422476508285713011640130252486568573874403279248369585169539213650618995126951019719642265868631105857663880266888615740687129117228288314207488263153874611799588864 0 0 0 0 0 -216322796837555313021432683645937044292921028613383407157804069297831574640998740656489092120685008467028608331849579265535298919026656996120638521170849310580349430742714282458612690837924997423939358531519250439003103809474194653867052412730011984853274391208927747745495001768576577005852099658803085546514828589578330785402902514368037827033046816681733696103002335485194130317912396254882191766550071245537280 0 0 0 0 0 -461037645433479417894020721333520318742787637796222824861773705209889273869538158383427629416696554307900636877857163108477972707536277062193762789904663727290361284224373517600871057249998734207159849953758589691456457289461969382313561313225919667846650484354465287838669574263259013740628682955721862333944942797610117714349319340424888849377188433375019685712170554798874566289464703683278915239936 0 0 0 0 0 -3006606488311441089896683017688393310181237526393515483185168180454254753097973363635722407434487318654611062408549655477030250215182281891825672566995224009864674440632939039163270907351880438387976862382953630127475285232095605983810246580601204355061953631934206101782233808526261885763004588113518320634896519093555011110157604966440212309535525594054654293518320014613131809110622208 0 0 0 0 0 -21667646451621122746329554641562526144092633323312599411016990419323105385099476066414168972485002571354506235276444763858199439264635997569307854261698326829531703857487029929169587379456251270438809123403197975344780862412222180332148184540879408846734261457232407592147312924337495632438881306066500258566449544033936294138097409605834038606201765458164323353573757812736 0 0 0 0 0 -36008946342647299345277533676465042992542509358162091707911485884063199188678585181307031154064029716715217548592392000646414311357113983560970141370451913098200635822787067067854257570327208938999696955706264073506673179971102683350614122127866850451153062491787093182867397127538003924258331826086311209206145468869911581822662684689775342390081444166762496 0 0 0 0 0 64738333885402706154009400777843384948514403975131509466836736265603889387062685884838924226241494383359395885853573043385536386037715829201209541872597706855188799653603478660006394706968635342978467902539925660331269747297563569373972862258677268612185384308671129076702627081272278586910256050615727493523124564910427355844022903201664598016 0 0 0 0 0 -26515019326962174180142979909852192000598024025005741295940640978614198820508372895246811842900425977352727727321855043342564236181262669572054649107156675328942799346600624572167621155490882477365676272092450671794375283335841074839674104033802419109510303627230113525211458922561813524476132216574712854465367040031027145736192 0 0 0 0 0 7206103572192660713378206441635342218917489717304647992423853713271386261468915707872924405011212678144586363155710573280556474140830016874081726445858124315662916567493737199217110913142452405975457031642733926038866594546019867393529529573884911052196182095293632879922014565430281245217054716156649445034819584 0 0 0 0 0 -1781067445792627012203411699914789751917558964317719007317246424900608235475797721781459407143458070618250900401160717537304193257391576912113861254338589725654811524225989470856639467420913364918958248936121424237401680876071173527822994467656057208698530802400487646077493116544189557449970155520 0 0 0 0 0 257785868023252499546719038629025522238370895088838886132974669167861057091364847664488796999614147085642953811171182098166013025545859882309438475565596820726130902460185426222014793570631782686609398943162320798462220946658785090792728810983258963716578939056822038673472371032064 0 0 0 0 0 -11784090207202014162295386617819122580975749672866993427537075993392758066192465164322165415699997447946113816444451865902475946080059998736123233932142195687596120620775313704725043713670267057116323795251403918781211539279372041111665200731953898028103168618921984 0 0 0 0 0 -516024270178733628499623062311311909026630748206142586718438261050317424310047984113834321775600080026192071968298564681207899012445940514128285818475704941072871032892579017242172498256146144732370397366971600828731748910067376163611390633039626240 0 0 0 0 0 30082639005203703587384390914836066417375929216836277495255127429645641088564854026651642629932602536304239256338883055950342516352052967456427931536708936701164689433642079716822865825451517411212445927909524063734481575283370491904 0 0 0 0 0 -473470234117762253449114353073575227253051133950080887048220406201777923641087656057923908627860421347898111116275922195546977433176120962969045561381814949718893972897291028710748149921273892963880265171252944044032 0 0 0 0 0 1716231160060069630599685050354626175015068955757203109707649882577572773165548338611188714799775273882912731234014004123562719620912869622981185312386637525543829470533595866145631607760885722906624 0 0 0 0 0 29097610765037817861202663659325678575900946766272112229562997159720733072202069362200879071525561150306287386997432893787696445551277644983772558101666007653602762940659581050683392 0 0 0 0 0 -359926316046483943753279829287876608460021803187136100943332906260813526077725113393005907399350257834664287535635450778981949557310768189387775714926393025942781952 0 0 0 0 0 1585164055408008634764541421847990628448201383564778254157208549989039915612818011950714697494640213070044956331618331201033480861222528629063286784 0 0 0 0 0 -2786147914453983786915822775172002754752542153742435684470657396691295332282129004399822009077517014397168296974400680697863864320 0 0 0 0 0 -38152084257499719867416104314045082135545017120806331924723488759543432766463641099223031913762482060169052160 0 0 0 0 0 6156765507729276548165940166182211314235431893392787456381452344509549569751736679901247307776 0 0 0 0 0 -6689833869884920066141475743520535508680559052015304499397212203049103130624 0 0 0 0 0 2000741892753026115892243757690184900091769801141945106432 0 0 0 0 0 -50111580155260460844584241578962989056 0 0 0 0 0 -28293184124737694080 0 0 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/P2_flint000066400000000000000000000157171461254215100220520ustar00rootroot00000000000000197 -28310353344841139100552181748454307699371666036116244754742401793218643713380030219421862581434817469922066224125055012815215325681116526395404676011373613866608161900350592983072884334292308619216354882297172368083029006308939618117161828471072924180575264038879779939805656825257151109494243443264219865294877386500916261837497315666484733938430585643406141600715650718240565303442163912954723026528570724465994296875 0 0 0 0 0 0 915001500080724490273678701926139708381334615244882865264611491309448298957732442920867683952007337394824299058964383439989850155971397032992220243024368120948624842745822828792711936583955142832819297968863158029395902337772286839099132523369188722876981022850698621752572070969426418346843877074728180638627770505626124519101882727985486576964038827862540064126043191272364714136814192087631541807002169938647 0 0 0 0 0 0 111047409699851425474472781218565089611748965560057356163638996125754302057308762178901397928575209379210788810849569342528342391749178882113338698284334230523647433044354657449374905984148944465200353270566947559938849302721896640452492594750010764216231029382738039292418776597132581726007477894710923384976114406819761389470497614887453753716283697357808663961887087440306836388048646109400860125838 0 0 0 0 0 0 -446342436365713036614130635720863725386185119948965071611207029365454771788822711476584787506411420422135216564356243037248906912604367449441283684192446673938176251135218686284948340883796155561115335823192701678998268848484659032469368810136451084165468453791123043378218533554595578195015983507458059878882057450574974574784497790037286318091730951313728999075142165392869857960842309558314 0 0 0 0 0 0 -187440093407889924244247131576894706827105923479576013561986032466242108109880365762800643147320791799582156022512637241916260918030778395894881518953921726871293149380578128573154399915594085473899886017850345945675964115821472712319344777151949799836538009720439574854725120145992256665059730410010752211709022446991249149391910452539320864648450679019044906506766076020563494169 0 0 0 0 0 0 -17102794394439706805776198127939060316155265269295312231169947645484747308421270732657492208139701219285821885435571808169466764196583947834680864034921001133742447449458024975904784478764857513616791096946478552340542833462046015413529864817057065008379889966945807204649255764622669389117701692136443679662367337268455584919772979179800068340016279258403217311651087 0 0 0 0 0 0 -275815447578474644398035255974304093333803507024117406233081251130586191058462184874523233093220062160117468825585457141720200965775274713193948397926645633561224672126011545418834288451598463778679890479755729969421947717408773498397537629829325228371226286879016209310715882107749116731036650268117840353997824377905367325679701580373416500519901155426 0 0 0 0 0 0 -3383392943161045860082785824856224602153833160172399482894339383679671124746195073992396969876936394621266742640931276778833848937010966504302629748926002549442884173154472778941684550808733346262368056361879331763847884626875273545761219240004933487247952008592968710624467830065517806091082927574314005384569585158552789842044795081067137 0 0 0 0 0 0 -108963684575873048260839944741548261543434811699059126045464951032657532484945711601180389252115722708970033531488546867414923370178978030162250135734829196553914201625936621798245438716493259999878171232188527027025890729622685030573371721830793460720840707992729733873280657872429876526673415594649800436851259689167481857861 0 0 0 0 0 0 -1557974760129835075313095154280642449218847022247303097842275420738179382995317816962119253003524249341590057208195376035592707716469927410115278092727376447412648334208226194975306770432460258987771576580664752178359234695037144807687548423181047384329627527809185702324027442678079108948993003438035725661956 0 0 0 0 0 0 17302921267519594345550354204620005258251933064318395484699258514555005078753672115284461814541960502221149391157581285432564438745616477372258534724806999275309899950109122791493615334671989654110910117630608555697797462878019640102860427882643327143767861600265996421251698005119199286586553382179 0 0 0 0 0 0 12654979874862764063686405487874493704097838775626997510710385090041481383897940304814741233413425922991659863888075986814359520864182401720473077822497367710906284557572723640104012779873497467594456854653413202478958783998117807115814839416100881996362051179884754238713497106567339 0 0 0 0 0 0 1616801576740305623945153068531681896924191661264846442757003800757083907864923878433546861284556282501786845098963533227697552677972061899297553194259291520288639094549747524572049843368202130424595286590124635094088025284970785774672224941411687072833679853620665530774 0 0 0 0 0 0 -8979068545151002444980930295734799420243062962208917290248502515234321524331501084733627060476606035189902558969738397466136892495105567603128268286401884777893637277868945362180419441594862370768637302515940412242207820297104653819246793094083033829181973 0 0 0 0 0 0 15237930941696373020352476225884779789101089097622553554094346974527573459890412533342297005948790683205934390343504116430221168680676088070928439821008879042108751135726779249306863964608992211279642832500757080274514204799536897054232813948 0 0 0 0 0 0 -16739780202013653222868337479667318685721853894040874758378246043276632839292138022321852386749059910091422513006826349115726979207744698487103871647890519144077319091058037516325232482273687032520482998435089573081629782245235 0 0 0 0 0 0 22730743329291107575190842597650036607768437482685721244829659353852422465267097654367390318492195714450709105069357733772778931925896656546604353495729197303916402530800440253922853757501382392875622128604816864 0 0 0 0 0 0 -10149112749478907554121091144535271656499860465648036172539624504562667340465652074646125315554645077813351946997889029849144241548367293525419015964987475467044567227919731966971629357366493817065 0 0 0 0 0 0 1859486774419660028159636849005789378630471918940661844379316290916898307352617928786371418389932742317718376717705399416806774851072854480381450330217281869105933514602513611584153 0 0 0 0 0 0 -594443216049251532716576982249995057259973022542911996481110835658629668923547242843292207121757297770457262521063333012093558042424422797852120247504691594633406150 0 0 0 0 0 0 127058140958638669557234514587109959786512335400281769148240959896345418849011806828366059801040589224211014992449039149957945680167624982550527769453 0 0 0 0 0 0 -978726354690708301718756630075803883963338759201505639564187621067024618919256291514988278247538800755582643504666083999974573798975 0 0 0 0 0 0 1916996027823831076174097616159892787981852201025306147821037034505522239663251577762289809221448026839610030948792 0 0 0 0 0 0 252098403759613672472548305553690793985423247953408901705036389731356107189863147816431830455183 0 0 0 0 0 0 -1026340195144569567353200593701346304300220688115248179976992623563484002279631 0 0 0 0 0 0 -148081399489442422271064380564577524511158844074841535828342 0 0 0 0 0 0 31740986257347426501430215023807359061062 0 0 0 0 0 0 420105788847689050183 0 0 0 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/P3_flint000066400000000000000000000425011461254215100220420ustar00rootroot00000000000000337 -260592205470461351505577073942438153087740965767777033125731549913233198374402714909467249179975671876894662816284552999977695295293834779150178112694894034411652965945292758353365558744420419279851470923181045032510744372597743103624930530496075117562151845244942758035258213116085089563940850384709050854448200721846157079098227475350491690779743239737043596739558493386453137954957559489234741672831093289323217104846996715756783844394818240144161076898848126480830288923324077467620120385583864046443087322432325250020257196081982695631959417868811616204473734591285127692910766124725341796875 0 0 0 0 0 0 116941716539847294135302104417215395166527395107192969255303342928149879237099227826133412401567253186412030897103018134982718169288437076761105073208698471755943074894461420468247368337215502657215351267168853259503104907286182032621201929363349129410450902218145554543167404933588292033254585294608380226994022637526738956498200248416659145424801366615706745527553248466547492285008487911356060834299957689701824633704633832348888809862533451855072015494571853594328521003545825401982843932961525744762500434298995661714049016992481213053006559262620888418022732691550713567491070556640625 0 0 0 0 0 0 -7224247278983622882191419074899072242709334383349770608129736858109903608581359455362240062102927879378796213353136894979290173822354850440872425161134334099500661360401941484580613699261277814931189809568609876879208564222805121166844440310419623925957140719896632287829020996191654412122025911326589750365940301131106434834390066803098683981307071179146558687979163232558173213306572899562432891266934499335808602571660305207189124701418833002368093613766047653448836394140782176569571638062164771020881782660525802543348843783377764305143121633153853321130920827825773205764740859375 0 0 0 0 0 0 -26859662564206140973099275264921352114626308337605505256696343878971641066033056474453807748626455042047742429631792474683674900216199173012275599467036958799901141189116024352482102647568960301153397794425918057407386847278070309173833555076596826551745788436328105936070255843831611545825135406922294334288696689302621658858555870897216989343675262571015150899280939901549850973785274811733536606862249262873392748084077272846074561543959917466560820511128195850314890399973645068477752864164517072971429560348709149395487341391223888371180035764230730146837591233414265855403778 0 0 0 0 0 0 -8631534765160638443177339649573792542547190810193038082432682417774632362377191518648003716640709839094677608555318248727975883802470591730439491560755627513141371017404889920568815584754265774082297226630664975399975436254559093938408129325619354828306467758470747919212615338603668384152346182914794187525378639876626321647150802038274827073511035691573980746211490336146036307791967721541072060657696632911712311008500347382867179332276573768391859485982483031634649333878269592243550023091272655052944289272803225708185993405437033520386607010049924054280219268298104796 0 0 0 0 0 0 -343281281890226098103345751292072035780787699373954041074399171064199640213619490112226182295341855053750122402136704014653581249667363469713061230049374587511779370977215705653390638079941528770279881162296030872185634605817930152898921075477577389311748571891980493600719346477423266899354199371938185438065479990926885973179192697016532463944634628627360009833280262611176384568288762853234121721226023574430003087713431284947433495825248550498361671598706247071268510666828088920727864664443562862223775065887418651976600157949272175475924556863398273776646326602 0 0 0 0 0 0 -6720786598611746394632931101064222501134482560341683336228982363549836625643298237229645433856562352581660769584426792291403058748698917455483343545373841379359593970799293202186350255712230140513509540930636578110081437812279222654795041605891313919359373572674147446895394272437568884059263034103245288227796531010778355266654013882506237285280368525626739505575951294121901815169642562958409879752456944474767696788336300823649968412709052695516033383161638881281200687983502246852659047458485969910932656011869857537497216724848323603191517475562425369507 0 0 0 0 0 0 -74660334243971879752513146227326906265608809048145831659436111965457671905023078254133444500602850842941773710382004680275363822464407281301799403761339014982334516230338853266630820186514092287531559456041290216794422091603790669232878609816767804166120977381589490169545849435638590315304503262971494762180806722307643173792660232839707221858200526031805207201647300704171927362672929259504970441341814823728044774938682148378619375906186326809692116053881567861379732210719462147892737537020074248476233131100325037903805140965727954139578729914462 0 0 0 0 0 0 -371429161960207467783378923191251508403239554430396160327767360918282103734185847032636663931000848188943769010940674019708059226887682316339501203264462316099303568912550694844461150125526921524697581404361725065676181475824419542188086570194072663079413870776849712805779435995975525692616905528711363702770971724229870842093206770784118536058973822703455843604092646459835211598257951857546932549394725922185108495131922710494650659206183638460419099227794391158132459350121202567646128497551869637962044382275719995265596349172110288663090 0 0 0 0 0 0 -727765376726521330790175774391991146444162594054850528110792960865489876712740251770937068009638082678860047012542828896447474472831508047158211376280211579454866447880458765667582407773373854870717836974984146876897646391905149982548308919393986324166460609316261226798416553617013901333397649445029063798728585275857250059238842486181662447379692150400448169854179766385976473612141965601830041452166474883972445658530039305771265947821011012126553375133418965016576464358864543316224638038681617404870213612165234320396969876235707 0 0 0 0 0 0 -423978745122627949197974286054678251634000596477225524521306173617029374677285617135268520647251135648359578647844870444706720638120934748464155119130371052357974658006130393106480427691318498158253468208831880997811458292759118747594110232321799018407648476010128616768000277285626224770182316403218567883049419830000142688151607327140515723561968253983832777121523432686352023031754817709802725468418440834138226077946120969036887043338785891711584717207467655413038510197735214231534966316970389118070719307257095762517845 0 0 0 0 0 0 -217223455142706232449730444332498185982589223047380506128707405908933161579463067366981457872377916941000202883516709249718196123386958722000513746188539962435947585736257033346452750215717586584196888527595440311381990889367706659490304518399196552651074000154343984495867810683978383707863292713571614285410851621509356831483780762386420657151346967011828392697481254821097677448953501730368589355939610385633395737864359773724289169307057658066084778998859513133708789606307714120900534023864548483366939414455944 0 0 0 0 0 0 432999261468210173792513146473539165925896752059366548294782094731973145361505107969222653251893208433972627083231399554525874066328976259252687352282846990759353956386850992994420066898859369978858682749967839565012986075628315691706705133630173036783464518679594593163661004578460750655098292416105521622104018694686281927312653035423841258063145050696504259772565566940126493639482610659465652032597575317150369765589276729134307278773478419407103753995446249573923702554275926258975710023954559347279457 0 0 0 0 0 0 -239955291118930019067363633698039926382588639535008239327011296859648380063269017822511303195300808206989492584063600609197391897084471711816672738531410706366201952483103563312581292106568865005546085749424266158523258260962556793303741955234971402299831712752859369595593335067189007465300571469471202307410436481881388073032140993980392809568001246043158231213250279011355888747797171434928287072079418740102885482064313134604472415309356618415891532702207088054262633218044730881644641234756985 0 0 0 0 0 0 60339597666219303345503483294849695192076523892564930975112268954948642257027672666748302585536002737580712680143773585627312649749074346981814617131536534289973292947995353336292683487522343521625569115093637898329744124748753852344301963542523138699379788546535870872324438896999648483503408045696250410041215096554599559444218202943192807668767561247679411372363731190236413006496499754244738783217316455876325538005832734846881241580696968359351282525878758817996176690623257306705190 0 0 0 0 0 0 -8211321876963121027027860653193433346433695989816520019537603086125018863497460891650083690512441761013251975405324685072626284657117458953150429581301911533454140127858822782955779397863681725048397063749452768259157694187016001809526821063028776633565432300605150530831602170884300941158385194245393183607773395933932402457477019407022118716308918166724796577945711425695925026664975167298049856199701785134212271278466283065842961071268618368691190474272844791620661948697838 0 0 0 0 0 0 593965599876544610070883928934870012120800689558523242615511290649696572719434297105842090674754952875294565322591224155616655216146394556975999806499381691063311083992947186337420960540010296908011328021227463418349338313097104815939545135791262698489205644787218674740111470075639692164542679086574619801948458738249549439861371498601118115219341331832640315930438712278936456327213499706981261127982961712111373013577164799448603059838928075664422907488839610746833 0 0 0 0 0 0 -22352957191095603363448172899277734456587027052431972462259947034864034701774525803661428391464128481783499709406466668676555500834276590393385262194542193364855024061013349477341598528138939291437876713805297702521091258039390403186195295954230401354967088989470761691272998393821319846312581937416632720572941068926095696455404832266086027345151226633667017881123959204446973435396198798650829305336362961393702485104209041581334508634916045514201307157806 0 0 0 0 0 0 406460875268361740833235881492967169660382357203148366977609502406148923627665703264343428674335175998791178664773896755464687483998691327655799684634661922151706074598382776602482445444404585391010494556014919350823416667273611334642726423189963897089785167747937825745827643013872283924069622300169128244226172355661935281428530544384045624533716362243419070284229475406717735683700878673505684418265540854204676590069328752930250576436149820272 0 0 0 0 0 0 -2694247516765145273647139004435207242762030911311960940055283722288048990217087421985604502599260088653716520124950278073558780168230029279719019126510064371039009688048023728880961029793927906772571310809675029599094713012806165720792551654518813882719350692472175650443188368076644713833010876029636716458311037746276130275066726993802292727087123955784130929619809428672335126137830116978419800406486112040522121143064011960660595856 0 0 0 0 0 0 1016080000414312588657991894274654556007300117863094297609992669977124828687673581576436920145333523887937382721046712299680853016831053316387651997961802247126535145031297813969725275065539664647689274880383571137431692421518028048170359209603120964793443736489577865784810178720226869220238594037189254885218980112415771661369483642510773548776918523736551548660798232787098106279242280791810478824204365065843661863489967 0 0 0 0 0 0 -5073309583914136060000501355608262042003526980559485693560637585979409138416978645072470117040865613218029965217525811300703350250376126062555032045062944458242355806010605206029580822866797799109767044457437684188244836522189896834384051584830012027159002353288066931621421849976996562926680240672176456098851943794306623353554666567201015281941067448106296117595243136129600866283299032321733064304559996679479 0 0 0 0 0 0 799516033595039329158328029904604644081340770214958169341220791976097197668152580614925599442379445299414617143847540829844711251011527782820836716422229838346408071136228881936097563596053143858842271812784034113911367143508941331533388052853225962902419681611258380778147870543530355455932700484404875659429231423554165738071461123290918609552745014023170959519419333026228339498419770172611150537 0 0 0 0 0 0 -23289545395992239810974884522551180832030612617635736582085750943044983246926999288326113335173529030939623002381438690051990780485198270516131277712405531032854425644371282170990353467970134027999014665172566884509643413213595761082085918782452419798116576875034580005320062960750735446712842053537316324542339240722133408453192394547872633848971371475725921796374018217550534322627036 0 0 0 0 0 0 -2134836041769807581719160047872715792271666061574437830807997379485117038004351385360027267291424658057169814719486072145746180206434081241891061587172573248760423878056026827657974931326938494272547850174983330856683245429315229957582463787226052104526006933097588631975292935334001564600538042662909766525443936720246348401097638256278079697963862447695924186912400622706 0 0 0 0 0 0 97796402611632821343096776054246055934202591595680429417464152170638817378653028414610827903374105048133540349604508370509281021745976348064839108127083602953921397523351177893315496793679079360054615484678146649472111366303728794572524288342803646638739728760262478271403814019138225010627319854465558372020121991268755351519237400155555158863011610763862414 0 0 0 0 0 0 -10953304362797718023228239800288113795143871535533590336948158359815748400519112636227534960426287254203190498848142994201508369354141645690239869775464214769531293849926124435686611516519170798445836444103027705697582358635459182999196212919761986072709035923796647763462325405972972034126674675777510302846307027136304335604034377021981060880201 0 0 0 0 0 0 -72532706500348212903629691336937355928992988933432832142192655856891761818495897515644866692321998551211796630237031056390758397560283349170293959775737482571338718761757739503218823655823135393469521602620406995182586101224280450937496161478313204207958772276326348720130220576066301604274319936631555062506754683900812970868096283 0 0 0 0 0 0 21077791811851432041644785051906826687445203574818973718424205585652199727937248915564800060069776013018089144559503977951458018555828171381622362857045100550217197529987895860180752083641950335475787649468925066906463131716936767774301278955532289075724275516282742961930120961191177328405900248526290568111988413766685 0 0 0 0 0 0 -275796261447991174773574890875592409530320406829662708446494121234951680168992387229971099342424384880545494480536071910015501161369987277004304643764229815097601620119517292738796547727645321664671204210078649661271422426777940137032016136467763630601978478702811114179278732376749249496728260610955285802 0 0 0 0 0 0 -1418969447083010332000195175858741514070146805507081452588792863114054795936914152568370938901535176569941555377523253827328140580979952181589944047216331815722058930441381174319346057494537566091052454215986984276052763844001153154931566591060124970470588579892052884818341877022634755741658 0 0 0 0 0 0 17260622364343192168429875976685191712956332044463997682429290305271479250480632214322223744739610074786255930437978128150858496909366062376610868785560896837592443326180703233117187530319581362847882483659632163417378162243427577242442286048456083357326490660782106391572479272 0 0 0 0 0 0 101219959900996633233949094946652348610784828706914553392818309399983712813436863853585468789099042480348495226337932218678398500513421319694755501885909297840492104218892362613729568742161392221246594559547082626595120619341102492192862205901758666793141229235201 0 0 0 0 0 0 111803692374052663867616847343627402954611417369181962442152132919569913119639261568527862621977807415522012193257383974630694814564153148336634758795818205319630419977474551214190361682032413251836116116747753360413722371569425657142638250126458502 0 0 0 0 0 0 -121324733952178108327632826761594718585447846660259275352666197766428125827040755289771117334193058694952104183736433271115326054535392606770460152191360512976007870514926055726351692701174940269621471022304680871567373624662244532870 0 0 0 0 0 0 -186839754473185672446867398398442909554969374632365570586956292688881159196451011466389348290307856175116191611684567948340363825394337558516278177233715085939158708028868205552181404567996684426149943405636562567859987 0 0 0 0 0 0 56172882434076838139884622381957084447606288990606143592554242409667147841887993072459086368084345817136183449393664319191376231296143886252941229567578514218372312018803754436350215766519644345431786425 0 0 0 0 0 0 68665764223795454785500423803245866948874161727672261432840938970786020949360420376180656032648216455883508724909821032147508441553960283702329880206088447982895448949237134359187795233430 0 0 0 0 0 0 -25710687666034713750981443595515971770750799820199755943709794034030444891854720614987965385650225531497440431141173883069292294856892788140331799781887306743304574986961607 0 0 0 0 0 0 -385649994157490715629224909333143587754982787260916674118391914548679375535983136813146137401476802930874386470740372159950287132964944917286234610212331623 0 0 0 0 0 0 512830196478323729707784268689778919994173566530742596949887487000580244495295339564436413231163295682972508842538193515937975664717825201780 0 0 0 0 0 0 31831459952553361024110262340038246946771996788579420763223580753921539891516520439158678173797708059124328030622381113522444 0 0 0 0 0 0 692439448693496305351990743693237607378428238222782065389836595060804742155137376521322481687589098588564247 0 0 0 0 0 0 5897836869712628093380277293677483057021999675871414119809452934891216431385439329542210680 0 0 0 0 0 0 10749846737921063686663144494034829203813822983810125200770970466728389918 0 0 0 0 0 0 -50449114733208840967063247056186982979845902609032876026 0 0 0 0 0 0 20185830687801058494974033981407660065 0 0 0 0 0 0 12292665886268512023 0 0 0 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/P4_flint000066400000000000000000006613211461254215100220520ustar00rootroot00000000000000463 27880568506008832189633659698627715184997666995037847731892883512048059530052559252557338229190089483620504681908259142571806193811753110764317242686090389152000022424962420610215195120163792877514370110919380237905524710623438513904505509622812408572766980748570792334684854990765085104258700525195352967599656833360993289655529813961048132030453923926202136565922108898294510123777679260208331008509232022818869789137823271480229887640242711479935522934307315997099115222743531328876235677248747953081158793862509809790462017172722689840008039658833118584760800595483811982422018383918761743665599474226858306105469793640645541421245158423730626864152976213114262222814790166640485886450582857731605268841500408598864629539093584753572940826416015625 345194012177611165944616435418061893503667718115713108050129731275540132771814261604658609751786367069931088957788287553894610282900136957294586773612143078157220921126396728462848895149748144014225034342375380874764041492651565967224321551304048473751081017792475711175367299010821899425103939202698638677507251435554003447054708550325331905521444216747459241127284012680095143521941053726935606327998307368451350471717939341648312283032147343650529857173153536906836692210541837694832410517863806013802547699273850672788861102639025961754777748047768224013131450756869434268322767902508871370607895491187185204537240356618974030380582834736407993033640871477740833324785170326572002935416563761882437750415569014134994899450248340144753456115722656250 2131901081953555309799627805314685624561364559416876350927612909655513298668349759126346374799873577634700967798225253576943813471120764772017914746235317126271528550161962003566860237265878864699324842077993612383558484255783787218581676650096712391418522365274810890134777388801755531597932530826021345127546153297656223857374660591842297616575504609055134834668721285603296126935887351885471158715832104554363170985092832897518764616029680787012835869082415616969409760602224863489721735244098946193622625101705134957718143847004148325496838753266779505344836780399473929654278831753728651176384966198831057947332881335968275165985305992328613481732866562171459833181599753792269667368495887570338980530569574513827182312479635584168136119842529296875 8756054212158330422765950240171166430200007638091812096458939615229792217915916810592993223178557448055399322393131609265544277076893746125471263931228511289924940203380961600396312195811368686330230721112600548156146327571430922945203109067474654912875224058382901943506310879497613079725856122631693483090977663186874704258205493186864805297908838522861617417365324887647214350458555570741394641222785449588263990869858377859888396597016456917028283378963347206321666577088865291378770521980006706359711052397532720649787725336632789343512733715752405400337443040915385809957315672620623526086038101385773714110871558988908897404380705672806898699183946212584113487841961721587790992994400067523570836223224328963438569207828550133854150772094726562500 26902969620213309322362566161349728862708749386214058484884259899322522257198161333152844728229718756708132221737920006839410376063683155631104586080157035009009521919981006586248578683447839922277624945170925211774837836071609719152954031574366237485163752399231781356848975617119424110481738291843904214232589649352628383660962863708915154495452384123428218313733999280415016423386546398039895517478096604821218098697248835987248870177410735976994017559509078987633051969177771533331314392574133659587001332192062713851252148201153800557143252439068104669959392669992507452312810943754183703631289798310882450296659195935940867650253191838910100610934970634392407283123700749722114260416043647066015204967846403435927718061293489881791174411773681640625 65953043616232500896945474476035133964772553720728470924513343613138889114448886546885858287396244770304475319133051936702267881081599031591316848758179511986353119521714225027475232135542097756131898785603414318308930800504689256812227715696553482933006614679408674934460243735796878128725637219911691585764618045442318991249441655207366910684190195124860786119390718403727068591316494021138012003323316164545105303454320970816019219892240079433125724005537536135636661163251580020412127464516516050145753358556932748539243938127144509740756632176977393140918827431835069123505609297534175628424693577411298567797569857657952494314272212608479095960755843734790937522956226883061945844023841728812496645790824942357629325101846916368231177330017089843750 134371792917967440554001684118719819880683674262656961838187670766756399240473210452948312794194270535685319295675312302313785756138367921990244238823443085677330268195219446675908890554421653134230117458827736210835172681971980207335698400803839348262138541503801572403257487395802030020601234214502104275583897588766309147051238389450733107833485430090849644130331470703675865852633105445400602206032524499577400055343676439012685757239809818263364932209956283189322558459973218730905365036531208674716885725713003261996671197259351376247046990230881733002792579449268704732409174938788712352389162921430747163396981846643422510157926037858018048895437751975895381505193484176069426916428624826122316268780894027096235607696208098786883056163787841796875 234004743945087795664771315768924985605692387152469910687683576440202805498444902965119801511148262392090088607026964833122849132620628793364961501598984648499182727273897905807992683255635738687380457377621905804707006909053703224893805226704404969067527668834359484136467929032752117747197422932721722739820822126112474388470866510177546930160985859619959223696813100256528065801112643115708445733493503286040242095557471443508935320039082135614983311109785867473326014513927528871803578980211729567204532713205040340043503317478321870125006792278657307208712810474045017944878184179488194274256339217816612515947854903271607218484221012301372887630293560193401618440670653661415216581937065966163820412221928192645199539118064451031386852264404296875000 355559637866081247510621261300302786487831271380553739053966779674709694723335031628724009056720142987476185625219541070278317885511770068580807652714433481130327649073132811783812419298081715556395137349130368117259560506614700973320534324690156373471336924358847993534605888453312468388662004134742758123848061026324179484659506503222574323778074222074077428235533165115387545818329045869281735124067589740728929711309779807922861537729377772625186214898759754121009773414436755746544947548700236575583653456377072724551174786127966801530404714275838141084851819703476814734230665321739997407372382398729599539912988257330860233920063582060871241818666142722779366965470867506112994609098463453637268665846611434202722038567602747934870421886444091796875 478835989404139545556463100276536777442443003681982350131881766366822086491258872377190750316267819704799039865190660064036945710156114439279764044111339696148204192946363595498016147488678285375082585480803277916291092248768428139842830662425338376291054074726215731380420607638198576901041476608347005404382570275900972256087255084193660306085764722263193132272046427578078623001465925019138344495385563168263293648494283883456147789156602035552281843757210904284539833668042784573002511119182452965726615378902076891133762808037269295063738839963374404310706408659252650229788432861174338390220351381253876707641499659110406205403166591269948584621998094363866124397848897205991920781234055774233590879858104228330317007210542861139401793479919433593750 578656848435111534416815163144671559231775004436115136621894925922771347912082237801936391415163662065130071761510572050881678178630320665343673861907785712214489067286239206047884852510197114085800140775701439692036713154644384820494969218987914362985994753228876065955755208379330054761936699508807033216533119291778202549104997378294662487256945423203748790025195983646264838166483570480652907132476962094618215408803067996102214977111116660268463647009858831421259133102276540256949431645361773454499584236636554929598422738692445866422888059867424891766804534357654760335475572447094190477559851123309171888653785912357693028278831469255992009799752137068107445815918938515899607851836340576561734273362455185380288868941143775009550154209136962890625 633812737500766169243817558063735439028014509532736981768982015171704083309819032558431488815754388336123723799493908859861230790876725245686582898601283699869109941241550605082542694106620845652333430176147025226520972029667015737161213845242751009687621972000024443559275699284003139254187140531736238009338650243861426728170381275547213765047012589004851840440890471157226160012430142572418650228099393925045821305869792755527121360133306439622087729896360622682148201610731488877799230644088318585911734689262196171940654423840809582413170768224134324665059471223273367638915120796648563182106201414042884494835516738484345137368621334479022101388005557581569736318022991994056232654795886013940751971444299417120034928625537251774221658706665039062500 634444188819562622834411010333026637057952207142905489621049861064630896495913215718764378994708969289683289982868811914309553506164010365645052309820996873501002104650364082355322193955432395028863836993858624341844481020025227937057713338882005367886824978050054187562880926312986336287992966015717277463456905861642709736799629147417614502191302399786482852191606290728927075938640525743237226900339896065538141951624982652989933395071491919428113473632188904290531738371790885533177794054758198721015203595604028297736853540196760569786303631484885498116363149729034724303556471884828295841807642625751712379164787781272413681036578545934766969759468418135329132190854689422217703750836259732967369122743983401399051534847376980441622436046600341796875 584426395302666348500579095409974800992058683668370173766847786708166929241643182376430684536491235004270601945066849173123067378631643961837164710123636186807140513517027303004979615319095350629808415761410239563087773062911944535687851892476795511710793639487016780518192672932131448112342288940627712168726472977271984496548697003973113903142603375879878364996534856265994555229513933809171095818852447020973700415519673529289305583453743163122530281428795875432814152465774333646421939531665791863545488378001245783254358100167395804015533219295318440246521173091299749692371491809173917182213257950569832825022129481151667212457886602026215455775220747502583349228919199845711708865763222582470296322176865354985272480604015244895592331886291503906250 498349767589860795047159009265219556087336402098485900449067020894507853151044006722809294053578041208002209364672553745921456503217575751860404517926929196830323234553356841882339090757076488839757273258832395513148505234965109377938768286913367895548385094711715735006538106053369834932783218617433008140092458487934442580563246188408653866027759619242734033795765462456695286565965668656843531799311089027630354951167848483032332580787040251436526931541840990802983743953413462743996343407249340370245125854909611605988370281542570154005096417993833988542653404274272204360395256650373899762730332875051404340762724856407590653868818495646454240167771562268108929501979638427997417723142458315408211575976642468719534913539555545107461512088775634765625 395381641386701670939059448439790205261002771377273913512138155174815026829457144688633018742853869257734544853910527074324107626494727623896060491980132934054045989288542315258323388628362899560257610698888734054546138239041718793611285204979271962974219733903567740295187684939053170016961134606021245911711719892810057707323501006938665691434806838938717356451647148730177329646283503609832762771612930349976117977442829605705247313841937203273458748155891203508789746280366874864165738132043499514805563422100483355437174262037488296572290645243855140063201396587361454974311372877007293380663487082395957314632188847367446402916251338069406685278608652047849179533926629334935609444668320045056012678539388408454326195456022281920909881591796875000000 293157367682720630783333283592140517832497748353323989137068243485657597159638492128576835521357683348933896776278149263059266214054146580373430465954059001925486264602234523196036648946592724547165564912963863327750141462008731645152796715188297401539022253597799957838871041554647041228431388798756437149709122373240259996707127794209277166726599628636837872717002145031043179513102749228443915411059481094254813982819738360535534347814305332422512849040584553852677979429124896561376894344440891360623464947311445655013210632068683016177195808041474215171610089129967579335743765970978030389164787703066320976536420570193769664255007204131144952014743469460622877652070718013504625410780501988526153122020863799682895024224265066357702016830444335937500 203928572761693494036194015316855265222035786115800045574897709408007810301490768671339746319419527057221830062713413825594953997311496446430931713349762488617221745125046451849921775178370025135854681189631133335019425012062613713987101186631836697403993838615181574474371747032144103010435940967172899737702207739407870870591466817783764453779813189641370127524966840084176834531033380975111852199471889538324434490213594484922552250456591620073309099784829171925535020782374322303570316574002936769473197792834306422639721163207281191844158653969442754959019329325803723783318983946523482026201500075848553255507260344060990757660862349639826510388278943620790496051658160724607006835033806921693703923160963929970239574281693106649816036224365234375000 133550628902888714216582570105701169234313096596608290763638759473609654814968644290107209133640468123275756648455870240816180450456512580157199620798988053470065718476264150886319754154855866560956242010324451138273393783931786189524085220226964496765276683874907037868618226927955277817345088992042151346401129060447613129719015742092910885685216196956591199515241804349691284548307365287171521693620410143991618791243888759923249925364399373095514082577812181404752513307789243034031729399281589963448291592866574599093308459323003097086658767239182919460081126184591205148620078975439142175793281530435371935629272276502354878809485099101175618114108769867704417115317785424676523281721361467019618944231727796611483618219292889829427003860473632812500 82592426147662518854812683842454900337772289159060539221885006296291031045871527803249454288998719465885873364139982194778296120090630299685540080024384199359965020657669155923063537667337917616043574089590685259700589406083978859656077181599374962037212320699487691096125740621725388860493336845404151273016902137919813416218218727579629974938957583298986210467289119608866532038445483145505578217687577581071775431514662471108753654120175445103044112183160376630534714007735122685751655291769914079005693589355613241881395500501037524086524078988428997895035602179352896039669445097684393049128671350308417098374748026391290765521815951836597091412493460162813977807893605430923828353411976961063352153832944371757855981529659772927165031433105468750000 48368201717574138341997875430113214002558637588937654486262987648691144996605925822846068034726523940165994303857184276681795083993196059589513667886367269257590173574740267749082152348986601130966111877216421507431932196257439931317175266276489415840060530271990930214931076283710675789072020567491366020153005981312607976392184557815532509679026897968674852923598140405704779169561294362084744810436593698456267928653456671683057670106457548629627338908382611881840612916415445015874736384436883637415687383818706920418527756357925004068710819436581384032021263268567932263142905407768766461170664973344401668071005307576863554989465230023822413740553975890841979813385006407467210969251959619637883855307837389274959507148700360037177801132202148437500 26889785395040965835557819094010566798456898345918177573470380407730784982906812363302089492948033395115909395996308992228009970846616256093656117160347245024709561246201745085596099093681980466321315258140307515290208683617946927847555486545819081315648200925225535641188634433905835489218171486782988688801747775511297363266557823189346597372028902866284980745848010380673049432655353935144347057272832464666233816713060906690022503835155609232432741868827649640669864433615794446619427301457746623612516468597907376865904165183902753446928819325489058487820088120251585014572050841987119196587643739075574183770180085661749085035909438959273994744895086636296423074048054980050220561260623125502945466378389734577897073913126971552431583404541015625000 14223426350585311564283607869769102990413123297850402161440068861227296707373873458357479064991840426511062104338653651301550046653876933761149619053969390189836158725448651868484267840709315872409246304558875800794003034473051370887049060750150788389863013488633222822076370990753317506128962207159540709528713621611764743725228134772921253765284201302969533243592282832633858605440431486237079183052140719591642770788328709705220523570095707167036274879355205609888220842534912577541394472787647649559441417027529052726975127892436747459520544708431159148620221508574960455145333487273624596360710509008094406041849991487664701104382190115691354947198740405708624489606915873483609188298409735068283339446365685001423897983135260435563325881958007812500 7173075874891707452476178857966647520314579556785836017111496200933380828144646651686041976837848495860225956110187796883297719826992621082237278784046414275412078022669678505352531290581622799175657061860559659666663951271794401586187826594997770642055248144099136132180849743419180714886165385771861312732762403816025500775200253941470685835411158191020162405629213809720499159872715037438124235842018433438358669170315956211523297993871681748892015672117133996768280968474927340421595224273439173009410413416950812895315258079114292802736839248844236221714016458596225761746530621806254761779402451835617858482295670563312586994756343665533696291891198190193030958534948952256117022203155118436340917402880827176738079576532019999418258666992187500000 3455491619783398148418103068898838516610760209829877261069386252875385696103721546505847308471825427073504795064162912770449144937303811426361594208139746058266709200463038057155781023074474577342528816991101997500778575022874055689819201282358438680552071596744755103120365333980360013409344060103236910450384702171872619112338520716116380561259008234608065666814378382212173767806768492739579387109399884684853765314781654371664009567573440837842785527617950650478044030300669436339931865423621103267398092273459229191490216246546472820424549953247170898733848978232867389854527087923125834350821630366245803829005174751663960295970056802834390332560864062145633246276702155211959217330020865989788056526302385732975389606271198134161233901977539062500 1592831432492713307038647963020133288221248841763299143437400861522051810634527537884250157542156741212107701242289885530939649685962634597554142062251000153422012007835899009922145174890700437565818073056299038670010022610470792022030248967265680804637857568125746085257954039180716443226128958323907646449499877885839298567218210925429307304860927982331488735038338394075979789854783636826072417010210616981591418520784586591156327027742683344254406743267576861148647770463182419101622677458206700111147603322073072691303929331572896505630728358017866837815863108834059130258522193028419175130291497016593234665771338047296481674172890345613915199577431730896637249340984078557501918950190593612081109853911039003759665984026906550255298614501953125000 703686022504841215251433474913322459755220943121235698533468652923475068398879603675191711801185452015821109576568688672438953216117789562214308465326961717686109210849781105810455589826475559599500234758046928793243978608379015357965569849776816630432837970901728296310719634614235274747774274335463940136823962939273838655006245204162976421773767350241112326953761990291015087045409226150472785003052282463612603353216815222013700989720033904627122959858625571743129268048383581296675836546401278783357742154274127609451547239248741910148994092208446950745553438113962038060461208795704476655087193316139046280818107585995393702302207563403480664056929796197526997865671752959848545680416195841387614533908094143230444640994928822726011276245117187500 298386138903523502228504103696093640228739724636872374739724193234034406504035682173903665892163844529999949662478750073509283167004003698030721661084702020612297440552343602411757912757851799936053952340786520974913305993319227432529600983361442708655904662520626446927872893250149351139908429566737400821356067405180883309607502930982166219985373950494689195128519770996378870462035297855315239907807079303361299617545078069277976654497856493940351571688993856984378287212520972937330893231193425184824800733318273333883711241572022820088519483430037678172612796413687299618420148306436984763719784994942564410409374774946420840999229603559384743364682533897574654734386014431755940608958812874502998640815380944752439710098596248862266540527343750000 121608528949654118262619208007654415472050889542004858351387902499214014612966090507451950347762946050504226627507422770559615648138378102536434003038038588520186133860668305542134083007390296571740913109078961150446141616140062933811632221091924477417201702068966947497904222214019423859217954312656749517609439904524254250598517966130132370317055700473051875835380517740753996741471629567412499899462515488284163614388340415163770605534438774487583775961733216513427736436109153526265348081929536612670597479715536083146267342772442248908638244152852054529617731315316655978581677125240183645988745120372424099106065728067594297806002871065645783486919449625424703429223087293245999253199015198529785073212891071631946560587861880762338638305664062500 47696730589182266190656147900587081914147262884573095701517555062374101259203434765540793480437714876451637827670196346566938110890145873240149948158244094091351709630230919942900167880005896952559729650285507079242885395996180629914140096555081354593333455952957592019736276060352497303178210697925467145532258917465180404889140454951768802485576729035657257956573734458588532885340628457506531882481823450645068983728173883108471580078985914891524538424431485660008430813931194651498616020481488373786202687343700889657971852479856454130007501029802888285034913153078928701002579646886866494876035195003777544396083241070857695252471053380501492358991163593918191422276528434157557441058738726283263568159169114854567088826784880590343475341796875000 18024721493860433300340383463970842253151394541669884642126896408274516536429907539230871004423184445586972209774721463353324744250729004068050211441883934316336082275619062223651249666456130804515644085415066382745068721055790000736434696953739701656634318569805409020453310801237776190020400995713939235590673877808834091416016847747742576007756821113980752815977641094594852290471218518181159209490101813606001997851855053081237584471927714779584961600897847739913084417859089397712556378591117828022400109814034031899744480378048684972106752229633322605690218437074652096810838596722190887334330227250251771289638940297922662163314641207906422153656511380487034210683200413356776230505040444325351468150368952007782043312059443297529220581054687500 6570318431987462186511157939933424092308386576909121296967752621934736130755763005064638526767936713675633983560792311886402484401826268751742784090266337598771157195828466400183045181112591845715372689509478134356060735297926757841333141728138689284592984639346951606789260196734994578043086711839609785833107681861025578721213870609931752559994864549725504465413076794835702917659242034742850033844402773659298269893389650525885849584694824239008329277301965609772541418047209448217660854332527995050439549250950828930239974879089339345116980766124320416787568444726700593297426770869037013521687637155850093764101634819003915926282374987321242042967587068540843322774930815022254887870675406455906496795857983459656773243400304615020751953125000000 2312566535602290672311452584439857698409352363451392403195263385881325845022120773879591142579011427833763635039485692474344008557283486471316083590782421837077937824548535099894948328134842331258936457191602134479696593715887924388159992487449519897346450604176000389557576787769577073664104349040021337001595609366828155685674814705874418797034259863347969376091523412234649601684542159846118589645041255321675917269142487528182404608209946126252987146825085019764127723499079465766372862381971125368294956456601826233579461549214233788776733741634532593139792557715435375719754028824571706293361724375083851406151336039604347191922261369146778711753257038452053916577940884363318210771405604495957360337877970787312145929938219243168830871582031250 786713157587049938574788296244069533363273495384693541009163829544509529901948730780960252560370574133216983221955992816524452169731913365042059367440530459807488436721769904685095687207036455037162049380442616368951227362555587246129427174830193745099337928901620192012939993197913051525315261832981778866560274180648733287542474441093866253541448831845265717545029884953799003716556988448650663731722031670234809954363660620434665768303581836049850715352442733260787590313226453332152481487023898812033163667272795607134138192315667208565076125530056841970129588368243445221312475743388312412118051386580236164733887403644797904328517270401997004219396822785077350040130180583800851014246329974758179238575720311611331874291279137010574340820312500 258911979845982734135185117329345635876686021643946069846356391878840054096096590149055412301715003116380171933361739867959986039284969858146273789830090163021114225648574750141524194064242457115687401170659692966252623731536261274430857276899087088587207152276415733710302836689181508413805406359500831894359517276855029066122458148445691784897495364129408705159795063871344675681523396068601981858449197978286225666366208887072936401882675621768982288372655568187514099253233828745697517889115585237201751490195304478969333524690907167503882267609905788242106134665007762166570596868308514478539586539526306952288853850579629804297756986874099121263294676311207511485928184260438944199504870525388360313765974607818113728655693532195091247558593750 82504495299175045138137294288402697566586275090224192014276754475925529793877657202391022868638579186935693672423257766528899952924444677597667446833773438218284446391450648345562301269354899000346743243982996057421468878637808445669506987778611959248896687375512921304272896141043242106440895133820796695304032374756725857540124275214157548742929797964550440815463013539660680437006492165058682801520412016661111813004922334736533691787526244834593328435543320608535303151428705495286954244226112153482494101678066210008629376862711822388751178717877682947725726244990921140668511680384678108388671997483409182909183741190303500521685243510851305385777506172348111504049806359078621117968550440211625682809115958347337708731714595661163330078125000 25476977805779374395735852020677973312328871376173759298895887706837331143838891771755409122325801133033399689826962743181040907448460450123718847994015271226870821631649953332412879372871553911135300019534250586315394715162133892712203097746189350043251412089865215308498696388699651359880094263571822391696794819621102447256114787001141450672840398930382234800111699411850304143067986026114079720715008233369211098355686042537122293256785209526763485601614590824524399101134482434256746974714520703576004832601188234374860068190433563106849150157584692838061653009822365961913134333242869099553267571535076221623377646354536005745769181788663903385837957987608311748994967195166155191434407121335608042641050609207080629114850188641548156738281250 7629547339042934588757584660891992480408653455133814149600064588462420009894177591006646827941875180506987265544894988663649304272843667402173919434166044397565749634523619263322957185535417621027679432305356257685265032692318092204770614697648307621967311902054150855410187467945873038948018776136311516514613995652785296778741172041510170001589072808002820565361208874451263258612337623097634552054251736112945671085547808665387189293791824811420487752927238558567630455549252344577311378009927125330592935810474713636077304530205259670506374526910754859981731926346808001020949127691274570940076105383427815686981173154679026915968603969101881577419381980074950970247110927612666775027653178217517996678156274926897669496539820295333862304687500 2217420796685488223828335096478482718977993736695779467637930985854860452518150401717491358405355245835013506144036098719091356796191267284455872865544656960653689830673307389336459918260041776983664320831175856982559659119654210653292543901677140281942107558380978319886582565784927729256936055891915331690861278620386373026689527647288519198997934983180665503052887378934532460530135566937604097876944966838882918659320714604325428121248208806966630017610906516274198389969072275793793437212151178039756825893258650101071800667238951010143283366662010660415733158892946168511173305563386482840779793825195840015318117732971701330002436774126063125877106008503082613327654889741721199791139090693234854180897446389188442346658736174583435058593750 625889136999308514488406903734539580084046145434358854461069782310934806564739060891980348344936029546176071647592618393493728925807195132082439507786575975753746272443171625115836800010059807180711747902980590186035355926510108060335046783123110436132832427086646950214265488380210494694955471169493477490004418703366725869760084277583840031013321224930276210435336962311873692161380971699540665969265645997067886583011073641756593304368671877521372220912352140018352215110484085620094669209780352461198896273503537543402118885219186219017901229093213319764144224994414857911666172247772963919087187159816077936065825821101899885983412603692276730042466938046899840122492451238610705339673923619024292591485893537681098525767885673522949218750000 171685229867569258185243324330009631096805727509495914547728937447924443091483045300761406765419682859543031807944833020476032875531647799614319948202094211937334638946300050584590417517040752997841493202108906452736707431284836241217763506594034379757725222448392103532721372162816595977536877539323442531235970569116058888916696842472759323927077794630815995218431690791707519815784205274332021504023341293997978914780208017020070867006320349773531030386313201725602463135929790564652665373778369672287853485268779032709064345293073899371879836944159833620456137031951903406180886690719503635444746652268164073047089332459134495129998653434850152825650407465972455838292381379702073686646972893985416413569822749087138469774280432701110839843750 45795927729857978327614454124568123298795623356697019884378714185924554509475599199018699137243885931974649953376316171164486878256096492853494802312186820314698883506611219899589455052128221628095477815997541762751102334930970057823088778613648440350225730680418923994966628890963163082407824083091402800784512070762168654624592621027450414967874604677505414212005203999684144990361353449604158220661918618279179897974884903651059296958186118144703621623330689364189596824917310719666089927860294475870033900295916299701576896160774352403501407253557367202194663531088952771688255171596443995118261396911600832566329288951506454075453223335423221600059517201813076656505366499539889157492092802375991734647223851080673968938366022872924804687500 11886070544176262681350266838972832463972029623454462042723767992927546226570355597905955080551964134947553487009809848746593976737516584521497933868155077321316295828420798733598552062541502624302804588100279852744619229954056201549806374180339036469115723929808145470734147877419611498414509253487350706788582652155032625093861317356709259420526202395364898473742483931370684159141723416202430658942605407242493412281419211958691065564357623104165300522662603438563720773699466041372528887845754845040313174346539214146419701652771101431696908173423314499042094392489245629766150596865290423414533636227026853254820145657598249554884012182448844954613379665927636139592093377409764039046123553548226936289634976992400327385988838386535644531250 3003407136266177072790926741017924019255023407803268514094545386324215690903656177526304722849595167695916593151917955557232749898546501018115698452647392370745560673253391554043127707425584865430091506401213077192746770879974498612906093838456716268466804587547559754474705649271404439620334925892537288873489089209361371505534134908291057051481434127548338031765065923915448525263770157764897844881662468409442487678455543541510610064846996525802575332635863416815047845502395334127741851478098563394015748954658151923894071710481690849529411653261050142077546061976838124745593777065989463820898911596760866567335997443490317735491249128712268056505494375008578346412604219867090050572921994109881985279808950501875880417102191925048828125000 739248060724466364312573185601749071646124792484086263588672279656900899835364439166060154656674725445170997774567104883134793976064494837288113743811909472489977475548097343854543813413588490727592590695548699434266625157776745425595540250683878953920948234948932416270656006461014437684986056398591199015122899244034029165672661563342935739659358527404537217519858321585973069251823269689701136533551653353145059180337562146293870501283423023197142076756053650754822852969723501573823598938651169952437970181651838393631689582108054829881941864214716346307917585923357362291065418144979899784177276358522942088007050502560686188108261213690539291758963466830949445278888549567047020565776294289643229582880726703221052044626715660095214843750 177333712066183711627611704290095744322667561931538340959196971430238174514494760269219278072620178378914698146670913360670737705304763147564216010851233473540017104793256814236572549453721840349770769922552897466992421794197495204742115145147364546893108319484290205207828386034710661209215129337027365363490079541905220499326330869021911301459705425329120556225219340043246066258624772935622388893650134119791746196635457467909956582398137677980636352130416973259469809802629913780414017072304608146763547254085711020945644610940569159274631160282578277575418447049151897235013170692278893780564987818277110816146159479138840080678925013818650535037864694311195508551641900326337255984838331369695546611352288062070663198460543289184570312500 41479422761593991994831571917999372332238573792146944650334845474334045693454129225743659277493114309571805250594766651671314951951385633113290012486868681872109070454543449446181562111354102060394904245540443928318996605894000258424635081404045101574107012941505446621170935049826931300951878423916927289674200749292321762786499774878261212657043479301710580559515955320552017014314423309689506316647806322941400664888746105160612338515763918516582919911567926698608070652299503030817589619692231354024913013275618268464959084554966688171116338339646019634861169271214628787741814059292947367335719362883140189573975307315001299475614074582027612430059153379217482036980662818579082196241973102879167754303889350697338069120947456359863281250 9464993085100791119756023326040350308920254243953859077824326363441118423970999225478837551419894164373772775173551132070600706307528293462025619496433082984487130357884562013046695417020172525815927081846545472560957831704686504042823822169057815693648421980312543556387330642422492231218950199142974729585885754291284101411212666691169608980714914093933574913496904995282903626104495736494468380428282645449190101051049369912472607310238219240640424462895446720367769492132296010354011848199926609468114491414005407839075453990894450940513328928367143643939082040191351985515488182563258304137171388929081623265103888700632884290607334176814069203061862516266491982951474333766375721256105591232547308612718868087933522392281494140625000000 2107906451296435414187208683295625314639435087563982911376171538687507274233058482967766021012408540461672877597342955170555098465655321476086442781050141804100759585661669030433799219733852412134297272547254097347506416487022031949217196172608303181473369124619949740349814250603474091326108482614384969245284578232428992285475893724885932305638108127249656857692001435817722370945258336548514558180370981377758900304082607227365220760921452725829777939816701001593590263118417620928076823286091210411099556477013599762477670451129054634103499300694102195384027404104628917915308304704893800991791266849594044980593430993903737116000143240842930552455912662260395575706571240831561107499016255234037112359432593266265413152249984741210937500 458368636880391694666644368090424334256493822003527715567032226528241016497776748886009893297432463248541715627354259998902313199541388529779162801647709233380963382748059172259426097368737261151746461438548175935243582819506655691907969702597103251321901352623911773825289464410101591374496338748565718757214235315388678793448024169094078558806087173398771200180080006630753265027739031558676976448167473908920124237964331250576491835216593091885844494762866166088599938189152752039140139154593975994188272793965530146220724124107450517326672211563663165018370172468648313752530714515307982985848480147704748701029602610211071545701310622155039546109789470366956774314851646735416517790292217568467278125013534945015946327245208740234375000 97362658428648869612071652288798735137504457483989594091964948310957904407891100675768088094618226486610402457612426718870760021699025914759423465888554103258432430493617751748869055860176463385404935254238199695045670439943419150762171772940251318646649076732434074757738003054809421145764032776803834562970271782360286468291901362246649748633570456253433602381286000073593135483437311682669304670694016930634388272811981512187160725270270575669071613862417699073209782249943625407828278681361005843653489511299383710970505981263591483833267096088055885646295698990385926411608277846449019573124319442030973576761470179066044348224750867827798320520455541959832006294159629091099780641342612232507648788946609055402890920733596801757812500 20209620364593549582114306849709549865622339905109039541418566030510429155491535350477622788183961515064051267808701990960970260696543633957470061429543240488048377187495170563860020407754948554425685839566814066654503036695566321557336744950271670652963365276074482205432895638136110013658500893992678052031554509381734900573516275630355129235203142128458058103762565368489834285959465915218095574478703008461560673149179235815473233699965664397104982929230846096096541457129791037443285058437115936372617147415887193407248340396795393670517388894860203138194104047571238681241540617402796629718724977237485108592776328202015521028358879428418185372851801659949781726701109564790846297210925999518365869963335884985830968158874511718750000 4100903345007962274969417606094520802206298296141082278283381495851652219217886030601238402553745334032696610232417077777873969143695876036904025275846801955553341248461175630857142298286068396114024030726266524501353352421432947072176442001109171609950197792179087711623986428734036962560369676498150169582525776689238857942881986463512948931403541646292074387851937316781260168306178911955346425269371647464855739742099876125385903787949991086244827847350879748371794735091170771685044521927387995758297773768988640409476808368461430560158598976081588846899926995289740370138275066419635899126962843629303902453709531857434166812327850484149091982438492510239528094993497421102290800527249098371044133713368502265522841156845092773437500 813799829024773815956987028870267447660161379347764670234163521776103271449761319005252163184512217212682352007499511405030581744185191039230420040366350225050581752101520900686766251165130707733396925576412855872687534796580484193000938104503156661989391163453710102182028787805639105811622563207094773439579770734255945530572146534797752200491631350560183552277804397061156669194875109179827122196379510439999051245138778764524486151763768232898416874353315745907717988898355152743516922819972746188285764836152881958992172369346889278698879956569364059419981896840920489798162807029271028475826662405137368571362610691649453845853454530295485564698790898938237541216368334142597017778903236848413675796743358228325748210748291015625000 157989171821763928837033390652379200384065245511642933018368347920749834193726661988022815397851908924910133241383604792013386035010147148330283897804844583404990357540249023983840289598451931312654705896097059820674559701185404468369740468868809912952906940667826014888785123418915802944588998272123679336575169324203325294369167486435102006797429797738343128492434820696417876632383783235976025035609815166570810127266459393229050116878888926773362669300196900935682578903917141883536500205656842286455938888924679899193005126812394307037618964458240621712702981041705256913521782268622225792075428130239622975450738485794613307373630782871339268219946428930905471141537197838248640506826592007519146563424915585172296422122192382812500 30016356840688393981246029964202710368263255255268556590644989610188265247194909848839756596895782843109877622522546741897477350644718395986032113843310711005593353674353682480815611569982970801267439814529691490254906180634410365095576257964169656145749515819190319664552793426905402425465628209910811320307150625391340245803020800534594323889679703003198013081672408297747139020745241616054029287194487497520547126083501537172831269474171781826479877653373567934919388786998489009552871336629501544383525756725014954533684226165501660115696676266285821168042900830466946344692423723149074944118417461704074995332664157187138133395618655403046963014108732107545194188740615187645231174968341231233591903301186208665161220288085937500000 5582817223901367580314022493176835118847993772254286995128363372502782719591678332167096329667613589041985460157862055438572623451088373421208629521235166885888723233534904026231089641626282635213289956778515321386274456127878018570420294172717368250208339404346820036213092092160161313138911160361826813946841019438019463181878494459825538957644533975558427646472036272361109006827676817888282207932982252280352205300009825801340681742635235635769998204045425426328789697906505497759811992474440517639530266552515874763066099566228834699939007959139110123192610502750324633195981315131963557825621369799103832382935330127953759262254295178681806485423685282050853097510716261156081244539462857300991861104855565527646774649047851562500 1016839299253811972349504908790188062904965618111466918924295338083808181777060604649643007725443443403493492079483226475177087969337863213808071716302206758402804536529746244364160397248189481694139743047833670981858143450966016558118876753814860540701045247500825918356156950769124754550170374812592617132340224936305616002012841761636412798927940274832829296577731614014588242575312181442649561615958469097823817010436617481636506985084605484637410692428958133731935683100315896797707848224586683567176421290644174179246703525975555419734445290103587057798794681732455516322268977869045302280187826748099411302848480156972826712996112250441296001671826077603516070125176888083085892910663998386328500128854921673475185401611328125000 181421419006125452241406323711995246405851856222503690558420218833827620187971575648973435294589198487738843387729240070836200965413656661386715771873194005969690796337044431538677124797261134196344114457788408156653253338703884369011474661594098856053262681732775897148749502748862880936025479665468845916225847203195790685948569551975569519880871919770398925484056444691627180283360515934171592724752780347437774180107363301961495987087604129727137994624719941177239148911409346044054301492610853805534001494467730371919124395309743358276377916737018556902813868633896302515241492354807009984923575349458287173485776490876835752539762578044095929419671673386886046166769601396240183507614775125072425275726963037816097150268554687500 31716944195218921217396900130426087583361668190707218219971037895052749867568137757346000497317870532964212491624645854168541109429328178345462505544648476553308434552414392126481518196655644582862035811907892461516246153885857647076313390938427284888937706190507180970942406716711746625951199834039699101975711564622381068630427099275031063791173489481272982982107743137736003603000234326283604158362691827582147559757811196375070729181283702258914546845585246081537024190639586492136655129332838231274621799021912464151844948024442255275106728674446388028628255881820223185548892214804416143735425151294171540874855967669468097227299877763224731506470779123657742826786880864184390540732564992660471082563784170652681540527343750000 5434823983788765371594603629124310830782700752432940910117763512948832568469012326911610627133666059233128492858555880831492082567172412293317792396111376277272158653123620645532277244885854353158231395012122146186565821089245818325274849088440625210939868150919876111713332782930962273349184429179274218089534458427532040456931527154137951332145138670635791163417476905065042332897581612493288971529942878205207495136362255685795305055581180144108358015407794251413365071848649208011450688644600140269004051095535985626699710586785310375669630130577995416435642050793318914131121829838425960656521556928199780269576755943822371883011431390876822182678963340064713216504399218639296136859775191493255155904296587409180733032226562500 913043863197419129117587724036735343036301941498470369167333515459047552495294133924416140181355498394002385158035628383450030826228436624837421848346389246530846774943703651218235009275717379682714687721459777389098709744472589820261443725202119256924767608406904403661232277450276257059108397714053552271917549354921979172859634769603647075391332667146253222810762715945629349928180428896944889468170356754307724162366167325755711850767873191336188769404886262843994997509302167238409061440573874368583347528401774485443564714884580527178336272568362040654358181294113887738083886313462360757932247004463774483329315905507320989369432697330819835824930875946061627668036243547050430907743200236341591609442496601092328857421875000 150427238601043294048551416446127013063052658823973293350485287615328082849595201127426480970326628197560140252157925598656510749761757684295125483182354643767560220654417134854079571319969307790806304576609692979558384876679295645965403771525555822771496761337937437977579508501360598045086259040014697554351920195767368724247108468747964097114718930372186871469792359239173836988465828339526293923983472113357037181334445918175291607382397552211014449474742364415777747525116943028022153368247715600921736761848191036728088746347118171659623518960074822273983827350794891246726557551347446758480211516762825726649319403597091116404522386455838737365197227069647682880160421659574581893523070802582534353300129953190489135742187500 24311003620359854990696448102212726877246613690033422960608704273846585870785725318759463428818641340447593261897444794415838998937283740240336553738501269873675304074077126867405177528546858493197660402905925766001607612955702440393555699957717142436977955646664137440214320092541274688730763485957724628394155025080921772887445716216266560739195598223728056538683700618122699146781605664283491996338083315141364481922815718134738210831310750677477845651161853729298712967119578740943513831999932015125806106582067435275697955165251437213697696527264754502910816526247302424003368302330255672456392268214231008168277948117381102488204687163444111231725165997215680668332158424568418459499504689407143775490073258832099609375000000 3855050966625183526746520505277390453527891972537570756754333459675613969990398491045420826788591167535130135954833686091153447538957018094733955939704624160422013818942072688967343261905271835289226937801250295562702830300220058090205142763538048151903139903891708889847433657082408630341948608358446188529258705358377211325043644569306874129796412674240814878245765628566102014494430292414399797501034264445119333683090941570520961297716477289162725009456116890691647046818741303953145697700883717649652565892522362125080774337487260121763998255955960526032281715246743171081635079014749408105718162847129165400509568592095633224455291401915845122919021673808733183529124041132783236425365821375831537061716951813268280029296875 599948556238666903677448174189154968502431453771665097374458933462463199864388229094979806621488642196565224910921373927115815775315572294731976106793452541343321271163211518576137050735314554056049842008072717133248915880037170083828763749261249545617632567082160459252074907694369650780545258943648702629718197315827073304599997406147711961331285619170461275225544747843244490227164987663929505547698785359301002552965916494809961819354920757690097268566758316061920077425034998898369799471949060491223935793622450879946611314605507329758892013793548361013358123428328508869443185679010186766126139200292155138861681523806608346562523025892007802641268552714491593596836854472433734060811142649163282053803261712895495605468750 91655194387341680918337582905126483674504032259011954912885018359753605322213913465129507743434120521407183274241445424821720080371832601707999026906020241010629082782861871305125790532366890422151596362614262686614654127869491401058474595679175808218277192863319948476960856445935622912905642363582998140904636008563491393940973510234760378393189056493603542379053047966425150888784239541192803710413254529230611216147695514784612690261925263313049231744480126876983829504122011579700339746226411530610502058545873081694915076113321682118723126005614485817652906179834036083050675144944165823576809098314270704456370657272849981108174559280758082838776327326617156787354611810180340469156618673115662580233960588372711181640625 13748607675204219764031570130324845891228944529428125813268307665588826552793631184059060133368845074309285616684420243379092524701445454701296769876273861250567343161328192195041572802549269084077588713493540308805442017086724919153460395268009005126011854645691799387014537723968481047850235406305171700860136095581233032834720104911784833188309090269434434188750562202234665030043103454638792532486540360240223951840179367310038998787176800056715993059672809732931217595307904796017116424188815659911221342165516112880635263045183923369894891460287838546972478693290859828429324627715795275366536200463347815250740871103001212500570132289427093122371917765715684140609326609090643748179728877725996747769103365663159179687500 2025420954371281792638854919323524557172488699397645686663951017473450020838193212956542842469754213288112335744219957103533531151982985135762951767433280325805910232098781257570416599050140302426837725572756365390890253027292744465728288299007096398721767742298257050053719468517864823873255863526796984578356519895834148933242767967847858741358071585134950125056679558108150356230639200807635762691158137888918355001153610840566271135076042874243190561327663763399394188453109637392378118471337816000995856952074951740606513651032639351722837377114380172038161344929677198574754166315946572835530628094938075409843764116899933431489388897780983905756854652825898644475458102397574121613237273432547027446429712036199951171875 293103038159648543772980868795994459402845601510734251666471255745652986736412566865521095097139798779588814824020644595635360810065613348955282776724847895000536959718626190148751130063186634821060488265540441153821294856434602250358673582347842405811893273347067146598683219938121940065222784187022486775072651110260529930098365347208877937919936116305993436095604385712626681748398669299380443141795751112964841031460595630395277388443456116295024393234840106415415970257569732535942646507014736956020721941965641569637447258890470192917271966449732994831922184981023684907702760059025197177049144571498797771920636540654283442657612935554499107072361189131619868591284795980565246285568280838279600438321273652590332031250 41673936616003107970069137977028882024188263190218543604016440475899737593049788402840475906504187891371028042633566997898737670373461927589912412463946940409918611013076433217750707187749022995741319002497678519088585756629619695233298694551298584857846881623864349010006790736734022777853561220676771643749130280453960744246742535752898281727456566233320813973480048411465220051299802682522100199999337303435545649033692170340733266520345501290897896284750589140017293291249727287464600347603437522812297200300754724584831460783197066307784004736206025765687185832812959342486586284108664094823171293271476573014735043680658129736997916720562585401264764817038586466545910575964791802502938154451670808555589133687744140625 5822855623997847327061083734691764756673502441923209192208434733085063276868117826275893407192821046587627589513575038023782109701438631111566538272477564888492928678473699935420946274255718084336660637908096650722548849288923237884587490211769676256270979527909612627024923169105578203980629788500329753292611422262900827486185185405024515132250823240787384036391870724460618348575006578853677961367744050207853771177746742612829890540535151583770306209720942152744869361476220230710917385061612282949038216483818591856882328794390664859092970268650771489683578005023072659843328175598539015225223482031906767328154675452043085807762771676924211266378211850541650073167425767681533851292267805758969371570183602978515625000 799687629028582251946351063766897734575183574810946378147585695522008965003493999650990801479826178454399023683169646127004274125655167205786505385843940111845633077107418691221895720666589858762272006479128070579552482964428729134727950652574861597342598809974731364071163043023681429603278830339331213554728293513870355732482222178748032028344983186831238376578601463503770677013836610587311624474339454112621838111646751354365582501278098305526827363747727452247410167075863414126841727917088578920094493187021289187511566776674682968709604415127141265191842100761907361124437386100087504695547779688933638232163090473061180250580954696600278019463497422894447210227582345625046239274482005139967021527424238824462890625 107969412293066137734511508569040439587746444523255577069198461876201465166204181046291471812096470768427357083553524663468492604067962730044406507878725696137466677080042528871380456863114646650839492017438540978273193767944579849711814962925764385396901574120118821299581593454467896278202763275605400434044899095053932987325707875694853424962222339219750884912066543694382272454160987479528270374370158614854668815441528097691694713555151086080760451288327153766494199374854902963756320091750193800424568378625794560392266685343389846789887371513618347916396582529030208633232481600582737614661727687486781210054394026246630080942898720911149083603434222851304377317768676782466102444346201519964520000233706039550781250 14333686920296055150142728818202485878537072075803830317585041262539315389377197125907726943057023992653985566958782044287883497189487308159114845772503710856229534783562095734719746777609591418329680153079291059649049164545743405092611655409867122254536689441106458582027933209854813329880029233925501194194418759832696842299650978873256815688070365822174667514353396856355018706783036922088310441030568406764326932950022093522183194413040679306965697690803371206602728944989660156710356950263600917531864202260328378929072717782109876962527602097766588556772974837002328020641389606040551668575969113100930706225565318321131751864229935580732914190221771718061233020530964837662354811600430462499225742338895793701171875 1871416622727683120760997171518799621906857936647391299615919724860492315179339454940172862242888776161925094237150809268754188979955434139256312760081142361225474088846096397364931891877217145846918588226591172409479832552005523012507754695477371698794483569499489810262175549486612423165837259045721293916967059085349522043251656619101319392325315342752760512316590262597346888530422718396311098667542780108113446493885111655943269180849353211349988795085984638920366503030545403545605071382144954204575789973774656928426728693360311527920238317878584122814444065471827647853454076459978124279029324516534285416636138969893400111768960376476827319915558228425537520350142607342191189885138722669957276814742041992187500 240333807129231243104294981966612276687516636037186442741778299090609247799140289606444217679294719631929644000146689299758443963761282727428633863008828271079442760191003968059524683660156580232654172406543416977141444390739557623591184525314063160350990221105439050647643640296274656787705840754964557074215043141814869685555861554586590162216356137688854013784210073183136820789961729634163132935887916593647441251307259399046280364403592164464963446774832512211049290524788556843629617475399532361446848739440667758654989183048738709292435177276424097386601957672784741383994979505934937030157699309061444237327201937745838056959965651720054462126766026708525258301059890915783678801752212716431639006733558837890625 30364450044751243680464137342001702848853021164646403522342594422611846601399821349180570219745878355728239355630423984125963962890707691923661199651030211960099578497033409052284072512233178530304987801618549509614647296128999277821920034800458881358425571265179816498309465129989116520876310054184815464735350577461477763411417004209592861451914951859989810165429383769087916991193622069833652959625074341730594224098686725432751455596222040544053929195919738982387798504858809429582000008154920444374623292111685490941916232302937866627338291568363092756731909966365040089724628003701171104578790984110931417986926455313291497995915157731156273528931644920487921940056276586581979512247744898853933828779180761718750 3774804887961310758555113903022286951820767324689959159984826216950631489496183941872426216356842077278959978137914924756995971168778959636405462509919146029810914509084037163589078818846425550521763942941175065973830586358678386109176670035445234162932876894239525202823381005942207743849552434467484857377288594681976245936380717508639088483914558847415104991681795315248136820857498823623454000370123894351445042345849403744425778701575028606209042830531090450659097988903905779390854572353690768432715739856165736469701128677970015716097457191277922369384248098943842242333045744634082304726946741521536325225906049458397742002439748931237173544896878581132793161702149733337585285794440755751465340642769091796875 461819837265707638379794137328952722131221131177310957386912838173516044238153234048794472236766365477261384099183250387663543417794304279784766132835358379860705146744162870855847295687748013213564167258477000529922386892694394406897218669246282226177986077683962635471150902460844601073481436929013375789636194614818052663899999769272775144132042332660098850870008684236343420055788658885340677217847968646570667383878924064606537595929844168075718173542115514663495876852739959338693449583326887574938103839052941531950241864584162229180043426676346733061603676336776640453174723407121965258506765469550000499293420098825085803925534974516776774271526655795808363812978028955558837795087661550704876625106250000000 55611966390698105100572816028835984228054074134829516220536729551822195823638823965423828844165115781247569500890528011483673400419902055048402150298562142490235062450338494849684705868882356256891192989631764171769854399497197495305829986034587148746770423280800588010896183575947160048668358287300150739280559965052860239530215612792291319075912690397581240814143168132418407884974728696882996084895641373813482572626954858853835284437935105052011958638338671295720982355678812585483203105138623880543695562507341108915131116837563423696890234474471115926183977899057052074510473127276778845958486492866498048478714163503748209813892332362375412119433765921104883953950537432548716744872801860191193134141015625000 6592472725227607355006676297854257297319815414123882819060568465704080026519964381650798147535051255476856318941555571848838360336542218977882466276865759304642279013195935798355796219193626160417446075405551369253249704099209747129946723534846888914519986870955158379959994349440921442962923689224872152928448012869265711411973978328020781728928805796028455610655251019724721989040425697261208714411157207243160685251278682967479916433654976452305519410262740007096110906061782322282538931024671373493924821599014317311652268785656312087014289972173073944840701043261557653576243713827178552182212146256883478138246526162038787666835670565752142716739959142195447618754265969426055334362637478908718816336406250000 769445690034933833901165310703646274666221717653806669898287545725958118229306091934850617381552701172091850960734820061112904905617858366136738434988877590539000307405051877280941880286103916855088481745817088750351072821577131280649212114219099400028296066472022587452698731502160114562795468419209811018679001947703628239591693198657112981391085174950838490626328055080897917688132786852473964782055160511027623113642100249425319169611049382160278865202925944845995209279262174672447334400189959941856881103358570081833389453256310828462382011447366745181644781566082504558100522068471890622923514175865692296088568968098288691591171378257636869703096456807529708817725276091021943947805389418337943596796875000 88434272275604728912718285490775382959606104329545925190098983295046573887152165541970983186117381715633720521959234320739883512041792664366457613211495857295562782574248503329506649067114389280308202341339203069740430173254521379772723188932817276492931534910663707171677511986876141134998948873810227163889454366693159229185618330775276594325760349783224909556043395749102646386465005006560388301645296833522932247464282854445875523721310074586928843505106572082585330921176989263851000963944179593177092008273288206064966032622597184638882264446881633883022808103227195441681636651995340815900921957312185009007457922312384602225004694774925800087767163776101293502973723927998552369831813864920120157812500000 10010093156467563047706544285476905539537115187065468217366272372849890532416198493627171469890135308190140543261354284616407466367256647777270616267246295830746546283610710216262827710294039688965176685650385407750068670149956860508105464553661950450498982881387135907887851319143987986477385805247784183813352499268870382570519780491358599244967409352258663832808113088706617855195198410681726602773820132299762867177684932988423262833791844658441110966562373793640436013540631886118159758513638226696141619979509383805880510815821578607336473538054743776910341865466916083831641562989356605304356826073704688635470084261390189621031665981066162643288744189371088983279513067270917174421015377117323112890625000 1116068482965433398602850983755503888899563804534060492209415151765625457414541852476614410186846129934621030406505665545712765021164039229243532577442722919436244393997407198504311146502469110234524702098141949830845529359134134142618842638209638492167266681453059737481525438868133883398483690850645617075065268319285921437830526038213476202041084141906817390369935094856859721330682043095185797603942949009283790332644772610783606508716754085560762353145500681678358532276582420673424291389359040043035208550147408408309100428666321471755945652322790133903149761737743709640147262675880664152972999000395341885223438789241848311095006642514064802662538938400184153890313185855412062090382821910754857093750000 122585084435222043188344010077639126563556697378041435999914832043346749102336645355337598525300750867657293582129292777950059327209424000145406706389227563347796145024053194810220900319121126411817745133531207021029697702647057217024514380327159067620756467239745982782344007218521605348055210795697612789955748001895377306538502262176934250180156562946582660078645020809156898987109754607454832023597370456418589955202965106018787599992862727130909073490926105286072970606066051854905545978881459537265508558819343102079941465651011029756730171693478006232366744316685133768876030093892838991266627589706540739982501290828274172697905493339174905729835964676710907606714245401594699372522105005877298046875000 13265874759028572371298369464912772639504321647755710122910979754187160364730364931321252806779943892456233756083665077801608979706034038120195142739868961019633924774766475330756880978089002788314184440554841184047681337883080494320007270544928046282156394576234994548091623200337487703203688965358228448877725733526144101557670503666836564346599324045641970512736016793562058470364054208306963446651074923845581224268715210548937019861665482547136851651519288480967832706605401396360384375489051341199668241833315958852431449026640560898784211712547372008074479850994627644415044093501831069041438632513381468016955509305437439670317877564282096013372145251629475857291825314048274465168746614097402125000000 1414626075228915236068610213175717954465596103418011157546771529365849888512177086032039699775849111148457309407053990091072632352512647388433832034495658829600159445040096607463191249516381643855828509926921798359350567186902807238165391550648606259139291472416293366692132512158596812976210951243564064270124156282517127457974076052926838778379383871913565343141988573330505001393206322036560555361970700536117574862204489613860878589544204873090385545649104755793995951286345508641877815897281681210224731044040699677708712569714117304643889195577310891615988611921634790792999169944326209547682262067581265006276834550525576050641835918545522416732054805282644187003745959490312521797799417290793484375000 148665301502876180283221480219151138906072883636684756020930638097636970448815539666931528420259687226528808150672452182127861999984674152937979826733749735934498324246674312892330688953181361846135826006624905687690851443006835068484001561228492213055968636920367535425512140953702812006867897592769669070871514729424188390031966772459429953169826768235224573490688591257395399084858571469546314917803532733576222926542334869677685124897207176220505395758887144674006411319673808700943037563960728415594587045543124576505050234183741665086643648206007685234888572527542423078772113289182050242837283374338847691207614584265385833265437893106351739887549250358162999572116543269293126808306809963642018750000 15399022518390495471456456649467826646981575570656293155102229674150307669044858987098110739946205095997287468833859683872960796748865392050069861284773475279832793338892630216068339572545966965861076952378382817923968349468253584265075685330310975789610506605187165082843676483431524748677099598785432041991212314583261079121025298386542459050937114601834016977917114090055004765177617452390899300709690187224989351493161234334747050187448285317317055689993155157760968020667091726081318261289588686412935954041636494926970312158216512169115700900869613569187816174979430594346976247901532048123779957882348361392150117277854833556113701142533499233783252004531757269968217191841743364692292777122253125000 1572332562579001284831882169574405089171983337533919668244067836234195181013345784559608670522448665475008823704508560440689534232577552882171065924491061688374049266525932848266626582079246381110613423240650978517991179815737503145838532530529538364928895165238190321025630998709222740293305522446679929430044660735793130068132093912256309321339271475121831314769647535980396911115994776622470548399256564878605532691453913613542001679550132803819726603357848493674998859603201440745658576103753065057027603564572779623900642660610374366266467466362896447475069796203590422301042954086988470946558424553730465040218674555404461621028365678619347947893967854530532950571455082325113357153239669218062500000 158275720914373795163270567368844216590276543769137953006269311931770585634053297830114385351445733126405436326539344019427834679366990486879990984224007391446574449651481441642814712701428664477808572916321115559980416922430962961208187835071699651789414058247552018844242882722047482317654889789088534608122662959387752355702767019984761129000512693820721526327084714734498904167806547067450163124990907517088370890750046502499507881238024637794143748013260347664048955733586104620853322855991633016245080857987380192624764799504101526749058470997835445409986314065012318069785672034650466195550595653531239299483749423132408929418339247138920253799913193106564235326331119447860733749666433909234375000 15709145905305806968401177866092526785376224099480504670492251340537849403630800718075749374695596805896569216412177512062862949841189018911714741212061395604302471904069801261649079756212422626601570650854269510043192518156123511646538121990041856836596514449349160566562590166964759607006322841869051065794766051876267577490475250573845178071343172464491552291574090333554026666113451709832476320645690228361833223510374654649080701550941870541257490080907505040225089999013062847193350210486379640736069775611844559090188904149984790736403539071918612121883235525072226227528960906697045648509258472909038357013155453358573067133152523889385837755732652046332875665573413265727555413307440005921250000 1537474185504996957023008079279707576729366182954070791260404059374961921756577058351895033831512062059663100890291825059949574176071417753824578269537307319977507149235126367984204347837062566715877082714199744383572315191126650841674316297927508142295123577836805961819731262616224116452911540887819797910483287743128584485808277945586979223437391175406111098619198510033688966797334865696782353656909010237879311938404608263648201813128999416282267486976596772191252245639718705117837810903060841581132170365859387460272698092078936473458095236708132195557844340779449557125709256745385912537126577117551436304295344329389809556972556032186148307821302842412097343021970444922867933194246566158125000 148397839550830509087046678727526825356936054726095625565300214165751536890472394945773755220806728330911445935911675406590340105925982110988121703523318678738175604381155383295241289357274406677542715249565491673558839554372968912192074543332821846568874168231072004881881572521049398117273354764490816266964744540838480614184958586096788542222034028512595839158488118922553768111237341057313920909183969438335842183973045928082345592871442972116069311536335907916190984267727910828126826542462946965927357007108845819885533801924764835089782837937963037436736611836677103122756727617453040514644357823499187348980606250435978061000301957320289538028565037663887114965919215280683931274500840470000000 14127269830834011215650925554735311321727718130660264291247951157222709656286284353403833658862343158871186900278435467754864498620975985658858681225909469058619863984488636967621384925763592859486852073145398639204658821760847223933857481327172803377334585808187765053101839869030213047106088113078709975313285268027907261932697556003329707771158954708109833999995600133573972897174661088798437841208894443602341026922910783616268180496719395212868031342229398117973469469936677952563793407526402664444039840058801450363625217296062250721024528350288501490673743565537902508613103358695948485798704982623412825619752028607264925357316025119794353571991361171205883282152388035184778248995753430312500 1326615936062974477315514726603206899146123729490160626342174295892853397959395081317435607207677100648336409635731397392486540484350710136003528848228231723078636461466864948358576623951472068164795951022294993304604926500761959874782457881674720196951873146270642232691585889407717240144669150100265778536539534756504534305133906551328675085183944868536586406268570501401579473648404132178736674356906891256889107073370223532256203795474348720762044306476756623556517854603121132023816658101403765536174750650077593727390300918020319363782425617627843089739270762898918603052143245270461767515209202796017169019964396987552148940011514279255344339716764843975145362478902511209180559521257835125000 122894620204820102992882570369234009698705500472508882737953957522319543455829510672624460742749644488397037235207129229529011735462727818597721073998988875900890053487255353527792633766327711769457634758949080180145484585088410831091174134664330797857702343941384134853580066875704054917206649445516209478165707543356818450954100852922065602028226781338399421314750005597743140840190601222072274294891056052419529180583764636517621741781093194513342751011191669574420963981934768479404238476449236813524279577618018020893435391171936382503325823079848939422155717366941649619898909963690347242520434299400401338991772899361562919034647069698836176508821372384678370049051667214075495721273511937500 11232194945697607837426107071230217362659090180053950965677735717958859501674436856040323103876152269150069163841492807298681967038322003000860957756559097312674222822290892279210304954478363064768698555004075092368334339172041394423294943956517313877629734717827600091672232183622809641742541066054192281654003313681777106154805891719028449549662984890993175191901074689216729761660636321996261145805756426394459802306319698918950692879086174620347492038136707919129721029254231431053289160744196075465122184699237626543766526139512116740330463510712423580080343206244156598305700616853630022263146637619846859459346800682865539493653827503388507560872751491410766716277382040601791645076297250000 1012938201000656095551217671884059578895638131743634357995328183335841517678146585869432497402097767781770482134160715701165123613145810462885941392792269704386401588348448455007134036256052897819111576568376172742043806389528139866560285530036603009065718655723696400903618800239828336722848958520766652021801365732843572928839425675396261806033373186265057315246229763551207728401562654760229267689169161318003538283780982110148394972190388001234689743568352646640940652542469776957611980044155547768252540986468946514137769280880631151701501266496328443248841977424671519670664544658234915068772939364132387676492701520337052484228351745203842121149056655562939073112883192637042317401860812500 90142450687274889086163612428643306074345359241438345540905992147751036861497110719471610346713237452860182052696411197822640886724165813801760342808349183761491789102505286932268627117295892080099325393196174111942255311195720403622401283503459386143045686984938527068729374124557012115449589059738265544786900907023766072648229928301175674755156841479911109322454265694110742568920726955497850612057146973410418044680975960887352582692672783611817824488815109526978642246579249713236160013944884882512483296525312763359007157028599317655880868679735959270063744158956148491126373151531685697767329907003701311772207786429502627677398724893422809826450134496695391489328805532178179478384475000 7916705814502738046284703556344198025797006013141940984580068157608032136169303189920095739516319317197105946584646544554769159991309833991114803834480965068907683069279139726131244117922973121590366825389116736230886918185077227838061390764297962269998542079874226119556144653778569852444891582804224881551693544491073681722173456171443790661128516362079502170585822916297442076640077484749573437157101210619769161512802198891526884652561309050382085062730788751530760698630589494271636564119724438938146964550335340127633009052518689650018285795196982525122796190763631181146402990343300704003517604464255376578283812822839695663550846102521787174046849652109400026056166222312811161218337500 686227565049481032244026779670512540505020140533690426155306564562797347313627300579639626480525901720544064374501067921642327620227452192122383736526950958313546847810492863150235566418873606436962476926758298005472404701987491603029622892337926896836993783439112569614212113456505592694640632971749956169632921003194866182388413910804649200654228101880951950236465872699750443493491319821230647966705538750171110185062759687111578647982918615582359935567803081087451662983794104270812130527617766550014161029626384324618081148902186403872243437578671729234504940148237531323221737056968401103711380710360952935569154919093429749062393690154950623011807715826412536975984390607602978015500000 58713672296042400394324020423644504090077573195150904920394610479953900870442667880501549980223214422303685801661664118414512381935411107532798563760087000777415204890253997613101712910047970232246109804793051959446383110869327098574398646708959104195682323919595422256313129697900660933856102648411935001251889255102629612426996149698686930021884790127613403834058392970989021141410264554427561160241650265446805242517575631032414757867796177957486342350330107806106444876706232922560175522223379779137814458214545548416890678359458462109600580810831007332107076000262882550328355789596136058765642197076470259218653409458305586169118824274493734647468006002819607496307442878560619389437500 4959020083037017463339159727915699310513453269363522314128079789014530755954246664245378624185892852779010174407867255251560736559452067621251495508902890401477683236641199285940403507907381288305904050427713197919646924562254212631945023863925891494664202892907785022890861679747187271073128421903845700442141961334089703197354499881764859317619735319143005681489489901171476508974134035171325814931944402039314581744010436483832078222106766049675589938461171306754307230993577926997288356425172489806634841843493507198209470938304911032869112309028299790673431945870632648675007489507671406257781513611400986825564003354098190748193655802520359121232295472406897378011627228800080251755000 413499826640740073744357747800691843348937384591992748123645704736741067295356757133777607603040491113487999063255501371285970811789697294215427602381330153552935800187261483430148113979951342865367968214587519554673474194837545550574780248512169402057398556490921794504032143771571349776200490837441343053128710367020162909206065421456094916954215818746574638288727587386611883454675366320679571826326724199717615084042358734754830372414097836527624725844265673784508490073592741349658614697566811525558000149733455532956498497621051126317115330109611071127893835784324763547482171114843134642060159810300042119533163693915270567636155870804863417754661093379657249204385865582477608712500 34041929331590471659576152456705938961847826288211699553488481087776072699254434791105728869582476772170346415097278519620074190559059711602655475588465004359994036619769365348571410856362434972464010265711604527329702613871023446750941397882327560887171096694904667852357022265211223954822119697552397213347328245122754316209381664799986745134291734021801277430202414636603864496686243545387000840684090351519240693389550214107014256445428320943828727649386746185078668462280933528356762036919827794682373090385321956859815332866802605099728947673552950471668081271388605187298640035749602044575134000038013082046922188476924909093934726591250371763418380902079402916732516817779495970000 2767248364058218175293974289541082082260754961068974796696289184278485048145817804244890390551303114373029326949869028611061285037363068131278675659239544803129483273824282714803456453978673775585952313872933392792774695835665506023384811030499390269174226348939824552265862857188575498806503962915109480574584592957031194060602061640271137361480446557391412502727444466448921211797016975870153790564730852376099920176703926617727412671101698324134342956656413061260429716224994077382834830828415190062509946301784408850690221969218231810302017858830044763902237667904118781456352179339295391842236713220942809974788716778211341552928932866409943050264573671661923304096267695029550797500 222132592846966660553273937104152968601479185593451200956626771822608487883495048590407646146367801550836881621472639860306746983730259034795490464477623971490619191902353225924604716133838983594199856577296207833596369892963845051486064198486691236461725993970358470616472342753828029103485935129725466624739563020943005626297344166442300530337134685543227733469892781889548630059124161348671987034988663065965025711195723173789406261205724422876684649929351201146196437024608719699437099672318971839977231814880712360980065485109328359886487155402031202986747566150748558518429786727346764211744901287553835643848710467462201149872921021963824630519542389444289344840103022321689349000 17609252529018395338619975298841977006030619280121232330328037049015184204490178550630298154013979733376858699992841921216138163557554866898263137373371775843374550262446008810317239329331252650954299834675342065510072999308858709923901494245799372323799162998883943075952732837182506015865194638374647389901423910280229415748159659607935577463902215391853590072674116243341968835464446683489216996844547028750798859711706080888832764834867908450320929217996960743746423468544891794118541001615606350920637871417030118808212456447645029034250086761644448179563083130417299295039504923384642547018478903707133909051508997864774788505249063923510169624197136787144247425747704685913556500 1378693295306857810748547491830386364494514827542479610163336102558672751167133730564730102806975510811808193778001324019397739514122091375397587901050664649492038359085658631137639106716722069389065603968007083601586638728748254655514737293510130522972813185328327087970259158664466715449258042113243223146056271381357210121715213228068833822711741673006568490053151479738143016656770297236337102718318728684125502574627373227110503886350652138771983352346665462007109475974053979176784348823001880017345209935218942672785314548450553408949215721835447697421146661081989662856034107179842634062289625385044024316659488312284193540676748515971173269732678226388540712958859433681520000 106616752129121167363735228004028269055746669508560039584649175812958560334094431091006546269996272923961961122547918455165094352532650039426880963314491644689075353963387704830061379135499742745561784890682230292721272827775198641287099531340871873065897758855884908507534472821670359785500025566307521228169093869045182890837945796772076088103319780845200236092762206744472472965627371447036064271327204159573080536202209246666894324021161346678226475176762481352788908944172258072442690854942891213857188483584023262455354615379808809740265770059282095472015968252204490230756544024850960363786159758435658203122761599267626496847261884889696560712512867521943048019119976900125000 8144164727115499802348563821725494641449377102834848930972153022987089787582183067353863396723296279266404651820677095679902273361988088845005717826694492250580431184880471636425423563171890636982296751035452554892181349085852703310816998865863367380311523759864610989981119075826249900247986965208167323379484476802979033600332445263055885605578475032208382770267199710259850690421673387389301513852217555153359066022757241324211770388741425580129626540642671984871613112111441336803168639787296748859375110501886437977447819247385844297090705903870280083712715818617318483053711204996478593629702390259599666754017397335519884145510913336459462487018501134962113872159983971461200 614557598151455445983624776160662103859445314861134054964139424056178939261785564876499714934546042560885847883883587995774771861165503155833223238841938706079726333838867057836062013827285241536206712265038441492701233470996151146835964756252882311122205730111581607192693964587724071857364879862230965134759768237504201213323088116269768726697479110596673398408739808575838032436463719025531800991902094023646178159189865713929540603042576851007971825881328742933452374023403749002427070286831824423383896278613124350452612548770427672679876698902948179477506630593242358633238068269402737153927929730432338083667564196773566781553037137405016169232155201165135363252337529517400 45814671178178113365937151428401551114772221240712675094790113809677048554446781401759177334263852660900473947633915850147574377318515747795007688239618666231902777276264179495098522428686572872553804257322540004229681166423463165009033317075810569650722840907290499093416630441763464738498359706954050445484468590367901050927768028583931630043936115947697349987240099277519185660502708248941500665849975622572747527568980535819581746165434770802049207564496307168762008448659504522151244263904701240220819718346012644518011468732022204965858857010806941493510420219623190184123267276317141932444302079454098111448936560704753405051162939807762493880256953952236515555659148125600 3374449043240164676084911062561017427108335361878113188428050555620541934011820845554653675144840892461423924601482189463093903204164278900014696347158372353085496354273515393518607087044027452229543292779082601871005770479082761120597209881315833194019500725005372899711142508906438178239883585188357097256161853851731439366880035819068511721336896493675238377850420404595505752225959484677617220618902885789821870486491895682153471615733906398638047562406572811546804125687386344617076438569818091840697903209620468253899398749014789595688039236132371947289696928640161994169395252218690393809110904423071304441944356158222599615428215720773315286802291066275194331465674145800 245576765411874048378393953440712024447181863081504467263672656345451073197520670953657638749153056505678501137088065263278495582543947723353868510019608976187551449529492073886930833806993445926675432495638368887071619447747936330668692139104767355359700279389100813631738753114405078559076220056081236742328870863937066827827132302122460769391783746281894764947591081418063205258982329916315286726698761248482169950391705490092441680181067670828569035016415418365796175686648314678181368962857352689543758617612363498534325391654290338133454188549232584495616123813785066950718258734410017086539798453866239452779283504016412657514453882450881285477951535244264700875979984560 17659848387152668303410890280967143333151973626987463820159554550422155405384268874773237474984429381696025834785088061882081096312798674781520310981508106921600896270957323049177755821547565477063767514975589084749952924054680409725380935345893922215363239295536434460706080978613372376165040357139852897365844321211312798154932333217366693871616649540155457441197746679177379182652801957606031908545705043706213314927211657289897296178909343444379225749436073369932321921376138184250844395073468254231770157166155695207386499143995573916754210200640522903601294929024595405196158277132196329558943906597914887157208437655325187716067123694549048148874390184678130266089905880 1254962030894994034119113439153483847323608254728288534304163187082499424602402986787135566314831800349438878680113018724088846738928510359713290600847626794299362993803373284089911443377304319790173989890230037609943824235776680876434996287058729230924515579052535041405347333928872582544426059707573002926696769437375745884701021079218178240880537947992130759480193305538087333062500844795060981569187429374375742176932065027366564905946010757991350083199667659700770368263781670926272762421324145207285313689577522074192099251930445334055196122040627251670755021097273775754036255303303474061205564771203059305237366985973081174200786535436241738688534951137623442103990080 88134549279925208553068716660521870213735425482140534693233835114231529674873007215244588227880878610219266721317504066753948446485080582803710621180604769932389515992603890853577590492071660231617265844923578826418277496729990096834384150910408045031370234169938349299602213780749060981380485871819833156946629611568168447689594770581426954735572022857381350494967968199279652484824529441218737027754051981730494429088943332235713092421485122324152247238769264910357433173502304066397487579684347319069164897038501924713378709393421348277156756518525851171920692758780332298716334199670847048693592455198477887504614359292451810018785339068240666176708139587306232612840440 6117321374857112898482966276277605468498101060986981477319833112133181930323192885507252655100523877652855968767837851314136871913396762962453436098718986141831118884358037705916861651299726441867729559084647572977455965602643756711346053750070083579937737408462758436020743127630536787541356953972107309661497881095841841592200396370734739283591519448688737122878899289949141959558969884388973879102981493531219529737533287182920382872993461489715849291061953058552109039995877580774847422078740154135435211657411731220168434977396303876780519387313095382861927983354863507672229602628116551043051644294858057045595042633117642612914780723686074435253830100361933489367408 419665147033315258386069040258869473211752860060609650590866411206448270793383345264217441844162064728447060471135217768798479984228389043087547999710102200089664082227335151603855669416815185440454779155713627521628740372094924546675537533064567178882229214101361421748945811181479764644313912612176293909502170582453287884065159960339586599529036128166853377615313876587586033599470911762202626567106645538696013504259034652091880997282367459553293082526405661404296353713925618785888815416596316245133940672336337391211539607531003276728348974433387525805615850536156642644458874116966105690844781803260941771007248251722640164933559163150732744771544117349387900957672 28457547884178052633803634315302314087383865084150997362442182512007205901349668919986082145615652581391573977202337332423380104919939819726009263917888569657576983634481843161249460536159322526629442825722463750119111396984239682327346210861558493187786506872803932506356060099490666517996112618365842663812561952730089322059030537010251287905612608537651315217586236012582900328833895310904233810185240235188132737887024355064911394366174299309589889078067664664980434657240293398339414774996974925357618366804979752816304526982086266302043536403404829188870152330746624912282452009395043259445566652327712014590373260254230577146465944293318781529884577065529070851872 1907528239212074132618961848819069872273720325480037968179188751854948784046924872511342815184445805249251387920020469672293351513838467301598175024685001376285093634082034591875759852005363054301666686098411051699409961498764472303441593249811850021189049364124333625992818011354795042446902808783791808973626662161256851321833801920798837294705679379145151140314977253771292196215241241421069441003938611988776238085827762139854212228492720253785085285654448016666197172821011887963628619753281910492878809936389883771218981197795189689523280928862010779037825485247681873032590734930608630920184007068836330212336722498707561488962532260935904685511970967907088464504 126400522743620491137099579936512915138791332828059769571612208787028969982503072679387902812739625998894586645865334145469095689621329169462849371913877972255216162942870653760766877583434373323533567188035068823750111763256104949391771241863297005862245058451321242749704800671975738062473133874654849179054042140208950656443712793098060450299756421035149043540928585155779783587658252647428026923343758941490436076135274960987691002275731355040755809379729201140935778474628935788547182323579252288313068106392946950340177982657319754388889295362543851876833308900653989372630035086374760428836859304123254205783446867626882887912890054782671180907911679074515271568 8280491905371326456174838425954996010443546371884164751576744544007792451368463061818781796412208135482239807213660699942113429863926032581025982044342324144870934019111700083230324595332267027294964423367300893704945753346664608976544892424548341356796185283934156162509232364751250478167294853392293389726435972751756571892971034107755287457523727859903452664330116161924602012590216866499986585064297524574278457357925733918648293427619278185817232466557268558656865052901530835969364923682788417011123815007810942049587601166348196023102154103425223180300213164583272185241772716410866209523888939416060742097604212710049861527559756989414875664981125680361424424 536311712592397481310323261317051596892892947786145767555542403981378967852354397941502158828736734438075219653386068383791512447043999831975746127343738846739516642550601374729015136127343208215956926420209196353896548089457432572050049250336290288478164333632218366798018341238823838679312973228017856258785379071217166147780493866644114243987213743146525280302254033863397073143510954268659455957614352792037346308834255448619740476228403527255142641290394980975960058455255608901604992398420988537307582985597308505126842500593529099031745906860545445134876846088580917891377370873039601664359432887397685260307809637217957820437591785476629818310089144432185984 34344432511420168445816126532219420822542629874186615503768597148374771031592379010606196263076994964217578648428455905168468614819514774055392038817759700489009178481708529203432907231661751985727699722207317569418040681368394969817677158246236572122094479341635439342236496891628002531500280407683762539078946749501867545788704568438715217952983836795784720741289579558293296789541964879028244235734762712344809540221654911913237465994924184248755343589680139090703324517887337030713073026846168874723072632445050739023318164166276887337410146919613082088384835560048966802149325352984778871179696050808010014213702616653318224566031399986011447246684664804321761 2174687770899741793625954189111818841119595767211861666308791267269447203500252048604559490720870779690192474064953482524128535466436665414940374417282676324457414320899038784175354606860022659886911361245407755311042186293964007674297164109272225615681907462537383708635649907532375093955014020650395153323432049405637068583063134341097580579083090171027458748146648254745198834536530315068856358810627040554101068129630647844458944032737322740043090453516107398195939106338653852781648246507627453622350780103768576907803852525566585954116917363832400163178037978407362561582120307445491572906207979449215453381468009139932317796024632950179403355898128666198762 136163945145466019105081167348007244327468659921754837429634383746909454912040620417801784876546830042276157367751599804400748885900651874362692423261761627808051224360152883098647211397085235814656968843350736004633501276493558386179087742157889140681043361378762055630189449815502251174125514026083399697571954043272757671193858594713740848946940232369233143968239913082141359743765052095237046765013604846549950159174455166452941621314020643454122309177829019430064199853358223248844531008975013679859467421848385550585774526386262152430416706751926005477615996372792845847041835204563474344065591229431008027263185128649515607285745772941898437488411174092019 8430914639630114433799413652999551171142335582753290484652388998009123636457833675243703569091034591064119483609072239786333937306124219157759608672269134198072142341568203310597987522370899641025893559307172794773020201001332894604934078310242750703126816589524572659944449692381171470248002446886694760557456695618436119863923967422601996322793553874875997059318782823615373241826594583706113620564544726093431201644600863438991579345554123428232182577145903563009595910153982528489293452436006550959593216378218834079684480833479034372508871278673174171254732475114942905773153040904069222388918948933098705372190127240375314407874160891495963284985083335076 516246228106855340154170787164698290869594866690263960799258544299342336253236219055184668918302247409696723890900521467366013677722529965783384602285282609756788998661333138625876005178744999638126063740228142211420432409782012330081560629893407459353279251557266888179022309435318307508768357683113667452523681382832174352454484500087837823287937979177567922604437217295013326565685641094855917932192529631982241220573072075584296918375684164289830036459891058530100998823718138779265816548967912424098288987058348838420698540461241713397391932903359078229359708644931256897871102867296244181145380510752191383183106404867869784419558568208741381459411245513 31262995435748729100371684719868633975393272699722450080927676801585717808697928620044559559757456629446239246343911269743179530164666990591711100567212272907272068132830629967715291324725660086338499523870654646107937549529500092100173666749273742055078354677781412699445443041296902535786851586716249870940148849205470397235226572554502444532926029438021913879226814221023158147358515175501788007363022957800749023457294730301147878951341572854638522163727462004210663563402563022577181725091968150854270238121134708587661156830022897809732491505151948312604482565971105005694947837427255369414765700466229875668234024894925404485676692077412372238840537654 1872480199215487742746635109082884428300173467819356579873605988580865797739471213932751951294700301656332372295314185729770923427625408515098968383281849259824787488389333550522069928471203588535915137483815104866898434073935830060159213804995424190996384352569562205565622340727282278660968908417856187844158449063342820301620328151709096735732413661863763124437513572849267982833087360692845605145264749039549475125198354607274680395270900246105510625521973998851240769211899189831627786257448763560604890321972282864554202577447483323189088710749903200050013039437048004930673343177834377969172974182219897912771820738295735903663406886922070827646726803 110927157920026220042062130155292793962688963235229635628741389934881376015600588562669427422603453453264298651296245629572513487906344252670532275832212636619376871118993221449018539819018528945968430283141314540381150857291414183187580339499385250419761858750608929565361061586599162362179080073954729515243170616375804367427715333301910774772389262692706893663885816853143266643038429405635572732038737429403245858633006541552472081906908176119038539719332996636064269024221205488547072401607315342221414942407314305105061755908431995113624750693228633317710476994312360871460182273284110388041510606914395952097496349967962363418827467596190242810702776 6499997741967096896169219185762093901295403209552095418784128465947393422134492366077781915807012006935260218039609646746150289985631781955082464689368359739610986231381569784257786773111448981507746966512290204716390907900790337004955881689450546799462742280249136261724852231792732967867658718668753127935071655059758216376139841783405012540487098326129805803142500603070165386472540356703446823295583763857559250667884559965014519325920603469534959294850816635193333817771202957075844585731230634208669043296658472065250681722051230931660347302504062272428781441890369561102985563378023036832201136841600756126226098811615601621007779255298900411584051 376758857260541551307405936888555288133105681643680287291219386480063991251776163315896335263473960246836779089949849803151180504370151164937670891239890569517911336434274235698793706180182069148121786365836388222400805108078974913632527424422803087714069469285911608865615370899170051589601702942396436349857742177923475747711655794005149226165030672042527989052001545173091491941420521032908961623388666591155666693369537381610470244787401963414488529327552495241757637169634897055914668590998349882527555342621987361638095712301771004737704492272387111913168142277147766024856902186663246206678745544075682003411138427494791651898039147516727952530790 21602727260912921039981708168258785729814057130794819262858653918767375968482889281012496710631397466912071977071603308184434242034511322915667841074244192234610430339541193078361132282495264663043804749954322975299890618030410835045591586205147937623530082140907226461375786485240049272405597570246074919356580910685459484219858273595675182482117890184463809238459679554937260380987719392391946197733656033334980630086039852525985813767643845054649067627228037748976717352649309184916925263424348581286880836766567184277334188665934801205586952265748699189149917557877150712310302230363159449692714190226804273172364236512323969049417582465468615468409 1225372338062554583232862700503094427185726331765666125225070293055273421488736262461659219679082595561434047009990188611678513617721311824602016673436583561822881255153082500641729488408772894993398022014394932248870498791408317704198920800969094720812115980368385297949725372594321913229949310049019592306938299535674111150049405072533793240069214530422653078689541654930561411443195504360792177715429360680979025196391256790373313804120737356358486784411398949107538660533470732900132426584400665007955407470658545015110034529633943088992435106151133268306912158086401907792749326637457323472070740914167062959837303396017237226001887853622898001988 68763996407515534136819188971371950122383403182835839767479342163533884220633075934222198269072050123823860101505778505160383749209140851242978437008339150277653029821963618617837647427456006218155431731085488474660291007505579273298385181786360043212936432943462548812244677161779580021357848193642188917797658408065209503691897799732719860964524804835424314933000660163430639518764702145370831312215887872432476181707153852314304422552176417341787449712997011654429339233441009992784230395412690940644203345294401243826624344396757836135206413504550467727024050948405882086771726202219851569883647117487868953350777637381990242178995635870380459571 3817741392517783739661405568197064144753920642938157729730416893624480210524564156676752512709513668564588740815418349439088021625412047254731188794945090468204827636614634501632947658561320246387630295500765366640633370533496567263026772133035107959596278341707325614267206953041693639078732276994230053243608688806987743540865655683014788697784883169139247446451303942908208665387148792117013895776906536242919853316828337080479953634990413532023091315328058701728404981696931532684933424043324429560348171911176595363753347152371874685117339657252871871108869174284700955051927783068497216345678951916416807919652189647805703313507620429703398138 209711733621008527691768108692029339214935082566473689896846551314963004997675428329280142057202354643778204185431304617934410846530496677145308055020319938755440732435792881814606611957140861002318950040268292627026245740282981311685713046195949758887938474438780259139646291133573334462791818332228472417783993833223683938651990800439643088758219047421845321480733790097869616494774905605007634901987909928878203096911240236142229539108332884649057677616568840725754822748807464029579889959202387177670826667289349591046360387108578475279981392054657418939112209825393008347363096901555187862952125338888748305772639481033580120774935128223003633 11397980331910821502955857412839570851646507260446797675822208628276889749611173666696715939370699306230478761224912729415186890065897886268839087316717991065545443228224243492224778511134239649588258317756737035302813656912908515723052619772750943228878922666584124778496106610815201940959533915584214986469616885549672893613222258801950021678879575143724253205745734400501579021127985088759744537337641930714358633901498223297869127345903616648136720916344494736871182041338037190357611601960415034416664713977557112879323173706069449567758620274494760100528219579115752484373105264567037534390684478567955250092940555576332714470034131734750272 612970836091816625875947238216933927905497477553514052594114054140876753640720252921045724067631156472356622598243332680675249092039446872893775799969138109761837283819793591429392261428272065392268591184416151581379597624312160152437440196672771945077428950592626601262282528964154576150503719544638964590709700755904902055192370300574774414332802981823403233644901042988215628586025260126074391405334609314555491199274234284260861737047791759668814587915305515174549134452848155642867203098397573914108123680489297328745241022386959215036816245621632243371406551441405269434709768222923766668086411019106608606220117595234161509264339441237524 32619395965279482902168022472945887341492124804449631823101889791289598486709371977251972711894688530654720239935327842030507166191673315885266155240972928945153238459364021714779740795245402769826671201433046642854626272020019740539147410569393972555336855404115743572766698923225263335970438719835893153537625129848430583345638118015984343696618862304830515881126933945436913447406934618597010661621846831826354456923653521666016481274587478017312581507777766477752282389720128764148083907369016674075694188985919707748048338089150131701910600295216297567916450264314635217731262546907071244560254769142309053853815792161015092321690135642888 1717723845002352377200352329714460945660198883571343198356326889553476893813245821828623948366139430108908728471257140544101239687673726130716965243278000687911876505593004605220866613662532444665808990170077221483915395258611598270715584855556124363745883417647471782732228408998441002865462049986034280002409104664606197500509538080156382985958076419313737306325020456997037023790869693665615298188360557288000186299323329970457661044625117870311860599463480059091188668704437545965974651210420311012902705588205108979040731618276735849384233922016657405775033077322398379285889219846747857887196243346301478583853311723230400888762767657212 89513578088928092921201003059969943592959147623251943616199642124898363227436244333113476372522649085913479350017365901302570711971448442613863511790003296795719879197261974989554060146818437142500934252621004773430183060540914913888069318163130787352043849262575811243608056652426720543501782039395663727175711022322580667595789884280243865060953117699003966239432327239994310779948923381986259917723214213044699116961980747285192286390706303797356713747873810302848108429775298584451696270986403765480972251865060345554710243276292434757095886684378773891229959603017030190166294775527669407510095838140677886649465702229805589055969523216 4616354340373868786323377236548538915921589782337859792893140637701223410641474923552614709580151577593987780023890968236842789616273287786926862133758286563531235774814968181708091924203508771574125199986411215022558048971109945658711225690294964879035813001398520893047163733923714780931570152866477225237527997205638465600345055091053696638562204275040461217338098872809092612114622334556410994292708927104788975814529641667355801597982777237609333102288619641700716078927426063297149743620236659161999000218379066621274639892879981798656886979885541800092177783828877411339052770394828855562046740515019905815806153343248774946445338228 235613515690950176838693042066149844303222539849145220153276082014903310510883645165481252637046748321744042394443124101156006986868736544206624074138146184071075445827945897402404292379702144290898062710831575417397232919863985988617600797919551736213502095638070774544802648940549423356770316230086697112050863299647512889742605871667882823559796541801590537397341662539897677153073746915831161071407543772501329087126362960174974069822012299870424622393703888905646133937618326702472903143712276989633214628700481477907402673203400561684383716389552426410890921149844826221517396023807352538504121989964588473437523831523200653669697656 11901672645819007770236931952020484728902658354868762649669672829559896193114542015057893957262239408703668568499366165172346212534172422794907566124123012866016945386584054838875512248057679012922180535213516538591797948827358690542027197996178814059431480614156093669616319152231547446447054859879380807229662359743028835109000560751283069050988872359741957322065256720491160840187927394461973514412157839870003863920208695189720135043246456698602442642222841362035041233151998878558026387898241735985569203805309527458367018505611652651159846662382752848621833500594057063925153483133988947544432451606656572585845329554040409380997692 595029009482170325896900696569432279613639936063834869638211455554799913097238652708922443042077536337177463117849149655813051142557674120450192986958950308248200769728250282676630628898052216002907158818845511311079121201303323669497236903806603815072717249110395064835410809605757497216534031732066167068935448700810820231971541544507217603652937325106050120680849893444834345237373447491324758269757184527064475827786578595643032793825591476842649489927806285437583129620335070782658267809343402070071451876356068830233813245931969842372079554053876916308035756920374709259803698311404235560036928317579058623787878933582167751462816 29444617892826713700788185686051585107984932844936902427319668813627607420957216999516528235274112481737429935864953871493654656206231045368362510308229576473425822688845160954412832829612637074208909785167332589787895078185948962866958320220711151779646742077904437745783118876041185540466568160061361388065705285599552580927722056434157760743702478231475705961263262576647307631385121447864408847838440209376265843623811799339942358001423425786946647536308206283049632041585518850980621497967266613323417524026345074534449623514357225098823678474126970559345122840345749488747536008071324083066984397342595359772330557517300837512876 1442202924862163448822601316635057464178027207873001839514871569272079276339197149504835028798861944121100040166375741735756598135481657667784153655013755770597064175178710807313229665613531894994836354900700046063373394767338858371282095696487962568785427526211886571032184355811817843446518491861311817683979070196688256007293992431206455151982790202703266856690071105968287597369852136114898531712736340413112784415371812238664953477880865702625915738683551867053258031131862713414129020211402497606253185087598752442590914010974385167891303711664781148169471709795618666970309189253571316678014783062005657087961952405941173616024 69922061875670372064722695581050837920559058916093783594333500579212837402554626738803477669094544918123917335902693683946434278379482810000242920376156633753371380681328275047899528067634252671971693823512946453082049052138720164731630909184366093838196504539997359091082632552829198234585284820875380042480476393692450777786347460967810417532227397499340512695506180250561728438164356736078916473836507216941433461114413784959745731366823804200825743115783516805026015068359225488814312935461233463840074640153340546137318944351652460971932078803348122980874982339005608130476920013884579207136910793900432124500151633808166625028 3355706337681441333135930335690067589532452222276291508755727719098086062076466226109055005423673098590511139119966391255334302546625152532429430552195902922373171522954409510669394896001540398656876539694540727248499044436548528143664794556150364839073061907126602576406091693129571877727442123981956652836561838538172478591080401270759272161663188122306464605314870314232775047253033110975644646853455474071054764111692443294677707646307176321607696317699021091707181984916041874453256461456896510465837205341634767097717730798370756974866731287220979287464172670215156109187984351967629389032495519493467684504603440532240142416 159422540946755703628202152271243971303517279515401859098307220120610441454941814988396982222712758217286611949796390384239222779867653677236190064408453730915002380978879464456311976884488043894260854599820243538720690850713012800283377446653952831862407322535363242316576471025786200064108431134460437184323451449429620951896128214597121262504167444237081953822507093910245080113738271852049173182725194291830139951358729624450663682819451955083560649053493857507804404596442573887933588959021560796159669757691270991367852920469130681486524103908440527227942049783420596966398059997368366898406480316755363152827588393441122412 7497655534782752260620574158601536559891949688265397291952644774117437123199261903830590309137701387368167855553081827959861566179591218920918136053328792084233022435570869360153927888196488975109831225931586483695829625203658306437459972763176302993623171511772426815634456583524724272853474655589463005185568326944280761867044133506999058127971950367403453188557718623406127386316104181625597065174400596749266431236625232845461266926579542282528187810049294129829391757780778906190675539607996147954446594596905346447220251038432604042977478705840054520545278088888500731003481280739762024946229274770727493772262614424914664 349079926653829474582825723424175795429808940186524474304115348393547261318838620593523001931951867539968675942408285764237517876769054489778204694712803640973591307209013433767431392675890736929981837471008459009692132829431051447642222450070170835639597262890379579348693291196192328732866329301886005031748392831144416597188214366775490087872633728271944509734885196457072623364808686642050234108463241323329697575382661583497288527956005692928494396073416697024104558394414690442034093838848375506185736809176347391645560350471750978767474700826601973402248575316747194728116428884361624538292186369563868007585212848319268 16090194763040554128659285631151720395463110613279700651956776585523825890631250545566605134789831444201159900556108412276041855277491380577761961059982405178303332957987555009396861395196909283848894700459920686768513651596732489879515116897704807859364102151404355186506157640665199979989071972890893623680723964684743011326763370838010081478130789736731175977950969570028191730201219258664551513102175173577351214164514749096627175823448739080790767195952823139270654373838344867568191139692481418456535214324189776383365377287622452345436475679287818947163072599670057698835832468206793824469866757000083725136042495631296 734256669375946547708863757459786914986199591827021690786370236003860501159212086182388857628017856307235996195501691681173762338441083906713736317260208677265482134270226549729911399258798439647558679930220366147514950064816901206210451188366965054663263058158946347544052551441367720100285164417800062828035928730053795414836186047567582905325739224862801204063746071536791068583728143394368267016609233045210206849689106780893377340168383823117747217658573820113540455460545728957646932119374785843881247724192883415168264976657719468640190630126156406615155246039446624119925089427598165460400788754095585838303126286062 33173978750330533787066362062063835219818441692879273919659520182116769660344340915247715609135029193095325482624035019972498826511064287190528756083128704454617612216152941118940543207799503896071386619815064498948995870715018044179573008099503811676968361875452105885604187568191687220240028427047815200766155226008879095806390748418784527078701529800158073323993871932138113118510150508453899903833318109719087464202127164243036679038244051390904456504072164779092748780328577932143837787942561299763386351723394673973967444714585849349515297235264316612716505986014295087181917213623285188364894164129806944584744931404 1483962506987318198343643957499043426211294410257222108086120559771327210292396715849483952739760742327621276708966172580507600582273490697022473336397629719117086949538782513020891847977045739655018090132366469311018434755088578483897845751635400654262563229967297504475911422327218536094098425033405874282254072470241327458266092537796159278594923112927140218710448203439245915178722702180626566233842650864383272177152450290717419323156648335668117359894204282146850472027662710386975491199746433468583450010793906476480065690137226446403781884921456099579345666722209232930989519806767772699477346083704725403442267818 65725877824619993084456116850915453231966471596454160889072615811472200818543287640645951694127184106731394725130392134248743953471234819173731230508093349489848091353028908432115920724968781853632649046979255373991233704834019932220870640589759932242392194116499727411217900777186165890013510741305624994640780989096292429464319383830825469053912651762129513960105698907140561414339274957505559773791828694357089112211784284417117598393724346517504468901884413446175904941872297228778514670144656207312616515495345555092021486165803065234713206730576117683473996657378713157008023019954767455082131765534416167583294776 2882372580053533256473242015811151615446441104227201285753528575330270876730170941428305560215495153857229086387456817621487359131303714772954288954564466964584599484438466221998484147049895371551540946642333249501262104378215502350061845451616438919310364350844934690897642110176546760517205483354862575446430939517965682276550284515923531221181082798702478239328711677059097088086059966273061288130331046603230355465591823277521709424288939882483856370230569824314756976439807148778488478749717330229266343775989951377693438292185383593375705358316726459846713494046039012087966379345753202550930336254908430454120542 125163014293065206644060131783780305202138449113797227994327071823550349633175842356940583560423715255152505934486388330906824759140213133474981184847941737542165134895321309628571313638976858431122882667890691840542090728733342977605083902565830609943724609952747550523603292438811244548081760089696164600161070587183201862446462298150409114249973088035984889423648231261102361134561513244966848577509670105737584380638191463950135174322602906109297229063793467834882477639202747715018522873394919197142957982749460596727436930510960568893413842997543645472887451011751239045415209430660588315578136954874198976908404 5381777847120283916849412704020409992649226108592354260861053779980205834962686970128645009490391743180479241039897665611006852800037321715553743291034010405668013283207596399711025819857081260145466618030148715237449415844955849614144876731394709728686727589660849624604347384178456274399053323427050962089944429151466568169295397358629684715676264029257650363979207373325031415449032573967227405118242209798379628413352192625861783860492373234597332775063337507914742817529841576636268030838250042125223976497547768637946924222041809541320524340224049181294600587250999948450162824463090857397508075513804256970922 229145234284816604565769398727701167037057575899671805408691641404000101496344799234044494752782215635684113778472901777338552160127763043934252967328430592059096128339829472796773767859238143894976099841293076276238007220954256135762868406990273191544785542608969104301143584605761392157357529871070687279921832975134878054983870873189849399701343854971405417783109774227030335858692238638923246997883249329092727878981319966736889675090915431828312241509581053236115225084997672816846230423434016272690918109260345273653832828621480239247378010667695416561939707131644374541949099976248190977175126121116958536912 9661452577130328776760236119911575733668903596492589429250084272302540752328965296584157836782000168029397633996561599700168927028859990596887695852677337044425818812901905205086649795265273061253636881910794694840345823775761164211489431085981519257600411319653171751576111457428482551180899711119320232252542722523712561384749546023829956733664223644371760997918543982273318040347307387808069870428554597379730315965418089882467945935247509171801079653835034175159458061724687218385457875846790380233576059475880277114154721557764709991605071201574324180166685080616821177415674145149750782947400960817778922138 403395973123783269368149228969772676317714515927431609764868177578537712472133510229289435641609841417407359351660796760858305962467586174556650041875388449745388897617029088556702330580438043304743010838198958532763877172214705064971450006696789321506176386901830665961476875842844133624883834754177975613428017667384366410347345976991615331979076427249621178580473852990140035631492188482597990705136030850546347489334417260884114661512562294599415721893246972743405714982207575643960036824472832091171823100386007964235291655071771527350295777380420616952998847188570315010228835374447456802096948549289792756 16679729539218095071233429291123961055264906942733209876599774924508327903499123054382720061625316054374698776061269851529820099847498230983724429658909764240135428415798498672668017524104077642068845835298227811875801618477463635489722040914356856776506759411503613972215243864542773365056760203026178262115417475144652010934825947261928855469413342839792940100468734470104597365929802944454659271076690287322705640864063186511499325836121478329359248884455678740242120115491363529075386130835806247253114895941204678707499111941444831755744404020896493756746728091384299407811973230735198270436307407663864462 683007265900408711392437374469594167734742762192944639906240167414953735564266587331010406827957470437778312954193515922541035956880946224351586647119525799405784491253490309600897065676694613248941637930313011542907487381015817832201432540080541551734946612813425830559248044741810490234393726547104357545663507045211503539397831265030422039267740800121876189400453629945713809092904844688173026067702428604352389123568381015608026504313352918931206295485537565401325356773432032355967053600861091140632278670868394833670888152453638463804472834848411691493466463323919909048352284392506679342646162831716536 27698156279830754017105088363631111831090341348532727063771639886545629033634236027983625652833014766919731149188943726341771707199344929692744320861660801195404754216790721372385406189222934839225505206670803031001271037875760808106213104382902766483860456771510934402316945862886475410625371474126828719207591276895542403314108380719254565861504670355360952734992484618457378931266992560211293705213012223854452108513625991765124871471721647763634554916970181075592215093121009390287390224967813935523017417903390874410572460667954422518620786144752817709973085639116303550188746760476751002706589551750106 1112437827625951459281225811441922948518164859102311049563694025954535059500528897247521480426506496507940483438145208194794757232153514400195684485180241813810975659676531799125830252815506212671937005901993358587522551709269099485469726341425476428378130629912448715142106097880264956486280552258222278257016328900085500868756421011804796712092828326691754268419299457672625518270108476870666699835273337925494753367775959862796076383581134247600739822449357831913953442890443825416684819152179157628932699687794594755086296165716015601022798667290623763083919324259238421963607516440238680088497070969164 44249656703904896814741385478279123922317810002052655745785714618471778559177460572794716973997877112972553092723014934685226375666235986403826962086160071441371754486758691222967466567075634485069766911739011754718879639580735081880504816773839870372346237012485809567857006880516496620225649528334886815978042753914464231366855493502808527938610992366803848606628571673309973895992749536316452274825103982298672755201652395243041015367877831699985105338372050407642314121006547033776732951960994087116003894606211872723736743373716100248916367029149754960306762531748339299123969488823379820942277979998 1743263539401273584819940567853845145787138452396188347729586327756678906918352408931975937813280568503583409617969237876484979052345560760807192485600714004460258808355638227659762274937924113962454132692975133100685122360286526457733148080505893806849754589779889875218701120520440609869283618088587485385037825026087320568876776416005894945597430050243827619275485486338562406848829356150797204379287736728531108313832927998445684031272486008151947787623502098133111340460695382494730079808444956018215123745805932524054837849440365899658446367019858716705736604739511543885044328488173739191637466816 68021261217308888340386060498061597174024748648084742032442822253952289607651022792289695271995750060416209269323409617380735253278201343011343621780943231400941545661141764230980130059147672503915422943685169522569552015716314022569232076670016728269976069760045950120072950666827575271399928632389856812627320090521956661203435084255000031891779284054953725402481943061457252553746980207276234167811151019519552012474276551822989858881251335290806974653092932840413749593982086427064436610411265475451661059458898874678064606415126433780366618241068387194504843519547192680828803648419601529990849588 2628839737822131397164513550261235078705480029376714170233598072016838300019503873179401749491741774428620949142874493083562353609785826475562792572409959602951061452437054171579430618666722641432596778379969441085989377213297665091130355126927016602465285532924507125656862861037487414956466993074042321804250224829939959378655959069112108796757217235121970633999736357239293306263395990321947911418620515153656279281187970299639961365688863130241105758706627627984776957425979597480785475931416115535315326354572020431367331638907309260850706981976238366857951890270691257445405786953999226961810888 100630688662939441806364441306635093271692030098623714112525752362442645770539687554770050961148927757933520238411338030592534379129657985778518608941768550341596706722854962589984252745283485439904736047958859261191293980345752836727570719682847329736550837374207751703587295323455069655266935797494474519122511251013856254228064415471007222256428338098544111071398355751893444934368341490508526160376970182185842169916325263917611759482525582846110317154560038605420380728145761805375786638482845712837491195274474087927371508756727515479468127914131669102226460392469897364283084074596085029358172 3815509937538540692449464937473143734866973828462170425505931580597100219844873958087680029438860719217387735980529768483567684231635221580929533349346268385424828259407718260807832183829800772381671162702871565514263702104031921368600438195891740120320359953031247785660638039762138056451803356721778322066623670016989239815516530394524095262501080692766645944790967874626935042364889672095077213112285105434388687018784832826607059958669659900262600724453808039941604062870702142489379003493323954348603839878410914141353463361108263923545354791987724262938292560806875852983722889203694864144144 143297711795125060221729469869839835160216434872342251563607271927412487504410592444699872567112990871019228099492441877500120356860366706437657596171324274420559370431075560877400961801455693592392314938169535078708478805067894348631577574071096724541674103591757967037161121111074557448468936144019469689745661777532074504452243807540239892980410086673954527933793559048659631802018936704951532831435286894306164772801608952247549142315767354699672914978932549067054591353261221216116768074127575557028999518911059191923424906408606726747862858489798066586358189565138802248479178593157192242708 5330880691799169367123551629198326494060684027028445093291446312805422317977021000676831705401137551040041960559386851590915284121767418458735321662380500883113055698274871250211754183854399042851530306347943921333105485649170292334708066747120277347618653943174334822683953092063617569619378324684047661086144011692149808608681412301303569245548934845794963920372094292381883456745984378392809389020478877017624167733715832176595431648494318185204220252147178687620855377960461051925875008811884215307049060493355698368526224927362672052338564287344459106202991503112342958846909762638227275704 196444574241275729454501066035523171392701473991953798373033738472265449415592672167729519186227583458947844851764881745137140216962833104783074386991194650113610881401472468756757579870666914290897253392028520952884759341476909256986185332220497241691333905162359067851095505490698929198286048781147428433882361098431528446506767775796797371570908996212125395454506811920976911548003606018295672551100987901723153591776147661613961959664118105910363109069530463737638639330635909851203272505374005212479057605497616379741520343177778979380550055154930746442830274719360315027625648683956470044 7170849695653731283475260163418424423882182081892682250724668132244156989670021698385283771356479649334772293010464855335722022655565072346107112028836628189341042991056389073194880343093979540739378705174916650302684099592099795563101851294390764469525260162880414035781984892165119122338064590921189737710913665563612558042678682199250005366668400526657333007225530533126669695083464166820486370071663539684284259301347268886020481330028360659833859902660441852382966801965676116125557528716488965873034093196735019741533817134192525139515034361682836719728185706131045518274544173646765856 259297696090744402698517756774281617789667566603451952895284589560205993431818514393425901893337416430264076704536913376841873921879390809985817926439341542729420863740925024317149657226773450036249809508469216763914949672616121284933786105706633655655468038184507919540703064380548500200243935341050907911900888488528203738957239107862519332274573607335807138377802242365965614746552972396259222743681873279419911251238122488423989708232838983963842597860761518370691950769126481274726614129388478723461370997241083385024805177474750116736440229673939117609357228821176726127582383808812332 9288207717654429692896522789899932381452033414417376209942636280899274086488912858079720751872861109491572556592487535585624228948008494322121056319952518748069588397353840583344652591245523787526984130974523580953385329537969808347886868901065006913672984673829849632359696968370003542658936395877796279194361414454920402456429004033574862111576524762676290865908485155723064207651180503535336359189232140347150713209880339139609501382490997417940347246382449007817753752257150721615052197835239266654060560921871927081076979322516362373718075652437611343106102808985362004018127430542104 329593004826072347357341067578442578920406192698685324595265568129439024736941337854419364297221296076230772371321928690406382799845997482644601773540718046939151912105857812280416797291211116743655897429198166332941006436411347531781422575235342482815061244490197889880999129609849655273474550847077887429923394663811357749325304661941719369432983026560083297294576505962231317343385120692120013823409807593697731685989122996477411885635786405747685029215255165510214096763615846155831838526821825657895398341558008888676351206600030549842302446416314463335629267231956718121931953496452 11586286381672368850304641642948055988023214634644979553139069027244061635533757119028787840831229146285712743607147300721736451322861437395555444392631018256190367123395054976260362482936886088112258138821533717460359125819662404344051990786097563075009903293917767900154217640036216668008396710261742348687690029649707265986921610752612525028327117450263594145221031426886838702082628548170548255265624883902729440509823907208740753543026019704635626609951581918026028997601624423628717528123473621604971248252455787787997603660985386943913386193871996996257392308800187552517880780752 403494816597754583888368253747771051650508710518476961864915261200016954834765786179699936134949193745259389024537045444714446756612512825942911594162035576173789040921767944724203112970747187445116659243943414162748942826918250455020418053665701579024487563193164541553877960629694038155363674951751135268291697258221509718499512216295116873046285004075611620583584403481671556412828624862288740503562254502891099878980738560993674962199427033160918846172888481442571447430904436671576397574928206317635612357699505999477600691461449354023537711445953458843660760832825789046396021868 13920862151176151144325240575460426009666103521678068905883102515852367640763312637771653263760695487396987988521840252429019259833915667871569327809802733895005001427155985978158299279409238316060248327511069433651814342885476627710009663700338406754965584904773016465173601941365262278818354426094656056015785400003284955971261758794219476788848354965823227918966316250848624939645411966564176605255964372826027192180724983908588467326629390544635395345078920000279593427836230607425203925999678959531707771877276555352163764968653168658507646442052502147063487720568256439164714856 475812278829149552961025297956181893051816351410219080718876498019287497100829816689349332954345910198608137490579307771649888008838424133781464644924746527747758293605657016388056770417119198412729081878468866601227695581217973238161778379503077103556476338547834182748587084940430679059453865318980199614064152443390748874396937049773477299942670428095033510363630034580316870357051344890557084452446554042320565234983516245369841460479526452322404012335696484981608978683106960497587695164548127833852454912378349893664415552363672792590834700113890236436539665581063139692033572 16112138632125082367791701042733522467189546171255962453522566507081815435921458958623778530732755387995363344208965123182044494740696613194481920961837848358961711185074713767386870438208299394825164641775810127020240009075799582244590757118704716798298805897890367001940150170630097635057531920366918541320916687696484017192959351053187811275103562558732286075010653442894758762194791595343455408404287086240122547958465400225064725541938301594634266678109279529396395776106844952130725963424711992581747774915410681146313673858640197788695927052129952270408781937510445184009536 540536826142021890000948485854316410781874681293077882185182673699349909332046114933045591055207806644758162733284192009179026137414686719590761049869982405751071390575662997763807687909308856065192473587232354740688085907580378131046444415506602606161053208629315789139108454999301938426953317041877359425057712146924981296465924902088818177752551063798711710058845844336877938665719068694584493654239720081993928042028111160524413934059795136329898555820454895725327836150726462346252973835661996707269449577345514263412648009285947251178988870198205650993353937377506858097051 17966285052642426709133539404098189223215095066501971280544188332495353251087854914528625112465043758082701199402579976770837141569934522155659625940025718771828443318043453375109913186117315464756659607935511568066536523340135283587300159652228777148464410644759874371221170354954099908318430546613417007880378502463703923159697610188235393939160489329554163646539682827846008118980676695793837634332245688087328177102156595367446709557111488773760055038575781594161084290883395809190610210397191994908735619612849831835001007283383539667923478823596000284578830123716850763694 591641139404168813927665540198512143806058159054450040163304229310385980461528158951490633948481042781894991320464897466389869590336322590829743498597804131051797690083255583286150342256892013959074595150516283053921080318010034484578828630765141954152624932837570445356133205274764424322502070681488387223956840109621982201770117008506046356609033401658541274765901920478168816179979516457743287065152694367183391371539681133940110575733193003275693280398925546239747965786995403384982618813599534154052176801161582828878820665128094535603074310349650091006400741956690185153 19303298847714887259868120951927988156457752553940788819909765611128421323607297876420294104467759204348499400093624189844449816075254618726666360401931340521924043766353224403545851403850605663110671233367236884266373940902936794720182275856840654960850227872707489193329609053994595450690023635229284395865999781753041696174169982621814965498885561011206838916011521733946086268615615544584236221456800497652954141889921168805692639145280806067162036162304637063112583600997059644688227137492386149982607052983702748202187387097911035099189088769352522566204491478115542156 623998632645449817879985416733968436650705916657324467326114895163717651777663945381845181785117875578316145601782437541645128225750620193847318928574582548754588868729937924293285728814119674516569077306528268758553828997330769424556173462292206790915960860195335941157098015037348063062975164341551812999449970897989134999399992382993545391689310229543631273924313804912551474679069664357532594705949193003034808817993722230678177549292016110166070672944508640085462679467381897289638707957926799144761966852429798847178173799171371424848789648464359499556735363512202963 19985745536300182204551563169567037027378116648679979261717483691681375109648129554191992086332295312982170796575862307708903443392487545546778027481521067299334144890995237605528467533189869702924734379643856646991002879105452023363867996908698090504590024154607425920650011924861563310412497142195911723005904484373605482472569447516813534319927882877210725417255901108539753883201351939857789191863507070210844058938566545735916636260382308451631498577132081044210612196251221707538804460315729080457984730805491431335797928087383484930983785451791834104956936051470258 634230603679872430718238344544765498149414846496659119711483593592827652303773742219007596408767301461957206647067062694348647343998664988800099938258185183936429759070192126974178199292467595316323236161249443181664082187031300977528437440937025608048848275616464526510918180183242213216612764429700313305351899543032496102018334581278664467941706246739526395610412553961120786975777334695244351458510987809527583204073561983069325588317396609588693783953298078180864010728214093399394436237648285056762112173114169383508092551617274128463222592362435473433933709549537 19942036670526756298761498202480758372607565236844754689651455700018915543568752188912594193822912113030084434220110031719128034572377514859712834304335295235865932661238121059974778224082315197735565420048431482402229456946756859043522525488867707688784201778520601552469721351770681422329850072274993403393679757523225834938675709773920209148392126711297541375703789433420039289035239489143483459048182134378962488588685675666851414677244115648425381415600900832849194654723551481460260000930744611310722736836954556611046385171498273280837704767470519768259846636584 621287320673853356794106389715118417516417659212079149722722054204528141862675551316272653082842303828597588319791317396503320643057580754208198332651247024492657554562438816598951916809649569979178185173192929047416767785909930817378278124829061856568056826486619391469063750102161708819300783151265558578631537135814840676351836915871727769348572255172587161601636663006059687870017917931696693257688302981350096898924732214726713165627340306379679716110999199539417978277627741703923887282674770022252179182527320120197206708001501724966405414856825079991204234353 19178788154464736236178955887918538730003645935687220251026143812561601400131829431815079167661493227146863832487106343266770520245166538669907185521451656711759509767881021582867405822573665159736873872149156076375639500528775954103193919529985346046496795062180522147594744551908939779460417438388484094816008551445597862210975830934863931728852442309556389713397706503020664032861434760092085600012590497129919862462456194873395903625591281786598463541131740788412515288685504830144396734336927737764721509624377486376557343574706382737198917288976865391599757474 586624764712237972063693790384135901984883522591756427953047868733159393157113644015317912499045905154363633904006635176545367496990543608136042886474173428098627488797490239330022843597696136239816037871935271019849101814141395086812182939439313594746019309641388408528103197404034968974270088682554978456755216828296276319953038092264074711643413281272000760307084174306285438169400715114371760597857961992181233967627524327984938540487696495758896108151571241901807541844640345443869048695281623138464387426428212415586601020505055140047526807134994600656588659 17779309620744541839354420372876925034730054708352161236213085596347077088790010909288492222512181150729721513599459148041870406918880675613131129757794706016140281951598846350566246749833742434333102568854868307750690395879034377181323335297953327383444749956532383429700700728796063579483493588665150798740127006885920673842691924403310704790174024595717789013615938545021031434627713591815842544851125983216755680944054561893910350954652433140751982637502358700735919046374426358090909797928561427796905188077487330888397794491419682292332671038533406585715756 533936013189326839238459072023181798521057305711484571043925841003733143930884652476224490045728359899521543966601761369411615780626089437320251902191700090815246625369759731049156936298462336441994388158546992638616479656669328417181144166405011420749835285793173154408655903054967155033722290750092123411391528805025409480239602555707909110214008385313368279290100834674970988135705441756675241514044437106819529339765265811310105191175525537804369960797919808664134428568919764523631357061786048656981638004061600844543843741444576350272053727627744417013937 15888677590997883285529034767336016068064458249167265167674647325443431585474605156804085573613011394779135407515036096010657852805272079929603916280393360209757071657883594425746606652936157606469994871886907616617209739951535421658006260128836576426137645121574866366546463829501142138638701270286581535321061577552179606328473215078830506598251645093309997151510267884434849221221101006596612636017347560532423478982320372694135565051170334132495129838002540262145116204616104968189657001848551720710951041085550384558693044364140430737145169686303822801534 468505558505980267263034099451993285617400572762373011158139216331011430658301960269177919055379315969946222384307904330720688217250389269390949751527244895822949703873489052212712111200852701110184992539853115916130282207094471498757790319401541524097501204381605047751285111922697759020562869957278631381080434984109642660877157481935227949155395049857422275236212618782843877753728838015550887565357445433051362840839922400486659687787304328460293179496913251027284149496262738251523282206182781073084969491098298163179127523457793419506276020712380009307 13689080773718337344332555467263238543123113489919400710349423980398362574657834676879859732935332004086375903864930077478488665942387258618027719689902829689039362156442884470326867417246222505747855355744346354761071428071286118199897150940759953637709014460388441524160516348047626430841723092577930413956857654079155293910614135233116834756005151945960672390415056576629559691851590686849710381099669138096969224779234995644367492477901942137743227357119041536423906291701307342055776859480236322451485544070402346784130708449749903975221366115611311872 396342185046015654993873677127690070687284749793870433951472562377676068652555323335630355079789036347471644191441244546009161006206433685257290633250694726887162927417463441861804642329108585649385915821191410157952923812875067556592213556204495865805952485184194534087287357830450956421600636460164585538758501624486251426779286310065119619575235906993919103914677773459199093751577948374943040629072220248848936966888289078065098341780667096699063155572990427521337701175226090716462554216701423848653329514538427826319842522511311328843604167805240048 11371207038391238611026880850104904160102895164282646032297739787443715277326299041550019970322086112091125833468627127171862831743423683819053185963334216388719165668697152994561391504847483640950512424703037771672640958890739253289763521437700106763714204363997210083380948999112597862259933803456633633602434584895468200436632082942731192786601242788641637173594060802639706653227487061736052368115556439341950438890056810478902928047763265725273934511798567479498737084330308864628154021339621715108945294460141088211869496711862503656735005097999456 323285864881520323781403070678763454440145179449241151087112732119003228154489660739565339140171207762044756134183617389591882511817852910004219219410940658109939757494508374639800924380885354187672380730333353763247490862079428923027306330449789761325144881155999230587606749280032335986137337830761691768545520584091652869620821523269517030762744035443488586650432538673018610981378649398869180223800310300564154362397835815118367102698112593193991530934979342178960685359622345144622141706717827176435568182002579360249653482004209843341807720788432 9107815482890877922029511155676397495812671267842678998479809098435514318526824208389713861819690229483728978978455584554451987125640570905624713599190168101569125252870462419381113386728281903356858676767093738145264804157349931647575940737111501473001083495271976332455592995795795147551986072401109879202586081812641285563065385487926307442948772030130739686156551706062482375604501375438763680057866860343822789077831593416250228216425456686737117462069978536231044432137979046900758473501181844465357445493835643359728442064585057216619880459456 254268414330839776930256060887515131244365508723930069383617080951636057213127912529459404781582187294382727980687812760855764167049812284452425405479598553933190105651529010794585654308256621452332639615027649406600819893802601680015863992763763847462042938877638969752505877164382453079523546334293171509941689061042598760023359566574335623102938713488883385975745866209992128194765258304411058806300197046640641983116824351216439127138007963319156965199614517761677722297161468019515433618753950322006274924908315756788579605641003833366142980976 7034357977932181480735134989041794157473100895294670963115859317771827491974877690340522584539238641168653314803830761113163918787786925105840266138922539126188840669930877811802024529562765470223294845108063757599139370398214101937794773113466474998004482847027772386546985763451279655706404023215021997267556445316659784759395478907016247096715685613751725743190341948932731260662240869072798802153717572872267533097014668674616317776763804873892598091790135876036359301553340672257440103940360729927661169190288153123383778855383588181490572704 192847229396354428706954910152449027177333437264447133981631484608367289002179823273896927292780377711177761581926964426048516651327327004782049980824636593835820327809771876279865039322197751654110578944935417984225439449416957795344523329127042334762221335882610143316038647252247105775668236752634380484716702884730302738073551314649623389085455331370579720500837438762684980585226067379205953426313830870287596367534789469988323733739183907681969604915228100531083259582594709945800454779741091385567530428976090860329063619945453840649794768 5239165378923933789344884719692840856965029036869109053581283505762541192657129162326793944346297219719000667921502791019437524492452542141834525157681795162523127552353359315859632672332045989591611441157270621745061536231908759719098433272501396734529180018174781258588285059121364350214523584145678457216023803472416735978458281455203899978962693250154305074604092136893478858693839949027733136720487596735605769440000902837228652690445548633814117670140073516641201349162806091388624705230559260373902747327798605305771254567177089755039616 141050070606883950313735433795527126457648557841707264118203135553297089165060978289626181245692961896373302059616769810398542337244121724104028299810278153560879949030190411703042225030436934415782662587402811520503761810548147080251587159374483067086678209307781198071346660847627523531652289878449006039464339107284255735608094393037390564085344235447890651910381023383285856863905136232509015648543607191646281415966479347659104617138905251536036657752464880652489003724425144240710630448010344401186392264904234852753309206614847088695568 3763133179180506374202379329270087092809891854890162188632949276510709641311812012416111366689195631403832508292264575931709756907977294219118965858409881653817153321344828480625819566582083062641517726892679325117026880881219547018691897467695550842712162793167254676099470266512310430484687972872560908638200143866040967323041129401502271649359659138975454879651373218547172764130629055460605406947293231457115742795858845355977783883158889770476273768204259073100970987270156287562090530559884473953604414557703312612826362396941509325088 99493197033812444957586382734345210854105204559457310328590085752019590053979605708782265053870903644066356017843811863433364050260636682653484034918271228096119915510068786895364207982660560878782988024763963315011528909746410071890708127260421392825385383983970130803582423728784238344548937904724251096856668814056287411841924349218079359826689833864158852113827027031179426268796876414151255801325368626025672406393624530225150786139469420362823115182305258251227440973315109465856066073368981720503287098272679386062783883381890774832 2606795678123707456287574107577460803048232033372892807411124978250929696505287999740990943646496568327671758564580294034282272909488720029999375956982401120742716586907742665289402736744147548243010143684747327459573651247856117461404273608099255119510888871776923528768938915689411596363172962146069393569192991207616974010359238701694172026979855026937259731803452261673792943091022952654985991110754625643818490423764362675486066330751562415731432099500149610949653010784642370931042413660436271599728076276491098961589389574378636224 67685018414631063947273130742581082148031695360329404568869156811179566479314136846219219293419188757965968953155829122878146359994014117695109105551260225780481119796319189736099562617686182602478256726848021664738092216952535352080222855236307463454399172410074782019573566799149762880489622345001135348654033363464493862470679253563147534460217075982484457738637078641111019272952526503315171964148793568118954141600236987527634639531919604294837876070290624863508157431947337755313338966173447689530834825108287029265496221543342608 1741614627063139343937102122386162803754281763489397736900671854918915407327647738512166460741830477714299482074087646096900515865642450945494501603532205633279165398105538824330828130077630699175279142568094716482788853350463569051205803869793746540578408667524947351061826950951955908687694432936266265221835820337460104419536204744295082516626219536316988078936901807557286759695077175907028518017566424603769654193214080341162286313260137315401718517986548040561916025211167308482899121161644019297682902811463988546653620331939040 44410675963683944353304513871402574818545015477833757345367725536117402779382966674361193669225841304424986849771185770552586786012480703063023909344888317817727820840314898078760991279011280434415584776784873586389985856401891974149850634534553636608266083235496850523070220457854165873251046056086047642678853741097408665181112951455379175049696223087178048798292346667903008213810661070056599841914218425135900600462890122709360931125093149767483400940203692661855768881661437344636312997153035627656924244585350257891674530491568 1122277411664381567368326648523395003932724394777460562985988573600288584075769788340338509945714374869922234438990239286817715791801881886366662354456182430811914771867118581395740074985249683853884707820733515582529386231580700008363125982272376582696701396313120907248523523089955226834894372101551009129024292757109058866675877377549982081158416743654217185243309086440952843854556022580526687196326091666219295475838936741340550470813095126499574444916941723668564398263503771429748667270250663289640945209692563778601533067520 28105553645550242228199672356165733547731924298683378946148151462806435097199765094271297313962066719059078423163958780239225292822626101720317474469247645090945307991632144217146673279668128694245094531592022078667269688901632972776710697625227965012062242465491304810482277696541067493166086643008230101740797798865794723265746517399255137678822152086205865436739944049049700746337284562512212735775847043068887243756795041174116072972445341148665040360607946515398722565663239570483844643341335225999201186703384852297433434840 697532704379773061295750234024770909909761595422332447052370430505369032786099537848807353848700476790118393829200296458209521552991253889205524402813531572503716421652980450165512895126026320561315886221535564554091007004061790681836875427767053201849290688867254258896308775939924313126773700180609079240395433340742841283751442020969527349428207284999721425116167722998564940726896561119111704116736086720248951093790300056212912478081676165661197556213308551751571136762630849146901447961904938003306616062753580453772487280 17156108739980020247733711857897221673604108791375199039737288090256334679282108684783627253097917369540955252138783117230392534240571500433820834633186822007848804328457481562405521431687676504447296147870229344192202483021206117615173692358875994797819036096519254642609924182348705502888425585095226266030851528340450777045374949378055773074070616637769755244457596484965560665665756986244563290413600264100485486432483223950340571136926963029208543461940337437501373790610415099971434479870895854624651762197579133892716040 418172940734628531730018632406084218906008507698961222095274929288137288907316822831664648166141076628579862589223146918705746830895684133119426878936411617414888060935840478264203255596643928187532584161162579452284915852518019352142939326096664293442361304062025632988834566096543337395702730260837496021411868997365604568988428348362623762706510712713775873900136599048764500692310924204990440174732052329640221524425213506629622530737619704035331357251255485846578852726404072103704832555778310862524500307927667831684960 10101293195640325060179755603354533955089674337594554958812466371791794650679819941792043594426888325375890444076064497157977129923251340852344895495683141796154377599601318368769125210275559729550295044814055980205233360444175708613000959603238372260590824300956765360976938512557670769444448451878741074970366636587287168418265271416693833189210698105803033774280082438001574495845230177003373766051730540910885473689206308750952291341580268385514553168341612466093012069841369432111656618477243048780786303977994657869720 241814750807794407427105529380224018933928849536789705299187676487013250869957285770770972369242233035047356954982760060772229694804438387719470527099349171403213823548082216941269547001300265954059129304625054379213155041402449884467338274186531211852187546659182455427355506101171001986318249086866147297492866113182593612877561622859135735408865856238728017714553737425359214924629471999864466526397415158953521481280648176965459148895815327417912712254618606823235181516372863516652662569302597268341715822448002712720 5736857613456414857201804877503046610872351237634699857582921687500558840685957398020656997899403734463735574170841848076639855510744714195709051989225853312601282397865659850377844945837564188774859482160061726191199925335638524299624037520860573026646291272778152429229256723505248757901233977647660028269823365349106760825989999891170459108304734857229132745825402184339711324452693342755381521557938960436907134126381219932467147167065361228609313521766400115444519052321422628851278309809114173857118563704771325960 134881188821660487426695481638483422076817707154338095954958531263128223430623458577358099896156951966538141545574873725359377934714993276647142957831477575806723948874446473177301470990672106397659257157047039576598435661716437713183327766840664118485120756584298748096049052738025807402012912593453729903909557882136113865957751354434934782293350675305116142954575814480923522388416572574846543229956709209404785131264549347520969010267147322370627176906243051772000125432103784028398902583184949866607941889317407808 3142788481650250638744896185171633857389934978366231226049277304237746798770334061293524225801420632148179426401338844525673493967119198831598955952967937337894170021180847282477124605157017849576015999774895083414388465385634422647054451994959060556202454933302806824415118296367293984769266086392450181825439069535730369343366868211202103539595333959492433609016162758600143781485559497456910176786730592967085836372794803861301454374760285485354236041245888613721579084628101636037616368436173943174887202598586952 72571425252744642088546876169745153924767165787844604255486691056190708899065502703526189679042740108016973250731143760200386449285672650433299162463590097155371378660003200254475892574073255041712545958483545761204114627258649265491897985894716408054120957148885551032163483289342643966309183600602120504272245737649041587740504815355714427018706332590088220855943192624890623621188441796036921141192403774177160853749595955343528192430234249276177107408312111057515867903963916940431394525520355565107438073224592 1660745252992876742470441177198474804148486400249836834479117019074409750497447731932735750336250456793146755625131025941911860642195484090129442294264905921439448442265489807648402760977198444832101228408249671902180217617137470848355198040441982249386025856637343278292489208588956515893093887952968839250161928394421468454438969639073988839150772342311205800172705959382071490253144376379869773815712012956853864418500545837682310811927842550687863613148905325757463874860651574716039462986507765387678214111704 37664069966745687738806450667623074856921550301480684057795282304084748332919062533289127402192730472752008275398686432069981704427436454920676732668490807851442350417801559276606995287651734332716426929369610330778604189230922210930634579173155260144524015131685737608872435023401691448145285662845160975547606678843506980928836543526787066119126681513310115289625169424062624627121260987526531174460625673951104752641829108208010384876805491927033006157134388814387180284885288031358585382132069368424497261408 846521879348204980308515347578681085427095248712976452052603602537264383508184994282425067053042573802014261954171443030494411398416909376954130323298813278011653074425547104317862761983577068349793189894973697511552129793212162930720544406240625794394797392418285029734023125055166865349518005855985776657888253021877933501287307794037063083606660089022287047039730687029831564243875044842777015922832704306722334542943598759745225298310341200119785818289945838767109021803703084447716714567336345619755072840 18855391142377404405008244392133427093160074977145650724608982918769544204221694228402434020771022727443103993119039265073402953574555976048493126492898542164441368484249006382096081842192945599187823670947151543384337683163722566534718521460745243528726568160862974875017586248663408205018711330066797115591166686967186073198100819795415972895055339680926598672683824238304420826645646002678196698574952400316517639201496703694698539759087471319955828285740890694754224618368791158910119562472800887528046448 416216112364910156441979601356197941393261045696763251380504084174902693776625701864253340968101252869340839223805288903881140279689763106859422045814153067602305496815422374572104984086187087641106940195642682867498647886397221359528365640254092295781210220287984465229294542578735642854649421188730241879867268143298665251912555638861694284225138592159743612774801506479161807316528373729643925109875210731664223990614750234098625364309706205875599001298191171469997904664430389661581466594651203314817560 9105161147520598973757975681219360896549687976872045612308352299700790611829935021043786722832700596115374267040871664581276063611493350964472927697691912757817584556841953026571697194083641171868693222305117037631760275308720927927672054352298194319979642901868399765273747684544833007392108835306180324015133988281635571481193411304451643422830020377103987410771588892837822480135338254934686805570632390385996990554690092095124395741749385667226944061596568796356556831029938810583142214773939393040640 197397236803805598938636680045383873502064256823242202346280587736121753077465214140722428843071368045004885313798483157341169315748382662735597735348551275349921101610217660212156013865589033734390761738375323144458976864556986614122495538911463459376588017678646859735782549096990208552373071775933325396187806208065481803644945969662543881240398609925787257769019171195877701379168838044321710601991200943870583843269824459215491646877610663194131551094080906059994928354348519458544914839451476019760 4241098129381209302063157336616996101764737464196084320171614450514411319635261195254384428429244349743600316703071662490928465307861772794788518334628678610978098337448638696529626742949783943780496206937179850022830986893143015471936238094186458461892744821017289520899744807110771716158740279320434615768341119185291074348741012778873783773337145983338106590279510619599550003765311617205630202662578179305397529684591603297600057255229341132287539140881921863910520149290176234858116086504379132640 90302211117641612400739956840633394917628351678537391631563124520494494707365208333789273449792066595750081642018326980681979450999381161695134188000152195605874831025199499587695546996379179183278254201206586646143833387260186465225971514372220130971512167832328712678701078797265917446582090126605594323703099701513388672731279510140493373607628211229884927060371950003205758975674809300983159213892278549862166657201004030119528129762537359851075017382910294293533811069402275743344398626030088080 1905461185913394672824503900079036777247054439388938621954494092463694329214235891471231907127654246532011770233947013797763455923554769970708033719629855824768646150306974415496875768251853803979121380591819772273465028947559132242767641057952549037230084163172288705173648596993533963760015132294144096181035982000823702733848187201141655823484124610052666002643394021205589791875829381787141127026035060388948485264424331820308017533597352988720267994881189202816751768741736600917839373810904000 39845767008876177479180257746801026221895854926238654517673744485295143307820573536350340898276095044343829652306687321474739336288626984312638432267046103356553814456210496221565749597755985664489199942952175619847256789739444770401380848410783753577887911694215044944189288546715329538249297506340621061284807341154221763292869232033502037467289333364333320697013287790480742545479325846410013673557033599699773335629404164500336247676124908660631234895220746640708830698042300954468462232262320 825739760353625282217469196725414444843702926291659043774806369061765022724054816033022954095389241298144020714694086991378900453156271541697380585489324435767129361123213630115996495037727309167659206917042190573370841949471876096494960926245399063778687533765535577384339308662123532515362855081766946546847477564238419172680290692386110933210795953177572545398237536586009555337122643462617530332966175732825183449465388732772856829517558797272044297923056900232318444757106612487202282860320 16958269695645817762033426015791731340660373964143094096638328966174416001514550931013795267766874589374170456569963925937345673987634751715540724309000166931208591443293343538373400669868485845102824403583442250649536655492245162852393760392297885621087596291854421630593205087520646096518589451112937008704458735505750159700577274021147070579950413207182122605954827275138976610480176257928560186671931108828678977797230026294332884537982639442277800113913890043526586942414030554352737298576 345140149130914055109309829676521501400637974178598729072931951432118039089456241146926011969319788055792588352851596905430076634856313848102775959054983689013325433026085601773077671194093992438320437054373450962239910890283072193800204152834998650549798800981218739749089365342566019046150585333372768687928973792394056601055287939387810986302801695438418203874518173802920437968739898737125559480493016402206125474677061457764429532498666484376696543418565823450882544401849252970737600384 6961184646220612840943085688987968177904810457780427428266344347475648635856053166664756385397274587272053626416630476925107028151410258657666545671532753245642633889656102186653595710562496404856777559096759228402924694581871492522494526258193314097837969939244871671077017139990947886325439963490015610895759758502780074731469155430282763075543825812648527970221873711839636051566853482884222291049137589681766092341884034047238071144937936163762257718076438934868812277857334283320903504 139136965672666219500083950155736965951338596146204348229330701330062913751165583271650994494813717134441885880882293502720203771783710100600345007615636795705263375039579093476007003257066387344587550339380065163023133315515805786289087802968343757300539778746878424001834578473885441404874736647325160837595546346561788364965626967614814804311974983201517387012442874029807751071272009509039891321945092195687220862782028094977544368193248488957292373889810415934562042621193662783186848 2755950641323643127235447102232510699812837554007161660106721594008832999397863650761617038375735714411351433205170154633890767793113088252377476479584290042369696050224777281923715938578522480320184783713446270511142746666037319180059878614597719259820025953135522762180418637964930849763839564871120919117305126161906584304580030305863950063606606782337155853321341792489939756805476619750339590349417766544570908598629928560138427075272162098333517123004570359604602299413917293286896 54096299482945369452749900500310724314076903494040570138018827729216253336929639027500938622541062544923159782848983096145448000526828082794413981493476071790224366597954646285581271085662090633482072467986282936643555641922181511869617677756471368661156431860916918435427122066121499324341323163903338281335474570618949250791762565191149231435247198524058392186582753194346128675063901643066303069151440733219197083884130787225778335048235090147655412110416720236533372186684130600128 1052273007652767755396974445449991771950002050009347180074476005215843157703643949675729038372804072266764895101527353707654151306710623902417998332478286879412353950544463638851336585623531411132136213059396241661620244250948949162933043154829644429544675836240680343957436928059876628106886003932635594961287990461986158988885146756810410103377281171425678383783431474822896263522394915920235457795496460669501740970425364268164036816912099137453225832057570930605387471172095876688 20283898972397222507899623448874781092322659100853887276478472015384884522694760262788046562277760030411454863214724853414858849021236503208822079828048087142661392492099916192337531907498958315713475421396787978636853921650612780370135553451588928406366720919948081710066672023623347551010901506388553184047268324137482019256456336019507709858833556932185185014625984018036003780120385943844764860718058476800722145721708934982674792224520777646045453522526152898592465600306085472 387466197153875359732457323802834268247962159038132386997513351006058568130942038844632371683143779809577858421418997531702616352911839044351925944160304401211269336000223988831868906439512499368597154949179357076026472018818322478103274461203068529857928167164120211602611324049291145309574786184981914762681092499199713490494134043514309536943058724248291979805639700904461775846047641836414815228494263415361458153942518483086803747926229558343285881265424642195121498264117104 7334536292883466675260282270587652166275579956047457782480652059074067553867281592926020642877213842702898627622878655358921200754039938296310876364383853835799469066936650418886166653848387312796462198164760903512510128750119225229687679582017427160605286762689918939721248972472935247117583575504600660692537676885332589461898113833845716926322589640357853575109068449904068943801908456929774073129487504832491136040769429870984835450976158391574629365420461296478121706471168 137583039632090142542679697916896042597668613317612510374978027613816968323196312024850636502499259243650100042678955107302993792594422352045463053127416495056631831973224854484527741625268169979932566821205120580277525468913938358362359353617526506034533203637537390186803027691960085396733554343675382068380128660326318033081838394367658419821914584746158247166955642462952649158555355808959014139448623912679915408697713859112585058740289066096516160796842619391216603607347 2557450992442859764150655108924481146319661286438024621514727524563775648498634270544794602799369431881980571923056933422864203795069910473224905710068371085073334301752441089241582612865931491726625320239832982376470433233967173669633810492425175445878788936349404571045282265406683484288029803998377187687972245684282974135883562788260858018458182305324795560890192108821586620112466023275766672597360212013246551015638624769345830602040683922876866246975087793416024871646 47108204901167813733276634542151695098523607785649203949951025026319932675300773032079596785621966363698619890419573104938974004296107136474148975287465802184647133842857850996239449739448158440741846193394041944954533713238801477809466716117774736869789524717330108541015383424674523833751580558547492310665769470740286095435081732424036694448366231251346145801249211336635486102907912078561521812019668848971139639186066444732588885798956544174678260402194880232132644233 859862651978619815437124199910465818527691009645398066696244321667460181083697003914819881280137861017622149168473652197922523490351599216041286702771520582922175679888665602468340149235521431348664533600948249501298604729898313049603384754620295955252908293723827208931820987992729194678095163451245233523124467789304491925347020721092082116169504944833404401952233645443040647708599566486670319886113442434817858632814638905539443957613499271061831553295131642483720876 15552536813697040667858379084103808501350142052774033487522379658268715842981238262114843914101192293170679631725329621294094319547940759952839028208078936795251693579823568581061118259620305618894759000725828583332353666033429334711325422557085292966434522678339429763299934178777880733196054246191956276065264256589900522094020148122208055702219449482614327139703287727837481478141551715847609821504721259738960598717712931134283281516582360406676152190488102446938347 278746346391910490934753842610656701229790238983072324892460587575433140664109759609396448045630514856941332150484865722392937653147001072296223758929828320044953800014087186510254065392654021670688619529481272563464289843050418474498157675610438753634216990869139768188091394663249255982030787004644724545420542080135479184487130228850329510443407384323700492543758537434237212825754111603502834919818505997010735858475362194697941408222014553059670911275808818307202 4950498564414051088334685501420761020584228474470193340861322676006489531117721413683654642203032564943890338411432706202434119582781310173524971791428715441364274470243070722934564248312854853757472111993665070236460521127173165314612685150632958727227839507899735693742902197793998295035722192458650874706288724017482980645161691252745163073971481588084056395489950882756156402086118772284495204515598885896343201917903748626945265492616929547905673763426842514665 87119698386008868661580943183592448059320048746689142824649167723809304771909768778594378736091352953379111727419467933488202820759018024433814736489950234357832103395613047236765617110631573956908591215576680618821340633402335200739881348977582998607086716801187069959715147548912890707138065042904467754784274546489504749015923724176859224185659731292667260309713515515468336656266209060501538962591865896037857561939197380082982601096989790433044403953893649448 1519172738336934249832766326892212132223034001485930315184706763725287037318443146480731990158812951294711817898370746908198958844854737962665212294928089512886425723386235686738807233772160964081889048461269533744387588774453035663942880900011196873751977071684710857549729571391775598283522940868188060152532737152891022233987786150014165397050840633775173833041845260944935730458157281132528785892115429816117905992236431656167445684202968009391022663296659241 26249248085962412311600061566442106244879081820464847269544085033946671724720378306269207264637269026883469105704495119493306752550555153733003304191594515816609035384001401106412699281537881299139151129974141000922594153193266919601734625324064774212722196220175520041915796877343113745996572493184631042244787391367539804325124684971789726331056247859800199367999391657270374068798594595788016570940188642351344385364617045321321231218853070582079139953618642 449408077345756988345987313220103181042497095744600582516474659497786973536962562685518027344114892642653694750554781827034756991385685467438761898266233315241232695484193875599005985036656677831995373022966148946375462539421704499954753476953223902674048273760204020601053147462200708334463341160633399448212655705396860535410337741694013633355129530048472193238864219991854070060463796992279604361648273310517001564086504167781742611873739009244423041000731 7623850997946257988261919193038251490610797127881048025772231347639506879013877214750529868521030015248433222752112657655256951631222563003825819827014342685548392438315855718811345272123669504095303961801263290982085586981419711134317791522507401032429065919396947772078645156886097075645813613941188802438647895930405024663016809555399642687178842272531809634274349897696091578393305354163287244918152145219070020517146168983950281916553293840131923710476 128148198526974224204735010599110859675449581809451759896964134027101235449949430538564683157631228821589525600055049787222066953232777222684341298221462835592273442933004013673044263796352592466298799133626231943267295662469405833624387239003076789637748349020336933537669467333723648416809217071321848576106000062255115915907330427833030681286521851220192411296566154629994205572233914882561950201986339007647192689748686030794540872452265433410663515049 2134273575302523855869153120943893693912930526499477913248604974089828066865242353668200877391675145791476200553475915716621387159204582617276030881217336184886335821296505438339996591510706253096474434984166054463527785026385279927409797102652838341089485692847370808975245337819172888193114198269387246013038507029200513337436393565770811479246803193948719373735263562103415915963248630300887891489507161396708190471926308080878808629625167750260380238 35219393899466391823593508364820140474554425451714184494272616975236915209079058732023483177244435269633577766651029399222643687422515330831955549497118020876546366749327979501025220244506659876840834437118161775166484247998966285720061360011893491204941430201017542911660701748087202530548865120229499927782356992043535372767836533370773087362473495591622280159784162884177603106080347136702471200168201878059785889220998693379685773860537134704414851 575840813330711251540352106686872236949704192957118238883642103062677225037992811567465706351776212417158242314259717656047713949122590196885804276820155901313743290616981004410641263747257295227496978794766922503096773399986757580969137552148502387201716834068211478103220986112706093786100765518911840831105512226556406616836014490440392710101157993367859439557324120647312790921130887670705538742052235722856547236519579243857468764803952402552128 9328378960743778653769934312522420531240530850263610510480310332452239733052208426016778366068885848789662689289748289347456151456565333931924843345787635718262594018917580004820243526682822999210482412950266529286156834940886925459305046069596941575699858950295661808834494018817280710076525966712567421799753303870438976768901477297401827191961729628715596172239539064637917939318160874872866519662423790850527354847885626997635146599043558872388 149722586758269080685222236961531994995240862495122067616099958849679565835187395649167258889800525286333169841810048420218640374661128465526776037212821441620069774397503945660432912146504100411960696235345187644153244723079012732123199361648223038661329738448149071547469501053600758138829374479230437987037037803154855061878488005202849615250703577581617151389031441368752187655214966196017889182897536404212286628604827728886911460273307037672 2380893259233235177616711540823552982489808065586929259035866305728078756167584937769150681645974583095467726110523820390722048349741757665642602119653180807810132630285203124815916590033581138878705839517713809278182325642835449517397759033963726326924171813281955663066230517658661740514199769551205475625015639054683215360274012262007323715203519380492682366441824067510221035491422300999724734392065681568687963434397859200177372005221969804 37510934131561863918646971587068604449398143068434287318492510149152377416099564998342417931658552005504256965351042925633734046162888333979366105304654670378899373815466918230770907046754794027843751656479031342739548554911251179744501651747793027949257294279734320489846360503148934148090802140800207213011112001173679547154766007646443269705613031621202867065243154858620853937059144257473240068907659441477704356785060458422549767246665168 585510784038682519465097145077777885876651686641844112362265829862043387047893220075721487265474147510422240950985760602797339085507096752006638574733085622954666766751607720251426290291852086763892840210661225376936316460973669636548319865970818058069705250914306870208791830075821129374431297963799119833883836076363871849363684424756220293689796597536115113086365883680892069264432090148033885922167948705966816206533933959391249835647524 9054501013780392177359324949161610622662469264779480262994660246271854677074453434812878225507291873027371685557912825988292795667366965217047865615574672817650292919355610152165855035980383165920498931669550469965202156982298095157488965425003628577839159865786151180234743876055575330509096463660797764274393856843072532243821046427687701602720250422021623469316467948466434747321787323167147392073628223823378110150496406649279987824024 138720329681335020172799914332026406163047957022360629168301113552410483743502833058588125086475148989230867314056386229547726235780908095272745134425126348241557970137290068639792236191265005674739515402213412760559741678304104515149911955046507398189630018020221449012928767953894117398261188613192823171494841799041754261520246964711075236032182718047670782729096584649167117226289978361215094642214762288740103491396216532257061124556 2105498104042308101048312964614775680787727252709411448512316296543163005610375261564721654510614448374787145902433501203765198967936592930786817537904718874341488824941613561453553426416533861515660059648082836074182057291733118123152633514672630356695014967554943550504371273603275100395461093646961110159602828673477045454650154666752712882520513938224701151721825657649626948109804638815433605139950445851974441128488138529596378912 31659332450491264699216806510524686836313436503626073867492292038605381579495500361765068809926096375924084205638906903778230086474752078321275444646709504563059883483196757276304129391102716039311221189005579949025595769859658493160998032868142816642068579775937994509559251272698555412459107746536101305506762307023341062905581711768627482444063781972300915178533537701418950834056335948209157556065859690002327883051200540393785084 471599820112356540666324008165855338689883746822734183645822677788166656879738104316173346827832383629260708376352755481487398924794279256449337088659359479612342550750259129932903184832127217989042943874266095153307071974420310778664273916486759887613651119375799050371523623963362952803736960680392668406675242790979660854458171380294064333592477119931934730378660750527048807082978083743880228717594891470578151462341394958395192 6959261016050184370354621600423296664377323082892640837735903719681455640100153654923080351903370203695829769140776396831667039054259481514855629458882258994212224807765914210536943689364970401894950097581466940222875443950065679514295559901482566288931651937795708653612112899638213768098465725977784959636191874364819466078141614552048040629184237811207680314935177316611367837828611887923696613424069062063849101247275775463412 101733196554163405792351711289404029638914523684722447642172175951720413472594438662951244087351881526721160491345431746040821226067102304722524215985318836040899187985879316709282512039325276802162202875789036029883960166543388239184638257211143847222485820092464977510965948261148878057704143101280321573498161096433146724596813520510418486358861180392205243943114682996771227766531102748808558047045364023790480193168405385488 1473209772665894300602206573905060777410434219770242632019846944525730600418845759156064377571240422114848081329903060681021182430683083787543967585954051174439626049315955803089069892078976544818255711406102013569475092712562357612002074267856928416534830239839431678304870151748128147040679244629095249155796487188237952083984772015946642655134578834565968642805156887537133527038162362743203799873072501815135272529486741436 21132987795578515809793775920537233331494338788005812086442500010704046660922394136907745033820943971555696151240671853350628892482431855856392953026924075739397099015303335970769315080872454980439777717679396324874406064786056540057291802686387941230328610165148453622114664840990151181465356612602260446656563253014902949999174453249907087400057965752517594493059188862988589599528930908985226772711917479630123618434942792 300291823580432891319322573720895285612918725545092936138796928707470099809263032733715811077152396139616915004310565059819267344812123616311688592582651009594765868455180299939781452257973770472605488989501176569205090015962975464410619062680129894228068318361904831271896634034966838473013653024703417285858203268860482673064615416888847525720454649666527626243391912220258247422116818231557528453288623289518023043976596 4226726000869669748399875090366206933742648008686569249381611232259646095966221209931729873230491396730198300600384103273144521799381715057868437543870542990271303220083878134235064487315710451699327558544251467915044325477485707932698788931845334143747847941430052960848280012809022805410119445821107717320774810640176139731941346249323521177744346684557885743422714635443768099103587652595003823600797770129031243247296 58929690399752604803210665238501279951526127276054195222378767880129841437580243883627558353497928453680068138722717280820348457381256306161515715019923535260987570400265140114946558900869009360828723302156068206670679271280495182193898296640425875103501374118250176218796398213327719851066865337332462236331872338454517096852615776121339742229784617130347009400684261073018824820145462226869338120961488491541322190414 813813693800088379129431933272822532821612867327514062578723804646298996162995410949892396834352185110821929724077162671252792669490715285013746448033796420005689476123853136227567099182757866608908672391573903415765879152683474010881685344256445229114725876702373269337069699289179376034771398627809702373160861834752697887196263747944940282337361113848842831624235081843915294042460722179780538542648772184939282188 11131858826701535646960637171148725024327046109136898987991160100143896122860798007195772105586574348456615622727857595079859028293641776680299423242828141303710561985723992102228190159881644447488087030405121057083835975124214948665065768354232219995872974382327031800559140268612826442743511837919291803882254959827905279043128952274827322796547253297052568106374485538558416682504978078582413908557854810891055306 150817986650623718099462708300260161170815814418013788127421169212160707977339908337604352200398090043262227149952078594347216513813553114393527116631484004421645504823627477408596436939524098651863327508281758391718393519824139628707300081346975978584540239322391622112550910215448849412127165750677421111281329345451614358146331707381127926163583239515926703496496861465247383919403526895092371446956265507801528 2023820651117226857148640546249124968921035556269777514756685470658320338763217940118789799789285084031229239978698532211906292303035325365716035348546353497757547988416715889674385298871818157946953319942441116490251497007902114318813086800989181308632140189616727136497969240234641393067850598823268816665257305673034450331267650234676556254957206850434422258500722646302541504178236089045092998737927991294398 26897679686040003087482085871086518664328254004140186631129170669647294644473949516720576704682112860998940513211382849498174639687971847397931618755518759318845914673840023843008667545443856992145652798064550604167076803128804812623388154107071280059324671488030344463169201786742999754781291715848999440570284359062268817744658135338682470186438032871052633015467868873971942103957857851461277482051350220212 354055858466212986903331597062676966239027276434436444454270918886751604632649828379634010844598255183870948359937355057793772709869412793169088840463419436058378405953465097025125717382297195939070575609971591345675458914031643465202627003199414086999869600100687666525614884846286360464990033704945910733217593983108240438956029563216263828520372033549028180992429244278568943393576551770590227888051509194 4615651120486938782214859502638206436504528545283157827671525156627401401966239827015447850275618428999668579158913457856083831183286036165287692551380664282799048402981424194245349447146349132394381966615097387577199612901677233392225626460289082495645874280914714931590102504541640268843863012263705433787936659673068926284830720342430990486596623509412577067751061362240918993315807328395487281933767888 59592035352937509049208749886290610477565847747891792877656721032128175453680652064511844431500460271702635517173781431887437881933278708882160825831888757621861306159992931217234461712725505019081859951882738852263565843193865672011082397977585449624286303154693917849247555543616538600456227394192266222524078458902501191854131298215535871308031584297901846034712416529906566395640189263849920095447674 761951151557671114873752853768636246675568593948534575765779837112775718662845163354197130517143676985492518250205196729116090691165584827700422548995938258372126740974165736584422001749309930709176038961394417897121685421234470028690694141970428212898259971012863909142113470531635962331653177833262584538985411388393647263961694296347742905808256676154841372791744432311521521677362701604064441487284 9648040028144469861810789133655846802076790921864689721574614289211691497297000233417540484091411083024149274581759783097755159209521266631316164230721510153216870308260502837554823078405817724278432814374449648085648373282250760839683085791669078958332213819336075864490795141128979394808518273801372889012934148163647349211248237647973662460743802761076957245797499502674633532479502779162130810926 120979917194116188160354504910137309979349770460510373654374663588169362997971724414831949169215152975696310055882192002920655628735861398224312706922560208620784053413738815538693797705899433531297416983234779261058487406799903086610968583404570247183007113517629870475186420407850518160384312858110698347860047865492248206741967903562613308792025750957936794286653956252539477484373813600087858232 1502237582858296785937966945743694584702671298235867715668779477595287959147422200953517675972870183217636483098160852186321096799208545552563820780255809118282964126204959391247103011305983962786442732776018536914636492546338186236910139845789683102810643534127646177069333358991135380749008292390123357639962888989903729566932369695084307249735427328244468009281330626340822280315061631027371194 18471570359351364583489723176295734677414728377275518180674341871418581569700383683112446630110632602944116297885249077849657011684549485513904688853938354669169754487260788249061437234318804619224109449963768106478218319541470900674818257092398212025992859055905871431325761162494808912226014918318182259142515819895972784640761144738940984235695649198513146168115118766325712133031684954803852 224904080917897082467604507206912249959278434213993372491805787558532198135654565439191306057710064006809597196886585863372700783104085942093767598937851732140319061184802164175155588610005444286210442476794562339716741361494999731014809866267261717254407067132154534232664039508405583555778631923768018330220373647308144467245659203999773214344891161414849121588098757284505048833133733104382 2711486220827536188340257335163012400536479954088674233761390053833014631621889136287989800772923429900312158451927015495832197084162582651734788206179866809327690436836175295450405617123821263195278757001812621429523643012074179809666264933175629919959919042433367768466914402513380784518975318746823388738938912614607150987522776480224352698177675095943153106979965768782433027618152599488 32368457250812878190171358128670395382385020514239008967039091686928347221834824062652485224864196200003264951066795485646658259340515319780973091525705553163197213581524856948914679190469460356861311976269230340719899223719373729785873807534061497145282617198309724486450791678933129214146070995135862668844191487984983661596117271463429937263202201670024445962015064621499996922846955076 382585820195232713162750746215145110750934345797955232857115838108872296016174965957152357105085027375780430517821869209291986637316329601874615642336306951613462737022191813248513181462733788323314375067952871093953878203180697263444675030840706168023702237101243405827482604394554982447908642770543413474977711722244915217895651578693606500380206253384293794543921680856120024079350632 4477292802125617261270477534179811890209554593619946017520503223640690889480878129511436638282344270905394671753117620966111797516325165378730560313138298323121337874754699470068522516780982481168020705466822587878609739427868558756572374809374475289442427712358236901765423821998034535851591577240097700622567908804023659749683405347421209643034769566640327272302496400441448799844236 51876314637951406827941124408685538587567945965471370441423453943972491523212582379616213335549362754024761333425425283597660282886960051113141268863918887020184540451103441108963099207122699012523707970817942771676759259272128949359768522263246645620932135503799346375699809547971349712736756322794233123707013312527427226347415450255313899908842413160671242356329136172761059544656 595081845668749983951215688884539033649033334518489689777345708015270907131958385855978559158931581250609134701260279265565927265230043746915432501607765185055973130158963893987345437523563176677486267170944371376826633572582951709588153778650994389997413983940183833201395891962254071898518268141670652977993629746199050064694971806551314353900696859967445784832753337865189175204 6758105500422984304440136484179059550735401941153363471025634573187381845712207219561512577549305599046954958707348030844733244163933204315472396868931340944865480655610733720971073268427014058831420531494258140398319329467930265728841777067534611328970480656196439749491460268509900451044628169566567004766325085676139318711726879318587901237953152607466217724802018909656203288 75980187397784066436929807441633380982957506520457053741003153086521202745629905651911582004405544117957005242607333810715949371885947904698069569904100232322809275630504037251381466168615498963284818118826845280495858962018331047698560860940277490899950556242346218115719567370436730809608746036454106970821067187446605894543962611251812088652742945006117270997540479772527436 845646891846403440223794191599340030485642488546180876392391576340848122120851838695215863532278474839771610439253920540458097075208616890090780467340860955383125877275697868119645591222503768504659250600228908172151831518934683574073965949979331290489774391183237928929959972236143073259376297739997876353173695606906382358136279472675433183640890656011545336190526901264288 9317018507285739674732620299730639609864252984466882144315474102182102716269280017308392591495313038547392819186980477585025458414373391569633122481130140988840633805967131066116264536230341306185179037051329652599564632930121481292501935016397362898492109026136180223616162496140546776220741138985969668372719158210465147092618984386243667476204874371513699005626886667548 101613096344222719389093940672888690123614124518449234006961079916464170343790798971052985615860022908164275194454744721419485652715788001614303793036220707511881123165654331859993303238834616453669756912661502271996871280366381208522368708455820682596470538088746370226243176202864936715509040190286718535477768121795334443197070603044396117448052408248728846852979839992 1096964505663866107825561187946836163543841617008923690647500613960375967327649233804395168436562683826098469547247340366918196486598612663732788046062094365458687261008902085262100860978057127053973830912730859021649689525629915152600087366834711775788367131684691524292119387124922065667679383488970466839530488264191278498949228006723273324311465896799106104064052564 11721701992684436181091931678946311594112905952119099106196129440013213619416763997911195940989821030115043922808680077285627787140776581973682213466834602676202547109531789971323005623904597370658379949737760454430704019541060945465010241026557315912332401179965992646160123696312692733520905563162582662548725194804429883083805335882041413538816204414224437790154768 123973465088240007685955018364001507899047532234585475937904248420690665623786597608359183734391038265214037353556101517638413695818248540904160902349304362219418377884390559102521451293656263068370355384255646637738355579512429239327728492530588170777413343153833078746828324009540793262390030748026307747934179015580370454403433278737085856638929292775146793007964 1297750549655053906194982412902341036283149191978716984000531052864959446669599011293853359460954743561223493576586921926782088323833765926434354020338276655404526460481365860390918213932985523218526387918906570316387038078481785319105223232459780414055721232795368797884361925194999614808229281076957589214175111574753358629673805918708876543643596311299909163144 13445045281377130862379178402546663114564196292440433574136143406048609527092797495330314452297651035738262219184901596925485187031576750392910902996461549260909178576857183239939565309844748554471409868135210059720376159892758482403478862794904739629244170542053480160563049335566884146263519075795884199602540834755641778273075400591100138556127952848068551796 137856015499279751029466742837774322161467023460057169165550154684014554666234754797757840887896073769007269484062695114288953475444305876241450859703341359398178687483380875929548508330471097031659835522163614709163243839266843418601344162361927257833767230595090922480009464954846858925672206978426183013425921780837174529367580736273675383686608504888398912 1398830528283304610391226567308494235647774366231179884020886618299019268991595899355327177116741489799723183904542350940849022029346484805314959684689070052058324980654084397179043934803473518381199439859157726904196068888531837786852058473939905727363793206232613068629374094648869309046874189899010111022406415362366550224905544252924685015733184069856889 14046354031409013502919003843182824071629613023821184953756639616366115742438595320287073828763471627507786338600237527086799141898841061712068116126757921138034211557269061071291885481966813066547565552769682386207039176936206384904611264802836170326686045856576818964541151537113640860156389041173036342076463541127266649473603171876268828880293072005146 139573870073085638570386243576359319937793586876382649126123624962009569054970808421050154656803090541952786866806006074933081130985535060461335334344638375856497384831121905780209092176340193618676338026440581696387703951341282896580072094223410795490226013789529127499395117889016631588384294084285386303282913360896904598400439207848756743375735956923 1372363541977305278312529572798182582718276610494446314342347766097084045969071740158155970473720212162569649849425188916239948032379925374418692942753138732623147853143907080773680648006735550393337135929211075238753873443012378816435706496681285957719972229421610786240010762333430842574469675162135111666663892588806633952834100030582958311462677444 13351835221144817731029506485780035942993102249530469725816275838688776476541095742718794918754698933062528531602640386024506108848967439340758246771181170520460131666955077007600435845297592077391262781809430214433989698809158941201642308414200198231098461131946760912886281867425554779711350494297255880263601872052961675571098775803190869255108833 128529065122776633629262135865976923639075842948053923030977767521164989243127303617608356865285409518549548476016562404755255811019175295486294774394761623938606651465691051393800412980847900588755516602950770297507236878176742871870915922036990493989081445870250703827687546171472315709951124552454745437037378049979478779631299070124480812366086 1224142074700245847557454029952770082007995423863910971859195426151047740389736272344881166428502626874133798793010973083675810919651051355742281011892484160178984309093120563190336077075745993126735891615621925982451859351686447132794903080735928676067723435710893909189377602625708991168002706987216225019752305567972498581424794180329962464923 11534891992024877031274265292584310491493664441419099560531111230860399776100346550144446300947089769102993581628411249352831558567076992294453698774249879092480805997901022695282761639297023834798621184409565713913313915582457275540673770599787854708066625517841298986749459032164650482504946358807208652004169264104549808450632114775613363128 107529404573131007834646880243148273715878927015022018582868990328017108641188833928931818168349426459087504904926343176413717711377963429085154747906990372039732868786790911818109749397426748637164912906613959467015111801964770596238584893054295917095904942859845455837791866957941798313681903275318440067324692476366382486789623421921346027 991638425860622682771626595490535193963934293480211545305024965777088419386732956275138631251733670998335817050337462740617986485406891295734579995993570151563027661867539759841266274209622204814591887828069894544964652702286177715887233277306874143889960730951219124430674153108112737268537444680223121353613357549984030521686122726612374 9046318303643838810033155608470204002876258961069774794422034942970548331753382831721088795581689670114338342630464971962353933661498121256693618113225686652671437219109821884724360813352513158414293909112127913178930721905455039541362731244723200368577476076060698066109896092396779367657841615608476974400020908393128879586242561123873 81632372095826956977237574517465254347940232337630797793166655711200034880407828383879342042458518202184058421270253562630727232043866312361516738891334905451898235796604918908342511859850428667668434048184562988373825271587590383423205002256164777209267372518842984239216746383355646993446901159477634661162106814143384062734409720356 728625266513925455040945867147291693784914171515177288519845421181586459647075554044805373888208134699666311620168153393207123357041526116678546330012659941103457174998220128985475161767984449394487080410703030174310822140287157458770937684065854266962153202992744757965012103175743161154198668196599480495381042074088829450913688107 6432445487558786996333616504743758966227116450715398750274840589537565675139647170779349402349804473633062898832255840395797524860940994684016067987786466165110249791728624136865317111390711349448126646307573430978532719899555562501691782640848370490605399603599487006426952428722935180961484153260406136834543059511806459530801354 56163799522340734160794153499005756961617061024775787409177523538763219954554433848163497012766995984531237395072898971804889284837111224852024703827571129068461606485062083272364743328354678049123464253236089853904560860989363687466157966035769814600471031502752474462111482753450932060613862225401691158788978298151012154078233 484979412488117558781806103571633213847941051328061885791052456612984755048036990293706270694541539459751235130353146786941621132449441842198143043501101603834661491983551630529123064625914756461643225263243734695984034122251177050303656131800356416646302446227243982504325004271377148336729404107537916485850915764337435734656 4141466249322925520295966175814241098046288243213379637641198872709704610399400778356261336913300314367897637179814780709022693867781399441629332621974633547330358333377457423069010625342159879111786621553763102210538904763230052264455943473477902539469117675832414123829969370739967290198202909026646927828215489009540690792 34972449494837784209575464880154308705432381778896930147865783701975979114695860482397853069199254675666464409189873925859533388461008954710482669369281381487674664198494997003466933902886143748838179226334228259177584880259736149836416314090158140205506007166240690349812046353056400863370615140797011057005621741987363984 292022104797805443415288465299440329735413087705477814234186872199637192672342909179268773771731018883999614190474055886418513013889922862752457267077930983517290118736006504463061716839740039716924295148626015599468833716688347535979191527121060910985070490307723351017290325505170823645178845226162393360863471105331128 2411011807411297445638732466001325027454196187141413117373965681395942816598992775041146347308126154030949848326886461373749477206161694619092092241933260274693997217177076339954771025921760837547606214218663460714276846262951879079588303757889080698634592541152725254285558485551722134967768336418865744360851834413856 19681246210317987568761616066193366725934736606807906818465885083045344925706186845674011704362758503411081839378535507064489882389123407644710698610609717122554940365663092327288512732399534750245272089920015690037556267971563561934298576020199877099805792325998446360452243334530398670740617245093214244788757809192 158836652434098635576244553221318648087672011660094836256221053767373087644664603428939697660693935690095219336148814905221329954715864496619792232888853303039846120738310378417867127689737403386816656610126773284268271543167391381255803413450657295040994806408010721299074741915893486609235761489065906003532716656 1267267982197463201279790958758971890469599886423155509727172281273128832514409111802217639117848156981854119731479264009713083419762224223145656606073714491302853723059502229641498227734868341232449772221301978003466865826533267347214229396203891989092045372528487335207535570772682015140742816133168586308034616 9994936284357893022641713686449020896341519652843926500287859065785112982346029474063684066023065843866736114416327679268264385437686292064908896486331320418258777340443760637016957472297912311523750498931248465906672418925016440115637005268370233400863895406058259025281736422344701941250643595963082509080384 77921828226442291555450025798698345710016120565226248373312178181924369202471478603671217175968495749431326812292242076814618117998471516392467438788716704092057067132155492794374125497091837766097430307991183230886905779618552603696310560596440036093007657740386083577680850374016416501015745218041279444888 600452901216398587244076991952720442923518652115678313945530307857445207793924177157180429180560044182257813222826603671463861624352482758510442890697749795317527536559321432294920113190257919537475660377518954456418625490205218096515144491921514824788732185541615441443769917014504079713110591773056651696 4573114781579161956325257258286503560070767826713870807357512849154692130755078437838189421173220179255966777401469900446758623677618260141713136003771193271884736818478850634879336991467719136963243297591863440215189580081067313486214447437624733751136320354574202219093551797711045080420882693639053512 34421569548944779171371489954710533264976266303141711352320694282040068353048508303957369705150739389931261144944416347555782599653724448871465913092076991672029830224469567775868885590588236556393159893619170275563432820607512657697340353167405510121051263804475191508827385326744329336962835043207584 256039016900814433028454077839374372651315403915261242028985934657002954766605499438535187645113292132712453177460104827350546914665358980266397636078495937178102289752467024575571263816078007359429743230530286702749574321636852360795508909904516924608258090303465661217380251209854291672249879728408 1881955988984752705354672087670169385293179187071096681184660314431135674914001155574914382894207214321209680391228772901162768232900127553771728918388916254141178790338984410162381476830974796218046785841844809060074191620983134167955665330273962019098185431433784046741228121696043576240401805136 13668187281350109000683028058393735632055762999709547083687688271113685119785405346503833478659513625427780684030953636169055766945343747683533168082601403950084521126937759405628469378438279785295673160851086784255883476891034461140297471195215624615572065359066290248785675134644022253149242632 98079947648039630670029412302059367642732260070848271727010953313335991422192454602944427212035831306968392172906994013897619479160950214976620440254756698139733224460014086144508354625312330357858840758845724023943865290931799425576313465112355855970944616899697857333743866977567987719284096 695322760448581697927135832935701331108675482240317777005799582524109629144342865155414559329667464675831385604432162557597700279229323987696481205777068143101817248158878923737415323453524435521719366333639042590821884325873391304292885527009647767408948158601518457555738216940761673340596 4869652864984555823757830959465017922808935528138289507137083914352973857890209588204594851415301457088941526693945214540592504582497266736051453600222689589941221522739810576896266018259752818741219026609670457634554107882044274156567191486899934403312754036635430714155583852578275621384 33688576156245449930541531902505034392027566842046443485362442512856467130242181655087030505467343551012174734337987922267382013586077115776415468950063056639076410555183038043426276526486457133607605709679451596751690749138364366985754347625019416927867443317250636466689745886781417308 230201144288083046312635035056877161071123277573780847196891940966880355240514431081251787262265146453792877308045484412392220026212761874432917621121540356318717757208978560007077190677146093654433722745246975623461612355040961480441888674520029050352984847518793295511785444246276816 1553598682869145194938864556397182442066251243347169243406043587414475570439644485878315720305326797064614619215227262680157812863798319794911795813522078072093308106776523946609098253032645162779645498272374216902777175399561790239630617641398795620989700876812651442457718782728020 10354816565364683137452506878201836650821193516352291905686622625593418129076111355165604289544588896982571402196523469420230969384537377544705155119952012513972524068266563842376435797068534908508445489484577563889251030730459733347251172038265376606048172207559444128477864106616 68152703818499022164846248428802707526930879197684402209660748744409607928047634365374828872433871113220201859952537546797693810744733586708434467467334220085039721322033300294076153080240741806016164840010356435277425463395553100901761073588349937085118083224515987595776780380 442919745683001696507019280993377575268941395541578398460710856651540728318179362597050879294750939799445918775797628903882407481085760108778071743308063401869751336209229140563674892456837845062967281615296751197862131264121999875305711234393150641407913395388285855231694560 2842049514068097596855315926842026095568516477196107858203728896967385971217283437764628005481598934921362151731081974412368823788636124552640535327535096721611216938352013549910734243184197447321712854537749519024451605759297825119081012466631856370607598388685644062866620 18003852926962293883355415510047371435834367934716709854007192018943417917867816994971720929702100274156364339033752129961811419420099055071538439978395202198264134281600900937394674552340961615781630773543501270529465559924069257416087638066744696010049144094478207208184 112586997615934843879038300022861750442010612081365122076449628286736264226749470952802392614297113556045976390346340309006263820093499813078113568101872597774571750852716730891020193741901801079300780541369743490712400976081300206941103907565247665312298272916671374516 694961714588296684167810310005342470023661692065213714838822608987878952460773817698153298030866261748683069008294363853225848512497180225757916773347311281390401674663038777645377306492237281955837190461300907541528994705199784037756575443566450687537723631178157776 4233927374355858844262300186429118122041272644343232369040901652947938914516566630027044664999293182791819458194736751099653969800291472950105430989938695319913564201748874066312376673516794849982719201462529006668616184906345761779401780653992199985309116080076092 25456279511748064372151625605009609760975205417639749779325277165464174120823089749025175234344394956435109010141794186041785752093038732519231957797641765991743466474530276468959267193941959888794144044632785947793143149901623976705756361445814373946858595629704 151033627340459839296219065230284890004556145995372832441751690039858084308747266894957301927257116462050585412462737665345579938514841282305089422400186853857619967060148786609983253489114420403270791473605656561850408957568800985375790935004931601666186221972 884172100477087364886179863050784378102217175453630873401433366742321936382539690529037017020356553971635903061432130167499474689621862703425320083324476601563480261432241987042060434851342674859879068046814494228301071900277895944565516797239384749774410112 5106703518259693549696922974841946280646283850349329682113053596414726035750060856429436368005811810778847011031411784770096374260468375083245915863496503083178952711225762087010328560836010540361318775707999430613086608894236391637778085690660271785351688 29096476606975787164600468006231119669218900609823361827214301206194395367278992959999233313277700811138726628273329521459186391173351938458224699626040298592449750336417135536980650596175054460478519832400460710623570450528264967910888027731782792162256 163527300431393676044634470851670479006965019164466279126915592706051246605869726748113787186723280670623397755535807093499585593732240751141840211005687553366045093105795921263938923174164202359505119577624446960590126955325869895156633510820820284312 906448945868419395211509451325006135320381574807060748348229670719219022782462241147268119307439950740812936398325250492982879699132171917993042920554901731802920500154890400666435025123541491310281448008651818381929170905102442693223844322093874336 4955091024192224731275500036287762585121876622008618199193176763617106597625268980258987137453310033425914382397452803902572232164411872338025251292189521910995463139906264898364717027178069837870674363884248746239600954410563538383926141167981256 26709513231515433607816870430493466079580496029527703700590136418480397490706903615062863337832797828761855497258010700887250918768982752076363867887551279288040612599238712922241183816942586593208674440998194099006232960088353757309104411087664 141950199852713114073282191002801167927138082744975553124156396475776733130865660273229839715193424269583079362323303876825910680115587294862467660815084485850536973317372873004280978147705696943613498858918666363845493915876997962400129415448 743721203379679294405239636516156139227281223761974953198776128140476244690764418001025746219751155474975094359605036296764063491503995521973279963395832774969117871221106947055354777811804926257202630973543854554417940834758112961899806016 3840922896656639174977358176724463552869374195525840282605536685086271389275943211524353636402035588555653610707527964606263951757567425074616691336782425844128630383036010118437755340684353506710951195061246401604302841055890209117016888 19550511421610794613163450509758004909237085856843736703666402308132177598603678144202187650573011146980608668373817422134829889646636430001589002697552533778292346879048003252850281124634206733790040831149812587506674113410931069359088 98066853511463240469613097500492685397776952567280026593709598588727927084579248440272556744264470595370275892830052821535132856022898671658116721044763980185142581256923818727576903756992802244941732725353620693757410213036570063272 484697763051992612284825112798018135001098810570842124704497755653801045107018649448804081975183184832110546198680915356593360586144370062304658239090252041226796550194284528140162958402220013837193265289523970513282962722017638944 2360185073096393086959551592231693089538351232233934548130960415749999774760360819285183778471869597518559840499356855646513075623521653153848008759010892964288053361063390341687182918470526579310281277334615140071944979426721208 11321070060973120057873063399235233449697439947200619271546958339232197516645236709139879174878664318442658838395253946258397199098389934646787480375856426661672833944416751974442515117079247784840180501992504664343564658937104 53485223240697857552300869235706484587385636399568717853377569465343004408535008002623532091313978340996052897872015664528607897861742108490483268857269597124936948435161140322917818724141949832994432920432247543690614317544 248841026275993591395437708185857510023691528248762677485441197371028784766552699783854348809522272743071860551462778815003213701537399087196923784623785150787320948230638803611367076452921285467805384471801832109326550656 1139953744232468604032846960093847760998462033903496811045369068926558553914203007514596804142884339482420558065086529025728381590361767147508396930463163965755902040396058815879133220266799018359420923727366179705787107 5141182762839151233907773065254127960495833768465697153902287597046645096117107636077031731598763634756972524295435422627112633647514985929535576053343577332978371077595032071104255136270544246683505676394608605281854 22823440124895266080507050430384946273281983004020204756619128401889715026590651571235284232102270812622520180496518986204995619652921051475837865410586370469895533265971358849116793026295008035843640247397933799577 99717461825011747716186201960001155881936053890158589854615997635710245860356301738146518683880547998416409978982456907129946540255107269353940592619595005376081547377989773540986638852961203096640867679035145452 428707633301342183377974371302704287755216926827263929363206113499459153601603335398787059318048552177950436818859171555286249700294291483114463860956388627911379445171204414458019237380366329143470852486098843 1813330288088410686879200172581832063521152680484655077064010407876806817836439432350059525216269682363703074543997594455080006993294509542473411522929326949649493559729321163322273969400129228124813000252706 7544700508040585323815794782213546014282152619322630706303234814602835392975749856021012127451190000347489416253522083938198800767330614798477606796001310639565856152860336758231193982896225674699155237497 30872938788497030141035365968474510605980988224320686431780088839016966062397046573483766293166865421199207470235147564661423099593559893924726548125227206016321231990105444418366874938884354880417360936 124223570932877118202681445016068850407193977169581889520771305083616983919791780475416824337423713148229841250739457850305885864948837318370982822685372028244583669047676323636182257053827167810379801 491401997831271726294817880496036347081460898257483402838886163174721587524851914892727239109692657703603691395228242199223757227486507923970510300463496142193634831473348571769047972174530440236594 1910693398871625388817084063579991109430980491316670640117117997654741533090809891229289554597662067307468057141248418652404025700269074561588965786847515907611393726057320488994026366596850375403 7300926364784074309694600385240656478627133374547021852787798751357135342967005188867912156519377615141757278760809540477770754360057353020569113362305440292842814394618481667275233735169706956 27409858769704851666077412675840127179978787482649026148776056858788187614663061609492012981170540884660970936049553432740376480077504083043927390819330908389371191859200694147242049259385113 101084283404326476410556775310211681776739024082599520217114165009572950576712824618914796896202651861582711019414866950902653706364155070108318306165081696367849884262711450424446041054958 366110058238157821572732054450222406540138644603677787262558113468955760247851413920893473941887140349082244790087557831520422511547289165370327372492533446307544128116222732026880488787 1301939905061307108493076295910016833078423677760270233035716432351298762776298035120687260146554588084784031428052651103647974193906895978949352907159348461415955807105589084173301184 4544836742869234848516378068859051870547301098486109867703979709655820880722984672140248206935721633512789637433675765862292532296910972637863648873254824977379254952834381484650828 15569946340016870581575264829408225210240465408187737104110123664655200819492762291271871843048071574267335692548168780736598902789831755785394782980102732104126651751040064522424 52334401211729425658137569911153505669842304005801658033994945038237431725470707606701242267138949864861093903696022911205613685025047138553995740310542074929799447661514082084 172545963636588290568071048767150734312745327379523937781382423183368852317182402827650269014093184414819385586967820645109535728622921801189696490638773228995291358682662256 557855729817628851249918389616426582587169843868578064305788700400799379313288583128730738338951534376441360703604075574844643798278520825953094102156259275890643715461612 1768139595830349473615895896563173072717215254805946924074295395992074901169032035552162354146249422822471490827830285767321147900775983837607845201457741158967329136584 5492403233399758722985234047272739823572714175183334244655109636242278694714310246817399944995602981567088113852413154508885478744557666256451632483163291909663375332 16715853680006411204321550401026195025571024344013370289563379177345302576766347513282345831248576081556995330615300427686502052689979805952301304842697509719621472 49828662346006122166677432728547413371695594777067887750117785259351296548108895596708950520374641287646211340766483902623211027857063370406148398281851610837748 145436548351158042140613643444495897160794069449468618295335886501225267856113758181683547434865471577299125913616424858268050389167540637469040812009280569256 415494530757531770767351391540688210022309084653439406377683128976286006991436761239687462213906152664086744202459445176612757458761163570164918112494407132 1161455454133125057842599200568746115273263231714466808677126167343901696961640274726504917314703585528897330968693434145237716048476408044396117002110256 3175611384153780777485246409540265100337103802980171227628546126078674191354460455328190383708319151613601902614983919931700059181324241370087208519476 8489368105863559785748629220914770078551426637084299309383502430038155904015017473352816104183373749591247485638323550115576097911559531108639622104 22180713827429506719052842298669505658433092692644444008947725656209917424609265902583709638438381212453303459487740386258085183500786042584622268 56617351117801686311995328853868559439311425491854697518859703600604209827991980390740423609633020867921780746387473303758507462549098292414016 141127469684794768233143436677559920383907478275091941903537286269366986216300709736049377437996590178915205438825827675964560672064478338418 343374093711127777117018784926208345009318026257921749481515435748900338372372830081526173441012441258742234683977527310528297551517454708 815107305245786831989770849954518316369242985282364500683843524785659820805230692950479185669685764992695047088712708830475287794714742 1886867559386493751783419471097697113978939207491597289783060707923644754393097004283989957258818373997607548134537335449859865011784 4257215468848261276778809325097629645780692902300452146544083690075473089106145766892003072725208934147238804664710016698797895938 9356966226481098866954128654084504099897450449156347114630449001147887408710293818955567101457146831314256613204558463786526156 20022855251354211654188430270173433763681996427721345512070154559542142400325287215359415975451188782968134452223769372089462 41691026907452331145488870889723173033288011981210084689683092801204775888283805828225478877417888120491001413202241711664 84414264393031816199283217517343026917922945707494641415754957496785332373692759695456806726396792904375628256101448198 166097331781476097062945656785562925565060268814543537991264264208698577497823062034716164547690460424563700609610316 317383756760289170871035574635936165893699017889508659267191562060874572398375871475396728705931580721906480550738 588527984397605190181986676936802311265148775493410916574640365728764614541741222573682673958873848597181641928 1058222969295968346860079018221157304947554942606015346387130808692788453400959234568522991956064043940780742 1843583048302552955772739432480387593691696707765427943276926571549970879303505352797014723215695991542644 3109211801044187953942055596537967131809199128106981247707160674438537741456248131748582855235616064898 5071582142426697899436277529455363344693451611748210603649449010355232782843867438680260293228925760 7993193051684062581377458071022039065473219877989032661826722452994856065381525826906828185368428 12159930851381845778431776740987842821276209149459419049712910673508827772533535415551171297400 17835918622771516186223947692977252089602466240247974697860932499981754155465892649539440260 25194116808696530810656977947394571885399747419692492417548259405211129953847038885410160 34228682111407242662100345550367581229050006282227704172693454344395767118354396311692 44665772016014459740422379813997121225156368515507871932946716444147328486329771528 55900101713919632283129953618672095345524845772117259846091473180622360342041028 66990062269499288281129280493866705182852936339922220558622343932347589826016 76738961338056040982412701538593752175273811020117965759051166741054060852 83870610459282201358463081523375345030141326378896496370936934176123816 87276264881067094375928003603450410557809367751746667469125043216796 86276272806442901147049153304044268141564927993122214122479175344 80818483376551668186698371857136099432838733225651104612065268 71540458929371753900545081776400237326118267425138092955096 59658765260943935233704345492511045323205638456912520700 46706276341375923136075096200416334570450433754138816 34194571427759690948280309578081355003985970857985 23307075784268029645971685333117771606877381610 14714581361637473623842426399529259513587155 8553864278939288610305973058795839407460 4546811012160950099828586006608103465 2191692676325879668485379848098870 948457828906656930119914608435 363939492824936224922436600 121892197865751514535971 34906438282775741574 8309708601927369 1578665363268 224383971 21210 1 flint-3.1.3/src/fmpz_poly_factor/profile/P5_flint000066400000000000000000000020151461254215100220400ustar00rootroot0000000000000065 198828783273803025550632280753863681 0 -8316202966928528723117528333532208416 0 100392008259975194458539996111340080624 0 -511762449216265420619809586571618679392 0 1258829468814790188483900997578812102776 0 -1771080720430629161685158978892152599456 0 1585722240968892813653220405983168716752 0 -968316307427310602872375357706532108000 0 423140580409718469187953106123559340828 0 -137048942135190916858196960829292680864 0 33785494292069713784801456649105169648 0 -6471399892949448329687739464771529952 0 978878175154164215599705915851796296 0 -118444912349891951852181962142375200 0 11582497564629879101390954172990800 0 -922739669127277027441017551584608 0 60261059130667890854325275719238 0 -3240853899326109989616514647392 0 143976257181996292530653998416 0 -5292590468585153795497272608 0 161038437520893531719546696 0 -4051269676739248306877664 0 84041236543621002233072 0 -1431186296399427673760 0 19875965471079809820 0 -223010452468129504 0 1995413247403984 0 -13981172308896 0 74737287288 0 -293134944 0 792048 0 -1312 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/P6_flint000066400000000000000000000164651461254215100220570ustar00rootroot00000000000000145 177261672401329485516917610498145304333994371552802686908369416399350057522133339110706087168495631289039585065632728817021628341301657599480912936960000000000000000 0 -485903990810307344052270497814889492275435973110511281614547471446441393964879005289507893730443801151244428482203907506474515032474678864520614510592000000000000000 0 234049781127204439493378994416237106466891175346255812998932755272471469709924877244104738861488153076537300860275980168246128589817100641707688711946240000000000000 0 -49235557812759065709900121603123650566352946850780565515328613623091647586415310943927105396743996780176285315514712432674431291543723888284611907682304000000000000 0 6309063813054346911934843629181444580879453597603245540130978326474251571132696075800163521639216529153362048840320768110349326652147308787812633937549721600000000 0 -570369357536244289545200896318517678424609764114455833303739707046068989805646681044620471062172415393368854166947008247525086695805465559262585450680811520000000 0 39509826679333956332128517326165088890140065405466534818233980989941644640637105284627380701191880434196948615849779385457503529317431052338570184027747123200000 0 -2210840743927574987346751156060160455877043710500856870828425703699553902840954667889272122662890794113782031066524745103720082081563672212533217896322564096000 0 103639772160574029091685540423523045057940990117035694003363531606312711943659177181823798176551759668527972339145076373128591507380846606299274564070755270656 0 -4177131921933200552946860746969849496338985781517775477607557788940749856349820731796918728753970560033758539234339137276170625258640673049382068952529633280 0 147462054650977060510322540650222878602258384991706781583606770366293494033452463277724851951185793620863882088409106920860227417992635453494036365859356672 0 -4620350719807857996343158844456904095062930948462586090049760222269735613646509297755766263474108089735940524448209373545646715367739030687911388884500480 0 129707918522705020933823697205723738828961079024099298107527300399275935302618491458109859483415499059421247127165205846644618443610153840363616858013696 0 -3285436244403486300156672833812020947044672346393291453134358895573996904422004642686126596145312868313289669498195040250802255006033172841232963993600 0 75504161276520761566581990647616248338002063153512083948958088422503734750604613416552778744099394173770171273973428972283693985520280680794748354560 0 -1581969972344287018439478358729237029418749542360114336183936115658188431671276585853309915862836264668634839699128752124845836502733563792405299200 0 30355015133021931711236884198423697213241690138355957556694052971183999195754729721093641004528036392992593333496386989231848102631376259131637760 0 -535744148165410578707269247802277125116237718320435691457284687766901199722688023586694205840051302196219629928467492808449835321883149048217600 0 8734088070851071918207899841925134694259051173322480408065630220049357755327476435900409745893636372348912718846504808634359470785515126521856 0 -132061630877557424949375423140502108733965726481431693280877530179804367294226853555751064025832224022728361181842221793968419869543817543680 0 1859051777569009179266121253236126763158585224368622305290769622038796515027508367191720598494621428095976399505647615248415199082873618432 0 -24449509937472868937418494594736926733036605708533223772870204125189424712818992883895726342443297870455870180124275893602338382681210880 0 301325961259187598411286034897348562615368736043040600893985659233611509167123717413329878607030481376525290613082799096488784461561856 0 -3489019962666773481435125477084455918552829819493219120128624771838494125573058660602594826599313030376845094326795056968051458048000 0 38032733755540592100240945999918298387133470801133403376650052532561544606546286239130670238798195258313424879318521765669162188800 0 -390893151300336007442962390784499078453713223420397942775961916114197990902115217462666500987628987162401821226422948222468096000 0 3791835863967198332202904916084424210682755026132632718139808011053133199851762546273299059834674225267401506878692584639692800 0 -34736556263460952729673498947428683003073675120806645701046626121587244185694762500526363120169285037581751596960742637568000 0 300585884862956515427358439323550327683985661414421993733018707921000515729699650644802382393553071858122344599688006205440 0 -2456832507087335316821964350152219521572973969408349430077048944797838208340515719964622552834356451189191242373264179200 0 18962991944204578269751427398563261603447382251066813274931546338073275379596102198309737272015903267370713339509166080 0 -138169639464441196588441953187917430304680006625343582468310826615617227961619434318217850803693250048428433888307200 0 949989992128927790454914520193668227207884554269233578111900510296167902916438371040328038930701624947940686019840 0 -6160918157594262266416465975344783653619686205415715361259284456763811611848564218569594323713868262081175056000 0 37671560865464958946035978310795669829221522192699322907051873739783003272439823178387027774190902407111709600 0 -217095142851772211602069152800677618441891378998344509547806791279386012375507987034904737009827086891092000 0 1178645736240292031542914856235083541045957060372918354300927132643147653763347782387958506045564476384225 0 -6026105129299802804644158785110166644827331412353176811685522227071709863604959721899025305618267253500 0 29001492315307740521480892957814847665135592563870936525506977224846690155655058660760209494862397570 0 -131317116873575856609740499654724113576375019114503771528891687673591029943404328581938965014270600 0 559107296821127445980362065707965292694051260003559867357049833588442693632639964757941602285315 0 -2236960070307875266079098088537543869184843368486268464183324363305750904840341178218245117100 0 8403928801357761831147230956611011561303847485575298811751612099313648536724054550874640970 0 -29620419005127043567983602666521284434917122339771781905818223985548981270758974693378500 0 97849481646312313309448526805202035844853611096807530141863557770184260072692451182225 0 -302627355161682699295928945711489911457488471322418313802596464854091066038473942000 0 875215314919086092502782410325689363401862270574467241297976312507886113712107850 0 -2363772700392768902746552419715705638836392093263565730483120119668760746776000 0 5953343357321640962008689914065878902206765033517279582952827676893093600040 0 -13960931908687585782471393420911466692052124192369553554538692384368111700 0 30433518311024634870744528752836676377808223007472407177503361169859330 0 -61561471428821681878700012839782720721586106149808685652966031109700 0 115335386392242296436210167585791134174145721390677228646025010740 0 -199721411095342320227493512964826619625933663309560796310375500 0 318954463719664053919300147529774724951804446656488195249300 0 -468612682351984725342664080471406958244247226498109871000 0 631691593637225090402149465347664443328001752956501675 0 -778906389480619770014514784743637439229036497114000 0 875515609187341512851099271609989487406615750036 0 -893581608671661295382006483638367964648334680 0 824364401490762870909565907955304285074907 0 -683755227329170560433448246709351045380 0 506668621024906943705605422680575826 0 -332864909491939804426456854248600 0 192070148718321545180565692435 0 -96206413961691904561411700 0 41206568608675801710510 0 -14794564124886020100 0 4332012749905826 0 -993836974780 0 167596572 0 -18480 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/P7_flint000066400000000000000000000176031461254215100220530ustar00rootroot00000000000000385 1 0 0 0 -1312 0 2688 0 790736 0 -3249536 0 -288217952 0 1803083008 0 70148482664 0 -608747285248 0 -11789704976032 0 139552844700544 0 1337873501671280 0 -22906525086545024 0 -86823853359472352 0 2755838317751945728 0 -604703470567171052 0 -242683463398261396992 0 867746383080188794464 0 15036606766682758781568 0 -110812140051499117848496 0 -558168849459401040401792 0 8367004033888599752868128 0 421584204508305083007744 0 -417312300270159339531276904 0 1469574753158779238618880768 0 12683888161394834713505065184 0 -104714078558802784318106099840 0 -97011889546882547379899021968 0 4030899680285432256244591861632 0 -11486136847653602463876896045664 0 -82719520473825530885762209539072 0 636476238163340700486239785040770 0 -67060437711827196745340402066432 0 -16168850177966444574234467450162144 0 60900250996792219903938468841336192 0 148334210680652950507041431995879728 0 -1865900109848787317127829088429658752 0 3776212388797927870036271990251218016 0 22518301841215050970349036178624108288 0 -151671561717527409427090398849337660040 0 157435823406284702022465344966234021632 0 1946214239337551882811355767059597602208 0 -9507461799423672827968239107804868975488 0 5064502499114652039942554152208761313168 0 117134924475677445266345359419918610289792 0 -486078660963527728354127934905653508163616 0 215981805179585477620101849540261476213248 0 5194203854159251275222068675588531884231876 0 -20734047820658568988275936059402711947017728 0 14536297216955830503478551630613916186616224 0 169175342474600857336267854630791970347612544 0 -728160923177532432734368307301546951132993232 0 857801883682099943393401445602061110029945216 0 3770338890638491690197073931984697408400069344 0 -20155870984868453921428960169029871029873026816 0 35678502314016261062669957308815203467391201416 0 42458761664544109590176744922860948325163352320 0 -409127196099540344827822267083216197901246090464 0 1017198743014627662452030126160377407213822309504 0 -438889754173509496485526778702864783925443828720 0 -5293770635485376373780245549877323689121315679104 0 19344122099435439221392220275291968082126607239776 0 -28316252723758767727063920591417929415960276217856 0 -23467596395913177283730452396010703208022675418897 0 224700723702451547250548684477625327859603021385728 0 -549559164398807351367842376124681242268062406583104 0 511794459281679041353181650437627271904824610740480 0 1092842568952222172588232179125871201495051916978720 0 -5420091343310782650929787940331686464407212939962112 0 10652861868552436050573714486446736780661652412264000 0 -7667744750013344084091387140428249411035227076054528 0 -20071709266144216052611059184842852037710936232372848 0 82183889480411906843967775056057008544393434972545536 0 -147754520313109154945759291396904736524658416428016192 0 112466442184160815734529437233098820229719120155902720 0 177325390288566649223808214767791044906689323104496736 0 -781367197373704646418680577881114479343182125137829120 0 1422259175797974242066654201242226182942196832000170816 0 -1333883906458422037241894284047610262502179821260819456 0 -470389574936206713500650777646496692766014207617166552 0 4316188707226600489898777614122491961476394293336896512 0 -8718522347659773662064402957125224933847299821177859136 0 9992970740446778405033661332284669241044839555951339776 0 -3787569355206528662450030300328428302003611331066025184 0 -11373631942311964217308097890062569225974793032780986112 0 30473177531114039424588796254446398535256431144838100800 0 -41718766231712320083217492971861522080961536366939042304 0 31989832030232079637532357895765677935860699666073352304 0 3557269201276898960369865589374153987409397615912091136 0 -53847947327977972193569550765423340566005288195414856512 0 93373776541254015993133971570931658997678053447377697536 0 -95043090396413563922985052519068277407737919259159868832 0 48061759535361844143276106219442460592578953529323404032 0 31267125899423496378270919154554601473493016050468627520 0 -105193517788833527845426599827204765082545756902658529280 0 135222739824560156445032577613150259051389600771681447708 0 -105193517788833527845426599827204765082545756902658529280 0 31267125899423496378270919154554601473493016050468627520 0 48061759535361844143276106219442460592578953529323404032 0 -95043090396413563922985052519068277407737919259159868832 0 93373776541254015993133971570931658997678053447377697536 0 -53847947327977972193569550765423340566005288195414856512 0 3557269201276898960369865589374153987409397615912091136 0 31989832030232079637532357895765677935860699666073352304 0 -41718766231712320083217492971861522080961536366939042304 0 30473177531114039424588796254446398535256431144838100800 0 -11373631942311964217308097890062569225974793032780986112 0 -3787569355206528662450030300328428302003611331066025184 0 9992970740446778405033661332284669241044839555951339776 0 -8718522347659773662064402957125224933847299821177859136 0 4316188707226600489898777614122491961476394293336896512 0 -470389574936206713500650777646496692766014207617166552 0 -1333883906458422037241894284047610262502179821260819456 0 1422259175797974242066654201242226182942196832000170816 0 -781367197373704646418680577881114479343182125137829120 0 177325390288566649223808214767791044906689323104496736 0 112466442184160815734529437233098820229719120155902720 0 -147754520313109154945759291396904736524658416428016192 0 82183889480411906843967775056057008544393434972545536 0 -20071709266144216052611059184842852037710936232372848 0 -7667744750013344084091387140428249411035227076054528 0 10652861868552436050573714486446736780661652412264000 0 -5420091343310782650929787940331686464407212939962112 0 1092842568952222172588232179125871201495051916978720 0 511794459281679041353181650437627271904824610740480 0 -549559164398807351367842376124681242268062406583104 0 224700723702451547250548684477625327859603021385728 0 -23467596395913177283730452396010703208022675418897 0 -28316252723758767727063920591417929415960276217856 0 19344122099435439221392220275291968082126607239776 0 -5293770635485376373780245549877323689121315679104 0 -438889754173509496485526778702864783925443828720 0 1017198743014627662452030126160377407213822309504 0 -409127196099540344827822267083216197901246090464 0 42458761664544109590176744922860948325163352320 0 35678502314016261062669957308815203467391201416 0 -20155870984868453921428960169029871029873026816 0 3770338890638491690197073931984697408400069344 0 857801883682099943393401445602061110029945216 0 -728160923177532432734368307301546951132993232 0 169175342474600857336267854630791970347612544 0 14536297216955830503478551630613916186616224 0 -20734047820658568988275936059402711947017728 0 5194203854159251275222068675588531884231876 0 215981805179585477620101849540261476213248 0 -486078660963527728354127934905653508163616 0 117134924475677445266345359419918610289792 0 5064502499114652039942554152208761313168 0 -9507461799423672827968239107804868975488 0 1946214239337551882811355767059597602208 0 157435823406284702022465344966234021632 0 -151671561717527409427090398849337660040 0 22518301841215050970349036178624108288 0 3776212388797927870036271990251218016 0 -1865900109848787317127829088429658752 0 148334210680652950507041431995879728 0 60900250996792219903938468841336192 0 -16168850177966444574234467450162144 0 -67060437711827196745340402066432 0 636476238163340700486239785040770 0 -82719520473825530885762209539072 0 -11486136847653602463876896045664 0 4030899680285432256244591861632 0 -97011889546882547379899021968 0 -104714078558802784318106099840 0 12683888161394834713505065184 0 1469574753158779238618880768 0 -417312300270159339531276904 0 421584204508305083007744 0 8367004033888599752868128 0 -558168849459401040401792 0 -110812140051499117848496 0 15036606766682758781568 0 867746383080188794464 0 -242683463398261396992 0 -604703470567171052 0 2755838317751945728 0 -86823853359472352 0 -22906525086545024 0 1337873501671280 0 139552844700544 0 -11789704976032 0 -608747285248 0 70148482664 0 1803083008 0 -288217952 0 -3249536 0 790736 0 2688 0 -1312 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/P8_flint000066400000000000000000000433361461254215100220560ustar00rootroot00000000000000973 1 0 0 0 0 0 0 0 0 -9845600508 0 0 0 0 0 0 0 0 4627300907776627026 0 0 0 0 0 0 0 0 4860233918228621614937627028 0 0 0 0 0 0 0 0 1379249217414955125529010236912889655 0 0 0 0 0 0 0 0 239079829691011149184766261605652470016424456 0 0 0 0 0 0 0 0 37696583558181387049538878733723098541745350338399500 0 0 0 0 0 0 0 0 5431630292765913660794320418597848752836401721376802757447304 0 0 0 0 0 0 0 0 551465034187531876191891719075337554392047748404412852760861524952571 0 0 0 0 0 0 0 0 35367980224750367856261927490056161163274277592663629001025202857179451185700 0 0 0 0 0 0 0 0 1413125936664597331327971455379171375706322642305663495299668693615313572327320595994 0 0 0 0 0 0 0 0 33678765999438058721558335331456491097123851652426420604462191042464584719159363460687206100 0 0 0 0 0 0 0 0 378769273361169128522390308767397701434692505459392663718283127176999579834847831743235258025623773 0 0 0 0 0 0 0 0 -85870273631639207697761195204507370985983310868227344822768501901082304185951658882372949718687436930912 0 0 0 0 0 0 0 0 -123544502848135239426533210207602386685516107926035644725009017761374937852711951009746190133606238020097704272 0 0 0 0 0 0 0 0 -26773851009465869240453746205574331675785203900586132688300278293797507050481664598259289422786230044040101731375200 0 0 0 0 0 0 0 0 -1777887156741684581177616396674298873400212126238817791466616869649509460332220157941197998808371142325871460271220500738 0 0 0 0 0 0 0 0 -11755216468652488960650164285264575640202647313353832185501185686197181643641016235278806003586766252381075314347493357372584 0 0 0 0 0 0 0 0 142403643496066660959426631703507504247816905501688820569749340419574096927457669184827639175184152661241842545124756811138259372 0 0 0 0 0 0 0 0 323222874675315777927487970387112233330821509983804239564129849725394483181528475245399100067519832366658777556930795058539309923465528 0 0 0 0 0 0 0 0 28593978872781224689856315403205336379567460667046801475194381413009660196285675283167425127809792929654123585151319551982595760435298414226 0 0 0 0 0 0 0 0 -1000647474276253916012455882464293634555276194407130207236336489825020638240132955337448869623692582784908920663588137818907198727960894772917104 0 0 0 0 0 0 0 0 143677793775231948041537063019614221055821445719259702379709993010761317876639109974690122321871725940680309284546715633642737862689798233757288932504 0 0 0 0 0 0 0 0 14883392085236938358303646242996081992699985944112141875096716549007594881571755491126250954306131068839692511282242911546153177550554116465805482693112464 0 0 0 0 0 0 0 0 -40430046400042651907407461584877801316860443846178163522075683176511567104370647526513839190033467702355509834627139899311018419025882465429321712284904978046 0 0 0 0 0 0 0 0 -7031199256833043261032462543992801363979010401472868185658667607119968563959642824520243334925764201777129207057652259484425325120479618311343972970856710386272520 0 0 0 0 0 0 0 0 37480968366231161066026792496203515440467793987285066615152683101111436320258004550951662356298270806247823189749019017088051763677287045038657624114401017871984677516 0 0 0 0 0 0 0 0 585519829404615086200050375375565727851462703136880324580781935694677966563698263024391076991241505212761128380097937878466201059668942783101999849120759125662019730222104 0 0 0 0 0 0 0 0 -2314907584031908143236453874182739007823662060775119966697925065900942302407136988285902542897782695796024882724271231747983013075883136483571913768387955762509957080433978994 0 0 0 0 0 0 0 0 -17411426583406021406633551256857077603312868986939457732147919252983216032828797861038317497452389381624829378694211606242709481873562781667270403072460016017682259943412039897824 0 0 0 0 0 0 0 0 21311378363691911942373039552862622785589744360155355596277730252256999138770807298122853707106300010986047291559952163962550821618607004014426172451398723129964519425769133004936176 0 0 0 0 0 0 0 0 120378703760184652718770307618779578283938416136956249878989068195910432632924269374689391637270932909286675139966273514288472023684601651684933586107177063489617114225989609138538175008 0 0 0 0 0 0 0 0 -53909391202091670488933299970866502720192641979272528566508381859175352367087973267468640435617720799486867303623533368279666351830345911389358979919424155050677276826394066985439881059365 0 0 0 0 0 0 0 0 -377036068975524221863105632594575360824640235719338539875852519366203484460100413311690467600774044508378690408563221544779606964650048530189592626091538282007234945762222630463551176916715700 0 0 0 0 0 0 0 0 57371586320749462859450841131664199456979754030726232060578813711900275931611198972000965155330173348469289269702323502786613197955724582805158275616407590939238292556068493193172147205465741366 0 0 0 0 0 0 0 0 -109579154799651432648934471166201807935838025699393058816421592469112663955247695446657622906011089637899170502696275645834765818657197644125453033614599912370433449674460616402863407584011445061252 0 0 0 0 0 0 0 0 85167739549328510043604999942042495332593892433858778881281379664197636880298323463319956931036364317175390153198748913881924499050050685471594626090554881347932400585541836181105960160367073556949133 0 0 0 0 0 0 0 0 14245083013712598175681009914081949020369113123042585031659865822054780807294697048720230632970169812874330486728068403882300480601756559396215326516609029221391009714833455288806940676374841710532118520 0 0 0 0 0 0 0 0 -437590797720011730719441006017131364608802826827497644845467817881652399793391057960436986551106153777313777535340694088021004373688955681851381666685977720076475638069114495482699099646140123519191985100 0 0 0 0 0 0 0 0 -6135407665473474113776270272340560200116165955857163744098566902369987543367322455219173580408813379113865655230145140271173310125108195264024412077293075779421586085735480428534188840926603873559427907976 0 0 0 0 0 0 0 0 299083495694882648665888540269961374338841860053089608943374175831320148458627954656088143121495157319581973942970971096833486636709451069879388639279753125357914803672988484078179399358206301115411442121313 0 0 0 0 0 0 0 0 -3363910826696636260047066818428579219883013375871792625034032529331138666236336537825903372534277806530669800181970180911809508515531053580683040417039904938077430749857186381591968910842852536837558332265396 0 0 0 0 0 0 0 0 14713468476159468150369305930867057197129058274051423704687964151636665301635723876901056360778743665632645173777554031850256475663341703775673207482859544961267912044604310846881770779901964703932727943456798 0 0 0 0 0 0 0 0 2036293172875311163272955270946431281961925156510064137603197386180719531533898529420707233802617505219769653488133991086638579217140221683129762811202580870219357044123794078589127872806986908996523530235484 0 0 0 0 0 0 0 0 -375703365754801921538790141836880176699994158354476470837056821030671097701917464223025760229115609540610062348509545771276515762259135471588102080934234608648654474825786319283867018290887700866868227061874649 0 0 0 0 0 0 0 0 2377370671341195152077199648494462277733826867050365841660894034173351978293335410876511809107230086437935493477417473136806300908745415874358957031941429663691721740018674592797210258139274098767200640573386048 0 0 0 0 0 0 0 0 -7945610458194193112059927969135285046880477052422705087583657102180184968824845252737860880696225556203233805313629367616898778510515723752328384281374060255402966649657157112963623576420206919916769168472031904 0 0 0 0 0 0 0 0 14102433546776693062624796179846435719773905001073198674788932376760359652515532885183243804528882317078396358603209724696939655382902436238664506426499138313059746542700180191479753259951722732163049811280143168 0 0 0 0 0 0 0 0 2623787366826220795136725012263887404562112519178189744572271539320625662432833064213046690104920943160756740055252376070946182597500912418772047361200326569412562266013170076264671484320169588150505194488677012 0 0 0 0 0 0 0 0 -82793498555963211288495170508101919603724934195874098989169806645589143109211592086911238268121278897428074613623401708541799300459142589674045699718528207580990475126748550467318227187999957987020705832186540784 0 0 0 0 0 0 0 0 196861722687695960081867091776062815964918251729408521677343256732250998514280149373442548310192978627806827458173915650259427308176709765867037865232825734620523826038158764222693710121298125629893687919629816840 0 0 0 0 0 0 0 0 -209929406674272324931041578583652498195426826023317367214814354497747221360836525308661455214987671075246954530612394998454935185192466187421003630577470521866066554989560830568459573347637849372916759290930170288 0 0 0 0 0 0 0 0 24191237641493343242198543437891397556873718175442058296774300285680626871965784248557078881532906533721201665020313723613423609152166893612904511187218618600510498213510121966704517230993080450261702532371816396 0 0 0 0 0 0 0 0 242685749385018077726682403547900055354725494213741960901995863723678306988192336705720668586789443505955772273149550588504849508962671350395428276721398133446808352927105430907119287383656371896807576142797976032 0 0 0 0 0 0 0 0 -368451350709136366513770523119103138820298009124100745547379777471637589267876528522685235462474172094076944173943393998212708675422227605525130357531399170144472303555661339430254000308717120932267953215228849072 0 0 0 0 0 0 0 0 242685749385018077726682403547900055354725494213741960901995863723678306988192336705720668586789443505955772273149550588504849508962671350395428276721398133446808352927105430907119287383656371896807576142797976032 0 0 0 0 0 0 0 0 24191237641493343242198543437891397556873718175442058296774300285680626871965784248557078881532906533721201665020313723613423609152166893612904511187218618600510498213510121966704517230993080450261702532371816396 0 0 0 0 0 0 0 0 -209929406674272324931041578583652498195426826023317367214814354497747221360836525308661455214987671075246954530612394998454935185192466187421003630577470521866066554989560830568459573347637849372916759290930170288 0 0 0 0 0 0 0 0 196861722687695960081867091776062815964918251729408521677343256732250998514280149373442548310192978627806827458173915650259427308176709765867037865232825734620523826038158764222693710121298125629893687919629816840 0 0 0 0 0 0 0 0 -82793498555963211288495170508101919603724934195874098989169806645589143109211592086911238268121278897428074613623401708541799300459142589674045699718528207580990475126748550467318227187999957987020705832186540784 0 0 0 0 0 0 0 0 2623787366826220795136725012263887404562112519178189744572271539320625662432833064213046690104920943160756740055252376070946182597500912418772047361200326569412562266013170076264671484320169588150505194488677012 0 0 0 0 0 0 0 0 14102433546776693062624796179846435719773905001073198674788932376760359652515532885183243804528882317078396358603209724696939655382902436238664506426499138313059746542700180191479753259951722732163049811280143168 0 0 0 0 0 0 0 0 -7945610458194193112059927969135285046880477052422705087583657102180184968824845252737860880696225556203233805313629367616898778510515723752328384281374060255402966649657157112963623576420206919916769168472031904 0 0 0 0 0 0 0 0 2377370671341195152077199648494462277733826867050365841660894034173351978293335410876511809107230086437935493477417473136806300908745415874358957031941429663691721740018674592797210258139274098767200640573386048 0 0 0 0 0 0 0 0 -375703365754801921538790141836880176699994158354476470837056821030671097701917464223025760229115609540610062348509545771276515762259135471588102080934234608648654474825786319283867018290887700866868227061874649 0 0 0 0 0 0 0 0 2036293172875311163272955270946431281961925156510064137603197386180719531533898529420707233802617505219769653488133991086638579217140221683129762811202580870219357044123794078589127872806986908996523530235484 0 0 0 0 0 0 0 0 14713468476159468150369305930867057197129058274051423704687964151636665301635723876901056360778743665632645173777554031850256475663341703775673207482859544961267912044604310846881770779901964703932727943456798 0 0 0 0 0 0 0 0 -3363910826696636260047066818428579219883013375871792625034032529331138666236336537825903372534277806530669800181970180911809508515531053580683040417039904938077430749857186381591968910842852536837558332265396 0 0 0 0 0 0 0 0 299083495694882648665888540269961374338841860053089608943374175831320148458627954656088143121495157319581973942970971096833486636709451069879388639279753125357914803672988484078179399358206301115411442121313 0 0 0 0 0 0 0 0 -6135407665473474113776270272340560200116165955857163744098566902369987543367322455219173580408813379113865655230145140271173310125108195264024412077293075779421586085735480428534188840926603873559427907976 0 0 0 0 0 0 0 0 -437590797720011730719441006017131364608802826827497644845467817881652399793391057960436986551106153777313777535340694088021004373688955681851381666685977720076475638069114495482699099646140123519191985100 0 0 0 0 0 0 0 0 14245083013712598175681009914081949020369113123042585031659865822054780807294697048720230632970169812874330486728068403882300480601756559396215326516609029221391009714833455288806940676374841710532118520 0 0 0 0 0 0 0 0 85167739549328510043604999942042495332593892433858778881281379664197636880298323463319956931036364317175390153198748913881924499050050685471594626090554881347932400585541836181105960160367073556949133 0 0 0 0 0 0 0 0 -109579154799651432648934471166201807935838025699393058816421592469112663955247695446657622906011089637899170502696275645834765818657197644125453033614599912370433449674460616402863407584011445061252 0 0 0 0 0 0 0 0 57371586320749462859450841131664199456979754030726232060578813711900275931611198972000965155330173348469289269702323502786613197955724582805158275616407590939238292556068493193172147205465741366 0 0 0 0 0 0 0 0 -377036068975524221863105632594575360824640235719338539875852519366203484460100413311690467600774044508378690408563221544779606964650048530189592626091538282007234945762222630463551176916715700 0 0 0 0 0 0 0 0 -53909391202091670488933299970866502720192641979272528566508381859175352367087973267468640435617720799486867303623533368279666351830345911389358979919424155050677276826394066985439881059365 0 0 0 0 0 0 0 0 120378703760184652718770307618779578283938416136956249878989068195910432632924269374689391637270932909286675139966273514288472023684601651684933586107177063489617114225989609138538175008 0 0 0 0 0 0 0 0 21311378363691911942373039552862622785589744360155355596277730252256999138770807298122853707106300010986047291559952163962550821618607004014426172451398723129964519425769133004936176 0 0 0 0 0 0 0 0 -17411426583406021406633551256857077603312868986939457732147919252983216032828797861038317497452389381624829378694211606242709481873562781667270403072460016017682259943412039897824 0 0 0 0 0 0 0 0 -2314907584031908143236453874182739007823662060775119966697925065900942302407136988285902542897782695796024882724271231747983013075883136483571913768387955762509957080433978994 0 0 0 0 0 0 0 0 585519829404615086200050375375565727851462703136880324580781935694677966563698263024391076991241505212761128380097937878466201059668942783101999849120759125662019730222104 0 0 0 0 0 0 0 0 37480968366231161066026792496203515440467793987285066615152683101111436320258004550951662356298270806247823189749019017088051763677287045038657624114401017871984677516 0 0 0 0 0 0 0 0 -7031199256833043261032462543992801363979010401472868185658667607119968563959642824520243334925764201777129207057652259484425325120479618311343972970856710386272520 0 0 0 0 0 0 0 0 -40430046400042651907407461584877801316860443846178163522075683176511567104370647526513839190033467702355509834627139899311018419025882465429321712284904978046 0 0 0 0 0 0 0 0 14883392085236938358303646242996081992699985944112141875096716549007594881571755491126250954306131068839692511282242911546153177550554116465805482693112464 0 0 0 0 0 0 0 0 143677793775231948041537063019614221055821445719259702379709993010761317876639109974690122321871725940680309284546715633642737862689798233757288932504 0 0 0 0 0 0 0 0 -1000647474276253916012455882464293634555276194407130207236336489825020638240132955337448869623692582784908920663588137818907198727960894772917104 0 0 0 0 0 0 0 0 28593978872781224689856315403205336379567460667046801475194381413009660196285675283167425127809792929654123585151319551982595760435298414226 0 0 0 0 0 0 0 0 323222874675315777927487970387112233330821509983804239564129849725394483181528475245399100067519832366658777556930795058539309923465528 0 0 0 0 0 0 0 0 142403643496066660959426631703507504247816905501688820569749340419574096927457669184827639175184152661241842545124756811138259372 0 0 0 0 0 0 0 0 -11755216468652488960650164285264575640202647313353832185501185686197181643641016235278806003586766252381075314347493357372584 0 0 0 0 0 0 0 0 -1777887156741684581177616396674298873400212126238817791466616869649509460332220157941197998808371142325871460271220500738 0 0 0 0 0 0 0 0 -26773851009465869240453746205574331675785203900586132688300278293797507050481664598259289422786230044040101731375200 0 0 0 0 0 0 0 0 -123544502848135239426533210207602386685516107926035644725009017761374937852711951009746190133606238020097704272 0 0 0 0 0 0 0 0 -85870273631639207697761195204507370985983310868227344822768501901082304185951658882372949718687436930912 0 0 0 0 0 0 0 0 378769273361169128522390308767397701434692505459392663718283127176999579834847831743235258025623773 0 0 0 0 0 0 0 0 33678765999438058721558335331456491097123851652426420604462191042464584719159363460687206100 0 0 0 0 0 0 0 0 1413125936664597331327971455379171375706322642305663495299668693615313572327320595994 0 0 0 0 0 0 0 0 35367980224750367856261927490056161163274277592663629001025202857179451185700 0 0 0 0 0 0 0 0 551465034187531876191891719075337554392047748404412852760861524952571 0 0 0 0 0 0 0 0 5431630292765913660794320418597848752836401721376802757447304 0 0 0 0 0 0 0 0 37696583558181387049538878733723098541745350338399500 0 0 0 0 0 0 0 0 239079829691011149184766261605652470016424456 0 0 0 0 0 0 0 0 1379249217414955125529010236912889655 0 0 0 0 0 0 0 0 4860233918228621614937627028 0 0 0 0 0 0 0 0 4627300907776627026 0 0 0 0 0 0 0 0 -9845600508 0 0 0 0 0 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/T1_flint000066400000000000000000004632321461254215100220540ustar00rootroot00000000000000901 8453228828215677509967005736818714191565624563853092826258438373968134745604823198688407816106004845054702916839823772768126539613261608560027494961633409480130502675619135755863871948684797657202510364499298580886575474564933151727965957222788824898778135247859344228353 126794808371350119456500889364059988137246915874962868808932805325117575061853509327629970699469680295056656615422742717336831125386282715967116130635148041391511524627287040386384652754865913512826612842214753296409688733691255851408336486098703550353368023904288616742882 919031277833015495311724200708942610252309383377936584212970109707886632318512253188014004717343647970083979498786325890185398658434687109494714827048118125459906264586482452088104395390062891319438419330088087401344503341870759871328897853340715494625899113194716705456563 4287151764831339275669693317592480848267840581314071920375442728874622773353818358234916879225825712599475616721570739078883171940634514580415698412488896577839560583854606562991709755741467748290715095897574416790572999894434600302347610481980708678638383168468643708137508 14462238651374897520893821729226175371451209879601387630404906260101330136458858589616605955285121469069411960124146448698528884651977743749789972972104730925040741556196445151441515240330965775759851364995652761374381077030719648168572220563436035536061251551889627359832845 37581376397125640588054628654079660404940516723983824436900782505009571222473991140939180428979784999718862188022411908980252231549095527524009010027373579503873950570581465244311160010307579478716500770646239444520945158349464180606509218508702188382336360972623301866148694 78247429148450344762259406036650928527247255336653021062372616457653594355643577159575913445134026468714211801994560283207354703117750308038639310884992935721047260027025261341771356522020673111624998543123317635236268565244290474353570234805535590885916240227407493298720623 134050136099575186691840328911041202681816893233902942979159301995576806576957699556002009154097829672271391525983406295365832766239192578091269217039170636806818221219022067312203996541527581361155218592108852420759677487576947875241924176391356699194340322858559010028580776 192558613446580907318311848169872267926629177708393199127730176083270223011476304501332158003093214224352526774978009417435157217351163492864314092788199805573740172466203297858067912147507867865971458952436316796898593369175746581945638319092008546717699764251527165198847741 235164648618337714919649371324364418636082314468244204760422514236084040033964690363544292738339842571427648654013213921480371099137518994823140693983584814006228559932404603553415335312858515882637299771422125334615121509021373715502597644490661772807766071972883692164526258 246710429331750347004264107517482623737362461970107912958949290448615819699857678008939629850297987495695168451992737636848789714616388112329160921034043469920209991479359927638987516463004780747826423156114766826545625413112613239611849644681505071375422122314785270964122455 224069872697373365699639366943759067879292906921222524121271152481400127594219271944234373956184986613275366628429060675191990065358684554785796095061365268038949503560699610757799548375642367925496624386368810990529353380016038623662217805485574088964015748834648994030122012 177202989787564073322266058162596134733708986835017680151534129887364880558223827629257238600524566249986718801798167630406270858651851624622722118015681525645726041340760834805767110896811485452879056086453382811138817695227330528150057023654931029377393085774461536716441641 122536296844469548511171303757524669914301201146531821068890227178019641762106314564395304366721216468339061222140050360066054639538931249201189679952802187083745137968282380678622960197662105653703057407531949581532417636651358275795922272456756213358143129910094964614077462 74300297862500992165817995264919070426694328217119043311899229109490968514460769042435237099103052861030706227459232088363750171392007518041588238077377634698176727647222609554330514564394390721773568572397996536421994369254660915997462592583020683751484489749679056600299859 39568841876170594457220860540919137520607762159076354935590688999400295085090659634103260397351694862245112083117821983402607660425970800687802330232921844690774154255603873912502321607256960970005746675070980345720227052188287496161284882771266061518407683990173177361602608 18504651265837171498105706127339040098596539884802869194351249912611398718755732130882604035751823594541911646183382066464033924037291704497930756211391378767423648156453890885312360834921950966578809834009943060840004227319312231324201215790516826292666802124216879857449329 7433970549428226750452846535350789384127847970475772055751561945346765186406019161748782661622558058458855548119145897239042943314451781530481215577046579071175153596927928335478247626757740647920464945656389514742445789190082244347558723811892562444657271497058028700833968 1539226656163659928813269422761047738109863513516811123451991951128533817231228145623180753600257715152249859790493731420051045082674896436669025600274914583125286238593918739710673578282365492703537993179025096735527301888779685683269548576876956968952138913291726675212221 -4411806755138109877669925068481214987461294119406694715006136229120311104409632057200128737640679120743323182805953741471062808485764188124209339888834658476722137697477491476780300409724552381380040759319212647948636771347982486668264186213899633008901246146288646199162904 -16455484545670636849433249780438285105057984548571495400070794180612332570782604530942755208081609002642228249656716265829614340267126549060833815645923580581046343790616503320641604805937489567932034515534092571946139271403495766353577677514043883447885696379473497175043415 -40497872424715775173697479544397093351559992313838866659122007323797932574538527675744758438960633909171605874220650309811472519341588389915730754849110862481387327892370520371201325943793204190214478601222309877819988954198854557765635940347387782031140243340744855892208616 -78602574036682914359854705263888875567544796604227729918026974166193388871646869661502757698315540937864586334029632829233983568220373404427694572296945811800306240631909270896322110892150092807339297867866669282565980444312357548109953340142074033658387643029955045969477275 -124733382023472444478824278617714068206584281084966461566989992227267379908616979437669292593166822302545671044290743001012821252256562701748560448946898138493583570996409935011127490698441611716461688281293317369157959234520296880903711556786418804686650210620435142899664960 -164872256045922152265787971801757613721798112343553613346206345968299702394562338890120049836403929917769385850547411047024165663021441457181698622692051195508372226001215255188316586497960047805531622881472573754335202832069918038684164842605823615393791243190686777334867667 -183778180758922611891070965072122356575025210759659859610180238720479513755212996088389408384069024298038875769745098955156980956246801558709124004438617274560948510290172835388195862170235632598582579008229500601067062492235648119390539024023307247086906703040828282440265232 -174180167155065505548441801289871406392770773353620527579135412404639983359814584262092362878306913435280879192908521144200841456673242631907641223422219949965800625290846076510649374994951661952009889427563347963653397427570547977710663748801553421845590779443986779506938407 -141046409758953584746806474889701454496422909116805707667089767465848287709805392101772886759941602442227149204347055603946289164199604873566508968571416535650575215479757738382250379866018945831228221615433573387669331320341503573754577140436298659193363174258276338267648456 -97733272608970028045642465027021339762948908133568692505608784577128551199568523969184788877315318985186186569286850746794493103545346665046627545154284998316072978414084970711764583181446695110056788230741231599953702751479092843058810697099285268605127648019708363058867051 -57809767718121382192437033157426673751024058294928047847826748165849076753026609204998524791108482470978095769921846544670237889421980410848268049320171873831333292208572512760514615884705203810015720238568531005405439930183172533150740493405167892211902711085525529616786088 -28942630074831475797266982703804634977562229771113518861869426835437199226576496363094159782245537105959250447248318011945290131259410559407114402574876928069022638291894220112279592251633632530315705341073319881885460305172944473301042526935413870463685941290129655566789297 -11875003377801251379948556934244075449819088310405057375567297843437319607008965823092492273638081558763521750761460826088650529138226660409842341107502521405047347996864914337076585614701211926564491122697198670780801080120625738303320020714414164152884193033887438592907414 -2776458626969756188152884358781873554480861623787245317369482147732602838061161104059275457536805447756346465021194620279149365625797775740960739418581492324237071527023383123109496526046526857782137500111220518184533233855278023993944549034161724949133663243897655298567215 4315136753382540874167711513659982276948202531747254284824512987706544935537460477541691336790497898800325295329837348922830069149327735541169786925400200868338941909955791703661543523431799882670666333597726967711689406184384989429068393592020356719524412690250058535833942 16091997075712317810944361593150500231482788439670387259151265313090050644276301755514173524378506997659486346482700796465020410631623992163178085497195069784121334293759875629309380464308012661190693117884974190029986951236961845947028853330237596649716746427142861570360204 38023946970474294517346679211997846419701139360522524101677169791288464501204561988695899904797201308380361676903071743405723393732591919949773017941311537074834082699017501372757149097873273439078849511874092863829974895836275515795495473177068592113296757202752583732978166 70624716858280797917053166041327237714250302483924134557044431083407972437438644510724633245545744629926432565056463525784382805542701174336029843954003690961617488032131677747092784931601373041007233303078743082271247739803997057339554965116785648949333952109659985143978831 106311800347199627432033477022445720732559334126176534874307070943062423889926255231580921543191844077124207736667334049410190139678839386262556777010129117168108087017988463246622818805465910369575323345720627847005623202821410967225538673044309495106273271213328601194882850 131379430370782487964469460720586979501531492175636272521915108213069422377272489618422518367451336345824145659674179320900818730978866494753568023442824370955171008436615324722294389344308741338597218342771646329755357268117222875872449443137576725909404188385643111107978578 133950243902763387661855509139470103931913876418500022423296557238329384488696684668467167634882599755763360475289863573427093549498413425936946229596361517564796031282458318546649409788485273329184429441090632143542701006581449411158733787050653873632520019551370789878457658 112226015535862669548195838325192491138620927877486575908485163137221322352335354948337488597782352680054950382732062622742227610339360671924349238015396111420092640255777046623210824627873140744853095661638949107525218780360097628187726573906266501717728382849843499918534065 75835918299695023090327265665787530736391238945027998144872681730412695008471047537182843098119414661336447678082430917606784818792453060613711150100463436676672023105390715924351378338782189499481600314766236689458997856527581620464310421209153086061841392335704468841312454 39189352959383976008347744239162339427894174295409546369109641923853183544119964618166386270745412911860257987413464627360398633347902649797391680117213702547855032650697944948439907660180358799142199124548888376837279390630255987978022302124139041285094319720397215306308008 12829977752671334158922801057195928619602352887341236772366923169372992187811696654241786253193419888878894054148799595103844992366172172810928881058450480283318048931164432419269689451241769912712416138092111752492645603329354516529949506825715568819650695692327877946457238 -598246423757559731132749774062029151438449218171864464536529123473115171337139198268090594430556682537704073943440216822619381189884366876302386606670814347715227956247611905199502728711198915720507335512564042034738161492125505675204204974195694881353870842127978978854633 -4454026933402084628841194435873873165516403970449827318337081935303671979236972445128323921728431451360256764280662924207291527397926916184107953358553889115760837825980593064284645432907052936203135940245292730262115810341157582483070175358072117053891252901469567384365470 -3757474105176733837406784974644194896015021763667125931737773986361035605349529999255329164591404129853040920505256848611004239567285137816398585406856160378982872091228183842053561316472557919315101065300234721525800783869451212168747866988495457227817267667097802799217448 -2289412065762864007273841576951313796708944182918411768477565814719383241130410584082208979698116915353533026684710006836725953019263503786188970508079152400798973897757487945825109892208609898503459740572207449415905803563597408800005008610512842552287269727959460888807002 -2495339112486607896577740047119466895179824846547492194222672764582900894124626177496639929754925970889420938346104074937884218564491718734487583033803222756560004543246566376598586731427641035764927352421617886224269119066242624928327497970927082674875851351115056557893915 -7046428613422512652994919370461503405596738430212050461469634631600108153346554904906672591461117594903347403951992717898196478021991118570351546472190246834424581799815167001700142102969624961789833517709452016895397996692974329874706753360452371965269576808406240683302292 -19557638135101040041832884577930088442203153910703874229579806730797593279025041945227073042663594273660369439028366395365453093061336338992957216578413572468291420141580089017513875471603068939026017492141690655084057303901229153416859193654010847952238440038741228111271522 -42427825465678971290676165239754470170687894067904357558909662078341312553299593818540973717655403107381941411919319674404470466387514326096857095131592971593090033395496792079342852346686093721480615115124820681581979827776384820425949597554481741026408701798083122465422038 -72808413098501566866016080581015549081857856339006867931450197273972939933338872846671488208303358693238235329572234863427703550488410786069219095636448570324191357980984254239530536588170792891261353506167078193627880268218751206555656024966557858937431998453592269918207597 -101132337558520152128972085924177532225012819192634722656976452350006544742245395241435208332705606253855292570938952849764380069150596676747412579184478054241648541901287264553491364659078488051236734356017675213713860308767826173232619082419935524790778326464857941924556456 -115579743474815539791993631626854757058152270139519056541733186929274880296526466025052284011696988913231952628218469966948679744693884678502388747141446963529568125832709463024551685949977709877381638940738583734819768620236697701638288319951942435058091125736672909141290380 -109831911824886934111792478482451674101352286457064868347817319876948769340361061563753234153223089671971920494895438299244172818588000294456773468867534415798194655927650186006919705684104884175577234699761753143307653786433294555513789012901085518735329768315480442831823690 -87280647101788093653863646405026709040027882614533769153685702857809370322868083472949888228932865154802093078024015004915364434722138121704268566376522473281442096610717433238485884105194338575339292717702832759356500673357579544471186894544059419590084112056754103297363251 -58064892927012212032227031827178110691196526149228760472071612384031154361612385517941149554942126358917712128390342388648566891300431060532024971243673635203829645694466760674247566757734880059960682667344720675282909041342936132291537872293195363890927097460178217446298636 -32187815074268057747915362384248620867904079091257271085128040787428630431713220626508145057608737879595892380559753953553153235526009546801509123478176773116857334879629677397120466139158990172718151112670482462802443463051127219575225726669151477504015595515701776508148190 -14661887372790425200193054527442351621455812743623298607359677439456944468652173270866535245236316762964328226602666637463100486679558879658779967323767352155133089035947089908406009626332263118935058038754654895812497214436495655538849723440208915136186974513712440533604950 -5296858638977807450339845871314596041389755808124360871761550458062107652179313609662254681517981373267523814568586679095691451532363292251367725690693755902051802134652904991218562194517543839659600746889125561160937670890050203164359168013168697608481387780412655714122778 -1308651256755008451198687896693796893020503842029763834020918329476536226349462487986222614418669538616800621349753907794395949066580047969811246559797850106353911302190051664993132979645407319572244992036008746057778397673996072625320348517615523612747966749984979802504644 287391555533446717259582423915522298381163166599845911510268788035152907355896393697763964584040230683378050410292110766976988468787798058310829889856725801080761338764499752994377480144985181848027600425789945589104517923175225977728346033586451566096427084192700052461684 1885989079593689806154161146901324421887411618798328557019625869084323493937256499803067374502706415058280172631317639502529206850628512261272517559907909973238856024963358919693987160827658840050856590109128538818657281105153379091361870368813641375595663655072701576468344 5554921562559247664049488571833380809289748784606887239405288826685239658524400920909775737257514369636006615544038370795221552566181631712559244066140885622716453277918374644956440151391621200344310360717921428422195357991659118870581496350597451450526047273189485565052322 13087686304826171812099822545524388511761582277364563000581590236483959972430363334842297635697698720155965887841849197623279363698676136388758230717988052768248779008589036416232304901848059782731183516149241495071180105847637145911386860756435832033984823703242105113047054 25141486205173064602811720852755486228728821533156445962470180425214107051947607573635307718449107675241114361058394994428923958141629280052531093172501722109179746827641030201297132592438676589452840062872008693160286225207311387344282425642172028525361743430924935776407319 40008400777000639926610532368240752467689976567477222070588302035142156580116179937206067411646120370796957640998291141856872171477243792220810324895419976828529385758876127031569463670195764609399382495341627147158932744716140467426244043136163541900143565684773582339755796 53466863200107441316675404756098544201356020796835277655656449835669489431468557763761738480595344134774834813223120316874241316298777384887907152469371662923077982280508068351516125118876246993657186919023552722206387019380047360486599153484550562390228751449912612625614945 60602707344368060618372389158240390590552578473230572855892746812411641052904721778445106938244743243142832598522691445807660608257711415707514968926809236991604727940913946061169316882582164163234566587664486023385769709817001028068916026480654169449994636334930583611966272 58653553477627056518539589890282336939247376747357527382573729822549990083187546292569218090264799062963334644281669516070745561109544413083176674895721236094675143727846384304955069025210532182075921018694844365178500193201779142428357493460959253265753823974760444464794662 48676886441057533289773834253321012600176258241516574942410026886143923357815034448258797896646471257247343424873640112699815186777868748325745081511965693675459119969901899535538872361885099293925104223264034128287867065403811692933838693581932406184524010352775416783108040 34712650391494379603453113652161632018472592174104474780032104985525459526907249548229667433104862083101933277973968396326484034975959267688818008541948352784080531513611206760863235059029248600234336565958835924079242586357147674293837378842063028713654972570680733325623124 21273554710525071585682886944642537223561731375095351453093451079079404027122843763101978912417389072233140542125973181286584370559143226967676871736227536761640605301578979637912243924037832987581475937704578595256266491457244827075432783605560556912460986703477805941668170 11182758370919564427728195413979348090617836281488022229255423378685040931411679160134722941490923946814798858044470285452328093944238911517786448214411847700877951974139394284621192935679168569802652040238401304756173518784337890955543112345301217718310105058416058876378141 5021385063168637260982923515192637054673032296104341775878569804752296246821369794857376176005886220024108227517262130675687241808526330470006949821665442596234189957585405808667531629728735051201479504181355445996414046723755896865359606555140658683319019319025869910582036 1909877562138030449797708630750321495726437093085751878922185339499407438818924227257255971529596186048973037599903059563449805256542545634114655204722724392455466328020781353169350183241213846433826844364386058794229369026526584002882099957282657662397424333144949144881881 569106689586050373218163527697978612729749430846902814097657734653452517352514393667935043696492506958329703438080294757544123502427520585154015027017163639415772500823108303651701865298720505056568719742124336828335149099358924826602379099534527590077392748027157723881104 -93978604391937364847514311311169074688994915467224942361681463543673304966122775479503503012709876504870602585596889607178941997721823342877051401816006458378044720012215624621231600289571960329896937212201382330902475845340567189577280491822325443384366611337060026608942 -919269656549849130198591155708977693868027096685870807569239834749800861249509252079913079242104816744520662549645999503435811264800506017325898331858827916695577322196985424943075947886181408487917541238187494911948486079775931650262935451603395222594646992674754018840476 -2529161834460570623710488905561020853222095890325809331979802664192476705529152176012067602075020807411188073579315708161657740236298591715197534495088558586252859666302040986333166301766232651650901798397047522957276300137064041484126116928150837866172582050771653537074096 -5129426132673628092709729364003024397820693889511356224071798435647451090720780000020614573069645181095384721465359348894795048803905632853621644495055564325869330880456873513765707451321269891125748107831064008909307127445152306510499879859401520916089662663836385162155556 -8220794160733921641327673148479047642051567420575200153279761595047450914786789815068009927019826010145528956733358480800047391689400791259594632498409613196345153503268881046072669012915369104744304529298780073590462479863614955707736127248432889944921223443665506478183933 -10696717542779910305741295197006606371174148100000854906846471843892222283274043496000302127757255863690099817137308759760639957719326349291595689874451242917439763661793478580696526161910872014913911441151566834144455804875602261790161339611752307781463934324430369397167912 -11493452776192327819234910724146943167932242998430194286221379957046521669304641494408267140012123206284330561652016761471872454063444280549595082446366080768594253170233862091445075845917733188027839431199099262878109714156059879819697107725686561247140112746020547445385569 -10313591931849920209690392060111463980995758769910643297109149847103917713760147076623265833788487584401320615966995395080089104023670814507921209648453709289191458820875339925958531918272643310780211441844917708897927775099550972828616343041005989424048108578186677558763032 -7784047591888197040820775883998139029135822027429008593736934752140333439498653816315896879498314093216963466069388251001444637235834227013888137009539114389563749751448725470120843373686932208884362727835077818921649146285444771796082572773073139468766540484473218148947368 -4959088202578763192271314770661626510795575304232495897503339099903437897485438211322222763019028052300049956972950788322650109124399947046761847054741079692524866245439267879706015839074904871470397469150077332962916198855738377859015286165075902614709954296808707175884452 -2667780296273545739602913268425808031575975991700680960181556749941356713359466609101182945877093619381312059724881804033670665106486429361097722012377720108334800518009475002009023462558602006622935158660979324107861063430193848325109624292002497123735962780671999158675086 -1208068589641182834433972070768634701070955691476238797775425030395223793456710979442091685779125246519966402693257145783207524330674892714282223915159321002549957468815793979004907041106569573693032916514947472182819193042905949255089679857267659165546608177989586205289196 -456415623650492414364183395951089904467413796429962618018661411761714030053998421314598974534282930956017959898705585815387677258069656179852545462519981642856951117925697191230857072848036592399248238038455374118012195373301286660185146834492739074003402719539636063397671 -134709664158908664048197261180012516575567691472007580614566182589820427061176272038851801570358086028352377480477959044382056095013274226975143704053788880266339971501493417145859903598849163339901302177567481291455858274215560965406562805239871636292673449077824039967316 7956682933141187917409978933265260698243407961040722382256713579011325163794766105687526083712123717196589658930363501361624657524035985638079026567843086836247989960571206031934188931209493011484214227713879173724177984426755786116624972214043357703553631867485605563270 147550577012395116068940991763939377734853040165968444670476864392305471153322344037704949259982377710702287986528217783177038951185211663325216534110073219693054263178068905966629408226610995125712855504131034745171795976170970555347359922383200548445135846596649245996204 385191241290512239801154778011942742859314610478091969262092063454840920533840613878694313531328558416546397152064647274545739633400982263881355652354239313048520721526864814661869625084595939557114351984823265651188128462617068581131873523778865150990222768392401256202352 723692733469061552679765026459855134636400938050280362545210784276848077744970449401063659237117908470190448490744907068101607827170526647905823571170632714634689058948144035483876377880343749087888300770147527206609808584403671407044127365669373549725913261496356160537714 1050156679455996911444910915556275469196829219137668808216463963492858923141497722706371937705179913820705581517889446648101939724975272560727659515312162426748148804756587672153974283535189638587957983876695632048736749252271415424251238257055547951983897997140199853570749 1196980826181570938944082348994957620025207957805202563038515067680869311880802321670023063008120050632963234878036884086219578356739737696113815753523930986515123713206907901981996246710192304119456789352745397119660369161988024218838326158856393864878687624001564567713778 1069251747848015921186938619812430094776102196953647182568700509164717751504040916968047417493869818352799742838460666493044892937912183408720431164898463623153271127808596389415551528741165228263239412434887461352664415403348601454229409883153029784691512312139693656257056 725891519269235289042474618185234331250758967836174851204124299701092743756368665172542389860905032472025892535367381797589168314879384627996564652550418028928863302896313745568152251240608846273722894034559423612748407386161797747877161031712169821392850127592770991686760 333477365569255927456023069068689697420557000067592935220082782295837019282122123333326194100091929397870672387165856899998362637491677644004109618247933509277177361162078820754244737571448120236751880586068752045609090469872749290175570455134347679171613358014313285124140 43180923538530674545247877568644420080493650341190876296859088442960721883794917398175191224489028740042350130974515971858347233775574399912402513169871960341313139000649785613589334300520469553018404652144295539846783075559320712412033168394786833669201373677103760360072 -92632957665816047490962324746801822901636823846528966342055550995044938530927214958449088191979020587344046380047885465302081839180738827326436217704033008520550442885083680931894606816034352956122329955526116185326828278099420903373709004342333682745077377208358045760284 -111107301356830341056987887731889621491177665847972454913669327725754460085397957964237409841925253739260525632769620608300810132219483247253742036591989312816933384013723976842526610927611697536126473617300777778519375408863095254905355437798434972939826997287432856587770 -78220358307972581497098185397546006613650725343063223817213675223020546100355482492575306050663319508926074369070083417044209903321702330318586757897777153504859384127125120969478403523365088001637753546898858547427672844957313340661895877778321181713451635226938139741145 -41061150880823296654356553506305387518617073568634087920174559836230906323627107103827650081748340958819793002399152192753428908092247096463588674110407825488449249905111097224275130226868919221934016182722510720590378868389327175564297610241422993783116864090264776514218 -16950470696056175725409813529047857641551464376499199829608368794382797887030310518254742637910126381629013596250038687814231376115118722486881096005772550700001413379628567837220259980270028310101524323641108209489540354366043491147896459200935419270832335622815555247072 -4163783522095845065265581640624404083870423094598040985047085939180058604936466370915724335493067664217194767796814547214709159202130081696965239633616173070068445245886461722319705602584983476019901062297764467195394823962469491058702021283203575696560515996094981542556 6769848006489096645957270976566862640262790998196465781850798983823938129842199452110865144871108283466359068039589413161226690640724994918346853092302308770002950427722657928837290042571511552206730495964882507366009335491275147779976179706016678460220781600964898731834 27478635328439604978597376310543981194622852527570265443274923823788755569350470976989928759493014882690836550515028799327644643186444146920544929089666796295345280132165363176329014986728850684740914467295064830333137454309990058231784975104017150028400092884875055456116 66488867331072930129281766117039825427395513109718386172165663979243384707549537141255373832965811219860384213878129758844226096188795243753403049263912395555373068154722086209939227516262277191771000795521706364571169304921248460272827320102948598947567514123917849692602 121386352044376230968113823926180656985222847345147025833767823923135232292255962517092821424803964165176658084489451209176526438090551112885234962885547247692428870326047577711316227015120310974678947600559561306309470534336902216102892124081223621695283459250362769131770 175194634440886795787429900388927748900920140981006333794075775437589554294984663632567597788347876302643574597450530628955645158605919072357987780647058393403643179285309621168612092006399395760515547919826679509429171166964304272754350539414443139607715373599456944050725 204707844762677933699537350201573835011178350203965971179820665087784453800949944925274856583644005345324758386753292701149414092992033137145128365799796037493268750321562796509940671398608186112282443873562838595612535341965666422462779171588320617226203928182813039870016 196439866424650109511615351676311296715650831664599922121411069157825590180809586513649969962910532830536520511671341452133328333456930627310256374223102661352459597476122678342777101643876908565368197042115275301801526745167148301194433006581178865455946513946969908804328 155976211629990910135533637716651247788377752440779798320218166899997851471088757916700684632492226063614235085429472527245203457401011074023776186271765539827134489392920242830991771571291244320239134645980946124582385232550553513786087342772605097978575026277643331680640 102580209349360022490915502204397317449638370420958430187241909770893803203741126624087639185354563449171213753559778364182961193171850750892560886039266681194347664558189925490945784844994771421998606736956344168648533441612507553726420888519276210376240289824276433912648 55486571501822240573799218761890102521580520719855384477125340687528954183750022151337728662101543005305284328024235717268302217000826789693047084819151803038447653143300759131241658549888605124293714944523875571301311365937998277194622136671674645369600496208925531554148 24180707741219080119137084732043530198137999276308381565235619433279501241478769576141686231099674774723431744615912942323250153023050445781076896347866147816295481264636029281465758700179326826729223358133097148138985126186890988825133903135994597097635727917882682961658 8054862861948119286545375309312149522732813991297528431143885261794807527093727528852490868810214881997437025256977496273083080560133419263044475836314928952636440464845837696633754358096337184249432708798284227508803219012769485011877310402213295907172225790603858771054 1723001002448130307495235457597736556113940506331735497129052613961159425619782622574279270339314077228590626409321585419820676634895948652658074934373368833519408913125777328620609509063906916211974548486673880318881665575901412581115184235973132492169191522674676516988 -39384598030285023626397170012274421916392423137586115070549413389038498022336989328418989961266049123128846990042565809130453766180606766137000933899250124225512157243964150622278547259269534777929001818998726201968168906325892743934527591369646406008165447246272797042 -402087576051569242809747721609746908491507698197227158579339126258853834871857007780225043349972720310954076206917307276170326815330443289087183447528517449369905038269300888586644525029810572172313414060367709341706372831760089805143504428461032401059574345345727859271 -798413129678823411335591620227582737476939256002011988332637424645752364501245478790165452488943566837322550868865686639657766901102969633284396630855228044848108650740329189404636766147044857757170391336113212193718534118312810683927229598613883635497494633315762143508 -1699915459261627591990080543464135946462295235115109504919096511869295283955633337810960747919589969061511541699470937528470055073806211821870735795128632561611128460222833100339118768048203137425096890015276000715137039948921358254276310261599524006507496340676389525577 -2991570171279486445954676044499656622230679525391208560512001042287631978503006780773650114685995083954018524066791754291115853665069437419332439267376162647275967879236812340898582800832982674770410042044210470759792231408847091132222208489121030201635717462772909368728 -4130464502334988394556167034571120764046784722794762460628976982841372512693557035880805192510052356613506876624940478394220628710982713327742541906431367321983529041551902001123873932712184894419737683995723947656279319414251805481096489313708868301032378279663544912512 -4493281864626066548593967968662757166231500096907656553646927672714103365007044327887150933435316374192650774044325178992300301674043390776590782168888859403591916267314837764406572647327282278283245933365798488333657168538372216910093642049610047751045357153361286427760 -3848551809963726051418359246487167186929101018551044831970038875032842677695958341364199443127445277494492351667445234872267167831907644261116938259170179216172726286696840738648047558217921224814543049946315925879301638992414801591714625012373613122270552098249341701122 -2535264502494329229697351020696871426823574796863410996363162767573382673875723943984373515715259985594218796020775771507768057063052253017065354917162680264294493607606333801524025503914846463181106443731576432240123827415663536794269846266569998010679268073800992646556 -1178019608460131861738775970416385816883591476348340836563685514023663033611930592547655239788109953457715918863006308111827097687706089617702229911396131921814559778484834999457637678176093944025823787502262142624353747454446605726796632408815956206940338324825917382802 -242746856839536098422090447866923038495411637891261313148054884253091473803377724028034843890991637976110088957155377769503573825446883960622695750781396612907816235428046580103351724011333528370558207762514019101301978586147363600691940336679105304210217306570164748208 172770274949738114864645075219724544785847889212467769598000451829929057687615752748645005838630405128592071088848715098476486627102534021240920296796712272748116558632891143425664693689003605756121200307958803419261982359815190897556951103369106660246145915325284480234 234697317674594829857923676887297653160507703042320396465394505818601095011147844735501068616888346829214432114214556632553326211284229747925711182088982746060030647872250493192975152234328280098222312069094158078613021310348151392608372602435231314125050286985100986558 157635436944473699739670116469276317847455566576069531121029480657804668730001416180554895490986557521522550737884380613835679968096157669269681436755477657914360245115875814078725625494947868079410504880640272249674552562766892672930768011226850105505279459689808596127 74224788691042903478697940024724317736300415104356401931347973414853678650081742773898489899575041681603309177055633084321595144485385994984316150733124705633431351928736369168078450638702338175891230923638442173672927973285368062008845706311585574340692603840850903544 25880732191039040375180543315140374694337154166553276508536529850006882908415238403519831479429066797690512875918816896701615860621164103351623470456194255138641875865124176144456965575527598794465175849517562809553669981723635183825336346266333485438710942495946283867 8801007115927924945366888439372000743671930820142482291842329329844146046231025327983850985036409805546360835222847835645793689173546001818212483417176438479708319084670297965727512828347637283051084240991473044789535914985918174480039320688748547493667520566438516212 13878195854011139110023511011772992560709955258577431355949352298858623441753826080561143337858743548501064226619137226154447269889902528763859853412038627463900546300978608809995998076815499262078955343118432854252567373066638478360572692369160743418030485503021688285 40247952329962676456709984486468137892684271032290272188157524278203822352014045251447698921935798526365707923284432893380544698565252939777291228957920403141963722781090784756083918839030698100647850434553270611529842560535537093283534179249192610567120784086499593164 88341136957890286448377316564503274332373047970827802771834338546175457207021712839930351830375031162096195263744016409470960957380590638817766372878917280218527553695990683607539231499328076718805501350714203403465940697096735361026818486925871366591901806509695877479 148096391268503653370657598831932510842546751270679125020629466106373302077286153429306745811697145838675569153386918945054070144949305597424801305223020830883205376083678111426436703797635101285781425578804236202754850971157515833933526216530770880274531184127209432556 197647322660205904869392763618955216792561513212615255236146751644025153347912440407086182329876249028900424315200534029645628810574328008652804871068047346856866609968991120842227041330296608799571187356671355230848192874583047299563562715430724693165729558441850138116 215760265297647141440604155977426806352572662803440854740814226908205322782424350863219318857038396369041952012284036156426133869325221985133433530723953512053272440578177487679815212564642007688970076682036469159522564404258631237181458276594742657987525528854596636400 196205558898326462065679047674931538028234603355961142137121204828175838017258162384770295885397204715608397632028907425351933275425362572636537355716801741905865725204201834227071430902974932962257865887350831011108789312836399509316496887513212225253153276516017064024 150513310276685671358799768936143966954485715267612325971541065279618855243898267551807703191376156487522228024785644017438762320611963547042041454736593639047095903241498100634845530977433232450900935166663657801377942505048261553653683037456302991511227068156540559628 98215114203954239396996008013707942054195046016167861128828945748769882059471840608513012378695361076760058940284000869142746918273373160429447500600740239644899109165498237149572218972658766582298761838864900706842655360727835693736553737191182390924571332018755731844 54763575705371745609589523296352707935352813577266181476867595503833873208930123687382776441478226788362594185211570657919225309911000532983445218709344347699705990667078484472324829093059438446195798054329568227723033387742259437952850279663630757901041713949373500628 26104174149075693098979175949638541246851675518171449524824234678801320893078864748430602164762709689671754560151485166391516426624216425840809787483368095207750370455027900346101688176928816786985840275851005432605905317692102801777010982896748132376575227552051423970 10584693390389970239368229978591756999206105034425661716408687979334321281587267323082182685769785376676498976605510600301446481891378874604169835538015649777059743161488734351141629960433608454670974720285516107912800930950509740437731605924601914876646615325175498012 3692980832429193580693202106556835029749093339224123976618294642061778602246837500524939876500097300720874002066424169911243031999901356605971814821019341689370845474053376931258841934618192629620204246348508538782072883157591175709601566579717485469442403576023987447 1882286672415160374210825269300909024536801326723940225111281320796308344285518230739182106098984014224630997457210631427886732858114478039364791640622829357742666789966419292556584146616382830010571223597473928471561965427250434141156950045153455098795243868448761078 4357439020427994039291179016968104573749396491522825966069176470383211155171022350332195027448407022459529076000662116137051776172639683033414450210572090166001632231798345854825978478190365650289173656706326218264017820624199238157357724974156057518360430291319698915 12565529569771680147116798317171839351279894938189304825488804998670947494771823903742429502392605229749269734210059827205079733273101998338653293223641247146874610583475924466226134182590411342811220279708032945879087423768767535530054669392961275350919934010467006294 27404572207350632901900654113679467716278301345030037392420450402764336817523193956558648686344734621768750691790717969541721192347474340340327594686076507319490507890960135187268316856645646084481501107485833352049990950996636229957084735896363998204627431008419468724 46034239730415191220895599637161804584971973877817592269668750899543349269641822581239414477235106183116564430534418540007666221428528665629507451463412023516444594368025373144631547777093213403169669120759669231335894600730850928161004398610866273795466372877054173836 61686491196189168024927012615840454771899571595536276905437915283607922044045998688332033100606657560111487599173554839195920726870739892875722252877522157672562249933660463588127742276594183817949473516109762528923349582122272654096582286701766892532998849266284516582 67562835906384228372175141622614865572431602926472592616202852906993044961940407892129662849907494221885872491437771140794738828504838899571907279730001198043172977472261710747076178073395521076023593759633227114634689418092202647490399315647092005271316206413551647272 61491658999545284801377575968102354394022023223797345747056257009812127834847902168410829114714695444058228918255256580610560686111236272360289008711138832910897386214620601365510719984526814911350672337555492926534646230431193668824411356159097696632513121343489414580 47035070766478325330962048340730672535361953548851227427057178942939042393882412007359922645381896909314025137360654144996049724172559064761623800995022357837503363276826194489864708399988152681389541701230771859224767021197002387120093373621554970015547630109954400100 30464195459771493748647144104731650640968434389668156797364847762092679257400526559585941913985571104830987892827279574623767885942148867737380273555129648342693512754553219952956432714047335199753416382972816163891607224842928327374031845712399978842071433589091278870 16784536841238903747102434030595640124588456314049035204702312576395247686454374404601098972900434288249111322124792093108413515874382790960121757616176208390882779887103022787991862875143843465119552550416591111823450968508393684112861252023836157392372279583745547312 7883260958018836690147810642117631764869330633407056740490049768532292223997472888150720277512815096941953754091229196424832081456414616443451119301457696212315574108798167981436356770076774421579011122630498422554330437646524684452709703420535373511558901569578866468 3156142315391798942048522093180988331568877874148054623665864595239994019171240231324603916450739937799700701761878248911165339430539330939193872633421288857599388465345680717885649164382234317964975351993685611122289881278797956230838152708589313743164296287746510194 1074854668387747340391936972723690744774071236990818792487264309742681633179957086522567641931194962126720623100690020327047743771398553561847406555958781277815905499266347125829044307362627023219262659482758097722989859933024988685925741959924725230825638074317914557 310115991011258898606055007669084289838996674274099203513886268931081976339680919062202907805277172478006018235060150298495941290626028061655114624484823169860619465658559223164081428128379661171281332830114366970897840924871579900553392096105612541570696659469520434 74026489255467637322530959050170355034663733758429202038307088190085150330653998137625931772027504694524707148363795770276790460892395389264160220338187538502980369270622472132792504943833593801385690255508838281795723759561670214903335105640763028277266930367490724 5026335088290927229734741625190914633176190198100103388497158917889484307564024822773582595445936267214429905185456985750890551875038688965206977085409048502548768693601165325732680522264921678833712367752220051217058466583414409148632413311512877051285562414169262 -35822962239229038216832577359286964737167235695855369060056009775522966307584101317483441827735050742832259332152708808842648052335540107995576190016546560667809946848348145106072353662338786082315312032697768277811565589516815810106997170537099077836869502367635371 -91128307571413214490887932286887783066723147615280116712397273145490291309706845534731005879986788483237459344065264850212508902864007065686048043508078420614772888458593839301218434823383564853557180759439989342272166910680214001311237454975354981996941271321238440 -154278038302294325500355299176547618961059090879699818399674990805113742164665123423294939510011503006223730228786902005640229852495149792945286355343247817530274563978069340642278142424151106129711580054459628483150883042554602034375275038500192365220688891235498284 -192780006215424677702441406155205915190314170938284449501433014323286236155908352700138295968042583860969620368933226043171138405046775275994827726692373589758551117731251672913362567539063482272679359124252640017217116931934423628681453678500453599512927610568551648 -179611545344304541652573597249178324569589630073159295806975097755605981056111915328466843428587052549267528416450719173199340251752798352106769348340137380854202599234916036934810148878817074664507188839735173551904887474921196804118092995282960283941314712258541908 -119012026790981406735268945745501184269766232210036420786990812238065973663322198579883637553778923033627195719131309368200981633649416246311562324361556270042187159986805381820283408075539047226102175981909071357499850331573843925044083149121672516111584149990039600 -43360939548346776042857827461215365062753807888754546745064191229619278149604192579054061376801120191673222422825183967456151286963285825609229458045013350847490865894012166993093965754591327553594981583214986763197384534315114217198033359803067233351479523342363228 13301448690066152663627704877481681651810321691615814367275976302348056474258431937297376653539466363444788040871569743831814364496292396098859201819351539482694014154891336117525380331461451580987794274680822635126802297307410029819823835406769940203792906113426296 37252888184412657505060429283521276064427566589749779015582506008915257694275583725996559659066755283666584112838424372965079203478376328302405580814141666884222071387087383391880977742696592515196952817613555521834793531377120264814739908877236755879366773866463292 35775172129860630438896727624341189866360503527078838217326243363624394716811256039720351929195318534820392159225852239027460672758946482512105246793785126340396016777277480706791642522012048742657505330871593225031508973362289376975042653569711365659265467102043740 23815564688840956796158513816753738485535644988631125696788722515555406303328778166699849333595210035334147990467087195748736919329354660951370186607984570305487156066230427728573673331419947004316021594112973643614128111990667624834604561056536415868638731666768294 12304884855707277907417881599851998789756581618197652332049487721556877697402173057771682094436066606776989369373954945939710121062464787096820003041849031117733071556314522115996206740241185737804420276322112360845124931576768552845021544079695341449008096442532514 5131908394021126884891867815956488417605531384968853337426206425533439830929945227982677364488240183491467335926232464680507564435141759706179248368515619270432218237812171353567741270086117184529985866243143154903745886464402238264493268194990358678259009268793926 1862527783729952210131052087809678095542798452335424222162377164365237536555461663056807880774394010289649299427307237085732560901044203603396892770148799933962337108019852993242026312437898098959207215067462495148314790736412148651884985353589536685559662567113768 1110349620306469758062094532093475014447900411883059660909478287934815701166495343077911143890577737005906071412693217931781664996780224566195380622749353802396598083908902029002797925060547689695158200599214702026237380748976566769314822878053373044220625068371366 2160782531091253428188781393200276685111803376684003321492689904746658391818599184355843762817917615902096889432383084023277051096190612106669890541910981030729238456284712798154563923297543307751854041776797998214578132760474147594493345691688647379499204272084672 4908130171994655051510852740765693498742196417296150891454739793296097013727825003876474065547739166110060351784294720114285452515167270706753369234803192537456367004879732461428317312976732847323619686232217678511334533393248855872045097818732668678655176759669892 9024416006692685394918816498151299410774924285051510733623159089729768118720290270240533439988378986266032779546875066483111260895615854295069416827117901810933109988693473202035697875702632961659253703875665738522634315610704006862245005500774214732348033527074716 13367599548325283781117333629937166242058996622529329405362406646984744789955235782621968983818409015352112997256741556205732672448755770556580815689187745665554554115904471359199533980001009844622364569600235618793791553362495417225521138793640958145281365055207078 16275335354887243332176109335298684343210422154338818870379681540354866179845332588093179241922291536169535115437419293059425740743463050516083419564013736263271059331117057212099693555203265158324905129601978673256400010276936486360376369089829551316943034000271520 16543715765561473994368919176134809820661818941597785377726706382675169349724424966518011045826364670974423988921996173682853465822874867098447019317961819478370699751671259424422205722536342605691065941862418636473672754939224479811314391728464663747529260392836718 14195594882852435937614958387688629131420783413114068834026140625915347171234039171502547910466748685054251345743237610679977589763786571185065419758677621286135970911236422914250047954041721135463099647316198595065369211925935823714841972818503779849538688184776296 10360907048465567618975085249816819814378797102609563061850638726899459338329700243764588459848786032696887261898727049989041306570517459975242595707167191326557453910752410591413552085294003925957595957233841293302605288571455854818737438821520383147250575090659684 6464451571178583584828962564064837866836017608435607565583511806701303890643069962920118084369584512663251040335956611543749830670054448266875909430030239672753690332010478789274819571451077828955307288336972751077160036480752506079383339461099015407870542608907000 3457713701447801714432391231581286075914132603095954000589238824190412303440198497028477126441995457289901167173496315926141749961595442187717838023416727675383739815198794393090428766741948366655943916083041087924447856312196482643413151356926686488171080141551812 1587034696457890584389741388065874677933813340512909705747394799777398409465479240451659345115327637155536489041100435762350210229961599598692113239551371270941171226662169723628938153507582658137045890744701502479655635569739541200176222672956002069632640196516254 624555397667566134159834244299545765917928194907595409091973713695236455149796984118962030446184231608993618617456972387167922616171926038166896232382938027610126647399818362594576876022541576466714169523047273806972747213194857824809866753393654038248125097342407 210189841099737572218050150419633501428797452013418061967829148929620843564180881530405583682411012630685689481488237201897815120987556540660065268603566414161385423228712554993484914880648543639801314582811021653685757332617032150259653147749291803235654781068332 60776375299262333934232813155544098567874908343070633281088095899632577472390602985161712371231309446916241915235609115255847603494983757046032847247046803493185647795713263595019638172808527747044295170596184762304712946674483421689868934231718081707980290119383 18921348290092646057912998802011624178912683295580978646168402582322707021744728676188158370831953816707989102291800481436051290961810713284831413787488771792756881236147910651649104697398704828170000819367758772621321760450424255259420850626173288666937045851256 19590987743027014625688366690793262245458800059087635754683076826093945687088603144921052201231167545298251976713539368623032784071304644818491443382858101217430305765830080422415104232689861075846763882854533842307076221806549033712690474782917278412549048666392 42213457051373347951049261021696800978165674642781958847089904847974342842087455830164905492142539020681841862698355069649758646883306242658440356349782638001086804156628861571852221579594549344526528325576900996991936772861206672404248539989102066432451709158904 76566108358611782982533335977511422193494929827503096466610267166267699856803206199612760167836946038813224260182886202984402846333189852500745603209917104005426926063134710430440140949434037775349335962848612097337655991829845078093764427147522429265681763005852 108810467851547870796098470745283221592381589952849302880445799399233744130401637946307084205236045828542766576374830727597625027161637835505083875815336509773376491939841496102607109622387967003869180572081470805498359535173328628303380616135800647738055951680156 124372532406839504112833062501295989464278311196932422626777964857599369549613860682529341974336154093435983080166785388708338016579681163810134038822792127277934083454685994187390545402924797544773940007941564382944711825477234991460368111973915283209987122459468 116900357285337483845155794449479597806454730756854104711986111414110991976405980302071689335015979726769175255945161543502658469990904357411743135537457620218218799039353348729198362504142348724817401813265381597211163229984275482612020569269766521015146253766048 91723353840357762967289028456094208652266457077002574339463904940539508443271775617228377317183320283439747443628840322641609080631471251751397713257945266726783473916927980786559361609463461132930317917106492932132861348486936414910124786857938223835317151803364 60677106640315129813850491218984785049865854969724469615646039225602408618963504089841460512602381710571959648719887030796599745447610110036527597101130222783540302222169157515288449155663002018700561409964486719583979094264829185462167722699028344140655933696040 34050676971946691061654431434186924752346063107767837566424583146873922089139217068431204710631894318414498339935195227054879019654861084817172477003185688349402891410863328003677931612996175432990151419302610545289486869712930587462104079423196738504376694160792 16261665970092500174426162021151419204804947082240222456508707040978081538070656361368976152377336485327490920408785275847454103958835186819395318758690773725919794421698159236957672784751915031866851641019154154006970753083847283154451307001038920437043475623412 6613085216653887027174328666741228818389317812812893024701188710309963517012444432799240683592020273026024792404620775858601758630030783637285693998208321904331673793405135952658781279931709886789613089967959737926546033248685462783748314229697160424955750137630 2285742656403771884237612765692719802492697190588364437537044805649663321902887728949955924545897804972170118886765064073177087697271199273597672221796727132494258107645742894918004816633237933848243989488539101126598835385021388672529837192249803809307066286400 672084897597781468189361395380894207846331725367758264888747605228200430310945331923530187949047484898886778141148526323616848610450141449732622793701303186063523383863940997253227540064368333412998759142391638441923045883222017867742835500525645605314322917777 191832486755278922184243022161002355977483879146454859030263553170848466992669807479280288020107415383906953386681950744683531249901790797872458366622523211955386091697476491581839324244209537475981394885377440948357858455208215852322292220542138328183203584664 136209328429194561968835388154073482607742359087066166571142663647096383761810368470058788465365961158387644200494220288221422092392384933053477442966284420411715435235518580883714808416299518393184073456894178611361244526063095004809538665841866711880530580436 253002529270121612516992338393089397082784287473545559569345457490745286005109222094128827413223265943226897852736120744120872790697291300610519872170661775731605448957202740492600109913012687309344517893991191786359145237591464927964606789581558361808910808224 434759995207669110786646099284336719988719047998338209269479496699995442547474541086808418064698061624000334610967354850046903864498566617594030566763944629496590819597734667140711447411838839714886727347701641572053017007023640473555909343907241383769936979456 589787487068353768952511318976125608523252306992146120777450956291321502430645778837952604687194313729617641886980101747883554202611371558641059364182740923549985106037524990028916135785912945455107870124037138018973633861195705602284459697259451177975180492788 644173424711417708526059995823387933630291876419828301666341626084543272763900899043359567715424622204467327744949714028299125998933507226340162420575786420668917641438589937323153981159979269001675856849617013146317771456073199488365021370541312008790737635258 579482631603777438670083383010641212817808330791414569819235221255170589382926981434499956432475762844984953399931917764492230520947840682052905673315695824271773121514190010205346320318933246744496794795891507497581598893760481683349918901858130326732970325000 436271943659402930562611143810300984143705168453577388376174892882039700012280576910994274344820364752416946129595770285679545015326820103671715102810254125501245386926251535427229498482539632729654773197277519116621161403274330671404526932710086899339132023752 277893525405488071824210331925361382312665446298120262307532869989109732986007480383613772602788122722597044784081357788227367126115509543760687202174093407869906498825972295123929945524916889083403302886034734296402211939479813901300161831467183331357665188616 150861398680525412827751216847033911094479138112449754679763624352352578283913026245824996492523586960023780145451535537952912346213295997920901715589948075740834936524515095493565195376095887238743740212810635509529221188666377803948293309731376641149185330588 70137734082522965842214852348128174722893041321293659229308965647204938021326966640666161597918920961781169051294954233230023527009530292656428590920044260711967461543306965005244332013065917195135725654698424115494277249678834390049624299036205663170780552824 28014024273442894255174516870123028701849651920231406359482111072290108009347121595343026591907072831463041516352842532511987654363900833951498824440354454343560816122014809206514989085202851488766565109684776567596123378362925237464190409591256442576967190812 9634344088216715240948819112050481916850148338908796060667422582351395043727726581987699563827720184580699815563906649258124475777009368194204090681809938833722741700888523532845781628295902645616061888978086358729213866089534171070326373130549992824484189746 2858711777438998155662471769887073071044965528677126089308472802296612138996847069799435962402215199593660502580841253050140788177520087357164035247948087106278926814947866979682195848637522234981017358488767280257147794335774776130659484587241132036044356565 733674385650963125083170637472760834471329292150724210849489197258116862286624738220596495515699943248199241622894077849060192983066394178764740837094977229582600174998858865987450673816617484044866654216268874779774553461606521918426870582735011476331115542 154076787264367396831609296030230673633030650835939851226461136239887505967177576278737794032793158275894338317554403613133433019411127354993735615114831800505160209225957981139822161689146871003084490709639884332325511129008725262490014616515066500215209208 -25186178195691084976174678884648872096628969051182474726227036161492732095951547762856268322537859149368026913624908944479990572905493618224487466007430516668939126697185348660220798942130004597364356718626075015032966123511280783844019765389470426770708384 -162792606596518615603121382893520897106725782529479223781085206143891840072959443929198457632865335075003417558332657133074499129452035528941544677863592615420503508762850951838246835943441299995518446761170834730659463501845261881186143009987348633384855512 -318156576605578675853448534433092093821071561990517817082836662662230307486531946815877563213922272735989072245766939157777076104119377231301850934365669364885108690221771090924900153852475306230123967501347478529487062243407087057124699536120675659528377400 -432692330704066754207137046380130185727036647002245990366624815146258172886098291280112147126975624763944129370926632600118510481868687736573782519292959900467587612169964997466225709578002485825558036560499023892317462302078186128912073813905621650662420628 -442952587218813688614016340345576577086554807666737716991393884620896172776154406904618111708018703957182697876944402946135990466113035004922953181008864665070695721386620631873959636800737336509183972410685358502913993200552211497865770072871515026494317608 -350088543102578355199936507162951199465357534566185115571325973440970158390820637638531864805097347007660847670482426946971171446315679507561221139921327098678759318169462107794892063334011378438532960207614349605859535781490842365811073511520619983667769148 -213235696777542807216961534345568934803732427368551296112933095354080020915054041130592249300198158854122922461948112444878244585087229898217968984571129884997793501431967455813638100563445483960122609707727084589915010344978629216986576557691669618219459712 -95707541260906648981241954639306096139519060194587760850762774087648621699652246621340975283503338198454119152867938885135723948979348948988612455208727633123127867417262704937468417817517874197473784836828265161061020579391093164663459397510026392740319896 -25890395453032439920272836229474414473569912586009331675316609627236762509555279118041921055496937124886585760706488095881179818571894281859057753832552695116149881572763752854284310915066448620717394719988122079571019225255903199321512507241193702531276832 2160922396206971062719166985313886421335801720239773202192033963714799809987328958934591233241124671720770071329959039888927266282444503517704510710666412258541497145095008988701650654095831898854176611725902470842810117892526055763798970487943447228308136 7416959682238703699672932992320681829279485150483286712919464367418250499140489456372292970027543216544547383216485699566217189812682628679320794681218988605986033791598163785409083111773685777217948883160227139428607663237649331705240013621848489598469388 5111426912892802703587298151183795686475075103339665224150744128806813410735083608864008298186537555031447729274058447188592270214049804040316702529757045208586519579727324152204216762935897235710613625502200485290328017998958723055529388312918471235003022 2352143969830590360523161391720710213283849367582786842366829641022054977324926832157209585110531785530869847150521486611407242028152076290745913568643475808163731377684499791542550935377526190722026725264304483094533902635209308845633446689573014309451214 802335954903090469338889498126326449377802627844156405490647889641043918428863590171572156203686293954910998089093838239883636092832289302098043326644019777821576949816771266162512905937273724549807750957441053872433849203148841203946677633749164207124560 82883299545091805274115799837697314364114637926468362224927713333116141058365304481044090483456749295018818175695692680627982577844929003707751619912697695737185855395024887299331336582772199155955732701337529804857968118628282138184266836276970631078082 -396602013949659536900950956899131595421753587101910132902715941542296868000423310066936093120377177087531813642003242002250443459843655474261154897798924387998887467430846550130059441423310164093069320013278281570987498218763116159519350614624900406773261 -849442875983364914165322972453855530212871692770686439989573343450685379299198784451599999805937422673245295659759157162364274201245067342706302650146327058971126010144585421078158927305410585557243179700682515369628413371403297282545533142781061678830700 -1141739481482992592169450206066669996736194771666825401937930764106712669173011920508293199592945823621091479856461401439469296087966557567783828028124085450564112406709528159302972009107713513636710446391276238935878225853159188000752215738190227122318859 -1095470616868731352928579822171002744266976334796914678251591676790705938670543133424876672160715624154335587065999163859838625145123403620039466715818960739387725794411902012513513573630951215011717280587522395481354516307364289419030839386726384144602526 -740380776590587139175193440295755881852758542427841522039656488456918869433453277518392861866611635970550277881396642331324323758136866740809707390513108128203476241807282954895991252060248129928685136640507906340894538711742654351749587309796253027568019 -296223167647795326932316049212878396957107796604185141434122903227209515611933857633101367351267684385570860712331824496506708734323438348096896865067335478322322769424990267834251815521051955542614519587892673393220445997306530180882751790831406548201768 24400203115066565252481365686973710947861567141780526924080077322235257504172029773081082100673624871247995555482148639316643711671912603953036524833094286906241038095688861178858299500998685510187900924207023571417730159310940258556411705288371799028775 153361941485691977811772748761592654497999167357423495841836229325013090444673580392735056502462401222397643537072149513627140639834071501972304404542641951632354843552167030001819537252437381646073389959777501093329555298210070152639881743038433804658542 147149343520558766563633637015038598218581400665667211331156697134794729077493873310447792028379927197249976840635435433544110634445770417274224378417822989491924590734400576864007991321081731009341372627552565543558249143304006477513142257294402905736089 92729536265888867989486973855384764347459018519303172457468559708711413149222233588261083161899979756002072267833742566656184173927052717125462834169960990743448134105635391985370372613155581324164819209730050666606763886071644849486548097311159104100908 44329211264522010020059285581534449380243023404544032746464492440899332812879746618698018157992826587794150213721740606655026358433135960576726110273232429856924058315379234930772570027112573126236263192524803806111897815703180269408455540617812653257647 16758880057114184892391485643448310215938816641388673922385011275264288960720591242666284211764718129199590313229255769550641204318059835273834707163222459822088817736871169819295572532132548670135468871002897238471656538077928362378684735635521956873696 5056345718730385365501758243542433712218409692055468134781940055659375863403476332952614277563765390509736250078258597168771288735439656479687067813186441543647764384748199381132427662466408543723682042864747193403190768581431502398599020328749619112088 1203543942885479118501566454418555960482067674969360615628877874979938988416025713888717437623162921776279496858027380556004943499818079451561104549381685397858473691578460160071544057897189350053686819633613592799203175253867825077043607214432705711632 262876430363306409739801700290455575969182205775452245818337120546829016860981132530962186960650763001121659649638861253612136232139705928804624522116722054762538308951109868211149673483612090472525075606312676348050092405567104049846360988678946015148 300285090520514673393807697119849140814906470858303452908466706861871368855645560128028405567272288591107481439165986176348546515982897015861566397236089116477560080817396907204428609899315077945335693304846332117095084127786714543937457774741074405718 803018301607106062176790999898804722575955096318287905734693102950026692633669044032267850561864066040511670197513698298569408534615959128921405256188090128581491139975830051354832436235895165288824095203744622431312399054405944744780839692518463163670 1518443158391740045609114327428193000712283909850486386275959781599258451821623546554807376296686159234310660507489560435223551206966851239529787273345057071994499660510125103580067085932235434649198799816097472128295681819943451962582847347509644583324 2081997245464721136743672334683270248298892956278564187664604250267985012926448778422140309944962011467096347864172679195860854323378447324774340545227666898734904856716856193860156354400505788214548642333094788910781233112820697833882537724204958588356 2191963451882660766192423372130597049722116812207396406808076792472771150418951123211999319366640376701993111954901155559114557186086908683560589930989317645247716524370188342182665830080076641162700997840170359894126391357656267070481990150737585590862 1834612262446268892727879838048519086213641201628469099427529769125661212213331834226600830070753835961094128703524545733992957422904772523213958421136954477686101392560007817996644567780576821885779811614732319726807546841827777509540727451724560029246 1246157177312559350324275463062583400046307015835733506263853742821046378503901768670527575903094471653922460514351507308178498162114973672142999488113007315489838395989466160479091427231540204677879979096017545827340479070308710910403341400855764728440 694538863129453189942197014644661604352718376242716414043375075612475847555950397649398286357667888495308459131680910182349155989305534772180894001745067537160634753338569681456183911348365820258552881744669466002402343901061595432230275057282461273828 318572663966089223732654338173860799973399140539763275591369559047424065637067670683887023238135996441376450265402198286611260331874477032807478466816947280800805364315202786792279255709620738919146342624980663868057797066878406257267699800232845661626 119584548343754219692045897999311415146185835320045586353763792886313928361848066272105309461452562647444972061353952475844013181014900303920640359923401068518582716632854748854956883705900558696244461544403038281912936970951410398343728429825690762418 36080583020574268748784796670523641019078058176020078847893132750578723164490432778276686240585411552672724739517244157619039387562103116246218237863115582177890368262707047197623158373320833626690334595744347169871937774698584188528457667193750721432 8379561482325970094466319787283135395884106712747786258582919715407079601656970643582456889393830706125994353785263957821839182212280031679773517631072144410218981402067211183653285064510521611453464123941835055072150990555290486691709385840157060454 1326068580709531511136888148587287031553879790975942914162621148127203242553337047645439356170947525412564885871020313967761715032399120995646026394191269439665887387789859122272521267258298164313079729385207527397577270864576652042809472081345174082 109238077594363433554272829780304655238758376658801936603627387718830923666798202769320783077855871577846553147523732940059081682522212371862993785821337522576825383706638916912598455604593344757888898465352032092558729703101857517805883700579627137 213392060773205278440566723581654670182029617173972858689100889445604321457531692012032009018706009974877371093565244129393507975393804724437428542317546492369923743082727475382852381144313296680353598851914090011093495089729132520890784301526246714 697213975957979225281092523042868186217878318870388467858365848281996153235984852837183080608255728389243190339458012232695506428852144651898110162660452925977094286567211345780964206580114878499048251511101277583594927368709002547022104859538566555 1296324388292267165888665041605087973138865085735323940336095775334901803595776191731702830549146421796158391344315922904555522087583436972289117071176058201993909599373043934999364496068661855716339627441084772338727436541096757182462926435301286148 1699164746417511212186012800213018348467053355542153353195929432487708244761045970981000307124426808770807870460092428693862068862999812052102772396209962733738903800422969903544265402138756822589160623379012622741981716287011131982530852301669074200 1685209078005648428286679207587245346021455836721649764409942377439153473255893868234811035602893506536667411263971428415714212938081778302149197897905314991771943874383346223453335495732857585011711660684465259839688968859788272475175555522014332622 1305432130615346121528276417088104360849239137439854098860669656719810659159794091662534131857157158835739454272769257155027839647577248236313748106430922351730720218891127270540336861735514867905489645884752139288811506578651400610418608182150616615 799143072947739355113181482662368959267054226376989498806591084633535528916674816000924704657478097833241015498142381537221507142855529836318360410231536367450154296683750099986529617937242005733633775859769774212355650393938524670974949009118717308 383482347767596660841507336074483843228861767146017703234561642641463543792986692692895368844574213326176578045495638255041172224891050373964174286544117416450174036144631323279274062156644020808549697873801014125679303326237061880507961517467050086 138119800181254115446418221382028024086262074078666644719894553084640520769725903551501472727522184880977752472847833030737737886282832604395847222677654323488736915210566173410397763126869407769061706542791552739750119882981659204958175850363410446 31742079593649636713288034887222744268663630644963856808377495269770818847563983924850562272505545606898985582250538130085795175964487872878055530836949031098496258421683149087125465005362063231304886270792972170347741219482067319144320589960684069 156122260376456701996285572051906416883704771630328811275740776875653296936096471843696565437072071038856708641642637098356719451868678023160214521295091389453991159925188534259324025106107977357664212805388059117306373995258053096432992174203012 -3910577847274880899669532399329993787284675877394846219147052679682533350116319703683312536813432786865983799962921166884308384280447360146538155609876150623834945606890348696838841610287325212811319133506886234852688683338929013785581041917112072 -2152606346472648851502927374336849480313348945078261660558633906220563255759716311468258131396870005614716666203577322729404789046551706207206953429179788649317027224181451267840531134039484831867194164826649997461631107008729082418805624217537624 -730001658486819189986667580377446675083461573458082125392536831932558147041003174369829882173448601367386177483660920078177575940523548308691604894996542778474001195284924796451019561698574106062293010199587551555614805458605049815427542649346404 -176879825866204184300247797994970905513770611535650365911404501385167073583111601867609871568716068570151309267591276628900230195351331009405049146905597678500232855379044237061580984732531649674488695191502123385666637632967091157577931096695530 -50303447164215560095495113442948702195995959663031639423387758574657553611679197753499418145891060008770405446096087945071034035593574758129857461394475504244414396264431766632568322050348506212427174755083755133223785946287392663883377262507030 -107658505591070493932258403315355015897227212990617219020208140703714681564169996084605619142599008375521620993862333510230616652747728362210308313291047488258960638077820280003341385120163981602723986099738792542475089722620804853097401151101148 -271093927699168272270135900275527069849570633339382395735407548418755553840120103600803571405016766984194732864646941037178876767568007260053432220230782860589703420474471617646188733077078077537306865443145873817700823738254629026691448580037310 -456329272633697624935483955767792585202529959631315986193427005592850223622949400773388152639396094786490375211983237937105596690474656406734025024023166405904558899128107222991538796194620934514822023722388697561992962694792115542116543395057956 -558130438357411595605854790290523133205718686344910139526471458931660285943188747504110295146144144914150850680756847090137063142462134498057509785339637101083710822063047163318141175353309977726369328997665074432436033366018360288603460871778350 -526676750351410426278044848373919031625892464563213878434323320504411511551359794557718454521578707263083056806461174130055836987151380626276994650227704908387675063664764036386032277354108521638033772814368425121888371858577216445431694588289456 -397368550190669262397434791196341027969992904033120967246981080844388486945761012975019378417725355808097571059352637420289120399601708296040539799831594261910834531531543724529027119776168953450617861318763714222343329646438400348269485976180486 -244828041082428865272742305734776654289115131884929931702288077135720171371884202713011298360174236050441709696130304226592062477489202897436648274161798117222589113777510719862181963279561978180557209523952655679285527050285979155385030956640216 -124564670522844180581072196249824061493546750123748781069695572505046631233554163160831901086374963103455664700612623166665183526598236316194971838834828167958252130397580230959931358590252542448893030111150801787636820974677436483418563514250442 -52499833743200402272411404270482979498640576631520441464841689997260476507510258174528594194717352983785307112693958571253351982194763672172628887329273895974256966937242898995603874331417352748242858545346662062548127074018422611046742671212524 -18243860338112656752068457710445774226564925419497471738583401431832507138343784567498208393983707362526356569314566013066740667743157725892576253074995053566437498703193664250545131370924118039808275168803612841116455737255152676112132679720778 -5151729215411102176548554037279000227986782737918147987248772641300775262657055990761784888116016989247163223610786378598792301480688748840302980218184180275484475660807767593570364617176203559749526492492335907995278975834876691588717572406256 -1145254625348312893928847707021563163589399524686656902757631037227164395127009218662458888837947893057107997838211011930577103008036483726399074541199726576628177376337643723527636055982605765138525834154563868191630693396531773159800106097272 -185941541407729214948606454031626555711971709271274740253222218401978191433387445562945094826558339515603796277302927332416367668791425984602100090263848589113846482560657296542056492149012557550951880335977025760198767632498557083255195417854 -22513997643997952208148557891140886413031936494768383613852414868156977671371119314298659779694047424401416967471213238962241241466245147465123387571409790304744329645879998356056782986545072151251258525618920970224482173859261133347225997184 -28888147063449408924392718329262718989848793611832154203507541656727086950684618580133649360868968523083210037448553814133449216024838619294295526456081880170748948999422205566633032865528347592986419760367125685628465950972869512607821651500 -73454660207520351765660447245849864040334148137345793060096949624136368000876315935503986038911396945738418548091192561629406484097098756423168267103103518958405231577213701699877080512630253000294795545262861860985382557135826847857386671566 -115068665520595113847874680076174991527882932609246985585982796441913308914831116599174354392810337755227255819929977568129951827943998648914290875520464105313915121385954158107742401880537376534478265225146845045501895891401580129677633754896 -125864515442042366272380235764329308775228913050709131298515332539389796308942323326463783474084436343724902942892023040602301085223950413891339612286001868760898033490741160222414645486390558595265244154219213099572385848305635042564011776042 -102156951178611814726268310576209401379583649361879529394742522023377901119902118579498592925904353719162391676106794453565916748357982691006616308932925518534447226420849361401083772065264435898379307035470704727838590875439198737748610195330 -62650395630459131261578372594533734594864054619984560013578941407788541168436789450736738014569407347537790510081577228549802933852337212837288438734064011112697285085324555000393027876603479479666048992838979715906473525423466326566318919141 -28204910388880856968836416004913618631380195487825359331010133443764870812850064557574913272293748542119009039011119390396159294742378080275833982604268144352556053763098382316602075051170631571160692869609448625205861089967873078713274120880 -7885520696349083104351182547541413306910718322278162065239755166939664060776271236170709386954638337705533819217878925849786135965177278099986749434634324358390983710160640275222271083969585693563247426739617664428605259038414382395436348869 219690713088463271965198047534877858626454983529347046369094251043802689950630654806151146569507196951159842686688813305713168972602612957382019572040243838880051955534170915459971315498511135045568267501276222872251623364887532459720087104 1800426268081919519451655373173450249302088268437079650537184163269007327986497607571394862862729624129058073694511423620579105607029400286282233188350793328660818261529709676766743866001470814382723576315344500518933103796791888499608533156 1254080427008593696544371036859096725542312434981996195612288108668395683859204653671617634620046711921778190364229922185894384812097464658237439737803055117075793117965205683793250903893519627285595858363914519833602552727386190135603881728 566646735989103954694794758059257159653497506820161310076356285426766890219447294543981086195550153458396398158329223392902896846672149850116975799311688645120006991765370780505998796805734745530917887774229031321154699585387079389644918896 193003617276750399797090615959298802031165891628887250892078488290726839466777726752638021313526851475764660929637104953094317960699118263628169429629596900864703885639104802221111446880583097330393762776161188380852664661225416251106193528 51634027120266472639994706899064656870449730733902256467323928442276949782586880283028647185647891359629956864998589747985115412167441428987233279222677619414502562109578831103309659220606573557658237351794471523313861855948039643161282060 10964767077903264499550583175185199108473795647311895939955974616704884717787884581078512335963317764369910995613819628306756143620952892287204144800028242601661018475390099829929216236627978695592488925935695408235385566149138006965847932 3174408838065950493919766125452273710552945564620630278881012540096462136431846760661414363196941555566802725065636137785645309512940155052205059675337233622920510755539078740722772314623696746724123339606232931294873789157269550002950094 6408490149327235119813766489145160806174976820841450073582286275220078086393360483836376561208048260541818472321314514440258122384133109981803229845531517133651837815260384430602195371329676972636883627264863814994997727008512008008485924 13879285926910437051466987836537031101145045791920436491911074821662916493518845582453371460665652475177770007816765228392530711169254438240580515625810982268086473346085141554632772352100560642214679177143426207438308170092303258644626700 20174172219221145283063144204704068890797807537196962464093990701097787180902319203853788918364089865899136462488073273936626705231633043529783646003917035471459774922101013328680717311323801052713805446661496954363587310655103120632154236 21445597027085248585787541321402859735168911500319275881829339666317180308371382020208109781724369879778097182927236328422844370965084678113557099083778344843619162579053381499088746072062685815763188947738678898583517850105423696132174062 17771230760054551201926657179245159618546169417624910109599017311767255002885808240104208865861258951518701984360886753018127091011289584259909972773530057639422770475863673493486832405088926497478004118751551092212994645758623218285252238 11941466428559681934398023801467230878716874975076717221478079774083414010214802213357936525396905187466991789734038323232474578625511037995459166235900200979125130198886924528424331812134778254162173792119605818655663499021671220258268290 6662154787736779142252997725187124299684713484730643317305478804549135904857124862375695027428679525516349870267390945373626607453231322971927611064124872322183993657290095282112923352410396635750394576110092089375201143638034706130287120 3124554351329239114014332905508423488392282774946964045501251440018749581488100320552371054268448417379079436676883983019874588182885102098514016223857754078414765970494923317463395169824206525306462344725285447171147096393695049321334226 1237334384856836764469631499271430892605670551885057698198034315007265404889521865189790829696792406024917059074834950505444535273512682521596509026544459938276954998162450395139072338576410945478946652209978844893304796326918496975948144 413272494252292231915281098293652705893525152359517793552661670379749320613061687416491937397338796044139200436485421371761136843286815700894851299100069227080783320597588932133473924733272175973999481104573775622525404459346417652889872 115888496108761534773158697539775105744028462561646669630962032577975805305994352218437650801086189629622124563691154270625629319575270943957871971891562484759740288411822403121819991047528732932676398618152047074592371365819239214019408 27103121394422148347076880431996087276147458555567721474670729655580459671649613845729926105496854556840954854323717813308311754331484575915854218160182646730411006945896517488833299019295273709772156051795833510879915173192990490354628 5247926795161696129554743654509273444167258900377724434809247306520922301699163805428872799840008179846092111021071335811717184379278503124072719298994859020573019721764094103228736809831806985653232656494787878699806252249499109585170 1048501825369270938215766395135065005640416840142223118656694342948843220088555320977919912382993234485567606442047931058238333012224225371577069618949603163539588955671657246300803856162411540612692497002378148563708841132985706672283 1087904353579338130416372384668920889160442260795660160360194503333029395730197111812389479479638289242282260854051811675652605460409924606479639275681626238350940640736614647731879101674265452698093960254401584410687761410083222235476 2151110875007533267308435215693758286154164292384303901436737101436278566815783040027479219773988794400872000262380744155068677822000371555754696835544972016378525796928340934933237616416886590946305277333185212414008050885116797447446 2984864650240572667060468776875863847407254048467747324498599603584895091835007665992919411754094252882696934003590149885582289331601855955408646504609776664768403057588778015128989845103879398972533124758068709061425337864170184844496 3014632902113693396620108785005151261358468086088052171022091664574179077243046794866431198237445640344582167842474028711526460636204322515874445548849549293006540950525339840051072303363248067691019258271486864835966581042826943110912 2376295478718719078082441215276893670070840861837279130964138897428642461893801601355125146036392406901141216013044241603250929792125960270701863099293138605406802365807751041713141819681236757629385751023691734841943624162050663700042 1534055435549935898868407900338680485140055756452405935457896773443241395576843970956226354135932285858006778491546427565724182827170939916896809816203725950933082824449278394792006419940331957904706129499641631215765232672225224472117 835774894268893884773424754993028511544201586210971146749923884020707257488875686921442224615027811209017858531067369352520965475136206028406619208475285687523727976788568863414025043291378901074038461383192483855061142486384372551452 390034659122920822914756918211362088102889887704461436886425138646048729343372296113428729370437162624864993733915422050836134344492844652388125500581002741963115618488402544135052820710890530396258408463524570945343980689099570155168 156580309406072718851045682385553215274242766433246783658614825574788839177065292583175072944671501824950987590079723132704781962893005039760787234564454956220220513784485764436517312943830050060625262613804076434628191073141666223024 54060045328459163750737187252362742817211299996375575605905153427238295962652985418934317491543354800247694711409850327343503009318736713865606028420259636751968971151892959435311692685542679699237309447528596641019518759091886847224 16060914117570615722910553313083357884366373732995659527138518090346271060146032356300691373759249291370668286996540507345436965876604453821773057077581331218198985654915934988730668134202343195683824537163364855948838549801611689376 4124289025981544523375234433878269881494432091951156435499234541785533803082484195017422619013548007315012862989913331571528383632843331746158151359050103512271844942813657041625207662750886683800842264307480711209062663634593532768 922941241433584424580247347684681166849493611859759930132189598991634118417055971022565385269922322504438800506384804766185509476506196742276608743067634338058236760584911815248432699259627586238183909769253928350755517789564369352 181394247172563550641283743621895024847468288734849264096340969313951911171153030181372491019204120415161598347301190414857277082838311408993517559115588074961715729279856370412199024940566779427045624113644202546234551115356044164 31284846490082418496438856589638348973426513591443548025058854941815181608720767699297517620998978745017328702678108994623382620738763804560298032591353704885409141419328143688782403627207013634630966265381128144319150399950896306 -9242586549549568118091830934800691517881015636675106470906910055267534331548192302858258575579490212728739372765684519928125413464056874689498353875798336710735215700596173918218799138103369872992673063778020062107174617019042828 -50799517220610115481941337511763728771970537253992690555116202568486021939873576244214419584116481127632776981534276903487854224935361454082973800923261676868571833043282193616630189531468994614499641970725102356635672275830227920 -88704948661870640830718140846058163948425010557744240161756274858293433252187806900861853208365513096121429115536020579999816349317724967761415218838174626719576132237773345772949014981133206656624063718069946746206901391079800572 -94384361944153123626839587470570912212085128338187224499848655661237169068003018379565541761240916355908242690543914658158417581356644782215925974854303226767677535316139159332135496484525855151076545575700981620628226662965041692 -68202849630248929008527464441793383090726926294465652450451382442128886171074756707700544200943394506204744646411967599698074594903577920544352277241411519329505702009842647442843228916870961487043385230023894118406278539773163274 -34404297262431620587877226327369475274774614821893785035556192678404249366368741377534744768792259885828066993217123028346418588425975382103813969366365297731027317057312966854645477463476494560742171085395166809761969424710097428 -11371517587732822852678102104236170283715109492331777799623583034032330102911591797518084179145648469576415986750878702723792119468317458909958563371710240080571477947756488221436133707241417764330485601678146853769934545474998650 -1388047959501690335987085809575665131750589793416304382796116082937494970513549671444057699130154055135462838835231200036211211148625430220198851860478308584612336830936335435062498251785220651208915745571813574503442698247414976 1059242414869922278309673935003475797631846278572826295669523360740921389691298078228800958952813486749796939511789807386021731788032352190804994126205090232713946520795203926401298972516816972738044900156701410935799631455060864 917107719783159131811105155528715370377456044792203827173267927447438048979002847214099772217566759848427017191062657344707801573150180150471496518284692915804629699547903531869794177577382186458857275009452992714806337843121536 431294556965491218813172770751448676346566663222186344441016818452836753126128025634166344498436675365063811678835646313220969110832187484263622838471605344653481267506323577552821438351935711530533903272223951387486690403951936 148103632242504275406609378081931621089694540795007825630021392443690437422721705252332719925958608201954481478132947964984170500718189574700194437518777943851599718088436246966063378889063186754348931511354866641510010670547632 39606173988151712394308680202009902455957784349111411215080426016061960550255218886825926509941383401976874577201926499918977087351045761661474991507391018701686707957941575277631437063041189145406375306882132471040725603823040 8379619183007483477804491591593760302201712503377780320874156037977889123042845536102923281913412579992596150839635420907063263564022391177338262953342564081289184781777025488852544203729951907418829588213219944469139096557218 532729548623086596278362177616640218875922265014861289550411984074039254731182758089364803708264480467557628303565579474455048393187212119719445769055935733179853775335048911580603069132266109038551595174714332171836031208230 -3182814747000776766485891127491794350040473977476184958309053258007640496639111838044099253521021059434141591039431653546519406697698855779581174438368902159031320099193437257618837041948053641173515888027267196356217329944482 -5793617779097040136096886180311304016312768494066156619120537101683497861716296465776104693301159145027949498452965728901796449791415069920527530096145259664229661325986716453622969535994273833564896127299598765311018070437755 -5829153475411850869787717089170935096786707206216890121751442398801628615384459778672112143233522892911506152722976436692464556131473828836334002725364902352127837944472748252127928462661896527869350149224818395536473792935596 -3569568777727170354715118610198006836353227292693090967847427534837417491771532736687560143544848035855091196124466731435129443528298276561318041301299869626863174348742367868970798752173064950330012030700724016340015625643569 -1057981897369799490369970202214029640972176986922697469250268672486956607443829403007666542024608644399565591773456368414531774782318010565858541523323320462521473478313548593522767650241925158991391658384871113713862956258480 338076377003530301201272628924535253973275177009372614998655061436323778314464986843485310662450738232800551774689841399863238600893420583434597023070998730822492568888240369981009209236396906302012344797128330215203123255760 650169454764458223996722241100055946415805467204412513021709705688831336957936357988869344451405079821349532752939030909175414174638816353771184767497074005517333974059887802137787535854865843169957085540300611863825594384512 472506414954092493055714507343209588475470648745114304507410808922934897361409122825466575239992487584710864104578798596553542315642085475782122491058528596517053914740192619569613369412444496441158638852567302214449114937972 238308100771099339674410752438577018519094107147551503374086859901656921398603614364095365268505996354467700301260649254969539278853125854976486453388156922218579078435217472294071658930086234480336615111762866975352786596888 92664152566347361753444092140220335731281332471519932748722883648145223621497919924169038266325353560175194536461554469821906397192775110474985610542852006215926360544043420554823925507317195195871707826662192314075120639172 28664377897298074933604018325760110473000738759177668526585522338563367592305308962819059255477115109333026722535173639753862697607346459046046950970224699266328480536093135359648605570119107587003170920863008263826168145680 7108281337919396707694342171205403015120652307572477946398189012762823821710072478694059387860656653366106086005328010943190977511422429967060631883061544428395480250944495889678237189113770988337324465207603933229641677812 1410423297610935376850179858554580745133320638025775865619667122556757844494622540911140654167260094158387479274174024346328597644446067354514028107637125259938783794892722148044052528086931685266435764561648802672582715888 222746029569809882798848305098712498934665859806534773396022756883576237827401578941067086707080598936578021837818855863093585807901065165633606840562295500149283594483321961112568412309370606213389177536149200984098138912 27932319271662466777925306415548521865642314715392282893221064053890542357102919113370219555789106017074413258921453071605430068069916751307587220197501755248942269923966679015517931648329142196000659494207032208966549064 36791796976742095464775488149199089244400777681785229181448931086224382874322701821426177326439341320478369120384099376766942733662455676190690314072516159576549148465331212692333762707568030953083260574555893430532792292 121422296124514162755051992598022286634060618299276841086865033620085329778174514393404634574867981145359441359123822771939254189059012999682646202390694675319933465974471541561710978526828270356780320205821792975752901978 207781341617945268858664138786650848802749983927554735490822952219227041697558043279052150959187536148445311739754649428313119453596706277397313725296592669249674025713505350236058205843714107369796859488647323111534328750 229645127098325914081114334503674023034970621251347549712764202236423718597601063994457899188221256498897875667548493090472525832124311328383114006362221078053388455562651976468804760853015104246912005119744855011958997112 185239701524124775905352207457743539336092630190498933031728354992449371802040951370051642890866467298489752786499692018932955962406298227907078593017156837329222729571296421576323062245749917030550118993494067090006570182 116628871270723188876319215059578524670281896501449845138113326083689863287681591730736087258685948182517813953114741613976671780704986132571203375942631409611966064134618825059653920562229015185172732268037156806046688704 59438146165214350653518638394473652725192329606791635032318405015641415787748526447801436447636935577684586126197925158662658129201751716006736475199015515158094113329033111982214596371910881189372109417078801772401422116 24907143676263319591147728729166696666663856464678831313885455049085592763085759337229312655709071320172720799941048235351354092633270212353825218608247082864968608167626980956516708726108546662505480567717898531551501376 8606519162283977562852718974067080298721413726669765445169228611163776448756041234370894630598822322909223507704078169637164662122714276271757214214683594851488593958705674883113427693870375679874711748348976896317490132 2444922077089775672238447638391961024832623744907709329338524937126007750256039726530514047328238559655659451836989955037809966845362276398848037776272937387314141902853270150205178144062307593755366502680801891476326160 568672012647366565966741923133130242037220216731191168149007028374564140028201432952131459011016311788437705816832927066762107553216520964817435504214153126111028479051252646175419638371501003620755804175490120553693364 108083804314321037338182837825702872334425239628949015288285791076252906504117875064947637414905732095182143287142779263838481021919387128005850479967824923177381637747743680972284892712612598768360837280445498569902032 16874900609634198569704017533136804196373812695178967055627636443199650883855519628395200365533533179125719057262146390680592944260484600584187213985419621769524146173668403967432624405666066037672461775956419755329312 2220878138491931166036382392619648656625724018703416821041174741625919985237362824483603666274315699080441574020743888443124242305300249328742687867099708451530896451488055019297703287096699700592642817395162528841698 1333020857282167432815540721767858971123900459698236194872963333506271649249940939997349160844019037511950502936544883434640030234024316869586255755150499353867619975958756845421834993485668017548868006711914119913465 3750278122964751223679259958945773289374705502623403018686352408282767971442087319866372039248706463008994890776832402522793192439204577710418270731681473710630446108807298043864277903199707119925941003312778371891734 6117610417007140597673274125859462914917022261822143138053146062990401244874646646664988048651135165128065791318289806021158178004402376184020634860726178225414683518219699592754809839439328748210263370078870379835829 6496362004072715089077983489792925284078246256379978423637982133657586835095173037400351681064807004138641761422321643537346833489040424132670272151554457422569702805418709416186024694727041269692755042635783162262652 5155039515966374614636983688784590843902688410224081836840578306660197183589596367121275990467693620619808501115642626115462600275071558341341558305848549061967951340899674510148433896915061779361386991977847111440808 3300958870707358548137927384836850232565455757984859701790239083474117247236116527703278310190653993765437430994928517078705622247230071387885405247600844812574617657673166930148788833072806608342151889361191289587768 1751611344832452821922683515825085191504268481549212943681077295187060663758830961513580983152586245281458396382221476889407838529991943508661991856840914207775035486663296860591047176225999168105639631498428390797548 766333059147229630336138375421718573373285139598250901351457223903180941007027411370446014735266934157290328791187811228469928578432869617213487239036580272552882810567313463277092974866488407416892544461199201082312 273512829049338067246195830291860300361758979637409805524691872509115188145511518671406253476628177280004358509703222799289847154195753544093219943109857286084167123612712359229662188032598800041110691364478896617848 79801810076127854774500435461965993897647129210278537900355783662709353231180062448762778261262988343650451831076128314257120156634034305537580030199814940087759822187771435147713574362746773090639768640757133845752 19426054336838044998051210880274626389139041463537199664966180120491368237832427855974544609580523879665631922612810739105339476675739483605513169645952729817783840727127390257940588078053626358032157162235067997516 4069359202459326543215535438255826408341594190974185291706806286336977293330496168096432243948995792559939869063811050184681344930615393258536219922566803571853083204220310522630839945159356909292594760839469520216 750189032234880550615948840604053241266621764338214119739693329350287301741507365540141970960835524953047272310048864356584738501430009275805941572571867362729427917061394914322818473088664220069311251766974977136 122946463415664695931519246026786073208179418667813608847834783612613999368238315635472197396467471585245146183491285686625926209283673179287724587767035623641361475433992141559373043330120474620032288450127209504 18383589254135409833943989867581228595846892323131785973089541642393144807572151606026347242199853741470165350493568092976087506322189125526432109335816291936450470064037256839392095813977191696249465862380552728 2573579520828289509968568131622643079673271551626825357293539419154342146106783977493492541775026237441855887441728004859561785328171069014401102192527726640740757537278309386242588519831196057711610113396252246 -3502560678221053982117633678292588336108118788097957177464113247751236517609600482512009643212879605758903399965077524209836900410221314057805600791823418986716450594495535098368459711846187777459553021229699826 -5565337947907113269611845270584847296250206287672870499703884258356574077038512882234418043658540003586361781656630264829240082221603021961171020895177258505603981886651022954783546451018713330092013600172802548 1275693754174835689364042990166244158081520351202359801422161472548950451207123584173968068121728757427869519579766007937682258893800152328808642608576493978703582018136566535957709894460858835298287381952786898 9467736815560363965877966791622330384110674701909025553996016018643899099052424717494134729746325041656578835183829285069514459289662380644378590094557344107281751220769326997358364345873495054391720288419681264 10747663734020164912798290779442941882542787537034779391073672873369012303302960556101451580515411763658887052075934266708455165985842257610455637202421488753343624255827497215964952474591512763961905198355018840 6962797887646735210964704551449238649527444778411638285183938519229456478616706653517244345393291793542698469155219530639891989820021779064436415444069731258531178871765515113513088624237985930438492900651275240 3171627169035203871996137439749476261234680156556370948868479448769913536970778757514833499052801522002083201161296130991863813473863983153254105196060399453707720129403767168133664580281022073623497320392520764 1158613657157467464500058553299897990242837994056760826748314296036022677174571419424058407212837082108155664571023645532928248759538798671824968817620129667963664275068031205670112735464341648218633925039337760 374005671760586955181987217093255653517481007463623778515691615172857261509835998143973410282551982364613191003903346511552587860824895804654849776843736052999989368960125620407197590247188053204726443437305776 108632309122845481709769943204378642477664913553150372064074502065963892511525900807117606621882691859967953836986810083429145351464337804837090249780329302569810955258399302728834962020843779871504094467669848 27116562330127176856767037048304005701754941989199736067807673419151499959606808323269793649646523104786063144545412972612601557945527459823715915108372467994009442004613830164043109962139962641756050108607540 5666915254988381430146730318824629098117651224215208482862046654014547662184375015596223682584361744757151858078192176951312736656986916711323529334539473487163492820512096432131710734306711004920889577818208 1027648137311545465194193566460830989987252465324746459908903569668600025196047500287869999572606380689315600929687533163015087520918486942027764630458338114980633865426173948385712192420444450266035062079392 168993036448518920402720491986734174123081004409990774717881072927806398539444495365585532047961616054061160524678909316105676025475663703758857181840034392489517784841341695320162391198269596600289241546410 -56884534256379892087128021225148218637648992184705349358607281314003800178224719041021312457149085262910094249450409452708348929515823279453261793708504835504056155234870726144740137018576284776218743364768 -130558385581094081319661463172930039860527830342398616827675307242427241991279412611749374844629161130457944566504018870321872786861902007538336612608092746746307222393402119203246777461064738114301970919056 11556447819900143450801347005335310110108047346108151217304355408847026409236372281640754004447257252356955826231585153031715316445131777243318145228282065204129862866269644556898512744373648622623100206412 213844099943216371538411189322145607612036662830855350507025543792068897863405073345635688123726560685230675230185151699829351108607058432193915985331720601812878918623506729646494787837052349661943457034656 269541398057534585260089805677519049709420534595995100715609661061251781432515635767252992765563441070364261431924944786858140832833889072514427393943696232207843948928619212133375697205386112576879586408472 194181398848709682472896325959116012156052169765244476784609084046381416855799303366358437009981479965176913530185451518074399952936058727805116424104705471631273187087191299436160614579967097580185069078072 101256795702405778643873310795399295816078574219799072815869887971564427668926576935982833135061686607674054199086744251616015352724991802174100035968480441972128078429279145868671924539323944810764808974428 43242472733770548334345556550871780598835154272402949249589539672701643113664714419166982741771175733005961332507089415317843796059104461243007700524849035245459372342080866447342624665453377520231663572336 16007890567555646354177126840722780939288104391448127267673479170749223733130261248153129386892076328586473964027407594459954738588257513784550317763632207851057611198320444775525565999157195453290380749556 5085124422202387417065869154769709965097209793993037060932708530943101386693189140038196315148596837346174286279254386416508355080224182804009052173788836604860242441106925515140237164382495483944622263888 1338400381247938822060551560724368046775560616586027088962044679939774452434420880913793638246046560201254629295607362757506805465057620537092615536448519488305329502578833120913422698420787631896098453696 288479028648088543414096395464317893448092340015252420415796735882426231892552988023675232398253846264795235761494380305132792106332924286777305640318463724326741356105455566237386936522360337387034016288 52549529078531650736436144229097597487880808197518893227440822444120373694112708148966193466643369102386401198345052979823032103154025817059454331706750188794643447673828056184901506702016945509579579408 8565067501806661770592488473845625499516681632385653222716019363695445020011056461021826031826867306289857302483146133707718382291848313125514365312695219261464346178420201815023085157135666687552245984 1276588888819529893972473973303939180299880416913371614129058605474311125881490303504731875174914006030761304142542011773310220925289730062966584019527763588776996452139939696874616424471923847970753904 166226614375757635801191736554341995004026120780425249489335436691273515030044084022178284204397470273309806240033153224457735208626939699282950566647729417386028600062429931387623996382463047927941188 877490696259982034571685674474890003006928235582744756775584648620821255775233959664224065072828802777732844442172442361862864679500707101529767106411621467717538605585503753654278433600167462452548382 2409516655890273112053472609107385840393005243101524092610064068565507187943580502486999994545632852991216720386858323544911025157105959269933095790651846484591808998217897877409599765138313359577363840 3284960851397996278575318703603325210125880763334890156716683783503323525776954531146750163056440096808382526380364982655168096480335444908339111764047850003381083858197555722992443351020222307646305912 2935250078791421016584762960739511116890596219782189900926740133269898633684729941563838229689288016052297603161642788821358858740624668045675746028718597481028447846312966581454437328628616070496710736 1938231523477267150178986165961964902605557430549980885908589017851093329888976221188551451203424925682425376185536750946076943010069169418414116258952726229162289532261206817109284173731520802600792272 1002364337552550628539313311041405922281444429758914884754891257562954121630953575207751032925060050560826624622256231249146527814060933434643794292416521801656899168031976075387059324604964168075475920 417549876093207265764057939450822173710517858529707271165595332635617814307996305538532701549731979040327711179875656341472817796804582342256432487679034637650802597096222285210459587384070825268882444 142392958924828858223107384670384854362919690007437877527018101782927783243601030156806965410413544924635318349495338892890013489824683399366289951274184882852610669862343654428977619181682491555262496 40300390362986673935537644554467350956857029547152119255648142861106070066904524303897601568720563229254275979990197756318462231629080185215727175565292264689533048961051812201707412566356654188027372 9573672718809587413682674326671095504512117790413258768714832801764735998759039427118272133964336050010790588493531505922909404293400673786460150965515457422461903924845181300652764717332610976524688 1919698656507195982001712649732092725762636416674182079034348107653624686081027797740514505000387886279420542271019070007764189553342894759810264302807006806923549324207941979199285558022615370784736 327624830187066491636373178851063366768552728145591164302648953989039641362205757785333707854268710458598602179614274031643757705235175127286084005570364064953829183090378688811166821220187684968128 49523428351761254862983152685831151268923230318070422006672624265434923003147704122308704207190551405231651840398077921765308282347909958146884695350862377970336668663542466986585316924356940909548 7144869685590832246722204273981817591794803258974066502156007275991950025126511393780326577764884661077317992397876768082338201959543588861617221200544606950664788432771156867873413323559339221602 14364748811740361239314980241596526134505761383786060177430549638912797970121464222964784030212287547696203771431704234050573371107374774055587160202604984411153738797357849844576188803677512627107 38392169807670000597979386374199330515112567071680887165012223334282426069810457284163556235425843586307591910931436812497582522424770373423931074504439633185568494421564730787367059617334596162896 52314154443799534850576355602243602347740366238296894051298880180081220286208466832487185420468367782626815557301814472115333035344514208174300427789508759496172634845052160371561208190283470191848 46836373043872669691703732564288460649119904943220488799893543748333739431570508477059719584087773127459193227585975534193706563353440546380119094985897418399696910437237298785730571203944648925904 31579536410101280339726063220718986545136761985607963939646930431022084179323183189388551020469867035326124497140087582137855623253260987527851869792826220412880127279904269097724437772327081855744 17040123120741743033994392268564042599238752362891579820028790105573686918895187806193053147388214938245354396579866883860231162495108878178756219890823791557403731972017792673013656384429180521352 7454342466599653787644149975374664750530502360625015624817290010971870615796527454968404777238186684984146723478618500708970787220764832561422910299436704471061037199147732941364959409532753215892 2640807894567614287106312533496537236821029735381378506659826247552899976802321260186370851760913696805222003796439394097543104431116382520129785655650518484666086532940223935951374568575952913832 766950744278052672773954297536290725721448417273251147395703894528732409484882467996773761349447087739877551813616562397650474296830922784995256864003040426375335405505059889549103590654118959280 188285766894012350317942737226864241129653526993360154450925150211245843794709407354981271563153554071787710075590214455706557482329405274100521977838088878472705371721546956062322349798832598576 40084197240220715362207879143656948595897108331954890122031940245931980009741740511917642586785653802652351049030036048022505287717409493568899973282656054612843864788675476652815655810845882072 7378825072056999457174466656128770193706880542913755292552089965298378953712747146985482198053659320267732681462832440299153965480060171319178174299251161332858526802200091571129138544653046432 1191129901554523688969395654184454053906178050678095745597250675727338569783520560351034043446051481557475492747170311598650968695661907544244241975340430287500682711354796137045770609392590416 189644095397674064637632071101378965041151762366344208463058943700018687862233526026974432952274801248054188154804398157997879957120868601389128812020931885383966752462210424527522384552391584 32282481409565712959135696426093822085189097541307845265661545455662596473237897856585704565087047484796421500631741606754576649694003504200904319494027948752369406795278888502120136985813136 4801445729567871728361190040320741630367665965345675851143553318335106061749112070611025876498935328355466911444080110972290011423975199141720021337217001649332028414710425279366408460867554 38026468561985513441925704628337424369316607958714895827327257099213630961635835662121748908302503187550542197368243213179666492713568297853506851651266936279429835701153010841552643279788608 117292713263576699695239012306201280744482924923431038509066333313776454410977144409231023066589903329629223415779759290897280618057757545010761679168094802252406378955965088069795366117396016 161339545429249432055761822159074450990988298669707991849014033248485019554192687792305648200478865617689667039081533004983354630789334947164447820610280916914417728431314950067512167780261528 130244975928701578682862992753862625673227054497095448685038596672580271593308592899904029624724551752822951475276831373426582524276228741743174092672616942935228322466099092773925151390198736 69515242806790480562139786283164170806144025744742318963813402844671979182446495019115442563362415705461707168375103155829402350413589650698531719090435804112138791079912514178171422832910888 26659845813185489100425376730533261368459376711796064426865452773286168997706730535471402939782169044229443516028860271570017061468837062279031795612743517343502258286500303923524835979777480 8095991366330280639267003199353731014741380357053676246548300281480193892446181066023911958827405301819292116163675103950901747599913674698245540780861577749328525648488053761070395826573204 2174393118264609264500912453792077206341904781253791026670118390037693916004807719745760603707511863226176491120681412097592510009688399390485362664954222774526161404541799083571946266205888 533341207756156812135993984425773244639803061877186277500546228700239497323491408091212806240885413989915562164652547332241547252401255413097896882010299255450338621199527600760171002468448 109156315217661929831878052759955140580103060472582894069282217893963504484468562070560958001655211482619413241290088529274210605573297450777330338111979172074401588353921202877154207833120 17422382390734538015784892750584049173129979616985788625361386427473957888557152962984791432926647165337795272839167654080786167229910753605999853006690026776500470927739212995895633487504 2667066878740035496963306947961125866349857828495314059825673083285658378270077010465876884492815271479825355999362061478288192633942937755009829419156531574194045369960653116461845361792 564673122570866363053164516575211669435612181909035003370448464386067552432164298179320759675067063976734926670558885599082128561507209121486313219098144745317989508170912425712914780568 118631221149232050905818412150403602578043093545422860320548178706963541135190625074575162691437589858618860573301576714696039153229610842544966079733709208994296426289019813717995149946 250964049561059762343925866104710512048053789865870007303128409503894314171339397062901046901033916714623095465440457398630250454768496549898392528152000803430652021214257408416172450132 659916811434530978708364538545886770166684991300905081613298828307164659385703042591152210879795132805979785711247074184281668401871123199828674521844179665282205091099048130741438984182 883724674676208576997089305080446799482247040866474591654475442171370371856343228280436681765841939731281758252893593946785143208349984194931339959461523734946376990756628173591238824193 745459393841049392056745478071229917429653261983211676970139463821821243385718418049995847658776614925547925016633999415369809025600736573118831670306716768523972189614327962383141087308 434513780604977217944471106001214610167016691969912311675640270072146658248737652787640277489610061579205151868349698624873548638571024075655507205105560005229114873892790975362706978143 182009793803715848553030659306928730258514935285391807645584170725858105968741531257367843567971770456147150638167204117359272689839472001942386147768467054880166649237724805212799774570 57092189773741286246552412880990794332878607071152745127415864682200651480547592273668949357233858717948348843055736385252894850428011058311732688744448791321886097058781949107337028001 14925125812355620893303934785228136108236346680656200824578248111692576076582119586535391221452257337167490422239377281971376696700055450234181472350679726575665796560212306826506413624 3815805142544621202528633441488444962245716234806617069537880108631193991559117336502601658807232308052242522690776362785016387077884164006799012163358236162243498204463990770893880315 926196628546196869786255103980911808208285934191546326510502218304590922175551191386034674941900968075855726533258772662035717449178384894989618308562123231998193825602929512528351822 168063588515434371481386081647603762394189252312044333189705187930702810439179910276857062513443792273754213044054518633979392431940793066956816559279301546399626944721303714980967641 21567351066665783137712850020468796173946085150976570675139369258637097453243746593519941408166883084369023807150807392445993083743607760687919823601198829398503409885328399374234052 4496742142296705482898620332589482504291788865151086281128323746370519960519736934211356068232500226817331821447250165192854149920580539523496840071367671461866289228725417891456319 1525699598945236558597469397520470098116985910760387098194300529978259172151781489376901316868492289280041246177661503576219815262248159107442658662277597253367035343465465379203162 315903806975105921458825662660962377982771653458497844064976435742209478232974982825444839856782408615017526487477262699476066032244231508510944576027561828269483131854256162584445 32357436617737337645142953060680609700106172500336467269315435829584785259098117264679174656487086930224361809466263188959443130605358737093734817205478747847923058656972139392752 708362987225811133771699010488795744059519155767820582300815700546963558269215643916192976618317331336088901191550565174501564506062993450547973481277813943293647871795271964165881 1546764378525283904810234545120262886395360526584548458999239932454436913585213099741940031426211306351727768217997755403487406216450149203739102422654880332842502456038909644409916 1440132862611791568398498763777238180251640872838469322228793338302689924688753764501480788857578757611525800955062591816143391901329835565154666859667431216090318281554051143442177 725213963867116218379522863344254280666955177227853617576939668361644225295430008024322072932604796902589098196294990437511027324467486721226366717118605751842008880273814377549664 211379641216292409252638927128102285592111978441334109818812134133244665339269690137898792332116903098596347794352812334682972366446961849114709055276648814594704655248265439229897 42800164934669304748952443764033110769623709305114578844707456204245443268867091552886393736831506938892923743458440841305032161839869079666771518676672061735673739961239665592364 13043793683563950582904930668263163226103784914514323798378238203365900120613412209128735228928096119941352790460517010527269744570981895281201013991432550151449806705497578841277 5309734119430329980628306283234537881367073619954268750237026699400601397513299105428978937735085013332032341105323074185676977299893722844445512506363061140789164041382853022288 1225312882679099361573753993721745189401309672152052176629738260333141855089877297274899562825179736935547267736778468235969873773001510977507004385714756901516587108459234312585 84760649094565127000967728435649985469139750348876980867834494191566505747978709195256801978743270864061294611847062965864953923764188734919916775600241324417524717390233225068 -2011267045547551241092353332343106501431923497633372754367586385765123534790061567485715131301538293356259567196239146479722579833658841161939271661919489485066768022208781031 8135532421445118517920963824263172501799446470951711620622613745982730145081757224036498854261287053114306230170071673113782370456239016129545818231977970720836765851376160432 3398899276714851743354841859221283374486940878216814779927402610048512124849977350413550954876232451888209350602678970228962287758962993061320793614045902137713777208057177757 521821949738616197974898118964752054202088741014869363070098070206747913744719457255378277148742945399823132240837387259154830775971758864709626603598109284402081265576597230 1749405403626715527522909667597779373820939753642618335405713854939437043014940908350330177006870447128223406441346202397549466871871298397064514903271048296171337562034729946 3616102308501871590007999482629045086084970242992366433342818456081905383835685449324014859851733559570805001315163114097864265638065352335842367640982994903963885088222061486 3523444246523037599606783475103552904277137766504736234666027102284098091215200160528646957256193618988662205471393377400634620845097704489394421226602248346500313614292608687 2014852185441871002076487868430726304001305759355639676683002978011403980448775997985912264923913079445584855929094797104248400864327116456058940667425273808119866401884147022 671222814504678592532807951865050694295472401144010947936462679450304363394944921907295863586844759909496606401805700750303025653668581922463094705946971195277928232662505276 103684350285238013724546139579771964669749975291963529862797203180451107359827260293809739870015766574227389345515856541829270641209070408315081892104415063409241688367500130 7062698740087603931553795574828009579550514378911724608195464535545101337625449584962978541593206711044373248308698232223712884912847209146356370310648576289890616402582357 10341924699459324204332078783084937903523689322145884299788276795949824594710018013610509083627852376903173226243953778386499761390912776190667431916850571522951767857371346 5802891826664694829976333351787601926043821021852533248686963177756213214363395540240752165907930114465388369421355361815497562051140175084506383885987129251383484645767646 789314591934746203928197942201874198719982669570068286369636800873173835463196180905798646543256079087236153315277342866005809283712333385936093207170652784161136260575862 -158180833477704098311959923950437322007991580462852145871536262988584243424062115475836463296978417053491090207757410635745426206230832675634212953199801479694483702398077 -23814880374632734765170578172625688857582411842992399717848621325667011225845707539964835336235474126054499674532228725451996903880815333930936016580606753710708294331354 15267117742868694360660739247859538050093624985985189638675427547675204867444834104122430827352773582023576803819706410869244175559304071880570155685465505723928829317856 4634750116070342140940116040393789949370206450525901422172206662794814208750256607786267777307979941215253840014985094767343041889297558602156462596774989757853913291986 451860753917668878781843160008779192754215347557505178557648314231819827242696977758979287411690803778294853505671144577261511060062577131480848447081732572347193250421 13440025566963711206528370951380749429244670900566831857938455502809592510895325141445100959772319285446391776166874076742208531330431602420483394933483970818791227520 1761156212279018404249255205436694417404361633913805114563542564187062225976538560275593255369738489891140255819386842831178032266319337451389636024198703287361473749228 2744357180458562942591468405372533180467176933854599849622355185606367460391008356087973002551592050389645004941917374664900787398023177172747736112659174954342297740862 1453591710062718670207689419738651018979715538884758763928153467445280021615865100843803783798113680717193217848417522835746408016426593989912396569271731994205964066145 134945915826022373879058836401423543347381576819899132115215282219767573456350669067474224639521000938423984180909403570095130147118805755259384121654180313366601019588 -127294735717112468373215815782415269123969355058756528459857127417509388343432713702822280529601259933449578768217089795090609684247552517028498350708112268105325553918 -17913368984592752717239506633147949217525613285241228825038314965885180944167297146738139621579404402412426070958885207167205549084503882280730488271696334154779820974 17224146141059186685070755708479818388323987487223178190272125590861304188286236632750874003350565456701698828221287964271280285592222899173689796597142798339469781355 5238104631384681615061015888451546269606208948438211129842553993372612301331608209288505944564043065593013462251893098376355317891440800503114134599822757512819422056 -382584162181839317272805109579451687152376594286192403479202861731410856639482887525401899337256665072500886135960604389385127066756304685074297871317153435162429320 -299781997187343159988431217561136341354294116454066374264852919615678136496369122519481415893287054297040114745896306075332301808745761346527517004479600818594171994 4004763439968392281633835733758085085207856684575278417577734747808077667772148677483552641346386313323893129867723526873396168896319114742206510396472030040201605 17227041944312136053626017911422672201176340776018671657767074154320564236961204215032935607879570287034615903762516384360833628112430208062559049946763428266512988 3042709006567994156284948918390282849228889446982254784518354822691217507731380462073303967676174903943075544983702671927905044226558082372836708553185333470261798 202427379900672397170519237462655768140655663887066764039876352862845694120323058785465514464526390003966321669774760386698637723716112249584547757814701973442348 1958035662905688851416639444532621026482620677047120380484049681417166054746004489048420401076196907657081696967177235017371047183818312574178460829534755424479913 2695083145178118605558960839970839685572152695956080226636960585250807770936383059779616182980261025065947189430094939733812792697452121267647642736542804475584420 1441005546558144624216195684619019032816744353331821036836940161759074361313514516244306373919514601826488085466206386863352450241992478929664020882293267271739112 336961197881255710502320353357874674259594611179442231113493338768873023213227042241433087417288659104687563049250526209993800626767715518449267825285426698024824 12133544343212633570626571066221566688525264520881486182683928671711959895346118035807531573907893769154764940235750780442634407434309298885973490974333316880014 -382592682688303606999259970745757638966776082957605995799316272901050745528915266008573989620626804802710056763056454995130142803645333245304847611002947287366 11435360844746982811387195148697298072456515634584608657575339712439649267565138120356535015168577446342883226913098780835929257893192021021172078708956549786197 6349886090152171019431284851488901105368749651138638640152279564915324290865454730411693614396484047253943998468084473633687087074810907350656866448369065012964 768465414142960103065856012844800413137149798021793018605869097210857680759730723016542871863396696062624340482178534797473366968985953500184247300368495423175 -356999704033515678536614686608193875099280463445971139553739384155392988507578498934475410479473329013801841114084647092442834734525313373877125072684246187840 -101688153752805106220840746850695823042532017331926292373352315007355017955278606497139765147282545424988460757581044757848943430746111193443867787036457350586 10986206704463824315677186049418394513775845333250063287288700056590458715318894583851965647251998341548255228072068631748463764499119105173197357988236958968 8003281557836260865716255368953157440742046098524363478606253022966849495423837154445715225053495609094904103057561888770732776573752378185269571166228853596 1221174769087048141915421222381615788809520447911183151940724382903710600946650535357355915036357780785306354574551204545640357996632159906815998152177535278 65878998635799424953892314978459496335433059118108538168666066184804151756217302376352625809941993993754512064704615633410054229340558392519311624463222895 151177287408016039382264507181646433048070862850167334923467392848708473331272689653113420058775523980508752043317004353968638457875480411281574889473712 1312508408873379231174787553640263147791210684285774289669059528465162489137837662351799243990413957344567489192168629687105859832610415414205056187944836597 1855556423224289450247306668153352402664418641825032049972579654922613238300593450030895731719752926251894085803312999517253561051034639820810185929710697288 933275663120791599986683097839801177155604649077382201781707633800638976584026447831572619320943957825712491418929357832027464999036358018961520257753531314 136493507601801339304866898134762414448765320058014226037799839595567089900103764337113064206882069750422637405487576789350553341193920622340016099917590684 -31799363439443406471513880171161446616156430362580190008032234889275626457941128795083584265974178834916438871433008942596504316400963212864300596009533228 -3250348722880355784290177170326714986354978539251354100364123379283178156831992818849654678725667579299340417871599271056985442446477457052896335596922400 5445753801057967770562257445748141531380739795975168276218839459255003827079454687687606782669262378997719852359988173237701324737555500117386239970823483 1292390525414579087829007569237760912525708054479053387362435815655412732626792654458769842983113078821637538174967287147311084887798958273487642335293656 -134133081589450412329514196524445258111159749798667347748035945949330361380980252931381543709145083686626229978313167119844407560815473739334303077728953 -62490775020743962980338144148173481390798606524984226493451379919696711024777250186834386805458296065983758804473176052049352621999377018433641861530904 3748782085502347665865169740097194937277203381628120654465530012357585404281219649883054789797174301356791329569596289504121850482602699108766174391736 3195973328108770343958349704922317882214363101958866031690892811485637098280253099334332432823530032185928679713913102675158985653375477131228972320884 354762204700397845556841760790534815240218359150069148776646080553636350924161584188209168225322833982774517548168185801915311485609970214670173224810 6032011760496694365129616511494961590022236923453860282666527007681701171925514159363684219314910899582677984257568606348412003201064649135257321794 1206824959863722299343011525142117623911760645674921123896988055409903928856528564232618890737526994482232944553243769261546338740992032218049342323092 2070287735105879746787451070459983322776513700407093528163316590703206163872836683625208044940856504956517944176570092135805093343066036013158436356884 1530875523049304158341743583496196221949189210611740292113459373542749660147557181298648558695254051122847931696515243169552953647522953527540043529698 548478028609516713517889841674902017213271120412886187126125868848375237449794580132012847475970290655999008044810369289768311468972135868503572984220 49470375297494103015270333654965353542527565607711170934426268660697959383945126433643373935753206909212433556343390213914069588662675671139084599920 -22460612582446833169065085343772939764322855620353682504223201755542907454212090755864836227300336299280794562512410958166280912618111134814688913482 -648797412604425703311961709468121558100323415131482054711974860545801238527234125518775013196898067583590713628247089175367678096658218575123196529 3232852482859947401066564983430849792152872183787438408132858741300956594379022320177465546689517040012358031759233020549381767109143934517478584066 567003263804414999394281003154817567492147029560316751504313969867537284593525459775327567945118926360356848975831368727536642275954764514231583488 -78772106703291463571887216193213557078147941724270225711486567639116407951316542772579327379000429158453892858584261817151088621948049409181374872 -9545167314591826767829260450384956473324293315930077072761342745876854830258975222104965939890976866901507089114028494527363519252783403100173412 6545085508031950002432452458528374012783639369841398806352062613509312329460944767782973088564467486001843469022525471613856823822041272531451608 1135916663376803755939168715984280571897811425096551384341219317663692904053813376968766377864816252555817116485796454613688249163757337093134044 15218954405932741922967840386761933884012316354031825353369715716625648103499511099268469556579982530563282377992330249297112705898509633997378 -2604240293606032607029678941523694145801134547960598278182804794471195510320796839149013723549880222664094679431127149007448854706030564378595 -7254165728259053686565497211441851590260767830696911307064964550880238495987881199643641446418896024828565256831527548992966613426763877888 8996709133882530062514841122180161981461261145960640063917213784024669739489920009811532265091696632780457234015981181405047616957102176828088 -78381798607757477660426282757721502992681099664359199359288465993448522827479284898250989248904337015534945350726113384780297470035151194351244 -98818674069799964842646705942407482769528901833880841145665884056135913625768004224176335752813747786725368411132641838049328035748134791550006 -30916640786044884817117086413938404847414529026221591661522541294543355017134135304428856604991824440276095035560408523824872286347731613492196 6487650223099484638763469229477945340017781208308536949653695194153464425262191201813372815313455153410031917655351595166496913861419208911142 4157099878064659739957704184019101570190154043140870037078551507989788069716915022748168138147430740784300387781681736790675447669673966977770 -403563248987134542828117440200363112030297022676095154543271292948926680328805857708615862615699518559703168453811889521556038879978059077187 -354212970813811288258197647039000224974953715397360213816700250901481545227389395854311562253575815413724767434348779990405971497169198865024 32737411731703757079897679753640810222165414223545996424651889290078567736904706666548060159712750771139889993665815488420035494180465632280 30896245020852680877686463840074640644301986551618723542209115118298550063299751323469767291575035429644005596850591850725363970043789457088 3428949806287095100441481004674489181882061373350018138669775040250107565024375286896507845351507335755990167162688734539128596609558053848 -65417498652851957450146886064442683840680842862344675141620023292576246123849411629580689900943337357832971507892008089656505437806282164 -11978818933201521814850630819251045733937550982008484606093806534152399305568483745417954031938920963083736381182677466935247149959797962 -360587252158063286584118966182805557756752302432676350076369276061428941749443577505730818800618656223414047041405333214013786539176408 -605517362778102813009758221842494760544110568050757525297077838990499880676479175277831880710759456863304031095479837505260850063536561833 -1007308125384044060183533010410128254906722943453244571970462879463908648042153583325323904903066886143109632957345115763914904188180246406 -537694067766424027145698164968522767775840412991634597181428661030646464883175961335539604062248397619147142107841299359752357273072652005 -14311012479145658163889245044350870471229685603795792701756980488724143109547503581180692590303065161675053669432202132991994029251916780 78034171638088143818153442943424700235257247811902680299222005476178756841581727805726014077934504885849772673951766131637419241052016685 14744184260285453340928476227647217062683900619085037449790378555224280671177336056820018443162244786552261156535529683537080419063276200 -6364381882403692622662849401664469873384628403651676780550894023858022650789759343454868641022940633991102551573419768284985819271342336 -2098720140842233980384544792108512920643779226988875297366802194888706615298119481080960681373818366921281424353388719951332985216283152 126281019516180527830002689878625232141067699862066272685948983086694152400711505133186427710399595954946590896262642062829467823440430 96054000675186326348316482820970879731997617577701379129933556781842305059914347009654707195725559791542576490485548635234944813761860 5234560305121449939704022347633274048857472112493411271303455122017700027580411128539758805556710365549211927706710936029039380406766 -496301229317908459066131224376640548943333342966278651699835696572568950615630218617170390174590310640163413049556757746013567575200 20207517185171391334469953585309139331436680320661037364612488032235668817521377344784877672456404830451186995823770969572707288034 -1675275623863135333935667572032088091971882491696258439501355448682038646740487633211779339080970252313822555036358992526125054462 16166014456738179399357973807714060482661220751237645634254492258815064593641006605671296595517660144505081818444250740707699545 154060523955556959105437025014221974361256478281716220423625327602777337878241081872707076700591776702343228238312631442366992 27095570611430341936167122860852884062434668373193778548007707116142177435108409531373095455651292895389537133102040609073016364203 53066525309875583798875862518296834910513927037557435995834154366389884172147735806031671331246871356875577938746937380039424232664 26759451324009937979236401371308413307149169370650324738256367998362644128176083536086754221598531599985754116194386715280930496185 -2485926532825653735020278095284633751171735796734941779215072120164534899314721589700802531188535255620336239815070003928237975300 -4304345322867207486820632403244793084688400380312285827064835785353155615365286142146289633554648894434902547301532486100464207597 -163624593340983497647962591374433101920185638111703104803766017865187569856714976918736393544977107113783508879595755363646117244 285763188135354212221279672409554004107576688916013773187474825032703721781626077859814765481393270602853833958702937961559904880 -6966159709615945843001341461879960868094200482452601156061827864003855701669347997206481817766956231836506762715220169084789360 -16636404116152589605997453235750210925227942425761910596729630256795653135393049584925331909678959558814373145234888113633652260 3163373130403758688895799633839996227547527100712814559216266102979964444231972339824896856120430291811036749417062185325876 275183003945323540956082875320825804704129067153478563302566847676802501081124951238487093537656433361295443141355463555474624 -13437615812682268961504698770237772634165559295055774067163043742350719984785602227802143802515183585330818944736597856303396 89804533956763777640937858038538708376892649697719182760164309933917047071648943159000508500939485413123840754714125175270 2421257149906704189044806133909814446257839183624588255752880274941840990180532444727747811373126465151898449584201622522 95458001843399760717193001423294058353537159319574835426284792949576724815065524151045839087615455571538731419150114311216222 102519155230771660171140282649898115103670530675212927027878202569366310984970785320229854572497634746331379005808570488236050 13059862619901836941491668871029841871616250933199349268357697550986522549787241882630101811517106249070791602197041343599733 -18141938649561756043090165406618728576692551764162032803177172373417573809234657107051945212590863434129242835313325384420050 -3023967761374039557745665095256576064333743445221736408421571223720979761499236428205488673158546236543818854287395449825180 2741366140946085750322017413325380121188213292183991106128726993715122126200035040441431829272993467009634748077491634850780 657426137754421391242624622844798146017266054770683483285868551874697447837284663361612354127849996123594002428300127179806 -136744653022113228734173734180113402449802966006335908277636195577415597716161562895261770628337376883804836376368043177984 -38964260161544030300201909903395448417758913267241058236137653568204445064070145964824983394098535979296118355782623949868 2338220634927740315351968693492642665432482139687867895770099690329975746638140626646582829597566464146185866458770770340 458792574467316732350702613478886132970882672349527708373562311141840772711626290632270543274819535140711259357371975918 -64976705116136357235114169836762176338927325066885221038709061482615230136407438242114907921526420427728564485914339320 1020074009458283703376698314380056603457512784802030654174261205165959960313024695928477785283346682241183801098754796 10619032219823768691343481051522322333879159417207669720279298971528747888380400395575238077361721144109505087673438 249713295163724681226242582508644116392459919359392655011540114588388784745339439997637440540411196166403362540675 -167336490352114741588771908840149556318596146604944780997863501226031130079004600794943690257313666117934891136 -6786241001382473102125164939182645820278040796319827618232588923510913855822472965495551208586277800367650538385880272 -8326779715881576865862062553123748932085168854318895675111894413848548490732342128540515018085328058061285399513133178 -3070640361275016870765232554725273743885507783649640177323267509979112288999307945037067150576478479690144950800864839 -143733285100273330014404472868567357063784482635130738320195088754066421689540072690981190761396694258747736997500680 83873089799928659999952891126829282370227102874459121639942451742081381090104149581526738330385263693953756571353044 17597256914030244270654879343704818568852456898634845675913828349085946107798127395577539191728769270758586083922504 14217697803657412484824098955564988532750666043710078235593352993403524765712053233835469343664263582412749536722176 3067606008882908000360279484981296092282248696730646361236568100489288806695298512339575359671978310232113539967504 -435038996644145887396712481525381506342015668184618591450484941961216200666091302690213936191320116735415758216132 -103029236762989518160263540395596682357155258905068213448552415647499400116941856381155261828838686601891914088512 3599523833525170617944961299522569151626703407369728594262955147703016374349781421550135595628963878229587298568 -21803885545807148176850407287780384371079077123109571068811805607956753535602359973752435315405302006310076188 1025607292681415446371597567022685336768602631545823688488099287652008287937171381961239351036908449541613802 -87851581754523317005092851569237189302060496302437404144822918943884680236960155795257214436627029502628 -1483430384183960839896078637183475629099705519913450445370585529456530794810616028729637710301420615439973386115 -172346977742078665657979573314798416056381085492715594006990779783783906727820882013893982215829374556570455320 1884124429419180372709321152140677006429527015970891428490014445399815610437605710350620556912685578668232191630 1318357761124814014213920199604141077942580387421296337036098780811336291523838785745372671420847020550494267360 134330571042326678801887339422440093242401418949556615909485102931930588106566098878160061456074614501799749860 -136553492892134731650898554348145008338471620408299895023325310953754338613498585119152249027266894422243724148 -40381339770100406138266086083733908097032118693368040177869068248511664574658278766663938207882592964514339442 1505317669889502869737973664021062658935564764334313580966676099519018025343395901232474960558912543190531856 1814847662783105934703514967034931978399421323893184072933250876932904674905745656873808822290739693121648190 183404436070958131833932344589031641344840007415416146866660076921824915859249299029529644867110657067611400 -925826163638081151020562994244880300198096464747379257693444684332538657823420177810979439249572705684532 -181713836937435567699445427925302497435549543511995055879723658752598679516754525766117396913494651334872 5983131589917054817149396392281104067728198616151592967740008306705028119361792006326699391940595156492 -16825577476277583466758981720420350442492825207756947484072749328448950727965079477448298947943227502 30048866262776886988145935650351246738606625678941446278007534365690015525213124947024643580409265 401608644065772914331743880447485297254909008542170345693022272986102250105915557380266814160 -449702749568627222602147359716020235694744204589270576994592002630473779418412843335137983111146479292101 -532176965597945808329681963846779877779605911513880849140934119319032991601477215079825831162433696483160 -165854151098412240520447095539530590168938451378570363488283224946331136791742156256095337083946446070880 34760179676027726867848028863572167725548721914241785592150212085834273768062222669362310344060498278840 28822012814622509723945653932266106482137402794873579076217120042871889462984451455149739014628293902916 3293669076006758917349921973480272866238026198998330041963464001703629319197103837174052931641274960356 -1029666733665014648530258373761017477083754850801038498835700429668003085189803658326876249671765799024 -291994875033839600214651463054898074285085148346890149516762685227831698910772435313373523083375102336 -21487026826690776515866227399289695052576458722515908385055008077234981036387245925055411428260761480 -59298424581811203787583649903832314951457350235860374923067235773297980335162852005439918065836792 33005933047858321149790386404658033122541966584302824212315539570630671329606892201861430332542696 -392142877601045608065978882803860680152575733980789166752262221782220652774053185392617786467796 -813472624087012320393898895062449454022106175338098341982432472359255454301611182248898047018 -28585529390561984472245310325252446363118520437892277282952608316306517624265189467628170 141051708879804664688447290557419274096623488690738618434893005562048207036235177489825845784279080 171022953451477693390188619933421198977148852269737415805575544155901629311733867392492876360748440 86198048845561701315792902664095387828608658649048294790248736673802536231121373024891746692332260 13904075296292198828133080070373775580248030449617662228289639724770207570674101733520956837326320 -8552415825920192832346025897314401018164534477404884123015722427840726305707630055273660287132800 -4483224048531226910880189131557068021440702613422437599097061997021539431195940001084059853802140 -213882929437845942777822634338839366092538424418886025385064986538193375457921457104333268288830 229338959015080991604517058009070558913869253915332296334927946005047131648656993067371023978560 36157167412858880206908497814538432422063288641350029322640947638736234566817514911851863320520 490162533434350854535990776446577981128216677601596011136745429535754025268819837772499453000 69324156856516686163493890254102617728132238262778473862726435643870248734131461544245704140 -1219004994717733587442486597475135777940359208622768254616214486279388129930176219365596952 6625091728533181749451172242925915856547460030804135502747864971448197344345492463627636 -1324806722211246900531412626442801728328281105177143005937411733049324817626455085794 74415663475238332585054033538451082007648375817540531316976535133209156483411 0 -22489499176535211836818480780478804999745569452048211944121884410753258438606559189065403800 -17461766737022044397325385104941239210244374493416551464530967969789938159010699576385187440 -857479063049769176464452955503524287429108698171629921958462188565419247704915395520971920 2349444978708188788472397836012167657222459937067718076325501880555938651048591780742900520 514222902068956694626267030136956220176984663163998734593378268866478368446795909177083372 -61027961229094919246860132775300618500077443559853954628257724245741215338168924411631984 -27256328933016974041174282806562205943632648540347832421519831259868672465975488560440768 -2428555207945561050769781292130247596751529687372260683592131926147021438731370871692096 -96746323979373541545110459231876567584562431771163868321940848513805813800252143826760 1638229576198177998082971568789354724258944813495249550115580249551694199610178294592 32547626580445643910937112076306240509936084401027120157302886274474092349009440744 50226361970223094649125309293130811136774970408653768564759179983826664020385300 2679622155854273179705512737060218030479527374198695617420924177158464490 0 6428012853171615560544008106466695301268242145670952205428227289198970444915577261935 4411320030494898576530496899338234073690044856751358466531410979125093716799842263910 268914031063460255301796763555466217210128180130244803096870144728509183267770416825 -581826942260749642987839002267091268463259987984596125074526928473824509589547772100 -194368478539879429907024476810466654172365847476070809370793049901686072787170203425 4316860258036334003130738039143091437607288030558402049953467812195656311793440382 12405521914096142797835676730744603505214212060592267627691782805044553373868122163 1591467211291607894488783308079129630913874923264620524037362501948898828595245896 19960065535590963441992571491196220264664183182116390179271221498174557545492545 8407158391858157429949238123097626359691571305008958114762510612751337437523410 -27140914300106124895281024568088084593077357883525146022263401425186380986089 -268856629295020526105021936369286130951927169227129439334816437264222847692 77449903534790085273366233381308138068551730278702155589876503889961 0 0 0 -226370705736740802502968716498881842850794657632075058235665757017925438710630 -31198849475586121119545598722551940003384048830203423507162602139503333003010 51313388206833528165688973872343315700775486441476589225876203481651173022220 3253511918109849726105790383573739745742284353807095370304795726232255033820 -4568194907856225822518892842678425044687903393222764428287279189716063617398 -36067973144828517377015876188182000916384167822938106974038609198598398658 114350252620525255824372775142674795796476903985275515765915093363089422600 -16731523139602200718709451695684531671820196647802180873459479901529838920 -276815229806619574360321848817544927323292782726493733767197180065716130 -1322171283547827177503414736411418812420214123676233713794334018896230 1766047475357779817492233734171259616522481456362864572485045220 0 0 0 19796130053237924681175159442197653648186813699389916909006744394542250 2574252467230055629740685475828226326096630225434143035123939262406830 5540968987644231510301045813567584646295593437880895709955657470944805 6682885371785994280369149278124587113354570735645359877672496370459480 788287066483634356193260593685511276547041505623856409910600830716000 -567905096409097929725537580105272915720078884660770033584563804405446 -95372031415277999828365999177146629631394038647865840713675163353275 9488631057750684638685359936898413731169012207997050635113031367840 718666710786223580322343662167964757287198582560955464275847933290 3317629920610874898015497837273827461962606225512724712544351810 30939659089289039066836826247042088143756238102196304409431 0 0 0 0 0 -2783916181163540685897344463417034081178645112149603264838475950 -1705036341910350950053578597265478645188412503383604993284734280 -43302460456231421784220453078583717912874425901979844349038440 143846760327941989019463052363056133975039984139172173340533940 39626589847808705554255424200692608446704800790492157771240590 1295251206991914963240603282044767195034955965544996953726180 -1092746714975165972524767913061424522595187417219310046703840 18784932795752175814329973157123118974850986198360048142360 399812760062956724169609567747483564730134415815036750 0 0 0 0 0 -156372289045266572399665209883482037331486737115067159795 -138665697606956267020657684686861521558092001334326832180 117512601030966347312243466326318223625189299984513384690 66362351238553984951575986078159424979776453653621184480 -16423115711459104154412000655710768634514036589808742790 -4580783735724097879225971434129816731556527070573596070 1135838381070569123175550992776551242356050640311900649 -41260772542508407314776209899538864541609601460892264 3570170416736984647739463054965532779894135508733 0 0 0 0 0 0 0 -48078693840041973715178247739685034636660387238860 -19783811895817430499640519582282970188449810023580 9020275729255310491378426295016008910319159329600 1922556064023789165960563837226701739059723294340 -689006220856838509098623766066629994556835095746 33955094302962980382464810507967779588018053990 19684992709686969389955825219517511558991960 0 0 0 0 0 0 0 7760633467518073204173439144815633041985500 2615948937550637552524360600577935272824940 -2180457704611898670272136593357178013109790 -84535388346538615389090693551269959111800 257015756549190883126708747864710403416480 -14159703231754535770305878365286610689874 53872741221701736939348428735333863279 0 0 0 0 0 0 0 0 0 149233974624585891245390048944631700 -12518392125787507085471741339590440 -27074094761109301093747275925791800 36268557495711824862235235996620 44085266345522855891786025774250 0 0 0 0 0 0 0 0 0 -1904783911339910725348884045 468125484342567746855238810 1832361602891640926702481735 548207014703994619729989740 -53939125565290359002535155 0 0 0 0 0 0 0 0 0 0 0 -1178225422126551858330 -397287893573915444070 63978277681332391900 0 0 0 0 0 0 0 0 0 0 0 32212254750 16106127330 -4484108451405 0 0 0 0 0 0 0 0 0 0 0 0 0 491550 0 0 0 0 0 0 0 0 0 0 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/T2_flint000066400000000000000000002253721461254215100220560ustar00rootroot00000000000000901 2102497609 -162928914664 11061406353852 -524697937974808 23571763538047512 -736302635914064396 21157242101905251976 -629637023894911440914 16352706283035898946664 -390481975305609160512413 8697565215866868036918255 -173676869328326033632586650 3221943383894013171868818410 -53569553013933198691972104816 832076922896888715785776406347 -11542038396091974163041796953514 143825836283813655472667637327108 -1630463831275805653165201087761536 15331210825306570996038683758565305 -126721882124402324191511686311217713 727811939223273644140064707065783956 -2609186707808053742408922827455648324 -6485258067337500843106025255968730149 176638123187238697759060083238609460049 783440521302610845515395482964143682536 -19395910081421636180565621487532787324935 546835613094574771039252761961236355351633 -3286833780861291322903585948799719580776523 44905989818254808150723571101299977996143900 -36269875433991507956127475503186457124597045 845491474975069749995359546139624056437822584 14566480526721770416359177457038149882880189057 -1403458092630813293031660373462749042554977677 807929933394023449612682922338502847536174408644 3574286889378025564766992225586180247769841267419 9501997749325013615294468871582193246113782064462 348494910285657650101060320431559407387192296573728 1391793307677250952876761384239923833982458226975934 11940880809996927027322694826977173588333233243283342 82532484190772289835583953351578886471423214096999304 26698877395420557448525977042231374692290037857677855 1333211038973519074618966990241934858813516637470878976 19390345108850445551140318344613187078660113994540472967 118850177073802902571964154939995710753151652886170104352 746437043385842045129923954601087881561346417945802558121 748842601117976631325847012230006857917446397921934083820 -18530482382025833995363756374732828732921279542396340916310 -99534200277161896492747890731967515939609727169372688240339 -187103793280361825835038122749523294906018998863052491380009 1475308422742317468470148833166165009311032265507895714700882 14861188419693846403488730515265292936068094433463047802291023 34604977384867725596380121190482181854010855474759951488442580 -141381908334427746939182189858977205140906183188471874555324227 -1375059320307928353962564486918202305092153734334709835707042248 -4368515404155817894092947580478313349676287511505450474943594099 197562483561257170311551589851867554935808215278929477221762105 77563073160171396237326702800476672325778865001206914341365472853 311608175709869788374468463492673002771339889211169271631153501492 -590961962005343098862518384616921961132139164805016649529225505952 -7324937967643888234566772695128858700290137107009138552146340730826 -17166148462359843802949148407134084259596267628547009693081721459594 -78562470442074119751944255847989863432766805324257683652571842218869 145315838565281674758046099748374740157324316443337750105270341330376 1529319463397954255191120168296190218826831657523144438565342036684844 -4365863959907642027157382346267580270048072161168736738476745868175591 -8799079548462347899916902443308024113961008804651256223449830275870756 149072253205023501857608525636871512587081489356241160351488346860811709 203195337239004010548106178775037337782398659744058249282886877449787301 2771106604087968415400719705671278069905051958868746828058459840614080583 11334869818355096369503411631914556229131284499585090745405479065719822959 -12074474675732734746829565181260562085954753425928538794700336697571133926 -65819184316102100123357880915665830167740055774982669876577385575441798463 306881220691503422142337422257148781100605680260021350370735699340893887392 -402873230511588210481408161694209200624127818481700361612576742772702497629 -3854029630342308197857341066600737717296093980931485699435442912271341642043 23811040351677437456847464359438138640353125718447269642089091408408458564873 -32017736573675375068148545068144222375242575755194441643452784311343995070842 -825014468754504533681329795543607668450699452263111377831342044235132606978298 -1034108170357475489419885252437738110516816782647004505735917335179030147599226 -9447685846068145012279849679528657871204876688548041827826107044195739395226885 -87340483886890082061553317406179559049145929157511311849754360417314176668753004 34815449411711371110344385381131856445056906002038096703245293002087363040790358 -11579861190526330759032111399551669625057918754348329547661299805368558503075397 -2019097363609526136366862169700620753892450078793651310114571456572879621394121426 14044365068668720883005971349750596318559009068684578253520093536130850235555631439 784494830636472853601239842266643226358861840794802697930465082087079168776692359 -1292643920895051116891940581287271959459360838364320577730645396187840563017676803 504237159562045324346538722858016291324188528949603873946925290422328790604488778685 1606639709386651867063416171541433008327300373379683557337973169151083589932200207160 2621602905210429410895985049882015047253901906080264727500449286565876351805200580384 47489033850457267426790623091232604794526755975839006374941925680975414371395847893379 44130635821043040922559759284893578881414452995119616086752615233429253529707810731583 151630747331076142713678081050529941168383745268938490425818346304529242319761163450046 634951472262980923196127167938781407885288435578743978909494106135277402736225054472990 -560739503363483004957397879391343024555859588603981083691565969931955301319585123048125 2112551976978400266660262834778682353040237530531036490861660407818956274529196771745686 -1373737667466180266063386262699994780484096989210897272989106970606161484783063445976672 32864460547435566221608769387266243031183179779150079965098494097705936317164928261475999 -34148609740450630515756312891733729825546471508336637196715589593554020586476753722630191 400643259942730294774106250383713294155000380201958688015527265667472695701514951792560008 479389483415049263881039304228272253823561653632041073513700123827018003708535398685387681 -633849361050548700297078045454761550120142375767223740102869082149984906204257880588474705 3417608336058544156213686485626167916452723730177669134355804508579498058034770662475360651 -15857403491300726167560691364074859447751909796365204354030349503767343619060338317320777928 -15181768221476239723704990331094535920382700452316478271236429999766852555275781758869942705 -94926916123172102453094645722015447061866425824068569725149726058596536993942242979280002122 157290421767939705459966222454615152576304176368860476096380038568661241936472872319799334433 -604811124108387902493467851047394169870105181314259107762714490009719556142206340753204661644 705799398350387194435989227826799837804645630311023323400123086301302589458746155571809576805 932381916935803247212926022551853997237350022804049256611862545710076958630222488580515698416 -8634107944674042758662175561416059516797743759807433994877415162530216807374802657992208330107 -4488260386981412506060178516273796339996583188608688467849120676051791156089543439323529981019 -54696634078787218574211577907483281930961252100938161794099552794066420669696244029653644408812 -98148147664339572129700096644943587061221886825683865480627776973481085657678736869040946090008 -658933803740809317916874935137562871877946551956028311206664834539792487699781925783084823488535 593429227726784747338395739217590514425270792866409110210049620234000148601774079587961554827599 -724617572130480683763231667480176103096519634875120533440892435800765001811075481273885985831546 2998603081083905419828156793256866897073021408044308445466730452188645829658684748653544922941779 -404038922025823502093736792256933028305019336371157626464535587050171166559566977195197684892399 -5838193190541691032408785930718389135053676036355858844779090145297150983369949560871569048102492 -2480600158273753667922923545501005732549669038282489615348842665490205017661223703124432351656848 -105850304497341395668755384249844250211073864519239835070952882414785758318247036402749672872718166 21904609933386310183921496700201814753905606272862584848060336141705413641262983038642225806195286 -840400456729822507399083666157153893644887467636173786150016348631041333175221639135980901845875388 2945391311983107411604599423673540742629931087513935008168962731208191547351767805953539654829416685 1159910853435795090026930081400161633960142802746409604010814189817351027106015727015702940340392012 15281883480210298512977305679288039750990410788208653388061728706951828296549995175637932728901023767 11795069854602666178452995667483810052908349108396987713782786030788031687295585878655354480650661229 24590800530303695388816456374527368677521184930306385330167562254373674521324115817052365066631888039 2896533020522107579933824687567498823611159861025588225077829166711202994696625688403542604171854657 108881062486548727608119706584904086994445586092349105619079189060453630731498961190413560413708858858 476887841678961294159257572724726316466640300073538332038337994156642812120601019471071862975347148040 506745704781898158487611324860087414275459178248542824266539266969377955529246680434142854080712537289 3494122169954950367112436807574509274020118718683228801888364333366971335029971307777400043388407059190 9787545491323209083607970668959050044737913639827884269408030655980674705216030060354820774139055487267 13881327575356751632484743108020584778916417656280520308106164447147137449604403910391868868683079926504 26644944666336897617215860762090484023045481736869843412622072800792040922218891825490392890971117741802 27159543721834158067305037449781750952529955437823248305965459545395654598235035254421662777641482327700 74682660514669477511411569908968521669092497002613158133797258053789824986317200679495319295533561556422 22853636431585193915784624465792259361705717781726758919817616113275274785526744784252810754348574512085 513369556470760658634018417630024178738205077513578380541185090958105494265879100216294641342652487636479 1694118529781538752919861769523747701162411651231095198460092750852477246401654204946651846538585065393512 679172541819084100190822212951529512904772972305666387860173446623980079684897906529621247787826029855390 6130027289924246823051909854003634871496162640719944161707673948093161641822759611889936181520853442259998 11048781172913027707742198287758969347658448075004181463829485344311899342927839799562463943861688765697361 4299296527526822289428462681685970648971309990422434527084576393066818315184850369699312362338852927023954 -3297049521517979124468184814180108489343452699927809387290372233553642278701931051924317383012251812832607 14672078921894630402222267723887663288317545138956170424487838257902084595231394981127214831716251670459302 -7286786010423849960478640484907574406277490163235114469518500448653251482941422599312011038042501977981231 -224509055427489551391781183572530114748716392212824221330535393616469225877376037926133418864654998912852466 1005823849401166637794037836749577276721059315383819606780573508623138972592706620429774271401032217024357029 -446893817551077650274323981871368966971538786891963613935599575917759916897936698298841067098484293594374954 228886113458849142354612959673331081485762248010299128326137230061386299595330088125145974142398551358803215 3956663553028899639572820187550061682579982811547067837318248147838496975556354506028054646733720356343046805 -3229215285581116390100089139820533412232522856257117000641794548232081253015148829854141041073883113475635555 968190711082123185849389829013944576223485640282808314996062305656810517985022443401163727002232981255350386 -18531204982472862687730663398302000599138177955408534754416195506641792857434811428718069178631354125502523207 -74646078394077656397018655540204462241336479780388821926325409504711544921438456654377404542576819115183748663 2749931818345370576055920814554401586422003327543913148820616537405414826713232368582413869000516789597873464 -200108345054743696555417806310136060231917205726882681622796785363127592373406231483463979352111441959884474138 56474291317720803068989845401114948356536803196645553571749312817985729107118662705825747238105901427017596383 37752906096986065247894570132116015725590448101556434005182304809485436238439377566299589278861234129643783428 -116875264895614080320423678271925533262801969841313725454852584841491893302485044714950684318821120846559084626 994582155908335614427312129361364905369503754083896756828513642185584441375524258273596414137490105687590012757 2199463384330462456810901951534892151058765474886352049930031893136293701804983940687800379705908220037358192459 -633784902050527142359008662039191912614877413027795411103914656703288621620785008592513851582135093906014643648 -5103236242219635464504237784468890756351639858741667532538439347560670559331271128972217216344864936248066163385 -7114170901057741377312801514997182002462226185913128646507031266922847653400200825050285367958260326213665121378 2898013576333625171272389352134939258816429468843393841247200484446518701000604666759302738570126530332624791946 -15464310722777996332749867286325361608107363951453815442727815219039310494715649614369498395012503413955963629528 -29953820717726448841299838432725921763620799581510835458404650064672519476685997977860217992645189917378694046733 -91175196223941810871204701807853255022034257979996345369591239854284712078486227524702897139855356756696851232767 -26969344087218021903630374816022464906747422186575539272589601124804026011330041691247904425927985242097027015713 49621241103906377065164467168941980600033549993379051298656058920880133793222036801999560378209807976315603399082 446628618881359590021672695492959093640610597165085834877587384867589907701688877695052841917144406306667819215635 485216735098510841880699557375705267091897231928307835882937341236453437229037256876363603665623635153247530606396 612890662090359912864934825040486310258729516363222878944781897039201327418922696859229049881754618532035197769435 2622328997498313014536491770169113385280590966850469709867442852348005997158642997461098725600162440066815862508643 5352542517368339222148680004919155080705323247341113982629168350567749241591091560675935773187404051704839564234744 2596592838581260300465034760403621132570008903847752308629823525839944101115818725969044972816601110953769198233161 -10411086997698617052792185905781391404107039894053301127202421197426972798266642000050686099491676897131843907438818 -15925601987129379643987910228999160222092645616832356256661313813767486635943535935287439389257750686577877279486226 6478774284328664885101000915042440948064169059723073446510128378582159864514700026321548880922229078061044963747245 4151968969825051074623515346858068594767288342392322055030319553491994731208558932570205246476826284285629079129384 4425314516242313435353327911249191311924078748006798917101531034081099998580565568985665626643340730031818207680442 -5549730788719049931586153516811997844531536000975499227860428123296947781342636589445702590916890991682919377533244 70783138994260403590807261355280072236059692208821370434880758094726058601038095278674806303826363746342751448535119 286970808990493987973233041889028615983641146532427337862653398386176192506338524035798164592143760813797688797848131 528183773347147933938241767032987547555173248512331560085321533257015938187572167536211405741951643634118631042603974 157827982524604421216997934828606345499237586596889711515898238184893108322946265905980128998576323771997929943087006 -323503444312386499741564576247241007436132064419506508736400950883745763072233864637546793802865381567942484181109149 -201655022545159062122594252806954432684004758089105465113905441037831450889422941034968484424196121252404011443026752 244946442528088133002160408850417478590969336352511027387197675156799509922526874346084099926992742017651166440914801 284774485038626006030645222323933045642330461283573316826928955788944999838925686915782899604985017879058079521928283 -4021414185518647713988216238324489315523991242107775603468221285481173821394276710445211906441018533299535769272979293 -4897290323989516370296099517554554421331015723905538124451986978576074119213978687234452159124354742894404649006311218 -3547959958669236215486439679884243928059918408183889247315755012367120716680634384303577105704040703513266020653085677 -9732560623501379934718471420341870321896032560684369611057952991221155768783992660770136062193948396857966422831077509 601709277409042832472466242043706412294320446775416386292390079486278700102406216756803673967116833536202305691001616 -8542353990320370258006178328902634781133728026457750337257926540233726761515196731030759529310041453800311442785234603 51861776156090806500385843814416618805734699596398019221408137787161651920721915317236086656636075696675358437042773271 11725490686665481062304141155870094598852857627459097304156560605666277681908413093115097680800289389872996390146089897 21727762003296225035921567329226927783870862753234469826032633676959916959457352207295812187412389848469414421017240593 316738251852555084394106779652846346786366319743519680198794840057240238532633998579802272357497160650939628593020708865 115445348093177824420265340572823849128302839643906956015131834598319408126135361157825243519497549643480162830405538266 38290692509070456685410852780220416605193317017831338279838016363516322257896741842412670923312648971324836147576098521 49771308448574019502884208697531811278934369042539431358750924322019215166880660305102105770836385826187514943578186714 -57381761796777285790917377015211800865693876329174575506079034073058398308145934320256654630045265036621176051757172313 779998868887598330360997280906389647768530957077034389022712924681669263060045901665841836176031587152045815980167340675 -210274698247171203004330088129946714987835764233649091941156914288401596468847743595336822934192526374018543540823309083 2039686809416560567182360035404764318642684064564593645006146505318917768082004402697858410643769260858651509902403340349 2118182509308347752532147115903313798324207125619067814407929814394930711991966967214023325421395659367522493472106613708 1325291532573824335527840889856921876234057504417493325212934221066730414215890857540101583090009746350546647737156596214 3087298158911085376743732997474918278264564027631573193113595545073492930491347760735717073416666745458560264076330919538 3056500105998284476154495216503702363269838522709297667813439713007783960042313500945668146218046430635027508470670335254 -2509693506915939097173412995607301481001944598278652955118620039660695209638815096320360332465412188949604762169629817849 -3848281571725699537458991984591275987114514018807773178616422465175625341148169629311442426457840580440499763404501048326 -34220383550726077696569065004003864516550518197009673406053417382331625245493813970319616126913378709580573348486473188904 -6413337789100014876499039010760253237398498342039565343572355330573880473340658666720387043929719462358613744423991211380 -886015438807498587989565078274570965938407343937759727087653238443082033977931285891144651228828226018784962777570337341 -42131759507358228848682915533331725542927648729485390145754081184595455846589086157883418165864076932849211691505724673369 2674967436418421827815831839961963407350444442631652238644148047755449746741630188089797105433367761462555945446494509909 8833967457927844203371248257346365341488881041661640366545700892914774681002030520066418780174442247103172110507837220479 -43682569678411771652472992433815882008683956615066719592313457441125380542136484246425790095052047324965665526829189967647 188972076157543429382123285091960835958032956481500061441814795744536108865042634221629874323285692481448812498958042369441 -43682832236886030187527483567503302439463092051935636892781558599833894550803853631366991593974893799662744888427498086183 133401659625889997403130196214603829346656960602958820182153526994083038329492267354999754825420686142563351762629267982386 159183136836649342631344470048753518544028949801194972509300302792374445938330772923632180495491653020496712823982886091355 -39484803116449579560739481828521206153536694271604376244752706549691620732326538104142350471053678948118213978996614048849 129681033795740208397577914391428137477733785409187430352567302582822679335230535486428241460255244598989016522430634754085 595193900394128757445003432546371693829286062891886616506845089038009915931421843679068723931931908584390889858426770276475 -29892081705921229891642817314401749456549367917733492103440710820523423005808131855157322224108091864128417444570630671875 -278643921519009788284802464534010509776733318305009775773428932715743461565603186224169139365999935411752211156087452015630 -493039466633261713437029145557929055144394504310531274306141692446999534746228774838382471913591444490482959297048425487515 843064091163076572278633977805313178327784721596440271067533218184079487254426939368983854775270067466586873075478419256051 -516203966672225201515810621339328691740438257663605489988792179757178435077943082717108993149493463609817185190129570320005 546673920611492118496248800702107253881755568779510342841922041158744143015126357125775350438232403649167096501790341530039 -1155530085130070290786553040886551771028697772522765718585846515627072361805638270265766040904152035966733881646247023017477 521012198689502512995069531852045678678940523859161858738937708481096111253090307099112272570893837284075882207286916323786 -509304860932867055651584609545977154873939761807979617589076557196570454248838203420042894851318331652603096140554743490735 784516528773559769278529911009813608685031441036815731605144378506791278131182930405732329181665248401390700925197062432638 2203452830719285353515908718915861825639789698992574696778515676766226766819182282298263311530364942801456263914760796345042 -2424968296786783623705552687254707008648706152764027213786165056719105523111978425712500778590579191751314408686377612008659 -2933382726573258497669996217343540617902553252272397627386545766325788734773574220715188221273691327169434080022084113662189 638707343985365589582637860698670390699957851752571511434013457887329146273257175566239316520694775537253960849875953438931 -5473100311256786843138995017668868342896928993799332929973110151082280706270123284848434515880441462264730340524662526698845 14048875301718977981003652506936578573111051342386221078327707542204530813953720018061893266200618595572222507299381306703993 -16353499876776877227024281652807026479948199141811965111396447112792349496999447175314370921884342533413693206343186945523565 -6291117934388946754657582135622408700409619729039811086217347933921193334497217590787386377687178093122500277219044919381804 -11735959561400946493343757195373721113991798146824728009424852668183168838946230352909089502414131946004424000795679470679897 1129867530604089309148583667942710582276977545540638098600752571971673141106712249445060006084102721078261661569494566550335 -3745728887631279472270012888871990380807535069255008367356974403334383539082030010743438637668847986247387200794364207124360 8994284681576098249287275522055798969637473374726489094803219647273530690909897870565376655656969123737103148437739762741660 34598751968696556363252204538401160066146534686295685759179291150999946629561116824331744153928093330783318226603952307443532 3131615443070380961808624997451422346672350578947469402229638760054628243326325209021046681982549754252188819079050519102972 14326944471898080133924396905024391201433795950174703270916328979772941305796816887362809309210418815872507178867526674970047 96408726175878747797409601077176890316992159711147973274051177729844357193679653709503207507491751760121414751173030472828627 32659947488868973133168596038832142682089612280120705580020975860639756329638920065761478805912572810250939667845707336701116 8552943448731401250843885040191410658808943693839641345215295475949604281705815948401160473212430214479525317460450679081144 15552735379196004766796942253506121356272803294844250880681162437198152464234444982665101533283474499353888191311981089609471 45421849214737230665366271847014564552468658200300310688118112911061418958089660733824748272760079403415978339769166932883247 37564287771254231833907015986418023388639297563599919942597738516790932042795170057262117296554364336032706129105837877244370 7172284658766568007009126899461846531187901935550777488518018336504415962290577653229874972836715840339792121264791177109279 483768132730255926928638574792499186459420088581464505980929559718311893597236186518175982186843005827095462589270543691374883 -97122442020496523976344883736655954588051432292243978687162162461765891557131381346854126293057143645569286512599761232240549 -22115520564628095479753579857410379735880680782965677902332710212505427277430293940680913577400983824697905091471499018385277 54696590410245334599139324294040501395611760990523116515808618174101792047272062339367596284320705310736539645572895024603124 235729448700199847318504331399790109292613976263991469495990979927490665807593601202592895429924136740078623144594375624051730 103584176232654678647771993499542266632583717214828962650574154304605192059661496047980998576912038883770842896638027962325643 -278783755509378509161040053326972554942625207664753558384520665064515375255709440298798260070912761480322123091011883688253289 588373370837576806006943033816751008305644504970770508506785224857678988442381936345147314669137980809849277321036893070927234 174784354207006586829853949525059147206869871637159983403122615795351364812859889783916919162299435668024142857103721698268534 -107694662829953873610299186311414308798903295137629434562011847020410848959182224246550039640424952610270144531557247223124599 365588390991120279776100283302832593774350551298647199277068419425481515671316246856637858786406801051846185152038743941415438 100249060522006889232958601673194145026044260083060819132662195737866690908923868904186255424512145925875111744313726062158117 -163871279673299124120584276426364607480749807233403339198687838810709631006241382894170477882108027683870861415421362334191536 -914229826834057224624642587629312694000489283247609359436916388746064382780075430667950867447795055125604991879862648482723449 -1118324027783048358781422801873558857579345133504094682783681980344664750331618479293626297197551471027918072877342198147329602 182773072066309822699398018218977528802718609558641688567434089419309343350228125756027673929780920513531880098003035476966438 -126625682672775869915659760549784244994578812472711705039999354419607608953244434601148593290653168902739444263615812717316868 265377664865201989020360782434068007317230800439096846093934997850384276623211248129031394766215885577935545516779168807416729 -225532751397556290350568561704599338157756202680681839493181818119017544028133023927098495939157805976097270530907465078100600 181944626038740086706178539224326588444187021504105147153030493689303896050791454004678444319923422387297025304878150454626852 -779823515485376055376816683291781605251931124802296979487054561268589361203438487654474701407487048429348787460697275221453847 -12586080278132944696768174404809034316692393522987632880755461736782386701491424217552227177783587987733496840732352848636946 399499105241615407407024491595190396217197714585113541699814763334830241668748864822227849050875735920316219200794246101565683 -43395380944766934924525831288292523417551992421736686932698819063069717662402904911357374603031521673330162664438812640739125 227912727380299708609892050494601542025966477880930597186477336790249200751905125987802350189065062580395730930152872765496397 382655670753628476656500983494004944312225124165799971840166046654458238761786417876077161009433909664089135043996494932292782 1473069673557172856717571742165969125892995928632773863460843196456429324590417702013980629397698611179441098773674489886160827 535482818773337480209146768873899001800703103555788958148420233578714296053364461976662052595319447601060425292106207230795137 993309151611683004870790164282148755969969773727203003468264692013622901773272061469547213648488338029333987799252295152136423 676423194801296744752293527893759416742006456933617648214209529227746778715796464581885804480027927745197873812377340604021336 -1257673609922408975953100484760863028121616235454376294340859206934441988265987272881666253284117678289876161769047790630319692 -2283011619266942078127752581069118198380085710430339508057268731079191093534246707650838995706598508067551536682372057076766493 1445811782386334617420528293260067400211211257917679462162993397723077995548523254997695793460458982026431384273141217721897444 2924695372451976372752845038813688196333563222166688275370731497317153134857084921787860455812804684898272713283342840636250858 2631969494062310067547338542055938064535233380795860850703921399891987993074633007335981254257714987845518255787260938788065912 1216896156887427062919099808293707907646412194359906338674055229532526929264451545985317309472151492701387191685276947830580729 888761034983971764453633429114101540348548347758184992468109501657836778170368334375660525752615888637558560266104438416348047 -812420737383720695195092680005109165414387593234139847111883700217753096182246614652863656369226031805781922329430077499631659 -1435669230595816071091849842057868695511018487157222730854181445117584084260624000385901386036957030535565098697053538538217865 2382173985974157867148229609132828891894456499941473315541330048053732156587692727236284060336253274548318121278134470652249149 3622279525589140122472889406892867100643416631612516599849667692304777930368357181232788953200234547060286233500889926538513178 1293974423225444787048930982059027197587883339255153535735886855424898026582594806335984027205443910320682249716667568186110585 -137338508958322193575451190379213777456863067115007445748262793232378656523421334267609351858994646914413562793521286118987156 -1582997060773143863889564923848622763481695560966748492265351848065744549512632133462095777584534356057850789196138665916767039 -3548888225281203484550870575343272778632842121937017261310741378239615262713809953034283161758305194079879464576938183399634501 -207396978853648571566564427798754533771694593573308060624863887304555932328446180019032295956485272750549463977716830481465528 2843628541589079428604225519940044801015305067071667047576312659067111033671157335244521378742247137873518624647942658560751952 3667490571675985692674737322729077852804112054375290967308514066299259567058371589428000335818376507643262392001127887585184349 -254830830316515196678873302760515486687541911496946571191070288248161915973068652902471153579022762723699324592721573955499304 -381026602328689764517525597628988838673314002585502018804807560212451737256477838196135918248046899950785684295924789783148087 -571617514668057723782649749777259116799820740292546340475378193592703271051892576034411745143468870565235696698562070376535079 -2430506644893215535333651719402586077229745651843753312094877870648137620914717809233923951883705634038804737397344288452202862 328893909614404371225370368219731330682964812153328259603196742463579173724073117194099913604566984665864048855632587648120598 4636518647118086765770745327802327999469589691547494988647213329598354125910763158826035799116756420217702607636303943897177460 3014079899605082802173874682231466507091035921054791409012964328828449044688745358608152491065527786202865550290576361304993797 -185775074480384138702539731512839645520684524799890120196348490727210006459107031659948864644623251778602902276619710825241926 -375973097505790752834379569639594570483261349135054301910568226903294736672351966479568124389692326446521266978651821627703247 524391327095648586865378285859800429751902651910727222435361003011311824801926083573986342238114251724947613176309822482166190 -50317714628566476455042480245674965505204487998224495015939095006958829439587407773820611142635936360629741904063256745139772 440658667023764971035613065618938233468976177459639739255875263272698073660021365295889881383428017841444644670107807313548239 4237973454445974841438802503033867480236321811599355627530679906074335010032941403085662380168004441428052932131827179047779407 882025649485759193995706721587441767981337158863359282118833158089023694291794689275182620600958324747535841778583284136765688 -583786789449866174730778763587397099840083281476208014555233439734951890662427719144391274799474002695703563344475208035710675 -673124831171527393132636604190524740981454307965810355863873087030599808267819236958064810230876851436266748607570757219189238 140348714527500430555107750457574268640574986546883648739009239049549941971837179885161748610950430156857213292230260006773435 190182165765010514495608973027246724241238949505753104633800620298046923120231017846021211230145095505658317396618465267795390 306889778454213984662549581143417994785338919577870388203610167305778496736599068278966787788770751549222021787528547797372745 2224120847979489343707784089619377328831830385265907745453767120971406689165492091453083662007835525104355947319891809628795515 273769394160123151664568762338145050920426427176764590147666146111119150363928543187830623245506326771982584452471446994737141 -662316983982599906820492118378814979900273646515511314308735406018167898919507700838501794577433742602093470343761031988645724 -567212253909374361673939163984341416935843687406568010348242120370471297219194350316470486023362834758801253908039819011221099 83964423979601801193995832552285866226394214350490878905227677763847879610950972662716191096382876836602869650598926133814288 129578067300341948408694875845431617878076040872206219835153670457856848854902564501733006421527756989913014266658051466036974 295550772251326157235329452557978702634359519436987709127765948823942465386369485777548468485354221138503927132987220009668775 379134439991697964929643582927746626212426184106764071902966446028261574547500432593633964394478258838885812848616842096151192 -37592047839822529053901350737937240977538799453448658425272596320584490280086861274606291182827924680282771268091670893151130 -516318256273681683458290721938188026522394122355279261321110813299881252298079552415975279971920536824388609710992711727266341 -392101619470762589558613284800040348245755182170987826346464727347167594175775205480094874240164985617253052509313543828694441 6736648769253765608125713197867669670204076720526773087565090865760462341578671668677624276909419040310877958606757184698973 61165195317343848925860401706596651302261040043770944953534034642885517823196152532220570794502288017246096854094049399854239 210285698874490104907532816725714816126245992933156214802913759232776402752100947906666687815175449328168877334657949203054666 25510254893389119885070419685776949491192379737149902066018546605862225192144526127202204544477932502819170242240190750608914 -33650297963511815361868303489572384653701648820115827199969539211929509430594460168621019457099546356926840630178514336925703 -260569782059603335083483989629607024553676986522059295301143850020526580980188981762669915184419389133289582306474976854681374 -117094315620990466782038368353440732598043297749146612382125822718009902088435898378091007690577730984244816875705183688374865 34845709211097867448004604334628816866445697806985595312824468132138083232600664500578923708377848166350835786450451466248606 52344064200916749111315174343235473077157684462563236730449518577871555148158546387198909400774715886275477727777603937198056 63896334187999031062722455224041110305161577569889476555300242944511410403655882605596011896203973029036394507157191159558493 -14308835915693130491976280255368927893735232807905781956056609083308244615333629009829359826044614886085270392911184132957725 -32747512464820877510433795886959286454208136051000712425367281871928963019460878527599532759408101171510998982576877224699207 -103960769892872633878464356045171305557012661529922183605788864261172738085636254784487110024120216032990992766497816923465860 -14992382090164070947340619716711481179604792160883591297292689593228368884818624695338466638355043478023958381479367328849242 20607254117279043979844799146828278978772354635649129637625798619476808796602245250026810172423704366769611437077545256126737 27919760624137025253535074369300770496205961028196116580229531681967121582265122536676361419922807973921473954063475984398789 21744151197590977407952867585431880779564758718996799768237041622448576297722126365631574190647726227233747561002365879890915 2459228294470505417909644138142856177733626498178833200912658427381610930129150202353131343115325673757668755195471767697619 -21818409025490222324396816174705865586504110588807214569499546273146469121601487409920427710490307737171588702039993260658596 -30694930298023912911300340282315550180103327632365186681589413808038198338855078657508792464462860482528495122665553959545091 5667067414952942153846699588636923060027656078571088849768390615944771188694516482419757531634504087785415133692927264901878 11901437907479685270487106970043984286864823954196879283144271827908988177274410322179432894265216287545370817713321017106136 7878583101762974656002166141641828707758612218367928616134914541617084808137512364285271242686839469841916253411533209526496 4652181440904022898522056369537277977069718408272984305495934225400164217861840299309116884590465163173236739968263779591166 758740575075507703525190827516771958158985230334359069103117305681381489122141056528402269834374416086167196750139171989733 -9763551164985909522604858548160986021182366356205735713891926433753073998142962312936554588264731768838583484265258649794315 -6932209221656771196373092516511193594881977096543439104806946450016580755793663733707476259435683773504282193432504569004917 1207561331171183723347330972410603648438558342433484544575515949678739226022458473815073152345559299959970740144096305676971 5757531882490399156036283566508877660444893302510645866296068746738381394354692211012971127688938693345397207545480243486305 1655539336013031436476677398605445116583294323620561489251707637670761713285827249358672545022751877334973617717653246535779 704504747752424001708903163314894284720500367198480209235913515594986592527471482321284680731592128367029011228340442104993 79670573428579492859316797972584803622647905644633304368867603244096437782051037951897071650707173367384288608922465918571 -2876418138820991003202925731895948270861444560914829747469161823849027398432573649190726393564340722539865799454678747970342 -1043743868760753331967862249581805984193932228977112515553378469197847168437179779953995985578188855250504212561294987022989 212038417256643233691941264545564550088795452224361374330189311314609991970024927356470563373498833092213762949650393493665 2343740043167150638095732544991439465008640963392764974259688662766120106918130577044923448967744308075883267932886477835491 292618880950283207044272858372740469009039108765539653502599603691715750729168082797272574056346236336153911389678089643142 70704863537664262990389724447948448125972943161737858217504850805141044638434527170838374810995332597227903437748283716882 -68322984432207368623349080113119370721105591345171669612665220660838824232670757482034536454788969021218741421455734359509 -505787109604270384984119243978366069751192233622525227424682466143321418616464849328209811526569940338138787830652224732409 -207546596977517807366011719928361271586261651406201778604505638105403850464319104398153252081392239713045259655234776079603 36390550244848708921956810455107802920360182802026912017903163552300826730356908414779127473009181596414709591000538593064 730377827748593855380911912649944949312278621990813407220625985662119595101201626971681891590436568685754820949791910833111 24708779700832793915704706279606080940041082109675421908006000362054112211147719639476334279279082954347985177313326099948 29121830367537683108166317411362877050654245426200850931200982333559047121469727800860156961117469266574344234826901684502 -16041114705543048828647781513680053186091577191327999201186730802995503308374780595467893470778170104376605820295362931694 -34663219353897519330928779321609866941309738369161981885120004131443564845523979878581724767617205112810778322723679245614 -19071778760357260343754569432879941476637757780188488226114651608342564185728669919960109346264440617011572984979349009657 21635323564354234193180119740318173656802430644465324907356548608461680316322814122170921070196038379699541085952090683357 178926692741335745812231441129710946880586529270091389616024709858573190034206744280264257317041146290216386480618848479616 5317941291197722512056877603685657923177686333399831980195697887667130965925823154380620623185269382958726176800672595128 12296647874946400754892200438825343189992750145118764126479523115430925161167500421510456132115031836347733445615983346169 -7214647004502646437539121708445861314642858363227717571304128583489435628801285598927151755157049049432162547545533970057 -540285020683476313467828344521657604154284576876465963772052389813777460987564435016116299900685474861990498899394625480 -1483127259212513578505228329145272554120078243855843114653591935113178117129274569490135418930333266885598494287753409313 6709995409143176996989473906823030970982408313689696765989362173038572632512735812629333021004030813123676153190895695638 27088741100519944862984922265626017977184637704944772779759481254310541948127917445911475278792746948598061250513242513268 1094733911749950845135693019915998190951644294656782528672168393557331686958287629958329935788079314318643813824247299814 4552610574781191714381254174549879410736474077700312596205606395999998948845522633386032813883290258206260314015641476823 -1880446942679898556462457454129699179064104114802104175532935312646472654351740077288173794189564054988999994734721300842 477855281461801240100169522210930600289933086369322011532748736435514946573587700513888188736427085802243388798859382688 178148400454367063451930317068432010416815080796355741320215075016138975558020467863971045215413515181735216948836956363 1584653676813695492619885295258734916388090067631697459466363946376887874772782863026860401921277106927319638914114877062 3197810759683816147983101499228615042821139571867773599481384598806036228056693093952044200990443667590594459344176575766 300311212950057534066269237644686981758226432354217190592942426758652283817793970879435808958717939510863513197779103701 1134848082503166328777904210268693895006555788356236910586107611715436140920423588845130488023252825163792058240456746246 -526451463385762075317118388391529746091456474920321299154894132151316261528615069649817220672668383975701249327826673027 72820904435412475829505302418153329071065006326777839302030940150539693126527254085633989219338868536366158255599170561 85145122032691805119372009807901479380960748999305418033686628655305971365547182825687371869666560902775747425540058109 207142222972731383412282797277986617262350566423545854399815573781829142184784226532201611291039292459230439084509116863 255663798252374317681904926787671075864041759361975522430593511057204808944289699738209911693781207046903429748150790586 76177863370222994685525286421925594749748073670116627875952218409853485864919792969365929867373612005723964451804796317 270477037120069206814473136155005553752437759060515828097570699927458664179883470521677425404754319742448509268633480954 -56602916467972081313508291275032369075285678798285764177876242802552891419010690959293567978115710673908523791950523618 13953375823995643196412447206085291168425237434269229563737872907502186249417844332180645666447972724905309926934100234 24690037071142864580521159807758045814929916951729875199995370665510630901053557023169429629193981483277463247702278960 34051060979000833124077469468949492122174776298363215415789160745728664461659933278868121244089573443641802732609662554 20949433897021503716276536068521557169458734844008747263091563245049295630597324249101258671178749464924379607332031875 16579995523453476174965238385462665447215009472360433301763537087855818997915499239739997503328494808016094376838811096 48519217144178745431809762028171580054326843118600387981024939961941079439367241826843959863523260758921721094087733571 -2679124578665389192095722334915750570755893956252261054078595402985016308527082039311969961296517399546343172413630712 1577263319195755195125945821288276918212105952369209609487586351763763362542745775950480770712348034520771330571185377 654383650601230527716204036765708576274870635854657752929927119922021878842152113069420336549940068426883731871827394 2890237154749656266003819099076985802063655003189912480840325857889722940867976436104694285151003064022312821411805309 959804600277488517035034006139216445767487070793830764201385863023873929342430887725459955975711566205074013043503051 499850141497102769566307137783977026452548402258115287339011962338921075925129975767021572540213960594910472513841933 4606786774256870283609343079021857534981873122934253931512171694217934633645957255959192504848242369249155758118207745 -30662212663377591561671863240781244719003500428674017114194157449058618759317061344669876989969145766870158585948512 -89387943301940251731158585603583832467695780959969904763371320108632350257320796917243875870312544868752540103348760 -629781555820426091181297367585865726728941967991241479632293161168671144433930691983599330995349155388472796799281445 56418089139763164310422685604948797397742734160455745314347631779605107336720148722123252431785137872486067116910508 4982029428286487999826714241338387513140413123793216201182859216332986359684642362380965237694925873869453555085680 -11096122915663543793247598915239326116105904090014907056140410510597875008281302767604421051151599623599269425706843 341128327702542121751630451641839844210679575206731272709383784012514590580352144948976006312268062138260051810526895 19120883110016047992260953280435410352927112340588159633157211997535144133806533991217404248520198018163105391626082 87990598124822967721856485919078722788949772767258183818826472088069155823629356540098746353454557677368541149181703 -77869399172444009065513977362004269183062363658198753794344963052715984072962142826385065217178673350299170784564848 -9819735838804685230074335142651917833329860128375512101531641280653982174199495171766915133723491863014287322684611 -2992846380757324211131809125066223841686725128710978262341302087589568452715811424108783895548510442365385541744166 -7750026682986924943024854458395329278338427594906092675593069521784519397373174270104488258178364292769899721104850 14372674877082214719234142945952607907547881282656086235630938872435837841596289299104670032171406923219682353461015 1916616363752763079394467277528027801404666312906928952223486041960776630442696848512416088410999283733625907503861 19993881059280963400337355531896802824670969755657826793304089668012193467277959142023083363852883668879429136227849 -960229336812563525154541365628994757448163907888832271571319980760570643772111128059171858707075960076230536752470 -1131833406654429368839275978163719446248154746853862118367716084556031355594300958679438843699521199669300409390534 -1568449914912753375025385431479128840039868324316572022580490763249282972296240559730717018709889655504806109437993 -1323102917121610030962507517975155574550180696079980838378489411733799987989275845383990531849982650602925101932053 288513000227869167580191129029623416698167711108399974091985989433209327464817654841045593535210765785880589325135 -111826781247471151601785786355456105105448881379903508835332353983705734547478901930705673462725520351174936791410 2728209642153239739879359487332572665637734732461898421818014761817144460188500989290665220541699003262139444068389 467686635545812325227945706565064908571898012259239018299540294720099617777056130543064614527895565297919036816575 96180426886498275870624245814994333739078849411125120438632746552555459159016870414403777632834133557284712845582 26977622803311147657651019380235073083709084225516190727257797642980901189654939219773925848528651019766826181132 -63656938446904428805408430851886457168613521019024924310045095929726901005818931043550831983897571726328929237039 6046262499018213475334585412407986601183713199659750148065021570640399737647055350119995031776852599274267786216 -50593574039665861297787518804592580545897659200512617927750818763415343738919319471513074749353656345354365188922 82921091427962588581384207443351828290420196096993205676762099119599313529951910751222456611628133145150747253629 18442997761280776242044677015056554675355919699970073871085780558629324735830451359428917715845836392722545674183 32050151442841956927859997262768974907748558286003840765452606588866348116817345135534265524763493485170622504158 28379963681880716627240076895654654029097407858718048498614381466374187717132609103554302326724449168349824660817 1206897567383174999433957319807223345405152086877347910961687729149071687165818615175763845086842402879304660575 611923650371306011781143470162549047936023373969459778293615480881813161764814646750660856007530320356885356147 -11266948895040854715711998721387008259223586167921437213376726674256700915330951913635806358097526403195156806123 -3429322825353562152255440909420706182100934526029194622669537993744695029081327970136113866857327511187061683419 -612979549639737702694182229679166629807204441485786686965807377167284422772125384793398046280096298251639295068 2104255475030003323151545390464242402723580757271112863781306119787412622026020818996202542842139055497867872996 2791255997971233922907343021548869632898545155895469434371449788780081519007502441715038430394805681872238101818 -71199828301558298835544926337165032031824777834937957754274409952246089462512133342117815571015855989486859864 40734496712372407415897991239831953049130075952457274903773469804987799703098637077427886476656434022936520903 -226895948752023223007306517295477436114705509280529499631513238213154128475131070336139351530837409604219694890 -174182441774317092162451638241401886394170005569632473366396216752619680660251142697855739671161994087512238089 -46289712980371374576664847003595196937303479056136199136469664503699353435892419926474104792144659925396192171 -127415530572146800570437055709747394551759445349763504533560955432639205429646624491349152308023164949489736268 19302245206093513798264412900622162590862633954395307727354492644911410475693656363688294074942364010026929653 1481070615107271091962189437828390838418597051311841109656029236173753328428792204111852409443661507405837665 29931242100730176213578538210283436572517696452386174774719714615937390065021968773063416102691620323939907800 26761933452872804393140371722213763742793944263557149283850434806519341256634985145748818456399387617364523633 12422740950612788066161916392197341546282019351337101742703788971933573769287940110335509184745394094767928160 -4033548006312790795326095126289945462599506882349440512312747022422131648864264601670181814182979870163885458 -25922561094709808652221979365653881877129450791746684693810681265617547736968659233588492696777756691173774056 1019003259672305655187874351522540617865993660674031382706100921435682679255690606526681200630607861830512178 1423218322350453814645426842664829374960927674955417031531444718096851806668999513732611143844554016778089633 1970823110146828946732910731157076900036472102908600631657794667515769915654244450895185627477004245474496706 1514727123367527698349593080687469678011238265785259889774057155911482981121502294535879121227688615692474121 57580066263103063191325641493534721247651495890354408920175692337088825802058477755153555920968112020494110 649843074199096690892295901811827571021432906153066381478690544102424373275098658746855801845637310517913560 535716397287519879853541658139887490582650596029013945330972404097443983978644323430542424552358959613893871 77221351865346025494644990146888773978991900007815937796340497680230110176722384341564973392966090779288053 -57963950783159169123950245703119262890880186659341716688431948891801503210605077634251498374360565851616218 7079831186123701232523288732767677477990888410871807955753890988800581687477700982929371469171232286406510 -15879749749252097811837048495778438344028558643534244682555637951881477282922702654997470243140238065997851 -4829133692818812955889848872443172493486569555622528838549894514282055173410502270157739504604238358625695 61288215300576022489581082677969769410490260012718970179100387146385401490666753966241899555741870080101468 16656589647507688731921004036975503830179865316892820821628807355143834629644691148892582567314678840111713 -1562693687166368268640064797967326261243274150630630266005546184429658674648390208030883171801081010163967 -279292363399049374006013139963335493792752081807853741985621501953074468649916013109115220093866463612622 -10987965135626347716201364547242143231448652131913654174481762224608750977896749602646170412250794954253018 -353582279606280750538404025200202902159164466790585630775851779675400049028767104265683824325383915269385 -404551225740365610701764000631924756597772959989781318426131670053294787821478536820935021135019308801853 -2006396275153379349397678974822465806753110386348550526223635783122267161504010922767619831287724938756930 -490108807723911365132664882801898557354937034513171407424168622729811775361493595876255096173098880479874 15400791450588788053445632281844691854810234949241904583161328908907561796157777290838792914839174348812 81928251472758420970611216001912243225825370072565373972952479862065224564877385068580454500949346147589 126970426261714469655710325043127521582548389050577274342183260508955529981821791694650060974525512763626 101159881256168732296004711133811580517525949709361296110472804661304997344798828506001354114401103704566 20752225147816333772151517577708145966897793607153619873912005343709998917448545788720675479485421172008 31650489540721964873410219312365335178106269739057058465110561948642628846864516325746423694580364748249 11829205945082031887752113710544652838582676271590079186065224945185801613192411272581712991565380589599 -19567159428312209701591373189532698981765317221871212940735803660209279192371036033240384776546950752944 44815079205264913751869047890525462544510140900148868110044965225765870156112663984750922458740282569821 15966398723291372637296800087205317734861299671320608372153289442191857700236293177591794976253928750094 1569697228395416218347213317427607831959291871129090545635099873893153451690097499130025637480508335584 5477771587168251259128306420049332839241307094923776120424209149466108180671547975936614509827951023621 3362491533766108790223754599364321110045619590404525221084497644077610647450688580063430535962850512212 374193181538987843714179305714995928483767235248559761016337552060046164075615797888666614769543010167 514195453722294230638886053510309436521690924001441917081044500540953843699388812029594830458905267059 -866149260452325584163933591994049286793371397841617398170547377375301816711956379723961928572373654686 -308830497487665758973174906538798785844208428415059692832119267826030412381588062211964585531897107284 -157415139653787849763163006180954031140026820180542968878253324489700368311516082366731454141930302230 -54314726444933481905539699373111868021115411359519078424407253042339537243185123715516032308290172528 -63621085444605067848499661425731229272821793297775558847931983241784254788045864050494997922723837698 6529738888616376014592138745238203996816721384300690051996624302163901214558471914130199428904537300 -10957791651103714626507480543550561613374750593906014927496562040185186757668621080952975313970680602 -20969506103137323882429670533860469547129431946570657594370581299327971818632482931291489125346062658 -5932611271961007493262297397747577488111373151966908593063682542204890885044670964988941817471331446 -28378162733270094865078734285350144758545085733702937716409247692764630227082943836372144918777409152 -17058197010710463344014983574817257476047425210956355024020536754071238093681171425980595186090824785 704103673420604123921147434727299724386469268881840476087088708979487475042370048685608139630259683 18591845758372772042147359007919877494708622184959928916565558306181483480202350869480123296966255 1963769505505188573673916483337399291871076612578085154101939530874037645157970543230679702491493763 1062817210925290942417917306584773029515319888376175432375956267656133107955540078646799756589735456 35313412960274557620667063098574355414053811773405173418643137601323680965061629078955117609775150 552406494152279388191613789898169431928495156005896295726553379342743086107809656021709554362123247 721358734995804261613617470476150853594885730950715902472172852284443542456563543500829017736904789 -48447025045564135560257777895094567738005844749746072167740269542627101366959695475731879246901196 23910579249566818804812107132817585188290366063883909413119421540108037429500691071941074244071731 31586643890237331858899140140320167889582847150896713007448793070404499270983617265645578329414503 29102093636461682978078059779698885670184531060159857842465441123240355616742266254731032213714717 27223913769543797728293466746854957598808952225825708907867389165166144488260422281166894972561386 96375767285622163194373398016273442677373815573207279907019660546348073439872212988143565267537026 -937722065752961626737266080802430459544395926899510160660440907096633857041783248790577706277434 5559090645420947928774313096491143279320888928479507065321640792807033095231493281137940020308547 5996770595749372370886636518348399883217754819190553036941756186218602928355386539074161757920652 1325383968591456235832066054366950174816499806994392109108444214124607794151854339814078098656150 -588001487071387616024558365815025877321094100458503392256963052543298546195856777337072627546207 907345709766652036977501746684885379246672569209338449073491220807706627870839655578578188292822 -1591118500716431681932769832701458147664977295522911430371893628003077862664389617018557407146767 -147962014624304412258639224294459565643397122199553585568276214291874467334212629595192472049965 263640541036261205893463611110297115774658345813463169234329659953601299494765428744078216611643 118739935694039258135090906960080385630919519541380405162566686117903752806189309280678767631430 -602099053847871941664396163967559268184266604927716652339664727373229845708889149953981414293 25073205665076410406733409731198789031956312537009522979025329282686814393081570186065237023609 -6565680212633093076090531972959548530539585449237913331235223749981722127280854989410296535138 -13368138608432949072525756107646316087696137128346580137863595022712171787452224045470719009422 7796653452244949740314290962329657299374515596743556329725197175630302301615713641412509227075 -7983356495932947579314873999490088906402635114014105691470522918476247534404633189877866753746 -6508038450176993029755993656950418832803980142128546158740118267789575789204534670470660219372 -140010233557215412979561799080259098298841423454927882537996702206614204640451326974958974985 182660810390275252450480833326890110459738184693751911641540516248904008253914285069468828677 977052972009864639307444710051136523126187927806056102001540511510805360624430675480053356967 1476187617078530371000485981153251029291805982964460256331422168194924686755232581956214894768 104247997752334640997648783668245060772376695162384389647528367555895657528635293259744949599 -185616764284020089052957298219788146105838208591896861748070535729269208201031784672988050647 41947872832392925770112791156182733688631235938900175375827048218822977985900771892745770145 15522825250071290242235985422722807423561575576265624803630757069043819826390656942290897331 -9497068896092946489192705391423630017183309350662119469124904240503781554325901731731636610 -17974113530111436479955541189124494322575491158541349995058309086178246098305701878408976469 -18306597793689332609910998155058641231244986290442019079158108548117245239076405154564733735 -8932510973954229115112833605554450775646000548397336143751297580972272371034419666561843174 15295553422002362314753316449352653428264591105194539909215963894343314611667685996248913215 2490080338158818100747692803700283923945989162794698681913642196857101503632619973776336498 -105864842729904868954343278950760533250019090339228939884598156327904509221693049575141338 -501212254458544274273900145010745817060868263690621842939933337998348022643427536947048210 -90868657004386455830676905022891027533230098506938966295128115346424599951152882356722067 -18695526244170024311710817388880728433071151507215833734358190490807719134537415374477498 -256828594662962723404245383786178218344406288008734195831797849620366853363240760284125531 -560749283589875058989929088316154518650748072206021964169547344420168352727180935662157949 -10335357517232242448018239021602315553648438026212791114400056734100516753540745156070215 4605272968774899401685948814106700962052710446361053951518925920416583854203377655350909 28483227875859994623158410360253720408548981004793792434636933748816768445964899493461073 781972219274377087698326670947409028458573968189156325967359564864965911020674706536459 2873733576405827930887233811245755500377132048478924095399967671207144914637486072039861 20770748211590839924106846473493013454694329494263773524593718573687900916728126369817600 16358214336934415594494924345078968841516256646658062091110887360823228877518160036754778 290992072976943548214412051296939064012902569419462765218202804613916188552190903669068 -2452220481289649643477847936382850444134250940780026284236373501551207136533655590419391 -1728151777162488838325144927097214651203089529114435896844154002434528145653678469957874 97253250826691460853034532703702457857949205100065376988137217887927314745275209584956 -106459827664507880209895991108423064768051623703678493059881569266942934216961846727305 -372881958202639855931171428273027025613670955340569526035521341066725298596805186876542 -168620025279870050553823820761503544243487123067073374752478861002439011479507057267888 20798518263307650610377956002987067360234834854265844516447968557072314397051024987301 158054463496425868010503908849553404799028744556281467525108434414278034000019941831141 32107303676787804569646600896204654315313842185852898296809772291646064530078142582505 -7297720939589285076652203214739635287918967982427772187450824754608429089625816192324 1877461926700565257609042584321046131307033471555314048131086527773686853798583143107 7779891810549345848559062610606048014087575652594352412777029581267889616791189831339 2926091009481318894370477476295432823128797775826152173887154603437023241193552064234 -1930015820665673406575955175091730611403722849950223947479838977398147631571663644761 -6034562305465615397257172726836138998592451853823989603043883663516041241844945000958 -535969830914992837326207315053310610216373157965796170560812913103892951916196901937 187041012946386156195006116916764781510654080779295424285565581642622586639479793695 78758339532655703934730082384253697615362402924619247000140786360724065785800407142 -56935710566292231915336656192492041991167396591292753618510305387938097322162205866 -25065552587653442207905068317888219973202983367376430035558774598759666886749039474 83986564152637643747614325397670984802242728326869932977663768810558090815456327234 107106335147454009556775179602706393947161789387035759429405357391725456790941661723 8946244232981081760499949892379506479495662975421568101223135713902737960833495536 -1737699523434703803919387071741920064189747751964734437132995885094363192155468410 -2078271044170157472476173896029474651962087320761857849048759699348645559883751400 687805832325293389838045062604838632921445487964476001306164010235038745349074635 -68372426038832048710171337490940356949814671732874789067652800573890961294646119 -2509971284630894005588324184676223103862184875527515507095666709684202849997391209 -1468724902243603686536038648856342928351667573525377453558100457494893641594533058 -141322704747208181732841628732933599823439888889574604215602525955281812867184629 99955780558593871799354802276491728380228042486281401539182008041654171042700735 79139419623370068894694623578781485727711126506348187933309014884212461598513378 14798968297882869412066793064856744365566538762934079158711629393776996048689650 17799677782751677238192162040625235003917247630675077294948635597786108532281104 38424180552236842165956512838440941329745573164960354182994001282619102113791232 15127329301516621306005474448205401871389808288276850401359721466072570253615587 2495582691730092189655376741765779474755695052857375683651622042436277737265879 -3976331075968097393875869948200899047677859927753691385118776424819553399957826 -712592181905393786064075943826503488034983799142566690684624416720424352557269 -553561979949018999404582727560942750670195079944936355928912144912994283522815 -757234370784834324286332463210346081072965821525755656679665479055246752005514 -530363506845919505147249716737833980082845954624365619195391967648044879111390 -144686808686616458600773420956028788045356206013556379183837905837812967224867 -21470426078790923863401921701052165104010197903901129710221177410822808361633 123004344628808073867886275299751534881756382271532326115155184633381166614740 20250449639522926326380085246646054647263088572033693337398270865075458266941 27527689195424535985146210202691653935194270420293134206516816901546105882058 20372329523483957298276519078465687461995204259290433967828421829788476986399 4562491911985808268595850566110421689003657576809192287326889429351382890560 612394421178841885530691317270418151568333566637694086587303226201652652607 -330043743264433562744231259910809041649810352260748988482423987127468491898 -1627933615391491766558091080836157286095487132761422731839341749745970011424 -101017580704404677110138995846854658391774447828806113125795542118226612615 -845448988734409897428943733224819427998048314586680889221125417853121076711 -479026067727019444679361351655991187685044761491910960554848823748513763602 -53511795856128806656053508443752270115568837549320625707025683158931688725 -53066939133899043123277255834929756749353288302251463903756692339099205 24014538496533348831734033002679253866979154010944232768980121814221729950 26981766287199028839669196816931267169889086455699349835311335355879514807 1664952523169273410938437913786864637263865522553317646932764559463297741 16717914470202522307018444709755722237284628340184888604840309429324271588 5383662911835435842078530649414755571269500946296641824249122646149506917 525371499142918634178622212083882342019318377378710619599164724664000456 305568839549565937183795694762463664909750691408564607108506791778873362 -93221321021245351083383088153237589271281077338905884468682531380882351 -196335528045921338408727064792414196876172129794886884957795388631188038 -20456090908341423843248174805429578750698333037370686240922046204456933 -298218597647928467054539428229121452669565474692054216197828799100646482 -22533117664154065867000431697387199438397467270696573646596489021271100 -739149025383734577569339383239292933168728998963610509884914962585104 -3791149162430309562952224990927839671892038841343703649574064828537237 762445484822154675344153012774983905776687972628390739192926809599331 1567918103399235961824992548030141854190409325253597311822379112771417 -551337510928632395662638447940428236095663176738952859464318800151423 3403665641790856591354476376939449144773850867347437963994600759448520 -229336473736315687172670419178897266992507084171794715332116915495245 -14829112252706295513707169864354942682083469117800921095332763187681 68789476240046955536984666560774169086114175882851825367425866768318 -6689856778175779966139011757236155152377581252561222163841964047094 -10418278971422313840842438667534223692367516936614718538873293207121 11359949193802149450109204637138866831290336141540769144746796301374 -22944288410630380092999124057454716795825822051288359847863367552025 5979022967000105457644519940821546250093690302572483756227413535614 1607670173128808588262559739741391390240840768059329394004586662512 450541597089565304785269966134036564058533889676758664446327288626 274407865789635311200428209670904049188857572480744035295069243310 -130472506816079842295589578587480363877301484106843113195990430721 -79298069098192051396225162632866854308654939647372467197814488217 128032149221921911931199135717590721386082467471980514947721001513 -128761249532438180889276819136492915820659600046400409087987945874 -37938762715985894033775475112411564172362069032977883636144767521 -8222913470601001186227924999486775001897830681392170556024461108 -2091015395001099407125168478600375016640568254008802342626919381 3857902583847120067633104973982410501074153687148918258252737847 207538211648138987639246745142118031942897499123490776888257431 -675435025185314473318345627078364813585441095813642436107429999 2234765234189076796635294926848189192472733555819065843213147676 1033365067878565818996690735407929368327345843345700095658945930 223230296639459393573483132978747490752924547818562936740645015 -9943302729362478558489239605231380326667208570364125610424475 -79248395420500117831983593124720254651420467633715423183530636 -446203891047351307285420852500225741162331770718133196786503 8122637498357498432805821400930002828042034960136056677796002 -24710157426657315136648269865425457678672416276746283548514546 -12687462740405766283419699622024518955474954331723133916956406 -971777439505288077763085910804317767989153494955533014065857 455255095320552343536524844726856381049893006933560865779470 1069429453216257855083541460253650343039775289338170054884700 -75335555974508878897811865060282476386905607027091747985667 -63317233906390846972279635203007397689566341946829732306999 77629783520881370393520329652671904758513612430579184965141 -19004624268281848558844786146269677004272043032381613634671 -60377688157145222906914046138129904633727406964564913374903 -915131964634292460866845704015419064045108494787475213817 -16043178934019379892551309615556525100938983658299955960321 -4022743562696556716286380181430022517778320115253893715601 -1778345308497332363136645573531423182583448788043896321002 -11893595318243063762696674193674103662191038747138191239 571873528636805247986453822671274198828583051709485730207 920389419222459899120446598586271958407290584279430883133 -389366769181135648577861036538927480202398959467497304591 124915955900791009772604864969462195893175952103267311007 96656012954769972090942272596111176232487334021812730924 51975479619065016572609721453092742634427726852511979365 -23929849371796841414764491235018737702694211970083703417 -17970039315865846303448435841616095978995595730140680873 -12793708264696451457416820350267534651307512374793330205 6051005939073821860632333749947559920541290494956730593 -1931540562324684930380065427918681083291519475739213987 -1521659557247320414429439197807703394309269802130401448 -389187273012053091067678177849595724398906451048965023 252222246321277012033821337236547736879449699965153730 207411659327822875423712356384676522260940427005041110 185066084521947819411166418626135719928804381949389897 -12874391331043482776381838565665036005001749508461825 -4201975117463119040595689733933630934417494663773114 9622474388566472964100732102634307777397662899832255 5681592100693664819591116292061921923967453416814669 3338228230429994163369135840075071071487118209772125 891421193250011429334987753527160647091517924597452 -527518991084278337835722586292361005951692607819923 -522082751190252658027640670717126433019075279021483 5632249243685656425780600105687150954643079175130 96152239343398718985353840625900267970463585607691 141938011208233283374569602978830116669849519939995 42839184624640265179010249716446176694759146847541 -2700702830957395752548660752293641638705988255728 -19643375803358460774210861963909927039518271195790 -11607690642592302131677846927164563561867852540772 -2494107642685145490438531499599106870428382724477 -1349702605477947040466769476249674863400361408557 -716738345901183964961745068442292415228400130726 -457872782756482995478602661922173722441782759172 -82924353530243871826109025719509925942752718492 216357678767741308476833179577688365696382251891 120823928392779596105199555492189409341223492522 39522941842081161151017101516792626714821219265 23392769947883429915077030118885199976770269974 5171288705090489886366506294843233513915158806 8324385273190877845489580503517033546541813855 3273907107985203763133145396016366837738973282 -798607114668639323770433750707054435445441032 -997376022221320209087513061970262700402999952 -510403020792653402126524433641140656861892300 41417075972744592345215303382186629718147558 10626174322778652650526769143037919352537994 -129641888650196984081443743848806370584794868 -85692706967364335351973999944295885898554259 -4472690351258570634077099267903835011913113 6092330770870187636843590911867838474504442 2624706238471699766748430476689316356469346 -1721300780049395247579518503409244298470515 -469601219273541030428587977297357899289284 -2306300859508579241473489465898947657601 184011538456774458951554295799448418411055 22421909730031400410231055569874208663856 26859019353117903498513847730056704205814 -17674437107991532169932660693913972319189 -22813068885838864834896365976340755264445 8118863411263934876141235730406944195482 21368191840841324449746596856105602871791 5225902817530428861595612590018061079858 -1176913845669416586829601802475471730907 -974514452364116833449364815848298475085 -109292373759669467110803848954636485705 130739368244582841568524844191986688916 -176592729459335887288639115379259070306 -248912229381915640266091128994989881083 -37978602202066449354002661750809399468 6165576512675678657926750171156015390 913747806164760610432244587502745667 -2428019776555503188891940086764373990 -521883040177994869744134049307871524 1797965405144323491618805504870006141 1438935101542939784786506240037476534 273653005979095451347530213963378470 192927546214127307354724679262427449 61033149369523402191569140988684513 895783761912857887229147870803419 -507713361461427781392821655576276 12061874038024041174401438166358578 14884162839464383660833611985200670 661009906919429996941531522278763 -3197451953601063002277127275224401 -1915008104243131513304249124938390 -275434741844513852116065066504371 54443994463423252456377310502936 -50046825738359165718843164787142 -6503046917119069199637778069298 -1710260267563431077184908687807 -4158678878181836518205522430894 4227578368380495280611218828956 1814719252458787576044660077994 799355116552954500788286136068 312519817146811003810431466658 14360056315652194689182760682 237409187243690675946999194330 345463916569725208139845371330 104780522284080964694693706748 -8203132591172027300029026522 -23340658978937825408887093586 -13530908243319603512291125922 -5914824524838612626309506495 -2863965618243793768924598776 -1413652991844899574442744197 -392429751909722864600828155 96426764606427991229669126 -14125147457412635235455245 -66862926652131868608635309 -3632146375595807566192089 22563003579509731899413874 6736338712899515894573764 921990907125114973193504 -2022903666342243219568217 -1077628140595060248322251 83675051708990570101948 222657996807382523568725 126194164530538126901143 34203683086982924898132 -7820421268523376652774 -18707047044424582653301 -3597803855506656453678 -140609579944931360026 -2908514179716864609016 -2678436272430993832767 -798039609018138500940 206389836846942506895 442496518651442618876 101579716332430001383 -16047245652160909320 5047230633159764481 10778020101893308846 3720149619719455826 -1790755509188155773 -2417405631379908893 277993154352661093 361157240100004296 245349060655577136 89982950788808365 12469382030292852 9359346895994192 -5214276039042746 -1367729501562195 -2157718430385040 -1003146361725464 -156815985765286 4763878833569 138229450877781 75706545574860 6169490534792 2111063414149 4457259381444 825534380488 27854202700 -855886165683 -355839573740 24405548220 50308019220 4579394490 -2516864908 -605843709 1212936 435 -2035904370 -1978964055 -486747180 124169790 57036340 435 0 870 900 0 -537680 -351816 0 0 30 30 0 465 30 0 0 0 0 0 30 0 0 0 0 0 0 1flint-3.1.3/src/fmpz_poly_factor/profile/T3_flint000066400000000000000000030637201461254215100220570ustar00rootroot000000000000002402 52363070740941976096640374193098524300378411299093639466572014529242004968284061022799812178373631452887083863588145865841051091299597433773821065373415082129269322565598178955461540374131161551590367566847647045807313177685390382488171835693754431100222966412230528797283432962778222580824259295631619620189540601904822124553642329354797056 -333026038053758101617142886810900838398614171588832919182011048771842788810429291734917455898733746983602780358902532609559334174490898860202119487550628677454278899002145583663809250225103133051011195530796303812271159008948198866787864761033881813396341731955488884221952609992739894468172762405284368877744183269461404760464663669584691200 5371117897097973583580043985388650858488641006439821122773434774951794600730243689710056276366745181732573530159745299105711271410893008640082750537227728779202999684160910208389613630008855139812112936499919606945799323172673773723418299009607773104213680958240760531434475988638950622436431845251409693202199944742407695255551896388947148800 37270396672288414999725227179658889680506493163879168920473563901508977887095965950681148546403814434007627175587060755302464913013187523080542890603999294767913626701271064394794686333796528461388543659300778282571772299978465017533421963103647441838632472114989706872314725006731264654028987028378217316172828860411040592136405178331116339200 -1174155608412110003427046512617581130275748716880351951208743500707381929399594404607038133407939448903133029773616365470587098026073745152923664284131676695085544389860838958695105290945021842330400306765012990031836266029540564918113172405492350092296634917951658977424581670830686820418934346025524133765741146333356018453269603394616649842688 24889080137368206833496871588473464181363965036112697984903273660417975808899282810378394403899271035268083389505022719816933624608835572862584433520940363309626259198596113084866789868227960831022096734545696907886819486905777130509388209255270549608820170532862883869515476784866889198282546615827787419824881329672987601279898705769666648735744 -131115664110237898075521679414284157737489677136801862132053565173360272339546934751888843525252487359385849303503998131840822800068213305568722239147240040627224108122385193657405984992295537852501543167478558776122281037156194818102826089479382291701930414399416514341633624383778367398854856072046663969478390639851962244882935985550308166074368 -410735583836220216504383765963166903442331009844240902986777048897461844597669164265829090671691062416899763964447158840954288161287847929524865780714816629527177499538409663500781182278057833922030732074627886929157823749811861907806085438167637247663511767949643901008150051041292449541061590258388502397774407262525535326212997624149095380680704 26035898590343889610380052699859253777242046710020955473952943060436917279852067490250522645032434094753366106435216501567001537058504863434494055902180417316218349236022595322065974085919507875988742829945547686144808508393668874520558793819438732714873102023645914112758494512729590255230703078208624800309616656728107194224902554461721989109252096 -297434875062522053745847570649419518345561135820933453167019413965520192162844795270039998947284993168335516611420002348090260443286258157080916002408217747157330268370627487478519162339931931163240379422806401149008245478316125795653381265164887076487949488651943870364363955880776218734414197308695748159158366363529686156551817084510071188749287424 1741937135182111022683363431755559988292771874498172378180053024445091502004066192638121268631197022025662489822537725654034825788049159600741206005175144511053510821508547694855541518903324077609769406785530383407328289518722956162554284554044338748654625453750228258150184960591571599572516780729851209471013226553001008125761355110484088033724334080 -1490351179661489527233764592893520115487983934461699161182361171502433382700143345006037402789011250805312371223988408861896220067363718303051505297925995724119168007130199946216695630397520283616624172329990879272462720191947664393299743512461964878034995978214302662854436668657949549456984648192763141587689855595750839191473541693148319619963944960 -46218322410714515012421278895248289420833638200747310121073708344013223697612098921189476169222052235560072869150360556391948580763294384832923006358903605937960408079047510726602933472771192615316232247809934950716415824873600693907560913766642414140378990229736573045600298809298704187235631707953439874502216388059505185164207859073703051245226295296 483048430937827227071476926274702555369946465373329168791207393315070520487765178256534782925944525253360622939045153754951403873204798946169427881340210924910694002848315085031834257955829683369467816687466906946834098006251469607193834159442974582802134824245859713782916095750826869832769242138962385743008971698288960998906512269577786478902544171008 -1350869253603425313344082069384190398581414609141449983573142326696290913892685870197334622976425549582274979798165006827425783454108390370780302635433219200594426044048659051196942512785627441870309086167321288050409663883831947646492350247460302013942703925148914646765856722335805223892889475128936712604281719201245391420669350439115339959616772505600 -5522165328916012301497461235520877212556388594632297301103204544964412930277150572582353724573558466028019075869689460422861995899215982349763266500356702609253405201691811358894626104506058182265527585344943902861395109776092453380321344272889819170571859846350907565103507274632930565255191455086573521950338399021364211807668003551606438041415032242176 80860822003267783416959559460980776814242613961005603812846799460837382660643066780010087741748182518656663457697939038436265398464160263006843263323076914161688360092894972880674757548296625068231797168276683443098592737194220833982029736692155445050186350558336515749718488746870262395328400592647295582814072600400211002352467931665914387108994127757312 -350259460501386863631777013170412225284263251821567660839964447644958141466624565358938697168686039377546422947910935639259184594819123408469865611177351787429749849012894550181443116598540766882850437707677865717028143528280596594161285166334668884256348974688688240428193263560132396070662354488378517904583194280392610478559730392642591401542578553749504 188903013238517964062457292002989316047777411196277514364237200875744584626601819667440683270612587233930006461527193457661033560110748893782762995249332050328320589557429028426085790508805641145456508825408846809671450789043718766527725361605730312556397498796770843671554156911850716736819786943047741083730823770392641205745346932423204572192719534817280 8253109042156876970495322889487226247609048871096006443070985310901174203181791574027730516204597093368871947551735438978816892600163612690763603881333515636651048823124461344731871672117943949469769862017221980170856676018288339865937870777251398204127747071621473710644982089361221465735424589023276367572307848198792035776433305889165730314189311458672640 -55026842978352617512170294311308071748703959035450687564508523836582864030894674854482623360654125765053584305062360868965322798393873250863123464149467456630765996957468513573701784074524674189410039045678348255995486601028995200692453905054338977683923130345897048335587620274440553118042839592251812903655157852261320479240670146638341252035954422793109504 104106642217708285390293858341254765583648206910083532991795118907235875602051040964443376052317992686444101433043378599962664018774047944080808938313149723307992032856890943590480093325729219011967916016034835603436048305385467267416767862160020807922015030295500233498817916176440781415056472101846025601001732632496263857778800269918664094390855186339856384 1173333411232481771887375988238639169742954323301963596128951786400741059906389580779985364675783659751210363782141558533193521970767377960656424194568496330540415427421665670234792473198577533028655494668924555977683479701803941680740449586876206336133525390947534025625159773801224890928077984144812738856643517198509541783580126139589044763937135340111790080 -6051469620245479701275535692283328602130572360462242363056128515917592579424725365904855638763285649745199497974492979904675708719442287550051292781460289600507627575593008985648228896239909775931362102642416226796824949482467638457022557684248319336903519924826649058442485396054520215857990487528882764705074996971315862920129705061334850301865670415282077696 11987828910899449070181148852162708536253623070595086157824027451651735646670096645065635987063112222241635375002804306340741415630806522541292609295734221830100244727530886410107539418352649078635953968520366559719565191314248188765743215326370916060941566359436745721101054917198887157841234792277079605601484431363441000831746734965563308450878125816965496832 155088827237693398941217804722690828213459093000442080507945472263595282757891956698852203733236791011374746173403869257147304272583888481322366634485412644500483194192154390781120446097111846075066487724033419600657444333598500181566084049539635466450296750164002554293528972186272502175038329914472818078801661001750704130944771322865609130819672259013431394304 -561381028370372154731011845485139737407315083852417479117973177054422200463124346539554338822100688906997043206687793213296109854775704548873711618130446456197219947484228500124672378681745871878888221599560420739347057447415406201977284984172459484512794077834730688370185677898794940511358393745891367214078632236546210816544224523902931487751191106827788091392 1339397804620335613749188664921250545997747983656540357026942936213654727686257336684943918781241336082482718823009149773438073599730160945352162996831502127318502801181445460078766805123533644619775250591654686267811789838443301427775052775543242859851432446222936249125252195632850996593080946349348462214398425446341135711291347822198392991536795775661730365440 15627547290806393765775187285166410993737406049374345159801170390141789953500438660903825291268571915922192864307544587921324352400643276488877406775531450992494946379747340267015464249235642176007226538200276000089667644914386671475613123737954071567918301911621506523998811798699757743006906050109314731624918248993412838739128700496742880908305475995361516748800 -77691678782946344757089232573583319003359969847436449570569770656878919802153133357495606220584464289686191599294026625758434012301868433973576872593512225567287778257329989519752038580202159259613149807021779099850270227284238777929632823578521272751397502312187856032049524020847669663038252681145668306007859169966391458137659469636257814436776630669150549655552 68343710598914683026002110008498818280908900019358873762876079314207360007466576342925242734735572483855510177240279015696159619731522619104205412440661044555892060922710737063660450566366863170422362225890962554896470678572302631966422805962254384163514339303359294282107455396923686451737799587513064129858227769090090176665881702515593112009115162538716566917120 2120745761887909367220864301011734368548618784631507781280984325302731940469395901984910348664570235854601097372799344973960885772685486929489082472381974658677534887376349450807546176657325669631581030525087586525728770467997167306401880397776498682121319382181171149413382217367690456345606180624480119880189521458199279300273493589268352760686075837334925127405568 -5338469093528731258034019464237677853380672593175113016731659907971485815118277575790259469832873537371684736940360549529664431056659500574086874597420169843524980769161526005189605335372259183970282193714985285634565542584486461240879888658517380529417509815746380254198671312864594248754473812174874563932017743374133403278893289255379591991593520123840843344249856 -2878545204258410447600636945787896619027873259531779086524600599389652486553087132702837064571440452846729957975564884727923215065558928665065097335088269905170985903082824336202198567121583482611373302512306526000254226475491401177055375286345720179644731911890883156677129935985605763095081300046871481065116668022538220082155167394260897068565329836417671724505088 234553518297432858635434714962819388076290983476723118132739350398734072677240930065873002672246766724908160859995703294425971159691009083952045776097834738406521459214493662454039295887085846696392546819791625965320304141525006903425331450850542097928587518432997085157816657846637203758532027240462736111456272243274961134071580955329300925419011372756990195468981504 -21286373891695516867501822519642771784724909541345378418949794874175683164231168756387430901506890958800867999202126906040582262034459123678116971444160183057197126577903255153973044818704268851828947325321312413111906098465642777376935580386374713942995208279439937697376891959252516705724796002619369982232395232398732700903964268760036985353646654631979504232222336 -1943149234489231256453966680220725333521313619165984543670656891038357784347093332064192931661979742241842757640983139745491028972738734586413779434320444257663399270130600747884993319711281208033473222937191995200309896149286003533123136256793506421679129799110132075720113254481167304912488004636282952710186239854055712840105163708163157041131144093706718209606535040 10843766925948682427403774811504559969828824671413209764056117575739657215330171443050546161285488842325222034401019841819977400621734729728830839253223554461183247200094100879073410793154271332932102283895233251708786111339920434044464630329660787598523794350473897591504807526239316335368615356210096206192274036367453960127402371348825181189924162374848288051540682816 38932795668561558138337139759873731911511822728909972669335441031909847431583208304057109074318710187107252479493374862183795859018785052902997401216971649768255307579076537405495537950135438634648153605679249110213675841087348512800082258018833161970305862343987318588868274393693842300841371241543739359566260878670777434629556765342032847741939058112549331303407105200 -70948573950790644761109293710968544050697323217955526875220381994845402037571764182232616775017552243782821897880251128369157000615863648624672246896061025598066561883545359515155844755816112856413259995181703820396014067939631553303972708844821953568555938388690099014491990104244877651787615527288973636768104469392021697258987134342468895396027675427160214740856388512 99465827087140930695867664907686809107717708513558121300488978472885885418475959334075961328485448056655957268869592938852015804827375706127501854329459528703874093149103250979190243916637022949788126244774535097611162807815664031017231365670727698344306645914441491185808298569792821300804500256313193780243027506223133757496818200187341555081066625818864539062028248496 2551495812604288890168314474468317900661799854072113824114375515587539062666847308652457564601740916915437489810323774375669085700921598475187272895202787696197010145111386469503268491374925536927245679851071109577834432331033450260394685785216377337154170407653743168982249657372083626980987190829526642227742016249488813109784565390156772769885578449067389814369594593568 -244941603383899893217149940899012203966914092276489250723229837461354111358219244419959782940561875234405860465422429428651549705780451415649488148912707103546690693318956008136254644855000472449364122654659169412963026716691158817174747648643461566460621968792017557908671768459334392081047238423487118064040536566822799258419812889775115294336200479574550638156500822209 -27016819294237216992602285108369950380677440810457522470936339506558323557720675995137261223000326231544942731196823104003709786773546164663833112783003768468320825270346135715510410250515310250017619912522569727103878152596823557526652625308985768407432958177961100896017789467429368437092448285494465017579711243038453351177933308759872931369395598068901898414951924131168 140147533912481917961457756834387754833451778505247197756243155114876441839466844960391220555271848126100511946394507357609615573726020347156963646606351225456765708366080681521597483144327440919814208229137253075567910728874720177181341021078110867162685322475930098205285998051890097305637778730353599363578786235450624051429342910145700592276129333999596380520094205046202 1018514675367691057606016434277394116676646858371798066876502218953840975340208594309157915523432666650283425431642487637784183250221699051076515763353503973251471432220078036863283240166519646835008935265264263272562663032673895376222752335440834411187553417213137332403816907770906645262663407081438050896368667454931068829531711518100188419716581230048496206261609044990809 -1225382945762219140779163317066632148183367250000559727238467917659707430843210927061471237746631252720310769973175532964147997751864909334882816142896600234961734450866296399970800547301069807230925308828868816076154585549588936630946392270432890475065660955136837364270725118304813263856067857982969432995059590528982456977660661083727070849902820997839866866959090875184117 -16705928792867049534882188723953402699058403123232320294420300939540583316109176851755817549307932520470294192861013444772376339056620703318263710879915477897977372464270258372873757814088015055368934009375132683676341403426073043591926616039019782611592204762381300579637220273646185291560121919168643524241109530570197209650029068669964882599689977816470315676288327848575998 12974838551362981619271128126555560873487868067846486922763428155136190045441820975831077329325144739890740083702126828001501832627369534272446179082151957949839763984612447802463953047553247269793765197222658268381512244393993546636968913141781698595603921221761464492059256989902344481761565574845665700103301303787243557918715475351271615527105006402199030099949211000441854 283074071465298040655582778108320441689130133763906027118206621008979720961853777182890619902869174058775280143504151531072043441844094662290323838361814402935096478186971673035586770779044251652180462747509713109189576167075995555112320091886203501207449170469335546911631996693967104999652275074400226777265908400758562654056510623510937290772562456763492316437409058474413110 130740623157720256315826522403232107212282639191316976508351356889334668362521138752142556051772099237688329884880640759627950043575800617370475142911876033932316697875229635602236286734932511434773160911450786274970915271064493006461652615473081885687602134693723352859442501526572017644635517203904985395302813133740986541701481303475733470128378317213777356241088997278432710 -3606549555225501819475212666597349072107769639487211078244298907293361546395243506997397653184637522748697062543465994723420154025625591451772035406670986132143374963460677543807958464709729682969897649673909979649151909149189944839748568617295434092298383103976915083601962492378304142005498353789848433630338876091855791274726636484783208600079928597446785042290927218603647488 -4946637068479904685729213904122863692471515524902142165777106059752461149216832464566206411623042477207919788998800299546181494248385446368593767810498370719705858978130846715522275818735544527387648467853359553455207485777741042517830171612003542966073364143923921186312878357863733671590597948266421920730559798629817119856895840391012986522360346533309075159167971833569160459 41670444639112845164277556711353233982456704539006567080303347848675928985767193843786613483067199888544270826412738751203864440338591149265659668958387814611556075188890428364274071797534745032238321140268427034017236528270368197770611733049168690948352487004545746070206348765816596500238111429071665839322566416235266981023779076694932673160249473148170099043832095771244057223 103716098955777353944317367856092393169868403686641956916598071690665569603564761170315254363483129917367494262944558233556390186147918488393576536485351468784728119516832915640464762382400330490719420430723623188610697713152480431738909935843082336772225390898414063157599796976933311347339909484978829343453476865259545736150300600801376407328465764051771134002550501715415572783 -385642325939378610037069044014388517384100272740722675698113037977303519324964775617290450144522991562215703195616149123131786331848446122265893709672100396652935813480860645232706478454115931862505383030731603641963958243066736539859544914004934820500777234790332175187134250844635955684741205825353790465823096396617068437269899914057303419748605193022188231657873534287168868165 -1703502816627587595820400492317632340616541711095232850250433539993479190018090086221540837403022108380973751760247464278923400011538854119983063895758170708421147495040122305363664693758405859585041028809997941298318018017535155764128450933760585928340983567985728763371109453147974699154598533144473984960439238447823923238142482327799431877827910400753869250094339017957326792411 905532395178099407210585825479725400235653716525974950962095683293774038419274441703273016772331757440354601532562894137066758481676280166760886938732478764567129389730685437812743010620868199452661072710297918320056115322773848479110485679660971976477084103821738768007736478214285869461678999913038389440736487765702756779791504648020053284377927846613200825059023723557163234767 12044352753421301307399190892867027496468371716537722191256603622318284523795931297578619898239724458779240800624545753376502302940681761490542615650398080514802538568358029449295837851318416523197013692846906920404894712540611982979274617924712965243274877162048621697917077796365607156908987145247654020090911264857630532420444715471036458800890485877169340532589162550900794065785 -9580751810492112369775287013013533661355481441711443930051265113071399790711231351889838838284283491922861973092775103451012811891063160556980747404380739989427556491201411505671307241799874534766673873642127013992424702542384066483104391126990388443067155752669423301192662711170883294024234670489389217232828957170449552330346165180369947794957813334231611063954214010747803796478 -147558617199232836893604160083323182224676427898477234774212189539616501749009986028290376800357129243859929943887795398548771050371208196270890817382781008633549614400082497539499775507785906992390962582047499502965200750784252323477230970281155065246874584970058718861308055360444100684790287166550137411651412482120447019233093978193311305210657524641797565289500342710976055720754 -203478493449925376719259085508392583445564110487036199480104448032784052234509721428532229664162441051761681833636984732485441655119786976670520451442803334422174645975503090513203062935043574786213461288826223533055951285234057744833128140326156514113287417517497178789261864079079784256361223951340811870030657784095215519289066852582271523854506055591818025612333082397223647744538 539571271823444039397009086901130067159018083903302640264382043990129049077260260126784257693141999921859318586924863645587831691347464691626147894962594709208237551033020119765070918413472066992201503793727314897970623508608304697118120406994501615567514000748596251657188595538687382836699313083774759279513394758330391808136954098752433687102354161435534311031782336923447905265981 1674891145473685889069608727282300451922318358142789704841759167680147198705951460076783372060023904222258869034894747670689781132769831754655077043109562495152541151054084955173132788651651297919387038831646670970700945591679910878974227513443512299042074923150303203554125240815234226184259375134659671554234526010392107469839065894521869376392410063676551107510693407695512328637799 -1618811399254957928354267852856777596520690211411124335737709210242131675086343603756057779035834694607728156484391995970954060098752586480102656385519016578058356618254038790659964896751735952917243539473539686584405771802590460887059906976109157811602749473203451141688941373449928417932577213380692478861272955428171001769301359565454643312955118611508347777594094259898507239462522 -19901963981209965937024442443546843230434752239492273816299713809588545155648150632529748758462431918706289273836130028391388205596119814148551544670545946644020121465763624502491911571048641854589184788362585119347025854773398394066106867348011087925071750705922182006178936824966433484818644276671917135907651575704254347224867677852042095395961556117157890131312000116827644345777278 -55070606655588378504421944415946017042469847872267716296883469314332352329243330872413504188069372510121076287879547612613801703234438865395603680462877599841754270007878544787143403796339057155803921991538763953070709159219308476208054624290460558856033043108378334746044801251564434544351819119068965379203876647957624798819107913958052377362056119176242738137717905031519328370994258 45805605447364202692214186020356498811802685575841251396146418347504482724453120882848901501338302342644005950383834155350194241393526863344943399381092200499391181725127715245072939130662292658112931098996780470595100701712405349553371482045383180104148220257697001172129568203772100750582624024819251084203003592415234937968622613943634398014945476698785690592850355684869802207550876 796832771874066421693080555458938721309371773897171459350716956447066211827123852083297305799154974263510206925207131318726811960900406185101825324036365729264236563147813263180686072652276206604942032054677378846214671688765062095974030548443865319266346278860464720436447442085169085862638626000927547424044564270761378148262909979446882027000701770324342768046767618735584758854147079 1184892553103150155109326517633325396216970684860841738825470341770384124546027689950498031762999816176283395070047802687362789774578916936642455537206098719740946580308031537611297204627895188387038126917099672598926546734295096922929907696660755679873849978736430353653407546843004339041263615054355384988619591560194441137276619470990629144012866613560921651397351852002347589908195805 -4809332152819364479435903305016078381589540514841802850181268641882557521515586112604683585939087204076554675996831449467006459830960169905171448817423173270706839787840026456246561909943531403502930554398218588642083919893067187129065380101301202480716926741130316339957131485159705140315732910982919970271606457181859913067575059379875465287807727510568833950488497340306812027124983582 -76607581685908371009202541837947610649699504303932304285344142721728328328301093769899301763715046767967373682100147846334880577490187419218010577763559632631879023031174487000411112979712606298006958830760804114694326188884787645945366223154202672652389024591064010258245353387279055666385693306674403436408508917387664670984694800493139655888066879046917799699771883013020721097276555 132219043584480882656784584808476340483648314173798709895629380482202541913199223956532772955574847568848123093407901766102817838208704253208316517389956659901155321077645886718968055214127481019629818532056742829073933790134991379476318807350724963364606894767670932644730503252332528356834206735269480301350257380906485004438512947453706318176876351752757094553875920788377311212142256585 371580558104984394319708248776538052904813543106418016663171674481282801861368912674404227338291200828036892673938655412383254905760867532379252010327470354240963446202470149427894416684428100945945353738515421140683962213978283129280244002141181634783063979024619984828207241910227930232913280163455070465637077189057344116159742202397416971933068891162929706158734071935769509576601538332 -274560601024213770797518842864725992843487962109678425092262898059582862456164385780572911313376229594613867497769723169613089422145852490659026528735925329811385848976847029655310861240864494621169592982941874907355886133579042370681708091115803484428673514430763506174727729998689851426263321511079325871408079332398770576725256182371681713850096153735566706054750413587994807056076307761 -1612496682176481516847810386946336768530344824864466438797561340804047663571526611520215312683227893786953626256046905148349182573689572263340218440521124658743281329470831663083710580912529593064254798772227937804639397749909896734128868327474201205929625062989675358286373824986574523708294976071112326780182906947615825709261666695720774176843834322056218138368933260342750965210981501756 6237621834902460000094129997657323560904045778793821300937125137385112095645797592855478629872788720097126437842335091389888839371198379866678770703818985118753137829798299029941169842374966270605288405552710269904622725625580184510850134803754109356170155676679556817011672432057885426761014112784561323870565231677076784558266264902790251201711139436677444882879938365599011169657687126610 24009321356401513214342786518636503591019596884263784033917778840943009084391669794433209136511354923292198494489598536023931334978060161844916784181718004586469768599832138900626924432173607598523958439837031827854636254014443125955464566789470371309337342271287134891028276625495496702576043199187200045982348446966900321866185865688892499962435962362084819878682955826124012434680698074091 -40966542718913384685959615001573967571401634486317563083941105202239219912136308937708088875968910328248036621941299022113994286084639947636689169362900272656438837553124919723647573567655819997825316917140019857968326476323603050135593526697998559950709266010629973974696598000167175991668681170678345984204622056502315491210700123918802779735421560825344960905285836596057924145144948024753 -242403802278076180174514097370531807845630198083500422426549208855924558718480389220216650962816204261915192688737037048966087098600945671895638289529357191758880504017445704111209421762020281170818930455357785763790845566655914704800156149476161168412061492924967171919775108968953442412438214494581293448453024685900355133629017438149279205699200766874714795280503324960486044031913816686169 119959621647096953147085426124966436124161901762275411770699512730015798591660891611581892568807457067644963544003208445573464888066301642187103498200151726790864720773662425021163660822516802119672191560201809610807880640568966401384621866407540091105505549266482744724626213474969746362033203524037777661768507041383933797790989706989058654453408606204469206047198318638444779753451457820079 1613154834167655472912329573484266587834758507786620380931118346105057634476450643342105824199382956328493749447997106374336385689033680001995654827726036388831509647279284075008288472336659862934640516904753131228999595346165734165593746806143063355144904845833583980500623133090778466051506807946250657022756684811511505948807289303164811707838207827802994992427969667437452768410099060306798 -887507157371485953736852351895990070971327473115459509773161134013928819019586228216822994118540788749004269825017965077217859696797560101083385307886689944032941661070689075348414184946638741320936391555170972290887449812266270210396857529589283001970102585305693722808840752396525693897747508416271981797014215413369603700539692572384027667793227026030786058297499000799728079355311513592358 -12192068319301058440744274042113800880916379379650028615960949363274360029516710634534364825872583281539317419314475285979743283973449805697487741184383986803034884882419907310644894296474532883173287968370723723010305302013191262126856070162656345386120773717016419159375119973041699934572309802005847636385463858697003128260482633245891522211003877272615452507605011415154897650940524581035179 5113465074837115938197195005560157120150181404109783733267627013930753369706485929104716495071501702601915471735686646198520719544010847314849834181754973678243049734055942356036394835564655225100723520852872740476744205033273324644063889526658668399167012146650653769708740341226449663916872055631007397727913678129670124459586446640255655208347605315140177923949451632929050527832514953303257 93985341936018247219830307213225822273502320016629459167714902926126321897417797877784799744252334259332079693176661671390090320240252294011465921330010774676689799260894146477642058359778720537603298549945457520035740909004275804105478520256658116767668882622317376596260348016882781479538090028472920967725878414311337455327643766378616126291529267685957553834698848588355865005047908160807967 2467994100498221882668980159267163677817356216068256262371293331221363149709100995315377553565258926636368741731067877240382402720399807369247615031939943866373777058911982731385655935951665195491161182219803018655626903249087944609559116576007812058786215502610634357523973588222494985093131597934580862495188749552203334874225035984553102387002878345635420067199767762773774460413797072361113 -635925333751183008510758975487598375748964200108825799622659038353286727506798056524466517635097804490156356863293954944513642732298913395083288258255928966241500712992582917237032833711158356882623896302205541121736111999681477793443525580012653564053040162593633507452670294672151340135242994106915673253674054570413678532379025348826550922581588349600547277448884875275877626060145244552811120 -406087536122823315655469362174584777532982251255034149251298783269498021352709152502973648707823356149077351713604278658070625774817044020933967917310692720444002953559305388907717705387297215366788148684890538073940415364648776357228681257111736773906316620916139568706904489549321822725615230185451004185566689932851499247486289983266807070491705081744602493282304274833529957759026807487257244 2624333108554999618287623574543823486206014539000216125285198547755340684870032174846271529625272443481896804582401996807784267316223761038750356274375517371815238084473190621601797516458883793648565677329322111932360996529616437657033974913581933068317455910568733517402360505299500136152848362939713109524869437036113361059148767125368814211493710881587836548756196388843813764237935608567717275 -1725799955362453914192065370286109905028243842905072323788981228644152940551857911665609500212014488097767675622237251422851600412082764367741286179994258137902941110940633155368711958426921238963876557601601602539864621013235061181465491911072903835866988341741808796352453792418947760960180073513537926290415241976451820905926999216855069877423589588581283151848978784667139334311223683695613237 -28901548800577692180924647422843869212143117739473990394969705175167958599680254248178424817318334663677576565022177515640919509999270050338593723104888103272893944073324233026965896186582590966354105349943685164262097767750656326681960331477326044781208357637638241928009944905249537979469403917849158955656591951574862070840818931635078769718340716754620130006348718067781842527457370613956568055 -20540908764266792339807236023658301135035215204110868170596046843278075586091171401610858004461460903044394869534282834722283438750157368695405405492047735356756237845063736925630533209029819559048450824891108379571409256302115576513691881740538972901546611338463569183022313770236595623827516286280598092337855795630011192658451329760316969465342664647590691478346273430789171994801141123554055318 116378030093652343801626330861310362446510762235865990084846399686698732720590995364583319238206912641737786945470217843076245237346581284880894781632032935393671826949176520792588471183161412379231193005824682225648316353852502525359050289201415110760099138456524529246707342905313148554530920362579099886600921726929934686693600231132058629778546720770962379781634625420773238661923936745453939202 32033930773568739894636230530091729336064248783179754106757338228565546642904648628817671617110357891165355579109296477282797287509785983799866155315271939356338566703829422013256044940425279601878435891731944271627073246432735663179307220282417963562895299860072133691394093572869429033672991024172496064111074218728888058007011426589450017138701687235668241515052791426515121898235022170021762963 -748991273715350744182315930446026658198964042003069900872969718622574207275443011642122020601271277215757372382964291237070564997242114888662288721429742392725954765846597792022877285588168262092637109343947689363392157111739710953845981395053477094011681852604003507057201918474932630285946266012752718200021357970188398706583595549252826430906765611659371834213227299520448370546568838066904473526 421783580231284191353109540980966109281260170368353443042973810852998794966839832667486820616115963126280958339632712919090694218864925701111071080445765273101796676724352560733817771137225475626997028370429876400369624710696699593418970475880542865140577621506917597710173107205594675811292890811737778987832130178374170342729241261629903340986830453628599757321889728905711769033266245303569281600 7932535533993530349971286758887607929729302107185548368103606182519315685768327889476867653603763874397667696870319146737459758083858476461164011772648591253136743452989323113446765756194764723147933735595713845539857326316228201185560850316294721716446352374341720946539424631820187860267017024507947944588508920902725382368320459714993010500505340348094790411442793746224986116931302432134457185298 8491212802601856903898824792703789268061019069420521397171963572397055669463488036216887315141181591720509606588895052871016256830018173904206070529000410837554458761795041480513847657828679261879945769953219815544772604909987160604057679163348577156924065304613068106422151854964121490844103114793210950389227837172206937912602569451485715379438968061419964995053534406081039745505354255701174408645 -15988454503190548043853731424952260664006172218077605791652017854059317346017613053895423205899093010218923936949868024450224769521309299190227778184479664688030875562017527625403979777742182819944472196205035923532562074297260402065981555113151491064291320514521747213953693519596920007570499173666828525175648742265997970089477071696563856163676185840234998417105437105877341065461873503459191471014 55240556857476194434466820872983735785802880782666030040633261343134453731506160267376326297853716583624177478916507616552210723930417264898688660820606524612983515236825323461798686432965704141801853560693368688910827298045206411432629571340112061673909858998524337319921211842770611237322299906590535275981302825618032810146436028508698895542890196391305723678102750753189787682976029885234562889441 447767549951252560001443767262499502110532520326867818617022258203368138820390560047971987604496483064471110248806343497730802357943254799178319478053641557940459663035627787273632030327309355331465929601566333754209319045410408518844707944221186300047973629762555138166985800783752371963760075986626792044874705710497723280468602225163167965444745179075321112584994875729498408027142882918131662448292 594476289506942546298578341915075127148713478024409011081138819704785143088497968108175989514054370952936555386502138470008955345903757250490583734181969366568489891880992275980351242806802635141674630247617257352338799334863536356909141986619916009704544288046145036486987156918740570646856253347748379283190970640898620514944355417971543825603301383658682538660201361338974281679755564216048507799075 -679452700867829504866448669929222633030368508769131580177258158397863436945677014577562913840610875416838584920145307656103114185713777182719030156350398020360487446353726923096441084730246164820978665324717655033676923010370806944399985998587467212103357534649721993789804986432139813823006985807162550541599760420018186035471296929166547109131656932797143994778472068655556038100356686264994175432995 1165855873814802245550578605278095980127424934336657090195605935215446895676971418171376227379948943666693945251686727388001384677235947740971650745056761042169339197523181668300283012172481849527211402004992608030969288916819272340919752494046812932840354371113177678460697250191242880535170825633796788121210959668232814403505374733280009393680236957956608100592631268356866227682020426490432437769139 17359650640724578397009217067743540973153982186137961660314684576640506066157097313751439067938439925932133215235511129150730550180450471929304147615523511069816689928076480122960016851307237223339387670978882816359259311311995894288981861005863609786426700302932527012911227645977597328111851729934973912372107433445579148060539915041130059028750691385359044696369088854929195158044417087737720703681098 25379858183458386757057700831538422058613069733100572222501016803784048678434876772258685944311664626760230089162786230682737569070225029404134513428581217935793866601534189009086942708709559989945094003087258165248494807388184059129601910206517652469809046673410537794636477354766605350158548948775978237437824521952497689949215518581812012604982727086941286218718965196265706808374803974101671350571757 -48775214924462871954923593401341789734942826404715133478591854230631806556245269745458557411890535830119733834103422158714944897265007915082488411267873927136852653216140862915279771042823194794019500715696820047443360025747755353575943463877254083339694542160562727540160532397146647352295397072691384912686981404884971643497974428026086239566509768794194692068244718617019757407342760560548671427488508 -78755577406617077968218497985395801677665685204612538147994235526672452527888045611290373050633958433262248430181116306629947932807426766230217092648380246747143769811596142225746182090168524434369467855394354678261044962250233202004762525154554779110274215314809472244880129047483789372807489218872079325947076847222936249721032812200518771421956109373570072377836724320868621671830337961509319111379517 440888536419061908524407056894293040172505497763964761742300448498724195880768734050745436040859861394821463712696694344374025579553231622393049332697555246007099128897686925015147457736405606909562718049010780096142647563712298999430062771947468862561136051358250022457539343022070477121490262769759015695233828728502601647972882334298217335726418636497193550964172709810697533232308038816892817512162954 840142014210017154645550735882758992427373628570679055622556104992173757135340875543718906105416561657385095640681219630571853337156431472351142171732618385756251900330612775634540938551454461220420646231250018142715300602271976427945857498458905451051283194280552436203809060758162486541747668704222809166325844629827025806669687407249050025120438133075871618250185055770594904762455985107908310968587283 -2480941631576092509495636947726470190102285604119893098823832984146115573427074385708028020147563918823891313467091992370453321929464372434288258341380249809371136599206541678307078573404672226872666857744734103081299172584072516341572428796524010874308935444017788743847409243465071419112185258737969100415533711399001455462153538248533017049923549655809010674656906518853602606548719669234573622878961978 -7880188019876293480692761470934172139738730004720280513006120465022107575374842194345846256930312097677700547871691093242787530799569570854605423306109227606102102544641840844987631984415438257870215251770909069256277946075888235686761678398493641402720150773164726983615248885452875287910582450744035581334285569822330484115488940515640914200307289635484475930760691168659746444051040540925630456515786279 2619654886784262793091870227547806901135580445515363570682042061309520287451513456288481438490238771856086708026264612699067134454583826251216629319767168628879167278439517541461557974612231649181434586845133664212046686141061412838966726082992250659021388617369919013518803741831757313218428829924713367668137884150677632927462356021705238847536463514538801310165180956708228705480807342647502804919276808 15127991084107916500390570076326222758803068367126736512425606975786019150733459674576864806673592593392626544672030792503034550052033895270617090239462202996044947755781047218016037296069802797577115100008418274624040425977308973686488476736995739831545160536096473725315331339078813989057242268553504924219035043681057201353490540412462992752897273614757023851145019428408624226453499693377743772903924533 -104141364790237843204933312917572320116785935761622060321940709204869646574197206974025813703490145772968438529710470063519286102434139132809221545530238406605962434950669501302196396418553503110136895473025531773611489594322559408130017064590121981548118755694099457818797950927193666999354002553497929905535689289180449735115732587350782760928673736652694241243701142381484785557706257141680300083924538916 -394924789673075712472677041678086960464723124860866800159060113861406349193672304902353939081248731264119988620541264333358019101575829114691661441305565840706489136743759019416939778359066294654966434837659890790420810425057233170441981236570580237985928134229645380285767610939654428465763768232111025104103433584813622791822383103145606742144835399996068751804479121806388261200017526039778247623829561562 -328461948803341217631057438985707186496741682567601015858692257045483977831077031865952199095690801170353869517295892617312205331678250841121776240494819821133601158253191684426230735980055339558265327797323779998348515073538450305925328762720942094818448696479799714195014252162553968969014070345727354047158285241294589455663886098071099394636753338044257848160217134421196560056841439921561796876062010142 67769833508143620125935061931354348708637778958488847160765791354290751527426773329478340854446563077437957352862714301002577325303714933356973688931331361461365505369155311773824298969388768800884651936628496283963721371549820153450200628904370236552756656195811742940281696808317702317175457012808029750652103083406736089215692039046058697580694506314666626045605992774158703141427652522320426860176844758 -2701150821960288866712263511235766139923177981380514833004778061348927348492406763003485903213176811539061043113763239821298989982891080737727155482293023243125513343650207323038322850216280102866316016002666000440267561754065118053110767905848981563221289342973814699820498227549365859489760641212173340392568284567227612032200470023440985925381117723347733898345284531447349482349884371265431049826890706221 -10571623131084444719289105491332984462145713022357026331798020112792440259353560660680508434621011003033034267179453371819087449906110079896294371588979416862868323584149730736583655767493663408668075546013860448280986679627508281227376679790094976991635181613617758231227629790201535118231702570367575733849586666112656550485401849413096196108283496452120464521187046280151728227991867149224702727931650675773 -7104678662713835761368531255297696052595140836742694532355155412140969778109564566343657510318468982520126555652875281124685397024424224155883412489003327612426784470230797464259204194366768060189747661162926994674342912585419438272186570165806246648457230059424888502310753387321965062056936969990561514542428398099383314153820170156015285425821127678575164978221750806090354707752670634438812663931847174695 27281287854454124338980989479373037561403725256139256878655839316298769211561966569775329207188481330515312850975748630808713568194908927387872429471942170697343026157600657424323894633513653670718225452577361059315058395711937383198837117035324382317289820272510487233912387667341547127719776001203824406057213174163690222831927633408558770159596581620743930277789687554151820851609489239234112627134148457786 53194791666619153846001368167217997842160299280971814445519077416244381866810611014818451014086507121714209448995757582355120676705651788088614200188340812034547878780269966774968547133181768128716784208266783007136483060946775367196884739150801651362085677266890872789854097933290097870292203883601714892185471717932599367613107486927171361204687434581120024763971785223994080050310202611408782124599455789373 106820171848258409784697234573417443355813127833357779028228907045951824483529164073130679054510085607465881400021119781364478204624307154560453827211319819091390283974038202808113788995263441871226932280384330396643935101735678566991385356802267180737592259287899524141255584785511472640296274753219753796547515818051596758388103384591508530530537404692673069978109758510834465348549777031591644483690555227909 845538232447636971739246695765101082517614737859263395320684940296543648237191660705839221285642626265063161077899796504224433356916677628963098061438653812334259979838965519666273008333233188718296519995934480153868306034276523758965492812899088700779276272088433022659135978784824104963950242012789939360743443890732416501236671352864006632769900088843161142907820281764688020673505988847093527647115422846922 3702322266943912379136163714548015686234007624197480473171836252914954002484796379598397788054934934992832488905674627616640773977071157791210565870769962636066060851902232115772200482220010083410556762621009825846450247234789953094527991631625537850384217963473035774629869581381931779643145446665532350788915105655798046589508102496258932623661017237123741671101631016022219215532496020351367933641717290835139 10325086332186895827655694400066086659746572944925945670887112063724498494468533835756634412679507781199691450449966576485778624506559942069549658035400017938087872941620486782396978034141470688478181672948975057756348640964186575396100103820518812550309260121967743198554084780705708662754326815710368595555682688713701218522842989503109178730834007045717079649148396998415686738243021372762174869156397774624516 26822708482787076264385767680472463021242987495333411320960298514383878895675889500931100971338829954482513727199242509699497663763267451867080851993331220149267888848837944768881807632646938491197922933421181983146231612733194374898301444073684378737077665845840745888223424482314194559439371378576095007241895905059090614189637276112452143142199637559893857222795913880065677645432998399047624592552321308804611 79865461647715059767419565826616081027466502660726239613542039601348137673657742651327248898292757863393014687057100466347832368035389830738454583886844772344590312477578188466110714916681253052406143190262056390858328431486161920068525534234024188400043800182826664183757331537104006079866083392705581024414560565708319051783408881263755040426614807024027256185265161972416486561145749859279308004029307475189937 233488219843438421485063278004130147301934448745828233860278271759269432066871817204686077472311692120688703181364670512222047810105788498885176427845872248989052820017357992389697195983847267466969609481429546105058674513706677663661758038764362608421554492532715013166864328858181965176772417096574117100961781651624978259032573578131608205576484916134803913884523549633621812779002296313305271840809655131243562 603635028642307435125941823442434322948983579307313745636847469423043673058548255103467722938768573585459900603346462280900550724139778930665367970735213373024516873301633971319507913860432475902076113680200963071774977711323095826135379945418907480292958115151207977393988646673193316669297761235781425579140271278712880262361205380061872956843877133758160154322452436115738481460483832365608689060984846331066496 1483384554750231578438745490119400125140432898793387025718736363056646400396792778175454038156877671082154749335667408626887793106290449960074874350246145627661594239915692312420924445379727590393740641752490153567928147579136057613663431207801402659144270861727673427271474926503102362751038385507656199451510560808755622593037891342000261196057226470995467481158721226163134895452246227382299853289620382485347679 3750128378099867329480344255403171342494616983108004325464500778246369601654070125233595296546215775167387743427700700029898422534024578112173909610183192230172065706294711872888877171200878780108753942075122381827372133951268935775718946342200070926969590585927203540651902670266673626626175317003383726276066372442705428936566090718770263105194358795903796508779113291369047947825233195035313134528479520985540665 9433070568730873155048436624956491283911889220603290865286941201701458836570321615155337065246068466536204751932775881059285667171468023884493421800525936071778585896750521039102117694305566982052352028432755780888926787945560052752793910745041999444071768880023585737480706947903083977120197756740546767952517580336288740591881901971936860804804422317510869790688461536750509155971716163503825450729216760049863318 22454478738480195374477000529655685315772337889336185939020805955165842662477158646754377534065431693666460170937455720217271811211037830225812987070544399752178879025731953472983339995638098534084228589006044559057190346079731337056346677340814403408289529673724419422743277159157852756152715532309331856994796431670130724173519053573507444372723380973023737955265294267006115774364710668954984883369979660154410154 51582469063638363213773051532240399629336830739841767864306432437930956960268850516391361032464240697807926148473346758768929256067086876182493348404889942654586653232029512528491715282890214321128202804704937134567399771022626568488689085087070167311973753956520848876308204349140401733499802556428633014228717118407202190997667502796486703084789334600035849498503666135311917543942596943374385539821133302679560981 118813092930701792142105246221421634537694534512067689628932923438682706441457991021173438210162696966200294556528153473317049854849672473930963396038998374826939320296098969164634162336623650466584427990770774884347240653846223667195404725999152781282794975067318016132730229241088378821562241051283675929569426808634799067804503872829375215585771923350864566322944758093043863846485015391866673506544101496795591446 271679577066966529228113355273253008949842507091030031142188554387905628275418828544891264567793869135114584865266284316412333410012452420393342120572881383588693392712606707962783858772594689110027832226453110776557455546126952906891206977067634538834313087082720003713363020070046461530095063771039569759760436768015649535390146615501515964197553200364381022603434725377800379179788539623247768462106201062473919833 599876062144316301727060319369356455518033792368597961197440571907547718183487855005674229421526133234457378183580359752352857270061415230052709701434625937705621439144278731934021470581631616533459538505935070908241685552392236713603499585314073285966684321998655902173941723633705072374025784398340108398699190557155023242614137784330070329792315285680715485223361478433631229142704037229860662257008255392960528504 1288204833066852008582895506637566415469875601462907254131664385259249183672641477965938798446058233023031532229916771578183177993245879892126258355415154430202546198102077609357044102067876400050015402601919223517458392958305283421653003263106562554532511699091794189380959430510647490765756219712564546401703789049208143436977912387873026258701607162361532502958564696783032512598568816610538468980373808313919140559 2752784816184909605232862263509777679114432387706898844456125772007682270409993302161605117800662025223354864299793510981328406881452606826574098774458791610435134491000670952452689644771394820323399393903576680448210923870752830938057624760146342492264958522693901389455043654248784052485232953540934612650577789993194675806603048227696071381541253358554612748380790694255341875890169734761427739921114275132971864945 5826215967880642368960466337200104218838603937414397448478142037073495320847178362809857863107543069847004039949728805641910098769947205031416006067166341387562754293934544813628724686216713694746895057668017934976548602776909405807239680860535853096068868499117445776203843519760153639693303965322939815079584633803921842292895663460446241772007657339073573376230234823678546730100004333203062659702535074142523688704 11982722863550823191603201219676509735288103011456021538903000273569036681905671243316969049086148003558018643144836810654767704955782797869662156118346835981166473691322559153957040253074613639318729177686930234294225971048961591794763269604720582645424411487933447387353305773482327952160866284800534301457363115766989440259013281197074798834369485083682055404616368710827777916727713922909601862488876553957169626944 24052850459918307364681896689162074644810534460015980272934481156366676395342230430421862892896702484930102469138099084363141951274741051460325715254745808423771436074997065599090848240222703918989155812597482692996909437285163915675512247030256548757969351214368889841363904622896282094121271937989652390918071515861975664340157683912158207687173752019722175102072401881811401452467513097660213883306821807183526167325 47945770385813739318953315734717826105523707223604987417836894955131831067874318892314863789182429994999232500089813053914720060134332802153166179597787609861579796514189806561777855857160180766007265803048743264470061469622745510088566466691282909630004666863847970992169085135060769823467555873592475258406820578963805066688691401153119341192946920239706307951981005897324867349911663121614344371122099845874388958435 94480186403109749976448729806035881952344314067995861122649457551643031739251961426734410465649264974611546034197557476369418721560317467706409809782097044735357719606223926387577952728578370966441696490673795272722180181133731056351881567216161079701623175216959050994578755296235263333360508517280741606486843594151095142511481042985058968149403317205803030277857104871809012572556337586085235741150885450395722407872 180963113761503157575870100781195692969526507435378598634622520151859810501718087034684776008674040407508659638611223558019177848605399005396400875894962144749739268525951771640440617138077397701451404868112635780783108007166172875554211299871866355799289738635251931585596356428547676777583619896407738666166427292505422913921498778468710728579929980568344364059367624392919307245038311407731589003447101784380998877080 338599251092575121335925976505248024044511468104897192852065698059494244535113370347990854666592933673601671119849918247209452186657673463148815954916112005366594712985798592049930356827814046887013456219189378600274546557469780497823766878735737817111922154904140281663453629352493740049735635882949379488697419535313782242917102616019488480897699686708136183030914825786714344478190771965218890193656668710976669341073 629434955193573619181858132963654632549775889205188248390294401738010986292346578059042556041588622746182278278536048207702716617218771779782218802712672936598056227119722429818861720325113162763747109377007110471253977811191762430209074056923779998200569784320000902653419758916291504783741152906111850956898373118107614532389326420340892679908298087834031446405270647250438491895684049899517590150066611118488058903856 1153858575806345335844686226521991302759141478025130768177564029070514131845493113087229137035124147846406714308631127539788868551488925871199362276471139429504116562942263345411240312367147445027734843380887057185395386255671518036383985998464277152645552016129170224718928932009497319563968574359719647008978045687597990337486341108238498481856784463619114446825872930776670075257111474703566980418377859600205176339257 2045744710763749299664696386090825916472283115885422294006272195069438291690155415761990777459980699357286542847469415152000346434533861742023473589698863573961009208624872876715458403878894112638937755027637770063859544260543335484438741199197415993997657419744806350771540664697153306570363099103734143840861433741000744824836653870138679216748589432135218831500362164639994569188566727988603755889512424017923401696494 3539634144675491582249574838569687864210307177932119544411268147180921107881400187700615114143781990936247628645868142919664317986564483373774525619804868345146745374773543478325055366128959927721956197061135095206977375342810829052986167635620437185831827123901035861741906417877660394180135270749424728255086762130336271624136457915682129298394493742852236405714156117779529058627014176723232307351288249393408166715090 6103226403314594039185116812591629778142838079329574835927367131853164103449095703146656361685042769810532021320096912848499047383283299539098142431898416332926047274052198041151492578175152645163050200451600299644558902385566595563043670142427625713150506930417354173779639277632139505790136963113361954996292733782008014686724162399098176183855799280099763144167306984457454709479384372868622591953177234101974018396279 10321003130190647399504992052741305053071155971893154408004246439573289326873296485601926686855220221197164805121606752785360705721045150399089213040013902624843587581806624165696600972901162521325021647352468004334321011291206420806885679901010445495932496234896351289825437747543287164259006230334035235675331415981256013590168853571445888484543496967238223821254488586139821806539454174098044150248516216705871060076733 16634394525950299899744030014942160200889658106953595839043781448446669065675179733822139073993849347884638749314609486987594204007912827374247377032169236737033632155739773180856700041853246165575252852552266536300292204277364674515823374288090932289908571705617543091773618957759727718595438138300759113750189863366530964899394890851017627991614318408880643516195588035424784091186312820362105458250496126887161380206931 26090646627693989649771606699428600498135327759665955296948447707790793050825947912818696856175811568243092197312475335288369478435409025863385289346241575847801563287901880435265029624185035299524849073778036593181800666177872791172003268103409648741644149942871781633542329261358971366501158264845067178444642095919264172520182016145404851044722329273691122049256475522942436346170569098133121338430812454510237950164593 41179594181631900888324086135443790306541523015752334291881034427346513426670888407135408331687689024820641868603912181232506066802305338990924051404343955747030666339086158360908168255472659244484450209491043679986824857130955231772384084015400242772217122164115917009154625538750608969774790753183197208298546352620124031733279530917037168974473674574605598488610666760322418560069101478797928273281483693799764709747534 62643826051424639162420126847320384211319770368067298980644231163827778560356920596451062829893202297396277326402329590800444064721490283262441803029698781062517288946355856443528913677069688275354364206751835593680325628361687161614228471116341080646062533675006138846422423356061029824321006621376661725816142802863312118187438582997112037575003122932489304373877885726897520904830152517902432591832180823863146265389897 86700191307916200004344804618835969319624520551493564282559204080199271210981619144194715885703148494397117566405480666213915076568096595104773882124801763905046704139567977275964164529154818563717365444599655219907110226630589814333675056323292192864958233387193529158120491031235456112708642914479864668553418268648654355586132450158945880487118438868520647427013758121434073747850939103123414080076750649321719054354971 116285420255747249389453434443994149817008268596729749020376939582153731884001187324989577733772896640966310941161668122245454310988292413629717187391065101853837186920740435567837531368205371862605665084097736897171301774880747898234700462715895766439681218131852488074541729309728602482518469959013566053820393268891928480317648582015062969113342377822505512544821212325981671223961912444162873786863717958738332961309030 163577115468944223930865861198040471320989304543354520276860780444582513644670229710578708671520649689408788656983065727098272301202465853728709892923758635101375725550020331623581091906633789769905200940930680437840321924052756282795027378405348226946819057888116558936187587107271310539855170024284207309116383930967893090868383634004797275728901256545866311414437346096297719935722495865827351865759041812857935082040780 203295091572028690604513541161884530808881390227439568576860609502945537102390826893162442201917281264793334038731568659301653552184447251187666461527715365594016901484062528990256758518072779313470587840827583572239923576184869488214827375185615147758962248572874561984691987044370175048728743922557551856495636467678437022017904388211622746520026350724720180514566220353368841977856884594120028815236349366315005646292103 172277531952012947790820642960935123495446672872542981290258665392594460060120566356679383936031373026608885433331706171749407527680790246147200313080172349076005924129440178458529392072117764129346282657447588274207112472448366649738170067015122973363536256408930661925494256807449725143434827501581957332925795495532538811567470300653773001913104712709576264316425768246781423564301657052358437931393231088051166746243287 130352089491442237070365019571877872444066874098985944269107733357869949020682448550339439718274836414024554228423299282212121904725034358484288988192516283102295915768041708353532523725458047714365634703411348056139587822359430082437463236087923421611461508849582885119800371265917104442422839625672599919456983238655180135344198006071246149602812922947351349233983829777708319526105866882157352687425563070690916335249178 191416018150293063616149515747929628959407414061478248663459356353962711791699158087546297227940281682685494499608023123708564490410181524377249321977523583335430062646381131476039926068405449013212650807549599091548334894442345990688016185694026484073193214069600139976039710614041587054737776801589126050290262126168757541638597200202419478699792300912701513940013674947979473353418349151825821738582643905162950465337090 3843774057666742702053505743038539084404555673851387063062376559918660829750026923434241548917557634662426486385496665731963310010945602779678883571508659255945231974356536798503317869020408938548341126612955509596418766765409973445096831670815730134319805181892120164651436426732401532389430523025706371826061612850432925693323425589418839894909723343274835013131234742635361508986756361109320681663206288174159190009368 -767626034811898508266779518005480920330331025839734234612650464473299811011081424255030259650531105741695191663294808799398252816839433663339431449599448964258111892495668702811687264029925578453351417256943962244019588957732355246744077445634064301533557418263238941548445077426126006945898628580838057747378769295202289882018965176466281321107533631493829707310609254785931776470092412489897638447468385401328189048680800 -677506932937153036447176038155757287487638403904460778937181985740592307023848961791146945385454615802477568901619667370522096605454882725116866191869877903490189189685893849132693773329764578854856771081978560733675426400154114919677454603235964407763629152686356600518395094979420626671268386233179403981026681043574476434542874007471608578022981605877964280905562427746359286862649908555375780646779576334819047875500029 1423911620181473828239052014889840452947690883051505373815033041511400191587688151566205872055450540047741730300105754645218724686456207190851265227354090788778299981866428720328538865987452444078748558877357337587355959083283799162267611701901873615318668759273883017580030268358927185666518214289572242589437841146669155956705875033165632573735959249338096046883142124152864113451272964246651080907159380646601918740131057 1986378179530543404743093932411749930526347284109633091630553282591512154306778576609804252046220669565878513214895658270959352259573661798016465627280666542487107140154527455583081563545021130691303910471938188351309763120039444809479532198050360097353132620874892550446880899631334492587308497054033664690826646742094093425063987930330047567950277201367621259195098645279647830803486090771052791166796154379401442991058537 2534182738449241682466693130989249313195765241785244624946557588363069863573895159736726430329245740123798916689787481711686515378728521334979386685965090372116507610518004828665046341113068392814951210428400164688342158587778493176474046080336044600356757116120506367350106212024984675571223863736581703737474840664164197624596903408772931756046588171240447792746159612838988971959495366534992873498330496333549947444448045 22527367903354307927228063365680556773359581532250149481872639365409293616020230172647698344016578249403659067905097066332136414878456364436458093932266775595107449187931740045111615719504276342745956694665538959962656521151715350761295524303847476780739572183479382874966106143215673603848970892638583693007617872669589655709073269547759630589572861085672797145923144970841059361412818051785785271965032443221538934880582540 65120915181566064241374799146544767675955444690762944238528037163262539291438877589488419508276504455812869886294674874997207759824153529716024316161398367948355358233824557573142766024545309050613343917226549694349257573992646393260663833830263777548552627093136139809698197284282709478584319731670985645212380493973572148296697185676750786449552401837398269794910039986259249952770732858539990134828821828843934082172482737 95914478616698745320989314095166440362812452691549332736587342140136372265456136345540343080058499025545956453924569598967832363050931645067972114020255169564946587333804239996959907698318665192622154378429878706844055488611786942003530559848934061435321620519970073995602106128138142341222085358083913632316758833545368403438204796856017523728978028335936359860060486860345891708617970419990482156647090868859979711643431278 168745275416258218917808697119396500272139145758528253143775798563347085950008164360217839804775575898614574944758515097740363982095750677456858940814282336631508960266075017336822045150051036931731534131136090476083206337128860330237960570015450042231880943265532869116369531600185578843199541669294512660945639123770216076309718766182773158192967430029461068596749179511147388886640029601041055080524800486512387007250410875 453689228554433855039160897324340246695659058891922469935720957185033517660437345827039924614557567097656671086273287327225524892388008889355672237384136831313638664372348214282822684434973649008140270552110313691222891769234607808200078896055108240230585257737648989043650576182239569892427494935084504509736410405913240201401864377672694167195973020438496126176559046317558920770746494402410279276287277803557084715963719583 843825790959623803231814028296275179318501959279242256580256371101691948688583887147234145469971738617934245224905201396695402896947817991279317296465056642258734571640133365883596189327465796576790542294492784627651760771316683748928788766478876921254260751669047951189271446350556136434454352719578359054166486242151097476247898571554372755540722916497922359215749309528095961630883156452033582543412156240390113319975548369 1061698916605829993724935027962348248813579133382961268178592998646566342360889967409486825096932452077878623241841890698672123510337974054413694324512597798764012710481356107928053581026334279979753053503280338259631775154415804951829596268665620437683084438589279247780913426564306388908119610556451776760077343502689738297403085014563382387525050582162161621272888013986035457398631159015379263920408093400146334612576243669 1840029440086386184729889066538219696431825484143540105048646376645793811542177774952638818895546613405180119761022004284175655977106521690813061759634487610923297927012681607963659980896797691142579487923244013953595545652806123035673189702850507961472518545691134862593508310262914084000597805390659405030361238616956266685638709988000389124976499326789476045675832222114172011638305340537268965543694666700701998198558482147 4126213434681562508111585371056920893643421567251200696896111323523160907639470170851298771176477116937753671035624859410285562294616886465760225447883252000371934509346195493777217034063391945602345983010732398980675333738244677483468833743153827065487664545941884626857203552718716160780289067789456240851825463203813776308624387941901843323091688625005091341091357768595017713692387226910831954428982961739307409278803447254 5884617343941929310003235267394322863395963599077902250238886691956470910748843643467093647454535174538978767832349106773825258043402539883648353990857507865398880343390650968663260356455474085054651160346986254881571753556963733692829156981291512327769846938031086198996995735606650169268913189709999948071153679725173655774090593531314531245762950704615653876767987489578785919443141761844605320869533298162408020022299403287 5900922567927950293727823011104784206564256074212726390549197251800973683802735308045288551279646056265595183275219962236175376393908035316788327027964765936023359020840260516919738204904040726983362869083683665329516797345929398519922804638413313062230301121995698337669411248314224248703176264596733267570644844186606983757294067701452565960753655090407886255652893478691171885464302351370912418782692585372781906744624386738 11518827240479241717707370497313947552901290166555197074699476284628128121065814463702017014848870175462575962616343515868758682715982886290229896486664087280375024906520583873462625208185109883862569107990764711532722699724742439140549047047840936576907845595801311866965379234737379761102127966664299185671576038113125486508260554835371103343533149243142616188881859145656693767759454776968756922238909866580244250192539600649 24191800248124104236418950682277158548664772198500619795707145823719322383361063605159258821103667817383184238938242692156602374579799161327917958062118665094578772820554028644055613628662272218287410643080385520310657905665314854845020840292339351809373006319152474199097781636116464804081982558610892257320166266307172674120619630470206510490120231060527315481656147279081256305557600748834869230373496975118779316360332403858 23471509842705925271326929068790878631519697219623357296911535690965590374649877750446718805327968650930232828143677622421973054526070842756655053932759108437279246055542368836802213056844817807821146075146526576533046466830783602993063176866841244062450326932211665153388144989269301424236285159253538035090925882217195561077446735371104297993765344404736295905252264990696900139487982327987708363137868246279952526035733394641 15454284770275099432035778301232433234711768990027738107311329661014026482891424448486221507055991226925211718487645490043142685632708542994968693284695351721351699990028364677914825174280147073884086295206896877139608553688617531153616460417664093639523489514246799990218981284632570565818441477272398797407242628369049317599805676649479713762932561358186398955811271909931254693005894031537527129690219667458621816454134315759 56694796803511463777921551075685169570522295576047023352107468419521978410889953707305854535724065267605353201458750712766260294508915492892917253139689519535506361420109624525712959362033134076527852224581195017382881336201422089360646206803579377208807078198114463186841456434165849273492948331365698669207158725569976295913112354038925893349722770063224498654355353648530704587585147520524989565517788298174233782134028609764 108764435829767214725629989854441671089684466121887256579478319542934456313646402190608867992914412266520209530673380724799680395348519372654331188978631126113017547170230625596110971453307265859381792699614049821929458944955171053260381445843306147422494322990930506408531198236004478869344376352990465464190149963864970818238404462594188225695184650472658862285149163281926501908592230659424079778980747325820968313288773217421 38187524025246769512210690530160521095009242075416987320516171521662701288079559326710185073091155218124217670558984897539699025527810186982149552272494904614636439282367116218091437959664607591698597038827789458961753688794871608795379307299080496048457655999928938757342778195291631694782269717233049532775705940617088267543305337730797323583024947907082603699071412056636924532966732999290276852850396489661587709041423440843 17322469949058846710252776861003211317969508073154978430894287802011446945186057163386433545735072914875993660056334965405491318425826500445117048140941914505339682732299615272350323074853491745006878207037969371214536223871035721321554403598314369625400537100532625480252569228208133611975619489223291595408353214892628308543128637451950641582172214998415973024646275469089349608130154886880006300252283811910160878764316156191 350861487016886010830160651892043664612439046470928104642102520387724015225194443979631394313394753955368619422325241187690721350515821994405790818137030105834346739728766288291766635002728178448608733315791378389357066884373135453737805497863521772363317410010039059874136514372975864383896212235325498078370133107451804587488144868709393728566409192213513489160606221706242144614978939020704194496731269324469489424568728346535 487225968951828626083417793603834229653938026724892976833147014165812445195124716209227703412416368865488333913043616166263649672214072137611788086476785432379315193201219997568881163887616061333489898379480306195600828146807236699650190663802172848986637722645399202878315526572389902520292848056259600061771484796508778290752214022621233609313090357504085919623115873433977916983096074713158504233459387581331307434796507552029 -61736466644303634076706533822991184690464979851653455117992451663786124143891708439961730607965506457801136032425302921298523150611409284078886591233718746363554835571769912557464808829881453473183849066753637423710320772444366126612682212682207973610046031833695614841949890056328589177745928577187761872512209494182054697933132472415780605340526569515389010187859486670279669161767261196604461837539980841289947597180847719904 484584384573130220974441675097061338626422723974440094178556634864537584153314453567976487008027945744259360598855370233291236023196924261585142906493135676862230799517621448754264786352070802075808137571023451611516795080741910037025553656886598472935455785196105725220489903483931057267472380855307323330132042393404784261818076181062992668752468036160315443553938697657647847923346929119079154407756944279457251907308220154299 2839525562415767717018468231017672374299025039148712318379277023969310607952833328218669740591066462242385886069622676621271183184343824141355548967408129748988381658109147450977161159437978513629226090035677903537776782881712418004658149930077336045647650069340512038989616538961976056074951257472081450889956512475870096861200709943434942333219036649265779532586722522712041760253136052919811889512100251586225810690595823964810 2527414636024069379198646104121594462636871182510851968757132654668916269178433631745335926243061154889246141490073569181498242084085658926058753396254780440979370244912092311757135177863447181342223855198511628848877411704067375482459930344295416586991778113355820046210972265541804120219218962559747051853991902876390726713132503262812005182337081841062961224478808349133605829097298137687665830554667519017172342990641792296193 300798638633442444161413555142654106111304238875609498604841284280584943091210128147000356517467728059804158810787166338079062800286359293066513935608073334931733141855990803314591120675754375560537463530434145670607320149122405113367550992717148958392541077570148733610254542301788840434846882705097765958447789799743368223417652134926833207104762151117532705885835741681169106685619706528764158860715426296120617744665695508114 7940522489008661247506425378829758907966643838944137806252622636123559332939337805916149935370454309304352998707541301419663337982141543405102327151024798164945801138765279211455598475052208009312979453156119365283117047675984223860235188461188504366014875371596696847092798141130820131123550401236168796367697207418633042583775574383906361020691079743541209890526631037379815238882934572211749809598108110383017588645990974519098 19904305012499300927136746151769389891656132874739666200372656887327309233893904298789310922415360153075184530171341564863596769454299634808352024030413494779485451606250101984346520499435861597045311850882103925419376775632930937076528656904578855865931586824803289328597287605463155004845606737322453075818548520305490560179124562942622051476188096769021448505281858527231761589832326147186642352761368410452079142199773294828294 11913779465117702616378581647494987526011745055499679416927372017700259670926098613679927757443713685552205525878413592146600317124292807468678979741012150897062884192077478385762603972881787310780976053951173268161260618438495181637182482215772058807360868750700437632917023413581605974303574787039479562505969748517026473639380106148208863279540831160866081093194677726041466898464974067291160597550753365394966276436626213233507 10911055564395971885411024549629138857212092845323438628990622223874027091401770207237525269628278695219458744927756773107045107296223734136850155335371253524757903726386045864483439202465921197017689174535278752934255441346865904307319490492377231604308108074179219659757963742889501541320730200188476876078381472043092990515801368749104689547903197517972709828980316227224727257787298536764773180404235075065447735266743767647603 67532122862049086870114644549757751345160264983072114444285197906802489476402984054520223381598751940718204220765212367114244000536376438341637226397236107366148946287386610005753112076327472582133867521335327537512876678541835502183454845699627770876065971683900248823045638366136236006134414523818415835455993655190388458423177185185968936843921672179316426031685656284886895331873583265074819281760256557995736062005160278678197 102266646328229699325098618157104329824537640794666441752196491664006234215077738039753000640654415896174601652045268116336320316548275184722851698423398076087701489185379654536438710806734381742607564353152458024220337900213466205891701581804349664041287857888455851723812813445655285463108045506981563745824997677213208373235102230513991892630254909828974236752619515039110019855346611745390946177968589157393578483641682842533352 39572694530712269178488009756451161888814025491279953291663975769669463065870517177867130416025092125904167072171365591775105691464286090081014516811707939882369207088738467541523712391045574792021644086489975346584600612344199955093453553323088472995854471112311760976089706368553221864605003335812416948307253322285896203483125027046755439910262978889515712882959501410770738742546853457665678431294457060349396131963945046216187 107477214185732448192069530453107350252848613061145169423863182927018628989402080573923023540076128625176317820528172767732090288290551385438168417803566911591191044672759839348572883001077946308370686389103662116948246068288698556827544897289960874170176985642941031267984316261504719673740173165863247280888013088919901934348002371575537527730853698356858600367234266193789628362819829974985144424375036335488690767054351643646979 396126922731204128593687086757259783444211509440420785596682366308297836051057972670248494088748359166026640729885972777611619954093427897955987047421277562580969090482913797509570965970626152546970923631381642096042067310921376122859354730875962602165700876305693692396500661742407049886286512714390765579635215828762657853296442776089577756924811188532066199276616595432146782048750192494421949183504299333309974841932879501673885 374591739837425449889524072022598816001664962074675360040956708797104894849158491009340053493518639159245967534401283966342024287887962875412987087275832660950224926932034207928291893429750558145183040701983987098621197866484172995344001398986616744886419068074726965558670423471655715455223691838224027537189421436697187338409178072401740319323378780812854262833814447207195736768934817388322572831750596447170707525079181906360402 105638845474148082725418175792179067751196462525626884678785781453770865602666763405192469305582078994775144962616496339243907303091964727645355920939879377993628801274703009384477704267153557164474519497805409308390509935484246736883947033519755445847150175820747553830315989781792579567708868002688455660450687381011425894824893807339945452980369523178869261754225754774950843408115735898456753530262846488985084540995497503687248 782054543954475999160907983936224983030900495360721344393981393976836789943883511878110690641410382818115262351697965991680678012684665115398172259296318534637436075257716189447525614535218721955024660622674737632656981459632335005728678779547681684776908346581384499931194832343339179281108982811058640916683790942719632442246140163358548496684592461044395720267388349590924640017820761606813404499539800820841552013323541532340638 1811822505107955474916046073777440801233990863996416513543335187452526832781875002858021884954607094285768852313553206409372557563480808228571426541452796685898266809092142590049675942385701974546107248849407812267643305682115467603088189605857264188013231691162444819049145905692788804718575192833203878849686177031022077953720182895779578369932750304109319753615885046716043625362761203802578085261162410816460180074993740552334846 987059171745530898838609796287301870181784769087567311823561030427389656793367182260176071961314438804350760076445381442998474648880550573086738945307439058068040066535862864948327763470920633755993767310055479764443204269847871770512130996828413716383709164197881156408541586605878254340833456531834023618280677374272029322593282966996765403395646254893397088229104085803318185406555157138490163906134082324739104535247881437363275 723228559150486376424816613847639660006755688048645468931664493682165295693923453885526163535720156705602529474415793584979937887401628162041134714581274631424436275662100596966180176339088913143699306441850408796922718625942309127642406235376358082273443695345932432545593896345039286619054354270465059945135787372787982106000674985442384194231369259532142730001031571062152857860223248360382831428311430501577666569536259154865326 4811746484249862709927906667135893488338626143431765450510026965909189974244043161396841473721155379830575977538158090778650319681613887296741885693404954188050613356104455589180683508036273080217722752395157556421927184549589712288155266366711209182779528369772018811406854572835352482718223838310290008880003642111476316218757802987174663451949600461997286660769320937943801030762925148264105499409545103699031385868898740373562741 6746644891522175133785778785166940624402522679856945912818893211021868973601967372414365230800376074772366515340891070608746234421397796997191615665050091932562477471344525136139016794528176289588998139491923305301964130339708125335204231705494705793051389540726498161969067594196500742702831962395055191675533783865013735323564463358742009814943933730167102064755458684358873495692504726529810985461212846302411546393995991676585983 2263052195241421211490173349318143385066933126301233471940424048378760374035936786519286381668138069141419149038918938197540422216884851941418723078001125293100463842481126316863000492546725720371636767278810679106958727560105969208382910243941123100350033006596407768379077788996734631206370717680542442356009919210844531449224140006356681158391946737514207428423968481888063375866397246816703505924854296887271569355097468336922170 7700030592003095253241968353537815798868155890004850450318897120662369444419641323664632168799190959933851508205569719270492270505403066620806482752026965415365658050830243531442892031583317503359204874773108549233999342468357040488962002567701927766286201667955107842040602590864100537973848319495721308674452531308671107980228917847824513944901257022459826003645536443306662040929755528370410276649403402572237711989401467059565923 24446616997513368305363709721733362848016325843751318694838830169238137035196324329765542538472537409631219596329350224534973824512899438107400353987987291549566185742844625343666243512685131172841276007497560847862328049334284965976516426409194877895484045239515100194998452003810549399301998562711002314370337094916719883066896962908182903061530986845807504222717467101571223902515769505984527966640655913566026001112936333634668169 19435565650894453278525154745412946828295073422947640381269746230184569578121398222632283534168847696175531563951829071107026395896359711582150035088506720235562491892513091852492772571353027273494815169956357307643013455262537520245922410027123380629300222434416608214026389380400770315237899919233958766369931088276181342034607949343903462931082312474047914781035730674283159369253367297963845165572611468678378889276776844187372206 10436023630227365690839095512088813361859297568799008874499950626780061738069850532333533624856640058659842731089107872470922103154199921819877206078992521254032222841344869150244157323608410533328924721967461559920790383199402371536749901716313297792707925492782422255456340405763690486735516008260756721557220674655698227380158682767032194945023357254491952488002211609990556419154983815680125186961854631396606077574080483797878609 59792383986894630898077556750807336626369274884178875898875922062665470184784366430095530925463390906800119076438547280055580400745143440515019568321931239251083220857188279729523685117303435292481952989039961869823473964872715084152019052273485009462619118197046686986496737060495340391905991223296150540187759988692141959132483141323121311448930326451440686123653691179038571879920090921613688465049603688645468624045902911075223114 95107311425492549696325937003113369372066867332789420414151433847384582498677304167744602093524809836746293333963652122153566283925285395636060233681253220815433001220378876927369545287056608377908002241134308387245178276844501895503023283220514876802164331123308355157348639661036699203077311493132568898673860857796391333633035590149314189301169724046823090965625862933222342957194564769385387640849303979049669576170550206434727787 30928729764222923747241584413549448025652475313354811975479947640249298594773108700880239762184557343836322593455989282341858747782651851428984138322852129059404200187931035267633777062247148397000929991706096456165976549596200130625811722861612951641435791802885385873105768308031050597983496703021430810161582052577238140353752304346398427005290595739446965370459433164534947277993575237873884567325346646441760540816069653964414580 93257925671175512353814270194494318133962378780845563517101440301767933595417421088451956981933825751867302920578058805107238037836337436891573886455988089620562626060141492506395346684656974204277564242183829770886554569586105612482129959092174259018346837875793218704968970619378749264490931527105554046128634902295257009942089096269494396689132928800983810994727980586512997495093956208640833582120328359424176507753875012143856877 346395280420199733213083988255991934111654185282488913627607239108934884682352439908153269911416430578859941691957109844316915872795133717374315141023573940104358753889199016159229840943858200861555018035041334978563567859586372260427448093218787782021838588705792903521241773223941775229187380601226723746352556606807244225878368889345149804421063054914849255498172472049401753524378094004497829992960740943795135261223119454064819648 227369383466382789667435097167221754117313655142217907193675118017436217445344202197283422089810441454206761068477688268763722051501867127839455364485205877887479286882182578000611977448924085110962176521170079188141691846858551643513683449795286162391501224276879166384504026217400444738175066045368256854807883752695549087347262703561759917450587872962814639387303200556276987198753487378210659614705559353723247501612974046007522838 -55268398298213235959524954686072998954752755228643980420550414599704800156497076895015706522465413610177428979205814343555197017505145129123757526917749046041880864953347434673238474491850455731942678554780371015555128073130160436433529989325902996727276531256765956552380728024650297014737769432744760479441696913934602304108606444899459352926309387342418764720294243425236728183051211078242103667539344950457579601541712717821407935 795709148278359238723264199739543234965235134569146582015382069704390936322948804668873095255116982451618697801243421031985954640847224017676376983557127343030550428993702641391288536922124930400990752930667268079535737241623773874668947958018242636135610984604925331946884140162965600848255104814464169139899475744188033035515537848048359668211851368958887511007845338602477026498956130257616290205068984841479926320552368352942943694 1575332031948920402305333771512495922406141012083611374242738758854069361754457814939632942435982279077527874889129507907766570445846347541023968191331651022689730213222722822083345425659407619393695874085486448525958148871986190577497681683079794165244408352378856294419452253732091318412958151042368173145832225032904435160943617310778668554855105447719847618014610883146062311538853382431095907865549459174728189937278403618881423784 -279178881714140181285315197617628451887244281046394270542156763142638901054519957904165953715197883682871146258658098331633007952137711121858805432276817746042370567508078842987251436082688879620041302395299290207808724023448341315090933105977683741485960889807734588543315781424384438977377267029135761965103629430606388986214931200071139795634608738052226863512897856315321447608476130875612409316993238179352539572033222478188034623 -422236622147283181722463937630021192260509182614554920602722577889273552662589730176776983522549373692773169393340939635941242214163491279567896049828918853063049947641899571308007411985907822257953424825239713635126501269123104789865991624835258973124964699323369699260730497425934151803502003932275949289645082310085495537256303751288502660699601128117751799299255440641403260126141488322033675968472807688023033461109393284905186397 5675241172225810275861509868213558231434022100858191191171705898509601825830992280658476395849125459179678074884417506169662212763621983327942721268985318166045408865695703846808081067014725103367880028697539699913754430290763285506491642758004387766565745994559463476812936709446164047506022700509195408764326250055731420649322153870411606862236657799818431929866421245093089178754794129419908888176758739966140704834489419272078857620 5277350426562969226370336633994056969709606728242026866729816539945164129750474084307374712147541128372210308140782239238143940811298263651919184451736807673528393602967711835919521277532774635271266379890424450222480819175143934586775075696207075062236104941358266007227632439375270769002882181950544287170543241557253487583265441169418681581037586645843943018533855031877573575831646523587296589154730414249064529705049890025209181408 -7324883098743778970241003484533615945148001230602253612113545819536490178399111621996899025524649432455158880866530980736771337529024559953977417614741788677980421649423285942999481083301058354169992823860831199764617452946417105350881325144356532575545123857248140982799999311644651483840393068807323518215838636395574071033718931175632892469437048663219033350027813505460602259264732974765963178477053821355362124196985241496697330206 1762858571894656212758382989803786081992250648971123484338808172210567070789539484080032017516515973714246009360984934052892085519266304834452619017340808208665229594447534803819697670149128070521511487236349327627050452939494399807377067114953049198822590724607211118243163867841398117266626641581726696641621850405183273542155468202626241589912206141635519724183548458054065164068008841143750108782946886262411891259965344165967699417 33938996125232040464570584109653034532416275640350826128295237262960993020818088883003743556461260529521577987032358237409460538918908791015368408355807164398418478385269338795284662690943606890713830165010398409915652871578315364516761459389178937478271173395241284240551439402948425404661995992567674235116509770182542204614252052140745970935603783197629126367050251106977610667019476424229965658235460140707830556384049479586753514304 6816733883892800344244333953947671997177136299135511804559524800988500866859897735253641661704604271242247024085745886661401035906356069508948598278143170316180433536909402567589229714714018088488785371362994800018775918121167921035360581071000366484376639264418785878067738062854269084109309662241450397306102765141658271369924661661579405877970729106241957956673336575886192074399807221936256604508597087720222692007663325813630757248 -53274283252343332137829472337966874820259826798592950928785332515541598561561350270944468463831302381583447212460343194359229614601778217596842647220856362710872256868979304119862180624126010857144946741218981018816952514752053471305704691239731690422301036976745912729143391351602979728695961202653184526856840716486949035220938457500162804300514691399603642954281301186775494862309887576562650306037321897702048754052177896049545150962 42527904137370762300189928381775975192545175548500089419024706627088279396094353358884426590665931836730828640105336454813173826629346807416461342005108892103373705706913927247299281600789321120234884582325812453682746098485134670247173208527942575070161374117889473304693577928507729127795638614813529586045747685828098443108590552193516126317801099707235271760729347449132878345478561395668443377325723670086757368855375884124717506010 169176087717125748789251705052814586295602377497443016434523993714466519807321097465600651300722462951578220169319562711406471293445610051832598362984494122515996676193784317598646834945858693670018532882286072978358135743906179416579840015578944246626108043904088685166320245835664698418523420728740062128136458331360995554468681230939226164072079542357701399253573870998492574717936098304794836981474840006715020473146513652058335812088 -73417980795858588771965359530701072021178762552349542514419349226995631176624030785958684639138140662071339348314923801483503954820027045337994517365315558780066493440783889193265016554113301274268872209270708339187320547463838531718749984114925741301099308625825188556536251144062711269123184942779106181428734560197472805524286939043467728132270239369102380729207214832856416531040949446378121035456569832056967360375046838199409504074 -266278079214452643308033810580627958233870161746667773861922320516254620503145640767842193536151111253676125060889410920160970797443503527690197395899368382341866946948963853315875529195357832820865657741745392636837953157026972365241592594715593100805957583183312540796570168905934051093883325691335377674485146447885168442757537673570268253414556622059510709003978009201034477009991405724693144640507573853486678828780586292660732522499 387793561866719253064660115823607853673568556585746192375923415927220528527669675584964188111962588498617487929279385707137302647206228967622840699681506487538042595161590146694747867716972668476645081052787536714514447545031293099864631474753239782785673213593366609770122911330754429540332498052867396018742428490793941352849858000697620470939146174045232364152490267074599196318798376907122868566915236408564802118239808645173514497446 685985531338598868768914391867807236410856257715211853302921575879495044444925378677773642383888973764511593896508698877666398324734939425225307123007868067101898493592450080050184551601850074036254959175316342051788869987181710708301836368187118401714639416450506761171519165035539980182776965571413688665698687847025804054867659225264419888255991571998742932316173676833006792318360879678256323294942805534599766426193329611083514400826 -813356769611236868952816970974994274666842689575936229680477362548677589709193740360980051139563986617088952999574482878984691780007684031006261164693917724463380797467853167123177407655849133986712251710504676439802299888328581313201344523925593110269703892708353605015137676955557954268624699305174682942620711889004890079013148527517597670015248963795415175692884131541951806587488888487322094404048216204375195926425445342923481174924 -968746242567416446841313734161882621920041152201630811412890213381337190573077408552173804224510409664490726029232743562168457595466317640830504068999950062322733816323824474153345158536927194013868853987437613004844275890792023151476409687561866261469675478426897930041986283370758080683203409483288344162116991900467906584267982467495847092910878766175189914772526155061311960096038975877605891860811260594400934095845641506487805013664 2529798398600827036663494466158531274132624647187369496248603372892114279494362843346735191307334471418807429841149183730662680888228417551738312433595532103692738367888880072749132697544733138865526329675098437021003276856867013988786834866136032995639759200125647723254527436738641094802581407272837478702145703464833550129906209673007857846801868327417416323021053793302177961046704298169525353035472874074994653150538983417586558537320 2066786236659004598164419734542594204813411554430501272563212966499374728006879764361680282130974403125208436109478449015868353433590270007125056970671863997623967068354641262689978483850916464099415168119984006221916612379450368906770545258471530148802672089456540751590200251561328243866237480271071846556094886697042959484846237945922093864367341769254039786215159111069960354998993081245027724904759808629442210286356001315554656043030 -5284877657743701330159107505912334677362054275748551535689200113086286949325010377332372654363055569070698317645185921576722936222474861898754307346821725377494207608690252065748200626250544948831349460346409416931657074760959198288603652953852665981676613162236144132462558287918016167999898753772462529097194880471471000408076820995563338467982849373428770786738908067555308961707917212219559972891841665864679820797979971908185922614454 -2000460829097137475692105262162333965268624555473903751865814890545707970377293494575228147335122291118781754864753582921742963462270130738124432982894910222449047063317826421316645965000319102798428624332166473756484290974923289210214949888426701779296281015096284127406491127889801096304170088992679416941176435197048652949199919954231325946128061824869147317793360457918127894122915251935068207197305475492001950329943605659218743021382 13355930346657859474017344718012701611652144612615128853271119644781927289075266919666116580169410387605742793563796915882356173458566226666070142576638151437849502711420655252941487610653616983511111518347799411856054614491275413440372965379580961678497513996550788404336203431825822990161429771591355642042027300202757953996304518144354690604559102478401597202787026402037553587796023690566332873222957847205906119168384041392358748517200 2683493341496254532615981421090486986804579009358039680701949746949950845955920640292975108993816153558013242814994671923641471662079593613375477255476509876843082271959645715687070099586550789872140232057155381361162603377773833939845215595515119036257674495784802099232889686605279373002090462874558217968188018117996166225975248296879645856271044955808604239120359043018633044454881626946325113201637318828367896015150453910667136404554 -26685077354691803440169107167854886729974508877061763554728056154005267033741879036495128247065998904972022103474859478750410313571289599507152379070307022331330749617702521751086017867089451521678241975647806181439860520596136953376454187338945238949445095374301921210013419513265280912641600255563820299256086832478676986040463563477062789521560926453186223520094355268416714825022426582061487715744972971356175347875977889676966092681470 4479773372344656092528895801673480051523962751365695090180185252839070420238531744863697069322328033289650204562300900030814124685242380843793721571271500031779418340430785408082182930764634758406080877793702562838310247378626419298901862430547711711671099947309769485689041297099887515113406935977066592927389643585286221581040226537030981193924728010084785168429399966672399680465380660397546072209005663509873415274099148153091957942644 59213029434017166877339684657478801882451444134344582343161155798253093102857869324370321926135613039986866996659514767732725220343069759113107169735179267787860124071589138442812543592164038152711844004753122456377047784274852203212547009674908088705896390682955778684018083864604889141353832926864201577967205704883236182961064003073285228655654041457076524195749291787696208130906345919275465040912919591067462975049577089539712481297530 -19071666128679629351921754531473887935918618957832471123497832095829927844225735607565228962889048235361377743529679306272312143143139438276155070384150641820447955721674329749647681298473522568347254417691376633488439340924784433827953917154038074082516741638943698627184266847777520443578640012484454019635811666426762427551932009875882194156645507146293646653985991868022001410361435420212663113211623032120713624479555038905722486756748 -110598071888637817367128179922032050237147709724831639569947644710142556374587274612669779859622975295200633372137722465257780582860869028929825515036209373093465653447186263300756856159662965657958607224380394005967734125437656206515896827240349199015977656447690583852503073199172067225781990668828844161168455855497724777304148147012112354379439509863009869359071951110545156356436539178461912488724512602087782770754585442903542912678598 77170148363407180011566973419681459034281721250570176696360760877604884825791104807571137252995148912689693133877616347589877399489784135874828992280770696275647363147553360637499031720511225753239486106020033023279220050049257794749353560541526789859492267758827135047056031434142329821025701502346014081190406948500713367412194273786371495056448338792525607446087908670720186841241597925622644898523340529186730024869443497370395169801354 219477272559870319682102078553830572393529570085804215707328292217069569943217379590323766081308601211773284682574571214814745535918042770190078027783706293329267081154789791838151773939809096965953529429320205726321974536118114136635395001275417053674652886978342468911051847135445950423286913948554989622495901194135557175372239865172953771257927916694000589894765672275073479066649757277643161280654728688148603274622341562457544717016616 -197905068377517549957370860582109405794165111426996525757216211570422853133034147831005570421731996057596916876431689114445976891045098117419239979222274661733258039436459009656845016895852952462096434147153528787599179064175133658099772205832396026224298060893415176645037955909940877381375075069333833998151800211182439415216187111735974133079038572610546036425010122064700970538172695217018368679881773417050664724849385307811725979970136 -372674066079455402256590216248077336106490948815664269396508421535046066037832113444415110495312039473775790360546064341604235165847973550086933159734357952870900727026564493505509264239627665147200866416597754866199573513632338905672374687923533350398971430673424886720129572903390188588806492035205651953616709079677407008417160046635513415924259118620453153509379131730621117383767202926784939013249916076201939492220828535449067123913562 521549855812104549986297667001911354118394710658977849965095521076045498062605522178828862543965563313429650673375799745666236624027837705614474855995579369364057598934116128146515208253060124342705246960563639732612551251101218525961370167895085992618755821249499521676635245609254931896256218538388607350129688085869554827288504414296773879259644666052126685510352119110859557618333379752701863965878556899793184215095616585398909794554350 646570153890226992914847628046710321685246343186321426031145197431549115610836200982937502461675178906318076874685568437970537239649655721750979233460802110991171510364979506969681783154808526458790961876400046099902405144537987044112897920196674567634823510204532009227073935516546381496064455866041705429295557234977285304198011086839230021601581115450258579003015382394302404278960864739495483548764586851686485442540256600572008794247245 -1158556154942464590109388487182484997140678334875818230608349436744242258908624853474364720886095754290492802192450290118849564955062720695847707610822132924583887665165246298901348735240987573054435360337134131001693975651287483380179430499249879905850237123873866425209837363133559546231286935682427232903261091940134792895746112672024402547220022925923552553689734128373836036955388077212515453554710435074495121012829214959703059457632548 -922466617757962367131489482457971271462544940694184966009593542983201765770945739169721058575931170193259766280242080601260017434142831048515508307718203176615815628194201124738043188202644267702858747162174466059014676203424200391278704581362720176383985106465999984279199976884413928168703523482138231300733817028301956994955676515266276853598512875424065185262835141731318122199425583225531380672631623597304250153031173243030892511092096 2595744361374875440995310412736133570705508571126183449307031396630277960710954083367118066642018282105649783092478564017571893043881779461647864857065401309039870587581091222850448936385069512635867631750073529882012837889647976121762291178553582499554888421511723998968939376084276362927697024289464293139234364053176278738558723330431183280944174925778158301856616495093978712603715450302505928902584524553085262061018981452601979573998959 1222967254848870658558045144591655042089135122331663129385559729431244959972080235231887100933837922260950422019983597945451546391810101438238022349859319099447627137011647778601119007746889041451491449852783750709941782869529277675326988508411805295217239585748998748957461529028030179146278763487490181390549236969527801989807031711476429389358760608844817908696575718198384072783923634869157109568227970112492144876114995119382991920552245 -5244303640055369803514812178707293349896446510411774799667285720271826849944741865508549366864393480133202550642540144469292115184361060292792308985319875188865253188080665721560285186035075529326695154720696420462468924080531325064751044705469352989257691374132698497472126457624355060470857245635431489392550498396749291211976257333616997959394418182367499382385909445770196127768057161708350871455635422181341780075487453580913697863891526 -845070755921925604351436833597475866250928319030113880705839594979292952551390297078559594983054447871450402882561992766961810921620194011714455886674386228927151329963549899436519199088737435709429134505536482881693151266677769513756115289932548267085245029990065731514476510613602824829909113228406654027934390149900982645920188309352739741005830211694846281552684514051098600821165659738505639434412189499886330799363951223821061342398748 10526344383667730019241121199734279183689270653225844363920274935721360072598570191089660970863176898851411759775324097457539643709230303230455614699861626724158735030027466910621493964211377320554787707110819705771325030514626159423856285680780488200334500372810954166162296603826980779678084680325880058470668669684616851894007775326789337577832905265772917435214359353483520825776844670841313760667661871128824386288814331132770909458646954 -876092357800932352318186609861366440017159726474976736536628974054538086570490334487735911264385513410911662075573548649437804055089896810688262916929373059402927958584661506534529703248315520882785780150068053963105845159881849126622437313379016116937372082989367758662746241625165342305831610609338583760817962705427784306678322312878952721711879797487859046808515815534923848514181051110185091299695447325907231544413552623536141700287441 -19546759028114825337180465131141625405501094293329518820620411993978754902461117134704898417204956056015142011757341701960878874619398828244321160212108320742181661513855609842480894374721848994777550769020740447593075652360560052551096459868378193147818101523222726989293436321463808234230701044390092475511175012100775370830529327620757351168956061274177858476189361887897652946292981928912853515120203054584086508862222525967078805314202796 7261124709125297553156366385386947257547139745651290994829540754044116925367546119310216511404383717464673950841589995705754941799359801214248795644021066012577395598336919461947008760301986224767740691333349167026422955363309387916297403880761034255826747705154216235490829433777849636910172055742478094030871667944621526060563952841759337737149609233968041001518630082593431154043214667453702923451268271642084023002192667290851229081541867 35514842050489986297231010581222875313391982887375358769770769771988379280820609873003224532118446817631712743468682566417099110869171198091890508909007129082980720731533754053342512160897982080990454253027166299110843648255299127289745823698021999167662348066989345072026569515197028232832330131295975021782235964027135306590766708339434125187169738673449471556586138599536914287797405430536431571320593587197241102066224693304527076627385712 -22452935792424834339199211390423857554993405863396868229108862227617278720705235983065363473962195715058553492252045179250135828820430057075163040173164835219893692055698110948779501268187662348934792954466852679435144709682391211437148295383837917752666194625421832616428312090647634981947353947527717522626216852892836497922595466952885250588175551524032332238776910578838230239231451317461868389078498539593168810077965066876692776964382742 -59892708495995524207475813730175631623700948016815666097356919923679453292287151905040632151320908125905434434757882920861411335205055153358088701040931368110106518973212075096341016480512230736951156923085379936484662780353295020004756033838653454563945306363426826043549045543928910138901981796284266234705884693539888556238622710865761766159305468960573195593950215104166376806256961501413417394557226580421297396378289081728338676278319465 59316802226841671937143884525513657986315249275496712914906902576954980837647587895956117486513221885248909671900413524293209560425942670618951002354616019450843038399390596745965995213718314488056307450472559457346598941669855065177745106433560803865583889680909605372401268606940153049060870550496306931801830575520920309359330874840991683149772643161251673688890886578940901063995210940785016893319911295586922385412878552799900802352524857 96824408782025166205682934981291187321462042822681040763336284531591908235798310555058928193087937370944726605778081952272509934875237211286585144807811912923203519781962900334989752679023124838985551471623236426852544258113365048887170230390759714292492824424971949821943099586461534350251372735419729902817994881368723422657047754245746532234806215244801434700519805043671828368075588527291006609073610663442186696294145806072172465526767599 -135463426627923555707765585454064404361162755007693593711129768665128109825290235380767465064741105670598869231615467314308469781451239937971017199778163106273660972416049039844763918463806398179964785614895335567830269764897626698826255924715593860872268100940488318414782880723546507324366015354965809313600278111465501391900407641019222774308189830006071788298105069793753104576221568089787638191914480605980529058771323941272526892765565870 -139331395159993283196733842755379167949141168128124126011602162934777859810489639540314903169301107642981979361031107048824647019826548587563016805879374847965935888926811438463144736606640424093102881271738937487095633713754374083641689794275623010443050905457228498689339132082039604082396263426729667477617730423852789476970233340507765837493873818362432040340567599396602370043445773220333399912774672566341915036438492352006898342338998124 291602995330588341260294255076280404378516348795512717057145583398222466033906066996209216282941685166360897837089517309103283590991507657451619968390423154217165125140167511498689237011654492054914948292954632087722291504460612800089903995655802264461288688372242481436040240750189871622668611215011113056310786409008951818781501225948872499246863047973641060760689921939420866231122404669401995979915493269215340989532376236179516657913156807 177276862422532524633727280702282678230472070155483999691870437496998678215764564575278109716094123754800385553448608150891816416341491314512587938650343970614712356585924905413067391832809802022716903711119945745577380130808386615529646161614799122679662615371942131193111305178356846177587426532827484902602268529178643874183207351994485184788194834287472783793005543586259361188009458990350625104778779938191218253254898449325586990908174422 -584799899295858077267681248604223028513648689031103947485824030691009388134096217378019182181221232169413144656965057250760554662839673793536808091881276099708781152422751869815840314505226851268179537548611714194472444088210479777687158959392343027741917842009663103894814046623476641517878331899492765536422622276038153307661302666463183541599790907649477020824544002483618364310595164285917613579847701654225951142162244427240908332118113861 -145464931372204336795692698454986679637774151357600010471951542584788071542463396323350694419530344773867666087099725853021359169988745469960638829013177903273287342049026425975454864407110693608644842049620347801496220870104951552860651867992966951483759374395801278558243165711358668517577866141756420581068301563647056200643595062851778546565924145889261906901737909613365924126682462322934464427996527338731781265600752198407674619709578264 1117776343733804710655933314372365786196094926264525181641081208554568420412707539160185274147049023128540417113837327527588757486090178037613430069073212440695883185892825691471246086268593432946642415266910442608471111461999821593383266463388858701290532657453359643726332301600908494955322144500187794141965944779382007675544184152634327321862582658590085392109535587039504990666516376740094556216747217131571738893535266570772492737560117201 -68848611801162595489889968356349169857968355366240638429963159454265868368225033915645600295751358608976985295086430188064865903921457945156627521203190546086129289738411224351618153602727598311096306576814552421560008005706706540766776030439482381230846618112234704579462609228121248770254696898518758396246642346693856983270160139749618925639090132397036686228726250933727249378742766701011164301277651991206428703821032910517400028676394905 -1998187588032747151582299622966279639753693082012396302399227851714781584810790189467504245896795433556013872472463319091811494390822919520272430420100013566708852645686841671128014098966750015456441500426215688866701780716853019422721363600041665374433381227607562025741777250039611973512902152735077371721558158505651802834885418546494018158873680374708547140346139203179552052145349761287421322042177132075108770276031235953711018768846445873 763621483407348070682502062523676396762906669516339394968185619761209662334414754561730891678659392603052016760226678795870804108645448253055218913665656672604699848988876950903742461816800454958536188335540268640151330786610158225506147177455477742967933429481208626527158147108352331610796016816648933268864888833990049456191357018302000105484411091132841049022281506340228398196513663032679468258961005636856010121443779549602506599596347312 3386195677974185300132045427604166054211769042910345016742379292986459615157917730359513870383427133968812522384225789426112004138284044472799622522401770904280674082969208307709707750170941057481345419371039884270467087046444628941229684534385531689964563392535803775986550446581430909028925023015606090728500826742295454012694510829973629123656542016685718157107149589260263598936567281243217311820695307509037949388037612360813724000205399074 -2484043439110123246590426795178379486617195515341085792276964729500975258677690377244297953741959149484254827748343683686629305461629251004218434399965273713087818782946183483314775036600785354600335152323917492642221949301046696647159631841383132287987787132570226406344295977988839993105775401598948199728617176185009224753103673049732913969772413870801485898781464294233855705476067697885731275421949472056303779009399660317329282564262619612 -5195476483287957590170870323202616332587245862544779154535094477868530545169613164468121329173201804276260750796050636434195561157935832146242386483919803633947895347051791323484287300998878497275614839345908729809972288797350254538728153890330782670339542399446358819582180876312135560735809222897348247568216755080220730176424804064002458274531409723892288010172533313569485859719250016519353064563028920631381597260350422972774426356818285972 6196882498587105511423958168849183269117766392323836547321665764440432946658202884041952036484352908246172270290037861428270454068660889970291392220490121778306858646882003954638872645656040241788783977230306520213767144328474502990970773095352514318320083090231833668511820040613076185255897133055998125491890510822820172691785161772195349497034940391961557445086106848219366115038181370091556298232925939548836591166184448525362384102717843067 7175364106082493106315976196214021091507969290526863135665529799305980307824395764385811580235353108164938749523868037431115283177591806152729847182865967363661173929647040423359379165017655193392831997947550880531082337695748781259814728225491180689167915516520217023837425692396928565204418496857084757039108607059658569387894992677480893701265418385191666548731017792167301490674688558342572114653891387359563409658243838036286904763264008110 -13448337395612513495409706935428976337050515143672461719303291246556537500173725937479605135248937336749892047361992307357820632372329089656071787973219529760944478316783210873102297928347274453716052599117437671680514808861723181753655751125892260823896888693558027058525172757230348374554592099109569498628444806493006380856727253640811355584834129639558890085505093326528507437643047382139553422214864917809003874408631407940042971317633706219 -7891707160420020682991364594465373283535644556749063018426994754827439966624620716938038175722110569337606142842123621064959158214419251721623296653187760283769930343997705099237208033829811068572659935252138104900460744095827344122818346668285215501722246593254273114068421388496791463014449874729613539315274411058971428017130133217524272122761790906387866853356943809186032573292321385054235355166873101329817987011810713300760771426297047887 26571875665271279591481087870183450545131111811388367488785343050107433572071494163980198148230281629406470548788830309672186433083128917219857252898014872738430129343528881902351287004248897718166621458302239758956681822764898926090286553112564397123234088919591938970846985998612903888190125474334209507548513354345200247575614281841231629562016043261906293043084121059707878668441745433338977863311760314197987612809243971300693912813831403152 4135943803410511005193457821799065942457804655785908532160550524047934439049814598653173630632127494453234976281324177968275635969085409499538496961287975567769676047138062877157102700920661355733965815953633184845955591060144554788279094332778327433389266253898900626654885044473933148347446618210638867315708148799191410505637209522906581159144298738520631657111562716484163446482268770041360441141496336833818956343892641952256670866453585491 -47336706264151023378485436515036347378804363103224715176370643085835445746323148583478920487568026712688282827439070805792013031927520159426302435114145478480520279882640543312890159597078553585367439731242760320526426249720718033696710513640920090142158143093003526439809238647450452944960083095791112836583183976909279420415759222486120746190999844759757088401224717883711073367796474700075023067294624675925244070879676592813964407692564053291 9830554739581157748184207579790836401020621640871103981191873350249379982220587323484834555821560092098936048957725645317763790045229759718573416840288287907235419793536651897094659089525818705549059186026057255655757466175644521185903950535500261816142099854240401585838734154247016175526923110775013562578562872105618209018867160682239216674088386681010764687293422037144746810060899677423717788831727691271990486676066314321859238857516845868 78538469531128148017836313602562039343162401634849152362161973973060474690670256316253084441080529548495047080548328858052347056519271753505963253451180194276840028272113736384587226335248941901979731843954681961981832008370722661882364010193083901029113709585224833130858747555117006572962205495980244381303536542151999367195324368483714025815712099609616222706007679920749999337245226731390688391019157152502028988124910393637113500597734615161 -45995096782031104328944329264996262045299049863591334454118205058299333951701321715120937060272745598103577244443538635388583825510359640310004411891312288932370460390451812415645145957503365710903682060314656788636110150735851050137060919994757629390514225544480439727138104219549612121322443273177712673913263857621480270881810526486732976675644682140076052030391627749198426877997611494082943491916252944850862120211238864386119493528713084204 -116301416341245431165467110923850804487333569161020905163795044932392435225896935267376805004118652563465968118652943594053771351508216831226846130818960226688472379335167728430273897433605675257989611098068440760286543925517794758876482331716767208252337943271090078726684424967881110518288866668351988331349076165325786316014506953007759211937489382200265292987717638136815371670776373995667539577102725765031749761285863935411180667911066051641 121064157215501976038949356594407716799484450878342485886840433595124060469179183186129974221092426062716393989415498318796763458396575001063410637369285378302864428938309081133700390273518424229235394340387061104144661440085120482395273999058276354161919671468408446112104972694467077474290705113183071593889312077124695229267837009045878603990149411674856483640319927073964166216813271404736528128096589819417470172993833417355289533474129096958 150249119724642821011257338667031030529270785570538944831495195961390323990898348730621889066623333383131303181311956230509936210052106615421805844490536677757639047610809466214015041840344133938492954489614940434465460289745486378250070459366531839022661602625849457526313399763761777473270511002591623855731562527449782090110064969767571712020881508950472090551438105114685264180477040349159327024585294113286351411328804366647375196970778212339 -253955932400730778732127353392878111485661668892974649260691585167016967811604682672365970830147775502307214290416415205091655943772385912531367866879855236082738428419575216893069836162456961019232018731779168531550095839800250149755912356522416359972532282916460817572263082724440719160195367723068266542291834096987967996429889313570022830072216427140970979160681230187774761878045151993342007293919380390970101211085915743046558456603090188229 -161535167183754950735212811481896228717386778353892303441568202074028767303636701459972709942544390814311898204965311000461499458614467644847374108544783298749804136664391390424963745537123004820512870784477417972384353719406198209002356332336875236273343755889867375961627760218744877645202932466837204716537031266281929200263716181071808656623480515848019069595697581557761308201219706651117351822524906352609172254761306832905616958641714244298 483799123613839590586139230034932837044423335060184046412698323735711656443653593609704102057263728103418757420072222347883296145406092959304032662444025324946492939701776317651534190606842807332220896958472995403771564348079732084996142610416321057952431741478442645027308983446477150740883661794163456086162124116601766299942061860400508369669407257586637429804114913575949256320682381637058813932290922404642804721189826619519681376491911524343 85901870354329809842830283835571382652665867335720068250146738063056050004971924077628821494613851310615388317481080591420714352741974251777255485466558498854114619730483684792539100917458494272301144066952836571652900502587196830664837335837251311692133368371023633022379091258326003648081981130318052536115895927481398844031528758716779597760800704173871922609877429577873822416287021942210807890246686181351210246166445370498138250030479934507 -807589359108132115728141631840683184233481268495390058800843385072722063553133469477706040236651440793742287340702492119411556501667977125107809330364716417765249519940385418502822404297321369886884380314389687826668741580487349123541668562400267679660955653472459403131589659618780406979829862054494810406132027377909937293568017085330836684359826857002096416687418199866718529558531135706111113750132868196928677382853228653573254152408166907420 134463073384048608016083998079722237600065483126545922069739990274618500036095589651160315799425115128748032419590877756949594503859705313153018903556326430883921898383612739960664588417604948605945889807438447066921788602777837779294896372652348077130168241535447074801385406237216450501589497303389019280846096483135991522132009614673454350952220564849493362374763393172970893588663770926616249203816469223610173920988072670623272557039143438817 1245853547855622892421278263549948788734413227518825650166543744560349343061683986375806680137287591111780469821082504525480111197446101703381948605743863367487256628751431013964093976634919436099997580257276527263672930783647578497598231378442682140194728232318542546507737521714393271431283220039014196978903520965528811446890189572888229126682794723052584304194503462748504374904760540392800717416385837744221637358932408772686772846643234598252 -599372826342004201832424882652909883717316876359482397180323933309936226355066874085471930613664730299537811424597783186805669393650372425916921404517881696754987150660605756892509868062761111788787157225586107444468516144450870888415787986863910075243914445841607528975662214619607232709386521343797277216615030758373307341157845469793676528395420988072610065076802770877213957119235244555432901249038136573580811413144203652187619944474653302197 -1822111830612699331912704555560082102203818261569714261303202289526071749495790920373735018559909385703211172459412159869694467900640265329679826127413451576340620003908795195962616824188723582625679480028520314498896545696287815472029839060543245248256397329366217573450311045330196389818542934539230473320442280061367491160549976088652357370775379158228388628042338105140864696964730208795136425534218405359944215683384089671376130745325295704384 1578261276589607970634679400098436202974229765034959451963859785640241577265361804383273080215159355805761132967221207439764485018399564572584913332184662414608559168627906935565875430198023528885815862893841376114494843004547131097324272098906370288467617083906255298709906645093847354115622306943356276791861331556081619108865065160598999815988789839874593646219893966226627876016720942410456048207365966429717539717040929395096176973031973706617 2284282028159538542583997747417534771319470716076296177311040077794760068292549343234713721217976729521643442898637519632327419681848421384698588713121927550906141977280869161572477730863232026658599197396376192554024436521213312834256672563928389924518989559225479089383943209655111056618753185638200087728227632559125322661559306310587220275932365426220367268865652018941087429251804789251678519908372960584261180970368173096518736976953730928471 -2972436193793195541128871338908871533053901276662858145645629087408092211658709929490548868014898428983371497254094437511490249123380983712524016460610374606819305061036123970013705227989416331424452048001205077135691009488764686814049734463849294790726519395467269401837678597641943848445442416637531986310205133817558015345322366083671068419959056634673774472718407873953258307075896675524586229706647261684679092768427819954572866721648467102504 -2879966246940262314041364610723075260439982375614402562040732803078538019217700387270745260257758822512033577657580948082291735152959904649645976901847407060443125585082795590124081491515472204516070937269760350760489358636167639082118461182387883307963792017608540217061202608885391006321427929180502398262042774960299895150361870808823389222242438810090280117174460166745072153866175157327668084977942989821744723944390176627048232745236237171459 5437152140194845023882604965816472201394335303405682659768442512398403908608949111637544283814876144744368978979665188725269364832966807996792642014003255879333227766171178924830222728812995094691585939131090172296165814574901988729324086055417628844762811316063084356851076502535349375517548936855669288093656483128875882324523015006240568227647666879852117051975791421311724898736602133967077794005922873505230064275338447776418465844882495092917 3275755690823136561251754791381664652543824845950183980809575383131114573250053473573573047112088673428023283791104671944525676290361830283292017490894928656543669909798063056891062477442170255694130308888438321384928518117810101385347456879067458402483325108617480967230413593321978847542264355968351160836522361311227922030363544716242679805810143875945506849649189132268727558580786136959978429021109844453002357989286162008876268767302099437239 -9637255411828577912412947011089506876432908526195429324249000257137932308607775729436238772971748435009798546304099834162327511371262701761591552889112461571340268417644033036785830035403144316853820094946736837580870030670880436525317436848916511195215765496921395913340979976846081197485244779155675678387989192466306877382802379417803330418925044192457749962703036259222864755964206857154846364941539251138466177027385865805062214672767080003995 -2349945625025945413452857179375978808398759017071021234498554891476624635669916161691046815709496905361434336603979921436558925485405771886619281490993873697738041203280438899653975069267094347616247846701943269345289550845542496281423060464359372809025915419905613006420565298147482890942385401449799395856502199341276139295713284368267016687541711955021156835949076418164851793663722153204432564364880837100490201358948706004455077477771939607727 14808015787664107249066239464046989904786181691981733384077419105234974271712170028656946307554072533197887017663543914923857978571948330073607217751314149707654600907343472762638427292110169468539602971254369609015896719987244083474485316091401820075790865337159114359869498960199111662645603259254637949223836672537380121357237569770377700427909484140123008627188982755130859248297056558848740918504285159694167976757598906925945045890470106505944 2446809355221751183724526254424366687532256899863070351551779279280181524376967084164662506410956518569805793213945588771965864085487225146310356246308569822057025198545080166203278319960547795365379124163463871532321882531148279795699821254830652550842872913979123650937585530845440025142731582530932363141684780723785252700175227641087500770831361492043260393816598080185698099802419587768330947199755886797744389999639095029089572182630876790745 -27153518846124021942775457096569277927822664419116003279047487374430489412909344441801100677807495084614207705236372346104338525599050463482844909459055161487431767157541169849451309620246080388001413507703802212980550959564814419379114372175126318015546248871083646532490621634669382212844497482213036580275590018860704225426186699013198647219245669259012293366645416097650691011256157640074091769509827570059384086216710871321747673480591118694938 4113240591236104828219848765289770717565518899007984302754120695489045166293490522060649548954878322870661497467993562379310193479028348429417570224074672844112071494205136658297518745883397487087674623704878383341753361495033699405585221809907238858885890965710357189404978494237832981682323324469364996966714502051631398224880726829366272045669716959805319273503024414243165805346440092085649028405991103081349357241881005013783870365990131173707 44239099868723323903432067966142911928125067539943915533672658499751267718070628724377138915617793908824998973611217458443391501040531206889239472711283479231825588083782437009265218024502643999695985405378905556253617844153191817700489129437607813842088908326097099369139473247511981609882300729555716045503865354847589059433066511492445426941274876384007489094971469400163881381192291592510863762627531377320768704088303359827426078083362316602356 -19693866672734071500298951443961747643159490610774366778091499893150881211180036670509681115959909843666006320414588331150965346938049282566174519028636786167639179407893363414381799164590518224941331087241888408632981359026460649637309884191931517958358315181746844586746736552240738431208219893153859098114987918550691603655211961617003108055909289597265515592367144814993698239449254649500128847577519224017620921582654905001772613188939475580742 -66434834393545599146023064021698401062064351357887454905556149841588450360424781351388356742138041669361423324728262449358946786172573381011887792899992245400463222114920446803311958390598751788647649872560077552220295594987969965442371860686500749252041333286176669428238292366629255149167287463736992908565577741175610509306689539465544926421843759915164354681179355561662870883969603509362871782198454679469588883518742526789871050823985452161356 44521909950143505329663759940517161981468561661630561248209235381765807298116000411603458391762142880235553245531277594835956797168135674257052580533790212058846504170887451576164636561109333361268682991182400065055015462427596406288275478634431069058521966800027153593690695975089518641909686751674738712558082167632803870926746278445962924502490335400974578397093962648051818817763269292840466680499527103963417513812652066832135216540068730828271 119321632150171524071878848875782209342486067573903456856047527967812643733033811035988165145036175644445156837891586508701517387685802776547667875291606762999271890084332976735691721550087089452431906255166216850447476295495793607256604687668073533572845461736263360537033370667506000296149341273377757727452136174668205194216354708743044642494521770408425650432991509423837581203676748775707573566192772143084011393685929075979563869564490638725865 -144040584089470267936425000619102821034670275921611756104419132875941919935741826703815494965082321430590484783488792497940228645065087967341878181442086326639182446893049311791358773880002840933664266197272288529286671539597498436420590547185777791424464924842710322583069627409406269514509977829637493266444902760783389592815496813250810616590330131159835464850539680108024144887793508829794869215997805971026564947245912473313260633796475762648023 -127017095830637007336482427224593947741045007544206291984362988631267448981805246440441715985087192733585543423840248506033818402955952559951071972171433694671795987371509939391302536325784063444274770546443609494482787067489312132922639877133979596750177921411931692634680209218141790546540598859052656148432186176170293836683619382510187480981013669292352329238301375655324732608849859515987183364974345529331803160350888817690811360825164931680030 275229660904896794742596084323713924314028117373778693302544223279692468190926503077954060846152972640768439574961366890744159431430632023389899671636066446791985108144186604669903370606700225266364539871379214388841388605009868741933363096462341082397307716034934303689049281767307143570953349401628293480503507379849624237071487575594485909820259733287316645359017490185935526965516855801794937469996640065535248043116627041007617752288982472777699 124444830042444619491624267964987501041203253541734017520725139487812924560568738818573422991233076686770450989492656417643158271842055229653894112733703814398513298622044328958756776464263156932993282037151713151606608246016886610462740947342215375342649838584243755056497935758808491737740852349407077162164010223576197885208624938679161042184412375923285538420850512312765157749819226077290904502753305792791088495797642445078759405809751935371631 -518592068907798646657643875343065626498137426603642303976965982099463169863647037770539703647838676866877377422642326931529204258875961031548229739290010294864363733639766954033533538824493048566161464906757106620728434353801289148956275859725169687498432960820255287700680372933663323823052125335023244922855715655140838928420651736641489224136430325231882875437753555867281668296517543200866712036961061738535551170515462562472732979367831217038157 -46418381239891331603770807437816664898703187659727542777532271358820436875422052434123167086869732387482852706354877755542365391674671733118107797577286101982348952981864455610985962463213876983758931313638375301038588301787037299785560763961622304770230673858142238392087732515491356909916794784323254412469119289784110704243535679996407584123010628732133884876676830552480359885263643848221711287962154108429441277770895893787274654132177590705858 1040992665505125080129414577810863587579247069621678936510498794514385428739505957294615182081476818616963384902459692563488179053144507912472664044199468221800985737656768969613825908217289956033068096929150051960234319996792893055795398730028501952272870633308587011170723618377382110332417719242641565565649585362900169585901938066978004171601055379747250115109589221831995483860428213918913048459916802164622629256193598412577081198108316269964410 -602964920204215863585097236940705137787818331617185429316370224956419757290099049414377450520943463385072076022854177087164766044495882233440822820855534995295557808274097146397034788873961095886578136441667868203961010252967055817468437147851241532287126010860413911181291044489948527036549457414917777521808503514679427537425452939894498433063922782253891161475734789504142867316906263193342744978941044141993739530817229293807621946096240599208040 -1211271066059208221829395988967396252998689736848671069976017325472670932200310893812198409256235248757591943100786166239405221635764674720607339922032832133030995585777789023856512160399488772050502060027321888744819691846884856149703119342722379963402061141309064988456551751013900608436289724679864781607764495531039097960158891670078327943117672659151026970109409583048229403429257871942764512783722420559344988422632419033828562237480639096012734 1270180546977884233725883100664811397726963007099318880909032115560701964502329186514984229388941973230372418929429761541856879933727765816539430273963106304080682626371130201309757054733364085236782594742676555117129393097233644225528468603506605768073007325943219977153678261059529377842821244307953144612985994746654765589048013031938404173855186169575802351438307080506036733665616803879088100903958795375036345560054216776363611036586442136634753 1760180678773018195101734763244106371399328390229085855914236127653528665957237985260716957039044405677266105416659902100805118200755255075798693363741800972590851919054203495241140767433724029315401576713328743030696359795364712095184630561182463095508593951664461358183062611916089433743260677930366719195237392377983602421286233928571362228592334790824228095798612075485096510027811980226276447730421955256383084214945029517971321309328991326959698 -3175696801757801139253217965731542036158605544220228185282434812785605524423972699511754875234042490348808024808378725991163564352401186323816201477523699856166036321932339857258139326608556101216934659102072022674732921925719559931010176209818306868072825496780959807460940920009915195268569464736978331390103692760050962866116688228750465303149566446913143686620148699125239939059184439664617615961768704050047832386245438504420447895631766345119785 -1528789777922844148079486076067964371437175521423329585214601599034097444302320716193374443185663345643308065266483256636259727998400981304732080569238501488130714733670772256094306022202136206497628732417149618948045799873466402989425241083351818800449786166533328391596666138338799750880504473291772302734557602506592918794118121398190791069372021683907795413286706279104981968455534392691690574743212263342502069915787429621896256175910381006542619 6717288214227644142030167105101380246286803710162890036837881343847809178663303513257409476374119772421046790132116727124273224767369813880033405320195926142796337798612583380715215465031440963158874481983704125884655505249250376934775361713394001850645802405005401392418030296073683266707234837934288667646703063069475923977517971687725647289283249052741857400271249238848738330627474050609410542885182676719019132520608049079245365364354891251884840 -2122783211747371986403305817842552599554071811685977951482776838015625796588778384480598040605657082880657378191230594577754537312488925714605499320549148237728604058264990182499549139164136792953713189410550646746137071526367832581198953203418444258583577874196189257152889965667310233752813910369222118327168052692575729597895961130689238387579582274251571265429297300775009489937503205955330565674719116036015378113651163467619525744257119071313777 -7839885468301154375585845074276630232322567166486755552528058840730206682519660789329397193574264161426836896464238215106626926037616768122487198885442683846008871923248788604554408475125442635238308431781044292575922611830001516988180804052127012082628536963051250230976795246394229751339441925299552847689027776059032751760479317806648863691168319185924702934589483370713749854935364305810400552533849978775975281594760585705522822763063933698779265 4267941135384614232078796842425193882599092031892105095685154813424903728532842256632032392697982659132545044815171027273349403370270638635475887107068678643141401315576445142988340153929749225720872386190222112908256585370210255666114765692446078312812343047312464495718914842615480544761797405980313301217909240735846827476103994388932693420041181373731044119507191182042815279411211539075936858846504358799342147896498949343397195400165018982599966 14452036582461461185090432206361655627051138199721082793748857423144631673988109695338820816278035709903282715122440010783600470288934213620615483491041969603979640090876277650178151923393796905733523157148537932140971842969197901289873090184614311484186331064300163051849723754520708988569931210657858931707150673238855215066489060117796238208762531137286442236234776210971131058225928596015037086408268708133714619851992310535656203614066372290674129 -17443903651427620355126768403385942427495344541474886634027993168774574704889141038257778204462064463646275398896494993100956211129980549089494231099912429276681797897989295716677312131759417601406003975148251840494218577119116787300497998233269488361389531626477086899137479135249771685926988058920639366507068578782112509757978210842395263173800127752091302908192533941282197153480423147719599417511805887828889448659250720841681042465931131568682976 -13017405902960047928697026510146863466379957913973753083649814786184406885648774080335319449653914105324842502043231713085965685505001752357756713750264252879501286831635738656724350831754775069454104935323342128946608043156778791602035539194324781493131026183994656604202804746194986732841096812341212944734014268511946543035489672561284617716955298085091983629056123660841099871398703789399399212671012690221323437301776220930499860957861540051551223 35666499713496525581007846635475921901246440741017155929943513958865576405979839530035537852425807088693860936606782876900092237522549087139273959614911176868367617046226007932050991877966205884976666740770293076535257404729225730315458525640338643462284435035091693057031495780347014610121545243979372340562667532992955512760033542452198110109982098865281815557722332286706444639918866662445469690962173992764480999831886303579119505544394359313025100 -2395647699970920364521929430575725480110325355374530048241303496147603019724461593221567410828667626598898889527345428736960116226747657883199964976162509767245223179414986847976663219265656813003417716658808187415937182331101004306886963565194257945911405739909149475905266235142716951853901563151361773707609844812329720123088161662982170376099993143948383358356967803436128711815560171442447730070880576412604828317897641809176466342532259378216489 -42188712084091179713916316188616635948202673059162460128576405436340622063517714858673474851958412278666114167411865345738235711406994036922868189240116599736362923401969505220592030996648298285601853583593003658720231106979984147161519503109879925713913446263023587575051605641872189661130750055074652889452618234383610362083982305014383939890047056068508780551883691409120077719561796463878137889501684734349669302458462996151188634680287734233912378 1315363382655960726733492117266571672221460679532005326146094984695732770602388693051875587232111684526551447617369423917178693390475268270607282387816132089448993890629884552213139653987022368275101125053541915131182436688388687752222716323362429070361030679824730688637022826587955110231464577002800096148294945959490871195041423341972984918231279813456723846313810761260292871551723933789441019962228121282024881809714224883021631409994074349244514 96891478020713310511604260632328454230436665349221709916894337382581851236150727630082332451862500260005638642187725613584178825794334905488109673140619916020320666550284141010947814000797961755372384837510876194422238119319622232739674123386284578427372811790918128610050949182514174844336953881092517320912781449017093910179041137206421079492635557064091482831966885364833599319019376790781588016712379031466960130326039442702723565091414264143047737 -82132071780063021846155708724948104463392483319160540022705495275894068538157349555849431461571315284117652614894404621817540105290880784404677004477001576111460549366149893335383086721884564129330762144505744916741666222898336381330013431620955205561041521903262769503756410614005440868193427631615470296059512670316821814531787624429382410483254092960480422108719277264885119995955646876087564825223618950026539975729448103959971398678723756503186502 -80271444180658289037851855241498784352964918346181364192118876447776752506387043137148626847441521202607282500014302084348756847081276315318095501200004959814278809239271054722017751782290683875600903066010204295402478754964169842463183901890359879252364655721026465740989915679255904170495621312196371315779184615951482548164524130582870996391646527490649575853706409783912962926529224304673199469593972742694281049960974334410546765255835044653464954 143382203868247862246007906306047194546614466070945691263384109830097741414038960784387515371906640950663593542010163774095796130263729749443408127386837553511423078203565184822582491069351140517483858243519380259564518970870479666207780413114023361258045470922996388965906460178886724754014039944213785718804314140163893358740511166338748469971748271510506931795356344723467001158764004506083303476913142623451463663272124617705709374293647660497032001 52675805105214737442600978199644340157236781497065238028736001458769254356558671281647652792389145680925776592210422246884195330673685975459294306613072977617593349695801010999283499306161425911067637133063461535825881479855636989694821382671113940460391023308801180742176423237598312269698784924963252138440946604870004814779428124119158401755752445322993773190630569382610067029177684210314905395277494895772931457861149906174881879806077390762580883 -187620630400659416331296246665470829956710613756231772922555824474870201985202176637377111011216357852127738508322570051846582637240727116148244329876823528245707170311969067612832582178552074657815376567628293214365375949546848102867415112252508141094740591409690340492776618871396098741583343631649368089171168837675607140342697566225864065058835689935204519146305702582891181904739935094664270721388814726085389968475314717418317105659952577884798064 -120364340487449080934436490022816287459299436554254184324267873207797989670851913268607734415072773282194404645975807544082071537660631141648812672680091132555859357244752392631131390414939666346044754439991769917932362954888080679766148173100439197377592793140861101816031574841281897327037719693211276433034895808363594973468866900153892234366295582876528987086343111435912558986604157607813952013027979812224694764560731640140103342118704147335891134 536212982884216495500349990431029305873163656125994995768918770454389116709066125880206465198423233963056430487750780329524706762761387953680641086471124983523872403161850319642879423883454971952526104859497370499166614473547110861254530761235452358409787739685307193175722934711764903006557845572938761906174231313658297603698761971556922393668166303940558414400754457260001136216705392062947613181857579827083436839935951539478579262320842965868925926 -313195856137573177355019403442636462901121088635931647650743877480148547322209281548905271886469935714546435164584205401021591873502394602178628170528256182423501007714433720317121440357143505170267343164270118025622495346804316438549986848441871626464956715909679589968258680195871726396735565496378192499461911326595300297717075689838648610587952441912423260514126165307065295945940301189772576412526041952351047407335540721628806001836844536152098835 -365138466179763529622341207419856151832232501190785960361124564365649114207730758897511736612035835196573727655722898865786975559674438944324979135037876044328548745488156558056926932474499005889612963085273396616542870927246064534223257035476195543619217345877798355552419249912471600219766968793729977502768322262524369666174483123799164221592454267452187049315182422927068901804868572052501872823679514575745544062078381931064949673301495652012459032 323547154606269459953782983544256781720814485858055305237127525521815109105273640234247858033216612318394661412290187062116312183759353783342976085317319194803369286265027505105332460378484594433096629748678992449586001786875992852136274810682188734469144686453936341774695481947733956133371499680608006877721054714744192519761398809194031867864654168353268505922890031378853026396788781845614149319450349565803865429546982532276695628261687154048164010 613532307427237557186472424887195793160123611005593802495403536309536966720198635333855032204566293211488010373140567752616327709015022108296359310633842709768364578782169122272883797760114729407612919528450507610331071201502865839717355234107105577958871171417839033562417584814876726339727743355312777025883774317371032997389266829259119324973603073003891396034126531089382714876517347502826859023683248230043163344704165779222642232463656958539412434 -692854150135765499330696607603461787641831944274479159951449942513469718446242101407952630984270991794298139613484201573543664209263917488385668061867038188894264442453153293266855330794589918454123753380072021040833024917587557047665537395579337967526142825505552625018374630334213018733959919197302437320946937317705984566505529658513971910500924321456133695635502975985149481776695585933422010446341933931922481504331597290052500440872948248759683960 -1063911525090705889268985431034398079011440980039527285359748975156402647383745082168320383757615485441131058652562156618510271058181326912743387817014001030144882207221394787839113591034055558660838415857319688861825000968975177662900989104957638345052664861170043851441211355617282286768679446498600640043894271955725635222767882134940043581115986567879896860934577945322001216735093981472858442897963487669224323016069334456703519964860789007084611056 2417587437641541411254298975763222229012927020220577449217541188518149586906576332655046287590080788809204884312898175072695910360336256819521672145285822678192539005693939592676491196156592033963768148953486013873867555213277058833450785164261320505827738450753786179890978521212375074414374257332996996218311123559036372115710978896698565103723303837754336014320564020232537841477072745648250718770876297946153849932220418812950416128520147815125686856 -921065018684343128171387603724490085328913824551842426252254452537692427233245178632994911736884399982828272950794406853537711515417436235494781598577940699730982084054965002944761051029183265259775286314952857913878800654322329484642717236345486349034642397346028212770864644608697872475774031430916995686099675236644225149697915522811262859182783924868043336516932502326485462505076394830422189770646284369894664186814684163068045776037549925869147377 -1124254504651890528603429984580069542115062401850369413168563934645615288537652246556941957702154242100238979689265502649253485908123402321217262253776635302224618957030992289908404679485328252419441349817484769793613582050218894093936231339228916977920955296359688401950999949514649162247879607556026281623541316293012450275601071472044416451068146709999120962506972728546788955964963626178851719435030488823311736441272306242044533651654980844411589938 -658887917790290908818180554019959180896700786613881182681577372031427295529326876239939143440997206349884372145586795380533853680825030672667582524298095836771446628353265613851515308157789014661503276473401966363842154596030842040890969832246165361501933977620502228529794730672040447910340843214331358233752008982697595334265308673565325920350433860566440951790776377658763613497340055833488931396597471677102417154832371773021482255225391197051384046 4390644921289760613804454028091182883971396459389514467376148122162402148581067833773875984577465572399814306284915377328178963598819804201881242315757485738420528288408492537679965091278091354038231847538432859307525204688918044501066676199720925215473632497599163360795254729065703891773390905367123421369520392711090621214731274844083997745543055502935202479113929756547358909374300741694362882575325206896530437712465058161362200813005239060002923606 -2448772652980024190462721095341793233919354699786557885602014173180209981990346257045835343854348609288251528412371763265603927245446660072505693890632360761423521937370212208125696680838083034466287173713750226754462743689444254581839346246541995924118173010753350945677053510536124478904412149231444273595685209798518293650908680872497230929300669319704308521825172922031102351964528157550945989887638200327860633150584507620209284413656334011727232854 -5587058356144673197478740525529946317992488221429483536637589419347391237623313861076943774297408612254342347112228004572670319845805438286084977035370439957908490140519909212709881056958956244706495639482235689217950637293742119900509649681749817355179013565423723678393593100051710425053587365801246019674399405960776754797694725227969411968982905377594912758149324720505051376884345874241131441222399945538060040470674576160846647208974994437827016596 8710213161893828974501447145210204070785710449812844302830452533832891303514582352194977670704286457296061928511729110675124060527655068293191208461990956872848010186780786185367616745709471413775743854277673915691728400904421319432868438996642927689860350501380968083651239644017303020053971422931332624375478192231960988014974666335423986674155993107978361328773985604446477266830463452353590555694497273414498627432813245489943542365922895752885519806 -1589012262583617642758174673298342255671378417324184425705752163174024776735995918596715026297620763079792386803027072951479041270190966839804311364677038809898760703695431331565480961425311756517938535825186653903162674138888863876090397046313634171952845344228716828158969880399043037989769275610168194502565005315046676030274355159691094498132392142454632356165165256648474747258188470037044393743650688539548483784946295915616479966121439730588688072 -1786128975161706924293980187033480011957344880769757036412163341797563856003365442646212779377508951337273043618571043252460324254602477488528135408339028029538796786132552596334014216101852861055992539366190645415328001539839372162822566967878847006844915375775269692199855153625064351865552438307669079755401720137200128375478070421654842671671019369805058037702605521005883387588612639083566177253588364497853022958140401899377005430377302791947573038 -11457579252581172179175414926424181649702643946916288847243350786128296777426266168713116265847710425833853837621075814172403744733235587213300023641489526010466214695844532799740230276251080336393334444347948755551862964966072908172621822616264876354710586075270942964736186224696987509646920440072372292480695774961128342210503595485314981195046091576234773203780781142496635293338757797315923730275260866525662062661033826146618579002380395039153632926 24999600097048275332414474986089237206562195231124970451398293159640961675925174987089458255794421410448036925630325557393425297376387309813516549610632054895610637901286670654990883133354080681046400565506012756593465048919565537508816950851842877143231300582958791454212470066711793499420090409339785772515931712205484118800347052120337674529574631051285327385090710268142303645296292031267197069305776361612281618480910912198565783723339394613793288658 -10929726005832710383860064565681003358054163443779689040939078902748872536996869401470875198308949794210802754975796210564945443046473587626819667231259262368136682096103047966068794634767385390897693557446047946724446281600769330104612035458836311196909319578860752182853608311063758301836530052212667869726358349293652675765759957675170694807401409050068455001318291977560523790151525200621532489501156824167035084492212482890094863971014920248510962352 -19917772800213230527745899493955860106746071688565653552602810249584596607831871556981765571820462787032730554111727154286146245293406086761893545607363198891325452718701275237804383336173862837509884720821759288091850730292756898713040296840768766656555554671448923844516198931556894569991756854116455808656582437229460215987682465045610152143104534924082561447787145152137139675250464530802178336381341612094739212635020388662663120417988603121925532234 23173328463573456823008027698497972087150394770754692597874052187305441305712121726752344003867498382410258693427213697405870182971718363499995781654284267775014248225839579769864686339823013981080944408992750795625842088271390820815952542224770674370687473623409696867266334827461157760460982473082601457371934721280626356792803812175575360180030212913917461814285646238368854510151946108566910447635290400197308033082318831334186117332577693511351565508 4791055280347144966060198331651578923312206530969097535653654654144423427364429545500677601530295228232499798313451356729874324501499224849769188763885561349886834681377332080036389720890286599026979929822579692671311083198749488503202092655831934265443959396454424248432814297472162124583067064138956438565763235403308942780630385762081943892232114419598504177071569467666923955204826069568536879799465823866342875335294295241701821846894089041954936004 102934305585495058726230752786097465062951916085979024561605127573758760567622401338593834783360876023184794433838513610376202969103615524159127881390647229723280184892374344204627230676719706490971558735602288295760883415898762864413637688327490872485559010584704325465057310831807087273294008936411010302587380921037988905748372623886800169811059023818166678212293364110878780362912198016645653598020623493222384499202109611184166594028389145277504178 -69740035449487227033970349537961602788146155285698088336931913519193913793782496788714943260807502272576664970221431603356504869690182551350825926940410268821932286829981433760621993631014184808597279514160769216179192568715891713531785732073260560616538044422118913901194186461046636244335012278503880407684946474281560174165915922167164190561658508350327110919927633471126973907379653952002285922228730609675508425845250754457301310614547746727772577442 121302850254488181545152420663017520728904734991935289314168480509894870546873757890592821361942793556265337561340097210373037374595561927991794623376517609784007858780389623362717134107420964835491315562996897157426162504641206932247931694153961600320462092612094324256520812445479227250016529626975729513571379260802436430981553047872554306950516724574071519869159310272699486263156117748726416547727777797064775804293409164633500942432074969745141711406 -60834772583323299536332557821863617992750485069786816176361857386328258998187302785384025968110448205062430298222876394649485540639393546474770631562277530178463422798221378720894798157970995011546965428284820810204211542631397882140638211316303832984614594617352415336830916014772782739137262784428566653095326726253641419157268188444352583575174576786179536571299411432334235666138987582264048151140578577334224163852438054322742221391017175785081274462 -42547717376820389508528095099245513970290319233243329759705897682347479098806261981669469330792483733253105677740589386440196734805062203093773874198152873092876309960476053497827077999363367010324643684296646236378746589058657194702316398342373562779119330682211466733797404316148143645541643601335360277197394325171023112127937344856759436458178263465390344797920236506444567740167918786999495410251144899232057021045548265171381414382888050650372096316 28420842810584803745755618944118893769737688864753415972312139171834610592102685037328250846929371579138063201649107201082963475515405428997208160732045067473801973065514879126150779151384077933319797111204717133332002753523866578007806947276656033836513399998317469935106123074993440414362813489669511261974393825313877740320598179634867571401089734488733385123117068662082704051470856597921428255352813798990716523844096494304968752846486952150200129034 76305650073195776998160046552555882910666969906493975519652580424287766480341138023478775564979802792451739441740300318463066101735047606724653999137156372637591890358047419923140228180236138260466035452962629816996525007283450939239074251271042201411357398666467081450714165899031621022327192183330345911890056235364363607308908185857424200574133981873801635713719297868693641677298754161505820955925827528761842112061814819039858006151774912542841466208 -18202216273003315116371755708058424205094807710208486226196975623478634956338965789166702783016597992530902871173886793300628072947261912369881070203512924645127792047103894381304684159405790356591873303925947436777670318038299162324059218012274679947877029862648612383677463425101203107894992346821831625220399442260352828401610016912994329863110988056331454679015765616384614428290085356845526127285042064446004732931792174531110352094457226616601451274 -286548215930098947125060247021642690352357831662489376945472168365003284497601210032227264287618702472750637055244588183021060664801952803085722532512516641686381781643257006727040702384493666344533648798000026437212884637908615645080363858989456678705451565814234618514747762645293037635777074341448419779241981119237317696667759015526637346066576802039421936711964210456647618965509118665478583384217363485902988625979239687258944971476413673329746342098 505765419066519944938259616263621824039880549506478386023184138942569034000046392287793284474430331113945820375120087082246030882628919528607393212674545617997191769993531333239481844809931870406301347442855413112156748516454307409230504615677318929185847354256187732891995594519330169736658674738200880022367991648285915136356135593298062016037431783900868216076450748819500369207573386416871328783204177250191535560676769591956968202154253753384577167026 -318454631076552255286740321329646348537795342375626970941181662065379629592993780941921821788915116007726074104938964749242395626007428838135091550789690403325920486328186501067843669637188804035284353997504967097829706178972839378655036056556848859292061418425089121243888091836865887778625586691532745259549807421345480868489621785121088424446875400660565642838395624360179854762978324857171302455391113288236044885246623451336238002604620639020718563150 6990494301605358171123555803958639487478479768305532422126299715995966693248624535080494386793596620475154444040382211957803753023609631902640748842904062728083487300821921464906551226491660720349358813789451831379354906462968687339118753809282377074864178427812065444424962241695521958212097111926121470479000137731471744369089521337406063148725692894286574376421244899196990354559913367469128639710348404190632077291711791220475886815268524562652273490 -133678889012969575194410541233129031954048367512286703565671380958929984659439700770173495990907570474811006698780445062202655853157591343397172778204689041422697107038122546917713149283867072155724959093286784329628363854971889934880336327743072643555758121411828739858446152404658074434516943334229323962775457281217003166464706808219653121885739813555418046768165385468936217579332696638791608684280238214328097203090036334078044894043830407227684564844 555099539343313618216495647385901577894397323838466074041596340799345623251715265878566038444094773610937666977854524112832141358952119332556517841883934859300473774223808317254719459034906041165485957406406989009345244446890459992127273215623507035320865952897801540747303466478228576022289806357193700592280861327141163509836216144119595739512955842099339183271314924204088322941692593873998397495962107206736431425340924159450946561219772714829447268630 -339560429589649563591196187329521207249935480296075607893739040965375757791038894157310991461763544491723059209683316091890859552333957611964454416099234702261805911699322563756980237814154955986370431873654339007082126082601385444656132180874667472447671318401012908720152863593957837998319226298810976668012666793215108237387471077384935374869682493285538069559733166599372915481338575140748763148132441887323198871533313137562056250607393568026249043484 -820572085249892984899936403215407074851847001463432111723424599390676523666817439276598800497800256677433372445454857433166572956289635948737042244949176232450050884288895920414096813261182898749825106442830897874333489862560231246462876843740675235844663420656015567024339623508307073653690512536963872435914324115399633623620872234879156660820354830087438813401691425458011923754552259859789257259070609248914181566508157435122344670500645035161513279882 1763639642295719744451868427582352750657839300760669671852147538242188547298129129082932078021784675544862402436203864693452460160471517833442574829283083056617056100933615852344444983191302306290454346379252593550622254252352714370205052627746981718552761435352817278027824970494688600992091062680128982744820927228695289847804323990191774784916209651479825440587839464852785262291096594532887222798121958089237357504417091429697800044479571629005842083440 -1343811934574920337670409783199601948378277423789748213401208284161554289305445574246999743912080098806485163350762203475972677695740755476541496644690249788514254100573908865641331414938629572805471105039707179191906063763105803055932277673046003682108062866633051406947956456754155255600920147955004019785365450133278319854925985117592985600194089191060732561957719599472141462378638071672477365444596428666110488860565925067064919538065772153823614393526 493527410953104847509557596101809613853851131159104344177059784817009839858977696103440848105591426538341030756634803512868256210134024205615984925536888923003850812146050541882726273539878407576463517079905436976207534718878347682493642989491616250526593468147860366788286518337193409091865757812644269440025836783820085818654587766354840634214518356470482876947225405117690611006692392252182934550910019481435007779137500891942313906541213184697156053842 -1170012460766979001546690878911052964570974680993454091705161398625375124862560824232557837472701834103375510535896699225468058140556594128171357845737025641122854824035760177167769826094461215183903379161201778431707777604353252359402987366286034065180733188386926439547129382379201356485485380427236907864523023709272984452730257460748243075059786351931065908061633974595512409399854079509971109482837997287320763250695294223740763641736303036579673875132 2964250987737185071738618322619762070892197214091517918473300896429641621333418948198316852391146242667912244493251911438855987278281785539331947865849237718808285194001610099002516083919081957791620168728140464945570242359552815396266924423435959878864232085215652619965054919359106649513632397174978345240137302346632962432919285203929977516338061709716849378540163493708186701607592804464364515590312426322868851843275976785112765106700375640346322711012 -2644409615551076223108058805666634671826551062601622278885366400481838190845570600706377926276906355829573275558894706194369186883915044631906697307636898535666366728871934421813800554904156757926483041108403976764996017797344359312360430168740341082238137015875907284351285763311305817936460657172596573520290547151121868060379372318730782761169152038630832043531549060347225887417827805205293084541986614478625065998204855317604494317138563811294749646026 -1160182564793037481636168481792426092382860432695446816476749393735122170488379923519000954539969037259734263694655560178639877618612394901340440992313369469952454426232800870410023833828915260595133244056403227764782744739053443709034841043320925849459628360883290210182393575411022154344680900196385758662522927089350362631048453461963707713958436571044978495921758543079222851443493093276925899355688619533127622012625612782453127107160897065944571246000 4821829699734630967618026466051738983060343112460453083014943769117418930973723796986558672268273705830972122028028988206398085394159962665824783379951883014305809138250492075093883723310347646058223702704777923286759479089815886325979823308016851772007401980479419238177933588638552498237222248301282664117078173739890487620553606325455285803301840090999546256060299117927225561883045858166656298784826762127401692429140178608200110741807761428765654985904 -4295544991098096015988632575300196962563061262241422165975837515600142190826152948189401016386495804508751095419140588881921061831896064720966716967359387410824436350683595961658439474601010656281506663630411090449803050887860153042192166796274626314394921375182699028087986358522870823696288064572911168683755671359622311656589036501080742622402061686325008755821557050263427054526514664760123967286937935020429589325963294126895675589488519757765157308984 2183544022767642358626431408543049148187597557143128195052308917276870041094271002565491491466902325165218954176595998052925071611534725974749268371864549119425841834849364663665415169609578238967804489289834666435407166812045509438033075678034008398572148377377417967702948041813322828308445829575624679919762006795806177734666899432973663315804757775669040357138809547491491730155467137053751432164271159773142818640666362659046849890391864854267051352178 -5039226295847076264651014519068540519092098865499522865475342014055774819026171756171298229664177940786200493477221379051895644843409945978588778081554840829416713716878999580256959705693739764565053394499109833869988255267610417898776129124253115808316449774508540777612875151126207973717644855235032106844482177245544772919662926880372144799329552591120276026524781082051883896464765442192629879063051631257404888970686704971389873971328417207510776010600 12356090482885361659111940193003811045328413428754486771008361622530402151112611050968119425105163540942259217169725687908467084941898849000105128782062244914564657758278453512649829973220887027419645713170046459362975502520573562036751778775787081321787184771917445610006281843012063835128584514701032204827893328264568466541482480563945124159838635668583037380350655908921931136767967846490974420198824507665324559122121231382694854395354839907051854104664 -13857599079241874324110185842996778462350427547547575754732429506325632670481658552648790651388578727634193479146860522299634423950627613140958072977679655044922453821724325201388482278767766031723414010476132947028742779646902884623678511568018781622813867541599698276842120633925316646810629962469602378567007323173256055675948130643543260320877030894507521867486955282399554586610114260038413434059419593309921688993859119967158600340752012724251304045462 3594104210009387581364719592171365631467664638815491489311373418745449226184625939802043117591985136888211751181544697437991151441742618368270519552821359758492302215803816794741196156357624685121612043884765227108334293534885580129919851601833250820067141744795963111603209773018160282219590104570671436437493929752682935565355564305584248598360877094043751883607383128424848307933662743927214914680608462134636954706818665634018373198917333157788464881408 8638330655123735758178779376909893903542426889877514460884297518564527435212492189033248295848982523286977992016685328979989891744445636249066844565268202783056796237138259515087138354411257471970927144267581676661671619395246966779888669551629393545270485246477028922194385097624049057074659497654684745372785886627965162316102861365412186575684900273941113169970229675689022801272901210211712955188446520481112495596571645108719331086759975269349692411886 -9367184492463868428957545760385778962940897810970197155823145484376805968968185135842639424234474897495767538936928095337281775846216216535847685213922078859476735841234943685358372849419097611839829814019106623117061868580628370081708021614757403179307912556206787759605456331780581898346383182004327018867143472040716976360751782800464227795845633137622167755354814422587197005163964885518525224990582849944627290670879093979805397185046471980361085995370 4193057444305797890861170478550743686715451941917535078015676056013241633037056615877751067096658273587920293813659350878362904638857612321393439572151090319438595952921217128258363139190745055464844189541023534359645228053116327461625349567402448952457933911614214478043415724033557738534439394785526340524093614130797693128446562800980061472065759048474176851970903597237849123745358396516252305051474290759545342150080015838748566356396808134787966521836 -13579409477151134557492063407033029809116108478756819657424483392799719307601968437866577273548046485219840545417224094793683738096358444062503402958605357549863236695765697162776809141957453428173404208544537017619050898990460288041536877068745178442685189840961073902719521307333126450876774336619161455867444221946973763851965736900673026481647308006932470802823257757093843400601212466511788559030540846638934278566628094783497036835797658458715505473926 40266035815116318328525328442719219566470147572365309081792862336430237381614355689667906801637934932319074380808863181555298659097973601840359095715298189367495763136569261053997433697452878574912250845142850921618021870114465870892946277252962911331779533064039719048071346011642791260617376918728427488676771943743349663338833642203573961988527141866340329473988846840489596147802207148216638044751652969258247453545313615573573589262790953582696045321052 -55248683149836665619996271002329367358198768114044065817067742392431613742705886410099658740163721339121732624456387385872706861701424263828577343331186110440489206500643140284483986371230515575740112390995142444860331642925235215810429072451714483608372962945989676612941117848925814215888351725984134256902468302310850749035420269622050215319697911893531156699333094522643133927602223261393213539294901158328833715600982396568289963464874152192976625998926 34713400690247237206640766019381854865820188047837609914382146328580408946987156064770743386605803250443807535891829436722405328323718009640447274169879920563679093773203137136979803924114533806401178411240354917019481191145894496731635100196271241201287594498621999744722376389999689687193982915953819030131343638974427476142279907517093800985278800915004113794274813960364092946370053261960932778013210876989603086647451409980320952589484681369466641933068 114378293894439317910944658084639393798801146994912901425692817217137134752098058001715926407902910579745430991746787199835801067387279927840424129835548104404891933742557232235992139985607677968893836464707434897112339145413664007027097780134052729467880731153741196930171549094513463680317808859127078144725815100826229989865488971616261250238013480147799211531070227300503734711622403295798136941711321691940570201226826886631691892157201520721583877098 -7135699611252071988830372816495346433905044845370158626321837402452255328276403475357591987151098973572196048723160933707982345491486601223149849819264756812270311317301853671516158175317990523019065346732395100003429121071294820107647919910991168280532396085783937267189234116386742309488098442078921683863321256754105679230144222431394933615266897796593958337492448394379158020769010831219495592735442295351087619695157839036719546081841146870406398442382 -8133147825565013646210384452610611682777880563947002921127580841511251171821548868843876958736587574661810803709693920369904059958540638523852010862641496572250972272710366806207628262998623005890563835036630666700215730047639307655176937056184732298871902501810745167562889183158307909823773761237424626820715933060447307763248336071565363484607148966270933117779365332390594849493373206900623250499853772042003418065724020863106187944489305128482302791404 -13489569818779209865254150135310347686356267483141514936702952980934701723631431673178159085556819850241623926463581351824971070491095208666528475364226154312313908700788207439897144330557224434734714185179931137638012661530677928692822959204329605816294986325145315589163885974335609466729226375281833617643243713194326948890240940359490916333926833553982897907800295267361787144553671277295669690684101715247691500427436880118809222671897458020099403365788 97771942366955422894277371431567250712356766501685283448096490216875142401447985865964558198842173083640222904647669426279031310479215217885462596950077568535221940242445855833279694581750050537358154053502752542231869550458952553903751133953354462304891780328946566763831559133074964577101756446867863857716101071848503996583406650043050535041030360174465480720168775355882754571671510994896007234218568969988815039742308344752960946062666745530962801597794 -173782502093761578495814259922975470459749945903819518541320559382874033979548155442309944891861210159586216695075831191714531688140527522013492375025382801930034740510802251440506963577080654851933518434113969522033943596917972081767248246505803163547456284866671493072116321288517482465482069667195821173662586071704431946301759788036680221030109209149498681507466742388810265512066264286759882621456600217260927549199404788657527537736788387559011956890752 154761531314696938503109847667651242130786180307455719524417719856421882635385851483856611187983907631284440015224496584508962397729954140945414710571678261480563830869853375062137457631854190386755349018383557014880035668186761815225553461149837619875285819295551030302641581393428370603133835224745439928987448624634488420029452042875595384716316458410706344828214084633850309700861306246350584758493199248513553463199051100965847685599945379530693591469464 -70607732529044872652088174736699378010816410800172712292677553301805951861939617546965460935578985892167638138042879671076062397681227184024303971398694231711571885990667245654751205728596242153327328801781776886167083710701498399191946414173652202905754540770799726891738525255665738799071003011025459202299397837904296359599370910413301631113268047285861915534192070040292534229754341697432494897336941319752508221263960762076339592956485828666124213590912 44894811228473139530304035959954591336506018904336683204439495583766818251389808930298230729103468945999331938633293597299181263631345035295910096242595810388140304367233397687597121868482718578050674372653857799634006817524121000141252304897722832796153687250013460580292223348622809599283968664110470175319058491673843905074009459744007196474140160312996168362438584262779119166786475081212391210275761647266213196433995560328633240440866556264620883375234 -101512198109885753275831960286512380283503095213352386450441774472794459504525689500613528278485859679505099322927038408742703290548169835843959648791403573386216886277395789956989372826808476068068536002370691970594108556275369854697626799476027216703873739575485908284386013107752706036358272530743639014144698212723278593942302691286564047362328025537502462614198529275990503774515001767044188881883569979675022026743346511110916702362258269954262065505492 83037030617840421866626212548003352894791840167182772066284079583886973586782791626313229889870578377308993487720991301155569467180520527880727568812877443594812493514743016909370986671849645265878487536112600594560036635739678919981092715111837711433749268326343219289529440672259377800871088833958314902680521062797167037384741623551977498941024244704654056891681167039028671738818658278732585303782808994132646908321869787215376079943575781549052182110612 140522833351261952889659045234785584482504013278603358995998750172523595825108178608833685302659941493350983737526027050338714283932269076466473589969155788835209641242499111678282848749275478195120674131151167262876320330379033992623221830529196790872132803700741602394944473036720719371143464208300017456105625256832820345516405274751600543113001850010977758328626010152723268026817386322254862124570997348201859357726028107859710805448380050582067994876016 -426029159778199941633340165503402649047256382864127654734226563888998341819625110057120080498338636531870297960127351176061427791066473751685554902882411598908465093240798741559688797807666374642001804493573128851461681158279344668023968413933387573622094985115077087444346991441723955108364971901128574720414876461826815195844125824045180791320885985894104395868667082902162217015045997912037593748845611506906395664215681484568064229322070233146495667091064 490748373715120195672508388390388724480757049564820120795814750017180915353736574255661586833544215659463940212765024902226707513599072895812658592398943234640036023953448559982563737819276697513190527791965502233386794053491057663899893454397103686686934774828175940284622350152303906275473090229538489391725387565171719805623407500171446573767573343278313694295578668585347724932226818134393347384657406418653180298486526099156133984624462142324993103696130 -320614686227082111751421252087535176991011223004336291570247254466603552140322520996844622613272435548446132171096894918960713220595112363225962872140892815056348544596656969349251545030197523435595772135433156134037818868892016050407619513461522463065200972037067460191581348498826102814257610056078032385297934406671215259082691152634926959402665312882018270015879886767740037334459172515298266374257540448145452338845922843228903616595201326913548725078020 250598166180709502250481157122082494805625793397861468908025679947477172601702562514673721502025925317752501222869091140677673378210987298397178519451642540251442097371767471308469521704930995263726838110896706332133402953288914664971465162487781433892264442255811212357236332550755589084895813146417011564989983015799625785790282365436362119608669857163240366105518331818179070699515461001606763293654534732001087169971444705519284196634858101859179149818374 -462655532053188087893074802473713471707315377559027262834481447817042196766362900411946453343509602056431457157683733225540505316037387132402810786883535416912685640863229210971514923885375531493856494461629231289970820397016348853026673405330585915243448313966820917594339559999569678973021400993547216826372408483530507713271246753852588450651587118341676980651871688718839750983910600124978323737672887436287846869294430175344035032524813532884593940216302 583972889569144201352082491910395172341927612813222575297202875179953261369146550297277708585948665698703281473256299961110724071477231841343071931509344660586966401902618510097413713716557670178543214541382226209731402507206492684805342516392857671043567792521555862384193731046123623922074123317560502333427856372584966765557485445253040985559128005896240341017860077731524374002563677900338428979964256594792769359707484341932523113166085163914811737912512 -116122261919334656229190232621383502165025570233501270287348423428915586253894157247427636798962472299313838872230086324457281745387785880199291845832071255375716185176739892756925214340701226824090483140339116898254400181105847242517185420655289830519125840080512449640032928914320025945083549895412882822367173736985884457640892059715927880252751867915507497586329841173580362462497167973707707776646277651451372327246454598632921980136266889778345706020294 -745102737344672110282283180736972002324117422888743181322411484099449978292733720610411070994272081880310956891971878240915710900691226935427527849264400464395666675275435759150968488857297040899313440471379920462167733163699149870213147198343444668515708035795777571391438279121926359526264396045750852454477786538252546695499787735540291950788912390817813292852408717648801167466153504234142182994020893961854891649377567033769564243445201734622262490328398 1186613823273116455837317342964307335789022256495669124151428898824143082419268973131474507346476015587659923540204034837992755967739132011800835016187755133490651982589502969399413652926466681495955629694241874649229119392277527901745043265291863895728686952441213755279847395716560963403274537626595067242573285261455513838876314371457697249663286810407799482645425862964692255115078322893161685413918075841224130719286959819121470744133385707141816106603034 -908564368038417629579380957691066723130763046925547630094186356351684376920313849397903607896956730749154494190947219322071885937449577043191054912313210426108637780861190959966213235368742477217423848980070581547983990126414277161161830528904349511091231536702727179912637747542570497053641149147489898798179788929539842685679870954785589594325592693689209241696323913286399659978708752298037187865793502139657266340443581168355787608391491143263224397563994 722731737566025312798017344291515478466217119841960314540540636425121803806267869880947354550942257724173914439459490674997009260074762139350980487916663203339670366738003326116466546779167943508744047348963734576633919225036455400361732353852223751541915671028835594164198193757463865195778189236453656182097765476128761868419454345094244400691362497124544890589586690699889671014655835536480173242605629671336779888016760221729580235043681640277599492808104 -1403876130586207392938067011265618627401134159304123837373471086413137542771717881757838353673677277733301254342020816237243139603098756011420594006077525638428647825887431006701062158641467706166938377510431068456557009697551417053732604978566463465795616791675430822683660490823008113916419603458533436372935845663591222042529586205332381027262995503052314153284484673502783765638089376566121605313224092539507957348986298810891943647604548430382993941443474 2223662560105617506421810698557001693686690651138799873318380535823034412010431777283869499085239136309640607663590738364237124970169960219692874264992637816193570804750157944996010221160572741933223397085605326130656771847516312601857797095136812376944977505909184439853384060301382715591135646183841819895033533120890776769705774681746345427025515145845760730646052166110278741135584822706990306522271306394819162711253743044998752039622575157746992360357994 -1596144600111983102962639244120266834698998975138445808762717780659775228232213233799456877290600726808229206489632246908725739999875731953673120058618600502924289713704035508094956063743156558168421480027644724435456615208376004872615523454624377582778917458385329885056042620046168388961087065175480635799023954415951968065381568751241086974117789929771761078970646468174933929017022686606642958289174382808510376473709970527020257603200049196278745983812108 -545710910537618837515419748593453061772025639635406131657024721638368099559378333006289034995623808219836379125311808731698791974156558023945224417817313201976134556957726887934080491079939515131769456526870654391562769632654340652359250620961639625504080541671897261559517802548248608216281111115800500848457845210548404152584631363096865269926023451663439487408964239442995807780166261021452641637137743840720202343883336543077539243136321203426238095506352 2157253864691612556265477976234321860153737173249700640115748137607625418822691908355267487173993357412075443064230639581435554051237054154512697557658991717963123022041305434228801697903863391448489297592165000421914161152394435969035423547545362385915382268237840668012201487451780899768977983815903427280429453799330395029944268353701954006727065242263078992337271256570569309749221807562970231381721718269987938918872593088600746697572373224354181622158842 -1828386041506719838154246704573031731846712382774817330778166580799414050612873575885357283085575565996061219486337417185936743457615195700538611972112214479764571868577316913549004454794608716950671123615850011831515008743703491481854137245227746490579466209425850037239594238101951419255299865643929817859309024969589334102632808563898345919463905380784938623392898299807226551431610160113029326494441006152635110971127541883324572054065788543167968662881518 1233533895498875861263018292463899066398694508530679427663648089605358882352789148102357180712744687250977264177849467489403014809329940665323417262059155588672276343445994458263735243108037626282448645029194936278693766179064307582884332177348645218396102189963410301028695333492282444422814173353551443699440737627378508937140576804031787276892007238503363296342301313314912414152031714722415358986245882595790617156991954614200624117868601296899527026270274 -2981962270389502092942950670681421212258812996270887927578935670308069263744322129359916249526455743694252595852431249464333377194022756843962016311850334324726083557546343696978157164423160625816383460034729459258084395260773526447353124175744600740644609645092228530102886321485013206871225942251894308100414769379574285174629936484092064814338089953781945471709369631015978108666197664946084278523747164042684368946415033218176164254621386402594565178774308 6142736259875417515027198654415673553205202421670671303429397543505396374414443844176169148837337618720331788733748211937711917268234576382202260574934410068862469601971462354812465407363011356693800700865638723103938814078936319700214147165614994033351382108891439169727460251272724662315747193995802650646674548460219659379923587938376625755136120112999220465727855445023019878657588667533457024642285770237341424367771870619538350407834391107337722331781368 -6385086670692817045722477995759775397662970948426410009796970879488452762200234135484319782175478576029329691739301024149552948857174577475311001702207884892417463059325367951044076542981030030239455101016146457759878524378739284984588935694394993304320398406458458971537132675042239579304989918638343146733471532484840468210484036521240843837233955411628746475148563408438170775042353741212770965021399971579536910762925181115140905249225994556175772657571826 2003872053019388270899109147257094067419908574616230376813319998115395723625608779306700027825154433189011560896207216116093349424923226759618871668355175478824036441168726736508837948604120243540559964524060044277717598008007201665684387709995430788752652541279084361627249873048182238544433836738439254535562341088484402089131481591385450534714031409825696579612358760873625591540072402326537582270609631820862446808319051895389231129711552705015959188889556 2582717813683777012988004989441915026459291775881326098957951944466123492281703576586196585059832736332505516343451487131392058121114067095921682577635110446276769763433340032839968754263020998979583010345242029745174822427253209642741518296860069295707756666862731759236615707384168929676964144167602214737494993123703171169767045721538186164350495699486537565571493067439540782410483339847615400819792440538987763430805846822895018273547598357232228392601342 -2499279658268774227299960257165192426390656305172685840665113763405614227337417317985393637493587019449714481847876014113587528497116013992206595679523896460620831073276170564502678166336540614870407862685059349824382038945404432202507636458022171564990636552015619199507671338865416521177556215937018751838856732710982812991529738664132220740180852250690003054945797242224789817957071829588372418681882113238001935957209775419608367475002603188191377614905960 364199371848396509835245610210987005034781543329066619697005692714558696885809702777937285476424892873182540289533660167155131639672858616475494407754828660463656877197250740913297380612094594133225274501544721793484991845251990023469366770542462872328947922279024022647357360564153334323830390551986050262835357622552072387452195458148401511673104417046363000382369826112736338142896617370188747726783489867687666382423069968189794771711500711097865740513762 -3668627732621106397299104469715309724583275414952082512751870638145115666883645768963787445211104300066250855154592676520248366268714979939093742610690530497746166209501639568325464925698904030057329291235161469940701892172553506441874647318772971419465018767511976787950743226798586845642333903788114329046643062510756679760022839345807211280270168326240432465372323918883684996654254487491034158130713006253974312762065513575115808089456675300879188355902766 12907629686824661988862304580117274868502560376989117207807534128142791071008086949987134533510809161585268163162483336798014937885181858623488226265741595700404005117683335813397464737399567904614788698988118822844906185468919664734318206324692478371552394717341563017311341217170958739107452947788150884564126517118353423552678468362269073557180400560582882799002668463930213356172725854147493873862031290712645060762469024994779235321903973537995743652141276 -17855174827614412503391695555173622008140036276410845314231586636410365766635962755291396200257845992925958137009592863486650450951309281414833971536040366812176372895672516311902209212528286774663358317346543852325654439285236115346807131076679661895843770105552309573605135365279780158995706612480146728277904442668542577496177034978466273500841328455210784515625475186313806266024609203643971807851857840772102080189922475215517588260506066853173817827171240 10825378756911853579588497231234306431938263998375962171681231238076525857045443272850635519828981948874343008520600135589517499795077357622664948237320111829425040325482674889087135774955566850837461909700522910321716278900126657443083780142328772014176211321756046639091148478829947810770113157423977094916415615385698683420590180277403331044830522529178895587329184715092359597603266103311278890467046889355838893241465134273485428745902465600381512862859026 387486363099559350240277785678354986750117731137446253207732794326999626852206751161729208315327381482791154656265628913538114369132042088026363755209477791995732718205622361615224259382765243479251557208287713582287683719294473439685943032637705421976851428104152348594430753826419502583250318275990890901475239705370347318233891466320239810647577794976082706779030725632563653307909782035346583653123047669270238709462121085861512652069518512374902965806188 -1642813867162421343752998499339936107812998322043766370367362454906776799185306837271104166742793435949530212924884994358359861463955935322988957149413542306375247780003877893207660042905234741744595730302957874517870467608159950603222097941123408372462774210336724325165731596643907272172393370587723543554695038293915313336539257404616349524874951136063039877436102041898560921243256695112533963319296794592036814071193669080516026062378060399153475128785588 -5473245689397080787024031404311785278750178103172060320863430054705091080437713146956599177850737562744057216138250810098794834855819226669866376175557706570769889585180806277756306144971795741626496390332326013166505179610239297291544175791670773413585946144729362938253129336410801650370411409373547173432072155762500213395732053486462469249679789973701815814112254383235382298355135709714160396992566821349194818335805681947472125701933940571854192963148716 2246082323074210324852412942864160267581653586687433780414846500212954565384485692226499876162036667170635106784070809653253448108434948001922316678520566349537291144481388385029819586580468522579010429912047407292596563624946964805742911205886391658727444258203836985391153692860591503763757286657368629604259493250490062132160616893142542006301631267361161758778259420890270499381887141441997822957756794460589561210983224312575459375334915670348231788768010 19590926115544449530404775770285363458653493751207661723659578146551296727314909142018096018780928090511096718687095948655960793548163291988609098873394458795462412047022560463752816056409655726333161272404805956538287290786030803255120782787796852441767678808865671157344535094815518549366334862682121636642252189669848552091928106329410758301225417679647418576658664013455135452482632085374057835749080380107155893910113509066528799044657459012329141396617820 -39462881677051736801466316740865487765873561429112565631774030198950956081636236669226989368893518275999405124392248426913080985451919687219123383915485497803299976324403172478604248783546225203015997496195569642507577633455317624139743078023930294268721685019518088006727779084694644658111930538341405933402820780071495580931839397191203696660460257899738479435495776520406106871758803062753979720925022723011408328623713307119677290287375100656577917772818492 32450089385548428167926882523392729132482131613318108642591681704660915416337368445550054207187632684766067425063222684314067128325708442763705290528750225506813849576159702787599429978017229996264339479501065426150927564447420420286612880529470015378523124399240028829136972037691692357323062582422558663916591304238423720108473275458987067825118575020619056349433904196998860620685418641015057789288390270756515874578921746961784746184569735650464775348021760 -7850561031786412491791878515825165998289345496430501830005840220738304226616407930959134473171422675264153755401461351697068008274848805558450509955784560302133601352267958599306310494352912068177509020725558374583872654195345471796844858687675411793497300023506203715179325317624232933520378807924216682422339364862852938881106198334830517483183319143173955670969324809830847376301228109470074195009824014289445808000150043553677802140553893093301295127619624 1377288477418687281869048074261933772884519469757863742957448558039811818177451446712989833065934192285699674483231101338900212315391294790473880545585193229461431979133426151857031077915438047037563497316901363126335991170313531558811265433671411803020554752736289972805769524637464364438569771015609605771657723945869135939910795695849746969234635355324978261849393713938143536210950537833737090310731187348270750025122351862748179501604827791397869307162752 -21517832430035897567614403045693484393746561865428093023456520223433655293241474797328574943626675154617287407136951967742911001065202449584994008495358224599158131861897575576543492428396451840745752345188278096548151896056670439416540122013844448652550303014148060830599381900332890209560041518292169847148721876157447300444598073260148614759786133325593686217819361249337241551976771733690427207512387685755508503148539115440279238946312971633732959125146564 27653145671618567137560544091310241877821626672365374621029721679033217330548655482098625690182870526183968589946562964515056484109231239760824648691307105447284664944135060963343516043155142071137193024251938394239399769909914042176737860456328100128101004164704343561580339960275561161597114286457339435295041678818630101394576129084025029108280899520628594560759640852922590488006010975978284732073357765433107050062136195429233087875304592927077240710635834 14434811052505696460682763019370255774324021853543496360873270900253677247184732009883524006932534290402161925983365328466977626381737255235902997490530405397485090593360549079491520054120531781360695458707912516219414888247110876535302971286306618457215192222734376057978085406094298758264450993983825241649348806139768962704398271872810358286109297403842182649284449743682568644372699445519127454223059450439449878284790647385984708694508660746882340010783056 -71344679249088926592313123286532126441658702525017051508505659950039266969589424279355250626815239339261476375267346705016509714423111264350543753312896412436496781950142702574165945491528598826128643020781441298866042910184884696584955599098825472417254641191373126396575163872397281770459166596878307765775025537724370118383184405429280906654236826238330052419458842482340737645474146462896325452994080090393353161913578191101082149845841288844535589852272984 76166931765568265571338634329277281707185160336620956706847219792867556155656217010934282893079193098289332837604080373291528208316499571513898634896692019735269291862610997004959926379676121655035472263607258718900109557205613397735031147783935928948236940240291043615691139297127860976645463617777972014184645706558062999683278916720172635598110096037203254317224261660336920756213994058894430681937188991609491044915776350287270405667788831118416341645528198 -26985221779168418659915847501831790796094826563785200582126635670186724787303675355400230921185177641859215533154209371216111698460514467971671988315622149862013153868247663001603847338174972770080423559428177806215547934558676776396208175631148377479778663465931067779898342842655754859113529008694529671873003825363766316482375666237328653810687014821447849671700278555471985834627411244608992283522397110770713949350181851166260250206705075718763517234764514 3011780087739065361539046230957502889568034397178357184576755664308637728369211392894907566099901574757707391499202124253507244807447892137854061322276033718211994042588139588501082728813001936602915337832638326325052005069144995867515061526737316949987837721887246575511953756777253473735086486985590670943260500596865687407273277051721972638263261510721964411439633293051351155167888583500696848496613118918021243468989015804869750701044395454455875403531376 -50212757870289385220926407193031152131990841619403222058525591971195763728491557726063155473835160824158991342900726589847676507026712505155547478906850954707892855778529140463977177473140487803354577114161459680312386673777296532237894306043371370879093982734348022053112548116127212043422779434132347228418362425033458615456185086442512560575686732132580779696148408023333424740873692907446548248636072361386310284444736672489103255079930354956824639990206128 93654594767177132816012676870342484162691491235465161865081690939642220057729731093163526457057449051544670155805121406128335594521093706932793036552322139339043977994072087330307315555679624536763863298939157446004201286099100127885860430317110731516451128997895486752914814259943262249666756008903015717606779548345784306248184787132803258921396173943967446322250386748897589668654024239577295798517334985943611418574138458562522673669755940236525738803857684 -30526991258529468629229319340227642474913771984505191507388193824134358976330432724107782031565767310583833173049873270965940911749400409326042780839941707951884946110297433106217752853689724631715500741964355684927518602784353115955251296589757112390501102903620150816017610239926488831484287409190867816114082927005886921895251020914354684435551000291247013101794609202189215083475568117837047256414464278196221908632795495180866658821023072411088527271987408 -103732650402817459220702369946888683425903159641519408815086640534404013045720246798574913789199145362516422058540876726606483720153572699620358939817097437001162730032286729041955279735790394415715831463288561119225632464787512434768189020271702763376142841117633247957306622814770541764913123667405647635984638575393683138891727504550147277305756072311062280084734911632870958091273443213009976867304398367195532365542891536379292178101393342698336987539028856 154024917576134244808339755109566825238829172081200080773796867056009804736069793332526801381945949121302323096735377807451122748708110641062157725353235759897126353230401915811406298478883869300664755126268036418199457783173885376240368483801812382053730952706504137288225520556831279990021003619182181717234916740760339294866905968760836223756712924509843212993201966135776130563010723156106260687534694960996286658039494209148273105587801994478938742656041056 -65615772345216110819862839912573069143865114846353753918048220539543291502289313481370603749244799454192223593646099195205013575849039621403635060178431920562475005103006946647545853771311515574105864620573616062720035306063454022211886961821753265036758401432927431363096512002056597165928152460259113877991749396412551097835186846370191722479052790039298799115297598490276244998647932180568730591075529201294370712120428069244666244829772978603227001840276282 -8492608525858227506711766370155092020836890434536344764196973739141714211144526123574325092278866978834998288553417705428813279615839691047252981341643486703155457073763612195992388795107700198693246840383845286090039840225509526832803384947295535807355326840308577406195378474265683922059626624073806721631914614093889156861519581815057920512407799060407009297328051580988856789746547311006552726494708647104776301245885745316312290518337164424466096379277244 -81534518392502417658854568817250502250133861148100310251859521611926987168103816003095557431778661882589400190309643675495024194368926335206580729616103868312651083654927647107107118413677445142542470957769861635294017366608042618426742998015540063406025671430478092658621137772024201702041794507893703093574424688274127276081694940489969529016126448246373003472268385741647553668652985782150553943085442431221078740513121693212783146517521393318994959139414776 225758602605732620508488631187920186353683777236154189039396413926723798718222032442371910345144988938838573476255634675809295695582774458993016413399100996948858713091647942950810730914206863987140434712728337608570121814667396039979634527529031974405509739687885821650597125008057846590086431900973685541540379829519682664954954589150070324935926481295718848290891860319419792774185412925429864333122734068132695171550528006739111130833921391811986494040596384 -168515250289454144158432719268695496043934595391042435992414078736619154253363098962763276229403514479374465831440092330708108959924605342139015889040628588649081615585993787868723219877969114994502145417847131869294143400336237600899239488775165384136572463842789989494231252352681056011581104954105899287651454450833091648769260976937947758149400082994259641353125705206491440547011077931026762191898904209851546245173225144403621101666785309511426828667195692 -103973624704124062868205166572690167487771531019361224548105606479473885912754605944375005181485957185274260175643968437280798497610319247549096061289159441405529472578427211783510459067594125053641072652735277596884210791643877894193944089417045366951889963886218623638698868497481573697174691625204907437282368450007885609364910742443002851797331471641878871499826052748931485304108746167864075056830088559837877438057487398055273772348472419214333993636682524 277785087521219090200611226418840828271277104174334631131076464296341955913975760688175216873847685328602537940100833494801341177785696974502478077567885175625755987957631079639770396877227341357651916016916281966824213032510665227695358448993217329102743114104634797082092334472135912412670896342336595229708298924630557879997659899575106589093971721294297203040509997296793526820095808105339943523935966239368110105480696930283049337359267498283823876881828760 -141783942252698073756139370101248422823284956474207920333897303505766032205255281857557302523207579509743570008088502795905608390960435074884612729418965279248564522329617049039026897866799922084273637935489915811843040768063636511430640903563835288113949560691974487779488650702285936939089863521694370775021209133675178408710692486407197794452407959723155941508418317946091846349329028525371621622000818751572157574574439088518483915238546470589699161830871152 -54414976636898547097711451610700624883688983218881939194463376475199535061893965400663744948186830399525382754225185813091659701732605285419511680829312427570757863720649122755245309493736820577912011170330705036998701445132478224206639658253786054635236189462307090140028411924800295149580659715820035410845893242992740137382895452233599603498547304899193886695242155495621004362811049574090427622930595785818378928642685299981798561847927562223791926411560196 -77860763034286037706132439707768864209979601309838021406391950731007329187643685757756214645118666727976203419962514861429920638280833516945255172852184613515548145280997166643190028192261660288563448026130880268684009910422854123096167556376166073499345511400859920442703063178434391973633196652449806896418385565778870838028739672419334894274099868513566037777105875292586887145368396928025468191587687134485619037078741732172503322321426427821614113320020496 440849578738340113052914434322007770986626554943281186589622215786028457785539025880247159228825201565157871995861491739837639630908250728432586038366560684290263046129327082733667959310131930873770653083114759051247997924776034635278212061371412468425232801090348508202223092893611507858244341723828077267262547431261466235023808065037956546651653164723975843323018230955853746690904494450322358392324459470878555993682479420061817114335039206771330834251069912 -486462414942327858995728609812200439850111724526111599009922638207167127634004534931607705355950988011253475754774718190494176665894447599057812486671613394617504236070312043990539729692555414552353277756425670892234774357653821465211536235318972222159337782282032264832809867525086206338636102541164702441522776051224857745375464866105750881608332936382682732916316203054406304806920572318312168022323088471350215707496883891249107215952365345638661645231162876 8180358827055576234553076905623997518330507191671457382906161285027685606575479210099336519630338206847073373332690642136945385297684446319548488277469082884122889051190255366353038825757666834486552194433052241416864908039754176478553220192239130237031899561505690339699590602920438213478202914165657485482566156445094023143552764050757936819215015360075220992637631604231457140892123824578094399253497176849652286185188172139725536761020982934516847433502644 443067261295104361764729576093838726540207956915161686030989129832672835875687796012892813229691193095860348391500851652807690612608339997210951590616727422073971617251299467144436494945697129254652954975683494606910282793121370285070524826730030643020421724893288096866312246489591789361184948440342623208946377931090873593431488790721511379046297527277030392211221415282876828313085944213783233108940530537460006168423561561186717720880485451360717338018372228 -285757180935845997150216630094929771541683789992740692149226804501856794037985448982184983547352632388542950360655832920883079328249175825666064575002770293101590503557860692587416440934383308668758017788602697369325494892484619242122886242201966070790306595127569779690769943460112844145346434038539215993235130870458601696767837741820948221304967764436095286588580691391610865205105072914078024722205430682980241092180633344271142065986243152392614143854524716 -165679875385655769890813604300282878635966761424590488328419961494821303415902986406008098500494338885455915383653862045821928593892968203465078773470033376863399358933008060979322510026330585694229303265585848918482462808183574504879491239790341230677772034853889293773917162780660463061019540971320161218219157922969642105612692610560405321700304593460822848519312257979329320291501692783183502466185541930389186674894201113145563087450081067026000157095281084 51128459423083364107665759790811357568787526336700994457520154415699970799270190535098766136340901327560379833413953458121417661829055003338847590076974987240644981593391400288553466424303448401939440224380437945841380700701710729916074152079369304504314252695185592723823397544992314685239347014706660542842586142363042062458514827385793797476730270874062172542113461308260468713365111645876975862499204957405245853934236278229785082082988723833954344788729388 711560323441960067618164056378957313110458963338203321290019999421862570092430044620440928979308688112732326476164661295828236590879471589398814537211119595431177764292704143163061027083178195921570573428429461333702187512529903742939162364665361175222520871907866297344956100592791009612540949299579735592904706530311912554487773649483232494505907739620709444862832340293427373644200841728363662974611195610462504059165297116736320533726472953177809336707929504 -1096828411400225923100382176378116357372081415902862635554160021969477260783744221109799551554629537224795112009927317508738412712454018184667553771832841433792882165755445368528588133491593548759307934325772884821913987389854003714413080494558753747862834706680608324908380994534488685766735998557681448549089426325870793706413208537073598892977496824189811750557570585487254152432183647681461473400401175699935919936867855622806445278134671079347689841736330300 390484849190009484372895886735313017000133004592493362113013716831331933202511732016354298952832694362864376055339630933922537260399379503571764738952831414054425408191390083171447387391948825193007421736120919634233458354332650925544421732338595663761635300741399369652722138038400061878387360044145558789413814669142191520601606717831525748412337150302445101858644148429062530209250771627683438256142615106171744115326107851283994565908106440032143427663013424 594722677463963370104481117262605047042424134349766528708575461657531490741814416680807817272561109900236166874270031125402972450607958018149364641430074841177531591027821827881776911381735377711782619168355836917547669559910922396767710673910405452164864099669667999297501089606336176888198144966664766275601669074561532134007081369270523140623708389478288461174658144970914435639751321811829479106982208279726575324774572677447578887309358955605659118016772396 -531069696985306361411488552875725317728041478068603514497522476670081144154055714751349453068769794724543585085823189888280555638012328158506888217903567746905342326387452268418906814786918529274717454204479717101055166316723518336849335954403132882364130054261606807555632313504598706261696475911867392623370519975963953622700023200074961066631309246406488615567142488549465329432531173998697796410402862996686517781818088374637296520749654349148457165035681540 -385735071760138614850696945394061281835404063866757965051245762382976187757468510152472410476964490402057778697354634763220634434033790895794515269083220659201003592235898119508491447410496130939954895606171701978834615013528785841563518903629176500804878183382132593339345407297588117914274834859809044161297042929050059151757131116383693850071399359611269002280258847274969643142235435063630846143123985460147226605303468937711099355160666078405395324348333352 489753120662456809909483646875369866022446354410012709565240356358579448222324299871876163889725651789231882529086111509199966557781583382741740029234683613403981100367606103310074586696724309111487516162578714127113870023608000540448899216875117092941677156460837886770850846250459818390993206840334220176483017120875181491801162001634679563772234333601586364067942227655292190105049537119407023767825535913765713453243998251749175768601936464831978715286843404 885317268186964050880492598336773718624200568225720303321258787903082358080319621822401675005555258188410463638164549761130472366332093491369896633858320730213052608753973262102786713102102806723816036826547856529072708418184683947984226633091152372433995958933142520341552084932303173215472574390799279297714988802897617802788124095545285480013555072280690094964957438821450548632455364826498000973231369061011337449370219654023694883800028198729495053047301752 -2072153621566397027591412518552953868284439327667200421486609699239258769742304003478548179771265778700795984863056360177887467185644229298864542601009595835088762910550675282124311115385359314798062116812948144753266340928855376579116629277796650263106841880677338450435676215416777092628261630099277508429912377636445388176641169373952089799322787644749121065907035669258214114914534541040222392669118742406661327850140916483407095310588379707922397895995225760 1271174687862651917748812453872408788740891864389098061342536311910535908732980586030948743004004572037823415991001620652202103954707552765497706490724186590968187063241445881553686449520799729942466898907821376949610240837669254514026216680123825568154775131586627034821190095261768961098891524322016521081345735558762110406866468899367159984481746966001138918657440489649600569789629960306392669942515978235559515779079020487610778164092146215511403113447092080 601655376875719475924935568017701903947687370155700532937927046062993918738550650118500724901589320566172181401140824852193537739086728395640123800360280754175483719697912126876405893724627755697433246309339499423660944324217076135029048709106020137653287945759730528419550322663485283498381141751775047175743533349891176617500784053369230746785640949406848179610107978484002321125450773721615808522524623275050993314009981651988532716886326769627213045922944564 -911997863070785781988857196116720729603130277803937052742014750488252707912368677341581512960337373061691482196063351016664851670220539284633007183332414991313679366372108396291384167331567439962836405832215123990400976608633009451265457049348380356670323022366492628542767508320817719564615735998177043482512955425909173786199525804325102081706660499163785188775055627520849397484334546327357181664784115861741635710966727774052756292993687630518892926241223300 -753006036695046148402974931068027158222872895027038756739247308178739977102298348077290800412891776169928626066873359151942406906597433728326362603321340382628018466479561601632625962526974337667113154481412646719016438867581862835261926892905613770317804461997750798066383245369551444869950123347878005046132501813386631653996844252066449918217013602399113133044756525788303770752851546114819335404384975261128939160680126239849623468139975499955304371886595928 1545483565043502339605567244024998809111250743589135647593668154333830636742811396914456596161908212219730056109891160690505287473112201912503002502669993687137266567108719813427150733829827659627748699414312522620443085894500388370385978196224480719796775566038493137725089252377339861360287821887894000950536926282716487438812319779304642002043273349714499242213372320964236044885991119180698120933133203036423638962096976650019725555185351511306424312771289912 568624773175349533644560854558438307309906513342100873605746552826235078549429621644338103570545904409895138420947966058562733963245958942803564614083889303117765160919094886751327459445160567701424660019664612038955164481864687581602276677210302465836177344494721917520659050514599020616980647836276924556426846477935752267606895271424595833336017928991033616963003533613548808035327676931955494754472621737741456293305080767997058508055625962716821459557653780 -3293736402033039138164397782208029549976768631232960919693877164869182148050798623344957858552030610896305332249064100379599152802979476857041262890516196503244378033072280291748436963760732818253841409292754358526814510489301215339221486130140471507134464301298976007825654837913807656226730236841897275200185561946385701046124173580949686514202236392851920550361242810626846484714563913195249887966613568679951294257188711462888512153226566008059959071279737112 2844655563824072291807198560427190426158895355514148396866155660472479300038682007325833655330494250554314120168661878086229088212518604600139611156238968551845108488179238609535169161838412900477958225456068686420080198281651586397995531754834541173125642355801747034028908899329806005088330449611017932309932025972082928548615406991753966093586788006702573227361103481577095296848182399602964341761399004893252754260486944061247376776930410080592414115920953628 305814849838711619508645004832680119650889082743875048096245560431727736634769800651745289636015706405361658236270805873921993146551783669291551531828616082878889113477151229376278656153203333913608865257667952165160161663168965159679288397916179040603888315417553854086269109650174963430824806409826789927252692530862994176874771325441937270865642298514458041893252884644348879328728484241914285233843030760072177047606600417274290825754489105359288638868720100 -1526175210923259278484756311598309500031291875932023261765624721835721222945702509780184612473141052448378263472720445480475446342516827659632527943287430750834258831476072399242007054766450217606267353763334523719159909927109919638825920449129045342462001439511142557094018981159748583077982270709271443083635564766687139831456857689912895987284152870309136936187089612952296522567967612758448765481829804500507448283853201664394706140122537822391615004859838551 -1189536907299414046976337838818605826016226913280123956109215642191611683961121060821346860949910945547223295383061371277748740310508767589940204218871702986496172028068874696946029608755820288110743965609218243184999921570814507902191807877037440460738776309524930850479665753546575621899729345144680163813698446503088728224375687424078522808534052095460796285819310731240059114835081439751001306987406230973702542106265056097197144394001956624729463890908949820 3559106627241153992432642959005726213294723464493325513708146806601990010926434567474598838488339265633648724360597115095021734562523090422427476991411203366463695784388476400910609738665265031459910651484970860886661346539610169424656825819741516996829546520653364330388686383968050317296560017903270905596670244396126063542094002235965037060798874346791545557232711677289954718619947074900670875934445426055309651510907298864623555605940602462621786653094195616 -904320877699445148045998760124795171730377599416085794899995893529566693962009130634348766009110040011902158522067019231221041506899155140072200397524184295316741681563730910729327018250474097425094732010083912923900813911102371745364475880013759542577999196895441423260921397487779512794861013024050687181597813762154500090638762374572034508017664493866000321758769685921069586912717244266192711950405938604004313094569268387386316728492308159372153730814745573 -4297995363505890103908785572707893942958158592681654247323148133509342003523440484831295008402368793013790615204382222013778361184871787152348292587288428864876831102195462229420531969663704092696761934762705484703823056285239976861330007223094679709287539070721765985127740126611480438106716947301060125600634180717184486164755703285143864978514883558165775441732477583768238033094969464066741844649477697688966998686084687680262445707223919270511125901224805825 5096445101574341799512037250409377811028677314066557126801064993974540222138310670838284858460160276420462381995019433274488794175783733182666419278217395703198551045424616994078788619267837004419365261392779430025944547859047402801998854353038105509706580152157655301270705599837091259923230464514668647402523090902033684142227580247981584806685995801435058835109685773651374705682986822048398724674619921778861648769188436272667602049167325783933291955324040512 -349313831568240871584091486980620873483687788934641515516128607822511579065084215450916192356420318985758515102654946125441269660837409238915672001897962699478598041990075589886521441064560358563559487348615417255802248342795895689714461791815371429230454563711293952751702414862279155705544110192147527347653972722312852162416374025674505688301413465774439441756105955294900473176331566621445738791077741194576978122574414965032236779923919277478682933737307770 -2672595244803421801592931746820540803263746806598940365463920227980182610517898121027035772934118347563393746717276977061927586386110151795656096461876876272785144356791487829175133158508786924734979835418289370095952960645214754578996463623195627450646858647820797898964531896154156399276418175607596210920881283420761021638343651460647395381881181810363135245510215502497437326857230458977569308759567044588715001417608512461287542718265193567357502195931827684 -1259473824585843210852949538266444076077353366539248697930420908882297694249011870901809511374568996247189340300430431064798908011922902521734490307432340897679955747780256218648783176737297857837720402549028192259647997704625228160427860168005033050218493896231043414563340531903231071906772007548210890152354447942967481858292336506967469212495356169659327274606689415403474671358506130990372380638089864628790443599517322053544641015988239071831831266259754937 6584037873970516916175523875541548193649066362564122846278392923978161701552730641313980661327726911010328212669521263063100634200337464697385242291838332418024906246210366469115590475289924505512570109057098969975756762349813852315466675933980738185136389680559885861713756383948181963174097344779475940403431339481863140401953153847372900747051609837855393992644101873907599366238518708998392386662064777936248432181648651496620039913535253566075446622399066006 -4222577109436598480014313861543840249053289766997534413021994773969876646317355098302218736733684073192925232891146236886812558380468500167489580312702290080980587924148880776620004340877344996058303430982590077356791088010755173698390492794375985880386469726023784858511245013394930497048635575096001377185041827168321336280547596067787468023550660510014809299243389831351748499839513532418442284319802894898476490425561233956855368964201029122152702474876093743 -4346199597090537221203430216057133276631928552099737143660922962880268177207724733170979570799501380200717402379652281464087739951522078825842944093169404515224528596108322761307655102413970766638910310301831888829114983616662600148348651776699804854804606710832547600859659233505465758961104186690292266707989291787936458169655364505753088248064899443592502133704472000032076345028047757835919967975724260184930987812144305605461235157731436934188711095039264962 7755167136755800904039645433959017276539861105449822400199673104215884794942401431906417782729983198231745561115768042094451362435881876914428157586404385769514544060789294812514277805844781759163798875194602286998613932328864302222187640002413675716858185651164419136637535102730580561356631636640053841929526912599077690646907788077332855877463975374619607718170557025871475282140263795778497553714931084245658229048345253870625469102878516880558314615020777292 -1283584027478598933598700317648467522503140174911127331068808662113649338770766248999706642755632375529630765971938744795165956848804146415741828927304297497572160785593326837136667759086790651283678287700793892750825215597904826412001734579552520407518792792110293659933384355349035842093051812210632581250422161459606313120678162093051836936190953596899349585190084450571427668651816526049185759078234536105025726845442517063036503940991990520292940000219866753 -4878025525058655497005123173050568931998536394584955812898600412088454874015630445747613732120565290707704874489359431387121544428010030121590104930174418088529049112601699690074482125374463400170490854995790954737226331132108989607371885736448080841011909854795701424685919137224120996485104909348923626826067830760429669899028679484740956322303600252511301095115662543321782171540230903336086973110565913502250941581654761952712898306711955550712451854552741705 7627458041998047190195598682029975752029607838272282512131598028062641823019140394817117072249061450915786177669416295856815510441819698333382895984078112363739497983658579689060240337339549997279439217301418715193938870124490612598506354136707236893549168596755685622676533063646617350726637411373253796149349090324027246046796788097016284870367664074557331681037433985880317549431816927217876856536026090146764283673899562207968648836825540523415127629655613 9963013420094350377789989464721812758622986114717185724123593146500304479556005769203573837838401742515998887401327994172884659429062485402281475084854995657643622196187855118512099737761215178963270207862266181590803592712382349437118823692487961123427159157939628322233076077704481766302288564222790469690564533726113248919765327259506868384104022756831344253262347615204102684385934089200905985038317500453564090922113910376849819062240351306834314880002069828 -9561107856515828748985055772359160498739770304545221292750064268696565033464454276280474774042044025545265216222192079612717290663297857280946362097721461532208066816703910865571444471701850313930556467463113050853638411766402566814864663218150893746256862965359941310006434140378444004067471355465139340935633370476233449939838697260090957769261541224778054038755342573620197960478673948761832528149004709697140248942065102102527112933096737301846011520342707916 -2849958547224741295451255769727983450912143658620486575857833509211683533440831946675241762004915170922606268333461115646313119300746039340014983839027401333122110934301620564904480437608606450722692316766162524114743477783569744030778045062388137054268091920619698394556328010709709239410769131533500720412906723863235583965877302489473109511026069088539945511733693753548937264994455044783041721423279404856249673673052794842059843991814812605905114385324226103 10562385448037890653261099132189805530820601034709158274413791966592544632905823489471416866643267315803512220017938055992157332955783521055855734879383584565970977746228404741122869774355351595824698789380177346845316199280743558842489070100302371585290363754258846411566974640817781631054607821182554570779696966406327771056338241567577958600462849905801057597116459403329455389637351780254881512052723953053951695843122078785407102395562648159969632858632575582 -2561111855575427353973425573413657147603985847138081336430081030028684129959208580206617251118111171585772754653874895880830682686055156746527906889908298324340450222037872703863340481048986841781173716778856148724540407549639436961061857804676561677853335297474505182657541605509082826146265722553880161302962129598596103878615283730535487299304168696267915132368852142994408511836101749969867217616343502633830894126200631378687444089762341723926683186552213255 -8511210300394518120619767755777674389865596601041515278475468590469240660976698743021164436537311144049325456180051243870061110058549959925954897781737522145987308359178585046160449058764886820452938026353249633353133885054199516392348210526618154375078654508137315833639155576808421400687431111772381869776421083198479374342568825262234147561799367007335315721742688967273573813026810523987283822504536363534820972830182309751471381756826010043480865165077682388 3809466340549374685989650105934114880232538461513651108472794280150860179941113538234845761439469838502868690419134332049090343877152506989930104099455777462210637887604605291286308953396722286765114395145055179389964783335625572309389105374059511211279881483009301128693807049296865160785495348546915718206782737463540691729304009307155916427112872329113252418373610294039372751500861317387925730583774535092612845288014595308240463303576471611005009080693946127 12288490252286161246858111823362332445363536380441044140817109881278683659930527265597857302659452539519904886780901280452343613215718907312359372604587981038661702944364571220325690145364477064593488651091726387263638251749293626381119614199067036897943769505957022759618171072446263654139092378547127235469987326002174316695152166223627755685388846592412413770790591383687826257349455761185869949434360880771101340503623985032567214983746725647425771379261658131 -16190084637490191978218738034448714862166819216549343108102344833928988122423201533163046074542506574628280450935915996381512201172223538023647625050314014340724914204176955039192539114014185635378469570070669212276066653542797752050583840493895844439171291990708286456642957844094535603520341211844947552930646344836482095590703633470834244036574961646678540004984057311635302889992279311288175796471863075843279206152823607153662111346031193027655456227309269149 157295440716270153965674132884572766904498641009680509935876524551499573035237690286631598789887863853540426579331031556826816262514611540695213454293426063735768650996669006042890244433906106677490490620322679828375266803132671056970770345923566374992173876846526595775707346657435591208405477448047396557461102220803465428432597143244566902565961926491748823333383096336909794467139307553251479505279409284292261051864274145192514413255960716725974600027726792 13650482889152555079422062680897221390966731808370675792245575140218106479750250331304217007046010153362217144613409413641808583125287297635205598121934572418826573022429646637791704718087060023248086336686063701534960463036147738800709196514844837756419927590728313223685021043368044999522250852682759685048068826996326780391298470037800496977116322211694566444894033099629095702794466638269964385971786759439012299595578612687082180979405453872922223128482007830 -4830768870056803349861267518958021031357191502989405247113595549721028134183234966152325408936105891850600438502063506655943057813887081793923930433205286237022968191377947383333469820338526881256100463763753676849983696574465898277939269182033244635104945439058237210892192925714154018811653311583844990075151829749142890776089834244892096567847547115444458254807495980095081615344419492360607466568263790102606338154291663277690967950562582200475789158695072018 -13048586052284889577526968901004529020880235049154383577246879650477598686420360487350805892104813035602724534348701601009611977126539451354248674878464206268804400934430054345145220148181514655360622981352372971884824647882117896022124804408661601493043007499533915241003470379873165360504701146350434147938455558952393930119056051155856181197569764603903427542287551042312668617050165816463734716117062873313810102463808413272053936047340438722752571106367810226 10638589311007678224857792016879304081687110216464703993972151013283783692487757632789649545127091631691047643760870883418955411140917490612223381897408964918581829558945761220866270743107991003554212009641333501591882749095940648516873511700459879701962816587121665006805136119706179060183483786563405835515844565637904061161913730023447615297692039274752738980346833102989124605055070279919446609976693756499590664052286152225531593414066162772217999441268522753 12146365388984256708146817021330857625544502624343848044964453108991855372747946599905870510883107581824866720118810631930526381509878090742941913600985586739664390575104580595240307115544559430426507986056067406498837363093134223257641547752067200095835995271914044996548931230790685430772015928264815335487101572279354288287725939020055900298998324272730385609418491407720541605997022156730417211080759113603794144510202847430099926719998400138706277344107887990 -22805059094021837271511688414031785708192875081827671914568140067731688008674796740377272860595001937891010815117034521886201933879190068764343493358438570256807713115860786335192788782947552725881263956723095383731764683465555749272058477499353864769438544690291465179973781730708497884864037346276619673693008109877716917986764493267468425864290879897597539778366420512334183909021832983605327925677593667147820351792071119253411181331408337993627302823267712717 4116362097184628233330823570850919638990236883057022348412364392032920157146909691187558722358065413373961673823501153277790694014208732223797718305415233291378471899021019791173022052550889610458797834023382713073470935986271715901529817224261182155796122987849246493749170379455103013958098999769215571003694096205571191500737307176582975449835323979883054318162763629801446490815757579550573211133512398119385702111949064060074244005705164420077095718326225450 17415532981902519080194316031079233187981464684372524631180286466135935953289426689462196904548513150851313791001424263940662451202593348417935962382729401127264484938606940211430785806866694666862484000206508936362817413876157145903825349142289701279307010193987175321940280865542130411085246872121555363705957010676897898457912108468825928510403871693797857648005451202825759837635743792858946509682119078408413231785855733400685981239955490383505319960952354584 -9250699504016724910382894224362331115089880486431802691322038262417515767831920328632996596776818044300502044552616551171536127265429439416625961474073332620992479767304637629988339915847449182598960200029853555191657944355983074898290903993463662698028959964092698035282480286331212058876669377049626028639956633378792277896354872044758264740108297894790663002888911586673102444439858768313963213672405099367120838120337998528701116519858890439555015977110175475 -16742310622058949856888834515525101270399028877519257707995535954101906149749499649643428386386426100689932110273108114137716204349773289772083918764331536349472189494510390092967398667784187950756790060183810693102835582898398339595177653814097179796818434145236921979522227155737785643750530232951560416024325939603229077479220101629775229931324831285251570071968305347801736012015378526833027522099823787008147816681855641415241889241655379795527152998171447806 19408294939498881141419813017318945919513589751487729212368331502597813656702473822740451156258675274912260605546847525112089247425473620209905097108604821736889807980677595048540360617845158125518561689139405067799058630298264208250633999775212299198948575858565976560850306380378638680817924368973566991742953565623899102287630818258482991007626718581858522661369102941004899104053664277873180431848108124867298010073797287832585212332898342060340256961822490886 9220648717974103527853494011622652197026179251668020727699522122562531508094359282484479353224147991636107102205244452824591948564699798503287470584415488325935907979204436851905128712055701742488274072700335367514311707179332837907640933815425281755977513496162926276829711993949709767738810247592006170233232372772794759180800979492110777100207444924454464735286163373176910572266028373635989991002217660544204510426636847919976353591932863401483457374020461515 -28469701222957297343618012911882573159884292860984867135781771762078872176570475742667851823748476149550501863961080074504940944847770992193521385452839544873885773804089379338154879487474740926761118348981358614578721684928305293779583059894654081219161117896077827188757146980010335383329903379470449765785652505609862902875716467811083131348879316017323153447600615513780539504845163988137834768249513857501578903650020511237050469622754173155035689477410539448 8705012680914192115140574618726450698459233890319153136052126560999285521383495713703433818781079264607218363732906624233357148888176404171879867605922852264408911757463516227052783620023094185153848540901381960173794326616422724268181571682839731917550354641118887586322363542108093562672107715987287078983516967896762604016728837979142448270450312760832810892843230341232353801278778362018442123297977773363210676316836374286862633085606807326731735161540687008 21657034089870114655267240066541626915279441137447304840698330425092588934971282977687207959998934671501897354061281351995898023548087742195174448606172774241288166274543189463385171413686738020340583117285810386818497638765200098327160575815276677496669998336025626936906961368270952034495878225701838695643763030587320543690867835533999880691608817615537327453543770623471463997569344637785585221618351298765684297565718091555373823199523549701495592911760208882 -16454834232963320599411281625900014017391987489347940009587914744286313799765496471404861247195309525690130921833595296499470507121145128438777893885819174741825601593799717000696150685183698142350839796395267802467127440482454373891523869478880169100582160085671969611682627581526196744513265249150760474923548782736301290223017320223979565922174410203264712204533717552071170164610539936705400737296856781252388307410257174400781439051724063902752599214478991687 -17476161440470470083515438870409746239888481776910501643672608899872804525660825697146600847915512378557234328768925493282245292202613522098243652420285775042526225405537073198691627977933890915038826185100670458444260554484932361471577866504467424015981671693727904075254261791212059121894180122709826327185818333510253679082823790752379300902152228516387789099313834799057506014533117074185792599469084199555966095789600674933877427193435423397076846295129451666 27720038403541646509061498677677226460413285199896530702807009927957069725932424776711147789221361369165410605567253978709050091054622960855723470834635454391729027276270665555012424394470686647046577080117310827638925586753484279385529403391187243234081931933864665926769018917490427264388010369461251485089845410016409668190133615751977169690023929396355197799644240173533274778351767176493072073779269006725635082718735426469572024833167864273450719367184147672 4611612180796364017556387045810375047456630710961928660703992181244566791766590222571315819361400173113585352464095867458336865184040153488683799263349836980742452474762363297994221754811356638803125394004288100541237681623164316875048567377946584481261547359825262650012025299331919380097352161393413953160179696638795239803454844020442778099785478254113959190252954124265489618968833548281178855952521081198772161507895401797088271698800446080477137933714294137 -33152471552651025077646061445742261247235951129006892038837328972247089840556194564134524849952670659629600006592961538832029923101757436759272171634506580941699365294931247928565986335251760902363451857610510937404984041332586692344544015801964296705206252945628347838592847719723524710168373066866066945666866700156914601451337989958057382890493180413482505731075942411725226370318745901944978405908398542589379166567368270955881970326201108834398158978657175058 14369339966270205409903109503860820345727292605548725946578861076941370348015137175476834481269674092398558623537087141161789264897733023220518552532710532134381375065059744153878477068958356025804716308718956956147877056850103825049013309457110280292562487236468580928843040610835687629891663764705255205382792456965472296940016943726164420695058333135204943966066197987603001234203850176802888970341847448662852281405714481474992019627413858252870134560163667508 24845818097796032778612228925066431392855737499449750317146336622205104605327792841763869006098046138248973944412943407526104824206732716157927516116805149232430772258805499203432153501492341366098576302977853373326015173544942740880779710879213183325241156198789354880742426424896547084222963533683904105440021861994051412671973407094255855832031525367055086958593818691729216101905521736002194133218701613398869985993985508268839328481945582203199094387921873643 -25311530921921353072796541609394048271924214009964536691496215397234600683084406291046167619635233805602630464430034564441440403902052376503723743493277019949371163162166300179193096930094055618508204687479080093615917089047001303174010805154367035962250542865600763858021383534336771207638438264185854020339090803684206069720010978936786363045511740691759867335338363199671809412319624861979959075090783886351392734438644115135779287495705044730090662491546444685 -14409899299695402257701467620241918396864642208396342981533982910460366154549891702211503908735858110201123672035969433015262363169771367181320932098729593547485211139177214848845572761272886972576244484129529257937836493087306398693545166143033235183542991246175989368197122901174156831533293344865058566984511630908295437774246023574988589229201388440244176858254830636541423491002410836926160734229868974558326280637855994773610404977134253727006617619667112634 33386222354109976922546632564249772341196733004371493301911512483965156198094852133342319541789503072035765767149761684324088448227067775065596357938452702983575776090460429177128938665782846315966967006158926203164661748595894400081943310581497734013633488796421329475983875612938352315291510350201784294778124118920231592943826694836894542498945088731181499840773395302237317620329947900671530187565067202360705735873163122554303192734073520136643641297159131514 -177670016142332461439525794843887454976271100383747825870284661262988954392359036291026890703342843773527507913377801650210885947158028470790834974828685878690080027287841697967061544945730286434754451099086129480446428302734745566733537253676430695887593645119001030823167585739793526742201582578542984858565905971889780871823128960817951339505955530020239165147728567570644274594154667954459783291975210233799281358656496306257515858404587799672676057833359666 -37078056175045576742151781215389559531876620600782203401852814416525844470159367967170065520712024405421667711041444110212477138512669663540743434569192479225668187163122828818965742253002430241496532290971553088624762575877095907255429106425677680276301328416048572480844313896014003998765442224358583106939796367013675104140029972873749831789781564615800062429445907337613041366107369510550741371607143290738286321182058031850401191583603811177923487101514494641 21676817828920135797291376946951531425055526471879692080646706902310846946295089075757869339706480240058043117247594039061734899091763041309601072604105303564128162695089034036414652030870054894198567231102129100533657952646656507493462059768762421978780210683844659473966390873484334127838280555521182198104820113139833820581240633905223134698141050261800915143951261108960789749681623440969946119362619214943596462574913270316842865592709321481089249921797145178 24728930976988941172731987630468087539404342947404601116379481806413208673932082996194300193696045965531369396937762770805677743552215844709592327712521128185562918852680524559003114325115747194215885568750506022260956596876541495361018373285550364654296456890539848711419533924421456318554365521876812898366569317433934445482060573202084386047352265883214051546611706153123261616261298520243999379743544631408255391729397693921831697810827212706096334236710697096 -32979609724307684729170759661684708315521236050600758568737999931228300209040057073692746209962156157865890834816492089125760236088004633459489746913877046243439570983774422784298292770719354122713284492087236373440315724478394441485443330168757247371399116695003490999525933002458585256061485635803102264522552893092297575811367461034253828712781570429994282310537575371842300415229664457868151540687386365900309342312122778268258997975097659987362408647656298464 -8803738375858203494424527742650675782349013225144441588825665369684755637496842598678252060736249128727066870453939672385869270716214170268917521994891979231045184516831241150629706402012494995129581989545296217861379239406423112699607661198833609357104467923467031654787267365136161232349440664972018357147838452896067683672644651231173140458892359311610803068175173415735199798306343663870274461791165961437139110280485967760908100484270956495775025978219714117 35804025617835924238469217399576289750554507579720730711999559790387731210496559068535037610486210814459958606874651867671991794773492583580118974206160301016736101844491731284785767446470452669200891213373207446226512454820654018846139822067260559780987036405511858109280387604020359769581140880157616240134956344290471380022892228807888756114603334403752395220405729322589492868731653121504511146768693879664486566835262592951562960365475605581691471977855053078 -4550449707195185282785944114149217354137370673846334177123694861976488816196876452059488881623555469775552267390008296249615762699062272021933858760470714076672215053744988192919047778437079419090292896651845716602009510506937291154574364085268611275660618751549789117562801111752965085174314336935681196041458017302661422791651238879884154949853923225185472851619624113728082203379999039858673724575400894856221709453722664769455098055022450244407653528586000287 -39614647044556571724518286396442173314942289154770580288798458976049921677190337261982092811048045772143679735591823818320093754820763438388112310037142854662943639681693605764653612556298510436129024987846059505981700960620250681454861955533336708731174461400792945738982311658790664989136385189903452624788832910712865635764150258208059467265315378585404272238609942500284579476489349150824213029661588610102818133088029744210463860859019157544943482838133831782 29974821626248825469784213782881469670840997127346190070730264018997089055422227066779933329183110267901849141224763570497570266464064866592663661529496482509471371934675878958764547378922234008416174231357529050885366993141298960375573975911257015814299488371894116199623546604772540207007562057853829113300737708219872808114959932177874378207941264015189024240088477795699103199040713676619215693263466994006540894453854808552959370958529411490432807472142842517 20126364262819236400263873743997918030989576201509131354840567382366000867290773239413351668997047139354128188192528627517297173955505161657106513760256870037831573865416266951191557424055309532347500911517651401084812493984560389660710938766436410710234363109065084851743646330357003585984289898122274838735970812567327376330342291771338436820547694540813591526967451239893635634695733021640683251987565835251386290572176899658381752836679317948820805123371906073 -36670111594283184153277382258523467707937371500549763951595092702599282851909571673310159959566405146002514539557853380297477720576584365289341378485937958607103323566058574221836617428061410542749067910961827240101537917455590211208674225269358246760679076724970181869962450560846847461705710040926558147983740206445694749884008601599420347442350292205107651929612638429627617783796883238552441444106949550523409872760756308493207946182882704244377410600275042698 -2998376905679967763207309225535351485130317571295702775823623317266999727507079254419195739150555055959585266548836941174013516272596242617673051601942137028362311301299924896511176715846495453154491940940304510982051370665958627060513566558970105939393440955885842249273029527750747361875377236619414794208587854001038841531140946116219640516410000139771960855285600895825329102587423703863809562426725162368328172588250076660953856586428016004063604153349782008 35751925590301896932096768755658904645999586523119028018840210204979158436799242796374406031598812696898865136796241765752456764893873649672743502943155734979097209565378530934564444394719261136415493637697162758461392953435355638676858278924022679488005748476191848165662433567524743230602279121349012436423760905723439950746304206678191642208786439675355664545755763830364422622497166631163993165744857200407567356786288812022003627198873468138067511543937596203 -8878869414046290649223576317980462401955180172827707386821404642336421868798959713827342191814610788117140079506687779935578621347138138136416993473756805528524239617358825343346608481773123480081205576138892036325857861331500323133559482907648405311883134051060161696543586762837346547284628067520351534892878013448419941744388958984617930737891641939463957879492689001691559126343131160249001983330750937338402056063863609293694050831310273640572724618199481169 -39261291371498137214559520773203393482766829320920353539009269748101136936722994147369545012213413729486182529814494883774464568241528747414072704900128269158374820908909553620078025746949693548445997733684907572436038627190639233615384484359637886598333982105864066892199127643748676320458165109237597200817340722114203317559486894800171354326442777902968760744532305565435283066191666815674398837360687515052015574068816675627182574546745167926396274052284261811 37032023526156754077670732284119388533803006967330255496068273384086367428077697011456586917857148127876171043555424642045519084918693349136639047080882213458140868890882443267060865291324125882654619722831545659661263841043683999253136915030958573622905868417333537439536875542836865910466101191562762959934627957541774188775647845907772019182441529028588432299746308528587070925453679657686537573454473392385712692051172929106066298326745244763614140859052057478 12149716259940404626716904893160884013275477204773492681701421541622904748750822481095257507715287381575499072566698464470953670287909500238611240031767524363570829624565390438417601969176962011000172037807226559152221587277149734742205396933985345925103668499367254020755677587950264550071655872314304956006255912514141402368267964629638146088953505789961690261996708580242113638278642617022832527271209978724709494068007642271577723369483994327952461125783534245 -35548499048725559596038129864281738628923831383285092154785533564995254566591090146075363394109519447563304520807421175271197329404748262226612827376745717858566265601085705007974605878916998386435527324176676900512945622646600868625915593548141908077445521998819423409206861692816050862976861645817745301691212328645819561590011449314387968938637528081261205516516502792481421021874539786009580332415371098568850134334974100588005966700734680580637477682318168241 1437030250503989496575224723496457488550882692681016972417303394532457548980199118093738167109795156959091635473335883502820884190648739890182507163006796590115869249607172666898343684916170239901030018195078096876208487452280747466151694725278062613774254587108509932315425008512913155608389682683711888770066376907307231862251236732492875099168940339026152123794270975991183342770013375790088482897337151473573488917042871738649859359181935629908307116643812913 34003324774944577186498246153604088466268778054925496667531854835137361033685993152125232822099857199857225591286819755436229968213355692419331504823349512082667730090002390384408583821041872053581480098873384246029720217990025855387690272799978802953219597555947464278454470568084505682931920292475173440930822967233130533723881441861327933038002359642560540133663163627383597090149737144487404489477118971623086471683563514558079974943393278384718387906326775638 -13298411026552678757297051171004544241233472412358741393945623438297383190957924900809582228891845154508249700480104649332851114940964780071056860553919295331152274994219454668512673402748920784689496986415248557483727826305591941065850029579043137792437965298179012842109992245216222052468154679914128596407681360431617063616971693686881384137185814806918507768155221916593795035131646830207826452912529993184278657001093980970752106678094197495932312410629257735 -35053475402311137396067598296404118397478145659128296804364251954773801880763776229809154308514406452798773503138496072499307356185484899437592698821068741468150336845517798570458540731008555538294101646039688231703807869174982939484870505875834418400052179486367470555076772972297514903231699244823985832392041803577655921606266219323282515528263320601895774481252023586745462163852153790554122778096914577751047051240900267452978713435918427548777198269288179026 40428180207018202889071833482366235818078096312956100566199654308288729200011031765280918187192329542188749241652194598613110862965538769047285279861459779223930779139370162948640528715860681817053125069952953772665312390183313732475587717833642909291918547653311359365090211785849245639896911061415896856086451911544201769851644723732953073141480309202593643333113194070024586841438356637181240574338419693434355477181384441753580801161026194010030422264676485860 3458546941960685145391150690035898033120687715651245157368908088327830990941506217903367843338296466207623217727114661765141972776672842535319277550239143083627059498308944083067665163148056230630690858893316652510642087259526511541687688769096788875437421732762525858556184801832762276809047798283672818513089891027698751118134225331057909018687521407958906750811473110336324956007241895020807633825316451533973590199087247810677824774170528721946887168093918534 -30916219459593654642389430596856558198852794620863229637887379788417785485172828902881605081203694794164388542293267897325393713801570787749443823516772957094453239683494457413674038527445284530789409964786114193667511837994705023807189102915913628794631139972684840276567400015316882439591419233270161638656980742375053259633141206640513904045192401630168099570077483027522328053027483874221700213585086357430271010994597049241357748902599246767438758287827374673 4443137565002259938546073743382508134159233522893545270416439879568399452745779685109423091180218222044604225341887925127612205879280312005143776734147031471058276609888095892466182669891792637574824552890567398105800639806640287122758345798444499672194731186464709197595125849112372869539743578499968943652834667978872602387191551299350981244747767190113108480732128664360448364781367683876898517679320356165670223663299049895416204892500409201846585159006095925 30523464159452051327584598642885203008568299355398400271192630929278411066872628420736502961555739394258366053396462691543281638870007683277913954615901851117921613491250038310818085189836741983885913404070507808574429980628319777801438643853849604469869601141412083317473892855899500864643798156564688069603472063454811239451583700501544939024687420931825305707657658182834776139648288491667170323886532033350827981946575713624774601716550446483040765686640912878 -16853861700467839716912525427025044018880482716964905209263370316696285722977378156893560366572333305379170242370057865564690824202860685125714152886754413178048051877235157545387311034025900083568343030087782867798397086110213210922438721098538787546306253925735011332329329274798203411000286095834236208966658281100941503948990457429849453816742121060196247038878843265799770888309797053495548468721685613722958972803386869800464565784803351972842251423810450242 -27834412938195902547869415311456999880421103551210133280009201953565710441124932474182083606930227881486118784024852624867426207691826713260073389752383341395221737149338818992804639935018246287020334284358399186436487221843177787084277951565784179239294736033424252667540065995453148629881184175964320853589814718811036499080609274736594452392177205502064389379966336845079811929634782373302732013680643155841756540653799932924985818569860762193506750543061816411 39370248263230961336405575772055065577124156588634839381171024735001891821481627498891574904677908863499111103762232146439869492104546282287589848736956340330802518994204183915480113288089949782425934839327638960854297282207929571717559005479049397475010023897028474457745058267893472724776617441452553332632167738731278547430872023059897399998987825235495583792898287047872808826645432946209884184387390069346459898668780913304889573790849398279463330361670166638 -3676603132902202586803564987508999647036243423768378508145614548013388238186056944030084741546278203329441907041028098765326399626631429695298947242935460501198553234587812380592232703407373901061334289227048370879930072351063727480648890419159361416649020977591190361157410431908547633758775298553647358032046891148369770498363699736760282573210670730098050344798166270994751241349394873588711415427812011982940629131104856110522069071951152347080081588365344442 -24734013960415750302742750458087656330081197380540982666915364411151997043047810069303159803741862277843021795103700414362046253756546074674216517639825499786350056224525069598100816865916689205579002449924888043696935710434390298762041022978126384758090315525653592432105481768401872418381594216992024541391613364882454638745028900791170214490134030139564828027921432432564000209773004589981644623666585853863861466628767728588767636122888985788383568500407540108 6592910153685827993519278941968547467089298348724142658471232435139821373464657086861907102219783235089029635294455966667374257670625604234225650099478072045297877596257847808980494168797996290685587862982490297210616543465000795319675333381002143178896943887307224082096664990280334591529441973720713389349784617808663181294959970264036264451246990808850025937837012455481129571698388747200139560137173282689787516517886612368230281307114926185636195320586824931 25094405720294139796480360657572881558485382161919331529953318624069561936237239368000574011443330135016410384453822103868007301034598477749359743020224608439991470358029120706036773113798354867892902310612669356132098072819993351638672901458890903745905123490694934823742346750818603962499106038909378349657323270361826886290116661989100378225910849298457932767333620538170643461794641561649046720198710438871646470729475615366399599912802077367015916794820792508 -18130956487494512640337835234954160255388026091001871955392906899371502790228962524557283666266738697851857854363060643809724485388321495811022204616215742990186319659011703200733304874061608048005064806807166081363506298199931767803990905056378537709512373733424009012644633505722948541686925263745913568090787477279600646321715169746044533384738351744989096522362558395249113953806274224854962203591537011791065297213534634409491763522167101265257852476886177801 -19885603056501379334777168367749103747306979928290204604742195107741035689151078635371720400598701848228474567555967435198720057523495154060999678759896031293948525923586866602263839508912612635724366428211358885569357015035907329510720526184078769315097328708336934431360744297542970398885178251763316397054062048008910978910151226931801478702612963099259042527644439589789061407746206312824525861938896069022392075194878286206755339805580874909157463096675570096 35074048812849687960055623171901115857173954530350363255319969893403156333756482967422074332629898900038972093757483213526348611680669533363149444750357867823161378156723765722816167141137888369860885986809964770624453896272455894284023613342977912946206092404522454665865919514745475071010298332434568714465483931215724210197100593673157659955539597834599084754127150277384969250064402414062810873691083522505166304536487242710073970687466137099778867577209830267 -8532957870715610844431960841551393925279283784266186137057165423676009724003244840843471943011066238486045291675356403933269284557543595439817948742452735462276599091050534932884669187274812336419687412229661377472532703351756442282522745569789229102796518726081291585307106272769436593786004219948781949419264781462208266339141049890436696151914860989358384527606555926999764132186315572427230469980678070801921688632106363281466201831691906201621567952665222239 -18244061544513467356809195637859240942729370429339479952697718848891628245770757662177963866460802217143312843448011775951190823566190500733756531566203986122126543789320847260542524374676777072456012169068728805158721200645354833464008926400036408908103741937848474909678725682667387629340747810731297778528204134438575783388858839089230667308037817660060795617612521758679199130502640942390745913628089888648954870704442195202618034505778952767117409382543545405 7975654582982839167149487890903726841736958365758057550525362513961324711557908837825968741070207511912946092366143719964877068589598714321719780266416355463652467188563498351017336511179510399494753539316983840421739327239177672943450182668835749576352393464926008212871122939206190929468691057005309244687398991927308498351333092941359128573638695330125932261127947306061839396120566071295623393074796533657990259479660199299733139019346897205704866512363183380 18321381574242283665062853878797078884123579300331171131362900791592421459074851797242242668110186713557094059324036921883850432378552227214282410483077577900533496956758559904487586206935647553113023926769379152483165671087253167218588356566837024470913986430909013370830673260913987499469878368067168385344284827284408369619246493743891482795188954969568327878435110260863129584109651028049170707183994857458853197908272378667686242726534407553266324166166346805 -16590431689125803708246479346870386660087671387225020292709076185251043777563875443819642088721945911334964166487775678911092037964323810529685233521436403866011948469557850281214068362952263666268170555994427291296870672971599155585155539946733412600948294086012564781140960742544259124580793565261110026853938579513504193690002231322221056986371408052279264398678530278834796539532326288585560378491320596355849506480021165477430958417805310081738002275507897958 -13324339959980245925391758278891948717249717192577124040748535348122046195786367173984936591747943067779974192908763778458856018181085803771067161954806782067446505297818352555223825743539340314483288139718092956983803868987894806734895572284791577348419648190137279432523276014141481726445027804285252610291510454344045862454873021826997067167244271058502970716017607568203365181516384005155775757931361556648458935621870008350959230158761384134387882541608144281 29528764746027428733281815506031953941872530116952867653947666162456734039403406299468092323302446524276371847417280239331126287423777728329262063915909471760081716915565775562959934372542852789264590114062582682246536858087833404308708657601074018239216756623139423968053626669927614256456927224835348152138668626977427844152641341981763823491586824381939382775151943565028145528163607077494429287277326578188411781909613492882044500284133150970280002791702032186 -11502411105478863671755954055789511831680547190962290879801754595078838738984665905417276163015192526930746829620499434466802493822262388043946906091310039799279814973419620101450186237311730859716646059332920300957789095636948123910968116678125121593694550058895190726244309050578368777335125500272133741644158727002390161222273004852160386632292485115302998279274939452889793933785048031635701321983384562701241591261511570376759806498359540499804001772468809683 -11895255994048490065320920509050858966808892611541499842969874706574249264253342956307773827622950377990615405231343799739070921742227863424350636700182794607128933180616484471931943850782343199689176770292398732066593394508191537579358604509440814007756415082280730566862137662722658230699818292183017143118970277241659249823496494838541122793640552348653600614093017498433391292304210003225383238628835380420009256122742636031307920554956060049069349154194042026 8155673743794720445991460594445976566465654452157917250403813790900784270465770485784114972763692839822240333099639866780026134173573551347137473482985640145182925426345827668921788188614557749548639630902546189180906294689355347490311368869948637906308939969930136386563594098530246805643747738521776387455755935313647571349324669283593356994633337302085624628576878680963252616454267073931343030473957492749460886869050131162594720519667208191564970266286342205 11645368849337653006832539354398172084307941210545937768141394801468307649141743527933790476940366076054990271930780592527799114235087958916230041927848534409382946792838335225834926684369445042976819840426352867841657448840709710985491487479147152888838408229271444755771840026606846066996281458747726558634964874423142564006180663802999710043452775927211985710477166372792335631367933261194158911083173713610103571814172337292096383826761392476931514260733935954 -13055418586949405532293119605022772365396645465017105319330578017132481739120480120559271808820231007975625361355100373894392340644485975030310389630055114641208482489400903659228405475509142776078243597324055756500642696489252521488982835360624164718254365304849652468126766726367347757374399541625543708271899856014774124161973534058333457140043901364654742894896638667078978452119234650955507869333983499707420432808749620219302075236824661741376449896383199405 -8934648507873495069668148971865809625294081174452940237012115578648334980973445616731334846852146952277325522830349458896795947223273572272229782063407410351104979571226515599027716925354678123569704038912964773233145955464793155085954363734316392990576515065828534767262933871762473722301230157289052793527433883033276867606369851114935244127532046764225905831161032255712786867839379603661277054543101385186104980077348753684480487087525204481274517612716809596 24109066055819791927265916188858509832383086513544291637805861385134375351919848092752950184660570149571435716984590271362176725924215048919080050751072823660719245250835321129278495769358442342057200114076824734898530762558218710482533720420299778659063961514428911827568562554985942682920688688578147564640409279351013848398967234785319037812921218633763457127865418309230007646904535951359970412014704266194034742413639436461744406377408265390029982247065149692 -13046899024112574726770801215925392755318942406874791967518790501565925830715028672112814711109859586245164089570807663445923701002752392001401577920481222934112524547239012708860245635781433974268220966286041853230304872230268790071789210330130326653199088791942688355292601352300504561718023287516462558878931265061713047288209147052070288879591032084391867511414228217387720755329240448375175291848851161159205482003833894113707265721775414748310207278907545150 -6048890447870103664207340977298536994793541635952527805443940593188527447018462786817873127757147771792357142493025892165213263746352013439258488865201928386554397728091848676324283777729454042604675811172565314354186646189733260577316719858512084434533737598177741667260359725424324900061261365458866090486695931871066138326301626957317606200998684319524188631803574559098783767465312234864092884960465643374365952594973466059073155124349163603417555652658481658 6943658268908857781482959849072140512967690146320817916795469870382577948554887268795713992905065913468171579884584935494817963445145130580342098775627559952791710629045314885217684952253108366233420143994938524806490995349422815134870791225673006876642857683991068425251168318979225868467407476961858080116208033364025609056948833409271153374490451737813153438889302201396858700806917752639554015060609981473948303120004152142965492587293000506911752827641213569 6392059139602838728309509391964487818256634919529074567220983519537207879899864456843960125936562802920585192172024834669027466721093480410200995416482374392127978696990890050355906343581113981788641990236530715012184639205126505460177920540157158724418402166769141181870040229366378750479306253222237207546657858622280659666172996642621767881837036360238556628989085689091852704819312355720562384156633540322951558951793785387868797894477673245653523333445507657 -8970536075588688182730737584710621508803321828801137416398516002531120187542463397431125718119034477041197444447052278420704841693610369488739148792212622157253224861787722399954354703334107214613179668357777259908542851588574270175090614566807552847776158334349865546102507190847404015656310974561801290939079744793127236865772243526788875235197401810306458544262568303411976348846481000602989607999987882549113336038903155622597299990078818722379055965377081297 -6316695388654187247379028269780153394559270895033260584070145580398754882798621644708820201530002791248485370236406074052356844699435168004866951005386727316500333034773352634599113465366445988326441659473323751955024382875756317536110340330784881477254228637553330065665546264217975470286477336852468412253713197840039131404110000415374113994193262803489872560737536437924345315943027311561530770843387423283403634897039080180463528410475061486850153800236009971 19235493851109263612014917074512368792986659829992616205273637570922431370375799977800720033143933193368120334223758512484482259681967960106772559664819452460478107935031189227908430832654226583043365184795213983402155388939199653805622406471914746975627534975774511856323640138297708241974403330290680991639800571544226222503697625026540380665043436483889040281221171966386698945472840973630945276330402178589874103254465609156058080465648598426073974447139123549 -13270839052807628519601202204682568989611258558244422377548718140655609109747968911804765264860092561611188151272489926883733412113567243478200980660674489182315363558500847865507692920962646816899041842329706158838516851640276320189137162579964146308722815186809634041765517560480966115188858124342913474053918856550315876702858613599777395219676797921625879983087933453284560370705672590219420044688075487801069612305640011544258746261696336828735113308718016612 -1319490718227538989043868090395217207133060565885243115624621417099843496995351842316772704146096013711627857214527291593014173023670409907703637610724394433971303347761793207836417734258631414406485904787015106651948423015742776131251215976068330781298440510773883821450728926685680721114466151857116518725042480692682791108297707349677770499639949073062196723726089566877687920097357450375436705171708646897574153776853851153062885529861974804640860209586434077 4853808529120375810912365827060071386526536233302302327056886717563921400925253086661542126836677496983907463699406561295246507215368210942050632684446817953134982418561817469997777981600407188395014454889689730441435030494545182737699004017748781536185056600849741709401013094957391943619691114365481151798077358837662500126467678707708241525533677689197133243017069499991130849189052974008181869244414351498595426376951341870575405487685254300653886675658854500 2979159379802039899159150850721204733615631479996027832956653060883348072848537192888134903211552382071759382313787807580383687163266469104448850670040153511344390677362390801464965232323023130053203227757704767755230519575993917137242786763799330304019251756114024081921798735100268083088068246999898153575849591031564135538471844649578236719512227540255571462367815319182722182444216760716231887153961512752289979586946035465166992388818236317003632801772053481 -5392514772026595164194734309141019041842194953041543012348669509075625869522635457646477923168880314465135479095445522869176792011430550866745350880929770171816144562737961074187751388656475164253852407610691147423192078604149949553248551409000889433975492799386687414828142169944017279762889189850901331427065033836477019226327890788809960314399572887743312948791548081141297398669208883842899729583807219912929495203445813077888422606580649374727600766171698451 -4753128095673148059575461298059627205247176637858107764342138325320563711487761455615881714517283339412875723563544744719644848828234302343828767285740889179451432946289216160137157434383348543573052831508708847619083647137283996535496876751626338921741644652754262249546667280151314741669343547024703548163040396825864781171109913805068590776156112707138747995800071266432606494727649955259827092391593203153890598452525621959298803969280515367898514464171251871 14891304481814051329205732941508218936456440333717939858709906635826547964368500571992371628334715107540986427702349705106139858301787429088507082665457949036107544016469728937775441060455927279855981242892255818696718175666378134957462090812203970929741928008269001591174100277635919345343436211293757790195162026593906452351862564700174570892449530390466559973740031450283952580036046979712952380848101918871889424400467554627859410546799792637851710235861531334 -12222793348498766891743979627833412149636464181876723516237380955437659254285358066491646126654981741522753806802714851308096218677979434450186838854616125971738256033461813051120275330773761458232717598160773163906052921442991482566202609596759015796710452891825540976319546408426291034694652094170069736601489742384635798926954683312865749492975858227883955433526242672037336180946323443245785486552017025852722639310133870976860013862626563352633551529680622135 1747173822250090171959105970501676290867546521627912195433584257784304120556367596639356319505710177041218636114378165942632784811990204226658628566387438546485433557625871958240214640725194623457878900746249394743090402645382231470332041997206631665437869992598341296125443405318552822986791952652565430864723201801011338297969842214035015779137752952937821197285407691197020661785683077021141644462478826973513340809102900253907348533414576713967744794912565860 2774448394606595389669658640166326256376677513440305336196587235059301688225083626499206567591762010927861934666643399868182402925137448298068733823986707242711965071957611775789153921414281162835882135624041679843334250128694810368763665614837363446834050425084319715659709283831765664083351581235483380983072682208808559545605414554388815539631658656726896917749085289379053287285564953007876508936593782070099063755184586028639846513985848477534122211234976970 988036325569231887548978024447552681454132285895366884962577177858027845765479309217402216239883163021385126751579246944952050700932766104059426532563278005612167727162072900584969049371112186326480438876325199908212920687190727843864058014408083417929264317711099285528876029835918214460130349187921583813526510070013005161105105656056344934251540143887371109399838502426804094785025395032813630561855448659060756303712525702887717509634907492263109712592703817 -2642288847204351161873746779744816268721329554474572878298969609204906881476325654653440412227520648822981144949445749909192935585539180068551128572184302861122133253110123746550175861383763886928608714190164870013084156801774774696597139194688311471386610414269539461291211557220008459871074780489677230350002042368545925961475189654941244689420051469243065265405851414985671060609665348223919256023154628592785311526234102710891004529290484495706688028892103335 -3790925160252247409437061687594907986537918708443181275490218514837918260607241266713377413741778733730936147004270597394433718480553943276813427742879933925412001284140726504086776317156174454732579623388814953895306331970497425598226418067326351442106837940980538177921644072166621363351193770352973342065682049320904480321542202741924219432496920278079592474590558691055250044168135796099150210658975241861944551394076389953709529575214904386392230295930373385 11117114985798529077924647072072461073175562914943919377457332526207325382295082790723306883667467209357904313476589469528497771632462755182350070192916093341955624097804559658491274357749254920334731502201342310070268873823025755777265223326013346581642568848499744468843274671089914460717522088296202615993947663083501594177654848451555390831826794267748701150757256202880752154728006432817624321800380595212003082438459556191302145382357158408551133099812144217 -10239184767066142418700801349978793871043686827317160200729912964361674612276055434342246471159640891309908528510261048010927584255413242689459981857911419026807536954567025641700442210910203005750806591227873238205597677094345126797381682284010925193195558729713886381802711551965722779256740886594910369966983008851111893070303934189712897159665882217640066557602664693934476842201903560238875729106666826309332127854628585036970682245853065381790138087394815404 3089733975165477450619538061755176131989964109998077624436040602610004516933789700947053570200590447463450956050343127162337843430605678040319909830288462493553924071870802018959620542571584382202349070186016981856155916055040992563866154819356631154313093092326784659386383159968908086300945257611584422606099715185412621551902805821302289755307579876989506473762869295106105177262411439022290013780316712168532363671846102032098759098542758554874277984114025347 1350362118704732571110941148940206782648564630707166148395574022090956151556367395685836660717608607947829526317843006722895432449053844443290757288702737714728423695041597805378562588893849872754355015775740334651160525449643070443140508871981689914488593103363193142972822490909739247802261845937296815352888200161184034863671148393579451427862801410471506904818136111070668721372430868363765316749613804230731974402971807256093479684543668854913716225820553218 -224685738219021666083078945160315477009303609853873906941670492910761132043194395157444313924704403073093340992100888814582770915832519144444507707458239592438416382958533869828695769234763399790674648603496181714555222354440609618994717302836042684262901593986287386988667342046260686837067291930477913227801499173584601675992373414270576859868994821569414107840961757716112504026790376168625909107214796737739303758768934677343024862372544448410738027411341505 -611315412871912707613242296825343554891794011780101778303457357665599714152949008988923681531224053467509822661117460715650381342693096130232326323511224419875272747489258883072961868251838193855645542166627039406228157764259156325821989685345407359161667626949666571606610822213534966037481179075437034412967432635553590562467402718426355361115166105995614293162335102104961900048859152783317625815683756095365272988574262669979469023392189509801261223184559155 -3243444635548771078572684857163615019027397013636533527175950950357491093194783359568642859009228628835163389089810565933841568149582564787713949377451702487066574986841437841400555237878026968452690200320646232205251931318964963353552440512493360272236639468248909323804680290450428355858115866186894757681099876112632730352029429705083556164816481327431307890971183691444223783438012594898120835181012482155984614541422894366344392474628110455622376380921092323 8056262676037231307979239011415728750487596711098625968446667715290809651680622284471494618958238579516065393383191854911875664155754321331405467571518240823532184346257714436144346026205151000987783513773801087341388541451237072014156110418715942363790811858516685095194896656669861124934459021043635211568972666784320772599759049696562813706220437003348333599280868046573251028296528080196917310549148845335341084267372926037013278693251204204078980222205127685 -7891338552145723019895356105048950028704450703301000344246828572751284381885310067167355381324716140626163066688038005843465577777835608724007435084332559837051064112908542867914795870558598594941285536051663443257336837689880751738566131460080791947906997321536110444120298688676398896019866581615614541555463227856972041688726815484157416803947287863657574094914981318137260209529549032870146046170304661103437399072812280748099797886275770425755671366576767781 3144980893575367630148544855416805412684713967448370303285384452381284537092992634448384942590043913204863348904602166632288839436410433694934951217172598760706522244029595324850747665991942926215643609735099623790157103217105031886412924883272914773192758124834584359601544839252819083411830955367934706073369055196581023932315512226363128356056865606069677369796080345035308876682187673192358032134190332608679889805372318934264444177009977987887660555007326788 702894435727106389720123075722649729100728616876749516635656968821838672563584784405554222563882305882753245787683730994826722473875473702289159403069084456852445030469690484737759589827637534136796580993363717623388300266423105788550319951657869841115931619188588887303294284290641481461033018313163093278625795171575917672828462368902493375250102380263743813616826399546729567995148140686295632938274648885733101276165450376407194848767119119041719954292433195 -1058552741785080816451481726957646990139690927639746516017514743493044328596244226815971157145400112326334984676910390086758290819923965468973860586683587096627096008671181972195604123361192199523229533909685441126640907461971081260017565994802863354645219975097941044249676047352305044741670725313793233055060630121178084499037329671364822273891568311778004220553065938528444780357867215793690850187240072750582415514365246728472104368604973236914054607104492726 841943688389630744683370897229894493917893578786204151234414871610922739512706986698671587155108050928424619947642235318063959795547840705278139717298116280083930852559073461387199370893033112061045228364412011758208100875019841353992115247932672789971777882050117954559129090232706807661334325062836291924519713695116901356851456998424401336549368221121593518244722244496632668179032777315364778567037227416901425920272257721019226705272480585430327319309028303 -2971827470335102192287756988954878689610075139895941180734944013946380765779719141534530822703001194345160462172443747183518551332152393310415646113866416605032723348527316943261580270633006332111222919987073510318253514860432315847440214672271891279830379518252021554103354802876562280086638965434492072123219579678922441873979173032647114877954494964911019787318612387408169331339989921477483396407536402161148986217051830602055028837225047440573337237733712210 5770517878044894589935433561180633951111139083208049814875114116258719247103513277368199912853782362022525360611449904507620961447290049166355973178648418562543971684593003054874507762713514375577501230703535498519528812000881666992949366233463044869824158692809514544482164897617431536281709501134192615378402849409389963927660655761273492336350249073915723552846446375188502230465887278092899430973977236683885555573711405426687892070808438053532822005360719455 -5695590690391940876680337862429427332940193056329261655390979896570531071254413219794105837542868337240199478899805654172423295976555119807248102145906728086459498556929911303261782827892257857311575385129707553146074125933895368733220835992508436821499593848711362156322713058413020594805566734611293056572103593125183439212766061050737054840977503495736576374997068717387614959622372986905520437960236897035311589301930137427601733353306259165503279876267524439 2531459427610571480305244024412311709857210292027408248189642424339320990360632285164082003875747088680483836148778013091208610439602926958343842374894850699282078345102858143712696825204863876752090693262505028777072880560737757637468323849292114034425450674418292717170921307432443552363069791659623878722498384880942532077594704768074993607375740135489927317963790311098661090283907624622948057273914537630732153203909391361003599258371768253176325145177002002 585388505525250188517683640060720865065604423985684576617498606419192594089238980627203024083080354354452522234681210360130592568751187937153549994938024431173056587955122131189562372361598305984955779945763994755149473774249957812766946355600108445748004975003575229189227074098492526090504437334197076992349855189848976078247202099941026647049414026322333894732825961042767209525219820468397700186842222292535457143995165751708473640047204090733169462354763270 -1616318843440733334794329594819513680608313202823283435847887824180948198219210992247156256543145837387534253966521567834850669188043687248693092645725654125082628947916788652803850738349118503787063579118106798008534134015373633150797371873243501014436921536520547222294101465933710810612051983913392799669416896486117140077355906738836001452453634670605192990436965201477445394154041721483064173162645792066607097531632421260338106550523792911728645487089117873 1762572080035073345755503161569235856782782054525325966827932027966043504181884297922326500636420391463813727872774956447613544303155680130580666782787217811072824150509719471394397902837770097768411623772759211188695450084215660393872017772124301790209356224592221174193619501657001040305111508662142750438747039528126699846455550546709206683432761937439230327055437284607486136071556351675426983448755633794926612664484494230775221811718633414217241673549793426 -2797048474640157945841089749058476158174903577335069647990394588836342602445871361269490096404698807317969517500773135710213918211358809152710229289292927775306578815312463297272397079520496734877849394197486199437479851332614012844088923688521372125998839481257675854647573651367247951227116506425738421235301525785517114796249514795479983567539015300222114749041419329400402907660254687796799820379549937251449332503326622675208661853234608201664606652390765308 4155139971971290740820678167704702458470094260237869073957481845068773634234882530228108989258446030452878975731883363355292804949422912324461748015282089599252869260793128856198614263376901795395443585524648035852964640815751394649590275057059414559040498454353863610798361416937503394533500831626441817410228885101648449805161981797927572745734735016595399307622119578559544318359753978517872296554856893714280439572579908909611599766128872578882590135616510412 -3922248021339067622610577761800625233624160360497971310203228985657339881494991170026437896889148747764019627124037947869808638780288166488621746168881984187162790161199854272530719305998738874508422642160499293324527124515450384524152001307715179476764278181084284344111356413011625767450140940923360320048794123211455310483665140289662529156326393726201778878882992683256984849825160137345667618518917539620173223733853943681597615463839646570873256408001322309 1745813278881135685941130746239254135630226823537561470405907276105855948652693471736622046388954414283113491427288727949688982429181966277297375977420559080954639023731155574767169273088158804566141704994257979238171877101362335158829107233465077493967314758921690139586028544316111320118611717538068045389246165778710615513219530684395186554672087539044427824184912894595654506770323245599600070585001927457132545452301008623471175446874884216462122732900002024 677879354534519027172249665959885025551339106207708132757433358897903768067334626078709125016277683456575887392491419587507604439118660562104246389785900335437916826811011835150308482313110098275618175053434609595638470658240653652168667718604395303870733690745515923690977820076813487578626494727485291207153651772536818667668842125893000499303422200742640458418855946520978547532899251560228006475056379001310446129330566461420681869683862318467021714574021882 -1880785755123526335563732063248804632566609092697021881790627474001427154133562850582927854330647516116851567735234420392105877961280868990024833952608947116507331971358134827371374436719239680243332657072998677241573851263198375936808719135564035686747827939930362740231481633915618751450721601760513717062414950136199372425411822526176931734845668040939048872153758079869590677871728720386878240579425385427501572969879061199877921570646942894179333114629065911 2175117906547079837380825899708858241548814423037548258108221292713033172411313377907579591862712029718027687997927748461355435609423385719377597116754100209237099266119263994489727773158980853662093888453213111562861415269608862719471208658012778045488271760437192274084365493216871486481604073912865743819500645666244520532432518637126430273188854744722442615293432674884702122826956259060411241002039962875178808302220263811064058124663214862332711663993138250 -2563519404358091435516035605964689470456499846779734629017294143779607491222829987285308879735597852689402820374196717382809034360449587728109607350941246646506734714569251138975555546187977127012850232603475956339272945723685670616952608593039346563967877592041706722728621655448938444375376110057950150564597688547494366559684520801378246678367436622895903915184284656344592580141505470142115559362328478049397273799578617437549652250403292144156727604576607587 3014505350561009930916029370079178868977457163938528999457223081011279501331818646892926873480850587611122489901707429530087510515915584244247515557833037273205540187354569317045266344881719105001308744647730732499024711012671793235424541318976402457299218544324992055626757439050105956328823083246952840043373070399220722377784992164529013469259920801264313347951735666731068924139092256022868609608758410794080452993106354684278681252019044738747840781334714839 -2610819883605441885924227714324471942280099880177519233130794498296159365686864976882321861446710226064680104675168926318614556516954876925721597765942471862786791641987660583450059725052320145105837759975631834363014621433890246578798386906073995350752873199091918892301384129408863764900955633522102031026001985784427129064337668320162486135171342292984851504864072609103511748234251346594791499493905202149111123484838353303424781219655154133953823452954691646 1057152671145513269912419492506454566263480975352028743891639993398482555218287379505899126861883377463400607117822801651585017119584120677203641157242115668157264439360037840266359320025706315531058706391892593974724472146584605819490590730910071670599518744636152259535151253309043487850344245951738847239179124664520321269715183077928322306622956390799771030025847384784593411378893983145566682359610073743323201012349354981472070153773265998227865931795599877 766688746959370105770638413399834277933232350545963371075346850574805599111499459194842913301409703582525362710093326274444866482755140653094710538125316857546523867927946801007062864700556141616687000726771646413897909095320163938788727533998895446963774179023035053082038782022750435902771345970597475547080581340379359741043292598594938640078748953240601794087649834879541397449807537923643451129919980032151692537096368874712970451816194037854078503252784974 -1863969994038104403632708681257291633796374759161773987298269057094575123333950750098578236385851946841328919183874726078991232184369539256218221433523642983300553690157790179745586987913008735707083737154998236899332299181777881509718192802316623908472959410347160631566157882586304767643186695089229596898515062643422178786401553877094311626802476203144248183133945992014971321794024222294289417187168759717529720682048419581720134203259844431723664044561165117 2164896098295340776791076627125295637066793826394671057464333743429127949904899800441097355790776260021551076227351819151378286072363196106481784718074323569005809167724591343975786955604829687501933371855649433668955706449078250867311369917749103385671875956635024104996192510883870986112028909938235479860011789221508650701892994341935841624810736178170005185198213834704832903244601231594550726988202820692415702691157618890440247227414379191876109678669906236 -2209633731755468710799596798772433913647307369877770833666221751125742934403264116967627371422459185223206847528659039175348942585778383112255304520157763208117215673414050711842488233791200804795107721169911053887130763298980126317408537279421199280313830567493998876254809554182868055678294243968464323632565164690331100271904877413459654515913588076152667221358247968784228769046616878610802814433839999350749261060358726610015265856444916322261097848534545245 2172667517701021847417094612846503750715018900664566280674978906435064322842337534494331737601447793581210518488909938062248510830614534825361083078168928584605822333146945116392552403058961201108526397825128384015607201813589358581398213385460425723934895558300139026245831816968408041805969300132899755581946206635215782716381096691180332902032672092995499352966692683297691281272769574811495474789311465163209051881771906614607762631441935409021363011143539101 -1684211718184618002878016082751287348337713751715773900831273521550579250410518066532187599275917232394130767289199256321332609660903042027150261356441006550740626217641959190122245192747470729184746017074434579671209245811770093420488031082334344996257271626073178625637178668008981790704120518348261132970748777262009775513523187726808351368574880031284393868257634843925539763685363835733425984109899797523374519147828169203103596251258310501028736447599405134 553079053314962950073987195352688162717635007400870519587517012643957184040281613677412203524726105705672746851725518990378666480805674120851252224229590204062926137726556831147570529210045808498481955828875579232177996836214673308551307626876780283055629858867889140217130819799038649752456357136071857482798451673035180158654381854468793266696730201832663935737218803864116647117176370651711770033595656784332325042014146468349140940233888955102022025649587384 771541181835336536853356184801707046574298110283945282320628503361059876483116713097463997556423240054632979770929083539029611474910801573086698949040803091464926091571985200343723500080419172956621923368315594158935173765538697157623399246938426594851654616676915323703829417781146281031514052455365809659323572103970442327436122238790381528700691496876187921210354521920193798849514825622421208648643493360057702629700074506080017633236735446686319536570981139 -1641695097882020461750724456733535608316585518895071738791058363456058929807811252642725694729399749701016913971088278066812120237151221427281881153151765159199900289298917762467568665596096596644814199876917301758423084801428379400835844886688764595114349262935285801700568337397971035326881829308967117988993839102137206619172575461863698664459741720259257964379902640491089867448354035257393571371877167192636392857658111337432935675337649587534945243603999186 1877647815040505354886007968308259066957138402386901753381241558969289970935779914592265704500338473395809008587479520951938177799754495797072874844324236371989894684855294538498632493086962796311351482392374306525756769466031974002471719473169678808549616543356424978480054452978553575563573584459122931580139821410784109893257612454671312758543858564375317546175900064767881994422077160403247346519139188783633978069041767298483030186434886729370674260566548826 -1766320421771631979235108184442154253136170103836499735573531905389199081263219884009569114438054673780202199723885686100724248268466272468115253368960030294355225237877030684774464513364180552925025472463242357287998706535357228661876882503843239065358729326619078782647044365532139058446910490321737954655711317266344576124374773300697575769025932788629230816409095918049605350959699297540403915775017505967116808723341730512954668558994888802193581865441373182 1523154923366106778195743839712475439990053135811526879840632927627279734266183758084457169664932267707623575683302833579780076738901377215568535638338295083799501776217449565859825071023242561512568174779157464538349249288604564294374285691245469175241113347234585882991190638031195683473678848911191553036505756808783280475049569439015645475554559945987152260336989310727051754792047262419425345001336128967168456785034140283694904615955411528978519675856877759 -1043187004133995866647114311673903103240681538394092872938235707739828352592671375244276272854580403603777842789717488047122941952629764832587456740213090462554000873614175949513365534542960084139495837620836020984019548772256187608816731988049374748015250740673706731491627723746598541882261080678216503115322687779557488261356273866207153811841088907875985443272882573964660552414995078584252049534072654496081346587368357873467705352364758729402113228980047368 224783916284998052179914503010016507708484248460783607880860253777496887299326798780592891450161900890069458261503136747791138893032366202890950018553668615103680149252379238847079652455242629950061482379911950817013706487523216756789810954665217927807349727027782504550975333222148946848844942767184345946629964283573864905461120647203512238083623560879580200944439722085204550986784776816303636346813945487099540625242351698477830457532712915614581899815479234 697940592834763149699558096190102438783070505914220645329113345297799161054529623626773879969137445321829977063379636288725746348385926143283783964384134033626754651008375105568077912048838173139216767292857337911336832982280278456718280611580092843084263771755900906782171052879471177826527139815796967552343788999063853368071476462331382538104420231747875652415592908108850481998427123956126081302025481670597947397337343843202151784070590111990038625186404484 -1318878931208424682711477200759126447807020077306100390946283784197653985165961933193178451923013116653822168688479956711354628479012053174084959702508938840567580687270391942582931762108442082561832275391220137234995250887607235023699263912945978149520600409088101690725250376108671097110558060903509447071720340759714477761714002538560987287434758147750383893985138785735904393488647584931523622451044431823134011260249418234895942832572285860465147401369384370 1469699168331497605521335262986772576759837201540490278364659227172196081893745457485026599562197479252122543488856589733450114022885929000729322738109104225928555135459581848373786559636504651961139507234669436720865891595903063410857652376039232327766033000465234448923768398727552127974745962349429615219760010335161523150456395605186450128095014785784082458394688401876586090571381573628432026883480919093574939209966850254884745474412321816534071042117191207 -1307416996217615939607261755482809573409357006949140833555046107335083397028751285276563813359525703838033753752026235852431401020066000472518009911021410929503198620971280113640899151474974471597884315356404150538601957482294030877790226133122162574415755920927858426737164070353116886365956987153410389244110550639485337573322159637939258203890486817361143207796492345203062443074936319206838169878403744093076408496584120529708968388783634777916622514409276206 1018904133360279255728356480375356513317436935822104510365149060867842219326684982839790481928249430823127151365513286407801320719120436061224750573043039482880607185461526551288937517571932252426451662552070433110129017237697646363765284685342895319004147451948610027674157723067926339564058857975046247202583667816067330651208934996869832425541684137000746250888204191336607546339090485563912976400440416552757593249711180166549284224525099432448518949966240397 -607417956896693392893480299256211360970867551004645264259260771501038739534391583512909027777789022426340214689557755209858247031887693308067212302637327557326708221534274180363830320463443734971790712253711920067069529441341815077045249956840385844870214381154633791247465211218944905428233789861624698286024246494328016718289861838177302236317769485310636916587394939423818529591115961009207138182048722298561929730153151191469164915023797683255002872979843009 30669635848720609943549754928724347814128755261921345495513738875730113532159167911956554095579508509772141008060032414402279992734387271935714367462821292650605991502302614015563407405269375286770795997336969222500187812082780313866514547260719383441162710841975491529131493229207103812927147024853996392997043205158309853074828315798888683334828673774214661652633324384950178456518786223225840888998395181178559411522866728934270321071091352891953448730037728 582532654533731639007796194248369482748778462081097052395830121906828818775839490086610790482876060660695956861814306258046550988775150956436269217473486012480450048603208398995610726436394212451406523261749927204611186840676461803227805190019244105981032650684272616226640972225398593528489544804376703483642483019071946777592035172059707111696821253755585935605286402943070411988726735162915758671411737023248374997612916234165338214281149789441487023841773593 -986528243235811549940883452597443104514848797040934759423645439595337481518994344476720131890701180177565499242581799377462798503647969107712112188160113587342702149879656575230064997163163120241502198467367136058307213962685188799965849426492104858907366055520140749056102874537113705245679036017698542767088076346213199716274650976401257498602913985498898540347128269682345683251031846591508483839168674352845527837276178973966267739996542376038606451216280053 1061944698020853110498987500905158922826360859807004289752207104972096180865021211756347702285690792066929820872921249957085915585440024224478653729435217928665850023222109048105568820996430884734030662471286284721689777965841448767669746544468807148759734262780272503242129484534653578454780170889078870862922362861708434966698509897479484229775344038973653162016730328526691731846644907983414926426395920774155449311474147098749010211852489488878229704361290191 -900631905033008276638434822657742815389065475833883608119297132450122815007602802789370120355504656220762267125846003919335450091086503817666853322329566563396734955269860897252270815928934401670420497983475361168090722312461661879209156737337626351942446823455070360386200655403851073490025209268163359367797441685593365595400038271890672901187933971655846494179815784901308428311794992135074315847110554575679553620682609612082037048784533695302369111694307511 641781573096340062438764579885523594955488447260577581369516756180580049620291778385814858430334028338532489439876348825322044751744138591840574335362859293446438134129795041120089550788774989485666872608230001908016736455384453937377937877343925456079596980937329418301715937894831338528992647565561099504121324543602393410002450730041042419012551614259746206451841259635424339525897323395430897637372166929619189122055149322059757349835115617105067949616651552 -321183852032715695507903361106531151509826994519637013945344938422466380375190108082450886115492494765358190451004738069911893878539689930019484791707555895571893595162146084233153831705604008650839433758564770662102477380692320594795328196025991704001834978438293126069138363218420925588277816358580314726795588362970002042373835119514334829625926605609861077735658579194734322211561939110161072484731327620500902891500439935974471769841297706596904551867358567 -70724728321476715290241456914384954256189827375357531628725658087464388823458176106895993028638462035232334604525734888056347154365857473632924314265428563309207004929729452681319751935128573746180028867893782344959862267467244410249222485781363243095943033640898208125977985988253622514375268885730590059725608756670969718096866246702275704194537416024615841735812285807515394633537380022842118284990612512864882577587665787190453839656270037475212455093044143 458478327982693063840965023092322177971726822512798992490036039843560431666745811017876638290898191864390946317937362584682311186728436336581549475416301635425304269269190698073138163844335850393585714360960447252496456936115200177879674719622320612711894896652295955285173439476120180698796863746195027108137918731373684603050710382230574887713026792370928854336589655236936833947878940639162264005324906198987396017903499779057619846975643602623473267678869234 -699063159385972390267666032542909329407555477722497262501151555487761489409270481428509574352580896716400095773876966547993918316509577336042355669049471054631609877661397625498907592442043737059456136391988936321537184484265894698051280578411055080823125807899973788165838070591196460155379622054277583213535139158324505114786937233144433261205541319587107569259605774173499381948311112079194429481163031469303128841293085565693329135469186659582181294991450302 721153366169395051908586873474144773441883762600402709525960919990905243735835957576835556216224444804084731843901804965394858857212027967721855642633240691071319380351194611136616717034345385022668505692144066193448450860291161213691560153051760201621590956160614116962803606668432227448380759998042044451222521614440401145661727940779834679345335273857464253489426404686542007805613551085216060188536710849721964685959207714774889205279959893058925485523103501 -582567086307975897500444346814505354597096554393555434449452525336046255887351128143028424338465604139077081768496347919557491202082493495847137925140356414827621594398105160646128280668751506742056142297045327896971705290331623370942593685397281138996964237189707287002832688039309187362293332228154410096424386945570278437674747445768540038165161352960279891756545677420610656350403283274367757421224906961888135553234423806823574612723992571474974762971620505 378175696315675651699976754349047615038525877281153530389503899131574627028252132524894823558572993017090043667221703844962341176179297561341897125950642049920127472534608921482901934909916638454170526985558252140582993210405872449080899741740423250798640502345557532267027250700203837949082547235301763290914753297747431304708521384270118668887312872012107552095841227523422233514593540221428477707828643120861551732385877007358070664364792451008619764600727479 -145393211479718480654341266859820121436204751389554620617911692714567389363286426439266621492450023921211856119899629703287869552645180387096397779344621100856203925885188541850033632089251361449642850246373292057237317592466835522412877314122785908859544453803426777816683146787177330198895513668439946524243451005147312272431560267765923917709927667655913361772436639218329896214080737781331424120636718452607569951829266855060599660436249834264599953652006974 -110647222448657085524102665515711697122044405310585449496664416824966385221053068521214470012419106149673345759787555035650191268601602576031377426034016722375272714735993052234248169930624883784743469137989466145364170218260707783843796498965243452154885355909574582903653420183159626228821406597896860200326509539327927114135883161659541463004519914832604830972140297525789871324247894280408499825943738674202241489151850962168409685024814564033520734867486304 343951498445636976379569444655469981208054694624940894124375724580424046496274092283284229453812315670371431870738967517074223043352662784942123043567247962156122625112479629457709168961517146785847565720463693260955477297546949348900236733769678468973366591909939579861269638821587649438756529464423272130115145279859179711424676266245176600829977819328224757481100274693010443141199315593393095347872977902883437197749669526440667601926778149605398241639487469 -474844588710103429559548936840264970139605686538159569596982680174758277295999839719027508801899622713592818212737680185850457576346300515074579130763111031527855488479856488082698737684451297064205226196413482261886917320845430448972562997658788172748323665843159750056664417616493540060540735227841016490473861997228741335235890159361922912474710133135027731750083282266049454976289935265464413788092755768095640842638303416068630886617600163384275572233474354 466626762194851775723415002631778395648275489459087763968347625726280769417506439955886519745324663511456292540920570397010175574422260865080743786320447429031869236242767964199466050548347777665393151623217132540420812935203266066257445999609492609544195407936672025065070423243165777028999804326343352001393132943180670164481073659483127859600860467995599876656918483927403523134320121699404340663918167071441603515087778793735183245600882209277001253547684971 -357464092611069245980116033635419724591538704787830524255728713767789654939817010318654389077328137609739759286037742827785293227810514756554078435368929389120424471731636180084536183624336264678132389244484052371885911775647429233575046817761025526464826131730643861638466755280625095308085954921847830213091131078761412280873667870069466646038637256302840192877446671728806430347511276768747493789512620592940777115373035111104869957877370567358610944927017962 208338564629068588026455642213324854110541414781286805277581500446210102673379880772571418884517851806142785064189987465132534287065956636553315638086384098130413066995845249703349288493154979773587887576537077029779097061522664351206194274114729358252424517356530268509638472526729866454072845852044777881143722061353417609739962600080998173482450973933420685583554346732076211595603941685239560221495762156268414603860658355928452677834269841613644094230947557 -48676646055419987280573748580653382510721120027096388281280206901165523222019180038150051457358283397095015772325204204833913773591340028812724655058650690881215641860162432682426874181262572840472243198622089627105325935421037577179951480707468747626154433922181583689164054680568511697099151893819025075357271400663829410283940227525138135354927791533685454469454799934381724578354826591216124543083624015837280992312076403751979010116213000508964212950867353 -112010422658406616344534658803213697952049655926346041430970200349081801009459898594732324956345903138519600300675319559985898320532238798601151055854270979613872725034180560062455861712930815558602433236174740536597908692842316950079753857818785593730779718305430714003976778710125472213776096259455553912985581273681013754391994955794730163053688514889293420070929675290938254470797397107345083999356009078502133847140156113772191106569622081218715223517601582 245669252453553298284687912610346008111549884511161884742960222281975668364853679288207731709890905372179792643433712725607182527234111089271466708570882303073113551537294990953009283210699258619732571948406850722295025153475789777087128114525927047677087139712660367820284955498522013663872431543412587187642342143351870440904192711326754353417394974604368676684211102542599689166771828829252229515450559963444127428132586694505556929843897604886255439275958546 -310165151731731118280427208012176936251565414760301945162524823028598758897636985169224253604176045848158752041895372113799967330043190751793364056722685279036090796760929202906366833809933337380170002701853554665417273400140379005390423026352334382915045032457127837948693815957695642076263655007976080061576000897637627652878970645317613482265674241143211823740377696960757508697792453851365035509934382599991910428927553028789483693591804090350327651439834191 289637973794581143816247834350434563659288723161044205465172381448830462847518909842586813925521378478269399981915180994592467398718352600654959681852034653146568740761683322511638663310826222466460105707144910344534745844683849651321301062282061923524804756402617617104836218580006824207241968378692517791587834088736614721833966138054884927951402755028083716902488804050188444879185892629125371078494872284002393894334328937325446522832994360722854115941315206 -209536274926658762457051012385382011996931923312299314417417959964836845785581796855369669019831901779378467649246343755100869411298187815658013368969882385434970885341394805860868893573335611098756237442476240614797758774516697166869842875217151155754078892510550753477786496700613786797114889355460631956069328414861557483682954068652929907576133754362718490564981280431696823671888896885816641394776108057458265278963387523077759884563672143674913946518213296 107394706512007548824547678781964215484122459022157747204026224354240045223952439941012717466418325276534939719613092158878866361364281098229610111190836225182228917722913270681896011614444712520126720599472523526790161765766583656299809402314404047444839566115355196141826482743664672507949119715724030017058562628697145464242565382654090416835265069341010282619464988432791286519570516073623682220258684178572104644936222101032753055779358454979303029686473898 -3585277193061198311958818766166109303928322975766953523531920756429647515645962088645817004464118197070914814066542204429686814155505091348627906679921111755787417696466761848389489822496100422842262338004547871148598970801884028632570437766193592347174924024992698224627960540052105414424369525541086908739346948925972293286044485666553146182716963617164600599516566439706808402974204475764518562102175084860963495740934417257511940398971883675086921381582187 -92968856035015979655138078513310524455387646135726735705857567756259679594058620131650843907515476946161576342675645546895782759216044005750344502045589464765561881252423705273488393427168725819283565046059573758584036586758809013998679351457063868655265423414543412953682028027601095767657248698194647875901280355928809226642739648075745758347306748933431687253840146427815526105335979115309592892834271963192593696703570838242764317886949347309764934836528866 165744527383824229295358569440136841711006421820078338630452835390277057407168073324717720850687995948880806056791143376172486965272394655571955632764215476343382036401145123662093506456451692320322341861740102479833090122228395138392944792189237841149794450658345701357396519263295399250475047718104785351513532823429676096964205644823751356941296531957252945938048713389320997200052529595783002584999842521869175511068205259938220963765495321956706391957557116 -193833125178925990357158074136243350830610299162237987650925289360410642069248735841401534385924636705884977122799034501819253710704759708247167111002327118036104633336355016767400516228278072517054188629977369828714527158638946759661160969720283587924599025870991144970283394255255038623109598110834709208137150095580986967515055605476294940119432336442273152686044348258667749872446328107044202847760306657679614158139338010030229343427961099253721624799983562 172133915364355635813603006895879531955345847855443631591356134814315876365832202643311565999921756526698272070078737578606017176783603461127494540655420124849691753210404910431337848882328556675333527614332120445396265237656998654518977188603595357597147568204983258645342677940741321630650857885531690177336444877459647696475878282826371366733706457693213866533806877191787967136131746716240700202583117841678719339526626665591980921878797723425840495275227016 -117263991970254139355654899640698003580418955101512670396580097328979240727657120758975751672464123965576493763634265055407405820463904700691013913425665623286597783593224324077113535044508560048022870266428048948905727939568435788093201055727104034762494483354893976631360961114424012444784941103785404667313883061569924653661379922543320790681271974601857077232262995216616610111208519217734885778345117033426548466863213799082385178570487754994403112501708968 51462874556617026959248265261661310220642484819882498953938866441633366136466223621505170147005051287253181564422940379991681191715108026417413536264450694475839040984685224481465900997801336044163052994079085565201005003227338548962099648533109720226310161943887289635976149303617965072786529159232410613930251894073130780492721316369419071066634293518522063542158911061669338072853110933921122477616688461384325783624722663075638223283792483532802883625037324 12302217521178409263153510783270443469743402495057033553924476420348048483894140978474518358805273178041668729454348840031316195198263361610674029530832056028367812242148266442924835837554065820376554998175109533842622959778825087707301757835861269027649788278803776368231493118746531599467775653485212742812770253901563007930543587447483595911846802849521398381415328882144163943662832154203044548151153471443054375418654719868747817414338036526566590292493963 -67450349871974812081580069503380897185499336299986127518462807980919374247045578726592438747911259774739987394614891101467278430852993173446709035699596330982160812531804632390407064190739723810196319722379504919326605889567615628522217233352740284104979256883890301254908807408076273671053185642912770314206245385174123738707600729288706771549116043572206679572508239713385079381129390727307617634327553872941265158879008288765248763137473508674202733903357482 104836197031284740378738615215085456110804797142815957365671590797470692854963113739787019682389754105844123284108859393872298812287042208895079614026029207704258320499330181123252052355666473512307929969759858422044206726452955656231318988714493902976343987024576830496608525702498041676039283465023707896885812512976504648546024792720736716215314808112267149240779291912441720981717880284906165850764536405737115150603589593948452850680180868297241387818479078 -114893624244452427244122857477038207715014797745240101431385287366606965539564235587492018832009207647457455155784576779274534239629304956384373422400535024303262627972870975543973621658206993564377756337830359537777610767870568621874504880819615763665640922709049877857834224475542248552390169624591140959702732678981599099629481253797297288879609624450060907782119035240724168716006552232416701892563069199133045115660246090838780146081580296069090456133496767 97177969677349589854113058683486007228353458008779962327613800131355559705136993581347455028403777965831787719555838558330622082827497795117915253096608743438466921135967936780605742017269921246145631453680393135158682589933947019536175159379593881136123490542384590379864317146000500356654917914282397894326320714469333929354687833964010359909631734237061040051837432160187929312751272958056920530444883069020873833988135351562527452997292949670013455372802345 -62103300101121167039714185799416415686285578350980115226033529712940334957918538420001059881802810422837516721761957650804406526591080150383003772227503375093347334709087225778729446921117632588513515978389081981946200337070143369154072354561725777369644186721810703684310229735898275433701476003814588603945174214454858281502435819797492084264921842128967606142877541918838788380465699109469616471956282843972997786774980648585191473729110882093320014161404062 22333694170522535291304644699969070866517623915054803878935791079708048062851180856404218580307291112632892781456818619388386665529859816504692988641140630547692389579085501336075766536632765129922719798871641888046621185545316526793211193686220053161104284993134343875950874464164119044312018222092665359959316482021486211928220357851655165623300767640249439564123177987125368183235401182052847504831797807502739649396293829068895302230994117108103844926093760 14453330134260253670185863621191333174403831487884159842573194223634614242935465341171968421883162851149605050661349352570437091991290165228099376010466804796875209187826667685945643193804635676725482055860604619922695455696732732137050642876378024457229854595356929819421025024064495536018471772288474307766878907709516218750274897193141932741125134906747345115635862168329089038355957830864307107879876023588792719291700588406532222616345066469103996527087750 -44108117489182763223694299199219352288046810880513914813922360845426745892461821386785499693199684174962336143168851561898786256485898690757633631805669298885901600797351095608555654854410046652995192369830321191302679281150935670117353484788938422493418320818902923936767628359488175405599609156256261356717329818438522210919344343579549030268294814741866686518040049799095882419515116459620532312588599820850547159862942627006321643514554712126448658823321438 61976527357943464676664941933586007452242465064637339217194123396223408318902671515736838192649089882103461534226179553477555912530723693965597145469141550272756282150046961409976682678280709650183243902214702826992082240872993002032967306608387089558571357685843325463006874397537365174850642156119322040499608985846256814315909304279153261673900007665618025474165381062703311861267335917236470968602161468961728606004257728088153545022456269798447871401950458 -64144068688826046578929878484311259976907378986644909423107062788952734923836712788357927576347108448043613764621777268304878573298931451787487840701527925195745509917084990641145133857881935671133007095685203374169990108712741506791652385399749553469117280812687389111518819725188988855313792667502004600440741405954095962079298681690877310535044659078844323057481919430192457919519181267921105217557001537844833840628738120219306040100258671474791671060435550 51663988072504015862891970123651072339984481194064031530334127527095524783808081403073447852650932761066257868668458643281319026844946833656637625196312184615160878830204364880268665533723022207847819535769192499219745222406228008767043731449399828113254510093519252085098808131842395889043721319386820836736097794306737562094008012885131281146091867800680258430057164498713463730110349508289998631556808953405185336085510958868496702772868710302500984496843737 -30727496151575589171903213597306011082042851892320744297965111720377377744238680315917564512702050606569771339951331464925405870266727879626921497532064869908098032411717587557362233485014065607211402112014735368147981756134227442544387073884820092575344960391547963241460049360373310068894577273262567006355824527447182790900041934478593017569866599751187061540204849076626713607327050842475547083041461008942872147656561375677258915022857800999038963611631956 8227813253600430118211288053509181613198138031379088902622131995635525614758470945400598083257436739863949136094953942305720149777571209199405092489782741709046425411117945969339217377077351948792680071574652391504116077673458684161530052970373986866484916928766453652361218684887825499769054097571917970893944458887977016258105552664131381781635111561437290077949163127692613120726195541437744481517265039349303944954085865070968069420795971744944056713604378 11606540883277898212031902217039679084595572339086417903018240482069711869954658509589653377816001601055744524668920810830340223411845122637124746163562711383440262392108068184085861871542778038952824989160492765895261780368521994888216132210199827887970400025861572811812593108774233557466258339803903608356823113238104291115467254788099683094766792186558809429203468241054056349055312160516939664779389517103931012935293271675747042490011869382605179343931114 -26480543091561395101919866777778367772309510034680090414938397960023458106503179248229058333849097140193578959308172246291248297210513983018214133433468605694084052047554738010471266354275793354632314534194301032568169683631406972208028137136518071791370551821772937501212475434914214106990766357123259067716324236562366453317261099966383115314869722115303374891429243955994215465684905432542466691476459833546534282765778599521259509417953057056990054776658406 34264368013130681773562596336630842722967575880609914973266252844674467602168974871176931862416343052859409548437864425456983584772880398390324439307211500970595105720607793179654545955532280295679503519477988128217019531868600773714604563960013800091826551892063601523610425789322473695908697641033237980639610430825962268011986362731656675076943045625129364863895231365208649317755914916215521702826351393904366817925635680372288425084489909057659158130232050 -33614593965599797477531652162349248313988443772895959815261700487237334750606232097475406265570539417058255258185744205498079846932256661982534927129122564930081740605790449965900127008642519763613039537491501137844241332664264823767775575677805924425076353852767481556670770242036878910748415397234181580685944142714142532378819741025641671334244444765087840834503992132245293269186233350837699078355783046919653367781575381999302653346103132496117397913584628 25716029308101689725018921667060735806019118062876573139781790864099550776081068851722071134238713546316644028020246485666482788856495717696388994638942580839763990001018491379379512368042167872804438921378674682320260642140429319095161146154362638954597539189225516230025055013996831986200376800614415886983307974251047641733905107506693878334182325425201618781643377891953648834782878739438797463445849314499152304176454990611574911346683262794744258312271770 -14036115907801486798340141323069005695041330519018483175260743317885136641283127407523483218100176420587669246156582339798391899270875656984304342196651825821046319007257251687727509654330243171565136924757268055894226325477668710823100361093003825464078138855990532271016162991273457864702939636796487114339511259280584199038179583210475887921345851164128644293163178022880389436507570980069724922014611718703540462476950683513636092673234801268660340376051350 2136914925092326719252396918012760805317729291198085395825032482794163789045583061612220063173480548810182829558144637529183531872315689561447818857956175431621510589663810372335818491608962446421961911973673777573559452267192009856923207218956926852921549284334150406439578355831231429466444010577968481484127308149390676294393017411843551398938214392935194340824710210334457524343769539916062097671966231623313756904088155301442155764366720714712188011289354 7824154108214700731818512545993625223240368338943777926059154697463022112589743565181569721771179689641255473276373309961087076119319622701513994920093960896098949457513969396549523608975037795751703756386049227333443738612200363006180577197603870894217568910952327206299694126163770841837166956848733576533854444026216519275384089071134808573281262017611911465135845323223313570035223010619524434714583602665901644901620172220907068480146411180919483184838048 -14728514809931569992913683806030255221145817796876313505947824728547132536267704082927713226757129991933002257753416145217775585237644911702059342017482962449474750965284629961380994148257917991708305278257563567048787394387725581042078041347059688338039755838542499796285265383837029682869769381199684314838334590732115964583237794202854497101621470406633047891088160559861135087897503238070609314776712099441656662956829782251502937994407185867844058368727964 17727779727833766493853007935318623409764715988724953605225345865698088349435986273789669512502597807177088256524704685164472807376906956644596070936478082374575705264321831360376864991579345545125736848358234947434596597800681312540331084516087016225749330009219192350792187906610158806099927007314387115607882382780240856540256736051938014403697439225265299546178823831057238575683455397492060142389432017431845254088229977619879718711653404080007594344094800 -16507048099609830943722535167954132683495900032721946038155172175824030103892511983972898945778882592767657729020336998616194742615418785572798933653833531944814376789813489207621479363131788552458936546377609889030880211658956433729044346862807559294363902796861333967560636991222533965352356317160177286257623246810664414684352675749169154011114012200951065470722604808887872083605340541170051982781953837420736772631264918828207095477219291830962882589346664 11944908457877126624182390986741281662536771406540703248533843914655177923034759469953515663237834641617925574233266855024266798195012241854494504867761917288145367935949489732402025798996461998860799135622143302844006243966488633276065298198228973927530919291980041592684343912767506449138810841170730339652270250362836018540458256411971732225798677531068887167803899620120305316903963855729565523636306037862116124934616623883480767890942165840077675132066278 -5861491793869445177042148137011141408014056573049465415283653082746409968108690505273875862643837662591295200272259737954606818771035789479220096133980054733268271723451936298203745019005582661399887510032057417113700172693093975960921704511069414790830269535763453629792319344369204940101988555800115807215333718198606380680350344927862879751703046637764108604887887513766781630548192440040412793694669834916535631835450353152183881522136843397009260291610654 -8568388614769990038169948884882470866968910118629516783604894048012848989390657104739371980152326850193396588163251812715105471822034688318885486130557528885889669688430534189957567799867569951195639691103296969852319686113374493887600753167921318075269068183664921421376866016887600681865188743736641998456947555972435437238195243428925359217369662015069638069672858847136080936755513283988028753156238565548834499511712741337652979860517877713323106930562 4652416155450309689956287132892371678579526360137812846489540562293330376708325408104117160978366231140008876245392675528585589134869672250689490489963486032266137140766651401665086288930379562049459877557383612771255555658619691324766018662700707091633191844037622376499356774883590296818463840658889258692862614479566565726727773065655616198914628739734339962996133059152312214349579625328113595499931729463561975199274786829183184232939821184897580333998286 -7594685458406237097943068432364276407655774604643326936214677312408007474129804673660408277613492861927688830066835370611662867476107448669385042105214841053036716171163643085355937498787597042924264432799053546027057197109903300914192425026650067433518567840901839627157340696568173964954644040647686156451109590765905657228612120171417760791413543670242960726347883167250821306416302625803237895165131308047042670379537027613243070777374201645173049370301074 8561020377719267063248279353432660424844016970521848304382693210304954053943977127239628892608547176779763835204631169169348748516893212039117290053951480845091466701936207835342790010756079149796738400856546490365918793379878640878873464217563540116701163189873959571517506891111573987778453940049884524103316681909469888667601432152719328999107470547149544552271875939126230863195266526464863107725094229583732998137707019712984860117802232210749396794868756 -7568935679714509699306647684514427532293262097251069212354575969975819879461954550798586281459358571258254916098715076942059937095427221889507938258078277112168391140604291012169303209426897352867004816579040425115528560939063192503303295207653887249138978761799414817088581525756629443257776404928304447936784602448917016249766835523856518155925366916364961302764749394110135915522985469268649998992134722846021436702956219849951721207256293992549839614576814 5154554758967866793324067268036649822060260006042001122407274615615506371659901805103581532683858233382067129398835786946912158658478851735787456280252232345626363666245463050463879730407284589868661085874703462004679530811455216403872176077215170555238240967546371268990899138764068661344656788022565652815493420980627791667472301070978324657622741806467578548544602528341780737630831962191094944573178798547203087948996195662231415008454153045696750748686804 -2208674386634330675945905374635949034857606798158749146833999394544469454433879610179766731838810657354491792554287497598274962332885676683830780487032259638236905431063752728239716285921754420946882433145472588853458297771358028328785250851912115113368748417541730931045346600625234301334811149955027556686145675796703232062781002136908407290618257307331246307421215972949893390317800407711401775524452011958679653652821058181138449385483590556131975130566266 -479235386553053259140100343010641625866240261704142089144148074449313259324374831989617651603572801918335307056508915718447704536022112802091419680889569674109470278477847405388814276472780780823768252906761866115566064762276426450361200064996564131321451756190212636174994623033642918700301815665650449839717536666546781430213510917489149461568479440990118603010712128994613396356948690006132661956223921562767365145605060105223153794425449935942367629973998 2476246229880849652772966323188525054759917104219999232269110286788119839441163718701113592764346924234258395646627783534910960499788902970221524478384693190185330682547416124477206409584859208656272418373915435485587146310379080805706769402929680056354941695931662953840203310361717475457217676210015531669014506402960566374887273880700587781628058415454756237070577969730118528721658245077633150896377637189212239937361518346299172813065984152890622913952718 -3612499669099665728472712049557701722517218715607977338212208875461395218444622424229180783961446920079615831291603272552831853591356032115458796625654340838390149822198436539392776948220339940475795077486920823791977686878642861549788702275388071085407310121796801332136178573186362939309093204918440921437937437476963691126523855673629113687267909487488719879175636797507426563740351434000852817004128344780286031143678458230771566787263461940535306192378976 3831995892540613513770225294721239623894387612780561463435572866347122796273483148390125299314506630581870521472166965485292874232314803811990708402601026653204725492735997983795357115287357480878097921222007488323524582653101925965063570840122947102323103164579836426638125980556340908149482250590100604251576684154463726707618282190864260397392871395766770147877296231074661688495663546811109223049761427327285497552700046692467485104844853584085801274998242 -3214664258459801201685954530595780086934362992841799622450576499289834584884792734856625528816033994502303262475405360621996123271005018082840950253282324485532808432933642760398066119084016748856892338424369113921750951905180315118689189839576646204128375536875518168471829556540536469770695701077587680233521001247532294257926383402347105325009286461581883790143912799006705126698263128351385855312464812419234807178437749255376142156775531015066017247705000 2045654617758848524135230315788100060874377578095951614224091878765364460038372894701608233078136831307941780957236215278180071520307969492826431260368277811165739722631652114113072232435075463919796536729906148822694177593582037517366677712280047208276106574075675895273597615487970346779954242548301348521320982330343512971007496162217835446640947654606285740579558663710845497568984170631628663899896520471075063459781856747285880625054371677494569739241608 -728811213677990069131629362994053165296117648243190414307447477192447293106569617928850471335823408774464712472194837756852978899322690690618775542204984492404648145128040334214839844344414548069324122590572150266109329839066355100579997954722569316023558660469832516570558429833635964403392859245424398731170873049617766443584309319944083437588011788297385929941509657219568844518319973609388357558254393660978532647345462411059804247452563868605763191151550 -403505727872038808047361475726571197218357881906442707185128978553335690215943156765906044388106665776991380084162927038023403749800095222321288297397346907329747300937924821552831168682151425337281739919952904646213500365935871513654054752641296474560833922167972148912599682129555276306381760199029124564696638695509586715375564712555408681673367519573293767577007609188148902182632530138157765091386224882928795471925298833765827407703838519340580391296238 1185941422207287959787991548889984187899046295822889059761321729550207710639628160483614602023145931887622724739595729150897093207344497034885863473817406919041137676732624445607967960746336580007321620722926188140429665659815171636352404382610203159155078825106680275484665266728841905730696908382883572490916525185816480999718063923297993165023288951185797026987499129388341334962485398580607577593783313354813150120716130597214947356738539623946145533696302 -1573050669159133650313719677016428600210880846867491494159756469545884694675651245049125507448134127919835005069700415453969371090844272907225875421296834408832493834589571404837760712717269456527054397067407632217772460793876627413870032886959909980103275267237149387966439282153333793419009523969144270204731335105340327728384963730558466175688289742303613263746690729313640538330469891467422133764396087640225881810173340130235210914448393617873632328025474 1572816042199244931945741066952608192125117063582501895633544371490259820509400779747923264325016535127211667000149968439781000000967670650899675098939396331312456893063563994384410873749990713606805523755952768101428540201831380036438706609639046267454257847451842741750143604933794906738648981726051399518295781200093428901885791788439342119133528323537985044990365226906138871511333187976870727770143453686890490462226574208670078441235174367362001947247904 -1247413970299641615542376142305270439910877678327613019241190912966989386843139275338294039136656193197220350596530193793276508325594858500560236606537448466080336662202558627532554341351429759241219938738847941330905233391007681317234245330095352521708416323594545470671646980401628107792373775338296846235320279601409407772882007918482099387003918654630095018561598366758618814511086023363533223411031061146442879463615703454475868445863792473468962908915978 731648469125143020466971182679816221653862113138580496145220688045885633917322586349887824154503039826467593351023890463557453254049443867093762380918024201122929825333916405998321218323438656395574636365546302136939834541639827004330272012993488738511782162587094443315566991150302613608933825587932230727905344350996478522150520852552958350561749976679668294089013491709747970345555230752896818666033559808539997914995133310315429485531457960090341482321960 -193662854158480593081262810846203556657942402040663736172088847083323710211914573487797259754454323400578600017587419869131249874440502144750430954448382549652592695262446352346165009973811107617037319471548690903621263737515906143387315026809890947965356769053635979917123067964908099701894030253885553144288797730493204842385053563237705393048327194150671805414050272299539023343118659210525146739288092013978375258929584144531058560566860104791713080552094 -238936914169674147965096894282601023377853183072003143054923807594801613491363346023172317985317231261263881040323505268417034773832582571575479417643742210723601709853235109938313878025065912852607103134830349740730729022900922474943938234570661476378889158833074168910471196590752437078507994849619210370937629989945487519230095152400405930408853038616864626068664484055067360404137150291884993302649156899870194402508301946927230876751235750749828827918639 511808631527539506740929628382968001315861132840674556705329239696576395758346540204410592441199046926968873778682219937670044552229157387790142106692820990805245570662571464669036188626049807999242124653493703946541485829766925173868047648208824695749784949892646595469963191309637763528815637611261948557174261681860193210416576111693652321305938431332122567519549183978087234822579810887382089622462409188321196649307194432168559045897101202433031552477934 -620787441276098516821262160497623415307835235805822596594124924034905187187576803100069993643548280620981637198447672934930355734033659549840763168321000250632678188693217331507400909937439288309496135946194464006505800534703830963919137125468740411510388933210841426663271169333727468464673430757895133829815200191016746386148662174418257698504418960805840346421485843449604815679388974629378402559712151685877203382344215080982668483897837769894923895356878 582678739867718641931684694805864855733712941921680154970506813433347939663843906130588192071253758023498110567844999112742074860989865900100222381922411996865412328216809031668463500732482717466071462394866916271820086767442571486941504622751161925075017101672743077883036489705061741629888458142335340248432286205492203340711485865610233587542947516374384561236490605111918400774775078669777813808732973316642794278534813012447782294867874063657029329990367 -432201842624419426179441410562866817059991588183285270601531598051329951893399412339875160342698214250772761026342678082770793052132819291814906833693942209586076331612612044129947331271090018266905575531119530451430931029279418923626517792917553745534159988626992242574296871505358999931871921042759158139808408940471601986722797222784201971341078644514049798538328528847759718522694219260308240397147519672593358987566736077292627334002605088444844870296098 226253861802102730452180569873696256723238150693958617076576321556324989482884089081388262910056444319545176193811009769125848492401867512272102392286213146642624831008502634925213313734947999984426516040146404375903934978962226229665207427368191778663344270747048664650176111433017720526635795761933810517750663857237094453745466612210198764078403180133545273867247279833277547693801191638354916272971179175834980480298251640406029688679745041760267286418478 -28348835875843188250068871450767326616347670918375290937906191086381998667386546026363552033349415285242376229692072201058817613755768952332133993846808368939489701898187856632469536858239457075825443786069583233185456796479181398613349816246143813178119994644175567668585639824086963848269827693480504081498552941663236721898444370325491578022911221608201734695688322046182438933618539363154863726965612027470369787383041944189467678041395162181072136007084 -117825408744993415626158795050764027143356017523655671998513822556536340405454588226505987508386841846869815481336372390580842088186021823973456104760978147627502513069692276036128609034943718538747005037383368202210189050305661669985566414220216442738722679694821511154194012367382339269742865967145762179386335149234335399310544127755915085687342230238538514104237587634433227451172743309800011680788984827018870227006445744859760606531319408206806017959627 198350866406938157180969364274796147725971627367811675993862427110214746678799292284104045096505365071697811995410706940182916959582218112986985547584636105375037801866703167970360270658829442123202663075437234008605642536465937218613661666974137762190905586669962222655431317969720900110390338769093203201304652072621560991738740465288242696191623743637858842275839611833711995039330842653455348013610735297267485288254740766711380857135124471212744379298210 -218288239073790754234451575866838880361278010154333078967781711792208148609907591753350010942973016713176291526134371108792899853782135190265701416214307596031995659745295024173793303543877661335002218168903435208085669910443901439981496356828692398335275214838125076866446440911177751210197996009449463343730819922422868032079654457612724426234532396545590616558830416929096517751413219886586670755015067938347252653799563642240207900716881838162171482659418 189295400610381029659460906809903369283974750938343077062200435477877744385728872506203956163535172959821705371238217655680530432113507945541605558748847768251685729084470263138619437903034533037107176086782054313601568050475766754784148600279547186667025891674364160961142500076937979358686444666838362606270465032765559300016208226774533940466824968131018596926863153452534487825368143809262189814703314152341077923863276816762017802887082884956962157345027 -127369680490701334259714558575448464384343112379510316718517146951599465824951232811907729212219069691003006134421141567214451778227413780927493975100680315742314598358476605241743455047451150673377205110073502070357858377729479598622723647327213776541152278637506446849782077938814958557418658274421310569377768883631508757820114756869023341514466219000200654966791657931801110344415140078321309891997382281397814593232677810420154487913900156833658742106236 53837811653873039314636404146617759106603795082303292826655883939975855821706615671607891838250526627050559492712987968450810337206730884905297318138498662905428627218085164087063097123899618614169567971771678108569891523635502430832288340955574907484302053844898726588394492460615374242594001291412491381166638567980415607403074992785659490525629038899434795682851814485180579636629433679586407299235370574869394541543342817806349088036998822276060888635830 9962705482853469495010943022782934025106697583874020649654018236443344751855403683812805027687895842376205504576562544578001488868427222517736210661725957233688481480028670927293155389505462862304104199003423001169602050566884956070912834419626022760675359332351378999250551892978119961691441892319674468355035984336395054161559762498873886935926501382888190027996345301715203359032922462224592955692938102121810740571208318896569971182250570818958581606479 -51273096107893637033516683597422368209319800341860532463653644413623099750367683473393290028990764196977179233595915014561850955115006470933471990523697988296095054030181157481498837587757450290886803523777569212474696476000130003675313250678156711926372887852664039769644358140979576028455999220124915873982670243002784817027388813021104567092320897351764526368743685935321113360637198978119145285419858798400526150626828017156474357067413147395271863852872 68422151695292817212144428285599618977819720320674653264197884197922193706664579143218635465122679999176285651957338980554000447280063460507668303931366061080966202833662462703615178992745886253512854336659410056501564044162062998802361369812378768873644218162714383055830857720219936210342755726079100113792234399913167316150446152052035074061879639140772949037199469808741414864253121900682539994603666632236401265691204966931898085008346826990983888165224 -66086779379706246001859042084818157688448433062441259081001170202888923006850323086944232557853965760712819928082773059560264987883237647681914224613479869314963568101232506950734405674702599944300865859031264847362996067587748700776139804779650562953614743702221903354526820258070865149680827958349627700437790723234937925590799219373086771975862528086831122093937274656378539310872859355974562294868302163091323384103846146471866153067315814201188092242479 50317578288216381295541808474686469723585891147147943695982485239892644773378310689585801727480185856014814847439359293522187696517532118597183097712137522616210373884099325913480666611503021273056047883746399356732222792571638599671358163678607577511432426638768995567552731517208274508458713553613630457162703852354848042567853903097230765867429917305057653428312945217571748958093517751709525165471946048562673436986754952313599933042722067454156611509967 -27451202898828711302183278214704549408229343446576443791082749438937627539243982733600771483015968690130919295690407998787826580513343895552139509093407441960587108212179664101271551322780213041177305427057902718703743701754179366443073915989381558085457159554981478610235503031166914716335069632111285143130874470538168071145112803863507769197509233349224636023107433165385657354283894925899096826775409554132394901289036477543048449137292197779239428363462 4472118681638111972992593415741513499723263293861927139262500618777966519932677837111401364955593197931556707037665869435728508233539387626025956989782141983183953200147332901453558695962410264185695029812540038432180417495827694394590822520188858743520500894341165486684157004030599935179815371562683379430304667021234803915911592263586999176894074009748646585768793990804700746584307783487595464905196546036418455870250357364189516493411376213886444866991 12488034708913641384045816287907608008517989717173782324205289399675451969969783884758434258682545252095722247182450049550231552973583254134828582191079440980736057826653848239399515655153374236346252026340079497850313597636198979059485540874978054261157836610226867880177535641229698374093783175119131996382945765924505099384997435061373529693457540021325827426702008585760275451150225426804470741863779842677735943427850474540199472990665794004340777321752 -20618946216964604409322987943089037909737128019968386575005295076217805214773604386737086208346926665680231605551968376748037734388695495448182883755517886688420662710530330545595937894549951926565346236052861485481913324443121407673289769845606822345978501974861283916925779417422533933434868564285340797980949618385489763787199801443364942368093752629165167947148110753775415325827879713393209148254488606020614281899096880630164712660478448526591513897882 20854631693834303357614434522219827790587388830177066954975281851527940827876231090030946939811463869932800912727185927099525215393516489952042691588815374948010962745928665814955844461069229244241604053971515071936523020642019205985481076705745696225624419699655403686256773445707824285040304227754889545766179368036100990504193624339464730450499726270475705205028488418679980534289267380334948924675391894859495383927651451556807603107516910853202186924057 -15933633935353046394866605018980554380689648019037687957077670137601434439401286128450722721856288315440212870165510487606909463329096217934339945559252608488316392615815899086815564753694481786806725974533882876096470037782863038297401237237114238432524406542221323599947550889143548119099361435117823965139035278401994459388950626901949578652619884497411525225958846753795580212783598274989395040567557686333383256463519622341628322185328890620128611642983 8526546277120667519206044572167043597759296388734384570585503272063942168613150881159814056889841584138034208852472222767574453449469852752731753180389216517347150860957905748197610454678271527088969395259154357096681585846692633117207804359845011781681074865937793772063630870441955145474369357303778470837012774180029256567895543178560601483155013768457600786316840107553629612486125560052785338880752508261308628937420331032901600836925620650395335571108 -827181613876201125474872611135428363842380219653027994794321625246257365289321779258976808924517971347513468865922202644402439808884487304295811477225416660259416174463060237716557481296756953307402112315359663017237712603342859648397231234031325339809829536202779175691704279532848314175213415459597837454185775875891384585429503571869194954984510383316891966509497374163595498156698462740154777588640187268604893617350394863652472706050125151075563832985 -5235633681458056572460205832144662931731504124928175763285840911752468171421505847044075065038753138734252184111887404800782880879451020697365615709732202812440864359146979168973975532457149077867309188748742655457627737248135854590627926126771516531024557775965524762136461818559722917455256399022808837856911858525615032650202300695315492528100808918053081453009412707359704659496119755327892351285250527317112544984526566170369251639927391621443710681632 8298200051750751470213715612533141333728581050466680069713024604277255371081236777126262658848698773567130897199509869201631478096939734114279803471097571055051035032363710196623395211177868199660695299337301133158271358993336657631431409990349097044940365399767994985480858921585098551853786205694055853682463004764858196140188410386574390197243192439172304933133499449991420966200301423752963819939999598928741852904114356021125159858187788961488448060318 -8156546766624980835469818085884550237097917341852587699736448149140017599767234994687786857440976040068461337387623447944020670940533694769764570242612215720840976216607377786422337829329213721654287648708677602017547429163663850087445231648376800428267860891888919897242112297441572706142278998926664879124176109188619294074214786310814952134264382485178758386661314511209295174832698105722778342072901768553019482189063918172686078362708484766099280296364 5739900304347194835938679619711625863600128724533881171211816719363354739804718426255743823374719846097513264849800196939182793156021631267321266455365404962253916717463067622641382265228879666123649424710255329080156289629338182253348029533010482456659809330166144451053603555454030468768340406150498109104954477208023694836900054146627358549668348463754050872537757476509757559867786350769691899163822480230740590502890404225525618385395754969820377525453 -2372485679454178254156175950514330712641914737679056689469899425698114299738435120502994399491400092335046085752501439361616257892490832055879921125139179257332052004242991249581462264098794605367445783508281429911050561693190266229757879169569776304453792905035133531738913626173041682062197523086821669377617630974141095572455961309721167816165082628720749025609552054777700268621517182404613910187704339677376442851396428487177289281190885313477808785111 -884214086692481557530393543084367024727794675184126081475041539207116003125334352728510441447485025332579840591015221140748113205348804054457389185509510921128686973042658849621209624887245283841980349220271521230987987984307807766102563420658288716496274859124394794022938478890311286983582074262791742803406539641890242534753935115811513542194472701713716445381565486513254258285891755513472253615347673290572605357626663783807251399213641536686689091708 3355811908753824087076366078979291751254610072643827776347658382724891506076601963471495888698212162581749766094331642005129189263690805453754905746570217674522887501908420277388384737141618518489801106435602027378932140284096745300600573464985276260981007264035080254186192631938396198316419993537971861846521480803207537384027132517095978731426288055295950040821560180497663606282371902996167572819120116391916780851193005111450628260467985212402694534236 -4629941244597484040819569041861872525402260337754090753398516449783595916929586231343088813815607965823963852949567228449954605467003785870990769925623538510069825949327184243862568503597414075874498605130960958267327081282802243861269473355409482896861058264651442403547952022548877850698804386799972619512614691229573352175682090784426190105666229142353619337966693954851675764180549947914529473469141113852683753693432989752263000078753901518231561230451 4562726149675201791746892019674716574670641895068449663310391103996867126439020052249086611966557867845619007232726746252452718306923243104409978390908472447726738130771156129822154240890053694284966606231655003291525270347691366064439529688518093265759365019226896750959104914503523936429063301071587940040785966190328498184531832718637406523749179342845793043869863060160155002666175126311217829452158287050995429987169307031103763350588209349647355081354 -3380105296401580892171798588487286828311312385125227082727564333315858254389751573073166304049752115849460146085370674659076011183566867794757341322622422218078088842463315147734704501534891218452481841704374724449563772567222921364267578212801943605730092699256529986182585975649048240595124277972805812921210216611144805185211005528329840613258581514971308549706731175826473248301908562120038765908074668584631751507466837277115790578899399649585347602538 1611852316907942287136889107583847305367908980181507050007931916868464886841971986362931013684186025616213955867600228737370304874038057659352381634771808261817770601712946607175701314368647104633569222347136428562953732804130403480900681956614907982787594182222232771820196410178182608889252208253498387222182664224007318684694207567928334625578678654875924372466048707364807262785293659658267889616109662493597754849806994825101524155029759519628102019604 170481307173365470667455490010226913761629258025511500045890437399185844705329628020207608868448548385839071648459675702600941283248268874216069573475801933976968467931694791332784835308968673550430156541361467215595940501511509195697327378453616219035600488508473703911892910514803097322909534969623259607282696591344346792751865943214718227097978600603731078412043137465144241287989359627645842630294511348348928360264543339338695981600147160960245378943 -1570049120281896120418348427249618339232778626205273215099565992466712377003242250013667247595665957764293169116722394234883127865275699260570105801041416380485503153478181488401713630454029971464719343101485164401993914396212192076796616191455637352296983564415847526941260294883274524100385344810373095127160193206189742928871618658427295403778733869202808264325330609468201168923538237014111950225502830937978992127606444425990086168265144784521633251860 2395288077809045164495739812027311234394804331379673790022507727980623521555877290785440329934841010519587335501998951313847193919241075176122938634264229355123167421065882632206790757456643572188159531190947328755289148869861352107574573803174417019375849856439591392140468898977744670976793304029281884251071975013268061658854488842522786956339564740749405408103813222914917558008811305379840314688455596547922160773735997733466133828885096917129770761156 -2596817065951044698431892876826766551948777057115049856724029704615009112110087297341320582290415668813322585119467738531054045664699656102447337851493526497472377511773400788661465271575470826058786682444243062145551187638908541862403324169134545588441965743173801895593877260651179448238210229039111183680793277806336010349181088088563868902144648879495096858671322489546369724655667916159502251956463257831654223391429207882215296618517463184721118302864 2235743710161673580278259461506053989333191804759869175072569952886174114151577001621443060818024356837209060025578824417052192974412746792713911070420827466057876290865327792681996436690872387217946067548842399361243469571724727108649602703903017558006800899329496666280746557479711432283296633964215758186194178353002057123470704355823931374023073522412442150458706647133646747694113978792409224430072084028567634562225726530784238194671360735192031064302 -1483791444473173481561154240082371672918862082620126068454172738392085217246646450748803641307828088800742595723458053711143225604732918865518498863381647076866002163148807892834465900787566480885125409963606537807994797437972805156182354906648030325417365483981449746081974695609496991783672150443955084010377061100701766115252189189908341061907694421212805729587234081582859350910006337924299317170761655111695548020938099128855546388739470669145623757325 584622070578290074749584522373255767936679189727591597323543212913164524333776028066288934908200260866372283555132485531993297690821585687132052732089951019041940224719405429416145543344088358775181307072078484583056289421849641042351545780695930717487584358297929269042771925175096659578735409689264840684043521395961554861595125346409923422528582191203423559820478656849342799630442082205493502892813937091589454899670487314147485489688187652034915833320 233676679841837307883008159902822741545219290416915249571916575287113818249277889017826181243141281497860464525022548424991567279432715186133754338629548098948549477270949466501581539743222574547713695838511007284024351771400349790696691160936040864200013469538020988748295693122915220970065060552111696779493154452830192224601767756710417507137607080316900316054449582526296955379740168030302916483989644313722302846014076385156195001860735864725527450285 -826226280374802762891976149689354779381159784322767852524006533983286884257376436337210459883652279673437733121917559501803520055155938968781808432579465229964894023327108991567036134092599719307920446967512444950946297775311917392688991754075903520158098918575477610963412369396844852689543776246689778992207183377274242781112838978148944810435751182906332328589364775202839740139807920474030091711302399383456732398802781081093047371030502125232973047085 1137539110220921282700750849813524963760666215127132465008604882543236012530751505565883639683909466676856141235001461000790621258434229381119938599139434950151046555280540799453741106878565895596364418642659934850521481772620737507406814906529952814263809160865395052185417400010008147450122294036235163055746577732200926624100234954903517121797903061985512310822042872492338767320197936295089752924565384971488863080364107664360455810417507744598074749590 -1174661981319098246739065345129392173831994120761598282883171622725122308572028874338732636790048069313369996430051729387339812923214072815726370453688229227762217186756750864303308342190042213251754584524140973354224285078039517196546908441703540101636720756234449661180815350307487186154852821304921663219564523479948773991743217107104545950382301509239834830378622016027231753205055968111437401531802310225501336716419637876659494633170447189590537129215 986964554029838509837045662585034525869056908032147771162337176211285457151678689526559235732084703367474592140795574938445641233316581776371105160938747379560761657343457842483594959085188754433102808626915416267209917346512813453522646246230617064017419826704534355328611377485796877127311973379875347886226766000038978127434907395792441856273917624388818279886365610239786997738416692887677021691118790837860493152161776604952136783337074096522020625323 -656449916104760823608534041098746413470940101665532657503538565162860767392366476322903518118046503250976578224029364396771732490265536402901468186701302784740671121183081475433989216758163015797001129882231156770495819239939167949031261527891354939776075339194612704473739631178268701630554961229307411794100139092171422368886093471226688392377925506332568733913775233594551438257648057458033240239626167798307479077170734878528854650977181373408200851075 280765253643348883838127957470146642949091882432448146120525627456601421740508065121962948819972173578234574583573328741766959801480170848138594784939377529775392833226681966394554835219794238422536440935216877350752692312455119420856435612504241692759863497014978801620795901052241184657187065009356121798390892166965878260871595763493397131548123453690249194336372143783808767502696788009306536625900799656702245642085390827606758708474778337593521952039 54626932605886697121521964106316979274890927917416527122901749846138454197567679973731206784865380609899108867883050984676731040547841106256087608634115430464968728065107449946511450775000516067984406306510899108769068023386407740912845150121559990703537997104182756420260284420162634413290524709711488511831447387164990558799901482173173467665417677214737768434135585227217351463770291300764546068219425773555362081898961074541105218261176372784893912500 -296942764775279123542396515279859162264029603662314136962883435519886371519816852021049080163042460518859625804670799880650976828702397815585533555513358502427432700466585163563591757514042756372610422763140488757301567969802052120826442481439515391532325598988177316163588606389197917324273110922345144013419544126992735516379427055782766997435915213170857903777209102184225670008800696060208476899582576248072221022165418198740052307723676788898578186161 427401284757682534336050155492887348530700448148014075805508154982692602986731520361862840632560580720138221847104526508622665940147853452354094851486646382018229230631715060960195811684527968416961248075343450783366116875367979824356749964104883402432154927111710830732797768193462307338776410713738475313029566984964794904744627077377698784378726545708817100199779984320139202690365723705752039155643252031916771288044096506773784506182752283466986764253 -451520021769291543277770881347751503201521255894071894266613128849432971127215422106111027215542673482944489998944309258550425489212485873353156776144085188447240743253118817678685014686326372469857273710203358528909680863873035254370918729069242405859019551555766533108526208484209972402631939043652832271392908510657081707746068535777010185338248511724593957497810201587498774613788672242010503641343346533546282455532231820666560695019061404043969285808 390414762973665959243302076862197953822745861774328719944694512017001689292222779954007662412635460019389189233106023833659811467986179617093140533258377937977148497106591737555266699296677929359800157446673413356190502848081438354026312594967617070159770747170050051984282218560516777781062523883534640623425828024286354587677249061310958487513489889098668664184765837300473870791341477713045484225098604590242051552066638788072757823101113819077610312652 -275322107863572537172581807119733224481663664999927229135089705293744912403659729175572935543297680367336994051151093413840415915923593442390083514345731517934493014425171313845099946522621870449796091751667783022063585741314168110202151098897906515321625568646196770310630412084640070531945537703845345746429680185648025299729309289682805009366974300643747472364782931450587358851432415454369379065009391779352989660498310875289892790485689905033927038749 141181059777773971213203120347149338411906565374257407688963076007735714414646022542248681793034957052300930566176923055274849813583147114892075302352970058082361536640678122755740034617153068590697072386005055675450049642100364246549784686747228237080149623833890749125064041168650616737850961755066209297123334324658418953921897976591835210099075294939705442839552647787259234833228040195102036820072243510740726258055884600007755604198398492945131640603 -18101286002210291820746414412932473594662271903495640735382075589455766214319927957233935775375213386901640954931078124594729210057339713943436220065424713009024392520003861677707894600684752825096363174183882612339842255247972428528148521658861211483798911627800950677625084424292535952301196020069750457293497356416657763090014234807932769390378624045971126098175730429473049966079314251565677823062043734262941580159629234496929976821831917976321508969 -74806205652550563484320337093545215054758023702033928287383991814929261764393611700653454002787261127585646710758638138250365884667289777290250365090879980761519646069853201067653455493301133260995097023001498840382810380598376326278435631754159381982508539282703256505890517801264892370291828474388867895773181846552723066305026830884796572639163749580883689234828538233738845747995129069928968447975946011463669471286925650299145666429694071609663799318 129973669371958313296522417481336617930710516100253724630192398661052903092844475559963226434311510173306498423443540388732899313798657753923867370082824677527286472880432817237975561781972568207369195519608396833987352694367442662356842705959799470420946193550157591607899926609039342643154986799583691785974245325136366880138005938037646025072491561454826944030235625091320894266332173110069575921208556627813260462608211339021471069705640190533836150828 -148412860503187515176692434791015577114863145019350502945142889370212658926918653665988973025814844974349831511207938198396154453140161991884249460102694900352513579868386796616787576876938990225407058124491730024147424650677558009190065730166384533247138863891556398814890829956019470936984882229638518165251687925599939207497042713506114516032833148379085676220894423457114795320180763211221995902922737460878535839412161427289060364012384188945442898257 136694714603614672824750786636834640901768567330448563290720158994798582679166258083002537797802254385016204152054220179833794191181280321092651595094740826871751494274501234794084973114951605604732520370622071954944687066551102682268028041923432223275609439292686890447240452299594430895539193623808399875399865957793295188674432997412126621810407424954621466195806045170438654366001870098165496170949396194452976292857830502301425795574488982513213089074 -104789571707147326282117159434421584783104076722166867126712170714704036004452352454701175625431124695234274106638756031867888760925112838275471847651886057364499729662598255372826813017813460046054145798186589931033942924343467298150149228660816008823889712436420449514526669500757435980335424495820406961697983696225755258485883926498635159991994119354754898218798932935746252071758915661893497601389420801154479842241525965910438683433887198231158728819 63891711022757687974687149038752642816666524441626872661616680661370819770118408438154551236098907862676107363645303385490883081094811459016908357012042903210722532831242976099228394643015827374082531025689339433713123356329016461887330813264813392344017210471486192236412237980854321622310083903563041147337447623002931355311276996977080099218565798441988271349771342242703675099931591503213417487044001275572279865955499971218427870321041587666942268728 -23881466455678190368850033104991637136596200963887833829880027562806885500299871668176852678667055793813291911737943181614371269746493535861374119189507915873982172727781070288654336426248070426827372838289292643464969977158292246743032406377643359948174438643331674406052206442097775713992159521910412227602944245512919614610268636548859325634532896254087766559721524001250632002792761199380112158842761991881988547583849283423946212832134697661904904811 -8544602643581111141634696492845919534794846577720691033274107764748943448136170158595022363288427374902851506785893439048219408334483620970601284569563526019260316973651358377837182392365803261707930375145475683770007697295405105091170066105240161870724550517684597718511653860477957281168246307651502319466045795687374219435107289069253698609969498624939240950488300732000107804142553820210569308850808975147405793596991881942657793580902945092641212363 30197352332796393945849390659713959050751397289507751953173456799135203079750623689473309827715007639896868254523187040351343103452955128752146069951335402720635031572139774001427321610394715134867844906267221756848805841636177837316295904985800008434949868695600996959635863982375132821788192930870549528949453144988750024638043381782593737371179340044760481520186843618199043649326328980351006892640196644303454830826719373204295469794275385601850426480 -40653075598898400740359178569850003303903567601290469543260817332419896754153924771313681008991251605066093592671578908968284745879689599143917749658654969532736036069567819820794504633342644639808383595935509646375909376044904909584983060871258033402062528641850616085460974168732373678195737044099036306012137069526253578378563787301771858024016384863511906462024408077081540763520565342705670947914298453232493469184962714979921248714857260833372395854 41373530528044948587616608826835807305308216640123901447820453913562222129653571032266743283452976092096480234622200682298359947118940153984989451870545263451556298121933205225453868592804856415983927999864706745910218531840987667561571834656155361527116057010547320515731729689843484476931172010967342195731893835621226193288259416982812359444785430923994796322139179601546654315795906877866272617620599966527275612358251453823280986557491869316534068343 -35009673072778898809086214644427415468685324171244197355681516867824442971393443889568454403618348373356314363064287653119915591911267370267940808668628373332589401471498720820115887944386458964459529938732336875462524756367341486876619767345927814832991343392332021775237883103390889556615226940018222933268971771569086537948727968546246816878920689640685014979440297284327618580621758682338383444751224182080571570534895719765941875536064465544699575864 24733150458184099092267153449450346052241348878539788099282104864414735986542936399247030057849077629201792487786023241768803442382549053750844465884101264784267820032697129011565993751027569749976769500869073203738926042898938247223945939491284881808663206773549804923287049900376432447043935825037073746896354769506854657946850912307684484664484055551711826833619149144193935106610639122858626372314038928247217510841542019558701222457587832226313899610 -13507769923587158923556208239540869784293809365965091341429811814371987665496788800154647031876246412169250969248379789790546924548952752102368758815028201481924981463947231015379614512793719516969974718374899958764595714923025413899192753848218879936207205208147497618937706200604652628737556554742012831438578809153548716145388755314828467337298926486935355224881867663479794054709321933709605848826944222602727092983158093980415667882098707032632748416 3524435435251872002176223350237445356058699900844016534300181904176274560159050249828445689543650132682400108598522327155911766711934632328603491361121017133504901497619588199579558035176526257098176127535504616101594502052076762642624036816728488704510407135152019521756947287232463155269612542886702960940556429767034517953688321117386333041741259830021887789124752414495551566535714659218867427549987094866828915583570670637098736357068256842478724561 3969009389472841393612354758750119490791365944842668678998222058447667544955576540979900711202130421259720284900571611937657403238238863182606799910509024630124246537597772614279605006046233293017520957646602892818981922770652721315882842137145914176456293519755696231751970687615203629715171563027837295547272479842970030636377027561369652615575300448120502159731763585583408826926937747692668374291837938788236176446526134640511850710286241024833049150 -8530578620341711941942196990739615298809218703719910524136817837374800188697433494708142199350610914743545153966057918332314307574542809897400175143613289870475171695067867282742568590169377619568694675764103543872057142491100901736156842910089290806439164736982554041416545200615098531843514831662469238792373212004812667923928028207387757270790834080615569096308517180399072648988973911229002523657621566311584330337108178184787412771290290240054588058 10310472599400435549321844115878931873023071566174676356491224723644217397380810645716454675322678770870656829135251125981848046848892664620000863933590155546395396825371291091894101808873545236822520158756319200664891513034598686362885365222616554680348667131560254251712601216392727885239397848182105671336312731790116538789006471829937082836208409578619776743979485310229895725106371661723645351414609347518325582235573485804584471752570210030128782248 -9861500543484904819360084220999674263421378905646319080668664125600501316781217917271540695744187309657998490190708758025636728448954985323288297549691374392003696362978136476986164384974402478297510118415299793620899383970709709816573260948483006862724410037532666856360959312429802427406230594182103972248263630559854861908325136101663733776153337152758557270971550855569236889210526576741812454987349799595964906838392750379725957100416798477955378158 7954213814914735600751532132116087491039907293540085761374534671210976129945699105121620570403675447193440142333086658693367425954091824953473656662498844310741371204607020593034345857797189160408483149343268625434169969969016335422408756003137985538659960586151943184370634437506745994159937645158740247111614708877584513140169216691258664233775368466419669000255507438136809571029830531341511894816607815123137655376972972108363631149749411139279019244 -5378840818401220734845647257210445508419621230387658973493905119570185509078427713096406536484415248592437654353492442955260557049313927276859187366596631067779048729553688188122284344990647861036708960691818568048158452523831329434693003376515106112347943025455686045864006280626221055018130789123818402075409790580966602784114837108014523431484058269677384858567265221938613767219023531342490853490013890641427199587554169839687393675750515763564404304 2780247450380659491006233720457566512787521563561986165921810412948522802936895408354251662736887607606011971299312617702123806439979800195760957868820894199385215137826187276030225173206523344343502548230863129456179287803803299290665561754771619092892991418051522138167651394494291416645009526089441637083762027277250567107438677577751092991962690939801887072716837957645684914997955384606148735825900768749121756827131251442320772391746033348767328325 -585133121296967242847663895088044726066923472075380976271131101265966296447646199941481041831795290052033130416524979089777420675066468151891724051930125855432324061130130714049037254128425855584582483960626544024151965725770737994034162294028206063448502036494902770974601745116646845836702342811961686968081032468818833399356125864702717852529786036858933969455238670775024650344897748141274231063483708748389951391112715929188925882231897688631663942 -987729642944387678273097254230179154336654393437012162196984929995464486872477113210341192919815170597031625072256768251861066791659455803152416888399672964498472913826758669362313228867302357462775454475505109518665275703262057250539421455285923409459064224323521273663003314404831823449400711871235702632429299219345706846827737940166542360093717070603432779814352968941796667397822160932672900393389938101167705595032116671494227771475793379285790540 1886528104615851178679262664824371500170672190641084886463237703415875586703460904501416273808349928753360988664797455350053162947599997593792706128313474964052420629270054810633189139426429774392314504672314643115879658842609138983981409805702362949252695379605851069223314946848130259547713823136272920297122356502983163741465671603282676209316283317330022737259973148193560409306693128460458906761235062780425621476048207930228710725774610509179453857 -2183270531999673531815044351003733570148517626104460372617974864535150301708118339320648112058967686202759887521792287136968648711349632098736418872085675903728652784224322929887327155904681501699517751035251167648603203740585464269038737282176270017229639823041522763823364153439542880142224509145122043640040699855343672443139844397397540834725206710505955052953147011009396548198257762632240455491293988703699620354063584880216058944077193481034456173 2028716185366827966033056853879593236179165618889976579918276528443145339112451097762073082807092282802551089200726105208246406308529910828646170013107562731661153990876998539658928873750809373576026980673486310750340302260117001374029116952805275256609142379612769548954800781654886202562410246002182725189459724344445343045140554858388405987211126619732873023996207760642355954862467355889700976775500787664628383709278919841227841391186310363665492688 -1602826223786359462875254799857489054675332111573054424571192580993937355477508691095817642608867424155644092235937236488530641727789896654008416242526572502878371771950486116430407141265633816665531540602015830873179413334301702062774234600034734276850457810367927439939619450941175395309590991972665235691040658939280007406554273946063216441286624393459833490655297695007484155863697803382495632628004308659333791856651432575084763582818158051005633920 1069993656814824165103358479981035747194773156053319916353350075871124483184864167437167861091886598126721505083402019844470786697437792656745003223041949284272405362460189147547734208378445022584566484371282089797984084276158412282765230865898876355170785794484857169540010158251753784043693229517749532032039208003804172538315602980594447921177811752454684613083216738127877374959119484142579023210159062948545590289304812970573602548900933858394626362 -553470100814567030344931061063708858058510348183447016805725120655639508008336430470961852045251446693578073467022416478654071735375726089274181638861731456660346266715371250161760158740886844032929648595571622462053783437448811233936344788790951525124629127893371812608157925442954611241191738506723513137312187889886832391097076034783747886178366935604023039180942793298364644067753801632927747460018722720097764650914438487301788788115925814069771520 130396951072917871654000464667211568720758399560164981985494390839009374920275520091936742925064212625272619964857979299031672324977067841117149091747547738524462115295005180202017896191515730195037363703051576260178959517194898933652473526284780867349238513352333319962123778513617732973643989660277264476563935259604836904497464343650031472684909616174807034407246643110946445398876228386306718071281527180480379456768479258506276828866460155676423676 163036064569341981701882309462035472050262802310447363482116825907266279709828973713372504195610808017609523706453506370129141371559930635692373462414040918449952813412080358785113996546811157869258337558668789953203998241651412650473582970486305792894878936620128453467981355974553379463347310452298028754008374609037251031688441425254749924276671006745830014507683161195440683631389903244932876476781329435848336712006781114824823404242471993959251208 -323716665567099011764131747215521524631546125698629778724729966744329270451111030762986855417152787080211122897152157458017380253551982500616914740135211959842763624122219971564149020404404006399714128629342012766981658195621736372068037900214128427635004859544831380675707637722837757584422283968274551797074808261021170103345091541756248516082024140243298227361195763014627071172978705008126017160709852667835835379577000950657140235803953366545355715 372192850474440891887283333602839284998237050829755981670743162692244113381356607826585419406254470149374012905290770459546126429216958387593661127752129961090672055408858780710616474230011517879338831344235813892122915241600557467106757771139493749787511604170229552913533357060364664750736579426679338681031524962000052672815409989818053678666463260907783596266490329537339535301628982928903600016630173030261305600632224839817862700298202433188746118 -341625617203391364221829556576117292810229009135051816149622526381805622017069121114613435263036618658434220178557292955365765548295121448258977493234325214947838828291405642059538039130335719066547972205484885994043277811479832327832222280018872942071637884078184704407617310273729013357849195884003684221205989998634742239663219638086669895265482013099224611911116925233525578383092651010793425675277925188914443952162051642933309299437543934528345624 266917461755282946959966502486527484451231082176992504899493112945175365748619915946862779111075344947174303175862959354328822163364926372154698134302442335849695276084445776678215442769134176103320170558589098497758207895361862496379244376391107492020497552948043520671158636268091174968953821392799485247114564086895964580942140403113103163960106486367725777457601018180279007753244813613480593525925082278899405744031278338987616764419478107074989096 -177273143963051770771535613711612592276111278026816785325035420190495100548006283013152992100591324758384848886294556298783966138402960400933115651300060579409106516644111139064909535397470686825365965441524526469096580090013196241407519737309354807223176560464189675493160837316124168578829273281014641201909783005060060170446436511722270171086999982786624431673242200920405654928122140640908138686714209203006085239766569435710607903855087860521502050 93359808687399988024888712287109541917197847154285419589942742377017001212973837312259963700300183872860803164753378336464410776444959289547795761714393833370266227443733321813674873176113134862276348736780783937185760395400351032886367157850120045523217389662968644573218005987307152012240159593234648005490444225877874810271426696118183198514733532118923011171509998611804304428686521679218673010238178317293480670172113326492012283429392914690431028 -27308012989393565920834129164551467248963927497862997121272339635139956505188998846346720942616247595322697677745079316692263742172070802807092573644580229746524989127413161401228634385423036906378414606580497353421149821882830535687205739864863186853258857907162554028048498504184614980888957868098050036117615910736515964364021053689093433173457308133533774167363524238687064712670888707614567198547251683755134370152074707068401186984161385833300552 -16203087984356722137129326619747827231503087872198403459383503410154917158979202105901906994813298650463758048843328545443759106969427338615655107355732029596816550256768241588519338682750287420782750665754294165444115570912909790228142909367368990038621360205793622211698149258004678517458976507803561395452539824732624671367295208150698193519606068428014338561310991956323253294401287079439066300689649597882969620882222839018992527729435534323855192 38281155622018358152185760910587073507089500462538929204739196348924605635216419018330508146314990226681161231162121945748891539539340439147828954820980022889354961119699098791279176898292587933036577891311454773518575533848550233137099156091473534927288195163262224191169966338184737657120420711276733604496541293285692460056073085835190509115161916997100780883707551750017535666072978031663943427847569182223842530640318969657396234959115317350559958 -43666336283480761000451985107056859596647799361929168648113828345296993914220389572917432782706419945558778242475936889687387639381919619877784246072276127838212168566673579478341412471758741389294977267714880125309559382984421360986211294332057865643107504419614276519563958633435417453582264731677035285261583582170232361587027078667804733860451354194407644635008195424482510949917937266973390172461341658965903105373763184617793384793625881600629144 38421581580092717389276744293622286049525602490478760077312532169523617902503074487075375485123578272432206610290837399128607032325831741530289523258788649600567664446378215795116773336141376615107495586543986307712215505529557796113629630882895917486874575340557470844575192929928287456370577767791315253973598598694470753996445483819843640983579420584359762440661647356618123320731245431261203564931286894923744346105886913863756621049763292378637616 -28131089906984391172051464956408074338396916937015787352646477653198371286740182022521655850883752159195076689956764423149875181882502481435896430131286861086059782164323201899911947172106792752113950466017195983240905045526592728457704517541617999804041936493634414376006959049131891489811180951958948454429056925331875919474388456639312854551382446606135740906790976134529143024244574037522590279865199993410824578158612790957657775343025335519131988 17014926936044160907943210975268576175270635596884051225176416273933980071645705089678519224273939232128387232514186187571962856045824792676371187377826879650660443964590347998036841398075039120081152006858390353988665854722597747575246450094151175403691126357539346986435049744566986588977595012885123591284161751736462490485827451646052603163223387496330705716216114574469451141062665118440665853295354089010982494070952615946131300251816495654906524 -7738983666062160467154567720374967351977521434102843078320169606239985341915784931950687444561488785855229028409854956459277779725007341717837498657877618856618944797868354077039691593099914977555280586818819196028517627092449700613519281435725026208559249095288758655441437955611578536791830932820324566644313885397114335300129793138837776462265455926392542704995082335813845953068124497978139509855428189697529636645894713703562334057238501684710536 1540940188734026035020596643053255284463249876382849503688378055116516116655923103229676710018769384234325270562924927898823685541161793336390850092588217839795569865193284121972128515728791804964055364678276786256490693218970745939097747006334986564361620964302483405929734014893285273711321433324525726836961422442699091770675928010686549343495675428388077630058400397802596861333679003416674194230310944781645744362165893060166657959587920064513740 1491977569724034320566119913360935103301886613666888885537838436723000694762110499939503466520248567329891790267145747636271461342737540618235021376328154573375494412906397977958166610374428309775098393191159629907684114760354950136552871027823701539026723072497312831880229287290046720453751054740895159602815158350629092691937842938977353236263197499280637072178762096073585473117352320104617553898355668133243349553533065549583307668688574982158636 -2036452190099082000679724802170872070116361348935399658824361616313130899712496439842492570511684725758441528904483306729822655394917614198095862645197130301040786308692603400588958286875525768343185075596280222148737212364613048350836320448665721660796217241546348636362858220602773105606204247708040244327422545757010994120460590362133029059685362405241291731834881531404881036292512446996547614996198763545925552745419085084207996729267684194813144 1093682498222338344231484747225664670306273988679819196949525294302850660813871225427497932312889119634064949635202059136564893870535028752729940860813845226498215482605575127567946054012910303120411322487302700987691527564389265207884044669805369078337844631835158329641643717657754945519610429791054332943181090637927592237444628717460244980671074195404573687374224577976335734131897198880537208976821877123869671157838399972151065496575322714295664 384514359017971508555623570256756141390008567943357218366188505816685559075912940444225980770497241038129814658248588503072052108804782418166967037449727823905816305953075792491996637842824600040621924257188433872873275690641486949323676271641923560728653938745855359911737179927791292465218804295152423268357346682473431695926836814102719947929109699593790861898395371214338411315046102321763997000953938280199231340270993991493660574628331575617400 -1700672153558091590467407516651640151433197990718850172324308382272535066923124180288669861504462849251321361715220316685211098158218284324054853474335063719899456330637105773654493452371044726150838456431409102495896778419922426604151821676129157072614377778685720512209940528259839734314177000223687945484163898354524156139238372809753438148800747182803775988749685563444870189616820929880050730111901701745389360158367883376069322658627396793974876 2460912055153965959167792888861396084016763685190526163469269735299795732122583800347891912455251181258910429270653492548632643156968063365605708915739399778029736051904206155081252030794443047650161687737310919418548360383701413377594830695981365388522443850409917477436017554869868014038678589522116872939143704445736603376032391435914309587531675011105981997543471238019100056051166807358320589036281967666712420818457325602953217170542118931742880 -2543636234704422780021586793094624775464106517483392974921308982588176824115595744263333792335386686580685952368467985068551759810378248005870064921222393758477043562993605605411213857853136531817769898046229063987798584562117179251559457766242676582404907059729661079260502980767931637110408873968354172166240634666910329279367347543447659476408822698184781679877319634401437217628537831423591353444602508411679611632284237245519208344333889733897368 2035567198615462584147859558092303860249030163947010330034999033524373967697274891803538359802046976868908545430864718504372194223299424651887815434081510147405296075010644726903996883465771716183470071530920914318958605326243248657707325486700350340934390680738609712605290405576649320962166952074060690915174198712294959201301567192636785148511986183574789271785056664465211470966594013058583340358119388338732169732524917730823410042931722305284160 -1151885680868941252870663359409065481421337498656850237589014236284308049139975803339345721325424895002100662893233594395182759948776694020189738618943332579895853666190802022483482124418006854576310017801716938734657591981198910465993068016382251938940662289088928515244895094970317411260023406625296281611023846844368966456415951100435464881869038548761397826162995398275065161118900867472622207691683800413568006124268509554813108455262524774959140 149583987624543838266750669307474313218773528749358942225776092948021766642135632226707847265008567671967809084258752586224905920323424682546471072124808532131416822803564441232831173687761785955507543556784790102547557490007563146804725689113701423749296776270161879094937478290347594453062995582493687473220777539675525942349960299413788591583182846665065347142101368253964360718972105998837458082568571968392778491471541044907071594086644986211176 747942118153711802687458186888227863947433443165721713531904490008600196668144290011110397377385302553680440709314005809327832130973559197338214874308724834119422014661620962449664841114832822815896051038405597336851084053900398965776632662454233825528435680720415760546267940194642733479549046103940298240376831014719818143221548857502526103270308164975964962037061364276003216323455766487350542023535933759706556681600848739753751496975042852611172 -1393811983566597380544902950803846638759248023233253784757059308394603524877831063710564791778174616948028436514837977924968434298527690470433716004013740382653964587702631194253424381561146371379334811764887868766517044108476242541237895715218649155613603333311267398619888297451880017176638943588301839195634509043721323347673843779207845381436703987075169858653455266887798658918505879461057956291149843823208512810628882223408174938357429086207848 1725589853433173296176497370639938008635976858050390462193424973367166017731754253528263162555555693765703255364538184007666145581064126171299188555923502638238055672637901282669552066704566732322196291328049802889637976385038453542251281098812688543961641192677383564424095733341279318279192771689540638866223519479674787388333274964477218215735533107945402429239053588016314708985105858640746633408790061395591812765264951385098194061875173051081296 -1752284694845592629154912293140912022704945433848498639726332315642123701601113016797015753379780847052453887816545921033937805879549387495411697627318404332199265427604027628334234285107137329870681632058825310117715925559444284104282845789174175539565026831538872469764122731115156248026988317690744135775159477155957098658614661256853165398767089234256876012616675763278284739460362942340939038162907391093675324720773760386099386470328999947505988 1533370077294267044835951637658069315669303793900994490159265176744088214362746185593187070192027590450095150065175296991471038402618878202040004247007445223419973700420468975810563839751911574524045361627557855030088050506501353468158276033923201625848088709990095056902233526445934869374004319134770779546900300164289849308235674128407956922158703835330888390064059312328814254636980621921643792641197968842687234791819334003335840934746566696047220 -1156194236354469707614778313387572970935716177167046506416713983857700057064597392709768344075620074171019002483172726707796601212025096562527487320376285273596170452605572140697560238697456875895888282220136005164575556343617694621809025388267931875315146201562450849478696190277907234300678612414262307813785231333856463595825601630797089001574746798215196522900302154593931638415403053897360991639338981444505632067413713324400450666910310775490988 714142089271625114151620208003922865254440355929166610908462397774402094388921878460954954899537265422570579817090259706517813535668522966751269777836237090832263730790769086029518587769887716106948624933393151882370820067762802892175573576292551225657488423671001469366775658709853505675971132936750975413965559693818714953507525355720870833151134496988886827999802403191333303914652830556249092607032628834923019813147374240059181993142086192934336 -288083902718585928161437473533509813538078906906110733713968438326875702104799617269437637768097747251099874251726685419784521855518186201344203815576612497569556218799149634948748301350584153275058278993631746664615618065581459288414243044766023369379081278907619960498928853316340899327881272320499767700253725156689219045402393880324356865477476508433046841781329647158719845227232272521360235664124339106878653924376754042518765370264665346002432 -64982166753232750818138461545192114309025692924455733464864886406122700429628230669133018223318752110380392235536392813209863420602744375767664942307498990639362158736860228252524108657790999696652880215134881074121925760637758559111925237036782504627709158775665950984064041251045952715217914992299585148482452854640841552682459983546057697020844422077968068696565430201705185733054788103752715833320679898676858980909842850945142300716217580002716 314812649901590310997501178708626551025711855730656908267891219960261007652038821398593722999106070773551557591175900931630175734853419840685127343188325635562079496804020974641556512491830484788692912420343840795905328716089129849032469095287055510011152237286180794653319082274500127497824425847557866975447713652198684781563544886111186052384603436164249247865166497718358993506513149525284391937881963629830331972952150784171266921796433459626768 -454802649467106516997566184849345173037263632414140869955469081342994343635597535836914808589617649695123969920170661962126003003993451414649384313412817004742014266901912221328707859375356489544254831366271119705227296564151861769668851601896017602391819511340889538868547019067015378535540394641254814068484926915220872842560513230041679722774036026093280586546066657009865204170400341298975242957660347518700234347039985472640006905437177615532256 496055199564285715211146192419266732890425309158561355607526228088775026508977468027383225361164885930127969366129901952218827991242635188453345005224057491961839898517017666006683510409360334804572534387764982988471288284880439906024027091353755354063135701054270449013995607813357070751342859946341053420534638537905452907032772211415480553938530196749055394606276608693909653221528483449105864725246112311087700047324099323848683679555365791638784 -460769529523853247045756558274178490135644894851097229737840625838077246446869181320808649758742309791951224955135482119082907452223072510522609344708002260818686302050109955864373454435575756860826999342272595986541568783309700047253025683226362110662200517268288077218269632797255737770379510609805182217873228183218210467657330460044207337376005909895233209669618514962804277904185634403099497006730767137703118558772783556522168565212266626917260 375926517252910977574898723919079250997990668752027098641200703058395669761941822609782754891190785669870086215164831190398986028479888028533021908497624002462260790400729819367959253338969721162271757662755329572428020295580629343551279188179794998604848768971987982501046264722793724877432127767165559215383289116151171029586854531317904690222832230972303689325329225560297159655801829212398558752232927036905901275486842904495564897949420550506032 -267795977142901733801065594825434846633341270915972149640398437845058501854121760469963794064824509531262002833273746855106560189821681541627156966617932860560504922891625049175188489560893059460131648413681584350795175112464134322555061314728717896060131567007389185466214613516721539080615567408645178181807247438288693851393693109170195687249451592449598119185989546269710520851066723452658619753628982251683087133971472003539545478000412169794272 158030811141077918833900106775195815442319247322151056508499231388005745895192235126058063718677302337428668215686062891281449956546073928553646884927143151475234809363315274498271676504299931272557206934239871313504164453268239162414744244414126166827353082372352250313205926008105151187083287038394394392167694804361545954138895708401393168269809002688037742665210295462369891199493501981479795468940276282853426495399873636982035248058094976467448 -61810736806491449780472930946253987958986986292724941080258984647377742749751274479866855574874320617457273440536368126807525957721857128551412449471496565869865105967668806698962730052492068186671937590564097322173377058120527817784485676306852043858010802770014310234488424146596717778800075388372621213431263988304110937178338818408604978361216432156449978485320544460054792326124500048026565246246099701127234977482608223752954674861199712722564 -12295226430098440071300875249496621133291074010838944000630701897645693882254501412927821383837251956083944829486532641224089184423765363809724283161395158050583725511364925635604282987739819006969256073365552371705152172148166826561499009317489930420051737103588708521022959983251962800419105520339908138774672772920796228881924110449042679604089155519987996811031755618977538722755728713988187578701339388054641824652217800198373699828743712907664 61412918354148712594054221958674443768655037668137011789196766940151354426584721695271659168243102311174683884692934144862878773105375286957009202924214572014932590259538516960713949847827809866332649732256396275276844983205515446322228177917750246249814011755762711576767725099240127343248869114496697878549290261651126303209562869988011880018188310610676734832803941498479352565077498775420557369413502847976731129974909301882059988791747690384720 -86965487452361668788296312935387940132818179103411043015261090785028515872216357748387070190507983070643762954801518289275413851534087958832572657272461047888938157795104834809903383191869765811748303008895942830216125419612611705107202293408351889098380554041189358923952788590469498119479018762465916682402251755911736702655168689848059431667342239553469482273601347132279906138376134626039047046866172551731851978171105935614804143192185301309504 93148790940634854329144375632819244084261373331528537183823022601071464991889511075068026153247252205582834930332696491556030309486051852387294534924070477147554100088250066434329407957278337863827247052598952624347782257450763587346170149738374829777473634509827097049885845383026804214702816794850994503557517524250042260391429656613994004494980028525505043343419017073585313209157259480318002157751789841275352038808749395818918362548951667390176 -85462918294151847007481062613430668460140574357469645266919496639145556247295100090665867434379654482374400048649673957492160668502246486942584116967453392564951538199195980226897648298231249628502998103211209319490064583266574215831441560206587920331931140932951647150395591808579004976268685063572746796222922784184876519661253190981396055503285434504244371814994735236728704790397251564556937109693268984320741299666697317721977451807163823240472 69484516185626733927492839019170877192849725837827951332718688270006020396948202877924121073909427628289736545735801831602664669520868057830632674727498129620865244638145401491996674101062249298354187293082442757868771083653718066699443871315690919965759371527821134124279945974999956274181496248597959508326176431640181833402408016032443855333909965210200966496153152510076210636349243848080452331487451656250516660317743717491680581613378230363796 -50041895098961443976047145474383189230748701560229786426597977952740146275622525732148027778291867737330379613290667375300065324846983996838626482410647818722847750860880551330105316681847335888419181435303450873901502982176462585552991412002541143176819448539892905599727838028285193570717647514270761124927500208290046981637885595077236514949018227587894479041657010113450577507542527617848983418573441964464056643171204663602793305357675710834860 30802638398658193287718866616533587109467256614566418199352826177727311173192842206183940431658904724485469826887939362496201345941258942010854368057402132377896265997469421533601293910725411311212713941819768619762963367282207567428697738626127204945418213566076784636552813624484294543585749769652868867614718785685386703146637197059568566279821106696274270492639681292138340522038937655374057105640583982638080851902903801398924052868561340993124 -14176028624652410694327305254096845610382368432473343408184783033433522407449149248609654057278877340036486043586368643436499731849569881728795209558140820044579571012762051628484662075681050084416704143874039211981961842653606700953719671482210663948214872690928515133857521528419325791601560156806943731360594918473552652978237833136690096602438576293704355134838524923871147616305141887659599138380968873136041861185181990499037719399806084299756 1418061160125546402734445631987716013500781626411488904207616609189124122036312057228742240755657594642178225181754687866922458072521648126548824469156709373780008267644798035985296164000307118833951288039637514220819206282636566082598281843995726206392373081763180594775847809097876940906295525764341630001956000313024921107836480661444670137142642807022488300546257414095249732333238075399620158339854137985069315791051884308268227168130142111216 7151293038340357702725486250200204061707323446789762342069261310047674990811598265484012528946221640810971921656851149216385725385229812199998454452922586758589031977832816381369405546129161362369913988919232445147407555920189208212576376634696123747637183036084764752532009781902602748305801401178616273617302302776990920424278329400868586564108277581630064649084801177524938223774159665516678847237964345490767822879535027882002632123905571526564 -11876171297829206390208276938991419946751763570006680263440137807520296432363091870838476873881324624401646155920303321605972743884503462459515640757997302982736102566510574017089307604850874396274243591487600523021007678390152067768698225908627769737209632214421095873091691690271745367697689488443305133874024390032855086516371542079973050329021818474659159519183074236537793640197641372323031155029473064745219506264255049912525636900217102572680 13486351864701184142744919132917943971782517003353684251443699470773117474526448612163409445468956261942079762499501804842260220098353522034945923791435556118347080819923584338359174617986177895011545627151044980522509720780838195773615226549127597350399732320955702008860358219826144146866126226648414410615043935701667672634657440903866835562794141734467063305687218926778229449485559354900990488029026875721582262958412549933917183640143923331148 -12860715026158275844388986634672279687636577837001626321950974556713796516330572332844502540743305908396308316706017684752799510292984357841823325035094627315001088042269704293699862222228878160013665595339174796850817242836708097782619807993846544605391238292640326272168321185419010602323138433561027558417083903879580038581428361184822545562960050117575946919793370263454072822585876508773602680134201271461215542468078917959835616138225513334064 10857770271373941279804540092992146425879207574865858976258885424078661850719446016084859521478971807381275033655848012081482822859551506602267600225755043228675880519222563016023116851274060958547509192491627944176210835804657483894644989031258982971802065582192880223852229332845099011653971055491943667024555143784468011801191688492468104229398643186881883542915658528453940689704242749744160033949419340101174251026187151556977078140432668247836 -8211681981313110092751260116741226119605773665525419247844793307300914922790620124037325593835289483592733563699967476904208551738763547178245304426954545583550923194307941512786421213441944004425745826224949631222804916858226435437828534378144175567028397676527781515687832569056112918304295618344648343778539571230247796970460152715947882534843173098103808747946520234588543148104447504820061417472668732728171804944863305645766966599742590326356 5481644811942482371998294837928656211878968053791734216098258021802626888024683221254029839276289056666991206954172459707361864389073598723878043996521547016172525521349960633187930119665233840999102350164691479749900399012643901139008753274776688735081716758461009601909073867216790875887808858341188988781049752466535892334933804788268027663194893613855531750235268833076594501306022492787544176892719620677290371609491445238724742206540581513512 -3040685886302457068863188322542578616662098194800713890797130590000841900465891952797741768710024256881623247294530778956675544431571558487922376857290631197772674609564707133936775317003306356672423525092439377947547542605242696021170814482485712050202946883045814423561221491677486074607344296021745589047378491418430626934593236393559901351644805331660420875334605832037125871141569502418029180208423877264694701105979589640066824157366933080656 1092192660224260627506021580017317888952618288721460874982326932411451617298779877432720639870259403205777229243380104421542652897025472365714959590050749352738098866439289710732029889477361053847034725946873962519626322948446484064803921356107021074847515206263516555410382516272832166583057621680573141706171838591017627952450721435495084977367222274190703952141799035410784322262599301504781522108970254162537779403290869091716002629231161101772 296041216345087338201396878733651818200339505259364928898013399486350383776293215326422715081068469184121598521751810911912411333100235642256471788179083106256371390329026928604609841574240721682234447826733738507967158175874251646767892801486824200795631767368006062212225631217359242818189718661126547594661811559345359291826199981428634023927560229882087393300440341845115549160276247209155900733653778730224824751677481495414971226552957497932 -1151314331081313301374097651548908702313368951087419319114076001362568668922661934545280907238224063942140434116830392411523883950142986463897608025704094045446157630128210328111958990452174148980621230718572352547241231018635554031933663100823246169446445643570110528497617870261062141947453669471318761339751926846488529439719871333702525025853660748382445878700618315050527674592610386437344846109104781352909172933680844023839415488324459699176 1558032240573414156019772405906800389522864619600568977290585233085552498032212354300026235779767379292185853413520600029777316556568383266605579871341095185933920966845444951666284750438341274082933505522929056809335454624551906466597913366639608619739969546961943267477806493569910759879094827058689062908165854982808103592578157338558919913134753126479379757229826018527207468573100715446618647175779300392508590067785147114551363692744689305312 -1626568880089319974041020284679390347750546706985579196741321696961394173865525293754168213469625703713591945741067116910992762649454587994177875871578829380945248556448397906431161760520570136654420254080203604069206473869450358681972370168391823051481541018796016058126198680357268079667146599539282641996061265952748207615422965668224113803716074160420462917352322393939332500948542318390517325167407311373894610514573187220093503687244862857984 1470157317047081317790151141024193977934211269165482379967579733874595141178653258814536595021097896262305351990543735051332198978584417344353161263874925204203373168798096895214236079419019396167757513318233234382052973660650497155112126326697746348097181972369753827409935924171951772724532013346594821121776804259808913035906599154190318225857149481812710894374154914951330173554056617896318923107004930772338223153100135755155088793494466247944 -1189562772778514162428895159743032468573020404539959981230868902909953937695170918756957031262830218446095941992699634329202596581277308377109576296101481773712885263540105380201784475045471585822986570898203868062930147763411642329330695874666904261549942354113717847630374118997111676141925516627581571487952945877907626380881086802940009982135482139620758276084184796135574445545382462206057620440943570284857253739564289349554445844821479257736 864688411510068691369745944203510983534070723780886437326942690710351802448546087088270301613175439711717248255066324423549380740318590545899275182244377466617852070811284523998788663078236945745033904901090091051171086158682408185475094581673781184471728731424207143968891052328275964004669119406453689334964445125585686802490410139742521368159597405602789471324471349359906459355170177963114436448897620619717990058430790751748374122393019240652 -551932159794037305805779220521012345437521486008403617151019669239820618276457946723326505593362126682839636762683553419266895316597663973745221445969366008087224414617684539181823000348747299576203329755584064379498696794207061314187194655083746088681944167414555721629655323476615480875835489785957577593607565229250606767620693694747059891872282473413572786796831218770558375790613472566631656009756497174347994959601711439339423942399176298204 285646425593529006897788905470208673833455887800830045511051423860039981560995508556009957224937782477701229948151300092651696008848660280606832077030975349530225987151793413945252862404545221743985591451221302138209086345172233148787384084209867128434912732177861534150846485293283920273832781538929582641656121599210903113266302188550942293188441704716241105050148971811165321922199804915138152595605389813769914329275577793893101384994157836300 -81896189048864116407781910939150247042113303821395371344042842027913479111242876934489196658133006586000279439924704404573816312169813981704626217749473930203440517913407161992179508875496319860194292602465494004426845848190353688981577593025817725003725040165586684106583247909422098530365980699325171170382916890936469118960605096659298705510672153779866703011404856541406852131192177769775869208238682702893256635217241241775526816091402561004 -56898952548852370994635157743886708368963827833779002023460026608395585347867233256745654389427700595213474699481041172570261182718753779890966485308964912997565586066010054320933432320597944186384625243408735848687559808627735860453204503379919348194016199615246808437200719292048129770605881500869693268787490655088897233360412154320931107404976303091145541575075967093567684684504774703470327000332009510501089779922121771817467299774180419440 137330931076241698219471626381099012455828077053146518654147116144047502104599312845049446810008164779796386148309787452045411799342906557420942148790797329344957894457213816286746989763290903822944550921228139477169702960937887690010241646196459191696105249809963726685768943975342965928581506384676558537261285535889007616757974862999755693336221376923331902300130167746527657679996638402658217279810800539489593198918385700716928018472321099044 -170903244489191228754714108119097839380750336502330878934411308769344973828941674332710772174353026932424162076481278193064483629195577092923168474029306298332294587552880098996082725102796905795039589913153922367496771160618227211042457879855743656219461876320196512659494641472043633012684461303217365815639566127499978807916659755691154100496078254174905151802224305193918124730107396777018972935495532649900143046348988643988736682178592955016 170774034037153811455594917319462649976745657777566492000937197504967253244123754519867444204434332655863083621253795859240166407580380460973886853262349535449857720189664091410319206374594021710969831544788304229702804006665612140967549072849466580229660870190606788627539086959476297341459858293432819566855966742307977008496399256283011107453716807434735416062827826577270737796672717209633974582447470632841558649322459211452986811133698699420 -149473196074933333556561771095800318303160469766663237584110944510168788442423198608125875546096762865533699734070217631974050592150857827660571028928301936972444341363203517060692938210628884676517410948407165282173067791209330539734594379293189051458712225498964546725033029933307787582026466316528389485919331586027314272667307974353290647099968384729169965476425674136569845297944244956216457896029986111282193988053407627205212878751887956448 117547278062194150270374535119080896722797802333725917590349370418108029986454451305989754354692620177539160224454771413970810760950541718969361827970705321704771776284745207581666840729025138719184720504883486057130861005413539847627265557868322680606883714469028971074296298441401271338332927629184842159313012444961309636603419487274152264319835695363174873973221333800543827877232005235461374678773509861139871596624801168814344482847863934244 -82965002599962548096144577449637664348859911622606133484984142966544616180258745709096673919684732742268320592405856627226145341221923775901969922181821804910552144864679087099648685772997312520988001182903124551442149295429048280594696684245177467601154376925900231181763421637379903915829688088972673225297137264660975398729180379912141699226277538592973156234946442287777303968423599754838887081217472840621899234350614108704011571566301756424 51067978384192319965198952395870283259180134117047205648294920836851533998616272205246532934696106340794090392599080639512447984846442531945725481493947622397657186078870995481605114357635287612349088504166412398855860410782844056905800229439668282855423997545544647636492689471640871943433819280967040867602449027425506988630265704742453009983773681898643382965883269649865503573241242083878083635757324305444112323054457059897426428858006167184 -24864867179277034535184782095180789328595585191011137836267302910209118389768388007651311808953725218611565573135873297121658042499651335959466894665370473904513404230202630912040531456366726325219705804535783262627879353834021348888545056232393136256149372317645104381381193436439571714173532350158106641065376465719287973510285274659763697735960128380858004552530217282755196142025773690059012313913021223909877781521417257134678161340753867124 5512688671514839107598134252025368753093671846843925627930199303279467678204079905642691274526540892034137831602763209398915186099193420366792227513790988927825527488924217935429242527673326916918998784277240144192400889634656056961150531257049535503229723451726414509007649347848509953443436366822787290242186254391157353332411455569621653678318577704141143799560992407206248223919001542665160361677216716918379246851714484570084816537088753416 7139162698296857471238598782715958662727360594708088731594460564972950539376738604318382125570920624223149805310144025878790621789419743165245202637176312402627887008452855867621323991244023713934028102842836836845699142534560506525244990909950675648269146064835710780167259351223441448706647989179722548527597787589181298134525041969237581413546895581463942165468721233213031331098903006560110413388118251900942510098897560583096906281966290192 -14038101207929201753716882640917133037409017770625278242241768981619599568837556322671407344398457672295750299956359967562355909820323014593561002851239762489386785939166768357050472456221124210272388957971104778658348546213328403302351799394232437085997597331388803556109451073879697608920070550062250041079854461556829288768352224721220325400470281216037909097944532870222086475986663619572038829038173567446879951842239326457212167437701148172 16505989449022995196604483486260469236179826312661881724185758197623739852197548205244267261443279349595847001402653540779693848999530036959728240030906455673431292439202853800843080222461572758070927659070413601990325879419766183877807089297106661071875028913293873857965706358649083680944713858541039190877597762527128016511981584854449188895584951801979583879347707787166892835225723548651931244092672043005622884216790541380897996552231671252 -15927655509231474233274674233159472502009358942300368412897585487772133324387841977188644400979512573909913918580074665350588287131133941188448397653295156219703211748754905959825841788072006894690393597774167062487112664113400428589941272824651688345857104629548196415911144461758245093988782869163990294977406310707338686207895102153236561788840334061668410717904295794891267947807432943484756522496734990070446445741821621151195512196649683360 13549721629942766596292331504694893208101749570516755159594141408831679309030639346326315471531400270651241045776661510684645722004263729292184505536396389959646763354808962079903971417650353487051652990232911647468897456735010466931163774479683917782265488468894563402252876423196731970629693765273135501594348456647570622040111599211262563556598628989994057062142613312536799639046955807884935020812431473091381288877748533075647764310578103452 -10372562667375839443014775536841256181981107704302707633990995880173684587158974996472404964242810040486055631697183945634422910539796240926425492441583650212402219208261537852309541209716394220967480887371878786477077912715507625554902215315596196345364336693562467673534930402581238765606106522721783516383593909468193353329479267982642145602988066707146426052667498988693715044039440141243408198033705626628211738191159744888722648356119639848 7114204117839394967911677635327855261593104366258070425158183780031246110943583338055437215761687120952615367756307422494537893332501278349969493477851539894795602953614101234975403974905211495314652758350713126548429463972179253755557821891759519482697682104520828514960236708825038670544185036162106106686560112097924067320317103747857022833863082761495336194934529375046257422354167151450153372556825645295848575169286540332687777567886329440 -4225249222489256732799747408616192758991542309921876201589119603122853492505727159476701731206162172083874805913545120207596736108906260500312521897016819837898730452001628793460444172708860432965431080911660958254017613880367868002627016578756380713993310081951849359370167828537625784254246454205437579662397358708137760537125947510312679151269310979395907010011361490872764298336788003128296838329583014966578090012374144524499342236339792644 1933383617039537861004779897292686721205411549216391387522752722140848443859192860802912702235271990925234374369128567813748105733163822268770836175607740912691496481472814394538393965855298328518550767595851030742294599325130491140766758570092069845201712419907044515439862679280207644271769020477214636942982477111735368741428828726047163415221890637948747326720393933200433093752679060938738655739548607998669042726301020342237985393328383960 -299961733169893808774223422748371846694487969699948221061455520614754617894155621427716866567932322664812804264538637249437105584621983963562358043782396250232489867060720887687601246178616512667554395510676419249258547860552822495294330685352075451184980154281641302999647246339527921325958655849398912855885309370001888042632614945042569551932686805425433596645513488075983231636692112397573702865336205767076540983886846027717731376062250732 -723262239963760892712037402564067695611099845531467602562299176171182883033791951433676123201058891564834169426813463131607025634712896618176780651229139259919463128521222837886924619619653579164840724093810142163839150445280424312017371980958403332378955031688634762398332694403835860003200168255232379774534792933064507986923041329918737796130118037059243903062305182127688998463554239771417976004744130800947344944829747188095606722205725508 1245082279424686245140797748590673503299432438097089335415899994781190557860620821847119300709638970883850735413378946461408606572166720792947909286859964395254348718272029912155643969300725063774139122406973559948922182568282803763705120880937216731971065132271980393681700528199103388103219045383505684633511974225696245601570189470906231709652846879116058730728528120794107424887665230321238333195918852864917198601127116331118644156578820036 -1396960705264515870918871530379740648475635741259332976997771166137204838922897503143087290099370866124663860120734339693561129588708685532730947775456831236795633306887319315845830134133623469041292263182468126751492004944265083022649067446221721783618327725058184545922531497715148712622066266146864286748837997604178128184096829363097160277678238587782441689408070707218089217565474959119503230387471360587751861851850666011871460843755525124 1306760453345525854539197545577991244497310544540868349443606520222054173950378108611260148825857800344420680770808225808465244967269318258861795714114538780580299542292556728581863577059859120715681448870494825790015170851086761576573891889316625160264215718066289708793775202556175807528938626943032572740265793469291880311256173383928101352643433291578301412691475053078436178783262789020872768820098389866182540846415996523557882380924848396 -1083232902528259579830317977811383948696983706298552265391560875800994910481909718300633244276857626485485036573021424414633293240337373107235872650501631381582149939236809524254988949077352704897195415521517545040141544101063892318618469318226222214133061043319152656412896361412455069292091257588717995959707851828374249343216322828156222076469656825852952606829410660225327950120971426577711280813793424463243965509130205334736256389373016776 809228235511028819081705703587484804044057347022885185898074579325731221207876090801633765171923953773234993520123020532219096925835295953101641793603682688162452367113783829510910022069150482522916025031519743783280945627463824954037731132577313741604909651773222464888033292357606918830285077041154511822794535412105022857531651203134363897137001420584134322703227370685303949162286125465609077982015144675436560979681835191606444096768367732 -541026983062224281627813021107620418471292671159668431799839041214613259161606480313814184391599611555615208822543185230748929899574394833585715258727576109702634694324236716279289329389860581338970353919773987845811649853920106650173540824578351952256394759804407223860558316632262313589483646614569175708215829106352305227488542490213895260045035453047240632554185436888235952256490558463991061719101397041545127552472052143632304675744158564 311491521260220844114214131942700390775356582511821310890058229375556095993003619289214891476070598899832146692879533982392443391178176228531659755688565954387606366228454801130319614239150310092761264843024717480326411744871169867462136288566692694899494943701951595932894567969356958276928730689830793134703930696057404418983423059880263270334478065854625988736465545514508843130927637382677591951367641371832149140727215741092235895012964604 -135105486345489284939493559917985671745051547308922387695411769824392238607264738113502050915905679343142136591466807907611049129549706912808741475950071714772197681917859868590848644373945313737923127340934374411852452470903774766656731028191298984324243392540926107007311887211142808115315862122972568091978928625612935439589487875799379515548932700440383395464762742926999494634180129130348755872390779829128550505761848201402660753402314008 13437181847724874404245572979694992954968788791430877873241753263665333980764922272448553838927678129028143752717722872490094996289400862670057521770861229984717794593610793780113320119256866304465203674077991952946696962852523354346204006017589798997918558987332704960492689156456965374252119162214141045857529265168461955231349184247320818362417342925350067244438131779119938493260640348729673948994306238897127685104612531029309716742681856 59854555640818787145467572215843246126166711587101978797559389219014104355830148059911991224644499329906371221500958381290339927725143599325849730867703716007225068954316714655268653244817703094924339824673298292541644017553790295398536149624706427573262350051917408045018415488807027309645404930818329346441882801462348306882416112540634392085105231976766075871844004550169918504925243458823590007564550284248724303557669087682605641941585168 -94955421123585755719582060904397481236462818955433296127667227399975565804033625514471424584786295721828809697193707458934370464409267476606561101757308888121252462611387960251499458679332094276939538756747701845184207907230248701245033004506508285763652163150204832232317279155881648206252324648899731426589537105563463598123846617728544410088394828197129718144261941276588671296396810603333750356262877709821244666296754325688940490113517016 102963206357986161058213535226328182900214903114431201689833081421063033217674856559028487081281478170023284502338262954887171328713024526195927311759068699878519719799889980245024373490930032313495528820100215494715628794810224030254982581425711999514933701941698122277556632950497868127056457177926467594427457802261964805066373265928056233467286058839953779217891461083616834980683110302964715201264556571081730950052510401215917037992552748 -94027050895695789376643664809027355599778407102150999166022790462835562552805486858127710612091948834362650422732690323982630180149238398946429253043306411308342606395313999746136292146895809777237692094148141657468051286401635474712703116457096992551700595731729572248397621685996961355715322917727361334043744677195476805973983353790118231684775113055462983184570251799777664270729194775691446344463298811039257715156187239569238959993242460 76371443305261707451184941575115971356577505177900829336013089828407630645669939278616505483809871694753512227761367506922218437153772974651873881144158570164579868800941143624740081260663069406193742801826073446832662649253723063058315323878069850484778305579254138516380409229052830113881106387363775121732442680850510160674740851519789712008281476208682092329484825440377580278262921404179378511648899450852282098705409714005382386588652580 -55981709446135093323946288157881003063746321311044931783070085214875028937694137615069893051152760705891484757861702307680181462432004103043307687031314800209459283322871657034143240825450645167963779326541306274324470214945755463179035233315684431529490841647352472486360792877639067226964185753108181200637561102940673696145073944142800508741988019338103664738168928507450517562702103836044146388390838144119543721371137117989531414923532084 36723353217809243578379332125872656647141325622754423521379284572458628607326412066289666753678727167460443587483794214153534334371487416771455516643689856101608349809448645320700999791298630396330486508039063876292202547388458308068058350642654173895941001050076318452865112360497361973436457779867800122379279838590247218910704895741679628334496555840161714352679862469116912315321892565706333250991739549916287768330904441763240658988780216 -20698308212756769904836214246143028082844601950928112509774560499580907768087598010100783609635438210108628429476255687494344612893146989459770221486905073082733911471584930384521524881483036041297357221774796914920007164952015545370259085736649740169112283975726826984896387738115186106747069074695699380828555018989114356649481392174710879740798675921094727782993049459333514927298301194203631577177352754167633764658794843510489685904633956 8693443752314298534070853148930823568432143958378330101757451606287916870296965159355946197905038931443911200364387572618476297086367703309367996661301654153490068117097217885767076832031097143301880436935344102217332161513731566746922635104597426089174950173797249380426450904654596828056977220869378041415779585533417485550734675197081094350735055297019821864750112569338219439270670927278951065592438422535135940669864870644908969237768880 -623275754612906008111176432414605100579681991157917963790467762561213976476255863441499066090771382802853130716909596870072575828525578690935344579666562358268601695079249691767787723469977201883629370480688289910589110873221655477795603784484377535809674497956103050352986667582484120451291077232213096832353879214963313541927417488806606864448295683186449031287045720337327718913445812826858851698857322002453966044719297602614686601588212 -4092982956491333356481985303947539418705400339408120429064559761059496414333817299711972931505333177861905186225477054508450948861976852575501188888103355531314384036855934536980938314198465172708873909738446534460530903237244647051981287956285073755992159203339889811021888691947518500875688820899708809864480167278137600120011196145713559913988884841865950741111856933172546164719961058249228746341423484166803441497982260440826259823286384 6244692953828377800409218813498794427099131529604062905458215480086657137351890050979293854523317871761041959010034957374482339155011216357108600758977034320263558583033902911292767894508810199315750504817296456466070338715969286107176681023868515448723533070011062592076834963023676916063990332880502521076537097448030231809035133674443160300294340709036342601533979491646593393853101250933820856699739434412111605551027576544259551415624924 -6634195843549746859866170914428728653619641289506599056462288883355299965903334368351525347422861425928018224948217356979466628139384076710464774051455419142266060904886104308703516178000127003286218120358337506292408468516816183172520493571774416230772438724562735057341699370026757945418293514775936427593508068582140453480489121142009001666042986675791527063829717508462605883917955109243168913974778144942575608120462242195998346315740896 5961923511752220586107699361113015071588285861945358740708930445143739003732407838401956702326542457209817881754726746065328676174560417163941696790563933717204012345280822518762603251023149361647359870839511042375649845979928073923614221751263766320989954109381264174041035338669103233519683422497520301680209983996506486071668263519743838795058928545554140617575657569829462865908865909631676876200137054298197648445996233031718679691679080 -4774277294883861642032314774357741965678954509527412412289950952938161713298663406693106024772559744568515052241925251174802361214133019619569868068456597377694128486266040721218130592816562231132658871527637867475358493427173924565017908802308152898223725790802114772579585756369842127920640439530243873372477263102349859217228377982582936532533014627783642329243476434781811014330899013139628847735923383102390793492011546115385266299132640 3454254334919566658632712282486426886215107888968070016414908144202154932680566656951786099198564326899548562258687255001948436656668411483614699222630849240122024211822559007165829852168397716589465858348591207680576086009503861960777165726216524310076772438112955391159500109373768799273198146577543350617948556651045062509185954500380013556969206541228870011017668333981555490802757355695511757089348304881168276801711076451622978809071328 -2238523054925686003080819446021191524581872540431087680521141791110129019533262886309826884243861331422103211815313546864746339868644781323533965842346416041931551935895862348932161071294956303884385956568191063123433555060705564980889969613106717326123025021368334489254757303126095419258464331930694742319192153482870638138110145108678805663489450261359537708348646251593808248378056363528035421123174348949124768053969235715903138180748596 1247680945230237773932092202377043983695156066022712690256517265303118209013869732613795752078444198798669934347402444182665959277126999163837472463014120137795590709890118649381312988191091847305212950522330828386151880416065620333110251059521629393178988410855493160129700412848821847542375168727877269999049784692818157075411390241340985187457133464452884209516976957279217733014022244584929336491736091907718582219994944918477398594476480 -519475750321086398821555457985691298641914107299756334605585966882993707468141806194337718547101635549825801239106844678610418924634779755179381725589371202720996426613542874864130033058717293825646763241107844667208943587385305135202239306621081177109536285998547898371025106442913502039146706743052774383024450609417645244569156866619429004583818617591715071687029400419718719191953274416910039737076145802265686830449002301436568910171932 39231731047350526112211261769261982870745757188922740179430413880500834788033206199222417698384300028721888594977334119879421030208702461467319798814946580696975382071141669115794645767867125599092038133869203459853663913633093083183401393053870164965892075124253264415330479536792388412201183900524885259994772931733891400969478038880000002042526339612397805775917415850155544900626712912085149104727839423627549128293696498846566034542756 235432672288242582831720528668461034608048465356565137343368198643995843152429542579808605375258587447787587305345041384051538816480858388563031606202301447404585674702667335224783586554784384258202949455262562856467260769863220691791678464828730123216700447628199721910013332185029328211988777431308278663056769953541808452097328596749265528430784888435538996645945158680194214343880014640940236513748147898325695098676194358844778904663524 -356781114376446345036739195853562488049437100386608354659335848995070737669676761863086539546178484757194980023074394892466138419155664184713738610396837293818432162443005134401744226288441440380648395352933843191395412717126475958063928263990246410686765656790331960505736305560713338870730710438008914229740212448186876646965115874835226024237235694683523491319044180847937544807806975073692847776839158006798092459524947032009791956181028 375462581514890616663776883495769949873467613832448891997752420429808571092852635930909465442035843215429283515139396884829954944549707827732226666374303830052553905110023348610291368633776713941223533630308402175520538273860979615377311639871375183744699419493025800929684111312789407881291895793768474447779062263359458814861685789000467164937644949467897824357215007214413479561089840226194134254825215278742505534122686050618896620119252 -334142851765464821050648251839736195012393869363472708860055058597699144579532133318913925525201155445098171486080358450003688693270640676085502444055422426787395878823881190189301272515892734344075700949248542803516980761982403650382475879554979442310044257625416616384412342466652285217519921744314580605586669751435266778017007441941722180869032434072408713217856283908925699752576065554278457815067190500551987694803363341946036766499640 265053689066959080682961390177048709938406712883593496310096150934585876363001550794117108018212237159403170584635664521537360855702867552539727235235440890103905672494778365364741356684103116694367476110669198871372536504774947082456036262004702802227855447707763037397506527058791057516096327501325249429124034515045702662831234360609714014660185838508817032880643227678576634241125072716717969106681984052464304720467010805720250547317928 -190090586306910834815439390639907783084939993491988391246619832547227355610206361090787259353002748569459495304699950806163793444503364583531795946070863642305520039855252646286574453003779894909203165618768276610599164340581061618163563800546178505891404498646125214571523894043925687671076689702285083222899654738381185083240218361502888148523817973365214944381675827780150789379487553909735302310289958739919029330194186883689595002769744 122288680789747044857117036173586265542814014756866920465906505935769611513781432743013739432216651851726695834410319539649655743101867774541078038358364574243882161039137917846575062209607456108161500129855787903804633850317569211015441698724450192725783172034296895845380109420770388417145223328990272929972502429868585696751271377858092375202822625286467457606379895719181437112494994228076070163906701368692679980865489811729106761260120 -67902510944451131712520145046587326670472098811918371914050074134091164589683345263746208130588912168130640872671861050697390659673632805898203286975679463664635050673410251785038323247106159159429906405811103472981488438163067079188107334783444616990480526246991305819460723039946717460515250936827972482670746409570395960952302348691562246733111421769849498128143905911727162460338108898813236112837800177075282334276262810784900191555196 28530615717206130367791240752059435976229494450877163917811331866668696025035523772744794619784917113549542173450537440309564156263239408520479666745650308262767637175931376896840003650594752069902938296575748132636006860169686545966546423175601091369269373760171185869212204086688059535972471645813893827443733340882042280395522571592888892769681457383749793310002066140984539102759939265628143372976299987650036364307256290447379662877680 -2949674393138599591492796505383587769421732409734775546822040660997169463293507480988716360293619400630553225446191516436946764938375534192421143837677322482856045721406265269075538688137078970094602034159513829818424881614543929675009532092689377372764344148798836476499321076006259963011825156089015037796774051717106472308042910010593731160913205475817568907137299711348982367461239400477948537178375869605690285694694664360964669334916 -11458630933581578008497384532984096965992155566033074255709750914789612510712160362619737936579311589259550342837909805678662833084219948816033791397788244437817684334874849756505434613310503557129068662735076057423160361419035069783471831009916090417638276186185632554292216447176437027611284832561216688441335723760465643938615193846074274201417496428470146699345344674665787827449657287126207419523254140878717890520406590392832467185648 17711354829720071970366010069494369751013107081388672540029180232618232480257598951908026630495256256059844161828983484788024382114184752986961435387695479999895701034154668897799936569157171853623034726272381105095541099235731995297716191202945838161030448122593952468275584722896858744975598999902277653339756211342880087215737267342534276775888586991810360567282638964365045144456093913824911968126698485267019754778751133171510467879928 -18619610855033358403535561521076345237680275969778958755106829194380050495179576764652551079842849554559580015132676230727175363202428124808999205968879624842626854352550917606833178082566245378467494106393924687664093432443070908377999224436067320430695146314117720007972077552803117214052978507109985050889843301950318499023554340993940129415223162609862643018102980088716509422666312583354735580727094544427930297411620376731626324436056 16483436313345457785599546295890475526305383487063433451607734341296017379204166263359797104967211634885987615851897350499901452425671719240604501096268299104613881944159557819587906682788806984386792993401546354315077797883754813962873407539176797489827339518917065687786348491629056782271072169949246251285467792650609645608580626672365695443139876634763414365993073424752687759270040155954414074519571289775466348026224671838312862272392 -12993572461607173150931573538270214435452853146481065112692551270916689938116667771684525242857944402983808592081712349658988431421003195546207357395474128739874941715898604203053918800674361099028687656774780973313537995144298162998381647047801719700296691944261299227202799760852207595774790332317625208715571802782993898489615735900758352905980013387827772172611281129800719668753065291365767607568645015940503778778525264507781533106832 9265117712042370273423677862969614304326214181679381719689723684384142191012817993075414762739605883763424782145485571826368800343091453470710184892709843218759247650548169632353107225686175940750899203368831004258395076907580418861613986200904661468643108846209060818220184213871544512927844678968689234895099522550232456644554774421416869589552632723616257757098975688320351388521791709898964070351998070897091345080157355467917605763096 -5939159403137267524233606619006640143092826418637377621104359385420900637969454993575813965700576284457109317452589306464037896415112356944665297151298654254964065772343390640244498444892543375211914590385093666267536304733055664567104610381649464648430456800979461414412783415791947087794315454254138809109353679461797239015626136702056342249607766974399583739771335865389080301414110049685418979324133448769538974448960620660992852281048 3305934695584379502688814716055389113847537907581210564941434514557352122688658840116696377092148778244851754065767923303352162843678582174097210877649380735635792750050086370323863570603078913085382189384805131722928907824760459800068600140142600913309808284266557124734199802317064628215588630852618055993818579333168651861040386711864043128231208010283197053148996891379080439711613237219948217292377367272801530399028715562862988688744 -1422921202309875325007751643497855900321502880600298049829621239413327039672487118737207134451214504319869069609787530169895296285288639228969876249732589156042451827626423079835307894463320414684109976974017325436176984141449715523948297984819479669701638884509952422286331587373317596521323952443747026020498886108521061305011759203916327245653542407988907696412397236315715531718039391210192918599580056588432996156833230452975698772208 213293738601084446203242264158737392648937263417250902406142074048533345015374408168694693244193468948612841940392182340190714507823392686129855065562136817562465461887793941773873339954932673094937359505336707976063258339822977426912341932249699371239002077944273288926423854412693619806273985421566691259643562951690975802359472004022318973376104688090533807742296486595529226194190160337880275981733053009949532693663806089012515163216 461437423416262788455458278996567527096347269362322253259895233364106277801932206257578548923721073667976856782171836949192908513824457096836063105215871321458886238419219986146498735671916984962383068432291694845950746356819791500641915301545178017743542286592926704526316622884011893409499567474828451307745814550041502639075832830450128010877631334819535034069730469712514258812117268193844884057089335636340886162344687460211033311448 -753155444801544468358220308776674539705847298557696528791261880969366434927557349999559555417125326224353902688147833599558255622003366696921277581238736694215463620483806372081184276283004091629938830104209198494143786084991325043332532929214076910606914679104944087168281704559742639336622305818524071274093791697890253311962369614196285948804303266737182815555688456197584709294770536295157830814320945724249315210599639032637881012224 798739013337233657899783445225354064452862807656968743473923709980760925364390867922792008262468627801997510222638099307341759101349262162672828715849136059194620447266630850151176816888901024691427876350471989475567730220501758138678544052204923301284094641055481845873093603080114376354277392666940742098670878172469392268600893686999289267875443510017971311818407534205867435252138944034324205566388873480797749199777166722003804525792 -707014367202953700626485603009536319292499238033464093810832616252645413785674325831238070452502639555453924167563544421657283753906040566328352437298456651878909285377674517238062559635984206365327575976286759570656391305997345421605284607910564227127303577732080360884635512678457460027608768875252461375684538552906037109418347467846787882877775760728645758470589574913916751007028650610362497951242257274849377977250650669485168881744 555981700342703021297849457072500702877648561141051141799972903303633833014724864190934956970998401970297630610160165210858569982022932268839544960050071470490180732093885791200040413463558967766998785751275971188428957403085398735781378629558767221450216241884267795756182574350585472970444580451932792431674475071220935313709703713380702678661537045608548211775137540441777893945547282642826710152841174501871092494130383640611565070640 -395718921624568505005103413303667328960677577941331639936864791769021498311531131185343957911268918740987751833056628193546712953970284854144344711634691428734521224754445121935506454849763699383571018342279293301586283706741262052544131749058713322428026139825594355256575065935657859019512794818784122486512042614325795671748747167740565899246481094550679706560314126176395707716705969488307786382467127477792014434216148272984884313440 254050669116191122618290058769580214771696307680469330011010285551853463816548426079770879440044824652092429906993824271058841340380821328744991751388580489073943083132945733789783852215370814840929201356419117619178261017236722435330988035212449695735324919046179259480635971907159508929436620828910099960867466040852195458451425788796244424737868853180983079853733697772796551838545410007767364871688261089384232510415841916929172521616 -142938406104554161447727693309973651682253099143308646848535559843658086504925708651562873731225081879156289674080735739877532325659774744263429086677837983799010286284220532468678449889243297057003928589797343418286787229414846411326242104286852352877338519815606506237625489739625450757267154285557395486807538971842283394987280322070697545879822914275763034116382365850602141658214200064447212721640556604777177543508421316175419061184 64172635387051909035250209487097787770607788288509886043342594861255146098283346480660442249169033366671098185012842192638431596813167520308033936578688758224582328405113934104170879844846875828688276516586938615001927140772347772944302404349855372503937907911424861620332469668056400442438325622721921334135966565812521193242405575114180441458713753866471076191691428924021897229124961714153116988022288062004591998549328400453317754672 -13891146765833055688454776225262370637810758736311766736194266886062301567969193608007648582480121124412477882865218796874764177991229834198002221854186125575934957536179734096898864087159841392293403301408182918668462853956204245778381663603294098765905332900651785466784612309681613576041219272729889122040807873003253489931392244671351565471040385893584645387700921057855800689939918800235157286472090597816616217700865105317782449920 -14145719971081905966334131191855926394790824607460473817067697006745399798835618827847334615408768290974669614090286271683970318472026681273624549618506755863643812493232368927516120407382980462491319035429681148441193312117983674978723478368920820169744497554288692398838600054715828175163615558956880761447227502553756151816588886035978954888723166367019272921587847266886668431272038956035016327830439293866725406219727806110265119440 26492654359897032410472523599550424429225466101051700999439578277471000114079847447030990946981122909915841342990303242165911725902382885138708847869045163834631454896389615253857021633793385713052229602049759991684208295273017228169563475010045056798773312920998549416773760841912156393735387231735939583987936452657984738457230066696731622275998793564784808434219128289867547125388251973993634282910045162692614165061620128885895199400 -28901510291281430615967603363733888186956705027282626186066676661117930892557185079374568615033652776729183228583949604076044998954895910230949826448495759889063132363917075741159898436122173342309051961943215679347214229022082567005610990247995777580266850592181116059641780264337191598267887767258693585386868370093408309051009391187777167860664604077206452080619584633479885021646010911750416415530070605067420595692503573750162744280 25836506375519726848014158181760128153135008090531698568484108606736747288246921904963063473397621742345177439407229842325562972547454302631952152987894363782601308429981350869733160959371656056449989263399347334189667913145062476808529030495939307905001975276172848696254145065910064843306864931724891703556389382466346757385234433393193810452114119444648134774541415631602545693420874649144487426528035784383041928403264223856119669688 -20419472310154703707577422839273191129283587000884948908463148676458318585560088926231417280249711921258585502612755122847008706214477298910410790095466594374949677008309845756385624244351513526940488179904131423868448753367618889296330387077671742656233978975991033576791718130786047787359737766827024595148013765379742364084520832751800664428960291213461148541199920172506819849756623281908553349522695080420852872669657655232974131808 14612545400366155884758936180966825248606734802098564235384962798513118554969955473980947263029745724406392298450754017725247588248645848984879846296699756597371419780304707642076047125706374997804143413634362626744953241947061355993494276475598743476842182804946610477144714163329326108345085372303352384722851261757780057260634679599668104445911153650244368412813796629439423484443511641210409528978190385380787979562681102785899257696 -9480909557835117998464173771623880134003137061949706798419335583379340794845616552850873475285757020384468590104952455980846806625238873145245627112442444010158366328628945714357756838833123076897421043745090624157946716062421960558376915166830910677406940323187779332394057928236980817858061845448122492367069739917797905911138034315779693381021875584486299046442662066789481335882720865331186724449513241368546272727729301577734621184 5465062413558303999221218648990504604695909674872399043998545742138036112942032046284534829671194618807891543331529140742699855712597357774441925697238915351400349864493980670992921748777188052558006009693830307723481504227947182502536529573195192716778577757492471078344692247067565346219434097756273571614409374243384191347506229707357984749314027554973319164807187389170471623640829708541816973659347701365293276160041548714099604816 -2620894088163268755933101344811076916595575767342749903101380007992145918983586360631967093026616336949475014964726284879432782746472353825421338866658271367304205052447028477396742922468770038036106753257202964644366472706592255602474142179626289494506929024749423485158108197567834379806025072263680780397039516911252591792421826755631677270710947717585715655187982652726348387010841634296853472332235562644286377498022103900517176248 799136898709734381202515511593236481142038630337316449864747238509962269101259379935838019735188796256857270418594988046763360608394812133969777533506291648675899068917223635646515852330288875418079954101126184162533627710191387907283303680046743427453045138372853085968463752103089312739311799824407983395029173929906290514234468514313262049377864707931269174821433617142145053402924075092629399225445969839658314736937050067581686184 232249289984761799699957802426242869195280371970076002843415886615142983271511900371861479421733541947981916680823561108912585297639399777323584139239516596477327515503242705770980125087064314697742729719830012150192781604364760026299785826338460282368879082887462502985109131507241554049833559491636515726011944294508139494945292300112500496700317345132892123050607994491558509787002103126915236493189383696133204004693669175483146872 -710851012651038467547677684969799593319903466937113329314768846411445035100969276444674540420582709908117140327571152417785884309719920523254357421482726354878903102331534510700273332439926247074661309604946112730544227125565992672623545868466773855048115740999072669802735176150827494451269545570212615586217142178196549564931120842623607919100428376476856442066692857094747525013113522952763090851146689381597899636483143028187674648 840348218908437394811806500342941073271522794195312477456936133257917883518627093228830217034946672947352494395140076221507150442505319928491842715162313575387808932857589848583081544048069054198527985216287338810137082816340222524792996074345296360950839625449375777116270471287076322473913703494183090921594557752969683398871053070178019709341095209937026360100269955709977504311864743516699311876642832617292491298381888906768934088 -776505397178390588865453319830191130373645885261178763857584181571833275616385616813969668224256286794626545276720293952983786250653896110251469789605203832967666806411640882004254805633827058749925926359337436615291623877841055507092300243460833020518848028926491801143706774623212368700749168977908155904950518659602069144848379604137545215438093835863639161232653404316674761144494544823444503676073833088129498936999674542000604640 626738928424440149186658511289043544042199119128600285314336784806321641828239410184026428340919017529650437229487917608614861306514123872581350351553732686821013492404532031278944125630668474383073238875070685869697502548319531199579130219717402936275999631680695621847194985163827605822855720665337057440649237441968091609096690609749247963123420303287391373734621560345525442825951630557716459370618831362740703851385853933372643026 -457494691240445358894228206136475706825469146582041408471224402098529830732644851778028458237882554198842835691432176021225045724669955070413725075131741994564231282902661233194056423272832900077689082851441806055439833709104951880593864394524590800205539415942372418196761194546121538416075476066622425179946502769959032096912653866415899026782339945816364493741626577337116528185154858822714945019762119702417020871945043500482553616 304733087682650121948325375759685126103405993218359625647861678084662129103656680310076631559200817024476672027002015070803703076294453122228727502092434093461365156475012402110575303995161126952006816575317170263070884924732963362993014814963078723575040647729512237567175080471884247415700443683069346043965766779367796812228250192178866143117750381798208463933221424361268670621136321866030935198942616056764018697569405417301866136 -183648510080323621924468014374645376945326752269463466723141624209326386556379457658651427004358860700962571176469203624171727936983929563263107482467476139515945742985792182000397287249533995352276451371018608207831255796126681346761719410216285282773402783163006142704857068904186605902792727146095650061255745961711697752307871086752575524972461896340352747890511546260551721261968406410106854191528056208988191456164920817811270154 96701692889890001645967794772523959591331088293612410594809014454418714669360043888979824243419721664513697643511446280791491819304087327731648564796326090692518765642769051237451978807730032473912849160310362947566902578546341868221306454216078105402890628093598468617748240534282228046586945749252270967076633150887137348815031640423366644928420369162687861142450048037874614338669846898613843081981139468852512420205487037099348763 -39794241493962361477913251089122312256528862031998768953067101559209886202982066306610975898092288342460130502424079160933976996360368816826320475616779062366232130913932923159917063791720244575073347740518853520482263718515242946135584923606769538831518985922129154408390084205275395434502180710322077005882798479734259826616366070431525411390854567214053573753641062179493550125321398771502554719079903776387717114287381593677863176 6269200754907049652957707458711286709726091927747741955390123350311333203041611387650375911018621623873286096878611628304644177665639981545533612147129694378418233744195867380082017462251322917246879276359509562404638483868995450936051039245584393473321011502383063660259284934975084248559074743726477338404954313209723689679991266551946909259583390647091767114800808419486934037815778375293421409061116768770504288646142132174567994 10783857937738289102359020603983884502712071168882780858884760556505827406705224739682030608688397528140664528750614402733548861343162934774971140746130563941016257729316934192418154921348670665088763777838150876296744953188229704912469532120772672404810505177510932143425414226486310716125605428601162381165893218478013560633394491783669031218186513627709301692059965023367622134385849928585654946200391015868489512889476793738848979 -17284139001465311975625996555559814259333465922225625918013633535625131189486716607670227973074612278723358248838511561280187177139614537179452342122453618628963975230816222758403047510077439438740928988388157138233332053238313003351090443580800824840645054105206468086863506705524581293115021515457708332449149821514439907036563276394196039995217226488192622314399782468787110669699545096468578987434083012510796554776498029713654753 17720055119157231824132815319269198243586023151334333453318535183392353401986721499033075020708310484462827755917510402599502967895323112716617547276640421132898246643410125788849337418390051847469627046670688111445802088682254630786304847005430072492988644590951533506871905054297237970750633625621689131677088745014399435605756084749410608455722610669453234599361285823708456644246208733334601579959466134517147108509954254417380218 -15200275227498272490124649424505886507369945535935139270670518234381191073401659116866038314863655981828592195935012832870164622459493895051847241776844789339372326407231959417610060670568792239708715210906945641417693969098650720660846115757956711693152630675355278405198847906450705538437921810917206794100295225195755707044887956069526445667145989483130959797876840010705072710975687323820582388902191192962084428141698297834927684 11674301778572424213281668607897075255130289718918298168434115601407593470599964470788540354826358885503098376117965074774423492672339783138585622856235413346098437210135302363125762371233823673503292314452162697163421720932155595515885383042161465216160522685008333923333921674915103094101697633149607045604374921722121920704648737391813022910708259360944807874591321023300877264557889357738624607942271893671725638781875938130826510 -8219903586390661765162931267613368596597002753308659016190022475826251492890372513031775322507983686398165040676825943497012337671072492173374024699082131072089310361785015566870631391846712368107596670808256256485853962834407814962764953030854582895224911146224991594044268678418538799949426470081074810892391315368952919237007778965066091847936013920039151959382209076895078337429322377793376550822157181426586655995834921959027662 5336551928580444013838699622652034866044357355890788440894214524213582280340888091204448767874585079358689594600563630856036166081486232320972907055777473496214847915377544669077725689962613213875343652112197826164497143706252569883566485109628287559598519792687881085275354818153418451492407822613997477281028121271600840933999203846953881547967002609293441646467664271233534754123022516384509752787126245983447265791029876165387646 -3171040639089711209785138056313896245538921265981416276509517113198496376888515172135790587765273941165520121399082102311441321503331648292316298090470368585384690343713962236475215025923153561302450189044670412166472627947893102401584538281851580374983260422673583373545147596546309560325512059240248810257527091609562840860369490398770484517307611579153539219534942028675926390191764361953384183602128318286865623070710938099427107 1676482290866695198526328549207262381507742998892489668384478233349026900210117001949458743431630376995134143969207692489823199198085672490537164588966742275121448299884507498125325716980741974203803714166013913093423710549937310212937046060202083274201931493497766450743250200477578657101466792996291735681454410603111733022132633816939965948011992619324509068620539021102440095887363199623982030944828826297685625163377642296064087 -725182601692076527533560626964780920123301671283996754151207491409321435739438742041498211458136084432595959965606834795640579304794812837436527914266244755110141716046027234526270845057437080604399649212260915021759180460568702148275399928675938098901456188508094190184019325087865796717022899437479303423552332803945146276261537573740954074806948324355157305526039695843492081840621241064253558089608972482818699949735195109269899 173462411844226857037764997614598365656268174395615034786463995714396543794610365941306635715029568851205119588401957572092194887118847861449153587616679146468244603529286444783964127380713421867015184258691444215514746540305347087066734972547516874159414857982457518411146867973833687440047944382313479779643206822751559219373193616751281704691580719469326794987608352808494724494109895746254961491174964010741178912879431461225769 108622606472026684799505145108664902842760460451244963566207015517023937746505090213029751263192741923966426619181208073762835730348275064355050499439213612534479786651815489600834259685441805142010822466505530282309517380119918008745228154088424230121656365140645288411319329019558779775535314102034166713899270680166488929949513619441446439651422429066609861434070482388743891258806055314804067096341646394014854424655411360563505 -223481841291711445652574747945486534044058695462541825702063633764070936050268226856062439578494888376107778788987022565178457497288303936782836838183377630014609996277193452617740989990311609602880548251290538104881692825095482619751715894575861315384784791623557179228967788033769870319528039570523912975225656418790188762980490601515369441803216131548211525225411220266530825168988682486029951693765841594630246488751785492563791 243709251632036149109137239243491035619174341807615611123862223731893978575688900838681764124409527769847394431105741744479523832692341056930056907906244420699484642310707570940947728381904289802770891771612688198788329265237414161433370479490308751048139122479160395460378059747001628522875406391197055092961025571035675537553568684033245360613333433622176953564655546184116659124415114801181213277378853165956828860684517450452041 -217331307959938615429397702860687348618623407280729078231986332922193182750333630718004838775793851177740759890054380776453852713109355028723088399648398272625862115597558379429403396428465560446136238261122426481175803605895951824259861867948649128967404434974557289288657404721091760024868483524925688905130701099999068807734134241199731948390682820942853586542605046119546814044168482754615450817169107794587060799825531243641538 173640638214291625270264670379186048634581752741101793588238340862201386708763319394520891508340465360490790143499859145800800423481309884328550007870193179385078732454745305870788972145244909336617060713362296261740635855528685501795571774162438617840228833845511922635350843932510411267276573615639020849828069898998189598800958044585866332352841357290894540767755524476857034593130226945298608137695152248736217713311833691867608 -128438790895393127707560549993486415206292735220384378141991991230981244274747943682116189826295821760004251320425803391288120082664517373647241761631874674947414063546049248704596408103258441300240844394627364825510392228379821616571625819427551883955438790789188234472636664703909543861028854092870010977959703503089876183260444108173626895028049395967688544501231493270926570542121314553958333986258364474890026248207212192615076 89118901403236467200326316941056413580349741733192799724319153083220463635705476055194373340468467821572814108726354868474042012446875286104778327148298895732118065300781318470507531132242844918607947902268522218430565985517259946425951731579446142035826761835152406456664359414339863640584233887789228859568432149458992156168245034927758493643163603360709405434888022018749076310659207993824718196297382678034866125282846658391833 -58237331473551631733797225119081863785612837105273890592728473707092779840598051136082140579111304248769482604037621137139195877170090810415402126899560239609896721252059689115917017279583750417089076265849698597086783887170645701407632675777276854733966427277468188126726600447258549913861396060820841173839699414141247315300735354176389557117227633361593998387081227058024948851285065170109954959502059627056588615175691193533019 35650870141153662231037038714061179727978641610252382329877356757751005670329317921604135887743434491823434228146159614354362415399399952432028737674604247534380297030519630580289774135408189278116326341068113024224040278178784243206253445354318578027514141706744889082149246047464218780917727148485069073261431408103169988498827751488852314624582151612421600799900468184285990350794247319889035076594700075971039567116891237992206 -20067102690309627812361098520791129592635090437541455062583298059493957400301527032039067496609984947799830966400560596998706345615643202591598607920752416220287988132672762814259217518828028351818459476849647580992241790339637202177618476240735338171585817849818002332293611181057471597100511639418329504985683528973107290832623484350634259718693684977859077873802485758663930945461483093047916879070901526893039559925301090260998 9927025620405546517012801788052138728880234676059956616013557963151986922736197272342299323490171047618619448835204983371929302617006571261970898243399661820588590872467815728764553457025670933379568644843450117290519466292935968608049668844426035231819246939723134884413477430771264387347883222093341667065968109992631965573678071520054944524253934701151616673111970335030765379670829578543755835841855204869760939276633290171874 -3729074597425656599148651487041740720000669644366564548021791301009667621360724239317294023337038959441063812884123701164003731509419155814500503067293172540999211818231259481942340104340906413864815649889155026333555250798533027005619016317579708411169464710854688885729321475547751019384094884470568787847252568355399238606773111462193304440128293722275720793945751984083249659878926220856909611322359527527272620419448780656202 220214563116762176993811766451849497764199698342583920941980748107767927216719161589551334937039465546756410660999089454710403029377458825619210608117356879347414996782825272496744445502865317850425602839776010179934106273345893176040109937098984915389877150223830533146769492446674024283355515280251444390823543497471817980596880160924085196398423656334612236953601039542805761030197669178183324652234278131134193709610981595333 1530103517435669323710892085298358628774441764237236504089551013875143847122756820414556285404947102206104457571818336630459169761716107251442341280452654521438442321894838236814955502011532403986409995961881948763207398109215625180825490105890450190428717237315234679702103408478086094941354021323810370861819196632721820289416710974847892401120828468864367914371899776375056333874340599343985370719681028461603764584022435931381 -2195386614251686074556729239615354212038715269475294727537097977139767350064403132936547927532236822047750871412851069286964281281797070365242255059440245809986267109485085220879699226010974400025500399976038712956577632935802463136388681313371433775803688665316452544026775858825824536078005813872987350375127476490128155156771993092341008935559621658145759982330337509226014411419697823017254448169639138783126055032649348570734 2248104005866537157913272858730923897653735303072110814085300294791563750222803366160233321480068210150353548293665165693827039822148631095095880136932299853092485721500710313039196020401552280089500482899470634030947100083985573684011286681605184651462657301838685274245968044183517673362324695347801970527379898038277523155164552725912467248613670983953381835840648128650341958404432136952588205108774292153517731042317523430371 -1990655533253089170527789468195234238678429310712185127194563182450228601636622794299097890311647194089970490041109300324848579257794478223689390826940536605780645129108266472765741068141432997615546778820328729308236158028367034258140041153421969459608830162311436274774095609431145254145563663087379808058059603739172888159529132558705660140301535564758946667781875388353470296622426650791142954156141740659357367338415258972983 1608074392728116537009723409613754768764093821547622996060684887257229791841644594860556518219012599737272006675740467988147111944315686339143133997228687032610563916656491985832023191048314041351024066625199808200480469892666501902187154167704593154623324133786791232187440563963829838882920453030981142770869142925378000950141347280484699935582924319069443802513202677231681508107627592120895825638211310698264910050666932368260 -1210866488911074926449020889778658250665605143068915415566110175034603927165708886562958777720256385030158550056218196783397841824327252215773694507188740085796849084692526546387896581705089710444606950722435979834052925740396632590606191844141805393640263280428734831811255068184901839212433262857559081367271262153981284095926188052909850901242484362481481826081219798839281194298088487964874321056672285871469144875258174030234 855963682997589973747990398880872179061425698745746525011548060223519667643940190692216276374813251500459717870836764879699237147823876654493761496896310395229292980827765782794302791752690004031216203863423867945677703295621014984061322457657024186106343748372778105857448030569772818103521820975491338623769013106864235872368189100650299292915191005906986312453694305919570112019921451992983988041584115362951635266110758638666 -566446379421782514822315136755598173496778261883392896228135604226188370082617861562597658464991628548439873511934954588806145159156203027600164406878277009631384247901683745762303516807913145581973945246146716687136704883096618351834288653607053901372160087054376944304377974280671668521859952549447095517511400320192371200525640438376464968880684569118015474678944820901609212807299807948305991790990441158882609263336350840720 346961822576867707688063563260724088895565056926887028766230766397737596384227687796153905574501578074609516424969820240238016594380207782938337620016361682062564289875050094618922697935852973194188429883682445166682568394222058755480312659494543543857803341485438325489492158264715647233244648687773320285912829913232521260380294653791234709825107121369382040880730227981125809019767071938908235280532469651671238230661454228124 -190965860788327119577265854576745638479217441310480250361538999740746554025573234694815940207903602778553917344554917203884022383698606917771984125345140064854824502529967016122571170647943440499508894351417663006068211696119693174541224535003881809819001121046816819016123841006116913567086868069264398173468303802170567655864184067777644529053356924294101367153194151650160771803841140809425367885239600373010837636599766739658 86959472125031616502130924097946295235159365609757084660523449464376986762689883838905868215362509155314775178018281519171657829525189149556806026833283035510544756331946256276693495927340456215141657069543826572302714612300628107472443069150039611480265892913297487827772243624630296789061428820850667650431891012144296624053701442079376905406662227568965731853269207426421932558116390215421977303179022035389486250127103214557 -23049236498281241767106481868563573834804943186344917901144934248430828686766983081903815722080284474083939554545726773940504231825570257321131296533568319304788712214737497024593475650834924366975190169900769522192021353674200147971732487774484636460847007427256684002338958415052264261894701103456053608682308870646656944329054804235221098280641511750383544319904552306573660100853687363638762892263050750469031400520685685361 -12011420405217927612053481555835880756949261258706873205002852186054454072852933040462940148418424049978288727488768262264487287975524435124043303564301920218956938750323398829726725441839389754301361639432304477026111243734796770708210169184569749492389124350461644162579173083673191897329681812310062811179725568249696636233472596847476003077927586814266513351899581137962006489368148524225495158755409216720014464551256314216 27994333651244632429419508869777145233115382942182096507435780639332139195184401465818830476227164051673009186323890370324191003906530062117885446006586544316537723128035252467049917976878057606291345945899361666749285508625807915734380206320943897849990681250305017991998753342968177581607014703863016056293780485765658359557728618455923834443105177071965564380775832618738801387714675889153190366684529405750402933135596908674 -32222410377422105527634713963250476753961642618883678982461341588139205524089849809430581546919821180447635040270697351333202099093267651889735647614744376633083377631822003939517620829291538426429823351430565117756723673222437738617870854992098824857046112303772898062666697903479356467349031867399065203040085102177269677147955390872539021665158600616801495849164131931967161713195789800612233735932470737989337696627295090013 29868678647333471493561639558104067731098277706601057896887203503689859762621293475438305139637282863630049036172790394875602561445894131595386500227968666809984647455924892984508986245302996838737142261493341963860433181615663264784924909423924389859908692585330865986514695927904519914168416098689075658631285873368802918431863000384800508482494234298972305651649965983546736255275899383249615871756188504007997858345765373242 -24547450694419674584486692401670838696963171500003922323343920833673281302078541064879219698348893395259877269234110646756725325072543586843760380593143919298475647068375097823779135354177249755453024247972731432112175465700243194994107380213801472442321899546121330758820891420029706666144970170613853674107791805899053869450061373852447116933206092318706033848083077594084875410937281427243424647623465933860227823460904181300 18505221947818020061305765192335569028238729901003026262897122327195515263314733988666611364412414064982869862538003201097113218852687686892025544389041341334150058859239224848643004811850185379506539444750727999758062215686204588897426927047155423274100574136995345938157270223382964721680756670182549179733440074505832602455916137797870210232234642624652216800020235930356021903368716625638613563002165539786714413339391418786 -12930355180301124157622308877170748525194473969477301928441294248176774678517746220987174640414792047427093445907222348897798189509355757685017324746056974985934259664833038113019338779581061074171518292365769960464149770023200331049612185474529707682330757359490777399889320567273728108613709524226432897643165585985126590967874297725772539205755245427551342424392941282148854849851119520715894646902373677822391302988959121807 8361251407674524048844616420675648078796445804181946213365536275728800376395012872043270629251476756540425043927291119773012679861970368949080034006669616074197263677943240237599294244903251051669341026792214567506038017711750409438480737315500061691786900485195025655502537899288280735249550638179570248949233115570478745419035905346677487509473565422261516303710932483390855665376873704299838301884337264850305090187212584423 -4933459889284797697192830064586702126460617539608693048066249085648223054278091932227371383178282593146805308618832986352053987327977344343498217218628135295144690163319800462940088962310749463015922230503660915062425695376813974723642212370090022898016595761216581585658968887336951033015791288392572907608885595914102251838024030470882483098190519592800594139396305504800215915272055811217193881037903458779928790076236455674 2553098381529235216599465069459373228593484831624835990050342886441681786818446008488505207900080427591481921955276484387995360974216038580354727683847737418692125883814672268799689032570181519433917698947809493999265804739627113345960468431587507827213075519123130239577094844965564650964892033203102517945016711606916308463515233568933541880739644990066620400247164285574404275586015874506923659626095985888594896077663029770 -1030705396704197340909066102133953975096026497155314370960017660111213871509635825526905587581104613786220788596641657208009045694277410843810581694722749903552084272964437174245896612142724560263467593084865274293154321683216191402139801853468534567996454097114946889121278755250407167695318278562463798145945229447588157800286669776013862739793620017290288308215098574326480120792568606100704151026405692497784208766837036763 146332573693132487931684184855441867813435484101982751553980274585129564391729192220342709280207888907997766041518321807980065610101950938119286082079891300124096253629238450094758669533687096729415554353672955210319770231778974191570410901255759486826165730321926230488823337839565681235847271018683221815684261299031879029831222930404090145331064440289112104295608144244838670603982750608169561073751036314293615333629188536 304058226952952136636770006959498271035686366646377400925675117168564786222294276312829570690079367286966505005025352562649856574714545731476302952572871152633638981780495553773280310137449950285046714729603152162963497114298386679514429372272278641373937502720982615645733931948311633986861229285017391083751182918147015476328299624967575046924491240035638309129794231728254929854883452167848150608744742694577159539789165788 -477568169872494265005241494072304629760155801745521100854870816825904901618061435547023155242169845066583965049140935614911257314899274561326852714784778551640974222556397686793820784633570275189394494199602982272955744969749848547772821574305946285187253345104991652538785473224762237621059477045507960148465949965731677471561752723993737934636562539453338214508832522234026315085735464002394292832784708498438499791498828150 489309173402159083661203954386288378031076272076404287590314653787501376340902991135403918084216586506919937647463308478666989677903620420788876063755520126331185119416944626116927319361660205387067633454797713689122455833133838575752740901568648434966508759075426945580899127043181683766362787479796002969855496267066294996659143600425939967768249739150626757669457452969145373441626996456647104133315835869963002714446735799 -422613806808848077293715699930957447223085237366929094168014774804382537022415125308386784480728906172301309140234726977357766423740508841695770034452889457823253518547366040227068040971431217586856127067006646387299419213408297295502115742438363531861581764107771708433427948480614722793618296481513067461782160657995036496284396693605896249299512852270406874678530476747450946611547246590039690439368570092690668226443793920 329315811236404549252731531479708293732109379061981603480346729126786956425202829343321422930553763776983825277096572645940553127937138698346112553750630266021327351004836728174548972285261689914428817738732174616384514440042850333757986536464082241118458167969480162689411112650900036100501197082760276237785582532298044858705768233353684990985834448380721937177714120418998368775655243190044742649605777708481281570425787276 -236349062045622762606915344408642878377020347715647583602101031864214520593132542099251889857492651656302900589856946072335842076747659647787717789407314558897937658537238352458004027230295975040726818571859822792088153002162805370764257420989952557790505397573476667968855926164854462420481644963611946453539353239210190834097404408571762430360418076016057092235889846121107620161851330479205066938210664438297951101344477881 156887678038564957746484717804988732498300880894738430691848678084821043930019012891261050492153470248022023090121144707290230988633333054888221359407418091905126957433777902607557658592389175710066205824598906919159445659571725646492133485158126827341630698994071818554520828707625061491130710668639327789634649674724448691694414242797490571810775647343824437535897804057787205600906525034669125344265508824406887084259918912 -95968136747601989314779586760175158828501323036534459290125899894399255412601045230510848087684879782276021316106035506800270517722460800354539852240759540151391697794708232718159383836838591778512626736349685732048763896911993050886185548897016207424982193210096502841854632089425276679580280039304944139104274370201677072292007156389924539216851353195408835723146621858046891002971285852134594465329579794629312724184169652 53070696483342729818629503073003673402001442951508402879033860950444794285149170971313655561864306827354900940799744453066769855888464065690048244343358362111564464469126084185394897855203679052722809002095691309613290298273338064700394308835132873356113753960435996411761942991428529124925088148420964157569806712058305558212523869326009223428937703399465170390029879105648412427835757353314355541692707592750505609519311827 -25024687401508369709089800808209733841916594899953431433618949227310624863885541455510155522712258857570892876944016372384567195795042309790150064582820773166722124228243923736541172604974705101554549735195850205254607190393344663268120165128090480415431962723073321020239334648578971034605626229842959859643514571908883898271371734202360564620412609991110025319401293456088841861898209074174820353096182186770655951412356331 8088356824081212914145061232248736813893032036502404123448088969228117281910280999999803070733914443728022556748522423707306304887624638324354867435114792462024778144133811355606315034206532307768257991371938582627599016815050539075234612937783840618254437181334823112529533907741198676512109991440960403860017172036146534780921035690327546763479068115039033454966265454523086944056756194365976700616975661576852377311314088 1097822479369907431784403131370169296376325712814037744766712338415022474896068241455684626666578118794052428259712408435753044972477688885504722529266679036462932698864801837872979356760362243819239475066538274348454370938168756659441669307178474062664977971320084179847189883154346770737475125237638214814456444251674444742037118937351826093031214668629374508622859823852145890707535642534733666397562585960324300821043062 -5202951621656054062858592475542759651705857147099445858380541697413348180734359962299293587805071368709365284525861172686995169738233314827656310730811660184895493261166504554099464276477158892626586796106608787131909260983857379038611041678139434470742754116577943341260511648035427205663092960688657113417875517219232445772947060104026917145040716863826888804751824206805687650248059574469437366841123104242142549100889342 6297781579379841873495636506729485953004925668583694251888645546042973681051270131519000041260956600793127869449858055642870689233052443583802886402957980912624480996667317671224150700737890069837262174596525354516330699966821454799079443002335234999413156139510109347394540878991194471883258622172568588942831708023230281970584658316649329364795610601318246824239828498497049932337660729808450510187286015139822355086612465 -5874807410513317478765474107338876818591576328443045417201166547544649030168025793826525879508078304020317946096470139936971278667765765567392551730829159695721511065645878345249791516634426210208736414761176207746633424028246786399146650704809027803502453231093974112572736174902740891988955440770088424826334393481572217033563580695039229633536821016444353087534872258034197959651237364094534548717327682579677357765671706 4816483072731807256015368621362897673931193757311131906506244443963909426642380022533927096711499959800329257475776403117787862484718463927633852677686102928392055456984444048823255074437510344338544203458815000894328369802043354191072926622603160998943991901147924453366470635361993853918635915702969730855255839493336943686707681485210013327569999020050174201957351773410644273116484277713130461950944374550348962609794223 -3590783603650974204504868493818388726259111066881139653170510504381939572570277316157029816337690182358982799486505836692748736699068490464821267944692765816192904122320480409782463144974489824230666155711028772767296476285034657844107950835522783319588381621620036689097554038600256459113402998429415598725922975598299347502699269589307447506623390749495788473024982663602301544242311527558754342120904287543749754569210728 2471978370275726732313086979341388481386671952671506042767913322777859968751963083178059518254919181429083246409553686469603922787756055570312027860122367783763172125920329964550060108221708013341125113414692189394986439107225242142214310731293617572566838273507360068316224769521468115777588923590183474483097354544732660973184539085817951811235779149158270488788448200897132018195475495368347365630245125632488450310628799 -1588502230751271344190270814350568929652581670523135732941732150678913367151882557041622559453696795005916548561399195415963143392697650772397412898306098861789603363858760966465108338586650540919813529201913759359140821003774197943191521766021024937178290967739294734763968827251785318055994180035214051745131181603871066621205772040001215214227379355917331434526483047439244893075842473016109043996953479633009549200948463 946327500772105807061439766294030230863954113869204829482162526443861298699901049384344542895603302813927886324548066498524068856042175280339132570230552097052836632029038687591862371463022271801674027632874495944048655031732152377332268001667265656074442739970218193598025937730432766174771706591579666830650127086689245190526831169313850554657259790778900065323464703820471949331707977611586717625564513433740073407793954 -505150824540818697662160157888703689236712180250681077918089285010154629263175028995718737627462482712341357440305352542398638152670872765548436030431880758115540814096380527545295043279858431935593695179599474235612365894187430094709184905625211652652383076731534488727800685200907799095834343081157044298717330369981922326726107222053644308034892430032122002551529570919105852695889785027201710696511059624974920779787060 223765498892861544411015252449005363997033269599452061505300270463571918575850306392096876682038282968342854983407606712160201788327314263290887575860115305729208923716592616731140732367022422462580569400425791479091072645223362033388887696488404692638216199872193095271048993269346067922371575010498334687559515779936961644492535793248572565806223921496995062615098866543528022889623478697218044836494573792843605251946561 -61622998593913445505038449469965645105975368647886657667216828784684781130431779477181167227390115380110341372546026831944038755337208788471531179797410352115400427980576556546879223634640373396136348015254472596099185227342539221092795512473847082415642548351850929644140023902142206644809535204689874629738457703613180018481012195443626652517575312061270911424201398864788396459745399764782438620340488109630727134929723 -20954783372392308450816161637737945862697556992426832818666967799249583592299353954752762241276392773204594065576197512544568950013683598206820323834066734142785578005157955443138119559036242648430098916551950530008798451917670930558362007480029292333596769329805168358893638404787989068413896135077963681481454814724893056821595370085537882730827936673386329061361016362938568386492190797417775988984659054957325824237862 55901287509369871149619594862091726465819070386490914837153638957968805924923178788355239291138596294903976079531440951677643399277219390356927744858796439879504150775442690788951783800390994433096095519605807974849038077553091174149326748117872371777379430495699271810449715515519355157922717408544095602398034093054629425243295033673591135608555699985675609314230228348966676267429277397952725931196632002052277450312906 -64157355640122109288514990662310621130320861551690943158967590385587409606296521322970625289165447804017144885503806051470294516897489646021085800617186349998398063473437982816762121057932481032482481091454819450638170299211774171356011155841703055234775577323466654871100451919744803764651253488830451622064536063932781206094624664577094584814059064981381601538541853495285985289914125163900954779937670583403612727983778 58200320342878152952556307894842371918805676203156206602321295996877524342361397081251364061104234357768533213834877470237335795625116113613574440962810487348763541173025074475879248337042364207674103855382406181982482094324548172514488109972944225241956735906440015910958296945104854945529557244385405179356193900836653585680883116774408384183645448373303253406755200765574893043024838079865340297637814059011328806994032 -46270617578622510841157252430125067684556682096332618215565166401810051085425970608924350837961360156572348910125689779892415394035411701248100512239118795317456324669916686924287501174959012165914920301206574612982842646983143570839758479083703838522385845200346675289558060386943724116669648050222124435574350885952102309803119969380606057947302079479308066599871527459160764912290983965177026707980015054530853194240102 33861457698586191734360881045907856869248180674822585783536741859421345301982653920910412340352906067020772514416166156872046433433881671706161585075492813182348121260061572649313465926892324472424985314965587899634907035950985071111579742975768347402779388226492674830073289331168345142102631389049785781149685824255423094812864367472071700391934786279708742540864593568875534785262573354363483535358016114178705212001051 -23321908879269629322479003125026553016649515048658611406287253348169816202114322671643443522434571918366445381418990993091474583655675823756693369383135756498817966348530381570712497512831206852450014949306616572265453051842087755930312646743870020603851656321473773034171814512410261543163817781867678392355174535529383366908306361959842395286617290918018637618039660590805069631451300843733571868999296110236946829705982 14968854978697066099176576594150584961222670364738459130804948661602190246791190093812220425560513028410466349258140251124716482410158001739823299001393765319109607129904242678768606773704991649676438468903784318837863792536249250893666431404601288722212422415779371194209850015564194489585935435279477062829209024807853593364269684115000350072189474455540119208090348919900613960874142128101110353704191308707530681042284 -8776337517523888461811556621121661617292913593069017875972987539493929716568909806299818871441078246444076860107652627232241109606905104544552228443016084931317844330074608666770007968274191038301097136222009816485153991427622194168018232955079332524401962144120326664380842724634084875537771847334330426630084227564596182710542319359343245499638748471897931963664019863173902620983968202874106833245547040368790210553783 4646230186364100139592490911556632707592147988791477872244198556676666593981359013890321389149503727567467041945642743958667257084313360355191713952561441974695118419495177292974043720680719156609175560138536562623095877464806628208518889932831341765918993122681317113045897092091108781553664773887571982369857812122134647651903563480239090042176387473616284530071448039866535501427774769363205764914492720837733311859366 -2123647100989455863387063619549458606614590853764959280685926915569694507925001731346995578566601750668528707878659171052589618509915615892945439193382068632311366107397783140745890665475323420387288620418883274195398902569599845993596464121311959298065422061096965717251125861590757260619487941046280446473804173799715949551030481042764605254839329034644030751823500540722051124539789065077005400442759500536946850716027 647077736295049331933397503141972396110982395393473560549093914954083711613276511625060942302865627003796432630358448155465501584177950659520141864773748441601511159561723424931413067884359355198767804349082843509294923176337371860893343769190897363952810988584392726696976396352735607212657427244413353813020816213810088876137075775742954408333877527071341694538801934991286103630264744083233045263302043544714906507511 149071077871026571267306796518232253428710680330966332144999124346230227842810979272973921255053538625477686615326094921750234098464991883102306350490774875770976114763107098993528250524602232149479395267558440572913651077882045003079733918658438559679688078835811209373649920752534131854078351225813665176670127644316095028078935909453426815928371426774313225484075032646729255241711141166382770177359924846145438849913 -486070793225349254635679824180924008134426495637750829730979796491714928782686482459695528104266185504639595300677897941091371970749982409542515674600810743745862889293008985849203182721687252258926287243722318913986735419011889153048893736639745378383210109991274532904463607909752120031427174328073718489906642871409175981456465162284816142489961333829653631310386261956644740437597374884828093269433279438406345907313 552645956283025509594365165011546860819754745281842218822885820001501383500052342319718491884598732892895452995191065285725784397073195090943515152524291904342491220401371166928106298319663110108490913140646754154117682146159841569263627593839074293244786118236402043827441470057835726434983441154892716389521363880025088437669251674248104991674377249235178679231624695442604308363802010658372722914459339460686295527269 -498921039691383329013830348532078091965318188534860439901401975983842512616596382779016803948197998072726795212173863756755438721407440261596868823643112569547010501335538007222088980504891956723830295917826549849288731158977113538634239747215243239647085637502345818432722745829063592461010375534664099249917367738506798559788993793196710854885888899749758696478943401668280841035649626257545834622859815465551295686014 405337166813956297819355576743050128499797603231327657232201440135883062108139292771871296051213293977087730541035164615882700616394228902932528844767968515169132555492161383295813131843042780379710807884626103946710097456436588698397737027431790253889087080180010919005504973364252778088187094730725067913761817655290744346530742331852617328768010488072921792014798138950408703362670875520471374957861748047671057931197 -302136416156546075080837047452533626088671789425747916322257242465287076554945988015018535145245386695021333057883413866143892946663949291449381357415282686619705645665889644966585646191174006863842651103899240568517797503101694499426007533230846135493356500742661408761471514457246450792973279855871762729280870153261766143255330834893253344987474443652613635868159864747255683033472034132390178956906000576738140971184 206138685733808058162204769072520693100378516894440938691094329621451802526169020300099964345044128469201877374089667069634457356444008639648461300625492324454387785717637278860501355148248126677162597173529841814769192233622075920411709198315092078093384709503939550715171008337643722159474483373599888857840949887204416531711354103588826931740464574596151694918896287682099049138306953708292914003727263049972251222991 -130879943657599284431743587553364200555863174471366095378307205091807402727207374411318743533898755316734127989717803935995233900950612195363965335837393757265368737621041481216552553918454124150643006038516053877535096887872894016342730440783642141805441537570000915313955857642956636888283839878693851759854074892045515942118735637434668789648207087839273058143482399367535287983173375033133273265024065777066012430334 78774564073664357559338608564369251328203760231614174656032007613078461823914976634854513355504681024280547626088440464350203792557596782326742172543273176548990767657909688096676626692535688640686343661942366392982871722600116115830646444961669288980415492453364726243469194309480620493474717087994204265258704020496306297228411845930609170938184226983484103453170567223443489972199901811047474764564370844062230120515 -43456934064174985290694231550031888358614887439199073886381133678095196439733600646652851902919049421443360490354022803878707900452194326127901363921750553248675320809099711844079325858534497185554126031514905589741980407228982332903142004654601127049906130327781686906183361755401085857484036375300469533008561489765120074515497822048639336859708889566703988225116792009663921442427864232982108957729842119812585208512 19949821634230126519382631728314554587735247624036481381388925392077650768740670783391745678142982958995507773210361283245192056694427358529869425845373543800548722798371881712844516264413713127297168317620699668514405311957733346905965361345642152404507679683762026608978993151498011706443236440873494140241947927494019967282251082803020887844432061804422528641162653270647758403336422677661814272207628656489226004021 -6208207191783812203730923495711692841776636184580510292715321730185076408803172547790975283000443053382441443442732655447826771367965095315101742142873861934110690735446497652692558232313104790208752136824046759495113183566700043134352687238279224662003101324220648143294440058896315491887623336334057608387684336628725383338770093721537599336765358049785663622374845862632879177730208308626694734976542892121225928864 -474237937892452059222782385940849286106324041564814247247886260629225769276797877749011648683394294978081630976874574395941555921700486577548541524546236568915787651752357379755195351318542383296922718641696074482345794607828749964448784707545343160579449789866207018649404430564326958412866951116742611135683003827235369141413760211701746721618028594937966993889505459072360993380404733423141065803669651802443658072 3370652172504995247799305317866579822266274794357139919961505370551893115042616331395368988155919403867071335885494389557166969562388245315635064472622898427821816179525009187225290421987120126848514843709499234640703228772290896112957012391822498535616121379848198698003916739756748969504134715859362521211512867306997915407501353209415112756751538956252525873090360908162805749307231462829173824084800298760062538378 -4366652881652519592625542225322514869055590784259149642168438249556270279075035387068363407634436832593490297387016277604721356904856580807758146838024287284505344812011796455990368326098471070312392361378995598123003110247205192383348294319454554688375289234939308335291370170103203165556099423346858872935962679491518610485745506559442060257874060641839262949645797389841254225060577770057267579964706358225112808294 4161680175909559550256357050684167332345310826980212095165976411924168215848300262331706325121446500356006642830323252328869168686932598563394086552401846105625576070392932085397839410546476198929117852796981479621961997155053632117404547725120628578258568906451860835152389924163464583555511454307345115066594599839142502054832703889034307797787028079649913960626911143695195610079377581958508263420238930441622272843 -3332357537687830833000131615372218514896867946620262039873662169745325335438304853839103521467730065633563110980604169020568083351699820232130627227055679418459269351565997637091119983067356487217215479377927984314364388305096772043800495181820998817880422018739924458841540705572691344677314292085564299469767027908235085951244604411803918894375821022318443883761615767435522273318155578607233533181143811884921549865 2430414064077223395318628245898933234102430783665173781090634758721125423196003448017700778630268577888598983368741602140677150964861771604076174859045247172214212398142662030757162896917072888661104849924265241101311424101126602888841190241223196715903289841557501839894754950139080186477523360562050063105962572007805006678375022513089112440246409169659610266527012002561904149975533651111627913659254601171067210401 -1694678494179879750414163088401138534789085383929369382728837828212074876574545348873294352709097942892377306648524468489825582029992897596518764936029718907693803581214527728214207942907415500633550951398561353966444636559657604098068303420532165231509671655189914776616967941567436633517552224140131581760404388334765886707329259226897324378716700064344540217076724083027487705282273217755194402359426245341447859793 1111993956900384068933242992931002751872209639108314842215187737929317185944428249741820326962026986656286989819353372375172322652628022891384804590704126202368928097479420422265205300251034042749409841389074586183554876243779108903205212351698798272674209834038512634840542317304863082100790147206990899830779420391161686043434295133173273039852119476773703232161549268912589069601436086417843586538129057340635432903 -657685586577569120861743712383199922716952225168616238833381158473551975266040998743899452672312766494400458938207766347310150214728144065506961680372563574773260241099838824761069726337668423491405585916776136018778259564319477315737767334158015411231873435146331533257973775731517133627910885464959754619122906955698482857823091375173391388299796671797828276815306521213711585658861753275317440242418818785244832248 347264555679028507399458249205170335913319814947986459081507710641028888378868917704640869867212924244186142810317989415529057835274803275913146861983416673766423945550296256852552295765923450244705207530509887477991306404226425862593048100667349317983036318439870692861665915221663180378740909586944027202817138633368168509304503296366420502330745320505051615667538063871984459936483096388723315670967710956855516745 -165614656030913091202406828521125278398211878472155888530641971396188583326215161750943109474566368182833321156993103011196362003894207514650985880463972032254869857630552556847681608907953192428764549396751376748816287500790660477055316125007175059599803189382543116189727795370454159014872054879853658174759538448410965978034416846763641903786528133867935378525621341961306989750317380038831780134852197036482982532 61933071366320462553476895984663218597242357519517579773878521775533969735499289450361126285847198285528812389438459541150461094914455835186159269935835229842164769352767727336173924722681148730113279750336051784032765223010416206908726277151634945904447669640824057034784512178186567805934809080351627445695736738274360432292276020369403498919603786966299128048079047709744779872089020745658703923252036942680493339 -919926797304866161563293180088441560605878068875338393217644193763169290888174957944678679115570810671756450006848674168505895642809978471122154863370743524433034194135336074450999169048247446740057351887777641471026786662441590107084941510774784263606593112477618996053258400437891420252432006436731933275408468716919353791394955919882170813149195148604161834038993055848824393314002729621663072473674544917240185 -27426413573067783270743536380513497860604398523078579363797866909903160544807976062783843515682515779738702907052626422979974440329026105697028272853908776474115090536429706786480825974985561212655837662705571234258430960148558427765500779606494640962448397091951035544955899947271200584841067502774483274909392862098969642583487312416102078166415844214210903551030498851951735140846962769352386125725905349913327901 32997492753041700522605887480358072349664458201513503600605048475809748582990357719244112248860566021147295416144254645353486317305815626259052306691722536357582305918968983922977410595137090064943138176002884233357350373178487267574405036969884897067527150635418506121600783021794716092412988905644211396856333096102421413083881859837758920113043077931554143398060172325266480813787232424608990723796412561530840926 -29602242978592411275125376576955861597721550206702517061869285202761300238428063905150025271200871533036851060200968543227807743698909655889788323068226958182721690982707151543090707334366518720395436234432696544298559250007945207412129205705034415773025141119625599146670052605278379247449143294190569799419956082289714007882967514952378870885249467713554361775649070015226268057210899217784675832866822319162430377 24597491891109314486650637422655183633183410290389968182819648348428591636659812559996258196692990233571654991888901726620038724028657419713000857243705248132416518938372630071665841797826989620386379960636358964198970906316986775610033151901190394783542412008992974408970949654022376509532820757475862616650047445901517340718322339833147142036123209988911960334166498783432006761522868076472038802014167992372897084 -18729823579564179150287697861780528802322082157493572838476707984349038418715144330455928738240773127605171861454878718155526271888088603803949939309708311154288066062536574717799121761255865691235187601328642345783845583935531841899659268654779331889466581326795346245742267017512847596522756081766865127631000788717385773091255461294932422187203078399349931276811349473926873626341204445506251694827467762137130190 12621716745460770865552692389414613268911539935903165345379103506786331282779545098888000578718442103780080793686775634856783173016988812543199647102245329712507835987134522126178605852923758402538183523773627570414917920574376817032912597095463218006521947332607882687868893922752078196369981070743176678076756496684229038694730130137986286622682701161104071807134665349800988237681875290207024561136565326452574591 -7810945800793085186783095569014446111834168863577043886218165481287043136983015908937947068151609116356795484584198887305119478691437584387566949810052176329928423048715173068631958047443028775397583678599144825049911941053513597174928742873344447907125451568272651497224012172417122075954342348070978681075417556500151215541193460231792515419247163487668453028562554740262916404918719783913775895172111136275055293 4696714047695463512471374907273986182507815466687041999768672155183369348021706677687342692971950912208194786609099608513758393300369782339628688061046842021979914284936581203188399887373409948045163824928330975901768979577001562140730699392697620614150390792295643443365703382374258755475024559929674124792538078157055183296584415387249302994905949631668657806706762658973901955586368616422920362875370478237238017 -2649851344884824520255200030529939097554824981307929741566174249743086094146503578622916675487758294519580569798103389037147977572090874974792637476356351563072470067651417631842097046657451103267126497017430925180805495233680403049492588936985324781423921909193017406976790946686352449131359885526082706559758731066115806574821488880599972605424714753315096423826960720253484478386541210905179196182218123412690693 1223229680870525011905570494909845044423700074696568783350122961822749210886439958567163857730050030356544768948674112977793760598460044482200174009935615927891329485246564858821713680569272720593413642508076846817969117126764385766157469216433280679424913376442918105105642731391572089595869007523230058156206154305477876782605973841515910840999984418242224668008019947048419264380990355066808317717295550947066612 -378019711636202959860916467628837580944175730048518686277962271460999690049019930594211041296595627162538546661529796783776100649669368025699153413748595163881606851829397841805036098759582111550428362984499600167079038956695042547417367936378016112537483384336416592683217084237573354218392660067018370901644001040823894785274572576102664019690513374222582922195605078742042687852744084346447580183547756126193691 2952801126882487778625408550987774371512986070442243348297553028600856749324917954726540651932143915866495554671010736819634348540892100198733307188155292332255701544612366146716785232556235247145158656885701777986605597161745582042259442764283174903564229171520654304692476945143329930907564787678749959243432498167906248463069712554632058535925272821726677339378449628957577382428640201978308787575022066551814 143289813352902962619873839884538507823066773664071554828379109406132532414057148032047609708375306746461367935439026724128341160794270878133816213836497353974509329537026895194434220208331092458575559377660405446020996780731652369002620598380057055991874295573404296533050963120295863241905000992142485102365307792728280105092554205546187946062806956951565975924785972806185435568841837962309818307509407125538593 -207075157106419564772219129030631924308956929751046076162081177817308506280978738079766460024445714587775151712309568125880458162656915227721220064849714541634930242552665977388436592454478521644843346906220876389762763614874880460440481374144006855550991684668278285048208867657677204300990462237075726111228163330474440668426870285681222407854418747710989648246699688919369009456023953487312076039567061272213709 208033664393269662957596585791515376851212893379959197630592979166671194423402704955339467523584755091894342690675947060893289166716175974632034333861444759353394652926428034596226585377511045581862223055678069769910450644254032736233081918583617853205662418512151631755727337514533303026811473983451145949976317319621151567373321501206649735172183997063553627368475062955919092647271148147647363677999963288321171 -162540118669388127270879668893110330888888464093180706136867304783882436928761141821508137892574479824087412013958617396019602736686513820600658271092881742129639239618985141019108056105963987634180486283200146341806103792213920925618752305599741609750782787444145418115785041144805565653627866181505210778149083106576008967559983644647687412307036474777128283504763633382080420925604304085662421182914788546044933 113261623433492454435451934777781159091877377064717187665407527211493148308030798536019803316796666422844554605328279669239501526143494428408974275132782447670365094954470840364723268125131391188063698971074025470001237440558545427152202176359276801578676853662386869731790420386294042463713633592660958740843744733343002987384521927256039172104784226019211439828228218596487613615198178633810400409231860661182765 -78815401319420343437469055405999012608112039417336258787870066617211475630280190317588757408823664874992430057444412574615128308912669644245773931661703853521117699038912656156164977501276007015123233852576978059934084786323323063837260712396475822128179961582265137575189108233395875835102602145089420871926296358490338074842281673974159568848133979387799102743235227814270278227007964962761757963729787981679304 52616207157103622654701494660630890213524190881598887467837886604650140116888218596185309313657132502785427773279347185247450010375747141157204436457191670282975822517529639107865400127200933655767094072424173946781511803362833157738962440083770402326966864021949567051435005082126768356710196878234823845595372200499352451191986100529320157622157717541626734118497177157209611444369679850016608205922475414290973 -30383423658128259815555711419967383720497770517273974382421487118524793823661891349223502497227974354883462144362308389729958514535316574844114823254304548489507397174192520275242512439616698010574566123671649291553016639049774989594886555511155674407233939662931639371516170923054638020808089196675246089830014599510179177886691309362437230210004558775203127608851184805879857008939957237085733720216720862195106 15355381969579443691979267273290970995822929169214788439635577943900381435595287035491516788131356197651862627230087462015925313268213631859332154197379229801097068911978412508838782928148885500931381518025580952200483577915370482083973043809620117304342076456311825423964813375043255907355968785078596489065338287408033262724098906076164363258398834527049016999473840129667964116061313604043110291607067255707317 -7505068283122574947403002565401749956292715878189307467679875231787879425163745786665261546196903063439151226699219793774279666141463384726207831834094022174509392287639850869836866075208387365639324844619508062606493355455650790181237250449926841707027316649631863226307971676175973482135160910307593258901128194202700995091809867499201703915301759843532553068266926756243287649163096619507297921518160005618510 3181562182564359389061097832419692800643336316145718564644838512036780550899731943696186214057885000332500974554923421205716147318448511241448618615771468369532410730480612473497281140834317129662861420475925201633986788705262840894416097532863448162309272124989147090353587740117966180372403435687763232635628628224847311566301867311658258747695146435521215776935424003842039529297428603793506738777159764955249 -373683810769070566324505150652053842745523161336873198373603300390294979635991399624562487485014956834269100767992974220688872505308064205921562155747501804233138423169619985190209807678711945203092475776142357100967985262257515924975161797885980972053435857823848337863423359550641477343263265770145402805673651833215043082335269960162606724205716877195913919501589699396215011171957814564502885742423304864057 -992244219807743541064874535364382845296910762366465969216722687013663519031976504859637637601682760957625233098933576496641010369824363984104335140278023954975573390578790641286229019368621824390689289487019738520231608483765650716941965644867703815770680636269094050965033590639779978434803923235700944395219625858761350073900034492633096128900345722237540775350702719616701712991652692876164544182021313370734 1182708759425099741375726230790676818227342397419507681196770027123224042226948887466006544110078943276444956297971969536141068328792486653600885796731238405527482925832141696536324433332476461192787565132356939167949964828016346282104297205872191780705639508393206957752478143417696048798678322585964424205519663958249491145261746225928415694449248434819028014929742365797679217321246771203971123090366405759170 -1014347808427905846166256683306824310168081080773103330677114376296085310977829786994966441397240182374015147675199698989185257149084933150132779138280349834345665822768650053796015449069968813317389979162395928177885695273005394661166518744323764859677447788654879123822046945168639386307735014187400811433080953790451845133748131050680366477149851812661264587605925849626708151189027306286445314379401752864087 866979869921456072185350123507171503394515446818828804084279036469272147549452179832610615639546332615866945874722007415080471789673411308581674629747546222680471290807347454269610860265700051317575307172196585968934365628545615831731744226077493930327104180980866581996069845639701229182822472554099505131397742893810746909119023145111398202130981329955065563157575003277636527168859309146827419390745271650262 -685037601348867098336224036297382058124411933370041486693322120727232637695057721174681464025901659610041357941161345880411013118075716515053442162371129417879896343464786894919338872796367116265308653352435346869253702567044931861608155059484435561301383592846694368853060848617236611203518258833399207427840359502319878546369691143056603698031384974623805258854162031879759086570554762998364740708243881097508 450443235628961453256208148959223446317514297374423635071209146166422596858256402242107138498503229079429203111211700603199201807261081242641627014788888187314098505400097751289503031079090520066399020406171972781711268276314317792294423326787880101380795747915284045697535365493578314547236981272192653005318449366462477645361883096037358781700974138056282781550239926258328392901684307237127160922935533601200 -265247488289907110483076438787313405689692736195823491906566087982061154817622827197128907252557412910796005834662445953371307189154738295591698246870127203257380130593823250361314131951205584887955958448025181822059349541081013892123300519868622023574444525571448508778095890859036986414748070511045790314423896118963499676564526112983022164942768785428132010312213425703917691294495238266791966231463227945579 163478136643692842998955799076420943016189147139821338912868275763625905753579938316375700210983612509569694111719927469293367495146760872100441018680574948048512961657157519050863592066246782410360740921517372284778139834224758784763702691078109999177264630357349598567510194503558545704830889474096057148122647305163992318875756936394309393725728537283299239539537825116133925987400300367368586132830194939704 -97412701508017950743869797974800226143636034222792884421639052155459851962069540653033482896271384533607557872903943191662716324716528223821782613059613181389158774900007860469430850898422422189637490196260891123551623952415749672506408696093231151214015964574669412939907769839563136410690766815956933801674493805997451089496262083037726380397370033259456997584310226429359392684667291942348781766610954181374 45308256472058619175270208465460940390170258102757262891871064694745829983107543937867183598708301904474242734292242665342934368771119962710149002538884622709241473888127862571349754761209233286550479841628026456396162378829138838720504714780019159513377294222081970749726679755907759279388795071925327294089259497915357130588464538825598382063170121693814153959847967853505817116011325090603842186976946359747 -14280641950788390766616264657824488067891657180905852340551572934997494183444180387860748737278831418933398456542052578027451939045202651563341082045125357425563679611854672291534234597928145090539788328733121747713886356184227685953789283825579735301699140367092928154744945184864468946082145123062098015808706418924110540065924088418229946219898922382892465583215560288752138690841682883012395228350554139466 3018140843703618726780110893003797670118974307199282784829375696065219372664707367310464987555074477767940947253560717012851258484232830537984878453393095886201358189715177301884819882261446829717326721032382643623694482340740919338117479900487511514786587753969425789390213611911013335027585212881209515660112598763421182309380728382120717400694557554879628644076475411460058268166476452878919368863452167195 1564946659428360998929461187918151421487327946258576007731851928087619455334000856962995588858827859872340665036545584008312015167424979655682282422958889575123469891035793502520135515860307792496879180321739551234537315484179504924424441630942513754519602562564438433764217549523812378374556394399732834689272645926088064249711157519541568746373859904836734988777611007602395415885668634744162010689496759017 -4827135043017300520378538473719013529096383706030280259521065439084934498463504417068902774208275432089467589299411440208960534333773724102839281443336278246991443431743110824636774759606675210915831147739038492655945719273415050210127595582289643953631040966666098422191336578272526393997591722148245894629507478291471905257049111357642850776055501061297500932638726937948197863796582963818782357591880113482 5515906776938666235361745698485157770338098047155653774016562206177076701034977005943015528313362358518040050574286640298541328219396276251259863142898853092502664749939880468448310313240736617207342748773126756680440511670481502264662665007553103746531285707993289520955280534376361872912594256669467586946380191673484900856756711457650596261549474750066841122039381220338816423842124927722626385760297385883 -4142301053532497785981921420837038313354082548098078453085373171790123413621784291635536258200596138291089485855458156994202171594350665211021110514948982800840139443609965356278206683441099240620939477765315894002323205953735186085027451917914724128502508047744788128052958646406801305042206564862920831159447739406527124911788132122384080282641579511984838853451664163453647495088676540826042160619648396154 2734533145525995310352435774075534244408584421060946771462183337638096165398954794970840966147095080494289266199026797994867829000785277813971943309314957845178656098973921457642977248468714192974517160389064465333824795442837143166949110705335606729950124404535028950373743216169566255352626678276161366644427849310871441137986893492631541317719598495945686033678526006190513856324659533541923718473323519001 -2017052546304238454840004846187506083410265512251411960713555207969359485984761536890048582414312603142530348180721752400292523887567756303369763879877662359108577813152036957758112153855228550221361207870196046657905880482997486618369843462159529513099793474407090537518115103990193760652263216098030016362418580436189738350748198715671684474925981216640007315301348145615768919198821504074953104886911394324 1405053571401560792451028570307810900199975100734479550922619666631658814950395218445329690797356637353641249409403773505073379155319001840622005856140231516363450671937569648348977444134453236216176585491564074244453550091013003775112883806451447549351203665832016074960185277211974879004086743449942976095133131609219788732974299311747128389695345276613749932692256680522462554713164206542782815046309781953 -786585734983914742450914990071978002635906231225378952993244164755533224900692932928636373144413079177894389901819649735681700494210562061116366447289648230558320868814725247999326289436489429763778661777114701859299511956494319406801422270252772436154430063150314574041483416430356355970695094402447751082391619954135579202348919365823243457145401154428957827999482280909389096026854730206058478815074793757 378720836757708116856344201081234870031676042168836860400529060646688893925167794542158381498804654998015559051465447112144388527967882805427600599083540179426109442361469999649638735852416833410575880260612307996386299086706695906841441273622487968600563170641509592637737293973733240673650939638942620219546208382781450153535874929204388194579772810248959244048691935049444759829499017826145036539722965166 -205284246385611726550404278310200143628166673723368616809627838782886308573704143411778994513554756643951044330457289149467765219839392075689368155753617318768634883450655677338197985655249355358488765755898350787961716618492037562410394601987624699770088989732554308446121017132159691622538980626410263062947879013976928547662074751256449351977986269965187295592764147481723589646890031436828373802789554496 107297829610124167978016971570075629032619836986618585480948569623319411459241096073697309672153367092646693680522208234124075317655116722365508020187388878815141100271749715229252096122994903444910088201046439882037657268418375873004788266187843259554525489839715904975454021911291600600686420116811182694396211421301801518874342934255741009647460301685410253495083655876393672349004203230179472468126164489 -23052768857626340294434258915367638923044372013908969136792396898354033924665822557014574322354596083870365778243741245931542920430184553145960642643771165525116381613229867204551322909396554215573534408664160086132985174076208684293644679805630979646035613436154822507161964464096283906709960167349749971928606283171563758937968083033932611704274578230625106464283942149885123010543773220911056191651613254 -15135108534097558959003159885537827476447269916218292045172011854483847239803969898569755797185039983641600162421512692863767525548671366186551515754935469183938171333191980667097507533507948158467748708821681545045801949382777063108516963499199567161419371077922587978015199336952332678983771131804167664113322878154473682781990792850604331242562950197153544061725778889800677470155689971744987787466592954 17631772596990465641869487730924949605478958483612907690026239527676688897952914929087885299253484710775286743718683141118519981463770585760400786763916428321111998795721620112524455050589405258081091559198545873102056130307060274826639252170421225087041714852168596391561423043364725835705824710086754249726701208662050583755764829209424500823448777662452454521900755764191139796020030166047489213838563094 -14151024216611309883406268951252330451572926084050628085907029779407935019953410094933274349227944847845642520669406278574025151640319974313821682534517204715487731464029717379620339579155279975773690708044827617645211074442931825923819658957805823761507774081058709273845512173312901954600233413359075747946899981881518561288137543258995447117965289592360550469970937469279690252005031285692376040978378471 15407046003636768899345929505230273541185011129943982125499767880847574217944883879622647743410031810666531145714013247571949016116507400901663341840431200870495897905333512202275050741321533710573209520524745761161106757063929720565250469908629109490631678769648035420711106252656529636721386925992505241820494032385589602081854429819782663997068256896469821856207234992203515415886018432229219848545681768 -13172947212468978943890339609077339688853855320849790824487842754390547744803459812791193975225162797202865953866584197831545353691935743827396711494805574300238240504921440736950609168090674648307491613154092284432355180073755918945129249184213608235256227755433763751544247500709688247185699151235035983859125015368806071740540524719333945986746545092954560162376177021521742618713717641143826755665457466 7880138119691784950833752868449034301965793672301140018275572784979082393338060800767551592501807306138977710015702725280278788845944171863063685663969485384913948095831340634226878493343349107230766738061444386056134196844006389078796579591870242987576967478658449837434275541849036631100895197166987632728285386187049674304166719248553343081513712206286029621466522149118629208550662733174828927925311364 -4346427541137655134639802974076963099016611917128996358167565820252351676693224422540389438517947213299074864412242788498730748642713848767886178910308319505419010595021362995003541752903812537324514553305907568283516551441333838959061095833012448066224159834969916506202795543646265870249389858158635995637223254109308907085335745894596522783481237542729781086836718517134678836615699312004448806421425686 2975926002758585209429913078391137314291601649023981333315061657761560296653826155292773502941582462010694363309203513855953463630992719457385937589054588499938491471943429612428536199576504642530530538677100657552809361247174875743609408116721160253170292569863772468414496813432282922446913606079323812188890812922573640603617348198135184000601651464286602166603714705195771373940180763618608250325791413 -1982361934653639711218809720857054428088565168517563671501618386491958726822293433938009733566810048659964448906587900810985185769767011897171060004830226780087090635477197315746604325040151225301255061348696978405795850269388717277542984133577402163054233531580782588361931621756727901252762212165157590583131808534263781529619566518054997810223403579247552386625612462767688605568894537490740367340726778 828886132105403207752067807772716938815613765652928750135663693426727142198181961862475903635181926136631254823842236796051983490884708248908037421905792908256432013240027969391880024514779215280914655353064736407937191864594022508620806428549836879931621161449203563997451622735337168267085792268917252949108488150569977390144939718932339926787770861516173888168460163683470958761929330394791467637634735 -264689995652703748475446785371488327368760543286280224984143597024467087435860427362258342620281317031745194316308634313019061632257968362304513124348178633052594800809220952959964847947214501112695957731296129417888186839165458084756604877714468430053447309794767233038624121115738992992091970752584985040955727870051119803580049429015881954026869924952805649358397467461342405298065961685057829478718331 130779608727538727729351779840170139354854151459902197330337135563130712827827460458174692285416130552134167087250576738924315949527814689805503543276003961127217120514610836905860720057872606767258223701251869291513292990548463292038732107789571470753644471045674415276181520554553291985407526308099273613080732618657976453832228477822662219215568709607907930321023693272579590678688922112780396771465200 -57375672646053544663584524557187352309621160095588796295682100341241139066424859349108194131712396814819051334947041565513770744450808328838776406234677710788293637230637832820000285333147988615803448588021046512708943140855978356497433519568781011087454101844389015032165633512856040774156036455019526821207905823770078389516882074159029122336213361690457186697677390607626150956202325972651292783009109 -48078758540378618293224887294542437792606922937472703088446696830914295646717155888161554641260165891303104577724318118363777666160890259961234625366314213351864881139039712078897484701985315382397826084698344023668735519779689938275243642764420357193582796659985439857971125229861334326381847144463437051269356047141102145790780163253529165356228782885726031130493020463335392817057050199820166938851255 76533868638222217175005459948580607917933515632553266960687549043564241500018813616196695925305514655262095255331333169277431401453311703265167376735337294047758984258679788143796331778700128496287134144938835412231665116892267742435805570853289518419701821210015041630639398674258437891569954692113789944839875671721638951627620515830887934324191524905979790738707740530142587590769813679192726301818901 -42329167471114543902103458328516786565197538775439373302486530753614782468617815427607781204568284330192842119115002678261662076632020106431472353082266483750293218564351859248548279050335330866997565668918193083207562068941135410303025606897951970354377954010163113897985568743163024414217462473566712268559715165060301365151583629142698725897514462339322393475624272004849654949404571114530194293186605 25952011750326757770306223767893533009669080903302830815399128554633201866134201601025460616294919735348384407414344762487132232512489173543258975060259447812421241535512808006912820542728630149551043662169205369096205743854736374545327387832890323568136179867871276273988992954597164195037361923171891314007377535258101557713004829994441526833527688762011233047110682160704165498085868076818883802951872 -24815302364277670582692864955434783116582291962686589919056680783444901775636318900620575946973957552322513395212194044378466759106994688262545787352962023365324467644469894146501614697242152219675493300390949931499366341410312653291342061074401545898942010359755356713343937899674485782386861066076628635283822877254108502396283224224688593179717902452204123704257407483010469317728079278177726914938025 20438122337315956633868187002874249336745217581366165087578267162315583433696338689370568477829149088957230843317887146134006060576582978914298753728455848766658179706167100839937728543093283559968941578112510512230591721907367910016832036419432716194389132719758082666852021853762488035896689747656917558358492839685863713822745011099632896821311048534861994349740822022269759590226626424042423382340715 -9202620708254209451451610593059036748006777578699342243660510160881192150470274008337710213443204153767383365507889818805597980210918779576382037730658548082546691006375144555183471709543450649594043860135546718704314108596330204767232785143246266805382456525141779850821610354294000748782296587867720633578375403797848940280074335270350742115107686164603008315922310614524569765506116418107859965827998 3862874242837787428059643098009439210734109583143197675847773318586999026193282981630812950427867546365104968379218033096970331297691983131631162046063198671481493741267044071512798116193278662359482247129526689183938625166386625034555056743892919191651777407713453860359626168274483944646352003764025130352471141259753836101444175963368011375647880580034919064431126125967166143242726311243623349188826 -3023598572857462095599739157801147631937440339292000549187107606821254974906223390363185961212368265351892333251595299173626774907905208495281253566641175871286815580201868494130805530785052745505373116508170942591207057571693912540795805083089194805526121538569134131765259205948511845074340983174245053273396268269604176057497687929192637228280109145737169605438557697173425845788631183703712865465365 1994605745702246926097542673093629393927188672543153170392372077791515727973761672133928549337835228891702613825312864513421808567495200018144034652770982188607474394809264425348782688409482661953502726020032338784218891411029890022043990417808573280945622958697117062006643795893201758418484943658748064948495758235004723552407150107776696621479078303791255189379591309062602386491885894398929981400809 -524049089313611583321705589993474583344456840481788376032151715036551022876014812711267572707684558527771993467532875807348466012122841748870409161343754202511365308230384294070302249413702124326305273444853371298532979931273464837914272249821433239259958135085519123748677996672225722621142991303536156370748745040128037468181751834823238773843659244293371547617932491600678456597128272607944196684355 -165738272451642024194580388382749117965389778791701710295517843110629878229243866627162020117650575700138824712869325633857314351797598410640037939259607863458890647142147225292038576439361273009508668320510227520615937453092444387306024576359995900725228217519361410842427081443766649627273956791942618115211169477730737083660251683013736921336371500243482813133062981374022499374929934483049858665442 -58010400574404768649388688978382233335852964468569726453398090937712613101285146990489049076992140284638497704833022552391618823332914239598908760912558934196354557522966608716634459429092181731919548953203411557291909759752577845482354945694937341972690999219397850720772045850872611873181216422232575949252686366196697675078116447253734056834742905960003449944868568817771557473202985714604366053348 58456302365861171542972819757644005865342572418930297718247258551240404677271396268445150151668568127588046056042624610307491501876009325715668355672645431740729390859405776356774966361232309496284642345864014464793031842494697929551786684388034554564682595893755372868242694036858739797612844833722451629711498801090863446102005971722980187482797170301670445154721052911822328136335267527995574260419 78708008799420226081147935516814682836322727479056158774082801431123185439471314988057171340114714266987736907546130619045811865071699317360005324921619018931083982940813564073526708376933467724295354306471613318001754992743867095667959791115800775653028772703841825536978102980040259835746047110982934710638789661980959287045494319770355824171769459460934603535590721574538130677948418081093325530250 -124864994544676402430583636072548260417003902204368105525903531516688735073165702147105625753730711053008174091454758372101509184623237173923857248050719259007480997612687823372061973384848801135530258867811308756812023617525773059380124246085676418925149724019163322616381329574720070546223952284929522090334900578523804793963256115507375842539293119920228279802004867008310155342805166367220317816567 38153883044751524403311991019450715673143503820932325162304815678244974690217034424395603520014560072726938703553754510760393011311190378837863438826175027683923828250097378143711729626142140783890611161481218838925089447001067691431278962147439440268858501816970940179857536652322267492343217271446658445214101843438778259606175870220146333069585524532599324281328329199595401446569097751713967783342 6314885826708249989352532533984062391473325812825760507256609064433925719244788195396253999016896409974555847859276274899934284345979033213284693545951957724277459026487363824182475712415331056379350699341197480368058323591120615314505978346726689484295750919561098817780065864396636383975752208926557549150177166162876558512704879465404613293808795288260058230811852998656915345467501923889302673519 14271500577154138308414620453541512052569644157169667231681884187675273909657860174812444858349612791783112951079240575728901654461741486860276538508970138330494904059453486398336122317644770028629111187835580219627315755383819773578436538517233341592013726849208454949851366137941179807027165666438751516717063863983393082656638068235957997365919681073871289803967769491041728092514839519554354709945 -16594319975999073051230247310415319602174499155982294149160244879454414527889462717010175147302507914160306866823984175899998045149331870923993080170129842398939264344861102258994608062109471201922002451978850186870970919380824292714054966972690159469725815829778919741085603645619068107137479940481269807857069289280594619197866040292919432194607807660979406932709147939338521955619860513481098458282 3190105235364820944253461959979417387322773460266095350765601985178872115433842873722476503418779833710116882524772995171441652548805634838414112021059185365711453404794380497439427138362132699878111912643423331252456039951269219726413201947013317236051914748732800123338810466135287073075133024859154171474303362555081325318487395034108100421840395763422468473224810380956874166460262828386760807510 5564936888941085902013730513411208284450198469685386558441579828615814414270103431485054676358192560068400843468060585824062686469841131373571538532568513257120527750336686777933359663115769158705906039534891470702577913985892415641100851359920586739930579722440766875597901152773437393483544520821643014406977125801108060481360685949367705390758899936953252086883467214996713667713946475597622011183 -248772875842925337446063153306778993767525065618988738322632255676356521387531107812392489502900806026440943500643181427399841021683397675097025141022297588961263695836230819678735268936525871358735955931402081052462752889583198513099759822039232629732566425392401097548735382554171988125415139786776787385739729935108830638801222896460331254403991722145455976784406732105504519484903231110864693286 -1435730746561720704993723639338611428095011976157373013274652330591383519707677435059896010238228791718106829219020711544427867857363183918953921978086811454618054053846985425878141822830524758453130618434500148305410368525579029696362617714010305884917695755831890946394294375683943573127921879138173371545996717531476370145886254234388409154729045482809098660411410454270275664774942101471349247996 -920669166542525229690156237356830818436175940466238355662184282673561161876610096502899518167222174434961905536558542462290301232221870265010326715427915409925064762809195401491397130663954379255505586164320154713391064822393639666175595535711915077845712444427062204325846887562519125150392260095912629363409682035708007322212589445726976079069453879248843311943963910951076486979323374153538404266 1636817576908002888596997800011932842215754720181393510839619082057574205117203015148265926006628985181816429725700869938458577083104418454760700148068774841472491541316432878615633795785215232060679578215634705062237574585017575844723758449376730180651122315754667546978436475815860653447517438833854143542148132146200095092537883170675855232947517593230458427886972491109101421998031004207881331011 -420054221856486638126542367263908384594778558394825081621179515627623393942522902960952835698986750957934625617913897844863555556830553514856024577855571866936929886165458224018298624408831149574112719328953407962938066355094480807356143374450217503791992947786010439498688334019128289251747326244072508600069568871264960004797268376568783891418724857983082050620845859981868218823925064943476226214 -331826127775165858780347042052190967296566897541220149602758428200606188430598675213714590071967040303839103715584806910457517233738934154261967649180301223996179473074355273487540668251213827687575884779314277557851627739138252294857855432350221073620146302167206730067174812962215705385813096322111936616054724340465038864391366188195253999897520850925401702993785398846061077616861034810325871956 -183039373294182757463346782108153464375672965797448684561468984556736995371585140694971874532985209255003351503896370486172404343529187388761665025447653973336481334499035873972209692736725641034463168106960974151486734929416121692376295246045798220873355157606350821248225968554159225776598908538618107438130525565485380370172967685377497867541370442493650650872903351680036164381615132935726580758 292687109025045167383686460154193300181568087567954805609430543474801613298841185973037838344053611699870093885119315994714966385980952206855736256036079497583316283837947015782813725053570515865242947501073321899056846698919165916519635879639666820772831362072906532423425913081988658913974530185140229355959439173750605792158152647746102452718891336865186605383937202076663778818376661299634163936 -50429402914379959984143656693376931837563318419953125963923394671950646207605228864656172660303709095599234390102249181979709215493792914718401310360071807116927353653288016402932991959820604857260113061471650062359772554039199787399068489919081205989320443168777134872757680114592577350282671063130122077790884352441084599341659440779654847185582874148070855613860161242112634677909440379968096924 -95015943551327395794261986946889324261998671969964571694850016012711306981295725441946231967569691957059213147043839496082599164995005625766741364536262826044528933676713321702980455975078238760840403671577349612591362644427680805553889690734470494088321386147479944430896311166587801910444150971919106526216142730892164517883210859338845297839100676615493938358526525943995003961644578072893830588 6471640484391465130493709418497023965693094803190243740820153113438209805945161344034888258421922876339329360554885946633527511637706822966472797698484606979877826298022499590739081216409650444167970339707274611454989103875830592583693374765003866368693576865489087543483397006458334558605250773496896499508794031495400491168548204716084336833246776372199809324650349655271155378838479834606638613 42773004876053439889333004404714975403939228892500134020430857524908586394209717051356124857263080668979988632700137711561460794105317775849841478891250392656112842519220059197584892000957441719854397276081169802049835530855920039207146271567721585196364921512409025590378271560854870669710691660438209122518750790219417501100502249667839043513826155150263058036608272424074842010203375696121681310 7264762666685673537255972000933590039632540424687040991824386684900207348971377736893788040078127560106877385706438676017250658026379283231391680420981127096737425632551270246875614949540311645338023252190386901089299396780069367948559543161577272464843406612493011382859646773143390582769030634760503555187691413743389547663214218178144170154619111224079730073132810449759211303098347496786470070 -23284350530630006040381682302033537800599769478978988147121150410864541398409117278646181928774475296372602092369783326344688071537085024499218044564309231486691829493066121189917577627283874260375221783090309577993215389978216478540539204998811826607552378162843822156824456544837366687395178001218532266716518020211127347123964028550633437821553799474705180871359381890556540735884476229694730649 5019794698746804584258475361127077206914134016153453635617571484478257543148778228318453875755207221182340852564549055656414097640344302210885343623960510944309436164648767818371790750904361901766614336822546524211382931127809029895677750611054623259646184384735533567255392696959179769792076207847949657432666542694758204352301104457927370251086909104930342501987867626784951514728431554095255675 7906665747605416391393107831749427008387273752180427438692034361964056962847776634315630474808871670442958040234483029066708625550819222548323390848168005487941707184924623842610355318321879759109806877364545193285076966454252990659048408896429311041623309543606532700224512257913104633118604717260281617890985515492559399122829175964600314691082334220683559512037834070637051472098476081961916990 1962641151257666692855735959512956713541384318653604261754915187627135916991116879074002641956102024168916928578595189667013102058330018715845306362629106946319976362851276378946937714596013513315292107534431811462785009751699918521250066709978488817585084108997141418808854268119979998716474218191041155349529311948080000505480856868635837319933762698151343280057953922628925744656537771890765100 -5453896309687458043530846499886314853638474135639172312360046849591076075712868090298760267808417587675846319768231457119000759361142917885961820052070672936842840164748577737272676629986098651592263247311670331728376629854668622481399151376583865194314265627178769829588509584492004496977765376912108332489414492971448539708931844788049886440126918196015744591979847529437242354612485435043727362 386299964199895928636925508253131113339059648623952914546469062350713266120802519470312377637488068600371592894942483672420141462694004515583606793022880662215744732103059386664985962584324014536533950128037526562865523144046816753210214330002082681786795024702503170130906727924227586885647281443175674425946818643705655215574518992048854076339313285765275370638031133744437948483499825237142258 1898156459417160459953222707581344924528320554806040474694045511186621430599097208418714944186306436508325616157511394277508459506366731864387640799472611384187560258205666442411411796935526833856374986051422274516412809774921011519105757447693347662584264203572584248113652077950323819685867021325460955529632648081152922284266865650695284591292689130829610774421359865255095961797967281637523670 -164194817262417966845325117139868455014268399294702488733602884289499223353820583685257164923874092442427626575910611800846269452580704515673828616542777903538868984964114500744936435077753407598630363989426103288485805865919192291492569410807792647232097189297182529604417220083122742591873225891430611309953972275673369635608329357439402934652513577347862221134889274013870807975390703115095970 -943738397620110502740130649709226573031673622713533842839323807949801418678650446103537034797177669816080183799298005647217251649865815879930831600737011381705431331006546813239469328283865902720209562546857512135191507025272157942605652479510461621863582297913596571868075390211119678449559450866734369130678511563820029891961952626902179030427357866048716962354325474825310966658732700409690985 -154516848278141722746428821614559173053151092457789246568841675946293744375067908653822621111238610552952708597007661386318157700058669905913916810905822022594517902660851538069403697076774971693376085747519690387148527621347284355479499671477673420456009508232004322744656397931464876827507985649689421390034577345747543309470576359732568143041071996595508550726104604313886487741140886932288816 512045569509618945073474005368931600057296660024805790285880209992274836580852189677261053632994613855683149554961930186616819700443497492811502303268614913921494250940895046378027339243388084857488646295232416745756785135123712865089883590015569278822523079222626154562706834771805572047056183254585234072768722747747816782468540433078039537582279268580456170051317853785205816795927191748142274 -99140269198397378125610966582647559667785097919717008286853801378845369735187255779676826552246660098901969635989563219529897946265063202373772632190556059202561530469022695999451126367114515393094070004042322655123907380035690698389984229877729329375033294278827099561419049185915544812751817031678182979525600291143526511649208031594429762394474591082745048713711146484602841994314147020239490 -112294074525241847333070943949669154949052226669426014461960151846899087117250495468232368265163161163485439201744989252061607528835739823328700655295950683872426103945442814611915833601977294280848808100406227918024519916516056810666231766741730864960319707817112319224642584487000162350902692552103479385752998852832895702970172737569248010079264763816746236688514475656122468248553087868300882 -74449232941485639748766285193545324763069174112438312735428164070965156627938581871329775328285866309233572983679797741329009686554776497527286789006684688973533090084860553147149459508397670837697675707410634945711944252829861495656987496737563631252046869643251091686465582152498645310635292865495922319551947103195638045647345722873962399063089396719045218480384182450846669584644522205653910 141453534089728894228782325292732469779467923173023795074229306626829602717791466157747217322410985679424499653430752951193325455265308383123981149081103527922749152014768930785918072358897356126286879712304422501884116403819897379110025623334562716521340304733323599869429803072935682781757815171609078725926392817948480011961559177053455207706655001941519618484462569336553958436470477917227884 -23874364446193387556369831160524653793268675524485269096970471466335266881051171741293497213851893491025735193050663148821294809806579976877157124812602945574664782903363609513651149325769098875615864166627022431976204646238105906387356204473537042873814390438634561127111713462760276873372642999113697195148048094343963671600360252560934368084779524159583647914809972458057545913470940957466794 -11475396461102875469332497237394933375263652915148349629398346679956462489776922259858243910733069048163775369889883925327795346033414119893549127876824830378847609030510934065857176098892640470231401131380270531924900791852109857391604125624737743994182391119753307273408551310760263825782203177599824377228205729089953205424045314233661267130196890001294792642793434796780049818953638070906970 -22009660807059783712800256509887810402274341413801168550492873126221875733932531631664602270400098863695655424389444834818150351516060019533801594249865005934369805430121787861673133908904020768682533869226381317176278307183774820238891630887376583674157189446529623094573348085400244907101710251275714791665665687101954683619961790694382404394365167544739606254659086758011850586825110763804010 32575108631991621560400296768838247488693564075638068568207302211463779883383362343655181715270451828815450249874331152779581744765111954359067943938677922505209974430773321952562101970752960391969537901339296456321370666924401433508137939789697255276804251076427636090222834014977933351215102183222362776253446089818463177448610039599525157817495553538640367482543943533185306188002472451191872 -6728916529826722549503737786695490293601944007816284650506149839306097942876665877955358363692427328649713595447413535617683761815014411929098961781664902142363467649846195101256728361355664901048874941236838402226710838180441951162578754624628081549902318492908528479861832296641807358673674939231895398056117301005774448693947257045260579140255020027491968348652671845810465640704109159510804 -1151107510466370545546847807845143519700018012609141492962363766728017315012188537758772680867867087610807359596074139885507176513727684380658566111068285497986047197645137979795400907253773161804766278759519905809611017486507024028918297200722212446139858467738333664150277601313322176542750521208385984511738456600268210703477842659662215132644432983985925585374478465931282623899316736936556 -6111833834193098067782334551457376646932101376531452018597626569396733560291925520339720225534700806369872184524907493104153573111966039033099003587451615327922143775111136195459665816779653664862409403135072613937515417636797487711929264289784373805451289945099482843584962360036433719822888586412499173004079674357770669844883485880788765439834012047043463732209969078050475353501933591496720 6502712236531277487866837951609438930554875736001568878295172453747567574367023563119734836566712340189311597717767847250354702517337656403573201189362587079358911200532151306695210608578619351284614574305321963810703157519726740466472465686327199729678030846549303326910053487056612068828534875518490856822781803370383146027830208711841687606603810523445628190399802225157680071911135469445482 -1646671239843410502216113510452864292868083825972131596180205384131730032051884610415305011106605403101302299604610542274073945056374226094111480504100322253555088194147814183020257642068548062922389061305700454951627041631270033155927704844723180872396262545957632026137848246664717006445795098069713868106566337878767384834553344501593289656257786371022191499074879912234374196704909601170322 32616591169762429623484736497884038935586775080165538092289777095945721158783028971661477433712429240324443350419134687867274150143285798289927964463689529475966984202423914416444604341058599865179050560614055538434308432403819354609383022148111218000118512485954908990023052941148584352955710860240290220445983603613963863333232038383925833331704207976406464447382745540217136422935998203466 -1537366237500709970432472816745163411204984867628520570380717857855679038253587731306504219296456262176436395372867880507899915940864170370862914560760769029039596832706034262150054131950398727875685003931300543900288531905100331689404478491857594214938249328392950237333577432173871052575526500107479483213559501874982932675519117454424978745365575182265940658562617865379978714656092325979038 1353173529659860116165564018279397340615433179904438540520381593587217952277633420778255245325006337342096877055963231376614239417956339445073520994390628456785863342194914506031172812583848584644173337027253179994099207504553236743823818650522518217440567560474889781308388518488324623539865685090343466434020964602684583214946815139806133503133053117286692995394522815762630027068046350419810 -334419251714042973536411041062908309306837664964828857893864002055318099085240521576965796439767953140306781326547274976029697626571011815267918227452420087440435989502296376637685468402518696637042363196177733300992281071204644545952626050240033546072575877141762909624777476645896397987798425767966402182140969136626753511156111993703933848855092917581113284813316059144521869052221044194356 93021983140913131923040576483585210579243649400880930486721731443257280965979670134229103465303408260955467484420805390318368017833125237007818237047773538797451997636489932581439423252855897564493483069695454452582044675707747875704586468417023914686798602068370534661837452108067106877730829006387062185969134117201745179035842794546327489045859673635579180121179746866298828515039683798734 -342380414829810505411783523853012399259249469177221712819035677030689122579034233421266473174546868392317734998854866940285949977820061740800461944429834728180894294106439549211403864688206090326281972820761654927152473411742503494261434366862440258679784639258555992615226433824154365538992021238270460162345817399324010066921613457731564445217290653562136486899913775408277177982096737417412 291848663985013262856440683904156180713165585394998574508199656276699956527708376159050294998822136805207306122713444170590426757439775772046972622072731135545608978894543529215085547547700767384247349320380698076850488836795068347596148154314721248108365432714803776409449700678452992130316571895488312772431706513163228714579481468993498722015214458104163565147762542878850516515414685369146 -72266130136624627511952413766617292267336026996621117068448167555276729082142368043486385826888250102216001887743007126924876823102485203520059597934435369809489255668418728503448362252059443381845728040381642904042872076279140414522853722558767244003176274225786797704602451501748344856863790542929307618892275346861214371051157311870023701584186426290908202077506026185777294475461149889866 39106716456948832360237155768914490139991595413390753944686280330125919904509398189900006123703819672771782177497052591385381553529865484045859089032805067028310850514374352002463204718717227906250165875138137891677932499537005742875496865888865440771641552421707368957146919823089338692335994710425500581042009446647543390817162104183727016574317558003770360360709210576868544426635238722026 -76723853016055450791262668880145447242186213054708382674472124631930794807190049561210230231887848886807900754759699317068334769197127036717972276508541262001748015138634312283275884081944061827311134049002605497333330597262709673526630317510298580423418373849432541779491819306408198171368475715675392538042140360362102962373443179712773011136064054424770721076207716232432119150026815853768 59281142250616103229915739153304361119021631932875188106047127748800732121330174424930838066962076704498686413325957441358738473412275941760645942071530989214918469924159412836786053827676702779187834312777409516182131336723118042954759320635020443326846146146334176115649581047665302104534025011016846907981302713652865152859538750245858525322984529070830505083908441401718804201658039644446 -17321467349227992685790077775133830002827166251312098895908568611107248943232313233812559987145262745145966264357801344468676954836314313705882391703805562815784166931377107343976113217505704812382755558811324156788430566032383313664422730462447675851719643094758708791062965149468389482370543237514300600003783734019892275156678861409450421863915688196985640811937669414546556280567312517688 10990352765846094971014511638323757230078387808597410111637472541995840423702004974314934566886962647999469983972029159001666517046582676090963877716418107392776964952532068868827863230734629485293242569805261146112236843910188886505487577208108635668403428910213771036115533785124351728704322596343760100531527726466994224745257495735132630500355714025092809236706658221279891867434022637032 -17607388953236201356170470499343250411332957370633329124064772776246371291815395608137539673756970649097027237973428444786297625614915367162341781744866134811067789266142234506908477532542342301732395701504738652057129932987290125736287182678469525125621670955453813460280222388745478432709269529950390206115718368269030593988904529933984815536710948246328100955752427260347288056745746939090 11742835123197239794771443098160516234095282673302806768502526668695919829146809145105678032009947751150757502453530578326211651171481364317552074984904009700173496100082652599816653799117882211177087489012733318373586289327875694020899158252388054363604477279694028695612712884129603401707836333973613416492972638766143109702859597712664424005850913873426028999684699089650622424419945968198 -4022679341137599062154614977899389124120737755061932885001697298751466824019427898394728364016132624573362002669705054543367196065542864037911264385014479467583827544044369862517568506259386379932183697656971072171315843337750995000739164732731738727786618507251091079529203201836554120648589249286500349133111413253578379745156980671192701375673449062695011314970417014561357877771780787998 2741132657076981342340389127345835771912901701509130710074736573758942369842761043422737337166560015560799582964283629941369074005240051679555522445140271595966551141733245367208237059338764292818688282972191512248251347931655423884678124783246199062303777550597986859263923406608223403236556809285948490373604326257227554354447838568683361825959151552750932132467219334134248933220659699930 -3751081606785197341492558308018652386480964690120131789855769979497152618402392949141925504599632001255220696531939499385314574486614999917902706972450904881161920468635951972070805709184083571527967160391460397878797797514141534415475787525625472861298388298308601977281822301328883830414420022103131526153322350709209864846980975380358558767309015365006529856187529067731377094397833679456 2346584943167114982922145238402619286080367556070167046172120197836731085916445228423757520586979543665468870966565602142122282431908754553401460993198570395922968925245290529550001399993738600645155502750337813956306166800001990345410828113503646657032562115046489472089422082011272905103609053285574829799883058428513403398850019652477929862952879794469545207927165293328570460302708307466 -839442173567255886645818820221797878043794429270663171384762071980867397152919766929058732894385374118877017929851583238768676142282315710593318241823770527954610263958928721100046198313372591979868903109129096476781412663741533272294534440223881237651408896946207496340365834517594080538103477223410580409089609226200496204287367290346815065117064674222317919151334741239611232397306946864 667805200253609268421044940826902373154694051789405445350551544103666768862359203244839741984779995889041511375380032337939291957606071835486941892409958503829531510795754298919889819296349022219004933713083639243901065947110060383942296131449909568581518700096790834556789903457050749489575477229225299010442772794636037660320647227980949650731176886543299560895353392596161760500385418406 -746259373594939135967521462125886229401468949088848921847796044514628796770495204049478496170404461383167922662981184679163670082870893315650181772332283944491963231232248760750306302879341142744934683958304638180397215332558777827199735288026611635722418899216012558038713150933153089058773845977973215913244414029504145909862798727540545037355355791938668972738638186106669817569913126643 453696957120831769961841549620557170071686558122827405358650563435417524600778572061329168012111484829210045301546808222341730035985603283009035736035771119531132957364812706574240921555005291902994354016566104666952846196087921284646978367689974202988172922781408847104681466203650906366389101263649655074647461894027127726514654059872343751507235435564157481628646364858178152506354806218 -163931691111340997208796301708251778659335342052098425062556280821991588640714589505383808177584393660975330968401458864450281242812920810190257532645083621525022017046874565873744701645313748814726852338810886743693321696529125739336435323359315042510009492037403465650466650023391766060253512618858877233585682532719006045805055650622211109598162150430137541606755792147745154833076709834 146501645855334398573888261425014867486024079248789670005716816023661792495730714559369236532257787671517371619126414709642911023198850794516353769509055869071660889362996241372895253770744764538500115092845974590532768206543031059984313842994498112366926092201834200746092892794671613085621513076385691882208842162329497345018148290436355076009126900086605147978173115930078809839135129587 -145743201971827971557642149921475547624051301992889414360087575008371268687808856283651897698668050061797660007636913361936844345229221970637460731459761091019452925681883104937048687244936822162151981589725861878981262831953669281662262382848475187772786482106030181782052092763512013066279723924512288442448839604409951502354904838047009805128241245593226831521240848634878134893935879690 81367696970262265449943920514712224814274412866006506817718350144489071445811331159539069817609653626153055626404775770441503349211606066054582582647794859118701532393526289980277044268666284008599929224838581131470318375154127819179879283161365804942157448129536256993216465395073933628189096565282692483410419880409147136516474498339758217823019732013294912834879358509159647349522743514 -32324296397122082198214986490845758593937468463524811328336020909189350348211955459849168319435879258940294463832209331477398880293511177673850466759924696968867315011212382257590102750516983507787018761892432788543752029926779408845671974119946710599170869826071524028223019540654675045080436250001595386818783952018637565119433637312203924538552852936184703224508051916587332795204656164 28837377039849024934414948592124326697941942622099034775994802780147559650114916832474153527463243759203069783319676117671075755635125437878909790370471390761336603179940136695685168448877428891826160421426738369064263275660697207665222009763961355666620871011681205998098476614857916143698044396915048514932416832813789675543371972757045700769490803554381752500213032348137509142345731521 -27599279220025088122881854283691606306869197903095508650207415902142281218311742013391680515400303532091036469292334072889875441990566081469444566227961002422597677190708438419959331093060876509128188168374834230143353399257270956430924534071181430754066560134919642951176110101866200979540156531624645891874900014665479847875748644740856103053496086886434974828486315103839133928878825218 13678504687310860689808361218648968568456971684656042382335467452344619816468749169049934747934827829654813932282987301103070543359827090460874814025089012068889229128581612327692282118369967811132246583434709112549664747872568624157266649060531207103473729280185367810125576415664859249013622201283790693725821662983940177935514981321126781614293982961544397339059338033851806365388305042 -6149296052670575187093673332845081018915254056756757232853488893926893259460854941380587044009775217875494465373762535442790124273181489712627200153929180690527709951758669131830517622755603418171933523782694169484220773085827787120985321894937268500438399614836971571587658631059518240377932278799893838184824964429864177251880415100660257509151752095454463312431503962368516246852618793 5519743745815172302096166648613366356405926867335189782413367418946870363194729127445780502373513187557098999029246275367917123206291957936263311854974307406965638917560334191634108672755880919434179810106644846549349207160467060803802186703956787797734975654448200404062995822826967138663900818932289375139971519833407684181441119862437049174278607127572994501821204542145834121112112304 -4866968299167328583589338435881492975538511734173877596194546014799823783613160718868881836835674719409312225963095783831068387220957794797085313497332363215848079048384590980358586495639902516229769589126259489068156463535913186992252894382087440872271650011481742874282226762089924727022322386403441102925820314547026956336478755437238177410465657070659416178387832972893821837265097774 2267946130730136104835995838511415760054712443948163813345288276639781622058158094556898785395373733449328315101977424949868256004393392202862649739411514032265963251747288576858055678259653611324970231282001475459411059141695444845689996030105372978865045157014177509610132500478455870320868146906511412825495387541868207316658379066100961234913074540745598124634371131176288749397771195 -1067701026354928894917187854208711605648591230576286957104425410257657118649139073728533397005262801468460013934132227602626996881907031680901267689960568649924623829319126231354254795257811057407387191161147840212108870920388006963404372885611735832484698429993757367195943916220195842015101324306507016814850368365119055286420582030858209386410526473477807272919403086768156332226841448 1050829874012031844002976593682769528342222595813780859959714538698360780780112954051961743075668402736963650188012667772770692569114425437468068696085097681687905666766259601237319754764478952447719271933994570589842674612536948577235204694361054120398684045802720981445984645541344855654648827130040691316660713819609111081017450895671625670589981420410081129486612751646613512916210528 -798628054190359691402364772291623142227664031026807783620180444503136814932934740396110842562591046462110159822515859896178634791688550802430725889801602691094808260550096267978813687647953126217234187209104188276983386048308331909959418741433796495134275424657622505767033123732295286368400663713091302151714805911667957281367725027215302809852932983737622069970326435252786172815454627 371127433848095109979344078293667834519622134576541588845559907352176780873697580155731183852973946936521237021519932952566764846094655188945614773168840868108928570059469469385322311123473743596184054466680118552695129500157221064844109231608416622765703336583984211259923990129544497012074967992474767895243595936863978161842339059694877463864657323509978358158924488782396756195761315 -180146401222489387967031296773346382532920314690781506680950575494352277271904307181505944688698048907797602291391127296075134605025575932003830618636794606943209141791688064255941569372259091986526822497522283697285772535239118814895345772762380163634903606955899377996491279978551401323944254797339508789398900623363486897463040104042998474057350365736551330013637469981355934590934650 188556883146003915717110650977331637234751131781035818171261633059388282651207540568581711466781934664021331056897781845171177909593856083463174049420495220660497380231887589985539817893788674763215849230541795141944238852582896747589382651207775636501513593258494090187145772325238388959920661989692664011407758539279050692300721633146382163228614466624581972324329351831701187082611159 -127248072826650786037187412072227491246665347144827658933564954231575670068881603001180867672410689281439318254287857357631134978146567719775173129325420408901956096301410814008819863215607792340486699526645319139798614460011479611996703477545493137402794210494275578031582459357910037395236240444869751174152003773716071683567523671105662722555048250038497435309108687054605049456095524 56701536333857603268543987758827514106329042428266220500983366540204485899175487528055779365258784873014867990708016527149227673669962089206439350640611809955249747725059627466511510341116998107791878726230264528744559918739408008988797101936076854769056242992189422972723834499609697842843403074388910545588116354361806533745874332076162145626125396269438304573140680092721088306151058 -31948988433706346768384263531740464873106046351447945548621797952347349114630224512724773910336872179322689021265511180147765190459124686447846786608524401047810392249512077225637519655617520376579638912359987852521509955799983478557224140530316965914570549727970742492481097300380458912712879197251261099487512262900850072009099510353709063609452882555429392938929054188754555903223903 31101878376563045976708654608188534099181560952590151139625062929478859983339545803904613613439190314766967443791185490049182641255967068347478857868394880630657349121053957699229442802615930727134358464220219921026582718643863926571818031847779132686300724643760081613242814548550758113878504727487495114489333673009513608633748369505466595988153214724784062499104888993200379937104521 -20065624353215457397449880146909692948787726040171810411153276760333515648355817431674812418223219382045149408943674594808440649124492907161305917434496265546490116536557063371044344293094653734062268290094203391680386130907809719063173176323044988674812238867085844723966166073144733581988149286020617420124724785728913104979292075630709595049029341246836571935880154694601206460833808 8096481050404770951424387343692298452029160030539260890928266737825072615929690768208060677374112172477890443050556622206849735652903372460446230549899665498055318758315739465641081944842440186481824848131361720113296286308065992583751945633845085782709591867507207476928164393427649968281962859511107231751617123406094556248652774238076502499766159999287567005313453149752200315658987 -5642986795091945654706057328171784868165132415511141114957038844904588001324063533282514368576435609068869851467525337162620869885303210847446041816089772573980063905770108587778824494500403159077840629160280995826069777721692725653679793425394606326607994758170651531321009066109009316675908960148509989651652958071122817092844161904913687713059913947648013782247654967667710265038700 4905634887630201838721993280241409826572482915553994783248615304732705412269423996375062587342139814655596282357184524661339419834199133243695363994067529136443351598625354322744746747642638219079240686096844928233678149934180667425111759608475988242944603637833243941274199655073135362213948959687700546732248440451509859209277679719904225465543613755796744869188074551077404196869982 -3001913247120168724289643364836067549564475876500707847587799395804584128447686486867862474989565214523842038020070773118795743315670230565344624723751877972078357637520050036125029824135768866987065640546979069840259972485485581693674163207571958862942952804042521825305184051815943521768624449952467958085864269041640178649297056257574284704863520475675166364118394199589331153440248 1183803388165782222153272382907098827249715125446691004574117338259619625430278591902510661149916769732929524235653072695775915868355070202782214327237215425309500686378143393521557332358797381883951188010636684184864563791934546169976076006992746294670418400375033601675552711562524554655703314321480765742492918705663286079919545027997793934739022483299627913517061450436690508355737 -916768106881122367997218646501316452459451571587071059823340007977846570475410847600022254491612828834128267769002685775779375329671301931396320308622009543975586789130356455632350284578311422117515330701328660848723833417347302742700711112414212802258172770848677320821043395678009054825811872812708662268819106669822251791047447825088811192010095086968137097061269729759416770031991 770121142361371978471219258666542784192580931652863690710581572694494358021480921433746666475692531134013430276743489709458951331051503391374223136641140544376575009912809305359092895968334534480850433335908124123278023515683056664257261260288314806050879608771921232024125302551998792731207251939881015469308771953691584709226524743571776844671386729599132089911892300542963281611652 -411458152950512664219611285668231454171757342277035922679949721603916455035519388031894696945029440529434636267612969577932174080110580857951189679407596660891579418330596085210713465180872267971856340903603128618505131428670926294619450490388102648856254703099791314965012354701652720271143035725384613891834652888928063856970150051486065069385043619272052165296281770106608995722004 182392096677447917404844973488389183959553333041627595899174284276927653720889939456693098781225213115536048811248193214849623939663253098476736603250626566943930087751607778066488262945060516700263427876807201110366269763701642165293360948890742568174106730451976099801357313459216331889708444421798558477220255373476395452784949608357705671908259255700045334091407123801227517618817 -139320473381627453415199550424976126538392485071237433893416574626726051127498133262164973001329672607954937157578338482875132993300624819308146668802226397313889733639089469265130220321538807288550789872960033163162423363289779989569969591718630737558487366920427797146071877449484907784611847300474814028218943455492427445521936811977998409202488824296034193315975485595269292384082 117018294729851079964021130367849985618364881832621663873687896988033488209982353178770660732698595495541426598000423096629804387573580348873245560234346983404860196841420521639641905274788477768071031047546078965446363515404974545230768869914012332941703735954005596640804960076037260147080023798063581260091141404738846575068133923837555975249738259274924665581181666608772739446530 -54006461029849134143028443669880722963449234637693267904051654222087660140421698288712720395485815276536439541735467407232481295389503155812267113136626518226996873004419430097409959518818914559765611976194742941965972483017190581096146539277751426229041568653884228194877107564733212313054248837257948848072781365945507090946202739836746931930616127580801502040677981136681263294732 26992971062949177630392601098281035903453767347361955117467198268952516437000198265873414063008721178173696345550912004002630281180477877268614932911931444277791532100077263124736545485235354828894899969135977584851037259772868636073613567343802621022793760663616441785502526560600812405722367207327616048415580786850957957339249942864295704422905323010031794474241611726381300933587 -21240821145307365149730057721557806855569617081081658808051061201262176393600773425984385114170365876236813977158985523217142121257843940727572105290112358399830146670027095342726538679546148050443637280622115265980360154330808144509829730848167521088872900358926260090310833943807924772640328224086523180181767504246154604173174912505694202756731370350966104614733566389133368043084 16305422027677989830606380163738512322793132385956797275040977012952192818231140066856003776954126065747145886100921566706871877535512958103795898956385796851791904790608369469869241087459778624233270934195541253027828457283211885600495570813660282753852639839029547289225848518438846076572995115628425144918916437944896346540475188444666370818638983635258365810079244153936766931204 -7256131800545227591637288399856079372118401332666680119106891111816706321590665450648957850150614229857433811142574409018802175025255673921226180025093605296385414283847388427147816173965804467856293505672590456780873389402671387412167261668785013210516440918892330216902021547618403010131107696424397773878911271756297950677956786247975216668603041288623308201397410189493263488456 3663528671970453653952156891295571090533763938248484202663699998682828231992571806588409824525757804800978454774152315772106759042597576114003135654625946278279636269958860682622926450119864797301023968185118859164898990854973076234513289777818866079747554985725482961326423381154263591051118639557578751155912554482405105298725067692168666494454321078124679604047955768489190691082 -3253369791803727598255472581687030033707865788308959352394534749595771489728477326847271217780951629152538557328557872697293743651235583684730626285085866215577844710303315100430576403145507623538021446500198380045528985253572792179847085025384875220444167286614573651317764713166453282607699448826905720600808814499515076229671775849639109576613800873853332243854479260350144868801 2097654374468651037288140790549544400616650779939082004842569060595682518107387992171977696321069139608861283318224339317459699139457523281892536375544203790935788912278096609387564377001963956803408798709635209509215184895958353660125573707722907576568759519517488216628131152957583602380991724382735970852574898884107098927201734790234205288490081257566098939917202934151295447952 -965817530423343064747964976885652817977970671656515401201383729179543516364630371879310903296517879486560870689628408657737406290211243090793862297288074929014826610373153138788312132672359582750004321599021373813915020915555767949032857790211544669873085501576720415660898287004292223113402498942903877117422699389700826740827707110511449583432772452488955979864846022041243885863 492272807102649986738351460643983037448931110337334052322131076088356154917715169665691586342212674887175563466725193423807933892818048095388102312554939297177558274921529683771122046319788058678803343811499940363813495826353349305671599850040748364421170376466318869562316059505498238138968911133228669776260525029552139807926715388919564087425319257677783069423280742096561894839 -465392061698411086826722809006899165962071589636531138581069558076877077605568445025774438419417040880212458151213951643553713458126189526349060182362654016825856749032481870381977811270753781944163118114694774885413691049849041839317189936112652983827996475300771547818325849502053852993537367979505987379530543005176098251269287038305909369124682563362550160319163385077163994406 266096565947475346223143728488889427792492214594379306721644136268372480531464720020958754313164978558960175123224299414408620450394143605161793182783140371116517385536534780088997680278339619221592744819943667755561775404256617988487651680231296563831203294685163505223674298673024051264520214544169604025873562750464198624837338161875554542121886547216733577529409622481659836621 -117265741906730936814685126560322787798996561374021963776099013908685400219339204508791779872322711172400427784459875358188883593247457216912697892686562687100006634883474399930741405488367297255325869029959017836993974088091122272003884386668705919978915343135912196255840400589835876014007598636720495918913436536930086885557205605076746469884770524566398411174043004163808062157 70547138808001098208252558071539330828056646148372198011124640376627511075833921034614875592659202979404239171399511450934362413934362312269725472375054321806946205420470596374902300092572801880591421730971440754519026687464929647179760618516448171830869977359965631692206380772174046130722998428575373641698558827200826657247988057791504142601733378841941445786742654449599658205 -60143106274459578222780535964806560437221798904361377863935295274005917477077575248717910203974496420372770421898646398303738365400348886620884296653741038731553923931370941366022204430231896925295524353101068274817683764782020071587680469521096998887331698404195852139111723408822655052954241756640600748178323125760772554711608587639976364354052796911124641190611926363463232457 33900048435287502169407726444972923278397573969025281649331060195312416362085369457503192863295386858923565770330493505592364363219931100882844327161187866958562480439517143725065492105738700857189914608071916542338117357823064371559103247916747741099123233954406311905455475181182577869283509295998340746391175639142624805638624133540104725023596010638612530038002633352912845408 -13155148448596273591013719229729529312974118961015708510242331626797988862726798839555911189108248183329184926430877073917519838992288901180783603344591368437608893735912912971362228923517273725600443191425421058077939520877956083294588573129196541311209699619417077668733257193202113919161100024139242972574900870507004053271804571820972638829177148304236807553874897648042701081 10080699355813057609379509117244473011067397501656730444609979435514925491899313052085089577015198081466386486198656319244706707251032463140753426981398139800759026945626938944058946903619465102538527661094203589753875571935265225870135170569319729903558690077942736362731698247162687103611964427635467297432148239601574257907571136116101050184564831616226773549723642474256928977 -7423091209838449069736285651306189952203394988483795398857436116448719975639777526956182824734720465538662589606134116849623141116064758330692584450194730285252686328915355068729966021504132065410710513599783088012156437242226216992695348446044834667747545576064566553928964698176227669742600974498346727254788124171930130705475889971105519491659535123508908633713897009235239896 4031541577785575815113632391008747337173258915789270463441834874631848980645985193999990658589054512044936323944443798625789823196674960358163239929575952435118092257952086656775176772929716897479583385121549358920785631101416056598588693390907127449016762888302311782214693105448131847714387471549407274632383884201265098333117568556241638319142658593855823840347681142640042244 -1545492580911798436869976367914436781162233556697549300103637629834433081287653781977890675198347482726966099360697431773807126007596284048454708376739878656519132514881819779585750671045643008033152990326109939789249171945144874759176422767851367798105658873548611854325024125995624372742454295685917103654720319873378406501076619146439676851977359054158756359453725392566343657 1298031396593709318095848088845058067488203195737894964020894893144943807661611898202864665960225986452040738802085098313380189467809633833166287563989899822257298069254082515279943863125741483863309692922420521943653653089092852737040426472064119538315484690672950776081296332546946690019949063397871480144324241915903352893263023094757861435082398930030375986014211074895410371 -931693045834295301832025870031830796779533559587983215712374270685929383786935893082149828025508713809899243945074958277192395620514374451053522845657554183839563204051071250177651409614684901028146317056529992739692672225751294820620301927180421084613060312386679696673185692395185132447998259313465270193991897186664171263591802018067596150454359581486990453992393326497467389 424864268949938979956127574431542060762081595861630984989809358296724847945785765843626194247691581455570445668118390834009309451386614841719613794587708089236457576379960408828715890248439551606801978861955221805205590924835115478959708821999567393375538646393716281999848945602872343830076407017730553384333093894298916586734073775106523011984630210722357046556148911666581758 -199746476644811877448115806959374482543324647342396084582345576135496016478526698963029882837218685035722125723077609125194028982606472255585369340524425367099604947045116277969851472698080279642524235327473526540076360376190174316352139539875733070533720398210807238373202608072170891816794588566170073595201814500625739416072071919879099636707482958594154941275309619933528328 153338828461269210667911108487743702931119635377958686645716212187921855579897886107284101111617971157864494390330031652901793241190700952330821444757188459400798191558442214239565305233741156059709604588510163762374964900571430339329336035326036789474994005453290211912023001954617661984829645950977940971161256098749773373124319534984954513319488609422760424386746614688397555 -113777211826154204919815641718364495487682217516155648702954498463395504081421123123434118087383831024373609596167581599963035601010139142230285691007575617242732120965782144934681870638519770931685093290639710906795639830348151174082871612422014272044587023452297155405897640523092147419107640981653684385236395409034133908686186236814665284017788648187100309930329473126353782 42502984498329361994729834853390890957547226812821489899539489210047018084006238100544698618907901369990425985242627095414185509993994217023075216373676244943069123086096871429045956775325304485279347993983473072889410216884339984359817193594553019690041966882385111578336843573680074402605492055165075158248244290601507177659097847754936297456416743283306024779713679455151101 -24466371637111371196319929254873043881576835579075456301823393824928935825738363642600511113160624254515330206895553069268116955771214579544314271836930572596923767228324790421860803469481134625943057427697258155764930224812977409218029560488679244489699488531333347328675436110814634519314567070489255503239629560680620447560619746946918706342849937067503021153160657332243024 18633658522354776934210640531268235531609000802778175383499139081138728756822711102793679747547663538770361507977577923362676537045434927205607144740956502516357796541422790793716486968264696729598584258876155866079535087171815652909708676488273673385775693928140971623105889266427334053544668833259826597217677630613317183253705788194860883791979077268424901976512956627923433 -12298616305946585886995083067778939906621567087501320851397774274419915882036096875590802646382671650160955655569737082731860014190903553316954112916955481206135307645645429451268362097600039046271511821992440991605224811779013231506228091829367746516226777363563526369986556246375402682264915487872154691615450098598346671140863100839802339073247463452129823273282240080479535 4675569388101922375437827262640444493587296118221411606536611393218034119092264999569146826272405021930235057471362137322193313142626291447067764239494398580623215371971423800169720064248061419176994191693342766536078972522727905203299930342014452563503653936602674481199120045274562643734723133724770127147636300833383889831873647806119532980017796465789276056320937318529820 -2587126778776516697841115641970423892784890009359756515340310471687767576878873292607439390738385899291361877399812053773287111305020636214986762059907862742465702855338629496414900540515480061472761124723076717522810888886435166973529235667397826402736710826695457859333877981247544153348097543201580293690890741476320776126929493638456098929045336909074968777672672715873590 2363343911787044065714220730742244250856853957479322827381434555841150734908813078506876064165928804621711237090195967912560615114842984975649596497382387316377239226316483245274213404908708901764108596451037953785685955561195918077875348188390468307632878188327154389360577522551230556816784554758405242693841790709944142002383760213236568426914314752059612053539008698470091 -1180176610426973491494926452013698111785694944780353695788282724511967595543327832955051300291055860682565581342476797779345011242812566545423741477142206757877312011499640697271861015897899925436696263627375519603951654179517345015763539427598400921261777895053092742349353303561750672911992859634880299852697594580189662305075258125532560632777385714850372904716350729989508 526242251677026811916721325512274508098938666471651243906136607388830670697985980960161732643137926923544014917870139211056341835686085617963696313197792925208793771060645443372373616922179007780352851795435697795360328978596113587490755290854266213090952524673671970535169700478278087160931205793710140282284640076642278380920917497109504604231896426298076606952213496816114 -274783079376219822606993614944929989765309648567243148021714457577782378464354306793539157305321589564431464765582418123404102599494382240323186728413603433938192490716410878436729353363219640706936955132467881052954967892687968329847796537972977752866347067712376265772991682859780225986148282605289349781514652261460313967703638333649194558502290113251022535606852290660644 269225231963838093828235246784959769651277440304298635522459903643346485264926745505092848977234139573175894560328274129051862575985904560174958706450533519833259935185429180381712917403214819230037105410044486779715370768314597707689640469594169027805900724304564150599246403038791923174559914638729434150015696053125264840518306341988135516239913850728574498480257478585041 -119168147695449781922203203545113952032889241155042801028209702178947604168311868778125916477623038151743212788342491306784501671253823714365114718873604695082016807073072860546523761046114346500332505441074614080072997692963587539201449328539931300299472459464882464587506283142103218715578511082945060813827695559953092687563755269222912383106526988872216329105213554269626 47949618721059725764079977265288002033312586877122411718386847238183435895922341099948070685383998851955633505905797476708671221853048534751570008216926212341368671981019692676748979566119028564838259810075839123359313353036756450432568982219719758614988235281581737811897783459600011025549669657987172189193979209421924347976562473721753697859370165539416498427046680409202 -35407910487010826020479189240078760181039506732873182605547091728089725412521671438096543342047572095937739889693169581550778708148847395001725418032109470112308072699753857960671313176415581502341372341664564061061504628453074814482630827435640123275894638294016040381986263977428192363264424342066005605495005203382445186092791315879164690571131116402046588666843439991108 25594113639239149926835434092739156936993123900138460883355237552159188318863185295583478736506978109968335548395419628522085746603887681521696494024486454717957747675477916560766287596952748163906489589041425090164959564912889800848026598322004000285239562072392903880316466354690017827076386966079255973392032088193940988799308296516824780248133831304325929521548991959086 -13084726307802820638460264540122079653817049839991411629394452358120200737027558979435072866649498659626500250802256707939755332906113171283550417160793576411688773197255821133551766900833681663262648008982433759226376539803303571915476570479637928847381961725553891995272936277856104608680517263163980068967646510185487321209520701586051285569150126157987808073949220528200 3649997852973190240846703512266023944261015530806904355330577701268178793769138139161579461537185250143514621864914110474522292070621876168894487751677137702270068889757904584302861127774328443118956983201791840315536379042948121182896793761265297776100705109840811031031052591993591263327413066509322173657468942466733291279801005440214727809501077546761010267979115116008 -4306270168791130637656053890061226481259058957126572562277726560030362882756070251245314806217120867494226663148472648192467813697932789003077856143885479481726169785109297782604337493817230998693395362305606861471568440033599840533975203309674116728415439421099621204212639722349770801863105937931427635338886607378083173857697187744227218912734583573350988309719708292151 2481469833115749627120138862330024783883533887686773051275404489856065221757003552979728809625807482194271551015382962098909078649453350586944728768405225407585464406151036213500391574399387127826806309329395935411618850275402568723507426432529553496139164302751140843204430311596554610761179533010180302161017542757422967102028263139837634488131703235415302847152321072206 -1153633348248248134290361546884843749584636612027236870716888183365218323954337434997162249442292327395911873353822042614585829809290551873520477542956487636922897154717178538781611497612959272324268548876891421581838743209117892109929621768804422670501283612699444864529513634523361686628751589849958808660394064604902245695565081541349749296899176042625615342617034475436 416769949462488119028079714876624459156425358947609634709478468249876472807683979679342753707467714419352064364352313812068140100643520687952061769435763115048747979371338002369375609599742186688730223686414218407882534548754589676380626808806170269900310482851037003095825583644076217432612499958996429859401965242926752119131565846740242622054060425723637106391055017113 -389063978846132288903184274679575241616066490093608677430149085812524155230547523404353373041356502529268180624241541992883044625408882932806286531834105393545152751647232055201043363801613998620786387976978125005087140973745531883514441676079464731259044752675841663982981660486136690102543928419595618685067619944745210120757822118505651045853698982114262187749531009117 285617638141765139926414878756883934082695353206262872141363508279473694689145016098268322789592839203855307858123861467937162325281275468995989433724012215957396716820564595209622745027312495982710043113609999384874937708448431640097447751525032517772446274543830413190787356288437641041539829176490312498714932700005491530198738670970645293558590037464721334546865572204 -67903084594754003890265180500217428949181323427307730818229353581049917978664500643843881860007297257048629504595098637702071855609099294318425231716292827276128507012649278460299707293663131762231412217909833677664970374647679773467096118119553031364318803337901220755709233425604437028365071743008464095859036069712832790555176180388668393763244890652608195312497043532 54176289693841644345621495076978803129203202806400404914364359270408735069151181290817893879327072127425378092113378224642143973468351130512701793491482181717106094178105014868245056364828735944417872391718908732329469412701760081368697478302097885653170271472578366723777839850976171665153915780123038666263585916205715582483769907385202532747940026182471618310441515918 -34461633285841750045354774664087660997141881199402573883693478782346567247443175486361281074634702071953844123670516894745128281077671958835206746660828885416895288445952088095335598281990066129137174353976294349472483958759476264618081244249738228078430559871017108455660550062676162356610918656718577976491181732609101401203459987836748293110299266956178375752238901584 26728866551373797104776364857330688856148142205612865048894725208550163598624074823922970207989851576196260581630380919541169346936866628884961671044393841117188872280039925002231287423852281550672084604635931619895622970076186277553589561369879981315957143885906821657003428141498398617173914960931745873453384193255184764567222057987019535253038684281618916388245957984 -5743793769884525903365753208536461320379286610511383347943829216935235599761991471481916876136443307846267719485629961926799633809577007426361107297294399251501033457843003967349924463119701048260492972403682727347366848575973166052339105626826767436130762780069214387333718577966457759202411888981113990720105295964078207602411545509676007263356991658630540570032674500 3903878798153129357765516583992562232754129615656978604766305684485475778697823318780837315796401197941566363932518077760010336534693855523229941565896081588605977429159559894254216702842036388965435891697130845843676821518001709667107350342573872691617670961970052514322432757243728703403795255725898320092063001759599060928582994165057892983130320302136290150782441165 -4506237149665769721885048916212006315053347405094050376332393051947144322442966324046662814191994934778691333463653592287945295158561357277461326701918139616778654204646281508496186710991087184973860733062132048821697501883625882334135566344499184331868465813545524888829934861242050636625820236233614402854767530278764465241070300063116783550658764775647244094700339178 1515982946930180969290648752052772180541253620509507537968125402713962461360123656437534181580206050268675613184761722749487687090445169163593942160695033422441251016433633743130315156687922281947108447698872954436904810456775624552097365159116736067392685845710777285245034170190640395693321026413981746637868442905851494522430310689440685478359711821127341805228498912 -756477695447434064917841739082128148261150474457942373121516972644301988721580150213920842896571153350333397636857318937780659211130825796584078617784996943017861364684678148368983296811665706303127434491442151381577438755899821429440242090312717539835813755955712634107424646147156083061815234007719838130383859683847874843236500756004063492095346459000297064657552628 214093182084180806930634711913424841850894127078750807541639309356187135240105280265542757798200808478596505045581518646436365973397248509171646807855770972276499553306598115112395839154234618469115953486890732964727315172168394112729691311651795288043177467297951279140594516385251250988077643014263686905524749986103739202044081571336889928480687240627316016188641230 -460711054717326912501200476871465016385269946314138802905195995014144224821175378442605296699587864340205017331135557788157815335784449083268407678067343196969026101440556396981927245926930831759293147092428173610889217581809411369171876078178021048568504736880065165745379661704770054920112915051270456943537333690426881713034974935659953284393931550338272151701188084 116712868822691391231829961457948550403469452653926714080555341162274369165799369684686957510056860586241717376071491810810723995664286813721590214311651154792927106961769248478236284214372753319849333217540968298240532881783912053037695653875687083969420124715260027196016732972941294929023168891887881645634995969280537715854778157742694356105790016356342807640176352 -29371733969188619953360685705518148989053250863591144893733568980155661438968308553251556258556072881457929772301349983142091414464203957656802247663810986879275380406078863614433036452435826756757377451004418615838148574258056780587321553931699914904574014619198794361696358793652312491532819764906755733539586301246048113898759599317893866180543036433141543203383452 44748498079601085926622770878361639523050025491098892829613384501456364932538738795511260368125464168288402161634075576022504838774360070164000979697471797285432085327699375412760199762906703494969678177108263305239832539767196137901106750806206553319927092454771186862747147780697606858422740881929417241757874638704931574299140267712632157692427756303319211799201750 -23643023197596099387136295387215021795401537147084398178586936794096474334256408596984702621948390733335701461175547664673723206615636834328904832142091345539597422338085959672844426373148261346088603836871331898165095423096099370761109960063139893678673585336303323365249809568363989508432306054067026947160932308638559356588133011235498643385660435378903867283625892 15682499571159912389543994946025937923764510087418969264313623582177006371567473690981004662519462804168745185556312557784175253656864902565703027050962789287006157088080808263559611853065400637647077791945969794822752744761329233268077920166942436938382698498172030024892189042651205721691055808317469632798284987106700245248982263786046751188546045897078697540503440 2095031350197183276906513376301849761325159114096006472621570419807982754572751479244886228918278930784366319051951343896568012070351218168494127174168059212076768868362628041041744154988529535606622431758690653583876703076522992038251967347456367385049762004718227428159383223358490313363521617889495992021185695613819235601469959379268812410823198447656905173899516 5038601414970190309526363758061727316486573229736469958201542123608149276363156248782818536936954693636174284628301826780870263884963103889184966870028554262641350058686444266522524891494503341813865562898581754474862110766581813024392221105946124387822287946903074432671486269072214840411524707866631140580638485185953426446742391676380574753038255918236973975384408 -2058612878528731888221890472484620880306809929600072817544944532381218790668479486048825533100694344848595242394903407862267282566761460206269946003279088026902354053258996979823536352729471802571184853757306026667655753482190908770809015693711728511414713204631534477790762200081972305754119640438085551083916822635242594994495953261876650506712143045891570160113960 408250680676558259027750062851910853862116479617323863717512408671484846772057949711102833012401360060566551591763178493452465016997095839947185974931330038438201996831076543117152195466410940090633538487917224430026369596188126734159156584034616069512667249680659973590329084795498832302328171388427907567119199288090264599838964268654140421362343537664249629133144 -260999534557289850054559730005164728863563129421910517752176730732868865192857313561725627939493771335030797971094997363774085776616509734635811931016683191473916885917156293751569414951089736540190864694266986498648873365008979704400788859014791377139589362695226590670258045121003201398688562412856776162823588386102537297030883167982678118658332005161168617831056 92658541753748845852468784926190908448269041879513912157868778351768418192071431967368109973381863597804008179158887549892911137930475515568857177541138938306652400728427641666725160050203535243338502759702615844037777503776924442516030360313499534229282887045993892309914382211236372410676019968754570726102848971840729011453998063780500387682711703925952709379508 -332268761075260469838575803512833328866273756508463528023937504186760269121458442657500703056360076738055135163211365985091996663869710465292139358081218968783746784149371071480944343551782813364452242906440851625013015363014968073158829324412424468012398644758063265869860752200796343538610220173680310065473479443978640481342627156611764968183774599308612695843556 -61294450883988529909433791583763083436294443051631010051777632001781450160707510663718615263155984708191450356620385633809565537621678764010953484490481481879738576012479922682863276951464292242837318653215832787067685949688142694228074710030764392630077994505210385443688752270275485723357636857339327964176916357252003073894599915849534119712263370662945903521172 -20614486155380945108879806512332091231771425731471913831942232797061446272638477780462163673126748483274212008893569654476173749555389004332863789653315980386380360592186840442483755519581875537378375987973352359785899491125319479176242939627000459232875732688082203667002330130393019007207876318769255907706429225128119039049313070548772546051184586410084706786780 20246547923842004869706276693080229968856456024363978153453521997513761613535595393502905416157088387969816370751430209865072182038771889838506402170068876870930761432718470587552941108408316925660620181440822103207373655040297893944528885652295673983112556759825322013978077136395841043696610717755623635023557301811019352480772994993625340689215370105667481544828 -6295207778144993661162613538758219350731521076499275262846930847063494553679973255830122067452683441958955716073611359684092827819699247459573233086728402883839274690856961754853306621914501447581633822183194224336092894279871925208810432390692766786728702518560751638173679233201399900816135628973638999932752371635539142319493467494319288721907128120163616276216 5414918825461049733262259362236274417539122416218689356770035227563474207613232953955725288377882987093022028880069323911869105967568612863099137854283585018545309651018903558675497172058375373787493376783926157292609627340331785652835016999403063031212651885706987059769099800040173253754297402167057955148144809772904053715589785920359914476879707378472965952132 6429635950806410284116606917195342364257164408336597680036568583592294723380816115904764268082441875787677791196722723709421061529897726094829456601025791123008211661050483383135334178910088777061250144041301751253733772054062358797740666906812227132896524581749883247443828704315225083526093307552902558536134440143251060267248424209184417203931639183971885250008 5601301988434715500021128956045963240523344760313040943424015477290285296219531015982248331428254967968080923497464258394957640928227532818242201193949616016903505492303571615004952669104094818838871006710230891227043273336221344160652055303442371221846819144016639574832204342283554071209196194253308576467507128290364561685384645436136323716164027675716238375796 750965953479047333024507164565881856545628217785562241693598413257216218447325917794413660662358477014620579672825471881212480682887167072237169758777251305811193081271757928841822214866957870506350227447064232087274363559238883012299275672642088185217617343972386331872603398680881899047824380299708324840339200827729317886229050481988497829890588214861752654396 -300502546920343218549252456838189576193775620054970197050969487995885846243910394273722271147592343818641395228473096806709928298244728648754637005213159029379215249805314346688979535517769489169910545814713863453018264550304177812284949063729527496051273409271876060621095254912397090394134551024156215616338460893564204754004711221853178273869219196416215873436 -47915705609399797367197519153134066513157271872452158197855987664550420792421391627159796121363518107472773252284790689441831743797171860513161920122816666112254330306100497084587718016776696001331653038139787337062166900176202686915828004672265504683357148980336149599956082343984082838789603585954020697791694100155293976026214029981602263557903925833331381704 -100239179433430203449762201578102024699025873709334004896139278916526574567183194194009878042175338670396856764816623126294602740676262302260195227652914435245170373832040721659285091609413862203486145252354337098717786480612588884905308263195428881697194195226371601471410489105494291968930241953063465144096637785978970752039618676894511675118465264110928625788 -281295146885967954873434629072506741748184330892621407951364620750445381626344233151059800429197649170162591393761350161931102011074985531762354077592955483374702088852055897363616524222920456839151646560564116457514587006519116953978851959285911713540958075606637770830441531989655399181140012711288729574102182837277235253512423877631905392374314441280721938064 -239030248358446045288375476584959862952882968136689863055336064681676972244837672689848888160346284773784859837812949988476624643585652572797412734490991170673182242586487052404631907268803452607402353323345689827006081619539959176230649635888678616436560043737795990235207748114902227891878308908265722086072430734332635720732232542343453491473572822908174857016 -85319297478401282279872697510577913178647327311465164706098510213814174322451479281237653010264194289879839268357286038019511303023709766757508357026827187453560496127025073633366082287352139670874818778164049748781935645239042770339126051666291689526155292829596508210137602111229817416470962110362165405011326443796552837533430655116785926341983210454830459044 -17707523350485671132805334101433857734702141440681032825605192698773545942969905475558831432087133459038864634942892359899401633692727880273817202349101161376887924272271079306933365377297779239377829278475316867811844474024402927447877826203426777329090400415198324335672637347925492663122613777054741442159527143009787582530095143275367394494109145088722070868 5693392151907732271426203246551612989079594421941478765745230237195162965815451978877186759348971755825862113953157395688315813051428454471836279050931429401865315924031021157613079105045403542503139883376803750842161666742885716982430135871532332860694296555098932395700867283872231988552914531805648854726312132240701892499398279575185856230495238269105766324 2262999480574647765367609960729069945832577856802258986762950910425297964050832189098434390610562133700277880732271445455104889775864187422571111497758485188373925898766650291044525821717542012012330407118614036743050801085835558908583685511360941959542687742380564218068199329791700705090492135052868536502533966508028756079310089667197031645731687718078752708 9337674736206940394045136125096588855404826227456802957190424850492368712618641467704824216955485662776378458114055190223802277727518172252610974361332068368708215255489319255126185192110537254786578085694653972302576747085859654657838972531269527641507286291604915724041105878853515247223096853818274558118929178843616677677404926579400101253892733973390090888 9184691746789355553721922469445689078611971302787289619388018487095841900806681994660126004505082188033498784999414769660757844471990655273453419380750397192116100807125640853306052255597698454942174203658081213209795977092633907364079381456937517359025950656050914594908492253206387211858033999463867417363887627966694996553296415607942772267408392716674630148 6094995590347164463365360256416174373607265676028264938947580673854943041134117574514113308508836262956456670338631697620165044869159775468202624478177064486944692322779763023057849288400685252537673026641775466386013217045186242969947626998090702784968448206614240349240792879018934460208795093135785144288107113012917629963793462202373049499457158232069373112 1809663377261977078105769200112031096044659456974640520209220314783778076820864425872227197618624428575517043496435350600414636481277297611611853030219479943422948631623480462965472705672346825671129812425553017245050270568154294728041123457599111087449843212273136330148769454858074908010652412387443977714239060412580876105342232502117879087050313180593066516 696698782118673380379979816222829253897877732234816184892160322229538621311059697732569651952839048239323590090256960939896451868587066617216663350470179430513073032514418584804370094061904312169491349235127253380685604196961280846400685725133512205215748038412363265252877865805204513560953342275421137938365854127653086298916223349943761673568203246571877532 -42862485365607544681861425572646780239606637653097580829299639343567245846005531776475881306354514548248949680804505835347066821539185383750143636888042918589651668818217974035815388995073606469548916059525776103529108284292232094696761982599260713319852638709517963720937845544174609815133356420999237390224906221311231472729900435652305541386695797751061564 -216532761687158797679508472268164105306772089253829202768421767671538036827550321827998241789138701978855413618062075781083375966547882942345062795192609739618603654118365276533148333397023921597158109885983492709296468654414304980719482910787069910160074790350764334695547031063697852518969034967269665515908992348351621664345354039464573722457104094714266292 -326303109302556037803258128107884338128386670259899613394205026445681603087410951165097716635035888382775864313967722607755719447232970563913254174770872628483138987326745181205922784734716384584564993523428451102113860444857579786223964514107329531789541709404294019355429892940380125810555487340561133339253912870824898366605189583703020516621129621174885020 -223881685326619587394906643876029433097881023779043560959349151343240333011518786896707517592698842678340434299620676724289933163602758285816468839974582524521736781639021975658900664046621258264793276178779925885174595661120049155459109366228701740019176754883643506304986838977003974874438125368670304449946626026628090338470428498114431893556920039035883384 -147968799753404334578471630339088839141603959314359269432109864828830105824348753405772054202481114911800843909874745968880280541989976918261590669033644760114072774137954685392273025848755076446846797808494792915597441818772085358862888793556575574380812863581818061989240185925186626453473808797001439670955904727569000470779878049400996040631561327271589060 -55087276770996400926840548209644798754296689226225467984056665184092896224655294031765804697235483050747057741862197261289694140007380544826491599716611237657302872086132957508492957244523326614429892218227619721237911914105042448869493386785135353636942100454904732395114061384699963716516324305902883499363408253065523041437769898962573870382468870122681800 -20277939432552319723608068054900336748537942573181371733551669002103999640522868876326451960872492211600021967231759371364762476278768157923100489976094511682612076868211274949200107438250453412581337320956579372228415833317588809107095992673363577803261048178216855522629500531338429434590785349112576136439302486609962081578166356852519147569691319579359604 652007173044233812469685509251306050301178104000412709699709812385347451007795459411374618315968769420355982683908205215315316509355981790617879097076866017207646139110557271195234696439004256031064048487485626922683234691771347443048675947037643681775005576773316421041070462673406949839590759999171331580097957323674647266091953327753544693749660937804128 7963529498201466911650711703377944906303150958478317137396308567462018401888944697661989344944723686563562389219630810855203425602267318550738561456111797461143041588435964191581771289291479652388236173735567676390623678496539620963696540544945469584607219370555743392773143789765984664893115575388149531000450625891975554363432062267396293406269751515125116 8424966956563900673365984542366669681802941201907765090518103865187997335193210211630269197235998921974147493709357755309002287417097270132147614297371289739281324880414973319791934205620948662686274728544513363325269324889308942398199209607766896377150012098090201663836794546232580535498445729982815756139536332564295276020915631146486116786514951577145324 4871644994056785161413634567662684057281970438554141509044979699080062043319036577638271803380926510103600055562604054354184995287408383095845960504518852692767528081356175871689792829583411923121547702675398531112152767193171380380255758488466619865554339984400643132608413100216481802152427378586965830571734552511637749109668810454681677396548523951241480 3573156673984367266026471640499758759373448216109111047524858064333876952668872338604087510137087847428859126687463855989153994406470373761706599098729082819279990228121406693536562210191768730477328079310439843283427495744335044772979590613277935878949031105478563233870898674991186592231028114113833201643475924882271698217423342999768317431847469243067656 1628983955133476717213522639604388645324138003321140454394555252556579010969024247940457206808914821796008911555346190331239785800109194003575709698095935384239126514769493320665872493115883712289116681894358584185581959966849947890968538894778436683966643953655581506935629015252677661033416793327560218046129621317957356150475455763449770577160838791397780 446493023560631092609190777776044145032900483903202222675202613888120850738451766784920834847089051457761742335787631490135874759484249177392630703121205423618188947543690178997019487157725697217049419424646861723294691643378087265950944035730544460315648927175327533797761374785752675031718007825446207875948363585262440609558329852681087050120496838279584 -35020619714368063188108219727853324941482778948936610248948959721646744329511943905647595598414318912288786544018540565073129406442925017278239384518639897298599117308840845813674130753011527823098814123567210789235528353342303077049710987270761986550612022590312449083656313007388318940006894278120829633952410541369461579986684138114418350752660723025488 -190706784577902966324350988411095228056770722381861109021574464670421649540042898992802492037626259224575199016176176694801329360271556872544591992782996436938824076343039124699262441391015286013331977454649527292979176909624691008894252243158101980987750077022997174106640678296366476931109007410313330903199464550653788773215663756880500740642827689454368 -189545006221763925506090100076490754285042723378365126568954107104898182364759845506772943382682826117497835282249925877196123172823575936767665703524689904144621970718089140409228919955770174896561746513509764781101279823968866255519655438765894323531933188567759495973286632882577713936279485321871670620561852214126918496225247722251151544485625723431108 -108368405001467503768988426728008325166262729464710502081603614505327752995703642358626295658722090254850881301710027704813180419808627114867160912375056357020407381158758037478228688022845865994132622675629062646918406679244382533247611466661035842189129230825497722131595586416363435533604684220979242504060799518600181785411522799352543857658103890361872 -80093852593480754283523641818201461440241365871146306261821420151337034860333191047965981425864783104426037813779549948848205879563782546349359373452076532149778813905499684084786083761378694776450036133310652962567871524340713662906454614367797259457810838172910615082505451243056934639836065766683113358192691206440589104366846272874377155613184723932960 -40654102583100870894599222382009617352283623108812856284960620821343193312559314071033993357083960179099549651371078083927736023971431613999082127447263642906266702788592809733847767877095374317040982116836877795940205835766136877044388910302996238394709365806021869236616760549580791650772094311334649664237077582660006945840406798082148829288938482259044 -9056711500643070359739666598375269328227219136512271842304742934815521502840197587741794323306096989548022627671657330193377841239226163441070573970028879335452663000680217676051710487363832957447805594853424149015980901586218920517569406316461394638432820710515954119130675022526208791123639800179012384963482224056454558430868556336345877303553291589616 1316682163644657640667480106415403262474989862099098819882731152151882609508627850023156509036460893129624589620640027367357509990080421444962960875517330025969896637643688966677360362094915030675186702688166724017686479950443164496329727154926465806362366535465961927995701065598611732069195737403702364975607963498838728695898240644822528920536682172604 3618296376340610673132422647906428302212945104884286377954957783502234914988032622365037145378228889318200328769187679650735760751705066081488900341244066090305682848168744654537955246195633180412997125643519315997093038317363714415882801085074498969441281475560803813596123322695345169732340038046459789036223436079653379601463059437014360671135006091860 4006768844967720549589694262052674077397582808442699725980318174939231938116384981531523520400125958628774658442637922971872305508798814358954844220057348794252534160766937227060738733504951199722577651027116707299040560584965018710860355299289736835966256815375332400716281034114846532449272436029794541371237572579124929316968206076578389510711616584296 2502942657696757102646201224545204621707331253019424499127858292912928908568330956253611396759517058670329226311748560696848645507086472960104603371606633555200085694474358410474517347985960701842249664212029454300043842247151927622953268705251715245347244880945725126199320316733731230202376725742096910335763785571813910165270632163324052464381952832756 1591653838412570516061159631650983448366038970351781082845416740615992383011850958491607305764297840035560970744983945142380493648769979256426201301494840792108135386361752355998892815255728208767510833741049737538491554560369144063953431580814625196738035873863586799878600044017758087807325555119968261412513400967608439978474109727834816189593787563176 861136814722388332662521731907994771055434980330601191761350066190436237599570857974330543393372650797765334423850429205174398269029921273037739934821182104666559879256193440254364704614690455537408460925240758576859867700167938559135168595243385218004316975656750872467876995609821071713845847197122112250554084536930964415184539033655340218101206917420 207229160583180627272613447933652953116953026340181891938532399624413582848184274904388529870272498766936426130194359222469850716922721261475866055148079534471826508054304110347990889492008638453805010627170943320499112891592498484730467519518627729654900481477253886981175532505820792940739819396649754726144389979341314610020285693449300825285270663064 -37118757495505088197331401539907000373937396423262017965130509003418937547432185482799072003940249575538394209468351036317789844837663492586980014641964381247791377027862949115968927299317398511123235150195574415588562078966382522890266584105471357442012644239552244545526587186030106371164646477882643987770004073445005299957434419453524046825935567260 -67833972152143538702911445161382305567507388651050819789818769454581022003221180778003477125827900135220758808720295659063344412303028234355977899236069710542241967557146064444928105728887016047151539224497820173095365755672898270813516455386637830041607644002777110302481658264437249163404553361998849894600535131240629819330565934101918537773419231620 -79469466294887911253115504405457501922048723221458216969565015550259104489749907131008702455380099044526401216145928586402058010062101361167191773559654862882327538287972173623998888021464132007444032126915980982697295824793426778662799771540314584285797098631299429033258216765531233020755328995858971758071235291647013440500204205490830316616280331928 -55549697242462304150148957736523305815898573462341113996315834571464449645046498600358328737898705694212283603315846777022880792800315054445730802576171444092050000813057098053593895369093655221184914445655334359048158045181551805793722259017265006494970734001965669396938476607468062391742828019786932398679575403568386635160233949981748767707329568248 -28902543055666132421611457849902619529347848195302388465363457515875227717110169695134523706336518217138253467960273329750118456793062348943020450754781199924538351991808771814331372398661338219767235933271803670600947992718664631699641131527750883174461645642934160944601951950952969068742305293169851064667588249124653340884606527126681282359807872692 -15922258095530775426750606598978245820684548630126704149964441313967480766819844621485225606202935761573801273730892416171650657913769793454728378898625341367579462620699457458619272359453928231510782233953364347123003250793016572964366040950546923398492253084794864570299795958976959996351409243473390869523295881652297338690947548696892615608819452000 -5099441161246452987266859059282987274236760309126948037958193078037944823123082733755767339358728172180519857049577317473370064697981736347272406847090803750382912908586839444735799204041132155422097329527395459076568616688671813058563507872380965186615096800208158482260798433815205284505935329236679478903863690794659334551882123513422690226319770560 856633974149404048606114709441838351866538157720349558897031050599725367747088486324603849702079176450563838791133723682931267883800386845717206396129808563079842518616018008356689987173925781232062601460747844290977244557459261033595562766833625802797546658087084034882417535637472588761536996091024529986428259174378109200905316912332489155874530528 1485185083526451752262019630501637661125651067745415203244593703401042115353266220838787922641855479222756396991298558349280854111733203097487071225340568593427959744924496303534815907564404026414030585617609097752580711886274971726644231836554878174766812217932638430204060223558823654866148683523279630011388132589570181890853169562859720565866149948 1442593438767771075268301870693901404765176515241842222905483937726529445585707202709657085653654625310272751719966597921831212867180971095241805961785063283872336250940570716025979663862889225317857780135060489569236743678045560837082961388571085594555980845335485491586434639919046921221255194738563049380555049226345653877310267311102782156586460672 1118054504567207749977311257987999745145684032506488365198118641513901389316698988860719442719514756836418081163642069093217823056533573904232258731745609755464303805505077840058281655919974982335860726857349919460751443415686137039934556075429332743956688336717726212973549400790923839581916139469538339257569500727601474812884654729542140301309120440 524061718035480532134083954449223829275188088683495910943274814250770339733618659327922415848952605813523579561155855853890411134914687756078499473163786055547128971938739387693400744156249198729391685612859412441812558652902265164758692276137638722344434458507213998546510585358435430190590983353826525355020592956880304781198622540222369005016677096 262656894390928293492855667416666389371800847635342894039204744632275463951350153654467724112598830903207176289677636589172623891573103787126105250344620563434433269073111938021562098919390960812972341835178426619837949621654373503707774315777183690978543571701776302695067136878990652385343194963350808674363716347392616741264851855712483351228602408 110734665935513944142095650657153396715353759850274784033885642580385444340134079318612781069975705600920851933130935214778282201864753564723541601391141950963943686679125431543622929930064123803348501770860112569444651825533472945529659424555227341906750651248240214098369653484849692084965682475312505470591810824827193850715604009655225038623478748 -13227674104525382607178017937255768239584533097046290230488825169174157900001646505268988746737695143908021212476379919886028781972187075484321928176820660112641441395560378306329277970090334382186836291335850932635318571024022548986928252555914509871488205781003870857183061205365744035474609493357223540469275890427783794179466273868996824098653056 -34977371467603068997706718050669809552668056348479777817358940977487034669964339598557017139454009871128695067024783372009360549154344947714983720902569361499500832411403575467142556954032432643085622966978192460397309518439666306684188241372271106578302354027618395738543526494664221008712837451660504777147313844600348938976724640311194455629670308 -25090140010510578613209040734980731950474618941609517456055657911577103246467473772638811141437866870461648563116547142255553593289946133351783910547310560818184158866772507560391347525375897154622253104592719393126986083719016393094974285715218777883069019586574232456266915201558281640158275041904786941488485262767700534565783538273265828155149500 -19785955325384816801599436847670524814892743795195012106605713608231178781523170111527456994792370869357457285390558619511488352309923503179261186802844986769710390263945791276113608837815838020657978624739949867366666462941618168678803048095642399132509145386671782302002613274354957226995466561460707478939043163474700054291894344425950056439872488 -10062288766802576959795053158247673175761683604881956104075058427961678727863608080130599497801243225977773917920271965814761234495857029041994981829540275232035760655727418797956508077191025020680468202920302166133119360833438498699230017660872871096060130327909973727677480012911882566277770042507353563179840067133093986569342704349485163107734516 -4011876638430895748755638624238686523693840214472625747595840901616219840709977976810090692447445113439830011770291421775109368816769661172349277378671948805250691749045400120007749425521341241967256783206406667163778185314778494993976269372888014180414200187138459165160373350373673476616099267150936090528683406372386891177961678290719625742359460 -1868070050765820230115575719798203402109699218761997590666943615790322815978141597571115439640677827502537202303287329831422459365869913593661559345049163735976806888617609111484236017746643414160918432911633039608077290798044145358562858096365356905318426171312863513188792425824088267623355999360814358203890665190104615816661075014961318406254188 6843142863116235830206389431436848289579881440378401310454056326148587143671851697599279783119588471144721670498533041036177384470426895068821063034065294648787646747975699879586914635227312928506281288947941880413864845853355929730831300415213209136149307466938480860109929587301119643095283284484268622465385308735284133297995560176704071728476 764538711055604755398279188164595069657800856617794379337641610077162457606370735782375252880605727678282623897983158562018581473145265483840833685955240465977083838611091310363134854666026327632578865639221757226315319966004952997422598889476110951713311078447369410654727590944961518141933981464121667260561800923209368833139931886132755482729128 468731821927698351174488282558955220533577745770987918498694206321983940596525833938500774746166928703396484142751406340091367236929184640019750231216258125869599310287975985970156443894415138738493537923391218437085246702852778743779151620813257841893417432350415173775905675317586916376167885811604453722684684391562102627776558159941349807510820 298065453106888066271363805166151119636278051358952918395850884506208440587018694215067519313878469725792437255547354900535302783423958352071043402707769347434782296711198392764543204410164842862514862629230496746222806628548696515884604266494025668080346592571976321364568779596875841065374882297846483103502312636908229918389908404121172477328636 195388172995372983350047116785157457366382864855513434267147975659425323831323699599604085855427899556224100155756093205542266776086720107124947907075946430641162492988633764313787210806845058877552047544163064526220825720673501752844670573644002464107047251869128539726279671009548194599234785699429986094705392696098805209051326523741340563661040 63655532050650751805994876008573925254835476439343473455493173577643731721914576171203016824186979591269227377307689801396253916226642432085470080628851957766324733505799971219251417235692343921814204403842292950921541050536505952700495670396986917815669987268514378922317257967296073894181919489488121415231156354059364709782226319907109040385136 21095298987685055077560174890683997479261000891326439686975664582964520068138406554211234723056675936556172547688882675428163954601706646712560102148781613557638368571640891282624884880798648535304456529053121084324683481286702355352692507624362263719635943903806424623344619904800935687430243084663738075125818972727195253190630378477776956699700 6129949114026935941620328680546274719800855714599971949009552961411638980309814140688009226369264416507621674035367509455147255500225257162086148024280481536002405600970212753282966136125547268634032781106457320982678676385759240779581645183232203286995775171024511108092561668604418644919779614176803139803663054759245491708004659961294044123484 -13987575564936016204035257983093534514120970042267919646821890198560353397262956752391842603326701081447168244834000456944258156823575498424315321910577251763553421892636080625018707434783322518272872439485001528838277863853555719028492463657665307416530287989155327375414545418151371849159648408165087686195862413890321255691719652158026585524308 -9878206721382187616591943608642440519143219286239283148567869002171513360942422363318214667559082554201332008662703277363733220846650602608736215589095063675176569356962429410591820088737408931926737699420570046185065534715417718525937640066710154021444348056442399866742664939535346976497947806264709322065188041053405426450999770857128655221152 -3730875512565673791868453190041512043127265789134723886978239982916964665974101845649512327005669331973560838007169583164993305291557042504511877625359718182928770369651646004221127748042158358735592411213206395531232448810751290093906270014133090250841232814793961942755485793294994801210468840146563137222831532509022850103127318532229643180904 -3462222596573937140016521702952484933336886437997523208611698174034311047998620150324411173410062063882982943391404897594000050857813127597451047516791095178288065384948151709183371912689458611071883585377472630718123943179913822853807612366492570897418665056514754239461604145639257412216433318234789878954562312077916631594642605789073355005364 -1230977833199476144937912375517643537419362109940923739189757617275432398366398383136461446214417937145627103537136827473562097431943484799343938732065104677036858380766845411200911289410243274102521753608444693773190683602311804682265727183932782363947329085523058732408449578603566347603530727869711877084009809309630587427152476495839453712408 -36320482632366174076794253374823597951481457871015436123089765973810420264755662009055232276896115604431024368277782618351430819432825447031993572163321144317361283627501587189187764271623361287345619075488197788672902209995172702311612080736969886878740067457338764847290784279275934308513952059246816551691456870206579929620531340023260301724 -186222009099239627626166098859923188008559398130669696855761031773512752939670040636806221665991640116892742930978057953908053457102295769128512056497839392710490684673818518550392657173930166570533875751324142425186505110776302044013792075970273566000487607765693647280918233909642160332349580303017081403937011919155271526769578614119005555120 186944501042350317381583122977707739702172490739185323344364937661630551130609255839007888185443685984384964060038569212829387512182251050540794594536336169687801987820671946779464858755802414244477624891046700906283133299183871706990780262428333537590588760360875169805522962746454327084308965163570238968630908277305301234527651003768591425932 218311865567476572403779598556651883185820100066175698503448483693868903980161518332713066432376605509133879970687662210998402651883624648937507627348689472124270490850604344823746182317958218697809706081623800529413144944780469754743685155539837445089877569485390360393214104259105367689222660063253781564104660747777026906200714301307843557324 40114666162982786494872219907564262308153211991797427343255830878160393906036702771921100022414833027256703050595163586062311603098660656980809140601984765366742344750407066710861100704014132471832248482533422289478064496876371628006700218466304431702689882809197333506600681336892223865821196348909691019742339840792206995900811493480325289328 50324745733732862258127249743176460993257032840147733862005840825707090074782771449902453600204746722906725655843214456375439612370553388218637302221530199090956892466731777066791657461634793867997316880578191376421404505885474464967255773577854987453019472996881078774748185202739081391866046450219162841862160595345763814120120515940779709456 28044623998421301922793332160363819446829884838120249061384970629743001845936903355720629519242648179784283851739245398192752091166008558483250160302445052670122533594534855687912143019713678036736132235814941553783953957796500137591228350970574827932042386870415487826451531980786341869111325640296696484381750065388355635954644352932318493100 -5289746511251816747248978589255949005230214787152884146500978323356859232941780818687223372242152952212418201092614567657795017594642966657554429839925310868494875285708922401622168090976252620268291138804776684403677073195650453599744721460911079595493006752087528288592073861810244375775116875837709321202003681107896992323073742738890648360 3035926531207655389159358130427858327896060921161247622600112714364317983810371265863247437369687877578254336248976520767868313846736116994131172143008030517754579873951807446098748103623470547480071713170369887030316556056808282987328617224612724269430483066340688713615141537013964771470423065489836918890609671047321558918890091639576338888 -1095102179303549053947815413458492279848973660440607215567722235415265459551377331510816380673796904381493676172590766733230689838046176692201806088269078249627297136773876384631668182164282876480340166432831888010693476175590010987683954991519911602710069524317129095093187214463711581081999386532963755854145075944007172448010260136283891448 -4573467696478808805326112200752994977582562430306085465656514914857708947025350808972813771543707119257473188377127447769232850500245207279177245480296595522647418860971633716842306326825585094182695909199505809891061502051737924958239633531345296424851253992936931737793414139430864610389188548558573893814339159616558634835247130843301076948 -468320793193366092225881414089619668767658617101936927560683416944816888256723941546366655589966641697617894955331893300371785303172855086231281357868953452086363338756354847536822002654223112663243802440327131681545432483417553147846520549835770078454364313371595030729835362266181383717351408325571632720808854475133781697700151777397214288 -507490932613402713995975011825178979995812915757677147163999445651790334313554011380891666388052494618999803661137667101433573407441648267676645230042384650240986493180464272053740595900345313520694405761318797376247251307357130936678549887983080358505067199390779300514856210720344960400296263276853501858985383378073968771248324322870406632 -627963642133969494021226251929179216127009256242288457209351390362797716666376999548116410013771801508225625279763790572571992985001674279034604790355586009934264887476000742742145745137498095985449013781878162657967851069624810902516850704462717164620716935929184076378571090538581505539341174969215399749856302663698693996534429779142493664 154768915241990279362258095754615235830894083772508934403784352365900243666272226530968202312090142254367379197690813435474553130433636693625926844891765140820504517330138132072998467209834467493405683709251339183466834658652007638888575947161593635177406457264077984527355734382580562743397318168605370694820827608339089453638777795500101848 -18132508899304737920663676027928150150764631725058642430317476114110848375274816104118277067085376544095019438915653493900279039698589757009508018081798457475646530004914171587758136270347885274001970860806667144891584749428709118361936233328509760495085099377709068701977803095846604763147051526777504223312830099674263187755617432176236536 -25566683025981329648812579663221416157816045624446061297395031822835434930959273880076392011049325914968352340340928434340584211246626414590832058102243619998888264450033471324226894702566520664221578185561731153189842419600501170958309606491484489259899324910418443577325196019797879876166728190260536394136093242835703178730066395325459096 84652944991747005850637218320896639437640761384571273308915770639421373514413193041472150756218691507528744919317159227776013229537331648383921209995573630981173396578196686440805527484342747091278290093086840748507568824711651158322400453162494314399986952605398427769215188318407110626702773546001754167368031106737772979014108800644825444 8885994355575622009121821760817227021311475587122573935158423346394860460864175565652315942188891734293669610139351138457756037774293394482478924699518490242644238150893063719316856479118039712792177629423548398081286935654442241722745207601822637199007584398715155084651944087164719068566243921902622845041543080579790153499585864101483824 1045020539705271059820130368767160188453362472079948980069783843087941260026134415237651106613578103550383338177009974576872496640282605360210647864985502438839675669743145611739500894748181553212727395701191482574670470906611783536479740842745146931990568555828364148562712560256142894669266725335132131899718829249224582586421954049005624 12383740092356610352805175872042429121446641801787493077097522565693095687908962318230219427224425984511670105994194580427262908768675860868495930973255936023887222281843566046284416078538352068628078067997909829505587702493734177733344729970870332401620975282493244228993782217496666444998007017376721105539340679934449260074512573662902428 -2688032439934084202798150160943853096184493996721407229897256089850900678018020047320553532452325162207996497732744961148011642689364123078288897156045199108739520386589049728242737040224339200862385899972605065607159376280019417211099584188154935596097771555660174522581110804964617437434296761574945592137981222300926316311054561371804052 -603859560881485255707387552894471703943977510350204243836628964517339459065997435722325424012810040499457952059831722710873983774175313736510596850217346591955150401001995267085941477222607147307202706728112594237955246428395631276328783388535480358892751947531607560721766097643878495707730783317801055965046220520784875052539339227231808 1054400615959537925712904027083863617222502715870385837106566217950450273311687422574978247041893240959799186113682198712344950185166092938509378737087761682084189669491583686563347324719342753220428035523574100515420723414435064949020670607694787104894809992290757224731516110008543256123937665366886077547074157863793704882357341859128624 -1335890140318908600843542583390999936486372610961372354828994160948677033129134679988771608818408548164210721604816474926083894834001964991987740802766661881591185800857702849125494068917658035182900667097865720909119246548074832900791374353185005553814432950459064562935728014614703321679277622397189639439268707228233734968691806725082872 -228973200937443240342208158994881382362837515605650796533574530269264496771646944108609590553903981644391009270803379665359755873667858970153398866598353377570671147718858444823432760808476715490466692390545932771987692663321088794253935127291327411227981501094530003882492407136317637475352546504496341412295441352536739465819406333307736 94095622988906830187705102814486572069907607385538706534116114135166359861089560740673339525981591075550391280866249912297480658887919127907653967189321457095555572720309891651482513143220434280799996175071812612089870762400899650702814598318440285937318134682946066031015481207550175018427209621311772655666330001573853751976366636539720 -207345636909340198996101977290435103382706315261417481819837234254118267282148637712936415613771728422416650967391977036558359383054553784914192083139589105810429854470346251562366072426291415169170368982881415695344785565014021562855021153105734794209712623466455291618021168312006944649175353540840145834179847611543861766298836020838464 30756424986525617498466080963972146335637730129299686470840570475502923102494107079471369849073491449655256616518657126378404407855576838350146920461011328822886749157113921159473214544151988386652825829970389540886233056137323289140766045416879604773668734445301291645299579567882530339246425327932930085650972224482948344609021821054036 25153438302560247092688718681743640818012056412554576542079976756921479921007359548224508633591021602179824894158162606627853027711065630200063658694239559489517245995451277171682992328840062001824295751154565256972965289536416371798067120424000975740079843486899554473955543134890383681612904330689292967595167325934241133296039134997792 -23021493653502839610728960833211494105970672738965414592117993868910608683611104582711265335764845494643455548897890827444160987837654918477371924519533339343065164949100869038065081419751868906215266162544158367917828909570088126320946416360387370158526639595134461671150505302292635853495214101261832463052818201807363564781443641636320 17694959451218915282937262656226558296879650077224667619006133659141027457451088557308643110400215607757450004623498773149238441671729550473312377621176401974426274241876747477770672667628774493782087225566758469200895668219356663173152836544147974160843281660787198706062482839538247328059660104418540833019476996923440327838522091318416 5448207510013924330375793321057213148350204783721290102013003874941525502524001441832721248373407351446546815016250973388680299512228890187201257648975527614992985017196613769589316984523862348758699960584317080112325883887110379609116498905536074348989809978406704569875290132758798658128634745438087291780720625911922455594862743053592 -2682210951440060347670365678427143566048169955819549233821502926291583514467772735258955153915820885650206073622358024450943870072562807731012970493535302136838945722590206847148848389073777250342668414855908626696700762254654009043107806738365441814316803889958264817200495794664582758974432247630483319435745572251824987491193073160024 2927381646523324638750270230972106625699328384272972279527729667275901333685183262447136601253243504638036898109160950961520000182281314829613877770359585213903109312933863821387660922721486661265254051442132258078283751535280310178652017360583136758418489537818591701325613965717195619538027671129733500667673018171693468341887395193408 -148533177222694066897297403688378674078614280001525052003699129161236115830105043728862410765112033268215055186837013812029419215275739395489564933279992535238686897201960755560293696843221144904496678588611926894211181366216421709888555742797769462053387958492659080888095251751242618430866187553997214137691596514039498653902229540592 -573614984806885546055873981949271069339830819443907486039638008139151733220024157882122034207535385729203999839733746114742390953379967336334946950044948827867725948295912613048464759435695124663882580508633530109873224381328743988043543450655893058287178129286706788952680741465363184255394038913392665840628207006810947713904176780688 377790311149812520539170742939809796932359597650034438940918223788334309654717707002961770937339158342147563735750186528452524719883314024906201451567708845455111348369968728657569829308566519476041723263592498693714479437630449480622362277792503433305338083726979773147822427238394970277570203804069840905963014762307370511596411076576 -193567123073664470969605067284749572801548052000860316155734502296777282998880495736981960469068476666733866152613365097051626046666041926472507320353721775958402629103253587279801684310595678972095622595628131186136619365567631213657204466305552032140545492423861891074952207461249350044603588434394893717094241796383858207072924150800 -107010672376177112026893071829091778679349772479946554847271180880612149494461250240177478864226011848674794318537946535084960895998423749900511635064391580649223322891202016387517452653673942301031026034856981818729923980111471098059336543269162048269136750486716297830718648451864020333614048719052805864635447304840541346271157315160 48374334424074886585399523654247929052759668387583926238694387361747132245949999812169248985846110041104125384461407891463904814104282558502567807219616484788604099723190066203184019355188645939506235481307829177292201451516737758405054284734237143508207837586590188948880155112688411287939395283487098868366151082311883217820753018152 -35085855300351808940341196826304311493962612901725250007286452073355401920765415490655021260704774995429601373471736961597869105215937569194230004373861317782578653238629345021871020399280152150037874526511921266575247812732329664518740089307893645836013724742711857458748539997340227346549622895694134319826649217802247988802899615800 -2876098316742649233471549559236052624056290149436815297136666956224317913978713141979885937713857058918886617601008696412243006417769530859561576594963463955247074298729895717135086406474960676447680668120872990056202449591147622537693763075724449051789447601067727788656310173696634777473765786653347867869935864187977487994668436104 9882000449903315390348102897134480868479109906264041282888938647366815176113320307945501287643743288790990979382748474408607970564239320351341462035454036966142215673246275611619077619779160933371097717178829105959177745366882286322662080217797892238188733300756388152896369301392245633729518661463032565512682536228731973493940569688 -5052116532382439152103837950095167542741789441107824892830156495316396286511215790102281414185208630711307984534420171212910314639484675120805531339983381242424874922149592189979341659353083966382360592801934298116838147671934269248288327508589463348768215842419036176961720803172659943387780746733241172770662121321134974056024080504 1670954846152606218102089821589066627124819597548673376535810546234233892965481538368022892193818880394911811321221449923406835970114659192362687355027614932566688908965310476397942455560994000167290798080311104135354670383310806772521605228734097253316361875158093667600546942970727618953895774811122651985624673525337947347771591776 1733356804036240696488221516538642612381274526715661348172323427070212090822569826017808244780031374927762418398204166823818428345950375638270790948825261907203876864580157658614250821223400147207204681381715268810299759130450885634780634491512564034008884076316263538575682346586160433094573125683601175484067761947171005489332338712 -671440626669297977772806467302511201960501026595325543604699156551551974921438788229378717129527113023197609774102582840329798916868337663160769974091835882085361289674025657647420589278011154704026308129030213376751558730732408290983253423419870764393889474857901020683826915483312016835045545668007908665393322914456771749031927376 359534593532583738399347962880527374898942155151804369977397057369941162888415588058751086340837118408116097742934356595210790783138298993778841425805527778902184623579543017311735870316247862643092885399230444225169138675505454935925383800842971487391907483113820760369398463291481645959281326226302293666429877135190976010525836984 94017097440586669855871967035428248983791812657829825696633028402743448775686676479034073488968600830315334387733087319062390841163103297143769802794405127604120173215093378705766874802853755924118500770262319798405776473003073783927921493936799165710807437557997928820204367461782545187234703172830359137677877859880893914387253880 -138886635152269656200261490141305064182956627393295298601679850230096792469548866710070833627074904781629906224251184471401343651492998220405787215868891574618322246267773192100604227418738584868938857802333308471313127078094011830938480341318765727209431876184911175447234882053632150106350977331132268891100402328580552351737196720 56679492172229757408700969758060426600453010499005569093550244162532828869943225307316424027840839549866943465104435941007386108213263380117567240785802886923887784785713926212956535784491750442703713111713651182633268326607359955302144953738518343177913740791054237285768495220132747472222243765449203195580695956586362160589953256 -9582801875009979413874123704440538960614357988516827499902426033099397998301012234018869751509929146850742588530866610579613901113885337825081329713072649552358231816625358231061273749836732614555372998786888788871108608115879058275541800632375756504414573961614099290018721085539460240752561863528849490676300465802423654267128304 -23642761763679093288570843167170564018695083076187836132396199884007576776607649025263324354222276111004179157299908600408005188620028358886030705594703393111932726618276629159651260671386463656454509286073149527889701164191596330347669634063014688844837936777523134392355411589856787315655696225346820339772569111466122577238987008 7421233231709749539613003540574623516895509611057152978708747961287532976075944635228747991983435966752589339817378512971779163881959129749850616694960848764314571340415207419338680999433174381416015391289405469569904144751398783153901011526005398899791226214337232213070082208406241011426561042723741676448818595148977133971382544 -3119964171103033224849148511890680569938155095387130656621642469373786475422937632485104992775328483508515390785233692577394126807269522234738237405141521120320720816579533328119465579468358318810244827644034147604317243759360936821345980527119392287220617446061735507850232401047230138799217282104638454724917687177061202119051400 -1627161386216781199634772411079270499494761938396675737581966095423546134226056344682151598592662158349188546740938827336796785185880940725673054641608988663787190640475451998259070920034665341553473942764071053065019206835093521724186877281939531407809667208405432785971605245142013191712532967889780426799997518425085342100400744 1635605663687523920415264807970711287214913136159628977308740458693939037910259972473668642734054073912695465659032267325841115945724284725633380889351030639832696738936539605227968842373364883960614120400985376380134663038502530329042929439682715410770396435536698580141792088259845001648591636415601607893884145839155551627623472 -534125025065854627290677337501795450857287774980042997861464312841707522500887713960528071209498114728804454319574010616784228861325315247940597129576747977250446824511579935932792681407692662196658981771783329250825819503804550410577700000557204966680012889340674358886192623543206764465244513540181744267337148395982110646720288 -4272903183807604713374183814926335473952681604192038479222589273445194282839186152091160282640729639042629511559824832382552692888787089933400915169405395918950244223528328042272640216994873888349234510633781267955589945090809531260393989870680930710095356377214710654060883650098986432278390799763092807249277076909652570825416 276741350821841250651770696094044691851259515145316838562227992151837454851062042095187836142713622272351193823420787372800683951372506193970617661388412641353889466991485193394160670798947358501348737068002392336460975864083312986461637625543831296996488015753621756975476779781161439618443814791478701107229302919222318898158848 -63869049643261517455944653810499223877691463396195033938192359408849843763276969200091687582176873152728171777862247482137817849160756238024322567855012257345882703829768845377073964915307443105146108149260282870525115672656907366943320532852091699507710778678194549823475669456186846591447884683107947576877655404874980014188456 22471830974486258216950772212989985415714498668294330380498054796032277831417273019617937047598828163309222284325394047910992899606925031746083509931148687699857635871088614373882516853185525202683919447886765418104780982968774949728719163545492767445939154070821094481594565887676100442489983402997821173668575585743255601454680 21621639504956833166481131245096981450578751947323530561685930710547779304677099212349298482179706176535751302022510980705035121114483550771673304773299442699112577204551055844006122364028805014161308378310352884093026839162548258115880370536403732999217399103170851259610545904500145247435131716522859861260934516359098707359474 -16383173756241597990424302638591788634961421338502756842105669243450999575731250301589114785582039895801084386279374538937595472808994642051449283791589314799385249132094522327459499636313375368951100249273447956407604743956285752990631209979027839468959672701343592397577183628714848451988857976953660857023590540107507403351672 4108123742724760999787287849562639437845893160082178059099187137931505742863240751410102895897219770139171068888839504887789831679581887030093146811152342383615505892174373546190145905198631911463662090298211923819276814449483402075732266569107580137119400143652542114096331061080714711302109179929028790579687197863920633664592 1076890276071456958824824665731203636049970229019453027840847418631822350705707391475846236251811040430512890205847358929101744522726646475572492808380083514968142559833643119137235663272908495145554636994101582085267778929551344520168510823570914515858793110196359725788432614342601040390626448929831921348398028681416827720710 -2818328417502541603118620984007371467108537691998784598191631390169274484051928509885933009691639915769101674213455179369660063513267761483129955613297143172219055406467423661508177174366419081211485754839713496179213112872858311908677000747137414622126275012313293804814038517307910246328687973237574019628446989519873615846294 369631983134908300985818491138028818653148828175939411417781083181315389929161819847498734551923425639980742474720148640820796465935477923103704899468495022002078830780526197753081841116277282561603317544733854864233348136473472707103366843029499400475762459642418417881165755443089119397099798645717882574109165628941240666960 -137750122169904723638065194380140959349247816945172513881166813156237760417092559224578609063342208374240305831917469160063476810971072056517399005692060608015306411282132403672242437195006988021217563327957176021295334746334793689606701994305468900607774101911621021206134157209694931643322430671055169080629275067557070944092 -243391045275128775225698093009256891644633938516762690604212881015163834275346322295254924370497544218990744100073787849471708173478422719001049744392211965696454109500879941512478670565159316992143935867630798628943250514721295577148106444192368817222538439303693956729940589841782966581243574964619168397208305182790474711748 141301735001028447806428033999476230964459627051135901289323281994252121601075722630559871756043752962462069771858644055567799502605588536099992081340393142773597072497615953231175556967281699581345904002929772280375599105477695356763855471647920293978032997537715348967303288736933007636721323951624339724127329208764291397166 -23834055493588489833390214409542352506872000514646906964509141170259581505489153941300589412483803573453257833762506816114579783023893552950155260719677387116555000997699385955172649107127708261554544797243931028974159900557388122005379598399689542961851381876089380611278738872384990462127660241487348969505221436596855060876 -18832901876594474816343065147916613237727778295120632922580716010567931183937262426714477794367754350864807082277312870104056866149747402246158660919788616071826266233505760089469423250261509353687894632012614895738128068631478982483837212991733467785357283860094563641458097631321876009017278204474894482084652722880399281190 25316101833786824744205062617014024871359362808455153253225577868857986078588183435552605340638002615522668419678542032142566996187729284038744885187737929942743063660632268507801794984206702190335750315080904490404012399193925063638712486293247551017547823158831975074964717900818438541569345004811762159488924126848286781904 10276962983539036977973384235093536724917055202982926682658687917652351722989276492485857631532388110178205733507096942799152337142889817943175474913036718955540444401498844850402942945774817830619299421084234851731061305656863819139161148738218020321213559458440887222508294227806222236804520474940505989974395229707259596 922353177723980692657104545246949362645637323763007366839372129867357753073968485771127648137635960596510567876999561480595835733256212011459948018843971646208814191984893186643810424464815158235786029856704623535969539303013296484418541347910995829653999528303293974319236059379526841521990184694895627266708374641465057694 2448466916218691574172763673207977716676619717753332184481297028519539440362364707596288679503662959236577996191521704788029262340180799334184997895492809577282145340514320134504375726666094737293416506669252978737808004309349278406631558468485272809358515157782523881388008308442142665708833809020020933746080702561778618298 -1045547533464313499940134722234748978774530616541108767024303058469388567398209007240728702997336720623580413615680763440809348549114344531382628532689833631093421919216490253770974014044682454517544833454130389532376426436370923310455375164196492317643585290730989913454924467292949985254398843235227926903469004562641817962 62810309894857096389697809488501481821864043284191466004179287836039610963283953991924420698381158166890284145516002393542606407696813092635092848524891678252387979179597366556603897831704314827540426733842331774693139086221244289271528824329669097174085883221087022848324393254020552262712666276886043586210364222857021432 226102696509448171614196696284125746659832388681394836267793772512593478603800465481359795361652191426951608415773121194257900433179990548224011632136034836742100046640695332768933596321919934465650621419208755955168216682054291889416825214494989732296961636508240296593718989541676471331369094276099849409874179260584852940 -203590365137798287374163348275458748636511615029037121815682917070428721072576665051633816366988841666902380276969362907298703563572654631382258638800962602008074402781187774750791698549871991123300836636571291741055691674179379365824830053712528689948109565000798256087429293251920223442925710275275983015836960913597746310 -38633855577352957710384724542214594688978849678230560459446898122993027732030147907110142163095449206047375713992305982664507888879345167394523207078273390063547847586797211357705985431484887779194708473731225529773555654284538919479823431460921402391003100347843224729242636133573243329540020239464937136842205090534965352 -11418519121813627460668539501074538987721623610235020773026440961807389751712845376358386647128469570608293191655610034624830442355458326711820563379528062641347348121600767759050808015727127663275590793336424233036874858817808211051616724362807646425456761159612875373525989394306432922227244013311346716143027117258909202 -23149397317027354943042873346426016161327601199108945666063471769831086780919496999979734590238078519816981364545425771729658465066974927935897084116847882646720428448500046645007017019263485460655035520715119974542724149215649520906017646883096928668939354929434564051003740911570882135548879504547145928854060298334135572 6525538439655649380697726390317883625136085526120158540981026035436171657083822910454180810052337799889701733157132939987967162216963631306248946354151841079931526905048686044054630011873996453982168159018302209526423757105308869834222233008590836560812673269862771590412393912374926252890932387560646772728406172355110738 919282840957584089212278311033896293595246384281519669289386628041335166910562839252617810369136367508712282222241565420365747422204438143501838646662852480591282483009781163361573534247208474523398043756516853827697095515438050419687204988722023061366740523494950502187360690340889928869531143754482214799819642502074034 -2106396725124944308850556653499633470606240461419043512500130128946694830803953303986389998431171614023474523180402740830063374416218731211328564723206244478359271412696364532886102286023436189941731889396903472955645944736404149379654069111125625768975338619843761971864139716214199565743925567115567048352889121885002302 1500416489520938833592380855387434564876864314132467474832448149410829908341781349420074410950363067612575313973320066246801087038305642622116325307463106923971843969477707909523641003768830335645940711540361515266563098277817700154745279039195513618905568631566269264523922283043009148685605211572132111052246597313564428 717200696312480090393959541150651756276665829209909326653980268120811314351076291882632278865769543978827803797239539751965928940227979672583682126749461218742914420078334580280336243929990830793015141171123027807595165737691441955181311162697882226457632252452089174150526563371776331720261737881786536959469344883446928 209154453651805021648684479097430031504344705096435168199655261619268638323454018994995894739619392707293796121409725154461363661276342689279615799388822693822236530570778619448152407863921898073315221453397377583476033336713809246665066036007272882522061452740224738961798505908889136265352883290270477274095865364468604 214072300844975183079838600455872493627035237448941968747070812385409385220090775916734362880095192943262675057137872644602733094344829476271902210833415375952821951295682124708242225761545241827172257056041892394986241045957750739336952772836754865731321691304126663008379309541677613963052945508510473510785777048141528 -33932273801196084960368444160116967497794254059057126282600529317719002662974455948243070741234096941460029560162206286687717676709548266598841438437433866943584886609584549673329521340041839280044012690952791895663373681489167898655845213510575964080337129674460131879070779068385095997217891484221194550262997735758230 -23417102080251031544835421056008129793276050862173065034372107606821405285401944803791580723220043861367041013271680482914894410662696224462572369166977077152855627297246136762145027319376884965626982653758619845120096304918505603472485223769046397665268175715416916715123023128167068450269664108499558827800640123484724 15041506156361069810831934818961927792248322795832323247936083956612860106050988268305247859795711305764282091987267555200549443656207173618040098456311486086162584545807845289002078086138309451566972452201332472851976701178159718279089993629576185501052327474428317495147774147834341332443787949707269796286048197339502 -11397729918120012778942855934119162768563679473393394761543751808631587152003615180756475120622691141389278521216055152372423255557406826766829239018372371367878719121599536412685423664901332278484268433042931928785398443423094584741209906512005315740153679126678492604098960254414896247665473878511306354962311982367592 -9543478524300361284864973301473415881751240701483589535426033750126311686263431945134381564545710937033075359580648498025930100335563954499405754224354071000660603530397497360696008729584311586409776554158568068859309724198462870466453687261579186117825773528356915351974334598040583059706162129620240913294154513008204 -3454299359370794049431613575168645444518447398779742768764597283035014740153167147752563143536803607922503883617143351376496570684518513255709172343082782562207210284339177897556684548634270125175907717204517387322571158117584965618549416312764902379638576333764137530013054147857541693659121956486798046227137448583890 -2012794383094452546136215193117542703491496453727031086674139108897858530172781073652387336678803796217631950341651845056214595423842974606309087333264799833992114968024786674757050942335856445234605927197498597191985476970429283682745156650638901784511929883480324677822936027381915384233511954884211794614666453171572 169181687645365831469432931487518923343884611028343493378323018200596997990974599409931255861544081650356918131639004981037830572759648890668392616678389200758073791956051028154834710000213883424337419364775076817977693397944473748836986326839478428349377944461693043610141934433861050164880022374846852598693905038644 376525746778130478055680157306047024348677567702051952980888982215978992514777748678684950045607472919977934382902396484684294806199996545141851002262367687329515560919113398933071838393745263687035716550257664596198598075032528499700484775042110419695491841815003178567756464211851608028569128983089393012231172493610 -36043987392827552222555639408308324515229810887052428905601396245087454227218718182097089233917628332530580930309307821876583216016845548509645182864957047868546018505775871058962009841980211984389300069184184610991874002347262416590789693199990645594812664863684104472546456022610088860372304540412183650511112700400 98121432960435663637191042025852306445981869491554156759126441388571235516658967456939750096945895378444232105763827961822574684452112372813932660377435178274861013441958885731063962597121477173163140973195287387129674726262829830622889932971507524799606107140600065441720236242374798071323002538985591980022357744308 110453062053959845050066915053253651144404420301091557551630669044953127603990028453171252001454298205535274179078653287272250542779056065871930420224200965748139977153568140729902413969982856071146550395081656374601630273404734700451342450315931248375761532802420303338864965633559332715221387425147758012488649752540 47228384806385358984774556986651652367315920928799352521310964166955723676617470958669087692155256621487633872541940647667990881460387814145364291467305964618975897743660076030146392776129463551855405485453130840530970044759768462519037644814462841250584083087730326779587138545326636134683994296147546041007460639046 19862091021575698998761951151152310917714775953063220537043004755209126724450581861964067421270824437109413315177394337955525356236214873978246019459744436448641275508409841071660613828563638385363696785467397046221187651345232368425178175981329424468663998671686819953508157407049491612913198109865545848045332053732 -1945843031615532922544899701814402301445027089010515884174642758690462564929025091253661008793861389741065984547839360746622984803142500167201407682199380480627246046251167380672340850029280934512741851381219814069083493354904365721076414816934672750251139928046417692713192942752075566768148603363632353274689996872 -5479265730743038864904577723095668042600683955313094302002555843958482765112168510648574483018404189975193637746424014873470547466406156684965078059188843117536369363479523100427623029254134241082269801267466112390354750899931057255551590432045280255865366061606820734310609295731407355040935764665607177163512837606 -1180005151240671225161948280579952482555741942964753041451463648385990637647654199262778007070373185921937288089574937225986239263087862885504331495851348456700569913252949015710111926008358184785735047735423859319035778457383565335710040186770817489704728575556571265427144492082956936788766158481324562382360560684 -1042538326929181909059556947493492055240418708185493729238991020993749759774892466600774517954010311631045138565375642007608516826609278029271728864201258530622241678598447206777126570527971841648168777958133535701459002145925324356335495152875976410033903650227936015105491770682869823705979296942900225531485863760 -1152662135393456982776894257690105930687388817455271623000595944342764427899198974944056883203495172884119067275920726243608976049499308631075796304901786034831403150571134071471359823930387472126368302598645237067404766350549307047507786994802067830366051318058920876526686328148547672420516883615239030023567821802 -561212729665954327944125518035727756172785152336961120038139626660978096226035321882470266084995861046218824973422982444471189380376057459692047572817639710796336738621400244291897843207285576757474571857292218792609029764855791701967620953484252425450628938313507823252587747594123884624870112206389299747527524258 -187275346309567623795260993488310158568753130346584891195315953523296057179649602405455392047049359445729019473097260603627167404790643566423231524886894712937787226812087882392772970036763725232956358270047386197610390759503449340832802903728968627104635268222949743939488152520367652480123617132886977468969974292 40000287400264598049919932294379751328527828940468029177056365499759185009495189725951384724777096832351462500033148747229799558811390880608790119540065052930829984159426178438004285383618422338935689003648289485030627760624816605570977026614728805363529573980586606247072582793151982786158895959892509014047635352 74934614410548583532789816615228225760219527675481766079095209870857065889589183109330009497375238964962150871947835247848322633900543312322736509475380552356195194309487465243203922470059193169518056009525591454281437509180980842738032428574056543301259514250829088878389003433663506189492455407591818023793572532 29566594240707223676798540217321398348489428550271392453880171627930174212869190630308861523877811323797082961002089469236493379222493002956883208120018838434934928478022528357689846468812731310162560936074026393120675123170683567851151623964817750532447687926505247932039056414299284922508834687026469222113634562 12503151791398733662033061854974499948136851529400173537083648199456909893678797339360017870662095560279091215995608931084992365410937981953610036304846586788544554083923086303720062571648966945733659416723128092549937813403464092709734641441647157489220702852924006502238575675591895276072025013078094398715424432 11263713214000703411538367731057897246841780241010279991034052788349730557226927550105427469496453512474001599936669396011640477863784782139958091374202232485353990738109421293101311638031746057395661330136079782091171962685108499788133719804651630617696377823815535022040021035957669757975049075088539169752424128 5519102049269693886294867106301034442257673236032965624399007090602239952977828172046993408662108800143618795111512388963727052541487014073147201655856820002244954506847296781262312022895281402335804617065056792149039400278428266463060012351830005252253376005890969275055105731731627127600300970364741013864172332 1551587001502541115712989412727850427255417728220589044155859882668898238459132287251506843811272090908585604760247946328413646830174442628853373241289951735295161723466793908368901365378982504032503120255045888244740564907336764135725793527340869259471359411425695297361242650966447825415354417940421896784055202 -689061842106057233202314688576671105062600093450392032966022747852031790496441115498626639129697018415476061839537506425981696740952267281041698526823325340315787962139725988859546037899207292771028024960543084860052165673552315523659655509911677106056652701190140836042703177470887492064671363402856981049940304 -1000226716563825801935412015090194993640622363566551974694897762947922298232564545333065270302381140184235872119004504756645183121167839786175993510862429174447469144838818167783094207044991646480963950625973373638495389186112887847868132409898542681941955962463385340434569106287038410132254816761212707013813422 -451954260267805830020801874085496607705610107013534586531621839923861277062566598593846707044251353608622930468084419658946018356599472242172242318577896338261936914325468299696686406784575278443505761504868228609207649482309509700011299736091137483587128585192187003627011557331727960200731137375882449770102068 -168497875309529980809248558496611515427497212404327087221292190852315256139944963128565830696346265763521806595136402212836008910389844364122573774941487244213502267137604571877577978521317995775099397472313186971237332881707897565794996310074888303809970694520620906264560326071134642186317173488467504229979910 -87987508228675958508607532800951558797715452160974035185044118322553326291831210004960440540039109171418804270020855701025251791825036645770028609071539031397371165032767148273272014139172526001219473384076921043153074905734954794355588384327767809625718956722390992261767455392728724558538745811358735420251934 -48810904740626551409054401590466912890577553887037020388769646456262546274547022947374951517265089067627441238026629279578062068226719982731573170626016181378352761201827918964945744693747434709558102185840243578196550930579879439139737110279990906394908481267955326898294944160459846883789408498598467153357860 -7297198201726165284496871491043378364539748950143360553438663178898190292831855761159782169852383942981504101509167943891423950760571839129139860234236361064669313985041442819177737502873743684230831275398088573107164337404595481895276355579425568223020955309792216373688609718128287739247229180018185903787300 9293570412210132842681876445661962154540493288584159339190333577102902369143243270048136784015450446078133432141334638036879145766236351021335491946075877834239018560502240355286570499355278260749501718491571323155521747279849435191517417849846460823536544137501910688621546166837080055156829850726305338966894 12688361950391771049620588770978216661246719771760521331494164679553013322900830178014071065208005382636716723143593437180105471990971520087410737509584677875346522397056613347010241776118765349610716559334279775401794840685938409531290159858311502183517623477272786103003018880328746012706263177810971525249598 5927403359412009985177384873885256604432638219694203708866467015519850546256589762142103635019530283716518954560628121394819340571835064635202763704056720740825335692846156710693330926745176331737805305202921918481249907816711724263183463681281183507339791335189353866620300823733037592110394049493514099395966 1821162386681290485384837567373675267852377335497651169634861257218375773714961604213550656495161509453097002460747838222171745348904570674518744185490956575248342377832130258258908303286167820236428466113958539147676048700910306839243341302267795579484454929790071856311135529715912237309478794773701252272796 659359503980264718637073687301593214583956254225937935761049015877872851410870127356095215501542381764158548283679546773139482443900762960503781398054588296844710249867001969948498078369977995509398956333459447416392247392013461439771013131042912404517658017802162702642703059368047338250546895039910244757018 254133525995468852319825296366938968534109813512850984851265922871863521912898560496825113196373965612222655064167544755396130197065089002428001815270968182885483511781110567917018290339907249486041627867006765739709937871562531916580335519187340735301366722000420415875417755219513707007371728420524174379394 17162101793012475320328699171503194258286422392385007660421444127092238303849850460466799892786116876535101685331487430508187284879638006492430422862828303360029438962242492230177758725683869482556948867715506801627479860333524682540013658841055966347164008281653348626016416131426730430961938902607007689990 -152585591175416648004604162269032660899970885291182255782074977266406462887851281487945368617698294319611289352338384074241637852044967466060149397839295147168891551426800054586364341491370694207168506471996868395168633415604824492613421024975736926496428628064741055456215006270113206640280908523225425345556 -131354548601663648520166855253366805163869282531067327938650374947505689477011876671302778390041837684869661044378350909535168594132341028218557961032407339242307577473713298310494918464564497138328441923385412914204745643979686203263057201102795475792057498666687633234841360623523871567292693600259627859262 -71018000270251805986439590079632264144566879477168120802234961029042590583812480352582744563373305390593464022567829298203973485889090147341736886136345050872666617716715854058935087746110578096519250197500680996057164482587947272437374874302201774987977757732967298698464956882015476985959454841258423276588 -17576821722628443960034568671502666410297323828890205389693151733321231384691337947335745162603306964413222085808459812902114614899684809540435664489615870124050597026700858303390985049280150598891047050739543741493605279158771184305036634366623348426508831602894132177489294227716194682884866419578273355780 -3555616004402825410242217953549368700539413279244400440461757117057204058897421197380912821646909907846331292524627683843358390153394273154048982611368544244597729662890128221356548085764122800456949351156033405217614498976877028072702617582614617545012183798107629287524691644570498767196603556105228400972 127332356349378270891309041468184774640480011999267943028398467262798471501768737785165893853612773169413859851812787367687332069012341993096618067244870253938381576474359762252260866543658203329825843176025530742779290718308616308066951191340076931903758174450729477835423504560583305491735064697323380974 1141304271311300981179609349969998518378635672338290831283730751926793619180142504039522259465474537442918655491520571312067580091543947246885210095704943079189854941189890348704088292567647003971172309694990115761594829536483862599425895539462583997377318149242457770548886437856149619306624288436523726690 1586302624234319051745623545864314138476715478084691661054827110015686606953909224129368035470453656109769080256909190869391504713245828470944018101735555126589923603485039218196154500047188301702472669920815060469602449630213239565175667832082052127410397992439791123414678445290087280341295222536524418792 1462413632088003809864468335414231388785462965147600031619950499426825898392213632370781469440846501106284233790490497451746304596265983009298004247242958589505335476835410886361216544853345579390420398966617029883697246315955000954166656112766002459331366951443223223732908707468282173630338301228592714332 676547937036748978590022507867153653862729797482437278585224708203386730036662041474893244174119424549521109103224195550463793206198391326140223455818681659494629928815809606219242411377474945955801129084585145929085608411273294094682634147270497260185964104908525966459924424729136404296172150864689868278 179258989646134227772071841193664345358528829477626784457476455187475089723702462127898724512480770766808331549758520324415047034221799236712865294159865098202444122240796100832532858630063813294755662607566497285739882525304428878456490410923013496544685627742169289812488350862323360821153469293749496268 -14820680063098610036805249533826453704549568017100592488865921675349039924692084519072288584113813147467990344678632982239182837245668771719283855881133601862745985132032334210985375867850371375784822601528041411843429888711507648558814237689882578653114335335660932544288348277966090224036330910607580068 -26025258069386893088411148452594395517540400352513502817057555829903836855239435767510586330443801998632098536281851338192624445197930950234133869247011624977826165208361614507404667628419438118187113502393985480068701851227185324750799650847771837822222552748229465000887223610373897070172937616188509660 -21283391336497047793044935383486141498548848024896314439811764723436510439098910173379895852059208153956902801316172630443560921667286865724222632583453011039442748110566718838051224076177569704571757397935062532586332236918032972686116453363691471674424864286726508454808740913132262871238548297422574310 -18892175670661627318695987836690471317319554457243309376075964329082066346971783451013396260295979921183842387713333368898166905189691310046617242241599854342231067519914354715151335366450610113115707391578347217893696017950708505130659795234768571770874239470678751844284898949602283693207717696937065164 -12714207890116052396855485080935226768516658620520363946254821413944634086564785712525036628626192938459380836844081486379232667445983051492572196568455236076216472832880938762591182893791192063339498507431622037452500638090580540986921274506849137523680077577130955309171033426523747797633971717860766254 -6614451279636883491871395533045269666232705460311546357000455372056817510467627597427877543777772216014581823942506530171338774590346804261264925417816776863414963097234061977209885395010624021337782644686568557598665435109512740848352368829511422731851837196704181919637308910128897962089234316284181072 -1146387488791282421252477590724975997996371179128022966724852318511467004865391664768740434475113901697622843659130153429737206364230996280258143291833004535727525444095684087435739531167758972011302170482293432781949910511443825848365835586848162935363713338047766901775308171392321515774104025111922090 403655952135848730160517548592360075587016320533157287047698790931429147566185127040118480945817063998134782901719333962054084104324985693532071103370198224286108917338271774948980429136925765731050443300747492424419148245577995898144433978207645624587951958587302223187638727561045393801078835277500918 537874582001151130851453217589292294524247559199016893657638927573875697633305221092353675872802894291652180622178476004164572744154378814486540169356015227340320751870489953501627638501279836990260800994637311440392304931200738535715622210237945046065621944161138560937113638574615977876069442511999426 307693650603291270702255038120082814927440145115665542774859134883994472502556411583920061511465814182749115399529120750600263328126399559348510102763752013151911476084662313026596124979105239422798325623974079902131677639189466016835380100458826103092425347992632356774640906232550284019375811534750988 168500764560777237837884027267955835997949911194088058956588814596838060800856657212498914009527337080840329166020178397993533973123715805425883747490298202028671696689540426195593384660012316001133381292659622500838049246117355225466192315323595943882866269193241653768464228658616934338470436417240210 123205744169164433048565941054962476378509408698674847250949490998331434260952068333458005787295856531404684514544624405665465530570221130708306221410288266237253894018937135328925408983056686556096360398829837774384508790157785358966819716242636188430462322988971990995669532306919477667411808603185460 43549597144431549481255441024630227565347603310727849607281320202350124537376874579320581920263174611914750959935162763012765355686370695757652851883792636850532372051500238981124700486700434946145201156160995620079855612009041612465706358924529008740790785682409772573678504305924492778123862571382830 11121450028402407535341148346455290134290042149027179976049624980334307450382292222495837969992731356760577976835379716115115696302792345447933300729232901230496759284138751104163910194707238871894648679051809263164690851834925187043109104926376271232050552184742367980525238836202642927048543068028772 -9421643533042253298085379371525444893261059399511132600926831099055752342774095941246624890064114143337170964380588040374729514841411836779691179981049946939108774178911062443438247737912781856641748417832857803553153760423528688364394927615727886168778035673968742398289786219058848232831731957499190 -5950195927508184078966844826390039146122831435081836714476255255046039743463718547844713651398402189160095237401402182966261965333998275676833477344964751107022801077215426731557126415233943763863245610106242560415263563813125392208751654996330821479480152712317490211094422515293913115121922912160024 -3876737405480555054996250383524650208907485128198934158734176371427314007702262783820375028746528436857744766493326697647804915967756895978949770063781545063428960945285241352372297734266259526404218389239219616105199702514678625199289310415408545863369339256331668706010379544990015539141442607779838 -1649324374486286868988094560110362784976046388440811046986337358769852955620642681169467375681668115669268704542586316083929342745268295942479232495274836052251931349312393413437008881492860374216841380894772726606571031008866736052178102129500878813100691166806829869167704154733427920839901822836636 -763157470690313012816884106751632792277397864573838631475930132444304210397432175291754251929465958845531396608913865044827628422902301710825446378229431459505305363074748491738792693706876539121321980208906266143365004634579425129613354404901953801481730774485893234262145879518847089752284363182090 -407288375444883943058121717598527313609253787681107361229558679636368020826950529719748529917074872562378842594330801650791032583116529602076636558514952379000873562138552669629990216939905963720991975397250232922393375847418516819846897669019788341235075598612932217865396357637852160878509196452624 27351457304766936697319942827894206158973382165101636421146667765218381282893903865348966693913278319785046018999918025311470742759843780402207815138691784540958439026242037805992219674384068474915809942193318017644723177250165454154006962456555835978434351391219793376620693949617704679700152713612 60011272155731787070865373100621164788808302234224845797698692405206298493848997846175341033656006222823415884126099634844353429503832948439557307083848697467808926262014030022524910708638151813281532063933303157962798050448100881293086461212837743748099277042112644019967495397410708426141115689604 96430797560017025763839830749261624798009365546833876519483309852823229162084739689365332201704352303254985339338571404516942735619817131710796230570821403445724850276581639537719932605916648033457191059860133225894678205926659590048914372278339164887227514945769954565383743089131631696016083435024 26868376231112854563086786144329533388664556591461698382478512618279572236158425089040369773222923309393206676193837312630912839642720478418061327790517869362924418255243027528518282407139655238026628245794851680361232055583990347931710450339126429807473996694189030333963703046776048659925200493646 17606665633420999819663812802806528658910361211979624899974742019092301095810137718852510078987290303098371518758486918003143141239778164105495373262998403768565530273783936802500591037868521611586475510109652528111634206189333173445113646392482741310142126074724087791000847360281967386042846939002 4226803439444319935521884782037992057445524282079348975355870712141622217950619453690515366396153800787389266868264829309591587515166505723135556423073738970839181184930565589735455906894062189625071351313374269431145531917167532429101874503810380380124346635168362545365947077866600210630723926570 2026387673215897334496950652986840107226818081493743246305096139909475049897833042978975261459642156000035523954088091426233368915126980345196993967560886580576878619180030806475538906461511549206367509813820114966262270070303532777289755565156296306202924247625681518140328171548216363505166036730 -217847392620247509541192023114049436907970360810464471149571581791482478867230909816256576183174639671946030623906488182745731873002978225546147975837813282073443558028218972942587462294795404631596112171587007065302123220627140328252124068053609157700506858705439258862668561560277783959417796010 -1199723262527551636388958698593369030420955087025190173430281465290587791569873118066644917594211932912889483830932193555281909923452946595201312537074263205295659545290361998763384845268045480067127434186884363453617327899526630941519199733814265065372240766867270756252723356029746853566261993968 -544274377432371226375251129738799221359307070846084273589717070291410617114959601997587295621560657443300136324051703355456296955430576254861676902392971413756889534958130812609426379197226233124158112171144915712950637409075278574687503827534577441233212708833982002266129073838323742715957214718 -456526462944500913081791674298009675417340974181092004782425568759920602051593343403365539004748793029316179421551446430151537316164518762092274938728432324074726060823712987965522396726695954209051174536571786482383943283250056312048122897007657481646675721650671034498173325163808673757097019288 -48173761565844595173210118977101588831544077331342761693705543727711477308556673997709380284769626577110223684521409440386025977411109323768571491594902975006931143023407389931264735527145603607848577865118989235206762915008603844752233703556264440832946819711015777891919958770558776937272049854 -57406627986238856089469330180052561300013788413994744136073478215537857209598147179341111650133727403147572641269442316676747786878061266666695459590028228797467612817405911343636339192214404539946648986362885064108816031829080291473940683271553179958114278695998931423140472836597710394126341262 12137548029673786233851134663436458222763694514500117946399984687273818672169073143444998360962664399071277892594276761907734797405705990361393706108887701349106695586324487406747210057223418452379078538476084667900855807168662783125934746468785174944318162823624173535944594856790733845672211962 957486356709288022356917203887253891163558118997486884302957601192908902449169138219114949252663798693784307861409503002529859523043513204132116360036079005163337713208697254079604171285936155105258734656536943388587989827355008296774213940538289591561228577316203261937053883619766080699083504 10246474275955206073761840588894400012681669601644721469013298973940853784933093929512848150235908632746647134794858439420037279832180127757971839942399144775046132839118383751916249643084283977108590871731724413696513793773982763600419120512382810370301232933463283396303697803793343981070868642 6893598635695144343041252435751027064679157218906826012269284878631984624774298781630515284343702900891157179964898248151642452909393152644422197873406720177604322618393954177030653561727103124354352608449920711572002222809287292418824348335387238220526055527001812062942105050709474258403753576 2302582533546760372001712698633452569859503423236857641137290704214479311201553381414729325103704582318779652041194154025670806308913432034647883825837376115140931003855033161231375823578209529056792116193893596711822824851941181690217473552324662430424838183959683797938334742589631388468611720 1178415677524211237139380010374519865815493836175171169831755971748082226382945148228500607094600521108522756457464372946539734361872681234303391936225190315588145193168447351893191062510865822386464605475925886507336735187101046364448421449619747742856232766755663579548399967915368559002120270 -246537123697097493603105758855376743177989978124296400917392950939943092622578951879366026472982091143368556106478679078455323431080149473141125647283368075945023458603705234383575468128062025013666117700205977123174013792812399185542364612875453552233768174804289480758906025957822534638707718 118710571444048122366876535169791717229423495478783562730643745676016915624419451493399310234890921533935650886990100004669577634665169797967603044504333467968716613690516593500627620870318943253907185064742073686585693306966258574683155726206174766154462531339484230976031551322292877773389214 -183106343860702703952495317257359334799106978469379335478253490328898522951979557238595147937156351475427649873367577056098986294716219670035840061431045872878414811863801854020199547554107281829571825125398644855682095305572183764897832222852464228821436520839164442372784868930622914557699750 -40841606930333440258404886834531969483718065661090822974492935260495980731646991611046717447005574275151408010731754729389821225972116673110960621618731865849512954688909943610779421930185636941275132701184969538846296899434003720163411585855198367814356374165856620369419445290926722604315800 -64853582361673674930048274745951121803246984313549321455922444961596806304225376565061786333059728195961851972474311443393531074077867144244592229078113173320049412674244848505285200489339800815135600350364811448873942179220976721182491056250695244352665700903111938831165139381673359233606602 -17650130938258784765999318058227912361097259583355539333714353621007551647477964192643974640485502228456443775092395427500012029845549667985401473858280620177648246507688346777476802835338267272204580902873604707815918480452296304181457676910729615703725702808503467024759301899026038634749348 -5078844683824765003588737963506912866048256572457912024768486854227179240051174493414018444371263846612455774986157092168348143046435664974836131972383682835451881709976368447723628273233910769298777194800298767039932710999107111209931732054483930627665739253172869655369349100556205582470158 -299114606220568441277812370643204592728726686911487572074243271954622244008750675379822025154510241389440452040848613644247985108821498723807505898115709306439170369794173570696925441049331738645787505644987897898794313614835321939960676847352807203552911672551064418223905756750413499980390 2491667770758694718250329370875498264809752763060638260100133538860704329027365146350491530294838160421911138451286666682541440346069111270066619019105066991127381842842159641273392452856689527226391981330396328454499874552362928258297806066250504546626307518415008623585981535073913531495858 160133877549707000425370739793926179893976131423101208226414289434542910338225306885775712581227316895755575143570707585488682854853162746597702461948273057449241954910068599162649742815944414104864801043327272174069741598886156274890744604480561244748182632475343398634669139220791500523338 1026900191641680091714354394473564216304558126432142641466019482875360082869832217228425728974502636410228022192874633918510630838932121945096713449558117817675398640825418879054601408820156314670749799680983304223656866870456081681240245563892244075371302125373264277023239676612820134745526 172333322082723078878920242800916517464153206327370471013420038433769696937890201187427012190320673896886959734031930613188028329961512555690128110274124220954458519452019786758117476061795408919508033081014722928281454271788878907588150772590576499059969743133072822777498159351954820315144 249164058268121394995188455055301447302196277718087699357369798600845137177180636206401702067290499813131682262551883218795550140268396697795028056678696421831563656759699959414370504636081820198379501245227747548740831855134874991525691233143948222701331411933895627568265873662257915947390 -14379285710011163430297289065674390336606853915594380700206314322304595898879020130343979791811136729319844599100764933821653581072970701430427405549287039554445430267075054976280759724817930095757836171604853790368317748464964030485277248199930654302955031538914126121197741133773896649148 -4724243377201039294702805190263697996504922928067910953681517537467865296172808248691270691888241495781050292425874321729149500087226716386748366430213095477159158030371992736018733711349164020931221337466140661732310215328022989646365690092646997070851075662328568929579379743713714639890 -14510777394120917824903653952249792723517731552734630299640987818874195403663736122303656942522146195280793394994887294513167217368939278680958396489711431896599581069294033728612822888743326440956180405607856024175820441114781880052210171228879237242099802903896883664023180754674924343664 -10971497822355518184633901729813424114524667770861845114057871725080883694992718788844169681520999477954584091937629505999633133197655802524205096447467032571301399604025231850540212362315427949686592493794201298337149059475163987500870749251250583921710818887534731112544426462757076271298 -2702584975814737819773703607417451319021220620903221356881557053708096303734138473480489804804553601334089462673684637427554630198553839250273883462911358644617119704668181463753918859708937175848847632727814128437419663619109214884334707174181024648557294886188649745503924312415981599158 -3823690593295036300989958056144498611767407030790737490457073997920618800152971574640631256514418911468043442019855776631293058283277973748481684233214918165830058580304729864680320551874083822913461291891019712440759778459537183336044446671270452554106010416351964812310685572745159270576 -68508609446020703623789423656797729031109736809664079419567245029746268674435778513966024377843293410219384609509816532577313589206206905843726657102600671769428133852778462187824357339228293199724983864487616218988075532517086701377994597030191861685204274660271990923769955189808283996 -547410168296278120514196645784649749578066066471528102446923511230334192421039849561498480077482810043761037124249305288335710075224529196623082539182238883538639108668194234671941417722468009031184005289210605863443499207547940549496626704824960526533577437680949769468145504164044560378 349177651988365205527044889808074125014333864611366737125216148818889999814956031840904331761977455783672757409416436149283825607904928763635905660655885833301103833130126038439610314930943546284492765550395676617287517797457655435457780827277299140832473406072358736685104434696982292932 76484677262001709109051664883763638860515803522716128992631133365314624926038324042094557527985834665648519818553249328374375769923650387922430128419562577929552172531071988070482599106411809730068303527474116479523887011142606000033398527565835361336160451292788354642873238966707054876 90982609796043596911580458854054914771694887408363954080049180338829145522048156391753096635177469078922955590916053381410466537435464986412492743637928883255061314825612686111320262423907772487433732494554512094699270037602040506992776771144512814762103106915660526602668902809800139320 30158371927321616246603248546626541920508781185765187222541850392047487973213018886697918756023234371279458429952533366321255396695346157167947014587052835412294669148306244369740831220824067884041943410269368007454260026174159412287109001009284778240379837398333307551575407145312113710 11263905032003479385060075460443470006331001868872658136198920705573526877440638119894628039290979077827618290280974579496929036685078432032487477159966172973395516932253129754776496519502849908973648420319246540933980489645720516716937836986694099924676907508916441146939226877431185756 9054408605249926624613588749375452189246555163233811208884406950342876305088047676632840872486161309863978817734107128712362667627367930227840662806933940387675385784132369956911035478174107905937049273521193124147263224415290276627561865236852038060735600861005551661311106090261956476 -2777732797434958731526956952128544220772120251610356882583049296548243693114709566169901461400198217668364319101211713294741047431021119561194049875973072725031385261043663887865453489867040832146380493290070463880424777703921670171643987675016145406502306789780513485037853727531547354 -5642854569598616100874402685211877557033773663288443842452784454459278407038306282653574135801278616544372271638959803860381833067259428602551356806987756655525068791762234531972060111549784750091480707704412157076674971293459595440391196737829379024413368052155309489113719874690448 -1845023424268313708324500353285812079792948897264268451310534462633889919267887444938916738739656242319914579331232611783289873362783653681794201154030051130703475542940362348372193632426073857900989843843746892521269844502264473405441643128284232800798750191494373289246842179971027890 -240694538948813819660978713715265119496592709704356871474164943121464299430316396178971357664083085625149657035304579544651546662768428813734712045244262958113111591580404689868885676640316373770420406351850250144125936598389085837298465109704665535825664493661061154539022279788133078 -340909870223682324064739361881894727140191574311165356786299022948557403074562645983703896504210057995427949535414569705312336568439405235593427625019751441808814423869798726067236984930887857809283569434310017400017401174843290963502204447792958049348060869471618843181995883848614564 -41714900128026081234703177325071102138217499328963241945631434129492783442871697758153674648434161279050047815258921024030808785685389460480517533551567394188711550271110856099884788908277059027237671585740531204631177850924774371513115268755232390546338900807195397368015488358149686 -20664544927165673025098606094880225306377225885708730821078473879853053048828546443446584770815454366406207789154452626405879141181445627310883110900176554032383928224223272144910073534600923376496571904549922618522815140583319247971912357046994618947984091572240861322956325872421588 -3169946846213768524344139925624567895587850981554969857697090532076241500652170522368901802697894701277286218658595163712067604021574717626820357660965148749255802923420456091697402969300131102947292222019101195452093685800818868194960792577261853214219985472974894493648800257100750 17742129894520393445377958502559344880903332548754694161129783957810640819981961072153422782790179453996547032734071860163390526165087107973142044315698651682622755324883960410899139822567773166949974414466554023012888097989497276061002827435983649688897670140258418380976074636134972 4761901316027028005408398329338448365134997197977352384260358318492293597678915413143258925520131310719790327261352099136275180475200726344193000855260099474155780408255064778577946287447408308904102660632170693281173385849971568741207529392431361563024665523869761276564613394651082 6269816057584656019121675365278355798684104049914319960854070782988616114018754818090552647561117434546720230635400130613831737673877931864821754962120803421692013660608158396608122568800245409200051292561368937665427626733044364848737389552919199594277549908386679004912623966888346 126469126414015156913186521977920823916210165728762955698216943110174451841618294572886231938611452741615181545025684157546419713855733199192562090632212782103554044005510601587264163875004346213918392420151136048853503835988442268285286578495395294359362719744693140927040854966168 833374426084492571505381167694168828861599218817119409426065144726229649860146844322846283512567773408458221451195991154193898580848159049647025938729085066406029204245483199896292390640271290220398460398734973241998037983604050002069858595499039095712514900461687068327708660806520 -114831291105557027826853435840547678636308661222216014815052215867308805130383530672169143731752438172810215539983462572047612577338476117644905658092880382219396147599137913752408345521727065121963513565806379112026203610743936247345688692948330676664523899283388092825864083297354 -27268418375161137749485130958302581385995805982529960744741832001269376619888808777270146000398564643034854928240800315216683686013219003552145028700302049076597000208648923499353155069199983905414311070242577306858476549216456350620027065816234721583703641353934426395753003476740 -82634748574782194811346506031384133751075758324014525894231438079937018484571679963260871457310471051949229641542988551517462590241777044977069530806914639193501597540849351732687187371743341162511497354084985666562893997137781286886935152956591840923908012635812459372050371029240 -66987181353249035665387852819890151612495091484336827626281101981743604291576695725558083428900029282831907011836153295905312030085282286390592705529429725423568595886084517061895254706601819203583041912990508478696199019049275298387747304346600889365493696872623352321441703484316 -17194604243940188261572506905682221661232973345768806842067227802231212254294179063993718485630023787322149554812381871192685184530712682687989923739079895020114401678932233550871746869705085682798264891272518670758468114576898307214296626574593288360163378273824878572756653714162 -14158633534656743948659003742361600998415574191133190124962912786022808381452588432716711495117461341260154559096389780233810527043468265900899888561041095049671908299395266462551739486144357158257617589596443201578394699908942849924644745264804036763056896415485109644025513675300 2180243669002329814772300298758896248306551113568380085965893259424157874638990162319698993191912847153321087854218707707620260515978715960415187750790424657619686819085017580537756101477439547826210649132733278595327364604648425780088916288733636262705152144733557780692129734764 -1027134662306011277364826379273226238354675250200811315432719960409383636797357772200090367384233049762433408098546055747409481379742975460940045319635730019376208888775088247410249961010323572697585140944832242467698547846495136176108083222439864207369973658227010355163388507800 1162774670821483557758903145539833990617498136321187940105374462166905048305921372085534319101176046949249917333703471613794443185738551723473037869491929214732822222425202712277704580106667009849870463746388717318766903027621917196264167265505493327852807589305127414764432154440 348632729463964007108700676831834548215357764163727454647728485751060798152695287268011128778762375385828212601399650396188450923673300304184919937959152313597394394242692358617012997358866158564614932235693866908155286875340333572878348554989863761528730426774504253302249294426 415587702021093598389290072989688319924054672882880162852678087008821297624375504885525980630642849749218769262678003984700893286237254664417634207827075902906124251990999876320731016766831422188765276738327932382830887965654411578731817093127972876803896488005424562451212363468 168089358358995929586218824593383732181478643392863011265850914215275351859124316543209015907718681759060557719408154968520267482863415937195980987537603106548863980224773444453417945174727012540027959427325553799758429175454699357551279064150236380507582435409920128451482542942 23510384768923510669408140182968549596490751251692866415097778720434378322149321658796913032712970580818774928023520983116810899553060208383985518937693448863156300971625101906762706302600295070463522814501324263682819272404091904803681224275304907353581104266665913429393057510 13973978850670888044700916399416626411099501262553755477086380806966649206160173210229637125277853518368669567934976320866222841031717655796928687999038713255333106899176504064906224479191262381530508025465310994458538752477602538102265552506920755586169464673330785676428099256 -12903657579581636591046056775945000030802861812224597682049924803670009731588406828921503037914796267115968301958484161871198037124497539404949407191253872065416178611533860286683241026776616112412811936338429980790618695018899415393820394580649430818769170285022719742485454826 -1493196013494134393590008759893259553984382713246397246217826749350132818529637226551264915391313182545628398579246666142683687918436739711179639646250479296701657018553292906330862462750254627122147796997600972180496340587102934201280037669928226279374002621550132619309549462 -5159767407695152830901577047803641908270299141226500858216007582241802978772337481199308447771041661670996458277391726979840714673665609176345381679467663000955255185997251432614834435720919377481751968911963347209251835558606957825098540996440443841603560860651720550621718174 -1406670663802846663732827735700409127150737764438795824395216446538927810392306481564377668530859830455277854159896031939586617893355548180714999675147324393382162798705261887005110696648567763085750727145995879671621510754734742707629361084653428917579315482388366974937033318 -1112944663430651598150397383397238218817629731959840000061496124854074048274730937533677281651847046514236246670900525583076249712336114375312104854242483562193254175653703743664489849813910916408628336441167276388778436719093618983000027967593306018499248151407460876764946792 -203001564256839549299806148543741247763005316472160051469600545464533049603368911533413064763221753567959194776501463516652927939114480745257835204768945746488439135191011070152754737999686754306491438041679565219767843886995204372112368288931992044538364093407568030323648846 50763707010656149799795324499313331671002866871972481464215136731850009239585059598442999143101493303554175962352427294521590247364656518595836853906229717183539796971188084784770136634250585078133895473329208720393053267067629920055755530588220458960929612210849099585364290 41245541637237176380992255292187692872987374719317231785242597326339814691986366014321490623158199722917202871670185118197735284089024161631303692123342938478270034660838962117399931368030115328346994787914459222506237467970364228923259482023382901970352996629009775166285740 47801213926454584304068784460283348814568468565107281488869293816962196863896671034937390022331980100340780936297162079666429720632327105827219993487319104335572977359963855380186645635349153924030886934818114789076306109273106660661224853451116787354632872337409694608291488 12717623208620396278134034445091464778481934655034838750855769763097169823179209275201275846439161393174459757751664433131816581085254011520863798087547953180636175804614386163100072794727066490779109309329243411102252437030975996517242348109697275319609688543414214536142642 15063838134565942330659287438239941511893146648424976344167507113818371696628647299135077251521974317259228036861212146845649491458065483822907421593952132126850726648664838611432551355890687560582566388928211432053951479597029976090759873133916913078066101151705965949447182 3246324352930552433791066887374902087949494220850307452467882227933409930844506395062748170799803545235314075355793234829524568101543242198862737326356336660574302097734136723105374942552323313424586949357831147724860684106975436330190673639834803149790125636418123727332510 1496058307171945083030078602941300465621385427598626544794756980241606333280711121022312010586175231739964619270143523782128783804964167268836063005630624093583141505114880958379299763246317095940529883315729741077511381171345458907957033644203337342827880512385416004895884 -459750439961489209382512087739571926212538303019474567649990402470517499522328401734176542544484448006111863687998542421431455222443660746456968856062368259137401913901322665012130477862474268851338731453452274586584983226484707345063806367944230911058642298252604718264228 -394002428844348604425147417285717604750436912370260068846211737987776238716951807601803790290379469269956523135393563296596880421166404357461051711132758517014873239720894683694758005037593503947228871676043669663431161165101076283780504758739273203399636819562410423299678 -247157315136508908974505479844118236015046233615272834384978741868785361599766680181412822784624379743983580996080484278114005780531912535647345179339502539949727163316426413095304892720075699587485083080610060766584365606423021530726450143926351287158333391356991114033956 -131849760845088497302640669921605884227590811141761930112154864831371221908857669957930274513889214201537682948767146318077587964292910340217579335868750528597438688446326907436018372776202621595626041725433078940053132494896324110902599336968976619482334145047876548116022 -42340465796176876248073877911025899308210276623438268687742338641640157095137491797691442969564559796807120661464611785711240235615087570425146270659425061464723360471775702239008821826994130175928818866624900687349951043616953826110119423863435892180330329769450568798048 -27827030231360280824906560411547416049877797066621640819509091798295154611823810322458910466099651965216739417675638116973147928077573612589123211890912194564395250833666892180209648505809529419406154869065935757900773226714645773468991979226839602086379349097562108325110 -1751160810365038680767244874559639838417685679257461525157416517000305865717954622874111009019218421923917714257473156713433367980084928832884030344747323359901861041559301206329812084446661128489837139067392886688299151069720101353720897656820972583176927054110279519482 1437415284756864136127384230410776426959071512786390706934332040130419779183909684788624028378628761499149701332842116625662940797045641587369034053906272558894279711937551204795757906179674847783807893245234372614229251589495815510595281635666541357387946045395044292756 3425405951943451499839479432287131140804116194211440887084664948049860901004537565431660506058051801804386710828399971778801897140200532173537912857577282334219466429387288571525112419040515844872119698601389536078907928186597132157580356000435577636597767119022150401028 1270747993786964838527755550706174586170863894008412305953659606334795932900882224818204629043857385017729163777697855261076580015233336190483844968338452671649066850007086068642783281625827336516185664573637443889918672357054050595105740908108090484987862516614131292442 689181956883402789836693525791161024494878968535903897691208119735780602159882706040180685726621376987827110019996993590056615695047186459964215522304093891120597749182247964822191002425039416327421496001091896050608901517183013312005277263157674895326930410455193522476 252771715074417031348997623833919345147466670443650244408810576020133345286874247198554794684879122124413122203782281456780542260348180711188905485355226568036739172987498131440397519654021396554199414387169626670266457101962114736263568269336764798820029102930524081980 88088646775903794766223527128950207455436159506388371213711887825331439212230098899515600184353404032695483706014772765619885533870950082163820650077789738593657758723805670537409102118724133276233858599760937531245638023539794042784193353563073722380139317179673572684 14607220766537183107143516139561695984032015806125146342376805609803590284703345006406890423614098016867981908687722957054275375845161687949458586613942153749553256850800267299168110373109649432797534328296815752270631191853112085536108789754188358271427713249591348674 -20202467171010607905702552812561647558456584520979654104807232113390528424985960050983719273685913572581698849488453190122966709036696116138152866160964167591979926292824586733112217467735007811488328898731542981601716369696458249756360008266744393718743906945244096360 -13958986902177264496732163181037314004166194263147658460424017122316626046416286211294037616614715427842515788769674914974229812582809101211738451941784761805543585238025477039629495052564807948895919144049773631039095374181960615997133851314124017063915018870237124928 -10619455311918561869315489575334920312604960373141820053594897023330569329718186670652004602378323320550228438831214093083412851401945929064122837068389770096804282387157825720030797418992432682679932121491227649749262663055346608199452337867607260801541731702058570004 -2580323560444233572514891575764718591517671751817844582528338196326051664169213394910660484245603508836109998819866232828317013674815610278468328305798319471735877695811322634708286725038908599334679203829384087484093897068833712570273143741064509331125116867723376660 -1267779436180110486420247703085588672695337064145855307079083299791587509257201557770740517565855930373239029269007075804598905875811139971283781991318300631637955731303455141336088856786097647993200897738996871748533721258887861165564260474778741520673090148131384408 -192850031530266152166037052528628351439305318384221159212558148515493156498533533457851477283690377249475686485433153522723646613422878245716228515277005413032416165739716026188741151054930497703173337190955857898686138771983253253459558716762013110123065279073881520 -57039694200757462212871938893445104510472339065001594334437891826652429119650726162159045591459206129600212517889231216239960978785043879886344859597231925074006365046809330654429123150812192958257752501118267889362483821587292497123487966978184715066537561475476830 105974348129052071679326470218362267639198691176414886490277254345552735414301343117749427860516676878440062878740128669639793044814124727491131145395026802156379272202231805903403381646123544760598031182556602949286804245785801997697975104119835627866624379741979264 98283004809737338853360441916437285560837377049117101391705314345143473969749657748927957583461177051652200155766482079134995918047985701891911031011556966908071955283075268210619795231286036580834443183428983354219609873185738020198392568633295079748431365060821812 41100949250635757293850588209942749689879906888554527964785937328728190490903957338214065601793086778391934111345262962595866994972136291480034985664953514517557373823820609561064822230794263635841577835174011985292202689523091177031020344591998829016807166960716238 20345422504421718330192260605237230316642811738334872979039522533477097841513943309939904046977293764154082967826239216222891200663148348224667395262334225296844623124979369439493773611338439176751653047164738113900328037277731869663416137393927095919252025206981318 2441269264493806080928338204998705308282728543235234159460973771462665658438698137710078025477514312507106458052067322818790822302903025985499833736510692811557883405220261378203031452676024201088359162661628665993380240543073952289996917463582492975691667676150500 1368361674154447225929658919733701564020940051423023923467905123223098527717004383116886816810790988640694463960067302112228507777451710902092800298086146706736189871464576335646566517163367707836443356591508913774031971081350898874683213022001425568653311700536992 -738555189157549851282151487964646626332081906702688562243461083209437253314166661927148142049432156022496905255145636242655393898794630312107963178949343974509062409000176995245566636736433742525714444381157776631057948972436267338151433951456876972828762912083532 -409044737273823013350602013337708772813894543700921850415842775329547044893497684967729738418215871900208803054469386894248722660025755355902633661899885102839798474754287413486448235921505153409519852258510502320492535873687275716247761131851513912046946716573128 -460508790946830083839035198932195634700590626680562806682724716174724627742650895752577063789877084893407129821788622912244944367729893252814022587077423968069436650743856027606915599814527107432981118837399966066073630445929088302346490893761705983486386547208660 -256000030815410281261735818548976320160140267452193821370691421089800769851859085410465301833733609618684026547794711460960659341093300376924172661230829972397973859854460754785245100312327456400559906040279439546576897523664295213343084829898487544401966375173100 -68127007811356471736331234934575547453419927182405494133858995676429340678959460236976352290695361105452108142879123720367353132922607980989389158770919307376723090964363098940291760766897624960937301336652766611901690880120360369778729376094271796744818625411934 -20008187266672514588807222784534285590436581041470007739493068837376163114357247480200194443925504896167995594270739679807837109971048255514696197714502587601618640638767864878303943373402862842384628046247319891678274485121071133728094448079763830186902069976308 5199584217606728765474713649172763757123186573214127333779602808590000973368827246929162063014657599967794780557963367190236593048930880200623762158658182491974649313192096623995641218343297348275284778626242771126229216419582854548804784083830219729136148558452 1054415404243398131987608107442152755337925185873377021630740200173481677331624678131602465627746685849457483505427309207328888586625273032378769022086790461092184688178467993143143941938139835862601718729327874854087329333765999728162104875965260478994830052300 3724967610257362312275282728924527659750271329143139040895812590961518707898036682728765783629040900335251071635396044113107693176102578955609834575869452992197628467708015384364632116198237623123222771676477629440815018231955553800496541525729657773655770340692 1984274548886512084965719926116339375444467756102738395441542071919660861251253259919748329633509264817815617722470904287891255403915211731716656474073135062916240859083625704980875175505222017234050059157347234658218105002013175134191219989817602702346101746428 1079888450723165889204524211178422610894493849775765599869342483109342460881932314338765414909721253170355926311348563942264895459944252812972302749473574848518596546127624569355768865827087346451390106574782105067012119676484904653647472295582507641302129724464 394088014654202485515905378589563734397059341909098095671866089711291918905906654470960049225812568078076196719004207802969817143868406695263901480538449179420814284109926511150588025952385168155860966932121617941582221716050311986686427694526940372312563869572 27331240304087927248686471680304061857817373253232678994537031210373294964194975976577259706163560672515246637331865387004037881493508163133852986493460934615028293665460327129659264350459907768639295337401866291756124977575708308835886169341414343609186263080 -18028697009432651193610299710315231883030001856149270315634651438652694055403007681663622453371367959641663849223913367109547062163337783748436100953346675275151911879773210518856399079966652446295159741794396491686061349552798196814008431259521124652544002700 -30611306256849485806249913271269170196841347098641934354223883748043934529704340041955109452835478068825361355740339493879820133816558066991422887443620176217602682814405801966426809970685225661855280692269592490889138458921950528879336983755248442614085936776 -11361878982724262251924914337394846046874502211699092065363990917692691576049402034599531413012288302032162030360225038053549886233359677309228592284451383846141258160042559244868982594170432334432622576109536651288379316812009809088562969682775985048270342304 -9608621033096463082527305460395785087203628807861180601742714720631118771737422018738621039746737641186214287551553536215157046875407235025223114578170502720499915124272121173923032861316173130633955998822787630053916550801653872581427999124039902651970997048 -4897506498946701534720005462999795834767817094147418905393243723106934842096057653205477396822325655179282635466345588891465635378078574948596475204177583749317712001450552474567207994257888342113310334508897486051747328897901810765781773674434359389653506856 -1497678066472956800941019170225259452555045788698668720836051841080860803595589887618834745503109809077095545626712451239060933793876652276533544546137860503943277717191785321702907226894639868306092612503266240688232779343031986061912509990462674485563817804 -127168656921583950886999170590214146072799728371179964513693889724284190266833723671474927059440458406026228631471511698592102417850559171439447841224215164375517843082324235185274099998685684395101885727806509511850970738044264144091642640898132409998145612 216238466230527066158259780588800264998561931604478034632584175048010550238232887943417212019822142616288704353772263778409871382941045440360256680989975248360536943659645640154034931012618816276286611184598509906616165208830206450335299891258423703153503540 130059196430756274702202619964695830351327176346235620420449125858016857822430687847764810808817586538378872679116106104654333260146860352937869156244323702762864115037119201314751802075687019534324654219245363763788866187565634706789965450604095561948854652 78851068082058939614912045805031628199476975771439300527604369192805721062086774602176655227196388989688456711142535837673294681829051924431065914918450688354180719055091993547491892510255750501988076926119744534963808789866115360902023019681036630771349428 37804332023162569538631129493182472902911466033688751497855226130439279720865346662481977585964181773714893652335600638100244104929757627215987110011843333526827581820140333541598849507156388664273578801866609049583874246382484312189882574722702748567412440 16737635169774633091828736698241167044200810265427761272835177207944948421430606028305939466669626083976500948192739434866004986143519020071792946704600954833405822130569471827092861381722347117605724554226178177158962738630377148129426699411019899957227948 6657642116098866021451469890217205968969798015501832734639878841096223628991613782479738295723088530008649052631345193448072592957289171790679449047397530912074143104870349441052982474441095556267174210754778169226438733065716857275665219861602811279647080 214201998499445239577626475601223067984225193121520810445593431605046114948054124925261072907271433844874839144238276721098679198576066839151523853881618636678478543057518889681690894369552148679895435674605400278131496879272550958022700322698642473287692 -1207248308333290253504658536955773064197136838752537267673724260304227031434689675532743965239910659597581898243190862499670680690937772580350090671006516975749546319105007773932375059446577470775851795023722974030904477091429585260769291348034676729946828 -770254961338804367390197384633599433782543754884530699455470521660339952973622224494573139747103905679730706674638985786471254991572286763963859214055560481749032386046449992347036740114832314611735745043185585296547356118779681130302127603840651213482148 -344515317883015907019124284520222454988122032437417960013948338018321030339378165163548649111965071895131085634390357009132156773680863381252375780974879953691227373441758776193610898074237345593164971730538665089067984357939714366926929330880466593462392 -129574022469762477754596400513349196846868807515746444881169290875490079454007012372901830908987696050016076850867415340889800131784295120716736053567617959862670568015991753235580221568213537201539554701932680219836157434463593563442657737934969211960364 -78107285586945775277909294960412029109288472629587544927388817841896898007287435295785257551879605143619712089704381486772709974349016249053568971685970419446152467744322742549310964918275398385223677851201046040029751260423247459275162943466387228254784 -17347749621448063281397325526839685035661376560288688886640263106669474780872581732125066948811732606025791876294990431324258662126600546987886797786916566851885005504304410300537085952840451647387514865363039467228729785931420457275258256517685980855880 572933223514324325418199334193499471064554984258265080935014254999210458893435460373205033089655364385990253390580940796047188590499268238129994186304559083822562147568615758147419632063953429991542630617513881060779938421281981608998138541983049596332 5102231251726480151301814632942520063061487719012419373882248805485517021323759306656921522254880379299549484168670840560056735216232491860536183849123763738801219830223180425906327441191451845309953753352368183655665286216964523969623732251617717815940 4023712959496451499525723417150005215468517480998928551998837095665759494131393057409736858170008532829982582449645085354864921259109022834231084275227533713882386655503958846082101728163943671670449117558470485924771975664944018027567218574145624602204 1443358473106896592940617988555357040300324560629890156272527243638770817504697673339602614004901460477697255609447496695744882515929283416671384498179783118918433644836848507563323434884270772442753525337870090936189688373582383099537523637249818762924 641010320302653464349962867660167434948553738512780029006119231249331040898087126622779505474563320764297770986684960467321544140161729544472498052493272985415522416986428734471859430025967748463856612964965018207264122091277406655773864947456387533712 132110905477429657991413795698567179998713748488688143490968694603156322350337014157512690689565568107464997829469013367693763981381120312271982380184823069894597241031631919048271386202560792967407028980216539401075387651442126663190582377207005126156 86360695377340938643782914793708162079539997461942264379561725083607166732761499043403268769327635564612326417115715017171582506251721260655382216459839031258493344586847672109046008640969932781277261605623310419722421920773542919675192310557789930960 -6487948787520085794677450176638407654756374408080359633815176417274507792266021919792818082472094550670622312984783787983864691998210269342088236174633829829152596989003738785085547363299392348586941554807321351219308264602967066146963874761146193652 -27929724913503260691419090280349119155802623677834544704918601382389116284723761087576038325242038818508688947843001832190296926755697537456152113381488871493730265397917978500114949611580765770054522976984242873973828148416263984055600789983192077506 -15288801316118692900891342302278331251545391385123925539976086266750488626026091633074914150220474803326361553117929507997252944943759386500077489768767513900422510443287127694024073975086794141470734593675032646613441400064364600165502102477974224868 -7453140399143821350873171586399004555727706150906924507596758602712442541706131784601964233927928850146918028175546615828481558158847018917864256104842537176189228236016859322508240291355398762842345667672848185688096808186936966232280167598368160636 -1501692375640192207970876705257155062644071091618838196564338718189154340610803230049028694712410039921723062142014184695597024149195583346537606707741124419906620306150252961724043937851721882283492793622324307059419512742485552499723814098046320366 -804887845062317446301819155566016727925389319463023771718233614610672760838103980596942139224710813484395146541747778841496121915092058115558962203435309021396277188462231754819325840677456567089920072033010103552621864529267834815525590641323256988 -29771680844117682204316273017712175408812453294487236468009677742308081656216936769847534894932038706727705078964460483434890007653487282556626752303308892571557957967570535930562437577126499665150605552939194113126551856554605551046880544570624628 52906780000587850067076033764158603598386877972449096719634242512433335469772909031729207757750985028376637871275403261872665585735333551886530732362236551331072157127053688364995106944044647982846041248188912985955466061552897190753694720253202568 80182856321415008743483742171986551337406253390571734695947131951274182032292019956589584373114036790309908771697900268726787101327313237038420820460733634801132697876827216784493888186805843975718738653365224826809228089219518466021428931541497510 76190122634684354771575616970009512362993831575800080121452303535818009360884145563434468658925400449276923451953034579420014366452023369076626471118635397902244619125970553250319950469253079142643026105241430007107843618656657697256483545330393616 25094202332983223532193888603879213045925176275093864153612378352420674708806085079620251416140733249768768806088415811476147980504253674971075606684803047221694550669237992021922993689378285886874848439719594771953872577191099680956334148976477708 8320606746937488093022629825911640445949978198563318298798860990119647834441349719267869815282781037193405050107910570305982542182503358159682057133619923716413654823855597574301418132877860086637878073109655911232776809407227146335599610004606410 94689956111052108562705990911602119416597525037130309739388773588755411663136589977271594299604776779889241593542344957611748702210517295302432236812822477314672070101459156468841755708032113733270406388770686967470156822307461703138515184852388 229787067600539103020996405305378191543999354964745329581070475827909103368725405567910865267398295228821881773421006893255106925720117698667305217023914402063691753597038990414652701763685361421687846704932512767260821018849801296404809744240108 -226158013541701454857233074195599101911876673740554427104497708761714259054090416578926698229654139463240386737851809582425153376376022035696091915313664032934209454900548442325074667356361589219978298251085285297420465305055835118902524444468718 -457096976670524528087647110375646284135224396001492470490840937799195613526657824235084373736904461769713562584169040743441118077551218435732242180113051909011119983083779106621873115416127702538046466157998494792093190651863514236746660864807904 -212953173624801781885229200419746473951831870102896972741824170679412756169950898993280399507477499536134590139867627962554835212699434021829834768596757214170332920151621279126042603207437468007419231798991671691556203938548269666035895252676332 -114224827525861352247916091604033199835359234941789301133624167489402614643814009107032088302954992203613959361474592774590060766881832938906410610691653107866845845977448949069572836855778996960439365437640363210678610995405737369035065703651642 -21440596255508699391485137324684826678166057488162657449128599385664591106987418414352193944108935852326811573666356416458330284691837265589885682626437238552488567763696841316182648011092341781379289970502646214993295452935399913140629023446014 -1519433811264718952478446340047399175158147029770842047486110542755156914336627071318588409008720237688872832857132193852934884700258252956819903085195274474527075551899607079970241722491752690477089585230426066049629056138228336764979237814392 2516360645772295518274476903235678717887325503834621333067083910688487930048203284977087039316193799187750824509820283843101731339382694937123586338622473526350201433446355223572832797278004256145742295448250822101032769210015599623652888829506 1997648636162811316093937540269772592572078948847151208421049724272537092731646323417251737779697789875220625653993329154089736225557296973565661295473842129939393049630127413550283320662466365367038260400564311876127019376293680117877847351880 785114119233308765702348597724710043242460515611571355627278005431586494234346418094008537966379092841070661356649153067819502236898926501590586998320344506283240751072448303748855166997977350707059729521919144311569665986816325436819505437888 1022523850154978509197066385920905803247458063709225185362805457214527075137335917590104417210193508185645927385328975212607743987862113590902928630906509942254547712306526885259589681725929822525512581552493523686735986145885263121151676471030 351675253611436951000409047287831813556873440997307783508485309222763950976060226725538815371307479770038212097391843072929141887542378905468460511651948731750252283993044418053162687905728984388525844744316581721369820969631077542170754790814 71782173595346040155170411379643548353942304897623102182035130558535924167972685456277075967006533752404086386447700024744035809796705483163941268168461880164786602726290973771218768423836478130052960131660279197669791171468224174565405873756 -8731863037052582815511128995980483870699386666579068998848064273555043097321342022215544000279702831980581751499925295958145491334229105926164168723132462290351129818712994530421688750123252645849584626976445323525322404023069242475270738522 -16800469640595503034419690386641404254796038163789836239979514990812973731783265535453267618498369138981111081696409296139670483565838801895687765004348831660902269998201863498527676406885718842085669981804015914384111387648247087276199776000 -4659726609420773373196020132684399502851322751851033742389076631133776654046166292568282310089077782820823961234281485504875566373448557988779773690605184810830924529323507160980627940419730522062660416999548996080714799722446804837545804656 -5916629732917745083696856270185924949696940038541050229003058255921053564319176299333612397902633281036238618864800608408437556251246774481772084916799034584691749751992622456985988246635280507533733601072279987602497371819315899696457033496 -1927958682593769474355942025686541774899842148544498344305062185152484567155116329856117745007922592141610358490527544157362197341493387924179971089526192907747355377115363632957755040082688916206759842731066387995140570548876883722577170018 -1172314966042900228290737230476535769955101542629053343541243371816751077415558690060588320282540162633572589140867872437150623127381568510920504835057700729427427517599574915560112723592245858090444539362685057065374611199027575617157775222 -338133540360240671449935343229440116298876663223288667154723459394504654449351833018332809860920992182332548699963152129121459905813424416212359019272587277117302797420982816330676211097615119478889991727937651109220161370114777987709437940 110700261181684166110424647037949013744074455449943761879050088507448649434222995182499870232481737771403034424385674508314146885387283090677830238165834818358223492010265242053614779483328921176164506022209525598584802264623911714003544592 59706065505758561375355102059309892215281351071635520891457465708559489008335000777963339669107880456328902800680687900657299313650606825750753886965166972514634398210149733343480138438993398050034172727686109437192670567269562311944623218 40705421739117294424748912322824222557640163456971601809451257998416681489938956016612190304625277621703848486482684211770652706305139702257068758713491790485449348749525710958713320778716896490346106584238909324698639176060911910727628252 6538886604912949020399342835259320173631769732314622396857513587509089985194551732696587070213726182650569275506028961069158995697285022390068553945257626597998880814882901235444852756343354378943703559072679351515072243222465675631792612 8788866017169524033069771105088531840336247394210255462036129859277317612646462478289589445296741326691096396348638023843807894307103689067716841945896547634252907035621924767422837608410718741816358237819141407775739226291169400269617416 3664060924645849578617026632558046860675058194289221692225719935635616524073457933642046107981753564961702500192267894029218435323138153520224172929466418977136131113684105771515261236559884559256727129976599405181673954356723570147915614 114725102487737696539072093059411929736717600798341050031269036238638383599272584751542852181419080678767607030663319580227932836578125477018838489691595202230085277479099788763921358959292624519350871533014565244347633592453036022070308 -55526969014026690365820538686339128936294184413352747539544599977544955667594023622439056950361349784435521286158828660075958797096250827448841056304199629474874023855317461029899755982451922671001426060391580200882280019792022004394912 -370924355161717154679333907283912976788024135147769644126695013716131913236179188735707827517898651851266671685506794243214506264078681214147485808201367906317255795290815073410616472886836782678730543829828208420650115181995440015965104 -105868607030201272981869123366649775794004337954740360816369218483643223514614400716543695352591573473183238467171547509233010947913226647114796503249738696352329987959637666889251643370004577357962400540318971104834565928378401097024512 -49234470660715581731310438082298968705460839816775690295347687827268942683681448104004496235825509377570882092754694600653281086657668186225740841582260688332925532166498449728430348287042882626333877495869479293232071626223869847189206 -13125533242662905279757786673590898000451535353505930554003394328578444747925573234193242026629470578058373838900434473475131119479745251260680244558179733955495216937124199288167992167198704954712155990597241324090680350198166436623656 -5375213030739819240268469809044350760498958912210096516342859233562316302676743395508108308149098525567115615128162700850984513992323107128343971230399455964415824639336575096531116630728837275372186626054421458045149965045771926254738 -4233346704987441535846397598535088757877502307980100035469707079905977158796050326855387847065391716197749101616446868790019575994583132134350741499493525300449523095149065169200943881728040775162884428595902445882747694555782513175338 2163750991642219068653841432960698218201889664050881063254396308895623929552067306917353571779360321758636260932376500725292271586724294505976945323626524709992249388744931493816962425590514327219113207185492446889045910825009421274748 958828372023966744613169000550411286677448134347278038638117991610500083753093256771543178371025302771298645012317279187542399310718527918224273658612093923195387396889096443668501784961807769326760602208043519614434884843329986569606 445903204484472763772812825730974394284782060441246197827856232463748929755292079018188065353204071259742477202784682950921871911806313977274189727511584402370778625363312363194494308906350957812830505350513670821995277697767523564242 118496049086938328153853197478818107248614773125818316789301530995004295367498246096275096375216984198120332934541147016458623086841048689267882751784979440557210478611581283860067583670542472818144527013271124995608798027222695042206 19488067348917036604756167001927439111777483365883319350814803281692944484953879658627921597573678131347546373689169104296614036611744075298597617439386756593269327906166362095238543436059071276772977365145350868596121154372609563286 25093632403578281930268150942637800977245744967290205553478189345724974610429905249289541171219905477924515915296163204908116157910655782103337113047546358128363398371175083202377424004587284572613809492860220035106940705179705786344 -5767442464758777340765522866647103922799962511971106527029580334729159462013334425636803122693846621441979549190356258803073067381094666734738259135102874880213901724348279065626474850387058693665330004819440239292753344016086716578 -282372442465437527883109159201860873139618547416328447794846976237717143512887052269173228132783839050611023067985346243647121141057358745773036866393173537671424454797762643996597749919824091388269271912622980350091324882913376446 -3799462898041158272358067414418280844069274856142552950663332357418870023320547628243357738509776887599438896339718964497624283228227776893575313586228797315629739109838928082382450557264800000356946472826079697001255352209611178808 -1992901412972601024783687417692717133370128207066311246070701787122639853290585020263958307969713004201464039522136823902486358156459636714045408504508360468176413318437068614661727501247757640325681771187168051037959286185469578900 -91509254363954445704024104675838074658978273804435062843164318471931281783567537400776467550119919864719522786191883857015875537301935565064172533978190406912668938511072958479701925230466124393625319290424787022941603072870598082 -76668218353118334810114213543539056688260362492035640631216242484849561314900910737762170460415833464333688009133508648793903703497249498163962421668318497830082800827943409618204169192936197440616096970880007934228364498649265978 29114930353371347822440003159276296324759419950765453000925298050571383906153113635931500078328450271336214796952204030144528336055351476189078585759795284816288220180039835692211892983215752954334286619531594036782775110347987566 -23048445975742294602810040062472216866315140640628480867161885335431016474365944257204844373221682750466427921989132664912529072085636500310441226927938451581696540058686252178618806544200894085996849914325230018464286025648761796 16645795853329158200415013691709201528262553245311326647476342699895394365745399876412694258064977699477104118432694518396373593399729165850404544863060134320209243361259738318069241765236024344905511651508260972618405649213987516 12178690895363582700443134136902700562600851681821604856195928430995351247324870541438725120515684888510945809648354592954790804609280552690006376228308462455503135714203745265208244457883943293880329391405578698823114220749433478 2419387694813663948595100389482890654009149194275780095719125319829736033781009561103789505356470197125374620797446388342491205951120762376551841950180240365290285237266627766104063567176150378543681702223308456175906217942162684 1961209371301025178441977709686350693185718238512015214538552931923844732023751579457096913659490003171912703539390119920427977974804706876760625752867067957339964188737399299918246865720659684880634035154388547576828444345185174 -439341991495228858367555666490772905986357031764852388094341045025037992239546225062737291683061089578456247359161390287367235069180142928815276994799210406597425205044568219794734228412383650299462252024416761705893667950718348 -69376103596777146664863401095553496222954085237768239383786307406449222976325647694460198642873308317299232807247321105632373934670856810015316760602578450014389407584431433204581424493248406067842769774309616179750427060077150 -33129559031536273419186715090841792399681398095115948079032927129904636966003918937998754731920851831216214838712003914585963422337636351716812725759523065020694650620581929188899494147582769613613727432840261885787425923968398 -22705797842851177479379766084224431317418353311223793859367056672501167049313221229218045929451431803274747096239739667888720879459207104765811349286384435606091291911224313751936304074351735686226867639722678267390574313407784 -17634179375081243922825063734437463805688110343372506140895381921343372669879817490800314821300721871471931907811614723241310696577425861781425405647340309683581613186082235899291615981000013731247483725136158595657407534993868 -22628247834713632878250306731350161021000064380215825550899704987463587454463867571864706444342769011557006774970242067566437133226508952538064590954367507483540484388504098504694100035041676279835181633150453320811104787111282 1463860957681392730284148143267455326324574601928990794783331280563200635789506129737320639302502529535253965161223064052348168032845448926947719498522756590875122068379034801575649578809903066795154927666959733999215683264936 518002097110602473740582425418272879914190883195586763405397997257319649258187781751867007957596217526560251697194016022428803477070384758359793199451170115227628000804031986187154191759291992588150708041777385017706543609424 385937139065095413066195249637602019663967262895916094758310678063758071213775663523365466931459463711314160427149065253489723700502359059024857680851556696416336310974792275467889863396982189165803374850546088554711354268344 290466898574777655879100840540244627927315979825295372978352271112934628389164623014724643378294435514116335898413146557509752922217847055688468579537231298676343191630846859003602304115927242041110450912560939745634182321026 -15722831898197605384266889731871491932525196678114932070251160178756979370926978669365787823198837457772652574625709887788083515884290709559398435301016144097687628412045827659119073485431322073445199899279714128785863422992 90534621001230601396898609372337410371919016124998889411659821313335714587582338314700959611517241064160915444337822897591863048268103824317329619162099977687824699214425372450427908153299457647327849629231521746075839271284 14669507051610793069755704596181186581177497079619295379425753354925326759044529538710942431362124426514072913530482139442685092363963154205541786190581888431668702179084806579188410677480057514299946813133689303279960153224 13540651000511927650174665650284819114872713639801483002667031060285319681189793149405332179440936426869618421627151619630719645864774146859745996974066705072161755955482700219596000317621201211384423456557066686741526573856 -3557676463162944945027474281572688835073216504239100412634086243353293527055982907334408029264600728444943391177046081220945904129737280593661554335771342401593219387570047874766257285873529102927744312861763824452367533352 -4370822707655518573593054612567259980594121311785875838841951101581008006742882333808452198281580533914752037908215574210051306587129058527078562621464404391993033239181516248501314195648333112082782376169025196548170756768 385285715123441122011897275757787784012928489107435784644546391676989018269670767168006162878788790276797360077719291565009954083292672557321370442919549740399494143994712349587042271684171045528940460236963549553612185374 -312126762582825655389602772759410667522190678794517057690371347444422401492642109238252415908814341145192685827629070889169243167465762079762959439405685074115775894750070073581927465253136319891630755093788521049910650824 -40888648238604395514802897889874713529469516145245324961669953045380958079303600060526753039688581271742397243855724981203425703234876302120990821031420912273040926693788256290894938704744586998944241353869486266161578712 -93129840718901848134371707221030307105931126295375665812812715379497731368174337341587593114871811731575852899995108248332822504865155899199526302695916850024535563342828109295755133245172133802475042596807137793546404754 -15395394425979117731772384493732417140171433663256467236064386682755800651033278274698249265778171796852137582296457841632059308713803388908181630574821666468221471654593661002734801238058202002167532885616521841111723822 17798071344016798661142635090396255401091238068645220097458105177806998757575617408849349004120681766849453813240759634303730039409923504336340274834620791884489178731622110379358372308770120357833976068833800611353910032 2786659975219860705148631709566450519740315360052682897603568092848406982014860689384371453856286100550284262912570024900004026412930063624207145780246497485177207052447997952455338645416207717609961703580931035071188208 4946480045984111729570808572110902041463600551635346715402788579326763499633360989316986433216812426425226463514389050065037451831735743412318334007896243452778674747125346662183219407606831424485832260789322481837338236 -656243333826244646675827509131960335981770839761586841644520605137070969976075552641573791998188106628922688890829076957405319372004469712846078373918326139318839097427598987779183917191239639084110594258622526805932764 -104531500027126487734434616815922100350506228617561940706666810932661261135571941092885518029260681944105425800330399455586098855366626186254774706206240422289186459353427631411029153413418341759028338443660430664195896 263158394709054936698457586314493736311592380493246516051808245609047288630551004031593560656637157434506711088820069926468169475834377816721284355690038578307210729780300240880835060282905306036149272947715859704075552 -1005515828001471643811904688773139801603817712262595550046660009945795251138081996353453009931726964683530327642496528964625349673698219210581704784284573385246897158217905221436758058074758168201182038527124353697982 -5244328722706592963753124255922226596710529461284227090488974116072287384753724590372473165037614180700454525887580923931627274131690296360911599983745679375343890869294810503447936856654582810160706511902362097082752 -38555333522489666698845742592240737510703699425459407878311927193587315411561354805339320646314670321886306272667045440073913873029206313279902434030248888726376188773874081361105784816597492539044466076417638461990000 -2715347883305003687973963772757353843487942232297556115173479361042017507420248380700379119214532327829365190331782779449181377434246792141603261192863852737997448496342243507838152852948336551215008426381878069138384 744618183980197280962580264310232012507828372807570073679939422251119595752630746603109806938766529551789948537538480998485932824948104808365781237003417738996405422005724588119789368344940889166368475594729748069948 -340762042926955411475428529305189465658768583436512744264358837581749248661975011980160128732730742459863188394970231491779656266294244794996310945485707228666816443868765980962378129739446589433591278804444730988000 420534288222705112121968734804174062445877898095515334292706139911759756827186264443228758871563867786907816333085591918095605557871768973735691794761772129891597919292063898713346348201039823784780135409395216538144 -322466136855632911705380082681178417688264004921909145636792551198280752569938180166195884849281096335360683663513583868929799395471834179872681297247682807080451329458458991340651618794368102939064521222884482804176 82088703952147640668971413337707384423074526245603875626350789668966648550715252231162350759869777432315792562839873237115430656027630027044398488029984280102613126689274015258023820254811443195114196873678080430160 66239021696798679676064520281644582078445794667891857130813695235810318643370768074034672709791425288758855094993670707089044268979546893989958277186322964428124419559191348036788571533630076397061704784513254843600 19220967369601760323766525018290538855870352870197542275382006176584339607768495091007615378562970525332375904307239236022142246472142384433468641022737031033552322659501579077812423372537777234656670929081830686080 1915223426626632937929357644943195264744533356945852772223888556640270701607950280134503055358521704623466478180319133510153158186544537265776581353259307973069069901853854974242975023529061603919541193620417294552 -6516162290563317050753957375713323401802589541343838632232707567010362164027311426600900056809531313632822170621784407943636121205912101016297214891377710025880825522308292465989796219255537959614741343299313458592 1186288047821542431654932815676767844080696495865091717174184750067757863077449940160647668423530965041463027401559129708992396706294274565693501058675391688869679203917174822639445145075190086647448678439197182784 84862591611400690617775923508217833668557486364120883153119234523401957380778531212570472620769883285122315128890783631452695416102200106004577567423238670509772738937429078155704419981104553801308957750099509112 -81631286549597264503128632967009830863589598812647994318629652756443654555638305382177675210685442260453894948541931652983572208609629635497267635262559416498381730783243534035937260168153421002326803999043686136 -87965558701335032483048873861415813914090397244935080153329521063672260320878526948048457318584034074212926851830941617856681738382867247226121866789074847448225130665647219044310105875504965629060050385885112000 -97162150728137545065057314569868048746238784974390732139524624747309438312706410655675744179666934840965574122505061092590950902809019811065535955896600562122410690365473692082852401688644272097665460998323630416 18676726863239075105594316599755270199803949050689129595597495657661790428439666687953070792975367034187262387596749129376063201878964764819727400609232051253964590863955068435176992337415130951754994722660694912 6320162062706960420455563661752275914205781531176027471901165524268963661243813936022765527146549582678430477604256527293361071117773300215589388428431706524411629382792307664068226519684554281586734800969566120 3690905195863008755498876894282359251429562541256082025562910153690765513800742822210695156820949722013262041640062251501675930563518185288805327686997975881820699213333839149288203834033765844821011448847696416 -631047198908466125291475301074396175018093573066435131432679922963128423478092053312466427663797436335306068678587453847761644327530639077088150710179259479697873664664884557467349990926461508612257866461684512 -720075047879341019878600297821406967119620835222232258539846376318961057141022590282468564206800277804527920196390741768786308860829656186041579277722088709800637710208531372151129885717200336533465508301597968 530723649726901988130612405572206931451601230432878850045560311774912781879492724237306232540406606324086104470643501920517102294883918424486852334378455478847477634256758891545876275655949698157254235413004280 104183309582712720132514907047386861755734502860697339411953118584075800790257239679656813712362529947461047392720365681969260774187437436973290700426520300560753640819686675768067358020578894995418700190871152 9216884506785561090266657825604331519272201907746875136787019293965893307352358549199080671057235587590458014355479578564397089303318030908267134638604534215614073639797389514702983429550354249136174828831768 -33142746799232065325202735455503293754518340023441067071136881636372929583117627599587073831881066205588016920603441869546528879792433013422030321575891967953536442487984857127468816207644782545114296182394960 -12930669958510544379389708899743031555212742500491831923192019097777379583374140202129639075572023148933041519998785906418156667717968273664204708529546825968694186930649321248382295659344573021509362875530000 4336141199203122576437809642584987082112589543530240803190828114492954376933789146359268113271335446076756223267877217207942212841969423240341071306453519831284885052962667329696820151041290736012804400836856 72899865860844608476160696610394686988155767328564397016604244768962231959907339411880476989336363114597666319992586369274737591764971004348131918402262479069577555163933805212701030434109819822371244793144 74161682705422529993108124657874348223075450099540885704485425508398307989312590669908381569185427649678028255589933847076934975226491185174910817766978166311406621116361218246174275235344133135909838355320 -450237222775949632003277502553375603466940271247373676201106575546515743044707029300938991601079492221384689722729978433362799627481101464515644059072933852546805546695018562265640799609908918883780524144768 -102017576962859523675802059436906468544852978388119204013283595921083118282132677113633150134326903809405782012915224655374965671406946851971703053258149831850899091480718368595235447553353081810982527093152 118338172836122790441486444506442728042422774836754155096678874648823483721780586537550302830531222476787917988011664201544804059257103242150844645250982223810345198540512680745835997206435266660154635046312 23409638923717290490435698269135601833029129371488837796943445970675209516743237020217074689747123153703129901192343445355107815529012763619160933072593744332446974387299399437001618292233819168059581583728 1040586784606853070882351244333992488465246397598802072035893500682666341385835301200415461501827954266652227693434772449027793378707729914547387876044430975465548616209739019441070156331690496596930577584 -6598346993926299178539943596271567124805782180750908801549166910344695625792623279918794827402822663878675204240013395443694722622522148009125987331620346755504025091593249709890167017588776971647937819664 -20272315841033350260637806314635827299703478232099580713599109488394246993242556708019162071817180438117185963836727479190149682909172900343159836487922515364860100463359506717740570864936381406434571000 1260674744663995312135316509517369056665970703344993102164271083015390205471871154556813155414033212441344266728566833500479774480386981507373753143997987255393931435716675757758297996806796431670758000944 14320770216366525570293863191403445229902896388510390977538078049431843434035771055003178508308702844740973779697988820157649349960749632084171191001160158286455988880437022966431282758004826149386588464 -86209838734680196558526121706145110652911410602037391451509089408786695958564996959604027970117691153318480034850684791509370762432215640459606263345249162496049931971886926289139481280329660229102829136 -115057856858503505784607138890829406449382517824454161003416948669803572440019716172337543780923289284802290575035370307764792258153676024757154648003722114471060720641986177344428690401094431683917426696 -5580554186633205192738934710085521012317986502734853824009796772824937216835236059429293459721214816741260787186945137425128306039924995470955152012923155866162946506710344956623383693036603397091468736 17542391853841421111210112399150994118714120691101932733149491423666136355442141057503694869641899287058832503203055279491848881245461182295395119188943667406479472730479305695005125910034044339272493456 2845569181664846277480562120848273753256304388019533592414109607007055207975223159878850044154237643030699266293026011369567916422169788257296147505646799117445165450319005195016721343935318027643906944 -1585177787927051940562346308455449955715213285625010308635703190828379570593258433588783687049953639387117155171210302677491571726466577049773997857805957091154466126104847641393955510480631462506518560 -1255004711540981286725493215529063749185096090619681647593778386361850506200649033641941586631053826481930597093877263638124337797057767313146447380890425961483087143568697262666510010325589956618089392 368795508673673081195792255040893981369492291021532856995078882521529157467542596052271384060989940292395263966355771690365259591582839960110546993459757163491297376802479488783567983662739761201762024 289568386824045332251882747128985522493804662736411256357318080100002431002020523591467510970981771113959977144083035021415904582464471392626738368058533329545680663201222480051666643915669816301965896 -5803560341432733405484837764871201851679077768437818321403190799068011566657382126897618215265676462479663421252961660905430324419207954713945698985770929907773136682401961400593960091114070371092600 -22399936398777918014784541378876247186308429411881477498994240862073755082804050497445921362998095181178653112407724955257900664103753989250132394288285201969694447188160117316495497677395942156812232 -15816155789299304223223933773858604186266864580759503373309057296235067088102857776722359620489701638660763094124693760744056726123919653951165232720901341498058598104631599300702956488336693304427520 1401584790561050379157216931759579341919657853605202310039405785526665784646305264408491349261083077022807450641900870602082953713265866743951133433058516341540840675064095493373038631575648521894408 3636824868972614529054762374624857833409241038164914614096292350525339127236604981926737734659412975580630752083960061552752690997386536888235918832783927628094682850165203176172229337821104077391744 -158772959347830031837740511934722895548021947412254134437897679711831156620251712390852300811073370332180270828838519056523520186056524824685147792324287487549405026959517188980047081856279131505352 -632818285976109351636501255727771018642602320111136977654482474682039671795349429075295029128350206445137516638750736249343386341371847150754325104061028600873282321684828338098556454018672367140048 -172972840866228636456123750358002010232586994634138649302249517074320664368514915095227952663665117704244117671847457919718736890506695780101236781141221886481323240023685609488087542933261180614296 96274826956747439027288172014924288528579301614186958115810081612655253307814685364790496981886286640926070987382234134240781497216063133190496929632925822878603313867980578507846545371188068188616 40989086978513848029519128941676053342975807154850556044771120804224869880236747398636681166849236236409150143264681355551823966734355586465969943707431792123269260082913669161815610897704874912576 -3136553948863958561302817379198264497124609453824546179949640484539458806698378250888613331696558019796805174960508995138869012882940658713235863665341810106122347014826616613935006767036649107152 -5657853329880182910884956137532981499728115586535681685970635513653776612750848601808004814239078324625365754865787835146445606754250475112705165768446092313980087480139571696831449792190837559656 -1827754297872333375166754732619393100068748081765445375374887946888113239387416974151217302213856641290688119474752172931078707420505377203765089735404900114238198495627906569516036461754469697656 1174220415829365321686711966656844049039263642409538977287404651579478725525536849659469238407594878972999329248968999351583521105395477980452490271897262625931845177918018468024706511427495153008 595483355729138421320237356520986492541072520391419698234528638579378746692831606335150802024083853852188261386186913279963962424588918139888994588617779061072228157338686744373625745811949800496 -113274201326343458258383732086743336201283130962672221505808585405843975495685935971450465292610747505365468524952676034708150707198976924779739298852678245031773340108874741069393079079722788608 -127653847155740093997839968415013258000256152359239991194250275423974316164312929818908499422623736224610808192429711238228415998984399171185224331426607003140840953281643856164891143172934348304 -12595894101478926323384255687421437332266998751334560547919494060050955266929794097064594851084395827310373331599735510333711367340296286784289123874174068349604702650709322602668608923604687280 17487504816466759879046771194006151528445804917609423830613786365158462387159482065325068409940234150530367798693388586013356261890597751494162174911367919774303951630547039574394007315580190776 5836495754795017847686120734305674307480642441731312131902572874434737257464769682255702177343881330190221506806790656239223148699677683243618079902506245788230947214131263313357118730375490200 -2101308396117067858689278146261296117504449508015930165250530098179263808188830596404372452091645814755491362155409335168779157320506429589074691637766510633406779808633459358559349313754384648 -1084679012498175500498656254523297772008664625150734318952493129134648476004027856813634025097932487902974242937033865739653841102564408211294898062224380480695445101825078006897017614117846248 -143025505156825376043701427540607921006309035193239478350966200253449497122128350952542692088841177059235130833102029757017809216111689182032425122822435952338068170570682650510168913601040928 259496494957776062502308586607776198469236971666003169759958688498956163288446267994788345501124128539354620463754822116059988569189803786401210548434955522557359470224644741818070122662056904 102804972717955420129943158496245724802016713699856780194684973269430911744593437241711058840555386047520266108735771915346218083894678853989308716455764901955189670748783048514139011625648800 -40939707413543190059306032237372417282745968463130537345133784482768921441554789497252642927784995990256669730527462651812185525085026953762714099499913328431877915538485239378910815304522984 -17747638428766372935544692272637306702043199143949925120779198758210521359474773450287329920541360252928551929531666667408060740665705811737321981688139830917811702826712983192095210184300944 1517748641906835862062071499135339496714955202939946716636477760594933321255830246323096651159168634732568064055662696421923988569075248233178217604803141303992672337293280388156793621169912 2963640712445381084641221525235551236363403436609083167025988018831914297682462327824942759352722381955727758166724571841588055777524683161568721119381520128060119103111179315287089921824192 555291008309839007047140273869679192130112982684371083376807356990232601422198507836683721219756723763616916135268930288592815303080545260858034996389212250766423044237638427454642607970416 -368816734694059295615589052249388880336931934246191038278793121981526808317288202579130115884696420787935051226227654662033691413478934033571331911341107901811061598351351275681341042845448 -244255462168325505492640274275804001453666650254097794322407781538668497574324140742140881464852335472762470193031950278675437735071899112844113136558853010478542660626346197012518131830608 5812981000297287218492810747923168773019183984577664054496001844392357493408482176344647683708292722544152218898664356836469294157753952436095683036119956950746228990801460484896472211056 53691077104229031740960722775519340589097325793614839478682940334717289745117798814281051159588526779998048897153198747837883297592268167508415797021303661516526792485230931228449953478744 8214481641279867700384600997223728197197779041800690866534728656030208394234875506681534919749628736016773638689021991774265988041852905235193479545677523343647469692620314819792778313112 -8103379761431085280892505937143566062676556515197899035968034609561130160409331020002739082285707908963889117305115029095929109810160992749428216290168875053559757033456607951883542833504 -1837970714092679735357607486321795989359871088751324312196440580973713424186239099885127403003711003867722269815497113087256115162533197681509650753571778700635442835699800894694380371192 546695123339422045039601954234925534166326322861345860245695693223844457904142556844710603529879245433813659409074141845828821964963628172709117149547179593117132869218007311573532486080 434280115559371243360129552048650892927997662168958773691479693232656397818743456427072419726683189730994051671995136770715813450556926919240060831043131402507702817720421119790371387952 95888629026283127713058894730756697650710863980712050188441609963205678674908235607480467216246102098175946998840687317924150933257295512818299373875951460648975949020817097317178651288 -78167050100381702682755724442409936257624893639920652832389079074621889964669798906354390758558731725012608537491368977796286947457008227043948978664637916377111968355530856845942847264 -35243039124067292061387688281976444031947683601154167404514200693204715101879250336165911974644338849207310838636672740676728427505055855857707980337095674613403136054786016035206524152 4646497300552521913855854108325538991996323615006098066821701063697336712329529459137211998241264551769645263851005248956631573757912851218467104037208623859676650423026483617344411816 8829211365550952066977799412891606274128862712327501228323548208655489849965969752113068662877902188480310725657864111915721223972330906275401226375359599205526857993806141554881920712 201204071983162235306745645094155088015654131526480806680596051495070121960307664385683597908007202604726706052751477448129646021689096000341487008361042361354647361857681548054084568 -1543039275835940727194592095956382301216648787028370909514792443071579407540516250188113735112055986743929018043960257497812793901631616861520523184201888043999567552010630628698313896 -18275375891116006318288703499910227493106266652766102981834337279884799877240967955354578569244224067602389432826938642908067203025979159634724471434246430159622945554052210439007504 35516797327338342797407980159391261727126779113383557619997798037134795515838223262615587650980422156443898756855941942811039730178872182095875494522516998477310740777826022980119128 61124824247853368783981877538199311601509090984687417248396297670922977843305237756365102154137340287397341917268527730644494907297855525966335176144202700261240481562268119160444200 19826899508290331920699842429705615727794303588277825231445827185884957527609874852247244094545455154486233146545990683764444919567491950174671732177984035373889394388152132594658568 -14984667644332854633906857922746644195494413220126081197691153908451300372406471595486001672739023386323927787378504455829413089321213372003691926512902798867368586794369956295069968 -6007451858707040067869374434416219887821653516826703889390468479561716332823180574861634986002590646508324625929477041216597652942857326627710181920336841263211261932024360994060912 2444193044707727554848603912893448429583073425786562758940903526278722025419003262208179476202518765585935698139664426366718293003428274549489389382583081957639401113353168582258784 858028935373930717498815232396244892071909228446500755803518492822469598038163771212465948633376699609472801716662461324229361579809415597158620845825681695967254585535261219014320 -142553689086934310813768640310926292588644745628976792590868957450379152415697414089979479092854526495490446299883898672357973460336419394347228601256891222238093501297385642025256 -99982982164957662896783399276509483924522712947880420248313716080335781184318165244161067165952922838044885953271319673693338359298538787966446124802204519891203027326320947264680 -36704125735427441844639794944596499784938970919870757306721189605633318653310445584575428319607443269941160085263031805935971274062279508165735280080173913848067630581556028227416 9452237640704489825288814223990643441771308610690470828841654460212014557664019303371507493361688755832903655150941490298642493547351110785849408350661718750836498873483173240472 10178562786156075012185883684598277144636384795305470168935403094172971228709289203149349382927085335536159537531287368462967293073289654114178174884875756798677562169046961762608 2451673826137803638107880725687913880291649126076934101826328082936921287371961830720883508577670370433284751859329142428369482952988972925609852976919935014414639246008653381816 -2935480390316028289114719643592370209363568608070423006672881555309284092795326267239481754665853293668505329706372279826533751081991440222577152296481796594596499867682666559984 -135447562227002849877987748014811681900106014627486825023005580390203937766799197650339650539313194045883449900681270217048320014927059782408464779513899369690304022238845898312 135636162519450335216905658909481793527225224651244351881291085522186136239376170035619744686951911060800436074539497356174430113585981945078965847035393581153412227092118493136 166679430919541871924298192398659639383803131388350316199820473954787525715903087078674642465114758040989312912494963301710250039081560341522782437384911906058886067550255644456 -35608913501905477695193442583849928385549190748502609495385502843744196688720098552736987653447625717609767913798717016741151011132742258225062499404485996333362462608037861296 -10110326458955176379928269567610561693323029043481199918053157798571728524936952596457487274399266037242183265574756572228780672874028668084808508805679375254034570713684676096 -2311375070257478056800421242299180660688046320715006973727567918520147106157344201549796461308025910826633190310630098865959808401661740675215001040745184424849249517554901184 -904578566717928578707261725555004312825933102351774889750508021177305116983041266036511167563625196221202995978550232756362020657450354270304555645715455879561333636746128832 1836727022292357317828418521383302563024353963446032964993865470722588470772055924377884873686994915576041354627235633987253428665308060178972662911742146292338893344361451992 392074023200241611225626476300349867721687958801183125777104993346248018724372763701075266702235856983944012391945105846518070911053510690668653609544878212309142667024993872 -515489991249953252298511103714177635251335209989070562899494311688868966717854766303885383380119707021748820882734482234765385887137573796133789946448647147724855413123823336 -10781997992284855341576929078852338966669006338810173317765833215656843048752108701413431389589475896587223651405092971693567113141172696439626806039920603865882688440313704 66195838312742106084049228736853126699987385241898808865399784025113838239133888045778113679849877765197183052562928703393884056710770341991327277694899851710421340778020616 -18175137171602073872915587607012267795701837830646072817562191643215815295324969001222534630385555091926304952031153307621450116168057753351895049836320034524192300200214040 7794875191738326870903049777541157830582343857434656888379045718192911656940081195272971800391096246171348988969777059832765210716705755463964024080388126514549614478465960 -1247027604271373163873714870318437273496773160704304825142647613686871667974080683530963558154704472883123396008712739758188342093823225725058363959942539561104213418853584 -1596999248095322914217982960444780280637636478463878196356194133713493761301370817261170675286099147645938243043631890680789486034954002021900614054609930967844509848452128 119689041128721425611948899775555551021837362994675361651591450623112497437788202445437244006448312093104007902389669253192770312041866701432699094461501972548353657762544 469756845685277065566286677299487871713646656700919973433614750594690599067865227086263768619641242424096863215847433833805450024120703345799886659284432186928135762010928 -144473057702668424370461437295759579096991934161010890261983519410865022454445617166163002415431983587372748025584846254117649037169010436353442425020264831713074106264712 -1148650282712608092591162454829158041971306964393169282013548849274824501811976590121598482010304879981493755607782853564002817258196831137164928063883769547786969032944 2990650129216796568324034265623163504319760725142557208319223775096138421434747186978303691074671032221376003763115364498895281821779800655735284047950274658906310629944 -1980517322491325493576172739898784722344608717883689606375488465282107500146308779790858027442784476194459905889812605469048923990672967336666313475245663343084288145040 828289185927854145427662181707544567499569810193346351874290658489057484260302203910544235969520826873908677684105157950035628589515765149286270883397647309945135614992 1149421089277792154805814805438772554057744044829402944046623277669218665541811350649958344512661144292161789805176121695126768041076511889802730705545729773174942243408 -507200395933147707616381896910610948327735422078794559311622259369443216636062554532728547885619207249387579991513104723517957683876306176216767036135875266083009759872 -73530312412080121090239357956675236694122909708730927954450295774070594261398344641945303181862912084125002897234200079084630810512458336516664462125595401689899293152 18981718654599127923980136642109214055126046261005215449747548092053020570293208469999048269738981383421740970499248099526944115860224371862839363386180297792717942400 31246822488387507622625941977378665167131221007037460138757162383752061244515479760389945780138532341793028295185385046768956244818968893383196135831071185145513106352 -5001867195163170569516541649016190162547083999107510888623808769269709749365523705223006857522948676578631821805025659272943526211133138370305743379271999831016353920 -5029254290676931438235039677460030130555865100617567434908887095857568725716624074137841641440780875929448323208506671017507848104019777027295566852593862508173530528 2665898295546891488407403658822447589403364189762094145618741088960166601727439115759563138989879881311085562233270858257396407288011707565597055509588936387911934976 -1015280393101553133158010679101949162761898722780353838289511141889958616417673993540570350779871010981765602132844502477282042209185158573575228832973234555218213968 820778869818376732183693751862142834330036140512675919421233697878459270689454365841205018060405006420597211905277246837154240635589678444898911687971865343029856 239304784634505241900063333210632873751692387080540115013667440211854302821510734737013751536521685813784150435450785807740676792086915133476858155344117332028827552 -39443280815313011375769524191465944406969112525194338697751938301549532774675247762786077555514229531183850961157275017302618954183405079847657171174958139393166592 -61612836160325625697083471409620332648908869056457596309245230945105131161924853299657885682666963745452325746730415400675974576806772488492642914658194072256578560 33620470631480469876544797945988582882127177038129882734776895833730536956304556259138460527145844192302288696307671682680914450098417433629846126213441167385591744 -5756914667496803332635884932032862232908397546343625251638995650667230640910676395125025010040330483540305818514869209025064029104149872672970152012886436364148352 -851710596363454270955112622173848037924853263415095010669474896117683748509344228633642630638495189864124710943012513751682933326843906947832003877853311103237120 662255826512307681346599687048261006865760693103784668606260377140077388550646715241230625608598551119027039192948448820354698019959110537311841598282595133539744 190097630059776381406772034486303461920635456710858272760020556290649865759075120762264640833220459709903388590635259893058034062718773253954646978590227458951232 -387900911700135371155365193638314967545250070612465096008386590538274542712936066848763063685250965360848239500782540441122765903759933006963040029616868692752064 168726108448796911024652285956472090778950935369957714975541602010742796721837480507627113360060438744281123435849252602435403068281166901942771170583288791433328 -11164071766809377634165220674907501555695102426852027746661214725657395924115687455307622406866046247500289597137645436128550414455005784039220114510466181030736 -10207017239331557968591867242453794677904630282130840024090673685636383611703702062449307675395575195839448670323128776963463535044559720502737506621567661690032 1355966129009476764166495415809512811016478047047553319343295496497864050766177359995354548000655535951054271722791284881507121384836620171483038493623242295584 1210588362407192368893138862033023284611457537799179825596173517886562723849870509686517851845447745545780644881148978812782826485676309660521031956589530078336 -518490901404870703356590759219713218594444684232301062335859657955646720603428702541842898898809180005053757681796018090989853576592672833835524190806516988032 -33557768046965551432276831481098780619489256667260663986310897434434276303608057864746181146837066431502774923693857144989866749248149121860546075544028592320 153811529462127200498803007954705495409085636038221442353258211806850659158424186437217047594772309430848359164638160555052528754536750218327404868561017286736 -66462498215068048828665472435703032182946037406885543843664387659928382302038358152920747276146921622711132079971549187177554458627324257701336719790960835728 5451470964547796427252825381904847439895292744720934413226419109148398904645897015546023010424031790976997506753253446227390101515739749268511024297159315344 -3306472814742531392117708846159862248439761909361152732478112569788538518029240964861319897623980797935256423673259166142485478349883186255214905424910738736 7758874583047845710562482562698403623998133835345657788397419135223176192764893949109702778889035313212698225211802051955568059497343809196581721550591401840 -5010965363402467922671452289652324310767756645146505371291096458831055055864031367537909859234651186423985989356473058535991168956369240900953985695174705568 1513413117303086690029063421562373999402655595998404294772781112415006231794970209963645040343114717825524265099520690296463459463007956405144527649749855148 -171248351616713120656319712988950876360534957492010253496859791244166812206583265060009089716793382185148383714808264827147820546709025619465730304958387488 -14193702670011648445093424350163757112752622597519001573687781039966229771592876902583014251901531169361979579260132778817149381012330332163187536636290496 -43585050115134091705911393272668169447813653604198955998004245297165496779496874176414556480571115566792359966861025902901729353094785890336242501276939436 50092028106119814955608183104489988279442022746037239949626466297945959798191752549629933237070359602368814318038270164761103698503088216889811685835274327 -20735966644448990212677983752282136160229100583369601847515760686277387998433303197500530714621722926923533883812991756107302899890247143694543468347885680 2003015686600015084824245368285260138645247198406422848473022646733623728427923931744172531705161226365345882208982122669373403917572093211778904074509738 1720985085299154361284204945600541740117638996545507373381066624708568441403920661945724139417469518238248089647509668254906350436783075434578583490957365 -712785057436389676363729291988854945512832383804908216412156329699151913044484523090705588050265600609672453692425647631323748524558479064387583528852645 3702608602168062064946771687933042052674310188501221430009650750084134189648921042136810350130910024296534461213236919759472307984506519186325832281090 71182618434339916261342487862380619856115991936887246422777347229397893887673513623277306571028057674798230992262085456960655355191358227604120749424130 8066091479524120298792060413853134816907358707792517442020675101512181629903017185104317908287744270021843136603936412752765765767992470804592336176222 -31646102181253168674718282051471188655247927296836677222943502552401612624837055494259303749730179415093655980799784693223958732706153963431721002222558 17213496503654088944458983255499617534360698645096146554980753785033819852918501164676936808974931926967842935203399702921945062555496476446233970216468 -4758883432622216478456153406643761849409750586604678362005171311982222221964225328071622723632039921949465492453165534401344926616621982425456536681523 1155122900004558244653679090862838566021175908638862925802458641131538120575267143235924414456254196901450867438102126719430487927746883524780919988955 -647670146443797323842366289433372111983918029377645674784478065696606803481468748578324856342081012335924764427153875086990863424051421346512749260553 396452432592045599802379139834297907301050445774472369969066470580748444163632822454074806919413342786828865398177038794309912936103428563997518826599 -158850274365112123998327756623813007887084543729126650255571216999579318117762633263796162425550610688645362176098799765316467442065656180020358012707 33672633068642295354571238590219091251701026507008275085981680654657255572455770274512346396022220741456778647973853139265435780947822687798178720547 -1170967815507652540175850671338603686503682747872789010516570767028958859714992125528834745230158512620414654904130806952095751619953560613066127905 1063141644137684709296939525166719404408833552420647286471514364530716635580140145758390995853061921298402722932578640410944275720103268057288446626 -2523290469734611304122663962353520685761216645526398497199166369054006629172309612156697782116782850430369205831095380257543782037542051344791593334 1189872394634580310861666841637110277788252449159353594906388446473144285566543696367418811762448391154114789232859209992857995329020907951707568400 -23666577849222031868181892897055688649075155034169120719242486467748051788422614909223024381332961578346162378526916370434909286808538997310444409 -216246586082370625905408353546392920770094480924893331360374811853435431806610375685921761354621922731981197333683751288337073066978208980029656197 104033240807167750854286764786687461010167718785247734770652314656326074526276595682047677546368054744430417913727116666769201142891739065180252606 -18898305887650198315000115045810872357191003648593840516628578578484227751840841665108925504260951339449278232623466801913666762728384777989067830 -32685658650552884161663995431244450894748326486265564456723718405612056923704599332147354357251155460122656436983242366459110570111773452443706 -1846221097061053050946278780719964935254300646647705663520830777390916847005657304298685925079325886378942981788828334996225570719841198809517808 2809256903680014813052674348825337500675293332850381321317284744982814315524901160047246655306616891319401250507564620417566536397942376613478085 -1543353118552255622140529696341035768095791371209481892535741390108682901750127995099470093628354319296997826920070029082636811375973869569736269 456310217521476556619110293474803970212620843833312885389476007143340227515018256943562286386817022203925171452691305127413542410984053370054276 -62673738319469160377977987068415895171769488458814991950637627239338888116492430664894415552247963897065288004771183099726581147819025846780325 6938455247736236192054450889588748728425972535951613280396031968907665257175600791207596198658090412319301155801627141980577449904115796649227 -11145632458729362110623865557967937080556216436090714965933905119372463323758315748552089990246321582028693763331741522130124728664371367767950 7718620158723246620962623428038601651398943789621756785506979372838833676828065589359632323921340874193994195823180987455325319390138874586954 -1951851010647851002525659103643455811897934959483082236161300676552273501594868031112400134887432034960566355717364444723857641987013956666956 -201773782511121929256020679730618571536727668465568742606987652284393760312544085851667807593912473288098205706722533007260758221970269671504 204264086487248198012166892815481897291562903085919773738249847539491618683242702594442398168808495626028901402515264209438000459039786090658 -2827794292198270736490501837136143626102876684981298606912426342461707034507323945479815447649959715207839943985551158296558730952312860602 -20083685359100382197975421553058565307214971546053021403868163299910655603629681631164325692164570501293496624162882818296589877486198427625 -6326056545689830456474486236130806088665098204612237543085266226410048488363240402963547317306301077124362425037251335262439359352721221987 12399556059700052411754856191731492734411479726720588741624468035934839532508433902066940073421670827458818449325135823523945297583599736444 -6414882953706535923321651993483470828894384033889813667473753197198840134864661582903524358812718610391090908965201624777410994777597024076 1449980160444502467765129078560441013403417666257627446224925019193997112282587691394519079230500454753041953606898536244606301538633842569 27757199028203531135641043393091391945769805257673913293829055823005629760652509403772883040892455928232536936601250864411463371053047210 -22116604369418562763863470784419151458165207954276025775651011972535934018220318040354508270794394635075670716038974839561263993894068162 -80538621831307692040673718307509070118787168953843513353916315313037603536035982309301514264741687033749088562177117992287196567692876462 57851818383500024700514539763344075480131675220956549517899389394819644529088063736908635760772211977638521567454790346029342361365142231 -14758488026843766584532884895793462712835628161515585861578342226310996821638555888061842601321554942398869767318920872562346138425200663 -1486244892553668187315460189005735694898876606492298765986240503416693875085946616606982489702790284546824189504780055582817406323058724 2096116897364690936939537921302603617188246620024767339413100983977937954350914855093724151382472843273154409500891568775374460658169906 -363782786762049560571460772993335905990394599940282663676472082990974246316502492626618887097829438508248896182081416559404427569889009 -159753572618193301880312229742452086757067248095742157934608189712544008042514041594681145208456853644988874481850924677887417059227156 77999286467601149738876146353261466540595336382407196492280384773772858875650657041092940020116357762949749826935237835479008323832068 6761506556847258552915699682034301226241430660133223701087412995651001306214329499158920971540422600375024125767375970774113620328462 -15317826430696020697944468176978980863372460935343467478898306115821434587094163735844271034656989577842385185436056627565753318043115 4683333134258632045113918943641781135758185429325684541950636283930596075222876595419927254296067453051169973060024899476425431390260 36524570720739876541509310711894150982548186855382818428816509665419051351108896959793136858576716090241540610143464194864304324088 -237602360048057138173848961861445090460693797293357421373801546267607673780680873397483274893773974645498084273885549828658758590625 -147692583196810290331102424733233442780700169286818363440966299924415360095620802565031497955569271092447497008856929808399111223344 130957639620834355264208584574914870607503194941669304305852937628700188107472577649490811993974625438139945881587453138042794656966 -19584401189609415517815974976157157993338191129939989853892141886155079917420454956320217853557926021349138915852773611892522886345 -17220051309809049985578699820838127054905960862211523753355596770116736958090162512486454453056970468968315193742316508049595642215 9710149797570069191188038734518162534422653431456758926245972905864292815547243180244072040090987461737384919079375218797511698206 -1117529445943397108242956094830065458213572203100956809581556709318733910956177246756920129785611310941797251621103136778518166184 -738060971410983021372966813392187487831614644374226513385390770594574677702312244313622811463954730215595978313228611971078341406 205204258055919455343054503678446101251832126309886092618716250497882621782092386981308212878780144185239726814430142314267064319 142653192520446300796087421016332300604757903615394085192966319852134811450075479189220735905076705390557201867244961477981003986 -113725755927763663741515556816908559417775306297533079383093515887261648563343422587762905599053221257784393697859741581345519761 28135615362015117149991473124465159704410553137656433480760717089493763628186631087209800018110975269266905605327510448758625894 4051561676494281605565620843972507468228088981304230296007768370018190171581606887694166139155931937495777835985907932031593953 -4292718674332573855848857736976413216187403018528901706098359109713108095922611333341245534156691616031744823291715222425127917 602639775790369418262019009936777634041437960786180810353691378552456583615402709569960064594527153384901619794624093657131112 419719277235454340722751842974705034955163368625674106507507432238208722288048801387303117600073680535674232055611708439506996 -201503470560181820566104081678469314520099068498498239622259067691167986122013351432853677731393662194098434415053032624103369 1709858101648023620838085308920140110492764436258123844879828432928164027946411818347434268876765140586824346701380905062539 24675638617394113984915862359581548459855566269686190318022769435898413537226973495553693027527730860658224660404915731241600 -7188738569223120551836334825500132010430203978388538102035338586953238215092061922331229948459757311324082180610383946897406 -451140431698640516592051837479084824429550951678832605080745864214098987450955456820579922238776388586920611714212235923796 339092629281256085344246720353810936101561555487285112333843993915348043297485199854654102486086630322539776044870546214756 283779578549042515155233624559026147476018970236119674281732711799131991352180395868800016757918513649687272521709342945174 -221479217903105530794493057960787650803779676161675260904737233607616331258719371573176070981274694003204253398632315081741 34033855297242905970253905475055496854646242156808034234233873006464682982115850124551019857946550600899764037783157278156 24880601642216690206237182466680558288555473000402071270612404064337401342315933877338357255747767435191615630379468692846 -13441317585820580654024036940542520369226945304153442362146139464257625437329332458139954816709193365352177631609641624965 689786649055987925738998451316088569700881117035452685914265689827181305766745902888365001837081271009173304368087662178 1547278060579310223301134209658502935375316455449639974972872498626556779620374280994631166879513647067193019606851219029 -363958444981394676758158182558949443150046027782712302047992377092419561527622632114346892932877161661829549721762592603 -224462598772922969341552247284636722453495025922348107313670424453923879814986519434857054387747197737224006109633072511 174442315853673219416391580199057341231565304082329113596779152512147097182235755919503091412875961967377363301666896837 -40264578759238614469757156512698890980060735582839909349098570234428915225004379895320005595474208741958497786108056687 -6556093497677995996354915695939288289258346703889573233491357863330559877383661062874505218319187165315504454228239628 6218805146325461745554993845256395892088735564327081704613741711116472439661579339167390417911385337316348323801281907 -778303760903598182819781572285410588729237174013057176550282262520603342981017806148160792994231013856430381986690600 -620742359459133335881396769809279058863122878252528428775800580263685353430752905705061050501315505738726998191751187 288165040924997111661288332893972882762820684397062230618936566430359926922534494689165382671385277849687542698242032 -13659353493271954040204956048043239071474231330875475570748137871786035728289745585453106139566572894877908742595603 -28510741453294744697835681691512472449117283513256461171722612248249097258610478646278883719476298885659761841116850 8895284215648750400751973368572225953499783678966738210883515246735326849379491514341983190461563935689685776255239 192201568805678630835798399109644893563465924292332304730477465642921274279086395375250987892198758104539538460768 -218271600717183414976355493452164413723707297031828496988694280188846748225817120571720158905821840957236497490580 -431328384024758898564250874323827445847831117332389030116680815890105885328499835894413276961554164148449745520302 270408541991193934807574743358587702025195079509142196704006329944376481485603322581317372192785032497900822070378 -32762779011964315563330885616827652857931489799391330268573345452971719982953946704071866112014248146755386187247 -27997863476381748658381799693305946917257598999871298109023223866589179650450873731383126010554418196555192751397 13094716211832456393045141823265915921976542716413301237519206374233416140285577446179120060208978202891638055347 422137096420825237503687748342734950925779387625619965502183494956505142450881359379388259807706366755316286619 -2018115410586747954408353858416306756013436943557779693448599976174013817773576707723651663142960066931696807937 424585692274157735154076370205628854820251627566378374582137172396033734959484026774073643451456694780345641094 257298988251313751703270863363771464935327079363144572749322511591338686679636683175728820772356919066106828965 -185808425704301436105602148463928724248600461111159283220683139827614756165029772192672990416603398626359102306 40520015733892942318779524961205831102068509808978385684614037010320683054911385288546329479649003001211746285 7215505444827203214772752401506511269897003726081442334458539260673490584548338348017163582635783284154976315 -6376995697863696608731868939447901334162524061236768035681334474781975438610801480949414393642821279303742307 752836695849191966479923726864504558656958684569418381743858310924492565684614015910994727963210083177389256 599473199644494077456075271262488470384793606025802751321896332784500265013734877357869551729399309174136817 -278456764163093056112225407273898535305145407312814061595602520405290488380720484887195030750453202761391090 18124454549310485460965170221318967797510833309462831498435776029916971273428383371364698172010679817464846 20884794873246005693771671399575466551353041094212934681972408704156121177948312353671870936972001569065601 -6388829228394654053151663808281895355777248356782219446963874285853890821648657567432592209819402577784223 -58809039330888596810109546888203342813332258556704660586798872467288084850683550611405538625259399057391 -89245417440401191784013643514812744376223341098002480704896572367329230566535022311551447413568829065309 472735310622897175935482933283793551672638202167065186608111032413167867272588333184672929062984786609654 -238176894394360747997094306723631597159750011427871616167466267958843577496875688347515807036987522862441 21326203135973546637587446235844704003944684781644847478226938966016275746254996069525249237136148992184 25854842571630780241413262976756713413154348073327103568881731729538690183942235572945938326867747939949 -9460002946759592632202730812617126672882659717279012180836786611879844341456806951453088571623303819909 -1233857885334891190889029555767451242627136374072337776801809929547169137150633243408081423013788398691 1822248738385388466169851713394280893739517696493457551160862812965863912653064491324944270025300540631 -343484154029963841020110445204662191293917209062105903691064205778844884142767257764084427560327190717 -214316358177779810154595735391754168383257424397966581737958611417060275314733539775167188535641369750 148259567395484736439257195764087170178648188320654597428606272364280519622696901833472572784725722915 -31496411064270334719917652881328230068313575698457497176519770149380464270183470378765498336919638520 -4902877608029750326718114841291360953492718716709062732684865103997904143136276356760016423391468029 4285165470717532749168006247286763633544314491173328196904134359343073514348647672314687400304877372 -545577911128211024391412035058241373418336222434557494108736201363312515197041818766036210369531553 -377535371527099309260809919221935780145140374175357593650321828758715674031586919384174089569452361 175015271024376900790787410314905018682688569515411289650434784612869160035346634995491724852643222 -10359956896900789816392506614688571363136741825836609932495153307071510990734720261241890317612934 -11547256780990819505512174529027870566563479059611618765389453171711233715275176870715959423933669 3111867421742098878830928506458253084416506565799601615659655776568074744544359567821861306283912 -70838251998825411246496351162622561135453863407734306887019135030707150419244961259787291301358 290761682401347581612905438915976918635884746758255860166475594690810362580285047963984012838100 -374466682476045032720183740921609605598568447801605703679393313607940413134084531861152203342705 153808912891511234691389380321722758280226744141087239780953053337115678954854745505264312647554 -6288196168557427145215425706454999974463268502656816600089473837813299890091977117155334226834 -18131119606489286814735219683786265374574682644526967207654979442815449656466145522081666633459 5856048463736803207711416392591327897858122670723236089039057651917134969848796961843206322714 883469083787381528972145978835624769300697162231954969242004937515405315944346575313432786861 -1113298583278290005250345640801160819545723693118921396269942518676863220897305317879291360349 199983162962209118288332291932176327342620502100621252839652681627453398564472166068148246908 113684059440096957376115628607538074482658900167922423939643100007361690681366693035690863207 -78547825419392781334247785801034089549192134056114994266210184521305724514933334331749691304 17058762370606548923247496332682649074822769186665114396902681806254288457088931785682965085 2098538107116471720849150278254667761922843053487520722176242435968285638119536220752420418 -1995678169185016628035488798534565617948696588968173534234115916075843669594522307370975347 227856770545980261601045517690296375250785351995010075761325623295446852269588000107184191 159468915065852246115746255126209079249689351404370674468054669601950489444884592113527534 -73385750663706559921452371827696964106705208625789444115112613440047673682749929944955188 7320629073013569792848208539084796490830144605851221660479924041152473141509351369431847 3171705283475514570603592023183275513277583641702945348012840285553818242467172175464020 -473859697083393018227218030541344484171515441513550772272875484944883058886961552436260 -81221262662787702330372809529944133163232201949011456604796696060732540551256848881170 -251189621258373499946294255317370227509587065100354181453801071224203901581981719402817 229390051983356212255223705673396413774174696672124509516436775176574461533457474923850 -81421834800184488742664627635043818886274209615740106648960803175198823125499561871858 5912230397069875601344851282860635324763837549173817511554645953506738936227815725816 7322245357667288700684788508470040954878089268710925236880093712783412093396124154526 -2520516712885024611402296690915646416595676212375583423082771845726109974290553268365 -356837853593237598684317714158276901010316625436909896283076167954383943826711487322 414819414463408601377737255603148554607843824473289822936727670965705923011872637609 -66056155264574398988112130984712275553504617043763617327457850599871611228832758843 -45394956465030250414838549827468219393660006921346240673705792801114330557262179414 30951245411047146638154106982346149842116622022393461569625557474111069876012220121 -7474162679464114151750252737596668481037846301301801519298085077605511667507993731 -168944152001534712102193858348615504300185776017396779464631430109658601431032315 537442224007750554153444558777193787361995747636729222414655949410718305240374335 -78309366081935013562196815593658375877229490497107716477050026802236028626010042 -31041605854191147959916128860321987446164491995481027849624482763012883305679643 13731960233581391129237580950164497260697128768806022766131084649501008614007393 -168538937789460664664195801284998871897440103184386503741257767703953680056392 -756699980355768198543040749967972654771248097209064692170502784320726374003840 -64028031597173217337078960946487678414994005878648986131102661859782304007231 62065829662528490795738585297514048326062884901927663614915515039774581167243 79788120265949682046254529534887265445996677687375501504434210899858222038961 -78794515333953626866703523022036606359530656437508378647518692135627234438610 27226903807807873675161463897069725393509617155092980002823711131482599972396 -1978937715157078658551127052637054248527578545359162490512320097366453202771 -1927116666768481736296568187779486137724785526842274095910887421173929351120 738696195562583613853958262507209048369773593701594626798101741501172702527 45036534861715387255194268108629803228123955274368620618153968505827392880 -111312076913657591452093334333452625367666671864578264061074877068811592823 22866114132111349702720645024294021646376645966282730661218045249440049305 8652704818481679915408456207657871148494139096331727771665132432240053108 -6605843529075601725484037972202136023784840552040197863335147798325616854 1991281931109633804755398592313918240698710583135885806746035446562994813 -181913359682930896731770973470016165365683100351530686109853232096195648 -67033638208646352205126842195395880894549942283390690134848919424320274 2582304714778150200235762937912453769412577962789960458122816117880846 9725600355610735164199992657946560647718137527493124284119858050892201 -2930690895564714318985088335321240409011517209311607811374875203386692 482019283498314804705223696588838314781408127232197395007679381849688 -56031882393966557451979756759241649095420777334165030081109670059754 48304987655693184203541222933210080982328626541278388582715584364160 -15429033445116510720823661675762102530878987889915399568996725892460 -23670890762533424516098369371459320629053916339604866361576087454072 21366817143068863515668515403726766070671039491575469905061817531207 -7856873619723001859059907226263036401291397126067481626607163851192 1357379601525775414993128531848291852869123657447328272498221836378 107166859217336892641788415352347213333063070468804662723034315853 -126375229130384709149303844378654912711126560084085991610950464957 15875023554643160764739202851689588387650551131458028498554696794 7623388290717014127458071175611165680695212793648791174927893344 -1610102361132957863357678179607209652859573272521381052505155468 -1593538944035767147468581031005896604783660150771403773018852578 1222160843766812964939503547801911674998770932333809182616280622 -400333433415408949705554285660766316362400266970478457979212394 61618862659228928071312065135390689576809793218835520292297091 6842032323529973224753570535085520668117390853081454893274254 -5029905980037482293674029776550026762999548431404147615631234 94153735676681802208904450234647724088491465685459324310846 171515555651642317767024163088253864996847233396045488008184 -506647328383847182730206859333824735081252541357672132154 36190119185025757069361211085765293807326326400461053678540 -27837644064238268321344132883007032967827471468393027109206 9322726853758730799107485490061531379351695271606782650812 -515128531490890237928152530095642403849491287514320346062 -2084471306169774151939301737125626333339808067031396809092 1231176030134323701432804218782732203438698445375774051044 -307160729857981054160348908592432002406113935686147840252 55745520570614090760404898271780555547018642276887960032 -8401203330831411538935332056864349534881986532168831730 155264835261247777741547038251027286349044774030722470 -792954312358914906151755618420419625817078924841301034 241285726678895046924118127406745031295715591049466138 194480463549943946882449110906661725139726384665471834 -166850624259142721331590856863258073990932469564865624 76348462904448207623973043428615287091313808908507630 -22363934387745750341533802542990173837810474235663936 2584504630787294811307707651176339848905776779091030 344683757227997208178596799336214779591224930724790 -109007588334167329416339365226436145104805858083074 47263463963356343864763656764511485413218260214556 -26779425817880917834577801065853668371670854034470 9163294873144165127498019535657008840931566560884 -1379759020786031850681298865609041545817539572016 -699478723107605893683431544878599911131239221406 244692049390161169302761970869086344567083038322 78540489082474710623493125543089178521377537610 -78716424601683602678608742465726709276737525494 25173518061014884135472369886037256780319988516 -4836166708211111809245880579909705615689129834 1768637095497261548326922468695557328400624940 -429850898341223440299348765179973816084530018 19469961208800979937888814373498281228239167 -24821751871467787485042676574274507156799610 3219790481697737478835915902290585311636786 9592865545868312374077558393501525441314837 -6556253014181766329530348484414202407590772 2773072326262366122713436092964407154800338 -715272895144819249545455557456728507209276 45978462810431309522584389119269652638825 6730573589612321449040643068050145310964 1325731081118472530350917783647975123638 1834448325146365375484205315831522219761 -1523305611725254525691255130351021799828 603441909532049430638491765376798875802 -101442462700799078539532417592458162035 -10241251250512568454720592435895293770 -6452094346751186800978178739271367110 6795353643266953595996716260612075075 -884990204900981964621706381999444245 -55908389909978144418982484043462972 -100028023126879465414712014342033203 26223103258562425215984276900225190 5351923747845358927379218498838662 -2625557939536756771368284160754409 909816404313314195979272810305553 -167829634694859162787921017709934 211284919717724389552207529747119 -171980293725162515422418572219958 67259250532723840311922302135190 -9851173505507339653953208561384 -2074464244243747821750225917355 149305688936004056360818191285 194773884650620572411731320922 90386304828566074319748489696 -66642243950496649664058138245 11890862993774590869697053316 239333315276351259950689278 346915238840060215147779328 -460449138542352681307280723 63143003875285086357707074 23719287807756147255827608 -6860231970239354052059120 128672921037763997167854 -213183294018995787329987 173594133554980864090344 -232650204821994824090433 50239507371429395768083 10025109079242094979860 1590059266159504846635 -4652704987316143090417 784949974508089914389 212442709444385689107 -51942528051583522862 -16397751259214265971 -514235278573781817 2849033087852990878 -864124208530433606 -14605367074230279 15032654473675925 516691534630103 -2444085114178734 663909169362152 1071310349477445 -389308767092952 -23217252226665 14438435571734 14673907180163 -5239909933531 -246143671962 308958779486 161505661149 -45392317474 -430204896 2797773328 547561623 0 81004098 23499616 646898 0 1810872 20727 0 0 25627 343 0 0 196 0 0 0 1 flint-3.1.3/src/fmpz_poly_factor/profile/p-factor_hard.c000066400000000000000000000055411461254215100233210ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2016 William Hart Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "profiler.h" /* assume that the user runs the program from the base directory of the flint repo */ #define MY_DIR "src/fmpz_poly_factor/profile/" void factor_poly(const char * file_str, const char * name, slong wanted_factors) { FILE * file; fmpz_poly_t f; fmpz_poly_factor_t fac; struct timeval start, stop; ulong ms; fmpz_poly_init(f); if (!strcmp(name, "S7")) fmpz_poly_swinnerton_dyer(f, 7); else if (!strcmp(name, "S8")) fmpz_poly_swinnerton_dyer(f, 8); else if (!strcmp(name, "S9")) fmpz_poly_swinnerton_dyer(f, 9); else if (!strcmp(name, "S10")) fmpz_poly_swinnerton_dyer(f, 10); else { file = fopen(file_str, "rw"); fmpz_poly_fread(file, f); fclose(file); } fmpz_poly_factor_init(fac); gettimeofday(&start, NULL); fmpz_poly_factor(fac, f); gettimeofday(&stop, NULL); ms = (stop.tv_sec - start.tv_sec)*1000 + (stop.tv_usec - start.tv_usec) / 1000; flint_printf("%s has %wd factors: %ld ms\n", name, fac->num, ms); if (fac->num != wanted_factors) { flint_printf("FAIL: expected %wd factors\n", wanted_factors); flint_abort(); } fmpz_poly_factor_clear(fac); fmpz_poly_clear(f); } int main(void) { flint_printf("\n"); flint_set_num_threads(8); factor_poly(MY_DIR"P1_flint", "P1", 36); factor_poly(MY_DIR"P2_flint", "P2", 12); factor_poly(MY_DIR"P3_flint", "P3", 16); factor_poly(MY_DIR"P4_flint", "P4", 2); factor_poly(MY_DIR"P5_flint", "P5", 1); factor_poly(MY_DIR"P6_flint", "P6", 6); factor_poly(MY_DIR"P7_flint", "P7", 1); factor_poly(MY_DIR"P8_flint", "P8", 1); factor_poly(MY_DIR"M12_5_flint", "M12_5", 1); factor_poly(MY_DIR"M12_6_flint", "M12_6", 2); factor_poly(MY_DIR"T1_flint", "T1", 2); factor_poly(MY_DIR"T2_flint", "T2", 2); factor_poly(MY_DIR"T3_flint", "T3", 4); factor_poly(MY_DIR"H1_flint", "H1", 28); factor_poly(MY_DIR"S7_flint", "S7", 1); factor_poly(MY_DIR"S8_flint", "S8", 1); factor_poly(MY_DIR"C1_flint", "C1", 32); /* Not run by default because they are too slow currently */ #if 0 factor_poly(MY_DIR"H2_flint", "H2", 6); /* 400 seconds */ factor_poly(MY_DIR"S9_flint", "S9", 1); /* 360 seconds */ factor_poly(MY_DIR"S10_flint", "S10", 1); /* long */ #endif } flint-3.1.3/src/fmpz_poly_factor/profile/p-factor_quadratic_cubic.c000066400000000000000000000240531461254215100255240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "profiler.h" static slong count_omega(const fmpz_poly_factor_t fac) { slong i, omega = 0; for (i = 0; i < fac->num; i++) omega += fac->exp[i]; return omega; } int main(void) { flint_bitcnt_t max_bits; slong it, i, j, omega; ulong tab[11][20]; timeit_t timer; FLINT_TEST_INIT(state); printf(" bits : "); omega = 0; for (max_bits = 10, it = 0; max_bits <= 3000; max_bits *= 2, it++) { fmpz_t d; fmpz_poly_t g; fmpz_poly_struct * f; fmpz_poly_factor_t fac; slong reps = 1000000/(max_bits + 100); slong outer_reps = 10; f = flint_malloc(reps * sizeof(fmpz_poly_struct)); for (i = 0; i < reps; i++) fmpz_poly_init(f + i); fmpz_poly_init(g); fmpz_poly_factor_init(fac); fmpz_init(d); tab[0][it] = max_bits; flint_printf(" %06wu", tab[0][it]); fflush(stdout); /* (degree 1)^2 */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_pow(f + i, g, 2); } timeit_start(timer); for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[1][it] = timer->cpu; /* (degree 1)*(degree 1) */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_set(f + i, g); do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_mul(f + i, f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[2][it] = timer->cpu; /* (degree 2 +) */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 3, n_randint(state, max_bits) + 2); } while (g->length != 3 || (fmpz_poly_discriminant(d, g), fmpz_sgn(d) < 0)); fmpz_poly_set(f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[3][it] = timer->cpu; /* (degree 2 -) */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 3, n_randint(state, max_bits) + 2); } while (g->length != 3 || (fmpz_poly_discriminant(d, g), fmpz_sgn(d) > 0)); fmpz_poly_set(f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[4][it] = timer->cpu; /* (degree 1)^3 */ for (i = 0; i< reps; i++) { do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_pow(f + i, g, 3); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[5][it] = timer->cpu; /* (degree 1)*(degree 1)^2 */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_pow(f + i, g, 2); do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_mul(f + i, f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[6][it] = timer->cpu; /* (degree 1)*(degree 1)*(degree 1) */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_set(f + i, g); do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_mul(f + i, f + i, g); do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_mul(f + i, f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[7][it] = timer->cpu; /* (degree 1)*(degree 2 +) */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_set(f + i, g); do { fmpz_poly_randtest(g, state, 3, n_randint(state, max_bits) + 2); } while (g->length != 3 || (fmpz_poly_discriminant(d, g), fmpz_sgn(d) < 0)); fmpz_poly_mul(f + i, f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[8][it] = timer->cpu; /* (degree 1)*(degree 2 -) */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_set(f + i, g); do { fmpz_poly_randtest(g, state, 3, n_randint(state, max_bits) + 2); } while (g->length != 3 || (fmpz_poly_discriminant(d, g), fmpz_sgn(d) > 0)); fmpz_poly_mul(f + i, f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[9][it] = timer->cpu; /* (degree 3) */ for (i = 0; i < reps; i++) { do { fmpz_poly_randtest(g, state, 4, n_randint(state, max_bits) + 2); } while (g->length != 4); fmpz_poly_set(f + i, g); } timeit_start(timer); for (i = 0; i < reps; i++) { fmpz_poly_factor(fac, f + i); omega += count_omega(fac); } for (j = 0; j < outer_reps; j++) for (i = 0; i < reps; i++) fmpz_poly_factor(fac, f + i); timeit_stop(timer); tab[10][it] = timer->cpu; for (i = 0; i < reps; i++) fmpz_poly_clear(f + i); flint_free(f); fmpz_poly_clear(g); fmpz_poly_factor_clear(fac); fmpz_clear(d); } flint_printf("\n", max_bits); printf("---------------"); for (i = 0; i < it; i++) flint_printf("-------"); printf("\n"); printf(" (d1)^2 : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[1][i]); printf("\n"); printf(" (d1)(d1) : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[2][i]); printf("\n"); printf(" (d2+) : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[3][i]); printf("\n"); printf(" (d2-) : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[4][i]); printf("\n"); printf(" (d1)^3 : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[5][i]); printf("\n"); printf(" (d1)(d1)^2 : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[6][i]); printf("\n"); printf("(d1)(d1)(d1) : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[7][i]); printf("\n"); printf(" (d1)(d2+) : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[8][i]); printf("\n"); printf(" (d1)(d2-) : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[9][i]); printf("\n"); printf(" (d3) : "); for (i = 0; i < it; i++) flint_printf(" %06wu", tab[10][i]); printf("\n"); FLINT_TEST_CLEANUP(state); flint_printf("factors found: %wd\n", omega); return 0; } flint-3.1.3/src/fmpz_poly_factor/realloc.c000066400000000000000000000035161461254215100205710ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_realloc(fmpz_poly_factor_t fac, slong alloc) { if (alloc == 0) /* Clear up, reinitialise */ { fmpz_poly_factor_clear(fac); fmpz_poly_factor_init(fac); } else if (fac->alloc) /* Realloc */ { if (fac->alloc > alloc) { slong i; for (i = alloc; i < fac->num; i++) fmpz_poly_clear(fac->p + i); fac->p = flint_realloc(fac->p, alloc * sizeof(fmpz_poly_struct)); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); fac->alloc = alloc; } else if (fac->alloc < alloc) { slong i; fac->p = flint_realloc(fac->p, alloc * sizeof(fmpz_poly_struct)); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); for (i = fac->alloc; i < alloc; i++) { fmpz_poly_init(fac->p + i); fac->exp[i] = WORD(0); } fac->alloc = alloc; } } else /* Nothing allocated already so do it now */ { slong i; fac->p = flint_malloc(alloc * sizeof(fmpz_poly_struct)); fac->exp = flint_calloc(alloc, sizeof(slong)); for (i = 0; i < alloc; i++) fmpz_poly_init(fac->p + i); fac->num = 0; fac->alloc = alloc; } } flint-3.1.3/src/fmpz_poly_factor/set.c000066400000000000000000000022611461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" void fmpz_poly_factor_set(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac) { if (res != fac) { if (fac->num == 0) { fmpz_poly_factor_clear(res); fmpz_poly_factor_init(res); } else { slong i; fmpz_poly_factor_fit_length(res, fac->num); fmpz_set(&(res->c), &(fac->c)); for (i = 0; i < fac->num; i++) { fmpz_poly_set(res->p + i, fac->p + i); res->exp[i] = fac->exp[i]; } for ( ; i < res->num; i++) { fmpz_poly_zero(res->p + i); res->exp[i] = 0; } res->num = fac->num; } } } flint-3.1.3/src/fmpz_poly_factor/test/000077500000000000000000000000001461254215100177565ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly_factor/test/main.c000066400000000000000000000021011461254215100210400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor.c" #include "t-factor_cubic.c" #include "t-factor_squarefree.c" #include "t-factor_zassenhaus.c" #include "t-zassenhaus_subset.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_poly_factor), TEST_FUNCTION(fmpz_poly_factor_cubic), TEST_FUNCTION(fmpz_poly_factor_squarefree), TEST_FUNCTION(fmpz_poly_factor_zassenhaus), TEST_FUNCTION(fmpz_poly_factor_zassenhaus_subset) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_poly_factor/test/t-factor.c000066400000000000000000000144661461254215100216540ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #define LONG_FAC_TEST 0 /* run an extra long test */ #define TEST_HARD 0 /* test hard polynomials */ #if LONG_FAC_TEST #define FAC_MULT 5 #else #define FAC_MULT 1 #endif #if TEST_HARD #include void factor_poly(const char * file_str, const char * name) { FILE * file; fmpz_poly_t f; fmpz_poly_factor_t fac; struct timeval start, stop; ulong ms; fmpz_poly_init(f); file = fopen(file_str, "rw"); fmpz_poly_fread(file, f); fmpz_poly_factor_init(fac); gettimeofday(&start, NULL); fmpz_poly_factor(fac, f); gettimeofday(&stop, NULL); ms = (stop.tv_sec - start.tv_sec)*1000 + (stop.tv_usec - start.tv_usec) / 1000; flint_printf("%s has %wd factors: %ld ms\n", name, fac->num, ms); fmpz_poly_factor_clear(fac); fclose(file); fmpz_poly_clear(f); } #endif TEST_FUNCTION_START(fmpz_poly_factor, state) { int i, result; int tmul = 100; #ifdef _WIN32 tmul = 1; #endif #if TEST_HARD #define MY_DIR "/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/" flint_printf("\n"); factor_poly(MY_DIR"P1_flint", "P1"); factor_poly(MY_DIR"P2_flint", "P2"); factor_poly(MY_DIR"P3_flint", "P3"); factor_poly(MY_DIR"P4_flint", "P4"); factor_poly(MY_DIR"P5_flint", "P5"); factor_poly(MY_DIR"P6_flint", "P6"); factor_poly(MY_DIR"P7_flint", "P7"); factor_poly(MY_DIR"P8_flint", "P8"); factor_poly(MY_DIR"M12_5_flint", "M12_5"); factor_poly(MY_DIR"M12_6_flint", "M12_6"); factor_poly(MY_DIR"T1_flint", "T1"); factor_poly(MY_DIR"T2_flint", "T2"); factor_poly(MY_DIR"T3_flint", "T3"); factor_poly(MY_DIR"H1_flint", "H1"); factor_poly(MY_DIR"S7_flint", "S7"); factor_poly(MY_DIR"S8_flint", "S8"); factor_poly(MY_DIR"C1_flint", "C1"); /* factor_poly(MY_DIR"S9_flint", "S9"); factor_poly(MY_DIR"S10_flint", "S10"); factor_poly(MY_DIR"H2_flint", "H2"); */ #endif for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_t c; fmpz_poly_t f, g, h, t; fmpz_poly_factor_t fac; slong j, k, n = n_randint(state, 10*FAC_MULT); slong facs1 = 0, facs2 = 0; fmpz_init(c); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(t); fmpz_poly_factor_init(fac); fmpz_randtest_not_zero(c, state, n_randint(state, 10) + 1); fmpz_poly_set_fmpz(f, c); for (j = 0; j < n; j++) { do { fmpz_poly_randtest(g, state, n_randint(state, 10) + 2, n_randint(state, 100)); } while (g->length == 0); k = 0; while (k < g->length && fmpz_is_zero(g->coeffs + k)) k++; facs1 += k; /* count powers of x separately */ if (k < g->length - 1) facs1++; /* rough lower bound of factors of f */ fmpz_poly_mul(f, f, g); } fmpz_poly_factor(fac, f); fmpz_poly_set_fmpz(h, &fac->c); for (j = 0; j < fac->num; j++) { if (fac->exp[j] == 1) fmpz_poly_mul(h, h, fac->p + j); else { fmpz_poly_pow(t, fac->p + j, fac->exp[j]); fmpz_poly_mul(h, h, t); } facs2 += fac->exp[j]; } result = fmpz_poly_equal(f, h) && facs1 <= facs2; if (!result) { flint_printf("FAIL:\n"); flint_printf("facs1 = %wd, facs2 = %wd\n", facs1, facs2); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("fac = "), fmpz_poly_factor_print(fac), flint_printf("\n\n"); fflush(stdout); flint_abort(); } for (j = 0; j < fac->num; j++) { for (k = j + 1; k < fac->num; k++) { if (fmpz_poly_equal(fac->p + j, fac->p + k)) { flint_printf("FAIL (repeated factor):\n"); flint_printf("facs1 = %wd, facs2 = %wd\n", facs1, facs2); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("fac = "), fmpz_poly_factor_print(fac), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_poly_content(c, fac->p + j); if (!fmpz_is_one(c) || fmpz_sgn((fac->p + j)->coeffs + fmpz_poly_degree(fac->p + j)) < 0) { flint_printf("FAIL (factor not reduced):\n"); flint_printf("facs1 = %wd, facs2 = %wd\n", facs1, facs2); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("fac = "), fmpz_poly_factor_print(fac), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(t); fmpz_poly_factor_clear(fac); } /* Regression test: #783 */ { fmpz_poly_t a; fmpz_poly_factor_t f; fmpz_poly_init(a); fmpz_poly_set_str(a, "31 294114975 822759704 601207031 3459410600 6329635407 5561735376 2870497527 -364079376 -984488613 -2855108728 -5168185293 -2678402184 -3199593893 -2740409376 -1003657917 -549998688 -252445155 -80724312 -19101979 -28418280 -2087859 -9732528 -2615547 -159120 -148311 -4680 -1359 2504 73 0 1"); fmpz_poly_factor_init(f); fmpz_poly_factor(f, a); fmpz_poly_factor_clear(f); fmpz_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_factor/test/t-factor_cubic.c000066400000000000000000000100451461254215100230060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" static void check_factorization( const fmpz_poly_factor_t fac, const fmpz_poly_t f, slong omega_lower_bound) { slong i; slong omega; fmpz_t c; fmpz_poly_t h, t; fmpz_init(c); fmpz_poly_init(h); fmpz_poly_init(t); omega = 0; fmpz_poly_set_fmpz(h, &fac->c); for (i = 0; i < fac->num; i++) { omega += fac->exp[i]; fmpz_poly_pow(t, fac->p + i, fac->exp[i]); fmpz_poly_mul(h, h, t); if (fac->p[i].length < 2) { flint_printf("FAIL\ncheck constant factor\n"); fflush(stdout); flint_abort(); } fmpz_poly_content(c, fac->p + i); if (!fmpz_is_one(c) || fmpz_sgn(fac->p[i].coeffs + fac->p[i].length - 1) < 0) { flint_printf("FAIL\ncheck factor content\n"); fflush(stdout); flint_abort(); } } if (!fmpz_poly_equal(h, f)) { flint_printf("FAIL\ncheck factorization matches\n"); fflush(stdout); flint_abort(); } if (omega < omega_lower_bound) { flint_printf("FAIL\ncheck omega\n"); fflush(stdout); flint_abort(); } fmpz_clear(c); fmpz_poly_clear(h); fmpz_poly_clear(t); } TEST_FUNCTION_START(fmpz_poly_factor_cubic, state) { flint_bitcnt_t max_bits = 2000; slong i, tmul = 500; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_poly_t f, g; fmpz_poly_factor_t fac; fmpz_poly_init(g); fmpz_poly_init(f); fmpz_poly_factor_init(fac); /* (degree 1)^3 */ do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_pow(f, g, 3); fmpz_poly_factor(fac, f); check_factorization(fac, f, 3); /* (degree 1)*(degree 1)^2 */ do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_pow(f, g, 2); do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_mul(f, f, g); fmpz_poly_factor(fac, f); check_factorization(fac, f, 3); /* (degree 1)*(degree 1)*(degree 1) */ do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_set(f, g); do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_mul(f, f, g); do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_mul(f, f, g); fmpz_poly_factor(fac, f); check_factorization(fac, f, 3); /* (degree 1)*(degree 2) */ do { fmpz_poly_randtest(g, state, 2, n_randint(state, max_bits) + 2); } while (g->length != 2); fmpz_poly_set(f, g); do { fmpz_poly_randtest(g, state, 3, n_randint(state, max_bits) + 2); } while (g->length != 3); fmpz_poly_mul(f, f, g); fmpz_poly_factor(fac, f); check_factorization(fac, f, 2); /* (degree 3) */ do { fmpz_poly_randtest(g, state, 4, n_randint(state, max_bits) + 2); } while (g->length != 4); fmpz_poly_set(f, g); fmpz_poly_factor(fac, f); check_factorization(fac, f, 1); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_factor_clear(fac); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_factor/test/t-factor_squarefree.c000066400000000000000000000057371461254215100240770ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" TEST_FUNCTION_START(fmpz_poly_factor_squarefree, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t f, g[10], h, t; fmpz_poly_factor_t fac; slong k, l, n = n_randint(state, 10) + 1; fmpz_poly_init(f); fmpz_poly_init(h); fmpz_poly_init(t); fmpz_poly_factor_init(fac); fmpz_poly_one(f); for (k = 0; k < n; k++) { fmpz_poly_init(g[k]); fmpz_poly_randtest_not_zero(g[k], state, n_randint(state, 40)+1, 20); l = n_randint(state, 2) + 1; while (l--) fmpz_poly_mul(f, f, g[k]); } fmpz_poly_factor_squarefree(fac, f); /* Squarefree? */ result = 1; for (k = 0; k < fac->num && result; k++) { fmpz_poly_derivative(h, fac->p + k); fmpz_poly_gcd(t, h, fac->p + k); result &= fmpz_poly_is_one(t); } /* Product? */ fmpz_poly_set_fmpz(h, &(fac->c)); for (k = 0; k < fac->num; k++) { if (fac->exp[k] == 1) fmpz_poly_mul(h, h, fac->p + k); else { fmpz_poly_pow(t, fac->p + k, fac->exp[k]); fmpz_poly_mul(h, h, t); } } result &= fmpz_poly_equal(f, h); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_print_pretty(f, "x"), flint_printf("\n\n"); for (k = 0; k < n; k++) { flint_printf("g[%wd] = ", k), fmpz_poly_print_pretty(g[k], "x"), flint_printf("\n\n"); } flint_printf("h = "), fmpz_poly_print_pretty(h, "x"), flint_printf("\n\n"); fmpz_poly_factor_print(fac); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); for (k = 0; k < n; k++) fmpz_poly_clear(g[k]); fmpz_poly_clear(h); fmpz_poly_clear(t); fmpz_poly_factor_clear(fac); } /* check that the zero polynomial doesn't crash */ { fmpz_poly_factor_t fac; fmpz_poly_t f; fmpz_poly_init(f); fmpz_poly_factor_init(fac); fmpz_poly_factor_squarefree(fac, f); if (fac->num != 0 || !fmpz_is_zero(&(fac->c))) { flint_printf("FAIL: 0\n"); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_factor_clear(fac); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_factor/test/t-factor_zassenhaus.c000066400000000000000000000076651461254215100241230ustar00rootroot00000000000000/* Copyright (C) 2010 Andy Novocin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" TEST_FUNCTION_START(fmpz_poly_factor_zassenhaus, state) { slong i; for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpz_t c; fmpz_poly_t f, g, h, t; fmpz_poly_factor_t fac; slong j, k, n = n_randint(state, 7) + 1; slong facs1 = 0, facs2 = 0; fmpz_init(c); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); fmpz_poly_init(t); fmpz_poly_factor_init(fac); fmpz_randtest_not_zero(c, state, n_randint(state, 100) + 1); fmpz_poly_set_fmpz(f, c); for (j = 0; j < n; j++) { do { fmpz_poly_randtest(g, state, n_randint(state, 35/n) + 2, n_randint(state, 100)); } while (g->length == 0); k = 0; while (k < g->length && fmpz_is_zero(g->coeffs + k)) k++; facs1 += k; /* count powers of x separately */ if (k < g->length - 1) facs1++; /* rough lower bound of factors of f */ fmpz_poly_mul(f, f, g); } fmpz_poly_factor_zassenhaus(fac, f); fmpz_poly_set_fmpz(h, &fac->c); for (j = 0; j < fac->num; j++) { if (fac->exp[j] == 1) fmpz_poly_mul(h, h, fac->p + j); else { fmpz_poly_pow(t, fac->p + j, fac->exp[j]); fmpz_poly_mul(h, h, t); } facs2 += fac->exp[j]; } if (!fmpz_poly_equal(f, h) || facs1 > facs2) { flint_printf("FAIL:\n"); flint_printf("facs1 = %wd, facs2 = %wd\n", facs1, facs2); flint_printf("f = "), fmpz_poly_print_pretty(f, "x"), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("fac = "), fmpz_poly_factor_print(fac), flint_printf("\n\n"); fflush(stdout); flint_abort(); } for (j = 0; j < fac->num; j++) { for (k = j + 1; k < fac->num; k++) { if (fmpz_poly_equal(fac->p + j, fac->p + k)) { flint_printf("FAIL (repeated factor):\n"); flint_printf("facs1 = %wd, facs2 = %wd\n", facs1, facs2); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("fac = "), fmpz_poly_factor_print(fac), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_poly_content(c, fac->p + j); if (!fmpz_is_one(c) || fmpz_sgn(fmpz_poly_lead(fac->p + j)) < 0) { flint_printf("FAIL (factor not reduced):\n"); flint_printf("facs1 = %wd, facs2 = %wd\n", facs1, facs2); flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n"); flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n"); flint_printf("fac = "), fmpz_poly_factor_print(fac), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } fmpz_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(t); fmpz_poly_factor_clear(fac); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_factor/test/t-zassenhaus_subset.c000066400000000000000000000115101461254215100241320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly_factor.h" /* manual slow implementation of zassenhaus_subset_next_disjoint */ static int my_next_disjoint(slong * s, slong r) { slong i, j; slong * olds; olds = flint_malloc(r*sizeof(slong)); for (i = 0; i < r; i++) olds[i] = s[i]; next: if (!zassenhaus_subset_next(s, r)) { flint_free(olds); return 0; } for (i = 0; i < r; i++) { if (olds[i] >= 0 && s[i] >= 0) goto next; } j = 0; for (i = 0; i < r; i++) { if (olds[i] < 0) s[j++] = s[i]; } flint_free(olds); return 1; } /* length of s is r */ static void my_subset_print(slong * s, slong r) { slong i; FLINT_ASSERT(r >= 0); for (i = 0; i < r; i++) { if (s[i] >= 0) flint_printf(" %wd", s[i]); else flint_printf(" X", s[i]); } } TEST_FUNCTION_START(fmpz_poly_factor_zassenhaus_subset, state) { fmpz_t f; slong i, j, k, r; slong * s, * s1, * s2; int res1, res2; fmpz_init(f); for (r = 0; r <= 13; r++) { s = (slong *) flint_malloc(r*sizeof(slong)); s1 = (slong *) flint_malloc(r*sizeof(slong)); s2 = (slong *) flint_malloc(r*sizeof(slong)); for (j = 0; j < r; j++) s[j] = j; for (i = 0; i <= r; i++) { ulong cnt = 0; zassenhaus_subset_first(s, r, i); do { cnt++; k = 0; for (j = 0; j < r; j++) { if (s[j] != j && s[j] != -j - 1) { flint_printf("FAIL\ncheck subset element\n"); fflush(stdout); flint_abort(); } k += (s[j] >= 0); } if (k != i) { flint_printf("FAIL\ncheck subset size\n"); fflush(stdout); flint_abort(); } for (j = 0; j < r; j++) { s1[j] = s[j]; s2[j] = s[j]; } res1 = zassenhaus_subset_next_disjoint(s1, r); res2 = my_next_disjoint(s2, r); if (res1 != res2) { flint_printf("FAIL\ncheck next disjoint success\n"); flint_printf("s:"); my_subset_print(s, r); flint_printf("\n"); flint_printf("res1: %d res2: %d\n", res1, res2); fflush(stdout); flint_abort(); } k = 0; for (j = 0; j < r; j++) { if (s[j] < 0) { if (s1[k] != s[j] && s1[k] != -s[j] - 1) { flint_printf("FAIL\ncheck next disjoint is disjoint\n"); fflush(stdout); flint_abort(); } k++; } } if (res1) { for (j = 0; j < r - i; j++) { if (s1[j] != s2[j]) { flint_printf("FAIL\ncheck next disjoint subset\n"); flint_printf("s:"); my_subset_print(s, r); flint_printf("\n"); flint_printf("s1: "); my_subset_print(s1, r - i); flint_printf("\n"); flint_printf("s2: "); my_subset_print(s2, r - i); flint_printf("\n"); fflush(stdout); flint_abort(); } } } } while (zassenhaus_subset_next(s, r)); fmpz_bin_uiui(f, r, i); if (!fmpz_equal_ui(f, cnt)) { flint_printf("FAIL\ncheck subset size\n"); fflush(stdout); flint_abort(); } } flint_free(s2); flint_free(s1); flint_free(s); } fmpz_clear(f); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_factor/van_hoeij_check_if_solved.c000066400000000000000000000070301461254215100242740ustar00rootroot00000000000000/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" int _compare_poly_lengths(const void * a, const void * b) { const fmpz_poly_struct * p = (fmpz_poly_struct *) a; const fmpz_poly_struct * q = (fmpz_poly_struct *) b; return p->length - q->length; } int fmpz_poly_factor_van_hoeij_check_if_solved(fmpz_mat_t M, fmpz_poly_factor_t final_fac, fmpz_poly_factor_t lifted_fac, const fmpz_poly_t f, fmpz_t P, slong exp, fmpz_t lc) { fmpz_poly_factor_t trial_factors; fmpz_poly_t prod, q, f_copy; fmpz_t temp_lc; fmpz_mat_t U; nmod_poly_t f2, g2, rem; int num_facs, res = 0; slong i, j, r; slong * part; r = lifted_fac->num; part = (slong *) flint_calloc(r, sizeof(slong)); fmpz_poly_factor_init(trial_factors); fmpz_poly_init(prod); fmpz_poly_init(q); fmpz_poly_init(f_copy); fmpz_mat_window_init(U, M, 0, 0, M->r, r); fmpz_init(temp_lc); nmod_poly_init(f2, 2); nmod_poly_init(g2, 2); nmod_poly_init(rem, 2); if ((num_facs = fmpz_mat_col_partition(part, U, 1)) == 0 || num_facs > r) goto cleanup; if (num_facs == 1) { /* f is irreducible */ fmpz_poly_factor_insert(final_fac, f, exp); res = 1; goto cleanup; } /* there is a potential 0-1 basis, so make the potential factors */ fmpz_set(temp_lc, lc); for (i = 1; i <= num_facs; i++) { fmpz_poly_set_fmpz(prod, temp_lc); for (j = 0; j < r; j++) { if (part[j] == i) { fmpz_poly_mul(prod, prod, lifted_fac->p + j); fmpz_poly_scalar_smod_fmpz(prod, prod, P); } } fmpz_poly_content(temp_lc, prod); fmpz_abs(temp_lc, temp_lc); fmpz_poly_scalar_divexact_fmpz(prod, prod, temp_lc); fmpz_poly_factor_insert(trial_factors, prod, 1); } /* sort factors by length */ qsort(trial_factors->p, trial_factors->num, sizeof(fmpz_poly_struct), _compare_poly_lengths); /* trial divide potential factors */ fmpz_poly_set(f_copy, f); for (i = 0; i < trial_factors->num && num_facs > 1; i++) { /* check if the polynomial divides mod 2 */ fmpz_poly_get_nmod_poly(f2, f_copy); fmpz_poly_get_nmod_poly(g2, trial_factors->p + i); nmod_poly_rem(rem, f2, g2); if (nmod_poly_is_zero(rem) && fmpz_poly_divides(q, f_copy, trial_factors->p + i)) { fmpz_poly_swap(q, f_copy); num_facs--; } else goto cleanup; } /* if we found all the factors, insert them */ if (num_facs == 1) { for (j = 0; j < i; j++) fmpz_poly_factor_insert(final_fac, trial_factors->p + j, exp); fmpz_poly_factor_insert(final_fac, f_copy, exp); res = 1; /* we factorised f */ } cleanup: nmod_poly_clear(f2); nmod_poly_clear(g2); nmod_poly_clear(rem); fmpz_clear(temp_lc); fmpz_poly_clear(q); fmpz_poly_clear(f_copy); fmpz_poly_clear(prod); fmpz_poly_factor_clear(trial_factors); fmpz_mat_window_clear(U); flint_free(part); return res; } flint-3.1.3/src/fmpz_poly_factor/zassenhaus_prune.c000066400000000000000000000060701461254215100225430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" void zassenhaus_prune_clear(zassenhaus_prune_t Z) { if (Z->alloc > 0) { flint_free(Z->pos_degs); flint_free(Z->new_degs); } } void zassenhaus_prune_set_degree(zassenhaus_prune_t Z, slong d) { slong i; if (d < 1) { flint_throw(FLINT_ERROR, "zassenhaus_prune_set_degree"); return; } if (Z->alloc > 0) { Z->pos_degs = (unsigned char *) flint_realloc(Z->pos_degs, (d + 1)*sizeof(unsigned char)); Z->new_degs = (slong *) flint_realloc(Z->new_degs, (d + 1)*sizeof(slong)); } else { Z->pos_degs = (unsigned char *) flint_malloc( (d + 1)*sizeof(unsigned char)); Z->new_degs = (slong *) flint_malloc((d + 1)*sizeof(slong)); } Z->alloc = d + 1; Z->deg = d; for (i = 0; i <= d; i++) Z->pos_degs[i] = 1; Z->new_length = 0; Z->new_total = 0; } void zassenhaus_prune_add_factor(zassenhaus_prune_t Z, slong deg, slong exp) { slong i; if (exp < 1 || deg < 1) return; for (i = 0; i < exp; i++) { if (Z->new_length >= Z->deg) { flint_throw(FLINT_ERROR, "zassenhaus_prune_add_factor"); return; } Z->new_total += deg; Z->new_degs[Z->new_length] = deg; Z->new_length++; } } void zassenhaus_prune_end_add_factors(zassenhaus_prune_t Z) { slong i, j; unsigned char * a = Z->pos_degs; unsigned char pos_mask = 1; unsigned char new_mask = 2; if (Z->new_total != Z->deg) { flint_throw(FLINT_ERROR, "zassenhaus_prune_add_factor"); } a[0] |= new_mask; for (j = 1; j <= Z->deg; j++) a[j] &= ~new_mask; for (i = 0; i < Z->new_length; i++) { slong d = Z->new_degs[i]; for (j = Z->deg; j >= 0; j--) { if ((a[j] & new_mask) != 0) { if (j + d > Z->deg) { flint_throw(FLINT_ERROR, "zassenhaus_prune_add_factor"); } a[j + d] |= new_mask; } } } /* merge new possibilities with old */ for (j = 0; j <= Z->deg; j++) a[j] &= a[j] >> 1; /* 0 and deg should always be possible */ if (a[0] != pos_mask || a[Z->deg] != pos_mask) { flint_throw(FLINT_ERROR, "zassenhaus_prune_add_factor"); } } int zassenhaus_prune_must_be_irreducible(const zassenhaus_prune_t Z) { slong i; for (i = 1; i < Z->deg; i++) { if (Z->pos_degs[i] != 0) return 0; } return 1; } flint-3.1.3/src/fmpz_poly_factor/zassenhaus_subset.c000066400000000000000000000037651461254215100227270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" /* first subset of size m */ void zassenhaus_subset_first(slong * s, slong r, slong m) { slong i; FLINT_ASSERT(0 <= m && m <= r); for (i = 0; i < r; i++) { if (i >= m) s[i] = (s[i] < 0) ? s[i] : -s[i] - 1; else s[i] = (s[i] >= 0) ? s[i] : -s[i] - 1; } } /* next subset of the same size, 1 for success, 0 for failure */ int zassenhaus_subset_next(slong * s, slong r) { slong i, j, k; i = 0; while (i < r && s[i] < 0) i++; j = i; while (i < r && s[i] >= 0) i++; k = i; if (k == 0 || k >= r) return 0; s[k] = -s[k] - 1; s[k - 1] = -s[k - 1] - 1; if (j > 0) { for (i = 0; i < k - j - 1; i++) if (s[i] < 0) s[i] = -s[i] - 1; for (i = k - j - 1; i < k - 1; i++) if (s[i] >= 0) s[i] = -s[i] - 1; } return 1; } /* next subset of same size and disjoint from current, delete current idxs */ slong zassenhaus_subset_next_disjoint(slong * s, slong r) { slong i, j, last, total, min; total = 0; last = r - 1; for (i = 0; i < r; i++) { if (s[i] >= 0) { total++; last = i; } } j = 0; for (i = 0; i < r; i++) if (s[i] < 0) s[j++] = s[i]; if (r - total < total || total < 1 || last == r - 1) return 0; min = FLINT_MIN(total - 1, last - total + 1); for (i = 0; i < min; i++) s[i] = -s[i] - 1; for (i = last - total + 1; i < last - min + 1; i++) s[i] = -s[i] - 1; return 1; } flint-3.1.3/src/fmpz_poly_mat.h000066400000000000000000000201321461254215100164510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef POLY_MAT_H #define POLY_MAT_H #ifdef FMPZ_POLY_MAT_INLINES_C #define FMPZ_POLY_MAT_INLINE #else #define FMPZ_POLY_MAT_INLINE static inline #endif #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif /* Types *********************************************************************/ FMPZ_POLY_MAT_INLINE fmpz_poly_struct * fmpz_poly_mat_entry(const fmpz_poly_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } FMPZ_POLY_MAT_INLINE slong fmpz_poly_mat_nrows(const fmpz_poly_mat_t mat) { return mat->r; } FMPZ_POLY_MAT_INLINE slong fmpz_poly_mat_ncols(const fmpz_poly_mat_t mat) { return mat->c; } /* Memory management *********************************************************/ void fmpz_poly_mat_init(fmpz_poly_mat_t mat, slong rows, slong cols); void fmpz_poly_mat_init_set(fmpz_poly_mat_t mat, const fmpz_poly_mat_t src); void fmpz_poly_mat_swap(fmpz_poly_mat_t mat1, fmpz_poly_mat_t mat2); FMPZ_POLY_MAT_INLINE void fmpz_poly_mat_swap_entrywise(fmpz_poly_mat_t mat1, fmpz_poly_mat_t mat2) { slong i, j; for (i = 0; i < fmpz_poly_mat_nrows(mat1); i++) for (j = 0; j < fmpz_poly_mat_ncols(mat1); j++) FLINT_SWAP(fmpz_poly_struct, *fmpz_poly_mat_entry(mat2, i, j), *fmpz_poly_mat_entry(mat1, i, j)); } void fmpz_poly_mat_set(fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2); void fmpz_poly_mat_clear(fmpz_poly_mat_t mat); /* Comparison ****************************************************************/ int fmpz_poly_mat_equal(const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2); int fmpz_poly_mat_is_zero(const fmpz_poly_mat_t mat); int fmpz_poly_mat_is_one(const fmpz_poly_mat_t mat); FMPZ_POLY_MAT_INLINE int fmpz_poly_mat_is_empty(const fmpz_poly_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } FMPZ_POLY_MAT_INLINE int fmpz_poly_mat_is_square(const fmpz_poly_mat_t mat) { return (mat->r == mat->c); } /* Standard matrices *********************************************************/ void fmpz_poly_mat_zero(fmpz_poly_mat_t mat); void fmpz_poly_mat_one(fmpz_poly_mat_t mat); /* Random matrices ***********************************************************/ void fmpz_poly_mat_randtest(fmpz_poly_mat_t mat, flint_rand_t state, slong len, flint_bitcnt_t bits); void fmpz_poly_mat_randtest_unsigned(fmpz_poly_mat_t mat, flint_rand_t state, slong len, flint_bitcnt_t bits); void fmpz_poly_mat_randtest_sparse(fmpz_poly_mat_t A, flint_rand_t state, slong len, flint_bitcnt_t bits, float density); /* Windows and concatenation */ void fmpz_poly_mat_window_init(fmpz_poly_mat_t window, const fmpz_poly_mat_t mat, slong r1, slong c1, slong r2, slong c2); void fmpz_poly_mat_window_clear(fmpz_poly_mat_t window); void fmpz_poly_mat_concat_horizontal(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2); void fmpz_poly_mat_concat_vertical(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2); /* Input and output **********************************************************/ void fmpz_poly_mat_print(const fmpz_poly_mat_t mat, const char * x); /* Norms *********************************************************************/ slong fmpz_poly_mat_max_bits(const fmpz_poly_mat_t A); slong fmpz_poly_mat_max_length(const fmpz_poly_mat_t A); /* Transpose *****************************************************************/ void fmpz_poly_mat_transpose(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); /* Truncation ****************************************************************/ void fmpz_poly_mat_truncate(fmpz_poly_mat_t A, slong len); /* Scalar arithmetic *********************************************************/ void fmpz_poly_mat_scalar_mul_fmpz_poly(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_poly_t c); void fmpz_poly_mat_scalar_mul_fmpz(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_t c); /* Matrix arithmetic *********************************************************/ void fmpz_poly_mat_add(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); void fmpz_poly_mat_sub(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); void fmpz_poly_mat_neg(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); void fmpz_poly_mat_mul(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); void fmpz_poly_mat_mul_classical(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); void fmpz_poly_mat_mul_KS(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); void fmpz_poly_mat_mullow(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B, slong len); void fmpz_poly_mat_sqr(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); void fmpz_poly_mat_sqr_classical(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); void fmpz_poly_mat_sqr_KS(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); void fmpz_poly_mat_sqrlow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, slong len); void fmpz_poly_mat_pow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp); void fmpz_poly_mat_pow_trunc(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp, slong len); void fmpz_poly_mat_prod(fmpz_poly_mat_t res, fmpz_poly_mat_t * const factors, slong n); /* Evaluation ****************************************************************/ void fmpz_poly_mat_evaluate_fmpz(fmpz_mat_t B, const fmpz_poly_mat_t A, const fmpz_t x); /* Row reduction *************************************************************/ slong fmpz_poly_mat_find_pivot_any(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c); slong fmpz_poly_mat_find_pivot_partial(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c); slong fmpz_poly_mat_fflu(fmpz_poly_mat_t B, fmpz_poly_t den, slong * perm, const fmpz_poly_mat_t A, int rank_check); slong fmpz_poly_mat_rref(fmpz_poly_mat_t B, fmpz_poly_t den, const fmpz_poly_mat_t A); /* Trace *********************************************************************/ void fmpz_poly_mat_trace(fmpz_poly_t trace, const fmpz_poly_mat_t mat); /* Determinant and rank ******************************************************/ void fmpz_poly_mat_det(fmpz_poly_t det, const fmpz_poly_mat_t A); void fmpz_poly_mat_det_fflu(fmpz_poly_t det, const fmpz_poly_mat_t A); void fmpz_poly_mat_det_interpolate(fmpz_poly_t det, const fmpz_poly_mat_t A); slong fmpz_poly_mat_rank(const fmpz_poly_mat_t A); /* Inverse *******************************************************************/ int fmpz_poly_mat_inv(fmpz_poly_mat_t Ainv, fmpz_poly_t den, const fmpz_poly_mat_t A); /* Nullspace *****************************************************************/ slong fmpz_poly_mat_nullspace(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat); /* Solving *******************************************************************/ int fmpz_poly_mat_solve(fmpz_poly_mat_t X, fmpz_poly_t den, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); int fmpz_poly_mat_solve_fflu(fmpz_poly_mat_t X, fmpz_poly_t den, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); void fmpz_poly_mat_solve_fflu_precomp(fmpz_poly_mat_t X, const slong * perm, const fmpz_poly_mat_t FFLU, const fmpz_poly_mat_t B); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_poly_mat/000077500000000000000000000000001461254215100163025ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly_mat/add.c000066400000000000000000000014711461254215100172010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_add(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_add(fmpz_poly_mat_entry(C, i, j), fmpz_poly_mat_entry(A, i, j), fmpz_poly_mat_entry(B, i, j)); } flint-3.1.3/src/fmpz_poly_mat/clear.c000066400000000000000000000013551461254215100175400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_clear(fmpz_poly_mat_t A) { if (A->entries) { slong i; for (i = 0; i < A->r * A->c; i++) fmpz_poly_clear(A->entries + i); flint_free(A->entries); flint_free(A->rows); } else if (A->r != 0) flint_free(A->rows); } flint-3.1.3/src/fmpz_poly_mat/concat.c000066400000000000000000000032351461254215100177200ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_concat_horizontal(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { fmpz_poly_set(fmpz_poly_mat_entry(res, i, j), fmpz_poly_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { fmpz_poly_set(fmpz_poly_mat_entry(res, i, j + c1), fmpz_poly_mat_entry(mat2, i, j)); } } } void fmpz_poly_mat_concat_vertical(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { fmpz_poly_set(fmpz_poly_mat_entry(res, i, j), fmpz_poly_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { fmpz_poly_set(fmpz_poly_mat_entry(res, i + r1, j), fmpz_poly_mat_entry(mat2, i, j)); } } } flint-3.1.3/src/fmpz_poly_mat/det.c000066400000000000000000000023621461254215100172250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_det(fmpz_poly_t det, const fmpz_poly_mat_t A) { slong n = A->r; if (n == 0) { fmpz_poly_set_ui(det, UWORD(1)); } else if (n == 1) { fmpz_poly_set(det, fmpz_poly_mat_entry(A, 0, 0)); } else if (n == 2) { fmpz_poly_t tmp; fmpz_poly_init(tmp); fmpz_poly_mul(det, fmpz_poly_mat_entry(A, 0, 0), fmpz_poly_mat_entry(A, 1, 1)); fmpz_poly_mul(tmp, fmpz_poly_mat_entry(A, 0, 1), fmpz_poly_mat_entry(A, 1, 0)); fmpz_poly_sub(det, det, tmp); fmpz_poly_clear(tmp); } else if (n < 15) /* should be entry sensitive too */ { fmpz_poly_mat_det_fflu(det, A); } else { fmpz_poly_mat_det_interpolate(det, A); } } flint-3.1.3/src/fmpz_poly_mat/det_fflu.c000066400000000000000000000016751461254215100202470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "perm.h" void fmpz_poly_mat_det_fflu(fmpz_poly_t det, const fmpz_poly_mat_t A) { slong n = fmpz_poly_mat_nrows(A); if (n == 0) fmpz_poly_one(det); else { fmpz_poly_mat_t tmp; slong * perm; fmpz_poly_mat_init_set(tmp, A); perm = _perm_init(n); fmpz_poly_mat_fflu(tmp, det, perm, tmp, 1); if (_perm_parity(perm, n)) fmpz_poly_neg(det, det); _perm_clear(perm); fmpz_poly_mat_clear(tmp); } } flint-3.1.3/src/fmpz_poly_mat/det_interpolate.c000066400000000000000000000024371461254215100216360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_det_interpolate(fmpz_poly_t det, const fmpz_poly_mat_t A) { slong i, l, n, len; fmpz_mat_t X; fmpz * x; fmpz * d; n = A->r; if (n == 0) { fmpz_poly_one(det); return; } l = fmpz_poly_mat_max_length(A); if (l == 0) { fmpz_poly_zero(det); return; } /* Bound degree based on Laplace expansion */ len = n*(l - 1) + 1; x = _fmpz_vec_init(len); d = _fmpz_vec_init(len); fmpz_mat_init(X, n, n); for (i = 0; i < len; i++) { fmpz_set_si(x + i, -len/2 + i); fmpz_poly_mat_evaluate_fmpz(X, A, x + i); fmpz_mat_det(d + i, X); } fmpz_poly_interpolate_fmpz_vec(det, x, d, len); _fmpz_vec_clear(x, len); _fmpz_vec_clear(d, len); fmpz_mat_clear(X); } flint-3.1.3/src/fmpz_poly_mat/equal.c000066400000000000000000000015061461254215100175570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int fmpz_poly_mat_equal(const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { slong i, j; if (A->r != B->r || A->c != B->c) return 0; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) if (!fmpz_poly_equal(fmpz_poly_mat_entry(A, i, j), fmpz_poly_mat_entry(B, i, j))) return 0; return 1; } flint-3.1.3/src/fmpz_poly_mat/evaluate_fmpz.c000066400000000000000000000013711461254215100213120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_evaluate_fmpz(fmpz_mat_t B, const fmpz_poly_mat_t A, const fmpz_t x) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_evaluate_fmpz(fmpz_mat_entry(B, i, j), fmpz_poly_mat_entry(A, i, j), x); } flint-3.1.3/src/fmpz_poly_mat/fflu.c000066400000000000000000000044361461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #define E(j,k) fmpz_poly_mat_entry(B,j,k) static inline void fmpz_poly_mat_swap_rows(fmpz_poly_mat_t mat, slong * perm, slong r, slong s) { if (r != s) { fmpz_poly_struct * u; slong t; if (perm) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } u = mat->rows[s]; mat->rows[s] = mat->rows[r]; mat->rows[r] = u; } } slong fmpz_poly_mat_fflu(fmpz_poly_mat_t B, fmpz_poly_t den, slong * perm, const fmpz_poly_mat_t A, int rank_check) { fmpz_poly_t t; slong m, n, j, k, rank, r, pivot_row, pivot_col; if (fmpz_poly_mat_is_empty(A)) { fmpz_poly_one(den); return 0; } fmpz_poly_mat_set(B, A); m = B->r; n = B->c; rank = pivot_row = pivot_col = 0; fmpz_poly_init(t); while (pivot_row < m && pivot_col < n) { r = fmpz_poly_mat_find_pivot_partial(B, pivot_row, m, pivot_col); if (r == -1) { if (rank_check) { fmpz_poly_zero(den); rank = 0; break; } pivot_col++; continue; } else if (r != pivot_row) fmpz_poly_mat_swap_rows(B, perm, pivot_row, r); rank++; for (j = pivot_row + 1; j < m; j++) { for (k = pivot_col + 1; k < n; k++) { fmpz_poly_mul(E(j, k), E(j, k), E(pivot_row, pivot_col)); fmpz_poly_mul(t, E(j, pivot_col), E(pivot_row, k)); fmpz_poly_sub(E(j, k), E(j, k), t); if (pivot_row > 0) fmpz_poly_divexact(E(j, k), E(j, k), den); } } fmpz_poly_set(den, E(pivot_row, pivot_col)); pivot_row++; pivot_col++; } fmpz_poly_clear(t); return rank; } flint-3.1.3/src/fmpz_poly_mat/find_pivot_any.c000066400000000000000000000013761461254215100214650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" slong fmpz_poly_mat_find_pivot_any(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c) { slong r; for (r = start_row; r < end_row; r++) { if (!fmpz_poly_is_zero(fmpz_poly_mat_entry(mat, r, c))) return r; } return -1; } flint-3.1.3/src/fmpz_poly_mat/find_pivot_partial.c000066400000000000000000000026511461254215100223270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" slong fmpz_poly_mat_find_pivot_partial(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c) { slong best_row, best_length, best_bits, i; best_row = start_row; best_length = fmpz_poly_length(fmpz_poly_mat_entry(mat, start_row, c)); best_bits = fmpz_poly_max_bits(fmpz_poly_mat_entry(mat, start_row, c)); best_bits = FLINT_ABS(best_bits); for (i = start_row + 1; i < end_row; i++) { slong b, l; l = fmpz_poly_length(fmpz_poly_mat_entry(mat, i, c)); if (l != 0 && (best_length == 0 || l <= best_length)) { b = fmpz_poly_max_bits(fmpz_poly_mat_entry(mat, i, c)); b = FLINT_ABS(b); if (best_length == 0 || l < best_length || b < best_bits) { best_row = i; best_length = l; best_bits = b; } } } if (best_length == 0) return -1; return best_row; } flint-3.1.3/src/fmpz_poly_mat/init.c000066400000000000000000000024651461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_init(fmpz_poly_mat_t A, slong rows, slong cols) { slong i; if (rows != 0) A->rows = (fmpz_poly_struct **) flint_malloc(rows * sizeof(fmpz_poly_struct *)); else A->rows = NULL; if (rows != 0 && cols != 0) { A->entries = (fmpz_poly_struct *) flint_malloc(flint_mul_sizes(rows, cols) * sizeof(fmpz_poly_struct)); for (i = 0; i < rows * cols; i++) fmpz_poly_init(A->entries + i); for (i = 0; i < rows; i++) A->rows[i] = A->entries + i * cols; } else { A->entries = NULL; if (rows != 0) { for (i = 0; i < rows; i++) A->rows[i] = NULL; } } A->r = rows; A->c = cols; } void fmpz_poly_mat_init_set(fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { fmpz_poly_mat_init(A, B->r, B->c); fmpz_poly_mat_set(A, B); } flint-3.1.3/src/fmpz_poly_mat/inlines.c000066400000000000000000000007111461254215100201060ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_MAT_INLINES_C #include "flint.h" #include "fmpz_poly_mat.h" flint-3.1.3/src/fmpz_poly_mat/inv.c000066400000000000000000000043101461254215100172400ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "perm.h" #define E fmpz_poly_mat_entry int fmpz_poly_mat_inv(fmpz_poly_mat_t Ainv, fmpz_poly_t den, const fmpz_poly_mat_t A) { slong n = fmpz_poly_mat_nrows(A); if (n == 0) { fmpz_poly_one(den); return 1; } else if (n == 1) { fmpz_poly_set(den, E(A, 0, 0)); fmpz_poly_one(E(Ainv, 0, 0)); return !fmpz_poly_is_zero(den); } else if (n == 2) { fmpz_poly_mat_det(den, A); if (fmpz_poly_is_zero(den)) { return 0; } else if (Ainv == A) { fmpz_poly_swap(E(A, 0, 0), E(A, 1, 1)); fmpz_poly_neg(E(A, 0, 1), E(A, 0, 1)); fmpz_poly_neg(E(A, 1, 0), E(A, 1, 0)); return 1; } else { fmpz_poly_set(E(Ainv, 0, 0), E(A, 1, 1)); fmpz_poly_set(E(Ainv, 1, 1), E(A, 0, 0)); fmpz_poly_neg(E(Ainv, 0, 1), E(A, 0, 1)); fmpz_poly_neg(E(Ainv, 1, 0), E(A, 1, 0)); return 1; } } else { fmpz_poly_mat_t LU, I; slong * perm; int result; perm = _perm_init(n); fmpz_poly_mat_init_set(LU, A); result = (fmpz_poly_mat_fflu(LU, den, perm, LU, 1) == n); if (result) { fmpz_poly_mat_init(I, n, n); fmpz_poly_mat_one(I); fmpz_poly_mat_solve_fflu_precomp(Ainv, perm, LU, I); fmpz_poly_mat_clear(I); } else fmpz_poly_zero(den); if (_perm_parity(perm, n)) { fmpz_poly_mat_neg(Ainv, Ainv); fmpz_poly_neg(den, den); } _perm_clear(perm); fmpz_poly_mat_clear(LU); return result; } } flint-3.1.3/src/fmpz_poly_mat/is_one.c000066400000000000000000000017301461254215100177230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int fmpz_poly_mat_is_one(const fmpz_poly_mat_t A) { slong i, j; if (A->r == 0 || A->c == 0) return 1; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (i == j) { if (!fmpz_poly_is_one(fmpz_poly_mat_entry(A, i, j))) return 0; } else { if (!fmpz_poly_is_zero(fmpz_poly_mat_entry(A, i, j))) return 0; } } } return 1; } flint-3.1.3/src/fmpz_poly_mat/is_zero.c000066400000000000000000000013551461254215100201240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int fmpz_poly_mat_is_zero(const fmpz_poly_mat_t A) { slong i, j; if (A->r == 0 || A->c == 0) return 1; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) if (!fmpz_poly_is_zero(fmpz_poly_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/fmpz_poly_mat/max_bits.c000066400000000000000000000017061461254215100202600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" slong fmpz_poly_mat_max_bits(const fmpz_poly_mat_t A) { slong i, j, bits, max; int sign; max = 0; sign = 0; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { bits = fmpz_poly_max_bits(fmpz_poly_mat_entry(A, i, j)); if (bits < 0) { sign = 1; max = FLINT_MAX(max, -bits); } else max = FLINT_MAX(max, bits); } } return sign ? -max : max; } flint-3.1.3/src/fmpz_poly_mat/max_length.c000066400000000000000000000014061461254215100205750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" slong fmpz_poly_mat_max_length(const fmpz_poly_mat_t A) { slong i, j, len, max; max = 0; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { len = fmpz_poly_length(fmpz_poly_mat_entry(A, i, j)); max = FLINT_MAX(len, max); } } return max; } flint-3.1.3/src/fmpz_poly_mat/mul.c000066400000000000000000000013111461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_mul(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { if (A->r < 8 || B->r < 8 || B->c < 8) { fmpz_poly_mat_mul_classical(C, A, B); } else { fmpz_poly_mat_mul_KS(C, A, B); } } flint-3.1.3/src/fmpz_poly_mat/mul_KS.c000066400000000000000000000043451461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "fmpz_mat.h" void fmpz_poly_mat_mul_KS(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { slong i, j; slong A_len, B_len; int signs; slong A_bits, B_bits, bit_size; fmpz_mat_t AA, BB, CC; if (B->r == 0) { fmpz_poly_mat_zero(C); return; } A_len = fmpz_poly_mat_max_length(A); B_len = fmpz_poly_mat_max_length(B); A_bits = fmpz_poly_mat_max_bits(A); B_bits = fmpz_poly_mat_max_bits(B); signs = (A_bits < 0 || B_bits < 0); bit_size = FLINT_ABS(A_bits) + FLINT_ABS(B_bits) + signs; bit_size += FLINT_BIT_COUNT(FLINT_MIN(A_len, B_len)); bit_size += FLINT_BIT_COUNT(B->r); /* flint_printf("A: BITS %wd LEN %wd\n", A_bits, A_len); flint_printf("B: BITS %wd LEN %wd\n", B_bits, B_len); flint_printf("bit_size: %wd\n", bit_size); */ fmpz_mat_init(AA, A->r, A->c); fmpz_mat_init(BB, B->r, B->c); fmpz_mat_init(CC, C->r, C->c); for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_bit_pack(fmpz_mat_entry(AA, i, j), fmpz_poly_mat_entry(A, i, j), bit_size); for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) fmpz_poly_bit_pack(fmpz_mat_entry(BB, i, j), fmpz_poly_mat_entry(B, i, j), bit_size); fmpz_mat_mul(CC, AA, BB); for (i = 0; i < C->r; i++) for (j = 0; j < C->c; j++) if (signs) fmpz_poly_bit_unpack(fmpz_poly_mat_entry(C, i, j), fmpz_mat_entry(CC, i, j), bit_size); else fmpz_poly_bit_unpack_unsigned(fmpz_poly_mat_entry(C, i, j), fmpz_mat_entry(CC, i, j), bit_size); fmpz_mat_clear(AA); fmpz_mat_clear(BB); fmpz_mat_clear(CC); } flint-3.1.3/src/fmpz_poly_mat/mul_classical.c000066400000000000000000000031241461254215100212610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_mul_classical(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { slong ar, bc, br; slong i, j, k; fmpz_poly_t t; ar = A->r; br = B->r; bc = B->c; if (br == 0) { fmpz_poly_mat_zero(C); return; } if (C == A || C == B) { fmpz_poly_mat_t T; fmpz_poly_mat_init(T, ar, bc); fmpz_poly_mat_mul_classical(T, A, B); fmpz_poly_mat_swap_entrywise(C, T); fmpz_poly_mat_clear(T); return; } fmpz_poly_init(t); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { fmpz_poly_mul(fmpz_poly_mat_entry(C, i, j), fmpz_poly_mat_entry(A, i, 0), fmpz_poly_mat_entry(B, 0, j)); for (k = 1; k < br; k++) { fmpz_poly_mul(t, fmpz_poly_mat_entry(A, i, k), fmpz_poly_mat_entry(B, k, j)); fmpz_poly_add(fmpz_poly_mat_entry(C, i, j), fmpz_poly_mat_entry(C, i, j), t); } } } fmpz_poly_clear(t); } flint-3.1.3/src/fmpz_poly_mat/mullow.c000066400000000000000000000031721461254215100177700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_mullow(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B, slong len) { slong ar, bc, br; slong i, j, k; fmpz_poly_t t; ar = A->r; br = B->r; bc = B->c; if (br == 0 || len < 1) { fmpz_poly_mat_zero(C); return; } if (C == A || C == B) { fmpz_poly_mat_t T; fmpz_poly_mat_init(T, ar, bc); fmpz_poly_mat_mullow(T, A, B, len); fmpz_poly_mat_swap_entrywise(C, T); fmpz_poly_mat_clear(T); return; } fmpz_poly_init(t); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { fmpz_poly_mullow(fmpz_poly_mat_entry(C, i, j), fmpz_poly_mat_entry(A, i, 0), fmpz_poly_mat_entry(B, 0, j), len); for (k = 1; k < br; k++) { fmpz_poly_mullow(t, fmpz_poly_mat_entry(A, i, k), fmpz_poly_mat_entry(B, k, j), len); fmpz_poly_add(fmpz_poly_mat_entry(C, i, j), fmpz_poly_mat_entry(C, i, j), t); } } } fmpz_poly_clear(t); } flint-3.1.3/src/fmpz_poly_mat/neg.c000066400000000000000000000013201461254215100172130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_neg(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_neg(fmpz_poly_mat_entry(B, i, j), fmpz_poly_mat_entry(A, i, j)); } flint-3.1.3/src/fmpz_poly_mat/nullspace.c000066400000000000000000000036631461254215100204440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" slong fmpz_poly_mat_nullspace(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat) { slong i, j, k, n, rank, nullity; slong * pivots; slong * nonpivots; fmpz_poly_mat_t tmp; fmpz_poly_t den; n = mat->c; fmpz_poly_init(den); fmpz_poly_mat_init_set(tmp, mat); rank = fmpz_poly_mat_rref(tmp, den, tmp); nullity = n - rank; fmpz_poly_mat_zero(res); if (rank == 0) { for (i = 0; i < nullity; i++) fmpz_poly_set_ui(res->rows[i] + i, UWORD(1)); } else if (nullity) { pivots = flint_malloc(rank * sizeof(slong)); nonpivots = flint_malloc(nullity * sizeof(slong)); for (i = j = k = 0; i < rank; i++) { while (fmpz_poly_is_zero(tmp->rows[i] + j)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } fmpz_poly_set(den, tmp->rows[0] + pivots[0]); for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) fmpz_poly_set(res->rows[pivots[j]] + i, tmp->rows[j] + nonpivots[i]); fmpz_poly_neg(res->rows[nonpivots[i]] + i, den); } flint_free(pivots); flint_free(nonpivots); } fmpz_poly_clear(den); fmpz_poly_mat_clear(tmp); return nullity; } flint-3.1.3/src/fmpz_poly_mat/one.c000066400000000000000000000012201461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_one(fmpz_poly_mat_t A) { slong i, n; fmpz_poly_mat_zero(A); n = FLINT_MIN(A->r, A->c); for (i = 0; i < n; i++) fmpz_poly_one(fmpz_poly_mat_entry(A, i, i)); } flint-3.1.3/src/fmpz_poly_mat/pow.c000066400000000000000000000026321461254215100172560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_pow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp) { slong d = fmpz_poly_mat_nrows(A); if (exp == 0 || d == 0) { fmpz_poly_mat_one(B); } else if (exp == 1) { fmpz_poly_mat_set(B, A); } else if (exp == 2) { fmpz_poly_mat_sqr(B, A); } else if (d == 1) { fmpz_poly_pow(fmpz_poly_mat_entry(B, 0, 0), fmpz_poly_mat_entry(A, 0, 0), exp); } else { fmpz_poly_mat_t T, U; slong i; fmpz_poly_mat_init_set(T, A); fmpz_poly_mat_init(U, d, d); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { fmpz_poly_mat_sqr(U, T); if (exp & (WORD(1) << i)) fmpz_poly_mat_mul(T, U, A); else fmpz_poly_mat_swap(T, U); } fmpz_poly_mat_swap(B, T); fmpz_poly_mat_clear(T); fmpz_poly_mat_clear(U); } } flint-3.1.3/src/fmpz_poly_mat/pow_trunc.c000066400000000000000000000031731461254215100204720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_pow_trunc(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp, slong len) { slong d = fmpz_poly_mat_nrows(A); if (len < 1) { fmpz_poly_mat_zero(B); } else if (exp == 0 || d == 0) { fmpz_poly_mat_one(B); } else if (exp == 1) { fmpz_poly_mat_set(B, A); fmpz_poly_mat_truncate(B, len); } else if (exp == 2) { fmpz_poly_mat_sqrlow(B, A, len); } else if (d == 1) { fmpz_poly_pow_trunc(fmpz_poly_mat_entry(B, 0, 0), fmpz_poly_mat_entry(A, 0, 0), exp, len); } else { fmpz_poly_mat_t T, U; slong i; fmpz_poly_mat_init_set(T, A); fmpz_poly_mat_truncate(T, len); fmpz_poly_mat_init(U, d, d); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { fmpz_poly_mat_sqrlow(U, T, len); if (exp & (WORD(1) << i)) fmpz_poly_mat_mullow(T, U, A, len); else fmpz_poly_mat_swap(T, U); } fmpz_poly_mat_swap(B, T); fmpz_poly_mat_clear(T); fmpz_poly_mat_clear(U); } } flint-3.1.3/src/fmpz_poly_mat/print.c000066400000000000000000000016321461254215100176040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_print(const fmpz_poly_mat_t A, const char * x) { slong i, j; flint_printf("<%wd x %wd matrix over Z[%s]>\n", A->r, A->c, x); for (i = 0; i < A->r; i++) { flint_printf("["); for (j = 0; j < A->c; j++) { fmpz_poly_print_pretty(fmpz_poly_mat_entry(A, i, j), x); if (j + 1 < A->c) flint_printf(", "); } flint_printf("]\n"); } flint_printf("\n"); } flint-3.1.3/src/fmpz_poly_mat/prod.c000066400000000000000000000025631461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" static void binary_splitting(fmpz_poly_mat_t P, fmpz_poly_mat_t * const factors, slong n1, slong n2) { if (n2 - n1 <= 0) { fmpz_poly_mat_one(P); } else if (n2 - n1 == 1) { fmpz_poly_mat_set(P, factors[n1]); } else if (n2 - n1 == 2) { fmpz_poly_mat_mul(P, factors[n1], factors[n1 + 1]); } else { fmpz_poly_mat_t P1, P2; slong m = (n1 + n2) / 2; fmpz_poly_mat_init(P1, P->r, P->c); fmpz_poly_mat_init(P2, P->r, P->c); binary_splitting(P1, factors, n1, m); binary_splitting(P2, factors, m, n2); fmpz_poly_mat_mul(P, P1, P2); fmpz_poly_mat_clear(P1); fmpz_poly_mat_clear(P2); } } void fmpz_poly_mat_prod(fmpz_poly_mat_t res, fmpz_poly_mat_t * const factors, slong n) { binary_splitting(res, factors, 0, n); } flint-3.1.3/src/fmpz_poly_mat/rand.c000066400000000000000000000031271461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_randtest(fmpz_poly_mat_t A, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_randtest(fmpz_poly_mat_entry(A, i, j), state, len, bits); } void fmpz_poly_mat_randtest_sparse(fmpz_poly_mat_t A, flint_rand_t state, slong len, flint_bitcnt_t bits, float density) { slong i, j; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (n_randint(state, 1000) < density * 1000) { slong l = n_randint(state, len + 1); l = FLINT_MAX(l, 1); fmpz_poly_randtest_not_zero(fmpz_poly_mat_entry(A, i, j), state, l, bits); } else { fmpz_poly_zero(fmpz_poly_mat_entry(A, i, j)); } } } } void fmpz_poly_mat_randtest_unsigned(fmpz_poly_mat_t A, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_randtest_unsigned(fmpz_poly_mat_entry(A, i, j), state, len, bits); } flint-3.1.3/src/fmpz_poly_mat/rank.c000066400000000000000000000015001461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" slong fmpz_poly_mat_rank(const fmpz_poly_mat_t A) { fmpz_poly_mat_t tmp; fmpz_poly_t den; slong rank; if (fmpz_poly_mat_is_empty(A)) return 0; fmpz_poly_mat_init_set(tmp, A); fmpz_poly_init(den); rank = fmpz_poly_mat_fflu(tmp, den, NULL, tmp, 0); fmpz_poly_mat_clear(tmp); fmpz_poly_clear(den); return rank; } flint-3.1.3/src/fmpz_poly_mat/rref.c000066400000000000000000000051551461254215100174120ustar00rootroot00000000000000/* Copyright (C) 2011-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" slong fmpz_poly_mat_rref(fmpz_poly_mat_t R, fmpz_poly_t den, const fmpz_poly_mat_t A) { slong i, j, k, m, n, rank; slong *pivots, *nonpivots; rank = fmpz_poly_mat_fflu(R, den, NULL, A, 0); m = fmpz_poly_mat_nrows(R); n = fmpz_poly_mat_ncols(R); /* clear bottom */ for (i = rank; i < m; i++) for (j = 0; j < n; j++) fmpz_poly_zero(fmpz_poly_mat_entry(R, i, j)); /* Convert row echelon form to reduced row echelon form */ if (rank > 1) { fmpz_poly_t tmp, tmp2; fmpz_poly_init(tmp); fmpz_poly_init(tmp2); pivots = flint_malloc(sizeof(slong) * n); nonpivots = pivots + rank; /* find pivot positions */ for (i = j = k = 0; i < rank; i++) { while (fmpz_poly_is_zero(fmpz_poly_mat_entry(R, i, j))) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (k = 0; k < n - rank; k++) { for (i = rank - 2; i >= 0; i--) { fmpz_poly_mul(tmp, den, fmpz_poly_mat_entry(R, i, nonpivots[k])); for (j = i + 1; j < rank; j++) { fmpz_poly_mul(tmp2, fmpz_poly_mat_entry(R, i, pivots[j]), fmpz_poly_mat_entry(R, j, nonpivots[k])); fmpz_poly_sub(tmp, tmp, tmp2); } fmpz_poly_divexact(fmpz_poly_mat_entry(R, i, nonpivots[k]), tmp, fmpz_poly_mat_entry(R, i, pivots[i])); } } /* clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { if (i == j) fmpz_poly_set(fmpz_poly_mat_entry(R, j, pivots[i]), den); else fmpz_poly_zero(fmpz_poly_mat_entry(R, j, pivots[i])); } } flint_free(pivots); fmpz_poly_clear(tmp); fmpz_poly_clear(tmp2); } return rank; } flint-3.1.3/src/fmpz_poly_mat/scalar.c000066400000000000000000000023351461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_scalar_mul_fmpz(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_t c) { slong i, j; for (i = 0; i < fmpz_poly_mat_nrows(B); i++) for (j = 0; j < fmpz_poly_mat_ncols(B); j++) fmpz_poly_scalar_mul_fmpz(fmpz_poly_mat_entry(B, i, j), fmpz_poly_mat_entry(A, i, j), c); } void fmpz_poly_mat_scalar_mul_fmpz_poly(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_poly_t c) { slong i, j; for (i = 0; i < fmpz_poly_mat_nrows(B); i++) for (j = 0; j < fmpz_poly_mat_ncols(B); j++) fmpz_poly_mul(fmpz_poly_mat_entry(B, i, j), fmpz_poly_mat_entry(A, i, j), c); } flint-3.1.3/src/fmpz_poly_mat/set.c000066400000000000000000000014001461254215100172340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_set(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) { if (A != B) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_set(fmpz_poly_mat_entry(B, i, j), fmpz_poly_mat_entry(A, i, j)); } } flint-3.1.3/src/fmpz_poly_mat/solve.c000066400000000000000000000012421461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "perm.h" int fmpz_poly_mat_solve(fmpz_poly_mat_t X, fmpz_poly_t den, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { return fmpz_poly_mat_solve_fflu(X, den, A, B); } flint-3.1.3/src/fmpz_poly_mat/solve_fflu.c000066400000000000000000000023521461254215100206140ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "perm.h" int fmpz_poly_mat_solve_fflu(fmpz_poly_mat_t X, fmpz_poly_t den, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { fmpz_poly_mat_t LU; slong dim, *perm; int result; if (fmpz_poly_mat_is_empty(B)) { fmpz_poly_one(den); return 1; } dim = fmpz_poly_mat_nrows(A); perm = _perm_init(dim); fmpz_poly_mat_init_set(LU, A); result = (fmpz_poly_mat_fflu(LU, den, perm, LU, 1) == dim); if (result) { fmpz_poly_mat_solve_fflu_precomp(X, perm, LU, B); if (_perm_parity(perm, dim)) { fmpz_poly_neg(den, den); fmpz_poly_mat_neg(X, X); } } else fmpz_poly_zero(den); _perm_clear(perm); fmpz_poly_mat_clear(LU); return result; } flint-3.1.3/src/fmpz_poly_mat/solve_fflu_precomp.c000066400000000000000000000046171461254215100223470ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "perm.h" #define XX(ii,jj) fmpz_poly_mat_entry(X,(ii),(jj)) #define BB(ii,jj) fmpz_poly_mat_entry(B,(ii),(jj)) #define LU(ii,jj) fmpz_poly_mat_entry(FFLU,(ii),(jj)) void fmpz_poly_mat_set_perm(fmpz_poly_mat_t X, const slong * perm, const fmpz_poly_mat_t B) { if (X == B) { flint_throw(FLINT_ERROR, "(%s): Not implemented\n", __func__); } else { slong i, j; if (perm == NULL) flint_throw(FLINT_ERROR, "(%s): perm == NULL\n", __func__); for (i = 0; i < fmpz_poly_mat_nrows(B); i++) for (j = 0; j < fmpz_poly_mat_ncols(B); j++) fmpz_poly_set(fmpz_poly_mat_entry(X, i, j), fmpz_poly_mat_entry(B, perm[i], j)); } } void fmpz_poly_mat_solve_fflu_precomp(fmpz_poly_mat_t X, const slong * perm, const fmpz_poly_mat_t FFLU, const fmpz_poly_mat_t B) { fmpz_poly_t T; slong i, j, k, m, n; n = X->r; m = X->c; fmpz_poly_init(T); fmpz_poly_mat_set_perm(X, perm, B); for (k = 0; k < m; k++) { /* Fraction-free forward substitution */ for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { fmpz_poly_mul(XX(j, k), XX(j, k), LU(i, i)); fmpz_poly_mul(T, LU(j, i), XX(i, k)); fmpz_poly_sub(XX(j, k), XX(j, k), T); if (i > 0) fmpz_poly_divexact(XX(j, k), XX(j, k), LU(i-1, i-1)); } } /* Fraction-free back substitution */ for (i = n - 2; i >= 0; i--) { fmpz_poly_mul(XX(i, k), XX(i, k), LU(n-1, n-1)); for (j = i + 1; j < n; j++) { fmpz_poly_mul(T, XX(j, k), LU(i, j)); fmpz_poly_sub(XX(i, k), XX(i, k), T); } fmpz_poly_divexact(XX(i, k), XX(i, k), LU(i, i)); } } fmpz_poly_clear(T); } flint-3.1.3/src/fmpz_poly_mat/sqr.c000066400000000000000000000011661461254215100172570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_sqr(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) { if (A->r < 8) fmpz_poly_mat_sqr_classical(B, A); else fmpz_poly_mat_sqr_KS(B, A); } flint-3.1.3/src/fmpz_poly_mat/sqr_KS.c000066400000000000000000000031671461254215100176570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "fmpz_mat.h" void fmpz_poly_mat_sqr_KS(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) { fmpz_mat_t AA, BB; slong i, j, n; slong A_len; int signs; slong A_bits, bit_size; n = A->r; if (n == 0) { fmpz_poly_mat_zero(B); return; } A_len = fmpz_poly_mat_max_length(A); A_bits = fmpz_poly_mat_max_bits(A); signs = A_bits < 0; bit_size = 2 * FLINT_ABS(A_bits) + signs; bit_size += FLINT_BIT_COUNT(A_len); bit_size += FLINT_BIT_COUNT(n); fmpz_mat_init(AA, n, n); fmpz_mat_init(BB, n, n); for (i = 0; i < n; i++) for (j = 0; j < n; j++) fmpz_poly_bit_pack(fmpz_mat_entry(AA, i, j), fmpz_poly_mat_entry(A, i, j), bit_size); fmpz_mat_sqr(BB, AA); for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (signs) fmpz_poly_bit_unpack(fmpz_poly_mat_entry(B, i, j), fmpz_mat_entry(BB, i, j), bit_size); else fmpz_poly_bit_unpack_unsigned(fmpz_poly_mat_entry(B, i, j), fmpz_mat_entry(BB, i, j), bit_size); fmpz_mat_clear(AA); fmpz_mat_clear(BB); } flint-3.1.3/src/fmpz_poly_mat/sqr_classical.c000066400000000000000000000024661461254215100213010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #define E fmpz_poly_mat_entry void fmpz_poly_mat_sqr_classical(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) { slong n = A->r; if (n == 0) return; if (n == 1) { fmpz_poly_sqr(E(B, 0, 0), E(A, 0, 0)); return; } if (n == 2) { fmpz_poly_t t, u; fmpz_poly_init(t); fmpz_poly_init(u); fmpz_poly_add(t, E(A, 0, 0), E(A, 1, 1)); fmpz_poly_mul(u, E(A, 0, 1), E(A, 1, 0)); fmpz_poly_sqr(E(B, 0, 0), E(A, 0, 0)); fmpz_poly_add(E(B, 0, 0), E(B, 0, 0), u); fmpz_poly_sqr(E(B, 1, 1), E(A, 1, 1)); fmpz_poly_add(E(B, 1, 1), E(B, 1, 1), u); fmpz_poly_mul(E(B, 0, 1), E(A, 0, 1), t); fmpz_poly_mul(E(B, 1, 0), E(A, 1, 0), t); fmpz_poly_clear(t); fmpz_poly_clear(u); return; } fmpz_poly_mat_mul_classical(B, A, A); } flint-3.1.3/src/fmpz_poly_mat/sqrlow.c000066400000000000000000000031721461254215100200000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #define E fmpz_poly_mat_entry static inline void fmpz_poly_addlow(fmpz_poly_t c, const fmpz_poly_t a, const fmpz_poly_t b, slong len) { fmpz_poly_add(c, a, b); fmpz_poly_truncate(c, len); } void fmpz_poly_mat_sqrlow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, slong len) { slong n = A->r; if (n == 0) return; if (len < 1) { fmpz_poly_mat_zero(B); return; } if (n == 1) { fmpz_poly_sqrlow(E(B, 0, 0), E(A, 0, 0), len); return; } if (n == 2) { fmpz_poly_t t, u; fmpz_poly_init(t); fmpz_poly_init(u); fmpz_poly_addlow(t, E(A, 0, 0), E(A, 1, 1), len); fmpz_poly_mullow(u, E(A, 0, 1), E(A, 1, 0), len); fmpz_poly_sqrlow(E(B, 0, 0), E(A, 0, 0), len); fmpz_poly_addlow(E(B, 0, 0), E(B, 0, 0), u, len); fmpz_poly_sqrlow(E(B, 1, 1), E(A, 1, 1), len); fmpz_poly_addlow(E(B, 1, 1), E(B, 1, 1), u, len); fmpz_poly_mullow(E(B, 0, 1), E(A, 0, 1), t, len); fmpz_poly_mullow(E(B, 1, 0), E(A, 1, 0), t, len); fmpz_poly_clear(t); fmpz_poly_clear(u); return; } fmpz_poly_mat_mullow(B, A, A, len); } flint-3.1.3/src/fmpz_poly_mat/sub.c000066400000000000000000000014711461254215100172420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_sub(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_sub(fmpz_poly_mat_entry(C, i, j), fmpz_poly_mat_entry(A, i, j), fmpz_poly_mat_entry(B, i, j)); } flint-3.1.3/src/fmpz_poly_mat/swap.c000066400000000000000000000010651461254215100174220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_swap(fmpz_poly_mat_t A, fmpz_poly_mat_t B) { FLINT_SWAP(fmpz_poly_mat_struct, *A, *B); } flint-3.1.3/src/fmpz_poly_mat/test/000077500000000000000000000000001461254215100172615ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly_mat/test/main.c000066400000000000000000000045171461254215100203600ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-det.c" #include "t-det_interpolate.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-mul.c" #include "t-mul_KS.c" #include "t-mullow.c" #include "t-neg.c" #include "t-nullspace.c" #include "t-one.c" #include "t-pow.c" #include "t-pow_trunc.c" #include "t-prod.c" #include "t-rank.c" #include "t-rref.c" #include "t-solve_fflu.c" #include "t-sqr.c" #include "t-sqr_KS.c" #include "t-sqrlow.c" #include "t-sub.c" #include "t-trace.c" #include "t-window_init_clear.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_poly_mat_add), TEST_FUNCTION(fmpz_poly_mat_concat_horizontal), TEST_FUNCTION(fmpz_poly_mat_concat_vertical), TEST_FUNCTION(fmpz_poly_mat_det), TEST_FUNCTION(fmpz_poly_mat_det_interpolate), TEST_FUNCTION(fmpz_poly_mat_init_clear), TEST_FUNCTION(fmpz_poly_mat_inv), TEST_FUNCTION(fmpz_poly_mat_mul), TEST_FUNCTION(fmpz_poly_mat_mul_KS), TEST_FUNCTION(fmpz_poly_mat_mullow), TEST_FUNCTION(fmpz_poly_mat_neg), TEST_FUNCTION(fmpz_poly_mat_nullspace), TEST_FUNCTION(fmpz_poly_mat_one), TEST_FUNCTION(fmpz_poly_mat_pow), TEST_FUNCTION(fmpz_poly_mat_pow_trunc), TEST_FUNCTION(fmpz_poly_mat_prod), TEST_FUNCTION(fmpz_poly_mat_rank), TEST_FUNCTION(fmpz_poly_mat_rref), TEST_FUNCTION(fmpz_poly_mat_solve_fflu), TEST_FUNCTION(fmpz_poly_mat_sqr), TEST_FUNCTION(fmpz_poly_mat_sqr_KS), TEST_FUNCTION(fmpz_poly_mat_sqrlow), TEST_FUNCTION(fmpz_poly_mat_sub), TEST_FUNCTION(fmpz_poly_mat_trace), TEST_FUNCTION(fmpz_poly_mat_window_init_clear), TEST_FUNCTION(fmpz_poly_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_poly_mat/test/t-add.c000066400000000000000000000105411461254215100204170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_add, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; fmpz_mat_t a, b, c, d; fmpz_t x; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_mat_init(a, m, n); fmpz_mat_init(b, m, n); fmpz_mat_init(c, m, n); fmpz_mat_init(d, m, n); fmpz_init(x); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_add(C, A, B); fmpz_randtest(x, state, 1 + n_randint(state, 100)); fmpz_poly_mat_evaluate_fmpz(a, A, x); fmpz_poly_mat_evaluate_fmpz(b, B, x); fmpz_poly_mat_evaluate_fmpz(d, C, x); fmpz_mat_add(c, a, b); if (!fmpz_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); fmpz_mat_clear(a); fmpz_mat_clear(b); fmpz_mat_clear(c); fmpz_mat_clear(d); fmpz_clear(x); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_add(C, A, B); fmpz_poly_mat_add(A, A, B); if (!fmpz_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_add(C, A, B); fmpz_poly_mat_add(B, A, B); if (!fmpz_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-concat_horizontal.c000066400000000000000000000034531461254215100234130ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_concat_horizontal, state) { fmpz_poly_mat_t A, B, C; fmpz_poly_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong c1, c2, r1, bits; c1 = n_randint(state, 10); c2 = n_randint(state, 10); r1 = n_randint(state, 10); bits = 1 + n_randint(state, 20); fmpz_poly_mat_init(A, r1, c1); fmpz_poly_mat_init(B, r1, c2); fmpz_poly_mat_init(C, r1, (c1 + c2)); fmpz_poly_mat_randtest(A, state, n_randint(state, 10) + 1, bits); fmpz_poly_mat_randtest(B, state, n_randint(state, 10) + 1, bits); fmpz_poly_mat_randtest(C, state, n_randint(state, 10) + 1, bits); fmpz_poly_mat_concat_horizontal(C, A, B); fmpz_poly_mat_window_init(window1, C, 0, 0, r1, c1); fmpz_poly_mat_window_init(window2, C, 0, c1, r1, (c1 + c2)); if (!(fmpz_poly_mat_equal(window1, A) && fmpz_poly_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); fmpz_poly_mat_window_clear(window1); fmpz_poly_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-concat_vertical.c000066400000000000000000000034471461254215100230360ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_concat_vertical, state) { fmpz_poly_mat_t A, B, C; fmpz_poly_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong r1, r2, c1, bits; r1 = n_randint(state, 10); r2 = n_randint(state, 10); c1 = n_randint(state, 10); bits = 1 + n_randint(state, 20); fmpz_poly_mat_init(A, r1, c1); fmpz_poly_mat_init(B, r2, c1); fmpz_poly_mat_init(C, (r1 + r2), c1); fmpz_poly_mat_randtest(A, state, n_randint(state, 10) + 1, bits); fmpz_poly_mat_randtest(B, state, n_randint(state, 10) + 1, bits); fmpz_poly_mat_randtest(C, state, n_randint(state, 10) + 1, bits); fmpz_poly_mat_concat_vertical(C, A, B); fmpz_poly_mat_window_init(window1, C, 0, 0, r1, c1); fmpz_poly_mat_window_init(window2, C, r1, 0, (r1 + r2), c1); if (!(fmpz_poly_mat_equal(window1, A) && fmpz_poly_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); fmpz_poly_mat_window_clear(window1); fmpz_poly_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-det.c000066400000000000000000000046271461254215100204530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_det, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; fmpz_poly_t a, b, ab, c; slong n, bits, deg; float density; n = n_randint(state, 10); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(C, n, n); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(ab); fmpz_poly_init(c); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); fmpz_poly_mat_randtest_sparse(B, state, deg, bits, density); fmpz_poly_mat_mul(C, A, B); fmpz_poly_mat_det(a, A); fmpz_poly_mat_det(b, B); fmpz_poly_mat_det(c, C); fmpz_poly_mul(ab, a, b); if (!fmpz_poly_equal(c, ab)) { flint_printf("FAIL:\n"); flint_printf("determinants don't agree!\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("det(A):\n"); fmpz_poly_print_pretty(a, "x"); flint_printf("\ndet(B):\n"); fmpz_poly_print_pretty(b, "x"); flint_printf("\ndet(C):\n"); fmpz_poly_print_pretty(c, "x"); flint_printf("\ndet(A)*det(B):\n"); fmpz_poly_print_pretty(ab, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(ab); fmpz_poly_clear(c); fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-det_interpolate.c000066400000000000000000000031221461254215100230460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_det_interpolate, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A; fmpz_poly_t a, b; slong n, bits, deg; n = n_randint(state, 10); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, n, n); fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_det(a, A); fmpz_poly_mat_det_interpolate(b, A); if (!fmpz_poly_equal(a, b)) { flint_printf("FAIL:\n"); flint_printf("determinants don't agree!\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("det(A):\n"); fmpz_poly_print_pretty(a, "x"); flint_printf("\ndet_interpolate(A):\n"); fmpz_poly_print_pretty(b, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-init_clear.c000066400000000000000000000017371461254215100220070ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_mat_t a; slong j, k; slong rows = n_randint(state, 100); slong cols = n_randint(state, 100); fmpz_poly_mat_init(a, rows, cols); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) fmpz_poly_zero(fmpz_poly_mat_entry(a, j, k)); fmpz_poly_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-inv.c000066400000000000000000000076611461254215100204740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_inv, state) { slong i; /* Test aliasing */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, Ainv; fmpz_poly_t den1, den2; slong n, bits, deg; float density; int ns1, ns2; int result; n = n_randint(state, 8); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(Ainv, n, n); fmpz_poly_init(den1); fmpz_poly_init(den2); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); ns1 = fmpz_poly_mat_inv(Ainv, den1, A); ns2 = fmpz_poly_mat_inv(A, den2, A); result = ns1 == ns2; if (result && ns1 != 0) { result = fmpz_poly_equal(den1, den2) && fmpz_poly_mat_equal(A, Ainv); } if (!result) { flint_printf("FAIL (aliasing)!\n"); fmpz_poly_mat_print(A, "x"); flint_printf("\n"); fmpz_poly_mat_print(Ainv, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(Ainv); fmpz_poly_clear(den1); fmpz_poly_clear(den2); } /* Check A^(-1) = A = 1 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, Ainv, B, Iden; fmpz_poly_t den, det; slong n, bits, deg; float density; int nonsingular; n = n_randint(state, 10); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(Ainv, n, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(Iden, n, n); fmpz_poly_init(den); fmpz_poly_init(det); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); nonsingular = fmpz_poly_mat_inv(Ainv, den, A); fmpz_poly_mat_det_interpolate(det, A); if (n == 0) { if (nonsingular == 0 || !fmpz_poly_is_one(den)) { flint_printf("FAIL: expected empty matrix to pass\n"); fflush(stdout); flint_abort(); } } else { if (!fmpz_poly_equal(den, det)) { fmpz_poly_neg(det, det); flint_printf("FAIL: den != det(A)\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_mul(B, Ainv, A); fmpz_poly_mat_one(Iden); fmpz_poly_mat_scalar_mul_fmpz_poly(Iden, Iden, den); if (!fmpz_poly_mat_equal(B, Iden)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("Ainv:\n"); fmpz_poly_mat_print(Ainv, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("den:\n"); fmpz_poly_print_pretty(den, "x"); fflush(stdout); flint_abort(); } } fmpz_poly_clear(den); fmpz_poly_clear(det); fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(Ainv); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(Iden); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-mul.c000066400000000000000000000111531461254215100204640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_mul, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; fmpz_mat_t a, b, c, d; fmpz_t x; slong m, n, k, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, n, k); fmpz_poly_mat_init(C, m, k); fmpz_mat_init(a, m, n); fmpz_mat_init(b, n, k); fmpz_mat_init(c, m, k); fmpz_mat_init(d, m, k); fmpz_init(x); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mul(C, A, B); fmpz_randtest(x, state, 1 + n_randint(state, 100)); fmpz_poly_mat_evaluate_fmpz(a, A, x); fmpz_poly_mat_evaluate_fmpz(b, B, x); fmpz_poly_mat_evaluate_fmpz(d, C, x); fmpz_mat_mul(c, a, b); if (!fmpz_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); fmpz_mat_clear(a); fmpz_mat_clear(b); fmpz_mat_clear(c); fmpz_mat_clear(d); fmpz_clear(x); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mul(C, A, B); fmpz_poly_mat_mul(A, A, B); if (!fmpz_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mul(C, A, B); fmpz_poly_mat_mul(B, A, B); if (!fmpz_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-mul_KS.c000066400000000000000000000107331461254215100210640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_mul_KS, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C, D; slong m, n, k, bits, deg; m = n_randint(state, 15); n = n_randint(state, 15); k = n_randint(state, 15); deg = 1 + n_randint(state, 15); bits = 1 + n_randint(state, 150); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, n, k); fmpz_poly_mat_init(C, m, k); fmpz_poly_mat_init(D, m, k); if (n_randint(state, 2)) fmpz_poly_mat_randtest(A, state, deg, bits); else fmpz_poly_mat_randtest_unsigned(A, state, deg, bits); if (n_randint(state, 2)) fmpz_poly_mat_randtest(B, state, deg, bits); else fmpz_poly_mat_randtest_unsigned(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mul_classical(C, A, B); fmpz_poly_mat_mul_KS(D, A, B); if (!fmpz_poly_mat_equal(C, D)) { flint_printf("FAIL:\n"); flint_printf("products don't agree!\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("D:\n"); fmpz_poly_mat_print(D, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); fmpz_poly_mat_clear(D); } /* Check aliasing C and A */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mul_KS(C, A, B); fmpz_poly_mat_mul_KS(A, A, B); if (!fmpz_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mul_KS(C, A, B); fmpz_poly_mat_mul_KS(B, A, B); if (!fmpz_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-mullow.c000066400000000000000000000107241461254215100212110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_mullow, state) { slong i; /* Compare with mul */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C, D; slong m, n, k, bits, deg, len; m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); len = n_randint(state, 10); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, n, k); fmpz_poly_mat_init(C, m, k); fmpz_poly_mat_init(D, m, k); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_randtest(D, state, deg, bits); /* noise in output */ fmpz_poly_mat_mullow(C, A, B, len); fmpz_poly_mat_mul(D, A, B); fmpz_poly_mat_truncate(D, len); if (!fmpz_poly_mat_equal(C, D)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("D:\n"); fmpz_poly_mat_print(D, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); fmpz_poly_mat_clear(D); } /* Check aliasing C and A */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg, len; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); len = n_randint(state, 10); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mullow(C, A, B, len); fmpz_poly_mat_mullow(A, A, B, len); if (!fmpz_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg, len; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); len = n_randint(state, 10); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_mullow(C, A, B, len); fmpz_poly_mat_mullow(B, A, B, len); if (!fmpz_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-neg.c000066400000000000000000000053751461254215100204510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_neg, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B; fmpz_mat_t a, b, c; fmpz_t x; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_mat_init(a, m, n); fmpz_mat_init(b, m, n); fmpz_mat_init(c, m, n); fmpz_init(x); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_neg(B, A); fmpz_randtest(x, state, 1 + n_randint(state, 100)); fmpz_poly_mat_evaluate_fmpz(a, A, x); fmpz_poly_mat_evaluate_fmpz(b, B, x); fmpz_mat_neg(c, a); if (!fmpz_mat_equal(b, c)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_mat_clear(a); fmpz_mat_clear(b); fmpz_mat_clear(c); fmpz_clear(x); } /* Check aliasing B and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_neg(B, A); fmpz_poly_mat_neg(A, A); if (!fmpz_poly_mat_equal(B, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-nullspace.c000066400000000000000000000040301461254215100216510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_nullspace, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, N, AN; slong n, m, bits, deg, rank, nullity; float density; m = n_randint(state, 13); n = n_randint(state, 13); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(N, n, n); fmpz_poly_mat_init(AN, m, n); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); rank = fmpz_poly_mat_rank(A); nullity = fmpz_poly_mat_nullspace(N, A); if (nullity + rank != n) { flint_printf("FAIL: wrong nullity!\n"); flint_printf("rank = %wd\n", rank); flint_printf("nullity = %wd\n", nullity); fmpz_poly_mat_print(A, "x"); flint_printf("\n"); fmpz_poly_mat_print(N, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } if (fmpz_poly_mat_rank(N) != nullity) { flint_printf("FAIL: wrong rank(N) != nullity!\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_mul(AN, A, N); if (!fmpz_poly_mat_is_zero(AN)) { flint_printf("FAIL: A * N != 0\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(N); fmpz_poly_mat_clear(AN); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-one.c000066400000000000000000000033461461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_one, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { fmpz_poly_mat_t A; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_randtest(A, state, n_randint(state, 5), n_randint(state, 100)); fmpz_poly_mat_one(A); if (!fmpz_poly_mat_is_one(A)) { flint_printf("FAIL: expected matrix to be one\n"); fflush(stdout); flint_abort(); } if (m > 0 && n > 0) { m = n_randint(state, m); n = n_randint(state, n); if (m != n) fmpz_poly_randtest_not_zero(fmpz_poly_mat_entry(A, m, n), state, 5, 5); else do { fmpz_poly_randtest_not_zero(fmpz_poly_mat_entry(A, m, n), state, 5, 5); } while (fmpz_poly_is_one(fmpz_poly_mat_entry(A, m, n))); if (fmpz_poly_mat_is_one(A)) { flint_printf("FAIL: expected matrix not to be one\n"); fflush(stdout); flint_abort(); } } fmpz_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-pow.c000066400000000000000000000051451461254215100205000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_pow, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, j, exp, bits, deg; m = n_randint(state, 6); deg = 1 + n_randint(state, 6); bits = 1 + n_randint(state, 100); exp = n_randint(state, 20); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, m); fmpz_poly_mat_init(C, m, m); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_pow(B, A, exp); fmpz_poly_mat_one(C); for (j = 0; j < exp; j++) fmpz_poly_mat_mul(C, C, A); if (!fmpz_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("exp = %wd\n", exp); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing B and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B; slong m, exp, bits, deg; m = n_randint(state, 6); deg = 1 + n_randint(state, 6); bits = 1 + n_randint(state, 100); exp = n_randint(state, 20); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, m); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_pow(B, A, exp); fmpz_poly_mat_pow(A, A, exp); if (!fmpz_poly_mat_equal(A, B)) { flint_printf("FAIL (aliasing)\n"); flint_printf("exp = %wd\n", exp); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-pow_trunc.c000066400000000000000000000054751461254215100217210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_pow_trunc, state) { slong i; /* Compare with pow */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong n, exp, bits, deg, len; n = n_randint(state, 10); exp = n_randint(state, 15); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); len = n_randint(state, 10); fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(C, n, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); /* noise in output */ fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_pow_trunc(B, A, exp, len); fmpz_poly_mat_pow(C, A, exp); fmpz_poly_mat_truncate(C, len); if (!fmpz_poly_mat_equal(B, C)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B; slong n, exp, bits, deg, len; n = n_randint(state, 10); exp = n_randint(state, 15); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); len = n_randint(state, 10); fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_pow_trunc(B, A, exp, len); fmpz_poly_mat_pow_trunc(A, A, exp, len); if (!fmpz_poly_mat_equal(B, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-prod.c000066400000000000000000000035231461254215100206350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_prod, state) { slong i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, *V; slong m, j, count, bits, deg; float density; m = n_randint(state, 6); deg = 1 + n_randint(state, 6); bits = 1 + n_randint(state, 100); count = n_randint(state, 20); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, m); V = flint_malloc(sizeof(fmpz_poly_mat_t) * count); for (j = 0; j < count; j++) { fmpz_poly_mat_init(V[j], m, m); fmpz_poly_mat_randtest_sparse(V[j], state, deg, bits, density); } fmpz_poly_mat_prod(A, V, count); fmpz_poly_mat_one(B); for (j = 0; j < count; j++) fmpz_poly_mat_mul(B, B, V[j]); if (!fmpz_poly_mat_equal(A, B)) { flint_printf("FAIL:\n"); flint_printf("count = %wd\n", count); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); for (j = 0; j < count; j++) fmpz_poly_mat_clear(V[j]); flint_free(V); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-rank.c000066400000000000000000000035051461254215100206240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_rank, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A; fmpz_mat_t Ax; fmpz_t x; slong j, m, n, bits, deg, rank, zrank; float density; m = n_randint(state, 15); n = n_randint(state, 15); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, m, n); fmpz_mat_init(Ax, m, n); fmpz_init(x); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); /* Probabilistic rank computation */ zrank = 0; for (j = 0; j < 5; j++) { slong r; fmpz_randbits(x, state, 15); fmpz_poly_mat_evaluate_fmpz(Ax, A, x); r = fmpz_mat_rank(Ax); zrank = FLINT_MAX(zrank, r); } rank = fmpz_poly_mat_rank(A); if (rank != zrank) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("Computed rank: %wd (zrank = %wd)\n", rank, zrank); fflush(stdout); flint_abort(); } fmpz_clear(x); fmpz_mat_clear(Ax); fmpz_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-rref.c000066400000000000000000000106741461254215100206340ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "fmpz_poly_mat.h" /* checks that the rref has the right form */ int check_rref(const fmpz_poly_mat_t A, const fmpz_poly_t den, slong rank) { slong i, j, k, prev_pivot; /* bottom should be zero */ for (i = rank; i < A->r; i++) for (j = 0; j < A->c; j++) if (!fmpz_poly_is_zero(fmpz_poly_mat_entry(A, i, j))) return 0; prev_pivot = -1; for (i = 0; i < rank; i++) { for (j = 0; j < A->c; j++) { if (!fmpz_poly_is_zero(fmpz_poly_mat_entry(A, i, j))) { /* pivot should have a higher column index than previous */ if (j <= prev_pivot) return 0; /* column should be 0 ... 0 1 0 ... 0 */ for (k = 0; k < rank; k++) { if (i == k && !fmpz_poly_equal(fmpz_poly_mat_entry(A, k, j), den)) return 0; if (i != k && !fmpz_poly_is_zero(fmpz_poly_mat_entry(A, k, j))) return 0; } prev_pivot = j; break; } } } return 1; } TEST_FUNCTION_START(fmpz_poly_mat_rref, state) { slong iter; for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { fmpz_poly_mat_t A, R, B, R2; fmpz_poly_t den, c, den2; slong j, k, m, n, deg, bits, rank1, rank2; slong *perm; float density; int equal; m = n_randint(state, 10); n = n_randint(state, 10); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(R, m, n); fmpz_poly_mat_init(B, 2 * m, n); fmpz_poly_mat_init(R2, 2 * m, n); fmpz_poly_init(c); fmpz_poly_init(den); fmpz_poly_init(den2); perm = _perm_init(2 * m); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); rank1 = fmpz_poly_mat_rref(R, den, A); check_rref(R, den, rank1); /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { fmpz_poly_randtest_not_zero(c, state, deg, bits); for (k = 0; k < n; k++) fmpz_poly_mul(fmpz_poly_mat_entry(B, perm[j], k), fmpz_poly_mat_entry(A, j, k), c); } for (j = 0; j < m; j++) { fmpz_poly_randtest_not_zero(c, state, deg, bits); for (k = 0; k < n; k++) fmpz_poly_mul(fmpz_poly_mat_entry(B, perm[m + j], k), fmpz_poly_mat_entry(R, j, k), c); } rank2 = fmpz_poly_mat_rref(R2, den2, B); equal = (rank1 == rank2); if (equal) { fmpz_poly_mat_scalar_mul_fmpz_poly(R, R, den2); fmpz_poly_mat_scalar_mul_fmpz_poly(R2, R2, den); for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_poly_equal(fmpz_poly_mat_entry(R, j, k), fmpz_poly_mat_entry(R2, j, k)); for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) equal = equal && fmpz_poly_is_zero(fmpz_poly_mat_entry(R2, j, k)); } if (!equal) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); fmpz_poly_mat_print(A, "x"); flint_printf("\n\n"); fmpz_poly_mat_print(R, "x"); flint_printf("\n\n"); fmpz_poly_mat_print(R2, "x"); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(c); fmpz_poly_clear(den); fmpz_poly_clear(den2); _perm_clear(perm); fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(R); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-solve_fflu.c000066400000000000000000000066301461254215100220370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_solve_fflu, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, X, B, AX, Bden; fmpz_poly_t den, det; slong n, m, bits, deg; float density; int solved; n = n_randint(state, 15); m = n_randint(state, 5); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(B, n, m); fmpz_poly_mat_init(X, n, m); fmpz_poly_mat_init(AX, n, m); fmpz_poly_mat_init(Bden, n, m); fmpz_poly_init(den); fmpz_poly_init(det); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); fmpz_poly_mat_randtest_sparse(B, state, deg, bits, density); solved = fmpz_poly_mat_solve_fflu(X, den, A, B); fmpz_poly_mat_det_interpolate(det, A); if (m == 0 || n == 0) { if (solved == 0) { flint_printf("FAIL: expected empty system to pass\n"); fflush(stdout); flint_abort(); } } else { if (!fmpz_poly_equal(den, det)) { fmpz_poly_neg(det, det); flint_printf("FAIL: den != +/- det(A)\n"); flint_printf("den:\n"); fmpz_poly_print_pretty(den, "x"); flint_printf("\n\n"); flint_printf("det:\n"); fmpz_poly_print_pretty(det, "x"); flint_printf("\n\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("X:\n"); fmpz_poly_mat_print(X, "x"); fflush(stdout); flint_abort(); } } if (solved != !fmpz_poly_is_zero(den)) { flint_printf("FAIL: return value does not match denominator\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_mul(AX, A, X); fmpz_poly_mat_scalar_mul_fmpz_poly(Bden, B, den); if (!fmpz_poly_mat_equal(AX, Bden)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("X:\n"); fmpz_poly_mat_print(X, "x"); flint_printf("AX:\n"); fmpz_poly_mat_print(AX, "x"); flint_printf("Bden:\n"); fmpz_poly_mat_print(Bden, "x"); fflush(stdout); flint_abort(); } fmpz_poly_clear(den); fmpz_poly_clear(det); fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(X); fmpz_poly_mat_clear(AX); fmpz_poly_mat_clear(Bden); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-sqr.c000066400000000000000000000054231461254215100204770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_sqr, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, C; fmpz_mat_t a, c, d; fmpz_t x; slong m, bits, deg; m = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(C, m, m); fmpz_mat_init(a, m, m); fmpz_mat_init(c, m, m); fmpz_mat_init(d, m, m); fmpz_init(x); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); fmpz_poly_mat_sqr(C, A); fmpz_randtest(x, state, 1 + n_randint(state, 100)); fmpz_poly_mat_evaluate_fmpz(a, A, x); fmpz_poly_mat_evaluate_fmpz(d, C, x); fmpz_mat_mul(c, a, a); if (!fmpz_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(C); fmpz_mat_clear(a); fmpz_mat_clear(c); fmpz_mat_clear(d); fmpz_clear(x); } /* Check aliasing B and A */ for (i = 0; i < 1000; i++) { fmpz_poly_mat_t A, B; slong m, bits, deg; m = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, m); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_sqr(B, A); fmpz_poly_mat_sqr(A, A); if (!fmpz_poly_mat_equal(B, A)) { flint_printf("FAIL (aliasing):\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-sqr_KS.c000066400000000000000000000053101461254215100210670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_sqr_KS, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, C, D; slong m, bits, deg; /* TODO: add separate unsigned tests */ m = n_randint(state, 15); deg = 1 + n_randint(state, 15); bits = 1 + n_randint(state, 150); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(C, m, m); fmpz_poly_mat_init(D, m, m); if (n_randint(state, 2)) fmpz_poly_mat_randtest(A, state, deg, bits); else fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_sqr_classical(C, A); fmpz_poly_mat_sqr_KS(D, A); if (!fmpz_poly_mat_equal(C, D)) { flint_printf("FAIL:\n"); flint_printf("products don't agree!\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("D:\n"); fmpz_poly_mat_print(D, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(C); fmpz_poly_mat_clear(D); } /* Check aliasing B and A */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B; slong m, bits, deg; m = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, m); fmpz_poly_mat_init(B, m, m); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_sqr_KS(B, A); fmpz_poly_mat_sqr_KS(A, A); if (!fmpz_poly_mat_equal(B, A)) { flint_printf("FAIL (aliasing):\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-sqrlow.c000066400000000000000000000053621461254215100212230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_sqrlow, state) { slong i; /* Compare with sqr */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong n, bits, deg, len; n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); len = n_randint(state, 10); fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(C, n, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); /* noise in output */ fmpz_poly_mat_randtest(C, state, deg, bits); /* noise in output */ fmpz_poly_mat_sqrlow(B, A, len); fmpz_poly_mat_sqr(C, A); fmpz_poly_mat_truncate(C, len); if (!fmpz_poly_mat_equal(B, C)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B; slong n, bits, deg, len; n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); len = n_randint(state, 10); fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_sqrlow(B, A, len); fmpz_poly_mat_sqrlow(A, A, len); if (!fmpz_poly_mat_equal(B, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-sub.c000066400000000000000000000105411461254215100204600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_sub, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; fmpz_mat_t a, b, c, d; fmpz_t x; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_mat_init(a, m, n); fmpz_mat_init(b, m, n); fmpz_mat_init(c, m, n); fmpz_mat_init(d, m, n); fmpz_init(x); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_sub(C, A, B); fmpz_randtest(x, state, 1 + n_randint(state, 100)); fmpz_poly_mat_evaluate_fmpz(a, A, x); fmpz_poly_mat_evaluate_fmpz(b, B, x); fmpz_poly_mat_evaluate_fmpz(d, C, x); fmpz_mat_sub(c, a, b); if (!fmpz_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); fmpz_mat_clear(a); fmpz_mat_clear(b); fmpz_mat_clear(c); fmpz_mat_clear(d); fmpz_clear(x); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_sub(C, A, B); fmpz_poly_mat_sub(A, A, B); if (!fmpz_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, C; slong m, n, bits, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); bits = 1 + n_randint(state, 100); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, m, n); fmpz_poly_mat_init(C, m, n); fmpz_poly_mat_randtest(A, state, deg, bits); fmpz_poly_mat_randtest(B, state, deg, bits); fmpz_poly_mat_sub(C, A, B); fmpz_poly_mat_sub(B, A, B); if (!fmpz_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); fmpz_poly_mat_print(A, "x"); flint_printf("B:\n"); fmpz_poly_mat_print(B, "x"); flint_printf("C:\n"); fmpz_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-trace.c000066400000000000000000000041371461254215100207710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_trace, state) { slong i; /* Test trace(AB) = trace(BA) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t A, B, AB, BA; fmpz_poly_t trab, trba; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_init(B, n, m); fmpz_poly_mat_init(AB, m, m); fmpz_poly_mat_init(BA, n, n); fmpz_poly_init(trab); fmpz_poly_init(trba); fmpz_poly_mat_randtest(A, state, 1 + n_randint(state, 10), 1 + n_randint(state, 100)); fmpz_poly_mat_randtest(B, state, 1 + n_randint(state, 10), 1 + n_randint(state, 100)); fmpz_poly_mat_mul(AB, A, B); fmpz_poly_mat_mul(BA, B, A); fmpz_poly_mat_trace(trab, AB); fmpz_poly_mat_trace(trba, BA); if (!fmpz_poly_equal(trab, trba)) { flint_printf("FAIL:\n"); fmpz_poly_mat_print(A, "x"), flint_printf("\n"); fmpz_poly_mat_print(B, "x"), flint_printf("\n"); fmpz_poly_mat_print(AB, "x"), flint_printf("\n"); fmpz_poly_mat_print(BA, "x"), flint_printf("\n"); flint_printf("tr(AB): "), fmpz_poly_print(trab), flint_printf("\n"); flint_printf("tr(BA): "), fmpz_poly_print(trba), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(AB); fmpz_poly_mat_clear(BA); fmpz_poly_clear(trab); fmpz_poly_clear(trba); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-window_init_clear.c000066400000000000000000000027751461254215100234010ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_window_init_clear, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_mat_t a, w; slong j, k, r1, r2, c1, c2, bits; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); bits = 1 + n_randint(state, 10); fmpz_poly_mat_init(a, rows, cols); fmpz_poly_mat_randtest(a, state, n_randint(state, 10) + 1, bits); r2 = n_randint(state, rows + 1); c2 = n_randint(state, cols + 1); if (r2) r1 = n_randint(state, r2); else r1 = 0; if (c2) c1 = n_randint(state, c2); else c1 = 0; fmpz_poly_mat_window_init(w, a, r1, c1, r2, c2); for (j = 0; j < r2 - r1; j++) for (k = 0; k < c2 - c1; k++) fmpz_poly_zero(fmpz_poly_mat_entry(w, j, k)); fmpz_poly_mat_window_clear(w); fmpz_poly_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/test/t-zero.c000066400000000000000000000027771461254215100206620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_mat.h" TEST_FUNCTION_START(fmpz_poly_mat_zero, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { fmpz_poly_mat_t A; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); fmpz_poly_mat_init(A, m, n); fmpz_poly_mat_randtest(A, state, n_randint(state, 5), n_randint(state, 100)); fmpz_poly_mat_zero(A); if (!fmpz_poly_mat_is_zero(A)) { flint_printf("FAIL: expected matrix to be zero\n"); fflush(stdout); flint_abort(); } if (m > 0 && n > 0) { m = n_randint(state, m); n = n_randint(state, n); fmpz_poly_randtest_not_zero(fmpz_poly_mat_entry(A, m, n), state, 5, 5); if (fmpz_poly_mat_is_zero(A)) { flint_printf("FAIL: expected matrix not to be zero\n"); fflush(stdout); flint_abort(); } } fmpz_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_mat/trace.c000066400000000000000000000014471461254215100175520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_trace(fmpz_poly_t trace, const fmpz_poly_mat_t mat) { slong i, n = fmpz_poly_mat_nrows(mat); if (n == 0) fmpz_poly_zero(trace); else { fmpz_poly_set(trace, fmpz_poly_mat_entry(mat, 0, 0)); for (i = 1; i < n; i++) fmpz_poly_add(trace, trace, fmpz_poly_mat_entry(mat, i, i)); } } flint-3.1.3/src/fmpz_poly_mat/transpose.c000066400000000000000000000023351461254215100204670ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_transpose(fmpz_poly_mat_t B, const fmpz_poly_mat_t A) { slong i, j; if (B->r != A->c || B->c != A->r) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_mat_transpose). Incompatible dimensions.\n"); } if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < A->r - 1; i++) for (j = i + 1; j < A->c; j++) fmpz_poly_swap(fmpz_poly_mat_entry(B, i, j), fmpz_poly_mat_entry(B, j, i)); } else /* Not aliased; general case */ { for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) fmpz_poly_set(fmpz_poly_mat_entry(B, i, j), fmpz_poly_mat_entry(A, j, i)); } } flint-3.1.3/src/fmpz_poly_mat/truncate.c000066400000000000000000000013011461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_truncate(fmpz_poly_mat_t A, slong len) { slong i, j; for (i = 0; i < fmpz_poly_mat_nrows(A); i++) for (j = 0; j < fmpz_poly_mat_ncols(A); j++) fmpz_poly_truncate(fmpz_poly_mat_entry(A, i, j), len); } flint-3.1.3/src/fmpz_poly_mat/window.c000066400000000000000000000023121461254215100177530ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid Copyright (C) 2015 Elena Sergeichave This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_mat.h" void fmpz_poly_mat_window_init(fmpz_poly_mat_t window, const fmpz_poly_mat_t mat, slong r1, slong c1, slong r2, slong c2) { slong i; window->entries = NULL; if (r2 > r1) window->rows = (fmpz_poly_struct **) flint_malloc((r2 - r1) * sizeof(fmpz_poly_struct *)); else window->rows = NULL; if (mat->c > 0) { for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; } else { for (i = 0; i < r2 - r1; i++) window->rows[i] = NULL; } window->r = r2 - r1; window->c = c2 - c1; } void fmpz_poly_mat_window_clear(fmpz_poly_mat_t window) { if (window->r != 0) flint_free(window->rows); } flint-3.1.3/src/fmpz_poly_mat/zero.c000066400000000000000000000012011461254215100174170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" void fmpz_poly_mat_zero(fmpz_poly_mat_t A) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_poly_zero(fmpz_poly_mat_entry(A, i, j)); } flint-3.1.3/src/fmpz_poly_q.h000066400000000000000000000137071461254215100161420ustar00rootroot00000000000000/* Copyright (C) 2009, 2010, 2011 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_POLY_Q_H #define FMPZ_POLY_Q_H #ifdef FMPZ_POLY_Q_INLINES_C #define FMPZ_POLY_Q_INLINE #else #define FMPZ_POLY_Q_INLINE static inline #endif #include "fmpz_poly.h" #ifdef __cplusplus extern "C" { #endif /* Accessing numerator and denominator ***************************************/ #define fmpz_poly_q_numref(op) ((op)->num) #define fmpz_poly_q_denref(op) ((op)->den) void fmpz_poly_q_canonicalise(fmpz_poly_q_t rop); int fmpz_poly_q_is_canonical(const fmpz_poly_q_t op); /* Memory management *********************************************************/ void fmpz_poly_q_init(fmpz_poly_q_t rop); void fmpz_poly_q_clear(fmpz_poly_q_t rop); /* Randomisation *************************************************************/ void fmpz_poly_q_randtest(fmpz_poly_q_t poly, flint_rand_t state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2); void fmpz_poly_q_randtest_not_zero(fmpz_poly_q_t poly, flint_rand_t state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2); /* Assignment ****************************************************************/ void fmpz_poly_q_set(fmpz_poly_q_t rop, const fmpz_poly_q_t op); void fmpz_poly_q_set_si(fmpz_poly_q_t rop, slong op); void fmpz_poly_q_swap(fmpz_poly_q_t op1, fmpz_poly_q_t op2); FMPZ_POLY_Q_INLINE void fmpz_poly_q_zero(fmpz_poly_q_t rop) { fmpz_poly_zero(rop->num); fmpz_poly_set_si(rop->den, 1); } FMPZ_POLY_Q_INLINE void fmpz_poly_q_one(fmpz_poly_q_t rop) { fmpz_poly_set_si(rop->num, 1); fmpz_poly_set_si(rop->den, 1); } FMPZ_POLY_Q_INLINE void fmpz_poly_q_neg(fmpz_poly_q_t rop, const fmpz_poly_q_t op) { fmpz_poly_neg(rop->num, op->num); fmpz_poly_set(rop->den, op->den); } void fmpz_poly_q_inv(fmpz_poly_q_t rop, const fmpz_poly_q_t op); /* Comparison ****************************************************************/ FMPZ_POLY_Q_INLINE int fmpz_poly_q_is_zero(const fmpz_poly_q_t op) { return fmpz_poly_is_zero(op->num); } FMPZ_POLY_Q_INLINE int fmpz_poly_q_is_one(const fmpz_poly_q_t op) { return fmpz_poly_is_one(op->num) && fmpz_poly_is_one(op->den); } FMPZ_POLY_Q_INLINE int fmpz_poly_q_equal(const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { return fmpz_poly_equal(op1->num, op2->num) && fmpz_poly_equal(op1->den, op2->den); } /* Addition and subtraction **************************************************/ void fmpz_poly_q_add_in_place(fmpz_poly_q_t rop, const fmpz_poly_q_t op); void fmpz_poly_q_sub_in_place(fmpz_poly_q_t rop, const fmpz_poly_q_t op); void fmpz_poly_q_add(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); void fmpz_poly_q_sub(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); void fmpz_poly_q_addmul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); void fmpz_poly_q_submul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); /* Scalar multiplication and division ****************************************/ void fmpz_poly_q_scalar_mul_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x); void fmpz_poly_q_scalar_mul_fmpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpz_t x); void fmpz_poly_q_scalar_mul_fmpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpq_t x); void fmpz_poly_q_scalar_div_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x); void fmpz_poly_q_scalar_div_fmpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpz_t x); void fmpz_poly_q_scalar_div_fmpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpq_t x); /* Multiplication and division ***********************************************/ void fmpz_poly_q_mul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); void fmpz_poly_q_div(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); /* Powering ******************************************************************/ void fmpz_poly_q_pow(fmpz_poly_q_t rop, const fmpz_poly_q_t op, ulong exp); /* Derivative ****************************************************************/ void fmpz_poly_q_derivative(fmpz_poly_q_t rop, const fmpz_poly_q_t op); /* Evaluation ****************************************************************/ int fmpz_poly_q_evaluate_fmpq(fmpq_t rop, const fmpz_poly_q_t f, const fmpq_t a); /* Input and output **********************************************************/ int fmpz_poly_q_set_str(fmpz_poly_q_t rop, const char *s); char * fmpz_poly_q_get_str(const fmpz_poly_q_t op); char * fmpz_poly_q_get_str_pretty(const fmpz_poly_q_t op, const char *x); int fmpz_poly_q_print(const fmpz_poly_q_t op); int fmpz_poly_q_print_pretty(const fmpz_poly_q_t op, const char *x); /* Declare old functions dead *************************************************/ #define fmpz_poly_q_scalar_mul_mpz _Pragma("GCC error \"'fmpz_poly_q_scalar_mul_mpz' is deprecated. Use 'fmpz_poly_q_scalar_mul_fmpz' instead.\"") #define fmpz_poly_q_scalar_mul_mpq _Pragma("GCC error \"'fmpz_poly_q_scalar_mul_mpq' is deprecated. Use 'fmpz_poly_q_scalar_mul_fmpq' instead.\"") #define fmpz_poly_q_scalar_div_mpz _Pragma("GCC error \"'fmpz_poly_q_scalar_div_mpz' is deprecated. Use 'fmpz_poly_q_scalar_div_fmpz' instead.\"") #define fmpz_poly_q_scalar_div_mpq _Pragma("GCC error \"'fmpz_poly_q_scalar_div_mpq' is deprecated. Use 'fmpz_poly_q_scalar_div_fmpq' instead.\"") #define fmpz_poly_q_evaluate _Pragma("GCC error \"'fmpz_poly_q_evaluate' is deprecated. Use 'fmpz_poly_q_evaluate_fmpq' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_poly_q/000077500000000000000000000000001461254215100157615ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly_q/add.c000066400000000000000000000151751461254215100166660ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "fmpz_poly_q.h" void fmpz_poly_q_add_in_place(fmpz_poly_q_t rop, const fmpz_poly_q_t op) { fmpz_poly_t d, poly, r2, s2; if (rop == op) { fmpz_poly_q_scalar_mul_si(rop, rop, 2); return; } if (fmpz_poly_q_is_zero(rop)) { fmpz_poly_q_set(rop, op); return; } if (fmpz_poly_q_is_zero(op)) { return; } /* Polynomials? */ if (fmpz_poly_length(rop->den) == 1 && fmpz_poly_length(op->den) == 1) { const slong len1 = fmpz_poly_length(rop->num); const slong len2 = fmpz_poly_length(op->num); fmpz_poly_fit_length(rop->num, FLINT_MAX(len1, len2)); _fmpq_poly_add(rop->num->coeffs, rop->den->coeffs, rop->num->coeffs, rop->den->coeffs, len1, op->num->coeffs, op->den->coeffs, len2); _fmpz_poly_set_length(rop->num, FLINT_MAX(len1, len2)); _fmpz_poly_set_length(rop->den, 1); _fmpz_poly_normalise(rop->num); return; } /* Denominators equal to one? */ if (fmpz_poly_is_one(rop->den)) { fmpz_poly_mul(rop->num, rop->num, op->den); fmpz_poly_add(rop->num, rop->num, op->num); fmpz_poly_set(rop->den, op->den); return; } if (fmpz_poly_is_one(op->den)) { fmpz_poly_init(poly); fmpz_poly_mul(poly, rop->den, op->num); fmpz_poly_add(rop->num, rop->num, poly); fmpz_poly_clear(poly); return; } /* Henrici's algorithm for summation in quotient fields */ fmpz_poly_init(d); fmpz_poly_gcd(d, rop->den, op->den); if (fmpz_poly_is_one(d)) { fmpz_poly_mul(rop->num, rop->num, op->den); fmpz_poly_mul(d, rop->den, op->num); /* Using d as temp */ fmpz_poly_add(rop->num, rop->num, d); fmpz_poly_mul(rop->den, rop->den, op->den); } else { fmpz_poly_init(r2); fmpz_poly_init(s2); fmpz_poly_divexact(r2, rop->den, d); fmpz_poly_divexact(s2, op->den, d); fmpz_poly_mul(rop->num, rop->num, s2); fmpz_poly_mul(s2, op->num, r2); /* Using s2 as temp */ fmpz_poly_add(rop->num, rop->num, s2); if (fmpz_poly_is_zero(rop->num)) { fmpz_poly_zero(rop->den); fmpz_poly_set_coeff_si(rop->den, 0, 1); } else { fmpz_poly_mul(rop->den, r2, op->den); fmpz_poly_gcd(r2, rop->num, d); /* Using r2 as temp */ if (!fmpz_poly_is_one(r2)) { fmpz_poly_divexact(rop->num, rop->num, r2); fmpz_poly_divexact(rop->den, rop->den, r2); } } fmpz_poly_clear(r2); fmpz_poly_clear(s2); } fmpz_poly_clear(d); } void fmpz_poly_q_add(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { fmpz_poly_t d, r2, s2; if (fmpz_poly_q_is_zero(op1)) { fmpz_poly_q_set(rop, op2); return; } if (fmpz_poly_q_is_zero(op2)) { fmpz_poly_q_set(rop, op1); return; } if (op1 == op2) { fmpz_poly_q_scalar_mul_si(rop, op1, 2); return; } if (rop == op1) { fmpz_poly_q_add_in_place(rop, op2); return; } if (rop == op2) { fmpz_poly_q_add_in_place(rop, op1); return; } /* From here on, we may assume that rop, op1 and op2 all refer to distinct objects in memory, although they may still be equal */ /* Polynomials? */ if (fmpz_poly_length(op1->den) == 1 && fmpz_poly_length(op2->den) == 1) { const slong len1 = fmpz_poly_length(op1->num); const slong len2 = fmpz_poly_length(op2->num); fmpz_poly_fit_length(rop->num, FLINT_MAX(len1, len2)); _fmpq_poly_add(rop->num->coeffs, rop->den->coeffs, op1->num->coeffs, op1->den->coeffs, len1, op2->num->coeffs, op2->den->coeffs, len2); _fmpz_poly_set_length(rop->num, FLINT_MAX(len1, len2)); _fmpz_poly_set_length(rop->den, 1); _fmpz_poly_normalise(rop->num); return; } /* Denominators equal to one? */ if (fmpz_poly_is_one(op1->den)) { fmpz_poly_mul(rop->num, op1->num, op2->den); fmpz_poly_add(rop->num, rop->num, op2->num); fmpz_poly_set(rop->den, op2->den); return; } if (fmpz_poly_is_one(op2->den)) { fmpz_poly_mul(rop->num, op2->num, op1->den); fmpz_poly_add(rop->num, op1->num, rop->num); fmpz_poly_set(rop->den, op1->den); return; } /* Henrici's algorithm for summation in quotient fields */ /* We begin by using rop->num as a temporary variable for the gcd of the two denominators' greatest common divisor */ fmpz_poly_gcd(rop->num, op1->den, op2->den); if (fmpz_poly_is_one(rop->num)) { fmpz_poly_mul(rop->num, op1->num, op2->den); fmpz_poly_mul(rop->den, op1->den, op2->num); /* Using rop->den as temp */ fmpz_poly_add(rop->num, rop->num, rop->den); fmpz_poly_mul(rop->den, op1->den, op2->den); } else { /* We now copy rop->num into a new variable d, so we no longer need rop->num as a temporary variable */ fmpz_poly_init(d); fmpz_poly_swap(d, rop->num); fmpz_poly_init(r2); fmpz_poly_init(s2); fmpz_poly_divexact(r2, op1->den, d); /* +ve leading coeff */ fmpz_poly_divexact(s2, op2->den, d); /* +ve leading coeff */ fmpz_poly_mul(rop->num, op1->num, s2); fmpz_poly_mul(rop->den, op2->num, r2); /* Using rop->den as temp */ fmpz_poly_add(rop->num, rop->num, rop->den); if (fmpz_poly_is_zero(rop->num)) { fmpz_poly_zero(rop->den); fmpz_poly_set_coeff_si(rop->den, 0, 1); } else { fmpz_poly_mul(rop->den, op1->den, s2); fmpz_poly_gcd(r2, rop->num, d); if (!fmpz_poly_is_one(r2)) { fmpz_poly_divexact(rop->num, rop->num, r2); fmpz_poly_divexact(rop->den, rop->den, r2); } } fmpz_poly_clear(d); fmpz_poly_clear(r2); fmpz_poly_clear(s2); } } flint-3.1.3/src/fmpz_poly_q/addmul.c000066400000000000000000000012651461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_addmul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { fmpz_poly_q_t temp; fmpz_poly_q_init(temp); fmpz_poly_q_mul(temp, op1, op2); fmpz_poly_q_add(rop, rop, temp); fmpz_poly_q_clear(temp); } flint-3.1.3/src/fmpz_poly_q/canonicalise.c000066400000000000000000000021171461254215100205560ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly_q.h" void fmpz_poly_q_canonicalise(fmpz_poly_q_t rop) { fmpz_poly_t gcd; if (fmpz_poly_is_zero(rop->den)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_q_canonicalise). Denominator is zero.\n"); } if (fmpz_poly_is_one(rop->den)) return; fmpz_poly_init(gcd); fmpz_poly_gcd(gcd, rop->num, rop->den); if (!fmpz_poly_is_unit(gcd)) { fmpz_poly_divexact(rop->num, rop->num, gcd); fmpz_poly_divexact(rop->den, rop->den, gcd); } fmpz_poly_clear(gcd); if (fmpz_sgn(fmpz_poly_lead(rop->den)) < 0) { fmpz_poly_neg(rop->num, rop->num); fmpz_poly_neg(rop->den, rop->den); } } flint-3.1.3/src/fmpz_poly_q/clear.c000066400000000000000000000013161461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_clear(fmpz_poly_q_t rop) { if (rop->num != NULL) { fmpz_poly_clear(rop->num); flint_free(rop->num); rop->num = NULL; } if (rop->den != NULL) { fmpz_poly_clear(rop->den); flint_free(rop->den); rop->den = NULL; } } flint-3.1.3/src/fmpz_poly_q/derivative.c000066400000000000000000000040561461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly_q.h" void fmpz_poly_q_derivative(fmpz_poly_q_t rop, const fmpz_poly_q_t op) { fmpz_poly_t d, lhs, rhs; if (fmpz_poly_q_is_zero(op)) { fmpz_poly_q_zero(rop); return; } if (fmpz_poly_length(op->den) == 1) { fmpz_poly_derivative(rop->num, op->num); fmpz_poly_set(rop->den, op->den); fmpz_poly_q_canonicalise(rop); return; } fmpz_poly_init(d); fmpz_poly_init(rhs); fmpz_poly_derivative(rhs, op->den); fmpz_poly_gcd(d, rhs, op->den); if (!fmpz_poly_is_one(d)) fmpz_poly_divexact(rhs, rhs, d); fmpz_poly_mul(rhs, op->num, rhs); fmpz_poly_derivative(rop->num, op->num); if (fmpz_poly_is_one(d)) { fmpz_poly_mul(rop->num, rop->num, op->den); fmpz_poly_pow(rop->den, op->den, 2); } else { fmpz_poly_init(lhs); fmpz_poly_divexact(lhs, op->den, d); fmpz_poly_mul(rop->num, rop->num, lhs); fmpz_poly_mul(rop->den, op->den, lhs); fmpz_poly_clear(lhs); } fmpz_poly_sub(rop->num, rop->num, rhs); /* Canonicalise: there can be at most a constant factor */ { fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_poly_content(a, rop->num); fmpz_poly_content(b, rop->den); fmpz_gcd(c, a, b); if (!fmpz_is_one(c)) { fmpz_poly_scalar_divexact_fmpz(rop->num, rop->num, c); fmpz_poly_scalar_divexact_fmpz(rop->den, rop->den, c); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } fmpz_poly_clear(d); fmpz_poly_clear(rhs); } flint-3.1.3/src/fmpz_poly_q/div.c000066400000000000000000000070661461254215100167200ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" #include "fmpz_poly_q.h" void fmpz_poly_q_div(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { if (fmpz_poly_q_is_zero(op2)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_q_div). Division by zero.\n"); } if (fmpz_poly_q_is_zero(op1)) { fmpz_poly_q_zero(rop); return; } if (op1 == op2) { fmpz_poly_q_one(rop); return; } if (rop == op1 || rop == op2) { fmpz_poly_q_t t; fmpz_poly_q_init(t); fmpz_poly_q_div(t, op1, op2); fmpz_poly_q_swap(rop, t); fmpz_poly_q_clear(t); return; } /* From here on, we know that rop, op1 and op2 refer to distinct objects in memory, and that op1 and op2 are non-zero rational functions */ /* XXX: Do not maintain the remaining part of the function separately!!! Instead, note that this is the same as the corresponding part of the multiplication code, with op2->num and op2->den swapped. The only caveat to this is that we cannot assume the leading coefficient of op2->num to be positive, and thus check for this in the very end. */ /* Denominator/ numerator equal to one? */ if (fmpz_poly_is_one(op1->den) && fmpz_poly_is_one(op2->num)) { fmpz_poly_mul(rop->num, op1->num, op2->den); fmpz_poly_set_si(rop->den, 1); return; } fmpz_poly_gcd(rop->num, op1->num, op2->num); if (fmpz_poly_is_one(rop->num)) { fmpz_poly_gcd(rop->den, op2->den, op1->den); if (fmpz_poly_is_one(rop->den)) { fmpz_poly_mul(rop->num, op1->num, op2->den); fmpz_poly_mul(rop->den, op1->den, op2->num); } else { fmpz_poly_divexact(rop->num, op2->den, rop->den); fmpz_poly_mul(rop->num, op1->num, rop->num); fmpz_poly_divexact(rop->den, op1->den, rop->den); fmpz_poly_mul(rop->den, rop->den, op2->num); } } else { fmpz_poly_gcd(rop->den, op2->den, op1->den); if (fmpz_poly_is_one(rop->den)) { fmpz_poly_divexact(rop->den, op2->num, rop->num); fmpz_poly_mul(rop->den, op1->den, rop->den); fmpz_poly_divexact(rop->num, op1->num, rop->num); fmpz_poly_mul(rop->num, rop->num, op2->den); } else { fmpz_poly_t t, u; fmpz_poly_init(t); fmpz_poly_init(u); fmpz_poly_divexact(t, op1->num, rop->num); fmpz_poly_divexact(u, op2->num, rop->num); fmpz_poly_divexact(rop->num, op2->den, rop->den); fmpz_poly_mul(rop->num, t, rop->num); fmpz_poly_divexact(rop->den, op1->den, rop->den); fmpz_poly_mul(rop->den, rop->den, u); fmpz_poly_clear(t); fmpz_poly_clear(u); } } /* XXX: Check that the numerator has the appropriate sign. */ if (fmpz_sgn(fmpz_poly_lead(rop->den)) < 0) { fmpz_poly_neg(rop->num, rop->num); fmpz_poly_neg(rop->den, rop->den); } } flint-3.1.3/src/fmpz_poly_q/evaluate_fmpq.c000066400000000000000000000033241461254215100207600ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_poly_q.h" int fmpz_poly_q_evaluate_fmpq(fmpq_t rop, const fmpz_poly_q_t f, const fmpq_t a) { if (fmpz_cmp_si(fmpq_denref(a), 1)) /* a is not an integer */ { fmpq_t fmpqnum, fmpqden; fmpq_init(fmpqden); fmpz_poly_evaluate_fmpq(fmpqden, f->den, a); if (fmpq_sgn(fmpqden) == 0) { fmpq_clear(fmpqden); return 1; } fmpq_init(fmpqnum); fmpz_poly_evaluate_fmpq(fmpqnum, f->num, a); fmpq_div(rop, fmpqnum, fmpqden); fmpq_clear(fmpqnum); fmpq_clear(fmpqden); return 0; } else /* a is an integer */ { fmpz_t num, den, a2; fmpz_init(num); fmpz_init(den); fmpz_init(a2); fmpz_set(a2, fmpq_numref(a)); fmpz_poly_evaluate_fmpz(den, f->den, a2); if (fmpz_is_zero(den)) { fmpz_clear(a2); fmpz_clear(num); fmpz_clear(den); return 1; } fmpz_poly_evaluate_fmpz(num, f->num, a2); fmpz_set(fmpq_numref(rop), num); fmpz_set(fmpq_denref(rop), den); _fmpq_canonicalise(fmpq_numref(rop), fmpq_denref(rop)); fmpz_clear(a2); fmpz_clear(num); fmpz_clear(den); return 0; } } flint-3.1.3/src/fmpz_poly_q/get_str.c000066400000000000000000000030561461254215100176000ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly_q.h" /** * \ingroup StringConversions * * Returns the string representation of the rational function \c op. */ char * fmpz_poly_q_get_str(const fmpz_poly_q_t op) { int i, j; char * str; char * numstr; char * denstr; if (fmpz_poly_is_one(op->den)) { numstr = fmpz_poly_get_str(op->num); i = strlen(numstr) - 1; if (numstr[i] == ' ') { numstr[i] = '\0'; } return numstr; } numstr = fmpz_poly_get_str(op->num); denstr = fmpz_poly_get_str(op->den); i = strlen(numstr) - 1; if (numstr[i] == ' ') numstr[i] = '\0'; i = strlen(denstr) - 1; if (denstr[i] == ' ') denstr[i] = '\0'; str = flint_malloc(strlen(numstr) + strlen(denstr) + 2); if (str == NULL) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_q_get_str). Memory allocation failed.\n"); } for (i = 0; i < strlen(numstr); i++) str[i] = numstr[i]; str[i++] = '/'; for (j = 0; j < strlen(denstr); j++) str[i++] = denstr[j]; str[i] = '\0'; flint_free(numstr); flint_free(denstr); return str; } flint-3.1.3/src/fmpz_poly_q/get_str_pretty.c000066400000000000000000000035221461254215100212050ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly_q.h" /** * \ingroup StringConversions * * Returns the pretty string representation of \c op. * * Returns the pretty string representation of the rational function \c op, * using the string \c x as the variable name. */ char * fmpz_poly_q_get_str_pretty(const fmpz_poly_q_t op, const char *x) { int i, j; char * str; char * numstr; char * denstr; if (fmpz_poly_is_one(op->den)) { return fmpz_poly_get_str_pretty(op->num, x); } numstr = fmpz_poly_get_str_pretty(op->num, x); denstr = fmpz_poly_get_str_pretty(op->den, x); str = flint_malloc(strlen(numstr) + strlen(denstr) + 6); if (!str) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_q_get_str_pretty). Memory allocation failed.\n"); } i = 0; if (fmpz_poly_degree(op->num) > 0) { str[i++] = '('; for (j = 0; j < strlen(numstr); j++) str[i++] = numstr[j]; str[i++] = ')'; } else { for (j = 0; j < strlen(numstr); j++) str[i++] = numstr[j]; } str[i++] = '/'; if (fmpz_poly_degree(op->den) > 0) { str[i++] = '('; for (j = 0; j < strlen(denstr); j++) str[i++] = denstr[j]; str[i++] = ')'; } else { for (j = 0; j < strlen(denstr); j++) str[i++] = denstr[j]; } str[i] = '\0'; flint_free(numstr); flint_free(denstr); return str; } flint-3.1.3/src/fmpz_poly_q/init.c000066400000000000000000000012321461254215100170660ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_init(fmpz_poly_q_t rop) { rop->num = flint_malloc(sizeof(fmpz_poly_struct)); rop->den = flint_malloc(sizeof(fmpz_poly_struct)); fmpz_poly_init(rop->num); fmpz_poly_init(rop->den); fmpz_poly_set_si(rop->den, 1); } flint-3.1.3/src/fmpz_poly_q/inlines.c000066400000000000000000000007051461254215100175700ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_Q_INLINES_C #include "flint.h" #include "fmpz_poly_q.h" flint-3.1.3/src/fmpz_poly_q/inv.c000066400000000000000000000022511461254215100167210ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly_q.h" void fmpz_poly_q_inv(fmpz_poly_q_t rop, const fmpz_poly_q_t op) { if (fmpz_poly_is_zero(op->num)) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_q_inv). Zero is not invertible.\n"); } if (rop == op) { fmpz_poly_swap(rop->num, rop->den); if (fmpz_sgn(fmpz_poly_lead(rop->den)) < 0) { fmpz_poly_neg(rop->num, rop->num); fmpz_poly_neg(rop->den, rop->den); } } else { if (fmpz_sgn(fmpz_poly_lead(op->num)) > 0) { fmpz_poly_set(rop->num, op->den); fmpz_poly_set(rop->den, op->num); } else { fmpz_poly_neg(rop->num, op->den); fmpz_poly_neg(rop->den, op->num); } } } flint-3.1.3/src/fmpz_poly_q/is_canonical.c000066400000000000000000000014131461254215100205460ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly_q.h" int fmpz_poly_q_is_canonical(const fmpz_poly_q_t op) { int ans; fmpz_poly_t t; if (fmpz_poly_is_zero(op->den)) return 0; if (fmpz_sgn(fmpz_poly_lead(op->den)) < 0) return 0; fmpz_poly_init(t); fmpz_poly_gcd(t, op->num, op->den); ans = fmpz_poly_is_one(t); fmpz_poly_clear(t); return ans; } flint-3.1.3/src/fmpz_poly_q/mul.c000066400000000000000000000067561461254215100167400ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "fmpz_poly_q.h" void fmpz_poly_q_mul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { if (fmpz_poly_q_is_zero(op1) || fmpz_poly_q_is_zero(op2)) { fmpz_poly_q_zero(rop); return; } if (op1 == op2) { fmpz_poly_pow(rop->num, op1->num, 2); fmpz_poly_pow(rop->den, op1->den, 2); return; } if (rop == op1 || rop == op2) { fmpz_poly_q_t t; fmpz_poly_q_init(t); fmpz_poly_q_mul(t, op1, op2); fmpz_poly_q_swap(rop, t); fmpz_poly_q_clear(t); return; } /* From here on, we may assume that rop, op1 and op2 refer to distinct objects in memory, and that op1 and op2 are non-zero */ /* Polynomials? */ if (fmpz_poly_length(op1->den) == 1 && fmpz_poly_length(op2->den) == 1) { const slong len1 = fmpz_poly_length(op1->num); const slong len2 = fmpz_poly_length(op2->num); fmpz_poly_fit_length(rop->num, len1 + len2 - 1); if (len1 >= len2) { _fmpq_poly_mul(rop->num->coeffs, rop->den->coeffs, op1->num->coeffs, op1->den->coeffs, len1, op2->num->coeffs, op2->den->coeffs, len2); } else { _fmpq_poly_mul(rop->num->coeffs, rop->den->coeffs, op2->num->coeffs, op2->den->coeffs, len2, op1->num->coeffs, op1->den->coeffs, len1); } _fmpz_poly_set_length(rop->num, len1 + len2 - 1); _fmpz_poly_set_length(rop->den, 1); return; } fmpz_poly_gcd(rop->num, op1->num, op2->den); if (fmpz_poly_is_one(rop->num)) { fmpz_poly_gcd(rop->den, op2->num, op1->den); if (fmpz_poly_is_one(rop->den)) { fmpz_poly_mul(rop->num, op1->num, op2->num); fmpz_poly_mul(rop->den, op1->den, op2->den); } else { fmpz_poly_divexact(rop->num, op2->num, rop->den); fmpz_poly_mul(rop->num, op1->num, rop->num); fmpz_poly_divexact(rop->den, op1->den, rop->den); fmpz_poly_mul(rop->den, rop->den, op2->den); } } else { fmpz_poly_gcd(rop->den, op2->num, op1->den); if (fmpz_poly_is_one(rop->den)) { fmpz_poly_divexact(rop->den, op2->den, rop->num); fmpz_poly_mul(rop->den, op1->den, rop->den); fmpz_poly_divexact(rop->num, op1->num, rop->num); fmpz_poly_mul(rop->num, rop->num, op2->num); } else { fmpz_poly_t t, u; fmpz_poly_init(t); fmpz_poly_init(u); fmpz_poly_divexact(t, op1->num, rop->num); fmpz_poly_divexact(u, op2->den, rop->num); fmpz_poly_divexact(rop->num, op2->num, rop->den); fmpz_poly_mul(rop->num, t, rop->num); fmpz_poly_divexact(rop->den, op1->den, rop->den); fmpz_poly_mul(rop->den, rop->den, u); fmpz_poly_clear(t); fmpz_poly_clear(u); } } } flint-3.1.3/src/fmpz_poly_q/pow.c000066400000000000000000000012631461254215100167340ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_pow(fmpz_poly_q_t rop, const fmpz_poly_q_t op, ulong exp) { if (exp == 0) { fmpz_poly_q_one(rop); } else { fmpz_poly_pow(rop->num, op->num, exp); fmpz_poly_pow(rop->den, op->den, exp); } } flint-3.1.3/src/fmpz_poly_q/print.c000066400000000000000000000011071461254215100172600ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" int fmpz_poly_q_print(const fmpz_poly_q_t op) { char *str; str = fmpz_poly_q_get_str(op); flint_printf("%s", str); flint_free(str); return 1; } flint-3.1.3/src/fmpz_poly_q/print_pretty.c000066400000000000000000000011471461254215100206730ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" int fmpz_poly_q_print_pretty(const fmpz_poly_q_t op, const char *x) { char *str; str = fmpz_poly_q_get_str_pretty(op, x); flint_printf("%s", str); flint_free(str); return 1; } flint-3.1.3/src/fmpz_poly_q/randtest.c000066400000000000000000000024741461254215100177600ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_randtest(fmpz_poly_q_t poly, flint_rand_t state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2) { len2 = FLINT_MAX(len2, 1); bits2 = FLINT_MAX(bits2, 1); fmpz_poly_randtest(poly->num, state, len1, bits1); fmpz_poly_randtest_not_zero(poly->den, state, len2, bits2); fmpz_poly_q_canonicalise(poly); } void fmpz_poly_q_randtest_not_zero(fmpz_poly_q_t poly, flint_rand_t state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2) { len1 = FLINT_MAX(len1, 1); len2 = FLINT_MAX(len2, 1); bits1 = FLINT_MAX(bits1, 1); bits2 = FLINT_MAX(bits2, 1); fmpz_poly_randtest_not_zero(poly->num, state, len1, bits1); fmpz_poly_randtest_not_zero(poly->den, state, len2, bits2); fmpz_poly_q_canonicalise(poly); } flint-3.1.3/src/fmpz_poly_q/scalar.c000066400000000000000000000114101461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly_q.h" void fmpz_poly_q_scalar_div_fmpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpq_t x) { fmpz_t num, den; if (fmpz_sgn(fmpq_numref(x)) == 0) flint_throw(FLINT_ERROR, "Division by zero in %s\n", __func__); fmpz_init(num); fmpz_init(den); fmpz_set(num, fmpq_numref(x)); fmpz_set(den, fmpq_denref(x)); fmpz_poly_scalar_mul_fmpz(rop->num, op->num, den); fmpz_poly_scalar_mul_fmpz(rop->den, op->den, num); fmpz_poly_q_canonicalise(rop); fmpz_clear(num); fmpz_clear(den); } void fmpz_poly_q_scalar_div_fmpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpz_t x) { fmpz_t y; if (fmpz_sgn(x) == 0) flint_throw(FLINT_ERROR, "Division by zero in %s\n", __func__); fmpz_init(y); fmpz_set(y, x); fmpz_poly_set(rop->num, op->num); fmpz_poly_scalar_mul_fmpz(rop->den, op->den, y); fmpz_poly_q_canonicalise(rop); fmpz_clear(y); } void fmpz_poly_q_scalar_div_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x) { fmpz_t cont, fx, gcd; if (FLINT_ABS(x) <= 1) { if (x == 0) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_q_scalar_div_si). Division by zero.\n"); } if (x == 1) fmpz_poly_q_set(rop, op); else fmpz_poly_q_neg(rop, op); return; } if (fmpz_poly_q_is_zero(op)) { fmpz_poly_q_zero(rop); return; } fmpz_init(cont); fmpz_poly_content(cont, op->num); if (fmpz_is_one(cont)) { if (x > 0) { fmpz_poly_set(rop->num, op->num); fmpz_poly_scalar_mul_si(rop->den, op->den, x); } else { fmpz_poly_neg(rop->num, op->num); fmpz_poly_scalar_mul_ui(rop->den, op->den, - ((ulong) x)); } fmpz_clear(cont); return; } fmpz_init(fx); fmpz_init(gcd); fmpz_set_si(fx, x); fmpz_gcd(gcd, cont, fx); if (fmpz_is_one(gcd)) { if (x > 0) { fmpz_poly_set(rop->num, op->num); fmpz_poly_scalar_mul_si(rop->den, op->den, x); } else { fmpz_poly_neg(rop->num, op->num); fmpz_poly_scalar_mul_ui(rop->den, op->den, - ((ulong) x)); } } else { fmpz_poly_scalar_divexact_fmpz(rop->num, op->num, gcd); fmpz_divexact(fx, fx, gcd); fmpz_poly_scalar_mul_fmpz(rop->den, op->den, fx); if (x < 0) { fmpz_poly_neg(rop->num, rop->num); fmpz_poly_neg(rop->den, rop->den); } } fmpz_clear(cont); fmpz_clear(fx); fmpz_clear(gcd); } void fmpz_poly_q_scalar_mul_fmpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpq_t x) { fmpz_t num, den; fmpz_init(num); fmpz_init(den); fmpz_set(num, fmpq_numref(x)); fmpz_set(den, fmpq_denref(x)); fmpz_poly_scalar_mul_fmpz(rop->num, op->num, num); fmpz_poly_scalar_mul_fmpz(rop->den, op->den, den); fmpz_poly_q_canonicalise(rop); fmpz_clear(num); fmpz_clear(den); } void fmpz_poly_q_scalar_mul_fmpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const fmpz_t x) { fmpz_t y; fmpz_init(y); fmpz_set(y, x); fmpz_poly_scalar_mul_fmpz(rop->num, op->num, y); fmpz_poly_set(rop->den, op->den); fmpz_poly_q_canonicalise(rop); fmpz_clear(y); } void fmpz_poly_q_scalar_mul_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x) { fmpz_t cont, fx, gcd; if (fmpz_poly_q_is_zero(op) || (x == 0)) { fmpz_poly_q_zero(rop); return; } if (x == 1) { fmpz_poly_q_set(rop, op); return; } fmpz_init(cont); fmpz_poly_content(cont, op->den); if (fmpz_is_one(cont)) { fmpz_poly_scalar_mul_si(rop->num, op->num, x); fmpz_poly_set(rop->den, op->den); fmpz_clear(cont); return; } fmpz_init(fx); fmpz_init(gcd); fmpz_set_si(fx, x); fmpz_gcd(gcd, cont, fx); if (fmpz_is_one(gcd)) { fmpz_poly_scalar_mul_si(rop->num, op->num, x); fmpz_poly_set(rop->den, op->den); } else { fmpz_divexact(fx, fx, gcd); fmpz_poly_scalar_mul_fmpz(rop->num, op->num, fx); fmpz_poly_scalar_divexact_fmpz(rop->den, op->den, gcd); } fmpz_clear(cont); fmpz_clear(fx); fmpz_clear(gcd); } flint-3.1.3/src/fmpz_poly_q/set.c000066400000000000000000000013301461254215100167150ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_set(fmpz_poly_q_t rop, const fmpz_poly_q_t op) { if (rop != op) { fmpz_poly_set(rop->num, op->num); fmpz_poly_set(rop->den, op->den); } } void fmpz_poly_q_set_si(fmpz_poly_q_t rop, slong op) { fmpz_poly_set_si(rop->num, op); fmpz_poly_set_si(rop->den, 1); } flint-3.1.3/src/fmpz_poly_q/set_str.c000066400000000000000000000037711461254215100176200ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly_q.h" /** * \ingroup StringConversions * * Sets the rational function \c rop to the value specified by the * null-terminated string \c s. * * This method has now already been somewhat improved and is not very tolerant * in the handling of malformed input. It expects either legitimate input for * an \c fmpz_poly_t element, or two such inputs separated by a / * only, in which case it is also assumed that the second polynomial is * non-zero. * * The rational function is brought into canonical form by calling * #fmpz_poly_q_canonicalize() in this function. * * Returns \c 0 if the string represents a valid rational function and * \c non-zero otherwise. */ int fmpz_poly_q_set_str(fmpz_poly_q_t rop, const char *s) { int ans, i, m; size_t len; char * numstr; len = strlen(s); for (m = 0; m < len; m++) { if (s[m] == '/') break; } if (m == len) { ans = fmpz_poly_set_str(rop->num, s); fmpz_poly_set_si(rop->den, 1); return ans; } else { numstr = flint_malloc(m + 1); if (!numstr) { flint_throw(FLINT_ERROR, "Exception (fmpz_poly_q_set_str). Memory allocation failed.\n"); } for (i = 0; i < m; i++) numstr[i] = s[i]; numstr[i] = '\0'; ans = fmpz_poly_set_str(rop->num, numstr); ans |= fmpz_poly_set_str(rop->den, s + (m + 1)); if (ans == 0) fmpz_poly_q_canonicalise(rop); else fmpz_poly_q_zero(rop); flint_free(numstr); return ans; } } flint-3.1.3/src/fmpz_poly_q/sub.c000066400000000000000000000106451461254215100167240ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "fmpz_poly_q.h" void fmpz_poly_q_sub_in_place(fmpz_poly_q_t rop, const fmpz_poly_q_t op) { if (rop == op) { fmpz_poly_q_zero(rop); return; } fmpz_poly_q_neg(rop, rop); fmpz_poly_q_add_in_place(rop, op); fmpz_poly_q_neg(rop, rop); } void fmpz_poly_q_sub(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { fmpz_poly_t d, r2, s2; if (fmpz_poly_is_zero(op1->num)) { fmpz_poly_q_neg(rop, op2); return; } if (fmpz_poly_is_zero(op2->num)) { fmpz_poly_q_set(rop, op1); return; } if (op1 == op2) { fmpz_poly_q_zero(rop); return; } if (rop == op1) { fmpz_poly_q_sub_in_place(rop, op2); return; } if (rop == op2) { fmpz_poly_q_sub_in_place(rop, op1); fmpz_poly_q_neg(rop, rop); return; } /* From here on, we know that rop, op1 and op2 refer to distinct objects in memory, although as rational functions they may still be equal XXX: Do not maintain the remaining part of the function separately!!! Instead, note that this is very similar to the corresponding part of the summation code. */ /* Polynomials? */ if (fmpz_poly_length(op1->den) == 1 && fmpz_poly_length(op2->den) == 1) { const slong len1 = fmpz_poly_length(op1->num); const slong len2 = fmpz_poly_length(op2->num); fmpz_poly_fit_length(rop->num, FLINT_MAX(len1, len2)); _fmpq_poly_sub(rop->num->coeffs, rop->den->coeffs, op1->num->coeffs, op1->den->coeffs, len1, op2->num->coeffs, op2->den->coeffs, len2); _fmpz_poly_set_length(rop->num, FLINT_MAX(len1, len2)); _fmpz_poly_set_length(rop->den, 1); _fmpz_poly_normalise(rop->num); return; } /* Denominators equal to one? */ if (fmpz_poly_is_one(op1->den)) { fmpz_poly_mul(rop->num, op1->num, op2->den); fmpz_poly_sub(rop->num, rop->num, op2->num); fmpz_poly_set(rop->den, op2->den); return; } if (fmpz_poly_is_one(op2->den)) { fmpz_poly_mul(rop->num, op2->num, op1->den); fmpz_poly_sub(rop->num, op1->num, rop->num); fmpz_poly_set(rop->den, op1->den); return; } /* Henrici's algorithm for summation in quotient fields */ /* We begin by using rop->num as a temporary variable for the gcd of the two denominators' greatest common divisor */ fmpz_poly_gcd(rop->num, op1->den, op2->den); if (fmpz_poly_is_one(rop->num)) { fmpz_poly_mul(rop->num, op1->num, op2->den); fmpz_poly_mul(rop->den, op1->den, op2->num); /* Using rop->den as temp */ fmpz_poly_sub(rop->num, rop->num, rop->den); fmpz_poly_mul(rop->den, op1->den, op2->den); } else { /* We now copy rop->num into a new variable d, so we no longer need rop->num as a temporary variable */ fmpz_poly_init(d); fmpz_poly_swap(d, rop->num); fmpz_poly_init(r2); fmpz_poly_init(s2); fmpz_poly_divexact(r2, op1->den, d); /* +ve leading coeff */ fmpz_poly_divexact(s2, op2->den, d); /* +ve leading coeff */ fmpz_poly_mul(rop->num, op1->num, s2); fmpz_poly_mul(rop->den, op2->num, r2); /* Using rop->den as temp */ fmpz_poly_sub(rop->num, rop->num, rop->den); if (fmpz_poly_degree(rop->num) < 0) { fmpz_poly_zero(rop->den); fmpz_poly_set_coeff_si(rop->den, 0, 1); } else { fmpz_poly_mul(rop->den, op1->den, s2); fmpz_poly_gcd(r2, rop->num, d); if (!fmpz_poly_is_one(r2)) { fmpz_poly_divexact(rop->num, rop->num, r2); fmpz_poly_divexact(rop->den, rop->den, r2); } } fmpz_poly_clear(d); fmpz_poly_clear(r2); fmpz_poly_clear(s2); } } flint-3.1.3/src/fmpz_poly_q/submul.c000066400000000000000000000012651461254215100174400ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_submul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { fmpz_poly_q_t temp; fmpz_poly_q_init(temp); fmpz_poly_q_mul(temp, op1, op2); fmpz_poly_q_sub(rop, rop, temp); fmpz_poly_q_clear(temp); } flint-3.1.3/src/fmpz_poly_q/swap.c000066400000000000000000000012771461254215100171060ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_swap(fmpz_poly_q_t op1, fmpz_poly_q_t op2) { if (op1 != op2) { fmpz_poly_struct *t; t = op1->num; op1->num = op2->num; op2->num = t; t = op1->den; op1->den = op2->den; op2->den = t; } } flint-3.1.3/src/fmpz_poly_q/test/000077500000000000000000000000001461254215100167405ustar00rootroot00000000000000flint-3.1.3/src/fmpz_poly_q/test/main.c000066400000000000000000000042341461254215100200330ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-addmul.c" #include "t-all.c" #include "t-derivative.c" #include "t-div.c" #include "t-evaluate_fmpq.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-mul.c" #include "t-neg.c" #include "t-pow.c" #include "t-scalar_div_fmpq.c" #include "t-scalar_div_fmpz.c" #include "t-scalar_div_si.c" #include "t-scalar_mul_fmpq.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_si.c" #include "t-set_equal.c" #include "t-set_si_equal.c" #include "t-sub.c" #include "t-submul.c" #include "t-swap.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_poly_q_add), TEST_FUNCTION(fmpz_poly_q_addmul), TEST_FUNCTION(fmpz_poly_q_all), TEST_FUNCTION(fmpz_poly_q_derivative), TEST_FUNCTION(fmpz_poly_q_div), TEST_FUNCTION(fmpz_poly_q_evaluate_fmpq), TEST_FUNCTION(fmpz_poly_q_init_clear), TEST_FUNCTION(fmpz_poly_q_inv), TEST_FUNCTION(fmpz_poly_q_mul), TEST_FUNCTION(fmpz_poly_q_neg), TEST_FUNCTION(fmpz_poly_q_pow), TEST_FUNCTION(fmpz_poly_q_scalar_div_fmpq), TEST_FUNCTION(fmpz_poly_q_scalar_div_fmpz), TEST_FUNCTION(fmpz_poly_q_scalar_div_si), TEST_FUNCTION(fmpz_poly_q_scalar_mul_fmpq), TEST_FUNCTION(fmpz_poly_q_scalar_mul_fmpz), TEST_FUNCTION(fmpz_poly_q_scalar_mul_si), TEST_FUNCTION(fmpz_poly_q_set_equal), TEST_FUNCTION(fmpz_poly_q_set_si_equal), TEST_FUNCTION(fmpz_poly_q_sub), TEST_FUNCTION(fmpz_poly_q_submul), TEST_FUNCTION(fmpz_poly_q_swap), TEST_FUNCTION(fmpz_poly_q_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_poly_q/test/t-add.c000066400000000000000000000067511461254215100201060ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_add, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_add(c, a, b); fmpz_poly_q_add(a, a, b); result = (fmpz_poly_q_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_add(c, a, b); fmpz_poly_q_add(b, a, b); result = fmpz_poly_q_equal(b, c); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check commutativity */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_add(c, a, b); fmpz_poly_q_add(d, b, a); result = fmpz_poly_q_equal(c, d) && fmpz_poly_q_is_canonical(c) && fmpz_poly_q_is_canonical(d); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fmpz_poly_q_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-addmul.c000066400000000000000000000047551461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_addmul, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_set(c, a); fmpz_poly_q_addmul(c, a, b); fmpz_poly_q_addmul(a, a, b); result = fmpz_poly_q_equal(a, c) && fmpz_poly_q_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_set(c, b); fmpz_poly_q_addmul(c, a, b); fmpz_poly_q_addmul(b, a, b); result = fmpz_poly_q_equal(b, c); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-all.c000066400000000000000000001225741461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "fmpq.h" #include "fmpz_poly_q.h" void test_set(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_set(rop, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_set: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_set_si(slong x, char * out) { int ans; fmpz_poly_q_t rop; char * res; fmpz_poly_q_init(rop); fmpz_poly_q_set_si(rop, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_set_si: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); flint_free(res); } void test_swap(char * in1, char * in2, char * out1, char * out2) { int ans; fmpz_poly_q_t op1, op2; char * res1; char * res2; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_swap(op1, op2); res1 = fmpz_poly_q_get_str(op1); res2 = fmpz_poly_q_get_str(op2); ans = !strcmp(out1, res1) && !strcmp(out2, res2); if (!ans) { flint_printf("test_swap: failed\n"); flint_printf(" Expected \"%s\" \"%s\", got \"%s\" \"%s\"\n", out1, out2, res1, res2); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res1); flint_free(res2); } void test_zero(char * in, char * out) { int ans; fmpz_poly_q_t op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_zero(op); res = fmpz_poly_q_get_str(op); ans = !strcmp(res, out); if (!ans) { flint_printf("test_zero: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); flint_free(res); } void test_neg(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_neg(rop, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(res, out); if (!ans) { flint_printf("test_neg: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_inv(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_inv(rop, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(res, out); if (!ans) { flint_printf("test_inv: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_inv_inplace(char * in, char * out) { int ans; fmpz_poly_q_t rop; char * res; fmpz_poly_q_init(rop); fmpz_poly_q_set_str(rop, in); fmpz_poly_q_inv(rop, rop); res = fmpz_poly_q_get_str(rop); ans = !strcmp(res, out); if (!ans) { flint_printf("test_inv_inplace: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); flint_free(res); } void test_is_zero(char * in, int out) { int ans; fmpz_poly_q_t op; int res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); res = fmpz_poly_q_is_zero(op); ans = (res == out); if (!ans) { flint_printf("test_equal: failed\n"); flint_printf(" Expected \"%d\", got \"%d\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); } void test_is_one(char * in, int out) { int ans; fmpz_poly_q_t op; int res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); res = fmpz_poly_q_is_one(op); ans = (res == out); if (!ans) { flint_printf("test_equal: failed\n"); flint_printf(" Expected \"%d\", got \"%d\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); } void test_equal(char * in1, char * in2, int out) { int ans; fmpz_poly_q_t op1, op2; int res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); res = fmpz_poly_q_equal(op1, op2); ans = (res == out); if (!ans) { flint_printf("test_equal: failed\n"); flint_printf(" Expected \"%d\", got \"%d\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); } void test_add(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t rop, op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_init(rop); fmpz_poly_q_add(rop, op1, op2); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_add: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); fmpz_poly_q_clear(rop); flint_free(res); } /* Runs in1 = in1 + in2 */ void test_add_in_place1(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_add(op1, op1, op2); res = fmpz_poly_q_get_str(op1); ans = !strcmp(out, res); if (!ans) { flint_printf("test_add_in_place1: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* Runs in2 = in1 + in2 */ void test_add_in_place2(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_add(op2, op1, op2); res = fmpz_poly_q_get_str(op2); ans = !strcmp(out, res); if (!ans) { flint_printf("test_add_in_place2: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* Runs out = in + in */ void test_add_in_place3(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_add(rop, op, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_add_in_place3: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); fmpz_poly_q_clear(op); flint_free(res); } void test_sub(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t rop, op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_init(rop); fmpz_poly_q_sub(rop, op1, op2); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_sub: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); fmpz_poly_q_clear(rop); flint_free(res); } /* in1 = in1 + in2 */ void test_sub_in_place1(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_sub(op1, op1, op2); res = fmpz_poly_q_get_str(op1); ans = !strcmp(out, res); if (!ans) { flint_printf("test_sub_in_place1: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* in2 = in1 + in2 */ void test_sub_in_place2(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_sub(op2, op1, op2); res = fmpz_poly_q_get_str(op2); ans = !strcmp(out, res); if (!ans) { flint_printf("test_sub_in_place2: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* Runs out = in - in */ void test_sub_in_place3(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_sub(rop, op, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_sub_in_place3: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); fmpz_poly_q_clear(op); flint_free(res); } void test_scalar_mul_si(char * in, slong x, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_scalar_mul_si(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_mul_si: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_mul_fmpz(char * in, fmpz_t x, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_scalar_mul_fmpz(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_mul_fmpz: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_mul_fmpq(char * in, fmpq_t x, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_scalar_mul_fmpq(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_mul_fmpq: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_div_si(char * in, slong x, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_scalar_div_si(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_div_si: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_div_fmpz(char * in, fmpz_t x, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_scalar_div_fmpz(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_div_fmpz: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_div_fmpq(char * in, fmpq_t x, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_scalar_div_fmpq(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_div_fmpq: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_mul(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t rop, op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_init(rop); fmpz_poly_q_mul(rop, op1, op2); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_mul: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); fmpz_poly_q_clear(rop); flint_free(res); } /* in1 = in1 * in2 */ void test_mul_in_place1(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_mul(op1, op1, op2); res = fmpz_poly_q_get_str(op1); ans = !strcmp(out, res); if (!ans) { flint_printf("test_mul_in_place1: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* in2 = in1 * in2 */ void test_mul_in_place2(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_mul(op2, op1, op2); res = fmpz_poly_q_get_str(op2); ans = !strcmp(out, res); if (!ans) { flint_printf("test_mul_in_place2: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* Runs out = in * in */ void test_mul_in_place3(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_mul(rop, op, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_mul_in_place3: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); fmpz_poly_q_clear(op); flint_free(res); } void test_div(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t rop, op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_init(rop); fmpz_poly_q_div(rop, op1, op2); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_div: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); fmpz_poly_q_clear(rop); flint_free(res); } /* in1 = in1 / in2 */ void test_div_in_place1(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_div(op1, op1, op2); res = fmpz_poly_q_get_str(op1); ans = !strcmp(out, res); if (!ans) { flint_printf("test_div_in_place1: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* in2 = in1 / in2 */ void test_div_in_place2(char * in1, char * in2, char * out) { int ans; fmpz_poly_q_t op1, op2; char * res; fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in1); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in2); fmpz_poly_q_div(op2, op1, op2); res = fmpz_poly_q_get_str(op2); ans = !strcmp(out, res); if (!ans) { flint_printf("test_div_in_place2: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } /* Runs out = in / in */ void test_div_in_place3(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_div(rop, op, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_div_in_place3: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); fmpz_poly_q_clear(op); flint_free(res); } void test_pow(char * in, ulong x, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_pow(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_pow: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_derivative(char * in, char * out) { int ans; fmpz_poly_q_t rop, op; char * res; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpz_poly_q_init(rop); fmpz_poly_q_derivative(rop, op); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_derivative: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_evaluate(char * in, int numa, int numb, char * out) { int ans, pole; fmpz_poly_q_t op; fmpq_t rop, a; char *res = NULL; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); fmpq_init(a); fmpq_set_si(a, numa, numb); fmpq_init(rop); pole = fmpz_poly_q_evaluate_fmpq(rop, op, a); if (pole && strcmp(out, "P")) { flint_printf("test_evaluate: failed\n"); flint_printf(" Expected \"%s\", got a pole\n", out); fflush(stdout); flint_abort(); } if (!pole && !strcmp(out, "P")) { res = fmpq_get_str(NULL, 10, rop); flint_printf("test_evaluate: failed\n"); flint_printf(" Expected a pole, got \"%s\"\n", res); fflush(stdout); flint_abort(); } if (!pole) { res = fmpq_get_str(NULL, 10, rop); ans = (strcmp(out, res) == 0); if (!ans) { flint_printf("test_evaluate: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } } fmpz_poly_q_clear(op); fmpq_clear(rop); fmpq_clear(a); flint_free(res); } void test_get_str_pretty(char * in, char * out) { int ans; fmpz_poly_q_t rop; char * res; fmpz_poly_q_init(rop); fmpz_poly_q_set_str(rop, in); res = fmpz_poly_q_get_str_pretty(rop, "t"); ans = !strcmp(out, res); if (!ans) { flint_printf("test_get_str_pretty: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); flint_free(res); } void test_addmul(char * in1, char * in2, char * in3, char * out) { int ans; fmpz_poly_q_t rop, op1, op2; char * res; fmpz_poly_q_init(rop); fmpz_poly_q_set_str(rop, in1); fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in2); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in3); fmpz_poly_q_addmul(rop, op1, op2); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_addmul: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } void test_submul(char * in1, char * in2, char * in3, char * out) { int ans; fmpz_poly_q_t rop, op1, op2; char * res; fmpz_poly_q_init(rop); fmpz_poly_q_set_str(rop, in1); fmpz_poly_q_init(op1); fmpz_poly_q_set_str(op1, in2); fmpz_poly_q_init(op2); fmpz_poly_q_set_str(op2, in3); fmpz_poly_q_submul(rop, op1, op2); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_submul: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(rop); fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } TEST_FUNCTION_START(fmpz_poly_q_all, state) { int ans; char *str, *strout; fmpz_poly_t zpoly; fmpz_poly_q_t qpoly1; fmpz_t fmpzzero, fmpzone, fmpztwo; fmpq_t fmpqzero, fmpqone, fmpqtwo, fmpqtwoinv; /* Accessing numerator and denominator ***********************************/ fmpz_poly_q_init(qpoly1); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); str = "2 -1 1"; strout = fmpz_poly_get_str(fmpz_poly_q_numref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_numref: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); flint_printf(" qpoly1 = \""), fmpz_poly_q_print(qpoly1), flint_printf("\"\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); str = "2 0 1"; strout = fmpz_poly_get_str(fmpz_poly_q_denref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_denref: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); fmpz_poly_set(zpoly, fmpz_poly_q_numref(qpoly1)); str = "2 -1 1"; strout = fmpz_poly_get_str(zpoly); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_get_num: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); fmpz_poly_set(zpoly, fmpz_poly_q_denref(qpoly1)); str = "2 0 1"; strout = fmpz_poly_get_str(zpoly); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_get_den: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "1 1/1 1"); fmpz_poly_set_str(zpoly, "2 0 1"); fmpz_poly_set(fmpz_poly_q_numref(qpoly1), zpoly); str = "2 0 1"; strout = fmpz_poly_get_str(fmpz_poly_q_numref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_set_num: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "1 1/1 1"); fmpz_poly_set_str(zpoly, "2 0 1"); fmpz_poly_set(fmpz_poly_q_denref(qpoly1), zpoly); str = "2 0 1"; strout = fmpz_poly_get_str(fmpz_poly_q_denref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_set_den: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); /* Canonicalise **********************************************************/ fmpz_poly_q_init(qpoly1); str = "2 -1 1/2 0 1"; fmpz_poly_q_set_str(qpoly1, str); strout = fmpz_poly_q_get_str(qpoly1); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_canonicalize: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); flint_free(strout); fmpz_poly_q_init(qpoly1); str = "2 -1 -1/2 0 1"; fmpz_poly_q_set_str(qpoly1, "2 1 1/2 0 -1"); strout = fmpz_poly_q_get_str(qpoly1); ans = !strcmp("2 -1 -1/2 0 1", strout); if (!ans) { flint_printf("test_canonicalize: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); fflush(stdout); flint_abort(); } flint_free(strout); fmpz_poly_q_clear(qpoly1); /* Initialization, memory management and basic operations ****************/ test_set("0", "0"); test_set("0/1 1", "0"); test_set("3 -1 0 1/2 0 1", "3 -1 0 1/2 0 1"); test_set("3 -1 0 1/2 1 1", "2 -1 1"); test_set_si(-1, "1 -1"); test_set_si(13, "1 13"); test_set_si(0, "0"); test_swap("3 -1 0 1/2 0 1", "1 2/1 3", "1 2/1 3", "3 -1 0 1/2 0 1"); test_zero("0", "0"); test_zero("0/1 1", "0"); test_zero("3 -1 0 1/2 0 1", "0"); test_neg("0", "0"); test_neg("1 1/1 2", "1 -1/1 2"); test_neg("3 -1 0 1/2 0 1", "3 1 0 -1/2 0 1"); test_inv("1 1/1 2", "1 2"); test_inv("3 -1 0 1/2 0 1", "2 0 1/3 -1 0 1"); test_inv("3 -1 0 -1/2 0 1", "2 0 -1/3 1 0 1"); test_inv_inplace("1 1/1 2", "1 2"); test_inv_inplace("3 -1 0 1/2 0 1", "2 0 1/3 -1 0 1"); test_inv_inplace("3 -1 0 -1/2 0 1", "2 0 -1/3 1 0 1"); test_is_zero("0", 1); test_is_zero("0/1 1", 1); test_is_zero("3 -1 0 1/2 0 1", 0); test_is_zero("3 -1 0 1/2 1 1", 0); test_is_one("0", 0); test_is_one("0/1 1", 0); test_is_one("1 1/1 1", 1); test_is_one("2 1 1/2 1 1", 1); test_is_one("3 -1 0 1/2 0 1", 0); test_equal("1 1/1 2", "1 1/1 2", 1); test_equal("1 1/1 2", "1 1/1 2", 1); test_equal("3 -1 0 1/2 1 1", "2 -1 1", 1); test_equal("3 -1 0 1/2 -1 1", "2 -1 1", 0); /* Addition and subtraction **********************************************/ test_add("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 1 0 1/4 0 1 0 1"); test_add("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 3 -2 1/2 -1 1"); test_add("0/2 1 1", "1 2/1 1", "1 2"); test_add("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_add("2 1 1/1 1", "2 -1 1/1 1", "2 0 2"); test_add("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 -1 2 2/3 0 -1 1"); test_add("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 7 12 7 1/3 2 3 1"); test_add("2 1 1/2 -1 1", "2 1 1", "3 0 1 1/2 -1 1"); test_add("1 1/2 1 1", "2 0 1/2 1 1", "1 1"); test_add("2 1 1/3 4 -4 1", "1 1/2 -2 1", "2 -1 2/3 4 -4 1"); test_add("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "0"); test_add("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2"); test_add("1 1/3 3 5 2", "1 1/3 6 7 2", "1 1/3 2 3 1"); test_add_in_place1("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 1 0 1/4 0 1 0 1"); test_add_in_place1("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 3 -2 1/2 -1 1"); test_add_in_place1("0/2 1 1", "1 2/1 1", "1 2"); test_add_in_place1("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_add_in_place1("2 1 1/1 1", "2 -1 1/1 1", "2 0 2"); test_add_in_place1("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 -1 2 2/3 0 -1 1"); test_add_in_place1("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 7 12 7 1/3 2 3 1"); test_add_in_place1("2 1 1/2 -1 1", "2 1 1", "3 0 1 1/2 -1 1"); test_add_in_place1("1 1/2 1 1", "2 0 1/2 1 1", "1 1"); test_add_in_place1("2 1 1/3 4 -4 1", "1 1/2 -2 1", "2 -1 2/3 4 -4 1"); test_add_in_place1("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "0"); test_add_in_place1("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2"); test_add_in_place2("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 1 0 1/4 0 1 0 1"); test_add_in_place2("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 3 -2 1/2 -1 1"); test_add_in_place2("0/2 1 1", "1 2/1 1", "1 2"); test_add_in_place2("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_add_in_place2("2 1 1/1 1", "2 -1 1/1 1", "2 0 2"); test_add_in_place2("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 -1 2 2/3 0 -1 1"); test_add_in_place2("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 7 12 7 1/3 2 3 1"); test_add_in_place2("2 1 1/2 -1 1", "2 1 1", "3 0 1 1/2 -1 1"); test_add_in_place2("1 1/2 1 1", "2 0 1/2 1 1", "1 1"); test_add_in_place2("2 1 1/3 4 -4 1", "1 1/2 -2 1", "2 -1 2/3 4 -4 1"); test_add_in_place2("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "0"); test_add_in_place2("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2"); test_add_in_place3("2 1 1", "2 2 2"); test_add_in_place3("2 1 1/1 2", "2 1 1"); test_sub("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub("0/2 1 1", "1 2/1 1", "1 -2"); test_sub("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub("2 -1 1/2 0 1", "1 1", "1 -1/2 0 1"); test_sub("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub("0/2 1 1", "1 2/1 1", "1 -2"); test_sub("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub("2 1 1/2 -1 1", "2 1 1", "3 2 1 -1/2 -1 1"); test_sub("1 1/2 1 1", "2 0 1/2 1 1", "2 1 -1/2 1 1"); test_sub("2 1 1/3 4 -4 1", "1 1/2 -2 1", "1 3/3 4 -4 1"); test_sub("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "2 0 2/2 1 1"); test_sub("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2/2 0 1"); test_sub("1 1/3 3 5 2", "1 1/3 6 7 2", "1 1/4 6 13 9 2"); test_sub("2 1 1/2 0 2", "2 1 1/2 0 2", "0"); test_sub("2 -1 2/2 0 1", "2 -1 1/2 0 1", "1 1"); test_sub_in_place1("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub_in_place1("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub_in_place1("0/2 1 1", "1 2/1 1", "1 -2"); test_sub_in_place1("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub_in_place1("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub_in_place1("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub_in_place1("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub_in_place2("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub_in_place2("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub_in_place2("0/2 1 1", "1 2/1 1", "1 -2"); test_sub_in_place2("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub_in_place2("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub_in_place2("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub_in_place2("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub_in_place3("2 -1 1/2 2 1", "0"); test_addmul("1 1/2 0 2", "2 3 1/1 4", "3 1 0 1/4 -2 0 0 1", "5 -4 3 1 5 1/5 0 -8 0 0 4"); test_submul("1 1/2 0 2", "2 3 1/1 4", "3 1 0 1/4 -2 0 0 1", "5 -4 -3 -1 -1 -1/5 0 -8 0 0 4"); /* Scalar multiplication and division ************************************/ fmpz_init_set_si(fmpzzero, 0); fmpz_init_set_si(fmpzone, 1); fmpz_init_set_si(fmpztwo, 2); fmpq_init(fmpqzero); fmpq_set_si(fmpqzero, 0, 1); fmpq_init(fmpqone); fmpq_set_si(fmpqone, 1, 1); fmpq_init(fmpqtwo); fmpq_set_si(fmpqtwo, 2, 1); fmpq_init(fmpqtwoinv); fmpq_set_si(fmpqtwoinv, 1, 2); test_scalar_mul_si("0", 1, "0"); test_scalar_mul_si("0", 0, "0"); test_scalar_mul_si("1 2", 0, "0"); test_scalar_mul_si("1 1/1 2", -2, "1 -1"); test_scalar_mul_si("2 1 1/2 -2 3", 5, "2 5 5/2 -2 3"); test_scalar_mul_si("2 1 1/2 -2 2", 3, "2 3 3/2 -2 2"); test_scalar_mul_fmpz("0", fmpzone, "0"); test_scalar_mul_fmpz("0", fmpzzero, "0"); test_scalar_mul_fmpz("1 2", fmpzzero, "0"); test_scalar_mul_fmpz("1 1/1 2", fmpztwo, "1 1"); test_scalar_mul_fmpq("0", fmpqone, "0"); test_scalar_mul_fmpq("0", fmpqzero, "0"); test_scalar_mul_fmpq("1 2", fmpqzero, "0"); test_scalar_mul_fmpq("1 1/1 2", fmpqtwo, "1 1"); test_scalar_mul_fmpq("1 -2/1 1", fmpqtwoinv, "1 -1"); test_scalar_div_si("0", 1, "0"); test_scalar_div_si("1 2", 2, "1 1"); test_scalar_div_si("1 1/1 2", -2, "1 -1/1 4"); test_scalar_div_si("3 -5 0 3/2 1 1", 2, "3 -5 0 3/2 2 2"); test_scalar_div_si("3 2 8 4/2 0 1", 3, "3 2 8 4/2 0 3"); test_scalar_div_si("3 2 8 4/2 0 1", -3, "3 -2 -8 -4/2 0 3"); test_scalar_div_si("3 -27 0 9/2 0 1", -3, "3 9 0 -3/2 0 1"); test_scalar_div_fmpz("0", fmpzone, "0"); test_scalar_div_fmpz("1 2", fmpztwo, "1 1"); test_scalar_div_fmpz("1 1/1 2", fmpztwo, "1 1/1 4"); test_scalar_div_fmpq("0", fmpqone, "0"); test_scalar_div_fmpq("1 2", fmpqone, "1 2"); test_scalar_div_fmpq("1 1/1 2", fmpqtwo, "1 1/1 4"); test_scalar_div_fmpq("1 -2/1 1", fmpqtwoinv, "1 -4"); fmpz_clear(fmpzzero); fmpz_clear(fmpzone); fmpz_clear(fmpztwo); fmpq_clear(fmpqzero); fmpq_clear(fmpqone); fmpq_clear(fmpqtwo); fmpq_clear(fmpqtwoinv); /* Multiplication, division and powing *********************************/ test_mul("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "1 -1"); test_mul("3 -1 0 1/2 1 1", "1 2/2 -1 1", "1 2"); test_mul("0/2 1 1", "1 2/1 1", "0"); test_mul("1 -3/1 4", "0/3 1 0 1", "0"); test_mul("2 1 1/1 1", "2 -1 1/1 1", "3 -1 0 1"); test_mul("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 2 3 1/3 0 -1 1"); test_mul("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "3 -2 1 1/2 1 1"); test_mul_in_place1("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "1 -1"); test_mul_in_place1("3 -1 0 1/2 1 1", "1 2/2 -1 1", "1 2"); test_mul_in_place1("0/2 1 1", "1 2/1 1", "0"); test_mul_in_place1("1 -3/1 4", "0/3 1 0 1", "0"); test_mul_in_place1("2 1 1/1 1", "2 -1 1/1 1", "3 -1 0 1"); test_mul_in_place1("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 2 3 1/3 0 -1 1"); test_mul_in_place1("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "3 -2 1 1/2 1 1"); test_mul_in_place2("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "1 -1"); test_mul_in_place2("3 -1 0 1/2 1 1", "1 2/2 -1 1", "1 2"); test_mul_in_place2("0/2 1 1", "1 2/1 1", "0"); test_mul_in_place2("1 -3/1 4", "0/3 1 0 1", "0"); test_mul_in_place2("2 1 1/1 1", "2 -1 1/1 1", "3 -1 0 1"); test_mul_in_place2("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 2 3 1/3 0 -1 1"); test_mul_in_place2("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "3 -2 1 1/2 1 1"); test_mul_in_place3("2 0 1/2 1 1", "3 0 0 1/3 1 2 1"); test_div("3 -1 0 1/1 2", "2 1 1/1 1", "2 -1 1/1 2"); test_div("0/2 1 1", "2 1 1/1 1", "0"); test_div("3 -1 0 1/1 4", "2 -1 -1/1 2", "2 1 -1/1 2"); test_div("2 1 1", "2 1 -1/2 1 -1", "2 1 1"); test_div("2 1 1/3 4 4 1", "2 -1 1/3 6 5 1", "3 3 4 1/3 -2 1 1"); test_div_in_place1("3 -1 0 1/1 2", "2 1 1/1 1", "2 -1 1/1 2"); test_div_in_place1("0/2 1 1", "2 1 1/1 1", "0"); test_div_in_place1("3 -1 0 1/1 4", "2 -1 -1/1 2", "2 1 -1/1 2"); test_div_in_place1("2 1 1", "2 1 -1/2 1 -1", "2 1 1"); test_div_in_place1("2 1 1/3 4 4 1", "2 -1 1/3 6 5 1", "3 3 4 1/3 -2 1 1"); test_div_in_place1("0", "1 2/2 3 5", "0"); test_div_in_place2("3 -1 0 1/1 2", "2 1 1/1 1", "2 -1 1/1 2"); test_div_in_place2("0/2 1 1", "2 1 1/1 1", "0"); test_div_in_place2("3 -1 0 1/1 4", "2 -1 -1/1 2", "2 1 -1/1 2"); test_div_in_place2("2 1 1", "2 1 -1/2 1 -1", "2 1 1"); test_div_in_place2("2 1 1/3 4 4 1", "2 -1 1/3 6 5 1", "3 3 4 1/3 -2 1 1"); test_div_in_place3("3 -1 0 1/1 2", "1 1"); test_pow("2 0 -1/1 2", 3, "4 0 0 0 -1/1 8"); test_pow("0", 0, "1 1"); test_pow("2 1 -1", 0, "1 1"); test_pow("2 1 1/2 0 1", 0, "1 1"); /* Derivative ************************************************************/ test_derivative("0", "0"); test_derivative("1 2", "0"); test_derivative("1 -1/1 2", "0"); test_derivative("2 0 1", "1 1"); test_derivative("3 1 0 1", "2 0 2"); test_derivative("1 1/2 0 1", "1 -1/3 0 0 1"); test_derivative("2 2 1/2 -1 1", "1 -3/3 1 -2 1"); test_derivative("2 0 1/3 1 2 1", "2 1 -1/4 1 3 3 1"); /* Bug which allowed constant factors */ test_derivative("3 5 1 -2/2 10 2", "3 0 -10 -1/3 25 10 1"); /* Evaluation ************************************************************/ test_evaluate("1 1/1 2", -2, 3, "1/2"); test_evaluate("3 1 0 1/2 0 1", -1, 2, "-5/2"); test_evaluate("2 3 1/2 -1 1", 1, 1, "P"); test_evaluate("2 3 1/2 -1 1", 2, 3, "-11"); test_evaluate("2 3 1/2 -1 2", 1, 2, "P"); test_evaluate("2 1 1/2 -1 1", 2, 1, "3"); /* String methods ********************************************************/ fmpz_poly_q_init(qpoly1); ans = fmpz_poly_q_set_str(qpoly1, "1 3/xyz"); if ((ans == 0) || !fmpz_poly_q_is_zero(qpoly1)) { flint_printf("test_set_str: failed\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_q_init(qpoly1); ans = fmpz_poly_q_set_str(qpoly1, "abc/1 3"); if ((ans == 0) || !fmpz_poly_q_is_zero(qpoly1)) { flint_printf("test_set_str: failed\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_q_init(qpoly1); ans = fmpz_poly_q_set_str(qpoly1, "abc/xyz"); if ((ans == 0) || !fmpz_poly_q_is_zero(qpoly1)) { flint_printf("test_set_str: failed\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(qpoly1); test_get_str_pretty("1 -3", "-3"); test_get_str_pretty("3 1 2 1", "t^2+2*t+1"); test_get_str_pretty("1 -2/2 1 1", "-2/(t+1)"); test_get_str_pretty("2 1 1/2 -1 1", "(t+1)/(t-1)"); test_get_str_pretty("2 1 1/1 2", "(t+1)/2"); test_get_str_pretty("1 1/1 2", "1/2"); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-derivative.c000066400000000000000000000066001461254215100215110ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_derivative, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_derivative(b, a); fmpz_poly_q_derivative(a, a); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } /* Check constants have derivative zero */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_set_si(a, z_randtest(state)); fmpz_poly_q_derivative(b, a); result = fmpz_poly_q_is_zero(b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } /* Check (f g)' = f' g + f g' */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d, lhs, rhs; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_poly_q_init(lhs); fmpz_poly_q_init(rhs); fmpz_poly_q_randtest(a, state, n_randint(state, 20), 20, n_randint(state, 20), 20); fmpz_poly_q_randtest(b, state, n_randint(state, 20), 20, n_randint(state, 20), 20); fmpz_poly_q_mul(lhs, a, b); fmpz_poly_q_derivative(lhs, lhs); fmpz_poly_q_derivative(c, a); fmpz_poly_q_derivative(d, b); fmpz_poly_q_mul(c, c, b); fmpz_poly_q_mul(d, a, d); fmpz_poly_q_add(rhs, c, d); result = fmpz_poly_q_equal(lhs, rhs) && fmpz_poly_q_is_canonical(lhs) && fmpz_poly_q_is_canonical(rhs); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(lhs), flint_printf("\n\n"); fmpz_poly_q_print(rhs), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); fmpz_poly_q_clear(lhs); fmpz_poly_q_clear(rhs); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-div.c000066400000000000000000000067661461254215100201460ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_div, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest_not_zero(c, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_div(a, b, c); fmpz_poly_q_div(b, b, c); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest_not_zero(c, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_div(a, b, c); fmpz_poly_q_div(c, b, c); result = (fmpz_poly_q_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check (c/b)+(d/b) = (c+d)/b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a1, a2, b, c, d; fmpz_poly_q_init(a1); fmpz_poly_q_init(a2); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_poly_q_randtest_not_zero(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(c, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(d, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_div(a1, c, b); fmpz_poly_q_div(a2, d, b); fmpz_poly_q_add(a1, a1, a2); fmpz_poly_q_add(c, c, d); fmpz_poly_q_div(a2, c, b); result = fmpz_poly_q_equal(a1, a2) && fmpz_poly_q_is_canonical(a1); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a1), flint_printf("\n\n"); fmpz_poly_q_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a1); fmpz_poly_q_clear(a2); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-evaluate_fmpq.c000066400000000000000000000041161461254215100222000ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_evaluate_fmpq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { int ans1, ans2; fmpq_t a, b; fmpz_t num, den; fmpz_poly_q_t f; fmpq_init(a); fmpq_init(b); fmpz_init(num); fmpz_init(den); fmpz_poly_q_init(f); fmpz_poly_q_randtest(f, state, n_randint(state, 10), 10, n_randint(state, 10), 10); fmpz_randtest(num, state, 50); fmpz_randtest_not_zero(den, state, 50); fmpz_set(fmpq_numref(a), num); fmpz_set(fmpq_denref(a), den); fmpq_canonicalise(a); ans1 = fmpz_poly_q_evaluate_fmpq(b, f, a); ans2 = fmpz_poly_q_evaluate_fmpq(a, f, a); result = (ans1 == ans2) && fmpq_equal(a, b); if (!result) { flint_printf("FAIL:\n"); flint_printf("f = "), fmpz_poly_q_print(f), flint_printf("\n"); flint_printf("num = "), fmpz_print(num), flint_printf("\n"); flint_printf("den = "), fmpz_print(den), flint_printf("\n"); flint_printf("a = "); fmpq_print(a); flint_printf("\n"); flint_printf("b = "); fmpq_print(b); flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } fmpq_clear(a); fmpq_clear(b); fmpz_clear(num); fmpz_clear(den); fmpz_poly_q_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-init_clear.c000066400000000000000000000017751461254215100214700ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_init_clear, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a; slong len1 = n_randint(state, 50); slong len2 = n_randint(state, 50); flint_bitcnt_t bits1 = n_randint(state, 50); flint_bitcnt_t bits2 = n_randint(state, 50); fmpz_poly_q_init(a); fmpz_poly_q_randtest(a, state, len1, bits1, len2, bits2); fmpz_poly_q_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-inv.c000066400000000000000000000037761461254215100201560ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_inv, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest_not_zero(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_inv(b, a); fmpz_poly_q_inv(a, a); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } /* Check a * (1/a) == 1 */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest_not_zero(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_inv(b, a); fmpz_poly_q_mul(b, a, b); result = fmpz_poly_q_is_one(b) && fmpz_poly_q_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-mul.c000066400000000000000000000067331461254215100201530ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_mul, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(c, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_mul(a, b, c); fmpz_poly_q_mul(b, b, c); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(c, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_mul(a, b, c); fmpz_poly_q_mul(c, b, c); result = (fmpz_poly_q_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a1, a2, b, c, d; fmpz_poly_q_init(a1); fmpz_poly_q_init(a2); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(c, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(d, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_mul(a1, b, c); fmpz_poly_q_mul(a2, b, d); fmpz_poly_q_add(a1, a1, a2); fmpz_poly_q_add(c, c, d); fmpz_poly_q_mul(a2, b, c); result = fmpz_poly_q_equal(a1, a2) && fmpz_poly_q_is_canonical(a1); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a1), flint_printf("\n\n"); fmpz_poly_q_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a1); fmpz_poly_q_clear(a2); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-neg.c000066400000000000000000000037541461254215100201270ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_neg, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_neg(b, a); fmpz_poly_q_neg(a, a); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } /* Check a + (-a) == 0 */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_neg(b, a); fmpz_poly_q_add(b, a, b); result = fmpz_poly_q_is_zero(b) && fmpz_poly_q_is_canonical(b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-pow.c000066400000000000000000000025621461254215100201570ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_pow, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; ulong e; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(b, state, n_randint(state, 10), 10, n_randint(state, 10), 10); e = n_randint(state, 10); fmpz_poly_q_pow(a, b, e); fmpz_poly_q_pow(b, b, e); result = fmpz_poly_q_equal(a, b) && fmpz_poly_q_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-scalar_div_fmpq.c000066400000000000000000000066151461254215100225070ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_scalar_div_fmpq, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_t x1, x2; fmpq_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x1); fmpz_init(x2); fmpq_init(y); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest_not_zero(x1, state, 50); fmpz_randtest_not_zero(x2, state, 50); fmpz_set(fmpq_numref(y), x1); fmpz_set(fmpq_denref(y), x2); fmpq_canonicalise(y); fmpz_poly_q_scalar_div_fmpq(a, b, y); fmpz_poly_q_scalar_div_fmpq(b, b, y); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x1); fmpz_clear(x2); fmpq_clear(y); } /* Check that x (a + b) == x * a + x * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d; fmpz_t x1, x2; fmpq_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_init(x1); fmpz_init(x2); fmpq_init(y); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest_not_zero(x1, state, 50); fmpz_randtest_not_zero(x2, state, 50); fmpz_set(fmpq_numref(y), x1); fmpz_set(fmpq_denref(y), x2); fmpq_canonicalise(y); fmpz_poly_q_scalar_div_fmpq(c, a, y); fmpz_poly_q_scalar_div_fmpq(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_div_fmpq(c, c, y); result = fmpz_poly_q_equal(c, d) && fmpz_poly_q_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_q_print(c), flint_printf("\n\n"); flint_printf("d = "), fmpz_poly_q_print(d), flint_printf("\n\n"); gmp_printf("y = %Qd\n\n", y); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); fmpz_clear(x1); fmpz_clear(x2); fmpq_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-scalar_div_fmpz.c000066400000000000000000000060741461254215100225170ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_scalar_div_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_t x; fmpz_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x); fmpz_init(y); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest_not_zero(x, state, 50); fmpz_set(y, x); fmpz_poly_q_scalar_div_fmpz(a, b, y); fmpz_poly_q_scalar_div_fmpz(b, b, y); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x); fmpz_clear(y); } /* Check that (a + b) / x == a / x + b / x */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d; fmpz_t x; fmpz_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_init(x); fmpz_init(y); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest_not_zero(x, state, 50); fmpz_set(y, x); fmpz_poly_q_scalar_div_fmpz(c, a, y); fmpz_poly_q_scalar_div_fmpz(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_div_fmpz(c, c, y); result = fmpz_poly_q_equal(c, d) && fmpz_poly_q_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_q_print(c), flint_printf("\n\n"); flint_printf("d = "), fmpz_poly_q_print(d), flint_printf("\n\n"); flint_printf("y = "); fmpz_print(y); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); fmpz_clear(x); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-scalar_div_si.c000066400000000000000000000055241461254215100221550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_scalar_div_si, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; slong x; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); x = z_randtest_not_zero(state); fmpz_poly_q_scalar_div_si(a, b, x); fmpz_poly_q_scalar_div_si(b, b, x); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } /* Check that (a + b) / x == a / x + b / x */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d; slong x; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); x = z_randtest_not_zero(state); fmpz_poly_q_scalar_div_si(c, a, x); fmpz_poly_q_scalar_div_si(d, b, x); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_div_si(c, c, x); result = fmpz_poly_q_equal(c, d) && fmpz_poly_q_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_q_print(c), flint_printf("\n\n"); flint_printf("d = "), fmpz_poly_q_print(d), flint_printf("\n\n"); flint_printf("x = %wd\n\n", x); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-scalar_mul_fmpq.c000066400000000000000000000066301461254215100225170ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_scalar_mul_fmpq, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_t x1, x2; fmpq_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x1); fmpz_init(x2); fmpq_init(y); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest(x1, state, 50); fmpz_randtest_not_zero(x2, state, 50); fmpz_set(fmpq_numref(y), x1); fmpz_set(fmpq_denref(y), x2); fmpq_canonicalise(y); fmpz_poly_q_scalar_mul_fmpq(a, b, y); fmpz_poly_q_scalar_mul_fmpq(b, b, y); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x1); fmpz_clear(x2); fmpq_clear(y); } /* Check that x (a + b) == x * a + x * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d; fmpz_t x1, x2; fmpq_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_init(x1); fmpz_init(x2); fmpq_init(y); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest(x1, state, 50); fmpz_randtest_not_zero(x2, state, 50); fmpz_set(fmpq_numref(y), x1); fmpz_set(fmpq_denref(y), x2); fmpq_canonicalise(y); fmpz_poly_q_scalar_mul_fmpq(c, a, y); fmpz_poly_q_scalar_mul_fmpq(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_mul_fmpq(c, c, y); result = fmpz_poly_q_equal(c, d) && fmpz_poly_q_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_q_print(c), flint_printf("\n\n"); flint_printf("d = "), fmpz_poly_q_print(d), flint_printf("\n\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); fmpz_clear(x1); fmpz_clear(x2); fmpq_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-scalar_mul_fmpz.c000066400000000000000000000060501461254215100225240ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_scalar_mul_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_t x; fmpz_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x); fmpz_init(y); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest(x, state, 50); fmpz_set(y, x); fmpz_poly_q_scalar_mul_fmpz(a, b, y); fmpz_poly_q_scalar_mul_fmpz(b, b, y); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x); fmpz_clear(y); } /* Check that x (a + b) == x * a + x * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d; fmpz_t x; fmpz_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_init(x); fmpz_init(y); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest(x, state, 50); fmpz_set(y, x); fmpz_poly_q_scalar_mul_fmpz(c, a, y); fmpz_poly_q_scalar_mul_fmpz(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_mul_fmpz(c, c, y); result = fmpz_poly_q_equal(c, d) && fmpz_poly_q_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_q_print(c), flint_printf("\n\n"); flint_printf("d = "), fmpz_poly_q_print(d), flint_printf("\n\n"); flint_printf("y = "), fmpz_print(y), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); fmpz_clear(x); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-scalar_mul_si.c000066400000000000000000000053601461254215100221660ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_scalar_mul_si, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; slong x; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); x = z_randtest(state); fmpz_poly_q_scalar_mul_si(a, b, x); fmpz_poly_q_scalar_mul_si(b, b, x); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } /* Check that x (a + b) == x * a + x * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c, d; slong x; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_init(d); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); x = z_randtest(state); fmpz_poly_q_scalar_mul_si(c, a, x); fmpz_poly_q_scalar_mul_si(d, b, x); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_mul_si(c, c, x); result = fmpz_poly_q_equal(c, d) && fmpz_poly_q_is_canonical(c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); flint_printf("c = "), fmpz_poly_q_print(c), flint_printf("\n\n"); flint_printf("d = "), fmpz_poly_q_print(d), flint_printf("\n\n"); flint_printf("x = %wd\n\n", x); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-set_equal.c000066400000000000000000000044501461254215100213320ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_set_equal, state) { int i, result; /* Equal polynomials */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_set(b, a); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; slong coeff = n_randint(state, 50); fmpz_t x1, x2; fmpz_init(x1); fmpz_init(x2); fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_set(b, a); fmpz_poly_get_coeff_fmpz(x2, fmpz_poly_q_numref(b), coeff); do fmpz_randtest(x1, state, 50); while (fmpz_equal(x1, x2)); fmpz_poly_set_coeff_fmpz(fmpz_poly_q_numref(b), coeff, x1); fmpz_poly_q_canonicalise(b); result = !fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(x1); fmpz_clear(x2); fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-set_si_equal.c000066400000000000000000000042611461254215100220250ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_set_si_equal, state) { int i, result; /* Equal polynomials */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; slong n; fmpz_poly_q_init(a); fmpz_poly_q_init(b); n = z_randtest(state); fmpz_poly_q_set_si(a, n); fmpz_poly_q_set(b, a); result = fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n\n", n); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; slong m, n; fmpz_poly_q_init(a); fmpz_poly_q_init(b); m = z_randtest(state); n = z_randtest(state); while (m == n) n = z_randtest(state); fmpz_poly_q_set_si(a, m); fmpz_poly_q_set_si(b, n); result = !fmpz_poly_q_equal(a, b); if (!result) { flint_printf("FAIL:\n"); flint_printf("m = %wd\n\n", m); flint_printf("n = %wd\n\n", n); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); flint_printf("b = "), fmpz_poly_q_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-sub.c000066400000000000000000000046031461254215100201410ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_sub, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_sub(c, a, b); fmpz_poly_q_sub(a, a, b); result = (fmpz_poly_q_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_sub(c, a, b); fmpz_poly_q_sub(b, a, b); result = fmpz_poly_q_equal(b, c); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-submul.c000066400000000000000000000047551461254215100206670ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_submul, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_set(c, a); fmpz_poly_q_submul(c, a, b); fmpz_poly_q_submul(a, a, b); result = fmpz_poly_q_equal(a, c) && fmpz_poly_q_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_set(c, b); fmpz_poly_q_submul(c, a, b); fmpz_poly_q_submul(b, a, b); result = fmpz_poly_q_equal(b, c); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-swap.c000066400000000000000000000027121461254215100203210ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_swap, state) { int i, result; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b, c; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_poly_q_init(c); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_set(c, b); fmpz_poly_q_swap(a, b); result = fmpz_poly_q_equal(a, c); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_q_print(a), flint_printf("\n\n"); fmpz_poly_q_print(b), flint_printf("\n\n"); fmpz_poly_q_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_poly_q/test/t-zero.c000066400000000000000000000022231461254215100203230ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly_q.h" TEST_FUNCTION_START(fmpz_poly_q_zero, state) { int i, result; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a; fmpz_poly_q_init(a); fmpz_poly_q_randtest(a, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_poly_q_zero(a); result = fmpz_poly_q_is_zero(a) && fmpz_poly_q_is_canonical(a); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_poly_q_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_q_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_types.h000066400000000000000000000045001461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_TYPES_H #define FMPZ_TYPES_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif typedef struct { int sign; fmpz * p; ulong * exp; slong alloc; slong num; } fmpz_factor_struct; typedef fmpz_factor_struct fmpz_factor_t[1]; typedef struct { mp_ptr dinv; slong n; flint_bitcnt_t norm; } fmpz_preinvn_struct; typedef fmpz_preinvn_struct fmpz_preinvn_t[1]; typedef struct { fmpz * coeffs; slong alloc; slong length; } fmpz_poly_struct; typedef fmpz_poly_struct fmpz_poly_t[1]; typedef struct { fmpz c; fmpz_poly_struct *p; slong *exp; slong num; slong alloc; } fmpz_poly_factor_struct; typedef fmpz_poly_factor_struct fmpz_poly_factor_t[1]; typedef struct { fmpz * entries; slong r; slong c; fmpz ** rows; } fmpz_mat_struct; typedef fmpz_mat_struct fmpz_mat_t[1]; typedef struct { fmpz_poly_struct * entries; slong r; slong c; fmpz_poly_struct ** rows; } fmpz_poly_mat_struct; typedef fmpz_poly_mat_struct fmpz_poly_mat_t[1]; typedef struct { fmpz * coeffs; /* alloc fmpzs */ ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* number of bits per exponent */ } fmpz_mpoly_struct; typedef fmpz_mpoly_struct fmpz_mpoly_t[1]; typedef struct { fmpz_t constant; fmpz_t constant_den; /* should be one after normal operations */ fmpz_mpoly_struct * poly; fmpz * exp; slong num; slong alloc; } fmpz_mpoly_factor_struct; typedef fmpz_mpoly_factor_struct fmpz_mpoly_factor_t[1]; typedef struct { fmpz_poly_struct *num; fmpz_poly_struct *den; } fmpz_poly_q_struct; typedef fmpz_poly_q_struct fmpz_poly_q_t[1]; typedef struct { fmpz_mpoly_struct num; fmpz_mpoly_struct den; } fmpz_mpoly_q_struct; typedef fmpz_mpoly_q_struct fmpz_mpoly_q_t[1]; typedef struct { fmpz a; fmpz b; } fmpzi_struct; typedef fmpzi_struct fmpzi_t[1]; #ifdef __cplusplus } #endif #endif /* FMPZ_TYPES_H */ flint-3.1.3/src/fmpz_vec.h000066400000000000000000000235531461254215100154140ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_VEC_H #define FMPZ_VEC_H #ifdef FMPZ_VEC_INLINES_C #define FMPZ_VEC_INLINE #else #define FMPZ_VEC_INLINE static inline #endif #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif #define FMPZ_VEC_NORM(vec, i) \ do { \ while ((i) && vec[(i) - 1] == WORD(0)) \ (i)--; \ } while (0) #define FMPZ_VEC_SWAP(vec1, len1, vec2, len2) \ do { \ fmpz *__t; \ slong __tn; \ __t = (vec1); \ (vec1) = (vec2); \ (vec2) = __t; \ __tn = (len1); \ (len1) = (len2); \ (len2) = __tn; \ } while (0); /* makes assignment to vec */ #define FMPZ_VEC_TMP_INIT(vec, len) \ do { \ fmpz * __vres; \ slong __vi; \ vec = __vres = TMP_ARRAY_ALLOC(len, fmpz); \ for (__vi = (len); __vi > 0; __vi--) \ fmpz_init(__vres + __vi - 1); \ } while (0) #define FMPZ_VEC_TMP_CLEAR(vec, len) \ do { \ fmpz * __vres = (vec); \ slong __vi; \ for (__vi = (len); __vi > 0; __vi--) \ fmpz_clear(__vres + __vi - 1); \ } while (0) /* Memory management *******************************************************/ FMPZ_VEC_INLINE fmpz * _fmpz_vec_init(slong len) { return (fmpz *) flint_calloc(len, sizeof(fmpz)); } void _fmpz_vec_clear(fmpz * vec, slong len); /* Randomisation ***********************************************************/ void _fmpz_vec_randtest(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits); void _fmpz_vec_randtest_unsigned(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits); /* Norms *******************************************************************/ slong _fmpz_vec_max_bits(const fmpz * vec, slong len); slong _fmpz_vec_max_bits_ref(const fmpz * vec, slong len); void _fmpz_vec_sum_max_bits(slong * sumabs, slong * maxabs, const fmpz * coeffs, slong length); mp_size_t _fmpz_vec_max_limbs(const fmpz * vec, slong len); void _fmpz_vec_height(fmpz_t height, const fmpz * vec, slong len); slong _fmpz_vec_height_index(const fmpz * vec, slong len); /* Input and output ********************************************************/ #ifdef FLINT_HAVE_FILE int _fmpz_vec_fprint(FILE * file, const fmpz * vec, slong len); int _fmpz_vec_fread(FILE * file, fmpz ** vec, slong * len); #endif int _fmpz_vec_print(const fmpz * vec, slong len); int _fmpz_vec_read(fmpz ** vec, slong * len); /* Conversions *************************************************************/ void _fmpz_vec_set_nmod_vec(fmpz * res, mp_srcptr poly, slong len, nmod_t mod); void _fmpz_vec_get_nmod_vec(mp_ptr res, const fmpz * poly, slong len, nmod_t mod); void _fmpz_vec_get_fft(mp_limb_t ** coeffs_f, const fmpz * coeffs_m, slong l, slong length); void _fmpz_vec_set_fft(fmpz * coeffs_m, slong length, const mp_ptr * coeffs_f, slong limbs, slong sign); slong _fmpz_vec_get_d_vec_2exp(double * appv, const fmpz * vec, slong len); /* Assignment and basic manipulation ***************************************/ void _fmpz_vec_set(fmpz * vec1, const fmpz * vec2, slong len2); void _fmpz_vec_swap(fmpz * vec1, fmpz * vec2, slong len2); void _fmpz_vec_zero(fmpz * vec, slong len); void _fmpz_vec_neg(fmpz * vec1, const fmpz * vec2, slong len2); void _fmpz_vec_scalar_abs(fmpz * vec1, const fmpz * vec2, slong len2); /* Comparison **************************************************************/ int _fmpz_vec_equal(const fmpz * vec1, const fmpz * vec2, slong len); int _fmpz_vec_is_zero(const fmpz * vec, slong len); void _fmpz_vec_max(fmpz * vec1, const fmpz * vec2, const fmpz * vec3, slong len); void _fmpz_vec_max_inplace(fmpz * vec1, const fmpz * vec2, slong len); void _fmpz_vec_min(fmpz * vec1, const fmpz * vec2, const fmpz * vec3, slong len); void _fmpz_vec_min_inplace(fmpz * vec1, const fmpz * vec2, slong len); /* Sorting ******************************************************************/ void _fmpz_vec_sort(fmpz * vec, slong len); /* Addition ****************************************************************/ void _fmpz_vec_add(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2); void _fmpz_vec_sub(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2); /* Scalar multiplication and division **************************************/ void _fmpz_vec_scalar_mul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); void _fmpz_vec_scalar_mul_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); void _fmpz_vec_scalar_mul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x); void _fmpz_vec_scalar_mul_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); void _fmpz_vec_scalar_divexact_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x); void _fmpz_vec_scalar_divexact_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); void _fmpz_vec_scalar_divexact_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); void _fmpz_vec_scalar_fdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c); void _fmpz_vec_scalar_fdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); void _fmpz_vec_scalar_fdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); void _fmpz_vec_scalar_fdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); void _fmpz_vec_scalar_fdiv_r_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); void _fmpz_vec_scalar_tdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c); void _fmpz_vec_scalar_tdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); void _fmpz_vec_scalar_tdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); void _fmpz_vec_scalar_tdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); void _fmpz_vec_scalar_addmul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); void _fmpz_vec_scalar_addmul_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); void _fmpz_vec_scalar_addmul_fmpz(fmpz * poly1, const fmpz * poly2, slong len2, const fmpz_t x); void _fmpz_vec_scalar_addmul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong exp); void _fmpz_vec_scalar_submul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); void _fmpz_vec_scalar_submul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x); void _fmpz_vec_scalar_submul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong exp); /* Vector sum and product **************************************************/ void _fmpz_vec_sum(fmpz_t res, const fmpz * vec, slong len); void _fmpz_vec_prod(fmpz_t res, const fmpz * vec, slong len); /* Reduction mod p **********************************************************/ void _fmpz_vec_scalar_mod_fmpz(fmpz *res, const fmpz *vec, slong len, const fmpz_t p); void _fmpz_vec_scalar_smod_fmpz(fmpz *res, const fmpz *vec, slong len, const fmpz_t p); /* Gaussian content ********************************************************/ void _fmpz_vec_content(fmpz_t res, const fmpz * vec, slong len); void _fmpz_vec_content_chained(fmpz_t res, const fmpz * vec, slong len, const fmpz_t inp); void _fmpz_vec_lcm(fmpz_t res, const fmpz * vec, slong len); /* Dot product *************************************************************/ void _fmpz_vec_dot_general_naive(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * a, const fmpz * b, int reverse, slong len); void _fmpz_vec_dot_general(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * a, const fmpz * b, int reverse, slong len); FMPZ_VEC_INLINE void _fmpz_vec_dot(fmpz_t res, const fmpz * vec1, const fmpz * vec2, slong len2) { _fmpz_vec_dot_general(res, NULL, 0, vec1, vec2, 0, len2); } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpz_vec/000077500000000000000000000000001461254215100152335ustar00rootroot00000000000000flint-3.1.3/src/fmpz_vec/add.c000066400000000000000000000011461461254215100161310ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_add(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2) { slong i; for (i = 0; i < len2; i++) fmpz_add(res + i, vec1 + i, vec2 + i); } flint-3.1.3/src/fmpz_vec/clear.c000066400000000000000000000011031461254215100164600ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_clear(fmpz * vec, slong len) { slong i; for (i = 0; i < len; i++) fmpz_clear(vec + i); flint_free(vec); } flint-3.1.3/src/fmpz_vec/content.c000066400000000000000000000025351461254215100170560ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_content(fmpz_t res, const fmpz * vec, slong len) { while (len > 0 && fmpz_is_zero(vec + 0)) { len--; vec++; } while (len > 1 && fmpz_is_zero(vec + len - 1)) len--; if (len <= 2) { if (len == 0) fmpz_zero(res); else if (len == 1) fmpz_abs(res, vec + 0); else fmpz_gcd(res, vec + 0, vec + 1); return; } if (fmpz_is_pm1(vec + 0) || fmpz_is_pm1(vec + len - 1)) { fmpz_one(res); return; } fmpz_gcd3(res, vec + 0, vec + 1, vec + len - 1); vec += 2; len -= 3; while (len >= 2 && !fmpz_is_one(res)) { fmpz_gcd3(res, vec + 0, vec + len - 1, res); vec++; len -= 2; } if (len != 0 && !fmpz_is_one(res)) fmpz_gcd(res, res, vec + 0); } flint-3.1.3/src/fmpz_vec/content_chained.c000066400000000000000000000024111461254215100205220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_content_chained(fmpz_t res, const fmpz * vec, slong len, const fmpz_t in) { while (len > 0 && fmpz_is_zero(vec + 0)) { len--; vec++; } while (len > 1 && fmpz_is_zero(vec + len - 1)) len--; if (len == 0) { fmpz_abs(res, in); return; } if (len == 1) { fmpz_gcd(res, vec + 0, in); return; } if (fmpz_is_pm1(in) || fmpz_is_pm1(vec + 0) || fmpz_is_pm1(vec + len - 1)) { fmpz_one(res); return; } fmpz_gcd3(res, vec + 0, vec + len - 1, in); vec++; len -= 2; while (len >= 2 && !fmpz_is_one(res)) { fmpz_gcd3(res, vec + 0, vec + len - 1, res); vec++; len -= 2; } if (len != 0 && !fmpz_is_one(res)) fmpz_gcd(res, res, vec + 0); } flint-3.1.3/src/fmpz_vec/dot.c000066400000000000000000000227461461254215100162000ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "fmpz.h" #include "fmpz_extras.h" #include "fmpz_vec.h" void _fmpz_vec_dot_general_naive(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * a, const fmpz * b, int reverse, slong len) { slong i; if (initial == NULL) { if (len == 0) { fmpz_zero(res); return; } fmpz_mul(res, a, reverse ? b + len - 1 : b); if (subtract) { fmpz_neg(res, res); for (i = 1; i < len; i++) fmpz_submul(res, a + i, reverse ? b + len - 1 - i : b + i); } else { for (i = 1; i < len; i++) fmpz_addmul(res, a + i, reverse ? b + len - 1 - i : b + i); } } else { if (res != initial) fmpz_set(res, initial); if (subtract) for(i = 0; i < len; i++) fmpz_submul(res, a + i, reverse ? b + len - 1 - i : b + i); else for(i = 0; i < len; i++) fmpz_addmul(res, a + i, reverse ? b + len - 1 - i : b + i); } } #define INITIAL_ALLOC 64 #define FMPZ_GET_MPN(xptr, xn, xneg, xtmplimb, x) \ if (!COEFF_IS_MPZ(x)) \ { \ (xtmplimb) = FLINT_ABS(x); \ (xptr) = &(xtmplimb); \ (xn) = 1; \ (xneg) = ((x) < 0); \ } \ else \ { \ __mpz_struct * __z1 = COEFF_TO_PTR(x); \ (xptr) = __z1->_mp_d; \ (xn) = FLINT_ABS(__z1->_mp_size); \ (xneg) = (__z1->_mp_size < 0); \ } /* (s,sn) = (a,an) + (b,bn). Allows an == 0 but not bn == 0. */ #define MPN_ADD(s, sn, a, an, b, bn) \ do { \ if ((an) == 0) \ { \ FLINT_SWAP(mp_ptr, s, b); \ (sn) = (bn); \ } \ else if ((an) >= (bn)) \ { \ mp_limb_t __cy; \ (s)[(an)] = __cy = mpn_add((s), (a), (an), (b), (bn)); \ (sn) = (an) + (__cy != 0); \ } \ else \ { \ mp_limb_t __cy; \ (s)[(bn)] = __cy = mpn_add((s), (b), (bn), (a), (an)); \ (sn) = (bn) + (__cy != 0); \ } \ } while (0) /* (s,sn) = (s,sn) + (a,an) * b. Allows sn == 0 but not an == 0. */ #define MPN_ADDMUL_1(s, sn, a, an, b) \ do { \ mp_limb_t __cy; \ if ((sn) >= (an)) \ { \ FLINT_ASSERT((an) != 0); \ __cy = mpn_addmul_1((s), (a), (an), (b)); \ if ((sn) > (an)) \ __cy = mpn_add_1((s) + (an), (s) + (an), (sn) - (an), __cy); \ (s)[(sn)] = __cy; \ (sn) += (__cy != 0); \ } \ else \ { \ (s)[(an)] = mpn_mul_1((s) + (sn), (a) + (sn), (an) - (sn), (b)); \ if ((sn) != 0) \ { \ __cy = mpn_addmul_1((s), (a), (sn), (b)); \ (s)[(an)] += mpn_add_1((s) + (sn), (s) + (sn), (an) - (sn), __cy); \ } \ (sn) = (an) + ((s)[(an)] != 0); \ } \ } while (0) \ FLINT_STATIC_NOINLINE void _fmpz_set_mpn(fmpz_t res, mp_srcptr x, mp_size_t xn, int neg) { if (xn <= 1 && x[0] <= COEFF_MAX) { _fmpz_demote(res); *res = neg ? -(slong) x[0] : x[0]; } else { fmpz_set_mpn_large(res, x, xn, neg); } } void _fmpz_vec_dot_general(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * a, const fmpz * b, int reverse, slong len) { mp_limb_t tmp1[INITIAL_ALLOC + 2]; mp_limb_t tmp2[INITIAL_ALLOC + 2]; mp_limb_t tmp3[INITIAL_ALLOC + 2]; mp_size_t alloc = INITIAL_ALLOC; mp_size_t new_alloc; /* We maintain separate sums for small terms, large positive terms, and large negative terms, the idea being to have fewer adjustments in the main loop in exchange for some added complexity combining things in the end. Should profile alternative strategies. */ mp_limb_t s0 = 0, s1 = 0, s2 = 0; mp_ptr neg = tmp1; mp_ptr pos = tmp2; mp_size_t posn = 0, negn = 0; /* Temporary space for products. */ mp_ptr t = tmp3; mp_size_t tn; mp_ptr tmp_heap = NULL; slong i; if (len <= 1) { if (initial == NULL) { if (len == 1) { fmpz_mul(res, a, b); if (subtract) fmpz_neg(res, res); } else fmpz_zero(res); } else { if (res != initial) fmpz_set(res, initial); if (subtract) { if (len == 1) fmpz_submul(res, a, b); } else { if (len == 1) fmpz_addmul(res, a, b); } } return; } if (initial != NULL) { fmpz ca; mp_limb_t atmp; mp_srcptr ap; mp_size_t an; int aneg; ca = *initial; FMPZ_GET_MPN(ap, an, aneg, atmp, ca); if (an <= 2) { s0 = ap[0]; if (an == 2) s1 = ap[1]; if (aneg ^ subtract) sub_dddmmmsss(s2, s1, s0, 0, 0, 0, 0, s1, s0); } else { if (an > INITIAL_ALLOC) { new_alloc = an + 4; tmp_heap = flint_malloc(3 * (new_alloc + 2) * sizeof(mp_limb_t)); t = tmp_heap; pos = t + (new_alloc + 2); neg = pos + (new_alloc + 2); alloc = new_alloc; } if (aneg ^ subtract) { flint_mpn_copyi(neg, ap, an); negn = an; } else { flint_mpn_copyi(pos, ap, an); posn = an; } } } for (i = 0; i < len; i++) { fmpz ca, cb; mp_limb_t atmp, btmp; mp_srcptr ap, bp; mp_size_t an, bn; mp_limb_t cy; int aneg, bneg; ca = a[i]; if (ca == 0) continue; cb = reverse ? b[len - 1 - i] : b[i]; if (cb == 0) continue; if (!COEFF_IS_MPZ(ca) && !COEFF_IS_MPZ(cb)) { mp_limb_t hi, lo; smul_ppmm(hi, lo, ca, cb); add_sssaaaaaa(s2, s1, s0, s2, s1, s0, FLINT_SIGN_EXT(hi), hi, lo); continue; } FMPZ_GET_MPN(ap, an, aneg, atmp, ca); FMPZ_GET_MPN(bp, bn, bneg, btmp, cb); tn = an + bn; if (tn > alloc) { mp_ptr p1, p2, p3; new_alloc = FLINT_MAX(3 * alloc / 2, tn + 4); p1 = flint_malloc(3 * (new_alloc + 2) * sizeof(mp_limb_t)); p2 = p1 + (new_alloc + 2); p3 = p2 + (new_alloc + 2); flint_mpn_copyi(p2, pos, posn); flint_mpn_copyi(p3, neg, negn); t = p1; pos = p2; neg = p3; FLINT_SWAP(mp_ptr, tmp_heap, p1); if (p1 != NULL) flint_free(p1); alloc = new_alloc; } if (an < bn) { FLINT_SWAP(mp_srcptr, ap, bp); FLINT_SWAP(mp_size_t, an, bn); } if (bn == 1) { mp_limb_t b0 = bp[0]; if (aneg ^ bneg) MPN_ADDMUL_1(neg, negn, ap, an, b0); else MPN_ADDMUL_1(pos, posn, ap, an, b0); continue; } if (ap == bp && an == bn) { flint_mpn_sqr(t, ap, an); cy = t[tn - 1]; } else { cy = flint_mpn_mul(t, ap, an, bp, bn); } tn -= (cy == 0); if (aneg ^ bneg) MPN_ADD(neg, negn, neg, negn, t, tn); else MPN_ADD(pos, posn, pos, posn, t, tn); } /* There are only small terms. */ if (posn == 0 && negn == 0) { if (subtract) sub_dddmmmsss(s2, s1, s0, 0, 0, 0, s2, s1, s0); fmpz_set_signed_uiuiui(res, s2, s1, s0); return; } /* Add small terms to large ones. */ if (((slong) s2 >= WORD(0))) { t[2] = s2; t[1] = s1; t[0] = s0; MPN_ADD(pos, posn, pos, posn, t, 3); } else { sub_dddmmmsss(t[2], t[1], t[0], 0, 0, 0, s2, s1, s0); MPN_ADD(neg, negn, neg, negn, t, 3); } MPN_NORM(pos, posn); MPN_NORM(neg, negn); if (negn == 0) { _fmpz_set_mpn(res, pos, posn, 0 ^ subtract); } else if (posn == 0) { _fmpz_set_mpn(res, neg, negn, 1 ^ subtract); } else { /* Do subtraction */ int tneg = 0; if (posn > negn) { tn = posn; } else if (negn > posn) { tn = negn; tneg = 1; } else if (posn != 0) { tn = posn; if (mpn_cmp(pos, neg, tn) < 0) tneg = 1; } if (tneg) mpn_sub(t, neg, negn, pos, posn); else mpn_sub(t, pos, posn, neg, negn); MPN_NORM(t, tn); _fmpz_set_mpn(res, t, tn, tneg ^ subtract); } if (tmp_heap != NULL) flint_free(tmp_heap); } flint-3.1.3/src/fmpz_vec/equal.c000066400000000000000000000012611461254215100165060ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" int _fmpz_vec_equal(const fmpz * vec1, const fmpz * vec2, slong len) { slong i; if (vec1 == vec2) return 1; for (i = 0; i < len; i++) if (!fmpz_equal(vec1 + i, vec2 + i)) return 0; return 1; } flint-3.1.3/src/fmpz_vec/get_d_vec_2exp.c000066400000000000000000000016651461254215100202640ustar00rootroot00000000000000/* Copyright (C) 2011, 2024 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "double_extras.h" slong _fmpz_vec_get_d_vec_2exp(double *appv, const fmpz * vec, slong len) { slong *exp, i, maxexp = 0L; TMP_INIT; TMP_START; exp = TMP_ALLOC(len * sizeof(slong)); for (i = 0; i < len; i++) { appv[i] = fmpz_get_d_2exp(&exp[i], vec + i); if (exp[i] > maxexp) maxexp = exp[i]; } for (i = 0; i < len; i++) appv[i] = d_mul_2exp(appv[i], exp[i] - maxexp); TMP_END; return maxexp; } flint-3.1.3/src/fmpz_vec/get_fft.c000066400000000000000000000043571461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2008-2011 William Hart Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz.h" #include "fmpz_vec.h" static void _fmpz_vec_get_fft_coeff(mp_limb_t ** coeffs_f, const fmpz * coeffs_m, slong l, slong i) { slong size_f = l + 1; mp_limb_t * coeff; slong size_j, c; int signed_c; c = coeffs_m[i]; signed_c = 0; if (!COEFF_IS_MPZ(c)) /* coeff is small */ { size_j = 1; if (c < 0) { signed_c = 1; c = -c; coeff = (mp_limb_t *) &c; } else coeff = (mp_limb_t *) coeffs_m + i; } else /* coeff is an mpz_t */ { __mpz_struct * mc = COEFF_TO_PTR(c); size_j = mc->_mp_size; if (size_j < 0) { signed_c = 1; size_j = -size_j; } coeff = mc->_mp_d; } if (signed_c) /* write out FFT coefficient, ensuring sign is correct */ { mpn_neg(coeffs_f[i], coeff, size_j); flint_mpn_store(coeffs_f[i] + size_j, size_f - size_j, WORD(-1)); } else { flint_mpn_copyi(coeffs_f[i], coeff, size_j); flint_mpn_zero(coeffs_f[i] + size_j, size_f - size_j); } } typedef struct { mp_limb_t ** coeffs_f; const fmpz * coeffs_m; slong limbs; } work_t; static void worker(slong i, work_t * work) { _fmpz_vec_get_fft_coeff(work->coeffs_f, work->coeffs_m, work->limbs, i); } void _fmpz_vec_get_fft(mp_limb_t ** coeffs_f, const fmpz * coeffs_m, slong limbs, slong length) { work_t work; slong max_threads; work.coeffs_f = coeffs_f; work.coeffs_m = coeffs_m; work.limbs = limbs; max_threads = flint_get_num_threads(); max_threads = FLINT_MIN(max_threads, 1e-5 * limbs * length + 1); flint_parallel_do((do_func_t) worker, &work, length, max_threads, FLINT_PARALLEL_UNIFORM); } flint-3.1.3/src/fmpz_vec/get_nmod_vec.c000066400000000000000000000012311461254215100200250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "nmod_poly.h" void _fmpz_vec_get_nmod_vec(mp_ptr res, const fmpz * poly, slong len, nmod_t mod) { slong i; for (i = 0; i < len; i++) res[i] = fmpz_get_nmod(poly + i, mod); } flint-3.1.3/src/fmpz_vec/height.c000066400000000000000000000012321461254215100166450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_height(fmpz_t height, const fmpz * vec, slong len) { if (len) { slong pos = _fmpz_vec_height_index(vec, len); fmpz_abs(height, vec + pos); } else fmpz_zero(height); } flint-3.1.3/src/fmpz_vec/height_index.c000066400000000000000000000037721461254215100200470ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" slong _fmpz_vec_height_index(const fmpz * vec, slong len) { if (len == 1) { return 0; } else { fmpz c; mp_srcptr max_d; slong max_mpz_limbs, i, max_i, max_coeff, mpz_limbs; max_coeff = 0; max_i = 0; for (i = 0; i < len; i++) { c = vec[i]; if (!COEFF_IS_MPZ(c)) { c = FLINT_ABS(c); if (c > max_coeff) { max_coeff = c; max_i = i; } } else { __mpz_struct * mc = COEFF_TO_PTR(c); max_d = mc->_mp_d; max_mpz_limbs = mc->_mp_size; max_mpz_limbs = FLINT_ABS(max_mpz_limbs); max_i = i; i++; break; } } for ( ; i < len; i++) { c = vec[i]; /* we have found at least one mpz, so only look for those */ if (COEFF_IS_MPZ(c)) { __mpz_struct * mc = COEFF_TO_PTR(c); mpz_limbs = mc->_mp_size; mpz_limbs = FLINT_ABS(mpz_limbs); if (mpz_limbs > max_mpz_limbs || ((mpz_limbs == max_mpz_limbs) && (mpn_cmp(mc->_mp_d, max_d, max_mpz_limbs) > 0))) { max_d = mc->_mp_d; max_mpz_limbs = mpz_limbs; max_i = i; } } } return max_i; } } flint-3.1.3/src/fmpz_vec/inlines.c000066400000000000000000000006771461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZ_VEC_INLINES_C #include "flint.h" #include "fmpz_vec.h" flint-3.1.3/src/fmpz_vec/io.c000066400000000000000000000052161461254215100160120ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_vec.h" /* printing *******************************************************************/ /* Recall the return value conventions for fputc (of type int) ``If there are no errors, the same character that has been written is returned. If an error occurs, EOF is returned and the error indicator is set'' where the EOF macro expands to a negative int, and flint_fprintf (of type int) ``On success, the total number of characters written is returned. On failure, a negative number is returned.'' */ int _fmpz_vec_fprint(FILE * file, const fmpz * vec, slong len) { int r; slong i; r = flint_fprintf(file, "%wd", len); if ((len > 0) && (r > 0)) { r = fputc(' ', file); for (i = 0; (i < len) && (r > 0); i++) { r = fputc(' ', file); if (r > 0) r = fmpz_fprint(file, vec + i); } } return r; } int _fmpz_vec_print(const fmpz * vec, slong len) { return _fmpz_vec_fprint(stdout, vec, len); } /* reading ********************************************************************/ int _fmpz_vec_fread(FILE * file, fmpz ** vec, slong * len) { int alloc, r; slong i; mpz_t t; alloc = (*vec == NULL); mpz_init(t); r = mpz_inp_str(t, file, 10); if (r == 0) { if (alloc) *len = 0; mpz_clear(t); return 0; } if (!mpz_fits_slong_p(t)) { flint_throw(FLINT_ERROR, "Exception (_fmpz_vec_fread). Length does not fit into a slong.\n"); } if (alloc) { *len = flint_mpz_get_si(t); *vec = _fmpz_vec_init(*len); } else { if (*len != flint_mpz_get_si(t)) { mpz_clear(t); return 0; } } mpz_clear(t); for (i = 0; i < *len; i++) { r = fmpz_fread(file, (*vec) + i); if (r <= 0) { if (alloc) { _fmpz_vec_clear(*vec, *len); *vec = NULL; *len = 0; } return r; } } return 1; } int _fmpz_vec_read(fmpz ** vec, slong * len) { return _fmpz_vec_fread(stdin, vec, len); } flint-3.1.3/src/fmpz_vec/is_zero.c000066400000000000000000000011411461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" int _fmpz_vec_is_zero(const fmpz * vec, slong len) { slong i; for (i = 0; i < len; i++) if (vec[i] != WORD(0)) return 0; return 1; } flint-3.1.3/src/fmpz_vec/lcm.c000066400000000000000000000012161461254215100161520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_lcm(fmpz_t res, const fmpz * vec, slong len) { slong i; fmpz_one(res); for (i = 0; i < len && !fmpz_is_zero(res); i++) fmpz_lcm(res, res, vec + i); fmpz_abs(res, res); } flint-3.1.3/src/fmpz_vec/max.c000066400000000000000000000017301461254215100161650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" /* vec1 = pointwise max of vec1 and vec2 */ void _fmpz_vec_max_inplace(fmpz * vec1, const fmpz * vec2, slong len) { slong i; for (i = WORD(0); i < len; i++) { if (fmpz_cmp(vec1 + i, vec2 + i) < 0) fmpz_set(vec1 + i, vec2 + i); } } /* vec1 = pointwise max of vec2 and vec3 */ void _fmpz_vec_max(fmpz * vec1, const fmpz * vec2, const fmpz * vec3, slong len) { slong i; for (i = WORD(0); i < len; i++) { int cmp = fmpz_cmp(vec2 + i, vec3 + i); fmpz_set(vec1 + i, (cmp > 0 ? vec2 : vec3) + i); } } flint-3.1.3/src/fmpz_vec/max_bits.c000066400000000000000000000037761461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" slong _fmpz_vec_max_bits(const fmpz * vec, slong len) { slong i, sign, max_limbs; mp_limb_t max_limb; mp_size_t limbs; sign = 1; max_limb = 0; for (i = 0; i < len; i++) { fmpz c = vec[i]; if (c >= 0) { if (c > COEFF_MAX) goto bignum; max_limb |= c; } else { if (c < COEFF_MIN) goto bignum; max_limb |= -c; sign = -1; } } return sign * FLINT_BIT_COUNT(max_limb); bignum: max_limbs = 1; for ( ; i < len; i++) { fmpz c = vec[i]; if (COEFF_IS_MPZ(c)) { __mpz_struct * z = COEFF_TO_PTR(c); limbs = z->_mp_size; if (limbs < 0) { sign = -1; limbs = -limbs; } if (limbs == max_limbs) max_limb |= z->_mp_d[limbs - 1]; else if (limbs > max_limbs) { max_limb = z->_mp_d[limbs - 1]; max_limbs = limbs; } } else if (c < 0) sign = -1; } return sign * ((max_limbs - 1) * FLINT_BITS + FLINT_BIT_COUNT(max_limb)); } slong _fmpz_vec_max_bits_ref(const fmpz * vec, slong len) { slong i, bits, max_bits = 0, sign = 1; for (i = 0; i < len; i++) { bits = fmpz_bits(vec + i); if (bits > max_bits) max_bits = bits; if (fmpz_sgn(vec + i) < 0) sign = WORD(-1); } return max_bits * sign; } flint-3.1.3/src/fmpz_vec/max_limbs.c000066400000000000000000000013121461254215100173470ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" mp_size_t _fmpz_vec_max_limbs(const fmpz * vec, slong len) { slong i; mp_size_t limbs, max_limbs = 0; for (i = 0; i < len; i++) { limbs = fmpz_size(vec + i); if (limbs > max_limbs) max_limbs = limbs; } return max_limbs; } flint-3.1.3/src/fmpz_vec/min.c000066400000000000000000000017301461254215100161630ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" /* vec1 = pointwise max of vec1 and vec2 */ void _fmpz_vec_min_inplace(fmpz * vec1, const fmpz * vec2, slong len) { slong i; for (i = WORD(0); i < len; i++) { if (fmpz_cmp(vec1 + i, vec2 + i) > 0) fmpz_set(vec1 + i, vec2 + i); } } /* vec1 = pointwise max of vec2 and vec3 */ void _fmpz_vec_min(fmpz * vec1, const fmpz * vec2, const fmpz * vec3, slong len) { slong i; for (i = WORD(0); i < len; i++) { int cmp = fmpz_cmp(vec2 + i, vec3 + i); fmpz_set(vec1 + i, (cmp < 0 ? vec2 : vec3) + i); } } flint-3.1.3/src/fmpz_vec/neg.c000066400000000000000000000011131461254215100161440ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_neg(fmpz * vec1, const fmpz * vec2, slong len2) { slong i; for (i = 0; i < len2; i++) fmpz_neg(vec1 + i, vec2 + i); } flint-3.1.3/src/fmpz_vec/prod.c000066400000000000000000000020071461254215100163420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_prod(fmpz_t res, const fmpz * vec, slong len) { if (len <= 1) { if (len == 1) fmpz_set(res, vec); else fmpz_one(res); } else if (len <= 3) { slong i; fmpz_mul(res, vec, vec + 1); for (i = 2; i < len; i++) fmpz_mul(res, res, vec + i); } else { slong m = len / 2; fmpz_t tmp; fmpz_init(tmp); _fmpz_vec_prod(res, vec, m); _fmpz_vec_prod(tmp, vec + m, len - m); fmpz_mul(res, res, tmp); fmpz_clear(tmp); } } flint-3.1.3/src/fmpz_vec/randtest.c000066400000000000000000000031111461254215100172170ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_randtest(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong i, sparseness; if (n_randint(state, 2)) { for (i = 0; i < len; i++) fmpz_randtest(f + i, state, bits); } else { sparseness = 1 + n_randint(state, FLINT_MAX(2, len)); for (i = 0; i < len; i++) { if (n_randint(state, sparseness)) fmpz_zero(f + i); else fmpz_randtest(f + i, state, bits); } } } void _fmpz_vec_randtest_unsigned(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong i, sparseness; if (n_randint(state, 2)) { for (i = 0; i < len; i++) fmpz_randtest_unsigned(f + i, state, bits); } else { sparseness = 1 + n_randint(state, FLINT_MAX(2, len)); for (i = 0; i < len; i++) { if (n_randint(state, sparseness)) fmpz_zero(f + i); else fmpz_randtest_unsigned(f + i, state, bits); } } } flint-3.1.3/src/fmpz_vec/scalar.c000066400000000000000000000230271461254215100166500ustar00rootroot00000000000000/* Copyright (C) 2010, 2016 William Hart Copyright (C) 2010-2012 Sebastian Pancratz Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_scalar_abs(fmpz * vec1, const fmpz * vec2, slong len2) { slong i; for (i = 0; i < len2; i++) fmpz_abs(vec1 + i, vec2 + i); } void _fmpz_vec_scalar_addmul_fmpz(fmpz * poly1, const fmpz * poly2, slong len2, const fmpz_t x) { fmpz c = *x; if (!COEFF_IS_MPZ(c)) { if (c == 0) return; else if (c == 1) _fmpz_vec_add(poly1, poly1, poly2, len2); else if (c == -1) _fmpz_vec_sub(poly1, poly1, poly2, len2); else _fmpz_vec_scalar_addmul_si(poly1, poly2, len2, c); } else { slong i; for (i = 0; i < len2; i++) fmpz_addmul(poly1 + i, poly2 + i, x); } } void _fmpz_vec_scalar_addmul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong exp) { slong i; fmpz_t temp; if (c == 0) return; /* nothing to add */ if (exp == 0) /* just do addmul */ { _fmpz_vec_scalar_addmul_si(vec1, vec2, len2, c); return; } fmpz_init(temp); if (c == 1) /* scalar is 1, just add c * 2^exp times c */ { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_add(vec1 + i, vec1 + i, temp); } } else if (c == -1) /* scalar is -1, subtract c * 2^exp */ { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_sub(vec1 + i, vec1 + i, temp); } } else /* generic case */ { if (c > 0) { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_addmul_ui(vec1 + i, temp, c); } } else { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_submul_ui(vec1 + i, temp, -c); } } } fmpz_clear(temp); } void _fmpz_vec_scalar_addmul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) { slong i; if (c >= 0) for (i = 0; i < len2; i++) fmpz_addmul_ui(vec1 + i, vec2 + i, c); else for (i = 0; i < len2; i++) fmpz_submul_ui(vec1 + i, vec2 + i, -c); } void _fmpz_vec_scalar_addmul_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) { ulong ix; for (ix = 0; ix < len2; ix++) fmpz_addmul_ui(vec1 + ix, vec2 + ix, c); } void _fmpz_vec_scalar_divexact_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x) { fmpz c = *x; if (!COEFF_IS_MPZ(c)) { if (c == 1) _fmpz_vec_set(vec1, vec2, len2); else if (c == -1) _fmpz_vec_neg(vec1, vec2, len2); else _fmpz_vec_scalar_divexact_si(vec1, vec2, len2, c); } else { slong i; for (i = 0; i < len2; i++) fmpz_divexact(vec1 + i, vec2 + i, x); } } void _fmpz_vec_scalar_divexact_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) { slong i; for (i = 0; i < len2; i++) fmpz_divexact_si(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_divexact_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) { slong i; for (i = 0; i < len2; i++) fmpz_divexact_ui(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_fdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) { slong i; for (i = 0; i < len2; i++) fmpz_fdiv_q_2exp(vec1 + i, vec2 + i, exp); } void _fmpz_vec_scalar_fdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c) { slong i; for (i = 0; i < len2; i++) fmpz_fdiv_q(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_fdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) { slong i; for (i = 0; i < len2; i++) fmpz_fdiv_q_si(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_fdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) { slong i; for (i = 0; i < len2; i++) fmpz_fdiv_q_ui(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_fdiv_r_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) { slong i; for (i = 0; i < len2; i++) fmpz_fdiv_r_2exp(vec1 + i, vec2 + i, exp); } void _fmpz_vec_scalar_mod_fmpz(fmpz *res, const fmpz *vec, slong len, const fmpz_t p) { slong i; for (i = 0; i < len; i++) fmpz_mod(res + i, vec + i, p); } void _fmpz_vec_scalar_mul_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) { slong i; for (i = 0; i < len2; i++) fmpz_mul_2exp(vec1 + i, vec2 + i, exp); } void _fmpz_vec_scalar_mul_fmpz(fmpz * poly1, const fmpz * poly2, slong len2, const fmpz_t x) { fmpz c = *x; if (!COEFF_IS_MPZ(c)) { if (c == 0) _fmpz_vec_zero(poly1, len2); else if (c == 1) _fmpz_vec_set(poly1, poly2, len2); else if (c == -1) _fmpz_vec_neg(poly1, poly2, len2); else _fmpz_vec_scalar_mul_si(poly1, poly2, len2, c); } else { slong i; for (i = 0; i < len2; i++) fmpz_mul(poly1 + i, poly2 + i, x); } } void _fmpz_vec_scalar_mul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) { slong i; for (i = 0; i < len2; i++) fmpz_mul_si(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_mul_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) { slong i; for (i = 0; i < len2; i++) fmpz_mul_ui(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_smod_fmpz(fmpz *res, const fmpz *vec, slong len, const fmpz_t p) { slong i; fmpz_t pdiv2; fmpz_init(pdiv2); fmpz_fdiv_q_2exp(pdiv2, p, 1); for (i = 0; i < len; i++) { fmpz_mod(res + i, vec + i, p); if (fmpz_cmp(res + i, pdiv2) > 0) { fmpz_sub(res + i, res + i, p); } } fmpz_clear(pdiv2); } void _fmpz_vec_scalar_submul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x) { fmpz c = *x; if (!COEFF_IS_MPZ(c)) { if (c == 0) return; else if (c == 1) _fmpz_vec_sub(vec1, vec1, vec2, len2); else if (c == -1) _fmpz_vec_add(vec1, vec1, vec2, len2); else _fmpz_vec_scalar_submul_si(vec1, vec2, len2, c); } else { slong i; for (i = 0; i < len2; i++) fmpz_submul(vec1 + i, vec2 + i, x); } } void _fmpz_vec_scalar_submul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong exp) { slong i; fmpz_t temp; if (c == 0) return; /* nothing to add */ if (exp == 0) /* just do submul */ { _fmpz_vec_scalar_submul_si(vec1, vec2, len2, c); return; } fmpz_init(temp); if (c == 1) /* scalar is 1, just subtract c * 2^exp times c */ { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_sub(vec1 + i, vec1 + i, temp); } } else if (c == -1) /* scalar is -1, add c * 2^exp */ { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_add(vec1 + i, vec1 + i, temp); } } else /* generic case */ { if (c >= 0) { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_submul_ui(vec1 + i, temp, c); } } else { for (i = 0; i < len2; i++) { fmpz_mul_2exp(temp, vec2 + i, exp); fmpz_addmul_ui(vec1 + i, temp, -c); } } } fmpz_clear(temp); } void _fmpz_vec_scalar_submul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) { slong i; if (c >= 0) for (i = 0; i < len2; i++) fmpz_submul_ui(vec1 + i, vec2 + i, c); else for (i = 0; i < len2; i++) fmpz_addmul_ui(vec1 + i, vec2 + i, -c); } void _fmpz_vec_scalar_tdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) { slong i; for (i = 0; i < len2; i++) fmpz_tdiv_q_2exp(vec1 + i, vec2 + i, exp); } void _fmpz_vec_scalar_tdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c) { slong i; for (i = 0; i < len2; i++) fmpz_tdiv_q(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_tdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) { slong i; for (i = 0; i < len2; i++) fmpz_tdiv_q_si(vec1 + i, vec2 + i, c); } void _fmpz_vec_scalar_tdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c) { slong i; for (i = 0; i < len2; i++) fmpz_tdiv_q_ui(vec1 + i, vec2 + i, c); } flint-3.1.3/src/fmpz_vec/set.c000066400000000000000000000011651461254215100161750ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_set(fmpz * vec1, const fmpz * vec2, slong len2) { slong i; if (vec1 != vec2) { for (i = 0; i < len2; i++) fmpz_set(vec1 + i, vec2 + i); } } flint-3.1.3/src/fmpz_vec/set_fft.c000066400000000000000000000055171461254215100170410ustar00rootroot00000000000000/* Copyright (C) 2008-2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "gmpcompat.h" #include "fmpz.h" #include "fmpz_vec.h" static void _fmpz_vec_set_fft_coeff(fmpz * coeffs_m, slong i, const mp_ptr * coeffs_f, slong limbs, slong sign) { slong size; mp_limb_t * data; __mpz_struct * mcoeffs_m; coeffs_m += i; if (sign) { mp_limb_t halflimb = UWORD(1) << (FLINT_BITS - 1); { mcoeffs_m = _fmpz_promote(coeffs_m); data = FLINT_MPZ_REALLOC(mcoeffs_m, limbs); if ((coeffs_f[i][limbs - 1] > halflimb) || coeffs_f[i][limbs]) { mpn_neg(data, coeffs_f[i], limbs); mpn_add_1(data, data, limbs, WORD(1)); size = limbs; while ((size) && (data[size - 1] == 0)) size--; /* normalise */ mcoeffs_m->_mp_size = -size; if (size >= WORD(-1)) _fmpz_demote_val(coeffs_m); /* coefficient may be small*/ } else { flint_mpn_copyi(data, coeffs_f[i], limbs); size = limbs; while ((size) && (data[size - 1] == WORD(0))) size--; /* normalise */ mcoeffs_m->_mp_size = size; if (size <= 1) _fmpz_demote_val(coeffs_m); /* coefficient may be small */ } } } else { { mcoeffs_m = _fmpz_promote(coeffs_m); data = FLINT_MPZ_REALLOC(mcoeffs_m, limbs); flint_mpn_copyi(data, coeffs_f[i], limbs); size = limbs; while ((size) && (data[size - 1] == WORD(0))) size--; /* normalise */ mcoeffs_m->_mp_size = size; if (size <= 1) _fmpz_demote_val(coeffs_m); /* coefficient may be small */ } } } typedef struct { fmpz * coeffs_m; const mp_ptr * coeffs_f; slong limbs; int sign; } work_t; static void worker(slong i, work_t * work) { _fmpz_vec_set_fft_coeff(work->coeffs_m, i, work->coeffs_f, work->limbs, work->sign); } void _fmpz_vec_set_fft(fmpz * coeffs_m, slong length, const mp_ptr * coeffs_f, slong limbs, slong sign) { work_t work; slong max_threads; work.coeffs_m = coeffs_m; work.coeffs_f = coeffs_f; work.limbs = limbs; work.sign = sign; max_threads = flint_get_num_threads(); max_threads = FLINT_MIN(max_threads, 1e-5 * limbs * length + 1); flint_parallel_do((do_func_t) worker, &work, length, max_threads, FLINT_PARALLEL_UNIFORM); } flint-3.1.3/src/fmpz_vec/set_nmod_vec.c000066400000000000000000000012321461254215100200420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "nmod_poly.h" void _fmpz_vec_set_nmod_vec(fmpz * res, mp_srcptr poly, slong len, nmod_t mod) { slong i; for (i = 0; i < len; i++) fmpz_set_ui_smod(res + i, poly[i], mod.n); } flint-3.1.3/src/fmpz_vec/sort.c000066400000000000000000000013641461254215100163720ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #ifndef __compar_fn_t #if defined(_MSC_VER) typedef int(*__compar_fn_t) (const void *, const void *); #else typedef int(*__compar_fn_t) (__const void *, __const void *); #endif #endif void _fmpz_vec_sort(fmpz * vec, slong len) { qsort(vec, len, sizeof(fmpz), (__compar_fn_t) fmpz_cmp); } flint-3.1.3/src/fmpz_vec/sub.c000066400000000000000000000011461461254215100161720ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_sub(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2) { slong i; for (i = 0; i < len2; i++) fmpz_sub(res + i, vec1 + i, vec2 + i); } flint-3.1.3/src/fmpz_vec/sum.c000066400000000000000000000014201461254215100162000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_sum(fmpz_t res, const fmpz * vec, slong len) { if (len <= 1) { if (len == 1) fmpz_set(res, vec); else fmpz_zero(res); } else { slong i; fmpz_add(res, vec, vec + 1); for (i = 2; i < len; i++) fmpz_add(res, res, vec + i); } } flint-3.1.3/src/fmpz_vec/sum_max_bits.c000066400000000000000000000033451461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" /* set sumabs = bit_count(sum of absolute values of coefficients); set maxabs = bit_count(max of absolute values of coefficients); */ void _fmpz_vec_sum_max_bits(slong * sumabs, slong * maxabs, const fmpz * coeffs, slong length) { slong j; ulong hi = 0, lo = 0; maxabs[0] = 0; for (j = 0; j < length && fmpz_fits_si(coeffs + j); j++) { slong c = fmpz_get_si(coeffs + j); ulong uc = (ulong) FLINT_ABS(c); add_ssaaaa(hi, lo, hi, lo, UWORD(0), uc); maxabs[0] = FLINT_MAX(maxabs[0], FLINT_BIT_COUNT(uc)); } if (j == length) { /* no large coeffs encountered */ if (hi != 0) sumabs[0] = FLINT_BIT_COUNT(hi) + FLINT_BITS; else sumabs[0] = FLINT_BIT_COUNT(lo); } else { /* restart with multiprecision routine */ fmpz_t sum; fmpz_init(sum); for (j = 0; j < length; j++) { slong this_size = fmpz_sizeinbase(coeffs + j, 2); maxabs[0] = FLINT_MAX(maxabs[0], this_size); if (fmpz_sgn(coeffs + j) < 0) fmpz_sub(sum, sum, coeffs + j); else fmpz_add(sum, sum, coeffs + j); } sumabs[0] = fmpz_sizeinbase(sum, 2); fmpz_clear(sum); } } flint-3.1.3/src/fmpz_vec/swap.c000066400000000000000000000011151461254215100163470ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_swap(fmpz * vec1, fmpz * vec2, slong len2) { slong i; for (i = 0; i < len2; i++) fmpz_swap(vec1 + i, vec2 + i); } flint-3.1.3/src/fmpz_vec/test/000077500000000000000000000000001461254215100162125ustar00rootroot00000000000000flint-3.1.3/src/fmpz_vec/test/main.c000066400000000000000000000066131461254215100173100ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-content.c" #include "t-dot.c" #include "t-dot_general.c" #include "t-get_d_vec_2exp.c" #include "t-get_set_fft.c" #include "t-get_set_nmod_vec.c" #include "t-height.c" #include "t-height_index.c" #include "t-init_clear.c" #include "t-is_zero.c" #include "t-lcm.c" #include "t-max_bits.c" #include "t-max_limbs.c" #include "t-neg.c" #include "t-prod.c" #include "t-scalar_abs.c" #include "t-scalar_addmul_fmpz.c" #include "t-scalar_addmul_si_2exp.c" #include "t-scalar_addmul_si.c" #include "t-scalar_addmul_ui.c" #include "t-scalar_divexact_fmpz.c" #include "t-scalar_divexact_si.c" #include "t-scalar_divexact_ui.c" #include "t-scalar_fdiv_q_fmpz.c" #include "t-scalar_mod_fmpz.c" #include "t-scalar_mul_2exp.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_si.c" #include "t-scalar_mul_ui.c" #include "t-scalar_smod_fmpz.c" #include "t-scalar_submul_fmpz.c" #include "t-scalar_submul_si_2exp.c" #include "t-scalar_submul_si.c" #include "t-set_equal.c" #include "t-sub.c" #include "t-sum.c" #include "t-sum_max_bits.c" #include "t-swap.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpz_vec_add), TEST_FUNCTION(fmpz_vec_content), TEST_FUNCTION(fmpz_vec_dot), TEST_FUNCTION(fmpz_vec_dot_general), TEST_FUNCTION(fmpz_vec_get_d_vec_2exp), TEST_FUNCTION(fmpz_vec_get_set_fft), TEST_FUNCTION(fmpz_vec_get_set_nmod_vec), TEST_FUNCTION(fmpz_vec_height), TEST_FUNCTION(fmpz_vec_height_index), TEST_FUNCTION(fmpz_vec_init_clear), TEST_FUNCTION(fmpz_vec_is_zero), TEST_FUNCTION(fmpz_vec_lcm), TEST_FUNCTION(fmpz_vec_max_bits), TEST_FUNCTION(fmpz_vec_max_limbs), TEST_FUNCTION(fmpz_vec_neg), TEST_FUNCTION(fmpz_vec_prod), TEST_FUNCTION(fmpz_vec_scalar_abs), TEST_FUNCTION(fmpz_vec_scalar_addmul_fmpz), TEST_FUNCTION(fmpz_vec_scalar_addmul_si_2exp), TEST_FUNCTION(fmpz_vec_scalar_addmul_si), TEST_FUNCTION(fmpz_vec_scalar_addmul_ui), TEST_FUNCTION(fmpz_vec_scalar_divexact_fmpz), TEST_FUNCTION(fmpz_vec_scalar_divexact_si), TEST_FUNCTION(fmpz_vec_scalar_divexact_ui), TEST_FUNCTION(fmpz_vec_scalar_fdiv_q_fmpz), TEST_FUNCTION(fmpz_vec_scalar_mod_fmpz), TEST_FUNCTION(fmpz_vec_scalar_mul_2exp), TEST_FUNCTION(fmpz_vec_scalar_mul_fmpz), TEST_FUNCTION(fmpz_vec_scalar_mul_si), TEST_FUNCTION(fmpz_vec_scalar_mul_ui), TEST_FUNCTION(fmpz_vec_scalar_smod_fmpz), TEST_FUNCTION(fmpz_vec_scalar_submul_fmpz), TEST_FUNCTION(fmpz_vec_scalar_submul_si_2exp), TEST_FUNCTION(fmpz_vec_scalar_submul_si), TEST_FUNCTION(fmpz_vec_set_equal), TEST_FUNCTION(fmpz_vec_sub), TEST_FUNCTION(fmpz_vec_sum), TEST_FUNCTION(fmpz_vec_sum_max_bits), TEST_FUNCTION(fmpz_vec_swap), TEST_FUNCTION(fmpz_vec_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpz_vec/test/t-add.c000066400000000000000000000042501461254215100173500ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_add, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_add(c, a, b, len); _fmpz_vec_add(a, a, b, len); result = (_fmpz_vec_equal(a, c, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_add(c, a, b, len); _fmpz_vec_add(b, a, b, len); result = (_fmpz_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-content.c000066400000000000000000000027711461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_content, state) { int i, result; /* Check that content(a f) = abs(a) content(f) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, c, d; fmpz *f; slong len = n_randint(state, 100); fmpz_init(a); fmpz_init(c); fmpz_init(d); f = _fmpz_vec_init(len); _fmpz_vec_randtest(f, state, len, 200); fmpz_randtest(a, state, 100); _fmpz_vec_content(c, f, len); _fmpz_vec_scalar_mul_fmpz(f, f, len, a); fmpz_abs(a, a); fmpz_mul(c, a, c); _fmpz_vec_content(d, f, len); result = (fmpz_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(c), flint_printf("\n\n"); fmpz_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); _fmpz_vec_clear(f, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-dot.c000066400000000000000000000040441461254215100174070ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_dot, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t res1, res2; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); fmpz_init(res1); fmpz_init(res2); _fmpz_vec_dot(res1, a, a, len); _fmpz_vec_dot(res2, a, b, len); result = fmpz_equal(res1, res2); if (!result) { flint_printf("FAIL:\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(res1); fmpz_clear(res2); } /* Check commutative law */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t res1, res2; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); fmpz_init(res1); fmpz_init(res2); _fmpz_vec_dot(res1, a, b, len); _fmpz_vec_dot(res2, b, a, len); result = fmpz_equal(res1, res2); if (!result) { flint_printf("FAIL:\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(res1); fmpz_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-dot_general.c000066400000000000000000000046271461254215100211130ustar00rootroot00000000000000/* Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_dot_general, state) { int iter; for (iter = 0; iter < 100000 * flint_test_multiplier(); iter++) { fmpz * a, * b; fmpz_t s, t, c; slong n, bits1, bits2; int alias, negate, initial, reverse; initial = n_randint(state, 2); alias = n_randint(state, 2); negate = n_randint(state, 2); reverse = n_randint(state, 2); n = n_randint(state, 8); if (n_randint(state, 30) == 0) bits1 = 2 + n_randint(state, 20000); else bits1 = 2 + n_randint(state, 1000); bits2 = 2 + n_randint(state, 1000); a = _fmpz_vec_init(n); b = _fmpz_vec_init(n); fmpz_init(s); fmpz_init(t); fmpz_init(c); fmpz_randtest(c, state, bits1); _fmpz_vec_randtest(a, state, n, bits1); _fmpz_vec_randtest(b, state, n, bits2); if (initial && alias) { fmpz_set(s, c); fmpz_set(t, c); _fmpz_vec_dot_general(s, s, negate, a, b, reverse, n); _fmpz_vec_dot_general_naive(t, t, negate, a, b, reverse, n); } else { _fmpz_vec_dot_general(s, initial ? c : NULL, negate, a, b, reverse, n); _fmpz_vec_dot_general_naive(t, initial ? c : NULL, negate, a, b, reverse, n); } if (!fmpz_equal(s, t) || !_fmpz_is_canonical(s)) { flint_printf("negate = %d, initial = %d, reverse = %d, alias = %d\n", negate, initial, reverse, alias); flint_printf("c = %{fmpz}\n\n", c); flint_printf("a = %{fmpz*}\n\n", a, n); flint_printf("b = %{fmpz*}\n\n", b, n); flint_printf("s = %{fmpz}\n\n", s); flint_printf("t = %{fmpz}\n\n", t); flint_abort(); } fmpz_clear(s); fmpz_clear(t); fmpz_clear(c); _fmpz_vec_clear(a, n); _fmpz_vec_clear(b, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-get_d_vec_2exp.c000066400000000000000000000034651461254215100215040ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "d_vec.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_get_d_vec_2exp, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int result; fmpz *a; double *d1, *d2; slong bits, j, len, l1, l2, l3; len = n_randint(state, 100); a = _fmpz_vec_init(len); d1 = _d_vec_init(len); d2 = _d_vec_init(len); bits = 1 + n_randint(state, 200); _fmpz_vec_randtest(a, state, len, bits); l1 = _fmpz_vec_get_d_vec_2exp(d1, a, len / 2); l2 = _fmpz_vec_get_d_vec_2exp(d1 + len / 2, a + len / 2, (len + 1) / 2); l3 = _fmpz_vec_get_d_vec_2exp(d2, a, len); if (l1 < l2) for (j = 0; j < len / 2; j++) d1[j] = ldexp(d1[j], l1 - l2); if (l2 < l1) for (j = len / 2; j < len; j++) d1[j] = ldexp(d1[j], l2 - l1); result = (l3 == FLINT_MAX(l1, l2) && _d_vec_equal(d1, d2, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _d_vec_clear(d1); _d_vec_clear(d2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-get_set_fft.c000066400000000000000000000062251461254215100211150ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fft.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_get_set_fft, state) { int i, result; /* convert back and forth and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz * a, * b; flint_bitcnt_t bits; slong len, limbs; mp_limb_t ** ii, * ptr; slong i, bt; bits = n_randint(state, 300) + 1; len = n_randint(state, 300) + 1; limbs = 2*((bits - 1)/FLINT_BITS + 1); ii = flint_malloc((len + len*(limbs + 1))*sizeof(mp_limb_t)); ptr = (mp_limb_t *) ii + len; for (i = 0; i < len; i++, ptr += (limbs + 1)) ii[i] = ptr; a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, bits); fmpz_one(a + 0); fmpz_mul_2exp(a + 0, a + 0, FLINT_BITS*limbs - 1); _fmpz_vec_get_fft(ii, a, limbs, len); bt = _fmpz_vec_max_bits(a, len); for (i = 0; i < len; i++) mpn_normmod_2expp1(ii[i], limbs); _fmpz_vec_set_fft(b, len, ii, limbs, bt < 0); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } flint_free(ii); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* convert back and forth unsigned and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz * a, * b; flint_bitcnt_t bits; slong len, limbs; mp_limb_t ** ii, * ptr; slong i, bt; bits = n_randint(state, 300) + 1; len = n_randint(state, 300) + 1; limbs = 2*((bits - 1)/FLINT_BITS + 1); ii = flint_malloc((len + len*(limbs + 1))*sizeof(mp_limb_t)); ptr = (mp_limb_t *) ii + len; for (i = 0; i < len; i++, ptr += (limbs + 1)) ii[i] = ptr; a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest_unsigned(a, state, len, bits); _fmpz_vec_get_fft(ii, a, limbs, len); bt = _fmpz_vec_max_bits(a, len); _fmpz_vec_set_fft(b, len, ii, limbs, bt < 0); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } flint_free(ii); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-get_set_nmod_vec.c000066400000000000000000000034411461254215100221250ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_get_set_nmod_vec, state) { int i, result; /* Check conversion to and from nmod_vec */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; mp_ptr c; nmod_t mod; slong i; mp_limb_t t; slong len = n_randint(state, 100); mp_limb_t n = n_randtest_not_zero(state); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _nmod_vec_init(len); nmod_init(&mod, n); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_get_nmod_vec(c, a, len, mod); _fmpz_vec_set_nmod_vec(b, c, len, mod); for (i = 0; i < len; i++) { fmpz_mod_ui(a + i, a + i, n); t = fmpz_get_ui(a + i); if (t > n / 2) fmpz_sub_ui(a + i, a + i, n); } result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _nmod_vec_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-height.c000066400000000000000000000026231461254215100200720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_height, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; fmpz_t h; slong len, bits, bits2; fmpz_init(h); len = n_randint(state, 100); a = _fmpz_vec_init(len); bits = n_randint(state, 200); _fmpz_vec_randtest(a, state, len, bits); bits2 = _fmpz_vec_max_bits(a, len); _fmpz_vec_height(h, a, len); result = (fmpz_bits(h) == FLINT_ABS(bits2)) && (fmpz_sgn(h) >= 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("bits = %wd, bits2 = %wd\n", bits, bits2); flint_printf("Computed height:\n"); fmpz_print(h); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(h); _fmpz_vec_clear(a, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-height_index.c000066400000000000000000000026031461254215100212570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" static slong refimpl(const fmpz * v, slong len) { slong i, max = 0; for (i = 1; i < len; i++) if (fmpz_cmpabs(v + i, v + max) > 0) max = i; return max; } TEST_FUNCTION_START(fmpz_vec_height_index, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong len, bits, p1, p2; len = 1 + n_randint(state, 100); a = _fmpz_vec_init(len); bits = n_randint(state, 200); _fmpz_vec_randtest(a, state, len, bits); p1 = _fmpz_vec_height_index(a, len); p2 = refimpl(a, len); result = (p1 == p2); if (!result) { flint_printf("FAIL:\n"); flint_printf("bits = %wd, p1 = %wd, p2 = %wd\n", bits, p1, p2); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-init_clear.c000066400000000000000000000014501461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong j, len = n_randint(state, 100) + 1; a = _fmpz_vec_init(len); for (j = 0; j < len; j++) fmpz_zero(a + j); _fmpz_vec_clear(a, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-is_zero.c000066400000000000000000000032531461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_is_zero, state) { int i, result; /* Check zero vector */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_zero(a, len); result = (_fmpz_vec_is_zero(a, len)); if (!result) { flint_printf("FAIL1:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); } /* Check non-zero vector */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong len = n_randint(state, 100) + 1; a = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); fmpz_set_ui(a + (len - 1), UWORD(1)); result = (!_fmpz_vec_is_zero(a, len)); if (!result) { flint_printf("FAIL2:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-lcm.c000066400000000000000000000031561461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_lcm, state) { int i, result; /* Check that lcm(a f) = abs(a) lcm(f) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, c, d; fmpz *f; slong len = n_randint(state, 100); fmpz_init(a); fmpz_init(c); fmpz_init(d); f = _fmpz_vec_init(len); _fmpz_vec_randtest(f, state, len, 200); fmpz_randtest(a, state, 100); _fmpz_vec_lcm(c, f, len); if (len == 0) { result = fmpz_is_one(c); } else { _fmpz_vec_scalar_mul_fmpz(f, f, len, a); fmpz_abs(a, a); fmpz_mul(c, a, c); _fmpz_vec_lcm(d, f, len); result = (fmpz_equal(c, d)); } if (!result) { fmpz_print(c), flint_printf("\n\n"); fmpz_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); _fmpz_vec_clear(f, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-max_bits.c000066400000000000000000000023071461254215100204270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_max_bits, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong len, bits, bits2, bits3; len = n_randint(state, 100); a = _fmpz_vec_init(len); bits = n_randint(state, 200); _fmpz_vec_randtest(a, state, len, bits); bits2 = _fmpz_vec_max_bits(a, len); bits3 = _fmpz_vec_max_bits_ref(a, len); result = (bits >= FLINT_ABS(bits2) && bits2 == bits3); if (!result) { flint_printf("FAIL:\n"); flint_printf("bits = %wd, bits2 = %wd bits3 = %wd\n", bits, bits2, bits3); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-max_limbs.c000066400000000000000000000026121461254215100205730ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_max_limbs, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong len, bits; mp_size_t limbs, limbs2; len = n_randint(state, 100); a = _fmpz_vec_init(len); bits = n_randint(state, 200); limbs = (bits + FLINT_BITS - 1) / FLINT_BITS; _fmpz_vec_randtest(a, state, len, bits); limbs2 = _fmpz_vec_max_limbs(a, len); result = (limbs >= limbs2); if (!result) { flint_printf("FAIL:\n"); flint_printf("bits = %wd\n", bits); flint_printf("limbs = %wd\n", limbs); flint_printf("a = {"), _fmpz_vec_print(a, len), flint_printf("}\n"); flint_printf("limbs2 = %wd\n", limbs2); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-neg.c000066400000000000000000000036471461254215100174020ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_neg, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_neg(b, a, len); _fmpz_vec_neg(a, a, len); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Check -(-a) == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_neg(b, a, len); _fmpz_vec_neg(b, b, len); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-prod.c000066400000000000000000000027661461254215100175760ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_prod, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t x, y, z; slong len1 = n_randint(state, 100); slong len2 = n_randint(state, 100); a = _fmpz_vec_init(len1 + len2); b = a + len1; _fmpz_vec_randtest(a, state, len1 + len2, 200); fmpz_init(x); fmpz_init(y); fmpz_init(z); _fmpz_vec_prod(x, a, len1); _fmpz_vec_prod(y, b, len2); fmpz_mul(x, x, y); _fmpz_vec_prod(z, a, len1 + len2); result = (fmpz_equal(x, z)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len1), flint_printf("\n\n"); _fmpz_vec_print(b, len2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len1 + len2); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_abs.c000066400000000000000000000037161461254215100207200ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_abs, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_abs(b, a, len); _fmpz_vec_scalar_abs(a, a, len); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Check |(|a|)| == |a| */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_abs(a, a, len); _fmpz_vec_scalar_abs(b, a, len); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_addmul_fmpz.c000066400000000000000000000054321461254215100224520ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" TEST_FUNCTION_START(fmpz_vec_scalar_addmul_fmpz, state) { int i, result; /* Compare with fmpz_vec_scalar_addmul_si */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; fmpz_t n1; slong len, n; len = n_randint(state, 100); n = (slong) n_randbits(state, FLINT_BITS - 1); if (n_randint(state, 2)) n = -n; fmpz_init(n1); fmpz_set_si(n1, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); _fmpz_vec_scalar_addmul_fmpz(b, a, len, n1); _fmpz_vec_scalar_addmul_si(c, a, len, n); result = (_fmpz_vec_equal(c, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } /* Compute a different way */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len = n_randint(state, 100); fmpz_t n1; fmpz_init(n1); fmpz_randtest(n1, state, 200); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); _fmpz_vec_scalar_addmul_fmpz(b, a, len, n1); _fmpz_vec_scalar_mul_fmpz(d, a, len, n1); _fmpz_vec_add(c, c, d, len); result = (_fmpz_vec_equal(c, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_addmul_si.c000066400000000000000000000032731461254215100221120ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_addmul_si, state) { int i, result; /* Compare with alternative method of computation */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len, x; len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); x = z_randtest(state); _fmpz_vec_scalar_addmul_si(b, a, len, x); _fmpz_vec_scalar_mul_si(d, a, len, x); _fmpz_vec_add(c, c, d, len); result = (_fmpz_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = %wd\n", x); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_addmul_si_2exp.c000066400000000000000000000034021461254215100230420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_addmul_si_2exp, state) { int i, result; /* Compare with alternative method of computation */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len, x; flint_bitcnt_t exp; len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); x = z_randtest(state); exp = n_randint(state, 200); _fmpz_vec_scalar_addmul_si_2exp(b, a, len, x, exp); _fmpz_vec_scalar_mul_2exp(d, a, len, exp); _fmpz_vec_scalar_addmul_si(c, d, len, x); result = (_fmpz_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = %wd, exp = %wu\n", x, exp); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_addmul_ui.c000066400000000000000000000033261461254215100221130ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2021 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_addmul_ui, state) { int i, result; /* Compare with alternative method of computation */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len; ulong x; len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); x = n_randtest(state); _fmpz_vec_scalar_addmul_ui(b, a, len, x); _fmpz_vec_scalar_mul_ui(d, a, len, x); _fmpz_vec_add(c, c, d, len); result = (_fmpz_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = %wd\n", x); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_divexact_fmpz.c000066400000000000000000000047611461254215100230170ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_divexact_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t n; slong len = n_randint(state, 100); fmpz_init(n); fmpz_randtest_not_zero(n, state, 100); if (n_randint(state, 2)) fmpz_neg(n, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_fmpz(a, a, len, n); _fmpz_vec_scalar_divexact_fmpz(b, a, len, n); _fmpz_vec_scalar_divexact_fmpz(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(n); } /* Check that a * n / n == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t n; slong len = n_randint(state, 100); fmpz_init(n); fmpz_randtest_not_zero(n, state, 100); if (n_randint(state, 2)) fmpz_neg(n, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); _fmpz_vec_scalar_mul_fmpz(a, a, len, n); _fmpz_vec_scalar_divexact_fmpz(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_divexact_si.c000066400000000000000000000043401461254215100224470ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_divexact_si, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); slong n; n = z_randtest_not_zero(state); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_si(a, a, len, n); _fmpz_vec_scalar_divexact_si(b, a, len, n); _fmpz_vec_scalar_divexact_si(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Check that a * n / n == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); slong n; n = z_randtest_not_zero(state); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); _fmpz_vec_scalar_mul_si(a, a, len, n); _fmpz_vec_scalar_divexact_si(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_divexact_ui.c000066400000000000000000000042571461254215100224600ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_divexact_ui, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; ulong n = n_randtest_not_zero(state); slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_ui(a, a, len, n); _fmpz_vec_scalar_divexact_ui(b, a, len, n); _fmpz_vec_scalar_divexact_ui(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Check that a * n / n == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; ulong n = n_randtest_not_zero(state); slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); _fmpz_vec_scalar_mul_ui(a, a, len, n); _fmpz_vec_scalar_divexact_ui(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_fdiv_q_fmpz.c000066400000000000000000000062561461254215100224610ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_fdiv_q_fmpz, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; fmpz_t n; mpz_t d, e, f, m; slong i; slong len = n_randint(state, 100); fmpz_init(n); fmpz_randtest_not_zero(n, state, 100); if (n_randint(state, 2)) fmpz_neg(n, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); _fmpz_vec_scalar_fdiv_q_fmpz(c, a, len, n); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(m); for (i = 0; i < len; i++) { fmpz_get_mpz(m, n); fmpz_get_mpz(d, b + i); mpz_fdiv_q(e, d, m); fmpz_get_mpz(f, c + i); result = (mpz_cmp(f, e) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, m = %Zd, e = %Zd, f = %Zd\n", d, m, e, f); fflush(stdout); flint_abort(); } } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); fmpz_clear(n); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(m); } /* Test aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t n; mpz_t d, e, f, m; slong i; slong len = n_randint(state, 100); fmpz_init(n); fmpz_randtest_not_zero(n, state, 100); if (n_randint(state, 2)) fmpz_neg(n, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); _fmpz_vec_scalar_fdiv_q_fmpz(a, a, len, n); mpz_init(d); mpz_init(e); mpz_init(f); mpz_init(m); for (i = 0; i < len; i++) { fmpz_get_mpz(m, n); fmpz_get_mpz(d, b + i); mpz_fdiv_q(e, d, m); fmpz_get_mpz(f, a + i); result = (mpz_cmp(f, e) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, m = %Zd, e = %Zd, f = %Zd\n", d, m, e, f); fflush(stdout); flint_abort(); } } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(n); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_mod_fmpz.c000066400000000000000000000045711461254215100217660ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_mod_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz *a, *b; slong len = n_randint(state, 100); fmpz_init(p); fmpz_randtest_unsigned(p, state, 100); fmpz_add_ui(p, p, 1); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mod_fmpz(b, a, len, p); _fmpz_vec_scalar_mod_fmpz(a, a, len, p); result = (_fmpz_vec_equal(a, a, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(p); } /* Check the result is reduced */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz *a, *b; slong j, len = n_randint(state, 100); fmpz_init(p); fmpz_randtest_unsigned(p, state, 100); fmpz_add_ui(p, p, 1); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mod_fmpz(b, a, len, p); result = 1; for (j = 0; j < len; j++) result &= (fmpz_sgn(b + j) >= 0 && fmpz_cmp(b + j, p) < 0); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fmpz_print(p), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_mul_2exp.c000066400000000000000000000044651461254215100217100ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_mul_2exp, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); ulong exp = n_randint(state, 200); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_2exp(b, a, len, exp); _fmpz_vec_scalar_mul_2exp(a, a, len, exp); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Check aliasing of (a*2^e1)*2^e2 equals a*2^(e1+e2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); ulong e1 = n_randint(state, 200); ulong e2 = n_randint(state, 200); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_2exp(b, a, len, e1); _fmpz_vec_scalar_mul_2exp(b, b, len, e2); _fmpz_vec_scalar_mul_2exp(a, a, len, e1 + e2); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("e1 = %wu, e2 = %wu\n", e1, e2); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_mul_fmpz.c000066400000000000000000000100121461254215100217670ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_mul_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t n; slong len = n_randint(state, 100); fmpz_init(n); fmpz_randtest(n, state, 100); if (n_randint(state, 2)) fmpz_neg(n, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_fmpz(b, a, len, n); _fmpz_vec_scalar_mul_fmpz(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(n); } /* Check that n (a + b) == na + nb */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *lhs, *rhs; fmpz_t n; slong len = n_randint(state, 100); fmpz_init(n); fmpz_randtest(n, state, 100); if (n_randint(state, 2)) fmpz_neg(n, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); lhs = _fmpz_vec_init(len); rhs = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_scalar_mul_fmpz(lhs, a, len, n); _fmpz_vec_scalar_mul_fmpz(rhs, b, len, n); _fmpz_vec_add(rhs, lhs, rhs, len); _fmpz_vec_add(lhs, a, b, len); _fmpz_vec_scalar_mul_fmpz(lhs, lhs, len, n); result = (_fmpz_vec_equal(lhs, rhs, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(lhs, len), flint_printf("\n\n"); _fmpz_vec_print(rhs, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(lhs, len); _fmpz_vec_clear(rhs, len); fmpz_clear(n); } /* Check that n2 * (n1 a) == (n1 * n2) a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t n1, n2, n; slong len = n_randint(state, 100); fmpz_init(n1); fmpz_init(n2); fmpz_init(n); fmpz_randtest(n1, state, 100); fmpz_randtest(n2, state, 100); if (n_randint(state, 2)) fmpz_neg(n1, n1); if (n_randint(state, 2)) fmpz_neg(n2, n2); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_fmpz(b, a, len, n1); _fmpz_vec_scalar_mul_fmpz(b, b, len, n2); fmpz_mul(n, n1, n2); _fmpz_vec_scalar_mul_fmpz(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(n1); fmpz_clear(n2); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_mul_si.c000066400000000000000000000044341461254215100214410ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_mul_si, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); slong n = z_randtest(state); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_si(b, a, len, n); _fmpz_vec_scalar_mul_si(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Check agreement with _fmpz */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len, n; fmpz_t x; len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); n = z_randtest(state); fmpz_init(x); fmpz_set_si(x, n); _fmpz_vec_scalar_mul_fmpz(b, a, len, x); _fmpz_vec_scalar_mul_si(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); flint_printf("%li\n\n", n); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_mul_ui.c000066400000000000000000000043671461254215100214500ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_mul_ui, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); ulong n = n_randtest(state); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_mul_ui(b, a, len, n); _fmpz_vec_scalar_mul_ui(a, a, len, n); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Check agreement with _fmpz */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); ulong n = n_randbits(state, FLINT_BITS); fmpz_t x; a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); fmpz_init(x); _fmpz_vec_randtest(a, state, len, 200); fmpz_set_ui(x, n); _fmpz_vec_scalar_mul_ui(b, a, len, n); _fmpz_vec_scalar_mul_fmpz(a, a, len, x); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_smod_fmpz.c000066400000000000000000000056231461254215100221500ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_smod_fmpz, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; fmpz *a, *b; slong len = n_randint(state, 100); fmpz_init(p); fmpz_randtest_unsigned(p, state, 100); fmpz_add_ui(p, p, 1); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_smod_fmpz(b, a, len, p); _fmpz_vec_scalar_smod_fmpz(a, a, len, p); result = (_fmpz_vec_equal(a, a, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(p); } /* Check the result is reduced */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p, lo, hi; fmpz *a, *b; slong j, len = n_randint(state, 100); fmpz_init(p); fmpz_init(lo); fmpz_init(hi); fmpz_randtest_unsigned(p, state, 100); fmpz_add_ui(p, p, 1); if (fmpz_cmp_ui(p, 2) > 0) { fmpz_fdiv_q_2exp(hi, p, 1); fmpz_neg(lo, hi); } else if (fmpz_cmp_ui(p, 2) == 0) { fmpz_zero(lo); fmpz_one(hi); } else { fmpz_zero(lo); fmpz_zero(hi); } a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_scalar_smod_fmpz(b, a, len, p); result = 1; for (j = 0; j < len; j++) result &= (fmpz_cmp(lo, b + j) <= 0 && fmpz_cmp(b + j, hi) <= 0); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fmpz_print(p), flint_printf("\n\n"); fmpz_print(lo), flint_printf("\n\n"); fmpz_print(hi), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(p); fmpz_clear(lo); fmpz_clear(hi); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_submul_fmpz.c000066400000000000000000000054321461254215100225130ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_submul_fmpz, state) { int i, result; /* Compare with fmpz_vec_scalar_submul_si */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; slong len, n; fmpz_t n1; len = n_randint(state, 100); n = (slong) n_randbits(state, FLINT_BITS - 1); if (n_randint(state, 2)) n = -n; fmpz_init(n1); fmpz_set_si(n1, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); _fmpz_vec_scalar_submul_fmpz(b, a, len, n1); _fmpz_vec_scalar_submul_si(c, a, len, n); result = (_fmpz_vec_equal(c, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } /* Compute a different way */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len = n_randint(state, 100); fmpz_t n1; fmpz_init(n1); fmpz_randtest(n1, state, 200); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); _fmpz_vec_scalar_submul_fmpz(b, a, len, n1); _fmpz_vec_scalar_mul_fmpz(d, a, len, n1); _fmpz_vec_sub(c, c, d, len); result = (_fmpz_vec_equal(c, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_submul_si.c000066400000000000000000000032551461254215100221530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_submul_si, state) { int i, result; /* Compare with alternative method of computation */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len = n_randint(state, 100), x; a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); x = z_randtest(state); _fmpz_vec_scalar_submul_si(b, a, len, x); _fmpz_vec_scalar_mul_si(d, a, len, x); _fmpz_vec_sub(c, c, d, len); result = (_fmpz_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = %wd\n", x); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-scalar_submul_si_2exp.c000066400000000000000000000033641461254215100231120ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_scalar_submul_si_2exp, state) { int i, result; /* Compare with alternative method of computation */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len = n_randint(state, 100), x; flint_bitcnt_t exp; a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); x = z_randtest(state); exp = n_randint(state, 200); _fmpz_vec_scalar_submul_si_2exp(b, a, len, x, exp); _fmpz_vec_scalar_mul_2exp(d, a, len, exp); _fmpz_vec_scalar_submul_si(c, d, len, x); result = (_fmpz_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("x = %wd, exp = %wu\n", x, exp); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-set_equal.c000066400000000000000000000050331461254215100206020ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_set_equal, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(a, a, len); result = (_fmpz_vec_equal(a, a, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); } /* Compare copied vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); result = (_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } /* Compare unequal vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; slong len = n_randint(state, 100) + 1; slong coeff; a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_set(b, a, len); coeff = n_randint(state, len); fmpz_add_ui(b + coeff, b + coeff, 1); result = (!_fmpz_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-sub.c000066400000000000000000000060641461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_sub, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_sub(c, a, b, len); _fmpz_vec_sub(a, a, b, len); result = (_fmpz_vec_equal(a, c, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_sub(c, a, b, len); _fmpz_vec_sub(b, a, b, len); result = (_fmpz_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } /* Check a + b - b = a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c, *d; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_add(c, a, b, len); _fmpz_vec_sub(d, c, b, len); result = (_fmpz_vec_equal(d, a, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(d, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-sum.c000066400000000000000000000027621461254215100174320ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_sum, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b; fmpz_t x, y, z; slong len1 = n_randint(state, 100); slong len2 = n_randint(state, 100); a = _fmpz_vec_init(len1 + len2); b = a + len1; _fmpz_vec_randtest(a, state, len1 + len2, 200); fmpz_init(x); fmpz_init(y); fmpz_init(z); _fmpz_vec_sum(x, a, len1); _fmpz_vec_sum(y, b, len2); fmpz_add(x, x, y); _fmpz_vec_sum(z, a, len1 + len2); result = (fmpz_equal(x, z)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len1), flint_printf("\n\n"); _fmpz_vec_print(b, len2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len1 + len2); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-sum_max_bits.c000066400000000000000000000031601461254215100213110ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_sum_max_bits, state) { slong i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz * a; fmpz_t max, sum, t; slong sum_bits, max_bits; slong len = n_randint(state, 300); a = _fmpz_vec_init(len); fmpz_init(max); fmpz_init(sum); fmpz_init(t); _fmpz_vec_randtest(a, state, len, 300); _fmpz_vec_sum_max_bits(&sum_bits, &max_bits, a, len); fmpz_zero(max); fmpz_zero(sum); for (j = 0; j < len; j++) { fmpz_abs(t, a + j); fmpz_add(sum, sum, t); if (fmpz_cmp(max, t) < 0) fmpz_set(max, t); } if (sum_bits != fmpz_bits(sum)) { flint_printf("FAIL: sum bits is wrong\n"); fflush(stdout); flint_abort(); } if (max_bits != fmpz_bits(max)) { flint_printf("FAIL: max bits is wrong\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); fmpz_clear(max); fmpz_clear(sum); fmpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-swap.c000066400000000000000000000026231461254215100175740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_swap, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a, *b, *c; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); _fmpz_vec_swap(a, b, len); result = (_fmpz_vec_equal(a, c, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); _fmpz_vec_print(b, len), flint_printf("\n\n"); _fmpz_vec_print(c, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/test/t-zero.c000066400000000000000000000021331461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" TEST_FUNCTION_START(fmpz_vec_zero, state) { int i, result; /* Check it's zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz *a; slong len = n_randint(state, 100); a = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_zero(a, len); result = (_fmpz_vec_is_zero(a, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(a, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpz_vec/zero.c000066400000000000000000000010541461254215100163560ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void _fmpz_vec_zero(fmpz * vec, slong len) { slong i; for (i = 0; i < len; i++) fmpz_zero(vec + i); } flint-3.1.3/src/fmpzi.h000066400000000000000000000112421461254215100147200ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FMPZI_H #define FMPZI_H #ifdef FMPZI_INLINES_C #define FMPZI_INLINE #else #define FMPZI_INLINE static inline #endif #include "fmpz.h" #ifdef __cplusplus extern "C" { #endif #define fmpzi_realref(x) (&((x)->a)) #define fmpzi_imagref(x) (&((x)->b)) FMPZI_INLINE void fmpzi_init(fmpzi_t x) { fmpz_init(fmpzi_realref(x)); fmpz_init(fmpzi_imagref(x)); } FMPZI_INLINE void fmpzi_clear(fmpzi_t x) { fmpz_clear(fmpzi_realref(x)); fmpz_clear(fmpzi_imagref(x)); } FMPZI_INLINE int fmpzi_equal(const fmpzi_t x, const fmpzi_t y) { return fmpz_equal(fmpzi_realref(x), fmpzi_realref(y)) && fmpz_equal(fmpzi_imagref(x), fmpzi_imagref(y)); } FMPZI_INLINE void fmpzi_zero(fmpzi_t x) { fmpz_zero(fmpzi_realref(x)); fmpz_zero(fmpzi_imagref(x)); } FMPZI_INLINE void fmpzi_one(fmpzi_t x) { fmpz_one(fmpzi_realref(x)); fmpz_zero(fmpzi_imagref(x)); } FMPZI_INLINE void fmpzi_set(fmpzi_t res, const fmpzi_t x) { fmpz_set(fmpzi_realref(res), fmpzi_realref(x)); fmpz_set(fmpzi_imagref(res), fmpzi_imagref(x)); } FMPZI_INLINE void fmpzi_conj(fmpzi_t res, const fmpzi_t x) { fmpz_set(fmpzi_realref(res), fmpzi_realref(x)); fmpz_neg(fmpzi_imagref(res), fmpzi_imagref(x)); } FMPZI_INLINE void fmpzi_swap(fmpzi_t x, fmpzi_t y) { FLINT_SWAP(fmpzi_struct, *x, *y); } void fmpzi_print(const fmpzi_t x); FMPZI_INLINE void fmpzi_set_si_si(fmpzi_t res, slong a, slong b) { fmpz_set_si(fmpzi_realref(res), a); fmpz_set_si(fmpzi_imagref(res), b); } FMPZI_INLINE void fmpzi_randtest(fmpzi_t res, flint_rand_t state, mp_bitcnt_t bits) { fmpz_randtest(fmpzi_realref(res), state, bits); fmpz_randtest(fmpzi_imagref(res), state, bits); } /* Special values */ FMPZI_INLINE int fmpzi_is_unit(const fmpzi_t x) { if (fmpz_is_zero(fmpzi_imagref(x))) return fmpz_is_pm1(fmpzi_realref(x)); if (fmpz_is_zero(fmpzi_realref(x))) return fmpz_is_pm1(fmpzi_imagref(x)); return 0; } FMPZI_INLINE int fmpzi_is_zero(const fmpzi_t x) { return fmpz_is_zero(fmpzi_realref(x)) && fmpz_is_zero(fmpzi_imagref(x)); } FMPZI_INLINE int fmpzi_is_one(const fmpzi_t x) { return fmpz_is_one(fmpzi_realref(x)) && fmpz_is_zero(fmpzi_imagref(x)); } /* Norms */ slong fmpzi_bits(const fmpzi_t x); FMPZI_INLINE void fmpzi_norm(fmpz_t res, const fmpzi_t x) { fmpz_fmma(res, fmpzi_realref(x), fmpzi_realref(x), fmpzi_imagref(x), fmpzi_imagref(x)); } /* Arithmetic */ FMPZI_INLINE void fmpzi_neg(fmpzi_t res, const fmpzi_t x) { fmpz_neg(fmpzi_realref(res), fmpzi_realref(x)); fmpz_neg(fmpzi_imagref(res), fmpzi_imagref(x)); } FMPZI_INLINE void fmpzi_add(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) { fmpz_add(fmpzi_realref(res), fmpzi_realref(x), fmpzi_realref(y)); fmpz_add(fmpzi_imagref(res), fmpzi_imagref(x), fmpzi_imagref(y)); } FMPZI_INLINE void fmpzi_sub(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) { fmpz_sub(fmpzi_realref(res), fmpzi_realref(x), fmpzi_realref(y)); fmpz_sub(fmpzi_imagref(res), fmpzi_imagref(x), fmpzi_imagref(y)); } void fmpzi_sqr(fmpzi_t res, const fmpzi_t x); void fmpzi_mul(fmpzi_t res, const fmpzi_t x, const fmpzi_t y); void fmpzi_pow_ui(fmpzi_t res, const fmpzi_t x, ulong exp); void fmpzi_mul_i(fmpzi_t z, const fmpzi_t x); void fmpzi_div_i(fmpzi_t z, const fmpzi_t x); void fmpzi_mul_i_pow_si(fmpzi_t res, const fmpzi_t z, slong k); /* todo */ slong fmpzi_canonical_unit_i_pow(const fmpzi_t x); FMPZI_INLINE void fmpzi_canonicalise_unit(fmpzi_t res, const fmpzi_t x) { fmpzi_mul_i_pow_si(res, x, fmpzi_canonical_unit_i_pow(x)); } /* Division */ void fmpzi_divrem(fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y); void fmpzi_divrem_approx(fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y); void fmpzi_divexact(fmpzi_t q, const fmpzi_t x, const fmpzi_t y); slong fmpzi_remove_one_plus_i(fmpzi_t res, const fmpzi_t x); /* GCD */ void fmpzi_gcd_euclidean(fmpzi_t res, const fmpzi_t x, const fmpzi_t y); void fmpzi_gcd_euclidean_improved(fmpzi_t res, const fmpzi_t x, const fmpzi_t y); void fmpzi_gcd_binary(fmpzi_t res, const fmpzi_t x, const fmpzi_t y); void fmpzi_gcd_shortest(fmpzi_t g, const fmpzi_t x, const fmpzi_t y); void fmpzi_gcd(fmpzi_t g, const fmpzi_t x, const fmpzi_t y); /* Primality check */ int fmpzi_is_prime(const fmpzi_t n); int fmpzi_is_probabprime(const fmpzi_t n); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fmpzi/000077500000000000000000000000001461254215100145475ustar00rootroot00000000000000flint-3.1.3/src/fmpzi/bits.c000066400000000000000000000030071461254215100156540ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" slong fmpzi_bits(const fmpzi_t x) { ulong v; fmpz a, b; a = *fmpzi_realref(x); b = *fmpzi_imagref(x); if (!COEFF_IS_MPZ(a)) { if (!COEFF_IS_MPZ(b)) { v = FLINT_ABS(a) | FLINT_ABS(b); return FLINT_BIT_COUNT(v); } else { return mpz_sizeinbase(COEFF_TO_PTR(b), 2); } } else { if (!COEFF_IS_MPZ(b)) { return mpz_sizeinbase(COEFF_TO_PTR(a), 2); } else { __mpz_struct *z1, *z2; slong s1, s2; z1 = COEFF_TO_PTR(a); z2 = COEFF_TO_PTR(b); s1 = FLINT_ABS(z1->_mp_size); s2 = FLINT_ABS(z2->_mp_size); if (s1 == s2) { v = z1->_mp_d[s1 - 1] | z2->_mp_d[s1 - 1]; } else if (s1 > s2) { v = z1->_mp_d[s1 - 1]; } else { v = z2->_mp_d[s2 - 1]; s1 = s2; } return (s1 - 1) * FLINT_BITS + FLINT_BIT_COUNT(v); } } } flint-3.1.3/src/fmpzi/canonical_unit_i_pow.c000066400000000000000000000015631461254215100211030ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" slong fmpzi_canonical_unit_i_pow(const fmpzi_t x) { int s, t; s = fmpz_cmp(fmpzi_realref(x), fmpzi_imagref(x)); if (s == 0) { if (fmpz_sgn(fmpzi_realref(x)) < 0) return 2; else return 0; } else { t = fmpz_cmpabs(fmpzi_realref(x), fmpzi_imagref(x)); if (s > 0) return (t <= 0) ? 1 : 0; else return (t <= 0) ? 3 : 2; } } flint-3.1.3/src/fmpzi/div_i.c000066400000000000000000000013161461254215100160060ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_div_i(fmpzi_t z, const fmpzi_t x) { if (z == x) { fmpz_swap(fmpzi_realref(z), fmpzi_imagref(z)); fmpz_neg(fmpzi_imagref(z), fmpzi_imagref(z)); } else { fmpz_set(fmpzi_realref(z), fmpzi_imagref(x)); fmpz_neg(fmpzi_imagref(z), fmpzi_realref(x)); } } flint-3.1.3/src/fmpzi/divexact.c000066400000000000000000000075141461254215100165310ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "double_extras.h" #include "fmpzi.h" static void _fmpzi_divexact(fmpzi_t q, const fmpzi_t x, const fmpzi_t y) { fmpzi_t t, y_conj; fmpz_t v; mpz_t ytmp; fmpzi_init(t); fmpz_init(v); /* shallow conjugate */ *fmpzi_realref(y_conj) = *fmpzi_realref(y); if (!COEFF_IS_MPZ(*fmpzi_imagref(y))) { *fmpzi_imagref(y_conj) = -*fmpzi_imagref(y); } else { *ytmp = *COEFF_TO_PTR(*fmpzi_imagref(y)); mpz_neg(ytmp, ytmp); *fmpzi_imagref(y_conj) = PTR_TO_COEFF(ytmp); } fmpzi_mul(t, x, y_conj); fmpz_fmma(v, fmpzi_realref(y), fmpzi_realref(y), fmpzi_imagref(y), fmpzi_imagref(y)); fmpz_divexact(fmpzi_realref(q), fmpzi_realref(t), v); fmpz_divexact(fmpzi_imagref(q), fmpzi_imagref(t), v); fmpzi_clear(t); fmpz_clear(v); } void fmpzi_divexact(fmpzi_t q, const fmpzi_t x, const fmpzi_t y) { slong xbits, ybits, zbits, trunc; if (fmpz_is_zero(fmpzi_imagref(y))) { fmpz_divexact(fmpzi_imagref(q), fmpzi_imagref(x), fmpzi_realref(y)); fmpz_divexact(fmpzi_realref(q), fmpzi_realref(x), fmpzi_realref(y)); return; } if (fmpz_is_zero(fmpzi_realref(y))) { fmpz_divexact(fmpzi_realref(q), fmpzi_realref(x), fmpzi_imagref(y)); fmpz_divexact(fmpzi_imagref(q), fmpzi_imagref(x), fmpzi_imagref(y)); fmpzi_div_i(q, q); return; } xbits = fmpzi_bits(x); ybits = fmpzi_bits(y); if (ybits == 0) { flint_throw(FLINT_ERROR, "fmpzi_divexact: division by zero\n"); } if (xbits == 0) { fmpzi_zero(q); return; } /* todo: special cases? */ if (ybits == 1) { } zbits = xbits - ybits; if (zbits < 45) { double a, b, c, d, t, u, v, w, qa, qb; slong aexp, bexp, cexp, dexp; if (xbits < 500) { a = fmpz_get_d(fmpzi_realref(x)); b = fmpz_get_d(fmpzi_imagref(x)); c = fmpz_get_d(fmpzi_realref(y)); d = fmpz_get_d(fmpzi_imagref(y)); } else { a = fmpz_get_d_2exp(&aexp, fmpzi_realref(x)); b = fmpz_get_d_2exp(&bexp, fmpzi_imagref(x)); c = fmpz_get_d_2exp(&cexp, fmpzi_realref(y)); d = fmpz_get_d_2exp(&dexp, fmpzi_imagref(y)); a = d_mul_2exp(a, FLINT_MAX(aexp - xbits, -1024)); b = d_mul_2exp(b, FLINT_MAX(bexp - xbits, -1024)); c = d_mul_2exp(c, FLINT_MAX(cexp - xbits, -1024)); d = d_mul_2exp(d, FLINT_MAX(dexp - xbits, -1024)); } t = a * c + b * d; u = b * c - a * d; v = c * c + d * d; w = 0.5 / v; t = (2.0 * t + v) * w; u = (2.0 * u + v) * w; qa = floor(t); qb = floor(u); fmpz_set_d(fmpzi_realref(q), qa); fmpz_set_d(fmpzi_imagref(q), qb); return; } if (ybits > zbits * 1.25 + 256) { fmpzi_t t, u; fmpzi_init(t); fmpzi_init(u); trunc = ybits - zbits - 20; fmpz_tdiv_q_2exp(fmpzi_realref(t), fmpzi_realref(x), trunc); fmpz_tdiv_q_2exp(fmpzi_imagref(t), fmpzi_imagref(x), trunc); fmpz_tdiv_q_2exp(fmpzi_realref(u), fmpzi_realref(y), trunc); fmpz_tdiv_q_2exp(fmpzi_imagref(u), fmpzi_imagref(y), trunc); fmpzi_divrem_approx(q, NULL, t, u); fmpzi_clear(t); fmpzi_clear(u); } else { _fmpzi_divexact(q, x, y); } } flint-3.1.3/src/fmpzi/divrem.c000066400000000000000000000041321461254215100162010ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_divrem(fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y) { fmpzi_t t, y_conj; fmpz_t v; mpz_t ytmp; slong xbits, ybits; xbits = fmpzi_bits(x); ybits = fmpzi_bits(y); if (ybits == 0) { flint_throw(FLINT_ERROR, "fmpzi_divrem: division by zero\n"); } if (xbits == 0) { fmpzi_zero(q); if (r != NULL) fmpzi_zero(r); return; } if (xbits < ybits - 2) { if (r != NULL) fmpzi_set(r, x); fmpzi_zero(q); return; } if (q == x || q == y) { fmpzi_init(t); fmpzi_divrem(t, r, x, y); fmpzi_swap(q, t); fmpzi_clear(t); return; } fmpzi_init(t); fmpz_init(v); /* shallow conjugate */ *fmpzi_realref(y_conj) = *fmpzi_realref(y); if (!COEFF_IS_MPZ(*fmpzi_imagref(y))) { *fmpzi_imagref(y_conj) = -*fmpzi_imagref(y); } else { *ytmp = *COEFF_TO_PTR(*fmpzi_imagref(y)); mpz_neg(ytmp, ytmp); *fmpzi_imagref(y_conj) = PTR_TO_COEFF(ytmp); } fmpzi_mul(t, x, y_conj); fmpz_mul_2exp(fmpzi_realref(t), fmpzi_realref(t), 1); fmpz_mul_2exp(fmpzi_imagref(t), fmpzi_imagref(t), 1); fmpz_fmma(v, fmpzi_realref(y), fmpzi_realref(y), fmpzi_imagref(y), fmpzi_imagref(y)); fmpz_add(fmpzi_realref(t), fmpzi_realref(t), v); fmpz_add(fmpzi_imagref(t), fmpzi_imagref(t), v); fmpz_mul_2exp(v, v, 1); fmpz_fdiv_q(fmpzi_realref(q), fmpzi_realref(t), v); fmpz_fdiv_q(fmpzi_imagref(q), fmpzi_imagref(t), v); if (r != NULL) { fmpzi_mul(t, q, y); fmpzi_sub(r, x, t); } fmpzi_clear(t); fmpz_clear(v); } flint-3.1.3/src/fmpzi/divrem_approx.c000066400000000000000000000050561461254215100176000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "double_extras.h" #include "fmpzi.h" void fmpzi_divrem_approx(fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y) { slong xbits, ybits; xbits = fmpzi_bits(x); ybits = fmpzi_bits(y); if (ybits == 0) { flint_throw(FLINT_ERROR, "fmpzi_divrem_approx: division by zero\n"); } if (xbits == 0) { fmpzi_zero(q); if (r != NULL) fmpzi_zero(r); return; } if (xbits < ybits - 2) { if (r != NULL) fmpzi_set(r, x); fmpzi_zero(q); return; } if (xbits < ybits + 45) { double a, b, c, d, t, u, v, w, qa, qb; slong aexp, bexp, cexp, dexp; if (xbits < 500) { a = fmpz_get_d(fmpzi_realref(x)); b = fmpz_get_d(fmpzi_imagref(x)); c = fmpz_get_d(fmpzi_realref(y)); d = fmpz_get_d(fmpzi_imagref(y)); } else { a = fmpz_get_d_2exp(&aexp, fmpzi_realref(x)); b = fmpz_get_d_2exp(&bexp, fmpzi_imagref(x)); c = fmpz_get_d_2exp(&cexp, fmpzi_realref(y)); d = fmpz_get_d_2exp(&dexp, fmpzi_imagref(y)); a = d_mul_2exp(a, FLINT_MAX(aexp - xbits, -1024)); b = d_mul_2exp(b, FLINT_MAX(bexp - xbits, -1024)); c = d_mul_2exp(c, FLINT_MAX(cexp - xbits, -1024)); d = d_mul_2exp(d, FLINT_MAX(dexp - xbits, -1024)); } t = a * c + b * d; u = b * c - a * d; v = c * c + d * d; w = 0.5 / v; t = (2.0 * t + v) * w; u = (2.0 * u + v) * w; qa = floor(t); qb = floor(u); if (r != NULL) { fmpzi_t t, u; fmpzi_init(t); fmpzi_init(u); fmpz_set_d(fmpzi_realref(u), qa); fmpz_set_d(fmpzi_imagref(u), qb); fmpzi_mul(t, u, y); fmpzi_sub(r, x, t); fmpzi_swap(q, u); fmpzi_clear(t); fmpzi_clear(u); } else { fmpz_set_d(fmpzi_realref(q), qa); fmpz_set_d(fmpzi_imagref(q), qb); } return; } fmpzi_divrem(q, r, x, y); } flint-3.1.3/src/fmpzi/gcd.c000066400000000000000000000041071461254215100154520ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" #if FLINT_BITS == 64 #define GCD_MAX_D WORD(1125899906842623) #define GCD_MIN_D WORD(-1125899906842623) #else #define GCD_MAX_D COEFF_MAX #define GCD_MIN_D COEFF_MIN #endif void _fmpzi_gcd_dddd(fmpzi_t res, double a, double b, double c, double d); void fmpzi_gcd(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) { fmpz a, b, c, d; slong bits1, bits2; if (fmpzi_is_zero(x)) { fmpzi_canonicalise_unit(res, y); return; } if (fmpzi_is_zero(y)) { fmpzi_canonicalise_unit(res, x); return; } a = *fmpzi_realref(x); b = *fmpzi_imagref(x); c = *fmpzi_realref(y); d = *fmpzi_imagref(y); if (GCD_MIN_D <= a && a <= GCD_MAX_D && GCD_MIN_D <= b && b <= GCD_MAX_D && GCD_MIN_D <= c && c <= GCD_MAX_D && GCD_MIN_D <= d && d <= GCD_MAX_D) { _fmpzi_gcd_dddd(res, a, b, c, d); return; } if ((!COEFF_IS_MPZ(a) && !COEFF_IS_MPZ(b)) || (!COEFF_IS_MPZ(c) && !COEFF_IS_MPZ(d))) { fmpzi_gcd_euclidean_improved(res, x, y); return; } bits1 = fmpzi_bits(x); bits2 = fmpzi_bits(y); if (bits1 <= 30000 || bits2 <= 30000) { fmpzi_gcd_euclidean_improved(res, x, y); return; } if (bits1 > bits2 * 1.5 + 64) { fmpzi_t q; fmpzi_init(q); fmpzi_divrem_approx(q, res, x, y); fmpzi_gcd_shortest(res, res, y); fmpzi_clear(q); } else if (bits2 > bits1 * 1.5 + 64) { fmpzi_t q; fmpzi_init(q); fmpzi_divrem_approx(q, res, y, x); fmpzi_gcd_shortest(res, x, res); fmpzi_clear(q); } else { fmpzi_gcd_shortest(res, x, y); } } flint-3.1.3/src/fmpzi/gcd_binary.c000066400000000000000000000064521461254215100170230ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "double_extras.h" #include "fmpzi.h" double fmpzi_norm_approx_d_2exp(slong * exp, const fmpzi_t x) { double a, b; slong aexp, bexp; int e; a = fmpz_get_d_2exp(&aexp, fmpzi_realref(x)); b = fmpz_get_d_2exp(&bexp, fmpzi_imagref(x)); if (aexp >= bexp) { if (aexp >= bexp + 64) b = 0.0; else b = d_mul_2exp(b, aexp - bexp); } else { if (bexp >= aexp + 64) a = 0.0; else a = d_mul_2exp(a, bexp - aexp); } a = a * a + b * b; a = frexp(a, &e); aexp += e; *exp = aexp; return a; } double fmpzi_norm_approx_d(const fmpzi_t x) { double a, b; a = fmpz_get_d(fmpzi_realref(x)); b = fmpz_get_d(fmpzi_imagref(x)); return a * a + b * b; } void fmpzi_gcd_binary(fmpzi_t res, const fmpzi_t X, const fmpzi_t Y) { fmpzi_t x, y, z; slong hx, hy; if (fmpzi_is_zero(X)) { fmpzi_canonicalise_unit(res, Y); return; } if (fmpzi_is_zero(Y)) { fmpzi_canonicalise_unit(res, X); return; } /* not implemented */ if (fmpzi_bits(X) > 500 || fmpzi_bits(Y) > 500) { fmpzi_gcd_euclidean(res, X, Y); return; } fmpzi_init(x); fmpzi_init(y); fmpzi_init(z); hx = fmpzi_remove_one_plus_i(x, X); hy = fmpzi_remove_one_plus_i(y, Y); if (fmpzi_norm_approx_d(x) < fmpzi_norm_approx_d(y)) fmpzi_swap(x, y); while (!fmpzi_is_zero(y)) { double a, b, c, d; double N, N1, N2, N3, N4; a = fmpz_get_d(fmpzi_realref(x)); b = fmpz_get_d(fmpzi_imagref(x)); c = fmpz_get_d(fmpzi_realref(y)); d = fmpz_get_d(fmpzi_imagref(y)); N1 = (a + b) * (a + b) + (c + d) * (c + d); N2 = (a - b) * (a - b) + (c - d) * (c - d); N3 = (a - d) * (a - d) + (b + c) * (b + c); N4 = (a + d) * (a + d) + (b - c) * (b - c); N = FLINT_MIN(FLINT_MIN(N1, N2), FLINT_MIN(N3, N4)); if (N == N1) { fmpzi_add(z, x, y); } else if (N == N2) { fmpzi_sub(z, x, y); } else if (N == N3) { fmpz_sub(fmpzi_realref(z), fmpzi_realref(x), fmpzi_imagref(y)); fmpz_add(fmpzi_imagref(z), fmpzi_imagref(x), fmpzi_realref(y)); } else { fmpz_add(fmpzi_realref(z), fmpzi_realref(x), fmpzi_imagref(y)); fmpz_sub(fmpzi_imagref(z), fmpzi_imagref(x), fmpzi_realref(y)); } fmpzi_remove_one_plus_i(x, z); if (fmpzi_norm_approx_d(x) < fmpzi_norm_approx_d(y)) fmpzi_swap(x, y); } fmpzi_swap(res, x); hx = FLINT_MIN(hx, hy); if (hx != 0) { fmpzi_set_si_si(x, 1, 1); fmpzi_pow_ui(x, x, hx); fmpzi_mul(res, res, x); } fmpzi_canonicalise_unit(res, res); fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(z); } flint-3.1.3/src/fmpzi/gcd_euclidean.c000066400000000000000000000021011461254215100174530ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_gcd_euclidean(fmpzi_t res, const fmpzi_t X, const fmpzi_t Y) { fmpzi_t x, y, q, r; if (fmpzi_is_zero(X)) { fmpzi_canonicalise_unit(res, Y); return; } if (fmpzi_is_zero(Y)) { fmpzi_canonicalise_unit(res, X); return; } fmpzi_init(x); fmpzi_init(y); fmpzi_init(q); fmpzi_init(r); fmpzi_set(x, X); fmpzi_set(y, Y); while (!fmpzi_is_zero(y)) { fmpzi_divrem(q, r, x, y); fmpzi_swap(x, y); fmpzi_swap(y, r); } fmpzi_swap(res, x); fmpzi_canonicalise_unit(res, res); fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(q); fmpzi_clear(r); } flint-3.1.3/src/fmpzi/gcd_euclidean_improved.c000066400000000000000000000054051461254215100213720ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpzi.h" #if FLINT_BITS == 64 #define GCD_MAX_D WORD(1125899906842623) #define GCD_MIN_D WORD(-1125899906842623) #else #define GCD_MAX_D COEFF_MAX #define GCD_MIN_D COEFF_MIN #endif void _fmpzi_gcd_dddd(fmpzi_t res, double a, double b, double c, double d) { double t, u, v, w, qa, qb; while (c != 0 || d != 0) { t = a * c + b * d; u = b * c - a * d; v = c * c + d * d; w = 0.5 / v; qa = floor((2.0 * t + v) * w); qb = floor((2.0 * u + v) * w); t = a - (qa * c - qb * d); u = b - (qb * c + qa * d); a = c; b = d; c = t; d = u; } if (a < 0) { a = -a; b = -b; } if (b > 0 && b > a) { t = b; b = -a; a = t; } else if (b < 0 && b <= -a) { t = b; b = a; a = -t; } fmpzi_set_si_si(res, a, b); } void fmpzi_gcd_euclidean_improved(fmpzi_t res, const fmpzi_t X, const fmpzi_t Y) { fmpzi_t x, y, q, r; fmpz a, b, c, d; if (fmpzi_is_zero(X)) { fmpzi_canonicalise_unit(res, Y); return; } if (fmpzi_is_zero(Y)) { fmpzi_canonicalise_unit(res, X); return; } a = *fmpzi_realref(X); b = *fmpzi_imagref(X); c = *fmpzi_realref(Y); d = *fmpzi_imagref(Y); if (GCD_MIN_D <= a && a <= GCD_MAX_D && GCD_MIN_D <= b && b <= GCD_MAX_D && GCD_MIN_D <= c && c <= GCD_MAX_D && GCD_MIN_D <= d && d <= GCD_MAX_D) { _fmpzi_gcd_dddd(res, a, b, c, d); return; } fmpzi_init(x); fmpzi_init(y); fmpzi_init(q); fmpzi_init(r); fmpzi_set(x, X); fmpzi_set(y, Y); while (!fmpzi_is_zero(y)) { a = *fmpzi_realref(x); b = *fmpzi_imagref(x); c = *fmpzi_realref(y); d = *fmpzi_imagref(y); if (GCD_MIN_D <= a && a <= GCD_MAX_D && GCD_MIN_D <= b && b <= GCD_MAX_D && GCD_MIN_D <= c && c <= GCD_MAX_D && GCD_MIN_D <= d && d <= GCD_MAX_D) { _fmpzi_gcd_dddd(res, a, b, c, d); goto cleanup; } fmpzi_divrem_approx(q, r, x, y); fmpzi_swap(x, y); fmpzi_swap(y, r); } fmpzi_swap(res, x); fmpzi_canonicalise_unit(res, res); cleanup: fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(q); fmpzi_clear(r); } flint-3.1.3/src/fmpzi/gcd_shortest.c000066400000000000000000000256351461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" #include "fmpq.h" /* return with (u1,u2) = t1*(c,b) + t2*(0,a) = the l_infty shortest vector in ZZ*(c, b) + ZZ*(0, a) !!! Note !!! must return (u1,u2) = (1,0) or (0,1) in the case [c b; 0 a] = [1 0; 0 1] The shortest is u = y*(c,b) - x*(0,a) for some t = (y,-x) in ZZ^2 (x/y) is either the last convergent of b/a that lies outside [(b-c)/a, (b+c)/a] or the first convergent that lies inside Simple fact: If I is a finite interval containing an integer with I > 1, then for any z in I, either the first or second convergent of z is in I. Outputs shouldn't alias the inputs. */ void _fmpz_mat22_shortest_l_infinity( fmpz_t u1, fmpz_t u2, fmpz_t t1, fmpz_t t2, const fmpz_t c, const fmpz_t b, const fmpz_t a) { int vcmp, tries_left; _fmpq_cfrac_list_t s; _fmpz_mat22_t m; _fmpq_ball_t x; fmpz_t Q; FLINT_ASSERT(fmpz_cmp_si(c, 0) > 0); FLINT_ASSERT(fmpz_cmp(a, b) > 0); FLINT_ASSERT(fmpz_cmp_si(b, 0) >= 0); fmpz_add(u1, b, c); fmpz_sub(u2, b, c); if (fmpz_cmp(a, c) <= 0) { fmpz_zero(u1); fmpz_set(u2, a); fmpz_zero(t1); fmpz_one(t2); return; } else if (fmpz_sgn(u2) <= 0) { fmpz_set(u1, c); fmpz_set(u2, b); fmpz_one(t1); fmpz_zero(t2); return; } else if (fmpz_cmp(a, u1) <= 0) { fmpz_set(u1, c); fmpz_sub(u2, b, a); fmpz_one(t1); fmpz_set_si(t2, -1); return; } fmpz_init(Q); _fmpq_cfrac_list_init(s); s->length = -1; /* don't need partial quotients */ _fmpz_mat22_init(m); _fmpz_mat22_one(m); /* initialize x manually */ fmpz_init_set(x->left_num, a); fmpz_init(x->left_den); fmpz_swap(x->left_den, u1); fmpz_init_set(x->right_num, a); fmpz_init(x->right_den); fmpz_swap(x->right_den, u2); x->exact = 0; _fmpq_ball_get_cfrac(s, m, 1, x); #define v12 x->left_den #define v22 x->left_num #define v11 x->right_den #define v21 x->right_num fmpz_add(v12, v12, v11); fmpz_fdiv_q_2exp(v12, v12, 1); fmpz_add(v22, v22, v21); fmpz_fdiv_q_2exp(v22, v22, 1); if (m->det < 0) fmpz_neg(v12, v12); else fmpz_neg(v22, v22); fmpz_mul(v11, m->_11, c); fmpz_mul(v21, m->_12, c); #if FLINT_WANT_ASSERT { fmpz_t tt; fmpz_init(tt); /* The remainder ball provides v12 and v22 easily in: v11 == m11*c v12 == m11*b - m21*a v21 == m12*c v22 == m12*b - m22*a */ fmpz_mul(tt, m->_11, c); FLINT_ASSERT(fmpz_equal(tt, v11)); fmpz_fmms(tt, m->_11, b, m->_21, a); FLINT_ASSERT(fmpz_equal(tt, v12)); fmpz_mul(tt, m->_12, c); FLINT_ASSERT(fmpz_equal(tt, v21)); fmpz_fmms(tt, m->_12, b, m->_22, a); FLINT_ASSERT(fmpz_equal(tt, v22)); fmpz_clear(tt); } #endif vcmp = fmpz_cmpabs(v11, v12); /* get_cfrac ensures I = M^-1([a/(b+c) a/(b-c)]) satisfies the simple fact. We have |m11*c| >= |m11*b - m21*a| iff a/(b-c) <= m11/m21 <= a/(b+c). */ FLINT_ASSERT(vcmp < 0); /* since infty = M^-1(m11/m21) is outside of I. */ /* u is best, t is transformation to best */ fmpz_set(u1, v11); fmpz_set(u2, v12); fmpz_set(t1, m->_11); fmpz_neg(t2, m->_21); /* The simple fact is satisfied with z = M^-1(a/b): generate at most two more convergents q1 and q2. |v12| is decreasing and |v11| is increasing. We are done as soon as |v11| >= |v12|, since then a/(b+c) <= m11/21 <= a/(b-c), which is the same thing as q1 or q1+1/q2 in I. */ tries_left = 2; while (--tries_left >= 0 && vcmp < 0) { fmpz_tdiv_q(Q, v22, v12); FLINT_ASSERT(fmpz_cmp_si(Q, 0) < 0); FLINT_ASSERT(fmpz_cmpabs(u1, u2) < 0); fmpz_submul(m->_12, m->_11, Q); fmpz_swap(m->_12, m->_11); fmpz_submul(m->_22, m->_21, Q); fmpz_swap(m->_22, m->_21); fmpz_submul(v21, v11, Q); fmpz_swap(v21, v11); fmpz_submul(v22, v12, Q); fmpz_swap(v22, v12); vcmp = fmpz_cmpabs(v11, v12); if (fmpz_cmpabs(vcmp < 0 ? v12 : v11, u2) < 0) { /* these could be swaps on last interation */ fmpz_set(u1, v11); fmpz_set(u2, v12); fmpz_set(t1, m->_11); fmpz_neg(t2, m->_21); } } #undef v11 #undef v12 #undef v21 #undef v22 fmpz_clear(Q); _fmpq_cfrac_list_clear(s); _fmpz_mat22_clear(m); _fmpq_ball_clear(x); } void _fmpzi_gcd_fmpz_shortest( fmpz_t gx, fmpz_t gy, const fmpz_t ax_, const fmpz_t ay_, const fmpz_t b) { fmpz_t A, B, C, ga, ua, va, g, u, v, axog, ayog, m1, m2, m3, m4; fmpz_t t, ax_copy, ay_copy; const fmpz* ax = ax_; const fmpz* ay = ay_; if (fmpz_is_zero(b)) { fmpz_set(gx, ax); fmpz_set(gy, ay); return; } fmpz_init(t); fmpz_init(ax_copy); fmpz_init(ay_copy); /* reduce ax+i*ay by b */ if (fmpz_cmpabs(ax, b) > 0) { fmpz_tdiv_qr(t, ax_copy, ax, b); ax = ax_copy; } if (fmpz_cmpabs(ay, b) > 0) { fmpz_tdiv_qr(t, ay_copy, ay, b); ay = ay_copy; } if (fmpz_is_zero(ax)) { fmpz_gcd(gx, ay, b); fmpz_zero(gy); goto cleanup_stage1; } else if (fmpz_is_zero(ay)) { fmpz_gcd(gx, ax, b); fmpz_zero(gy); goto cleanup_stage1; } fmpz_init(A); fmpz_init(B); fmpz_init(C); fmpz_init(ga); fmpz_init(ua); fmpz_init(va); fmpz_init(g); fmpz_init(u); fmpz_init(v); fmpz_init(axog); fmpz_init(ayog); fmpz_init(m1); fmpz_init(m2); fmpz_init(m3); fmpz_init(m4); fmpz_xgcd(ga, ua, va, ax, ay); fmpz_xgcd(g, u, v, ga, b); /* v not needed */ fmpz_divexact(axog, ax, g); fmpz_divexact(ayog, ay, g); fmpz_fmms(m1, ayog, ua, axog, va); fmpz_fmma(m2, ax, axog, ay, ayog); fmpz_divexact(m2, m2, ga); fmpz_divexact(B, b, g); fmpz_gcd(A, m2, B); fmpz_one(C); fmpz_mul(B, m1, u); fmpz_mod(B, B, A); _fmpz_mat22_shortest_l_infinity(gx, gy, u, v, C, B, A); fmpz_mul(gx, gx, g); fmpz_mul(gy, gy, g); fmpz_clear(A); fmpz_clear(B); fmpz_clear(C); fmpz_clear(ga); fmpz_clear(ua); fmpz_clear(va); fmpz_clear(g); fmpz_clear(u); fmpz_clear(v); fmpz_clear(axog); fmpz_clear(ayog); fmpz_clear(m1); fmpz_clear(m2); fmpz_clear(m3); fmpz_clear(m4); cleanup_stage1: fmpz_clear(t); fmpz_clear(ax_copy); fmpz_clear(ay_copy); } /* ax ay g*1 g*B g = gcd(gx, gy) -ay ax row ops 0 g*A g^2*A = norm(gx + i*gy) bx by ------> 0 0 -by bx 0 0 Except when the gcd is purely real or purely imaginary, it is any shortest vector in the above lattice in the l_infinity norm. In the exceptional case, it turns out that A = 1 and B = 0, and we rely on _shortest_l_infinity returning (1,0) or (0,1) instead of (1,1) in this case. */ void _fmpzi_gcd_shortest( fmpz_t gx, fmpz_t gy, const fmpz_t ax, const fmpz_t ay, const fmpz_t bx_, const fmpz_t by_) { fmpz_t A, B, C, ag, t1, t2, bg, bu, bv, g, u, v, m1, m2, m3, m4; fmpz_t bx_copy, by_copy; const fmpz* bx = bx_; const fmpz* by = by_; /* ensure norm(a) <= norm(b) approximately */ { slong ax_size = fmpz_size(ax); slong ay_size = fmpz_size(ay); slong bx_size = fmpz_size(bx); slong by_size = fmpz_size(by); if (FLINT_MAX(ax_size, ay_size) > FLINT_MAX(bx_size, by_size)) { FLINT_SWAP(const fmpz *, ax, bx); FLINT_SWAP(const fmpz *, ay, by); } } if (fmpz_is_zero(ax)) { _fmpzi_gcd_fmpz_shortest(gx, gy, bx, by, ay); return; } else if (fmpz_is_zero(ay)) { _fmpzi_gcd_fmpz_shortest(gx, gy, bx, by, ax); return; } fmpz_init(A); fmpz_init(B); fmpz_init(C); fmpz_init(ag); fmpz_init(t1); fmpz_init(t2); fmpz_init(bg); fmpz_init(bu); fmpz_init(bv); fmpz_init(g); fmpz_init(u); fmpz_init(v); fmpz_init(m1); fmpz_init(m2); fmpz_init(m3); fmpz_init(m4); fmpz_init(bx_copy); fmpz_init(by_copy); /* first find t1*ax + t2*ay = ag [ ax, ay] [ag, t1*ay - t2*ax ] [-ay, ax] ---> [ 0, (ax^2+ay^2)/ag] */ fmpz_xgcd(ag, t1, t2, ax, ay); fmpz_fmms(m1, t1, ay, t2, ax); fmpz_fmma(m2, ax, ax, ay, ay); fmpz_divexact(m2, m2, ag); /* next reduce bx+i*by by (ax^2+ay^2)/ag */ if (fmpz_cmpabs(bx, m2) > 0) { fmpz_tdiv_qr(t1, bx_copy, bx, m2); bx = bx_copy; } if (fmpz_cmpabs(by, m2) > 0) { fmpz_tdiv_qr(t1, by_copy, by, m2); by = by_copy; } /* now reduce [bx by; -by bx] */ if (fmpz_is_zero(bx) && fmpz_is_zero(by)) { /* avoid division by bg below */ fmpz_set(gx, ax); fmpz_set(gy, ay); goto cleanup; } fmpz_xgcd(bg, bu, bv, bx, by); fmpz_xgcd(g, u, v, ag, bg); if (!fmpz_is_one(g)) { fmpz_divexact(m1, m1, g); fmpz_divexact(m2, m2, g); fmpz_divexact(t1, bx, g); fmpz_divexact(t2, by, g); fmpz_fmms(m3, bu, t2, bv, t1); fmpz_fmma(m4, bx, t1, by, t2); } else { fmpz_fmms(m3, bu, by, bv, bx); fmpz_fmma(m4, bx, bx, by, by); } fmpz_divexact(m4, m4, bg); /* now reduce the one remaining 2x2 */ fmpz_fmms(t1, m3, ag, m1, bg); fmpz_fmma(m1, m1, u, m3, v); if (fmpz_is_one(g)) fmpz_swap(m3, t1); else fmpz_divexact(m3, t1, g); /* reduce last column */ fmpz_gcd3(A, m2, m3, m4); fmpz_fdiv_qr(t1, B, m1, A); fmpz_one(C); _fmpz_mat22_shortest_l_infinity(gx, gy, u, v, C, B, A); fmpz_mul(gx, gx, g); fmpz_mul(gy, gy, g); cleanup: fmpz_clear(A); fmpz_clear(B); fmpz_clear(C); fmpz_clear(ag); fmpz_clear(t1); fmpz_clear(t2); fmpz_clear(bg); fmpz_clear(bu); fmpz_clear(bv); fmpz_clear(g); fmpz_clear(u); fmpz_clear(v); fmpz_clear(m1); fmpz_clear(m2); fmpz_clear(m3); fmpz_clear(m4); fmpz_clear(bx_copy); fmpz_clear(by_copy); } void fmpzi_gcd_shortest(fmpzi_t g, const fmpzi_t a, const fmpzi_t b) { _fmpzi_gcd_shortest(fmpzi_realref(g), fmpzi_imagref(g), fmpzi_realref(a), fmpzi_imagref(a), fmpzi_realref(b), fmpzi_imagref(b)); fmpzi_canonicalise_unit(g, g); } flint-3.1.3/src/fmpzi/inlines.c000066400000000000000000000006521461254215100163570ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FMPZI_INLINES_C #include "fmpzi.h" flint-3.1.3/src/fmpzi/io.c000066400000000000000000000011311461254215100153160ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_print(const fmpzi_t x) { fmpz_print(fmpzi_realref(x)); if (fmpz_sgn(fmpzi_imagref(x)) >= 0) flint_printf("+"); fmpz_print(fmpzi_imagref(x)); flint_printf("*I"); } flint-3.1.3/src/fmpzi/is_prime.c000066400000000000000000000016171461254215100165270ustar00rootroot00000000000000/* Copyright (C) 2023 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" int fmpzi_is_prime(const fmpzi_t n) { fmpz_t t; const fmpz *a, *b; int res = 0; fmpz_init(t); a = fmpzi_realref(n); b = fmpzi_imagref(n); if (fmpz_is_zero(b)) { if (fmpz_tdiv_ui(a, 4) == 3) fmpz_abs(t, a); } else if (fmpz_is_zero(a)) { if (fmpz_tdiv_ui(b, 4) == 3) fmpz_abs(t, b); } else { fmpzi_norm(t, n); } res = fmpz_is_prime(t); fmpz_clear(t); return res; } flint-3.1.3/src/fmpzi/is_probabprime.c000066400000000000000000000016331461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2023 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" int fmpzi_is_probabprime(const fmpzi_t n) { fmpz_t t; const fmpz *a, *b; int res = 0; fmpz_init(t); a = fmpzi_realref(n); b = fmpzi_imagref(n); if (fmpz_is_zero(b)) { if (fmpz_tdiv_ui(a, 4) == 3) fmpz_abs(t, a); } else if (fmpz_is_zero(a)) { if (fmpz_tdiv_ui(b, 4) == 3) fmpz_abs(t, b); } else { fmpzi_norm(t, n); } res = fmpz_is_probabprime(t); fmpz_clear(t); return res; } flint-3.1.3/src/fmpzi/mul.c000066400000000000000000000052061461254215100155130ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_mul(fmpzi_t res, const fmpzi_t x, const fmpzi_t y) { slong asize, bsize, csize, dsize; fmpzi_struct * rp; fmpzi_t tmp; fmpz * t; fmpz * u; int xsmall, ysmall; const fmpz *a = fmpzi_realref(x); const fmpz *b = fmpzi_imagref(x); const fmpz *c = fmpzi_realref(y); const fmpz *d = fmpzi_imagref(y); const fmpz ca = *a; const fmpz cb = *b; const fmpz cc = *c; const fmpz cd = *d; if (x == y) { fmpzi_sqr(res, x); return; } xsmall = !COEFF_IS_MPZ(ca) && !COEFF_IS_MPZ(cb); ysmall = !COEFF_IS_MPZ(cc) && !COEFF_IS_MPZ(cd); if (xsmall && ysmall) { ulong thi, tlo, uhi, ulo, ahi, alo, bhi, blo; smul_ppmm(thi, tlo, ca, cc); smul_ppmm(uhi, ulo, cb, cd); sub_ddmmss(ahi, alo, thi, tlo, uhi, ulo); smul_ppmm(thi, tlo, ca, cd); smul_ppmm(uhi, ulo, cb, cc); add_ssaaaa(bhi, blo, thi, tlo, uhi, ulo); fmpz_set_signed_uiui(fmpzi_realref(res), ahi, alo); fmpz_set_signed_uiui(fmpzi_imagref(res), bhi, blo); return; } /* todo: detect pure real and imaginary operands */ if (res == x || res == y) { fmpzi_init(tmp); rp = tmp; } else { rp = res; } t = fmpzi_realref(rp); u = fmpzi_imagref(rp); if (!xsmall && !ysmall) { asize = fmpz_size(a); if (asize >= 13) { bsize = fmpz_size(b); csize = fmpz_size(c); dsize = fmpz_size(d); if (csize >= 13 && FLINT_ABS(asize - bsize) <= 2 && FLINT_ABS(csize - dsize) <= 2) { fmpz_t v; fmpz_init(v); fmpz_add(t, a, b); fmpz_add(v, c, d); fmpz_mul(u, t, v); fmpz_mul(t, a, c); fmpz_mul(v, b, d); fmpz_sub(u, u, t); fmpz_sub(u, u, v); fmpz_sub(t, t, v); fmpz_clear(v); goto cleanup; } } } fmpz_mul(t, a, c); fmpz_submul(t, b, d); fmpz_mul(u, a, d); fmpz_addmul(u, b, c); cleanup: if (res == x || res == y) { fmpzi_swap(res, tmp); fmpzi_clear(tmp); } } flint-3.1.3/src/fmpzi/mul_i.c000066400000000000000000000013161461254215100160210ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_mul_i(fmpzi_t z, const fmpzi_t x) { if (z == x) { fmpz_swap(fmpzi_realref(z), fmpzi_imagref(z)); fmpz_neg(fmpzi_realref(z), fmpzi_realref(z)); } else { fmpz_neg(fmpzi_realref(z), fmpzi_imagref(x)); fmpz_set(fmpzi_imagref(z), fmpzi_realref(x)); } } flint-3.1.3/src/fmpzi/mul_i_pow_si.c000066400000000000000000000012261461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_mul_i_pow_si(fmpzi_t res, const fmpzi_t z, slong k) { k &= 3; if (k == 0) fmpzi_set(res, z); else if (k == 1) fmpzi_mul_i(res, z); else if (k == 2) fmpzi_neg(res, z); else fmpzi_div_i(res, z); } flint-3.1.3/src/fmpzi/pow_ui.c000066400000000000000000000037761461254215100162320ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" /* todo: maybe handle (+-1 +- i)^n as a special case */ void fmpzi_pow_ui(fmpzi_t res, const fmpzi_t x, ulong exp) { fmpzi_struct * R, * S, * T; fmpzi_t tmp; ulong bit; /* todo: cubing formula? */ if (exp <= 2) { if (exp == 0) fmpzi_one(res); else if (exp == 1) fmpzi_set(res, x); else fmpzi_sqr(res, x); return; } if (fmpz_is_zero(fmpzi_imagref(x))) { fmpz_pow_ui(fmpzi_realref(res), fmpzi_realref(x), exp); fmpz_zero(fmpzi_imagref(res)); return; } if (fmpz_is_zero(fmpzi_realref(x))) { fmpz_pow_ui(fmpzi_realref(res), fmpzi_imagref(x), exp); fmpz_zero(fmpzi_imagref(res)); if (exp % 4 >= 2) fmpz_neg(fmpzi_realref(res), fmpzi_realref(res)); if (exp % 2 == 1) fmpz_swap(fmpzi_realref(res), fmpzi_imagref(res)); return; } if (res == x) { fmpzi_t tmp; fmpzi_init(tmp); fmpzi_pow_ui(tmp, x, exp); fmpzi_swap(tmp, res); fmpzi_clear(tmp); return; } fmpzi_init(tmp); R = res; S = tmp; bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2); fmpzi_sqr(R, x); if (bit & exp) { fmpzi_mul(S, R, x); T = R; R = S; S = T; } while (bit >>= 1) { fmpzi_sqr(S, R); if (bit & exp) { fmpzi_mul(R, S, x); } else { T = R; R = S; S = T; } } if (R != res) fmpzi_swap(R, res); fmpzi_clear(tmp); } flint-3.1.3/src/fmpzi/profile/000077500000000000000000000000001461254215100162075ustar00rootroot00000000000000flint-3.1.3/src/fmpzi/profile/p-gcd.c000066400000000000000000000040711461254215100173470ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" #include "profiler.h" /* approx nbits(norm(x)) = n */ static void fmpzi_randbits_norm(fmpzi_t x, flint_rand_t state, flint_bitcnt_t n) { fmpz_randbits(fmpzi_realref(x), state, (n+1)/2); fmpz_randtest(fmpzi_imagref(x), state, (n+0)/2); if (n_randint(state, 2)) fmpz_swap(fmpzi_realref(x), fmpzi_imagref(x)); } double profile_it(ulong a_bits, ulong b_bits, ulong g_bits, flint_rand_t state) { fmpzi_t g, a, b; slong i, nreps; timeit_t timer; fmpzi_init(g); fmpzi_init(a); fmpzi_init(b); nreps = 1 + 5000000/(1 + a_bits + b_bits); timeit_start(timer); for (i = 0; i < nreps; i++) { fmpzi_randbits_norm(a, state, FLINT_MAX(1, a_bits - g_bits)); fmpzi_randbits_norm(b, state, FLINT_MAX(1, b_bits - g_bits)); fmpzi_randbits_norm(g, state, g_bits); fmpzi_mul(a, a, g); fmpzi_mul(b, b, g); fmpzi_gcd_shortest(g, a, b); fmpzi_gcd_shortest(g, b, a); } timeit_stop(timer); fmpzi_clear(g); fmpzi_clear(a); fmpzi_clear(b); return timer->wall/nreps; } int main(void) { ulong a_bits, b_bits, g_bits; flint_rand_t state; flint_randinit(state); for (a_bits = 100000; a_bits < 10000000; a_bits += 1 + a_bits/2) for (b_bits = a_bits; b_bits < 10000000; b_bits += 1 + b_bits/2) { flint_printf("a_bits:%8wu, b_bits:%8wu |", a_bits, b_bits); for (g_bits = 1; g_bits < a_bits/2; g_bits += 100 + g_bits/2) { double t = profile_it(a_bits, b_bits, g_bits, state); flint_printf(" %5.0f", t); fflush(stdout); } flint_printf("\n"); } flint_randclear(state); return 0; } flint-3.1.3/src/fmpzi/remove_one_plus_i.c000066400000000000000000000033261461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" slong fmpzi_remove_one_plus_i(fmpzi_t res, const fmpzi_t x) { slong s, t; int odd; if (fmpzi_is_zero(x)) { fmpzi_zero(res); return 0; } if (fmpz_is_zero(fmpzi_imagref(x))) { s = fmpz_val2(fmpzi_realref(x)); odd = 0; } else if (fmpz_is_zero(fmpzi_realref(x))) { s = fmpz_val2(fmpzi_imagref(x)); odd = 0; } else { s = fmpz_val2(fmpzi_realref(x)); t = fmpz_val2(fmpzi_imagref(x)); if (s == t) { odd = 1; } else { s = FLINT_MIN(s, t); odd = 0; } } if (s == 0) { fmpzi_mul_i_pow_si(res, x, -s); } else { fmpz_tdiv_q_2exp(fmpzi_realref(res), fmpzi_realref(x), s); fmpz_tdiv_q_2exp(fmpzi_imagref(res), fmpzi_imagref(x), s); fmpzi_mul_i_pow_si(res, res, -s); } if (odd) { /* (a+bi) / (1+i) = ((a+b)/2) + ((b-a)/2)i */ fmpz_t t; fmpz_init(t); fmpz_add(t, fmpzi_realref(res), fmpzi_imagref(res)); fmpz_sub(fmpzi_imagref(res), fmpzi_imagref(res), fmpzi_realref(res)); fmpz_tdiv_q_2exp(fmpzi_realref(res), t, 1); fmpz_tdiv_q_2exp(fmpzi_imagref(res), fmpzi_imagref(res), 1); fmpz_clear(t); } return 2 * s + odd; } flint-3.1.3/src/fmpzi/sqr.c000066400000000000000000000047641461254215100155330ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" void fmpzi_sqr(fmpzi_t res, const fmpzi_t x) { slong asize, bsize; fmpzi_struct * rp; fmpzi_t tmp; fmpz * t; fmpz * u; const fmpz *a = fmpzi_realref(x); const fmpz *b = fmpzi_imagref(x); const fmpz ca = *a; const fmpz cb = *b; if (!COEFF_IS_MPZ(ca) && !COEFF_IS_MPZ(cb)) { ulong thi, tlo, uhi, ulo, ahi, alo, bhi, blo; smul_ppmm(thi, tlo, ca, ca); smul_ppmm(uhi, ulo, cb, cb); sub_ddmmss(ahi, alo, thi, tlo, uhi, ulo); smul_ppmm(bhi, blo, ca + ca, cb); fmpz_set_signed_uiui(fmpzi_realref(res), ahi, alo); fmpz_set_signed_uiui(fmpzi_imagref(res), bhi, blo); return; } if (cb == 0) { fmpz_mul(fmpzi_realref(res), a, a); fmpz_zero(fmpzi_imagref(res)); return; } if (ca == 0) { fmpz_mul(fmpzi_realref(res), b, b); fmpz_neg(fmpzi_realref(res), fmpzi_realref(res)); fmpz_zero(fmpzi_imagref(res)); return; } if (res == x) { fmpzi_init(tmp); rp = tmp; } else { rp = res; } t = fmpzi_realref(rp); u = fmpzi_imagref(rp); if (COEFF_IS_MPZ(ca) && COEFF_IS_MPZ(cb)) { asize = COEFF_TO_PTR(ca)->_mp_size; asize = FLINT_ABS(asize); if (asize >= 16) { bsize = COEFF_TO_PTR(cb)->_mp_size; bsize = FLINT_ABS(bsize); if (FLINT_ABS(asize - bsize) <= 2) { fmpz_t v; fmpz_init(v); /* a^2-b^2, (a+b)^2-a^2-b^2 */ fmpz_add(v, a, b); fmpz_mul(u, v, v); fmpz_mul(t, a, a); fmpz_sub(u, u, t); fmpz_mul(v, b, b); fmpz_sub(t, t, v); fmpz_sub(u, u, v); fmpz_clear(v); goto cleanup; } } } fmpz_mul(t, a, a); fmpz_mul(u, b, b); fmpz_sub(t, t, u); fmpz_mul(u, a, b); fmpz_mul_2exp(u, u, 1); cleanup: if (res == x) { fmpzi_swap(res, tmp); fmpzi_clear(tmp); } } flint-3.1.3/src/fmpzi/test/000077500000000000000000000000001461254215100155265ustar00rootroot00000000000000flint-3.1.3/src/fmpzi/test/main.c000066400000000000000000000030731461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-divexact.c" #include "t-divrem_approx.c" #include "t-divrem.c" #include "t-gcd_binary.c" #include "t-gcd.c" #include "t-gcd_euclidean.c" #include "t-gcd_euclidean_improved.c" #include "t-gcd_shortest.c" #include "t-is_prime.c" #include "t-is_probabprime.c" #include "t-mul.c" #include "t-pow_ui.c" #include "t-remove_one_plus_i.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fmpzi_add_sub), TEST_FUNCTION(fmpzi_divexact), TEST_FUNCTION(fmpzi_divrem_approx), TEST_FUNCTION(fmpzi_divrem), TEST_FUNCTION(fmpzi_gcd_binary), TEST_FUNCTION(fmpzi_gcd), TEST_FUNCTION(fmpzi_gcd_euclidean), TEST_FUNCTION(fmpzi_gcd_euclidean_improved), TEST_FUNCTION(fmpzi_gcd_shortest), TEST_FUNCTION(fmpzi_is_prime), TEST_FUNCTION(fmpzi_is_probabprime), TEST_FUNCTION(fmpzi_mul), TEST_FUNCTION(fmpzi_pow_ui), TEST_FUNCTION(fmpzi_remove_one_plus_i) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fmpzi/test/t-add_sub.c000066400000000000000000000027011461254215100175340ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_add_sub, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { /* check x - y = x + (-y) */ fmpzi_t x, y, s, t; fmpzi_init(x); fmpzi_init(y); fmpzi_init(s); fmpzi_init(t); fmpzi_randtest(x, state, 100); fmpzi_randtest(y, state, 100); fmpzi_randtest(s, state, 100); fmpzi_randtest(t, state, 100); fmpzi_sub(s, x, y); fmpzi_neg(t, y); fmpzi_add(t, x, t); if (!fmpzi_equal(s, t)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("t = "); fmpzi_print(t); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(s); fmpzi_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-divexact.c000066400000000000000000000040411461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_divexact, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, xy, q; int aliasing; slong bits; fmpzi_init(x); fmpzi_init(y); fmpzi_init(xy); fmpzi_init(q); if (n_randint(state, 10) == 0) bits = 2000; else bits = 200; fmpzi_randtest(x, state, 2 + n_randint(state, bits)); do { fmpzi_randtest(y, state, 2 + n_randint(state, bits)); } while (fmpzi_is_zero(y)); fmpzi_randtest(q, state, 2 + n_randint(state, 200)); fmpzi_mul(xy, x, y); aliasing = n_randint(state, 3); switch (aliasing) { case 0: fmpzi_divexact(q, xy, y); break; case 1: fmpzi_set(q, xy); fmpzi_divexact(q, q, y); break; case 2: fmpzi_set(q, y); fmpzi_divexact(q, xy, q); break; } if (!fmpzi_equal(q, x)) { flint_printf("FAIL\n"); flint_printf("aliasing = %d\n", aliasing); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("xy = "); fmpzi_print(xy); printf("\n"); flint_printf("q = "); fmpzi_print(q); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(xy); fmpzi_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-divrem.c000066400000000000000000000116621461254215100174270ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" void fmpzi_divrem_ref(fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y) { fmpzi_t t, y_conj; fmpz_t v; mpz_t ytmp; fmpzi_init(t); fmpz_init(v); /* shallow conjugate */ *fmpzi_realref(y_conj) = *fmpzi_realref(y); if (!COEFF_IS_MPZ(*fmpzi_imagref(y))) { *fmpzi_imagref(y_conj) = -*fmpzi_imagref(y); } else { *ytmp = *COEFF_TO_PTR(*fmpzi_imagref(y)); mpz_neg(ytmp, ytmp); *fmpzi_imagref(y_conj) = PTR_TO_COEFF(ytmp); } fmpzi_mul(t, x, y_conj); fmpz_mul_2exp(fmpzi_realref(t), fmpzi_realref(t), 1); fmpz_mul_2exp(fmpzi_imagref(t), fmpzi_imagref(t), 1); fmpz_fmma(v, fmpzi_realref(y), fmpzi_realref(y), fmpzi_imagref(y), fmpzi_imagref(y)); fmpz_add(fmpzi_realref(t), fmpzi_realref(t), v); fmpz_add(fmpzi_imagref(t), fmpzi_imagref(t), v); fmpz_mul_2exp(v, v, 1); fmpz_fdiv_q(fmpzi_realref(q), fmpzi_realref(t), v); fmpz_fdiv_q(fmpzi_imagref(q), fmpzi_imagref(t), v); if (r != NULL) { fmpzi_mul(t, q, y); fmpzi_sub(r, x, t); } fmpzi_clear(t); fmpz_clear(v); } TEST_FUNCTION_START(fmpzi_divrem, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, q, r, s, t; fmpz_t ny, nr; int aliasing; fmpzi_init(x); fmpzi_init(y); fmpzi_init(q); fmpzi_init(r); fmpzi_init(s); fmpzi_init(t); fmpz_init(ny); fmpz_init(nr); fmpzi_randtest(x, state, 2 + n_randint(state, 200)); do { fmpzi_randtest(y, state, 2 + n_randint(state, 200)); } while (fmpzi_is_zero(y)); fmpzi_randtest(q, state, 2 + n_randint(state, 200)); fmpzi_randtest(r, state, 2 + n_randint(state, 200)); if (n_randint(state, 3) == 0) { fmpzi_mul(x, y, q); if (n_randint(state, 3) == 0) fmpzi_add(x, x, r); } aliasing = n_randint(state, 7); switch (aliasing) { case 0: fmpzi_divrem(q, r, x, y); break; case 1: fmpzi_set(q, x); fmpzi_divrem(q, r, q, y); break; case 2: fmpzi_set(q, y); fmpzi_divrem(q, r, x, q); break; case 3: fmpzi_set(r, x); fmpzi_divrem(q, r, r, y); break; case 4: fmpzi_set(r, y); fmpzi_divrem(q, r, x, r); break; case 5: fmpzi_set(q, x); fmpzi_set(r, y); fmpzi_divrem(q, r, q, r); break; default: fmpzi_set(q, y); fmpzi_set(r, x); fmpzi_divrem(q, r, r, q); break; } fmpzi_mul(s, q, y); fmpzi_add(t, s, r); fmpzi_norm(ny, y); fmpzi_norm(nr, r); fmpz_mul_2exp(nr, nr, 1); if (!fmpzi_equal(t, x) || !(fmpz_cmp(nr, ny) <= 0)) { flint_printf("FAIL\n"); flint_printf("aliasing = %d\n", aliasing); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("q = "); fmpzi_print(q); printf("\n"); flint_printf("r = "); fmpzi_print(r); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("t = "); fmpzi_print(t); printf("\n"); flint_printf("nr = "); fmpz_print(nr); printf("\n"); flint_printf("ny = "); fmpz_print(ny); printf("\n"); flint_abort(); } fmpzi_divrem_ref(s, t, x, y); if (!fmpzi_equal(q, s) || !fmpzi_equal(r, t)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("q = "); fmpzi_print(q); printf("\n"); flint_printf("r = "); fmpzi_print(r); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("t = "); fmpzi_print(t); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(q); fmpzi_clear(r); fmpzi_clear(s); fmpzi_clear(t); fmpz_clear(ny); fmpz_clear(nr); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-divrem_approx.c000066400000000000000000000064401461254215100210160ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_divrem_approx, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, q, r, s, t; fmpz_t ny, nr; int aliasing; fmpzi_init(x); fmpzi_init(y); fmpzi_init(q); fmpzi_init(r); fmpzi_init(s); fmpzi_init(t); fmpz_init(ny); fmpz_init(nr); fmpzi_randtest(x, state, 2 + n_randint(state, 600)); do { fmpzi_randtest(y, state, 2 + n_randint(state, 600)); } while (fmpzi_is_zero(y)); fmpzi_randtest(q, state, 2 + n_randint(state, 600)); fmpzi_randtest(r, state, 2 + n_randint(state, 600)); if (n_randint(state, 3) == 0) { fmpzi_mul(x, y, q); if (n_randint(state, 3) == 0) fmpzi_add(x, x, r); } aliasing = n_randint(state, 7); switch (aliasing) { case 0: fmpzi_divrem_approx(q, r, x, y); break; case 1: fmpzi_set(q, x); fmpzi_divrem_approx(q, r, q, y); break; case 2: fmpzi_set(q, y); fmpzi_divrem_approx(q, r, x, q); break; case 3: fmpzi_set(r, x); fmpzi_divrem_approx(q, r, r, y); break; case 4: fmpzi_set(r, y); fmpzi_divrem_approx(q, r, x, r); break; case 5: fmpzi_set(q, x); fmpzi_set(r, y); fmpzi_divrem_approx(q, r, q, r); break; default: fmpzi_set(q, y); fmpzi_set(r, x); fmpzi_divrem_approx(q, r, r, q); break; } fmpzi_mul(s, q, y); fmpzi_add(t, s, r); fmpzi_norm(ny, y); fmpzi_norm(nr, r); if (!fmpzi_equal(t, x) || !(fmpz_cmp(nr, ny) < 0)) { flint_printf("FAIL\n"); flint_printf("aliasing = %d\n", aliasing); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("q = "); fmpzi_print(q); printf("\n"); flint_printf("r = "); fmpzi_print(r); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("t = "); fmpzi_print(t); printf("\n"); flint_printf("nr = "); fmpz_print(nr); printf("\n"); flint_printf("ny = "); fmpz_print(ny); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(q); fmpzi_clear(r); fmpzi_clear(s); fmpzi_clear(t); fmpz_clear(ny); fmpz_clear(nr); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-gcd.c000066400000000000000000000051531461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_gcd, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, d, xd, yd, g; fmpzi_init(x); fmpzi_init(y); fmpzi_init(d); fmpzi_init(xd); fmpzi_init(yd); fmpzi_init(g); if (iter % 100 == 0) { fmpzi_randtest(x, state, 2 + n_randint(state, 50000)); fmpzi_randtest(y, state, 2 + n_randint(state, 50000)); } else { fmpzi_randtest(x, state, 2 + n_randint(state, 100)); fmpzi_randtest(y, state, 2 + n_randint(state, 100)); } fmpzi_randtest(xd, state, 2 + n_randint(state, 100)); fmpzi_randtest(yd, state, 2 + n_randint(state, 100)); fmpzi_gcd(d, x, y); if (fmpzi_is_zero(x) && fmpzi_is_zero(y)) { fmpzi_zero(g); } else { if (!fmpzi_is_zero(d)) { fmpzi_divrem(x, g, x, d); fmpzi_divrem(y, g, y, d); } fmpzi_mul_i_pow_si(x, x, n_randint(state, 4)); fmpzi_mul_i_pow_si(y, y, n_randint(state, 4)); if (iter % 100 == 0) fmpzi_randtest(d, state, 2 + n_randint(state, 50000)); else fmpzi_randtest(d, state, 2 + n_randint(state, 100)); fmpzi_mul(xd, x, d); fmpzi_mul(yd, y, d); fmpzi_gcd(g, xd, yd); fmpzi_canonicalise_unit(d, d); } if (!fmpzi_equal(g, d)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("d = "); fmpzi_print(d); printf("\n"); flint_printf("xd = "); fmpzi_print(xd); printf("\n"); flint_printf("yd = "); fmpzi_print(yd); printf("\n"); flint_printf("g = "); fmpzi_print(g); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(d); fmpzi_clear(xd); fmpzi_clear(yd); fmpzi_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-gcd_binary.c000066400000000000000000000044411461254215100202370ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_gcd_binary, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, d, xd, yd, g; fmpzi_init(x); fmpzi_init(y); fmpzi_init(d); fmpzi_init(xd); fmpzi_init(yd); fmpzi_init(g); fmpzi_randtest(x, state, 2 + n_randint(state, 100)); fmpzi_randtest(y, state, 2 + n_randint(state, 100)); fmpzi_randtest(xd, state, 2 + n_randint(state, 100)); fmpzi_randtest(yd, state, 2 + n_randint(state, 100)); fmpzi_gcd_binary(d, x, y); if (fmpzi_is_zero(x) && fmpzi_is_zero(y)) { fmpzi_zero(g); } else { if (!fmpzi_is_zero(d)) { fmpzi_divrem(x, g, x, d); fmpzi_divrem(y, g, y, d); } fmpzi_mul_i_pow_si(x, x, n_randint(state, 4)); fmpzi_mul_i_pow_si(y, y, n_randint(state, 4)); fmpzi_randtest(d, state, 2 + n_randint(state, 100)); fmpzi_mul(xd, x, d); fmpzi_mul(yd, y, d); fmpzi_gcd_binary(g, xd, yd); fmpzi_canonicalise_unit(d, d); } if (!fmpzi_equal(g, d)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("d = "); fmpzi_print(d); printf("\n"); flint_printf("xd = "); fmpzi_print(xd); printf("\n"); flint_printf("yd = "); fmpzi_print(yd); printf("\n"); flint_printf("g = "); fmpzi_print(g); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(d); fmpzi_clear(xd); fmpzi_clear(yd); fmpzi_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-gcd_euclidean.c000066400000000000000000000044521461254215100207060ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_gcd_euclidean, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, d, xd, yd, g; fmpzi_init(x); fmpzi_init(y); fmpzi_init(d); fmpzi_init(xd); fmpzi_init(yd); fmpzi_init(g); fmpzi_randtest(x, state, 2 + n_randint(state, 100)); fmpzi_randtest(y, state, 2 + n_randint(state, 100)); fmpzi_randtest(xd, state, 2 + n_randint(state, 100)); fmpzi_randtest(yd, state, 2 + n_randint(state, 100)); fmpzi_gcd_euclidean(d, x, y); if (fmpzi_is_zero(x) && fmpzi_is_zero(y)) { fmpzi_zero(g); } else { if (!fmpzi_is_zero(d)) { fmpzi_divrem(x, g, x, d); fmpzi_divrem(y, g, y, d); } fmpzi_mul_i_pow_si(x, x, n_randint(state, 4)); fmpzi_mul_i_pow_si(y, y, n_randint(state, 4)); fmpzi_randtest(d, state, 2 + n_randint(state, 100)); fmpzi_mul(xd, x, d); fmpzi_mul(yd, y, d); fmpzi_gcd_euclidean(g, xd, yd); fmpzi_canonicalise_unit(d, d); } if (!fmpzi_equal(g, d)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("d = "); fmpzi_print(d); printf("\n"); flint_printf("xd = "); fmpzi_print(xd); printf("\n"); flint_printf("yd = "); fmpzi_print(yd); printf("\n"); flint_printf("g = "); fmpzi_print(g); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(d); fmpzi_clear(xd); fmpzi_clear(yd); fmpzi_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-gcd_euclidean_improved.c000066400000000000000000000045361461254215100226160ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_extras.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_gcd_euclidean_improved, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, d, xd, yd, g; fmpzi_init(x); fmpzi_init(y); fmpzi_init(d); fmpzi_init(xd); fmpzi_init(yd); fmpzi_init(g); fmpzi_randtest(x, state, 2 + n_randint(state, 100)); fmpzi_randtest(y, state, 2 + n_randint(state, 100)); fmpzi_randtest(xd, state, 2 + n_randint(state, 100)); fmpzi_randtest(yd, state, 2 + n_randint(state, 100)); fmpzi_gcd_euclidean_improved(d, x, y); if (fmpzi_is_zero(x) && fmpzi_is_zero(y)) { fmpzi_zero(g); } else { if (!fmpzi_is_zero(d)) { fmpzi_divrem(x, g, x, d); fmpzi_divrem(y, g, y, d); } fmpzi_mul_i_pow_si(x, x, n_randint(state, 4)); fmpzi_mul_i_pow_si(y, y, n_randint(state, 4)); fmpzi_randtest(d, state, 2 + n_randint(state, 100)); fmpzi_mul(xd, x, d); fmpzi_mul(yd, y, d); fmpzi_gcd_euclidean_improved(g, xd, yd); fmpzi_canonicalise_unit(d, d); } if (!fmpzi_equal(g, d)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("d = "); fmpzi_print(d); printf("\n"); flint_printf("xd = "); fmpzi_print(xd); printf("\n"); flint_printf("yd = "); fmpzi_print(yd); printf("\n"); flint_printf("g = "); fmpzi_print(g); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(d); fmpzi_clear(xd); fmpzi_clear(yd); fmpzi_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-gcd_shortest.c000066400000000000000000000056251461254215100206330ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_gcd_shortest, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, d, xd, yd, g; fmpzi_init(x); fmpzi_init(y); fmpzi_init(d); fmpzi_init(xd); fmpzi_init(yd); fmpzi_init(g); fmpzi_randtest(x, state, 2 + n_randint(state, 200)); fmpzi_randtest(y, state, 2 + n_randint(state, 200)); fmpzi_randtest(xd, state, 2 + n_randint(state, 200)); fmpzi_randtest(yd, state, 2 + n_randint(state, 200)); if (n_randint(state, 2)) { fmpzi_conj(yd, y); fmpzi_mul(x, x, yd); fmpzi_mul(y, y, yd); } fmpzi_gcd_shortest(d, x, y); fmpzi_gcd_euclidean(g, x, y); if (!fmpzi_equal(d, g)) { flint_printf("FAIL: check against euclidean (iter = %wd)\n", iter); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("d = "); fmpzi_print(d); printf("\n"); flint_printf("g = "); fmpzi_print(g); printf("\n"); flint_abort(); } if (fmpzi_is_zero(x) && fmpzi_is_zero(y)) { fmpzi_zero(g); } else { if (!fmpzi_is_zero(d)) { fmpzi_divrem(x, g, x, d); fmpzi_divrem(y, g, y, d); } fmpzi_mul_i_pow_si(x, x, n_randint(state, 4)); fmpzi_mul_i_pow_si(y, y, n_randint(state, 4)); fmpzi_randtest(d, state, 2 + n_randint(state, 100)); fmpzi_mul(xd, x, d); fmpzi_mul(yd, y, d); fmpzi_gcd_shortest(g, xd, yd); fmpzi_canonicalise_unit(d, d); } if (!fmpzi_equal(g, d)) { flint_printf("FAIL: (iter = %wd)\n", iter); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("d = "); fmpzi_print(d); printf("\n"); flint_printf("xd = "); fmpzi_print(xd); printf("\n"); flint_printf("yd = "); fmpzi_print(yd); printf("\n"); flint_printf("g = "); fmpzi_print(g); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(d); fmpzi_clear(xd); fmpzi_clear(yd); fmpzi_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-is_prime.c000066400000000000000000000026141461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2023 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_is_prime, state) { fmpzi_t n; fmpzi_init(n); int small_gaussian_primes[10][10] = { {0, 0, 0, 1, 0, 0, 0, 1, 0, 0}, {0, 1, 1, 0, 1, 0, 1, 0, 0, 0}, {0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, {1, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, {1, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0} }; for (int a = 0; a < 10; a ++) { for (int b = 0; b < 10; b ++) { fmpzi_set_si_si(n, a, b); if (fmpzi_is_prime(n) != small_gaussian_primes[a][b]) { flint_printf("FAIL\n"); flint_printf("n = "); fmpzi_print(n); printf("\n"); flint_abort(); } } } fmpzi_clear(n); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-is_probabprime.c000066400000000000000000000026301461254215100211310ustar00rootroot00000000000000/* Copyright (C) 2023 Mathieu Gouttenoire This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_is_probabprime, state) { fmpzi_t n; fmpzi_init(n); int small_gaussian_primes[10][10] = { {0, 0, 0, 1, 0, 0, 0, 1, 0, 0}, {0, 1, 1, 0, 1, 0, 1, 0, 0, 0}, {0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, {1, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, {1, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0} }; for (int a = 0; a < 10; a ++) { for (int b = 0; b < 10; b ++) { fmpzi_set_si_si(n, a, b); if (fmpzi_is_probabprime(n) != small_gaussian_primes[a][b]) { flint_printf("FAIL\n"); flint_printf("n = "); fmpzi_print(n); printf("\n"); flint_abort(); } } } fmpzi_clear(n); TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-mul.c000066400000000000000000000051031461254215100167270ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_mul, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, z, s, t, u; fmpzi_init(x); fmpzi_init(y); fmpzi_init(z); fmpzi_init(s); fmpzi_init(t); fmpzi_init(u); fmpzi_randtest(x, state, 2000); fmpzi_randtest(y, state, 2000); fmpzi_randtest(z, state, 2000); fmpzi_randtest(s, state, 2000); fmpzi_randtest(t, state, 2000); /* check x * (y + z) = x * y + z * x */ fmpzi_add(s, y, z); if (n_randint(state, 2)) fmpzi_mul(s, x, s); else fmpzi_mul(s, s, x); fmpzi_mul(t, x, y); fmpzi_mul(u, z, x); fmpzi_add(t, t, u); if (!fmpzi_equal(s, t)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("z = "); fmpzi_print(z); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("t = "); fmpzi_print(t); printf("\n"); flint_abort(); } /* test squaring */ fmpzi_randtest(x, state, 2000); fmpzi_randtest(y, state, 2000); fmpzi_randtest(s, state, 2000); fmpzi_randtest(t, state, 2000); fmpzi_set(y, x); fmpzi_mul(s, x, y); if (n_randint(state, 2)) { fmpzi_mul(t, x, x); } else { fmpzi_set(t, x); fmpzi_mul(t, t, t); } if (!fmpzi_equal(s, t)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("t = "); fmpzi_print(t); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(z); fmpzi_clear(s); fmpzi_clear(t); fmpzi_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-pow_ui.c000066400000000000000000000037101461254215100174360ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_pow_ui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, s, t, u, v; ulong e, f; fmpzi_init(x); fmpzi_init(y); fmpzi_init(s); fmpzi_init(t); fmpzi_init(u); fmpzi_init(v); fmpzi_randtest(x, state, 100); fmpzi_randtest(y, state, 100); fmpzi_randtest(s, state, 100); fmpzi_randtest(t, state, 100); fmpzi_randtest(u, state, 100); e = n_randint(state, 30); f = n_randint(state, 30); if (n_randint(state, 2)) { fmpzi_pow_ui(s, x, e); } else { fmpzi_set(s, x); fmpzi_pow_ui(s, s, e); } fmpzi_pow_ui(t, x, f); fmpzi_mul(v, s, t); fmpzi_pow_ui(u, x, e + f); if (!fmpzi_equal(v, u)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("t = "); fmpzi_print(t); printf("\n"); flint_printf("u = "); fmpzi_print(u); printf("\n"); flint_printf("v = "); fmpzi_print(v); printf("\n"); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(s); fmpzi_clear(t); fmpzi_clear(u); fmpzi_clear(v); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fmpzi/test/t-remove_one_plus_i.c000066400000000000000000000032501461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpzi.h" TEST_FUNCTION_START(fmpzi_remove_one_plus_i, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpzi_t x, y, z, s; slong v, w; fmpzi_init(x); fmpzi_init(y); fmpzi_init(z); fmpzi_init(s); do { fmpzi_randtest(x, state, 100); } while (fmpzi_is_zero(x)); fmpzi_remove_one_plus_i(x, x); v = n_randint(state, 10); fmpz_one(fmpzi_realref(y)); fmpz_one(fmpzi_imagref(y)); fmpzi_pow_ui(y, y, v); fmpzi_mul(z, x, y); fmpzi_randtest(s, state, 200); w = fmpzi_remove_one_plus_i(s, z); if (v != w || !fmpzi_equal(s, x)) { flint_printf("FAIL\n"); flint_printf("x = "); fmpzi_print(x); printf("\n"); flint_printf("v = %wd\n", v); flint_printf("y = "); fmpzi_print(y); printf("\n"); flint_printf("z = "); fmpzi_print(z); printf("\n"); flint_printf("s = "); fmpzi_print(s); printf("\n"); flint_printf("w = %wd\n", w); flint_abort(); } fmpzi_clear(x); fmpzi_clear(y); fmpzi_clear(z); fmpzi_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq.h000066400000000000000000000151461461254215100142100ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_H #define FQ_H #ifdef FQ_INLINES_C #define FQ_INLINE #define FQ_TEMPLATES_INLINE #else #define FQ_INLINE static inline #define FQ_TEMPLATES_INLINE static inline #endif #include "fq_types.h" /* Data types and context ****************************************************/ #ifdef __cplusplus extern "C" { #endif void fq_ctx_init(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var); int _fq_ctx_init_conway_ui(fq_ctx_t ctx, ulong p, slong d, const char * var); void fq_ctx_init_conway_ui(fq_ctx_t ctx, ulong p, slong d, const char * var); int _fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var); void fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var); void fq_ctx_init_modulus(fq_ctx_t ctx, const fmpz_mod_poly_t modulus, const fmpz_mod_ctx_t ctxp, const char * var); void fq_ctx_init_randtest(fq_ctx_t ctx, flint_rand_t state, int type); void fq_ctx_init_randtest_reducible(fq_ctx_t ctx, flint_rand_t state, int type); void fq_ctx_clear(fq_ctx_t ctx); FQ_INLINE const fmpz_mod_poly_struct* fq_ctx_modulus(const fq_ctx_t ctx) { return ctx->modulus; } FQ_INLINE slong fq_ctx_degree(const fq_ctx_t ctx) { return ctx->modulus->length - 1; } FQ_INLINE const fmpz * fq_ctx_prime(const fq_ctx_t ctx) { return ctx->ctxp->n; } void fq_ctx_order(fmpz_t f, const fq_ctx_t ctx); #ifdef FLINT_HAVE_FILE int fq_ctx_fprint(FILE * file, const fq_ctx_t ctx); #endif void fq_ctx_print(const fq_ctx_t ctx); /* Memory management *********************************************************/ void fq_init(fq_t rop, const fq_ctx_t ctx); void fq_init2(fq_t rop, const fq_ctx_t ctx); void fq_clear(fq_t rop, const fq_ctx_t ctx); void _fq_sparse_reduce(fmpz * R, slong lenR, const fq_ctx_t ctx); void _fq_dense_reduce(fmpz * R, slong lenR, const fq_ctx_t ctx); void _fq_reduce(fmpz * R, slong lenR, const fq_ctx_t ctx); void fq_reduce(fq_t rop, const fq_ctx_t ctx); /* Basic arithmetic **********************************************************/ void fq_add(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx); void fq_sub(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx); void fq_sub_one(fq_t rop, const fq_t op1, const fq_ctx_t ctx); void fq_neg(fq_t rop, const fq_t op1, const fq_ctx_t ctx); void fq_mul(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx); void fq_mul_fmpz(fq_t rop, const fq_t op, const fmpz_t x, const fq_ctx_t ctx); void fq_mul_si(fq_t rop, const fq_t op, slong x, const fq_ctx_t ctx); void fq_mul_ui(fq_t rop, const fq_t op, ulong x, const fq_ctx_t ctx); void fq_sqr(fq_t rop, const fq_t op, const fq_ctx_t ctx); void fq_inv(fq_t rop, const fq_t op1, const fq_ctx_t ctx); void _fq_pow(fmpz *rop, const fmpz *op, slong len, const fmpz_t e, const fq_ctx_t ctx); void fq_pow(fq_t rop, const fq_t op1, const fmpz_t e, const fq_ctx_t ctx); void fq_pow_ui(fq_t rop, const fq_t op, const ulong e, const fq_ctx_t ctx); /* Roots *********************************************************************/ int fq_sqrt(fq_t rop, const fq_t op, const fq_ctx_t ctx); void fq_pth_root(fq_t rop, const fq_t op1, const fq_ctx_t ctx); int fq_is_square(const fq_t op, const fq_ctx_t ctx); /* Randomisation *************************************************************/ void fq_randtest(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); void fq_randtest_dense(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); void fq_randtest_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); void fq_rand(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); void fq_rand_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); /* Comparison ****************************************************************/ int fq_equal(const fq_t op1, const fq_t op2, const fq_ctx_t ctx); int fq_is_zero(const fq_t op, const fq_ctx_t ctx); int fq_is_one(const fq_t op, const fq_ctx_t ctx); /* Assignments and conversions ***********************************************/ void fq_set(fq_t rop, const fq_t op, const fq_ctx_t ctx); void fq_set_ui(fq_t rop, const ulong x, const fq_ctx_t ctx); void fq_set_si(fq_t rop, const slong x, const fq_ctx_t ctx); void fq_set_fmpz(fq_t rop, const fmpz_t x, const fq_ctx_t ctx); void fq_set_fmpz_poly(fq_t a, const fmpz_poly_t b, const fq_ctx_t ctx); void fq_set_fmpz_mod_poly(fq_t a, const fmpz_mod_poly_t b, const fq_ctx_t ctx); int fq_get_fmpz(fmpz_t a, const fq_t b, const fq_ctx_t ctx); void fq_get_fmpz_poly(fmpz_poly_t a, const fq_t b, const fq_ctx_t ctx); void fq_get_fmpz_mod_poly(fmpz_mod_poly_t a, const fq_t b, const fq_ctx_t ctx); void fq_zero(fq_t rop, const fq_ctx_t ctx); void fq_one(fq_t rop, const fq_ctx_t ctx); void fq_swap(fq_t op1, fq_t op2, const fq_ctx_t ctx); void fq_gen(fq_t rop, const fq_ctx_t ctx); /* Output ********************************************************************/ #ifdef FLINT_HAVE_FILE int fq_fprint(FILE * file, const fq_t op, const fq_ctx_t ctx); void fq_print(const fq_t op, const fq_ctx_t ctx); int fq_fprint_pretty(FILE * file, const fq_t op, const fq_ctx_t ctx); int fq_print_pretty(const fq_t op, const fq_ctx_t ctx); #endif char * fq_get_str(const fq_t op, const fq_ctx_t ctx); char * fq_get_str_pretty(const fq_t op, const fq_ctx_t ctx); /* Special functions *********************************************************/ void _fq_trace(fmpz_t rop, const fmpz *op, slong len, const fq_ctx_t ctx); void fq_trace(fmpz_t rop, const fq_t op, const fq_ctx_t ctx); void _fq_frobenius(fmpz *rop, const fmpz *op, slong len, slong e, const fq_ctx_t ctx); void fq_frobenius(fq_t rop, const fq_t op, slong e, const fq_ctx_t ctx); void _fq_norm(fmpz_t rop, const fmpz *op, slong len, const fq_ctx_t ctx); void fq_norm(fmpz_t rop, const fq_t op, const fq_ctx_t ctx); /* Bit packing ******************************************************/ void fq_bit_pack(fmpz_t f, const fq_t op, flint_bitcnt_t bit_size, const fq_ctx_t ctx); void fq_bit_unpack(fq_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_ctx_t ctx); /* Inlines *******************************************************************/ void __fq_ctx_prime(fmpz_t p, fq_ctx_t ctx); #ifdef T #undef T #endif #define T fq #define CAP_T FQ #define B fmpz_mod #include "fq_templates.h" #undef B #undef CAP_T #undef T #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq/000077500000000000000000000000001461254215100140305ustar00rootroot00000000000000flint-3.1.3/src/fq/add.c000066400000000000000000000016201461254215100147230ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_add(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx) { slong max = FLINT_MAX(op1->length, op2->length); fmpz_poly_fit_length(rop, max); _fmpz_mod_poly_add(rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx->ctxp); _fmpz_poly_set_length(rop, max); _fmpz_poly_normalise(rop); } flint-3.1.3/src/fq/assignments.c000066400000000000000000000017741461254215100165400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_set(fq_t rop, const fq_t op, const fq_ctx_t ctx) { fmpz_poly_set(rop, op); } void fq_set_fmpz(fq_t rop, const fmpz_t x, const fq_ctx_t ctx) { fmpz_poly_set_fmpz(rop, x); fq_reduce(rop, ctx); } void fq_set_ui(fq_t rop, const ulong x, const fq_ctx_t ctx) { fmpz_poly_set_ui(rop, x); fq_reduce(rop, ctx); } void fq_set_si(fq_t rop, const slong x, const fq_ctx_t ctx) { fmpz_poly_set_si(rop, x); fq_reduce(rop, ctx); } void fq_zero(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_zero(rop); } void fq_one(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_one(rop); } flint-3.1.3/src/fq/bit_pack.c000066400000000000000000000010611461254215100157460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_bit_pack(fmpz_t f, const fq_t op, flint_bitcnt_t bit_size, const fq_ctx_t ctx) { fmpz_poly_bit_pack(f, op, bit_size); } flint-3.1.3/src/fq/bit_unpack.c000066400000000000000000000011331461254215100163110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_bit_unpack(fq_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_ctx_t ctx) { fmpz_poly_bit_unpack_unsigned(rop, f, bit_size); fq_reduce(rop, ctx); } flint-3.1.3/src/fq/clear.c000066400000000000000000000007561461254215100152720ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_clear(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_clear(rop); } flint-3.1.3/src/fq/comparisons.c000066400000000000000000000012771461254215100165400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" int fq_equal(const fq_t op1, const fq_t op2, const fq_ctx_t ctx) { return fmpz_poly_equal(op1, op2); } int fq_is_zero(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_is_zero(op); } int fq_is_one(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_is_one(op); } flint-3.1.3/src/fq/ctx_clear.c000066400000000000000000000014371461254215100161450ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_ctx_clear(fq_ctx_t ctx) { fmpz_mod_poly_clear(ctx->modulus, ctx->ctxp); fmpz_mod_poly_clear(ctx->inv, ctx->ctxp); fmpz_mod_ctx_clear(ctx->ctxp); flint_free(ctx->var); _fmpz_vec_clear(ctx->a, ctx->len); flint_free(ctx->j); } flint-3.1.3/src/fq/ctx_init.c000066400000000000000000000115211461254215100160150ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq_nmod.h" #include "fq.h" /* Assumes that everything fits inside a small fmpz */ void fq_ctx_init_set_clear_small_fq_nmod_ctx(fq_ctx_t c1, fq_nmod_ctx_t c2) { fmpz_mod_ctx_struct * ctxp = c1->ctxp; fmpz_mod_poly_struct * m1 = c1->modulus; fmpz_mod_poly_struct * i1 = c1->inv; nmod_poly_struct * m2 = c2->modulus; nmod_poly_struct * i2 = c2->inv; /* Init c1->ctxp */ *ctxp->n = c2->mod.n; ctxp->add_fxn = _fmpz_mod_add1; ctxp->sub_fxn = _fmpz_mod_sub1; ctxp->mul_fxn = _fmpz_mod_mul1; ctxp->mod = c2->mod; ctxp->n_limbs[0] = 0; ctxp->n_limbs[1] = 0; ctxp->n_limbs[2] = 0; ctxp->ninv_huge = NULL; c1->sparse_modulus = c2->sparse_modulus; c1->is_conway = c2->is_conway; c1->a = (fmpz *) c2->a; c1->j = c2->j; c1->len = c2->len; /* Init c1->modulus and c1->inv */ m1->coeffs = (fmpz *) m2->coeffs; m1->alloc = m2->alloc; m1->length = m2->length; i1->coeffs = (fmpz *) i2->coeffs; i1->alloc = i2->alloc; i1->length = i2->length; c1->var = c2->var; } int _fq_ctx_init_conway_ui(fq_ctx_t ctx, ulong p, slong d, const char * var) { fq_nmod_ctx_t ctx2; if (_fq_nmod_ctx_init_conway_ui(ctx2, p, d, var)) { fq_ctx_init_set_clear_small_fq_nmod_ctx(ctx, ctx2); return 1; } else return 0; } void fq_ctx_init_conway_ui(fq_ctx_t ctx, ulong p, slong d, const char *var) { int result; result = _fq_ctx_init_conway_ui(ctx, p, d, var); if (!result) flint_throw(FLINT_ERROR, "Exception (fq_ctx_init_conway_ui). The " "polynomial for (p, d) = (%wu, %wd) is not present " "in the database.\n", p, d); ctx->is_conway = 1; } int _fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var) { if (*p < 2 || *p > 109987) /* NOTE: This works. */ return 0; else return _fq_ctx_init_conway_ui(ctx, *p, d, var); } void fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var) { if (*p < 2 || *p > 109987) /* NOTE: This works. */ flint_throw(FLINT_ERROR, "Exception (fq_ctx_init_conway). The " "polynomial for (p, d) = (%{fmpz}, %wd) is not present " "in the database.\n", p, d); else fq_ctx_init_conway_ui(ctx, *p, d, var); } void fq_ctx_init(fq_ctx_t ctx, const fmpz_t p, slong d, const char * var) { flint_rand_t state; fmpz_mod_poly_t poly; fmpz_mod_ctx_t ctxp; if (_fq_ctx_init_conway(ctx, p, d, var)) { ctx->is_conway = 1; return; } ctx->is_conway = 0; flint_randinit(state); fmpz_mod_ctx_init(ctxp, p); fmpz_mod_poly_init2(poly, d + 1, ctxp); fmpz_mod_poly_randtest_sparse_irreducible(poly, state, d + 1, ctxp); fq_ctx_init_modulus(ctx, poly, ctxp, var); fmpz_mod_poly_clear(poly, ctxp); fmpz_mod_ctx_clear(ctxp); flint_randclear(state); } /* FIXME: Test super big primes? */ void fq_ctx_init_randtest(fq_ctx_t ctx, flint_rand_t state, int type) { fq_nmod_ctx_t nmod_ctx; fq_nmod_ctx_init_randtest(nmod_ctx, state, type); fq_ctx_init_set_clear_small_fq_nmod_ctx(ctx, nmod_ctx); } void fq_ctx_init_randtest_reducible(fq_ctx_t ctx, flint_rand_t state, int type) { fmpz_mod_ctx_t ctxp; fmpz_mod_poly_t mod; ulong prime; slong deg; /* Big prime < 2^30, big degree <= 30 */ /* Small prime < 2^10, small degree <= 15 */ switch (type) { case 0: prime = n_randprime(state, 2 + n_randint(state, 29), 1); deg = 1 + n_randint(state, 30); break; case 1: prime = n_randprime(state, 2 + n_randint(state, 29), 1); deg = 1 + n_randint(state, 15); break; case 2: prime = n_randprime(state, 2 + n_randint(state, 9), 1); deg = 1 + n_randint(state, 30); break; case 3: prime = n_randprime(state, 2 + n_randint(state, 9), 1); deg = 1 + n_randint(state, 15); break; default: FLINT_UNREACHABLE; } fmpz_mod_ctx_init_ui(ctxp, prime); fmpz_mod_poly_init(mod, ctxp); fmpz_mod_poly_randtest_monic(mod, state, deg + 1, ctxp); fq_ctx_init_modulus(ctx, mod, ctxp, "a"); fmpz_mod_poly_clear(mod, ctxp); fmpz_mod_ctx_clear(ctxp); } flint-3.1.3/src/fq/ctx_init_modulus.c000066400000000000000000000040241461254215100175650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_ctx_init_modulus(fq_ctx_t ctx, const fmpz_mod_poly_t modulus, const fmpz_mod_ctx_t ctxp, const char *var) { slong nz; int i, j; const fmpz * p = fmpz_mod_ctx_modulus(ctxp); fmpz_t inv; /* Count number of nonzero coefficients */ nz = 0; for (i = 0; i < modulus->length; i++) nz += !fmpz_is_zero(modulus->coeffs + i); ctx->len = nz; ctx->a = _fmpz_vec_init(ctx->len); ctx->j = flint_malloc(ctx->len * sizeof(slong)); fmpz_init(inv); fmpz_invmod(inv, modulus->coeffs + modulus->length - 1, p); /* Copy the polynomial */ j = 0; for (i = 0; i < modulus->length; i++) { if (!fmpz_is_zero(modulus->coeffs + i)) { fmpz_mul(ctx->a + j, inv, modulus->coeffs + i); fmpz_mod(ctx->a + j, ctx->a + j, p); ctx->j[j] = i; j++; } } fmpz_clear(inv); if (ctx->len < 6) ctx->sparse_modulus = 1; else ctx->sparse_modulus = 0; fmpz_mod_ctx_init(ctx->ctxp, p); ctx->var = flint_malloc(strlen(var) + 1); strcpy(ctx->var, var); /* Set the modulus */ fmpz_mod_poly_init(ctx->modulus, ctx->ctxp); fmpz_mod_poly_set(ctx->modulus, modulus, ctx->ctxp); /* Precompute the inverse of the modulus */ fmpz_mod_poly_init(ctx->inv, ctx->ctxp); fmpz_mod_poly_reverse(ctx->inv, ctx->modulus, ctx->modulus->length, ctx->ctxp); fmpz_mod_poly_inv_series(ctx->inv, ctx->inv, ctx->modulus->length, ctx->ctxp); ctx->is_conway = 0; } flint-3.1.3/src/fq/ctx_order.c000066400000000000000000000010161461254215100161630ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq.h" void fq_ctx_order(fmpz_t f, const fq_ctx_t ctx) { fmpz_pow_ui(f, fq_ctx_prime(ctx), fq_ctx_degree(ctx)); } flint-3.1.3/src/fq/embed_templates.c000066400000000000000000000011621461254215100173260ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" #include "fq.h" #include "fq_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq #define CAP_T FQ #define B fmpz_mod #include "fq_embed_templates/composition_matrix.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq/frobenius.c000066400000000000000000000037421461254215100161760ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fq.h" /* Sets (rop, 2d-1) to the image of (op, len) under the Frobenius operator raised to the e-th power, assuming that neither op nor e are zero. */ void _fq_frobenius(fmpz * rop, const fmpz * op, slong len, slong e, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); if (len == 1) /* op is in Fp, not just Fq */ { _fmpz_vec_set(rop, op, len); _fmpz_vec_zero(rop + len, (2 * d - 1) - len); } else { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, fq_ctx_prime(ctx), e); _fq_pow(rop, op, len, t, ctx); fmpz_clear(t); } } void fq_frobenius(fq_t rop, const fq_t op, slong e, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); e = e % d; if (e < 0) e += d; if (fq_is_zero(op, ctx)) { fq_zero(rop, ctx); } else if (e == 0) { fq_set(rop, op, ctx); } else { fmpz *t; if (rop == op) { t = _fmpz_vec_init(2 * d - 1); } else { fmpz_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } _fq_frobenius(t, op->coeffs, op->length, e, ctx); if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } else { _fmpz_poly_set_length(rop, d); } _fmpz_poly_normalise(rop); } } flint-3.1.3/src/fq/gcdinv.c000066400000000000000000000044771461254215100154620ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_gcdinv(fq_t rop, fq_t inv, const fq_t op, const fq_ctx_t ctx) { fmpz *g, *s; slong lenG; fmpz_t f; if (fq_is_zero(op, ctx)) { fq_zero(rop, ctx); return; } fmpz_init(f); if (rop == op) { g = _fmpz_vec_init(op->length); } else { fmpz_poly_fit_length(rop, op->length); g = rop->coeffs; } if (inv == op) { s = _fmpz_vec_init(ctx->modulus->length - 1); } else { fmpz_poly_fit_length(inv, ctx->modulus->length - 1); s = inv->coeffs; } lenG = _fmpz_mod_poly_gcdinv_f(f, g, s, op->coeffs, op->length, ctx->modulus->coeffs, ctx->modulus->length, ctx->ctxp); if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = g; rop->alloc = op->length; } if (inv == op) { _fmpz_vec_clear(inv->coeffs, inv->alloc); inv->coeffs = s; inv->alloc = ctx->modulus->length - 1; } if (!fmpz_is_one(f)) { _fmpz_poly_set_length(inv, 0); fq_zero(rop, ctx); goto cleanup; } _fmpz_poly_set_length(rop, lenG); _fmpz_poly_set_length(inv, ctx->modulus->length - lenG); _fmpz_poly_normalise(inv); if (fmpz_is_one(fmpz_poly_lead(rop))) goto cleanup; if (!fmpz_invmod(f, fmpz_poly_lead(rop), fq_ctx_prime(ctx))) { fq_zero(rop, ctx); goto cleanup; } _fmpz_mod_vec_scalar_mul_fmpz_mod(rop->coeffs, rop->coeffs, rop->length, f, ctx->ctxp); _fmpz_mod_vec_scalar_mul_fmpz_mod(inv->coeffs, inv->coeffs, inv->length, f, ctx->ctxp); cleanup: fmpz_clear(f); return; } flint-3.1.3/src/fq/gen.c000066400000000000000000000017751461254215100147570ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fq.h" void fq_gen(fq_t rop, const fq_ctx_t ctx) { if (ctx->modulus->length == 2) { fmpz_poly_fit_length(rop, 1); fmpz_invmod(rop->coeffs, ctx->modulus->coeffs + 1, fq_ctx_prime(ctx)); fmpz_neg(rop->coeffs, rop->coeffs); fmpz_mul(rop->coeffs, rop->coeffs, ctx->modulus->coeffs); fmpz_mod(rop->coeffs, rop->coeffs, fq_ctx_prime(ctx)); _fmpz_poly_set_length(rop, !fmpz_is_zero(rop->coeffs)); } else { fmpz_poly_zero(rop); fmpz_poly_set_coeff_ui(rop, 0, 0); fmpz_poly_set_coeff_ui(rop, 1, 1); } } flint-3.1.3/src/fq/get_fmpz.c000066400000000000000000000011631461254215100160100ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq.h" int fq_get_fmpz(fmpz_t a, const fq_t b, const fq_ctx_t ctx) { if (b->length > 1) return 0; if (b->length == 1) fmpz_set(a, b->coeffs + 0); else fmpz_zero(a); return 1; } flint-3.1.3/src/fq/get_fmpz_mod_poly.c000066400000000000000000000013651461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_get_fmpz_mod_poly(fmpz_mod_poly_t a, const fq_t b, const fq_ctx_t ctx) { slong i, len = b->length; fmpz_mod_poly_fit_length(a, len, ctx->ctxp); for (i = 0; i < len; i++) fmpz_set(a->coeffs + i, b->coeffs + i); _fmpz_mod_poly_set_length(a, len); _fmpz_mod_poly_normalise(a); } flint-3.1.3/src/fq/get_fmpz_poly.c000066400000000000000000000010101461254215100170420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_get_fmpz_poly(fmpz_poly_t a, const fq_t b, const fq_ctx_t ctx) { fmpz_poly_set(a, b); } flint-3.1.3/src/fq/get_set_fmpz_mod_mat.c000066400000000000000000000021741461254215100203660ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_mat.h" #include "fq.h" void fq_get_fmpz_mod_mat(fmpz_mod_mat_t col, const fq_t a, const fq_ctx_t ctx) { slong i, n = fq_ctx_degree(ctx); for (i = 0; i < a->length; i++) fmpz_set(fmpz_mod_mat_entry(col, i, 0), a->coeffs + i); for ( ; i < n; i++) fmpz_zero(fmpz_mod_mat_entry(col, i, 0)); } void fq_set_fmpz_mod_mat(fq_t a, const fmpz_mod_mat_t col, const fq_ctx_t ctx) { slong i, n = fq_ctx_degree(ctx); fmpz_poly_fit_length(a, n); a->length = n; for (i = 0; i < n; i++) fmpz_set(a->coeffs + i, fmpz_mod_mat_entry(col, i, 0)); _fmpz_poly_normalise(a); } flint-3.1.3/src/fq/get_str.c000066400000000000000000000007741461254215100156530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" char * fq_get_str(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_get_str(op); } flint-3.1.3/src/fq/get_str_pretty.c000066400000000000000000000010241461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" char * fq_get_str_pretty(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_get_str_pretty(op, ctx->var); } flint-3.1.3/src/fq/init.c000066400000000000000000000011131461254215100151330ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_init(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_init(rop); } void fq_init2(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_init2(rop, fq_ctx_degree(ctx)); } flint-3.1.3/src/fq/inlines.c000066400000000000000000000010371461254215100156360ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_INLINES_C #include "fmpz.h" #include "fq.h" /* TODO: Remove this */ void __fq_ctx_prime(fmpz_t p, fq_ctx_t ctx) { fmpz_set(p, fq_ctx_prime(ctx)); } flint-3.1.3/src/fq/inv.c000066400000000000000000000032541461254215100147740ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" void _fq_inv(fmpz * rop, const fmpz * op, slong len, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); if (len == 1) { fmpz_invmod(rop, op, fq_ctx_prime(ctx)); _fmpz_vec_zero(rop + 1, d - 1); } else { _fmpz_mod_poly_invmod(rop, op, len, ctx->modulus->coeffs, d + 1, ctx->ctxp); } } void fq_inv(fq_t rop, const fq_t op, const fq_ctx_t ctx) { if (fq_is_zero(op, ctx)) { flint_throw(FLINT_ERROR, "Exception (fq_inv). Zero is not invertible.\n"); } else { const slong d = fq_ctx_degree(ctx); fmpz *t; if (rop == op) { t = _fmpz_vec_init(d); } else { fmpz_poly_fit_length(rop, d); t = rop->coeffs; } _fq_inv(t, op->coeffs, op->length, ctx); if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = d; rop->length = d; } else { _fmpz_poly_set_length(rop, d); } _fmpz_poly_normalise(rop); } } flint-3.1.3/src/fq/io.c000066400000000000000000000030721461254215100146050ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" /* printing *******************************************************************/ int fq_ctx_fprint(FILE * file, const fq_ctx_t ctx) { int r; r = flint_fprintf(file, "p = "); if (r <= 0) return r; r = fmpz_fprint(file, fq_ctx_prime(ctx)); if (r <= 0) return r; r = flint_fprintf(file, "\nd = %wd\n", fq_ctx_degree(ctx)); if (r <= 0) return r; r = flint_fprintf(file, "f(X) = "); if (r <= 0) return r; r = fmpz_mod_poly_fprint_pretty(file, ctx->modulus, "X", ctx->ctxp); if (r <= 0) return r; r = flint_fprintf(file, "\n"); return r; } void fq_ctx_print(const fq_ctx_t ctx) { fq_ctx_fprint(stdout, ctx); } int fq_fprint(FILE * file, const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_fprint(file, op); } void fq_print(const fq_t op, const fq_ctx_t ctx) { fmpz_poly_print(op); } int fq_fprint_pretty(FILE * file, const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_fprint_pretty(file, op, ctx->var); } int fq_print_pretty(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_print_pretty(op, ctx->var); } flint-3.1.3/src/fq/mat_templates.c000066400000000000000000000055361461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2015 Elena Sergeicheva Copyright (C) 2018 Tommy Hofmann Copyright (C) 2020, 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_mod_mat.h" #include "fq.h" #include "fq_vec.h" #include "fq_mat.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/add.c" #include "fq_mat_templates/can_solve.c" #include "fq_mat_templates/charpoly.c" #include "fq_mat_templates/clear.c" #include "fq_mat_templates/concat_horizontal.c" #include "fq_mat_templates/concat_vertical.c" #include "fq_mat_templates/equal.c" #include "fq_mat_templates/init.c" #include "fq_mat_templates/init_set.c" #include "fq_mat_templates/inv.c" #include "fq_mat_templates/io.c" #include "fq_mat_templates/is_one.c" #include "fq_mat_templates/is_zero.c" #include "fq_mat_templates/lu.c" #include "fq_mat_templates/lu_classical.c" #include "fq_mat_templates/lu_recursive.c" #include "fq_mat_templates/mat_entry_set.c" #include "fq_mat_templates/mat_invert_cols.c" #include "fq_mat_templates/mat_swap_cols.c" #include "fq_mat_templates/mat_swap_entrywise.c" #include "fq_mat_templates/minpoly.c" #include "fq_mat_templates/mul.c" #include "fq_mat_templates/mul_classical.c" #include "fq_mat_templates/mul_KS.c" #include "fq_mat_templates/mul_vec.c" #include "fq_mat_templates/neg.c" #include "fq_mat_templates/nullspace.c" #include "fq_mat_templates/one.c" #include "fq_mat_templates/randops.c" #include "fq_mat_templates/randpermdiag.c" #include "fq_mat_templates/randrank.c" #include "fq_mat_templates/randtest.c" #include "fq_mat_templates/randtril.c" #include "fq_mat_templates/randtriu.c" #include "fq_mat_templates/rank.c" #include "fq_mat_templates/rref.c" #include "fq_mat_templates/set.c" #include "fq_mat_templates/set_fmpz_mod_mat.c" #include "fq_mat_templates/set_nmod_mat.c" #include "fq_mat_templates/similarity.c" #include "fq_mat_templates/solve.c" #include "fq_mat_templates/solve_tril.c" #include "fq_mat_templates/solve_tril_classical.c" #include "fq_mat_templates/solve_tril_recursive.c" #include "fq_mat_templates/solve_triu.c" #include "fq_mat_templates/solve_triu_classical.c" #include "fq_mat_templates/solve_triu_recursive.c" #include "fq_mat_templates/sub.c" #include "fq_mat_templates/submul.c" #include "fq_mat_templates/swap.c" #include "fq_mat_templates/vec_mul.c" #include "fq_mat_templates/window_clear.c" #include "fq_mat_templates/window_init.c" #include "fq_mat_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq/mul.c000066400000000000000000000011341461254215100147700ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_mul(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx) { fmpz_poly_mul(rop, op1, op2); fq_reduce(rop, ctx); } flint-3.1.3/src/fq/mul_fmpz.c000066400000000000000000000011421461254215100160230ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_mul_fmpz(fq_t rop, const fq_t op, const fmpz_t x, const fq_ctx_t ctx) { fmpz_poly_scalar_mul_fmpz(rop, op, x); fq_reduce(rop, ctx); } flint-3.1.3/src/fq/mul_si.c000066400000000000000000000011271461254215100154650ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_mul_si(fq_t rop, const fq_t op, slong x, const fq_ctx_t ctx) { fmpz_poly_scalar_mul_si(rop, op, x); fq_reduce(rop, ctx); } flint-3.1.3/src/fq/mul_ui.c000066400000000000000000000011271461254215100154670ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_mul_ui(fq_t rop, const fq_t op, ulong x, const fq_ctx_t ctx) { fmpz_poly_scalar_mul_ui(rop, op, x); fq_reduce(rop, ctx); } flint-3.1.3/src/fq/neg.c000066400000000000000000000013721461254215100147500ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_neg(fq_t rop, const fq_t op, const fq_ctx_t ctx) { slong len = op->length; fmpz_poly_fit_length(rop, len); _fmpz_poly_set_length(rop, len); _fmpz_mod_poly_neg(rop->coeffs, op->coeffs, op->length, ctx->ctxp); } flint-3.1.3/src/fq/norm.c000066400000000000000000000034041461254215100151500ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2017 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq.h" /* Computes the norm on $\mathbf{F}_q$. */ void _fq_norm(fmpz_t rop, const fmpz * op, slong len, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); if (d == 1) { fmpz_set(rop, op + 0); } else if (len == 1) { fmpz_mod_pow_ui(rop, op + 0, d, ctx->ctxp); } else { _fmpz_mod_poly_resultant(rop, ctx->modulus->coeffs, ctx->modulus->length, op, len, ctx->ctxp); /* XXX: This part of the code is currently untested as the Conway polynomials used for the extension Fq/Fp are monic. TODO: make polynomial monic!!! reading the source, a[] is monic, modulus is not. Why???? */ if (!fmpz_is_one(ctx->modulus->coeffs + d)) { fmpz_t f; fmpz_init(f); fmpz_mod_pow_ui(f, ctx->modulus->coeffs + d, len - 1, ctx->ctxp); fmpz_mod_inv(f, f, ctx->ctxp); fmpz_mod_mul(rop, f, rop, ctx->ctxp); fmpz_clear(f); } } } void fq_norm(fmpz_t rop, const fq_t op, const fq_ctx_t ctx) { if (fq_is_zero(op, ctx)) { fmpz_zero(rop); } else { _fq_norm(rop, op->coeffs, op->length, ctx); } } flint-3.1.3/src/fq/poly_factor_templates.c000066400000000000000000000041741461254215100206010ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2019 Edouard Rousseau Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fq.h" #include "fq_vec.h" #include "fq_mat.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/clear.c" #include "fq_poly_factor_templates/concat.c" #include "fq_poly_factor_templates/factor_berlekamp.c" #include "fq_poly_factor_templates/factor.c" #include "fq_poly_factor_templates/factor_cantor_zassenhaus.c" #include "fq_poly_factor_templates/factor_distinct_deg.c" #include "fq_poly_factor_templates/factor_equal_deg.c" #include "fq_poly_factor_templates/factor_equal_deg_prob.c" #include "fq_poly_factor_templates/factor_kaltofen_shoup.c" #include "fq_poly_factor_templates/factor_split_single.c" #include "fq_poly_factor_templates/factor_squarefree.c" #include "fq_poly_factor_templates/fit_length.c" #include "fq_poly_factor_templates/init.c" #include "fq_poly_factor_templates/insert.c" #include "fq_poly_factor_templates/is_irreducible_ben_or.c" #include "fq_poly_factor_templates/is_irreducible.c" #include "fq_poly_factor_templates/is_irreducible_ddf.c" #include "fq_poly_factor_templates/is_squarefree.c" #include "fq_poly_factor_templates/iterated_frobenius_preinv.c" #include "fq_poly_factor_templates/pow.c" #include "fq_poly_factor_templates/print.c" #include "fq_poly_factor_templates/print_pretty.c" #include "fq_poly_factor_templates/realloc.c" #include "fq_poly_factor_templates/roots.c" #include "fq_poly_factor_templates/set.c" #undef CAP_T #undef T flint-3.1.3/src/fq/poly_templates.c000066400000000000000000000123571461254215100172450ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007-2012 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2010-2012 Sebastian Pancratz Copyright (C) 2011, 2012 Fredrik Johansson Copyright (C) 2012 Andres Goens Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_vec.h" #include "fq.h" #include "fq_vec.h" #include "fq_mat.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/add.c" #include "fq_poly_templates/add_series.c" #include "fq_poly_templates/add_si.c" #include "fq_poly_templates/clear.c" #include "fq_poly_templates/comparisons.c" #include "fq_poly_templates/compose.c" #include "fq_poly_templates/compose_mod.c" #include "fq_poly_templates/compose_mod_brent_kung.c" #include "fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c" #include "fq_poly_templates/compose_mod_brent_kung_preinv.c" #include "fq_poly_templates/compose_mod_horner.c" #include "fq_poly_templates/compose_mod_horner_preinv.c" #include "fq_poly_templates/compose_mod_preinv.c" #include "fq_poly_templates/deflate.c" #include "fq_poly_templates/deflation.c" #include "fq_poly_templates/derivative.c" #include "fq_poly_templates/div.c" #include "fq_poly_templates/div_newton_n_preinv.c" #include "fq_poly_templates/div_series.c" #include "fq_poly_templates/divides.c" #include "fq_poly_templates/divrem.c" #include "fq_poly_templates/divrem_f.c" #include "fq_poly_templates/divrem_newton_n_preinv.c" #include "fq_poly_templates/equal.c" #include "fq_poly_templates/equal_trunc.c" #include "fq_poly_templates/evaluate_fq.c" #include "fq_poly_templates/evaluate_fq_vec.c" #include "fq_poly_templates/evaluate_fq_vec_fast.c" #include "fq_poly_templates/evaluate_fq_vec_iter.c" #include "fq_poly_templates/fit_length.c" #include "fq_poly_templates/gcd.c" #include "fq_poly_templates/gcd_euclidean_f.c" #include "fq_poly_templates/gen.c" #include "fq_poly_templates/get_coeff.c" #include "fq_poly_templates/get_str.c" #include "fq_poly_templates/get_str_pretty.c" #include "fq_poly_templates/hamming_weight.c" #include "fq_poly_templates/inflate.c" #include "fq_poly_templates/init.c" #include "fq_poly_templates/inv_series_newton.c" #include "fq_poly_templates/invsqrt_series.c" #include "fq_poly_templates/io.c" #include "fq_poly_templates/is_gen.c" #include "fq_poly_templates/make_monic.c" #define USE_MUL_REORDER 1 #include "fq_poly_templates/mul.c" #undef USE_MUL_REORDER /* #include "fq_poly_templates/mul_classical.c" */ #include "fq_poly_templates/mul_KS.c" #include "fq_poly_templates/mul_reorder.c" #include "fq_poly_templates/mulhigh.c" #include "fq_poly_templates/mulhigh_classical.c" #include "fq_poly_templates/mullow.c" #include "fq_poly_templates/mullow_classical.c" #include "fq_poly_templates/mullow_KS.c" #include "fq_poly_templates/mulmod.c" #include "fq_poly_templates/mulmod_preinv.c" #include "fq_poly_templates/neg.c" #include "fq_poly_templates/normalise.c" #include "fq_poly_templates/one.c" #include "fq_poly_templates/pow.c" #include "fq_poly_templates/pow_trunc.c" #include "fq_poly_templates/pow_trunc_binexp.c" #include "fq_poly_templates/powmod_fmpz_binexp.c" #include "fq_poly_templates/powmod_fmpz_binexp_preinv.c" #include "fq_poly_templates/powmod_fmpz_sliding_preinv.c" #include "fq_poly_templates/powmod_ui_binexp.c" #include "fq_poly_templates/powmod_ui_binexp_preinv.c" #include "fq_poly_templates/powmod_x_fmpz_preinv.c" #include "fq_poly_templates/randtest.c" #include "fq_poly_templates/randtest_irreducible.c" #include "fq_poly_templates/randtest_monic.c" #include "fq_poly_templates/realloc.c" #include "fq_poly_templates/rem.c" #include "fq_poly_templates/remove.c" #include "fq_poly_templates/reverse.c" #include "fq_poly_templates/scalar_addmul_fq.c" #include "fq_poly_templates/scalar_div_fq.c" #include "fq_poly_templates/scalar_mul_fq.c" #include "fq_poly_templates/scalar_submul_fq.c" #include "fq_poly_templates/set.c" #include "fq_poly_templates/set_coeff.c" #include "fq_poly_templates/set_fmpz_mod_poly.c" #include "fq_poly_templates/set_fq.c" #include "fq_poly_templates/set_length.c" #include "fq_poly_templates/set_nmod_poly.c" #include "fq_poly_templates/set_trunc.c" #include "fq_poly_templates/shift_left.c" #include "fq_poly_templates/shift_right.c" #define USE_SQR_REORDER 1 #include "fq_poly_templates/sqr.c" #undef USE_SQR_REORDER #include "fq_poly_templates/sqr_classical.c" #include "fq_poly_templates/sqr_KS.c" #include "fq_poly_templates/sqr_reorder.c" #include "fq_poly_templates/sqrt.c" #include "fq_poly_templates/sqrt_series.c" #include "fq_poly_templates/sub.c" #include "fq_poly_templates/sub_series.c" #include "fq_poly_templates/swap.c" #include "fq_poly_templates/tree.c" #include "fq_poly_templates/truncate.c" #include "fq_poly_templates/xgcd.c" #include "fq_poly_templates/xgcd_euclidean_f.c" #include "fq_poly_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq/pow.c000066400000000000000000000100411461254215100147750ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fq.h" void _fq_pow(fmpz * rop, const fmpz * op, slong len, const fmpz_t e, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); if (fmpz_is_zero(e)) { fmpz_one(rop); _fmpz_vec_zero(rop + 1, 2 * d - 1 - 1); } else if (fmpz_is_one(e)) { _fmpz_vec_set(rop, op, len); _fmpz_vec_zero(rop + len, 2 * d - 1 - len); } else { ulong bit; fmpz *v = _fmpz_vec_init(2 * d - 1); fmpz *R, *S, *T; _fmpz_vec_zero(rop, 2 * d - 1); /* Set bits to the bitmask with a 1 one place lower than the msb of e */ bit = fmpz_bits(e) - 2; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if (fmpz_tstbit(e, bit2)) swaps = ~swaps; while (bit2--) if (!fmpz_tstbit(e, bit2)) swaps = ~swaps; if (swaps == 0U) { R = rop; S = v; } else { R = v; S = rop; } } /* We unroll the first step of the loop, referring to {op, len} */ _fmpz_poly_sqr(R, op, len); _fq_reduce(R, 2 * len - 1, ctx); if (fmpz_tstbit(e, bit)) { _fmpz_poly_mul(S, R, d, op, len); _fq_reduce(S, d + len - 1, ctx); T = R; R = S; S = T; } while (bit--) { if (fmpz_tstbit(e, bit)) { _fmpz_poly_sqr(S, R, d); _fq_reduce(S, 2 * d - 1, ctx); _fmpz_poly_mul(R, S, d, op, len); _fq_reduce(R, d + len - 1, ctx); } else { _fmpz_poly_sqr(S, R, d); _fq_reduce(S, 2 * d - 1, ctx); T = R; R = S; S = T; } } _fmpz_vec_clear(v, 2 * d - 1); } } void fq_pow(fq_t rop, const fq_t op, const fmpz_t e, const fq_ctx_t ctx) { if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "Exception (fq_pow). e < 0.\n"); } if (fmpz_is_zero(e)) { fq_one(rop, ctx); } else if (fq_is_zero(op, ctx)) { fq_zero(rop, ctx); } else if (fmpz_is_one(e)) { fq_set(rop, op, ctx); } else { const slong d = fq_ctx_degree(ctx); fmpz *t; if (rop == op) { t = _fmpz_vec_init(2 * d - 1); } else { fmpz_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } if (fmpz_cmpabs(e, fq_ctx_prime(ctx)) < 0) _fq_pow(t, op->coeffs, op->length, e, ctx); else { fmpz_t order, e_mod; fmpz_init(e_mod); fmpz_init(order); fq_ctx_order(order, ctx); fmpz_sub_ui(order, order, 1); fmpz_mod(e_mod, e, order); _fq_pow(t, op->coeffs, op->length, e_mod, ctx); fmpz_clear(order); fmpz_clear(e_mod); } if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } else { _fmpz_poly_set_length(rop, d); } _fmpz_poly_normalise(rop); } } flint-3.1.3/src/fq/pow_ui.c000066400000000000000000000011421461254215100154740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq.h" /* TODO: optimize */ void fq_pow_ui(fq_t rop, const fq_t op, const ulong e, const fq_ctx_t ctx) { fmpz_t exp; fmpz_init_set_ui(exp, e); fq_pow(rop, op, exp, ctx); fmpz_clear(exp); } flint-3.1.3/src/fq/profile/000077500000000000000000000000001461254215100154705ustar00rootroot00000000000000flint-3.1.3/src/fq/profile/p-inv.c000066400000000000000000000030061461254215100166640ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "profiler.h" #ifndef REPS #define REPS 1000000 #endif int main(void) { timeit_t t0; slong i, d, cpu, wall; fmpz_t p; fq_ctx_t ctx; fq_t a,b; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2+ n_randint(state,3),1)); d = n_randint(state,10)+1; fq_ctx_init_conway(ctx,p,d,"a"); fq_init(a, ctx); fq_init(b, ctx); fq_randtest_not_zero(a,state,ctx); flint_printf("INV benchmark:single repeated inversion: \n"); timeit_start(t0); for(i=0;icpu , t0->wall ); flint_printf("random inversions: \n"); wall = 0; cpu = 0; for(i=0;icpu; wall = wall + t0->wall; } flint_printf ( " cpu = %wd ms, wall = %wd ms \n " , cpu , wall ); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq/profile/p-mul.c000066400000000000000000000017611461254215100166730ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "profiler.h" #ifndef REPS #define REPS 1000000 #endif int main(void) { fmpz_t p; slong d; fq_ctx_t ctx; fq_t a,b,c; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2+ n_randint(state,3),1)); d = n_randint(state,10)+1; fq_ctx_init_conway(ctx,p,d,"a"); fq_init(a, ctx); fq_init(b, ctx); fq_init(c, ctx); fq_randtest_not_zero(a,state,ctx); fq_randtest_not_zero(b,state,ctx); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq/profile/p-reduce.c000066400000000000000000000032551461254215100173450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fq.h" #include "profiler.h" int main(int argc, char** argv) { slong i, result; fmpz_t p; slong d; fq_ctx_t ctx; fq_t a,b,c; double dense; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); d = atoi(argv[2]); fq_ctx_init(ctx,p,d,"a"); fq_init(a, ctx); fq_init(b, ctx); fq_init(c, ctx); fq_randtest_not_zero(a,state,ctx); fq_randtest_not_zero(b,state,ctx); fmpz_poly_mul(c, a, b); init_clock(0); prof_start(); for (i=0; i < 1000; i++) { fmpz_poly_set(a, c); _fq_dense_reduce(a->coeffs, a->length, ctx); } prof_stop(); dense = get_clock(0); init_clock(0); prof_start(); for (i = 0; i < 1000; i++) { fmpz_poly_set(b, c); _fq_sparse_reduce(b->coeffs, b->length, ctx); } prof_stop(); if (get_clock(0) <= dense) { result = 1; } else { result = 0; } fmpz_print(p); flint_printf(" %d %d %d\n", ctx->len, ctx->modulus->length, result); fq_clear(a, ctx); fq_clear(b, ctx); fq_clear(c, ctx); fq_ctx_clear(ctx); fmpz_clear(p); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq/pth_root.c000066400000000000000000000013431461254215100160330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" void fq_pth_root(fq_t rop, const fq_t op1, const fq_ctx_t ctx) { slong i, d; if (fq_is_zero(op1, ctx) || fq_is_one(op1, ctx)) { fq_set(rop, op1, ctx); return; } d = fq_ctx_degree(ctx) - 1; fq_set(rop, op1, ctx); for (i = 0; i < d; i++) { fq_pow(rop, rop, fq_ctx_prime(ctx), ctx); } } flint-3.1.3/src/fq/rand.c000066400000000000000000000017621461254215100151260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fq.h" void fq_rand(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); slong i; fmpz_poly_fit_length(rop, d); for (i = 0; i < d; i++) { fmpz_randm(rop->coeffs + i, state, fq_ctx_prime(ctx)); } _fmpz_poly_set_length(rop, d); _fmpz_poly_normalise(rop); } void fq_rand_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) { int tries = 3; do { fq_rand(rop, state, ctx); if (!fq_is_zero(rop, ctx)) return; } while (--tries >= 0); fq_one(rop, ctx); } flint-3.1.3/src/fq/randtest.c000066400000000000000000000034521461254215100160240ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fq.h" void fq_randtest(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); slong i, sparse; fmpz_poly_fit_length(rop, d); if (n_randint(state, 2)) { for (i = 0; i < d; i++) fmpz_randm(rop->coeffs + i, state, fq_ctx_prime(ctx)); } else { sparse = 1 + n_randint(state, FLINT_MAX(2, d)); for (i = 0; i < d; i++) if (n_randint(state, sparse)) fmpz_zero(rop->coeffs + i); else fmpz_randm(rop->coeffs + i, state, fq_ctx_prime(ctx)); } _fmpz_poly_set_length(rop, d); _fmpz_poly_normalise(rop); } void fq_randtest_dense(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); slong i; fmpz_poly_fit_length(rop, d); for (i = 0; i < d - 1; i++) { fmpz_randm(rop->coeffs + i, state, fq_ctx_prime(ctx)); } fmpz_one(rop->coeffs + d - 1); _fmpz_poly_set_length(rop, d); _fmpz_poly_normalise(rop); } void fq_randtest_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx) { slong i; fq_randtest(rop, state, ctx); for (i = 0; fq_is_zero(rop, ctx) && (i < 10); i++) fq_randtest(rop, state, ctx); if (fq_is_zero(rop, ctx)) fq_one(rop, ctx); } flint-3.1.3/src/fq/reduce.c000066400000000000000000000042201461254215100154410ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" #include "fq.h" void _fq_sparse_reduce(fmpz *R, slong lenR, const fq_ctx_t ctx) { const slong d = ctx->j[ctx->len - 1]; FMPZ_VEC_NORM(R, lenR); if (lenR > d) { slong i, k; for (i = lenR - 1; i >= d; i--) { for (k = ctx->len - 2; k >= 0; k--) { fmpz_submul(R + ctx->j[k] + i - d, R + i, ctx->a + k); } fmpz_zero(R + i); } } _fmpz_mod_vec_set_fmpz_vec(R, R, FLINT_MIN(d, lenR), ctx->ctxp); } void _fq_dense_reduce(fmpz* R, slong lenR, const fq_ctx_t ctx) { fmpz *q, *r; if (lenR < ctx->modulus->length) { _fmpz_mod_vec_set_fmpz_vec(R, R, lenR, ctx->ctxp); return; } q = _fmpz_vec_init(lenR - ctx->modulus->length + 1); r = _fmpz_vec_init(ctx->modulus->length - 1); _fmpz_mod_vec_set_fmpz_vec(R, R, lenR, ctx->ctxp); _fmpz_mod_poly_divrem_newton_n_preinv(q, r, R, lenR, ctx->modulus->coeffs, ctx->modulus->length, ctx->inv->coeffs, ctx->inv->length, ctx->ctxp); _fmpz_vec_set(R, r, ctx->modulus->length - 1); _fmpz_vec_clear(q, lenR - ctx->modulus->length + 1); _fmpz_vec_clear(r, ctx->modulus->length - 1); } void _fq_reduce(fmpz* R, slong lenR, const fq_ctx_t ctx) { if (ctx->sparse_modulus) _fq_sparse_reduce(R, lenR, ctx); else _fq_dense_reduce(R, lenR, ctx); } void fq_reduce(fq_t rop, const fq_ctx_t ctx) { _fq_reduce(rop->coeffs, rop->length, ctx); rop->length = FLINT_MIN(rop->length, ctx->modulus->length - 1); _fmpz_poly_normalise(rop); } flint-3.1.3/src/fq/set_fmpz_mod_poly.c000066400000000000000000000022271461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_set_fmpz_mod_poly(fq_t a, const fmpz_mod_poly_t b, const fq_ctx_t ctx) { slong i, len = b->length; if (len <= 2*(ctx->modulus->length - 1)) { fmpz_poly_fit_length(a, len); for (i = 0; i < len; i++) fmpz_set(a->coeffs + i, b->coeffs + i); _fmpz_poly_set_length(a, len); fq_reduce(a, ctx); } else { fmpz_mod_poly_t q, r; fmpz_mod_poly_init(q, ctx->ctxp); fmpz_mod_poly_init(r, ctx->ctxp); fmpz_mod_poly_divrem(q, r, b, fq_ctx_modulus(ctx), ctx->ctxp); fmpz_mod_poly_get_fmpz_poly(a, r, ctx->ctxp); fmpz_mod_poly_clear(q, ctx->ctxp); fmpz_mod_poly_clear(r, ctx->ctxp); } } flint-3.1.3/src/fq/set_fmpz_poly.c000066400000000000000000000021471461254215100170720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_set_fmpz_poly(fq_t a, const fmpz_poly_t b, const fq_ctx_t ctx) { if (b->length <= 2*(ctx->modulus->length - 1)) { fmpz_poly_set(a, b); fq_reduce(a, ctx); } else { fmpz_mod_poly_t bp, q, r; fmpz_mod_poly_init(bp, ctx->ctxp); fmpz_mod_poly_init(q, ctx->ctxp); fmpz_mod_poly_init(r, ctx->ctxp); fmpz_mod_poly_set_fmpz_poly(bp, b, ctx->ctxp); fmpz_mod_poly_divrem(q, r, bp, ctx->modulus, ctx->ctxp); fmpz_mod_poly_get_fmpz_poly(a, r, ctx->ctxp); fmpz_mod_poly_clear(bp, ctx->ctxp); fmpz_mod_poly_clear(q, ctx->ctxp); fmpz_mod_poly_clear(r, ctx->ctxp); } } flint-3.1.3/src/fq/sqr.c000066400000000000000000000011501461254215100147760ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_sqr(fq_t rop, const fq_t op, const fq_ctx_t ctx) { fmpz_poly_sqr(rop, op); fq_reduce(rop, ctx); } flint-3.1.3/src/fq/sub.c000066400000000000000000000015401461254215100147650ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" void fq_sub(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx) { slong max = FLINT_MAX(op1->length, op2->length); fmpz_poly_fit_length(rop, max); _fmpz_mod_poly_sub(rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx->ctxp); _fmpz_poly_set_length(rop, max); _fmpz_poly_normalise(rop); } flint-3.1.3/src/fq/sub_one.c000066400000000000000000000011001461254215100156160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" void fq_sub_one(fq_t rop, const fq_t op1, const fq_ctx_t ctx) { fq_t one; fq_init(one, ctx); fq_one(one, ctx); fq_sub(rop, op1, one, ctx); fq_clear(one, ctx); } flint-3.1.3/src/fq/swap.c000066400000000000000000000007731461254215100151550ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" void fq_swap(fq_t op1, fq_t op2, const fq_ctx_t ctx) { fmpz_poly_swap(op1, op2); } flint-3.1.3/src/fq/templates.c000066400000000000000000000014561461254215100162000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Luca De Feo Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/div.c" #include "fq_templates/is_invertible.c" #include "fq_templates/is_invertible_f.c" #include "fq_templates/is_square.c" #include "fq_templates/multiplicative_order.c" #include "fq_templates/sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/000077500000000000000000000000001461254215100150075ustar00rootroot00000000000000flint-3.1.3/src/fq/test/main.c000066400000000000000000000041631461254215100161030ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-assign.c" #include "t-ctx_init.c" #include "t-div.c" #include "t-frobenius.c" #include "t-get_set_fmpz.c" #include "t-get_set_fmpz_mod_poly.c" #include "t-get_set_fmpz_poly.c" #include "t-inv.c" #include "t-is_invertible.c" #include "t-is_invertible_f.c" #include "t-is_primitive.c" #include "t-is_square.c" #include "t-mul.c" #include "t-mul_fmpz.c" #include "t-mul_si.c" #include "t-multiplicative_order.c" #include "t-mul_ui.c" #include "t-neg.c" #include "t-norm.c" #include "t-pow.c" #include "t-pth_root.c" #include "t-sqr.c" #include "t-sqrt.c" #include "t-sub.c" #include "t-trace.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_add), TEST_FUNCTION(fq_assign), TEST_FUNCTION(fq_ctx_init), TEST_FUNCTION(fq_div), TEST_FUNCTION(fq_frobenius), TEST_FUNCTION(fq_get_set_fmpz), TEST_FUNCTION(fq_get_set_fmpz_mod_poly), TEST_FUNCTION(fq_get_set_fmpz_poly), TEST_FUNCTION(fq_inv), TEST_FUNCTION(fq_is_invertible), TEST_FUNCTION(fq_is_invertible_f), TEST_FUNCTION(fq_is_primitive), TEST_FUNCTION(fq_is_square), TEST_FUNCTION(fq_mul), TEST_FUNCTION(fq_mul_fmpz), TEST_FUNCTION(fq_mul_si), TEST_FUNCTION(fq_multiplicative_order), TEST_FUNCTION(fq_mul_ui), TEST_FUNCTION(fq_neg), TEST_FUNCTION(fq_norm), TEST_FUNCTION(fq_pow), TEST_FUNCTION(fq_pth_root), TEST_FUNCTION(fq_sqr), TEST_FUNCTION(fq_sqrt), TEST_FUNCTION(fq_sub), TEST_FUNCTION(fq_trace) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq/test/t-add.c000066400000000000000000000011131461254215100161400ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-assign.c000066400000000000000000000010001461254215100166670ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-assign.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-ctx_init.c000066400000000000000000000011221461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-ctx_init.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-div.c000066400000000000000000000007751461254215100162070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-div.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-frobenius.c000066400000000000000000000011211461254215100174030ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-frobenius.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-get_set_fmpz.c000066400000000000000000000010111461254215100200730ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-get_set_fmpz.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-get_set_fmpz_mod_poly.c000066400000000000000000000032201461254215100220010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_poly.h" #include "fq.h" TEST_FUNCTION_START(fq_get_set_fmpz_mod_poly, state) { slong i, j; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fq_ctx_t ctx; fq_t x, y; fmpz_mod_poly_t z, t; fq_ctx_init_randtest(ctx, state, 0); fq_init(x, ctx); fq_init(y, ctx); fmpz_mod_poly_init(z, ctx->ctxp); fmpz_mod_poly_init(t, ctx->ctxp); for (j = 0; j < 100; j++) { fq_rand(x, state, ctx); fq_rand(y, state, ctx); fq_get_fmpz_mod_poly(z, x, ctx); fmpz_mod_poly_randtest(t, state, 20, ctx->ctxp); fmpz_mod_poly_mul(t, t, ctx->modulus, ctx->ctxp); fmpz_mod_poly_add(z, z, t, ctx->ctxp); fq_set_fmpz_mod_poly(y, z, ctx); if (!fq_equal(y, x, ctx)) { flint_printf("FAIL:\n"); flint_printf("check get/set match i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_mod_poly_clear(t, ctx->ctxp); fmpz_mod_poly_clear(z, ctx->ctxp); fq_clear(y, ctx); fq_clear(x, ctx); fq_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq/test/t-get_set_fmpz_poly.c000066400000000000000000000032621461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" TEST_FUNCTION_START(fq_get_set_fmpz_poly, state) { slong i, j; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_ctx_t ctx; fq_t x, y; fmpz_poly_t z, t1, t2; fq_ctx_init_randtest(ctx, state, 0); fq_init(x, ctx); fq_init(y, ctx); fmpz_poly_init(z); fmpz_poly_init(t1); fmpz_poly_init(t2); for (j = 0; j < 20; j++) { fq_rand(x, state, ctx); fq_rand(y, state, ctx); fq_get_fmpz_poly(z, x, ctx); fmpz_poly_randtest(t1, state, 20, 200); fmpz_mod_poly_get_fmpz_poly(t2, ctx->modulus, ctx->ctxp); fmpz_poly_mul(t1, t1, t2); fmpz_poly_add(z, z, t1); fq_set_fmpz_poly(y, z, ctx); if (!fq_equal(y, x, ctx)) { flint_printf("FAIL:\n"); flint_printf("check get/set match i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_poly_clear(t2); fmpz_poly_clear(t1); fmpz_poly_clear(z); fq_clear(y, ctx); fq_clear(x, ctx); fq_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq/test/t-inv.c000066400000000000000000000011131461254215100162040ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-inv.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-is_invertible.c000066400000000000000000000010071461254215100202500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-is_invertible.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-is_invertible_f.c000066400000000000000000000010111461254215100205500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-is_invertible_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-is_primitive.c000066400000000000000000000010061461254215100201140ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-is_primitive.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-is_square.c000066400000000000000000000010041461254215100174020ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-is_square.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-mul.c000066400000000000000000000011131461254215100162050ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-mul_fmpz.c000066400000000000000000000011121461254215100172400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-mul_fmpz.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-mul_si.c000066400000000000000000000011101461254215100166750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-mul_si.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-mul_ui.c000066400000000000000000000011101461254215100166770ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-mul_ui.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-multiplicative_order.c000066400000000000000000000010161461254215100216400ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-multiplicative_order.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-neg.c000066400000000000000000000011131461254215100161610ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-norm.c000066400000000000000000000011141461254215100163640ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-norm.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-pow.c000066400000000000000000000011131461254215100162150ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-pow.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-pth_root.c000066400000000000000000000011201461254215100172440ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-pth_root.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-sqr.c000066400000000000000000000011131461254215100162150ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-sqr.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-sqrt.c000066400000000000000000000007771461254215100164200ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-sub.c000066400000000000000000000011131461254215100162010ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq/test/t-trace.c000066400000000000000000000011151461254215100165100ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_templates/test/t-trace.c" #undef CAP_T #undef T flint-3.1.3/src/fq/trace.c000066400000000000000000000026631461254215100153010ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq.h" void _fq_trace(fmpz_t rop, const fmpz * op, slong len, const fq_ctx_t ctx) { const slong d = fq_ctx_degree(ctx); slong i, l; fmpz *t; t = _fmpz_vec_init(d); fmpz_set_ui(t + 0, d); for (i = 1; i < d; i++) { for (l = ctx->len - 2; l >= 0 && ctx->j[l] >= d - (i - 1); l--) { fmpz_addmul(t + i, t + (ctx->j[l] + i - d), ctx->a + l); } if (l >= 0 && ctx->j[l] == d - i) { fmpz_addmul_ui(t + i, ctx->a + l, i); } fmpz_neg(t + i, t + i); fmpz_mod(t + i, t + i, fq_ctx_prime(ctx)); } fmpz_zero(rop); for (i = 0; i < len; i++) { fmpz_addmul(rop, op + i, t + i); } fmpz_mod(rop, rop, fq_ctx_prime(ctx)); _fmpz_vec_clear(t, d); } void fq_trace(fmpz_t rop, const fq_t op, const fq_ctx_t ctx) { if (fq_is_zero(op, ctx)) { fmpz_zero(rop); } else { _fq_trace(rop, op->coeffs, op->length, ctx); } } flint-3.1.3/src/fq/vec_templates.c000066400000000000000000000021111461254215100170220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.h" #include "fq.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/add.c" #include "fq_vec_templates/clear.c" #include "fq_vec_templates/equal.c" #include "fq_vec_templates/init.c" #include "fq_vec_templates/io.c" #include "fq_vec_templates/is_zero.c" #include "fq_vec_templates/neg.c" #include "fq_vec_templates/randtest.c" #include "fq_vec_templates/scalar_addmul_fq.c" #include "fq_vec_templates/scalar_mul_fq.c" #include "fq_vec_templates/scalar_submul_fq.c" #include "fq_vec_templates/set.c" #include "fq_vec_templates/sub.c" #include "fq_vec_templates/swap.c" #include "fq_vec_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_default.h000066400000000000000000000651751461254215100157230ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_DEFAULT_H #define FQ_DEFAULT_H #ifdef FQ_DEFAULT_INLINES_C #define FQ_DEFAULT_INLINE #else #define FQ_DEFAULT_INLINE static inline #endif #include "nmod.h" #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_nmod.h" #include "fq_zech.h" #include "gr.h" /* Internal type codes */ #define _FQ_DEFAULT_FQ_ZECH GR_CTX_FQ_ZECH #define _FQ_DEFAULT_FQ_NMOD GR_CTX_FQ_NMOD #define _FQ_DEFAULT_FQ GR_CTX_FQ #define _FQ_DEFAULT_NMOD GR_CTX_NMOD #define _FQ_DEFAULT_FMPZ_MOD GR_CTX_FMPZ_MOD /* Original type codes for backward compatibility. */ #define FQ_DEFAULT_FQ_ZECH 1 #define FQ_DEFAULT_FQ_NMOD 2 #define FQ_DEFAULT_FQ 3 #define FQ_DEFAULT_NMOD 4 #define FQ_DEFAULT_FMPZ_MOD 5 /* Data types and context ****************************************************/ #ifdef __cplusplus extern "C" { #endif typedef union fq_default_struct { fq_t fq; fq_nmod_t fq_nmod; fq_zech_t fq_zech; ulong nmod; fmpz_t fmpz_mod; } fq_default_struct; typedef fq_default_struct fq_default_t[1]; typedef gr_ctx_struct fq_default_ctx_struct; typedef fq_default_ctx_struct fq_default_ctx_t[1]; #define FQ_DEFAULT_GR_CTX(ctx) ((gr_ctx_struct *) (ctx)) #define _FQ_DEFAULT_TYPE(ctx) (FQ_DEFAULT_GR_CTX(ctx)->which_ring) #define FQ_DEFAULT_CTX_FQ(ctx) ((fq_ctx_struct *) GR_CTX_DATA_AS_PTR(FQ_DEFAULT_GR_CTX(ctx))) #define FQ_DEFAULT_CTX_FQ_ZECH(ctx) ((fq_zech_ctx_struct *) GR_CTX_DATA_AS_PTR(FQ_DEFAULT_GR_CTX(ctx))) #define FQ_DEFAULT_CTX_FQ_NMOD(ctx) ((fq_nmod_ctx_struct *) GR_CTX_DATA_AS_PTR(FQ_DEFAULT_GR_CTX(ctx))) #define FQ_DEFAULT_CTX_NMOD(ctx) ((nmod_t *) FQ_DEFAULT_GR_CTX(ctx))[0] #define FQ_DEFAULT_CTX_FMPZ_MOD(ctx) ((fmpz_mod_ctx_struct *) GR_CTX_DATA_AS_PTR(FQ_DEFAULT_GR_CTX(ctx))) /* hack: access to gr_ctx internals for nmod and fmpz_mod; this will be removed after further refactoring */ typedef struct { fmpz_mod_ctx_struct * ctx; truth_t is_prime; fmpz a; /* when used as finite field with defining polynomial x - a */ } _gr_fmpz_mod_ctx_struct; typedef struct { nmod_t nmod; ulong a; /* when used as finite field with defining polynomial x - a */ } _gr_nmod_ctx_struct; /* end hack */ #define NMOD_CTX_A(ring_ctx) (&((((_gr_nmod_ctx_struct *)(ring_ctx))->a))) #define FMPZ_MOD_CTX_A(ring_ctx) (&((((_gr_fmpz_mod_ctx_struct *)(ring_ctx))->a))) #define FQ_DEFAULT_CTX_NMOD_A(ctx) NMOD_CTX_A(ctx) #define FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx) FMPZ_MOD_CTX_A(ctx) void fq_default_ctx_init_type(fq_default_ctx_t ctx, const fmpz_t p, slong d, const char *var, int type); FQ_DEFAULT_INLINE void fq_default_ctx_init(fq_default_ctx_t ctx, const fmpz_t p, slong d, const char *var) { fq_default_ctx_init_type(ctx, p, d, var, 0); } FQ_DEFAULT_INLINE void * fq_default_ctx_inner(const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) return (void *) &FQ_DEFAULT_CTX_NMOD(ctx); else return (void *) GR_CTX_DATA_AS_PTR(ctx); } void fq_default_ctx_init_modulus_type(fq_default_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var, int type); void fq_default_ctx_init_modulus(fq_default_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var); void fq_default_ctx_init_modulus_nmod_type(fq_default_ctx_t ctx, const nmod_poly_t modulus, const char * var, int type); void fq_default_ctx_init_modulus_nmod(fq_default_ctx_t ctx, const nmod_poly_t modulus, const char * var); FQ_DEFAULT_INLINE void fq_default_ctx_clear(fq_default_ctx_t ctx) { gr_ctx_clear(FQ_DEFAULT_GR_CTX(ctx)); } FQ_DEFAULT_INLINE int fq_default_ctx_type(const fq_default_ctx_t ctx) { int type = FQ_DEFAULT_GR_CTX(ctx)->which_ring; if (type == _FQ_DEFAULT_FQ_ZECH) return FQ_DEFAULT_FQ_ZECH; if (type == _FQ_DEFAULT_FQ_NMOD) return FQ_DEFAULT_FQ_NMOD; if (type == _FQ_DEFAULT_FQ) return FQ_DEFAULT_FQ; if (type == _FQ_DEFAULT_NMOD) return FQ_DEFAULT_NMOD; if (type == _FQ_DEFAULT_FMPZ_MOD) return FQ_DEFAULT_FMPZ_MOD; FLINT_UNREACHABLE; } FQ_DEFAULT_INLINE slong fq_default_ctx_degree(const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_ctx_degree(FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_ctx_degree(FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return 1; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return 1; } else { return fq_ctx_degree(FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_ctx_prime(fmpz_t prime, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fmpz_set_ui(prime, fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fmpz_set_ui(prime, fq_nmod_ctx_prime(FQ_DEFAULT_CTX_FQ_NMOD(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_set_ui(prime, FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(prime, fmpz_mod_ctx_modulus(FQ_DEFAULT_CTX_FMPZ_MOD(ctx))); } else { fmpz_set(prime, fq_ctx_prime(FQ_DEFAULT_CTX_FQ(ctx))); } } void fq_default_ctx_modulus(fmpz_mod_poly_t p, const fq_default_ctx_t ctx); FQ_DEFAULT_INLINE void fq_default_ctx_order(fmpz_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fmpz_set_ui(f, fq_zech_ctx_order_ui(FQ_DEFAULT_CTX_FQ_ZECH(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_ctx_order(f, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_set_ui(f, FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(f, fmpz_mod_ctx_modulus(FQ_DEFAULT_CTX_FMPZ_MOD(ctx))); } else { fq_ctx_order(f, FQ_DEFAULT_CTX_FQ(ctx)); } } #ifdef FLINT_HAVE_FILE int fq_default_ctx_fprint(FILE * file, const fq_default_ctx_t ctx); #endif void fq_default_ctx_print(const fq_default_ctx_t ctx); /* Memory management *********************************************************/ FQ_DEFAULT_INLINE void fq_default_init(fq_default_t rop, const fq_default_ctx_t ctx) { gr_init(rop, FQ_DEFAULT_GR_CTX(ctx)); } FQ_DEFAULT_INLINE void fq_default_init2(fq_default_t rop, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_init2(rop->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_init2(rop->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = 0; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_init(rop->fmpz_mod); } else { fq_init2(rop->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_clear(fq_default_t rop, const fq_default_ctx_t ctx) { gr_clear(rop, FQ_DEFAULT_GR_CTX(ctx)); } /* Basic arithmetic **********************************************************/ /* GR_IGNORE(...) because we assume that basic arithmetic is well-implemented */ FQ_DEFAULT_INLINE void fq_default_add(fq_default_t rop, const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) { GR_IGNORE(gr_add(rop, op1, op2, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_sub(fq_default_t rop, const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) { GR_IGNORE(gr_sub(rop, op1, op2, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_sub_one(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { GR_IGNORE(gr_sub_ui(rop, op1, 1, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_neg(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { GR_IGNORE(gr_neg(rop, op1, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_mul(fq_default_t rop, const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) { GR_IGNORE(gr_mul(rop, op1, op2, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_mul_fmpz(fq_default_t rop, const fq_default_t op, const fmpz_t x, const fq_default_ctx_t ctx) { GR_IGNORE(gr_mul_fmpz(rop, op, x, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_mul_si(fq_default_t rop, const fq_default_t op, slong x, const fq_default_ctx_t ctx) { GR_IGNORE(gr_mul_si(rop, op, x, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_mul_ui(fq_default_t rop, const fq_default_t op, ulong x, const fq_default_ctx_t ctx) { GR_IGNORE(gr_mul_ui(rop, op, x, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_sqr(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { GR_IGNORE(gr_sqr(rop, op, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE int fq_default_is_invertible(const fq_default_t op, const fq_default_ctx_t ctx) { truth_t is_inv = gr_is_invertible(op, FQ_DEFAULT_GR_CTX(ctx)); if (is_inv == T_UNKNOWN) flint_throw(FLINT_ERROR, "is_invertible failed"); return (is_inv == T_TRUE); } FQ_DEFAULT_INLINE void fq_default_inv(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { GR_MUST_SUCCEED(gr_inv(rop, op1, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_div(fq_default_t rop, fq_default_t op1, fq_default_t op2, const fq_default_ctx_t ctx) { GR_MUST_SUCCEED(gr_div(rop, op1, op2, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_pow(fq_default_t rop, const fq_default_t op1, const fmpz_t e, const fq_default_ctx_t ctx) { GR_MUST_SUCCEED(gr_pow_fmpz(rop, op1, e, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_pow_ui(fq_default_t rop, const fq_default_t op, const ulong e, const fq_default_ctx_t ctx) { GR_MUST_SUCCEED(gr_pow_ui(rop, op, e, FQ_DEFAULT_GR_CTX(ctx))); } /* Roots *********************************************************************/ FQ_DEFAULT_INLINE int fq_default_is_square(const fq_default_t op, const fq_default_ctx_t ctx) { truth_t is_square = gr_is_square(op, FQ_DEFAULT_GR_CTX(ctx)); if (is_square == T_UNKNOWN) flint_throw(FLINT_ERROR, "sqrt failed"); return (is_square == T_TRUE); } FQ_DEFAULT_INLINE int fq_default_sqrt(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { int status = gr_sqrt(rop, op, FQ_DEFAULT_GR_CTX(ctx)); if (status == GR_UNABLE) flint_throw(FLINT_ERROR, "sqrt failed"); return (status == GR_SUCCESS); } FQ_DEFAULT_INLINE void fq_default_pth_root(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_pth_root(rop->fq_zech, op1->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_pth_root(rop->fq_nmod, op1->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = op1->nmod; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(rop->fmpz_mod, op1->fmpz_mod); } else { fq_pth_root(rop->fq, op1->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Randomisation *************************************************************/ FQ_DEFAULT_INLINE void fq_default_randtest(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_randtest(rop->fq_zech, state, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_randtest(rop->fq_nmod, state, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = n_randint(state, FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_rand(rop->fmpz_mod, state, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_randtest(rop->fq, state, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_randtest_not_zero(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_randtest_not_zero(rop->fq_zech, state, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_randtest_not_zero(rop->fq_nmod, state, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = n_randint(state, FQ_DEFAULT_CTX_NMOD(ctx).n - 1) + 1; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_rand_not_zero(rop->fmpz_mod, state, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_randtest_not_zero(rop->fq, state, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_rand(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_rand(rop->fq_zech, state, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_rand(rop->fq_nmod, state, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = n_randint(state, FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_rand(rop->fmpz_mod, state, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_rand(rop->fq, state, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_rand_not_zero(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_rand_not_zero(rop->fq_zech, state, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_rand_not_zero(rop->fq_nmod, state, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = n_randint(state, FQ_DEFAULT_CTX_NMOD(ctx).n - 1) + 1; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_rand_not_zero(rop->fmpz_mod, state, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_rand_not_zero(rop->fq, state, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Comparison ****************************************************************/ FQ_DEFAULT_INLINE int fq_default_equal(const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) { return gr_equal(op1, op2, FQ_DEFAULT_GR_CTX(ctx)) == T_TRUE; } FQ_DEFAULT_INLINE int fq_default_is_zero(const fq_default_t op, const fq_default_ctx_t ctx) { return gr_is_zero(op, FQ_DEFAULT_GR_CTX(ctx)) == T_TRUE; } FQ_DEFAULT_INLINE int fq_default_is_one(const fq_default_t op, const fq_default_ctx_t ctx) { return gr_is_one(op, FQ_DEFAULT_GR_CTX(ctx)) == T_TRUE; } /* Assignments and conversions ***********************************************/ FQ_DEFAULT_INLINE void fq_default_set(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { GR_IGNORE(gr_set(rop, op, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_set_fmpz(fq_default_t rop, const fmpz_t x, const fq_default_ctx_t ctx) { GR_IGNORE(gr_set_fmpz(rop, x, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_set_ui(fq_default_t rop, const ulong x, const fq_default_ctx_t ctx) { GR_IGNORE(gr_set_ui(rop, x, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_set_si(fq_default_t rop, const slong x, const fq_default_ctx_t ctx) { GR_IGNORE(gr_set_si(rop, x, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_zero(fq_default_t rop, const fq_default_ctx_t ctx) { GR_IGNORE(gr_zero(rop, FQ_DEFAULT_GR_CTX(ctx))); } FQ_DEFAULT_INLINE void fq_default_one(fq_default_t rop, const fq_default_ctx_t ctx) { GR_IGNORE(gr_one(rop, FQ_DEFAULT_GR_CTX(ctx))); } /* todo: should this swap the fq_default_struct? */ FQ_DEFAULT_INLINE void fq_default_swap(fq_default_t op1, fq_default_t op2, const fq_default_ctx_t ctx) { gr_swap(op1, op2, FQ_DEFAULT_GR_CTX(ctx)); } FQ_DEFAULT_INLINE void fq_default_gen(fq_default_t rop, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_gen(rop->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_gen(rop->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = *FQ_DEFAULT_CTX_NMOD_A(ctx); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(rop->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx)); } else { fq_gen(rop->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_get_nmod_poly(nmod_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_get_nmod_poly(poly, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_get_nmod_poly(poly, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_fit_length(poly, 1); poly->length = (op->nmod != 0); poly->coeffs[0] = op->nmod; } else { flint_throw(FLINT_ERROR, "Impossible conversion\n"); } } FQ_DEFAULT_INLINE void fq_default_set_nmod_poly(fq_default_t op, const nmod_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_set_nmod_poly(op->fq_zech, poly, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_set_nmod_poly(op->fq_nmod, poly, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { op->nmod = nmod_poly_evaluate_nmod(poly, *FQ_DEFAULT_CTX_NMOD_A(ctx)); } else { flint_throw(FLINT_ERROR, "Impossible conversion\n"); } } FQ_DEFAULT_INLINE int fq_default_get_fmpz(fmpz_t z, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_get_fmpz(z, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_get_fmpz(z, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_set_ui(z, op->nmod); return 1; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(z, op->fmpz_mod); return 1; } else { return fq_get_fmpz(z, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } void fq_default_get_fmpz_mod_poly(fmpz_mod_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx); void fq_default_set_fmpz_mod_poly(fq_default_t op, const fmpz_mod_poly_t poly, const fq_default_ctx_t ctx); void fq_default_get_fmpz_poly(fmpz_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx); void fq_default_set_fmpz_poly(fq_default_t op, const fmpz_poly_t poly, const fq_default_ctx_t ctx); FQ_DEFAULT_INLINE void fq_default_get_coeff_fmpz(fmpz_t c, fq_default_t op, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { nmod_poly_t p; ulong c0; nmod_poly_init(p, fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx))); fq_zech_get_nmod_poly(p, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); c0 = nmod_poly_get_coeff_ui(p, n); fmpz_set_ui(c, c0); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { ulong c0 = nmod_poly_get_coeff_ui((nmod_poly_struct *) op->fq_nmod, n); fmpz_set_ui(c, c0); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { if (n != 0) fmpz_zero(c); else fmpz_set_ui(c, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { if (n != 0) fmpz_zero(c); else fmpz_set(c, op->fmpz_mod); } else { fmpz_mod_ctx_t mod_ctx; fmpz_mod_ctx_init(mod_ctx, fq_ctx_prime(FQ_DEFAULT_CTX_FQ(ctx))); fmpz_mod_poly_get_coeff_fmpz(c, (fmpz_mod_poly_struct *) op->fq, n, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); } } /* Output ********************************************************************/ #ifdef FLINT_HAVE_FILE int fq_default_fprint(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx); int fq_default_fprint_pretty(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx); #endif void fq_default_print(const fq_default_t op, const fq_default_ctx_t ctx); void fq_default_print_pretty(const fq_default_t op, const fq_default_ctx_t ctx); FQ_DEFAULT_INLINE char * fq_default_get_str(const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_get_str(op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_get_str(op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_t f; char* s; fmpz_init_set_ui(f, op->nmod); s = fmpz_get_str(NULL, 10, f); fmpz_clear(f); return s; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_get_str(NULL, 10, op->fmpz_mod); } else { return fq_get_str(op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE char * fq_default_get_str_pretty(const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_get_str_pretty(op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_get_str_pretty(op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_t f; char* s; fmpz_init_set_ui(f, op->nmod); s = fmpz_get_str(NULL, 10, f); fmpz_clear(f); return s; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_get_str(NULL, 10, op->fmpz_mod); } else { return fq_get_str_pretty(op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Special functions *********************************************************/ FQ_DEFAULT_INLINE void fq_default_trace(fmpz_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_trace(rop, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_trace(rop, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_set_ui(rop, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(rop, op->fmpz_mod); } else { fq_trace(rop, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_frobenius(fq_default_t rop, const fq_default_t op, slong e, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_frobenius(rop->fq_zech, op->fq_zech, e, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_frobenius(rop->fq_nmod, op->fq_nmod, e, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { rop->nmod = op->nmod; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(rop->fmpz_mod, op->fmpz_mod); } else { fq_frobenius(rop->fq, op->fq, e, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_INLINE void fq_default_norm(fmpz_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_norm(rop, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_norm(rop, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_set_ui(rop, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(rop, op->fmpz_mod); } else { fq_norm(rop, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_default/000077500000000000000000000000001461254215100155345ustar00rootroot00000000000000flint-3.1.3/src/fq_default/ctx.c000066400000000000000000000171731461254215100165070ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_default.h" void fq_default_ctx_init_type(fq_default_ctx_t ctx, const fmpz_t p, slong d, const char *var, int type) { int bits = fmpz_bits(p); if (type == FQ_DEFAULT_FQ_ZECH || (type == 0 && d > 1 && bits*d <= 16)) { gr_ctx_init_fq_zech(FQ_DEFAULT_GR_CTX(ctx), *p, d, var); } else if (type == FQ_DEFAULT_FQ_NMOD || (type == 0 && d > 1 && fmpz_abs_fits_ui(p))) { gr_ctx_init_fq_nmod(FQ_DEFAULT_GR_CTX(ctx), fmpz_get_ui(p), d, var); } else if (type == FQ_DEFAULT_NMOD || (type == 0 && d == 1 && fmpz_abs_fits_ui(p))) { gr_ctx_init_nmod(FQ_DEFAULT_GR_CTX(ctx), fmpz_get_ui(p)); NMOD_CTX_A(FQ_DEFAULT_GR_CTX(ctx))[0] = 0; gr_ctx_nmod_set_primality(FQ_DEFAULT_GR_CTX(ctx), T_TRUE); } else if (type == FQ_DEFAULT_FMPZ_MOD || (type == 0 && d == 1)) { gr_ctx_init_fmpz_mod(FQ_DEFAULT_GR_CTX(ctx), p); gr_ctx_fmpz_mod_set_primality(FQ_DEFAULT_GR_CTX(ctx), T_TRUE); } else { gr_ctx_init_fq(FQ_DEFAULT_GR_CTX(ctx), p, d, var); } } int gr_ctx_init_fq_zech_modulus_nmod_poly(gr_ctx_t ctx, const nmod_poly_t modulus, const char * var); int gr_ctx_init_fq_zech_modulus_fmpz_mod_poly(gr_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var); int gr_ctx_init_fq_nmod_modulus_nmod_poly(gr_ctx_t ctx, const nmod_poly_t modulus, const char * var); int gr_ctx_init_fq_nmod_modulus_fmpz_mod_poly(gr_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var); int gr_ctx_init_fq_modulus_nmod_poly(gr_ctx_t ctx, const nmod_poly_t modulus, const char * var); int gr_ctx_init_fq_modulus_fmpz_mod_poly(gr_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var); void fq_default_ctx_init_modulus_type(fq_default_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var, int type) { fmpz const * p = fmpz_mod_ctx_modulus(mod_ctx); int bits = fmpz_bits(p); int d = fmpz_mod_poly_degree(modulus, mod_ctx); if (type == FQ_DEFAULT_FQ_ZECH || (type == 0 && d > 1 && bits*d <= 16)) { if (gr_ctx_init_fq_zech_modulus_fmpz_mod_poly(FQ_DEFAULT_GR_CTX(ctx), modulus, mod_ctx, var) != GR_SUCCESS) fq_default_ctx_init_modulus_type(ctx, modulus, mod_ctx, var, FQ_DEFAULT_FQ_NMOD); } else if (type == FQ_DEFAULT_FQ_NMOD || (type == 0 && d > 1 && fmpz_abs_fits_ui(p))) { GR_MUST_SUCCEED(gr_ctx_init_fq_nmod_modulus_fmpz_mod_poly(FQ_DEFAULT_GR_CTX(ctx), modulus, mod_ctx, var)); } else if (type == FQ_DEFAULT_NMOD || (type == 0 && d == 1 && fmpz_abs_fits_ui(p))) { mp_limb_t c0, c1, a; nmod_t mod; nmod_init(&mod, fmpz_get_ui(p)); c0 = fmpz_get_ui(modulus->coeffs + 0); c1 = fmpz_get_ui(modulus->coeffs + 1); c0 = nmod_neg(c0, mod); a = nmod_div(c0, c1, mod); _gr_ctx_init_nmod(FQ_DEFAULT_GR_CTX(ctx), &mod); NMOD_CTX_A(FQ_DEFAULT_GR_CTX(ctx))[0] = a; gr_ctx_nmod_set_primality(FQ_DEFAULT_GR_CTX(ctx), T_TRUE); } else if (type == FQ_DEFAULT_FMPZ_MOD || (type == 0 && d == 1)) { gr_ctx_init_fmpz_mod(FQ_DEFAULT_GR_CTX(ctx), p); gr_ctx_fmpz_mod_set_primality(FQ_DEFAULT_GR_CTX(ctx), T_TRUE); fmpz_mod_divides(FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx), modulus->coeffs + 0, modulus->coeffs + 1, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_mod_neg(FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx), FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx), FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_set(FMPZ_MOD_CTX_A(FQ_DEFAULT_GR_CTX(ctx)), FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx)); } else { GR_MUST_SUCCEED(gr_ctx_init_fq_modulus_fmpz_mod_poly(FQ_DEFAULT_GR_CTX(ctx), modulus, mod_ctx, var)); } } void fq_default_ctx_init_modulus(fq_default_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var) { fq_default_ctx_init_modulus_type(ctx, modulus, mod_ctx, var, 0); } void fq_default_ctx_init_modulus_nmod_type(fq_default_ctx_t ctx, const nmod_poly_t modulus, const char * var, int type) { ulong p = modulus->mod.n; int bits = FLINT_BIT_COUNT(p); int d = nmod_poly_degree(modulus); if (type == FQ_DEFAULT_FQ_ZECH || (type == 0 && d > 1 && bits*d <= 16)) { if (gr_ctx_init_fq_zech_modulus_nmod_poly(FQ_DEFAULT_GR_CTX(ctx), modulus, var) != GR_SUCCESS) fq_default_ctx_init_modulus_nmod_type(ctx, modulus, var, FQ_DEFAULT_FQ_NMOD); } else if (type == FQ_DEFAULT_FQ_NMOD || (type == 0 && d > 1)) { GR_MUST_SUCCEED(gr_ctx_init_fq_nmod_modulus_nmod_poly(FQ_DEFAULT_GR_CTX(ctx), modulus, var)); } else if (type == FQ_DEFAULT_NMOD || (type == 0 && d == 1)) { mp_limb_t c0, c1, a; nmod_t mod; nmod_init(&mod, p); c0 = modulus->coeffs[0]; c1 = modulus->coeffs[1]; c0 = nmod_neg(c0, mod); a = nmod_div(c0, c1, mod); _gr_ctx_init_nmod(FQ_DEFAULT_GR_CTX(ctx), &mod); NMOD_CTX_A(FQ_DEFAULT_GR_CTX(ctx))[0] = a; gr_ctx_nmod_set_primality(FQ_DEFAULT_GR_CTX(ctx), T_TRUE); } else if (type == FQ_DEFAULT_FMPZ_MOD || (type == 0 && d == 1)) { fmpz_t pp; mp_limb_t c0, c1, a; c0 = modulus->coeffs[0]; c1 = modulus->coeffs[1]; c0 = nmod_neg(c0, modulus->mod); a = nmod_div(c0, c1, modulus->mod); fmpz_init_set_ui(pp, p); gr_ctx_init_fmpz_mod(FQ_DEFAULT_GR_CTX(ctx), pp); fmpz_clear(pp); gr_ctx_fmpz_mod_set_primality(FQ_DEFAULT_GR_CTX(ctx), T_TRUE); fmpz_set_ui(FMPZ_MOD_CTX_A(FQ_DEFAULT_GR_CTX(ctx)), a); } else { GR_MUST_SUCCEED(gr_ctx_init_fq_modulus_nmod_poly(FQ_DEFAULT_GR_CTX(ctx), modulus, var)); } } void fq_default_ctx_init_modulus_nmod(fq_default_ctx_t ctx, const nmod_poly_t modulus, const char * var) { fq_default_ctx_init_modulus_nmod_type(ctx, modulus, var, 0); } void fq_default_ctx_modulus(fmpz_mod_poly_t p, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { nmod_poly_struct const * mod = fq_zech_ctx_modulus(FQ_DEFAULT_CTX_FQ_ZECH(ctx)); fmpz_mod_poly_set_nmod_poly(p, mod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { nmod_poly_struct const * mod = fq_nmod_ctx_modulus(FQ_DEFAULT_CTX_FQ_NMOD(ctx)); fmpz_mod_poly_set_nmod_poly(p, mod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { _fmpz_mod_poly_fit_length(p, 2); _fmpz_mod_poly_set_length(p, 2); fmpz_set_ui(p->coeffs + 0, nmod_neg(FQ_DEFAULT_CTX_NMOD_A(ctx)[0], FQ_DEFAULT_CTX_NMOD(ctx))); fmpz_one(p->coeffs + 1); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { _fmpz_mod_poly_fit_length(p, 2); _fmpz_mod_poly_set_length(p, 2); fmpz_mod_neg(p->coeffs + 0, FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx), FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_one(p->coeffs + 1); } else { fmpz_mod_ctx_struct const * mod = FQ_DEFAULT_CTX_FQ(ctx)->ctxp; fmpz_mod_poly_set(p, FQ_DEFAULT_CTX_FQ(ctx)->modulus, mod); } } flint-3.1.3/src/fq_default/get_set.c000066400000000000000000000141241461254215100173340ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq_default.h" void fq_default_get_fmpz_mod_poly(fmpz_mod_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { nmod_poly_t p; ulong mod = fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx)); nmod_poly_init(p, mod); fq_zech_get_nmod_poly(p, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); fmpz_mod_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { nmod_poly_t p; ulong mod = fq_nmod_ctx_prime(FQ_DEFAULT_CTX_FQ_NMOD(ctx)); nmod_poly_init(p, mod); fq_nmod_get_nmod_poly(p, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); fmpz_mod_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { _fmpz_mod_poly_fit_length(poly, 1); fmpz_set_ui(poly->coeffs + 0, op->nmod); _fmpz_mod_poly_set_length(poly, op->nmod != 0); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { _fmpz_mod_poly_fit_length(poly, 1); fmpz_set(poly->coeffs + 0, op->fmpz_mod); _fmpz_mod_poly_set_length(poly, !fmpz_is_zero(op->fmpz_mod)); } else { fq_get_fmpz_mod_poly(poly, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } void fq_default_get_fmpz_poly(fmpz_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { nmod_poly_t p; ulong mod = fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx)); nmod_poly_init(p, mod); fq_zech_get_nmod_poly(p, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); fmpz_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { nmod_poly_t p; ulong mod = fq_nmod_ctx_prime(FQ_DEFAULT_CTX_FQ_NMOD(ctx)); nmod_poly_init(p, mod); fq_nmod_get_nmod_poly(p, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); fmpz_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_poly_fit_length(poly, 1); fmpz_set_ui(poly->coeffs + 0, op->nmod); _fmpz_poly_set_length(poly, op->nmod != 0); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_poly_fit_length(poly, 1); fmpz_set(poly->coeffs + 0, op->fmpz_mod); _fmpz_poly_set_length(poly, !fmpz_is_zero(op->fmpz_mod)); } else { fq_get_fmpz_poly(poly, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } void fq_default_set_fmpz_mod_poly(fq_default_t op, const fmpz_mod_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { nmod_poly_t p; ulong mod = fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx)); nmod_poly_init(p, mod); fmpz_mod_poly_get_nmod_poly(p, poly); fq_zech_set_nmod_poly(op->fq_zech, p, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { nmod_poly_t p; ulong mod = fq_nmod_ctx_prime(FQ_DEFAULT_CTX_FQ_NMOD(ctx)); nmod_poly_init(p, mod); fmpz_mod_poly_get_nmod_poly(p, poly); fq_nmod_set_nmod_poly(op->fq_nmod, p, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_t p; nmod_poly_init_mod(p, FQ_DEFAULT_CTX_NMOD(ctx)); fmpz_mod_poly_get_nmod_poly(p, poly); op->nmod = nmod_poly_evaluate_nmod(p, *FQ_DEFAULT_CTX_NMOD_A(ctx)); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_evaluate_fmpz(op->fmpz_mod, poly, FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx), FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_set_fmpz_mod_poly(op->fq, poly, FQ_DEFAULT_CTX_FQ(ctx)); } } void fq_default_set_fmpz_poly(fq_default_t op, const fmpz_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { nmod_poly_t p; ulong mod = fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx)); nmod_poly_init(p, mod); fmpz_poly_get_nmod_poly(p, poly); fq_zech_set_nmod_poly(op->fq_zech, p, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { nmod_poly_t p; ulong mod = fq_nmod_ctx_prime(FQ_DEFAULT_CTX_FQ_NMOD(ctx)); nmod_poly_init(p, mod); fmpz_poly_get_nmod_poly(p, poly); fq_nmod_set_nmod_poly(op->fq_nmod, p, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_t p; nmod_poly_init_mod(p, FQ_DEFAULT_CTX_NMOD(ctx)); fmpz_poly_get_nmod_poly(p, poly); op->nmod = nmod_poly_evaluate_nmod(p, *FQ_DEFAULT_CTX_NMOD_A(ctx)); nmod_poly_clear(p); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_t p; fmpz_mod_poly_init(p, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_mod_poly_set_fmpz_poly(p, poly, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_mod_poly_evaluate_fmpz(op->fmpz_mod, p, FQ_DEFAULT_CTX_FMPZ_MOD_A(ctx), FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_mod_poly_clear(p, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_set_fmpz_poly(op->fq, poly, FQ_DEFAULT_CTX_FQ(ctx)); } } flint-3.1.3/src/fq_default/inlines.c000066400000000000000000000006601461254215100173430ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_INLINES_C #include "fq_default.h" flint-3.1.3/src/fq_default/io.c000066400000000000000000000062121461254215100163100ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fq_default.h" #include "gr.h" /* printing *******************************************************************/ int fq_default_ctx_fprint(FILE * file, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_ctx_fprint(file, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_ctx_fprint(file, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return flint_fprintf(file, "p = %wu\n", FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { int z = flint_fprintf(file, "p = "); if (z <= 0) return z; z = fmpz_fprint(file, fmpz_mod_ctx_modulus(FQ_DEFAULT_CTX_FMPZ_MOD(ctx))); if (z <= 0) return z; return flint_fprintf(file, "\n"); } else { return fq_ctx_fprint(file, FQ_DEFAULT_CTX_FQ(ctx)); } } int fq_default_fprint(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_fprint(file, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_fprint(file, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return flint_fprintf(file, "%wu", op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_fprint(file, op->fmpz_mod); } else { return fq_fprint(file, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } int fq_default_fprint_pretty(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_fprint_pretty(file, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_fprint_pretty(file, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return flint_fprintf(file, "%wu", op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_fprint(file, op->fmpz_mod); } else { return fq_fprint_pretty(file, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } void fq_default_ctx_print(const fq_default_ctx_t ctx) { fq_default_ctx_fprint(stdout, ctx); } void fq_default_print(const fq_default_t op, const fq_default_ctx_t ctx) { fq_default_fprint(stdout, op, ctx); } void fq_default_print_pretty(const fq_default_t op, const fq_default_ctx_t ctx) { fq_default_fprint_pretty(stdout, op, ctx); } flint-3.1.3/src/fq_default/test/000077500000000000000000000000001461254215100165135ustar00rootroot00000000000000flint-3.1.3/src/fq_default/test/main.c000066400000000000000000000025371461254215100176120ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-ctx_init.c" #include "t-ctx_init_modulus.c" #include "t-ctx_init_modulus_nmod.c" #include "t-ctx_modulus.c" #include "t-get_set_fmpz.c" #include "t-get_set_fmpz_mod_poly.c" #include "t-get_set_fmpz_poly.c" #include "t-init.c" #include "t-inlines.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_default_ctx_init), TEST_FUNCTION(fq_default_ctx_init_modulus), TEST_FUNCTION(fq_default_ctx_init_modulus_nmod), TEST_FUNCTION(fq_default_ctx_modulus), TEST_FUNCTION(fq_default_get_set_fmpz), TEST_FUNCTION(fq_default_get_set_fmpz_mod_poly), TEST_FUNCTION(fq_default_get_set_fmpz_poly), TEST_FUNCTION(fq_default_init), TEST_FUNCTION(fq_default_inlines) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_default/test/t-ctx_init.c000066400000000000000000000164761461254215100207570ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* NOTE: Here we check that we get the contexts we expect. */ #include "test_helpers.h" #include "fq_default.h" static const char str_fq_zech[] = "fq_zech"; static const char str_fq_nmod[] = "fq_nmod"; static const char str_fq[] = "fq"; static const char str_nmod[] = "nmod"; static const char str_fmpz_mod[] = "fmpz_mod"; static const char * get_str(int type) { switch (type) { case FQ_DEFAULT_FQ_ZECH: return str_fq_zech; case FQ_DEFAULT_FQ_NMOD: return str_fq_nmod; case FQ_DEFAULT_FQ: return str_fq; case FQ_DEFAULT_NMOD: return str_nmod; case FQ_DEFAULT_FMPZ_MOD: return str_fmpz_mod; default: FLINT_UNREACHABLE; } } static slong rand_deg_p_fq_zech(flint_rand_t state, fmpz_t p) { /* d > 1 and d * bits(p) <= 16 */ /* 2 <= bits(p) <= 16 / d */ slong d = 2 + n_randint(state, 7); /* in {2, ..., 8} */ flint_bitcnt_t bits = 2 + n_randint(state, 16 / d - 1); fmpz_randprime(p, state, bits, 0); return d; } static slong rand_deg_p_fq_nmod(flint_rand_t state, fmpz_t p) { /* d > 1 and fits_ui(p) and d * bits(p) > 16 */ slong d = 2 + n_randint(state, 20); flint_bitcnt_t bits = FLINT_MAX((16 + d - 1) / d + 1, 2) + n_randint(state, FLINT_BITS - FLINT_MAX((16 + d - 1) / d + 1, 2) + 1); fmpz_randprime(p, state, bits, 0); return d; } static slong rand_deg_p_nmod(flint_rand_t state, fmpz_t p) { /* d == 1 and fits_ui(p) */ slong d = 1; flint_bitcnt_t bits = 2 + n_randint(state, FLINT_BITS - 1); fmpz_randprime(p, state, bits, 0); return d; } static slong rand_deg_p_fmpz_mod(flint_rand_t state, fmpz_t p) { /* d == 1 and not fits_ui(p) */ slong d = 1; flint_bitcnt_t bits = FLINT_BITS + 1 + n_randint(state, 64); fmpz_randprime(p, state, bits, 0); return d; } static slong rand_deg_p_fq(flint_rand_t state, fmpz_t p) { /* d > 1 and not fits_ui(p) */ slong d = 2 + n_randint(state, 20); flint_bitcnt_t bits = FLINT_BITS + 1 + n_randint(state, 64); fmpz_randprime(p, state, bits, 0); return d; } #define TYPE_MIN FQ_DEFAULT_FQ_ZECH #define TYPE_MAX FQ_DEFAULT_FMPZ_MOD TEST_FUNCTION_START(fq_default_ctx_init, state) { slong ix; int result; fq_default_ctx_t ctx; /* fq_default_ctx_init_type */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { int type; fmpz_t p; slong d; char var[] = "x"; type = TYPE_MIN + n_randint(state, TYPE_MAX + TYPE_MIN - 1); fmpz_init(p); switch (type) { case FQ_DEFAULT_FQ_ZECH: d = rand_deg_p_fq_zech(state, p); break; case FQ_DEFAULT_FQ_NMOD: d = rand_deg_p_fq_nmod(state, p); break; case FQ_DEFAULT_FQ: d = rand_deg_p_fq(state, p); break; case FQ_DEFAULT_NMOD: d = rand_deg_p_nmod(state, p); break; case FQ_DEFAULT_FMPZ_MOD: d = rand_deg_p_fmpz_mod(state, p); break; default: FLINT_UNREACHABLE; } fq_default_ctx_init_type(ctx, p, d, var, 0); result = (fq_default_ctx_type(ctx) == type); if (!result) TEST_FUNCTION_FAIL( "fq_default_ctx_init_type:\n" "ix = %wd\n" "p = %{fmpz}\n" "d = %{slong}\n" "Expected type: %s\n" "Got type: %s\n", ix, p, d, get_str(type), get_str(fq_default_ctx_type(ctx))); fq_default_ctx_clear(ctx); fmpz_clear(p); } /* fq_default_ctx_init_modulus */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { int type; fmpz_mod_poly_t modulus; fmpz_mod_ctx_t mod_ctx; fmpz_t p; slong d; char var[] = "x"; type = TYPE_MIN + n_randint(state, TYPE_MAX + TYPE_MIN - 1); fmpz_init(p); /* Get degree and prime */ switch (type) { case FQ_DEFAULT_FQ_ZECH: d = rand_deg_p_fq_zech(state, p); break; case FQ_DEFAULT_FQ_NMOD: d = rand_deg_p_fq_nmod(state, p); break; case FQ_DEFAULT_FQ: d = rand_deg_p_fq(state, p); break; case FQ_DEFAULT_NMOD: d = rand_deg_p_nmod(state, p); break; case FQ_DEFAULT_FMPZ_MOD: d = rand_deg_p_fmpz_mod(state, p); break; default: FLINT_UNREACHABLE; } fmpz_mod_ctx_init(mod_ctx, p); fmpz_mod_poly_init(modulus, mod_ctx); if (type != FQ_DEFAULT_FQ_ZECH) fmpz_mod_poly_randtest_monic_irreducible(modulus, state, d + 1, mod_ctx); else fmpz_mod_poly_randtest_monic_primitive(modulus, state, d + 1, mod_ctx); fq_default_ctx_init_modulus(ctx, modulus, mod_ctx, var); result = (fq_default_ctx_type(ctx) == type); if (!result) TEST_FUNCTION_FAIL( "fq_default_ctx_init_modulus:\n" "ix = %wd\n" "p = %{fmpz}\n" "d = %{slong}\n" "Expected type: %s\n" "Got type: %s\n", ix, p, d, get_str(type), get_str(fq_default_ctx_type(ctx))); fq_default_ctx_clear(ctx); fmpz_mod_poly_clear(modulus, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fmpz_clear(p); } /* fq_default_ctx_init_modulus_nmod */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { int type; nmod_poly_t modulus; nmod_t mod_ctx; fmpz_t p; ulong px; slong d; char var[] = "x"; type = TYPE_MIN + n_randint(state, TYPE_MAX + TYPE_MIN - 1); fmpz_init(p); /* Get degree and prime */ switch (type) { case FQ_DEFAULT_FQ_ZECH: d = rand_deg_p_fq_zech(state, p); break; case FQ_DEFAULT_FQ_NMOD: d = rand_deg_p_fq_nmod(state, p); break; case FQ_DEFAULT_FQ: fmpz_clear(p); continue; case FQ_DEFAULT_NMOD: d = rand_deg_p_nmod(state, p); break; case FQ_DEFAULT_FMPZ_MOD: fmpz_clear(p); continue; default: FLINT_UNREACHABLE; } px = fmpz_get_ui(p); fmpz_clear(p); nmod_init(&mod_ctx, px); nmod_poly_init_mod(modulus, mod_ctx); if (type != FQ_DEFAULT_FQ_ZECH) nmod_poly_randtest_monic_irreducible(modulus, state, d + 1); else nmod_poly_randtest_monic_primitive(modulus, state, d + 1); fq_default_ctx_init_modulus_nmod(ctx, modulus, var); result = (fq_default_ctx_type(ctx) == type); if (!result) TEST_FUNCTION_FAIL( "fq_default_ctx_init_modulus_nmod:\n" "ix = %wd\n" "p = %{fmpz}\n" "d = %{slong}\n" "Expected type: %s\n" "Got type: %s\n", ix, p, d, get_str(type), get_str(fq_default_ctx_type(ctx))); fq_default_ctx_clear(ctx); nmod_poly_clear(modulus); } TEST_FUNCTION_END(state); } #undef TYPE_MIN #undef TYPE_MAX flint-3.1.3/src/fq_default/test/t-ctx_init_modulus.c000066400000000000000000000060131461254215100225110ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_ctx_init_modulus, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq; fmpz_t p; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod; fmpz_init(p); fmpz_set_ui(p, 3); fmpz_mod_ctx_init(mod_ctx, p); fmpz_mod_poly_init(mod, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 0, 1, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 1, 2, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 3, 1, mod_ctx); fq_default_ctx_init_modulus(ctx, mod, mod_ctx, "x"); fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); fmpz_mod_poly_clear(mod, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fmpz_clear(p); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq; fmpz_t p; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod; fmpz_init(p); fmpz_set_ui(p, 3); fmpz_mod_ctx_init(mod_ctx, p); fmpz_mod_poly_init(mod, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 0, 1, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 1, 2, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 3, 1, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 16, 1, mod_ctx); fq_default_ctx_init_modulus(ctx, mod, mod_ctx, "x"); fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); fmpz_mod_poly_clear(mod, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fmpz_clear(p); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq; fmpz_t p; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod; fmpz_init(p); fmpz_set_str(p, "73786976294838206473", 10); fmpz_mod_ctx_init(mod_ctx, p); fmpz_mod_poly_init(mod, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 0, 1, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 1, 2, mod_ctx); fmpz_mod_poly_set_coeff_si(mod, 3, 1, mod_ctx); fq_default_ctx_init_modulus(ctx, mod, mod_ctx, "x"); fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); fmpz_mod_poly_clear(mod, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default/test/t-ctx_init_modulus_nmod.c000066400000000000000000000110071461254215100235250ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_ctx_init_modulus_nmod, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq; ulong p; slong len; nmod_poly_t mod; p = 3; nmod_poly_init(mod, p); len = n_randint(state, 16) + 2; nmod_poly_randtest_irreducible(mod, state, len); fq_default_ctx_init_modulus_nmod(ctx, mod, "x"); fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq; ulong p; slong len; nmod_poly_t mod; p = 3; nmod_poly_init(mod, p); len = n_randint(state, 16) + 2; nmod_poly_randtest_irreducible(mod, state, len); fq_default_ctx_init_modulus_nmod_type(ctx, mod, "x", 3); fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); } { fq_default_ctx_t ctx; fq_default_t fq; ulong p; int result; nmod_poly_t mod; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod2, mod3; fmpz_t pp; p = 3; nmod_poly_init(mod, p); nmod_poly_fit_length(mod, 2); nmod_poly_set_coeff_ui(mod, 0, 2); nmod_poly_set_coeff_ui(mod, 1, 1); fq_default_ctx_init_modulus_nmod(ctx, mod, "x"); fmpz_init(pp); fmpz_set_ui(pp, 3); fmpz_mod_ctx_init(mod_ctx, pp); fmpz_mod_poly_init(mod2, mod_ctx); fmpz_mod_poly_init(mod3, mod_ctx); fmpz_mod_poly_set_coeff_ui(mod3, 0, 2, mod_ctx); fmpz_mod_poly_set_coeff_ui(mod3, 1, 1, mod_ctx); fq_default_ctx_modulus(mod2, ctx); result = fmpz_mod_poly_equal(mod2, mod3, mod_ctx); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(mod2, mod_ctx); flint_printf("\n"); fmpz_mod_poly_print(mod3, mod_ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); fmpz_mod_poly_clear(mod2, mod_ctx); fmpz_mod_poly_clear(mod3, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fmpz_clear(pp); nmod_poly_clear(mod); } { fq_default_ctx_t ctx; fq_default_t fq; ulong p; int result; nmod_poly_t mod; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod2, mod3; fmpz_t pp; p = 3; nmod_poly_init(mod, p); nmod_poly_fit_length(mod, 2); nmod_poly_set_coeff_ui(mod, 0, 2); nmod_poly_set_coeff_ui(mod, 1, 1); fq_default_ctx_init_modulus_nmod_type(ctx, mod, "x", FQ_DEFAULT_FMPZ_MOD); FLINT_TEST(fq_default_ctx_type(ctx) == FQ_DEFAULT_FMPZ_MOD); fmpz_init(pp); fmpz_set_ui(pp, 3); fmpz_mod_ctx_init(mod_ctx, pp); fmpz_mod_poly_init(mod2, mod_ctx); fmpz_mod_poly_init(mod3, mod_ctx); fmpz_mod_poly_set_coeff_ui(mod3, 0, 2, mod_ctx); fmpz_mod_poly_set_coeff_ui(mod3, 1, 1, mod_ctx); fq_default_ctx_modulus(mod2, ctx); result = fmpz_mod_poly_equal(mod2, mod3, mod_ctx); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(mod2, mod_ctx); flint_printf("\n"); fmpz_mod_poly_print(mod3, mod_ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); fmpz_mod_poly_clear(mod2, mod_ctx); fmpz_mod_poly_clear(mod3, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fmpz_clear(pp); nmod_poly_clear(mod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default/test/t-ctx_modulus.c000066400000000000000000000057031461254215100214730ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_ctx_modulus, state) { int i, result; /* fq_zech range */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fmpz_mod_ctx_init(mod_ctx, p); fmpz_mod_poly_init(mod, mod_ctx); fq_default_ctx_modulus(mod, ctx); result = (fmpz_mod_poly_length(mod, mod_ctx) == 4); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(mod, mod_ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(mod, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fq_default_ctx_clear(ctx); } /* fq_nmod range */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 16, "x"); fmpz_mod_ctx_init(mod_ctx, p); fmpz_mod_poly_init(mod, mod_ctx); fq_default_ctx_modulus(mod, ctx); result = (fmpz_mod_poly_length(mod, mod_ctx) == 17); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(mod, mod_ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(mod, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } /* fq range */ for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fmpz_mod_ctx_t mod_ctx; fmpz_mod_poly_t mod; fmpz_t p; fmpz_init(p); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fmpz_mod_ctx_init(mod_ctx, p); fmpz_mod_poly_init(mod, mod_ctx); fq_default_ctx_modulus(mod, ctx); result = (fmpz_mod_poly_length(mod, mod_ctx) == 2); if (!result) { flint_printf("FAIL:\n"); fmpz_mod_poly_print(mod, mod_ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(mod, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default/test/t-get_set_fmpz.c000066400000000000000000000033051461254215100216070ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_get_set_fmpz, state) { slong i, j; for (i = 0; i < 30*flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t a, b; fmpz_t s, t, p; slong d; fmpz_init(p); fmpz_randprime(p, state, n_randint(state, 2) ? 60 : 120, 1); d = n_randint(state, 4) + 1, fq_default_ctx_init(ctx, p, d, "a"); fq_default_init(a, ctx); fq_default_init(b, ctx); fmpz_init(s); fmpz_init(t); for (j = 0; j < 30*flint_test_multiplier(); j++) { fq_default_randtest(a, state, ctx); fq_default_randtest(b, state, ctx); fmpz_randbits(t, state, 100); fq_default_set_fmpz(a, t, ctx); FLINT_TEST(fq_default_get_fmpz(s, a, ctx)); fmpz_sub(t, t, s); FLINT_TEST(fmpz_divisible(t, p)); if (fq_default_get_fmpz(t, a, ctx)) { fq_default_set_fmpz(b, t, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); } } fmpz_clear(s); fmpz_clear(t); fq_default_clear(a, ctx); fq_default_clear(b, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default/test/t-get_set_fmpz_mod_poly.c000066400000000000000000000101441461254215100235100ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_get_set_fmpz_mod_poly, state) { int i, result; /* fq_zech range */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq1, fq2; fmpz_mod_ctx_t fctx; fmpz_mod_poly_t fmod; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fq_default_init(fq1, ctx); fq_default_init(fq2, ctx); fmpz_mod_ctx_init(fctx, p); fmpz_mod_poly_init(fmod, fctx); fq_default_randtest(fq1, state, ctx); fq_default_get_fmpz_mod_poly(fmod, fq1, ctx); fq_default_set_fmpz_mod_poly(fq2, fmod, ctx); result = (fq_default_equal(fq1, fq2, ctx)); if (!result) { flint_printf("FAIL:\n"); fq_default_print(fq1, ctx); flint_printf("\n\n"); fq_default_print(fq2, ctx); flint_printf("\n\n"); fmpz_mod_poly_print(fmod, fctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(fmod, fctx); fmpz_mod_ctx_clear(fctx); fq_default_clear(fq1, ctx); fq_default_clear(fq2, ctx); fq_default_ctx_clear(ctx); } /* fq_nmod range */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq1, fq2; fmpz_mod_ctx_t fctx; fmpz_mod_poly_t fmod; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 16, "x"); fq_default_init(fq1, ctx); fq_default_init(fq2, ctx); fmpz_mod_ctx_init(fctx, p); fmpz_mod_poly_init(fmod, fctx); fq_default_randtest(fq1, state, ctx); fq_default_get_fmpz_mod_poly(fmod, fq1, ctx); fq_default_set_fmpz_mod_poly(fq2, fmod, ctx); result = (fq_default_equal(fq1, fq2, ctx)); if (!result) { flint_printf("FAIL:\n"); fq_default_print(fq1, ctx); flint_printf("\n\n"); fq_default_print(fq2, ctx); flint_printf("\n\n"); fmpz_mod_poly_print(fmod, fctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(fmod, fctx); fmpz_mod_ctx_clear(fctx); fq_default_clear(fq1, ctx); fq_default_clear(fq2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } /* fq range */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq1, fq2; fmpz_mod_ctx_t fctx; fmpz_mod_poly_t fmod; fmpz_t p; fmpz_init(p); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fq_default_init(fq1, ctx); fq_default_init(fq2, ctx); fmpz_mod_ctx_init(fctx, p); fmpz_mod_poly_init(fmod, fctx); fq_default_randtest(fq1, state, ctx); fq_default_get_fmpz_mod_poly(fmod, fq1, ctx); fq_default_set_fmpz_mod_poly(fq2, fmod, ctx); result = (fq_default_equal(fq1, fq2, ctx)); if (!result) { flint_printf("FAIL:\n"); fq_default_print(fq1, ctx); flint_printf("\n\n"); fq_default_print(fq2, ctx); flint_printf("\n\n"); fmpz_mod_poly_print(fmod, fctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_mod_poly_clear(fmod, fctx); fmpz_mod_ctx_clear(fctx); fq_default_clear(fq1, ctx); fq_default_clear(fq2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default/test/t-get_set_fmpz_poly.c000066400000000000000000000072321461254215100226550ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_get_set_fmpz_poly, state) { int i, result; /* fq_zech range */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq1, fq2; fmpz_poly_t f; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fq_default_init(fq1, ctx); fq_default_init(fq2, ctx); fmpz_poly_init(f); fq_default_randtest(fq1, state, ctx); fq_default_get_fmpz_poly(f, fq1, ctx); fq_default_set_fmpz_poly(fq2, f, ctx); result = (fq_default_equal(fq1, fq2, ctx)); if (!result) { flint_printf("FAIL:\n"); fq_default_print(fq1, ctx); flint_printf("\n\n"); fq_default_print(fq2, ctx); flint_printf("\n\n"); fmpz_poly_print(f); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fq_default_clear(fq1, ctx); fq_default_clear(fq2, ctx); fq_default_ctx_clear(ctx); } /* fq_nmod range */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq1, fq2; fmpz_poly_t f; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 16, "x"); fq_default_init(fq1, ctx); fq_default_init(fq2, ctx); fmpz_poly_init(f); fq_default_randtest(fq1, state, ctx); fq_default_get_fmpz_poly(f, fq1, ctx); fq_default_set_fmpz_poly(fq2, f, ctx); result = (fq_default_equal(fq1, fq2, ctx)); if (!result) { flint_printf("FAIL:\n"); fq_default_print(fq1, ctx); flint_printf("\n\n"); fq_default_print(fq2, ctx); flint_printf("\n\n"); fmpz_poly_print(f); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fq_default_clear(fq1, ctx); fq_default_clear(fq2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } /* fq range */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq1, fq2; fmpz_poly_t f; fmpz_t p; fmpz_init(p); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fq_default_init(fq1, ctx); fq_default_init(fq2, ctx); fmpz_poly_init(f); fq_default_randtest(fq1, state, ctx); fq_default_get_fmpz_poly(f, fq1, ctx); fq_default_set_fmpz_poly(fq2, f, ctx); result = (fq_default_equal(fq1, fq2, ctx)); if (!result) { flint_printf("FAIL:\n"); fq_default_print(fq1, ctx); flint_printf("\n\n"); fq_default_print(fq2, ctx); flint_printf("\n\n"); fmpz_poly_print(f); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(f); fq_default_clear(fq1, ctx); fq_default_clear(fq2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default/test/t-init.c000066400000000000000000000054501461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_init, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t fq; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fq_default_init(fq, ctx); fq_default_clear(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_ctx_clear(ctx); fq_default_ctx_init(ctx, p, 16, "x"); fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fq_default_init(fq, ctx); fq_default_randtest(fq, state, ctx); fq_default_clear(fq, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fq_default_ctx_t ctx; fq_default_t x, y; int type = 1 + n_randint(state, 5); fmpz_init(p); fmpz_set_ui(p, 7); fq_default_ctx_init_type(ctx, p, 1, "x", type); FLINT_TEST(fq_default_ctx_type(ctx) == type); fq_default_init(x, ctx); fq_default_init(y, ctx); fq_default_randtest(x, state, ctx); fq_default_sqr(y, x, ctx); if (type == FQ_DEFAULT_FQ) fq_sqr((fq_struct *) x, (const fq_struct *) x, (const fq_ctx_struct *) fq_default_ctx_inner(ctx)); else if (type == FQ_DEFAULT_FQ_NMOD) fq_nmod_sqr((fq_nmod_struct *) x, (const fq_nmod_struct *) x, (const fq_nmod_ctx_struct *) fq_default_ctx_inner(ctx)); else if (type == FQ_DEFAULT_FQ_ZECH) fq_zech_sqr((fq_zech_struct *) x, (const fq_zech_struct *) x, (const fq_zech_ctx_struct *) fq_default_ctx_inner(ctx)); else if (type == FQ_DEFAULT_FMPZ_MOD) fmpz_mod_mul((fmpz *) x, (const fmpz *) x, (const fmpz *) x, (const fmpz_mod_ctx_struct *) fq_default_ctx_inner(ctx)); else ((ulong *) x)[0] = nmod_mul(((ulong *) x)[0], ((ulong *) x)[0], *((const nmod_t *) fq_default_ctx_inner(ctx))); FLINT_TEST(fq_default_equal(x, y, ctx)); fq_default_clear(x, ctx); fq_default_clear(y, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default/test/t-inlines.c000066400000000000000000000067621461254215100205740ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default.h" TEST_FUNCTION_START(fq_default_inlines, state) { slong i; for (i = 0; i < 10*flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_t a, b, c; fmpz_t p, p1, o, o1; slong d; fmpz_init(p); fmpz_init(p1); fmpz_init(o); fmpz_init(o1); fmpz_randprime(p, state, n_randint(state, 2) ? 60 : 120, 1); d = n_randint(state, 4) + 1, fq_default_ctx_init(ctx, p, d, "a"); fq_default_init(a, ctx); fq_default_init(b, ctx); fq_default_init(c, ctx); FLINT_TEST(fq_default_ctx_degree(ctx) == d); fq_default_ctx_prime(p1, ctx); FLINT_TEST(fmpz_equal(p1, p)); fq_default_ctx_order(o, ctx); fmpz_pow_ui(o1, p, d); FLINT_TEST(fmpz_equal(o1, o)); fq_default_randtest(a, state, ctx); fq_default_randtest(b, state, ctx); fq_default_randtest(c, state, ctx); FLINT_TEST(!!fq_default_is_zero(a, ctx) == !fq_default_is_invertible(a, ctx)); fq_default_add(a, b, c, ctx); fq_default_sub(a, a, c, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); fq_default_sub_one(a, c, ctx); fq_default_one(b, ctx); fq_default_sub(b, c, b, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); fq_default_randtest(a, state, ctx); fq_default_randtest(b, state, ctx); fq_default_randtest_not_zero(c, state, ctx); fq_default_inv(a, c, ctx); fq_default_mul(a, a, c, ctx); FLINT_TEST(fq_default_is_one(a, ctx)); fq_default_div(a, b, c, ctx); fq_default_mul(a, a, c, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); fq_default_neg(a, c, ctx); fq_default_mul_si(b, c, -1, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); fq_default_add(a, c, c, ctx); fq_default_mul_ui(b, c, 2, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); fq_default_mul_fmpz(a, c, p, ctx); FLINT_TEST(fq_default_is_zero(a, ctx)); fq_default_pow_ui(c, b, 2, ctx); fq_default_sqr(a, b, ctx); FLINT_TEST(fq_default_equal(a, c, ctx)); fq_default_pow(a, b, o, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); fq_default_mul(a, b, b, ctx); fq_default_sqr(c, b, ctx); FLINT_TEST(fq_default_equal(a, c, ctx)); fq_default_randtest(a, state, ctx); fq_default_randtest(b, state, ctx); fq_default_randtest(c, state, ctx); fq_default_pth_root(a, b, ctx); fq_default_pow(a, a, p, ctx); FLINT_TEST(fq_default_equal(a, b, ctx)); fq_default_sqr(a, b, ctx); FLINT_TEST(fq_default_is_square(a, ctx)); FLINT_TEST(fq_default_sqrt(c, a, ctx)); fq_default_sqr(c, c, ctx); FLINT_TEST(fq_default_equal(c, a, ctx)); fq_default_clear(a, ctx); fq_default_clear(b, ctx); fq_default_clear(c, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); fmpz_clear(p1); fmpz_clear(o); fmpz_clear(o1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_mat.h000066400000000000000000001304271461254215100165550ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_DEFAULT_MAT_H #define FQ_DEFAULT_MAT_H #ifdef FQ_DEFAULT_MAT_INLINES_C #define FQ_DEFAULT_MAT_INLINE #else #define FQ_DEFAULT_MAT_INLINE static inline #endif #include "nmod_mat.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fq_mat.h" #include "fq_nmod_mat.h" #include "fq_zech_mat.h" #include "fq_default.h" #ifdef __cplusplus extern "C" { #endif typedef union fq_default_mat_struct { fq_mat_t fq; fq_nmod_mat_t fq_nmod; fq_zech_mat_t fq_zech; nmod_mat_t nmod; fmpz_mod_mat_t fmpz_mod; } fq_default_mat_struct; typedef fq_default_mat_struct fq_default_mat_t[1]; /* Memory management ********************************************************/ FQ_DEFAULT_MAT_INLINE void fq_default_mat_init(fq_default_mat_t mat, slong rows, slong cols, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_init(mat->fq_zech, rows, cols, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_init(mat->fq_nmod, rows, cols, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_init(mat->nmod, rows, cols, FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_init(mat->fmpz_mod, rows, cols, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_init(mat->fq, rows, cols, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_init_set(fq_default_mat_t mat, const fq_default_mat_t src, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_init_set(mat->fq_zech, src->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_init_set(mat->fq_nmod, src->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_init_set(mat->nmod, src->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_init_set(mat->fmpz_mod, src->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_init_set(mat->fq, src->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_swap(fq_default_mat_t mat1, fq_default_mat_t mat2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_swap(mat1->fq_zech, mat2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_swap(mat1->fq_nmod, mat2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_swap(mat1->nmod, mat2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_swap(mat1->fmpz_mod, mat2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_swap(mat1->fq, mat2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_set(fq_default_mat_t mat1, const fq_default_mat_t mat2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_set(mat1->fq_zech, mat2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_set(mat1->fq_nmod, mat2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_set(mat1->nmod, mat2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_set(mat1->fmpz_mod, mat2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_set(mat1->fq, mat2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_clear(fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_clear(mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_clear(mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_clear(mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_clear(mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_clear(mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE int fq_default_mat_equal(const fq_default_mat_t mat1, const fq_default_mat_t mat2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_equal(mat1->fq_zech, mat2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_equal(mat1->fq_nmod, mat2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_equal(mat1->nmod, mat2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_equal(mat1->fmpz_mod, mat2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_equal(mat1->fq, mat2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_zero(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_is_zero(mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_is_zero(mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_is_zero(mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_is_zero(mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_is_zero(mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_one(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_is_one(mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_is_one(mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_is_one(mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_is_one(mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_is_one(mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_empty(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_is_empty(mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_is_empty(mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_is_empty(mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_is_empty(mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_is_empty(mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_square(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_is_square(mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_is_square(mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_is_square(mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_is_square(mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_is_square(mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_entry(fq_default_t val, const fq_default_mat_t mat, slong i, slong j, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_set(val->fq_zech, fq_zech_mat_entry(mat->fq_zech, i, j), FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_set(val->fq_nmod, fq_nmod_mat_entry(mat->fq_nmod, i, j), FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { val->nmod = nmod_mat_entry(mat->nmod, i, j); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(val->fmpz_mod, fmpz_mod_mat_entry(mat->fmpz_mod, i, j)); } else { fq_set(val->fq, fq_mat_entry(mat->fq, i, j), FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_entry_set(fq_default_mat_t mat, slong i, slong j, const fq_default_t x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_entry_set(mat->fq_zech, i, j, x->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_entry_set(mat->fq_nmod, i, j, x->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_entry(mat->nmod, i, j) = x->nmod; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_set(fmpz_mod_mat_entry(mat->fmpz_mod, i, j), x->fmpz_mod); } else { fq_mat_entry_set(mat->fq, i, j, x->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_entry_set_fmpz(fq_default_mat_t mat, slong i, slong j, const fmpz_t x, const fq_default_ctx_t ctx) { fq_default_t c; fq_default_init(c, ctx); fq_default_set_fmpz(c, x, ctx); fq_default_mat_entry_set(mat, i, j, c, ctx); fq_default_clear(c, ctx); } FQ_DEFAULT_MAT_INLINE slong fq_default_mat_nrows(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_nrows(mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_nrows(mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_nrows(mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_nrows(mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_nrows(mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE slong fq_default_mat_ncols(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_ncols(mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_ncols(mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_ncols(mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_ncols(mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_ncols(mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_swap_rows(fq_default_mat_t mat, slong * perm, slong r, slong s, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_swap_rows(mat->fq_zech, perm, r, s, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_swap_rows(mat->fq_nmod, perm, r, s, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_swap_rows(mat->nmod, perm, r, s); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_swap_rows(mat->fmpz_mod, perm, r, s, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_swap_rows(mat->fq, perm, r, s, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_invert_rows(fq_default_mat_t mat, slong * perm, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_invert_rows(mat->fq_zech, perm, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_invert_rows(mat->fq_nmod, perm, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_invert_rows(mat->nmod, perm); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_invert_rows(mat->fmpz_mod, perm, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_invert_rows(mat->fq, perm, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_swap_cols(fq_default_mat_t mat, slong * perm, slong r, slong s, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_swap_cols(mat->fq_zech, perm, r, s, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_swap_cols(mat->fq_nmod, perm, r, s, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_swap_cols(mat->nmod, perm, r, s); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_swap_cols(mat->fmpz_mod, perm, r, s, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_swap_cols(mat->fq, perm, r, s, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_invert_cols(fq_default_mat_t mat, slong * perm, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_invert_cols(mat->fq_zech, perm, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_invert_cols(mat->fq_nmod, perm, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_invert_cols(mat->nmod, perm); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_invert_cols(mat->fmpz_mod, perm, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_invert_cols(mat->fq, perm, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Assignment ***************************************************************/ FQ_DEFAULT_MAT_INLINE void fq_default_mat_zero(fq_default_mat_t A, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_zero(A->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_zero(A->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_zero(A->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_zero(A->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_zero(A->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_one(fq_default_mat_t A, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_one(A->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_one(A->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_one(A->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_one(A->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_one(A->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Conversions ***************************************************************/ FQ_DEFAULT_MAT_INLINE void fq_default_mat_set_nmod_mat(fq_default_mat_t mat1, const nmod_mat_t mat2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_set_nmod_mat(mat1->fq_zech, mat2, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_set_nmod_mat(mat1->fq_nmod, mat2, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_set(mat1->nmod, mat2); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_mod_mat_set_nmod_mat(mat1->fmpz_mod, mat2, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_set_nmod_mat(mat1->fq, mat2, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_set_fmpz_mod_mat(fq_default_mat_t mat1, const fmpz_mod_mat_t mat2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_set_fmpz_mod_mat(mat1->fq_zech, mat2, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_set_fmpz_mod_mat(mat1->fq_nmod, mat2, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_mat_get_nmod_mat(mat1->nmod, mat2); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_set(mat1->fmpz_mod, mat2, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_set_fmpz_mod_mat(mat1->fq, mat2, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_set_fmpz_mat(fq_default_mat_t mat1, const fmpz_mat_t mat2, const fq_default_ctx_t ctx) { fmpz_mod_mat_t mod_mat; if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fmpz_mod_ctx_t ctx2; fmpz_t prime; fmpz_init_set_ui(prime, fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx))); fmpz_mod_ctx_init(ctx2, prime); fmpz_mod_mat_init(mod_mat, mat2->r, mat2->c, ctx2); fmpz_mod_mat_set_fmpz_mat(mod_mat, mat2, ctx2); fq_zech_mat_set_fmpz_mod_mat(mat1->fq_zech, mod_mat, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); fmpz_mod_mat_clear(mod_mat, ctx2); fmpz_mod_ctx_clear(ctx2); fmpz_clear(prime); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fmpz_mod_ctx_t ctx2; fmpz_t prime; fmpz_init_set_ui(prime, fq_nmod_ctx_prime(FQ_DEFAULT_CTX_FQ_NMOD(ctx))); fmpz_mod_ctx_init(ctx2, prime); fmpz_mod_mat_init(mod_mat, mat2->r, mat2->c, ctx2); fmpz_mod_mat_set_fmpz_mat(mod_mat, mat2, ctx2); fq_nmod_mat_set_fmpz_mod_mat(mat1->fq_nmod, mod_mat, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); fmpz_mod_mat_clear(mod_mat, ctx2); fmpz_mod_ctx_clear(ctx2); fmpz_clear(prime); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_mat_get_nmod_mat(mat1->nmod, mat2); return; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_set_fmpz_mat(mat1->fmpz_mod, mat2, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); return; } else { fmpz_mod_ctx_t ctx2; fmpz_mod_ctx_init(ctx2, fq_ctx_prime(FQ_DEFAULT_CTX_FQ(ctx))); fmpz_mod_mat_init(mod_mat, mat2->r, mat2->c, ctx2); fmpz_mod_mat_set_fmpz_mat(mod_mat, mat2, ctx2); fq_mat_set_fmpz_mod_mat(mat1->fq, mod_mat, FQ_DEFAULT_CTX_FQ(ctx)); fmpz_mod_mat_clear(mod_mat, ctx2); fmpz_mod_ctx_clear(ctx2); } } /* Windows and concatenation */ FQ_DEFAULT_MAT_INLINE void fq_default_mat_window_init(fq_default_mat_t window, const fq_default_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_window_init(window->fq_zech, mat->fq_zech, r1, c1, r2, c2, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_window_init(window->fq_nmod, mat->fq_nmod, r1, c1, r2, c2, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_window_init(window->nmod, mat->nmod, r1, c1, r2, c2); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_window_init(window->fmpz_mod, mat->fmpz_mod, r1, c1, r2, c2, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_window_init(window->fq, mat->fq, r1, c1, r2, c2, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_window_clear(fq_default_mat_t window, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_window_clear(window->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_window_clear(window->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_window_clear(window->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_window_clear(window->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_window_clear(window->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_concat_horizontal(fq_default_mat_t res, const fq_default_mat_t mat1, const fq_default_mat_t mat2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_concat_horizontal(res->fq_zech, mat1->fq_zech, mat2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_concat_horizontal(res->fq_nmod, mat1->fq_nmod, mat2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_concat_horizontal(res->nmod, mat1->nmod, mat2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_concat_horizontal(res->fmpz_mod, mat1->fmpz_mod, mat2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_concat_horizontal(res->fq, mat1->fq, mat2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_concat_vertical(fq_default_mat_t res, const fq_default_mat_t mat1, const fq_default_mat_t mat2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_concat_vertical(res->fq_zech, mat1->fq_zech, mat2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_concat_vertical(res->fq_nmod, mat1->fq_nmod, mat2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_concat_vertical(res->nmod, mat1->nmod, mat2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_concat_vertical(res->fmpz_mod, mat1->fmpz_mod, mat2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_concat_vertical(res->fq, mat1->fq, mat2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Input and output *********************************************************/ #ifdef FLINT_HAVE_FILE int fq_default_mat_fprint(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx); int fq_default_mat_fprint_pretty(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx); #endif int fq_default_mat_print(const fq_default_mat_t mat, const fq_default_ctx_t ctx); int fq_default_mat_print_pretty(const fq_default_mat_t mat, const fq_default_ctx_t ctx); /* TODO: Read functions */ /* Random matrix generation *************************************************/ FQ_DEFAULT_MAT_INLINE void fq_default_mat_randtest(fq_default_mat_t mat, flint_rand_t state, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_randtest(mat->fq_zech, state, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_randtest(mat->fq_nmod, state, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_randtest(mat->nmod, state); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_randtest(mat->fmpz_mod, state, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_randtest(mat->fq, state, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_randrank(fq_default_mat_t mat, flint_rand_t state, slong rank, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_randrank(mat->fq_zech, state, rank, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_randrank(mat->fq_nmod, state, rank, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_randrank(mat->nmod, state, rank); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_randrank(mat->fmpz_mod, state, rank, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_randrank(mat->fq, state, rank, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_randops(fq_default_mat_t mat, flint_rand_t state, slong count, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_randops(mat->fq_zech, state, count, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_randops(mat->fq_nmod, state, count, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_randops(mat->nmod, state, count); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_randops(mat->fmpz_mod, state, count, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_randops(mat->fq, state, count, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_randtril(fq_default_mat_t mat, flint_rand_t state, int unit, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_randtril(mat->fq_zech, state, unit, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_randtril(mat->fq_nmod, state, unit, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_randtril(mat->nmod, state, unit); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_randtril(mat->fmpz_mod, state, unit, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_randtril(mat->fq, state, unit, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_randtriu(fq_default_mat_t mat, flint_rand_t state, int unit, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_randtriu(mat->fq_zech, state, unit, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_randtriu(mat->fq_nmod, state, unit, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_randtriu(mat->nmod, state, unit); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_randtriu(mat->fmpz_mod, state, unit, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_randtriu(mat->fq, state, unit, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Norms */ /* Transpose */ /* Addition and subtraction */ FQ_DEFAULT_MAT_INLINE void fq_default_mat_add(fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_add(C->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_add(C->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_add(C->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_add(C->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_add(C->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_sub(fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_sub(C->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_sub(C->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_sub(C->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_sub(C->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_sub(C->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_neg(fq_default_mat_t B, const fq_default_mat_t A, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_neg(B->fq_zech, A->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_neg(B->fq_nmod, A->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_neg(B->nmod, A->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_neg(B->fmpz_mod, A->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_neg(B->fq, A->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_submul(fq_default_mat_t D, const fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_submul(D->fq_zech, C->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_submul(D->fq_nmod, C->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_submul(D->nmod, C->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_submul(D->fmpz_mod, C->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_submul(D->fq, C->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Scalar operations */ /* Multiplication */ FQ_DEFAULT_MAT_INLINE void fq_default_mat_mul(fq_default_mat_t C, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_mul(C->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_mul(C->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_mul(C->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_mul(C->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_mul(C->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE slong fq_default_mat_lu(slong * P, fq_default_mat_t A, int rank_check, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_lu(P, A->fq_zech, rank_check, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_lu(P, A->fq_nmod, rank_check, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_lu(P, A->nmod, rank_check); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_lu(P, A->fmpz_mod, rank_check, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_lu(P, A->fq, rank_check, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Inverse *******************************************************************/ FQ_DEFAULT_MAT_INLINE int fq_default_mat_inv(fq_default_mat_t B, fq_default_mat_t A, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_inv(B->fq_zech, A->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_inv(B->fq_nmod, A->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_inv(B->nmod, A->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_inv(B->fmpz_mod, A->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_inv(B->fq, A->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Solving *******************************************************************/ FQ_DEFAULT_MAT_INLINE slong fq_default_mat_rref(fq_default_mat_t B, const fq_default_mat_t A, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_rref(B->fq_zech, A->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_rref(B->fq_nmod, A->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_set(B->nmod, A->nmod); return nmod_mat_rref(B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_rref(B->fmpz_mod, A->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_rref(B->fq, A->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE slong fq_default_mat_nullspace(fq_default_mat_t X, const fq_default_mat_t A, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_nullspace(X->fq_zech, A->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_nullspace(X->fq_nmod, A->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_nullspace(X->nmod, A->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_nullspace(X->fmpz_mod, A->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_nullspace(X->fq, A->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE slong fq_default_mat_rank(const fq_default_mat_t A, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_rank(A->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_rank(A->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_rank(A->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_rank(A->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_rank(A->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_solve_tril(fq_default_mat_t X, const fq_default_mat_t L, const fq_default_mat_t B, int unit, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_solve_tril(X->fq_zech, L->fq_zech, B->fq_zech, unit, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_solve_tril(X->fq_nmod, L->fq_nmod, B->fq_nmod, unit, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_solve_tril(X->nmod, L->nmod, B->nmod, unit); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_solve_tril(X->fmpz_mod, L->fmpz_mod, B->fmpz_mod, unit, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_solve_tril(X->fq, L->fq, B->fq, unit, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_solve_triu(fq_default_mat_t X, const fq_default_mat_t U, const fq_default_mat_t B, int unit, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_solve_triu(X->fq_zech, U->fq_zech, B->fq_zech, unit, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_solve_triu(X->fq_nmod, U->fq_nmod, B->fq_nmod, unit, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_solve_triu(X->nmod, U->nmod, B->nmod, unit); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_solve_triu(X->fmpz_mod, U->fmpz_mod, B->fmpz_mod, unit, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_solve_triu(X->fq, U->fq, B->fq, unit, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Nonsingular solving *******************************************************/ FQ_DEFAULT_MAT_INLINE int fq_default_mat_solve(fq_default_mat_t X, const fq_default_mat_t A, const fq_default_mat_t C, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_solve(X->fq_zech, A->fq_zech, C->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_solve(X->fq_nmod, A->fq_nmod, C->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_solve(X->nmod, A->nmod, C->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_solve(X->fmpz_mod, A->fmpz_mod, C->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_solve(X->fq, A->fq, C->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Solving *******************************************************************/ FQ_DEFAULT_MAT_INLINE int fq_default_mat_can_solve(fq_default_mat_t X, const fq_default_mat_t A, const fq_default_mat_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_can_solve(X->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_can_solve(X->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_can_solve(X->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_can_solve(X->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_can_solve(X->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Transforms ****************************************************************/ FQ_DEFAULT_MAT_INLINE void fq_default_mat_similarity(fq_default_mat_t A, slong r, fq_default_t d, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_similarity(A->fq_zech, r, d->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_similarity(A->fq_nmod, r, d->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_similarity(A->nmod, r, d->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_similarity(A->fmpz_mod, r, d->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_similarity(A->fq, r, d->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Characteristic polynomial *************************************************/ /* this prototype really lives in fq_poly_templates.h * FQ_DEFAULT_MAT_INLINE * void fq_default_mat_charpoly(fq_default_poly_t) p, * fq_default_mat_t A, const fq_default_ctx_t ctx) * { * fq_default_mat_charpoly_danilevsky(p, A, ctx) * } */ /* Minimal polynomial ********************************************************/ /* this prototype really lives in fq_poly_templates.h * FQ_DEFAULT_MAT_INLINE * void fq_default_mat_minpoly(fq_default_poly_t) p, * const fq_default_mat_t X, const fq_default_ctx_t ctx) */ #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_default_mat/000077500000000000000000000000001461254215100163755ustar00rootroot00000000000000flint-3.1.3/src/fq_default_mat/inlines.c000066400000000000000000000007751461254215100202130ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_MAT_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fq_default.h" #include "fq_default_mat.h" flint-3.1.3/src/fq_default_mat/io.c000066400000000000000000000043611461254215100171540ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fq_default_mat.h" int fq_default_mat_fprint(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_fprint(file, mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_fprint(file, mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_fprint(file, mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return fmpz_mod_mat_fprint(file, mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_fprint(file, mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } int fq_default_mat_fprint_pretty(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_mat_fprint_pretty(file, mat->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_mat_fprint_pretty(file, mat->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_mat_fprint_pretty(file, mat->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_mat_fprint_pretty(file, mat->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_mat_fprint_pretty(file, mat->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } int fq_default_mat_print(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { return fq_default_mat_fprint(stdout, mat, ctx); } int fq_default_mat_print_pretty(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { return fq_default_mat_fprint_pretty(stdout, mat, ctx); } flint-3.1.3/src/fq_default_mat/test/000077500000000000000000000000001461254215100173545ustar00rootroot00000000000000flint-3.1.3/src/fq_default_mat/test/main.c000066400000000000000000000016171461254215100204510ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-init.c" #include "t-inlines.c" #include "t-set_fmpz_mat.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_default_mat_init), TEST_FUNCTION(fq_default_mat_inlines), TEST_FUNCTION(fq_default_mat_set_fmpz_mat) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_default_mat/test/t-init.c000066400000000000000000000031151461254215100207240ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default_mat.h" TEST_FUNCTION_START(fq_default_mat_init, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_mat_t fq_mat; fmpz_t p; slong rows, cols; rows = n_randint(state, 20); cols = n_randint(state, 20); fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fq_default_mat_init(fq_mat, rows, cols, ctx); fq_default_mat_randtest(fq_mat, state, ctx); fq_default_mat_clear(fq_mat, ctx); fq_default_ctx_clear(ctx); fq_default_ctx_init(ctx, p, 16, "x"); fq_default_mat_init(fq_mat, rows, cols, ctx); fq_default_mat_randtest(fq_mat, state, ctx); fq_default_mat_clear(fq_mat, ctx); fq_default_ctx_clear(ctx); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fq_default_mat_init(fq_mat, rows, cols, ctx); fq_default_mat_randtest(fq_mat, state, ctx); fq_default_mat_clear(fq_mat, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_mat/test/t-inlines.c000066400000000000000000000047271461254215100214340ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default_mat.h" TEST_FUNCTION_START(fq_default_mat_inlines, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; slong deg; fq_default_ctx_t ctx; fq_default_t t; fq_default_mat_t a, b, c, d, e, f, g; slong n = n_randint(state, 4) + 1; fmpz_init(p); fmpz_randprime(p, state, n_randint(state, 2) ? 60 : 120, 1); deg = n_randint(state, 4) + 1; fq_default_ctx_init(ctx, p, deg, "a"); fq_default_init(t, ctx); fq_default_mat_init(a, n, n, ctx); fq_default_mat_init(b, n, n, ctx); fq_default_mat_init(c, n, n, ctx); fq_default_mat_init(d, n, n, ctx); fq_default_mat_init(e, n, n, ctx); fq_default_mat_init(f, n, n, ctx); fq_default_mat_init(g, n, n, ctx); fq_default_mat_randtest(a, state, ctx); fq_default_mat_randtest(b, state, ctx); fq_default_mat_randtest(c, state, ctx); fq_default_mat_randtest(d, state, ctx); fq_default_mat_randtest(e, state, ctx); fq_default_mat_randtest(f, state, ctx); fq_default_mat_randtest(g, state, ctx); fq_default_mat_add(e, a, b, ctx); fq_default_mat_mul(d, e, c, ctx); fq_default_mat_mul(f, a, c, ctx); fq_default_mat_mul(g, b, c, ctx); fq_default_mat_add(e, f, g, ctx); FLINT_TEST(fq_default_mat_equal(d, e, ctx)); fq_default_mat_sub(e, a, b, ctx); fq_default_mat_mul(d, e, c, ctx); fq_default_mat_mul(f, a, c, ctx); fq_default_mat_mul(g, b, c, ctx); fq_default_mat_sub(e, f, g, ctx); FLINT_TEST(fq_default_mat_equal(d, e, ctx)); fq_default_clear(t, ctx); fq_default_mat_clear(a, ctx); fq_default_mat_clear(b, ctx); fq_default_mat_clear(c, ctx); fq_default_mat_clear(d, ctx); fq_default_mat_clear(e, ctx); fq_default_mat_clear(f, ctx); fq_default_mat_clear(g, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_mat/test/t-set_fmpz_mat.c000066400000000000000000000072211461254215100224530ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default_mat.h" TEST_FUNCTION_START(fq_default_mat_set_fmpz_mat, state) { int i, result; for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_mat_t fq_mat1, fq_mat2; fmpz_mat_t mat; fmpz_t p; slong rows, cols; rows = n_randint(state, 20); cols = n_randint(state, 20); fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fmpz_mat_init(mat, rows, cols); fmpz_mat_one(mat); fq_default_mat_init(fq_mat1, rows, cols, ctx); fq_default_mat_init(fq_mat2, rows, cols, ctx); fq_default_mat_set_fmpz_mat(fq_mat1, mat, ctx); fq_default_mat_one(fq_mat2, ctx); result = fq_default_mat_equal(fq_mat1, fq_mat2, ctx); if (!result) { flint_printf("FAIL: matrices not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fq_default_mat_clear(fq_mat1, ctx); fq_default_mat_clear(fq_mat2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_mat_t fq_mat1, fq_mat2; fmpz_mat_t mat; fmpz_t p; slong rows, cols; rows = n_randint(state, 20); cols = n_randint(state, 20); fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 16, "x"); fmpz_mat_init(mat, rows, cols); fmpz_mat_one(mat); fq_default_mat_init(fq_mat1, rows, cols, ctx); fq_default_mat_init(fq_mat2, rows, cols, ctx); fq_default_mat_set_fmpz_mat(fq_mat1, mat, ctx); fq_default_mat_one(fq_mat2, ctx); result = fq_default_mat_equal(fq_mat1, fq_mat2, ctx); if (!result) { flint_printf("FAIL: matrices not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fq_default_mat_clear(fq_mat1, ctx); fq_default_mat_clear(fq_mat2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_mat_t fq_mat1, fq_mat2; fmpz_mat_t mat; fmpz_t p; slong rows, cols; rows = n_randint(state, 20); cols = n_randint(state, 20); fmpz_init(p); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fmpz_mat_init(mat, rows, cols); fmpz_mat_one(mat); fq_default_mat_init(fq_mat1, rows, cols, ctx); fq_default_mat_init(fq_mat2, rows, cols, ctx); fq_default_mat_set_fmpz_mat(fq_mat1, mat, ctx); fq_default_mat_one(fq_mat2, ctx); result = fq_default_mat_equal(fq_mat1, fq_mat2, ctx); if (!result) { flint_printf("FAIL: matrices not equal\n"); fflush(stdout); flint_abort(); } fmpz_mat_clear(mat); fq_default_mat_clear(fq_mat1, ctx); fq_default_mat_clear(fq_mat2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_poly.h000066400000000000000000002302121461254215100167500ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_DEFAULT_POLY_H #define FQ_DEFAULT_POLY_H #ifdef FQ_DEFAULT_POLY_INLINES_C #define FQ_DEFAULT_POLY_INLINE #else #define FQ_DEFAULT_POLY_INLINE static inline #endif #include "fq_default.h" #include "fq_vec.h" #include "fq_poly.h" #include "fq_nmod_poly.h" #include "fq_zech_poly.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions *********************************************************/ typedef union fq_default_poly_struct { fq_poly_t fq; fq_nmod_poly_t fq_nmod; fq_zech_poly_t fq_zech; nmod_poly_t nmod; fmpz_mod_poly_t fmpz_mod; } fq_default_poly_struct; typedef fq_default_poly_struct fq_default_poly_t[1]; /* Memory management ********************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_init(fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_init(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_init(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_init(poly->nmod, FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_init(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_init(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_init2(fq_default_poly_t poly, slong alloc, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_init2(poly->fq_zech, alloc, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_init2(poly->fq_nmod, alloc, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_init2(poly->nmod, FQ_DEFAULT_CTX_NMOD(ctx).n, alloc); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_init2(poly->fmpz_mod, alloc, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_init2(poly->fq, alloc, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_realloc(fq_default_poly_t poly, slong alloc, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_realloc(poly->fq_zech, alloc, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_realloc(poly->fq_nmod, alloc, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_realloc(poly->nmod, alloc); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_realloc(poly->fmpz_mod, alloc, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_realloc(poly->fq, alloc, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_truncate(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_truncate(poly->fq_zech, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_truncate(poly->fq_nmod, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_truncate(poly->nmod, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_truncate(poly->fmpz_mod, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_truncate(poly->fq, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_set_trunc(fq_default_poly_t poly1, fq_default_poly_t poly2, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_set_trunc(poly1->fq_zech, poly2->fq_zech, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_set_trunc(poly1->fq_nmod, poly2->fq_nmod, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_set_trunc(poly1->nmod, poly2->nmod, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_set_trunc(poly1->fmpz_mod, poly2->fmpz_mod, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_set_trunc(poly1->fq, poly2->fq, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_fit_length(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_fit_length(poly->fq_zech, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_fit_length(poly->fq_nmod, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_fit_length(poly->nmod, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_fit_length(poly->fmpz_mod, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_fit_length(poly->fq, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void _fq_default_poly_set_length(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { _fq_zech_poly_set_length(poly->fq_zech, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { _fq_nmod_poly_set_length(poly->fq_nmod, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { _nmod_poly_set_length(poly->nmod, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { _fmpz_mod_poly_set_length(poly->fmpz_mod, len); } else { _fq_poly_set_length(poly->fq, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_clear(fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_clear(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_clear(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_clear(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_clear(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_clear(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Polynomial parameters ***************************************************/ FQ_DEFAULT_POLY_INLINE slong fq_default_poly_length(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_length(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_length(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_length(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_length(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_length(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE slong fq_default_poly_degree(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_degree(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_degree(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_degree(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_degree(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_degree(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Randomisation ***********************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_randtest(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_randtest(f->fq_zech, state, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_randtest(f->fq_nmod, state, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_randtest(f->nmod, state, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_randtest(f->fmpz_mod, state, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_randtest(f->fq, state, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_randtest_not_zero(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_randtest_not_zero(f->fq_zech, state, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_randtest_not_zero(f->fq_nmod, state, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_randtest_not_zero(f->nmod, state, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_randtest_not_zero(f->fmpz_mod, state, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_randtest_not_zero(f->fq, state, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_randtest_monic(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_randtest_monic(f->fq_zech, state, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_randtest_monic(f->fq_nmod, state, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_randtest_monic(f->nmod, state, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_randtest_monic(f->fmpz_mod, state, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_randtest_monic(f->fq, state, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_randtest_irreducible(fq_default_poly_t f, flint_rand_t state, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_randtest_irreducible(f->fq_zech, state, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_randtest_irreducible(f->fq_nmod, state, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_randtest_irreducible(f->nmod, state, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_randtest_irreducible(f->fmpz_mod, state, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_randtest_irreducible(f->fq, state, len, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Assignment and basic manipulation ***************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_set(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_set(rop->fq_zech, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_set(rop->fq_nmod, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_set(rop->nmod, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_set(rop->fmpz_mod, op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_set(rop->fq, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_set_fq_default(fq_default_poly_t poly, const fq_default_t c, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_set_fq_zech(poly->fq_zech, c->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_set_fq_nmod(poly->fq_nmod, c->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_zero(poly->nmod); nmod_poly_set_coeff_ui(poly->nmod, 0, c->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_set_fmpz(poly->fmpz_mod, c->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_set_fq(poly->fq, c->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_swap(fq_default_poly_t op1, fq_default_poly_t op2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_swap(op1->fq_zech, op2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_swap(op1->fq_nmod, op2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_swap(op1->nmod, op2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_swap(op1->fmpz_mod, op2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_swap(op1->fq, op2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_zero(fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_zero(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_zero(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_zero(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_zero(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_zero(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_one(fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_one(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_one(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_one(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_one(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_one(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_gen(fq_default_poly_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_gen(f->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_gen(f->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_one(f->nmod); nmod_poly_shift_left(f->nmod, f->nmod, 1); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_gen(f->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_gen(f->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_make_monic(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_make_monic(rop->fq_zech, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_make_monic(rop->fq_nmod, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_make_monic(rop->nmod, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_make_monic(rop->fmpz_mod, op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_make_monic(rop->fq, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_reverse(fq_default_poly_t res, const fq_default_poly_t poly, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_reverse(res->fq_zech, poly->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_reverse(res->fq_nmod, poly->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_reverse(res->nmod, poly->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_reverse(res->fmpz_mod, poly->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_reverse(res->fq, poly->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE ulong fq_default_poly_deflation(const fq_default_poly_t input, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_deflation(input->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_deflation(input->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_deflation(input->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_deflation(input->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_deflation(input->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_deflate(fq_default_poly_t result, const fq_default_poly_t input, ulong deflation, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_deflate(result->fq_zech, input->fq_zech, deflation, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_deflate(result->fq_nmod, input->fq_nmod, deflation, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_deflate(result->nmod, input->nmod, deflation); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_deflate(result->fmpz_mod, input->fmpz_mod, deflation, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_deflate(result->fq, input->fq, deflation, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_inflate(fq_default_poly_t result, const fq_default_poly_t input, ulong inflation, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_inflate(result->fq_zech, input->fq_zech, inflation, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_inflate(result->fq_nmod, input->fq_nmod, inflation, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_inflate(result->nmod, input->nmod, inflation); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_inflate(result->fmpz_mod, input->fmpz_mod, inflation, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_inflate(result->fq, input->fq, inflation, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Getting and setting coefficients ****************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_get_coeff(fq_default_t x, const fq_default_poly_t poly, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_get_coeff(x->fq_zech, poly->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_get_coeff(x->fq_nmod, poly->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { x->nmod = nmod_poly_get_coeff_ui(poly->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_get_coeff_fmpz(x->fmpz_mod, poly->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_get_coeff(x->fq, poly->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_set_coeff(fq_default_poly_t poly, slong n, const fq_default_t x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_set_coeff(poly->fq_zech, n, x->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_set_coeff(poly->fq_nmod, n, x->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_set_coeff_ui(poly->nmod, n, x->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_set_coeff_fmpz(poly->fmpz_mod, n, x->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_set_coeff(poly->fq, n, x->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_set_coeff_fmpz(fq_default_poly_t poly, slong n, const fmpz_t x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_set_coeff_fmpz(poly->fq_zech, n, x, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_set_coeff_fmpz(poly->fq_nmod, n, x, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_set_coeff_ui(poly->nmod, n, fmpz_get_nmod(x, FQ_DEFAULT_CTX_NMOD(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_set_coeff_fmpz(poly->fmpz_mod, n, x, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_set_coeff_fmpz(poly->fq, n, x, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_set_nmod_poly(fq_default_poly_t rop, const nmod_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_set_nmod_poly(rop->fq_zech, op, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_set_nmod_poly(rop->fq_nmod, op, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_set(rop->nmod, op); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_set_nmod_poly(rop->fmpz_mod, op); } else { fq_poly_set_nmod_poly(rop->fq, op, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_set_fmpz_mod_poly(fq_default_poly_t rop, const fmpz_mod_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_set_fmpz_mod_poly(rop->fq_zech, op, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_set_fmpz_mod_poly(rop->fq_nmod, op, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_mod_poly_get_nmod_poly(rop->nmod, op); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_set(rop->fmpz_mod, op, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_set_fmpz_mod_poly(rop->fq, op, FQ_DEFAULT_CTX_FQ(ctx)); } } void fq_default_poly_set_fmpz_poly(fq_default_poly_t rop, const fmpz_poly_t op, const fq_default_ctx_t ctx); /* Comparison **************************************************************/ FQ_DEFAULT_POLY_INLINE int fq_default_poly_equal(const fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_equal(poly1->fq_zech, poly2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_equal(poly1->fq_nmod, poly2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_equal(poly1->nmod, poly2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_equal(poly1->fmpz_mod, poly2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_equal(poly1->fq, poly2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE int fq_default_poly_equal_trunc(const fq_default_poly_t poly1, const fq_default_poly_t poly2, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_equal_trunc(poly1->fq_zech, poly2->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_equal_trunc(poly1->fq_nmod, poly2->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_equal_trunc(poly1->nmod, poly2->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_equal_trunc(poly1->fmpz_mod, poly2->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_equal_trunc(poly1->fq, poly2->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_zero(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_is_zero(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_is_zero(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_is_zero(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_is_zero(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_is_zero(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_one(const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_is_one(op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_is_one(op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_is_one(op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_is_one(op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_is_one(op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_unit(const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_is_unit(op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_is_unit(op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_is_unit(op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_is_unit(op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_is_unit(op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_gen(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_is_gen(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_is_gen(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_is_gen(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_is_gen(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_is_gen(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE int fq_default_poly_equal_fq_default(const fq_default_poly_t poly, const fq_default_t c, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_equal_fq_zech(poly->fq_zech, c->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_equal_fq_nmod(poly->fq_nmod, c->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { if (c->nmod == 0) return poly->nmod->length == 0; else return poly->nmod->length == 1 && poly->nmod->coeffs[0] == c->nmod; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { if (fmpz_is_zero(c->fmpz_mod)) return poly->fmpz_mod->length == 0; else return poly->fmpz_mod->length == 1 && fmpz_equal(poly->fmpz_mod->coeffs + 0, c->fmpz_mod); } else { return fq_poly_equal_fq(poly->fq, c->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Addition and subtraction ************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_add(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_add(rop->fq_zech, op1->fq_zech, op2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_add(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_add(rop->nmod, op1->nmod, op2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_add(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_add(rop->fq, op1->fq, op2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_add_si(fq_default_poly_t rop, const fq_default_poly_t op1, slong c, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_add_si(rop->fq_zech, op1->fq_zech, c, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_add_si(rop->fq_nmod, op1->fq_nmod, c, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_add_ui(rop->nmod, op1->nmod, nmod_set_si(c, FQ_DEFAULT_CTX_NMOD(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_add_si(rop->fmpz_mod, op1->fmpz_mod, c, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_add_si(rop->fq, op1->fq, c, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_add_series(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_add_series(rop->fq_zech, op1->fq_zech, op2->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_add_series(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_add_series(rop->nmod, op1->nmod, op2->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_add_series(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_add_series(rop->fq, op1->fq, op2->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_sub(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_sub(rop->fq_zech, op1->fq_zech, op2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_sub(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_sub(rop->nmod, op1->nmod, op2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_sub(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_sub(rop->fq, op1->fq, op2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_sub_series(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_sub_series(rop->fq_zech, op1->fq_zech, op2->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_sub_series(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_sub_series(rop->nmod, op1->nmod, op2->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_sub_series(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_sub_series(rop->fq, op1->fq, op2->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_neg(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_neg(rop->fq_zech, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_neg(rop->fq_nmod, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_neg(rop->nmod, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_neg(rop->fmpz_mod, op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_neg(rop->fq, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Scalar multiplication and division **************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_scalar_mul_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_scalar_mul_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_scalar_mul_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_scalar_mul_nmod(rop->nmod, op->nmod, x->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_scalar_mul_fmpz(rop->fmpz_mod, op->fmpz_mod, x->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_scalar_mul_fq(rop->fq, op->fq, x->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_scalar_div_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_scalar_div_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_scalar_div_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_scalar_mul_nmod(rop->nmod, op->nmod, nmod_inv(x->nmod, FQ_DEFAULT_CTX_NMOD(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_t t; fmpz_init(t); fmpz_mod_inv(t, x->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_mod_poly_scalar_mul_fmpz(rop->fmpz_mod, op->fmpz_mod, t, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_clear(t); } else { fq_poly_scalar_div_fq(rop->fq, op->fq, x->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_scalar_addmul_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_scalar_addmul_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_scalar_addmul_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_scalar_addmul_nmod(rop->nmod, op->nmod, x->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_scalar_addmul_fmpz(rop->fmpz_mod, op->fmpz_mod, x->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_scalar_addmul_fq(rop->fq, op->fq, x->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_scalar_submul_fq_default(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_t x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_scalar_submul_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_scalar_submul_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_scalar_addmul_nmod(rop->nmod, op->nmod, nmod_neg(x->nmod, FQ_DEFAULT_CTX_NMOD(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_t t; fmpz_init(t); fmpz_mod_neg(t, x->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_mod_poly_scalar_addmul_fmpz(rop->fmpz_mod, op->fmpz_mod, t, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_clear(t); } else { fq_poly_scalar_submul_fq(rop->fq, op->fq, x->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Multiplication **********************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_mul(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_mul(rop->fq_zech, op1->fq_zech, op2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_mul(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_mul(rop->nmod, op1->nmod, op2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_mul(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_mul(rop->fq, op1->fq, op2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_mullow(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_mullow(rop->fq_zech, op1->fq_zech, op2->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_mullow(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_mullow(rop->nmod, op1->nmod, op2->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_mullow(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_mullow(rop->fq, op1->fq, op2->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_mulhigh(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, slong start, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_mulhigh(rop->fq_zech, op1->fq_zech, op2->fq_zech, start, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_mulhigh(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, start, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_mulhigh(rop->nmod, op1->nmod, op2->nmod, start); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_mulhigh(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, start, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_mulhigh(rop->fq, op1->fq, op2->fq, start, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_mulmod(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_mulmod(res->fq_zech, poly1->fq_zech, poly2->fq_zech, f->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_mulmod(res->fq_nmod, poly1->fq_nmod, poly2->fq_nmod, f->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_mulmod(res->nmod, poly1->nmod, poly2->nmod, f->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_mulmod(res->fmpz_mod, poly1->fmpz_mod, poly2->fmpz_mod, f->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_mulmod(res->fq, poly1->fq, poly2->fq, f->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Squaring ******************************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_sqr(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_sqr(rop->fq_zech, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_sqr(rop->fq_nmod, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_mul(rop->nmod, op->nmod, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_sqr(rop->fmpz_mod, op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_sqr(rop->fq, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Powering ****************************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_pow(fq_default_poly_t rop, const fq_default_poly_t op, ulong e, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_pow(rop->fq_zech, op->fq_zech, e, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_pow(rop->fq_nmod, op->fq_nmod, e, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_pow(rop->nmod, op->nmod, e); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_pow(rop->fmpz_mod, op->fmpz_mod, e, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_pow(rop->fq, op->fq, e, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_pow_trunc(fq_default_poly_t res, const fq_default_poly_t poly, ulong e, slong trunc, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_pow_trunc(res->fq_zech, poly->fq_zech, e, trunc, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_pow_trunc(res->fq_nmod, poly->fq_nmod, e, trunc, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_pow_trunc(res->nmod, poly->nmod, e, trunc); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_pow_trunc(res->fmpz_mod, poly->fmpz_mod, e, trunc, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_pow_trunc(res->fq, poly->fq, e, trunc, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_powmod_fmpz_binexp(fq_default_poly_t res, const fq_default_poly_t poly, const fmpz_t e, const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_powmod_fmpz_binexp(res->fq_zech, poly->fq_zech, e, f->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_powmod_fmpz_binexp(res->fq_nmod, poly->fq_nmod, e, f->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_powmod_fmpz_binexp(res->nmod, poly->nmod, (fmpz*) e, f->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_powmod_fmpz_binexp(res->fmpz_mod, poly->fmpz_mod, e, f->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_powmod_fmpz_binexp(res->fq, poly->fq, e, f->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_powmod_ui_binexp(fq_default_poly_t res, const fq_default_poly_t poly, ulong e, const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_powmod_ui_binexp(res->fq_zech, poly->fq_zech, e, f->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_powmod_ui_binexp(res->fq_nmod, poly->fq_nmod, e, f->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_powmod_ui_binexp(res->nmod, poly->nmod, e, f->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_powmod_ui_binexp(res->fmpz_mod, poly->fmpz_mod, e, f->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_powmod_ui_binexp(res->fq, poly->fq, e, f->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Shifting ****************************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_shift_left(fq_default_poly_t rop, const fq_default_poly_t op, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_shift_left(rop->fq_zech, op->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_shift_left(rop->fq_nmod, op->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_shift_left(rop->nmod, op->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_shift_left(rop->fmpz_mod, op->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_shift_left(rop->fq, op->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_shift_right(fq_default_poly_t rop, const fq_default_poly_t op, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_shift_right(rop->fq_zech, op->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_shift_right(rop->fq_nmod, op->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_shift_right(rop->nmod, op->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_shift_right(rop->fmpz_mod, op->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_shift_right(rop->fq, op->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Norms *******************************************************************/ FQ_DEFAULT_POLY_INLINE slong fq_default_poly_hamming_weight(const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_hamming_weight(op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_hamming_weight(op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_hamming_weight(op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_hamming_weight(op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_hamming_weight(op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Greatest common divisor *************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_gcd(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_gcd(rop->fq_zech, op1->fq_zech, op2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_gcd(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_gcd(rop->nmod, op1->nmod, op2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_gcd(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_gcd(rop->fq, op1->fq, op2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_xgcd(fq_default_poly_t G, fq_default_poly_t S, fq_default_poly_t T, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_xgcd(G->fq_zech, S->fq_zech, T->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_xgcd(G->fq_nmod, S->fq_nmod, T->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_xgcd(G->nmod, S->nmod, T->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_xgcd(G->fmpz_mod, S->fmpz_mod, T->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_xgcd(G->fq, S->fq, T->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Euclidean division ******************************************************/ FQ_DEFAULT_POLY_INLINE ulong fq_default_poly_remove(fq_default_poly_t f, const fq_default_poly_t g, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_remove(f->fq_zech, g->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_remove(f->fq_nmod, g->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_remove(f->nmod, g->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_remove(f->fmpz_mod, g->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_remove(f->fq, g->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_divrem(fq_default_poly_t Q, fq_default_poly_t R, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_divrem(Q->fq_zech, R->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_divrem(Q->fq_nmod, R->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_divrem(Q->nmod, R->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_divrem(Q->fmpz_mod, R->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_divrem(Q->fq, R->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_rem(fq_default_poly_t R, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_rem(R->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_rem(R->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_rem(R->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_rem(R->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_rem(R->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_inv_series(fq_default_poly_t Qinv, const fq_default_poly_t Q, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_inv_series(Qinv->fq_zech, Q->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_inv_series(Qinv->fq_nmod, Q->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_inv_series(Qinv->nmod, Q->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_inv_series(Qinv->fmpz_mod, Q->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_inv_series(Qinv->fq, Q->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_div_series(fq_default_poly_t Q, const fq_default_poly_t A, const fq_default_poly_t B, slong n, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_div_series(Q->fq_zech, A->fq_zech, B->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_div_series(Q->fq_nmod, A->fq_nmod, B->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_div_series(Q->nmod, A->nmod, B->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_div_series(Q->fmpz_mod, A->fmpz_mod, B->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_div_series(Q->fq, A->fq, B->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Divisibility testing ****************************************************/ FQ_DEFAULT_POLY_INLINE int fq_default_poly_divides(fq_default_poly_t Q, const fq_default_poly_t A, const fq_default_poly_t B, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_divides(Q->fq_zech, A->fq_zech, B->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_divides(Q->fq_nmod, A->fq_nmod, B->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_divides(Q->nmod, A->nmod, B->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_divides(Q->fmpz_mod, A->fmpz_mod, B->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_divides(Q->fq, A->fq, B->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Derivative **************************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_derivative(fq_default_poly_t rop, const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_derivative(rop->fq_zech, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_derivative(rop->fq_nmod, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_derivative(rop->nmod, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_derivative(rop->fmpz_mod, op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_derivative(rop->fq, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Square root ***************************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_invsqrt_series(fq_default_poly_t rop, const fq_default_poly_t op, slong n, fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_invsqrt_series(rop->fq_zech, op->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_invsqrt_series(rop->fq_nmod, op->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_invsqrt_series(rop->nmod, op->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_invsqrt_series(rop->fmpz_mod, op->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_invsqrt_series(rop->fq, op->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_sqrt_series(fq_default_poly_t rop, const fq_default_poly_t op, slong n, fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_sqrt_series(rop->fq_zech, op->fq_zech, n, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_sqrt_series(rop->fq_nmod, op->fq_nmod, n, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_sqrt_series(rop->nmod, op->nmod, n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_sqrt_series(rop->fmpz_mod, op->fmpz_mod, n, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_sqrt_series(rop->fq, op->fq, n, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE int fq_default_poly_sqrt(fq_default_poly_t rop, const fq_default_poly_t op, fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_sqrt(rop->fq_zech, op->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_sqrt(rop->fq_nmod, op->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_sqrt(rop->nmod, op->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_sqrt(rop->fmpz_mod, op->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_sqrt(rop->fq, op->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Evaluation **************************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_evaluate_fq_default(fq_default_t res, const fq_default_poly_t f, const fq_default_t a, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_evaluate_fq_zech(res->fq_zech, f->fq_zech, a->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_evaluate_fq_nmod(res->fq_nmod, f->fq_nmod, a->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { res->nmod = nmod_poly_evaluate_nmod(f->nmod, a->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_mod_poly_evaluate_fmpz(res->fmpz_mod, f->fmpz_mod, a->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_evaluate_fq(res->fq, f->fq, a->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Composition *************************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_poly_compose(fq_default_poly_t rop, const fq_default_poly_t op1, const fq_default_poly_t op2, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_compose(rop->fq_zech, op1->fq_zech, op2->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_compose(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_compose(rop->nmod, op1->nmod, op2->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_compose(rop->fmpz_mod, op1->fmpz_mod, op2->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_compose(rop->fq, op1->fq, op2->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_compose_mod(fq_default_poly_t res, const fq_default_poly_t poly1, const fq_default_poly_t poly2, const fq_default_poly_t poly3, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_compose_mod(res->fq_zech, poly1->fq_zech, poly2->fq_zech, poly3->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_compose_mod(res->fq_nmod, poly1->fq_nmod, poly2->fq_nmod, poly3->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_compose_mod(res->nmod, poly1->nmod, poly2->nmod, poly3->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_compose_mod(res->fmpz_mod, poly1->fmpz_mod, poly2->fmpz_mod, poly3->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_compose_mod(res->fq, poly1->fq, poly2->fq, poly3->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Input and output ********************************************************/ #ifdef FLINT_HAVE_FILE int fq_default_poly_fprint(FILE * file, const fq_default_poly_t poly, const fq_default_ctx_t ctx); int fq_default_poly_fprint_pretty(FILE * file, const fq_default_poly_t poly, const char *x, const fq_default_ctx_t ctx); #endif int fq_default_poly_print(const fq_default_poly_t poly, const fq_default_ctx_t ctx); int fq_default_poly_print_pretty(const fq_default_poly_t poly, const char *x, const fq_default_ctx_t ctx); FQ_DEFAULT_POLY_INLINE char * fq_default_poly_get_str_pretty(const fq_default_poly_t poly, const char *x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_get_str_pretty(poly->fq_zech, x, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_get_str_pretty(poly->fq_nmod, x, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_get_str_pretty(poly->nmod, x); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_get_str_pretty(poly->fmpz_mod, x, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_get_str_pretty(poly->fq, x, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_INLINE char * fq_default_poly_get_str(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_get_str(poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_get_str(poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_get_str(poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_get_str(poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_get_str(poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } #include "fq_default_mat.h" /* Characteristic polynomial *************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_mat_charpoly(fq_default_poly_t p, const fq_default_mat_t M, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_charpoly(p->fq_zech, M->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_charpoly(p->fq_nmod, M->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_charpoly(p->nmod, M->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_charpoly(p->fmpz_mod, M->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_charpoly(p->fq, M->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } /* Minimal polynomial ********************************************************/ FQ_DEFAULT_POLY_INLINE void fq_default_mat_minpoly(fq_default_poly_t p, const fq_default_mat_t X, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_mat_minpoly(p->fq_zech, X->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_mat_minpoly(p->fq_nmod, X->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_mat_minpoly(p->nmod, X->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_mat_minpoly(p->fmpz_mod, X->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_mat_minpoly(p->fq, X->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_default_poly/000077500000000000000000000000001461254215100165775ustar00rootroot00000000000000flint-3.1.3/src/fq_default_poly/inlines.c000066400000000000000000000007771461254215100204170ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_POLY_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fq_default.h" #include "fq_default_poly.h" flint-3.1.3/src/fq_default_poly/io.c000066400000000000000000000050511461254215100173530ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fq_default_poly.h" /* printing *******************************************************************/ int fq_default_poly_fprint(FILE * file, const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_fprint(file, poly->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_fprint(file, poly->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_fprint(file, poly->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_fprint(file, poly->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_fprint(file, poly->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } int fq_default_poly_fprint_pretty(FILE * file, const fq_default_poly_t poly, const char *x, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_fprint_pretty(file, poly->fq_zech, x, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_fprint_pretty(file, poly->fq_nmod, x, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_fprint_pretty(file, poly->nmod, x); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_fprint_pretty(file, poly->fmpz_mod, x, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_fprint_pretty(file, poly->fq, x, FQ_DEFAULT_CTX_FQ(ctx)); } } int fq_default_poly_print(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { return fq_default_poly_fprint(stdout, poly, ctx); } int fq_default_poly_print_pretty(const fq_default_poly_t poly, const char *x, const fq_default_ctx_t ctx) { return fq_default_poly_fprint_pretty(stdout, poly, x, ctx); } flint-3.1.3/src/fq_default_poly/set_fmpz_poly.c000066400000000000000000000033331461254215100216370ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_default_poly.h" void fq_default_poly_set_fmpz_poly(fq_default_poly_t rop, const fmpz_poly_t op, const fq_default_ctx_t ctx) { fmpz_mod_ctx_t mod; fmpz_mod_poly_t mod_poly; if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fmpz_mod_ctx_init_ui(mod, fq_zech_ctx_prime(FQ_DEFAULT_CTX_FQ_ZECH(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fmpz_mod_ctx_init_ui(mod, fq_nmod_ctx_prime(FQ_DEFAULT_CTX_FQ_NMOD(ctx))); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_mod_ctx_init_ui(mod, FQ_DEFAULT_CTX_NMOD(ctx).n); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_init(mod_poly, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fmpz_mod_poly_set_fmpz_poly(mod_poly, op, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); fq_default_poly_set_fmpz_mod_poly(rop, mod_poly, ctx); fmpz_mod_poly_clear(mod_poly, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); return; } else { fmpz_mod_ctx_init(mod, fq_ctx_prime(FQ_DEFAULT_CTX_FQ(ctx))); } fmpz_mod_poly_init(mod_poly, mod); fmpz_mod_poly_set_fmpz_poly(mod_poly, op, mod); fq_default_poly_set_fmpz_mod_poly(rop, mod_poly, ctx); fmpz_mod_poly_clear(mod_poly, mod); fmpz_mod_ctx_clear(mod); } flint-3.1.3/src/fq_default_poly/test/000077500000000000000000000000001461254215100175565ustar00rootroot00000000000000flint-3.1.3/src/fq_default_poly/test/main.c000066400000000000000000000016241461254215100206510ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-init.c" #include "t-inlines.c" #include "t-set_fmpz_poly.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_default_poly_init), TEST_FUNCTION(fq_default_poly_inlines), TEST_FUNCTION(fq_default_poly_set_fmpz_poly) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_default_poly/test/t-init.c000066400000000000000000000030351461254215100211270ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default_poly.h" TEST_FUNCTION_START(fq_default_poly_init, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_poly_t fq_poly; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fq_default_poly_init(fq_poly, ctx); fq_default_poly_randtest(fq_poly, state, n_randint(state, 10), ctx); fq_default_poly_clear(fq_poly, ctx); fq_default_ctx_clear(ctx); fq_default_ctx_init(ctx, p, 16, "x"); fq_default_poly_init(fq_poly, ctx); fq_default_poly_randtest(fq_poly, state, n_randint(state, 10), ctx); fq_default_poly_clear(fq_poly, ctx); fq_default_ctx_clear(ctx); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fq_default_poly_init(fq_poly, ctx); fq_default_poly_randtest(fq_poly, state, n_randint(state, 10), ctx); fq_default_poly_clear(fq_poly, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_poly/test/t-inlines.c000066400000000000000000000133631461254215100216320ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default_poly.h" TEST_FUNCTION_START(fq_default_poly_inlines, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; slong deg; fq_default_ctx_t ctx; fq_default_t t; fq_default_poly_t a, b, c, d, e; fmpz_init(p); fmpz_randprime(p, state, n_randint(state, 2) ? 60 : 120, 1); deg = n_randint(state, 4) + 1; fq_default_ctx_init(ctx, p, deg, "a"); fq_default_init(t, ctx); fq_default_poly_init(a, ctx); fq_default_poly_init(b, ctx); fq_default_poly_init(c, ctx); fq_default_poly_init(d, ctx); fq_default_poly_init(e, ctx); fq_default_poly_randtest(a, state, n_randint(state, 100), ctx); fq_default_poly_randtest(b, state, n_randint(state, 100), ctx); fq_default_poly_randtest(c, state, n_randint(state, 100), ctx); fq_default_poly_get_coeff(t, a, 0, ctx); FLINT_TEST(!fq_default_poly_is_unit(a, ctx) == !fq_default_is_invertible(t, ctx) || fq_default_poly_length(a, ctx) != 1); FLINT_TEST(fq_default_poly_hamming_weight(a, ctx) <= fq_default_poly_length(a, ctx)); fq_default_poly_add(a, b, c, ctx); fq_default_poly_sub(a, a, c, ctx); FLINT_TEST(fq_default_poly_equal(a, b, ctx)); fq_default_poly_neg(b, a, ctx); fq_default_poly_add(b, a, b, ctx); fq_default_poly_zero(a, ctx); FLINT_TEST(fq_default_poly_equal(a, b, ctx)); fq_default_poly_randtest(a, state, n_randint(state, 100), ctx); fq_default_poly_randtest(b, state, n_randint(state, 100), ctx); fq_default_poly_randtest(c, state, n_randint(state, 100), ctx); fq_default_poly_randtest(d, state, n_randint(state, 100), ctx); fq_default_randtest(t, state, ctx); fq_default_poly_add_si(a, b, 1, ctx); fq_default_poly_add_si(a, a, -1, ctx); FLINT_TEST(fq_default_poly_equal(a, b, ctx)); fq_default_poly_set_fq_default(d, t, ctx); fq_default_poly_scalar_mul_fq_default(a, c, t, ctx); fq_default_poly_mul(b, c, d, ctx); FLINT_TEST(fq_default_poly_equal(a, b, ctx)); if (!fq_default_is_zero(t, ctx)) { fq_default_poly_scalar_div_fq_default(a, a, t, ctx); FLINT_TEST(fq_default_poly_equal(a, c, ctx)); } fq_default_poly_set(a, b, ctx); fq_default_poly_scalar_addmul_fq_default(a, c, t, ctx); fq_default_poly_scalar_mul_fq_default(d, c, t, ctx); fq_default_poly_add(d, d, b, ctx); FLINT_TEST(fq_default_poly_equal(a, d, ctx)); fq_default_poly_set(a, b, ctx); fq_default_poly_scalar_addmul_fq_default(a, c, t, ctx); fq_default_poly_scalar_submul_fq_default(a, c, t, ctx); FLINT_TEST(fq_default_poly_equal(a, b, ctx)); fq_default_poly_shift_left(a, b, 1, ctx); fq_default_poly_shift_right(a, a, 1, ctx); FLINT_TEST(fq_default_poly_equal(a, b, ctx)); fq_default_poly_randtest(a, state, n_randint(state, 50), ctx); fq_default_poly_randtest(b, state, n_randint(state, 50), ctx); fq_default_poly_randtest(c, state, n_randint(state, 50), ctx); fq_default_poly_randtest(d, state, n_randint(state, 50), ctx); fq_default_poly_randtest_not_zero(e, state, n_randint(state, 9) + 1, ctx); fq_default_poly_mul(a, a, e, ctx); fq_default_poly_mul(b, b, e, ctx); fq_default_poly_gcd(d, a, b, ctx); FLINT_TEST(fq_default_poly_divides(c, d, e, ctx)); if (!fq_default_poly_is_zero(d, ctx)) { FLINT_TEST(fq_default_poly_divides(c, a, d, ctx)); fq_default_poly_mul(c, c, d, ctx); FLINT_TEST(fq_default_poly_equal(c, a, ctx)); FLINT_TEST(fq_default_poly_divides(c, b, d, ctx)); fq_default_poly_mul(c, c, d, ctx); FLINT_TEST(fq_default_poly_equal(c, b, ctx)); } else { FLINT_TEST(fq_default_poly_is_zero(a, ctx)); FLINT_TEST(fq_default_poly_is_zero(b, ctx)); } fq_default_poly_xgcd(d, c, e, a, b, ctx); fq_default_poly_mul(c, c, a, ctx); fq_default_poly_mul(e, e, b, ctx); fq_default_poly_add(c, c, e, ctx); FLINT_TEST(fq_default_poly_equal(c, d, ctx)); fq_default_poly_randtest(a, state, n_randint(state, 50), ctx); fq_default_poly_randtest_not_zero(b, state, n_randint(state, 50) + 1, ctx); fq_default_poly_randtest(c, state, n_randint(state, 50), ctx); fq_default_poly_randtest(d, state, n_randint(state, 50), ctx); fq_default_poly_randtest(e, state, n_randint(state, 50), ctx); fq_default_poly_rem(e, a, b, ctx); fq_default_poly_divrem(c, d, a, b, ctx); FLINT_TEST(fq_default_poly_equal(d, e, ctx)); fq_default_poly_mul(e, c, b, ctx); fq_default_poly_add(e, e, d, ctx); FLINT_TEST(fq_default_poly_equal(e, a, ctx)); fq_default_clear(t, ctx); fq_default_poly_clear(a, ctx); fq_default_poly_clear(b, ctx); fq_default_poly_clear(c, ctx); fq_default_poly_clear(d, ctx); fq_default_poly_clear(e, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_poly/test/t-set_fmpz_poly.c000066400000000000000000000065331461254215100230640ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fq_default_poly.h" TEST_FUNCTION_START(fq_default_poly_set_fmpz_poly, state) { int i, result; for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_poly_t fq_poly1, fq_poly2; fmpz_poly_t poly; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fq_default_poly_init(fq_poly1, ctx); fq_default_poly_init(fq_poly2, ctx); fmpz_poly_init(poly); fq_default_poly_one(fq_poly1, ctx); fmpz_poly_one(poly); fq_default_poly_set_fmpz_poly(fq_poly2, poly, ctx); result = fq_default_poly_equal(fq_poly1, fq_poly2, ctx); if (!result) { flint_printf("Polynomials not equal\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(poly); fq_default_poly_clear(fq_poly1, ctx); fq_default_poly_clear(fq_poly2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_poly_t fq_poly1, fq_poly2; fmpz_poly_t poly; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 16, "x"); fq_default_poly_init(fq_poly1, ctx); fq_default_poly_init(fq_poly2, ctx); fmpz_poly_init(poly); fq_default_poly_one(fq_poly1, ctx); fmpz_poly_one(poly); fq_default_poly_set_fmpz_poly(fq_poly2, poly, ctx); result = fq_default_poly_equal(fq_poly1, fq_poly2, ctx); if (!result) { flint_printf("Polynomials not equal\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(poly); fq_default_poly_clear(fq_poly1, ctx); fq_default_poly_clear(fq_poly2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } for (i = 0; i < 1 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_poly_t fq_poly1, fq_poly2; fmpz_poly_t poly; fmpz_t p; fmpz_init(p); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fq_default_poly_init(fq_poly1, ctx); fq_default_poly_init(fq_poly2, ctx); fmpz_poly_init(poly); fq_default_poly_one(fq_poly1, ctx); fmpz_poly_one(poly); fq_default_poly_set_fmpz_poly(fq_poly2, poly, ctx); result = fq_default_poly_equal(fq_poly1, fq_poly2, ctx); if (!result) { flint_printf("Polynomials not equal\n"); fflush(stdout); flint_abort(); } fmpz_poly_clear(poly); fq_default_poly_clear(fq_poly1, ctx); fq_default_poly_clear(fq_poly2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_poly_factor.h000066400000000000000000000507101461254215100203110ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_DEFAULT_POLY_FACTOR_H #define FQ_DEFAULT_POLY_FACTOR_H #ifdef FQ_DEFAULT_POLY_FACTOR_INLINES_C #define FQ_DEFAULT_POLY_FACTOR_INLINE #else #define FQ_DEFAULT_POLY_FACTOR_INLINE static inline #endif #include "nmod_poly_factor.h" #include "fmpz_mod_poly_factor.h" #include "fq_poly_factor.h" #include "fq_nmod_poly_factor.h" #include "fq_zech_poly_factor.h" #include "fq_default_poly.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions *********************************************************/ typedef union fq_default_poly_factor_struct { fq_poly_factor_t fq; fq_nmod_poly_factor_t fq_nmod; fq_zech_poly_factor_t fq_zech; nmod_poly_factor_t nmod; fmpz_mod_poly_factor_t fmpz_mod; } fq_default_poly_factor_struct; typedef fq_default_poly_factor_struct fq_default_poly_factor_t[1]; FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_init(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_init(fac->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_init(fac->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_init(fac->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { fmpz_mod_poly_factor_init(fac->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_init(fac->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_clear(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_clear(fac->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_clear(fac->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_clear(fac->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_clear(fac->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_clear(fac->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_realloc(fq_default_poly_factor_t fac, slong alloc, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_realloc(fac->fq_zech, alloc, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_realloc(fac->fq_nmod, alloc, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_realloc(fac->nmod, alloc); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_realloc(fac->fmpz_mod, alloc, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_realloc(fac->fq, alloc, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_fit_length(fq_default_poly_factor_t fac, slong len, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_fit_length(fac->fq_zech, len, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_fit_length(fac->fq_nmod, len, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_fit_length(fac->nmod, len); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_fit_length(fac->fmpz_mod, len, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_fit_length(fac->fq, len, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE slong fq_default_poly_factor_length(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fac->fq_zech->num; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fac->fq_nmod->num; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return fac->nmod->num; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fac->fmpz_mod->num; } else { return fac->fq->num; } } FQ_DEFAULT_POLY_FACTOR_INLINE slong fq_default_poly_factor_exp(fq_default_poly_factor_t fac, slong i, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fac->fq_zech->exp[i]; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fac->fq_nmod->exp[i]; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return fac->nmod->exp[i]; } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fac->fmpz_mod->exp[i]; } else { return fac->fq->exp[i]; } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_set(fq_default_poly_factor_t res, const fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_set(res->fq_zech, fac->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_set(res->fq_nmod, fac->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_set(res->nmod, fac->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_set(res->fmpz_mod, fac->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_set(res->fq, fac->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_insert(fq_default_poly_factor_t fac, const fq_default_poly_t poly, slong exp, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_insert(fac->fq_zech, poly->fq_zech, exp, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_insert(fac->fq_nmod, poly->fq_nmod, exp, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_insert(fac->nmod, poly->nmod, exp); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_insert(fac->fmpz_mod, poly->fmpz_mod, exp, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_insert(fac->fq, poly->fq, exp, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_get_poly(fq_default_poly_t poly, const fq_default_poly_factor_t fac, slong i, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_get_poly(poly->fq_zech, fac->fq_zech, i, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_get_poly(poly->fq_nmod, fac->fq_nmod, i, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_get_poly(poly->nmod, fac->nmod, i); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_get_poly(poly->fmpz_mod, fac->fmpz_mod, i, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_get_poly(poly->fq, fac->fq, i, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_print(const fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_print(fac->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_print(fac->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_print(fac->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_print(fac->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_print(fac->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_print_pretty(const fq_default_poly_factor_t fac, const char * var, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_print_pretty(fac->fq_zech, var, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_print_pretty(fac->fq_nmod, var, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_print_pretty(fac->nmod, var); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_print_pretty(fac->fmpz_mod, var, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_print_pretty(fac->fq, var, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_concat(fq_default_poly_factor_t res, const fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_concat(res->fq_zech, fac->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_concat(res->fq_nmod, fac->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_concat(res->nmod, fac->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_concat(res->fmpz_mod, fac->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_concat(res->fq, fac->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_pow(fq_default_poly_factor_t fac, slong exp, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_pow(fac->fq_zech, exp, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_pow(fac->fq_nmod, exp, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_pow(fac->nmod, exp); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_pow(fac->fmpz_mod, exp, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_pow(fac->fq, exp, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE int fq_default_poly_is_squarefree(const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_is_squarefree(f->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_is_squarefree(f->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_is_squarefree(f->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_is_squarefree(f->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_is_squarefree(f->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_squarefree(fq_default_poly_factor_t res, const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_squarefree(res->fq_zech, f->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_squarefree(res->fq_nmod, f->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_squarefree(res->nmod, f->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_squarefree(res->fmpz_mod, f->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_squarefree(res->fq, f->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE int fq_default_poly_is_irreducible(const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { return fq_zech_poly_is_irreducible(f->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { return fq_nmod_poly_is_irreducible(f->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { return nmod_poly_is_irreducible(f->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { return fmpz_mod_poly_is_irreducible(f->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { return fq_poly_is_irreducible(f->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_distinct_deg(fq_default_poly_factor_t res, const fq_default_poly_t poly, slong * const * degs, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_distinct_deg(res->fq_zech, poly->fq_zech, degs, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_distinct_deg(res->fq_nmod, poly->fq_nmod, degs, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_distinct_deg(res->nmod, poly->nmod, degs); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_distinct_deg(res->fmpz_mod, poly->fmpz_mod, degs, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_distinct_deg(res->fq, poly->fq, degs, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_equal_deg(fq_default_poly_factor_t factors, const fq_default_poly_t pol, slong d, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_equal_deg(factors->fq_zech, pol->fq_zech, d, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_equal_deg(factors->fq_nmod, pol->fq_nmod, d, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_factor_equal_deg(factors->nmod, pol->nmod, d); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor_equal_deg(factors->fmpz_mod, pol->fmpz_mod, d, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_factor_equal_deg(factors->fq, pol->fq, d, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor(fq_default_poly_factor_t result, fq_default_t leading_coeff, const fq_default_poly_t input, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor(result->fq_zech, leading_coeff->fq_zech, input->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor(result->fq_nmod, leading_coeff->fq_nmod, input->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { leading_coeff->nmod = nmod_poly_factor(result->nmod, input->nmod); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_factor(result->fmpz_mod, input->fmpz_mod, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); if (input->fmpz_mod->length < 1) fmpz_zero(leading_coeff->fmpz_mod); else fmpz_set(leading_coeff->fmpz_mod, input->fmpz_mod->coeffs + input->fmpz_mod->length - 1); } else { fq_poly_factor(result->fq, leading_coeff->fq, input->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_split_single(fq_default_poly_t linfactor, const fq_default_poly_t input, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_factor_split_single(linfactor->fq_zech, input->fq_zech, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_factor_split_single(linfactor->fq_nmod, input->fq_nmod, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { flint_throw(FLINT_ERROR, "operation not implemented"); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { flint_throw(FLINT_ERROR, "operation not implemented"); } else { fq_poly_factor_split_single(linfactor->fq, input->fq, FQ_DEFAULT_CTX_FQ(ctx)); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_roots(fq_default_poly_factor_t r, const fq_default_poly_t f, int with_multiplicity, const fq_default_ctx_t ctx) { if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_ZECH) { fq_zech_poly_roots(r->fq_zech, f->fq_zech, with_multiplicity, FQ_DEFAULT_CTX_FQ_ZECH(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FQ_NMOD) { fq_nmod_poly_roots(r->fq_nmod, f->fq_nmod, with_multiplicity, FQ_DEFAULT_CTX_FQ_NMOD(ctx)); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_NMOD) { nmod_poly_roots(r->nmod, f->nmod, with_multiplicity); } else if (_FQ_DEFAULT_TYPE(ctx) == _FQ_DEFAULT_FMPZ_MOD) { fmpz_mod_poly_roots(r->fmpz_mod, f->fmpz_mod, with_multiplicity, FQ_DEFAULT_CTX_FMPZ_MOD(ctx)); } else { fq_poly_roots(r->fq, f->fq, with_multiplicity, FQ_DEFAULT_CTX_FQ(ctx)); } } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_default_poly_factor/000077500000000000000000000000001461254215100201355ustar00rootroot00000000000000flint-3.1.3/src/fq_default_poly_factor/inlines.c000066400000000000000000000010521461254215100217400ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_POLY_FACTOR_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fq_default.h" #include "fq_default_poly.h" #include "fq_default_poly_factor.h" flint-3.1.3/src/fq_default_poly_factor/test/000077500000000000000000000000001461254215100211145ustar00rootroot00000000000000flint-3.1.3/src/fq_default_poly_factor/test/main.c000066400000000000000000000015231461254215100222050ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-init.c" #include "t-inlines.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_default_poly_factor_init), TEST_FUNCTION(fq_default_poly_factor_inlines) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_default_poly_factor/test/t-init.c000066400000000000000000000045141461254215100224700ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default_poly_factor.h" TEST_FUNCTION_START(fq_default_poly_factor_init, state) { int i; for (i = 0; i < 30 * flint_test_multiplier(); i++) { fq_default_ctx_t ctx; fq_default_poly_factor_t fq_poly_fac; fq_default_poly_t poly; fq_default_t c; fmpz_t p; fmpz_init(p); fmpz_set_ui(p, 3); fq_default_ctx_init(ctx, p, 3, "x"); fq_default_poly_factor_init(fq_poly_fac, ctx); fq_default_poly_init(poly, ctx); fq_default_init(c, ctx); while (fq_default_poly_is_zero(poly, ctx)) fq_default_poly_randtest(poly, state, n_randint(state, 10), ctx); fq_default_poly_factor(fq_poly_fac, c, poly, ctx); fq_default_clear(c, ctx); fq_default_poly_factor_clear(fq_poly_fac, ctx); fq_default_ctx_clear(ctx); fq_default_ctx_init(ctx, p, 16, "x"); fq_default_poly_factor_init(fq_poly_fac, ctx); fq_default_poly_init(poly, ctx); fq_default_init(c, ctx); while (fq_default_poly_is_zero(poly, ctx)) fq_default_poly_randtest(poly, state, n_randint(state, 10), ctx); fq_default_poly_factor(fq_poly_fac, c, poly, ctx); fq_default_clear(c, ctx); fq_default_poly_factor_clear(fq_poly_fac, ctx); fq_default_ctx_clear(ctx); fmpz_set_str(p, "73786976294838206473", 10); fq_default_ctx_init(ctx, p, 1, "x"); fq_default_poly_factor_init(fq_poly_fac, ctx); fq_default_poly_init(poly, ctx); fq_default_init(c, ctx); while (fq_default_poly_is_zero(poly, ctx)) fq_default_poly_randtest(poly, state, n_randint(state, 10), ctx); fq_default_poly_factor(fq_poly_fac, c, poly, ctx); fq_default_clear(c, ctx); fq_default_poly_factor_clear(fq_poly_fac, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_default_poly_factor/test/t-inlines.c000066400000000000000000000043611461254215100231660ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_default_poly_factor.h" TEST_FUNCTION_START(fq_default_poly_factor_inlines, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; slong deg; fq_default_ctx_t ctx; fq_default_t t; fq_default_poly_t a, b, c, d, e; fq_default_poly_factor_t f; fmpz_init(p); fmpz_randprime(p, state, n_randint(state, 2) ? 40 : 80, 1); deg = n_randint(state, 3) + 1; fq_default_ctx_init(ctx, p, deg, "a"); fq_default_init(t, ctx); fq_default_poly_init(a, ctx); fq_default_poly_init(b, ctx); fq_default_poly_init(c, ctx); fq_default_poly_init(d, ctx); fq_default_poly_init(e, ctx); fq_default_poly_factor_init(f, ctx); fq_default_poly_one(a, ctx); for (j = n_randint(state, 5); j > 0; j--) { fq_default_poly_randtest_not_zero(b, state, 5, ctx); fq_default_poly_mul(a, a, b, ctx); } fq_default_poly_factor(f, t, a, ctx); fq_default_poly_set_fq_default(b, t, ctx); for (j = fq_default_poly_factor_length(f, ctx) - 1; j >= 0; j--) { fq_default_poly_factor_get_poly(c, f, j, ctx); FLINT_TEST(fq_default_poly_is_irreducible(c, ctx)); fq_default_poly_pow(d, c, fq_default_poly_factor_exp(f, j, ctx), ctx); fq_default_poly_mul(b, b, d, ctx); } FLINT_TEST(fq_default_poly_equal(a, b, ctx)); fq_default_clear(t, ctx); fq_default_poly_clear(a, ctx); fq_default_poly_clear(b, ctx); fq_default_poly_clear(c, ctx); fq_default_poly_clear(d, ctx); fq_default_poly_clear(e, ctx); fq_default_poly_factor_clear(f, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_embed.h000066400000000000000000000015651461254215100153440ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_EMBED_H #define FQ_EMBED_H #ifdef FQ_EMBED_INLINES_C #define FQ_EMBED_INLINE #define FQ_EMBED_TEMPLATES_INLINE #else #define FQ_EMBED_INLINE static inline #define FQ_EMBED_TEMPLATES_INLINE static inline #endif #include "fq_types.h" #define T fq #define B fmpz_mod #include "fq_embed_templates.h" #undef B #undef T void fq_modulus_pow_series_inv(fmpz_mod_poly_t res, const fq_ctx_t ctx, slong trunc); void fq_modulus_derivative_inv(fq_t m_prime, fq_t m_prime_inv, const fq_ctx_t ctx); #endif flint-3.1.3/src/fq_embed/000077500000000000000000000000001461254215100151645ustar00rootroot00000000000000flint-3.1.3/src/fq_embed/derivative_inv.c000066400000000000000000000016641461254215100203550ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_embed.h" void fq_modulus_derivative_inv(fq_t m_prime, fq_t m_prime_inv, const fq_ctx_t ctx) { fmpz_mod_poly_t tmp; fmpz_mod_poly_init(tmp, ctx->ctxp); fmpz_mod_poly_derivative(tmp, fq_ctx_modulus(ctx), ctx->ctxp); fmpz_poly_fit_length(m_prime, tmp->length); _fmpz_vec_set(m_prime->coeffs, tmp->coeffs, tmp->length); _fmpz_poly_set_length(m_prime, tmp->length); fq_inv(m_prime_inv, m_prime, ctx); fmpz_mod_poly_clear(tmp, ctx->ctxp); } flint-3.1.3/src/fq_embed/embed.c000066400000000000000000000036141461254215100164100ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #include "fq_embed.h" void fq_embed_gens(fq_t gen_sub, fq_t gen_sup, fmpz_mod_poly_t minpoly, const fq_ctx_t sub_ctx, const fq_ctx_t sup_ctx) { if (fq_ctx_degree(sub_ctx) == 1) { fq_gen(gen_sub, sub_ctx); fq_set(gen_sup, gen_sub, sup_ctx); } else { _fq_embed_gens_naive(gen_sub, gen_sup, minpoly, sub_ctx, sup_ctx); } } void _fq_embed_gens_naive(fq_t gen_sub, fq_t gen_sup, fmpz_mod_poly_t minpoly, const fq_ctx_t sub_ctx, const fq_ctx_t sup_ctx) { fq_poly_t modulus, fact; flint_rand_t state; fq_poly_init(modulus, sup_ctx); fq_poly_init(fact, sup_ctx); fq_poly_set_fmpz_mod_poly(modulus, fq_ctx_modulus(sub_ctx), sup_ctx); flint_randinit(state); /* Get one linear factor of sub_ctx->modulus in sup_ctx */ while (fq_poly_degree(modulus, sup_ctx) != 1) { while (!fq_poly_factor_equal_deg_prob(fact, state, modulus, 1, sup_ctx)) { }; fq_poly_set(modulus, fact, sup_ctx); } fq_gen(gen_sub, sub_ctx); fq_set(gen_sup, modulus->coeffs, sup_ctx); fq_neg(gen_sup, gen_sup, sup_ctx); fmpz_mod_poly_set(minpoly, fq_ctx_modulus(sub_ctx), sub_ctx->ctxp); fq_poly_clear(modulus, sup_ctx); fq_poly_clear(fact, sup_ctx); } flint-3.1.3/src/fq_embed/matrices.c000066400000000000000000000161641461254215100171470ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_poly.h" #include "fq_embed.h" void fq_embed_mono_to_dual_matrix(fmpz_mod_mat_t res, const fq_ctx_t ctx) { slong i, j, n = fq_ctx_degree(ctx); fmpz_mod_poly_t ctx_inv_rev, d_ctx; const fmpz_mod_poly_struct *modulus = fq_ctx_modulus(ctx); fmpz_mod_poly_init(ctx_inv_rev, ctx->ctxp); fmpz_mod_poly_init(d_ctx, ctx->ctxp); /* Half of this is precomputed in ctx. Maybe a call to some internal Newton stuff could be enough to double it. */ fq_modulus_pow_series_inv(ctx_inv_rev, ctx, 2*n); fmpz_mod_poly_derivative(d_ctx, modulus, ctx->ctxp); fmpz_mod_poly_reverse(d_ctx, d_ctx, n, ctx->ctxp); fmpz_mod_poly_mullow(ctx_inv_rev, ctx_inv_rev, d_ctx, 2*n, ctx->ctxp); fmpz_mod_mat_zero(res, ctx->ctxp); for (i = 0; i < n; i++) for (j = 0; j < n && i+j < ctx_inv_rev->length; j++) fmpz_mod_mat_set_entry(res, i, j, ctx_inv_rev->coeffs + i + j, ctx->ctxp); fmpz_mod_poly_clear(ctx_inv_rev, ctx->ctxp); fmpz_mod_poly_clear(d_ctx, ctx->ctxp); } void fq_embed_dual_to_mono_matrix(fmpz_mod_mat_t res, const fq_ctx_t ctx) { slong i, j, n = fq_ctx_degree(ctx); fq_t d_ctx, d_ctx_inv; const fmpz_mod_poly_struct *modulus = fq_ctx_modulus(ctx); fmpz_mod_mat_t mul_mat, tmp; fq_init(d_ctx, ctx); fq_init(d_ctx_inv, ctx); fmpz_mod_mat_init(mul_mat, n, n, ctx->ctxp); fmpz_mod_mat_init(tmp, n, n, ctx->ctxp); fmpz_mod_mat_zero(tmp, ctx->ctxp); for (i = 0; i < n; i++) for (j = 0; j < n - i; j++) fmpz_mod_mat_set_entry(tmp, i, j, modulus->coeffs + i + j + 1, ctx->ctxp); fq_modulus_derivative_inv(d_ctx, d_ctx_inv, ctx); fq_embed_mul_matrix(mul_mat, d_ctx_inv, ctx); fmpz_mod_mat_mul(res, mul_mat, tmp, ctx->ctxp); fq_clear(d_ctx, ctx); fq_clear(d_ctx_inv, ctx); fmpz_mod_mat_clear(mul_mat, ctx->ctxp); fmpz_mod_mat_clear(tmp, ctx->ctxp); } /* Given: - a context `sup_ctx` defining a field K of degree n, - a context `sub_ctx` defining a subfield k of degree m|n, - the n×m change-of-basis matrix from k to K, Return the m×n matrix of the trace from K to k. If m=n, res is the inverse of basis. */ void fq_embed_trace_matrix(fmpz_mod_mat_t res, const fmpz_mod_mat_t basis, const fq_ctx_t sub_ctx, const fq_ctx_t sup_ctx) { slong m = fmpz_mod_mat_ncols(basis, sub_ctx->ctxp); slong n = fmpz_mod_mat_nrows(basis, sub_ctx->ctxp); fmpz_mod_mat_t m2d, d2m, tmp; fmpz_mod_mat_init(m2d, n, n, sub_ctx->ctxp); fmpz_mod_mat_init(d2m, m, m, sub_ctx->ctxp); fmpz_mod_mat_init(tmp, m, n, sub_ctx->ctxp); fq_embed_mono_to_dual_matrix(m2d, sup_ctx); fmpz_mod_mat_transpose(res, basis, sub_ctx->ctxp); fq_embed_dual_to_mono_matrix(d2m, sub_ctx); fmpz_mod_mat_mul(tmp, res, m2d, sub_ctx->ctxp); fmpz_mod_mat_mul(res, d2m, tmp, sub_ctx->ctxp); fmpz_mod_mat_clear(m2d, sub_ctx->ctxp); fmpz_mod_mat_clear(d2m, sub_ctx->ctxp); fmpz_mod_mat_clear(tmp, sub_ctx->ctxp); } void fq_embed_matrices(fmpz_mod_mat_t embed, fmpz_mod_mat_t project, const fq_t gen_sub, const fq_ctx_t sub_ctx, const fq_t gen_sup, const fq_ctx_t sup_ctx, const fmpz_mod_poly_t gen_minpoly) { const fmpz_mod_ctx_struct * ctxp = sub_ctx->ctxp; slong m = fq_ctx_degree(sub_ctx); slong n = fq_ctx_degree(sup_ctx); slong d = n / m; fmpz_t invd; fq_ctx_t gen_ctx; fmpz_mod_poly_t gen_minpoly_cp; fmpz_mod_mat_t gen2sub, sub2gen, gen2sup, sup2gen; /* Is there any good reason why the modulus argument to fq_ctx_init_modulus is not const? */ fmpz_mod_poly_init(gen_minpoly_cp, ctxp); fmpz_mod_poly_set(gen_minpoly_cp, gen_minpoly, ctxp); fmpz_init(invd); fq_ctx_init_modulus(gen_ctx, gen_minpoly_cp, ctxp, "x"); fmpz_mod_mat_init(gen2sub, m, m, ctxp); fmpz_mod_mat_init(sub2gen, m, m, ctxp); fmpz_mod_mat_init(gen2sup, n, m, ctxp); fmpz_mod_mat_init(sup2gen, m, n, ctxp); /* Gen -> Sub */ fq_embed_composition_matrix(gen2sub, gen_sub, sub_ctx); /* Sub -> Gen */ fq_embed_trace_matrix(sub2gen, gen2sub, gen_ctx, sub_ctx); /* Gen -> Sup */ fq_embed_composition_matrix_sub(gen2sup, gen_sup, sup_ctx, m); /* Sup -> Gen (trace) */ fq_embed_trace_matrix(sup2gen, gen2sup, gen_ctx, sup_ctx); /* Correct the projection Sup -> Gen */ /* If this is an isomorphism, there is no need for correction */ if (d == 1) {} /* If the extension degree is invertible mod p, multiply trace by 1/d */ else if (fmpz_set_si(invd, d), fmpz_invmod(invd, invd, fmpz_mod_ctx_modulus(ctxp))) { fmpz_mod_mat_scalar_mul_fmpz(sup2gen, sup2gen, invd, ctxp); } /* Otherwise pre-multiply by an element of trace equal to 1 */ else { int i; fq_t mul, trace; fmpz_mod_mat_t column, tvec, mat_mul, tmp; fq_init(mul, sup_ctx); fq_init(trace, sup_ctx); fmpz_mod_mat_init(tvec, n, 1, ctxp); fmpz_mod_mat_init(mat_mul, n, n, ctxp); fmpz_mod_mat_init(tmp, m, n, ctxp); /* Look for a non-zero column in sup2gen (we know it has full rank, so first row is non-null) */ for (i = 1; i < n; i++) { if (!fmpz_is_zero(fmpz_mod_mat_entry(sup2gen, 0, i))) break; } /* Set mul to x^i */ fq_gen(mul, sup_ctx); fq_pow_ui(mul, mul, i, sup_ctx); /* Set trace to its trace */ fmpz_mod_mat_window_init(column, sup2gen, 0, i, m, i+1, ctxp); fmpz_mod_mat_mul(tvec, gen2sup, column, ctxp); fq_set_fmpz_mod_mat(trace, tvec, sup_ctx); /* Get an element of trace 1 */ fq_div(mul, mul, trace, sup_ctx); /* Correct the matrix */ fq_embed_mul_matrix(mat_mul, mul, sup_ctx); fmpz_mod_mat_mul(tmp, sup2gen, mat_mul, ctxp); fmpz_mod_mat_swap(tmp, sup2gen, ctxp); fmpz_mod_mat_clear(tmp, ctxp); fmpz_mod_mat_clear(mat_mul, ctxp); fmpz_mod_mat_clear(tvec, ctxp); fmpz_mod_mat_window_clear(column, ctxp); fq_clear(mul, sup_ctx); fq_clear(trace, sup_ctx); } fmpz_mod_mat_mul(embed, gen2sup, sub2gen, ctxp); fmpz_mod_mat_mul(project, gen2sub, sup2gen, ctxp); fmpz_mod_mat_clear(gen2sub, ctxp); fmpz_mod_mat_clear(sub2gen, ctxp); fmpz_mod_mat_clear(gen2sup, ctxp); fmpz_mod_mat_clear(sup2gen, ctxp); fq_ctx_clear(gen_ctx); fmpz_clear(invd); fmpz_mod_poly_clear(gen_minpoly_cp, ctxp); } flint-3.1.3/src/fq_embed/mul_matrix.c000066400000000000000000000035301461254215100175120ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_mat.h" #include "fq.h" #include "fq_embed.h" void fq_embed_mul_matrix(fmpz_mod_mat_t matrix, const fq_t gen, const fq_ctx_t ctx) { slong i, j, len = fq_ctx_degree(ctx); fmpz_t lead; /* This is usually 1, unless the context is non-monic */ fmpz_init(lead); fmpz_invmod(lead, ctx->modulus->coeffs + len, fq_ctx_prime(ctx)); for (i = 0; i < gen->length; i++) fmpz_set(fmpz_mod_mat_entry(matrix, i, 0), gen->coeffs + i); for (i = gen->length; i < len; i++) fmpz_zero(fmpz_mod_mat_entry(matrix, i, 0)); /* M[i, j] = M[i - 1, j - 1] - M[len - 1, j - 1] * lead * ctx->modulus->coeffs[i] */ for (j = 1; j < len; j++) { fmpz_mul(fmpz_mod_mat_entry(matrix, len - 1, j), fmpz_mod_mat_entry(matrix, len - 1, j - 1), lead); for (i = 0; i < len; i++) { fmpz_mul(fmpz_mod_mat_entry(matrix, i, j), fmpz_mod_mat_entry(matrix, len - 1, j), ctx->modulus->coeffs + i); if (i > 0) fmpz_sub(fmpz_mod_mat_entry(matrix, i, j), fmpz_mod_mat_entry(matrix, i, j), fmpz_mod_mat_entry(matrix, i - 1, j - 1)); fmpz_neg(fmpz_mod_mat_entry(matrix, i, j), fmpz_mod_mat_entry(matrix, i, j)); } } _fmpz_mod_mat_reduce(matrix, ctx->ctxp); fmpz_clear(lead); } flint-3.1.3/src/fq_embed/pow_series_inv.c000066400000000000000000000012461461254215100203660ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_embed.h" void fq_modulus_pow_series_inv(fmpz_mod_poly_t res, const fq_ctx_t ctx, slong trunc) { fmpz_mod_poly_reverse(res, fq_ctx_modulus(ctx), fq_ctx_degree(ctx) + 1, ctx->ctxp); fmpz_mod_poly_inv_series(res, res, trunc, ctx->ctxp); } flint-3.1.3/src/fq_embed/test/000077500000000000000000000000001461254215100161435ustar00rootroot00000000000000flint-3.1.3/src/fq_embed/test/main.c000066400000000000000000000020351461254215100172330ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-composition_matrix.c" #include "t-embed.c" #include "t-embed_matrices.c" #include "t-mono_dual_matrix.c" #include "t-mul_matrix.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_embed_composition_matrix), TEST_FUNCTION(fq_embed), TEST_FUNCTION(fq_embed_matrices), TEST_FUNCTION(fq_embed_mono_dual_matrix), TEST_FUNCTION(fq_embed_mul_matrix) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_embed/test/t-composition_matrix.c000066400000000000000000000050561461254215100225050ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mat.h" #include "fq.h" #include "fq_embed.h" TEST_FUNCTION_START(fq_embed_composition_matrix, state) { int i; /* Check that Mat(a^p) = Mat(x^p) * Mat(a) for random a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_ctx_t ctx; fq_t frob, a; fmpz_mod_mat_t mat_frob, mat_a, mat_aq, res; slong d; while (fq_ctx_init_randtest(ctx, state, 1), d = fq_ctx_degree(ctx), d == 1) { fq_ctx_clear(ctx); } fq_init(frob, ctx); fq_init(a, ctx); fmpz_mod_mat_init(mat_frob, d, d, ctx->ctxp); fmpz_mod_mat_init(mat_a, d, d, ctx->ctxp); fmpz_mod_mat_init(mat_aq, d, d, ctx->ctxp); fmpz_mod_mat_init(res, d, d, ctx->ctxp); fq_gen(frob, ctx); fq_pow(frob, frob, fq_ctx_prime(ctx), ctx); fq_embed_composition_matrix(mat_frob, frob, ctx); fq_randtest(a, state, ctx); fq_embed_composition_matrix(mat_a, a, ctx); fmpz_mod_mat_mul(res, mat_frob, mat_a, ctx->ctxp); fq_pow(a, a, fq_ctx_prime(ctx), ctx); fq_embed_composition_matrix(mat_aq, a, ctx); if (!fmpz_mod_mat_equal(res, mat_aq, ctx->ctxp)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), fq_ctx_print(ctx), flint_printf("\n"); flint_printf("x^q: "), fq_print_pretty(frob, ctx), flint_printf("\n"); flint_printf("M(x^q)*M(a) = M(a^q)\n"), fmpz_mod_mat_print_pretty(mat_frob, ctx->ctxp), flint_printf("\n"), fmpz_mod_mat_print_pretty(mat_a, ctx->ctxp), flint_printf("\n"), fmpz_mod_mat_print_pretty(mat_aq, ctx->ctxp), flint_printf("\n"), fmpz_mod_mat_print_pretty(res, ctx->ctxp), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(mat_frob, ctx->ctxp); fmpz_mod_mat_clear(mat_a, ctx->ctxp); fmpz_mod_mat_clear(mat_aq, ctx->ctxp); fmpz_mod_mat_clear(res, ctx->ctxp); fq_clear(frob, ctx); fq_clear(a, ctx); fq_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_embed/test/t-embed.c000066400000000000000000000045751461254215100176370ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_poly.h" #include "fq_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq #define CAP_T FQ #define B fmpz_mod #ifdef T #ifdef B #include "templates.h" TEST_FUNCTION_START(fq_embed, state) { int i; /* Check isomorphism to self */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, ev_a, ev_b; TEMPLATE(B, poly_t) minpoly; TEMPLATE(T, poly_t) minpoly_fq; TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); TEMPLATE(T, init) (a, ctx); TEMPLATE(T, init) (b, ctx); TEMPLATE(T, init) (ev_a, ctx); TEMPLATE(T, init) (ev_b, ctx); TEMPLATE(B, poly_init) (minpoly, ctx->ctxp); TEMPLATE(T, poly_init) (minpoly_fq, ctx); TEMPLATE(T, embed_gens) (a, b, minpoly, ctx, ctx); TEMPLATE4(T, poly_set, B, poly)(minpoly_fq, minpoly, ctx); TEMPLATE3(T, poly_evaluate, T)(ev_a, minpoly_fq, a, ctx); TEMPLATE3(T, poly_evaluate, T)(ev_b, minpoly_fq, b, ctx); if (!TEMPLATE(T, is_zero)(ev_a, ctx) || !TEMPLATE(T, is_zero)(ev_b, ctx)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), TEMPLATE(T, ctx_print)(ctx), flint_printf("\n"); flint_printf("a: "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b: "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("minpoly: "), TEMPLATE(B, poly_print_pretty)(minpoly, "x", ctx->ctxp), flint_printf("\n"); flint_abort(); } TEMPLATE(T, clear) (a, ctx); TEMPLATE(T, clear) (b, ctx); TEMPLATE(T, clear) (ev_a, ctx); TEMPLATE(T, clear) (ev_b, ctx); TEMPLATE(B, poly_clear) (minpoly, ctx->ctxp); TEMPLATE(T, poly_clear) (minpoly_fq, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif #endif #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_embed/test/t-embed_matrices.c000066400000000000000000000110011461254215100215040ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_mat.h" #include "fq.h" #include "fq_embed.h" TEST_FUNCTION_START(fq_embed_matrices, state) { slong ix, jx; /* Check that isomorphism to self gives identity matrices */ for (ix = 0; ix < 20 * flint_test_multiplier(); ix++) { fq_ctx_t ctx; fq_t gen; const fmpz_mod_poly_struct *modulus; fmpz_mod_mat_t embed, project, one; slong d; fq_ctx_init_randtest(ctx, state, 3); d = fq_ctx_degree(ctx); modulus = fq_ctx_modulus(ctx); fq_init(gen, ctx); fq_gen(gen, ctx); fq_pow(gen, gen, fq_ctx_prime(ctx), ctx); fmpz_mod_mat_init(embed, d, d, ctx->ctxp); fmpz_mod_mat_init(project, d, d, ctx->ctxp); fmpz_mod_mat_init(one, d, d, ctx->ctxp); fq_embed_matrices(embed, project, gen, ctx, gen, ctx, modulus); fmpz_mod_mat_one(one, ctx->ctxp); if (!fmpz_mod_mat_equal(embed, one, ctx->ctxp) || !fmpz_mod_mat_equal(project, one, ctx->ctxp)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), fq_ctx_print(ctx), flint_printf("\n"); flint_printf("x^p: "), fq_print_pretty(gen, ctx), flint_printf("\n"); flint_printf("Embed\n"), fmpz_mod_mat_print_pretty(embed, ctx->ctxp), flint_printf("\nProject\n"), fmpz_mod_mat_print_pretty(project, ctx->ctxp), flint_printf("\n"); flint_abort(); } fmpz_mod_mat_clear(embed, ctx->ctxp); fmpz_mod_mat_clear(project, ctx->ctxp); fmpz_mod_mat_clear(one, ctx->ctxp); fq_clear(gen, ctx); fq_ctx_clear(ctx); } /* Check random emebedding (degrees 1..5) */ for (ix = 1; ix < 6; ix++) { for (jx = 0; jx < FLINT_MAX(flint_test_multiplier(), 1); jx++) { fq_ctx_t ctx1, ctx2; fq_t gen1, gen2; fmpz_mod_poly_t minpoly; fmpz_mod_poly_t modulus2; fmpz_mod_mat_t embed, project, comp, one; slong m, n; while (fq_ctx_init_randtest(ctx1, state, 3), m = fq_ctx_degree(ctx1), m == 1) { fq_ctx_clear(ctx1); } n = m * ix; fmpz_mod_poly_init(modulus2, ctx1->ctxp); fmpz_mod_poly_randtest_monic_irreducible(modulus2, state, n+1, ctx1->ctxp); fq_ctx_init_modulus(ctx2, modulus2, ctx1->ctxp, "X"); fq_init(gen1, ctx1); fq_init(gen2, ctx2); fmpz_mod_poly_init(minpoly, ctx1->ctxp); fq_embed_gens(gen1, gen2, minpoly, ctx1, ctx2); fmpz_mod_mat_init(embed, n, m, ctx1->ctxp); fmpz_mod_mat_init(project, m, n, ctx1->ctxp); fmpz_mod_mat_init(comp, m, m, ctx1->ctxp); fmpz_mod_mat_init(one, m, m, ctx1->ctxp); fq_embed_matrices(embed, project, gen1, ctx1, gen2, ctx2, minpoly); fmpz_mod_mat_mul(comp, project, embed, ctx1->ctxp); fmpz_mod_mat_one(one, ctx1->ctxp); if (!fmpz_mod_mat_equal(comp, one, ctx1->ctxp)) { flint_printf("FAIL:\n\n"); flint_printf("CTX 1\n"), fq_ctx_print(ctx1), flint_printf("\n"); flint_printf("CTX 2\n"), fq_ctx_print(ctx2), flint_printf("\n"); flint_printf("Embed\n"), fmpz_mod_mat_print_pretty(embed, ctx1->ctxp), flint_printf("\nProject\n"), fmpz_mod_mat_print_pretty(project, ctx1->ctxp), flint_printf("\nComposition\n"), fmpz_mod_mat_print_pretty(comp, ctx1->ctxp), flint_printf("\n"); flint_abort(); } fmpz_mod_mat_clear(embed, ctx1->ctxp); fmpz_mod_mat_clear(project, ctx1->ctxp); fmpz_mod_mat_clear(comp, ctx1->ctxp); fmpz_mod_mat_clear(one, ctx1->ctxp); fmpz_mod_poly_clear(minpoly, ctx1->ctxp); fmpz_mod_poly_clear(modulus2, ctx1->ctxp); fq_clear(gen1, ctx1); fq_ctx_clear(ctx1); fq_clear(gen2, ctx2); fq_ctx_clear(ctx2); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_embed/test/t-mono_dual_matrix.c000066400000000000000000000035731461254215100221210ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mat.h" #include "fq.h" #include "fq_embed.h" TEST_FUNCTION_START(fq_embed_mono_dual_matrix, state) { int i; /* Check that the two functions are inverse of one another */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_ctx_t ctx; fmpz_mod_mat_t m2d, d2m, one, two; slong d; fq_ctx_init_randtest(ctx, state, 0); d = fq_ctx_degree(ctx); fmpz_mod_mat_init(m2d, d, d, ctx->ctxp); fmpz_mod_mat_init(d2m, d, d, ctx->ctxp); fmpz_mod_mat_init(one, d, d, ctx->ctxp); fmpz_mod_mat_init(two, d, d, ctx->ctxp); fq_embed_mono_to_dual_matrix(m2d, ctx); fq_embed_dual_to_mono_matrix(d2m, ctx); fmpz_mod_mat_mul(one, m2d, d2m, ctx->ctxp); fmpz_mod_mat_one(two, ctx->ctxp); if (!fmpz_mod_mat_equal(one, two, ctx->ctxp)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), fq_ctx_print(ctx), flint_printf("\n"); flint_printf("Mono -> Dual\n"), fmpz_mod_mat_print_pretty(m2d, ctx->ctxp), flint_printf("\nDual -> Mono\n"), fmpz_mod_mat_print_pretty(d2m, ctx->ctxp), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(m2d, ctx->ctxp); fmpz_mod_mat_clear(d2m, ctx->ctxp); fmpz_mod_mat_clear(one, ctx->ctxp); fmpz_mod_mat_clear(two, ctx->ctxp); fq_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_embed/test/t-mul_matrix.c000066400000000000000000000040671461254215100207400ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mod_mat.h" #include "fq.h" #include "fq_embed.h" TEST_FUNCTION_START(fq_embed_mul_matrix, state) { int i; /* Check that Mat(a^2) = Mat(a)^2 for random a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_ctx_t ctx; fq_t a; fmpz_mod_mat_t mat_a, mat_a_sq, mat_a_a; slong d; fq_ctx_init_randtest(ctx, state, 0); d = fq_ctx_degree(ctx); fq_init(a, ctx); fmpz_mod_mat_init(mat_a, d, d, ctx->ctxp); fmpz_mod_mat_init(mat_a_sq, d, d, ctx->ctxp); fmpz_mod_mat_init(mat_a_a, d, d, ctx->ctxp); fq_randtest(a, state, ctx); fq_embed_mul_matrix(mat_a, a, ctx); fq_mul(a, a, a, ctx); fq_embed_mul_matrix(mat_a_sq, a, ctx); fmpz_mod_mat_mul(mat_a_a, mat_a, mat_a, ctx->ctxp); if (!fmpz_mod_mat_equal(mat_a_a, mat_a_sq, ctx->ctxp)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), fq_ctx_print(ctx), flint_printf("\n"); flint_printf("a^2: "), fq_print_pretty(a, ctx), flint_printf("\n"); flint_printf("M(a)^2 = M(a^2)\n"), fmpz_mod_mat_print_pretty(mat_a, ctx->ctxp), flint_printf("^2\n=\n"), fmpz_mod_mat_print_pretty(mat_a_a, ctx->ctxp), flint_printf("\n=\n"), fmpz_mod_mat_print_pretty(mat_a_sq, ctx->ctxp), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(mat_a, ctx->ctxp); fmpz_mod_mat_clear(mat_a_sq, ctx->ctxp); fmpz_mod_mat_clear(mat_a_a, ctx->ctxp); fq_clear(a, ctx); fq_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_embed_templates.h000066400000000000000000000072731461254215100174240ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #ifdef __cplusplus extern "C" { #endif void TEMPLATE(T, embed_gens)(TEMPLATE(T, t) gen_sub, TEMPLATE(T, t) gen_sup, TEMPLATE(B, poly_t) minpoly, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, ctx_t) sup_ctx); void _TEMPLATE(T, embed_gens_naive)(TEMPLATE(T, t) gen_sub, TEMPLATE(T, t) gen_sup, TEMPLATE(B, poly_t) minpoly, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, ctx_t) sup_ctx); void _TEMPLATE(T, embed_gens_allombert)(TEMPLATE(T, t) gen_sub, TEMPLATE(T, t) gen_sup, TEMPLATE(B, poly_t) minpoly, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, ctx_t) sup_ctx); /* Convert to-from column vectors */ void TEMPLATE(T, embed_matrices)(TEMPLATE(B, mat_t) embed, TEMPLATE(B, mat_t) project, const TEMPLATE(T, t) gen_sub, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, t) gen_sup, const TEMPLATE(T, ctx_t) sup_ctx, const TEMPLATE(B, poly_t) gen_minpoly); /* Given: - a context `sup_ctx` defining a field K of degree n, - a context `sub_ctx` defining a subfield k of degree m|n, - the n×m change-of-basis matrix from k to K, Return the m×n matrix of the trace from K to k. If m=n, res is the inverse of basis. */ void TEMPLATE(T, embed_trace_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(B, mat_t) basis, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, ctx_t) sup_ctx); /* Compute the matrix whose columns are (gen^0, gen^1, ..., gen^(trunc-1)) */ void TEMPLATE(T, embed_composition_matrix_sub)(TEMPLATE(B, mat_t) matrix, const TEMPLATE(T, t) gen, const TEMPLATE(T, ctx_t) ctx, slong trunc); void TEMPLATE(T, embed_composition_matrix)(TEMPLATE(B, mat_t) matrix, const TEMPLATE(T, t) gen, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, embed_mul_matrix)(TEMPLATE(B, mat_t) matrix, const TEMPLATE(T, t) gen, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, embed_mono_to_dual_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, embed_dual_to_mono_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(T, ctx_t) ctx); #ifdef __cplusplus } #endif #endif #endif flint-3.1.3/src/fq_embed_templates/000077500000000000000000000000001461254215100172425ustar00rootroot00000000000000flint-3.1.3/src/fq_embed_templates/composition_matrix.c000066400000000000000000000037071461254215100233440ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #include "fmpz.h" #include "fmpz_mod_mat.h" /* The naming of these macros is an abuse */ #define __nmod_poly_get_coeff(p, i) ((p)->coeffs[(i)]) #define __fmpz_mod_poly_get_coeff(p, i) ((p)->coeffs + (i)) #define __nmod_mat_zero nmod_mat_zero(matrix) #define __fmpz_mod_mat_zero fmpz_mod_mat_zero(matrix, ctx->ctxp) #define __nmod_mat_set_entry(c) nmod_mat_set_entry(matrix, i, j, c) #define __fmpz_mod_mat_set_entry(c) fmpz_mod_mat_set_entry(matrix, i, j, c, ctx->ctxp) void TEMPLATE(T, embed_composition_matrix_sub)(TEMPLATE(B, mat_t) matrix, const TEMPLATE(T, t) gen, const TEMPLATE(T, ctx_t) ctx, slong trunc) { slong i, j, len = TEMPLATE(T, ctx_degree)(ctx); TEMPLATE(T, t) tmp; TEMPLATE(T, init)(tmp, ctx); TEMPLATE(T, one)(tmp, ctx); __TEMPLATE(B, mat_zero); for (j = 0; j < trunc; j++) { for (i = 0; i < tmp->length; i++) { __TEMPLATE(B, mat_set_entry)(__TEMPLATE(B, poly_get_coeff)(tmp, i)); } if (j < len - 1) TEMPLATE(T, mul)(tmp, tmp, gen, ctx); } TEMPLATE(T, clear)(tmp, ctx); } void TEMPLATE(T, embed_composition_matrix)(TEMPLATE(B, mat_t) matrix, const TEMPLATE(T, t) gen, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, embed_composition_matrix_sub)(matrix, gen, ctx, TEMPLATE(T, ctx_degree(ctx))); } #endif #endif flint-3.1.3/src/fq_embed_templates/embed.c000066400000000000000000000043031461254215100204620ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" void TEMPLATE(T, embed_gens)(TEMPLATE(T, t) gen_sub, TEMPLATE(T, t) gen_sup, TEMPLATE(B, poly_t) minpoly, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, ctx_t) sup_ctx) { if (TEMPLATE(T, ctx_degree)(sub_ctx) == 1) { TEMPLATE(T, gen)(gen_sub, sub_ctx); TEMPLATE(T, set)(gen_sup, gen_sub, sup_ctx); } else { _TEMPLATE(T, embed_gens_naive)(gen_sub, gen_sup, minpoly, sub_ctx, sup_ctx); } } void _TEMPLATE(T, embed_gens_naive)(TEMPLATE(T, t) gen_sub, TEMPLATE(T, t) gen_sup, TEMPLATE(B, poly_t) minpoly, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, ctx_t) sup_ctx) { TEMPLATE(T, poly_t) modulus, fact; flint_rand_t state; TEMPLATE(T, poly_init) (modulus, sup_ctx); TEMPLATE(T, poly_init) (fact, sup_ctx); TEMPLATE4(T, poly_set, B, poly)(modulus, TEMPLATE(T, ctx_modulus)(sub_ctx), sup_ctx); flint_randinit(state); /* Get one linear factor of sub_ctx->modulus in sup_ctx */ while (TEMPLATE(T, poly_degree)(modulus, sup_ctx) != 1) { while (!TEMPLATE(T, poly_factor_equal_deg_prob) (fact, state, modulus, 1, sup_ctx)) { }; TEMPLATE(T, poly_set)(modulus, fact, sup_ctx); } TEMPLATE(T, gen)(gen_sub, sub_ctx); TEMPLATE(T, set)(gen_sup, modulus->coeffs, sup_ctx); TEMPLATE(T, neg)(gen_sup, gen_sup, sup_ctx); TEMPLATE(B, poly_set)(minpoly, TEMPLATE(T, ctx_modulus)(sub_ctx)); TEMPLATE(T, poly_clear) (modulus, sup_ctx); TEMPLATE(T, poly_clear) (fact, sup_ctx); } #endif #endif flint-3.1.3/src/fq_embed_templates/matrices.c000066400000000000000000000211751461254215100212230ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #define __nmod_poly_get_coeff(p,i) ((p)->coeffs[(i)]) #define __fmpz_mod_poly_get_coeff(p,i) ((p)->coeffs + (i)) void TEMPLATE(T, embed_mono_to_dual_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(T, ctx_t) ctx) { slong i, j, n = TEMPLATE(T, ctx_degree)(ctx); TEMPLATE(B, poly_t) ctx_inv_rev, d_ctx; const TEMPLATE(B, poly_struct) *modulus = TEMPLATE(T, ctx_modulus)(ctx); TEMPLATE(B, poly_init)(ctx_inv_rev, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, poly_init)(d_ctx, TEMPLATE(B, poly_modulus)(modulus)); /* Half of this is precomputed in ctx. Maybe a call to some internal Newton stuff could be enough to double it. */ TEMPLATE(T, modulus_pow_series_inv)(ctx_inv_rev, ctx, 2*n); TEMPLATE(B, poly_derivative)(d_ctx, modulus); TEMPLATE(B, poly_reverse)(d_ctx, d_ctx, n); TEMPLATE(B, poly_mullow)(ctx_inv_rev, ctx_inv_rev, d_ctx, 2*n); TEMPLATE(B, mat_zero)(res); for (i = 0; i < n; i++) for (j = 0; j < n && i+j < ctx_inv_rev->length; j++) TEMPLATE(B, mat_set_entry)(res, i, j, __TEMPLATE(B, poly_get_coeff)(ctx_inv_rev, i + j)); TEMPLATE(B, poly_clear)(ctx_inv_rev); TEMPLATE(B, poly_clear)(d_ctx); } void TEMPLATE(T, embed_dual_to_mono_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(T, ctx_t) ctx) { slong i, j, n = TEMPLATE(T, ctx_degree)(ctx); TEMPLATE(T, t) d_ctx, d_ctx_inv; const TEMPLATE(B, poly_struct) *modulus = TEMPLATE(T, ctx_modulus)(ctx); TEMPLATE(B, mat_t) mul_mat, tmp; TEMPLATE(T, init)(d_ctx, ctx); TEMPLATE(T, init)(d_ctx_inv, ctx); TEMPLATE(B, mat_init)(mul_mat, n, n, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(tmp, n, n, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_zero)(tmp); for (i = 0; i < n; i++) for (j = 0; j < n - i; j++) TEMPLATE(B, mat_set_entry)(tmp, i, j, __TEMPLATE(B, poly_get_coeff)(modulus, i + j + 1)); TEMPLATE(T, modulus_derivative_inv)(d_ctx, d_ctx_inv, ctx); TEMPLATE(T, embed_mul_matrix)(mul_mat, d_ctx_inv, ctx); TEMPLATE(B, mat_mul)(res, mul_mat, tmp); TEMPLATE(T, clear)(d_ctx, ctx); TEMPLATE(T, clear)(d_ctx_inv, ctx); TEMPLATE(B, mat_clear)(mul_mat); TEMPLATE(B, mat_clear)(tmp); } /* Given: - a context `sup_ctx` defining a field K of degree n, - a context `sub_ctx` defining a subfield k of degree m|n, - the n×m change-of-basis matrix from k to K, Return the m×n matrix of the trace from K to k. If m=n, res is the inverse of basis. */ void TEMPLATE(T, embed_trace_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(B, mat_t) basis, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, ctx_t) sup_ctx) { slong m = TEMPLATE(B, mat_ncols)(basis), n = TEMPLATE(B, mat_nrows)(basis); const TEMPLATE(B, poly_struct) *modulus = TEMPLATE(T, ctx_modulus)(sub_ctx); TEMPLATE(B, mat_t) m2d, d2m, tmp; TEMPLATE(B, mat_init)(m2d, n, n, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(d2m, m, m, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(tmp, m, n, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(T, embed_mono_to_dual_matrix)(m2d, sup_ctx); TEMPLATE(B, mat_transpose)(res, basis); TEMPLATE(T, embed_dual_to_mono_matrix)(d2m, sub_ctx); TEMPLATE(B, mat_mul)(tmp, res, m2d); TEMPLATE(B, mat_mul)(res, d2m, tmp); TEMPLATE(B, mat_clear)(m2d); TEMPLATE(B, mat_clear)(d2m); TEMPLATE(B, mat_clear)(tmp); } static inline int __fmpz_mod_inv_degree(fmpz_t invd, slong d, const fmpz_t p) { fmpz_set_si(invd, d); return fmpz_invmod(invd, invd, p); } static inline int __nmod_inv_degree(fmpz_t invd, slong d, mp_limb_t p) { mp_limb_t ud = d % p; if (!ud) return 0; ud = n_invmod(ud, p); fmpz_set_ui(invd, ud); return 1; } #define fmpz_mod_mat_entry_is_zero(mat, i, j) (fmpz_is_zero(fmpz_mod_mat_entry((mat), (i), (j)))) #define nmod_mat_entry_is_zero(mat, i, j) (nmod_mat_entry((mat), (i), (j)) == 0) void TEMPLATE(T, embed_matrices)(TEMPLATE(B, mat_t) embed, TEMPLATE(B, mat_t) project, const TEMPLATE(T, t) gen_sub, const TEMPLATE(T, ctx_t) sub_ctx, const TEMPLATE(T, t) gen_sup, const TEMPLATE(T, ctx_t) sup_ctx, const TEMPLATE(B, poly_t) gen_minpoly) { slong m = TEMPLATE(T, ctx_degree)(sub_ctx), n = TEMPLATE(T, ctx_degree)(sup_ctx), d = n / m; fmpz_t invd; TEMPLATE(T, ctx_t) gen_ctx; TEMPLATE(B, poly_t) gen_minpoly_cp; TEMPLATE(B, mat_t) gen2sub, sub2gen, gen2sup, sup2gen; /* Is there any good reason why the modulus argument to fq_ctx_init_modulus is not const? */ TEMPLATE(B, poly_init)(gen_minpoly_cp, TEMPLATE(B, poly_modulus)(gen_minpoly)); TEMPLATE(B, poly_set)(gen_minpoly_cp, gen_minpoly); fmpz_init(invd); TEMPLATE(T, ctx_init_modulus)(gen_ctx, gen_minpoly_cp, "x"); TEMPLATE(B, mat_init)(gen2sub, m, m, TEMPLATE(B, poly_modulus)(gen_minpoly)); TEMPLATE(B, mat_init)(sub2gen, m, m, TEMPLATE(B, poly_modulus)(gen_minpoly)); TEMPLATE(B, mat_init)(gen2sup, n, m, TEMPLATE(B, poly_modulus)(gen_minpoly)); TEMPLATE(B, mat_init)(sup2gen, m, n, TEMPLATE(B, poly_modulus)(gen_minpoly)); /* Gen -> Sub */ TEMPLATE(T, embed_composition_matrix)(gen2sub, gen_sub, sub_ctx); /* Sub -> Gen */ TEMPLATE(T, embed_trace_matrix)(sub2gen, gen2sub, gen_ctx, sub_ctx); /* Gen -> Sup */ TEMPLATE(T, embed_composition_matrix_sub)(gen2sup, gen_sup, sup_ctx, m); /* Sup -> Gen (trace) */ TEMPLATE(T, embed_trace_matrix)(sup2gen, gen2sup, gen_ctx, sup_ctx); /* Correct the projection Sup -> Gen */ /* If this is an isomorphism, there is no need for correction */ if (d == 1) {} /* If the extension degree is invertible mod p, multiply trace by 1/d */ else if (__TEMPLATE(B, inv_degree)(invd, d, TEMPLATE(B, poly_modulus)(gen_minpoly))) { TEMPLATE(B, mat_scalar_mul_fmpz)(sup2gen, sup2gen, invd); } /* Otherwise pre-multiply by an element of trace equal to 1 */ else { int i; TEMPLATE(T, t) mul, trace; TEMPLATE(B, mat_t) column, tvec, mat_mul, tmp; TEMPLATE(T, init)(mul, sup_ctx); TEMPLATE(T, init)(trace, sup_ctx); TEMPLATE(B, mat_init)(tvec, n, 1, TEMPLATE(B, poly_modulus)(gen_minpoly)); TEMPLATE(B, mat_init)(mat_mul, n, n, TEMPLATE(B, poly_modulus)(gen_minpoly)); TEMPLATE(B, mat_init)(tmp, m, n, TEMPLATE(B, poly_modulus)(gen_minpoly)); /* Look for a non-zero column in sup2gen (we know it has full rank, so first row is non-null) */ for (i = 1; i < n; i++) { if (!TEMPLATE(B, mat_entry_is_zero(sup2gen, 0, i))) break; } /* Set mul to x^i */ TEMPLATE(T, gen)(mul, sup_ctx); TEMPLATE(T, pow_ui)(mul, mul, i, sup_ctx); /* Set trace to its trace */ TEMPLATE(B, mat_window_init)(column, sup2gen, 0, i, m, i+1); TEMPLATE(B, mat_mul)(tvec, gen2sup, column); TEMPLATE4(T, set, B, mat)(trace, tvec, sup_ctx); /* Get an element of trace 1 */ TEMPLATE(T, div)(mul, mul, trace, sup_ctx); /* Correct the matrix */ TEMPLATE(T, embed_mul_matrix)(mat_mul, mul, sup_ctx); TEMPLATE(B, mat_mul)(tmp, sup2gen, mat_mul); TEMPLATE(B, mat_swap)(tmp, sup2gen); TEMPLATE(B, mat_clear)(tmp); TEMPLATE(B, mat_clear)(mat_mul); TEMPLATE(B, mat_clear)(tvec); TEMPLATE(B, mat_window_clear)(column); TEMPLATE(T, clear)(mul, sup_ctx); TEMPLATE(T, clear)(trace, sup_ctx); } TEMPLATE(B, mat_mul)(embed, gen2sup, sub2gen); TEMPLATE(B, mat_mul)(project, gen2sub, sup2gen); TEMPLATE(B, mat_clear)(gen2sub); TEMPLATE(B, mat_clear)(sub2gen); TEMPLATE(B, mat_clear)(gen2sup); TEMPLATE(B, mat_clear)(sup2gen); TEMPLATE(T, ctx_clear)(gen_ctx); fmpz_clear(invd); TEMPLATE(B, poly_clear)(gen_minpoly_cp); } #endif #endif flint-3.1.3/src/fq_embed_templates/test/000077500000000000000000000000001461254215100202215ustar00rootroot00000000000000flint-3.1.3/src/fq_embed_templates/test/t-composition_matrix.c000066400000000000000000000062321461254215100245600ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, embed_composition_matrix, state) { int i; /* Check that Mat(a^p) = Mat(x^p) * Mat(a) for random a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) frob, a; const TEMPLATE(B, poly_struct) *modulus; TEMPLATE(B, mat_t) mat_frob, mat_a, mat_aq, res; slong d; while (TEMPLATE(T, ctx_init_randtest)(ctx, state, 3), d = TEMPLATE(T, ctx_degree)(ctx), d == 1) { TEMPLATE(T, ctx_clear)(ctx); } modulus = TEMPLATE(T, ctx_modulus)(ctx); TEMPLATE(T, init)(frob, ctx); TEMPLATE(T, init)(a, ctx); TEMPLATE(B, mat_init)(mat_frob, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(mat_a, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(mat_aq, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(res, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(T, gen)(frob, ctx); #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) TEMPLATE(T, pow_ui)(frob, frob, TEMPLATE(T, ctx_prime)(ctx), ctx); #else TEMPLATE(T, pow)(frob, frob, TEMPLATE(T, ctx_prime)(ctx), ctx); #endif TEMPLATE(T, embed_composition_matrix)(mat_frob, frob, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, embed_composition_matrix)(mat_a, a, ctx); TEMPLATE(B, mat_mul)(res, mat_frob, mat_a); #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) TEMPLATE(T, pow_ui)(a, a, TEMPLATE(T, ctx_prime)(ctx), ctx); #else TEMPLATE(T, pow)(a, a, TEMPLATE(T, ctx_prime)(ctx), ctx); #endif TEMPLATE(T, embed_composition_matrix)(mat_aq, a, ctx); if (!TEMPLATE(B, mat_equal)(res, mat_aq)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), TEMPLATE(T, ctx_print)(ctx), flint_printf("\n"); flint_printf("x^q: "), TEMPLATE(T, print_pretty)(frob, ctx), flint_printf("\n"); flint_printf("M(x^q)*M(a) = M(a^q)\n"), TEMPLATE(B, mat_print_pretty)(mat_frob), flint_printf("\n"), TEMPLATE(B, mat_print_pretty)(mat_a), flint_printf("\n"), TEMPLATE(B, mat_print_pretty)(mat_aq), flint_printf("\n"), TEMPLATE(B, mat_print_pretty)(res), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(B, mat_clear)(mat_frob); TEMPLATE(B, mat_clear)(mat_a); TEMPLATE(B, mat_clear)(mat_aq); TEMPLATE(B, mat_clear)(res); TEMPLATE(T, clear)(frob, ctx); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif #endif flint-3.1.3/src/fq_embed_templates/test/t-embed.c000066400000000000000000000043761461254215100217140ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, embed, state) { int i; /* Check isomorphism to self */ for (i = 0; i < 4 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, ev_a, ev_b; TEMPLATE(B, poly_t) minpoly; TEMPLATE(T, poly_t) minpoly_fq; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init) (a, ctx); TEMPLATE(T, init) (b, ctx); TEMPLATE(T, init) (ev_a, ctx); TEMPLATE(T, init) (ev_b, ctx); TEMPLATE(B, poly_init) (minpoly, TEMPLATE(B, poly_modulus)(TEMPLATE(T, ctx_modulus)(ctx))); TEMPLATE(T, poly_init) (minpoly_fq, ctx); TEMPLATE(T, embed_gens) (a, b, minpoly, ctx, ctx); TEMPLATE4(T, poly_set, B, poly)(minpoly_fq, minpoly, ctx); TEMPLATE3(T, poly_evaluate, T)(ev_a, minpoly_fq, a, ctx); TEMPLATE3(T, poly_evaluate, T)(ev_b, minpoly_fq, b, ctx); if (!TEMPLATE(T, is_zero)(ev_a, ctx) || !TEMPLATE(T, is_zero)(ev_b, ctx)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), TEMPLATE(T, ctx_print)(ctx), flint_printf("\n"); flint_printf("a: "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b: "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("minpoly: "), TEMPLATE(B, poly_print_pretty)(minpoly, "x"), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (a, ctx); TEMPLATE(T, clear) (b, ctx); TEMPLATE(T, clear) (ev_a, ctx); TEMPLATE(T, clear) (ev_b, ctx); TEMPLATE(B, poly_clear) (minpoly); TEMPLATE(T, poly_clear) (minpoly_fq, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif #endif flint-3.1.3/src/fq_embed_templates/test/t-embed_matrices.c000066400000000000000000000122361461254215100235750ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, embed_matrices, state) { int i, j; /* Check that isomorphism to self gives identity matrices */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) gen; const TEMPLATE(B, poly_struct) *modulus; TEMPLATE(B, mat_t) embed, project, one; slong d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); d = TEMPLATE(T, ctx_degree)(ctx); modulus = TEMPLATE(T, ctx_modulus)(ctx); TEMPLATE(T, init)(gen, ctx); TEMPLATE(T, gen)(gen, ctx); #if defined(FQ_NMOD_EMBED_H) || defined(FQ_ZECH_EMBED_H) TEMPLATE(T, pow_ui)(gen, gen, TEMPLATE(T, ctx_prime)(ctx), ctx); #else TEMPLATE(T, pow)(gen, gen, TEMPLATE(T, ctx_prime)(ctx), ctx); #endif TEMPLATE(B, mat_init)(embed, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(project, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(one, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(T, embed_matrices)(embed, project, gen, ctx, gen, ctx, modulus); TEMPLATE(B, mat_one)(one); if (!TEMPLATE(B, mat_equal)(embed, one) || !TEMPLATE(B, mat_equal)(project, one)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), TEMPLATE(T, ctx_print)(ctx), flint_printf("\n"); flint_printf("x^p: "), TEMPLATE(T, print_pretty)(gen, ctx), flint_printf("\n"); flint_printf("Embed\n"), TEMPLATE(B, mat_print_pretty)(embed), flint_printf("\nProject\n"), TEMPLATE(B, mat_print_pretty)(project), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(B, mat_clear)(embed); TEMPLATE(B, mat_clear)(project); TEMPLATE(B, mat_clear)(one); TEMPLATE(T, clear)(gen, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check random emebedding (degrees 1..5) */ for (j = 1; j < 6; j++) { for (i = 0; i < (6 - j) * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx1, ctx2; TEMPLATE(T, t) gen1, gen2; TEMPLATE(B, poly_t) minpoly; const TEMPLATE(B, poly_struct) *modulus; TEMPLATE(B, poly_t) modulus2; TEMPLATE(B, mat_t) embed, project, comp, one; slong m, n; while (TEMPLATE(T, ctx_init_randtest)(ctx1, state, 3), m = TEMPLATE(T, ctx_degree)(ctx1), m == 1) { TEMPLATE(T, ctx_clear)(ctx1); } n = m*j; modulus = TEMPLATE(T, ctx_modulus)(ctx1); TEMPLATE(B, poly_init)(modulus2, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, poly_randtest_monic_irreducible)(modulus2, state, n+1); TEMPLATE(T, ctx_init_modulus)(ctx2, modulus2, "X"); TEMPLATE(T, init)(gen1, ctx1); TEMPLATE(T, init)(gen2, ctx2); TEMPLATE(B, poly_init)(minpoly, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(T, embed_gens)(gen1, gen2, minpoly, ctx1, ctx2); TEMPLATE(B, mat_init)(embed, n, m, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(project, m, n, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(comp, m, m, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(one, m, m, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(T, embed_matrices)(embed, project, gen1, ctx1, gen2, ctx2, minpoly); TEMPLATE(B, mat_mul)(comp, project, embed); TEMPLATE(B, mat_one)(one); if (!TEMPLATE(B, mat_equal)(comp, one)) { flint_printf("FAIL:\n\n"); flint_printf("CTX 1\n"), TEMPLATE(T, ctx_print)(ctx1), flint_printf("\n"); flint_printf("CTX 2\n"), TEMPLATE(T, ctx_print)(ctx2), flint_printf("\n"); flint_printf("Embed\n"), TEMPLATE(B, mat_print_pretty)(embed), flint_printf("\nProject\n"), TEMPLATE(B, mat_print_pretty)(project), flint_printf("\nComposition\n"), TEMPLATE(B, mat_print_pretty)(comp), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(B, mat_clear)(embed); TEMPLATE(B, mat_clear)(project); TEMPLATE(B, mat_clear)(comp); TEMPLATE(B, mat_clear)(one); TEMPLATE(B, poly_clear)(minpoly); TEMPLATE(B, poly_clear)(modulus2); TEMPLATE(T, clear)(gen1, ctx1); TEMPLATE(T, ctx_clear)(ctx1); TEMPLATE(T, clear)(gen2, ctx2); TEMPLATE(T, ctx_clear)(ctx2); } } TEST_FUNCTION_END(state); } #endif #endif flint-3.1.3/src/fq_embed_templates/test/t-mono_dual_matrix.c000066400000000000000000000041251461254215100241710ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, embed_mono_dual_matrix, state) { int i; /* Check that the two functions are inverse of one another */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; const TEMPLATE(B, poly_struct) *modulus; TEMPLATE(B, mat_t) m2d, d2m, one, two; slong d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); d = TEMPLATE(T, ctx_degree)(ctx); modulus = TEMPLATE(T, ctx_modulus)(ctx); TEMPLATE(B, mat_init)(m2d, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(d2m, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(one, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(two, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(T, embed_mono_to_dual_matrix)(m2d, ctx); TEMPLATE(T, embed_dual_to_mono_matrix)(d2m, ctx); TEMPLATE(B, mat_mul)(one, m2d, d2m); TEMPLATE(B, mat_one)(two); if (!TEMPLATE(B, mat_equal)(one, two)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), TEMPLATE(T, ctx_print)(ctx), flint_printf("\n"); flint_printf("Mono -> Dual\n"), TEMPLATE(B, mat_print_pretty)(m2d), flint_printf("\nDual -> Mono\n"), TEMPLATE(B, mat_print_pretty)(d2m), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(B, mat_clear)(m2d); TEMPLATE(B, mat_clear)(d2m); TEMPLATE(B, mat_clear)(one); TEMPLATE(B, mat_clear)(two); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif #endif flint-3.1.3/src/fq_embed_templates/test/t-mul_matrix.c000066400000000000000000000044671461254215100230220ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, embed_mul_matrix, state) { int i; /* Check that Mat(a^2) = Mat(a)^2 for random a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a; TEMPLATE(B, mat_t) mat_a, mat_a_sq, mat_a_a; const TEMPLATE(B, poly_struct) *modulus; slong d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); d = TEMPLATE(T, ctx_degree)(ctx); modulus = TEMPLATE(T, ctx_modulus)(ctx); TEMPLATE(T, init)(a, ctx); TEMPLATE(B, mat_init)(mat_a, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(mat_a_sq, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(B, mat_init)(mat_a_a, d, d, TEMPLATE(B, poly_modulus)(modulus)); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, embed_mul_matrix)(mat_a, a, ctx); TEMPLATE(T, mul)(a, a, a, ctx); TEMPLATE(T, embed_mul_matrix)(mat_a_sq, a, ctx); TEMPLATE(B, mat_mul)(mat_a_a, mat_a, mat_a); if (!TEMPLATE(B, mat_equal)(mat_a_a, mat_a_sq)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), TEMPLATE(T, ctx_print)(ctx), flint_printf("\n"); flint_printf("a^2: "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("M(a)^2 = M(a^2)\n"), TEMPLATE(B, mat_print_pretty)(mat_a), flint_printf("^2\n=\n"), TEMPLATE(B, mat_print_pretty)(mat_a_a), flint_printf("\n=\n"), TEMPLATE(B, mat_print_pretty)(mat_a_sq), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(B, mat_clear)(mat_a); TEMPLATE(B, mat_clear)(mat_a_sq); TEMPLATE(B, mat_clear)(mat_a_a); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif #endif flint-3.1.3/src/fq_mat.h000066400000000000000000000017611461254215100150470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_MAT_H #define FQ_MAT_H #ifdef FQ_MAT_INLINES_C #define FQ_MAT_TEMPLATES_INLINE #define FQ_MAT_INLINE #else #define FQ_MAT_TEMPLATES_INLINE static inline #define FQ_MAT_INLINE static inline #endif #include "fq_types.h" /* Cutoff between classical and recursive triangular solving */ #define FQ_MAT_SOLVE_TRI_ROWS_CUTOFF 64 #define FQ_MAT_SOLVE_TRI_COLS_CUTOFF 64 /* Cutoff between classical and recursive LU decomposition */ #define FQ_MAT_LU_RECURSIVE_CUTOFF 4 int FQ_MAT_MUL_KS_CUTOFF(slong r, slong c, const fq_ctx_t ctx); #define T fq #define CAP_T FQ #include "fq_mat_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_mat/000077500000000000000000000000001461254215100146715ustar00rootroot00000000000000flint-3.1.3/src/fq_mat/inlines.c000066400000000000000000000006501461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_MAT_INLINES_C #include "fq_mat.h" flint-3.1.3/src/fq_mat/mul_ks_cutoff.c000066400000000000000000000011111461254215100176670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" int FQ_MAT_MUL_KS_CUTOFF(slong r, slong c, const fq_ctx_t ctx) { if (5 * FLINT_MIN(r, c) > 8 * fq_ctx_degree(ctx) + 29) return 1; else return 0; } flint-3.1.3/src/fq_mat/profile/000077500000000000000000000000001461254215100163315ustar00rootroot00000000000000flint-3.1.3/src/fq_mat/profile/p-mul.c000066400000000000000000000010301461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/profile/p-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/reduce_row.c000066400000000000000000000031201461254215100171670ustar00rootroot00000000000000/* Copyright (C) 2015, 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" #include "fq_mat.h" slong fq_mat_reduce_row(fq_mat_t A, slong * P, slong * L, slong m, const fq_ctx_t ctx) { slong n = A->c, i, j, r, res = -WORD(1); fmpz_poly_t h; fmpz_poly_init(h); for (i = 0; i < n; i++) { if (i != 0) fq_reduce(fq_mat_entry(A, m, i), ctx); if (!fq_is_zero(fq_mat_entry(A, m, i), ctx)) { r = P[i]; if (r != -WORD(1)) { for (j = i + 1; j < L[r]; j++) { fmpz_poly_mul(h, fq_mat_entry(A, r, j), fq_mat_entry(A, m, i)); fmpz_poly_sub(fq_mat_entry(A, m, j), fq_mat_entry(A, m, j), h); } fq_zero(fq_mat_entry(A, m, i), ctx); } else { fq_inv(h, fq_mat_entry(A, m, i), ctx); fq_one(fq_mat_entry(A, m, i), ctx); for (j = i + 1; j < L[m]; j++) { fq_reduce(fq_mat_entry(A, m, j), ctx); fq_mul(fq_mat_entry(A, m, j), fq_mat_entry(A, m, j), h, ctx); } P[i] = m; res = i; break; } } } fmpz_poly_clear(h); return res; } flint-3.1.3/src/fq_mat/test/000077500000000000000000000000001461254215100156505ustar00rootroot00000000000000flint-3.1.3/src/fq_mat/test/main.c000066400000000000000000000053071461254215100167450ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-can_solve.c" #include "t-charpoly.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-equal.c" #include "t-inv.c" #include "t-invert_rows_cols.c" #include "t-is_zero.c" #include "t-lu_classical.c" #include "t-lu_recursive.c" #include "t-minpoly.c" #include "t-mul.c" #include "t-mul_KS.c" #include "t-mul_vec.c" #include "t-nullspace.c" #include "t-one.c" #include "t-rank.c" #include "t-rref.c" #include "t-set_fmpz_mod_mat.c" #include "t-set_nmod_mat.c" #include "t-solve.c" #include "t-solve_tril.c" #include "t-solve_tril_classical.c" #include "t-solve_tril_recursive.c" #include "t-solve_triu.c" #include "t-solve_triu_classical.c" #include "t-solve_triu_recursive.c" #include "t-submul.c" #include "t-vec_mul.c" #include "t-window_init_clear.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_mat_add_sub), TEST_FUNCTION(fq_mat_can_solve), TEST_FUNCTION(fq_mat_charpoly), TEST_FUNCTION(fq_mat_concat_horizontal), TEST_FUNCTION(fq_mat_concat_vertical), TEST_FUNCTION(fq_mat_equal), TEST_FUNCTION(fq_mat_inv), TEST_FUNCTION(fq_mat_invert_rows_cols), TEST_FUNCTION(fq_mat_is_zero), TEST_FUNCTION(fq_mat_lu_classical), TEST_FUNCTION(fq_mat_lu_recursive), TEST_FUNCTION(fq_mat_minpoly), TEST_FUNCTION(fq_mat_mul), TEST_FUNCTION(fq_mat_mul_KS), TEST_FUNCTION(fq_mat_mul_vec), TEST_FUNCTION(fq_mat_nullspace), TEST_FUNCTION(fq_mat_one), TEST_FUNCTION(fq_mat_rank), TEST_FUNCTION(fq_mat_rref), TEST_FUNCTION(fq_mat_set_fmpz_mod_mat), TEST_FUNCTION(fq_mat_set_nmod_mat), TEST_FUNCTION(fq_mat_solve), TEST_FUNCTION(fq_mat_solve_tril), TEST_FUNCTION(fq_mat_solve_tril_classical), TEST_FUNCTION(fq_mat_solve_tril_recursive), TEST_FUNCTION(fq_mat_solve_triu), TEST_FUNCTION(fq_mat_solve_triu_classical), TEST_FUNCTION(fq_mat_solve_triu_recursive), TEST_FUNCTION(fq_mat_submul), TEST_FUNCTION(fq_mat_vec_mul), TEST_FUNCTION(fq_mat_window_init_clear), TEST_FUNCTION(fq_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_mat/test/t-add_sub.c000066400000000000000000000010311461254215100176510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-add_sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-can_solve.c000066400000000000000000000010341461254215100202240ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-can_solve.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-charpoly.c000066400000000000000000000010571461254215100201010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-charpoly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-concat_horizontal.c000066400000000000000000000010511461254215100217720ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-concat_horizontal.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-concat_vertical.c000066400000000000000000000010471461254215100214170ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-concat_vertical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-equal.c000066400000000000000000000010271461254215100173640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-equal.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-inv.c000066400000000000000000000010271461254215100170510ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-inv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-invert_rows_cols.c000066400000000000000000000010441461254215100216550ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-invert_rows_cols.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-is_zero.c000066400000000000000000000010311461254215100177220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-is_zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-lu_classical.c000066400000000000000000000010361461254215100207130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-lu_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-lu_recursive.c000066400000000000000000000010361461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-lu_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-minpoly.c000066400000000000000000000010561461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-minpoly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-mul.c000066400000000000000000000010251461254215100170500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-mul_KS.c000066400000000000000000000010301461254215100174410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-mul_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-mul_vec.c000066400000000000000000000010601461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-mul_vec.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-nullspace.c000066400000000000000000000010331461254215100202400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-nullspace.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-one.c000066400000000000000000000010261461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-one.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-rank.c000066400000000000000000000010261461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-rank.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-rref.c000066400000000000000000000010261461254215100172120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-rref.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-set_fmpz_mod_mat.c000066400000000000000000000010431461254215100216020ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-set_fmpz_mod_mat.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-set_nmod_mat.c000066400000000000000000000010371461254215100207270ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-set_nmod_mat.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-solve.c000066400000000000000000000010311461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-solve.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-solve_tril.c000066400000000000000000000010341461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-solve_tril.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-solve_tril_classical.c000066400000000000000000000010461461254215100224560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-solve_tril_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-solve_tril_recursive.c000066400000000000000000000010461461254215100225270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-solve_tril_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-solve_triu.c000066400000000000000000000010341461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-solve_triu.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-solve_triu_classical.c000066400000000000000000000010461461254215100224670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-solve_triu_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-solve_triu_recursive.c000066400000000000000000000010461461254215100225400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-solve_triu_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-submul.c000066400000000000000000000010301461254215100175560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-submul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-vec_mul.c000066400000000000000000000010601461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-vec_mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-window_init_clear.c000066400000000000000000000010751461254215100217600ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-window_init_clear.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat/test/t-zero.c000066400000000000000000000010261461254215100172330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/test/t-zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_mat_templates.h000066400000000000000000000327161461254215100171310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "nmod_types.h" #include "fmpz_mod_types.h" #include "templates.h" #ifdef __cplusplus extern "C" { #endif /* Memory management ********************************************************/ void TEMPLATE(T, mat_init)(TEMPLATE(T, mat_t) mat, slong rows, slong cols, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_init_set)(TEMPLATE(T, mat_t) mat, const TEMPLATE(T, mat_t) src, const TEMPLATE(T, ctx_t) ctx); FQ_MAT_TEMPLATES_INLINE slong TEMPLATE(T, mat_nrows)(const TEMPLATE(T, mat_t) mat , const TEMPLATE(T, ctx_t) ctx) { return mat->r; } FQ_MAT_TEMPLATES_INLINE slong TEMPLATE(T, mat_ncols)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { return mat->c; } FQ_MAT_TEMPLATES_INLINE TEMPLATE(T, struct) * TEMPLATE(T, mat_entry)(const TEMPLATE(T, mat_t) mat, slong i, slong j) { return mat->rows[i] + j; } void TEMPLATE(T, mat_entry_set)(TEMPLATE(T, mat_t) mat, slong i, slong j, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_swap)(TEMPLATE(T, mat_t) mat1, TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_swap_entrywise)(TEMPLATE(T, mat_t) mat1, TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_set)(TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_clear)(TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, mat_equal)(const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, mat_is_zero)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, mat_is_one)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); FQ_MAT_TEMPLATES_INLINE int TEMPLATE(T, mat_is_empty)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { return (mat->r == 0) || (mat->c == 0); } FQ_MAT_TEMPLATES_INLINE int TEMPLATE(T, mat_is_square)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { return (mat->r == mat->c); } FQ_MAT_TEMPLATES_INLINE void TEMPLATE(T, mat_swap_rows)(TEMPLATE(T, mat_t) mat, slong * perm, slong r, slong s, const TEMPLATE(T, ctx_t) ctx) { if (r != s && !TEMPLATE(T, mat_is_empty)(mat, ctx)) { if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(TEMPLATE(T, struct) *, mat->rows[r], mat->rows[s]); } } FQ_MAT_TEMPLATES_INLINE void TEMPLATE(T, mat_invert_rows)(TEMPLATE(T, mat_t) mat, slong * perm, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < mat->r/2; i++) TEMPLATE(T, mat_swap_rows)(mat, perm, i, mat->r - i - 1, ctx); } void TEMPLATE(T, mat_swap_cols)(TEMPLATE(T, mat_t) mat, slong * perm, slong r, slong s, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_invert_cols)(TEMPLATE(T, mat_t) mat, slong * perm, const TEMPLATE(T, ctx_t) ctx); /* Assignment ***************************************************************/ void TEMPLATE(T, mat_zero)(TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_one)(TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); /* Conversions ***************************************************************/ void TEMPLATE(T, mat_set_nmod_mat) (TEMPLATE(T, mat_t) mat1, const nmod_mat_t mat2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_set_fmpz_mod_mat) (TEMPLATE(T, mat_t) mat1, const fmpz_mod_mat_t mat2, const TEMPLATE(T, ctx_t) ctx); /* Windows and concatenation */ void TEMPLATE(T, mat_window_init)(TEMPLATE(T, mat_t) window, const TEMPLATE(T, mat_t) mat, slong r1, slong c1, slong r2, slong c2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_window_clear)(TEMPLATE(T, mat_t) window, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_concat_horizontal)(TEMPLATE(T, mat_t) res, const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_concat_vertical)(TEMPLATE(T, mat_t) res, const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); /* Input and output *********************************************************/ #ifdef FLINT_HAVE_FILE int TEMPLATE(T, mat_fprint)(FILE * file, const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, mat_fprint_pretty)(FILE * file, const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); #endif int TEMPLATE(T, mat_print)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, mat_print_pretty)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); /* TODO: Read functions */ /* Random matrix generation *************************************************/ void TEMPLATE(T, mat_randtest)(TEMPLATE(T, mat_t) mat, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_randrank)(TEMPLATE(T, mat_t) mat, flint_rand_t state, slong rank, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, mat_randpermdiag)(TEMPLATE(T, mat_t) mat, flint_rand_t state, TEMPLATE(T, struct) * diag, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_randops)(TEMPLATE(T, mat_t) mat, flint_rand_t state, slong count, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_randtril)(TEMPLATE(T, mat_t) mat, flint_rand_t state, int unit, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_randtriu)(TEMPLATE(T, mat_t) mat, flint_rand_t state, int unit, const TEMPLATE(T, ctx_t) ctx); /* Norms */ /* Transpose */ /* Addition and subtraction */ void TEMPLATE(T, mat_add)(TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_sub)(TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_neg)(TEMPLATE(T, mat_t) B, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_submul)(TEMPLATE(T, mat_t) D, const TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); /* Scalar operations */ /* Multiplication */ void TEMPLATE(T, mat_mul)(TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_mul_classical)(TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_mul_KS)(TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); slong TEMPLATE(T, mat_lu)(slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx); slong TEMPLATE(T, mat_lu_recursive)(slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx); slong TEMPLATE(T, mat_lu_classical)(slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx); /* Inverse *******************************************************************/ int TEMPLATE(T, mat_inv)(TEMPLATE(T, mat_t) B, TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); /* Solving *******************************************************************/ slong TEMPLATE(T, mat_rref)(TEMPLATE(T, mat_t) B, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); slong TEMPLATE(T, mat_reduce_row)(TEMPLATE(T, mat_t) A, slong * P, slong * L, slong m, const TEMPLATE(T, ctx_t) ctx); slong TEMPLATE(T, mat_nullspace)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); slong TEMPLATE(T, mat_rank)(const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_solve_tril)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) L, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_solve_tril_classical)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) L, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_solve_tril_recursive)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) L, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_solve_triu)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) U, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_solve_triu_classical)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) U, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_solve_triu_recursive)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) U, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_mul_vec)(TEMPLATE(T, struct) * c, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, struct) * b, slong blen, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_mul_vec_ptr)(TEMPLATE(T, struct) * const * c, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, struct) * const * b, slong blen, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_vec_mul)(TEMPLATE(T, struct) * c, const TEMPLATE(T, struct) * a, slong alen, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_vec_mul_ptr)(TEMPLATE(T, struct) * const * c, const TEMPLATE(T, struct) * const * a, slong alen, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); /* Nonsingular solving *******************************************************/ int TEMPLATE(T, mat_solve)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t A), const TEMPLATE(T, mat_t) C, const TEMPLATE(T, ctx_t) ctx); /* Solving *******************************************************************/ int TEMPLATE(T, mat_can_solve)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); /* Transforms ****************************************************************/ void TEMPLATE(T, mat_similarity) (TEMPLATE(T, mat_t) A, slong r, TEMPLATE(T, t) d, const TEMPLATE(T, ctx_t) ctx); /* Characteristic polynomial *************************************************/ /* this prototype really lives in fq_poly_templates.h * FQ_MAT_TEMPLATES_INLINE * void TEMPLATE(T, mat_charpoly)(TEMPLATE(T, poly_t) p, * TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx) * { * TEMPLATE(T, mat_charpoly_danilevsky) (p, A, ctx); * } */ /* Minimal polynomial ********************************************************/ /* this prototype really lives in fq_poly_templates.h * * void TEMPLATE(T, mat_minpoly) (TEMPLATE(T, poly_t) p, * const TEMPLATE(T, mat_t) X, const TEMPLATE(T, ctx_t) ctx); */ #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_mat_templates/000077500000000000000000000000001461254215100167475ustar00rootroot00000000000000flint-3.1.3/src/fq_mat_templates/add.c000066400000000000000000000015561461254215100176520ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_add) (TEMPLATE(T, mat_t) res, const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { slong i; if (res->c < 1) return; for (i = 0; i < res->r; i++) _TEMPLATE(T, vec_add) (res->rows[i], mat1->rows[i], mat2->rows[i], res->c, ctx); } #endif flint-3.1.3/src/fq_mat_templates/can_solve.c000066400000000000000000000061451461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, mat_can_solve)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { slong i, j, k, col, *pivots, rank, *perm; TEMPLATE(T, mat_t) LU, LU2, PB; int result = 1; if (X->r != A->c || X->c != B->c) return 0; if (A->r == 0 || B->c == 0) { TEMPLATE(T, mat_zero)(X, ctx); return 1; } if (A->c == 0) { TEMPLATE(T, mat_zero)(X, ctx); return TEMPLATE(T, mat_is_zero)(B, ctx); } TEMPLATE(T, mat_init_set)(LU, A, ctx); perm = flint_malloc(sizeof(slong) * A->r); for (i = 0; i < A->r; i++) perm[i] = i; rank = TEMPLATE(T, mat_lu)(perm, LU, 0, ctx); TEMPLATE(T, mat_window_init)(PB, B, 0, 0, B->r, B->c, ctx); for (i = 0; i < B->r; i++) PB->rows[i] = B->rows[perm[i]]; TEMPLATE(T, mat_init)(LU2, rank, rank, ctx); pivots = flint_malloc(sizeof(slong)*rank); col = 0; for (i = 0; i < rank; i++) { while (TEMPLATE(T, is_zero)(TEMPLATE(T, mat_entry)(LU, i, col), ctx)) col++; pivots[i] = col; for (j = 0; j < rank; j++) TEMPLATE(T, mat_entry_set)(LU2, j, i, TEMPLATE(T, mat_entry)(LU, j, col), ctx); col++; } X->r = rank; PB->r = rank; LU->r = rank; TEMPLATE(T, mat_solve_tril)(X, LU, PB, 1, ctx); LU->r = A->r; if (A->r > rank) { TEMPLATE(T, mat_t) P; LU->rows += rank; LU->r = A->r - rank; X->r = LU->c; TEMPLATE(T, mat_init)(P, LU->r, B->c, ctx); TEMPLATE(T, mat_mul)(P, LU, X, ctx); PB->r = LU->r; PB->rows += rank; result = TEMPLATE(T, mat_equal)(P, PB, ctx); PB->rows -= rank; TEMPLATE(T, mat_clear)(P, ctx); LU->rows -= rank; if (!result) { X->r = A->c; TEMPLATE(T, mat_zero)(X, ctx); goto cleanup; } } TEMPLATE(T, mat_solve_triu)(X, LU2, X, 0, ctx); X->r = A->c; k = rank - 1; for (i = A->c - 1; i >= 0; i--) { if (k < 0 || i != pivots[k]) { for (j = 0; j < B->c; j++) TEMPLATE(T, zero)(TEMPLATE(T, mat_entry)(X, i, j), ctx); } else { for (j = 0; j < B->c; j++) TEMPLATE(T, mat_entry_set)(X, i, j, TEMPLATE(T, mat_entry)(X, k, j), ctx); k--; } } cleanup: TEMPLATE(T, mat_clear)(LU2, ctx); PB->r = B->r; TEMPLATE(T, mat_window_clear)(PB, ctx); LU->r = A->r; TEMPLATE(T, mat_clear)(LU, ctx); flint_free(perm); flint_free(pivots); return result; } #endif flint-3.1.3/src/fq_mat_templates/charpoly.c000066400000000000000000000162501461254215100207400ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_charpoly_danilevsky) (TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) M, const TEMPLATE(T, ctx_t) ctx) { slong n = M->r, i, j, k; TEMPLATE(T, struct) * V, * W, * T; TEMPLATE(T, poly_t) b; TEMPLATE(T, t) c, h; TEMPLATE(T, mat_t) A; if (n == 0) { TEMPLATE(T, poly_one) (p, ctx); return; } TEMPLATE(T, init) (c, ctx); if (n == 1) { TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (p, 1, c, ctx); TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (M, 0, 0), ctx); TEMPLATE(T, poly_set_coeff) (p, 0, c, ctx); _TEMPLATE(T, poly_set_length) (p, 2, ctx); TEMPLATE(T, clear) (c, ctx); return; } i = 1; TEMPLATE(T, init) (h, ctx); TEMPLATE(T, poly_one) (p, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, mat_init_set) (A, M, ctx); V = (TEMPLATE(T, struct) *) _TEMPLATE(T, vec_init) (n, ctx); W = (TEMPLATE(T, struct) *) _TEMPLATE(T, vec_init) (n, ctx); T = (TEMPLATE(T, struct) *) _TEMPLATE(T, vec_init) (n, ctx); while (i < n) { TEMPLATE(T, set) (h, TEMPLATE(T, mat_entry) (A, n - i, n - i - 1), ctx); while (TEMPLATE(T, is_zero) (h, ctx)) { k = 1; while (k < n - i && TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, n - i, n - i - k - 1), ctx)) k++; if (k == n - i) { TEMPLATE(T, poly_fit_length) (b, i + 1, ctx); TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (b, i, c, ctx); for (k = 1; k <= i; k++) { TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (A, n - i, n - k), ctx); TEMPLATE(T, poly_set_coeff) (b, k - 1, c, ctx); } _TEMPLATE(T, poly_set_length) (b, i + 1, ctx); TEMPLATE(T, poly_mul) (p, p, b, ctx); n -= i; i = 1; if (n == 1) { TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (b, 1, c, ctx); TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (A, 0, 0), ctx); TEMPLATE(T, poly_set_coeff) (b, 0, c, ctx); _TEMPLATE(T, poly_set_length) (b, 2, ctx); TEMPLATE(T, poly_mul) (p, p, b, ctx); goto cleanup; } } else { TEMPLATE(T, struct) * ptr; ptr = A->rows[n - i - k - 1]; A->rows[n - i - k - 1] = A->rows[n - i - 1]; A->rows[n - i - 1] = ptr; for (j = 1; j <= n - i + 1; j++) { TEMPLATE(T, swap) (TEMPLATE(T, mat_entry) (A, j - 1, n - i - k - 1), TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), ctx); } } TEMPLATE(T, set) (h, TEMPLATE(T, mat_entry) (A, n - i, n - i - 1), ctx); } TEMPLATE(T, neg) (h, h, ctx); TEMPLATE(T, inv) (h, h, ctx); for (j = 1; j <= n; j++) { TEMPLATE(T, mul) (V + j - 1, TEMPLATE(T, mat_entry) (A, n - i, j - 1), h, ctx); TEMPLATE(T, set) (W + j - 1, TEMPLATE(T, mat_entry) (A, n - i, j - 1), ctx); } TEMPLATE(T, neg) (h, h, ctx); for (j = 1; j <= n - i; j++) { for (k = 1; k <= n - i - 1; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), V + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, j - 1, k - 1), TEMPLATE(T, mat_entry) (A, j - 1, k - 1), c, ctx); } for (k = n - i + 1; k <= n; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), V + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, j - 1, k - 1), TEMPLATE(T, mat_entry) (A, j - 1, k - 1), c, ctx); } TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), h, ctx); } for (j = 1; j <= n - i - 1; j++) { TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), W + n - i - 1, ctx); for (k = 1; k < n - i; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, k - 1, j - 1), W + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), c, ctx); } } for (j = n - i; j <= n - 1; j++) { TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), W + n - i - 1, ctx); for (k = 1; k < n - i; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, k - 1, j - 1), W + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), c, ctx); } TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), W + j, ctx); } TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), W + n - i - 1, ctx); for (k = 1; k < n - i; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, k - 1, n - 1), W + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), c, ctx); } i++; } TEMPLATE(T, poly_fit_length) (b, n + 1, ctx); TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (b, n, c, ctx); for (i = 1; i <= n; i++) { TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (A, 0, n - i), ctx); TEMPLATE(T, poly_set_coeff) (b, i - 1, c, ctx); } _TEMPLATE(T, poly_set_length) (b, n + 1, ctx); TEMPLATE(T, poly_mul) (p, p, b, ctx); cleanup: TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, clear) (c, ctx); TEMPLATE(T, clear) (h, ctx); TEMPLATE(T, poly_clear) (b, ctx); _TEMPLATE(T, vec_clear) (T, A->r, ctx); _TEMPLATE(T, vec_clear) (V, A->r, ctx); _TEMPLATE(T, vec_clear) (W, A->r, ctx); } void TEMPLATE(T, mat_charpoly)(TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) M, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) A; TEMPLATE(T, mat_init) (A, M->r, M->c, ctx); TEMPLATE(T, mat_set) (A, M, ctx); if (A->r != A->c) { flint_throw(FLINT_ERROR, "Exception (fq_mat_charpoly). Non-square matrix.\n"); } TEMPLATE(T, mat_charpoly_danilevsky) (p, A, ctx); TEMPLATE(T, mat_clear) (A, ctx); } #endif flint-3.1.3/src/fq_mat_templates/clear.c000066400000000000000000000016601461254215100202040ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_clear) (TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { if (mat->entries) { slong i; for (i = 0; i < mat->r * mat->c; i++) TEMPLATE(T, clear) (mat->entries + i, ctx); /* Clear all coefficients */ flint_free(mat->entries); /* Clean up array of entries */ flint_free(mat->rows); /* Clean up row array */ } else if (mat->r != 0) flint_free(mat->rows); } #endif flint-3.1.3/src/fq_mat_templates/concat_horizontal.c000066400000000000000000000017311461254215100226350ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_concat_horizontal) (TEMPLATE(T, mat_t) res, const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { slong i; slong r1 = mat1->r; slong c1 = mat1->c; slong c2 = mat2->c; for (i = 0; i < r1; i++) { if (c1 > 0) _TEMPLATE(T, vec_set) (res->rows[i], mat1->rows[i], c1, ctx); if (c2 > 0) _TEMPLATE(T, vec_set) (res->rows[i] + c1, mat2->rows[i], c2, ctx); } } #endif flint-3.1.3/src/fq_mat_templates/concat_vertical.c000066400000000000000000000017571461254215100222650ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "fmpz_mat.h" void TEMPLATE(T, mat_concat_vertical) (TEMPLATE(T, mat_t) res, const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { slong i; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; if (c1 > 0) { for (i = 0; i < r1; i++) _TEMPLATE(T, vec_set) (res->rows[i], mat1->rows[i], c1, ctx); for (i = 0; i < r2; i++) _TEMPLATE(T, vec_set) (res->rows[i + r1], mat2->rows[i], c1, ctx); } } #endif flint-3.1.3/src/fq_mat_templates/equal.c000066400000000000000000000017371461254215100202320ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, mat_equal) (const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { slong j; if (mat1->r != mat2->r || mat1->c != mat2->c) { return 0; } if (mat1->r == 0 || mat1->c == 0) return 1; for (j = 0; j < mat1->r; j++) { if (!_TEMPLATE(T, vec_equal) (mat1->rows[j], mat2->rows[j], mat1->c, ctx)) { return 0; } } return 1; } #endif flint-3.1.3/src/fq_mat_templates/init.c000066400000000000000000000027021461254215100200570ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_init) (TEMPLATE(T, mat_t) mat, slong rows, slong cols, const TEMPLATE(T, ctx_t) ctx) { slong i; if (rows != 0) mat->rows = (TEMPLATE(T, struct) **) flint_malloc(rows * sizeof(TEMPLATE(T, struct) *)); else mat->rows = NULL; if (rows != 0 && cols != 0) /* Allocate space for r*c small entries */ { slong j; mat->entries = (TEMPLATE(T, struct) *) flint_malloc(flint_mul_sizes(rows, cols) * sizeof(TEMPLATE(T, struct))); for (i = 0; i < rows; i++) { mat->rows[i] = mat->entries + i * cols; for (j = 0; j < cols; j++) { TEMPLATE(T, init) (mat->rows[i] + j, ctx); } } } else { mat->entries = NULL; if (rows != 0) { for (i = 0; i < rows; i++) mat->rows[i] = NULL; } } mat->r = rows; mat->c = cols; } #endif flint-3.1.3/src/fq_mat_templates/init_set.c000066400000000000000000000013771461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_init_set) (TEMPLATE(T, mat_t) mat, const TEMPLATE(T, mat_t) src, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_init) (mat, src->r, src->c, ctx); TEMPLATE(T, mat_set) (mat, src, ctx); } #endif flint-3.1.3/src/fq_mat_templates/inv.c000066400000000000000000000025361461254215100177150ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, mat_inv)(TEMPLATE(T, mat_t) B, TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) I; slong i, dim; int result; dim = A->r; switch (dim) { case 0: result = 1; break; case 1: if (TEMPLATE(T, is_zero)(TEMPLATE(T, mat_entry)(A, 0, 0), ctx)) { result = 0; } else { TEMPLATE(T, inv)(TEMPLATE(T, mat_entry(B, 0, 0)), TEMPLATE(T, mat_entry(A, 0, 0)), ctx); result = 1; } break; default: TEMPLATE(T, mat_init)(I, dim, dim, ctx); for (i = 0; i < dim; i++) TEMPLATE(T, one)(TEMPLATE(T, mat_entry)(I, i, i), ctx); result = TEMPLATE(T, mat_solve)(B, A, I, ctx); TEMPLATE(T, mat_clear)(I, ctx); } return result; } #endif flint-3.1.3/src/fq_mat_templates/io.c000066400000000000000000000065071461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* printing *******************************************************************/ /* The macros xxx_putc, xxx_printf, and xxx_T_print are provided as wrappers to handle return values and error conditions. While this is not exactly pretty, it improves the readability of the functions TEMPLATE(T, mat_fprint) and TEMPLATE(T, mat_fprint_pretty). Moreover, if we later want to improve the handling of returns values, e.g. to return the number of characters printed, this will be easier. The macros are undef'd at the end of the file. */ #define xxx_putc(c) \ do { \ z = fputc((c), file); \ if (z <= 0) \ return z; \ } while (0) #define xxx_printf() \ do { \ z = flint_fprintf(file, WORD_FMT "d " WORD_FMT "d ", r, c); \ if (z <= 0) \ return z; \ } while (0) #define xxx_T_print(f, ctx) \ do { \ z = TEMPLATE(T, fprint)(file, (f), (ctx)); \ if (z <= 0) \ return z; \ } while(0) #define xxx_T_print_pretty(f, ctx) \ do { \ z = TEMPLATE(T, fprint_pretty)(file, (f), (ctx)); \ if (z <= 0) \ return z; \ } while(0) int TEMPLATE(T, mat_fprint) (FILE * file, const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { int z; slong i, j; slong r = mat->r; slong c = mat->c; xxx_printf(); for (i = 0; (i < r); i++) { for (j = 0; j < c; j++) { xxx_T_print(mat->rows[i] + j, ctx); if (j != c - 1) xxx_putc(' '); } if (i != r - 1) xxx_putc(' '); } return z; } int TEMPLATE(T, mat_fprint_pretty) (FILE * file, const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { int z; slong i, j; slong r = mat->r; slong c = mat->c; xxx_putc('['); for (i = 0; i < r; i++) { xxx_putc('['); for (j = 0; j < c; j++) { xxx_T_print_pretty(mat->rows[i] + j, ctx); if (j != c - 1) xxx_putc(' '); } xxx_putc(']'); xxx_putc('\n'); } xxx_putc(']'); return z; } #undef xxx_putc #undef xxx_printf #undef xxx_T_print int TEMPLATE(T, mat_print)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { return TEMPLATE(T, mat_fprint)(stdout, mat, ctx); } int TEMPLATE(T, mat_print_pretty)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { return TEMPLATE(T, mat_fprint_pretty)(stdout, mat, ctx); } #endif flint-3.1.3/src/fq_mat_templates/is_one.c000066400000000000000000000016161461254215100203730ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, mat_is_one) (const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { slong i, j; if (mat->r == 0 || mat->c == 0) return 1; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) if (i == j ? !TEMPLATE(T, is_one)(TEMPLATE(T, mat_entry)(mat, i, j), ctx) : !TEMPLATE(T, is_zero)(TEMPLATE(T, mat_entry)(mat, i, j), ctx)) return 0; } return 1; } #endif flint-3.1.3/src/fq_mat_templates/is_zero.c000066400000000000000000000014401461254215100205640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, mat_is_zero) (const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { slong j; if (mat->r == 0 || mat->c == 0) return 1; for (j = 0; j < mat->r; j++) { if (!_TEMPLATE(T, vec_is_zero) (mat->rows[j], mat->c, ctx)) return 0; } return 1; } #endif flint-3.1.3/src/fq_mat_templates/lu.c000066400000000000000000000012221461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong TEMPLATE(T, mat_lu) (slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx) { return TEMPLATE(T, mat_lu_recursive) (P, A, rank_check, ctx); } #endif flint-3.1.3/src/fq_mat_templates/lu_classical.c000066400000000000000000000053541461254215100215600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" static inline int TEMPLATE(T, mat_pivot) (TEMPLATE(T, mat_t) A, slong * P, slong start_row, slong col, const TEMPLATE(T, ctx_t) ctx) { slong j, t; TEMPLATE(T, struct) * u; if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, start_row, col), ctx)) return 1; for (j = start_row + 1; j < A->r; j++) { if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, j, col), ctx)) { u = A->rows[j]; A->rows[j] = A->rows[start_row]; A->rows[start_row] = u; t = P[j]; P[j] = P[start_row]; P[start_row] = t; return -1; } } return 0; } slong TEMPLATE(T, mat_lu_classical) (slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) d, e, neg_e; TEMPLATE(T, struct) ** a; slong i, m, n, rank, length, row, col; m = A->r; n = A->c; a = A->rows; rank = row = col = 0; for (i = 0; i < m; i++) P[i] = i; TEMPLATE(T, init) (d, ctx); TEMPLATE(T, init) (e, ctx); TEMPLATE(T, init) (neg_e, ctx); while (row < m && col < n) { if (TEMPLATE(T, mat_pivot) (A, P, row, col, ctx) == 0) { if (rank_check) { rank = 0; goto cleanup; } col++; continue; } rank++; TEMPLATE(T, inv) (d, a[row] + col, ctx); length = n - col - 1; for (i = row + 1; i < m; i++) { TEMPLATE(T, mul) (e, a[i] + col, d, ctx); if (length != 0) { TEMPLATE(T, neg) (neg_e, e, ctx); _TEMPLATE3(T, vec_scalar_addmul, T) (a[i] + col + 1, a[row] + col + 1, length, neg_e, ctx); } TEMPLATE(T, zero) (a[i] + col, ctx); TEMPLATE(T, set) (a[i] + rank - 1, e, ctx); } row++; col++; } cleanup: TEMPLATE(T, clear) (d, ctx); TEMPLATE(T, clear) (e, ctx); TEMPLATE(T, clear) (neg_e, ctx); return rank; } #endif flint-3.1.3/src/fq_mat_templates/lu_recursive.c000066400000000000000000000067661461254215100216410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" static void _apply_permutation(slong * AP, TEMPLATE(T, mat_t) A, slong * P, slong n, slong offset) { if (n != 0) { TEMPLATE(T, struct) ** Atmp; slong *APtmp; slong i; Atmp = flint_malloc(sizeof(TEMPLATE(T, struct) *) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } slong TEMPLATE(T, mat_lu_recursive) (slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx) { slong i, j, m, n, r1, r2, n1; TEMPLATE(T, mat_t) A0, A1, A00, A01, A10, A11; slong *P1; m = A->r; n = A->c; if (m < TEMPLATE(CAP_T, MAT_LU_RECURSIVE_CUTOFF) || n < TEMPLATE(CAP_T, MAT_LU_RECURSIVE_CUTOFF)) { r1 = TEMPLATE(T, mat_lu_classical) (P, A, rank_check, ctx); return r1; } n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; P1 = flint_malloc(sizeof(slong) * m); TEMPLATE(T, mat_window_init) (A0, A, 0, 0, m, n1, ctx); TEMPLATE(T, mat_window_init) (A1, A, 0, n1, m, n, ctx); r1 = TEMPLATE(T, mat_lu) (P1, A0, rank_check, ctx); if (rank_check && (r1 != n1)) { flint_free(P1); TEMPLATE(T, mat_window_clear) (A0, ctx); TEMPLATE(T, mat_window_clear) (A1, ctx); return 0; } if (r1 != 0) { _apply_permutation(P, A, P1, m, 0); } TEMPLATE(T, mat_window_init) (A00, A, 0, 0, r1, r1, ctx); TEMPLATE(T, mat_window_init) (A10, A, r1, 0, m, r1, ctx); TEMPLATE(T, mat_window_init) (A01, A, 0, n1, r1, n, ctx); TEMPLATE(T, mat_window_init) (A11, A, r1, n1, m, n, ctx); if (r1 != 0) { TEMPLATE(T, mat_solve_tril) (A01, A00, A01, 1, ctx); TEMPLATE(T, mat_submul) (A11, A11, A10, A01, ctx); } r2 = TEMPLATE(T, mat_lu) (P1, A11, rank_check, ctx); if (rank_check && (r1 + r2 < FLINT_MIN(m, n))) { r1 = r2 = 0; } else { _apply_permutation(P, A, P1, m - r1, r1); /* Compress L */ if (r1 != n1) { for (i = 0; i < m - r1; i++) { TEMPLATE(T, struct) * row = A->rows[r1 + i]; for (j = 0; j < FLINT_MIN(i, r2); j++) { TEMPLATE(T, set) (row + r1 + j, row + n1 + j, ctx); TEMPLATE(T, zero) (row + n1 + j, ctx); } } } } flint_free(P1); TEMPLATE(T, mat_window_clear) (A00, ctx); TEMPLATE(T, mat_window_clear) (A01, ctx); TEMPLATE(T, mat_window_clear) (A10, ctx); TEMPLATE(T, mat_window_clear) (A11, ctx); TEMPLATE(T, mat_window_clear) (A0, ctx); TEMPLATE(T, mat_window_clear) (A1, ctx); return r1 + r2; } #endif flint-3.1.3/src/fq_mat_templates/mat_entry_set.c000066400000000000000000000013031461254215100217650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_entry_set)(TEMPLATE(T, mat_t) mat, slong i, slong j, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, set)(TEMPLATE(T, mat_entry)(mat, i, j), x, ctx); } #endif flint-3.1.3/src/fq_mat_templates/mat_invert_cols.c000066400000000000000000000017621461254215100223110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_invert_cols)(TEMPLATE(T, mat_t) mat, slong * perm, const TEMPLATE(T, ctx_t) ctx) { if (!TEMPLATE(T, mat_is_empty)(mat, ctx)) { slong t, i; slong c = mat->c; slong k = mat->c/2; if (perm != NULL) for (i = 0; i < k; i++) FLINT_SWAP(slong, perm[i], perm[c - i - 1]); for (t = 0; t < mat->r; t++) for (i = 0; i < k; i++) TEMPLATE(T, swap)(TEMPLATE(T, mat_entry)(mat, t, i), TEMPLATE(T, mat_entry)(mat, t, c - i - 1), ctx); } } #endif flint-3.1.3/src/fq_mat_templates/mat_swap_cols.c000066400000000000000000000015631461254215100217530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_swap_cols)(TEMPLATE(T, mat_t) mat, slong * perm, slong r, slong s, const TEMPLATE(T, ctx_t) ctx) { if (r != s && !TEMPLATE(T, mat_is_empty)(mat, ctx)) { slong t; if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); for (t = 0; t < mat->r; t++) TEMPLATE(T, swap)(TEMPLATE(T, mat_entry)(mat, t, r), TEMPLATE(T, mat_entry)(mat, t, s), ctx); } } #endif flint-3.1.3/src/fq_mat_templates/mat_swap_entrywise.c000066400000000000000000000014511461254215100230400ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_swap_entrywise)(TEMPLATE(T, mat_t) mat1, TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { slong i, j; for (i = 0; i < TEMPLATE(T, mat_nrows)(mat1, ctx); i++) for (j = 0; j < TEMPLATE(T, mat_ncols)(mat1, ctx); j++) TEMPLATE(T, swap)(TEMPLATE(T, mat_entry)(mat2, i, j), TEMPLATE(T, mat_entry)(mat1, i, j), ctx); } #endif flint-3.1.3/src/fq_mat_templates/minpoly.c000066400000000000000000000115631461254215100206100ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_minpoly) (TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) X, const TEMPLATE(T, ctx_t) ctx) { slong n = X->r, i, j, c, c1, c2, r1, r2; slong * P1, * P2, * L1, * L2; TEMPLATE(T, mat_t) A, B, v; int first_poly = 1, indep = 1; TEMPLATE(T, poly_t) b, g, r; TEMPLATE(T, t) t, h; TMP_INIT; if (X->r != X->c) { flint_throw(FLINT_ERROR, "Exception (fq_mat_charpoly). Non-square matrix.\n"); } if (n == 0) { TEMPLATE(T, poly_one) (p, ctx); return; } TEMPLATE(T, init) (t, ctx); if (n == 1) { TEMPLATE(T, set_ui) (t, 1, ctx); TEMPLATE(T, poly_set_coeff) (p, 1, t, ctx); TEMPLATE(T, neg) (t, TEMPLATE(T, mat_entry) (X, 0, 0), ctx); TEMPLATE(T, poly_set_coeff) (p, 0, t, ctx); _TEMPLATE(T, poly_set_length) (p, 2, ctx); TEMPLATE(T, clear) (t, ctx); return; } TMP_START; TEMPLATE(T, init) (h, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_one) (p, ctx); TEMPLATE(T, mat_init) (A, n + 1, 2*n + 1, ctx); TEMPLATE(T, mat_init) (B, n, n, ctx); TEMPLATE(T, mat_init) (v, n, 1, ctx); L1 = (slong *) TMP_ALLOC((n + 1)*sizeof(slong)); L2 = (slong *) TMP_ALLOC(n*sizeof(slong)); P1 = (slong *) TMP_ALLOC((2*n + 1)*sizeof(slong)); P2 = (slong *) TMP_ALLOC(n*sizeof(slong)); for (i = 1; i <= n + 1; i++) L1[i - 1] = n + i; for (i = 1; i <= n; i++) L2[i - 1] = n; for (i = 1; i < n; i++) P2[i] = -WORD(1); P2[0] = 0; r2 = c2 = 0; first_poly = 1; while (r2 < n) { for (i = 0; i < 2*n + 1; i++) P1[i] = -WORD(1); for (i = 0; i < n; i++) { TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (v, i, 0), ctx); TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (B, r2, i), ctx); TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, 0, i), ctx); } P1[c2] = 0; P2[c2] = r2; TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (v, c2, 0), ctx); TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (B, r2, c2), ctx); TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (A, 0, c2), ctx); TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (A, 0, n), ctx); indep = 1; r1 = 0; c1 = -WORD(1); while (c1 < n && r1 < n) { r1++; r2 = indep ? r2 + 1 : r2; TEMPLATE(T, mat_mul) (v, X, v, ctx); for (i = 0; i < n; i++) TEMPLATE(T, set) (TEMPLATE(T, mat_entry) (A, r1, i), TEMPLATE(T, mat_entry) (v, i, 0), ctx); for (i = n; i < n + r1; i++) TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, r1, i), ctx); TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (A, r1, n + r1), ctx); c1 = TEMPLATE(T, mat_reduce_row) (A, P1, L1, r1, ctx); if (indep && r2 < n && !first_poly) { for (i = 0; i < n; i++) TEMPLATE(T, set) (TEMPLATE(T, mat_entry) (B, r2, i), TEMPLATE(T, mat_entry) (v, i, 0), ctx); c = TEMPLATE(T, mat_reduce_row) (B, P2, L2, r2, ctx); indep = c != -WORD(1); } } if (first_poly) { for (i = 0; i < n; i++) P2[i] = P1[i]; r2 = r1; } c = -WORD(1); for (i = c2 + 1; i < n; i++) { if (P2[i] == -WORD(1)) { c = i; break; } } c2 = c; TEMPLATE(T, poly_fit_length) (b, r1 + 1, ctx); TEMPLATE(T, inv) (h, TEMPLATE(T, mat_entry) (A, r1, n + r1), ctx); for (i = 0; i < r1 + 1; i++) { TEMPLATE(T, mul) (t, TEMPLATE(T, mat_entry) (A, r1, n + i), h, ctx); TEMPLATE(T, poly_set_coeff) (b, i, t, ctx); } _TEMPLATE(T, poly_set_length) (b, r1 + 1, ctx); TEMPLATE(T, poly_gcd) (g, p, b, ctx); TEMPLATE(T, poly_mul) (p, p, b, ctx); TEMPLATE(T, poly_divrem) (p, r, p, g, ctx); if (first_poly && r2 < n) { for (i = 0; i < r1; i++) { for (j = 0; j < n; j++) TEMPLATE(T, set) (TEMPLATE(T, mat_entry) (B, i, j), TEMPLATE(T, mat_entry) (A, i, j), ctx); } } first_poly = 0; } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (v, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, clear) (t, ctx); TEMPLATE(T, clear) (h, ctx); TMP_END; } #endif flint-3.1.3/src/fq_mat_templates/mul.c000066400000000000000000000022031461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_mul) (TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { FLINT_ASSERT(C->r == A->r); FLINT_ASSERT(C->c == B->c); FLINT_ASSERT(A->c == B->r); if (C == A || C == B) { TEMPLATE(T, mat_t) TT; TEMPLATE(T, mat_init) (TT, A->r, B->c, ctx); TEMPLATE(T, mat_mul) (TT, A, B, ctx); TEMPLATE(T, mat_swap_entrywise) (TT, C, ctx); TEMPLATE(T, mat_clear) (TT, ctx); return; } if (TEMPLATE(CAP_T, MAT_MUL_KS_CUTOFF) (A->r, B->c, ctx)) TEMPLATE(T, mat_mul_KS) (C, A, B, ctx); else TEMPLATE(T, mat_mul_classical) (C, A, B, ctx); } #endif flint-3.1.3/src/fq_mat_templates/mul_KS.c000066400000000000000000000045731461254215100203160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "fmpz_mat.h" void TEMPLATE(T, mat_mul_KS) (TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { slong bits; slong ar, bc, br; slong i, j; fmpz_mat_t fa, fb, fc; fmpz_t beta; ar = A->r; br = B->r; bc = B->c; if (br == 0) { TEMPLATE(T, mat_zero) (C, ctx); return; } /* Compute the number of bits needed */ /* TODO: Make this generic based on say an TEMPLATE(T, * bits_needed) and TEMPLATE(T, bit_pack) */ fmpz_init(beta); #if defined(FQ_NMOD_MAT_H) || defined(FQ_ZECH_MAT_H) fmpz_set_ui(beta, TEMPLATE(T, ctx_prime) (ctx)); #else fmpz_set(beta, TEMPLATE(T, ctx_prime) (ctx)); #endif fmpz_sub_ui(beta, beta, 1); fmpz_mul(beta, beta, beta); fmpz_mul_si(beta, beta, A->c); fmpz_mul_si(beta, beta, TEMPLATE(T, ctx_degree) (ctx)); bits = fmpz_bits(beta) + 1; fmpz_mat_init(fa, A->r, A->c); fmpz_mat_init(fb, B->r, B->c); fmpz_mat_init(fc, A->r, B->c); for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) TEMPLATE(T, bit_pack) (fmpz_mat_entry(fa, i, j), TEMPLATE(T, mat_entry) (A, i, j), bits, ctx); for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) TEMPLATE(T, bit_pack) (fmpz_mat_entry(fb, i, j), TEMPLATE(T, mat_entry) (B, i, j), bits, ctx); fmpz_mat_mul(fc, fa, fb); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { TEMPLATE(T, bit_unpack) (TEMPLATE(T, mat_entry) (C, i, j), fmpz_mat_entry(fc, i, j), bits, ctx); } } fmpz_mat_clear(fa); fmpz_mat_clear(fb); fmpz_mat_clear(fc); fmpz_clear(beta); } #endif flint-3.1.3/src/fq_mat_templates/mul_classical.c000066400000000000000000000032711461254215100217310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_mul_classical) (TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { slong ar, bc, br; slong i, j; TEMPLATE(T, struct) * trB; TMP_INIT; ar = A->r; br = B->r; bc = B->c; if (br == 0) { TEMPLATE(T, mat_zero) (C, ctx); return; } if (C == A || C == B) { TEMPLATE(T, mat_t) T; TEMPLATE(T, mat_init) (T, ar, bc, ctx); TEMPLATE(T, mat_mul_classical) (T, A, B, ctx); TEMPLATE(T, mat_swap_entrywise) (C, T, ctx); TEMPLATE(T, mat_clear) (T, ctx); return; } TMP_START; trB = (TEMPLATE(T, struct) *) TMP_ALLOC(br*bc*sizeof(TEMPLATE(T, struct))); /* shallow transpose so columns of B are vectors */ for (i = 0; i < br; i++) { for (j = 0; j < bc; j++) trB[j*br + i] = *TEMPLATE(T, mat_entry) (B, i, j); } for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { _TEMPLATE(T, vec_dot) (TEMPLATE(T, mat_entry) (C, i, j), A->rows[i], trB + j * br, br, ctx); } } TMP_END; } #endif flint-3.1.3/src/fq_mat_templates/mul_vec.c000066400000000000000000000033631461254215100205520ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_mul_vec)(TEMPLATE(T, struct) * c, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, struct) * b, slong blen, const TEMPLATE(T, ctx_t) ctx) { slong i, j; slong len = FLINT_MIN(A->c, blen); TEMPLATE(T, t) t; TEMPLATE(T, init)(t, ctx); for (i = A->r - 1; i >= 0; i--) { TEMPLATE(T, zero)(c + i, ctx); for (j = 0; j < len; j++) { TEMPLATE(T, mul)(t, TEMPLATE(T, mat_entry)(A, i, j), b + j, ctx); TEMPLATE(T, add)(c + i, c + i, t, ctx); } } TEMPLATE(T, clear)(t, ctx); } void TEMPLATE(T, mat_mul_vec_ptr)(TEMPLATE(T, struct) * const * c, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, struct) * const * b, slong blen, const TEMPLATE(T, ctx_t) ctx) { slong i, j; slong len = FLINT_MIN(A->c, blen); TEMPLATE(T, t) t; TEMPLATE(T, init)(t, ctx); for (i = A->r - 1; i >= 0; i--) { TEMPLATE(T, zero)(c[i], ctx); for (j = 0; j < len; j++) { TEMPLATE(T, mul)(t, TEMPLATE(T, mat_entry)(A, i, j), b[j], ctx); TEMPLATE(T, add)(c[i], c[i], t, ctx); } } TEMPLATE(T, clear)(t, ctx); } #endif flint-3.1.3/src/fq_mat_templates/neg.c000066400000000000000000000014111461254215100176610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_neg) (TEMPLATE(T, mat_t) res, const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { slong i; if (res->c < 1) return; for (i = 0; i < res->r; i++) _TEMPLATE(T, vec_neg) (res->rows[i], mat->rows[i], res->c, ctx); } #endif flint-3.1.3/src/fq_mat_templates/nullspace.c000066400000000000000000000042511461254215100211030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong TEMPLATE(T, mat_nullspace) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx) { slong i, j, k, m, n, rank, nullity; slong *p; slong *pivots; slong *nonpivots; TEMPLATE(T, mat_t) tmp; m = A->r; n = A->c; p = flint_malloc(sizeof(slong) * FLINT_MAX(m, n)); TEMPLATE(T, mat_init_set) (tmp, A, ctx); rank = TEMPLATE(T, mat_rref) (tmp, tmp, ctx); nullity = n - rank; TEMPLATE(T, mat_zero) (X, ctx); if (rank == 0) { for (i = 0; i < nullity; i++) TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (X, i, i), ctx); } else if (nullity) { pivots = p; /* length = rank */ nonpivots = p + rank; /* length = nullity */ for (i = j = k = 0; i < rank; i++) { while (TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (tmp, i, j), ctx)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) { TEMPLATE(T, neg) (TEMPLATE(T, mat_entry) (X, pivots[j], i), TEMPLATE(T, mat_entry) (tmp, j, nonpivots[i]), ctx); } TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (X, nonpivots[i], i), ctx); } } flint_free(p); TEMPLATE(T, mat_clear) (tmp, ctx); return nullity; } #endif flint-3.1.3/src/fq_mat_templates/one.c000066400000000000000000000012601461254215100176730ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_one)(TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx) { slong i, n; TEMPLATE(T, mat_zero)(mat, ctx); n = FLINT_MIN(mat->r, mat->c); for (i = 0; i < n; i++) TEMPLATE(T, one)(TEMPLATE(T, mat_entry)(mat, i, i), ctx); } #endif flint-3.1.3/src/fq_mat_templates/profile/000077500000000000000000000000001461254215100204075ustar00rootroot00000000000000flint-3.1.3/src/fq_mat_templates/profile/p-mul.c000066400000000000000000000047011461254215100216070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include #include "flint.h" #include "fmpz.h" #include "templates.h" #include #include "profiler.h" #define nalgs 2 #define cpumin 2 #define ncases 1 int main(int argc, char** argv) { fmpz_t p; int c, n, reps = 0; slong d, mat_size; fq_ctx_t ctx; fq_mat_t f, g, h; double s[nalgs]; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); d = atol(argv[2]); mat_size = atol(argv[3]); TEMPLATE(T, ctx_init)(ctx, p, d, "a"); TEMPLATE(T, mat_init)(f, mat_size, mat_size, ctx); TEMPLATE(T, mat_init)(g, mat_size, mat_size, ctx); TEMPLATE(T, mat_init)(h, mat_size, mat_size, ctx); for (c = 0; c < nalgs; c++) s[c] = 0.0; for (n = 0; n < ncases; n++) { double t[nalgs]; int lo, loops = 1; /* Construct random elements of fq */ { TEMPLATE(T, mat_randtest)(g, state, ctx); TEMPLATE(T, mat_randtest)(h, state, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, mat_mul_classical)(h, f, g, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, mat_mul_KS)(h, f, g, ctx); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { printf("%20f", s[c] / (double) reps); fflush(stdout); } printf("\n"); TEMPLATE(T, mat_clear)(f, ctx); TEMPLATE(T, mat_clear)(g, ctx); TEMPLATE(T, mat_clear)(h, ctx); TEMPLATE(T, ctx_clear)(ctx); fmpz_clear(p); FLINT_TEST_CLEANUP(state); return 0; } #endif flint-3.1.3/src/fq_mat_templates/randops.c000066400000000000000000000035141461254215100205640ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_randops) (TEMPLATE(T, mat_t) mat, flint_rand_t state, slong count, const TEMPLATE(T, ctx_t) ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; if (mat->r == 0 || mat->c == 0) return; for (c = 0; c < count; c++) { if (n_randint(state, 2)) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) TEMPLATE(T, add) (mat->rows[j] + k, mat->rows[j] + k, mat->rows[i] + k, ctx); else for (k = 0; k < n; k++) TEMPLATE(T, sub) (mat->rows[j] + k, mat->rows[j] + k, mat->rows[i] + k, ctx); } else { if ((i = n_randint(state, n)) == (j = n_randint(state, n))) continue; if (n_randint(state, 2)) for (k = 0; k < m; k++) TEMPLATE(T, add) (mat->rows[k] + j, mat->rows[k] + j, mat->rows[k] + i, ctx); else for (k = 0; k < m; k++) TEMPLATE(T, sub) (mat->rows[k] + j, mat->rows[k] + j, mat->rows[k] + i, ctx); } } } #endif flint-3.1.3/src/fq_mat_templates/randpermdiag.c000066400000000000000000000022331461254215100215500ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" #include "perm.h" int TEMPLATE(T, mat_randpermdiag) (TEMPLATE(T, mat_t) mat, flint_rand_t state, TEMPLATE(T, struct) * diag, slong n, const TEMPLATE(T, ctx_t) ctx) { int parity; slong i; slong *rows; slong *cols; rows = _perm_init(mat->r); cols = _perm_init(mat->c); parity = _perm_randtest(rows, mat->r, state); parity ^= _perm_randtest(cols, mat->c, state); TEMPLATE(T, mat_zero) (mat, ctx); for (i = 0; i < n; i++) TEMPLATE(T, mat_entry_set) (mat, rows[i], cols[i], diag + i, ctx); _perm_clear(rows); _perm_clear(cols); return parity; } #endif flint-3.1.3/src/fq_mat_templates/randrank.c000066400000000000000000000020301461254215100207060ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_randrank) (TEMPLATE(T, mat_t) mat, flint_rand_t state, slong rank, const TEMPLATE(T, ctx_t) ctx) { slong i; TEMPLATE(T, struct) * diag; if (rank < 0 || rank > mat->r || rank > mat->c) { flint_throw(FLINT_ERROR, "(%s): Impossible rank.\n", __func__); } diag = _TEMPLATE(T, vec_init) (rank, ctx); for (i = 0; i < rank; i++) TEMPLATE(T, randtest_not_zero) (diag + i, state, ctx); TEMPLATE(T, mat_randpermdiag) (mat, state, diag, rank, ctx); _TEMPLATE(T, vec_clear) (diag, rank, ctx); } #endif flint-3.1.3/src/fq_mat_templates/randtest.c000066400000000000000000000014071461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_randtest) (TEMPLATE(T, mat_t) mat, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { slong r, c, i, j; r = mat->r; c = mat->c; for (i = 0; i < r; i++) for (j = 0; j < c; j++) TEMPLATE(T, randtest) (mat->rows[i] + j, state, ctx); } #endif flint-3.1.3/src/fq_mat_templates/randtril.c000066400000000000000000000023051461254215100207320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_randtril) (TEMPLATE(T, mat_t) mat, flint_rand_t state, int unit, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * e; slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { e = TEMPLATE(T, mat_entry) (mat, i, j); if (j < i) { TEMPLATE(T, randtest) (e, state, ctx); } else if (i == j) { TEMPLATE(T, randtest) (e, state, ctx); if (unit || TEMPLATE(T, is_zero) (e, ctx)) TEMPLATE(T, one) (e, ctx); } else { TEMPLATE(T, zero) (e, ctx); } } } } #endif flint-3.1.3/src/fq_mat_templates/randtriu.c000066400000000000000000000023041461254215100207420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_randtriu) (TEMPLATE(T, mat_t) mat, flint_rand_t state, int unit, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * e; slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { e = TEMPLATE(T, mat_entry) (mat, i, j); if (j > i) { TEMPLATE(T, randtest) (e, state, ctx); } else if (i == j) { TEMPLATE(T, randtest) (e, state, ctx); if (unit || TEMPLATE(T, is_zero)(e, ctx)) TEMPLATE(T, one) (e, ctx); } else { TEMPLATE(T, zero) (e, ctx); } } } } #endif flint-3.1.3/src/fq_mat_templates/rank.c000066400000000000000000000016521461254215100200520ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong TEMPLATE(T, mat_rank) (const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx) { slong m, n, rank; slong *perm; TEMPLATE(T, mat_t) tmp; m = A->r; n = A->c; if (m == 0 || n == 0) return 0; TEMPLATE(T, mat_init_set) (tmp, A, ctx); perm = flint_malloc(sizeof(slong) * m); rank = TEMPLATE(T, mat_lu) (perm, tmp, 0, ctx); flint_free(perm); TEMPLATE(T, mat_clear) (tmp, ctx); return rank; } #endif flint-3.1.3/src/fq_mat_templates/reduce_row.c000066400000000000000000000032271461254215100212550ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong TEMPLATE(T, mat_reduce_row)(TEMPLATE(T, mat_t) A, slong * P, slong * L, slong m, const TEMPLATE(T, ctx_t) ctx) { slong n = A->c, i, j, r; TEMPLATE(T, t) h; TEMPLATE(T, init) (h, ctx); for (i = 0; i < n; i++) { if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, m, i), ctx)) { r = P[i]; if (r != -WORD(1)) { for (j = i + 1; j < L[r]; j++) { TEMPLATE(T, mul) (h, TEMPLATE(T, mat_entry) (A, r, j), TEMPLATE(T, mat_entry) (A, m, i), ctx); TEMPLATE(T, sub) (TEMPLATE(T, mat_entry) (A, m, j), TEMPLATE(T, mat_entry) (A, m, j), h, ctx); } TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, m, i), ctx); } else { TEMPLATE(T, inv) (h, TEMPLATE(T, mat_entry) (A, m, i), ctx); TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (A, m, i), ctx); for (j = i + 1; j < L[m]; j++) TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, m, j), TEMPLATE(T, mat_entry) (A, m, j), h, ctx); P[i] = m; TEMPLATE(T, clear) (h, ctx); return i; } } } TEMPLATE(T, clear) (h, ctx); return -WORD(1); } #endif flint-3.1.3/src/fq_mat_templates/rref.c000066400000000000000000000100151461254215100200460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "perm.h" slong TEMPLATE(T, mat_rref) (TEMPLATE(T, mat_t) B, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx) { slong i, j, k, n, rank; slong *pivots; slong *nonpivots; slong *P; TEMPLATE(T, struct) * e; TEMPLATE(T, mat_t) U, V; TEMPLATE(T, mat_set)(B, A, ctx); if (TEMPLATE(T, mat_is_zero)(B, ctx)) return 0; if (B->r == 1) { TEMPLATE(T, struct) * c; slong i, j; slong r = 0; for (i = 0; i < B->c; i++) { c = TEMPLATE(T, mat_entry)(B, 0, i); if (!TEMPLATE(T, is_zero)(c, ctx)) { r = 1; if (TEMPLATE(T, is_one)(c, ctx)) break; TEMPLATE(T, inv)(c, c, ctx); for (j = i + 1;j < B->c; j++) { TEMPLATE(T, mul)(TEMPLATE(T, mat_entry)(B, 0, j), TEMPLATE(T, mat_entry)(B, 0, j), c, ctx); } TEMPLATE(T, one)(c, ctx); break; } } return r; } n = A->c; P = _perm_init(TEMPLATE(T, mat_nrows) (B, ctx)); rank = TEMPLATE(T, mat_lu) (P, B, 0, ctx); _perm_clear(P); if (rank == 0) return rank; /* Clear L */ for (i = 0; i < B->r; i++) for (j = 0; j < FLINT_MIN(i, rank); j++) TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (B, i, j), ctx); /* We now reorder U to proper upper triangular form U | V with U full-rank triangular, set V = U^(-1) V, and then put the column back in the original order. An improvement for some matrices would be to compress V by discarding columns containing nothing but zeros. */ TEMPLATE(T, mat_init) (U, rank, rank, ctx); TEMPLATE(T, mat_init) (V, rank, n - rank, ctx); pivots = flint_malloc(sizeof(slong) * rank); nonpivots = flint_malloc(sizeof(slong) * (n - rank)); for (i = j = k = 0; i < rank; i++) { while (TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (B, i, j), ctx)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (i = 0; i < rank; i++) { for (j = 0; j <= i; j++) { e = TEMPLATE(T, mat_entry) (B, j, pivots[i]); TEMPLATE(T, mat_entry_set) (U, j, i, e, ctx); } } for (i = 0; i < n - rank; i++) { for (j = 0; j < rank; j++) { e = TEMPLATE(T, mat_entry) (B, j, nonpivots[i]); TEMPLATE(T, mat_entry_set) (V, j, i, e, ctx); } } TEMPLATE(T, mat_solve_triu) (V, U, V, 0, ctx); /* Clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j <= i; j++) { if (i == j) { TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (B, j, pivots[i]), ctx); } else { TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (B, j, pivots[i]), ctx); } } } /* Write back the actual content */ for (i = 0; i < n - rank; i++) { for (j = 0; j < rank; j++) TEMPLATE(T, mat_entry_set) (B, j, nonpivots[i], TEMPLATE(T, mat_entry) (V, j, i), ctx); } TEMPLATE(T, mat_clear) (U, ctx); TEMPLATE(T, mat_clear) (V, ctx); flint_free(pivots); flint_free(nonpivots); return rank; } #endif flint-3.1.3/src/fq_mat_templates/set.c000066400000000000000000000015721461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2008-2009 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_set) (TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { if (mat1 != mat2) { slong i; if (mat2->r && mat2->c) for (i = 0; i < mat2->r; i++) _TEMPLATE(T, vec_set) (mat1->rows[i], mat2->rows[i], mat2->c, ctx); } } #endif flint-3.1.3/src/fq_mat_templates/set_fmpz_mod_mat.c000066400000000000000000000016021461254215100224410ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_set_fmpz_mod_mat) (TEMPLATE(T, mat_t) mat1, const fmpz_mod_mat_t mat2, const TEMPLATE(T, ctx_t) ctx) { slong i, j; TEMPLATE(T, t) t; TEMPLATE(T, init)(t, ctx); for (i = 0; i < mat1->r; i++) { for (j = 0; j < mat1->c; j++) { TEMPLATE(T, set_fmpz)(t, fmpz_mod_mat_entry(mat2, i, j), ctx); TEMPLATE(T, mat_entry_set)(mat1, i, j, t, ctx); } } TEMPLATE(T, clear)(t, ctx); } #endif flint-3.1.3/src/fq_mat_templates/set_nmod_mat.c000066400000000000000000000016161461254215100215700ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "nmod_mat.h" void TEMPLATE(T, mat_set_nmod_mat) (TEMPLATE(T, mat_t) mat1, const nmod_mat_t mat2, const TEMPLATE(T, ctx_t) ctx) { slong i, j; TEMPLATE(T, t) t; TEMPLATE(T, init)(t, ctx); for (i = 0; i < mat1->r; i++) { for (j = 0; j < mat1->c; j++) { TEMPLATE(T, set_ui)(t, nmod_mat_entry(mat2, i, j), ctx); TEMPLATE(T, mat_entry_set)(mat1, i, j, t, ctx); } } TEMPLATE(T, clear)(t, ctx); } #endif flint-3.1.3/src/fq_mat_templates/similarity.c000066400000000000000000000032011461254215100212750ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_similarity) (TEMPLATE(T, mat_t) A, slong r, TEMPLATE(T, t) d, const TEMPLATE(T, ctx_t) ctx) { slong n = A->r, i, j; TEMPLATE(T, t) t; TEMPLATE(T, init) (t, ctx); for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) { TEMPLATE(T, mul) (t, TEMPLATE(T, mat_entry) (A, i, r), d, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, i, j), TEMPLATE(T, mat_entry) (A, i, j), t, ctx); } for (j = r + 1; j < n; j++) { TEMPLATE(T, mul) (t, TEMPLATE(T, mat_entry) (A, i, r), d, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, i, j), TEMPLATE(T, mat_entry) (A, i, j), t, ctx); } } for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) { TEMPLATE(T, mul) (t, TEMPLATE(T, mat_entry) (A, j, i), d, ctx); TEMPLATE(T, sub) (TEMPLATE(T, mat_entry) (A, r, i), TEMPLATE(T, mat_entry) (A, r, i), t, ctx); } for (j = r + 1; j < n; j++) { TEMPLATE(T, mul) (t, TEMPLATE(T, mat_entry) (A, j, i), d, ctx); TEMPLATE(T, sub) (TEMPLATE(T, mat_entry) (A, r, i), TEMPLATE(T, mat_entry) (A, r, i), t, ctx); } } TEMPLATE(T, clear) (t, ctx); } #endif flint-3.1.3/src/fq_mat_templates/solve.c000066400000000000000000000026071461254215100202500ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, mat_solve)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { slong i, rank, *perm; TEMPLATE(T, mat_t) LU; int result; if (A->r == 0 || B->c == 0) return 1; TEMPLATE(T, mat_init_set)(LU, A, ctx); perm = flint_malloc(sizeof(slong) * A->r); for (i = 0; i < A->r; i++) perm[i] = i; rank = TEMPLATE(T, mat_lu)(perm, LU, 1, ctx); if (rank == A->r) { TEMPLATE(T, mat_t) PB; TEMPLATE(T, mat_window_init)(PB, B, 0, 0, B->r, B->c, ctx); for (i = 0; i < A->r; i++) PB->rows[i] = B->rows[perm[i]]; TEMPLATE(T, mat_solve_tril)(X, LU, PB, 1, ctx); TEMPLATE(T, mat_solve_triu)(X, LU, X, 0, ctx); TEMPLATE(T, mat_window_clear)(PB, ctx); result = 1; } else { result = 0; } TEMPLATE(T, mat_clear)(LU, ctx); flint_free(perm); return result; } #endif flint-3.1.3/src/fq_mat_templates/solve_tril.c000066400000000000000000000017111461254215100212750ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_solve_tril) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) L, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx) { if (B->r < TEMPLATE(CAP_T, MAT_SOLVE_TRI_ROWS_CUTOFF) || B->c < TEMPLATE(CAP_T, MAT_SOLVE_TRI_COLS_CUTOFF)) { TEMPLATE(T, mat_solve_tril_classical) (X, L, B, unit, ctx); } else { TEMPLATE(T, mat_solve_tril_recursive) (X, L, B, unit, ctx); } } #endif flint-3.1.3/src/fq_mat_templates/solve_tril_classical.c000066400000000000000000000035311461254215100233150ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_solve_tril_classical) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) L, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx) { slong i, j, n, m; TEMPLATE(T, struct) * inv, *tmp; n = L->r; m = B->c; if (!unit) { inv = _TEMPLATE(T, vec_init) (n, ctx); for (i = 0; i < n; i++) TEMPLATE(T, inv) (inv + i, TEMPLATE(T, mat_entry) (L, i, i), ctx); } else inv = NULL; tmp = _TEMPLATE(T, vec_init) (n, ctx); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) TEMPLATE(T, set) (tmp + j, TEMPLATE(T, mat_entry) (X, j, i), ctx); for (j = 0; j < n; j++) { TEMPLATE(T, t) s; TEMPLATE(T, init) (s, ctx); _TEMPLATE(T, vec_dot) (s, L->rows[j], tmp, j, ctx); TEMPLATE(T, sub) (s, TEMPLATE(T, mat_entry) (B, j, i), s, ctx); if (!unit) TEMPLATE(T, mul) (s, s, inv + j, ctx); TEMPLATE(T, set) (tmp + j, s, ctx); TEMPLATE(T, clear) (s, ctx); } for (j = 0; j < n; j++) TEMPLATE(T, mat_entry_set) (X, j, i, tmp + j, ctx); } _TEMPLATE(T, vec_clear) (tmp, n, ctx); if (!unit) _TEMPLATE(T, vec_clear) (inv, n, ctx); } #endif flint-3.1.3/src/fq_mat_templates/solve_tril_recursive.c000066400000000000000000000036751461254215100233770ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_solve_tril_recursive) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) L, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) LA, LC, LD, XX, XY, BX, BY; slong r, n, m; n = L->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A 0]^ [X] == [A^ 0 ] [X] == [A^ X] [C D] [Y] == [-D^ C A^ D^] [Y] == [D^ (Y - C A^ X)] */ TEMPLATE(T, mat_window_init) (LA, L, 0, 0, r, r, ctx); TEMPLATE(T, mat_window_init) (LC, L, r, 0, n, r, ctx); TEMPLATE(T, mat_window_init) (LD, L, r, r, n, n, ctx); TEMPLATE(T, mat_window_init) (BX, B, 0, 0, r, m, ctx); TEMPLATE(T, mat_window_init) (BY, B, r, 0, n, m, ctx); TEMPLATE(T, mat_window_init) (XX, X, 0, 0, r, m, ctx); TEMPLATE(T, mat_window_init) (XY, X, r, 0, n, m, ctx); TEMPLATE(T, mat_solve_tril) (XX, LA, BX, unit, ctx); TEMPLATE(T, mat_submul) (XY, BY, LC, XX, ctx); TEMPLATE(T, mat_solve_tril) (XY, LD, XY, unit, ctx); TEMPLATE(T, mat_window_clear) (LA, ctx); TEMPLATE(T, mat_window_clear) (LC, ctx); TEMPLATE(T, mat_window_clear) (LD, ctx); TEMPLATE(T, mat_window_clear) (BX, ctx); TEMPLATE(T, mat_window_clear) (BY, ctx); TEMPLATE(T, mat_window_clear) (XX, ctx); TEMPLATE(T, mat_window_clear) (XY, ctx); } #endif flint-3.1.3/src/fq_mat_templates/solve_triu.c000066400000000000000000000017111461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_solve_triu) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) U, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx) { if (B->r < TEMPLATE(CAP_T, MAT_SOLVE_TRI_ROWS_CUTOFF) || B->c < TEMPLATE(CAP_T, MAT_SOLVE_TRI_COLS_CUTOFF)) { TEMPLATE(T, mat_solve_triu_classical) (X, U, B, unit, ctx); } else { TEMPLATE(T, mat_solve_triu_recursive) (X, U, B, unit, ctx); } } #endif flint-3.1.3/src/fq_mat_templates/solve_triu_classical.c000066400000000000000000000036311461254215100233270ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_solve_triu_classical) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) U, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx) { slong i, j, n, m; TEMPLATE(T, struct) * inv, *tmp; n = U->r; m = B->c; if (!unit) { inv = _TEMPLATE(T, vec_init) (n, ctx); for (i = 0; i < n; i++) TEMPLATE(T, inv) (inv + i, TEMPLATE(T, mat_entry) (U, i, i), ctx); } else inv = NULL; tmp = _TEMPLATE(T, vec_init) (n, ctx); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) TEMPLATE(T, set) (tmp + j, TEMPLATE(T, mat_entry) (X, j, i), ctx); for (j = n - 1; j >= 0; j--) { TEMPLATE(T, t) s; TEMPLATE(T, init) (s, ctx); _TEMPLATE(T, vec_dot) (s, U->rows[j] + j + 1, tmp + j + 1, n - j - 1, ctx); TEMPLATE(T, sub) (s, TEMPLATE(T, mat_entry) (B, j, i), s, ctx); if (!unit) TEMPLATE(T, mul) (s, s, inv + j, ctx); TEMPLATE(T, set) (tmp + j, s, ctx); TEMPLATE(T, clear) (s, ctx); } for (j = 0; j < n; j++) TEMPLATE(T, mat_entry_set) (X, j, i, tmp + j, ctx); } _TEMPLATE(T, vec_clear) (tmp, n, ctx); if (!unit) _TEMPLATE(T, vec_clear) (inv, n, ctx); } #endif flint-3.1.3/src/fq_mat_templates/solve_triu_recursive.c000066400000000000000000000036241461254215100234020ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_solve_triu_recursive) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) U, const TEMPLATE(T, mat_t) B, int unit, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) UA, UB, UD, XX, XY, BX, BY; slong r, n, m; n = U->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A B]^ [X] == [A^ (X - B D^ Y)] [0 D] [Y] == [ D^ Y ] */ TEMPLATE(T, mat_window_init) (UA, U, 0, 0, r, r, ctx); TEMPLATE(T, mat_window_init) (UB, U, 0, r, r, n, ctx); TEMPLATE(T, mat_window_init) (UD, U, r, r, n, n, ctx); TEMPLATE(T, mat_window_init) (BX, B, 0, 0, r, m, ctx); TEMPLATE(T, mat_window_init) (BY, B, r, 0, n, m, ctx); TEMPLATE(T, mat_window_init) (XX, X, 0, 0, r, m, ctx); TEMPLATE(T, mat_window_init) (XY, X, r, 0, n, m, ctx); TEMPLATE(T, mat_solve_triu) (XY, UD, BY, unit, ctx); TEMPLATE(T, mat_submul) (XX, BX, UB, XY, ctx); TEMPLATE(T, mat_solve_triu) (XX, UA, XX, unit, ctx); TEMPLATE(T, mat_window_clear) (UA, ctx); TEMPLATE(T, mat_window_clear) (UB, ctx); TEMPLATE(T, mat_window_clear) (UD, ctx); TEMPLATE(T, mat_window_clear) (BX, ctx); TEMPLATE(T, mat_window_clear) (BY, ctx); TEMPLATE(T, mat_window_clear) (XX, ctx); TEMPLATE(T, mat_window_clear) (XY, ctx); } #endif flint-3.1.3/src/fq_mat_templates/sub.c000066400000000000000000000015561461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_sub) (TEMPLATE(T, mat_t) res, const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { slong i; if (res->c < 1) return; for (i = 0; i < res->r; i++) _TEMPLATE(T, vec_sub) (res->rows[i], mat1->rows[i], mat2->rows[i], res->c, ctx); } #endif flint-3.1.3/src/fq_mat_templates/submul.c000066400000000000000000000016461461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_submul) (TEMPLATE(T, mat_t) D, const TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) tmp; TEMPLATE(T, mat_init) (tmp, A->r, B->c, ctx); TEMPLATE(T, mat_mul) (tmp, A, B, ctx); TEMPLATE(T, mat_sub) (D, C, tmp, ctx); TEMPLATE(T, mat_clear) (tmp, ctx); } #endif flint-3.1.3/src/fq_mat_templates/swap.c000066400000000000000000000012131461254215100200620ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_swap) (TEMPLATE(T, mat_t) mat1, TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx) { FLINT_SWAP(TEMPLATE(T, mat_struct), *mat1, *mat2); } #endif flint-3.1.3/src/fq_mat_templates/test/000077500000000000000000000000001461254215100177265ustar00rootroot00000000000000flint-3.1.3/src/fq_mat_templates/test/t-add_sub.c000066400000000000000000000032071461254215100217360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_add_sub, state) { slong m, n, rep; for (rep = 0; rep < 50 * flint_test_multiplier(); rep++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A; TEMPLATE(T, mat_t) B; TEMPLATE(T, mat_t) C; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 20); n = n_randint(state, 20); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_neg) (C, A, ctx); TEMPLATE(T, mat_add) (A, A, B, ctx); TEMPLATE(T, mat_sub) (A, A, B, ctx); TEMPLATE(T, mat_neg) (A, A, ctx); if (!TEMPLATE(T, mat_equal) (A, C, ctx)) { printf("FAIL: matrices not equal!\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-can_solve.c000066400000000000000000000076261461254215100223170ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_can_solve, state) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, X2, B, AX; slong i, k, m, n; int solved; /* test random systems */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 50); n = n_randint(state, 50); k = n_randint(state, 50); TEMPLATE(T, mat_init) (A, m, k, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (X, k, n, ctx); TEMPLATE(T, mat_init) (AX, m, n, ctx); TEMPLATE(T, mat_randrank)(A, state, n_randint(state, FLINT_MIN(m, k) + 1), ctx); TEMPLATE(T, mat_randtest)(B, state, ctx); /* Dense */ if (n_randint(state, 2)) TEMPLATE(T, mat_randops)(A, state, 1+n_randint(state, 1+m*m), ctx); solved = TEMPLATE(T, mat_can_solve)(X, A, B, ctx); TEMPLATE(T, mat_mul)(AX, A, X, ctx); if (solved && !TEMPLATE(T, mat_equal)(AX, B, ctx)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"); TEMPLATE(T, mat_print_pretty)(A, ctx); flint_printf("B:\n"); TEMPLATE(T, mat_print_pretty)(B, ctx); flint_printf("X:\n"); TEMPLATE(T, mat_print_pretty)(X, ctx); flint_printf("AX:\n"); TEMPLATE(T, mat_print_pretty)(AX, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, mat_clear)(X, ctx); TEMPLATE(T, mat_clear)(AX, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test random solvable systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); TEMPLATE(T, mat_init) (A, m, k, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (X, k, n, ctx); TEMPLATE(T, mat_init) (X2, k, n, ctx); TEMPLATE(T, mat_init) (AX, m, n, ctx); TEMPLATE(T, mat_randrank)(A, state, n_randint(state, FLINT_MIN(m, k) + 1), ctx); TEMPLATE(T, mat_randtest)(X2, state, ctx); TEMPLATE(T, mat_mul)(B, A, X2, ctx); solved = TEMPLATE(T, mat_can_solve)(X, A, B, ctx); TEMPLATE(T, mat_mul)(AX, A, X, ctx); if (!solved || !TEMPLATE(T, mat_equal)(AX, B, ctx)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"); TEMPLATE(T, mat_print_pretty)(A, ctx); flint_printf("B:\n"); TEMPLATE(T, mat_print_pretty)(B, ctx); flint_printf("X:\n"); TEMPLATE(T, mat_print_pretty)(X, ctx); flint_printf("AX:\n"); TEMPLATE(T, mat_print_pretty)(AX, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, mat_clear)(X, ctx); TEMPLATE(T, mat_clear)(X2, ctx); TEMPLATE(T, mat_clear)(AX, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-charpoly.c000066400000000000000000000036001461254215100221530ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_charpoly, state) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, poly_t) p1, p2; slong i, m, n; /* charpoly(AB) == charpoly(BA) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = m; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (p1, ctx); TEMPLATE(T, poly_init) (p2, ctx); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_mul) (C, A, B, ctx); TEMPLATE(T, mat_charpoly) (p1, C, ctx); TEMPLATE(T, mat_mul) (C, B, A, ctx); TEMPLATE(T, mat_charpoly) (p2, C, ctx); if (!TEMPLATE(T, poly_equal) (p1, p2, ctx)) { flint_printf("FAIL:\n"); flint_printf("charpoly(AB) != charpoly(BA).\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, poly_clear) (p1, ctx); TEMPLATE(T, poly_clear) (p2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-concat_horizontal.c000066400000000000000000000036241461254215100240600ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_concat_horizontal, state) { slong i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, mat_t) window1, window2; slong c1, c2, r1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); c1 = n_randint(state, 10); c2 = n_randint(state, 10); r1 = n_randint(state, 10); TEMPLATE(T, mat_init) (A, r1, c1, ctx); TEMPLATE(T, mat_init) (B, r1, c2, ctx); TEMPLATE(T, mat_init) (C, r1, (c1 + c2), ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_randtest) (C, state, ctx); TEMPLATE(T, mat_concat_horizontal) (C, A, B, ctx); TEMPLATE(T, mat_window_init) (window1, C, 0, 0, r1, c1, ctx); TEMPLATE(T, mat_window_init) (window2, C, 0, c1, r1, (c1 + c2), ctx); if (!(TEMPLATE(T, mat_equal) (window1, A, ctx) && TEMPLATE(T, mat_equal) (window2, B, ctx))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, mat_window_clear) (window1, ctx); TEMPLATE(T, mat_window_clear) (window2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-concat_vertical.c000066400000000000000000000036161461254215100235010ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_concat_vertical, state) { slong i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, mat_t) window1, window2; slong r1, r2, c1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); r1 = n_randint(state, 10); r2 = n_randint(state, 10); c1 = n_randint(state, 10); TEMPLATE(T, mat_init) (A, r1, c1, ctx); TEMPLATE(T, mat_init) (B, r2, c1, ctx); TEMPLATE(T, mat_init) (C, (r1 + r2), c1, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_randtest) (C, state, ctx); TEMPLATE(T, mat_concat_vertical) (C, A, B, ctx); TEMPLATE(T, mat_window_init) (window1, C, 0, 0, r1, c1, ctx); TEMPLATE(T, mat_window_init) (window2, C, r1, 0, (r1+r2), c1, ctx); if (!(TEMPLATE(T, mat_equal) (window1, A, ctx) && TEMPLATE(T, mat_equal) (window2, B, ctx))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, mat_window_clear) (window1, ctx); TEMPLATE(T, mat_window_clear) (window2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-equal.c000066400000000000000000000045231461254215100214460ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_equal, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C, D, E; TEMPLATE(T, t) x; slong m, n, j; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init) (x, ctx); m = n_randint(state, 20); n = n_randint(state, 20); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_init) (D, m + 1, n, ctx); TEMPLATE(T, mat_init) (E, m, n + 1, ctx); if (TEMPLATE(T, mat_equal) (A, D, ctx) || TEMPLATE(T, mat_equal) (A, E, ctx)) { printf("FAIL: different dimensions should not be equal\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_set) (B, A, ctx); if (!TEMPLATE(T, mat_equal) (A, B, ctx)) { printf("FAIL: copied matrices should be equal\n"); fflush(stdout); flint_abort(); } if (m && n) { j = n_randint(state, m * n); TEMPLATE(T, one) (x, ctx); TEMPLATE(T, add) (A->entries + j, A->entries + j, x, ctx); if (TEMPLATE(T, mat_equal) (A, B, ctx)) { printf("FAIL: modified matrices should not be equal\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, mat_clear) (D, ctx); TEMPLATE(T, mat_clear) (E, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-inv.c000066400000000000000000000072011461254215100211270ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_inv, state) { TEMPLATE(T, mat_t) A, B, C, I; TEMPLATE(T, ctx_t) ctx; slong i, j, m, r; int result; for (i = 0; i < 5 * flint_test_multiplier(); i++) { m = n_randint(state, 20); TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, mat_init)(A, m, m, ctx); TEMPLATE(T, mat_init)(B, m, m, ctx); TEMPLATE(T, mat_init)(C, m, m, ctx); TEMPLATE(T, mat_init)(I, m, m, ctx); for (j = 0; j < m; j++) TEMPLATE(T, one)(TEMPLATE(T, mat_entry)(I, j, j), ctx); /* Verify that A * A^-1 = I for random matrices */ TEMPLATE(T, mat_randrank)(A, state, m, ctx); /* Dense or sparse? */ if (n_randint(state, 2)) TEMPLATE(T, mat_randops)(A, state, 1+n_randint(state, 1+m*m), ctx); result = TEMPLATE(T, mat_inv)(B, A, ctx); TEMPLATE(T, mat_mul)(C, A, B, ctx); if (!TEMPLATE(T, mat_equal)(C, I, ctx) || !result) { flint_printf("FAIL:\n"); flint_printf("A * A^-1 != I!\n"); flint_printf("A:\n"); TEMPLATE(T, mat_print_pretty)(A, ctx); flint_printf("A^-1:\n"); TEMPLATE(T, mat_print_pretty)(B, ctx); flint_printf("A * A^-1:\n"); TEMPLATE(T, mat_print_pretty)(C, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } /* Test aliasing */ TEMPLATE(T, mat_set)(C, A, ctx); TEMPLATE(T, mat_inv)(A, A, ctx); TEMPLATE(T, mat_mul)(B, A, C, ctx); if (!TEMPLATE(T, mat_equal)(B, I, ctx)) { flint_printf("FAIL:\n"); flint_printf("aliasing failed!\n"); TEMPLATE(T, mat_print_pretty)(C, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, mat_clear)(C, ctx); TEMPLATE(T, mat_clear)(I, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 20); r = n_randint(state, m); TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, mat_init)(A, m, m, ctx); TEMPLATE(T, mat_init)(B, m, m, ctx); TEMPLATE(T, mat_randrank)(A, state, r, ctx); /* Dense */ if (n_randint(state, 2)) TEMPLATE(T, mat_randops)(A, state, 1+n_randint(state, 1+m*m), ctx); result = TEMPLATE(T, mat_inv)(B, A, ctx); if (result) { flint_printf("FAIL:\n"); flint_printf("singular matrix reported as invertible\n"); fflush(stdout); flint_abort(); } /* Aliasing */ result = TEMPLATE(T, mat_inv)(A, A, ctx); if (result) { flint_printf("FAIL:\n"); flint_printf("singular matrix reported as invertible\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-invert_rows_cols.c000066400000000000000000000036131461254215100237370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_invert_rows_cols, state) { slong m, n, rep, i, j; for (rep = 0; rep < 50 * flint_test_multiplier(); rep++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A; TEMPLATE(T, mat_t) B; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 20); n = n_randint(state, 20); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_set)(B, A, ctx); TEMPLATE(T, mat_invert_rows)(A, NULL, ctx); TEMPLATE(T, mat_invert_cols)(A, NULL, ctx); for (i = 0; i < A->r; i++) { for (j =0; j < A->c; j++) { if (!TEMPLATE(T, equal)(TEMPLATE(T, mat_entry)(B, i, j), TEMPLATE(T, mat_entry)(A, A->r - i - 1, A->c - j - 1), ctx)) { flint_printf("FAIL: B != A\n"); flint_printf("A:\n"); TEMPLATE(T, mat_print_pretty)(A, ctx); flint_printf("B:\n"); TEMPLATE(T, mat_print_pretty)(B, ctx); fflush(stdout); flint_abort(); } } } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-is_zero.c000066400000000000000000000031741461254215100220120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_is_zero, state) { int i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A; TEMPLATE(T, t) x; slong j; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, mat_init) (A, rows, cols, ctx); if (!TEMPLATE(T, mat_is_zero) (A, ctx)) { printf("FAIL!\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, init) (x, ctx); TEMPLATE(T, randtest_not_zero) (x, state, ctx); if (rows && cols) { j = n_randint(state, rows * cols); TEMPLATE(T, add) (A->entries + j, A->entries + j, x, ctx); if (TEMPLATE(T, mat_is_zero) (A, ctx)) { printf("FAIL!\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-lu_classical.c000066400000000000000000000103121461254215100227660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" /* Defined in t-lu_classical.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(TEMPLATE(T, mat_t) A, slong * P) { slong i; TEMPLATE(T, struct) ** tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(TEMPLATE(T, struct) *) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu_classical.c and t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, TEMPLATE(T, mat_t) LU, const TEMPLATE(T, mat_t) A, slong rank, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) B, L, U; slong m, n, i, j; m = A->r; n = A->c; TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (L, m, m, ctx); TEMPLATE(T, mat_init) (U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (LU, i, j), ctx)) { printf("FAIL: wrong shape!\n"); fflush(stdout); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) TEMPLATE(T, mat_entry_set) (L, i, j, TEMPLATE(T, mat_entry) (LU, i, j), ctx); if (i < rank) TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (L, i, i), ctx); for (j = i; j < n; j++) TEMPLATE(T, mat_entry_set) (U, i, j, TEMPLATE(T, mat_entry) (LU, i, j), ctx); } TEMPLATE(T, mat_mul) (B, L, U, ctx); perm(B, P); if (!TEMPLATE(T, mat_equal) (A, B, ctx)) { printf("FAIL\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("LU:\n"); TEMPLATE(T, mat_print_pretty) (LU, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (L, ctx); TEMPLATE(T, mat_clear) (U, ctx); } #endif TEST_TEMPLATE_FUNCTION_START(T, mat_lu_classical, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, LU; slong m, n, r, d, rank; slong *P; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 20); n = n_randint(state, 20); for (r = 0; r <= FLINT_MIN(m, n); r++) { TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_randrank) (A, state, r, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2 * m * n + 1); TEMPLATE(T, mat_randops) (A, state, d, ctx); } TEMPLATE(T, mat_init_set) (LU, A, ctx); P = flint_malloc(sizeof(slong) * m); rank = TEMPLATE(T, mat_lu_classical) (P, LU, 0, ctx); if (r != rank) { printf("FAIL:\n"); printf("wrong rank!\n"); printf("A:"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("LU:"); TEMPLATE(T, mat_print_pretty) (LU, ctx); fflush(stdout); flint_abort(); } check(P, LU, A, rank, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (LU, ctx); flint_free(P); } TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-lu_recursive.c000066400000000000000000000103111461254215100230360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" /* Defined in t-lu_classical.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(TEMPLATE(T, mat_t) A, slong * P) { slong i; TEMPLATE(T, struct) ** tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(TEMPLATE(T, struct) *) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu_classical.c and t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, TEMPLATE(T, mat_t) LU, const TEMPLATE(T, mat_t) A, slong rank, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) B, L, U; slong m, n, i, j; m = A->r; n = A->c; TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (L, m, m, ctx); TEMPLATE(T, mat_init) (U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (LU, i, j), ctx)) { printf("FAIL: wrong shape!\n"); fflush(stdout); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) TEMPLATE(T, mat_entry_set) (L, i, j, TEMPLATE(T, mat_entry) (LU, i, j), ctx); if (i < rank) TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (L, i, i), ctx); for (j = i; j < n; j++) TEMPLATE(T, mat_entry_set) (U, i, j, TEMPLATE(T, mat_entry) (LU, i, j), ctx); } TEMPLATE(T, mat_mul) (B, L, U, ctx); perm(B, P); if (!TEMPLATE(T, mat_equal) (A, B, ctx)) { printf("FAIL\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("LU:\n"); TEMPLATE(T, mat_print_pretty) (LU, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (L, ctx); TEMPLATE(T, mat_clear) (U, ctx); } #endif TEST_TEMPLATE_FUNCTION_START(T, mat_lu_recursive, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, LU; slong m, n, r, d, rank; slong *P; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 20); n = n_randint(state, 20); for (r = 0; r <= FLINT_MIN(m, n); r++) { TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_randrank) (A, state, r, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2 * m * n + 1); TEMPLATE(T, mat_randops) (A, state, d, ctx); } TEMPLATE(T, mat_init_set) (LU, A, ctx); P = flint_malloc(sizeof(slong) * m); rank = TEMPLATE(T, mat_lu_recursive) (P, LU, 0, ctx); if (r != rank) { printf("FAIL:\n"); printf("wrong rank!\n"); printf("A:"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("LU:"); TEMPLATE(T, mat_print_pretty) (LU, ctx); fflush(stdout); flint_abort(); } check(P, LU, A, rank, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (LU, ctx); flint_free(P); } TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-minpoly.c000066400000000000000000000067641461254215100220370ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_minpoly, state) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) t; TEMPLATE(T, mat_t) A, B; TEMPLATE(T, poly_t) p1, p2, q, r; slong i, j, k, m, n; /* minpoly(A) divides charpoly(A) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = m; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (p1, ctx); TEMPLATE(T, poly_init) (p2, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_charpoly) (p1, A, ctx); TEMPLATE(T, mat_minpoly) (p2, A, ctx); TEMPLATE(T, poly_divrem) (q, r, p1, p2, ctx); if (!TEMPLATE(T, poly_is_zero) (r, ctx)) { flint_printf("FAIL:\n"); flint_printf("minpoly(A) doesn't divide charpoly(A).\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, poly_clear) (p1, ctx); TEMPLATE(T, poly_clear) (p2, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* minpoly(P^{-1}AP) == minpoly(A) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = m; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init) (t, ctx); TEMPLATE(T, poly_init) (p1, ctx); TEMPLATE(T, poly_init) (p2, ctx); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); for (j = 0; j < n/2; j++) { for (k = 0; k < n/2; k++) { TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, j + n/2, k), ctx); TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, j, k + n/2), ctx); TEMPLATE(T, set) (TEMPLATE(T, mat_entry) (A, j + n/2, k + n/2), TEMPLATE(T, mat_entry) (A, j, k), ctx); } } TEMPLATE(T, mat_set) (B, A, ctx); TEMPLATE(T, mat_minpoly) (p1, A, ctx); for (j = 0; j < n; j++) { TEMPLATE(T, set_ui) (t, n_randint(state, 6) - 3, ctx); TEMPLATE(T, mat_similarity) (B, n_randint(state, n), t, ctx); } TEMPLATE(T, mat_minpoly) (p2, B, ctx); if (!TEMPLATE(T, poly_equal) (p1, p2, ctx)) { flint_printf("FAIL:\n"); flint_printf("minpoly(P^{-1}AP) != minpoly(A).\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (t, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, poly_clear) (p1, ctx); TEMPLATE(T, poly_clear) (p2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-mul.c000066400000000000000000000110231461254215100211250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_mul, state) { slong i; /* Check aliasing C and A */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; slong m, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 20); n = n_randint(state, 20); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, n, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_randtest) (C, state, ctx); /* noise in output */ TEMPLATE(T, mat_mul) (C, A, B, ctx); TEMPLATE(T, mat_mul) (A, A, B, ctx); if (!TEMPLATE(T, mat_equal) (C, A, ctx)) { printf("FAIL:\n"); printf("A:\n"); TEMPLATE(T, mat_print) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print) (B, ctx); printf("C:\n"); TEMPLATE(T, mat_print) (C, ctx); printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing C and B */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; slong m, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 20); n = n_randint(state, 20); TEMPLATE(T, mat_init) (A, m, m, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_randtest) (C, state, ctx); /* noise in output */ TEMPLATE(T, mat_mul) (C, A, B, ctx); TEMPLATE(T, mat_mul) (B, A, B, ctx); if (!TEMPLATE(T, mat_equal) (C, B, ctx)) { printf("FAIL:\n"); printf("A:\n"); TEMPLATE(T, mat_print) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print) (B, ctx); printf("C:\n"); TEMPLATE(T, mat_print) (C, ctx); printf("\n"); fflush(stdout); flint_abort(); } if (n == m) { TEMPLATE(T, mat_mul) (C, A, B, ctx); TEMPLATE(T, mat_mul) (A, A, B, ctx); if (!TEMPLATE(T, mat_equal) (A, C, ctx)) { flint_printf("FAIL: aliasing failed\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing with windows */ { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, A_window; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, mat_init)(A, 2, 2, ctx); TEMPLATE(T, mat_init)(B, 2, 2, ctx); TEMPLATE(T, mat_window_init)(A_window, A, 0, 0, 2, 2, ctx); TEMPLATE(T, mat_one)(A, ctx); TEMPLATE(T, mat_one)(B, ctx); TEMPLATE(T, set_ui)(TEMPLATE(T, mat_entry)(B, 0, 1), 1, ctx); TEMPLATE(T, set_ui)(TEMPLATE(T, mat_entry)(B, 1, 0), 1, ctx); TEMPLATE(T, mat_mul)(A_window, B, A_window, ctx); if (!TEMPLATE(T, mat_equal)(A, B, ctx)) { flint_printf("FAIL: window aliasing failed\n"); TEMPLATE(T, mat_print)(A, ctx); flint_printf("\n\n"); TEMPLATE(T, mat_print)(B, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_window_clear)(A_window, ctx); TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-mul_KS.c000066400000000000000000000061361461254215100215330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_mul_KS, state) { slong i; /* Check aliasing C and A */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; slong m, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 50); n = n_randint(state, 50); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, n, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_randtest) (C, state, ctx); /* noise in output */ TEMPLATE(T, mat_mul_KS) (C, A, B, ctx); TEMPLATE(T, mat_mul_KS) (A, A, B, ctx); if (!TEMPLATE(T, mat_equal) (C, A, ctx)) { printf("FAIL:\n"); printf("A:\n"); TEMPLATE(T, mat_print) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print) (B, ctx); printf("C:\n"); TEMPLATE(T, mat_print) (C, ctx); printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing C and B */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; slong m, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 50); n = n_randint(state, 50); TEMPLATE(T, mat_init) (A, m, m, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_randtest) (C, state, ctx); /* noise in output */ TEMPLATE(T, mat_mul_KS) (C, A, B, ctx); TEMPLATE(T, mat_mul_KS) (B, A, B, ctx); if (!TEMPLATE(T, mat_equal) (C, B, ctx)) { printf("FAIL:\n"); printf("A:\n"); TEMPLATE(T, mat_print) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print) (B, ctx); printf("C:\n"); TEMPLATE(T, mat_print) (C, ctx); printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-mul_vec.c000066400000000000000000000062251461254215100217720ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_mul_vec, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, struct) * b, * c; TEMPLATE(T, struct) ** bb, ** cc; slong j, m, n, blen; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 50); n = n_randint(state, 50); blen = n_randint(state, 50); TEMPLATE(T, mat_init)(C, m, 1, ctx); TEMPLATE(T, mat_init)(A, m, n, ctx); TEMPLATE(T, mat_init)(B, n, 1, ctx); c = _TEMPLATE(T, vec_init)(m, ctx); b = _TEMPLATE(T, vec_init)(blen, ctx); TEMPLATE(T, mat_randtest)(A, state, ctx); _TEMPLATE(T, vec_randtest)(c, state, m, ctx); _TEMPLATE(T, vec_randtest)(b, state, blen, ctx); cc = FLINT_ARRAY_ALLOC(m, TEMPLATE(T, struct) *); for (j = 0; j < m; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, TEMPLATE(T, struct)); TEMPLATE(T, init)(cc[j], ctx); TEMPLATE(T, set)(cc[j], c + j, ctx); } bb = FLINT_ARRAY_ALLOC(blen, TEMPLATE(T, struct) *); for (j = 0; j < blen; j++) { bb[j] = FLINT_ARRAY_ALLOC(1, TEMPLATE(T, struct)); TEMPLATE(T, init)(bb[j], ctx); TEMPLATE(T, set)(bb[j], b + j, ctx); } TEMPLATE(T, mat_mul_vec)(c, A, b, blen, ctx); TEMPLATE(T, mat_mul_vec_ptr)(cc, A, (const TEMPLATE(T, struct) * const *)bb, blen, ctx); /* supposed to match mul of the chopped or zero-extended b */ for (j = 0; j < n && j < blen; j++) TEMPLATE(T, set)(TEMPLATE(T, mat_entry)(B, j, 0), b + j, ctx); TEMPLATE(T, mat_mul)(C, A, B, ctx); for (j = 0; j < m; j++) { if (!TEMPLATE(T, equal)(TEMPLATE(T, mat_entry)(C, j, 0), c + j, ctx) || !TEMPLATE(T, equal)(TEMPLATE(T, mat_entry)(C, j, 0), cc[j], ctx)) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); _TEMPLATE(T, vec_clear)(c, m, ctx); _TEMPLATE(T, vec_clear)(b, blen, ctx); for (j = 0; j < m; j++) { TEMPLATE(T, clear)(cc[j], ctx); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < blen; j++) { TEMPLATE(T, clear)(bb[j], ctx); flint_free(bb[j]); } flint_free(bb); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-nullspace.c000066400000000000000000000052021461254215100223200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "ulong_extras.h" TEST_TEMPLATE_FUNCTION_START(T, mat_nullspace, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, ker; slong m, n, d, r, nullity, nulrank; m = n_randint(state, 30); n = n_randint(state, 30); for (r = 0; r <= FLINT_MIN(m, n); r++) { TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); d = n_randint(state, 2 * m * n + 1); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (ker, n, n, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_randrank) (A, state, r, ctx); /* Densify */ if (n_randlimb(state) % 2) TEMPLATE(T, mat_randops) (A, state, d, ctx); nullity = TEMPLATE(T, mat_nullspace) (ker, A, ctx); nulrank = TEMPLATE(T, mat_rank) (ker, ctx); if (nullity != nulrank) { flint_printf("FAIL:\n"); flint_printf("rank(ker) != nullity!\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } if (nullity + r != n) { flint_printf("FAIL:\n"); flint_printf("nullity + rank != n\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_mul) (B, A, ker, ctx); if (TEMPLATE(T, mat_rank) (B, ctx) != 0) { flint_printf("FAIL:\n"); flint_printf("A * ker != 0\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (ker, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, ctx_clear) (ctx); } } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-one.c000066400000000000000000000024231461254215100211150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_one, state) { int iter; for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A; slong m, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 10); n = n_randint(state, 10); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_one) (A, ctx); if (!TEMPLATE(T, mat_is_one) (A, ctx)) { printf("FAIL: expected matrix to be one\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-rank.c000066400000000000000000000042111461254215100212640ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_rank, state) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A; slong i, m, n, d, r; /* Maximally sparse matrices of given rank */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); for (r = 0; r <= FLINT_MIN(m, n); r++) { TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_randrank) (A, state, r, ctx); if (r != TEMPLATE(T, mat_rank) (A, ctx)) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); } TEMPLATE(T, ctx_clear) (ctx); } /* Dense */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); for (r = 0; r <= FLINT_MIN(m, n); r++) { d = n_randint(state, 2 * m * n + 1); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_randrank) (A, state, r, ctx); TEMPLATE(T, mat_randops) (A, state, d, ctx); if (r != TEMPLATE(T, mat_rank) (A, ctx)) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); } TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-rref.c000066400000000000000000000124651461254215100213010ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "perm.h" int check_rref_form(slong * perm, TEMPLATE(T, mat_t) A, slong rank, const TEMPLATE(T, ctx_t) ctx) { slong i, j, k, prev_pivot; /* bottom should be zero */ for (i = rank; i < A->r; i++) for (j = 0; j < A->c; j++) if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, i, j), ctx)) return 0; prev_pivot = -1; for (i = 0; i < rank; i++) { for (j = 0; j < A->c; j++) { if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, i, j), ctx)) { /* pivot should have a higher column index than previous */ if (j <= prev_pivot) return 0; /* column should be 0 ... 0 1 0 ... 0 */ for (k = 0; k < rank; k++) { if (i == k) { if (!TEMPLATE(T, is_one) (TEMPLATE(T, mat_entry) (A, k, j), ctx)) return 0; } else { if (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, k, j), ctx)) return 0; } } prev_pivot = j; break; } } } return 1; } TEST_TEMPLATE_FUNCTION_START(T, mat_rref, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C, D; TEMPLATE(T, t) c; slong j, k, m, n, rank1, rank2; slong *perm; int equal; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init) (c, ctx); m = n_randint(state, 20); n = n_randint(state, 20); perm = _perm_init(2 * m); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (D, 2 * m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_init_set) (B, A, ctx); TEMPLATE(T, mat_init_set) (C, A, ctx); rank1 = TEMPLATE(T, mat_rref) (B, B, ctx); if (!check_rref_form(perm, B, rank1, ctx)) { printf("FAIL (malformed rref)\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("\n\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("\n\n"); fflush(stdout); flint_abort(); } /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { TEMPLATE(T, randtest_not_zero) (c, state, ctx); for (k = 0; k < n; k++) { TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (D, perm[j], k), TEMPLATE(T, mat_entry) (A, j, k), c, ctx); } } for (j = 0; j < m; j++) { TEMPLATE(T, randtest_not_zero) (c, state, ctx); for (k = 0; k < n; k++) { TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (D, perm[m + j], k), TEMPLATE(T, mat_entry) (B, j, k), c, ctx); } } rank2 = TEMPLATE(T, mat_rref) (D, D, ctx); equal = (rank1 == rank2); if (equal) { for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) { equal = equal && TEMPLATE(T, equal) (TEMPLATE(T, mat_entry) (B, j, k), TEMPLATE(T, mat_entry) (D, j, k), ctx); } for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) { equal = equal && TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (D, j, k), ctx); } } if (!equal) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("\n\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("\n\n"); TEMPLATE(T, mat_print_pretty) (D, ctx); printf("\n\n"); fflush(stdout); flint_abort(); } _perm_clear(perm); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, mat_clear) (D, ctx); TEMPLATE(T, clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-set_fmpz_mod_mat.c000066400000000000000000000036321461254215100236660ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz_mod_mat.h" #include "fmpz_mod.h" TEST_TEMPLATE_FUNCTION_START(T, mat_set_fmpz_mod_mat, state) { int i, result; /* Check conversion of identity matrix */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) a; fmpz_mod_mat_t m; slong r, c; fmpz_mod_ctx_t pctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); r = n_randint(state, 10); c = n_randint(state, 10); TEMPLATE(T, mat_init)(a, r, c, ctx); TEMPLATE(T, mat_randtest)(a, state, ctx); #if defined(FQ_NMOD_MAT_H) || defined(FQ_ZECH_MAT_H) fmpz_mod_ctx_init_ui(pctx, TEMPLATE(T, ctx_prime)(ctx)); #else fmpz_mod_ctx_init(pctx, TEMPLATE(T, ctx_prime)(ctx)); #endif fmpz_mod_mat_init(m, r, c, pctx); fmpz_mod_mat_one(m, pctx); TEMPLATE(T, mat_set_fmpz_mod_mat)(a, m, ctx); result = (TEMPLATE(T, mat_is_one)(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, mat_print)(a, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mod_mat_clear(m, pctx); fmpz_mod_ctx_clear(pctx); TEMPLATE(T, mat_clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-set_nmod_mat.c000066400000000000000000000034171461254215100230110ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" #include "nmod_mat.h" TEST_TEMPLATE_FUNCTION_START(T, mat_set_nmod_mat, state) { int i, result; /* Check conversion of identity matrix */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) a; nmod_mat_t m; slong r, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); r = n_randint(state, 10); c = n_randint(state, 10); TEMPLATE(T, mat_init)(a, r, c, ctx); TEMPLATE(T, mat_randtest)(a, state, ctx); #if defined(FQ_NMOD_MAT_H) || defined(FQ_ZECH_MAT_H) nmod_mat_init(m, r, c, TEMPLATE(T, ctx_prime)(ctx)); #else nmod_mat_init(m, r, c, fmpz_get_ui(TEMPLATE(T, ctx_prime)(ctx))); #endif nmod_mat_one(m); TEMPLATE(T, mat_set_nmod_mat)(a, m, ctx); result = (TEMPLATE(T, mat_is_one)(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, mat_print)(a, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_mat_clear(m); TEMPLATE(T, mat_clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-solve.c000066400000000000000000000066261461254215100214750ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_solve, state) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, AX; slong i, m, n, r; int solved; for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 50); n = n_randint(state, 50); TEMPLATE(T, mat_init) (A, m, m, ctx); TEMPLATE(T, mat_init) (B, m, n, ctx); TEMPLATE(T, mat_init) (X, m, n, ctx); TEMPLATE(T, mat_init) (AX, m, n, ctx); TEMPLATE(T, mat_randrank)(A, state, m, ctx); TEMPLATE(T, mat_randtest)(B, state, ctx); /* Dense */ if (n_randint(state, 2)) TEMPLATE(T, mat_randops)(A, state, 1+n_randint(state, 1+m*m), ctx); solved = TEMPLATE(T, mat_solve)(X, A, B, ctx); TEMPLATE(T, mat_mul)(AX, A, X, ctx); if (!TEMPLATE(T, mat_equal)(AX, B, ctx) || !solved) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"); TEMPLATE(T, mat_print_pretty)(A, ctx); flint_printf("B:\n"); TEMPLATE(T, mat_print_pretty)(B, ctx); flint_printf("X:\n"); TEMPLATE(T, mat_print_pretty)(X, ctx); flint_printf("AX:\n"); TEMPLATE(T, mat_print_pretty)(AX, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, mat_clear)(X, ctx); TEMPLATE(T, mat_clear)(AX, ctx); TEMPLATE(T, ctx_clear) (ctx); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); r = n_randint(state, m); TEMPLATE(T, mat_init)(A, m, m, ctx); TEMPLATE(T, mat_init)(B, m, n, ctx); TEMPLATE(T, mat_init)(X, m, n, ctx); TEMPLATE(T, mat_init)(AX, m, n, ctx); TEMPLATE(T, mat_randrank)(A, state, r, ctx); TEMPLATE(T, mat_randtest)(B, state, ctx); /* Dense */ if (n_randint(state, 2)) TEMPLATE(T, mat_randops)(A, state, 1+n_randint(state, 1+m*m), ctx); solved = TEMPLATE(T, mat_solve)(X, A, B, ctx); if (solved) { flint_printf("FAIL:\n"); flint_printf("singular system was 'solved'\n"); TEMPLATE(T, mat_print_pretty)(A, ctx); TEMPLATE(T, mat_print_pretty)(X, ctx); TEMPLATE(T, mat_print_pretty)(B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, mat_clear)(X, ctx); TEMPLATE(T, mat_clear)(AX, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-solve_tril.c000066400000000000000000000047511461254215100225240ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_solve_tril, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, Y; slong rows, cols; int unit; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); TEMPLATE(T, mat_init) (A, rows, rows, ctx); TEMPLATE(T, mat_init) (B, rows, cols, ctx); TEMPLATE(T, mat_init) (X, rows, cols, ctx); TEMPLATE(T, mat_init) (Y, rows, cols, ctx); TEMPLATE(T, mat_randtril) (A, state, unit, ctx); TEMPLATE(T, mat_randtest) (X, state, ctx); TEMPLATE(T, mat_mul) (B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ TEMPLATE(T, mat_solve_tril) (Y, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (Y, X, ctx)) { printf("FAIL!\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("X:\n"); TEMPLATE(T, mat_print_pretty) (X, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("Y:\n"); TEMPLATE(T, mat_print_pretty) (Y, ctx); fflush(stdout); flint_abort(); } /* Check aliasing */ TEMPLATE(T, mat_solve_tril) (B, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (B, X, ctx)) { printf("FAIL!\n"); printf("aliasing test failed"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (X, ctx); TEMPLATE(T, mat_clear) (Y, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-solve_tril_classical.c000066400000000000000000000050071461254215100245350ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_solve_tril_classical, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, Y; slong rows, cols; int unit; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); TEMPLATE(T, mat_init) (A, rows, rows, ctx); TEMPLATE(T, mat_init) (B, rows, cols, ctx); TEMPLATE(T, mat_init) (X, rows, cols, ctx); TEMPLATE(T, mat_init) (Y, rows, cols, ctx); TEMPLATE(T, mat_randtril) (A, state, unit, ctx); TEMPLATE(T, mat_randtest) (X, state, ctx); TEMPLATE(T, mat_mul) (B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ TEMPLATE(T, mat_solve_tril_classical) (Y, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (Y, X, ctx)) { printf("FAIL!\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("X:\n"); TEMPLATE(T, mat_print_pretty) (X, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("Y:\n"); TEMPLATE(T, mat_print_pretty) (Y, ctx); fflush(stdout); flint_abort(); } /* Check aliasing */ TEMPLATE(T, mat_solve_tril_classical) (B, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (B, X, ctx)) { printf("FAIL!\n"); printf("aliasing test failed"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (X, ctx); TEMPLATE(T, mat_clear) (Y, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-solve_tril_recursive.c000066400000000000000000000050071461254215100246060ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_solve_tril_recursive, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, Y; slong rows, cols; int unit; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); TEMPLATE(T, mat_init) (A, rows, rows, ctx); TEMPLATE(T, mat_init) (B, rows, cols, ctx); TEMPLATE(T, mat_init) (X, rows, cols, ctx); TEMPLATE(T, mat_init) (Y, rows, cols, ctx); TEMPLATE(T, mat_randtril) (A, state, unit, ctx); TEMPLATE(T, mat_randtest) (X, state, ctx); TEMPLATE(T, mat_mul) (B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ TEMPLATE(T, mat_solve_tril_recursive) (Y, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (Y, X, ctx)) { printf("FAIL!\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("X:\n"); TEMPLATE(T, mat_print_pretty) (X, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("Y:\n"); TEMPLATE(T, mat_print_pretty) (Y, ctx); fflush(stdout); flint_abort(); } /* Check aliasing */ TEMPLATE(T, mat_solve_tril_recursive) (B, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (B, X, ctx)) { printf("FAIL!\n"); printf("aliasing test failed"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (X, ctx); TEMPLATE(T, mat_clear) (Y, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-solve_triu.c000066400000000000000000000047501461254215100225340ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_solve_triu, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, Y; slong rows, cols; int unit; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); TEMPLATE(T, mat_init) (A, rows, rows, ctx); TEMPLATE(T, mat_init) (B, rows, cols, ctx); TEMPLATE(T, mat_init) (X, rows, cols, ctx); TEMPLATE(T, mat_init) (Y, rows, cols, ctx); TEMPLATE(T, mat_randtriu) (A, state, unit, ctx); TEMPLATE(T, mat_randtest) (X, state, ctx); TEMPLATE(T, mat_mul) (B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ TEMPLATE(T, mat_solve_triu) (Y, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (Y, X, ctx)) { printf("FAIL!\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("X:\n"); TEMPLATE(T, mat_print_pretty) (X, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("Y:\n"); TEMPLATE(T, mat_print_pretty) (Y, ctx); fflush(stdout); flint_abort(); } /* Check aliasing */ TEMPLATE(T, mat_solve_triu) (B, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (B, X, ctx)) { printf("FAIL!\n"); printf("aliasing test failed"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (X, ctx); TEMPLATE(T, mat_clear) (Y, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-solve_triu_classical.c000066400000000000000000000050061461254215100245450ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_solve_triu_classical, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, Y; slong rows, cols; int unit; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); TEMPLATE(T, mat_init) (A, rows, rows, ctx); TEMPLATE(T, mat_init) (B, rows, cols, ctx); TEMPLATE(T, mat_init) (X, rows, cols, ctx); TEMPLATE(T, mat_init) (Y, rows, cols, ctx); TEMPLATE(T, mat_randtriu) (A, state, unit, ctx); TEMPLATE(T, mat_randtest) (X, state, ctx); TEMPLATE(T, mat_mul) (B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ TEMPLATE(T, mat_solve_triu_classical) (Y, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (Y, X, ctx)) { printf("FAIL!\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("X:\n"); TEMPLATE(T, mat_print_pretty) (X, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("Y:\n"); TEMPLATE(T, mat_print_pretty) (Y, ctx); fflush(stdout); flint_abort(); } /* Check aliasing */ TEMPLATE(T, mat_solve_triu_classical) (B, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (B, X, ctx)) { printf("FAIL!\n"); printf("aliasing test failed"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (X, ctx); TEMPLATE(T, mat_clear) (Y, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-solve_triu_recursive.c000066400000000000000000000050061461254215100246160ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_solve_triu_recursive, state) { slong i; for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, Y; slong rows, cols; int unit; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); rows = n_randint(state, 50); cols = n_randint(state, 50); unit = n_randint(state, 2); TEMPLATE(T, mat_init) (A, rows, rows, ctx); TEMPLATE(T, mat_init) (B, rows, cols, ctx); TEMPLATE(T, mat_init) (X, rows, cols, ctx); TEMPLATE(T, mat_init) (Y, rows, cols, ctx); TEMPLATE(T, mat_randtriu) (A, state, unit, ctx); TEMPLATE(T, mat_randtest) (X, state, ctx); TEMPLATE(T, mat_mul) (B, A, X, ctx); /* Check Y = A^(-1) * (A * X) = X */ TEMPLATE(T, mat_solve_triu_recursive) (Y, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (Y, X, ctx)) { printf("FAIL!\n"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("X:\n"); TEMPLATE(T, mat_print_pretty) (X, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); printf("Y:\n"); TEMPLATE(T, mat_print_pretty) (Y, ctx); fflush(stdout); flint_abort(); } /* Check aliasing */ TEMPLATE(T, mat_solve_triu_recursive) (B, A, B, unit, ctx); if (!TEMPLATE(T, mat_equal) (B, X, ctx)) { printf("FAIL!\n"); printf("aliasing test failed"); printf("A:\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); printf("B:\n"); TEMPLATE(T, mat_print_pretty) (B, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (X, ctx); TEMPLATE(T, mat_clear) (Y, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-submul.c000066400000000000000000000052531461254215100216470ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_submul, state) { slong i; for (i = 0; i < 2 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C, D, T, E; slong m, k, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 50); k = n_randint(state, 50); n = n_randint(state, 50); TEMPLATE(T, mat_init) (A, m, k, ctx); TEMPLATE(T, mat_init) (B, k, n, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); TEMPLATE(T, mat_init) (D, m, n, ctx); TEMPLATE(T, mat_init) (T, m, n, ctx); TEMPLATE(T, mat_init) (E, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_randtest) (B, state, ctx); TEMPLATE(T, mat_randtest) (C, state, ctx); TEMPLATE(T, mat_submul) (D, C, A, B, ctx); TEMPLATE(T, mat_mul) (T, A, B, ctx); TEMPLATE(T, mat_sub) (E, C, T, ctx); if (!TEMPLATE(T, mat_equal) (D, E, ctx)) { printf("FAIL: results not equal\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); TEMPLATE(T, mat_print_pretty) (B, ctx); TEMPLATE(T, mat_print_pretty) (C, ctx); TEMPLATE(T, mat_print_pretty) (D, ctx); TEMPLATE(T, mat_print_pretty) (E, ctx); fflush(stdout); flint_abort(); } /* Check aliasing */ TEMPLATE(T, mat_submul) (C, C, A, B, ctx); if (!TEMPLATE(T, mat_equal) (C, E, ctx)) { printf("FAIL: results not equal (aliasing)\n"); TEMPLATE(T, mat_print_pretty) (A, ctx); TEMPLATE(T, mat_print_pretty) (B, ctx); TEMPLATE(T, mat_print_pretty) (C, ctx); TEMPLATE(T, mat_print_pretty) (D, ctx); TEMPLATE(T, mat_print_pretty) (E, ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, mat_clear) (D, ctx); TEMPLATE(T, mat_clear) (E, ctx); TEMPLATE(T, mat_clear) (T, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-vec_mul.c000066400000000000000000000062171461254215100217730ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_vec_mul, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, struct) * a, * c; TEMPLATE(T, struct) ** aa, ** cc; slong j, m, n, alen; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 50); n = n_randint(state, 50); alen = n_randint(state, 50); TEMPLATE(T, mat_init)(C, 1, n, ctx); TEMPLATE(T, mat_init)(A, 1, m, ctx); TEMPLATE(T, mat_init)(B, m, n, ctx); c = _TEMPLATE(T, vec_init)(n, ctx); a = _TEMPLATE(T, vec_init)(alen, ctx); TEMPLATE(T, mat_randtest)(B, state, ctx); _TEMPLATE(T, vec_randtest)(c, state, n, ctx); _TEMPLATE(T, vec_randtest)(a, state, alen, ctx); cc = FLINT_ARRAY_ALLOC(n, TEMPLATE(T, struct) *); for (j = 0; j < n; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, TEMPLATE(T, struct)); TEMPLATE(T, init)(cc[j], ctx); TEMPLATE(T, set)(cc[j], c + j, ctx); } aa = FLINT_ARRAY_ALLOC(alen, TEMPLATE(T, struct) *); for (j = 0; j < alen; j++) { aa[j] = FLINT_ARRAY_ALLOC(1, TEMPLATE(T, struct)); TEMPLATE(T, init)(aa[j], ctx); TEMPLATE(T, set)(aa[j], a + j, ctx); } TEMPLATE(T, mat_vec_mul)(c, a, alen, B, ctx); TEMPLATE(T, mat_vec_mul_ptr)(cc, (const TEMPLATE(T, struct) * const *)aa, alen, B, ctx); /* supposed to match mul of the chopped or zero-extended b */ for (j = 0; j < m && j < alen; j++) TEMPLATE(T, set)(TEMPLATE(T, mat_entry)(A, 0, j), a + j, ctx); TEMPLATE(T, mat_mul)(C, A, B, ctx); for (j = 0; j < n; j++) { if (!TEMPLATE(T, equal)(TEMPLATE(T, mat_entry)(C, 0, j), c + j, ctx) || !TEMPLATE(T, equal)(TEMPLATE(T, mat_entry)(C, 0, j), cc[j], ctx)) { flint_printf("FAIL: wrong answer\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, mat_clear)(C, ctx); _TEMPLATE(T, vec_clear)(c, n, ctx); _TEMPLATE(T, vec_clear)(a, alen, ctx); for (j = 0; j < n; j++) { TEMPLATE(T, clear)(cc[j], ctx); flint_free(cc[j]); } flint_free(cc); for (j = 0; j < alen; j++) { TEMPLATE(T, clear)(aa[j], ctx); flint_free(aa[j]); } flint_free(aa); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-window_init_clear.c000066400000000000000000000027621461254215100240420ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_window_init_clear, state) { slong i; for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) a, w; slong j, r1, r2, c1, c2; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, mat_init) (a, rows, cols, ctx); TEMPLATE(T, mat_randtest) (a, state, ctx); r2 = n_randint(state, rows + 1); c2 = n_randint(state, cols + 1); if (r2) r1 = n_randint(state, r2); else r1 = 0; if (c2) c1 = n_randint(state, c2); else c1 = 0; TEMPLATE(T, mat_window_init) (w, a, r1, c1, r2, c2, ctx); for (j = 0; j < r2 - r1; j++) _TEMPLATE(T, vec_zero) (w->rows[j], c2 - c1, ctx); TEMPLATE(T, mat_window_clear) (w, ctx); TEMPLATE(T, mat_clear) (a, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/test/t-zero.c000066400000000000000000000033061461254215100213140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mat_zero, state) { int iter; for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A; slong m, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); m = n_randint(state, 10); n = n_randint(state, 10); TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_randtest) (A, state, ctx); TEMPLATE(T, mat_zero) (A, ctx); if (!TEMPLATE(T, mat_is_zero) (A, ctx)) { printf("FAIL: expected matrix to be zero\n"); fflush(stdout); flint_abort(); } if (m > 0 && n > 0) { m = n_randint(state, m); n = n_randint(state, n); TEMPLATE(T, randtest_not_zero) (TEMPLATE(T, mat_entry) (A, m, n), state, ctx); if (TEMPLATE(T, mat_is_zero) (A, ctx)) { printf("FAIL: expected matrix not to be zero\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_mat_templates/vec_mul.c000066400000000000000000000033631461254215100205520ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_vec_mul)(TEMPLATE(T, struct) * c, const TEMPLATE(T, struct) * a, slong alen, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { slong i, j; slong len = FLINT_MIN(B->r, alen); TEMPLATE(T, t) t; TEMPLATE(T, init)(t, ctx); for (i = B->c - 1; i >= 0; i--) { TEMPLATE(T, zero)(c + i, ctx); for (j = 0; j < len; j++) { TEMPLATE(T, mul)(t, a + j, TEMPLATE(T, mat_entry)(B, j, i), ctx); TEMPLATE(T, add)(c + i, c + i, t, ctx); } } TEMPLATE(T, clear)(t, ctx); } void TEMPLATE(T, mat_vec_mul_ptr)(TEMPLATE(T, struct) * const * c, const TEMPLATE(T, struct) * const * a, slong alen, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { slong i, j; slong len = FLINT_MIN(B->r, alen); TEMPLATE(T, t) t; TEMPLATE(T, init)(t, ctx); for (i = B->c - 1; i >= 0; i--) { TEMPLATE(T, zero)(c[i], ctx); for (j = 0; j < len; j++) { TEMPLATE(T, mul)(t, a[j], TEMPLATE(T, mat_entry)(B, j, i), ctx); TEMPLATE(T, add)(c[i], c[i], t, ctx); } } TEMPLATE(T, clear)(t, ctx); } #endif flint-3.1.3/src/fq_mat_templates/window_clear.c000066400000000000000000000014071461254215100215720ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart. Copyright (C) 2008, Richard Howell-Peak Copyright (C) 2008, Martin Albrecht Copyright (C) 2010, Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_window_clear) (TEMPLATE(T, mat_t) window, const TEMPLATE(T, ctx_t) ctx) { if (window->r != 0) flint_free(window->rows); } #endif flint-3.1.3/src/fq_mat_templates/window_init.c000066400000000000000000000025201461254215100214440ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart. Copyright (C) 2008, Richard Howell-Peak Copyright (C) 2008, Martin Albrecht Copyright (C) 2010, Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_window_init) (TEMPLATE(T, mat_t) window, const TEMPLATE(T, mat_t) mat, slong r1, slong c1, slong r2, slong c2, const TEMPLATE(T, ctx_t) ctx) { slong i; window->entries = NULL; if (r2 > r1) window->rows = (TEMPLATE(T, struct) **) flint_malloc((r2 - r1) * sizeof(TEMPLATE(T, struct) *)); else window->rows = NULL; if (mat->c > 0) { for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; } else { for (i = 0; i < r2 - r1; i++) window->rows[i] = NULL; } window->r = r2 - r1; window->c = c2 - c1; } #endif flint-3.1.3/src/fq_mat_templates/zero.c000066400000000000000000000012731461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_zero) (TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, i, j), ctx); } #endif flint-3.1.3/src/fq_nmod.h000066400000000000000000000177521461254215100152320ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_H #define FQ_NMOD_H #ifdef FQ_NMOD_INLINES_C #define FQ_NMOD_INLINE #define FQ_TEMPLATES_INLINE #else #define FQ_NMOD_INLINE static inline #define FQ_TEMPLATES_INLINE static inline #endif #include "fq_nmod_types.h" #ifdef __cplusplus extern "C" { #endif /* Context ********************************************************************/ void fq_nmod_ctx_init_ui(fq_nmod_ctx_t ctx, ulong prime, slong deg, const char * var); int _fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong prime, slong deg, const char * var); void fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong prime, slong deg, const char * var); void fq_nmod_ctx_init_modulus(fq_nmod_ctx_t ctx, const nmod_poly_t modulus, const char * var); void fq_nmod_ctx_init_randtest(fq_nmod_ctx_t ctx, flint_rand_t state, int type); void fq_nmod_ctx_init_randtest_reducible(fq_nmod_ctx_t ctx, flint_rand_t state, int type); void fq_nmod_ctx_clear(fq_nmod_ctx_t ctx); FQ_NMOD_INLINE const nmod_poly_struct * fq_nmod_ctx_modulus(const fq_nmod_ctx_t ctx) { return ctx->modulus; } FQ_NMOD_INLINE slong fq_nmod_ctx_degree(const fq_nmod_ctx_t ctx) { return ctx->modulus->length - 1; } FQ_NMOD_INLINE ulong fq_nmod_ctx_prime(const fq_nmod_ctx_t ctx) { return ctx->mod.n; } void fq_nmod_ctx_order(fmpz_t f, const fq_nmod_ctx_t ctx); #ifdef FLINT_HAVE_FILE int fq_nmod_ctx_fprint(FILE * file, const fq_nmod_ctx_t ctx); #endif void fq_nmod_ctx_print(const fq_nmod_ctx_t ctx); /* Memory management *********************************************************/ void fq_nmod_init(fq_nmod_t rop, const fq_nmod_ctx_t ctx); void fq_nmod_init2(fq_nmod_t rop, const fq_nmod_ctx_t ctx); void fq_nmod_clear(fq_nmod_t rop, const fq_nmod_ctx_t ctx); void _fq_nmod_sparse_reduce(mp_limb_t *R, slong lenR, const fq_nmod_ctx_t ctx); void _fq_nmod_dense_reduce(mp_limb_t* R, slong lenR, const fq_nmod_ctx_t ctx); void _fq_nmod_reduce(mp_limb_t* R, slong lenR, const fq_nmod_ctx_t ctx); void fq_nmod_reduce(fq_nmod_t rop, const fq_nmod_ctx_t ctx); /* Basic arithmetic **********************************************************/ void fq_nmod_add(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx); void fq_nmod_sub(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx); void fq_nmod_sub_one(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); void fq_nmod_neg(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); void fq_nmod_mul(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx); void fq_nmod_mul_fmpz(fq_nmod_t rop, const fq_nmod_t op, const fmpz_t x, const fq_nmod_ctx_t ctx); void fq_nmod_mul_si(fq_nmod_t rop, const fq_nmod_t op, slong x, const fq_nmod_ctx_t ctx); void fq_nmod_mul_ui(fq_nmod_t rop, const fq_nmod_t op, ulong x, const fq_nmod_ctx_t ctx); void fq_nmod_sqr(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); void fq_nmod_inv(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); void _fq_nmod_pow(mp_limb_t *rop, const mp_limb_t *op, slong len, const fmpz_t e, const fq_nmod_ctx_t ctx); void fq_nmod_pow(fq_nmod_t rop, const fq_nmod_t op1, const fmpz_t e, const fq_nmod_ctx_t ctx); void fq_nmod_pow_ui(fq_nmod_t rop, const fq_nmod_t op1, const ulong e, const fq_nmod_ctx_t ctx); /* Roots ********************************************************************/ int fq_nmod_sqrt(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); void fq_nmod_pth_root(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); int fq_nmod_is_square(const fq_nmod_t op, const fq_nmod_ctx_t ctx); /* Randomisation *************************************************************/ void fq_nmod_randtest(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); void fq_nmod_randtest_dense(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); void fq_nmod_randtest_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); void fq_nmod_rand(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); void fq_nmod_rand_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); /* Comparison ****************************************************************/ int fq_nmod_equal(const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx); int fq_nmod_is_zero(const fq_nmod_t op, const fq_nmod_ctx_t ctx); int fq_nmod_is_one(const fq_nmod_t op, const fq_nmod_ctx_t ctx); int fq_nmod_cmp(const fq_nmod_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); /* Assignments and conversions ***********************************************/ void fq_nmod_set(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); void fq_nmod_set_si(fq_nmod_t rop, const slong x, const fq_nmod_ctx_t ctx); void fq_nmod_set_ui(fq_nmod_t rop, const ulong x, const fq_nmod_ctx_t ctx); void fq_nmod_set_fmpz(fq_nmod_t rop, const fmpz_t x, const fq_nmod_ctx_t ctx); void fq_nmod_set_nmod_poly(fq_nmod_t a, const nmod_poly_t b, const fq_nmod_ctx_t ctx); int fq_nmod_get_fmpz(fmpz_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); void fq_nmod_get_nmod_poly(nmod_poly_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); void fq_nmod_swap(fq_nmod_t op1, fq_nmod_t op2, const fq_nmod_ctx_t ctx); void fq_nmod_zero(fq_nmod_t rop, const fq_nmod_ctx_t ctx); void fq_nmod_one(fq_nmod_t rop, const fq_nmod_ctx_t ctx); void fq_nmod_gen(fq_nmod_t rop, const fq_nmod_ctx_t ctx); /* Output ********************************************************************/ #ifdef FLINT_HAVE_FILE int fq_nmod_fprint(FILE * file, const fq_nmod_t op, const fq_nmod_ctx_t ctx); int fq_nmod_fprint_pretty(FILE * file, const fq_nmod_t op, const fq_nmod_ctx_t ctx); #endif void fq_nmod_print(const fq_nmod_t op, const fq_nmod_ctx_t ctx); void fq_nmod_print_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx); char * fq_nmod_get_str(const fq_nmod_t op, const fq_nmod_ctx_t ctx); char * fq_nmod_get_str_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx); /* Special functions *********************************************************/ void _fq_nmod_trace(fmpz_t rop, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx); void fq_nmod_trace(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); void _fq_nmod_frobenius(mp_limb_t *rop, const mp_limb_t *op, slong len, slong e, const fq_nmod_ctx_t ctx); void fq_nmod_frobenius(fq_nmod_t rop, const fq_nmod_t op, slong e, const fq_nmod_ctx_t ctx); void _fq_nmod_norm(fmpz_t rop, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx); void fq_nmod_norm(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); /* Bit packing ******************************************************/ void fq_nmod_bit_pack(fmpz_t f, const fq_nmod_t op, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx); void fq_nmod_bit_unpack(fq_nmod_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx); /* Deprecated functions ******************************************************/ void fq_nmod_ctx_init(fq_nmod_ctx_t, fmpz_t, slong, const char *); int _fq_nmod_ctx_init_conway(fq_nmod_ctx_t, fmpz_t, slong, const char *); void fq_nmod_ctx_init_conway(fq_nmod_ctx_t, fmpz_t, slong, const char *); #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #define B nmod #include "fq_templates.h" #undef B #undef CAP_T #undef T #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_nmod/000077500000000000000000000000001461254215100150455ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod/add.c000066400000000000000000000016061461254215100157440ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_add(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) { slong max = FLINT_MAX(op1->length, op2->length); nmod_poly_fit_length(rop, max); _nmod_poly_add(rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, rop->mod); _nmod_poly_set_length(rop, max); _nmod_poly_normalise(rop); } flint-3.1.3/src/fq_nmod/assignments.c000066400000000000000000000034201461254215100175430ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod.h" #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_set(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_set(rop, op); } void fq_nmod_set_si(fq_nmod_t rop, const slong x, const fq_nmod_ctx_t ctx) { mp_limb_t rx = x < 0 ? -x : x; rx = n_mod2_preinv(rx, ctx->mod.n, ctx->mod.ninv); if (x < 0) rx = ctx->mod.n - rx; nmod_poly_zero(rop); nmod_poly_set_coeff_ui(rop, 0, rx); } void fq_nmod_set_ui(fq_nmod_t rop, const ulong x, const fq_nmod_ctx_t ctx) { nmod_poly_zero(rop); nmod_poly_set_coeff_ui(rop, 0, n_mod2_preinv(x, ctx->mod.n, ctx->mod.ninv)); } void fq_nmod_swap(fq_nmod_t op1, fq_nmod_t op2, const fq_nmod_ctx_t ctx) { nmod_poly_swap(op1, op2); } void fq_nmod_zero(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_zero(rop); } void fq_nmod_one(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_one(rop); } void fq_nmod_gen(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { if (ctx->modulus->length == 2) { nmod_poly_set_coeff_ui(rop, 0, nmod_neg(nmod_div(ctx->modulus->coeffs[0], ctx->modulus->coeffs[1], ctx->mod), ctx->mod)); } else { nmod_poly_zero(rop); nmod_poly_set_coeff_ui(rop, 0, 0); nmod_poly_set_coeff_ui(rop, 1, 1); } } flint-3.1.3/src/fq_nmod/bit_pack.c000066400000000000000000000011121461254215100167600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_bit_pack(fmpz_t f, const fq_nmod_t op, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx) { nmod_poly_bit_pack(f, op, bit_size); } flint-3.1.3/src/fq_nmod/bit_unpack.c000066400000000000000000000011601461254215100173260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_bit_unpack(fq_nmod_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx) { nmod_poly_bit_unpack(rop, f, bit_size); fq_nmod_reduce(rop, ctx); } flint-3.1.3/src/fq_nmod/comparisons.c000066400000000000000000000022731461254215100175520ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" int fq_nmod_equal(const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) { return nmod_poly_equal(op1, op2); } int fq_nmod_is_zero(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_is_zero(op); } int fq_nmod_is_one(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_is_one(op); } int fq_nmod_cmp(const fq_nmod_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx) { slong i; if (a->length != b->length) return a->length < b->length ? -1 : 1; for (i = 0; i < a->length; i++) { if (a->coeffs[i] != b->coeffs[i]) return a->coeffs[i] < b->coeffs[i] ? -1 : 1; } return 0; } flint-3.1.3/src/fq_nmod/ctx_clear.c000066400000000000000000000013331461254215100171550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" void fq_nmod_ctx_clear(fq_nmod_ctx_t ctx) { nmod_poly_clear(ctx->modulus); nmod_poly_clear(ctx->inv); _nmod_vec_clear(ctx->a); flint_free(ctx->j); flint_free(ctx->var); } flint-3.1.3/src/fq_nmod/ctx_init.c000066400000000000000000000101761461254215100170370ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" int _fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char * var) { int ret; ulong conway_poly[410]; /* Largest degree in database is 409 */ nmod_poly_struct tmp; ret = _nmod_poly_conway(conway_poly, p, d); if (!ret) return 0; nmod_poly_init(&tmp, p); tmp.coeffs = conway_poly; tmp.length = d + 1; fq_nmod_ctx_init_modulus(ctx, &tmp, var); /* No need to clear tmp */ return 1; } void fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char * var) { if (!_fq_nmod_ctx_init_conway_ui(ctx, p, d, var)) flint_throw(FLINT_ERROR, "Exception (fq_nmod_ctx_init_conway_ui). " "The polynomial for (p, d) = (%wu, %wd) is not present in the " "database.\n", p, d); ctx->is_conway = 1; } void fq_nmod_ctx_init_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char *var) { if (_fq_nmod_ctx_init_conway_ui(ctx, p, d, var)) { ctx->is_conway = 1; return; } else { flint_rand_t state; nmod_poly_t poly; ctx->is_conway = 0; flint_randinit(state); nmod_poly_init2(poly, p, d + 1); nmod_poly_randtest_sparse_irreducible(poly, state, d + 1); fq_nmod_ctx_init_modulus(ctx, poly, var); nmod_poly_clear(poly); flint_randclear(state); } } void fq_nmod_ctx_init_randtest(fq_nmod_ctx_t ctx, flint_rand_t state, int type) { ulong prime; slong degree; prime = _nmod_poly_conway_rand(°ree, state, type); fq_nmod_ctx_init_conway_ui(ctx, prime, degree, "a"); /* Test non-monic modulus */ if (n_randint(state, 2)) { nmod_poly_t modulus; mp_limb_t x; nmod_poly_init(modulus, ctx->mod.n); nmod_poly_set(modulus, ctx->modulus); x = n_randint(state, ctx->mod.n - 1) + 1; nmod_poly_scalar_mul_nmod(modulus, modulus, x); fq_nmod_ctx_clear(ctx); fq_nmod_ctx_init_modulus(ctx, modulus, "a"); nmod_poly_clear(modulus); } } void fq_nmod_ctx_init_randtest_reducible(fq_nmod_ctx_t ctx, flint_rand_t state, int type) { ulong prime; slong deg; nmod_poly_t mod; /* Big prime < 2^20, big degree <= 30 */ /* Small prime < 2^10, small degree <= 15 */ switch (type) { case 0: prime = n_randprime(state, 2 + n_randint(state, 19), 1); deg = 1 + n_randint(state, 30); break; case 1: prime = n_randprime(state, 2 + n_randint(state, 19), 1); deg = 1 + n_randint(state, 15); break; case 2: prime = n_randprime(state, 2 + n_randint(state, 9), 1); deg = 1 + n_randint(state, 30); break; case 3: prime = n_randprime(state, 2 + n_randint(state, 9), 1); deg = 1 + n_randint(state, 15); break; default: FLINT_UNREACHABLE; } nmod_poly_init(mod, prime); nmod_poly_randtest_monic(mod, state, deg + 1); fq_nmod_ctx_init_modulus(ctx, mod, "a"); nmod_poly_clear(mod); } /* Deprecated functions ******************************************************/ void fq_nmod_ctx_init(fq_nmod_ctx_t ctx, fmpz_t p, slong d, const char * var) { fq_nmod_ctx_init_ui(ctx, fmpz_get_ui(p), d, var); } int _fq_nmod_ctx_init_conway(fq_nmod_ctx_t ctx, fmpz_t p, slong d, const char * var) { return _fq_nmod_ctx_init_conway_ui(ctx, fmpz_get_ui(p), d, var); } void fq_nmod_ctx_init_conway(fq_nmod_ctx_t ctx, fmpz_t p, slong d, const char * var) { fq_nmod_ctx_init_conway_ui(ctx, fmpz_get_ui(p), d, var); } flint-3.1.3/src/fq_nmod/ctx_init_modulus.c000066400000000000000000000037731461254215100206140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_ctx_init_modulus(fq_nmod_ctx_t ctx, const nmod_poly_t modulus, const char * var) { slong nz; int i, j; mp_limb_t inv; ctx->mod.n = modulus->mod.n; ctx->mod.ninv = modulus->mod.ninv; ctx->mod.norm = modulus->mod.norm; /* Count number of nonzero coefficients */ nz = 0; for (i = 0; i < modulus->length; i++) { if (modulus->coeffs[i] != 0) { nz += 1; } } ctx->len = nz; ctx->a = _nmod_vec_init(ctx->len); ctx->j = flint_malloc(ctx->len * sizeof(mp_limb_t)); inv = n_invmod(modulus->coeffs[modulus->length - 1], ctx->mod.n); /* Copy the polynomial */ j = 0; for (i = 0; i < modulus->length; i++) { if (modulus->coeffs[i] != 0) { ctx->a[j] = n_mulmod2_preinv(inv, modulus->coeffs[i], ctx->mod.n, ctx->mod.ninv); ctx->j[j] = i; j++; } } if (ctx->len < 6) ctx->sparse_modulus = 1; else ctx->sparse_modulus = 0; ctx->var = flint_malloc(strlen(var) + 1); strcpy(ctx->var, var); /* Set the modulus */ nmod_poly_init(ctx->modulus, ctx->mod.n); nmod_poly_set(ctx->modulus, modulus); /* Precompute the inverse of the modulus */ nmod_poly_init(ctx->inv, ctx->mod.n); nmod_poly_reverse(ctx->inv, ctx->modulus, ctx->modulus->length); nmod_poly_inv_series_newton(ctx->inv, ctx->inv, ctx->modulus->length); ctx->is_conway = 0; } flint-3.1.3/src/fq_nmod/ctx_order.c000066400000000000000000000010601461254215100171770ustar00rootroot00000000000000/* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" void fq_nmod_ctx_order(fmpz_t f, const fq_nmod_ctx_t ctx) { fmpz_ui_pow_ui(f, fq_nmod_ctx_prime(ctx), fq_nmod_ctx_degree(ctx)); } flint-3.1.3/src/fq_nmod/embed_templates.c000066400000000000000000000015131461254215100203430ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "fq_nmod_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_nmod #define CAP_T FQ_NMOD #define B nmod #include "fq_embed_templates/composition_matrix.c" #include "fq_embed_templates/embed.c" #include "fq_embed_templates/matrices.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/frobenius.c000066400000000000000000000040711461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" /* Sets (rop, 2d-1) to the image of (op, len) under the Frobenius operator raised to the e-th power, assuming that neither op nor e are zero. */ void _fq_nmod_frobenius(mp_limb_t *rop, const mp_limb_t *op, slong len, slong e, const fq_nmod_ctx_t ctx) { const slong d = ctx->j[ctx->len - 1]; if (len == 1) /* op is in Fp, not just Fq */ { _nmod_vec_set(rop, op, len); _nmod_vec_zero(rop + len, (2*d - 1) - len); } else { fmpz_t t; fmpz_init(t); fmpz_ui_pow_ui(t, fq_nmod_ctx_prime(ctx), e); _fq_nmod_pow(rop, op, len, t, ctx); fmpz_clear(t); } } void fq_nmod_frobenius(fq_nmod_t rop, const fq_nmod_t op, slong e, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); e = e % d; if (e < 0) e += d; if (fq_nmod_is_zero(op, ctx)) { fq_nmod_zero(rop, ctx); } else if (e == 0) { fq_nmod_set(rop, op, ctx); } else { mp_limb_t *t; if (rop == op) { t = _nmod_vec_init(2 * d - 1); } else { nmod_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } _fq_nmod_frobenius(t, op->coeffs, op->length, e, ctx); if (rop == op) { _nmod_vec_clear(rop->coeffs); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } else { _nmod_poly_set_length(rop, d); } _nmod_poly_normalise(rop); } } flint-3.1.3/src/fq_nmod/gcdinv.c000066400000000000000000000011121461254215100164560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_gcdinv(fq_nmod_t rop, fq_nmod_t inv, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_gcdinv(rop, inv, op, ctx->modulus); } flint-3.1.3/src/fq_nmod/get_fmpz.c000066400000000000000000000012111461254215100170170ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" int fq_nmod_get_fmpz(fmpz_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx) { if (b->length > 1) return 0; if (b->length == 1) fmpz_set_ui(a, b->coeffs[0]); else fmpz_zero(a); return 1; } flint-3.1.3/src/fq_nmod/get_nmod_poly.c000066400000000000000000000012461461254215100200530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_get_nmod_poly(nmod_poly_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(b->mod.n == ctx->modulus->mod.n); a->mod = ctx->modulus->mod; nmod_poly_set(a, b); } flint-3.1.3/src/fq_nmod/get_set_fmpz_mod_mat.c000066400000000000000000000021431461254215100213770ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_nmod.h" void fq_nmod_get_nmod_mat(nmod_mat_t col, const fq_nmod_t a, const fq_nmod_ctx_t ctx) { slong i, n = fq_nmod_ctx_degree(ctx); for (i = 0; i < a->length; i++) nmod_mat_set_entry(col, i, 0, a->coeffs[i]); for ( ; i < n; i++) nmod_mat_entry(col, i, 0) = 0; } void fq_nmod_set_nmod_mat(fq_nmod_t a, const nmod_mat_t col, const fq_nmod_ctx_t ctx) { slong i, n = fq_nmod_ctx_degree(ctx); nmod_poly_fit_length(a, n); a->length = n; for (i = 0; i < n; i++) a->coeffs[i] = nmod_mat_entry(col, i, 0); _nmod_poly_normalise(a); } flint-3.1.3/src/fq_nmod/get_str.c000066400000000000000000000010201461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" char * fq_nmod_get_str(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_get_str(op); } flint-3.1.3/src/fq_nmod/get_str_pretty.c000066400000000000000000000010501461254215100202630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" char * fq_nmod_get_str_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_get_str_pretty(op, ctx->var); } flint-3.1.3/src/fq_nmod/init.c000066400000000000000000000014531461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_init(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_init2_preinv(rop, ctx->mod.n, ctx->mod.ninv, fq_nmod_ctx_degree(ctx)); } void fq_nmod_init2(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_init2_preinv(rop, ctx->mod.n, ctx->mod.ninv, fq_nmod_ctx_degree(ctx)); } void fq_nmod_clear(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_clear(rop); } flint-3.1.3/src/fq_nmod/inlines.c000066400000000000000000000007201461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_INLINES_C #include "fq_nmod.h" flint-3.1.3/src/fq_nmod/inv.c000066400000000000000000000033411461254215100160060ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fq_nmod.h" void _fq_nmod_inv(mp_limb_t *rop, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); if (len == 1) { rop[0] = n_invmod(op[0], ctx->mod.n); _nmod_vec_zero(rop + 1, d - 1); } else { _nmod_poly_invmod(rop, op, len, ctx->modulus->coeffs, d + 1, ctx->mod); } } void fq_nmod_inv(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { if (fq_nmod_is_zero(op, ctx)) { flint_throw(FLINT_ERROR, "Exception (fq_nmod_inv). Zero is not invertible.\n"); } else { const slong d = fq_nmod_ctx_degree(ctx); mp_limb_t *t; if (rop == op) { t = _nmod_vec_init(d); } else { nmod_poly_fit_length(rop, d); t = rop->coeffs; } _fq_nmod_inv(t, op->coeffs, op->length, ctx); if (rop == op) { _nmod_vec_clear(rop->coeffs); rop->coeffs = t; rop->alloc = d; rop->length = d; } else { _nmod_poly_set_length(rop, d); } _nmod_poly_normalise(rop); } } flint-3.1.3/src/fq_nmod/io.c000066400000000000000000000043321461254215100156220ustar00rootroot00000000000000/* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" /* printing *******************************************************************/ /* TODO */ int fq_nmod_ctx_fprint(FILE * file, const fq_nmod_ctx_t ctx) { int r; slong i, k; r = flint_fprintf(file, "p = %wu", fq_nmod_ctx_prime(ctx)); if (r <= 0) return r; r = flint_fprintf(file, "\nd = %wd\nf(X) = ", ctx->j[ctx->len - 1]); if (r <= 0) return r; r = flint_fprintf(file, "%wu", ctx->a[0]); if (r <= 0) return r; for (k = 1; k < ctx->len; k++) { i = ctx->j[k]; r = flint_fprintf(file, " + "); if (r <= 0) return r; if (ctx->a[k] == UWORD(1)) { if (i == 1) r = flint_fprintf(file, "X"); else r = flint_fprintf(file, "X^%wd", i); if (r <= 0) return r; } else { r = flint_fprintf(file, "%wu", ctx->a[k]); if (r <= 0) return r; if (i == 1) r = flint_fprintf(file, "*X"); else r = flint_fprintf(file, "*X^%wd", i); if (r <= 0) return r; } } r = flint_fprintf(file, "\n"); return r; } void fq_nmod_ctx_print(const fq_nmod_ctx_t ctx) { fq_nmod_ctx_fprint(stdout, ctx); } int fq_nmod_fprint(FILE * file, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_fprint(file, op); } void fq_nmod_print(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_print(op); } int fq_nmod_fprint_pretty(FILE * file, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_fprint_pretty(file, op, ctx->var); } void fq_nmod_print_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_print_pretty(op, ctx->var); } flint-3.1.3/src/fq_nmod/mat_templates.c000066400000000000000000000056471461254215100200640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2015 Elena Sergeicheva Copyright (C) 2018 Tommy Hofmann Copyright (C) 2015, 2019-2021 William Hart Copyright (C) 2021 Daniel Schultz Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_mod_mat.h" #include "fq_nmod.h" #include "fq_nmod_vec.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/add.c" #include "fq_mat_templates/can_solve.c" #include "fq_mat_templates/charpoly.c" #include "fq_mat_templates/clear.c" #include "fq_mat_templates/concat_horizontal.c" #include "fq_mat_templates/concat_vertical.c" #include "fq_mat_templates/equal.c" #include "fq_mat_templates/init.c" #include "fq_mat_templates/init_set.c" #include "fq_mat_templates/inv.c" #include "fq_mat_templates/io.c" #include "fq_mat_templates/is_one.c" #include "fq_mat_templates/is_zero.c" #include "fq_mat_templates/lu.c" #include "fq_mat_templates/lu_classical.c" #include "fq_mat_templates/lu_recursive.c" #include "fq_mat_templates/mat_entry_set.c" #include "fq_mat_templates/mat_invert_cols.c" #include "fq_mat_templates/mat_swap_cols.c" #include "fq_mat_templates/mat_swap_entrywise.c" #include "fq_mat_templates/minpoly.c" #include "fq_mat_templates/mul.c" #include "fq_mat_templates/mul_classical.c" #include "fq_mat_templates/mul_KS.c" #include "fq_mat_templates/mul_vec.c" #include "fq_mat_templates/neg.c" #include "fq_mat_templates/nullspace.c" #include "fq_mat_templates/one.c" #include "fq_mat_templates/randops.c" #include "fq_mat_templates/randpermdiag.c" #include "fq_mat_templates/randrank.c" #include "fq_mat_templates/randtest.c" #include "fq_mat_templates/randtril.c" #include "fq_mat_templates/randtriu.c" #include "fq_mat_templates/rank.c" #include "fq_mat_templates/rref.c" #include "fq_mat_templates/set.c" #include "fq_mat_templates/set_fmpz_mod_mat.c" #include "fq_mat_templates/set_nmod_mat.c" #include "fq_mat_templates/similarity.c" #include "fq_mat_templates/solve.c" #include "fq_mat_templates/solve_tril.c" #include "fq_mat_templates/solve_tril_classical.c" #include "fq_mat_templates/solve_tril_recursive.c" #include "fq_mat_templates/solve_triu.c" #include "fq_mat_templates/solve_triu_classical.c" #include "fq_mat_templates/solve_triu_recursive.c" #include "fq_mat_templates/sub.c" #include "fq_mat_templates/submul.c" #include "fq_mat_templates/swap.c" #include "fq_mat_templates/vec_mul.c" #include "fq_mat_templates/window_clear.c" #include "fq_mat_templates/window_init.c" #include "fq_mat_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/mul.c000066400000000000000000000012421461254215100160050ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_mul(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) { nmod_poly_mul(rop, op1, op2); fq_nmod_reduce(rop, ctx); } flint-3.1.3/src/fq_nmod/mul_fmpz.c000066400000000000000000000012651461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" void fq_nmod_mul_fmpz(fq_nmod_t rop, const fq_nmod_t op, const fmpz_t x, const fq_nmod_ctx_t ctx) { ulong rx; rx = fmpz_fdiv_ui(x, fq_nmod_ctx_prime(ctx)); nmod_poly_scalar_mul_nmod(rop, op, rx); } flint-3.1.3/src/fq_nmod/mul_si.c000066400000000000000000000011271461254215100165020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_mul_si(fq_nmod_t rop, const fq_nmod_t op, slong x, const fq_nmod_ctx_t ctx) { nmod_poly_scalar_mul_nmod(rop, op, nmod_set_si(x, ctx->mod)); } flint-3.1.3/src/fq_nmod/mul_ui.c000066400000000000000000000011261461254215100165030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_mul_ui(fq_nmod_t rop, const fq_nmod_t op, ulong x, const fq_nmod_ctx_t ctx) { nmod_poly_scalar_mul_nmod(rop, op, nmod_set_ui(x, ctx->mod)); } flint-3.1.3/src/fq_nmod/neg.c000066400000000000000000000011721461254215100157630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_neg(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { slong len = op->length; nmod_poly_fit_length(rop, len); _nmod_poly_set_length(rop, len); nmod_poly_neg(rop, op); } flint-3.1.3/src/fq_nmod/norm.c000066400000000000000000000036331461254215100161710ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2017 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" /* This computes the norm on $\mathbf{F}_q$. */ void _fq_nmod_norm(fmpz_t rop2, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); mp_limb_t rop; if (d == 1) { rop = op[0]; } else if (len == 1) /* element scalar */ { rop = n_powmod2_ui_preinv(op[0], d, ctx->mod.n, ctx->mod.ninv); } else { rop = _nmod_poly_resultant(ctx->modulus->coeffs, ctx->modulus->length, op, len, ctx->mod); /* XXX: This part of the code is currently untested as the Conway polynomials used for the extension Fq/Fp are monic. TODO: make polynomial monic!!! reading the source, a[] is monic, modulus is not. Why???? */ if (ctx->modulus->coeffs[d] != WORD(1)) { mp_limb_t f; f = n_powmod2_ui_preinv(ctx->modulus->coeffs[d], len - 1, ctx->mod.n, ctx->mod.ninv); f = n_invmod(f, ctx->mod.n); rop = n_mulmod2_preinv(f, rop, ctx->mod.n, ctx->mod.ninv); } } fmpz_set_ui(rop2, rop); } void fq_nmod_norm(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { if (fq_nmod_is_zero(op, ctx)) { fmpz_zero(rop); return; } else { _fq_nmod_norm(rop, op->coeffs, op->length, ctx); } } flint-3.1.3/src/fq_nmod/poly_factor_templates.c000066400000000000000000000036151461254215100216150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_vec.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/clear.c" #include "fq_poly_factor_templates/concat.c" #include "fq_poly_factor_templates/factor_berlekamp.c" #include "fq_poly_factor_templates/factor.c" #include "fq_poly_factor_templates/factor_cantor_zassenhaus.c" #include "fq_poly_factor_templates/factor_distinct_deg.c" #include "fq_poly_factor_templates/factor_equal_deg.c" #include "fq_poly_factor_templates/factor_equal_deg_prob.c" #include "fq_poly_factor_templates/factor_kaltofen_shoup.c" #include "fq_poly_factor_templates/factor_split_single.c" #include "fq_poly_factor_templates/factor_squarefree.c" #include "fq_poly_factor_templates/fit_length.c" #include "fq_poly_factor_templates/init.c" #include "fq_poly_factor_templates/insert.c" #include "fq_poly_factor_templates/is_irreducible_ben_or.c" #include "fq_poly_factor_templates/is_irreducible.c" #include "fq_poly_factor_templates/is_irreducible_ddf.c" #include "fq_poly_factor_templates/is_squarefree.c" #include "fq_poly_factor_templates/iterated_frobenius_preinv.c" #include "fq_poly_factor_templates/pow.c" #include "fq_poly_factor_templates/print.c" #include "fq_poly_factor_templates/print_pretty.c" #include "fq_poly_factor_templates/realloc.c" #include "fq_poly_factor_templates/roots.c" #include "fq_poly_factor_templates/set.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/poly_templates.c000066400000000000000000000120321461254215100202500ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Fredrik Johansson Copyright (C) 2012 William Hart Copyright (C) 2013 Mike Hansen Copyright (C) 2017 Luca De Feo Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "fq_nmod_vec.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/add.c" #include "fq_poly_templates/add_series.c" #include "fq_poly_templates/add_si.c" #include "fq_poly_templates/clear.c" #include "fq_poly_templates/comparisons.c" #include "fq_poly_templates/compose.c" #include "fq_poly_templates/compose_mod.c" #include "fq_poly_templates/compose_mod_brent_kung.c" #include "fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c" #include "fq_poly_templates/compose_mod_brent_kung_preinv.c" #include "fq_poly_templates/compose_mod_horner.c" #include "fq_poly_templates/compose_mod_horner_preinv.c" #include "fq_poly_templates/compose_mod_preinv.c" #include "fq_poly_templates/deflate.c" #include "fq_poly_templates/deflation.c" #include "fq_poly_templates/derivative.c" #include "fq_poly_templates/div.c" #include "fq_poly_templates/div_newton_n_preinv.c" #include "fq_poly_templates/div_series.c" #include "fq_poly_templates/divides.c" #include "fq_poly_templates/divrem.c" #include "fq_poly_templates/divrem_f.c" #include "fq_poly_templates/divrem_newton_n_preinv.c" #include "fq_poly_templates/equal.c" #include "fq_poly_templates/equal_trunc.c" #include "fq_poly_templates/evaluate_fq.c" #include "fq_poly_templates/evaluate_fq_vec.c" #include "fq_poly_templates/evaluate_fq_vec_fast.c" #include "fq_poly_templates/evaluate_fq_vec_iter.c" #include "fq_poly_templates/fit_length.c" #include "fq_poly_templates/gcd.c" #include "fq_poly_templates/gcd_euclidean_f.c" #include "fq_poly_templates/gen.c" #include "fq_poly_templates/get_coeff.c" #include "fq_poly_templates/get_str.c" #include "fq_poly_templates/get_str_pretty.c" #include "fq_poly_templates/hamming_weight.c" #include "fq_poly_templates/inflate.c" #include "fq_poly_templates/init.c" #include "fq_poly_templates/inv_series_newton.c" #include "fq_poly_templates/invsqrt_series.c" #include "fq_poly_templates/io.c" #include "fq_poly_templates/is_gen.c" #include "fq_poly_templates/make_monic.c" /* #include "fq_poly_templates/mul.c" */ /* #include "fq_poly_templates/mul_classical.c" */ #include "fq_poly_templates/mul_KS.c" /* #include "fq_poly_templates/mul_reorder.c" */ #include "fq_poly_templates/mulhigh.c" #include "fq_poly_templates/mulhigh_classical.c" #include "fq_poly_templates/mullow.c" #include "fq_poly_templates/mullow_classical.c" #include "fq_poly_templates/mullow_KS.c" #include "fq_poly_templates/mulmod.c" #include "fq_poly_templates/mulmod_preinv.c" #include "fq_poly_templates/neg.c" #include "fq_poly_templates/normalise.c" #include "fq_poly_templates/one.c" #include "fq_poly_templates/pow.c" #include "fq_poly_templates/pow_trunc.c" #include "fq_poly_templates/pow_trunc_binexp.c" #include "fq_poly_templates/powmod_fmpz_binexp.c" #include "fq_poly_templates/powmod_fmpz_binexp_preinv.c" #include "fq_poly_templates/powmod_fmpz_sliding_preinv.c" #include "fq_poly_templates/powmod_ui_binexp.c" #include "fq_poly_templates/powmod_ui_binexp_preinv.c" #include "fq_poly_templates/powmod_x_fmpz_preinv.c" #include "fq_poly_templates/randtest.c" #include "fq_poly_templates/randtest_irreducible.c" #include "fq_poly_templates/randtest_monic.c" #include "fq_poly_templates/realloc.c" #include "fq_poly_templates/rem.c" #include "fq_poly_templates/remove.c" #include "fq_poly_templates/reverse.c" #include "fq_poly_templates/scalar_addmul_fq.c" #include "fq_poly_templates/scalar_div_fq.c" #include "fq_poly_templates/scalar_mul_fq.c" #include "fq_poly_templates/scalar_submul_fq.c" #include "fq_poly_templates/set.c" #include "fq_poly_templates/set_coeff.c" #include "fq_poly_templates/set_fmpz_mod_poly.c" #include "fq_poly_templates/set_fq.c" #include "fq_poly_templates/set_length.c" #include "fq_poly_templates/set_nmod_poly.c" #include "fq_poly_templates/set_trunc.c" #include "fq_poly_templates/shift_left.c" #include "fq_poly_templates/shift_right.c" #include "fq_poly_templates/sqr.c" #include "fq_poly_templates/sqr_classical.c" #include "fq_poly_templates/sqr_KS.c" /* #include "fq_poly_templates/sqr_reorder.c" */ #include "fq_poly_templates/sqrt.c" #include "fq_poly_templates/sqrt_series.c" #include "fq_poly_templates/sub.c" #include "fq_poly_templates/sub_series.c" #include "fq_poly_templates/swap.c" #include "fq_poly_templates/tree.c" #include "fq_poly_templates/truncate.c" #include "fq_poly_templates/xgcd.c" #include "fq_poly_templates/xgcd_euclidean_f.c" #include "fq_poly_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/pow.c000066400000000000000000000111271461254215100160200ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" void _fq_nmod_pow(mp_limb_t *rop, const mp_limb_t *op, slong len, const fmpz_t e, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); if (fmpz_is_zero(e)) { rop[0] = WORD(1); _nmod_vec_zero(rop + 1, 2 * d - 1 - 1); } else if (fmpz_is_one(e)) { _nmod_vec_set(rop, op, len); _nmod_vec_zero(rop + len, 2 * d - 1 - len); } else { ulong bit; mp_limb_t *v = _nmod_vec_init(2 * d - 1); mp_limb_t *R, *S, *T; _nmod_vec_zero(v, 2 * d - 1); _nmod_vec_zero(rop, 2 * d - 1); /* Set bits to the bitmask with a 1 one place lower than the msb of e */ bit = fmpz_bits(e) - 2; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if (fmpz_tstbit(e, bit2)) swaps = ~swaps; while (bit2--) if (!fmpz_tstbit(e, bit2)) swaps = ~swaps; if (swaps == 0U) { R = rop; S = v; } else { R = v; S = rop; } } /* We unroll the first step of the loop, referring to {op, len} */ _nmod_poly_mul(R, op, len, op, len, ctx->mod); _fq_nmod_reduce(R, 2 * len - 1, ctx); if (fmpz_tstbit(e, bit)) { _nmod_poly_mul(S, R, d, op, len, ctx->mod); _fq_nmod_reduce(S, d + len - 1, ctx); T = R; R = S; S = T; } while (bit--) { if (fmpz_tstbit(e, bit)) { _nmod_poly_mul(S, R, d, R, d, ctx->mod); _fq_nmod_reduce(S, 2 * d - 1, ctx); _nmod_poly_mul(R, S, d, op, len, ctx->mod); _fq_nmod_reduce(R, d + len - 1, ctx); } else { _nmod_poly_mul(S, R, d, R, d, ctx->mod); _fq_nmod_reduce(S, 2 * d - 1, ctx); T = R; R = S; S = T; } } _nmod_vec_clear(v); } } void fq_nmod_pow(fq_nmod_t rop, const fq_nmod_t op, const fmpz_t e, const fq_nmod_ctx_t ctx) { if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "Exception (fq_nmod_pow). e < 0.\n"); } if (fmpz_is_zero(e)) { fq_nmod_one(rop, ctx); } else if (fq_nmod_is_zero(op, ctx)) { fq_nmod_zero(rop, ctx); } else if (fmpz_is_one(e)) { fq_nmod_set(rop, op, ctx); } else { const slong d = fq_nmod_ctx_degree(ctx); mp_limb_t *t; if (rop == op) { t = _nmod_vec_init(2 * d - 1); } else { nmod_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } if (fmpz_cmp_ui(e, fq_nmod_ctx_prime(ctx)) < 0) _fq_nmod_pow(t, op->coeffs, op->length, e, ctx); else { fmpz_t order, e_mod; fmpz_init(e_mod); fmpz_init(order); fq_nmod_ctx_order(order, ctx); fmpz_sub_ui(order, order, 1); fmpz_mod(e_mod, e, order); _fq_nmod_pow(t, op->coeffs, op->length, e_mod, ctx); fmpz_clear(order); fmpz_clear(e_mod); } if (rop == op) { _nmod_vec_clear(rop->coeffs); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } else { _nmod_poly_set_length(rop, d); } _nmod_poly_normalise(rop); } } /* TODO: Move into separate function / optimize */ void fq_nmod_pow_ui(fq_nmod_t rop, const fq_nmod_t op, const ulong e, const fq_nmod_ctx_t ctx) { fmpz_t exp; fmpz_init_set_ui(exp, e); fq_nmod_pow(rop, op, exp, ctx); fmpz_clear(exp); } flint-3.1.3/src/fq_nmod/pth_root.c000066400000000000000000000015121461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" void fq_nmod_pth_root(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx) { slong i, d; if (fq_nmod_is_zero(op1, ctx) || fq_nmod_is_one(op1, ctx)) { fq_nmod_set(rop, op1, ctx); return; } /* TODO: Use modular composition */ d = fq_nmod_ctx_degree(ctx) - 1; fq_nmod_set(rop, op1, ctx); for (i = 0; i < d; i++) { fq_nmod_pow_ui(rop, rop, fq_nmod_ctx_prime(ctx), ctx); } } flint-3.1.3/src/fq_nmod/rand.c000066400000000000000000000020041461254215100161310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_rand(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); slong i; nmod_poly_fit_length(rop, d); for (i = 0; i < d; i++) rop->coeffs[i] = n_randint(state, ctx->mod.n); _nmod_poly_set_length(rop, d); _nmod_poly_normalise(rop); } void fq_nmod_rand_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) { int tries = 3; do { fq_nmod_rand(rop, state, ctx); if (!fq_nmod_is_zero(rop, ctx)) return; } while (--tries >= 0); fq_nmod_one(rop, ctx); } flint-3.1.3/src/fq_nmod/randtest.c000066400000000000000000000035001461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_randtest(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); slong i, sparse; nmod_poly_fit_length(rop, d); if (n_randint(state, 2)) { for (i = 0; i < d; i++) rop->coeffs[i] = n_randint(state, ctx->mod.n); } else { sparse = 1 + n_randint(state, FLINT_MAX(2, d)); for (i = 0; i < d; i++) if (n_randint(state, sparse)) rop->coeffs[i] = WORD(0); else rop->coeffs[i] = n_randint(state, ctx->mod.n); } _nmod_poly_set_length(rop, d); _nmod_poly_normalise(rop); } void fq_nmod_randtest_dense(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); slong i; nmod_poly_fit_length(rop, d); for (i = 0; i < d - 1; i++) rop->coeffs[i] = n_randint(state, ctx->mod.n); rop->coeffs[d - 1] = 1; _nmod_poly_set_length(rop, d); _nmod_poly_normalise(rop); } void fq_nmod_randtest_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx) { slong i; fq_nmod_randtest(rop, state, ctx); for (i = 0; fq_nmod_is_zero(rop, ctx) && (i < 10); i++) fq_nmod_randtest(rop, state, ctx); if (fq_nmod_is_zero(rop, ctx)) fq_nmod_one(rop, ctx); } flint-3.1.3/src/fq_nmod/reduce.c000066400000000000000000000042611461254215100164630ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fq_nmod.h" void _fq_nmod_sparse_reduce(mp_limb_t *R, slong lenR, const fq_nmod_ctx_t ctx) { slong i, k; const slong d = ctx->j[ctx->len - 1]; NMOD_VEC_NORM(R, lenR); for (i = lenR - 1; i >= d; i--) { for (k = ctx->len - 2; k >= 0; k--) { /* TODO clean this mess up */ R[ctx->j[k] + i - d] = n_submod(R[ctx->j[k] + i - d], n_mulmod2_preinv(R[i], ctx->a[k], ctx->mod.n, ctx->mod.ninv), ctx->mod.n); } R[i] = UWORD(0); } } void _fq_nmod_dense_reduce(mp_limb_t* R, slong lenR, const fq_nmod_ctx_t ctx) { mp_limb_t *q, *r; if (lenR < ctx->modulus->length) { _nmod_vec_reduce(R, R, lenR, ctx->mod); return; } q = _nmod_vec_init(lenR - ctx->modulus->length + 1); r = _nmod_vec_init(ctx->modulus->length - 1); _nmod_poly_divrem_newton_n_preinv(q, r, R, lenR, ctx->modulus->coeffs, ctx->modulus->length, ctx->inv->coeffs, ctx->inv->length, ctx->mod); _nmod_vec_set(R, r, ctx->modulus->length - 1); _nmod_vec_clear(q); _nmod_vec_clear(r); } void _fq_nmod_reduce(mp_limb_t* R, slong lenR, const fq_nmod_ctx_t ctx) { if (ctx->sparse_modulus) _fq_nmod_sparse_reduce(R, lenR, ctx); else _fq_nmod_dense_reduce(R, lenR, ctx); } void fq_nmod_reduce(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(rop->length <= 2*(ctx->modulus->length - 1)); _fq_nmod_reduce(rop->coeffs, rop->length, ctx); rop->length = FLINT_MIN(rop->length, ctx->modulus->length - 1); _nmod_poly_normalise(rop); } flint-3.1.3/src/fq_nmod/set_fmpz.c000066400000000000000000000012251461254215100170400ustar00rootroot00000000000000/* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" void fq_nmod_set_fmpz(fq_nmod_t rop, const fmpz_t x, const fq_nmod_ctx_t ctx) { ulong rx; rx = fmpz_fdiv_ui(x, fq_nmod_ctx_prime(ctx)); nmod_poly_zero(rop); nmod_poly_set_coeff_ui(rop, 0, rx); } flint-3.1.3/src/fq_nmod/set_nmod_poly.c000066400000000000000000000015221461254215100200640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_set_nmod_poly(fq_nmod_t a, const nmod_poly_t b, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(a->mod.n == b->mod.n); FLINT_ASSERT(a->mod.n == ctx->modulus->mod.n); if (b->length <= 2*(ctx->modulus->length - 1)) { nmod_poly_set(a, b); fq_nmod_reduce(a, ctx); } else { nmod_poly_rem(a, b, ctx->modulus); } } flint-3.1.3/src/fq_nmod/sqr.c000066400000000000000000000010661461254215100160210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_sqr(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_mul(rop, op, op); fq_nmod_reduce(rop, ctx); } flint-3.1.3/src/fq_nmod/sub.c000066400000000000000000000016061461254215100160050ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void fq_nmod_sub(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx) { slong max = FLINT_MAX(op1->length, op2->length); nmod_poly_fit_length(rop, max); _nmod_poly_sub(rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx->mod); _nmod_poly_set_length(rop, max); _nmod_poly_normalise(rop); } flint-3.1.3/src/fq_nmod/sub_one.c000066400000000000000000000011621461254215100166430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" void fq_nmod_sub_one(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx) { fq_nmod_t one; fq_nmod_init(one, ctx); fq_nmod_one(one, ctx); fq_nmod_sub(rop, op1, one, ctx); fq_nmod_clear(one, ctx); } flint-3.1.3/src/fq_nmod/templates.c000066400000000000000000000014751461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2020 William Hart Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/div.c" #include "fq_templates/is_invertible.c" #include "fq_templates/is_invertible_f.c" #include "fq_templates/is_square.c" #include "fq_templates/multiplicative_order.c" #include "fq_templates/sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/000077500000000000000000000000001461254215100160245ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod/test/main.c000066400000000000000000000042361461254215100171210ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-assign.c" #include "t-ctx_init.c" #include "t-div.c" #include "t-frobenius.c" #include "t-get_set_fmpz.c" #include "t-get_set_nmod_poly.c" #include "t-inv.c" #include "t-is_invertible.c" #include "t-is_invertible_f.c" #include "t-is_primitive.c" #include "t-is_square.c" #include "t-mul.c" #include "t-mul_fmpz.c" #include "t-mul_si.c" #include "t-multiplicative_order.c" #include "t-mul_ui.c" #include "t-neg.c" #include "t-norm.c" #include "t-pow.c" #include "t-pth_root.c" #include "t-sqr.c" #include "t-sqrt.c" #include "t-sub.c" #include "t-trace.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_add), TEST_FUNCTION(fq_nmod_assign), TEST_FUNCTION(fq_nmod_ctx_init), TEST_FUNCTION(fq_nmod_div), TEST_FUNCTION(fq_nmod_frobenius), TEST_FUNCTION(fq_nmod_get_set_fmpz), TEST_FUNCTION(fq_nmod_get_set_nmod_poly), TEST_FUNCTION(fq_nmod_inv), TEST_FUNCTION(fq_nmod_is_invertible), TEST_FUNCTION(fq_nmod_is_invertible_f), TEST_FUNCTION(fq_nmod_is_primitive), TEST_FUNCTION(fq_nmod_is_square), TEST_FUNCTION(fq_nmod_mul), TEST_FUNCTION(fq_nmod_mul_fmpz), TEST_FUNCTION(fq_nmod_mul_si), TEST_FUNCTION(fq_nmod_multiplicative_order), TEST_FUNCTION(fq_nmod_mul_ui), TEST_FUNCTION(fq_nmod_neg), TEST_FUNCTION(fq_nmod_norm), TEST_FUNCTION(fq_nmod_pow), TEST_FUNCTION(fq_nmod_pth_root), TEST_FUNCTION(fq_nmod_sqr), TEST_FUNCTION(fq_nmod_sqrt), TEST_FUNCTION(fq_nmod_sub), TEST_FUNCTION(fq_nmod_trace) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod/test/t-add.c000066400000000000000000000010141461254215100171550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-assign.c000066400000000000000000000010171461254215100177140ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-assign.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-ctx_init.c000066400000000000000000000010211461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-ctx_init.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-div.c000066400000000000000000000010141461254215100172070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-div.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-frobenius.c000066400000000000000000000010221461254215100204200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-frobenius.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-get_set_fmpz.c000066400000000000000000000010301461254215100211110ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-get_set_fmpz.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-get_set_nmod_poly.c000066400000000000000000000036251461254215100221510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "fq_nmod.h" TEST_FUNCTION_START(fq_nmod_get_set_nmod_poly, state) { slong i, j; fq_nmod_ctx_t ctx; for (j = 0; j < 10*flint_test_multiplier(); j++) { fq_nmod_ctx_init_randtest(ctx, state, 0); for (i = 0; i < 100; i++) { fq_nmod_t a, b; nmod_poly_t c, t; fq_nmod_init(a, ctx); fq_nmod_init(b, ctx); nmod_poly_init(c, 1); /* modulus don't care */ nmod_poly_init_mod(t, ctx->modulus->mod); fq_nmod_randtest(a, state, ctx); fq_nmod_get_nmod_poly(c, a, ctx); nmod_poly_randtest(t, state, 20); nmod_poly_mul(t, t, ctx->modulus); nmod_poly_add(c, c, t); fq_nmod_set_nmod_poly(b, c, ctx); if (!fq_nmod_equal(a, b, ctx)) { flint_printf("FAIL:n\n"); fq_nmod_ctx_print(ctx); flint_printf("\n"); flint_printf("a = "), fq_nmod_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), nmod_poly_print_pretty(c, "x"), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(b, ctx); nmod_poly_clear(c); nmod_poly_clear(t); } fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod/test/t-inv.c000066400000000000000000000010141461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-inv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-is_invertible.c000066400000000000000000000010261461254215100212660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-is_invertible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-is_invertible_f.c000066400000000000000000000010301461254215100215660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-is_invertible_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-is_primitive.c000066400000000000000000000010251461254215100211320ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-is_primitive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-is_square.c000066400000000000000000000010231461254215100204200ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-is_square.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-mul.c000066400000000000000000000010141461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-mul_fmpz.c000066400000000000000000000064101461254215100202630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" TEST_FUNCTION_START(fq_nmod_mul_fmpz, state) { int i, result; /* Check aliasing of a, b */ for (i = 0; i < 2000; i++) { fmpz_t p; slong d; fq_nmod_ctx_t ctx; fmpz_t x; fq_nmod_t a, b; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; fq_nmod_ctx_init_conway_ui(ctx, fmpz_get_ui(p), d, "a"); fq_nmod_init(a, ctx); fq_nmod_init(b, ctx); fmpz_init(x); fq_nmod_randtest(a, state, ctx); fmpz_randtest_mod_signed(x, state, p); fq_nmod_mul_fmpz(b, a, x, ctx); fq_nmod_mul_fmpz(a, a, x, ctx); result = (fq_nmod_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_nmod_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(b, ctx); fmpz_clear(x); fmpz_clear(p); fq_nmod_ctx_clear(ctx); } /* compare with direct multiplication */ for (i = 0; i < 2000; i++) { fmpz_t p; slong d; fq_nmod_ctx_t ctx; fmpz_t x; fq_nmod_t a, c; nmod_poly_t b; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; fq_nmod_ctx_init_conway_ui(ctx, fmpz_get_ui(p), d, "a"); fq_nmod_init(a, ctx); fq_nmod_init(c, ctx); fmpz_init(x); nmod_poly_init(b, fmpz_get_ui(p)); fq_nmod_randtest(a, state, ctx); fmpz_randtest_mod_signed(x, state, p); fq_nmod_mul_fmpz(c, a, x, ctx); if (fmpz_cmp_ui(x, 0) < 0) { nmod_poly_scalar_mul_nmod(b,a,-fmpz_get_si(x)); nmod_poly_neg(b, b); } else { nmod_poly_scalar_mul_nmod(b,a,fmpz_get_ui(x)); } result = (fq_nmod_equal(c, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_nmod_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(c, ctx); nmod_poly_clear(b); fmpz_clear(p); fmpz_clear(x); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod/test/t-mul_si.c000066400000000000000000000065651461254215100177350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "nmod.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" TEST_FUNCTION_START(fq_nmod_mul_si, state) { int i, result; { fq_nmod_t rop; fq_nmod_ctx_t ctx; fmpz_t f; fmpz_init(f); fq_nmod_ctx_init_ui(ctx, 23, 1, "x"); fq_nmod_init(rop, ctx); for (i = 8; i <= 10; i++) { fq_nmod_set_si(rop, 1, ctx); fq_nmod_mul_si(rop, rop, 23 + i, ctx); fq_nmod_get_fmpz(f, rop, ctx); if (!fmpz_equal_si(f, i)) { flint_printf("FAIL: f should have been %wd\n", i); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); fflush(stdout); flint_abort(); } } fq_nmod_clear(rop, ctx); fq_nmod_ctx_clear(ctx); fmpz_clear(f); } /* Check aliasing of a, b */ for (i = 0; i < 1000; i++) { fq_nmod_ctx_t ctx; slong x; fq_nmod_t a, b; fq_nmod_ctx_init_randtest(ctx, state, 0); fq_nmod_init(a, ctx); fq_nmod_init(b, ctx); fq_nmod_randtest(a, state, ctx); x = z_randtest(state); fq_nmod_mul_si(b, a, x, ctx); fq_nmod_mul_si(a, a, x, ctx); result = (fq_nmod_equal(a, b, ctx)); if (!result) { flint_printf("FAIL: check aliasing\n"); flint_printf("a = "), fq_nmod_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = %wd\n",x); fflush(stdout); flint_abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(b, ctx); fq_nmod_ctx_clear(ctx); } /* compare with direct multiplication */ for (i = 0; i < 1000; i++) { fq_nmod_ctx_t ctx; slong x; fq_nmod_t a, c; nmod_poly_t b; fq_nmod_ctx_init_randtest(ctx, state, 0); fq_nmod_init(a, ctx); fq_nmod_init(c, ctx); nmod_poly_init(b, ctx->mod.n); fq_nmod_randtest(a, state, ctx); x = z_randtest(state); fq_nmod_mul_si(c, a, x, ctx); if (x < 0) { nmod_poly_scalar_mul_nmod(b, a, nmod_set_ui(-x, ctx->mod)); nmod_poly_neg(b, b); } else { nmod_poly_scalar_mul_nmod(b, a, nmod_set_ui(x, ctx->mod)); } result = (fq_nmod_equal(c, b, ctx)); if (!result) { flint_printf("FAIL: check direct\n"); flint_printf("a = "), fq_nmod_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = %wd\n",x); fflush(stdout); flint_abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(c, ctx); nmod_poly_clear(b); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod/test/t-mul_ui.c000066400000000000000000000047761461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "nmod_poly.h" #include "fq_nmod.h" TEST_FUNCTION_START(fq_nmod_mul_ui, state) { int i, result; /* Check aliasing of a, b */ for (i = 0; i < 2000; i++) { fq_nmod_ctx_t ctx; ulong x; fq_nmod_t a, b; fq_nmod_ctx_init_randtest(ctx, state, 0); fq_nmod_init(a, ctx); fq_nmod_init(b, ctx); fq_nmod_randtest(a, state, ctx); x = z_randtest(state); fq_nmod_mul_ui(b, a, x, ctx); fq_nmod_mul_ui(a, a, x, ctx); result = (fq_nmod_equal(a, b, ctx)); if (!result) { flint_printf("FAIL 1:\n\n"); flint_printf("a = "), fq_nmod_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = %wu\n",x); fflush(stdout); flint_abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(b, ctx); fq_nmod_ctx_clear(ctx); } /* compare with direct multiplication */ for (i = 0; i < 2000; i++) { fq_nmod_ctx_t ctx; ulong x; fq_nmod_t a, c; nmod_poly_t b; fq_nmod_ctx_init_randtest(ctx, state, 0); fq_nmod_init(a, ctx); fq_nmod_init(c, ctx); nmod_poly_init(b, ctx->mod.n); fq_nmod_randtest(a, state, ctx); x = n_randint(state, ctx->mod.n); fq_nmod_mul_ui(c, a, x, ctx); nmod_poly_scalar_mul_nmod(b,a,x); result = (fq_nmod_equal(c, b, ctx)); if (!result) { flint_printf("FAIL 2:\n\n"); flint_printf("a = "), fq_nmod_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_nmod_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_nmod_print_pretty(c, ctx), flint_printf("\n"); flint_printf("x = %wu\n",x); fflush(stdout); flint_abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(c, ctx); nmod_poly_clear(b); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod/test/t-multiplicative_order.c000066400000000000000000000010351461254215100226560ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-multiplicative_order.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-neg.c000066400000000000000000000010141461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-norm.c000066400000000000000000000010151461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-norm.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-pow.c000066400000000000000000000010141461254215100172320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-pow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-pth_root.c000066400000000000000000000010211461254215100202610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-pth_root.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-sqr.c000066400000000000000000000010141461254215100172320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-sqr.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-sqrt.c000066400000000000000000000010161461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-sub.c000066400000000000000000000010141461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/test/t-trace.c000066400000000000000000000010161461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_templates/test/t-trace.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod/trace.c000066400000000000000000000035341461254215100163140ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "fmpz.h" #include "fq_nmod.h" void _fq_nmod_trace(fmpz_t rop2, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); slong i, l; mp_limb_t *t, rop; t = _nmod_vec_init(d); _nmod_vec_zero(t, d); t[0] = n_mod2_preinv(d, ctx->mod.n, ctx->mod.ninv); for (i = 1; i < d; i++) { for (l = ctx->len - 2; l >= 0 && ctx->j[l] >= d - (i - 1); l--) { t[i] = n_addmod(t[i], n_mulmod2_preinv(t[ctx->j[l] + i - d], ctx->a[l], ctx->mod.n, ctx->mod.ninv), ctx->mod.n); } if (l >= 0 && ctx->j[l] == d - i) { t[i] = n_addmod(t[i], n_mulmod2_preinv(ctx->a[l], i, ctx->mod.n, ctx->mod.ninv), ctx->mod.n); } t[i] = n_negmod(t[i], ctx->mod.n); } rop = WORD(0); for (i = 0; i < len; i++) { rop = n_addmod(rop, n_mulmod2_preinv(op[i], t[i], ctx->mod.n, ctx->mod.ninv), ctx->mod.n); } _nmod_vec_clear(t); fmpz_set_ui(rop2, rop); } void fq_nmod_trace(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { if (fq_nmod_is_zero(op, ctx)) { fmpz_zero(rop); return; } _fq_nmod_trace(rop, op->coeffs, op->length, ctx); } flint-3.1.3/src/fq_nmod/vec_templates.c000066400000000000000000000021061461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fq_nmod.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/add.c" #include "fq_vec_templates/clear.c" #include "fq_vec_templates/equal.c" #include "fq_vec_templates/init.c" #include "fq_vec_templates/io.c" #include "fq_vec_templates/is_zero.c" #include "fq_vec_templates/neg.c" #include "fq_vec_templates/randtest.c" #include "fq_vec_templates/scalar_addmul_fq.c" #include "fq_vec_templates/scalar_mul_fq.c" #include "fq_vec_templates/scalar_submul_fq.c" #include "fq_vec_templates/set.c" #include "fq_vec_templates/sub.c" #include "fq_vec_templates/swap.c" #include "fq_vec_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_embed.h000066400000000000000000000021101461254215100163440ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_EMBED_H #define FQ_NMOD_EMBED_H #ifdef FQ_NMOD_EMBED_INLINES_C #define FQ_NMOD_EMBED_INLINE #define FQ_EMBED_TEMPLATES_INLINE #else #define FQ_NMOD_EMBED_INLINE static inline #define FQ_EMBED_TEMPLATES_INLINE static inline #endif #include "fq_nmod_types.h" #define T fq_nmod #define B nmod #include "fq_embed_templates.h" void TEMPLATE(T, modulus_pow_series_inv)(TEMPLATE(B, poly_t) res, const TEMPLATE(T, ctx_t) ctx, slong trunc); #undef B #undef T void fq_nmod_modulus_derivative_inv(fq_nmod_t m_prime, fq_nmod_t m_prime_inv, const fq_nmod_ctx_t ctx); #endif flint-3.1.3/src/fq_nmod_embed/000077500000000000000000000000001461254215100162015ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_embed/modulus_derivative_inv.c000066400000000000000000000013121461254215100231300ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_embed.h" void fq_nmod_modulus_derivative_inv(fq_nmod_t m_prime, fq_nmod_t m_prime_inv, const fq_nmod_ctx_t ctx) { nmod_poly_derivative(m_prime, fq_nmod_ctx_modulus(ctx)); fq_nmod_inv(m_prime_inv, m_prime, ctx); } flint-3.1.3/src/fq_nmod_embed/modulus_pow_series_inv.c000066400000000000000000000016151461254215100231530ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_embed.h" #define T fq_nmod #define B nmod void TEMPLATE(T, modulus_pow_series_inv)(TEMPLATE(B, poly_t) res, const TEMPLATE(T, ctx_t) ctx, slong trunc) { TEMPLATE(B, poly_reverse)(res, TEMPLATE(T, ctx_modulus)(ctx), TEMPLATE(T, ctx_degree)(ctx) + 1); TEMPLATE(B, poly_inv_series)(res, res, trunc); } #undef B #undef T flint-3.1.3/src/fq_nmod_embed/mul_matrix.c000066400000000000000000000034561461254215100205360ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "fq_nmod.h" #include "fq_nmod_embed.h" void fq_nmod_embed_mul_matrix(nmod_mat_t matrix, const fq_nmod_t gen, const fq_nmod_ctx_t ctx) { slong i, j, len = fq_nmod_ctx_degree(ctx); const nmod_poly_struct *modulus = ctx->modulus; const nmod_t mod = modulus->mod; mp_limb_t lead; /* This is usually 1, unless the context is non-monic */ lead = nmod_inv(modulus->coeffs[len], mod); for (i = 0; i < gen->length; i++) nmod_mat_entry(matrix, i, 0) = gen->coeffs[i]; for (i = gen->length; i < len; i++) nmod_mat_entry(matrix, i, 0) = 0; /* M[i, j] = M[i - 1, j - 1] - M[len - 1, j - 1] * lead * ctx->modulus->coeffs[i] */ for (j = 1; j < len; j++) { nmod_mat_entry(matrix, len - 1, j) = nmod_mul(nmod_mat_entry(matrix, len - 1, j - 1), lead, mod); for (i = 0; i < len; i++) { nmod_mat_entry(matrix, i, j) = nmod_mul(nmod_mat_entry(matrix, len - 1, j), modulus->coeffs[i], mod); if (i > 0) nmod_mat_entry(matrix, i, j) = nmod_sub(nmod_mat_entry(matrix, i, j), nmod_mat_entry(matrix, i - 1, j - 1), mod); nmod_mat_entry(matrix, i, j) = nmod_neg(nmod_mat_entry(matrix, i, j), mod); } } } flint-3.1.3/src/fq_nmod_embed/test/000077500000000000000000000000001461254215100171605ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_embed/test/main.c000066400000000000000000000020661461254215100202540ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-composition_matrix.c" #include "t-embed.c" #include "t-embed_matrices.c" #include "t-mono_dual_matrix.c" #include "t-mul_matrix.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_embed_composition_matrix), TEST_FUNCTION(fq_nmod_embed), TEST_FUNCTION(fq_nmod_embed_matrices), TEST_FUNCTION(fq_nmod_embed_mono_dual_matrix), TEST_FUNCTION(fq_nmod_embed_mul_matrix) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod_embed/test/t-composition_matrix.c000066400000000000000000000012541461254215100235160ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_nmod #define CAP_T FQ_NMOD #define B nmod #include "fq_embed_templates/test/t-composition_matrix.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_embed/test/t-embed.c000066400000000000000000000012211461254215100206350ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_nmod #define CAP_T FQ_NMOD #define B nmod #include "fq_embed_templates/test/t-embed.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_embed/test/t-embed_matrices.c000066400000000000000000000012261461254215100225310ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_nmod.h" #include "fq_nmod_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_nmod #define CAP_T FQ_NMOD #define B nmod #include "fq_embed_templates/test/t-embed_matrices.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_embed/test/t-mono_dual_matrix.c000066400000000000000000000012301461254215100231220ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_nmod.h" #include "fq_nmod_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_nmod #define CAP_T FQ_NMOD #define B nmod #include "fq_embed_templates/test/t-mono_dual_matrix.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_embed/test/t-mul_matrix.c000066400000000000000000000012221461254215100217430ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_nmod.h" #include "fq_nmod_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_nmod #define CAP_T FQ_NMOD #define B nmod #include "fq_embed_templates/test/t-mul_matrix.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat.h000066400000000000000000000020621461254215100160570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_MAT_H #define FQ_NMOD_MAT_H #ifdef FQ_NMOD_MAT_INLINES_C #define FQ_MAT_TEMPLATES_INLINE #define FQ_NMOD_MAT_INLINE #else #define FQ_MAT_TEMPLATES_INLINE static inline #define FQ_NMOD_MAT_INLINE static inline #endif #include "fq_nmod_types.h" /* Cutoff between classical and recursive triangular solving */ #define FQ_NMOD_MAT_SOLVE_TRI_ROWS_CUTOFF 64 #define FQ_NMOD_MAT_SOLVE_TRI_COLS_CUTOFF 64 /* Cutoff between classical and recursive LU decomposition */ #define FQ_NMOD_MAT_LU_RECURSIVE_CUTOFF 4 int FQ_NMOD_MAT_MUL_KS_CUTOFF(slong r, slong c, const fq_nmod_ctx_t ctx); #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_nmod_mat/000077500000000000000000000000001461254215100157065ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mat/inlines.c000066400000000000000000000006621461254215100175170ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_MAT_INLINES_C #include "fq_nmod_mat.h" flint-3.1.3/src/fq_nmod_mat/mul_ks_cutoff.c000066400000000000000000000011731461254215100207140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" int FQ_NMOD_MAT_MUL_KS_CUTOFF(slong r, slong c, const fq_nmod_ctx_t ctx) { slong d2 = FLINT_MAX(0, 12 - fq_nmod_ctx_degree(ctx)); if (2*(r + 1)*c > d2*d2) return 1; else return 0; } flint-3.1.3/src/fq_nmod_mat/reduce_row.c000066400000000000000000000076001461254215100202130ustar00rootroot00000000000000/* Copyright (C) 2015, 2019 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" slong fq_nmod_mat_reduce_row_KS(fq_nmod_mat_t A, slong * P, slong * L, slong m, const fq_nmod_ctx_t ctx) { slong n = A->c, i, j, r, bits, res = -WORD(1); fq_nmod_t h; fmpz * mvec; fmpz_t mz, rz; bits = 2 * FLINT_BIT_COUNT(fq_nmod_ctx_prime(ctx)) + FLINT_BIT_COUNT(m + 1) + FLINT_BIT_COUNT(fq_nmod_ctx_degree(ctx) + 1); fq_nmod_init(h, ctx); fmpz_init(mz); fmpz_init(rz); mvec = (fmpz *) _fmpz_vec_init(n); for (i = 0; i < n; i++) fq_nmod_bit_pack(mvec + i, fq_nmod_mat_entry(A, m, i), bits, ctx); for (i = 0; i < n; i++) { if (i != 0) fq_nmod_bit_unpack(fq_nmod_mat_entry(A, m, i), mvec + i, bits, ctx); if (!fq_nmod_is_zero(fq_nmod_mat_entry(A, m, i), ctx)) { r = P[i]; if (r != -WORD(1)) { fq_nmod_neg(h, fq_nmod_mat_entry(A, m, i), ctx); fq_nmod_bit_pack(mz, h, bits, ctx); for (j = i + 1; j < L[r]; j++) { fq_nmod_bit_pack(rz, fq_nmod_mat_entry(A, r, j), bits, ctx); fmpz_mul(rz, rz, mz); fmpz_add(mvec + j, mvec + j, rz); } fq_nmod_zero(fq_nmod_mat_entry(A, m, i), ctx); } else { fq_nmod_inv(h, fq_nmod_mat_entry(A, m, i), ctx); fq_nmod_one(fq_nmod_mat_entry(A, m, i), ctx); for (j = i + 1; j < L[m]; j++) { fq_nmod_bit_unpack(fq_nmod_mat_entry(A, m, j), mvec + j, bits, ctx); fq_nmod_mul(fq_nmod_mat_entry(A, m, j), fq_nmod_mat_entry(A, m, j), h, ctx); } P[i] = m; res = i; break; } } } fq_nmod_clear(h, ctx); fmpz_clear(mz); fmpz_clear(rz); _fmpz_vec_clear(mvec, n); return res; } slong fq_nmod_mat_reduce_row(fq_nmod_mat_t A, slong * P, slong * L, slong m, const fq_nmod_ctx_t ctx) { slong n = A->c, i, j, r; nmod_poly_t h; if (m > 10 && fq_nmod_ctx_degree(ctx) > 6) return fq_nmod_mat_reduce_row_KS(A, P, L, m, ctx); nmod_poly_init(h, fq_nmod_ctx_prime(ctx)); for (i = 0; i < n; i++) { if (i != 0) fq_nmod_reduce(fq_nmod_mat_entry(A, m, i), ctx); if (!fq_nmod_is_zero(fq_nmod_mat_entry(A, m, i), ctx)) { r = P[i]; if (r != -WORD(1)) { for (j = i + 1; j < L[r]; j++) { nmod_poly_mul(h, fq_nmod_mat_entry(A, r, j), fq_nmod_mat_entry(A, m, i)); nmod_poly_sub(fq_nmod_mat_entry(A, m, j), fq_nmod_mat_entry(A, m, j), h); } fq_nmod_zero(fq_nmod_mat_entry(A, m, i), ctx); } else { fq_nmod_inv(h, fq_nmod_mat_entry(A, m, i), ctx); fq_nmod_one(fq_nmod_mat_entry(A, m, i), ctx); for (j = i + 1; j < L[m]; j++) { fq_nmod_reduce(fq_nmod_mat_entry(A, m, j), ctx); fq_nmod_mul(fq_nmod_mat_entry(A, m, j), fq_nmod_mat_entry(A, m, j), h, ctx); } P[i] = m; nmod_poly_clear(h); return i; } } } for (j = i + 1; j < L[m]; j++) fq_nmod_reduce(fq_nmod_mat_entry(A, m, j), ctx); nmod_poly_clear(h); return -WORD(1); } flint-3.1.3/src/fq_nmod_mat/test/000077500000000000000000000000001461254215100166655ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mat/test/main.c000066400000000000000000000055471461254215100177700ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-can_solve.c" #include "t-charpoly.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-equal.c" #include "t-inv.c" #include "t-invert_rows_cols.c" #include "t-is_zero.c" #include "t-lu_classical.c" #include "t-lu_recursive.c" #include "t-minpoly.c" #include "t-mul.c" #include "t-mul_KS.c" #include "t-mul_vec.c" #include "t-nullspace.c" #include "t-one.c" #include "t-rank.c" #include "t-rref.c" #include "t-set_fmpz_mod_mat.c" #include "t-set_nmod_mat.c" #include "t-solve.c" #include "t-solve_tril.c" #include "t-solve_tril_classical.c" #include "t-solve_tril_recursive.c" #include "t-solve_triu.c" #include "t-solve_triu_classical.c" #include "t-solve_triu_recursive.c" #include "t-submul.c" #include "t-vec_mul.c" #include "t-window_init_clear.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_mat_add_sub), TEST_FUNCTION(fq_nmod_mat_can_solve), TEST_FUNCTION(fq_nmod_mat_charpoly), TEST_FUNCTION(fq_nmod_mat_concat_horizontal), TEST_FUNCTION(fq_nmod_mat_concat_vertical), TEST_FUNCTION(fq_nmod_mat_equal), TEST_FUNCTION(fq_nmod_mat_inv), TEST_FUNCTION(fq_nmod_mat_invert_rows_cols), TEST_FUNCTION(fq_nmod_mat_is_zero), TEST_FUNCTION(fq_nmod_mat_lu_classical), TEST_FUNCTION(fq_nmod_mat_lu_recursive), TEST_FUNCTION(fq_nmod_mat_minpoly), TEST_FUNCTION(fq_nmod_mat_mul), TEST_FUNCTION(fq_nmod_mat_mul_KS), TEST_FUNCTION(fq_nmod_mat_mul_vec), TEST_FUNCTION(fq_nmod_mat_nullspace), TEST_FUNCTION(fq_nmod_mat_one), TEST_FUNCTION(fq_nmod_mat_rank), TEST_FUNCTION(fq_nmod_mat_rref), TEST_FUNCTION(fq_nmod_mat_set_fmpz_mod_mat), TEST_FUNCTION(fq_nmod_mat_set_nmod_mat), TEST_FUNCTION(fq_nmod_mat_solve), TEST_FUNCTION(fq_nmod_mat_solve_tril), TEST_FUNCTION(fq_nmod_mat_solve_tril_classical), TEST_FUNCTION(fq_nmod_mat_solve_tril_recursive), TEST_FUNCTION(fq_nmod_mat_solve_triu), TEST_FUNCTION(fq_nmod_mat_solve_triu_classical), TEST_FUNCTION(fq_nmod_mat_solve_triu_recursive), TEST_FUNCTION(fq_nmod_mat_submul), TEST_FUNCTION(fq_nmod_mat_vec_mul), TEST_FUNCTION(fq_nmod_mat_window_init_clear), TEST_FUNCTION(fq_nmod_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod_mat/test/t-add_sub.c000066400000000000000000000010551461254215100206740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-add_sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-can_solve.c000066400000000000000000000010601461254215100212400ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-can_solve.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-charpoly.c000066400000000000000000000011101461254215100211040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-charpoly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-concat_horizontal.c000066400000000000000000000010751461254215100230150ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-concat_horizontal.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-concat_vertical.c000066400000000000000000000010731461254215100224330ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-concat_vertical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-equal.c000066400000000000000000000010531461254215100204000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-equal.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-inv.c000066400000000000000000000010531461254215100200650ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-inv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-invert_rows_cols.c000066400000000000000000000010701461254215100226710ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-invert_rows_cols.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-is_zero.c000066400000000000000000000010551461254215100207450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-is_zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-lu_classical.c000066400000000000000000000010621461254215100217270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-lu_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-lu_recursive.c000066400000000000000000000010621461254215100220000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-lu_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-minpoly.c000066400000000000000000000011071461254215100207600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-minpoly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-mul.c000066400000000000000000000010511461254215100200640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-mul_KS.c000066400000000000000000000010541461254215100204640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-mul_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-mul_vec.c000066400000000000000000000011111461254215100207160ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-mul_vec.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-nullspace.c000066400000000000000000000010571461254215100212630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-nullspace.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-one.c000066400000000000000000000010521461254215100200510ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-one.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-rank.c000066400000000000000000000010521461254215100202230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-rank.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-rref.c000066400000000000000000000010521461254215100202260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-rref.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-set_fmpz_mod_mat.c000066400000000000000000000010671461254215100226250ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-set_fmpz_mod_mat.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-set_nmod_mat.c000066400000000000000000000011331461254215100217410ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-set_nmod_mat.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-solve.c000066400000000000000000000010551461254215100204230ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-solve.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-solve_tril.c000066400000000000000000000010601461254215100214510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-solve_tril.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-solve_tril_classical.c000066400000000000000000000010721461254215100234720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-solve_tril_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-solve_tril_recursive.c000066400000000000000000000010721461254215100235430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-solve_tril_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-solve_triu.c000066400000000000000000000010601461254215100214620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-solve_triu.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-solve_triu_classical.c000066400000000000000000000010721461254215100235030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-solve_triu_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-solve_triu_recursive.c000066400000000000000000000010721461254215100235540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-solve_triu_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-submul.c000066400000000000000000000010541461254215100206010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-submul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-vec_mul.c000066400000000000000000000011111461254215100207160ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-vec_mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-window_init_clear.c000066400000000000000000000011261461254215100227720ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-window_init_clear.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mat/test/t-zero.c000066400000000000000000000010521461254215100202470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/test/t-zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_mpoly.h000066400000000000000000001742151461254215100164500ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_MPOLY_H #define FQ_NMOD_MPOLY_H #ifdef FQ_NMOD_MPOLY_INLINES_C #define FQ_NMOD_MPOLY_INLINE #else #define FQ_NMOD_MPOLY_INLINE static inline #endif #include "fq_nmod_types.h" #include "mpoly_types.h" #if FLINT_WANT_ASSERT # include "fq_nmod.h" # include "mpoly.h" #endif #ifdef __cplusplus extern "C" { #endif /* Internal type definitions *************************************************/ /* fq_nmod_mpoly_univar_t sparse univariates with multivariate coefficients */ typedef struct { fq_nmod_mpoly_struct * coeffs; /* multivariate coefficients */ fmpz * exps; slong alloc; slong length; } fq_nmod_mpoly_univar_struct; typedef fq_nmod_mpoly_univar_struct fq_nmod_mpoly_univar_t[1]; /* fq_nmod_mpolyu_t sparse univariates with fq_nmod_mpoly_t coefficients with uniform bits and LEX ordering */ typedef struct { fq_nmod_mpoly_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* default bits to construct coeffs */ } fq_nmod_mpolyu_struct; typedef fq_nmod_mpolyu_struct fq_nmod_mpolyu_t[1]; /* fq_nmod_mpolyn_t multivariates with fq_nmod_poly_t coefficients */ typedef struct { n_fq_poly_struct * coeffs; ulong * exps; slong alloc; slong length; slong bits; } fq_nmod_mpolyn_struct; typedef fq_nmod_mpolyn_struct fq_nmod_mpolyn_t[1]; /* fq_nmod_mpolyun_t sparse univariates with fq_nmod_mpolyn_t coefficients with uniform bits and LEX ordering */ typedef struct { fq_nmod_mpolyn_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* default bits to construct coeffs */ } fq_nmod_mpolyun_struct; typedef fq_nmod_mpolyun_struct fq_nmod_mpolyun_t[1]; /* Embeddings ****************************************************************/ /* see fq_nmod_mpoly/fq_nmod_embed.c for more info */ typedef struct bad_fq_nmod_embed { const fq_nmod_ctx_struct * smctx; /* modulus is f */ fq_nmod_poly_t phi_sm; /* phi as an element of F_p[theta][x] */ fq_nmod_poly_t h; n_fq_poly_t h_as_n_fq_poly; const fq_nmod_ctx_struct * lgctx; /* modulus is g */ fq_nmod_t theta_lg; /* theta as an element of F_p[phi]/g(phi) */ fq_nmod_t x_lg; /* x as an element of F_p[phi]/g(phi) */ nmod_mat_t lg_to_sm_mat; nmod_mat_t sm_to_lg_mat; } bad_fq_nmod_embed_struct; typedef bad_fq_nmod_embed_struct bad_fq_nmod_embed_t[1]; void bad_fq_nmod_embed_clear(bad_fq_nmod_embed_t emb); void bad_fq_nmod_embed_array_init(bad_fq_nmod_embed_struct * emb, const fq_nmod_ctx_t bigctx, const fq_nmod_ctx_t smallctx); void bad_fq_nmod_embed_sm_to_lg(fq_nmod_t out, const fq_nmod_poly_t in, const bad_fq_nmod_embed_t emb); void bad_fq_nmod_embed_lg_to_sm(fq_nmod_poly_t out, const fq_nmod_t in, const bad_fq_nmod_embed_t emb); void bad_n_fq_embed_sm_to_lg(mp_limb_t * out_, const n_poly_t in_, const bad_fq_nmod_embed_t emb); void bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(fq_nmod_t out, const n_poly_t in_, const bad_fq_nmod_embed_t emb); void bad_n_fq_embed_lg_to_sm(n_poly_t out_, const mp_limb_t * in_, const bad_fq_nmod_embed_t emb); void bad_fq_nmod_embed_fq_nmod_lg_to_n_fq_sm(n_poly_t out_, const fq_nmod_t in, const bad_fq_nmod_embed_t emb); void bad_n_fq_embed_sm_elem_to_lg(mp_limb_t * out, const mp_limb_t * in, const bad_fq_nmod_embed_t emb); void bad_fq_nmod_embed_sm_elem_to_lg(fq_nmod_t out, const fq_nmod_t in, const bad_fq_nmod_embed_t emb); typedef struct bad_fq_nmod_mpoly_embed_chooser { bad_fq_nmod_embed_struct * embed; slong m; /* degree of the extension F_q / F_p */ slong n; /* degree of the extension F_q^n / F_q */ slong k; /* index of current in embed */ mp_limb_t p; } bad_fq_nmod_mpoly_embed_chooser_struct; typedef bad_fq_nmod_mpoly_embed_chooser_struct bad_fq_nmod_mpoly_embed_chooser_t[1]; bad_fq_nmod_embed_struct * bad_fq_nmod_mpoly_embed_chooser_init( bad_fq_nmod_mpoly_embed_chooser_t embc, fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate); void bad_fq_nmod_mpoly_embed_chooser_clear( bad_fq_nmod_mpoly_embed_chooser_t embc, fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate); bad_fq_nmod_embed_struct * bad_fq_nmod_mpoly_embed_chooser_next( bad_fq_nmod_mpoly_embed_chooser_t embc, fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate); /* Context object ************************************************************/ void fq_nmod_mpoly_ctx_init_deg(fq_nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t p, slong deg); void fq_nmod_mpoly_ctx_init(fq_nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fq_nmod_ctx_t fqctx); void fq_nmod_mpoly_ctx_init_rand(fq_nmod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, flint_bitcnt_t p_bits, slong deg_bound); void fq_nmod_mpoly_ctx_clear(fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE slong fq_nmod_mpoly_ctx_nvars(const fq_nmod_mpoly_ctx_t ctx) { return ctx->minfo->nvars; } FQ_NMOD_MPOLY_INLINE ordering_t fq_nmod_mpoly_ctx_ord(const fq_nmod_mpoly_ctx_t ctx) { return ctx->minfo->ord; } /* Memory management ********************************************************/ FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_init(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->bits = MPOLY_MIN_BITS; A->coeffs_alloc = 0; A->exps_alloc = 0; } FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_clear(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { if (A->coeffs_alloc > 0) flint_free(A->coeffs); if (A->exps_alloc > 0) flint_free(A->exps); } void fq_nmod_mpoly_init2(fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_init3(fq_nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_realloc(fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_fit_length(fq_nmod_mpoly_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_fit_length_fit_bits(fq_nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_fit_length_reset_bits(fq_nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE void _fq_nmod_mpoly_fit_length( mp_limb_t ** coeffs, slong * coeffs_alloc, slong d, ulong ** exps, slong * exps_alloc, slong N, slong length) { if (d*length > *coeffs_alloc) { *coeffs_alloc = FLINT_MAX(d*length, *coeffs_alloc*2); *coeffs = (mp_limb_t *) flint_realloc(*coeffs, *coeffs_alloc*sizeof(mp_limb_t)); } if (N*length > *exps_alloc) { *exps_alloc = FLINT_MAX(N*length, *exps_alloc*2); *exps = (mp_limb_t *) flint_realloc(*exps, *exps_alloc*sizeof(ulong)); } } FQ_NMOD_MPOLY_INLINE void _fq_nmod_mpoly_set_length(fq_nmod_mpoly_t A, slong newlen, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(fq_nmod_ctx_degree(ctx->fqctx)*newlen <= A->coeffs_alloc); FLINT_ASSERT(mpoly_words_per_exp(A->bits, ctx->minfo)*newlen <= A->exps_alloc); A->length = newlen; } FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_truncate(fq_nmod_mpoly_t A, slong newlen, const fq_nmod_mpoly_ctx_t ctx) { if (A->length > newlen) { A->length = newlen; } } /* Input/output **************************************************************/ int fq_nmod_mpoly_set_str_pretty(fq_nmod_mpoly_t A, const char * str, const char ** x, const fq_nmod_mpoly_ctx_t ctx); char * fq_nmod_mpoly_get_str_pretty(const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx); #ifdef FLINT_HAVE_FILE int fq_nmod_mpoly_fprint_pretty(FILE * file, const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx); #endif int fq_nmod_mpoly_print_pretty(const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx); /* Basic manipulation *******************************************************/ void fq_nmod_mpoly_gen(fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_is_gen(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_equal(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_swap(fq_nmod_mpoly_t A, fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { FLINT_SWAP(fq_nmod_mpoly_struct, *A, *B); } /* Constants *****************************************************************/ FQ_NMOD_MPOLY_INLINE mp_limb_t * fq_nmod_mpoly_get_nonzero_n_fq(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(mpoly_monomial_is_zero(A->exps, mpoly_words_per_exp(A->bits, ctx->minfo))); return A->coeffs; } int fq_nmod_mpoly_is_fq_nmod(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_n_fq(fq_nmod_mpoly_t A, const mp_limb_t * c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_ui(fq_nmod_mpoly_t A, ulong c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_fmpz(fq_nmod_mpoly_t A, const fmpz_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_fq_nmod_gen(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_equal_fq_nmod(const fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_zero(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { _fq_nmod_mpoly_set_length(A, 0, ctx); } void fq_nmod_mpoly_one(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE int fq_nmod_mpoly_is_zero(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return A->length == 0; } int fq_nmod_mpoly_is_one(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); /* Degrees *******************************************************************/ int fq_nmod_mpoly_degrees_fit_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_degrees_fmpz(fmpz ** degs, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_degrees_si(slong * degs, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_degree_fmpz(fmpz_t deg, const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); slong fq_nmod_mpoly_degree_si(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_total_degree_fits_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_total_degree_fmpz(fmpz_t td, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); slong fq_nmod_mpoly_total_degree_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_used_vars(int * used, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); /* Coefficients **************************************************************/ void fq_nmod_mpoly_get_coeff_fq_nmod_monomial(fq_nmod_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t M, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_coeff_fq_nmod_monomial(fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_t M, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_coeff_fq_nmod_fmpz(fq_nmod_t c, const fq_nmod_mpoly_t A, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_coeff_fq_nmod_ui(fq_nmod_t c, const fq_nmod_mpoly_t A, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_coeff_fq_nmod_ui(fq_nmod_mpoly_t A, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_coeff_vars_ui(fq_nmod_mpoly_t C, const fq_nmod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE mp_limb_t * _fq_nmod_mpoly_leadcoeff( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return A->coeffs + 0; } int fq_nmod_mpoly_is_monic(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); /* conversion ****************************************************************/ int fq_nmod_mpoly_is_fq_nmod_poly(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_get_fq_nmod_poly(fq_nmod_poly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_set_fq_nmod_poly(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_struct * Bcoeffs, slong Blen, slong var, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_fq_nmod_poly(fq_nmod_mpoly_t A, const fq_nmod_poly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); /* comparison ****************************************************************/ int fq_nmod_mpoly_cmp(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); /* container operations ******************************************************/ int fq_nmod_mpoly_is_canonical(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE slong fq_nmod_mpoly_length(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return A->length; } void fq_nmod_mpoly_resize(fq_nmod_mpoly_t A, slong new_length, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_term_coeff_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_term_coeff_fq_nmod(fq_nmod_mpoly_t A, slong i, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_term_exp_fits_ui(const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_term_exp_fits_si(const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_term_exp_fmpz(fmpz ** exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_term_exp_ui(ulong * exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_term_exp_si(slong * exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); ulong fq_nmod_mpoly_get_term_var_exp_ui(const fq_nmod_mpoly_t A, slong i, slong var, const fq_nmod_mpoly_ctx_t ctx); slong fq_nmod_mpoly_get_term_var_exp_si(const fq_nmod_mpoly_t A, slong i, slong var, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_term_exp_fmpz(fq_nmod_mpoly_t A, slong i, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_term_exp_ui(fq_nmod_mpoly_t A, slong i, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_term(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_get_term_monomial(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_push_term_fq_nmod_fmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_push_term_fq_nmod_ffmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_push_term_fq_nmod_ui(fq_nmod_mpoly_t A, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_sort_terms(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_combine_like_terms(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_reverse(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_assert_canonical(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_radix_sort1(fq_nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask, slong d); void _fq_nmod_mpoly_radix_sort(fq_nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask, slong d); void _fq_nmod_mpoly_push_exp_ffmpz(fq_nmod_mpoly_t A, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_push_exp_pfmpz(fq_nmod_mpoly_t A, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_push_exp_ui(fq_nmod_mpoly_t A, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx); /* Random generation *********************************************************/ void fq_nmod_mpoly_randtest_bound(fq_nmod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_randtest_bounds(fq_nmod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_randtest_bits(fq_nmod_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const fq_nmod_mpoly_ctx_t ctx); /* Addition/Subtraction ******************************************************/ slong _fq_nmod_mpoly_add( mp_limb_t * coeff1, ulong * exp1, mp_limb_t * coeff2, const ulong * exp2, slong len2, mp_limb_t * coeff3, const ulong * exp3, slong len3, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx); void fq_nmod_mpoly_add_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_add_n_fq(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mp_limb_t * c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_sub_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t C, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_add(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_sub(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx); /* Scalar operations *********************************************************/ void fq_nmod_mpoly_neg(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_scalar_mul_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_scalar_mul_n_fq(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mp_limb_t * c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_make_monic(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_scalar_addmul_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_t e, const fq_nmod_mpoly_ctx_t ctx); /* Differentiation **********************************************************/ void fq_nmod_mpoly_derivative(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ void fq_nmod_mpoly_evaluate_one_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_t val, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_eval_all_fq_nmod(fq_nmod_t ev, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, fq_nmod_struct * const * alphas, const mpoly_ctx_t mctx, const fq_nmod_ctx_t fqctx); void fq_nmod_mpoly_evaluate_all_fq_nmod(fq_nmod_t ev, const fq_nmod_mpoly_t A, fq_nmod_struct * const * vals, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_compose_fq_nmod_poly(fq_nmod_poly_t A, const fq_nmod_mpoly_t B, fq_nmod_poly_struct * const * C, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_compose_mat(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz_mat_t M, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC); int fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, fq_nmod_mpoly_struct * const * C, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC); int fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, fq_nmod_mpoly_struct * const * C, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC); int fq_nmod_mpoly_compose_fq_nmod_mpoly(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, fq_nmod_mpoly_struct * const * C, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC); void fq_nmod_mpoly_compose_fq_nmod_mpoly_gen(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const slong * c, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC); /* Multiplication ************************************************************/ void fq_nmod_mpoly_mul(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_mul_johnson(fq_nmod_mpoly_t poly1, const fq_nmod_mpoly_t poly2, const fq_nmod_mpoly_t poly3, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_mul_johnson( fq_nmod_mpoly_t A, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t ctx); /* Powering ******************************************************************/ int fq_nmod_mpoly_pow_fmpz(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz_t k, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_pow_ui(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, ulong k, const fq_nmod_mpoly_ctx_t ctx); /* Division ******************************************************************/ int fq_nmod_mpoly_divides(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_div(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_divrem(fq_nmod_mpoly_t Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_divrem_ideal(fq_nmod_mpoly_struct ** Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, fq_nmod_mpoly_struct * const * B, slong len, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_divexact(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_divides(Q, A, B, ctx)) return; flint_throw(FLINT_ERROR, "fq_nmod_mpoly_divexact: nonexact division"); } int fq_nmod_mpoly_divides_monagan_pearce(fq_nmod_mpoly_t poly1, const fq_nmod_mpoly_t poly2, const fq_nmod_mpoly_t poly3, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_div_monagan_pearce(fq_nmod_mpoly_t q, const fq_nmod_mpoly_t poly2, const fq_nmod_mpoly_t poly3, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_divrem_monagan_pearce(fq_nmod_mpoly_t q, fq_nmod_mpoly_t r, const fq_nmod_mpoly_t poly2, const fq_nmod_mpoly_t poly3, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_divrem_ideal_monagan_pearce( fq_nmod_mpoly_struct ** q, fq_nmod_mpoly_t r, const fq_nmod_mpoly_t poly2, fq_nmod_mpoly_struct * const * poly3, slong len, const fq_nmod_mpoly_ctx_t ctx); int _fq_nmod_mpoly_divides_monagan_pearce(fq_nmod_mpoly_t A, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx); /* Square root ***************************************************************/ int fq_nmod_mpoly_sqrt_heap(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE int fq_nmod_mpoly_sqrt(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return fq_nmod_mpoly_sqrt_heap(Q, A, ctx); } FQ_NMOD_MPOLY_INLINE int fq_nmod_mpoly_is_square(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { int res; fq_nmod_mpoly_t Q; fq_nmod_mpoly_init(Q, ctx); res = fq_nmod_mpoly_sqrt_heap(Q, A, ctx); fq_nmod_mpoly_clear(Q, ctx); return res; } int fq_nmod_mpoly_quadratic_root(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); /* GCD ***********************************************************************/ void fq_nmod_mpoly_term_content(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_content_vars(fq_nmod_mpoly_t g, const fq_nmod_mpoly_t A, slong * vars, slong vars_length, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_gcd(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); int _fq_nmod_mpoly_gcd_algo(fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo); int fq_nmod_mpoly_gcd_cofactors(fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_gcd_brown(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_gcd_hensel(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_gcd_zippel(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_gcd_zippel2(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_deflation(fmpz * shift, fmpz * stride, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_deflate(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_inflate(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fq_nmod_mpoly_ctx_t ctx); /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ void mpoly_void_ring_init_fq_nmod_mpoly_ctx(mpoly_void_ring_t R, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyl_lead_coeff(fq_nmod_mpoly_t c, const fq_nmod_mpoly_t A, slong num_vars, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_to_mpolyl_perm_deflate( fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t lctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride); void fq_nmod_mpoly_from_mpolyl_perm_inflate( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride); int fq_nmod_mpolyl_gcd_zippel_smprime( fq_nmod_mpoly_t rG, const slong * rGdegs, fq_nmod_mpoly_t rAbar, fq_nmod_mpoly_t rBbar, const fq_nmod_mpoly_t A, const slong * Adegs, const fq_nmod_mpoly_t B, const slong * Bdegs, const fq_nmod_mpoly_t gamma, const slong * gammadegs, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyl_gcd_zippel_lgprime( fq_nmod_mpoly_t rG, const slong * rGdegs, fq_nmod_mpoly_t rAbar, fq_nmod_mpoly_t rBbar, const fq_nmod_mpoly_t A, const slong * Adegs, const fq_nmod_mpoly_t B, const slong * Bdegs, const fq_nmod_mpoly_t gamma, const slong * gammadegs, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyl_gcd_hensel_smprime( fq_nmod_mpoly_t G, slong Gdeg, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyl_content(fq_nmod_mpoly_t g, const fq_nmod_mpoly_t A, slong num_vars, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_pow_rmul(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, ulong k, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_to_fq_nmod_poly_deflate(fq_nmod_poly_t A, const fq_nmod_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_from_fq_nmod_poly_inflate(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_repack_bits(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_repack_bits_inplace(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_ctx_change_modulus(fq_nmod_mpoly_ctx_t ctx, slong deg); /* Univariates ***************************************************************/ void fq_nmod_mpoly_univar_init(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_univar_clear(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_univar_fit_length(fq_nmod_mpoly_univar_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_univar_print_pretty(const fq_nmod_mpoly_univar_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_univar_assert_canonical(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_univar_zero(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) { A->length = 0; } void fq_nmod_mpoly_univar_set_coeff_ui(fq_nmod_mpoly_univar_t A, ulong e, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_to_univar(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_from_univar(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_univar_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_from_univar(fq_nmod_mpoly_t A, const fq_nmod_mpoly_univar_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_univar_swap(fq_nmod_mpoly_univar_t A, fq_nmod_mpoly_univar_t B, const fq_nmod_mpoly_ctx_t ctx) { FLINT_SWAP(fq_nmod_mpoly_univar_struct, *A, *B); } int fq_nmod_mpoly_univar_degree_fits_si(const fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE slong fq_nmod_mpoly_univar_length(const fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) { return A->length; } slong fq_nmod_mpoly_univar_get_term_exp_si(fq_nmod_mpoly_univar_t A, slong i, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_univar_get_term_coeff(fq_nmod_mpoly_t c, const fq_nmod_mpoly_univar_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong)A->length); fq_nmod_mpoly_set(c, A->coeffs + i, ctx); } FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_univar_swap_term_coeff(fq_nmod_mpoly_t c, fq_nmod_mpoly_univar_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong)A->length); fq_nmod_mpoly_swap(c, A->coeffs + i, ctx); } int fq_nmod_mpoly_univar_pseudo_gcd(fq_nmod_mpoly_univar_t Gx, const fq_nmod_mpoly_univar_t Ax, const fq_nmod_mpoly_univar_t Bx, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_univar_resultant(fq_nmod_mpoly_t R, const fq_nmod_mpoly_univar_t Ax, const fq_nmod_mpoly_univar_t Bx, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_univar_discriminant(fq_nmod_mpoly_t D, const fq_nmod_mpoly_univar_t Fx, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_resultant(fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_discriminant(fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); /* mpolyu ********************************************************************/ int fq_nmod_mpolyu_is_canonical(const fq_nmod_mpolyu_t poly, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_init(fq_nmod_mpolyu_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_clear(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx); FQ_NMOD_MPOLY_INLINE void fq_nmod_mpolyu_swap(fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t uctx) { fq_nmod_mpolyu_struct t = *B; *B = *A; *A = t; } void fq_nmod_mpolyu_zero(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx); int fq_nmod_mpolyu_is_one(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx); void fq_nmod_mpolyu_print_pretty(const fq_nmod_mpolyu_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_fit_length(fq_nmod_mpolyu_t A, slong length, const fq_nmod_mpoly_ctx_t uctx); void fq_nmod_mpolyu_one(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx); void fq_nmod_mpolyu_degrees_si( slong * degs, const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_repack_bits_inplace( fq_nmod_mpolyu_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_shift_right(fq_nmod_mpolyu_t A, ulong s); void fq_nmod_mpolyu_shift_left(fq_nmod_mpolyu_t A, ulong s); int fq_nmod_mpolyu_content_mpoly(fq_nmod_mpoly_t g, const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_scalar_mul_fq_nmod(fq_nmod_mpolyu_t A, fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_set(fq_nmod_mpolyu_t A, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t uctx); void fq_nmod_mpolyu_evaluate_one_fq_nmod(fq_nmod_mpolyu_t E, fq_nmod_mpolyu_t A, slong var, const fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_setform(fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx); fq_nmod_mpoly_struct * _fq_nmod_mpolyu_get_coeff(fq_nmod_mpolyu_t A, ulong pow, const fq_nmod_mpoly_ctx_t uctx); void fq_nmod_mpoly_to_mpolyu_perm_deflate( fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride); void fq_nmod_mpoly_from_mpolyu_perm_inflate( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride); int fq_nmod_mpolyuu_divides(fq_nmod_mpolyu_t Q, const fq_nmod_mpolyu_t A, const fq_nmod_mpolyu_t B, slong nmainvars, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_divexact_mpoly_inplace(fq_nmod_mpolyu_t A, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_mul_mpoly(fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_mul_mpoly_inplace(fq_nmod_mpolyu_t A, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyu_gcdm_zippel(fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate); FQ_NMOD_MPOLY_INLINE mp_limb_t * fq_nmod_mpolyu_leadcoeff( const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return _fq_nmod_mpoly_leadcoeff(A->coeffs + 0, ctx); } /* mpolyn ********************************************************************/ void fq_nmod_mpolyn_init(fq_nmod_mpolyn_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_clear(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_swap(fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B); int fq_nmod_mpolyn_is_canonical(const fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_zero(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_one(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyn_is_zero(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_print_pretty(const fq_nmod_mpolyn_t A, const char ** x_in, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_fit_length(fq_nmod_mpolyn_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_fit_bits(fq_nmod_mpolyn_t A, slong bits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_set(fq_nmod_mpolyn_t A, const fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE mp_limb_t * fq_nmod_mpolyn_leadcoeff( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { /* slong d = fq_nmod_ctx_degree(ctx->fqctx); */ slong d = ctx->fqctx->modulus->length - 1; n_poly_struct * leadpoly; FLINT_ASSERT(A->length > 0); leadpoly = A->coeffs + 0; FLINT_ASSERT(leadpoly->length > 0); return leadpoly->coeffs + d*(leadpoly->length - 1); } FQ_NMOD_MPOLY_INLINE n_poly_struct * fq_nmod_mpolyn_leadcoeff_poly( const fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return A->coeffs + 0; } /* mpolyun *******************************************************************/ void fq_nmod_mpoly_to_mpolyn_perm_deflate(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t nctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride); void fq_nmod_mpoly_from_mpolyn_perm_inflate(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t nctx, const slong * perm, const ulong * shift, const ulong * stride); void fq_nmod_mpolyun_init(fq_nmod_mpolyun_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_clear(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyun_is_canonical(const fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_print_pretty(const fq_nmod_mpolyun_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_swap(fq_nmod_mpolyun_t A, fq_nmod_mpolyun_t B); void fq_nmod_mpolyun_zero(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_fit_length(fq_nmod_mpolyun_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_one(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyn_is_nonzero_fq_nmod(const fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyun_is_nonzero_fq_nmod(const fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_scalar_mul_fq_nmod(fq_nmod_mpolyn_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_scalar_mul_fq_nmod(fq_nmod_mpolyun_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_shift_right(fq_nmod_mpolyun_t A, ulong s); void fq_nmod_mpolyun_shift_left(fq_nmod_mpolyun_t A, ulong s); void fq_nmod_mpolyn_mul_poly(fq_nmod_mpolyn_t A, const fq_nmod_mpolyn_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t t); void fq_nmod_mpolyun_mul_poly(fq_nmod_mpolyun_t A, const fq_nmod_mpolyun_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_divexact_poly(fq_nmod_mpolyn_t A, const fq_nmod_mpolyn_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t q, fq_nmod_poly_t r); void fq_nmod_mpolyun_divexact_poly(fq_nmod_mpolyun_t A, const fq_nmod_mpolyun_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_content_poly(fq_nmod_poly_t g, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_content_poly(fq_nmod_poly_t g, fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ctx); slong fq_nmod_mpolyn_lastdeg(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); slong fq_nmod_mpolyun_lastdeg(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_set( fq_nmod_mpolyun_t A, const fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_cvtto_mpolyn( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_cvtto_mpolyun( fq_nmod_mpolyun_t A, const fq_nmod_mpolyu_t B, slong k, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_cvtfrom_mpolyn( fq_nmod_mpoly_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyu_cvtfrom_mpolyun( fq_nmod_mpolyu_t A, fq_nmod_mpolyun_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE n_poly_struct * fq_nmod_mpolyun_leadcoeff_poly( const fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return fq_nmod_mpolyn_leadcoeff_poly(A->coeffs + 0, ctx); } /*** gcd *********************************************************************/ int fq_nmod_next(fq_nmod_t alpha, const fq_nmod_ctx_t fqctx); void fq_nmod_next_not_zero(fq_nmod_t alpha, const fq_nmod_ctx_t fqctx); nmod_gcds_ret_t fq_nmod_mpolyu_gcds_zippel(fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, fq_nmod_mpolyu_t f, slong var, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate, slong * degbound); int fq_nmod_mpolyu_gcdp_zippel_univar(fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyu_gcdp_zippel_univar_no_cofactors(fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyu_gcdp_zippel(fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, slong var, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate); int fq_nmod_mpolyn_gcd_brown_smprime(fq_nmod_mpolyn_t G, fq_nmod_mpolyn_t Abar, fq_nmod_mpolyn_t Bbar, fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyn_gcd_brown_lgprime(fq_nmod_mpolyn_t G, fq_nmod_mpolyn_t Abar, fq_nmod_mpolyn_t Bbar, fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_monomial_evals2_cache(n_fq_polyun_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const fq_nmod_struct * betas, slong m, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_monomial_evals_cache(n_fq_poly_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const fq_nmod_struct * betas, slong start, slong stop, const fq_nmod_mpoly_ctx_t ctx); void n_fq_bpoly_eval_step_sep(n_fq_bpoly_t E, n_fq_polyun_t cur, const n_fq_polyun_t inc, const fq_nmod_mpoly_t A, const fq_nmod_ctx_t ctx); void n_fq_polyun_zip_start(n_fq_polyun_t Z, n_fq_polyun_t H, slong req_images, const fq_nmod_ctx_t ctx); int n_fq_polyu2n_add_zip_must_match(n_fq_polyun_t Z, const n_fq_bpoly_t A, slong cur_length, const fq_nmod_ctx_t ctx); int n_fq_polyun_zip_solve(fq_nmod_mpoly_t A, n_fq_polyun_t Z, n_fq_polyun_t H, n_fq_polyun_t M, const fq_nmod_mpoly_ctx_t ctx); /* gcd_helper_eval_interp ****************************************************/ void nmod_mpolyn_interp_reduce_lg_poly(fq_nmod_poly_t E, const fq_nmod_ctx_t fqctx, const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_lift_lg_poly(slong * lastdeg_, nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx, const fq_nmod_poly_t B, const fq_nmod_ctx_t fqctx); int nmod_mpolyn_interp_crt_lg_poly(slong * lastdeg_, nmod_mpolyn_t F, nmod_mpolyn_t T, n_poly_t modulus, const nmod_mpoly_ctx_t ctx, fq_nmod_poly_t A, const fq_nmod_ctx_t fqctx); void nmod_mpolyn_interp_lift_lg_bpoly(slong * lastdeg_, nmod_mpolyn_t F, const nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx); int nmod_mpolyn_interp_crt_lg_bpoly(slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, n_fq_poly_t modulus, const nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx); void nmod_mpolyn_interp_reduce_lg_mpolyn(fq_nmod_mpolyn_t E, fq_nmod_mpoly_ctx_t ectx, nmod_mpolyn_t A, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_lift_lg_mpolyn(slong * lastdeg, nmod_mpolyn_t A, slong var, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ectx); int nmod_mpolyn_interp_crt_lg_mpolyn(slong * lastdeg_, nmod_mpolyn_t F, nmod_mpolyn_t T, n_poly_t modulus, slong var, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ectx); void nmod_mpolyn_interp_reduce_lg_mpoly(fq_nmod_mpoly_t A, nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ffctx, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_interp_reduce_lg_mpolyu(fq_nmod_mpolyu_t A, nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ffctx, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_lift_lg_mpoly(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx, fq_nmod_mpoly_t Ap, const fq_nmod_mpoly_ctx_t ctxp); void nmod_mpolyun_interp_lift_lg_mpolyu(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t Ap, const fq_nmod_mpoly_ctx_t ctxp); int nmod_mpolyun_interp_crt_lg_mpolyu(slong * lastdeg, nmod_mpolyun_t F, nmod_mpolyun_t T, n_poly_t m, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ffctx); int nmod_mpolyn_interp_mcrt_lg_mpoly(slong * lastdeg_, nmod_mpolyn_t H, const nmod_mpoly_ctx_t smctx, const n_poly_t m, const mp_limb_t * inv_m_eval,fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t lgctx); int nmod_mpolyun_interp_mcrt_lg_mpolyu(slong * lastdeg, nmod_mpolyun_t H, const nmod_mpoly_ctx_t ctx, n_poly_t m, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctxp); void fq_nmod_mpolyn_interp_reduce_sm_poly(fq_nmod_poly_t E, const fq_nmod_mpolyn_t A, const fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_interp_lift_sm_poly(fq_nmod_mpolyn_t A, const fq_nmod_poly_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyn_interp_crt_sm_poly(slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, const fq_nmod_poly_t A, const fq_nmod_poly_t modulus, const fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_interp_lift_sm_bpoly(fq_nmod_mpolyn_t F, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyn_interp_crt_sm_bpoly(slong * lastdeg, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, const n_fq_bpoly_t A, const n_fq_poly_t modulus, n_fq_poly_t alphapow, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_interp_reduce_sm_mpolyn(fq_nmod_mpolyn_t E, fq_nmod_mpolyn_t A, slong var, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_interp_lift_sm_mpolyn(fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyn_interp_mcrt_sm_mpoly(slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpoly_t A, const n_fq_poly_t modulus, n_fq_poly_t alphapow, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyn_interp_crt_sm_mpolyn(slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_mpolyn_t A, slong var, fq_nmod_poly_t modulus, const fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_interp_reduce_lg_poly(fq_nmod_poly_t E, const fq_nmod_mpoly_ctx_t ectx, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyn_interp_lift_lg_poly(slong * lastdeg_, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb); int fq_nmod_mpolyn_interp_crt_lg_poly(slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_poly_t modulus, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyn_interp_lift_lg_bpoly(slong * lastdeg_, fq_nmod_mpolyn_t F, const fq_nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx, const bad_fq_nmod_embed_t emb); int fq_nmod_mpolyn_interp_crt_lg_bpoly(slong * lastdeg, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, n_fq_poly_t modulus, const fq_nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyn_interp_reduce_lg_mpolyn(fq_nmod_mpolyn_t E, const fq_nmod_mpoly_ctx_t ectx, fq_nmod_mpolyn_t A, slong var, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyn_interp_lift_lg_mpolyn(slong * lastdeg_, fq_nmod_mpolyn_t A, slong var, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb); int fq_nmod_mpolyn_interp_crt_lg_mpolyn(slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_poly_t modulus, slong var, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyun_interp_reduce_sm_mpolyu(fq_nmod_mpolyu_t B, fq_nmod_mpolyun_t A, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_interp_lift_sm_mpoly( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyun_interp_lift_sm_mpolyu(fq_nmod_mpolyun_t A, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpolyun_interp_crt_sm_mpolyu(slong * lastdeg, fq_nmod_mpolyun_t F, fq_nmod_mpolyun_t T, fq_nmod_mpolyu_t A, fq_nmod_poly_t modulus, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyn_interp_reduce_lg_mpoly( fq_nmod_mpoly_t A, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyun_interp_reduce_lg_mpolyu(fq_nmod_mpolyu_t A, fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyn_interp_lift_lg_mpoly(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx,fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb); void fq_nmod_mpolyun_interp_lift_lg_mpolyu(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb); int fq_nmod_mpolyun_interp_crt_lg_mpolyu(slong * lastdeg, fq_nmod_mpolyun_t F, fq_nmod_mpolyun_t T, fq_nmod_poly_t m, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb); int fq_nmod_mpolyun_interp_mcrt_lg_mpolyu(slong * lastdeg, fq_nmod_mpolyun_t H, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t m, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ectx, bad_fq_nmod_embed_t emb); /* geobuckets ****************************************************************/ typedef struct fq_nmod_mpoly_geobucket { fq_nmod_mpoly_struct polys[FLINT_BITS/2]; fq_nmod_mpoly_struct temps[FLINT_BITS/2]; slong length; } fq_nmod_mpoly_geobucket_struct; typedef fq_nmod_mpoly_geobucket_struct fq_nmod_mpoly_geobucket_t[1]; void fq_nmod_mpoly_geobucket_init(fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_geobucket_clear(fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_geobucket_empty(fq_nmod_mpoly_t p, fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_geobucket_fit_length(fq_nmod_mpoly_geobucket_t B, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_geobucket_set(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_geobucket_add(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_geobucket_sub(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx); /****************************************************************************** Internal consistency checks ******************************************************************************/ void fq_nmod_mpoly_remainder_strongtest(const fq_nmod_mpoly_t r, const fq_nmod_mpoly_t g, const fq_nmod_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_nmod_mpoly/000077500000000000000000000000001461254215100162655ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mpoly/add.c000066400000000000000000000102271461254215100171630ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" slong _fq_nmod_mpoly_add( mp_limb_t * Acoeffs, ulong * Aexps, mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); nmod_t mod = fq_nmod_ctx_mod(fqctx); slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + N*i, Cexps + N*j, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + N*k, Bexps + N*i, N); _n_fq_set(Acoeffs + d*k, Bcoeffs + d*i, d); i++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + N*k, Bexps + N*i, N); _n_fq_add(Acoeffs + d*k, Bcoeffs + d*i, Ccoeffs + d*j, d, mod); k -= _n_fq_is_zero(Acoeffs + d*k, d); i++; j++; } else { mpoly_monomial_set(Aexps + N*k, Cexps + N*j, N); _n_fq_set(Acoeffs + d*k, Ccoeffs + d*j, d); j++; } k++; } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); _n_fq_set(Acoeffs + d*k, Bcoeffs + d*i, d); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); _n_fq_set(Acoeffs + d*k, Ccoeffs + d*j, d); j++; k++; } return k; } void fq_nmod_mpoly_add( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx) { slong Alen; ulong * Bexps = B->exps, * Cexps = C->exps; flint_bitcnt_t Abits = FLINT_MAX(B->bits, C->bits); slong N = mpoly_words_per_exp(Abits, ctx->minfo); ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_set(A, C, ctx); return; } else if (fq_nmod_mpoly_is_zero(C, ctx)) { fq_nmod_mpoly_set(A, B, ctx); return; } TMP_START; cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits > C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_fit_length_reset_bits(T, B->length + C->length, Abits, ctx); Alen = _fq_nmod_mpoly_add(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->fqctx); fq_nmod_mpoly_swap(T, A, ctx); fq_nmod_mpoly_clear(T, ctx); } else { fq_nmod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); Alen = _fq_nmod_mpoly_add(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->fqctx); } _fq_nmod_mpoly_set_length(A, Alen, ctx); if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/add_fq_nmod.c000066400000000000000000000067451461254215100207000ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_add_n_fq( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mp_limb_t * c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong Blen = B->length; if (_n_fq_is_zero(c, d)) { fq_nmod_mpoly_set(A, B, ctx); return; } if (Blen < 1) { fq_nmod_mpoly_set_n_fq(A, c, ctx); return; } if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*(Blen - 1)); mpoly_copy_monomials(A->exps, B->exps, Blen, N); _fq_nmod_mpoly_set_length(A, B->length, ctx); } n_fq_add(A->coeffs + d*(Blen - 1), B->coeffs + d*(Blen - 1), c, ctx->fqctx); if (_n_fq_is_zero(A->coeffs + d*(Blen - 1), d)) _fq_nmod_mpoly_set_length(A, Blen - 1, ctx); } else { if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, Blen + 1, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*Blen); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } else { fq_nmod_mpoly_fit_length(A, Blen + 1, ctx); } mpoly_monomial_zero(A->exps + N*Blen, N); _n_fq_set(A->coeffs + d*Blen, c, d); _fq_nmod_mpoly_set_length(A, Blen + 1, ctx); } } void fq_nmod_mpoly_add_fq_nmod( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong Blen = B->length; if (fq_nmod_is_zero(c, ctx->fqctx)) { fq_nmod_mpoly_set(A, B, ctx); return; } if (Blen < 1) { fq_nmod_mpoly_set_fq_nmod(A, c, ctx); return; } if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*(Blen - 1)); mpoly_copy_monomials(A->exps, B->exps, Blen, N); _fq_nmod_mpoly_set_length(A, B->length, ctx); } n_fq_add_fq_nmod(A->coeffs + d*(Blen - 1), B->coeffs + d*(Blen - 1), c, ctx->fqctx); if (_n_fq_is_zero(A->coeffs + d*(Blen - 1), d)) _fq_nmod_mpoly_set_length(A, Blen - 1, ctx); } else { if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, Blen + 1, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*Blen); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } else { fq_nmod_mpoly_fit_length(A, Blen + 1, ctx); } mpoly_monomial_zero(A->exps + N*Blen, N); n_fq_set_fq_nmod(A->coeffs + d*Blen, c, ctx->fqctx); _fq_nmod_mpoly_set_length(A, Blen + 1, ctx); } } flint-3.1.3/src/fq_nmod_mpoly/cmp.c000066400000000000000000000022761461254215100172170ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_cmp( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i; slong length = A->length; const mp_limb_t * Acoeffs = A->coeffs; const mp_limb_t * Bcoeffs = B->coeffs; int cmp; if (A->length != B->length) return A->length < B->length ? -1 : 1; if (length < 1) return 0; cmp = mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, length, ctx->minfo); if (cmp != 0) return cmp; for (i = 0; i < d*length; i++) { if (Acoeffs[i] != Bcoeffs[i]) return Acoeffs[i] < Bcoeffs[i] ? -1 : 1; } return 0; } flint-3.1.3/src/fq_nmod_mpoly/combine_like_terms.c000066400000000000000000000031561461254215100222700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* assuming that the exponents are valid and sorted, put the polynomial in canonical form i.e. 2*x^e + 3*x^e -> 5x^e 2*x^e - 2*x^e -> 0 */ void fq_nmod_mpoly_combine_like_terms( fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong in, out; out = -1; for (in = 0; in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= 0 && mpoly_monomial_equal(A->exps + N*out, A->exps + N*in, N)) { n_fq_add(A->coeffs + d*out, A->coeffs + d*out, A->coeffs + d*in, ctx-> fqctx); } else { if (out < 0 || !_n_fq_is_zero(A->coeffs + d*out, d)) out++; if (out != in) { mpoly_monomial_set(A->exps + N*out, A->exps + N*in, N); _n_fq_swap(A->coeffs + d*out, A->coeffs + d*in, d); } } } if (out < WORD(0) || !_n_fq_is_zero(A->coeffs + d*out, d)) out++; A->length = out; } flint-3.1.3/src/fq_nmod_mpoly/compose_fq_nmod_mpoly.c000066400000000000000000000037301461254215100230240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fmpz_mat.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* evaluate B(xbar) at xbar = C */ int fq_nmod_mpoly_compose_fq_nmod_mpoly(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, fq_nmod_mpoly_struct * const * C, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC) { slong i; fmpz_mat_t M; FLINT_ASSERT(A != B); if (B->length == 0) { fq_nmod_mpoly_zero(A, ctxAC); return 1; } fmpz_mat_init(M, ctxAC->minfo->nfields + 1, ctxB->minfo->nfields); fmpz_mat_zero(M); for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) goto matrix_no_good; if (C[i]->length == 0) { mpoly_compose_mat_fill_column(M, NULL, 0, i, ctxB->minfo, ctxAC->minfo); } else { if (!_n_fq_is_one(C[i]->coeffs, fq_nmod_ctx_degree(ctxAC->fqctx))) goto matrix_no_good; mpoly_compose_mat_fill_column(M, C[i]->exps, C[i]->bits, i, ctxB->minfo, ctxAC->minfo); } } _fq_nmod_mpoly_compose_mat(A, B, M, ctxB, ctxAC); fmpz_mat_clear(M); return 1; matrix_no_good: fmpz_mat_clear(M); for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) { return fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(A, B, C, ctxB, ctxAC); } } return fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(A, B, C, ctxB, ctxAC); } flint-3.1.3/src/fq_nmod_mpoly/compose_fq_nmod_mpoly_gen.c000066400000000000000000000024561461254215100236610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* evaluate B(x_1,...,x_n) at x_i = y_c[i], y_j are vars of ctxAC */ void fq_nmod_mpoly_compose_fq_nmod_mpoly_gen(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const slong * c, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC) { fmpz_mat_t M; if (B->length == 0) { fq_nmod_mpoly_zero(A, ctxAC); return; } fmpz_mat_init(M, ctxAC->minfo->nfields + 1, ctxB->minfo->nfields); mpoly_compose_mat_gen(M, c, ctxB->minfo, ctxAC->minfo); if (A == B) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctxAC); _fq_nmod_mpoly_compose_mat(T, B, M, ctxB, ctxAC); fq_nmod_mpoly_swap(A, T, ctxAC); fq_nmod_mpoly_clear(T, ctxAC); } else { _fq_nmod_mpoly_compose_mat(A, B, M, ctxB, ctxAC); } fmpz_mat_clear(M); return; } flint-3.1.3/src/fq_nmod_mpoly/compose_fq_nmod_mpoly_geobucket.c000066400000000000000000000037171461254215100250610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* evaluate B(xbar) at xbar = C */ int fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, fq_nmod_mpoly_struct * const * C, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC) { slong d = fq_nmod_ctx_degree(ctxAC->fqctx); int success = 1; slong i, j; slong Blen = B->length; const ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fq_nmod_mpoly_t U, V, W; fq_nmod_mpoly_geobucket_t T; fmpz * e; fq_nmod_mpoly_init(U, ctxAC); fq_nmod_mpoly_init(V, ctxAC); fq_nmod_mpoly_init(W, ctxAC); fq_nmod_mpoly_geobucket_init(T, ctxAC); e = _fmpz_vec_init(ctxB->minfo->nvars); for (i = 0; success && i < Blen; i++) { fq_nmod_mpoly_set_n_fq(U, B->coeffs + d*i, ctxAC); mpoly_get_monomial_ffmpz(e, Bexp + BN*i, Bbits, ctxB->minfo); for (j = 0; j < ctxB->minfo->nvars; j++) { success = success && fq_nmod_mpoly_pow_fmpz(V, C[j], e + j, ctxAC); fq_nmod_mpoly_mul(W, U, V, ctxAC); fq_nmod_mpoly_swap(U, W, ctxAC); } fq_nmod_mpoly_geobucket_add(T, U, ctxAC); } if (success) fq_nmod_mpoly_geobucket_empty(A, T, ctxAC); fq_nmod_mpoly_clear(U, ctxAC); fq_nmod_mpoly_clear(V, ctxAC); fq_nmod_mpoly_clear(W, ctxAC); fq_nmod_mpoly_geobucket_clear(T, ctxAC); _fmpz_vec_clear(e, ctxB->minfo->nvars); return success; } flint-3.1.3/src/fq_nmod_mpoly/compose_fq_nmod_mpoly_horner.c000066400000000000000000000255151461254215100244060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" typedef struct { slong f; slong r; slong v_var; fmpz_t v_exp; /* will be managed as stack grows / shrinks */ int ret; } stack_entry_struct; typedef stack_entry_struct stack_entry_t[1]; /* A = A * X^pow */ static int _fq_nmod_mpoly_pmul(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t X, const fmpz_t pow, fq_nmod_mpoly_t T, const fq_nmod_mpoly_ctx_t ctx) { ulong p; FLINT_ASSERT(fmpz_sgn(pow) > 0); if (!fmpz_fits_si(pow)) { if (!fq_nmod_mpoly_pow_fmpz(T, X, pow, ctx)) { fq_nmod_mpoly_zero(A, ctx); return 0; } fq_nmod_mpoly_mul(A, A, T, ctx); return 1; } p = fmpz_get_ui(pow); if (X->length <= WORD(2) || A->length/p < X->length) { if (!fq_nmod_mpoly_pow_ui(T, X, p, ctx)) { fq_nmod_mpoly_zero(A, ctx); return 0; } fq_nmod_mpoly_mul(A, A, T, ctx); } else { while (p >= 1) { fq_nmod_mpoly_mul(T, A, X, ctx); fq_nmod_mpoly_swap(A, T, ctx); p--; } } return 1; } /* evaluate B(xbar) at xbar = C, */ int fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, fq_nmod_mpoly_struct * const * C, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC) { int ret, success = 1; slong d = fq_nmod_ctx_degree(ctxB->fqctx); slong nvars = ctxB->minfo->nvars; slong i, j, k, cur, next, f, r, f_prev, r_prev, v; slong sp, rp; stack_entry_struct * stack; fq_nmod_mpoly_struct * regs; fq_nmod_mpoly_t temp; slong * rtypes; ulong totalcounts, maxcounts; ulong * counts; slong Blen = B->length; slong * Blist; const mp_limb_t * Bcoeffs = B->coeffs; ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fmpz * Buexp; fmpz * mdegs; fmpz_t score, tz; TMP_INIT; if (Blen < 1) { fq_nmod_mpoly_zero(A, ctxAC); return 1; } if (nvars < 1) { FLINT_ASSERT(Blen == 1); fq_nmod_mpoly_set_n_fq(A, B->coeffs + 0, ctxAC); return 1; } FLINT_ASSERT(A != B); FLINT_ASSERT(Blen > 0); TMP_START; fmpz_init(score); fmpz_init(tz); /* unpack B exponents */ Buexp = _fmpz_vec_init(nvars*Blen); for (i = 0; i < Blen; i++) mpoly_get_monomial_ffmpz(Buexp + nvars*i, Bexp + BN*i, Bbits, ctxB->minfo); counts = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); mdegs = _fmpz_vec_init(nvars); /* stack */ sp = -WORD(1); /* start with empty stack */ stack = (stack_entry_struct *) TMP_ALLOC(nvars*(Blen + 1)*sizeof(stack_entry_struct)); Blist = (slong *) TMP_ALLOC(Blen*sizeof(slong)); /* registers of polynomials */ rp = 0; rtypes = (slong *) TMP_ALLOC((nvars + 1)*sizeof(slong)); regs = (fq_nmod_mpoly_struct *) TMP_ALLOC(nvars*sizeof(fq_nmod_mpoly_struct)); for (i = 0; i < nvars; i++) fq_nmod_mpoly_init(regs + i, ctxAC); fq_nmod_mpoly_init(temp, ctxAC); /* polynomials will be stored as link lists */ for (i = 0; i + 1 < Blen; i++) Blist[i] = i + 1; Blist[i] = -WORD(1); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 0; (stack + sp)->f = 0; HornerForm: f = (stack + sp)->f; FLINT_ASSERT(f != -WORD(1)); /* f is not supposed to be zero */ /* obtain a count of the number of terms containing each variable */ for (i = 0; i < nvars; i++) { counts[i] = 0; fmpz_set_si(mdegs + i, -WORD(1)); } for (j = f; j != -WORD(1); j = Blist[j]) { for (i = 0; i < nvars; i++) { if (!fmpz_is_zero(Buexp + nvars*j + i )) { counts[i]++; if (fmpz_sgn(mdegs + i) < 0 || fmpz_cmp(mdegs + i, Buexp + nvars*j + i) > 0) { fmpz_set(mdegs + i, Buexp + nvars*j + i); } } } } totalcounts = 0; maxcounts = 0; v = -WORD(1); for (i = 0; i < nvars; i++) { maxcounts = FLINT_MAX(maxcounts, counts[i]); totalcounts += counts[i]; if (counts[i] != 0) v = i; } /* handle simple cases */ if (totalcounts == 0) { FLINT_ASSERT(Blist[f] == -WORD(1)); /* f should have had only one term */ rtypes[rp] = f; goto HornerFormReturn; } else if (totalcounts == 1) { FLINT_ASSERT(!fmpz_is_zero(Buexp + nvars*f + v)); /* this term should not be a scalar */ if (!fq_nmod_mpoly_pow_fmpz(regs + rp, C[v], Buexp + nvars*f + v, ctxAC)) { success = 0; } fq_nmod_mpoly_scalar_mul_n_fq(regs + rp, regs + rp, Bcoeffs + d*f, ctxAC); if (Blist[f] != -WORD(1)) /* if f has a second term */ { /* this term should be a scalar */ FLINT_ASSERT(fmpz_is_zero(Buexp + nvars*Blist[f] + v)); fq_nmod_mpoly_add_n_fq(regs + rp, regs + rp, Bcoeffs + d*Blist[f], ctxAC); } rtypes[rp] = -WORD(1); goto HornerFormReturn; } /* pick best power to pull out */ k = 0; if (maxcounts == 1) { fmpz_set_si(score, -WORD(1)); for (i = 0; i < nvars; i++) { if (counts[i] == 1 && (fmpz_sgn(score) < 0 || fmpz_cmp(mdegs + i, score) < 0)) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_set(score, mdegs + i); k = i; } } } else { fmpz_zero(score); for (i = 0; i < nvars; i++) { if (counts[i] > 1) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_mul_ui(tz, mdegs + i, counts[i] - 1); if (fmpz_cmp(tz, score) > 0) { fmpz_swap(score, tz); k = i; } } } } /* set variable power v */ (stack + sp)->v_var = k; fmpz_set((stack + sp)->v_exp, mdegs + k); /* scan f and split into q and v with f = q*v + r then set f = q */ r = -WORD(1); cur = f; f_prev = -WORD(1); r_prev = -WORD(1); while (cur != -WORD(1)) { next = Blist[cur]; if (fmpz_is_zero(Buexp + nvars*cur + k)) { if (f_prev == -WORD(1)) f = Blist[cur]; else Blist[f_prev] = Blist[cur]; if (r_prev == -WORD(1)) r = cur; else Blist[r_prev] = cur; Blist[cur] = -WORD(1); r_prev = cur; } else { /* mdegs[k] should be minimum non zero exponent */ fmpz_sub(Buexp + nvars*cur + k, Buexp + nvars*cur + k, mdegs + k); FLINT_ASSERT(fmpz_sgn(Buexp + nvars*cur + k) >= 0); f_prev = cur; } cur = next; } (stack + sp)->r = r; /* convert the quotient */ sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 1; (stack + sp)->f = f; goto HornerForm; HornerForm1: /* convert the remainder */ r = (stack + sp)->r; if (r != -WORD(1)) { /* remainder is non zero */ rp++; FLINT_ASSERT(0 <= rp && rp <= nvars); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 2; (stack + sp)->f = r; goto HornerForm; HornerForm2: if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] == -WORD(1)) { /* both quotient and remainder are polynomials */ if (!_fq_nmod_mpoly_pmul(regs + rp - 1, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } fq_nmod_mpoly_add(temp, regs + rp - 1, regs + rp, ctxAC); fq_nmod_mpoly_swap(temp, regs + rp - 1, ctxAC); } else if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] != -WORD(1)) { /* quotient is a polynomial, remainder is a scalar */ if (!_fq_nmod_mpoly_pmul(regs + rp - 1, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } fq_nmod_mpoly_add_n_fq(regs + rp - 1, regs + rp - 1, Bcoeffs + d*rtypes[rp], ctxAC); } else if (rtypes[rp - 1] != -WORD(1) && rtypes[rp] == -WORD(1)) { /* quotient is a scalar, remainder is a polynomial */ if (!fq_nmod_mpoly_pow_fmpz(temp, C[(stack + sp)->v_var], (stack + sp)->v_exp, ctxAC)) { success = 0; } fq_nmod_mpoly_scalar_mul_n_fq(temp, temp, Bcoeffs + d*rtypes[rp - 1], ctxAC); fq_nmod_mpoly_add(regs + rp - 1, temp, regs + rp, ctxAC); } else { /* quotient is a scalar, remainder is a scalar */ FLINT_ASSERT(0); /* this should have been handled by simple case */ } rp--; FLINT_ASSERT(0 <= rp && rp <= nvars); } else { /* remainder is zero */ FLINT_ASSERT(rtypes[rp] == -WORD(1)); /* quotient is a scalar */ /* quotient is a polynomial */ if (!_fq_nmod_mpoly_pmul(regs + rp, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } } rtypes[rp] = -WORD(1); HornerFormReturn: if (!success) { while (sp >= 0) { fmpz_clear((stack + sp)->v_exp); sp--; } goto cleanup; } ret = (stack + sp)->ret; fmpz_clear((stack + sp)->v_exp); sp--; if (ret == 1) goto HornerForm1; if (ret == 2) goto HornerForm2; FLINT_ASSERT(rp == 0); FLINT_ASSERT(sp == -WORD(1)); if (rtypes[rp] == -WORD(1)) fq_nmod_mpoly_swap(A, regs + rp, ctxAC); else fq_nmod_mpoly_set_n_fq(A, Bcoeffs + d*rtypes[rp], ctxAC); cleanup: for (i = 0; i < nvars; i++) fq_nmod_mpoly_clear(regs + i, ctxAC); fq_nmod_mpoly_clear(temp, ctxAC); fmpz_clear(score); fmpz_clear(tz); _fmpz_vec_clear(mdegs, nvars); _fmpz_vec_clear(Buexp, nvars*Blen); TMP_END; return success; } flint-3.1.3/src/fq_nmod_mpoly/compose_fq_nmod_poly.c000066400000000000000000000155421461254215100226530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" int _fq_nmod_mpoly_compose_fq_nmod_poly_sp(fq_nmod_poly_t A, const fq_nmod_mpoly_t B, fq_nmod_poly_struct * const * C, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success = 1; flint_bitcnt_t bits = B->bits; slong i, j, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, shift, off; slong Blen = B->length; const mp_limb_t * Bcoeff = B->coeffs; ulong * Bexp = B->exps; slong * degrees; slong * offs; ulong * masks; fq_nmod_poly_struct * powers; fq_nmod_poly_t t, t2; TMP_INIT; FLINT_ASSERT(Blen != 0); TMP_START; degrees = TMP_ARRAY_ALLOC(nvars, slong); mpoly_degrees_si(degrees, Bexp, Blen, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_ff_poly_pow_ui_is_not_feasible(C[i]->length, degrees[i])) { success = 0; goto cleanup_degrees; } entries += FLINT_BIT_COUNT(degrees[i]); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fq_nmod_poly_struct); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = FLINT_BIT_COUNT(degrees[i]); mpoly_gen_offset_shift_sp(&off, &shift, i, bits, ctx->minfo); for (j = 0; j < varibits; j++) { offs[k] = off; masks[k] = UWORD(1) << (shift + j); fq_nmod_poly_init(powers + k, ctx->fqctx); if (j == 0) fq_nmod_poly_set(powers + k, C[i], ctx->fqctx); else fq_nmod_poly_mul(powers + k, powers + k - 1, powers + k - 1, ctx->fqctx); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fq_nmod_poly_zero(A, ctx->fqctx); fq_nmod_poly_init(t, ctx->fqctx); fq_nmod_poly_init(t2, ctx->fqctx); for (i = 0; i < Blen; i++) { fq_nmod_poly_fit_length(t, 1, ctx->fqctx); n_fq_get_fq_nmod(t->coeffs + 0, Bcoeff + d*i, ctx->fqctx); t->length = 1; for (k = 0; k < k_len; k++) { if ((Bexp[N*i + offs[k]] & masks[k]) != WORD(0)) { fq_nmod_poly_mul(t2, t, powers + k, ctx->fqctx); fq_nmod_poly_swap(t, t2, ctx->fqctx); } } fq_nmod_poly_add(A, A, t, ctx->fqctx); } fq_nmod_poly_clear(t, ctx->fqctx); fq_nmod_poly_clear(t2, ctx->fqctx); for (k = 0; k < k_len; k++) fq_nmod_poly_clear(powers + k, ctx->fqctx); cleanup_degrees: TMP_END; return success; } int _fq_nmod_mpoly_compose_fq_nmod_poly_mp(fq_nmod_poly_t A, const fq_nmod_mpoly_t B, fq_nmod_poly_struct * const * C, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success = 1; flint_bitcnt_t bits = B->bits; ulong l; slong i, k, N, nvars = ctx->minfo->nvars; slong entries, k_len, off; slong Blen = B->length; const mp_limb_t * Bcoeff = B->coeffs; ulong * Bexp = B->exps; fmpz * degrees; slong * offs; ulong * masks; flint_bitcnt_t * bitcounts; fq_nmod_poly_struct * powers; fq_nmod_poly_t t, t2; TMP_INIT; FLINT_ASSERT(Blen != 0); TMP_START; bitcounts = TMP_ARRAY_ALLOC(nvars, flint_bitcnt_t); degrees = TMP_ARRAY_ALLOC(nvars, fmpz); for (i = 0; i < nvars; i++) fmpz_init(degrees + i); mpoly_degrees_ffmpz(degrees, Bexp, Blen, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_ff_poly_pow_fmpz_is_not_feasible(C[i]->length, degrees + i)) { success = 0; goto cleanup_degrees; } bitcounts[i] = fmpz_bits(degrees + i); entries += bitcounts[i]; } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, fq_nmod_poly_struct); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the variables */ k = 0; for (i = 0; i < nvars; i++) { off = mpoly_gen_offset_mp(i, bits, ctx->minfo); for (l = 0; l < bitcounts[i]; l++) { offs[k] = off + (l/FLINT_BITS); masks[k] = UWORD(1) << (l%FLINT_BITS); fq_nmod_poly_init(powers + k, ctx->fqctx); if (l == 0) fq_nmod_poly_set(powers + k, C[i], ctx->fqctx); else fq_nmod_poly_mul(powers + k, powers + k - 1, powers + k - 1, ctx->fqctx); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ fq_nmod_poly_zero(A, ctx->fqctx); fq_nmod_poly_init(t, ctx->fqctx); fq_nmod_poly_init(t2, ctx->fqctx); for (i = 0; i < Blen; i++) { fq_nmod_poly_fit_length(t, 1, ctx->fqctx); n_fq_get_fq_nmod(t->coeffs + 0, Bcoeff + d*i, ctx->fqctx); t->length = 1; for (k = 0; k < k_len; k++) { if ((Bexp[N*i + offs[k]] & masks[k]) != WORD(0)) { fq_nmod_poly_mul(t2, t, powers + k, ctx->fqctx); fq_nmod_poly_swap(t, t2, ctx->fqctx); } } fq_nmod_poly_add(A, A, t, ctx->fqctx); } fq_nmod_poly_clear(t, ctx->fqctx); fq_nmod_poly_clear(t2, ctx->fqctx); for (k = 0; k < k_len; k++) fq_nmod_poly_clear(powers + k, ctx->fqctx); cleanup_degrees: for (i = 0; i < nvars; i++) fmpz_clear(degrees + i); TMP_END; return success; } int fq_nmod_mpoly_compose_fq_nmod_poly(fq_nmod_poly_t A, const fq_nmod_mpoly_t B, fq_nmod_poly_struct * const * C, const fq_nmod_mpoly_ctx_t ctx) { if (B->length == 0) { fq_nmod_poly_zero(A, ctx->fqctx); return 1; } if (B->bits <= FLINT_BITS) { return _fq_nmod_mpoly_compose_fq_nmod_poly_sp(A, B, C, ctx); } else { return _fq_nmod_mpoly_compose_fq_nmod_poly_mp(A, B, C, ctx); } } flint-3.1.3/src/fq_nmod_mpoly/compose_mat.c000066400000000000000000000044341461254215100207440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* essentially exps(A) = M*exps(B) */ void _fq_nmod_mpoly_compose_mat( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz_mat_t M, const fq_nmod_mpoly_ctx_t ctxB, const fq_nmod_mpoly_ctx_t ctxAC) { slong d = fq_nmod_ctx_degree(ctxAC->fqctx); slong i; fmpz * u, * v; flint_bitcnt_t vbits; slong Blen = B->length; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); const ulong * Bexp = B->exps; const mp_limb_t * Bcoeffs = B->coeffs; slong AN; FLINT_ASSERT(A != B); FLINT_ASSERT(fmpz_mat_nrows(M) == ctxAC->minfo->nfields + 1); FLINT_ASSERT(fmpz_mat_ncols(M) == ctxB->minfo->nfields); u = _fmpz_vec_init(ctxB->minfo->nfields); v = _fmpz_vec_init(ctxAC->minfo->nfields + 1); fq_nmod_mpoly_fit_length_reset_bits(A, Blen, MPOLY_MIN_BITS, ctxAC); A->length = 0; for (i = 0; i < Blen; i++) { mpoly_unpack_vec_fmpz(u, Bexp + BN*i, Bbits, ctxB->minfo->nfields, 1); fmpz_mat_mul_fmpz_vec(v, M, u, fmpz_mat_ncols(M)); if (!fmpz_is_zero(v + ctxAC->minfo->nfields)) continue; vbits = _fmpz_vec_max_bits(v, ctxAC->minfo->nfields); FLINT_ASSERT(vbits >= 0); vbits = mpoly_fix_bits(vbits + 1, ctxAC->minfo); fq_nmod_mpoly_fit_length_fit_bits(A, A->length + 1, vbits, ctxAC); _n_fq_set(A->coeffs + d*A->length, Bcoeffs + d*i, d); AN = mpoly_words_per_exp(A->bits, ctxAC->minfo); mpoly_pack_vec_fmpz(A->exps + AN*A->length, v, A->bits, ctxAC->minfo->nfields, 1); A->length++; } _fmpz_vec_clear(u, ctxB->minfo->nfields); _fmpz_vec_clear(v, ctxAC->minfo->nfields + 1); fq_nmod_mpoly_sort_terms(A, ctxAC); fq_nmod_mpoly_combine_like_terms(A, ctxAC); return; } flint-3.1.3/src/fq_nmod_mpoly/content_vars.c000066400000000000000000000130051461254215100211350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" #include "fq_nmod_mpoly_factor.h" /* content wrt gen(0), ..., gen(num_vars-1) successful answer will be returned with g->bits == A->bits */ int fq_nmod_mpolyl_content( fq_nmod_mpoly_t g, const fq_nmod_mpoly_t A, slong num_vars, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; slong i, j, off, shift; ulong old_shift, new_shift; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; slong Alen = A->length; fq_nmod_mpoly_struct * v; slong vlen, valloc; FLINT_ASSERT(g != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); i = 0; old_shift = (Aexps + N*i)[off] >> shift; valloc = 4; v = FLINT_ARRAY_ALLOC(valloc, fq_nmod_mpoly_struct); vlen = 0; v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + d*i; v[vlen].exps = Aexps + N*i; v[vlen].length = i; v[vlen].coeffs_alloc = d*v[vlen].length; v[vlen].exps_alloc = N*v[vlen].length; vlen++; for (i = 1; i < Alen; old_shift = new_shift, i++) { new_shift = (Aexps + N*i)[off] >> shift; if (new_shift != old_shift) goto new_one; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto new_one; continue; new_one: v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].coeffs_alloc = d*v[vlen - 1].length; v[vlen - 1].exps_alloc = N*v[vlen - 1].length; if (vlen + 1 > valloc) { valloc += 2 + valloc/2; v = (fq_nmod_mpoly_struct *) flint_realloc(v, valloc* sizeof(fq_nmod_mpoly_struct)); } v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + d*i; v[vlen].exps = Aexps + N*i; v[vlen].length = i; vlen++; } v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].coeffs_alloc = d*v[vlen - 1].length; v[vlen - 1].exps_alloc = N*v[vlen - 1].length; success = _fq_nmod_mpoly_vec_content_mpoly(g, v, vlen, ctx); if (success) { /* remove gen(0) ... gen(num_vars-1) from the answer */ ulong * gexps; ulong mask; fq_nmod_mpoly_repack_bits_inplace(g, A->bits, ctx); gexps = g->exps; mask = (shift > 0) ? ((-UWORD(1)) >> (FLINT_BITS - shift)) : 0; for (i = 0; i < g->length; i++) { (gexps + N*i)[off] &= mask; for (j = off + 1; j < N; j++) (gexps + N*i)[j] = 0; } } flint_free(v); return success; } int fq_nmod_mpoly_content_vars( fq_nmod_mpoly_t g, const fq_nmod_mpoly_t A, slong * vars, slong num_vars, const fq_nmod_mpoly_ctx_t ctx) { int success; slong i, j, k; fq_nmod_mpolyv_t v, w; fq_nmod_mpoly_univar_t u; if (num_vars < 1) { fq_nmod_mpoly_set(g, A, ctx); return 1; } for (i = 0; i < num_vars; i++) { if (vars[i] >= (ulong) ctx->minfo->nvars) flint_throw(FLINT_ERROR, "fq_nmod_mpoly_content_vars: variable out of range"); } if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_mpoly_zero(g, ctx); return 1; } if (A->bits <= FLINT_BITS && ctx->minfo->ord == ORD_LEX && num_vars < ctx->minfo->nvars) { for (i = 0; i < num_vars; i++) if (vars[i] != i) goto do_general; if (g == A) { fq_nmod_mpoly_t t; fq_nmod_mpoly_init(t, ctx); success = fq_nmod_mpolyl_content(t, A, num_vars, ctx); fq_nmod_mpoly_swap(g, t, ctx); fq_nmod_mpoly_clear(t, ctx); return success; } return fq_nmod_mpolyl_content(g, A, num_vars, ctx); } do_general: fq_nmod_mpolyv_init(v, ctx); fq_nmod_mpolyv_init(w, ctx); fq_nmod_mpoly_univar_init(u, ctx); i = 0; fq_nmod_mpoly_to_univar(u, A, vars[i], ctx); fq_nmod_mpolyv_fit_length(v, u->length, ctx); v->length = u->length; for (j = 0; j < u->length; j++) fq_nmod_mpoly_swap(v->coeffs + j, u->coeffs + j, ctx); for (i = 1; i < num_vars; i++) { w->length = 0; for (k = 0; k < v->length; k++) { fq_nmod_mpoly_to_univar(u, v->coeffs + k, vars[i], ctx); fq_nmod_mpolyv_fit_length(w, w->length + u->length, ctx); for (j = 0; j < u->length; j++) { fq_nmod_mpoly_swap(w->coeffs + w->length, u->coeffs + j, ctx); w->length++; } } fq_nmod_mpolyv_swap(v, w, ctx); } fq_nmod_mpoly_univar_clear(u, ctx); fq_nmod_mpolyv_clear(w, ctx); success = _fq_nmod_mpoly_vec_content_mpoly(g, v->coeffs, v->length, ctx); fq_nmod_mpolyv_clear(v, ctx); return success; } flint-3.1.3/src/fq_nmod_mpoly/ctx_change_modulus.c000066400000000000000000000011611461254215100223030ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_ctx_change_modulus(fq_nmod_mpoly_ctx_t ctx, slong deg) { ulong p = ctx->fqctx->mod.n; fq_nmod_ctx_clear(ctx->fqctx); fq_nmod_ctx_init_ui(ctx->fqctx, p, deg, "#"); } flint-3.1.3/src/fq_nmod_mpoly/ctx_clear.c000066400000000000000000000010761461254215100204010ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_ctx_clear(fq_nmod_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); fq_nmod_ctx_clear(ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/ctx_init.c000066400000000000000000000017011461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_ctx_init_deg(fq_nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t p, slong deg) { mpoly_ctx_init(ctx->minfo, nvars, ord); fq_nmod_ctx_init_ui(ctx->fqctx, p, deg, "#"); } void fq_nmod_mpoly_ctx_init(fq_nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fq_nmod_ctx_t fqctx) { mpoly_ctx_init(ctx->minfo, nvars, ord); fq_nmod_ctx_init_modulus(ctx->fqctx, fqctx->modulus, fqctx->var); } flint-3.1.3/src/fq_nmod_mpoly/ctx_init_rand.c000066400000000000000000000024611461254215100212610ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_ctx_init_rand(fq_nmod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, flint_bitcnt_t p_bits_bound, slong deg_bound) { ulong p; slong d; flint_bitcnt_t p_bits; nmod_poly_t poly; d = 1 + n_randint(state, deg_bound); p_bits = 1 + n_randint(state, p_bits_bound); if (p_bits >= FLINT_BITS) { p = n_randlimb(state); p |= UWORD(1) << (FLINT_BITS - 1); p &= ~(UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX)); } else { p = n_randtest_bits(state, p_bits); } p = n_nextprime(p, 1); nmod_poly_init2(poly, p, d + 1); nmod_poly_randtest_monic_irreducible(poly, state, d + 1); fq_nmod_ctx_init_modulus(ctx->fqctx, poly, "#"); nmod_poly_clear(poly); mpoly_ctx_init_rand(ctx->minfo, state, max_nvars); } flint-3.1.3/src/fq_nmod_mpoly/deflate.c000066400000000000000000000032511461254215100200360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_deflate( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong bits = B->bits; slong NA = mpoly_words_per_exp(bits, ctx->minfo); if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_zero(A, ctx); return; } if (A == B) { slong new_alloc = NA*A->length; ulong * texps = flint_malloc(new_alloc*sizeof(ulong)); mpoly_monomials_deflate(texps, bits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = bits; A->exps_alloc = new_alloc; } else { fq_nmod_mpoly_fit_length_reset_bits(A, B->length, bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*B->length); mpoly_monomials_deflate(A->exps, bits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _fq_nmod_mpoly_set_length(A, B->length, ctx); } if (ctx->minfo->ord != ORD_LEX) fq_nmod_mpoly_sort_terms(A, ctx); } flint-3.1.3/src/fq_nmod_mpoly/deflation.c000066400000000000000000000013231461254215100203750ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_deflation(fmpz * shift, fmpz * stride, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { mpoly_monomials_deflation(shift, stride, A->exps, A->bits, A->length, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/degrees.c000066400000000000000000000043151461254215100200520ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_degrees_fit_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_degrees_fit_si(A->exps, A->length, A->bits, ctx->minfo); } void fq_nmod_mpoly_degrees_fmpz(fmpz ** degs, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { mpoly_degrees_pfmpz(degs, A->exps, A->length, A->bits, ctx->minfo); } void fq_nmod_mpoly_degrees_si(slong * degs, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { mpoly_degrees_si(degs, A->exps, A->length, A->bits, ctx->minfo); } void fq_nmod_mpoly_degree_fmpz(fmpz_t deg, const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } slong fq_nmod_mpoly_degree_si(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } int fq_nmod_mpoly_total_degree_fits_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return mpoly_total_degree_fits_si(A->exps, A->length, A->bits, ctx->minfo); } void fq_nmod_mpoly_total_degree_fmpz(fmpz_t td, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { mpoly_total_degree_fmpz(td, A->exps, A->length, A->bits, ctx->minfo); } slong fq_nmod_mpoly_total_degree_si(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return mpoly_total_degree_si(A->exps, A->length, A->bits, ctx->minfo); } void fq_nmod_mpoly_used_vars(int * used, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < ctx->minfo->nvars; i++) used[i] = 0; mpoly_used_vars_or(used, A->exps, A->length, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/derivative.c000066400000000000000000000066201461254215100205770ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" static slong _fq_nmod_mpoly_derivative( mp_limb_t * Acoeff, ulong * Aexp, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, flint_bitcnt_t bits, slong N, slong offset, slong shift, ulong * oneexp, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); nmod_t mod = fq_nmod_ctx_mod(fqctx); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong i, Alen; /* x^c -> c*x^(c-1) */ Alen = 0; for (i = 0; i < Blen; i++) { ulong c = (Bexp[N*i + offset] >> shift) & mask; if (c == 0) continue; _n_fq_mul_ui(Acoeff + d*Alen, Bcoeff + d*i, c, d, mod); if (_n_fq_is_zero(Acoeff + d*Alen, d)) continue; mpoly_monomial_sub(Aexp + N*Alen, Bexp + N*i, oneexp, N); Alen++; } return Alen; } static slong _fq_nmod_mpoly_derivative_mp( mp_limb_t * Acoeff, ulong * Aexp, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, flint_bitcnt_t bits, slong N, slong offset, ulong * oneexp, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); nmod_t mod = fq_nmod_ctx_mod(fqctx); slong i, Alen; fmpz_t c; fmpz_init(c); /* x^c -> c*x^(c-1) */ Alen = 0; for (i = 0; i < Blen; i++) { fmpz_set_ui_array(c, Bexp + N*i + offset, bits/FLINT_BITS); if (fmpz_is_zero(c)) continue; _n_fq_mul_ui(Acoeff + d*Alen, Bcoeff + d*i, fmpz_fdiv_ui(c, mod.n), d, mod); if (_n_fq_is_zero(Acoeff + d*Alen, d)) continue; mpoly_monomial_sub_mp(Aexp + N*Alen, Bexp + N*i, oneexp, N); Alen++; } fmpz_clear(c); return Alen; } void fq_nmod_mpoly_derivative( fq_nmod_mpoly_t poly1, const fq_nmod_mpoly_t poly2, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong bits, N, offset, shift; ulong * oneexp; slong len1; TMP_INIT; TMP_START; bits = poly2->bits; fq_nmod_mpoly_fit_length_reset_bits(poly1, poly2->length, bits, ctx); N = mpoly_words_per_exp(bits, ctx->minfo); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (bits <= FLINT_BITS) { mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, bits, ctx->minfo); len1 = _fq_nmod_mpoly_derivative(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, shift, oneexp, ctx->fqctx); } else { offset = mpoly_gen_monomial_offset_mp(oneexp, var, bits, ctx->minfo); len1 = _fq_nmod_mpoly_derivative_mp(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, oneexp, ctx->fqctx); } _fq_nmod_mpoly_set_length(poly1, len1, ctx); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/discriminant.c000066400000000000000000000014731461254215100211220ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_discriminant(fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { int success; fq_nmod_mpoly_univar_t Ax; fq_nmod_mpoly_univar_init(Ax, ctx); fq_nmod_mpoly_to_univar(Ax, A, var, ctx); success = fq_nmod_mpoly_univar_discriminant(R, Ax, ctx); fq_nmod_mpoly_univar_clear(Ax, ctx); return success; } flint-3.1.3/src/fq_nmod_mpoly/div.c000066400000000000000000000011731461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_div(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { /* nothing fancy */ fq_nmod_mpoly_div_monagan_pearce(Q, A, B, ctx); } flint-3.1.3/src/fq_nmod_mpoly/div_monagan_pearce.c000066400000000000000000000241731461254215100222410ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" static int _fq_nmod_mpoly_div_monagan_pearce( fq_nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); slong i, j, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; slong Qlen; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; int lt_divides; mp_limb_t * lc_minus_inv, * pp; TMP_INIT; TMP_START; pp = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); lc_minus_inv = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; Qlen = 0; /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coefficient info */ n_fq_inv(lc_minus_inv, Bcoeffs + d*0, fqctx); _n_fq_neg(lc_minus_inv, lc_minus_inv, d, fqctx->mod); while (heap_len > 1) { _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, N, Qlen + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides(Qexps + N*Qlen, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; lt_divides = mpoly_monomial_divides_mp(Qexps + N*Qlen, exp, Bexps, N, bits); } _n_fq_zero(Qcoeffs + d*Qlen, d); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, fqctx); } else { hind[x->i] |= WORD(1); n_fq_mul(pp, Bcoeffs + d*x->i, Qcoeffs + d*x->j, fqctx); n_fq_add(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, pp, fqctx); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) continue; if (!lt_divides) continue; n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lc_minus_inv, fqctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; TMP_END; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; TMP_END; return 0; } void fq_nmod_mpoly_div_monagan_pearce( fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t Qbits; ulong * Aexps = A->exps, * Bexps = B->exps; ulong * cmpmask; int freeAexps = 0, freeBexps = 0; fq_nmod_mpoly_t TQ; fq_nmod_mpoly_struct * q; if (fq_nmod_mpoly_is_zero(B, ctx)) { flint_throw(FLINT_DIVZERO, "fq_nmod_mpoly_div_monagan_pearce: divide by zero"); } if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_mpoly_zero(Q, ctx); return; } fq_nmod_mpoly_init(TQ, ctx); Qbits = FLINT_MAX(A->bits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (Qbits > A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(Aexps, Bexps, N, cmpmask)) { fq_nmod_mpoly_zero(Q, ctx); goto cleanup; } /* take care of aliasing */ if (Q == A || Q == B) q = TQ; else q = Q; /* do division with remainder */ while (1) { fq_nmod_mpoly_fit_length_reset_bits(q, A->length/B->length + 1, Qbits, ctx); if (_fq_nmod_mpoly_div_monagan_pearce(q, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->fqctx)) { break; } Qbits = mpoly_fix_bits(Qbits + 1, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; if (freeBexps) flint_free(Bexps); Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); freeBexps = 1; } /* deal with aliasing */ if (Q == A || Q == B) fq_nmod_mpoly_swap(Q, TQ, ctx); cleanup: fq_nmod_mpoly_clear(TQ, ctx); if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); flint_free(cmpmask); } flint-3.1.3/src/fq_nmod_mpoly/divides.c000066400000000000000000000012771461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_divides(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { /* nothing fancy here */ return fq_nmod_mpoly_divides_monagan_pearce(Q, A, B, ctx); } flint-3.1.3/src/fq_nmod_mpoly/divides_monagan_pearce.c000066400000000000000000000543711461254215100231110ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" static int _fq_nmod_mpoly_divides_monagan_pearce1( fq_nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, slong bits, ulong cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); int lt_divides; slong i, j, Qlen, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; slong * hind; ulong mask, exp, maxexp = Aexps[Alen - 1]; mp_limb_t * lc_minus_inv, * t; int lazy_size = _n_fq_dot_lazy_size(Blen, fqctx); TMP_INIT; TMP_START; t = (mp_limb_t *) TMP_ALLOC(6*d*sizeof(mp_limb_t)); lc_minus_inv = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); Qlen = 0; /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexps[0], x); /* precompute leading coefficient info */ _n_fq_inv(lc_minus_inv, Bcoeffs + d*0, fqctx, t); _n_fq_neg(lc_minus_inv, lc_minus_inv, d, fqctx->mod); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_exact_division; _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, 1, Qlen + 1); lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Bexps[0], mask); _n_fq_zero(Qcoeffs + d*Qlen, d); _nmod_vec_zero(t, 6*d); switch (lazy_size) { #define lazycase1(n) \ case n: \ do { \ x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); \ do { \ *store++ = x->i; \ *store++ = x->j; \ if (x->i == -WORD(1)) \ { \ _n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, \ Acoeffs + d*x->j, d, fqctx->mod); \ } \ else \ { \ hind[x->i] |= WORD(1); \ _n_fq_madd2_lazy##n(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, d);\ } \ } while ((x = x->next) != NULL); \ } while (heap_len > 1 && heap[1].exp == exp); \ _n_fq_reduce2_lazy##n(t, d, fqctx->mod); \ break; \ lazycase1(1) lazycase1(2) lazycase1(3) default: do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { _n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, d, fqctx->mod); } else { hind[x->i] |= WORD(1); _n_fq_madd2(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, fqctx, t + 2*d); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); break; } _nmod_vec_add(t, t, Qcoeffs + d*Qlen, d, fqctx->mod); _n_fq_reduce2(Qcoeffs + d*Qlen, t, fqctx, t + 2*d); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexps[x->j], x, &next_loc, &heap_len, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } } } if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) { continue; } _n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lc_minus_inv, fqctx, t); if (!lt_divides || (exp^cmpmask) < (maxexp^cmpmask)) goto not_exact_division; /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, cmpmask); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; TMP_END; return 1; not_exact_division: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; TMP_END; return 0; } int _fq_nmod_mpoly_divides_monagan_pearce( fq_nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; slong Qlen; ulong * exp, * exps; ulong ** exp_list; slong exp_next; mp_limb_t * lc_minus_inv, * t; int lazy_size = _n_fq_dot_lazy_size(Blen, fqctx); ulong mask; slong * hind; TMP_INIT; if (N == 1) return _fq_nmod_mpoly_divides_monagan_pearce1(Q, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, Blen, bits, cmpmask[0], fqctx); TMP_START; t = (mp_limb_t *) TMP_ALLOC(6*d*sizeof(mp_limb_t)); lc_minus_inv = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(mpoly_heap_t *)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; Qlen = 0; /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coefficient info */ _n_fq_inv(lc_minus_inv, Bcoeffs + d*0, fqctx, t); _n_fq_neg(lc_minus_inv, lc_minus_inv, d, fqctx->mod); while (heap_len > 1) { _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, N, Qlen + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; lt_divides = mpoly_monomial_divides(Qexps + N*Qlen, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto not_exact_division; lt_divides = mpoly_monomial_divides_mp(Qexps + N*Qlen, exp, Bexps, N, bits); } _n_fq_zero(Qcoeffs + d*Qlen, d); _nmod_vec_zero(t, 6*d); switch (lazy_size) { #define lazycase(n) \ case n: \ do { \ exp_list[--exp_next] = heap[1].exp; \ x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); \ do { \ *store++ = x->i; \ *store++ = x->j; \ if (x->i == -WORD(1)) \ { \ n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, \ Acoeffs + d*x->j, fqctx); \ } \ else \ { \ hind[x->i] |= WORD(1); \ _n_fq_madd2_lazy##n(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, d);\ } \ } while ((x = x->next) != NULL); \ } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); \ _n_fq_reduce2_lazy##n(t, d, fqctx->mod); \ break; \ lazycase(1) lazycase(2) lazycase(3) default: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, fqctx); } else { hind[x->i] |= WORD(1); _n_fq_madd2(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, fqctx, t + 2*d); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); break; } _nmod_vec_add(t, t, Qcoeffs + d*Qlen, d, fqctx->mod); _n_fq_reduce2(Qcoeffs + d*Qlen, t, fqctx, t + 2*d); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go up */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if (((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1))) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) { continue; } _n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lc_minus_inv, fqctx, t); if (!lt_divides || mpoly_monomial_gt(Aexps + N*(Alen - 1), exp, N, cmpmask)) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; TMP_END; return 1; not_exact_division: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; TMP_END; return 0; } /* return 1 if quotient is exact */ int fq_nmod_mpoly_divides_monagan_pearce( fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t Qbits; fmpz * Amaxfields, * Bmaxfields; ulong * cmpmask; ulong * Aexps = A->exps, * Bexps = B->exps, * expq; int divides, easy_exit, freeAexps = 0, freeBexps = 0; ulong mask = 0; TMP_INIT; if (fq_nmod_mpoly_is_zero(B, ctx)) { flint_throw(FLINT_DIVZERO, "Divide by zero in fq_nmod_mpoly_divides_monagan_pearce"); } if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_mpoly_zero(Q, ctx); return 1; } TMP_START; Amaxfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); Bmaxfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(Amaxfields + i); fmpz_init(Bmaxfields + i); } mpoly_max_fields_fmpz(Amaxfields, Aexps, A->length, A->bits, ctx->minfo); mpoly_max_fields_fmpz(Bmaxfields, Bexps, B->length, B->bits, ctx->minfo); easy_exit = 0; for (i = 0; i < ctx->minfo->nfields; i++) { if (fmpz_cmp(Amaxfields + i, Bmaxfields + i) < 0) easy_exit = 1; } Qbits = 1 + _fmpz_vec_max_bits(Amaxfields, ctx->minfo->nfields); Qbits = FLINT_MAX(Qbits, A->bits); Qbits = FLINT_MAX(Qbits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(Amaxfields + i); fmpz_clear(Bmaxfields + i); } if (easy_exit) { fq_nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* temporary space to check leading monomials divide */ expq = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* quick check for easy case of inexact division of leading monomials */ if (Qbits == A->bits && Qbits == B->bits && A->exps[N - 1] < B->exps[N - 1]) { fq_nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } /* ensure input exponents packed to same size as output exponents */ if (Qbits > A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); } /* check leading monomial divides exactly */ if (Qbits <= FLINT_BITS) { /* mask with high bit of each exponent vector field set */ for (i = 0; i < FLINT_BITS/Qbits; i++) mask = (mask << Qbits) + (UWORD(1) << (Qbits - 1)); if (!mpoly_monomial_divides(expq, Aexps, Bexps, N, mask)) { fq_nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } } else { if (!mpoly_monomial_divides_mp(expq, Aexps, Bexps, N, Qbits)) { fq_nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } } /* deal with aliasing and divide polynomials */ if (Q == A || Q == B) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_fit_length_reset_bits(T, A->length/B->length + 1, Qbits, ctx); divides = _fq_nmod_mpoly_divides_monagan_pearce(T, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->fqctx); fq_nmod_mpoly_swap(Q, T, ctx); fq_nmod_mpoly_clear(T, ctx); } else { fq_nmod_mpoly_fit_length_reset_bits(Q, A->length/B->length + 1, Qbits, ctx); divides = _fq_nmod_mpoly_divides_monagan_pearce(Q, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->fqctx); } cleanup: if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); TMP_END; return divides; } flint-3.1.3/src/fq_nmod_mpoly/divrem.c000066400000000000000000000013111461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_divrem(fq_nmod_mpoly_t Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { /* nothing fancy */ fq_nmod_mpoly_divrem_monagan_pearce(Q, R, A, B, ctx); } flint-3.1.3/src/fq_nmod_mpoly/divrem_ideal.c000066400000000000000000000013461461254215100210610ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_divrem_ideal(fq_nmod_mpoly_struct ** Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, fq_nmod_mpoly_struct * const * B, slong len, const fq_nmod_mpoly_ctx_t ctx) { /* nothing fancy */ fq_nmod_mpoly_divrem_ideal_monagan_pearce(Q, R, A, B, len, ctx); } flint-3.1.3/src/fq_nmod_mpoly/divrem_ideal_monagan_pearce.c000066400000000000000000000323141461254215100240770ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* As for divrem_monagan_pearce except that an array of divisor polynomials is passed and an array of quotient polynomials is returned. These are not in low level format. */ int _fq_nmod_mpoly_divrem_ideal_monagan_pearce( fq_nmod_mpoly_struct ** Q, fq_nmod_mpoly_t R, const mp_limb_t * poly2, const ulong * exp2, slong len2, fq_nmod_mpoly_struct * const * poly3, ulong * const * exp3, slong len, slong N, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx, const ulong * cmpmask) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j, p, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_nheap_t ** chains, * chains_ptr; slong ** hinds, * hinds_ptr; mpoly_nheap_t * x; mp_limb_t * r_coeff = R->coeffs; ulong * r_exp = R->exps; slong r_len; ulong * exp, * exps, * texp; ulong ** exp_list; slong exp_next; ulong mask; slong * q_len, * s; mp_limb_t * acc, * pp, * lc_minus_inv; TMP_INIT; TMP_START; chains = TMP_ARRAY_ALLOC(len, mpoly_nheap_t *); hinds = TMP_ARRAY_ALLOC(len, slong *); /* chains[w], hinds[w] will be arrays of length poly3[w]->length; combine the allocations*/ len3 = 0; for (w = 0; w < len; w++) len3 += poly3[w]->length; chains_ptr = TMP_ARRAY_ALLOC(len3, mpoly_nheap_t); hinds_ptr = TMP_ARRAY_ALLOC(len3, slong); len3 = 0; for (w = 0; w < len; w++) { chains[w] = chains_ptr + len3; hinds[w] = hinds_ptr + len3; len3 += poly3[w]->length; for (i = 0; i < poly3[w]->length; i++) hinds[w][i] = 1; } next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong)); exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); q_len = (slong *) TMP_ALLOC(len*sizeof(slong)); s = (slong *) TMP_ALLOC(len*sizeof(slong)); exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; r_len = 0; for (w = 0; w < len; w++) { q_len[w] = 0; s[w] = poly3[w]->length; } x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coeff info */ pp = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); acc = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); lc_minus_inv = (mp_limb_t *) TMP_ALLOC(d*len*sizeof(mp_limb_t)); for (w = 0; w < len; w++) { n_fq_inv(lc_minus_inv + d*w, poly3[w]->coeffs + d*0, ctx->fqctx); _n_fq_neg(lc_minus_inv + d*w, lc_minus_inv + d*w, d, ctx->fqctx->mod); } while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; } _n_fq_zero(acc, d); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i == -WORD(1)) { n_fq_sub(acc, acc, poly2 + d*x->j, ctx->fqctx); } else { hinds[x->p][x->i] |= WORD(1); n_fq_mul(pp, poly3[x->p]->coeffs + d*x->i, Q[x->p]->coeffs + d*x->j, ctx->fqctx); n_fq_add(acc, acc, pp, ctx->fqctx); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < len2) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < poly3[p]->length) && (hinds[p][i + 1] == 2*j + 1) ) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[x->p] + N*x->i, Q[x->p]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len[p]) { s[p]++; } else if ( ((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1)) ) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[x->p] + N*x->i, Q[x->p]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (_n_fq_is_zero(acc, d)) continue; for (w = 0; w < len; w++) { int divides; if (bits <= FLINT_BITS) divides = mpoly_monomial_divides(texp, exp, exp3[w] + N*0, N, mask); else divides = mpoly_monomial_divides_mp(texp, exp, exp3[w] + N*0, N, bits); if (divides) { fq_nmod_mpoly_fit_length(Q[w], q_len[w] + 1, ctx); n_fq_mul(Q[w]->coeffs + d*q_len[w], acc, lc_minus_inv + d*w, ctx->fqctx); mpoly_monomial_set(Q[w]->exps + N*q_len[w], texp, N); if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = q_len[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3[w] + N*x->i, Q[w]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s[w] = 1; q_len[w]++; /* break out of w for loop and continue in heap loop */ goto break_continue; } } /* if get here, no leading terms divided */ _fq_nmod_mpoly_fit_length(&r_coeff, &R->coeffs_alloc, d, &r_exp, &R->exps_alloc, N, r_len + 1); _n_fq_neg(r_coeff + d*r_len, acc, d, ctx->fqctx->mod); mpoly_monomial_set(r_exp + N*r_len, exp, N); r_len++; break_continue:; } R->coeffs = r_coeff; R->exps = r_exp; R->length = r_len; for (i = 0; i < len; i++) Q[i]->length = q_len[i]; TMP_END; return 1; exp_overflow: R->coeffs = r_coeff; R->exps = r_exp; R->length = 0; for (i = 0; i < len; i++) Q[i]->length = 0; TMP_END; return 0; } /* Assumes divisor polys don't alias any output polys */ void fq_nmod_mpoly_divrem_ideal_monagan_pearce( fq_nmod_mpoly_struct ** Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, fq_nmod_mpoly_struct * const * B, slong len, const fq_nmod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t QRbits; slong len3 = 0; ulong * cmpmask; ulong * Aexps; ulong ** Bexps; int freeAexps, * freeBexps; fq_nmod_mpoly_t TR; fq_nmod_mpoly_struct * r; TMP_INIT; for (i = 0; i < len; i++) { len3 = FLINT_MAX(len3, B[i]->length); if (fq_nmod_mpoly_is_zero(B[i], ctx)) { flint_throw(FLINT_DIVZERO, "fq_nmod_mpoly_divrem_ideal_monagan_pearce: divide by zero"); } } /* dividend is zero, write out quotients and remainder */ if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_mpoly_zero(R, ctx); for (i = 0; i < len; i++) fq_nmod_mpoly_zero(Q[i], ctx); return; } TMP_START; fq_nmod_mpoly_init(TR, ctx); freeBexps = (int *) TMP_ALLOC(len*sizeof(int)); Bexps = (ulong **) TMP_ALLOC(len*sizeof(ulong *)); /* compute maximum degrees that can occur in any input or output polys */ QRbits = A->bits; for (i = 0; i < len; i++) QRbits = FLINT_MAX(QRbits, B[i]->bits); QRbits = mpoly_fix_bits(QRbits, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ Aexps = A->exps; freeAexps = 0; if (QRbits > A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); } for (i = 0; i < len; i++) { Bexps[i] = B[i]->exps; freeBexps[i] = 0; if (QRbits > B[i]->bits) { freeBexps[i] = 1; Bexps[i] = (ulong *) flint_malloc(N*B[i]->length*sizeof(ulong)); mpoly_repack_monomials(Bexps[i], QRbits, B[i]->exps, B[i]->bits, B[i]->length, ctx->minfo); } } /* check leading mon. of at least one divisor is at most that of dividend */ for (i = 0; i < len; i++) { if (!mpoly_monomial_lt(Aexps + N*0, Bexps[i] + N*0, N, cmpmask)) break; } if (i == len) { fq_nmod_mpoly_set(R, A, ctx); for (i = 0; i < len; i++) fq_nmod_mpoly_zero(Q[i], ctx); goto cleanup; } /* take care of aliasing */ if (R == A) r = TR; else r = R; /* do division with remainder */ while (1) { fq_nmod_mpoly_fit_length_reset_bits(r, len3, QRbits, ctx); for (i = 0; i < len; i++) fq_nmod_mpoly_fit_length_reset_bits(Q[i], 1, QRbits, ctx); if (_fq_nmod_mpoly_divrem_ideal_monagan_pearce(Q, r, A->coeffs, Aexps, A->length, B, Bexps, len, N, QRbits, ctx, cmpmask)) { break; } QRbits = mpoly_fix_bits(QRbits + 1, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; for (i = 0; i < len; i++) { if (freeBexps[i]) flint_free(Bexps[i]); Bexps[i] = (ulong *) flint_malloc(N*B[i]->length*sizeof(ulong)); mpoly_repack_monomials(Bexps[i], QRbits, B[i]->exps, B[i]->bits, B[i]->length, ctx->minfo); freeBexps[i] = 1; } } /* take care of aliasing */ if (R == A) fq_nmod_mpoly_swap(R, TR, ctx); cleanup: fq_nmod_mpoly_clear(TR, ctx); if (freeAexps) flint_free(Aexps); for (i = 0; i < len; i++) { if (freeBexps[i]) flint_free(Bexps[i]); } flint_free(cmpmask); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/divrem_monagan_pearce.c000066400000000000000000000602541461254215100227450ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" static int _fq_nmod_mpoly_divrem_monagan_pearce1_binomial( fq_nmod_mpoly_t Q, fq_nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, flint_bitcnt_t bits, ulong maskhi, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); mp_limb_t * Qcoeffs = Q->coeffs; mp_limb_t * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; ulong lexp, mask = mpoly_overflow_mask_sp(bits); mp_limb_t * tmp, * lc_inv, * mBcoeff1; int lc_inv_is_one; slong Qlen = 0; slong Rlen = 0; slong Aidx = 0; slong Qidx = 0; TMP_INIT; TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*(2 + FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_INV_ITCH))*sizeof(mp_limb_t)); lc_inv = tmp + d*FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_INV_ITCH); mBcoeff1 = lc_inv + d; _n_fq_inv(lc_inv, Bcoeffs + d*0, fqctx, tmp); _n_fq_neg(mBcoeff1, Bcoeffs + d*1, d, fqctx->mod); lc_inv_is_one = _n_fq_is_one(lc_inv, d); while (1) { FLINT_ASSERT(0 <= Aidx && Aidx <= Alen); FLINT_ASSERT(0 <= Qidx && Qidx <= Qlen); _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, 1, Qlen + 1); if (Aidx < Alen) { lexp = Aexps[Aidx]; if (Qidx < Qlen) { ulong thisexp = Bexps[1] + Qexps[Qidx]; int cmp = mpoly_monomial_cmp1(lexp, thisexp, maskhi); if (cmp < 0) { lexp = thisexp; _n_fq_mul(Qcoeffs + d*Qlen, mBcoeff1, Qcoeffs + d*Qidx, fqctx, tmp); Qidx++; } else if (cmp == 0) { _n_fq_mul(Qcoeffs + d*Qlen, mBcoeff1, Qcoeffs + d*Qidx, fqctx, tmp); _n_fq_add(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*Aidx, d, fqctx->mod); Aidx++; Qidx++; } else { _n_fq_set(Qcoeffs + d*Qlen, Acoeffs + d*Aidx, d); Aidx++; } } else { _n_fq_set(Qcoeffs + d*Qlen, Acoeffs + d*Aidx, d); Aidx++; } } else if (Qidx < Qlen) { lexp = Bexps[1] + Qexps[Qidx]; _n_fq_mul(Qcoeffs + d*Qlen, mBcoeff1, Qcoeffs + d*Qidx, fqctx, tmp); Qidx++; } else { break; } if (mpoly_monomial_overflows1(lexp, mask)) goto exp_overflow; if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) continue; if (!mpoly_monomial_divides1(Qexps + Qlen, lexp, Bexps[0], mask)) { _fq_nmod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, d, &Rexps, &R->exps_alloc, 1, Rlen + 1); _n_fq_set(Rcoeffs + d*Rlen, Qcoeffs + d*Qlen, d); Rexps[Rlen] = lexp; Rlen++; continue; } if (!lc_inv_is_one) _n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lc_inv, fqctx, tmp); Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; TMP_END; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; TMP_END; return 0; } static int _fq_nmod_mpoly_divrem_monagan_pearce1( fq_nmod_mpoly_t Q, fq_nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, ulong maskhi, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j, Qlen, Rlen, s; slong next_loc, heap_len = 2; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; mp_limb_t * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; slong * hind; ulong mask, exp; int lt_divides; mp_limb_t * lc_minus_inv, * t; int lazy_size = _n_fq_dot_lazy_size(Blen, ctx); TMP_INIT; TMP_START; t = (mp_limb_t *) TMP_ALLOC(6*d*sizeof(mp_limb_t)); lc_minus_inv = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* quotient and remainder poly indices start at -1 */ Qlen = WORD(0); Rlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexps[0], x); /* precompute leading coefficient info */ _n_fq_inv(lc_minus_inv, Bcoeffs + d*0, ctx, t); _n_fq_neg(lc_minus_inv, lc_minus_inv, d, ctx->mod); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, 1, Qlen + 1); lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Bexps[0], mask); _n_fq_zero(Qcoeffs + d*Qlen, d); _nmod_vec_zero(t, 6*d); switch (lazy_size) { case 1: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, ctx); } else { hind[x->i] |= WORD(1); _n_fq_madd2_lazy1(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, d); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); _n_fq_reduce2_lazy1(t, d, ctx->mod); break; case 2: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, ctx); } else { hind[x->i] |= WORD(1); _n_fq_madd2_lazy2(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, d); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); _n_fq_reduce2_lazy2(t, d, ctx->mod); break; case 3: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, ctx); } else { hind[x->i] |= WORD(1); _n_fq_madd2_lazy3(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, d); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); _n_fq_reduce2_lazy3(t, d, ctx->mod); break; default: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, ctx); } else { hind[x->i] |= WORD(1); _n_fq_madd2(t, Bcoeffs + d*x->i, Qcoeffs + d*x->j, ctx, t + 2*d); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); break; } _nmod_vec_add(t, t, Qcoeffs + d*Qlen, d, ctx->mod); _n_fq_reduce2(Qcoeffs + d*Qlen, t, ctx, t + 2*d); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexps[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } } } /* try to divide accumulated term by leading term */ if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) continue; if (!lt_divides) { _fq_nmod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, d, &Rexps, &R->exps_alloc, 1, Rlen + 1); _n_fq_neg(Rcoeffs + d*Rlen, Qcoeffs + d*Qlen, d, ctx->mod); Rexps[Rlen] = exp; Rlen++; continue; } _n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lc_minus_inv, ctx, t); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; TMP_END; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; TMP_END; return 0; } static int _fq_nmod_mpoly_divrem_monagan_pearce( fq_nmod_mpoly_t Q, fq_nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); slong i, j, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; mp_limb_t * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; slong Qlen; slong Rlen; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; int lt_divides; mp_limb_t * lc_minus_inv, * pp; TMP_INIT; if (N == 1) { if (Blen == 2) return _fq_nmod_mpoly_divrem_monagan_pearce1_binomial(Q, R, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, bits, cmpmask[0], fqctx); else return _fq_nmod_mpoly_divrem_monagan_pearce1(Q, R, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, Blen, bits, cmpmask[0], fqctx); } TMP_START; pp = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); lc_minus_inv = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; Qlen = 0; Rlen = 0; /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coefficient info */ n_fq_inv(lc_minus_inv, Bcoeffs + d*0, fqctx); _n_fq_neg(lc_minus_inv, lc_minus_inv, d, fqctx->mod); while (heap_len > 1) { _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, N, Qlen + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides(Qexps + N*Qlen, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; lt_divides = mpoly_monomial_divides_mp(Qexps + N*Qlen, exp, Bexps, N, bits); } _n_fq_zero(Qcoeffs + d*Qlen, d); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { n_fq_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Acoeffs + d*x->j, fqctx); } else { hind[x->i] |= WORD(1); n_fq_mul(pp, Bcoeffs + d*x->i, Qcoeffs + d*x->j, fqctx); n_fq_add(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, pp, fqctx); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) continue; /* try to divide accumulated term by leading term */ if (!lt_divides) { _fq_nmod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, d, &Rexps, &R->exps_alloc, N, Rlen + 1); _n_fq_neg(Rcoeffs + d*Rlen, Qcoeffs + d*Qlen, d, fqctx->mod); mpoly_monomial_set(Rexps + N*Rlen, exp, N); Rlen++; continue; } n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lc_minus_inv, fqctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; TMP_END; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; TMP_END; return 0; } void fq_nmod_mpoly_divrem_monagan_pearce( fq_nmod_mpoly_t Q, fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t QRbits; ulong * Aexps = A->exps, * Bexps = B->exps; ulong * cmpmask; int freeAexps = 0, freeBexps = 0; fq_nmod_mpoly_t TQ, TR; fq_nmod_mpoly_struct * q, * r; if (fq_nmod_mpoly_is_zero(B, ctx)) { flint_throw(FLINT_DIVZERO, "fq_nmod_mpoly_divrem_monagan_pearce: divide by zero"); } if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_mpoly_zero(Q, ctx); fq_nmod_mpoly_zero(R, ctx); return; } fq_nmod_mpoly_init(TQ, ctx); fq_nmod_mpoly_init(TR, ctx); QRbits = FLINT_MAX(A->bits, B->bits); QRbits = mpoly_fix_bits(QRbits, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (QRbits != A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); } if (QRbits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, QRbits, B->exps, B->bits, B->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(Aexps, Bexps, N, cmpmask)) { fq_nmod_mpoly_set(R, A, ctx); fq_nmod_mpoly_zero(Q, ctx); goto cleanup; } /* take care of aliasing */ if (Q == A || Q == B) q = TQ; else q = Q; if (R == A || R == B) r = TR; else r = R; /* do division with remainder */ while (1) { fq_nmod_mpoly_fit_length_reset_bits(q, A->length/B->length + 1, QRbits, ctx); fq_nmod_mpoly_fit_length_reset_bits(r, B->length, QRbits, ctx); if (_fq_nmod_mpoly_divrem_monagan_pearce(q, r, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, QRbits, N, cmpmask, ctx->fqctx)) { break; } QRbits = mpoly_fix_bits(QRbits + 1, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; if (freeBexps) flint_free(Bexps); Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, QRbits, B->exps, B->bits, B->length, ctx->minfo); freeBexps = 1; } /* deal with aliasing */ if (Q == A || Q == B) fq_nmod_mpoly_swap(Q, TQ, ctx); if (R == A || R == B) fq_nmod_mpoly_swap(R, TR, ctx); cleanup: fq_nmod_mpoly_clear(TQ, ctx); fq_nmod_mpoly_clear(TR, ctx); if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); flint_free(cmpmask); } flint-3.1.3/src/fq_nmod_mpoly/equal.c000066400000000000000000000017351461254215100175460ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_equal( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i; if (A == B) return 1; if (A->length != B->length) return 0; for (i = 0; i < d*A->length; i++) { if (A->coeffs[i] != B->coeffs[i]) return 0; } return 0 == mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, A->length, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/equal_fq_nmod.c000066400000000000000000000016111461254215100212420ustar00rootroot00000000000000/* Copyright (C) 2017, 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_equal_fq_nmod( const fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong N; if (fq_nmod_is_zero(c, ctx->fqctx)) return A->length == 0; if (A->length != 1) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return n_fq_equal_fq_nmod(A->coeffs, c, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/evaluate_all.c000066400000000000000000000065121461254215100210730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_poly.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void _fq_nmod_mpoly_eval_all_fq_nmod( fq_nmod_t eval, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, fq_nmod_struct * const * alphas, const mpoly_ctx_t mctx, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); slong i, j; slong nvars = mctx->nvars; ulong mask = (Abits <= FLINT_BITS) ? (-UWORD(1)) >> (FLINT_BITS - Abits) : 0; slong N = mpoly_words_per_exp(Abits, mctx); ulong varexp_sp; fmpz_t varexp_mp; slong * offsets, * shifts; n_poly_struct * caches; mp_limb_t * t; TMP_INIT; TMP_START; fmpz_init(varexp_mp); t = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); caches = (n_poly_struct *) TMP_ALLOC(3*nvars*sizeof(n_poly_struct)); offsets = (slong *) TMP_ALLOC(2*nvars*sizeof(slong)); shifts = offsets + nvars; for (j = 0; j < nvars; j++) { if (Abits <= FLINT_BITS) mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, Abits, mctx); else offsets[j] = mpoly_gen_offset_mp(j, Abits, mctx); n_poly_init(caches + 3*j + 0); n_poly_init(caches + 3*j + 1); n_poly_init(caches + 3*j + 2); n_fq_pow_cache_start_fq_nmod(alphas[j], caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, fqctx); } nmod_poly_fit_length(eval, d); _n_fq_zero(eval->coeffs, d); for (i = 0; i < Alen; i++) { _n_fq_set(t, Acoeffs + d*i, d); if (Abits <= FLINT_BITS) { for (j = 0; j < nvars; j++) { varexp_sp = ((Aexps + N*i)[offsets[j]]>>shifts[j])&mask; n_fq_pow_cache_mulpow_ui(t, t, varexp_sp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, fqctx); } } else { for (j = 0; j < nvars; j++) { fmpz_set_ui_array(varexp_mp, Aexps + N*i + offsets[j], Abits/FLINT_BITS); n_fq_pow_cache_mulpow_fmpz(t, t, varexp_mp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, fqctx); } } _n_fq_add(eval->coeffs, eval->coeffs, t, d, fqctx->mod); } _nmod_poly_set_length(eval, d); _nmod_poly_normalise(eval); fmpz_clear(varexp_mp); for (j = 0; j < 3*nvars; j++) n_poly_clear(caches + j); TMP_END; } void fq_nmod_mpoly_evaluate_all_fq_nmod(fq_nmod_t ev, const fq_nmod_mpoly_t A, fq_nmod_struct * const * vals, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_zero(ev, ctx->fqctx); return; } _fq_nmod_mpoly_eval_all_fq_nmod(ev, A->coeffs, A->exps, A->length, A->bits, vals, ctx->minfo, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/evaluate_one.c000066400000000000000000000137511461254215100211070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void _fq_nmod_mpoly_evaluate_one_fq_nmod_sp( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_t val, const fq_nmod_mpoly_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, N, off, shift; ulong * cmpmask, * one; slong Blen = B->length; const mp_limb_t * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; mp_limb_t * Acoeffs; ulong * Aexps; ulong mask, k; int need_sort = 0, cmp; n_poly_struct * cache[3]; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; n_poly_stack_fit_request(St, 3); cache[0] = n_poly_stack_take_top(St); cache[1] = n_poly_stack_take_top(St); cache[2] = n_poly_stack_take_top(St); n_fq_pow_cache_start_fq_nmod(val, cache[0], cache[1], cache[2], ctx->fqctx); fq_nmod_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; mask = (-UWORD(1)) >> (FLINT_BITS - bits); N = mpoly_words_per_exp(bits, ctx->minfo); one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; _n_fq_set(Acoeffs + d*Alen, Bcoeffs + d*i, d); n_fq_pow_cache_mulpow_ui(Acoeffs + d*Alen, Bcoeffs + d*i, k, cache[0], cache[1], cache[2], ctx->fqctx); if (_n_fq_is_zero(Acoeffs + d*Alen, d)) continue; mpoly_monomial_msub(Aexps + N*Alen, Bexps + N*i, k, one, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } _n_fq_add(Acoeffs + d*(Alen - 1), Acoeffs + d*(Alen - 1), Acoeffs + d*Alen, d, fq_nmod_ctx_mod(ctx->fqctx)); Alen -= _n_fq_is_zero(Acoeffs + d*(Alen - 1), d); } A->length = Alen; n_poly_stack_give_back(St, 3); TMP_END; if (need_sort) { fq_nmod_mpoly_sort_terms(A, ctx); fq_nmod_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fq_nmod_mpoly_is_canonical(A, ctx)); } /* exponents of B are multiprecision */ static void _fq_nmod_mpoly_evaluate_one_fq_nmod_mp( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_t val, const fq_nmod_mpoly_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, N, off; ulong * cmpmask, * one, * tmp; slong Blen = B->length; const mp_limb_t * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; mp_limb_t * Acoeffs; ulong * Aexps; fmpz_t k; int need_sort = 0, cmp; n_poly_struct * cache[3]; TMP_INIT; FLINT_ASSERT((B->bits % FLINT_BITS) == 0); TMP_START; fmpz_init(k); n_poly_stack_fit_request(St, 3); cache[0] = n_poly_stack_take_top(St); cache[1] = n_poly_stack_take_top(St); cache[2] = n_poly_stack_take_top(St); n_fq_pow_cache_start_fq_nmod(val, cache[0], cache[1], cache[2], ctx->fqctx); fq_nmod_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; N = mpoly_words_per_exp(bits, ctx->minfo); one = (ulong*) TMP_ALLOC(3*N*sizeof(ulong)); cmpmask = one + N; tmp = cmpmask + N; off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexps + N*i + off, bits/FLINT_BITS); n_fq_pow_cache_mulpow_fmpz(Acoeffs + d*Alen, Bcoeffs + d*i, k, cache[0], cache[1], cache[2], ctx->fqctx); if (_n_fq_is_zero(Acoeffs + d*Alen, d)) continue; mpoly_monomial_mul_fmpz(tmp, one, N, k); mpoly_monomial_sub_mp(Aexps + N*Alen, Bexps + N*i, tmp, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } _n_fq_add(Acoeffs + d*(Alen - 1), Acoeffs + d*(Alen - 1), Acoeffs + d*Alen, d, fq_nmod_ctx_mod(ctx->fqctx)); Alen -= _n_fq_is_zero(Acoeffs + d*(Alen - 1), d); } A->length = Alen; n_poly_stack_give_back(St, 3); fmpz_clear(k); TMP_END; if (need_sort) { fq_nmod_mpoly_sort_terms(A, ctx); fq_nmod_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fq_nmod_mpoly_is_canonical(A, ctx)); } void fq_nmod_mpoly_evaluate_one_fq_nmod( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_t val, const fq_nmod_mpoly_ctx_t ctx) { n_poly_stack_t St; if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_zero(A, ctx); return; } n_poly_stack_init(St); if (B->bits <= FLINT_BITS) _fq_nmod_mpoly_evaluate_one_fq_nmod_sp(A, B, var, val, ctx, St); else _fq_nmod_mpoly_evaluate_one_fq_nmod_mp(A, B, var, val, ctx, St); n_poly_stack_clear(St); } flint-3.1.3/src/fq_nmod_mpoly/fit_length.c000066400000000000000000000014231461254215100205540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_fit_length( fq_nmod_mpoly_t A, slong len, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); _fq_nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, d, &A->exps, &A->exps_alloc, N, len); } flint-3.1.3/src/fq_nmod_mpoly/fit_length_fit_bits.c000066400000000000000000000032131461254215100224360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_fit_length_fit_bits( fq_nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (d*len > A->coeffs_alloc) { A->coeffs_alloc = FLINT_MAX(d*len, 2*A->coeffs_alloc); A->coeffs = flint_realloc(A->coeffs, A->coeffs_alloc*sizeof(mp_limb_t)); } if (bits > A->bits) { slong newN = mpoly_words_per_exp(bits, ctx->minfo); slong new_exps_alloc = newN*len; ulong * t; if (len < 1) { A->bits = bits; return; } t = (ulong *) flint_malloc(new_exps_alloc*sizeof(ulong)); if (A->length > 0) mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, ctx->minfo); if (A->exps_alloc > 0) flint_free(A->exps); A->exps = t; A->exps_alloc = new_exps_alloc; A->bits = bits; } else { if (N*len > A->exps_alloc) { A->exps_alloc = FLINT_MAX(N*len, 2*A->exps_alloc); A->exps = flint_realloc(A->exps, A->exps_alloc*sizeof(ulong)); } } } flint-3.1.3/src/fq_nmod_mpoly/fit_length_reset_bits.c000066400000000000000000000015101461254215100227740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_fit_length_reset_bits( fq_nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(bits, ctx->minfo); _fq_nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, d, &A->exps, &A->exps_alloc, N, len); A->bits = bits; } flint-3.1.3/src/fq_nmod_mpoly/fq_nmod_embed.c000066400000000000000000000505251461254215100212170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" /* F_q is the "small" field presented as F_p[theta]/f(theta) where q = p^m and f is a polynomial over F_p of degree m We would like to extend this small field to a "large" field F_q^n presented as F_p[phi]/g(phi) where g is a polynomial over F_p of degree m*n F_q^n is then isomorphic to F_p[theta][x]/(f(theta), h(theta, x)) for some h of degree n in x. we compute h and values x as an element of F_p[phi]/g(phi) theta as an element of F_p[phi]/g(phi) phi as an element of F_p[theta][x] Example: with theta printed as # as phi as $, the two embeddings for a degree 8 extension F_{3^16} = F_3/($^16+$^10+2) of F_9 = F_3[#]/(#^2+#+2) could be: **** emb[0]: p: 3 m: 2 n: 8 sm modulus: #^2+#+2 lg modulus: $^16+$^10+2 h: x^8+(2*#+1)*x^6+x^4+(#+1)*x^2+(2*#) phi $: x theta #: 2*$^14+$^10+$^6+$^4+2*$^2+1 x: $ **** emb[1]: p: 3 m: 2 n: 8 sm modulus: #^2+#+2 lg modulus: $^16+$^10+2 h: x^8+(#+2)*x^6+x^4+(2*#)*x^2+(#+1) phi $: x theta #: $^14+2*$^10+2*$^6+2*$^4+$^2+1 x: $ */ /* the polynomial h is printed with variable x */ /* static void _embed_print(const bad_fq_nmod_embed_t emb) { flint_printf("p: %wu\n", emb->smctx->modulus->mod.n); flint_printf("m: %wd\n", nmod_poly_degree(emb->smctx->modulus)); flint_printf("n: %wd\n", fq_nmod_poly_degree(emb->h, emb->smctx)); printf("sm modulus: "); nmod_poly_print_pretty(emb->smctx->modulus, emb->smctx->var); printf("\n"); printf("lg modulus: "); nmod_poly_print_pretty(emb->lgctx->modulus, emb->lgctx->var); printf("\n"); printf("h: "); fq_nmod_poly_print_pretty(emb->h, "x", emb->smctx); printf("\n"); printf(" phi %s: ",emb->lgctx->var); fq_nmod_poly_print_pretty(emb->phi_sm, "x", emb->smctx); printf("\n"); printf("theta %s: ",emb->smctx->var); fq_nmod_print_pretty(emb->theta_lg, emb->lgctx); printf("\n"); printf(" x: "); fq_nmod_print_pretty(emb->x_lg, emb->lgctx); printf("\n"); } */ void bad_fq_nmod_embed_clear(bad_fq_nmod_embed_t emb) { fq_nmod_poly_clear(emb->phi_sm, emb->smctx); fq_nmod_poly_clear(emb->h, emb->smctx); n_fq_poly_clear(emb->h_as_n_fq_poly); fq_nmod_clear(emb->theta_lg, emb->lgctx); fq_nmod_clear(emb->x_lg, emb->lgctx); nmod_mat_clear(emb->lg_to_sm_mat); nmod_mat_clear(emb->sm_to_lg_mat); } static void bad_fq_nmod_embed_array_clear(bad_fq_nmod_embed_struct * emb, slong m) { slong i; for (i = 0; i < m; i++) bad_fq_nmod_embed_clear(emb + i); } /* matrices that allow conversion to be done via matrix-vector products */ static void _set_matrices(bad_fq_nmod_embed_t cur) { slong m = fq_nmod_ctx_degree(cur->smctx); slong n = fq_nmod_ctx_degree(cur->lgctx); slong i; n_fq_poly_t phi_as_n_fq_poly, phi_pow, q; mp_limb_t ** Mrows = cur->lg_to_sm_mat->rows; n_fq_poly_init(phi_as_n_fq_poly); n_fq_poly_init(phi_pow); n_fq_poly_init(q); n_fq_poly_set_fq_nmod_poly(phi_as_n_fq_poly, cur->phi_sm, cur->smctx); n_fq_poly_one(phi_pow, cur->smctx); for (i = 0; i < n; i++) { n_fq_poly_divrem(q, phi_pow, phi_pow, cur->h_as_n_fq_poly, cur->smctx); FLINT_ASSERT(phi_pow->length <= n/m); _nmod_vec_set(Mrows[i], phi_pow->coeffs, phi_pow->length*m); n_fq_poly_mul(phi_pow, phi_pow, phi_as_n_fq_poly, cur->smctx); } n_fq_poly_clear(phi_as_n_fq_poly); n_fq_poly_clear(phi_pow); n_fq_poly_clear(q); /* matrix for going from large to small */ nmod_mat_transpose(cur->lg_to_sm_mat, cur->lg_to_sm_mat); /* matrix for going from small to large */ if (!nmod_mat_inv(cur->sm_to_lg_mat, cur->lg_to_sm_mat)) flint_throw(FLINT_ERROR, "bad_fq_nmod_embed_array_init: singular matrix"); } /* Initialize an array of m embeddings making an extension of degree n This allows for the conversion between Fp[phi]/g(phi) <-> Fp[theta][x]/h(x) with the arbitrary choice that phi is mapped to x and x is mapped to phi. */ void bad_fq_nmod_embed_array_init(bad_fq_nmod_embed_struct * emb, const fq_nmod_ctx_t bigctx, const fq_nmod_ctx_t smallctx) { slong i, j, k, l; bad_fq_nmod_embed_struct * cur; fq_nmod_poly_t poly; fq_nmod_t t; fq_nmod_poly_t poly2; fq_nmod_t t2, lead2; fq_nmod_t t3; fq_nmod_poly_factor_t fac2; nmod_mat_t M, Msol; fq_nmod_t biggen; fmpz_t P; mp_limb_t lc_inv; mp_limb_t p = smallctx->modulus->mod.n; slong n, m = nmod_poly_degree(smallctx->modulus); /* n is the degree of the extension */ n = nmod_poly_degree(bigctx->modulus); FLINT_ASSERT((n%m) == 0); n = n/m; fmpz_init_set_ui(P, p); if (m == 1) { cur = emb + 0; cur->smctx = smallctx; cur->lgctx = bigctx; fq_nmod_init(cur->theta_lg, bigctx); FLINT_ASSERT(1 == nmod_poly_get_coeff_ui(cur->smctx->modulus, 1)); fq_nmod_set_ui(cur->theta_lg, nmod_poly_get_coeff_ui( cur->smctx->modulus, 0), bigctx); fq_nmod_neg(cur->theta_lg, cur->theta_lg, bigctx); fq_nmod_init(cur->x_lg, bigctx); fq_nmod_gen(cur->x_lg, bigctx); fq_nmod_poly_init(cur->phi_sm, smallctx); fq_nmod_poly_gen(cur->phi_sm, smallctx); fq_nmod_poly_init(cur->h, smallctx); fq_nmod_init(t, smallctx); for (i = 0; i < nmod_poly_length(bigctx->modulus); i++) { fq_nmod_set_ui(t, nmod_poly_get_coeff_ui(bigctx->modulus, i), smallctx); fq_nmod_poly_set_coeff(cur->h, i, t, smallctx); } /* matrix for going from large to small - columns are powers of phi */ n_fq_poly_init(cur->h_as_n_fq_poly); n_fq_poly_set_fq_nmod_poly(cur->h_as_n_fq_poly, cur->h, smallctx); nmod_mat_init(cur->lg_to_sm_mat, m*n, m*n, p); nmod_mat_init(cur->sm_to_lg_mat, m*n, m*n, p); _set_matrices(cur); fq_nmod_clear(t, smallctx); fmpz_clear(P); return; } /* poly will be bigctx->modulus as a polynomial over smallctx */ fq_nmod_poly_init(poly, smallctx); fq_nmod_init(t, smallctx); for (i = 0; i < nmod_poly_length(bigctx->modulus); i++) { fq_nmod_set_ui(t, nmod_poly_get_coeff_ui(bigctx->modulus, i), smallctx); fq_nmod_poly_set_coeff(poly, i, t, smallctx); } /* poly2 will be smallctx->modulus as a polynomial over bigctx */ fq_nmod_poly_init(poly2, bigctx); fq_nmod_init(t2, bigctx); fq_nmod_init(t3, bigctx); for (i = 0; i < nmod_poly_length(smallctx->modulus); i++) { fq_nmod_set_ui(t2, nmod_poly_get_coeff_ui(smallctx->modulus, i), bigctx); fq_nmod_poly_set_coeff(poly2, i, t2, bigctx); } /* poly2 should factor into m linear factors over bigctx*/ fq_nmod_poly_factor_init(fac2, bigctx); fq_nmod_init(lead2, bigctx); fq_nmod_poly_factor(fac2, lead2, poly2, bigctx); FLINT_ASSERT(fac2->num == m); nmod_mat_init(M, m*n, m*n+1, p); nmod_mat_init(Msol, m*n+1, 1, p); fq_nmod_init(biggen, bigctx); fq_nmod_gen(biggen, bigctx); for (k = 0; k < m; k++) { cur = emb + k; cur->smctx = smallctx; cur->lgctx = bigctx; /* we will send x to phi and phi to x */ fq_nmod_init(cur->x_lg, bigctx); fq_nmod_gen(cur->x_lg, bigctx); fq_nmod_poly_init(cur->phi_sm, smallctx); fq_nmod_poly_gen(cur->phi_sm, smallctx); /* theta is determined from a factor of poly2 */ FLINT_ASSERT(fac2->exp[k] == 1); FLINT_ASSERT(fq_nmod_poly_degree(fac2->poly + k, bigctx) == 1); fq_nmod_init(cur->theta_lg, bigctx); fq_nmod_poly_get_coeff(cur->theta_lg, fac2->poly + k, 0, bigctx); fq_nmod_poly_get_coeff(t2, fac2->poly + k, 1, bigctx); fq_nmod_inv(t2, t2, bigctx); fq_nmod_neg(t2, t2, bigctx); fq_nmod_mul(cur->theta_lg, cur->theta_lg, t2, bigctx); /* determine h by a nullspace calculation */ fq_nmod_one(t2, bigctx); for (i = 0; i < n; i++) { fq_nmod_set(t3, t2, bigctx); for (j = 0; j < m; j++) { FLINT_ASSERT(nmod_poly_degree(t3) < m*n); for (l = 0; l < m*n; l++) { nmod_mat_entry(M, l, m*i + j) = nmod_poly_get_coeff_ui(t3, l); } fq_nmod_mul(t3, t3, cur->theta_lg, bigctx); } fq_nmod_mul(t2, t2, biggen, bigctx); } fq_nmod_pow_ui(t3, biggen, n, bigctx); for (l = 0; l < m*n; l++) { nmod_mat_entry(M, l, m*n) = nmod_poly_get_coeff_ui(t3, l); } i = nmod_mat_nullspace(Msol, M); FLINT_ASSERT(i == 1); /* this is the coefficient of x^n in h */ FLINT_ASSERT(nmod_mat_entry(Msol, m*n, 0) != 0); lc_inv = nmod_inv(nmod_mat_entry(Msol, m*n, 0), smallctx->modulus->mod); /* set h now */ fq_nmod_poly_init(cur->h, smallctx); for (i = 0; i < n; i++) { fq_nmod_zero(t, smallctx); for (j = 0; j < m; j++) { nmod_poly_set_coeff_ui(t, j, nmod_mul(lc_inv, nmod_mat_entry(Msol, m*i + j, 0), smallctx->modulus->mod)); } fq_nmod_poly_set_coeff(cur->h, i, t, smallctx); } fq_nmod_set_ui(t, 1, smallctx); fq_nmod_poly_set_coeff(cur->h, n, t, smallctx); /* the set of h's should be the factorization of bigctx->modulus */ FLINT_ASSERT(fq_nmod_poly_is_irreducible(cur->h, smallctx)); FLINT_ASSERT(fq_nmod_poly_divides(poly, poly, cur->h, smallctx)); n_fq_poly_init(cur->h_as_n_fq_poly); n_fq_poly_set_fq_nmod_poly(cur->h_as_n_fq_poly, cur->h, smallctx); nmod_mat_init(cur->lg_to_sm_mat, m*n, m*n, p); nmod_mat_init(cur->sm_to_lg_mat, m*n, m*n, p); _set_matrices(cur); } FLINT_ASSERT(fq_nmod_poly_degree(poly, smallctx) == 0); nmod_mat_clear(Msol); nmod_mat_clear(M); fq_nmod_clear(biggen, bigctx); fq_nmod_poly_clear(poly2, bigctx); fq_nmod_clear(t2, bigctx); fq_nmod_clear(t3, bigctx); fq_nmod_poly_factor_clear(fac2, bigctx); fq_nmod_clear(lead2, bigctx); fq_nmod_poly_clear(poly, smallctx); fq_nmod_clear(t, smallctx); fmpz_clear(P); } /***************** convert Fp[phi]/g(phi) to Fp[theta][x]/h(x) ***************/ /* just matrix-vector multiplication */ void bad_n_fq_embed_lg_to_sm( n_fq_poly_t out, /* poly over smctx */ const mp_limb_t * in, /* element of lgctx */ const bad_fq_nmod_embed_t emb) { slong smd = fq_nmod_ctx_degree(emb->smctx); slong lgd = fq_nmod_ctx_degree(emb->lgctx); slong i; int nlimbs = _nmod_vec_dot_bound_limbs(lgd, emb->lgctx->mod); n_poly_fit_length(out, lgd); for (i = 0; i < lgd; i++) out->coeffs[i] = _nmod_vec_dot(emb->lg_to_sm_mat->rows[i], in, lgd, emb->lgctx->mod, nlimbs); FLINT_ASSERT(lgd/smd == emb->h->length - 1); out->length = emb->h->length - 1; _n_fq_poly_normalise(out, smd); #if FLINT_WANT_ASSERT { fq_nmod_t in_; fq_nmod_poly_t out_, out_check; fq_nmod_init(in_, emb->lgctx); fq_nmod_poly_init(out_, emb->smctx); fq_nmod_poly_init(out_check, emb->smctx); n_fq_get_fq_nmod(in_, in, emb->lgctx); n_fq_poly_get_fq_nmod_poly(out_, out, emb->smctx); bad_fq_nmod_embed_lg_to_sm(out_check, in_, emb); FLINT_ASSERT(fq_nmod_poly_equal(out_check, out_, emb->smctx)); fq_nmod_clear(in_, emb->lgctx); fq_nmod_poly_clear(out_, emb->smctx); fq_nmod_poly_clear(out_check, emb->smctx); } #endif } /* poorly-implemented old version looking at retirement */ void bad_fq_nmod_embed_lg_to_sm( fq_nmod_poly_t out, /* poly over smctx */ const fq_nmod_t in, /* element of lgctx */ const bad_fq_nmod_embed_t emb) { slong i; fq_nmod_poly_t t1; fq_nmod_t t2; fq_nmod_poly_init(t1, emb->smctx); fq_nmod_init(t2, emb->smctx); fq_nmod_poly_zero(out, emb->smctx); for (i = 0; i < nmod_poly_length(in); i++) { fq_nmod_poly_pow(t1, emb->phi_sm, i, emb->smctx); fq_nmod_set_ui(t2, nmod_poly_get_coeff_ui(in, i), emb->smctx); fq_nmod_poly_scalar_mul_fq_nmod(t1, t1, t2, emb->smctx); fq_nmod_poly_add(out, out, t1, emb->smctx); } fq_nmod_poly_rem(out, out, emb->h, emb->smctx); fq_nmod_poly_clear(t1, emb->smctx); fq_nmod_clear(t2, emb->smctx); } void bad_fq_nmod_embed_fq_nmod_lg_to_n_fq_sm( n_poly_t out_, /* poly over smctx */ const fq_nmod_t in, /* element of lgctx */ const bad_fq_nmod_embed_t emb) { fq_nmod_poly_t out; fq_nmod_poly_init(out, emb->smctx); bad_fq_nmod_embed_lg_to_sm(out, in, emb); n_fq_poly_set_fq_nmod_poly(out_, out, emb->smctx); fq_nmod_poly_clear(out, emb->smctx); } /***************** convert Fp[theta][x]/h(x) to Fp[phi]/g(phi) ***************/ /* just matrix-vector multiplication */ void bad_n_fq_embed_sm_to_lg( mp_limb_t * out, /* element of lgctx */ const n_fq_poly_t in, /* poly over smctx */ const bad_fq_nmod_embed_t emb) { slong smd = fq_nmod_ctx_degree(emb->smctx); slong lgd = fq_nmod_ctx_degree(emb->lgctx); slong i; int nlimbs = _nmod_vec_dot_bound_limbs(lgd, emb->lgctx->mod); n_poly_stack_t St; /* TODO: pass the stack in */ n_fq_poly_struct * q, * in_red; n_poly_stack_init(St); n_poly_stack_fit_request(St, 2); q = n_poly_stack_take_top(St); in_red = n_poly_stack_take_top(St); n_fq_poly_divrem_(q, in_red, in, emb->h_as_n_fq_poly, emb->smctx, St); FLINT_ASSERT(smd*in_red->length <= lgd); for (i = 0; i < lgd; i++) out[i] = _nmod_vec_dot(emb->sm_to_lg_mat->rows[i], in_red->coeffs, smd*in_red->length, emb->lgctx->mod, nlimbs); n_poly_stack_give_back(St, 2); n_poly_stack_clear(St); #if FLINT_WANT_ASSERT { fq_nmod_t out_, out_check; fq_nmod_poly_t in_; fq_nmod_init(out_, emb->smctx); fq_nmod_init(out_check, emb->smctx); fq_nmod_poly_init(in_, emb->lgctx); n_fq_get_fq_nmod(out_, out, emb->lgctx); n_fq_poly_get_fq_nmod_poly(in_, in, emb->smctx); bad_fq_nmod_embed_sm_to_lg(out_check, in_, emb); FLINT_ASSERT(fq_nmod_equal(out_check, out_, emb->lgctx)); fq_nmod_clear(out_, emb->smctx); fq_nmod_clear(out_check, emb->smctx); fq_nmod_poly_clear(in_, emb->lgctx); } #endif } /* poorly-implemented old version */ void bad_fq_nmod_embed_sm_to_lg( fq_nmod_t out, /* element of lgctx */ const fq_nmod_poly_t in, /* poly over smctx */ const bad_fq_nmod_embed_t emb) { slong i, j; fq_nmod_poly_t inred; fq_nmod_t t1, t2; fq_nmod_poly_init(inred, emb->smctx); fq_nmod_poly_rem(inred, in, emb->h, emb->smctx); fq_nmod_init(t1, emb->lgctx); fq_nmod_init(t2, emb->lgctx); fq_nmod_zero(out, emb->lgctx); for (i = 0; i < fq_nmod_poly_length(inred, emb->smctx); i++) { nmod_poly_struct * coeff = inred->coeffs + i; fq_nmod_zero(t1, emb->lgctx); for (j = 0; j < nmod_poly_length(coeff); j++) { fq_nmod_pow_ui(t2, emb->theta_lg, j, emb->lgctx); fq_nmod_mul_ui(t2, t2, nmod_poly_get_coeff_ui(coeff, j), emb->lgctx); fq_nmod_add(t1, t1, t2, emb->lgctx); } fq_nmod_pow_ui(t2, emb->x_lg, i, emb->lgctx); fq_nmod_mul(t1, t1, t2, emb->lgctx); fq_nmod_add(out, out, t1, emb->lgctx); } fq_nmod_clear(t1, emb->lgctx); fq_nmod_clear(t2, emb->lgctx); fq_nmod_poly_clear(inred, emb->smctx); } void bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg( fq_nmod_t out, /* element of lgctx */ const n_poly_t in_, /* poly over smctx */ const bad_fq_nmod_embed_t emb) { fq_nmod_poly_t in; fq_nmod_poly_init(in, emb->smctx); n_fq_poly_get_fq_nmod_poly(in, in_, emb->smctx); bad_fq_nmod_embed_sm_to_lg(out, in , emb); fq_nmod_poly_clear(in, emb->smctx); } /**************** convert Fp[theta]/f(theta) to Fp[phi]/g(phi) ***************/ void bad_n_fq_embed_sm_elem_to_lg( mp_limb_t * out, const mp_limb_t * in, const bad_fq_nmod_embed_t emb) { slong smd = fq_nmod_ctx_degree(emb->smctx); slong lgd = fq_nmod_ctx_degree(emb->lgctx); slong i; int nlimbs = _nmod_vec_dot_bound_limbs(smd, emb->lgctx->mod); for (i = 0; i < lgd; i++) out[i] = _nmod_vec_dot(emb->sm_to_lg_mat->rows[i], in, smd, emb->lgctx->mod, nlimbs); } void bad_fq_nmod_embed_sm_elem_to_lg( fq_nmod_t out, const fq_nmod_t in, const bad_fq_nmod_embed_t emb) { slong smd = fq_nmod_ctx_degree(emb->smctx); slong lgd = fq_nmod_ctx_degree(emb->lgctx); slong i; int nlimbs = _nmod_vec_dot_bound_limbs(smd, emb->lgctx->mod); FLINT_ASSERT(in->length <= smd); nmod_poly_fit_length(out, lgd); for (i = 0; i < lgd; i++) { out->coeffs[i] = _nmod_vec_dot(emb->sm_to_lg_mat->rows[i], in->coeffs, in->length, emb->lgctx->mod, nlimbs); } out->length = lgd; _nmod_poly_normalise(out); } /*****************************************************************************/ bad_fq_nmod_embed_struct * bad_fq_nmod_mpoly_embed_chooser_init(bad_fq_nmod_mpoly_embed_chooser_t embc, fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { nmod_poly_t ext_modulus; fq_nmod_ctx_t ext_fqctx; mp_limb_t p = ctx->fqctx->modulus->mod.n; slong m = nmod_poly_degree(ctx->fqctx->modulus); slong n; n = WORD(20)/(m*FLINT_BIT_COUNT(p)); n = FLINT_MAX(n, WORD(2)); embc->p = p; embc->m = m; embc->n = n; embc->embed = (bad_fq_nmod_embed_struct *) flint_malloc(m* sizeof(bad_fq_nmod_embed_struct)); /* init ectx with modulus of degree m*n */ nmod_poly_init2(ext_modulus, p, m*n + 1); nmod_poly_randtest_sparse_irreducible(ext_modulus, randstate, m*n + 1); fq_nmod_ctx_init_modulus(ext_fqctx, ext_modulus, "$"); fq_nmod_mpoly_ctx_init(ectx, ctx->minfo->nvars, ORD_LEX, ext_fqctx); fq_nmod_ctx_clear(ext_fqctx); nmod_poly_clear(ext_modulus); bad_fq_nmod_embed_array_init(embc->embed, ectx->fqctx, ctx->fqctx); embc->k = 0; return embc->embed + embc->k; } void bad_fq_nmod_mpoly_embed_chooser_clear(bad_fq_nmod_mpoly_embed_chooser_t embc, fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { bad_fq_nmod_embed_array_clear(embc->embed, embc->m); fq_nmod_mpoly_ctx_clear(ectx); flint_free(embc->embed); } bad_fq_nmod_embed_struct * bad_fq_nmod_mpoly_embed_chooser_next(bad_fq_nmod_mpoly_embed_chooser_t embc, fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { nmod_poly_t ext_modulus; fq_nmod_ctx_t ext_fqctx; mp_limb_t p = embc->p; slong m = embc->m; slong n = embc->n; embc->k++; if (embc->k < m) return embc->embed + embc->k; n++; embc->n = n; if (n > 1000) return NULL; bad_fq_nmod_embed_array_clear(embc->embed, embc->m); fq_nmod_mpoly_ctx_clear(ectx); /* init ectx with modulus of degree m*n */ nmod_poly_init2(ext_modulus, p, m*n + 1); nmod_poly_randtest_sparse_irreducible(ext_modulus, randstate, m*n + 1); fq_nmod_ctx_init_modulus(ext_fqctx, ext_modulus, "$"); fq_nmod_mpoly_ctx_init(ectx, ctx->minfo->nvars, ORD_LEX, ext_fqctx); fq_nmod_ctx_clear(ext_fqctx); nmod_poly_clear(ext_modulus); bad_fq_nmod_embed_array_init(embc->embed, ectx->fqctx, ctx->fqctx); embc->k = 0; return embc->embed + embc->k; } flint-3.1.3/src/fq_nmod_mpoly/gcd.c000066400000000000000000001657321461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" #include "fq_nmod_mpoly_factor.h" /* For each j, set out[j] to the evaluation of A at x_i = alpha[i] (i != j) i.e. if nvars = 3 out[0] = A(x, alpha[1], alpha[2]) out[1] = A(alpha[0], x, alpha[2]) out[2] = A(alpha[0], alpha[1], x) If ignore[j] is nonzero, then out[j] need not be calculated, probably because we shouldn't calculate it in dense form. */ void fq_nmod_mpoly_evals( slong * Atdeg, /* total degree of deflated A, or -1 for overflow */ n_fq_poly_struct * out, const int * ignore, const fq_nmod_mpoly_t A, ulong * Amin_exp, ulong * Amax_exp, ulong * Astride, fq_nmod_struct * alpha, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j; slong nvars = ctx->minfo->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong * offsets = FLINT_ARRAY_ALLOC(2*nvars, slong); slong * shifts = offsets + nvars; ulong * varexps = FLINT_ARRAY_ALLOC(nvars, ulong); ulong varexp; slong total_degree, lo, hi; n_poly_struct * caches = FLINT_ARRAY_ALLOC(3*nvars, n_poly_struct); mp_limb_t * t = FLINT_ARRAY_ALLOC(2*d, mp_limb_t); mp_limb_t * meval = t + d; for (j = 0; j < nvars; j++) { mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, ctx->minfo); n_poly_init(caches + 3*j + 0); n_poly_init(caches + 3*j + 1); n_poly_init(caches + 3*j + 2); n_fq_pow_cache_start_fq_nmod(alpha + j, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, ctx->fqctx); if (ignore[j]) continue; i = (Astride[j] < 2) ? Amax_exp[j] - Amin_exp[j] : (Amax_exp[j] - Amin_exp[j])/Astride[j]; n_poly_fit_length(out + j, d*(i + 1)); _nmod_vec_zero(out[j].coeffs, d*(i + 1)); out[j].length = i + 1; } total_degree = 0; for (i = 0; i < A->length; i++) { mp_limb_t * s = A->coeffs + d*i; /* source */ lo = hi = 0; for (j = 0; j < nvars; j++) { varexp = ((A->exps + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexps[j] = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; add_ssaaaa(hi, lo, hi, lo, 0, varexps[j]); n_fq_pow_cache_mulpow_ui(meval, s, varexps[j], caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, ctx->fqctx); s = meval; } if (hi == 0 && FLINT_SIGN_EXT(lo) == 0 && total_degree >= 0) total_degree = FLINT_MAX(total_degree, lo); else total_degree = -1; for (j = 0; j < nvars; j++) { varexp = varexps[j]; if (ignore[j]) continue; FLINT_ASSERT(out[j].alloc >= d*(varexp + 1)); n_fq_pow_cache_mulpow_neg_ui(t, meval, varexp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, ctx->fqctx); n_fq_add(out[j].coeffs + d*varexp, out[j].coeffs + d*varexp, t, ctx->fqctx); } } *Atdeg = total_degree; for (j = 0; j < nvars; j++) _n_fq_poly_normalise(out + j, d); for (j = 0; j < 3*nvars; j++) n_poly_clear(caches + j); flint_free(offsets); flint_free(varexps); flint_free(caches); flint_free(t); } void fq_nmod_mpoly_evals_lgprime( slong * Atdeg, /* total degree of deflated A, or -1 for overflow */ n_fq_poly_struct * out, const int * ignore, const fq_nmod_mpoly_t A, ulong * Amin_exp, ulong * Amax_exp, ulong * Astride, const fq_nmod_mpoly_ctx_t smctx, fq_nmod_struct * alpha, const fq_nmod_mpoly_ctx_t lgctx, const bad_fq_nmod_embed_t emb) { slong smd = fq_nmod_ctx_degree(smctx->fqctx); slong lgd = fq_nmod_ctx_degree(lgctx->fqctx); slong i, j; slong nvars = smctx->minfo->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong N = mpoly_words_per_exp_sp(A->bits, smctx->minfo); slong * offsets = FLINT_ARRAY_ALLOC(2*nvars, slong); slong * shifts = offsets + nvars; ulong * varexps = FLINT_ARRAY_ALLOC(nvars, ulong); ulong varexp, lo, hi; slong total_degree; n_poly_struct * caches = FLINT_ARRAY_ALLOC(3*nvars, n_poly_struct); mp_limb_t * t = FLINT_ARRAY_ALLOC(2*lgd, mp_limb_t); mp_limb_t * meval = t + lgd; for (j = 0; j < nvars; j++) { mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, smctx->minfo); n_poly_init(caches + 3*j + 0); n_poly_init(caches + 3*j + 1); n_poly_init(caches + 3*j + 2); n_fq_pow_cache_start_fq_nmod(alpha + j, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, lgctx->fqctx); if (ignore[j]) continue; i = (Astride[j] < 2) ? Amax_exp[j] - Amin_exp[j] : (Amax_exp[j] - Amin_exp[j])/Astride[j]; n_poly_fit_length(out + j, lgd*(i + 1)); _nmod_vec_zero(out[j].coeffs, lgd*(i + 1)); out[j].length = i + 1; } total_degree = 0; for (i = 0; i < A->length; i++) { bad_n_fq_embed_sm_elem_to_lg(meval, A->coeffs + smd*i, emb); hi = lo = 0; for (j = 0; j < nvars; j++) { varexp = ((A->exps + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexps[j] = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; add_ssaaaa(hi, lo, hi, lo, 0, varexps[j]); n_fq_pow_cache_mulpow_ui(meval, meval, varexps[j], caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, lgctx->fqctx); } if (hi == 0 && FLINT_SIGN_EXT(lo) == 0 && total_degree >= 0) total_degree = FLINT_MAX(total_degree, lo); else total_degree = -1; for (j = 0; j < nvars; j++) { varexp = varexps[j]; if (ignore[j]) continue; FLINT_ASSERT(out[j].alloc >= lgd*(varexp + 1)); n_fq_pow_cache_mulpow_neg_ui(t, meval, varexp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, lgctx->fqctx); n_fq_add(out[j].coeffs + lgd*varexp, out[j].coeffs + lgd*varexp, t, lgctx->fqctx); } } *Atdeg = total_degree; for (j = 0; j < nvars; j++) _n_fq_poly_normalise(out + j, lgd); for (j = 0; j < 3*nvars; j++) n_poly_clear(caches + j); flint_free(offsets); flint_free(varexps); flint_free(caches); flint_free(t); } void mpoly_gcd_info_set_estimates_fq_nmod_mpoly( mpoly_gcd_info_t I, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int tries_left = 10; slong nvars = ctx->minfo->nvars; slong i, j; n_fq_poly_t Geval; n_fq_poly_struct * Aevals, * Bevals; fq_nmod_struct * alpha; flint_rand_t state; slong ignore_limit; int * ignore; flint_randinit(state); ignore = FLINT_ARRAY_ALLOC(nvars, int); alpha = FLINT_ARRAY_ALLOC(nvars, fq_nmod_struct); Aevals = FLINT_ARRAY_ALLOC(2*nvars, n_fq_poly_struct); Bevals = Aevals + nvars; n_fq_poly_init(Geval); for (j = 0; j < nvars; j++) { fq_nmod_init(alpha + j, ctx->fqctx); n_fq_poly_init(Aevals + j); n_fq_poly_init(Bevals + j); } ignore_limit = FLINT_MAX(WORD(9999), (A->length + B->length)/4096); I->Gdeflate_deg_bounds_are_nice = 1; for (j = 0; j < nvars; j++) { if (I->Adeflate_deg[j] > ignore_limit || I->Bdeflate_deg[j] > ignore_limit) { ignore[j] = 1; I->Gdeflate_deg_bounds_are_nice = 0; } else { ignore[j] = 0; } } try_again: if (--tries_left < 0) { I->Gdeflate_deg_bounds_are_nice = 0; for (j = 0; j < nvars; j++) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } goto cleanup; } for (j = 0; j < nvars; j++) { fq_nmod_rand(alpha + j, state, ctx->fqctx); if (fq_nmod_is_zero(alpha + j, ctx->fqctx)) fq_nmod_one(alpha + j, ctx->fqctx); } fq_nmod_mpoly_evals(&I->Adeflate_tdeg, Aevals, ignore, A, I->Amin_exp, I->Amax_exp, I->Gstride, alpha, ctx); fq_nmod_mpoly_evals(&I->Bdeflate_tdeg, Bevals, ignore, B, I->Bmin_exp, I->Bmax_exp, I->Gstride, alpha, ctx); for (j = 0; j < nvars; j++) { if (ignore[j]) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } else { if (I->Adeflate_deg[j] != n_fq_poly_degree(Aevals + j) || I->Bdeflate_deg[j] != n_fq_poly_degree(Bevals + j)) { goto try_again; } n_fq_poly_gcd(Geval, Aevals + j, Bevals + j, ctx->fqctx); I->Gterm_count_est[j] = 0; I->Gdeflate_deg_bound[j] = n_fq_poly_degree(Geval); for (i = I->Gdeflate_deg_bound[j]; i >= 0; i--) I->Gterm_count_est[j] += _n_fq_is_zero(Geval->coeffs + d*i, d); } } cleanup: n_fq_poly_clear(Geval); for (j = 0; j < nvars; j++) { fq_nmod_clear(alpha + j, ctx->fqctx); n_fq_poly_clear(Aevals + j); n_fq_poly_clear(Bevals + j); } flint_free(ignore); flint_free(alpha); flint_free(Aevals); flint_randclear(state); return; } void mpoly_gcd_info_set_estimates_fq_nmod_mpoly_lgprime( mpoly_gcd_info_t I, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t smctx) { int tries_left = 10; slong nvars = smctx->minfo->nvars; slong i, j; n_fq_poly_t Geval; n_fq_poly_struct * Aevals, * Bevals; fq_nmod_struct * alpha; flint_rand_t state; slong ignore_limit; int * ignore; fq_nmod_mpoly_ctx_t lgctx; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; flint_randinit(state); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, lgctx, smctx, state); ignore = FLINT_ARRAY_ALLOC(nvars, int); alpha = FLINT_ARRAY_ALLOC(nvars, fq_nmod_struct); Aevals = FLINT_ARRAY_ALLOC(2*nvars, n_fq_poly_struct); Bevals = Aevals + nvars; n_fq_poly_init(Geval); for (j = 0; j < nvars; j++) { fq_nmod_init(alpha + j, lgctx->fqctx); n_fq_poly_init(Aevals + j); n_fq_poly_init(Bevals + j); } ignore_limit = FLINT_MAX(WORD(9999), (A->length + B->length)/4096); I->Gdeflate_deg_bounds_are_nice = 1; for (j = 0; j < nvars; j++) { if (I->Adeflate_deg[j] > ignore_limit || I->Bdeflate_deg[j] > ignore_limit) { ignore[j] = 1; I->Gdeflate_deg_bounds_are_nice = 0; } else { ignore[j] = 0; } } try_again: if (--tries_left < 0 || cur_emb == NULL) { I->Gdeflate_deg_bounds_are_nice = 0; for (j = 0; j < nvars; j++) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } goto cleanup; } for (j = 0; j < nvars; j++) { fq_nmod_rand(alpha + j, state, lgctx->fqctx); if (fq_nmod_is_zero(alpha + j, lgctx->fqctx)) fq_nmod_one(alpha + j, lgctx->fqctx); } fq_nmod_mpoly_evals_lgprime(&I->Adeflate_tdeg, Aevals, ignore, A, I->Amin_exp, I->Amax_exp, I->Gstride, smctx, alpha, lgctx, cur_emb); fq_nmod_mpoly_evals_lgprime(&I->Bdeflate_tdeg, Bevals, ignore, B, I->Bmin_exp, I->Bmax_exp, I->Gstride, smctx, alpha, lgctx, cur_emb); for (j = 0; j < nvars; j++) { if (ignore[j]) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } else { slong lgd = fq_nmod_ctx_degree(lgctx->fqctx); if (I->Adeflate_deg[j] != n_fq_poly_degree(Aevals + j) || I->Bdeflate_deg[j] != n_fq_poly_degree(Bevals + j)) { cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, lgctx, smctx, state); goto try_again; } n_fq_poly_gcd(Geval, Aevals + j, Bevals + j, lgctx->fqctx); I->Gterm_count_est[j] = 0; I->Gdeflate_deg_bound[j] = n_fq_poly_degree(Geval); for (i = I->Gdeflate_deg_bound[j]; i >= 0; i--) I->Gterm_count_est[j] += _n_fq_is_zero(Geval->coeffs + lgd*i, lgd); } } cleanup: n_fq_poly_clear(Geval); for (j = 0; j < nvars; j++) { fq_nmod_clear(alpha + j, lgctx->fqctx); n_fq_poly_clear(Aevals + j); n_fq_poly_clear(Bevals + j); } flint_free(ignore); flint_free(alpha); flint_free(Aevals); bad_fq_nmod_mpoly_embed_chooser_clear(embc, lgctx, smctx, state); flint_randclear(state); return; } /* (Abar, Bbar) = (A, B) */ static void _parallel_set( fq_nmod_mpoly_t Abar, /* could be NULL */ fq_nmod_mpoly_t Bbar, /* could be NULL */ const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (Abar == B && Bbar == A) { FLINT_ASSERT(Abar != NULL && Bbar != NULL); fq_nmod_mpoly_set(Abar, B, ctx); fq_nmod_mpoly_set(Bbar, A, ctx); fq_nmod_mpoly_swap(Abar, Bbar, ctx); } else if (Abar == B && Bbar != A) { FLINT_ASSERT(Abar != NULL); if (Bbar != NULL) fq_nmod_mpoly_set(Bbar, B, ctx); fq_nmod_mpoly_set(Abar, A, ctx); } else { if (Abar != NULL) fq_nmod_mpoly_set(Abar, A, ctx); if (Bbar != NULL) fq_nmod_mpoly_set(Bbar, B, ctx); } } /* The variables in ess(A) and ess(B) are disjoint. gcd is trivial to compute */ static int _do_trivial( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, /* could be NULL */ fq_nmod_mpoly_t Bbar, /* could be NULL */ const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mpoly_gcd_info_t I, const fq_nmod_mpoly_ctx_t ctx) { _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) mpoly_monomials_shift_right_ui(Abar->exps, Abar->bits, Abar->length, I->Gmin_exp, ctx->minfo); if (Bbar != NULL) mpoly_monomials_shift_right_ui(Bbar->exps, Bbar->bits, Bbar->length, I->Gmin_exp, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(G, 1, I->Gbits, ctx); mpoly_set_monomial_ui(G->exps, I->Gmin_exp, I->Gbits, ctx->minfo); _n_fq_one(G->coeffs, fq_nmod_ctx_degree(ctx->fqctx)); _fq_nmod_mpoly_set_length(G, 1, ctx); return 1; } /*********************** Easy when B is a monomial ***************************/ static int _do_monomial_gcd( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, /* could be NULL */ fq_nmod_mpoly_t Bbar, /* could be NULL */ const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); fmpz * minAfields, * minAdegs, * minBdegs; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length == 1); TMP_START; /* get the field-wise minimum of A */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, A->bits, ctx->minfo); /* unpack to get the min degrees of each variable in A */ minAdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minAdegs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(minAdegs, minAfields, ctx->minfo); /* get the degree of each variable in B */ minBdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minBdegs + i); mpoly_get_monomial_ffmpz(minBdegs, B->exps, B->bits, ctx->minfo); /* compute the degree of each variable in G */ _fmpz_vec_min_inplace(minBdegs, minAdegs, ctx->minfo->nvars); _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) mpoly_monomials_shift_right_ffmpz(Abar->exps, Abar->bits, Abar->length, minBdegs, ctx->minfo); if (Bbar != NULL) mpoly_monomials_shift_right_ffmpz(Bbar->exps, Bbar->bits, Bbar->length, minBdegs, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(G, 1, Gbits, ctx); mpoly_set_monomial_ffmpz(G->exps, minBdegs, Gbits, ctx->minfo); _n_fq_one(G->coeffs + 0, fq_nmod_ctx_degree(ctx->fqctx)); _fq_nmod_mpoly_set_length(G, 1, ctx); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(minAfields + i); } for (i = 0; i < ctx->minfo->nvars; i++) { fmpz_clear(minAdegs + i); fmpz_clear(minBdegs + i); } TMP_END; return 1; } /********************** See if cofactors are monomials ***********************/ static int _try_monomial_cofactors( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, /* could be NULL */ fq_nmod_mpoly_t Bbar, /* could be NULL */ const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; slong i, j; slong NA, NG; slong nvars = ctx->minfo->nvars; fmpz * Abarexps, * Bbarexps, * Texps; mp_limb_t * tmp, * t1, * t2, * a0, * b0; fq_nmod_mpoly_t T; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); flint_bitcnt_t Abarbits = A->bits; flint_bitcnt_t Bbarbits = B->bits; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (A->length != B->length) return 0; TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*(4 + FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_INV_ITCH))*sizeof(mp_limb_t)); t1 = tmp + d*FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_INV_ITCH); t2 = t1 + d; a0 = t2 + d; b0 = a0 + d; for (i = A->length - 1; i > 0; i--) { _n_fq_mul(t1, A->coeffs + d*0, B->coeffs + d*i, ctx->fqctx, tmp); _n_fq_mul(t2, B->coeffs + d*0, A->coeffs + d*i, ctx->fqctx, tmp); success = _n_fq_equal(t1, t2, d); if (!success) goto cleanup_less; } _n_fq_set(a0, A->coeffs + d*0, d); _n_fq_set(b0, B->coeffs + d*0, d); Abarexps = (fmpz *) TMP_ALLOC(3*nvars*sizeof(fmpz)); Bbarexps = Abarexps + 1*nvars; Texps = Abarexps + 2*nvars; for (j = 0; j < nvars; j++) { fmpz_init(Abarexps + j); fmpz_init(Bbarexps + j); fmpz_init(Texps + j); } success = mpoly_monomial_cofactors(Abarexps, Bbarexps, A->exps, A->bits, B->exps, B->bits, A->length, ctx->minfo); if (!success) goto cleanup_more; fq_nmod_mpoly_init3(T, A->length, Gbits, ctx); NG = mpoly_words_per_exp(Gbits, ctx->minfo); NA = mpoly_words_per_exp(A->bits, ctx->minfo); _n_fq_inv(t1, A->coeffs + d*0, ctx->fqctx, tmp); T->length = A->length; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ffmpz(Texps, A->exps + NA*i, A->bits, ctx->minfo); _fmpz_vec_sub(Texps, Texps, Abarexps, nvars); mpoly_set_monomial_ffmpz(T->exps + NG*i, Texps, Gbits, ctx->minfo); n_fq_mul(T->coeffs + d*i, A->coeffs + d*i, t1, ctx->fqctx); } fq_nmod_mpoly_swap(G, T, ctx); fq_nmod_mpoly_clear(T, ctx); if (Abar != NULL) { fq_nmod_mpoly_fit_length_reset_bits(Abar, 1, Abarbits, ctx); mpoly_set_monomial_ffmpz(Abar->exps, Abarexps, Abarbits, ctx->minfo); _n_fq_set(Abar->coeffs + d*0, a0, d); _fq_nmod_mpoly_set_length(Abar, 1, ctx); } if (Bbar != NULL) { fq_nmod_mpoly_fit_length_reset_bits(Bbar, 1, Bbarbits, ctx); mpoly_set_monomial_ffmpz(Bbar->exps, Bbarexps, Bbarbits, ctx->minfo); _n_fq_set(Bbar->coeffs + d*0, b0, d); _fq_nmod_mpoly_set_length(Bbar, 1, ctx); } success = 1; cleanup_more: for (j = 0; j < nvars; j++) { fmpz_clear(Abarexps + j); fmpz_clear(Bbarexps + j); fmpz_clear(Texps + j); } cleanup_less: TMP_END; return success; } /*** ess(A) and ess(B) depend on only one variable v_in_both ****************/ static int _do_univar( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong v_in_both, const mpoly_gcd_info_t I, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_poly_t a, b, g, t, r; fq_nmod_poly_init(a, ctx->fqctx); fq_nmod_poly_init(b, ctx->fqctx); fq_nmod_poly_init(g, ctx->fqctx); fq_nmod_poly_init(t, ctx->fqctx); fq_nmod_poly_init(r, ctx->fqctx); _fq_nmod_mpoly_to_fq_nmod_poly_deflate(a, A, v_in_both, I->Amin_exp, I->Gstride, ctx); _fq_nmod_mpoly_to_fq_nmod_poly_deflate(b, B, v_in_both, I->Bmin_exp, I->Gstride, ctx); fq_nmod_poly_gcd(g, a, b, ctx->fqctx); _fq_nmod_mpoly_from_fq_nmod_poly_inflate(G, I->Gbits, g, v_in_both, I->Gmin_exp, I->Gstride, ctx); if (Abar != NULL) { fq_nmod_poly_divrem(t, r, a, g, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(r, ctx->fqctx)); _fq_nmod_mpoly_from_fq_nmod_poly_inflate(Abar, I->Abarbits, t, v_in_both, I->Abarmin_exp, I->Gstride, ctx); } if (Bbar != NULL) { fq_nmod_poly_divrem(t, r, b, g, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(r, ctx->fqctx)); _fq_nmod_mpoly_from_fq_nmod_poly_inflate(Bbar, I->Bbarbits, t, v_in_both, I->Bbarmin_exp, I->Gstride, ctx); } fq_nmod_poly_clear(a, ctx->fqctx); fq_nmod_poly_clear(b, ctx->fqctx); fq_nmod_poly_clear(g, ctx->fqctx); fq_nmod_poly_clear(t, ctx->fqctx); fq_nmod_poly_clear(r, ctx->fqctx); return 1; } /********* Assume B has length one when converted to univar format ***********/ static int _try_missing_var( fq_nmod_mpoly_t G, flint_bitcnt_t Gbits, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, slong var, const fq_nmod_mpoly_t A, ulong Ashift, const fq_nmod_mpoly_t B, ulong Bshift, const fq_nmod_mpoly_ctx_t ctx) { int success; fq_nmod_mpoly_univar_t Au; fq_nmod_mpoly_univar_init(Au, ctx); #if FLINT_WANT_ASSERT fq_nmod_mpoly_to_univar(Au, B, var, ctx); FLINT_ASSERT(Au->length == 1); #endif fq_nmod_mpoly_to_univar(Au, A, var, ctx); fq_nmod_mpoly_univar_fit_length(Au, Au->length + 1, ctx); fq_nmod_mpoly_set(Au->coeffs + Au->length, B, ctx); Au->length++; if (Abar == NULL && Bbar == NULL) { success = _fq_nmod_mpoly_vec_content_mpoly(G, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; fq_nmod_mpoly_repack_bits_inplace(G, Gbits, ctx); _mpoly_gen_shift_left(G->exps, G->bits, G->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); } else { fq_nmod_mpoly_t tG, tAbar, tBbar; fq_nmod_mpoly_init(tG, ctx); fq_nmod_mpoly_init(tAbar, ctx); fq_nmod_mpoly_init(tBbar, ctx); success = _fq_nmod_mpoly_vec_content_mpoly(tG, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; fq_nmod_mpoly_repack_bits_inplace(tG, Gbits, ctx); _mpoly_gen_shift_left(tG->exps, tG->bits, tG->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); if (Abar != NULL) { success = fq_nmod_mpoly_divides(tAbar, A, tG, ctx); FLINT_ASSERT(success); } if (Bbar != NULL) { success = fq_nmod_mpoly_divides(tBbar, B, tG, ctx); FLINT_ASSERT(success); } fq_nmod_mpoly_swap(G, tG, ctx); if (Abar != NULL) fq_nmod_mpoly_swap(Abar, tAbar, ctx); if (Bbar != NULL) fq_nmod_mpoly_swap(Bbar, tBbar, ctx); fq_nmod_mpoly_clear(tG, ctx); fq_nmod_mpoly_clear(tAbar, ctx); fq_nmod_mpoly_clear(tBbar, ctx); } success = 1; cleanup: fq_nmod_mpoly_univar_clear(Au, ctx); return success; } /************************ See if B divides A ********************************/ static int _try_divides( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t BB, const fq_nmod_mpoly_ctx_t ctx) { int success = 0; fq_nmod_mpoly_t Q, B, M; fq_nmod_mpoly_init(Q, ctx); fq_nmod_mpoly_init(B, ctx); fq_nmod_mpoly_init(M, ctx); /* BB = M*B */ fq_nmod_mpoly_term_content(M, BB, ctx); fq_nmod_mpoly_divides(B, BB, M, ctx); if (fq_nmod_mpoly_divides(Q, A, B, ctx)) { /* gcd(Q*B, M*B) */ _do_monomial_gcd(G, Abar, Bbar, Q, M, ctx); fq_nmod_mpoly_mul(G, G, B, ctx); success = 1; } fq_nmod_mpoly_clear(Q, ctx); fq_nmod_mpoly_clear(B, ctx); fq_nmod_mpoly_clear(M, ctx); return success; } /********************** Hit A and B with zippel ******************************/ static int _try_zippel( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mpoly_gcd_info_t I, const fq_nmod_mpoly_ctx_t ctx) { slong m = I->mvars; int success; flint_bitcnt_t wbits; flint_rand_t randstate; fq_nmod_mpoly_ctx_t uctx; fq_nmod_mpolyu_t Au, Bu, Gu, Abaru, Bbaru; fq_nmod_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL)) return 0; FLINT_ASSERT(m >= WORD(2)); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); flint_randinit(randstate); /* uctx is context for Fq[y_1,...,y_{m-1}]*/ fq_nmod_mpoly_ctx_init(uctx, m - 1, ORD_LEX, ctx->fqctx); wbits = FLINT_MAX(A->bits, B->bits); fq_nmod_mpolyu_init(Au, wbits, uctx); fq_nmod_mpolyu_init(Bu, wbits, uctx); fq_nmod_mpolyu_init(Gu, wbits, uctx); fq_nmod_mpolyu_init(Abaru, wbits, uctx); fq_nmod_mpolyu_init(Bbaru, wbits, uctx); fq_nmod_mpoly_init3(Ac, 0, wbits, uctx); fq_nmod_mpoly_init3(Bc, 0, wbits, uctx); fq_nmod_mpoly_init3(Gc, 0, wbits, uctx); fq_nmod_mpoly_init3(Abarc, 0, wbits, uctx); fq_nmod_mpoly_init3(Bbarc, 0, wbits, uctx); fq_nmod_mpoly_to_mpolyu_perm_deflate(Au, uctx, A, ctx, I->zippel_perm, I->Amin_exp, I->Gstride); fq_nmod_mpoly_to_mpolyu_perm_deflate(Bu, uctx, B, ctx, I->zippel_perm, I->Bmin_exp, I->Gstride); success = fq_nmod_mpolyu_content_mpoly(Ac, Au, uctx) && fq_nmod_mpolyu_content_mpoly(Bc, Bu, uctx); if (!success) goto cleanup; fq_nmod_mpolyu_divexact_mpoly_inplace(Au, Ac, uctx); fq_nmod_mpolyu_divexact_mpoly_inplace(Bu, Bc, uctx); success = fq_nmod_mpolyu_gcdm_zippel(Gu, Abaru, Bbaru, Au, Bu, uctx, randstate); if (!success) goto cleanup; if (Abar == NULL && Bbar == NULL) { success = fq_nmod_mpoly_gcd(Gc, Ac, Bc, uctx); if (!success) goto cleanup; fq_nmod_mpoly_repack_bits_inplace(Gc, wbits, uctx); fq_nmod_mpolyu_mul_mpoly_inplace(Gu, Gc, uctx); fq_nmod_mpoly_from_mpolyu_perm_inflate(G, I->Gbits, ctx, Gu, uctx, I->zippel_perm, I->Gmin_exp, I->Gstride); } else { success = fq_nmod_mpoly_gcd_cofactors(Gc, Abarc, Bbarc, Ac, Bc, uctx); if (!success) goto cleanup; fq_nmod_mpoly_repack_bits_inplace(Gc, wbits, uctx); fq_nmod_mpoly_repack_bits_inplace(Abarc, wbits, uctx); fq_nmod_mpoly_repack_bits_inplace(Bbarc, wbits, uctx); fq_nmod_mpolyu_mul_mpoly_inplace(Gu, Gc, uctx); fq_nmod_mpolyu_mul_mpoly_inplace(Abaru, Abarc, uctx); fq_nmod_mpolyu_mul_mpoly_inplace(Bbaru, Bbarc, uctx); fq_nmod_mpoly_from_mpolyu_perm_inflate(G, I->Gbits, ctx, Gu, uctx, I->zippel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) fq_nmod_mpoly_from_mpolyu_perm_inflate(Abar, I->Abarbits, ctx, Abaru, uctx, I->zippel_perm, I->Abarmin_exp, I->Gstride); if (Bbar != NULL) fq_nmod_mpoly_from_mpolyu_perm_inflate(Bbar, I->Bbarbits, ctx, Bbaru, uctx, I->zippel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fq_nmod_mpolyu_clear(Au, uctx); fq_nmod_mpolyu_clear(Bu, uctx); fq_nmod_mpolyu_clear(Gu, uctx); fq_nmod_mpolyu_clear(Abaru, uctx); fq_nmod_mpolyu_clear(Bbaru, uctx); fq_nmod_mpoly_clear(Ac, uctx); fq_nmod_mpoly_clear(Bc, uctx); fq_nmod_mpoly_clear(Gc, uctx); fq_nmod_mpoly_clear(Abarc, uctx); fq_nmod_mpoly_clear(Bbarc, uctx); fq_nmod_mpoly_ctx_clear(uctx); flint_randclear(randstate); return success; } static int _try_zippel2( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mpoly_gcd_info_t I, const fq_nmod_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; fq_nmod_mpoly_ctx_t lctx; fq_nmod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fq_nmod_mpoly_t Al_lc, Bl_lc, Ac, Bc, Gc, Abarc, Bbarc, Gamma; slong * tmp, * Gl_degs, * Al_degs, * Bl_degs, * Gamma_degs, * Gguess; slong max_degree; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL2)) return 0; FLINT_ASSERT(m >= WORD(3)); tmp = FLINT_ARRAY_ALLOC(5*m, slong); Al_degs = tmp + 1*m; Bl_degs = tmp + 2*m; Gl_degs = tmp + 3*m; Gamma_degs = tmp + 4*m; fq_nmod_mpoly_ctx_init(lctx, m, ORD_LEX, ctx->fqctx); max_degree = 0; for (i = 0; i < m; i++) { k = I->zippel2_perm[i]; Gl_degs[i] = I->Gdeflate_deg_bound[k]; Al_degs[i] = I->Adeflate_deg[k]; max_degree = FLINT_MAX(max_degree, Al_degs[i]); Bl_degs[i] = I->Bdeflate_deg[k]; max_degree = FLINT_MAX(max_degree, Bl_degs[i]); } wbits = 1 + FLINT_BIT_COUNT(max_degree); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fq_nmod_mpoly_init3(Al, 0, wbits, lctx); fq_nmod_mpoly_init3(Bl, 0, wbits, lctx); fq_nmod_mpoly_init3(Gl, 0, wbits, lctx); fq_nmod_mpoly_init3(Abarl, 0, wbits, lctx); fq_nmod_mpoly_init3(Bbarl, 0, wbits, lctx); fq_nmod_mpoly_init3(Ac, 0, wbits, lctx); fq_nmod_mpoly_init3(Bc, 0, wbits, lctx); fq_nmod_mpoly_init3(Gc, 0, wbits, lctx); fq_nmod_mpoly_init3(Abarc, 0, wbits, lctx); fq_nmod_mpoly_init3(Bbarc, 0, wbits, lctx); fq_nmod_mpoly_init3(Gamma, 0, wbits, lctx); fq_nmod_mpoly_init3(Al_lc, 0, wbits, lctx); fq_nmod_mpoly_init3(Bl_lc, 0, wbits, lctx); fq_nmod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->zippel2_perm, I->Amin_exp, I->Gstride); fq_nmod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->zippel2_perm, I->Bmin_exp, I->Gstride); success = fq_nmod_mpolyl_content(Ac, Al, 2, lctx) && fq_nmod_mpolyl_content(Bc, Bl, 2, lctx); if (!success) goto cleanup; if (Abar == NULL && Bbar == NULL) success = fq_nmod_mpoly_gcd(Gc, Ac, Bc, lctx); else success = fq_nmod_mpoly_gcd_cofactors(Gc, Abarc, Bbarc, Ac, Bc, lctx); if (!success) goto cleanup; fq_nmod_mpoly_degrees_si(tmp, Ac, lctx); for (i = 0; i < m; i++) Al_degs[i] -= tmp[i]; if (!fq_nmod_mpoly_is_one(Ac, lctx)) { success = fq_nmod_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); } fq_nmod_mpoly_degrees_si(tmp, Bc, lctx); for (i = 0; i < m; i++) Bl_degs[i] -= tmp[i]; if (!fq_nmod_mpoly_is_one(Bc, lctx)) { success = fq_nmod_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); } fq_nmod_mpoly_degrees_si(tmp, Gc, lctx); for (i = 0; i < m; i++) Gl_degs[i] -= tmp[i]; fq_nmod_mpoly_repack_bits_inplace(Al, wbits, lctx); fq_nmod_mpoly_repack_bits_inplace(Bl, wbits, lctx); fq_nmod_mpolyl_lead_coeff(Al_lc, Al, 2, lctx); fq_nmod_mpolyl_lead_coeff(Bl_lc, Bl, 2, lctx); success = fq_nmod_mpoly_gcd(Gamma, Al_lc, Bl_lc, lctx); if (!success) goto cleanup; fq_nmod_mpoly_repack_bits_inplace(Gamma, wbits, lctx); fq_nmod_mpoly_degrees_si(Gamma_degs, Gamma, lctx); Gguess = I->Gdeflate_deg_bounds_are_nice ? Gl_degs : NULL; success = fq_nmod_mpolyl_gcd_zippel_smprime(Gl, Gguess, Abarl, Bbarl, Al, Al_degs, Bl, Bl_degs, Gamma, Gamma_degs, lctx); if (!success) { success = fq_nmod_mpolyl_gcd_zippel_lgprime(Gl, Gguess, Abarl, Bbarl, Al, Al_degs, Bl, Bl_degs, Gamma, Gamma_degs, lctx); if (!success) goto cleanup; } if (!fq_nmod_mpoly_is_one(Gc, lctx)) fq_nmod_mpoly_mul(Gl, Gl, Gc, lctx); fq_nmod_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->zippel2_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fq_nmod_mpoly_mul(Abarl, Abarl, Abarc, lctx); fq_nmod_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->zippel2_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fq_nmod_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fq_nmod_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->zippel2_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fq_nmod_mpoly_clear(Al, lctx); fq_nmod_mpoly_clear(Bl, lctx); fq_nmod_mpoly_clear(Gl, lctx); fq_nmod_mpoly_clear(Abarl, lctx); fq_nmod_mpoly_clear(Bbarl, lctx); fq_nmod_mpoly_clear(Ac, lctx); fq_nmod_mpoly_clear(Bc, lctx); fq_nmod_mpoly_clear(Gc, lctx); fq_nmod_mpoly_clear(Abarc, lctx); fq_nmod_mpoly_clear(Bbarc, lctx); fq_nmod_mpoly_clear(Gamma, lctx); fq_nmod_mpoly_clear(Al_lc, lctx); fq_nmod_mpoly_clear(Bl_lc, lctx); fq_nmod_mpoly_ctx_clear(lctx); flint_free(tmp); return success; } /******************** Hit A and B with hensel lifting ************************/ static int _try_hensel( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mpoly_gcd_info_t I, const fq_nmod_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; fq_nmod_mpoly_ctx_t lctx; fq_nmod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; fq_nmod_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; slong max_deg; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_HENSEL)) return 0; FLINT_ASSERT(m >= WORD(2)); fq_nmod_mpoly_ctx_init(lctx, m, ORD_LEX, ctx->fqctx); max_deg = 0; for (i = 0; i < m; i++) { k = I->hensel_perm[i]; max_deg = FLINT_MAX(max_deg, I->Adeflate_deg[k]); max_deg = FLINT_MAX(max_deg, I->Bdeflate_deg[k]); } wbits = 1 + FLINT_BIT_COUNT(max_deg); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); fq_nmod_mpoly_init3(Al, 0, wbits, lctx); fq_nmod_mpoly_init3(Bl, 0, wbits, lctx); fq_nmod_mpoly_init3(Gl, 0, wbits, lctx); fq_nmod_mpoly_init3(Abarl, 0, wbits, lctx); fq_nmod_mpoly_init3(Bbarl, 0, wbits, lctx); fq_nmod_mpoly_init3(Ac, 0, wbits, lctx); fq_nmod_mpoly_init3(Bc, 0, wbits, lctx); fq_nmod_mpoly_init3(Gc, 0, wbits, lctx); fq_nmod_mpoly_init3(Abarc, 0, wbits, lctx); fq_nmod_mpoly_init3(Bbarc, 0, wbits, lctx); fq_nmod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->hensel_perm, I->Amin_exp, I->Gstride); fq_nmod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->hensel_perm, I->Bmin_exp, I->Gstride); success = fq_nmod_mpolyl_content(Ac, Al, 1, lctx) && fq_nmod_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; if (Abar == NULL && Bbar == NULL) success = fq_nmod_mpoly_gcd(Gc, Ac, Bc, lctx); else success = fq_nmod_mpoly_gcd_cofactors(Gc, Abarc, Bbarc, Ac, Bc, lctx); if (!success) goto cleanup; success = fq_nmod_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = fq_nmod_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); fq_nmod_mpoly_repack_bits_inplace(Al, wbits, lctx); fq_nmod_mpoly_repack_bits_inplace(Bl, wbits, lctx); max_deg = I->Gdeflate_deg_bound[I->hensel_perm[0]]; success = fq_nmod_mpolyl_gcd_hensel_smprime(Gl, max_deg, Abarl, Bbarl, Al, Bl, lctx); if (!success) goto cleanup; fq_nmod_mpoly_mul(Gl, Gl, Gc, lctx); fq_nmod_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->hensel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { fq_nmod_mpoly_mul(Abarl, Abarl, Abarc, lctx); fq_nmod_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->hensel_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { fq_nmod_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); fq_nmod_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->hensel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: fq_nmod_mpoly_clear(Al, lctx); fq_nmod_mpoly_clear(Bl, lctx); fq_nmod_mpoly_clear(Gl, lctx); fq_nmod_mpoly_clear(Abarl, lctx); fq_nmod_mpoly_clear(Bbarl, lctx); fq_nmod_mpoly_clear(Ac, lctx); fq_nmod_mpoly_clear(Bc, lctx); fq_nmod_mpoly_clear(Gc, lctx); fq_nmod_mpoly_clear(Abarc, lctx); fq_nmod_mpoly_clear(Bbarc, lctx); fq_nmod_mpoly_ctx_clear(lctx); return success; } /*********************** Hit A and B with brown ******************************/ static int _try_brown( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, mpoly_gcd_info_t I, const fq_nmod_mpoly_ctx_t ctx) { int success; slong m = I->mvars; flint_bitcnt_t wbits; fq_nmod_mpoly_ctx_t nctx; fq_nmod_mpolyn_t An, Bn, Gn, Abarn, Bbarn; if (!(I->can_use & MPOLY_GCD_USE_BROWN)) return 0; FLINT_ASSERT(m >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); wbits = FLINT_MAX(A->bits, B->bits); fq_nmod_mpoly_ctx_init(nctx, m, ORD_LEX, ctx->fqctx); fq_nmod_mpolyn_init(An, wbits, nctx); fq_nmod_mpolyn_init(Bn, wbits, nctx); fq_nmod_mpolyn_init(Gn, wbits, nctx); fq_nmod_mpolyn_init(Abarn, wbits, nctx); fq_nmod_mpolyn_init(Bbarn, wbits, nctx); fq_nmod_mpoly_to_mpolyn_perm_deflate(An, nctx, A, ctx, I->brown_perm, I->Amin_exp, I->Gstride); fq_nmod_mpoly_to_mpolyn_perm_deflate(Bn, nctx, B, ctx, I->brown_perm, I->Bmin_exp, I->Gstride); FLINT_ASSERT(An->bits == wbits); FLINT_ASSERT(Bn->bits == wbits); FLINT_ASSERT(An->length > 1); FLINT_ASSERT(Bn->length > 1); success = fq_nmod_mpolyn_gcd_brown_smprime(Gn, Abarn, Bbarn, An, Bn, m - 1, nctx); if (!success) { fq_nmod_mpoly_to_mpolyn_perm_deflate(An, nctx, A, ctx, I->brown_perm, I->Amin_exp, I->Gstride); fq_nmod_mpoly_to_mpolyn_perm_deflate(Bn, nctx, B, ctx, I->brown_perm, I->Bmin_exp, I->Gstride); success = fq_nmod_mpolyn_gcd_brown_lgprime(Gn, Abarn, Bbarn, An, Bn, m - 1, nctx); } if (!success) goto cleanup; fq_nmod_mpoly_from_mpolyn_perm_inflate(G, I->Gbits, ctx, Gn, nctx, I->brown_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) fq_nmod_mpoly_from_mpolyn_perm_inflate(Abar, I->Abarbits, ctx, Abarn, nctx, I->brown_perm, I->Abarmin_exp, I->Gstride); if (Bbar != NULL) fq_nmod_mpoly_from_mpolyn_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarn, nctx, I->brown_perm, I->Bbarmin_exp, I->Gstride); success = 1; cleanup: fq_nmod_mpolyn_clear(An, nctx); fq_nmod_mpolyn_clear(Bn, nctx); fq_nmod_mpolyn_clear(Gn, nctx); fq_nmod_mpolyn_clear(Abarn, nctx); fq_nmod_mpolyn_clear(Bbarn, nctx); fq_nmod_mpoly_ctx_clear(nctx); return success; } /* Both A and B have to be packed into bits <= FLINT_BITS return is 1 for success, 0 for failure. */ static int _fq_nmod_mpoly_gcd_algo_small( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, /* could be NULL */ fq_nmod_mpoly_t Bbar, /* could be NULL */ const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); flint_bitcnt_t Abarbits = A->bits; flint_bitcnt_t Bbarbits = B->bits; slong v_in_both; slong v_in_either; slong v_in_A_only; slong v_in_B_only; slong j; slong nvars = ctx->minfo->nvars; mpoly_gcd_info_t I; #if FLINT_WANT_ASSERT fq_nmod_mpoly_t T, Asave, Bsave; #endif if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); else if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); #if FLINT_WANT_ASSERT fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_init(Asave, ctx); fq_nmod_mpoly_init(Bsave, ctx); fq_nmod_mpoly_set(Asave, A, ctx); fq_nmod_mpoly_set(Bsave, B, ctx); #endif mpoly_gcd_info_init(I, nvars); /* entries of I are all now invalid */ I->Gbits = Gbits; I->Abarbits = Abarbits; I->Bbarbits = Bbarbits; mpoly_gcd_info_limits(I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, A->exps, A->bits, A->length, ctx->minfo); mpoly_gcd_info_limits(I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, B->exps, B->bits, B->length, ctx->minfo); /* set ess(p) := p/term_content(p) */ /* check if the cofactors could be monomials, i.e. ess(A) == ess(B) */ for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] - I->Amin_exp[j] != I->Bmax_exp[j] - I->Bmin_exp[j]) goto skip_monomial_cofactors; } if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) { goto successful; } skip_monomial_cofactors: mpoly_gcd_info_stride(I->Gstride, A->exps, A->bits, A->length, I->Amax_exp, I->Amin_exp, B->exps, B->bits, B->length, I->Bmax_exp, I->Bmin_exp, ctx->minfo); for (j = 0; j < nvars; j++) { ulong t = I->Gstride[j]; if (t == 0) { FLINT_ASSERT(I->Amax_exp[j] == I->Amin_exp[j] || I->Bmax_exp[j] == I->Bmin_exp[j]); } else { FLINT_ASSERT((I->Amax_exp[j] - I->Amin_exp[j]) % t == 0); FLINT_ASSERT((I->Bmax_exp[j] - I->Bmin_exp[j]) % t == 0); } I->Adeflate_deg[j] = t == 0 ? 0 : (I->Amax_exp[j] - I->Amin_exp[j])/t; I->Bdeflate_deg[j] = t == 0 ? 0 : (I->Bmax_exp[j] - I->Bmin_exp[j])/t; t = FLINT_MIN(I->Amin_exp[j], I->Bmin_exp[j]); I->Gmin_exp[j] = t; I->Abarmin_exp[j] = I->Amin_exp[j] - t; I->Bbarmin_exp[j] = I->Bmin_exp[j] - t; } /* The following are now valid: I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, I->Gstride I->Adeflate_deg I->Bdeflate_deg I->Gmin_exp */ /* check if ess(A) and ess(B) have a variable v_in_both in common */ v_in_both = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_both = j; break; } } if (v_in_both == -WORD(1)) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } /* check if ess(A) and ess(B) depend on another variable v_in_either */ FLINT_ASSERT(0 <= v_in_both && v_in_both < nvars); v_in_either = -WORD(1); for (j = 0; j < nvars; j++) { if (j == v_in_both) continue; if (I->Amax_exp[j] > I->Amin_exp[j] || I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_either = j; break; } } if (v_in_either == -WORD(1)) { _do_univar(G, Abar, Bbar, A, B, v_in_both, I, ctx); goto successful; } /* check if there is a variable in ess(A) that is not in ess(B) */ v_in_A_only = -WORD(1); v_in_B_only = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] == I->Bmin_exp[j]) { v_in_A_only = j; break; } if (I->Bmax_exp[j] > I->Bmin_exp[j] && I->Amax_exp[j] == I->Amin_exp[j]) { v_in_B_only = j; break; } } if (v_in_A_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Abar, Bbar, v_in_A_only, A, I->Amin_exp[v_in_A_only], B, I->Bmin_exp[v_in_A_only], ctx); goto cleanup; } if (v_in_B_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Bbar, Abar, v_in_B_only, B, I->Bmin_exp[v_in_B_only], A, I->Amin_exp[v_in_B_only], ctx); goto cleanup; } /* all variable are now either missing from both ess(A) and ess(B), or present in both ess(A) and ess(B) and there are at least two in the latter case */ mpoly_gcd_info_set_estimates_fq_nmod_mpoly(I, A, B, ctx); if (!I->Gdeflate_deg_bounds_are_nice) mpoly_gcd_info_set_estimates_fq_nmod_mpoly_lgprime(I, A, B, ctx); mpoly_gcd_info_set_perm(I, A->length, B->length, ctx->minfo); /* everything in I is valid now */ /* check divisibility A/B and B/A */ { int gcd_is_trivial = 1; int try_a = I->Gdeflate_deg_bounds_are_nice; int try_b = I->Gdeflate_deg_bounds_are_nice; for (j = 0; j < nvars; j++) { if (I->Gdeflate_deg_bound[j] != 0) gcd_is_trivial = 0; if (I->Adeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_a = 0; if (I->Bdeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_b = 0; } if (gcd_is_trivial) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } if (try_a && _try_divides(G, Bbar, Abar, B, A, ctx)) goto successful; if (try_b && _try_divides(G, Abar, Bbar, A, B, ctx)) goto successful; } if (I->mvars < 3) { mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); algo &= (MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); if (algo == MPOLY_GCD_USE_BROWN) { success = _try_brown(G, Abar, Bbar, A, B, I, ctx); } else if (algo == MPOLY_GCD_USE_HENSEL) { success = _try_hensel(G, Abar, Bbar, A, B, I, ctx); } else { if (I->Adensity + I->Bdensity > 0.05) { success = _try_brown(G, Abar, Bbar, A, B, I, ctx) || _try_hensel(G, Abar, Bbar, A, B, I, ctx); } else { success = _try_hensel(G, Abar, Bbar, A, B, I, ctx) || _try_brown(G, Abar, Bbar, A, B, I, ctx); } } goto cleanup; } else if (algo == MPOLY_GCD_USE_HENSEL) { mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); success = _try_hensel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_BROWN) { mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); success = _try_brown(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL) { mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); success = _try_zippel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL2) { mpoly_gcd_info_measure_zippel2(I, A->length, B->length, ctx->minfo); success = _try_zippel2(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else { slong k; double density = I->Adensity + I->Bdensity; /* mpoly gcd case. Only rule is that measure_X must be called before try_X is called or I->X_perm is accessed. */ mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_zippel2(I, A->length, B->length, ctx->minfo); if (density > 0.08) { if (_try_brown(G, Abar, Bbar, A, B, I, ctx)) goto successful; } if (I->Adeflate_tdeg > 0 && I->Bdeflate_tdeg > 0) { fmpz_t x; double tdensity; fmpz_init(x); fmpz_bin_uiui(x, (ulong)I->Adeflate_tdeg + I->mvars, I->mvars); tdensity = A->length/fmpz_get_d(x); fmpz_bin_uiui(x, (ulong)I->Bdeflate_tdeg + I->mvars, I->mvars); tdensity += B->length/fmpz_get_d(x); density = FLINT_MAX(density, tdensity); fmpz_clear(x); } if (density > 0.05) { if (_try_hensel(G, Abar, Bbar, A, B, I, ctx)) goto successful; } k = I->zippel2_perm[1]; k = FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); if ((A->length + B->length)/64 < k) { if (_try_zippel(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_zippel2(G, Abar, Bbar, A, B, I, ctx)) goto successful; } else { if (_try_zippel2(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_zippel(G, Abar, Bbar, A, B, I, ctx)) goto successful; } success = _try_hensel(G, Abar, Bbar, A, B, I, ctx) || _try_brown(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } success = 0; goto cleanup; successful: success = 1; cleanup: mpoly_gcd_info_clear(I); if (success) { FLINT_ASSERT(G->length > 0); if (!n_fq_is_one(G->coeffs + 0, ctx->fqctx)) { if (Abar != NULL) fq_nmod_mpoly_scalar_mul_n_fq(Abar, Abar, G->coeffs + 0, ctx); if (Bbar != NULL) fq_nmod_mpoly_scalar_mul_n_fq(Bbar, Bbar, G->coeffs + 0, ctx); fq_nmod_mpoly_make_monic(G, G, ctx); } FLINT_ASSERT(fq_nmod_mpoly_divides(T, Asave, G, ctx)); FLINT_ASSERT(Abar == NULL || fq_nmod_mpoly_equal(T, Abar, ctx)); FLINT_ASSERT(fq_nmod_mpoly_divides(T, Bsave, G, ctx)); FLINT_ASSERT(Bbar == NULL || fq_nmod_mpoly_equal(T, Bbar, ctx)); } #if FLINT_WANT_ASSERT fq_nmod_mpoly_clear(T, ctx); fq_nmod_mpoly_clear(Asave, ctx); fq_nmod_mpoly_clear(Bsave, ctx); #endif return success; } /* The gcd calculation is unusual. First see if both inputs fit into FLINT_BITS. Then, try deflation as a last resort. */ static int _fq_nmod_mpoly_gcd_algo_large( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong k; fmpz * Ashift, * Astride; fmpz * Bshift, * Bstride; fmpz * Gshift, * Gstride; fq_nmod_mpoly_t Anew, Bnew; const fq_nmod_mpoly_struct * Ause, * Buse; if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) return 1; fq_nmod_mpoly_init(Anew, ctx); fq_nmod_mpoly_init(Bnew, ctx); Ause = A; if (A->bits > FLINT_BITS) { if (!fq_nmod_mpoly_repack_bits(Anew, A, FLINT_BITS, ctx)) goto could_not_repack; Ause = Anew; } Buse = B; if (B->bits > FLINT_BITS) { if (!fq_nmod_mpoly_repack_bits(Bnew, B, FLINT_BITS, ctx)) goto could_not_repack; Buse = Bnew; } success = _fq_nmod_mpoly_gcd_algo_small(G, Abar, Bbar, Ause, Buse, ctx, algo); goto cleanup; could_not_repack: /* One of A or B could not be repacked into FLINT_BITS. See if they both fit into FLINT_BITS after deflation. */ Ashift = _fmpz_vec_init(ctx->minfo->nvars); Astride = _fmpz_vec_init(ctx->minfo->nvars); Bshift = _fmpz_vec_init(ctx->minfo->nvars); Bstride = _fmpz_vec_init(ctx->minfo->nvars); Gshift = _fmpz_vec_init(ctx->minfo->nvars); Gstride = _fmpz_vec_init(ctx->minfo->nvars); fq_nmod_mpoly_deflation(Ashift, Astride, A, ctx); fq_nmod_mpoly_deflation(Bshift, Bstride, B, ctx); _fmpz_vec_min(Gshift, Ashift, Bshift, ctx->minfo->nvars); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_gcd(Gstride + k, Astride + k, Bstride + k); } fq_nmod_mpoly_deflate(Anew, A, Ashift, Gstride, ctx); if (Anew->bits > FLINT_BITS) { success = fq_nmod_mpoly_repack_bits(Anew, Anew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } fq_nmod_mpoly_deflate(Bnew, B, Bshift, Gstride, ctx); if (Bnew->bits > FLINT_BITS) { success = fq_nmod_mpoly_repack_bits(Bnew, Bnew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } success = _fq_nmod_mpoly_gcd_algo(G, Abar, Bbar, Anew, Bnew, ctx, algo); if (!success) goto deflate_cleanup; for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_sub(Ashift + k, Ashift + k, Gshift + k); fmpz_sub(Bshift + k, Bshift + k, Gshift + k); FLINT_ASSERT(fmpz_sgn(Ashift + k) >= 0); FLINT_ASSERT(fmpz_sgn(Bshift + k) >= 0); } fq_nmod_mpoly_inflate(G, G, Gshift, Gstride, ctx); if (Abar != NULL) fq_nmod_mpoly_inflate(Abar, Abar, Ashift, Gstride, ctx); if (Bbar != NULL) fq_nmod_mpoly_inflate(Bbar, Bbar, Bshift, Gstride, ctx); FLINT_ASSERT(G->length > 0); if (!n_fq_is_one(G->coeffs + 0, ctx->fqctx)) { if (Abar != NULL) fq_nmod_mpoly_scalar_mul_n_fq(Abar, Abar, G->coeffs + 0, ctx); if (Bbar != NULL) fq_nmod_mpoly_scalar_mul_n_fq(Bbar, Bbar, G->coeffs + 0, ctx); fq_nmod_mpoly_make_monic(G, G, ctx); } fq_nmod_mpoly_make_monic(G, G, ctx); deflate_cleanup: _fmpz_vec_clear(Ashift, ctx->minfo->nvars); _fmpz_vec_clear(Astride, ctx->minfo->nvars); _fmpz_vec_clear(Bshift, ctx->minfo->nvars); _fmpz_vec_clear(Bstride, ctx->minfo->nvars); _fmpz_vec_clear(Gshift, ctx->minfo->nvars); _fmpz_vec_clear(Gstride, ctx->minfo->nvars); cleanup: fq_nmod_mpoly_clear(Anew, ctx); fq_nmod_mpoly_clear(Bnew, ctx); return success; } int _fq_nmod_mpoly_gcd_algo( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { FLINT_ASSERT(!fq_nmod_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!fq_nmod_mpoly_is_zero(B, ctx)); if (A->bits <= FLINT_BITS && B->bits <= FLINT_BITS) return _fq_nmod_mpoly_gcd_algo_small(G, Abar, Bbar, A, B, ctx, algo); else return _fq_nmod_mpoly_gcd_algo_large(G, Abar, Bbar, A, B, ctx, algo); } int fq_nmod_mpoly_gcd( fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_is_zero(A, ctx)) { if (fq_nmod_mpoly_is_zero(B, ctx)) fq_nmod_mpoly_zero(G, ctx); else fq_nmod_mpoly_make_monic(G, B, ctx); return 1; } if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_make_monic(G, A, ctx); return 1; } return _fq_nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/fq_nmod_mpoly/gcd_brown.c000066400000000000000000000014141461254215100203750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_gcd_brown( fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_is_zero(A, ctx) || fq_nmod_mpoly_is_zero(B, ctx)) return fq_nmod_mpoly_gcd(G, A, B, ctx); return _fq_nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_BROWN); } flint-3.1.3/src/fq_nmod_mpoly/gcd_cofactors.c000066400000000000000000000032611461254215100212330ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_gcd_cofactors( fq_nmod_mpoly_t G, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_is_zero(A, ctx)) { if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_zero(G, ctx); fq_nmod_mpoly_zero(Abar, ctx); fq_nmod_mpoly_zero(Bbar, ctx); return 1; } fq_nmod_mpoly_set(G, B, ctx); fq_nmod_mpoly_zero(Abar, ctx); fq_nmod_mpoly_one(Bbar, ctx); if (!n_fq_is_one(G->coeffs + 0, ctx->fqctx)) { fq_nmod_mpoly_scalar_mul_n_fq(Bbar, Bbar, G->coeffs + 0, ctx); fq_nmod_mpoly_make_monic(G, G, ctx); } return 1; } if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_set(G, A, ctx); fq_nmod_mpoly_zero(Bbar, ctx); fq_nmod_mpoly_one(Abar, ctx); if (!n_fq_is_one(G->coeffs + 0, ctx->fqctx)) { fq_nmod_mpoly_scalar_mul_n_fq(Abar, Abar, G->coeffs + 0, ctx); fq_nmod_mpoly_make_monic(G, G, ctx); } return 1; } return _fq_nmod_mpoly_gcd_algo(G, Abar, Bbar, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/fq_nmod_mpoly/gcd_hensel.c000066400000000000000000000321731461254215100205320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" #include "fq_nmod_mpoly_factor.h" /* in F[x_1, ..., x_n][X]: cont_X(A) = cont_X(B) = 1 compute gamma = gcd(lc_X(A), lc_X(B)) try to find evaluation point x_i -> alpha_i a = A(x_i = alpha_i) in F[X] b = B(x_i = alpha_i) in F[X] compute univariate a = g*abar, b = g*bbar try to find mu1, mu2 in F with gcd(g, mu1*abar + mu2*bbar) = 1 set H = mu1*A + mu2*B lift the univariate factorization g * (mu1*abar + mu2*bbar) against gamma*H imposing (gamma, lc_X H) as the leading coefficients remove content from the lift of g to get G and divide to get Abar and Bbar */ int fq_nmod_mpolyl_gcd_hensel_smprime( fq_nmod_mpoly_t G, slong Gdeg, fq_nmod_mpoly_t Abar, fq_nmod_mpoly_t Bbar, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success, alphas_tries_remaining, gamma_is_one; const slong n = ctx->minfo->nvars - 1; slong i, k; flint_bitcnt_t bits = A->bits; fq_nmod_struct * alphas; fq_nmod_t mu1, mu2; fq_nmod_mpoly_struct * Aevals, * Bevals, * Hevals; fq_nmod_mpoly_struct * H; /* points to A, B, or Hevals + n */ fq_nmod_mpoly_struct * Glcs, * Hlcs; fq_nmod_mpoly_struct Hfac[2], Htfac[2]; slong * Hdegs; slong Adegx, Bdegx, gdegx; fq_nmod_mpoly_t t1, t2, g, abar, bbar, hbar; flint_rand_t state; mp_limb_t * tmp, * q; FLINT_ASSERT(n > 0); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); flint_randinit(state); tmp = FLINT_ARRAY_ALLOC(d*(N_FQ_MUL_INV_ITCH + 1), mp_limb_t); q = tmp + d*N_FQ_MUL_INV_ITCH; fq_nmod_init(mu1, ctx->fqctx); fq_nmod_init(mu2, ctx->fqctx); Hdegs = FLINT_ARRAY_ALLOC(n + 1, slong); Glcs = FLINT_ARRAY_ALLOC(3*(n + 1), fq_nmod_mpoly_struct); Hlcs = Glcs + (n + 1); Hevals = Hlcs + (n + 1); for (i = 0; i < n + 1; i++) { fq_nmod_mpoly_init(Glcs + i, ctx); fq_nmod_mpoly_init(Hlcs + i, ctx); fq_nmod_mpoly_init(Hevals + i, ctx); } alphas = FLINT_ARRAY_ALLOC(n, fq_nmod_struct); Aevals = FLINT_ARRAY_ALLOC(2*(n + 1), fq_nmod_mpoly_struct); Bevals = Aevals + (n + 1); for (i = 0; i < n; i++) { fq_nmod_init(alphas + i, ctx->fqctx); fq_nmod_mpoly_init(Aevals + i, ctx); fq_nmod_mpoly_init(Bevals + i, ctx); } fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(hbar, ctx); fq_nmod_mpoly_init(Hfac + 0, ctx); fq_nmod_mpoly_init(Hfac + 1, ctx); fq_nmod_mpoly_init(Htfac + 0, ctx); fq_nmod_mpoly_init(Htfac + 1, ctx); /* init done */ alphas_tries_remaining = 10; /* try all zeros first */ for (i = 0; i < n; i++) fq_nmod_zero(alphas + i, ctx->fqctx); goto got_alpha; next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) fq_nmod_rand(alphas + i, state, ctx->fqctx); got_alpha: /* ensure deg_X do not drop under evaluation */ Adegx = fq_nmod_mpoly_degree_si(A, 0, ctx); Bdegx = fq_nmod_mpoly_degree_si(B, 0, ctx); for (i = n - 1; i >= 0; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alphas + i, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + i, i == n - 1 ? B : Bevals + i + 1, i + 1, alphas + i, ctx); if (Adegx != fq_nmod_mpoly_degree_si(Aevals + i, 0, ctx) || Bdegx != fq_nmod_mpoly_degree_si(Bevals + i, 0, ctx)) { goto next_alpha; } } /* univariate gcd */ success = fq_nmod_mpoly_gcd_cofactors(g, abar, bbar, Aevals + 0, Bevals + 0, ctx) && fq_nmod_mpoly_gcd(t1, g, abar, ctx) && fq_nmod_mpoly_gcd(t2, g, bbar, ctx); if (!success) goto cleanup; gdegx = fq_nmod_mpoly_degree_si(g, 0, ctx); if (gdegx == 0) { fq_nmod_mpoly_set(Abar, A, ctx); fq_nmod_mpoly_set(Bbar, B, ctx); fq_nmod_mpoly_one(G, ctx); success = 1; goto cleanup; } else if (gdegx > Gdeg) { goto next_alpha; } else if (gdegx < Gdeg) { Gdeg = gdegx; goto next_alpha; } /* the degbound gdegx (== Gdeg) has at least two witnesses now */ if (gdegx == Adegx) { if (fq_nmod_mpoly_divides(Bbar, B, A, ctx)) { fq_nmod_mpoly_set(G, A, ctx); fq_nmod_mpoly_one(Abar, ctx); success = 1; goto cleanup; } goto next_alpha; } else if (gdegx == Bdegx) { if (fq_nmod_mpoly_divides(Abar, A, B, ctx)) { fq_nmod_mpoly_set(G, B, ctx); fq_nmod_mpoly_one(Bbar, ctx); success = 1; goto cleanup; } goto next_alpha; } FLINT_ASSERT(0 < gdegx && gdegx < FLINT_MIN(Adegx, Bdegx)); /* set Hlcs[n], Glcs[n] (gamma), H, and Hevals */ if (fq_nmod_mpoly_is_one(t1, ctx)) { fq_nmod_one(mu1, ctx->fqctx); fq_nmod_zero(mu2, ctx->fqctx); fq_nmod_mpoly_swap(hbar, abar, ctx); fq_nmod_mpolyl_lead_coeff(Hlcs + n, A, 1, ctx); fq_nmod_mpolyl_lead_coeff(t2, B, 1, ctx); success = fq_nmod_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fq_nmod_mpoly_struct *) A; gamma_is_one = fq_nmod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fq_nmod_mpoly_swap(Hevals + i, Aevals + i, ctx); } else if (fq_nmod_mpoly_is_one(t2, ctx)) { fq_nmod_zero(mu1, ctx->fqctx); fq_nmod_one(mu2, ctx->fqctx); fq_nmod_mpoly_swap(hbar, bbar, ctx); fq_nmod_mpolyl_lead_coeff(Hlcs + n, B, 1, ctx); fq_nmod_mpolyl_lead_coeff(t2, A, 1, ctx); success = fq_nmod_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fq_nmod_mpoly_struct *) B; gamma_is_one = fq_nmod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fq_nmod_mpoly_swap(Hevals + i, Bevals + i, ctx); } else { int mu_tries_remaining = 10; next_mu: if (--mu_tries_remaining < 0) { success = 0; goto cleanup; } fq_nmod_one(mu1, ctx->fqctx); fq_nmod_rand_not_zero(mu2, state, ctx->fqctx); fq_nmod_mpoly_scalar_addmul_fq_nmod(hbar, abar, bbar, mu2, ctx); /* make sure the linear combo did not drop degree */ if (fq_nmod_mpoly_degree_si(hbar, 0, ctx) != FLINT_MAX(Adegx, Bdegx) - gdegx) goto next_mu; /* make sure the linear combo is prime to g */ success = fq_nmod_mpoly_gcd(t1, hbar, g, ctx); if (!success) goto cleanup; if (!fq_nmod_mpoly_is_one(t1, ctx)) goto next_mu; fq_nmod_mpolyl_lead_coeff(t1, A, 1, ctx); fq_nmod_mpolyl_lead_coeff(t2, B, 1, ctx); success = fq_nmod_mpoly_gcd(Glcs + n, t1, t2, ctx); if (!success) goto cleanup; H = Hevals + n; fq_nmod_mpoly_scalar_addmul_fq_nmod(H, A, B, mu2, ctx); fq_nmod_mpolyl_lead_coeff(Hlcs + n, H, 1, ctx); gamma_is_one = fq_nmod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fq_nmod_mpoly_scalar_addmul_fq_nmod(Hevals + i, Aevals + i, Bevals + i, mu2, ctx); } if (!gamma_is_one) { fq_nmod_mpoly_mul(Hevals + n, H, Glcs + n, ctx); H = Hevals + n; for (i = n - 1; i >= 0; i--) fq_nmod_mpoly_evaluate_one_fq_nmod(Hevals + i, Hevals + i + 1, i + 1, alphas + i, ctx); } success = H->bits <= FLINT_BITS || fq_nmod_mpoly_repack_bits_inplace(H, FLINT_BITS, ctx); if (!success) goto cleanup; /* the evals should all fit in H->bits */ for (i = 0; i < n; i++) fq_nmod_mpoly_repack_bits_inplace(Hevals + i, H->bits, ctx); fq_nmod_mpoly_degrees_si(Hdegs, H, ctx); /* computed evaluated leading coeffs */ for (i = n - 1; i >= 0; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Glcs + i, Glcs + i + 1, i + 1, alphas + i, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Hlcs + i, Hlcs + i + 1, i + 1, alphas + i, ctx); /* evaluation could have killed gamma */ if (fq_nmod_mpoly_is_zero(Glcs + i, ctx) || fq_nmod_mpoly_is_zero(Hlcs + i, ctx)) { goto next_alpha; } } /* make the leading coefficients match Glcs[0], Hlcs[0] */ FLINT_ASSERT(fq_nmod_mpoly_is_fq_nmod(Glcs + 0, ctx) && Glcs[0].length == 1); FLINT_ASSERT(fq_nmod_mpoly_is_fq_nmod(Hlcs + 0, ctx) && Hlcs[0].length == 1); _n_fq_inv(q, g->coeffs + 0, ctx->fqctx, tmp); _n_fq_mul(q, q, Glcs[0].coeffs + 0, ctx->fqctx, tmp); fq_nmod_mpoly_scalar_mul_n_fq(Hfac + 0, g, q, ctx); _n_fq_inv(q, hbar->coeffs + 0, ctx->fqctx, tmp); _n_fq_mul(q, q, Hlcs[0].coeffs + 0, ctx->fqctx, tmp); fq_nmod_mpoly_scalar_mul_n_fq(Hfac + 1, hbar, q, ctx); for (k = 1; k <= n; k++) { _fq_nmod_mpoly_set_lead0(Htfac + 0, Hfac + 0, Glcs + k, ctx); _fq_nmod_mpoly_set_lead0(Htfac + 1, Hfac + 1, Hlcs + k, ctx); success = fq_nmod_mpoly_hlift(k, Htfac, 2, alphas, k < n ? Hevals + k : H, Hdegs, ctx); if (!success) goto next_alpha; fq_nmod_mpoly_swap(Hfac + 0, Htfac + 0, ctx); fq_nmod_mpoly_swap(Hfac + 1, Htfac + 1, ctx); } success = fq_nmod_mpolyl_content(t1, Hfac + 0, 1, ctx); if (!success) goto cleanup; success = fq_nmod_mpoly_divides(G, Hfac + 0, t1, ctx); FLINT_ASSERT(success); if (fq_nmod_is_zero(mu2, ctx->fqctx)) { FLINT_ASSERT(fq_nmod_is_one(mu1, ctx->fqctx)); /* the division by t1 should succeed, but let's be careful */ fq_nmod_mpolyl_lead_coeff(t1, G, 1, ctx); success = fq_nmod_mpoly_divides(Abar, Hfac + 1, t1, ctx) && fq_nmod_mpoly_divides(Bbar, B, G, ctx); } else if (fq_nmod_is_zero(mu1, ctx->fqctx)) { FLINT_ASSERT(fq_nmod_is_one(mu2, ctx->fqctx)); /* ditto */ fq_nmod_mpolyl_lead_coeff(t1, G, 1, ctx); success = fq_nmod_mpoly_divides(Bbar, Hfac + 1, t1, ctx) && fq_nmod_mpoly_divides(Abar, A, G, ctx); } else { FLINT_ASSERT(fq_nmod_is_one(mu1, ctx->fqctx)); success = fq_nmod_mpoly_divides(Abar, A, G, ctx) && fq_nmod_mpoly_divides(Bbar, B, G, ctx); } if (!success) goto next_alpha; success = 1; cleanup: flint_randclear(state); flint_free(tmp); fq_nmod_clear(mu1, ctx->fqctx); fq_nmod_clear(mu2, ctx->fqctx); flint_free(Hdegs); for (i = 0; i < n + 1; i++) { fq_nmod_mpoly_clear(Glcs + i, ctx); fq_nmod_mpoly_clear(Hlcs + i, ctx); fq_nmod_mpoly_clear(Hevals + i, ctx); } flint_free(Glcs); for (i = 0; i < n; i++) { fq_nmod_clear(alphas + i, ctx->fqctx); fq_nmod_mpoly_clear(Aevals + i, ctx); fq_nmod_mpoly_clear(Bevals + i, ctx); } flint_free(alphas); flint_free(Aevals); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(hbar, ctx); fq_nmod_mpoly_clear(Hfac + 0, ctx); fq_nmod_mpoly_clear(Hfac + 1, ctx); fq_nmod_mpoly_clear(Htfac + 0, ctx); fq_nmod_mpoly_clear(Htfac + 1, ctx); if (success) { fq_nmod_mpoly_repack_bits_inplace(G, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(Abar, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(Bbar, bits, ctx); } return success; } /* should find its way back here in interesting cases */ int fq_nmod_mpoly_gcd_hensel( fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_is_zero(A, ctx) || fq_nmod_mpoly_is_zero(B, ctx)) return fq_nmod_mpoly_gcd(G, A, B, ctx); return _fq_nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_HENSEL); } flint-3.1.3/src/fq_nmod_mpoly/gcd_zippel.c000066400000000000000000000362171461254215100205620ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpolyu_gcdm_zippel_bivar( fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { slong var = 0; slong Alastdeg, Blastdeg; slong bound; slong lastdeg; int success = 0, changed, have_enough; fq_nmod_mpolyun_t An, Bn, H, Ht; fq_nmod_poly_t modulus, gamma, hc, tmp1, tmp2; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx; fq_nmod_mpolyu_t Aeval, Beval, Geval; fq_nmod_t t, geval; FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(Abar->bits == A->bits); FLINT_ASSERT(Bbar->bits == A->bits); FLINT_ASSERT(B->bits == A->bits); fq_nmod_mpolyun_init(An, A->bits, ctx); fq_nmod_mpolyun_init(Bn, A->bits, ctx); fq_nmod_mpolyu_cvtto_mpolyun(An, A, var, ctx); fq_nmod_mpolyu_cvtto_mpolyun(Bn, B, var, ctx); FLINT_ASSERT(An->bits == B->bits); FLINT_ASSERT(An->bits == G->bits); FLINT_ASSERT(An->length > 0); FLINT_ASSERT(Bn->length > 0); FLINT_ASSERT(An->exps[A->length - 1] == 0); FLINT_ASSERT(Bn->exps[B->length - 1] == 0); fq_nmod_poly_init(tmp1, ctx->fqctx); fq_nmod_poly_init(tmp2, ctx->fqctx); fq_nmod_poly_init(gamma, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp1, fq_nmod_mpolyun_leadcoeff_poly(An, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp2, fq_nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->fqctx); fq_nmod_poly_gcd(gamma, tmp1, tmp2, ctx->fqctx); /* bound on the number of images */ Alastdeg = fq_nmod_mpolyun_lastdeg(An, ctx); Blastdeg = fq_nmod_mpolyun_lastdeg(Bn, ctx); bound = 1 + fq_nmod_poly_degree(gamma, ctx->fqctx) + FLINT_MIN(Alastdeg, Blastdeg); fq_nmod_poly_init(hc, ctx->fqctx); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_poly_one(modulus, ctx->fqctx); fq_nmod_mpolyun_init(H, A->bits, ctx); fq_nmod_mpolyun_init(Ht, A->bits, ctx); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx, ctx, randstate); /* Once Aeval, Beval, ..., t are inited in ectx->fqctx, they do not need to be cleared and reinited when ectx->fqctx changes. */ fq_nmod_mpolyu_init(Aeval, A->bits, ectx); fq_nmod_mpolyu_init(Beval, A->bits, ectx); fq_nmod_mpolyu_init(Geval, A->bits, ectx); fq_nmod_init(geval, ectx->fqctx); fq_nmod_init(t, ectx->fqctx); /* initialization already picked a prime */ goto have_prime; choose_prime_outer: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, randstate); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto finished; } have_prime: FLINT_ASSERT(cur_emb != NULL); /* make sure reduction does not kill both lc(A) and lc(B) */ bad_fq_nmod_embed_sm_to_lg(geval, gamma, cur_emb); if (fq_nmod_is_zero(geval, ectx->fqctx)) goto choose_prime_outer; /* make sure reduction does not kill either A or B */ fq_nmod_mpolyun_interp_reduce_lg_mpolyu(Aeval, An, ectx, ctx, cur_emb); fq_nmod_mpolyun_interp_reduce_lg_mpolyu(Beval, Bn, ectx, ctx, cur_emb); if (Aeval->length == 0 || Beval->length == 0) goto choose_prime_outer; FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Aeval, ectx)); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Beval, ectx)); fq_nmod_mpolyu_gcdp_zippel_univar_no_cofactors(Geval, Aeval, Beval, ectx); if (fq_nmod_mpolyu_is_one(Geval, ectx)) { fq_nmod_mpolyu_one(G, ctx); fq_nmod_mpolyu_swap(Abar, A, ctx); fq_nmod_mpolyu_swap(Bbar, B, ctx); success = 1; goto finished; } FLINT_ASSERT(Geval->length > 0); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { if (Geval->exps[0] > H->exps[0]) { goto choose_prime_outer; } else if (Geval->exps[0] < H->exps[0]) { fq_nmod_poly_one(modulus, ctx->fqctx); } } n_fq_get_fq_nmod(t, fq_nmod_mpolyu_leadcoeff(Geval, ectx), ectx->fqctx); fq_nmod_inv(t, t, ectx->fqctx); fq_nmod_mul(t, t, geval, ectx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Geval, t, ectx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { changed = fq_nmod_mpolyun_interp_crt_lg_mpolyu(&lastdeg, H, Ht, modulus, ctx, Geval, ectx, cur_emb); fq_nmod_poly_mul(modulus, modulus, cur_emb->h, ctx->fqctx); have_enough = fq_nmod_poly_degree(modulus, ctx->fqctx) >= bound; if (changed && !have_enough) { goto choose_prime_outer; } if (!changed || have_enough) { fq_nmod_mpolyun_content_poly(hc, H, ctx); fq_nmod_mpolyun_divexact_poly(Ht, H, hc, ctx); fq_nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( fq_nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && fq_nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { fq_nmod_poly_one(modulus, ctx->fqctx); goto choose_prime_outer; } } else { fq_nmod_mpolyun_interp_lift_lg_mpolyu(H, ctx, Geval, ectx, cur_emb); fq_nmod_poly_set(modulus, cur_emb->h, ctx->fqctx); } goto choose_prime_outer; finished: fq_nmod_poly_clear(tmp1, ctx->fqctx); fq_nmod_poly_clear(tmp2, ctx->fqctx); fq_nmod_poly_clear(gamma, ctx->fqctx); fq_nmod_poly_clear(hc, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_mpolyun_clear(An, ctx); fq_nmod_mpolyun_clear(Bn, ctx); fq_nmod_mpolyun_clear(H, ctx); fq_nmod_mpolyun_clear(Ht, ctx); fq_nmod_mpolyu_clear(Aeval, ectx); fq_nmod_mpolyu_clear(Beval, ectx); fq_nmod_mpolyu_clear(Geval, ectx); fq_nmod_clear(geval, ectx->fqctx); fq_nmod_clear(t, ectx->fqctx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx, ctx, randstate); return success; } int fq_nmod_mpolyu_gcdm_zippel( fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { slong degbound; slong bound; slong Alastdeg, Blastdeg; slong lastdeg; int success, changed, have_enough; fq_nmod_mpolyun_t An, Bn, Hn, Ht; fq_nmod_poly_t modulus, gamma, hc, tmp1, tmp2; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx; fq_nmod_mpolyu_t Aeval, Beval, Geval, Abareval, Bbareval, Gform; fq_nmod_t t, gammaeval; FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(B->bits == A->bits); success = fq_nmod_mpolyu_gcdp_zippel(G, Abar, Bbar, A, B, ctx->minfo->nvars - 1, ctx, randstate); if (success) { return 1; } /* bivariate more comfortable separated */ if (ctx->minfo->nvars == 1) { return fq_nmod_mpolyu_gcdm_zippel_bivar(G, Abar, Bbar, A, B, ctx, randstate); } FLINT_ASSERT(ctx->minfo->nvars > 1); fq_nmod_poly_init(hc, ctx->fqctx); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_mpolyun_init(An, A->bits, ctx); fq_nmod_mpolyun_init(Bn, A->bits, ctx); fq_nmod_mpolyu_cvtto_mpolyun(An, A, ctx->minfo->nvars - 1, ctx); fq_nmod_mpolyu_cvtto_mpolyun(Bn, B, ctx->minfo->nvars - 1, ctx); FLINT_ASSERT(An->bits == A->bits); FLINT_ASSERT(Bn->bits == A->bits); FLINT_ASSERT(An->length > 0); FLINT_ASSERT(Bn->length > 0); FLINT_ASSERT(An->exps[A->length - 1] == 0); FLINT_ASSERT(Bn->exps[B->length - 1] == 0); fq_nmod_poly_init(tmp1, ctx->fqctx); fq_nmod_poly_init(tmp2, ctx->fqctx); fq_nmod_poly_init(gamma, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp1, fq_nmod_mpolyun_leadcoeff_poly(An, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp2, fq_nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->fqctx); fq_nmod_poly_gcd(gamma, tmp1, tmp2, ctx->fqctx); /* bound on the number of images */ Alastdeg = fq_nmod_mpolyun_lastdeg(An, ctx); Blastdeg = fq_nmod_mpolyun_lastdeg(Bn, ctx); bound = 1 + fq_nmod_poly_degree(gamma, ctx->fqctx) + FLINT_MIN(Alastdeg, Blastdeg); /* degree bound on the gcd */ degbound = FLINT_MIN(A->exps[0], B->exps[0]); fq_nmod_poly_one(modulus, ctx->fqctx); fq_nmod_mpolyun_init(Hn, A->bits, ctx); fq_nmod_mpolyun_init(Ht, A->bits, ctx); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx, ctx, randstate); /* Once Aeval, Beval, ..., t are inited in ectx->fqctx, they do not need to be cleared and reinited when ectx->fqctx changes. */ fq_nmod_mpolyu_init(Aeval, A->bits, ectx); fq_nmod_mpolyu_init(Beval, A->bits, ectx); fq_nmod_mpolyu_init(Geval, A->bits, ectx); fq_nmod_mpolyu_init(Abareval, A->bits, ectx); fq_nmod_mpolyu_init(Bbareval, A->bits, ectx); fq_nmod_mpolyu_init(Gform, A->bits, ectx); fq_nmod_init(gammaeval, ectx->fqctx); fq_nmod_init(t, ectx->fqctx); /* initialization already picked a prime */ goto have_prime; choose_prime_outer: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, randstate); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto finished; } have_prime: FLINT_ASSERT(cur_emb != NULL); /* make sure reduction does not kill both lc(A) and lc(B) */ bad_fq_nmod_embed_sm_to_lg(gammaeval, gamma, cur_emb); if (fq_nmod_is_zero(gammaeval, ectx->fqctx)) { goto choose_prime_outer; } /* make sure reduction does not kill either A or B */ fq_nmod_mpolyun_interp_reduce_lg_mpolyu(Aeval, An, ectx, ctx, cur_emb); fq_nmod_mpolyun_interp_reduce_lg_mpolyu(Beval, Bn, ectx, ctx, cur_emb); if (Aeval->length == 0 || Beval->length == 0) goto choose_prime_outer; FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Aeval, ectx)); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Beval, ectx)); success = fq_nmod_mpolyu_gcdp_zippel(Geval, Abareval, Bbareval, Aeval, Beval, ctx->minfo->nvars - 2, ectx, randstate); FLINT_ASSERT(!success || Geval->length > 0); if (!success || Geval->exps[0] > degbound) goto choose_prime_outer; degbound = Geval->exps[0]; if (Geval->length == 1 && Geval->exps[0] == 0) { FLINT_ASSERT(fq_nmod_mpoly_is_one(Geval->coeffs + 0, ectx)); FLINT_ASSERT(!fq_nmod_mpoly_is_zero(Geval->coeffs + 0, ectx)); fq_nmod_mpolyu_one(G, ctx); fq_nmod_mpolyu_swap(Abar, A, ctx); fq_nmod_mpolyu_swap(Bbar, B, ctx); success = 1; goto finished; } n_fq_get_fq_nmod(t, fq_nmod_mpolyu_leadcoeff(Geval, ectx), ectx->fqctx); fq_nmod_inv(t, t, ectx->fqctx); fq_nmod_mul(t, t, gammaeval, ectx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Geval, t, ectx); fq_nmod_mpolyu_setform(Gform, Geval, ectx); fq_nmod_mpolyun_interp_lift_lg_mpolyu(Hn, ctx, Geval, ectx, cur_emb); fq_nmod_poly_set(modulus, cur_emb->h, ctx->fqctx); choose_prime_inner: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, randstate); if (cur_emb == NULL) { success = 0; goto finished; } /* make sure reduction does not kill both lc(A) and lc(B) */ bad_fq_nmod_embed_sm_to_lg(gammaeval, gamma, cur_emb); if (fq_nmod_is_zero(gammaeval, ectx->fqctx)) goto choose_prime_inner; /* make sure reduction does not kill either A or B */ fq_nmod_mpolyun_interp_reduce_lg_mpolyu(Aeval, An, ectx, ctx, cur_emb); fq_nmod_mpolyun_interp_reduce_lg_mpolyu(Beval, Bn, ectx, ctx, cur_emb); if (Aeval->length == 0 || Beval->length == 0) goto choose_prime_inner; switch (fq_nmod_mpolyu_gcds_zippel(Geval, Aeval, Beval, Gform, ctx->minfo->nvars - 1, ectx, randstate, °bound)) { default: FLINT_ASSERT(0); case nmod_gcds_form_main_degree_too_high: case nmod_gcds_form_wrong: case nmod_gcds_no_solution: goto choose_prime_outer; case nmod_gcds_scales_not_found: case nmod_gcds_eval_point_not_found: case nmod_gcds_eval_gcd_deg_too_high: goto choose_prime_inner; case nmod_gcds_success: break; } n_fq_get_fq_nmod(t, fq_nmod_mpolyu_leadcoeff(Geval, ectx), ectx->fqctx); if (fq_nmod_is_zero(t, ectx->fqctx)) { goto choose_prime_inner; } fq_nmod_inv(t, t, ectx->fqctx); fq_nmod_mul(t, t, gammaeval, ectx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Geval, t, ectx); changed = fq_nmod_mpolyun_interp_mcrt_lg_mpolyu(&lastdeg, Hn, ctx, modulus, Geval, ectx, cur_emb); fq_nmod_poly_mul(modulus, modulus, cur_emb->h, ctx->fqctx); have_enough = fq_nmod_poly_degree(modulus, ctx->fqctx) >= bound; if (changed && !have_enough) { goto choose_prime_inner; } if (!changed || have_enough) { fq_nmod_mpolyun_content_poly(hc, Hn, ctx); fq_nmod_mpolyun_divexact_poly(Ht, Hn, hc, ctx); fq_nmod_mpolyu_cvtfrom_mpolyun(G, Ht, ctx->minfo->nvars - 1, ctx); if ( fq_nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && fq_nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { fq_nmod_poly_one(modulus, ctx->fqctx); goto choose_prime_outer; } goto choose_prime_inner; finished: fq_nmod_poly_clear(tmp1, ctx->fqctx); fq_nmod_poly_clear(tmp2, ctx->fqctx); fq_nmod_poly_clear(gamma, ctx->fqctx); fq_nmod_poly_clear(hc, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_mpolyun_clear(An, ctx); fq_nmod_mpolyun_clear(Bn, ctx); fq_nmod_mpolyun_clear(Hn, ctx); fq_nmod_mpolyun_clear(Ht, ctx); fq_nmod_mpolyu_clear(Aeval, ectx); fq_nmod_mpolyu_clear(Beval, ectx); fq_nmod_mpolyu_clear(Geval, ectx); fq_nmod_mpolyu_clear(Abareval, ectx); fq_nmod_mpolyu_clear(Bbareval, ectx); fq_nmod_mpolyu_clear(Gform, ectx); fq_nmod_clear(gammaeval, ectx->fqctx); fq_nmod_clear(t, ectx->fqctx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx, ctx, randstate); return success; } /* should find its way back here in interesting cases */ int fq_nmod_mpoly_gcd_zippel( fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_is_zero(A, ctx) || fq_nmod_mpoly_is_zero(B, ctx)) return fq_nmod_mpoly_gcd(G, A, B, ctx); return _fq_nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL); } flint-3.1.3/src/fq_nmod_mpoly/gcd_zippel2.c000066400000000000000000002564061461254215100206500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" #include "fq_nmod_mpoly_factor.h" #if FLINT_WANT_ASSERT # include "fq_nmod_poly.h" #endif void _fq_nmod_mpoly_monomial_evals_cache( n_fq_poly_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const fq_nmod_struct * betas, slong start, slong stop, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, Ai; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, ctx->minfo); slong * off, * shift; n_poly_struct * caches; mp_limb_t * c; slong num = stop - start; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(num > 0); caches = FLINT_ARRAY_ALLOC(3*num, n_fq_poly_struct); off = FLINT_ARRAY_ALLOC(2*num, slong); shift = off + num; for (i = 0; i < num; i++) { mpoly_gen_offset_shift_sp(&off[i], &shift[i], i + start, Abits, ctx->minfo); n_fq_poly_init(caches + 3*i + 0); n_fq_poly_init(caches + 3*i + 1); n_fq_poly_init(caches + 3*i + 2); n_fq_pow_cache_start_fq_nmod(betas + i, caches + 3*i + 0, caches + 3*i + 1, caches + 3*i + 2, ctx->fqctx); } n_poly_fit_length(E, d*Alen); E->length = Alen; for (Ai = 0; Ai < Alen; Ai++) { c = E->coeffs + d*Ai; _n_fq_one(c, d); for (i = 0; i < num; i++) { ulong ei = (Aexps[N*Ai + off[i]] >> shift[i]) & mask; n_fq_pow_cache_mulpow_ui(c, c, ei, caches + 3*i + 0, caches + 3*i + 1, caches + 3*i + 2, ctx->fqctx); } } for (i = 0; i < num; i++) { n_fq_poly_clear(caches + 3*i + 0); n_fq_poly_clear(caches + 3*i + 1); n_fq_poly_clear(caches + 3*i + 2); } flint_free(caches); flint_free(off); } void _fq_nmod_mpoly_monomial_evals2_cache( n_fq_polyun_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const fq_nmod_struct * betas, slong m, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, Ai, Ei; ulong e0, e1, e01; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, ctx->minfo); slong * off, * shift; n_fq_poly_struct * caches; mp_limb_t * c; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(m > 2); caches = FLINT_ARRAY_ALLOC(3*(m - 2), n_fq_poly_struct); off = FLINT_ARRAY_ALLOC(2*m, slong); shift = off + m; for (i = 0; i < m; i++) { mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, Abits, ctx->minfo); if (i >= 2) { n_fq_poly_init(caches + 3*(i - 2) + 0); n_fq_poly_init(caches + 3*(i - 2) + 1); n_fq_poly_init(caches + 3*(i - 2) + 2); n_fq_pow_cache_start_fq_nmod(betas + i - 2, caches + 3*(i - 2) + 0, caches + 3*(i - 2) + 1, caches + 3*(i - 2) + 2, ctx->fqctx); } } Ai = 0; Ei = 0; e0 = (Aexps[N*Ai + off[0]] >> shift[0]) & mask; e1 = (Aexps[N*Ai + off[1]] >> shift[1]) & mask; e01 = pack_exp2(e0, e1); n_polyun_fit_length(E, Ei + 1); E->exps[Ei] = e01; n_poly_fit_length(E->coeffs + Ei, d*1); c = E->coeffs[Ei].coeffs + d*0; E->coeffs[Ei].length = 1; Ei++; _n_fq_one(c, d); for (i = 2; i < m; i++) { ulong ei = (Aexps[N*Ai + off[i]] >> shift[i]) & mask; n_fq_pow_cache_mulpow_ui(c, c, ei, caches + 3*(i - 2) + 0, caches + 3*(i - 2) + 1, caches + 3*(i - 2) + 2, ctx->fqctx); } for (Ai++; Ai < Alen; Ai++) { e0 = (Aexps[N*Ai + off[0]] >> shift[0]) & mask; e1 = (Aexps[N*Ai + off[1]] >> shift[1]) & mask; e01 = pack_exp2(e0, e1); if (e01 == E->exps[Ei - 1]) { slong len = E->coeffs[Ei - 1].length; n_poly_fit_length(E->coeffs + Ei - 1, d*(len + 1)); c = E->coeffs[Ei - 1].coeffs + d*len; E->coeffs[Ei - 1].length = len + 1; } else { n_polyun_fit_length(E, Ei + 1); E->exps[Ei] = e01; n_poly_fit_length(E->coeffs + Ei, d*1); c = E->coeffs[Ei].coeffs + d*0; E->coeffs[Ei].length = 1; Ei++; } _n_fq_one(c, d); for (i = 2; i < m; i++) { ulong ei = (Aexps[N*Ai + off[i]] >> shift[i]) & mask; n_fq_pow_cache_mulpow_ui(c, c, ei, caches + 3*(i - 2) + 0, caches + 3*(i - 2) + 1, caches + 3*(i - 2) + 2, ctx->fqctx); } } E->length = Ei; for (i = 0; i < m - 2; i++) { n_fq_poly_clear(caches + 3*i + 0); n_fq_poly_clear(caches + 3*i + 1); n_fq_poly_clear(caches + 3*i + 2); } flint_free(caches); flint_free(off); #if FLINT_WANT_ASSERT Ai = 0; for (i = 0; i < E->length; i++) Ai += E->coeffs[i].length; FLINT_ASSERT(Ai == Alen); #endif } void n_fq_bpoly_eval_step_sep( n_fq_bpoly_t E, n_fq_polyun_t cur, const n_fq_polyun_t inc, const fq_nmod_mpoly_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, Ai; slong e0, e1; mp_limb_t * c = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_bpoly_zero(E); Ai = 0; for (i = 0; i < cur->length; i++) { slong this_len = cur->coeffs[i].length; _n_fq_zip_eval_step(c, cur->coeffs[i].coeffs, inc->coeffs[i].coeffs, A->coeffs + d*Ai, this_len, ctx); Ai += this_len; e0 = extract_exp(cur->exps[i], 1, 2); e1 = extract_exp(cur->exps[i], 0, 2); if (_n_fq_is_zero(c, d)) continue; n_fq_bpoly_set_coeff_n_fq(E, e0, e1, c, ctx); } FLINT_ASSERT(Ai == A->length); flint_free(c); } static void n_fq_poly_eval_step_sep( mp_limb_t * res, n_fq_poly_t cur, const n_fq_poly_t inc, const fq_nmod_mpoly_t A, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(A->length == cur->length); FLINT_ASSERT(A->length == inc->length); _n_fq_zip_eval_step(res, cur->coeffs, inc->coeffs, A->coeffs, A->length, ctx); } static void n_fq_bpoly_evalp_step_sep( n_fq_bpoly_t E, n_polyun_t cur, const n_polyun_t inc, const fq_nmod_mpoly_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, Ai; slong e0, e1; mp_limb_t * c = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_bpoly_zero(E); Ai = 0; for (i = 0; i < cur->length; i++) { slong this_len = cur->coeffs[i].length; _n_fqp_zip_eval_step(c, cur->coeffs[i].coeffs, inc->coeffs[i].coeffs, A->coeffs + d*Ai, this_len, d, ctx->mod); Ai += this_len; e0 = extract_exp(cur->exps[i], 1, 2); e1 = extract_exp(cur->exps[i], 0, 2); if (_n_fq_is_zero(c, d)) continue; n_fq_bpoly_set_coeff_n_fq(E, e0, e1, c, ctx); } FLINT_ASSERT(Ai == A->length); flint_free(c); } static void n_fq_poly_evalp_step_sep( mp_limb_t * res, n_poly_t cur, const n_poly_t inc, const fq_nmod_mpoly_t A, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(A->length == cur->length); FLINT_ASSERT(A->length == inc->length); _n_fqp_zip_eval_step(res, cur->coeffs, inc->coeffs, A->coeffs, A->length, fq_nmod_ctx_degree(ctx), ctx->mod); } static ulong _fq_nmod_mpoly_bidegree( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return _mpoly_bidegree(A->exps, A->bits, ctx->minfo); } static void fq_nmod_mpoly_monomial_evals2( n_fq_polyun_t E, const fq_nmod_mpoly_t A, const fq_nmod_struct * betas, slong m, const fq_nmod_mpoly_ctx_t ctx) { _fq_nmod_mpoly_monomial_evals2_cache(E, A->exps, A->bits, A->length, betas, m, ctx); } static void fq_nmod_mpoly_monomial_evalsp2( n_polyun_t E, const fq_nmod_mpoly_t A, const mp_limb_t * betas, slong m, const fq_nmod_mpoly_ctx_t ctx) { _nmod_mpoly_monomial_evals2_cache(E, A->exps, A->bits, A->length, betas, m, ctx->minfo, ctx->fqctx->mod); } static void fq_nmod_mpoly_monomial_evalsp( n_poly_t E, const fq_nmod_mpoly_t A, const mp_limb_t * betas, slong start, slong stop, const fq_nmod_mpoly_ctx_t ctx) { _nmod_mpoly_monomial_evals_cache(E, A->exps, A->bits, A->length, betas, start, stop, ctx->minfo, ctx->fqctx->mod); } static void fq_nmod_mpoly_monomial_evals( n_fq_poly_t E, const fq_nmod_mpoly_t A, const fq_nmod_struct * betas, slong start, slong stop, const fq_nmod_mpoly_ctx_t ctx) { _fq_nmod_mpoly_monomial_evals_cache(E, A->exps, A->bits, A->length, betas, start, stop, ctx); } int n_fq_polyun_zip_solve( fq_nmod_mpoly_t A, n_fq_polyun_t Z, n_fq_polyun_t H, n_fq_polyun_t M, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; slong Ai, i, n; n_poly_t t; n_poly_init(t); FLINT_ASSERT(Z->length == H->length); FLINT_ASSERT(Z->length == M->length); /* A has the right length, but possibly from a smaller ctx */ if (A->length*d > A->coeffs_alloc) { slong new_alloc = FLINT_MAX(A->coeffs_alloc + A->coeffs_alloc/2, A->length*d); A->coeffs = (mp_limb_t *) flint_realloc(A->coeffs, new_alloc*sizeof(mp_limb_t)); A->coeffs_alloc = new_alloc; } Ai = 0; for (i = 0; i < H->length; i++) { n = H->coeffs[i].length; FLINT_ASSERT(M->coeffs[i].length == n + 1); FLINT_ASSERT(Z->coeffs[i].length >= n); FLINT_ASSERT(Ai + n <= A->length); n_poly_fit_length(t, d*n); success = _n_fq_zip_vand_solve(A->coeffs + d*Ai, H->coeffs[i].coeffs, n, Z->coeffs[i].coeffs, Z->coeffs[i].length, M->coeffs[i].coeffs, t->coeffs, ctx->fqctx); if (success < 1) { n_poly_clear(t); return success; } Ai += n; FLINT_ASSERT(Ai <= A->length); } FLINT_ASSERT(Ai == A->length); n_poly_clear(t); return 1; } static int n_fq_polyun_zip_solvep( fq_nmod_mpoly_t A, n_fq_polyun_t Z, n_fq_polyun_t H, n_fq_polyun_t M, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; slong Ai, i, n; n_poly_t t; n_poly_init(t); FLINT_ASSERT(Z->length == H->length); FLINT_ASSERT(Z->length == M->length); /* A has the right length, but possibly from a smaller ctx */ if (A->length*d > A->coeffs_alloc) { slong new_alloc = FLINT_MAX(A->coeffs_alloc + A->coeffs_alloc/2, A->length*d); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, mp_limb_t); A->coeffs_alloc = new_alloc; } Ai = 0; for (i = 0; i < H->length; i++) { n = H->coeffs[i].length; FLINT_ASSERT(M->coeffs[i].length == n + 1); FLINT_ASSERT(Z->coeffs[i].length >= n); FLINT_ASSERT(Ai + n <= A->length); n_poly_fit_length(t, n); success = _n_fqp_zip_vand_solve(A->coeffs + d*Ai, H->coeffs[i].coeffs, n, Z->coeffs[i].coeffs, Z->coeffs[i].length, M->coeffs[i].coeffs, t->coeffs, ctx->fqctx); if (success < 1) { n_poly_clear(t); return success; } Ai += n; FLINT_ASSERT(Ai <= A->length); } FLINT_ASSERT(Ai == A->length); n_poly_clear(t); return 1; } void n_fq_polyun_zip_start( n_fq_polyun_t Z, n_fq_polyun_t H, slong req_images, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong j; n_polyun_fit_length(Z, H->length); Z->length = H->length; for (j = 0; j < H->length; j++) { Z->exps[j] = H->exps[j]; n_poly_fit_length(Z->coeffs + j, d*req_images); Z->coeffs[j].length = 0; } } int n_fq_polyu2n_add_zip_must_match( n_fq_polyun_t Z, const n_fq_bpoly_t A, slong cur_length, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, Ai, ai; n_poly_struct * Zcoeffs = Z->coeffs; ulong * Zexps = Z->exps; const n_poly_struct * Acoeffs = A->coeffs; Ai = A->length - 1; ai = (Ai < 0) ? 0 : n_fq_poly_degree(A->coeffs + Ai); for (i = 0; i < Z->length; i++) { if (Ai >= 0 && Zexps[i] == pack_exp2(Ai, ai)) { /* Z present, A present */ _n_fq_set(Zcoeffs[i].coeffs + d*cur_length, Acoeffs[Ai].coeffs + d*ai, d); Zcoeffs[i].length = cur_length + 1; do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_fq_poly_degree(Acoeffs + Ai); } } else if (Ai < 0 || Zexps[i] > pack_exp2(Ai, ai)) { /* Z present, A missing */ _n_fq_zero(Zcoeffs[i].coeffs + d*cur_length, d); Zcoeffs[i].length = cur_length + 1; } else { /* Z missing, A present */ return 0; } } return 1; } #define USE_G 1 #define USE_ABAR 2 #define USE_BBAR 4 /* gamma = gcd(lc(A), lc(B)) fake answers G, Abar, Bbar with G*Abar = gamma*A G*Bbar = gamma*B lc(G) = gamma lc(Abar) = lc(A) lc(Bbar) = lc(B) real answers rG = pp(G) rAbar = Abar/lc(rG) rBbar = Bbar/lc(rG) */ int fq_nmod_mpolyl_gcd_zippel_smprime( fq_nmod_mpoly_t rG, const slong * rGdegs, fq_nmod_mpoly_t rAbar, fq_nmod_mpoly_t rBbar, const fq_nmod_mpoly_t A, const slong * Adegs, const fq_nmod_mpoly_t B, const slong * Bdegs, const fq_nmod_mpoly_t gamma, const slong * gammadegs, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success, use, betas_in_fp, main_tries_left; slong i, m; slong nvars = ctx->minfo->nvars; flint_bitcnt_t bits = A->bits; fq_nmod_struct * alphas, * betas; mp_limb_t * betasp; flint_rand_t state; fq_nmod_mpoly_t cont; fq_nmod_mpoly_t T, G, Abar, Bbar; n_fq_polyun_t HG, HAbar, HBbar, MG, MAbar, MBbar, ZG, ZAbar, ZBbar; n_fq_bpoly_t Aev, Bev, Gev, Abarev, Bbarev; const mp_limb_t * gammaev; fq_nmod_mpolyn_t Tn, Gn, Abarn, Bbarn; slong lastdeg; slong cur_zip_image, req_zip_images, this_length; n_fq_polyun_t Aeh_cur, Aeh_inc, Beh_cur, Beh_inc; n_fq_poly_t gammaeh_cur, gammaeh_inc; n_fq_poly_t modulus, alphapow; fq_nmod_mpoly_struct * Aevals, * Bevals; fq_nmod_mpoly_struct * gammaevals; n_poly_bpoly_stack_t St; mp_limb_t * c; fq_nmod_t start_alpha; ulong GdegboundXY, newdegXY, Abideg, Bbideg; slong degxAB, degyAB; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == gamma->bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(gamma->length > 0); fq_nmod_mpoly_fit_length_reset_bits(rG, 1, bits, ctx); fq_nmod_mpoly_fit_length_reset_bits(rAbar, 1, bits, ctx); fq_nmod_mpoly_fit_length_reset_bits(rBbar, 1, bits, ctx); #if FLINT_WANT_ASSERT { slong * tmp_degs = FLINT_ARRAY_ALLOC(nvars, slong); fq_nmod_mpoly_degrees_si(tmp_degs, A, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Adegs[i]); fq_nmod_mpoly_degrees_si(tmp_degs, B, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Bdegs[i]); fq_nmod_mpoly_degrees_si(tmp_degs, gamma, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == gammadegs[i]); flint_free(tmp_degs); } #endif FLINT_ASSERT(gammadegs[0] == 0); FLINT_ASSERT(gammadegs[1] == 0); fq_nmod_init(start_alpha, ctx->fqctx); c = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_fq_polyun_init(HG); n_fq_polyun_init(HAbar); n_fq_polyun_init(HBbar); n_fq_polyun_init(MG); n_fq_polyun_init(MAbar); n_fq_polyun_init(MBbar); n_fq_polyun_init(ZG); n_fq_polyun_init(ZAbar); n_fq_polyun_init(ZBbar); n_fq_bpoly_init(Aev); n_fq_bpoly_init(Bev); n_fq_bpoly_init(Gev); n_fq_bpoly_init(Abarev); n_fq_bpoly_init(Bbarev); n_fq_poly_init2(alphapow, 4, ctx->fqctx); fq_nmod_mpoly_init3(cont, 1, bits, ctx); fq_nmod_mpoly_init3(T, 0, bits, ctx); fq_nmod_mpoly_init3(G, 0, bits, ctx); fq_nmod_mpoly_init3(Abar, 0, bits, ctx); fq_nmod_mpoly_init3(Bbar, 0, bits, ctx); fq_nmod_mpolyn_init(Tn, bits, ctx); fq_nmod_mpolyn_init(Gn, bits, ctx); fq_nmod_mpolyn_init(Abarn, bits, ctx); fq_nmod_mpolyn_init(Bbarn, bits, ctx); n_fq_polyun_init(Aeh_cur); n_fq_polyun_init(Aeh_inc); n_fq_polyun_init(Beh_cur); n_fq_polyun_init(Beh_inc); n_fq_poly_init(gammaeh_cur); n_fq_poly_init(gammaeh_inc); n_fq_poly_init(modulus); n_poly_stack_init(St->poly_stack); n_bpoly_stack_init(St->bpoly_stack); betasp = FLINT_ARRAY_ALLOC(nvars, mp_limb_t); betas = FLINT_ARRAY_ALLOC(nvars, fq_nmod_struct); alphas = FLINT_ARRAY_ALLOC(nvars, fq_nmod_struct); for (i = 0; i < nvars; i++) { fq_nmod_init(betas + i, ctx->fqctx); fq_nmod_init(alphas + i, ctx->fqctx); } flint_randinit(state); Aevals = FLINT_ARRAY_ALLOC(nvars + 1, fq_nmod_mpoly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars + 1, fq_nmod_mpoly_struct); gammaevals = FLINT_ARRAY_ALLOC(nvars + 1, fq_nmod_mpoly_struct); for (i = 0; i < nvars; i++) { fq_nmod_mpoly_init3(Aevals + i, 0, bits, ctx); fq_nmod_mpoly_init3(Bevals + i, 0, bits, ctx); fq_nmod_mpoly_init3(gammaevals + i, 0, bits, ctx); } Aevals[nvars] = *A; Bevals[nvars] = *B; gammaevals[nvars] = *gamma; Abideg = _fq_nmod_mpoly_bidegree(A, ctx); Bbideg = _fq_nmod_mpoly_bidegree(B, ctx); degxAB = FLINT_MAX(Adegs[0], Bdegs[0]); degyAB = FLINT_MAX(Adegs[1], Bdegs[1]); GdegboundXY = pack_exp2(FLINT_MIN(Adegs[0], Bdegs[0]), FLINT_MIN(Adegs[1], Bdegs[1])); if (GdegboundXY == 0) goto gcd_is_trivial; main_tries_left = 3; choose_main: if (--main_tries_left < 0) { success = 0; goto cleanup; } for (i = 2; i < nvars; i++) fq_nmod_rand_not_zero(alphas + i, state, ctx->fqctx); for (i = nvars - 1; i >= 2; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + i, Aevals + i + 1, i, alphas + i, ctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + i, bits, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + i, Bevals + i + 1, i, alphas + i, ctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + i, bits, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + i, gammaevals + i + 1, i, alphas + i, ctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + i, bits, ctx); if (fq_nmod_mpoly_is_zero(gammaevals + i, ctx)) goto choose_main; if (Aevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + i, ctx) != Abideg) goto choose_main; if (Bevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + i, ctx) != Bbideg) goto choose_main; } m = 2; if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = mpoly_gcd_get_use_first(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m]); fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, ctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, ctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->fqctx, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_main; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, ctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, ctx->fqctx); fq_nmod_mpolyn_interp_lift_sm_bpoly(Gn, Gev, ctx); fq_nmod_mpolyn_interp_lift_sm_bpoly(Abarn, Abarev, ctx); fq_nmod_mpolyn_interp_lift_sm_bpoly(Bbarn, Bbarev, ctx); n_fq_poly_one(modulus, ctx->fqctx); n_fq_set_fq_nmod(c, alphas + m, ctx->fqctx); n_fq_poly_shift_left_scalar_submul(modulus, 1, c, ctx->fqctx); fq_nmod_set(start_alpha, alphas + m, ctx->fqctx); while (1) { choose_alpha_2: fq_nmod_next_not_zero(alphas + m, ctx->fqctx); if (fq_nmod_equal(alphas + m, start_alpha, ctx->fqctx)) goto choose_main; FLINT_ASSERT(alphapow->alloc >= d*2); alphapow->length = 2; _n_fq_one(alphapow->coeffs + d*0, d); n_fq_set_fq_nmod(alphapow->coeffs + d*1, alphas + m, ctx->fqctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + m, Aevals + m + 1, m, alphas + m, ctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + m, bits, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + m, Bevals + m + 1, m, alphas + m, ctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + m, bits, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + m, gammaevals + m + 1, m, alphas + m, ctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, ctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, ctx)) goto choose_alpha_2; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, ctx) != Abideg) goto choose_alpha_2; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, ctx) != Bbideg) goto choose_alpha_2; fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, ctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, ctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->fqctx, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alpha_2; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_main; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, ctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, ctx->fqctx); n_fq_poly_eval_pow(c, modulus, alphapow, ctx->fqctx); n_fq_inv(c, c, ctx->fqctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, c, ctx->fqctx); if ((use & USE_G) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Gn, Tn, Gev, modulus, alphapow, ctx)) { if (m == nvars - 1) { fq_nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx); success = fq_nmod_mpolyl_content(cont, rG, 2, ctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rG, rG, cont, ctx); fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); if (fq_nmod_mpoly_divides(rAbar, A, rG, ctx) && fq_nmod_mpoly_divides(rBbar, B, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fq_nmod_mpoly_cvtfrom_mpolyn(G, Gn, m, ctx); fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(Abar, T, G, ctx)) { fq_nmod_mpoly_repack_bits_inplace(Abar, bits, ctx); fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(Bbar, T, G, ctx)) { fq_nmod_mpoly_repack_bits_inplace(Bbar, bits, ctx); break; } } } } if ((use & USE_ABAR) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Abarn, Tn, Abarev, modulus, alphapow, ctx)) { if (m == nvars - 1) { fq_nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx); success = fq_nmod_mpolyl_content(cont, rAbar, 2, ctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rAbar, rAbar, cont, ctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); if (fq_nmod_mpoly_divides(rG, A, rAbar, ctx) && fq_nmod_mpoly_divides(rBbar, B, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fq_nmod_mpoly_cvtfrom_mpolyn(Abar, Abarn, m, ctx); fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(G, T, Abar, ctx)) { fq_nmod_mpoly_repack_bits_inplace(G, bits, ctx); fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(Bbar, T, G, ctx)) { fq_nmod_mpoly_repack_bits_inplace(Bbar, bits, ctx); break; } } } } if ((use & USE_BBAR) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Bbarn, Tn, Bbarev, modulus, alphapow, ctx)) { if (m == nvars - 1) { fq_nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx); success = fq_nmod_mpolyl_content(cont, rBbar, 2, ctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rBbar, rBbar, cont, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); if (fq_nmod_mpoly_divides(rG, B, rBbar, ctx) && fq_nmod_mpoly_divides(rAbar, A, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); break; } } else { fq_nmod_mpoly_cvtfrom_mpolyn(Bbar, Bbarn, m, ctx); fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(G, T, Bbar, ctx)) { fq_nmod_mpoly_repack_bits_inplace(G, bits, ctx); fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(Abar, T, G, ctx)) { fq_nmod_mpoly_repack_bits_inplace(Abar, bits, ctx); break; } } } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_main; } FLINT_ASSERT(n_fq_equal_fq_nmod(alphapow->coeffs + d*1, alphas + m, ctx->fqctx)); n_fq_poly_shift_left_scalar_submul(modulus, 1, alphapow->coeffs + d*1, ctx->fqctx); } for (m = 3; m < nvars; m++) { /* G, Abar, Bbar are in Fq[gen(0), ..., gen(m - 1)] */ fq_nmod_mpolyn_interp_lift_sm_mpoly(Gn, G, ctx); fq_nmod_mpolyn_interp_lift_sm_mpoly(Abarn, Abar, ctx); fq_nmod_mpolyn_interp_lift_sm_mpoly(Bbarn, Bbar, ctx); if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = 0; n_fq_poly_one(modulus, ctx->fqctx); n_fq_set_fq_nmod(c, alphas + m, ctx->fqctx); n_fq_poly_shift_left_scalar_submul(modulus, 1, c, ctx->fqctx); fq_nmod_set(start_alpha, alphas + m, ctx->fqctx); choose_betas: /* only beta[0], beta[1], ..., beta[m - 1] will be used */ betas_in_fp = (ctx->fqctx->mod.norm < FLINT_BITS/4); if (betas_in_fp) { for (i = 2; i < ctx->minfo->nvars; i++) betasp[i] = n_urandint(state, ctx->fqctx->mod.n - 3) + 2; fq_nmod_mpoly_monomial_evalsp2(HG, G, betasp + 2, m, ctx); fq_nmod_mpoly_monomial_evalsp2(HAbar, Abar, betasp + 2, m, ctx); fq_nmod_mpoly_monomial_evalsp2(HBbar, Bbar, betasp + 2, m, ctx); } else { for (i = 2; i < ctx->minfo->nvars; i++) fq_nmod_rand_not_zero(betas + i, state, ctx->fqctx); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(Abar->bits == bits); FLINT_ASSERT(Bbar->bits == bits); fq_nmod_mpoly_monomial_evals2(HG, G, betas + 2, m, ctx); fq_nmod_mpoly_monomial_evals2(HAbar, Abar, betas + 2, m, ctx); fq_nmod_mpoly_monomial_evals2(HBbar, Bbar, betas + 2, m, ctx); } if (use == 0) { this_length = gammaevals[m + 1].length + Aevals[m + 1].length + Bevals[m + 1].length; use = nmod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar); } req_zip_images = 1; if (use & USE_G) { this_length = betas_in_fp ? n_polyun_product_roots(MG, HG, ctx->fqctx->mod) : n_fq_polyun_product_roots(MG, HG, ctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_ABAR) { this_length = betas_in_fp ? n_polyun_product_roots(MAbar, HAbar, ctx->fqctx->mod) : n_fq_polyun_product_roots(MAbar, HAbar, ctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_BBAR) { this_length = betas_in_fp ? n_polyun_product_roots(MBbar, HBbar, ctx->fqctx->mod) : n_fq_polyun_product_roots(MBbar, HBbar, ctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } while (1) { choose_alpha_m: fq_nmod_next_not_zero(alphas + m, ctx->fqctx); if (fq_nmod_equal(alphas + m, start_alpha, ctx->fqctx)) goto choose_main; FLINT_ASSERT(alphapow->alloc >= d*2); alphapow->length = 2; _n_fq_one(alphapow->coeffs + d*0, d); n_fq_set_fq_nmod(alphapow->coeffs + d*1, alphas + m, ctx->fqctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + m, Aevals + m + 1, m, alphas + m, ctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + m, bits, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + m, Bevals + m + 1, m, alphas + m, ctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + m, bits, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + m, gammaevals + m + 1, m, alphas + m, ctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, ctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, ctx)) goto choose_alpha_m; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, ctx) != Abideg) goto choose_alpha_m; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, ctx) != Bbideg) goto choose_alpha_m; if (betas_in_fp) { fq_nmod_mpoly_monomial_evalsp2(Aeh_inc, Aevals + m, betasp + 2, m, ctx); fq_nmod_mpoly_monomial_evalsp2(Beh_inc, Bevals + m, betasp + 2, m, ctx); fq_nmod_mpoly_monomial_evalsp(gammaeh_inc, gammaevals + m, betasp + 2, 2, m, ctx); n_polyun_set(Aeh_cur, Aeh_inc); n_polyun_set(Beh_cur, Beh_inc); n_poly_set(gammaeh_cur, gammaeh_inc); } else { fq_nmod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, betas + 2, m, ctx); fq_nmod_mpoly_monomial_evals2(Beh_inc, Bevals + m, betas + 2, m, ctx); fq_nmod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, betas + 2, 2, m, ctx); n_fq_polyun_set(Aeh_cur, Aeh_inc, ctx->fqctx); n_fq_polyun_set(Beh_cur, Beh_inc, ctx->fqctx); n_fq_poly_set(gammaeh_cur, gammaeh_inc, ctx->fqctx); } n_fq_polyun_zip_start(ZG, HG, req_zip_images, ctx->fqctx); n_fq_polyun_zip_start(ZAbar, HAbar, req_zip_images, ctx->fqctx); n_fq_polyun_zip_start(ZBbar, HBbar, req_zip_images, ctx->fqctx); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { if (betas_in_fp) { n_fq_bpoly_evalp_step_sep(Aev, Aeh_cur, Aeh_inc, Aevals + m, ctx->fqctx); n_fq_bpoly_evalp_step_sep(Bev, Beh_cur, Beh_inc, Bevals + m, ctx->fqctx); n_fq_poly_evalp_step_sep(c, gammaeh_cur, gammaeh_inc, gammaevals + m, ctx->fqctx); } else { n_fq_bpoly_eval_step_sep(Aev, Aeh_cur, Aeh_inc, Aevals + m, ctx->fqctx); n_fq_bpoly_eval_step_sep(Bev, Beh_cur, Beh_inc, Bevals + m, ctx->fqctx); n_fq_poly_eval_step_sep(c, gammaeh_cur, gammaeh_inc, gammaevals + m, ctx->fqctx); } if (_n_fq_is_zero(c, d)) goto choose_betas; if (Aev->length < 1 || n_bpoly_bidegree(Aev) != Abideg) goto choose_betas; if (Bev->length < 1 || n_bpoly_bidegree(Bev) != Bbideg) goto choose_betas; success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->fqctx, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_betas; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_main; } n_fq_bpoly_scalar_mul_n_fq(Gev, c, ctx->fqctx); if ((use & USE_G) && !n_fq_polyu2n_add_zip_must_match(ZG, Gev, cur_zip_image, ctx->fqctx)) goto choose_main; if ((use & USE_ABAR) && !n_fq_polyu2n_add_zip_must_match(ZAbar, Abarev, cur_zip_image, ctx->fqctx)) goto choose_main; if ((use & USE_BBAR) && !n_fq_polyu2n_add_zip_must_match(ZBbar, Bbarev, cur_zip_image, ctx->fqctx)) goto choose_main; } if (betas_in_fp) { if ((use & USE_G) && n_fq_polyun_zip_solvep(G, ZG, HG, MG, ctx) < 1) goto choose_main; if ((use & USE_ABAR) && n_fq_polyun_zip_solvep(Abar, ZAbar, HAbar, MAbar, ctx) < 1) goto choose_main; if ((use & USE_BBAR) && n_fq_polyun_zip_solvep(Bbar, ZBbar, HBbar, MBbar, ctx) < 1) goto choose_main; } else { if ((use & USE_G) && n_fq_polyun_zip_solve(G, ZG, HG, MG, ctx) < 1) goto choose_main; if ((use & USE_ABAR) && n_fq_polyun_zip_solve(Abar, ZAbar, HAbar, MAbar, ctx) < 1) goto choose_main; if ((use & USE_BBAR) && n_fq_polyun_zip_solve(Bbar, ZBbar, HBbar, MBbar, ctx) < 1) goto choose_main; } n_fq_poly_eval_pow(c, modulus, alphapow, ctx->fqctx); n_fq_inv(c, c, ctx->fqctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, c, ctx->fqctx); if ((use & USE_G) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Gn, G, modulus, alphapow, ctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx); if (m == nvars - 1) { success = fq_nmod_mpolyl_content(cont, rG, 2, ctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rG, rG, cont, ctx); fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); if (fq_nmod_mpoly_divides(rAbar, A, rG, ctx) && fq_nmod_mpoly_divides(rBbar, B, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(rAbar, T, rG, ctx)) { fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(rBbar, T, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); fq_nmod_mpoly_swap(G, rG, ctx); fq_nmod_mpoly_swap(Abar, rAbar, ctx); fq_nmod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if ((use & USE_ABAR) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Abarn, Abar, modulus, alphapow, ctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx); if (m == nvars - 1) { success = fq_nmod_mpolyl_content(cont, rAbar, 2, ctx); if (!success) goto cleanup; success = fq_nmod_mpoly_divides(rAbar, rAbar, cont, ctx); FLINT_ASSERT(success); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); if (fq_nmod_mpoly_divides(rG, A, rAbar, ctx) && fq_nmod_mpoly_divides(rBbar, B, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(rG, T, rAbar, ctx)) { fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(rBbar, T, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); fq_nmod_mpoly_swap(G, rG, ctx); fq_nmod_mpoly_swap(Abar, rAbar, ctx); fq_nmod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if ((use & USE_BBAR) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Bbarn, Bbar, modulus, alphapow, ctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx); if (m == nvars - 1) { success = fq_nmod_mpolyl_content(cont, rBbar, 2, ctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rBbar, rBbar, cont, ctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); if (fq_nmod_mpoly_divides(rG, B, rBbar, ctx) && fq_nmod_mpoly_divides(rAbar, A, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); break; } } else { fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(rG, T, rBbar, ctx)) { fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (fq_nmod_mpoly_divides(rAbar, T, rG, ctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, ctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); fq_nmod_mpoly_swap(G, rG, ctx); fq_nmod_mpoly_swap(Abar, rAbar, ctx); fq_nmod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_main; } FLINT_ASSERT(n_fq_equal_fq_nmod(alphapow->coeffs + d*1, alphas + m, ctx->fqctx)); n_fq_poly_shift_left_scalar_submul(modulus, 1, alphapow->coeffs + d*1, ctx->fqctx); } } success = 1; cleanup: n_fq_polyun_clear(HG); n_fq_polyun_clear(HAbar); n_fq_polyun_clear(HBbar); n_fq_polyun_clear(MG); n_fq_polyun_clear(MAbar); n_fq_polyun_clear(MBbar); n_fq_polyun_clear(ZG); n_fq_polyun_clear(ZAbar); n_fq_polyun_clear(ZBbar); n_fq_bpoly_clear(Aev); n_fq_bpoly_clear(Bev); n_fq_bpoly_clear(Gev); n_fq_bpoly_clear(Abarev); n_fq_bpoly_clear(Bbarev); n_fq_poly_clear(alphapow); fq_nmod_mpoly_clear(cont, ctx); fq_nmod_mpoly_clear(T, ctx); fq_nmod_mpoly_clear(G, ctx); fq_nmod_mpoly_clear(Abar, ctx); fq_nmod_mpoly_clear(Bbar, ctx); fq_nmod_mpolyn_clear(Tn, ctx); fq_nmod_mpolyn_clear(Gn, ctx); fq_nmod_mpolyn_clear(Abarn, ctx); fq_nmod_mpolyn_clear(Bbarn, ctx); n_fq_polyun_clear(Aeh_cur); n_fq_polyun_clear(Aeh_inc); n_fq_polyun_clear(Beh_cur); n_fq_polyun_clear(Beh_inc); n_fq_poly_clear(gammaeh_cur); n_fq_poly_clear(gammaeh_inc); n_fq_poly_clear(modulus); n_poly_stack_clear(St->poly_stack); n_bpoly_stack_clear(St->bpoly_stack); fq_nmod_clear(start_alpha, ctx->fqctx); flint_free(c); flint_free(betasp); for (i = 0; i < nvars; i++) { fq_nmod_clear(betas + i, ctx->fqctx); fq_nmod_clear(alphas + i, ctx->fqctx); } flint_free(betas); flint_free(alphas); flint_randclear(state); for (i = 0; i < nvars; i++) { fq_nmod_mpoly_clear(Aevals + i, ctx); fq_nmod_mpoly_clear(Bevals + i, ctx); fq_nmod_mpoly_clear(gammaevals + i, ctx); } flint_free(Aevals); flint_free(Bevals); flint_free(gammaevals); FLINT_ASSERT(!success || rG->bits == bits); FLINT_ASSERT(!success || rAbar->bits == bits); FLINT_ASSERT(!success || rBbar->bits == bits); return success; gcd_is_trivial: fq_nmod_mpoly_one(rG, ctx); fq_nmod_mpoly_set(rAbar, A, ctx); fq_nmod_mpoly_set(rBbar, B, ctx); success = 1; goto cleanup; } /* TODO: make this the real fq_nmod_mpolyn_interp_mcrt_lg_mpoly */ static int newfq_nmod_mpolyn_interp_mcrt_lg_mpoly( slong * lastdeg, fq_nmod_mpolyn_t H, const fq_nmod_mpoly_ctx_t ctx, const n_fq_poly_t m, const mp_limb_t * inv_m_eval, fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(ectx->fqctx); slong i; #if FLINT_WANT_ASSERT slong N = mpoly_words_per_exp(A->bits, ctx->minfo); #endif int changed = 0; mp_limb_t * u, * v, * tmp; n_fq_poly_struct * w, * u_sm; n_poly_stack_t St; FLINT_ASSERT(H->length == A->length); FLINT_ASSERT(H->bits == A->bits); n_poly_stack_init(St); n_poly_stack_fit_request(St, 3); w = n_poly_stack_take_top(St); u_sm = n_poly_stack_take_top(St); tmp = n_poly_stack_vec_init(St, lgd*(2 + N_FQ_MUL_ITCH)); u = tmp + lgd*N_FQ_MUL_ITCH; v = u + lgd; for (i = 0; i < A->length; i++) { FLINT_ASSERT(mpoly_monomial_equal(H->exps + N*i, A->exps + N*i, N)); bad_n_fq_embed_sm_to_lg(u, H->coeffs + i, emb); _n_fq_sub(v, A->coeffs + lgd*i, u, lgd, ectx->fqctx->mod); if (!_n_fq_is_zero(v, lgd)) { changed = 1; _n_fq_mul(u, v, inv_m_eval, ectx->fqctx, tmp); bad_n_fq_embed_lg_to_sm(u_sm, u, emb); n_fq_poly_mul_(w, u_sm, m, ctx->fqctx, St); n_fq_poly_add(H->coeffs + i, H->coeffs + i, w, ctx->fqctx); } *lastdeg = FLINT_MAX(*lastdeg, n_fq_poly_degree(H->coeffs + i)); FLINT_ASSERT(n_fq_poly_degree(H->coeffs + i) < n_fq_poly_degree(m) + fq_nmod_poly_degree(emb->h, ctx->fqctx)); } n_poly_stack_vec_clear(St); n_poly_stack_give_back(St, 2); n_poly_stack_clear(St); return changed; } int fq_nmod_mpolyl_gcd_zippel_lgprime( fq_nmod_mpoly_t rG, const slong * rGdegs, fq_nmod_mpoly_t rAbar, fq_nmod_mpoly_t rBbar, const fq_nmod_mpoly_t A, const slong * Adegs, const fq_nmod_mpoly_t B, const slong * Bdegs, const fq_nmod_mpoly_t gamma, const slong * gammadegs, const fq_nmod_mpoly_ctx_t smctx) { slong lgd; int success, use; slong i, m; slong nvars = smctx->minfo->nvars; flint_bitcnt_t bits = A->bits; fq_nmod_struct * alphas, * betas; flint_rand_t state; fq_nmod_mpoly_t cont; fq_nmod_mpoly_t T, G, Abar, Bbar; n_fq_polyun_t HG, HAbar, HBbar, MG, MAbar, MBbar, ZG, ZAbar, ZBbar; n_fq_bpoly_t Aev, Bev, Gev, Abarev, Bbarev; const mp_limb_t * gammaev; fq_nmod_mpolyn_t Tn, Gn, Abarn, Bbarn; slong lastdeg; slong cur_zip_image, req_zip_images, this_length; n_fq_polyun_t Aeh_cur, Aeh_inc, Beh_cur, Beh_inc; n_fq_poly_t gammaeh_cur, gammaeh_inc; fq_nmod_mpoly_struct * Aevals, * Bevals; fq_nmod_mpoly_struct * gammaevals; n_fq_poly_t modulus, alphapow; n_poly_bpoly_stack_t St; fq_nmod_t start_alpha; n_poly_t tmp; /* tmp arithmetic space */ ulong GdegboundXY, newdegXY, Abideg, Bbideg; slong degxAB, degyAB; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t lgctx; fq_nmod_mpolyn_t gamman; fq_nmod_mpolyn_t An, Bn; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == gamma->bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(gamma->length > 0); fq_nmod_mpoly_fit_length_reset_bits(rG, 1, bits, smctx); fq_nmod_mpoly_fit_length_reset_bits(rAbar, 1, bits, smctx); fq_nmod_mpoly_fit_length_reset_bits(rBbar, 1, bits, smctx); #if FLINT_WANT_ASSERT { slong * tmp_degs = FLINT_ARRAY_ALLOC(nvars, slong); fq_nmod_mpoly_degrees_si(tmp_degs, A, smctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Adegs[i]); fq_nmod_mpoly_degrees_si(tmp_degs, B, smctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Bdegs[i]); fq_nmod_mpoly_degrees_si(tmp_degs, gamma, smctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == gammadegs[i]); flint_free(tmp_degs); } #endif FLINT_ASSERT(gammadegs[0] == 0); FLINT_ASSERT(gammadegs[1] == 0); n_fq_polyun_init(HG); n_fq_polyun_init(HAbar); n_fq_polyun_init(HBbar); n_fq_polyun_init(MG); n_fq_polyun_init(MAbar); n_fq_polyun_init(MBbar); n_fq_polyun_init(ZG); n_fq_polyun_init(ZAbar); n_fq_polyun_init(ZBbar); n_fq_bpoly_init(Aev); n_fq_bpoly_init(Bev); n_fq_bpoly_init(Gev); n_fq_bpoly_init(Abarev); n_fq_bpoly_init(Bbarev); fq_nmod_mpoly_init3(cont, 1, bits, smctx); fq_nmod_mpoly_init3(T, 0, bits, smctx); fq_nmod_mpoly_init3(G, 0, bits, smctx); fq_nmod_mpoly_init3(Abar, 0, bits, smctx); fq_nmod_mpoly_init3(Bbar, 0, bits, smctx); fq_nmod_mpolyn_init(Tn, bits, smctx); fq_nmod_mpolyn_init(Gn, bits, smctx); fq_nmod_mpolyn_init(Abarn, bits, smctx); fq_nmod_mpolyn_init(Bbarn, bits, smctx); n_fq_polyun_init(Aeh_cur); n_fq_polyun_init(Aeh_inc); n_fq_polyun_init(Beh_cur); n_fq_polyun_init(Beh_inc); n_fq_poly_init(gammaeh_cur); n_fq_poly_init(gammaeh_inc); n_fq_poly_init(modulus); n_poly_stack_init(St->poly_stack); n_bpoly_stack_init(St->bpoly_stack); fq_nmod_mpolyn_init(An, bits, smctx); fq_nmod_mpolyn_init(Bn, bits, smctx); fq_nmod_mpolyn_init(gamman, bits, smctx); /* alphas[nvars - 1] not used - it is replaced by cur_emb */ betas = FLINT_ARRAY_ALLOC(nvars, fq_nmod_struct); alphas = FLINT_ARRAY_ALLOC(nvars, fq_nmod_struct); for (i = 0; i < nvars; i++) { fq_nmod_init(betas + i, smctx->fqctx); fq_nmod_init(alphas + i, smctx->fqctx); } flint_randinit(state); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, lgctx, smctx, state); lgd = fq_nmod_ctx_degree(lgctx->fqctx); n_poly_init2(tmp, lgd); n_poly_init2(alphapow, 2*lgd); fq_nmod_init(start_alpha, lgctx->fqctx); /* Aevals[nvars] does not exist - it is replaced by An */ Aevals = FLINT_ARRAY_ALLOC(nvars, fq_nmod_mpoly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars, fq_nmod_mpoly_struct); gammaevals = FLINT_ARRAY_ALLOC(nvars, fq_nmod_mpoly_struct); for (i = 0; i < nvars; i++) { fq_nmod_mpoly_init3(Aevals + i, 0, bits, smctx); fq_nmod_mpoly_init3(Bevals + i, 0, bits, smctx); fq_nmod_mpoly_init3(gammaevals + i, 0, bits, smctx); } fq_nmod_mpoly_cvtto_mpolyn(An, A, nvars - 1, smctx); fq_nmod_mpoly_cvtto_mpolyn(Bn, B, nvars - 1, smctx); fq_nmod_mpoly_cvtto_mpolyn(gamman, gamma, nvars - 1, smctx); Abideg = _fq_nmod_mpoly_bidegree(A, smctx); Bbideg = _fq_nmod_mpoly_bidegree(B, smctx); degxAB = FLINT_MAX(Adegs[0], Bdegs[0]); degyAB = FLINT_MAX(Adegs[1], Bdegs[1]); GdegboundXY = pack_exp2(FLINT_MIN(Adegs[0], Bdegs[0]), FLINT_MIN(Adegs[1], Bdegs[1])); if (GdegboundXY == 0) goto gcd_is_trivial; goto got_alpha_m; increase_degree: do { cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, lgctx, smctx, state); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto cleanup; } } while (fq_nmod_ctx_degree(lgctx->fqctx) <= lgd); lgd = fq_nmod_ctx_degree(lgctx->fqctx); goto got_alpha_m; choose_main: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, lgctx, smctx, state); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto cleanup; } lgd = fq_nmod_ctx_degree(lgctx->fqctx); got_alpha_m: n_poly_fit_length(tmp, lgd); n_poly_fit_length(alphapow, 2*lgd); for (i = 2; i < nvars - 1; i++) fq_nmod_rand_not_zero(alphas + i, state, lgctx->fqctx); i = nvars - 1; fq_nmod_mpolyn_interp_reduce_lg_mpoly(Aevals + i, An, lgctx, smctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_mpoly(Bevals + i, Bn, lgctx, smctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_mpoly(gammaevals + i, gamman, lgctx, smctx, cur_emb); if (fq_nmod_mpoly_is_zero(gammaevals + i, lgctx)) goto choose_main; if (Aevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + i, lgctx) != Abideg) goto choose_main; if (Bevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + i, lgctx) != Bbideg) goto choose_main; for (i--; i >= 2; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + i, Aevals + i + 1, i, alphas + i, lgctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + i, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + i, Bevals + i + 1, i, alphas + i, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + i, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + i, gammaevals + i + 1, i, alphas + i, lgctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + i, bits, lgctx); if (fq_nmod_mpoly_is_zero(gammaevals + i, lgctx)) goto choose_main; if (Aevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + i, lgctx) != Abideg) goto choose_main; if (Bevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + i, lgctx) != Bbideg) goto choose_main; } m = 2; if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = mpoly_gcd_get_use_first(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m]); fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, lgctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, lgctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_main; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, lgctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, lgctx->fqctx); if (nvars == 3) { fq_nmod_mpolyn_interp_lift_lg_bpoly(&lastdeg, Gn, smctx, Gev, lgctx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_bpoly(&lastdeg, Abarn, smctx, Abarev, lgctx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_bpoly(&lastdeg, Bbarn, smctx, Bbarev, lgctx, cur_emb); n_fq_poly_set(modulus, cur_emb->h_as_n_fq_poly, smctx->fqctx); while (1) { choose_alpha_2_last: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, lgctx, smctx, state); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto cleanup; } lgd = fq_nmod_ctx_degree(lgctx->fqctx); n_poly_fit_length(tmp, lgd); n_poly_fit_length(alphapow, 2*lgd); fq_nmod_mpolyn_interp_reduce_lg_mpoly(Aevals + m, An, lgctx, smctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_mpoly(Bevals + m, Bn, lgctx, smctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_mpoly(gammaevals + m, gamman, lgctx, smctx, cur_emb); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_2_last; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_2_last; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_2_last; fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, lgctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, lgctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alpha_2_last; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_main; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, lgctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, lgctx->fqctx); if ((use & USE_G) && !fq_nmod_mpolyn_interp_crt_lg_bpoly( &lastdeg, Gn, Tn, modulus, smctx, Gev, lgctx, cur_emb)) { fq_nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, smctx); success = fq_nmod_mpolyl_content(cont, rG, 2, smctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rG, rG, cont, smctx); fq_nmod_mpoly_repack_bits_inplace(rG, bits, smctx); if (fq_nmod_mpoly_divides(rAbar, A, rG, smctx) && fq_nmod_mpoly_divides(rBbar, B, rG, smctx)) { fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_ABAR) && !fq_nmod_mpolyn_interp_crt_lg_bpoly( &lastdeg, Abarn, Tn, modulus, smctx, Abarev, lgctx, cur_emb)) { fq_nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, smctx); success = fq_nmod_mpolyl_content(cont, rAbar, 2, smctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rAbar, rAbar, cont, smctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); if (fq_nmod_mpoly_divides(rG, A, rAbar, smctx) && fq_nmod_mpoly_divides(rBbar, B, rG, smctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, smctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_BBAR) && !fq_nmod_mpolyn_interp_crt_lg_bpoly( &lastdeg, Bbarn, Tn, modulus, smctx, Bbarev, lgctx, cur_emb)) { fq_nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, smctx); success = fq_nmod_mpolyl_content(cont, rBbar, 2, smctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rBbar, rBbar, cont, smctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); if (fq_nmod_mpoly_divides(rG, B, rBbar, smctx) && fq_nmod_mpoly_divides(rAbar, A, rG, smctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, smctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); break; } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_main; } n_fq_poly_mul_(modulus, modulus, cur_emb->h_as_n_fq_poly, smctx->fqctx, St->poly_stack); } success = 1; goto cleanup; } fq_nmod_mpolyn_interp_lift_sm_bpoly(Gn, Gev, lgctx); fq_nmod_mpolyn_interp_lift_sm_bpoly(Abarn, Abarev, lgctx); fq_nmod_mpolyn_interp_lift_sm_bpoly(Bbarn, Bbarev, lgctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_one(modulus, lgctx->fqctx); n_fq_set_fq_nmod(tmp->coeffs, alphas + m, lgctx->fqctx); n_fq_poly_shift_left_scalar_submul(modulus, 1, tmp->coeffs, lgctx->fqctx); fq_nmod_set(start_alpha, alphas + m, lgctx->fqctx); while (1) { choose_alpha_2: fq_nmod_next_not_zero(alphas + m, lgctx->fqctx); if (fq_nmod_equal(alphas + m, start_alpha, lgctx->fqctx)) goto increase_degree; FLINT_ASSERT(alphapow->alloc >= lgd*2); alphapow->length = 2; _n_fq_one(alphapow->coeffs + lgd*0, lgd); n_fq_set_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + m, Aevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + m, Bevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + m, gammaevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, lgctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_2; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_2; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_2; fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, lgctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, lgctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alpha_2; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_main; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, lgctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, lgctx->fqctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_pow(tmp->coeffs, modulus, alphapow, lgctx->fqctx); n_fq_inv(tmp->coeffs, tmp->coeffs, lgctx->fqctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Gn, Tn, Gev, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(G, Gn, m, lgctx); fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(Abar, T, G, lgctx)) { fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(Bbar, T, G, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(Abar, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bbar, bits, lgctx); break; } } } if ((use & USE_ABAR) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Abarn, Tn, Abarev, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(Abar, Abarn, m, lgctx); fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(G, T, Abar, lgctx)) { fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(Bbar, T, G, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(G, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bbar, bits, lgctx); break; } } } if ((use & USE_BBAR) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Bbarn, Tn, Bbarev, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(Bbar, Bbarn, m, lgctx); fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(G, T, Bbar, lgctx)) { fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(Abar, T, G, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(G, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(Abar, bits, lgctx); break; } } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_main; } FLINT_ASSERT(n_fq_equal_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx)); n_fq_poly_shift_left_scalar_submul(modulus, 1, alphapow->coeffs + lgd*1, lgctx->fqctx); } for (m = 3; m < nvars - 1; m++) { /* G, Abar, Bbar are in Fq[gen(0), ..., gen(m - 1)] */ fq_nmod_mpolyn_interp_lift_sm_mpoly(Gn, G, lgctx); fq_nmod_mpolyn_interp_lift_sm_mpoly(Abarn, Abar, lgctx); fq_nmod_mpolyn_interp_lift_sm_mpoly(Bbarn, Bbar, lgctx); if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = 0; FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_one(modulus, lgctx->fqctx); n_fq_set_fq_nmod(tmp->coeffs, alphas + m, lgctx->fqctx); n_fq_poly_shift_left_scalar_submul(modulus, 1, tmp->coeffs, lgctx->fqctx); fq_nmod_set(start_alpha, alphas + m, lgctx->fqctx); choose_betas_m: /* only beta[2], beta[1], ..., beta[m - 1] will be used */ for (i = 2; i < nvars; i++) fq_nmod_rand_not_zero(betas + i, state, lgctx->fqctx); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(Abar->bits == bits); FLINT_ASSERT(Bbar->bits == bits); fq_nmod_mpoly_monomial_evals2(HG, G, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HAbar, Abar, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HBbar, Bbar, betas + 2, m, lgctx); if (use == 0) { this_length = gammaevals[m + 1].length + Aevals[m + 1].length + Bevals[m + 1].length; use = nmod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar); } req_zip_images = 1; if (use & USE_G) { this_length = n_fq_polyun_product_roots(MG, HG, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_ABAR) { this_length = n_fq_polyun_product_roots(MAbar, HAbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_BBAR) { this_length = n_fq_polyun_product_roots(MBbar, HBbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } while (1) { choose_alpha_m: fq_nmod_next_not_zero(alphas + m, lgctx->fqctx); if (fq_nmod_equal(alphas + m, start_alpha, lgctx->fqctx)) goto choose_main; FLINT_ASSERT(alphapow->alloc >= lgd*2); alphapow->length = 2; _n_fq_one(alphapow->coeffs + lgd*0, lgd); n_fq_set_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + m, Aevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + m, Bevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + m, gammaevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, lgctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_m; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_m; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_m; fq_nmod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(Beh_inc, Bevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, betas + 2, 2, m, lgctx); n_fq_polyun_set(Aeh_cur, Aeh_inc, lgctx->fqctx); n_fq_polyun_set(Beh_cur, Beh_inc, lgctx->fqctx); n_fq_poly_set(gammaeh_cur, gammaeh_inc, lgctx->fqctx); n_fq_polyun_zip_start(ZG, HG, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZAbar, HAbar, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZBbar, HBbar, req_zip_images, lgctx->fqctx); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { n_fq_bpoly_eval_step_sep(Aev, Aeh_cur, Aeh_inc, Aevals + m, lgctx->fqctx); n_fq_bpoly_eval_step_sep(Bev, Beh_cur, Beh_inc, Bevals + m, lgctx->fqctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_step_sep(tmp->coeffs, gammaeh_cur, gammaeh_inc, gammaevals + m, lgctx->fqctx); if (_n_fq_is_zero(tmp->coeffs, lgd)) goto choose_betas_m; if (Aev->length < 1 || n_bpoly_bidegree(Aev) != Abideg) goto choose_betas_m; if (Bev->length < 1 || n_bpoly_bidegree(Bev) != Bbideg) goto choose_betas_m; success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_betas_m; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_main; } n_fq_bpoly_scalar_mul_n_fq(Gev, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !n_fq_polyu2n_add_zip_must_match(ZG, Gev, cur_zip_image, lgctx->fqctx)) goto choose_main; if ((use & USE_ABAR) && !n_fq_polyu2n_add_zip_must_match(ZAbar, Abarev, cur_zip_image, lgctx->fqctx)) goto choose_main; if ((use & USE_BBAR) && !n_fq_polyu2n_add_zip_must_match(ZBbar, Bbarev, cur_zip_image, lgctx->fqctx)) goto choose_main; } if ((use & USE_G) && n_fq_polyun_zip_solve(G, ZG, HG, MG, lgctx) < 1) goto choose_main; if ((use & USE_ABAR) && n_fq_polyun_zip_solve(Abar, ZAbar, HAbar, MAbar, lgctx) < 1) goto choose_main; if ((use & USE_BBAR) && n_fq_polyun_zip_solve(Bbar, ZBbar, HBbar, MBbar, lgctx) < 1) goto choose_main; FLINT_ASSERT(n_fq_poly_degree(modulus) > 0); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_pow(tmp->coeffs, modulus, alphapow, lgctx->fqctx); n_fq_inv(tmp->coeffs, tmp->coeffs, lgctx->fqctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Gn, G, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, lgctx); fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(rAbar, T, rG, lgctx)) { fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(rBbar, T, rG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, lgctx); fq_nmod_mpoly_swap(G, rG, lgctx); fq_nmod_mpoly_swap(Abar, rAbar, lgctx); fq_nmod_mpoly_swap(Bbar, rBbar, lgctx); break; } } } if ((use & USE_ABAR) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Abarn, Abar, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, lgctx); fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(rG, T, rAbar, lgctx)) { fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(rBbar, T, rG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, lgctx); fq_nmod_mpoly_swap(G, rG, lgctx); fq_nmod_mpoly_swap(Abar, rAbar, lgctx); fq_nmod_mpoly_swap(Bbar, rBbar, lgctx); break; } } } if ((use & USE_BBAR) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Bbarn, Bbar, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, lgctx); fq_nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(rG, T, rBbar, lgctx)) { fq_nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(rAbar, T, rG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, lgctx); fq_nmod_mpoly_swap(G, rG, lgctx); fq_nmod_mpoly_swap(Abar, rAbar, lgctx); fq_nmod_mpoly_swap(Bbar, rBbar, lgctx); break; } } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_main; } FLINT_ASSERT(n_fq_equal_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx)); n_fq_poly_shift_left_scalar_submul(modulus, 1, alphapow->coeffs + lgd*1, lgctx->fqctx); } } m = nvars - 1; { /* G, Abar, Bbar are in Fq/alpha(gen(m-1))[gen(0), ..., gen(m - 1)] */ fq_nmod_mpolyn_interp_lift_lg_mpoly(Gn, smctx, G, lgctx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_mpoly(Abarn, smctx, Abar, lgctx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_mpoly(Bbarn, smctx, Bbar, lgctx, cur_emb); if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = 0; n_fq_poly_set(modulus, cur_emb->h_as_n_fq_poly, smctx->fqctx); while (1) { choose_alpha_last: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, lgctx, smctx, state); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto cleanup; } lgd = fq_nmod_ctx_degree(lgctx->fqctx); n_poly_fit_length(tmp, lgd); n_poly_fit_length(alphapow, 2*lgd); fq_nmod_mpolyn_interp_reduce_lg_mpoly(Aevals + m, An, lgctx, smctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_mpoly(Bevals + m, Bn, lgctx, smctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_mpoly(gammaevals + m, gamman, lgctx, smctx, cur_emb); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_last; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_last; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_last; choose_betas_last: /* only beta[2], ..., beta[m - 1] will be used */ for (i = 2; i < nvars; i++) fq_nmod_rand_not_zero(betas + i, state, lgctx->fqctx); fq_nmod_mpoly_monomial_evals2(HG, G, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HAbar, Abar, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HBbar, Bbar, betas + 2, m, lgctx); if (use == 0) { this_length = gamma->length + A->length + B->length; use = nmod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar); } req_zip_images = 1; if (use & USE_G) { this_length = n_fq_polyun_product_roots(MG, HG, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_ABAR) { this_length = n_fq_polyun_product_roots(MAbar, HAbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_BBAR) { this_length = n_fq_polyun_product_roots(MBbar, HBbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } fq_nmod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(Beh_inc, Bevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, betas + 2, 2, m, lgctx); n_fq_polyun_set(Aeh_cur, Aeh_inc, lgctx->fqctx); n_fq_polyun_set(Beh_cur, Beh_inc, lgctx->fqctx); n_fq_poly_set(gammaeh_cur, gammaeh_inc, lgctx->fqctx); n_fq_polyun_zip_start(ZG, HG, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZAbar, HAbar, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZBbar, HBbar, req_zip_images, lgctx->fqctx); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { n_fq_bpoly_eval_step_sep(Aev, Aeh_cur, Aeh_inc, Aevals + m, lgctx->fqctx); n_fq_bpoly_eval_step_sep(Bev, Beh_cur, Beh_inc, Bevals + m, lgctx->fqctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_step_sep(tmp->coeffs, gammaeh_cur, gammaeh_inc, gammaevals + m, lgctx->fqctx); if (_n_fq_is_zero(tmp->coeffs, lgd)) goto choose_betas_last; if (Aev->length < 1 || n_bpoly_bidegree(Aev) != Abideg) goto choose_betas_last; if (Bev->length < 1 || n_bpoly_bidegree(Bev) != Bbideg) goto choose_betas_last; success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_betas_last; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_main; } n_fq_bpoly_scalar_mul_n_fq(Gev, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !n_fq_polyu2n_add_zip_must_match(ZG, Gev, cur_zip_image, lgctx->fqctx)) goto choose_main; if ((use & USE_ABAR) && !n_fq_polyu2n_add_zip_must_match(ZAbar, Abarev, cur_zip_image, lgctx->fqctx)) goto choose_main; if ((use & USE_BBAR) && !n_fq_polyu2n_add_zip_must_match(ZBbar, Bbarev, cur_zip_image, lgctx->fqctx)) goto choose_main; } if ((use & USE_G) && n_fq_polyun_zip_solve(G, ZG, HG, MG, lgctx) < 1) goto choose_main; if ((use & USE_ABAR) && n_fq_polyun_zip_solve(Abar, ZAbar, HAbar, MAbar, lgctx) < 1) goto choose_main; if ((use & USE_BBAR) && n_fq_polyun_zip_solve(Bbar, ZBbar, HBbar, MBbar, lgctx) < 1) goto choose_main; FLINT_ASSERT(n_fq_poly_degree(modulus) > 0); FLINT_ASSERT(tmp->alloc >= lgd); bad_n_fq_embed_sm_to_lg(tmp->coeffs, modulus, cur_emb); n_fq_inv(tmp->coeffs, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !newfq_nmod_mpolyn_interp_mcrt_lg_mpoly( &lastdeg, Gn, smctx, modulus, tmp->coeffs, G, lgctx, cur_emb)) { fq_nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, smctx); success = fq_nmod_mpolyl_content(cont, rG, 2, smctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rG, rG, cont, smctx); fq_nmod_mpoly_repack_bits_inplace(rG, bits, smctx); if (fq_nmod_mpoly_divides(rAbar, A, rG, smctx) && fq_nmod_mpoly_divides(rBbar, B, rG, smctx)) { fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_ABAR) && !newfq_nmod_mpolyn_interp_mcrt_lg_mpoly( &lastdeg, Abarn, smctx, modulus, tmp->coeffs, Abar, lgctx, cur_emb)) { fq_nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, smctx); success = fq_nmod_mpolyl_content(cont, rAbar, 2, smctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rAbar, rAbar, cont, smctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); if (fq_nmod_mpoly_divides(rG, A, rAbar, smctx) && fq_nmod_mpoly_divides(rBbar, B, rG, smctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, smctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_BBAR) && !newfq_nmod_mpolyn_interp_mcrt_lg_mpoly( &lastdeg, Bbarn, smctx, modulus, tmp->coeffs, Bbar, lgctx, cur_emb)) { fq_nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, smctx); success = fq_nmod_mpolyl_content(cont, rBbar, 2, smctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(rBbar, rBbar, cont, smctx); fq_nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); if (fq_nmod_mpoly_divides(rG, B, rBbar, smctx) && fq_nmod_mpoly_divides(rAbar, A, rG, smctx)) { fq_nmod_mpoly_repack_bits_inplace(rG, bits, smctx); fq_nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); break; } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_main; } n_fq_poly_mul_(modulus, modulus, cur_emb->h_as_n_fq_poly, smctx->fqctx, St->poly_stack); } } success = 1; cleanup: for (i = 0; i < nvars; i++) { fq_nmod_clear(betas + i, smctx->fqctx); fq_nmod_clear(alphas + i, smctx->fqctx); } flint_free(betas); flint_free(alphas); fq_nmod_mpolyn_clear(An, smctx); fq_nmod_mpolyn_clear(Bn, smctx); fq_nmod_mpolyn_clear(gamman, smctx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, lgctx, smctx, state); n_fq_polyun_clear(HG); n_fq_polyun_clear(HAbar); n_fq_polyun_clear(HBbar); n_fq_polyun_clear(MG); n_fq_polyun_clear(MAbar); n_fq_polyun_clear(MBbar); n_fq_polyun_clear(ZG); n_fq_polyun_clear(ZAbar); n_fq_polyun_clear(ZBbar); n_fq_bpoly_clear(Aev); n_fq_bpoly_clear(Bev); n_fq_bpoly_clear(Gev); n_fq_bpoly_clear(Abarev); n_fq_bpoly_clear(Bbarev); fq_nmod_mpoly_clear(cont, smctx); fq_nmod_mpoly_clear(T, smctx); fq_nmod_mpoly_clear(G, smctx); fq_nmod_mpoly_clear(Abar, smctx); fq_nmod_mpoly_clear(Bbar, smctx); fq_nmod_mpolyn_clear(Tn, smctx); fq_nmod_mpolyn_clear(Gn, smctx); fq_nmod_mpolyn_clear(Abarn, smctx); fq_nmod_mpolyn_clear(Bbarn, smctx); n_fq_polyun_clear(Aeh_cur); n_fq_polyun_clear(Aeh_inc); n_fq_polyun_clear(Beh_cur); n_fq_polyun_clear(Beh_inc); n_fq_poly_clear(gammaeh_cur); n_fq_poly_clear(gammaeh_inc); n_fq_poly_clear(modulus); n_poly_stack_clear(St->poly_stack); n_bpoly_stack_clear(St->bpoly_stack); n_poly_clear(tmp); n_fq_poly_clear(alphapow); fq_nmod_clear(start_alpha, smctx->fqctx); flint_randclear(state); for (i = 0; i < nvars; i++) { fq_nmod_mpoly_clear(Aevals + i, smctx); fq_nmod_mpoly_clear(Bevals + i, smctx); fq_nmod_mpoly_clear(gammaevals + i, smctx); } flint_free(Aevals); flint_free(Bevals); flint_free(gammaevals); FLINT_ASSERT(!success || rG->bits == bits); FLINT_ASSERT(!success || rAbar->bits == bits); FLINT_ASSERT(!success || rBbar->bits == bits); return success; gcd_is_trivial: fq_nmod_mpoly_one(rG, smctx); fq_nmod_mpoly_set(rAbar, A, smctx); fq_nmod_mpoly_set(rBbar, B, smctx); success = 1; goto cleanup; } /* should find its way back here in interesting cases */ int fq_nmod_mpoly_gcd_zippel2( fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { if (fq_nmod_mpoly_is_zero(A, ctx) || fq_nmod_mpoly_is_zero(B, ctx)) return fq_nmod_mpoly_gcd(G, A, B, ctx); return _fq_nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL2); } flint-3.1.3/src/fq_nmod_mpoly/gen.c000066400000000000000000000017771461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_gen( fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits; bits = mpoly_gen_bits_required(var, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, 1, bits, ctx); _n_fq_one(A->coeffs, fq_nmod_ctx_degree(ctx->fqctx)); if (bits <= FLINT_BITS) mpoly_gen_monomial_sp(A->exps, var, bits, ctx->minfo); else mpoly_gen_monomial_offset_mp(A->exps, var, bits, ctx->minfo); _fq_nmod_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/fq_nmod_mpoly/geobuckets.c000066400000000000000000000103451461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_geobucket_init(fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { fq_nmod_mpoly_init(B->polys + i, ctx); fq_nmod_mpoly_init(B->temps + i, ctx); } B->length = 0; } void fq_nmod_mpoly_geobucket_clear(fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { fq_nmod_mpoly_clear(B->polys + i, ctx); fq_nmod_mpoly_clear(B->temps + i, ctx); } } /* empty out bucket B into polynomial p */ void fq_nmod_mpoly_geobucket_empty(fq_nmod_mpoly_t p, fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (B->length < 2) { if (B->length < 1) fq_nmod_mpoly_zero(p, ctx); else fq_nmod_mpoly_set(p, B->polys + 0, ctx); } else if (B->length == 2) { fq_nmod_mpoly_add(p, B->polys + 1, B->polys + 0, ctx); } else { fq_nmod_mpoly_add(B->temps + 1, B->polys + 1, B->polys + 0, ctx); for (i = 2; i < B->length - 1; i++) fq_nmod_mpoly_add(B->temps + i, B->polys + i, B->temps + i - 1, ctx); fq_nmod_mpoly_add(p, B->polys + i, B->temps + i - 1, ctx); } B->length = 0; } void fq_nmod_mpoly_geobucket_fit_length(fq_nmod_mpoly_geobucket_t B, slong len, const fq_nmod_mpoly_ctx_t ctx) { slong j; for (j = B->length; j < len; j++) fq_nmod_mpoly_zero(B->polys + j, ctx); B->length = j; } /* set bucket B to polynomial p */ void fq_nmod_mpoly_geobucket_set(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx) { slong i = mpoly_geobucket_clog4(p->length); B->length = 0; fq_nmod_mpoly_geobucket_fit_length(B, i + 1, ctx); fq_nmod_mpoly_swap(B->polys + i, p, ctx); B->length = i + 1; } /* internal function for fixing overflows */ void _fq_nmod_mpoly_geobucket_fix(fq_nmod_mpoly_geobucket_t B, slong i, const fq_nmod_mpoly_ctx_t ctx) { while (mpoly_geobucket_clog4((B->polys + i)->length) > i) { FLINT_ASSERT(i + 1 <= B->length); if (i + 1 == B->length) { B->length = i + 2; fq_nmod_mpoly_set(B->polys + i + 1, B->polys + i, ctx); } else { fq_nmod_mpoly_add(B->temps + i + 1, B->polys + i + 1, B->polys + i, ctx); fq_nmod_mpoly_swap(B->polys + i + 1, B->temps + i + 1, ctx); } fq_nmod_mpoly_zero(B->polys + i, ctx); i++; } } /* add polynomial p to buckect B */ void fq_nmod_mpoly_geobucket_add(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (fq_nmod_mpoly_is_zero(p, ctx)) return; i = mpoly_geobucket_clog4(p->length); fq_nmod_mpoly_geobucket_fit_length(B, i + 1, ctx); fq_nmod_mpoly_add(B->temps + i, B->polys + i, p, ctx); fq_nmod_mpoly_swap(B->polys + i, B->temps + i, ctx); _fq_nmod_mpoly_geobucket_fix(B, i, ctx); } /* sub polynomial p to buckect B */ void fq_nmod_mpoly_geobucket_sub(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (fq_nmod_mpoly_is_zero(p, ctx)) return; i = mpoly_geobucket_clog4(p->length); fq_nmod_mpoly_geobucket_fit_length(B, i + 1, ctx); fq_nmod_mpoly_sub(B->temps + i, B->polys + i, p, ctx); fq_nmod_mpoly_swap(B->polys + i, B->temps + i, ctx); _fq_nmod_mpoly_geobucket_fix(B, i, ctx); } flint-3.1.3/src/fq_nmod_mpoly/get_coeff_fq_nmod_fmpz.c000066400000000000000000000020031461254215100231040ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_coeff_fq_nmod_fmpz( fq_nmod_t c, const fq_nmod_mpoly_t A, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_pfmpz(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { fq_nmod_zero(c, ctx->fqctx); } else { slong d = fq_nmod_ctx_degree(ctx->fqctx); FLINT_ASSERT(index < A->length); n_fq_get_fq_nmod(c, A->coeffs + d*index, ctx->fqctx); } } flint-3.1.3/src/fq_nmod_mpoly/get_coeff_fq_nmod_monomial.c000066400000000000000000000035161461254215100237550ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_coeff_fq_nmod_monomial( fq_nmod_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t M, const fq_nmod_mpoly_ctx_t ctx) { slong index, N; ulong * cmpmask, * pexp; int exists; TMP_INIT; if (M->length != WORD(1)) { flint_throw(FLINT_ERROR, "M not monomial in fq_nmod_mpoly_get_coeff_fq_nmod_monomial"); } TMP_START; N = mpoly_words_per_exp(A->bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); pexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, A->bits, ctx->minfo); if (M->bits == A->bits) { mpoly_monomial_set(pexp, M->exps + N*0, N); } else { int could_repack = mpoly_repack_monomials(pexp, A->bits, M->exps + N*0, M->bits, 1, ctx->minfo); if (!could_repack) { FLINT_ASSERT(M->bits > A->bits); fq_nmod_zero(c, ctx->fqctx); goto clean_up; } } exists = mpoly_monomial_exists(&index, A->exps, pexp, A->length, N, cmpmask); if (!exists) { fq_nmod_zero(c, ctx->fqctx); } else { slong d = fq_nmod_ctx_degree(ctx->fqctx); FLINT_ASSERT(index < A->length); n_fq_get_fq_nmod(c, A->coeffs + d*index, ctx->fqctx); } clean_up: TMP_END; return; } flint-3.1.3/src/fq_nmod_mpoly/get_coeff_fq_nmod_ui.c000066400000000000000000000020121461254215100225450ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_coeff_fq_nmod_ui(fq_nmod_t c, const fq_nmod_mpoly_t A, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_ui(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { fq_nmod_zero(c, ctx->fqctx); } else { slong d = fq_nmod_ctx_degree(ctx->fqctx); FLINT_ASSERT(index < A->length); n_fq_get_fq_nmod(c, A->coeffs + d*index, ctx->fqctx); } } flint-3.1.3/src/fq_nmod_mpoly/get_coeff_vars_ui.c000066400000000000000000000104101461254215100220760ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_coeff_vars_ui( fq_nmod_mpoly_t C, const fq_nmod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong i, j; slong offset, shift; slong maxoffset, minoffset; ulong * uexp; ulong * tmask, * texp; slong nvars = ctx->minfo->nvars; mp_limb_t * Ccoeffs; ulong * Cexps; slong Clen; TMP_INIT; if (C == A) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_get_coeff_vars_ui(T, A, vars, exps, length, ctx); fq_nmod_mpoly_swap(T, C, ctx); fq_nmod_mpoly_clear(T, ctx); return; } TMP_START; uexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); for (i = 0; i < nvars; i++) uexp[i] = 0; for (i = 0; i < length; i++) uexp[vars[i]] = exps[i]; if (bits < mpoly_exp_bits_required_ui(uexp, ctx->minfo)) { fq_nmod_mpoly_zero(C, ctx); goto cleanup; } fq_nmod_mpoly_fit_length_reset_bits(C, 4, bits, ctx); tmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(tmask, N); mpoly_set_monomial_ui(texp, uexp, bits, ctx->minfo); if (bits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { mpoly_gen_offset_shift_sp(&offset, &shift, vars[i], bits, ctx->minfo); tmask[offset] |= mask << shift; maxoffset = FLINT_MAX(maxoffset, offset); minoffset = FLINT_MIN(minoffset, offset); } FLINT_ASSERT(minoffset < N); Ccoeffs = C->coeffs; Cexps = C->exps; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_sp; } _fq_nmod_mpoly_fit_length(&Ccoeffs, &C->coeffs_alloc, d, &Cexps, &C->exps_alloc, N, Clen + 1); mpoly_monomial_sub(Cexps + N*Clen, A->exps + N*i, texp, N); _n_fq_set(Ccoeffs + d*Clen, A->coeffs + d*i, d); Clen++; continue_outer_sp:; } C->coeffs = Ccoeffs; C->exps = Cexps; _fq_nmod_mpoly_set_length(C, Clen, ctx); } else { ulong wpf = A->bits/FLINT_BITS; maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { offset = mpoly_gen_offset_mp(vars[i], A->bits, ctx->minfo); minoffset = FLINT_MIN(minoffset, offset); maxoffset = FLINT_MAX(maxoffset, offset + wpf - 1); for (j = 0; j < wpf; j++) tmask[offset + j] = -UWORD(1); } FLINT_ASSERT(minoffset < N); Ccoeffs = C->coeffs; Cexps = C->exps; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_mp; } _fq_nmod_mpoly_fit_length(&Ccoeffs, &C->coeffs_alloc, d, &Cexps, &C->exps_alloc, N, Clen + 1); mpoly_monomial_sub_mp(Cexps + N*Clen, A->exps + N*i, texp, N); _n_fq_set(Ccoeffs + d*Clen, A->coeffs + d*i, d); Clen++; continue_outer_mp:; } C->coeffs = Ccoeffs; C->exps = Cexps; _fq_nmod_mpoly_set_length(C, Clen, ctx); } cleanup: TMP_END; return; } flint-3.1.3/src/fq_nmod_mpoly/get_fq_nmod.c000066400000000000000000000020141461254215100207100ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_fq_nmod( fq_nmod_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong N; if (A->length > 1) flint_throw(FLINT_ERROR, "fq_nmod_mpoly_get_fq_nmod: nonconstant polynomial"); if (A->length < 1) { fq_nmod_zero(c, ctx->fqctx); return; } N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) flint_throw(FLINT_ERROR, "fq_nmod_mpoly_get_fq_nmod: nonconstant polynomial"); n_fq_get_fq_nmod(c, A->coeffs, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/get_set_is_fq_nmod_poly.c000066400000000000000000000101511461254215100233220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_is_fq_nmod_poly( const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { return mpoly_is_poly(A->exps, A->length, A->bits, var, ctx->minfo); } int fq_nmod_mpoly_get_fq_nmod_poly( fq_nmod_poly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong Blen = B->length; const mp_limb_t * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t Bbits = B->bits; slong i, N = mpoly_words_per_exp(Bbits, ctx->minfo); ulong k; int success; fq_nmod_t t; fq_nmod_init(t, ctx->fqctx); fq_nmod_poly_zero(A, ctx->fqctx); if (B->length < 1) { success = 1; goto cleanup; } if (Bbits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - Bbits); slong off, shift; mpoly_gen_offset_shift_sp(&off, &shift, var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; n_fq_get_fq_nmod(t, Bcoeffs + d*i, ctx->fqctx); fq_nmod_poly_set_coeff(A, k, t, ctx->fqctx); } success = 1; goto cleanup; } else { slong j, off; ulong check, wpf = Bbits/FLINT_BITS; off = mpoly_gen_offset_mp(var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = Bexps[N*i + off + 0]; check = 0; for (j = 1; j < wpf; j++) check |= Bexps[N*i + off + j]; if (check != 0 || (slong) k < 0) { success = 0; goto cleanup; } n_fq_get_fq_nmod(t, Bcoeffs + d*i, ctx->fqctx); fq_nmod_poly_set_coeff(A, k, t, ctx->fqctx); } success = 1; goto cleanup; } cleanup: fq_nmod_clear(t, ctx->fqctx); return success; } void _fq_nmod_mpoly_set_fq_nmod_poly( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_struct * Bcoeffs, slong Blen, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += !fq_nmod_is_zero(Bcoeffs + i, ctx->fqctx); fq_nmod_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { if (fq_nmod_is_zero(Bcoeffs + i, ctx->fqctx)) continue; FLINT_ASSERT(d*Alen < A->coeffs_alloc); FLINT_ASSERT(N*Alen < A->exps_alloc); n_fq_set_fq_nmod(A->coeffs + d*Alen, Bcoeffs + i, ctx->fqctx); if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } void fq_nmod_mpoly_set_fq_nmod_poly( fq_nmod_mpoly_t A, const fq_nmod_poly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits; if (B->length < 1) { fq_nmod_mpoly_zero(A, ctx); return; } bits = mpoly_gen_pow_exp_bits_required(var, B->length - 1, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); _fq_nmod_mpoly_set_fq_nmod_poly(A, bits, B->coeffs, B->length, var, ctx); } flint-3.1.3/src/fq_nmod_mpoly/get_str_pretty.c000066400000000000000000000074251461254215100215170ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" #define ALLOC_PER_VAR ((FLINT_BITS+4)/3) char * _fq_nmod_mpoly_get_str_pretty( const mp_limb_t * coeff, const ulong * exp, slong len, const char ** x_in, slong bits, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); char * str, ** x = (char **) x_in, *xtmp; slong i, j, N, bound, off; fmpz * exponents; int first; char ** coeffstrs; TMP_INIT; if (len == 0) { str = flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } N = mpoly_words_per_exp(bits, ctx->minfo); TMP_START; if (x == NULL) { xtmp = (char *) TMP_ALLOC(ctx->minfo->nvars * ALLOC_PER_VAR * sizeof(char)); x = (char **) TMP_ALLOC(ctx->minfo->nvars*sizeof(char *)); for (i = 0; i < ctx->minfo->nvars; i++) { x[i] = xtmp + i * ALLOC_PER_VAR; flint_sprintf(x[i], "x%wd", i + 1); } } coeffstrs = (char **)flint_malloc(len * sizeof(char *)); bound = 1; for (i = 0; i < len; i++) { coeffstrs[i] = n_fq_get_str_pretty(coeff + d*i, ctx->fqctx); bound += 5 + strlen(coeffstrs[i]); } exponents = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(ulong)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(exponents + i); mpoly_degrees_ffmpz(exponents, exp, len, bits, ctx->minfo); for (i = 0; i < ctx->minfo->nvars; i++) bound += (2 + fmpz_sizeinbase(exponents + i, 10) + strlen(x[i]) + 3)*len; str = flint_malloc(bound); off = 0; for (i = 0; i < len; i++) { if (i > 0) { str[off++] = ' '; str[off++] = '+'; str[off++] = ' '; } first = _n_fq_is_one(coeff + d*i, d); if (!first) { off += flint_sprintf(str + off, "(%s)", coeffstrs[i]); } mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, ctx->minfo); for (j = 0; j < ctx->minfo->nvars; j++) { if (fmpz_is_zero(exponents + j)) continue; if (!first) { str[off++] = '*'; } if (fmpz_cmp_ui(exponents + j, UWORD(1)) > 0) { off += flint_sprintf(str + off, "%s^", x[j]); if (!COEFF_IS_MPZ(exponents[j])) off += flint_sprintf(str + off, "%wd", exponents[j]); else off += gmp_sprintf(str + off, "%Zd", COEFF_TO_PTR(exponents[j])); } else { off += flint_sprintf(str + off, "%s", x[j]); } first = 0; } if (first) { off += flint_sprintf(str + off, "1"); } FLINT_ASSERT(off < bound); } for (i = 0; i < len; i++) flint_free(coeffstrs[i]); flint_free(coeffstrs); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(exponents + i); TMP_END; return str; } char * fq_nmod_mpoly_get_str_pretty(const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx) { return _fq_nmod_mpoly_get_str_pretty(A->coeffs, A->exps, A->length, x, A->bits, ctx); } flint-3.1.3/src/fq_nmod_mpoly/get_term.c000066400000000000000000000020571461254215100202430ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_term( fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "fq_nmod_mpoly_get_term: index out of range"); } fq_nmod_mpoly_fit_length_reset_bits(M, 1, bits, ctx); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); _n_fq_set(M->coeffs + d*0, A->coeffs + d*i, d); _fq_nmod_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/fq_nmod_mpoly/get_term_coeff_fq_nmod.c000066400000000000000000000014701461254215100231060ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_term_coeff_fq_nmod( fq_nmod_t c, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "fmpz_mpoly_get_term_coeff_fmpz: index out of range"); } n_fq_get_fq_nmod(c, A->coeffs + d*i, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/get_term_exp_fmpz.c000066400000000000000000000015671461254215100221600ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_term_exp_fmpz(fmpz ** exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fq_nmod_mpoly_get_term_exp_fmpz"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_pfmpz(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/get_term_exp_si.c000066400000000000000000000015621461254215100216120ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_term_exp_si(slong * exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fq_nmod_mpoly_get_term_exp_si"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_si(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/get_term_exp_ui.c000066400000000000000000000015621461254215100216140ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_term_exp_ui(ulong * exp, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fq_nmod_mpoly_get_term_exp_ui"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_ui(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/get_term_monomial.c000066400000000000000000000020601461254215100221300ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_get_term_monomial( fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "fq_nmod_mpoly_get_term_monomial: index out of range"); } fq_nmod_mpoly_fit_length_reset_bits(M, 1, bits, ctx); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); _n_fq_one(M->coeffs + d*0, d); _fq_nmod_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/fq_nmod_mpoly/get_term_var_exp_si.c000066400000000000000000000016021461254215100224550ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" slong fq_nmod_mpoly_get_term_var_exp_si(const fq_nmod_mpoly_t A, slong i, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fq_nmod_mpoly_get_term_var_exp_si"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_get_monomial_var_exp_si(A->exps + N*i, var, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/get_term_var_exp_ui.c000066400000000000000000000016021461254215100224570ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" ulong fq_nmod_mpoly_get_term_var_exp_ui(const fq_nmod_mpoly_t A, slong i, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in fq_nmod_mpoly_get_term_var_exp_ui"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_get_monomial_var_exp_ui(A->exps + N*i, var, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/inflate.c000066400000000000000000000051041461254215100200530ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fmpz.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_inflate( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int have_zero_stride; slong j; flint_bitcnt_t Abits; slong nvars = ctx->minfo->nvars; fmpz * exps; TMP_INIT; if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_zero(A, ctx); return; } TMP_START; exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exps + j); /* quick and safe bound on bits required */ mpoly_degrees_ffmpz(exps, B->exps, B->length, B->bits, ctx->minfo); have_zero_stride = 0; for (j = 0; j < nvars; j++) { have_zero_stride |= fmpz_is_zero(stride + j); fmpz_mul(exps + j, exps + j, stride + j); fmpz_add(exps + j, exps + j, shift + j); } Abits = mpoly_exp_bits_required_ffmpz(exps, ctx->minfo); Abits = mpoly_fix_bits(Abits, ctx->minfo); for (j = 0; j < nvars; j++) fmpz_clear(exps + j); if (A == B) { slong NA = mpoly_words_per_exp(Abits, ctx->minfo); slong exps_alloc = NA*B->length; ulong * texps = flint_malloc(exps_alloc*sizeof(ulong)); mpoly_monomials_inflate(texps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = Abits; A->exps_alloc = exps_alloc; } else { fq_nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*B->length); mpoly_monomials_inflate(A->exps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _fq_nmod_mpoly_set_length(A, B->length, ctx); } TMP_END; if (have_zero_stride || ctx->minfo->ord != ORD_LEX) { fq_nmod_mpoly_sort_terms(A, ctx); if (have_zero_stride) fq_nmod_mpoly_combine_like_terms(A, ctx); } return; } flint-3.1.3/src/fq_nmod_mpoly/init.c000066400000000000000000000024131461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_init3( fq_nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(bits, ctx->minfo); if (alloc > 0) { A->coeffs_alloc = d*alloc; A->coeffs = FLINT_ARRAY_ALLOC(A->coeffs_alloc, mp_limb_t); A->exps_alloc = N*alloc; A->exps = FLINT_ARRAY_ALLOC(A->exps_alloc, ulong); } else { A->coeffs = NULL; A->exps = NULL; A->coeffs_alloc = 0; A->exps_alloc = 0; } A->length = 0; A->bits = bits; } void fq_nmod_mpoly_init2( fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = mpoly_fix_bits(MPOLY_MIN_BITS, ctx->minfo); fq_nmod_mpoly_init3(A, alloc, bits, ctx); } flint-3.1.3/src/fq_nmod_mpoly/inlines.c000066400000000000000000000006701461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_MPOLY_INLINES_C #include "fq_nmod_mpoly.h" flint-3.1.3/src/fq_nmod_mpoly/interp.c000066400000000000000000003234011461254215100177350ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" /* interp_reduce: map from Fp[x] to Fp[x]/poly(x) interp_lift: map from Fp[x]/poly(x) to Fp[x] interp_crt: update element of Fp[x] with a new image in Fp[x]/poly(x) interp_mcrt: same as interp_mcrt, but monomial match, thus easier ..._sm: poly(x) is x - alpha ..._lg: poly(x) is modulus of finite field */ static void _n_poly_mul_n_fq( n_poly_t a, const n_poly_t b, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); n_poly_t C; C->coeffs = (mp_limb_t *) c; C->length = d; C->alloc = d; _n_poly_normalise(C); n_poly_mod_mul(a, b, C, ctx->mod); } /****************** bivar - image in F_q *************************************/ /* E = A mod alpha(v) A is in Fp[X][][v] E is in (Fp/alpha(v))[X] */ void nmod_mpolyn_interp_reduce_lg_poly( fq_nmod_poly_t E, const fq_nmod_ctx_t fqctx, const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { fq_nmod_t v; slong Ai, Alen, k; n_poly_struct * Acoeff; ulong * Aexp; slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fq_nmod_init(v, fqctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = A->length; fq_nmod_poly_zero(E, fqctx); for (Ai = 0; Ai < Alen; Ai++) { k = (Aexp + N*Ai)[off] >> shift; n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(v), Acoeff + Ai, evil_const_cast_nmod_poly_to_n_poly(fqctx->modulus), ctx->mod); fq_nmod_poly_set_coeff(E, k, v, fqctx); } fq_nmod_clear(v, fqctx); } /* Convert B to A using the lowest degree representative A is in Fp [X][][v] B is in (Fp/alpha(v))[X] */ void nmod_mpolyn_interp_lift_lg_poly( slong * lastdeg_, nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx, const fq_nmod_poly_t B, const fq_nmod_ctx_t fqctx) { slong Bexp; slong Blen = fq_nmod_poly_length(B, fqctx); fq_nmod_struct * Bcoeff = B->coeffs; n_poly_struct * Acoeff; ulong * Aexp; slong Ai; slong lastdeg = -WORD(1); slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; Ai = 0; for (Bexp = Blen - 1; Bexp >= 0; Bexp--) { if (!fq_nmod_is_zero(Bcoeff + Bexp, fqctx)) { FLINT_ASSERT(Ai < A->alloc); n_poly_set_nmod_poly(Acoeff + Ai, Bcoeff + Bexp); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Acoeff + Ai)); mpoly_monomial_zero(Aexp + N*Ai, N); (Aexp + N*Ai)[off] = Bexp << shift; Ai++; } } A->length = Ai; *lastdeg_ = lastdeg; } /* F = F + modulus*((A - F(alpha))/(modulus(alpha))) no assumptions about matching monomials F is in Fp[X][v] A is in (Fp/alpha(v))[X] alpha(v) is fqctx->modulus(v) */ int nmod_mpolyn_interp_crt_lg_poly( slong * lastdeg_, nmod_mpolyn_t F, nmod_mpolyn_t T, n_poly_t modulus, const nmod_mpoly_ctx_t ctx, fq_nmod_poly_t A, const fq_nmod_ctx_t fqctx) { int changed = 0; slong lastdeg = -WORD(1); fq_nmod_t u, v; n_poly_t w; slong Fi, Ti, Aexp; fq_nmod_struct * Acoeff = A->coeffs; slong Flen = F->length; n_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; n_poly_struct * Tcoeffs; ulong * Texps; fq_nmod_t inv_m_eval; slong N, off, shift; FLINT_ASSERT(T->bits == F->bits); N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, F->bits, ctx->minfo); fq_nmod_init(inv_m_eval, fqctx); n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(inv_m_eval), modulus, evil_const_cast_nmod_poly_to_n_poly(fqctx->modulus), ctx->mod); fq_nmod_inv(inv_m_eval, inv_m_eval, fqctx); Fi = 0; fq_nmod_init(u, fqctx); fq_nmod_init(v, fqctx); n_poly_init(w); Aexp = fq_nmod_poly_degree(A, fqctx); nmod_mpolyn_fit_length(T, Flen + Aexp + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; Ti = 0; while (Fi < Flen || Aexp >= 0) { FLINT_ASSERT(Ti < T->alloc); if (Fi < Flen) { FLINT_ASSERT(!n_poly_is_zero(Fcoeffs + Fi)); FLINT_ASSERT(n_poly_degree(Fcoeffs + Fi) < n_poly_degree(modulus)); } if (Aexp >= 0) { FLINT_ASSERT(!fq_nmod_is_zero(Acoeff + Aexp, fqctx)); } mpoly_monomial_zero(Texps + N*Ti, N); if (Fi < Flen && Aexp >= 0 && ((Fexps + N*Fi)[off]>>shift) == Aexp) { /* F term ok, A term ok */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(u), Fcoeffs + Fi, evil_const_cast_nmod_poly_to_n_poly(fqctx->modulus), ctx->mod); fq_nmod_sub(v, Acoeff + Aexp, u, fqctx); if (!fq_nmod_is_zero(v, fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, fqctx); n_poly_mod_mul(w, modulus, evil_cast_nmod_poly_to_n_poly(u), ctx->mod); n_poly_mod_add(Tcoeffs + Ti, Fcoeffs + Fi, w, ctx->mod); } else { n_poly_set(Tcoeffs + Ti, Fcoeffs + Fi); } (Texps + N*Ti)[off] = (Fexps + N*Fi)[off]; Fi++; do { Aexp--; } while (Aexp >= 0 && fq_nmod_is_zero(Acoeff + Aexp, fqctx)); } else if (Fi < Flen && (Aexp < 0 || ((Fexps + N*Fi)[off]>>shift) > Aexp)) { /* F term ok, A term missing */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(v), Fcoeffs + Fi, evil_const_cast_nmod_poly_to_n_poly(fqctx->modulus), ctx->mod); if (!fq_nmod_is_zero(v, fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, fqctx); n_poly_mod_mul(w, evil_const_cast_nmod_poly_to_n_poly(u), modulus, ctx->mod); n_poly_mod_sub(Tcoeffs + Ti, Fcoeffs + Fi, w, ctx->mod); } else { n_poly_set(Tcoeffs + Ti, Fcoeffs + Fi); } (Texps + N*Ti)[off] = (Fexps + N*Fi)[off]; Fi++; } else if (Aexp >= 0 && (Fi >= Flen || ((Fexps + N*Fi)[off]>>shift) < Aexp)) { /* F term missing, A term ok */ changed = 1; fq_nmod_mul(u, Acoeff + Aexp, inv_m_eval, fqctx); n_poly_mod_mul(Tcoeffs + Ti, modulus, evil_const_cast_nmod_poly_to_n_poly(u), ctx->mod); (Texps + N*Ti)[off] = Aexp << shift; do { Aexp--; } while (Aexp >= 0 && fq_nmod_is_zero(Acoeff + Aexp, fqctx)); } else { FLINT_ASSERT(0); } FLINT_ASSERT(!n_poly_is_zero(Tcoeffs + Ti)); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Tcoeffs + Ti)); Ti++; } T->length = Ti; if (changed) { nmod_mpolyn_swap(T, F); } fq_nmod_clear(u, fqctx); fq_nmod_clear(v, fqctx); n_poly_clear(w); fq_nmod_clear(inv_m_eval, fqctx); *lastdeg_ = lastdeg; return changed; } void nmod_mpolyn_interp_lift_lg_bpoly( slong * lastdeg_, nmod_mpolyn_t F, const nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx) { slong lgd = fq_nmod_ctx_degree(lgctx->fqctx); slong N = mpoly_words_per_exp_sp(F->bits, smctx->minfo); slong i, j, Fi; slong lastdeg = -WORD(1); slong off0, shift0, off1, shift1; mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, smctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, smctx->minfo); Fi = 0; for (i = A->length - 1; i >= 0; i--) { n_fq_poly_struct * Ai = A->coeffs + i; for (j = Ai->length - 1; j >= 0; j--) { if (_n_fq_is_zero(Ai->coeffs + lgd*j, lgd)) continue; nmod_mpolyn_fit_length(F, Fi + 1, smctx); mpoly_monomial_zero(F->exps + N*Fi, N); (F->exps + N*Fi)[off0] += (i << shift0); (F->exps + N*Fi)[off1] += (j << shift1); n_fq_get_n_poly(F->coeffs + Fi, Ai->coeffs + lgd*j, lgctx->fqctx); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(F->coeffs + Fi)); Fi++; } } F->length = Fi; *lastdeg_ = lastdeg; } int nmod_mpolyn_interp_crt_lg_bpoly( slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, n_fq_poly_t modulus, const nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx) { slong lgd = fq_nmod_ctx_degree(lgctx->fqctx); int changed = 0; slong N = mpoly_words_per_exp(T->bits, smctx->minfo); slong off0, shift0, off1, shift1; n_fq_poly_struct * Acoeffs = A->coeffs; slong Fi, Ti, Ai, ai; slong Flen = F->length; ulong * Fexps = F->exps; n_poly_struct * Fcoeffs = F->coeffs; ulong * Texps = T->exps; n_poly_struct * Tcoeffs = T->coeffs; mp_limb_t * u = FLINT_ARRAY_ALLOC(3*lgd, mp_limb_t); mp_limb_t * v = u + lgd; mp_limb_t * inv_m_eval = v + lgd; ulong Fexpi, mask; mask = (-UWORD(1)) >> (FLINT_BITS - F->bits); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, smctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, smctx->minfo); _n_fq_set_n_poly(u, modulus->coeffs, modulus->length, lgctx->fqctx); n_fq_inv(inv_m_eval, u, lgctx->fqctx); FLINT_ASSERT(nmod_mpolyn_is_canonical(F, smctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(A, lgctx->fqctx)); FLINT_ASSERT(T->bits == F->bits); *lastdeg = -1; Ti = Fi = 0; Ai = A->length - 1; ai = (Ai < 0) ? 0 : n_fq_poly_degree(Acoeffs + Ai); while (Fi < Flen || Ai >= 0) { if (Ti >= T->alloc) { slong extra = FLINT_MAX(Flen - Fi, Ai); nmod_mpolyn_fit_length(T, Ti + extra + 1, smctx); Tcoeffs = T->coeffs; Texps = T->exps; } if (Fi < Flen) { Fexpi = pack_exp2(((Fexps + N*Fi)[off0]>>shift0)&mask, ((Fexps + N*Fi)[off1]>>shift1)&mask); } else { Fexpi = 0; } if (Fi < Flen && Ai >= 0 && Fexpi == pack_exp2(Ai, ai)) { /* F term ok, A term ok */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); _n_fq_set_n_poly(u, Fcoeffs[Fi].coeffs, Fcoeffs[Fi].length, lgctx->fqctx); n_fq_sub(v, Acoeffs[Ai].coeffs + lgd*ai, u, lgctx->fqctx); if (!_n_fq_is_zero(v, lgd)) { changed = 1; n_fq_mul(u, v, inv_m_eval, lgctx->fqctx); _n_poly_mul_n_fq(Tcoeffs + Ti, modulus, u, lgctx->fqctx); n_poly_mod_add(Tcoeffs + Ti, Tcoeffs + Ti, Fcoeffs + Fi, smctx->mod); } else { n_poly_set(Tcoeffs + Ti, Fcoeffs + Fi); } Fi++; do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + lgd*ai, lgd)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_fq_poly_degree(Acoeffs + Ai); } } else if (Fi < Flen && (Ai < 0 || Fexpi > pack_exp2(Ai, ai))) { /* F term ok, Aterm missing */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); _n_fq_set_n_poly(v, Fcoeffs[Fi].coeffs, Fcoeffs[Fi].length, lgctx->fqctx); if (!_n_fq_is_zero(v, lgd)) { changed = 1; n_fq_mul(u, v, inv_m_eval, lgctx->fqctx); _n_poly_mul_n_fq(Tcoeffs + Ti, modulus, u, lgctx->fqctx); n_poly_mod_sub(Tcoeffs + Ti, Fcoeffs + Fi, Tcoeffs + Ti, smctx->mod); } else { n_poly_set(Tcoeffs + Ti, Fcoeffs + Fi); } Fi++; } else { FLINT_ASSERT(Ai >= 0 && (Fi >= Flen || Fexpi < pack_exp2(Ai, ai))); /* F term missing, A term ok */ mpoly_monomial_zero(Texps + N*Ti, N); (Texps + N*Ti)[off0] += (Ai << shift0); (Texps + N*Ti)[off1] += (ai << shift1); changed = 1; n_fq_mul(u, Acoeffs[Ai].coeffs + lgd*ai, inv_m_eval, lgctx->fqctx); _n_poly_mul_n_fq(Tcoeffs + Ti, modulus, u, lgctx->fqctx); do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + lgd*ai, lgd)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_fq_poly_degree(Acoeffs + Ai); } } FLINT_ASSERT(!n_poly_is_zero(Tcoeffs + Ti)); *lastdeg = FLINT_MAX(*lastdeg, n_poly_degree(Tcoeffs + Ti)); Ti++; } T->length = Ti; if (changed) nmod_mpolyn_swap(T, F); FLINT_ASSERT(nmod_mpolyn_is_canonical(F, smctx)); flint_free(u); return changed; } /*********************** multivar - image in F_q *****************************/ /* E = A mod alpha(x_var) A is in Fp[x_0, ..., x_(var-2), x_(var-1)][x_var] E is in (Fp/alpha(x_var))[x_0, ..., x_(var-2)][x_(var-1)] alpha is ectx->modulus */ void nmod_mpolyn_interp_reduce_lg_mpolyn( fq_nmod_mpolyn_t E, fq_nmod_mpoly_ctx_t ectx, nmod_mpolyn_t A, slong var, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift, k; ulong mask; fq_nmod_t v; n_poly_struct * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong Alen = A->length; slong Ai; n_poly_struct * Ecoeff; ulong * Eexp; slong Ei; fq_nmod_init(v, ectx->fqctx); FLINT_ASSERT(var > 0); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); Ecoeff = E->coeffs; Eexp = E->exps; Ei = 0; for (Ai = 0; Ai < Alen; Ai++) { n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(v), Acoeff + Ai, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); k = ((Aexp + N*Ai)[offset] >> shift) & mask; if (fq_nmod_is_zero(v, ectx->fqctx)) { continue; } if (Ei > 0 && mpoly_monomial_equal_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ n_fq_poly_set_coeff_fq_nmod(Ecoeff + Ei - 1, k, v, ectx->fqctx); } else { FLINT_ASSERT(Ei == 0 || mpoly_monomial_gt_nomask_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Ei >= E->alloc) { fq_nmod_mpolyn_fit_length(E, Ei + 1, ectx); Ecoeff = E->coeffs; Eexp = E->exps; } mpoly_monomial_set_extra(Eexp + N*Ei, Aexp + N*Ai, N, offset, -(k << shift)); n_poly_zero(Ecoeff + Ei); n_fq_poly_set_coeff_fq_nmod(Ecoeff + Ei, k, v, ectx->fqctx); Ei++; } } E->length = Ei; fq_nmod_clear(v, ectx->fqctx); } /* A = B using lowest degree representative A is in Fp [x_0, ..., x_(var-1), x_(var-1)][x_var] B is in (Fp[x_var]/alpha(x_var))[x_0, ..., x_(var-2)][x_(var-1)] */ void nmod_mpolyn_interp_lift_lg_mpolyn( slong * lastdeg_, nmod_mpolyn_t A, slong var, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ectx) { slong d = fq_nmod_ctx_degree(ectx->fqctx); slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong offset, shift; slong vi; n_fq_poly_struct * Bcoeff = B->coeffs; ulong * Bexp = B->exps; slong Blen = B->length; slong Bi; n_poly_struct * Acoeff; ulong * Aexp; slong Ai; slong lastdeg = -WORD(1); FLINT_ASSERT(A->bits == B->bits); nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Ai = 0; for (Bi = 0; Bi < Blen; Bi++) { if (Ai + (Bcoeff + Bi)->length >= A->alloc) { nmod_mpolyn_fit_length(A, Ai + (Bcoeff + Bi)->length, ctx); Acoeff = A->coeffs; Aexp = A->exps; } for (vi = (Bcoeff + Bi)->length - 1; vi >= 0; vi--) { if (!_n_fq_is_zero((Bcoeff + Bi)->coeffs + d*vi, d)) { mpoly_monomial_set_extra(Aexp + N*Ai, Bexp + N*Bi, N, offset, vi << shift); n_fq_get_n_poly(Acoeff + Ai, (Bcoeff + Bi)->coeffs + d*vi, ectx->fqctx); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Acoeff + Ai)); Ai++; } } } A->length = Ai; *lastdeg_ = lastdeg; } int nmod_mpolyn_interp_crt_lg_mpolyn( slong * lastdeg_, nmod_mpolyn_t F, nmod_mpolyn_t T, n_poly_t modulus, slong var, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ectx) { slong d = fq_nmod_ctx_degree(ectx->fqctx); int changed = 0; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift; slong lastdeg = -WORD(1); slong vi; fq_nmod_t u, v; n_poly_t w; n_poly_struct * Tcoeff; ulong * Texp; slong Ti; n_fq_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai; n_poly_struct * Fcoeff = F->coeffs; slong Flen = F->length; ulong * Fexp = F->exps; slong Fi; fq_nmod_t inv_m_eval; fq_nmod_t at; fq_nmod_init(inv_m_eval, ectx->fqctx); n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(inv_m_eval), modulus, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); fq_nmod_inv(inv_m_eval, inv_m_eval, ectx->fqctx); fq_nmod_init(at, ectx->fqctx); fq_nmod_init(u, ectx->fqctx); fq_nmod_init(v, ectx->fqctx); n_poly_init(w); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); FLINT_ASSERT(F->bits == A->bits); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Flen = F->length; nmod_mpolyn_fit_length(T, FLINT_MAX(Flen, Alen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = 0; Fi = Ai = vi = 0; if (Ai < Alen) { vi = n_poly_degree(A->coeffs + Ai); } while (Fi < Flen || Ai < Alen) { if (Ti >= T->alloc) { nmod_mpolyn_fit_length(T, Ti + FLINT_MAX(Flen - Fi, Alen - Ai), ctx); Tcoeff = T->coeffs; Texp = T->exps; } if (Fi < Flen && Ai < Alen && mpoly_monomial_equal_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift)) { /* F term ok, A term ok */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(u), Fcoeff + Fi, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); n_fq_get_fq_nmod(at, Acoeff[Ai].coeffs + d*vi, ectx->fqctx); fq_nmod_sub(v, at, u, ectx->fqctx); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); n_poly_mod_mul(w, modulus, evil_const_cast_nmod_poly_to_n_poly(u), ctx->mod); n_poly_mod_add(Tcoeff + Ti, Fcoeff + Fi, w, ctx->mod); } else { n_poly_set(Tcoeff + Ti, Fcoeff + Fi); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; do { vi--; } while (vi >= 0 && _n_fq_is_zero(Acoeff[Ai].coeffs + d*vi, d)); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_poly_degree(A->coeffs + Ai); } } } else if (Fi < Flen && (Ai >= Alen || mpoly_monomial_gt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))) { /* F term ok, A term missing */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(v), Fcoeff + Fi, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); n_poly_mod_mul(w, evil_const_cast_nmod_poly_to_n_poly(u), modulus, ctx->mod); n_poly_mod_sub(Tcoeff + Ti, Fcoeff + Fi, w, ctx->mod); } else { n_poly_set(Tcoeff + Ti, Fcoeff + Fi); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; } else { FLINT_ASSERT(Ai < Alen && (Fi >= Flen || mpoly_monomial_lt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))); /* F term missing, A term ok */ changed = 1; n_fq_get_fq_nmod(at, Acoeff[Ai].coeffs + d*vi, ectx->fqctx); fq_nmod_mul(u, at, inv_m_eval, ectx->fqctx); n_poly_mod_mul(Tcoeff + Ti, evil_const_cast_nmod_poly_to_n_poly(u), modulus, ctx->mod); mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, vi << shift); do { vi--; } while (vi >= 0 && _n_fq_is_zero(Acoeff[Ai].coeffs + d*vi, d)); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_poly_degree(A->coeffs + Ai); } } } FLINT_ASSERT(!n_poly_is_zero(Tcoeff + Ti)); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Tcoeff + Ti)); Ti++; } T->length = Ti; if (changed) { nmod_mpolyn_swap(T, F); } fq_nmod_clear(inv_m_eval, ectx->fqctx); fq_nmod_clear(u, ectx->fqctx); fq_nmod_clear(v, ectx->fqctx); fq_nmod_clear(at, ectx->fqctx); n_poly_clear(w); FLINT_ASSERT(nmod_mpolyn_is_canonical(F, ctx)); *lastdeg_ = lastdeg; return changed; } /******************** multivar - image in Fq *********************************/ /* A = B mod alpha(x_var) B is in Fp [x_0, ..., x_(var-2), x_(var-1)][x_var] A is in (Fp/alpha(x_var))[x_0, ..., x_(var-2), x_(var-1)] alpha is ectx->modulus */ void nmod_mpolyn_interp_reduce_lg_mpoly( fq_nmod_mpoly_t A, nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ffctx, const nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ffctx->fqctx); slong N = N = mpoly_words_per_exp(B->bits, ctx->minfo); slong i, Alen; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(ffctx->minfo->ord == ORD_LEX); FLINT_ASSERT(ffctx->minfo->nvars == ctx->minfo->nvars); Alen = 0; fq_nmod_mpoly_fit_length(A, B->length, ffctx); for (i = 0; i < B->length; i++) { mpoly_monomial_set(A->exps + N*Alen, B->exps + N*i, N); if (B->coeffs[i].length > d) { _nmod_poly_rem(A->coeffs + d*Alen, B->coeffs[i].coeffs, B->coeffs[i].length, ffctx->fqctx->modulus->coeffs, d + 1, fq_nmod_ctx_mod(ffctx->fqctx)); } else { _n_fq_set_n_poly(A->coeffs + d*Alen, B->coeffs[i].coeffs, B->coeffs[i].length, ffctx->fqctx); } Alen += !_n_fq_is_zero(A->coeffs + d*Alen, d); } A->length = Alen; } /* A = B mod alpha(x_var) B is in Fp [X][x_0, ..., x_(var-2), x_(var-1)][x_var] A is in (Fp/alpha(x_var))[X][x_0, ..., x_(var-2), x_(var-1)] alpha is ectx->modulus */ void nmod_mpolyun_interp_reduce_lg_mpolyu( fq_nmod_mpolyu_t A, nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ffctx, const nmod_mpoly_ctx_t ctx) { slong i, k, Blen; fq_nmod_mpoly_struct * Acoeff; nmod_mpolyn_struct * Bcoeff; ulong * Aexp, * Bexp; Blen = B->length; fq_nmod_mpolyu_fit_length(A, Blen, ffctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; k = 0; for (i = 0; i < Blen; i++) { nmod_mpolyn_interp_reduce_lg_mpoly(Acoeff + k, Bcoeff + i, ffctx, ctx); Aexp[k] = Bexp[i]; k += !fq_nmod_mpoly_is_zero(Acoeff + k, ffctx); } A->length = k; } /* A = Ap using lowest degree A is in Fp [x_0, ..., x_(var-2), x_(var-1)][x_var] Ap is in (Fp/alpha(x_var))[x_0, ..., x_(var-2), x_(var-1)] alpha is ectx->modulus */ void nmod_mpolyn_interp_lift_lg_mpoly( nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx, fq_nmod_mpoly_t Ap, const fq_nmod_mpoly_ctx_t ctxp) { slong d = fq_nmod_ctx_degree(ctxp->fqctx); slong i, N; FLINT_ASSERT(Ap->bits == A->bits); nmod_mpolyn_fit_length(A, Ap->length, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); for (i = 0; i < Ap->length; i++) { mpoly_monomial_set(A->exps + N*i, Ap->exps + N*i, N); n_fq_get_n_poly(A->coeffs + i, Ap->coeffs + d*i, ctxp->fqctx); } A->length = Ap->length; } /* A = Ap using lowest degree A is in Fp [X][x_0, ..., x_(var-2), x_(var-1)][x_var] Ap is in (Fp/alpha(x_var))[X][x_0, ..., x_(var-2), x_(var-1)] alpha is ectx->modulus */ void nmod_mpolyun_interp_lift_lg_mpolyu( nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t Ap, const fq_nmod_mpoly_ctx_t ctxp) { slong i; FLINT_ASSERT(Ap->bits == A->bits); nmod_mpolyun_fit_length(A, Ap->length, ctx); for (i = 0; i < Ap->length; i++) { A->exps[i] = Ap->exps[i]; nmod_mpolyn_interp_lift_lg_mpoly(A->coeffs + i, ctx, Ap->coeffs + i, ctxp); } A->length = Ap->length; } /* F = F + modulus*((A - F(alpha))/(modulus(alpha))) no assumptions about matching monomials */ static int nmod_mpolyn_interp_crt_lg_mpoly( slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, n_poly_t m, const nmod_mpoly_ctx_t ctx, fq_nmod_mpoly_t A, fq_nmod_t inv_m_eval, const fq_nmod_mpoly_ctx_t ffctx) { slong d = fq_nmod_ctx_degree(ffctx->fqctx); int changed = 0; slong i, j, k; slong N; fq_nmod_t u, v; n_poly_t w; flint_bitcnt_t bits = A->bits; slong Flen = F->length, Alen = A->length; ulong * Fexp = F->exps, * Aexp = A->exps; ulong * Texp; mp_limb_t * Acoeff = A->coeffs; n_poly_struct * Fcoeff = F->coeffs; n_poly_struct * Tcoeff; fq_nmod_t at; FLINT_ASSERT(F->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); fq_nmod_init(u, ffctx->fqctx); fq_nmod_init(v, ffctx->fqctx); n_poly_init(w); fq_nmod_init(at, ffctx->fqctx); nmod_mpolyn_fit_length(T, Flen + Alen, ctx); Texp = T->exps; Tcoeff = T->coeffs; N = mpoly_words_per_exp(bits, ctx->minfo); i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || mpoly_monomial_gt_nomask(Fexp + N*i, Aexp + N*j, N))) { FLINT_ASSERT(!n_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_poly_degree(Fcoeff + i) < n_poly_degree(m)); /* F term ok, A term missing */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(v), Fcoeff + i, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); if (!fq_nmod_is_zero(v, ffctx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ffctx->fqctx); n_poly_mod_mul(w, evil_const_cast_nmod_poly_to_n_poly(u), m, ctx->mod); n_poly_mod_sub(Tcoeff + k, Fcoeff + i, w, ctx->mod); } else { n_poly_set(Tcoeff + k, Fcoeff + i); } FLINT_ASSERT(!n_poly_is_zero(Tcoeff + k)); *lastdeg = FLINT_MAX(*lastdeg, n_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Fexp + N*i, N); k++; i++; } else if (j < Alen && (i >= Flen || mpoly_monomial_lt_nomask(Fexp + N*i, Aexp + N*j, N))) { /* F term missing, A term ok */ if (!_n_fq_is_zero(Acoeff + d*j, d)) { changed = 1; n_fq_get_fq_nmod(at, Acoeff + d*j, ffctx->fqctx); fq_nmod_mul(u, at, inv_m_eval, ffctx->fqctx); n_poly_mod_mul(Tcoeff + k, m, evil_const_cast_nmod_poly_to_n_poly(u), ctx->mod); *lastdeg = FLINT_MAX(*lastdeg, n_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; } j++; } else if (i < Flen && j < Alen && mpoly_monomial_equal(Fexp + N*i, Aexp + N*j, N)) { FLINT_ASSERT(!n_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_poly_degree(Fcoeff + i) < n_poly_degree(m)); /* F term ok, A term ok */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(u), Fcoeff + i, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); n_fq_get_fq_nmod(at, Acoeff + d*j, ffctx->fqctx); fq_nmod_sub(v, at, u, ffctx->fqctx); if (!fq_nmod_is_zero(v, ffctx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ffctx->fqctx); n_poly_mod_mul(w, m, evil_const_cast_nmod_poly_to_n_poly(u), ctx->mod); n_poly_mod_add(Tcoeff + k, Fcoeff + i, w, ctx->mod); } else { n_poly_set(Tcoeff + k, Fcoeff + i); } FLINT_ASSERT(!n_poly_is_zero(Tcoeff + k)); *lastdeg = FLINT_MAX(*lastdeg, n_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; i++; j++; } else { FLINT_ASSERT(0); } } nmod_mpolyn_set_length(T, k, ctx); if (changed) { nmod_mpolyn_swap(T, F); } fq_nmod_clear(u, ffctx->fqctx); fq_nmod_clear(v, ffctx->fqctx); n_poly_clear(w); fq_nmod_clear(at, ffctx->fqctx); return changed; } /* F = F + modulus*((A - F(alpha))/(modulus(alpha))) no assumptions about matching monomials */ int nmod_mpolyun_interp_crt_lg_mpolyu( slong * lastdeg, nmod_mpolyun_t F, nmod_mpolyun_t T, n_poly_t m, const nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ffctx) { int changed = 0; slong i, j, k; ulong * Texp; ulong * Fexp; ulong * Aexp; slong Flen; slong Alen; nmod_mpolyn_t S; nmod_mpolyn_struct * Tcoeff; nmod_mpolyn_struct * Fcoeff; fq_nmod_mpoly_struct * Acoeff; fq_nmod_mpoly_t zero; fq_nmod_t inv_m_eval; *lastdeg = -WORD(1); FLINT_ASSERT(F->bits == T->bits); FLINT_ASSERT(T->bits == A->bits); nmod_mpolyn_init(S, F->bits, ctx); Flen = F->length; Alen = A->length; nmod_mpolyun_fit_length(T, Flen + Alen, ctx); Tcoeff = T->coeffs; Fcoeff = F->coeffs; Acoeff = A->coeffs; Texp = T->exps; Fexp = F->exps; Aexp = A->exps; fq_nmod_mpoly_init(zero, ffctx); fq_nmod_mpoly_fit_length_reset_bits(zero, 0, A->bits, ffctx); fq_nmod_init(inv_m_eval, ffctx->fqctx); n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(inv_m_eval), m, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); fq_nmod_inv(inv_m_eval, inv_m_eval, ffctx->fqctx); i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || Fexp[i] > Aexp[j])) { /* F term ok, A term missing */ nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= nmod_mpolyn_interp_crt_lg_mpoly(lastdeg, Tcoeff + k, S, m, ctx, zero, inv_m_eval, ffctx); Texp[k] = Fexp[i]; k++; i++; } else if (j < Alen && (i >= Flen || Aexp[j] > Fexp[i])) { /* F term missing, A term ok */ nmod_mpolyn_zero(Tcoeff + k, ctx); changed |= nmod_mpolyn_interp_crt_lg_mpoly(lastdeg, Tcoeff + k, S, m, ctx, Acoeff + j, inv_m_eval, ffctx); Texp[k] = Aexp[j]; k++; j++; } else if (i < Flen && j < Alen && (Fexp[i] == Aexp[j])) { /* F term ok, A term ok */ nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= nmod_mpolyn_interp_crt_lg_mpoly(lastdeg, Tcoeff + k, S, m, ctx, Acoeff + j, inv_m_eval, ffctx); Texp[k] = Aexp[j]; FLINT_ASSERT(!nmod_mpolyn_is_zero(Tcoeff + k, ctx)); k++; i++; j++; } else { FLINT_ASSERT(0); } } T->length = k; if (changed) { nmod_mpolyun_swap(T, F); } fq_nmod_clear(inv_m_eval, ffctx->fqctx); nmod_mpolyn_clear(S, ctx); fq_nmod_mpoly_clear(zero, ffctx); return changed; } int nmod_mpolyn_interp_mcrt_lg_mpoly( slong * lastdeg_, nmod_mpolyn_t H, const nmod_mpoly_ctx_t smctx, const n_poly_t m, const mp_limb_t * inv_m_eval, fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t lgctx) { slong lastdeg = *lastdeg_; slong i, lgd = fq_nmod_ctx_degree(lgctx->fqctx); #if FLINT_WANT_ASSERT slong N = mpoly_words_per_exp(A->bits, smctx->minfo); #endif int changed = 0; mp_limb_t * u = FLINT_ARRAY_ALLOC(lgd, mp_limb_t); n_poly_t w; n_poly_init(w); FLINT_ASSERT(H->length == A->length); FLINT_ASSERT(H->bits == A->bits); for (i = 0; i < A->length; i++) { FLINT_ASSERT(mpoly_monomial_equal(H->exps + N*i, A->exps + N*i, N)); _n_fq_set_n_poly(u, H->coeffs[i].coeffs, H->coeffs[i].length, lgctx->fqctx); n_fq_sub(u, A->coeffs + lgd*i, u, lgctx->fqctx); if (!_n_fq_is_zero(u, lgd)) { changed = 1; n_fq_mul(u, u, inv_m_eval, lgctx->fqctx); _n_poly_mul_n_fq(w, m, u, lgctx->fqctx); n_poly_mod_add(H->coeffs + i, H->coeffs + i, w, smctx->mod); } lastdeg = FLINT_MAX(lastdeg, n_poly_degree(H->coeffs + i)); FLINT_ASSERT(n_poly_degree(H->coeffs + i) < n_poly_degree(m) + nmod_poly_degree(lgctx->fqctx->modulus)); } *lastdeg_ = lastdeg; flint_free(u); n_poly_clear(w); return changed; } /* Update H so that it does not change mod m, and is now A mod p It is asserted that the monomials in H and A match */ int nmod_mpolyn_CRT_fq_nmod_mpoly( slong * lastdeg, nmod_mpolyn_t H, const nmod_mpoly_ctx_t ctx, n_poly_t m, fq_nmod_t inv_m_eval, fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctxp) { slong d = fq_nmod_ctx_degree(ctxp->fqctx); slong i; #if FLINT_WANT_ASSERT slong N; #endif int changed = 0; fq_nmod_t u, v, at; n_poly_t w; fq_nmod_init(u, ctxp->fqctx); fq_nmod_init(v, ctxp->fqctx); fq_nmod_init(at, ctxp->fqctx); n_poly_init(w); FLINT_ASSERT(H->length == A->length); FLINT_ASSERT(H->bits == A->bits); #if FLINT_WANT_ASSERT N = mpoly_words_per_exp(A->bits, ctx->minfo); #endif for (i = 0; i < A->length; i++) { FLINT_ASSERT(mpoly_monomial_equal(H->exps + N*i, A->exps + N*i, N)); n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(u), H->coeffs + i, evil_const_cast_nmod_poly_to_n_poly(ctxp->fqctx->modulus), ctx->mod); n_fq_get_fq_nmod(at, A->coeffs + d*i, ctxp->fqctx); fq_nmod_sub(v, at, u, ctxp->fqctx); if (!fq_nmod_is_zero(v, ctxp->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ctxp->fqctx); n_poly_mod_mul(w, evil_const_cast_nmod_poly_to_n_poly(u), m, ctx->mod); n_poly_mod_add(H->coeffs + i, H->coeffs + i, w, ctx->mod); } *lastdeg = FLINT_MAX(*lastdeg, n_poly_degree(H->coeffs + i)); FLINT_ASSERT(n_poly_degree(H->coeffs + i) < n_poly_degree(m) + nmod_poly_degree(ctxp->fqctx->modulus)); } fq_nmod_clear(u, ctxp->fqctx); fq_nmod_clear(v, ctxp->fqctx); fq_nmod_clear(at, ctxp->fqctx); n_poly_clear(w); return changed; } int nmod_mpolyun_interp_mcrt_lg_mpolyu( slong * lastdeg, nmod_mpolyun_t H, const nmod_mpoly_ctx_t ctx, n_poly_t m, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctxp) { slong i; int changed = 0; fq_nmod_t inv_m_eval; *lastdeg = -WORD(1); fq_nmod_init(inv_m_eval, ctxp->fqctx); n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(inv_m_eval), m, evil_const_cast_nmod_poly_to_n_poly(ctxp->fqctx->modulus), ctx->mod); fq_nmod_inv(inv_m_eval, inv_m_eval, ctxp->fqctx); FLINT_ASSERT(H->bits == A->bits); FLINT_ASSERT(H->length == A->length); for (i = 0; i < A->length; i++) { FLINT_ASSERT(H->exps[i] == A->exps[i]); changed |= nmod_mpolyn_CRT_fq_nmod_mpoly(lastdeg, H->coeffs + i, ctx, m, inv_m_eval, A->coeffs + i, ctxp); } H->length = A->length; fq_nmod_clear(inv_m_eval, ctxp->fqctx); return changed; } /*****************************************************************************/ /* E = A(v = alpha) A is in Fq[X][v] E is in Fq[X] */ void fq_nmod_mpolyn_interp_reduce_sm_poly( fq_nmod_poly_t E, const fq_nmod_mpolyn_t A, const fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_t v; slong Ai, Alen, k; n_poly_struct * Acoeff; ulong * Aexp; slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fq_nmod_init(v, ctx->fqctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = A->length; Ai = 0; fq_nmod_poly_zero(E, ctx->fqctx); for (Ai = 0; Ai < Alen; Ai++) { n_fq_poly_evaluate_fq_nmod(v, Acoeff + Ai, alpha, ctx->fqctx); k = (Aexp + N*Ai)[off] >> shift; fq_nmod_poly_set_coeff(E, k, v, ctx->fqctx); } fq_nmod_clear(v, ctx->fqctx); } /* A = B A is in Fq[X][v] (no v appears) B is in Fq[X] */ void fq_nmod_mpolyn_interp_lift_sm_poly( fq_nmod_mpolyn_t A, const fq_nmod_poly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong Bi; slong Blen = fq_nmod_poly_length(B, ctx->fqctx); fq_nmod_struct * Bcoeff = B->coeffs; n_poly_struct * Acoeff; ulong * Aexp; slong Ai; slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; Ai = 0; for (Bi = Blen - 1; Bi >= 0; Bi--) { if (!fq_nmod_is_zero(Bcoeff + Bi, ctx->fqctx)) { FLINT_ASSERT(Ai < A->alloc); n_fq_poly_set_fq_nmod(Acoeff + Ai, Bcoeff + Bi, ctx->fqctx); mpoly_monomial_zero(Aexp + N*Ai, N); (Aexp + N*Ai)[off] = Bi << shift; Ai++; } } A->length = Ai; } /* F = F + modulus*(A - F(v = alpha)) no assumptions about matching monomials F is in Fq[X][v] A is in Fq[X] it is expected that modulus(alpha) == 1 */ int fq_nmod_mpolyn_interp_crt_sm_poly( slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, const fq_nmod_poly_t A, const fq_nmod_poly_t modulus, const fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { int changed = 0; slong lastdeg = -WORD(1); fq_nmod_t u, v; slong Fi, Ti, Ai; fq_nmod_struct * Acoeff = A->coeffs; slong Flen = F->length; n_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; n_poly_struct * Tcoeffs; ulong * Texps; fq_nmod_poly_t tp; slong N, off, shift; n_poly_t tpt; N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, F->bits, ctx->minfo); Fi = 0; Ai = fq_nmod_poly_degree(A, ctx->fqctx); fq_nmod_init(u, ctx->fqctx); fq_nmod_init(v, ctx->fqctx); fq_nmod_poly_init(tp, ctx->fqctx); n_poly_init(tpt); fq_nmod_mpolyn_fit_length(T, Flen + Ai + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; Ti = 0; while (Fi < Flen || Ai >= 0) { FLINT_ASSERT(Ti < T->alloc); if (Fi < Flen) { FLINT_ASSERT(!n_poly_is_zero(Fcoeffs + Fi)); FLINT_ASSERT(n_poly_degree(Fcoeffs + Fi) < fq_nmod_poly_degree(modulus, ctx->fqctx)); } if (Ai >= 0) { FLINT_ASSERT(!fq_nmod_is_zero(Acoeff + Ai, ctx->fqctx)); } mpoly_monomial_zero(Texps + N*Ti, N); if (Fi < Flen && Ai >= 0 && ((Fexps + N*Fi)[off]>>shift) == Ai) { /* F term ok, A term ok */ n_fq_poly_evaluate_fq_nmod(u, Fcoeffs + Fi, alpha, ctx->fqctx); fq_nmod_sub(v, Acoeff + Ai, u, ctx->fqctx); if (!fq_nmod_is_zero(v, ctx->fqctx)) { changed = 1; fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, v, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(tpt, tp, ctx->fqctx); n_fq_poly_add(Tcoeffs + Ti, Fcoeffs + Fi, tpt, ctx->fqctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx->fqctx); } (Texps + N*Ti)[off] = Ai << shift; Fi++; do { Ai--; } while (Ai >= 0 && fq_nmod_is_zero(Acoeff + Ai, ctx->fqctx)); } else if (Fi < Flen && (Ai < 0 || ((Fexps + N*Fi)[off]>>shift) > Ai)) { /* F term ok, A term missing */ n_fq_poly_evaluate_fq_nmod(v, Fcoeffs + Fi, alpha, ctx->fqctx); if (!fq_nmod_is_zero(v, ctx->fqctx)) { changed = 1; fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, v, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(tpt, tp, ctx->fqctx); n_fq_poly_sub(Tcoeffs + Ti, Fcoeffs + Fi, tpt, ctx->fqctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx->fqctx); } (Texps + N*Ti)[off] = (Fexps + N*Fi)[off]; Fi++; } else if (Ai >= 0 && (Fi >= Flen || ((Fexps + N*Fi)[off]>>shift) < Ai)) { /* F term missing, A term ok */ changed = 1; fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, Acoeff + Ai, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(Tcoeffs + Ti, tp, ctx->fqctx); (Texps + N*Ti)[off] = Ai << shift; do { Ai--; } while (Ai >= 0 && fq_nmod_is_zero(Acoeff + Ai, ctx->fqctx)); } else { FLINT_ASSERT(0); } FLINT_ASSERT(!n_poly_is_zero(Tcoeffs + Ti)); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Tcoeffs + Ti)); Ti++; } T->length = Ti; fq_nmod_clear(u, ctx->fqctx); fq_nmod_clear(v, ctx->fqctx); fq_nmod_poly_clear(tp, ctx->fqctx); n_poly_clear(tpt); if (changed) { fq_nmod_mpolyn_swap(T, F); } *lastdeg_ = lastdeg; return changed; } void fq_nmod_mpolyn_interp_lift_sm_bpoly( fq_nmod_mpolyn_t F, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); slong i, j, Fi; slong off0, shift0, off1, shift1; mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo); Fi = 0; for (i = A->length - 1; i >= 0; i--) { n_fq_poly_struct * Ai = A->coeffs + i; for (j = Ai->length - 1; j >= 0; j--) { if (_n_fq_is_zero(Ai->coeffs + d*j, d)) continue; fq_nmod_mpolyn_fit_length(F, Fi + 1, ctx); mpoly_monomial_zero(F->exps + N*Fi, N); (F->exps + N*Fi)[off0] += (i << shift0); (F->exps + N*Fi)[off1] += (j << shift1); n_fq_poly_set_n_fq(F->coeffs + Fi, Ai->coeffs + d*j, ctx->fqctx); Fi++; } } F->length = Fi; } int fq_nmod_mpolyn_interp_crt_sm_bpoly( slong * lastdeg, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, const n_fq_bpoly_t A, const n_fq_poly_t modulus, n_fq_poly_t alphapow, const fq_nmod_mpoly_ctx_t ctx) { int changed = 0; slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(F->bits, ctx->minfo); slong off0, shift0, off1, shift1; n_poly_struct * Acoeffs = A->coeffs; slong Fi, Ti, Ai, ai; slong Flen = F->length; ulong * Fexps = F->exps; n_fq_poly_struct * Fcoeffs = F->coeffs; ulong * Texps = T->exps; n_fq_poly_struct * Tcoeffs = T->coeffs; mp_limb_t * v = FLINT_ARRAY_ALLOC(d, mp_limb_t); ulong Fexpi, mask; FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(F, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx->fqctx)); mask = (-UWORD(1)) >> (FLINT_BITS - F->bits); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo); FLINT_ASSERT(T->bits == F->bits); *lastdeg = -1; Ti = Fi = 0; Ai = A->length - 1; ai = (Ai < 0) ? 0 : n_poly_degree(Acoeffs + Ai); while (Fi < Flen || Ai >= 0) { if (Ti >= T->alloc) { slong extra = FLINT_MAX(Flen - Fi, Ai); fq_nmod_mpolyn_fit_length(T, Ti + extra + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; } if (Fi < Flen) Fexpi = pack_exp2(((Fexps + N*Fi)[off0]>>shift0)&mask, ((Fexps + N*Fi)[off1]>>shift1)&mask); else Fexpi = 0; if (Fi < Flen && Ai >= 0 && Fexpi == pack_exp2(Ai, ai)) { /* F term ok, A term ok */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); n_fq_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx->fqctx); n_fq_sub(v, Acoeffs[Ai].coeffs + d*ai, v, ctx->fqctx); if (!_n_fq_is_zero(v, d)) { changed = 1; n_fq_poly_scalar_addmul_n_fq(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx->fqctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx->fqctx); } Fi++; do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_fq_poly_degree(Acoeffs + Ai); } } else if (Ai >= 0 && (Fi >= Flen || Fexpi < pack_exp2(Ai, ai))) { /* F term missing, A term ok */ mpoly_monomial_zero(Texps + N*Ti, N); (Texps + N*Ti)[off0] += (Ai << shift0); (Texps + N*Ti)[off1] += (ai << shift1); changed = 1; n_fq_poly_scalar_mul_n_fq(Tcoeffs + Ti, modulus, Acoeffs[Ai].coeffs + d*ai, ctx->fqctx); do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_fq_poly_degree(Acoeffs + Ai); } } else { FLINT_ASSERT(Fi < Flen && (Ai < 0 || Fexpi > pack_exp2(Ai, ai))); /* F term ok, Aterm missing */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); n_fq_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx->fqctx); if (!_n_fq_is_zero(v, d)) { changed = 1; _n_fq_neg(v, v, d, ctx->fqctx->mod); n_fq_poly_scalar_addmul_n_fq(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx->fqctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx->fqctx); } Fi++; } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeffs + Ti)); *lastdeg = FLINT_MAX(*lastdeg, n_fq_poly_degree(Tcoeffs + Ti)); Ti++; } T->length = Ti; if (changed) fq_nmod_mpolyn_swap(T, F); flint_free(v); return changed; } /****************************************************************************/ /* E = A(x_var = alpha) A is in Fq[x_0, ..., x_(var-2), x_(var-1)][x_var] E is in Fq[x_0, ..., x_(var-2)][x_(var-1)] */ void fq_nmod_mpolyn_interp_reduce_sm_mpolyn( fq_nmod_mpolyn_t E, fq_nmod_mpolyn_t A, slong var, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift, k; ulong mask; fq_nmod_t v; n_poly_struct * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong Alen = A->length; slong Ai; n_poly_struct * Ecoeff; ulong * Eexp; slong Ei; fq_nmod_init(v, ctx->fqctx); FLINT_ASSERT(var > 0); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); Ecoeff = E->coeffs; Eexp = E->exps; Ei = 0; for (Ai = 0; Ai < Alen; Ai++) { n_fq_poly_evaluate_fq_nmod(v, Acoeff + Ai, alpha, ctx->fqctx); k = ((Aexp + N*Ai)[offset] >> shift) & mask; if (fq_nmod_is_zero(v, ctx->fqctx)) { continue; } if (Ei > 0 && mpoly_monomial_equal_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ n_fq_poly_set_coeff_fq_nmod(Ecoeff + Ei - 1, k, v, ctx->fqctx); } else { FLINT_ASSERT(Ei == 0 || mpoly_monomial_gt_nomask_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Ei >= E->alloc) { fq_nmod_mpolyn_fit_length(E, Ei + 1, ctx); Ecoeff = E->coeffs; Eexp = E->exps; } mpoly_monomial_set_extra(Eexp + N*Ei, Aexp + N*Ai, N, offset, -(k << shift)); n_poly_zero(Ecoeff + Ei); n_fq_poly_set_coeff_fq_nmod(Ecoeff + Ei, k, v, ctx->fqctx); Ei++; } } E->length = Ei; fq_nmod_clear(v, ctx->fqctx); } /* A = B A is in Fq[x_0, ..., x_(var-1), x_(var-1)][x_var] B is in Fq[x_0, ..., x_(var-2)][x_(var-1)] */ void fq_nmod_mpolyn_interp_lift_sm_mpolyn( fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong offset, shift; slong vi; n_fq_poly_struct * Bcoeff = B->coeffs; ulong * Bexp = B->exps; slong Blen = B->length; slong Bi; n_fq_poly_struct * Acoeff; ulong * Aexp; slong Ai; fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Ai = 0; for (Bi = 0; Bi < Blen; Bi++) { if (Ai + (Bcoeff + Bi)->length >= A->alloc) { fq_nmod_mpolyn_fit_length(A, Ai + (Bcoeff + Bi)->length, ctx); Acoeff = A->coeffs; Aexp = A->exps; } for (vi = (Bcoeff + Bi)->length - 1; vi >= 0; vi--) { if (!_n_fq_is_zero(Bcoeff[Bi].coeffs + d*vi, d)) { mpoly_monomial_set_extra(Aexp + N*Ai, Bexp + N*Bi, N, offset, vi << shift); n_fq_poly_zero(Acoeff + Ai); n_fq_poly_set_coeff_n_fq(Acoeff + Ai, 0, Bcoeff[Bi].coeffs + d*vi, ctx->fqctx); Ai++; } } } A->length = Ai; } /* F = F + modulus*(A - F(alpha)) with matching monomials */ int fq_nmod_mpolyn_interp_mcrt_sm_mpoly( slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpoly_t A, /* could have zero coeffs */ const n_fq_poly_t modulus, n_fq_poly_t alphapow, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); #if FLINT_WANT_ASSERT slong N = mpoly_words_per_exp(A->bits, ctx->minfo); #endif slong lastdeg = *lastdeg_; int changed = 0; mp_limb_t * v = FLINT_ARRAY_ALLOC(d, mp_limb_t); slong i, Alen = A->length; mp_limb_t * Acoeffs = A->coeffs; n_fq_poly_struct * Fcoeffs = F->coeffs; FLINT_ASSERT(F->bits == A->bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(F->length == Alen); for (i = 0; i < Alen; i++) { FLINT_ASSERT(mpoly_monomial_equal(F->exps + N*i, A->exps + N*i, N)); FLINT_ASSERT(!n_fq_poly_is_zero(Fcoeffs + i)); FLINT_ASSERT(n_fq_poly_degree(Fcoeffs + i) < n_fq_poly_degree(modulus)); n_fq_poly_eval_pow(v, Fcoeffs + i, alphapow, ctx->fqctx); n_fq_sub(v, Acoeffs + d*i, v, ctx->fqctx); if (!_n_fq_is_zero(v, d)) { changed = 1; n_fq_poly_scalar_addmul_n_fq(Fcoeffs + i, Fcoeffs + i, modulus, v, ctx->fqctx); } FLINT_ASSERT(!n_fq_poly_is_zero(Fcoeffs + i)); lastdeg = FLINT_MAX(lastdeg, n_fq_poly_degree(Fcoeffs + i)); } flint_free(v); *lastdeg_ = lastdeg; return changed; } /* T = F + modulus*(A - F(x_var = alpha)) no assumptions about matching monomials F is in Fq[x_0, ..., x_(var-1), x_(var-1)][x_var] A is in Fq[x_0, ..., x_(var-2)][x_(var-1)] in order to fxn correctly, modulus(alpha) should be 1 */ int fq_nmod_mpolyn_interp_crt_sm_mpolyn( slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_mpolyn_t A, slong var, fq_nmod_poly_t modulus, const fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int changed = 0; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong lastdeg = -WORD(1); slong offset, shift; slong vi; fq_nmod_t v, at; fq_nmod_poly_t tp; n_fq_poly_t tpt; n_fq_poly_struct * Tcoeff; ulong * Texp; slong Ti; n_fq_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai; n_fq_poly_struct * Fcoeff = F->coeffs; slong Flen = F->length; ulong * Fexp = F->exps; slong Fi; fq_nmod_poly_init(tp, ctx->fqctx); fq_nmod_init(v, ctx->fqctx); fq_nmod_init(at, ctx->fqctx); n_fq_poly_init(tpt); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); FLINT_ASSERT(F->bits == A->bits); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Flen = F->length; fq_nmod_mpolyn_fit_length(T, FLINT_MAX(Flen, Alen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = 0; Fi = Ai = vi = 0; if (Ai < Alen) { vi = n_fq_poly_degree(A->coeffs + Ai); } while (Fi < Flen || Ai < Alen) { if (Ti >= T->alloc) { fq_nmod_mpolyn_fit_length(T, Ti + FLINT_MAX(Flen - Fi, Alen - Ai), ctx); Tcoeff = T->coeffs; Texp = T->exps; } if (Ai < Alen) { FLINT_ASSERT(!_n_fq_is_zero(Acoeff[Ai].coeffs + d*vi, d)); } if (Fi < Flen && Ai < Alen && mpoly_monomial_equal_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift)) { /* F term ok, A term ok */ n_fq_poly_evaluate_fq_nmod(v, Fcoeff + Fi, alpha, ctx->fqctx); n_fq_get_fq_nmod(at, Acoeff[Ai].coeffs + d*vi, ctx->fqctx); fq_nmod_sub(v, at, v, ctx->fqctx); if (!fq_nmod_is_zero(v, ctx->fqctx)) { changed = 1; fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, v, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(tpt, tp, ctx->fqctx); n_fq_poly_add(Tcoeff + Ti, Fcoeff + Fi, tpt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->fqctx); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; do { vi--; } while (vi >= 0 && _n_fq_is_zero(Acoeff[Ai].coeffs + d*vi, d)); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_fq_poly_degree(A->coeffs + Ai); } } } else if (Fi < Flen && (Ai >= Alen || mpoly_monomial_gt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))) { /* F term ok, A term missing */ n_fq_poly_evaluate_fq_nmod(v, Fcoeff + Fi, alpha, ctx->fqctx); if (!fq_nmod_is_zero(v, ctx->fqctx)) { changed = 1; fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, v, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(tpt, tp, ctx->fqctx); n_fq_poly_sub(Tcoeff + Ti, Fcoeff + Fi, tpt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->fqctx); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; } else { FLINT_ASSERT(Ai < Alen && (Fi >= Flen || mpoly_monomial_lt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))); /* F term missing, A term ok */ changed = 1; n_fq_get_fq_nmod(at, Acoeff[Ai].coeffs + d*vi, ctx->fqctx); fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, at, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(Tcoeff + Ti, tp, ctx->fqctx); mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, vi << shift); do { vi--; } while (vi >= 0 && _n_fq_is_zero(Acoeff[Ai].coeffs + d*vi, d)); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_fq_poly_degree(A->coeffs + Ai); } } } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + Ti)); lastdeg = FLINT_MAX(lastdeg, n_fq_poly_degree(Tcoeff + Ti)); Ti++; } T->length = Ti; if (changed) { fq_nmod_mpolyn_swap(T, F); } fq_nmod_poly_clear(tp, ctx->fqctx); fq_nmod_clear(v, ctx->fqctx); fq_nmod_clear(at, ctx->fqctx); n_fq_poly_clear(tpt); FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(F, ctx)); *lastdeg_ = lastdeg; return changed; } /*****************************************************************************/ /* A is in Fq [X][v] E is in (Fq[v]/alpha(v))[X] */ void fq_nmod_mpolyn_interp_reduce_lg_poly( fq_nmod_poly_t E, const fq_nmod_mpoly_ctx_t ectx, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb) { fq_nmod_t v; slong Ai, Alen, k; n_fq_poly_struct * Acoeff; ulong * Aexp; slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fq_nmod_init(v, ectx->fqctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = A->length; fq_nmod_poly_zero(E, ectx->fqctx); for (Ai = 0; Ai < Alen; Ai++) { k = (Aexp + N*Ai)[off] >> shift; bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(v, Acoeff + Ai, emb); fq_nmod_poly_set_coeff(E, k, v, ectx->fqctx); } fq_nmod_clear(v, ectx->fqctx); } /* A = B A is in Fq [X][][v] B is in (Fq[v]/alpha(v))[X] */ void fq_nmod_mpolyn_interp_lift_lg_poly( slong * lastdeg_, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong Bexp; slong Blen = fq_nmod_poly_length(B, ectx->fqctx); fq_nmod_struct * Bcoeff = B->coeffs; n_fq_poly_struct * Acoeff; ulong * Aexp; slong Ai; slong lastdeg = -WORD(1); slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; Ai = 0; for (Bexp = Blen - 1; Bexp >= 0; Bexp--) { if (!fq_nmod_is_zero(Bcoeff + Bexp, ectx->fqctx)) { FLINT_ASSERT(Ai < A->alloc); bad_fq_nmod_embed_fq_nmod_lg_to_n_fq_sm(Acoeff + Ai, Bcoeff + Bexp, emb); FLINT_ASSERT(!n_fq_poly_is_zero(Acoeff + Ai)); lastdeg = FLINT_MAX(lastdeg, n_fq_poly_degree(Acoeff + Ai)); mpoly_monomial_zero(Aexp + N*Ai, N); (Aexp + N*Ai)[off] = Bexp << shift; Ai++; } } A->length = Ai; *lastdeg_ = lastdeg; } /* F = F + modulus*((A - F(alpha))/(modulus(alpha))) F is in Fq [X][][v] A is in (Fq[v]/alpha(v))[X] alpha(v) is ectx->fqctx->modulus(v) */ int fq_nmod_mpolyn_interp_crt_lg_poly( slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_poly_t modulus, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { int changed = 0; slong lastdeg = -WORD(1); fq_nmod_t u, v; fq_nmod_poly_t u_sm, w; n_fq_poly_t wt; slong Fi, Ti, Aexp; fq_nmod_struct * Acoeff = A->coeffs; slong Flen = F->length; n_fq_poly_struct * Fcoeff = F->coeffs; ulong * Fexp = F->exps; n_fq_poly_struct * Tcoeff; ulong * Texp; fq_nmod_poly_t tp; fq_nmod_t inv_m_eval; slong N, off, shift; FLINT_ASSERT(T->bits == F->bits); N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, F->bits, ctx->minfo); fq_nmod_init(inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_sm_to_lg(inv_m_eval, modulus, emb); fq_nmod_inv(inv_m_eval, inv_m_eval, ectx->fqctx); fq_nmod_init(u, ectx->fqctx); fq_nmod_init(v, ectx->fqctx); fq_nmod_poly_init(u_sm, ctx->fqctx); fq_nmod_poly_init(w, ctx->fqctx); n_fq_poly_init(wt); Fi = 0; Aexp = fq_nmod_poly_degree(A, ectx->fqctx); fq_nmod_poly_init(tp, ctx->fqctx); fq_nmod_mpolyn_fit_length(T, Flen + Aexp + 1, ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = 0; while (Fi < Flen || Aexp >= 0) { FLINT_ASSERT(Ti < T->alloc); if (Fi < Flen) { FLINT_ASSERT(!n_fq_poly_is_zero(Fcoeff + Fi)); FLINT_ASSERT(n_fq_poly_degree(Fcoeff + Fi) < fq_nmod_poly_degree(modulus, ctx->fqctx)); } if (Aexp >= 0) { FLINT_ASSERT(!fq_nmod_is_zero(Acoeff + Aexp, ectx->fqctx)); } mpoly_monomial_zero(Texp + N*Ti, N); if (Fi < Flen && Aexp >= 0 && ((Fexp + N*Fi)[off]>>shift) == Aexp) { /* F term ok, A term ok */ bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(u, Fcoeff + Fi, emb); fq_nmod_sub(v, Acoeff + Aexp, u, ectx->fqctx); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, modulus, u_sm, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(wt, w, ctx->fqctx); n_fq_poly_add(Tcoeff + Ti, Fcoeff + Fi, wt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->fqctx); } (Texp + N*Ti)[off] = (Fexp + N*Fi)[off]; Fi++; do { Aexp--; } while (Aexp >= 0 && fq_nmod_is_zero(Acoeff + Aexp, ectx->fqctx)); } else if (Fi < Flen && (Aexp < 0 || ((Fexp + N*Fi)[off]>>shift) > Aexp)) { /* F term ok, A term missing */ bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(v, Fcoeff + Fi, emb); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, u_sm, modulus, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(wt, w, ctx->fqctx); n_fq_poly_add(Tcoeff + Ti, Fcoeff + Fi, wt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->fqctx); } (Texp + N*Ti)[off] = (Fexp + N*Fi)[off]; Fi++; } else if (Aexp >= 0 && (Fi >= Flen || ((Fexp + N*Fi)[off]>>shift) < Aexp)) { /* F term missing, A term ok */ changed = 1; fq_nmod_mul(u, Acoeff + Aexp, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, modulus, u_sm, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(Tcoeff + Ti, w, ctx->fqctx); (Texp + N*Ti)[off] = Aexp << shift; do { Aexp--; } while (Aexp >= 0 && fq_nmod_is_zero(Acoeff + Aexp, ectx->fqctx)); } else { FLINT_ASSERT(0); } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + Ti)); lastdeg = FLINT_MAX(lastdeg, n_fq_poly_degree(Tcoeff + Ti)); Ti++; } T->length = Ti; if (changed) { fq_nmod_mpolyn_swap(T, F); } fq_nmod_clear(u, ectx->fqctx); fq_nmod_clear(v, ectx->fqctx); fq_nmod_poly_clear(u_sm, ctx->fqctx); fq_nmod_poly_clear(w, ctx->fqctx); n_fq_poly_clear(wt); fq_nmod_clear(inv_m_eval, ectx->fqctx); *lastdeg_ = lastdeg; return changed; } void fq_nmod_mpolyn_interp_lift_lg_bpoly( slong * lastdeg_, fq_nmod_mpolyn_t F, const fq_nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(lgctx->fqctx); slong N = mpoly_words_per_exp_sp(F->bits, smctx->minfo); slong i, j, Fi; slong lastdeg = -WORD(1); slong off0, shift0, off1, shift1; mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, smctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, smctx->minfo); Fi = 0; for (i = A->length - 1; i >= 0; i--) { n_fq_poly_struct * Ai = A->coeffs + i; for (j = Ai->length - 1; j >= 0; j--) { if (_n_fq_is_zero(Ai->coeffs + lgd*j, lgd)) continue; fq_nmod_mpolyn_fit_length(F, Fi + 1, smctx); mpoly_monomial_zero(F->exps + N*Fi, N); (F->exps + N*Fi)[off0] += (i << shift0); (F->exps + N*Fi)[off1] += (j << shift1); bad_n_fq_embed_lg_to_sm(F->coeffs + Fi, Ai->coeffs + lgd*j, emb); lastdeg = FLINT_MAX(lastdeg, n_fq_poly_degree(F->coeffs + Fi)); Fi++; } } F->length = Fi; *lastdeg_ = lastdeg; } int fq_nmod_mpolyn_interp_crt_lg_bpoly( slong * lastdeg, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, n_fq_poly_t modulus, const fq_nmod_mpoly_ctx_t smctx, n_fq_bpoly_t A, const fq_nmod_mpoly_ctx_t lgctx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(lgctx->fqctx); int changed = 0; slong N = mpoly_words_per_exp(T->bits, smctx->minfo); slong off0, shift0, off1, shift1; n_fq_poly_struct * Acoeffs = A->coeffs; slong Fi, Ti, Ai, ai; slong Flen = F->length; ulong * Fexps = F->exps; n_fq_poly_struct * Fcoeffs = F->coeffs; ulong * Texps = T->exps; n_fq_poly_struct * Tcoeffs = T->coeffs; mp_limb_t * u = FLINT_ARRAY_ALLOC(3*lgd, mp_limb_t); mp_limb_t * v = u + lgd; mp_limb_t * inv_m_eval = v + lgd; n_fq_poly_t u_sm; ulong Fexpi, mask; mask = (-UWORD(1)) >> (FLINT_BITS - F->bits); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, smctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, smctx->minfo); n_fq_poly_init(u_sm); bad_n_fq_embed_sm_to_lg(u, modulus, emb); n_fq_inv(inv_m_eval, u, lgctx->fqctx); FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(F, smctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(A, lgctx->fqctx)); FLINT_ASSERT(T->bits == F->bits); *lastdeg = -1; Ti = Fi = 0; Ai = A->length - 1; ai = (Ai < 0) ? 0 : n_fq_poly_degree(Acoeffs + Ai); while (Fi < Flen || Ai >= 0) { if (Ti >= T->alloc) { slong extra = FLINT_MAX(Flen - Fi, Ai); fq_nmod_mpolyn_fit_length(T, Ti + extra + 1, smctx); Tcoeffs = T->coeffs; Texps = T->exps; } if (Fi < Flen) { Fexpi = pack_exp2(((Fexps + N*Fi)[off0]>>shift0)&mask, ((Fexps + N*Fi)[off1]>>shift1)&mask); } else { Fexpi = 0; } if (Fi < Flen && Ai >= 0 && Fexpi == pack_exp2(Ai, ai)) { /* F term ok, A term ok */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); bad_n_fq_embed_sm_to_lg(u, Fcoeffs + Fi, emb); n_fq_sub(v, Acoeffs[Ai].coeffs + lgd*ai, u, lgctx->fqctx); if (!_n_fq_is_zero(v, lgd)) { changed = 1; n_fq_mul(u, v, inv_m_eval, lgctx->fqctx); bad_n_fq_embed_lg_to_sm(u_sm, u, emb); n_fq_poly_mul(Tcoeffs + Ti, modulus, u_sm, smctx->fqctx); n_fq_poly_add(Tcoeffs + Ti, Tcoeffs + Ti, Fcoeffs + Fi, smctx->fqctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, smctx->fqctx); } Fi++; do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + lgd*ai, lgd)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_fq_poly_degree(Acoeffs + Ai); } } else if (Fi < Flen && (Ai < 0 || Fexpi > pack_exp2(Ai, ai))) { /* F term ok, Aterm missing */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); bad_n_fq_embed_sm_to_lg(v, Fcoeffs + Fi, emb); if (!_n_fq_is_zero(v, lgd)) { changed = 1; n_fq_mul(u, v, inv_m_eval, lgctx->fqctx); bad_n_fq_embed_lg_to_sm(u_sm, u, emb); n_fq_poly_mul(Tcoeffs + Ti, modulus, u_sm, smctx->fqctx); n_fq_poly_sub(Tcoeffs + Ti, Fcoeffs + Fi, Tcoeffs + Ti, smctx->fqctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, smctx->fqctx); } Fi++; } else { FLINT_ASSERT(Ai >= 0 && (Fi >= Flen || Fexpi < pack_exp2(Ai, ai))); /* F term missing, A term ok */ mpoly_monomial_zero(Texps + N*Ti, N); (Texps + N*Ti)[off0] += (Ai << shift0); (Texps + N*Ti)[off1] += (ai << shift1); changed = 1; n_fq_mul(u, Acoeffs[Ai].coeffs + lgd*ai, inv_m_eval, lgctx->fqctx); bad_n_fq_embed_lg_to_sm(u_sm, u, emb); n_fq_poly_mul(Tcoeffs + Ti, modulus, u_sm, smctx->fqctx); do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + lgd*ai, lgd)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_fq_poly_degree(Acoeffs + Ai); } } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeffs + Ti)); *lastdeg = FLINT_MAX(*lastdeg, n_fq_poly_degree(Tcoeffs + Ti)); Ti++; } T->length = Ti; if (changed) fq_nmod_mpolyn_swap(T, F); FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(F, smctx)); n_fq_poly_clear(u_sm); flint_free(u); return changed; } /*****************************************************************************/ /* A is in Fq [x_0,...,x_(var-2), x_(var-1)][x_var] E is in (Fq[x_var]/alpha(x_var))[x_0,...,x_(var-2)][x_(var-1)] */ void fq_nmod_mpolyn_interp_reduce_lg_mpolyn( fq_nmod_mpolyn_t E, const fq_nmod_mpoly_ctx_t ectx, fq_nmod_mpolyn_t A, slong var, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb) { slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift, k; ulong mask; fq_nmod_t v; n_fq_poly_struct * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong Alen = A->length; slong Ai; n_fq_poly_struct * Ecoeff; ulong * Eexp; slong Ei; fq_nmod_init(v, ectx->fqctx); FLINT_ASSERT(var > 0); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); Ecoeff = E->coeffs; Eexp = E->exps; Ei = 0; for (Ai = 0; Ai < Alen; Ai++) { bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(v, Acoeff + Ai, emb); k = ((Aexp + N*Ai)[offset] >> shift) & mask; if (fq_nmod_is_zero(v, ectx->fqctx)) { continue; } if (Ei > 0 && mpoly_monomial_equal_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ n_fq_poly_set_coeff_fq_nmod(Ecoeff + Ei - 1, k, v, ectx->fqctx); } else { FLINT_ASSERT(Ei == 0 || mpoly_monomial_gt_nomask_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Ei >= E->alloc) { fq_nmod_mpolyn_fit_length(E, Ei + 1, ectx); Ecoeff = E->coeffs; Eexp = E->exps; } mpoly_monomial_set_extra(Eexp + N*Ei, Aexp + N*Ai, N, offset, -(k << shift)); n_fq_poly_zero(Ecoeff + Ei); n_fq_poly_set_coeff_fq_nmod(Ecoeff + Ei, k, v, ectx->fqctx); Ei++; } } E->length = Ei; fq_nmod_clear(v, ectx->fqctx); } /* A = B using lowest degree representative A is in Fq [x_0,...,x_(var-2), x_(var-1)][x_var] B is in (Fq[x_var]/alpha(x_var))[x_0,...,x_(var-2)][x_(var-1)] alpha is emb->h */ void fq_nmod_mpolyn_interp_lift_lg_mpolyn( slong * lastdeg_, fq_nmod_mpolyn_t A, slong var, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(ectx->fqctx); slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong offset, shift; slong vi; n_fq_poly_struct * Bcoeff = B->coeffs; ulong * Bexp = B->exps; slong Blen = B->length; slong Bi; n_fq_poly_struct * Acoeff; ulong * Aexp; slong Ai; slong lastdeg = -WORD(1); FLINT_ASSERT(A->bits == B->bits); fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Ai = 0; for (Bi = 0; Bi < Blen; Bi++) { if (Ai + Bcoeff[Bi].length >= A->alloc) { fq_nmod_mpolyn_fit_length(A, Ai + Bcoeff[Bi].length, ctx); Acoeff = A->coeffs; Aexp = A->exps; } for (vi = Bcoeff[Bi].length - 1; vi >= 0; vi--) { if (_n_fq_is_zero(Bcoeff[Bi].coeffs + lgd*vi, lgd)) continue; mpoly_monomial_set_extra(Aexp + N*Ai, Bexp + N*Bi, N, offset, vi << shift); bad_n_fq_embed_lg_to_sm(Acoeff + Ai, Bcoeff[Bi].coeffs + lgd*vi, emb); FLINT_ASSERT(!n_fq_poly_is_zero(Acoeff + Ai)); lastdeg = FLINT_MAX(lastdeg, n_fq_poly_degree(Acoeff + Ai)); Ai++; } } A->length = Ai; *lastdeg_ = lastdeg; } /* F = F + modulus*((A - F(alpha))/modulus(alpha)) F is in Fq [x_0,...,x_(var-2), x_(var-1)][x_var] A is in (Fq[x_var]/alpha(x_var))[x_0,...,x_(var-2)][x_(var-1)] */ int fq_nmod_mpolyn_interp_crt_lg_mpolyn( slong * lastdeg_, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_poly_t modulus, slong var, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(ectx->fqctx); int changed = 0; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift; slong lastdeg = -WORD(1); slong vi; fq_nmod_t u, v; fq_nmod_poly_t u_sm, w; fq_nmod_t inv_m_eval; fq_nmod_t at; n_fq_poly_t wt; n_fq_poly_struct * Tcoeff; ulong * Texp; slong Ti; n_fq_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai; n_fq_poly_struct * Fcoeff = F->coeffs; slong Flen = F->length; ulong * Fexp = F->exps; slong Fi; fq_nmod_init(inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_sm_to_lg(inv_m_eval, modulus, emb); fq_nmod_inv(inv_m_eval, inv_m_eval, ectx->fqctx); fq_nmod_init(u, ectx->fqctx); fq_nmod_init(v, ectx->fqctx); fq_nmod_poly_init(u_sm, ctx->fqctx); fq_nmod_poly_init(w, ctx->fqctx); fq_nmod_init(at, ectx->fqctx); n_fq_poly_init(wt); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); FLINT_ASSERT(F->bits == A->bits); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Flen = F->length; fq_nmod_mpolyn_fit_length(T, FLINT_MAX(Flen, Alen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = 0; Fi = Ai = vi = 0; if (Ai < Alen) { vi = n_fq_poly_degree(A->coeffs + Ai); } while (Fi < Flen || Ai < Alen) { if (Ti >= T->alloc) { fq_nmod_mpolyn_fit_length(T, Ti + FLINT_MAX(Flen - Fi, Alen - Ai), ctx); Tcoeff = T->coeffs; Texp = T->exps; } if (Fi < Flen && Ai < Alen && mpoly_monomial_equal_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift)) { /* F term ok, A term ok */ bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(u, Fcoeff + Fi, emb); n_fq_get_fq_nmod(at, Acoeff[Ai].coeffs + lgd*vi, ectx->fqctx); fq_nmod_sub(v, at, u, ectx->fqctx); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, modulus, u_sm, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(wt, w, ctx->fqctx); n_fq_poly_add(Tcoeff + Ti, Fcoeff + Fi, wt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->fqctx); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; do { vi--; } while (vi >= 0 && _n_fq_is_zero(Acoeff[Ai].coeffs + lgd*vi, lgd)); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_fq_poly_degree(A->coeffs + Ai); } } } else if (Fi < Flen && (Ai >= Alen || mpoly_monomial_gt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))) { /* F term ok, A term missing */ bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(v, Fcoeff + Fi, emb); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, u_sm, modulus, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(wt, w, ctx->fqctx); n_fq_poly_sub(Tcoeff + Ti, Fcoeff + Fi, wt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + Ti, Fcoeff + Fi, ctx->fqctx); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; } else { FLINT_ASSERT(Ai < Alen && (Fi >= Flen || mpoly_monomial_lt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))); /* F term missing, A term ok */ changed = 1; n_fq_get_fq_nmod(at, Acoeff[Ai].coeffs + lgd*vi, ectx->fqctx); fq_nmod_mul(u, at, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, modulus, u_sm, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(Tcoeff + Ti, w, ctx->fqctx); mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, vi << shift); do { vi--; } while (vi >= 0 && _n_fq_is_zero(Acoeff[Ai].coeffs + lgd*vi, lgd)); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_fq_poly_degree(A->coeffs + Ai); } } } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + Ti)); lastdeg = FLINT_MAX(lastdeg, n_fq_poly_degree(Tcoeff + Ti)); Ti++; } T->length = Ti; if (changed) { fq_nmod_mpolyn_swap(T, F); } fq_nmod_clear(inv_m_eval, ectx->fqctx); fq_nmod_clear(u, ectx->fqctx); fq_nmod_clear(v, ectx->fqctx); fq_nmod_poly_clear(u_sm, ctx->fqctx); fq_nmod_poly_clear(w, ctx->fqctx); fq_nmod_clear(at, ectx->fqctx); n_fq_poly_clear(wt); FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(F, ctx)); *lastdeg_ = lastdeg; return changed; } /*****************************************************************************/ /* evaluate A at lastvar = alpha */ void fq_nmod_mpolyn_interp_reduce_sm_mpoly( fq_nmod_mpoly_t B, fq_nmod_mpolyn_t A, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, k, N; fq_nmod_t bt; FLINT_ASSERT(B->bits == A->bits); fq_nmod_init(bt, ctx->fqctx); fq_nmod_mpoly_fit_length(B, A->length, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); k = 0; for (i = 0; i < A->length; i++) { mpoly_monomial_set(B->exps + N*k, A->exps + N*i, N); n_fq_poly_evaluate_fq_nmod(bt, A->coeffs + i, alpha, ctx->fqctx); n_fq_set_fq_nmod(B->coeffs + d*k, bt, ctx->fqctx); k += !_n_fq_is_zero(B->coeffs + d*k, d); } B->length = k; fq_nmod_clear(bt, ctx->fqctx); } void fq_nmod_mpolyun_interp_reduce_sm_mpolyu( fq_nmod_mpolyu_t B, fq_nmod_mpolyun_t A, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { slong i, k; FLINT_ASSERT(B->bits == A->bits); fq_nmod_mpolyu_fit_length(B, A->length, ctx); k = 0; for (i = 0; i < A->length; i++) { B->exps[k] = A->exps[i]; fq_nmod_mpolyn_interp_reduce_sm_mpoly(B->coeffs + k, A->coeffs + i, alpha, ctx); k += !fq_nmod_mpoly_is_zero(B->coeffs + k, ctx); } B->length = k; } void fq_nmod_mpolyn_interp_lift_sm_mpoly( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i; slong N; n_fq_poly_struct * Acoeff; mp_limb_t * Bcoeff; ulong * Aexp, * Bexp; slong Blen; fq_nmod_mpolyn_fit_bits(A, B->bits, ctx); A->bits = B->bits; Blen = B->length; fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < Blen; i++) { n_fq_poly_set_n_fq(Acoeff + i, Bcoeff + d*i, ctx->fqctx); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } A->length = Blen; } void fq_nmod_mpolyun_interp_lift_sm_mpolyu( fq_nmod_mpolyun_t A, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; FLINT_ASSERT(A->bits == B->bits); fq_nmod_mpolyun_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; fq_nmod_mpolyn_interp_lift_sm_mpoly(A->coeffs + i, B->coeffs + i, ctx); FLINT_ASSERT((A->coeffs + i)->bits == B->bits); } A->length = B->length; } /* F = F + modulus*(A - F(alpha)) */ int fq_nmod_mpolyn_interp_crt_sm_mpoly( slong * lastdeg, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_mpoly_t A, fq_nmod_poly_t modulus, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); int changed = 0; slong i, j, k; fq_nmod_t v; slong Flen = F->length, Alen = A->length; ulong * Fexp = F->exps, * Aexp = A->exps; ulong * Texp; mp_limb_t * Acoeff = A->coeffs; n_fq_poly_struct * Fcoeff = F->coeffs; n_fq_poly_struct * Tcoeff; fq_nmod_poly_t tp; n_fq_poly_t tpt; fq_nmod_t at; FLINT_ASSERT(F->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); fq_nmod_init(v, ctx->fqctx); fq_nmod_poly_init(tp, ctx->fqctx); n_fq_poly_init(tpt); fq_nmod_init(at, ctx->fqctx); fq_nmod_mpolyn_fit_length(T, Flen + Alen, ctx); Texp = T->exps; Tcoeff = T->coeffs; i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || mpoly_monomial_gt_nomask(Fexp + N*i, Aexp + N*j, N))) { FLINT_ASSERT(!n_fq_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_fq_poly_degree(Fcoeff + i) < fq_nmod_poly_degree(modulus, ctx->fqctx)); /* F term ok, A term missing */ n_fq_poly_evaluate_fq_nmod(v, Fcoeff + i, alpha, ctx->fqctx); if (!fq_nmod_is_zero(v, ctx->fqctx)) { changed = 1; fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, v, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(tpt, tp, ctx->fqctx); n_fq_poly_sub(Tcoeff + k, Fcoeff + i, tpt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + k, Fcoeff + i, ctx->fqctx); } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + k)); lastdeg[0] = FLINT_MAX(lastdeg[0], n_fq_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Fexp + N*i, N); k++; i++; } else if (j < Alen && (i >= Flen || mpoly_monomial_lt_nomask(Fexp + N*i, Aexp + N*j, N))) { /* F term missing, A term ok */ if (!_n_fq_is_zero(Acoeff + d*j, d)) { changed = 1; n_fq_get_fq_nmod(at, Acoeff + d*j, ctx->fqctx); fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, at, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(Tcoeff + k, tp, ctx->fqctx); FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + k)); lastdeg[0] = FLINT_MAX(lastdeg[0], n_fq_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; } j++; } else if (i < Flen && j < Alen && mpoly_monomial_equal(Fexp + N*i, Aexp + N*j, N)) { FLINT_ASSERT(!n_fq_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_fq_poly_degree(Fcoeff + i) < fq_nmod_poly_degree(modulus, ctx->fqctx)); /* F term ok, A term ok */ n_fq_poly_evaluate_fq_nmod(v, Fcoeff + i, alpha, ctx->fqctx); n_fq_get_fq_nmod(at, Acoeff + d*j, ctx->fqctx); fq_nmod_sub(v, at, v, ctx->fqctx); if (!fq_nmod_is_zero(v, ctx->fqctx)) { changed = 1; fq_nmod_poly_scalar_mul_fq_nmod(tp, modulus, v, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(tpt, tp, ctx->fqctx); n_fq_poly_add(Tcoeff + k, Fcoeff + i, tpt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + k, Fcoeff + i, ctx->fqctx); } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + k)); lastdeg[0] = FLINT_MAX(lastdeg[0], n_fq_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; i++; j++; } else { FLINT_ASSERT(0); } } T->length = k; if (changed) { fq_nmod_mpolyn_swap(T, F); } fq_nmod_poly_clear(tp, ctx->fqctx); fq_nmod_clear(v, ctx->fqctx); n_fq_poly_clear(tpt); fq_nmod_clear(at, ctx->fqctx); return changed; } int fq_nmod_mpolyun_interp_crt_sm_mpolyu( slong * lastdeg, fq_nmod_mpolyun_t F, fq_nmod_mpolyun_t T, fq_nmod_mpolyu_t A, fq_nmod_poly_t modulus, fq_nmod_t alpha, const fq_nmod_mpoly_ctx_t ctx) { int changed = 0; slong i, j, k; ulong * Texp; ulong * Fexp; ulong * Aexp; slong Flen; slong Alen; fq_nmod_mpolyn_t S; fq_nmod_mpolyn_struct * Tcoeff; fq_nmod_mpolyn_struct * Fcoeff; fq_nmod_mpoly_struct * Acoeff; fq_nmod_mpoly_t zero; lastdeg[0] = -WORD(1); FLINT_ASSERT(F->bits == T->bits); FLINT_ASSERT(T->bits == A->bits); fq_nmod_mpolyn_init(S, F->bits, ctx); Flen = F->length; Alen = A->length; fq_nmod_mpolyun_fit_length(T, Flen + Alen, ctx); Tcoeff = T->coeffs; Fcoeff = F->coeffs; Acoeff = A->coeffs; Texp = T->exps; Fexp = F->exps; Aexp = A->exps; fq_nmod_mpoly_init(zero, ctx); fq_nmod_mpoly_fit_length_reset_bits(zero, 0, A->bits, ctx); i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || Fexp[i] > Aexp[j])) { /* F term ok, A term missing */ fq_nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= fq_nmod_mpolyn_interp_crt_sm_mpoly(lastdeg, Tcoeff + k, S, zero, modulus, alpha, ctx); Texp[k] = Fexp[i]; k++; i++; } else if (j < Alen && (i >= Flen || Aexp[j] > Fexp[i])) { /* F term missing, A term ok */ fq_nmod_mpolyn_zero(Tcoeff + k, ctx); changed |= fq_nmod_mpolyn_interp_crt_sm_mpoly(lastdeg, Tcoeff + k, S, Acoeff + j, modulus, alpha, ctx); Texp[k] = Aexp[j]; k++; j++; } else if (i < Flen && j < Alen && (Fexp[i] == Aexp[j])) { /* F term ok, A term ok */ fq_nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= fq_nmod_mpolyn_interp_crt_sm_mpoly(lastdeg, Tcoeff + k, S, Acoeff + j, modulus, alpha, ctx); Texp[k] = Aexp[j]; FLINT_ASSERT(!fq_nmod_mpolyn_is_zero(Tcoeff + k, ctx)); k++; i++; j++; } else { FLINT_ASSERT(0); } } T->length = k; if (changed) { fq_nmod_mpolyun_swap(T, F); } fq_nmod_mpolyn_clear(S, ctx); fq_nmod_mpoly_clear(zero, ctx); return changed; } /*****************************************************************************/ /* reduce B via the map F_q[x] -> F_q^n */ void fq_nmod_mpolyn_interp_reduce_lg_mpoly( fq_nmod_mpoly_t A, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(ectx->fqctx); slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong i, k; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(ectx->minfo->ord == ORD_LEX); FLINT_ASSERT(ectx->minfo->nvars == ctx->minfo->nvars); k = 0; for (i = 0; i < B->length; i++) { fq_nmod_mpoly_fit_length(A, k + 1, ectx); mpoly_monomial_set(A->exps + N*k, B->exps + N*i, N); bad_n_fq_embed_sm_to_lg(A->coeffs + lgd*k, B->coeffs + i, emb); k += !_n_fq_is_zero(A->coeffs + lgd*k, lgd); } _fq_nmod_mpoly_set_length(A, k, ectx); } /* reduce B via the map from F_q[x] -> F_q^n */ void fq_nmod_mpolyun_interp_reduce_lg_mpolyu( fq_nmod_mpolyu_t A, fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb) { slong i, k, Blen; fq_nmod_mpoly_struct * Acoeff; fq_nmod_mpolyn_struct * Bcoeff; ulong * Aexp, * Bexp; Blen = B->length; fq_nmod_mpolyu_fit_length(A, Blen, ectx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; k = 0; for (i = 0; i < Blen; i++) { fq_nmod_mpolyn_interp_reduce_lg_mpoly(Acoeff + k, Bcoeff + i, ectx, ctx, emb); Aexp[k] = Bexp[i]; k += !fq_nmod_mpoly_is_zero(Acoeff + k, ectx); } A->length = k; } /* Convert B to A using the map F_q^n -> F_q[x] */ void fq_nmod_mpolyn_interp_lift_lg_mpoly( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(ectx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong i; FLINT_ASSERT(B->bits == A->bits); fq_nmod_mpolyn_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { mpoly_monomial_set(A->exps + N*i, B->exps + N*i, N); bad_n_fq_embed_lg_to_sm(A->coeffs + i, B->coeffs + lgd*i, emb); FLINT_ASSERT(!n_fq_poly_is_zero(A->coeffs + i)); } A->length = B->length; } void fq_nmod_mpolyun_interp_lift_lg_mpolyu( fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong i; FLINT_ASSERT(B->bits == A->bits); fq_nmod_mpolyun_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; fq_nmod_mpolyn_interp_lift_lg_mpoly(A->coeffs + i, ctx, B->coeffs + i, ectx, emb); FLINT_ASSERT(!fq_nmod_mpolyn_is_zero(A->coeffs + i, ctx)); } A->length = B->length; } /* update F so that it doesn't change mod m and is A mod emb->h F = F + m*((A - F(alpha))/(m(alpha))) no assumptions about matching monomials */ int fq_nmod_mpolyn_interp_crt_lg_mpoly( slong * lastdeg, fq_nmod_mpolyn_t F, fq_nmod_mpolyn_t T, fq_nmod_poly_t m, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpoly_t A, fq_nmod_t inv_m_eval, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(ectx->fqctx); int changed = 0; slong i, j, k; slong N; fq_nmod_t u, v; fq_nmod_poly_t u_sm, w; flint_bitcnt_t bits = A->bits; slong Flen = F->length, Alen = A->length; ulong * Fexp = F->exps, * Aexp = A->exps; ulong * Texp; mp_limb_t * Acoeff = A->coeffs; n_fq_poly_struct * Fcoeff = F->coeffs; n_fq_poly_struct * Tcoeff; fq_nmod_t at; n_fq_poly_t wt; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(F->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); fq_nmod_init(u, ectx->fqctx); fq_nmod_init(v, ectx->fqctx); fq_nmod_poly_init(u_sm, ctx->fqctx); fq_nmod_poly_init(w, ctx->fqctx); n_fq_poly_init(wt); fq_nmod_init(at, ectx->fqctx); fq_nmod_mpolyn_fit_length(T, Flen + Alen, ctx); Texp = T->exps; Tcoeff = T->coeffs; N = mpoly_words_per_exp(bits, ctx->minfo); i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || mpoly_monomial_gt_nomask(Fexp + N*i, Aexp + N*j, N))) { FLINT_ASSERT(!n_fq_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_fq_poly_degree(Fcoeff + i) < fq_nmod_poly_degree(m, ctx->fqctx)); /* F term ok, A term missing */ bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(v, Fcoeff + i, emb); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, u_sm, m, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(wt, w, ctx->fqctx); n_fq_poly_sub(Tcoeff + k, Fcoeff + i, wt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + k, Fcoeff + i, ctx->fqctx); } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + k)); lastdeg[0] = FLINT_MAX(lastdeg[0], n_fq_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Fexp + N*i, N); k++; i++; } else if (j < Alen && (i >= Flen || mpoly_monomial_lt_nomask(Fexp + N*i, Aexp + N*j, N))) { /* F term missing, A term ok */ if (!_n_fq_is_zero(Acoeff + lgd*j, lgd)) { changed = 1; n_fq_get_fq_nmod(at, Acoeff + lgd*j, ectx->fqctx); fq_nmod_mul(u, at, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, m, u_sm, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(Tcoeff + k, w, ctx->fqctx); FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + k)); lastdeg[0] = FLINT_MAX(lastdeg[0], n_fq_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; } j++; } else if (i < Flen && j < Alen && mpoly_monomial_equal(Fexp + N*i, Aexp + N*j, N)) { FLINT_ASSERT(!n_fq_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_fq_poly_degree(Fcoeff + i) < fq_nmod_poly_degree(m, ctx->fqctx)); /* F term ok, A term ok */ bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(u, Fcoeff + i, emb); n_fq_get_fq_nmod(at, Acoeff + lgd*j, ectx->fqctx); fq_nmod_sub(v, at, u, ectx->fqctx); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, m, u_sm, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(wt, w, ctx->fqctx); n_fq_poly_add(Tcoeff + k, Fcoeff + i, wt, ctx->fqctx); } else { n_fq_poly_set(Tcoeff + k, Fcoeff + i, ctx->fqctx); } FLINT_ASSERT(!n_fq_poly_is_zero(Tcoeff + k)); lastdeg[0] = FLINT_MAX(lastdeg[0], n_fq_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; i++; j++; } else { FLINT_ASSERT(0); } } T->length = k; if (changed) { fq_nmod_mpolyn_swap(T, F); } fq_nmod_clear(u, ectx->fqctx); fq_nmod_clear(v, ectx->fqctx); fq_nmod_poly_clear(u_sm, ctx->fqctx); fq_nmod_poly_clear(w, ctx->fqctx); n_fq_poly_clear(wt); fq_nmod_clear(at, ectx->fqctx); return changed; } int fq_nmod_mpolyun_interp_crt_lg_mpolyu( slong * lastdeg, fq_nmod_mpolyun_t F, fq_nmod_mpolyun_t T, fq_nmod_poly_t m, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { int changed = 0; slong i, j, k; ulong * Texp; ulong * Fexp; ulong * Aexp; slong Flen; slong Alen; fq_nmod_mpolyn_t S; fq_nmod_mpolyn_struct * Tcoeff; fq_nmod_mpolyn_struct * Fcoeff; fq_nmod_mpoly_struct * Acoeff; fq_nmod_mpoly_t zero; fq_nmod_t inv_m_eval; lastdeg[0] = -WORD(1); FLINT_ASSERT(F->bits == T->bits); FLINT_ASSERT(T->bits == A->bits); fq_nmod_mpolyn_init(S, F->bits, ctx); Flen = F->length; Alen = A->length; fq_nmod_mpolyun_fit_length(T, Flen + Alen, ctx); Tcoeff = T->coeffs; Fcoeff = F->coeffs; Acoeff = A->coeffs; Texp = T->exps; Fexp = F->exps; Aexp = A->exps; fq_nmod_mpoly_init(zero, ectx); fq_nmod_mpoly_fit_length_reset_bits(zero, 0, A->bits, ectx); fq_nmod_init(inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_sm_to_lg(inv_m_eval, m, emb); fq_nmod_inv(inv_m_eval, inv_m_eval, ectx->fqctx); i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || Fexp[i] > Aexp[j])) { /* F term ok, A term missing */ fq_nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= fq_nmod_mpolyn_interp_crt_lg_mpoly(lastdeg, Tcoeff + k, S, m, ctx, zero, inv_m_eval, ectx, emb); Texp[k] = Fexp[i]; FLINT_ASSERT(!fq_nmod_mpolyn_is_zero(Tcoeff + k, ctx)); k++; i++; } else if (j < Alen && (i >= Flen || Aexp[j] > Fexp[i])) { /* F term missing, A term ok */ fq_nmod_mpolyn_zero(Tcoeff + k, ctx); changed |= fq_nmod_mpolyn_interp_crt_lg_mpoly(lastdeg, Tcoeff + k, S, m, ctx, Acoeff + j, inv_m_eval, ectx, emb); Texp[k] = Aexp[j]; FLINT_ASSERT(!fq_nmod_mpolyn_is_zero(Tcoeff + k, ctx)); k++; j++; } else if (i < Flen && j < Alen && (Fexp[i] == Aexp[j])) { /* F term ok, A term ok */ fq_nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= fq_nmod_mpolyn_interp_crt_lg_mpoly(lastdeg, Tcoeff + k, S, m, ctx, Acoeff + j, inv_m_eval, ectx, emb); Texp[k] = Aexp[j]; FLINT_ASSERT(!fq_nmod_mpolyn_is_zero(Tcoeff + k, ctx)); k++; i++; j++; } else { FLINT_ASSERT(0); } } T->length = k; if (changed) { fq_nmod_mpolyun_swap(T, F); } fq_nmod_clear(inv_m_eval, ectx->fqctx); fq_nmod_mpolyn_clear(S, ctx); fq_nmod_mpoly_clear(zero, ectx); return changed; } /* Update H so that it does not change mod m, and is now A mod p It is asserted that the monomials in H and A match */ int fq_nmod_mpolyn_interp_mcrt_lg_mpoly( slong * lastdeg, fq_nmod_mpolyn_t H, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t m, fq_nmod_t inv_m_eval, fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(ectx->fqctx); slong i; #if FLINT_WANT_ASSERT slong N = mpoly_words_per_exp(A->bits, ctx->minfo); #endif int changed = 0; fq_nmod_t u, v, at; fq_nmod_poly_t w, u_sm; n_fq_poly_t wt; fq_nmod_init(u, ectx->fqctx); fq_nmod_init(v, ectx->fqctx); fq_nmod_poly_init(w, ctx->fqctx); n_fq_poly_init(wt); fq_nmod_poly_init(u_sm, ctx->fqctx); fq_nmod_init(at, ectx->fqctx); FLINT_ASSERT(H->length == A->length); FLINT_ASSERT(H->bits == A->bits); for (i = 0; i < A->length; i++) { FLINT_ASSERT(mpoly_monomial_equal(H->exps + N*i, A->exps + N*i, N)); bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(u, H->coeffs + i, emb); n_fq_get_fq_nmod(at, A->coeffs + lgd*i, ectx->fqctx); fq_nmod_sub(v, at, u, ectx->fqctx); if (!fq_nmod_is_zero(v, ectx->fqctx)) { changed = 1; fq_nmod_mul(u, v, inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_lg_to_sm(u_sm, u, emb); fq_nmod_poly_mul(w, u_sm, m, ctx->fqctx); n_fq_poly_set_fq_nmod_poly(wt, w, ctx->fqctx); n_fq_poly_add(H->coeffs + i, H->coeffs + i, wt, ctx->fqctx); } *lastdeg = FLINT_MAX(*lastdeg, n_fq_poly_degree(H->coeffs + i)); FLINT_ASSERT(n_fq_poly_degree(H->coeffs + i) < fq_nmod_poly_degree(m, ctx->fqctx) + fq_nmod_poly_degree(emb->h, ctx->fqctx)); } fq_nmod_clear(u, ectx->fqctx); fq_nmod_clear(v, ectx->fqctx); fq_nmod_poly_clear(w, ctx->fqctx); n_fq_poly_clear(wt); fq_nmod_poly_clear(u_sm, ctx->fqctx); fq_nmod_clear(at, ectx->fqctx); return changed; } int fq_nmod_mpolyun_interp_mcrt_lg_mpolyu( slong * lastdeg, fq_nmod_mpolyun_t H, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t m, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ectx, bad_fq_nmod_embed_t emb) { slong i; int changed = 0; fq_nmod_t inv_m_eval; *lastdeg = -WORD(1); fq_nmod_init(inv_m_eval, ectx->fqctx); bad_fq_nmod_embed_sm_to_lg(inv_m_eval, m, emb); fq_nmod_inv(inv_m_eval, inv_m_eval, ectx->fqctx); FLINT_ASSERT(H->bits == A->bits); FLINT_ASSERT(H->length == A->length); for (i = 0; i < A->length; i++) { FLINT_ASSERT(H->exps[i] == A->exps[i]); changed |= fq_nmod_mpolyn_interp_mcrt_lg_mpoly(lastdeg, H->coeffs + i, ctx, m, inv_m_eval, A->coeffs + i, ectx, emb); } H->length = A->length; fq_nmod_clear(inv_m_eval, ectx->fqctx); return changed; } flint-3.1.3/src/fq_nmod_mpoly/io.c000066400000000000000000000136611461254215100170470ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* printing *******************************************************************/ int fq_nmod_mpoly_fprint_pretty( FILE * file, const fq_nmod_mpoly_t A, const char ** x_in, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong len = A->length; ulong * exp = A->exps; slong bits = A->bits; slong i, j, N; fmpz * exponents; int r = 0; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { r = (EOF != fputc('0', file)); return r; } #define CHECK_r if (r <= 0) goto done; N = mpoly_words_per_exp(bits, ctx->minfo); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(ctx->minfo->nvars*sizeof(char *)); for (i = 0; i < ctx->minfo->nvars; i++) { x[i] = (char *) TMP_ALLOC(((FLINT_BITS+4)/3)*sizeof(char)); flint_sprintf(x[i], "x%wd", i+1); } } exponents = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(exponents + i); for (i = 0; i < len; i++) { if (i > 0) { r = flint_fprintf(file, " + "); CHECK_r } r = flint_fprintf(file, "("); CHECK_r r = n_fq_fprint_pretty(file, A->coeffs + d*i, ctx->fqctx); CHECK_r r = flint_fprintf(file, ")"); CHECK_r mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, ctx->minfo); for (j = 0; j < ctx->minfo->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, 1); if (cmp > 0) { r = flint_fprintf(file, "*%s^", x[j]); CHECK_r r = fmpz_fprint(file, exponents + j); CHECK_r } else if (cmp == 0) { r = flint_fprintf(file, "*%s", x[j]); CHECK_r } } } done: for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(exponents + i); TMP_END; return r; } int fq_nmod_mpoly_print_pretty(const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx) { return fq_nmod_mpoly_fprint_pretty(stdout, A, x, ctx); } /* debugging ******************************************************************/ /* test that r is a valid remainder upon division by g this means that no monomial of r is divisible by lm(g) */ void fq_nmod_mpoly_remainder_strongtest(const fq_nmod_mpoly_t r, const fq_nmod_mpoly_t g, const fq_nmod_mpoly_ctx_t ctx) { slong i, N, bits; ulong mask = 0; ulong * rexp, * gexp; bits = FLINT_MAX(r->bits, g->bits); N = mpoly_words_per_exp(bits, ctx->minfo); if (g->length == 0 ) flint_throw(FLINT_ERROR, "Zero denominator in remainder test"); if (r->length == 0 ) return; rexp = (ulong *) flint_malloc(N*r->length*sizeof(ulong)); gexp = (ulong *) flint_malloc(N*1 *sizeof(ulong)); mpoly_repack_monomials(rexp, bits, r->exps, r->bits, r->length, ctx->minfo); mpoly_repack_monomials(gexp, bits, g->exps, g->bits, 1, ctx->minfo); if (bits <= FLINT_BITS) mask = mpoly_overflow_mask_sp(bits); else mask = 0; for (i = 0; i < r->length; i++) { int divides; if (bits <= FLINT_BITS) divides = mpoly_monomial_divides_test(rexp + i*N, gexp + 0*N, N, mask); else divides = mpoly_monomial_divides_mp_test(rexp + i*N, gexp + 0*N, N, bits); if (divides) { flint_throw(FLINT_ERROR, "fq_nmod_mpoly_remainder_strongtest FAILED i = %wd\n" "rem %s\n\n" "den %s\n\n", i, fq_nmod_mpoly_get_str_pretty(r, NULL, ctx), fq_nmod_mpoly_get_str_pretty(g, NULL, ctx)); } } flint_free(rexp); flint_free(gexp); } void fq_nmod_mpolyn_print_pretty(const fq_nmod_mpolyn_t A, const char ** x_in, const fq_nmod_mpoly_ctx_t ctx) { slong len = A->length; ulong * exp = A->exps; slong bits = A->bits; slong i, j, N; fmpz * exponents; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { flint_printf("0"); return; } N = mpoly_words_per_exp(bits, ctx->minfo); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(ctx->minfo->nvars*sizeof(char *)); for (i = 0; i < ctx->minfo->nvars; i++) { x[i] = (char *) TMP_ALLOC(((FLINT_BITS+4)/3)*sizeof(char)); flint_sprintf(x[i], "x%wd", i+1); } } exponents = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(exponents + i); for (i = 0; i < len; i++) { if (i > 0) { printf(" + "); } flint_printf("("); n_fq_poly_print_pretty(A->coeffs + i, "v", ctx->fqctx); flint_printf(")"); mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, ctx->minfo); for (j = 0; j < ctx->minfo->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, WORD(1)); if (cmp > 0) { printf("*%s^", x[j]); fmpz_print(exponents + j); } else if (cmp == 0) { printf("*%s", x[j]); } } } for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(exponents + i); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/is_canonical.c000066400000000000000000000047211461254215100210570ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_is_canonical( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong i; if (d*A->length > A->coeffs_alloc) return 0; if (N*A->length > A->exps_alloc) return 0; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { if (!n_fq_is_canonical(A->coeffs + d*i, ctx->fqctx)) return 0; if (_n_fq_is_zero(A->coeffs + d*i, d)) return 0; } return 1; } void fq_nmod_mpoly_assert_canonical( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong i; if (d*A->length > A->coeffs_alloc) flint_throw(FLINT_ERROR, "Polynomial coefficient allocation is bad"); if (N*A->length > A->exps_alloc) flint_throw(FLINT_ERROR, "Polynomial exponent allocation is bad"); if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents out of order"); for (i = 0; i < A->length; i++) { if (!n_fq_is_canonical(A->coeffs + d*i, ctx->fqctx)) flint_throw(FLINT_ERROR, "Polynomial has a bad coefficient"); if (_n_fq_is_zero(A->coeffs + d*i, d)) flint_throw(FLINT_ERROR, "Polynomial has a zero coefficient"); } } flint-3.1.3/src/fq_nmod_mpoly/is_fq_nmod.c000066400000000000000000000014131461254215100205460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_is_fq_nmod(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong N; if (A->length > WORD(1)) return 0; if (A->length == WORD(0)) return 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } flint-3.1.3/src/fq_nmod_mpoly/is_gen.c000066400000000000000000000014561461254215100177030ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_is_gen(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); if (A->length != 1) return 0; if (!_n_fq_is_one(A->coeffs + d*0, d)) return 0; return mpoly_is_gen(A->exps, var, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/is_monic.c000066400000000000000000000011741461254215100202340ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_is_monic(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return A->length > 0 && _n_fq_is_one(A->coeffs + 0, fq_nmod_ctx_degree(ctx->fqctx)); } flint-3.1.3/src/fq_nmod_mpoly/is_one.c000066400000000000000000000014661461254215100177140ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_is_one(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N; if (A->length != 1) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return _n_fq_is_one(A->coeffs + d*0, d); } flint-3.1.3/src/fq_nmod_mpoly/lead_coeff_vars.c000066400000000000000000000037361461254215100215440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* leading coefficient wrt gen(0), ..., gen(num_vars-1) c will be returned with c->bits == A->bits */ void fq_nmod_mpolyl_lead_coeff( fq_nmod_mpoly_t c, const fq_nmod_mpoly_t A, slong num_vars, const fq_nmod_mpoly_ctx_t ctx) { slong d; slong i, j, off, shift; ulong mask, first_mask; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; ulong * cexps; slong Alen = A->length; FLINT_ASSERT(c != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) << shift; i = 0; first_mask = (Aexps + N*i)[off] & mask; for (i = 1; i < Alen; i++) { if (((Aexps + N*i)[off] & mask) != first_mask) goto break_outer; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto break_outer; } break_outer: fq_nmod_mpoly_fit_length_reset_bits(c, i, A->bits, ctx); c->length = i; cexps = c->exps; d = fq_nmod_ctx_degree(ctx->fqctx); _nmod_vec_set(c->coeffs, A->coeffs, d*i); mask = ~mask; for (i = 0; i < c->length; i++) { for (j = 0; j < off; j++) (cexps + N*i)[j] = (Aexps + N*i)[j]; (cexps + N*i)[off] = mask & (Aexps + N*i)[off]; for (j = off + 1; j < N; j++) (cexps + N*i)[j] = 0; } } flint-3.1.3/src/fq_nmod_mpoly/make_monic.c000066400000000000000000000017131461254215100205350ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_make_monic( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); mp_limb_t * c; TMP_INIT; if (B->length < 1) { flint_throw(FLINT_ERROR, "fq_nmod_mpoly_make_monic: input is zero"); } TMP_START; c = (mp_limb_t *) TMP_ALLOC((1 + N_FQ_INV_ITCH)*d*sizeof(mp_limb_t)); _n_fq_inv(c, B->coeffs + d*0, ctx->fqctx, c + d); fq_nmod_mpoly_scalar_mul_n_fq(A, B, c, ctx); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/mpolyn.c000066400000000000000000000077741461254215100177660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpolyn_one(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { n_poly_struct * Acoeff; ulong * Aexp; slong N; fq_nmod_mpolyn_fit_length(A, 1, ctx); Acoeff = A->coeffs; Aexp = A->exps; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); n_fq_poly_one(Acoeff + 0, ctx->fqctx); mpoly_monomial_zero(Aexp + N*0, N); A->length = 1; } int fq_nmod_mpolyn_is_canonical( const fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) { return 0; } if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { if (!n_fq_poly_is_canonical(A->coeffs + i, ctx->fqctx)) return 0; if (n_poly_is_zero(A->coeffs + i)) return 0; } return 1; } void fq_nmod_mpolyn_init(fq_nmod_mpolyn_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void fq_nmod_mpolyn_clear(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) n_poly_clear(A->coeffs + i); flint_free(A->coeffs); flint_free(A->exps); } void fq_nmod_mpolyn_swap(fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B) { fq_nmod_mpolyn_struct t = *A; *A = *B; *B = t; } void fq_nmod_mpolyn_zero(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { A->length = 0; } int fq_nmod_mpolyn_is_zero(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { return A->length == 0; } void fq_nmod_mpolyn_fit_length(fq_nmod_mpolyn_t A, slong length, const fq_nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); A->exps = (ulong *) flint_realloc(A->exps, new_alloc*N*sizeof(ulong)); A->coeffs = (n_poly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(n_poly_struct)); for (i = old_alloc; i < new_alloc; i++) n_poly_init(A->coeffs + i); A->alloc = new_alloc; } } void fq_nmod_mpolyn_fit_bits(fq_nmod_mpolyn_t A, slong bits, const fq_nmod_mpoly_ctx_t ctx) { slong N; ulong * t; if (A->bits < bits) { if (A->alloc != 0) { N = mpoly_words_per_exp(bits, ctx->minfo); t = flint_malloc(N*A->alloc*sizeof(ulong)); mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, ctx->minfo); flint_free(A->exps); A->exps = t; } A->bits = bits; } } void fq_nmod_mpolyn_set(fq_nmod_mpolyn_t A, const fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; n_poly_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; slong Blen; slong N; FLINT_ASSERT(A->bits == B->bits); /* fq_nmod_mpolyn_fit_bits(A, B->bits, ctx); A->bits = B->bits; */ Blen = B->length; fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < Blen; i++) { n_fq_poly_set(Acoeff + i, Bcoeff + i, ctx->fqctx); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } A->length = Blen; } flint-3.1.3/src/fq_nmod_mpoly/mpolyn_gcd_brown.c000066400000000000000000001052341461254215100220000ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpolyn_gcd_brown_smprime_bivar( fq_nmod_mpolyn_t G, fq_nmod_mpolyn_t Abar, fq_nmod_mpolyn_t Bbar, fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx) { int success; slong bound; fq_nmod_t alpha, temp, gammaeval; fq_nmod_poly_t Aeval, Beval, Geval, Abareval, Bbareval; fq_nmod_mpolyn_t T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; fq_nmod_poly_t cA, cB, cG, cAbar, cBbar, gamma, trem, leadG; fq_nmod_poly_t modulus, tempmod; flint_bitcnt_t bits = A->bits; slong N, off, shift; #if FLINT_WANT_ASSERT fq_nmod_poly_t leadA, leadB; #endif #if FLINT_WANT_ASSERT fq_nmod_poly_init(leadA, ctx->fqctx); fq_nmod_poly_init(leadB, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadA, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadB, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); #endif N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fq_nmod_poly_init(cA, ctx->fqctx); fq_nmod_poly_init(cB, ctx->fqctx); fq_nmod_poly_init(cG, ctx->fqctx); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_poly_init(tempmod, ctx->fqctx); fq_nmod_poly_init(trem, ctx->fqctx); fq_nmod_poly_init(leadG, ctx->fqctx); fq_nmod_poly_init(cAbar, ctx->fqctx); fq_nmod_poly_init(cBbar, ctx->fqctx); fq_nmod_poly_init(Aeval, ctx->fqctx); fq_nmod_poly_init(Beval, ctx->fqctx); fq_nmod_poly_init(Geval, ctx->fqctx); fq_nmod_poly_init(Abareval, ctx->fqctx); fq_nmod_poly_init(Bbareval, ctx->fqctx); fq_nmod_mpolyn_init(T, bits, ctx); fq_nmod_mpolyn_content_poly(cA, A, ctx); fq_nmod_mpolyn_content_poly(cB, B, ctx); fq_nmod_mpolyn_divexact_poly(A, A, cA, ctx, tempmod, trem); fq_nmod_mpolyn_divexact_poly(B, B, cB, ctx, tempmod, trem); fq_nmod_poly_gcd(cG, cA, cB, ctx->fqctx); fq_nmod_poly_divrem(cAbar, trem, cA, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); fq_nmod_poly_divrem(cBbar, trem, cB, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); fq_nmod_poly_init(gamma, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tempmod, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); fq_nmod_poly_gcd(gamma, trem, tempmod, ctx->fqctx); ldegA = fq_nmod_mpolyn_lastdeg(A, ctx); ldegB = fq_nmod_mpolyn_lastdeg(B, ctx); deggamma = fq_nmod_poly_degree(gamma, ctx->fqctx); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); fq_nmod_poly_one(modulus, ctx->fqctx); fq_nmod_poly_gen(tempmod, ctx->fqctx); fq_nmod_poly_neg(tempmod, tempmod, ctx->fqctx); fq_nmod_init(gammaeval, ctx->fqctx); fq_nmod_init(alpha, ctx->fqctx); fq_nmod_init(temp, ctx->fqctx); fq_nmod_set_ui(alpha, 0, ctx->fqctx); choose_prime: /* prime is v - alpha */ if (fq_nmod_next(alpha, ctx->fqctx) == 0) { success = 0; goto cleanup; } /* make sure evaluation point does not kill both lc(A) and lc(B) */ fq_nmod_poly_evaluate_fq_nmod(gammaeval, gamma, alpha, ctx->fqctx); if (fq_nmod_is_zero(gammaeval, ctx->fqctx)) { goto choose_prime; } /* evaluation point should kill neither A nor B */ fq_nmod_mpolyn_interp_reduce_sm_poly(Aeval, A, alpha, ctx); fq_nmod_mpolyn_interp_reduce_sm_poly(Beval, B, alpha, ctx); FLINT_ASSERT(Aeval->length > 0); FLINT_ASSERT(Beval->length > 0); fq_nmod_poly_gcd(Geval, Aeval, Beval, ctx->fqctx); fq_nmod_poly_divrem(Abareval, trem, Aeval, Geval, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); fq_nmod_poly_divrem(Bbareval, trem, Beval, Geval, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); FLINT_ASSERT(Geval->length > 0); FLINT_ASSERT(Abareval->length); FLINT_ASSERT(Bbareval->length > 0); if (fq_nmod_poly_degree(Geval, ctx->fqctx) == 0) { fq_nmod_mpolyn_one(G, ctx); fq_nmod_mpolyn_swap(Abar, A); fq_nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { FLINT_ASSERT(G->length > 0); if (fq_nmod_poly_degree(Geval, ctx->fqctx) > ((G->exps + N*0)[off]>>shift)) { goto choose_prime; } else if (fq_nmod_poly_degree(Geval, ctx->fqctx) < ((G->exps + N*0)[off]>>shift)) { fq_nmod_poly_one(modulus, ctx->fqctx); } } fq_nmod_poly_scalar_mul_fq_nmod(Geval, Geval, gammaeval, ctx->fqctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { fq_nmod_poly_evaluate_fq_nmod(temp, modulus, alpha, ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_poly_scalar_mul_fq_nmod(modulus, modulus, temp, ctx->fqctx); fq_nmod_mpolyn_interp_crt_sm_poly(&ldegG, G, T, Geval, modulus, alpha, ctx); fq_nmod_mpolyn_interp_crt_sm_poly(&ldegAbar, Abar, T, Abareval, modulus, alpha, ctx); fq_nmod_mpolyn_interp_crt_sm_poly(&ldegBbar, Bbar, T, Bbareval, modulus, alpha, ctx); } else { fq_nmod_mpolyn_interp_lift_sm_poly(G, Geval, ctx); fq_nmod_mpolyn_interp_lift_sm_poly(Abar, Abareval, ctx); fq_nmod_mpolyn_interp_lift_sm_poly(Bbar, Bbareval, ctx); ldegG = 0; ldegAbar = 0; ldegBbar = 0; } fq_nmod_poly_set_coeff(tempmod, 0, alpha, ctx->fqctx); fq_nmod_poly_mul(modulus, modulus, tempmod, ctx->fqctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } fq_nmod_poly_one(modulus, ctx->fqctx); goto choose_prime; successful: fq_nmod_mpolyn_content_poly(modulus, G, ctx); fq_nmod_mpolyn_divexact_poly(G, G, modulus, ctx, tempmod, trem); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); fq_nmod_mpolyn_divexact_poly(Abar, Abar, leadG, ctx, tempmod, trem); fq_nmod_mpolyn_divexact_poly(Bbar, Bbar, leadG, ctx, tempmod, trem); successful_put_content: fq_nmod_mpolyn_mul_poly(G, G, cG, ctx, tempmod); fq_nmod_mpolyn_mul_poly(Abar, Abar, cAbar, ctx, tempmod); fq_nmod_mpolyn_mul_poly(Bbar, Bbar, cBbar, ctx, tempmod); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadA, ctx->fqctx)); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadB, ctx->fqctx)); } fq_nmod_poly_clear(leadA, ctx->fqctx); fq_nmod_poly_clear(leadB, ctx->fqctx); #endif fq_nmod_poly_clear(cA, ctx->fqctx); fq_nmod_poly_clear(cB, ctx->fqctx); fq_nmod_poly_clear(cG, ctx->fqctx); fq_nmod_poly_clear(cAbar, ctx->fqctx); fq_nmod_poly_clear(cBbar, ctx->fqctx); fq_nmod_poly_clear(trem, ctx->fqctx); fq_nmod_poly_clear(leadG, ctx->fqctx); fq_nmod_poly_clear(gamma, ctx->fqctx); fq_nmod_poly_clear(Aeval, ctx->fqctx); fq_nmod_poly_clear(Beval, ctx->fqctx); fq_nmod_poly_clear(Geval, ctx->fqctx); fq_nmod_poly_clear(Abareval, ctx->fqctx); fq_nmod_poly_clear(Bbareval, ctx->fqctx); fq_nmod_clear(gammaeval, ctx->fqctx); fq_nmod_clear(alpha, ctx->fqctx); fq_nmod_clear(temp, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_poly_clear(tempmod, ctx->fqctx); fq_nmod_mpolyn_clear(T, ctx); return success; } int fq_nmod_mpolyn_gcd_brown_smprime( fq_nmod_mpolyn_t G, fq_nmod_mpolyn_t Abar, fq_nmod_mpolyn_t Bbar, fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { int success; slong bound; fq_nmod_t alpha, temp, gammaeval; fq_nmod_mpolyn_t Aeval, Beval, Geval, Abareval, Bbareval; fq_nmod_mpolyn_t T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; fq_nmod_poly_t cA, cB, cG, cAbar, cBbar, gamma, trem, leadG; fq_nmod_poly_t modulus, tempmod; flint_bitcnt_t bits = A->bits; slong N, offset, shift; #if FLINT_WANT_ASSERT fq_nmod_poly_t leadA, leadB; #endif FLINT_ASSERT(var > 0); if (var == 1) return fq_nmod_mpolyn_gcd_brown_smprime_bivar(G, Abar, Bbar, A, B, ctx); N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, G->bits, ctx->minfo); #if FLINT_WANT_ASSERT fq_nmod_poly_init(leadA, ctx->fqctx); fq_nmod_poly_init(leadB, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadA, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadB, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); #endif fq_nmod_init(gammaeval, ctx->fqctx); fq_nmod_init(alpha, ctx->fqctx); fq_nmod_init(temp, ctx->fqctx); fq_nmod_poly_init(cAbar, ctx->fqctx); fq_nmod_poly_init(cBbar, ctx->fqctx); fq_nmod_poly_init(trem, ctx->fqctx); fq_nmod_poly_init(leadG, ctx->fqctx); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_poly_init(tempmod, ctx->fqctx); fq_nmod_poly_init(gamma, ctx->fqctx); fq_nmod_poly_init(cG, ctx->fqctx); fq_nmod_poly_init(cA, ctx->fqctx); fq_nmod_poly_init(cB, ctx->fqctx); fq_nmod_mpolyn_init(Aeval, bits, ctx); fq_nmod_mpolyn_init(Beval, bits, ctx); fq_nmod_mpolyn_init(Geval, bits, ctx); fq_nmod_mpolyn_init(Abareval, bits, ctx); fq_nmod_mpolyn_init(Bbareval, bits, ctx); fq_nmod_mpolyn_init(T, bits, ctx); fq_nmod_mpolyn_content_poly(cA, A, ctx); fq_nmod_mpolyn_content_poly(cB, B, ctx); fq_nmod_mpolyn_divexact_poly(A, A, cA, ctx, tempmod, trem); fq_nmod_mpolyn_divexact_poly(B, B, cB, ctx, tempmod, trem); fq_nmod_poly_gcd(cG, cA, cB, ctx->fqctx); fq_nmod_poly_divrem(cAbar, trem, cA, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); fq_nmod_poly_divrem(cBbar, trem, cB, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tempmod, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); fq_nmod_poly_gcd(gamma, trem, tempmod, ctx->fqctx); ldegA = fq_nmod_mpolyn_lastdeg(A, ctx); ldegB = fq_nmod_mpolyn_lastdeg(B, ctx); deggamma = fq_nmod_poly_degree(gamma, ctx->fqctx); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); fq_nmod_poly_one(modulus, ctx->fqctx); fq_nmod_poly_gen(tempmod, ctx->fqctx); fq_nmod_poly_neg(tempmod, tempmod, ctx->fqctx); fq_nmod_set_ui(alpha, 0, ctx->fqctx); choose_prime: if (fq_nmod_next(alpha, ctx->fqctx) == 0) { success = 0; goto cleanup; } /* make sure evaluation point does not kill both lc(A) and lc(B) */ fq_nmod_poly_evaluate_fq_nmod(gammaeval, gamma, alpha, ctx->fqctx); if (fq_nmod_is_zero(gammaeval, ctx->fqctx)) { goto choose_prime; } /* evaluation point should kill neither A nor B */ fq_nmod_mpolyn_interp_reduce_sm_mpolyn(Aeval, A, var, alpha, ctx); fq_nmod_mpolyn_interp_reduce_sm_mpolyn(Beval, B, var, alpha, ctx); FLINT_ASSERT(Aeval->length > 0); FLINT_ASSERT(Beval->length > 0); success = fq_nmod_mpolyn_gcd_brown_smprime(Geval, Abareval, Bbareval, Aeval, Beval, var - 1, ctx); if (success == 0) { goto choose_prime; } FLINT_ASSERT(Geval->length > 0); FLINT_ASSERT(Abareval->length > 0); FLINT_ASSERT(Bbareval->length > 0); if (fq_nmod_mpolyn_is_nonzero_fq_nmod(Geval, ctx)) { fq_nmod_mpolyn_one(G, ctx); fq_nmod_mpolyn_swap(Abar, A); fq_nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { int cmp; slong k; FLINT_ASSERT(G->length > 0); k = n_fq_poly_degree(Geval->coeffs + 0); cmp = mpoly_monomial_cmp_nomask_extra(G->exps + N*0, Geval->exps + N*0, N, offset, k << shift); if (cmp < 0) { goto choose_prime; } else if (cmp > 0) { fq_nmod_poly_one(modulus, ctx->fqctx); } } n_fq_get_fq_nmod(temp, fq_nmod_mpolyn_leadcoeff(Geval, ctx), ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_mul(temp, temp, gammaeval, ctx->fqctx); fq_nmod_mpolyn_scalar_mul_fq_nmod(Geval, temp, ctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { fq_nmod_poly_evaluate_fq_nmod(temp, modulus, alpha, ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_poly_scalar_mul_fq_nmod(modulus, modulus, temp, ctx->fqctx); fq_nmod_mpolyn_interp_crt_sm_mpolyn(&ldegG, G, T, Geval, var, modulus, alpha, ctx); fq_nmod_mpolyn_interp_crt_sm_mpolyn(&ldegAbar, Abar, T, Abareval, var, modulus, alpha, ctx); fq_nmod_mpolyn_interp_crt_sm_mpolyn(&ldegBbar, Bbar, T, Bbareval, var, modulus, alpha, ctx); } else { fq_nmod_mpolyn_interp_lift_sm_mpolyn(G, Geval, var, ctx); fq_nmod_mpolyn_interp_lift_sm_mpolyn(Abar, Abareval, var, ctx); fq_nmod_mpolyn_interp_lift_sm_mpolyn(Bbar, Bbareval, var, ctx); ldegG = 0; ldegAbar = 0; ldegBbar = 0; } fq_nmod_poly_set_coeff(tempmod, 0, alpha, ctx->fqctx); fq_nmod_poly_mul(modulus, modulus, tempmod, ctx->fqctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } fq_nmod_poly_one(modulus, ctx->fqctx); goto choose_prime; successful: fq_nmod_mpolyn_content_poly(modulus, G, ctx); fq_nmod_mpolyn_divexact_poly(G, G, modulus, ctx, tempmod, trem); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); fq_nmod_mpolyn_divexact_poly(Abar, Abar, leadG, ctx, tempmod, trem); fq_nmod_mpolyn_divexact_poly(Bbar, Bbar, leadG, ctx, tempmod, trem); successful_put_content: fq_nmod_mpolyn_mul_poly(G, G, cG, ctx, tempmod); fq_nmod_mpolyn_mul_poly(Abar, Abar, cAbar, ctx, tempmod); fq_nmod_mpolyn_mul_poly(Bbar, Bbar, cBbar, ctx, tempmod); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadA, ctx->fqctx)); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadB, ctx->fqctx)); } fq_nmod_poly_clear(leadA, ctx->fqctx); fq_nmod_poly_clear(leadB, ctx->fqctx); #endif fq_nmod_clear(gammaeval, ctx->fqctx); fq_nmod_clear(alpha, ctx->fqctx); fq_nmod_clear(temp, ctx->fqctx); fq_nmod_poly_clear(cA, ctx->fqctx); fq_nmod_poly_clear(cB, ctx->fqctx); fq_nmod_poly_clear(cG, ctx->fqctx); fq_nmod_poly_clear(cAbar, ctx->fqctx); fq_nmod_poly_clear(cBbar, ctx->fqctx); fq_nmod_poly_clear(trem, ctx->fqctx); fq_nmod_poly_clear(leadG, ctx->fqctx); fq_nmod_poly_clear(gamma, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_poly_clear(tempmod, ctx->fqctx); fq_nmod_mpolyn_clear(Aeval, ctx); fq_nmod_mpolyn_clear(Beval, ctx); fq_nmod_mpolyn_clear(Geval, ctx); fq_nmod_mpolyn_clear(Abareval, ctx); fq_nmod_mpolyn_clear(Bbareval, ctx); fq_nmod_mpolyn_clear(T, ctx); return success; } int fq_nmod_mpolyn_gcd_brown_lgprime_bivar( fq_nmod_mpolyn_t G, fq_nmod_mpolyn_t Abar, fq_nmod_mpolyn_t Bbar, fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx) { int success; slong bound; fq_nmod_t temp, gammaeval; fq_nmod_poly_t Aeval, Beval, Geval, Abareval, Bbareval; fq_nmod_mpolyn_t T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; fq_nmod_poly_t cA, cB, cG, cAbar, cBbar, gamma, tquo, trem, leadG; fq_nmod_poly_t modulus, tempmod; flint_rand_t randstate; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx; slong N, off, shift; #if FLINT_WANT_ASSERT fq_nmod_poly_t leadA, leadB; #endif #if FLINT_WANT_ASSERT fq_nmod_poly_init(leadA, ctx->fqctx); fq_nmod_poly_init(leadB, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadA, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadB, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); #endif N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); fq_nmod_poly_init(tquo, ctx->fqctx); fq_nmod_poly_init(trem, ctx->fqctx); fq_nmod_poly_init(leadG, ctx->fqctx); fq_nmod_poly_init(cA, ctx->fqctx); fq_nmod_poly_init(cB, ctx->fqctx); fq_nmod_poly_init(cG, ctx->fqctx); fq_nmod_poly_init(cAbar, ctx->fqctx); fq_nmod_poly_init(cBbar, ctx->fqctx); fq_nmod_poly_init(gamma, ctx->fqctx); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_poly_init(tempmod, ctx->fqctx); fq_nmod_mpolyn_init(T, A->bits, ctx); fq_nmod_mpolyn_content_poly(cA, A, ctx); fq_nmod_mpolyn_content_poly(cB, B, ctx); fq_nmod_mpolyn_divexact_poly(A, A, cA, ctx, tquo, trem); fq_nmod_mpolyn_divexact_poly(B, B, cB, ctx, tquo, trem); fq_nmod_poly_gcd(cG, cA, cB, ctx->fqctx); fq_nmod_poly_divrem(cAbar, trem, cA, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); fq_nmod_poly_divrem(cBbar, trem, cB, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tempmod, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); fq_nmod_poly_gcd(gamma, trem, tempmod, ctx->fqctx); ldegA = fq_nmod_mpolyn_lastdeg(A, ctx); ldegB = fq_nmod_mpolyn_lastdeg(B, ctx); deggamma = fq_nmod_poly_degree(gamma, ctx->fqctx); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); fq_nmod_poly_one(modulus, ctx->fqctx); flint_randinit(randstate); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx, ctx, randstate); /* Once Aeval, Beval, ..., t are inited in ectx->fqctx, they do not need to be cleared and reinited when ectx->fqctx changes. Thanks fq_nmod! */ fq_nmod_poly_init(Aeval, ectx->fqctx); fq_nmod_poly_init(Beval, ectx->fqctx); fq_nmod_poly_init(Geval, ectx->fqctx); fq_nmod_poly_init(Abareval, ectx->fqctx); fq_nmod_poly_init(Bbareval, ectx->fqctx); fq_nmod_init(gammaeval, ectx->fqctx); fq_nmod_init(temp, ectx->fqctx); /* initialization already picked a prime */ goto have_prime; choose_prime: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, randstate); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto cleanup; } have_prime: /* make sure reduction does not kill both lc */ bad_fq_nmod_embed_sm_to_lg(gammaeval, gamma, cur_emb); if (fq_nmod_is_zero(gammaeval, ectx->fqctx)) { goto choose_prime; } /* make sure reduction does not kill either A or B */ fq_nmod_mpolyn_interp_reduce_lg_poly(Aeval, ectx, A, ctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_poly(Beval, ectx, B, ctx, cur_emb); if (Aeval->length == 0 || Beval->length == 0) { goto choose_prime; } fq_nmod_poly_gcd(Geval, Aeval, Beval, ectx->fqctx); success = fq_nmod_poly_divides(Abareval, Aeval, Geval, ectx->fqctx); FLINT_ASSERT(success); success = fq_nmod_poly_divides(Bbareval, Beval, Geval, ectx->fqctx); FLINT_ASSERT(success); FLINT_ASSERT(Geval->length > 0); FLINT_ASSERT(Abareval->length > 0); FLINT_ASSERT(Bbareval->length > 0); if (fq_nmod_poly_degree(Geval, ectx->fqctx) == 0) { fq_nmod_mpolyn_one(G, ctx); fq_nmod_mpolyn_swap(Abar, A); fq_nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { slong Gdeg; FLINT_ASSERT(G->length > 0); Gdeg = (G->exps + N*0)[off]>>shift; if (fq_nmod_poly_degree(Geval, ectx->fqctx) > Gdeg) { goto choose_prime; } else if (fq_nmod_poly_degree(Geval, ectx->fqctx) < Gdeg) { fq_nmod_poly_one(modulus, ctx->fqctx); } } FLINT_ASSERT(fq_nmod_is_one(Geval->coeffs + Geval->length - 1, ectx->fqctx)); fq_nmod_poly_scalar_mul_fq_nmod(Geval, Geval, gammaeval, ectx->fqctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { fq_nmod_mpolyn_interp_crt_lg_poly(&ldegG, G, T, modulus, ctx, Geval, ectx, cur_emb); fq_nmod_mpolyn_interp_crt_lg_poly(&ldegAbar, Abar, T, modulus, ctx, Abareval, ectx, cur_emb); fq_nmod_mpolyn_interp_crt_lg_poly(&ldegBbar, Bbar, T, modulus, ctx, Bbareval, ectx, cur_emb); } else { fq_nmod_mpolyn_interp_lift_lg_poly(&ldegG, G, ctx, Geval, ectx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_poly(&ldegAbar, Abar, ctx, Abareval, ectx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_poly(&ldegBbar, Bbar, ctx, Bbareval, ectx, cur_emb); } fq_nmod_poly_mul(modulus, modulus, cur_emb->h, ctx->fqctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } fq_nmod_poly_one(modulus, ctx->fqctx); goto choose_prime; successful: fq_nmod_mpolyn_content_poly(modulus, G, ctx); fq_nmod_mpolyn_divexact_poly(G, G, modulus, ctx, tquo, trem); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); fq_nmod_mpolyn_divexact_poly(Abar, Abar, leadG, ctx, tquo, trem); fq_nmod_mpolyn_divexact_poly(Bbar, Bbar, leadG, ctx, tquo, trem); successful_put_content: fq_nmod_mpolyn_mul_poly(G, G, cG, ctx, tquo); fq_nmod_mpolyn_mul_poly(Abar, Abar, cAbar, ctx, tquo); fq_nmod_mpolyn_mul_poly(Bbar, Bbar, cBbar, ctx, tquo); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadA, ctx->fqctx)); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadB, ctx->fqctx)); } fq_nmod_poly_clear(leadA, ctx->fqctx); fq_nmod_poly_clear(leadB, ctx->fqctx); #endif fq_nmod_poly_clear(cA, ctx->fqctx); fq_nmod_poly_clear(cB, ctx->fqctx); fq_nmod_poly_clear(cG, ctx->fqctx); fq_nmod_poly_clear(cAbar, ctx->fqctx); fq_nmod_poly_clear(cBbar, ctx->fqctx); fq_nmod_poly_clear(tquo, ctx->fqctx); fq_nmod_poly_clear(trem, ctx->fqctx); fq_nmod_poly_clear(leadG, ctx->fqctx); fq_nmod_poly_clear(gamma, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_poly_clear(tempmod, ctx->fqctx); fq_nmod_mpolyn_clear(T, ctx); fq_nmod_poly_clear(Aeval, ectx->fqctx); fq_nmod_poly_clear(Beval, ectx->fqctx); fq_nmod_poly_clear(Geval, ectx->fqctx); fq_nmod_poly_clear(Abareval, ectx->fqctx); fq_nmod_poly_clear(Bbareval, ectx->fqctx); fq_nmod_clear(gammaeval, ectx->fqctx); fq_nmod_clear(temp, ectx->fqctx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx, ctx, randstate); flint_randclear(randstate); return success; } int fq_nmod_mpolyn_gcd_brown_lgprime( fq_nmod_mpolyn_t G, fq_nmod_mpolyn_t Abar, fq_nmod_mpolyn_t Bbar, fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { int success; slong bound; fq_nmod_t temp, gammaeval; fq_nmod_mpolyn_t Aeval, Beval, Geval, Abareval, Bbareval; fq_nmod_mpolyn_t T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; fq_nmod_poly_t cA, cB, cG, cAbar, cBbar, gamma, tquo, trem, leadG; fq_nmod_poly_t modulus, tempmod; flint_rand_t randstate; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx; flint_bitcnt_t bits = A->bits; slong N, offset, shift; #if FLINT_WANT_ASSERT fq_nmod_poly_t leadA, leadB; #endif FLINT_ASSERT(var > 0); if (var == 1) return fq_nmod_mpolyn_gcd_brown_lgprime_bivar(G, Abar, Bbar, A, B, ctx); N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, bits, ctx->minfo); #if FLINT_WANT_ASSERT fq_nmod_poly_init(leadA, ctx->fqctx); fq_nmod_poly_init(leadB, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadA, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(leadB, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); #endif fq_nmod_poly_init(cA, ctx->fqctx); fq_nmod_poly_init(cB, ctx->fqctx); fq_nmod_poly_init(cG, ctx->fqctx); fq_nmod_poly_init(cAbar, ctx->fqctx); fq_nmod_poly_init(cBbar, ctx->fqctx); fq_nmod_poly_init(tquo, ctx->fqctx); fq_nmod_poly_init(trem, ctx->fqctx); fq_nmod_poly_init(leadG, ctx->fqctx); fq_nmod_poly_init(gamma, ctx->fqctx); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_poly_init(tempmod, ctx->fqctx); fq_nmod_mpolyn_init(T, bits, ctx); fq_nmod_mpolyn_content_poly(cA, A, ctx); fq_nmod_mpolyn_content_poly(cB, B, ctx); fq_nmod_mpolyn_divexact_poly(A, A, cA, ctx, tquo, trem); fq_nmod_mpolyn_divexact_poly(B, B, cB, ctx, tquo, trem); fq_nmod_poly_gcd(cG, cA, cB, ctx->fqctx); fq_nmod_poly_divrem(cAbar, trem, cA, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); fq_nmod_poly_divrem(cBbar, trem, cB, cG, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_is_zero(trem, ctx->fqctx)); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(A, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tempmod, fq_nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->fqctx); fq_nmod_poly_gcd(gamma, trem, tempmod, ctx->fqctx); ldegA = fq_nmod_mpolyn_lastdeg(A, ctx); ldegB = fq_nmod_mpolyn_lastdeg(B, ctx); deggamma = fq_nmod_poly_degree(gamma, ctx->fqctx); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); fq_nmod_poly_one(modulus, ctx->fqctx); flint_randinit(randstate); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx, ctx, randstate); /* Once Aeval, Beval, ..., t are inited in ectx->fqctx, they do not need to be cleared and reinited when ectx->fqctx changes. Thanks fq_nmod! */ fq_nmod_mpolyn_init(Aeval, bits, ectx); fq_nmod_mpolyn_init(Beval, bits, ectx); fq_nmod_mpolyn_init(Geval, bits, ectx); fq_nmod_mpolyn_init(Abareval, bits, ectx); fq_nmod_mpolyn_init(Bbareval, bits, ectx); fq_nmod_init(gammaeval, ectx->fqctx); fq_nmod_init(temp, ectx->fqctx); /* initialization already picked a prime */ goto have_prime; choose_prime: /* prime is irreducible element of Fq[v] (cur_emb->h) */ cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, randstate); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto cleanup; } have_prime: /* make sure reduction does not kill both lc */ bad_fq_nmod_embed_sm_to_lg(gammaeval, gamma, cur_emb); if (fq_nmod_is_zero(gammaeval, ectx->fqctx)) { goto choose_prime; } /* make sure reduction does not kill either A or B */ fq_nmod_mpolyn_interp_reduce_lg_mpolyn(Aeval, ectx, A, var, ctx, cur_emb); fq_nmod_mpolyn_interp_reduce_lg_mpolyn(Beval, ectx, B, var, ctx, cur_emb); if (Aeval->length == 0 || Beval->length == 0) { goto choose_prime; } FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(Aeval, ectx)); FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(Beval, ectx)); success = fq_nmod_mpolyn_gcd_brown_smprime(Geval, Abareval, Bbareval, Aeval, Beval, var - 1, ectx); if (success == 0) { goto choose_prime; } if (fq_nmod_mpolyn_is_nonzero_fq_nmod(Geval, ectx)) { fq_nmod_mpolyn_one(G, ctx); fq_nmod_mpolyn_swap(Abar, A); fq_nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { /* compare leading monomials of Geval and G */ int cmp = 0; slong k; FLINT_ASSERT(G->length > 0); k = n_fq_poly_degree(Geval->coeffs + 0); cmp = mpoly_monomial_cmp_nomask_extra(G->exps + N*0, Geval->exps + N*0, N, offset, k << shift); if (cmp < 0) { goto choose_prime; } else if (cmp > 0) { fq_nmod_poly_one(modulus, ctx->fqctx); } } n_fq_get_fq_nmod(temp, fq_nmod_mpolyn_leadcoeff(Geval, ectx), ectx->fqctx); fq_nmod_inv(temp, temp, ectx->fqctx); fq_nmod_mul(temp, temp, gammaeval, ectx->fqctx); fq_nmod_mpolyn_scalar_mul_fq_nmod(Geval, temp, ectx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { fq_nmod_mpolyn_interp_crt_lg_mpolyn(&ldegG, G, T, modulus, var, ctx, Geval, ectx, cur_emb); fq_nmod_mpolyn_interp_crt_lg_mpolyn(&ldegAbar, Abar, T, modulus, var, ctx, Abareval, ectx, cur_emb); fq_nmod_mpolyn_interp_crt_lg_mpolyn(&ldegBbar, Bbar, T, modulus, var, ctx, Bbareval, ectx, cur_emb); } else { fq_nmod_mpolyn_interp_lift_lg_mpolyn(&ldegG, G, var, ctx, Geval, ectx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_mpolyn(&ldegAbar, Abar, var, ctx, Abareval, ectx, cur_emb); fq_nmod_mpolyn_interp_lift_lg_mpolyn(&ldegBbar, Bbar, var, ctx, Bbareval, ectx, cur_emb); } fq_nmod_poly_mul(modulus, modulus, cur_emb->h, ctx->fqctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } fq_nmod_poly_one(modulus, ctx->fqctx); goto choose_prime; successful: fq_nmod_mpolyn_content_poly(modulus, G, ctx); fq_nmod_mpolyn_divexact_poly(G, G, modulus, ctx, tquo, trem); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); fq_nmod_mpolyn_divexact_poly(Abar, Abar, leadG, ctx, tquo, trem); fq_nmod_mpolyn_divexact_poly(Bbar, Bbar, leadG, ctx, tquo, trem); successful_put_content: fq_nmod_mpolyn_mul_poly(G, G, cG, ctx, tquo); fq_nmod_mpolyn_mul_poly(Abar, Abar, cAbar, ctx, tquo); fq_nmod_mpolyn_mul_poly(Bbar, Bbar, cBbar, ctx, tquo); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadA, ctx->fqctx)); n_fq_poly_get_fq_nmod_poly(leadG, fq_nmod_mpolyn_leadcoeff_poly(G, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(trem, fq_nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->fqctx); fq_nmod_poly_mul(modulus, leadG, trem, ctx->fqctx); FLINT_ASSERT(fq_nmod_poly_equal(modulus, leadB, ctx->fqctx)); } fq_nmod_poly_clear(leadA, ctx->fqctx); fq_nmod_poly_clear(leadB, ctx->fqctx); #endif fq_nmod_poly_clear(cA, ctx->fqctx); fq_nmod_poly_clear(cB, ctx->fqctx); fq_nmod_poly_clear(cG, ctx->fqctx); fq_nmod_poly_clear(cAbar, ctx->fqctx); fq_nmod_poly_clear(cBbar, ctx->fqctx); fq_nmod_poly_clear(tquo, ctx->fqctx); fq_nmod_poly_clear(trem, ctx->fqctx); fq_nmod_poly_clear(leadG, ctx->fqctx); fq_nmod_poly_clear(gamma, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_poly_clear(tempmod, ctx->fqctx); fq_nmod_mpolyn_clear(T, ctx); fq_nmod_mpolyn_clear(Aeval, ectx); fq_nmod_mpolyn_clear(Beval, ectx); fq_nmod_mpolyn_clear(Geval, ectx); fq_nmod_mpolyn_clear(Abareval, ectx); fq_nmod_mpolyn_clear(Bbareval, ectx); fq_nmod_clear(gammaeval, ectx->fqctx); fq_nmod_clear(temp, ectx->fqctx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx, ctx, randstate); flint_randclear(randstate); return success; } flint-3.1.3/src/fq_nmod_mpoly/mpolyu.c000066400000000000000000000567621461254215100177760ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" #include "fq_nmod_mpoly_factor.h" int fq_nmod_mpolyu_is_canonical(const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->length; i++) { if ((slong)(A->exps[i]) < 0) { return 0; } if (i > 0 && A->exps[i - 1] <= A->exps[i]) { return 0; } if (!fq_nmod_mpoly_is_canonical(A->coeffs + i, ctx)) { return 0; } if (fq_nmod_mpoly_is_zero(A->coeffs + i, ctx)) { return 0; } } return 1; } void fq_nmod_mpolyu_init(fq_nmod_mpolyu_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void fq_nmod_mpolyu_clear(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx) { slong i; for (i = 0; i < A->alloc; i++) fq_nmod_mpoly_clear(A->coeffs + i, uctx); flint_free(A->coeffs); flint_free(A->exps); } void fq_nmod_mpolyu_zero(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx) { slong i; for (i = 0; i < A->alloc; i++) { fq_nmod_mpoly_clear(A->coeffs + i, uctx); fq_nmod_mpoly_init(A->coeffs + i, uctx); } A->length = 0; } int fq_nmod_mpolyu_is_one(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx) { if (A->length != 1 || A->exps[0] != UWORD(0)) return 0; return fq_nmod_mpoly_is_one(A->coeffs + 0, uctx); } void fq_nmod_mpolyu_print_pretty(const fq_nmod_mpolyu_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (poly->length == 0) flint_printf("0"); for (i = 0; i < poly->length; i++) { if (i != 0) flint_printf(" + "); flint_printf("("); fq_nmod_mpoly_print_pretty(poly->coeffs + i,x,ctx); flint_printf(")*X^%wd",poly->exps[i]); } } void fq_nmod_mpolyu_fit_length(fq_nmod_mpolyu_t A, slong length, const fq_nmod_mpoly_ctx_t uctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (fq_nmod_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_nmod_mpoly_struct)); for (i = old_alloc; i < new_alloc; i++) fq_nmod_mpoly_init3(A->coeffs + i, 0, A->bits, uctx); A->alloc = new_alloc; } } void fq_nmod_mpolyu_one(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx) { fq_nmod_mpolyu_fit_length(A, 1, uctx); A->exps[0] = 0; fq_nmod_mpoly_one(A->coeffs + 0, uctx); A->length = 1; } void fq_nmod_mpolyu_degrees_si( slong * degs, const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong * pmax, mask; TMP_INIT; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (A->length < 1) { for (j = 0; j < ctx->minfo->nvars; j++) degs[j] = -1; } TMP_START; mask = mpoly_overflow_mask_sp(bits); pmax = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(pmax, N); for (i = 0; i < A->length; i++) { ulong * Aiexps = A->coeffs[i].exps; FLINT_ASSERT(A->coeffs[i].bits == bits); for (j = 0; j < A->coeffs[i].length; j++) mpoly_monomial_max(pmax, pmax, Aiexps + N*j, bits, N, mask); } mpoly_unpack_vec_ui((ulong *) degs, pmax, bits, ctx->minfo->nvars, 1); for (i = 0; i < ctx->minfo->nvars/2; i++) FLINT_SWAP(slong, degs[i], degs[ctx->minfo->nvars - i - 1]); TMP_END; } void fq_nmod_mpolyu_repack_bits_inplace( fq_nmod_mpolyu_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (bits == A->bits) return; A->bits = bits; for (i = 0; i < A->alloc; i++) fq_nmod_mpoly_repack_bits_inplace(A->coeffs + i, bits, ctx); } /* if the coefficient doesn't exist, a new one is created (and set to zero) */ fq_nmod_mpoly_struct * _fq_nmod_mpolyu_get_coeff(fq_nmod_mpolyu_t A, ulong pow, const fq_nmod_mpoly_ctx_t uctx) { slong i, j; fq_nmod_mpoly_struct * xk; for (i = 0; i < A->length && A->exps[i] >= pow; i++) { if (A->exps[i] == pow) { return A->coeffs + i; } } fq_nmod_mpolyu_fit_length(A, A->length + 1, uctx); for (j = A->length; j > i; j--) { A->exps[j] = A->exps[j - 1]; fq_nmod_mpoly_swap(A->coeffs + j, A->coeffs + j - 1, uctx); } A->length++; A->exps[i] = pow; xk = A->coeffs + i; xk->length = 0; FLINT_ASSERT(xk->bits == A->bits); return xk; } /* Convert B to A using the variable permutation perm. The uctx should be the context of the coefficients of A. The ctx should be the context of B. operation on each term: for 0 <= k <= m l = perm[k] Aexp[k] = (Bexp[l] - shift[l])/stride[l] */ void fq_nmod_mpoly_to_mpolyu_perm_deflate( fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j, k, l; slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong NA, NB; ulong * uexps; ulong * Bexps; fq_nmod_mpoly_struct * Ac; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 1 <= n); TMP_START; FLINT_ASSERT(fq_nmod_mpoly_is_canonical(B, ctx)); uexps = (ulong *) TMP_ALLOC((m + 1)*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); fq_nmod_mpolyu_zero(A, uctx); NA = mpoly_words_per_exp(A->bits, uctx->minfo); NB = mpoly_words_per_exp(B->bits, ctx->minfo); for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); for (k = 0; k < m + 1; k++) { l = perm[k]; FLINT_ASSERT(stride[l] != UWORD(0)); FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == UWORD(0)); uexps[k] = (Bexps[l] - shift[l]) / stride[l]; } Ac = _fq_nmod_mpolyu_get_coeff(A, uexps[0], uctx); FLINT_ASSERT(Ac->bits == A->bits); fq_nmod_mpoly_fit_length(Ac, Ac->length + 1, uctx); _n_fq_set(Ac->coeffs + d*Ac->length, B->coeffs + d*j, d); mpoly_set_monomial_ui(Ac->exps + NA*Ac->length, uexps + 1, A->bits, uctx->minfo); Ac->length++; } for (i = 0; i < A->length; i++) fq_nmod_mpoly_sort_terms(A->coeffs + i, uctx); TMP_END; FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(A, uctx)); } /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k <= m l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void fq_nmod_mpoly_from_mpolyu_perm_inflate( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong i, j, k, l; slong NA, NB; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * uexps; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 1 <= n); TMP_START; uexps = (ulong *) TMP_ALLOC((m + 1)*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, uctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { fq_nmod_mpoly_struct * Bc = B->coeffs + i; FLINT_ASSERT(Bc->bits == B->bits); _fq_nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, d, &Aexp, &A->exps_alloc, NA, Alen + Bc->length); for (j = 0; j < Bc->length; j++) { _n_fq_set(Acoeff + d*(Alen + j), Bc->coeffs + d*j, d); mpoly_get_monomial_ui(uexps + 1, Bc->exps + NB*j, Bc->bits, uctx->minfo); uexps[0] = B->exps[i]; for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m + 1; k++) { l = perm[k]; Aexps[l] += stride[l]*uexps[k]; } mpoly_set_monomial_ui(Aexp + NA*(Alen + j), Aexps, Abits, ctx->minfo); } Alen += Bc->length; } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; TMP_END; fq_nmod_mpoly_sort_terms(A, ctx); } /* Convert B to A using the variable permutation perm. The uctx should be the context of the coefficients of A. The ctx should be the context of B. operation on each term: for 0 <= k < m + 2 l = perm[k] Aexp[k] = (Bexp[l] - shift[l])/stride[l] the most significant main variable uses Aexp[0] the least significant main variable uses Aexp[1] the coefficients of A use variables Aexp[2], ..., Aexp[m + 1] maxexps if it exists is supposed to be a degree bound on B */ void fq_nmod_mpoly_to_mpolyuu_perm_deflate( fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j, k, l; slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong NA, NB; ulong * uexps; ulong * Bexps; fq_nmod_mpoly_struct * Ac; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 2 <= n); fq_nmod_mpolyu_zero(A, uctx); TMP_START; uexps = (ulong *) TMP_ALLOC((m + 2)*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(A->bits, uctx->minfo); NB = mpoly_words_per_exp(B->bits, ctx->minfo); for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); for (k = 0; k < m + 2; k++) { l = perm[k]; if (stride[l] == 1) { uexps[k] = (Bexps[l] - shift[l]); } else { FLINT_ASSERT(stride[l] != 0); FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == 0); uexps[k] = (Bexps[l] - shift[l]) / stride[l]; } } FLINT_ASSERT(FLINT_BIT_COUNT(uexps[0]) < FLINT_BITS/2); FLINT_ASSERT(FLINT_BIT_COUNT(uexps[1]) < FLINT_BITS/2); Ac = _fq_nmod_mpolyu_get_coeff(A, (uexps[0] << (FLINT_BITS/2)) + uexps[1], uctx); FLINT_ASSERT(Ac->bits == A->bits); fq_nmod_mpoly_fit_length(Ac, Ac->length + 1, uctx); _n_fq_set(Ac->coeffs + d*Ac->length, B->coeffs + d*j, d); mpoly_set_monomial_ui(Ac->exps + NA*Ac->length, uexps + 2, A->bits, uctx->minfo); Ac->length++; } for (i = 0; i < A->length; i++) fq_nmod_mpoly_sort_terms(A->coeffs + i, uctx); TMP_END; } /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k < m + 2 l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void fq_nmod_mpoly_from_mpolyuu_perm_inflate( /* only for 2 main vars */ fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong i, j, k, l; slong NA, NB; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * uexps; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 2 <= n); TMP_START; uexps = (ulong *) TMP_ALLOC((m + 2)*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, uctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { fq_nmod_mpoly_struct * Bc = B->coeffs + i; FLINT_ASSERT(Bc->bits == B->bits); _fq_nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, d, &Aexp, &A->exps_alloc, NA, Alen + Bc->length); for (j = 0; j < Bc->length; j++) { _n_fq_set(Acoeff + d*(Alen + j), Bc->coeffs + d*j, d); mpoly_get_monomial_ui(uexps + 2, Bc->exps + NB*j, Bc->bits, uctx->minfo); uexps[0] = B->exps[i] >> (FLINT_BITS/2); uexps[1] = B->exps[i] & ((-UWORD(1)) >> (FLINT_BITS - FLINT_BITS/2)); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m + 2; k++) { l = perm[k]; Aexps[l] += stride[l]*uexps[k]; } mpoly_set_monomial_ui(Aexp + NA*(Alen + j), Aexps, Abits, ctx->minfo); } Alen += Bc->length; } A->coeffs = Acoeff; A->exps = Aexp; _fq_nmod_mpoly_set_length(A, Alen, ctx); fq_nmod_mpoly_sort_terms(A, ctx); TMP_END; } /** 0 variables *************************************/ void fq_nmod_mpoly_to_mpolyl_perm_deflate( fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t lctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d; slong j, k, l; slong m = lctx->minfo->nvars; slong n = ctx->minfo->nvars; slong NA, NB; ulong * lexps; ulong * Bexps; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; fq_nmod_mpoly_fit_length(A, B->length, lctx); A->length = B->length; lexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(A->bits, lctx->minfo); NB = mpoly_words_per_exp(B->bits, ctx->minfo); d = fq_nmod_ctx_degree(ctx->fqctx); FLINT_ASSERT(d == fq_nmod_ctx_degree(lctx->fqctx)); _nmod_vec_set(A->coeffs, B->coeffs, B->length*d); for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); for (k = 0; k < m; k++) { l = perm[k]; if (stride[l] == 1) { lexps[k] = (Bexps[l] - shift[l]); } else { FLINT_ASSERT(stride[l] != 0); FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == 0); lexps[k] = (Bexps[l] - shift[l]) / stride[l]; } } mpoly_set_monomial_ui(A->exps + NA*j, lexps, A->bits, lctx->minfo); } TMP_END; fq_nmod_mpoly_sort_terms(A, lctx); FLINT_ASSERT(fq_nmod_mpoly_is_canonical(A, lctx)); } /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k < m + 2 l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void fq_nmod_mpoly_from_mpolyl_perm_inflate( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d; slong n = ctx->minfo->nvars; slong m = lctx->minfo->nvars; slong i, k, l; slong NA, NB; ulong * Bexps; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, lctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); A->length = B->length; d = fq_nmod_ctx_degree(ctx->fqctx); FLINT_ASSERT(d == fq_nmod_ctx_degree(lctx->fqctx)); _nmod_vec_set(A->coeffs, B->coeffs, B->length*d); for (i = 0; i < B->length; i++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, lctx->minfo); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m; k++) { l = perm[k]; Aexps[l] += stride[l]*Bexps[k]; } mpoly_set_monomial_ui(A->exps + NA*i, Aexps, Abits, ctx->minfo); } TMP_END; fq_nmod_mpoly_sort_terms(A, ctx); FLINT_ASSERT(fq_nmod_mpoly_is_canonical(A, ctx)); } void fq_nmod_mpolyu_shift_right(fq_nmod_mpolyu_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { FLINT_ASSERT(A->exps[i] >= s); A->exps[i] -= s; } } void fq_nmod_mpolyu_shift_left(fq_nmod_mpolyu_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { A->exps[i] += s; } } void fq_nmod_mpolyu_scalar_mul_fq_nmod(fq_nmod_mpolyu_t A, fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->length; i++) fq_nmod_mpoly_scalar_mul_fq_nmod(A->coeffs + i, A->coeffs + i, c, ctx); } void fq_nmod_mpolyu_set(fq_nmod_mpolyu_t A, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t uctx) { slong i; FLINT_ASSERT(A != B); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(B, uctx)); fq_nmod_mpolyu_fit_length(A, B->length, uctx); A->length = B->length; for (i = 0; i < B->length; i++) { fq_nmod_mpoly_set(A->coeffs + i, B->coeffs + i, uctx); A->exps[i] = B->exps[i]; } } void fq_nmod_mpolyu_divexact_mpoly_inplace( fq_nmod_mpolyu_t A, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong * cmpmask; fq_nmod_mpoly_t t; TMP_INIT; FLINT_ASSERT(bits == c->bits); FLINT_ASSERT(c->length > 0); if (fq_nmod_mpoly_is_fq_nmod(c, ctx)) { slong d = fq_nmod_ctx_degree(ctx->fqctx); mp_limb_t * inv; if (_n_fq_is_one(c->coeffs + d*0, d)) return; TMP_START; inv = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); n_fq_inv(inv, c->coeffs + d*0, ctx->fqctx); for (i = 0; i < A->length; i++) { fq_nmod_mpoly_struct * Ai = A->coeffs + i; for (j = 0; j < Ai->length; j++) n_fq_mul(Ai->coeffs + d*j, Ai->coeffs + d*j, inv, ctx->fqctx); } TMP_END; return; } fq_nmod_mpoly_init3(t, 0, bits, ctx); TMP_START; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); for (i = A->length - 1; i >= 0; i--) { FLINT_ASSERT(A->coeffs[i].bits == bits); _fq_nmod_mpoly_divides_monagan_pearce(t, A->coeffs[i].coeffs, A->coeffs[i].exps, A->coeffs[i].length, c->coeffs, c->exps, c->length, bits, N, cmpmask, ctx->fqctx); fq_nmod_mpoly_swap(A->coeffs + i, t, ctx); FLINT_ASSERT(A->coeffs[i].length > 0); } TMP_END; fq_nmod_mpoly_clear(t, ctx); } /* A = B * c and preserve the bit packing */ void fq_nmod_mpolyu_mul_mpoly( fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong * cmpmask; TMP_INIT; TMP_START; FLINT_ASSERT(A != B); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == c->bits); fq_nmod_mpolyu_fit_length(A, B->length, ctx); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; fq_nmod_mpoly_fit_length(A->coeffs + i, B->coeffs[i].length + c->length, ctx); _fq_nmod_mpoly_mul_johnson(A->coeffs + i, c->coeffs, c->exps, c->length, B->coeffs[i].coeffs, B->coeffs[i].exps, B->coeffs[i].length, bits, N, cmpmask, ctx->fqctx); } A->length = B->length; TMP_END; } void fq_nmod_mpolyu_mul_mpoly_inplace( fq_nmod_mpolyu_t A, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong i; ulong * cmpmask; fq_nmod_mpoly_t t; TMP_INIT; FLINT_ASSERT(bits == c->bits); FLINT_ASSERT(c->length > 0); if (fq_nmod_mpoly_is_fq_nmod(c, ctx)) { if (n_fq_is_one(c->coeffs + 0, ctx->fqctx)) return; for (i = 0; i < A->length; i++) fq_nmod_mpoly_scalar_mul_n_fq(A->coeffs + i, A->coeffs + i, c->coeffs + 0, ctx); return; } fq_nmod_mpoly_init3(t, 0, bits, ctx); TMP_START; cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); for (i = A->length - 1; i >= 0; i--) { FLINT_ASSERT(A->coeffs[i].bits == bits); _fq_nmod_mpoly_mul_johnson(t, A->coeffs[i].coeffs, A->coeffs[i].exps, A->coeffs[i].length, c->coeffs, c->exps, c->length, bits, N, cmpmask, ctx->fqctx); fq_nmod_mpoly_swap(A->coeffs + i, t, ctx); FLINT_ASSERT(A->coeffs[i].length > 0); } TMP_END; fq_nmod_mpoly_clear(t, ctx); } int fq_nmod_mpolyu_content_mpoly( fq_nmod_mpoly_t g, const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx) { int success; success = _fq_nmod_mpoly_vec_content_mpoly(g, A->coeffs, A->length, ctx); if (!success) fq_nmod_mpoly_zero(g, ctx); fq_nmod_mpoly_repack_bits_inplace(g, A->bits, ctx); return success; } flint-3.1.3/src/fq_nmod_mpoly/mpolyu_divides.c000066400000000000000000000367571461254215100215070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* A = D - B*C, coefficients of D are clobbered */ static void _fq_nmod_mpoly_mulsub(fq_nmod_mpoly_t A, mp_limb_t * Dcoeff, const ulong * Dexp, slong Dlen, const mp_limb_t * Bcoeffs, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexp, slong Clen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; mp_limb_t * Acoeffs = A->coeffs; ulong * Aexps = A->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; mp_limb_t * t; int lazy_size = _n_fq_dot_lazy_size(Blen, fqctx); TMP_INIT; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); TMP_START; next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* space for heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; t = (mp_limb_t *) TMP_ALLOC(6*d*sizeof(mp_limb_t)); /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, Bexp[0] + Cexp[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; if (bits <= FLINT_BITS) mpoly_monomial_add(heap[1].exp, Bexp + N*0, Cexp + N*0, N); else mpoly_monomial_add_mp(heap[1].exp, Bexp + N*0, Cexp + N*0, N); hind[0] = 2*1 + 0; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt(Dexp + N*Di, exp, N, cmpmask)) { _fq_nmod_mpoly_fit_length(&Acoeffs, &A->coeffs_alloc, d, &Aexps, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexps + N*Alen, Dexp + N*Di, N); _n_fq_set(Acoeffs + d*Alen, Dcoeff + d*Di, d); Alen++; Di++; } _fq_nmod_mpoly_fit_length(&Acoeffs, &A->coeffs_alloc, d, &Aexps, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexps + N*Alen, exp, N); _nmod_vec_zero(t, 6*d); switch (lazy_size) { case 1: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy1(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _n_fq_reduce2_lazy1(t, d, fqctx->mod); break; case 2: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy2(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _n_fq_reduce2_lazy2(t, d, fqctx->mod); break; case 3: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy3(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _n_fq_reduce2_lazy3(t, d, fqctx->mod); break; default: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, fqctx, t + 2*d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); break; } _n_fq_reduce2(Acoeffs + d*Alen, t, fqctx, t + 2*d); if (Di < Dlen && mpoly_monomial_equal(Dexp + N*Di, exp, N)) { _n_fq_sub(Acoeffs + d*Alen, Dcoeff + d*Di, Acoeffs + d*Alen, d, fqctx->mod); Di++; } else { _n_fq_neg(Acoeffs + d*Alen, Acoeffs + d*Alen, d, fqctx->mod); } Alen += !_n_fq_is_zero(Acoeffs + d*Alen, d); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ( (j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } FLINT_ASSERT(Di <= Dlen); if (Di < Dlen) { _fq_nmod_mpoly_fit_length(&Acoeffs, &A->coeffs_alloc, d, &Aexps, &A->exps_alloc, N, Alen + Dlen - Di); _nmod_vec_set(Acoeffs + d*Alen, Dcoeff + d*Di, d*(Dlen - Di)); mpoly_copy_monomials(Aexps + N*Alen, Dexp + N*Di, Dlen - Di, N); Alen += Dlen - Di; } A->coeffs = Acoeffs; A->exps = Aexps; A->length = Alen; TMP_END; } /* Q = A/B return 1 if division was exact. nmainvars is the number of main vars. */ int fq_nmod_mpolyuu_divides( fq_nmod_mpolyu_t Q, const fq_nmod_mpolyu_t A, const fq_nmod_mpolyu_t B, slong nmainvars, const fq_nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; fq_nmod_mpoly_struct * Bcoeff = B->coeffs; slong Blen = B->length; ulong * Bexp = B->exps; fq_nmod_mpoly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; fq_nmod_mpoly_struct * a, * b, * q; slong N; ulong * cmpmask; /* cmp mask for lesser variables */ fq_nmod_mpoly_t T, S; int success; ulong maskhi = 0; /* main variables are in lex */ int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; ulong mask, exp, maxexp = Aexp[Alen - 1]; TMP_INIT; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == Q->bits); TMP_START; N = mpoly_words_per_exp(bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < B->length; i++) hind[i] = 1; /* mask with high bit set in each field of main exponent vector */ mask = 0; for (i = 0; i < nmainvars; i++) mask = (mask << (FLINT_BITS/nmainvars)) + (UWORD(1) << (FLINT_BITS/nmainvars - 1)); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexp[0], x); Q->length = 0; fq_nmod_mpoly_init3(T, 16, bits, ctx); fq_nmod_mpoly_init3(S, 16, bits, ctx); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) { goto not_exact_division; } fq_nmod_mpolyu_fit_length(Q, Q->length + 1, ctx); lt_divides = mpoly_monomial_divides1(Q->exps + Q->length, exp, Bexp[0], mask); T->length = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { a = Acoeff + x->j; fq_nmod_mpoly_fit_length(S, T->length + a->length, ctx); S->length = _fq_nmod_mpoly_add( S->coeffs, S->exps, T->coeffs, T->exps, T->length, a->coeffs, a->exps, a->length, N, cmpmask, ctx->fqctx); } else { b = Bcoeff + x->i; q = Q->coeffs + x->j; _fq_nmod_mpoly_mulsub(S, T->coeffs, T->exps, T->length, b->coeffs, b->exps, b->length, q->coeffs, q->exps, q->length, bits, N, cmpmask, ctx->fqctx); } fq_nmod_mpoly_swap(S, T, ctx); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexp[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == Q->length) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } } } if (T->length == 0) { continue; } if (mpoly_monomials_overflow_test(T->exps, T->length, bits, ctx->minfo)) { goto not_exact_division; } q = Q->coeffs + Q->length; FLINT_ASSERT(q->bits == bits); b = Bcoeff + 0; if (!_fq_nmod_mpoly_divides_monagan_pearce(q, T->coeffs, T->exps, T->length, b->coeffs, b->exps, b->length, bits, N, cmpmask, ctx->fqctx)) { goto not_exact_division; } if (!lt_divides || (exp^maskhi) < (maxexp^maskhi)) { goto not_exact_division; } /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Q->length; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; Q->length++; } success = 1; cleanup: fq_nmod_mpoly_clear(T, ctx); fq_nmod_mpoly_clear(S, ctx); TMP_END; return success; not_exact_division: success = 0; Q->length = 0; goto cleanup; } flint-3.1.3/src/fq_nmod_mpoly/mpolyu_gcdp_zippel.c000066400000000000000000001355031461254215100223450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mpoly.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_next(fq_nmod_t alpha, const fq_nmod_ctx_t fqctx) { slong i; slong deg = nmod_poly_degree(fqctx->modulus); for (i = 0; i < deg; i++) { ulong c = nmod_poly_get_coeff_ui(alpha, i); c += UWORD(1); if (c < fqctx->mod.n) { nmod_poly_set_coeff_ui(alpha, i, c); return 1; } nmod_poly_set_coeff_ui(alpha, i, 0); } return 0; } void fq_nmod_next_not_zero(fq_nmod_t alpha, const fq_nmod_ctx_t fqctx) { slong i; slong deg = fqctx->modulus->length - 1; for (i = 0; i < deg; i++) { ulong c = nmod_poly_get_coeff_ui(alpha, i); c += UWORD(1); if (c < fqctx->mod.n) { nmod_poly_set_coeff_ui(alpha, i, c); return; } nmod_poly_set_coeff_ui(alpha, i, UWORD(0)); } /* we hit zero, so skip to 1 */ nmod_poly_set_coeff_ui(alpha, 0, UWORD(1)); } /* Assuming that "A" depends only on the main variable, convert it to a poly "a". */ static void fq_nmod_mpolyu_cvtto_poly( fq_nmod_poly_t a, fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; fq_nmod_t at; FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(A, ctx)); fq_nmod_init(at, ctx->fqctx); fq_nmod_poly_zero(a, ctx->fqctx); for (i = 0; i < A->length; i++) { FLINT_ASSERT((A->coeffs + i)->length == 1); FLINT_ASSERT(mpoly_monomial_is_zero((A->coeffs + i)->exps, mpoly_words_per_exp((A->coeffs + i)->bits, ctx->minfo))); n_fq_get_fq_nmod(at, (A->coeffs + i)->coeffs + 0, ctx->fqctx); fq_nmod_poly_set_coeff(a, A->exps[i], at, ctx->fqctx); } fq_nmod_clear(at, ctx->fqctx); } static void fq_nmod_mpolyu_cvtfrom_poly( fq_nmod_mpolyu_t A, fq_nmod_poly_t a, const fq_nmod_mpoly_ctx_t ctx) { slong i; slong k; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); fq_nmod_t c; fq_nmod_init(c, ctx->fqctx); fq_nmod_mpolyu_zero(A, ctx); k = 0; for (i = fq_nmod_poly_length(a, ctx->fqctx) - 1; i >= 0; i--) { fq_nmod_poly_get_coeff(c, a, i, ctx->fqctx); if (!fq_nmod_is_zero(c, ctx->fqctx)) { fq_nmod_mpolyu_fit_length(A, k + 1, ctx); A->exps[k] = i; fq_nmod_mpoly_fit_length_reset_bits(A->coeffs + k, 1, A->bits, ctx); n_fq_set_fq_nmod((A->coeffs + k)->coeffs + 0, c, ctx->fqctx); (A->coeffs + k)->length = 1; mpoly_monomial_zero((A->coeffs + k)->exps + N*0, N); k++; } } A->length = k; fq_nmod_clear(c, ctx->fqctx); } /* store in each coefficient the evaluation of the corresponding monomial */ static void fq_nmod_mpoly_evalsk( fq_nmod_mpoly_t A, fq_nmod_mpoly_t B, slong entries, slong * offs, ulong * masks, fq_nmod_struct * powers, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j; slong N; FLINT_ASSERT(A->bits == B->bits); fq_nmod_mpoly_fit_length(A, B->length, ctx); N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < B->length; i++) { _n_fq_one(A->coeffs + d*i, d); for (j = 0; j < entries; j++) { if ((B->exps + N*i)[offs[j]] & masks[j]) { n_fq_mul_fq_nmod(A->coeffs + d*i, A->coeffs + d*i, powers + j, ctx->fqctx); } } mpoly_monomial_set(A->exps + N*i, B->exps + N*i, N); } A->length = B->length; } static void fq_nmod_mpolyu_evalsk( fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, slong entries, slong * offs, ulong * masks, fq_nmod_struct * powers, const fq_nmod_mpoly_ctx_t ctx) { slong i; fq_nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; fq_nmod_mpoly_evalsk(A->coeffs + i, B->coeffs + i, entries, offs, masks, powers, ctx); } A->length = B->length; } /* multiply the coefficients of A pointwise by those of B */ static void fq_nmod_mpolyu_mulsk( fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j; FLINT_ASSERT(A->length == B->length); for (i = 0; i < A->length; i++) { FLINT_ASSERT(A->exps[i] == B->exps[i]); FLINT_ASSERT((A->coeffs + i)->length == (B->coeffs + i)->length); for (j = 0; j < (A->coeffs + i)->length; j++) { n_fq_mul((A->coeffs + i)->coeffs + d*j, (A->coeffs + i)->coeffs + d*j, (B->coeffs + i)->coeffs + d*j, ctx->fqctx); } } } /* return 0 if the leading coeff of A vanishes else return 1 */ static int fq_nmod_mpolyu_evalfromsk( fq_nmod_poly_t e, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t SK, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j; int ret = 0; mp_limb_t * pp, * acc; fq_nmod_t acct; FLINT_ASSERT(A->length == SK->length); pp = FLINT_ARRAY_ALLOC(d, mp_limb_t); acc = FLINT_ARRAY_ALLOC(d, mp_limb_t); fq_nmod_init(acct, ctx->fqctx); fq_nmod_poly_zero(e, ctx->fqctx); for (i = 0; i < A->length; i++) { FLINT_ASSERT((A->coeffs + i)->length == (SK->coeffs + i)->length); _n_fq_zero(acc, d); for (j = 0; j < A->coeffs[i].length; j++) { n_fq_mul(pp, A->coeffs[i].coeffs + d*j, SK->coeffs[i].coeffs + d*j, ctx->fqctx); n_fq_add(acc, acc, pp, ctx->fqctx); } n_fq_get_fq_nmod(acct, acc, ctx->fqctx); fq_nmod_poly_set_coeff(e, A->exps[i], acct, ctx->fqctx); ret |= (i == 0 && !fq_nmod_is_zero(acct, ctx->fqctx)); } flint_free(acc); flint_free(pp); fq_nmod_clear(acct, ctx->fqctx); return ret; } void fq_nmod_poly_product_roots(fq_nmod_poly_t P, fq_nmod_struct * r, slong n, const fq_nmod_ctx_t fqctx) { slong i; fq_nmod_poly_t B; fq_nmod_t a; fq_nmod_init(a, fqctx); fq_nmod_poly_init(B, fqctx); fq_nmod_poly_one(P, fqctx); fq_nmod_poly_gen(B, fqctx); for (i = 0; i < n; i++) { fq_nmod_neg(a, r + i, fqctx); fq_nmod_poly_set_coeff(B, 0, a, fqctx); fq_nmod_poly_mul(P, P, B, fqctx); } fq_nmod_clear(a, fqctx); fq_nmod_poly_clear(B, fqctx); } /* solve [ a[0] a[1] ... a[n-1] ] [ x[0] ] [ b[0] ] [ a[0]^2 a[1]^2 ... a[n-1]^2 ] [ x[1] ] [ b[1] ] [ ... ... ] . [ ... ] = [ ... ] [ a[0]^n a[1]^n ... a[n-1]^n ] [ x[n-1] ] [ b[n-1] ] for x */ int fq_nmod_vandsolve(mp_limb_t * X, mp_limb_t * A, fq_nmod_struct * b, slong n, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); int success = 0; slong i, j; fq_nmod_t t, s; fq_nmod_t Dinv; fq_nmod_poly_t Q, P, R, u; fq_nmod_struct * x, * a; x = FLINT_ARRAY_ALLOC(n, fq_nmod_struct); a = FLINT_ARRAY_ALLOC(n, fq_nmod_struct); fq_nmod_init(t, fqctx); fq_nmod_init(s, fqctx); fq_nmod_init(Dinv, fqctx); for (i = 0; i < n; i++) { fq_nmod_init(a + i, fqctx); fq_nmod_init(x + i, fqctx); n_fq_get_fq_nmod(a + i, A + d*i, fqctx); fq_nmod_zero(x + i, fqctx); } fq_nmod_poly_init(Q, fqctx); fq_nmod_poly_init(P, fqctx); fq_nmod_poly_init(R, fqctx); fq_nmod_poly_init(u, fqctx); fq_nmod_poly_gen(u, fqctx); fq_nmod_poly_product_roots(P, a, n, fqctx); for (i = 0; i < n; i++) { if (fq_nmod_is_zero(a + i, fqctx)) goto cleanup; fq_nmod_neg(t, a + i, fqctx); fq_nmod_poly_set_coeff(u, 0, t, fqctx); fq_nmod_poly_divrem(Q, R, P, u, fqctx); fq_nmod_poly_evaluate_fq_nmod(t, Q, a + i, fqctx); fq_nmod_mul(t, a + i, t, fqctx); if (fq_nmod_is_zero(t, fqctx)) goto cleanup; fq_nmod_inv(Dinv, t, fqctx); for (j = 0; j < n; j++) { fq_nmod_mul(t, b + j, Dinv, fqctx); fq_nmod_poly_get_coeff(s, Q, j, fqctx); fq_nmod_mul(t, t, s, fqctx); fq_nmod_add(x + i, x + i, t, fqctx); } } success = 1; cleanup: fq_nmod_poly_clear(Q, fqctx); fq_nmod_poly_clear(P, fqctx); fq_nmod_poly_clear(R, fqctx); fq_nmod_poly_clear(u, fqctx); fq_nmod_clear(t, fqctx); fq_nmod_clear(s, fqctx); fq_nmod_clear(Dinv, fqctx); for (i = 0; i < n; i++) { n_fq_set_fq_nmod(X + d*i, x + i, fqctx); fq_nmod_clear(a + i, fqctx); fq_nmod_clear(x + i, fqctx); } flint_free(a); flint_free(x); return success; } /* Try to set G to the gcd of A and B given the form f of G. return codes as enumerated in nmod_mpoly.h: nmod_mpoly_gcds_success, nmod_mpoly_gcds_form_wrong, nmod_mpoly_gcds_no_solution, nmod_mpoly_gcds_scales_not_found, nmod_mpoly_gcds_eval_point_not_found, nmod_mpoly_gcds_eval_gcd_deg_too_high */ nmod_gcds_ret_t fq_nmod_mpolyu_gcds_zippel( fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, fq_nmod_mpolyu_t f, slong var, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate, slong * degbound) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int eval_points_tried; nmod_gcds_ret_t success; fq_nmod_mpolyu_t Aevalsk1, Bevalsk1, fevalsk1, Aevalski, Bevalski, fevalski; fq_nmod_poly_t Aeval, Beval, Geval; fq_nmod_struct * alpha, * b; fq_nmod_mat_struct * M, * ML; fq_nmod_mat_t MF, Msol; int lc_ok; int underdeterminedcount = 0; int exceededcount = 0; int * ML_is_initialized; slong i, j, k, s, S, nullity; slong * tlen; slong l; fq_nmod_struct * W; slong entries; slong * offs; ulong * masks; fq_nmod_struct * powers; fq_nmod_t ck; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(f->length > 0); FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(A->bits == G->bits); FLINT_ASSERT(A->bits == f->bits); FLINT_ASSERT(var >= 0); FLINT_ASSERT(*degbound == f->exps[0]); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(A, ctx)); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(B, ctx)); FLINT_ASSERT(var > 0); if (f->length == 1) { if ((f->coeffs + 0)->length > 1) { /* impossible to find scale factors in this case */ return nmod_gcds_scales_not_found; } else { /* otherwise set the coeff of the monomial to one */ nmod_gcds_ret_t ret; FLINT_ASSERT((f->coeffs + 0)->length == 1); fq_nmod_mpolyu_set(G, f, ctx); _n_fq_one((G->coeffs + 0)->coeffs + d*0, d); fq_nmod_mpolyu_init(Aevalsk1, f->bits, ctx); ret = nmod_gcds_form_wrong; if ( fq_nmod_mpolyuu_divides(Aevalsk1, A, G, 1, ctx) && fq_nmod_mpolyuu_divides(Aevalsk1, B, G, 1, ctx)) { ret = nmod_gcds_success; } fq_nmod_mpolyu_clear(Aevalsk1, ctx); return ret; } } TMP_START; fq_nmod_init(ck, ctx->fqctx); fq_nmod_mpolyu_init(Aevalsk1, f->bits, ctx); fq_nmod_mpolyu_init(Bevalsk1, f->bits, ctx); fq_nmod_mpolyu_init(fevalsk1, f->bits, ctx); fq_nmod_mpolyu_init(Aevalski, f->bits, ctx); fq_nmod_mpolyu_init(Bevalski, f->bits, ctx); fq_nmod_mpolyu_init(fevalski, f->bits, ctx); fq_nmod_poly_init(Aeval, ctx->fqctx); fq_nmod_poly_init(Beval, ctx->fqctx); fq_nmod_poly_init(Geval, ctx->fqctx); tlen = (slong *) TMP_ALLOC(f->length*sizeof(slong)); for (i = 0; i < f->length; i++) { tlen[i] = i; } /* make tlen sort the coeffs so that (f->coeffs + tlen[j-1])->length <= (f->coeffs + tlen[j-0])->length for all j */ for (i = 1; ilength; i++) { for (j=i; j > 0 && (f->coeffs + tlen[j-1])->length > (f->coeffs + tlen[j-0])->length; j--) { slong temp = tlen[j-1]; tlen[j-1] = tlen[j-0]; tlen[j-0] = temp; } } /* l is the number of images we will try to construct */ l = f->length - 3; for (i = 0; i < f->length; i++) { l += (f->coeffs + i)->length; } l = l / (f->length - 1); l = FLINT_MAX(l, (f->coeffs + tlen[f->length - 1])->length); /* one extra test image */ l += 1; alpha = (fq_nmod_struct *) TMP_ALLOC(var*sizeof(fq_nmod_struct)); ML = (fq_nmod_mat_struct *) TMP_ALLOC(f->length*sizeof(fq_nmod_mat_struct)); b = (fq_nmod_struct *) TMP_ALLOC((f->coeffs + tlen[f->length - 1])->length *sizeof(fq_nmod_struct)); for (i = 0; i < var; i++) fq_nmod_init(alpha + i, ctx->fqctx); for (i = 0; i < (f->coeffs + tlen[f->length - 1])->length; i++) fq_nmod_init(b + i, ctx->fqctx); fq_nmod_mat_init(MF, 0, l, ctx->fqctx); M = (fq_nmod_mat_struct *) TMP_ALLOC(f->length*sizeof(fq_nmod_mat_struct)); ML_is_initialized = (int *) TMP_ALLOC(f->length*sizeof(int)); for (i = 0; i < f->length; i++) { fq_nmod_mat_init(M + i, l, (f->coeffs + i)->length, ctx->fqctx); ML_is_initialized[i] = 0; } W = (fq_nmod_struct *) flint_malloc(l*f->length*sizeof(fq_nmod_struct)); for (i = 0; i < l*f->length; i++) fq_nmod_init(W + i, ctx->fqctx); fq_nmod_mat_init(Msol, l, 1, ctx->fqctx); /* compute how many masks are needed */ entries = f->bits * var; offs = (slong *) TMP_ALLOC(entries*sizeof(slong)); masks = (ulong *) TMP_ALLOC(entries*sizeof(slong)); powers = (fq_nmod_struct *) TMP_ALLOC(entries*sizeof(fq_nmod_struct)); for (i = 0; i < entries; i++) fq_nmod_init(powers + i, ctx->fqctx); /***** evaluation loop head *******/ eval_points_tried = 0; pick_evaluation_point: if (++eval_points_tried > 10) { success = nmod_gcds_eval_point_not_found; goto finished; } /* avoid 0 for the evaluation points */ for (i = 0; i < var; i++) fq_nmod_randtest_not_zero(alpha + i, randstate, ctx->fqctx); /* store bit masks for each power of two of the non-main variables */ for (i = 0; i < var; i++) { slong shift, off; mpoly_gen_offset_shift_sp(&off, &shift, i, f->bits, ctx->minfo); for (j = 0; j < f->bits; j++) { offs[f->bits*i + j] = off; masks[f->bits*i + j] = UWORD(1) << (j + shift); if (j == 0) fq_nmod_set(powers + f->bits*i + j, alpha + i, ctx->fqctx); else fq_nmod_mul(powers + f->bits*i + j, powers + f->bits*i + j - 1, powers + f->bits*i + j - 1, ctx->fqctx); } } fq_nmod_mpolyu_evalsk(Aevalsk1, A, entries, offs, masks, powers, ctx); fq_nmod_mpolyu_evalsk(Bevalsk1, B, entries, offs, masks, powers, ctx); fq_nmod_mpolyu_evalsk(fevalsk1, f, entries, offs, masks, powers, ctx); for (i = 0; i < l*f->length; i++) { fq_nmod_zero(W + i, ctx->fqctx); } for (i = 0; i < l; i++) { if (i == 0) { fq_nmod_mpolyu_set(Aevalski, Aevalsk1, ctx); fq_nmod_mpolyu_set(Bevalski, Bevalsk1, ctx); fq_nmod_mpolyu_set(fevalski, fevalsk1, ctx); } else { fq_nmod_mpolyu_mulsk(Aevalski, Aevalsk1, ctx); fq_nmod_mpolyu_mulsk(Bevalski, Bevalsk1, ctx); fq_nmod_mpolyu_mulsk(fevalski, fevalsk1, ctx); } for (j = 0; j < f->length; j++) { for (k = 0; k < (f->coeffs + j)->length; k++) { n_fq_get_fq_nmod((M + j)->rows[i] + k, (fevalski->coeffs + j)->coeffs + d*k, ctx->fqctx); } } lc_ok = 1; lc_ok = lc_ok && fq_nmod_mpolyu_evalfromsk(Aeval, A, Aevalski, ctx); lc_ok = lc_ok && fq_nmod_mpolyu_evalfromsk(Beval, B, Bevalski, ctx); if (!lc_ok) { /* lc of A or B vanished */ goto pick_evaluation_point; } fq_nmod_poly_gcd(Geval, Aeval, Beval, ctx->fqctx); if (f->exps[0] < fq_nmod_poly_degree(Geval, ctx->fqctx)) { ++exceededcount; if (exceededcount < 2) goto pick_evaluation_point; success = nmod_gcds_eval_gcd_deg_too_high; goto finished; } if (f->exps[0] > fq_nmod_poly_degree(Geval, ctx->fqctx)) { success = nmod_gcds_form_main_degree_too_high; *degbound = fq_nmod_poly_degree(Geval, ctx->fqctx); goto finished; } k = fq_nmod_poly_length(Geval, ctx->fqctx); j = WORD(0); while ((--k) >= 0) { fq_nmod_poly_get_coeff(ck, Geval, k, ctx->fqctx); if (!fq_nmod_is_zero(ck, ctx->fqctx)) { while (j < f->length && f->exps[j] > k) { j++; } if (j >= f->length || f->exps[j] != k) { success = nmod_gcds_form_wrong; goto finished; } fq_nmod_set(W + l*j + i, ck, ctx->fqctx); } } } nullity = -1; fq_nmod_mat_clear(MF, ctx->fqctx); fq_nmod_mat_init(MF, 0, l, ctx->fqctx); for (S = 0; S < f->length; S++) { s = tlen[S]; if (!ML_is_initialized[s]) { fq_nmod_mat_init(ML + s, l, (f->coeffs + s)->length + l, ctx->fqctx); ML_is_initialized[s] = 1; for (i = 0; i < l; i++) { for (j = 0; j < (f->coeffs + s)->length; j++) { fq_nmod_set((ML + s)->rows[i] + j, (M + s)->rows[i] + j, ctx->fqctx); } fq_nmod_set((ML + s)->rows[i] + (f->coeffs + s)->length + i, W + l*s + i, ctx->fqctx); } } else { for (i = 0; i < l; i++) { for (j = 0; j < (f->coeffs + s)->length; j++) { fq_nmod_set((ML + s)->rows[i] + j, (M + s)->rows[i] + j, ctx->fqctx); } for (j = 0; j < l; j++) { if (j == i) { fq_nmod_set((ML + s)->rows[i] + (f->coeffs + s)->length + j, W + l*s + i, ctx->fqctx); } else { fq_nmod_zero((ML + s)->rows[i] + (f->coeffs + s)->length + j, ctx->fqctx); } } } } fq_nmod_mat_rref(ML + s, ML + s, ctx->fqctx); for (i = 0; i < (f->coeffs + s)->length; i++) { if (!fq_nmod_is_one((ML + s)->rows[i] + i, ctx->fqctx)) { /* evaluation points produced a singular vandermonde matrix */ goto pick_evaluation_point; } } { /* appends rows to MF */ fq_nmod_mat_t MFtemp; fq_nmod_mat_t Mwindow; fq_nmod_mat_window_init(Mwindow, ML + s, (f->coeffs + s)->length, (f->coeffs + s)->length, l, (f->coeffs + s)->length + l, ctx->fqctx); fq_nmod_mat_init(MFtemp, fq_nmod_mat_nrows(MF, ctx->fqctx) + l - (f->coeffs + s)->length, l, ctx->fqctx); fq_nmod_mat_concat_vertical(MFtemp, MF, Mwindow, ctx->fqctx); fq_nmod_mat_swap(MFtemp, MF, ctx->fqctx); fq_nmod_mat_clear(MFtemp, ctx->fqctx); fq_nmod_mat_window_clear(Mwindow, ctx->fqctx); } nullity = l - fq_nmod_mat_rref(MF, MF, ctx->fqctx); if (nullity == 0) { /* There is no solution for scale factors. Form f must be wrong */ success = nmod_gcds_form_wrong; goto finished; } if (nullity == 1) { /* There is one solution for scale factors based on equations considered thus far. Accept this as a solution and perform checks of the remaining equations at the end. */ break; } } if (nullity != 1) { ++underdeterminedcount; if (underdeterminedcount < 2) goto pick_evaluation_point; success = nmod_gcds_scales_not_found; goto finished; } nullity = fq_nmod_mat_nullspace(Msol, MF, ctx->fqctx); FLINT_ASSERT(nullity == 1); fq_nmod_mpolyu_setform(G, f, ctx); for (i = 0; i < f->length; i++) { for (j = 0; j < (f->coeffs + i)->length; j++) { FLINT_ASSERT((f->coeffs + i)->length <= l); FLINT_ASSERT(j < (f->coeffs + tlen[f->length - 1])->length); fq_nmod_mul(b + j, W + l*i + j, Msol->rows[j] + 0, ctx->fqctx); } success = fq_nmod_vandsolve((G->coeffs + i)->coeffs, (fevalsk1->coeffs + i)->coeffs, b, (f->coeffs + i)->length, ctx->fqctx); if (!success) { /* evaluation points produced a singular vandermonde matrix */ goto pick_evaluation_point; } } /* check solution */ for (s = 0; s < f->length; s++) { fq_nmod_t acc, pp, u; fq_nmod_init(acc, ctx->fqctx); fq_nmod_init(pp, ctx->fqctx); fq_nmod_init(u, ctx->fqctx); for (i = 0; i < l; i++) { fq_nmod_zero(acc, ctx->fqctx); for (j = 0; j < (f->coeffs + s)->length; j++) { n_fq_get_fq_nmod(u, (G->coeffs + s)->coeffs + d*j, ctx->fqctx); fq_nmod_mul(pp, (M + s)->rows[i] + j, u, ctx->fqctx); fq_nmod_add(acc, acc, pp, ctx->fqctx); } fq_nmod_mul(u, W + l*s + i, Msol->rows[i] + 0, ctx->fqctx); if (!fq_nmod_equal(acc, u, ctx->fqctx)) { fq_nmod_clear(acc, ctx->fqctx); fq_nmod_clear(pp, ctx->fqctx); fq_nmod_clear(u, ctx->fqctx); success = nmod_gcds_no_solution; goto finished; } } fq_nmod_clear(acc, ctx->fqctx); fq_nmod_clear(pp, ctx->fqctx); fq_nmod_clear(u, ctx->fqctx); } success = nmod_gcds_success; finished: for (i = 0; i < entries; i++) fq_nmod_clear(powers + i, ctx->fqctx); for (i = 0; i < var; i++) fq_nmod_clear(alpha + i, ctx->fqctx); for (i = 0; i < (f->coeffs + tlen[f->length - 1])->length; i++) fq_nmod_clear(b + i, ctx->fqctx); for (i = 0; i < l*f->length; i++) fq_nmod_clear(W + i, ctx->fqctx); flint_free(W); fq_nmod_mat_clear(MF, ctx->fqctx); fq_nmod_mat_clear(Msol, ctx->fqctx); for (i = 0; i < f->length; i++) { fq_nmod_mat_clear(M + i, ctx->fqctx); if (ML_is_initialized[i]) { fq_nmod_mat_clear(ML + i, ctx->fqctx); } } fq_nmod_clear(ck, ctx->fqctx); fq_nmod_mpolyu_clear(Aevalsk1, ctx); fq_nmod_mpolyu_clear(Bevalsk1, ctx); fq_nmod_mpolyu_clear(fevalsk1, ctx); fq_nmod_mpolyu_clear(Aevalski, ctx); fq_nmod_mpolyu_clear(Bevalski, ctx); fq_nmod_mpolyu_clear(fevalski, ctx); fq_nmod_poly_clear(Aeval, ctx->fqctx); fq_nmod_poly_clear(Beval, ctx->fqctx); fq_nmod_poly_clear(Geval, ctx->fqctx); TMP_END; return success; } /* setform copies the exponents and zeros the coefficients */ void fq_nmod_mpoly_setform_mpolyn( fq_nmod_mpoly_t A, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i; slong N; FLINT_ASSERT(A->bits == B->bits); fq_nmod_mpoly_fit_length(A, B->length, ctx); N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < B->length; i++) { _n_fq_zero(A->coeffs + d*i, d); mpoly_monomial_set(A->exps + N*i, B->exps + N*i, N); } A->length = B->length; } void fq_nmod_mpolyu_setform_mpolyun(fq_nmod_mpolyu_t A, fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; fq_nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { FLINT_ASSERT((B->coeffs + i)->bits == B->bits); fq_nmod_mpoly_setform_mpolyn(A->coeffs + i, B->coeffs + i, ctx); A->exps[i] = B->exps[i]; } A->length = B->length; } int fq_nmod_mpolyu_gcdp_zippel_univar( fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_poly_t a, b, g, t, r; FLINT_ASSERT(A->bits == B->bits); fq_nmod_poly_init(a, ctx->fqctx); fq_nmod_poly_init(b, ctx->fqctx); fq_nmod_poly_init(g, ctx->fqctx); fq_nmod_poly_init(t, ctx->fqctx); fq_nmod_poly_init(r, ctx->fqctx); fq_nmod_mpolyu_cvtto_poly(a, A, ctx); fq_nmod_mpolyu_cvtto_poly(b, B, ctx); fq_nmod_poly_gcd(g, a, b, ctx->fqctx); fq_nmod_mpolyu_cvtfrom_poly(G, g, ctx); fq_nmod_poly_divrem(t, r, a, g, ctx->fqctx); fq_nmod_mpolyu_cvtfrom_poly(Abar, t, ctx); fq_nmod_poly_divrem(t, r, b, g, ctx->fqctx); fq_nmod_mpolyu_cvtfrom_poly(Bbar, t, ctx); fq_nmod_poly_clear(a, ctx->fqctx); fq_nmod_poly_clear(b, ctx->fqctx); fq_nmod_poly_clear(g, ctx->fqctx); fq_nmod_poly_clear(t, ctx->fqctx); fq_nmod_poly_clear(r, ctx->fqctx); return 1; } int fq_nmod_mpolyu_gcdp_zippel_univar_no_cofactors( fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_poly_t a, b, g; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(A,ctx)); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(B,ctx)); fq_nmod_poly_init(a, ctx->fqctx); fq_nmod_poly_init(b, ctx->fqctx); fq_nmod_poly_init(g, ctx->fqctx); fq_nmod_mpolyu_cvtto_poly(a, A, ctx); fq_nmod_mpolyu_cvtto_poly(b, B, ctx); fq_nmod_poly_gcd(g, a, b, ctx->fqctx); fq_nmod_mpolyu_cvtfrom_poly(G, g, ctx); fq_nmod_poly_clear(a, ctx->fqctx); fq_nmod_poly_clear(b, ctx->fqctx); fq_nmod_poly_clear(g, ctx->fqctx); return 1; } int fq_nmod_mpolyu_gcdp_zippel_bivar( fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { slong var = 0; slong Alastdeg; slong Blastdeg; ulong Ashift, Bshift, Gshift; slong lastdeg; slong bound; int success = 0, changed, have_enough; fq_nmod_poly_t a, b, c, g, modulus, tempmod, tmp1, tmp2; fq_nmod_mpolyu_t Aeval, Beval, Geval; fq_nmod_mpolyun_t An, Bn, H, Ht; fq_nmod_t geval, temp, alpha, alphastart; fmpz_t minusone; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(var >= -WORD(1)); FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(G->bits == B->bits); fmpz_init(minusone); fmpz_set_si(minusone, -WORD(1)); fq_nmod_mpolyun_init(An, A->bits, ctx); fq_nmod_mpolyun_init(Bn, A->bits, ctx); fq_nmod_mpolyu_cvtto_mpolyun(An, A, var, ctx); fq_nmod_mpolyu_cvtto_mpolyun(Bn, B, var, ctx); FLINT_ASSERT(An->length > 0); FLINT_ASSERT(Bn->length > 0); Ashift = A->exps[A->length - 1]; Bshift = B->exps[B->length - 1]; Gshift = FLINT_MIN(Ashift, Bshift); fq_nmod_mpolyun_shift_right(An, Ashift); fq_nmod_mpolyun_shift_right(Bn, Bshift); fq_nmod_poly_init(a, ctx->fqctx); fq_nmod_poly_init(b, ctx->fqctx); fq_nmod_poly_init(c, ctx->fqctx); fq_nmod_poly_init(g, ctx->fqctx); fq_nmod_poly_init(tmp1, ctx->fqctx); fq_nmod_poly_init(tmp2, ctx->fqctx); /* if the gcd has content wrt last variable, we are going to fail */ fq_nmod_mpolyun_content_poly(a, An, ctx); fq_nmod_mpolyun_content_poly(b, Bn, ctx); fq_nmod_mpolyun_divexact_poly(An, An, a, ctx); fq_nmod_mpolyun_divexact_poly(Bn, Bn, b, ctx); fq_nmod_poly_gcd(c, a, b, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp1, fq_nmod_mpolyun_leadcoeff_poly(An, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp2, fq_nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->fqctx); fq_nmod_poly_gcd(g, tmp1, tmp2, ctx->fqctx); Alastdeg = fq_nmod_mpolyun_lastdeg(An, ctx); Blastdeg = fq_nmod_mpolyun_lastdeg(Bn, ctx); /* bound of the number of images required */ bound = 1 + FLINT_MIN(Alastdeg, Blastdeg) + fq_nmod_poly_degree(g, ctx->fqctx); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_poly_init(tempmod, ctx->fqctx); fq_nmod_poly_set_coeff_fmpz(tempmod, 1, minusone, ctx->fqctx); fq_nmod_mpolyu_init(Aeval, A->bits, ctx); fq_nmod_mpolyu_init(Beval, A->bits, ctx); fq_nmod_mpolyu_init(Geval, A->bits, ctx); fq_nmod_mpolyun_init(H, A->bits, ctx); fq_nmod_mpolyun_init(Ht, A->bits, ctx); fq_nmod_init(temp, ctx->fqctx); fq_nmod_init(geval, ctx->fqctx); fq_nmod_init(alpha, ctx->fqctx); fq_nmod_init(alphastart, ctx->fqctx); /* fail if the gcd has content wrt last variable */ if (fq_nmod_poly_degree(c, ctx->fqctx) > 0) { success = 0; goto finished; } fq_nmod_poly_one(modulus, ctx->fqctx); fq_nmod_mpolyun_zero(H, ctx); fq_nmod_randtest_not_zero(alphastart, randstate, ctx->fqctx); fq_nmod_set(alpha, alphastart, ctx->fqctx); while (1) { /* get new evaluation point */ fq_nmod_next_not_zero(alpha, ctx->fqctx); if (fq_nmod_equal(alpha, alphastart, ctx->fqctx)) { success = 0; goto finished; } /* make sure evaluation point does not kill both lc(A) and lc(B) */ fq_nmod_poly_evaluate_fq_nmod(geval, g, alpha, ctx->fqctx); if (fq_nmod_is_zero(geval, ctx->fqctx)) goto outer_continue; /* make sure evaluation point does not kill either A or B */ fq_nmod_mpolyun_interp_reduce_sm_mpolyu(Aeval, An, alpha, ctx); fq_nmod_mpolyun_interp_reduce_sm_mpolyu(Beval, Bn, alpha, ctx); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Aeval, ctx)); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Beval, ctx)); if (Aeval->length == 0 || Beval->length == 0) goto outer_continue; fq_nmod_mpolyu_gcdp_zippel_univar_no_cofactors(Geval, Aeval, Beval, ctx); if (fq_nmod_mpolyu_is_one(Geval, ctx)) { fq_nmod_mpolyu_one(G, ctx); fq_nmod_mpolyu_swap(Abar, A, ctx); fq_nmod_mpolyu_swap(Bbar, B, ctx); fq_nmod_mpolyu_shift_left(G, Gshift); fq_nmod_mpolyu_shift_left(Abar, Ashift - Gshift); fq_nmod_mpolyu_shift_left(Bbar, Bshift - Gshift); success = 1; goto finished; } FLINT_ASSERT(Geval->length > 0); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { if (Geval->exps[0] > H->exps[0]) { goto outer_continue; } else if (Geval->exps[0] < H->exps[0]) { fq_nmod_poly_one(modulus, ctx->fqctx); } } /* update interpolant H */ n_fq_get_fq_nmod(temp, fq_nmod_mpolyu_leadcoeff(Geval, ctx), ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_mul(temp, geval, temp, ctx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Geval, temp, ctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { fq_nmod_poly_evaluate_fq_nmod(temp, modulus, alpha, ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_poly_scalar_mul_fq_nmod(modulus, modulus, temp, ctx->fqctx); changed = fq_nmod_mpolyun_interp_crt_sm_mpolyu(&lastdeg, H, Ht, Geval, modulus, alpha, ctx); fq_nmod_poly_set_coeff(tempmod, 0, alpha, ctx->fqctx); fq_nmod_poly_mul(modulus, modulus, tempmod, ctx->fqctx); have_enough = fq_nmod_poly_degree(modulus, ctx->fqctx) >= bound; if (changed && !have_enough) { goto outer_continue; } if (!changed || have_enough) { fq_nmod_mpolyun_content_poly(a, H, ctx); fq_nmod_mpolyun_divexact_poly(Ht, H, a, ctx); fq_nmod_mpolyun_shift_left(Ht, Gshift); fq_nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( fq_nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && fq_nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { fq_nmod_poly_one(modulus, ctx->fqctx); goto outer_continue; } } else { fq_nmod_mpolyun_interp_lift_sm_mpolyu(H, Geval, ctx); lastdeg = WORD(0); fq_nmod_poly_set_coeff(tempmod, 0, alpha, ctx->fqctx); fq_nmod_poly_mul(modulus, modulus, tempmod, ctx->fqctx); } outer_continue:; } success = 0; finished: fmpz_clear(minusone); fq_nmod_clear(temp, ctx->fqctx); fq_nmod_clear(geval, ctx->fqctx); fq_nmod_clear(alpha, ctx->fqctx); fq_nmod_clear(alphastart, ctx->fqctx); fq_nmod_poly_clear(a, ctx->fqctx); fq_nmod_poly_clear(b, ctx->fqctx); fq_nmod_poly_clear(c, ctx->fqctx); fq_nmod_poly_clear(g, ctx->fqctx); fq_nmod_poly_clear(tmp1, ctx->fqctx); fq_nmod_poly_clear(tmp2, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_poly_clear(tempmod, ctx->fqctx); fq_nmod_mpolyu_clear(Aeval, ctx); fq_nmod_mpolyu_clear(Beval, ctx); fq_nmod_mpolyu_clear(Geval, ctx); fq_nmod_mpolyun_clear(An, ctx); fq_nmod_mpolyun_clear(Bn, ctx); fq_nmod_mpolyun_clear(H, ctx); fq_nmod_mpolyun_clear(Ht, ctx); return success; } int fq_nmod_mpolyu_gcdp_zippel( fq_nmod_mpolyu_t G, fq_nmod_mpolyu_t Abar, fq_nmod_mpolyu_t Bbar, fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, slong var, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { slong lastdeg; slong Alastdeg; slong Blastdeg; ulong Ashift, Bshift, Gshift; slong degbound; slong bound; int success = 0, changed, have_enough; fq_nmod_mpolyun_t An, Bn; fq_nmod_poly_t a, b, c, g, tmp1, tmp2; fq_nmod_poly_t modulus, tempmod; fq_nmod_mpolyu_t Aeval, Beval, Geval, Abareval, Bbareval, Gform; fq_nmod_mpolyun_t H, Ht; fq_nmod_t geval, temp; fq_nmod_t alpha, alphastart; fmpz_t minusone; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(var >= -WORD(1)); FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(G->bits == B->bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(A,ctx)); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(B,ctx)); if (var == -WORD(1)) { /* no more variables left to interpolate */ return fq_nmod_mpolyu_gcdp_zippel_univar(G, Abar, Bbar, A, B, ctx); } if (var == WORD(0)) { /* bivariate is more comfortable separated */ return fq_nmod_mpolyu_gcdp_zippel_bivar(G, Abar, Bbar, A, B, ctx, randstate); } fq_nmod_mpolyun_init(An, A->bits, ctx); fq_nmod_mpolyun_init(Bn, A->bits, ctx); fq_nmod_mpolyu_cvtto_mpolyun(An, A, var, ctx); fq_nmod_mpolyu_cvtto_mpolyun(Bn, B, var, ctx); Ashift = A->exps[A->length - 1]; Bshift = B->exps[B->length - 1]; Gshift = FLINT_MIN(Ashift, Bshift); fq_nmod_mpolyun_shift_right(An, Ashift); fq_nmod_mpolyun_shift_right(Bn, Bshift); fq_nmod_poly_init(a, ctx->fqctx); fq_nmod_poly_init(b, ctx->fqctx); fq_nmod_poly_init(c, ctx->fqctx); fq_nmod_poly_init(g, ctx->fqctx); fq_nmod_poly_init(tmp1, ctx->fqctx); fq_nmod_poly_init(tmp2, ctx->fqctx); /* if the gcd has content wrt last variable, we are going to fail */ fq_nmod_mpolyun_content_poly(a, An, ctx); fq_nmod_mpolyun_content_poly(b, Bn, ctx); fq_nmod_mpolyun_divexact_poly(An, An, a, ctx); fq_nmod_mpolyun_divexact_poly(Bn, Bn, b, ctx); fq_nmod_poly_gcd(c, a, b, ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp1, fq_nmod_mpolyun_leadcoeff_poly(An, ctx), ctx->fqctx); n_fq_poly_get_fq_nmod_poly(tmp2, fq_nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->fqctx); fq_nmod_poly_gcd(g, tmp1, tmp2, ctx->fqctx); Alastdeg = fq_nmod_mpolyun_lastdeg(An, ctx); Blastdeg = fq_nmod_mpolyun_lastdeg(Bn, ctx); /* bound of the number of images required */ bound = 1 + FLINT_MIN(Alastdeg, Blastdeg) + fq_nmod_poly_degree(g, ctx->fqctx); /* degree bound on the gcd */ degbound = FLINT_MIN(A->exps[0], B->exps[0]); fq_nmod_poly_init(modulus, ctx->fqctx); fq_nmod_poly_init(tempmod, ctx->fqctx); fmpz_init(minusone); fmpz_set_si(minusone, WORD(-1)); fq_nmod_poly_set_coeff_fmpz(tempmod, 1, minusone, ctx->fqctx); fq_nmod_mpolyu_init(Aeval, A->bits, ctx); fq_nmod_mpolyu_init(Beval, A->bits, ctx); fq_nmod_mpolyu_init(Geval, A->bits, ctx); fq_nmod_mpolyu_init(Abareval, A->bits, ctx); fq_nmod_mpolyu_init(Bbareval, A->bits, ctx); fq_nmod_mpolyu_init(Gform, A->bits, ctx); fq_nmod_mpolyun_init(H, A->bits, ctx); fq_nmod_mpolyun_init(Ht, A->bits, ctx); fq_nmod_init(geval, ctx->fqctx); fq_nmod_init(temp, ctx->fqctx); fq_nmod_init(alpha, ctx->fqctx); fq_nmod_init(alphastart, ctx->fqctx); /* fail if the gcd has content wrt last variable */ if (fq_nmod_poly_degree(c, ctx->fqctx) > 0) { success = 0; goto finished; } /* we don't expect this function to work over F_p */ if (nmod_poly_degree(ctx->fqctx->modulus) < WORD(2)) { success = 0; goto finished; } fq_nmod_poly_one(modulus, ctx->fqctx); fq_nmod_mpolyun_zero(H, ctx); fq_nmod_randtest_not_zero(alphastart, randstate, ctx->fqctx); fq_nmod_set(alpha, alphastart, ctx->fqctx); while (1) { /* get new evaluation point */ fq_nmod_next_not_zero(alpha, ctx->fqctx); if (fq_nmod_equal(alpha, alphastart, ctx->fqctx)) { success = 0; goto finished; } /* make sure evaluation point does not kill both lc(A) and lc(B) */ fq_nmod_poly_evaluate_fq_nmod(geval, g, alpha, ctx->fqctx); if (fq_nmod_is_zero(geval, ctx->fqctx)) { goto outer_continue; } /* make sure evaluation point does not kill either A or B */ fq_nmod_mpolyun_interp_reduce_sm_mpolyu(Aeval, An, alpha, ctx); fq_nmod_mpolyun_interp_reduce_sm_mpolyu(Beval, Bn, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) { goto outer_continue; } success = fq_nmod_mpolyu_gcdp_zippel(Geval, Abareval, Bbareval, Aeval, Beval, var - 1, ctx, randstate); if (!success || Geval->exps[0] > degbound) { success = 0; goto finished; } degbound = Geval->exps[0]; if (fq_nmod_mpolyu_is_one(Geval, ctx)) { fq_nmod_mpolyu_one(G, ctx); fq_nmod_mpolyu_swap(Abar, A, ctx); fq_nmod_mpolyu_swap(Bbar, B, ctx); fq_nmod_mpolyu_shift_left(G, Gshift); fq_nmod_mpolyu_shift_left(Abar, Ashift - Gshift); fq_nmod_mpolyu_shift_left(Bbar, Bshift - Gshift); success = 1; goto finished; } if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { if (Geval->exps[0] > H->exps[0]) { goto outer_continue; } else if (Geval->exps[0] < H->exps[0]) { fq_nmod_poly_one(modulus, ctx->fqctx); } } /* update interpolant H */ n_fq_get_fq_nmod(temp, fq_nmod_mpolyu_leadcoeff(Geval, ctx), ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_mul(temp, geval, temp, ctx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Geval, temp, ctx); if (fq_nmod_poly_degree(modulus, ctx->fqctx) > 0) { fq_nmod_poly_evaluate_fq_nmod(temp, modulus, alpha, ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_poly_scalar_mul_fq_nmod(modulus, modulus, temp, ctx->fqctx); changed = fq_nmod_mpolyun_interp_crt_sm_mpolyu(&lastdeg, H, Ht, Geval, modulus, alpha, ctx); if (!changed) { fq_nmod_mpolyun_content_poly(a, H, ctx); fq_nmod_mpolyun_divexact_poly(Ht, H, a, ctx); fq_nmod_mpolyun_shift_left(Ht, Gshift); fq_nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( !fq_nmod_mpolyuu_divides(Abar, A, G, 1, ctx) || !fq_nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { goto outer_continue; } success = 1; goto finished; } } else { fq_nmod_mpolyun_interp_lift_sm_mpolyu(H, Geval, ctx); } fq_nmod_poly_set_coeff(tempmod, 0, alpha, ctx->fqctx); fq_nmod_poly_mul(modulus, modulus, tempmod, ctx->fqctx); fq_nmod_mpolyu_setform_mpolyun(Gform, H, ctx); while (1) { /* get new evaluation point */ fq_nmod_next_not_zero(alpha, ctx->fqctx); if (fq_nmod_equal(alpha, alphastart, ctx->fqctx)) { success = 0; goto finished; } /* make sure evaluation point does not kill both lc(A) and lc(B) */ fq_nmod_poly_evaluate_fq_nmod(geval, g, alpha, ctx->fqctx); if (fq_nmod_is_zero(geval, ctx->fqctx)) { goto inner_continue; } /* make sure evaluation point does not kill either A or B */ fq_nmod_mpolyun_interp_reduce_sm_mpolyu(Aeval, An, alpha, ctx); fq_nmod_mpolyun_interp_reduce_sm_mpolyu(Beval, Bn, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) { goto inner_continue; } switch (fq_nmod_mpolyu_gcds_zippel(Geval, Aeval, Beval, Gform, var, ctx, randstate, °bound)) { default: FLINT_ASSERT(0); case nmod_gcds_form_main_degree_too_high: /* fq_nmod_mpolyu_gcds_zippel has updated degbound */ fq_nmod_poly_one(modulus, ctx->fqctx); goto outer_continue; case nmod_gcds_form_wrong: case nmod_gcds_no_solution: success = 0; goto finished; case nmod_gcds_scales_not_found: case nmod_gcds_eval_point_not_found: case nmod_gcds_eval_gcd_deg_too_high: goto inner_continue; case nmod_gcds_success: (void)(NULL); } n_fq_get_fq_nmod(temp, fq_nmod_mpolyu_leadcoeff(Geval, ctx), ctx->fqctx); if (fq_nmod_is_zero(temp, ctx->fqctx)) { goto inner_continue; } /* update interpolant H */ FLINT_ASSERT(fq_nmod_poly_degree(modulus, ctx->fqctx) > 0); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_mul(temp, temp, geval, ctx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Geval, temp, ctx); fq_nmod_poly_evaluate_fq_nmod(temp, modulus, alpha, ctx->fqctx); fq_nmod_inv(temp, temp, ctx->fqctx); fq_nmod_poly_scalar_mul_fq_nmod(modulus, modulus, temp, ctx->fqctx); changed = fq_nmod_mpolyun_interp_crt_sm_mpolyu(&lastdeg, H, Ht, Geval, modulus, alpha, ctx); fq_nmod_poly_set_coeff(tempmod, 0, alpha, ctx->fqctx); fq_nmod_poly_mul(modulus, modulus, tempmod, ctx->fqctx); have_enough = fq_nmod_poly_degree(modulus, ctx->fqctx) >= bound; if (changed && !have_enough) { goto inner_continue; } if (!changed || have_enough) { fq_nmod_mpolyun_content_poly(a, H, ctx); fq_nmod_mpolyun_divexact_poly(Ht, H, a, ctx); fq_nmod_mpolyun_shift_left(Ht, Gshift); fq_nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( fq_nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && fq_nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { fq_nmod_poly_one(modulus, ctx->fqctx); goto outer_continue; } inner_continue:; } FLINT_ASSERT(0 && "not reachable"); outer_continue:; } FLINT_ASSERT(0 && "not reachable"); finished: fmpz_clear(minusone); fq_nmod_clear(geval, ctx->fqctx); fq_nmod_clear(temp, ctx->fqctx); fq_nmod_clear(alpha, ctx->fqctx); fq_nmod_clear(alphastart, ctx->fqctx); fq_nmod_poly_clear(a, ctx->fqctx); fq_nmod_poly_clear(b, ctx->fqctx); fq_nmod_poly_clear(c, ctx->fqctx); fq_nmod_poly_clear(g, ctx->fqctx); fq_nmod_poly_clear(tmp1, ctx->fqctx); fq_nmod_poly_clear(tmp2, ctx->fqctx); fq_nmod_poly_clear(modulus, ctx->fqctx); fq_nmod_poly_clear(tempmod, ctx->fqctx); fq_nmod_mpolyu_clear(Aeval, ctx); fq_nmod_mpolyu_clear(Beval, ctx); fq_nmod_mpolyu_clear(Geval, ctx); fq_nmod_mpolyu_clear(Abareval, ctx); fq_nmod_mpolyu_clear(Bbareval, ctx); fq_nmod_mpolyu_clear(Gform, ctx); fq_nmod_mpolyun_clear(An, ctx); fq_nmod_mpolyun_clear(Bn, ctx); fq_nmod_mpolyun_clear(H, ctx); fq_nmod_mpolyun_clear(Ht, ctx); return success; } flint-3.1.3/src/fq_nmod_mpoly/mpolyun.c000066400000000000000000000454071461254215100201460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpolyun_init( fq_nmod_mpolyun_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void fq_nmod_mpolyun_clear( fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fq_nmod_mpolyn_clear(A->coeffs + i, ctx); flint_free(A->coeffs); flint_free(A->exps); } int fq_nmod_mpolyun_is_canonical( const fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (A->length > A->alloc) { return 0; } for (i = 0; i < A->length; i++) { if (!fq_nmod_mpolyn_is_canonical(A->coeffs + i, ctx)) { return 0; } if (i > 0 && A->exps[i - 1] <= A->exps[i]) { return 0; } } return 1; } void fq_nmod_mpolyun_print_pretty( const fq_nmod_mpolyun_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (poly->length == 0) flint_printf("0"); for (i = 0; i < poly->length; i++) { if (i != 0) flint_printf(" + "); flint_printf("("); fq_nmod_mpolyn_print_pretty(poly->coeffs + i,x,ctx); flint_printf(")*X^%wd",poly->exps[i]); } } void fq_nmod_mpolyun_swap( fq_nmod_mpolyun_t A, fq_nmod_mpolyun_t B) { fq_nmod_mpolyun_struct t = *A; *A = *B; *B = t; } void fq_nmod_mpolyun_zero( fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx) { A->length = 0; } void fq_nmod_mpolyun_fit_length( fq_nmod_mpolyun_t A, slong length, const fq_nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (fq_nmod_mpolyn_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_nmod_mpolyn_struct)); for (i = old_alloc; i < new_alloc; i++) fq_nmod_mpolyn_init(A->coeffs + i, A->bits, ctx); A->alloc = new_alloc; } } void fq_nmod_mpolyun_one( fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpolyun_fit_length(A, 1, ctx); fq_nmod_mpolyn_one(A->coeffs + 0, ctx); A->exps[0] = 0; A->length = 1; } int fq_nmod_mpolyn_is_nonzero_fq_nmod( const fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { slong N; if (A->length != WORD(1)) return 0; if (n_fq_poly_degree(A->coeffs + 0) != 0) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } int fq_nmod_mpolyun_is_nonzero_fq_nmod( const fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx) { if (A->length != 1 || A->exps[0] != 0) return 0; return fq_nmod_mpolyn_is_nonzero_fq_nmod(A->coeffs + 0, ctx); } void fq_nmod_mpolyn_scalar_mul_fq_nmod( fq_nmod_mpolyn_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i; mp_limb_t * cc; FLINT_ASSERT(!fq_nmod_is_zero(c, ctx->fqctx)); if (fq_nmod_is_one(c, ctx->fqctx)) return; cc = FLINT_ARRAY_ALLOC(fq_nmod_ctx_degree(ctx->fqctx), mp_limb_t); n_fq_set_fq_nmod(cc, c, ctx->fqctx); for (i = 0; i < A->length; i++) { n_fq_poly_scalar_mul_n_fq(A->coeffs + i, A->coeffs + i, cc, ctx->fqctx); } flint_free(cc); } void fq_nmod_mpolyun_scalar_mul_fq_nmod( fq_nmod_mpolyun_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; mp_limb_t * cc; FLINT_ASSERT(!fq_nmod_is_zero(c, ctx->fqctx)); if (fq_nmod_is_one(c, ctx->fqctx)) return; cc = FLINT_ARRAY_ALLOC(fq_nmod_ctx_degree(ctx->fqctx), mp_limb_t); n_fq_set_fq_nmod(cc, c, ctx->fqctx); for (i = 0; i < A->length; i++) { fq_nmod_mpolyn_struct * Ai = A->coeffs + i; for (j = 0; j < Ai->length; j++) { n_fq_poly_scalar_mul_n_fq(Ai->coeffs + j, Ai->coeffs + j, cc, ctx->fqctx); } } flint_free(cc); } void fq_nmod_mpolyun_shift_right( fq_nmod_mpolyun_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { FLINT_ASSERT(A->exps[i] >= s); A->exps[i] -= s; } } void fq_nmod_mpolyun_shift_left( fq_nmod_mpolyun_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { A->exps[i] += s; FLINT_ASSERT(A->exps[i] >= s); } } void fq_nmod_mpolyn_mul_poly( fq_nmod_mpolyn_t A, const fq_nmod_mpolyn_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t t /* temp */) { slong i; n_fq_poly_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; slong Blen = B->length; slong N; n_fq_poly_t cc, tt; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx)); n_fq_poly_init(cc); n_fq_poly_init(tt); n_fq_poly_set_fq_nmod_poly(cc, c, ctx->fqctx); if (A == B) { Acoeff = A->coeffs; for (i = 0; i < Blen; i++) { n_fq_poly_mul(tt, Acoeff + i, cc, ctx->fqctx); n_fq_poly_swap(tt, Acoeff + i); } } else { fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); for (i = 0; i < Blen; i++) { n_fq_poly_mul(Acoeff + i, Bcoeff + i, cc, ctx->fqctx); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } A->length = Blen; } n_fq_poly_clear(cc); n_fq_poly_clear(tt); } void fq_nmod_mpolyun_mul_poly( fq_nmod_mpolyun_t A, const fq_nmod_mpolyun_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i, Blen; fq_nmod_mpolyn_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; fq_nmod_poly_t t; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx)); fq_nmod_poly_init(t, ctx->fqctx); Blen = B->length; fq_nmod_mpolyun_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; for (i = 0; i < Blen; i++) { fq_nmod_mpolyn_mul_poly(Acoeff + i, Bcoeff + i, c, ctx, t); Aexp[i] = Bexp[i]; } A->length = Blen; fq_nmod_poly_clear(t, ctx->fqctx); } void fq_nmod_mpolyn_divexact_poly( fq_nmod_mpolyn_t A, const fq_nmod_mpolyn_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_poly_t q, /* temp */ fq_nmod_poly_t r /* temp */) { slong i; n_fq_poly_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; slong Blen = B->length; slong N; n_fq_poly_t cc, qq, rr; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx)); n_fq_poly_init(cc); n_fq_poly_init(qq); n_fq_poly_init(rr); n_fq_poly_set_fq_nmod_poly(cc, c, ctx->fqctx); if (A == B) { Acoeff = A->coeffs; for (i = 0; i < Blen; i++) { n_fq_poly_divrem(qq, rr, Acoeff + i, cc, ctx->fqctx); FLINT_ASSERT(n_fq_poly_is_zero(rr)); n_fq_poly_swap(qq, Acoeff + i); } } else { fq_nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); for (i = 0; i < Blen; i++) { n_fq_poly_divrem(Acoeff + i, rr, Bcoeff + i, cc, ctx->fqctx); FLINT_ASSERT(n_fq_poly_is_zero(rr)); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } A->length = Blen; } n_fq_poly_clear(cc); n_fq_poly_clear(qq); n_fq_poly_clear(rr); } void fq_nmod_mpolyun_divexact_poly( fq_nmod_mpolyun_t A, const fq_nmod_mpolyun_t B, const fq_nmod_poly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i, Blen; fq_nmod_mpolyn_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; fq_nmod_poly_t q, r; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx)); fq_nmod_poly_init(q, ctx->fqctx); fq_nmod_poly_init(r, ctx->fqctx); Blen = B->length; fq_nmod_mpolyun_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; for (i = 0; i < Blen; i++) { fq_nmod_mpolyn_divexact_poly(Acoeff + i, Bcoeff + i, c, ctx, q, r); Aexp[i] = Bexp[i]; } A->length = Blen; fq_nmod_poly_clear(q, ctx->fqctx); fq_nmod_poly_clear(r, ctx->fqctx); } void fq_nmod_mpolyn_content_poly( fq_nmod_poly_t g, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; n_fq_poly_t gg, tt; n_fq_poly_init(gg); n_fq_poly_init(tt); for (i = 0; i < B->length; i++) { n_fq_poly_gcd(tt, gg, B->coeffs + i, ctx->fqctx); n_fq_poly_swap(tt, gg); if (n_fq_poly_degree(gg) == 0) break; } n_fq_poly_get_fq_nmod_poly(g, gg, ctx->fqctx); n_fq_poly_clear(gg); n_fq_poly_clear(tt); } void fq_nmod_mpolyun_content_poly( fq_nmod_poly_t g, fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; n_fq_poly_t gg, tt; n_fq_poly_init(gg); n_fq_poly_init(tt); for (i = 0; i < B->length; i++) { for (j = 0; j < B->coeffs[i].length; j++) { n_fq_poly_gcd(tt, gg, B->coeffs[i].coeffs + j, ctx->fqctx); n_fq_poly_swap(tt, gg); if (n_fq_poly_degree(gg) == 0) break; } } n_fq_poly_get_fq_nmod_poly(g, gg, ctx->fqctx); n_fq_poly_clear(gg); n_fq_poly_clear(tt); } void fq_nmod_mpoly_to_mpolyn_perm_deflate( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t nctx, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong j, k, l; slong NA = mpoly_words_per_exp_sp(A->bits, nctx->minfo); slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong n = ctx->minfo->nvars; slong m = nctx->minfo->nvars; ulong * Bexps; slong * offs, * shifts; fq_nmod_mpoly_t T; TMP_INIT; FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); offs = (slong *) TMP_ALLOC(m*sizeof(slong)); shifts = (slong *) TMP_ALLOC(m*sizeof(slong)); for (k = 0; k < m; k++) { mpoly_gen_offset_shift_sp(offs + k, shifts + k, k, A->bits, nctx->minfo); } fq_nmod_mpoly_init3(T, B->length, A->bits, nctx); T->length = B->length; for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); _n_fq_set(T->coeffs + d*j, B->coeffs + d*j, d); mpoly_monomial_zero(T->exps + NA*j, NA); for (k = 0; k < m; k++) { l = perm[k]; (T->exps + NA*j)[offs[k]] += ((Bexps[l] - shift[l]) / stride[l]) << shifts[k]; } } fq_nmod_mpoly_sort_terms(T, nctx); fq_nmod_mpoly_cvtto_mpolyn(A, T, nctx->minfo->nvars - 1, nctx); fq_nmod_mpoly_clear(T, nctx); TMP_END; } void fq_nmod_mpoly_from_mpolyn_perm_inflate( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t nctx, const slong * perm, const ulong * shift, const ulong * stride) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong n = ctx->minfo->nvars; slong m = nctx->minfo->nvars; slong i, h, k, l; slong NA, NB; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * Bexps; ulong * Aexps, * tAexp, * tAgexp; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, nctx->minfo); tAexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); tAgexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); mpoly_gen_monomial_sp(tAgexp, perm[m - 1], Abits, ctx->minfo); for (i = 0; i < NA; i++) tAgexp[i] *= stride[perm[m - 1]]; fq_nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, nctx->minfo); FLINT_ASSERT(Bexps[m - 1] == 0); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m; k++) { l = perm[k]; Aexps[l] += stride[l]*Bexps[k]; } mpoly_set_monomial_ui(tAexp, Aexps, Abits, ctx->minfo); h = (B->coeffs + i)->length; _fq_nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, d, &Aexp, &A->exps_alloc, NA, Alen + h); for (h--; h >= 0; h--) { if (_n_fq_is_zero(B->coeffs[i].coeffs + d*h, d)) continue; _n_fq_set(Acoeff + d*Alen, B->coeffs[i].coeffs + d*h, d); mpoly_monomial_madd(Aexp + NA*Alen, tAexp, h, tAgexp, NA); Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; fq_nmod_mpoly_sort_terms(A, ctx); TMP_END; } slong fq_nmod_mpolyn_lastdeg( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; slong deg = -WORD(1); for (i = 0; i < A->length; i++) deg = FLINT_MAX(deg, n_fq_poly_degree(A->coeffs + i)); return deg; } slong fq_nmod_mpolyun_lastdeg( fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; slong deg = -WORD(1); for (i = 0; i < A->length; i++) { fq_nmod_mpolyn_struct * Ai = A->coeffs + i; for (j = 0; j < Ai->length; j++) deg = FLINT_MAX(deg, n_fq_poly_degree(Ai->coeffs + j)); } return deg; } void fq_nmod_mpolyun_set( fq_nmod_mpolyun_t A, const fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i, Blen; fq_nmod_mpolyn_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; Blen = B->length; fq_nmod_mpolyun_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; for (i = 0; i < Blen; i++) { fq_nmod_mpolyn_set(Acoeff + i, Bcoeff + i, ctx); FLINT_ASSERT((Acoeff + i)->bits == B->bits); Aexp[i] = Bexp[i]; } A->length = Blen; } /* take the last variable of B out */ void fq_nmod_mpoly_cvtto_mpolyn( fq_nmod_mpolyn_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i; slong k; ulong * oneexp; slong offset; slong shift; ulong mask; slong N; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(A->bits == B->bits); TMP_START; N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, B->bits, ctx->minfo); /* fq_nmod_mpolyn_fit_bits(A, B->bits, ctx); A->bits = B->bits; */ k = 0; for (i = 0; i < B->length; i++) { ulong c = (B->exps[N*i + offset] >> shift) & mask; fq_nmod_mpolyn_fit_length(A, k + 1, ctx); mpoly_monomial_msub(A->exps + N*k, B->exps + N*i, c, oneexp, N); if (k > 0 && mpoly_monomial_equal(A->exps + N*k, A->exps + N*(k - 1), N)) { n_fq_poly_set_coeff_n_fq(A->coeffs + k - 1, c, B->coeffs + d*i, ctx->fqctx); } else { n_fq_poly_zero(A->coeffs + k); n_fq_poly_set_coeff_n_fq(A->coeffs + k, c, B->coeffs + d*i, ctx->fqctx); k++; } } A->length = k; TMP_END; } void fq_nmod_mpolyu_cvtto_mpolyun( fq_nmod_mpolyun_t A, const fq_nmod_mpolyu_t B, slong k, const fq_nmod_mpoly_ctx_t ctx) { slong i, Blen = B->length; fq_nmod_mpolyun_fit_length(A, Blen, ctx); A->length = Blen; for (i = 0; i < Blen; i++) { fq_nmod_mpoly_cvtto_mpolyn(A->coeffs + i, B->coeffs + i, k, ctx); A->exps[i] = B->exps[i]; } } /* put the last variable of B back into A */ void fq_nmod_mpoly_cvtfrom_mpolyn( fq_nmod_mpoly_t A, fq_nmod_mpolyn_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j, k; slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); ulong * genexp; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_sp(genexp, var, B->bits, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); k = 0; for (i = 0; i < B->length; i++) { for (j = B->coeffs[i].length - 1; j >= 0; j--) { if (_n_fq_is_zero(B->coeffs[i].coeffs + d*j, d)) continue; _fq_nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, d, &A->exps, &A->exps_alloc, N, k + 1); _n_fq_set(A->coeffs + d*k, B->coeffs[i].coeffs + d*j, d); mpoly_monomial_madd(A->exps + N*k, B->exps + N*i, j, genexp, N); k++; } } A->length = k; TMP_END; } void fq_nmod_mpolyu_cvtfrom_mpolyun( fq_nmod_mpolyu_t A, fq_nmod_mpolyun_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong i; fq_nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { fq_nmod_mpoly_cvtfrom_mpolyn(A->coeffs + i, B->coeffs + i, var, ctx); A->exps[i] = B->exps[i]; } A->length = B->length; } flint-3.1.3/src/fq_nmod_mpoly/mul.c000066400000000000000000000011741461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_mul(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx) { /* nothing fancy for now */ fq_nmod_mpoly_mul_johnson(A, B, C, ctx); } flint-3.1.3/src/fq_nmod_mpoly/mul_johnson.c000066400000000000000000000355411461254215100207740ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void _fq_nmod_mpoly_mul_johnson1( fq_nmod_mpoly_t A, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, ulong maskhi, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; ulong exp; mp_limb_t * t; int lazy_size = _n_fq_dot_lazy_size(Blen, ctx); mp_limb_t * Acoeffs = A->coeffs; ulong * Aexps = A->exps; slong Acoeffs_alloc = A->coeffs_alloc; slong Aexps_alloc = A->exps_alloc; slong Alen; TMP_INIT; TMP_START; next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); t = (mp_limb_t *) TMP_ALLOC(6*d*sizeof(mp_limb_t)); for (i = 0; i < Blen; i++) hind[i] = 1; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Bexps[0] + Cexps[0], x); hind[0] = 2*1 + 0; Alen = 0; while (heap_len > 1) { exp = heap[1].exp; _fq_nmod_mpoly_fit_length(&Acoeffs, &Acoeffs_alloc, d, &Aexps, &Aexps_alloc, 1, Alen + 1); Aexps[Alen] = exp; _nmod_vec_zero(t, 6*d); switch (lazy_size) { case 1: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy1(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); _n_fq_reduce2_lazy1(t, d, ctx->mod); break; case 2: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy2(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); _n_fq_reduce2_lazy2(t, d, ctx->mod); break; case 3: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy3(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); _n_fq_reduce2_lazy3(t, d, ctx->mod); break; default: do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, ctx, t + 2*d); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); break; } _n_fq_reduce2(Acoeffs + d*Alen, t, ctx, t + 2*d); Alen += !_n_fq_is_zero(Acoeffs + d*Alen, d); while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ((i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Cexps[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if ((j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Cexps[x->j], x, &next_loc, &heap_len, maskhi); } } } A->coeffs = Acoeffs; A->exps = Aexps; A->coeffs_alloc = Acoeffs_alloc; A->exps_alloc = Aexps_alloc; A->length = Alen; TMP_END; } void _fq_nmod_mpoly_mul_johnson( fq_nmod_mpoly_t A, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; mp_limb_t * t; int lazy_size = _n_fq_dot_lazy_size(Blen, ctx); mp_limb_t * Acoeffs = A->coeffs; ulong * Aexps = A->exps; slong Alen; TMP_INIT; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); FLINT_ASSERT(A->bits == bits); if (N == 1) { _fq_nmod_mpoly_mul_johnson1(A, Bcoeffs, Bexps, Blen, Ccoeffs, Cexps, Clen, cmpmask[0], ctx); return; } TMP_START; next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); t = (mp_limb_t *) TMP_ALLOC(6*d*sizeof(mp_limb_t)); for (i = 0; i < Blen; i++) { exp_list[i] = exps + i*N; hind[i] = 1; } /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; if (bits <= FLINT_BITS) mpoly_monomial_add(heap[1].exp, Bexps + N*0, Cexps + N*0, N); else mpoly_monomial_add_mp(heap[1].exp, Bexps + N*0, Cexps + N*0, N); hind[0] = 2*1 + 0; Alen = 0; while (heap_len > 1) { exp = heap[1].exp; _fq_nmod_mpoly_fit_length(&Acoeffs, &A->coeffs_alloc, d, &Aexps, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexps + N*Alen, exp, N); _nmod_vec_zero(t, 6*d); switch (lazy_size) { case 1: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy1(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _n_fq_reduce2_lazy1(t, d, ctx->mod); break; case 2: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy2(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _n_fq_reduce2_lazy2(t, d, ctx->mod); break; case 3: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2_lazy3(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _n_fq_reduce2_lazy3(t, d, ctx->mod); break; default: do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; _n_fq_madd2(t, Bcoeffs + d*x->i, Ccoeffs + d*x->j, ctx, t + 2*d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); break; } _n_fq_reduce2(Acoeffs + d*Alen, t, ctx, t + 2*d); Alen += !_n_fq_is_zero(Acoeffs + d*Alen, d); while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ((i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexps + x->i*N, Cexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Cexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ((j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexps + x->i*N, Cexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Cexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } A->coeffs = Acoeffs; A->exps = Aexps; A->length = Alen; TMP_END; } void fq_nmod_mpoly_mul_johnson( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t Abits; fmpz * Bmaxfields, * Cmaxfields; ulong * cmpmask; ulong * Bexps = B->exps, * Cexps = C->exps; int freeBexps = 0, freeCexps = 0; fq_nmod_mpoly_struct * P, T[1]; TMP_INIT; if (B->length < 1 || C->length < 1) { fq_nmod_mpoly_zero(A, ctx); return; } TMP_START; Bmaxfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); Cmaxfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(Bmaxfields + i); fmpz_init(Cmaxfields + i); } mpoly_max_fields_fmpz(Bmaxfields, Bexps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(Cmaxfields, Cexps, C->length, C->bits, ctx->minfo); _fmpz_vec_add(Bmaxfields, Bmaxfields, Cmaxfields, ctx->minfo->nfields); Abits = 1 + _fmpz_vec_max_bits(Bmaxfields, ctx->minfo->nfields); Abits = FLINT_MAX(Abits, B->bits); Abits = FLINT_MAX(Abits, C->bits); Abits = mpoly_fix_bits(Abits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(Bmaxfields + i); fmpz_clear(Cmaxfields + i); } N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); /* ensure input exponents are packed into same sized fields as output */ if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fq_nmod_mpoly_init(T, ctx); P = T; } else { P = A; } fq_nmod_mpoly_fit_length_reset_bits(P, B->length + C->length, Abits, ctx); if (B->length > C->length) { _fq_nmod_mpoly_mul_johnson(P, C->coeffs, Cexps, C->length, B->coeffs, Bexps, B->length, Abits, N, cmpmask, ctx->fqctx); } else { _fq_nmod_mpoly_mul_johnson(P, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, Abits, N, cmpmask, ctx->fqctx); } if (A == B || A == C) { fq_nmod_mpoly_swap(A, T, ctx); fq_nmod_mpoly_clear(T, ctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/neg.c000066400000000000000000000017541461254215100172110ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_neg( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(B->bits, ctx->minfo); if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); } _nmod_vec_neg(A->coeffs, B->coeffs, d*B->length, fq_nmod_ctx_mod(ctx->fqctx)); _fq_nmod_mpoly_set_length(A, B->length, ctx); } flint-3.1.3/src/fq_nmod_mpoly/one.c000066400000000000000000000014431461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_one(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); fq_nmod_mpoly_fit_length(A, 1, ctx); _n_fq_one(A->coeffs + d*0, d); mpoly_monomial_zero(A->exps, N); _fq_nmod_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/fq_nmod_mpoly/pow_fmpz.c000066400000000000000000000037241461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_pow_fmpz(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fmpz_t k, const fq_nmod_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields; flint_bitcnt_t exp_bits; TMP_INIT; if (fmpz_sgn(k) < 0) flint_throw(FLINT_ERROR, "fq_nmod_mpoly_pow_fmpz: power is negative"); if (fmpz_fits_si(k)) return fq_nmod_mpoly_pow_ui(A, B, fmpz_get_ui(k), ctx); /* we are raising a polynomial to an unreasonable exponent It must either be zero or a monomial with unit coefficient */ if (B->length == 0) { fq_nmod_mpoly_zero(A, ctx); return 1; } if (B->length != 1) return 0; TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_fmpz(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = 1 + _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, 1, exp_bits, ctx); n_fq_pow_fmpz(A->coeffs, B->coeffs, k, ctx->fqctx); mpoly_pack_vec_fmpz(A->exps, maxBfields, exp_bits, ctx->minfo->nfields, 1); _fq_nmod_mpoly_set_length(A, 1, ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/fq_nmod_mpoly/pow_rmul.c000066400000000000000000000017131461254215100202770ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_pow_rmul(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, ulong k, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctx); if (A == B) { fq_nmod_mpoly_pow_rmul(T, A, k, ctx); fq_nmod_mpoly_swap(T, A, ctx); goto cleanup; } fq_nmod_mpoly_set_ui(A, 1, ctx); while (k >= 1) { fq_nmod_mpoly_mul_johnson(T, A, B, ctx); fq_nmod_mpoly_swap(A, T, ctx); k -= 1; } cleanup: fq_nmod_mpoly_clear(T, ctx); } flint-3.1.3/src/fq_nmod_mpoly/pow_ui.c000066400000000000000000000036141461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_pow_ui( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, ulong k, const fq_nmod_mpoly_ctx_t ctx) { slong i, exp_bits; fmpz * maxBfields; TMP_INIT; if (k == 0) { fq_nmod_mpoly_one(A, ctx); return 1; } if (B->length == 0) { fq_nmod_mpoly_zero(A, ctx); return 1; } if (k == 1) { fq_nmod_mpoly_set(A, B, ctx); return 1; } if (k == 2) { fq_nmod_mpoly_mul(A, B, B, ctx); return 1; } if (B->length != 1) { fq_nmod_mpoly_pow_rmul(A, B, k, ctx); return 1; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_ui(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, 1, exp_bits, ctx); n_fq_pow_ui(A->coeffs, B->coeffs, k, ctx->fqctx); mpoly_pack_vec_fmpz(A->exps + 0, maxBfields, exp_bits, ctx->minfo->nfields, 1); _fq_nmod_mpoly_set_length(A, 1, ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/fq_nmod_mpoly/profile/000077500000000000000000000000001461254215100177255ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mpoly/profile/p-gcd.c000066400000000000000000000213541461254215100210700ustar00rootroot00000000000000/* Copyright 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" slong count = 0; slong total_super = 0; void profile_gcd( const fq_nmod_mpoly_t realG, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { fq_nmod_mpoly_t G; timeit_t timer; slong hensel = -1, brown = -1, zippel = -1, zippel2 = -1, super = -1; fq_nmod_mpoly_init(G, ctx); if (algo & MPOLY_GCD_USE_BROWN) { fq_nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); fq_nmod_mpoly_gcd_brown(G, A, B, ctx); timeit_stop(timer); brown = timer->wall; if (!fq_nmod_mpoly_equal(G, realG, ctx)) { flint_printf("brown is wrong\n"); flint_abort(); } } flint_printf("%10wd ", brown); fflush(stdout); if (algo & MPOLY_GCD_USE_HENSEL) { fq_nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); fq_nmod_mpoly_gcd_hensel(G, A, B, ctx); timeit_stop(timer); hensel = timer->wall; if (!fq_nmod_mpoly_equal(G, realG, ctx)) { flint_printf("hensel is wrong\n"); flint_abort(); } } flint_printf("%10wd ", hensel); fflush(stdout); if (algo & MPOLY_GCD_USE_ZIPPEL2) { fq_nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); fq_nmod_mpoly_gcd_zippel2(G, A, B, ctx); timeit_stop(timer); zippel2 = timer->wall; if (!fq_nmod_mpoly_equal(G, realG, ctx)) { flint_printf("zippel2 is wrong\n"); flint_abort(); } } flint_printf("%10wd ", zippel2); fflush(stdout); if (algo & MPOLY_GCD_USE_ZIPPEL) { fq_nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); fq_nmod_mpoly_gcd_zippel(G, A, B, ctx); timeit_stop(timer); zippel = timer->wall; if (!fq_nmod_mpoly_equal(G, realG, ctx)) { flint_printf("zippel is wrong\n"); flint_abort(); } } flint_printf("%10wd ", zippel); fflush(stdout); { fq_nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); fq_nmod_mpoly_gcd(G, A, B, ctx); timeit_stop(timer); super = timer->wall; if (!fq_nmod_mpoly_equal(G, realG, ctx)) { flint_printf("super is wrong\n"); flint_abort(); } } count++; flint_printf("%10wd #%wd\n", super, count); fflush(stdout); total_super += super; fq_nmod_mpoly_clear(G, ctx); } void print_banner(void) { flint_printf("| brown | hensel | zippel2 | zippel | super |\n"); flint_printf("+----------+----------+----------+----------+----------+\n"); } int main(int argc, char *argv[]) { slong i; const char * vars[] = {"x", "y", "z", "t" ,"u", "v", "w", "s", "p"}; mp_limb_t p = UWORD(4611686018427388073); print_banner(); for (i = 50; i < 100; i += 4) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, t, m; fq_nmod_mpoly_ctx_init_deg(ctx, 2, ORD_LEX, p, 2); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_mpoly_set_str_pretty(a, "1+#*x+y", vars, ctx); fq_nmod_mpoly_pow_ui(a, a, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "x", vars, ctx); fq_nmod_mpoly_add(a, a, m, ctx); fq_nmod_mpoly_set_str_pretty(b, "#-2*x-#*y", vars, ctx); fq_nmod_mpoly_pow_ui(b, b, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "y", vars, ctx); fq_nmod_mpoly_add(b, b, m, ctx); fq_nmod_mpoly_set_str_pretty(t, "2+#-x+y", vars, ctx); fq_nmod_mpoly_pow_ui(t, t, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "x-#*y", vars, ctx); fq_nmod_mpoly_add(t, t, m, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 3; i < 10; i += 1) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, t, m; fq_nmod_mpoly_ctx_init_deg(ctx, 2, ORD_LEX, p, 2); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_mpoly_set_str_pretty(a, "#-#*x^31+y^51", vars, ctx); fq_nmod_mpoly_pow_ui(a, a, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "x^7", vars, ctx); fq_nmod_mpoly_add(a, a, m, ctx); fq_nmod_mpoly_set_str_pretty(b, "1-2*#*x^23+#*y^47", vars, ctx); fq_nmod_mpoly_pow_ui(b, b, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "y^9", vars, ctx); fq_nmod_mpoly_add(b, b, m, ctx); fq_nmod_mpoly_set_str_pretty(t, "2*#-x^39+#^2*y^24", vars, ctx); fq_nmod_mpoly_pow_ui(t, t, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "x^6*y^7", vars, ctx); fq_nmod_mpoly_add(t, t, m, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 15; i < 25; i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, t, m; fq_nmod_mpoly_ctx_init_deg(ctx, 3, ORD_LEX, p, 2); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_mpoly_set_str_pretty(a, "#+x+#*y+z", vars, ctx); fq_nmod_mpoly_pow_ui(a, a, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "x", vars, ctx); fq_nmod_mpoly_add(a, a, m, ctx); fq_nmod_mpoly_set_str_pretty(b, "1-2*#^2*x-y+#*z", vars, ctx); fq_nmod_mpoly_pow_ui(b, b, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "y", vars, ctx); fq_nmod_mpoly_add(b, b, m, ctx); fq_nmod_mpoly_set_str_pretty(t, "3*#+x+#*y-2*z", vars, ctx); fq_nmod_mpoly_pow_ui(t, t, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "z", vars, ctx); fq_nmod_mpoly_add(t, t, m, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_ALL); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 1; i < 10; i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, t, m; fq_nmod_mpoly_ctx_init_deg(ctx, 7, ORD_LEX, p, 2); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_mpoly_set_str_pretty(a, "1+#*x+y+z+#*t+#*u+2*v+w", vars, ctx); fq_nmod_mpoly_pow_ui(a, a, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "x", vars, ctx); fq_nmod_mpoly_add(a, a, m, ctx); fq_nmod_mpoly_set_str_pretty(b, "1+x+#*y+z+#*t+u+3*v+#*w", vars, ctx); fq_nmod_mpoly_pow_ui(b, b, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "y", vars, ctx); fq_nmod_mpoly_add(b, b, m, ctx); fq_nmod_mpoly_set_str_pretty(t, "1+#*x+y+#*z+#*t+u+4*#*v+#*w", vars, ctx); fq_nmod_mpoly_pow_ui(t, t, i, ctx); fq_nmod_mpoly_set_str_pretty(m, "z", vars, ctx); fq_nmod_mpoly_add(t, t, m, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_HENSEL | MPOLY_GCD_USE_ZIPPEL2); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); } flint_printf("--------------------\ntotal time: %wd\n", total_super); flint_cleanup_master(); return 0; } flint-3.1.3/src/fq_nmod_mpoly/push_term_fq_nmod_fmpz.c000066400000000000000000000044561461254215100232070ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void _fq_nmod_mpoly_push_exp_ffmpz( fq_nmod_mpoly_t A, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_nmod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ffmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void _fq_nmod_mpoly_push_exp_pfmpz( fq_nmod_mpoly_t A, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_nmod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_pfmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void fq_nmod_mpoly_push_term_fq_nmod_fmpz( fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) { slong d; _fq_nmod_mpoly_push_exp_pfmpz(A, exp, ctx); d = fq_nmod_ctx_degree(ctx->fqctx); FLINT_ASSERT(A->length > 0); n_fq_set_fq_nmod(A->coeffs + d*(A->length - 1), c, ctx->fqctx); } void fq_nmod_mpoly_push_term_fq_nmod_ffmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, const fmpz *exp, const fq_nmod_mpoly_ctx_t ctx) { slong d; _fq_nmod_mpoly_push_exp_ffmpz(A, exp, ctx); d = fq_nmod_ctx_degree(ctx->fqctx); FLINT_ASSERT(A->length > 0); n_fq_set_fq_nmod(A->coeffs + d * (A->length - 1), c, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/push_term_fq_nmod_ui.c000066400000000000000000000025171461254215100226440ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void _fq_nmod_mpoly_push_exp_ui( fq_nmod_mpoly_t A, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_nmod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ui(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void fq_nmod_mpoly_push_term_fq_nmod_ui( fq_nmod_mpoly_t A, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) { slong d; _fq_nmod_mpoly_push_exp_ui(A, exp, ctx); FLINT_ASSERT(A->length > 0); d = fq_nmod_ctx_degree(ctx->fqctx); n_fq_set_fq_nmod(A->coeffs + d*(A->length - 1), c, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/quadratic_root.c000066400000000000000000000373501461254215100214610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* solve z^2+z=c */ static int _quadratic_root_const( mp_limb_t * z, const mp_limb_t * c, const fq_nmod_ctx_t fqctx) { slong i, d = fq_nmod_ctx_degree(fqctx); mp_limb_t * t, * p, * u, * cp, * ut, * up, * ct; int success; TMP_INIT; #if FLINT_WANT_ASSERT mp_limb_t * c_org = FLINT_ARRAY_ALLOC(d, mp_limb_t); _n_fq_set(c_org, c, d); #endif TMP_START; i = FLINT_MAX(N_FQ_REDUCE_ITCH, N_FQ_MUL_INV_ITCH); t = (mp_limb_t *) TMP_ALLOC((i + 7)*d*sizeof(mp_limb_t)); p = t + d*i; u = p + d*2; ut = u + d; up = ut + d; ct = up + d; cp = ct + d; /* find u with trace 1 */ for (i = 0; i < d; i++) { p[2*i] = 0; p[2*i + 1] = nmod_poly_get_coeff_ui(fqctx->modulus, 2*i + 1); } _n_fq_reduce2(ut, p, fqctx, t); FLINT_ASSERT(!_n_fq_is_zero(ut, d)); _n_fq_inv(u, ut, fqctx, t); _n_fq_set(cp, c, d); _n_fq_zero(ut, d); _n_fq_set(up, u, d); _n_fq_set(ct, c, d); _n_fq_zero(z, d); for (i = 0; i < d - 1; i++) { _n_fq_add(ut, ut, up, d, fqctx->mod); _n_fq_mul(cp, cp, cp, fqctx, t); _n_fq_mul(p, cp, ut, fqctx, t); _n_fq_add(z, z, p, d, fqctx->mod); _n_fq_add(ct, ct, cp, d, fqctx->mod); _n_fq_mul(up, up, up, fqctx, t); } success = _n_fq_is_zero(ct, d); #if FLINT_WANT_ASSERT if (success) { _n_fq_add(ut, ut, up, d, fqctx->mod); FLINT_ASSERT(_n_fq_is_one(ut, d)); _n_fq_mul(p, z, z, fqctx, t); _n_fq_add(p, p, z, d, fqctx->mod); FLINT_ASSERT(_n_fq_equal(p, c_org, d)); } flint_free(c_org); #endif TMP_END; return success; } /* solve x^2+A*x=B if x = Q + x' for the candidate solution terms Q, x'^2+Ax'=B-Q^2-A*Q B has heap idx (-1, j) Q^2 has heap idx (-2, j) A*Q has heap idx (i, j) for 0 <= i < Alen */ static int _fq_nmod_mpoly_quadratic_root_heap( fq_nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, slong bits, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); slong i, j, Qlen, Qs, As; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; mp_limb_t * t, * c, * lcAinv; int mcmp; TMP_INIT; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); TMP_START; t = (mp_limb_t *) TMP_ALLOC(8*d*sizeof(mp_limb_t)); c = t + 6*d; lcAinv = c + d; _n_fq_inv(lcAinv, Acoeffs + d*0, fqctx, t); /* alloc array of heap nodes which can be chained together */ next_loc = Alen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Alen + 3)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC((Alen + 2)*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*(Alen + 2)*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC((Alen + 2)*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC((Alen + 2)*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < Alen + 2; i++) exp_list[i] = exps + i*N; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; Qs = 1; As = Alen; mcmp = 1; Qlen = 0; /* insert (-1, 0, Bexps[0]) into heap */ x = chain + Alen + 0; x->i = -UWORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Bexps + N*0, N); while (heap_len > 1) { FLINT_ASSERT(heap_len - 1 <= Alen + 2); _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, N, Qlen + 1); /* exp can overflow, but divisibility & halving check their answers */ mpoly_monomial_set(exp, heap[1].exp, N); _nmod_vec_zero(t, 6*d); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -UWORD(1)) { FLINT_ASSERT(x->j < Blen); _nmod_vec_add(t, t, Bcoeffs + d*x->j, d, fqctx->mod); } else { const mp_limb_t * s = (x->i == -UWORD(2)) ? Qcoeffs + d*x->j : Acoeffs + d*x->i; FLINT_ASSERT(x->j < Qlen); FLINT_ASSERT(x->i == -UWORD(2) || x->i < Alen); _n_fq_madd2(t, s, Qcoeffs + d*x->j, fqctx, t + 2*d); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _n_fq_reduce2(Qcoeffs + d*Qlen, t, fqctx, t + 2*d); while (store > store_base) { j = *--store; i = *--store; if (i == -UWORD(1)) { if (j + 1 < Blen) { x = chain + Alen; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Bexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); } } else if (i == -UWORD(2)) { if (j + 1 < Qlen) { x = chain + Alen + 1; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Qexps + N*x->j, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } else { FLINT_ASSERT(j + 1 == Qlen); FLINT_ASSERT(Qs == 0); Qs = 1; } } else { FLINT_ASSERT(0 <= i && i < Alen); if (j + 1 < Qlen) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Aexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } else { FLINT_ASSERT(j + 1 == Qlen); As++; FLINT_ASSERT(As <= Alen); } } } if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) continue; /* mcmp > 0: The last written Qexp is > lm(A) mcmp = 0: = lm(A) mcmp < 0: < lm(A) must find an m such that m^2 + lt(A)*m = acc*exp */ if (mcmp <= 0) goto try_less; if (bits <= FLINT_BITS ? !mpoly_monomial_halves(Qexps + N*Qlen, exp, N, mask) : !mpoly_monomial_halves_mp(Qexps + N*Qlen, exp, N, bits)) { goto try_less; } if (mpoly_monomial_gt(Qexps + N*Qlen, Aexps + N*0, N, cmpmask)) { for (j = 1; j < d; j++) _n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, fqctx, t); goto mfound; } /* try equal */ if (!mpoly_monomial_equal(Qexps + Qlen*N, Aexps + N*0, N)) goto try_less; if (d < 2) goto try_less; _n_fq_mul(c, Qcoeffs + d*Qlen, lcAinv, fqctx, t); _n_fq_mul(c, c, lcAinv, fqctx, t); if (_quadratic_root_const(c, c, fqctx)) { _n_fq_mul(Qcoeffs + d*Qlen, c, Acoeffs + d*0, fqctx, t); mcmp = 0; goto mfound; } try_less: mcmp = -1; if (bits <= FLINT_BITS ? !mpoly_monomial_divides(Qexps + Qlen*N, exp, Aexps + N*0, N, mask) : !mpoly_monomial_divides_mp(Qexps + Qlen*N, exp, Aexps + N*0, N, bits)) { goto no_solution; } if (!mpoly_monomial_lt(Qexps + N*Qlen, Aexps + N*0, N, cmpmask)) goto no_solution; _n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lcAinv, fqctx, t); mfound: /* verify heap consistency (i >= 0, j) should be in the heap iff i >= As (-2, j) should be in the heap iff Qs = 0 */ FLINT_ASSERT(Qs == 0 || Qs == 1); FLINT_ASSERT(As <= Alen); #if FLINT_WANT_ASSERT { slong Asleft = Alen, Qsleft = 1; for (i = 1; i < heap_len; i++) { mpoly_heap_t * x = (mpoly_heap_t *) heap[i].next; do { if (x->i == -UWORD(1)) { continue; } else if (x->i == -UWORD(2)) { Qsleft--; } else { FLINT_ASSERT(x->i >= As); Asleft--; } } while ((x = x->next) != NULL); } FLINT_ASSERT(Asleft == As); FLINT_ASSERT(Qsleft == Qs); } #endif FLINT_ASSERT(mcmp < 0 || Qs == 1); if ((mcmp >= 0) < Qs) { /* the new Q^2 term did not cancel exp */ x = chain + Alen + 1; x->i = -UWORD(2); x->j = Qlen; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Qexps + N*x->j, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } Qs = FLINT_MIN(Qs, (mcmp >= 0)); for (i = (mcmp <= 0); i < As; i++) { /* the new Q*A[i] term did not not cancel exp */ x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Aexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } As = FLINT_MIN(As, (mcmp <= 0)); FLINT_ASSERT(!_n_fq_is_zero(Qcoeffs + d*Qlen, d)); Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; TMP_END; return 1; no_solution: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; TMP_END; return 0; } int fq_nmod_mpoly_quadratic_root( fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t Qbits; ulong * cmpmask; ulong * Aexps = A->exps, * Bexps = B->exps; int success, freeAexps = 0, freeBexps = 0; TMP_INIT; if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_zero(Q, ctx); return 1; } if (fq_nmod_mpoly_is_zero(A, ctx)) { return fq_nmod_mpoly_sqrt(Q, B, ctx); } if (ctx->fqctx->mod.n != 2) { mp_limb_t mhalf = (ctx->fqctx->mod.n - 1)/2; fq_nmod_mpoly_t t1, t2; fq_nmod_t c; fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_mpoly_mul(t1, A, A, ctx); fq_nmod_set_ui(c, nmod_mul(mhalf, mhalf, ctx->fqctx->mod), ctx->fqctx); fq_nmod_mpoly_scalar_addmul_fq_nmod(t2, B, t1, c, ctx); success = fq_nmod_mpoly_sqrt(t1, t2, ctx); if (success) { fq_nmod_set_ui(c, mhalf, ctx->fqctx); fq_nmod_mpoly_scalar_addmul_fq_nmod(Q, t1, A, c, ctx); } fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); return success; } TMP_START; Qbits = FLINT_MAX(A->bits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (Qbits > A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); } if (Q == A || Q == B) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init3(T, B->length/A->length + 1, Qbits, ctx); success = _fq_nmod_mpoly_quadratic_root_heap(T, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->fqctx); fq_nmod_mpoly_swap(T, Q, ctx); fq_nmod_mpoly_clear(T, ctx); } else { fq_nmod_mpoly_fit_length_reset_bits(Q, B->length/A->length + 1, Qbits, ctx); success = _fq_nmod_mpoly_quadratic_root_heap(Q, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->fqctx); } if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); TMP_END; return success; } flint-3.1.3/src/fq_nmod_mpoly/randtest_bits.c000066400000000000000000000026771461254215100213120ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_randtest_bits( fq_nmod_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j, nvars = ctx->minfo->nvars; flint_bitcnt_t bits = mpoly_fix_bits(FLINT_MAX(exp_bits, 1), ctx->minfo); fmpz * exp; TMP_INIT; TMP_START; exp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exp + j); fq_nmod_mpoly_fit_length_reset_bits(A, length, bits, ctx); A->length = 0; for (i = 0; i < length; i++) { mpoly_monomial_randbits_fmpz(exp, state, exp_bits, ctx->minfo); _fq_nmod_mpoly_push_exp_ffmpz(A, exp, ctx); n_fq_randtest_not_zero(A->coeffs + d*(A->length - 1), state, ctx->fqctx); } fq_nmod_mpoly_sort_terms(A, ctx); fq_nmod_mpoly_combine_like_terms(A, ctx); for (j = 0; j < nvars; j++) fmpz_clear(exp + j); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/randtest_bound.c000066400000000000000000000023441461254215100214470ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_randtest_bound( fq_nmod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); fq_nmod_mpoly_fit_length_reset_bits(A, length, MPOLY_MIN_BITS, ctx); A->length = 0; for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bound); _fq_nmod_mpoly_push_exp_ui(A, exp, ctx); n_fq_randtest_not_zero(A->coeffs + d*(A->length - 1), state, ctx->fqctx); } fq_nmod_mpoly_sort_terms(A, ctx); fq_nmod_mpoly_combine_like_terms(A, ctx); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/randtest_bounds.c000066400000000000000000000023461461254215100216340ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_randtest_bounds(fq_nmod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); fq_nmod_mpoly_fit_length_reset_bits(A, length, MPOLY_MIN_BITS, ctx); A->length = 0; for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bounds[j]); _fq_nmod_mpoly_push_exp_ui(A, exp, ctx); n_fq_randtest_not_zero(A->coeffs + d*(A->length - 1), state, ctx->fqctx); } fq_nmod_mpoly_sort_terms(A, ctx); fq_nmod_mpoly_combine_like_terms(A, ctx); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/realloc.c000066400000000000000000000020261461254215100200520ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_realloc( fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (alloc == 0) /* Clear up, reinitialise */ { fq_nmod_mpoly_clear(A, ctx); fq_nmod_mpoly_init(A, ctx); return; } A->exps_alloc = N*alloc; A->exps = (ulong *) flint_realloc(A->exps, A->exps_alloc*sizeof(ulong)); A->coeffs_alloc = d*alloc; A->coeffs = (mp_limb_t *) flint_realloc(A->coeffs, A->coeffs_alloc*sizeof(ulong)); } flint-3.1.3/src/fq_nmod_mpoly/repack_bits.c000066400000000000000000000042061461254215100207210ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_repack_bits( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx) { int success; Abits = mpoly_fix_bits(Abits, ctx->minfo); if (B->bits == Abits || B->length == 0) { fq_nmod_mpoly_set(A, B, ctx); return 1; } if (A == B) return fq_nmod_mpoly_repack_bits_inplace(A, Abits, ctx); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); success = mpoly_repack_monomials(A->exps, Abits, B->exps, B->bits, B->length, ctx->minfo); if (success) { slong d = fq_nmod_ctx_degree(ctx->fqctx); _nmod_vec_set(A->coeffs, B->coeffs, d*B->length); A->length = B->length; } else { A->length = 0; } return success; } int fq_nmod_mpoly_repack_bits_inplace( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx) { int success; ulong * texps; slong talloc; slong N = mpoly_words_per_exp(Abits, ctx->minfo); if (A->bits == Abits) { return 1; } if (A->length < 1) { A->bits = Abits; return 1; } N = mpoly_words_per_exp(Abits, ctx->minfo); talloc = N*A->length; texps = FLINT_ARRAY_ALLOC(talloc, ulong); success = mpoly_repack_monomials(texps, Abits, A->exps, A->bits, A->length, ctx->minfo); A->bits = Abits; if (success) { flint_free(A->exps); A->exps = texps; A->exps_alloc = talloc; } else { flint_free(texps); A->length = 0; } return success; } flint-3.1.3/src/fq_nmod_mpoly/resize.c000066400000000000000000000021511461254215100177310ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_resize( fq_nmod_mpoly_t A, slong new_length, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong old_length = A->length; slong N; new_length = FLINT_MAX(WORD(0), new_length); if (new_length > old_length) { fq_nmod_mpoly_fit_length(A, new_length, ctx); /* must zero out the new coeffs/exps past the old end */ N = mpoly_words_per_exp(A->bits, ctx->minfo); flint_mpn_zero(A->exps + N*old_length, N*(new_length - old_length)); _nmod_vec_zero(A->coeffs + d*old_length, d*(new_length - old_length)); } A->length = new_length; } flint-3.1.3/src/fq_nmod_mpoly/resultant.c000066400000000000000000000016731461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_resultant(fq_nmod_mpoly_t R, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { int success; fq_nmod_mpoly_univar_t Ax, Bx; fq_nmod_mpoly_univar_init(Ax, ctx); fq_nmod_mpoly_univar_init(Bx, ctx); fq_nmod_mpoly_to_univar(Ax, A, var, ctx); fq_nmod_mpoly_to_univar(Bx, B, var, ctx); success = fq_nmod_mpoly_univar_resultant(R, Ax, Bx, ctx); fq_nmod_mpoly_univar_clear(Ax, ctx); fq_nmod_mpoly_univar_clear(Bx, ctx); return success; } flint-3.1.3/src/fq_nmod_mpoly/reverse.c000066400000000000000000000021721461254215100201060ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_reverse( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong i; slong Blen = B->length; if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, Blen, B->bits, ctx); A->length = B->length; for (i = 0; i < Blen; i++) _n_fq_set(A->coeffs + d*i, B->coeffs + d*(Blen - i - 1), d); } else { for (i = 0; i < Blen/2; i++) _n_fq_swap(A->coeffs + d*i, A->coeffs + d*(Blen - i - 1), d); } mpoly_reverse(A->exps, B->exps, Blen, N); } flint-3.1.3/src/fq_nmod_mpoly/scalar_addmul_fq_nmod.c000066400000000000000000000111711461254215100227300ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" static slong _fq_nmod_mpoly_scalar_addmul_n_fq( mp_limb_t * Acoeffs, ulong * Aexps, mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, const mp_limb_t * f, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); slong i = 0, j = 0, k = 0; mp_limb_t * tmp; TMP_INIT; TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*N_FQ_MUL_ITCH*sizeof(mp_limb_t)); while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + N*i, Cexps + N*j, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + N*k, Bexps + N*i, N); _n_fq_set(Acoeffs + d*k, Bcoeffs + d*i, d); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + N*k, Bexps + N*i, N); _n_fq_addmul(Acoeffs + d*k, Bcoeffs + d*i, Ccoeffs + d*j, f, fqctx, tmp); k += !_n_fq_is_zero(Acoeffs + d*k, d); i++; j++; } else { mpoly_monomial_set(Aexps + N*k, Cexps + N*j, N); _n_fq_mul(Acoeffs + d*k, Ccoeffs + d*j, f, fqctx, tmp); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); _n_fq_set(Acoeffs + d*k, Bcoeffs + d*i, d); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); _n_fq_mul(Acoeffs + d*k, Ccoeffs + d*j, f, fqctx, tmp); j++; k++; } TMP_END; return k; } void fq_nmod_mpoly_scalar_addmul_fq_nmod( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_t e, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); ulong * Bexps = B->exps, * Cexps = C->exps; flint_bitcnt_t Abits = FLINT_MAX(B->bits, C->bits); slong N = mpoly_words_per_exp(Abits, ctx->minfo); ulong * cmpmask; int freeBexps = 0, freeCexps = 0; mp_limb_t * f; TMP_INIT; if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_scalar_mul_fq_nmod(A, C, e, ctx); return; } else if (fq_nmod_mpoly_is_zero(C, ctx) || fq_nmod_is_zero(e, ctx->fqctx)) { fq_nmod_mpoly_set(A, B, ctx); return; } TMP_START; cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); f = (mp_limb_t *) TMP_ALLOC(d*sizeof(mp_limb_t)); n_fq_set_fq_nmod(f, e, ctx->fqctx); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_fit_length_reset_bits(T, B->length + C->length, Abits, ctx); T->length = _fq_nmod_mpoly_scalar_addmul_n_fq(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, f, N, cmpmask, ctx->fqctx); fq_nmod_mpoly_swap(A, T, ctx); fq_nmod_mpoly_clear(T, ctx); } else { fq_nmod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _fq_nmod_mpoly_scalar_addmul_n_fq(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, f, N, cmpmask, ctx->fqctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/scalar_mul_fq_nmod.c000066400000000000000000000050271461254215100222620ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_scalar_mul_n_fq( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const mp_limb_t * c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i; mp_limb_t * t; TMP_INIT; if (_n_fq_is_zero(c, d)) { fq_nmod_mpoly_zero(A, ctx); return; } if (A == B) { if (_n_fq_is_one(c, d)) return; } else { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); A->length = B->length; mpoly_copy_monomials(A->exps, B->exps, B->length, N); if (_n_fq_is_one(c, d)) { _nmod_vec_set(A->coeffs, B->coeffs, d*B->length); return; } } TMP_START; t = (mp_limb_t *) TMP_ALLOC(d*N_FQ_MUL_ITCH*sizeof(mp_limb_t)); for (i = 0; i < B->length; i++) _n_fq_mul(A->coeffs + d*i, B->coeffs + d*i, c, ctx->fqctx, t); TMP_END; } void fq_nmod_mpoly_scalar_mul_fq_nmod( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong i; mp_limb_t * t; TMP_INIT; if (fq_nmod_is_zero(c, ctx->fqctx)) { fq_nmod_mpoly_zero(A, ctx); return; } if (A == B) { if (fq_nmod_is_one(c, ctx->fqctx)) return; } else { slong N; fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); A->length = B->length; N = mpoly_words_per_exp(B->bits, ctx->minfo); mpoly_copy_monomials(A->exps, B->exps, B->length, N); if (fq_nmod_is_one(c, ctx->fqctx)) { _nmod_vec_set(A->coeffs, B->coeffs, d*B->length); return; } } TMP_START; t = (mp_limb_t *) TMP_ALLOC(d*(1 + N_FQ_MUL_ITCH)*sizeof(mp_limb_t)); n_fq_set_fq_nmod(t, c, ctx->fqctx); for (i = 0; i < B->length; i++) _n_fq_mul(A->coeffs + d*i, B->coeffs + d*i, t, ctx->fqctx, t + d); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/set.c000066400000000000000000000016711461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(B->bits, ctx->minfo); if (A == B) return; fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*B->length); mpoly_copy_monomials(A->exps, B->exps, B->length, N); _fq_nmod_mpoly_set_length(A, B->length, ctx); } flint-3.1.3/src/fq_nmod_mpoly/set_coeff_fq_nmod_fmpz.c000066400000000000000000000060351461254215100231310ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void _fq_nmod_mpoly_set_coeff_fq_nmod_fmpz( fq_nmod_mpoly_t A, const fq_nmod_t c, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t exp_bits; slong i, N, index; ulong * cmpmask; ulong * packed_exp; int exists; TMP_INIT; TMP_START; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_nmod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, A->bits, ctx->minfo); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, A->bits, ctx->minfo); exists = mpoly_monomial_exists(&index, A->exps, packed_exp, A->length, N, cmpmask); if (!exists) { if (!fq_nmod_is_zero(c, ctx->fqctx)) { /* make new term only if coeff is nonzero*/ fq_nmod_mpoly_fit_length(A, A->length + 1, ctx); for (i = A->length; i >= index + 1; i--) { _n_fq_set(A->coeffs + d*i, A->coeffs + d*(i - 1), d); mpoly_monomial_set(A->exps + N*i, A->exps + N*(i - 1), N); } n_fq_set_fq_nmod(A->coeffs + d*index, c, ctx->fqctx); mpoly_monomial_set(A->exps + N*index, packed_exp, N); _fq_nmod_mpoly_set_length(A, A->length + 1, ctx); } } else if (fq_nmod_is_zero(c, ctx->fqctx)) /* zero coeff, remove term */ { for (i = index; i < A->length - 1; i++) { _n_fq_set(A->coeffs + d*i, A->coeffs + d*(i + 1), d); mpoly_monomial_set(A->exps + N*i, A->exps + N*(i + 1), N); } _fq_nmod_mpoly_set_length(A, A->length - 1, ctx); } else /* term with that monomial exists, coeff is nonzero */ { n_fq_set_fq_nmod(A->coeffs + d*index, c, ctx->fqctx); } TMP_END; } void fq_nmod_mpoly_set_coeff_fq_nmod_fmpz( fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_init(newexp + i); fmpz_set(newexp + i, exp[i]); } _fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(A, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/set_coeff_fq_nmod_monomial.c000066400000000000000000000023421461254215100237650ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_coeff_fq_nmod_monomial(fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_t M, const fq_nmod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * texps; TMP_INIT; if (M->length != WORD(1)) { flint_throw(FLINT_ERROR, "M not monomial in fq_nmod_mpoly_set_coeff_fq_nmod_monomial"); } TMP_START; texps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init(texps + i); mpoly_get_monomial_ffmpz(texps, M->exps + 0, M->bits, ctx->minfo); _fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(A, c, texps, ctx); for (i = 0; i < nvars; i++) fmpz_clear(texps + i); TMP_END; return; } flint-3.1.3/src/fq_nmod_mpoly/set_coeff_fq_nmod_ui.c000066400000000000000000000016511461254215100225710ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_coeff_fq_nmod_ui(fq_nmod_mpoly_t poly, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); _fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(poly, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/set_fmpz.c000066400000000000000000000023111461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_ui( fq_nmod_mpoly_t A, ulong c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (c >= ctx->fqctx->mod.n) NMOD_RED(c, c, ctx->fqctx->mod); if (c == 0) { fq_nmod_mpoly_zero(A, ctx); return; } fq_nmod_mpoly_fit_length(A, 1, ctx); _n_fq_zero(A->coeffs + d*0, d); A->coeffs[0] = c; mpoly_monomial_zero(A->exps, N); _fq_nmod_mpoly_set_length(A, 1, ctx); } void fq_nmod_mpoly_set_fmpz( fq_nmod_mpoly_t A, const fmpz_t c, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpoly_set_ui(A, fmpz_fdiv_ui(c, ctx->fqctx->mod.n), ctx); } flint-3.1.3/src/fq_nmod_mpoly/set_fq_nmod.c000066400000000000000000000024721461254215100207340ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_n_fq( fq_nmod_mpoly_t A, const mp_limb_t * c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); fq_nmod_mpoly_fit_length(A, 1, ctx); mpoly_monomial_zero(A->exps + N*0, N); _n_fq_set(A->coeffs + d*0, c, d); _fq_nmod_mpoly_set_length(A, !_n_fq_is_zero(A->coeffs + d*0, d), ctx); } void fq_nmod_mpoly_set_fq_nmod( fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (fq_nmod_is_zero(c, ctx->fqctx)) { fq_nmod_mpoly_zero(A, ctx); return; } fq_nmod_mpoly_fit_length(A, 1, ctx); n_fq_set_fq_nmod(A->coeffs, c, ctx->fqctx); mpoly_monomial_zero(A->exps + N*0, N); _fq_nmod_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/fq_nmod_mpoly/set_fq_nmod_gen.c000066400000000000000000000015351461254215100215640ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_fq_nmod_gen( fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(A->bits, ctx->minfo); fq_nmod_mpoly_fit_length(A, 1, ctx); n_fq_gen(A->coeffs + 0, ctx->fqctx); mpoly_monomial_zero(A->exps, N); _fq_nmod_mpoly_set_length(A, !_n_fq_is_zero(A->coeffs + 0, d), ctx); } flint-3.1.3/src/fq_nmod_mpoly/set_str_pretty.c000066400000000000000000000026061461254215100215270ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_set_str_pretty(fq_nmod_mpoly_t poly, const char * str, const char** x, const fq_nmod_mpoly_ctx_t ctx) { int ret; slong i; fq_nmod_mpoly_t val; mpoly_parse_t E; char dummy[FLINT_BITS/2]; mpoly_void_ring_init_fq_nmod_mpoly_ctx(E->R, ctx); mpoly_parse_init(E); fq_nmod_mpoly_init(val, ctx); for (i = 0; i < ctx->minfo->nvars; i++) { fq_nmod_mpoly_gen(val, i, ctx); if (x == NULL) { flint_sprintf(dummy, "x%wd", i + 1); mpoly_parse_add_terminal(E, dummy, (const void *)val); } else { mpoly_parse_add_terminal(E, x[i], (const void *)val); } } fq_nmod_mpoly_set_fq_nmod_gen(val, ctx); mpoly_parse_add_terminal(E, ctx->fqctx->var, (const void *)val); fq_nmod_mpoly_clear(val, ctx); ret = mpoly_parse_parse(E, poly, str, strlen(str)); mpoly_parse_clear(E); return ret; } flint-3.1.3/src/fq_nmod_mpoly/set_term_coeff_fq_nmod.c000066400000000000000000000015051461254215100231210ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_term_coeff_fq_nmod(fq_nmod_mpoly_t A, slong i, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "fq_nmod_mpoly_set_term_coeff_fq_nmod: index is out of range"); } n_fq_set_fq_nmod(A->coeffs + d*i, c, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly/set_term_exp_fmpz.c000066400000000000000000000020361461254215100221640ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_term_exp_fmpz(fq_nmod_mpoly_t A, slong i, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "fq_nmod_mpoly_set_term_exp_fmpz: index is out of range."); } exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_nmod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_pfmpz(A->exps + N*i, exp, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/set_term_exp_ui.c000066400000000000000000000020231461254215100216210ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_set_term_exp_ui(fq_nmod_mpoly_t A, slong i, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "fq_nmod_mpoly_set_term_exp_ui: index is out of range"); } exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_nmod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ui(A->exps + N*i, exp, A->bits, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/setform.c000066400000000000000000000025721461254215100201160ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* setform copies the exponents and zeros the coefficients */ void fq_nmod_mpoly_setform(fq_nmod_mpoly_t A, fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, bits, ctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); _nmod_vec_zero(A->coeffs, d*B->length); A->length = B->length; } void fq_nmod_mpolyu_setform(fq_nmod_mpolyu_t A, fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; fq_nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { fq_nmod_mpoly_setform(A->coeffs + i, B->coeffs + i, ctx); A->exps[i] = B->exps[i]; } A->length = B->length; } flint-3.1.3/src/fq_nmod_mpoly/sort_terms.c000066400000000000000000000111121461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* sort terms in [left, right) by exponent assuming that bits in position > pos are already sorted and assuming exponent vectors fit into one word and assuming that all bit positions that need to be sorted are in totalmask */ void _fq_nmod_mpoly_radix_sort1( fq_nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask, slong d) { ulong mask = UWORD(1) << pos; ulong cmp = cmpmask & mask; slong mid, cur; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < FLINT_BITS); /* do nothing on lists of 0 or 1 elements */ if (left + 1 >= right) { return; } /* return if there is no information to sort on this bit */ if ((totalmask & mask) == WORD(0)) { if (pos < 1) return; pos--; _fq_nmod_mpoly_radix_sort1(A, left, right, pos, cmpmask, totalmask, d); return; } /* find first 'zero' */ mid = left; while (mid < right && ((A->exps + 1*mid)[0] & mask) != cmp) { mid++; } /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ cur = mid; while (++cur < right) { if (((A->exps + 1*cur)[0] & mask) != cmp) { _n_fq_swap(A->coeffs + d*cur, A->coeffs + d*mid, d); mpoly_monomial_swap(A->exps + 1*cur, A->exps + 1*mid, 1); mid++; } } if (pos < 1) return; pos--; _fq_nmod_mpoly_radix_sort1(A, left, mid, pos, cmpmask, totalmask, d); _fq_nmod_mpoly_radix_sort1(A, mid, right, pos, cmpmask, totalmask, d); } /* sort terms in [left, right) by exponent assuming that bits in position > pos are already sorted TODO: Stack depth is proportional to N*FLINT_BITS Might turn into iterative version Low priority */ void _fq_nmod_mpoly_radix_sort( fq_nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask, slong d) { ulong off = pos/FLINT_BITS; ulong bit = pos%FLINT_BITS; ulong mask = UWORD(1) << bit; ulong cmp = cmpmask[off] & mask; slong mid, check; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < N*FLINT_BITS); /* do nothing on lists of 0 or 1 elements */ if (left + 1 >= right) return; /* find first 'zero' */ mid = left; while (mid < right && ((A->exps+N*mid)[off] & mask) != cmp) { mid++; } /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ check = mid; while (++check < right) { if (((A->exps + N*check)[off] & mask) != cmp) { _n_fq_swap(A->coeffs + d*check, A->coeffs + d*mid, d); mpoly_monomial_swap(A->exps + N*check, A->exps + N*mid, N); mid++; } } if (pos < 1) return; pos--; _fq_nmod_mpoly_radix_sort(A, left, mid, pos, N, cmpmask, d); _fq_nmod_mpoly_radix_sort(A, mid, right, pos, N, cmpmask, d); } /* sort the terms in A by exponent assuming that the exponents are valid (other than being in order) */ void fq_nmod_mpoly_sort_terms(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong d; slong i, msb, N; ulong himask, * ptempexp; TMP_INIT; TMP_START; N = mpoly_words_per_exp(A->bits, ctx->minfo); ptempexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(ptempexp, N, A->bits, ctx->minfo); himask = 0; for (i = 0; i < A->length; i++) { himask |= (A->exps + N*i)[N - 1]; } if (himask != 0) { msb = flint_clz(himask); msb = (FLINT_BITS - 1)^msb; } else { msb = -WORD(1); } d = fq_nmod_ctx_degree(ctx->fqctx); if (N == 1) { if (msb >= 0) { _fq_nmod_mpoly_radix_sort1(A, 0, A->length, msb, ptempexp[0], himask, d); } } else { _fq_nmod_mpoly_radix_sort(A, 0, A->length, (N - 1)*FLINT_BITS + msb, N, ptempexp, d); } TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/sqrt_heap.c000066400000000000000000000336431461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif /* try to prove that A is not a square */ static int _is_proved_not_square( int count, flint_rand_t state, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx, const fq_nmod_ctx_t fqctx) { int tries_left, success = 0; slong i, N = mpoly_words_per_exp(Abits, mctx); fq_nmod_struct eval[1], * alphas, ** alpha_ptrs; ulong * t; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; t = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (count == 1) { success = mpoly_is_proved_not_square(Aexps, Alen, Abits, N, t); if (success) goto cleanup; } tries_left = 3*count; fq_nmod_init(eval, fqctx); alphas = (fq_nmod_struct *) TMP_ALLOC(mctx->nvars*sizeof(fq_nmod_struct)); alpha_ptrs = (fq_nmod_struct **) TMP_ALLOC(mctx->nvars*sizeof(fq_nmod_struct *)); for (i = 0; i < mctx->nvars; i++) { alpha_ptrs[i] = alphas + i; fq_nmod_init(alphas + i, fqctx); } next_p: for (i = 0; i < mctx->nvars; i++) fq_nmod_rand(alphas + i, state, fqctx); _fq_nmod_mpoly_eval_all_fq_nmod(eval, Acoeffs, Aexps, Alen, Abits, alpha_ptrs, mctx, fqctx); success = !fq_nmod_is_square(eval, fqctx); if (!success && --tries_left >= 0) goto next_p; fq_nmod_clear(eval, fqctx); for (i = 0; i < mctx->nvars; i++) fq_nmod_clear(alphas + i, fqctx); cleanup: TMP_END; return success; } static int n_fq_sqrt(mp_limb_t * q, const mp_limb_t * a, const fq_nmod_ctx_t ctx) { int res; fq_nmod_t t; fq_nmod_init(t, ctx); n_fq_get_fq_nmod(t, a, ctx); res = fq_nmod_sqrt(t, t, ctx); n_fq_set_fq_nmod(q, t, ctx); fq_nmod_clear(t, ctx); return res; } static int _fq_nmod_mpoly_sqrt_heap( fq_nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t bits, const mpoly_ctx_t mctx, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); slong N = mpoly_words_per_exp(bits, mctx); ulong * cmpmask; slong i, j, Qlen, Ai; slong next_loc; slong heap_len = 1, heap_alloc; int exp_alloc; mpoly_heap_s * heap; mpoly_heap_t * chain_nodes[64]; mpoly_heap_t ** chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exp3; ulong * exps[64]; ulong ** exp_list; slong exp_next; ulong mask; mp_limb_t * t, * t2, * lc_inv; int lt_divides, halves; flint_rand_t heuristic_state; int heuristic_count = 0; TMP_INIT; TMP_START; t = (mp_limb_t *) TMP_ALLOC(13*d*sizeof(mp_limb_t)); t2 = t + 6*d; lc_inv = t2 + 6*d; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, mctx); flint_randinit(heuristic_state); /* alloc array of heap nodes which can be chained together */ next_loc = 2*sqrt(Alen) + 4; /* something bigger than heap can ever be */ heap_alloc = next_loc - 3; heap = (mpoly_heap_s *) flint_malloc((heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[0] = (mpoly_heap_t *) flint_malloc(heap_alloc*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_malloc(heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_malloc(2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc; i++) chain[i] = chain_nodes[0] + i; /* array of exponent vectors, each of "N" words */ exps[0] = (ulong *) flint_malloc(heap_alloc*N*sizeof(ulong)); exp_alloc = 1; /* list of pointers to available exponent vectors */ exp_list = (ulong **) flint_malloc(heap_alloc*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* final exponent */ exp3 = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < heap_alloc; i++) exp_list[i] = exps[0] + i*N; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; /* "insert" (-1, 1, Aexps[0]) into "heap" */ Ai = 1; /* compute first term */ Qlen = 0; _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, N, Qlen + 1); if (!n_fq_sqrt(Qcoeffs + d*0, Acoeffs + d*0, fqctx)) goto not_sqrt; Qlen = 1; /* precompute leading coefficient info */ _n_fq_add(t2, Qcoeffs + d*0, Qcoeffs + d*0, d, fqctx->mod); _n_fq_inv(lc_inv, t2, fqctx, t); if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(Qexps + 0, Aexps + 0, N, mask); else halves = mpoly_monomial_halves_mp(Qexps + 0, Aexps + 0, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ /* optimisation, compute final term */ { if (!n_fq_sqrt(t, Acoeffs + d*(Alen - 1), fqctx)) goto not_sqrt; if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(exp3, Aexps + (Alen - 1)*N, N, mask); else halves = mpoly_monomial_halves_mp(exp3, Aexps + (Alen - 1)*N, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ if (bits <= FLINT_BITS) mpoly_monomial_add(exp3, exp3, Qexps + 0, N); else mpoly_monomial_add_mp(exp3, exp3, Qexps + 0, N); } while (heap_len > 1 || Ai < Alen) { _fq_nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, d, &Qexps, &Q->exps_alloc, N, Qlen + 1); if (heap_len > 1 && Ai < Alen && mpoly_monomial_equal(Aexps + N*Ai, heap[1].exp, N)) { /* take from both A and heap */ mpoly_monomial_set(exp, Aexps + N*Ai, N); _n_fq_set(Qcoeffs + d*Qlen, Acoeffs + d*Ai, d); Ai++; } else if (heap_len > 1 && (Ai >= Alen || mpoly_monomial_lt( Aexps + N*Ai, heap[1].exp, N, cmpmask))) { /* take only from heap */ mpoly_monomial_set(exp, heap[1].exp, N); _n_fq_zero(Qcoeffs + d*Qlen, d); if (bits <= FLINT_BITS ? mpoly_monomial_overflows(exp, N, mask) : mpoly_monomial_overflows_mp(exp, N, bits)) goto not_sqrt; } else { FLINT_ASSERT(Ai < Alen); /* take only from A */ mpoly_monomial_set(exp, Aexps + N*Ai, N); _n_fq_set(Qcoeffs + d*Qlen, Acoeffs + d*Ai, d); Ai++; goto skip_heap; } _nmod_vec_zero(t, 6*d); _nmod_vec_zero(t2, 6*d); /* TODO lazy_size = _n_fq_dot_lazy_size(heap_alloc + 1, fqctx) */ { do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { mp_limb_t * dest; *store++ = x->i; *store++ = x->j; dest = (x->i != x->j) ? t2 : t; _n_fq_madd2(dest, Qcoeffs + d*x->i, Qcoeffs + d*x->j, fqctx, dest + 2*d); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); _nmod_vec_add(t, t, t2, 2*d, fqctx->mod); _nmod_vec_add(t, t, t2, 2*d, fqctx->mod); } _n_fq_reduce2(t2, t, fqctx, t + 2*d); _nmod_vec_sub(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, t2, d, fqctx->mod); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right */ if (j < i) { x = chain[i]; x->i = i; x->j = j + 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + N*x->i, Qexps + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } if (_n_fq_is_zero(Qcoeffs + d*Qlen, d)) continue; skip_heap: if (bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(Qexps + N*Qlen, exp, Qexps + N*0, N, mask); else lt_divides = mpoly_monomial_divides_mp(Qexps + N*Qlen, exp, Qexps + N*0, N, bits); if (!lt_divides) goto not_sqrt; _n_fq_mul(Qcoeffs + d*Qlen, Qcoeffs + d*Qlen, lc_inv, fqctx, t); if (Qlen >= heap_alloc) { /* run some tests if the square root is getting long */ if (Qlen > Alen && _is_proved_not_square( ++heuristic_count, heuristic_state, Acoeffs, Aexps, Alen, bits, mctx, fqctx)) { goto not_sqrt; } heap_alloc *= 2; heap = (mpoly_heap_s *) flint_realloc(heap, (heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[exp_alloc] = (mpoly_heap_t *) flint_malloc((heap_alloc/2)*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_realloc(chain, heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_realloc(store_base, 2*heap_alloc*sizeof(mpoly_heap_t *)); exps[exp_alloc] = (ulong *) flint_malloc((heap_alloc/2)*N*sizeof(ulong)); exp_list = (ulong **) flint_realloc(exp_list, heap_alloc*sizeof(ulong *)); for (i = 0; i < heap_alloc/2; i++) { chain[i + heap_alloc/2] = chain_nodes[exp_alloc] + i; exp_list[i + heap_alloc/2] = exps[exp_alloc] + i*N; } exp_alloc++; } /* put (Qlen, 1) in heap */ i = Qlen; x = chain[i]; x->i = i; x->j = 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); Qlen++; } cleanup: flint_randclear(heuristic_state); Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; flint_free(heap); flint_free(chain); flint_free(store_base); flint_free(exp_list); for (i = 0; i < exp_alloc; i++) { flint_free(exps[i]); flint_free(chain_nodes[i]); } TMP_END; return Qlen > 0; not_sqrt: Qlen = 0; goto cleanup; } int fq_nmod_mpoly_sqrt_heap(fq_nmod_mpoly_t Q, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { int success; slong lenq_est; if ((ctx->fqctx->mod.n % 2) == 0) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t bits = A->bits; mp_limb_t * Aexps = A->exps; slong Alen = A->length; slong i, j, N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; mp_limb_t * t; if (Q != A) fq_nmod_mpoly_fit_length_reset_bits(Q, Alen, bits, ctx); for (i = 0; i < Alen; i++) { if (bits <= FLINT_BITS ? !mpoly_monomial_halves(Q->exps + N*i, Aexps + N*i, N, mask) : !mpoly_monomial_halves_mp(Q->exps + N*i, Aexps + N*i, N, bits)) { Q->length = 0; return 0; } } t = FLINT_ARRAY_ALLOC(N_FQ_MUL_ITCH*d, mp_limb_t); for (i = 0; i < Alen; i++) { _n_fq_set(Q->coeffs + d*i, A->coeffs + d*i, d); for (j = 1; j < d; j++) _n_fq_mul(Q->coeffs + d*i, Q->coeffs + d*i, Q->coeffs + d*i, ctx->fqctx, t); } flint_free(t); Q->length = Alen; return 1; } if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_mpoly_zero(Q, ctx); return 1; } lenq_est = n_sqrt(A->length); if (Q == A) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init3(T, lenq_est, A->bits, ctx); success = _fq_nmod_mpoly_sqrt_heap(T, A->coeffs, A->exps, A->length, A->bits, ctx->minfo, ctx->fqctx); fq_nmod_mpoly_swap(Q, T, ctx); fq_nmod_mpoly_clear(T, ctx); } else { fq_nmod_mpoly_fit_length_reset_bits(Q, lenq_est, A->bits, ctx); success = _fq_nmod_mpoly_sqrt_heap(Q, A->coeffs, A->exps, A->length, A->bits, ctx->minfo, ctx->fqctx); } return success; } flint-3.1.3/src/fq_nmod_mpoly/sub.c000066400000000000000000000102411461254215100172200ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" slong _fq_nmod_mpoly_sub( mp_limb_t * Acoeffs, ulong * Aexps, mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, const fq_nmod_ctx_t fqctx) { slong d = fq_nmod_ctx_degree(fqctx); nmod_t mod = fq_nmod_ctx_mod(fqctx); slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + N*i, Cexps + N*j, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + N*k, Bexps + N*i, N); _n_fq_set(Acoeffs + d*k, Bcoeffs + d*i, d); i++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + N*k, Bexps + N*i, N); _n_fq_sub(Acoeffs + d*k, Bcoeffs + d*i, Ccoeffs + d*j, d, mod); k -= _n_fq_is_zero(Acoeffs + d*k, d); i++; j++; } else { mpoly_monomial_set(Aexps + N*k, Cexps + N*j, N); _n_fq_neg(Acoeffs + d*k, Ccoeffs + d*j, d, mod); j++; } k++; } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); _n_fq_set(Acoeffs + d*k, Bcoeffs + d*i, d); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); _n_fq_neg(Acoeffs + d*k, Ccoeffs + d*j, d, mod); j++; k++; } return k; } void fq_nmod_mpoly_sub( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t C, const fq_nmod_mpoly_ctx_t ctx) { slong Alen; ulong * Bexps = B->exps, * Cexps = C->exps; flint_bitcnt_t Abits = FLINT_MAX(B->bits, C->bits); slong N = mpoly_words_per_exp(Abits, ctx->minfo); ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fq_nmod_mpoly_is_zero(B, ctx)) { fq_nmod_mpoly_neg(A, C, ctx); return; } else if (fq_nmod_mpoly_is_zero(C, ctx)) { fq_nmod_mpoly_set(A, B, ctx); return; } TMP_START; cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits > C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_fit_length_reset_bits(T, B->length + C->length, Abits, ctx); Alen = _fq_nmod_mpoly_sub(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->fqctx); fq_nmod_mpoly_swap(T, A, ctx); fq_nmod_mpoly_clear(T, ctx); } else { fq_nmod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); Alen = _fq_nmod_mpoly_sub(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->fqctx); } _fq_nmod_mpoly_set_length(A, Alen, ctx); if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/sub_fq_nmod.c000066400000000000000000000042231461254215100207260ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_sub_fq_nmod( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong Blen = B->length; fq_nmod_mpoly_assert_canonical(B, ctx); if (fq_nmod_is_zero(c, ctx->fqctx)) { fq_nmod_mpoly_set(A, B, ctx); return; } if (Blen < 1) { fq_nmod_mpoly_set_fq_nmod(A, c, ctx); fq_nmod_mpoly_neg(A, A, ctx); return; } if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, Blen, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*(Blen - 1)); mpoly_copy_monomials(A->exps, B->exps, Blen, N); _fq_nmod_mpoly_set_length(A, Blen, ctx); } n_fq_sub_fq_nmod(A->coeffs + d*(Blen - 1), B->coeffs + d*(Blen - 1), c, ctx->fqctx); if (_n_fq_is_zero(A->coeffs + d*(Blen - 1), d)) _fq_nmod_mpoly_set_length(A, Blen - 1, ctx); } else { if (A != B) { fq_nmod_mpoly_fit_length_reset_bits(A, Blen + 1, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, d*Blen); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } else { fq_nmod_mpoly_fit_length(A, Blen + 1, ctx); } mpoly_monomial_zero(A->exps + N*Blen, N); n_fq_set_fq_nmod(A->coeffs + d*Blen, c, ctx->fqctx); _n_fq_neg(A->coeffs + d*Blen, A->coeffs + d*Blen, d, fq_nmod_ctx_mod(ctx->fqctx)); _fq_nmod_mpoly_set_length(A, Blen + 1, ctx); } } flint-3.1.3/src/fq_nmod_mpoly/term_content.c000066400000000000000000000034521461254215100211360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_term_content(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t Abits; fmpz * minAfields, * min_degs; TMP_INIT; if (fq_nmod_mpoly_is_zero(A, ctx)) { fq_nmod_mpoly_zero(M, ctx); return; } TMP_START; Abits = A->bits; /* get the field-wise minimum */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, Abits, ctx->minfo); /* unpack to get the min exponents of each variable */ min_degs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(min_degs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(min_degs, minAfields, ctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(M, 1, Abits, ctx); mpoly_set_monomial_ffmpz(M->exps, min_degs, Abits, ctx->minfo); _n_fq_one(M->coeffs + 0, fq_nmod_ctx_degree(ctx->fqctx)); _fq_nmod_mpoly_set_length(M, 1, ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(minAfields + i); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(min_degs + i); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/term_exp_fits.c000066400000000000000000000015461461254215100213070ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_nmod_mpoly.h" int fq_nmod_mpoly_term_exp_fits_ui(const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_ui(A->exps, A->bits, i, ctx->minfo); } int fq_nmod_mpoly_term_exp_fits_si(const fq_nmod_mpoly_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_si(A->exps, A->bits, i, ctx->minfo); } flint-3.1.3/src/fq_nmod_mpoly/test/000077500000000000000000000000001461254215100172445ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mpoly/test/main.c000066400000000000000000000103711461254215100203360ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-add_sub_fq_nmod.c" #include "t-cmp.c" #include "t-compose_fq_nmod_mpoly.c" #include "t-compose_fq_nmod_poly.c" #include "t-degree.c" #include "t-derivative.c" #include "t-div_monagan_pearce.c" #include "t-divrem_ideal_monagan_pearce.c" #include "t-divrem_monagan_pearce.c" #include "t-evaluate.c" #include "t-gcd_brown.c" #include "t-gcd.c" #include "t-gcd_cofactors.c" #include "t-gcd_hensel.c" #include "t-gcd_zippel2.c" #include "t-gcd_zippel.c" #include "t-gen.c" #include "t-get_coeff_vars_ui.c" #include "t-get_set_coeff.c" #include "t-get_set_coeff_fq_nmod_monomial.c" #include "t-get_set_is_fq_nmod.c" #include "t-get_set_str_pretty.c" #include "t-get_set_term_coeff_fq_nmod.c" #include "t-get_set_term_exp_fmpz.c" #include "t-get_set_term_exp_si.c" #include "t-get_set_term_exp_ui.c" #include "t-get_term.c" #include "t-get_term_monomial.c" #include "t-mpolyuu_divides.c" #include "t-mul_johnson.c" #include "t-push_term_fq_nmod_fmpz.c" #include "t-push_term_fq_nmod_ui.c" #include "t-quadratic_root.c" #include "t-repack_bits.c" #include "t-resize.c" #include "t-resultant_discriminant.c" #include "t-reverse.c" #include "t-scalar_addmul_fq_nmod.c" #include "t-scalar_mul_fq_nmod.c" #include "t-sort_terms.c" #include "t-sqrt.c" #include "t-total_degree.c" #include "t-univar.c" #include "t-univar_resultant.c" #include "t-used_vars.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_mpoly_add_sub), TEST_FUNCTION(fq_nmod_mpoly_add_sub_fq_nmod), TEST_FUNCTION(fq_nmod_mpoly_cmp), TEST_FUNCTION(fq_nmod_mpoly_compose_fq_nmod_mpoly), TEST_FUNCTION(fq_nmod_mpoly_compose_fq_nmod_poly), TEST_FUNCTION(fq_nmod_mpoly_degree), TEST_FUNCTION(fq_nmod_mpoly_derivative), TEST_FUNCTION(fq_nmod_mpoly_div_monagan_pearce), TEST_FUNCTION(fq_nmod_mpoly_divrem_ideal_monagan_pearce), TEST_FUNCTION(fq_nmod_mpoly_divrem_monagan_pearce), TEST_FUNCTION(fq_nmod_mpoly_evaluate), TEST_FUNCTION(fq_nmod_mpoly_gcd_brown), TEST_FUNCTION(fq_nmod_mpoly_gcd), TEST_FUNCTION(fq_nmod_mpoly_gcd_cofactors), TEST_FUNCTION(fq_nmod_mpoly_gcd_hensel), TEST_FUNCTION(fq_nmod_mpoly_gcd_zippel2), TEST_FUNCTION(fq_nmod_mpoly_gcd_zippel), TEST_FUNCTION(fq_nmod_mpoly_gen), TEST_FUNCTION(fq_nmod_mpoly_get_coeff_vars_ui), TEST_FUNCTION(fq_nmod_mpoly_get_set_coeff), TEST_FUNCTION(fq_nmod_mpoly_get_set_coeff_fq_nmod_monomial), TEST_FUNCTION(fq_nmod_mpoly_get_set_is_fq_nmod), TEST_FUNCTION(fq_nmod_mpoly_get_set_str_pretty), TEST_FUNCTION(fq_nmod_mpoly_get_set_term_coeff_fq_nmod), TEST_FUNCTION(fq_nmod_mpoly_get_set_term_exp_fmpz), TEST_FUNCTION(fq_nmod_mpoly_get_set_term_exp_si), TEST_FUNCTION(fq_nmod_mpoly_get_set_term_exp_ui), TEST_FUNCTION(fq_nmod_mpoly_get_term), TEST_FUNCTION(fq_nmod_mpoly_get_term_monomial), TEST_FUNCTION(fq_nmod_mpoly_mpolyuu_divides), TEST_FUNCTION(fq_nmod_mpoly_mul_johnson), TEST_FUNCTION(fq_nmod_mpoly_push_term_fq_nmod_fmpz), TEST_FUNCTION(fq_nmod_mpoly_push_term_fq_nmod_ui), TEST_FUNCTION(fq_nmod_mpoly_quadratic_root), TEST_FUNCTION(fq_nmod_mpoly_repack_bits), TEST_FUNCTION(fq_nmod_mpoly_resize), TEST_FUNCTION(fq_nmod_mpoly_resultant_discriminant), TEST_FUNCTION(fq_nmod_mpoly_reverse), TEST_FUNCTION(fq_nmod_mpoly_scalar_addmul_fq_nmod), TEST_FUNCTION(fq_nmod_mpoly_scalar_mul_fq_nmod), TEST_FUNCTION(fq_nmod_mpoly_sort_terms), TEST_FUNCTION(fq_nmod_mpoly_sqrt), TEST_FUNCTION(fq_nmod_mpoly_total_degree), TEST_FUNCTION(fq_nmod_mpoly_univar), TEST_FUNCTION(fq_nmod_mpoly_univar_resultant), TEST_FUNCTION(fq_nmod_mpoly_used_vars) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod_mpoly/test/t-add_sub.c000066400000000000000000000305441461254215100212600ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_add_sub, state) { int i, j, result; /* Check (f + g) - g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 1; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fq_nmod_mpoly_add(h, g, f, ctx); fq_nmod_mpoly_sub(k, h, g, ctx); result = fq_nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + g) - g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check f + g = g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fq_nmod_mpoly_add(h, f, g, ctx); fq_nmod_mpoly_add(k, g, f, ctx); result = fq_nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + g = g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check f - g = -g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fq_nmod_mpoly_sub(h, f, g, ctx); fq_nmod_mpoly_neg(k, g, ctx); fq_nmod_mpoly_add(k, k, f, ctx); result = fq_nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + g = g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check f + (g + h) = (f + g) + h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k1, ctx); fq_nmod_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); fq_nmod_mpoly_add(k1, f, g, ctx); fq_nmod_mpoly_add(k1, k1, h, ctx); fq_nmod_mpoly_add(k2, g, h, ctx); fq_nmod_mpoly_add(k2, k2, f, ctx); result = fq_nmod_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + (g + h) = (f + g) + h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k1, ctx); fq_nmod_mpoly_clear(k2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check f - (g + h) = (f - g) - h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k1, ctx); fq_nmod_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); fq_nmod_mpoly_add(k1, g, h, ctx); fq_nmod_mpoly_sub(k1, f, k1, ctx); fq_nmod_mpoly_sub(k2, f, g, ctx); fq_nmod_mpoly_sub(k2, k2, h, ctx); result = fq_nmod_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f - (g + h) = (f - g) - h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k1, ctx); fq_nmod_mpoly_clear(k2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first arg */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_set(h, f, ctx); fq_nmod_mpoly_add(f, f, g, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); fq_nmod_mpoly_sub(f, f, g, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); result = fq_nmod_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second arg */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); if ((j % 2) == 0) { fq_nmod_mpoly_add(h, g, f, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_add(f, g, f, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); } else { fq_nmod_mpoly_sub(h, g, f, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_sub(f, g, f, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); } result = fq_nmod_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-add_sub_fq_nmod.c000066400000000000000000000100031461254215100227470ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_add_sub_fq_nmod, state) { int i, j, result; /* Check (f + a) - a = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; fq_nmod_t c; slong len, exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_init(c, ctx->fqctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; for (j = 0; j < 10; j++) { fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_randtest(c, state, ctx->fqctx); fq_nmod_mpoly_add_fq_nmod(g, f, c, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); fq_nmod_mpoly_sub_fq_nmod(h, g, c, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); result = fq_nmod_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + a) - a = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; fq_nmod_t c; slong len, exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_init(c, ctx->fqctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; for (j = 0; j < 10; j++) { fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_set(g, f, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_randtest(c, state, ctx->fqctx); fq_nmod_mpoly_set_fq_nmod(h, c, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_add(h, f, h, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_add_fq_nmod(f, f, c, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); result = fq_nmod_mpoly_equal(f, h, ctx); fq_nmod_mpoly_set_fq_nmod(h, c, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_sub(h, f, h, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_sub_fq_nmod(f, f, c, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); result = result && fq_nmod_mpoly_equal(f, h, ctx); result = result && fq_nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-cmp.c000066400000000000000000000134641461254215100204400ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_cmp, state) { int result; slong i, j1, j2; /* check polynomial terms are in order */ for (i = 0; i < 10*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, mf, mg; slong len; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(mf, ctx); fq_nmod_mpoly_init(mg, ctx); len = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits = n_randint(state, exp_bits) + 2; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_repack_bits(g, f, f->bits + n_randint(state, FLINT_BITS), ctx); fq_nmod_mpoly_assert_canonical(f, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); for (j1 = 0; j1 < f->length; j1++) for (j2 = 0; j2 < g->length; j2++) { fq_nmod_mpoly_get_term_monomial(mf, f, j1, ctx); fq_nmod_mpoly_get_term_monomial(mg, g, j2, ctx); result = fq_nmod_mpoly_cmp(mf, mg, ctx); result = (result == 0 && j1 == j2) || (result == +1 && j1 < j2) || (result == -1 && j1 > j2); if (!result) { flint_printf("FAIL\n" "check polynomial terms are in order\n" "i = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(mf, ctx); fq_nmod_mpoly_clear(mg, ctx); fq_nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, c, aa, bb, cc; int a_a, a_b, a_c, a_aa, a_bb, a_cc; int b_a, b_b, b_c, b_aa, b_bb, b_cc; int c_a, c_b, c_c, c_aa, c_bb, c_cc; flint_bitcnt_t newbits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(c, ctx); fq_nmod_mpoly_init(aa, ctx); fq_nmod_mpoly_init(bb, ctx); fq_nmod_mpoly_init(cc, ctx); fq_nmod_mpoly_randtest_bits(a, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fq_nmod_mpoly_randtest_bits(b, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); fq_nmod_mpoly_randtest_bits(c, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(aa, a, newbits, ctx); newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(bb, b, newbits, ctx); newbits = c->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(cc, c, newbits, ctx); a_a = fq_nmod_mpoly_cmp(a, a, ctx); a_b = fq_nmod_mpoly_cmp(a, b, ctx); a_c = fq_nmod_mpoly_cmp(a, c, ctx); a_aa = fq_nmod_mpoly_cmp(a, aa, ctx); a_bb = fq_nmod_mpoly_cmp(a, bb, ctx); a_cc = fq_nmod_mpoly_cmp(a, cc, ctx); b_a = fq_nmod_mpoly_cmp(b, a, ctx); b_b = fq_nmod_mpoly_cmp(b, b, ctx); b_c = fq_nmod_mpoly_cmp(b, c, ctx); b_aa = fq_nmod_mpoly_cmp(b, aa, ctx); b_bb = fq_nmod_mpoly_cmp(b, bb, ctx); b_cc = fq_nmod_mpoly_cmp(b, cc, ctx); c_a = fq_nmod_mpoly_cmp(c, a, ctx); c_b = fq_nmod_mpoly_cmp(c, b, ctx); c_c = fq_nmod_mpoly_cmp(c, c, ctx); c_aa = fq_nmod_mpoly_cmp(c, aa, ctx); c_bb = fq_nmod_mpoly_cmp(c, bb, ctx); c_cc = fq_nmod_mpoly_cmp(c, cc, ctx); if (a_a != 0 || a_aa != 0 || b_b != 0 || b_bb != 0 || c_c != 0 || c_cc != 0) { flint_printf("FAIL\n" "check polynomial compares equal to itself\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if (a_b != a_bb || a_c != a_cc || b_a != b_aa || b_c != b_cc || c_a != c_aa || c_b != c_bb) { flint_printf("FAIL\n" "check polynomial comparison with differing bits\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if ((a_b*b_c == 0 && a_c != a_b + b_c) || (a_b*b_c > 0 && a_c != a_b)) { flint_printf("FAIL\n" "check transitivity\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(c, ctx); fq_nmod_mpoly_clear(aa, ctx); fq_nmod_mpoly_clear(bb, ctx); fq_nmod_mpoly_clear(cc, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-compose_fq_nmod_mpoly.c000066400000000000000000000403711461254215100242460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_compose_fq_nmod_mpoly, state) { slong i, j, v; { fq_nmod_mpoly_t A, A1, A2, B; fq_nmod_mpoly_struct * Cp[3]; fq_nmod_mpoly_struct C[3]; fq_nmod_mpoly_ctx_t ctxAC, ctxB; fq_nmod_mpoly_ctx_init_deg(ctxB, 3, ORD_LEX, 13, 3); fq_nmod_mpoly_ctx_init(ctxAC, 2, ORD_LEX, ctxB->fqctx); fq_nmod_mpoly_init(B, ctxB); fq_nmod_mpoly_init(A, ctxAC); fq_nmod_mpoly_init(A1, ctxAC); fq_nmod_mpoly_init(A2, ctxAC); for (i = 0; i < 3; i++) { Cp[i] = C + i; fq_nmod_mpoly_init(C + i, ctxAC); } fq_nmod_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB); fq_nmod_mpoly_set_str_pretty(C + 0, "x1 + x2", NULL, ctxAC); fq_nmod_mpoly_set_str_pretty(C + 1, "x1 - x2", NULL, ctxAC); fq_nmod_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (fq_nmod_mpoly_compose_fq_nmod_mpoly(A, B, Cp, ctxB, ctxAC) || fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set_str_pretty(C + 0, "x1", NULL, ctxAC); fq_nmod_mpoly_set_str_pretty(C + 1, "2*x2", NULL, ctxAC); fq_nmod_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (!fq_nmod_mpoly_compose_fq_nmod_mpoly(A, B, Cp, ctxB, ctxAC) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 2\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set_str_pretty(C + 0, "2*x1", NULL, ctxAC); fq_nmod_mpoly_set_str_pretty(C + 1, "x2", NULL, ctxAC); fq_nmod_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (!fq_nmod_mpoly_compose_fq_nmod_mpoly(A, B, Cp, ctxB, ctxAC) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check example 3\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(B, ctxB); fq_nmod_mpoly_clear(A, ctxAC); fq_nmod_mpoly_clear(A1, ctxAC); fq_nmod_mpoly_clear(A2, ctxAC); for (i = 0; i < 3; i++) fq_nmod_mpoly_clear(C + i, ctxAC); fq_nmod_mpoly_ctx_clear(ctxB); fq_nmod_mpoly_ctx_clear(ctxAC); } /* check composition with generators */ for (i = 0; i < 10*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctxB, ctxAC; fq_nmod_mpoly_t B, A, A1, A2, A3; fq_nmod_mpoly_struct ** C; slong * c; slong nvarsB, nvarsAC; slong len; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctxB, state, 5, FLINT_BITS, 3); fq_nmod_mpoly_ctx_init(ctxAC, n_randint(state, 5) + 1, mpoly_ordering_randtest(state), ctxB->fqctx); nvarsB = ctxB->minfo->nvars; nvarsAC = ctxAC->minfo->nvars; fq_nmod_mpoly_init(B, ctxB); fq_nmod_mpoly_init(A, ctxAC); fq_nmod_mpoly_init(A1, ctxAC); fq_nmod_mpoly_init(A2, ctxAC); fq_nmod_mpoly_init(A3, ctxAC); c = (slong *) flint_malloc(nvarsB*sizeof(slong)); C = (fq_nmod_mpoly_struct **) flint_malloc(nvarsB * sizeof(fq_nmod_mpoly_struct *)); for (v = 0; v < nvarsB; v++) { C[v] = (fq_nmod_mpoly_struct *) flint_malloc(sizeof(fq_nmod_mpoly_struct)); fq_nmod_mpoly_init(C[v], ctxAC); } for (j = 0; j < 4; j++) { len = n_randint(state, 200); exp_bits = n_randint(state, 100) + 1; for (v = 0; v < nvarsB; v++) { c[v] = n_randint(state, nvarsAC + 2) - 2; if (c[v] >= 0) fq_nmod_mpoly_gen(C[v], c[v], ctxAC); else fq_nmod_mpoly_zero(C[v], ctxAC); } fq_nmod_mpoly_randtest_bits(B, state, len, exp_bits, ctxB); fq_nmod_mpoly_compose_fq_nmod_mpoly_gen(A, B, c, ctxB, ctxAC); if (!fq_nmod_mpoly_compose_fq_nmod_mpoly(A1, B, C, ctxB, ctxAC) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(A2, B, C, ctxB, ctxAC) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(A3, B, C, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition success with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_equal(A, A1, ctxAC) || !fq_nmod_mpoly_equal(A, A2, ctxAC) || !fq_nmod_mpoly_equal(A, A3, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(A, ctxAC); fq_nmod_mpoly_assert_canonical(A1, ctxAC); fq_nmod_mpoly_assert_canonical(A2, ctxAC); fq_nmod_mpoly_assert_canonical(A3, ctxAC); } for (v = 0; v < nvarsB; v++) { fq_nmod_mpoly_clear(C[v], ctxAC); flint_free(C[v]); } flint_free(C); flint_free(c); fq_nmod_mpoly_clear(B, ctxB); fq_nmod_mpoly_clear(A, ctxAC); fq_nmod_mpoly_clear(A1, ctxAC); fq_nmod_mpoly_clear(A2, ctxAC); fq_nmod_mpoly_clear(A3, ctxAC); fq_nmod_mpoly_ctx_clear(ctxB); fq_nmod_mpoly_ctx_clear(ctxAC); } /* Check composition with identity */ for (i = 0; i < 10*flint_test_multiplier(); i++) { slong nvars, len, exp_bits; fq_nmod_mpoly_struct ** vals1; fq_nmod_mpoly_t f, g, g1, g2; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); nvars = ctx->minfo->nvars; vals1 = (fq_nmod_mpoly_struct **) flint_malloc(nvars*sizeof(fq_nmod_mpoly_struct *)); for (v = 0; v < nvars; v++) { vals1[v] = (fq_nmod_mpoly_struct *) flint_malloc(sizeof(fq_nmod_mpoly_struct)); fq_nmod_mpoly_init(vals1[v], ctx); fq_nmod_mpoly_gen(vals1[v], v, ctx); } fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(g1, ctx); fq_nmod_mpoly_init(g2, ctx); len = n_randint(state, 50); exp_bits = n_randint(state, 100) + 1; fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (!fq_nmod_mpoly_compose_fq_nmod_mpoly(g, f, vals1, ctx, ctx) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(g1, f, vals1, ctx, ctx) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(g2, f, vals1, ctx, ctx) || !fq_nmod_mpoly_equal(g, g1, ctx) || !fq_nmod_mpoly_equal(g, g2, ctx)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(g, ctx); fq_nmod_mpoly_assert_canonical(g1, ctx); fq_nmod_mpoly_assert_canonical(g2, ctx); if (!fq_nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check composition with identity\ni: %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(g1, ctx); fq_nmod_mpoly_clear(g2, ctx); for (v = 0; v < nvars; v++) { fq_nmod_mpoly_clear(vals1[v], ctx); flint_free(vals1[v]); } flint_free(vals1); fq_nmod_mpoly_ctx_clear(ctx); } /* Check composition and evalall commute */ for (i = 0; i < 40*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx1, ctx2; fq_nmod_mpoly_t f, g, g1, g2; fq_nmod_mpoly_struct ** vals1; fq_nmod_t fe, ge; fq_nmod_struct ** vals2, ** vals3; slong nvars1, nvars2; slong len1, len2; slong exp_bound1; flint_bitcnt_t exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx1, state, 3, FLINT_BITS, 10); fq_nmod_mpoly_ctx_init(ctx2, n_randint(state, 5) + 1, mpoly_ordering_randtest(state), ctx1->fqctx); nvars1 = ctx1->minfo->nvars; nvars2 = ctx2->minfo->nvars; fq_nmod_mpoly_init(f, ctx1); fq_nmod_mpoly_init(g, ctx2); fq_nmod_mpoly_init(g1, ctx2); fq_nmod_mpoly_init(g2, ctx2); fq_nmod_init(fe, ctx1->fqctx); fq_nmod_init(ge, ctx1->fqctx); len1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars1) + 1); len2 = n_randint(state, 10/FLINT_MAX(WORD(1), nvars2) + 1); exp_bound1 = n_randint(state, 10/FLINT_MAX(WORD(1), nvars1) + 1) + 1; exp_bits2 = n_randint(state, 100) + 1; fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx1); vals1 = (fq_nmod_mpoly_struct **) flint_malloc(nvars1 * sizeof(fq_nmod_mpoly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fq_nmod_mpoly_struct *) flint_malloc( sizeof(fq_nmod_mpoly_struct)); fq_nmod_mpoly_init(vals1[v], ctx2); fq_nmod_mpoly_randtest_bound(vals1[v], state, len2, exp_bits2, ctx2); } vals2 = (fq_nmod_struct **) flint_malloc(nvars2*sizeof(fq_nmod_struct*)); for (v = 0; v < nvars2; v++) { vals2[v] = (fq_nmod_struct *) flint_malloc(sizeof(fq_nmod_struct)); fq_nmod_init(vals2[v], ctx1->fqctx); fq_nmod_randtest(vals2[v], state, ctx1->fqctx); } vals3 = (fq_nmod_struct **) flint_malloc(nvars1*sizeof(fq_nmod_struct*)); for (v = 0; v < nvars1; v++) { vals3[v] = (fq_nmod_struct *) flint_malloc(sizeof(fq_nmod_struct)); fq_nmod_init(vals3[v], ctx1->fqctx); fq_nmod_mpoly_evaluate_all_fq_nmod(vals3[v], vals1[v], vals2, ctx2); } if (!fq_nmod_mpoly_compose_fq_nmod_mpoly(g, f, vals1, ctx1, ctx2) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(g1, f, vals1, ctx1, ctx2) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(g2, f, vals1, ctx1, ctx2) || !fq_nmod_mpoly_equal(g, g1, ctx2) || !fq_nmod_mpoly_equal(g, g2, ctx2)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(g, ctx2); fq_nmod_mpoly_assert_canonical(g1, ctx2); fq_nmod_mpoly_assert_canonical(g2, ctx2); fq_nmod_mpoly_evaluate_all_fq_nmod(fe, f, vals3, ctx1); fq_nmod_mpoly_evaluate_all_fq_nmod(ge, g, vals2, ctx2); if (!fq_nmod_equal(fe, ge, ctx1->fqctx)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } for (v = 0; v < nvars1; v++) { fq_nmod_mpoly_clear(vals1[v], ctx2); flint_free(vals1[v]); } flint_free(vals1); for (v = 0; v < nvars2; v++) { fq_nmod_clear(vals2[v], ctx1->fqctx); flint_free(vals2[v]); } flint_free(vals2); for (v = 0; v < nvars1; v++) { fq_nmod_clear(vals3[v], ctx1->fqctx); flint_free(vals3[v]); } flint_free(vals3); fq_nmod_clear(fe, ctx1->fqctx); fq_nmod_clear(ge, ctx2->fqctx); fq_nmod_mpoly_clear(f, ctx1); fq_nmod_mpoly_clear(g, ctx2); fq_nmod_mpoly_clear(g1, ctx2); fq_nmod_mpoly_clear(g2, ctx2); fq_nmod_mpoly_ctx_clear(ctx1); fq_nmod_mpoly_ctx_clear(ctx2); } /* Check composition with constants matches evalall */ for (i = 0; i < 10*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx1, ctx2; fq_nmod_mpoly_t f, g, g1, g2; fq_nmod_mpoly_struct ** vals1; fq_nmod_struct ** vals2; fq_nmod_t e1, e2; slong nvars1; slong len1; flint_bitcnt_t exp_bits1; fq_nmod_mpoly_ctx_init_rand(ctx1, state, 10, FLINT_BITS, 10); fq_nmod_mpoly_ctx_init(ctx2, n_randint(state, 10) + 1, mpoly_ordering_randtest(state), ctx1->fqctx); nvars1 = ctx1->minfo->nvars; fq_nmod_init(e1, ctx1->fqctx); fq_nmod_init(e2, ctx1->fqctx); fq_nmod_mpoly_init(f, ctx1); fq_nmod_mpoly_init(g, ctx2); fq_nmod_mpoly_init(g1, ctx2); fq_nmod_mpoly_init(g2, ctx2); len1 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 1; fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx1); vals1 = (fq_nmod_mpoly_struct **) flint_malloc(nvars1 * sizeof(fq_nmod_mpoly_struct *)); vals2 = (fq_nmod_struct **) flint_malloc(nvars1*sizeof(fq_nmod_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fq_nmod_mpoly_struct *) flint_malloc( sizeof(fq_nmod_mpoly_struct)); fq_nmod_mpoly_init(vals1[v], ctx2); vals2[v] = (fq_nmod_struct *) flint_malloc(sizeof(fq_nmod_struct)); fq_nmod_init(vals2[v], ctx1->fqctx); fq_nmod_randtest(vals2[v], state, ctx1->fqctx); fq_nmod_mpoly_set_fq_nmod(vals1[v], vals2[v], ctx2); } if (!fq_nmod_mpoly_compose_fq_nmod_mpoly(g, f, vals1, ctx1, ctx2) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_geobucket(g1, f, vals1, ctx1, ctx2) || !fq_nmod_mpoly_compose_fq_nmod_mpoly_horner(g2, f, vals1, ctx1, ctx2)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(g, ctx2); fq_nmod_mpoly_assert_canonical(g1, ctx2); fq_nmod_mpoly_assert_canonical(g2, ctx2); fq_nmod_mpoly_evaluate_all_fq_nmod(e2, f, vals2, ctx1); if (!fq_nmod_mpoly_is_fq_nmod(g, ctx2) || (fq_nmod_mpoly_get_fq_nmod(e1, g, ctx2), !fq_nmod_equal(e1, e2, ctx1->fqctx))) { printf("FAIL\n"); flint_printf("Check composition with constants matches evalall\ni: %wd\n", i); fflush(stdout); flint_abort(); } for (v = 0; v < nvars1; v++) { fq_nmod_mpoly_clear(vals1[v], ctx2); flint_free(vals1[v]); fq_nmod_clear(vals2[v], ctx1->fqctx); flint_free(vals2[v]); } flint_free(vals1); flint_free(vals2); fq_nmod_clear(e1, ctx1->fqctx); fq_nmod_clear(e2, ctx1->fqctx); fq_nmod_mpoly_clear(f, ctx1); fq_nmod_mpoly_clear(g, ctx2); fq_nmod_mpoly_clear(g1, ctx2); fq_nmod_mpoly_clear(g2, ctx2); fq_nmod_mpoly_ctx_clear(ctx1); fq_nmod_mpoly_ctx_clear(ctx2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-compose_fq_nmod_poly.c000066400000000000000000000134151461254215100240700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_compose_fq_nmod_poly, state) { slong i, v; { fq_nmod_poly_t A; fq_nmod_mpoly_t B; fq_nmod_poly_struct * Cp[3]; fq_nmod_poly_struct C[3]; fq_nmod_mpoly_ctx_t ctxB; fmpz one = 1, two = 2, three = 3; fq_nmod_mpoly_ctx_init_deg(ctxB, 3, ORD_LEX, 13, 3); fq_nmod_mpoly_init(B, ctxB); fq_nmod_poly_init(A, ctxB->fqctx); for (i = 0; i < 3; i++) { Cp[i] = C + i; fq_nmod_poly_init(C + i, ctxB->fqctx); } fq_nmod_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB); fq_nmod_poly_zero(C + 0, ctxB->fqctx); fq_nmod_poly_zero(C + 1, ctxB->fqctx); fq_nmod_poly_zero(C + 2, ctxB->fqctx); fq_nmod_poly_set_coeff_fmpz(C + 0, 1, &one, ctxB->fqctx); fq_nmod_poly_set_coeff_fmpz(C + 1, 2, &two, ctxB->fqctx); fq_nmod_poly_set_coeff_fmpz(C + 2, 3, &three, ctxB->fqctx); if (fq_nmod_mpoly_compose_fq_nmod_poly(A, B, Cp, ctxB)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } fq_nmod_poly_zero(C + 0, ctxB->fqctx); fq_nmod_poly_zero(C + 1, ctxB->fqctx); fq_nmod_poly_zero(C + 2, ctxB->fqctx); fq_nmod_poly_set_coeff_fmpz(C + 0, 0, &one, ctxB->fqctx); fq_nmod_poly_set_coeff_fmpz(C + 1, 0, &two, ctxB->fqctx); fq_nmod_poly_set_coeff_fmpz(C + 2, 0, &three, ctxB->fqctx); if (!fq_nmod_mpoly_compose_fq_nmod_poly(A, B, Cp, ctxB)) { printf("FAIL\n"); flint_printf("Check example 2\n", i); fflush(stdout); flint_abort(); } if (!fq_nmod_poly_is_zero(A, ctxB->fqctx)) { printf("FAIL\n"); flint_printf("Check example 2 equality\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(B, ctxB); fq_nmod_poly_clear(A, ctxB->fqctx); for (i = 0; i < 3; i++) fq_nmod_poly_clear(C + i, ctxB->fqctx); fq_nmod_mpoly_ctx_clear(ctxB); } /* Check composition and evalall commute */ for (i = 0; i < 20*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; fq_nmod_poly_t g; fq_nmod_poly_struct ** vals1; fq_nmod_t fe, ge; fq_nmod_t vals2; fq_nmod_struct ** vals3; slong nvars1; slong len1, len2; slong exp_bound1; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); nvars1 = ctx->minfo->nvars; fq_nmod_mpoly_init(f, ctx); fq_nmod_poly_init(g, ctx->fqctx); fq_nmod_init(fe, ctx->fqctx); fq_nmod_init(ge, ctx->fqctx); len1 = n_randint(state, 40/FLINT_MAX(WORD(1), nvars1) + 1); len2 = n_randint(state, 20); exp_bound1 = n_randint(state, 100/FLINT_MAX(WORD(1), nvars1) + 2) + 1; fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); vals1 = (fq_nmod_poly_struct **) flint_malloc(nvars1* sizeof(fq_nmod_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (fq_nmod_poly_struct *) flint_malloc( sizeof(fq_nmod_poly_struct)); fq_nmod_poly_init(vals1[v], ctx->fqctx); fq_nmod_poly_randtest(vals1[v], state, len2, ctx->fqctx); } fq_nmod_init(vals2, ctx->fqctx); fq_nmod_randtest(vals2, state, ctx->fqctx); vals3 = (fq_nmod_struct **) flint_malloc(nvars1*sizeof(fq_nmod_struct *)); for (v = 0; v < nvars1; v++) { vals3[v] = (fq_nmod_struct *) flint_malloc(sizeof(fq_nmod_struct)); fq_nmod_init(vals3[v], ctx->fqctx); fq_nmod_poly_evaluate_fq_nmod(vals3[v], vals1[v], vals2, ctx->fqctx); } if (fq_nmod_mpoly_total_degree_si(f, ctx) < 50) { if (!fq_nmod_mpoly_compose_fq_nmod_poly(g, f, vals1, ctx)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_evaluate_all_fq_nmod(fe, f, vals3, ctx); fq_nmod_poly_evaluate_fq_nmod(ge, g, vals2, ctx->fqctx); if (!fq_nmod_equal(fe, ge, ctx->fqctx)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars1; v++) { fq_nmod_poly_clear(vals1[v], ctx->fqctx); flint_free(vals1[v]); } flint_free(vals1); fq_nmod_clear(vals2, ctx->fqctx); for (v = 0; v < nvars1; v++) { fq_nmod_clear(vals3[v], ctx->fqctx); flint_free(vals3[v]); } flint_free(vals3); fq_nmod_mpoly_clear(f, ctx); fq_nmod_poly_clear(g, ctx->fqctx); fq_nmod_clear(fe, ctx->fqctx); fq_nmod_clear(ge, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-degree.c000066400000000000000000000143031461254215100211050ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_nmod_mpoly.h" /* check various degree operations */ void _check_degrees(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; int fits_si; fmpz ** degs; slong * degs_si; slong nvars = ctx->minfo->nvars; degs = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); for (i = 0; i < nvars; i++) { degs[i] = flint_malloc(sizeof(fmpz)); fmpz_init(degs[i]); } fq_nmod_mpoly_degrees_fmpz(degs, A, ctx); fits_si = 1; for (i = 0; i < nvars; i++) { fits_si = fits_si && fmpz_fits_si(degs[i]); } if (fits_si != fq_nmod_mpoly_degrees_fit_si(A, ctx)) { printf("FAIL\n"); flint_printf("Check degrees_fit_si\n"); fflush(stdout); flint_abort(); } if (fits_si) { degs_si = (slong *) flint_malloc(nvars*sizeof(slong)); fq_nmod_mpoly_degrees_si(degs_si, A, ctx); for (i = 0; i < nvars; i++) { if (degs_si[i] != fmpz_get_si(degs[i])) { printf("FAIL\n"); flint_printf("Check degrees_si\n"); fflush(stdout); flint_abort(); } if (degs_si[i] != fq_nmod_mpoly_degree_si(A, i, ctx)) { printf("FAIL\n"); flint_printf("Check individual degree_si\n"); fflush(stdout); flint_abort(); } } flint_free(degs_si); } for (i = 0; i < nvars; i++) { fmpz_t degi; fmpz_init(degi); fq_nmod_mpoly_degree_fmpz(degi, A, i, ctx); if (!fmpz_equal(degi, degs[i])) { printf("FAIL\n"); flint_printf("Check individual degree_fmpz\n"); fflush(stdout); flint_abort(); } fmpz_clear(degi); } for (i = 0; i < nvars; i++) { fmpz_clear(degs[i]); flint_free(degs[i]); } flint_free(degs); } TEST_FUNCTION_START(fq_nmod_mpoly_degree, state) { int i, j; /* Check degree does not go up under addition */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < ctx->minfo->nvars; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_add(h, f, g, ctx); _check_degrees(h, ctx); _check_degrees(f, ctx); _check_degrees(g, ctx); fq_nmod_mpoly_degree_fmpz(hdeg, h, j, ctx); fq_nmod_mpoly_degree_fmpz(fdeg, f, j, ctx); fq_nmod_mpoly_degree_fmpz(gdeg, g, j, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check degree adds under multiplication */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { int ok; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < ctx->minfo->nvars; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_mul(h, f, g, ctx); _check_degrees(h, ctx); _check_degrees(f, ctx); _check_degrees(g, ctx); fq_nmod_mpoly_degree_fmpz(hdeg, h, j, ctx); fq_nmod_mpoly_degree_fmpz(fdeg, f, j, ctx); fq_nmod_mpoly_degree_fmpz(gdeg, g, j, ctx); if (fq_nmod_mpoly_is_zero(g, ctx) || fq_nmod_mpoly_is_zero(f, ctx)) { ok = (fmpz_cmp_si(hdeg, -WORD(1)) == 0); } else { fmpz_sub(hdeg, hdeg, fdeg); ok = (fmpz_cmp(hdeg, gdeg) == 0); } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-derivative.c000066400000000000000000000144761461254215100220270ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_derivative, state) { int i, j, result; slong tmul = 5; /* Check d(f*g) = df*g + f*dg */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, fp, gp, hp, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; slong idx; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); if (fq_nmod_mpoly_ctx_nvars(ctx) < 1) { fq_nmod_mpoly_ctx_clear(ctx); continue; } fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(fp, ctx); fq_nmod_mpoly_init(gp, ctx); fq_nmod_mpoly_init(hp, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; fq_nmod_mpoly_randtest_bits(hp, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(fp, state, len, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(gp, state, len, exp_bits2, ctx); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); idx = n_randint(state, fq_nmod_mpoly_ctx_nvars(ctx)); fq_nmod_mpoly_mul(h, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_derivative(hp, h, idx, ctx); fq_nmod_mpoly_assert_canonical(hp, ctx); fq_nmod_mpoly_derivative(fp, f, idx, ctx); fq_nmod_mpoly_assert_canonical(fp, ctx); fq_nmod_mpoly_derivative(gp, g, idx, ctx); fq_nmod_mpoly_assert_canonical(gp, ctx); fq_nmod_mpoly_mul(t1, f, gp, ctx); fq_nmod_mpoly_assert_canonical(t1, ctx); fq_nmod_mpoly_mul(t2, g, fp, ctx); fq_nmod_mpoly_assert_canonical(t2, ctx); fq_nmod_mpoly_add(t1, t1, t2, ctx); fq_nmod_mpoly_assert_canonical(t1, ctx); result = fq_nmod_mpoly_equal(hp, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(fp, ctx); fq_nmod_mpoly_clear(gp, ctx); fq_nmod_mpoly_clear(hp, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check d(f*g) = df*g + f*dg with aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, fp, gp, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; slong idx; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 2); if (fq_nmod_mpoly_ctx_nvars(ctx) < 1) { fq_nmod_mpoly_ctx_clear(ctx); continue; } fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(fp, ctx); fq_nmod_mpoly_init(gp, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(fp, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(gp, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); idx = n_randint(state, fq_nmod_mpoly_ctx_nvars(ctx)); fq_nmod_mpoly_mul(h, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_derivative(h, h, idx, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_set(fp, f, ctx); fq_nmod_mpoly_derivative(fp, fp, idx, ctx); fq_nmod_mpoly_assert_canonical(fp, ctx); fq_nmod_mpoly_set(gp, g, ctx); fq_nmod_mpoly_derivative(gp, gp, idx, ctx); fq_nmod_mpoly_assert_canonical(gp, ctx); fq_nmod_mpoly_mul(t1, f, gp, ctx); fq_nmod_mpoly_assert_canonical(t1, ctx); fq_nmod_mpoly_mul(t2, g, fp, ctx); fq_nmod_mpoly_assert_canonical(t2, ctx); fq_nmod_mpoly_add(t1, t1, t2, ctx); fq_nmod_mpoly_assert_canonical(t1, ctx); result = fq_nmod_mpoly_equal(h, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(fp, ctx); fq_nmod_mpoly_clear(gp, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000152161461254215100234570ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_div_monagan_pearce, state) { int i, j, result; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k, l; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_mpoly_init(l, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(l, state, len, exp_bits, ctx); fq_nmod_mpoly_mul(h, f, g, ctx); fq_nmod_mpoly_div_monagan_pearce(k, h, g, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); result = fq_nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(l, h, ctx); fq_nmod_mpoly_div_monagan_pearce(l, l, g, ctx); fq_nmod_mpoly_assert_canonical(l, ctx); result = fq_nmod_mpoly_equal(l, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing dividend\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_div_monagan_pearce(g, h, g, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); result = fq_nmod_mpoly_equal(g, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing divisor\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_clear(l, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check div matches divrem for random polys */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, q, r, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(q, ctx); fq_nmod_mpoly_init(r, ctx); fq_nmod_mpoly_init(k, ctx); len = n_randint(state, 10); len1 = n_randint(state, 15); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 100/n) + 1; exp_bound1 = n_randint(state, 100/n) + 1; exp_bound2 = n_randint(state, 100/n) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bound(q, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fq_nmod_mpoly_divrem_monagan_pearce(q, r, f, g, ctx); fq_nmod_mpoly_assert_canonical(q, ctx); fq_nmod_mpoly_assert_canonical(r, ctx); fq_nmod_mpoly_remainder_strongtest(r, g, ctx); fq_nmod_mpoly_mul_johnson(k, q, g, ctx); fq_nmod_mpoly_add(k, k, r, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); result = fq_nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_div_monagan_pearce(k, f, g, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); result = fq_nmod_mpoly_equal(k, q, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check div matches divrem\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(k, f, ctx); fq_nmod_mpoly_div_monagan_pearce(k, k, g, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); result = fq_nmod_mpoly_equal(k, q, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check div matches divrem aliasing dividend\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_div_monagan_pearce(g, f, g, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); result = fq_nmod_mpoly_equal(g, q, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check div matches divrem aliasing divisor\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_clear(r, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000220061461254215100253140ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_divrem_ideal_monagan_pearce, state) { int result; slong i, j, w; /* Check f*g/g = f */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k, r; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_struct * qarr[1], * darr[1]; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_mpoly_init(r, ctx); len = n_randint(state, 30); len1 = n_randint(state, 30); len2 = n_randint(state, 30) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2 + 1, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(r, state, len, exp_bits, ctx); fq_nmod_mpoly_mul_johnson(h, f, g, ctx); qarr[0] = k; darr[0] = g; fq_nmod_mpoly_divrem_ideal_monagan_pearce(qarr, r, h, darr, 1, ctx); fq_nmod_mpoly_assert_canonical(qarr[0], ctx); fq_nmod_mpoly_assert_canonical(r, ctx); result = fq_nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_clear(r, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check f = g1*q1 + ... + gn*qn + r for random polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, r, k1, k2; fq_nmod_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; fq_nmod_mpoly_struct * qarr[5], * darr[5]; slong n; num = n_randint(state, 5) + 1; g = (fq_nmod_mpoly_struct *) flint_malloc(num*sizeof(fq_nmod_mpoly_struct)); q = (fq_nmod_mpoly_struct *) flint_malloc(num*sizeof(fq_nmod_mpoly_struct)); fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); for (w = 0; w < num; w++) { fq_nmod_mpoly_init(g + w, ctx); darr[w] = g + w; fq_nmod_mpoly_init(q + w, ctx); qarr[w] = q + w; } fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(k1, ctx); fq_nmod_mpoly_init(k2, ctx); fq_nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 10/n + 1) + 2; exp_bound1 = n_randint(state, 25/n + 1) + 2; exp_bound2 = n_randint(state, 20/n + 1) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); for (w = 0; w < num; w++) { fq_nmod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (fq_nmod_mpoly_is_zero(darr[w], ctx)) fq_nmod_mpoly_one(darr[w], ctx); fq_nmod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } fq_nmod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); fq_nmod_mpoly_divrem_ideal_monagan_pearce(qarr, r, f, darr, num, ctx); fq_nmod_mpoly_assert_canonical(r, ctx); for (w = 0; w < num; w++) { fq_nmod_mpoly_assert_canonical(qarr[w], ctx); fq_nmod_mpoly_remainder_strongtest(r, darr[w], ctx); } fq_nmod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { fq_nmod_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fq_nmod_mpoly_add(k2, k2, k1, ctx); } fq_nmod_mpoly_add(k2, k2, r, ctx); result = fq_nmod_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g1*q1 + ... + gn*qn + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) fq_nmod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fq_nmod_mpoly_clear(darr[w], ctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(k1, ctx); fq_nmod_mpoly_clear(k2, ctx); fq_nmod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, r, k1, k2; fq_nmod_mpoly_struct * g, * q; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; fq_nmod_mpoly_struct * qarr[5], * darr[5]; slong n; num = n_randint(state, 5) + 1; g = (fq_nmod_mpoly_struct *) flint_malloc(num*sizeof(fq_nmod_mpoly_struct)); q = (fq_nmod_mpoly_struct *) flint_malloc(num*sizeof(fq_nmod_mpoly_struct)); fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); for (w = 0; w < num; w++) { fq_nmod_mpoly_init(g + w, ctx); darr[w] = g + w; fq_nmod_mpoly_init(q + w, ctx); qarr[w] = q + w; } fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(k1, ctx); fq_nmod_mpoly_init(k2, ctx); fq_nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 10/n + 1) + 2; exp_bound1 = n_randint(state, 25/n + 1) + 2; exp_bound2 = n_randint(state, 20/n + 1) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); for (w = 0; w < num; w++) { fq_nmod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (fq_nmod_mpoly_is_zero(darr[w], ctx)) fq_nmod_mpoly_one(darr[w], ctx); fq_nmod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } fq_nmod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); fq_nmod_mpoly_set(r, f, ctx); fq_nmod_mpoly_divrem_ideal_monagan_pearce(qarr, f, f, darr, num, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); for (w = 0; w < num; w++) { fq_nmod_mpoly_assert_canonical(qarr[w], ctx); fq_nmod_mpoly_remainder_strongtest(f, darr[w], ctx); } fq_nmod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { fq_nmod_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); fq_nmod_mpoly_add(k2, k2, k1, ctx); } fq_nmod_mpoly_add(k2, k2, f, ctx); result = fq_nmod_mpoly_equal(r, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) fq_nmod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) fq_nmod_mpoly_clear(darr[w], ctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(k1, ctx); fq_nmod_mpoly_clear(k2, ctx); fq_nmod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-divrem_monagan_pearce.c000066400000000000000000000341431461254215100241630ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_divrem_monagan_pearce, state) { int result; slong i, j, tmul = 10; /* Check f*g/g = f */ for (i = 0; i < 5 * tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k, r; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_mpoly_init(r, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(r, state, len, exp_bits, ctx); fq_nmod_mpoly_mul_johnson(h, f, g, ctx); fq_nmod_mpoly_divrem_monagan_pearce(k, r, h, g, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); fq_nmod_mpoly_assert_canonical(r, ctx); result = fq_nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_clear(r, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check f = g*q + r for random polys */ for (i = 0; i < 5 * tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k, r; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 15); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fq_nmod_mpoly_divrem_monagan_pearce(h, r, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_assert_canonical(r, ctx); fq_nmod_mpoly_remainder_strongtest(r, g, ctx); fq_nmod_mpoly_mul_johnson(k, h, g, ctx); fq_nmod_mpoly_add(k, k, r, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); result = fq_nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_clear(r, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, r1, r2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(r1, ctx); fq_nmod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); fq_nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_assert_canonical(r1, ctx); fq_nmod_mpoly_remainder_strongtest(r1, g, ctx); fq_nmod_mpoly_divrem_monagan_pearce(f, r2, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_assert_canonical(r2, ctx); fq_nmod_mpoly_remainder_strongtest(r2, g, ctx); result = fq_nmod_mpoly_equal(h, f, ctx) && fq_nmod_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(r1, ctx); fq_nmod_mpoly_clear(r2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, r1, r2; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(r1, ctx); fq_nmod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); fq_nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_assert_canonical(r1, ctx); fq_nmod_mpoly_remainder_strongtest(r1, g, ctx); fq_nmod_mpoly_divrem_monagan_pearce(g, r2, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_assert_canonical(r2, ctx); result = fq_nmod_mpoly_equal(h, g, ctx) && fq_nmod_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(r1, ctx); fq_nmod_mpoly_clear(r2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k, r1; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 15); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fq_nmod_mpoly_mul_johnson(h, f, g, ctx); fq_nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_assert_canonical(r1, ctx); fq_nmod_mpoly_remainder_strongtest(r1, g, ctx); fq_nmod_mpoly_divrem_monagan_pearce(k, f, f, g, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); fq_nmod_mpoly_remainder_strongtest(f, g, ctx); result = fq_nmod_mpoly_equal(h, k, ctx) && fq_nmod_mpoly_equal(r1, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_clear(r1, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k, r1; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 15); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); fq_nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); fq_nmod_mpoly_mul_johnson(h, f, g, ctx); fq_nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_assert_canonical(r1, ctx); fq_nmod_mpoly_remainder_strongtest(r1, g, ctx); fq_nmod_mpoly_divrem_monagan_pearce(k, g, f, g, ctx); fq_nmod_mpoly_assert_canonical(k, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); result = fq_nmod_mpoly_equal(h, k, ctx) && fq_nmod_mpoly_equal(r1, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_clear(r1, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-evaluate.c000066400000000000000000000177301461254215100214670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_evaluate, state) { slong i, j, v; slong tmul = 5; /* Check repeated evalone matches evalall */ for (i = 0; i < 2*tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g; fq_nmod_t fe; fq_nmod_struct ** vals; slong * perm; slong nvars, len; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); nvars = ctx->minfo->nvars; fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_init(fe, ctx->fqctx); len = n_randint(state, 50); exp_bits = n_randint(state, 200) + 1; perm = (slong *) flint_malloc(nvars*sizeof(slong)); vals = (fq_nmod_struct **) flint_malloc(nvars*sizeof(fq_nmod_struct *)); for (v = 0; v < nvars; v++) { vals[v] = (fq_nmod_struct *) flint_malloc(sizeof(fq_nmod_struct)); fq_nmod_init(vals[v], ctx->fqctx); fq_nmod_randtest(vals[v], state, ctx->fqctx); perm[v] = v; } for (j = 0; j < 2*nvars; j++) { slong a, b, c; a = n_randint(state, nvars); b = n_randint(state, nvars); c = perm[a]; perm[a] = perm[b]; perm[b] = c; } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_evaluate_all_fq_nmod(fe, f, vals, ctx); for (v = 0; v < nvars; v++) { fq_nmod_mpoly_evaluate_one_fq_nmod(g, f, perm[v], vals[perm[v]], ctx); fq_nmod_mpoly_assert_canonical(g, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(f, f, perm[v], vals[perm[v]], ctx); fq_nmod_mpoly_assert_canonical(f, ctx); if (!fq_nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check evalone aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } if (!fq_nmod_mpoly_equal_fq_nmod(f, fe, ctx)) { flint_printf("FAIL\n"); flint_printf("Check repeated evalone matches evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < ctx->minfo->nvars; v++) { fq_nmod_clear(vals[v], ctx->fqctx); flint_free(vals[v]); } flint_free(vals); fq_nmod_clear(fe, ctx->fqctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); flint_free(perm); } /* Check add commutes with evalall */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, fg; fq_nmod_t fe, ge, te, fge; fq_nmod_struct ** vals; slong nvars, len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); nvars = ctx->minfo->nvars; fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(fg, ctx); fq_nmod_init(fe, ctx->fqctx); fq_nmod_init(ge, ctx->fqctx); fq_nmod_init(te, ctx->fqctx); fq_nmod_init(fge, ctx->fqctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 80) + 1; exp_bits2 = n_randint(state, 80) + 1; vals = (fq_nmod_struct **) flint_malloc(nvars*sizeof(fq_nmod_struct *)); for (v = 0; v < nvars; v++) { vals[v] = (fq_nmod_struct *) flint_malloc(sizeof(fq_nmod_struct)); fq_nmod_init(vals[v], ctx->fqctx); fq_nmod_randtest(vals[v], state, ctx->fqctx); } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_add(fg, f, g, ctx); fq_nmod_mpoly_evaluate_all_fq_nmod(fe, f, vals, ctx); fq_nmod_mpoly_evaluate_all_fq_nmod(ge, g, vals, ctx); fq_nmod_mpoly_evaluate_all_fq_nmod(fge, fg, vals, ctx); fq_nmod_add(te, fe, ge, ctx->fqctx); if (!fq_nmod_equal(fge, te, ctx->fqctx)) { flint_printf("FAIL\n"); flint_printf("Check add commutes with evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fq_nmod_clear(vals[v], ctx->fqctx); flint_free(vals[v]); } flint_free(vals); fq_nmod_clear(fe, ctx->fqctx); fq_nmod_clear(ge, ctx->fqctx); fq_nmod_clear(te, ctx->fqctx); fq_nmod_clear(fge, ctx->fqctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(fg, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check mul commutes with evalall */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, fg; fq_nmod_t fe, ge, te, fge; fq_nmod_struct ** vals; slong nvars, len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); nvars = ctx->minfo->nvars; fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(fg, ctx); fq_nmod_init(fe, ctx->fqctx); fq_nmod_init(ge, ctx->fqctx); fq_nmod_init(te, ctx->fqctx); fq_nmod_init(fge, ctx->fqctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); exp_bits1 = n_randint(state, 70) + 1; exp_bits2 = n_randint(state, 70) + 1; vals = (fq_nmod_struct **) flint_malloc(nvars*sizeof(fq_nmod_struct *)); for (v = 0; v < nvars; v++) { vals[v] = (fq_nmod_struct *) flint_malloc(sizeof(fq_nmod_struct)); fq_nmod_init(vals[v], ctx->fqctx); fq_nmod_randtest(vals[v], state, ctx->fqctx); } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_mul(fg, f, g, ctx); fq_nmod_mpoly_evaluate_all_fq_nmod(fe, f, vals, ctx); fq_nmod_mpoly_evaluate_all_fq_nmod(ge, g, vals, ctx); fq_nmod_mpoly_evaluate_all_fq_nmod(fge, fg, vals, ctx); fq_nmod_mul(te, fe, ge, ctx->fqctx); if (!fq_nmod_equal(fge, te, ctx->fqctx)) { flint_printf("FAIL\n"); flint_printf("Check add commutes with evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars; v++) { fq_nmod_clear(vals[v], ctx->fqctx); flint_free(vals[v]); } flint_free(vals); fq_nmod_clear(fe, ctx->fqctx); fq_nmod_clear(ge, ctx->fqctx); fq_nmod_clear(te, ctx->fqctx); fq_nmod_clear(fge, ctx->fqctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(fg, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-gcd.c000066400000000000000000000540511461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c, t-gcd_zippel.c */ #define gcd_check gcd_check_gcd void gcd_check( fq_nmod_mpoly_t g, fq_nmod_mpoly_t a, fq_nmod_mpoly_t b, const fq_nmod_mpoly_t gdiv, const fq_nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fq_nmod_mpoly_t ca, cb, cg; fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); res = fq_nmod_mpoly_gcd(g, a, b, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_zero(gdiv, ctx)) { if (!fq_nmod_mpoly_divides(ca, g, gdiv, ctx)) { printf("FAIL\n"); flint_printf("Check divisor of gcd\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fq_nmod_mpoly_is_zero(g, ctx)) { if (!fq_nmod_mpoly_is_zero(a, ctx) || !fq_nmod_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fq_nmod_mpoly_is_monic(g, ctx)) { printf("FAIL\n"); flint_printf("Check gcd leading coefficient is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fq_nmod_mpoly_divides(ca, a, g, ctx); res = res && fq_nmod_mpoly_divides(cb, b, g, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check divisibility\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = fq_nmod_mpoly_gcd(cg, ca, cb, ctx); fq_nmod_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_gcd, state) { slong i, j, k, tmul = 7; /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(t, state, 1, exp_bits, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(b, state, len2, exp_bits2, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); gcd_check(g, a, b, t, ctx, i, j, "monomial"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t1, t2; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(t1, state, 1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(t2, state, 1, exp_bits2, ctx); if (t1->length != 1 || t2->length != 1) { flint_printf("FAIL:\ncheck random monomial generation\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); fq_nmod_mpoly_mul(b, a, t1, ctx); fq_nmod_mpoly_mul(t2, a, t2, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); gcd_check(g, t2, b, a, ctx, i, j, "monomial cofactors"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_t c; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_init(c, ctx->fqctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t1, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(t2, state, len2, exp_bound2, ctx); fq_nmod_mpoly_mul(b, t1, t2, ctx); fq_nmod_randtest_not_zero(c, state, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(a, t2, c, ctx); fq_nmod_randtest_not_zero(c, state, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(b, b, c, ctx); fq_nmod_mpoly_randtest_bound(g, state, len, exp_bound, ctx); if ((j%2) == 0) fq_nmod_mpoly_swap(a, b, ctx); gcd_check(g, a, b, t2, ctx, i, j, "one input divides the other"); } fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fq_nmod_mpoly_ctx_init_rand(ctx, state, 7, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 30/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse inputs"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len, len1, len2; slong degbound; fq_nmod_mpoly_ctx_init_rand(ctx, state, 7, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 30/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(b, b, newbits, ctx); } fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse input with repacking"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; fq_nmod_mpoly_ctx_init_rand(ctx, state, 7, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 30/(2*ctx->minfo->nvars - 1); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fq_nmod_mpoly_inflate(a, a, shifts1, strides, ctx); fq_nmod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fq_nmod_mpoly_inflate(t, t, shifts1, strides, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len1 = n_randint(state, 200) + 1; len2 = n_randint(state, 200); len3 = n_randint(state, 200); len4 = n_randint(state, 200); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); gcd_check(g, a, b, t, ctx, i, j, "dense input"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len1 = n_randint(state, 200) + 1; len2 = n_randint(state, 200); len3 = n_randint(state, 200); len4 = n_randint(state, 200); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 16/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 16/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 16/ctx->minfo->nvars); } bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(b, b, newbits, ctx); } fq_nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); gcd_check(g, a, b, t, ctx, i, j, "dense input with repacking"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len1 = n_randint(state, 200) + 1; len2 = n_randint(state, 200); len3 = n_randint(state, 200); len4 = n_randint(state, 200); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 15/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); } bits4 = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fq_nmod_mpoly_inflate(a, a, shifts1, strides, ctx); fq_nmod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fq_nmod_mpoly_inflate(t, t, shifts1, strides, ctx); gcd_check(g, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fq_nmod_mpoly/test/t-gcd_brown.c000066400000000000000000000107131461254215100216170ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c, t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_brown void gcd_check( fq_nmod_mpoly_t g, fq_nmod_mpoly_t a, fq_nmod_mpoly_t b, fq_nmod_mpoly_t t, fq_nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fq_nmod_mpoly_t ca, cb, cg; fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); if (!fq_nmod_mpoly_gcd_brown(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(g, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) { if (!fq_nmod_mpoly_is_zero(a, ctx) || !fq_nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fq_nmod_mpoly_is_monic(g, ctx)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_zero(t, ctx) && !fq_nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_divides(ca, a, g, ctx) || !fq_nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_gcd_brown(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(cg, ctx); if (!fq_nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_gcd_brown, state) { slong i, j; for (i = 0; i < 5*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, t, g; slong len, len1, len2; slong n, degbound; flint_bitcnt_t pbits; slong deg; pbits = 1 + n_randint(state, FLINT_BITS); pbits = 1 + n_randint(state, pbits); deg = 1 + n_randint(state, 4); fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, pbits, deg); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); len = n_randint(state, 100) + 1; len1 = n_randint(state, 150); len2 = n_randint(state, 150); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); degbound = 1 + 50/n/n; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(g, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fq_nmod_mpoly/test/t-gcd_cofactors.c000066400000000000000000000710661461254215100224630ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c, t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_cofactors void gcd_check( fq_nmod_mpoly_t g, fq_nmod_mpoly_t abar, fq_nmod_mpoly_t bbar, fq_nmod_mpoly_t a, fq_nmod_mpoly_t b, const fq_nmod_mpoly_t gdiv, const fq_nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fq_nmod_mpoly_t ca, cb, cg, u, v, w; fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); fq_nmod_mpoly_init(u, ctx); fq_nmod_mpoly_init(v, ctx); fq_nmod_mpoly_init(w, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); fq_nmod_mpoly_assert_canonical(abar, ctx); fq_nmod_mpoly_assert_canonical(bbar, ctx); if (!fq_nmod_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_zero(gdiv, ctx) && !fq_nmod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_mul(ca, g, abar, ctx); fq_nmod_mpoly_mul(cb, g, bbar, ctx); if (!fq_nmod_mpoly_equal(ca, a, ctx) || !fq_nmod_mpoly_equal(cb, b, ctx)) { flint_printf("FAIL: check cofactors\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (fq_nmod_mpoly_is_zero(g, ctx)) { if (!fq_nmod_mpoly_is_zero(a, ctx) || !fq_nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fq_nmod_mpoly_is_monic(g, ctx)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(u, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, a, u, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(v, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, a, v, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(w, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, a, w, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(u, a, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, u, b, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(v, a, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, v, b, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(w, a, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, w, b, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(u, a, ctx); fq_nmod_mpoly_set(v, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, u, v, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(v, a, ctx); fq_nmod_mpoly_set(u, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, v, u, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(u, a, ctx); fq_nmod_mpoly_set(w, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, u, w, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(w, a, ctx); fq_nmod_mpoly_set(u, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, w, u, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(v, a, ctx); fq_nmod_mpoly_set(w, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, v, w, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(w, a, ctx); fq_nmod_mpoly_set(v, b, ctx); fq_nmod_mpoly_gcd_cofactors(u, v, w, w, v, ctx); if (!fq_nmod_mpoly_equal(g, u, ctx) || !fq_nmod_mpoly_equal(abar, v, ctx) || !fq_nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_gcd_cofactors(cg, ca, cb, abar, bbar, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(cg, ctx); if (!fq_nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_equal(ca, abar, ctx) || !fq_nmod_mpoly_equal(cb, bbar, ctx)) { flint_printf("FAIL: check cofactors of cofactors\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_gcd_cofactors(cg, abar, bbar, abar, bbar, ctx) || !fq_nmod_mpoly_equal(ca, abar, ctx) || !fq_nmod_mpoly_equal(cb, bbar, ctx)) { flint_printf("FAIL: check cofactors of cofactors with aliasing\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(cg, ctx); cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); fq_nmod_mpoly_clear(u, ctx); fq_nmod_mpoly_clear(v, ctx); fq_nmod_mpoly_clear(w, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_gcd_cofactors, state) { slong i, j, k, tmul = 2; /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(t, state, 1, exp_bits, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(b, state, len2, exp_bits2, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "monomial"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(t1, state, 1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(t2, state, 1, exp_bits2, ctx); if (t1->length != 1 || t2->length != 1) { flint_printf("FAIL:\ncheck random monomial generation\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); fq_nmod_mpoly_mul(b, a, t1, ctx); fq_nmod_mpoly_mul(t2, a, t2, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); gcd_check(g, abar, bbar, t2, b, a, ctx, i, j, "monomial cofactors"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_t c; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_init(c, ctx->fqctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t1, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(t2, state, len2, exp_bound2, ctx); fq_nmod_mpoly_mul(b, t1, t2, ctx); fq_nmod_randtest(c, state, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(a, t2, c, ctx); fq_nmod_randtest(c, state, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(b, b, c, ctx); fq_nmod_mpoly_randtest_bound(g, state, len, exp_bound, ctx); if ((j%2) == 0) fq_nmod_mpoly_swap(a, b, ctx); gcd_check(g, abar, bbar, a, b, t2, ctx, i, j, "one input divides the other"); } fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; slong degbound; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse inputs"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len, len1, len2; slong degbound; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(b, b, newbits, ctx); } fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with repacking"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 15) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fq_nmod_mpoly_inflate(a, a, shifts1, strides, ctx); fq_nmod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fq_nmod_mpoly_inflate(t, t, shifts1, strides, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len1 = n_randint(state, 200) + 1; len2 = n_randint(state, 200); len3 = n_randint(state, 200); len4 = n_randint(state, 200); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 10/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 10/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 10/ctx->minfo->nvars); } bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len1 = n_randint(state, 200) + 1; len2 = n_randint(state, 200); len3 = n_randint(state, 200); len4 = n_randint(state, 200); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 10/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 10/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 10/ctx->minfo->nvars); } bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(b, b, newbits, ctx); } fq_nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with repacking"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, FLINT_BITS, 4); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(abar, ctx); fq_nmod_mpoly_init(bbar, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len1 = n_randint(state, 200) + 1; len2 = n_randint(state, 200); len3 = n_randint(state, 200); len4 = n_randint(state, 200); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 10/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 10/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 10/ctx->minfo->nvars); } bits4 = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } fq_nmod_mpoly_inflate(a, a, shifts1, strides, ctx); fq_nmod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } fq_nmod_mpoly_inflate(t, t, shifts1, strides, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(abar, ctx); fq_nmod_mpoly_clear(bbar, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fq_nmod_mpoly/test/t-gcd_hensel.c000066400000000000000000000130151461254215100217440ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c, t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_hensel void gcd_check( fq_nmod_mpoly_t g, fq_nmod_mpoly_t a, fq_nmod_mpoly_t b, fq_nmod_mpoly_t t, fq_nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fq_nmod_mpoly_t ca, cb, cg; fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); if (!fq_nmod_mpoly_gcd_hensel(g, a, b, ctx)) { if (ctx->fqctx->mod.n < 1000) goto cleanup; flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(g, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) { if (!fq_nmod_mpoly_is_zero(a, ctx) || !fq_nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fq_nmod_mpoly_is_monic(g, ctx)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_zero(t, ctx) && !fq_nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_divides(ca, a, g, ctx) || !fq_nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_gcd_hensel(cg, ca, cb, ctx)) { if (ctx->fqctx->mod.n < 1000) goto cleanup; flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(cg, ctx); if (!fq_nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_gcd_hensel, state) { slong i, j; for (i = 0; i < 10*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t1, t2, t3; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 3); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); fq_nmod_mpoly_init(t3, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 1 + 30/(2*ctx->minfo->nvars - 1); degbounds = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 6; j++) { fq_nmod_mpoly_randtest_bounds(t1, state, len, degbounds, ctx); fq_nmod_mpoly_randtest_bounds(t2, state, len1, degbounds1, ctx); fq_nmod_mpoly_randtest_bounds(t3, state, len2, degbounds2, ctx); switch (n_randint(state, 4)) { case 3: fq_nmod_mpoly_mul(t3, t1, t2, ctx); break; case 2: fq_nmod_mpoly_mul(t3, t3, t1, ctx); break; case 1: fq_nmod_mpoly_mul(t3, t3, t2, ctx); break; default: break; } fq_nmod_mpoly_mul(a, t1, t3, ctx); fq_nmod_mpoly_mul(b, t2, t3, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t3, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_clear(t3, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fq_nmod_mpoly/test/t-gcd_zippel.c000066400000000000000000000124401461254215100217720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c, t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_zippel void gcd_check( fq_nmod_mpoly_t g, fq_nmod_mpoly_t a, fq_nmod_mpoly_t b, fq_nmod_mpoly_t t, fq_nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fq_nmod_mpoly_t ca, cb, cg; fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); if (!fq_nmod_mpoly_gcd_zippel(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(g, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) { if (!fq_nmod_mpoly_is_zero(a, ctx) || !fq_nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!fq_nmod_mpoly_is_monic(g, ctx)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_zero(t, ctx) && !fq_nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_divides(ca, a, g, ctx) || !fq_nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_gcd_zippel(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(cg, ctx); if (!fq_nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_gcd_zippel, state) { slong i, j; for (i = 0; i < 20*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, ca, cb, cg, t; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; flint_bitcnt_t pbits; slong deg; pbits = 1 + n_randint(state, FLINT_BITS); pbits = 1 + n_randint(state, pbits); deg = 2 + n_randint(state, 4); fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, pbits, deg); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 30) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 50/(2*ctx->minfo->nvars - 1); degbounds = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len, degbounds, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len1, degbounds1, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len2, degbounds2, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fq_nmod_mpoly/test/t-gcd_zippel2.c000066400000000000000000000125431461254215100220600ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly.h" /* Defined in t-gcd_brown.c, t-gcd.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c, t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_zippel2 void gcd_check( fq_nmod_mpoly_t g, fq_nmod_mpoly_t a, fq_nmod_mpoly_t b, fq_nmod_mpoly_t t, fq_nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { fq_nmod_mpoly_t ca, cb, cg; fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); if (!fq_nmod_mpoly_gcd_zippel2(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(g, ctx); if (fq_nmod_mpoly_is_zero(g, ctx)) { if (!fq_nmod_mpoly_is_zero(a, ctx) || !fq_nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!_n_fq_is_one(g->coeffs, fq_nmod_ctx_degree(ctx->fqctx))) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_zero(t, ctx) && !fq_nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_divides(ca, a, g, ctx) || !fq_nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_gcd_zippel2(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } fq_nmod_mpoly_assert_canonical(cg, ctx); if (!fq_nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_gcd_zippel2, state) { slong i, j; for (i = 0; i < 10*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, ca, cb, cg, t; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; flint_bitcnt_t pbits; slong deg; pbits = 1 + n_randint(state, FLINT_BITS); pbits = 1 + n_randint(state, pbits); deg = 2 + n_randint(state, 4); fq_nmod_mpoly_ctx_init_rand(ctx, state, 9, pbits, deg); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 70/(2*ctx->minfo->nvars - 1); degbounds = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bounds(t, state, len, degbounds, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bounds(a, state, len1, degbounds1, ctx); fq_nmod_mpoly_randtest_bounds(b, state, len2, degbounds2, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/fq_nmod_mpoly/test/t-gen.c000066400000000000000000000047671461254215100204400ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_gen, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f1, f2; slong len, k1, k2; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); if (fq_nmod_mpoly_ctx_nvars(ctx) < 1) { fq_nmod_mpoly_ctx_clear(ctx); continue; } fq_nmod_mpoly_init(f1, ctx); fq_nmod_mpoly_init(f2, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; fq_nmod_mpoly_randtest_bits(f1, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(f2, state, len, exp_bits, ctx); k1 = n_randint(state, ctx->minfo->nvars); k2 = n_randint(state, ctx->minfo->nvars); fq_nmod_mpoly_gen(f1, k1, ctx); fq_nmod_mpoly_assert_canonical(f1, ctx); fq_nmod_mpoly_gen(f2, k2, ctx); fq_nmod_mpoly_assert_canonical(f2, ctx); result = 1; result = result && fq_nmod_mpoly_is_gen(f1, k1, ctx); result = result && fq_nmod_mpoly_is_gen(f1, -WORD(1), ctx); result = result && fq_nmod_mpoly_is_gen(f2, k2, ctx); result = result && fq_nmod_mpoly_is_gen(f2, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check one generator\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_mul(f1, f1, f2, ctx); result = 1; result = result && !fq_nmod_mpoly_is_gen(f1, k1, ctx); result = result && !fq_nmod_mpoly_is_gen(f1, k2, ctx); result = result && !fq_nmod_mpoly_is_gen(f1, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check product of two generators\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_clear(f2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000137331461254215100233310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_coeff_vars_ui, state) { slong i, j1, j2; /* check simple example */ { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g; /* get the coefficient of y^1*x^2*/ slong varl[2] = {1, 0}; ulong expl[2] = {1, 2}; const char * vars[] = {"x", "y", "z", "w"}; fq_nmod_mpoly_ctx_init_deg(ctx, 4, ORD_LEX, 11, 2); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_set_str_pretty(f, "x^2*y*(z+w)+x+y+x*y^2+z^2+w^2", vars, ctx); fq_nmod_mpoly_set_str_pretty(g, "z+w", vars, ctx); fq_nmod_mpoly_get_coeff_vars_ui(f, f, varl, expl, 2, ctx); if (!fq_nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\ncheck simple example\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* check 1 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, m; slong len, nvars; ulong exp_bound; slong vars[1]; ulong exps[1]; slong var1; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); nvars = ctx->minfo->nvars; if (nvars < 1) { fq_nmod_mpoly_ctx_clear(ctx); continue; } fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 20) + 1; fq_nmod_mpoly_randtest_bound(f, state, len, exp_bound, ctx); fq_nmod_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars); fq_nmod_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { vars[0] = var1; exps[0] = j1; fq_nmod_mpoly_get_coeff_vars_ui(g, f, vars, exps, 1, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); fq_nmod_mpoly_gen(m, var1, ctx); if (!fq_nmod_mpoly_pow_ui(m, m, j1, ctx)) { flint_printf("FAIL\n"); flint_printf("Check power success\ni = %wd, j1 = %wd\n", i, j1); fflush(stdout); flint_abort(); } fq_nmod_mpoly_mul(g, g, m, ctx); fq_nmod_mpoly_add(h, h, g, ctx); } if (!fq_nmod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n"); flint_printf("Check 1 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* check 2 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, m; slong len, nvars; ulong exp_bound; slong vars[2]; ulong exps[2]; slong var1, var2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); nvars = ctx->minfo->nvars; if (nvars < 2) { fq_nmod_mpoly_ctx_clear(ctx); continue; } fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 12) + 1; fq_nmod_mpoly_randtest_bound(f, state, len, exp_bound, ctx); fq_nmod_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars - 1); var2 = 1 + var1 + n_randint(state, nvars - 1 - var1); fq_nmod_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { for (j2 = 0; j2 < exp_bound; j2++) { vars[0] = var1; exps[0] = j1; vars[1] = var2; exps[1] = j2; fq_nmod_mpoly_get_coeff_vars_ui(g, f, vars, exps, 2, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); fq_nmod_mpoly_gen(m, var1, ctx); if (!fq_nmod_mpoly_pow_ui(m, m, j1, ctx)) { flint_printf("FAIL\n"); flint_printf("Check power success\ni = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } fq_nmod_mpoly_mul(g, g, m, ctx); fq_nmod_mpoly_gen(m, var2, ctx); if (!fq_nmod_mpoly_pow_ui(m, m, j2, ctx)) { flint_printf("FAIL\n"); flint_printf("Check power success\ni = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } fq_nmod_mpoly_mul(g, g, m, ctx); fq_nmod_mpoly_add(h, h, g, ctx); } } if (!fq_nmod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n" "check 2 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_coeff.c000066400000000000000000000075751461254215100224630ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_coeff, state) { int i, j, k, result; /* Check _fmpz_fmpz */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; flint_bitcnt_t exp_bits, exp_bits2; slong len; fq_nmod_t c, d; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(d, ctx->fqctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (j = 0; j < 10; j++) { fmpz ** exp = (fmpz **) flint_malloc(ctx->minfo->nvars*sizeof(fmpz*)); fq_nmod_randtest(c, state, ctx->fqctx); for (k = 0; k < fq_nmod_mpoly_ctx_nvars(ctx); k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_randtest_unsigned(exp[k], state, exp_bits2); } fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(f, c, exp, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_fmpz(d, f, exp, ctx); result = fq_nmod_equal(c, d, ctx->fqctx); if (!result) { printf("FAIL\n"); flint_printf("Check _fmpz_fmpz\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } for (k = 0; k < fq_nmod_mpoly_ctx_nvars(ctx); k++) { fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_clear(d, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check _fmpz_ui */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; flint_bitcnt_t exp_bits; slong len; fq_nmod_t c, d; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(d, ctx->fqctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (j = 0; j < 10; j++) { ulong * exp = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); fq_nmod_randtest(c, state, ctx->fqctx); for (k = 0; k < fq_nmod_mpoly_ctx_nvars(ctx); k++) exp[k] = n_randtest(state); fq_nmod_mpoly_set_coeff_fq_nmod_ui(f, c, exp, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_ui(d, f, exp, ctx); result = fq_nmod_equal(c, d, ctx->fqctx); if (!result) { printf("FAIL\n"); flint_printf("Check _fmpz_ui\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } flint_free(exp); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_clear(d, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_coeff_fq_nmod_monomial.c000066400000000000000000000076261461254215100260560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_coeff_fq_nmod_monomial, state) { slong i, j, k; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, m; fmpz ** exp; fq_nmod_t cm, ce, q; slong len; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_init(cm, ctx->fqctx); fq_nmod_init(ce, ctx->fqctx); fq_nmod_init(q, ctx->fqctx); fq_nmod_one(q, ctx->fqctx); /* anything nonzero is ok */ len = n_randint(state, 100); exp_bits = n_randint(state, FLINT_BITS + 10) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); /* check a random monomial - this also randomizes m->bits */ exp = (fmpz **) flint_malloc(ctx->minfo->nvars*sizeof(fmpz *)); for (k = 0; k < ctx->minfo->nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); fmpz_randtest_unsigned(exp[k], state, exp_bits1); } fq_nmod_mpoly_zero(m, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(m, q, exp, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_monomial(cm, f, m, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_fmpz(ce, f, exp, ctx); if (!fq_nmod_equal(cm, ce, ctx->fqctx)) { flint_printf("FAIL\ncheck a random monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } /* check all coeffs in f */ for (j = 0; j < fq_nmod_mpoly_length(f, ctx); j++) { fq_nmod_mpoly_get_term_exp_fmpz(exp, f, j, ctx); fq_nmod_mpoly_zero(m, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(m, q, exp, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_monomial(cm, f, m, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_fmpz(ce, f, exp, ctx); if (!fq_nmod_equal(cm, ce, ctx->fqctx)) { flint_printf("FAIL\ncheck all coeffs in f\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } /* set random coeff and check */ for (j = 0; j < 10; j++) { for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits2); } fq_nmod_randtest(cm, state, ctx->fqctx); fq_nmod_mpoly_zero(m, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(m, q, exp, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_monomial(f, cm, m, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_monomial(ce, f, m, ctx); if (!fq_nmod_equal(cm, ce, ctx->fqctx)) { flint_printf("FAIL\nset random coeff and check\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp); fq_nmod_clear(q, ctx->fqctx); fq_nmod_clear(cm, ctx->fqctx); fq_nmod_clear(ce, ctx->fqctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_is_fq_nmod.c000066400000000000000000000055401461254215100235050ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_is_fq_nmod, state) { slong i; /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; fq_nmod_t c, d; ulong b; slong len; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(d, ctx->fqctx); len = n_randint(state, 10); exp_bits = n_randint(state, 200); fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (fq_nmod_mpoly_is_fq_nmod(f, ctx)) { fq_nmod_mpoly_get_fq_nmod(c, f, ctx); if (!fq_nmod_mpoly_equal_fq_nmod(f, c, ctx)) { printf("FAIL\n"); flint_printf("Check is_fq_nmod and get_fq_nmod catch constants\ni = %wd\n", i); fflush(stdout); flint_abort(); } } fq_nmod_randtest(c, state, ctx->fqctx); fq_nmod_mpoly_set_fq_nmod(f, c, ctx); if (!fq_nmod_mpoly_is_fq_nmod(f, ctx)) { printf("FAIL\n"); flint_printf("Check set_fq_nmod makes is_fq_nmod true\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_get_fq_nmod(d, f, ctx); if (!fq_nmod_equal(c, d, ctx->fqctx)) { printf("FAIL\n"); flint_printf("Check get_fq_nmod matches set_fq_nmod\ni = %wd\n", i); fflush(stdout); flint_abort(); } b = n_randlimb(state); fq_nmod_set_ui(c, b, ctx->fqctx); fq_nmod_mpoly_set_ui(f, b, ctx); if (!fq_nmod_mpoly_is_fq_nmod(f, ctx)) { printf("FAIL\n"); flint_printf("Check set_ui makes is_fq_nmod true\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_get_fq_nmod(d, f, ctx); if (!fq_nmod_equal(c, d, ctx->fqctx)) { printf("FAIL\n"); flint_printf("Check get_fq_nmod matches set_ui\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_clear(c, ctx->fqctx); fq_nmod_clear(d, ctx->fqctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_str_pretty.c000066400000000000000000000033331461254215100236040ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_str_pretty, state) { slong i; { slong len1; flint_bitcnt_t exp_bits1; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, f1; char * str; const char * vars[] = {"x","y","z","w","u","v"}; for (i = 0; i < 10*flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_init_rand(ctx, state, 6, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(f1, ctx); for (len1 = 3; len1 < 100; len1 += len1/2) { exp_bits1 = 3 + n_randint(state, 200); fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); str = fq_nmod_mpoly_get_str_pretty(f, vars, ctx); fq_nmod_mpoly_set_str_pretty(f1, str, vars, ctx); flint_free(str); if (!fq_nmod_mpoly_equal(f, f1, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_ctx_clear(ctx); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_term_coeff_fq_nmod.c000066400000000000000000000036141461254215100252030ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_term_coeff_fq_nmod, state) { slong i, j; /* Set coeff and get coeff and compare */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; fq_nmod_t c, d; slong len, index; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(d, ctx->fqctx); len = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (fq_nmod_mpoly_is_zero(f, ctx)) fq_nmod_mpoly_one(f, ctx); for (j = 0; j < 10; j++) { fq_nmod_randtest(c, state, ctx->fqctx); index = n_randint(state, f->length); fq_nmod_mpoly_set_term_coeff_fq_nmod(f, index, c, ctx); fq_nmod_mpoly_get_term_coeff_fq_nmod(d, f, index, ctx); if (!fq_nmod_equal(c, d, ctx->fqctx)) { printf("FAIL\n"); flint_printf("check get and set match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_clear(d, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000054541461254215100242520ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_term_exp_fmpz, state) { slong i, j, k; int result; /* check fmpz */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); nvars = fq_nmod_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 100) + 1; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (fq_nmod_mpoly_is_zero(f, ctx)) fq_nmod_mpoly_one(f, ctx); for (j = 0; j < 10; j++) { fmpz ** exp1 = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); fmpz ** exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz*)); for (k = 0; k < nvars; k++) { exp1[k] = (fmpz *) flint_malloc(sizeof(fmpz)); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp1[k]); fmpz_init(exp2[k]); fmpz_randtest_unsigned(exp1[k], state, 200); } index = n_randint(state, f->length); fq_nmod_mpoly_set_term_exp_fmpz(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fq_nmod_mpoly_get_term_exp_fmpz(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && fmpz_equal(exp1[k], exp2[k]); fmpz_clear(exp1[k]); fmpz_clear(exp2[k]); flint_free(exp1[k]); flint_free(exp2[k]); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000051641461254215100237070ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_term_exp_si, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); nvars = fq_nmod_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (fq_nmod_mpoly_is_zero(f, ctx)) fq_nmod_mpoly_one(f, ctx); for (j = 0; j < 10; j++) { slong * exp1 = (slong *) flint_malloc(nvars*sizeof(slong)); slong * exp2 = (slong *) flint_malloc(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS - 1) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); fq_nmod_mpoly_set_term_exp_ui(f, index, (ulong *) exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fq_nmod_mpoly_get_term_exp_si(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fq_nmod_mpoly_get_term_var_exp_si(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000051471461254215100237120ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_set_term_exp_ui, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); nvars = fq_nmod_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 100) + 2; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (fq_nmod_mpoly_is_zero(f, ctx)) fq_nmod_mpoly_one(f, ctx); for (j = 0; j < 10; j++) { ulong * exp1 = (ulong *) flint_malloc(nvars*sizeof(ulong)); ulong * exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); fq_nmod_mpoly_set_term_exp_ui(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); fq_nmod_mpoly_get_term_exp_ui(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == fq_nmod_mpoly_get_term_var_exp_ui(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_term.c000066400000000000000000000037601461254215100214650ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_term, state) { int i, j; /* Check a polynomial is the sum of its terms */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); fq_nmod_mpoly_zero(h, ctx); for (j = fq_nmod_mpoly_length(f, ctx) - 1; j >= 0; j--) { fq_nmod_mpoly_get_term(g, f, j, ctx); fq_nmod_mpoly_add(h, h, g, ctx); } if (!fq_nmod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\nCheck a polynomial is the sum of its terms\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-get_term_monomial.c000066400000000000000000000047471461254215100233660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_get_term_monomial, state) { int i, j; /* Check getting a coeff by its monomial */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_t c, d; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(d, ctx->fqctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); fq_nmod_mpoly_repack_bits(h, f, f->bits + n_randint(state, 2*FLINT_BITS), ctx); for (j = fq_nmod_mpoly_length(f, ctx) - 1; j >= 0; j--) { fq_nmod_mpoly_get_term_monomial(g, f, j, ctx); fq_nmod_mpoly_repack_bits(g, g, g->bits + n_randint(state, FLINT_BITS), ctx); fq_nmod_mpoly_get_term_coeff_fq_nmod(d, f, j, ctx); fq_nmod_mpoly_get_coeff_fq_nmod_monomial(c, h, g, ctx); if (!fq_nmod_equal(c, d, ctx->fqctx)) { flint_printf("FAIL\nCheck getting a coeff by its monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_clear(d, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-mpolyuu_divides.c000066400000000000000000000132731461254215100231000ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" void univar_divides_check( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx, slong ii, slong jj, const char * name, flint_rand_t randstate) { int divides, udivides; fq_nmod_mpoly_ctx_t uctx; fq_nmod_mpolyu_t Au, Bu, Qu; fq_nmod_mpoly_t Q, Qcheck; flint_bitcnt_t ABbits; ulong * shift, * stride; slong * perm; slong i, j, k; if ( A->bits > FLINT_BITS || B->bits > FLINT_BITS || A->length == 0 || B->length == 0 || ctx->minfo->nvars < 2) { return; } perm = (slong *) flint_malloc((ctx->minfo->nvars)*sizeof(slong)); shift = (ulong *) flint_malloc((ctx->minfo->nvars)*sizeof(ulong)); stride = (ulong *) flint_malloc((ctx->minfo->nvars)*sizeof(ulong)); fq_nmod_mpoly_init(Q, ctx); fq_nmod_mpoly_init(Qcheck, ctx); fq_nmod_mpoly_ctx_init(uctx, ctx->minfo->nvars - 1, ORD_LEX, ctx->fqctx); ABbits = FLINT_MAX(A->bits, B->bits); fq_nmod_mpolyu_init(Au, ABbits, uctx); fq_nmod_mpolyu_init(Bu, ABbits, uctx); fq_nmod_mpolyu_init(Qu, ABbits, uctx); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } /* randomize perm */ for (k = 0; k < ctx->minfo->nvars; k++) { slong t1, t2; i = n_randint(randstate, ctx->minfo->nvars - 1); j = i + n_randint(randstate, ctx->minfo->nvars - i); t1 = perm[i]; t2 = perm[j]; perm[i] = t2; perm[j] = t1; } fq_nmod_mpoly_to_mpolyu_perm_deflate(Au, uctx, A, ctx, perm, shift, stride); fq_nmod_mpoly_to_mpolyu_perm_deflate(Bu, uctx, B, ctx, perm, shift, stride); udivides = fq_nmod_mpolyuu_divides(Qu, Au, Bu, 1, uctx); divides = fq_nmod_mpoly_divides(Q, A, B, ctx); if (divides != udivides) { flint_printf("check univariate divisibility\n" "i = %wd, j = %wd, %s\n", ii, jj, name); fflush(stdout); flint_abort(); } if (!divides) { goto cleanup; } fq_nmod_mpoly_from_mpolyu_perm_inflate(Qcheck, ABbits, ctx, Qu, uctx, perm, shift, stride); if (!fq_nmod_mpoly_equal(Q, Qcheck, ctx)) { flint_printf("check univariate quotient\n" "i = %wd, j = %wd, %s\n", ii, jj, name); fflush(stdout); flint_abort(); } cleanup: fq_nmod_mpolyu_clear(Au, uctx); fq_nmod_mpolyu_clear(Bu, uctx); fq_nmod_mpolyu_clear(Qu, uctx); fq_nmod_mpoly_ctx_clear(uctx); fq_nmod_mpoly_clear(Q, ctx); fq_nmod_mpoly_clear(Qcheck, ctx); flint_free(perm); flint_free(shift); flint_free(stride); } TEST_FUNCTION_START(fq_nmod_mpoly_mpolyuu_divides, state) { slong i, j, tmul = 50; /* Check (a*b)/b = a */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b; slong len1, len2; flint_bitcnt_t exp_bits; flint_bitcnt_t pbits; slong deg; pbits = 1 + n_randint(state, FLINT_BITS); pbits = 1 + n_randint(state, pbits); deg = 1 + n_randint(state, 4); fq_nmod_mpoly_ctx_init_rand(ctx, state, 15, pbits, deg); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); exp_bits = n_randint(state, FLINT_BITS/2 - 2) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(b, state, len2, exp_bits, ctx); fq_nmod_mpoly_mul(a, a, b, ctx); univar_divides_check(a, b, ctx, i, j, "univar Check (a*b)/b = a", state); } fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check (a*b + c)/b */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, c; slong len1, len2, len3; flint_bitcnt_t exp_bits; flint_bitcnt_t pbits; slong deg; pbits = 1 + n_randint(state, FLINT_BITS); pbits = 1 + n_randint(state, pbits); deg = 1 + n_randint(state, 4); fq_nmod_mpoly_ctx_init_rand(ctx, state, 12, pbits, deg); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(c, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); len3 = n_randint(state, 30); exp_bits = n_randint(state, 8) + 3; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(b, state, len2, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(c, state, len3, exp_bits, ctx); fq_nmod_mpoly_mul(a, a, b, ctx); fq_nmod_mpoly_add(a, a, c, ctx); univar_divides_check(a, b, ctx, i, j, "univar Check (a*b + c)/b", state); } fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(c, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-mul_johnson.c000066400000000000000000000143071461254215100222110ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_mul_johnson, state) { int i, j, result; slong tmul = 5; /* Check f*(g + h) = f*g + f*h */ for (i = 0; i < 2 * tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k1, ctx); fq_nmod_mpoly_init(k2, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; fq_nmod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); fq_nmod_mpoly_randtest_bits(h, state, len2, exp_bits2, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_add(t1, g, h, ctx); fq_nmod_mpoly_assert_canonical(t1, ctx); fq_nmod_mpoly_mul_johnson(k1, f, t1, ctx); fq_nmod_mpoly_assert_canonical(k1, ctx); fq_nmod_mpoly_mul_johnson(t1, f, g, ctx); fq_nmod_mpoly_assert_canonical(t1, ctx); fq_nmod_mpoly_mul_johnson(t2, f, h, ctx); fq_nmod_mpoly_assert_canonical(t2, ctx); fq_nmod_mpoly_add(k2, t1, t2, ctx); fq_nmod_mpoly_assert_canonical(k2, ctx); result = fq_nmod_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*(g + h) = f*g + f*h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k1, ctx); fq_nmod_mpoly_clear(k2, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_mul_johnson(h, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_mul_johnson(f, f, g, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); result = fq_nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_mul_johnson(h, f, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); fq_nmod_mpoly_mul_johnson(g, f, g, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); result = fq_nmod_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-push_term_fq_nmod_fmpz.c000066400000000000000000000112621461254215100244200ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_push_term_fq_nmod_fmpz, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f1, f2, f3, m; flint_bitcnt_t exp_bits; fmpz **exp, **exp2, *exp3; slong len, nvars; fq_nmod_t c, c2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 10); fq_nmod_mpoly_init(f1, ctx); fq_nmod_mpoly_init(f2, ctx); fq_nmod_mpoly_init(f3, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(c2, ctx->fqctx); nvars = fq_nmod_mpoly_ctx_nvars(ctx); exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); fmpz_init(exp3 + k); } len = n_randint(state, 20); exp_bits = n_randint(state, 200); fq_nmod_mpoly_zero(f1, ctx); fq_nmod_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fq_nmod_randtest(c, state, ctx->fqctx); for (k = 0; k < nvars; k++){ fmpz_randtest_unsigned(exp[k], state, exp_bits); fmpz_set(exp3 + k, exp[k]); } /* add it to f1 */ fq_nmod_mpoly_zero(m, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(m, c, exp, ctx); fq_nmod_mpoly_add(f1, f1, m, ctx); fq_nmod_mpoly_assert_canonical(f1, ctx); /* push it back on f2 and f3*/ fq_nmod_mpoly_push_term_fq_nmod_fmpz(f2, c, exp, ctx); fq_nmod_mpoly_push_term_fq_nmod_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ fq_nmod_mpoly_get_term_coeff_fq_nmod(c2, f2, fq_nmod_mpoly_length(f2, ctx) - 1, ctx); fq_nmod_mpoly_get_term_exp_fmpz(exp2, f2, fq_nmod_mpoly_length(f2, ctx) - 1, ctx); if (!fq_nmod_equal(c, c2, ctx->fqctx)) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (!fmpz_equal(exp[k], exp2[k])) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } } } fq_nmod_mpoly_sort_terms(f2, ctx); fq_nmod_mpoly_combine_like_terms(f2, ctx); fq_nmod_mpoly_assert_canonical(f2, ctx); fq_nmod_mpoly_sort_terms(f3, ctx); fq_nmod_mpoly_combine_like_terms(f3, ctx); fq_nmod_mpoly_assert_canonical(f3, ctx); if (!fq_nmod_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushed polynomial matches add\ni=%wd\n", i, j); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check pushed ffmpz polynomial matches add\ni=%wd\n", i, j); fflush(stdout); flint_abort(); } fq_nmod_clear(c2, ctx->fqctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_clear(f2, ctx); fq_nmod_mpoly_clear(f3, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); fmpz_clear(exp3 + k); } flint_free(exp3); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-push_term_fq_nmod_ui.c000066400000000000000000000067231461254215100240670ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_push_term_fq_nmod_ui, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 800 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f1, f2, m; flint_bitcnt_t exp_bits; ulong * exp, * exp2; slong len, nvars; fq_nmod_t c, c2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 10); fq_nmod_mpoly_init(f1, ctx); fq_nmod_mpoly_init(f2, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(c2, ctx->fqctx); nvars = fq_nmod_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 20); exp_bits = n_randint(state, FLINT_BITS) + 1; fq_nmod_mpoly_zero(f1, ctx); fq_nmod_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fq_nmod_randtest(c, state, ctx->fqctx); for (k = 0; k < nvars; k++) exp[k] = n_randtest_bits(state, n_randint(state, exp_bits) + 1); /* add it to f1 */ fq_nmod_mpoly_zero(m, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_ui(m, c, exp, ctx); fq_nmod_mpoly_add(f1, f1, m, ctx); /* push it back on f2 */ fq_nmod_mpoly_push_term_fq_nmod_ui(f2, c, exp, ctx); /* make sure last term matches */ fq_nmod_mpoly_get_term_coeff_fq_nmod(c2, f2, fq_nmod_mpoly_length(f2, ctx) - 1, ctx); fq_nmod_mpoly_get_term_exp_ui(exp2, f2, fq_nmod_mpoly_length(f2, ctx) - 1, ctx); if (!fq_nmod_equal(c, c2, ctx->fqctx)) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (exp[k] != exp2[k]) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } } } fq_nmod_mpoly_sort_terms(f2, ctx); fq_nmod_mpoly_combine_like_terms(f2, ctx); fq_nmod_mpoly_assert_canonical(f2, ctx); if (!fq_nmod_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushback matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } fq_nmod_clear(c2, ctx->fqctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_clear(f2, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-quadratic_root.c000066400000000000000000000067151461254215100227020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" void _test_root( fq_nmod_mpoly_t x, const fq_nmod_mpoly_t a, const fq_nmod_mpoly_t b, const fq_nmod_mpoly_ctx_t ctx, int sol_exists) { int success, success2; fq_nmod_mpoly_t s, t; fq_nmod_mpoly_init(s, ctx); fq_nmod_mpoly_init(t, ctx); success = fq_nmod_mpoly_quadratic_root(x, a, b, ctx); if (sol_exists && !success) { flint_printf("FAIL: solution exists but root failed\n"); fflush(stdout); flint_abort(); } if (success) { fq_nmod_mpoly_add(t, x, a, ctx); fq_nmod_mpoly_mul(s, t, x, ctx); if (!fq_nmod_mpoly_equal(s, b, ctx)) { flint_printf("FAIL: reported solution is not a solution\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_set(t, a, ctx); success2 = fq_nmod_mpoly_quadratic_root(t, t, b, ctx); if (success != success2 || (success && !fq_nmod_mpoly_equal(x, t, ctx))) { flint_printf("FAIL: Check aliasing first argument\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(t, b, ctx); success2 = fq_nmod_mpoly_quadratic_root(t, a, t, ctx); if (success != success2 || (success && !fq_nmod_mpoly_equal(x, t, ctx))) { flint_printf("FAIL: Check aliasing second argument\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(s, ctx); fq_nmod_mpoly_clear(t, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_quadratic_root, state) { slong i, j, tmul = 20; /* Check sqrt(f^2) = +-f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, a, b, x; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; fq_nmod_mpoly_ctx_init_rand(ctx, state, 9, (i % 2) ? FLINT_BITS : 1, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(x, ctx); for (j = 0; j < 5; j++) { len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 100) + 1; exp_bits1 = n_randint(state, 100) + 1; fq_nmod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_add(b, f, a, ctx); fq_nmod_mpoly_mul(b, b, f, ctx); _test_root(x, a, b, ctx, 1); len = n_randint(state, 50); len1 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 20) + 1; exp_bits1 = n_randint(state, 20) + 1; fq_nmod_mpoly_randtest_bits(a, state, len1, 10, ctx); fq_nmod_mpoly_randtest_bits(b, state, len, 10, ctx); _test_root(x, a, b, ctx, 0); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(x, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-repack_bits.c000066400000000000000000000152231461254215100221420ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_repack_bits, state) { slong i, j; int success; /* Check packing up */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2, newbits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 9); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fq_nmod_mpoly_repack_bits(f, g, newbits, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); if (!success || !fq_nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing up\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fq_nmod_mpoly_repack_bits(g, g, newbits, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); if (!success || !fq_nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing up with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check repacking down up */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2, newbits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 9); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len2, exp_bits2, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); fq_nmod_mpoly_repack_bits(f, g, newbits, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fq_nmod_mpoly_repack_bits(h, f, newbits, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); if (!success || !fq_nmod_mpoly_equal(h, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check repacking down\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fq_nmod_mpoly_repack_bits(f, f, newbits, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); if (!success || !fq_nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check repacking down with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check packing down */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2, newbits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 9); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (g->bits <= MPOLY_MIN_BITS) continue; newbits = n_randint(state, g->bits - MPOLY_MIN_BITS) + MPOLY_MIN_BITS; newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fq_nmod_mpoly_repack_bits(f, g, newbits, ctx); fq_nmod_mpoly_assert_canonical(f, ctx); if (success && !fq_nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing down\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(f, g, ctx); newbits = n_randint(state, g->bits - MPOLY_MIN_BITS) + MPOLY_MIN_BITS; newbits = mpoly_fix_bits(newbits, ctx->minfo); success = fq_nmod_mpoly_repack_bits(g, g, newbits, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); if (success && !fq_nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing down with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-resize.c000066400000000000000000000062151461254215100211560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_resize, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f1, f2, f3, m; flint_bitcnt_t exp_bits; ulong * exp, * exp2; slong len, nvars; fq_nmod_t c; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 10); fq_nmod_mpoly_init(f1, ctx); fq_nmod_mpoly_init(f2, ctx); fq_nmod_mpoly_init(f3, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_init(c, ctx->fqctx); nvars = fq_nmod_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 200); exp_bits = n_randint(state, FLINT_BITS) + 1; fq_nmod_mpoly_zero(f1, ctx); fq_nmod_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ fq_nmod_randtest(c, state, ctx->fqctx); for (k = 0; k < nvars; k++) exp[k] = n_randtest_bits(state, n_randint(state, exp_bits) + 1); /* add it to f1 */ fq_nmod_mpoly_zero(m, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_ui(m, c, exp, ctx); fq_nmod_mpoly_add(f1, f1, m, ctx); /* push it back on f2 */ fq_nmod_mpoly_push_term_fq_nmod_ui(f2, c, exp, ctx); /* manually push it on f3 */ fq_nmod_mpoly_resize(f3, j + 1 + n_randint(state, 10), ctx); fq_nmod_mpoly_set_term_coeff_fq_nmod(f3, j, c, ctx); fq_nmod_mpoly_set_term_exp_ui(f3, j, exp, ctx); } fq_nmod_mpoly_sort_terms(f2, ctx); fq_nmod_mpoly_combine_like_terms(f2, ctx); fq_nmod_mpoly_assert_canonical(f2, ctx); fq_nmod_mpoly_sort_terms(f3, ctx); fq_nmod_mpoly_combine_like_terms(f3, ctx); fq_nmod_mpoly_assert_canonical(f3, ctx); if (!fq_nmod_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushback matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check resize+setterm matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_clear(f2, ctx); fq_nmod_mpoly_clear(f3, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-resultant_discriminant.c000066400000000000000000000205541461254215100244440ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_resultant_discriminant, state) { slong i, j; /* Check quadratic polynomial */ { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, d, d1; const char * vars[] = {"x","a","b","c"}; fq_nmod_mpoly_ctx_init_deg(ctx, 4, ORD_DEGLEX, 3, 4); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(d, ctx); fq_nmod_mpoly_init(d1, ctx); fq_nmod_mpoly_set_str_pretty(f, "a^10*x^2 + b^100*x + c^100000000000000000000", vars, ctx); fq_nmod_mpoly_set_str_pretty(d1, "b^200 - 4*a^10*c^100000000000000000000", vars, ctx); if (!fq_nmod_mpoly_discriminant(d, f, 0, ctx)) { flint_printf("FAIL: could not compute quadratic discriminant\n"); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(d, ctx); fq_nmod_mpoly_clear(d1, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* fq_nmod_poly_resultant is missing */ #if 0 /* Check univariate resultant */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, r; fq_nmod_poly_t au, bu; fq_nmod_t ru; slong len1, len2, exp_bound1, exp_bound2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 1, FLINT_BITS, 5); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(r, ctx); fq_nmod_poly_init(au, ctx->fqctx); fq_nmod_poly_init(bu, ctx->fqctx); fq_nmod_init(ru, ctx->fqctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 50) + 1; exp_bound2 = n_randint(state, 50) + 1; fq_nmod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); fq_nmod_mpoly_get_fq_nmod_poly(au, a, 0, ctx); fq_nmod_mpoly_get_fq_nmod_poly(bu, b, 0, ctx); fq_nmod_poly_resultant(ru, au, bu); if (!fq_nmod_mpoly_resultant(r, a, b, 0, ctx) || !fq_nmod_mpoly_equal_fq_nmod(r, ru, ctx)) { flint_printf("FAIL: Check univariate resultant \n"); flint_printf("i: %wd\n",i); fflush(stdout); flint_abort(); } fq_nmod_clear(ru, ctx->fqctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(r, ctx); fq_nmod_poly_clear(au, ctx->fqctx); fq_nmod_poly_clear(bu, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } #endif /* Check res(a*b,c) = res(a,c)*res(b,c) */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, c, ab, ra, rb, rab, p; slong len1, len2, len3, exp_bound1, exp_bound2, exp_bound3; fq_nmod_mpoly_ctx_init_rand(ctx, state, 3, FLINT_BITS, 4); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(c, ctx); fq_nmod_mpoly_init(ab, ctx); fq_nmod_mpoly_init(ra, ctx); fq_nmod_mpoly_init(rb, ctx); fq_nmod_mpoly_init(rab, ctx); fq_nmod_mpoly_init(p, ctx); len1 = n_randint(state, 12); len2 = n_randint(state, 12); len3 = n_randint(state, 12); exp_bound1 = n_randint(state, 5) + 1; exp_bound2 = n_randint(state, 5) + 1; exp_bound3 = n_randint(state, 5) + 1; fq_nmod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); fq_nmod_mpoly_randtest_bound(c, state, len3, exp_bound3, ctx); for (j = 0; j < fq_nmod_mpoly_ctx_nvars(ctx); j++) { fq_nmod_mpoly_mul(ab, a, b, ctx); if (!fq_nmod_mpoly_resultant(ra, a, c, j, ctx)) continue; fq_nmod_mpoly_assert_canonical(ra, ctx); if (!fq_nmod_mpoly_resultant(rb, b, c, j, ctx)) continue; fq_nmod_mpoly_assert_canonical(rb, ctx); if (!fq_nmod_mpoly_resultant(rab, ab, c, j, ctx)) continue; fq_nmod_mpoly_assert_canonical(rab, ctx); fq_nmod_mpoly_mul(p, ra, rb, ctx); if (!fq_nmod_mpoly_equal(p,rab,ctx)) { flint_printf("FAIL: Check res(a*b,c) = res(a,c)*res(b,c)\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(c, ctx); fq_nmod_mpoly_clear(ab, ctx); fq_nmod_mpoly_clear(ra, ctx); fq_nmod_mpoly_clear(rb, ctx); fq_nmod_mpoly_clear(rab, ctx); fq_nmod_mpoly_clear(p, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2 */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, ab, r, da, db, dab, p; slong len1, len2, exp_bound1, exp_bound2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 3, FLINT_BITS, 4); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(ab, ctx); fq_nmod_mpoly_init(da, ctx); fq_nmod_mpoly_init(db, ctx); fq_nmod_mpoly_init(dab, ctx); fq_nmod_mpoly_init(r, ctx); fq_nmod_mpoly_init(p, ctx); len1 = n_randint(state, 12); len2 = n_randint(state, 12); exp_bound1 = n_randint(state, 4) + 1; exp_bound2 = n_randint(state, 5) + 1; fq_nmod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); for (j = 0; j < fq_nmod_mpoly_ctx_nvars(ctx); j++) { if (fq_nmod_mpoly_degree_si(a, j, ctx) < 1) continue; if (fq_nmod_mpoly_degree_si(b, j, ctx) < 1) continue; fq_nmod_mpoly_mul(ab, a, b, ctx); if (!fq_nmod_mpoly_resultant(r, a, b, j, ctx)) continue; if (!fq_nmod_mpoly_discriminant(da, a, j, ctx)) continue; if (!fq_nmod_mpoly_discriminant(db, b, j, ctx)) continue; if (!fq_nmod_mpoly_discriminant(dab, ab, j, ctx)) continue; fq_nmod_mpoly_mul(p, da, db, ctx); fq_nmod_mpoly_mul(p, p, r, ctx); fq_nmod_mpoly_mul(p, p, r, ctx); if (!fq_nmod_mpoly_equal(dab, p, ctx)) { flint_printf("FAIL: Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2\n"); flint_printf("a: "); fq_nmod_mpoly_print_pretty(a, NULL, ctx); flint_printf("\n"); flint_printf("b: "); fq_nmod_mpoly_print_pretty(b, NULL, ctx); flint_printf("\n"); flint_printf("disc(a*b): "); fq_nmod_mpoly_print_pretty(dab, NULL, ctx); flint_printf("\n"); flint_printf("disc(a): "); fq_nmod_mpoly_print_pretty(da, NULL, ctx); flint_printf("\n"); flint_printf("disc(b): "); fq_nmod_mpoly_print_pretty(db, NULL, ctx); flint_printf("\n"); flint_printf("res(a, b): "); fq_nmod_mpoly_print_pretty(r, NULL, ctx); flint_printf("\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(ab, ctx); fq_nmod_mpoly_clear(da, ctx); fq_nmod_mpoly_clear(db, ctx); fq_nmod_mpoly_clear(dab, ctx); fq_nmod_mpoly_clear(r, ctx); fq_nmod_mpoly_clear(p, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-reverse.c000066400000000000000000000046341461254215100213330ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_reverse, state) { int i, result; /* Check rev(rev(a)) == a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len, exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_reverse(h, f, ctx); fq_nmod_mpoly_reverse(g, h, ctx); result = fq_nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check rev(rev(a)) == a\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g; slong len, exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_reverse(g, f, ctx); fq_nmod_mpoly_reverse(g, g, ctx); result = fq_nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd\n", i); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-scalar_addmul_fq_nmod.c000066400000000000000000000060341461254215100241520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_scalar_addmul_fq_nmod, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k; fq_nmod_t c; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_init(c, ctx->fqctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fq_nmod_randtest(c, state, ctx->fqctx); fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); fq_nmod_mpoly_scalar_addmul_fq_nmod(f, g, h, c, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(k, h, c, ctx); fq_nmod_mpoly_add(k, k, g, ctx); if (!fq_nmod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: check definition\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(k, g, ctx); fq_nmod_mpoly_scalar_addmul_fq_nmod(k, k, h, c, ctx); if (!fq_nmod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: check aliasing first argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_set(k, h, ctx); fq_nmod_mpoly_scalar_addmul_fq_nmod(k, g, k, c, ctx); if (!fq_nmod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: check aliasing second argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-scalar_mul_fq_nmod.c000066400000000000000000000141451461254215100235030ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_scalar_mul_fq_nmod, state) { int i, j, result; /* Check (f*a)*b = f*(a*b) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k; fq_nmod_t a, b, c; slong len1, len2, len3, len4; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3, exp_bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_init(a, ctx->fqctx); fq_nmod_init(b, ctx->fqctx); fq_nmod_init(c, ctx->fqctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); len4 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; exp_bits4 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); fq_nmod_mpoly_randtest_bits(k, state, len4, exp_bits4, ctx); fq_nmod_randtest(a, state, ctx->fqctx); fq_nmod_randtest(b, state, ctx->fqctx); fq_nmod_mul(c, a, b, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(g, f, a, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(h, g, b, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(k, f, c, ctx); result = fq_nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b)\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(g, f, a, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(g, g, b, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(f, f, c, ctx); result = fq_nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b) with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_clear(a, ctx->fqctx); fq_nmod_clear(b, ctx->fqctx); fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check f*a*inv(a) = f */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h, k; fq_nmod_t a, b; slong len1, len2, len3, len4; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3, exp_bits4; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_init(k, ctx); fq_nmod_init(a, ctx->fqctx); fq_nmod_init(b, ctx->fqctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); len4 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; exp_bits4 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); fq_nmod_mpoly_randtest_bits(k, state, len4, exp_bits4, ctx); fq_nmod_randtest_not_zero(a, state, ctx->fqctx); fq_nmod_inv(b, a, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(g, f, a, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(h, g, b, ctx); result = fq_nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*a*inv(a) = f\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(g, f, a, ctx); fq_nmod_mpoly_scalar_mul_fq_nmod(g, g, b, ctx); result = fq_nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*a*inv(a) = f with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_clear(k, ctx); fq_nmod_clear(a, ctx->fqctx); fq_nmod_clear(b, ctx->fqctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-sort_terms.c000066400000000000000000000040361461254215100220550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_sort_terms, state) { int i, j, result; /* Check scramble and sort */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g; slong len; flint_bitcnt_t exp_bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 20); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); len = n_randint(state, 200); exp_bits = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N, k; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fq_nmod_mpoly_set(g, f, ctx); N = mpoly_words_per_exp(f->bits, ctx->minfo); for (k = WORD(0); k < f->length; k++) { ulong a, b; a = n_randint(state, f->length); b = n_randint(state, f->length); _n_fq_swap(f->coeffs + d*a, f->coeffs + d*b, d); mpoly_monomial_swap(f->exps + N*a, f->exps + N*b, N); } fq_nmod_mpoly_sort_terms(f, ctx); result = fq_nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check scramble and sort\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-sqrt.c000066400000000000000000000126341461254215100206500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_sqrt, state) { slong i, j, tmul = 10; /* Check sqrt(f^2) = +-f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 5) + 1; exp_bits1 = n_randint(state, 5) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_mul(g, f, f, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); sqr = fq_nmod_mpoly_sqrt(h, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); if (!sqr) { flint_printf("FAIL: Check sqrt(f^2) returns 1\n"); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_equal(h, f, ctx) && !(fq_nmod_mpoly_neg(h, h, ctx), fq_nmod_mpoly_equal(h, f, ctx))) { flint_printf("FAIL: Check sqrt(f^2) = +-f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check sqrt(random) */ for (i = 0; i < 2*tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; /* low bits: sqrt(random) is less reliable in positive char */ exp_bits1 = n_randint(state, 20) + 1; for (j = 0; j < 10; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); sqr = fq_nmod_mpoly_sqrt(g, f, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); if (sqr) { fq_nmod_mpoly_mul(g, g, g, ctx); if (!fq_nmod_mpoly_equal(g, f, ctx)) { flint_printf("FAIL: Check sqrt(random)\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } else if (!fq_nmod_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of square root with input */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr1, sqr2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 5); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); fq_nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); fq_nmod_mpoly_mul(g, f, f, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); sqr1 = fq_nmod_mpoly_sqrt(h, g, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); sqr2 = fq_nmod_mpoly_sqrt(g, g, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); if (sqr1 != sqr2 || !fq_nmod_mpoly_equal(g, h, ctx)) { printf("FAIL: Check aliasing\n"); flint_printf("\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-total_degree.c000066400000000000000000000116011461254215100223060ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" /* foolproof way to check totdeg_check is correct */ void _check_total_degree(const fmpz_t totdeg_check, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { fmpz_t totdeg; fmpz_init(totdeg); mpoly_total_degree_fmpz_ref(totdeg, A->exps, A->length, A->bits, ctx->minfo); if (!fmpz_equal(totdeg_check, totdeg)) flint_throw(FLINT_ERROR, "Total degree is wrong"); fmpz_clear(totdeg); } TEST_FUNCTION_START(fq_nmod_mpoly_total_degree, state) { int i, j; /* Check total_degree does not go up under addition */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_add(h, f, g, ctx); fq_nmod_mpoly_total_degree_fmpz(hdeg, h, ctx); fq_nmod_mpoly_total_degree_fmpz(fdeg, f, ctx); fq_nmod_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } /* Check total_degree adds under multiplication */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { int ok; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_mul(h, f, g, ctx); fq_nmod_mpoly_total_degree_fmpz(hdeg, h, ctx); fq_nmod_mpoly_total_degree_fmpz(fdeg, f, ctx); fq_nmod_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if (fq_nmod_mpoly_is_zero(f, ctx) || fq_nmod_mpoly_is_zero(g, ctx)) { ok = fmpz_equal_si(hdeg, -WORD(1)) && (fmpz_equal_si(fdeg, -WORD(1)) || fmpz_equal_si(gdeg, -WORD(1))); } else { fmpz_add(gdeg, gdeg, fdeg); ok = fmpz_equal(hdeg, gdeg); } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-univar.c000066400000000000000000000066551461254215100211710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_univar, state) { slong i, j, k; /* Check mpoly -> mpoly_univar -> mpoly */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, h; fq_nmod_mpoly_univar_t fx, gx; slong len1, len2, n; flint_bitcnt_t exp_bits1, exp_bits2, bits; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(h, ctx); fq_nmod_mpoly_univar_init(fx, ctx); fq_nmod_mpoly_univar_init(gx, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 3*FLINT_BITS) + 1; exp_bits2 = n_randint(state, 3*FLINT_BITS) + 1; for (j = 0; j < ctx->minfo->nvars; j++) { fq_nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); fq_nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); fq_nmod_mpoly_to_univar(fx, f, j, ctx); fq_nmod_mpoly_univar_assert_canonical(fx, ctx); fq_nmod_mpoly_from_univar(g, fx, j, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); if (!fq_nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check mpoly -> mpoly_univar -> mpoly\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } bits = mpoly_fix_bits(f->bits + n_randint(state, FLINT_BITS), ctx->minfo); _fq_nmod_mpoly_from_univar(h, bits, fx, j, ctx); fq_nmod_mpoly_assert_canonical(h, ctx); if (h->bits != bits || !fq_nmod_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check mpoly -> mpoly_univar -> mpoly with bits\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_univar_degree_fits_si(fx, ctx)) continue; n = fq_nmod_mpoly_univar_length(fx, ctx); fq_nmod_mpoly_univar_fit_length(gx, n, ctx); gx->length = n; for (k = 0; k < n; k++) { fq_nmod_mpoly_univar_swap_term_coeff(gx->coeffs + k, fx, k, ctx); fmpz_set_si(gx->exps + k, fq_nmod_mpoly_univar_get_term_exp_si(fx, k, ctx)); } fq_nmod_mpoly_from_univar(g, gx, j, ctx); if (!fq_nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check construction\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(h, ctx); fq_nmod_mpoly_univar_clear(gx, ctx); fq_nmod_mpoly_univar_clear(fx, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-univar_resultant.c000066400000000000000000000136121461254215100232610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" /* fq_nmod_poly_resultant is missing */ #if 0 void test_resultant( const fq_nmod_mpoly_t fx, const fq_nmod_mpoly_t gx, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpoly_univar_t F, G; fq_nmod_poly_t f, g; fq_nmod_mpoly_t R; fq_nmod_t r; fq_nmod_mpoly_univar_init(F, ctx); fq_nmod_mpoly_univar_init(G, ctx); fq_nmod_poly_init(f, ctx->fqctx); fq_nmod_poly_init(g, ctx->fqctx); fq_nmod_mpoly_init(R, ctx); fq_nmod_init(r, ctx->fqctx); fq_nmod_mpoly_get_fq_nmod_poly(f, fx, 0, ctx); fq_nmod_mpoly_get_fq_nmod_poly(g, gx, 0, ctx); fq_nmod_poly_resultant(r, f, g, ctx->fqctx); fq_nmod_mpoly_to_univar(F, fx, 0, ctx); fq_nmod_mpoly_to_univar(G, gx, 0, ctx); fq_nmod_mpoly_univar_resultant(R, F, G, ctx); if (!fq_nmod_mpoly_equal_fq_nmod(R, r, ctx)) { flint_printf("FAIL: Check resultant against univariate\n"); flint_printf("fx: "); fq_nmod_mpoly_print_pretty(fx, NULL, ctx); flint_printf("\n"); flint_printf("gx: "); fq_nmod_mpoly_print_pretty(gx, NULL, ctx); flint_printf("\n"); flint_printf("R: "); fq_nmod_mpoly_print_pretty(R, NULL, ctx); flint_printf("\n"); flint_printf("r: %wu\n", r); fflush(stdout); flint_abort(); } fq_nmod_clear(r, ctx->fqctx); fq_nmod_mpoly_univar_clear(F, ctx); fq_nmod_mpoly_univar_clear(G, ctx); fq_nmod_poly_clear(f, ctx->fqctx); fq_nmod_poly_clear(g, ctx->fqctx); fq_nmod_mpoly_clear(R, ctx); } #endif TEST_FUNCTION_START(fq_nmod_mpoly_univar_resultant, state) { { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t t, s; fq_nmod_mpoly_univar_t f; const char * vars[] = {"a", "b", "c", "d"}; fq_nmod_mpoly_ctx_init_deg(ctx, 4, ORD_DEGLEX, 3, 4); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(s, ctx); fq_nmod_mpoly_univar_init(f, ctx); fq_nmod_mpoly_univar_zero(f, ctx); fq_nmod_mpoly_set_str_pretty(t, "a", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "b", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "1", vars, ctx); fq_nmod_mpoly_univar_discriminant(s, f, ctx); if (!fq_nmod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check linear discriminant\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_univar_zero(f, ctx); fq_nmod_mpoly_set_str_pretty(t, "a", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 2, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "b", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "c", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "b^2-4*a*c", vars, ctx); fq_nmod_mpoly_univar_discriminant(s, f, ctx); if (!fq_nmod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check quadratic discriminant\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_univar_zero(f, ctx); fq_nmod_mpoly_set_str_pretty(t, "a", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 3, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "b", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 2, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "c", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "d", vars, ctx); fq_nmod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); fq_nmod_mpoly_set_str_pretty(t, "b^2*c^2-4*a*c^3-4*b^3*d-27*a^2*d^2+18*a*b*c*d", vars, ctx); fq_nmod_mpoly_univar_discriminant(s, f, ctx); if (!fq_nmod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check cubic discriminant\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(s, ctx); fq_nmod_mpoly_univar_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } #if 0 for (i = 0; i < 10 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f, g, t; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); fq_nmod_mpoly_ctx_init_rand(ctx, state, 1, modulus); fq_nmod_mpoly_init(f, ctx); fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(t, ctx); for (j = 0; j < 10; j++) { fq_nmod_mpoly_randtest_bound(f, state, 3, 3, ctx); if (fq_nmod_mpoly_is_zero(f, ctx)) fq_nmod_mpoly_one(f, ctx); fq_nmod_mpoly_zero(g, ctx); while (fq_nmod_mpoly_degree_si(f, 0, ctx) < 100) { fq_nmod_mpoly_randtest_bound(t, state, 5, 10, ctx); fq_nmod_mpoly_mul(t, t, f, ctx); fq_nmod_mpoly_add(g, g, t, ctx); fq_nmod_mpoly_swap(f, g, ctx); } fq_nmod_mpoly_randtest_bound(f, state, 20, 50, ctx); fq_nmod_mpoly_randtest_bound(g, state, 20, 50, ctx); test_resultant(f, g, ctx); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/test/t-used_vars.c000066400000000000000000000044071461254215100216510ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly.h" TEST_FUNCTION_START(fq_nmod_mpoly_used_vars, state) { slong i, j, k; for (i = 0; i < 20 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t f; fmpz_t fdeg; slong len, var; fq_nmod_t one; flint_bitcnt_t exp_bits; int * used; fq_nmod_mpoly_ctx_init_rand(ctx, state, 20, FLINT_BITS, 10); fq_nmod_mpoly_init(f, ctx); fmpz_init(fdeg); fq_nmod_init(one, ctx->fqctx); fq_nmod_sub_one(one, one, ctx->fqctx); fq_nmod_neg(one, one, ctx->fqctx); used = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, int); for (j = 0; j < ctx->minfo->nvars; j++) { len = n_randint(state, 200); exp_bits = n_randint(state, 200) + 2; fq_nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (k = n_randint(state, ctx->minfo->nvars); k > 0; k--) { var = n_randint(state, ctx->minfo->nvars); fq_nmod_mpoly_evaluate_one_fq_nmod(f, f, var, one, ctx); } fq_nmod_mpoly_used_vars(used, f, ctx); for (var = 0; var < ctx->minfo->nvars; var++) { fq_nmod_mpoly_degree_fmpz(fdeg, f, var, ctx); if ((fmpz_sgn(fdeg) <= 0) != !used[var]) { flint_printf("FAIL: checked used matches degree\n"); flint_printf("var = %wd\n", var); flint_printf("deg: "); fmpz_print(fdeg); flint_printf("\n"); fflush(stdout); flint_abort(); } } } flint_free(used); fq_nmod_clear(one, ctx->fqctx); fmpz_clear(fdeg); fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly/to_from_fq_nmod_poly.c000066400000000000000000000071461461254215100226540ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" /* set A(x_var^Bstride[var]) to B/xbar^Bshifts it is asserted that the conversion is correct */ void _fq_nmod_mpoly_to_fq_nmod_poly_deflate( fq_nmod_poly_t A, const fq_nmod_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); ulong mask; slong i, shift, off, N; slong len = B->length; mp_limb_t * coeff = B->coeffs; ulong * exp = B->exps; ulong var_shift, var_stride; flint_bitcnt_t bits = B->bits; fq_nmod_t cc; FLINT_ASSERT(len > 0); FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo); fq_nmod_init(cc, ctx->fqctx); fq_nmod_poly_zero(A, ctx->fqctx); mask = (-UWORD(1)) >> (FLINT_BITS - bits); var_shift = Bshift[var]; var_stride = Bstride[var]; for (i = 0; i < len; i++) { ulong k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT(k >= var_shift); k -= var_shift; if (k != 0) { k /= var_stride; } n_fq_get_fq_nmod(cc, coeff + d*i, ctx->fqctx); fq_nmod_poly_set_coeff(A, k, cc, ctx->fqctx); } fq_nmod_clear(cc, ctx->fqctx); #if FLINT_WANT_ASSERT for (i = 0; i < len; i++) { slong v; for (v = 0; v < ctx->minfo->nvars; v++) { ulong k; mpoly_gen_offset_shift_sp(&off, &shift, v, bits, ctx->minfo); k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT( (v == var && k >= Bshift[v]) || (v != var && k == Bshift[v])); } } #endif } /* set A to B(x_var^Astride[var])*xbar^Ashift A must be packed into bits = Abits */ void _fq_nmod_mpoly_from_fq_nmod_poly_inflate( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp_sp(Abits, ctx->minfo); slong k, Alen; ulong * shiftexp, * strideexp; slong Bdeg = fq_nmod_poly_degree(B, ctx->fqctx); TMP_INIT; TMP_START; /* must have at least space for the highest exponent of var */ FLINT_ASSERT(Bdeg >= 0); FLINT_ASSERT(1 + FLINT_BIT_COUNT(Ashift[var] + Bdeg*Astride[var]) <= Abits); strideexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); shiftexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ui(shiftexp, Ashift, Abits, ctx->minfo); mpoly_gen_monomial_sp(strideexp, var, Abits, ctx->minfo); mpoly_monomial_mul_ui(strideexp, strideexp, N, Astride[var]); fq_nmod_mpoly_fit_length_reset_bits(A, Bdeg + 1, Abits, ctx); Alen = 0; for (k = Bdeg; k >= 0; k--) { n_fq_set_fq_nmod(A->coeffs + d*Alen, B->coeffs + k, ctx->fqctx); if (!_n_fq_is_zero(A->coeffs + d*Alen, d)) { mpoly_monomial_madd(A->exps + N*Alen, shiftexp, k, strideexp, N); Alen++; } } _fq_nmod_mpoly_set_length(A, Alen, ctx); TMP_END; } flint-3.1.3/src/fq_nmod_mpoly/univar.c000066400000000000000000000454701461254215100177470ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_univar_init( fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; } void fq_nmod_mpoly_univar_clear(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = A->alloc - 1; i >= 0; i--) { fq_nmod_mpoly_clear(A->coeffs + i, ctx); fmpz_clear(A->exps + i); } if (A->coeffs) flint_free(A->coeffs); if (A->exps) flint_free(A->exps); } void fq_nmod_mpoly_univar_fit_length(fq_nmod_mpoly_univar_t A, slong length, const fq_nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { if (old_alloc == 0) { A->exps = (fmpz *) flint_malloc(new_alloc*sizeof(fmpz)); A->coeffs = (fq_nmod_mpoly_struct *) flint_malloc( new_alloc*sizeof(fq_nmod_mpoly_struct)); } else { A->exps = (fmpz *) flint_realloc(A->exps, new_alloc*sizeof(fmpz)); A->coeffs = (fq_nmod_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_nmod_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) { fmpz_init(A->exps + i); fq_nmod_mpoly_init(A->coeffs + i, ctx); } A->alloc = new_alloc; } } void fq_nmod_mpoly_univar_set_coeff_ui( fq_nmod_mpoly_univar_t A, ulong e, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; for (i = A->length; i >= 0; i--) { int cmp = i > 0 ? fmpz_cmp_ui(A->exps + i - 1, e) : 1; if (cmp > 0) { if (fq_nmod_mpoly_is_zero(c, ctx)) return; fq_nmod_mpoly_univar_fit_length(A, A->length + 1, ctx); for (j = A->length; j > i; j--) { fq_nmod_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } A->length++; fmpz_set_ui(A->exps + i, e); fq_nmod_mpoly_set(A->coeffs + i, c, ctx); return; } else if (cmp == 0) { fq_nmod_mpoly_set(A->coeffs + i, c, ctx); if (!fq_nmod_mpoly_is_zero(A->coeffs + i, ctx)) return; A->length--; for (j = i; j < A->length; j++) { fq_nmod_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } } } FLINT_ASSERT(0 && "unreachable"); return; } int fq_nmod_mpoly_univar_degree_fits_si(const fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) { return A->length == 0 || fmpz_fits_si(A->exps + 0); } slong fq_nmod_mpoly_univar_get_term_exp_si(fq_nmod_mpoly_univar_t A, slong i, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong)A->length); return fmpz_get_si(A->exps + i); } void fq_nmod_mpoly_univar_assert_canonical(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i + 1 < A->length; i++) { if (fmpz_cmp(A->exps + i, A->exps + i + 1) <= 0 || fmpz_sgn(A->exps + i) < 0 || fmpz_sgn(A->exps + i + 1) < 0) { flint_throw(FLINT_ERROR, "Univariate polynomial exponents out of order"); } } for (i = 0; i < A->length; i++) fq_nmod_mpoly_assert_canonical(A->coeffs + i, ctx); } void fq_nmod_mpoly_univar_print_pretty(const fq_nmod_mpoly_univar_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (A->length == 0) flint_printf("0"); for (i = 0; i < A->length; i++) { if (i != 0) flint_printf("+"); flint_printf("("); fq_nmod_mpoly_print_pretty(A->coeffs + i,x,ctx); flint_printf(")*X^"); fmpz_print(A->exps + i); } } static void _tree_data_clear_sp( fq_nmod_mpoly_univar_t A, mpoly_rbtree_ui_t tree, slong idx, const fq_nmod_mpoly_ctx_t ctx) { mpoly_rbnode_ui_struct * nodes = tree->nodes + 2; fq_nmod_mpoly_struct * data = (fq_nmod_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_sp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set_ui(A->exps + A->length, nodes[idx].key); fq_nmod_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fq_nmod_mpoly_clear(data + idx, ctx); _tree_data_clear_sp(A, tree, nodes[idx].left, ctx); } static void _tree_data_clear_mp( fq_nmod_mpoly_univar_t A, mpoly_rbtree_fmpz_t tree, slong idx, const fq_nmod_mpoly_ctx_t ctx) { mpoly_rbnode_fmpz_struct * nodes = tree->nodes + 2; fq_nmod_mpoly_struct * data = (fq_nmod_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_mp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set(A->exps + A->length, nodes[idx].key); fq_nmod_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fq_nmod_mpoly_clear(data + idx, ctx); _tree_data_clear_mp(A, tree, nodes[idx].left, ctx); } /* the coefficients of A should be constructed with the same bits as B */ void fq_nmod_mpoly_to_univar(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong shift, off; slong Blen = B->length; const mp_limb_t * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; slong i; int its_new; ulong * one; #define LUT_limit (48) fq_nmod_mpoly_struct LUT[LUT_limit]; if (B->length == 0) { A->length = 0; return; } one = FLINT_ARRAY_ALLOC(N, ulong); if (bits <= FLINT_BITS) { slong Alen; mpoly_rbtree_ui_t tree; fq_nmod_mpoly_struct * t; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); mpoly_rbtree_ui_init(tree, sizeof(fq_nmod_mpoly_struct)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); for (i = 0; i < LUT_limit; i++) fq_nmod_mpoly_init3(LUT + i, 4, bits, ctx); /* fill in tree/LUT from B */ for (i = 0; i < Blen; i++) { ulong k = (Bexp[N*i + off] >> shift) & mask; if (k < LUT_limit) { t = LUT + k; } else { t = mpoly_rbtree_ui_lookup(tree, &its_new, k); if (its_new) fq_nmod_mpoly_init3(t, 4, bits, ctx); } fq_nmod_mpoly_fit_length(t, t->length + 1, ctx); _n_fq_set(t->coeffs + d*t->length, Bcoeff + d*i, d); mpoly_monomial_msub(t->exps + N*t->length, Bexp + N*i, k, one, N); t->length++; } /* clear out tree to A */ Alen = tree->length; for (i = LUT_limit - 1; i >= 0; i--) Alen += (LUT[i].length > 0); fq_nmod_mpoly_univar_fit_length(A, Alen, ctx); A->length = 0; _tree_data_clear_sp(A, tree, mpoly_rbtree_ui_head(tree), ctx); for (i = LUT_limit - 1; i >= 0; i--) { t = LUT + i; if (t->length > 0) { FLINT_ASSERT(A->length < A->alloc); fmpz_set_si(A->exps + A->length, i); fq_nmod_mpoly_swap(A->coeffs + A->length, t, ctx); A->length++; } fq_nmod_mpoly_clear(t, ctx); } mpoly_rbtree_ui_clear(tree); } else { mpoly_rbtree_fmpz_t tree; fq_nmod_mpoly_struct * t; fmpz_t k; fmpz_init(k); mpoly_rbtree_fmpz_init(tree, sizeof(fq_nmod_mpoly_struct)); off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); /* fill in tree from B */ for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexp + N*i + off, bits/FLINT_BITS); t = mpoly_rbtree_fmpz_lookup(tree, &its_new, k); if (its_new) fq_nmod_mpoly_init3(t, 4, bits, ctx); fq_nmod_mpoly_fit_length(t, t->length + 1, ctx); _n_fq_set(t->coeffs + d*t->length, Bcoeff + d*i, d); mpoly_monomial_msub_ui_array(t->exps + N*t->length, Bexp + N*i, Bexp + N*i + off, bits/FLINT_BITS, one, N); t->length++; } /* clear out tree to A */ fq_nmod_mpoly_univar_fit_length(A, tree->length, ctx); A->length = 0; _tree_data_clear_mp(A, tree, mpoly_rbtree_fmpz_head(tree), ctx); fmpz_clear(k); mpoly_rbtree_fmpz_clear(tree); } flint_free(one); } /* Currently this function does not work if the coefficients depend on "var". The assertion x->next == NULL would need to be replaced by a loop. Other asserts would need to be removed as well. */ void _fq_nmod_mpoly_from_univar( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_univar_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i; slong next_loc, heap_len = 1; ulong * cmpmask; slong total_len; mpoly_heap_s * heap; slong Alen; ulong ** Btexp; ulong * exp; ulong * one; mpoly_heap_t * chain, * x; TMP_INIT; if (B->length == 0) { fq_nmod_mpoly_fit_length_reset_bits(A, 0, Abits, ctx); A->length = 0; return; } TMP_START; /* pack everything into Abits */ one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); Btexp = (ulong **) TMP_ALLOC(B->length*sizeof(ulong*)); total_len = 0; for (i = 0; i < B->length; i++) { fq_nmod_mpoly_struct * Bi = B->coeffs + i; total_len += Bi->length; Btexp[i] = Bi->exps; if (Abits != Bi->bits) { Btexp[i] = (ulong *) flint_malloc(N*Bi->length*sizeof(ulong)); if (!mpoly_repack_monomials(Btexp[i], Abits, Bi->exps, Bi->bits, Bi->length, ctx->minfo)) { FLINT_ASSERT(0 && "repack does not fit"); } } } fq_nmod_mpoly_fit_length_reset_bits(A, total_len, Abits, ctx); next_loc = B->length + 2; heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); exp = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); Alen = 0; if (Abits <= FLINT_BITS) { mpoly_gen_monomial_sp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { FLINT_ASSERT(fmpz_fits_si(B->exps + i)); x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + i), one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); _n_fq_set(A->coeffs + d*Alen, (B->coeffs + x->i)->coeffs + d*x->j, d); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { FLINT_ASSERT(fmpz_fits_si(B->exps + x->i)); x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + x->i), one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } else { mpoly_gen_monomial_offset_mp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + i, one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); _n_fq_set(A->coeffs + d*Alen, (B->coeffs + x->i)->coeffs + d*x->j, d); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + x->i, one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } A->length = Alen; for (i = 0; i < B->length; i++) { if (Btexp[i] != (B->coeffs + i)->exps) flint_free(Btexp[i]); } TMP_END; } void fq_nmod_mpoly_from_univar(fq_nmod_mpoly_t A, const fq_nmod_mpoly_univar_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong n = ctx->minfo->nfields; flint_bitcnt_t bits; slong i; fmpz * gen_fields, * tmp_fields, * max_fields; TMP_INIT; if (B->length == 0) { fq_nmod_mpoly_zero(A, ctx); return; } TMP_START; /* find bits required to represent result */ gen_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); tmp_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(gen_fields + i); fmpz_init(tmp_fields + i); fmpz_init(max_fields + i); } mpoly_gen_fields_fmpz(gen_fields, var, ctx->minfo); for (i = 0; i < B->length; i++) { fq_nmod_mpoly_struct * Bi = B->coeffs + i; mpoly_max_fields_fmpz(tmp_fields, Bi->exps, Bi->length, Bi->bits, ctx->minfo); _fmpz_vec_scalar_addmul_fmpz(tmp_fields, gen_fields, n, B->exps + i); _fmpz_vec_max_inplace(max_fields, tmp_fields, n); } bits = _fmpz_vec_max_bits(max_fields, n); bits = FLINT_MAX(MPOLY_MIN_BITS, bits + 1); bits = mpoly_fix_bits(bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(gen_fields + i); fmpz_clear(tmp_fields + i); fmpz_clear(max_fields + i); } TMP_END; _fq_nmod_mpoly_from_univar(A, bits, B, var, ctx); } #define COEFF(A, i) ((void*)(A->coeffs + (i)*R->elem_size)) static void mpoly_univar_set_fq_nmod_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, const fq_nmod_mpoly_univar_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); A->length = B->length; for (i = B->length - 1; i >= 0; i--) { fmpz_set(A->exps + i, B->exps + i); fq_nmod_mpoly_set(COEFF(A, i), B->coeffs + i, ctx); } } static void mpoly_univar_swap_fq_nmod_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, fq_nmod_mpoly_univar_t B, const fq_nmod_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); fq_nmod_mpoly_univar_fit_length(B, A->length, ctx); for (i = FLINT_MAX(A->length, B->length) - 1; i >= 0; i--) { fmpz_swap(A->exps + i, B->exps + i); fq_nmod_mpoly_swap(COEFF(A, i), B->coeffs + i, ctx); } FLINT_SWAP(slong, A->length, B->length); } int fq_nmod_mpoly_univar_pseudo_gcd( fq_nmod_mpoly_univar_t gx, const fq_nmod_mpoly_univar_t ax, const fq_nmod_mpoly_univar_t bx, const fq_nmod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx, Gx; mpoly_void_ring_init_fq_nmod_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_init(Gx, R); mpoly_univar_set_fq_nmod_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_fq_nmod_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_pseudo_gcd_ducos(Gx, Ax, Bx, R); if (success) mpoly_univar_swap_fq_nmod_mpoly_univar(Gx, R, gx, ctx); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); mpoly_univar_clear(Gx, R); return success; } int fq_nmod_mpoly_univar_resultant( fq_nmod_mpoly_t d, const fq_nmod_mpoly_univar_t ax, const fq_nmod_mpoly_univar_t bx, const fq_nmod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx; mpoly_void_ring_init_fq_nmod_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_set_fq_nmod_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_fq_nmod_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_resultant(d, Ax, Bx, R); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); return success; } int fq_nmod_mpoly_univar_discriminant( fq_nmod_mpoly_t d, const fq_nmod_mpoly_univar_t fx, const fq_nmod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Fx; mpoly_void_ring_init_fq_nmod_mpoly_ctx(R, ctx); mpoly_univar_init(Fx, R); mpoly_univar_set_fq_nmod_mpoly_univar(Fx, R, fx, ctx); success = mpoly_univar_discriminant(d, Fx, R); mpoly_univar_clear(Fx, R); return success; } flint-3.1.3/src/fq_nmod_mpoly/void_ring.c000066400000000000000000000077421461254215100204230ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mpoly.h" static void fq_nmod_mpoly_void_init(void * a, const void * ctx) { fq_nmod_mpoly_init(a, ctx); } static void fq_nmod_mpoly_void_clear(void * a, const void * ctx) { fq_nmod_mpoly_clear(a, ctx); } static int fq_nmod_mpoly_void_is_zero(const void * a, const void * ctx) { return fq_nmod_mpoly_is_zero(a, ctx); } static void fq_nmod_mpoly_void_zero(void * a, const void * ctx) { fq_nmod_mpoly_zero(a, ctx); } static void fq_nmod_mpoly_void_one(void * a, const void * ctx) { fq_nmod_mpoly_one(a, ctx); } static void fq_nmod_mpoly_void_set(void * a, const void * b, const void * ctx) { fq_nmod_mpoly_set(a, b, ctx); } static void fq_nmod_mpoly_void_set_fmpz(void * a, const fmpz_t b, const void * ctx) { fq_nmod_mpoly_set_fmpz(a, b, ctx); } static void fq_nmod_mpoly_void_swap(void * a, void * b, const void * ctx) { fq_nmod_mpoly_swap(a, b, ctx); } static void fq_nmod_mpoly_void_neg(void * a, const void * b, const void * ctx) { fq_nmod_mpoly_neg(a, b, ctx); } static void fq_nmod_mpoly_void_add(void * a, const void * b, const void * c, const void * ctx) { fq_nmod_mpoly_add(a, b, c, ctx); } static void fq_nmod_mpoly_void_sub(void * a, const void * b, const void * c, const void * ctx) { fq_nmod_mpoly_sub(a, b, c, ctx); } static void fq_nmod_mpoly_void_mul(void * a, const void * b, const void * c, const void * ctx) { fq_nmod_mpoly_mul(a, b, c, ctx); } static void fq_nmod_mpoly_void_mul_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx_) { const fq_nmod_mpoly_ctx_struct * ctx = ctx_; fq_nmod_t C; fq_nmod_init(C, ctx->fqctx); fq_nmod_set_fmpz(C, c, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(a, b, C, ctx); fq_nmod_clear(C, ctx->fqctx); } static void fq_nmod_mpoly_void_divexact(void * a, const void * b, const void * c, const void * ctx) { if (!fq_nmod_mpoly_divides(a, b, c, ctx)) flint_throw(FLINT_ERROR, "fq_nmod_mpoly_void_divexact: nonexact"); } static int fq_nmod_mpoly_void_divides(void * a, const void * b, const void * c, const void * ctx) { return fq_nmod_mpoly_divides(a, b, c, ctx); } static int fq_nmod_mpoly_void_pow_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { return fq_nmod_mpoly_pow_fmpz(a, b, c, ctx); } static slong fq_nmod_mpoly_void_length(const void * a, const void * ctx) { return fq_nmod_mpoly_length(a, ctx); } void mpoly_void_ring_init_fq_nmod_mpoly_ctx( mpoly_void_ring_t R, const fq_nmod_mpoly_ctx_t ctx) { R->elem_size = sizeof(fq_nmod_mpoly_struct); R->ctx = ctx; R->init = fq_nmod_mpoly_void_init; R->clear = fq_nmod_mpoly_void_clear; R->is_zero = fq_nmod_mpoly_void_is_zero; R->zero = fq_nmod_mpoly_void_zero; R->one = fq_nmod_mpoly_void_one; R->set = fq_nmod_mpoly_void_set; R->set_fmpz = fq_nmod_mpoly_void_set_fmpz; R->swap = fq_nmod_mpoly_void_swap; R->neg = fq_nmod_mpoly_void_neg; R->add = fq_nmod_mpoly_void_add; R->sub = fq_nmod_mpoly_void_sub; R->mul = fq_nmod_mpoly_void_mul; R->mul_fmpz = fq_nmod_mpoly_void_mul_fmpz; R->divexact = fq_nmod_mpoly_void_divexact; R->divides = fq_nmod_mpoly_void_divides; R->pow_fmpz = fq_nmod_mpoly_void_pow_fmpz; R->length = fq_nmod_mpoly_void_length; } flint-3.1.3/src/fq_nmod_mpoly_factor.h000066400000000000000000000370641461254215100200060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_MPOLY_FACTOR_H #define FQ_NMOD_MPOLY_FACTOR_H #ifdef FQ_NMOD_MPOLY_FACTOR_INLINES_C #define FQ_NMOD_MPOLY_FACTOR_INLINE #else #define FQ_NMOD_MPOLY_FACTOR_INLINE static inline #endif #include "fq_nmod_mpoly.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ typedef struct { fq_nmod_t constant; fq_nmod_mpoly_struct * poly; fmpz * exp; slong num; slong alloc; } fq_nmod_mpoly_factor_struct; typedef fq_nmod_mpoly_factor_struct fq_nmod_mpoly_factor_t[1]; void fq_nmod_mpoly_factor_init(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_realloc(fq_nmod_mpoly_factor_t f, slong alloc, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_fit_length(fq_nmod_mpoly_factor_t f, slong len, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_clear(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_FACTOR_INLINE slong fq_nmod_mpoly_factor_length(const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { return f->num; } void fq_nmod_mpoly_factor_get_constant_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_FACTOR_INLINE void fq_nmod_mpoly_factor_get_base(fq_nmod_mpoly_t p, const fq_nmod_mpoly_factor_t f, slong i, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fq_nmod_mpoly_set(p, f->poly + i, ctx); } FQ_NMOD_MPOLY_FACTOR_INLINE void fq_nmod_mpoly_factor_swap_base(fq_nmod_mpoly_t p, const fq_nmod_mpoly_factor_t f, slong i, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); fq_nmod_mpoly_swap(p, f->poly + i, ctx); } slong fq_nmod_mpoly_factor_get_exp_si(fq_nmod_mpoly_factor_t f, slong i, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_set(fq_nmod_mpoly_factor_t a, const fq_nmod_mpoly_factor_t b, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_print_pretty(const fq_nmod_mpoly_factor_t f, const char ** vars, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_append_ui(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, ulong e, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_append_fmpz(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fmpz_t e, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_content(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_squarefree(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_separable(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, int sep); int fq_nmod_mpoly_factor(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_factor_sort(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_cmp(const fq_nmod_mpoly_factor_t A, const fq_nmod_mpoly_factor_t B, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_FACTOR_INLINE void fq_nmod_mpoly_factor_swap(fq_nmod_mpoly_factor_t A, fq_nmod_mpoly_factor_t B, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpoly_factor_struct t = *A; *A = *B; *B = t; } void fq_nmod_mpoly_factor_one(fq_nmod_mpoly_factor_t a, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_expand(fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_FACTOR_INLINE int fq_nmod_mpoly_factor_matches(const fq_nmod_mpoly_t a, const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { int matches; fq_nmod_mpoly_t t; fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_factor_expand(t, f, ctx); matches = fq_nmod_mpoly_equal(t, a, ctx); fq_nmod_mpoly_clear(t, ctx); return matches; } void _fq_nmod_mpoly_get_lead0( fq_nmod_mpoly_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_set_lead0( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); /*****************************************************************************/ void n_fq_bpoly_mul( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const fq_nmod_ctx_t ctx); void n_fq_bpoly_mul_series( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, slong order, const fq_nmod_ctx_t ctx); void n_fq_bpoly_add( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const fq_nmod_ctx_t ctx); void n_fq_bpoly_sub( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const fq_nmod_ctx_t ctx); void n_fq_bpoly_divrem_series( n_bpoly_t Q, n_bpoly_t R, const n_bpoly_t A, const n_bpoly_t B, slong order, const fq_nmod_ctx_t ctx); int n_fq_bpoly_divides( n_bpoly_t Q, const n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx); void n_fq_bpoly_make_primitive( n_poly_t g, n_bpoly_t A, const fq_nmod_ctx_t ctx); void fq_nmod_mpoly_get_n_fq_bpoly( n_bpoly_t A, const fq_nmod_mpoly_t B, slong varx, slong vary, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_set_n_fq_bpoly( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong varx, slong vary, const fq_nmod_mpoly_ctx_t ctx); int n_fq_bpoly_factor_smprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, int allow_shift, const fq_nmod_ctx_t ctx); int n_fq_bpoly_factor_lgprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, const fq_nmod_ctx_t ctx, flint_rand_t state); /*****************************************************************************/ void n_polyu3_fq_print_pretty( const n_polyu_t A, const char * var0, const char * var1, const char * var2, const fq_nmod_ctx_t ctx); int n_polyu_fq_is_canonical( const n_polyu_t A, const fq_nmod_ctx_t ctx); /*****************************************************************************/ void n_polyu2n_fq_print_pretty( const n_polyun_t A, const char * var0, const char * var1, const char * varlast, const fq_nmod_ctx_t ctx); void n_polyu3n_fq_print_pretty( const n_polyun_t A, const char * var0, const char * var1, const char * var2, const char * varlast, const fq_nmod_ctx_t ctx); int n_polyun_fq_is_canonical( const n_polyun_t A, const fq_nmod_ctx_t ctx); /*****************************************************************************/ typedef struct { fq_nmod_mpoly_struct * coeffs; slong alloc; slong length; } fq_nmod_mpolyv_struct; typedef fq_nmod_mpolyv_struct fq_nmod_mpolyv_t[1]; FQ_NMOD_MPOLY_FACTOR_INLINE void fq_nmod_mpolyv_init(fq_nmod_mpolyv_t A, const fq_nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FQ_NMOD_MPOLY_FACTOR_INLINE void fq_nmod_mpolyv_swap(fq_nmod_mpolyv_t A, fq_nmod_mpolyv_t B, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpolyv_struct t = *A; *A = *B; *B = t; } void fq_nmod_mpolyv_clear(fq_nmod_mpolyv_t A, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyv_print_pretty(const fq_nmod_mpolyv_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyv_fit_length(fq_nmod_mpolyv_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpolyv_set_coeff(fq_nmod_mpolyv_t A, slong i, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_to_mpolyv(fq_nmod_mpolyv_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t xalpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_from_mpolyv(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpolyv_t B, const fq_nmod_mpoly_t xalpha, const fq_nmod_mpoly_ctx_t ctx); int _fq_nmod_mpoly_vec_content_mpoly(fq_nmod_mpoly_t g, const fq_nmod_mpoly_struct * A, slong Alen, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_vec_divexact_mpoly(fq_nmod_mpoly_struct * A, slong Alen, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_vec_mul_mpoly(fq_nmod_mpoly_struct * A, slong Alen, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); /*****************************************************************************/ int _fq_nmod_mpoly_factor_separable(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, int sep); int fq_nmod_mpoly_factor_lcc_wang( fq_nmod_mpoly_struct * lc_divs, const fq_nmod_mpoly_factor_t lcAfac, const n_poly_t Auc, const n_bpoly_struct * Auf, slong r, const n_poly_struct * alpha, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_irred_smprime_zassenhaus( fq_nmod_mpolyv_t fac, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state); int fq_nmod_mpoly_factor_irred_lgprime_zassenhaus( fq_nmod_mpolyv_t fac, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state); int fq_nmod_mpoly_factor_irred_smprime_wang( fq_nmod_mpolyv_t fac, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state); int fq_nmod_mpoly_factor_irred_lgprime_wang( fq_nmod_mpolyv_t Af, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state); int fq_nmod_mpoly_factor_irred_smprime_zippel( fq_nmod_mpolyv_t fac, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state); int fq_nmod_mpoly_factor_irred_lgprime_zippel( fq_nmod_mpolyv_t Af, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state); /*****************************************************************************/ void fq_nmod_mpoly_compression_do(fq_nmod_mpoly_t L, const fq_nmod_mpoly_ctx_t Lctx, mp_limb_t * Acoeffs, slong Alen, mpoly_compression_t M); void fq_nmod_mpoly_compression_undo(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t Actx, fq_nmod_mpoly_t L, const fq_nmod_mpoly_ctx_t Lctx, mpoly_compression_t M); /*****************************************************************************/ typedef struct { flint_bitcnt_t bits; slong w; slong r; fq_nmod_poly_struct * inv_prod_dbetas; fq_nmod_mpoly_struct * inv_prod_dbetas_mvar; fq_nmod_poly_struct * dbetas; fq_nmod_mpoly_struct * dbetas_mvar; fq_nmod_mpoly_struct * prod_mbetas; fq_nmod_mpolyv_struct * prod_mbetas_coeffs; fq_nmod_mpoly_struct * mbetas; fq_nmod_mpoly_struct * deltas; fq_nmod_mpoly_struct * xalpha; fq_nmod_mpoly_struct * q; fq_nmod_mpoly_geobucket_struct * G; fq_nmod_mpoly_struct * qt; fq_nmod_mpoly_struct * newt; fq_nmod_mpolyv_struct * delta_coeffs; fq_nmod_mpoly_t T; fq_nmod_mpoly_t Q; fq_nmod_mpoly_t R; } fq_nmod_mpoly_pfrac_struct; typedef fq_nmod_mpoly_pfrac_struct fq_nmod_mpoly_pfrac_t[1]; int fq_nmod_mpoly_pfrac_init( fq_nmod_mpoly_pfrac_t I, flint_bitcnt_t bits, slong l, slong r, const fq_nmod_mpoly_struct * betas, const fq_nmod_struct * alpha, const fq_nmod_mpoly_ctx_t ctx); void fq_nmod_mpoly_pfrac_clear( fq_nmod_mpoly_pfrac_t I, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_pfrac( slong r, fq_nmod_mpoly_t t, const slong * deg, fq_nmod_mpoly_pfrac_t I, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_hlift( slong m, fq_nmod_mpoly_struct * f, /* length r */ slong r, const fq_nmod_struct * alpha, const fq_nmod_mpoly_t A, const slong * degs, const fq_nmod_mpoly_ctx_t ctx); int n_fq_bpoly_hlift2_cubic( n_fq_bpoly_t A, /* clobbered (shifted by alpha) */ n_fq_bpoly_t B0, n_fq_bpoly_t B1, const fq_nmod_t alpha_, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, nmod_eval_interp_t E, n_poly_bpoly_stack_t St); int n_fq_bpoly_hlift2( n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_t B0, n_bpoly_t B1, const fq_nmod_t alpha, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t St); int n_fq_bpoly_hlift_cubic( n_fq_bpoly_t A, /* clobbered (shifted by alpha) */ n_fq_bpoly_t B0, n_fq_bpoly_t B1, const fq_nmod_t alpha_, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, nmod_eval_interp_t E, n_poly_bpoly_stack_t St); int n_fq_bpoly_hlift( slong r, n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_struct * B, const fq_nmod_t alpha, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t St); int n_fq_polyu3_hlift( slong r, n_polyun_struct * BB, n_polyu_t A, n_polyu_struct * B, const fq_nmod_t beta, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t St); int fq_nmod_mpoly_factor_algo(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo); int fq_nmod_mpoly_factor_wang(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_zassenhaus(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int fq_nmod_mpoly_factor_zippel(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); int _fq_nmod_mpoly_eval_rest_n_fq_poly(n_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, slong var, const n_fq_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, const fq_nmod_ctx_t ctx); void _fq_nmod_mpoly_eval_rest_to_n_fq_bpoly(n_bpoly_t E, const fq_nmod_mpoly_t A, const n_poly_struct * alphabetas, const fq_nmod_mpoly_ctx_t ctx); void _fq_nmod_mpoly_set_n_fq_bpoly_gen1_zero(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_nmod_mpoly_factor/000077500000000000000000000000001461254215100176235ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mpoly_factor/append.c000066400000000000000000000020641461254215100212400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_append_ui( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, ulong e, const fq_nmod_mpoly_ctx_t ctx) { slong i = f->num; fq_nmod_mpoly_factor_fit_length(f, i + 1, ctx); fq_nmod_mpoly_set(f->poly + i, A, ctx); fmpz_set_ui(f->exp + i, e); f->num = i + 1; } void fq_nmod_mpoly_factor_append_fmpz( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fmpz_t e, const fq_nmod_mpoly_ctx_t ctx) { slong i = f->num; fq_nmod_mpoly_factor_fit_length(f, i + 1, ctx); fq_nmod_mpoly_set(f->poly + i, A, ctx); fmpz_set(f->exp + i, e); f->num = i + 1; } flint-3.1.3/src/fq_nmod_mpoly_factor/clear.c000066400000000000000000000015201461254215100210530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_clear( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { if (f->alloc > 0) { slong i; for (i = 0; i < f->alloc; i++) { fq_nmod_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } flint_free(f->poly); flint_free(f->exp); } fq_nmod_clear(f->constant, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly_factor/cmp.c000066400000000000000000000020371461254215100205500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mpoly_factor.h" int fq_nmod_mpoly_factor_cmp( const fq_nmod_mpoly_factor_t A, const fq_nmod_mpoly_factor_t B, const fq_nmod_mpoly_ctx_t ctx) { int cmp; slong i; cmp = fq_nmod_cmp(A->constant, B->constant, ctx->fqctx); if (cmp != 0) return cmp; if (A->num != B->num) return A->num > B->num ? 1 : -1; for (i = 0; i < A->num; i++) { cmp = fmpz_cmp(A->exp + i, B->exp + i); if (cmp != 0) return cmp; cmp = fq_nmod_mpoly_cmp(A->poly + i, B->poly + i, ctx); if (cmp != 0) return cmp; } return 0; } flint-3.1.3/src/fq_nmod_mpoly_factor/compression.c000066400000000000000000000064451461254215100223410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_compression_do( fq_nmod_mpoly_t L, const fq_nmod_mpoly_ctx_t Lctx, mp_limb_t * Acoeffs, slong Alen, mpoly_compression_t M) { slong d = fq_nmod_ctx_degree(Lctx->fqctx); slong i, max_deg; flint_bitcnt_t Lbits; slong mvars = Lctx->minfo->nvars; slong nvars = M->nvars; slong LN; FLINT_ASSERT(mvars == M->mvars); max_deg = M->degs[0]; for (i = 1; i < mvars; i++) max_deg = FLINT_MAX(max_deg, M->degs[i]); Lbits = mpoly_fix_bits(1 + FLINT_BIT_COUNT(max_deg), Lctx->minfo); fq_nmod_mpoly_fit_length_reset_bits(L, Alen, Lbits, Lctx); LN = mpoly_words_per_exp_sp(Lbits, Lctx->minfo); L->length = Alen; for (i = 0; i < Alen; i++) { _n_fq_set(L->coeffs + d*i, Acoeffs + d*i, d); mpoly_set_monomial_ui(L->exps + LN*i, (ulong *)M->exps + nvars*i, Lbits, Lctx->minfo); } fq_nmod_mpoly_sort_terms(L, Lctx); fq_nmod_mpoly_make_monic(L, L, Lctx); } void fq_nmod_mpoly_compression_undo( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t Actx, fq_nmod_mpoly_t L, const fq_nmod_mpoly_ctx_t Lctx, mpoly_compression_t M) { slong d = fq_nmod_ctx_degree(Lctx->fqctx); slong i, k, l; slong nvars = Actx->minfo->nvars; slong NA = mpoly_words_per_exp(Abits, Actx->minfo); slong mvars = Lctx->minfo->nvars; flint_bitcnt_t Lbits = L->bits; slong NL = mpoly_words_per_exp(Lbits, Lctx->minfo); slong * mins, * texps; TMP_INIT; FLINT_ASSERT(mvars == M->mvars); FLINT_ASSERT(fq_nmod_mpoly_degrees_fit_si(L, Lctx)); TMP_START; texps = (slong *) TMP_ALLOC(nvars*sizeof(slong)); mins = (slong *) TMP_ALLOC(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) mins[k] = WORD_MAX; _slong_array_fit_length(&M->exps, &M->exps_alloc, L->length*nvars); fq_nmod_mpoly_fit_length_reset_bits(A, L->length, Abits, Actx); _fq_nmod_mpoly_set_length(A, L->length, Actx); for (i = 0; i < L->length; i++) { _n_fq_set(A->coeffs + d*i, L->coeffs + d*i, d); mpoly_get_monomial_ui((ulong *)texps, L->exps + NL*i, Lbits, Lctx->minfo); for (k = 0; k < nvars; k++) { slong tot = M->deltas[k]; for (l = 0; l < mvars; l++) tot += M->umat[k*nvars + l]*texps[l]; M->exps[i*nvars + k] = tot; mins[k] = FLINT_MIN(mins[k], tot); } } for (i = 0; i < L->length; i++) { for (k = 0; k < nvars; k++) M->exps[i*nvars + k] -= mins[k]; mpoly_set_monomial_ui(A->exps + NA*i, (ulong *)M->exps + i*nvars, Abits, Actx->minfo); } TMP_END; fq_nmod_mpoly_sort_terms(A, Actx); fq_nmod_mpoly_make_monic(A, A, Actx); } flint-3.1.3/src/fq_nmod_mpoly_factor/eval.c000066400000000000000000000141511461254215100207200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" /* only E and alphas are shifted by "var" so output is in E[0] */ int _fq_nmod_mpoly_eval_rest_n_fq_poly( n_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, slong var, const n_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, const fq_nmod_ctx_t ctx) { slong v, stop; ulong next_e; FLINT_ASSERT(var < nvars); E -= var; alphas -= var; v = var; starts[v] = 0; ends[v] = Alen; n_poly_zero(E + v); if (Alen < 1) return 1; calculate: /* input: v starts[v] ends[v] */ FLINT_ASSERT(ends[v] > starts[v]); es[v] = mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]); n_poly_zero(E + v); next: FLINT_ASSERT(es[v] == (mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]))); stop = starts[v] + 1; while (stop < ends[v] && (mask & (Aexps[N*stop + offsets[v]] >> shifts[v])) == es[v]) { stop++; } stops[v] = stop; if (v + 1 < nvars) { starts[v + 1] = starts[v]; ends[v + 1] = stops[v]; v++; goto calculate; calculate_return: n_fq_poly_add(E + v, E + v, E + v + 1, ctx); } else { slong d = fq_nmod_ctx_degree(ctx); n_fq_poly_set_n_fq(E + v + 1, Acoeffs + d*starts[v], ctx); n_fq_poly_add(E + v, E + v, E + v + 1, ctx); } if (stops[v] < ends[v]) { next_e = mask & (Aexps[N*stops[v] + offsets[v]] >> shifts[v]); FLINT_ASSERT(next_e < es[v]); n_fq_poly_pow(E + v + 1, alphas + v, es[v] - next_e, ctx); n_fq_poly_mul(E + v, E + v, E + v + 1, ctx); es[v] = next_e; starts[v] = stops[v]; goto next; } else { n_fq_poly_pow(E + v + 1, alphas + v, es[v], ctx); n_fq_poly_mul(E + v, E + v, E + v + 1, ctx); } if (v > var) { v--; goto calculate_return; } return 1; } void _fq_nmod_mpoly_eval_rest_to_n_fq_bpoly( n_bpoly_t E, const fq_nmod_mpoly_t A, const n_poly_struct * alphabetas, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong n = ctx->minfo->nvars; slong i, N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong * offsets, * shifts; slong offset, shift; slong start, stop; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * starts, * ends, * stops; ulong * es; n_poly_struct * realE; E->length = 0; if (A->length < 1) return; starts = FLINT_ARRAY_ALLOC(n, slong); ends = FLINT_ARRAY_ALLOC(n, slong); stops = FLINT_ARRAY_ALLOC(n, slong); es = FLINT_ARRAY_ALLOC(n, ulong); realE = FLINT_ARRAY_ALLOC(n + 1, n_poly_struct); for (i = 0; i < n + 1; i++) n_poly_init(realE + i); offsets = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); shifts = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); for (i = 0; i < ctx->minfo->nvars; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, A->bits, ctx->minfo); offset = offsets[0]; shift = shifts[0]; start = 0; e = mask & (A->exps[N*start + offset] >> shift); next: FLINT_ASSERT(start < A->length); FLINT_ASSERT(e == (mask & (A->exps[N*start + offset] >> shift))); stop = start + 1; while (stop < A->length && (mask & (A->exps[N*stop + offset] >> shift)) == e) stop++; n_bpoly_fit_length(E, e + 1); while (E->length <= e) { n_poly_zero(E->coeffs + E->length); E->length++; } _fq_nmod_mpoly_eval_rest_n_fq_poly(realE, starts, ends, stops, es, A->coeffs + d*start, A->exps + N*start, stop - start, 1, alphabetas, offsets, shifts, N, mask, ctx->minfo->nvars, ctx->fqctx); n_fq_poly_set(E->coeffs + e, realE + 0, ctx->fqctx); if (stop < A->length) { FLINT_ASSERT(e > (mask & (A->exps[N*stop + offset] >> shift))); e = (mask & (A->exps[N*stop + offset] >> shift)); start = stop; goto next; } n_bpoly_normalise(E); for (i = 0; i < n + 1; i++) n_poly_clear(realE + i); flint_free(realE); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); } /* A = B(gen(var), 0) */ void _fq_nmod_mpoly_set_n_fq_bpoly_gen1_zero( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong var, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; slong Blen = B->length; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += (B->coeffs[i].length > 0); fq_nmod_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { n_fq_bpoly_get_coeff_n_fq(A->coeffs + d*Alen, B, i, 0, ctx->fqctx); if (_n_fq_is_zero(A->coeffs + d*Alen, d)) continue; if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } flint-3.1.3/src/fq_nmod_mpoly_factor/expand.c000066400000000000000000000022051461254215100212450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod_mpoly_factor.h" int fq_nmod_mpoly_factor_expand( fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { int success = 1; slong i; fq_nmod_mpoly_t t1, t2; fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); fq_nmod_mpoly_set_fq_nmod(A, f->constant, ctx); for (i = 0; i < f->num; i++) { if (fmpz_sgn(f->exp + i) < 0 || !fq_nmod_mpoly_pow_fmpz(t1, f->poly + i, f->exp + i, ctx)) { success = 0; goto cleanup; } fq_nmod_mpoly_mul(t2, A, t1, ctx); fq_nmod_mpoly_swap(A, t2, ctx); } cleanup: fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/factor.c000066400000000000000000000677271461254215100212700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" static slong _deflate( fq_nmod_mpoly_t A, slong tot_deg, const ulong * strides, const slong * perm, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; slong nvars = ctx->minfo->nvars; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong * texps, * sexps; TMP_INIT; for (j = 0; j < nvars; j++) { if (strides[j] != 1 || perm[j] != j) goto do_it; } return tot_deg; do_it: TMP_START; texps = (ulong *) TMP_ALLOC(2*nvars*sizeof(ulong)); sexps = texps + nvars; tot_deg = 1; for (i = 0; i < A->length; i++) { slong this_deg = 0; mpoly_get_monomial_ui(texps, A->exps + N*i, bits, ctx->minfo); for (j = 0; j < nvars; j++) { FLINT_ASSERT(0 == texps[j] % strides[j]); texps[j] = texps[j]/strides[j]; } for (j = 0; j < nvars; j++) { sexps[j] = texps[perm[j]]; this_deg += sexps[j]; } tot_deg = FLINT_MAX(tot_deg, this_deg); mpoly_set_monomial_ui(A->exps + N*i, sexps, bits, ctx->minfo); } TMP_END; fq_nmod_mpoly_sort_terms(A, ctx); fq_nmod_mpoly_make_monic(A, A, ctx); return tot_deg; } static void _inflate( fq_nmod_mpoly_t A, flint_bitcnt_t bits, const ulong * strides, const slong * perm, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; slong nvars = ctx->minfo->nvars; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong * texps, * sexps; TMP_INIT; for (j = 0; j < nvars; j++) { if (strides[j] != 1 || perm[j] != j) goto do_it; } return; do_it: fq_nmod_mpoly_repack_bits_inplace(A, bits, ctx); TMP_START; texps = (ulong *) TMP_ALLOC(2*nvars*sizeof(ulong)); sexps = texps + nvars; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ui(sexps, A->exps + N*i, bits, ctx->minfo); for (j = 0; j < nvars; j++) texps[perm[j]] = sexps[j]; for (j = 0; j < nvars; j++) texps[j] = texps[j]*strides[j]; mpoly_set_monomial_ui(A->exps + N*i, texps, bits, ctx->minfo); } TMP_END; fq_nmod_mpoly_sort_terms(A, ctx); fq_nmod_mpoly_make_monic(A, A, ctx); return; } /* A has degree 2 wrt gen(0) */ static int _apply_quadratic( fq_nmod_mpolyv_t Af, fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { int success; slong i, shift, off, N, d; flint_bitcnt_t bits = A->bits; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); fq_nmod_mpoly_t a_mock, b_mock, c_mock; fq_nmod_mpoly_t t0, t1, t2, t3; FLINT_ASSERT(A->length > 1 || A->coeffs[0] != 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); fq_nmod_mpoly_init(t0, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); fq_nmod_mpoly_init(t3, ctx); mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo); N = mpoly_words_per_exp_sp(bits, ctx->minfo); d = fq_nmod_ctx_degree(ctx->fqctx); i = 0; a_mock->exps = A->exps + N*i; a_mock->coeffs = A->coeffs + d*i; a_mock->bits = bits; while (i < A->length && (mask & (A->exps[N*i + off] >> shift)) == 2) i++; a_mock->length = i; a_mock->coeffs_alloc = d*a_mock->length; a_mock->exps_alloc = N*a_mock->length; b_mock->exps = A->exps + N*i; b_mock->coeffs = A->coeffs + d*i; b_mock->bits = bits; while (i < A->length && (mask & (A->exps[N*i + off] >> shift)) == 1) i++; b_mock->length = i - a_mock->length; b_mock->coeffs_alloc = d*b_mock->length; b_mock->exps_alloc = N*b_mock->length; c_mock->exps = A->exps + N*i; c_mock->coeffs = A->coeffs + d*i; c_mock->bits = bits; c_mock->length = A->length - i; c_mock->coeffs_alloc = d*c_mock->length; c_mock->exps_alloc = N*c_mock->length; FLINT_ASSERT(a_mock->length > 0); FLINT_ASSERT(c_mock->length > 0); fq_nmod_mpoly_mul(t1, a_mock, c_mock, ctx); fq_nmod_mpoly_neg(t1, t1, ctx); if (!fq_nmod_mpoly_quadratic_root(t2, b_mock, t1, ctx)) { fq_nmod_mpolyv_fit_length(Af, 1, ctx); Af->length = 1; fq_nmod_mpoly_swap(Af->coeffs + 0, A, ctx); success = 1; goto cleanup; } fq_nmod_mpoly_neg(t2, t2, ctx); success = fq_nmod_mpoly_gcd_cofactors(t0, t1, t2, a_mock, t2, ctx); if (!success) goto cleanup; fq_nmod_mpoly_divides(t3, c_mock, t2, ctx); fq_nmod_mpolyv_fit_length(Af, 2, ctx); Af->length = 2; fq_nmod_mpoly_add(Af->coeffs + 0, t1, t2, ctx); fq_nmod_mpoly_add(Af->coeffs + 1, t0, t3, ctx); success = 1; cleanup: fq_nmod_mpoly_clear(t0, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_clear(t3, ctx); return success; } /* The property "sep" used here is that of the returned factors of _nmod_mpoly_factor_separable with sep = 1, namely: (1) monic (2) primitive wrt each variable (3) for all i, derivative(A, gen(i)) = 0, or gcd(A, derivative(A, gen(i))) = 1 (4) there is at least one i for which derivative(A, gen(i)) != 0 Input A is sep and compressed. return 1 for success, 0 for failure */ static int _factor_irred_compressed( fq_nmod_mpolyv_t Af, fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j, tot_deg; slong nvars = ctx->minfo->nvars; slong * perm; ulong * strides, * texps; flint_bitcnt_t Abits; flint_rand_t state; #if FLINT_WANT_ASSERT fq_nmod_mpoly_t Aorg; fq_nmod_mpoly_init(Aorg, ctx); fq_nmod_mpoly_set(Aorg, A, ctx); #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(n_fq_is_one(A->coeffs + 0, ctx->fqctx)); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (A->length < 2) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(!fq_nmod_mpoly_is_fq_nmod(A, ctx)); fq_nmod_mpolyv_fit_length(Af, 1, ctx); fq_nmod_mpoly_swap(Af->coeffs + 0, A, ctx); Af->length = 1; return 1; } if (A->bits > FLINT_BITS && !fq_nmod_mpoly_repack_bits_inplace(A, FLINT_BITS, ctx)) { return 0; } Abits = A->bits; flint_randinit(state); strides = FLINT_ARRAY_ALLOC(2*nvars, ulong); texps = strides + nvars; perm = FLINT_ARRAY_ALLOC(nvars, slong); /* fill perm with id, and fill in strides */ { ulong ppowt, ppow = fq_nmod_ctx_mod(ctx->fqctx).n; slong N = mpoly_words_per_exp_sp(Abits, ctx->minfo); while (!n_mul_checked(&ppowt, ppow, fq_nmod_ctx_mod(ctx->fqctx).n)) ppow = ppowt; for (j = 0; j < nvars; j++) { strides[j] = ppow; perm[j] = j; } tot_deg = 1; for (i = 0; i < A->length; i++) { slong this_deg = 0; mpoly_get_monomial_ui(texps, A->exps + N*i, Abits, ctx->minfo); for (j = 0; j < nvars; j++) { if (z_add_checked(&this_deg, this_deg, texps[j])) { success = 0; goto cleanup; } strides[j] = n_gcd(strides[j], texps[j]); } tot_deg = FLINT_MAX(tot_deg, this_deg); } } /* find permutation with gcd(A, derivative(A, gen(perm[0]))) = 1 */ for (i = 0; i < nvars; i++) { if (strides[i] == 1) { FLINT_SWAP(slong, perm[0], perm[i]); break; } } if (nvars < 2) { fq_nmod_t c; fq_nmod_poly_t Au; fq_nmod_poly_factor_t Auf; FLINT_ASSERT(nvars == 1); fq_nmod_init(c, ctx->fqctx); fq_nmod_poly_init(Au, ctx->fqctx); fq_nmod_poly_factor_init(Auf, ctx->fqctx); FLINT_ASSERT(fq_nmod_mpoly_is_fq_nmod_poly(A, perm[0], ctx)); success = fq_nmod_mpoly_get_fq_nmod_poly(Au, A, perm[0], ctx); FLINT_ASSERT(success); fq_nmod_poly_factor(Auf, c, Au, ctx->fqctx); FLINT_ASSERT(fq_nmod_is_one(c, ctx->fqctx)); fq_nmod_mpolyv_fit_length(Af, Auf->num, ctx); Af->length = Auf->num; for (i = 0; i < Auf->num; i++) { FLINT_ASSERT(Auf->exp[i] == 1); _fq_nmod_mpoly_set_fq_nmod_poly(Af->coeffs + i, Abits, Auf->poly[i].coeffs, Auf->poly[i].length, perm[0], ctx); } fq_nmod_clear(c, ctx->fqctx); fq_nmod_poly_clear(Au, ctx->fqctx); fq_nmod_poly_factor_clear(Auf, ctx->fqctx); success = 1; } else if (nvars == 2) { n_fq_poly_t c; n_fq_bpoly_t Ab; n_fq_tpoly_t Abf; n_poly_init(c); n_bpoly_init(Ab); n_tpoly_init(Abf); fq_nmod_mpoly_get_n_fq_bpoly(Ab, A, perm[0], perm[1], ctx); success = n_fq_bpoly_factor_smprime(c, Abf, Ab, 1, ctx->fqctx); if (!success) { fq_nmod_mpoly_get_n_fq_bpoly(Ab, A, perm[0], perm[1], ctx); n_fq_bpoly_factor_lgprime(c, Abf, Ab, ctx->fqctx, state); } FLINT_ASSERT(n_poly_degree(c) == 0); fq_nmod_mpolyv_fit_length(Af, Abf->length, ctx); Af->length = Abf->length; for (i = 0; i < Abf->length; i++) { fq_nmod_mpoly_set_n_fq_bpoly(Af->coeffs + i, Abits, Abf->coeffs + i, perm[0], perm[1], ctx); fq_nmod_mpoly_make_monic(Af->coeffs + i, Af->coeffs + i, ctx); } n_poly_clear(c); n_bpoly_clear(Ab); n_tpoly_clear(Abf); success = 1; } else { slong Adeg0; fq_nmod_mpoly_t lcA; fq_nmod_mpoly_factor_t lcAf; fq_nmod_mpoly_init(lcA, ctx); fq_nmod_mpoly_factor_init(lcAf, ctx); tot_deg = _deflate(A, tot_deg, strides, perm, ctx); #if FLINT_WANT_ASSERT { fq_nmod_mpoly_t g; fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_derivative(g, A, 0, ctx); FLINT_ASSERT(fq_nmod_mpoly_gcd(g, g, A, ctx)); FLINT_ASSERT(fq_nmod_mpoly_is_one(g, ctx)); fq_nmod_mpoly_clear(g, ctx); } #endif Adeg0 = fq_nmod_mpoly_degree_si(A, 0, ctx); if (Adeg0 == 1) { fq_nmod_mpolyv_fit_length(Af, 1, ctx); Af->length = 1; fq_nmod_mpoly_swap(Af->coeffs + 0, A, ctx); success = 1; goto cleanup_inflate; } else if (Adeg0 == 2) { success = _apply_quadratic(Af, A, ctx); goto cleanup_inflate; } success = 0; if (!(algo & (MPOLY_FACTOR_USE_WANG | MPOLY_FACTOR_USE_ZIP))) goto try_zassenhaus; /* TODO lcc_kaltofen */ _fq_nmod_mpoly_get_lead0(lcA, A, ctx); if (!fq_nmod_mpoly_factor(lcAf, lcA, ctx)) goto try_zassenhaus; if (!(algo & MPOLY_FACTOR_USE_ZIP)) { if (success == 0) success = fq_nmod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fq_nmod_mpoly_factor_irred_lgprime_wang( Af, A, lcAf, lcA, ctx, state); } else if (!(algo & MPOLY_FACTOR_USE_WANG)) { if (success == 0) success = fq_nmod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fq_nmod_mpoly_factor_irred_lgprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { double tdensity; fmpz_t x; fmpz_init(x); fmpz_bin_uiui(x, (ulong)tot_deg + nvars, nvars); tdensity = A->length/fmpz_get_d(x); fmpz_clear(x); if (tdensity > 0.005) { if (success == 0) success = fq_nmod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fq_nmod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { if (success == 0) success = fq_nmod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fq_nmod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); } if (tdensity > 0.001) { if (success == 0) success = fq_nmod_mpoly_factor_irred_lgprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fq_nmod_mpoly_factor_irred_lgprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { if (success == 0) success = fq_nmod_mpoly_factor_irred_lgprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = fq_nmod_mpoly_factor_irred_lgprime_wang( Af, A, lcAf, lcA, ctx, state); } } try_zassenhaus: if (algo & MPOLY_FACTOR_USE_ZAS) { if (success == 0) success = fq_nmod_mpoly_factor_irred_smprime_zassenhaus( Af, A, ctx, state); if (success == 0) success = fq_nmod_mpoly_factor_irred_lgprime_zassenhaus( Af, A, ctx, state); } cleanup_inflate: success = (success > 0); if (success) { for (i = 0; i < Af->length; i++) _inflate(Af->coeffs + i, Abits, strides, perm, ctx); } fq_nmod_mpoly_clear(lcA, ctx); fq_nmod_mpoly_factor_clear(lcAf, ctx); } cleanup: flint_randclear(state); flint_free(strides); flint_free(perm); #if FLINT_WANT_ASSERT if (success) { fq_nmod_mpoly_t prod; fq_nmod_mpoly_init(prod, ctx); fq_nmod_mpoly_one(prod, ctx); for (i = 0; i < Af->length; i++) fq_nmod_mpoly_mul(prod, prod, Af->coeffs + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(prod, Aorg, ctx)); fq_nmod_mpoly_clear(prod, ctx); fq_nmod_mpoly_clear(Aorg, ctx); } #endif FLINT_ASSERT(success == 0 || success == 1); return success; } /* f is already squarefree make the factors in f have the sep property */ static int _refine_sep( fq_nmod_mpolyv_t f, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpolyv_t g) /* temp */ { int success; slong v, i; fq_nmod_mpoly_struct * t; fq_nmod_mpoly_univar_t u; fq_nmod_mpoly_univar_init(u, ctx); /* first make primitive */ for (v = 0; v < ctx->minfo->nvars; v++) { g->length = 0; for (i = 0; i < f->length; i++) { fq_nmod_mpoly_to_univar(u, f->coeffs + i, v, ctx); FLINT_ASSERT(u->length > 0); FLINT_ASSERT(fmpz_is_zero(u->exps + u->length - 1)); fq_nmod_mpolyv_fit_length(g, g->length + 2, ctx); success = _fq_nmod_mpoly_vec_content_mpoly(g->coeffs + g->length, u->coeffs, u->length, ctx); if (!success) goto cleanup; if (fq_nmod_mpoly_is_fq_nmod(g->coeffs + g->length, ctx)) { fq_nmod_mpoly_swap(g->coeffs + g->length, f->coeffs + i, ctx); g->length++; } else { success = fq_nmod_mpoly_divides(g->coeffs + g->length + 1, f->coeffs + i, g->coeffs + g->length, ctx); FLINT_ASSERT(success); if (fq_nmod_mpoly_is_fq_nmod(g->coeffs + g->length + 1, ctx)) g->length += 1; else g->length += 2; } } fq_nmod_mpolyv_swap(f, g, ctx); } /* now make separable/derivative zero wrt each variable */ fq_nmod_mpolyv_fit_length(g, 1, ctx); t = g->coeffs + 0; for (v = 0; v < ctx->minfo->nvars; v++) { i = 0; while (i < f->length) { fq_nmod_mpoly_derivative(t, f->coeffs + i, v, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) { /* f[i] has zero derivative */ i++; continue; } fq_nmod_mpolyv_fit_length(f, f->length + 1, ctx); success = fq_nmod_mpoly_gcd_cofactors(f->coeffs + f->length, f->coeffs + i, t, f->coeffs + i, t, ctx); if (!success) goto cleanup; if (fq_nmod_mpoly_is_fq_nmod(f->coeffs + f->length, ctx)) { /* f[i] is comprime with its derivative */ i++; } else { /* f[i] and f[end] at least got smaller */ f->length++; } } } success = 1; cleanup: fq_nmod_mpoly_univar_clear(u, ctx); return 1; } /* A is sep. return 1 for success, 0 for failure */ static int _factor_irred( fq_nmod_mpolyv_t Af, fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t Actx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t Abits; mpoly_compression_t M; #if FLINT_WANT_ASSERT fq_nmod_mpoly_t Aorg; fq_nmod_mpoly_init(Aorg, Actx); fq_nmod_mpoly_set(Aorg, A, Actx); #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); if (A->length < 2) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(!fq_nmod_mpoly_is_fq_nmod(A, Actx)); fq_nmod_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; fq_nmod_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; goto cleanup_less; } if (A->bits > FLINT_BITS && !fq_nmod_mpoly_repack_bits_inplace(A, FLINT_BITS, Actx)) { success = 0; goto cleanup_less; } Abits = A->bits; mpoly_compression_init(M); mpoly_compression_set(M, A->exps, A->bits, A->length, Actx->minfo); if (M->is_irred) { fq_nmod_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; fq_nmod_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; } else if (M->is_trivial) { success = _factor_irred_compressed(Af, A, Actx, algo); } else { fq_nmod_mpoly_ctx_t Lctx; fq_nmod_mpolyv_t Lf, Lft, Lfs; fq_nmod_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX, Actx->fqctx); fq_nmod_mpolyv_init(Lf, Lctx); fq_nmod_mpolyv_init(Lft, Lctx); fq_nmod_mpolyv_init(Lfs, Lctx); fq_nmod_mpolyv_fit_length(Lft, 1, Lctx); Lft->length = 1; fq_nmod_mpoly_compression_do(Lft->coeffs + 0, Lctx, A->coeffs, A->length, M); _refine_sep(Lft, Lctx, Lf); if (Lft->length == 1) { success = _factor_irred_compressed(Lf, Lft->coeffs + 0, Lctx, algo); } else { success = 1; Lf->length = 0; for (i = 0; i < Lft->length; i++) { success = _factor_irred(Lfs, Lft->coeffs + i, Lctx, algo); if (!success) break; fq_nmod_mpolyv_fit_length(Lf, Lf->length + Lfs->length, Lctx); for (j = 0; j < Lfs->length; j++) { fq_nmod_mpoly_swap(Lf->coeffs + Lf->length, Lfs->coeffs + j, Lctx); Lf->length++; } } } if (success) { fq_nmod_mpolyv_fit_length(Af, Lf->length, Actx); Af->length = Lf->length; for (i = 0; i < Lf->length; i++) { fq_nmod_mpoly_compression_undo(Af->coeffs + i, Abits, Actx, Lf->coeffs + i, Lctx, M); } } fq_nmod_mpolyv_clear(Lf, Lctx); fq_nmod_mpolyv_clear(Lft, Lctx); fq_nmod_mpolyv_clear(Lfs, Lctx); fq_nmod_mpoly_ctx_clear(Lctx); } mpoly_compression_clear(M); cleanup_less: #if FLINT_WANT_ASSERT if (success) { fq_nmod_mpoly_t prod; fq_nmod_mpoly_init(prod, Actx); fq_nmod_mpoly_one(prod, Actx); for (i = 0; i < Af->length; i++) fq_nmod_mpoly_mul(prod, prod, Af->coeffs + i, Actx); FLINT_ASSERT(fq_nmod_mpoly_equal(prod, Aorg, Actx)); fq_nmod_mpoly_clear(prod, Actx); fq_nmod_mpoly_clear(Aorg, Actx); } #endif FLINT_ASSERT(success == 0 || success == 1); return success; } /* Assume each factor in f is sep. Replace f by an irreducible factorization. */ int fq_nmod_mpoly_factor_irred( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; fq_nmod_mpolyv_t t; fq_nmod_mpoly_factor_t g; fq_nmod_mpolyv_init(t, ctx); fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_set(g->constant, f->constant, ctx->fqctx); g->num = 0; for (j = 0; j < f->num; j++) { success = _factor_irred(t, f->poly + j, ctx, algo); if (!success) goto cleanup; fq_nmod_mpoly_factor_fit_length(g, g->num + t->length, ctx); for (i = 0; i < t->length; i++) { fmpz_set(g->exp + g->num, f->exp + j); fq_nmod_mpoly_swap(g->poly + g->num, t->coeffs + i, ctx); g->num++; } } fq_nmod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fq_nmod_mpolyv_clear(t, ctx); fq_nmod_mpoly_factor_clear(g, ctx); return success; } /* append factor(f)^e to g assuming f is compressed and content free */ static int _compressed_content_to_irred( fq_nmod_mpoly_factor_t g, fq_nmod_mpoly_t f, const fmpz_t e, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong j, k; fq_nmod_mpoly_factor_t h; fq_nmod_mpolyv_t v; fq_nmod_mpoly_factor_init(h, ctx); fq_nmod_mpolyv_init(v, ctx); success = _fq_nmod_mpoly_factor_separable(h, f, ctx, 1); if (!success) goto cleanup; for (j = 0; j < h->num; j++) { success = h->num > 1 ? _factor_irred(v, h->poly + j, ctx, algo) : _factor_irred_compressed(v, h->poly + j, ctx, algo); if (!success) goto cleanup; fq_nmod_mpoly_factor_fit_length(g, g->num + v->length, ctx); for (k = 0; k < v->length; k++) { fmpz_mul(g->exp + g->num, h->exp + j, e); fq_nmod_mpoly_swap(g->poly + g->num, v->coeffs + k, ctx); g->num++; } } cleanup: fq_nmod_mpoly_factor_clear(h, ctx); fq_nmod_mpolyv_clear(v, ctx); return success; } int fq_nmod_mpoly_factor_algo( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t bits; fq_nmod_mpoly_factor_t g; mpoly_compression_t M; if (!fq_nmod_mpoly_factor_content(f, A, ctx)) return 0; fq_nmod_mpoly_factor_init(g, ctx); mpoly_compression_init(M); /* write into g */ fq_nmod_set(g->constant, f->constant, ctx->fqctx); g->num = 0; for (i = 0; i < f->num; i++) { if (f->poly[i].length < 2) { fq_nmod_mpoly_factor_fit_length(g, g->num + 1, ctx); fq_nmod_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; continue; } if (f->poly[i].bits > FLINT_BITS && !fq_nmod_mpoly_repack_bits_inplace(f->poly + i, FLINT_BITS, ctx)) { success = 0; goto cleanup; } bits = f->poly[i].bits; mpoly_compression_set(M, f->poly[i].exps, bits, f->poly[i].length, ctx->minfo); if (M->is_irred) { fq_nmod_mpoly_factor_fit_length(g, g->num + 1, ctx); fq_nmod_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; } else if (M->is_trivial) { success = _compressed_content_to_irred(g, f->poly + i, f->exp + i, ctx, algo); if (!success) goto cleanup; } else { fq_nmod_mpoly_ctx_t Lctx; fq_nmod_mpoly_t L; fq_nmod_mpoly_factor_t h; /* compression may have messed up the content factorization */ fq_nmod_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX, ctx->fqctx); fq_nmod_mpoly_init(L, Lctx); fq_nmod_mpoly_factor_init(h, Lctx); fq_nmod_mpoly_compression_do(L, Lctx, f->poly[i].coeffs, f->poly[i].length, M); if (M->is_perm) { success = _compressed_content_to_irred(h, L, f->exp + i, Lctx, algo); fmpz_one(f->exp + i); } else { success = fq_nmod_mpoly_factor_separable(h, L, Lctx, 1) && fq_nmod_mpoly_factor_irred(h, Lctx, algo); } if (success) { FLINT_ASSERT(fq_nmod_is_one(h->constant, ctx->fqctx)); fq_nmod_mpoly_factor_fit_length(g, g->num + h->num, ctx); for (j = 0; j < h->num; j++) { fmpz_mul(g->exp + g->num, f->exp + i, h->exp + j); fq_nmod_mpoly_compression_undo(g->poly + g->num, bits, ctx, h->poly + j, Lctx, M); g->num++; } } fq_nmod_mpoly_factor_clear(h, Lctx); fq_nmod_mpoly_clear(L, Lctx); fq_nmod_mpoly_ctx_clear(Lctx); if (!success) goto cleanup; } } fq_nmod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fq_nmod_mpoly_factor_clear(g, ctx); mpoly_compression_clear(M); FLINT_ASSERT(!success || fq_nmod_mpoly_factor_matches(A, f, ctx)); return success; } int fq_nmod_mpoly_factor( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return fq_nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ALL); } int fq_nmod_mpoly_factor_zassenhaus( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return fq_nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZAS); } int fq_nmod_mpoly_factor_wang( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return fq_nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_WANG); } int fq_nmod_mpoly_factor_zippel( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return fq_nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZIP); } flint-3.1.3/src/fq_nmod_mpoly_factor/factor_content.c000066400000000000000000000122111461254215100227740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" /* either give a non-trivial split a = f*g or establish that a is primitive wrt all variables return: 1: split a = f*g 0: a is primitive wrt all variables (f & g undefined) -1: failed */ static int _split( fq_nmod_mpoly_t f, fq_nmod_mpoly_t g, fq_nmod_mpoly_t a, fmpz_t a_vars_left, const fq_nmod_mpoly_ctx_t ctx, fq_nmod_mpoly_univar_struct * u, /* temp */ slong * vars) { slong i, j, v; slong nvars = ctx->minfo->nvars; slong mvars = 0; for (v = 0; v < nvars; v++) { if (!fmpz_tstbit(a_vars_left, v)) continue; fq_nmod_mpoly_to_univar(u + v, a, v, ctx); vars[mvars] = v; mvars++; } if (mvars < 1) return 0; /* sort vars by decreasing length */ for (i = 1; i < mvars; i++) for (j = i; j > 0 && u[vars[j]].length > u[vars[j - 1]].length; j--) FLINT_SWAP(slong, vars[j], vars[j - 1]); for (i = 0; i < mvars; i++) { v = vars[i]; FLINT_ASSERT(fmpz_tstbit(a_vars_left, v)); fmpz_clrbit(a_vars_left, v); if (u[v].length < 2) { FLINT_ASSERT(u[v].length == 1); FLINT_ASSERT(fmpz_is_zero(u[v].exps + 0)); continue; } if (!_fq_nmod_mpoly_vec_content_mpoly(g, u[v].coeffs, u[v].length, ctx)) return -1; if (g->length < 2) { FLINT_ASSERT(fq_nmod_mpoly_is_one(g, ctx)); continue; } fq_nmod_mpoly_divides(f, a, g, ctx); FLINT_ASSERT(f->length > 1); return 1; } return 0; } /* return factors that are primitive wrt each variable */ int fq_nmod_mpoly_factor_content( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { int success; slong nvars = ctx->minfo->nvars; slong v; fq_nmod_mpoly_univar_struct * u; fq_nmod_mpoly_factor_t g; /* exponents are bitsets */ slong * vars; f->num = 0; if (fq_nmod_mpoly_is_fq_nmod(A, ctx)) { fq_nmod_mpoly_get_fq_nmod(f->constant, A, ctx); return 1; } vars = FLINT_ARRAY_ALLOC(nvars, slong); fq_nmod_mpoly_factor_init(g, ctx); u = FLINT_ARRAY_ALLOC(nvars, fq_nmod_mpoly_univar_struct); for (v = 0; v < nvars; v++) fq_nmod_mpoly_univar_init(u + v, ctx); /* remove leading coefficient */ FLINT_ASSERT(A->length > 0); n_fq_get_fq_nmod(f->constant, A->coeffs + 0, ctx->fqctx); fq_nmod_mpoly_factor_fit_length(g, nvars, ctx); fq_nmod_mpoly_make_monic(g->poly + 0, A, ctx); /* remove monomial divisors */ mpoly_remove_var_powers(g->exp, g->poly[0].exps, g->poly[0].bits, g->poly[0].length, ctx->minfo); for (v = 0; v < nvars; v++) { if (fmpz_is_zero(g->exp + v)) continue; fq_nmod_mpoly_factor_fit_length(f, f->num + 1, ctx); fq_nmod_mpoly_gen(f->poly + f->num, v, ctx); fmpz_swap(f->exp + f->num, g->exp + v); f->num++; } /* done if g->poly[0] is constant */ if (g->poly[0].length == 1) { FLINT_ASSERT(fq_nmod_mpoly_is_one(g->poly + 0, ctx)); success = 1; goto cleanup; } /* g has length one and no variable has been checked yet */ fmpz_one(g->exp + 0); fmpz_mul_2exp(g->exp + 0, g->exp + 0, nvars); fmpz_sub_ui(g->exp + 0, g->exp + 0, 1); g->num = 1; while (g->num > 0) { slong t = g->num - 1; fq_nmod_mpoly_factor_fit_length(g, t + 3, ctx); success = _split(g->poly + t + 2, g->poly + t + 1, g->poly + t, g->exp + t, ctx, u, vars); if (success < 0) { success = 0; goto cleanup; } else if (success == 0) { FLINT_ASSERT(!fq_nmod_mpoly_is_fq_nmod(g->poly + t, ctx)); fq_nmod_mpoly_factor_fit_length(f, f->num + 1, ctx); fq_nmod_mpoly_swap(f->poly + f->num, g->poly + t, ctx); fmpz_one(f->exp + f->num); f->num++; g->num = t; } else { FLINT_ASSERT(!fq_nmod_mpoly_is_fq_nmod(g->poly + t + 1, ctx)); FLINT_ASSERT(!fq_nmod_mpoly_is_fq_nmod(g->poly + t + 2, ctx)); fq_nmod_mpoly_swap(g->poly + t, g->poly + t + 2, ctx); fmpz_set(g->exp + t + 1, g->exp + t); g->num = t + 2; } } success = 1; cleanup: fq_nmod_mpoly_factor_clear(g, ctx); for (v = 0; v < nvars; v++) fq_nmod_mpoly_univar_clear(u + v, ctx); flint_free(u); flint_free(vars); FLINT_ASSERT(!success || fq_nmod_mpoly_factor_matches(A, f, ctx)); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/factor_squarefree.c000066400000000000000000000304621461254215100234740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly_factor.h" #if FLINT_WANT_ASSERT /* return: 0 no 1 yes -1 don't know */ static int fq_nmod_mpoly_factor_is_pairwise_prime( const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int result; slong i, j; fq_nmod_mpoly_t g; fq_nmod_mpoly_init(g, ctx); for (i = 0; i + 1 < f->num; i++) for (j = i + 1; j < f->num; j++) { /* make sure factors are monic */ if (f->poly[i].length < 1 || f->poly[j].length < 1 || !_n_fq_is_one(f->poly[i].coeffs + d*0, d) || !_n_fq_is_one(f->poly[j].coeffs + d*0, d)) { result = 0; goto cleanup; } if (fq_nmod_mpoly_gcd(g, f->poly + i, f->poly + j, ctx)) { if (!fq_nmod_mpoly_is_one(g, ctx)) { result = 0; goto cleanup; } } else { result = -1; goto cleanup; } } result = 1; cleanup: fq_nmod_mpoly_clear(g, ctx); return result; } #endif /* b and c are pairwise prime produce a=b*c pairwise prime and return 1 else return 0 with a undefined */ static int fq_nmod_mpoly_factor_mul_pairwise_prime( fq_nmod_mpoly_factor_t a, fq_nmod_mpoly_factor_t b, /* clobbered */ fq_nmod_mpoly_factor_t c, /* clobbered */ const fq_nmod_mpoly_ctx_t ctx) { int success; slong i, j; fq_nmod_mpoly_t T1, T2; fq_nmod_mpoly_t g; fmpz_t t; #if FLINT_WANT_ASSERT int ae_ok = 1; fq_nmod_mpoly_t ae, be, ce; #endif if (a == b || a == c) { fq_nmod_mpoly_factor_t ta; fq_nmod_mpoly_factor_init(ta, ctx); success = fq_nmod_mpoly_factor_mul_pairwise_prime(ta, b, c, ctx); fq_nmod_mpoly_factor_swap(a, ta, ctx); fq_nmod_mpoly_factor_clear(ta, ctx); return success; } #if FLINT_WANT_ASSERT fq_nmod_mpoly_init(ae, ctx); fq_nmod_mpoly_init(be, ctx); fq_nmod_mpoly_init(ce, ctx); ae_ok = fq_nmod_mpoly_factor_expand(be, b, ctx) && fq_nmod_mpoly_factor_expand(ce, c, ctx); if (ae_ok) fq_nmod_mpoly_mul(ae, be, ce, ctx); #endif fmpz_init(t); fq_nmod_mpoly_init(T1, ctx); fq_nmod_mpoly_init(T2, ctx); FLINT_ASSERT(fq_nmod_mpoly_factor_is_pairwise_prime(b, ctx) != 0); FLINT_ASSERT(fq_nmod_mpoly_factor_is_pairwise_prime(c, ctx) != 0); fq_nmod_mpoly_init(g, ctx); fq_nmod_mul(a->constant, b->constant, c->constant, ctx->fqctx); a->num = 0; for (i = 0; i < b->num; i++) for (j = 0; j < c->num; j++) { if (!fq_nmod_mpoly_gcd_cofactors(g, b->poly + i, c->poly + j, b->poly + i, c->poly + j, ctx)) { success = 0; goto cleanup; } if (!fq_nmod_mpoly_is_one(g, ctx)) { fq_nmod_mpoly_factor_fit_length(a, a->num + 1, ctx); fq_nmod_mpoly_swap(a->poly + a->num, g, ctx); fmpz_add(a->exp + a->num, b->exp + i, c->exp + j); a->num++; } } for (i = 0; i < b->num; i++) { if (!fq_nmod_mpoly_is_one(b->poly + i, ctx)) { fq_nmod_mpoly_factor_fit_length(a, a->num + 1, ctx); fq_nmod_mpoly_swap(a->poly + a->num, b->poly + i, ctx); fmpz_swap(a->exp + a->num, b->exp + i); a->num++; } } for (j = 0; j < c->num; j++) { if (!fq_nmod_mpoly_is_one(c->poly + j, ctx)) { fq_nmod_mpoly_factor_fit_length(a, a->num + 1, ctx); fq_nmod_mpoly_swap(a->poly + a->num, c->poly + j, ctx); fmpz_swap(a->exp + a->num, c->exp + j); a->num++; } } success = 1; cleanup: FLINT_ASSERT(!success || fq_nmod_mpoly_factor_is_pairwise_prime(a, ctx) != 0); FLINT_ASSERT(!(ae_ok && success) || fq_nmod_mpoly_factor_matches(ae, a, ctx)); #if FLINT_WANT_ASSERT fq_nmod_mpoly_clear(ae, ctx); fq_nmod_mpoly_clear(be, ctx); fq_nmod_mpoly_clear(ce, ctx); #endif fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(T1, ctx); fq_nmod_mpoly_clear(T2, ctx); fmpz_clear(t); return success; } /* a has zero derivative wrt gen(i) for all i for which vars_left[i] = 0 gcd(a, derivative(a, gen(var))) = 1 sep = false: just tack on a sep = true: make sure either 1. derivative(a, gen(var)) = 0, or 2. gcd(a, derivative(a, gen(i))) = 1 holds for the other factors for all i for which vars_left[i] != 0 */ static int _append_factor_sep( fq_nmod_mpoly_factor_t f, fq_nmod_mpoly_t a, ulong k, int * vars_left, const fq_nmod_mpoly_ctx_t ctx, int sep, fq_nmod_mpoly_t t) /* temp */ { slong v, org = f->num; if (fq_nmod_mpoly_is_fq_nmod(a, ctx)) { FLINT_ASSERT(fq_nmod_mpoly_is_one(a, ctx)); return 1; } fq_nmod_mpoly_factor_fit_length(f, org + 1, ctx); fq_nmod_mpoly_swap(f->poly + org, a, ctx); fmpz_set_ui(f->exp + org, k); f->num = org + 1; if (!sep) return 1; for (v = 0; v < ctx->minfo->nvars; v++) { slong i = org; if (!vars_left[v]) continue; while (i < f->num) { fq_nmod_mpoly_derivative(t, f->poly + i, v, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) { /* f[i] has zero derivative */ i++; continue; } fq_nmod_mpoly_factor_fit_length(f, f->num + 1, ctx); fmpz_set_ui(f->exp + f->num, k); if (!fq_nmod_mpoly_gcd_cofactors(f->poly + f->num, f->poly + i, t, f->poly + i, t, ctx)) { return 0; } if (fq_nmod_mpoly_is_fq_nmod(f->poly + f->num, ctx)) { /* f[i] is comprime with its derivative */ i++; } else { /* f[i] and f[end] at least got smaller */ f->num++; } } } return 1; } int _fq_nmod_mpoly_factor_separable( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, int sep) { int success; slong i, j, v, var; ulong k; int * vars_left; fmpz * shift, * stride; fq_nmod_mpoly_factor_t Tf; fmpz_t g, gr, p, pk; fq_nmod_mpoly_t B, C, U, V, W, G; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(n_fq_is_one(A->coeffs + 0, ctx->fqctx)); fq_nmod_mpoly_init(B, ctx); fq_nmod_mpoly_init(C, ctx); fq_nmod_mpoly_init(U, ctx); fq_nmod_mpoly_init(V, ctx); fq_nmod_mpoly_init(W, ctx); fq_nmod_mpoly_init(G, ctx); fmpz_init_set_ui(p, ctx->fqctx->modulus->mod.n); fmpz_init(pk); fmpz_init(g); fmpz_init(gr); fq_nmod_mpoly_factor_init(Tf, ctx); shift = _fmpz_vec_init(ctx->minfo->nvars); stride = _fmpz_vec_init(ctx->minfo->nvars); vars_left = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, int); for (v = 0; v < ctx->minfo->nvars; v++) vars_left[v] = 1; fq_nmod_mpoly_factor_one(f, ctx); fq_nmod_mpoly_set(C, A, ctx); for (j = 0; j < ctx->minfo->nvars; j++) { /* take the next variable with shortest derivative */ var = -1; for (v = 0; v < ctx->minfo->nvars; v++) { if (!vars_left[v]) continue; fq_nmod_mpoly_derivative(U, C, v, ctx); if (var < 0 || U->length < G->length) { var = v; fq_nmod_mpoly_swap(G, U, ctx); } } FLINT_ASSERT(var >= 0); FLINT_ASSERT(vars_left[var] == 1); vars_left[var] = 0; success = fq_nmod_mpoly_gcd_cofactors(C, W, V, C, G, ctx); if (!success) goto cleanup; for (k = 1; k + 1 < ctx->fqctx->modulus->mod.n && !(fq_nmod_mpoly_derivative(G, W, var, ctx), fq_nmod_mpoly_sub(U, V, G, ctx), fq_nmod_mpoly_is_zero(U, ctx)); k++) { success = fq_nmod_mpoly_gcd_cofactors(G, W, V, W, U, ctx); if (!success) goto cleanup; success = _append_factor_sep(f, G, k, vars_left, ctx, sep, U); if (!success) goto cleanup; if (!fq_nmod_mpoly_is_one(W, ctx)) { success = fq_nmod_mpoly_divides(U, C, W, ctx); FLINT_ASSERT(success); fq_nmod_mpoly_swap(C, U, ctx); } } success = _append_factor_sep(f, W, k, vars_left, ctx, sep, U); if (!success) goto cleanup; } if (fq_nmod_mpoly_is_fq_nmod(C, ctx)) { FLINT_ASSERT(fq_nmod_mpoly_is_one(C, ctx)); } else { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong mk_mod_deg; fq_nmod_mpoly_deflation(shift, stride, C, ctx); fmpz_zero(g); for (var = 0; var < ctx->minfo->nvars; var++) { fmpz_gcd(g, g, stride + var); fmpz_gcd(g, g, shift + var); } k = fmpz_remove(gr, g, p); FLINT_ASSERT(k > 0); fmpz_pow_ui(pk, p, k); /* p^k th root of exponents */ for (var = 0; var < ctx->minfo->nvars; var++) { fmpz_set(stride + var, pk); fmpz_zero(shift + var); } fq_nmod_mpoly_deflate(C, C, shift, stride, ctx); /* p^k th root of coefficients */ mk_mod_deg = (ulong)k % (ulong)fq_nmod_ctx_degree(ctx->fqctx); if (mk_mod_deg > 0) mk_mod_deg = fq_nmod_ctx_degree(ctx->fqctx) - mk_mod_deg; for (i = 0; i < C->length; i++) { for (j = 0; j < mk_mod_deg; j++) { n_fq_pow_ui(C->coeffs + d*i, C->coeffs + d*i, fq_nmod_ctx_mod(ctx->fqctx).n, ctx->fqctx); } } success = _fq_nmod_mpoly_factor_separable(Tf, C, ctx, sep); if (!success) goto cleanup; /* p^k power of factors */ /* f = f * Cf */ FLINT_ASSERT(fq_nmod_is_one(Tf->constant, ctx->fqctx)); _fmpz_vec_scalar_mul_fmpz(Tf->exp, Tf->exp, Tf->num, pk); fq_nmod_mpoly_factor_mul_pairwise_prime(f, f, Tf, ctx); } success = 1; cleanup: fq_nmod_mpoly_clear(C, ctx); fq_nmod_mpoly_clear(U, ctx); fq_nmod_mpoly_clear(V, ctx); fq_nmod_mpoly_clear(W, ctx); fq_nmod_mpoly_clear(G, ctx); fmpz_clear(p); fmpz_clear(pk); fmpz_clear(g); fmpz_clear(gr); fq_nmod_mpoly_factor_clear(Tf, ctx); _fmpz_vec_clear(shift, ctx->minfo->nvars); _fmpz_vec_clear(stride, ctx->minfo->nvars); flint_free(vars_left); return success; } /* if sep = true, each returned factor should satisfy: (1) monic (2) primitive wrt each variable (3) for all i, derivative(a, gen(i)) = 0, or gcd(a, derivative(a, gen(i))) = 1 (4) there is at least i for which derivative(a, gen(i)) != 0 otherwise, the factors are just squarefree */ int fq_nmod_mpoly_factor_separable( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, int sep) { int success; slong i, j; fq_nmod_mpoly_factor_t g, t; if (!fq_nmod_mpoly_factor_content(f, A, ctx)) return 0; fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_factor_init(t, ctx); fq_nmod_set(g->constant, f->constant, ctx->fqctx); g->num = 0; for (j = 0; j < f->num; j++) { success = _fq_nmod_mpoly_factor_separable(t, f->poly + j, ctx, sep); if (!success) goto cleanup; FLINT_ASSERT(fq_nmod_is_one(t->constant, ctx->fqctx)); fq_nmod_mpoly_factor_fit_length(g, g->num + t->num, ctx); for (i = 0; i < t->num; i++) { fmpz_mul(g->exp + g->num, t->exp + i, f->exp + j); fq_nmod_mpoly_swap(g->poly + g->num, t->poly + i, ctx); g->num++; } } fq_nmod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: fq_nmod_mpoly_factor_clear(t, ctx); fq_nmod_mpoly_factor_clear(g, ctx); FLINT_ASSERT(!success || fq_nmod_mpoly_factor_matches(A, f, ctx)); return success; } int fq_nmod_mpoly_factor_squarefree( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { return fq_nmod_mpoly_factor_separable(f, A, ctx, 0); } flint-3.1.3/src/fq_nmod_mpoly_factor/fit_length.c000066400000000000000000000013511461254215100221120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_fit_length( fq_nmod_mpoly_factor_t f, slong len, const fq_nmod_mpoly_ctx_t ctx) { if (len > f->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * f->alloc) len = 2 * f->alloc; fq_nmod_mpoly_factor_realloc(f, len, ctx); } } flint-3.1.3/src/fq_nmod_mpoly_factor/get_constant_fq_nmod.c000066400000000000000000000011401461254215100241560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_get_constant_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_set(c, f->constant, ctx->fqctx); } flint-3.1.3/src/fq_nmod_mpoly_factor/get_exp_si.c000066400000000000000000000011471461254215100221200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod_mpoly_factor.h" slong fq_nmod_mpoly_factor_get_exp_si(fq_nmod_mpoly_factor_t f, slong i, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); return fmpz_get_si(f->exp + i); } flint-3.1.3/src/fq_nmod_mpoly_factor/get_set_lead0.c000066400000000000000000000022731461254215100224720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" void _fq_nmod_mpoly_get_lead0( fq_nmod_mpoly_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpolyl_lead_coeff(c, A, 1, ctx); } void _fq_nmod_mpoly_set_lead0( fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong deg; fq_nmod_mpoly_t t, g; fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(g, ctx); deg = fq_nmod_mpoly_degree_si(B, 0, ctx); FLINT_ASSERT(deg >= 0); fq_nmod_mpoly_gen(g, 0, ctx); fq_nmod_mpoly_pow_ui(g, g, deg, ctx); _fq_nmod_mpoly_get_lead0(t, B, ctx); fq_nmod_mpoly_sub(t, c, t, ctx); fq_nmod_mpoly_mul(t, t, g, ctx); fq_nmod_mpoly_add(A, B, t, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(g, ctx); } flint-3.1.3/src/fq_nmod_mpoly_factor/init.c000066400000000000000000000012711461254215100207330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_init( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_init(f->constant, ctx->fqctx); fq_nmod_one(f->constant, ctx->fqctx); f->poly = NULL; f->exp = NULL; f->num = 0; f->alloc = 0; } flint-3.1.3/src/fq_nmod_mpoly_factor/inlines.c000066400000000000000000000007061461254215100214330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_MPOLY_FACTOR_INLINES_C #include "fq_nmod_mpoly_factor.h" flint-3.1.3/src/fq_nmod_mpoly_factor/io.c000066400000000000000000000061431461254215100204020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_print_pretty( const fq_nmod_mpoly_factor_t f, const char ** vars, const fq_nmod_mpoly_ctx_t ctx) { slong i; flint_printf("("); fq_nmod_print_pretty(f->constant, ctx->fqctx); flint_printf(")"); for (i = 0; i < f->num; i++) { flint_printf("\n*(", i); fq_nmod_mpoly_print_pretty(f->poly + i, vars, ctx); flint_printf(")^"); fmpz_print(f->exp + i); } } void n_polyu2n_fq_print_pretty( const n_polyun_t A, const char * var0, const char * var1, const char * varlast, const fq_nmod_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; flint_printf("("); n_fq_poly_print_pretty(A->coeffs + i, varlast, ctx); flint_printf(")*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 1, 2), var1, extract_exp(A->exps[i], 0, 2)); } if (first) flint_printf("0"); } void n_polyu3n_fq_print_pretty( const n_polyun_t A, const char * var0, const char * var1, const char * var2, const char * varlast, const fq_nmod_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; flint_printf("("); n_fq_poly_print_pretty(A->coeffs + i, varlast, ctx); flint_printf(")*%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } void fq_nmod_mpolyv_print_pretty( const fq_nmod_mpolyv_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < poly->length; i++) { flint_printf("coeff[%wd]: ", i); fq_nmod_mpoly_print_pretty(poly->coeffs + i, x, ctx); flint_printf("\n"); } } void n_polyu3_fq_print_pretty( const n_polyu_t A, const char * var0, const char * var1, const char * var2, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; flint_printf("("); n_fq_print_pretty(A->coeffs + d*i, ctx); flint_printf(")*%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } flint-3.1.3/src/fq_nmod_mpoly_factor/irred_lgprime.c000066400000000000000000000230111461254215100226100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" static void _map_poly( fq_nmod_mpoly_t eA, const fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb) { slong smd = fq_nmod_ctx_degree(ctx->fqctx); slong lgd = fq_nmod_ctx_degree(ectx->fqctx); slong N = mpoly_words_per_exp(A->bits, ectx->minfo); slong i; FLINT_ASSERT(eA != A); fq_nmod_mpoly_fit_length_reset_bits(eA, A->length, A->bits, ectx); mpoly_copy_monomials(eA->exps, A->exps, A->length, N); for (i = 0; i < A->length; i++) bad_n_fq_embed_sm_elem_to_lg(eA->coeffs + lgd*i, A->coeffs + smd*i, emb); eA->length = A->length; } static void _frob_combine( fq_nmod_mpolyv_t Af, fq_nmod_mpolyv_t eAf, const fq_nmod_mpoly_ctx_t ctx, const fq_nmod_mpoly_ctx_t ectx, const bad_fq_nmod_embed_t emb) { slong smd = fq_nmod_ctx_degree(ctx->fqctx); slong lgd = fq_nmod_ctx_degree(ectx->fqctx); slong i, j; fq_nmod_mpolyv_t tfac; fq_nmod_mpoly_t t; fq_nmod_mpoly_struct * s; n_poly_t c; slong k = lgd/smd; fmpz_t q; FLINT_ASSERT(k > 1); fmpz_init(q); fq_nmod_mpoly_init(t, ectx); fq_nmod_mpolyv_init(tfac, ectx); n_poly_init(c); fmpz_ui_pow_ui(q, fq_nmod_ctx_prime(ctx->fqctx), fq_nmod_ctx_degree(ctx->fqctx)); Af->length = 0; while (eAf->length > 0) { eAf->length--; fq_nmod_mpoly_swap(t, eAf->coeffs + eAf->length, ectx); fq_nmod_mpolyv_fit_length(tfac, 1, ectx); fq_nmod_mpoly_set(tfac->coeffs + 0, t, ectx); tfac->length = 1; for (i = 1; i < k; i++) { for (j = 0; j < t->length; j++) n_fq_pow_fmpz(t->coeffs + lgd*j, t->coeffs + lgd*j, q, ectx->fqctx); for (j = 0; j < eAf->length; j++) { if (fq_nmod_mpoly_equal(t, eAf->coeffs + j, ectx)) break; } if (j >= eAf->length) continue; /* t, should already be in tfac */ fq_nmod_mpolyv_fit_length(tfac, tfac->length + 1, ectx); fq_nmod_mpoly_swap(tfac->coeffs + tfac->length, eAf->coeffs + j, ectx); tfac->length++; eAf->length--; fq_nmod_mpoly_swap(eAf->coeffs + j, eAf->coeffs + eAf->length, ectx); } fq_nmod_mpoly_swap(t, tfac->coeffs + 0, ectx); for (i = 1; i < tfac->length; i++) fq_nmod_mpoly_mul(t, t, tfac->coeffs + i, ectx); fq_nmod_mpolyv_fit_length(Af, Af->length + 1, ctx); s = Af->coeffs + Af->length; Af->length++; fq_nmod_mpoly_fit_length_reset_bits(s, t->length, t->bits, ctx); s->length = t->length; mpoly_copy_monomials(s->exps, t->exps, mpoly_words_per_exp(t->bits, ectx->minfo), t->length); for (i = 0; i < t->length; i++) { bad_n_fq_embed_lg_to_sm(c, t->coeffs + lgd*i, emb); if (c->length != 1) { flint_throw(FLINT_ERROR, "fatal error in _frob_combine"); } _n_fq_set(s->coeffs + smd*i, c->coeffs + smd*0, smd); } } n_poly_clear(c); fq_nmod_mpolyv_clear(tfac, ectx); fq_nmod_mpoly_clear(t, ectx); fmpz_clear(q); } /* return: 1: success 0: failed, ran out of primes, don't try again -1: failed, don't try again */ int fq_nmod_mpoly_factor_irred_lgprime_zassenhaus( fq_nmod_mpolyv_t Af, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; fq_nmod_mpolyv_t eAf; fq_nmod_mpoly_t eA; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx; cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx, ctx, state); fq_nmod_mpoly_init(eA, ectx); fq_nmod_mpolyv_init(eAf, ectx); goto have_prime; choose_prime: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, state); if (cur_emb == NULL) { success = 0; goto cleanup; } have_prime: _map_poly(eA, ectx, A, ctx, cur_emb); success = fq_nmod_mpoly_factor_irred_smprime_zassenhaus(eAf, eA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx, cur_emb); success = 1; cleanup: fq_nmod_mpoly_clear(eA, ectx); fq_nmod_mpolyv_clear(eAf, ectx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx, ctx, state); return success; } /* the methods in the extended context want an irreducible factorization */ static int _map_fac( fq_nmod_mpoly_factor_t eAfac, const fq_nmod_mpoly_ctx_t ectx, const fq_nmod_mpoly_factor_t Afac, const fq_nmod_mpoly_ctx_t ctx, const bad_fq_nmod_embed_t emb) { int success; slong i, j; fq_nmod_mpoly_t t; fq_nmod_mpoly_factor_t tfac; fq_nmod_mpoly_init(t, ectx); fq_nmod_mpoly_factor_init(tfac, ectx); bad_fq_nmod_embed_sm_elem_to_lg(eAfac->constant, Afac->constant, emb); eAfac->num = 0; for (i = 0; i < Afac->num; i++) { _map_poly(t, ectx, Afac->poly + i, ctx, emb); success = fq_nmod_mpoly_factor(tfac, t, ectx); if (!success) goto cleanup; FLINT_ASSERT(fq_nmod_is_one(tfac->constant, ectx->fqctx)); fq_nmod_mpoly_factor_fit_length(eAfac, eAfac->num + tfac->num, ectx); for (j = 0; j < tfac->num; j++) { fq_nmod_mpoly_swap(eAfac->poly + eAfac->num, tfac->poly + j, ectx); fmpz_mul(eAfac->exp + eAfac->num, tfac->exp + j, Afac->exp + i); eAfac->num++; } } success = 1; cleanup: fq_nmod_mpoly_clear(t, ectx); fq_nmod_mpoly_factor_clear(tfac, ectx); return success; } int fq_nmod_mpoly_factor_irred_lgprime_wang( fq_nmod_mpolyv_t Af, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; fq_nmod_mpoly_factor_t elcAfac; fq_nmod_mpolyv_t eAf; fq_nmod_mpoly_t eA, elcA; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(_n_fq_is_one(A->coeffs + 0, fq_nmod_ctx_degree(ctx->fqctx))); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx, ctx, state); fq_nmod_mpoly_init(eA, ectx); fq_nmod_mpolyv_init(eAf, ectx); fq_nmod_mpoly_init(elcA, ectx); fq_nmod_mpoly_factor_init(elcAfac, ectx); goto have_prime; choose_prime: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, state); if (cur_emb == NULL) { success = 0; goto cleanup; } have_prime: _map_poly(eA, ectx, A, ctx, cur_emb); _map_poly(elcA, ectx, lcA, ctx, cur_emb); _map_fac(elcAfac, ectx, lcAfac, ctx, cur_emb); success = fq_nmod_mpoly_factor_irred_smprime_wang(eAf, eA, elcAfac, elcA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx, cur_emb); success = 1; cleanup: fq_nmod_mpoly_clear(eA, ectx); fq_nmod_mpolyv_clear(eAf, ectx); fq_nmod_mpoly_clear(elcA, ectx); fq_nmod_mpoly_factor_clear(elcAfac, ectx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx, ctx, state); return success; } int fq_nmod_mpoly_factor_irred_lgprime_zippel( fq_nmod_mpolyv_t Af, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; fq_nmod_mpoly_factor_t elcAfac; fq_nmod_mpolyv_t eAf; fq_nmod_mpoly_t eA, elcA; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(_n_fq_is_one(A->coeffs + 0, fq_nmod_ctx_degree(ctx->fqctx))); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx, ctx, state); fq_nmod_mpoly_init(eA, ectx); fq_nmod_mpolyv_init(eAf, ectx); fq_nmod_mpoly_init(elcA, ectx); fq_nmod_mpoly_factor_init(elcAfac, ectx); goto have_prime; choose_prime: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx, ctx, state); if (cur_emb == NULL) { success = 0; goto cleanup; } have_prime: _map_poly(eA, ectx, A, ctx, cur_emb); _map_poly(elcA, ectx, lcA, ctx, cur_emb); _map_fac(elcAfac, ectx, lcAfac, ctx, cur_emb); success = fq_nmod_mpoly_factor_irred_smprime_zippel(eAf, eA, elcAfac, elcA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx, cur_emb); success = 1; cleanup: fq_nmod_mpoly_clear(eA, ectx); fq_nmod_mpolyv_clear(eAf, ectx); fq_nmod_mpoly_clear(elcA, ectx); fq_nmod_mpoly_factor_clear(elcAfac, ectx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx, ctx, state); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/irred_smprime_wang.c000066400000000000000000000213331461254215100236460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly_factor.h" int fq_nmod_mpoly_factor_irred_smprime_wang( fq_nmod_mpolyv_t fac, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; fq_nmod_struct * alpha; n_poly_struct * alphabetas; fq_nmod_mpoly_struct * Aevals; slong * degs, * degeval; fq_nmod_mpolyv_t tfac; fq_nmod_mpoly_t t, Acopy; fq_nmod_mpoly_struct * newA; n_poly_t Abfc; n_bpoly_t Ab; n_tpoly_t Abfp; fq_nmod_mpoly_t m, mpow; fq_nmod_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(_n_fq_is_one(A->coeffs + d*0, d)); FLINT_ASSERT(A->bits <= FLINT_BITS); fq_nmod_mpoly_init(Acopy, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_mpoly_init(mpow, ctx); fq_nmod_mpolyv_init(new_lcs, ctx); fq_nmod_mpolyv_init(lc_divs, ctx); n_poly_init(Abfc); n_tpoly_init(Abfp); n_bpoly_init(Ab); degs = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); alpha = FLINT_ARRAY_ALLOC(n, fq_nmod_struct); alphabetas = FLINT_ARRAY_ALLOC(n, n_poly_struct); Aevals = FLINT_ARRAY_ALLOC(n, fq_nmod_mpoly_struct); for (i = 0; i < n; i++) { fq_nmod_init(alpha + i, ctx->fqctx); n_poly_init(alphabetas + i); fq_nmod_mpoly_init(Aevals + i, ctx); } fq_nmod_mpolyv_init(tfac, ctx); fq_nmod_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; fq_nmod_mpoly_degrees_si(degs, A, ctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) { fq_nmod_rand(alpha + i, state, ctx->fqctx); } for (i = n - 1; i >= 0; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fq_nmod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } fq_nmod_mpoly_derivative(t, Aevals + 0, 0, ctx); fq_nmod_mpoly_gcd(t, t, Aevals + 0, ctx); if (!fq_nmod_mpoly_is_one(t, ctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 10) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { n_poly_fit_length(alphabetas + i, d*alphabetas_length); n_fq_set_fq_nmod(alphabetas[i].coeffs + d*0, alpha + i, ctx->fqctx); for (j = d; j < d*alphabetas_length; j++) alphabetas[i].coeffs[j] = n_urandint(state, ctx->fqctx->mod.n); alphabetas[i].length = alphabetas_length; _n_fq_poly_normalise(alphabetas + i, d); } _fq_nmod_mpoly_eval_rest_to_n_fq_bpoly(Ab, A, alphabetas, ctx); success = n_fq_bpoly_factor_smprime(Abfc, Abfp, Ab, 0, ctx->fqctx); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { fq_nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } fq_nmod_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = fq_nmod_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) fq_nmod_mpoly_one(lc_divs->coeffs + i, ctx); } success = fq_nmod_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = fq_nmod_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } fq_nmod_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fq_nmod_mpoly_is_one(mpow, ctx)) { newA = (fq_nmod_mpoly_struct *) A; } else { newA = Acopy; fq_nmod_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } fq_nmod_mpoly_degrees_si(degs, newA, ctx); fq_nmod_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(t, mpow, i + 1, alpha + i, ctx); fq_nmod_mpoly_swap(t, mpow, ctx); fq_nmod_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); } fq_nmod_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fq_nmod_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fq_nmod_mpoly_evaluate_one_fq_nmod(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fq_nmod_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { fq_nmod_t q, qt; fq_nmod_init(q, ctx->fqctx); fq_nmod_init(qt, ctx->fqctx); FLINT_ASSERT(fq_nmod_mpoly_is_fq_nmod(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fq_nmod_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _fq_nmod_mpoly_set_n_fq_bpoly_gen1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); n_fq_get_fq_nmod(qt, fac->coeffs[i].coeffs + d*0, ctx->fqctx); fq_nmod_inv(q, qt, ctx->fqctx); n_fq_get_fq_nmod(qt, new_lcs->coeffs[0*r + i].coeffs + 0, ctx->fqctx); fq_nmod_mul(q, q, qt, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(fac->coeffs + i, fac->coeffs + i, q, ctx); fq_nmod_clear(q, ctx->fqctx); fq_nmod_clear(qt, ctx->fqctx); } fq_nmod_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _fq_nmod_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } success = fq_nmod_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); if (!success) goto next_alphabetas; fq_nmod_mpolyv_swap(tfac, fac, ctx); } if (!fq_nmod_mpoly_is_fq_nmod(m, ctx)) { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!fq_nmod_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fq_nmod_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } } for (i = 0; i < r; i++) fq_nmod_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); success = 1; cleanup: fq_nmod_mpolyv_clear(new_lcs, ctx); fq_nmod_mpolyv_clear(lc_divs, ctx); n_bpoly_clear(Ab); n_poly_clear(Abfc); n_tpoly_clear(Abfp); for (i = 0; i < n; i++) { fq_nmod_clear(alpha + i, ctx->fqctx); fq_nmod_mpoly_clear(Aevals + i, ctx); n_poly_clear(alphabetas + i); } flint_free(alphabetas); flint_free(alpha); flint_free(Aevals); flint_free(degs); flint_free(degeval); fq_nmod_mpolyv_clear(tfac, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(Acopy, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { fq_nmod_mpoly_t prod; fq_nmod_mpoly_init(prod, ctx); fq_nmod_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) fq_nmod_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(prod, A, ctx)); fq_nmod_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000270341461254215100251020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fmpz_poly_factor.h" #include "fq_nmod_mpoly_factor.h" /* return: 1: success 0: lift is impossible -1: failed, don't try again */ static int _try_lift( fq_nmod_mpolyv_t qfac, const fq_nmod_mpoly_t q, const fq_nmod_mpolyv_t pfac, const fq_nmod_mpoly_t p, slong m, fq_nmod_struct * alpha, slong n, const fq_nmod_mpoly_ctx_t ctx) { int success; slong i; slong * newdeg; fq_nmod_mpoly_t lcq, lcp, t, newq; FLINT_ASSERT(pfac->length > 1); newdeg = (slong *) flint_malloc((n + 1)*sizeof(slong)); fq_nmod_mpoly_init(lcq, ctx); fq_nmod_mpoly_init(lcp, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(newq, ctx); #if FLINT_WANT_ASSERT fq_nmod_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fq_nmod_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(t, p, ctx)); #endif _fq_nmod_mpoly_get_lead0(lcq, q, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(lcp, lcq, m, alpha + m - 1, ctx); FLINT_ASSERT(lcp->length > 0); fq_nmod_mpoly_pow_ui(t, lcq, pfac->length - 1, ctx); fq_nmod_mpoly_mul(newq, q, t, ctx); if (newq->bits > FLINT_BITS) { success = -1; goto cleanup; } fq_nmod_mpoly_degrees_si(newdeg, newq, ctx); fq_nmod_mpolyv_fit_length(qfac, pfac->length, ctx); qfac->length = pfac->length; for (i = 0; i < pfac->length; i++) { _fq_nmod_mpoly_get_lead0(t, pfac->coeffs + i, ctx); success = fq_nmod_mpoly_divides(t, lcp, t, ctx); FLINT_ASSERT(success); fq_nmod_mpoly_mul(qfac->coeffs + i, pfac->coeffs + i, t, ctx); _fq_nmod_mpoly_set_lead0(qfac->coeffs + i, qfac->coeffs + i, lcq, ctx); } success = fq_nmod_mpoly_hlift(m, qfac->coeffs, qfac->length, alpha, newq, newdeg, ctx); if (!success) goto cleanup; for (i = 0; i < qfac->length; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(qfac->coeffs[i].bits <= FLINT_BITS); if (!fq_nmod_mpolyl_content(t, qfac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fq_nmod_mpoly_divides(qfac->coeffs + i, qfac->coeffs + i, t, ctx); FLINT_ASSERT(success); fq_nmod_mpoly_make_monic(qfac->coeffs + i, qfac->coeffs + i, ctx); } success = 1; cleanup: flint_free(newdeg); fq_nmod_mpoly_clear(lcq, ctx); fq_nmod_mpoly_clear(lcp, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(newq, ctx); #if FLINT_WANT_ASSERT if (success > 0) { fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_one(t, ctx); for (i = 0; i < qfac->length; i++) fq_nmod_mpoly_mul(t, t, qfac->coeffs + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(t, q, ctx)); fq_nmod_mpoly_clear(t, ctx); } #endif return success; } /* return: 1: success 0: failed, may try again -1: failed, don't try again */ int fq_nmod_mpoly_factor_irred_smprime_zassenhaus( fq_nmod_mpolyv_t fac, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state) { int tries_left = 10; int success; const slong n = ctx->minfo->nvars - 1; slong i, j, k, m, len; slong * subset; fq_nmod_struct * alpha; fq_nmod_mpoly_struct * Aevals; slong * deg, * degeval; fq_nmod_mpolyv_t qfac, pfac, tfac, dfac; fq_nmod_mpoly_t t, p, q; n_poly_t c; n_bpoly_t B; n_tpoly_t F; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(_n_fq_is_one(A->coeffs, fq_nmod_ctx_degree(ctx->fqctx))); FLINT_ASSERT(A->bits <= FLINT_BITS); subset = (slong*) flint_malloc(4*sizeof(slong)); alpha = (fq_nmod_struct *) flint_malloc(n*sizeof(fq_nmod_struct)); for (i = 0; i < n; i++) fq_nmod_init(alpha + i, ctx->fqctx); deg = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); Aevals = FLINT_ARRAY_ALLOC(n, fq_nmod_mpoly_struct); for (i = 0; i < n; i++) fq_nmod_mpoly_init(Aevals + i, ctx); fq_nmod_mpolyv_init(pfac, ctx); fq_nmod_mpolyv_init(qfac, ctx); fq_nmod_mpolyv_init(tfac, ctx); fq_nmod_mpolyv_init(dfac, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(p, ctx); fq_nmod_mpoly_init(q, ctx); n_poly_init(c); n_bpoly_init(B); n_tpoly_init(F); fq_nmod_mpoly_degrees_si(deg, A, ctx); goto got_alpha; next_alpha: tries_left--; if (tries_left < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) fq_nmod_rand(alpha + i, state, ctx->fqctx); got_alpha: /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); fq_nmod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) { if (degeval[j] != deg[j]) goto next_alpha; } } /* make sure univar is squarefree */ fq_nmod_mpoly_derivative(t, Aevals + 0, 0, ctx); success = fq_nmod_mpoly_gcd(t, t, Aevals + 0, ctx); if (!success) goto cleanup; if (!fq_nmod_mpoly_is_one(t, ctx)) goto next_alpha; /* make evaluations primitive */ for (i = n - 1; i > 0; i--) { success = fq_nmod_mpolyl_content(t, Aevals + i, 1, ctx); if (!success) goto cleanup; success = fq_nmod_mpoly_divides(Aevals + i, Aevals + i, t, ctx); FLINT_ASSERT(success); fq_nmod_mpoly_make_monic(Aevals + i, Aevals + i, ctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); } fq_nmod_mpoly_get_n_fq_bpoly(B, Aevals + 1, 0, 1, ctx); success = n_fq_bpoly_factor_smprime(c, F, B, 1, ctx->fqctx); if (!success) goto next_alpha; FLINT_ASSERT(n_poly_degree(c) == 0); fq_nmod_mpolyv_fit_length(pfac, F->length, ctx); pfac->length = F->length; for (i = 0; i < F->length; i++) { fq_nmod_mpoly_set_n_fq_bpoly(pfac->coeffs + i, A->bits, F->coeffs + i, 0, 1, ctx); fq_nmod_mpoly_make_monic(pfac->coeffs + i, pfac->coeffs + i, ctx); } /* number of of local factors can only decrease from here on */ subset = flint_realloc(subset, pfac->length*sizeof(slong)); for (m = 2; m <= n; m++) { fq_nmod_mpoly_set(q, m < n ? Aevals + m : A, ctx); fq_nmod_mpoly_set(p, Aevals + m - 1, ctx); #if FLINT_WANT_ASSERT fq_nmod_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fq_nmod_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(t, p, ctx)); #endif /* if one local factor, A must be irreducible */ if (pfac->length < 2) { fq_nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } success = _try_lift(qfac, q, pfac, p, m, alpha, n, ctx); if (success > 0) { fq_nmod_mpolyv_swap(qfac, pfac, ctx); continue; } else if (success < 0) { goto cleanup; } /* if we couldn't lift two local factors, A must be irreducible */ if (pfac->length == 2) { fq_nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } qfac->length = 0; len = pfac->length; for (k = 0; k < len; k++) subset[k] = k; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); #if FLINT_WANT_ASSERT fq_nmod_mpoly_one(t, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fq_nmod_mpoly_mul(t, t, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } FLINT_ASSERT(fq_nmod_mpoly_equal(t, p, ctx)); #endif while (1) { fq_nmod_mpolyv_fit_length(dfac, 2, ctx); dfac->length = 2; fq_nmod_mpoly_one(dfac->coeffs + 0, ctx); fq_nmod_mpoly_one(dfac->coeffs + 1, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fq_nmod_mpoly_mul(dfac->coeffs + in, dfac->coeffs + in, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } success = _try_lift(tfac, q, dfac, p, m, alpha, n, ctx); if (success > 0) { fq_nmod_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fq_nmod_mpoly_swap(qfac->coeffs + qfac->length, tfac->coeffs + 1, ctx); qfac->length++; fq_nmod_mpoly_swap(q, tfac->coeffs + 0, ctx); fq_nmod_mpoly_swap(p, dfac->coeffs + 0, ctx); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else if (success < 0) { success = 0; goto cleanup; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } /* remnants are irreducible */ if (!fq_nmod_mpoly_is_fq_nmod(q, ctx)) { fq_nmod_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fq_nmod_mpoly_swap(qfac->coeffs + qfac->length, q, ctx); qfac->length++; } else { FLINT_ASSERT(fq_nmod_mpoly_is_one(q, ctx)); } fq_nmod_mpolyv_swap(qfac, pfac, ctx); } success = 1; fq_nmod_mpolyv_swap(fac, pfac, ctx); cleanup: flint_free(subset); for (i = 0; i < n; i++) fq_nmod_clear(alpha + i, ctx->fqctx); flint_free(alpha); for (i = 0; i < n; i++) fq_nmod_mpoly_clear(Aevals + i, ctx); flint_free(Aevals); flint_free(deg); flint_free(degeval); fq_nmod_mpolyv_clear(pfac, ctx); fq_nmod_mpolyv_clear(qfac, ctx); fq_nmod_mpolyv_clear(tfac, ctx); fq_nmod_mpolyv_clear(dfac, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(p, ctx); fq_nmod_mpoly_clear(q, ctx); n_poly_clear(c); n_bpoly_clear(B); n_tpoly_clear(F); FLINT_ASSERT(success == 0 || success == 1); #if FLINT_WANT_ASSERT if (success) { fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_one(t, ctx); for (i = 0; i < fac->length; i++) fq_nmod_mpoly_mul(t, t, fac->coeffs + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(t, A, ctx)); fq_nmod_mpoly_clear(t, ctx); } #endif return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/irred_smprime_zippel.c000066400000000000000000001312441461254215100242200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" static void _sort_and_delete_duplicates( fq_nmod_mpoly_t A, slong d, const mpoly_ctx_t mctx) { slong i, j; slong N = mpoly_words_per_exp(A->bits, mctx); for (i = 1; i < A->length; i++) for (j = i; j > 0 && mpoly_monomial_lt_nomask(A->exps + N*(j - 1), A->exps + N*j, N); j--) { mpoly_monomial_swap(A->exps + N*(j - 1), A->exps + N*j, N); _n_fq_swap(A->coeffs + d*(j - 1), A->coeffs + d*(j), d); } j = -1; for (i = 0; i < A->length; i++) { if (j >= 0 && mpoly_monomial_equal(A->exps + N*j, A->exps + N*i, N)) { FLINT_ASSERT(_n_fq_equal(A->coeffs + d*j, A->coeffs + d*i, d)); continue; } j++; _n_fq_set(A->coeffs + d*j, A->coeffs + d*i, d); mpoly_monomial_set(A->exps + N*j, A->exps + N*i, N); } j++; A->length = j; } static void _clearit( n_polyun_t W, mpoly_rbtree_ui_t T, slong idx) { mpoly_rbnode_ui_struct * nodes = T->nodes + 2; FLINT_ASSERT(0 <= idx && idx < T->length); if (nodes[idx].right >= 0) _clearit(W, T, nodes[idx].right); FLINT_ASSERT(W->length < W->alloc); W->exps[W->length] = nodes[idx].key; W->coeffs[W->length] = ((n_poly_struct *) T->data)[idx]; W->length++; if (nodes[idx].left >= 0) _clearit(W, T, nodes[idx].left); } static void fq_nmod_mpoly_set_eval_helper3( n_polyun_t EH, const fq_nmod_mpoly_t A, slong yvar, n_poly_struct * caches, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong xvar = 0; slong zvar = 1; slong i, j, k, n; ulong y, x, z; slong yoff, xoff, zoff, * off; slong yshift, xshift, zshift, * shift; mp_limb_t * p; flint_bitcnt_t bits = A->bits; slong Alen = A->length; const ulong * Aexps = A->exps; const mp_limb_t * Acoeffs = A->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; mpoly_rbtree_ui_t W; TMP_INIT; TMP_START; n_polyun_init(T); mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Alen; i++) { n_poly_struct * Wc; int its_new; y = (Aexps[N*i + yoff] >> yshift) & mask; x = (Aexps[N*i + xoff] >> xshift) & mask; z = (Aexps[N*i + zoff] >> zshift) & mask; Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); n_polyun_fit_length(EH, T->length); EH->length = T->length; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; n = T->coeffs[i].length; n_poly_fit_length(EH->coeffs + i, d*3*n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Ai = ind[j]; /* set cur = monomial eval */ _n_fq_one(p + d*j, d); for (k = 2; k < yvar; k++) { ulong ei = (Aexps[N*Ai + off[k]] >> shift[k]) & mask; n_fq_pow_cache_mulpow_ui(p + d*j, p + d*j, ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->fqctx); } /* copy cur to inc */ _n_fq_set(p + d*(1*n + j), p + d*(0*n + j), d); /* copy coeff */ _n_fq_set(p + d*(2*n + j), Acoeffs + d*Ai, d); } } n_polyun_clear(T); TMP_END; } static void fq_nmod_mpoly_set_evalp_helper3( n_polyun_t EH, const fq_nmod_mpoly_t A, slong yvar, n_poly_struct * caches, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong xvar = 0; slong zvar = 1; slong i, j, k, n; ulong y, x, z; slong yoff, xoff, zoff, * off; slong yshift, xshift, zshift, * shift; mp_limb_t * p; flint_bitcnt_t bits = A->bits; slong Alen = A->length; const ulong * Aexps = A->exps; const mp_limb_t * Acoeffs = A->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; mpoly_rbtree_ui_t W; TMP_INIT; TMP_START; n_polyun_init(T); mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Alen; i++) { n_poly_struct * Wc; int its_new; y = (Aexps[N*i + yoff] >> yshift) & mask; x = (Aexps[N*i + xoff] >> xshift) & mask; z = (Aexps[N*i + zoff] >> zshift) & mask; Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); n_polyun_fit_length(EH, T->length); EH->length = T->length; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; n = T->coeffs[i].length; n_poly_fit_length(EH->coeffs + i, (d + 2)*n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Ai = ind[j]; /* set cur = monomial eval */ p[j] = 1; for (k = 2; k < yvar; k++) { ulong ei = (Aexps[N*Ai + off[k]] >> shift[k]) & mask; p[j] = nmod_pow_cache_mulpow_ui(p[j], ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->fqctx->mod); } /* copy cur to inc */ p[j + n] = p[j]; /* copy coeff */ _n_fq_set(p + 2*n + d*j, Acoeffs + d*Ai, d); } } TMP_END; n_polyun_clear(T); } /* for each term Y^y*X^x*Z^z * pol(x1,...) in B with j < deg set Y^0*X^x*Z^z in H as the monomials with the monomial evals as coeffs merge monomial sets coming from different y's (shouldn't happen) */ static slong fq_nmod_mpoly_set_eval_helper_and_zip_form3( ulong * deg_, /* deg_X(B), output */ n_polyun_t EH, fq_nmod_mpolyu_t H, const fq_nmod_mpoly_t B, n_poly_struct * caches, slong yvar, /* Y = gen(yvar) (X = gen(0), Z = gen(1))*/ const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong xvar = 0; slong zvar = 1; slong i, j, k, n; slong * off, * shift; ulong y, x, z; mp_limb_t * p; fq_nmod_mpoly_struct * Hc; slong old_len, zip_length = 0; flint_bitcnt_t bits = B->bits; slong Blen = B->length; const ulong * Bexps = B->exps; const mp_limb_t * Bcoeffs = B->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; ulong deg; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == H->bits); FLINT_ASSERT(Blen > 0); TMP_START; off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); /* init T */ { mpoly_rbtree_ui_t W; n_poly_struct * Wc; slong yoff, xoff, zoff; slong yshift, xshift, zshift; int its_new; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); deg = (Bexps[N*0 + xoff] >> xshift) & mask; mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Blen; i++) { y = (Bexps[N*i + yoff] >> yshift) & mask; x = (Bexps[N*i + xoff] >> xshift) & mask; z = (Bexps[N*i + zoff] >> zshift) & mask; FLINT_ASSERT(x <= deg); Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); } n_polyun_fit_length(EH, T->length); EH->length = T->length; H->length = 0; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; y = extract_exp(EH->exps[i], 2, 3); x = extract_exp(EH->exps[i], 1, 3); z = extract_exp(EH->exps[i], 0, 3); n = T->coeffs[i].length; n_poly_fit_length(EH->coeffs + i, d*3*n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Bi = ind[j]; /* set cur = monomial eval */ _n_fq_one(p + d*j, d); for (k = 2; k < yvar; k++) { ulong ei = (Bexps[N*Bi + off[k]] >> shift[k]) & mask; n_fq_pow_cache_mulpow_ui(p + d*j, p + d*j, ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->fqctx); } /* copy cur to inc */ _n_fq_set(p + d*(1*n + j), p + d*(0*n + j), d); /* copy coeff */ _n_fq_set(p + d*(2*n + j), Bcoeffs + d*Bi, d); } if (x < deg) { FLINT_ASSERT(y == 0 && "strange but ok"); Hc = _fq_nmod_mpolyu_get_coeff(H, pack_exp3(0, x, z), ctx); fq_nmod_mpoly_fit_length(Hc, n, ctx); old_len = Hc->length; for (j = 0; j < n; j++) { _n_fq_set(Hc->coeffs + d*(old_len + j), p + d*j, d); mpoly_monomial_set(Hc->exps + N*(old_len + j), Bexps + N*ind[j], N); } Hc->length += n; zip_length = FLINT_MAX(zip_length, Hc->length); if (old_len > 0) { FLINT_ASSERT(0 && "strange but ok"); _sort_and_delete_duplicates(Hc, d, ctx->minfo); } } } n_polyun_clear(T); TMP_END; *deg_ = deg; return zip_length; } static slong fq_nmod_mpoly_set_evalp_helper_and_zip_form3( ulong * deg_, /* deg_X(B), output */ n_polyun_t EH, fq_nmod_mpolyu_t H, const fq_nmod_mpoly_t B, n_poly_struct * caches, slong yvar, /* Y = gen(yvar) (X = gen(0), Z = gen(1))*/ const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong xvar = 0; slong zvar = 1; slong i, j, k, n; slong * off, * shift; ulong y, x, z; mp_limb_t * p; fq_nmod_mpoly_struct * Hc; slong old_len, zip_length = 0; flint_bitcnt_t bits = B->bits; slong Blen = B->length; const ulong * Bexps = B->exps; const mp_limb_t * Bcoeffs = B->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; ulong deg; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == H->bits); FLINT_ASSERT(Blen > 0); TMP_START; off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); /* init T */ { mpoly_rbtree_ui_t W; n_poly_struct * Wc; slong yoff, xoff, zoff; slong yshift, xshift, zshift; int its_new; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); deg = (Bexps[N*0 + xoff] >> xshift) & mask; mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Blen; i++) { y = (Bexps[N*i + yoff] >> yshift) & mask; x = (Bexps[N*i + xoff] >> xshift) & mask; z = (Bexps[N*i + zoff] >> zshift) & mask; FLINT_ASSERT(x <= deg); Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); } n_polyun_fit_length(EH, T->length); EH->length = T->length; H->length = 0; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; y = extract_exp(EH->exps[i], 2, 3); x = extract_exp(EH->exps[i], 1, 3); z = extract_exp(EH->exps[i], 0, 3); n = T->coeffs[i].length; n_poly_fit_length(EH->coeffs + i, (d + 2)*n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Bi = ind[j]; /* set cur = monomial eval */ p[j] = 1; for (k = 2; k < yvar; k++) { ulong ei = (Bexps[N*Bi + off[k]] >> shift[k]) & mask; p[j] = nmod_pow_cache_mulpow_ui(p[j], ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->fqctx->mod); } /* copy cur to inc */ p[j + n] = p[j]; /* copy coeff */ _n_fq_set(p + 2*n + d*j, Bcoeffs + d*Bi, d); } if (x < deg) { FLINT_ASSERT(y == 0 && "strange but ok"); Hc = _fq_nmod_mpolyu_get_coeff(H, pack_exp3(0, x, z), ctx); _fq_nmod_mpoly_fit_length(&Hc->coeffs, &Hc->coeffs_alloc, 1, &Hc->exps, &Hc->exps_alloc, N, n); old_len = Hc->length; for (j = 0; j < n; j++) { Hc->coeffs[old_len + j] = p[j]; mpoly_monomial_set(Hc->exps + N*(old_len + j), Bexps + N*ind[j], N); } Hc->length += n; zip_length = FLINT_MAX(zip_length, Hc->length); if (old_len > 0) { FLINT_ASSERT(0 && "strange but ok"); _sort_and_delete_duplicates(Hc, 1, ctx->minfo); } } } n_polyun_clear(T); TMP_END; *deg_ = deg; return zip_length; } static void fq_nmod_polyu_eval_step( n_polyu_t E, n_polyun_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong Ai, Ei, n; mp_limb_t * p; n_polyu_fit_length(E, d*A->length); Ei = 0; for (Ai = 0; Ai < A->length; Ai++) { FLINT_ASSERT(Ei < E->alloc); E->exps[Ei] = A->exps[Ai]; n = A->coeffs[Ai].length; p = A->coeffs[Ai].coeffs; FLINT_ASSERT(A->coeffs[Ai].alloc >= d*3*n); _n_fq_zip_eval_step(E->coeffs + d*Ei, p + d*(0*n), p + d*(1*n), p + d*(2*n), n, ctx); Ei += !_n_fq_is_zero(E->coeffs + d*Ei, d); } E->length = Ei; } static void fq_nmod_polyu_evalp_step( n_polyu_t E, n_polyun_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong Ai, Ei, n; mp_limb_t * p; n_polyu_fit_length(E, d*A->length); Ei = 0; for (Ai = 0; Ai < A->length; Ai++) { FLINT_ASSERT(Ei < E->alloc); E->exps[Ei] = A->exps[Ai]; n = A->coeffs[Ai].length; p = A->coeffs[Ai].coeffs; FLINT_ASSERT(A->coeffs[Ai].alloc >= (d + 2)*n); _n_fqp_zip_eval_step(E->coeffs + d*Ei, p + 0*n, p + 1*n, p + 2*n, n, d, ctx->mod); Ei += !_n_fq_is_zero(E->coeffs + d*Ei, d); } E->length = Ei; } static void fq_nmod_polyu3_add_zip_limit1( n_polyun_t Z, const n_polyun_t A, const ulong deg1, slong cur_length, slong fit_length, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); const n_fq_poly_struct * Acoeffs = A->coeffs; ulong * Aexps = A->exps; n_fq_poly_struct * Zcoeffs = Z->coeffs; ulong * Zexps = Z->exps; slong Ai, ai, Zi, j; for (Zi = 0; Zi < Z->length; Zi++) { FLINT_ASSERT(Z->coeffs[Zi].length == cur_length); } Ai = -1; ai = -1; do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = n_poly_degree(Acoeffs + Ai); Zi = 0; while (Ai < A->length && Zi < Z->length) { if (Aexps[Ai] + ai > Zexps[Zi]) { /* missing from Z */ n_polyun_fit_length(Z, Z->length + 1); Zcoeffs = Z->coeffs; Zexps = Z->exps; for (j = Z->length; j > Zi; j--) { n_poly_swap(Zcoeffs + j, Zcoeffs + j - 1); FLINT_SWAP(ulong, Zexps[j], Zexps[j - 1]); } Z->length++; Zexps[Zi] = Aexps[Ai] + ai; n_poly_fit_length(Zcoeffs + Zi, d*fit_length); Zcoeffs[Zi].length = cur_length; flint_mpn_zero(Zcoeffs[Zi].coeffs, d*cur_length); goto in_both; } else if (Aexps[Ai] + ai < Zexps[Zi]) { /* missing from A */ FLINT_ASSERT(d*(cur_length + 1) <= Zcoeffs[Zi].alloc); _n_fq_zero(Zcoeffs[Zi].coeffs + d*cur_length, d); Zcoeffs[Zi].length = cur_length + 1; Zi++; } else { in_both: FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(d*(cur_length + 1) <= Zcoeffs[Zi].alloc); _n_fq_set(Zcoeffs[Zi].coeffs + d*cur_length, Acoeffs[Ai].coeffs + d*ai, d); Zcoeffs[Zi].length = cur_length + 1; Zi++; do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = n_poly_degree(Acoeffs + Ai); } } } /* everything in A must be put on the end of Z */ while (Ai < A->length) { Zi = Z->length; n_polyun_fit_length(Z, Zi + A->length - Ai); Zcoeffs = Z->coeffs; Zexps = Z->exps; Zexps[Zi] = Aexps[Ai] + ai; n_poly_fit_length(Zcoeffs + Zi, d*fit_length); Zcoeffs[Zi].length = cur_length; flint_mpn_zero(Zcoeffs[Zi].coeffs, d*cur_length); FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(d*(cur_length + 1) <= Zcoeffs[Zi].alloc); _n_fq_set(Zcoeffs[Zi].coeffs + d*cur_length, Acoeffs[Ai].coeffs + d*ai, d); Zcoeffs[Zi].length = cur_length + 1; Z->length = ++Zi; do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = n_poly_degree(Acoeffs + Ai); } } /* everything in Z must have a zero appended */ while (Zi < Z->length) { FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(d*(cur_length + 1) <= Zcoeffs[Zi].alloc); _n_fq_zero(Zcoeffs[Zi].coeffs + d*cur_length, d); Zcoeffs[Zi].length = cur_length + 1; Zi++; } for (Zi = 0; Zi < Z->length; Zi++) { FLINT_ASSERT(Z->coeffs[Zi].length == cur_length + 1); } } /* for each Y^y*X^x*Z^z in B with x = deg, keep the Y^y*X^x*Z^z*poly(x1,...) in B for each Y^y*X^x*Z^z in Z, assert that x < deg if there is no Y^0*X^x*Z^y in H, fail find coefficients of poly using this entry in H output Y^y*X^x*Z^z*poly(x1,...) to A sort A return -1: singular vandermonde matrix encountered 0: inconsistent system encountered 1: success */ static int fq_nmod_mpoly_from_zip( fq_nmod_mpoly_t B, const n_polyun_t Z, fq_nmod_mpolyu_t H, ulong deg, slong yvar, /* Y = gen(yvar) */ const fq_nmod_mpoly_ctx_t ctx, n_polyun_t M, /* temp */ n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; slong Hi, Zi, Bi, i, j; slong xvar = 0; slong zvar = 1; ulong x, y, z; flint_bitcnt_t bits = B->bits; mp_limb_t * Bcoeffs; ulong * Bexps; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong xoff, xshift, yoff, yshift, zoff, zshift; fq_nmod_mpoly_struct * Hc; slong Hlen = H->length; FLINT_ASSERT(bits == H->bits); n_polyun_fit_length(M, Hlen + 1); for (i = 0; i <= Hlen; i++) M->coeffs[i].length = 0; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); /* x is most significant in ctx, so keeping the lc_x in B is easy */ FLINT_ASSERT(xvar == 0); for (Bi = 0; Bi < B->length; Bi++) { x = (((B->exps + N*Bi)[xoff] >> xshift) & mask); FLINT_ASSERT(x <= deg); if (x != deg) break; } for (Zi = 0; Zi < Z->length; Zi++) { y = extract_exp(Z->exps[Zi], 2, 3); x = extract_exp(Z->exps[Zi], 1, 3); z = extract_exp(Z->exps[Zi], 0, 3); FLINT_ASSERT(x < deg); Hi = mpoly_monomial_index1_nomask(H->exps, H->length, pack_exp3(0, x, z)); if (Hi < 0) return 0; FLINT_ASSERT(Hi < Hlen); FLINT_ASSERT(H->exps[Hi] == pack_exp3(0, x, z)); Hc = H->coeffs + Hi; FLINT_ASSERT(bits == Hc->bits); FLINT_ASSERT(Hc->length > 0); fq_nmod_mpoly_fit_length(B, Bi + Hc->length, ctx); Bcoeffs = B->coeffs; if (M->coeffs[Hi].length < 1) n_fq_poly_product_roots_n_fq(M->coeffs + Hi, Hc->coeffs, Hc->length, ctx->fqctx, St); n_poly_fit_length(M->coeffs + Hlen, d*Hc->length); success = _n_fq_zip_vand_solve(Bcoeffs + d*Bi, Hc->coeffs, Hc->length, Z->coeffs[Zi].coeffs, Z->coeffs[Zi].length, M->coeffs[Hi].coeffs, M->coeffs[Hlen].coeffs, ctx->fqctx); if (success < 1) return success; Bexps = B->exps; for (j = Bi, i = 0; i < Hc->length; j++, i++) { if (_n_fq_is_zero(Bcoeffs + d*j, d)) continue; FLINT_ASSERT(N*Bi < B->exps_alloc); FLINT_ASSERT(d*Bi < B->coeffs_alloc); _n_fq_set(Bcoeffs + d*Bi, Bcoeffs + d*j, d); mpoly_monomial_set(Bexps + N*Bi, Hc->exps + N*i, N); (Bexps + N*Bi)[yoff] += y << yshift; Bi++; } } B->length = Bi; fq_nmod_mpoly_sort_terms(B, ctx); FLINT_ASSERT(fq_nmod_mpoly_is_canonical(B, ctx)); return 1; } static int fq_nmod_mpoly_from_zipp( fq_nmod_mpoly_t B, const n_polyun_t Z, fq_nmod_mpolyu_t H, ulong deg, slong yvar, /* Y = gen(yvar) */ const fq_nmod_mpoly_ctx_t ctx, n_polyun_t M) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; slong Hi, Zi, Bi, i, j; slong xvar = 0; slong zvar = 1; ulong x, y, z; flint_bitcnt_t bits = B->bits; mp_limb_t * Bcoeffs; ulong * Bexps; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong xoff, xshift, yoff, yshift, zoff, zshift; fq_nmod_mpoly_struct * Hc; slong Hlen = H->length; FLINT_ASSERT(bits == H->bits); n_polyun_fit_length(M, Hlen + 1); for (i = 0; i <= Hlen; i++) M->coeffs[i].length = 0; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); /* x is most significant in ctx, so keeping the lc_x in B is easy */ FLINT_ASSERT(xvar == 0); for (Bi = 0; Bi < B->length; Bi++) { x = (((B->exps + N*Bi)[xoff] >> xshift) & mask); FLINT_ASSERT(x <= deg); if (x != deg) break; } for (Zi = 0; Zi < Z->length; Zi++) { y = extract_exp(Z->exps[Zi], 2, 3); x = extract_exp(Z->exps[Zi], 1, 3); z = extract_exp(Z->exps[Zi], 0, 3); FLINT_ASSERT(x < deg); Hi = mpoly_monomial_index1_nomask(H->exps, H->length, pack_exp3(0, x, z)); if (Hi < 0) return 0; FLINT_ASSERT(Hi < Hlen); FLINT_ASSERT(H->exps[Hi] == pack_exp3(0, x, z)); Hc = H->coeffs + Hi; FLINT_ASSERT(bits == Hc->bits); FLINT_ASSERT(Hc->length > 0); fq_nmod_mpoly_fit_length(B, Bi + Hc->length, ctx); Bcoeffs = B->coeffs; if (M->coeffs[Hi].length < 1) n_poly_mod_product_roots_nmod_vec(M->coeffs + Hi, Hc->coeffs, Hc->length, ctx->fqctx->mod); n_poly_fit_length(M->coeffs + Hlen, Hc->length); success = _n_fqp_zip_vand_solve(Bcoeffs + d*Bi, Hc->coeffs, Hc->length, Z->coeffs[Zi].coeffs, Z->coeffs[Zi].length, M->coeffs[Hi].coeffs, M->coeffs[Hlen].coeffs, ctx->fqctx); if (success < 1) return success; Bexps = B->exps; for (j = Bi, i = 0; i < Hc->length; j++, i++) { if (_n_fq_is_zero(Bcoeffs + d*j, d)) continue; FLINT_ASSERT(d*Bi < B->coeffs_alloc); FLINT_ASSERT(N*Bi < B->exps_alloc); _n_fq_set(Bcoeffs + d*Bi, Bcoeffs + d*j, d); mpoly_monomial_set(Bexps + N*Bi, Hc->exps + N*i, N); (Bexps + N*Bi)[yoff] += y << yshift; Bi++; } } B->length = Bi; fq_nmod_mpoly_sort_terms(B, ctx); FLINT_ASSERT(fq_nmod_mpoly_is_canonical(B, ctx)); return 1; } /* bit counts of all degrees should be < FLINT_BITS/3 */ int fq_nmod_mpoly_hlift_zippel( slong m, fq_nmod_mpoly_struct * B, slong r, const fq_nmod_struct * alpha, const fq_nmod_mpoly_t A, const slong * degs, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success, betas_in_fp; slong i; slong zip_fails_remaining; slong req_zip_images, cur_zip_image; fq_nmod_mpolyu_struct * H; n_polyun_struct M[1], Aeh[1], * Beh, * BBeval, * Z; n_polyu_struct Aeval[1], * Beval; fq_nmod_struct * beta; n_poly_struct * caches; flint_bitcnt_t bits = A->bits; fq_nmod_mpoly_t T1, T2; n_poly_bpoly_stack_t St; ulong * Bdegs; const slong degs0 = degs[0]; FLINT_ASSERT(m > 2); FLINT_ASSERT(r > 1); FLINT_ASSERT(bits <= FLINT_BITS); #if FLINT_WANT_ASSERT { fq_nmod_mpoly_t T; slong j, * check_degs = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_degrees_si(check_degs, A, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); fq_nmod_mpoly_one(T, ctx); for (i = 0; i < r; i++) { fq_nmod_mpoly_degrees_si(check_degs, B + i, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); fq_nmod_mpoly_mul(T, T, B + i, ctx); } fq_nmod_mpoly_sub(T, A, T, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(T, T, m, alpha + m - 1, ctx); FLINT_ASSERT(fq_nmod_mpoly_is_zero(T, ctx)); fq_nmod_mpoly_clear(T, ctx); flint_free(check_degs); } #endif n_poly_stack_init(St->poly_stack); n_bpoly_stack_init(St->bpoly_stack); beta = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, fq_nmod_struct); for (i = 0; i < ctx->minfo->nvars; i++) fq_nmod_init(beta + i, ctx->fqctx); /* caches for powers of the betas */ caches = FLINT_ARRAY_ALLOC(3*ctx->minfo->nvars, n_poly_struct); for (i = 0; i < 3*ctx->minfo->nvars; i++) n_poly_init(caches + i); Bdegs = FLINT_ARRAY_ALLOC(r, ulong); H = FLINT_ARRAY_ALLOC(r, fq_nmod_mpolyu_struct); Beh = FLINT_ARRAY_ALLOC(r, n_polyun_struct); Beval = FLINT_ARRAY_ALLOC(r, n_polyu_struct); BBeval = FLINT_ARRAY_ALLOC(r, n_polyun_struct); Z = FLINT_ARRAY_ALLOC(r, n_polyun_struct); n_polyun_init(Aeh); n_polyu_init(Aeval); n_polyun_init(M); for (i = 0; i < r; i++) { fq_nmod_mpolyu_init(H + i, bits, ctx); n_polyun_init(Beh + i); n_polyu_init(Beval + i); n_polyun_init(BBeval + i); n_polyun_init(Z + i); } /* init done */ for (i = 0; i < r; i++) { success = fq_nmod_mpoly_repack_bits_inplace(B + i, bits, ctx); if (!success) goto cleanup; } zip_fails_remaining = 3; choose_betas: /* only beta[2], beta[3], ..., beta[m - 1] will be used */ betas_in_fp = (ctx->fqctx->mod.norm < FLINT_BITS/4); if (betas_in_fp) { for (i = 2; i < m; i++) { ulong bb = n_urandint(state, ctx->fqctx->mod.n - 3) + 2; fq_nmod_set_ui(beta + i, bb, ctx->fqctx); nmod_pow_cache_start(bb, caches + 3*i + 0, caches + 3*i + 1, caches + 3*i + 2); } fq_nmod_mpoly_set_evalp_helper3(Aeh, A, m, caches, ctx); } else { for (i = 2; i < m; i++) { fq_nmod_rand_not_zero(beta + i, state, ctx->fqctx); n_fq_pow_cache_start_fq_nmod(beta + i, caches + 3*i + 0, caches + 3*i + 1, caches + 3*i + 2, ctx->fqctx); } fq_nmod_mpoly_set_eval_helper3(Aeh, A, m, caches, ctx); } req_zip_images = 1; for (i = 0; i < r; i++) { slong this_images = betas_in_fp ? fq_nmod_mpoly_set_evalp_helper_and_zip_form3( Bdegs + i, Beh + i, H + i, B + i, caches, m, ctx) : fq_nmod_mpoly_set_eval_helper_and_zip_form3( Bdegs + i, Beh + i, H + i, B + i, caches, m, ctx); req_zip_images = FLINT_MAX(req_zip_images, this_images); FLINT_ASSERT(Bdegs[i] > 0); Z[i].length = 0; } for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { if (betas_in_fp) { fq_nmod_polyu_evalp_step(Aeval, Aeh, ctx->fqctx); for (i = 0; i < r; i++) fq_nmod_polyu_evalp_step(Beval + i, Beh + i, ctx->fqctx); } else { fq_nmod_polyu_eval_step(Aeval, Aeh, ctx->fqctx); for (i = 0; i < r; i++) fq_nmod_polyu_eval_step(Beval + i, Beh + i, ctx->fqctx); } success = n_fq_polyu3_hlift(r, BBeval, Aeval, Beval, alpha + m - 1, degs0, ctx->fqctx, St); if (success < 1) { if (--zip_fails_remaining >= 0) goto choose_betas; success = 0; goto cleanup; } for (i = 0; i < r; i++) { fq_nmod_polyu3_add_zip_limit1(Z + i, BBeval + i, Bdegs[i], cur_zip_image, req_zip_images, ctx->fqctx); } } for (i = 0; i < r; i++) { success = betas_in_fp ? fq_nmod_mpoly_from_zipp(B + i, Z + i, H + i, Bdegs[i], m, ctx, M) : fq_nmod_mpoly_from_zip(B + i, Z + i, H + i, Bdegs[i], m, ctx, M, St->poly_stack); if (success < 1) { success = 0; goto cleanup; } } fq_nmod_mpoly_init3(T1, A->length, bits, ctx); fq_nmod_mpoly_init3(T2, A->length, bits, ctx); fq_nmod_mpoly_mul(T1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { fq_nmod_mpoly_mul(T2, T1, B + i, ctx); fq_nmod_mpoly_swap(T1, T2, ctx); } success = fq_nmod_mpoly_equal(T1, A, ctx); fq_nmod_mpoly_clear(T1, ctx); fq_nmod_mpoly_clear(T2, ctx); cleanup: n_polyun_clear(Aeh); n_polyu_clear(Aeval); n_polyun_clear(M); for (i = 0; i < r; i++) { fq_nmod_mpolyu_clear(H + i, ctx); n_polyun_clear(Beh + i); n_polyu_clear(Beval + i); n_polyun_clear(BBeval + i); n_polyun_clear(Z + i); } for (i = 0; i < ctx->minfo->nvars; i++) fq_nmod_clear(beta + i, ctx->fqctx); flint_free(beta); for (i = 0; i < 3*ctx->minfo->nvars; i++) n_poly_clear(caches + i); flint_free(caches); flint_free(Bdegs); flint_free(H); flint_free(Beh); flint_free(Beval); flint_free(BBeval); flint_free(Z); n_poly_stack_clear(St->poly_stack); n_bpoly_stack_clear(St->bpoly_stack); return success; } /* return 1: success 0: failed -1: exception */ int fq_nmod_mpoly_factor_irred_smprime_zippel( fq_nmod_mpolyv_t fac, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_factor_t lcAfac, const fq_nmod_mpoly_t lcA, const fq_nmod_mpoly_ctx_t ctx, flint_rand_t state) { slong d = fq_nmod_ctx_degree(ctx->fqctx); int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; fq_nmod_struct * alpha; n_poly_struct * alphabetas; fq_nmod_mpoly_struct * Aevals; slong * degs, * degeval; fq_nmod_mpolyv_t tfac; fq_nmod_mpoly_t t, Acopy; fq_nmod_mpoly_struct * newA; n_poly_t Abfc; n_bpoly_t Ab; n_tpoly_t Abfp; fq_nmod_mpoly_t m, mpow; fq_nmod_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(_n_fq_is_one(A->coeffs + d*0, d)); FLINT_ASSERT(A->bits <= FLINT_BITS); if (ctx->fqctx->modulus->length < n_clog(A->length, ctx->fqctx->modulus->mod.n)) return 0; fq_nmod_mpoly_init(Acopy, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_mpoly_init(mpow, ctx); fq_nmod_mpolyv_init(new_lcs, ctx); fq_nmod_mpolyv_init(lc_divs, ctx); n_poly_init(Abfc); n_tpoly_init(Abfp); n_bpoly_init(Ab); degs = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); alpha = FLINT_ARRAY_ALLOC(n, fq_nmod_struct); alphabetas = FLINT_ARRAY_ALLOC(n, n_poly_struct); Aevals = FLINT_ARRAY_ALLOC(n, fq_nmod_mpoly_struct); for (i = 0; i < n; i++) { fq_nmod_init(alpha + i, ctx->fqctx); n_poly_init(alphabetas + i); fq_nmod_mpoly_init(Aevals + i, ctx); } fq_nmod_mpolyv_init(tfac, ctx); fq_nmod_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; fq_nmod_mpoly_degrees_si(degs, A, ctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) { fq_nmod_rand(alpha + i, state, ctx->fqctx); if (fq_nmod_is_zero(alpha + i, ctx->fqctx)) fq_nmod_one(alpha + i, ctx->fqctx); } /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fq_nmod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } /* make sure univar is squarefree */ fq_nmod_mpoly_derivative(t, Aevals + 0, 0, ctx); fq_nmod_mpoly_gcd(t, t, Aevals + 0, ctx); if (!fq_nmod_mpoly_is_one(t, ctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 5) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { n_poly_fit_length(alphabetas + i, d*alphabetas_length); n_fq_set_fq_nmod(alphabetas[i].coeffs + d*0, alpha + i, ctx->fqctx); for (j = d; j < d*alphabetas_length; j++) alphabetas[i].coeffs[j] = n_urandint(state, ctx->fqctx->mod.n); alphabetas[i].length = alphabetas_length; _n_fq_poly_normalise(alphabetas + i, d); } _fq_nmod_mpoly_eval_rest_to_n_fq_bpoly(Ab, A, alphabetas, ctx); success = n_fq_bpoly_factor_smprime(Abfc, Abfp, Ab, 0, ctx->fqctx); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { fq_nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } fq_nmod_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = fq_nmod_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) fq_nmod_mpoly_one(lc_divs->coeffs + i, ctx); } success = fq_nmod_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = fq_nmod_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } fq_nmod_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fq_nmod_mpoly_is_one(mpow, ctx)) { newA = (fq_nmod_mpoly_struct *) A; } else { newA = Acopy; fq_nmod_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } fq_nmod_mpoly_degrees_si(degs, newA, ctx); for (i = 0; i < n + 1; i++) { if (FLINT_BIT_COUNT(degs[i]) >= FLINT_BITS/3) { success = -1; goto cleanup; } } fq_nmod_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(t, mpow, i + 1, alpha + i, ctx); fq_nmod_mpoly_swap(t, mpow, ctx); fq_nmod_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); } fq_nmod_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fq_nmod_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fq_nmod_mpoly_evaluate_one_fq_nmod(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fq_nmod_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { fq_nmod_t q, qt; fq_nmod_init(q, ctx->fqctx); fq_nmod_init(qt, ctx->fqctx); FLINT_ASSERT(fq_nmod_mpoly_is_fq_nmod(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fq_nmod_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _fq_nmod_mpoly_set_n_fq_bpoly_gen1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); n_fq_get_fq_nmod(qt, fac->coeffs[i].coeffs + d*0, ctx->fqctx); fq_nmod_inv(q, qt, ctx->fqctx); n_fq_get_fq_nmod(qt, new_lcs->coeffs[0*r + i].coeffs + 0, ctx->fqctx); fq_nmod_mul(q, q, qt, ctx->fqctx); fq_nmod_mpoly_scalar_mul_fq_nmod(fac->coeffs + i, fac->coeffs + i, q, ctx); fq_nmod_clear(q, ctx->fqctx); fq_nmod_clear(qt, ctx->fqctx); } fq_nmod_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _fq_nmod_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } if (k > 2) { success = fq_nmod_mpoly_hlift_zippel(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx, state); } else { success = fq_nmod_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); } if (!success) goto next_alphabetas; fq_nmod_mpolyv_swap(tfac, fac, ctx); } if (!fq_nmod_mpoly_is_fq_nmod(m, ctx)) { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!fq_nmod_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = fq_nmod_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } } for (i = 0; i < r; i++) fq_nmod_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); success = 1; cleanup: fq_nmod_mpolyv_clear(new_lcs, ctx); fq_nmod_mpolyv_clear(lc_divs, ctx); n_poly_clear(Abfc); n_tpoly_clear(Abfp); n_bpoly_clear(Ab); for (i = 0; i < n; i++) { fq_nmod_mpoly_clear(Aevals + i, ctx); n_poly_clear(alphabetas + i); fq_nmod_clear(alpha + i, ctx->fqctx); } flint_free(alphabetas); flint_free(alpha); flint_free(Aevals); flint_free(degs); flint_free(degeval); fq_nmod_mpolyv_clear(tfac, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(Acopy, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { fq_nmod_mpoly_t prod; fq_nmod_mpoly_init(prod, ctx); fq_nmod_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) fq_nmod_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(prod, A, ctx)); fq_nmod_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/lcc_wang.c000066400000000000000000000102331461254215100215430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" int fq_nmod_mpoly_factor_lcc_wang( fq_nmod_mpoly_struct * lc_divs, const fq_nmod_mpoly_factor_t lcAfac, const n_poly_t Auc, const n_bpoly_struct * Auf, slong r, const n_poly_struct * alpha, const fq_nmod_mpoly_ctx_t ctx) { int success; slong i, j, k; const slong n = ctx->minfo->nvars - 1; n_poly_struct * lcAfaceval; n_poly_struct * d; n_poly_t Q, R; fq_nmod_mpoly_t t; slong N, * offsets, * shifts, * starts, * ends, * stops; ulong mask, * es; n_poly_struct * T; n_poly_init(Q); n_poly_init(R); fq_nmod_mpoly_init(t, ctx); lcAfaceval = FLINT_ARRAY_ALLOC(lcAfac->num, n_poly_struct); for (i = 0; i < lcAfac->num; i++) n_poly_init(lcAfaceval + i); d = FLINT_ARRAY_ALLOC(lcAfac->num + 1, n_poly_struct); for (i = 0; i < lcAfac->num + 1; i++) n_poly_init(d + i); starts = FLINT_ARRAY_ALLOC(n + 1, slong); ends = FLINT_ARRAY_ALLOC(n + 1, slong); stops = FLINT_ARRAY_ALLOC(n + 1, slong); es = FLINT_ARRAY_ALLOC(n + 1, ulong); T = FLINT_ARRAY_ALLOC(n + 2, n_poly_struct); for (i = 0; i < n + 2; i++) n_poly_init(T + i); offsets = FLINT_ARRAY_ALLOC(n + 1, slong); shifts = FLINT_ARRAY_ALLOC(n + 1, slong); /* init done */ for (j = 0; j < lcAfac->num; j++) { fq_nmod_mpoly_struct * P = lcAfac->poly + j; for (i = 0; i < n + 1; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, P->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - P->bits); N = mpoly_words_per_exp_sp(P->bits, ctx->minfo); _fq_nmod_mpoly_eval_rest_n_fq_poly(T, starts, ends, stops, es, P->coeffs, P->exps, P->length, 1, alpha, offsets, shifts, N, mask, n + 1, ctx->fqctx); n_fq_poly_set(lcAfaceval + j, T + 0, ctx->fqctx); } n_fq_poly_set(d + 0, Auc, ctx->fqctx); for (i = 0; i < lcAfac->num; i++) { n_fq_poly_make_monic(Q, lcAfaceval + i, ctx->fqctx); if (n_poly_degree(Q) < 1) { success = 0; goto cleanup; } for (j = i; j >= 0; j--) { n_fq_poly_set(R, d + j, ctx->fqctx); while (n_poly_degree(R) > 0) { n_fq_poly_gcd(R, R, Q, ctx->fqctx); n_fq_poly_divrem(Q, T + 0, Q, R, ctx->fqctx); FLINT_ASSERT(n_poly_is_zero(T + 0)); if (n_poly_degree(Q) < 1) { success = 0; goto cleanup; } } } n_fq_poly_set(d + i + 1, Q, ctx->fqctx); } for (j = 0; j < r; j++) { fq_nmod_mpoly_one(lc_divs + j, ctx); n_fq_poly_mul(R, Auf[j].coeffs + Auf[j].length - 1, Auc, ctx->fqctx); for (i = lcAfac->num - 1; i >= 0; i--) { n_fq_poly_make_monic(Q, lcAfaceval + i, ctx->fqctx); if (n_poly_degree(Q) < 1) continue; k = n_fq_poly_remove(R, Q, ctx->fqctx); fq_nmod_mpoly_pow_ui(t, lcAfac->poly + i, k, ctx); fq_nmod_mpoly_mul(lc_divs + j, lc_divs + j, t, ctx); } } success = 1; cleanup: n_poly_clear(Q); n_poly_clear(R); fq_nmod_mpoly_clear(t, ctx); for (i = 0; i < lcAfac->num; i++) n_poly_clear(lcAfaceval + i); flint_free(lcAfaceval); for (i = 0; i < lcAfac->num + 1; i++) n_poly_clear(d + i); flint_free(d); for (i = 0; i < n + 2; i++) n_poly_clear(T + i); flint_free(T); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/mpoly_hlift.c000066400000000000000000000276721461254215100223330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" static int _hlift_quartic2( slong m, fq_nmod_mpoly_struct * f, slong r, const fq_nmod_struct * alpha, const fq_nmod_mpoly_t A, const slong * degs, const fq_nmod_mpoly_ctx_t ctx) { int success; slong i, j; fq_nmod_mpoly_t Aq, t, t2, t3, xalpha; fq_nmod_mpoly_geobucket_t G; fq_nmod_mpoly_struct betas[2], * deltas; fq_nmod_mpoly_pfrac_t I; fq_nmod_mpolyv_struct B[2]; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r == 2); r = 2; fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(t2, ctx); fq_nmod_mpoly_init(t3, ctx); fq_nmod_mpoly_init(xalpha, ctx); fq_nmod_mpoly_init(Aq, ctx); fq_nmod_mpoly_geobucket_init(G, ctx); fq_nmod_mpoly_gen(xalpha, m, ctx); fq_nmod_mpoly_sub_fq_nmod(xalpha, xalpha, alpha + m - 1, ctx); fq_nmod_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (i = 0; i < r; i++) { fq_nmod_mpolyv_init(B + i, ctx); fq_nmod_mpoly_repack_bits_inplace(f + i, bits, ctx); fq_nmod_mpoly_to_mpolyv(B + i, f + i, xalpha, ctx); fq_nmod_mpolyv_fit_length(B + i, degs[m] + 1, ctx); for (j = B[i].length; j <= degs[m]; j++) fq_nmod_mpoly_zero(B[i].coeffs + j, ctx); } for (i = 0; i < r; i++) betas[i] = B[i].coeffs[0]; success = fq_nmod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; fq_nmod_mpoly_divrem(Aq, t, A, xalpha, ctx); #if FLINT_WANT_ASSERT fq_nmod_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fq_nmod_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { fq_nmod_mpoly_divrem(t2, t, Aq, xalpha, ctx); fq_nmod_mpoly_swap(Aq, t2, ctx); fq_nmod_mpoly_geobucket_set(G, t, ctx); for (i = 0; i <= j; i++) { fq_nmod_mpoly_mul(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx); fq_nmod_mpoly_geobucket_sub(G, t, ctx); } fq_nmod_mpoly_geobucket_empty(t, G, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) continue; success = fq_nmod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fq_nmod_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fq_nmod_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fq_nmod_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } } success = 1; cleanup: fq_nmod_mpoly_pfrac_clear(I, ctx); for (i = 0; i < r; i++) { if (success) fq_nmod_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); fq_nmod_mpolyv_clear(B + i, ctx); } fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_clear(t3, ctx); fq_nmod_mpoly_clear(xalpha, ctx); fq_nmod_mpoly_clear(Aq, ctx); fq_nmod_mpoly_geobucket_clear(G, ctx); return success; } static int _hlift_quartic( slong m, fq_nmod_mpoly_struct * f, slong r, const fq_nmod_struct * alpha, const fq_nmod_mpoly_t A, const slong * degs, const fq_nmod_mpoly_ctx_t ctx) { int success; slong i, j, k; fq_nmod_mpoly_t Aq, t, t1, t2, t3, xalpha; fq_nmod_mpoly_struct * betas, * deltas; fq_nmod_mpoly_pfrac_t I; fq_nmod_mpolyv_struct * B, * U; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 2); betas = FLINT_ARRAY_ALLOC(r, fq_nmod_mpoly_struct); B = FLINT_ARRAY_ALLOC(2*r, fq_nmod_mpolyv_struct); U = B + r; fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(t1, ctx); fq_nmod_mpoly_init(t2, ctx); fq_nmod_mpoly_init(t3, ctx); fq_nmod_mpoly_init(xalpha, ctx); fq_nmod_mpoly_init(Aq, ctx); fq_nmod_mpoly_gen(xalpha, m, ctx); fq_nmod_mpoly_sub_fq_nmod(xalpha, xalpha, alpha + m - 1, ctx); fq_nmod_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (k = 0; k < r; k++) { fq_nmod_mpolyv_init(U + k, ctx); fq_nmod_mpolyv_fit_length(U + k, degs[m] + 1, ctx); for (j = 0; j <= degs[m]; j++) fq_nmod_mpoly_zero(U[k].coeffs + j, ctx); fq_nmod_mpolyv_init(B + k, ctx); fq_nmod_mpoly_repack_bits_inplace(f + k, bits, ctx); fq_nmod_mpoly_to_mpolyv(B + k, f + k, xalpha, ctx); fq_nmod_mpolyv_fit_length(B + k, degs[m] + 1, ctx); for (j = B[k].length; j <= degs[m]; j++) fq_nmod_mpoly_zero(B[k].coeffs + j, ctx); betas[k] = B[k].coeffs[0]; } success = fq_nmod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; k = r - 2; fq_nmod_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k >= 1; k--) fq_nmod_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx); fq_nmod_mpoly_divrem(Aq, t, A, xalpha, ctx); #if FLINT_WANT_ASSERT fq_nmod_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fq_nmod_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fq_nmod_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { k = r - 2; fq_nmod_mpoly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { fq_nmod_mpoly_mul(t1, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fq_nmod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t1, ctx); } for (k--; k >= 1; k--) { fq_nmod_mpoly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { fq_nmod_mpoly_mul(t1, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); fq_nmod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t1, ctx); } } fq_nmod_mpoly_divrem(t2, t, Aq, xalpha, ctx); fq_nmod_mpoly_swap(Aq, t2, ctx); for (i = 0; i <= j; i++) { fq_nmod_mpoly_mul(t2, B[0].coeffs + i, U[1].coeffs + j - i, ctx); fq_nmod_mpoly_sub(t3, t, t2, ctx); fq_nmod_mpoly_swap(t, t3, ctx); } if (fq_nmod_mpoly_is_zero(t, ctx)) continue; success = fq_nmod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fq_nmod_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fq_nmod_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fq_nmod_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } k = r - 2; fq_nmod_mpoly_mul(t, B[k].coeffs + 0, deltas + k + 1, ctx); fq_nmod_mpoly_mul(t1, deltas + k, B[k + 1].coeffs + 0, ctx); fq_nmod_mpoly_add(t, t, t1, ctx); fq_nmod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); for (k--; k >= 1; k--) { fq_nmod_mpoly_mul(t1, B[k].coeffs + 0, t, ctx); fq_nmod_mpoly_swap(t, t1, ctx); fq_nmod_mpoly_mul(t1, deltas + k, U[k + 1].coeffs + 0, ctx); fq_nmod_mpoly_add(t, t, t1, ctx); fq_nmod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } success = 1; cleanup: fq_nmod_mpoly_pfrac_clear(I, ctx); flint_free(betas); for (i = 0; i < r; i++) { if (success) fq_nmod_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); fq_nmod_mpolyv_clear(B + i, ctx); fq_nmod_mpolyv_clear(U + i, ctx); } flint_free(B); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(t1, ctx); fq_nmod_mpoly_clear(t2, ctx); fq_nmod_mpoly_clear(t3, ctx); fq_nmod_mpoly_clear(xalpha, ctx); fq_nmod_mpoly_clear(Aq, ctx); return success; } static int _hlift_quintic( slong m, fq_nmod_mpoly_struct * f, slong r, const fq_nmod_struct * alpha, const fq_nmod_mpoly_t A, const slong * degs, const fq_nmod_mpoly_ctx_t ctx) { int success; slong i, j; fq_nmod_mpoly_t e, t, pow, xalpha, q; fq_nmod_mpoly_struct * betas, * deltas; fq_nmod_mpoly_pfrac_t I; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 1); fq_nmod_mpoly_init(e, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_init(pow, ctx); fq_nmod_mpoly_init(xalpha, ctx); fq_nmod_mpoly_init(q, ctx); betas = (fq_nmod_mpoly_struct *) flint_malloc(r*sizeof(fq_nmod_mpoly_struct)); for (i = 0; i < r; i++) { fq_nmod_mpoly_init(betas + i, ctx); fq_nmod_mpoly_repack_bits_inplace(f + i, bits, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(betas + i, f + i, m, alpha + m - 1, ctx); } fq_nmod_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fq_nmod_mpoly_mul(t, t, f + i, ctx); fq_nmod_mpoly_sub(e, A, t, ctx); fq_nmod_mpoly_one(pow, ctx); fq_nmod_mpoly_repack_bits_inplace(pow, bits, ctx); fq_nmod_mpoly_gen(xalpha, m, ctx); fq_nmod_mpoly_sub_fq_nmod(xalpha, xalpha, alpha + m - 1, ctx); fq_nmod_mpoly_repack_bits_inplace(xalpha, bits, ctx); fq_nmod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); deltas = I->deltas + (m - 1)*I->r; for (j = 1; j <= degs[m]; j++) { if (fq_nmod_mpoly_is_zero(e, ctx)) { success = 1; goto cleanup; } fq_nmod_mpoly_mul(pow, pow, xalpha, ctx); success = fq_nmod_mpoly_divides(q, e, pow, ctx); FLINT_ASSERT(success); fq_nmod_mpoly_evaluate_one_fq_nmod(t, q, m, alpha + m - 1, ctx); success = fq_nmod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } for (i = 0; i < r; i++) { fq_nmod_mpoly_mul(t, deltas + i, pow, ctx); fq_nmod_mpoly_add(f + i, f + i, t, ctx); } fq_nmod_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fq_nmod_mpoly_mul(t, t, f + i, ctx); fq_nmod_mpoly_sub(e, A, t, ctx); } success = fq_nmod_mpoly_is_zero(e, ctx); cleanup: fq_nmod_mpoly_pfrac_clear(I, ctx); fq_nmod_mpoly_clear(e, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(pow, ctx); fq_nmod_mpoly_clear(xalpha, ctx); fq_nmod_mpoly_clear(q, ctx); for (i = 0; i < r; i++) { if (success) fq_nmod_mpoly_repack_bits_inplace(f + i, bits, ctx); fq_nmod_mpoly_clear(betas + i, ctx); } flint_free(betas); return success; } /* should have A = prod_i f[i] mod (gen(m) - alpha[m-1]) */ int fq_nmod_mpoly_hlift( slong m, fq_nmod_mpoly_struct * f, /* length r */ slong r, const fq_nmod_struct * alpha, const fq_nmod_mpoly_t A, const slong * degs, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(r >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (r == 2) return _hlift_quartic2(m, f, r, alpha, A, degs, ctx); else if (r < 20) return _hlift_quartic(m, f, r, alpha, A, degs, ctx); else return _hlift_quintic(m, f, r, alpha, A, degs, ctx); } flint-3.1.3/src/fq_nmod_mpoly_factor/mpoly_pfrac.c000066400000000000000000000233061461254215100223060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #include "fq_nmod_mpoly_factor.h" int fq_nmod_mpoly_pfrac_init( fq_nmod_mpoly_pfrac_t I, flint_bitcnt_t bits, slong r, slong w, const fq_nmod_mpoly_struct * betas, const fq_nmod_struct * alpha, const fq_nmod_mpoly_ctx_t ctx) { slong success = 1; slong i, j, k; fq_nmod_poly_t p; fq_nmod_poly_t G, S, pq; FLINT_ASSERT(bits <= FLINT_BITS); I->bits = bits; I->r = r; I->w = w; I->dbetas = FLINT_ARRAY_ALLOC(r, fq_nmod_poly_struct); I->inv_prod_dbetas = FLINT_ARRAY_ALLOC(r, fq_nmod_poly_struct); I->prod_mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, fq_nmod_mpoly_struct); I->prod_mbetas_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, fq_nmod_mpolyv_struct); I->mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, fq_nmod_mpoly_struct); I->deltas = FLINT_ARRAY_ALLOC((w + 1)*r, fq_nmod_mpoly_struct); I->xalpha = FLINT_ARRAY_ALLOC(w + 1, fq_nmod_mpoly_struct); I->q = FLINT_ARRAY_ALLOC(w + 1, fq_nmod_mpoly_struct); I->G = FLINT_ARRAY_ALLOC(w + 1, fq_nmod_mpoly_geobucket_struct); I->qt = FLINT_ARRAY_ALLOC(w + 1, fq_nmod_mpoly_struct); I->newt = FLINT_ARRAY_ALLOC(w + 1, fq_nmod_mpoly_struct); I->delta_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, fq_nmod_mpolyv_struct); for (i = 0; i <= w; i++) { fq_nmod_mpoly_init(I->xalpha + i, ctx); fq_nmod_mpoly_init(I->q + i, ctx); fq_nmod_mpoly_geobucket_init(I->G + i, ctx); fq_nmod_mpoly_init(I->qt + i, ctx); fq_nmod_mpoly_init(I->newt + i, ctx); for (j = 0; j < r; j++) { fq_nmod_mpoly_init(I->deltas + i*r + j, ctx); fq_nmod_mpolyv_init(I->delta_coeffs + i*r + j, ctx); } if (i < 1) continue; fq_nmod_mpoly_gen(I->xalpha + i, i, ctx); fq_nmod_mpoly_sub_fq_nmod(I->xalpha + i, I->xalpha + i, alpha + i - 1, ctx); fq_nmod_mpoly_repack_bits_inplace(I->xalpha + i, I->bits, ctx); } fq_nmod_poly_init(p, ctx->fqctx); fq_nmod_poly_init(G, ctx->fqctx); fq_nmod_poly_init(S, ctx->fqctx); fq_nmod_poly_init(pq, ctx->fqctx); /* set betas */ i = w; for (j = 0; j < r; j++) { fq_nmod_mpoly_init(I->mbetas + i*r + j, ctx); fq_nmod_mpoly_set(I->mbetas + i*r + j, betas + j, ctx); } for (i--; i >= 0; i--) { for (j = 0; j < r; j++) { fq_nmod_mpoly_init(I->mbetas + i*r + j, ctx); fq_nmod_mpoly_evaluate_one_fq_nmod(I->mbetas + i*r + j, I->mbetas + (i + 1)*r + j, i + 1, alpha + i, ctx); } } for (j = 0; j < r; j++) { fq_nmod_poly_init(I->dbetas + j, ctx->fqctx); if (!fq_nmod_mpoly_get_fq_nmod_poly(I->dbetas + j, I->mbetas + 0*r + j, 0, ctx)) { success = 0; } } /* set product of betas */ for (i = w; i >= 0; i--) { for (j = 0; j < r; j++) { fq_nmod_mpoly_init(I->prod_mbetas + i*r + j, ctx); fq_nmod_mpoly_one(I->prod_mbetas + i*r + j, ctx); for (k = 0; k < r; k++) { if (k == j) continue; fq_nmod_mpoly_mul(I->prod_mbetas + i*r + j, I->prod_mbetas + i*r + j, I->mbetas + i*r + k, ctx); } fq_nmod_mpolyv_init(I->prod_mbetas_coeffs + i*r + j, ctx); if (i > 0) { fq_nmod_mpoly_to_mpolyv(I->prod_mbetas_coeffs + i*r + j, I->prod_mbetas + i*r + j, I->xalpha + i, ctx); } } } for (j = 0; j < r; j++) fq_nmod_poly_init(I->inv_prod_dbetas + j, ctx->fqctx); for (j = 0; success && j < r; j++) { if (fq_nmod_poly_degree(I->dbetas + j, ctx->fqctx) != fq_nmod_mpoly_degree_si(betas + j, 0, ctx)) { success = 0; } } for (j = 0; success && j < r; j++) { fq_nmod_poly_one(pq, ctx->fqctx); for (k = 0; k < r; k++) { if (k == j) continue; fq_nmod_poly_mul(pq, pq, I->dbetas + k, ctx->fqctx); } fq_nmod_poly_xgcd(G, S, I->inv_prod_dbetas + j, I->dbetas + j, pq, ctx->fqctx); if (!fq_nmod_poly_is_one(G, ctx->fqctx)) { success = 0; } } fq_nmod_poly_clear(p, ctx->fqctx); fq_nmod_poly_clear(G, ctx->fqctx); fq_nmod_poly_clear(S, ctx->fqctx); fq_nmod_poly_clear(pq, ctx->fqctx); I->dbetas_mvar = FLINT_ARRAY_ALLOC(r, fq_nmod_mpoly_struct); I->inv_prod_dbetas_mvar = FLINT_ARRAY_ALLOC(r, fq_nmod_mpoly_struct); for (j = 0; j < r; j++) { fq_nmod_mpoly_init(I->dbetas_mvar + j, ctx); fq_nmod_mpoly_init(I->inv_prod_dbetas_mvar + j, ctx); _fq_nmod_mpoly_set_fq_nmod_poly(I->dbetas_mvar + j, I->bits, I->dbetas[j].coeffs, I->dbetas[j].length, 0, ctx); _fq_nmod_mpoly_set_fq_nmod_poly(I->inv_prod_dbetas_mvar + j, I->bits, I->inv_prod_dbetas[j].coeffs, I->inv_prod_dbetas[j].length, 0, ctx); } fq_nmod_mpoly_init(I->T, ctx); fq_nmod_mpoly_init(I->Q, ctx); fq_nmod_mpoly_init(I->R, ctx); FLINT_ASSERT(success == 1); return success; } void fq_nmod_mpoly_pfrac_clear( fq_nmod_mpoly_pfrac_t I, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; for (i = 0; i <= I->w; i++) { fq_nmod_mpoly_clear(I->xalpha + i, ctx); fq_nmod_mpoly_clear(I->q + i, ctx); fq_nmod_mpoly_geobucket_clear(I->G + i, ctx); fq_nmod_mpoly_clear(I->qt + i, ctx); fq_nmod_mpoly_clear(I->newt + i, ctx); for (j = 0; j < I->r; j++) fq_nmod_mpolyv_clear(I->delta_coeffs + i*I->r + j, ctx); } flint_free(I->xalpha); flint_free(I->q); flint_free(I->G); flint_free(I->qt); flint_free(I->newt); flint_free(I->delta_coeffs); for (j = 0; j < I->r; j++) { fq_nmod_poly_clear(I->inv_prod_dbetas + j, ctx->fqctx); fq_nmod_poly_clear(I->dbetas + j, ctx->fqctx); for (i = 0; i <= I->w; i++) { fq_nmod_mpolyv_clear(I->prod_mbetas_coeffs + i*I->r + j, ctx); fq_nmod_mpoly_clear(I->prod_mbetas + i*I->r + j, ctx); fq_nmod_mpoly_clear(I->mbetas + i*I->r + j, ctx); fq_nmod_mpoly_clear(I->deltas + i*I->r + j, ctx); } } flint_free(I->inv_prod_dbetas); flint_free(I->dbetas); flint_free(I->prod_mbetas); flint_free(I->prod_mbetas_coeffs); flint_free(I->mbetas); flint_free(I->deltas); for (j = 0; j < I->r; j++) { fq_nmod_mpoly_clear(I->dbetas_mvar + j, ctx); fq_nmod_mpoly_clear(I->inv_prod_dbetas_mvar + j, ctx); } flint_free(I->dbetas_mvar); flint_free(I->inv_prod_dbetas_mvar); fq_nmod_mpoly_clear(I->T, ctx); fq_nmod_mpoly_clear(I->Q, ctx); fq_nmod_mpoly_clear(I->R, ctx); } int fq_nmod_mpoly_pfrac( slong l, fq_nmod_mpoly_t t, const slong * degs, fq_nmod_mpoly_pfrac_t I, const fq_nmod_mpoly_ctx_t ctx) { slong i, j, k; int success; fq_nmod_mpoly_struct * deltas = I->deltas + l*I->r; fq_nmod_mpoly_struct * newdeltas = I->deltas + (l - 1)*I->r; fq_nmod_mpoly_struct * q = I->q + l; fq_nmod_mpoly_struct * qt = I->qt + l; fq_nmod_mpoly_struct * newt = I->newt + l; fq_nmod_mpolyv_struct * delta_coeffs = I->delta_coeffs + l*I->r; fq_nmod_mpoly_geobucket_struct * G = I->G + l; FLINT_ASSERT(l >= 0); if (!fq_nmod_mpoly_repack_bits_inplace(t, I->bits, ctx)) return -1; if (l < 1) { for (i = 0; i < I->r; i++) { fq_nmod_mpoly_divrem(I->Q, I->R, t, I->dbetas_mvar + i, ctx); fq_nmod_mpoly_mul(I->T, I->R, I->inv_prod_dbetas_mvar + i, ctx); fq_nmod_mpoly_divrem(I->Q, deltas + i, I->T, I->dbetas_mvar + i, ctx); } return 1; } for (i = 0; i < I->r; i++) delta_coeffs[i].length = 0; for (k = 0; k <= degs[l]; k++) { fq_nmod_mpoly_divrem(q, newt, t, I->xalpha + l, ctx); fq_nmod_mpoly_swap(t, q, ctx); fq_nmod_mpoly_geobucket_set(G, newt, ctx); for (j = 0; j < k; j++) for (i = 0; i < I->r; i++) { if (j >= delta_coeffs[i].length) continue; if (k - j >= I->prod_mbetas_coeffs[l*I->r + i].length) continue; fq_nmod_mpoly_mul(qt, delta_coeffs[i].coeffs + j, I->prod_mbetas_coeffs[l*I->r + i].coeffs + k - j, ctx); fq_nmod_mpoly_geobucket_sub(G, qt, ctx); } fq_nmod_mpoly_geobucket_empty(newt, G, ctx); if (fq_nmod_mpoly_is_zero(newt, ctx)) continue; success = fq_nmod_mpoly_pfrac(l - 1, newt, degs, I, ctx); if (success < 1) return success; for (i = 0; i < I->r; i++) { if (fq_nmod_mpoly_is_zero(newdeltas + i, ctx)) continue; if (k + I->prod_mbetas_coeffs[l*I->r + i].length - 1 > degs[l]) return 0; fq_nmod_mpolyv_set_coeff(delta_coeffs + i, k, newdeltas + i, ctx); } } for (i = 0; i < I->r; i++) fq_nmod_mpoly_from_mpolyv(deltas + i, I->bits, delta_coeffs + i, I->xalpha + l, ctx); return 1; } flint-3.1.3/src/fq_nmod_mpoly_factor/mpolyv.c000066400000000000000000000076451461254215100213310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpolyv_clear(fq_nmod_mpolyv_t A, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (A->alloc > 0) { for (i = 0; i < A->alloc; i++) fq_nmod_mpoly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } } void fq_nmod_mpolyv_fit_length( fq_nmod_mpolyv_t A, slong length, const fq_nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length <= old_alloc) return; if (old_alloc > 0) { A->coeffs = (fq_nmod_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_nmod_mpoly_struct)); } else { A->coeffs = (fq_nmod_mpoly_struct *) flint_malloc( new_alloc*sizeof(fq_nmod_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) fq_nmod_mpoly_init(A->coeffs + i, ctx); A->alloc = new_alloc; } void fq_nmod_mpolyv_set_coeff( fq_nmod_mpolyv_t A, slong i, fq_nmod_mpoly_t c, /* clobbered */ const fq_nmod_mpoly_ctx_t ctx) { slong j; FLINT_ASSERT(!fq_nmod_mpoly_is_zero(c, ctx)); fq_nmod_mpolyv_fit_length(A, i + 1, ctx); for (j = A->length; j < i; j++) fq_nmod_mpoly_zero(A->coeffs + j, ctx); fq_nmod_mpoly_swap(A->coeffs + i, c, ctx); A->length = FLINT_MAX(A->length, i + 1); } void fq_nmod_mpoly_to_mpolyv( fq_nmod_mpolyv_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_t xalpha, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_mpoly_t Q, T; fq_nmod_mpoly_init(Q, ctx); fq_nmod_mpoly_init(T, ctx); fq_nmod_mpolyv_fit_length(A, 8, ctx); fq_nmod_mpoly_divrem(Q, A->coeffs + 0, B, xalpha, ctx); A->length = 1; while (!fq_nmod_mpoly_is_zero(Q, ctx)) { fq_nmod_mpolyv_fit_length(A, A->length + 1, ctx); fq_nmod_mpoly_divrem(T, A->coeffs + A->length, Q, xalpha, ctx); fq_nmod_mpoly_swap(Q, T, ctx); A->length++; } while (A->length > 0 && fq_nmod_mpoly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; fq_nmod_mpoly_clear(Q, ctx); fq_nmod_mpoly_clear(T, ctx); } void fq_nmod_mpoly_from_mpolyv( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpolyv_t B, const fq_nmod_mpoly_t xalpha, const fq_nmod_mpoly_ctx_t ctx) { slong i; fq_nmod_mpoly_t T; fq_nmod_mpoly_init(T, ctx); fq_nmod_mpoly_zero(A, ctx); for (i = B->length - 1; i >= 0; i--) { fq_nmod_mpoly_mul(T, A, xalpha, ctx); fq_nmod_mpoly_add(A, T, B->coeffs + i, ctx); } fq_nmod_mpoly_clear(T, ctx); fq_nmod_mpoly_repack_bits_inplace(A, Abits, ctx); } int _fq_nmod_mpoly_vec_content_mpoly( fq_nmod_mpoly_t g, const fq_nmod_mpoly_struct * A, slong Alen, const fq_nmod_mpoly_ctx_t ctx) { slong i; int success; fq_nmod_mpoly_zero(g, ctx); for (i = 0; i < Alen; i++) { success = fq_nmod_mpoly_gcd(g, g, A + i, ctx); if (!success) return 0; } return 1; } void _fq_nmod_mpoly_vec_divexact_mpoly( fq_nmod_mpoly_struct * A, slong Alen, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) fq_nmod_mpoly_divexact(A + i, A + i, c, ctx); } void _fq_nmod_mpoly_vec_mul_mpoly( fq_nmod_mpoly_struct * A, slong Alen, const fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) fq_nmod_mpoly_mul(A + i, A + i, c, ctx); } flint-3.1.3/src/fq_nmod_mpoly_factor/n_bpoly_fq.c000066400000000000000000000245721461254215100221310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" void n_fq_poly_mullow_( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, slong order, const fq_nmod_ctx_t ctx, n_poly_stack_t St); void n_fq_bpoly_add( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const fq_nmod_ctx_t ctx) { slong i; slong Alen = FLINT_MAX(B->length, C->length); n_bpoly_fit_length(A, Alen); for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) { n_fq_poly_add(A->coeffs + i, B->coeffs + i, C->coeffs + i, ctx); } else { n_fq_poly_set(A->coeffs + i, B->coeffs + i, ctx); } } else { FLINT_ASSERT(i < C->length); n_fq_poly_set(A->coeffs + i, C->coeffs + i, ctx); } } A->length = Alen; n_bpoly_normalise(A); } void n_fq_bpoly_sub( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const fq_nmod_ctx_t ctx) { slong i; slong Alen = FLINT_MAX(B->length, C->length); n_bpoly_fit_length(A, Alen); for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) { n_fq_poly_sub(A->coeffs + i, B->coeffs + i, C->coeffs + i, ctx); } else { n_fq_poly_set(A->coeffs + i, B->coeffs + i, ctx); } } else { FLINT_ASSERT(i < C->length); n_fq_poly_neg(A->coeffs + i, C->coeffs + i, ctx); } } A->length = Alen; n_bpoly_normalise(A); } void n_fq_bpoly_mul( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const fq_nmod_ctx_t ctx) { slong i, j; n_poly_struct * t; n_poly_stack_t St; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); if (B->length < 1 || C->length < 1) { A->length = 0; return; } n_poly_stack_init(St); n_poly_stack_fit_request(St, 1); t = n_poly_stack_take_top(St); n_bpoly_fit_length(A, B->length + C->length - 1); for (i = 0; i < B->length + C->length - 1; i++) n_poly_zero(A->coeffs + i); for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { n_fq_poly_mul_(t, B->coeffs + i, C->coeffs + j, ctx, St); n_fq_poly_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } A->length = B->length + C->length - 1; n_bpoly_normalise(A); n_poly_stack_give_back(St, 1); n_poly_stack_clear(St); } void n_fq_bpoly_mul_series( n_fq_bpoly_t A, const n_fq_bpoly_t B, const n_fq_bpoly_t C, slong order, const fq_nmod_ctx_t ctx) { slong i, j; n_poly_struct * t; n_poly_stack_t St; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_poly_stack_init(St); n_poly_stack_fit_request(St, 1); t = n_poly_stack_take_top(St); n_fq_bpoly_fit_length(A, B->length + C->length - 1); for (i = 0; i < B->length + C->length - 1; i++) n_fq_poly_zero(A->coeffs + i); for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { n_fq_poly_mullow_(t, B->coeffs + i, C->coeffs + j, order, ctx, St); n_fq_poly_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } A->length = B->length + C->length - 1; n_bpoly_normalise(A); n_poly_stack_give_back(St, 1); n_poly_stack_clear(St); } /* division in (Fq[y]/y^order)[x] inputs need not be reduced mod y^order */ void n_fq_bpoly_divrem_series( n_bpoly_t Q, n_bpoly_t R, const n_bpoly_t A, const n_bpoly_t B, slong order, const fq_nmod_ctx_t ctx) { slong i, qoff; n_poly_struct * q, * t, * binv; n_poly_stack_t St; FLINT_ASSERT(R != A); FLINT_ASSERT(R != B); FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); n_poly_stack_init(St); n_poly_stack_fit_request(St, 3); q = n_poly_stack_take_top(St); t = n_poly_stack_take_top(St); binv = n_poly_stack_take_top(St); n_fq_bpoly_set(R, A, ctx); for (i = 0; i < R->length; i++) n_fq_poly_truncate(R->coeffs + i, order, ctx); n_bpoly_normalise(R); n_fq_poly_inv_series(binv, B->coeffs + B->length - 1, order, ctx); Q->length = 0; while (R->length >= B->length) { n_fq_poly_mullow_(q, R->coeffs + R->length - 1, binv, order, ctx, St); for (i = 0; i < B->length; i++) { n_fq_poly_mullow_(t, B->coeffs + i, q, order, ctx, St); n_fq_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { n_bpoly_fit_length(Q, qoff + 1); for (i = Q->length; i <= qoff; i++) n_poly_zero(Q->coeffs + i); Q->length = qoff + 1; } n_fq_poly_set(Q->coeffs + qoff, q, ctx); FLINT_ASSERT(n_poly_is_zero(R->coeffs + R->length - 1)); n_bpoly_normalise(R); } n_poly_stack_give_back(St, 3); n_poly_stack_clear(St); } int n_fq_bpoly_divides( n_bpoly_t Q, const n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx) { slong i, qoff; int divides; n_fq_poly_struct * q, * t; n_fq_bpoly_t R; n_poly_stack_t St; FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); n_poly_stack_init(St); n_poly_stack_fit_request(St, 2); q = n_poly_stack_take_top(St); t = n_poly_stack_take_top(St); n_bpoly_init(R); n_fq_bpoly_set(R, A, ctx); Q->length = 0; while (R->length >= B->length) { n_fq_poly_divrem_(q, t, R->coeffs + R->length - 1, B->coeffs + B->length - 1, ctx, St); if (!n_poly_is_zero(t)) { divides = 0; goto cleanup; } for (i = 0; i < B->length; i++) { n_fq_poly_mul_(t, B->coeffs + i, q, ctx, St); n_fq_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { n_bpoly_fit_length(Q, qoff + 1); for (i = Q->length; i <= qoff; i++) n_poly_zero(Q->coeffs + i); Q->length = qoff + 1; } n_fq_poly_set(Q->coeffs + qoff, q, ctx); FLINT_ASSERT(n_fq_poly_is_zero(R->coeffs + R->length - 1)); n_bpoly_normalise(R); } divides = (R->length == 0); cleanup: n_poly_stack_give_back(St, 2); n_poly_stack_clear(St); n_bpoly_clear(R); return divides; } void n_fq_bpoly_make_primitive( n_poly_t g, n_bpoly_t A, const fq_nmod_ctx_t ctx) { slong Alen = A->length; slong i; n_poly_t q, r; n_poly_init(q); n_poly_init(r); n_poly_zero(g); for (i = 0; i < Alen; i++) { n_fq_poly_gcd(q, g, A->coeffs + i, ctx); n_poly_swap(g, q); } for (i = 0; i < Alen; i++) { n_fq_poly_divrem(q, r, A->coeffs + i, g, ctx); n_fq_poly_set(A->coeffs + i, q, ctx); } /* make lc_xy(A) one */ if (Alen > 0) { slong d = fq_nmod_ctx_degree(ctx); n_poly_struct * Alead = A->coeffs + Alen - 1; mp_limb_t * c, * c_ = Alead->coeffs + d*(Alead->length - 1); c = FLINT_ARRAY_ALLOC(d, mp_limb_t); if (!_n_fq_is_one(c_, d)) { n_fq_poly_scalar_mul_n_fq(g, g, c_, ctx); n_fq_inv(c, c_, ctx); for (i = 0; i < Alen; i++) n_fq_poly_scalar_mul_n_fq(A->coeffs + i, A->coeffs + i, c, ctx); } flint_free(c); } n_poly_clear(q); n_poly_clear(r); } void fq_nmod_mpoly_get_n_fq_bpoly( n_bpoly_t A, const fq_nmod_mpoly_t B, slong varx, slong vary, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong j; slong NB; ulong Bexpx, Bexpy; slong Boffx, Bshiftx, Boffy, Bshifty; ulong mask; FLINT_ASSERT(B->bits <= FLINT_BITS); NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); n_bpoly_zero(A); for (j = 0; j < B->length; j++) { Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask; Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask; n_fq_bpoly_set_coeff_n_fq(A, Bexpx, Bexpy, B->coeffs + d*j, ctx->fqctx); } } void fq_nmod_mpoly_set_n_fq_bpoly( fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong varx, slong vary, const fq_nmod_mpoly_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx->fqctx); slong n = ctx->minfo->nvars; slong i, j; slong NA; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); TMP_START; Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); for (i = 0; i < n; i++) Aexps[i] = 0; fq_nmod_mpoly_fit_length_reset_bits(A, 4, Abits, ctx); NA = mpoly_words_per_exp(Abits, ctx->minfo); A->length = 0; for (i = 0; i < B->length; i++) { n_poly_struct * Bc = B->coeffs + i; for (j = 0; j < Bc->length; j++) { Aexps[varx] = i; Aexps[vary] = j; if (_n_fq_is_zero(Bc->coeffs + d*j, d)) continue; fq_nmod_mpoly_fit_length(A, A->length + 1, ctx); _n_fq_set(A->coeffs + d*A->length, Bc->coeffs + d*j, d); mpoly_set_monomial_ui(A->exps + NA*A->length, Aexps, Abits, ctx->minfo); A->length++; } } TMP_END; fq_nmod_mpoly_sort_terms(A, ctx); } flint-3.1.3/src/fq_nmod_mpoly_factor/n_bpoly_fq_factor_lgprime.c000066400000000000000000000603751461254215100252070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "nmod_mat.h" #include "fmpz_poly_factor.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" static void n_fq_bpoly_eval_sm_to_lg( fq_nmod_poly_t E, const n_bpoly_t B, const bad_fq_nmod_embed_t emb) { slong i; fq_nmod_poly_fit_length(E, B->length, emb->lgctx); for (i = 0; i < B->length; i++) bad_fq_nmod_embed_n_fq_sm_to_fq_nmod_lg(E->coeffs + i, B->coeffs + i, emb); E->length = B->length; _fq_nmod_poly_normalise(E, emb->lgctx); } static void n_fq_bpoly_set_n_fq_poly_gen0_lg_to_sm( n_bpoly_t A, const n_poly_t E, const bad_fq_nmod_embed_t emb) { slong lgd = fq_nmod_ctx_degree(emb->lgctx); slong i; n_bpoly_fit_length(A, E->length); for (i = 0; i < E->length; i++) bad_n_fq_embed_lg_to_sm(A->coeffs + i, E->coeffs + lgd*i, emb); A->length = E->length; n_bpoly_normalise(A); } static void n_fq_bpoly_make_monic_mod_poly( n_bpoly_t A, const n_bpoly_t B, const n_poly_t m, const fq_nmod_ctx_t ctx) { slong i; n_poly_t lcinv, t, g; FLINT_ASSERT(A != B); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(n_fq_bpoly_is_canonical(B, ctx)); n_poly_init(lcinv); n_poly_init(g); n_poly_init(t); n_fq_poly_xgcd(g, lcinv, t, B->coeffs + B->length - 1, m, ctx); FLINT_ASSERT(n_fq_poly_is_one(g, ctx)); n_bpoly_fit_length(A, B->length); for (i = 0; i < B->length; i++) n_fq_poly_mulmod(A->coeffs + i, B->coeffs + i, lcinv, m, ctx); A->length = B->length; n_bpoly_normalise(A); n_poly_clear(lcinv); n_poly_clear(t); n_poly_clear(g); } /* multiplication in (Fq[y]/m(y))[x], inputs need not be reduced */ static void n_fq_bpoly_mul_mod_poly( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const n_poly_t m, const fq_nmod_ctx_t ctx) { slong i, j; n_poly_t t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_poly_init(t); n_bpoly_fit_length(A, B->length + C->length - 1); for (i = 0; i < B->length + C->length - 1; i++) n_poly_zero(A->coeffs + i); for (i = 0; i < B->length; i++) for (j = 0; j < C->length; j++) { n_fq_poly_mul(t, B->coeffs + i, C->coeffs + j, ctx); n_fq_poly_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); n_fq_poly_rem(A->coeffs + i + j, A->coeffs + i + j, m, ctx); } A->length = B->length + C->length - 1; n_bpoly_normalise(A); n_poly_clear(t); } /* division in (Fq[y]/m(y))[x], inputs need not be reduced */ static void n_fq_bpoly_divrem_mod_poly( n_bpoly_t Q, n_bpoly_t R, const n_bpoly_t A, const n_bpoly_t B, const n_poly_t m, const fq_nmod_ctx_t ctx) { slong i, qoff; n_poly_t q, t, Binv; FLINT_ASSERT(R != A); FLINT_ASSERT(R != B); FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); n_poly_init(q); n_poly_init(t); n_poly_init(Binv); n_fq_bpoly_set(R, A, ctx); Q->length = 0; n_fq_poly_xgcd(q, Binv, t, B->coeffs + B->length - 1, m, ctx); FLINT_ASSERT(n_fq_poly_is_one(q, ctx)); while (R->length >= B->length) { n_fq_poly_mulmod(q, R->coeffs + R->length - 1, Binv, m, ctx); for (i = 0; i < B->length; i++) { n_fq_poly_mulmod(t, B->coeffs + i, q, m, ctx); n_fq_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { n_bpoly_fit_length(Q, qoff + 1); for (i = Q->length; i <= qoff; i++) n_poly_zero(Q->coeffs + i); Q->length = qoff + 1; } n_fq_poly_set(Q->coeffs + qoff, q, ctx); FLINT_ASSERT(n_poly_is_zero(R->coeffs + R->length - 1)); n_bpoly_normalise(R); } n_poly_clear(q); n_poly_clear(t); n_poly_clear(Binv); } static void _lattice( nmod_mat_t N, n_bpoly_struct * const * g, slong r, const n_poly_t lift_alpha_pow, slong * starts, const n_bpoly_t f, const fq_nmod_ctx_t ctx) { slong deg = fq_nmod_ctx_degree(ctx); slong i, j, k, l; n_bpoly_t Q, R, dg; n_bpoly_struct * ld; nmod_mat_t M, T1, T2; int nlimbs; mp_limb_t * trow; slong lift_order = lift_alpha_pow->length - 1; nlimbs = _nmod_vec_dot_bound_limbs(r, ctx->mod); trow = (mp_limb_t *) flint_malloc(r*sizeof(mp_limb_t)); n_bpoly_init(Q); n_bpoly_init(R); n_bpoly_init(dg); ld = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); for (i = 0; i < r; i++) n_bpoly_init(ld + i); /* init done */ for (i = 0; i < r; i++) { n_fq_bpoly_divrem_mod_poly(Q, R, f, g[i], lift_alpha_pow, ctx); FLINT_ASSERT(R->length == 0); n_fq_bpoly_derivative_gen0(R, g[i], ctx); n_fq_bpoly_mul_mod_poly(ld + i, Q, R, lift_alpha_pow, ctx); } for (k = 0; k + 1 < f->length; k++) { slong d = nmod_mat_nrows(N); if (d < 2) break; if (lift_order <= starts[k]) continue; nmod_mat_init(M, deg*(lift_order - starts[k]), d, ctx->modulus->mod.n); for (j = starts[k]; j < lift_order; j++) for (l = 0; l < deg; l++) { for (i = 0; i < r; i++) { if (k >= ld[i].length || j >= ld[i].coeffs[k].length) { trow[i] = 0; } else { trow[i] = ld[i].coeffs[k].coeffs[deg*j + l]; } } for (i = 0; i < d; i++) nmod_mat_entry(M, (j - starts[k])*deg + l, i) = _nmod_vec_dot(trow, N->rows[i], r, ctx->mod, nlimbs); } nmod_mat_init_nullspace_tr(T1, M); nmod_mat_init(T2, nmod_mat_nrows(T1), nmod_mat_ncols(N), ctx->mod.n); nmod_mat_mul(T2, T1, N); nmod_mat_swap(T2, N); nmod_mat_rref(N); nmod_mat_clear(M); nmod_mat_clear(T1); nmod_mat_clear(T2); } flint_free(trow); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(dg); for (i = 0; i < r; i++) n_bpoly_clear(ld + i); flint_free(ld); } static int _zassenhaus( slong limit, n_tpoly_t F, const n_poly_t final_alpha_pow, const nmod_mat_t N, n_bpoly_struct * const * loc_fac_org, slong r, const n_bpoly_t B, const fq_nmod_ctx_t ctx) { int success; n_bpoly_t Q, R, t1, t2; n_poly_t g; slong i, j, s, len, d = nmod_mat_nrows(N); slong * subset; n_bpoly_struct * loc_fac; n_bpoly_struct * f; n_bpoly_t B_copy; FLINT_ASSERT(nmod_mat_ncols(N) == r); n_poly_init(g); n_bpoly_init(Q); n_bpoly_init(R); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(B_copy); subset = FLINT_ARRAY_ALLOC(d, slong); loc_fac = FLINT_ARRAY_ALLOC(d, n_bpoly_struct); for (i = 0; i < d; i++) { subset[i] = i; n_bpoly_init(loc_fac + i); } for (i = 0; i < d; i++) { n_fq_bpoly_one(loc_fac + i, ctx); for (j = 0; j < r; j++) { if (nmod_mat_entry(N, i, j) == 0) continue; FLINT_ASSERT(nmod_mat_entry(N, i, j) == 1); n_fq_bpoly_mul_mod_poly(t1, loc_fac + i, loc_fac_org[j], final_alpha_pow, ctx); n_bpoly_swap(t1, loc_fac + i); } } f = (n_bpoly_struct *) B; len = d; for (s = 1; s <= len/2; s++) { if (s > limit) { success = 0; goto cleanup; } zassenhaus_subset_first(subset, len, s); while (1) { FLINT_ASSERT(f->length > 0); n_fq_bpoly_set_n_fq_poly_gen1(t1, f->coeffs + f->length - 1, ctx); for (i = 0; i < len; i++) { if (subset[i] >= 0) { n_fq_bpoly_mul_mod_poly(t2, t1, loc_fac + subset[i], final_alpha_pow, ctx); n_bpoly_swap(t1, t2); } } n_fq_bpoly_make_primitive(g, t1, ctx); if (n_fq_bpoly_divides(Q, f, t1, ctx)) { n_tpoly_fit_length(F, F->length + 1); n_bpoly_swap(F->coeffs + F->length, t1); F->length++; f = B_copy; n_bpoly_swap(f, Q); len -= s; if (!zassenhaus_subset_next_disjoint(subset, len + s)) break; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (f->length > 1) { n_tpoly_fit_length(F, F->length + 1); n_fq_bpoly_set(F->coeffs + F->length, f, ctx); F->length++; } else { FLINT_ASSERT(f->length == 1); FLINT_ASSERT(n_fq_poly_is_one(f->coeffs + 0, ctx)); } success = 1; cleanup: n_poly_clear(g); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(B_copy); for (i = 0; i < d; i++) n_bpoly_clear(loc_fac + i); flint_free(loc_fac); flint_free(subset); return success; } static void _hensel_build_tree( slong * link, n_bpoly_struct * v, n_bpoly_struct * w, const fq_nmod_poly_struct * local_facs, slong r, const bad_fq_nmod_embed_t emb) { slong i, j; n_poly_t d; n_poly_struct * V; n_poly_struct * W; V = FLINT_ARRAY_ALLOC(2*r - 2, n_poly_struct); W = FLINT_ARRAY_ALLOC(2*r - 2, n_poly_struct); n_poly_init(d); for (i = 0; i < 2*r - 2; i++) { n_poly_init(V + i); n_poly_init(W + i); } for (i = 0; i < r; i++) { n_fq_poly_set_fq_nmod_poly(V + i, local_facs + i, emb->lgctx); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp, mind; minp = j; mind = n_poly_degree(V + j); for (s = j + 1; s < i; s++) { if (n_poly_degree(V + s) < mind) { minp = s; mind = n_poly_degree(V + s); } } n_poly_swap(V + j, V + minp); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = n_poly_degree(V + j + 1); for (s = j + 2; s < i; s++) { if (n_poly_degree(V + s) < mind) { minp = s; mind = n_poly_degree(V + s); } } n_poly_swap(V + j + 1, V + minp); FLINT_SWAP(slong, link[j + 1], link[minp]); n_fq_poly_mul(V + i, V + j, V + j + 1, emb->lgctx); link[i] = j; } for (j = 0; j < 2*r - 2; j += 2) { n_fq_poly_xgcd(d, W + j, W + j + 1, V + j, V + j + 1, emb->lgctx); FLINT_ASSERT(n_fq_poly_is_one(d, emb->lgctx)); } for (j = 0; j < 2*r - 2; j++) { n_fq_bpoly_set_n_fq_poly_gen0_lg_to_sm(v + j, V + j, emb); n_fq_bpoly_set_n_fq_poly_gen0_lg_to_sm(w + j, W + j, emb); } n_poly_clear(d); for (i = 0; i < 2*r - 2; i++) { n_poly_clear(V + i); n_poly_clear(W + i); } flint_free(V); flint_free(W); } static void _hensel_lift_fac( n_bpoly_t G, n_bpoly_t H, const n_bpoly_t f, n_bpoly_t g, n_bpoly_t h, const n_bpoly_t a, const n_bpoly_t b, const n_poly_t p0, const n_poly_t p1, const fq_nmod_ctx_t ctx) { slong i; n_bpoly_t c, t1, t2, q, r; n_poly_t tq, tr; n_bpoly_init(c); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(q); n_bpoly_init(r); n_poly_init(tq); n_poly_init(tr); #if FLINT_WANT_ASSERT n_fq_bpoly_mul(t1, g, a, ctx); n_fq_bpoly_mul(t2, h, b, ctx); n_fq_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_fq_poly_neg(c->coeffs + i, c->coeffs + i, ctx); n_fq_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { n_fq_poly_divrem(tq, tr, c->coeffs + i, p0, ctx); FLINT_ASSERT(n_fq_poly_is_canonical(tr, ctx)); FLINT_ASSERT(n_poly_is_zero(tr)); } #endif n_fq_bpoly_mul(t1, g, h, ctx); n_fq_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { n_fq_poly_divrem(tq, tr, c->coeffs + i, p0, ctx); FLINT_ASSERT(n_fq_poly_is_canonical(tr, ctx)); FLINT_ASSERT(n_poly_is_zero(tr)); n_fq_poly_divrem(tr, c->coeffs + i, tq, p1, ctx); } n_fq_bpoly_mul_mod_poly(t1, c, b, p1, ctx); n_fq_bpoly_divrem_mod_poly(q, r, t1, g, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_mul(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < g->length; i++) n_fq_poly_divrem(tq, g->coeffs + i, g->coeffs + i, p0, ctx); n_fq_bpoly_add(t1, r, g, ctx); n_fq_bpoly_mul_mod_poly(t2, c, a, p1, ctx); n_fq_bpoly_divrem_mod_poly(q, r, t2, h, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_mul(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < h->length; i++) n_fq_poly_divrem(tq, h->coeffs + i, h->coeffs + i, p0, ctx); n_fq_bpoly_add(t2, r, h, ctx); n_bpoly_swap(G, t1); n_bpoly_swap(H, t2); #if FLINT_WANT_ASSERT { n_poly_t p01; n_poly_init(p01); n_fq_poly_mul(p01, p0, p1, ctx); n_fq_bpoly_mul(t1, G, H, ctx); n_fq_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { n_fq_poly_divrem(tq, tr, c->coeffs + i, p01, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); } n_poly_clear(p01); } #endif n_bpoly_clear(c); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(q); n_bpoly_clear(r); n_poly_clear(tq); n_poly_clear(tr); } static void _hensel_lift_inv( n_bpoly_t A, n_bpoly_t B, const n_bpoly_t G, const n_bpoly_t H, n_bpoly_t a, n_bpoly_t b, const n_poly_t p0, const n_poly_t p1, const fq_nmod_ctx_t ctx) { slong i; n_bpoly_t c, t1, t2, q, r; n_poly_t tq, tr; n_bpoly_init(c); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(q); n_bpoly_init(r); n_poly_init(tq); n_poly_init(tr); #if FLINT_WANT_ASSERT { n_fq_bpoly_mul(t1, G, A, ctx); n_fq_bpoly_mul(t2, H, B, ctx); n_fq_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_fq_poly_neg(c->coeffs + i, c->coeffs + i, ctx); n_fq_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { n_fq_poly_divrem(tq, tr, c->coeffs + i, p0, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); } } #endif for (i = 0; i < b->length; i++) n_fq_poly_divrem(tq, b->coeffs + i, b->coeffs + i, p0, ctx); for (i = 0; i < a->length; i++) n_fq_poly_divrem(tq, a->coeffs + i, a->coeffs + i, p0, ctx); n_fq_bpoly_mul(t1, G, a, ctx); n_fq_bpoly_mul(t2, H, b, ctx); n_fq_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_fq_poly_neg(c->coeffs + i, c->coeffs + i, ctx); n_fq_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { n_fq_poly_divrem(tq, tr, c->coeffs + i, p0, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); n_fq_poly_divrem(tr, c->coeffs + i, tq, p1, ctx); } n_fq_bpoly_mul_mod_poly(t1, c, b, p1, ctx); n_fq_bpoly_divrem_mod_poly(q, r, t1, G, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_mul(r->coeffs + i, r->coeffs + i, p0, ctx); n_fq_bpoly_add(t1, r, b, ctx); n_fq_bpoly_mul_mod_poly(t2, c, a, p1, ctx); n_fq_bpoly_divrem_mod_poly(q, r, t2, H, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_mul(r->coeffs + i, r->coeffs + i, p0, ctx); n_fq_bpoly_add(t2, r, a, ctx); n_bpoly_swap(t1, B); n_bpoly_swap(t2, A); #if FLINT_WANT_ASSERT { n_poly_t p01; n_poly_init(p01); n_fq_poly_mul(p01, p0, p1, ctx); n_fq_bpoly_mul(t1, G, A, ctx); n_fq_bpoly_mul(t2, H, B, ctx); n_fq_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_fq_poly_neg(c->coeffs + i, c->coeffs + i, ctx); n_fq_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { n_fq_poly_divrem(tq, tr, c->coeffs + i, p01, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); } n_poly_clear(p01); } #endif n_bpoly_clear(c); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(q); n_bpoly_clear(r); n_poly_clear(tq); n_poly_clear(tr); } static void _hensel_lift_tree( int opt, slong * link, n_bpoly_struct * v, n_bpoly_struct * w, const n_bpoly_t f, slong j, const n_poly_t p0, const n_poly_t p1, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(p1->length <= p0->length); if (j < 0) return; if (opt >= 0) _hensel_lift_fac(v + j, v + j + 1, f, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); if (opt <= 0) _hensel_lift_inv(w + j, w + j + 1, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j, link[j], p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j + 1, link[j + 1], p0, p1, ctx); } int n_fq_bpoly_factor_lgprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, const fq_nmod_ctx_t ctx, flint_rand_t state) { int success; slong i, r, edeg; slong Blenx = B->length; slong Bleny; slong final_pow, curr_lift_pow, prev_lift_pow, next_lift_pow; slong * starts; fq_nmod_poly_t Beval; fq_nmod_poly_factor_t local_fac; fq_nmod_t Blc; n_bpoly_t monicB; nmod_mat_t N; slong * link; n_bpoly_struct * v, * w, ** lift_fac; n_tpoly_t tmp; slong e[FLINT_BITS]; slong old_nrows; slong zas_limit; n_poly_t final_alpha_pow, curr_alpha_pow, prev_alpha_pow, next_alpha_pow; n_poly_t alpha, p1; bad_fq_nmod_mpoly_embed_chooser_t embc; bad_fq_nmod_embed_struct * cur_emb; fq_nmod_mpoly_ctx_t ectx_mock, ctx_mock; FLINT_ASSERT(Blenx > 1); /* TODO remove mpoly_ctx_t from bad_fq_nmod_mpoly_embed_chooser interface */ mpoly_ctx_init(ctx_mock->minfo, 2, ORD_LEX); *ctx_mock->fqctx = *ctx; cur_emb = bad_fq_nmod_mpoly_embed_chooser_init(embc, ectx_mock, ctx_mock, state); n_poly_init(final_alpha_pow); n_poly_init(curr_alpha_pow); n_poly_init(prev_alpha_pow); n_poly_init(next_alpha_pow); n_poly_init(p1); n_poly_init(alpha); n_bpoly_init(monicB); n_tpoly_init(tmp); fq_nmod_poly_init(Beval, ectx_mock->fqctx); fq_nmod_poly_factor_init(local_fac, ectx_mock->fqctx); fq_nmod_init(Blc, ectx_mock->fqctx); nmod_mat_init(N, 0, 0, ctx->mod.n); starts = (slong *) flint_malloc(Blenx*sizeof(slong)); link = (slong *) flint_malloc(sizeof(slong)); lift_fac = FLINT_ARRAY_ALLOC(1, n_bpoly_struct *); /* init done */ n_fq_poly_set_fq_nmod_poly(alpha, cur_emb->h, ctx); edeg = cur_emb->h->length - 1; n_fq_bpoly_make_primitive(c, B, ctx); /* deg_y(B) + 1 */ Bleny = 0; for (i = 0; i < B->length; i++) Bleny = FLINT_MAX(Bleny, (B->coeffs + i)->length); /* CLD bounds */ for (i = 0; i < Blenx; i++) starts[i] = Bleny; goto got_alpha; next_alpha: cur_emb = bad_fq_nmod_mpoly_embed_chooser_next(embc, ectx_mock, ctx_mock, state); if (cur_emb == NULL) { /* ran out of primes */ success = 0; goto cleanup; } n_fq_poly_set_fq_nmod_poly(alpha, cur_emb->h, ctx); edeg = cur_emb->h->length - 1; got_alpha: n_fq_bpoly_eval_sm_to_lg(Beval, B, cur_emb); /* if killed leading coeff, get new alpha */ if (Beval->length != Blenx) goto next_alpha; fq_nmod_poly_factor(local_fac, Blc, Beval, ectx_mock->fqctx); r = local_fac->num; /* if multiple factors, get new alpha */ for (i = 0; i < r; i++) { if (local_fac->exp[i] != 1) goto next_alpha; } /* if one factor, A is irreducible */ if (r < 2) { n_tpoly_fit_length(F, 1); n_bpoly_swap(F->coeffs + 0, B); F->length = 1; success = 1; goto cleanup; } for (i = 0; i < r; i++) { FLINT_ASSERT(local_fac->poly[i].length > 1); FLINT_ASSERT(fq_nmod_is_one(local_fac->poly[i].coeffs + local_fac->poly[i].length - 1, ectx_mock->fqctx)); } /* precision for constructing true factors */ final_pow = (Bleny + edeg - 1)/edeg; n_fq_poly_pow(final_alpha_pow, alpha, final_pow, ctx); nmod_mat_clear(N); nmod_mat_init(N, r, r, ctx->mod.n); for (i = 0; i < r; i++) nmod_mat_entry(N, i, i) = 1; link = (slong *) flint_realloc(link, (2*r - 2)*sizeof(slong)); lift_fac = (n_bpoly_struct **) flint_realloc(lift_fac, r*sizeof(n_bpoly_struct *)); n_tpoly_fit_length(tmp, 2*(2*r - 2)); v = tmp->coeffs + 0; w = tmp->coeffs + (2*r - 2); curr_lift_pow = final_pow + r; n_fq_poly_pow(curr_alpha_pow, alpha, curr_lift_pow, ctx); n_fq_bpoly_make_monic_mod_poly(monicB, B, curr_alpha_pow, ctx); _hensel_build_tree(link, v, w, local_fac->poly, r, cur_emb); for (i = 0; i < 2*r - 2; i++) if (-link[i] - 1 >= 0) lift_fac[-link[i] - 1] = v + i; FLINT_ASSERT(curr_lift_pow > 1); for (i = 0, e[i] = curr_lift_pow; e[i] > 1; i++) e[i+1] = (e[i] + 1) / 2; for (i--; i > 0; i--) { n_fq_poly_pow(prev_alpha_pow, alpha, e[i+1], ctx); n_fq_poly_pow(p1, alpha, e[i]-e[i+1], ctx); _hensel_lift_tree(0, link, v, w, monicB, 2*r-4, prev_alpha_pow, p1, ctx); } prev_lift_pow = e[1]; n_fq_poly_pow(prev_alpha_pow, alpha, prev_lift_pow, ctx); n_fq_poly_pow(p1, alpha, curr_lift_pow - prev_lift_pow, ctx); _hensel_lift_tree(1, link, v, w, monicB, 2*r-4, prev_alpha_pow, p1, ctx); zas_limit = 1; try_zas: F->length = 0; success = _zassenhaus(zas_limit, F, final_alpha_pow, N, lift_fac, r, B, ctx); if (success) goto cleanup; zas_limit = 2; more: old_nrows = nmod_mat_nrows(N); _lattice(N, lift_fac, r, curr_alpha_pow, starts, B, ctx); if (nmod_mat_nrows(N) < old_nrows && nmod_mat_is_reduced(N)) goto try_zas; next_lift_pow = curr_lift_pow + r; next_lift_pow = FLINT_MIN(next_lift_pow, 2*curr_lift_pow); n_fq_poly_pow(p1, alpha, curr_lift_pow - prev_lift_pow, ctx); _hensel_lift_tree(-1, link, v, w, monicB, 2*r-4, prev_alpha_pow, p1, ctx); n_fq_poly_pow(p1, alpha, next_lift_pow - curr_lift_pow, ctx); n_fq_poly_mul(next_alpha_pow, next_alpha_pow, p1, ctx); n_fq_bpoly_make_monic_mod_poly(monicB, B, next_alpha_pow, ctx); _hensel_lift_tree(0, link, v, w, monicB, 2*r-4, curr_alpha_pow, p1, ctx); prev_lift_pow = curr_lift_pow; curr_lift_pow = next_lift_pow; n_poly_swap(prev_alpha_pow, curr_alpha_pow); n_poly_swap(curr_alpha_pow, next_alpha_pow); goto more; cleanup: flint_free(starts); flint_free(link); flint_free(lift_fac); nmod_mat_clear(N); n_poly_clear(final_alpha_pow); n_poly_clear(curr_alpha_pow); n_poly_clear(prev_alpha_pow); n_poly_clear(next_alpha_pow); n_poly_clear(p1); n_poly_clear(alpha); n_bpoly_clear(monicB); n_tpoly_clear(tmp); fq_nmod_poly_clear(Beval, ctx); fq_nmod_poly_factor_clear(local_fac, ctx); fq_nmod_clear(Blc, ctx); bad_fq_nmod_mpoly_embed_chooser_clear(embc, ectx_mock, ctx_mock, state); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/n_bpoly_fq_factor_smprime.c000066400000000000000000001127501461254215100252170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "nmod_mat.h" #include "fmpz_poly_factor.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" #include "fq_nmod_mpoly_factor.h" #define FLINT_TMP_ARRAY_ALLOC(n, T) (T *) TMP_ALLOC(n*sizeof(T)) #define n_fq_bpoly_swap n_bpoly_swap static void n_fq_bpoly_eval_gen1( fq_nmod_poly_t E, const n_bpoly_t A, const fq_nmod_t alpha, const fq_nmod_ctx_t ctx) { slong i; fq_nmod_t t; fq_nmod_poly_t s; fq_nmod_init(t, ctx); fq_nmod_poly_init(s, ctx); fq_nmod_poly_zero(E, ctx); for (i = A->length - 1; i >= 0; i--) { n_fq_poly_get_fq_nmod_poly(s, A->coeffs + i, ctx); fq_nmod_poly_evaluate_fq_nmod(t, s, alpha, ctx); fq_nmod_poly_set_coeff(E, i, t, ctx); } fq_nmod_clear(t, ctx); fq_nmod_poly_clear(s, ctx); } static void n_fq_bpoly_make_monic_series( n_bpoly_t A, const n_bpoly_t B, slong order, const fq_nmod_ctx_t ctx) { slong i; n_poly_t lcinv; FLINT_ASSERT(A != B); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(n_fq_bpoly_is_canonical(B, ctx)); n_poly_init(lcinv); n_fq_poly_inv_series(lcinv, B->coeffs + B->length - 1, order, ctx); n_bpoly_fit_length(A, B->length); for (i = 0; i < B->length; i++) n_fq_poly_mullow(A->coeffs + i, B->coeffs + i, lcinv, order, ctx); A->length = B->length; n_bpoly_normalise(A); n_poly_clear(lcinv); } static void n_fq_bpoly_reverse_gens( n_fq_bpoly_t a, const n_fq_bpoly_t b, const fq_nmod_ctx_t ctx) { slong i, j, d = fq_nmod_ctx_degree(ctx); n_fq_bpoly_zero(a); for (i = 0; i < b->length; i++) { const n_fq_poly_struct * bi = b->coeffs + i; for (j = 0; j < bi->length; j++) { n_fq_bpoly_set_coeff_n_fq(a, j, i, bi->coeffs + d*j, ctx); } } } /****************** lifting **************************************************/ static void _hensel_build_tree( slong * link, n_fq_bpoly_struct * v, n_fq_bpoly_struct * w, const fq_nmod_poly_struct * local_facs, slong r, const fq_nmod_ctx_t ctx) { slong i, j; n_fq_poly_t d; n_fq_poly_struct * V; n_fq_poly_struct * W; V = FLINT_ARRAY_ALLOC(2*r - 2, n_fq_poly_struct); W = FLINT_ARRAY_ALLOC(2*r - 2, n_fq_poly_struct); n_poly_init(d); for (i = 0; i < 2*r - 2; i++) { n_poly_init(V + i); n_poly_init(W + i); } for (i = 0; i < r; i++) { n_fq_poly_set_fq_nmod_poly(V + i, local_facs + i, ctx); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp, mind; minp = j; mind = n_poly_degree(V + j); for (s = j + 1; s < i; s++) { if (n_poly_degree(V + s) < mind) { minp = s; mind = n_poly_degree(V + s); } } n_poly_swap(V + j, V + minp); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = n_poly_degree(V + j + 1); for (s = j + 2; s < i; s++) { if (n_poly_degree(V + s) < mind) { minp = s; mind = n_poly_degree(V + s); } } n_poly_swap(V + j + 1, V + minp); FLINT_SWAP(slong, link[j + 1], link[minp]); n_fq_poly_mul(V + i, V + j, V + j + 1, ctx); link[i] = j; } for (j = 0; j < 2*r - 2; j += 2) { n_fq_poly_xgcd(d, W + j, W + j + 1, V + j, V + j + 1, ctx); FLINT_ASSERT(n_fq_poly_is_one(d, ctx)); } for (j = 0; j < 2*r - 2; j++) { n_fq_bpoly_set_n_fq_poly_gen0(v + j, V + j, ctx); n_fq_bpoly_set_n_fq_poly_gen0(w + j, W + j, ctx); FLINT_ASSERT(n_fq_bpoly_is_canonical(v + j, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(w + j, ctx)); } n_poly_clear(d); for (i = 0; i < 2*r - 2; i++) { n_poly_clear(V + i); n_poly_clear(W + i); } flint_free(V); flint_free(W); } static void _hensel_lift_fac( n_fq_bpoly_t G, n_fq_bpoly_t H, const n_fq_bpoly_t f, n_fq_bpoly_t g, n_fq_bpoly_t h, const n_bpoly_t a, const n_bpoly_t b, slong p0, slong p1, const fq_nmod_ctx_t ctx) { slong i; n_bpoly_t c, t1, t2, q, r; FLINT_ASSERT(n_fq_bpoly_is_canonical(G, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(H, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(f, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(g, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(h, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(a, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(b, ctx)); n_fq_bpoly_init(c); n_fq_bpoly_init(t1); n_fq_bpoly_init(t2); n_fq_bpoly_init(q); n_fq_bpoly_init(r); n_fq_bpoly_mul(t1, g, h, ctx); n_fq_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { #if FLINT_WANT_ASSERT { slong j, d = fq_nmod_ctx_degree(ctx); for (j = 0; j < FLINT_MIN(p0, c->coeffs[i].length); j++) FLINT_ASSERT(_n_fq_is_zero(c->coeffs[i].coeffs + d*j, d)); } #endif n_fq_poly_shift_right(c->coeffs + i, c->coeffs + i, p0, ctx); n_fq_poly_truncate(c->coeffs + i, p1, ctx); } n_fq_bpoly_normalise(c); n_fq_bpoly_mul_series(t1, c, b, p1, ctx); n_fq_bpoly_divrem_series(q, r, t1, g, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < g->length; i++) n_fq_poly_truncate(g->coeffs + i, p0, ctx); n_fq_bpoly_add(t1, r, g, ctx); n_fq_bpoly_mul_series(t2, c, a, p1, ctx); n_fq_bpoly_divrem_series(q, r, t2, h, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < h->length; i++) n_fq_poly_truncate(h->coeffs + i, p0, ctx); n_fq_bpoly_add(t2, r, h, ctx); n_bpoly_swap(G, t1); n_bpoly_swap(H, t2); #if FLINT_WANT_ASSERT { slong j, d = fq_nmod_ctx_degree(ctx); n_fq_bpoly_mul(t1, G, H, ctx); n_fq_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) for (j = 0; j < FLINT_MIN(p0 + p1, c->coeffs[i].length); j++) FLINT_ASSERT(_n_fq_is_zero(c->coeffs[i].coeffs + d*j, d)); } #endif n_fq_bpoly_clear(c); n_fq_bpoly_clear(t1); n_fq_bpoly_clear(t2); n_fq_bpoly_clear(q); n_fq_bpoly_clear(r); FLINT_ASSERT(n_fq_bpoly_is_canonical(G, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(H, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(f, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(g, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(h, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(a, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(b, ctx)); } static void _hensel_lift_inv( n_bpoly_t A, n_bpoly_t B, const n_bpoly_t G, const n_bpoly_t H, n_bpoly_t a, n_bpoly_t b, slong p0, slong p1, const fq_nmod_ctx_t ctx) { slong i; n_bpoly_t c, t1, t2, q, r; FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(B, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(G, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(H, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(a, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(b, ctx)); n_fq_bpoly_init(c); n_fq_bpoly_init(t1); n_fq_bpoly_init(t2); n_fq_bpoly_init(q); n_fq_bpoly_init(r); for (i = 0; i < b->length; i++) n_fq_poly_truncate(b->coeffs + i, p0, ctx); for (i = 0; i < a->length; i++) n_fq_poly_truncate(a->coeffs + i, p0, ctx); n_fq_bpoly_mul(t1, G, a, ctx); n_fq_bpoly_mul(t2, H, b, ctx); n_fq_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_fq_poly_neg(c->coeffs + i, c->coeffs + i, ctx); n_fq_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { #if FLINT_WANT_ASSERT { slong j, d = fq_nmod_ctx_degree(ctx); for (j = 0; j < p0; j++) { FLINT_ASSERT(j >= c->coeffs[i].length || _n_fq_is_zero(c->coeffs[i].coeffs + d*j, d)); } } #endif n_fq_poly_shift_right(c->coeffs + i, c->coeffs + i, p0, ctx); n_fq_poly_truncate(c->coeffs + i, p1, ctx); } n_fq_bpoly_mul_series(t1, c, b, p1, ctx); n_fq_bpoly_divrem_series(q, r, t1, G, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); n_fq_bpoly_add(t1, r, b, ctx); n_fq_bpoly_mul_series(t2, c, a, p1, ctx); n_fq_bpoly_divrem_series(q, r, t2, H, p1, ctx); for (i = 0; i < r->length; i++) n_fq_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); n_fq_bpoly_add(t2, r, a, ctx); n_bpoly_swap(t1, B); n_bpoly_swap(t2, A); #if FLINT_WANT_ASSERT n_fq_bpoly_mul(t1, G, A, ctx); n_fq_bpoly_mul(t2, H, B, ctx); n_fq_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_fq_poly_neg(c->coeffs + i, c->coeffs + i, ctx); n_fq_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_fq_bpoly_normalise(c); { slong j, d = fq_nmod_ctx_degree(ctx); for (i = 0; i < c->length; i++) for (j = 0; j < p0 + p1; j++) { FLINT_ASSERT(j >= c->coeffs[i].length || _n_fq_is_zero(c->coeffs[i].coeffs + d*j, d)); } } #endif n_fq_bpoly_clear(c); n_fq_bpoly_clear(t1); n_fq_bpoly_clear(t2); n_fq_bpoly_clear(q); n_fq_bpoly_clear(r); FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(B, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(G, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(H, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(a, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(b, ctx)); } static void _hensel_lift_tree( int opt, slong * link, n_bpoly_struct * v, n_bpoly_struct * w, const n_bpoly_t f, slong j, slong p0, slong p1, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(p1 <= p0); if (j < 0) return; if (opt >= 0) _hensel_lift_fac(v + j, v + j + 1, f, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); if (opt <= 0) _hensel_lift_inv(w + j, w + j + 1, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j, link[j], p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j + 1, link[j + 1], p0, p1, ctx); } typedef struct { slong * link; n_fq_bpoly_struct ** lifted_fac; n_fq_tpoly_t tmp; n_fq_bpoly_t bmp; slong r; slong fac_lift_order; slong inv_lift_order; nmod_eval_interp_t E; int Eok; int use_linear; n_poly_stack_t St; } n_fq_bpoly_lift_struct; typedef n_fq_bpoly_lift_struct n_fq_bpoly_lift_t[1]; static void n_fq_bpoly_lift_init(n_fq_bpoly_lift_t L) { L->link = NULL; L->lifted_fac = NULL; n_tpoly_init(L->tmp); n_bpoly_init(L->bmp); L->r = 0; L->fac_lift_order = 0; L->inv_lift_order = 0; nmod_eval_interp_init(L->E); n_poly_stack_init(L->St); } static void n_fq_bpoly_lift_clear(n_fq_bpoly_lift_t L) { flint_free(L->link); flint_free(L->lifted_fac); n_tpoly_clear(L->tmp); n_bpoly_clear(L->bmp); nmod_eval_interp_clear(L->E); n_poly_stack_clear(L->St); } static void n_fq_bpoly_lift_start( n_fq_bpoly_lift_t L, fq_nmod_poly_struct * local_facs, slong r, const fq_nmod_ctx_t ctx) { slong i, k, degx; n_fq_bpoly_struct * A, * Bfinal, * U, * Ue, * Be, * B; n_fq_poly_struct * s, * Binv; n_fq_poly_struct * c, * t, * ce, * vk, * vek, * g1, * g2; degx = 0; for (i = 0; i < r; i++) degx += local_facs[i].length - 1; L->r = r; L->lifted_fac = (n_fq_bpoly_struct **) flint_realloc(L->lifted_fac, r*sizeof(n_fq_bpoly_struct *)); /* linear lifting has large memory requirements wrt r */ if (r < 20 + 5*FLINT_BIT_COUNT(degx)) L->use_linear = 1; else L->use_linear = 0; L->fac_lift_order = 1; L->inv_lift_order = 1; if (!L->use_linear) { n_fq_bpoly_struct * v, * w; L->link = (slong *) flint_realloc(L->link, (2*r - 2)*sizeof(slong)); n_tpoly_fit_length(L->tmp, 2*(2*r - 2)); v = L->tmp->coeffs + 0; w = L->tmp->coeffs + (2*r - 2); _hensel_build_tree(L->link, v, w, local_facs, r, ctx); for (i = 0; i < 2*r - 2; i++) if (-L->link[i] - 1 >= 0) L->lifted_fac[-L->link[i] - 1] = v + i; return; } n_tpoly_fit_length(L->tmp, 4*r + 1); A = L->tmp->coeffs; Bfinal = A + 1; U = Ue = Bfinal + r; B = U + r; Be = B + r; n_fq_bpoly_fit_length(A, 1); A->length = 1; n_fq_poly_one(A->coeffs + 0, ctx); for (k = 0; k < r; k++) { n_fq_bpoly_fit_length(B + k, 1); B[k].length = 1; n_fq_poly_set_fq_nmod_poly(B[k].coeffs + 0, local_facs + k, ctx); n_fq_poly_mul(A->coeffs + 0, A->coeffs + 0, B[k].coeffs + 0, ctx); L->lifted_fac[k] = Bfinal + k; n_fq_bpoly_reverse_gens(L->lifted_fac[k], B + k, ctx); } FLINT_ASSERT(degx == n_fq_poly_degree(A->coeffs + 0)); /* try evaluation when not too many local factors */ if (r < 10 + FLINT_BIT_COUNT(degx)) L->Eok = nmod_eval_interp_set_degree_modulus(L->E, degx, ctx->mod); else L->Eok = 0; n_bpoly_fit_length(L->bmp, 2*r + 7); s = L->bmp->coeffs; Binv = s + r; c = Binv + r; t = c + 1; ce = t + 1; vk = ce + 1; vek = vk + 1; g1 = vek + 1; g2 = g1 + 1; for (k = 0; k < r; k++) { /* s[k] = (prod_{i!=k} B[i].coeffs[0])^-1 (mod B[k].coeffs[0]) */ n_fq_poly_divrem_(t, g1, A->coeffs + 0, B[k].coeffs + 0, ctx, L->St); n_fq_poly_xgcd(g1, s + k, g2, t, B[k].coeffs + 0, ctx); if (!n_fq_poly_is_one(g1, ctx)) flint_throw(FLINT_IMPINV, "n_fq_bpoly_mod_lift_start: bad inverse"); /* set up mul (mod B[k].coeffs[0]) */ /* n_fq_poly_reverse(t, B[k].coeffs + 0, B[k].coeffs[0].length); n_fq_poly_inv_series(Binv[k], t, B[k].coeffs[0].length, ctx); */ if (L->Eok) { n_fq_bpoly_fit_length(Be + k, 1); nmod_eval_interp_from_coeffs_n_fq_poly(Be[k].coeffs + 0, B[k].coeffs + 0, L->E, ctx); /* Ue[0] is not used */ if (k > 0) { n_fq_bpoly_fit_length(Ue + k, 1); Ue[k].length = 1; n_fq_evals_zero(Ue[k].coeffs + 0); } } else { /* Ue[0] is not used */ if (k > 0) { n_fq_bpoly_fit_length(U + k, 1); U[k].length = 1; n_fq_poly_zero(U[k].coeffs + 0); } } } if (r > 2) { if (L->Eok) { slong len = nmod_eval_interp_eval_length(L->E); k = r - 2; n_fq_evals_mul(Ue[k].coeffs + 0, Be[k].coeffs + 0, Be[k + 1].coeffs + 0, len, ctx); for (k--; k > 0; k--) n_fq_evals_mul(Ue[k].coeffs + 0, Be[k].coeffs + 0, Ue[k + 1].coeffs + 0, len, ctx); } else { k = r - 2; n_fq_poly_mul_(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx, L->St); for (k--; k > 0; k--) n_fq_poly_mul_(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx, L->St); } } } static void n_fq_bpoly_lift_continue( n_fq_bpoly_lift_t L, const n_fq_bpoly_t monicA, slong order, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j, k; slong r = L->r; n_fq_bpoly_struct * A, * Bfinal, * U, * Ue, * Be, * B; n_fq_poly_struct * s, * Binv; n_fq_poly_struct * c, * t, * ce, * vk, * vek, * g1, * g2; if (order <= L->fac_lift_order) return; if (!L->use_linear) { n_fq_bpoly_struct * v = L->tmp->coeffs + 0; n_fq_bpoly_struct * w = L->tmp->coeffs + (2*r - 2); slong e[FLINT_BITS+1]; FLINT_ASSERT(1 <= L->inv_lift_order); FLINT_ASSERT(L->fac_lift_order <= 2*L->inv_lift_order); for (i = 0, e[i] = order; e[i] > L->fac_lift_order; i++) e[i+1] = (e[i] + 1)/2; e[i] = L->fac_lift_order; e[i+1] = L->inv_lift_order; if (e[i+1] < e[i]) _hensel_lift_tree(-1, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); for (i--; i > 0; i--) _hensel_lift_tree(0, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); _hensel_lift_tree(1, L->link, v, w, monicA, 2*r-4, e[1], e[0]-e[1], ctx); L->fac_lift_order = e[0]; L->inv_lift_order = e[1]; return; } A = L->tmp->coeffs; Bfinal = A + 1; U = Ue = Bfinal + r; B = U + r; Be = B + r; s = L->bmp->coeffs; Binv = s + r; c = Binv + r; t = c + 1; ce = t + 1; vk = ce + 1; vek = vk + 1; g1 = vek + 1; g2 = g1 + 1; /* tack on reversal of monicA */ for (i = 0; i < monicA->length; i++) { n_poly_struct * Bi = monicA->coeffs + i; j = FLINT_MIN(Bi->length, order); for (j--; j >= L->fac_lift_order; j--) n_fq_bpoly_set_coeff_n_fq(A, j, i, Bi->coeffs + d*j, ctx); } /* tack on zeros to the B[k] */ for (k = 0; k < r; k++) { n_fq_bpoly_fit_length(B + k, order); if (L->Eok) n_fq_bpoly_fit_length(Be + k, order); for (i = B[k].length; i < order; i++) { n_fq_poly_zero(B[k].coeffs + i); if (L->Eok) n_fq_evals_zero(Be[k].coeffs + i); } /* U[0] is not used, zero out both U and Ue */ if (k > 0) { n_bpoly_fit_length(U + k, order); for (i = U[k].length; i < order; i++) U[k].coeffs[i].length = 0; U[k].length = order; } } if (L->Eok && r > 2) { slong len = nmod_eval_interp_eval_length(L->E); for (j = L->fac_lift_order; j < order; j++) { k = r - 2; n_fq_evals_zero(Ue[k].coeffs + j); for (i = 0; i <= j; i++) n_fq_evals_addmul(Ue[k].coeffs + j, Be[k].coeffs + i, Be[k + 1].coeffs + j - i, len, ctx); for (k--; k > 0; k--) { n_fq_evals_zero(Ue[k].coeffs + j); for (i = 0; i <= j; i++) n_fq_evals_addmul(Ue[k].coeffs + j, Be[k].coeffs + i, Ue[k + 1].coeffs + j - i, len, ctx); } n_fq_evals_zero(ce); for (i = 0; i <= j; i++) n_fq_evals_addmul(ce, Be[0].coeffs + i, Ue[1].coeffs + j - i, len, ctx); nmod_eval_interp_to_coeffs_n_fq_poly(c, ce, L->E, ctx); if (j < A->length) n_fq_poly_sub(c, A->coeffs + j, c, ctx); else n_fq_poly_neg(c, c, ctx); if (n_poly_is_zero(c)) continue; for (k = r - 1; k >= 0; k--) { n_fq_poly_divrem_(g1, t, c, B[k].coeffs + 0, ctx, L->St); n_fq_poly_mul_(g2, s + k, t, ctx, L->St); n_fq_poly_divrem_(g1, vk, g2, B[k].coeffs + 0, ctx, L->St); nmod_eval_interp_from_coeffs_n_fq_poly(vek, vk, L->E, ctx); if (!n_fq_poly_is_zero(vk)) { n_fq_evals_add_inplace(Be[k].coeffs + j, vek, len, ctx); n_fq_poly_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_fq_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } /* correct the U's */ if (k > r - 2) { n_fq_poly_swap(ce, vek); } else if (k > 0) { n_fq_poly_struct * p; p = (k == r - 2) ? Be[k + 1].coeffs : Ue[k + 1].coeffs; n_fq_evals_fmma(ce, Be[k].coeffs + 0, ce, p, vek, len, ctx); n_fq_evals_add_inplace(Ue[k].coeffs + j, ce, len, ctx); } } } } else if (L->Eok) { slong len = nmod_eval_interp_eval_length(L->E); FLINT_ASSERT(r == 2); for (j = L->fac_lift_order; j < order; j++) { n_fq_evals_zero(ce); for (i = 0; i <= j; i++) n_fq_evals_addmul(ce, Be[0].coeffs + i, Be[1].coeffs + j - i, len, ctx); nmod_eval_interp_to_coeffs_n_fq_poly(c, ce, L->E, ctx); if (j < A->length) n_fq_poly_sub(c, A->coeffs + j, c, ctx); else n_fq_poly_neg(c, c, ctx); if (n_fq_poly_is_zero(c)) continue; for (k = 0; k < r; k++) { n_fq_poly_divrem(g1, t, c, B[k].coeffs + 0, ctx); n_fq_poly_mul(g2, s + k, t, ctx); n_fq_poly_divrem(g1, vk, g2, B[k].coeffs + 0, ctx); nmod_eval_interp_from_coeffs_n_fq_poly(vek, vk, L->E, ctx); if (!n_fq_poly_is_zero(vk)) { n_fq_evals_add_inplace(Be[k].coeffs + j, vek, len, ctx); n_fq_poly_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_fq_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } } } } else if (r > 2) { for (j = L->fac_lift_order; j < order; j++) { k = r - 2; n_fq_poly_zero(U[k].coeffs + j); for (i = FLINT_MIN(j, B[k].length - 1); i >= 0; i--) { n_fq_poly_mul_(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx, L->St); n_fq_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } for (k--; k > 0; k--) { n_poly_zero(U[k].coeffs + j); for (i = FLINT_MIN(j, B[k].length - 1); i >= 0; i--) { n_fq_poly_mul_(t, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx, L->St); n_fq_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } if (j < A->length) n_fq_poly_set(c, A->coeffs + j, ctx); else n_fq_poly_zero(c); for (i = FLINT_MIN(j, B[0].length - 1); i >= 0; i--) { n_fq_poly_mul_(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx, L->St); n_fq_poly_sub(c, c, t, ctx); } if (n_fq_poly_is_zero(c)) continue; for (k = r - 1; k >= 0; k--) { n_fq_poly_divrem_(g1, t, c, B[k].coeffs + 0, ctx, L->St); n_fq_poly_mul_(g2, s + k, t, ctx, L->St); n_fq_poly_divrem_(g1, vk, g2, B[k].coeffs + 0, ctx, L->St); if (!n_fq_poly_is_zero(vk)) { n_fq_poly_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_fq_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } /* correct the U's */ if (k > r - 2) { n_fq_poly_swap(ce, vk); } else if (k > 0) { n_fq_poly_struct * p; n_fq_poly_mul_(t, B[k].coeffs + 0, ce, ctx, L->St); p = (k == r - 2) ? B[k + 1].coeffs : U[k + 1].coeffs; n_fq_poly_mul_(ce, p, vk, ctx, L->St); n_fq_poly_add(ce, ce, t, ctx); n_fq_poly_add(U[k].coeffs + j, U[k].coeffs + j, ce, ctx); } } } } else { FLINT_ASSERT(r == 2); for (j = L->fac_lift_order; j < order; j++) { if (j < A->length) n_fq_poly_set(c, A->coeffs + j, ctx); else n_fq_poly_zero(c); for (i = FLINT_MIN(j, B[0].length - 1); i >= 0; i--) { n_fq_poly_mul_(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx, L->St); n_fq_poly_sub(c, c, t, ctx); } if (n_fq_poly_is_zero(c)) continue; for (k = 0; k < r; k++) { n_fq_poly_divrem_(g1, t, c, B[k].coeffs + 0, ctx, L->St); n_fq_poly_mul_(g2, s + k, t, ctx, L->St); n_fq_poly_divrem_(g1, vk, g2, B[k].coeffs + 0, ctx, L->St); if (!n_fq_poly_is_zero(vk)) { n_fq_poly_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_fq_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } } } } L->fac_lift_order = order; for (k = 0; k < r; k++) n_fq_bpoly_reverse_gens(Bfinal + k, B + k, ctx); #if FLINT_WANT_ASSERT { n_fq_bpoly_t t1, t2; n_fq_bpoly_init(t1); n_fq_bpoly_init(t2); n_fq_bpoly_set(t1, Bfinal + 0, ctx); for (k = 1; k < r; k++) { n_fq_bpoly_mul_series(t2, t1, Bfinal + k, order, ctx); n_fq_bpoly_swap(t1, t2); } n_fq_bpoly_sub(t2, monicA, t1, ctx); for (i = 0; i < t2->length; i++) { for (j = 0; j < FLINT_MIN(order, t2->coeffs[i].length); j++) { FLINT_ASSERT(_n_fq_is_zero(t2->coeffs[i].coeffs + d*j, d)); } } n_fq_bpoly_clear(t1); n_fq_bpoly_clear(t2); } #endif } /************* lattice reduction *********************************************/ /* The rows of N, if they are 0-1, correspond to combinations of the g that give factors of A. Compute {A/g[i]*g[i]'}_i and use the CLD bounds to try to make N smaller. */ static void _lattice( nmod_mat_t N, n_bpoly_struct * const * g, slong r, slong lift_order, slong * CLD, const n_bpoly_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j, k, l; n_fq_bpoly_t Q, R, dg; n_fq_bpoly_struct * ld; nmod_mat_t M, T1, T2; int nlimbs; mp_limb_t * trow; nlimbs = _nmod_vec_dot_bound_limbs(r, ctx->mod); trow = (mp_limb_t *) flint_malloc(r*sizeof(mp_limb_t)); n_fq_bpoly_init(Q); n_fq_bpoly_init(R); n_fq_bpoly_init(dg); ld = FLINT_ARRAY_ALLOC(r, n_fq_bpoly_struct); for (i = 0; i < r; i++) { n_fq_bpoly_init(ld + i); n_fq_bpoly_divrem_series(Q, R, A, g[i], lift_order, ctx); FLINT_ASSERT(R->length == 0); n_fq_bpoly_derivative_gen0(R, g[i], ctx); n_fq_bpoly_mul_series(ld + i, Q, R, lift_order, ctx); } for (k = 0; k + 1 < A->length; k++) { slong nrows = nmod_mat_nrows(N); if (lift_order <= CLD[k]) continue; nmod_mat_init(M, d*(lift_order - CLD[k]), nrows, ctx->modulus->mod.n); for (j = CLD[k]; j < lift_order; j++) for (l = 0; l < d; l++) { for (i = 0; i < r; i++) { if (k >= ld[i].length || j >= ld[i].coeffs[k].length) trow[i] = 0; else trow[i] = ld[i].coeffs[k].coeffs[d*j + l]; } for (i = 0; i < nrows; i++) nmod_mat_entry(M, (j - CLD[k])*d + l, i) = _nmod_vec_dot(trow, N->rows[i], r, ctx->mod, nlimbs); } nmod_mat_init_nullspace_tr(T1, M); nmod_mat_init(T2, nmod_mat_nrows(T1), nmod_mat_ncols(N), ctx->mod.n); nmod_mat_mul(T2, T1, N); nmod_mat_swap(T2, N); nmod_mat_rref(N); nmod_mat_clear(M); nmod_mat_clear(T1); nmod_mat_clear(T2); } flint_free(trow); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(dg); for (i = 0; i < r; i++) n_fq_bpoly_clear(ld + i); flint_free(ld); } /**************** recombination **********************************************/ /* First multiply the g[i] into the gprod[i] according the the rows of N. Then, run zassenhaus on the gprod[i] as factors of A. */ static int _zassenhaus( const zassenhaus_prune_t zas, slong limit, n_tpoly_t F, const fq_nmod_t malpha, const nmod_mat_t N, n_bpoly_struct * const * g, slong r, slong order, const n_bpoly_t A, const fq_nmod_ctx_t ctx) { slong total_deg; int success; n_fq_bpoly_t Q, R, t1, t2; n_fq_poly_t cont; slong i, j, k, len, nrows = nmod_mat_nrows(N); slong * subset; n_fq_bpoly_struct * gprod; n_fq_bpoly_struct * f; n_fq_bpoly_t A_copy; FLINT_ASSERT(nmod_mat_ncols(N) == r); n_fq_poly_init(cont); n_fq_bpoly_init(Q); n_fq_bpoly_init(R); n_fq_bpoly_init(t1); n_fq_bpoly_init(t2); n_fq_bpoly_init(A_copy); gprod = FLINT_ARRAY_ALLOC(nrows, n_fq_bpoly_struct); subset = FLINT_ARRAY_ALLOC(nrows, slong); for (i = 0; i < nrows; i++) { subset[i] = i; n_bpoly_init(gprod + i); n_fq_bpoly_one(gprod + i, ctx); for (j = 0; j < r; j++) { if (nmod_mat_entry(N, i, j) == 0) continue; FLINT_ASSERT(nmod_mat_entry(N, i, j) == 1); n_fq_bpoly_mul_series(t1, gprod + i, g[j], order, ctx); n_fq_bpoly_swap(t1, gprod + i); } } f = (n_fq_bpoly_struct *) A; len = nrows; for (k = 1; k <= len/2; k++) { if (k > limit) { success = 0; goto cleanup; } zassenhaus_subset_first(subset, len, k); while (1) { total_deg = 0; for (i = 0; i < len; i++) { if (subset[i] >= 0) total_deg += gprod[subset[i]].length - 1; } if (!zassenhaus_prune_degree_is_possible(zas, total_deg)) { if (!zassenhaus_subset_next(subset, len)) break; continue; } FLINT_ASSERT(f->length > 0); n_fq_bpoly_set_n_fq_poly_gen1(t1, f->coeffs + f->length - 1, ctx); for (i = 0; i < len; i++) { if (subset[i] >= 0) { n_fq_bpoly_mul_series(t2, t1, gprod + subset[i], order, ctx); n_fq_bpoly_swap(t1, t2); } } n_fq_bpoly_make_primitive(cont, t1, ctx); if (n_fq_bpoly_divides(Q, f, t1, ctx)) { n_fq_bpoly_taylor_shift_gen1_fq_nmod(t1, t1, malpha, ctx); n_tpoly_fit_length(F, F->length + 1); n_bpoly_swap(F->coeffs + F->length, t1); F->length++; f = A_copy; n_bpoly_swap(f, Q); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (f->length > 1) { n_tpoly_fit_length(F, F->length + 1); n_fq_bpoly_taylor_shift_gen1_fq_nmod(F->coeffs + F->length, f, malpha, ctx); F->length++; } else { FLINT_ASSERT(f->length == 1); FLINT_ASSERT(n_fq_poly_is_one(f->coeffs + 0, ctx)); } success = 1; cleanup: for (i = 0; i < nrows; i++) n_bpoly_clear(gprod + i); flint_free(gprod); flint_free(subset); n_poly_clear(cont); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(A_copy); return success; } /*****************************************************************************/ /* x = gen(0), y = gen(1). A is supposed to be squarefree wrt x. Put the content of A wrt x in c, and the factors in F. Return 1 for success, i.e. a good evaluation point y = alpha was found. If allow_shift is false, only y = 0 is tried. */ int n_fq_bpoly_factor_smprime( n_fq_poly_t c, /* poly in gen(1) */ n_fq_tpoly_t F, n_fq_bpoly_t A, /* clobbered */ int allow_shift, const fq_nmod_ctx_t ctx) { int success; slong i, r; slong Alenx, Aleny; slong final_order, lift_order; slong * CLD; fq_nmod_t alpha, Alc; fq_nmod_poly_t Aeval; fq_nmod_poly_factor_t local_fac; n_fq_bpoly_t monicA; nmod_mat_t N; slong old_nrows; slong zas_limit; zassenhaus_prune_t zas; n_fq_bpoly_lift_t L; n_fq_bpoly_make_primitive(c, A, ctx); Alenx = 1 + n_fq_bpoly_degree0(A); Aleny = 1 + n_fq_bpoly_degree1(A); FLINT_ASSERT(Alenx > 1); fq_nmod_init(alpha, ctx); fq_nmod_init(Alc, ctx); fq_nmod_poly_init(Aeval, ctx); fq_nmod_poly_factor_init(local_fac, ctx); n_fq_bpoly_init(monicA); nmod_mat_init(N, 0, 0, ctx->mod.n); CLD = FLINT_ARRAY_ALLOC(Alenx, slong); zassenhaus_prune_init(zas); n_fq_bpoly_lift_init(L); /* TODO: CLD bounds */ for (i = 0; i < Alenx; i++) CLD[i] = Aleny; zassenhaus_prune_set_degree(zas, Alenx - 1); fq_nmod_zero(alpha, ctx); goto got_alpha; next_alpha: if (!allow_shift || !fq_nmod_next(alpha, ctx)) { success = 0; goto cleanup; } got_alpha: n_fq_bpoly_eval_gen1(Aeval, A, alpha, ctx); /* if killed leading coeff, get new alpha */ if (Aeval->length != Alenx) goto next_alpha; /* note the constant term of Aeval can be zero */ fq_nmod_poly_factor(local_fac, Alc, Aeval, ctx); r = local_fac->num; zassenhaus_prune_start_add_factors(zas); for (i = 0; i < r; i++) zassenhaus_prune_add_factor(zas, local_fac->poly[i].length - 1, local_fac->exp[i]); zassenhaus_prune_end_add_factors(zas); /* check for irreducibility */ if ((r < 2 && local_fac->exp[0] == 1) || zassenhaus_prune_must_be_irreducible(zas)) { n_tpoly_fit_length(F, 1); F->length = 1; n_fq_bpoly_swap(F->coeffs + 0, A); success = 1; goto cleanup; } /* if multiple factors, get new alpha */ for (i = 0; i < r; i++) { if (local_fac->exp[i] != 1) goto next_alpha; } /* done if A is constant in y */ if (Aleny < 2) { n_tpoly_fit_length(F, r); F->length = r; for (i = 0; i < r; i++) n_fq_bpoly_set_fq_nmod_poly_gen0(F->coeffs + i, local_fac->poly + i, ctx); success = 1; goto cleanup; } /* precision for constructing true factors */ final_order = Aleny; n_fq_bpoly_taylor_shift_gen1_fq_nmod(A, A, alpha, ctx); n_fq_bpoly_lift_start(L, local_fac->poly, r, ctx); /* precision for lifted local factors */ lift_order = final_order + r; n_fq_bpoly_make_monic_series(monicA, A, lift_order, ctx); n_fq_bpoly_lift_continue(L, monicA, lift_order, ctx); /* the rows of N give the combinations of local factors */ nmod_mat_clear(N); nmod_mat_init(N, r, r, ctx->mod.n); for (i = 0; i < r; i++) nmod_mat_entry(N, i, i) = 1; /* size limit on subsets in zassenhaus combination */ zas_limit = 1; _lattice(N, L->lifted_fac, r, lift_order, CLD, A, ctx); if (!nmod_mat_is_reduced(N)) goto more; try_zas: /* zassenhaus only make sense if N is a nice 0-1 mat */ FLINT_ASSERT(nmod_mat_is_reduced(N)); /* combine local factors according the rows of N, then by subsets */ F->length = 0; fq_nmod_neg(alpha, alpha, ctx); success = _zassenhaus(zas, zas_limit, F, alpha, N, L->lifted_fac, r, final_order, A, ctx); fq_nmod_neg(alpha, alpha, ctx); if (success) goto cleanup; /* first attempt failed, try subsets of size 1 or 2 from now on */ zas_limit = 2; more: /* increase precision until N has fewer rows and is a nice 0-1 mat */ old_nrows = nmod_mat_nrows(N); _lattice(N, L->lifted_fac, r, lift_order, CLD, A, ctx); if (nmod_mat_nrows(N) < old_nrows && nmod_mat_is_reduced(N)) goto try_zas; lift_order += r; n_fq_bpoly_make_monic_series(monicA, A, lift_order, ctx); n_fq_bpoly_lift_continue(L, monicA, lift_order, ctx); goto more; cleanup: n_fq_bpoly_lift_clear(L); flint_free(CLD); nmod_mat_clear(N); fq_nmod_clear(alpha, ctx); fq_nmod_clear(Alc, ctx); fq_nmod_poly_clear(Aeval, ctx); fq_nmod_poly_factor_clear(local_fac, ctx); n_fq_bpoly_clear(monicA); zassenhaus_prune_clear(zas); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/n_bpoly_hlift.c000066400000000000000000000405271461254215100226270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly_factor.h" /* input A, B0, B1 with A(y,x) = B0(y,x) * B1(y,x) mod (y-alpha) return -1: B0(alpha,x) & B1(alpha,x) are not pairwise prime, or A(alpha,x) has wrong degree w.r.t x 0: lift of B0 and B1 to true factors is impossible 1: successfully lifted B0 and B1 to true factors without changing lc_x */ int n_fq_bpoly_hlift2_cubic( n_fq_bpoly_t A, /* clobbered (shifted by alpha) */ n_fq_bpoly_t B0, n_fq_bpoly_t B1, const fq_nmod_t alpha_, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, nmod_eval_interp_t E, n_poly_bpoly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); int success; slong len = nmod_eval_interp_eval_length(E); slong i, j; n_fq_poly_struct * c, * s, * t, * u, * v, * g, * ce; n_fq_bpoly_struct * B0e, * B1e; mp_limb_t * alpha; FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(B0, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(B1, ctx)); if (A->length < 1 || B0->length < 1 || B1->length < 1) return -1; n_poly_stack_fit_request(St->poly_stack, 7); c = n_poly_stack_take_top(St->poly_stack); s = n_poly_stack_take_top(St->poly_stack); t = n_poly_stack_take_top(St->poly_stack); u = n_poly_stack_take_top(St->poly_stack); v = n_poly_stack_take_top(St->poly_stack); g = n_poly_stack_take_top(St->poly_stack); ce = n_poly_stack_take_top(St->poly_stack); n_bpoly_stack_fit_request(St->bpoly_stack, 2); B0e = n_bpoly_stack_take_top(St->bpoly_stack); B1e = n_bpoly_stack_take_top(St->bpoly_stack); alpha = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_fq_set_fq_nmod(alpha, alpha_, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(A, alpha, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(B0, alpha, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(B1, alpha, ctx); #if FLINT_WANT_ASSERT { n_fq_poly_t T; n_fq_poly_init(T); n_fq_poly_mul(T, B0->coeffs + 0, B1->coeffs + 0, ctx); FLINT_ASSERT(n_fq_poly_equal(A->coeffs + 0, T, ctx)); n_fq_poly_clear(T); } #endif if (n_poly_degree(A->coeffs + 0) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0)); n_fq_poly_xgcd(g, s, t, B1->coeffs + 0, B0->coeffs + 0, ctx); if (!n_fq_poly_is_one(g, ctx)) { success = -1; goto cleanup; } n_fq_bpoly_fit_length(B0, A->length); n_fq_bpoly_fit_length(B0e, A->length); for (i = 0; i < B0->length; i++) nmod_eval_interp_from_coeffs_n_fq_poly(B0e->coeffs + i, B0->coeffs + i, E, ctx); for (i = B0->length; i < A->length; i++) { n_fq_poly_zero(B0->coeffs + i); n_fq_evals_zero(B0e->coeffs + i); } n_fq_bpoly_fit_length(B1, A->length); n_fq_bpoly_fit_length(B1e, A->length); for (i = 0; i < B1->length; i++) nmod_eval_interp_from_coeffs_n_fq_poly(B1e->coeffs + i, B1->coeffs + i, E, ctx); for (i = B1->length; i < A->length; i++) { n_fq_poly_zero(B1->coeffs + i); n_fq_evals_zero(B1e->coeffs + i); } for (j = 1; j < A->length; j++) { n_fq_evals_zero(ce); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { n_fq_evals_addmul(ce, B0e->coeffs + i, B1e->coeffs + j - i, len, ctx); } } nmod_eval_interp_to_coeffs_n_fq_poly(c, ce, E, ctx); n_fq_poly_sub(c, A->coeffs + j, c, ctx); #if FLINT_WANT_ASSERT { n_fq_poly_t c_check; n_fq_poly_init(c_check); n_fq_poly_set(c_check, A->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { n_fq_poly_mul(t, B0->coeffs + i, B1->coeffs + j - i, ctx); n_fq_poly_sub(c_check, c_check, t, ctx); } } assert(n_fq_poly_equal(c, c_check, ctx)); n_fq_poly_clear(c_check); } #endif if (n_fq_poly_is_zero(c)) continue; n_fq_poly_mul_(t, s, c, ctx, St->poly_stack); n_fq_poly_divrem_(g, u, t, B0->coeffs + 0, ctx, St->poly_stack); n_fq_poly_mul_(t, u, B1->coeffs + 0, ctx, St->poly_stack); n_fq_poly_sub(ce, c, t, ctx); n_fq_poly_divrem_(v, g, ce, B0->coeffs + 0, ctx, St->poly_stack); if (!n_fq_poly_is_zero(u)) { n_fq_poly_add(B0->coeffs + j, B0->coeffs + j, u, ctx); nmod_eval_interp_from_coeffs_n_fq_poly(B0e->coeffs + j, B0->coeffs + j, E, ctx); } if (!n_fq_poly_is_zero(v)) { n_fq_poly_add(B1->coeffs + j, B1->coeffs + j, v, ctx); nmod_eval_interp_from_coeffs_n_fq_poly(B1e->coeffs + j, B1->coeffs + j, E, ctx); } if (!n_fq_poly_is_zero(B0->coeffs + j)) B0->length = FLINT_MAX(B0->length, j + 1); if (!n_fq_poly_is_zero(B1->coeffs + j)) B1->length = FLINT_MAX(B1->length, j + 1); if (B0->length - 1 + B1->length - 1 > A->length - 1) { success = 0; goto cleanup; } } _n_fq_neg(alpha, alpha, d, ctx->mod); n_fq_bpoly_taylor_shift_gen0_n_fq(B0, alpha, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(B1, alpha, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { n_bpoly_t tp1, tp2; n_bpoly_init(tp1); n_bpoly_init(tp2); n_fq_set_fq_nmod(alpha, alpha_, ctx); _n_fq_neg(alpha, alpha, d, ctx->mod); n_fq_bpoly_taylor_shift_gen0_n_fq(A, alpha, ctx); n_fq_bpoly_mul(tp1, B0, B1, ctx); FLINT_ASSERT(n_fq_bpoly_equal(tp1, A, ctx)); n_bpoly_clear(tp1); n_bpoly_clear(tp2); } #endif n_poly_stack_give_back(St->poly_stack, 7); n_bpoly_stack_give_back(St->bpoly_stack, 2); flint_free(alpha); return success; } int n_fq_bpoly_hlift2( n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_t B0, n_bpoly_t B1, const fq_nmod_t alpha_, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); int success; slong i, j; n_fq_poly_struct * c, * s, * t, * u, * v, * g; mp_limb_t * alpha; FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(B0, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(B1, ctx)); if (A->length < 1 || B0->length < 1 || B1->length < 1) return -1; n_poly_stack_fit_request(St->poly_stack, 6); c = n_poly_stack_take_top(St->poly_stack); s = n_poly_stack_take_top(St->poly_stack); t = n_poly_stack_take_top(St->poly_stack); u = n_poly_stack_take_top(St->poly_stack); v = n_poly_stack_take_top(St->poly_stack); g = n_poly_stack_take_top(St->poly_stack); alpha = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_fq_set_fq_nmod(alpha, alpha_, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(A, alpha, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(B0, alpha, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(B1, alpha, ctx); #if FLINT_WANT_ASSERT { n_poly_t T; n_poly_init(T); n_fq_poly_mul(T, B0->coeffs + 0, B1->coeffs + 0, ctx); FLINT_ASSERT(n_fq_poly_equal(A->coeffs + 0, T, ctx)); n_poly_clear(T); } #endif if (n_poly_degree(A->coeffs + 0) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0)); n_fq_poly_xgcd(g, s, t, B1->coeffs + 0, B0->coeffs + 0, ctx); if (!n_fq_poly_is_one(g, ctx)) { success = -1; goto cleanup; } n_bpoly_fit_length(B0, A->length); n_bpoly_fit_length(B1, A->length); for (j = 1; j < A->length; j++) { n_fq_poly_set(c, A->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { n_fq_poly_mul_(t, B0->coeffs + i, B1->coeffs + j - i, ctx, St->poly_stack); n_fq_poly_sub(c, c, t, ctx); } } if (n_fq_poly_is_zero(c)) continue; n_fq_poly_mul_(t, s, c, ctx, St->poly_stack); n_fq_poly_divrem_(g, u, t, B0->coeffs + 0, ctx, St->poly_stack); n_fq_poly_mul_(t, u, B1->coeffs + 0, ctx, St->poly_stack); n_fq_poly_sub(c, c, t, ctx); n_fq_poly_divrem_(v, g, c, B0->coeffs + 0, ctx, St->poly_stack); if (j < B0->length) n_fq_poly_add(B0->coeffs + j, B0->coeffs + j, u, ctx); else n_fq_poly_set(B0->coeffs + j, u, ctx); if (j < B1->length) n_fq_poly_add(B1->coeffs + j, B1->coeffs + j, v, ctx); else n_fq_poly_set(B1->coeffs + j, v, ctx); if (!n_fq_poly_is_zero(B0->coeffs + j)) B0->length = FLINT_MAX(B0->length, j + 1); if (!n_fq_poly_is_zero(B1->coeffs + j)) B1->length = FLINT_MAX(B1->length, j + 1); if (B0->length - 1 + B1->length - 1 > A->length - 1) { success = 0; goto cleanup; } } _n_fq_neg(alpha, alpha, d, ctx->mod); n_fq_bpoly_taylor_shift_gen0_n_fq(B0, alpha, ctx); n_fq_bpoly_taylor_shift_gen0_n_fq(B1, alpha, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { n_bpoly_t tp1, tp2; n_bpoly_init(tp1); n_bpoly_init(tp2); n_fq_set_fq_nmod(alpha, alpha_, ctx); _n_fq_neg(alpha, alpha, d, ctx->mod); n_fq_bpoly_taylor_shift_gen0_n_fq(A, alpha, ctx); n_fq_bpoly_mul(tp1, B0, B1, ctx); FLINT_ASSERT(n_fq_bpoly_equal(tp1, A, ctx)); n_bpoly_clear(tp1); n_bpoly_clear(tp2); } #endif n_poly_stack_give_back(St->poly_stack, 6); flint_free(alpha); return success; } /* r factor version */ int n_fq_bpoly_hlift( slong r, n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_struct * B, const fq_nmod_t alpha, slong degree_inner, /* required degree in x */ const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t St) { int success; slong i, j, k, tdeg; n_poly_struct * s, * v; n_poly_t c, t, u, g1, g2; n_bpoly_struct * U; fq_nmod_t malpha; FLINT_ASSERT(r > 2); FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); if (A->length < 1) return -1; for (i = 0; i < r; i++) { FLINT_ASSERT(n_fq_bpoly_is_canonical(B + i, ctx)); if (B[i].length < 1) return -1; } U = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); for (i = 0; i < r; i++) { n_bpoly_init(U + i); n_bpoly_fit_length(U + i, A->length); for (j = 0; j < A->length; j++) n_poly_zero(U[i].coeffs + j); U[i].length = A->length; n_bpoly_fit_length(B + i, A->length); } s = FLINT_ARRAY_ALLOC(r, n_poly_struct); v = FLINT_ARRAY_ALLOC(r, n_poly_struct); for (i = 0; i < r; i++) { n_poly_init(s + i); n_poly_init(v + i); } n_poly_init(c); n_poly_init(t); n_poly_init(u); n_poly_init(g1); n_poly_init(g2); fq_nmod_init(malpha, ctx); fq_nmod_neg(malpha, alpha, ctx); n_fq_bpoly_taylor_shift_gen0_fq_nmod(A, alpha, ctx); for (i = 0; i < r; i++) n_fq_bpoly_taylor_shift_gen0_fq_nmod(B + i, alpha, ctx); /* supposed to have A(alpha,x) = B0(alpha,x) * B1(alpha,x) * ... */ #if FLINT_WANT_ASSERT { n_poly_t T; n_poly_init(T); n_fq_poly_mul(T, B[0].coeffs + 0, B[1].coeffs + 0, ctx); for (i = 2; i < r; i++) n_fq_poly_mul(T, T, B[i].coeffs + 0, ctx); FLINT_ASSERT(n_fq_poly_equal(A->coeffs + 0, T, ctx)); n_poly_clear(T); } #endif if (n_poly_degree(A->coeffs + 0) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0)); for (i = 0; i < r; i++) { n_fq_poly_one(t, ctx); for (j = 0; j < r; j++) { if (j != i) n_fq_poly_mul(t, t, B[j].coeffs + 0, ctx); } n_fq_poly_xgcd(g1, s + i, g2, t, B[i].coeffs + 0, ctx); if (!n_fq_poly_is_one(g1, ctx)) { success = -1; goto cleanup; } } k = r - 2; n_fq_poly_mul(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k > 0; k--) n_fq_poly_mul(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx); for (j = 1; j < A->length; j++) { for (k = 0; k < r; k++) n_poly_zero(U[k].coeffs + j); k = r - 2; n_poly_zero(U[k].coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { n_fq_poly_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); n_fq_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (k--; k > 0; k--) { n_poly_zero(U[k].coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length) { n_fq_poly_mul(t, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); n_fq_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } } n_fq_poly_set(c, A->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[0].length) { n_fq_poly_mul(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx); n_fq_poly_sub(c, c, t, ctx); } } if (n_poly_is_zero(c)) continue; tdeg = 0; for (i = 0; i < r; i++) { n_fq_poly_mul(t, s + i, c, ctx); n_fq_poly_divrem(g1, v + i, t, B[i].coeffs + 0, ctx); while (j >= B[i].length) { n_poly_zero(B[i].coeffs + B[i].length); B[i].length++; } n_fq_poly_add(B[i].coeffs + j, B[i].coeffs + j, v + i, ctx); n_bpoly_normalise(B + i); tdeg += B[i].length - 1; } if (tdeg >= A->length) { success = 0; goto cleanup; } k = r - 2; n_fq_poly_mul(t, B[k].coeffs + 0, v + k + 1, ctx); n_fq_poly_mul(u, B[k + 1].coeffs + 0, v + k, ctx); n_fq_poly_add(t, t, u, ctx); n_fq_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); for (k--; k > 0; k--) { n_fq_poly_mul(u, B[k].coeffs + 0, t, ctx); n_fq_poly_mul(t, U[k + 1].coeffs + 0, v + k, ctx); n_fq_poly_add(t, t, u, ctx); n_fq_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (i = 0; i < r; i++) n_fq_bpoly_taylor_shift_gen0_fq_nmod(B + i, malpha, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { n_fq_bpoly_t tp1, tp2; n_fq_bpoly_init(tp1); n_fq_bpoly_init(tp2); n_fq_bpoly_taylor_shift_gen0_fq_nmod(A, malpha, ctx); n_fq_bpoly_mul(tp1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { n_fq_bpoly_mul(tp2, tp1, B + i, ctx); n_bpoly_swap(tp1, tp2); } FLINT_ASSERT(n_fq_bpoly_equal(tp1, A, ctx)); n_fq_bpoly_clear(tp1); n_fq_bpoly_clear(tp2); } #endif for (i = 0; i < r; i++) { n_bpoly_clear(U + i); n_poly_clear(s + i); n_poly_clear(v + i); } flint_free(U); flint_free(s); flint_free(v); n_poly_clear(c); n_poly_clear(t); n_poly_clear(u); n_poly_clear(g1); n_poly_clear(g2); fq_nmod_clear(malpha, ctx); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/one.c000066400000000000000000000011031461254215100205430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_one(fq_nmod_mpoly_factor_t a, const fq_nmod_mpoly_ctx_t ctx) { fq_nmod_one(a->constant, ctx->fqctx); a->num = 0; } flint-3.1.3/src/fq_nmod_mpoly_factor/polyu.c000066400000000000000000000016221461254215100211400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly_factor.h" int n_polyu_fq_is_canonical( const n_polyu_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (!n_fq_is_canonical(A->coeffs + d*i, ctx)) return 0; if (_n_fq_is_zero(A->coeffs + d*i, d)) return 0; if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } flint-3.1.3/src/fq_nmod_mpoly_factor/polyu3_hlift.c000066400000000000000000000345331461254215100224200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly_factor.h" #if FLINT_WANT_ASSERT static void n_fq_polyu_set_n_fq_polyun( n_polyu_t A, const n_polyun_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j; A->length = 0; for (i = 0; i < B->length; i++) { for (j = B->coeffs[i].length - 1; j >= 0; j--) { if (_n_fq_is_zero(B->coeffs[i].coeffs + d*j, d)) continue; n_polyu_fit_length(A, d*(A->length + 1)); _n_fq_set(A->coeffs + d*A->length, B->coeffs[i].coeffs + d*j, d); A->exps[A->length] = B->exps[i] + j; A->length++; } } } static void n_fq_polyu_sort_terms( n_polyu_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j; for (i = 1; i < A->length; i++) for (j = i; j > 0 && A->exps[j - 1] < A->exps[j]; j--) { FLINT_SWAP(ulong, A->exps[j - 1], A->exps[j]); _n_fq_swap(A->coeffs + d*(j - 1), A->coeffs + d*(j), d); } return; } static void n_fq_polyu_combine_like_terms( n_fq_polyu_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); slong in, out; out = -1; for (in = 0; in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= 0 && A->exps[out] == A->exps[in]) { _n_fq_add(A->coeffs + d*out, A->coeffs + d*out, A->coeffs + d*in, d, mod); } else { if (out < 0 || !_n_fq_is_zero(A->coeffs + d*out, d)) out++; if (out != in) { A->exps[out] = A->exps[in]; _n_fq_set(A->coeffs + d*out, A->coeffs + d*in, d); } } } if (out < 0 || !_n_fq_is_zero(A->coeffs + d*out, d)) out++; A->length = out; } static int n_fq_polyu_equal( n_polyu_t A, n_polyu_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (!_n_fq_equal(A->coeffs + d*i, B->coeffs + d*i, d)) return 0; if (A->exps[i] != B->exps[i]) return 0; } return 1; } static void fq_nmod_polyu_mul( n_polyu_t A, const n_polyu_t B, const n_polyu_t C, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong Ai, Bi, Ci; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_polyu_fit_length(A, d*B->length*C->length); Ai = 0; for (Bi = 0; Bi < B->length; Bi++) for (Ci = 0; Ci < C->length; Ci++) { A->exps[Ai] = B->exps[Bi] + C->exps[Ci]; n_fq_mul(A->coeffs + d*Ai, B->coeffs + d*Bi, C->coeffs + d*Ci, ctx); Ai++; } A->length = Ai; n_fq_polyu_sort_terms(A, ctx); n_fq_polyu_combine_like_terms(A, ctx); } #endif void n_fq_poly_fill_power( n_fq_poly_t alphapow, slong e, const fq_nmod_ctx_t ctx, mp_limb_t * tmp) { if (e + 1 > alphapow->length) { slong d = fq_nmod_ctx_degree(ctx); slong k; slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); n_poly_fit_length(alphapow, d*(e + 1)); for (k = oldlength; k <= e; k++) { _n_fq_mul(alphapow->coeffs + d*k, alphapow->coeffs + d*(k - 1), alphapow->coeffs + d*1, ctx, tmp); } alphapow->length = e + 1; } } void fq_nmod_polyu3_interp_reduce_bpoly( n_bpoly_t Ap, const n_polyu_t A, n_fq_poly_t alphapow, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; slong cur0, cur1, e0, e1, e2; mp_limb_t * tmp, * t; TMP_INIT; TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*(1 + N_FQ_MUL_ITCH)*sizeof(mp_limb_t)); t = tmp + d*N_FQ_MUL_ITCH; n_bpoly_zero(Ap); FLINT_ASSERT(A->length > 0); i = 0; cur0 = extract_exp(A->exps[i], 2, 3); cur1 = extract_exp(A->exps[i], 1, 3); e2 = extract_exp(A->exps[i], 0, 3); n_fq_poly_fill_power(alphapow, e2, ctx, tmp); _n_fq_mul(t, A->coeffs + d*i, alphapow->coeffs + d*e2, ctx, tmp); for (i = 1; i < A->length; i++) { e0 = extract_exp(A->exps[i], 2, 3); e1 = extract_exp(A->exps[i], 1, 3); e2 = extract_exp(A->exps[i], 0, 3); FLINT_ASSERT(e0 <= cur0); if (e0 < cur0 || e1 < cur1) { n_fq_bpoly_set_coeff_n_fq(Ap, cur0, cur1, t, ctx); _n_fq_zero(t, d); } else { FLINT_ASSERT(e0 == cur0); FLINT_ASSERT(e1 == cur1); } cur0 = e0; cur1 = e1; n_fq_poly_fill_power(alphapow, e2, ctx, tmp); _n_fq_addmul(t, t, A->coeffs + d*i, alphapow->coeffs + d*e2, ctx, tmp); } n_fq_bpoly_set_coeff_n_fq(Ap, cur0, cur1, t, ctx); TMP_END; } /* T(x0, x1, x2) is in F[x2][x0, x1] A(x0, x1) are B(x0, x1) are in F[x0, x1] set T so that T(x0, x1, x2) == A(x0, x1) mod (x2 - alpha) T(x0, x1, x2) == B(x0, x1) mod (x2 + alpha) */ void fq_nmod_polyu3n_interp_lift_sm_bpoly( slong * lastdeg, n_polyun_t T, const n_bpoly_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong lastlength = 0; slong Ti; slong Ai, j; Ti = 0; for (Ai = A->length - 1; Ai >= 0; Ai--) { n_poly_struct * Ac = A->coeffs + Ai; for (j = Ac->length - 1; j >= 0; j--) { if (_n_fq_is_zero(Ac->coeffs + d*j, d)) continue; n_polyun_fit_length(T, Ti + 1); T->exps[Ti] = pack_exp3(Ai, j, 0); n_fq_poly_set_n_fq(T->coeffs + Ti, Ac->coeffs + d*j, ctx); Ti++; lastlength = 1; } } T->length = Ti; *lastdeg = lastlength - 1; return; } /* F is in Fq[x2][x0, x1] A is in Fq[x0, x1] T = F + modulus*(A - F(alpha)) */ int fq_nmod_polyu3n_interp_crt_sm_bpoly( slong * lastdeg, n_polyun_t F, n_polyun_t T, const n_bpoly_t A, const n_poly_t modulus, n_fq_poly_t alphapow, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); int changed = 0; slong lastlength = 0; n_poly_struct * Tcoeffs; ulong * Texps; slong Ti; n_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; slong Flen = F->length; slong Fi; const n_poly_struct * Acoeffs = A->coeffs; slong Ai, ai; mp_limb_t * v = FLINT_ARRAY_ALLOC(d, mp_limb_t); FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(n_polyun_fq_is_canonical(F, ctx)); n_polyun_fit_length(T, FLINT_MAX(Flen, A->length)); Tcoeffs = T->coeffs; Texps = T->exps; Ti = Fi = 0; Ai = A->length - 1; ai = (Ai < 0) ? 0 : n_poly_degree(A->coeffs + Ai); while (Fi < Flen || Ai >= 0) { if (Ti >= T->alloc) { slong extra = Flen - Fi; extra = FLINT_MAX(extra, Ai); n_polyun_fit_length(T, Ti + extra + 1); Tcoeffs = T->coeffs; Texps = T->exps; } FLINT_ASSERT(Fi >= Flen || Fcoeffs[Fi].length > 0); FLINT_ASSERT(Ai < 0 || !_n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (Fi < Flen && Ai >= 0 && Fexps[Fi] == pack_exp3(Ai, ai, 0)) { /* F term ok, A term ok */ n_fq_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx); _n_fq_sub(v, Acoeffs[Ai].coeffs + d*ai, v, d, mod); if (!_n_fq_is_zero(v, d)) { changed = 1; n_fq_poly_scalar_addmul_n_fq(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx); } Texps[Ti] = Fexps[Fi]; Fi++; do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_poly_degree(Acoeffs + Ai); } } else if (Fi < Flen && (Ai < 0 || Fexps[Fi] > pack_exp3(Ai, ai, 0))) { /* F term ok, A term missing */ n_fq_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx); if (!_n_fq_is_zero(v, d)) { changed = 1; _n_fq_neg(v, v, d, ctx->mod); n_fq_poly_scalar_addmul_n_fq(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx); } else { n_fq_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx); } Texps[Ti] = Fexps[Fi]; Fi++; } else { FLINT_ASSERT(Ai >= 0 && (Fi >= Flen || Fexps[Fi] < pack_exp3(Ai, ai, 0))); /* F term missing, Aterm ok */ Texps[Ti] = pack_exp3(Ai, ai, 0); changed = 1; n_fq_poly_scalar_mul_n_fq(Tcoeffs + Ti, modulus, Acoeffs[Ai].coeffs + d*ai, ctx); do { ai--; } while (ai >= 0 && _n_fq_is_zero(Acoeffs[Ai].coeffs + d*ai, d)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_poly_degree(Acoeffs + Ai); } } FLINT_ASSERT(!n_poly_is_zero(Tcoeffs + Ti)); lastlength = FLINT_MAX(lastlength, Tcoeffs[Ti].length); Ti++; } T->length = Ti; if (changed) n_polyun_swap(T, F); FLINT_ASSERT(n_polyun_fq_is_canonical(F, ctx)); flint_free(v); *lastdeg = lastlength - 1; return changed; } int n_fq_polyu3_hlift( slong r, n_polyun_struct * BB, n_polyu_t A, n_polyu_struct * B, const fq_nmod_t beta, slong degree_inner, /* required degree in X (var 1) */ const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); int success, Eok; slong i, j; n_polyun_t T; n_bpoly_struct * Bp; n_bpoly_t Ap; n_fq_poly_t modulus, alphapow; fq_nmod_t alpha; slong * BBdegZ; slong AdegY, AdegX, AdegZ; slong bad_primes_left; mp_limb_t * c = FLINT_ARRAY_ALLOC(d, mp_limb_t); nmod_eval_interp_t E; fq_nmod_init(alpha, ctx); FLINT_ASSERT(n_polyu_fq_is_canonical(A, ctx)); for (i = 0; i < r; i++) FLINT_ASSERT(n_polyu_fq_is_canonical(B + i, ctx)); BBdegZ = FLINT_ARRAY_ALLOC(r, slong); Bp = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); for (i = 0; i < r; i++) n_bpoly_init(Bp + i); n_polyun_init(T); n_fq_poly_init(modulus); n_poly_init2(alphapow, 2*d); n_bpoly_init(Ap); nmod_eval_interp_init(E); Eok = nmod_eval_interp_set_degree_modulus(E, degree_inner, ctx->mod); n_polyu3_degrees(&AdegY, &AdegX, &AdegZ, A); if (AdegX != degree_inner) { success = -1; goto cleanup; } n_fq_poly_one(modulus, ctx); fq_nmod_zero(alpha, ctx); bad_primes_left = FLINT_MAX(5, AdegZ); choose_prime: if (fq_nmod_next(alpha, ctx) == 0) { success = -1; goto cleanup; } FLINT_ASSERT(alphapow->alloc >= 2*d); alphapow->length = 2; _n_fq_one(alphapow->coeffs + d*0, d); n_fq_set_fq_nmod(alphapow->coeffs + d*1, alpha, ctx); fq_nmod_polyu3_interp_reduce_bpoly(Ap, A, alphapow, ctx); for (i = 0; i < r; i++) fq_nmod_polyu3_interp_reduce_bpoly(Bp + i, B + i, alphapow, ctx); if (r < 3) { if (Eok) success = n_fq_bpoly_hlift2_cubic(Ap, Bp + 0, Bp + 1, beta, degree_inner, ctx, E, St); else success = n_fq_bpoly_hlift2(Ap, Bp + 0, Bp + 1, beta, degree_inner, ctx, St); } else { success = n_fq_bpoly_hlift(r, Ap, Bp, beta, degree_inner, ctx, St); } if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } if (n_fq_poly_degree(modulus) > 0) { n_fq_poly_eval_pow(c, modulus, alphapow, ctx); n_fq_inv(c, c, ctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, c, ctx); for (i = 0; i < r; i++) { fq_nmod_polyu3n_interp_crt_sm_bpoly(BBdegZ + i, BB + i, T, Bp + i, modulus, alphapow, ctx); } } else { for (i = 0; i < r; i++) { fq_nmod_polyu3n_interp_lift_sm_bpoly(BBdegZ + i, BB + i, Bp + i, ctx); } } n_fq_poly_shift_left_scalar_submul(modulus, 1, alphapow->coeffs + d*1, ctx); j = BBdegZ[0]; for (i = 1; i < r; i++) j += BBdegZ[i]; if (j > AdegZ) { success = 0; goto cleanup; } if (n_fq_poly_degree(modulus) <= AdegZ) { goto choose_prime; } success = 1; cleanup: #if FLINT_WANT_ASSERT if (success == 1) { n_polyu_t T1, T2, T3; n_polyu_init(T1); n_polyu_init(T2); n_polyu_init(T3); n_fq_polyu_set_n_fq_polyun(T2, BB + 0, ctx); n_fq_polyu_set_n_fq_polyun(T3, BB + 1, ctx); fq_nmod_polyu_mul(T1, T2, T3, ctx); for (i = 2; i < r; i++) { n_fq_polyu_set_n_fq_polyun(T3, BB + i, ctx); fq_nmod_polyu_mul(T2, T1, T3, ctx); n_polyu_swap(T2, T1); } FLINT_ASSERT(n_fq_polyu_equal(A, T1, ctx)); n_polyu_clear(T1); n_polyu_clear(T2); n_polyu_clear(T3); } #endif n_polyun_clear(T); n_bpoly_clear(Ap); for (i = 0; i < r; i++) n_bpoly_clear(Bp + i); flint_free(BBdegZ); flint_free(Bp); n_fq_poly_clear(alphapow); n_fq_poly_clear(modulus); fq_nmod_clear(alpha, ctx); flint_free(c); nmod_eval_interp_clear(E); return success; } flint-3.1.3/src/fq_nmod_mpoly_factor/polyun.c000066400000000000000000000015541461254215100213220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly_factor.h" int n_polyun_fq_is_canonical( const n_polyun_t A, const fq_nmod_ctx_t ctx) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (!n_fq_poly_is_canonical(A->coeffs + i, ctx)) return 0; if (n_poly_is_zero(A->coeffs + i)) return 0; if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } flint-3.1.3/src/fq_nmod_mpoly_factor/profile/000077500000000000000000000000001461254215100212635ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mpoly_factor/profile/p-factor.c000066400000000000000000000063611461254215100231500ustar00rootroot00000000000000/* Copyright 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "fq_nmod_mpoly_factor.h" slong check_omega(slong om, const fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx) { slong i; fq_nmod_mpoly_t q; fq_nmod_mpoly_factor_t g; fmpz_t omega; timeit_t timer; flint_printf("---------------------------\n"); fmpz_init(omega); fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_init(q, ctx); timeit_start(timer); fq_nmod_mpoly_factor(g, p, ctx); timeit_stop(timer); fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, om) < 0) { flint_printf("factorization has wrong number of factors\n"); flint_abort(); } fq_nmod_mpoly_factor_expand(q, g, ctx); if (!fq_nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); flint_abort(); } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fmpz_clear(omega); return timer->wall; } int main(int argc, char *argv[]) { slong i, time, total_time = 0; mp_limb_t p = UWORD(4611686018427388073); flint_printf("starting dense\n"); { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, c; const char * vars[] = {"x", "y", "z", "t"}; fq_nmod_mpoly_ctx_init_deg(ctx, 4, ORD_LEX, p, 2); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(c, ctx); for (i = 1; i <= 10; i++) { fq_nmod_mpoly_set_str_pretty(a, "x", vars, ctx); fq_nmod_mpoly_set_str_pretty(b, "y", vars, ctx); fq_nmod_mpoly_set_str_pretty(c, "#^4+#^3*x+#^2*y+#*z+0*t", vars, ctx); fq_nmod_mpoly_pow_ui(c, c, i, ctx); fq_nmod_mpoly_add(a, a, c, ctx); fq_nmod_mpoly_add(b, b, c, ctx); fq_nmod_mpoly_mul(a, a, b, ctx); time = check_omega(2, a, ctx); flint_printf("power %wd: %wd\n", i, time); total_time += time; } flint_printf("total_time: %wd\n", total_time); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(c, ctx); fq_nmod_mpoly_ctx_clear(ctx); } { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a; const char * vars[] = {"x", "y", "z", "t" ,"u", "v", "w"}; flint_printf("starting sparse\n"); fq_nmod_mpoly_ctx_init_deg(ctx, 7, ORD_LEX, p, 2); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_set_str_pretty(a, "(x+(1+#*x+y+z+#*t+u+2*v+w)^7)" "*(y+(#+x+y+#*z-t+u+v+3*#*w)^7)", vars, ctx); time = check_omega(2, a, ctx); flint_printf("sparse: %wd\n", time); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } flint_cleanup_master(); return 0; } flint-3.1.3/src/fq_nmod_mpoly_factor/realloc.c000066400000000000000000000037271461254215100214210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_realloc(fq_nmod_mpoly_factor_t f, slong alloc, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (alloc <= 0) { fq_nmod_mpoly_factor_clear(f, ctx); fq_nmod_mpoly_factor_init(f, ctx); return; } if (f->alloc > 0) { if (f->alloc > alloc) { for (i = alloc; i < f->alloc; i++) { fq_nmod_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fq_nmod_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fq_nmod_mpoly_struct)); } else if (f->alloc < alloc) { f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fq_nmod_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fq_nmod_mpoly_struct)); for (i = f->alloc; i < alloc; i++) { fq_nmod_mpoly_init(f->poly + i, ctx); fmpz_init(f->exp + i); } } } else { f->exp = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); f->poly = (fq_nmod_mpoly_struct *) flint_malloc(alloc * sizeof(fq_nmod_mpoly_struct)); for (i = 0; i < alloc; i++) fq_nmod_mpoly_init(f->poly + i, ctx); } f->alloc = alloc; } flint-3.1.3/src/fq_nmod_mpoly_factor/set.c000066400000000000000000000016171461254215100205670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mpoly_factor.h" void fq_nmod_mpoly_factor_set( fq_nmod_mpoly_factor_t a, const fq_nmod_mpoly_factor_t b, const fq_nmod_mpoly_ctx_t ctx) { slong i; if (a == b) return; fq_nmod_mpoly_factor_fit_length(a, b->num, ctx); fq_nmod_set(a->constant, b->constant, ctx->fqctx); for (i = 0; i < b->num; i++) { fq_nmod_mpoly_set(a->poly + i, b->poly + i, ctx); fmpz_set(a->exp + i, b->exp + i); } a->num = b->num; } flint-3.1.3/src/fq_nmod_mpoly_factor/sort.c000066400000000000000000000035531461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fq_nmod_mpoly_factor.h" typedef struct { slong idx; fmpz exp; const fq_nmod_mpoly_struct * polys; const fq_nmod_mpoly_ctx_struct * ctx; } sort_struct; static int _sort(const void * a_, const void * b_) { int cmp; const sort_struct * a = (const sort_struct *) a_; const sort_struct * b = (const sort_struct *) b_; const fq_nmod_mpoly_struct * apoly = a->polys + a->idx; const fq_nmod_mpoly_struct * bpoly = b->polys + b->idx; cmp = fmpz_cmp(&a->exp, &b->exp); if (cmp != 0) return cmp; return fq_nmod_mpoly_cmp(apoly, bpoly, a->ctx); } void fq_nmod_mpoly_factor_sort( fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx) { slong i; sort_struct * data; fq_nmod_mpoly_struct * fc; if (f->num < 1) return; data = (sort_struct *) flint_malloc(f->num*sizeof(sort_struct)); for (i = 0; i < f->num; i++) { data[i].idx = i; data[i].exp = f->exp[i]; data[i].polys = f->poly; data[i].ctx = ctx; } qsort(data, f->num, sizeof(sort_struct), _sort); /* we will not permute in place */ fc = (fq_nmod_mpoly_struct *) flint_malloc(f->num * sizeof(fq_nmod_mpoly_struct)); memcpy(fc, f->poly, f->num*sizeof(fq_nmod_mpoly_struct)); for (i = 0; i < f->num; i++) { f->exp[i] = data[i].exp; f->poly[i] = fc[data[i].idx]; } flint_free(fc); flint_free(data); return; } flint-3.1.3/src/fq_nmod_mpoly_factor/test/000077500000000000000000000000001461254215100206025ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_mpoly_factor/test/main.c000066400000000000000000000023551461254215100216770ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor.c" #include "t-factor_content.c" #include "t-factor_squarefree.c" #include "t-factor_wang.c" #include "t-factor_zassenhaus.c" #include "t-factor_zippel.c" #include "t-gcd_subresultant.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_mpoly_factor), TEST_FUNCTION(fq_nmod_mpoly_factor_content), TEST_FUNCTION(fq_nmod_mpoly_factor_squarefree), TEST_FUNCTION(fq_nmod_mpoly_factor_wang), TEST_FUNCTION(fq_nmod_mpoly_factor_zassenhaus), TEST_FUNCTION(fq_nmod_mpoly_factor_zippel), TEST_FUNCTION(fq_nmod_mpoly_factor_gcd_subresultant) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod_mpoly_factor/test/t-factor.c000066400000000000000000000111571461254215100224720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx, int (* factor_fun)(fq_nmod_mpoly_factor_t, const fq_nmod_mpoly_t, const fq_nmod_mpoly_ctx_t)) { slong i; fq_nmod_mpoly_t q; fq_nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_factor_init(h, ctx); fq_nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { if (!fq_nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\ncheck factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (!fq_nmod_mpoly_is_monic(g->poly + i, ctx)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_factor_expand(q, g, ctx); if (!fq_nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { fq_nmod_mpoly_factor_sort(g, ctx); fq_nmod_mpoly_factor_sort(h, ctx); if (fq_nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fq_nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fq_nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fq_nmod_mpoly_factor, state) { slong i, j, tmul = 40; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; if (i % 2 == 0) fq_nmod_mpoly_ctx_init_rand(ctx, state, 7, 1 + n_randint(state, FLINT_BITS), 4); else fq_nmod_mpoly_ctx_init_rand(ctx, state, 2, 3, 1); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 2 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 50/nfacs/n; lower = 0; fq_nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 1 + 20/powbound/nfacs); fq_nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fq_nmod_mpoly_is_fq_nmod(t, ctx)) lower += pow; fq_nmod_mpoly_pow_ui(t, t, pow, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fq_nmod_mpoly_factor); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly_factor/test/t-factor_content.c000066400000000000000000000075751461254215100242350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly_factor.h" void check_content(const fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx) { slong i, v; fq_nmod_mpoly_t q; fq_nmod_mpoly_factor_t g; fmpz_t deg; fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_init(q, ctx); fmpz_init(deg); if (!fq_nmod_mpoly_factor_content(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_factor_expand(q, g, ctx); if (!fq_nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { for (v = 0; v < ctx->minfo->nvars; v++) { if (fq_nmod_mpoly_length(g->poly + i, ctx) < 2) { if (!fq_nmod_mpoly_is_gen(g->poly + i, -1, ctx)) { flint_printf("FAIL:\nmonomial is bad\n"); fflush(stdout); flint_abort(); } } else { if (!fq_nmod_mpoly_content_vars(q, g->poly + i, &v, 1, ctx)) { flint_printf("FAIL:\ncheck content could be computed\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_degree_fmpz(deg, g->poly + i, v, ctx); if (!fq_nmod_mpoly_is_one(q, ctx) && !fmpz_is_zero(deg)) { flint_printf("FAIL:\ncontent is bad\n"); fflush(stdout); flint_abort(); } } } } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fmpz_clear(deg); } TEST_FUNCTION_START(fq_nmod_mpoly_factor_content, state) { slong i, j, k, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, t; slong n, nfacs, len; ulong * expbounds; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 4); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 5 + (8 + n_randint(state, 8))/n; expbounds = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); for (k = 0; k < ctx->minfo->nvars; k++) expbounds[k] = 3; fq_nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 9); if (ctx->minfo->nvars > 0) { k = n_randint(state, ctx->minfo->nvars); expbounds[k] = 1; } fq_nmod_mpoly_randtest_bounds(t, state, len, expbounds, ctx); if (!fq_nmod_mpoly_is_zero(t, ctx)) { fq_nmod_mpoly_mul(t, a, t, ctx); if (t->length < 1500) fq_nmod_mpoly_swap(a, t, ctx); } } check_content(a, ctx); flint_free(expbounds); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000066171461254215100247210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly_factor.h" /* check total number of factors with multiplicity is between lower and upper */ void check_it(const fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx) { slong i, j; fq_nmod_mpoly_t q; fq_nmod_mpoly_factor_t g, h; fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_factor_init(h, ctx); fq_nmod_mpoly_init(q, ctx); if (!fq_nmod_mpoly_factor_squarefree(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (!fq_nmod_mpoly_is_monic(g->poly + i, ctx)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_factor_expand(q, g, ctx); if (!fq_nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { fq_nmod_mpoly_factor_squarefree(h, g->poly + i, ctx); for (j = 0; j < h->num; j++) { if (!fmpz_is_one(h->exp + j)) { flint_printf("FAIL:\nfactor has a square factor\n"); fflush(stdout); flint_abort(); } } } for (i = 1; i < g->num; i++) for (j = 0; j < i; j++) { if (!fq_nmod_mpoly_gcd(q, g->poly + i, g->poly + j, ctx)) { flint_printf("FAIL:\ncheck gcd could be computed\n"); } if (!fq_nmod_mpoly_is_one(q, ctx)) { flint_printf("FAIL:\nbases have a common factor\n"); } } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fq_nmod_mpoly_factor_clear(h, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_factor_squarefree, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, t; slong nfacs, len; ulong expbound, powbound, pow; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 4); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); nfacs = 2 + n_randint(state, 4); powbound = 3; expbound = 2 + 20/nfacs/FLINT_MAX(WORD(1), ctx->minfo->nvars); fq_nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { pow = 1 + n_randint(state, powbound); len = 1 + n_randint(state, 2 + 15/pow/nfacs); fq_nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_pow_ui(t, t, pow, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); } check_it(a, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly_factor/test/t-factor_wang.c000066400000000000000000000107511461254215100235050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx, int (* factor_fun)(fq_nmod_mpoly_factor_t, const fq_nmod_mpoly_t, const fq_nmod_mpoly_ctx_t)) { slong i; fq_nmod_mpoly_t q; fq_nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_factor_init(h, ctx); fq_nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { if (!fq_nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\ncheck factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (!fq_nmod_mpoly_is_monic(g->poly + i, ctx)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_factor_expand(q, g, ctx); if (!fq_nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { fq_nmod_mpoly_factor_sort(g, ctx); fq_nmod_mpoly_factor_sort(h, ctx); if (fq_nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fq_nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fq_nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fq_nmod_mpoly_factor_wang, state) { slong i, j, tmul = 15; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 4); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 2 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 40/nfacs/n; lower = 0; fq_nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 1 + 20/powbound/nfacs); fq_nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fq_nmod_mpoly_is_fq_nmod(t, ctx)) lower += pow; fq_nmod_mpoly_pow_ui(t, t, pow, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fq_nmod_mpoly_factor_wang); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000107651461254215100247420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx, int (* factor_fun)(fq_nmod_mpoly_factor_t, const fq_nmod_mpoly_t, const fq_nmod_mpoly_ctx_t)) { slong i; fq_nmod_mpoly_t q; fq_nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_factor_init(h, ctx); fq_nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { if (!fq_nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\ncheck factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (!fq_nmod_mpoly_is_monic(g->poly + i, ctx)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_factor_expand(q, g, ctx); if (!fq_nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { fq_nmod_mpoly_factor_sort(g, ctx); fq_nmod_mpoly_factor_sort(h, ctx); if (fq_nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fq_nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fq_nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fq_nmod_mpoly_factor_zassenhaus, state) { slong i, j, tmul = 15; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; fq_nmod_mpoly_ctx_init_rand(ctx, state, 5, FLINT_BITS, 5); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 2 + (5 + n_randint(state, 5))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 30/nfacs/n; lower = 0; fq_nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 1 + 20/powbound/nfacs); fq_nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fq_nmod_mpoly_is_fq_nmod(t, ctx)) lower += pow; fq_nmod_mpoly_pow_ui(t, t, pow, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fq_nmod_mpoly_factor_zassenhaus); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000107551461254215100240600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c, * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx, int (* factor_fun)(fq_nmod_mpoly_factor_t, const fq_nmod_mpoly_t, const fq_nmod_mpoly_ctx_t)) { slong i; fq_nmod_mpoly_t q; fq_nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); fq_nmod_mpoly_factor_init(g, ctx); fq_nmod_mpoly_factor_init(h, ctx); fq_nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { if (!fq_nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\ncheck factorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (!fq_nmod_mpoly_is_monic(g->poly + i, ctx)) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } fq_nmod_mpoly_factor_expand(q, g, ctx); if (!fq_nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != fq_nmod_mpoly_factor) { fq_nmod_mpoly_factor_sort(g, ctx); fq_nmod_mpoly_factor_sort(h, ctx); if (fq_nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { fq_nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fq_nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(fq_nmod_mpoly_factor_zippel, state) { slong i, j, tmul = 15; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; fq_nmod_mpoly_ctx_init_rand(ctx, state, 6, FLINT_BITS, 5); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 2 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 50/nfacs/n; lower = 0; fq_nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 1 + 15/powbound/nfacs); fq_nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!fq_nmod_mpoly_is_fq_nmod(t, ctx)) lower += pow; fq_nmod_mpoly_pow_ui(t, t, pow, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, fq_nmod_mpoly_factor_zippel); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000163521461254215100245660ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly_factor.h" int compute_gcd( fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx) { int success; slong var = 0; fq_nmod_mpoly_t Ac, Bc, Gc, s, t; fq_nmod_mpoly_univar_t Ax, Bx, Gx; if (fq_nmod_mpoly_is_zero(A, ctx) || fq_nmod_mpoly_is_zero(B, ctx)) return fq_nmod_mpoly_gcd(G, A, B, ctx); fq_nmod_mpoly_init(Ac, ctx); fq_nmod_mpoly_init(Bc, ctx); fq_nmod_mpoly_init(Gc, ctx); fq_nmod_mpoly_init(s, ctx); fq_nmod_mpoly_init(t, ctx); fq_nmod_mpoly_univar_init(Ax, ctx); fq_nmod_mpoly_univar_init(Bx, ctx); fq_nmod_mpoly_univar_init(Gx, ctx); fq_nmod_mpoly_to_univar(Ax, A, var, ctx); fq_nmod_mpoly_to_univar(Bx, B, var, ctx); success = _fq_nmod_mpoly_vec_content_mpoly(Ac, Ax->coeffs, Ax->length, ctx) && _fq_nmod_mpoly_vec_content_mpoly(Bc, Bx->coeffs, Bx->length, ctx) && fq_nmod_mpoly_gcd(Gc, Ac, Bc, ctx); if (!success) goto cleanup; _fq_nmod_mpoly_vec_divexact_mpoly(Ax->coeffs, Ax->length, Ac, ctx); _fq_nmod_mpoly_vec_divexact_mpoly(Bx->coeffs, Bx->length, Bc, ctx); success = fmpz_cmp(Ax->exps + 0, Bx->exps + 0) > 0 ? fq_nmod_mpoly_univar_pseudo_gcd(Gx, Ax, Bx, ctx) : fq_nmod_mpoly_univar_pseudo_gcd(Gx, Bx, Ax, ctx); if (!success) goto cleanup; if (fq_nmod_mpoly_gcd(t, Ax->coeffs + 0, Bx->coeffs + 0, ctx) && t->length == 1) { fq_nmod_mpoly_term_content(s, Gx->coeffs + 0, ctx); fq_nmod_mpoly_divexact(t, Gx->coeffs + 0, s, ctx); _fq_nmod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } else if (fq_nmod_mpoly_gcd(t, Ax->coeffs + Ax->length - 1, Bx->coeffs + Bx->length - 1, ctx) && t->length == 1) { fq_nmod_mpoly_term_content(s, Gx->coeffs + Gx->length - 1, ctx); fq_nmod_mpoly_divexact(t, Gx->coeffs + Gx->length - 1, s, ctx); _fq_nmod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } success = _fq_nmod_mpoly_vec_content_mpoly(t, Gx->coeffs, Gx->length, ctx); if (!success) goto cleanup; _fq_nmod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); _fq_nmod_mpoly_vec_mul_mpoly(Gx->coeffs, Gx->length, Gc, ctx); _fq_nmod_mpoly_from_univar(G, FLINT_MIN(A->bits, B->bits), Gx, var, ctx); fq_nmod_mpoly_make_monic(G, G, ctx); success = 1; cleanup: fq_nmod_mpoly_clear(Ac, ctx); fq_nmod_mpoly_clear(Bc, ctx); fq_nmod_mpoly_clear(Gc, ctx); fq_nmod_mpoly_clear(s, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_univar_clear(Ax, ctx); fq_nmod_mpoly_univar_clear(Bx, ctx); fq_nmod_mpoly_univar_clear(Gx, ctx); return success; } void gcd_check( fq_nmod_mpoly_t g, fq_nmod_mpoly_t a, fq_nmod_mpoly_t b, const fq_nmod_mpoly_t gdiv, fq_nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; fq_nmod_mpoly_t ca, cb, cg; fq_nmod_mpoly_init(ca, ctx); fq_nmod_mpoly_init(cb, ctx); fq_nmod_mpoly_init(cg, ctx); res = compute_gcd(g, a, b, ctx); fq_nmod_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_zero(gdiv, ctx)) { if (!fq_nmod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (fq_nmod_mpoly_is_zero(g, ctx)) { if (!fq_nmod_mpoly_is_zero(a, ctx) || !fq_nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (!_n_fq_is_one(g->coeffs, fq_nmod_ctx_degree(ctx->fqctx))) { flint_printf("FAIL: Check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && fq_nmod_mpoly_divides(ca, a, g, ctx); res = res && fq_nmod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd(cg, ca, cb, ctx); fq_nmod_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!fq_nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(fq_nmod_mpoly_factor_gcd_subresultant, state) { slong i, j, tmul = 15; for (i = 0; i < tmul * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; fq_nmod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; fq_nmod_mpoly_ctx_init_rand(ctx, state, 4, FLINT_BITS, 4); if (fq_nmod_mpoly_ctx_nvars(ctx) < 1) { fq_nmod_mpoly_ctx_clear(ctx); continue; } fq_nmod_mpoly_init(g, ctx); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(b, ctx); fq_nmod_mpoly_init(t, ctx); len = n_randint(state, 10) + 1; len1 = n_randint(state, 10); len2 = n_randint(state, 10); degbound = 1 + 10/ctx->minfo->nvars; for (j = 0; j < 4; j++) { fq_nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (fq_nmod_mpoly_is_zero(t, ctx)) fq_nmod_mpoly_one(t, ctx); fq_nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); fq_nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); fq_nmod_mpoly_mul(a, a, t, ctx); fq_nmod_mpoly_mul(b, b, t, ctx); fq_nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense"); } fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_clear(b, ctx); fq_nmod_mpoly_clear(t, ctx); fq_nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_poly.h000066400000000000000000000023141461254215100162610ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_POLY_H #define FQ_NMOD_POLY_H #ifdef FQ_NMOD_POLY_INLINES_C #define FQ_POLY_TEMPLATES_INLINE #define FQ_NMOD_POLY_INLINE #else #define FQ_POLY_TEMPLATES_INLINE static inline #define FQ_NMOD_POLY_INLINE static inline #endif #include "fq_nmod_types.h" #define FQ_NMOD_POLY_DIVREM_DIVCONQUER_CUTOFF 16 #define FQ_NMOD_COMPOSE_MOD_LENH_CUTOFF 6 #define FQ_NMOD_COMPOSE_MOD_PREINV_LENH_CUTOFF 6 #define FQ_NMOD_MUL_CLASSICAL_CUTOFF 6 #define FQ_NMOD_SQR_CLASSICAL_CUTOFF 6 #define FQ_NMOD_MULLOW_CLASSICAL_CUTOFF 6 #define FQ_NMOD_POLY_HGCD_CUTOFF 25 #define FQ_NMOD_POLY_SMALL_GCD_CUTOFF 110 #define FQ_NMOD_POLY_GCD_CUTOFF 120 #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_nmod_poly/000077500000000000000000000000001461254215100161105ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_poly/inlines.c000066400000000000000000000006641461254215100177230ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_POLY_INLINES_C #include "fq_nmod_poly.h" flint-3.1.3/src/fq_nmod_poly/mul.c000066400000000000000000000031301461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" void _fq_nmod_poly_mul(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) { if (len1 <= 1 || len2 <= 1 || (fq_nmod_ctx_degree(ctx) == 2 && FLINT_MAX(len1, len2) <= 2) || FLINT_BIT_COUNT(fq_nmod_ctx_prime(ctx)) * fq_nmod_ctx_degree(ctx) * FLINT_MAX(len1, len2) <= 8) { _fq_nmod_poly_mul_classical(rop, op1, len1, op2, len2, ctx); } else _fq_nmod_poly_mul_univariate(rop, op1, len1, op2, len2, ctx); } void fq_nmod_poly_mul(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) { slong len1 = fq_nmod_poly_length(op1, ctx); slong len2 = fq_nmod_poly_length(op2, ctx); if (len1 <= 1 || len2 <= 1 || (fq_nmod_ctx_degree(ctx) == 2 && FLINT_MAX(len1, len2) <= 2) || FLINT_BIT_COUNT(fq_nmod_ctx_prime(ctx)) * fq_nmod_ctx_degree(ctx) * FLINT_MAX(len1, len2) <= 8) { fq_nmod_poly_mul_classical(rop, op1, op2, ctx); } else fq_nmod_poly_mul_univariate(rop, op1, op2, ctx); } flint-3.1.3/src/fq_nmod_poly/mul_classical.c000066400000000000000000000047351461254215100211000ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" void _fq_nmod_poly_mul_classical(fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) { if (len1 == 1 && len2 == 1) { fq_nmod_mul(rop, op1, op2, ctx); } else { slong i, j; nmod_poly_t t; nmod_poly_init_mod(t, (rop + 0)->mod); /* Set res[i] = poly1[i]*poly2[0] */ for (j = 0; j < len1; j++) nmod_poly_mul(rop + j, op1 + j, op2 + 0); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ for (j = 0; j < len2 - 1; j++) nmod_poly_mul(rop + len1 + j, op2 + j + 1, op1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len1 - 1; i++) { for (j = 0; j < len2 - 1; j++) { nmod_poly_mul(t, op2 + j + 1, op1 + i); nmod_poly_add(rop + i + j + 1, rop + i + j + 1, t); } } for (i = 0; i < len1 + len2 - 1; i++) fq_nmod_reduce(rop + i, ctx); nmod_poly_clear(t); } } void fq_nmod_poly_mul_classical(fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) { const slong len = op1->length + op2->length - 1; if (op1->length == 0 || op2->length == 0) { fq_nmod_poly_zero(rop, ctx); return; } if (rop == op1 || rop == op2) { fq_nmod_poly_t t; fq_nmod_poly_init2(t, len, ctx); _fq_nmod_poly_mul_classical(t->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx); fq_nmod_poly_swap(rop, t, ctx); fq_nmod_poly_clear(t, ctx); } else { fq_nmod_poly_fit_length(rop, len, ctx); _fq_nmod_poly_mul_classical(rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx); } _fq_nmod_poly_set_length(rop, len, ctx); } flint-3.1.3/src/fq_nmod_poly/mul_univariate.c000066400000000000000000000107261461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2016 Jean-Pierre Flori This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_vec.h" #include "fq_nmod_poly.h" void _fq_nmod_poly_mul_univariate_no_pad (fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) { const slong fqlen = ctx->modulus->length - 1; const slong pfqlen = 2*fqlen - 1; const nmod_t mod = ctx->mod; const slong rlen = len1 + len2 - 1; const slong llen1 = (op1 + (len1 - 1))->length; const slong llen2 = (op2 + (len2 - 1))->length; const slong clen1 = pfqlen*(len1-1) + llen1; const slong clen2 = pfqlen*(len2-1) + llen2; const slong crlen = clen1 + clen2 - 1; const slong lrlen = llen1 + llen2 - 1; slong i; slong len; mp_ptr cop1, cop2, crop; cop1 = (mp_limb_t *) flint_malloc(clen1*sizeof(mp_limb_t)); for (i = 0; i < len1 - 1; i++) { flint_mpn_copyi(cop1 + pfqlen*i, (op1 + i)->coeffs, (op1 + i)->length); flint_mpn_zero(cop1 + pfqlen*i + (op1 + i)->length, pfqlen - (op1 + i)->length); } { flint_mpn_copyi(cop1 + pfqlen*i, (op1 + i)->coeffs, (op1 + i)->length); } if (op2 != op1) { cop2 = (mp_limb_t *) flint_malloc(clen2*sizeof(mp_limb_t)); for (i = 0; i < len2 - 1; i++) { flint_mpn_copyi(cop2 + pfqlen*i, (op2 + i)->coeffs,(op2 + i)->length); flint_mpn_zero(cop2 + pfqlen*i + (op2 + i)->length, pfqlen - (op2 + i)->length); } { flint_mpn_copyi(cop2 + pfqlen*i, (op2 + i)->coeffs, (op2 + i)->length); } } else { cop2 = cop1; } crop = (mp_limb_t *) flint_malloc(crlen*sizeof(mp_limb_t)); if (clen1 >= clen2) _nmod_poly_mul(crop, cop1, clen1, cop2, clen2, mod); else _nmod_poly_mul(crop, cop2, clen2, cop1, clen1, mod); for (i = 0; i < rlen - 1; i++) { _fq_nmod_reduce(crop + pfqlen*i, pfqlen, ctx); len = fqlen; while (len && (*(crop + pfqlen*i + len - 1) == UWORD(0))) len--; nmod_poly_fit_length(rop + i, len); (rop + i)->length = len; flint_mpn_copyi((rop + i)->coeffs, crop + pfqlen*i, len); } { len = lrlen; if (len > fqlen) { _fq_nmod_reduce(crop + pfqlen*i, len, ctx); len = fqlen; while (len && (*(crop + pfqlen*i + len - 1) == UWORD(0))) len--; } nmod_poly_fit_length(rop + i, len); (rop + i)->length = len; flint_mpn_copyi((rop + i)->coeffs, crop + pfqlen*i, len); } flint_free(cop1); if (op2 != op1) { flint_free(cop2); } flint_free(crop); } void _fq_nmod_poly_mul_univariate (fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, const fq_nmod_ctx_t ctx) { slong len1n = len1, len2n = len2; _fq_nmod_poly_normalise2(op1, &len1n, ctx); _fq_nmod_poly_normalise2(op2, &len2n, ctx); if (len1n == 0) _fq_nmod_vec_zero(rop, len1 + len2 - 1, ctx); else if (len2n == 0) _fq_nmod_vec_zero(rop, len1 + len2 - 1, ctx); else { _fq_nmod_poly_mul_univariate_no_pad(rop, op1, len1n, op2, len2n, ctx); _fq_nmod_vec_zero(rop + len1n + len2n - 1, len1 + len2 - len1n - len2n, ctx); } } void fq_nmod_poly_mul_univariate (fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, const fq_nmod_ctx_t ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong rlen = op1->length + op2->length - 1; if (len1 == 0 || len2 == 0) { fq_nmod_poly_zero(rop, ctx); return; } else { fq_nmod_poly_fit_length(rop, rlen, ctx); _fq_nmod_poly_mul_univariate(rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, ctx); _fq_nmod_poly_set_length(rop, rlen, ctx); } } flint-3.1.3/src/fq_nmod_poly/mullow_univariate.c000066400000000000000000000064151461254215100220300ustar00rootroot00000000000000/* Copyright (C) 2016 Jean-Pierre Flori This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" void _fq_nmod_poly_mullow_univariate (fq_nmod_struct * rop, const fq_nmod_struct * op1, slong len1, const fq_nmod_struct * op2, slong len2, slong n, const fq_nmod_ctx_t ctx) { const slong fqlen = ctx->modulus->length - 1; const slong pfqlen = 2*fqlen - 1; const nmod_t mod = ctx->mod; const slong rlen = len1 + len2 - 1; const slong m = FLINT_MIN(n, rlen); const slong cmlen = pfqlen*m; const slong clen1 = pfqlen*len1; const slong clen2 = pfqlen*len2; slong i; slong len; mp_ptr cop1, cop2, crop; if (!len1 || !len2) { _fq_nmod_poly_zero(rop, n, ctx); return; } cop1 = (mp_limb_t *) flint_malloc(clen1*sizeof(mp_limb_t)); for (i = 0; i < len1; i++) { flint_mpn_copyi(cop1 + pfqlen*i, (op1 + i)->coeffs, (op1 + i)->length); flint_mpn_zero(cop1 + pfqlen*i + (op1 + i)->length, pfqlen - (op1 + i)->length); } if (op2 != op1) { cop2 = (mp_limb_t *) flint_malloc(clen2*sizeof(mp_limb_t)); for (i = 0; i < len2; i++) { flint_mpn_copyi(cop2 + pfqlen*i, (op2 + i)->coeffs,(op2 + i)->length); flint_mpn_zero(cop2 + pfqlen*i + (op2 + i)->length, pfqlen - (op2 + i)->length); } } else { cop2 = cop1; } crop = (mp_limb_t *) flint_malloc(cmlen*sizeof(mp_limb_t)); if (clen1 >= clen2) _nmod_poly_mullow(crop, cop1, clen1, cop2, clen2, cmlen, mod); else _nmod_poly_mullow(crop, cop2, clen2, cop1, clen1, cmlen, mod); for (i = 0; i < m; i++) { _fq_nmod_reduce(crop + pfqlen*i, pfqlen, ctx); len = fqlen; while (len && (*(crop + pfqlen*i + len - 1) == UWORD(0))) len--; nmod_poly_fit_length(rop + i, len); (rop + i)->length = len; flint_mpn_copyi((rop + i)->coeffs, crop + pfqlen*i, len); } for (; i < n; i++) { (rop + i)->length = 0; } flint_free(cop1); if (op2 != op1) { flint_free(cop2); } flint_free(crop); } void fq_nmod_poly_mullow_univariate (fq_nmod_poly_t rop, const fq_nmod_poly_t op1, const fq_nmod_poly_t op2, slong n, const fq_nmod_ctx_t ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong rlen = op1->length + op2->length - 1; const slong m = FLINT_MIN(n, rlen); if (len1 == 0 || len2 == 0 || n == 0) { fq_nmod_poly_zero(rop, ctx); return; } else { fq_nmod_poly_fit_length(rop, m, ctx); _fq_nmod_poly_mullow_univariate(rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, m, ctx); _fq_nmod_poly_set_length(rop, m, ctx); _fq_nmod_poly_normalise(rop, ctx); } } flint-3.1.3/src/fq_nmod_poly/profile/000077500000000000000000000000001461254215100175505ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_poly/profile/p-factor_kaltofen_shoup_vs_fq_poly.c000066400000000000000000000066631461254215100270040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" #include "nmod_poly.h" #include "fmpz_poly.h" #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #define nalgs 2 #define ncases 1 #define cpumin 2 int main(int argc, char** argv) { slong s[nalgs]; int c, n, len, ext, reps = 0; slong j; fmpz_t p, temp; fq_poly_t f, g; fq_nmod_poly_t fn; fq_ctx_t ctx; fq_nmod_ctx_t ctxn; fmpz_poly_t fpoly; nmod_poly_t nmod; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); fmpz_set_str(temp, argv[3], 10); len = fmpz_get_si(temp); fq_ctx_init(ctx, p, ext, "a"); fmpz_poly_init(fpoly); nmod_poly_init(nmod, fmpz_get_ui(p)); fmpz_poly_get_nmod_poly(nmod, fpoly); fq_nmod_ctx_init_modulus(ctxn, nmod, "a"); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_nmod_poly_init(fn, ctxn); for (c = 0; c < nalgs; c++) { s[c] = WORD(0); } for (n = 0; n < ncases; n++) { timeit_t t[nalgs]; int l, loops = 1; fq_poly_factor_t res; fq_nmod_poly_factor_t resn; /* Construct random elements of fq */ { fq_poly_randtest_irreducible(f, state, len + 1, ctx); fq_poly_randtest_irreducible(g, state, len + 2, ctx); fq_poly_mul(f, f, g, ctx); fq_poly_make_monic(f, f, ctx); fq_nmod_poly_fit_length(fn, f->length, ctxn); for (j = 0; j < f->length; j++) { fmpz_poly_get_nmod_poly(fn->coeffs + j, f->coeffs + j); } _fq_nmod_poly_set_length(fn, f->length, ctxn); } loop: fflush(stdout); timeit_start(t[0]); for (l = 0; l < loops; l++) { fq_poly_factor_init(res, ctx); fq_poly_factor_kaltofen_shoup(res, f, ctx); fq_poly_factor_clear(res, ctx); } timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) { fq_nmod_poly_factor_init(resn, ctxn); fq_nmod_poly_factor_kaltofen_shoup(resn, fn, ctxn); fq_nmod_poly_factor_clear(resn, ctxn); } timeit_stop(t[1]); for (c = 0; c < nalgs; c++) if (t[c]->cpu <= cpumin) { loops += 2; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]->cpu; reps += loops; } for (c = 0; c < nalgs; c++) { flint_printf("%20f ", s[c] / (double) reps); fflush(stdout); } printf("\n"); fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_nmod_poly_clear(fn, ctxn); nmod_poly_clear(nmod); fq_ctx_clear(ctx); fq_nmod_ctx_clear(ctxn); fmpz_clear(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq_nmod_poly/profile/p-factor_xnpxp1.c000066400000000000000000000011531461254215100227450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/profile/p-factor_xnpxp1.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/profile/p-is_irreducible.c000066400000000000000000000012001461254215100231260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/profile/p-is_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/profile/p-iterated_frobenius.c000066400000000000000000000012261461254215100240270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/profile/p-iterated_frobenius.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/profile/p-iterated_frobenius_table.c000066400000000000000000000012341461254215100251750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/profile/p-iterated_frobenius_table.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/profile/p-mul_univariate.c000066400000000000000000000041251461254215100231770ustar00rootroot00000000000000#include #include "flint.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "profiler.h" #define nalgs 2 #define ncases 10 #define cpumin 2 int main(int argc, char** argv) { double s[nalgs]; int c, n, lenf, leng, ext, reps = 0; ulong p; fmpz_t temp; fq_nmod_poly_t f, g, h; fq_nmod_ctx_t ctx; FLINT_TEST_INIT(state); p = strtoull(argv[1], NULL, 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); lenf = atol(argv[3]); leng = atol(argv[4]); fq_nmod_ctx_init_ui(ctx, p, ext, "a"); fq_nmod_poly_init(f, ctx); fq_nmod_poly_init(g, ctx); fq_nmod_poly_init(h, ctx); for (c = 0; c < nalgs; c++) { s[c] = 0.0; } for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; /* Construct random elements of fq */ { fq_nmod_poly_randtest_monic(f, state, lenf, ctx); fq_nmod_poly_randtest_monic(g, state, leng, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { fq_nmod_poly_mul(h, f, g, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { fq_nmod_poly_mul_univariate(h, f, g, ctx); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { flint_printf("%20f ", s[c] / (double) reps); fflush(stdout); } printf("\n"); fq_nmod_poly_clear(h, ctx); fq_nmod_poly_clear(f, ctx); fq_nmod_poly_clear(g, ctx); fq_nmod_ctx_clear(ctx); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq_nmod_poly/profile/p-mullow.c000066400000000000000000000011271461254215100214710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/profile/p-mullow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/000077500000000000000000000000001461254215100170675ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_poly/test/main.c000066400000000000000000000133721461254215100201650ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_series.c" #include "t-compose.c" #include "t-compose_mod_brent_kung.c" #include "t-compose_mod_brent_kung_preinv.c" #include "t-compose_mod.c" #include "t-compose_mod_horner.c" #include "t-compose_mod_horner_preinv.c" #include "t-compose_mod_preinv.c" #include "t-deflate.c" #include "t-derivative.c" #include "t-div.c" #include "t-divides.c" #include "t-div_newton_n_preinv.c" #include "t-divrem.c" #include "t-divrem_newton_n_preinv.c" #include "t-div_series.c" #include "t-equal_trunc.c" #include "t-evaluate_fq.c" #include "t-evaluate_fq_vec_fast.c" #include "t-gcd.c" #include "t-gcd_euclidean_f.c" #include "t-get_str.c" #include "t-get_str_pretty.c" #include "t-hamming_weight.c" #include "t-inflate.c" #include "t-inv_series_newton.c" #include "t-invsqrt_series.c" #include "t-make_monic.c" #include "t-mul.c" #include "t-mul_classical.c" #include "t-mulhigh.c" #include "t-mulhigh_classical.c" #include "t-mul_KS.c" #include "t-mullow.c" #include "t-mullow_classical.c" #include "t-mullow_KS.c" #include "t-mullow_univariate.c" #include "t-mulmod.c" #include "t-mulmod_preinv.c" #include "t-mul_univariate.c" #include "t-neg.c" #include "t-pow.c" #include "t-powmod_fmpz_binexp.c" #include "t-powmod_fmpz_binexp_preinv.c" #include "t-powmod_fmpz_sliding_preinv.c" #include "t-powmod_ui_binexp.c" #include "t-powmod_ui_binexp_preinv.c" #include "t-powmod_x_fmpz_preinv.c" #include "t-pow_trunc_binexp.c" #include "t-pow_trunc.c" #include "t-randtest_irreducible.c" #include "t-scalar_addmul_fq.c" #include "t-scalar_div_fq.c" #include "t-scalar_mul_fq.c" #include "t-scalar_submul_fq.c" #include "t-set_fmpz_mod_poly.c" #include "t-set_nmod_poly.c" #include "t-set_trunc.c" #include "t-shift_left_right.c" #include "t-sqr.c" #include "t-sqr_classical.c" #include "t-sqr_KS.c" #include "t-sqrt.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-xgcd.c" #include "t-xgcd_euclidean_f.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_poly_add), TEST_FUNCTION(fq_nmod_poly_add_series), TEST_FUNCTION(fq_nmod_poly_compose), TEST_FUNCTION(fq_nmod_poly_compose_mod_brent_kung), TEST_FUNCTION(fq_nmod_poly_compose_mod_brent_kung_preinv), TEST_FUNCTION(fq_nmod_poly_compose_mod), TEST_FUNCTION(fq_nmod_poly_compose_mod_horner), TEST_FUNCTION(fq_nmod_poly_compose_mod_horner_preinv), TEST_FUNCTION(fq_nmod_poly_compose_mod_preinv), TEST_FUNCTION(fq_nmod_poly_deflate), TEST_FUNCTION(fq_nmod_poly_derivative), TEST_FUNCTION(fq_nmod_poly_div), TEST_FUNCTION(fq_nmod_poly_divides), TEST_FUNCTION(fq_nmod_poly_div_newton_n_preinv), TEST_FUNCTION(fq_nmod_poly_divrem), TEST_FUNCTION(fq_nmod_poly_divrem_newton_n_preinv), TEST_FUNCTION(fq_nmod_poly_div_series), TEST_FUNCTION(fq_nmod_poly_equal_trunc), TEST_FUNCTION(fq_nmod_poly_evaluate_fq), TEST_FUNCTION(fq_nmod_poly_evaluate_fq_nmod_vec_fast), TEST_FUNCTION(fq_nmod_poly_gcd), TEST_FUNCTION(fq_nmod_poly_gcd_euclidean_f), TEST_FUNCTION(fq_nmod_poly_get_str), TEST_FUNCTION(fq_nmod_poly_get_str_pretty), TEST_FUNCTION(fq_nmod_poly_hamming_weight), TEST_FUNCTION(fq_nmod_poly_inflate), TEST_FUNCTION(fq_nmod_poly_inv_series_newton), TEST_FUNCTION(fq_nmod_poly_invsqrt_series), TEST_FUNCTION(fq_nmod_poly_make_monic), TEST_FUNCTION(fq_nmod_poly_mul), TEST_FUNCTION(fq_nmod_poly_mul_classical), TEST_FUNCTION(fq_nmod_poly_mulhigh), TEST_FUNCTION(fq_nmod_poly_mulhigh_classical), TEST_FUNCTION(fq_nmod_poly_mul_KS), TEST_FUNCTION(fq_nmod_poly_mullow), TEST_FUNCTION(fq_nmod_poly_mullow_classical), TEST_FUNCTION(fq_nmod_poly_mullow_KS), TEST_FUNCTION(fq_nmod_poly_mullow_univariate), TEST_FUNCTION(fq_nmod_poly_mulmod), TEST_FUNCTION(fq_nmod_poly_mulmod_preinv), TEST_FUNCTION(fq_nmod_poly_mul_univariate), TEST_FUNCTION(fq_nmod_poly_neg), TEST_FUNCTION(fq_nmod_poly_pow), TEST_FUNCTION(fq_nmod_poly_powmod_fmpz_binexp), TEST_FUNCTION(fq_nmod_poly_powmod_fmpz_binexp_preinv), TEST_FUNCTION(fq_nmod_poly_powmod_fmpz_sliding_preinv), TEST_FUNCTION(fq_nmod_poly_powmod_ui_binexp), TEST_FUNCTION(fq_nmod_poly_powmod_ui_binexp_preinv), TEST_FUNCTION(fq_nmod_poly_powmod_x_fmpz_preinv), TEST_FUNCTION(fq_nmod_poly_pow_trunc_binexp), TEST_FUNCTION(fq_nmod_poly_pow_trunc), TEST_FUNCTION(fq_nmod_poly_randtest_irreducible), TEST_FUNCTION(fq_nmod_poly_scalar_addmul_fq), TEST_FUNCTION(fq_nmod_poly_scalar_div_fq), TEST_FUNCTION(fq_nmod_poly_scalar_mul_fq), TEST_FUNCTION(fq_nmod_poly_scalar_submul_fq), TEST_FUNCTION(fq_nmod_poly_set_fmpz_mod_poly), TEST_FUNCTION(fq_nmod_poly_set_nmod_poly), TEST_FUNCTION(fq_nmod_poly_set_trunc), TEST_FUNCTION(fq_nmod_poly_shift_left_right), TEST_FUNCTION(fq_nmod_poly_sqr), TEST_FUNCTION(fq_nmod_poly_sqr_classical), TEST_FUNCTION(fq_nmod_poly_sqr_KS), TEST_FUNCTION(fq_nmod_poly_sqrt), TEST_FUNCTION(fq_nmod_poly_sqrt_series), TEST_FUNCTION(fq_nmod_poly_sub), TEST_FUNCTION(fq_nmod_poly_sub_series), TEST_FUNCTION(fq_nmod_poly_xgcd), TEST_FUNCTION(fq_nmod_poly_xgcd_euclidean_f) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod_poly/test/t-add.c000066400000000000000000000010531461254215100202230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-add_series.c000066400000000000000000000010621461254215100215750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-add_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-compose.c000066400000000000000000000010571461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-compose.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-compose_mod.c000066400000000000000000000010631461254215100220000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-compose_mod.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000010761461254215100242220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-compose_mod_brent_kung.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000011051461254215100255760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-compose_mod_brent_kung_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-compose_mod_horner.c000066400000000000000000000010721461254215100233550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-compose_mod_horner.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-compose_mod_horner_preinv.c000066400000000000000000000011011461254215100247310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-compose_mod_horner_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-compose_mod_preinv.c000066400000000000000000000010721461254215100233630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-compose_mod_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-deflate.c000066400000000000000000000010571461254215100211030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-deflate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-derivative.c000066400000000000000000000010621461254215100216350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-derivative.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-div.c000066400000000000000000000010531461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-div.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-div_newton_n_preinv.c000066400000000000000000000010731461254215100235510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-div_newton_n_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-div_series.c000066400000000000000000000010621461254215100216270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-div_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-divides.c000066400000000000000000000010571461254215100211260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-divides.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-divrem.c000066400000000000000000000010561461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-divrem.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000010761461254215100242600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-divrem_newton_n_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-equal_trunc.c000066400000000000000000000010631461254215100220160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-equal_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-evaluate_fq.c000066400000000000000000000010631461254215100217700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-evaluate_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-evaluate_fq_vec_fast.c000066400000000000000000000012561461254215100236460ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 William Hart Copyright (C) 2011, 2012 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_vec.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-evaluate_fq_vec_fast.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-gcd.c000066400000000000000000000010531461254215100202300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-gcd.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-gcd_euclidean_f.c000066400000000000000000000010671461254215100225530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-gcd_euclidean_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-get_str.c000066400000000000000000000010571461254215100211460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-get_str.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-get_str_pretty.c000066400000000000000000000010661461254215100225550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-get_str_pretty.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-hamming_weight.c000066400000000000000000000010661461254215100224660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-hamming_weight.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-inflate.c000066400000000000000000000010571461254215100211210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-inflate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-inv_series_newton.c000066400000000000000000000010711461254215100232330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-inv_series_newton.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-invsqrt_series.c000066400000000000000000000010661461254215100225570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-invsqrt_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-make_monic.c000066400000000000000000000010621461254215100215750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-make_monic.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mul.c000066400000000000000000000010531461254215100202700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mul_KS.c000066400000000000000000000010561461254215100206700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mul_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mul_classical.c000066400000000000000000000010651461254215100223110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mul_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mul_univariate.c000066400000000000000000000010661461254215100225230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mul_univariate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mulhigh.c000066400000000000000000000010571461254215100211340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mulhigh.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mulhigh_classical.c000066400000000000000000000010711461254215100231460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mulhigh_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mullow.c000066400000000000000000000010561461254215100210150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mullow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mullow_KS.c000066400000000000000000000010611461254215100214060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mullow_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mullow_classical.c000066400000000000000000000010701461254215100230270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mullow_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mullow_univariate.c000066400000000000000000000010711461254215100232410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mullow_univariate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mulmod.c000066400000000000000000000010561461254215100207730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mulmod.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-mulmod_preinv.c000066400000000000000000000010651461254215100223560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-mulmod_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-neg.c000066400000000000000000000010531461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-pow.c000066400000000000000000000010531461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-pow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-pow_trunc.c000066400000000000000000000010611461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-pow_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-pow_trunc_binexp.c000066400000000000000000000010701461254215100230570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-pow_trunc_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000010721461254215100234020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-powmod_fmpz_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000011011461254215100247560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-powmod_fmpz_binexp_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000011021461254215100251230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-powmod_fmpz_sliding_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-powmod_ui_binexp.c000066400000000000000000000010701461254215100230410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-powmod_ui_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000010771461254215100244330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-powmod_ui_binexp_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000010741461254215100237510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-powmod_x_fmpz_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-randtest_irreducible.c000066400000000000000000000011351461254215100236710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-randtest_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-scalar_addmul_fq.c000066400000000000000000000010701461254215100227530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-scalar_addmul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-scalar_div_fq.c000066400000000000000000000010651461254215100222730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-scalar_div_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-scalar_mul_fq.c000066400000000000000000000010651461254215100223060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-scalar_mul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-scalar_submul_fq.c000066400000000000000000000010701461254215100230140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-scalar_submul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-set_fmpz_mod_poly.c000066400000000000000000000042001461254215100232210ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" TEST_FUNCTION_START(fq_nmod_poly_set_fmpz_mod_poly, state) { int i, result; /* Check litfed polynomials by evaluating at random points */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; fq_nmod_ctx_t ctx; fq_nmod_t r, s; fq_nmod_poly_t a; fmpz_mod_poly_t b; fmpz_t p; fmpz_mod_ctx_t ctxp; len = n_randint(state, 15) + 1; fq_nmod_ctx_init_randtest(ctx, state, 0); fq_nmod_init(r, ctx); fq_nmod_init(s, ctx); fq_nmod_poly_init(a, ctx); fmpz_mod_ctx_init_ui(ctxp, fq_nmod_ctx_prime(ctx)); fmpz_mod_poly_init(b, ctxp); fmpz_init(p); fmpz_mod_poly_randtest(b, state, len, ctxp); fmpz_randtest(p, state, 10); fq_nmod_poly_set_fmpz_mod_poly(a, b, ctx); fq_nmod_set_fmpz(r, p, ctx); fq_nmod_poly_evaluate_fq_nmod(r, a, r, ctx); fmpz_mod_poly_evaluate_fmpz(p, b, p, ctxp); fq_nmod_set_fmpz(s, p, ctx); result = fq_nmod_equal(r, s, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"); fq_nmod_ctx_print(ctx); flint_printf("\nb = "); fmpz_mod_poly_print_pretty(b, "X", ctxp); flint_printf("\np = "); fmpz_print(p); flint_printf("\n"); fflush(stdout); flint_abort(); } fq_nmod_clear(r, ctx); fq_nmod_clear(s, ctx); fmpz_mod_poly_clear(b, ctxp); fmpz_mod_ctx_clear(ctxp); fmpz_clear(p); fq_nmod_poly_clear(a, ctx); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_nmod_poly/test/t-set_nmod_poly.c000066400000000000000000000010651461254215100223510ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-set_nmod_poly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-set_trunc.c000066400000000000000000000010611461254215100215000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-set_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-shift_left_right.c000066400000000000000000000010701461254215100230160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-shift_left_right.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-sqr.c000066400000000000000000000010531461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-sqr.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-sqr_KS.c000066400000000000000000000010561461254215100207000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-sqr_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-sqr_classical.c000066400000000000000000000010651461254215100223210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-sqr_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-sqrt.c000066400000000000000000000010541461254215100204650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-sqrt_series.c000066400000000000000000000010631461254215100220370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-sqrt_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-sub.c000066400000000000000000000010531461254215100202640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-sub_series.c000066400000000000000000000010621461254215100216360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-sub_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-xgcd.c000066400000000000000000000010541461254215100204210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-xgcd.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly/test/t-xgcd_euclidean_f.c000066400000000000000000000010701461254215100227350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/test/t-xgcd_euclidean_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor.h000066400000000000000000000021471461254215100176230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_POLY_FACTOR_H #define FQ_NMOD_POLY_FACTOR_H #ifdef FQ_NMOD_POLY_FACTOR_INLINES_C #define FQ_POLY_FACTOR_TEMPLATES_INLINE #define FQ_NMOD_POLY_FACTOR_INLINE #else #define FQ_POLY_FACTOR_TEMPLATES_INLINE static inline #define FQ_NMOD_POLY_FACTOR_INLINE static inline #endif #include "fq_nmod_types.h" int FQ_NMOD_POLY_ITERATED_FROBENIUS_CUTOFF(const fq_nmod_ctx_t ctx, slong length); #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates.h" #undef CAP_T #undef T /* Inlines *******************************************************************/ void fq_nmod_poly_factor_get_poly(fq_nmod_poly_t z, const fq_nmod_poly_factor_t fac, slong i, const fq_nmod_ctx_t ctx); #endif flint-3.1.3/src/fq_nmod_poly_factor/000077500000000000000000000000001461254215100174465ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_poly_factor/inlines.c000066400000000000000000000012641461254215100212560ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_POLY_FACTOR_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" void fq_nmod_poly_factor_get_poly(fq_nmod_poly_t z, const fq_nmod_poly_factor_t fac, slong i, const fq_nmod_ctx_t ctx) { fq_nmod_poly_set(z, fac->poly + i, ctx); } flint-3.1.3/src/fq_nmod_poly_factor/iterated_frobenius_cutoff.c000066400000000000000000000014271461254215100250410ustar00rootroot00000000000000/* Copyright (C) 2023 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_nmod_poly_factor.h" int FQ_NMOD_POLY_ITERATED_FROBENIUS_CUTOFF(const fq_nmod_ctx_t ctx, slong length) { int result; fmpz_t q; fmpz_init(q); fq_nmod_ctx_order(q, ctx); if ( 2 * fmpz_sizeinbase(q, 2) < 3 * (n_sqrt(length) + 1)) result = 1; else result = 0; fmpz_clear(q); return result; } flint-3.1.3/src/fq_nmod_poly_factor/profile/000077500000000000000000000000001461254215100211065ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_poly_factor/profile/p-roots.c000066400000000000000000000042151461254215100226570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "ulong_extras.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "profiler.h" int main(int argc, char *argv[]) { slong i; { ulong p; fq_nmod_ctx_t ctx; fq_nmod_t lc; fq_nmod_poly_t f, g; fq_nmod_poly_factor_t r; flint_rand_t randstate; timeit_t timer; flint_randinit(randstate); p = UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX); p = n_nextprime(p, 1); fq_nmod_ctx_init_ui(ctx, p, 6, "a"); fq_nmod_poly_init(f, ctx); fq_nmod_poly_init(g, ctx); fq_nmod_poly_factor_init(r, ctx); fq_nmod_poly_one(f, ctx); fq_nmod_init(lc, ctx); for (i = 1; i <= 32; i++) { fq_nmod_poly_fit_length(g, 2, ctx); fq_nmod_rand(g->coeffs + 0, randstate, ctx); fq_nmod_rand(g->coeffs + 1, randstate, ctx); if (fq_nmod_is_zero(g->coeffs + 1, ctx)) fq_nmod_one(g->coeffs + 1, ctx); g->length = 2; fq_nmod_poly_mul(f, f, g, ctx); timeit_start(timer); fq_nmod_poly_roots(r, f, 0, ctx); timeit_stop(timer); flint_printf("degree %wd time: %wd %wd", i, timer->wall, timer->wall/i); timeit_start(timer); fq_nmod_poly_factor(r, lc, f, ctx); timeit_stop(timer); flint_printf(" factor time: %wd %wd", timer->wall, timer->wall/i); printf("\n"); } fq_nmod_clear(lc, ctx); fq_nmod_poly_factor_clear(r, ctx); fq_nmod_poly_clear(g, ctx); fq_nmod_poly_clear(f, ctx); fq_nmod_ctx_clear(ctx); flint_randclear(randstate); } flint_cleanup_master(); return 0; } flint-3.1.3/src/fq_nmod_poly_factor/test/000077500000000000000000000000001461254215100204255ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_poly_factor/test/main.c000066400000000000000000000036111461254215100215160ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor_berlekamp.c" #include "t-factor.c" #include "t-factor_cantor_zassenhaus.c" #include "t-factor_distinct_deg.c" #include "t-factor_equal_deg_prob.c" #include "t-factor_kaltofen_shoup.c" #include "t-factor_split_single.c" #include "t-factor_squarefree.c" #include "t-is_irreducible_ben_or.c" #include "t-is_irreducible.c" #include "t-is_irreducible_ddf.c" #include "t-is_squarefree.c" #include "t-iterated_frobenius_preinv.c" #include "t-roots.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_poly_factor_berlekamp), TEST_FUNCTION(fq_nmod_poly_factor), TEST_FUNCTION(fq_nmod_poly_factor_cantor_zassenhaus), TEST_FUNCTION(fq_nmod_poly_factor_distinct_deg), TEST_FUNCTION(fq_nmod_poly_factor_equal_deg_prob), TEST_FUNCTION(fq_nmod_poly_factor_kaltofen_shoup), TEST_FUNCTION(fq_nmod_poly_factor_split_single), TEST_FUNCTION(fq_nmod_poly_factor_squarefree), TEST_FUNCTION(fq_nmod_poly_factor_is_irreducible_ben_or), TEST_FUNCTION(fq_nmod_poly_factor_is_irreducible), TEST_FUNCTION(fq_nmod_poly_factor_is_irreducible_ddf), TEST_FUNCTION(fq_nmod_poly_factor_is_squarefree), TEST_FUNCTION(fq_nmod_poly_factor_iterated_frobenius_preinv), TEST_FUNCTION(fq_nmod_poly_factor_roots) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor.c000066400000000000000000000011261461254215100223100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000011401461254215100243260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor_berlekamp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000011501461254215100261170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor_cantor_zassenhaus.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000011431461254215100250270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor_distinct_deg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000011451461254215100253410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor_equal_deg_prob.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000011451461254215100254120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor_kaltofen_shoup.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor_split_single.c000066400000000000000000000011501461254215100250610ustar00rootroot00000000000000/* Copyright (C) 2019 Edouard Rousseau This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor_split_single.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-factor_squarefree.c000066400000000000000000000011411461254215100245270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-factor_squarefree.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-is_irreducible.c000066400000000000000000000011361461254215100240170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-is_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-is_irreducible_ben_or.c000066400000000000000000000011451461254215100253430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-is_irreducible_ben_or.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000011421461254215100246310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-is_irreducible_ddf.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-is_squarefree.c000066400000000000000000000011351461254215100236670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-is_squarefree.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-iterated_frobenius_preinv.c000066400000000000000000000011511461254215100262700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-iterated_frobenius_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_poly_factor/test/t-roots.c000066400000000000000000000011301461254215100221730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/test/t-roots.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_types.h000066400000000000000000000034301461254215100164420ustar00rootroot00000000000000/* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_TYPES_H #define FQ_NMOD_TYPES_H #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif typedef nmod_poly_t fq_nmod_t; typedef nmod_poly_struct fq_nmod_struct; typedef struct { nmod_t mod; int sparse_modulus; int is_conway; /* whether field was generated using Flint Conway table (assures primitivity */ mp_limb_t *a; slong *j; slong len; nmod_poly_t modulus; nmod_poly_t inv; char *var; } fq_nmod_ctx_struct; typedef fq_nmod_ctx_struct fq_nmod_ctx_t[1]; typedef struct { fq_nmod_struct * entries; slong r; slong c; fq_nmod_struct ** rows; } fq_nmod_mat_struct; typedef fq_nmod_mat_struct fq_nmod_mat_t[1]; typedef struct { fq_nmod_struct * coeffs; slong alloc; slong length; } fq_nmod_poly_struct; typedef fq_nmod_poly_struct fq_nmod_poly_t[1]; typedef struct { fq_nmod_poly_struct * poly; slong * exp; slong num; slong alloc; } fq_nmod_poly_factor_struct; typedef fq_nmod_poly_factor_struct fq_nmod_poly_factor_t[1]; typedef struct { mp_limb_t * coeffs; ulong * exps; slong length; flint_bitcnt_t bits; /* number of bits per exponent */ slong coeffs_alloc; /* abs size in mp_limb_t units */ slong exps_alloc; /* abs size in ulong units */ } fq_nmod_mpoly_struct; typedef fq_nmod_mpoly_struct fq_nmod_mpoly_t[1]; #ifdef __cplusplus } #endif #endif /* FQ_NMOD_TYPES_H */ flint-3.1.3/src/fq_nmod_vec.h000066400000000000000000000027141461254215100160570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_NMOD_VEC_H #define FQ_NMOD_VEC_H #ifdef FQ_NMOD_VEC_INLINES_C #define FQ_VEC_TEMPLATES_INLINE #define FQ_NMOD_VEC_INLINE #else #define FQ_VEC_TEMPLATES_INLINE static inline #define FQ_NMOD_VEC_INLINE static inline #endif #include "fq_nmod_types.h" #define FQ_NMOD_VEC_NORM(vec, i, ctx) \ do { \ while ((i) && fq_nmod_is_zero((vec) + (i) - 1, ctx)) \ (i)--; \ } while (0) #define FQ_NMOD_VEC_SWAP(vec1, len1, vec2, len2) \ do { \ fq_nmod_struct *__t; \ slong __tn; \ __t = (vec1); \ (vec1) = (vec2); \ (vec2) = __t; \ __tn = (len1); \ (len1) = (len2); \ (len2) = __tn; \ } while (0); #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_nmod_vec/000077500000000000000000000000001461254215100157025ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_vec/dot.c000066400000000000000000000017501461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2019 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" #include "fq_nmod_vec.h" void _fq_nmod_vec_dot(fq_nmod_t res, const fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len2, const fq_nmod_ctx_t ctx) { slong i; nmod_poly_t t; if (len2 == 0) { fq_nmod_zero(res, ctx); return; } nmod_poly_init(t, fq_nmod_ctx_prime(ctx)); nmod_poly_mul(res, vec1 + 0, vec2 + 0); for (i = 1; i < len2; i++) { nmod_poly_mul(t, vec1 + i, vec2 + i); nmod_poly_add(res, res, t); } fq_nmod_reduce(res, ctx); nmod_poly_clear(t); } flint-3.1.3/src/fq_nmod_vec/inlines.c000066400000000000000000000006621461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_VEC_INLINES_C #include "fq_nmod_vec.h" flint-3.1.3/src/fq_nmod_vec/test/000077500000000000000000000000001461254215100166615ustar00rootroot00000000000000flint-3.1.3/src/fq_nmod_vec/test/main.c000066400000000000000000000020331461254215100177470ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-is_zero.c" #include "t-neg.c" #include "t-sub.c" #include "t-swap.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_nmod_vec_add), TEST_FUNCTION(fq_nmod_vec_is_zero), TEST_FUNCTION(fq_nmod_vec_neg), TEST_FUNCTION(fq_nmod_vec_sub), TEST_FUNCTION(fq_nmod_vec_swap), TEST_FUNCTION(fq_nmod_vec_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_nmod_vec/test/t-add.c000066400000000000000000000010511461254215100200130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_vec/test/t-is_zero.c000066400000000000000000000010551461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/test/t-is_zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_vec/test/t-neg.c000066400000000000000000000010511461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_vec/test/t-sub.c000066400000000000000000000010511461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_vec/test/t-swap.c000066400000000000000000000010521461254215100202360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/test/t-swap.c" #undef CAP_T #undef T flint-3.1.3/src/fq_nmod_vec/test/t-zero.c000066400000000000000000000010521461254215100202430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/test/t-zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly.h000066400000000000000000000021651461254215100152500ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_POLY_H #define FQ_POLY_H #ifdef FQ_POLY_INLINES_C #define FQ_POLY_INLINE #define FQ_POLY_TEMPLATES_INLINE #else #define FQ_POLY_INLINE static inline #define FQ_POLY_TEMPLATES_INLINE static inline #endif #include "fq_types.h" #define FQ_POLY_DIVREM_DIVCONQUER_CUTOFF 16 #define FQ_COMPOSE_MOD_LENH_CUTOFF 6 #define FQ_COMPOSE_MOD_PREINV_LENH_CUTOFF 6 #define FQ_MUL_CLASSICAL_CUTOFF 6 #define FQ_MULLOW_CLASSICAL_CUTOFF 6 #define FQ_SQR_CLASSICAL_CUTOFF 6 #define FQ_POLY_HGCD_CUTOFF 30 #define FQ_POLY_SMALL_GCD_CUTOFF 80 #define FQ_POLY_GCD_CUTOFF 90 #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_poly/000077500000000000000000000000001461254215100150735ustar00rootroot00000000000000flint-3.1.3/src/fq_poly/inlines.c000066400000000000000000000006521461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_POLY_INLINES_C #include "fq_poly.h" flint-3.1.3/src/fq_poly/mul_classical.c000066400000000000000000000045401461254215100200550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" #include "fq_poly.h" void _fq_poly_mul_classical(fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) { if (len1 == 1 && len2 == 1) { fq_mul(rop, op1, op2, ctx); } else { slong i, j; fmpz_poly_t t; fmpz_poly_init(t); /* Set res[i] = poly1[i]*poly2[0] */ for (j = 0; j < len1; j++) fmpz_poly_mul(rop + j, op1 + j, op2 + 0); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ for (j = 0; j < len2 - 1; j++) fmpz_poly_mul(rop + len1 + j, op2 + j + 1, op1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len1 - 1; i++) { for (j = 0; j < len2 - 1; j++) { fmpz_poly_mul(t, op2 + j + 1, op1 + i); fmpz_poly_add(rop + i + j + 1, rop + i + j + 1, t); } } for (i = 0; i < len1 + len2 - 1; i++) fq_reduce(rop + i, ctx); fmpz_poly_clear(t); } } void fq_poly_mul_classical(fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) { const slong len = op1->length + op2->length - 1; if (op1->length == 0 || op2->length == 0) { fq_poly_zero(rop, ctx); return; } if (rop == op1 || rop == op2) { fq_poly_t t; fq_poly_init2(t, len, ctx); _fq_poly_mul_classical(t->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx); fq_poly_swap(rop, t, ctx); fq_poly_clear(t, ctx); } else { fq_poly_fit_length(rop, len, ctx); _fq_poly_mul_classical(rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx); } _fq_poly_set_length(rop, len, ctx); } flint-3.1.3/src/fq_poly/mul_univariate.c000066400000000000000000000066761461254215100203020ustar00rootroot00000000000000/* Copyright (C) 2016 Jean-Pierre Flori This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fq.h" #include "fq_poly.h" void _fq_poly_mul_univariate (fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, const fq_ctx_t ctx) { const slong fqlen = ctx->modulus->length - 1; const slong pfqlen = 2*fqlen - 1; const slong rlen = len1 + len2 - 1; const slong llen1 = (op1 + (len1 - 1))->length; const slong llen2 = (op2 + (len2 - 1))->length; const slong clen1 = pfqlen*(len1-1) + llen1; const slong clen2 = pfqlen*(len2-1) + llen2; const slong crlen = clen1 + clen2 - 1; const slong lrlen = llen1 + llen2 - 1; slong i; slong len; fmpz *cop1, *cop2, *crop; cop1 = _fmpz_vec_init(clen1); for (i = 0; i < len1 - 1; i++) { _fmpz_vec_set(cop1 + pfqlen*i, (op1 + i)->coeffs, (op1 + i)->length); _fmpz_vec_zero(cop1 + pfqlen*i + (op1 + i)->length, pfqlen - (op1 + i)->length); } { _fmpz_vec_set(cop1 + pfqlen*i, (op1 + i)->coeffs, (op1 + i)->length); } if (op2 != op1) { cop2 = _fmpz_vec_init(clen2); for (i = 0; i < len2 - 1; i++) { _fmpz_vec_set(cop2 + pfqlen*i, (op2 + i)->coeffs,(op2 + i)->length); _fmpz_vec_zero(cop2 + pfqlen*i + (op2 + i)->length, pfqlen - (op2 + i)->length); } { _fmpz_vec_set(cop2 + pfqlen*i, (op2 + i)->coeffs, (op2 + i)->length); } } else { cop2 = cop1; } crop = _fmpz_vec_init(crlen); if (clen1 >= clen2) _fmpz_poly_mul(crop, cop1, clen1, cop2, clen2); else _fmpz_poly_mul(crop, cop2, clen2, cop1, clen1); for (i = 0; i < rlen - 1; i++) { _fq_reduce(crop + pfqlen*i, pfqlen, ctx); len = fqlen; while (len && !(*(crop + pfqlen*i + len - 1))) len--; fmpz_poly_fit_length(rop + i, len); (rop + i)->length = len; _fmpz_vec_set((rop + i)->coeffs, crop + pfqlen*i, len); } { _fq_reduce(crop + pfqlen*i, lrlen, ctx); len = FLINT_MIN(fqlen, lrlen); while (len && !(*(crop + pfqlen*i + len - 1))) len--; fmpz_poly_fit_length(rop + i, len); (rop + i)->length = len; _fmpz_vec_set((rop + i)->coeffs, crop + pfqlen*i, len); } _fmpz_vec_clear(cop1, clen1); if (op2 != op1) { _fmpz_vec_clear(cop2, clen2); } _fmpz_vec_clear(crop, crlen); } void fq_poly_mul_univariate (fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, const fq_ctx_t ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong rlen = op1->length + op2->length - 1; if (len1 == 0 || len2 == 0) { fq_poly_zero(rop, ctx); return; } else { fq_poly_fit_length(rop, rlen, ctx); _fq_poly_mul_univariate(rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, ctx); _fq_poly_set_length(rop, rlen, ctx); } } flint-3.1.3/src/fq_poly/mullow_univariate.c000066400000000000000000000061231461254215100210070ustar00rootroot00000000000000/* Copyright (C) 2016 Jean-Pierre Flori This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fq.h" #include "fq_poly.h" void _fq_poly_mullow_univariate (fq_struct * rop, const fq_struct * op1, slong len1, const fq_struct * op2, slong len2, slong n, const fq_ctx_t ctx) { const slong fqlen = ctx->modulus->length - 1; const slong pfqlen = 2*fqlen - 1; const slong rlen = len1 + len2 - 1; const slong m = FLINT_MIN(n, rlen); const slong cmlen = pfqlen*m; const slong clen1 = pfqlen*len1; const slong clen2 = pfqlen*len2; slong i; slong len; fmpz *cop1, *cop2, *crop; if (!len1 || !len2) { _fq_poly_zero(rop, n, ctx); return; } cop1 = _fmpz_vec_init(clen1); for (i = 0; i < len1; i++) { _fmpz_vec_set(cop1 + pfqlen*i, (op1 + i)->coeffs, (op1 + i)->length); _fmpz_vec_zero(cop1 + pfqlen*i + (op1 + i)->length, pfqlen - (op1 + i)->length); } if (op2 != op1) { cop2 = _fmpz_vec_init(clen2); for (i = 0; i < len2; i++) { _fmpz_vec_set(cop2 + pfqlen*i, (op2 + i)->coeffs,(op2 + i)->length); _fmpz_vec_zero(cop2 + pfqlen*i + (op2 + i)->length, pfqlen - (op2 + i)->length); } } else { cop2 = cop1; } crop = _fmpz_vec_init(cmlen); if (clen1 >= clen2) _fmpz_poly_mullow(crop, cop1, clen1, cop2, clen2, cmlen); else _fmpz_poly_mullow(crop, cop2, clen2, cop1, clen1, cmlen); for (i = 0; i < m; i++) { _fq_reduce(crop + pfqlen*i, pfqlen, ctx); len = fqlen; while (len && !(*(crop + pfqlen*i + len - 1))) len--; fmpz_poly_fit_length(rop + i, len); (rop + i)->length = len; _fmpz_vec_set((rop + i)->coeffs, crop + pfqlen*i, len); } for (; i < n; i++) { (rop + i)->length = 0; } _fmpz_vec_clear(cop1, clen1); if (op2 != op1) { _fmpz_vec_clear(cop2, clen2); } _fmpz_vec_clear(crop, cmlen); } void fq_poly_mullow_univariate (fq_poly_t rop, const fq_poly_t op1, const fq_poly_t op2, slong n, const fq_ctx_t ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong rlen = op1->length + op2->length - 1; const slong m = FLINT_MIN(n, rlen); if (len1 == 0 || len2 == 0 || n == 0) { fq_poly_zero(rop, ctx); return; } else { fq_poly_fit_length(rop, m, ctx); _fq_poly_mullow_univariate(rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, m, ctx); _fq_poly_set_length(rop, m, ctx); _fq_poly_normalise(rop, ctx); } } flint-3.1.3/src/fq_poly/profile/000077500000000000000000000000001461254215100165335ustar00rootroot00000000000000flint-3.1.3/src/fq_poly/profile/p-compose_mod.c000066400000000000000000000046721461254215100214510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fq.h" #include "fq_poly.h" #include "profiler.h" #define nalgs 2 #define cpumin 2 #define ncases 1 int main(int argc, char** argv) { fmpz_t p; int c, n, reps = 0; slong d, lenf, leng, lenh; fq_ctx_t ctx; fq_poly_t f, g, h, res; double s[nalgs]; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); d = atol(argv[2]); lenf = atol(argv[3]); leng = atol(argv[4]); lenh = atol(argv[5]); fq_ctx_init(ctx, p, d, "a"); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_poly_init(h, ctx); fq_poly_init(res, ctx); for (c = 0; c < nalgs; c++) s[c] = 0.0; for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; /* Construct random elements of fq */ { fq_poly_randtest_monic(f, state, lenf, ctx); fq_poly_randtest_monic(g, state, leng, ctx); fq_poly_randtest_monic(h, state, lenh, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) fq_poly_compose_mod_horner(res, f, g, h, ctx); prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) fq_poly_compose_mod_brent_kung(res, f, g, h, ctx); prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { printf("%20f", s[c] / (double) reps); fflush(stdout); } printf("\n"); fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_poly_clear(h, ctx); fq_poly_clear(res, ctx); fq_ctx_clear(ctx); fmpz_clear(p); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq_poly/profile/p-compose_mod_preinv.c000066400000000000000000000051601461254215100230250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fq.h" #include "fq_poly.h" #include "profiler.h" #define nalgs 2 #define cpumin 2 #define ncases 1 int main(int argc, char** argv) { fmpz_t p; int c, n, reps = 0; slong d, lenf, leng, lenh; fq_ctx_t ctx; fq_poly_t f, g, h, hinv, res; double s[nalgs]; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); d = atol(argv[2]); lenf = atol(argv[3]); leng = atol(argv[4]); lenh = atol(argv[5]); fq_ctx_init(ctx, p, d, "a"); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_poly_init(h, ctx); fq_poly_init(hinv, ctx); fq_poly_init(res, ctx); for (c = 0; c < nalgs; c++) s[c] = 0.0; for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; /* Construct random elements of fq */ { fq_poly_randtest_monic(f, state, lenf, ctx); fq_poly_randtest_monic(g, state, leng, ctx); fq_poly_randtest_monic(h, state, lenh, ctx); fq_poly_reverse(hinv, h, h->length, ctx); fq_poly_inv_series_newton(hinv, hinv, h->length, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) fq_poly_compose_mod_horner_preinv(res, f, g, h, hinv, ctx); prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) fq_poly_compose_mod_brent_kung_preinv(res, f, g, h, hinv, ctx); prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { printf("%20f", s[c] / (double) reps); fflush(stdout); } printf("\n"); fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_poly_clear(h, ctx); fq_poly_clear(res, ctx); fq_ctx_clear(ctx); fmpz_clear(p); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq_poly/profile/p-factor_xnpxp1.c000066400000000000000000000011711461254215100217300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/profile/p-factor_xnpxp1.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/profile/p-is_irreducible.c000066400000000000000000000011721461254215100221210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/profile/p-is_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/profile/p-iterated_frobenius.c000066400000000000000000000012201461254215100230040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_mat.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/profile/p-iterated_frobenius.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/profile/p-iterated_frobenius_table.c000066400000000000000000000012261461254215100241610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_mat.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/profile/p-iterated_frobenius_table.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/profile/p-mul_univariate.c000066400000000000000000000040761461254215100221670ustar00rootroot00000000000000#include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_poly.h" #include "profiler.h" #define nalgs 2 #define ncases 10 #define cpumin 2 int main(int argc, char** argv) { double s[nalgs]; int c, n, lenf, leng, ext, reps = 0; fmpz_t p, temp; fq_poly_t f, g, h; fq_ctx_t ctx; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); lenf = atol(argv[3]); leng = atol(argv[4]); fq_ctx_init(ctx, p, ext, "a"); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_poly_init(h, ctx); for (c = 0; c < nalgs; c++) { s[c] = 0.0; } for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; /* Construct random elements of fq */ { fq_poly_randtest_monic(f, state, lenf, ctx); fq_poly_randtest_monic(g, state, leng, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { fq_poly_mul_classical(h, f, g, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { fq_poly_mul_univariate(h, f, g, ctx); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { flint_printf("%20f ", s[c] / (double) reps); fflush(stdout); } printf("\n"); fq_poly_clear(h, ctx); fq_poly_clear(f, ctx); fq_poly_clear(g, ctx); fq_ctx_clear(ctx); fmpz_clear(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq_poly/profile/p-mulmod.c000066400000000000000000000075541461254215100204440ustar00rootroot00000000000000/* Copyright 2010 William Hart Copyright 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fq.h" #include "fq_poly.h" typedef struct { slong n; slong s; slong alg; } info_t; void sample(void *arg, ulong count) { info_t *info = (info_t *) arg; slong n = info->n, i, j, s = info->s, alg = info->alg; slong scale; fq_poly_t a, b, c, d, dinv; fq_ctx_t ctx; FLINT_TEST_INIT(state); fq_ctx_init_randtest(ctx, state, 0); fq_poly_init2(a, n, ctx); fq_poly_init2(b, n, ctx); fq_poly_init2(c, 2 * n - 1, ctx); fq_poly_init2(d, s, ctx); fq_poly_init2(dinv, s, ctx); fq_poly_randtest_monic(a, state, n, ctx); fq_poly_randtest_monic(b, state, n, ctx); fq_poly_randtest_monic(d, state, s, ctx); fq_poly_reverse(dinv, d, s, ctx); fq_poly_inv_series_newton(dinv, dinv, s, ctx); scale = 1; if (n < 100000) scale = 10; if (n < 10000) scale = 100; if (n < 100) scale = 1000; for (i = 0; i < count; i++) { if (alg == 1) { prof_start(); for (j = 0; j < scale; j++) { fq_poly_mulmod_preinv(c, a, b, d, dinv, ctx); } prof_stop(); } else { prof_start(); for (j = 0; j < scale; j++) { fq_poly_mulmod(c, a, b, d, ctx); } prof_stop(); } } fq_poly_clear(a, ctx); fq_poly_clear(b, ctx); fq_poly_clear(c, ctx); fq_poly_clear(d, ctx); fq_poly_clear(dinv, ctx); fq_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); } int main(void) { double min, max; info_t info; slong i, k, scale; for (k = 2; k <= 6; k++) { info.n = 1 << k; for (i = 0; i < 3; i++) { if (i == 0) info.s = info.n / 2; else if (i == 1) info.s = info.n + ((1 << (k + 1)) - (1 << k)) / 2 * i; else if (i == 2) info.s = info.n * 2 - 1; scale = 1; if (info.n < 100000) scale = 10; if (info.n < 10000) scale = 10; if (info.n < 100) scale = 10; info.alg = 1; prof_repeat(&min, &max, sample, (void *) &info); flint_printf ("length %wd, modulus degree %wd, min %.3g ms, max %.3g ms, norm %.3g\n", info.n, info.s, ((min / (double) FLINT_CLOCK_SCALE_FACTOR) / scale) / 2400000.0, ((max / (double) FLINT_CLOCK_SCALE_FACTOR) / scale) / 2400000.0, (((min / (double) FLINT_CLOCK_SCALE_FACTOR) / scale) / 2400000.0) * 500000.0 / info.n / FLINT_BIT_COUNT(info.n)); fflush(stdout); info.alg = 2; prof_repeat(&min, &max, sample, (void *) &info); flint_printf ("length %wd, modulus degree %wd, min %.3g ms, max %.3g ms, norm %.3g\n", info.n, info.s, ((min / (double) FLINT_CLOCK_SCALE_FACTOR) / scale) / 2400000.0, ((max / (double) FLINT_CLOCK_SCALE_FACTOR) / scale) / 2400000.0, (((min / (double) FLINT_CLOCK_SCALE_FACTOR) / scale) / 2400000.0) * 500000.0 / info.n / FLINT_BIT_COUNT(info.n)); fflush(stdout); } } return 0; } flint-3.1.3/src/fq_poly/test/000077500000000000000000000000001461254215100160525ustar00rootroot00000000000000flint-3.1.3/src/fq_poly/test/main.c000066400000000000000000000132411461254215100171430ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_series.c" #include "t-compose.c" #include "t-compose_mod_brent_kung.c" #include "t-compose_mod_brent_kung_preinv.c" #include "t-compose_mod.c" #include "t-compose_mod_horner.c" #include "t-compose_mod_horner_preinv.c" #include "t-compose_mod_preinv.c" #include "t-deflate.c" #include "t-derivative.c" #include "t-div.c" #include "t-divides.c" #include "t-div_newton_n_preinv.c" #include "t-divrem.c" #include "t-divrem_newton_n_preinv.c" #include "t-div_series.c" #include "t-equal_trunc.c" #include "t-evaluate_fq.c" #include "t-evaluate_fq_vec_fast.c" #include "t-gcd.c" #include "t-gcd_euclidean_f.c" #include "t-get_str.c" #include "t-get_str_pretty.c" #include "t-hamming_weight.c" #include "t-inflate.c" #include "t-inv_series_newton.c" #include "t-invsqrt_series.c" #include "t-make_monic.c" #include "t-mul.c" #include "t-mul_classical.c" #include "t-mulhigh.c" #include "t-mulhigh_classical.c" #include "t-mul_KS.c" #include "t-mullow.c" #include "t-mullow_classical.c" #include "t-mullow_KS.c" #include "t-mullow_univariate.c" #include "t-mulmod.c" #include "t-mulmod_preinv.c" #include "t-mul_reorder.c" #include "t-mul_univariate.c" #include "t-neg.c" #include "t-pow.c" #include "t-powmod_fmpz_binexp.c" #include "t-powmod_fmpz_binexp_preinv.c" #include "t-powmod_fmpz_sliding_preinv.c" #include "t-powmod_ui_binexp.c" #include "t-powmod_ui_binexp_preinv.c" #include "t-powmod_x_fmpz_preinv.c" #include "t-pow_trunc_binexp.c" #include "t-pow_trunc.c" #include "t-randtest_irreducible.c" #include "t-scalar_addmul_fq.c" #include "t-scalar_div_fq.c" #include "t-scalar_mul_fq.c" #include "t-scalar_submul_fq.c" #include "t-set_fmpz_mod_poly.c" #include "t-set_nmod_poly.c" #include "t-set_trunc.c" #include "t-shift_left_right.c" #include "t-sqr.c" #include "t-sqr_classical.c" #include "t-sqr_KS.c" #include "t-sqr_reorder.c" #include "t-sqrt.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-xgcd.c" #include "t-xgcd_euclidean_f.c" #include "t-xgcd_euclidean_f_composite_characteristic.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_poly_add), TEST_FUNCTION(fq_poly_add_series), TEST_FUNCTION(fq_poly_compose), TEST_FUNCTION(fq_poly_compose_mod_brent_kung), TEST_FUNCTION(fq_poly_compose_mod_brent_kung_preinv), TEST_FUNCTION(fq_poly_compose_mod), TEST_FUNCTION(fq_poly_compose_mod_horner), TEST_FUNCTION(fq_poly_compose_mod_horner_preinv), TEST_FUNCTION(fq_poly_compose_mod_preinv), TEST_FUNCTION(fq_poly_deflate), TEST_FUNCTION(fq_poly_derivative), TEST_FUNCTION(fq_poly_div), TEST_FUNCTION(fq_poly_divides), TEST_FUNCTION(fq_poly_div_newton_n_preinv), TEST_FUNCTION(fq_poly_divrem), TEST_FUNCTION(fq_poly_divrem_newton_n_preinv), TEST_FUNCTION(fq_poly_div_series), TEST_FUNCTION(fq_poly_equal_trunc), TEST_FUNCTION(fq_poly_evaluate_fq), TEST_FUNCTION(fq_poly_evaluate_fq_vec_fast), TEST_FUNCTION(fq_poly_gcd), TEST_FUNCTION(fq_poly_gcd_euclidean_f), TEST_FUNCTION(fq_poly_get_str), TEST_FUNCTION(fq_poly_get_str_pretty), TEST_FUNCTION(fq_poly_hamming_weight), TEST_FUNCTION(fq_poly_inflate), TEST_FUNCTION(fq_poly_inv_series_newton), TEST_FUNCTION(fq_poly_invsqrt_series), TEST_FUNCTION(fq_poly_make_monic), TEST_FUNCTION(fq_poly_mul), TEST_FUNCTION(fq_poly_mul_classical), TEST_FUNCTION(fq_poly_mulhigh), TEST_FUNCTION(fq_poly_mulhigh_classical), TEST_FUNCTION(fq_poly_mul_KS), TEST_FUNCTION(fq_poly_mullow), TEST_FUNCTION(fq_poly_mullow_classical), TEST_FUNCTION(fq_poly_mullow_KS), TEST_FUNCTION(fq_poly_mullow_univariate), TEST_FUNCTION(fq_poly_mulmod), TEST_FUNCTION(fq_poly_mulmod_preinv), TEST_FUNCTION(fq_poly_mul_reorder), TEST_FUNCTION(fq_poly_mul_univariate), TEST_FUNCTION(fq_poly_neg), TEST_FUNCTION(fq_poly_pow), TEST_FUNCTION(fq_poly_powmod_fmpz_binexp), TEST_FUNCTION(fq_poly_powmod_fmpz_binexp_preinv), TEST_FUNCTION(fq_poly_powmod_fmpz_sliding_preinv), TEST_FUNCTION(fq_poly_powmod_ui_binexp), TEST_FUNCTION(fq_poly_powmod_ui_binexp_preinv), TEST_FUNCTION(fq_poly_powmod_x_fmpz_preinv), TEST_FUNCTION(fq_poly_pow_trunc_binexp), TEST_FUNCTION(fq_poly_pow_trunc), TEST_FUNCTION(fq_poly_randtest_irreducible), TEST_FUNCTION(fq_poly_scalar_addmul_fq), TEST_FUNCTION(fq_poly_scalar_div_fq), TEST_FUNCTION(fq_poly_scalar_mul_fq), TEST_FUNCTION(fq_poly_scalar_submul_fq), TEST_FUNCTION(fq_poly_set_fmpz_mod_poly), TEST_FUNCTION(fq_poly_set_nmod_poly), TEST_FUNCTION(fq_poly_set_trunc), TEST_FUNCTION(fq_poly_shift_left_right), TEST_FUNCTION(fq_poly_sqr), TEST_FUNCTION(fq_poly_sqr_classical), TEST_FUNCTION(fq_poly_sqr_KS), TEST_FUNCTION(fq_poly_sqr_reorder), TEST_FUNCTION(fq_poly_sqrt), TEST_FUNCTION(fq_poly_sqrt_series), TEST_FUNCTION(fq_poly_sub), TEST_FUNCTION(fq_poly_sub_series), TEST_FUNCTION(fq_poly_xgcd), TEST_FUNCTION(fq_poly_xgcd_euclidean_f), TEST_FUNCTION(fq_poly_xgcd_euclidean_f_composite_characteristic) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_poly/test/t-add.c000066400000000000000000000011451461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-add_series.c000066400000000000000000000011541461254215100205620ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-add_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-compose.c000066400000000000000000000011051461254215100201210ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-compose_mod.c000066400000000000000000000010371461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_mod.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000010521461254215100231770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_mod_brent_kung.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000010611461254215100245620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_mod_brent_kung_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-compose_mod_horner.c000066400000000000000000000010461461254215100223410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_mod_horner.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-compose_mod_horner_preinv.c000066400000000000000000000010551461254215100237240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_mod_horner_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-compose_mod_preinv.c000066400000000000000000000010461461254215100223470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_mod_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-deflate.c000066400000000000000000000011041461254215100200570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-deflate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-derivative.c000066400000000000000000000011101461254215100206120ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-derivative.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-div.c000066400000000000000000000011451461254215100172420ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2009 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-div.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-div_newton_n_preinv.c000066400000000000000000000011551461254215100225350ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-div_newton_n_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-div_series.c000066400000000000000000000011541461254215100206140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-div_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-divides.c000066400000000000000000000011051461254215100201030ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-divides.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-divrem.c000066400000000000000000000011041461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-divrem.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000011601461254215100232350ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-divrem_newton_n_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-equal_trunc.c000066400000000000000000000011111461254215100207730ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-equal_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-evaluate_fq.c000066400000000000000000000011111461254215100207450ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-evaluate_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-evaluate_fq_vec_fast.c000066400000000000000000000012251461254215100226250ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 William Hart Copyright (C) 2011, 2012 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-evaluate_fq_vec_fast.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-gcd.c000066400000000000000000000010271461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-gcd.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-gcd_euclidean_f.c000066400000000000000000000010431461254215100215300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-gcd_euclidean_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-get_str.c000066400000000000000000000010331461254215100201230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-get_str.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-get_str_pretty.c000066400000000000000000000010421461254215100215320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-get_str_pretty.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-hamming_weight.c000066400000000000000000000011601461254215100214440ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-hamming_weight.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-inflate.c000066400000000000000000000011041461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-inflate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-inv_series_newton.c000066400000000000000000000011631461254215100222200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-inv_series_newton.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-invsqrt_series.c000066400000000000000000000011601461254215100215350ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-invsqrt_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-make_monic.c000066400000000000000000000011461461254215100205630ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-make_monic.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mul.c000066400000000000000000000011451461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mul_KS.c000066400000000000000000000011501461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mul_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mul_classical.c000066400000000000000000000011571461254215100212760ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mul_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mul_reorder.c000066400000000000000000000011551461254215100210000ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mul_reorder.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mul_univariate.c000066400000000000000000000011601461254215100215010ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mul_univariate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mulhigh.c000066400000000000000000000010331461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mulhigh.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mulhigh_classical.c000066400000000000000000000010451461254215100221320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mulhigh_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mullow.c000066400000000000000000000011041461254215100177720ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mullow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mullow_KS.c000066400000000000000000000011071461254215100203720ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mullow_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mullow_classical.c000066400000000000000000000011161461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mullow_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mullow_univariate.c000066400000000000000000000011171461254215100222250ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mullow_univariate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mulmod.c000066400000000000000000000010321461254215100177500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mulmod.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-mulmod_preinv.c000066400000000000000000000012201461254215100213320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-mulmod_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-neg.c000066400000000000000000000011451461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-pow.c000066400000000000000000000011451461254215100172650ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-pow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-pow_trunc.c000066400000000000000000000011531461254215100204770ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-pow_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-pow_trunc_binexp.c000066400000000000000000000011621461254215100220440ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-pow_trunc_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000010461461254215100223660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-powmod_fmpz_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000010551461254215100237510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-powmod_fmpz_binexp_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000010561461254215100241160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-powmod_fmpz_sliding_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-powmod_ui_binexp.c000066400000000000000000000010441461254215100220250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-powmod_ui_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000010531461254215100234100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-powmod_ui_binexp_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000010501461254215100227260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-powmod_x_fmpz_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-randtest_irreducible.c000066400000000000000000000011041461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-randtest_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-scalar_addmul_fq.c000066400000000000000000000011161461254215100217370ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-scalar_addmul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-scalar_div_fq.c000066400000000000000000000011131461254215100212500ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-scalar_div_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-scalar_mul_fq.c000066400000000000000000000011131461254215100212630ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-scalar_mul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-scalar_submul_fq.c000066400000000000000000000011161461254215100220000ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-scalar_submul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-set_fmpz_mod_poly.c000066400000000000000000000036531461254215100222170ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_poly.h" TEST_FUNCTION_START(fq_poly_set_fmpz_mod_poly, state) { int i, result; /* Check litfed polynomials by evaluating at random points */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; fq_ctx_t ctx; fq_t r, s; fq_poly_t a; fmpz_mod_poly_t b; fmpz_t p; len = n_randint(state, 15) + 1; fq_ctx_init_randtest(ctx, state, 0); fq_init(r, ctx); fq_init(s, ctx); fq_poly_init(a, ctx); fmpz_mod_poly_init(b, ctx->ctxp); fmpz_init(p); fmpz_mod_poly_randtest(b, state, len, ctx->ctxp); fmpz_randtest(p, state, 10); fq_poly_set_fmpz_mod_poly(a, b, ctx); fq_set_fmpz(r, p, ctx); fq_poly_evaluate_fq(r, a, r, ctx); fmpz_mod_poly_evaluate_fmpz(p, b, p, ctx->ctxp); fq_set_fmpz(s, p, ctx); result = fq_equal(r, s, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"); fq_ctx_print(ctx); flint_printf("\nb = "); fmpz_mod_poly_print_pretty(b, "X", ctx->ctxp); flint_printf("\np = "); fmpz_print(p); flint_printf("\n"); fflush(stdout); flint_abort(); } fq_clear(r, ctx); fq_clear(s, ctx); fmpz_mod_poly_clear(b, ctx->ctxp); fmpz_clear(p); fq_poly_clear(a, ctx); fq_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_poly/test/t-set_nmod_poly.c000066400000000000000000000010701461254215100213300ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-set_nmod_poly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-set_trunc.c000066400000000000000000000011071461254215100204640ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-set_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-shift_left_right.c000066400000000000000000000011621461254215100220030ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-shift_left_right.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sqr.c000066400000000000000000000011451461254215100172650ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sqr.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sqr_KS.c000066400000000000000000000011501461254215100176560ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sqr_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sqr_classical.c000066400000000000000000000011571461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sqr_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sqr_reorder.c000066400000000000000000000011551461254215100210100ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sqr_reorder.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sqrt.c000066400000000000000000000011461461254215100174520ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sqrt_series.c000066400000000000000000000011551461254215100210240ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sqrt_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sub.c000066400000000000000000000011451461254215100172510ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-sub_series.c000066400000000000000000000011541461254215100206230ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-sub_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-xgcd.c000066400000000000000000000010301461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-xgcd.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-xgcd_euclidean_f.c000066400000000000000000000010441461254215100217210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-xgcd_euclidean_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly/test/t-xgcd_euclidean_f_composite_characteristic.c000066400000000000000000000062531461254215100270620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_poly.h" TEST_FUNCTION_START(fq_poly_xgcd_euclidean_f_composite_characteristic, state) { slong i, j; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; fmpz_mod_poly_t h; fq_ctx_t ctx; fq_poly_t a, b, g, s, t, t1, t2; fq_t f; fmpz_mod_ctx_t ctxp; fmpz_mod_ctx_init_ui(ctxp, 2 + n_randint(state, 200)); fmpz_mod_poly_init(h, ctxp); fmpz_mod_poly_set_coeff_ui(h, 2, 1, ctxp); fmpz_mod_poly_set_coeff_ui(h, 1, 1, ctxp); fmpz_mod_poly_set_coeff_ui(h, 0, 1, ctxp); fq_ctx_init_modulus(ctx, h, ctxp, "t"); fq_poly_init(a, ctx); fq_poly_init(b, ctx); fq_poly_init(g, ctx); fq_poly_init(s, ctx); fq_poly_init(t, ctx); fq_poly_init(t1, ctx); fq_poly_init(t2, ctx); fq_init(f, ctx); for (j = 0; j < 10; j++) { fq_poly_randtest(a, state, n_randint(state, 10), ctx); fq_poly_randtest(b, state, n_randint(state, 10), ctx); fq_poly_xgcd_euclidean_f(f, g, s, t, a, b, ctx); if (fq_is_one(f, ctx)) { fq_poly_mul(t1, s, a, ctx); fq_poly_mul(t2, t, b, ctx); fq_poly_add(t1, t1, t2, ctx); if (!fq_poly_equal(t1, g, ctx)) { flint_printf("FAIL:\n"); flint_printf("p: "); fmpz_print(p); flint_printf("\n"); flint_printf("h: "); fmpz_mod_poly_print_pretty(h, "t", ctxp); flint_printf("\n"); flint_printf("f: "); fq_print_pretty(f, ctx); flint_printf("\n"); flint_printf("a: "); fq_poly_print_pretty(a, "x", ctx); flint_printf("\n"); flint_printf("b: "); fq_poly_print_pretty(b, "x", ctx); flint_printf("\n"); flint_printf("s: "); fq_poly_print_pretty(s, "x", ctx); flint_printf("\n"); flint_printf("t: "); fq_poly_print_pretty(t, "x", ctx); flint_printf("\n"); flint_printf("g: "); fq_poly_print_pretty(g, "x", ctx); flint_printf("\n"); flint_printf("s*a+t*b: "); fq_poly_print_pretty(t1, "x", ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } } fmpz_mod_poly_clear(h, ctxp); fmpz_mod_ctx_clear(ctxp); fq_poly_clear(a, ctx); fq_poly_clear(b, ctx); fq_poly_clear(g, ctx); fq_poly_clear(s, ctx); fq_poly_clear(t, ctx); fq_poly_clear(t1, ctx); fq_poly_clear(t2, ctx); fq_clear(f, ctx); fq_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_poly_factor.h000066400000000000000000000020351461254215100166020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_POLY_FACTOR_H #define FQ_POLY_FACTOR_H #ifdef FQ_POLY_FACTOR_INLINES_C #define FQ_POLY_FACTOR_TEMPLATES_INLINE #define FQ_POLY_FACTOR_INLINE #else #define FQ_POLY_FACTOR_TEMPLATES_INLINE static inline #define FQ_POLY_FACTOR_INLINE static inline #endif #include "fq_types.h" int FQ_POLY_ITERATED_FROBENIUS_CUTOFF(const fq_ctx_t ctx, slong length); #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates.h" #undef CAP_T #undef T /* Inlines *******************************************************************/ void fq_poly_factor_get_poly(fq_poly_t z, const fq_poly_factor_t fac, slong i, const fq_ctx_t ctx); #endif flint-3.1.3/src/fq_poly_factor/000077500000000000000000000000001461254215100164315ustar00rootroot00000000000000flint-3.1.3/src/fq_poly_factor/inlines.c000066400000000000000000000011641461254215100202400ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fq.h" #include "fq_poly.h" void fq_poly_factor_get_poly(fq_poly_t z, const fq_poly_factor_t fac, slong i, const fq_ctx_t ctx) { fq_poly_set(z, fac->poly + i, ctx); } flint-3.1.3/src/fq_poly_factor/iterated_frobenius_cutoff.c000066400000000000000000000013721461254215100240230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_poly_factor.h" int FQ_POLY_ITERATED_FROBENIUS_CUTOFF(const fq_ctx_t ctx, slong length) { int result; fmpz_t q; fmpz_init(q); fq_ctx_order(q, ctx); if ( fmpz_sizeinbase(q, 2) < 3 * (n_sqrt(length) + 1)) result = 1; else result = 0; fmpz_clear(q); return result; } flint-3.1.3/src/fq_poly_factor/test/000077500000000000000000000000001461254215100174105ustar00rootroot00000000000000flint-3.1.3/src/fq_poly_factor/test/main.c000066400000000000000000000035031461254215100205010ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor_berlekamp.c" #include "t-factor.c" #include "t-factor_cantor_zassenhaus.c" #include "t-factor_distinct_deg.c" #include "t-factor_equal_deg_prob.c" #include "t-factor_kaltofen_shoup.c" #include "t-factor_split_single.c" #include "t-factor_squarefree.c" #include "t-is_irreducible_ben_or.c" #include "t-is_irreducible.c" #include "t-is_irreducible_ddf.c" #include "t-is_squarefree.c" #include "t-iterated_frobenius_preinv.c" #include "t-roots.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_poly_factor_berlekamp), TEST_FUNCTION(fq_poly_factor), TEST_FUNCTION(fq_poly_factor_cantor_zassenhaus), TEST_FUNCTION(fq_poly_factor_distinct_deg), TEST_FUNCTION(fq_poly_factor_equal_deg_prob), TEST_FUNCTION(fq_poly_factor_kaltofen_shoup), TEST_FUNCTION(fq_poly_factor_split_single), TEST_FUNCTION(fq_poly_factor_squarefree), TEST_FUNCTION(fq_poly_factor_is_irreducible_ben_or), TEST_FUNCTION(fq_poly_factor_is_irreducible), TEST_FUNCTION(fq_poly_factor_is_irreducible_ddf), TEST_FUNCTION(fq_poly_factor_is_squarefree), TEST_FUNCTION(fq_poly_factor_iterated_frobenius_preinv), TEST_FUNCTION(fq_poly_factor_roots) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_poly_factor/test/t-factor.c000066400000000000000000000013531461254215100212750ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000011071461254215100233140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor_berlekamp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000011171461254215100251050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor_cantor_zassenhaus.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000011121461254215100240060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor_distinct_deg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000011141461254215100243200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor_equal_deg_prob.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000011141461254215100243710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor_kaltofen_shoup.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-factor_split_single.c000066400000000000000000000011171461254215100240470ustar00rootroot00000000000000/* Copyright (C) 2019 Edouard Rousseau This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor_split_single.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-factor_squarefree.c000066400000000000000000000011101461254215100235060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-factor_squarefree.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-is_irreducible.c000066400000000000000000000011051461254215100227760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-is_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-is_irreducible_ben_or.c000066400000000000000000000011141461254215100243220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-is_irreducible_ben_or.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000011111461254215100236100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-is_irreducible_ddf.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-is_squarefree.c000066400000000000000000000011041461254215100226460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-is_squarefree.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-iterated_frobenius_preinv.c000066400000000000000000000011201461254215100252470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-iterated_frobenius_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor/test/t-roots.c000066400000000000000000000010771461254215100211700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_poly.h" #include "fq_poly_factor.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/test/t-roots.c" #undef CAP_T #undef T flint-3.1.3/src/fq_poly_factor_templates.h000066400000000000000000000145011461254215100206610ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #ifdef __cplusplus extern "C" { #endif void TEMPLATE(T, poly_factor_init)(TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_clear)(TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_realloc)(TEMPLATE(T, poly_factor_t) fac, slong alloc, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_fit_length)(TEMPLATE(T, poly_factor_t) fac, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_set)(TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_insert)(TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, poly_t) poly, slong exp, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_print)(const TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_print_pretty)(const TEMPLATE(T, poly_factor_t) fac, const char * var, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_concat)(TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_pow)(TEMPLATE(T, poly_factor_t) fac, slong exp, const TEMPLATE(T, ctx_t) ctx); int _TEMPLATE(T, poly_is_squarefree)(const TEMPLATE(T, struct) * f, slong len, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_is_squarefree)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_squarefree)(TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_is_irreducible)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_is_irreducible_ddf)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_is_irreducible_ben_or)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_distinct_deg)(TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) poly, slong * const *degs, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_factor_equal_deg_prob)(TEMPLATE(T, poly_t) factor, flint_rand_t state, const TEMPLATE(T, poly_t) pol, slong d, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_equal_deg)(TEMPLATE(T, poly_factor_t) factors, const TEMPLATE(T, poly_t) pol, slong d, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_cantor_zassenhaus)(TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_kaltofen_shoup)(TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_berlekamp)(TEMPLATE(T, poly_factor_t) factors, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_with_berlekamp)(TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_with_cantor_zassenhaus)( TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_with_kaltofen_shoup)(TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor)(TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_iterated_frobenius_preinv)(TEMPLATE(T, poly_t)* rop, slong n, const TEMPLATE(T, poly_t) v, const TEMPLATE(T, poly_t) vinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_factor_split_single)(TEMPLATE(T, poly_t) linfactor, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_roots)(TEMPLATE(T, poly_factor_t) r, const TEMPLATE(T, poly_t) f, int with_multiplicity, const TEMPLATE(T, ctx_t) ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_poly_factor_templates/000077500000000000000000000000001461254215100205075ustar00rootroot00000000000000flint-3.1.3/src/fq_poly_factor_templates/clear.c000066400000000000000000000016741461254215100217510ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" void TEMPLATE(T, poly_factor_clear) (TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < fac->alloc; i++) { TEMPLATE(T, poly_clear) (fac->poly + i, ctx); } flint_free(fac->poly); flint_free(fac->exp); } #endif flint-3.1.3/src/fq_poly_factor_templates/concat.c000066400000000000000000000017151461254215100221260ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_concat) (TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < fac->num; i++) TEMPLATE(T, poly_factor_insert) (res, fac->poly + i, fac->exp[i], ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/factor.c000066400000000000000000000164321461254215100221370ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #define ZASSENHAUS 0 #define BERLEKAMP 1 #define KALTOFEN 2 static inline void __TEMPLATE(T, poly_factor1) (TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) f, int algorithm, const TEMPLATE(T, ctx_t) ctx) { if (algorithm == KALTOFEN) TEMPLATE(T, poly_factor_kaltofen_shoup) (res, f, ctx); else if (algorithm == ZASSENHAUS) TEMPLATE(T, poly_factor_cantor_zassenhaus) (res, f, ctx); else TEMPLATE(T, poly_factor_berlekamp) (res, f, ctx); } void __TEMPLATE(T, poly_factor) (TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, int algorithm, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) monic_input; TEMPLATE(T, poly_factor_t) sqfree_factors, factors; slong i, len; len = input->length; if (len <= 1) { if (len == 0) { TEMPLATE(T, zero) (leading_coeff, ctx); return; } else { TEMPLATE(T, set) (leading_coeff, input->coeffs, ctx); } } TEMPLATE(T, poly_get_coeff) (leading_coeff, input, TEMPLATE(T, poly_degree) (input, ctx), ctx); TEMPLATE(T, poly_init) (monic_input, ctx); TEMPLATE(T, poly_make_monic) (monic_input, input, ctx); if (len == 2) { TEMPLATE(T, poly_factor_insert) (result, monic_input, 1, ctx); TEMPLATE(T, poly_clear) (monic_input, ctx); TEMPLATE(T, set) (leading_coeff, input->coeffs + 1, ctx); return; } TEMPLATE(T, poly_factor_init) (sqfree_factors, ctx); TEMPLATE(T, poly_factor_squarefree) (sqfree_factors, monic_input, ctx); TEMPLATE(T, poly_clear) (monic_input, ctx); /* Run CZ on each of the square-free factors */ for (i = 0; i < sqfree_factors->num; i++) { TEMPLATE(T, poly_factor_init) (factors, ctx); __TEMPLATE(T, poly_factor1) (factors, sqfree_factors->poly + i, algorithm, ctx); TEMPLATE(T, poly_factor_pow) (factors, sqfree_factors->exp[i], ctx); TEMPLATE(T, poly_factor_concat) (result, factors, ctx); TEMPLATE(T, poly_factor_clear) (factors, ctx); } TEMPLATE(T, poly_factor_clear) (sqfree_factors, ctx); return; } void __TEMPLATE(T, poly_factor_deflation) (TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, int algorithm, const TEMPLATE(T, ctx_t) ctx) { slong i; ulong deflation; if (input->length <= 1) { if (input->length == 0) { TEMPLATE(T, zero) (leading_coeff, ctx); return; } else { TEMPLATE(T, set) (leading_coeff, input->coeffs, ctx); return; } } deflation = TEMPLATE(T, poly_deflation) (input, ctx); if (deflation == 1) { __TEMPLATE(T, poly_factor) (result, leading_coeff, input, algorithm, ctx); return; } else { TEMPLATE(T, poly_factor_t) def_res; TEMPLATE(T, poly_t) def; TEMPLATE(T, t) lc_dummy; TEMPLATE(T, init) (lc_dummy, ctx); TEMPLATE(T, poly_init) (def, ctx); TEMPLATE(T, poly_deflate) (def, input, deflation, ctx); TEMPLATE(T, poly_factor_init) (def_res, ctx); __TEMPLATE(T, poly_factor) (def_res, leading_coeff, def, algorithm, ctx); TEMPLATE(T, poly_clear) (def, ctx); for (i = 0; i < def_res->num; i++) { /* Inflate */ TEMPLATE(T, poly_t) pol; TEMPLATE(T, poly_init) (pol, ctx); TEMPLATE(T, poly_inflate) (pol, def_res->poly + i, deflation, ctx); /* Factor inflation */ if (def_res->exp[i] == 1) __TEMPLATE(T, poly_factor) (result, lc_dummy, pol, algorithm, ctx); else { TEMPLATE(T, poly_factor_t) t; TEMPLATE(T, poly_factor_init) (t, ctx); __TEMPLATE(T, poly_factor) (t, lc_dummy, pol, algorithm, ctx); TEMPLATE(T, poly_factor_pow) (t, def_res->exp[i], ctx); TEMPLATE(T, poly_factor_concat) (result, t, ctx); TEMPLATE(T, poly_factor_clear) (t, ctx); } TEMPLATE(T, poly_clear) (pol, ctx); } TEMPLATE(T, clear) (lc_dummy, ctx); TEMPLATE(T, poly_factor_clear) (def_res, ctx); } } void TEMPLATE(T, poly_factor_with_berlekamp) (TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx) { __TEMPLATE(T, poly_factor_deflation) (result, leading_coeff, input, BERLEKAMP, ctx); } void TEMPLATE(T, poly_factor_with_cantor_zassenhaus) ( TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx) { __TEMPLATE(T, poly_factor_deflation) (result, leading_coeff, input, ZASSENHAUS, ctx); } void TEMPLATE(T, poly_factor_with_kaltofen_shoup) ( TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx) { __TEMPLATE(T, poly_factor_deflation) (result, leading_coeff, input, KALTOFEN, ctx); } void TEMPLATE(T, poly_factor) (TEMPLATE(T, poly_factor_t) result, TEMPLATE(T, t) leading_coeff, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx) { #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) flint_bitcnt_t bits = FLINT_BIT_COUNT(TEMPLATE(T, ctx_prime)(ctx)); #else flint_bitcnt_t bits = fmpz_bits(TEMPLATE(T, ctx_prime)(ctx)); #endif slong n = TEMPLATE(T, poly_degree) (input, ctx); result->num = 0; if (n < 10 + 50 / bits) __TEMPLATE(T, poly_factor_deflation) (result, leading_coeff, input, ZASSENHAUS, ctx); else __TEMPLATE(T, poly_factor_deflation) (result, leading_coeff, input, KALTOFEN, ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_berlekamp.c000066400000000000000000000230411461254215100241530ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "perm.h" static void TEMPLATE(T, to_mat_col) (TEMPLATE(T, mat_t) mat, slong col, TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < poly->length; i++) TEMPLATE(T, set) (TEMPLATE(T, mat_entry) (mat, i, col), poly->coeffs + i, ctx); for (; i < mat->r; i++) TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (mat, i, col), ctx); } static void TEMPLATE(T, mat_col_to_shifted) (TEMPLATE(T, poly_t) poly, TEMPLATE(T, mat_t) mat, slong col, slong * shift, const TEMPLATE(T, ctx_t) ctx) { slong i, j, rows = mat->r; TEMPLATE(T, poly_fit_length) (poly, rows, ctx); for (i = 0, j = 0; j < rows; j++) { if (shift[j]) TEMPLATE(T, zero) (poly->coeffs + j, ctx); else { TEMPLATE(T, set) (poly->coeffs + j, TEMPLATE(T, mat_entry) (mat, i, col), ctx); i++; } } _TEMPLATE(T, poly_set_length) (poly, rows, ctx); _TEMPLATE(T, poly_normalise) (poly, ctx); } static void __TEMPLATE(T, poly_factor_berlekamp) (TEMPLATE(T, poly_factor_t) factors, flint_rand_t state, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { const slong n = TEMPLATE(T, poly_degree) (f, ctx); TEMPLATE(T, poly_factor_t) fac1, fac2; TEMPLATE(T, poly_t) x, x_q; TEMPLATE(T, poly_t) x_qi, x_qi2; TEMPLATE(T, poly_t) Q, r; TEMPLATE(T, mat_t) matrix; TEMPLATE(T, t) mul, coeff, neg_one; fmpz_t q, s, pow; slong i, nullity, col, row; slong *shift; TEMPLATE(T, poly_t) * basis; if (f->length <= 2) { TEMPLATE(T, poly_factor_insert) (factors, f, 1, ctx); return; } TEMPLATE(T, init) (coeff, ctx); TEMPLATE(T, init) (neg_one, ctx); TEMPLATE(T, init) (mul, ctx); fmpz_init(q); TEMPLATE(T, ctx_order) (q, ctx); TEMPLATE(T, one) (neg_one, ctx); TEMPLATE(T, neg) (neg_one, neg_one, ctx); /* s = q - 1 */ fmpz_init_set(s, q); fmpz_sub_ui(s, s, 1); /* pow = (q-1)/2 */ fmpz_init(pow); #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) if (TEMPLATE(T, ctx_prime)(ctx) > UWORD(3)) { #else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 3) > 0) { #endif fmpz_set(pow, s); fmpz_divexact_ui(pow, pow, 2); } /* Step 1, compute x^q mod f in F_p[X]/ */ TEMPLATE(T, poly_init) (x, ctx); TEMPLATE(T, poly_init) (x_q, ctx); TEMPLATE(T, poly_gen) (x, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (x_q, x, q, f, ctx); TEMPLATE(T, poly_clear) (x, ctx); /* Step 2, compute the matrix for the Berlekamp Map */ TEMPLATE(T, mat_init) (matrix, n, n, ctx); TEMPLATE(T, poly_init) (x_qi, ctx); TEMPLATE(T, poly_init) (x_qi2, ctx); TEMPLATE(T, poly_one) (x_qi, ctx); for (i = 0; i < n; i++) { /* Q - I */ TEMPLATE(T, poly_set) (x_qi2, x_qi, ctx); TEMPLATE(T, poly_get_coeff) (coeff, x_qi2, i, ctx); TEMPLATE(T, sub_one) (coeff, coeff, ctx); TEMPLATE(T, poly_set_coeff) (x_qi2, i, coeff, ctx); TEMPLATE(T, to_mat_col) (matrix, i, x_qi2, ctx); TEMPLATE(T, poly_mulmod) (x_qi, x_qi, x_q, f, ctx); } TEMPLATE(T, poly_clear) (x_q, ctx); TEMPLATE(T, poly_clear) (x_qi, ctx); TEMPLATE(T, poly_clear) (x_qi2, ctx); /* Row reduce Q - I */ nullity = n - TEMPLATE(T, mat_rref) (matrix, matrix, ctx); /* Find a basis for the nullspace */ basis = flint_malloc(nullity * sizeof(TEMPLATE(T, poly_t))); shift = (slong *) flint_calloc(n, sizeof(slong)); col = 1; /* first column is always zero */ row = 0; shift[0] = 1; for (i = 1; i < nullity; i++) { TEMPLATE(T, poly_init) (basis[i], ctx); while (!TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (matrix, row, col), ctx)) { row++; col++; } TEMPLATE(T, mat_col_to_shifted) (basis[i], matrix, col, shift, ctx); TEMPLATE(T, poly_set_coeff) (basis[i], col, neg_one, ctx); shift[col] = 1; col++; } flint_free(shift); TEMPLATE(T, mat_clear) (matrix, ctx); /* we are done */ if (nullity == 1) { TEMPLATE(T, poly_factor_insert) (factors, f, 1, ctx); } else { /* Generate random linear combinations */ TEMPLATE(T, poly_t) factor, b, power, g; TEMPLATE(T, poly_init) (factor, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (power, ctx); TEMPLATE(T, poly_init) (g, ctx); while (1) { do { TEMPLATE(T, poly_zero) (factor, ctx); for (i = 1; i < nullity; i++) { TEMPLATE(T, randtest) (mul, state, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (b, basis[i], mul, ctx); TEMPLATE(T, poly_add) (factor, factor, b, ctx); } TEMPLATE(T, randtest) (coeff, state, ctx); TEMPLATE(T, poly_set_coeff) (factor, 0, coeff, ctx); if (!TEMPLATE(T, poly_is_zero) (factor, ctx)) TEMPLATE(T, poly_make_monic) (factor, factor, ctx); } while (TEMPLATE(T, poly_is_zero) (factor, ctx) || (factor->length < 2 && TEMPLATE(T, is_one) (factor->coeffs, ctx))); TEMPLATE(T, poly_gcd) (g, f, factor, ctx); if (TEMPLATE(T, poly_length) (g, ctx) != 1) break; #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) if (TEMPLATE(T, ctx_prime)(ctx) > UWORD(3)) #else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 3) > 0) #endif TEMPLATE(T, poly_powmod_fmpz_binexp) (power, factor, pow, f, ctx); else TEMPLATE(T, poly_set) (power, factor, ctx); TEMPLATE(T, sub_one) (power->coeffs, power->coeffs, ctx); _TEMPLATE(T, poly_normalise) (power, ctx); TEMPLATE(T, poly_gcd) (g, power, f, ctx); if (TEMPLATE(T, poly_length) (g, ctx) != 1) break; } TEMPLATE(T, poly_clear) (power, ctx); TEMPLATE(T, poly_clear) (factor, ctx); TEMPLATE(T, poly_clear) (b, ctx); if (!TEMPLATE(T, poly_is_zero) (g, ctx)) TEMPLATE(T, poly_make_monic) (g, g, ctx); TEMPLATE(T, poly_factor_init) (fac1, ctx); TEMPLATE(T, poly_factor_init) (fac2, ctx); __TEMPLATE(T, poly_factor_berlekamp) (fac1, state, g, ctx); TEMPLATE(T, poly_init) (Q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_divrem) (Q, r, f, g, ctx); TEMPLATE(T, poly_clear) (r, ctx); if (!TEMPLATE(T, poly_is_zero) (Q, ctx)) TEMPLATE(T, poly_make_monic) (Q, Q, ctx); __TEMPLATE(T, poly_factor_berlekamp) (fac2, state, Q, ctx); TEMPLATE(T, poly_factor_concat) (factors, fac1, ctx); TEMPLATE(T, poly_factor_concat) (factors, fac2, ctx); TEMPLATE(T, poly_factor_clear) (fac1, ctx); TEMPLATE(T, poly_factor_clear) (fac2, ctx); TEMPLATE(T, poly_clear) (Q, ctx); TEMPLATE(T, poly_clear) (g, ctx); } for (i = 1; i < nullity; i++) TEMPLATE(T, poly_clear) (basis[i], ctx); flint_free(basis); TEMPLATE(T, clear) (coeff, ctx); TEMPLATE(T, clear) (neg_one, ctx); TEMPLATE(T, clear) (mul, ctx); fmpz_clear(pow); fmpz_clear(q); fmpz_clear(s); } void TEMPLATE(T, poly_factor_berlekamp) (TEMPLATE(T, poly_factor_t) factors, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { slong i; flint_rand_t r; TEMPLATE(T, poly_t) v; TEMPLATE(T, poly_factor_t) sq_free; TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_make_monic) (v, f, ctx); /* compute squarefree factorisation */ TEMPLATE(T, poly_factor_init) (sq_free, ctx); TEMPLATE(T, poly_factor_squarefree) (sq_free, v, ctx); /* run Berlekamp algorithm for all squarefree factors */ flint_randinit(r); for (i = 0; i < sq_free->num; i++) { __TEMPLATE(T, poly_factor_berlekamp) (factors, r, sq_free->poly + i, ctx); } flint_randclear(r); /* compute multiplicities of factors in f */ for (i = 0; i < factors->num; i++) factors->exp[i] = TEMPLATE(T, poly_remove) (v, factors->poly + i, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_factor_clear) (sq_free, ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_cantor_zassenhaus.c000066400000000000000000000041061461254215100257440ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_cantor_zassenhaus) (TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) h, v, g, x; fmpz_t q; slong i, j, num; fmpz_init(q); TEMPLATE(T, ctx_order) (q, ctx); TEMPLATE(T, poly_init) (h, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (x, ctx); TEMPLATE(T, poly_gen) (h, ctx); TEMPLATE(T, poly_gen) (x, ctx); TEMPLATE(T, poly_make_monic) (v, f, ctx); i = 0; do { i++; TEMPLATE(T, poly_powmod_fmpz_binexp) (h, h, q, v, ctx); TEMPLATE(T, poly_sub) (h, h, x, ctx); TEMPLATE(T, poly_gcd) (g, h, v, ctx); TEMPLATE(T, poly_add) (h, h, x, ctx); if (g->length != 1) { TEMPLATE(T, poly_make_monic) (g, g, ctx); num = res->num; TEMPLATE(T, poly_factor_equal_deg) (res, g, i, ctx); for (j = num; j < res->num; j++) res->exp[j] = TEMPLATE(T, poly_remove) (v, res->poly + j, ctx); } } while (v->length >= 2 * i + 3); if (v->length > 1) TEMPLATE(T, poly_factor_insert) (res, v, 1, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (h, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (x, ctx); fmpz_clear(q); } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_distinct_deg.c000066400000000000000000000140611461254215100246530ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include void TEMPLATE(T, poly_factor_distinct_deg) (TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) poly, slong * const *degs, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) f, g, s, reducedH0, v, vinv, tmp; TEMPLATE(T, poly_t) * h, *H, *I; fmpz_t q; slong i, j, l, m, n, index, d; double beta; TEMPLATE(T, mat_t) HH, HHH; TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_make_monic) (v, poly, ctx); n = TEMPLATE(T, poly_degree) (poly, ctx); if (n == 1) { TEMPLATE(T, poly_factor_insert) (res, poly, 1, ctx); (*degs)[0] = 1; TEMPLATE(T, poly_clear) (v, ctx); return; } beta = 0.5 * (1. - (log(2) / log(n))); l = ceil(pow(n, beta)); m = ceil(0.5 * n / l); fmpz_init(q); TEMPLATE(T, ctx_order) (q, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (reducedH0, ctx); TEMPLATE(T, poly_init) (vinv, ctx); TEMPLATE(T, poly_init) (tmp, ctx); h = flint_malloc((2 * m + l + 1) * sizeof(TEMPLATE(T, poly_struct))); H = h + (l + 1); I = H + m; for (i = 0; i < l + 1; i++) TEMPLATE(T, poly_init) (h[i], ctx); for (i = 0; i < m; i++) { TEMPLATE(T, poly_init) (H[i], ctx); TEMPLATE(T, poly_init) (I[i], ctx); } TEMPLATE(T, poly_make_monic) (v, poly, ctx); TEMPLATE(T, poly_reverse) (vinv, v, v->length, ctx); TEMPLATE(T, poly_inv_series_newton) (vinv, vinv, v->length, ctx); /* compute baby steps: h[i]=x^{q^i}mod v */ /* h[0] = x */ TEMPLATE(T, poly_iterated_frobenius_preinv) (h, l + 1, v, vinv, ctx); /* compute coarse distinct-degree factorisation */ index = 0; TEMPLATE(T, poly_set) (s, v, ctx); TEMPLATE(T, poly_set) (H[0], h[l], ctx); TEMPLATE(T, poly_set) (reducedH0, H[0], ctx); TEMPLATE(T, mat_init) (HH, n_sqrt(v->length - 1) + 1, v->length - 1, ctx); TEMPLATE(T, poly_precompute_matrix) (HH, reducedH0, s, vinv, ctx); d = 1; for (j = 0; j < m; j++) { /* compute giant steps: H[j]=x^{q^(lj)}mod s */ if (j > 0) { if (I[j - 1]->length > 1) { _TEMPLATE(T, poly_reduce_matrix_mod_poly) (HHH, HH, s, ctx); TEMPLATE(T, mat_clear) (HH, ctx); TEMPLATE(T, mat_init_set) (HH, HHH, ctx); TEMPLATE(T, mat_clear) (HHH, ctx); TEMPLATE(T, poly_rem) (reducedH0, reducedH0, s, ctx); TEMPLATE(T, poly_rem) (tmp, H[j - 1], s, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv) (H[j], tmp, HH, s, vinv, ctx); } else { TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv) (H[j], H[j - 1], HH, s, vinv, ctx); } } /* compute interval polynomials */ TEMPLATE(T, poly_one) (I[j], ctx); for (i = l - 1; (i >= 0) && (2 * d <= s->length - 1); i--, d++) { TEMPLATE(T, poly_rem) (tmp, h[i], s, ctx); TEMPLATE(T, poly_sub) (tmp, H[j], tmp, ctx); TEMPLATE(T, poly_mulmod_preinv) (I[j], tmp, I[j], s, vinv, ctx); } /* compute F_j=f^{[j*l+1]} * ... * f^{[j*l+l]} */ /* F_j is stored on the place of I_j */ TEMPLATE(T, poly_gcd) (I[j], s, I[j], ctx); if (I[j]->length > 1) { TEMPLATE(T, poly_remove) (s, I[j], ctx); TEMPLATE(T, poly_reverse) (vinv, s, s->length, ctx); TEMPLATE(T, poly_inv_series_newton) (vinv, vinv, s->length, ctx); } if (s->length - 1 < 2 * d) { break; } } if (s->length > 1) { TEMPLATE(T, poly_factor_insert) (res, s, 1, ctx); (*degs)[index++] = s->length - 1; } /* compute fine distinct-degree factorisation */ for (j = 0; j < m; j++) { if (I[j]->length - 1 > (j + 1) * l || j == 0) { TEMPLATE(T, poly_set) (g, I[j], ctx); for (i = l - 1; i >= 0 && (g->length > 1); i--) { /* compute f^{[l*(j+1)-i]} */ TEMPLATE(T, poly_sub) (tmp, H[j], h[i], ctx); TEMPLATE(T, poly_gcd) (f, g, tmp, ctx); if (f->length > 1) { /* insert f^{[l*(j+1)-i]} into res */ TEMPLATE(T, poly_make_monic) (f, f, ctx); TEMPLATE(T, poly_factor_insert) (res, f, 1, ctx); (*degs)[index++] = l * (j + 1) - i; TEMPLATE(T, poly_remove) (g, f, ctx); } } } else if (I[j]->length > 1) { TEMPLATE(T, poly_make_monic) (I[j], I[j], ctx); TEMPLATE(T, poly_factor_insert) (res, I[j], 1, ctx); (*degs)[index++] = I[j]->length - 1; } } /* cleanup */ fmpz_clear(q); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (reducedH0, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (vinv, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); TEMPLATE(T, mat_clear) (HH, ctx); for (i = 0; i < l + 1; i++) TEMPLATE(T, poly_clear) (h[i], ctx); for (i = 0; i < m; i++) { TEMPLATE(T, poly_clear) (H[i], ctx); TEMPLATE(T, poly_clear) (I[i], ctx); } flint_free(h); } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_equal_deg.c000066400000000000000000000032341461254215100241410ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "ulong_extras.h" void TEMPLATE(T, poly_factor_equal_deg) (TEMPLATE(T, poly_factor_t) factors, const TEMPLATE(T, poly_t) pol, slong d, const TEMPLATE(T, ctx_t) ctx) { if (pol->length == d + 1) { TEMPLATE(T, poly_factor_insert) (factors, pol, 1, ctx); } else { TEMPLATE(T, poly_t) f, g, r; flint_rand_t state; TEMPLATE(T, poly_init) (f, ctx); flint_randinit(state); while (!TEMPLATE(T, poly_factor_equal_deg_prob) (f, state, pol, d, ctx)) { }; flint_randclear(state); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_divrem) (g, r, pol, f, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_factor_equal_deg) (factors, f, d, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_factor_equal_deg) (factors, g, d, ctx); TEMPLATE(T, poly_clear) (g, ctx); } } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_equal_deg_prob.c000066400000000000000000000070001461254215100251560ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "ulong_extras.h" int TEMPLATE(T, poly_factor_equal_deg_prob) (TEMPLATE(T, poly_t) factor, flint_rand_t state, const TEMPLATE(T, poly_t) pol, slong d, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) a, b, c, polinv; TEMPLATE(T, t) t; fmpz_t exp, q; int res = 1; slong i, k; if (pol->length <= 1) { flint_throw(FLINT_ERROR, "Exception (" TEMPLATE_STR(T) "_poly_factor_equal_deg_prob): Input polynomial is linear.\n"); } fmpz_init(q); TEMPLATE(T, ctx_order) (q, ctx); TEMPLATE(T, poly_init) (a, ctx); do { TEMPLATE(T, poly_randtest) (a, state, pol->length - 1, ctx); } while (a->length <= 1); TEMPLATE(T, poly_gcd) (factor, a, pol, ctx); if (factor->length != 1) { TEMPLATE(T, poly_clear) (a, ctx); fmpz_clear(q); return 1; } TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (polinv, ctx); TEMPLATE(T, poly_reverse) (polinv, pol, pol->length, ctx); TEMPLATE(T, poly_inv_series_newton) (polinv, polinv, polinv->length, ctx); fmpz_init(exp); #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) if (TEMPLATE(T, ctx_prime)(ctx) > 2) { #else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime) (ctx), 2) > 0) { #endif /* compute a^{(q^d-1)/2} rem pol */ fmpz_pow_ui(exp, q, d); fmpz_sub_ui(exp, exp, 1); fmpz_fdiv_q_2exp(exp, exp, 1); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (b, a, exp, 0, pol, polinv, ctx); } else { /* compute b = (a^{2^{k*d-1}}+a^{2^{k*d-2}}+...+a^4+a^2+a) rem pol */ k = d * TEMPLATE(T, ctx_degree) (ctx); /* TODO: Handle overflow? */ TEMPLATE(T, poly_rem) (b, a, pol, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_set) (c, b, ctx); for (i = 1; i < k; i++) { /* c = a^{2^i} = (a^{2^{i-1}})^2 */ TEMPLATE(T, poly_powmod_ui_binexp_preinv) (c, c, 2, pol, polinv, ctx); TEMPLATE(T, poly_add) (b, b, c, ctx); } TEMPLATE(T, poly_rem) (b, b, pol, ctx); TEMPLATE(T, poly_clear) (c, ctx); } fmpz_clear(exp); TEMPLATE(T, init) (t, ctx); TEMPLATE(T, sub_one) (t, b->coeffs + 0, ctx); TEMPLATE(T, poly_set_coeff) (b, 0, t, ctx); TEMPLATE(T, clear) (t, ctx); TEMPLATE(T, poly_gcd) (factor, b, pol, ctx); if ((factor->length <= 1) || (factor->length == pol->length)) res = 0; TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (polinv, ctx); fmpz_clear(q); return res; } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_kaltofen_shoup.c000066400000000000000000000040471461254215100252370ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include void TEMPLATE(T, poly_factor_kaltofen_shoup) (TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) v; TEMPLATE(T, poly_factor_t) sq_free, dist_deg; slong i, j, k, l, res_num, dist_deg_num; slong *degs; degs = flint_malloc(TEMPLATE(T, poly_degree) (poly, ctx) * sizeof(slong)); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_make_monic) (v, poly, ctx); /* compute squarefree factorisation */ TEMPLATE(T, poly_factor_init) (sq_free, ctx); TEMPLATE(T, poly_factor_squarefree) (sq_free, v, ctx); /* compute distinct-degree factorisation */ TEMPLATE(T, poly_factor_init) (dist_deg, ctx); for (i = 0; i < sq_free->num; i++) { dist_deg_num = dist_deg->num; TEMPLATE(T, poly_factor_distinct_deg) (dist_deg, sq_free->poly + i, °s, ctx); /* compute equal-degree factorisation */ for (j = dist_deg_num, l = 0; j < dist_deg->num; j++, l++) { res_num = res->num; TEMPLATE(T, poly_factor_equal_deg) (res, dist_deg->poly + j, degs[l], ctx); for (k = res_num; k < res->num; k++) res->exp[k] = TEMPLATE(T, poly_remove) (v, res->poly + k, ctx); } } flint_free(degs); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_factor_clear) (dist_deg, ctx); TEMPLATE(T, poly_factor_clear) (sq_free, ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_split_single.c000066400000000000000000000044041461254215100247070ustar00rootroot00000000000000/* Copyright (C) 2019 Edouard Rousseau This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_split_single) (TEMPLATE(T, poly_t) linfactor, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx) { if (input->length == 2) { TEMPLATE(T, poly_set) (linfactor, input, ctx); } else { flint_rand_t state; ulong deflation; TEMPLATE(T, poly_t) pol; flint_randinit(state); TEMPLATE(T, poly_init) (pol, ctx); TEMPLATE(T, poly_set) (linfactor, input, ctx); deflation = TEMPLATE(T, poly_deflation) (input, ctx); if (deflation == 1 || deflation == TEMPLATE(T, poly_degree)(input, ctx)) { TEMPLATE(T, poly_set) (pol, input, ctx); while (TEMPLATE(T, poly_degree)(linfactor, ctx) != 1) { while (!TEMPLATE(T, poly_factor_equal_deg_prob) (linfactor, state, pol, 1, ctx)) { }; TEMPLATE(T, poly_set) (pol, linfactor, ctx); } } else { TEMPLATE(T, poly_deflate) (pol, input, deflation, ctx); while (TEMPLATE(T, poly_degree)(pol, ctx) != 1) { while (!TEMPLATE(T, poly_factor_equal_deg_prob) (linfactor, state, pol, 1, ctx)) { }; TEMPLATE(T, poly_set) (pol, linfactor, ctx); } TEMPLATE(T, poly_inflate) (pol, linfactor, deflation, ctx); while (TEMPLATE(T, poly_degree)(pol, ctx) != 1) { while (!TEMPLATE(T, poly_factor_equal_deg_prob) (linfactor, state, pol, 1, ctx)) { }; TEMPLATE(T, poly_set) (pol, linfactor, ctx); } } flint_randclear(state); TEMPLATE(T, poly_clear) (pol, ctx); } } #endif flint-3.1.3/src/fq_poly_factor_templates/factor_squarefree.c000066400000000000000000000123141461254215100243540ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "ulong_extras.h" void TEMPLATE(T, poly_factor_squarefree) (TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) f_d, g, g_1, r; TEMPLATE(T, t) x; slong deg, i, p_ui; if (f->length <= 1) { res->num = 0; return; } if (f->length == 2) { TEMPLATE(T, poly_factor_insert) (res, f, 1, ctx); TEMPLATE(T, poly_make_monic) (res->poly + (res->num - 1), res->poly + (res->num - 1), ctx); return; } deg = TEMPLATE(T, poly_degree) (f, ctx); /* Step 1, look at f', if it is zero then we are done since f = h(x)^p for some particular h(x), clearly f(x) = sum a_k x^kp, k <= deg(f) */ TEMPLATE(T, init) (x, ctx); TEMPLATE(T, poly_init) (g_1, ctx); TEMPLATE(T, poly_init) (f_d, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_derivative) (f_d, f, ctx); /* Case 1 */ if (TEMPLATE(T, poly_is_zero) (f_d, ctx)) { TEMPLATE(T, poly_factor_t) new_res; TEMPLATE(T, poly_t) h; /* We can do this since deg is a multiple of p in this case */ #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) p_ui = TEMPLATE(T, ctx_prime)(ctx); #else p_ui = fmpz_get_ui(TEMPLATE(T, ctx_prime)(ctx)); #endif TEMPLATE(T, poly_init) (h, ctx); for (i = 0; i <= deg / p_ui; i++) /* this will be an integer since f'=0 */ { TEMPLATE(T, poly_get_coeff) (x, f, i * p_ui, ctx); TEMPLATE(T, pth_root) (x, x, ctx); TEMPLATE(T, poly_set_coeff) (h, i, x, ctx); } /* Now run squarefree on h, and return it to the pth power */ TEMPLATE(T, poly_factor_init) (new_res, ctx); TEMPLATE(T, poly_factor_squarefree) (new_res, h, ctx); TEMPLATE(T, poly_factor_pow) (new_res, p_ui, ctx); TEMPLATE(T, poly_factor_concat) (res, new_res, ctx); TEMPLATE(T, poly_clear) (h, ctx); TEMPLATE(T, poly_factor_clear) (new_res, ctx); } else { TEMPLATE(T, poly_t) h, z; TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_gcd) (g, f, f_d, ctx); TEMPLATE(T, poly_divrem) (g_1, r, f, g, ctx); i = 1; TEMPLATE(T, poly_init) (h, ctx); TEMPLATE(T, poly_init) (z, ctx); /* Case 2 */ while (g_1->length > 1) { TEMPLATE(T, poly_gcd) (h, g_1, g, ctx); TEMPLATE(T, poly_divrem) (z, r, g_1, h, ctx); /* out <- out.z */ if (z->length > 1) { TEMPLATE(T, poly_factor_insert) (res, z, 1, ctx); TEMPLATE(T, poly_make_monic) (res->poly + (res->num - 1), res->poly + (res->num - 1), ctx); if (res->num) res->exp[res->num - 1] *= i; } i++; TEMPLATE(T, poly_set) (g_1, h, ctx); TEMPLATE(T, poly_divrem) (g, r, g, h, ctx); } TEMPLATE(T, poly_clear) (h, ctx); TEMPLATE(T, poly_clear) (z, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_make_monic) (g, g, ctx); if (g->length > 1) { /* so now we multiply res with squarefree(g^1/p) ^ p */ TEMPLATE(T, poly_t) g_p; /* g^(1/p) */ TEMPLATE(T, poly_factor_t) new_res_2; TEMPLATE(T, poly_init) (g_p, ctx); #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) p_ui = TEMPLATE(T, ctx_prime)(ctx); #else p_ui = fmpz_get_ui(TEMPLATE(T, ctx_prime)(ctx)); #endif for (i = 0; i <= TEMPLATE(T, poly_degree) (g, ctx) / p_ui; i++) { TEMPLATE(T, poly_get_coeff) (x, g, i * p_ui, ctx); TEMPLATE(T, pth_root) (x, x, ctx); TEMPLATE(T, poly_set_coeff) (g_p, i, x, ctx); } TEMPLATE(T, poly_factor_init) (new_res_2, ctx); /* squarefree(g^(1/p)) */ TEMPLATE(T, poly_factor_squarefree) (new_res_2, g_p, ctx); TEMPLATE(T, poly_factor_pow) (new_res_2, p_ui, ctx); TEMPLATE(T, poly_factor_concat) (res, new_res_2, ctx); TEMPLATE(T, poly_clear) (g_p, ctx); TEMPLATE(T, poly_factor_clear) (new_res_2, ctx); } } TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, poly_clear) (g_1, ctx); TEMPLATE(T, poly_clear) (f_d, ctx); TEMPLATE(T, poly_clear) (g, ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/fit_length.c000066400000000000000000000016261461254215100230030ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_fit_length) (TEMPLATE(T, poly_factor_t) fac, slong len, const TEMPLATE(T, ctx_t) ctx) { if (len > fac->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * fac->alloc) len = 2 * fac->alloc; TEMPLATE(T, poly_factor_realloc) (fac, len, ctx); } } #endif flint-3.1.3/src/fq_poly_factor_templates/init.c000066400000000000000000000017771461254215100216320ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_init) (TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx) { slong i; fac->alloc = 5; fac->num = 0; fac->poly = flint_malloc(sizeof(TEMPLATE(T, poly_struct)) * 5); fac->exp = flint_malloc(sizeof(slong) * 5); for (i = 0; i < fac->alloc; i++) TEMPLATE(T, poly_init) (fac->poly + i, ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/insert.c000066400000000000000000000031211461254215100221540ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_insert) (TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, poly_t) poly, slong exp, const TEMPLATE(T, ctx_t) ctx) { slong i; if (poly->length <= 1) return; for (i = 0; i < fac->num; i++) { if (TEMPLATE(T, poly_equal) (poly, fac->poly + i, ctx)) { fac->exp[i] += exp; return; } } if (fac->alloc == fac->num) { slong new_size = 2 * fac->alloc; fac->poly = flint_realloc(fac->poly, sizeof(TEMPLATE(T, poly_struct)) * new_size); fac->exp = flint_realloc(fac->exp, sizeof(slong) * new_size); for (i = fac->alloc; i < new_size; i++) TEMPLATE(T, poly_init) (fac->poly + i, ctx); fac->alloc = new_size; } TEMPLATE(T, poly_set) (fac->poly + fac->num, poly, ctx); fac->exp[fac->num] = exp; fac->num++; } #endif flint-3.1.3/src/fq_poly_factor_templates/is_irreducible.c000066400000000000000000000016061461254215100236420ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, poly_is_irreducible) (const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, poly_length) (f, ctx) > 2) { return TEMPLATE(T, poly_is_irreducible_ddf) (f, ctx); } return 1; } #endif flint-3.1.3/src/fq_poly_factor_templates/is_irreducible_ben_or.c000066400000000000000000000055251461254215100251720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "math.h" int TEMPLATE(T, poly_is_irreducible_ben_or) (const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { int result; slong i, n; fmpz_t q; TEMPLATE(T, poly_t) g, x, xq, xqimx; TEMPLATE(T, poly_t) v, vinv; n = TEMPLATE(T, poly_degree) (f, ctx); if (n < 2) return 1; if (!TEMPLATE(T, poly_is_squarefree) (f, ctx)) return 0; TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (vinv, ctx); TEMPLATE(T, poly_make_monic) (v, f, ctx); TEMPLATE(T, poly_reverse) (vinv, v, v->length, ctx); TEMPLATE(T, poly_inv_series_newton) (vinv, vinv, v->length, ctx); TEMPLATE(T, poly_init) (x, ctx); TEMPLATE(T, poly_init) (xq, ctx); TEMPLATE(T, poly_init) (xqimx, ctx); /* Compute xq = x^q mod f */ fmpz_init(q); #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) fmpz_ui_pow_ui(q, TEMPLATE(T, ctx_prime)(ctx), TEMPLATE(T, ctx_degree)(ctx)); #else fmpz_pow_ui(q, TEMPLATE(T, ctx_prime)(ctx), TEMPLATE(T, ctx_degree)(ctx)); #endif TEMPLATE(T, poly_gen) (x, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (xq, x, q, 0, v, vinv, ctx); TEMPLATE(T, poly_set) (xqimx, xq, ctx); result = 1; TEMPLATE(T, poly_init) (g, ctx); for (i = 1; i <= n / 2; i++) { TEMPLATE(T, poly_sub) (xqimx, xqimx, x, ctx); TEMPLATE(T, poly_gcd) (g, f, xqimx, ctx); if (!TEMPLATE(T, poly_is_one) (g, ctx)) { result = 0; break; } else if (i == n / 2) { /* We don't need to compute the last step */ break; } TEMPLATE(T, poly_add) (xqimx, xqimx, x, ctx); if (TEMPLATE(CAP_T, POLY_ITERATED_FROBENIUS_CUTOFF) (ctx, v->length)) { TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (xqimx, xqimx, q, 0, v, vinv, ctx); } else { TEMPLATE(T, poly_compose_mod_preinv) (xqimx, xqimx, xq, v, vinv, ctx); } } TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (x, ctx); TEMPLATE(T, poly_clear) (xq, ctx); TEMPLATE(T, poly_clear) (xqimx, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (vinv, ctx); fmpz_clear(q); return result; } #endif flint-3.1.3/src/fq_poly_factor_templates/is_irreducible_ddf.c000066400000000000000000000027431461254215100244620ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "math.h" int TEMPLATE(T, poly_is_irreducible_ddf) (const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { slong i, n; slong *degs; TEMPLATE(T, poly_factor_t) dist_deg; n = TEMPLATE(T, poly_degree) (f, ctx); if (n < 2) return 1; if (!TEMPLATE(T, poly_is_squarefree) (f, ctx)) return 0; degs = (slong *) flint_malloc(n * sizeof(slong)); TEMPLATE(T, poly_factor_init) (dist_deg, ctx); TEMPLATE(T, poly_factor_distinct_deg) (dist_deg, f, °s, ctx); for (i = 0; i < dist_deg->num; i++) { if (degs[i] == n) { flint_free(degs); TEMPLATE(T, poly_factor_clear) (dist_deg, ctx); return 1; } if (degs[i] > 0) { flint_free(degs); TEMPLATE(T, poly_factor_clear) (dist_deg, ctx); return 0; } } flint_free(degs); TEMPLATE(T, poly_factor_clear) (dist_deg, ctx); return 1; } #endif flint-3.1.3/src/fq_poly_factor_templates/is_squarefree.c000066400000000000000000000026271461254215100235170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "ulong_extras.h" int _TEMPLATE(T, poly_is_squarefree) (const TEMPLATE(T, struct) * f, slong len, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * fd, *g; slong dlen; int res; if (len <= 2) return len != 0; fd = _TEMPLATE(T, vec_init) (2 * (len - 1), ctx); g = fd + len - 1; _TEMPLATE(T, poly_derivative) (fd, f, len, ctx); dlen = len - 1; TEMPLATE(CAP_T, VEC_NORM) (fd, dlen, ctx); if (dlen) { res = (_TEMPLATE(T, poly_gcd) (g, f, len, fd, dlen, ctx) == 1); } else res = 0; /* gcd(f, 0) = f, and len(f) > 2 */ _TEMPLATE(T, vec_clear) (fd, 2 * (len - 1), ctx); return res; } int TEMPLATE(T, poly_is_squarefree) (const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_is_squarefree) (f->coeffs, f->length, ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/iterated_frobenius_preinv.c000066400000000000000000000034111461254215100261120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_iterated_frobenius_preinv) (TEMPLATE(T, poly_t) * rop, slong n, const TEMPLATE(T, poly_t) v, const TEMPLATE(T, poly_t) vinv, const TEMPLATE(T, ctx_t) ctx) { slong i; fmpz_t q; TEMPLATE(T, mat_t) HH; fmpz_init(q); TEMPLATE(T, ctx_order) (q, ctx); TEMPLATE(T, poly_gen) (rop[0], ctx); if (TEMPLATE(CAP_T, POLY_ITERATED_FROBENIUS_CUTOFF) (ctx, v->length)) { TEMPLATE(T, mat_init) (HH, n_sqrt(v->length - 1) + 1, v->length - 1, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (rop[1], rop[0], q, 0, v, vinv, ctx); TEMPLATE(T, poly_precompute_matrix) (HH, rop[1], v, vinv, ctx); for (i = 2; i < n; i++) { TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv) (rop[i], rop[i - 1], HH, v, vinv, ctx); } TEMPLATE(T, mat_clear) (HH, ctx); } else { for (i = 1; i < n; i++) TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (rop[i], rop[i - 1], q, 0, v, vinv, ctx); } fmpz_clear(q); } #endif flint-3.1.3/src/fq_poly_factor_templates/pow.c000066400000000000000000000015221461254215100214600ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_pow) (TEMPLATE(T, poly_factor_t) fac, slong exp, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < fac->num; i++) fac->exp[i] *= exp; } #endif flint-3.1.3/src/fq_poly_factor_templates/print.c000066400000000000000000000016461461254215100220160ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_print) (const TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < fac->num; i++) { TEMPLATE(T, poly_print) (fac->poly + i, ctx); flint_printf(" ^ %wd\n", fac->exp[i]); } } #endif flint-3.1.3/src/fq_poly_factor_templates/print_pretty.c000066400000000000000000000014451461254215100234220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_print_pretty) (const TEMPLATE(T, poly_factor_t) fac, const char *var, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < fac->num; i++) { TEMPLATE(T, poly_print_pretty) (fac->poly + i, var, ctx); flint_printf(" ^ %wd\n", fac->exp[i]); } } #endif flint-3.1.3/src/fq_poly_factor_templates/realloc.c000066400000000000000000000042371461254215100223020ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" void TEMPLATE(T, poly_factor_realloc) (TEMPLATE(T, poly_factor_t) fac, slong alloc, const TEMPLATE(T, ctx_t) ctx) { if (alloc == 0) /* Clear up, reinitialise */ { TEMPLATE(T, poly_factor_clear) (fac, ctx); TEMPLATE(T, poly_factor_init) (fac, ctx); } else if (fac->alloc) /* Realloc */ { if (fac->alloc > alloc) { slong i; for (i = alloc; i < fac->num; i++) TEMPLATE(T, poly_clear) (fac->poly + i, ctx); fac->poly = flint_realloc(fac->poly, alloc * sizeof(TEMPLATE(T, poly_struct))); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); fac->alloc = alloc; } else if (fac->alloc < alloc) { slong i; fac->poly = flint_realloc(fac->poly, alloc * sizeof(TEMPLATE(T, poly_struct))); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); for (i = fac->alloc; i < alloc; i++) { TEMPLATE(T, poly_init) (fac->poly + i, ctx); fac->exp[i] = WORD(0); } fac->alloc = alloc; } } else /* Nothing allocated already so do it now */ { slong i; fac->poly = flint_malloc(alloc * sizeof(TEMPLATE(T, poly_struct))); fac->exp = flint_calloc(alloc, sizeof(slong)); for (i = 0; i < alloc; i++) TEMPLATE(T, poly_init) (fac->poly + i, ctx); fac->num = 0; fac->alloc = alloc; } } #endif flint-3.1.3/src/fq_poly_factor_templates/roots.c000066400000000000000000000225231461254215100220250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "ulong_extras.h" /* split f assuming that f has degree(f) distinct nonzero roots in Fq */ void _TEMPLATE(T, poly_split_rabin)( TEMPLATE(T, poly_t) a, TEMPLATE(T, poly_t) b, const TEMPLATE(T, poly_t) f, const fmpz_t halfq, /* (q-1)/2 or 0 in characteristic 2 */ TEMPLATE(T, poly_t) t, /* temp space */ TEMPLATE(T, poly_t) t2, /* temp space */ flint_rand_t randstate, const TEMPLATE(T, ctx_t) ctx) { slong i; FLINT_ASSERT(TEMPLATE(T, poly_degree)(f, ctx) > 1); TEMPLATE(T, poly_reverse)(t, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton)(t2, t, t->length, ctx); try_again: /* a = random linear */ TEMPLATE(T, poly_fit_length)(a, 2, ctx); TEMPLATE(T, rand)(a->coeffs + 0, randstate, ctx); TEMPLATE(T, rand)(a->coeffs + 1, randstate, ctx); if (TEMPLATE(T, is_zero)(a->coeffs + 1, ctx)) TEMPLATE(T, one)(a->coeffs + 1, ctx); a->length = 2; if (!fmpz_is_zero(halfq)) { #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) FLINT_ASSERT(TEMPLATE(T, ctx_prime)(ctx) > 2); #else FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) > 0); #endif TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(t, a, halfq, 0, f, t2, ctx); TEMPLATE(T, poly_add_si)(t, t, -1, ctx); } else { /* it is important that coeff(a, x^1) is random */ #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) FLINT_ASSERT(TEMPLATE(T, ctx_prime)(ctx) == 2); #else FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0); #endif TEMPLATE(T, poly_set)(t, a, ctx); for (i = TEMPLATE(T, ctx_degree)(ctx); i > 1; i--) { TEMPLATE(T, poly_powmod_ui_binexp_preinv)(a, a, 2, f, t2, ctx); TEMPLATE(T, poly_add)(t, t, a, ctx); } } TEMPLATE(T, poly_gcd)(a, t, f, ctx); FLINT_ASSERT(!TEMPLATE(T, poly_is_zero)(a, ctx)); if (0 >= TEMPLATE(T, poly_degree)(a, ctx) || TEMPLATE(T, poly_degree)(a, ctx) >= TEMPLATE(T, poly_degree)(f, ctx)) { goto try_again; } TEMPLATE(T, poly_div)(b, f, a, ctx); /* ensure deg a >= deg b */ if (TEMPLATE(T, poly_degree)(a, ctx) < TEMPLATE(T, poly_degree)(b, ctx)) TEMPLATE(T, poly_swap)(a, b, ctx); return; } /* Helper function for finding roots. The roots of a monic f are written with exponent given in mult to r. Uses Rabin's Las Vegas algorithm via gcd computations with (x + delta)^halfq - 1. */ static void _TEMPLATE(T, poly_push_roots)( TEMPLATE(T, poly_factor_t) r, TEMPLATE(T, poly_t) f, /* clobbered */ slong mult, /* expoenent to write on the roots */ const fmpz_t halfq, /* (q-1)/2 or 0 in characteristic 2 */ TEMPLATE(T, poly_t) t, /* temp */ TEMPLATE(T, poly_t) t2, /* more temp */ TEMPLATE(T, poly_struct) * stack, /* temp of size FLINT_BITS */ flint_rand_t randstate, const TEMPLATE(T, ctx_t) ctx) { slong i, sp; TEMPLATE(T, poly_struct) * a, * b; FLINT_ASSERT(TEMPLATE(T, poly_degree)(f, ctx) >= 1); FLINT_ASSERT(TEMPLATE(T, is_one)(f->coeffs + TEMPLATE(T, poly_degree)(f, ctx), ctx)); /* handle zero roots */ if (TEMPLATE(T, is_zero)(f->coeffs + 0, ctx)) { TEMPLATE(T, poly_factor_fit_length)(r, r->num + 1, ctx); TEMPLATE(T, poly_fit_length)(r->poly + r->num, 2, ctx); TEMPLATE(T, zero)(r->poly[r->num].coeffs + 0, ctx); TEMPLATE(T, one)(r->poly[r->num].coeffs + 1, ctx); r->poly[r->num].length = 2; r->exp[r->num] = mult; r->num++; i = 1; while (i < f->length && TEMPLATE(T, is_zero)(f->coeffs + i, ctx)) i++; TEMPLATE(T, poly_shift_right)(f, f, i, ctx); } if (TEMPLATE(T, poly_degree)(f, ctx) <= 1) { if (TEMPLATE(T, poly_degree)(f, ctx) == 1) { TEMPLATE(T, poly_factor_fit_length)(r, r->num + 1, ctx); TEMPLATE(T, poly_swap)(r->poly + r->num, f, ctx); r->exp[r->num] = mult; r->num++; } return; } FLINT_ASSERT(!(TEMPLATE(T, is_zero)(f->coeffs + 0, ctx))); TEMPLATE(T, poly_reverse)(t, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton)(t2, t, t->length, ctx); a = stack + 0; b = stack + 1; TEMPLATE(T, poly_gen)(a, ctx); if (!fmpz_is_zero(halfq)) { #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) FLINT_ASSERT(TEMPLATE(T, ctx_prime)(ctx) > 2); #else FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) > 0); #endif TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(t, a, halfq, 0, f, t2, ctx); TEMPLATE(T, poly_add_si)(t, t, -1, ctx); TEMPLATE(T, poly_gcd)(a, t, f, ctx); TEMPLATE(T, poly_add_si)(t, t, 1, ctx); } else { #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) FLINT_ASSERT(TEMPLATE(T, ctx_prime)(ctx) == 2); #else FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0); #endif TEMPLATE(T, poly_set)(t, a, ctx); for (i = TEMPLATE(T, ctx_degree)(ctx); i > 1; i--) { TEMPLATE(T, poly_powmod_ui_binexp_preinv)(a, a, 2, f, t2, ctx); TEMPLATE(T, poly_add)(t, t, a, ctx); } TEMPLATE(T, poly_gcd)(a, t, f, ctx); } TEMPLATE(T, poly_add_si)(t, t, 1, ctx); TEMPLATE(T, poly_gcd)(b, t, f, ctx); /* ensure deg a >= deg b */ if (TEMPLATE(T, poly_degree)(a, ctx) < TEMPLATE(T, poly_degree)(b, ctx)) TEMPLATE(T, poly_swap)(a, b, ctx); TEMPLATE(T, poly_factor_fit_length)(r, r->num + TEMPLATE(T, poly_degree)(a, ctx) + TEMPLATE(T, poly_degree)(b, ctx), ctx); /* initial split failed if b = 1 */ sp = (TEMPLATE(T, poly_degree)(b, ctx) > 0) ? 2 : 1; while (sp > 0) { sp--; FLINT_ASSERT(sp < FLINT_BITS); TEMPLATE(T, poly_swap)(f, stack + sp, ctx); FLINT_ASSERT(TEMPLATE(T, poly_degree)(f, ctx) >= 0); FLINT_ASSERT( FLINT_BIT_COUNT(TEMPLATE(T, poly_degree)(f, ctx)) <= FLINT_BITS - sp); if (TEMPLATE(T, poly_degree)(f, ctx) <= 1) { if (TEMPLATE(T, poly_degree)(f, ctx) == 1) { FLINT_ASSERT(r->num < r->alloc); TEMPLATE(T, poly_set)(r->poly + r->num, f, ctx); r->exp[r->num] = mult; r->num++; } } else { FLINT_ASSERT(sp + 1 < FLINT_BITS); _TEMPLATE(T, poly_split_rabin)(stack + sp + 0, stack + sp + 1, f, halfq, t, t2, randstate, ctx); FLINT_ASSERT( FLINT_BIT_COUNT(TEMPLATE(T, poly_degree)(stack + sp + 1, ctx)) <= FLINT_BITS - (sp + 1)); FLINT_ASSERT( FLINT_BIT_COUNT(TEMPLATE(T, poly_degree)(stack + sp + 0, ctx)) <= FLINT_BITS - (sp + 0)); sp += 2; } } } void TEMPLATE(T, poly_roots)( TEMPLATE(T, poly_factor_t) r, const TEMPLATE(T, poly_t) f, int with_multiplicity, const TEMPLATE(T, ctx_t) ctx) { slong i; fmpz_t q2; flint_rand_t randstate; TEMPLATE(T, poly_struct) t[FLINT_BITS + 3]; r->num = 0; if (TEMPLATE(T, poly_degree)(f, ctx) < 2) { if (TEMPLATE(T, poly_degree)(f, ctx) == 1) { TEMPLATE(T, poly_factor_fit_length)(r, 1, ctx); TEMPLATE(T, poly_make_monic)(r->poly + 0, f, ctx); r->exp[0] = 1; r->num = 1; } else if (TEMPLATE(T, poly_degree)(f, ctx) < 0) { flint_throw(FLINT_ERROR, "Exception in fq_poly_roots: " "input polynomial is zero."); } return; } fmpz_init(q2); TEMPLATE(T, ctx_order(q2, ctx)); fmpz_sub_ui(q2, q2, 1); if (fmpz_is_even(q2)) fmpz_fdiv_q_2exp(q2, q2, 1); else fmpz_zero(q2); flint_randinit(randstate); for (i = 0; i < FLINT_BITS + 3; i++) TEMPLATE(T, poly_init)(t + i, ctx); if (with_multiplicity) { TEMPLATE(T, poly_factor_t) sqf; TEMPLATE(T, poly_factor_init)(sqf, ctx); TEMPLATE(T, poly_factor_squarefree)(sqf, f, ctx); for (i = 0; i < sqf->num; i++) { _TEMPLATE(T, poly_push_roots)(r, sqf->poly + i, sqf->exp[i], q2, t + 1, t + 2, t + 3, randstate, ctx); } TEMPLATE(T, poly_factor_clear)(sqf, ctx); } else { TEMPLATE(T, poly_make_monic)(t + 0, f, ctx); _TEMPLATE(T, poly_push_roots)(r, t + 0, 1, q2, t + 1, t + 2, t + 3, randstate, ctx); } fmpz_clear(q2); flint_randclear(randstate); for (i = 0; i < FLINT_BITS + 3; i++) TEMPLATE(T, poly_clear)(t + i, ctx); } #endif flint-3.1.3/src/fq_poly_factor_templates/set.c000066400000000000000000000025611461254215100214520ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_factor_set) (TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx) { if (res != fac) { if (fac->num == 0) { TEMPLATE(T, poly_factor_clear) (res, ctx); TEMPLATE(T, poly_factor_init) (res, ctx); } else { slong i; TEMPLATE(T, poly_factor_fit_length) (res, fac->num, ctx); for (i = 0; i < fac->num; i++) { TEMPLATE(T, poly_set) (res->poly + i, fac->poly + i, ctx); res->exp[i] = fac->exp[i]; } for (; i < res->num; i++) { TEMPLATE(T, poly_zero) (res->poly + i, ctx); res->exp[i] = 0; } res->num = fac->num; } } } #endif flint-3.1.3/src/fq_poly_factor_templates/test/000077500000000000000000000000001461254215100214665ustar00rootroot00000000000000flint-3.1.3/src/fq_poly_factor_templates/test/t-factor.c000066400000000000000000000211651461254215100233560ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor, state) { int iter; /* Default algorithm */ for (iter = 0; iter < 3 * flint_test_multiplier(); iter++) { int result = 1; TEMPLATE(T, poly_t) pol1, poly, quot, rem, product; TEMPLATE(T, poly_factor_t) res; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) randlead; TEMPLATE(T, t) lead; slong length, num, i, j; ulong exp[5]; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init) (randlead, ctx); TEMPLATE(T, randtest_not_zero) (randlead, state, ctx); TEMPLATE(T, poly_init) (pol1, ctx); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (quot, ctx); TEMPLATE(T, poly_init) (rem, ctx); TEMPLATE(T, poly_zero) (pol1, ctx); TEMPLATE3(T, poly_set, T) (pol1, randlead, ctx); length = n_randint(state, 4) + 2; TEMPLATE(T, poly_randtest_irreducible) (poly, state, length, ctx); exp[0] = n_randint(state, 3) + 1; for (i = 0; i < exp[0]; i++) TEMPLATE(T, poly_mul) (pol1, pol1, poly, ctx); num = n_randint(state, 3) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 3) + 2; TEMPLATE(T, poly_randtest_irreducible) (poly, state, length, ctx); TEMPLATE(T, poly_divrem) (quot, rem, pol1, poly, ctx); } while ((poly->length < 2) || (rem->length == 0)); exp[i] = n_randint(state, 3) + 1; for (j = 0; j < exp[i]; j++) TEMPLATE(T, poly_mul) (pol1, pol1, poly, ctx); } TEMPLATE(T, poly_factor_init) (res, ctx); TEMPLATE(T, init) (lead, ctx); switch (n_randint(state, 4)) { case 0: TEMPLATE(T, poly_factor) (res, lead, pol1, ctx); break; case 1: TEMPLATE(T, poly_factor_with_berlekamp) (res, lead, pol1, ctx); break; case 2: #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) if (TEMPLATE(T, ctx_prime)(ctx) % 2 == 0) #else if (fmpz_is_even(TEMPLATE(T, ctx_prime) (ctx))) #endif TEMPLATE(T, poly_factor) (res, lead, pol1, ctx); else TEMPLATE(T, poly_factor_with_cantor_zassenhaus) (res, lead, pol1, ctx); break; case 3: TEMPLATE(T, poly_factor_with_kaltofen_shoup) (res, lead, pol1, ctx); break; } fflush(stdout); result &= (res->num == num); if (!result) { flint_printf("Error: number of factors incorrect, %wd, %wd\n", res->num, num); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_init) (product, ctx); TEMPLATE(T, poly_one) (product, ctx); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) TEMPLATE(T, poly_mul) (product, product, res->poly + i, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (product, product, lead, ctx); result &= TEMPLATE(T, poly_equal) (pol1, product, ctx); if (!result) { flint_printf ("Error: product of factors does not equal original polynomial\n"); TEMPLATE(T, poly_print_pretty) (pol1, "x", ctx); flint_printf("\n"); TEMPLATE(T, poly_print_pretty) (product, "x", ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (product, ctx); TEMPLATE(T, poly_clear) (quot, ctx); TEMPLATE(T, poly_clear) (rem, ctx); TEMPLATE(T, poly_clear) (pol1, ctx); TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_factor_clear) (res, ctx); TEMPLATE(T, clear) (lead, ctx); TEMPLATE(T, clear) (randlead, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test deflation trick */ for (iter = 0; iter < 2 * flint_test_multiplier(); iter++) { TEMPLATE(T, poly_t) pol1, poly, quot, rem; TEMPLATE(T, poly_factor_t) res, res2; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) lead; slong length, num, i, j; slong exp[5]; ulong inflation; int found; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (pol1, ctx); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (quot, ctx); TEMPLATE(T, poly_init) (rem, ctx); TEMPLATE(T, poly_zero) (pol1, ctx); TEMPLATE(T, poly_one) (pol1, ctx); inflation = n_randint(state, 7) + 1; length = n_randint(state, 4) + 2; TEMPLATE(T, poly_randtest_irreducible) (poly, state, length, ctx); TEMPLATE(T, poly_inflate) (poly, poly, inflation, ctx); exp[0] = n_randint(state, 6) + 1; for (i = 0; i < exp[0]; i++) TEMPLATE(T, poly_mul) (pol1, pol1, poly, ctx); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 6) + 2; TEMPLATE(T, poly_randtest_irreducible) (poly, state, length, ctx); TEMPLATE(T, poly_divrem) (quot, rem, pol1, poly, ctx); } while ((poly->length < 2) || (rem->length == 0)); exp[i] = n_randint(state, 6) + 1; TEMPLATE(T, poly_inflate) (poly, poly, inflation, ctx); for (j = 0; j < exp[i]; j++) TEMPLATE(T, poly_mul) (pol1, pol1, poly, ctx); } TEMPLATE(T, poly_factor_init) (res, ctx); TEMPLATE(T, poly_factor_init) (res2, ctx); TEMPLATE(T, init) (lead, ctx); switch (n_randint(state, 4)) { case 0: TEMPLATE(T, poly_factor) (res, lead, pol1, ctx); break; case 1: TEMPLATE(T, poly_factor_with_berlekamp) (res, lead, pol1, ctx); break; case 2: TEMPLATE(T, poly_factor_with_cantor_zassenhaus) (res, lead, pol1, ctx); break; case 3: TEMPLATE(T, poly_factor_with_kaltofen_shoup) (res, lead, pol1, ctx); break; } TEMPLATE(T, poly_factor_cantor_zassenhaus) (res2, pol1, ctx); if (res->num != res2->num) { flint_printf("FAIL: different number of factors found\n"); fflush(stdout); flint_abort(); } for (i = 0; i < res->num; i++) { found = 0; for (j = 0; j < res2->num; j++) { if (TEMPLATE(T, poly_equal) (res->poly + i, res2->poly + j, ctx) && res->exp[i] == res2->exp[j]) { found = 1; break; } } if (!found) { flint_printf("FAIL: factor not found\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, poly_clear) (quot, ctx); TEMPLATE(T, poly_clear) (rem, ctx); TEMPLATE(T, poly_clear) (pol1, ctx); TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_factor_clear) (res, ctx); TEMPLATE(T, poly_factor_clear) (res2, ctx); TEMPLATE(T, clear) (lead, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-factor_berlekamp.c000066400000000000000000000103741461254215100254000ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_berlekamp, state) { int iter; for (iter = 0; iter < 15 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly1, poly, q, r, product; TEMPLATE(T, poly_factor_t) res; slong i, j, length, num; slong exp[5]; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_zero) (poly1, ctx); TEMPLATE(T, poly_one) (poly1, ctx); length = n_randint(state, 4) + 2; do { TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) TEMPLATE(T, poly_make_monic) (poly, poly, ctx); } while ((poly->length < 2) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx))); exp[0] = n_randint(state, 5) + 1; for (i = 0; i < exp[0]; i++) TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 5) + 2; TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) { TEMPLATE(T, poly_make_monic) (poly, poly, ctx); TEMPLATE(T, poly_divrem) (q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx)) || (r->length == 0)); exp[i] = n_randint(state, 5) + 1; for (j = 0; j < exp[i]; j++) TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); } TEMPLATE(T, poly_factor_init) (res, ctx); TEMPLATE(T, poly_factor_berlekamp) (res, poly1, ctx); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); TEMPLATE(T, ctx_print) (ctx); flint_printf("\n"); TEMPLATE(T, poly_print_pretty) (poly1, "x", ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_init) (product, ctx); TEMPLATE(T, poly_one) (product, ctx); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) TEMPLATE(T, poly_mul) (product, product, res->poly + i, ctx); TEMPLATE3(T, poly_scalar_mul, T) (product, product, poly1->coeffs + poly1->length - 1, ctx); if (!TEMPLATE(T, poly_equal) (poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); TEMPLATE(T, poly_print) (product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (product, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_factor_clear) (res, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-factor_cantor_zassenhaus.c000066400000000000000000000102151461254215100271620ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_cantor_zassenhaus, state) { int iter; for (iter = 0; iter < 2 * flint_test_multiplier(); iter++) { TEMPLATE(T, poly_t) poly1, poly, q, r, product; TEMPLATE(T, poly_factor_t) res; TEMPLATE(T, ctx_t) ctx; slong i, j, length, num; slong exp[5]; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_zero) (poly1, ctx); TEMPLATE(T, poly_one) (poly1, ctx); length = n_randint(state, 4) + 2; do { TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) TEMPLATE(T, poly_make_monic) (poly, poly, ctx); } while ((poly->length != length) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx))); exp[0] = n_randint(state, 5) + 1; for (i = 0; i < exp[0]; i++) TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 4) + 2; TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) { TEMPLATE(T, poly_make_monic) (poly, poly, ctx); TEMPLATE(T, poly_divrem) (q, r, poly1, poly, ctx); } } while ((poly->length != length) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx)) || (r->length == 0)); exp[i] = n_randint(state, 5) + 1; for (j = 0; j < exp[i]; j++) TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); } TEMPLATE(T, poly_factor_init) (res, ctx); TEMPLATE(T, poly_factor_cantor_zassenhaus) (res, poly1, ctx); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_init) (product, ctx); TEMPLATE(T, poly_one) (product, ctx); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) TEMPLATE(T, poly_mul) (product, product, res->poly + i, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (product, product, poly1->coeffs + (poly1->length - 1), ctx); if (!TEMPLATE(T, poly_equal) (poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); TEMPLATE(T, poly_print) (product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (product, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_factor_clear) (res, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-factor_distinct_deg.c000066400000000000000000000076461461254215100261060ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_distinct_deg, state) { int iter; for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly1, poly, q, r, product; TEMPLATE(T, poly_factor_t) res; slong i, length, num; slong *degs; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_zero) (poly1, ctx); TEMPLATE(T, poly_one) (poly1, ctx); length = n_randint(state, 7) + 2; do { TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) TEMPLATE(T, poly_make_monic) (poly, poly, ctx); } while ((poly->length < 2) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx))); TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) { TEMPLATE(T, poly_make_monic) (poly, poly, ctx); TEMPLATE(T, poly_divrem) (q, r, poly1, poly, ctx); } } while ((poly->length < 2) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx)) || (r->length == 0)); TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); } if (!(degs = flint_malloc((poly1->length - 1) * sizeof(slong)))) { flint_printf("Fatal error: not enough memory."); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_factor_init) (res, ctx); TEMPLATE(T, poly_factor_distinct_deg) (res, poly1, °s, ctx); TEMPLATE(T, poly_init) (product, ctx); TEMPLATE(T, poly_one) (product, ctx); for (i = 0; i < res->num; i++) TEMPLATE(T, poly_mul) (product, product, res->poly + i, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (product, product, poly1->coeffs + (poly1->length - 1), ctx); if (!TEMPLATE(T, poly_equal) (poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n"); flint_printf("product:\n"); TEMPLATE(T, poly_print) (product, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(degs); TEMPLATE(T, poly_clear) (product, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_factor_clear) (res, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-factor_equal_deg_prob.c000066400000000000000000000053451461254215100264100ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_equal_deg_prob, state) { int iter; for (iter = 0; iter < 5 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly1, poly2, q, r; slong length; int i, num; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly2, ctx); length = n_randint(state, 10) + 2; do { TEMPLATE(T, poly_randtest) (poly1, state, length, ctx); if (poly1->length) TEMPLATE(T, poly_make_monic) (poly1, poly1, ctx); } while ((poly1->length != length) || (!TEMPLATE(T, poly_is_irreducible) (poly1, ctx))); num = n_randint(state, 5) + 1; for (i = 0; i < num; i++) { do { TEMPLATE(T, poly_randtest) (poly2, state, length, ctx); if (poly2->length) TEMPLATE(T, poly_make_monic) (poly2, poly2, ctx); } while ((poly2->length != length) || (!TEMPLATE(T, poly_is_irreducible) (poly2, ctx))); TEMPLATE(T, poly_mul) (poly1, poly1, poly2, ctx); } while (!TEMPLATE(T, poly_factor_equal_deg_prob) (poly2, state, poly1, length - 1, ctx)) { }; TEMPLATE(T, poly_divrem) (q, r, poly1, poly2, ctx); if (!TEMPLATE(T, poly_is_zero) (r, ctx)) { flint_printf("FAIL:\n"); flint_printf ("Error: factor does not divide original polynomial\n"); flint_printf("factor:\n"); TEMPLATE(T, poly_print) (poly2, ctx); flint_printf("\n\n"); flint_printf("polynomial:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-factor_kaltofen_shoup.c000066400000000000000000000104341461254215100264540ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_kaltofen_shoup, state) { int iter; for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly1, poly, q, r, product; TEMPLATE(T, poly_factor_t) res; slong i, j, length, num; slong exp[5]; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_one) (poly1, ctx); length = n_randint(state, 7) + 2; do { TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) TEMPLATE(T, poly_make_monic) (poly, poly, ctx); } while ((poly->length != length) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx))); exp[0] = n_randint(state, 5) + 1; for (i = 0; i < exp[0]; i++) { TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); } num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 5) + 2; TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) { TEMPLATE(T, poly_make_monic) (poly, poly, ctx); TEMPLATE(T, poly_divrem) (q, r, poly1, poly, ctx); } } while ((poly->length != length) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx)) || (r->length == 0)); exp[i] = n_randint(state, 5) + 1; for (j = 0; j < exp[i]; j++) { TEMPLATE(T, poly_mul) (poly1, poly1, poly, ctx); } } TEMPLATE(T, poly_factor_init) (res, ctx); TEMPLATE(T, poly_factor_kaltofen_shoup) (res, poly1, ctx); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_init) (product, ctx); TEMPLATE(T, poly_one) (product, ctx); for (i = 0; i < res->num; i++) { for (j = 0; j < res->exp[i]; j++) { TEMPLATE(T, poly_mul) (product, product, res->poly + i, ctx); } } TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (product, product, poly1->coeffs + (poly1->length - 1), ctx); if (!TEMPLATE(T, poly_equal) (poly1, product, ctx)) { flint_printf ("Error: product of factors does not equal to the original polynomial\n"); TEMPLATE(T, ctx_print) (ctx); flint_printf("\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print_pretty) (poly1, "x", ctx); flint_printf("\n"); flint_printf("product:\n"); TEMPLATE(T, poly_print_pretty) (product, "x", ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, ctx_clear) (ctx); TEMPLATE(T, poly_clear) (product, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_factor_clear) (res, ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-factor_split_single.c000066400000000000000000000043461461254215100261340ustar00rootroot00000000000000/* Copyright (C) 2019 Edouard Rousseau This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_split_single, state) { int iter; /* Compute a random splitting polynomial then check factorization */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { int len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); /* random splitting monic polynomial of degree len */ TEMPLATE(T, poly_randtest_monic) (a, state, 2, ctx); while (TEMPLATE(T, poly_degree) (a, ctx) < len) { TEMPLATE(T, poly_randtest_monic) (b, state, 2, ctx); TEMPLATE(T, poly_mul)(a, a, b, ctx); } /* b should be a factor of a */ TEMPLATE(T, poly_factor_split_single) (b, a, ctx); /* check that b divides a */ TEMPLATE(T, poly_divrem) (q, r, a, b, ctx); if (!TEMPLATE(T, poly_is_zero) (r, ctx)) { flint_printf("FAIL:\n"); flint_printf ("Error: factor does not divide original polynomial\n"); flint_printf("factor:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n\n"); flint_printf("polynomial:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-factor_squarefree.c000066400000000000000000000072561461254215100256050ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "ulong_extras.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_squarefree, state) { int iter; for (iter = 0; iter < 5 * flint_test_multiplier(); iter++) { int result = 1; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) pol1, poly, quot, rem; TEMPLATE(T, poly_factor_t) res; slong exp[5], prod1; slong length, i, j, num; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (pol1, ctx); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (quot, ctx); TEMPLATE(T, poly_init) (rem, ctx); TEMPLATE(T, poly_one) (pol1, ctx); length = n_randint(state, 5) + 2; do { TEMPLATE(T, poly_randtest) (poly, state, length, ctx); TEMPLATE(T, poly_make_monic) (poly, poly, ctx); } while ((poly->length != length) || (!TEMPLATE(T, poly_is_irreducible) (poly, ctx))); exp[0] = n_randprime(state, 5, 0); prod1 = exp[0]; for (i = 0; i < exp[0]; i++) TEMPLATE(T, poly_mul) (pol1, pol1, poly, ctx); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; TEMPLATE(T, poly_randtest) (poly, state, length, ctx); if (poly->length) { TEMPLATE(T, poly_make_monic) (poly, poly, ctx); TEMPLATE(T, poly_divrem) (quot, rem, pol1, poly, ctx); } } while ((!TEMPLATE(T, poly_is_irreducible) (poly, ctx)) || (poly->length != length) || (rem->length == 0)); do exp[i] = n_randprime(state, 5, 0); while (prod1 % exp[i] == 0); prod1 *= exp[i]; for (j = 0; j < exp[i]; j++) TEMPLATE(T, poly_mul) (pol1, pol1, poly, ctx); } TEMPLATE(T, poly_factor_init) (res, ctx); TEMPLATE(T, poly_factor_squarefree) (res, pol1, ctx); result &= (res->num == num); if (result) { ulong prod2 = 1; for (i = 0; i < num; i++) prod2 *= res->exp[i]; result &= (prod1 == prod2); } if (!result) { flint_printf("Error: exp don't match. Ctx = "); TEMPLATE(T, ctx_print) (ctx); flint_printf("\n"); for (i = 0; i < res->num; i++) flint_printf("%wd ", res->exp[i]); flint_printf("\n"); for (i = 0; i < num; i++) flint_printf("%wd ", exp[i]); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (quot, ctx); TEMPLATE(T, poly_clear) (rem, ctx); TEMPLATE(T, poly_clear) (pol1, ctx); TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_factor_clear) (res, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-is_irreducible.c000066400000000000000000000044521461254215100250640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_is_irreducible, state) { int iter; for (iter = 0; iter < 5 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly1, poly2; slong length; int i, num; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly2, ctx); length = n_randint(state, 5) + 2; do { TEMPLATE(T, poly_randtest) (poly1, state, length, ctx); if (!TEMPLATE(T, poly_is_zero) (poly1, ctx)) TEMPLATE(T, poly_make_monic) (poly1, poly1, ctx); } while ((!TEMPLATE(T, poly_is_irreducible) (poly1, ctx)) || (poly1->length < 2)); num = n_randint(state, 5) + 1; for (i = 0; i < num; i++) { do { TEMPLATE(T, poly_randtest) (poly2, state, length, ctx); if (!TEMPLATE(T, poly_is_zero) (poly2, ctx)) TEMPLATE(T, poly_make_monic) (poly2, poly2, ctx); } while ((!TEMPLATE(T, poly_is_irreducible) (poly2, ctx)) || (poly2->length < 2)); TEMPLATE(T, poly_mul) (poly1, poly1, poly2, ctx); } if (TEMPLATE(T, poly_is_irreducible) (poly1, ctx)) { flint_printf ("Error: reducible polynomial declared irreducible!\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-is_irreducible_ben_or.c000066400000000000000000000045061461254215100264100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_is_irreducible_ben_or, state) { int iter; for (iter = 0; iter < 5 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly1, poly2; slong length; int i, num; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly2, ctx); length = n_randint(state, 7) + 2; do { TEMPLATE(T, poly_randtest) (poly1, state, length, ctx); if (!TEMPLATE(T, poly_is_zero) (poly1, ctx)) TEMPLATE(T, poly_make_monic) (poly1, poly1, ctx); } while ((!TEMPLATE(T, poly_is_irreducible_ben_or) (poly1, ctx)) || (poly1->length < 2)); num = n_randint(state, 5) + 1; for (i = 0; i < num; i++) { do { TEMPLATE(T, poly_randtest) (poly2, state, length, ctx); if (!TEMPLATE(T, poly_is_zero) (poly2, ctx)) TEMPLATE(T, poly_make_monic) (poly2, poly2, ctx); } while ((!TEMPLATE(T, poly_is_irreducible_ben_or) (poly2, ctx)) || (poly2->length < 2)); TEMPLATE(T, poly_mul) (poly1, poly1, poly2, ctx); } if (TEMPLATE(T, poly_is_irreducible_ben_or) (poly1, ctx)) { flint_printf ("Error: reducible polynomial declared irreducible!\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-is_irreducible_ddf.c000066400000000000000000000044721461254215100257030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_is_irreducible_ddf, state) { int iter; for (iter = 0; iter < 5 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly1, poly2; slong length; int i, num; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly2, ctx); length = n_randint(state, 7) + 2; do { TEMPLATE(T, poly_randtest) (poly1, state, length, ctx); if (!TEMPLATE(T, poly_is_zero) (poly1, ctx)) TEMPLATE(T, poly_make_monic) (poly1, poly1, ctx); } while ((!TEMPLATE(T, poly_is_irreducible_ddf) (poly1, ctx)) || (poly1->length < 2)); num = n_randint(state, 5) + 1; for (i = 0; i < num; i++) { do { TEMPLATE(T, poly_randtest) (poly2, state, length, ctx); if (!TEMPLATE(T, poly_is_zero) (poly2, ctx)) TEMPLATE(T, poly_make_monic) (poly2, poly2, ctx); } while ((!TEMPLATE(T, poly_is_irreducible_ddf) (poly2, ctx)) || (poly2->length < 2)); TEMPLATE(T, poly_mul) (poly1, poly1, poly2, ctx); } if (TEMPLATE(T, poly_is_irreducible_ddf) (poly1, ctx)) { flint_printf ("Error: reducible polynomial declared irreducible!\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-is_squarefree.c000066400000000000000000000061321461254215100247320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_is_squarefree, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly, Q, R, t; fmpz_t x; #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) fmpz_t m; #endif slong i, num_factors, exp, max_exp; int v, result; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (Q, ctx); TEMPLATE(T, poly_init) (R, ctx); fmpz_init(x); #if defined(FQ_NMOD_POLY_FACTOR_H) || defined(FQ_ZECH_POLY_FACTOR_H) fmpz_init_set_ui(m, TEMPLATE(T, ctx_prime)(ctx)); fmpz_randtest_mod(x, state, m); fmpz_clear(m); #else fmpz_randtest_mod(x, state, TEMPLATE(T, ctx_prime)(ctx)); #endif TEMPLATE(T, poly_set_coeff_fmpz) (poly, 0, x, ctx); num_factors = n_randint(state, 5); max_exp = 0; for (i = 0; i < num_factors; i++) { do { TEMPLATE(T, poly_randtest) (t, state, n_randint(state, 10), ctx); } while (!TEMPLATE(T, poly_is_irreducible) (t, ctx) || (TEMPLATE(T, poly_length) (t, ctx) < 2)); exp = n_randint(state, 4) + 1; if (n_randint(state, 2) == 0) exp = 1; TEMPLATE(T, poly_divrem) (Q, R, poly, t, ctx); if (!TEMPLATE(T, poly_is_zero) (R, ctx)) { TEMPLATE(T, poly_pow) (t, t, exp, ctx); TEMPLATE(T, poly_mul) (poly, poly, t, ctx); max_exp = FLINT_MAX(exp, max_exp); } } v = TEMPLATE(T, poly_is_squarefree) (poly, ctx); if (v == 1) result = (max_exp <= 1 && !TEMPLATE(T, poly_is_zero) (poly, ctx)); else result = (max_exp > 1 || TEMPLATE(T, poly_is_zero) (poly, ctx)); if (!result) { flint_printf("FAIL: "); TEMPLATE(T, ctx_print) (ctx); flint_printf(" %wd, %d\n", max_exp, v); TEMPLATE(T, poly_print) (poly, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (Q, ctx); TEMPLATE(T, poly_clear) (R, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-iterated_frobenius_preinv.c000066400000000000000000000051271461254215100273400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_factor_iterated_frobenius_preinv, state) { int i, j; for (j = 0; j < 20 * flint_test_multiplier(); j++) { int result; fmpz_t q; slong n; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) v, vinv, *h1, *h2; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); fmpz_init(q); TEMPLATE(T, ctx_order) (q, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (vinv, ctx); TEMPLATE(T, poly_randtest_monic) (v, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (vinv, v, v->length, ctx); TEMPLATE(T, poly_inv_series_newton) (vinv, vinv, v->length, ctx); n = n_randint(state, 5) + 2; if (!(h1 = flint_malloc((2 * n) * sizeof(TEMPLATE(T, poly_struct))))) { flint_printf("Exception (t-fq_poly_iterated_frobenius_preinv):\n"); flint_printf("Not enough memory.\n"); fflush(stdout); flint_abort(); } h2 = h1 + n; for (i = 0; i < 2 * n; i++) TEMPLATE(T, poly_init) (h1[i], ctx); TEMPLATE(T, poly_iterated_frobenius_preinv) (h1, n, v, vinv, ctx); TEMPLATE(T, poly_gen) (h2[0], ctx); for (i = 1; i < n; i++) TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (h2[i], h2[i - 1], q, 0, v, vinv, ctx); result = 1; for (i = 0; i < n; i++) result = result && TEMPLATE(T, poly_equal) (h1[i], h2[i], ctx); if (!result) { flint_printf("FAIL (composition):\n"); flint_printf("v:\n"); TEMPLATE(T, poly_print) (v, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (vinv, ctx); for (i = 0; i < 2 * n; i++) TEMPLATE(T, poly_clear) (h1[i], ctx); flint_free(h1); TEMPLATE(T, ctx_clear) (ctx); fmpz_clear(q); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_factor_templates/test/t-roots.c000066400000000000000000000071331461254215100232450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" void test_poly( TEMPLATE(T, poly_factor_t) roots, const TEMPLATE(T, poly_t) f, int want_mult, const TEMPLATE(T, ctx_t) ctx) { slong i, multiplicity; TEMPLATE(T, poly_t) q, qt, r; TEMPLATE(T, poly_init)(q, ctx); TEMPLATE(T, poly_init)(qt, ctx); TEMPLATE(T, poly_init)(r, ctx); TEMPLATE(T, poly_set)(q, f, ctx); TEMPLATE(T, poly_roots)(roots, f, want_mult, ctx); for (i = 0; i < roots->num; i++) { if (TEMPLATE(T, poly_degree)(roots->poly + i, ctx) != 1) { flint_printf("FAILED:\ncheck root is linear\n"); fflush(stdout); flint_abort(); } if (TEMPLATE(T, is_one)(roots->poly[i].coeffs + 1, ctx) == 0) { flint_printf("FAILED:\ncheck root is monic\n"); fflush(stdout); flint_abort(); } multiplicity = 0; while (TEMPLATE(T, poly_divrem)(qt, r, q, roots->poly + i, ctx), TEMPLATE(T, poly_is_zero)(r, ctx)) { TEMPLATE(T, poly_swap)(q, qt, ctx); multiplicity++; } if (multiplicity <= 0) { flint_printf("FAILED:\ncheck root is a root\n"); fflush(stdout); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, poly_roots)(roots, q, want_mult, ctx); if (roots->num > 0) { flint_printf("FAILED:\ncheck missing roots\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(q, ctx); TEMPLATE(T, poly_clear)(qt, ctx); TEMPLATE(T, poly_clear)(r, ctx); } TEST_TEMPLATE_FUNCTION_START(T, poly_factor_roots, state) { slong i, j, k, l; for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong n, m; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f; TEMPLATE(T, poly_factor_t) r; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init)(f, ctx); TEMPLATE(T, poly_factor_init)(r, ctx); n = 1 + n_randint(state, 10); m = n_randint(state, 5); for (j = 0; j < 4; j++) { TEMPLATE(T, poly_randtest_not_zero)(f, state, n, ctx); for (k = 0; k < m; k++) { TEMPLATE(T, poly_t) ff; TEMPLATE(T, poly_init)(ff, ctx); TEMPLATE(T, poly_randtest_not_zero)(ff, state, 2, ctx); for (l = 1 + n_randint(state, 5); l > 0; l--) TEMPLATE(T, poly_mul)(f, f, ff, ctx); TEMPLATE(T, poly_clear)(ff, ctx); } if (n_randint(state, 2)) { test_poly(r, f, 1, ctx); test_poly(r, f, 0, ctx); } else { test_poly(r, f, 0, ctx); test_poly(r, f, 1, ctx); } } TEMPLATE(T, poly_factor_clear)(r, ctx); TEMPLATE(T, poly_clear)(f, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates.h000066400000000000000000001366611461254215100173370ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "nmod_types.h" #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif /* Memory management ********************************************************/ void TEMPLATE(T, poly_init)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_init2)(TEMPLATE(T, poly_t) poly, slong alloc, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_realloc)(TEMPLATE(T, poly_t) poly, slong alloc, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_truncate)(TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_set_trunc)(TEMPLATE(T, poly_t) poly1, TEMPLATE(T, poly_t) poly2, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_fit_length)(TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_clear)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_normalise)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_normalise2)(const TEMPLATE(T, struct) *poly, slong *length, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_set_length)(TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx); /* Polynomial parameters ***************************************************/ FQ_POLY_TEMPLATES_INLINE slong TEMPLATE(T, poly_length)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return poly->length; } FQ_POLY_TEMPLATES_INLINE slong TEMPLATE(T, poly_degree)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return poly->length - 1; } FQ_POLY_TEMPLATES_INLINE TEMPLATE(T, struct) * TEMPLATE(T, poly_lead)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return poly->length > 0 ? poly->coeffs + (poly->length - 1) : NULL; } /* Randomisation ***********************************************************/ void TEMPLATE(T, poly_randtest)(TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_randtest_not_zero)(TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_randtest_monic) (TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_randtest_irreducible) (TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); /* Assignment and basic manipulation ***************************************/ void _TEMPLATE(T, poly_set)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_set)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE3(T, poly_set, T)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_set_fmpz_mod_poly)(TEMPLATE(T, poly_t) rop, const fmpz_mod_poly_t op, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_set_nmod_poly)(TEMPLATE(T, poly_t) rop, const nmod_poly_t op, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_swap)(TEMPLATE(T, poly_t) op1, TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_zero)(TEMPLATE(T, struct) *rop, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_zero)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_one)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_gen)(TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_make_monic)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong length, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_make_monic)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_reverse)(TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, slong len, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_reverse)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, ctx_t) ctx); ulong TEMPLATE(T, poly_deflation)(const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_deflate)(TEMPLATE(T, poly_t) result, const TEMPLATE(T, poly_t) input, ulong deflation, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_inflate)(TEMPLATE(T, poly_t) result, const TEMPLATE(T, poly_t) input, ulong inflation, const TEMPLATE(T, ctx_t) ctx); /* Getting and setting coefficients ****************************************/ void TEMPLATE(T, poly_get_coeff)(TEMPLATE(T, t) x, const TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_set_coeff)(TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_set_coeff_fmpz)(TEMPLATE(T, poly_t) poly, slong n, const fmpz_t x, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_is_gen)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); /* Comparison **************************************************************/ int TEMPLATE(T, poly_equal)(const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_equal_trunc)(const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, slong n, const TEMPLATE(T, ctx_t) ctx); FQ_POLY_TEMPLATES_INLINE int TEMPLATE(T, poly_is_zero)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return (poly->length == 0); } int TEMPLATE(T, poly_is_one)(const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_is_unit)(const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE3(T, poly_equal, T)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx); /* Addition and subtraction ************************************************/ void _TEMPLATE(T, poly_add)(TEMPLATE(T, struct) *res, const TEMPLATE(T, struct) *poly1, slong len1, const TEMPLATE(T, struct) *poly2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_add)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_add_si)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, slong c, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_add_series)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_sub)(TEMPLATE(T, struct) *res, const TEMPLATE(T, struct) *poly1, slong len1, const TEMPLATE(T, struct) *poly2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_sub)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_sub_series)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_neg)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_neg)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); /* Scalar multiplication and division **************************************/ void _TEMPLATE3(T, poly_scalar_mul, T)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE3(T, poly_scalar_mul, T)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE3(T, poly_scalar_div, T)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE3(T, poly_scalar_div, T)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE3(T, poly_scalar_addmul, T)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE3(T, poly_scalar_addmul, T)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE3(T, poly_scalar_submul, T)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE3(T, poly_scalar_submul, T)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); /* Multiplication **********************************************************/ void _TEMPLATE(T, poly_mul_classical)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mul_classical)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mul_reorder)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mul_reorder)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mul_univariate)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mul_univariate)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mul_KS)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mul_KS)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mul)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mul)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mullow_classical)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mullow_classical)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mullow_KS)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mullow_KS)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mullow_univariate)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mullow_univariate)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mullow)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mullow)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mulhigh_classical)( TEMPLATE(T, struct)* rop, const TEMPLATE(T, struct)* op1, slong len1, const TEMPLATE(T, struct)* op2, slong len2, slong start, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mulhigh_classical)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong start, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mulhigh)(TEMPLATE(T, struct)* res, const TEMPLATE(T, struct)* poly1, slong len1, const TEMPLATE(T, struct)* poly2, slong len2, slong n, TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mulhigh)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong start, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mulmod)(TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mulmod)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_mulmod_preinv)(TEMPLATE(T, struct) *res, const TEMPLATE(T, struct) *poly1, slong len1, const TEMPLATE(T, struct) *poly2, slong len2, const TEMPLATE(T, struct) *f, slong lenf, const TEMPLATE(T, struct) *finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_mulmod_preinv)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx); /* Squaring ******************************************************************/ void _TEMPLATE(T, poly_sqr_classical)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_sqr_classical)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_sqr_reorder)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_sqr_reorder)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_sqr_KS)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_sqr_KS)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_sqr)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_sqr)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); /* Powering ****************************************************************/ void _TEMPLATE(T, poly_pow)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, ulong e, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_pow)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, ulong e, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_pow_trunc_binexp) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_pow_trunc_binexp) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_pow_trunc) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_pow_trunc) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_powmod_fmpz_binexp)(TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, const fmpz_t e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_powmod_fmpz_binexp)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, const fmpz_t e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_powmod_fmpz_binexp_preinv)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, const fmpz_t e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) *finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_powmod_fmpz_binexp_preinv)( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, const fmpz_t e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_powmod_ui_binexp)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_powmod_ui_binexp)( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_powmod_ui_binexp_preinv)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_powmod_ui_binexp_preinv)( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, const fmpz_t e, ulong k, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, const fmpz_t e, ulong k, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_powmod_x_fmpz_preinv)( TEMPLATE(T, struct) * res, const fmpz_t e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct)* finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_powmod_x_fmpz_preinv)( TEMPLATE(T, poly_t) res, const fmpz_t e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx); /* Shifting ****************************************************************/ void _TEMPLATE(T, poly_shift_left)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_shift_left)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_shift_right)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_shift_right)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, slong n, const TEMPLATE(T, ctx_t) ctx); /* Norms *******************************************************************/ slong _TEMPLATE(T, poly_hamming_weight)(const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); slong TEMPLATE(T, poly_hamming_weight)(const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); /* Greatest common divisor *************************************************/ void TEMPLATE(T, poly_gcd_euclidean)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); slong _TEMPLATE(T, poly_gcd_euclidean)(TEMPLATE(T, struct)* G, const TEMPLATE(T, struct)* A, slong lenA, const TEMPLATE(T, struct)* B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx); slong _TEMPLATE(T, poly_gcd)(TEMPLATE(T, struct)* G, const TEMPLATE(T, struct)* A, slong lenA, const TEMPLATE(T, struct)* B, slong lenB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_gcd)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); slong _TEMPLATE(T, poly_gcd_euclidean_f)(TEMPLATE(T, t) f, TEMPLATE(T, struct)* G, const TEMPLATE(T, struct)* A, slong lenA, const TEMPLATE(T, struct)* B, slong lenB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_gcd_euclidean_f)(TEMPLATE(T, t) f, TEMPLATE(T, poly_t) G, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); slong _TEMPLATE(T, poly_xgcd_euclidean_f)(TEMPLATE(T, t) f, TEMPLATE(T, struct) *G, TEMPLATE(T, struct) *S, TEMPLATE(T, struct) *T, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_xgcd_euclidean_f)(TEMPLATE(T, t) f, TEMPLATE(T, poly_t) G, TEMPLATE(T, poly_t) S, TEMPLATE(T, poly_t) T, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); slong _TEMPLATE(T, poly_xgcd)(TEMPLATE(T, struct) *G, TEMPLATE(T, struct) *S, TEMPLATE(T, struct) *T, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_xgcd)(TEMPLATE(T, poly_t) G, TEMPLATE(T, poly_t) S, TEMPLATE(T, poly_t) T, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); /* Euclidean division ******************************************************/ ulong TEMPLATE(T, poly_remove)(TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) g, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_div)(TEMPLATE(T, struct) *Q, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_div)(TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); /* flint 2.x compatibility needed by Nemo */ void TEMPLATE(T, poly_div_basecase)(TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_divrem)(TEMPLATE(T, struct) *Q, TEMPLATE(T, struct) *R, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_divrem)(TEMPLATE(T, poly_t) Q, TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_rem)(TEMPLATE(T, struct) *R, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_rem)(TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_inv_series_newton)(TEMPLATE(T, struct) * Qinv, const TEMPLATE(T, struct) * Q, slong n, const TEMPLATE(T, t) cinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_inv_series_newton)(TEMPLATE(T, poly_t) Qinv, const TEMPLATE(T, poly_t) Q, slong n, const TEMPLATE(T, ctx_t) ctx); FQ_POLY_TEMPLATES_INLINE void _TEMPLATE(T, poly_inv_series)(TEMPLATE(T, struct) * Qinv, const TEMPLATE(T, struct) * Q, slong n, const TEMPLATE(T, t) cinv, const TEMPLATE(T, ctx_t) ctx) { _TEMPLATE(T, poly_inv_series_newton) (Qinv, Q, n, cinv, ctx); } FQ_POLY_TEMPLATES_INLINE void TEMPLATE(T, poly_inv_series)(TEMPLATE(T, poly_t) Qinv, const TEMPLATE(T, poly_t) Q, slong n, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_inv_series_newton) (Qinv, Q, n, ctx); } void _TEMPLATE(T, poly_div_series) (TEMPLATE(T, struct) * Q, const TEMPLATE(T, struct) * A, slong Alen, const TEMPLATE(T, struct) * B, slong Blen, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_div_series)(TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_div_newton_n_preinv) ( TEMPLATE(T, struct) *Q, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct)* B, slong lenB, const TEMPLATE(T, struct)* Binv, slong lenBinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_div_newton_n_preinv) (TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, poly_t) Binv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_divrem_newton_n_preinv) ( TEMPLATE(T, struct)* Q, TEMPLATE(T, struct)* R, const TEMPLATE(T, struct)* A, slong lenA, const TEMPLATE(T, struct)* B, slong lenB, const TEMPLATE(T, struct)* Binv, slong lenBinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_divrem_newton_n_preinv)( TEMPLATE(T, poly_t) Q, TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, poly_t) Binv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_divrem_f)(TEMPLATE(T, t) f, TEMPLATE(T, struct)* Q, TEMPLATE(T, struct)* R, const TEMPLATE(T, struct)* A, slong lenA, const TEMPLATE(T, struct)* B, slong lenB, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_divrem_f)(TEMPLATE(T, t) f, TEMPLATE(T, poly_t) Q, TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); /* Divisibility testing ***************************************************/ int _TEMPLATE(T, poly_divides)(TEMPLATE(T, struct) *Q, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_divides)(TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); /* Derivative **************************************************************/ void _TEMPLATE(T, poly_derivative)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_derivative)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); /* Square root ***************************************************************/ void _TEMPLATE(T, poly_invsqrt_series)(TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong n, TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_invsqrt_series)(TEMPLATE(T, poly_t) g, const TEMPLATE(T, poly_t) h, slong n, TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_sqrt_series)(TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong n, TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_sqrt_series)(TEMPLATE(T, poly_t) g, const TEMPLATE(T, poly_t) h, slong n, TEMPLATE(T, ctx_t) ctx); int _TEMPLATE(T, poly_sqrt)(TEMPLATE(T, struct) * s, const TEMPLATE(T, struct) * p, slong len, TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_sqrt)(TEMPLATE(T, poly_t) b, const TEMPLATE(T, poly_t) a, TEMPLATE(T, ctx_t) ctx); /* Evaluation **************************************************************/ void _TEMPLATE3(T, poly_evaluate, T)(TEMPLATE(T, t) rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, t) a, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE3(T, poly_evaluate, T)(TEMPLATE(T, t) res, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, t) a, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE4(T, poly_evaluate, T, vec)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, struct) *coeffs, slong len, const TEMPLATE(T, struct) *xs, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE4(T, poly_evaluate, T, vec)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx); TEMPLATE(T, poly_struct) ** _TEMPLATE(T, poly_tree_alloc)(slong len, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_tree_free)(TEMPLATE(T, poly_struct) ** tree, slong len, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_tree_build)(TEMPLATE(T, poly_struct) ** tree, const TEMPLATE(T, struct) * roots, slong len, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE4(T, poly_evaluate, T, vec_fast_precomp) (TEMPLATE(T, struct) * vs, const TEMPLATE(T, struct) * poly, slong plen, TEMPLATE(T, poly_struct) * const * tree, slong len, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE4(T, poly_evaluate, T, vec_fast)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, struct) * poly, slong plen, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE4(T, poly_evaluate, T, vec_fast)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, struct) *xs, slong n, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE4(T, poly_evaluate, T, vec_iter)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, struct) * coeffs, slong len, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE4(T, poly_evaluate, T, vec_iter)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx); /* Composition *************************************************************/ void _TEMPLATE(T, poly_compose)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_compose_mod)(TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose_mod)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_compose_mod_preinv)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, struct) * hinv, slong lenhinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose_mod_preinv)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_compose_mod_horner)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose_mod_horner)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_compose_mod_horner_preinv)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, struct) * hinv, slong lenhinv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose_mod_horner_preinv)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose_mod_brent_kung)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_compose_mod_brent_kung)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, const TEMPLATE(T, struct) * poly3, slong len3, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_compose_mod_brent_kung_preinv)( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, const TEMPLATE(T, struct) * poly3, slong len3, const TEMPLATE(T, struct) * poly3inv, slong len3inv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose_mod_brent_kung_preinv)( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_reduce_matrix_mod_poly) (TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_precompute_matrix) ( TEMPLATE(T, mat_t A), const TEMPLATE(T, struct)* poly1, const TEMPLATE(T, struct)* poly2, slong len2, const TEMPLATE(T, struct)* poly2inv, slong len2inv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_precompute_matrix) (TEMPLATE(T, mat_t A), const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly2inv, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv)( TEMPLATE(T, struct)* res, const TEMPLATE(T, struct)* poly1, slong len1, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, struct)* poly3, slong len3, const TEMPLATE(T, struct)* poly3inv, slong len3inv, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv)( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx); /* Input and output ********************************************************/ #ifdef FLINT_HAVE_FILE int _TEMPLATE(T, poly_fprint_pretty)(FILE *file, const TEMPLATE(T, struct) *poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_fprint_pretty)(FILE * file, const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx); int _TEMPLATE(T, poly_fprint)(FILE * file, const TEMPLATE(T, struct) *poly, slong len, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_fprint)(FILE * file, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); #endif int _TEMPLATE(T, poly_print)(const TEMPLATE(T, struct) *poly, slong len, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_print)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); int _TEMPLATE(T, poly_print_pretty)(const TEMPLATE(T, struct) *poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, poly_print_pretty)(const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx); char * _TEMPLATE(T, poly_get_str_pretty)(const TEMPLATE(T, struct) * poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx); char * TEMPLATE(T, poly_get_str_pretty)(const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx); char * _TEMPLATE(T, poly_get_str)(const TEMPLATE(T, struct) * poly, slong len, const TEMPLATE(T, ctx_t) ctx); char * TEMPLATE(T, poly_get_str)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); /* Characteristic polynomial ************************************************/ void TEMPLATE(T, mat_charpoly_danilevsky) (TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, mat_charpoly)(TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) M, const TEMPLATE(T, ctx_t) ctx); /* Minimal polynomial ************************************************/ void TEMPLATE(T, mat_minpoly) (TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) X, const TEMPLATE(T, ctx_t) ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_poly_templates/000077500000000000000000000000001461254215100171515ustar00rootroot00000000000000flint-3.1.3/src/fq_poly_templates/add.c000066400000000000000000000032101461254215100200410ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_add) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, ctx_t) ctx) { const slong min = FLINT_MIN(len1, len2); slong i; for (i = 0; i < min; i++) TEMPLATE(T, add) (res + i, poly1 + i, poly2 + i, ctx); if (poly1 != res) for (i = min; i < len1; i++) TEMPLATE(T, set) (res + i, poly1 + i, ctx); if (poly2 != res) for (i = min; i < len2; i++) TEMPLATE(T, set) (res + i, poly2 + i, ctx); } void TEMPLATE(T, poly_add) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, ctx_t) ctx) { const slong max = FLINT_MAX(poly1->length, poly2->length); TEMPLATE(T, poly_fit_length) (res, max, ctx); _TEMPLATE(T, poly_add) (res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _TEMPLATE(T, poly_set_length) (res, max, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/add_series.c000066400000000000000000000022771461254215100214270ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_add_series) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, slong n, const TEMPLATE(T, ctx_t) ctx) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); TEMPLATE(T, poly_fit_length) (res, max, ctx); _TEMPLATE(T, poly_add) (res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); _TEMPLATE(T, poly_set_length) (res, max, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/add_si.c000066400000000000000000000015641461254215100205460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "ulong_extras.h" void TEMPLATE(T, poly_add_si)( TEMPLATE(T, poly_t a), const TEMPLATE(T, poly_t) b, slong c, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init)(t, ctx); TEMPLATE(T, poly_fit_length)(t, 1, ctx); TEMPLATE(T, set_si)(t->coeffs + 0, c, ctx); t->length = !TEMPLATE(T, is_zero)(t->coeffs + 0, ctx); TEMPLATE(T, poly_add)(a, b, t, ctx); TEMPLATE(T, poly_clear)(t, ctx); } #endif flint-3.1.3/src/fq_poly_templates/clear.c000066400000000000000000000013111461254215100203770ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_clear) (TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { if (poly->coeffs) { _TEMPLATE(T, vec_clear) (poly->coeffs, poly->alloc, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/comparisons.c000066400000000000000000000022761461254215100216610ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, poly_is_one)(const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { return (op->length == 1) && (TEMPLATE(T, is_one)(op->coeffs + 0, ctx)); } int TEMPLATE(T, poly_is_unit)(const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { return (op->length == 1) && (!(TEMPLATE(T, is_zero)(op->coeffs + 0, ctx))); } int TEMPLATE3(T, poly_equal, T)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { return ((poly->length == 0) && TEMPLATE(T, is_zero)(c, ctx)) || ((poly->length == 1) && TEMPLATE(T, equal)(poly->coeffs, c, ctx)); } #endif flint-3.1.3/src/fq_poly_templates/compose.c000066400000000000000000000042451461254215100207670ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "gr_poly.h" void _TEMPLATE(T, poly_compose) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, const TEMPLATE(T, ctx_t) ctx) { gr_ctx_t gr_ctx; TEMPLATE3(_gr_ctx_init, T, from_ref)(gr_ctx, ctx); GR_MUST_SUCCEED(_gr_poly_compose(rop, op1, len1, op2, len2, gr_ctx)); } void TEMPLATE(T, poly_compose) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (len1 == 0) { TEMPLATE(T, poly_zero) (rop, ctx); } else if (len1 == 1 || len2 == 0) { TEMPLATE(T, TEMPLATE(poly_set, T)) (rop, op1->coeffs + 0, ctx); } else if (rop != op1 && rop != op2) { TEMPLATE(T, poly_fit_length) (rop, lenr, ctx); _TEMPLATE(T, poly_compose) (rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, ctx); _TEMPLATE(T, poly_set_length) (rop, lenr, ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } else { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, lenr, ctx); _TEMPLATE(T, poly_compose) (t->coeffs, op1->coeffs, len1, op2->coeffs, len2, ctx); _TEMPLATE(T, poly_set_length) (t, lenr, ctx); _TEMPLATE(T, poly_normalise) (t, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/compose_mod.c000066400000000000000000000062061461254215100216250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" void _TEMPLATE(T, poly_compose_mod) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, ctx_t) ctx) { if (lenh < TEMPLATE(CAP_T, COMPOSE_MOD_LENH_CUTOFF) || lenf >= lenh) _TEMPLATE(T, poly_compose_mod_horner) (res, f, lenf, g, h, lenh, ctx); else _TEMPLATE(T, poly_compose_mod_brent_kung) (res, f, lenf, g, h, lenh, ctx); } void TEMPLATE(T, poly_compose_mod) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) inv3; slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); TEMPLATE(T, struct) * ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (len1 == 0 || len3 == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 == 1) { TEMPLATE(T, poly_set) (res, poly1, ctx); return; } if (res == poly3 || res == poly1) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_compose_mod) (tmp, poly1, poly2, poly3, ctx); TEMPLATE(T, poly_swap) (tmp, res, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); return; } ptr2 = _TEMPLATE(T, vec_init) (vec_len, ctx); if (len2 <= len) { _TEMPLATE(T, vec_set) (ptr2, poly2->coeffs, len2, ctx); _TEMPLATE(T, vec_zero) (ptr2 + len2, len - len2, ctx); } else { TEMPLATE(T, init) (inv3, ctx); TEMPLATE(T, inv) (inv3, poly3->coeffs + len, ctx); _TEMPLATE(T, poly_rem) (ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); TEMPLATE(T, clear) (inv3, ctx); } TEMPLATE(T, poly_fit_length) (res, len, ctx); _TEMPLATE(T, poly_compose_mod) (res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, ctx); _TEMPLATE(T, poly_set_length) (res, len, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); _TEMPLATE(T, vec_clear) (ptr2, vec_len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/compose_mod_brent_kung.c000066400000000000000000000120201461254215100240320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_compose_mod_brent_kung) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, const TEMPLATE(T, struct) * poly3, slong len3, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, struct) * t, *h, *tmp; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { TEMPLATE(T, set) (res, poly1, ctx); return; } if (len3 == 2) { _TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (res, poly1, len1, poly2, ctx); return; } m = n_sqrt(n) + 1; TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, m, m, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); h = _TEMPLATE(T, vec_init) (2 * n - 1, ctx); t = _TEMPLATE(T, vec_init) (2 * n - 1, ctx); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _TEMPLATE(T, vec_set) (B->rows[i], poly1 + i * m, m, ctx); _TEMPLATE(T, vec_set) (B->rows[i], poly1 + i * m, len1 % m, ctx); /* Set rows of A to powers of poly2 */ TEMPLATE(T, one) (A->rows[0], ctx); _TEMPLATE(T, vec_set) (A->rows[1], poly2, n, ctx); tmp = _TEMPLATE(T, vec_init) (2 * n - 1, ctx); for (i = 2; i < m; i++) { _TEMPLATE(T, poly_mulmod) (tmp, A->rows[i - 1], n, poly2, n, poly3, len3, ctx); _TEMPLATE(T, vec_set) (A->rows[i], tmp, n, ctx); } _TEMPLATE(T, vec_clear) (tmp, 2 * n - 1, ctx); TEMPLATE(T, mat_mul) (C, B, A, ctx); /* Evaluate block composition using the Horner scheme */ _TEMPLATE(T, vec_set) (res, C->rows[m - 1], n, ctx); _TEMPLATE(T, poly_mulmod) (h, A->rows[m - 1], n, poly2, n, poly3, len3, ctx); for (i = m - 2; i >= 0; i--) { _TEMPLATE(T, poly_mulmod) (t, res, n, h, n, poly3, len3, ctx); _TEMPLATE(T, poly_add) (res, t, n, C->rows[i], n, ctx); } _TEMPLATE(T, vec_clear) (h, 2 * n - 1, ctx); _TEMPLATE(T, vec_clear) (t, 2 * n - 1, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); } void TEMPLATE(T, poly_compose_mod_brent_kung) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, ctx_t) ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); TEMPLATE(T, struct) * ptr2; TEMPLATE(T, t) inv3; if (len3 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(%s): The degree of the first polynomial must " "be smaller than that of the modulus\n", __func__); } if (len1 == 0 || len3 == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 == 1) { TEMPLATE(T, poly_set) (res, poly1, ctx); return; } if (res == poly3 || res == poly1) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (tmp, poly1, poly2, poly3, ctx); TEMPLATE(T, poly_swap) (tmp, res, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); return; } ptr2 = _TEMPLATE(T, vec_init) (vec_len, ctx); if (len2 <= len) { _TEMPLATE(T, vec_set) (ptr2, poly2->coeffs, len2, ctx); _TEMPLATE(T, vec_zero) (ptr2 + len2, vec_len - len2, ctx); } else { TEMPLATE(T, init) (inv3, ctx); TEMPLATE(T, inv) (inv3, poly3->coeffs + len, ctx); _TEMPLATE(T, poly_rem) (ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); TEMPLATE(T, clear) (inv3, ctx); } TEMPLATE(T, poly_fit_length) (res, len, ctx); _TEMPLATE(T, poly_compose_mod_brent_kung) (res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, ctx); _TEMPLATE(T, poly_set_length) (res, len, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); _TEMPLATE(T, vec_clear) (ptr2, vec_len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000167421461254215100271610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" void _TEMPLATE(T, poly_reduce_matrix_mod_poly) (TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { slong n = f->length - 1; slong i, m = n_sqrt(n) + 1; TEMPLATE(T, t) invf; TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (A, 0, 0), ctx); TEMPLATE(T, init) (invf, ctx); TEMPLATE(T, inv) (invf, f->coeffs + (f->length - 1), ctx); for (i = 1; i < m; i++) _TEMPLATE(T, poly_rem) (A->rows[i], B->rows[i], B->c, f->coeffs, f->length, invf, ctx); TEMPLATE(T, clear) (invf, ctx); } void _TEMPLATE(T, poly_precompute_matrix) ( TEMPLATE(T, mat_t) A, const TEMPLATE(T, struct) * poly1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, struct) * poly2inv, slong len2inv, const TEMPLATE(T, ctx_t) ctx) { /* Set rows of A to powers of poly1 */ slong i, n, m; n = len2 - 1; m = n_sqrt(n) + 1; TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (A, 0, 0), ctx); _TEMPLATE(T, vec_set) (A->rows[1], poly1, n, ctx); for (i = 2; i < m; i++) _TEMPLATE(T, poly_mulmod_preinv) (A->rows[i], A->rows[i - 1], n, poly1, n, poly2, len2, poly2inv, len2inv, ctx); } void TEMPLATE(T, poly_precompute_matrix) (TEMPLATE(T, mat_t) A, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly2inv, const TEMPLATE(T, ctx_t) ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong len = len2 - 1; slong m = n_sqrt(len) + 1; TEMPLATE(T, struct) * ptr1; if (len2 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero.\n", __func__); } if (A->r != m || A->c != len) { flint_throw(FLINT_ERROR, "(%s): Wrong dimensions.\n", __func__); } if (len2 == 1) { TEMPLATE(T, mat_zero) (A, ctx); return; } ptr1 = _TEMPLATE(T, vec_init) (len, ctx); if (len1 <= len) { _TEMPLATE(T, vec_set) (ptr1, poly1->coeffs, len1, ctx); _TEMPLATE(T, vec_zero) (ptr1 + len1, len - len1, ctx); } else { TEMPLATE(T, t) inv2; TEMPLATE(T, init) (inv2, ctx); TEMPLATE(T, inv) (inv2, poly2->coeffs + len2 - 1, ctx); _TEMPLATE(T, poly_rem) (ptr1, poly1->coeffs, len1, poly2->coeffs, len2, inv2, ctx); TEMPLATE(T, clear) (inv2, ctx); } _TEMPLATE(T, poly_precompute_matrix) (A, ptr1, poly2->coeffs, len2, poly2inv->coeffs, poly2inv->length, ctx); _TEMPLATE(T, vec_clear) (ptr1, len, ctx); } void _TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, struct) * poly3, slong len3, const TEMPLATE(T, struct) * poly3inv, slong len3inv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) B, C; TEMPLATE(T, struct) * t, *h; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { TEMPLATE(T, set) (res, poly1, ctx); return; } if (len3 == 2) { _TEMPLATE3(T, poly_evaluate, T) (res, poly1, len1, TEMPLATE(T, mat_entry) (A, 1, 0), ctx); return; } m = n_sqrt(n) + 1; /* TODO check A */ TEMPLATE(T, mat_init) (B, m, m, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); h = _TEMPLATE(T, vec_init) (n, ctx); t = _TEMPLATE(T, vec_init) (n, ctx); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _TEMPLATE(T, vec_set) (B->rows[i], poly1 + i * m, m, ctx); _TEMPLATE(T, vec_set) (B->rows[i], poly1 + i * m, len1 % m, ctx); TEMPLATE(T, mat_mul) (C, B, A, ctx); /* Evaluate block composition using the Horner scheme */ _TEMPLATE(T, vec_set) (res, C->rows[m - 1], n, ctx); _TEMPLATE(T, poly_mulmod_preinv) (h, A->rows[m - 1], n, A->rows[1], n, poly3, len3, poly3inv, len3inv, ctx); for (i = m - 2; i >= 0; i--) { _TEMPLATE(T, poly_mulmod_preinv) (t, res, n, h, n, poly3, len3, poly3inv, len3inv, ctx); _TEMPLATE(T, poly_add) (res, t, n, C->rows[i], n, ctx); } _TEMPLATE(T, vec_clear) (h, n, ctx); _TEMPLATE(T, vec_clear) (t, n, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); } void TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv) ( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx) { slong len1 = poly1->length; slong len3 = poly3->length; slong len = len3 - 1; if (len3 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero.\n", __func__); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(%s): The degree of the first polynomial must be smaller than that of the modulus.\n", __func__); } if (len1 == 0 || len3 == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 == 1) { TEMPLATE(T, poly_set) (res, poly1, ctx); return; } if (res == poly3 || res == poly1 || res == poly3inv) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv) (tmp, poly1, A, poly3, poly3inv, ctx); TEMPLATE(T, poly_swap) (tmp, res, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); return; } TEMPLATE(T, poly_fit_length) (res, len, ctx); _TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv) (res->coeffs, poly1->coeffs, len1, A, poly3->coeffs, len3, poly3inv->coeffs, poly3inv->length, ctx); res->length = len; _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/compose_mod_brent_kung_preinv.c000066400000000000000000000125331461254215100254260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_compose_mod_brent_kung_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, const TEMPLATE(T, struct) * poly3, slong len3, const TEMPLATE(T, struct) * poly3inv, slong len3inv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, struct) * t, *h, *tmp; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { TEMPLATE(T, set) (res, poly1, ctx); return; } if (len3 == 2) { _TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (res, poly1, len1, poly2, ctx); return; } m = n_sqrt(n) + 1; TEMPLATE(T, mat_init) (A, m, n, ctx); TEMPLATE(T, mat_init) (B, m, m, ctx); TEMPLATE(T, mat_init) (C, m, n, ctx); h = _TEMPLATE(T, vec_init) (2 * n - 1, ctx); t = _TEMPLATE(T, vec_init) (2 * n - 1, ctx); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _TEMPLATE(T, vec_set) (B->rows[i], poly1 + i * m, m, ctx); _TEMPLATE(T, vec_set) (B->rows[i], poly1 + i * m, len1 % m, ctx); /* Set rows of A to powers of poly2 */ TEMPLATE(T, one) (A->rows[0], ctx); _TEMPLATE(T, vec_set) (A->rows[1], poly2, n, ctx); tmp = _TEMPLATE(T, vec_init) (2 * n - 1, ctx); for (i = 2; i < m; i++) { _TEMPLATE(T, poly_mulmod_preinv) (tmp, A->rows[i - 1], n, poly2, n, poly3, len3, poly3inv, len3inv, ctx); _TEMPLATE(T, vec_set) (A->rows[i], tmp, n, ctx); } _TEMPLATE(T, vec_clear) (tmp, 2 * n - 1, ctx); TEMPLATE(T, mat_mul) (C, B, A, ctx); /* Evaluate block composition using the Horner scheme */ _TEMPLATE(T, vec_set) (res, C->rows[m - 1], n, ctx); _TEMPLATE(T, poly_mulmod_preinv) (h, A->rows[m - 1], n, poly2, n, poly3, len3, poly3inv, len3inv, ctx); for (i = m - 2; i >= 0; i--) { _TEMPLATE(T, poly_mulmod_preinv) (t, res, n, h, n, poly3, len3, poly3inv, len3inv, ctx); _TEMPLATE(T, poly_add) (res, t, n, C->rows[i], n, ctx); } _TEMPLATE(T, vec_clear) (h, 2 * n - 1, ctx); _TEMPLATE(T, vec_clear) (t, 2 * n - 1, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); } void TEMPLATE(T, poly_compose_mod_brent_kung_preinv) ( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len3inv = poly3inv->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); TEMPLATE(T, struct) * ptr2; TEMPLATE(T, t) inv3; if (len3 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(%s): The degree of the first polynomial must be smaller than that of the modulus\n", __func__); } if (len1 == 0 || len3 == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 == 1) { TEMPLATE(T, poly_set) (res, poly1, ctx); return; } if (res == poly3 || res == poly1) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (tmp, poly1, poly2, poly3, poly3inv, ctx); TEMPLATE(T, poly_swap) (tmp, res, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); return; } ptr2 = _TEMPLATE(T, vec_init) (vec_len, ctx); if (len2 <= len) { _TEMPLATE(T, vec_set) (ptr2, poly2->coeffs, len2, ctx); _TEMPLATE(T, vec_zero) (ptr2 + len2, vec_len - len2, ctx); } else { TEMPLATE(T, init) (inv3, ctx); TEMPLATE(T, inv) (inv3, poly3->coeffs + len, ctx); _TEMPLATE(T, poly_rem) (ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); TEMPLATE(T, clear) (inv3, ctx); } TEMPLATE(T, poly_fit_length) (res, len, ctx); _TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, poly3inv->coeffs, len3inv, ctx); _TEMPLATE(T, poly_set_length) (res, len, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); _TEMPLATE(T, vec_clear) (ptr2, vec_len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/compose_mod_horner.c000066400000000000000000000071101461254215100231750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" void _TEMPLATE(T, poly_compose_mod_horner) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, ctx_t) ctx) { slong i, len; TEMPLATE(T, struct) * t; if (lenh == 1) return; if (lenf == 1) { TEMPLATE(T, set) (res, f, ctx); return; } if (lenh == 2) { _TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (res, f, lenf, g, ctx); return; } len = lenh - 1; i = lenf - 1; t = _TEMPLATE(T, vec_init) (2 * lenh - 3, ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (res, g, len, f + i, ctx); i--; if (i >= 0) { TEMPLATE(T, add) (res, res, f + i, ctx); } while (i > 0) { i--; _TEMPLATE(T, poly_mulmod) (t, res, len, g, len, h, lenh, ctx); _TEMPLATE(T, poly_add) (res, t, len, f + i, 1, ctx); } _TEMPLATE(T, vec_clear) (t, 2 * lenh - 3, ctx); } void TEMPLATE(T, poly_compose_mod_horner) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) inv3; slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); TEMPLATE(T, struct) * ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (len1 == 0 || len3 == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 == 1) { TEMPLATE(T, poly_set) (res, poly1, ctx); return; } if (res == poly3 || res == poly1) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_compose_mod_horner) (tmp, poly1, poly2, poly3, ctx); TEMPLATE(T, poly_swap) (tmp, res, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); return; } ptr2 = _TEMPLATE(T, vec_init) (vec_len, ctx); if (len2 <= len3 - 1) { _TEMPLATE(T, vec_set) (ptr2, poly2->coeffs, len2, ctx); _TEMPLATE(T, vec_zero) (ptr2 + len2, vec_len - len2, ctx); } else { TEMPLATE(T, init) (inv3, ctx); TEMPLATE(T, inv) (inv3, poly3->coeffs + len, ctx); _TEMPLATE(T, poly_rem) (ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); TEMPLATE(T, clear) (inv3, ctx); } TEMPLATE(T, poly_fit_length) (res, len, ctx); _TEMPLATE(T, poly_compose_mod_horner) (res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, ctx); _TEMPLATE(T, poly_set_length) (res, len, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); _TEMPLATE(T, vec_clear) (ptr2, vec_len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/compose_mod_horner_preinv.c000066400000000000000000000076421461254215100245720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" void _TEMPLATE(T, poly_compose_mod_horner_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, struct) * hinv, slong lenhinv, const TEMPLATE(T, ctx_t) ctx) { slong i, len; TEMPLATE(T, struct) * t; if (lenh == 1) return; if (lenf == 1) { TEMPLATE(T, set) (res, f, ctx); return; } if (lenh == 2) { _TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (res, f, lenf, g, ctx); return; } len = lenh - 1; i = lenf - 1; t = _TEMPLATE(T, vec_init) (2 * lenh - 3, ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (res, g, len, f + i, ctx); i--; if (i >= 0) { TEMPLATE(T, add) (res, res, f + i, ctx); } while (i > 0) { i--; _TEMPLATE(T, poly_mulmod_preinv) (t, res, len, g, len, h, lenh, hinv, lenhinv, ctx); _TEMPLATE(T, poly_add) (res, t, len, f + i, 1, ctx); } _TEMPLATE(T, vec_clear) (t, 2 * lenh - 3, ctx); } void TEMPLATE(T, poly_compose_mod_horner_preinv) ( TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) inv3; slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len3inv = poly3inv->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); TEMPLATE(T, struct) * ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (len1 == 0 || len3 == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 == 1) { TEMPLATE(T, poly_set) (res, poly1, ctx); return; } if (res == poly3 || res == poly1) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (tmp, poly1, poly2, poly3, poly3inv, ctx); TEMPLATE(T, poly_swap) (tmp, res, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); return; } ptr2 = _TEMPLATE(T, vec_init) (vec_len, ctx); if (len2 <= len3 - 1) { _TEMPLATE(T, vec_set) (ptr2, poly2->coeffs, len2, ctx); _TEMPLATE(T, vec_zero) (ptr2 + len2, vec_len - len2, ctx); } else { TEMPLATE(T, init) (inv3, ctx); TEMPLATE(T, inv) (inv3, poly3->coeffs + len, ctx); _TEMPLATE(T, poly_rem) (ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); TEMPLATE(T, clear) (inv3, ctx); } TEMPLATE(T, poly_fit_length) (res, len, ctx); _TEMPLATE(T, poly_compose_mod_horner_preinv) (res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, poly3inv->coeffs, len3inv, ctx); _TEMPLATE(T, poly_set_length) (res, len, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); _TEMPLATE(T, vec_clear) (ptr2, vec_len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/compose_mod_preinv.c000066400000000000000000000071311461254215100232060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" void _TEMPLATE(T, poly_compose_mod_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong lenh, const TEMPLATE(T, struct) * hinv, slong lenhinv, const TEMPLATE(T, ctx_t) ctx) { if (lenh < TEMPLATE(CAP_T, COMPOSE_MOD_PREINV_LENH_CUTOFF) || lenf >= lenh) _TEMPLATE(T, poly_compose_mod_horner_preinv) (res, f, lenf, g, h, lenh, hinv, lenhinv, ctx); else _TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (res, f, lenf, g, h, lenh, hinv, lenhinv, ctx); } void TEMPLATE(T, poly_compose_mod_preinv) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) poly3, const TEMPLATE(T, poly_t) poly3inv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) inv3; slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len3inv = poly3inv->length; slong len = len3 - 1; slong vec_len = FLINT_MAX(len3 - 1, len2); TEMPLATE(T, struct) * ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (len1 == 0 || len3 == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 == 1) { TEMPLATE(T, poly_set) (res, poly1, ctx); return; } if (res == poly3 || res == poly1) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_compose_mod_preinv) (tmp, poly1, poly2, poly3, poly3inv, ctx); TEMPLATE(T, poly_swap) (tmp, res, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); return; } ptr2 = _TEMPLATE(T, vec_init) (vec_len, ctx); if (len2 <= len) { _TEMPLATE(T, vec_set) (ptr2, poly2->coeffs, len2, ctx); _TEMPLATE(T, vec_zero) (ptr2 + len2, len - len2, ctx); } else { TEMPLATE(T, init) (inv3, ctx); TEMPLATE(T, inv) (inv3, poly3->coeffs + len, ctx); _TEMPLATE(T, poly_rem) (ptr2, poly2->coeffs, len2, poly3->coeffs, len3, inv3, ctx); TEMPLATE(T, clear) (inv3, ctx); } TEMPLATE(T, poly_fit_length) (res, len, ctx); _TEMPLATE(T, poly_compose_mod_preinv) (res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, poly3inv->coeffs, len3inv, ctx); _TEMPLATE(T, poly_set_length) (res, len, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); _TEMPLATE(T, vec_clear) (ptr2, vec_len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/deflate.c000066400000000000000000000023451461254215100207250ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_deflate) (TEMPLATE(T, poly_t) result, const TEMPLATE(T, poly_t) input, ulong deflation, const TEMPLATE(T, ctx_t) ctx) { slong res_length, i; if (deflation == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (input->length <= 1 || deflation == 1) { TEMPLATE(T, poly_set) (result, input, ctx); return; } res_length = (input->length - 1) / deflation + 1; TEMPLATE(T, poly_fit_length) (result, res_length, ctx); for (i = 0; i < res_length; i++) TEMPLATE(T, set) (result->coeffs + i, input->coeffs + (i * deflation), ctx); result->length = res_length; } #endif flint-3.1.3/src/fq_poly_templates/deflation.c000066400000000000000000000023231461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" ulong TEMPLATE(T, poly_deflation) (const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx) { ulong deflation; slong i, coeff; if (input->length <= 1) return input->length; coeff = 1; while (TEMPLATE(T, is_zero) (input->coeffs + coeff, ctx)) coeff++; deflation = n_gcd(input->length - 1, coeff); while ((deflation > 1) && (coeff + deflation < input->length)) { for (i = 0; i < deflation - 1; i++) { coeff++; if (!TEMPLATE(T, is_zero) (input->coeffs + coeff, ctx)) deflation = n_gcd(coeff, deflation); } if (i == deflation - 1) coeff++; } return deflation; } #endif flint-3.1.3/src/fq_poly_templates/derivative.c000066400000000000000000000024531461254215100214630ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_derivative) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 1; i < len; i++) TEMPLATE(T, mul_ui) (rop + (i - 1), op + i, i, ctx); } void TEMPLATE(T, poly_derivative) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { const slong len = op->length; if (len < 2) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len - 1, ctx); _TEMPLATE(T, poly_derivative) (rop->coeffs, op->coeffs, len, ctx); _TEMPLATE(T, poly_set_length) (rop, len - 1, ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/div.c000066400000000000000000000052011461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "gr_poly.h" void _TEMPLATE(T, poly_div) (TEMPLATE(T, struct) * Q, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx) { gr_ctx_t gr_ctx; TEMPLATE3(_gr_ctx_init, T, from_ref)(gr_ctx, ctx); if (lenB <= 15 || lenA - lenB <= 15) GR_MUST_SUCCEED(_gr_poly_div_basecase_preinv1(Q, A, lenA, B, lenB, invB, gr_ctx)); else GR_MUST_SUCCEED(_gr_poly_div_newton(Q, A, lenA, B, lenB, gr_ctx)); /* todo: pass invB */ } void TEMPLATE(T, poly_div) (TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; TEMPLATE(T, struct) * q; TEMPLATE(T, t) invB; if (lenA < lenB) { TEMPLATE(T, poly_zero) (Q, ctx); return; } TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, inv) (invB, B->coeffs + (lenB - 1), ctx); if (Q == A || Q == B) { q = _TEMPLATE(T, vec_init) (lenQ, ctx); } else { TEMPLATE(T, poly_fit_length) (Q, lenQ, ctx); q = Q->coeffs; } _TEMPLATE(T, poly_div) (q, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _TEMPLATE(T, vec_clear) (Q->coeffs, Q->alloc, ctx); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _TEMPLATE(T, poly_set_length) (Q, lenQ, ctx); } TEMPLATE(T, clear) (invB, ctx); } /* flint 2.x compatibility needed by Nemo */ void TEMPLATE(T, poly_div_basecase) (TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_div) (Q, A, B, ctx); } #endif flint-3.1.3/src/fq_poly_templates/div_newton_n_preinv.c000066400000000000000000000045511461254215100233760ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_div_newton_n_preinv) ( TEMPLATE(T, struct) *Q, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, struct) * Binv, slong lenBinv, const TEMPLATE(T, ctx_t) ctx) { const slong lenQ = lenA - lenB + 1; TEMPLATE(T, struct) * Arev; Arev = _TEMPLATE(T, vec_init) (lenQ, ctx); _TEMPLATE(T, poly_reverse) (Arev, A + (lenA - lenQ), lenQ, lenQ, ctx); _TEMPLATE(T, poly_mullow) (Q, Arev, lenQ, Binv, FLINT_MIN(lenQ, lenBinv), lenQ, ctx); _TEMPLATE(T, poly_reverse) (Q, Q, lenQ, lenQ, ctx); _TEMPLATE(T, vec_clear) (Arev, lenQ, ctx); } void TEMPLATE(T, poly_div_newton_n_preinv) (TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, poly_t) Binv, const TEMPLATE(T, ctx_t) ctx) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1, lenBinv = Binv->length; TEMPLATE(T, struct) * q; if (lenB == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (lenA < lenB) { TEMPLATE(T, poly_zero) (Q, ctx); return; } if (Q == A || Q == B || Q == Binv) { q = _TEMPLATE(T, vec_init) (lenQ, ctx); } else { TEMPLATE(T, poly_fit_length) (Q, lenQ, ctx); q = Q->coeffs; } _TEMPLATE(T, poly_div_newton_n_preinv) (q, A->coeffs, lenA, B->coeffs, lenB, Binv->coeffs, lenBinv, ctx); if (Q == A || Q == B || Q == Binv) { TEMPLATE(T, poly_clear) (Q, ctx); Q->coeffs = q; Q->alloc = lenQ; } Q->length = lenQ; } #endif flint-3.1.3/src/fq_poly_templates/div_series.c000066400000000000000000000073121461254215100214540ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_div_series) (TEMPLATE(T, struct) * Q, const TEMPLATE(T, struct) * A, slong Alen, const TEMPLATE(T, struct) * B, slong Blen, slong n, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) u, d; TEMPLATE(T, init)(d, ctx); TEMPLATE(T, init)(u, ctx); if (!TEMPLATE(T, is_one)(B + 0, ctx)) TEMPLATE(T, inv)(u, B + 0, ctx); else TEMPLATE(T, set_si)(u, 1, ctx); Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (Blen == 1) { if (TEMPLATE(T, is_one)(B + 0, ctx)) _TEMPLATE(T, vec_set)(Q, A, Alen, ctx); else _TEMPLATE3(T, poly_scalar_mul, T)(Q, A, Alen, u, ctx); _TEMPLATE(T, vec_zero)(Q + Alen, n - Alen, ctx); } else if (n < 16 || Blen < 10) { slong i, j; TEMPLATE(T, t) temp; TEMPLATE(T, init)(temp, ctx); if (TEMPLATE(T, is_one)(B + 0, ctx)) TEMPLATE(T, set)(Q + 0, A + 0, ctx); else TEMPLATE(T, mul)(Q + 0, u, A + 0, ctx); for (i = 1; i < n; i++) { TEMPLATE(T, mul)(Q + i, B + 1, Q + i - 1, ctx); for (j = 2; j < FLINT_MIN(i + 1, Blen); j++) { TEMPLATE(T, mul)(temp, B + j, Q + i - j, ctx); TEMPLATE(T, add)(Q + i, Q + i, temp, ctx); } if (i < Alen) TEMPLATE(T, sub)(Q + i, A + i, Q + i, ctx); else TEMPLATE(T, neg)(Q + i, Q + i, ctx); if (!TEMPLATE(T, is_one)(B + 0, ctx)) TEMPLATE(T, mul)(Q + i, Q + i, u, ctx); } TEMPLATE(T, clear)(temp, ctx); } else { TEMPLATE(T, struct) * B2, * Binv = _TEMPLATE(T, vec_init)(n, ctx); if (n > Blen) { B2 = _TEMPLATE(T, vec_init)(n, ctx); _TEMPLATE(T, vec_set)(B2, B, Blen, ctx); } else B2 = (TEMPLATE(T, struct) *) B; _TEMPLATE(T, poly_inv_series)(Binv, B2, n, u, ctx); _TEMPLATE(T, poly_mullow)(Q, Binv, n, A, Alen, n, ctx); _TEMPLATE(T, vec_clear)(Binv, n, ctx); if (n > Blen) _TEMPLATE(T, vec_clear)(B2, n, ctx); } TEMPLATE(T, clear)(d, ctx); TEMPLATE(T, clear)(u, ctx); } void TEMPLATE(T, poly_div_series)(TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, slong n, const TEMPLATE(T, ctx_t) ctx) { slong Alen = FLINT_MIN(A->length, n); slong Blen = FLINT_MIN(B->length, n); if (Blen == 0) { flint_throw(FLINT_ERROR, "Exception (fq_poly_div_series). Division by zero.\n"); } if (Alen == 0) { TEMPLATE(T, poly_zero)(Q, ctx); return; } if (Q == A || Q == B) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2)(t, n, ctx); _TEMPLATE(T, poly_div_series)(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, ctx); TEMPLATE(T, poly_swap)(Q, t, ctx); TEMPLATE(T, poly_clear)(t, ctx); } else { TEMPLATE(T, poly_fit_length)(Q, n, ctx); _TEMPLATE(T, poly_div_series)(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, ctx); } _TEMPLATE(T, poly_set_length)(Q, n, ctx); _TEMPLATE(T, poly_normalise)(Q, ctx); } #endif flint-3.1.3/src/fq_poly_templates/divides.c000066400000000000000000000054331461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int _TEMPLATE(T, poly_divides) ( TEMPLATE(T, struct) * Q, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * R; slong lenR = lenB - 1; R = _TEMPLATE(T, vec_init) (lenA, ctx); _TEMPLATE(T, poly_divrem) (Q, R, A, lenA, B, lenB, invB, ctx); TEMPLATE(CAP_T, VEC_NORM) (R, lenR, ctx); _TEMPLATE(T, vec_clear) (R, lenA, ctx); return (lenR == 0); } int TEMPLATE(T, poly_divides) (TEMPLATE(T, poly_t) Q, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, poly_is_zero) (B, ctx)) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (TEMPLATE(T, poly_is_zero) (A, ctx)) { TEMPLATE(T, poly_zero) (Q, ctx); return 1; } if (TEMPLATE(T, poly_length) (A, ctx) < TEMPLATE(T, poly_length) (B, ctx)) { return 0; } { const slong lenQ = TEMPLATE(T, poly_length) (A, ctx) - TEMPLATE(T, poly_length) (B, ctx) + 1; int ans; TEMPLATE(T, t) invB; TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, inv) (invB, TEMPLATE(T, poly_lead) (B, ctx), ctx); if (Q == A || Q == B) { TEMPLATE(T, poly_t) T; TEMPLATE(T, poly_init2) (T, lenQ, ctx); ans = _TEMPLATE(T, poly_divides) (T->coeffs, A->coeffs, A->length, B->coeffs, B->length, invB, ctx); _TEMPLATE(T, poly_set_length) (T, lenQ, ctx); _TEMPLATE(T, poly_normalise) (T, ctx); TEMPLATE(T, poly_swap) (Q, T, ctx); TEMPLATE(T, poly_clear) (T, ctx); } else { TEMPLATE(T, poly_fit_length) (Q, lenQ, ctx); ans = _TEMPLATE(T, poly_divides) (Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, invB, ctx); _TEMPLATE(T, poly_set_length) (Q, lenQ, ctx); _TEMPLATE(T, poly_normalise) (Q, ctx); } TEMPLATE(T, clear) (invB, ctx); return ans; } } #endif flint-3.1.3/src/fq_poly_templates/divrem.c000066400000000000000000000057351461254215100206150ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "gr_poly.h" void _TEMPLATE(T, poly_divrem) (TEMPLATE(T, struct) * Q, TEMPLATE(T, struct) * R, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx) { gr_ctx_t gr_ctx; TEMPLATE3(_gr_ctx_init, T, from_ref)(gr_ctx, ctx); /* todo: tuning, and make sure it is also used in gr_poly_divrem */ if (lenB <= 10 || lenA - lenB <= 1) GR_MUST_SUCCEED(_gr_poly_divrem_basecase_preinv1(Q, R, A, lenA, B, lenB, invB, gr_ctx)); else GR_MUST_SUCCEED(_gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, gr_ctx)); /* todo: pass invB */ } void TEMPLATE(T, poly_divrem) (TEMPLATE(T, poly_t) Q, TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; TEMPLATE(T, struct) * q, *r; TEMPLATE(T, t) invB; if (lenA < lenB) { TEMPLATE(T, poly_set) (R, A, ctx); TEMPLATE(T, poly_zero) (Q, ctx); return; } TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, inv) (invB, TEMPLATE(T, poly_lead) (B, ctx), ctx); if (Q == A || Q == B) { q = _TEMPLATE(T, vec_init) (lenQ, ctx); } else { TEMPLATE(T, poly_fit_length) (Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { r = _TEMPLATE(T, vec_init) (lenA, ctx); } else { TEMPLATE(T, poly_fit_length) (R, lenA, ctx); r = R->coeffs; } _TEMPLATE(T, poly_divrem) (q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _TEMPLATE(T, vec_clear) (Q->coeffs, Q->alloc, ctx); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _TEMPLATE(T, poly_set_length) (Q, lenQ, ctx); } if (R == B) { _TEMPLATE(T, vec_clear) (R->coeffs, R->alloc, ctx); R->coeffs = r; R->alloc = lenA; R->length = lenA; } _TEMPLATE(T, poly_set_length) (R, lenB - 1, ctx); _TEMPLATE(T, poly_normalise) (R, ctx); TEMPLATE(T, clear) (invB, ctx); } #endif flint-3.1.3/src/fq_poly_templates/divrem_f.c000066400000000000000000000056471461254215100211240ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_divrem_f) (TEMPLATE(T, t) f, TEMPLATE(T, struct) * Q, TEMPLATE(T, struct) * R, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) invB; TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, gcdinv) (f, invB, B + lenB - 1, ctx); if (TEMPLATE(T, is_one) (f, ctx)) { _TEMPLATE(T, poly_divrem) (Q, R, A, lenA, B, lenB, invB, ctx); } TEMPLATE(T, clear) (invB, ctx); } void TEMPLATE(T, poly_divrem_f) (TEMPLATE(T, t) f, TEMPLATE(T, poly_t) Q, TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { const slong lenA = A->length; const slong lenB = B->length; const slong lenQ = lenA - lenB + 1; TEMPLATE(T, struct) * q, *r; TEMPLATE(T, t) invB; TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, gcdinv) (f, invB, TEMPLATE(T, poly_lead) (B, ctx), ctx); if (!TEMPLATE(T, is_one) (f, ctx)) { TEMPLATE(T, clear) (invB, ctx); return; } if (lenA < lenB) { TEMPLATE(T, poly_set) (R, A, ctx); TEMPLATE(T, poly_zero) (Q, ctx); TEMPLATE(T, clear) (invB, ctx); return; } if (Q == A || Q == B) { q = _TEMPLATE(T, vec_init) (lenQ, ctx); } else { TEMPLATE(T, poly_fit_length) (Q, lenQ, ctx); q = Q->coeffs; } if (R == A || R == B) { r = _TEMPLATE(T, vec_init) (lenA, ctx); } else { TEMPLATE(T, poly_fit_length) (R, lenA, ctx); r = R->coeffs; } _TEMPLATE(T, poly_divrem) (q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (Q == A || Q == B) { _TEMPLATE(T, vec_clear) (Q->coeffs, Q->alloc, ctx); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _TEMPLATE(T, poly_set_length) (Q, lenQ, ctx); } if (R == A || R == B) { _TEMPLATE(T, vec_clear) (R->coeffs, R->alloc, ctx); R->coeffs = r; R->alloc = lenA; R->length = lenA; } _TEMPLATE(T, poly_set_length) (R, lenB - 1, ctx); _TEMPLATE(T, poly_normalise) (R, ctx); TEMPLATE(T, clear) (invB, ctx); } #endif flint-3.1.3/src/fq_poly_templates/divrem_newton_n_preinv.c000066400000000000000000000062111461254215100240750ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_divrem_newton_n_preinv) ( TEMPLATE(T, struct) * Q, TEMPLATE(T, struct) * R, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, struct) * Binv, slong lenBinv, const TEMPLATE(T, ctx_t) ctx) { const slong lenQ = lenA - lenB + 1; _TEMPLATE(T, poly_div_newton_n_preinv) (Q, A, lenA, B, lenB, Binv, lenBinv, ctx); if (lenB > 1) { if (lenQ >= lenB - 1) _TEMPLATE(T, poly_mullow) (R, Q, lenQ, B, lenB - 1, lenB - 1, ctx); else _TEMPLATE(T, poly_mullow) (R, B, lenB - 1, Q, lenQ, lenB - 1, ctx); _TEMPLATE(T, vec_sub) (R, A, R, lenB - 1, ctx); } } void TEMPLATE(T, poly_divrem_newton_n_preinv) (TEMPLATE(T, poly_t) Q, TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, poly_t) Binv, const TEMPLATE(T, ctx_t) ctx) { const slong lenA = A->length, lenB = B->length, lenBinv = Binv->length; TEMPLATE(T, struct) * q, *r; if (lenB == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (lenA < lenB) { TEMPLATE(T, poly_set) (R, A, ctx); TEMPLATE(T, poly_zero) (Q, ctx); return; } if (lenA > 2 * lenB - 2) { TEMPLATE_PRINTF("Exception (%s_poly_divrem_newton_n_preinv).\n", T); } if (Q == A || Q == B || Q == Binv) { q = _TEMPLATE(T, vec_init) (lenA - lenB + 1, ctx); } else { TEMPLATE(T, poly_fit_length) (Q, lenA - lenB + 1, ctx); q = Q->coeffs; } if (R == A || R == B || R == Binv) { r = _TEMPLATE(T, vec_init) (lenB - 1, ctx); } else { TEMPLATE(T, poly_fit_length) (R, lenB - 1, ctx); r = R->coeffs; } _TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, A->coeffs, lenA, B->coeffs, lenB, Binv->coeffs, lenBinv, ctx); if (Q == A || Q == B || Q == Binv) { _TEMPLATE(T, vec_clear) (Q->coeffs, Q->alloc, ctx); Q->coeffs = q; Q->alloc = lenA - lenB + 1; } if (R == A || R == B || R == Binv) { _TEMPLATE(T, vec_clear) (R->coeffs, R->alloc, ctx); R->coeffs = r; R->alloc = lenB - 1; } Q->length = lenA - lenB + 1; R->length = lenB - 1; _TEMPLATE(T, poly_normalise) (R, ctx); } #endif flint-3.1.3/src/fq_poly_templates/equal.c000066400000000000000000000016411461254215100204260ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, poly_equal) (const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx) { slong i; if (op1 == op2) return 1; if (op1->length != op2->length) return 0; for (i = 0; i < op1->length; i++) if (!TEMPLATE(T, equal) (op1->coeffs + i, op2->coeffs + i, ctx)) return 0; return 1; } #endif flint-3.1.3/src/fq_poly_templates/equal_trunc.c000066400000000000000000000025261461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2014 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, poly_equal_trunc) (const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx) { slong i, len1, len2; if (op1 == op2) return 1; if (n < 0) n = 0; len1 = FLINT_MIN(op1->length, n); len2 = FLINT_MIN(op2->length, n); if (len1 < len2) { for (i = len1; i < len2; i++) { if (!TEMPLATE(T, is_zero)(op2->coeffs + i, ctx)) return 0; } } else if (len2 < len1) { for (i = len2; i < len1; i++) { if (!TEMPLATE(T, is_zero)(op1->coeffs + i, ctx)) return 0; } } for (i = 0; i < FLINT_MIN(len1, len2); i++) if (!TEMPLATE(T, equal) (op1->coeffs + i, op2->coeffs + i, ctx)) return 0; return 1; } #endif flint-3.1.3/src/fq_poly_templates/evaluate_fq.c000066400000000000000000000034541461254215100216170ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE3(T, poly_evaluate, T) (TEMPLATE(T, t) rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, t) a, const TEMPLATE(T, ctx_t) ctx) { if (len == 0) { TEMPLATE(T, zero) (rop, ctx); } else if (len == 1 || TEMPLATE(T, is_zero) (a, ctx)) { TEMPLATE(T, set) (rop, op + 0, ctx); } else { slong i = len - 1; TEMPLATE(T, t) t; TEMPLATE(T, init) (t, ctx); TEMPLATE(T, set) (rop, op + i, ctx); for (i = len - 2; i >= 0; i--) { TEMPLATE(T, mul) (t, rop, a, ctx); TEMPLATE(T, add) (rop, op + i, t, ctx); } TEMPLATE(T, clear) (t, ctx); } } void TEMPLATE3(T, poly_evaluate, T) (TEMPLATE(T, t) rop, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, t) a, const TEMPLATE(T, ctx_t) ctx) { if (rop == a) { TEMPLATE(T, t) t; TEMPLATE(T, init) (t, ctx); _TEMPLATE3(T, poly_evaluate, T) (t, f->coeffs, f->length, a, ctx); TEMPLATE(T, swap) (rop, t, ctx); TEMPLATE(T, clear) (t, ctx); } else { _TEMPLATE3(T, poly_evaluate, T) (rop, f->coeffs, f->length, a, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/evaluate_fq_vec.c000066400000000000000000000027251461254215100224540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE4(T, poly_evaluate, T, vec)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, struct) *coeffs, slong len, const TEMPLATE(T, struct) *xs, slong n, const TEMPLATE(T, ctx_t) ctx) { if (len < 32) _TEMPLATE4(T, poly_evaluate, T, vec_iter)(ys, coeffs, len, xs, n, ctx); else _TEMPLATE4(T, poly_evaluate, T, vec_fast)(ys, coeffs, len, xs, n, ctx); } void TEMPLATE4(T, poly_evaluate, T, vec)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx) { _TEMPLATE4(T, poly_evaluate, T, vec)(ys, poly->coeffs, poly->length, xs, n, ctx); } #endif flint-3.1.3/src/fq_poly_templates/evaluate_fq_vec_fast.c000066400000000000000000000107441461254215100234710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2012 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE4(T, poly_evaluate, T, vec_fast_precomp) (TEMPLATE(T, struct) * vs, const TEMPLATE(T, struct) * poly, slong plen, TEMPLATE(T, poly_struct) * const * tree, slong len, const TEMPLATE(T, ctx_t) ctx) { slong height, i, j, pow, left; slong tree_height; TEMPLATE(T, t) temp, inv; TEMPLATE(T, struct) * t, * u, * pb, * pc, * swap; TEMPLATE(T, poly_struct) * pa; TEMPLATE(T, init)(temp, ctx); TEMPLATE(T, init)(inv, ctx); /* avoid worrying about some degenerate cases */ if (len < 2 || plen < 2) { if (len == 1) { TEMPLATE(T, neg)(temp, tree[0]->coeffs, ctx); _TEMPLATE3(T, poly_evaluate, T)(vs, poly, plen, temp, ctx); } else if (len != 0 && plen == 0) _TEMPLATE(T, vec_zero)(vs, len, ctx); else if (len != 0 && plen == 1) for (i = 0; i < len; i++) TEMPLATE(T, set)(vs + i, poly, ctx); TEMPLATE(T, clear)(temp, ctx); TEMPLATE(T, clear)(inv, ctx); return; } t = _TEMPLATE(T, vec_init)(2*len, ctx); u = _TEMPLATE(T, vec_init)(2*len, ctx); left = len; /* Initial reduction. We allow the polynomial to be larger or smaller than the number of points. */ height = FLINT_BIT_COUNT(plen - 1) - 1; tree_height = FLINT_CLOG2(len); while (height >= tree_height) height--; pow = WORD(1) << height; for (i = j = 0; i < len; i += pow, j++) { pa = tree[height] + j; TEMPLATE(T, inv)(inv, pa->coeffs + pa->length - 1, ctx); _TEMPLATE(T, poly_rem)(t + i, poly, plen, pa->coeffs, pa->length, inv, ctx); } for (i = height - 1; i >= 0; i--) { pow = WORD(1) << i; left = len; pa = tree[i]; pb = t; pc = u; left = len; while (left >= 2 * pow) { TEMPLATE(T, inv)(inv, pa->coeffs + pa->length - 1, ctx); _TEMPLATE(T, poly_rem)(pc, pb, 2 * pow, pa->coeffs, pa->length, inv, ctx); pa++; TEMPLATE(T, inv)(inv, pa->coeffs + pa->length - 1, ctx); _TEMPLATE(T, poly_rem)(pc + pow, pb, 2 * pow, pa->coeffs, pa->length, inv, ctx); pa++; pb += 2 * pow; pc += 2 * pow; left -= 2 * pow; } if (left > pow) { TEMPLATE(T, inv)(inv, pa->coeffs + pa->length - 1, ctx); _TEMPLATE(T, poly_rem)(pc, pb, left, pa->coeffs, pa->length, inv, ctx); pa ++; TEMPLATE(T, inv)(inv, pa->coeffs + pa->length - 1, ctx); _TEMPLATE(T, poly_rem)(pc + pow, pb, left, pa->coeffs, pa->length, inv, ctx); } else if (left > 0) _TEMPLATE(T, vec_set)(pc, pb, left, ctx); swap = t; t = u; u = swap; } TEMPLATE(T, clear)(temp, ctx); TEMPLATE(T, clear)(inv, ctx); _TEMPLATE(T, vec_set)(vs, t, len, ctx); _TEMPLATE(T, vec_clear)(t, 2*len, ctx); _TEMPLATE(T, vec_clear)(u, 2*len, ctx); } void _TEMPLATE4(T, poly_evaluate, T, vec_fast)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, struct) * poly, slong plen, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_struct) ** tree; tree = _TEMPLATE(T, poly_tree_alloc)(n, ctx); _TEMPLATE(T, poly_tree_build)(tree, xs, n, ctx); _TEMPLATE4(T, poly_evaluate, T, vec_fast_precomp)(ys, poly, plen, tree, n, ctx); _TEMPLATE(T, poly_tree_free)(tree, n, ctx); } void TEMPLATE4(T, poly_evaluate, T, vec_fast)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, struct) *xs, slong n, const TEMPLATE(T, ctx_t) ctx) { _TEMPLATE4(T, poly_evaluate, T, vec_fast)(ys, poly->coeffs, poly->length, xs, n, ctx); } #endif flint-3.1.3/src/fq_poly_templates/evaluate_fq_vec_iter.c000066400000000000000000000025361461254215100234770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE4(T, poly_evaluate, T, vec_iter)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, struct) * coeffs, slong len, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < n; i++) _TEMPLATE3(T, poly_evaluate, T)(ys + i, coeffs, len, xs + i, ctx); } void TEMPLATE4(T, poly_evaluate, T, vec_iter)(TEMPLATE(T, struct) * ys, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, struct) * xs, slong n, const TEMPLATE(T, ctx_t) ctx) { _TEMPLATE4(T, poly_evaluate, T, vec_iter)(ys, poly->coeffs, poly->length, xs, n, ctx); } #endif flint-3.1.3/src/fq_poly_templates/fit_length.c000066400000000000000000000015241461254215100214420ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_fit_length) (TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx) { if (len > poly->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * poly->alloc) len = 2 * poly->alloc; TEMPLATE(T, poly_realloc) (poly, len, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/gcd.c000066400000000000000000000060731461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "gr_poly.h" slong _TEMPLATE(T, poly_gcd) (TEMPLATE(T, struct)*G, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, ctx_t) ctx) { gr_ctx_t gr_ctx; slong cutoff; slong lenG; #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) if (FLINT_BIT_COUNT(TEMPLATE(T, ctx_prime)(ctx)) <= 8) #else if (fmpz_bits(TEMPLATE(T, ctx_prime)(ctx)) <= 8) #endif cutoff = TEMPLATE(CAP_T, POLY_SMALL_GCD_CUTOFF); else cutoff = TEMPLATE(CAP_T, POLY_GCD_CUTOFF); TEMPLATE3(_gr_ctx_init, T, from_ref)(gr_ctx, ctx); if (FLINT_MIN(lenA, lenB) < cutoff) GR_MUST_SUCCEED(_gr_poly_gcd_euclidean(G, &lenG, A, lenA, B, lenB, gr_ctx)); else GR_MUST_SUCCEED(_gr_poly_gcd_hgcd(G, &lenG, A, lenA, B, lenB, TEMPLATE(CAP_T, POLY_HGCD_CUTOFF), cutoff, gr_ctx)); return lenG; } void TEMPLATE(T, poly_gcd) (TEMPLATE(T, poly_t) G, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { if (A->length < B->length) { TEMPLATE(T, poly_gcd) (G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; TEMPLATE(T, struct) * g; if (lenA == 0) /* lenA = lenB = 0 */ { TEMPLATE(T, poly_zero) (G, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { TEMPLATE(T, poly_make_monic) (G, A, ctx); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { g = _TEMPLATE(T, vec_init) (FLINT_MIN(lenA, lenB), ctx); } else { TEMPLATE(T, poly_fit_length) (G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } lenG = _TEMPLATE(T, poly_gcd) (g, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _TEMPLATE(T, vec_clear) (G->coeffs, G->alloc, ctx); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _TEMPLATE(T, poly_set_length) (G, lenG, ctx); if (G->length == 1) TEMPLATE(T, one) (G->coeffs, ctx); else TEMPLATE(T, poly_make_monic) (G, G, ctx); } } } #endif flint-3.1.3/src/fq_poly_templates/gcd_euclidean_f.c000066400000000000000000000124671461254215100224020ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong _TEMPLATE(T, poly_gcd_euclidean_f) (TEMPLATE(T, t) f, TEMPLATE(T, struct) * G, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, ctx_t) ctx) { slong lenG = 0; if (lenB == 1) { TEMPLATE(T, t) invB; TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, gcdinv) (f, invB, B, ctx); if (TEMPLATE(T, is_one) (f, ctx)) { TEMPLATE(T, one) (G, ctx); lenG = 1; } TEMPLATE(T, clear) (invB, ctx); } else /* lenA >= lenB > 1 */ { const slong lenW = FLINT_MAX(lenA - lenB + 1, lenB) + lenA + 2 * lenB; TEMPLATE(T, struct) * Q, *R1, *R2, *R3, *T, *W; slong lenR2, lenR3; W = _TEMPLATE(T, vec_init) (lenW, ctx); Q = W; R1 = W + FLINT_MAX(lenA - lenB + 1, lenB); R2 = R1 + lenA; R3 = R2 + lenB; _TEMPLATE(T, poly_divrem_f) (f, Q, R1, A, lenA, B, lenB, ctx); if (!TEMPLATE(T, is_one) (f, ctx)) goto exit; lenR3 = lenB - 1; TEMPLATE(CAP_T, VEC_NORM) (R1, lenR3, ctx); if (lenR3 == 0) { _TEMPLATE(T, vec_set) (G, B, lenB, ctx); lenG = lenB; } else { T = R3; R3 = R1; R1 = T; _TEMPLATE(T, vec_set) (R2, B, lenB, ctx); lenR2 = lenB; do { _TEMPLATE(T, poly_divrem_f) (f, Q, R1, R2, lenR2, R3, lenR3, ctx); if (!TEMPLATE(T, is_one) (f, ctx)) goto exit; lenR2 = lenR3--; TEMPLATE(CAP_T, VEC_NORM) (R1, lenR3, ctx); T = R2; R2 = R3; R3 = R1; R1 = T; } while (lenR3 > 0); _TEMPLATE(T, vec_set) (G, R2, lenR2, ctx); lenG = lenR2; } exit: _TEMPLATE(T, vec_clear) (W, lenW, ctx); } return lenG; } void TEMPLATE(T, poly_gcd_euclidean_f) (TEMPLATE(T, t) f, TEMPLATE(T, poly_t) G, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { if (A->length < B->length) { TEMPLATE(T, poly_gcd_euclidean_f) (f, G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; slong lenG; TEMPLATE(T, struct) * g; if (lenA == 0) /* lenA = lenB = 0 */ { TEMPLATE(T, poly_zero) (G, ctx); TEMPLATE(T, one) (f, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { TEMPLATE(T, t) invA; TEMPLATE(T, init) (invA, ctx); TEMPLATE(T, gcdinv) (f, invA, A->coeffs + lenA - 1, ctx); if (TEMPLATE(T, is_one) (f, ctx)) TEMPLATE3(T, poly_scalar_mul, T) (G, A, invA, ctx); else TEMPLATE(T, poly_zero) (G, ctx); TEMPLATE(T, clear) (invA, ctx); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { g = _TEMPLATE(T, vec_init) (FLINT_MIN(lenA, lenB), ctx); } else { TEMPLATE(T, poly_fit_length) (G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } lenG = _TEMPLATE(T, poly_gcd_euclidean_f) (f, g, A->coeffs, lenA, B->coeffs, lenB, ctx); if (TEMPLATE(T, is_one) (f, ctx)) { if (G == A || G == B) { _TEMPLATE(T, vec_clear) (G->coeffs, G->alloc, ctx); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _TEMPLATE(T, poly_set_length) (G, lenG, ctx); if (lenG == 1) TEMPLATE(T, one) (G->coeffs, ctx); else TEMPLATE(T, poly_make_monic) (G, G, ctx); } else /* Factor found, ensure G is normalised */ { if (G == A || G == B) _TEMPLATE(T, vec_clear) (g, FLINT_MIN(lenA, lenB), ctx); else { _TEMPLATE(T, vec_zero) (G->coeffs, FLINT_MIN(lenA, lenB), ctx); _TEMPLATE(T, poly_set_length) (G, 0, ctx); } } } } } #endif flint-3.1.3/src/fq_poly_templates/gen.c000066400000000000000000000012511461254215100200650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_gen) (TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_fit_length) (f, 2, ctx); TEMPLATE(T, zero) (f->coeffs, ctx); TEMPLATE(T, one) (f->coeffs + 1, ctx); _TEMPLATE(T, poly_set_length) (f, 2, ctx); } #endif flint-3.1.3/src/fq_poly_templates/get_coeff.c000066400000000000000000000014641461254215100212430ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_get_coeff) (TEMPLATE(T, t) x, const TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, ctx_t) ctx) { if (n < poly->length) TEMPLATE(T, set) (x, poly->coeffs + n, ctx); else TEMPLATE(T, zero) (x, ctx); } #endif flint-3.1.3/src/fq_poly_templates/get_str.c000066400000000000000000000036171461254215100207730ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include char *_TEMPLATE(T, poly_get_str) (const TEMPLATE(T, struct) * poly, slong len, const TEMPLATE(T, ctx_t) ctx) { char *str, **coeffstrs; size_t off; slong i, bound; if (len == 0) { str = (char *)flint_malloc(2 * sizeof(char)); str[0] = '0'; str[1] = '\0'; return str; } coeffstrs = (char **)flint_malloc(len * sizeof(char *)); bound = (slong) (ceil(log10((double)(len + 1)))) + 2; for (i = 0; i < len; i++) { if (!TEMPLATE(T, is_zero) (poly + i, ctx)) { coeffstrs[i] = TEMPLATE(T, get_str) (poly + i, ctx); bound += 1 + strlen(coeffstrs[i]); } else { bound += 2; } } str = (char *)flint_malloc(bound * sizeof(char)); off = 0; off += flint_sprintf(str + off, "%wd ", len); for (i = 0; i < len; i++) { if (TEMPLATE(T, is_zero) (poly + i, ctx)) { off += flint_sprintf(str + off, " 0"); } else { off += flint_sprintf(str + off, " %s", coeffstrs[i]); flint_free(coeffstrs[i]); } } flint_free(coeffstrs); return str; } char *TEMPLATE(T, poly_get_str) (const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_get_str) (poly->coeffs, poly->length, ctx); } #endif flint-3.1.3/src/fq_poly_templates/get_str_pretty.c000066400000000000000000000054271461254215100224030ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include char *_TEMPLATE(T, poly_get_str_pretty) (const TEMPLATE(T, struct) * poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx) { char *str, **coeffstrs; size_t off; slong i, bound, nz; if (len == 0) { str = flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } if (len == 1) { return TEMPLATE(T, get_str_pretty) (poly, ctx); } coeffstrs = (char **)flint_malloc(len * sizeof(char *)); nz = 0; bound = 1; for (i = 0; i < len; i++) if (!TEMPLATE(T, is_zero) (poly + i, ctx)) { coeffstrs[i] = TEMPLATE(T, get_str_pretty) (poly + i, ctx); bound += strlen(coeffstrs[i]); nz++; } bound += nz * (5 + strlen(x) + (slong) (ceil(log10(len)))); str = flint_malloc(bound); off = 0; i = len - 1; if (TEMPLATE(T, is_one) (poly + i, ctx)) { } else off += flint_sprintf(str + off, "(%s)*", coeffstrs[i]); if (i > 1) off += flint_sprintf(str + off, "%s^%wd", x, i); else off += flint_sprintf(str + off, "%s", x); for (--i; i > 0; --i) { if (TEMPLATE(T, is_zero) (poly + i, ctx)) continue; if (!TEMPLATE(T, is_one) (poly + i, ctx)) { off += flint_sprintf(str + off, "+(%s)*", coeffstrs[i]); } else { off += flint_sprintf(str + off, "+"); } if (i > 1) off += flint_sprintf(str + off, "%s^%wd", x, i); else off += flint_sprintf(str + off, "%s", x); } if (!TEMPLATE(T, is_zero) (poly + i, ctx)) { off += flint_sprintf(str + off, "+(%s)", coeffstrs[i]); } for (i = 0; i < len; i++) if (!TEMPLATE(T, is_zero) (poly + i, ctx)) { flint_free(coeffstrs[i]); } flint_free(coeffstrs); return str; } char *TEMPLATE(T, poly_get_str_pretty) (const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_get_str_pretty) (poly->coeffs, poly->length, x, ctx); } #endif flint-3.1.3/src/fq_poly_templates/hamming_weight.c000066400000000000000000000016701461254215100223100ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong _TEMPLATE(T, poly_hamming_weight) (const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i, sum = 0; for (i = 0; i < len; i++) sum += !TEMPLATE(T, is_zero) (op + i, ctx); return sum; } slong TEMPLATE(T, poly_hamming_weight) (const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_hamming_weight) (op->coeffs, op->length, ctx); } #endif flint-3.1.3/src/fq_poly_templates/inflate.c000066400000000000000000000032761461254215100207470ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_inflate) (TEMPLATE(T, poly_t) result, const TEMPLATE(T, poly_t) input, ulong inflation, const TEMPLATE(T, ctx_t) ctx) { if (input->length <= 1 || inflation == 1) { TEMPLATE(T, poly_set) (result, input, ctx); } else if (inflation == 0) { TEMPLATE(T, t) v; TEMPLATE(T, init) (v, ctx); TEMPLATE(T, one) (v, ctx); TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (v, input, v, ctx); TEMPLATE(T, poly_zero) (result, ctx); TEMPLATE(T, poly_set_coeff) (result, 0, v, ctx); TEMPLATE(T, clear) (v, ctx); } else { slong i, j, res_length = (input->length - 1) * inflation + 1; TEMPLATE(T, poly_fit_length) (result, res_length, ctx); for (i = input->length - 1; i > 0; i--) { TEMPLATE(T, set) (result->coeffs + (i * inflation), input->coeffs + i, ctx); for (j = i * inflation - 1; j > (i - 1) * inflation; j--) TEMPLATE(T, zero) (result->coeffs + j, ctx); } TEMPLATE(T, set) (result->coeffs, input->coeffs, ctx); result->length = res_length; } } #endif flint-3.1.3/src/fq_poly_templates/init.c000066400000000000000000000016101461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_init) (TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { poly->coeffs = NULL; poly->alloc = 0; poly->length = 0; } void TEMPLATE(T, poly_init2) (TEMPLATE(T, poly_t) poly, slong alloc, const TEMPLATE(T, ctx_t) ctx) { poly->coeffs = (alloc) ? _TEMPLATE(T, vec_init) (alloc, ctx) : NULL; poly->alloc = alloc; poly->length = 0; } #endif flint-3.1.3/src/fq_poly_templates/inv_series_newton.c000066400000000000000000000067451461254215100230710ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #define FQ_POLY_INV_NEWTON_CUTOFF 64 void _TEMPLATE(T, poly_inv_series_newton) (TEMPLATE(T, struct) * Qinv, const TEMPLATE(T, struct) * Q, slong n, const TEMPLATE(T, t) cinv, const TEMPLATE(T, ctx_t) ctx) { if (n == 1) /* {Q,1} x* cinv == 1 mod (x) */ { TEMPLATE(T, set) (Qinv, cinv, ctx); } else { const slong alloc = FLINT_MAX(n, 3 * FQ_POLY_INV_NEWTON_CUTOFF); slong *a, i, m; TEMPLATE(T, struct) * W; W = _TEMPLATE(T, vec_init) (alloc, ctx); for (i = 1; (WORD(1) << i) < n; i++) ; a = (slong *) flint_malloc(i * sizeof(slong)); a[i = 0] = n; while (n >= FQ_POLY_INV_NEWTON_CUTOFF) a[++i] = (n = (n + 1) / 2); /* Base case */ { TEMPLATE(T, struct) * Qrev = W + 2 * FQ_POLY_INV_NEWTON_CUTOFF; _TEMPLATE(T, poly_reverse) (Qrev, Q, n, n, ctx); _TEMPLATE(T, vec_zero) (W, 2 * n - 2, ctx); TEMPLATE(T, one) (W + (2 * n - 2), ctx); _TEMPLATE(T, poly_div) (Qinv, W, 2 * n - 1, Qrev, n, cinv, ctx); _TEMPLATE(T, poly_reverse) (Qinv, Qinv, n, n, ctx); } for (i--; i >= 0; i--) { m = n; n = a[i]; _TEMPLATE(T, poly_mullow) (W, Q, n, Qinv, m, n, ctx); _TEMPLATE(T, poly_mullow) (Qinv + m, Qinv, m, W + m, n - m, n - m, ctx); _TEMPLATE(T, poly_neg) (Qinv + m, Qinv + m, n - m, ctx); } _TEMPLATE(T, vec_clear) (W, alloc, ctx); flint_free(a); } } void TEMPLATE(T, poly_inv_series_newton) (TEMPLATE(T, poly_t) Qinv, const TEMPLATE(T, poly_t) Q, slong n, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) cinv; TEMPLATE(T, struct) * Qcopy; int Qalloc; if (Q->length >= n) { Qcopy = Q->coeffs; Qalloc = 0; } else { Qcopy = _TEMPLATE(T, vec_init) (n, ctx); _TEMPLATE(T, vec_set) (Qcopy, Q->coeffs, Q->length, ctx); Qalloc = 1; } TEMPLATE(T, init) (cinv, ctx); TEMPLATE(T, inv) (cinv, Q->coeffs, ctx); if (Qinv != Q) { TEMPLATE(T, poly_fit_length) (Qinv, n, ctx); _TEMPLATE(T, poly_inv_series_newton) (Qinv->coeffs, Qcopy, n, cinv, ctx); } else { TEMPLATE(T, struct) * t = _TEMPLATE(T, vec_init) (n, ctx); _TEMPLATE(T, poly_inv_series_newton) (t, Qcopy, n, cinv, ctx); _TEMPLATE(T, vec_clear) (Qinv->coeffs, Qinv->alloc, ctx); Qinv->coeffs = t; Qinv->alloc = n; Qinv->length = n; } _TEMPLATE(T, poly_set_length) (Qinv, n, ctx); _TEMPLATE(T, poly_normalise) (Qinv, ctx); if (Qalloc) _TEMPLATE(T, vec_clear) (Qcopy, n, ctx); TEMPLATE(T, clear) (cinv, ctx); } #endif flint-3.1.3/src/fq_poly_templates/invsqrt_series.c000066400000000000000000000072131461254215100224000ustar00rootroot00000000000000/* Copyright (C) 2011, 2021, 2022 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" static void _TEMPLATE(T, poly_invsqrt_series_prealloc)(TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, TEMPLATE(T, struct) * t, TEMPLATE(T, struct) * u, slong n, const TEMPLATE(T, ctx_t) ctx) { const int alloc = (t == NULL); const slong m = (n + 1) / 2; TEMPLATE(T, t) c, inv2, one; if (n == 1) { TEMPLATE(T, set_ui)(g + 0, 1, ctx); return; } if (alloc) { t = _TEMPLATE(T, vec_init)(n, ctx); u = _TEMPLATE(T, vec_init)(n, ctx); } TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(inv2, ctx); TEMPLATE(T, init)(one, ctx); TEMPLATE(T, set_ui)(one, 1, ctx); TEMPLATE(T, set_ui)(inv2, 2, ctx); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) if (TEMPLATE(T, ctx_prime)(ctx) != 2) #else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) != 0) #endif TEMPLATE(T, inv)(inv2, inv2, ctx); _TEMPLATE(T, poly_invsqrt_series_prealloc)(g, h, t, u, m, ctx); _TEMPLATE(T, vec_zero)(g + m, n - m, ctx); _TEMPLATE(T, poly_mul)(t, g, m, g, m, ctx); if (2*m - 1 < n) TEMPLATE(T, zero)(t + n - 1, ctx); _TEMPLATE(T, poly_mullow)(u, t, n, g, n, n, ctx); _TEMPLATE(T, poly_mullow)(t, u, n, h, n, n, ctx); TEMPLATE(T, sub)(c, c, one, ctx); TEMPLATE(T, mul)(c, c, inv2, ctx); _TEMPLATE3(T, vec_scalar_mul, T)(g + m, t + m, n - m, c, ctx); if (alloc) { _TEMPLATE(T, vec_clear)(t, n, ctx); _TEMPLATE(T, vec_clear)(u, n, ctx); } TEMPLATE(T, clear)(one, ctx); TEMPLATE(T, clear)(inv2, ctx); TEMPLATE(T, clear)(c, ctx); } void _TEMPLATE(T, poly_invsqrt_series)(TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong n, TEMPLATE(T, ctx_t) ctx) { _TEMPLATE(T, poly_invsqrt_series_prealloc)(g, h, NULL, NULL, n, ctx); } void TEMPLATE(T, poly_invsqrt_series)(TEMPLATE(T, poly_t) g, const TEMPLATE(T, poly_t) h, slong n, TEMPLATE(T, ctx_t) ctx) { const slong hlen = h->length; TEMPLATE(T, struct) * g_coeffs; TEMPLATE(T, struct) * h_coeffs; TEMPLATE(T, poly_t) t1; if (n == 0 || h->length == 0 || TEMPLATE(T, is_zero)(h->coeffs + 0, ctx)) { flint_throw(FLINT_ERROR, "Exception (fq_poly_invsqrt). Division by zero.\n"); } if (!TEMPLATE(T, is_one)(h->coeffs + 0, ctx)) { flint_throw(FLINT_ERROR, "Exception (fq_poly_invsqrt_series). Constant term != 1.\n"); } if (hlen < n) { h_coeffs = _TEMPLATE(T, vec_init)(n, ctx); _TEMPLATE(T, vec_set)(h_coeffs, h->coeffs, hlen, ctx); } else h_coeffs = h->coeffs; if (h == g && hlen >= n) { TEMPLATE(T, poly_init2)(t1, n, ctx); g_coeffs = t1->coeffs; } else { TEMPLATE(T, poly_fit_length)(g, n, ctx); g_coeffs = g->coeffs; } _TEMPLATE(T, poly_invsqrt_series)(g_coeffs, h_coeffs, n, ctx); if (h == g && hlen >= n) { TEMPLATE(T, poly_swap)(g, t1, ctx); TEMPLATE(T, poly_clear)(t1, ctx); } g->length = n; if (hlen < n) _TEMPLATE(T, vec_clear)(h_coeffs, n, ctx); _TEMPLATE(T, poly_normalise)(g, ctx); } #endif flint-3.1.3/src/fq_poly_templates/io.c000066400000000000000000000110701461254215100177230ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "fmpz.h" /* printing *******************************************************************/ /* TODO: When op has only one non-zero term, this function would omit the parentheses. */ static void __TEMPLATE(T, print)(FILE * file, const TEMPLATE(T, struct) * op, const TEMPLATE(T, ctx_t) ctx) { fputc('(', file); TEMPLATE(T, fprint_pretty) (file, op, ctx); fputc(')', file); } int _TEMPLATE(T, poly_fprint)(FILE * file, const TEMPLATE(T, struct) * poly, slong len, const TEMPLATE(T, ctx_t) ctx) { int r; slong i; r = flint_fprintf(file, "%wd ", len); if (r <= 0) return r; if (len == 0) return r; for (i = 0; (r > 0) && (i < len); i++) { r = flint_fprintf(file, " "); if (r <= 0) return r; r = TEMPLATE(T, fprint) (file, poly + i, ctx); if (r <= 0) return r; } return r; } int _TEMPLATE(T, poly_fprint_pretty)(FILE * file, const TEMPLATE(T, struct) * poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx) { if (len == 0) { fputc('0', file); } else if (len == 1) { TEMPLATE(T, fprint_pretty) (file, poly + 0, ctx); } else if (len == 2) { if (TEMPLATE(T, is_one) (poly + 1, ctx)) flint_fprintf(file, "%s", x); else { __TEMPLATE(T, print) (file, poly + 1, ctx); flint_fprintf(file, "*%s", x); } if (!TEMPLATE(T, is_zero) (poly + 0, ctx)) { fputc('+', file); __TEMPLATE(T, print) (file, poly + 0, ctx); } } else { slong i = len - 1; { if (TEMPLATE(T, is_one) (poly + i, ctx)) flint_fprintf(file, "%s^%wd", x, i); else { __TEMPLATE(T, print) (file, poly + i, ctx); flint_fprintf(file, "*%s^%wd", x, i); } --i; } for (; i > 1; --i) { if (TEMPLATE(T, is_zero) (poly + i, ctx)) continue; if (TEMPLATE(T, is_one) (poly + i, ctx)) flint_fprintf(file, "+%s^%wd", x, i); else { fputc('+', file); __TEMPLATE(T, print) (file, poly + i, ctx); flint_fprintf(file, "*%s^%wd", x, i); } } if (!TEMPLATE(T, is_zero) (poly + 1, ctx)) { if (TEMPLATE(T, is_one) (poly + 1, ctx)) { fputc('+', file); fputs(x, file); } else { fputc('+', file); __TEMPLATE(T, print) (file, poly + 1, ctx); fputc('*', file); fputs(x, file); } } if (!TEMPLATE(T, is_zero) (poly + 0, ctx)) { fputc('+', file); __TEMPLATE(T, print) (file, poly + 0, ctx); } } return 1; } int TEMPLATE(T, poly_fprint)(FILE * file, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_fprint)(file, poly->coeffs, poly->length, ctx); } int TEMPLATE(T, poly_fprint_pretty)(FILE * file, const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_fprint_pretty)(file, poly->coeffs, poly->length, x, ctx); } int _TEMPLATE(T, poly_print)(const TEMPLATE(T, struct) *poly, slong len, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_fprint)(stdout, poly, len, ctx); } int TEMPLATE(T, poly_print)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return TEMPLATE(T, poly_fprint)(stdout, poly, ctx); } int _TEMPLATE(T, poly_print_pretty)(const TEMPLATE(T, struct) *poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_fprint_pretty)(stdout, poly, len, x, ctx); } int TEMPLATE(T, poly_print_pretty)(const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx) { return TEMPLATE(T, poly_fprint_pretty)(stdout, poly, x, ctx); } #endif flint-3.1.3/src/fq_poly_templates/is_gen.c000066400000000000000000000013741461254215100205660ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, poly_is_gen)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { return ((poly->length == 2) && TEMPLATE(T, is_zero)(poly->coeffs, ctx) && TEMPLATE(T, is_one)(poly->coeffs + 1, ctx)); } #endif flint-3.1.3/src/fq_poly_templates/make_monic.c000066400000000000000000000026251461254215100214240ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_make_monic) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong length, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) inv; TEMPLATE(T, init) (inv, ctx); TEMPLATE(T, inv) (inv, &op[length - 1], ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (rop, op, length, inv, ctx); TEMPLATE(T, clear) (inv, ctx); } void TEMPLATE(T, poly_make_monic) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { if (op->length == 0) { TEMPLATE(T, poly_zero) (rop, ctx); return; } TEMPLATE(T, poly_fit_length) (rop, op->length, ctx); _TEMPLATE(T, poly_make_monic) (rop->coeffs, op->coeffs, op->length, ctx); _TEMPLATE(T, poly_set_length) (rop, op->length, ctx); } #endif flint-3.1.3/src/fq_poly_templates/mul.c000066400000000000000000000041551461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_mul) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, const TEMPLATE(T, ctx_t) ctx) { if (FLINT_MAX(len1, len2) < TEMPLATE(CAP_T, MUL_CLASSICAL_CUTOFF)) { _TEMPLATE(T, poly_mul_classical) (rop, op1, len1, op2, len2, ctx); } #ifdef USE_MUL_REORDER else if (TEMPLATE(T, ctx_degree) (ctx) < 4) { _TEMPLATE(T, poly_mul_reorder) (rop, op1, len1, op2, len2, ctx); } #endif else { _TEMPLATE(T, poly_mul_KS) (rop, op1, len1, op2, len2, ctx); } } void TEMPLATE(T, poly_mul) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong rlen = op1->length + op2->length - 1; if (len1 == 0 || len2 == 0) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (rop == op1 || rop == op2) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, rlen, ctx); _TEMPLATE(T, poly_mul) (t->coeffs, op1->coeffs, len1, op2->coeffs, len2, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, rlen, ctx); _TEMPLATE(T, poly_mul) (rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, ctx); } _TEMPLATE(T, poly_set_length) (rop, rlen, ctx); } #endif flint-3.1.3/src/fq_poly_templates/mul_KS.c000066400000000000000000000055551461254215100205210ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "fmpz_poly.h" void _TEMPLATE(T, poly_mul_KS) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, const TEMPLATE(T, ctx_t) ctx) { const slong in1_len = len1, in2_len = len2; const slong d = TEMPLATE(T, ctx_degree) (ctx); slong bits, i; fmpz *f, *g, *h; TEMPLATE(CAP_T, VEC_NORM) (op1, len1, ctx); TEMPLATE(CAP_T, VEC_NORM) (op2, len2, ctx); if (!len1 | !len2) { if (in1_len + in2_len - 1 > 0) _TEMPLATE(T, poly_zero) (rop, in1_len + in2_len - 1, ctx); return; } bits = FLINT_BIT_COUNT(d) + FLINT_BIT_COUNT(FLINT_MIN(len1, len2)); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) bits += 2 * FLINT_BIT_COUNT(TEMPLATE(T, ctx_prime)(ctx)); #else bits += 2 * fmpz_bits(TEMPLATE(T, ctx_prime)(ctx)); #endif f = _fmpz_vec_init((len1 + len2 - 1) + (len1) + (len2)); g = f + (len1 + len2 - 1); h = g + len1; for (i = 0; i < len1; i++) { TEMPLATE(T, bit_pack) (g + i, op1 + i, bits, ctx); } for (i = 0; i < len2; i++) { TEMPLATE(T, bit_pack) (h + i, op2 + i, bits, ctx); } if (len1 >= len2) _fmpz_poly_mul(f, g, len1, h, len2); else _fmpz_poly_mul(f, h, len2, g, len1); for (i = 0; i < len1 + len2 - 1; i++) { TEMPLATE(T, bit_unpack) (rop + i, f + i, bits, ctx); } _TEMPLATE(T, poly_zero) (rop + (len1 + len2 - 1), (in1_len - len1) + (in2_len - len2), ctx); _fmpz_vec_clear(f, (len1 + len2 - 1) + (len1) + (len2)); } void TEMPLATE(T, poly_mul_KS) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong rlen = len1 + len2 - 1; if (len1 == 0 || len2 == 0) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, rlen, ctx); _TEMPLATE(T, poly_mul_KS) (rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, ctx); _TEMPLATE(T, poly_set_length) (rop, rlen, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/mul_classical.c000066400000000000000000000052101461254215100221260ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_mul_classical) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, const TEMPLATE(T, ctx_t) ctx) { if (len1 == 1 && len2 == 1) { TEMPLATE(T, mul) (rop, op1, op2, ctx); } else { slong i; /* Set res[i] = poly1[i]*poly2[0] */ _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (rop, op1, len1, op2, ctx); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (rop + len1, op2 + 1, len2 - 1, op1 + len1 - 1, ctx); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len1 - 1; i++) _TEMPLATE(T, TEMPLATE(poly_scalar_addmul, T)) (rop + i + 1, op2 + 1, len2 - 1, op1 + i, ctx); } } void TEMPLATE(T, poly_mul_classical) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx) { const slong len = op1->length + op2->length - 1; if (op1->length == 0 || op2->length == 0) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (rop == op1 || rop == op2) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, len, ctx); _TEMPLATE(T, poly_mul_classical) (t->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len, ctx); _TEMPLATE(T, poly_mul_classical) (rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx); } _TEMPLATE(T, poly_set_length) (rop, len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/mul_reorder.c000066400000000000000000000135451461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T /* Inclusion of both mul_reorder.c and sqr_reorder.c can screw things up by * multiple definitions. If changes are made to this file, make sure that * proper changes are made to the other file as well. */ #define MUL_REORDER_C #include "templates.h" /* Include routines for vectors over \code{fmpz_poly_struct}, for use in the classical multiplication routine in the $X$-direction. */ #ifndef SQR_REORDER_C static fmpz_poly_struct * __vec_init(slong len) { slong i; fmpz_poly_struct *v; v = flint_malloc(len * sizeof(fmpz_poly_struct)); for (i = 0; i < len; i++) fmpz_poly_init(v + i); return v; } static fmpz_poly_struct * __vec_init2(slong len, slong n) { slong i; fmpz_poly_struct *v; v = flint_malloc(len * sizeof(fmpz_poly_struct)); for (i = 0; i < len; i++) fmpz_poly_init2(v + i, n); return v; } static void __vec_clear(fmpz_poly_struct * v, slong len) { slong i; for (i = 0; i < len; i++) fmpz_poly_clear(v + i); flint_free(v); } static void __scalar_addmul(fmpz_poly_struct * rop, const fmpz_poly_struct * op, slong len, const fmpz_poly_t x) { slong i; if (fmpz_poly_is_zero(x)) { return; } else if (fmpz_poly_is_one(x)) { for (i = 0; i < len; i++) fmpz_poly_add(rop + i, rop + i, op + i); } else { fmpz_poly_t t; fmpz_poly_init(t); for (i = 0; i < len; i++) { fmpz_poly_mul(t, op + i, x); fmpz_poly_add(rop + i, rop + i, t); } fmpz_poly_clear(t); } } static void __scalar_mul(fmpz_poly_struct * rop, const fmpz_poly_struct * op, slong len, const fmpz_poly_t x) { slong i; if (fmpz_poly_is_zero(x)) { for (i = 0; i < len; i++) fmpz_poly_zero(rop + i); } else if (fmpz_poly_is_one(x)) { for (i = 0; i < len; i++) fmpz_poly_set(rop + i, op + i); } else { for (i = 0; i < len; i++) fmpz_poly_mul(rop + i, op + i, x); } } #endif static void __mul(fmpz_poly_struct * rop, fmpz_poly_struct * op1, slong len1, fmpz_poly_struct * op2, slong len2) { if (len1 == 1 && len2 == 1) { fmpz_poly_mul(rop, op1, op2); } else { slong i; __scalar_mul(rop, op1, len1, op2); __scalar_mul(rop + len1, op2 + 1, len2 - 1, op1 + len1 - 1); for (i = 0; i < len1 - 1; i++) __scalar_addmul(rop + i + 1, op2 + 1, len2 - 1, op1 + i); } } void _TEMPLATE(T, poly_mul_reorder) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, const TEMPLATE(T, ctx_t) ctx) { const slong d = TEMPLATE(T, ctx_degree) (ctx); fmpz_poly_struct *f, *g, *h; slong i, j, k, len; f = __vec_init(2 * d - 1); g = __vec_init2(d, len1); h = __vec_init2(d, len2); /* Convert (op1, len1) to (g, d) */ for (i = 0; i < len1; i++) for (j = 0; j < fmpz_poly_length(op1 + i); j++) fmpz_set((g + j)->coeffs + i, (op1 + i)->coeffs + j); /* Convert (op2, len2) to (h, d) */ for (i = 0; i < len2; i++) for (j = 0; j < fmpz_poly_length(op2 + i); j++) fmpz_set((h + j)->coeffs + i, (op2 + i)->coeffs + j); for (j = 0; j < d; j++) { _fmpz_poly_set_length(g + j, len1); _fmpz_poly_set_length(h + j, len2); _fmpz_poly_normalise(g + j); _fmpz_poly_normalise(h + j); } __mul(f, g, d, h, d); /* Normalise (f, len) */ len = 2 * d - 1; while ((len) && fmpz_poly_is_zero(f + (len - 1))) len--; /* Reduce (f, j) using polynomial operations */ if (len > d) { for (i = len - 1; i >= d; i--) { for (k = ctx->len - 2; k >= 0; k--) { fmpz_poly_scalar_submul_fmpz(f + ctx->j[k] + i - d, f + i, ctx->a + k); } fmpz_poly_zero(f + i); } } for (j = 0; j < FLINT_MIN(d, len); j++) fmpz_poly_scalar_mod_fmpz(f + j, f + j, TEMPLATE(T, ctx_prime) (ctx)); /* Convert (f, d) to (rop, len1 + len2 - 1) */ for (i = 0; i < len1 + len2 - 1; i++) { fmpz_poly_fit_length(rop + i, d); _fmpz_vec_zero((rop + i)->coeffs, d); } for (j = 0; j < d; j++) for (i = 0; i < fmpz_poly_length(f + j); i++) fmpz_set((rop + i)->coeffs + j, (f + j)->coeffs + i); for (i = 0; i < len1 + len2 - 1; i++) { _fmpz_poly_set_length(rop + i, d); _fmpz_poly_normalise(rop + i); } __vec_clear(f, 2 * d - 1); __vec_clear(g, d); __vec_clear(h, d); } void TEMPLATE(T, poly_mul_reorder) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx) { const slong len = op1->length + op2->length - 1; if (op1->length == 0 || op2->length == 0) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len, ctx); _TEMPLATE(T, poly_mul_reorder) (rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, ctx); _TEMPLATE(T, poly_set_length) (rop, len, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/mulhigh.c000066400000000000000000000054511461254215100207570ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_mulhigh) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, slong n, TEMPLATE(T, ctx_t) ctx) { if (FLINT_MAX(len1, len2) < 6) { _TEMPLATE(T, poly_mulhigh_classical) (rop, op1, len1, op2, len2, n, ctx); } else { _TEMPLATE(T, poly_mul_KS) (rop, op1, len1, op2, len2, ctx); } } void TEMPLATE(T, poly_mulhigh) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong start, const TEMPLATE(T, ctx_t) ctx) { slong len_out = op1->length + op2->length - 1; if (op1->length == 0 || op2->length == 0 || start >= len_out) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (rop == op1 || rop == op2) { TEMPLATE(T, poly_t) temp; TEMPLATE(T, poly_init2) (temp, len_out, ctx); if (op1->length >= op2->length) _TEMPLATE(T, poly_mulhigh_classical) (temp->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, start, ctx); else _TEMPLATE(T, poly_mulhigh_classical) (temp->coeffs, op2->coeffs, op2->length, op1->coeffs, op1->length, start, ctx); TEMPLATE(T, poly_swap) (rop, temp, ctx); TEMPLATE(T, poly_clear) (temp, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len_out, ctx); if (op1->length >= op2->length) _TEMPLATE(T, poly_mulhigh_classical) (rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, start, ctx); else _TEMPLATE(T, poly_mulhigh_classical) (rop->coeffs, op2->coeffs, op2->length, op1->coeffs, op1->length, start, ctx); } _TEMPLATE(T, poly_set_length) (rop, len_out, ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } #endif flint-3.1.3/src/fq_poly_templates/mulhigh_classical.c000066400000000000000000000073771461254215100230060ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* Assumes op1 and op2 are not length 0. */ void _TEMPLATE(T, poly_mulhigh_classical) ( TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, slong start, const TEMPLATE(T, ctx_t) ctx) { slong m, n; _TEMPLATE(T, vec_zero) (rop, start, ctx); if (len1 == 1) /* Special case if the length of both inputs is 1 */ { if (start == 0) TEMPLATE(T, mul) (rop, op1, op2, ctx); } else /* Ordinary case */ { slong i; /* Set res[i] = poly1[i]*poly2[0] */ if (start < len1) _TEMPLATE3(T, vec_scalar_mul, T) (rop + start, op1 + start, len1 - start, op2, ctx); if (len2 == 1) return; /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ m = FLINT_MAX(len1 - 1, start); _TEMPLATE3(T, vec_scalar_mul, T) (rop + m, op2 + m - len1 + 1, len2 - 1 + len1 - m, op1 + len1 - 1, ctx); /* out[i+j] += in1[i]*in2[j] */ m = FLINT_MAX(start, len2 - 1); for (i = m - len2 + 1; i < len1 - 1; i++) { n = FLINT_MAX(i + 1, start); _TEMPLATE3(T, vec_scalar_addmul, T) (rop + n, op2 + n - i, len2 + i - n, op1 + i, ctx); } } } void TEMPLATE(T, poly_mulhigh_classical) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong start, const TEMPLATE(T, ctx_t) ctx) { slong len_out = op1->length + op2->length - 1; if (op1->length == 0 || op2->length == 0 || start >= len_out) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (rop == op1 || rop == op2) { TEMPLATE(T, poly_t) temp; TEMPLATE(T, poly_init2) (temp, len_out, ctx); if (op1->length >= op2->length) _TEMPLATE(T, poly_mulhigh_classical) (temp->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, start, ctx); else _TEMPLATE(T, poly_mulhigh_classical) (temp->coeffs, op2->coeffs, op2->length, op1->coeffs, op1->length, start, ctx); TEMPLATE(T, poly_swap) (rop, temp, ctx); TEMPLATE(T, poly_clear) (temp, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len_out, ctx); if (op1->length >= op2->length) _TEMPLATE(T, poly_mulhigh_classical) (rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, start, ctx); else _TEMPLATE(T, poly_mulhigh_classical) (rop->coeffs, op2->coeffs, op2->length, op1->coeffs, op1->length, start, ctx); } _TEMPLATE(T, poly_set_length) (rop, len_out, ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } #endif flint-3.1.3/src/fq_poly_templates/mullow.c000066400000000000000000000043621461254215100206410ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_mullow) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, slong n, const TEMPLATE(T, ctx_t) ctx) { if (n < TEMPLATE(CAP_T, MULLOW_CLASSICAL_CUTOFF) || FLINT_MAX(len1, len2) < 6) { _TEMPLATE(T, poly_mullow_classical) (rop, op1, len1, op2, len2, n, ctx); } else { _TEMPLATE(T, poly_mullow_KS) (rop, op1, len1, op2, len2, n, ctx); } } void TEMPLATE(T, poly_mullow) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx) { const slong len1 = op1->length; const slong len2 = op2->length; const slong lenr = op1->length + op2->length - 1; if (len1 == 0 || len2 == 0 || n == 0) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (n > lenr) n = lenr; if (rop == op1 || rop == op2) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, n, ctx); _TEMPLATE(T, poly_mullow) (t->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, n, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, n, ctx); _TEMPLATE(T, poly_mullow) (rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, n, ctx); } _TEMPLATE(T, poly_set_length) (rop, n, ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } #endif flint-3.1.3/src/fq_poly_templates/mullow_KS.c000066400000000000000000000055451461254215100212420ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "fmpz_poly.h" void _TEMPLATE(T, poly_mullow_KS) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, slong n, const TEMPLATE(T, ctx_t) ctx) { const slong d = TEMPLATE(T, ctx_degree) (ctx); slong bits, i, m; fmpz *f, *g, *h; TEMPLATE(CAP_T, VEC_NORM) (op1, len1, ctx); TEMPLATE(CAP_T, VEC_NORM) (op2, len2, ctx); if (!len1 | !len2) { _TEMPLATE(T, poly_zero) (rop, n, ctx); return; } bits = FLINT_BIT_COUNT(d) + FLINT_BIT_COUNT(FLINT_MIN(len1, len2)); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) bits += 2 * FLINT_BIT_COUNT(TEMPLATE(T, ctx_prime)(ctx)); #else bits += 2 * fmpz_bits(TEMPLATE(T, ctx_prime)(ctx)); #endif f = _fmpz_vec_init(n + len1 + len2); g = f + n; h = g + len1; for (i = 0; i < len1; i++) { TEMPLATE(T, bit_pack) (g + i, op1 + i, bits, ctx); } for (i = 0; i < len2; i++) { TEMPLATE(T, bit_pack) (h + i, op2 + i, bits, ctx); } m = FLINT_MIN(n, len1 + len2 - 1); if (len1 >= len2) _fmpz_poly_mullow(f, g, len1, h, len2, m); else _fmpz_poly_mullow(f, h, len2, g, len1, m); for (i = 0; i < m; i++) { TEMPLATE(T, bit_unpack) (rop + i, f + i, bits, ctx); } for (; i < n; i++) { TEMPLATE(T, zero) (rop + i, ctx); } _fmpz_vec_clear(f, n + len1 + len2); } void TEMPLATE(T, poly_mullow_KS) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx) { const slong len1 = op1->length; const slong len2 = op2->length; if (len1 == 0 || len2 == 0 || n == 0) { TEMPLATE(T, poly_zero) (rop, ctx); } else { const slong lenr = op1->length + op2->length - 1; if (n > lenr) n = lenr; TEMPLATE(T, poly_fit_length) (rop, n, ctx); _TEMPLATE(T, poly_mullow_KS) (rop->coeffs, op1->coeffs, len1, op2->coeffs, len2, n, ctx); _TEMPLATE(T, poly_set_length) (rop, n, ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/mullow_classical.c000066400000000000000000000053201461254215100226520ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_mullow_classical) ( TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, slong n, const TEMPLATE(T, ctx_t) ctx) { if ((len1 == 1 && len2 == 1) || n == 1) { TEMPLATE(T, mul) (rop, op1, op2, ctx); } else { slong i; _TEMPLATE3(T, poly_scalar_mul, T)(rop, op1, FLINT_MIN(len1, n), op2, ctx); if (n > len1) _TEMPLATE3(T, poly_scalar_mul, T) (rop + len1, op2 + 1, n - len1, op1 + len1 - 1, ctx); for (i = 0; i < FLINT_MIN(len1, n) - 1; i++) _TEMPLATE3(T, poly_scalar_addmul, T) (rop + i + 1, op2 + 1, FLINT_MIN(len2, n - i) - 1, op1 + i, ctx); } } void TEMPLATE(T, poly_mullow_classical) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, slong n, const TEMPLATE(T, ctx_t) ctx) { const slong len = op1->length + op2->length - 1; if (op1->length == 0 || op2->length == 0 || n == 0) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (n > len) n = len; if (rop == op1 || rop == op2) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, n, ctx); _TEMPLATE(T, poly_mullow_classical) (t->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, n, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, n, ctx); _TEMPLATE(T, poly_mullow_classical) (rop->coeffs, op1->coeffs, op1->length, op2->coeffs, op2->length, n, ctx); } _TEMPLATE(T, poly_set_length) (rop, n, ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } #endif flint-3.1.3/src/fq_poly_templates/mulmod.c000066400000000000000000000054711461254215100206210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_mulmod) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; TEMPLATE(T, t) invf; slong lenT, lenQ; lenT = len1 + len2 - 1; lenQ = lenT - lenf + 1; T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; if (len1 >= len2) _TEMPLATE(T, poly_mul) (T, poly1, len1, poly2, len2, ctx); else _TEMPLATE(T, poly_mul) (T, poly2, len2, poly1, len1, ctx); TEMPLATE(T, init) (invf, ctx); TEMPLATE(T, inv) (invf, f + lenf - 1, ctx); _TEMPLATE(T, poly_divrem) (Q, res, T, lenT, f, lenf, invf, ctx); _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); TEMPLATE(T, clear) (invf, ctx); } void TEMPLATE(T, poly_mulmod) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { slong len1, len2, lenf; TEMPLATE(T, struct) * fcoeffs; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (lenf == 1 || len1 == 0 || len2 == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 + len2 - lenf > 0) { if (f == res) { fcoeffs = _TEMPLATE(T, vec_init) (lenf, ctx); _TEMPLATE(T, vec_set) (fcoeffs, f->coeffs, lenf, ctx); } else fcoeffs = f->coeffs; TEMPLATE(T, poly_fit_length) (res, len1 + len2 - 1, ctx); _TEMPLATE(T, poly_mulmod) (res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fcoeffs, lenf, ctx); if (f == res) _TEMPLATE(T, vec_clear) (fcoeffs, lenf, ctx); _TEMPLATE(T, poly_set_length) (res, lenf - 1, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } else { TEMPLATE(T, poly_mul) (res, poly1, poly2, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/mulmod_preinv.c000066400000000000000000000077311461254215100222050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_mulmod_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; slong lenT, lenQ; lenT = len1 + len2 - 1; lenQ = lenT - lenf + 1; if (len1 + len2 > lenf) /* reduction necessary */ { T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; if (len1 >= len2) _TEMPLATE(T, poly_mul) (T, poly1, len1, poly2, len2, ctx); else _TEMPLATE(T, poly_mul) (T, poly2, len2, poly1, len1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, lenT, f, lenf, finv, lenfinv, ctx); _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); } else /* just use mul */ { if (len1 >= len2) _TEMPLATE(T, poly_mul) (res, poly1, len1, poly2, len2, ctx); else _TEMPLATE(T, poly_mul) (res, poly2, len2, poly1, len1, ctx); if (lenT < lenf - 1) _TEMPLATE(T, vec_zero) (res + lenT, lenf - lenT - 1, ctx); } } void TEMPLATE(T, poly_mulmod_preinv) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx) { slong len1, len2, lenf; TEMPLATE(T, struct) * fcoeffs, * coeffs1, * coeffs2; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (lenf == 1 || len1 == 0 || len2 == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (len1 + len2 - lenf > 0) { if (f == res) { fcoeffs = _TEMPLATE(T, vec_init) (lenf, ctx); _TEMPLATE(T, vec_set) (fcoeffs, f->coeffs, lenf, ctx); } else fcoeffs = f->coeffs; if (poly1 == res) { coeffs1 = _TEMPLATE(T, vec_init) (len1, ctx); _TEMPLATE(T, vec_set) (coeffs1, poly1->coeffs, len1, ctx); } else coeffs1 = poly1->coeffs; if (poly2 == res) { coeffs2 = _TEMPLATE(T, vec_init) (len2, ctx); _TEMPLATE(T, vec_set) (coeffs2, poly2->coeffs, len2, ctx); } else coeffs2 = poly2->coeffs; TEMPLATE(T, poly_fit_length) (res, lenf - 1, ctx); _TEMPLATE(T, poly_mulmod_preinv) (res->coeffs, coeffs1, len1, coeffs2, len2, fcoeffs, lenf, finv->coeffs, finv->length, ctx); if (f == res) _TEMPLATE(T, vec_clear) (fcoeffs, lenf, ctx); if (poly1 == res) _TEMPLATE(T, vec_clear) (coeffs1, len1, ctx); if (poly2 == res) _TEMPLATE(T, vec_clear) (coeffs2, len2, ctx); res->length = lenf - 1; _TEMPLATE(T, poly_normalise) (res, ctx); } else { TEMPLATE(T, poly_mul) (res, poly1, poly2, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/neg.c000066400000000000000000000020471461254215100200710ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_neg) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) TEMPLATE(T, neg) (rop + i, op + i, ctx); } void TEMPLATE(T, poly_neg) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_fit_length) (rop, op->length, ctx); _TEMPLATE(T, poly_neg) (rop->coeffs, op->coeffs, op->length, ctx); _TEMPLATE(T, poly_set_length) (rop, op->length, ctx); } #endif flint-3.1.3/src/fq_poly_templates/normalise.c000066400000000000000000000017751461254215100213200ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_normalise) (TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = poly->length - 1; (i >= 0) && TEMPLATE(T, is_zero) (poly->coeffs + i, ctx); i--) ; poly->length = i + 1; } void _TEMPLATE(T, poly_normalise2) (const TEMPLATE(T, struct) * poly, slong * length, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = (*length) - 1; (i >= 0) && TEMPLATE(T, is_zero) (poly + i, ctx); i--) ; (*length) = i + 1; } #endif flint-3.1.3/src/fq_poly_templates/one.c000066400000000000000000000012611461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_one) (TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_fit_length) (poly, 1, ctx); TEMPLATE(T, one) (poly->coeffs + 0, ctx); _TEMPLATE(T, poly_set_length) (poly, 1, ctx); } #endif flint-3.1.3/src/fq_poly_templates/pow.c000066400000000000000000000074621461254215100201330ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_pow) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, ulong e, const TEMPLATE(T, ctx_t) ctx) { ulong bit = ~((~UWORD(0)) >> 1); slong rlen; slong alloc = (slong) e * (len - 1) + 1; TEMPLATE(T, struct) * v = _TEMPLATE(T, vec_init) (alloc, ctx); TEMPLATE(T, struct) * R, *S, *T; /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = rop; S = v; } else { R = v; S = rop; } } /* We unroll the first step of the loop, referring to {poly, len} */ _TEMPLATE(T, poly_sqr) (R, op, len, ctx); rlen = 2 * len - 1; if ((bit & e)) { _TEMPLATE(T, poly_mul) (S, R, rlen, op, len, ctx); rlen += len - 1; T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _TEMPLATE(T, poly_sqr) (S, R, rlen, ctx); rlen += rlen - 1; _TEMPLATE(T, poly_mul) (R, S, rlen, op, len, ctx); rlen += len - 1; } else { _TEMPLATE(T, poly_sqr) (S, R, rlen, ctx); rlen += rlen - 1; T = R; R = S; S = T; } } _TEMPLATE(T, vec_clear) (v, alloc, ctx); } void TEMPLATE(T, poly_pow) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, ulong e, const TEMPLATE(T, ctx_t) ctx) { const slong len = op->length; if ((len < 2) | (e < UWORD(3))) { if (e == UWORD(0)) TEMPLATE(T, poly_one) (rop, ctx); else if (len == 0) TEMPLATE(T, poly_zero) (rop, ctx); else if (len == 1) { fmpz_t f; fmpz_init_set_ui(f, e); TEMPLATE(T, poly_fit_length) (rop, 1, ctx); TEMPLATE(T, pow) (rop->coeffs + 0, op->coeffs + 0, f, ctx); _TEMPLATE(T, poly_set_length) (rop, 1, ctx); fmpz_clear(f); } else if (e == UWORD(1)) TEMPLATE(T, poly_set) (rop, op, ctx); else /* e == UWORD(2) */ TEMPLATE(T, poly_sqr) (rop, op, ctx); } else { const slong rlen = (slong) e * (len - 1) + 1; if (rop != op) { TEMPLATE(T, poly_fit_length) (rop, rlen, ctx); _TEMPLATE(T, poly_pow) (rop->coeffs, op->coeffs, len, e, ctx); _TEMPLATE(T, poly_set_length) (rop, rlen, ctx); } else { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, rlen, ctx); _TEMPLATE(T, poly_pow) (t->coeffs, op->coeffs, len, e, ctx); _TEMPLATE(T, poly_set_length) (t, rlen, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } } } #endif flint-3.1.3/src/fq_poly_templates/pow_trunc.c000066400000000000000000000055661461254215100213510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_pow_trunc) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx) { _TEMPLATE(T, poly_pow_trunc_binexp) (res, poly, e, trunc, ctx); } void TEMPLATE(T, poly_pow_trunc) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx) { const slong len = poly->length; TEMPLATE(T, struct) * p; int pcopy = 0; if (len < 2 || e < UWORD(3) || trunc == 0) { if (len == 0 || trunc == 0) TEMPLATE(T, poly_zero) (res, ctx); else if (len == 1) { TEMPLATE(T, poly_fit_length) (res, 1, ctx); TEMPLATE(T, pow_ui) (res->coeffs + 0, poly->coeffs + 0, e, ctx); _TEMPLATE(T, poly_set_length) (res, 1, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } else if (e == UWORD(0)) { TEMPLATE(T, t) c; TEMPLATE(T, init) (c, ctx); TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (res, 0, c, ctx); _TEMPLATE(T, poly_set_length) (res, 1, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); TEMPLATE(T, clear) (c, ctx); } else if (e == UWORD(1)) { TEMPLATE(T, poly_set) (res, poly, ctx); TEMPLATE(T, poly_truncate) (res, trunc, ctx); } else /* e == UWORD(2) */ TEMPLATE(T, poly_mullow) (res, poly, poly, trunc, ctx); return; } if (poly->length < trunc) { p = _TEMPLATE(T, vec_init) (trunc, ctx); _TEMPLATE(T, vec_set) (p, poly->coeffs, poly->length, ctx); _TEMPLATE(T, vec_zero) (p + poly->length, trunc - poly->length, ctx); pcopy = 1; } else p = poly->coeffs; if (res != poly || pcopy) { TEMPLATE(T, poly_fit_length) (res, trunc, ctx); _TEMPLATE(T, poly_pow_trunc) (res->coeffs, p, e, trunc, ctx); } else { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, trunc, ctx); _TEMPLATE(T, poly_pow_trunc) (t->coeffs, p, e, trunc, ctx); TEMPLATE(T, poly_swap) (res, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } if (pcopy) _TEMPLATE(T, vec_clear) (p, trunc, ctx); _TEMPLATE(T, poly_set_length) (res, trunc, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/pow_trunc_binexp.c000066400000000000000000000107031461254215100227030ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_pow_trunc_binexp) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx) { ulong bit = ~((~UWORD(0)) >> 1); TEMPLATE(T, struct) * v = _TEMPLATE(T, vec_init) (trunc, ctx); TEMPLATE(T, struct) * R, * S, * T; /* Set bits to the bitmask with a 1 one place `lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, len} */ _TEMPLATE(T, poly_mullow) (R, poly, trunc, poly, trunc, trunc, ctx); if ((bit & e)) { _TEMPLATE(T, poly_mullow) (S, R, trunc, poly, trunc, trunc, ctx); T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _TEMPLATE(T, poly_mullow) (S, R, trunc, R, trunc, trunc, ctx); _TEMPLATE(T, poly_mullow) (R, S, trunc, poly, trunc, trunc, ctx); } else { _TEMPLATE(T, poly_mullow) (S, R, trunc, R, trunc, trunc, ctx); T = R; R = S; S = T; } } _TEMPLATE(T, vec_clear) (v, trunc, ctx); } void TEMPLATE(T, poly_pow_trunc_binexp) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, slong trunc, const TEMPLATE(T, ctx_t) ctx) { const slong len = poly->length; TEMPLATE(T, struct) * p; int pcopy = 0; if (len < 2 || e < UWORD(3) || trunc == 0) { if (len == 0 || trunc == 0) TEMPLATE(T, poly_zero) (res, ctx); else if (len == 1) { TEMPLATE(T, poly_fit_length) (res, 1, ctx); TEMPLATE(T, pow_ui) (res->coeffs + 0, poly->coeffs + 0, e, ctx); _TEMPLATE(T, poly_set_length) (res, 1, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } else if (e == UWORD(0)) { TEMPLATE(T, t) c; TEMPLATE(T, init) (c, ctx); TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (res, 0, c, ctx); _TEMPLATE(T, poly_set_length) (res, 1, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); TEMPLATE(T, clear) (c, ctx); } else if (e == UWORD(1)) { TEMPLATE(T, poly_set) (res, poly, ctx); TEMPLATE(T, poly_truncate) (res, trunc, ctx); } else /* e == UWORD(2) */ TEMPLATE(T, poly_mullow) (res, poly, poly, trunc, ctx); return; } if (poly->length < trunc) { p = _TEMPLATE(T, vec_init) (trunc, ctx); _TEMPLATE(T, vec_set) (p, poly->coeffs, poly->length, ctx); _TEMPLATE(T, vec_zero) (p + poly->length, trunc - poly->length, ctx); pcopy = 1; } else p = poly->coeffs; if (res != poly || pcopy) { TEMPLATE(T, poly_fit_length) (res, trunc, ctx); _TEMPLATE(T, poly_pow_trunc_binexp) (res->coeffs, p, e, trunc, ctx); } else { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, trunc, ctx); _TEMPLATE(T, poly_pow_trunc_binexp) (t->coeffs, p, e, trunc, ctx); TEMPLATE(T, poly_swap) (res, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } if (pcopy) _TEMPLATE(T, vec_clear) (p, trunc, ctx); res->length = trunc; _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/powmod_fmpz_binexp.c000066400000000000000000000103741461254215100232300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" void _TEMPLATE(T, poly_powmod_fmpz_binexp) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, const fmpz_t e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; TEMPLATE(T, t) invf; slong lenT, lenQ; slong i; if (lenf == 2) { TEMPLATE(T, pow) (res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; TEMPLATE(T, init) (invf, ctx); TEMPLATE(T, inv) (invf, f + lenf - 1, ctx); _TEMPLATE(T, vec_set) (res, poly, lenf - 1, ctx); for (i = fmpz_sizeinbase(e, 2) - 2; i >= 0; i--) { _TEMPLATE(T, poly_sqr) (T, res, lenf - 1, ctx); _TEMPLATE(T, poly_divrem) (Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); if (fmpz_tstbit(e, i)) { _TEMPLATE(T, poly_mul) (T, res, lenf - 1, poly, lenf - 1, ctx); _TEMPLATE(T, poly_divrem) (Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); } } TEMPLATE(T, clear) (invf, ctx); _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); } void TEMPLATE(T, poly_powmod_fmpz_binexp) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, const fmpz_t e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "(%s): Division by zero\n", __func__); } if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "(%s): Negative exp not implemented\n", __func__); } if (len >= lenf) { TEMPLATE(T, poly_t) t, r; TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_divrem) (t, r, poly, f, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (res, r, e, f, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (r, ctx); return; } if (fmpz_is_zero(e)) { if (lenf == 1) TEMPLATE(T, poly_zero)(res, ctx); else TEMPLATE(T, poly_one)(res, ctx); return; } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (fmpz_is_one(e)) { TEMPLATE(T, poly_set) (res, poly, ctx); return; } else if (*e == WORD(2)) /* NOTE: This check works */ { TEMPLATE(T, poly_mulmod) (res, poly, poly, f, ctx); return; } if (poly->length < trunc) { q = _TEMPLATE(T, vec_init) (trunc, ctx); _TEMPLATE(T, vec_set) (q, poly->coeffs, len, ctx); _TEMPLATE(T, vec_zero) (q + len, trunc - len, ctx); qcopy = 1; } else { q = poly->coeffs; } if ((res == poly && !qcopy) || (res == f)) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_fmpz_binexp) (t->coeffs, q, e, f->coeffs, lenf, ctx); TEMPLATE(T, poly_swap) (res, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (res, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_fmpz_binexp) (res->coeffs, q, e, f->coeffs, lenf, ctx); } if (qcopy) _TEMPLATE(T, vec_clear) (q, trunc, ctx); _TEMPLATE(T, poly_set_length) (res, trunc, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/powmod_fmpz_binexp_preinv.c000066400000000000000000000113041461254215100246050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, const fmpz_t e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; slong lenT, lenQ; slong i; if (lenf == 2) { TEMPLATE(T, pow) (res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; _TEMPLATE(T, vec_set) (res, poly, lenf - 1, ctx); for (i = fmpz_sizeinbase(e, 2) - 2; i >= 0; i--) { _TEMPLATE(T, poly_sqr) (T, res, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); if (fmpz_tstbit(e, i)) { _TEMPLATE(T, poly_mul) (T, res, lenf - 1, poly, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); } } _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); } void TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, const fmpz_t e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "(%s): Divide by zero\n", __func__); } if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "(%s): Negative exp not implemented\n", __func__); } if (len >= lenf) { TEMPLATE(T, poly_t) t, r; TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_divrem) (t, r, poly, f, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res, r, e, f, finv, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (r, ctx); return; } if (fmpz_is_zero(e)) { if (lenf == 1) TEMPLATE(T, poly_zero)(res, ctx); else TEMPLATE(T, poly_one)(res, ctx); return; } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (fmpz_is_one(e)) { TEMPLATE(T, poly_set) (res, poly, ctx); return; } else if (*e == WORD(2)) /* NOTE: This check works */ { TEMPLATE(T, poly_mulmod) (res, poly, poly, f, ctx); return; } if (poly->length < trunc) { q = _TEMPLATE(T, vec_init) (trunc, ctx); _TEMPLATE(T, vec_set) (q, poly->coeffs, len, ctx); _TEMPLATE(T, vec_zero) (q + len, trunc - len, ctx); qcopy = 1; } else { q = poly->coeffs; } if ((res == poly && !qcopy) || (res == f)) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (t->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); TEMPLATE(T, poly_swap) (res, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (res, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } if (qcopy) _TEMPLATE(T, vec_clear) (q, trunc, ctx); _TEMPLATE(T, poly_set_length) (res, trunc, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/powmod_fmpz_sliding_preinv.c000066400000000000000000000174711461254215100247640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, const fmpz_t e, ulong k, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; TEMPLATE(T, poly_struct) * precomp; TEMPLATE(T, poly_t) poly_squared; ulong twokm1; slong lenT, lenQ; slong i, l, j; int index; if (lenf == 2) { TEMPLATE(T, pow) (res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; /* Precomputation */ twokm1 = n_pow(2, k - 1); precomp = flint_malloc(twokm1 * sizeof(TEMPLATE(T, poly_struct))); TEMPLATE(T, poly_init) (precomp, ctx); TEMPLATE(T, poly_fit_length) (precomp, lenf - 1, ctx); _TEMPLATE(T, vec_set) (precomp->coeffs, poly, lenf - 1, ctx); TEMPLATE(T, poly_init) (poly_squared, ctx); if (k > 1) { TEMPLATE(T, poly_fit_length) (poly_squared, lenf - 1, ctx); _TEMPLATE(T, poly_mul) (T, poly, lenf - 1, poly, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, poly_squared->coeffs, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); } for (i = 1; i < twokm1; i++) { TEMPLATE(T, poly_init) (precomp + i, ctx); TEMPLATE(T, poly_fit_length) (precomp + i, lenf - 1, ctx); _TEMPLATE(T, poly_mul) (T, (precomp + i - 1)->coeffs, lenf - 1, poly_squared->coeffs, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, (precomp + i)->coeffs, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); } _TEMPLATE(T, vec_set) (res, poly, lenf - 1, ctx); i = fmpz_sizeinbase(e, 2) - 2; while (i >= 0) { if (fmpz_tstbit(e, i) == 0) { _TEMPLATE(T, poly_sqr) (T, res, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); i -= 1; } else { l = FLINT_MAX(i - k + 1, 0); while (fmpz_tstbit(e, l) == 0) { l += 1; } for (j = 0; j < i - l + 1; j++) { _TEMPLATE(T, poly_sqr) (T, res, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); } index = fmpz_tstbit(e, i); for (j = i - 1; j >= l; j--) { index = index << 1; index += fmpz_tstbit(e, j); } index = (index - 1) / 2; _TEMPLATE(T, poly_mul) (T, res, lenf - 1, (precomp + index)->coeffs, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); i = l - 1; } } for (j = 0; j < twokm1; j++) { TEMPLATE(T, poly_clear) (precomp + j, ctx); } flint_free(precomp); TEMPLATE(T, poly_clear) (poly_squared, ctx); _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); } void TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, const fmpz_t e, ulong k, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; flint_bitcnt_t bits; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception: " TEMPLATE_STR(T) "_poly_powmod_fmpz_sliding_preinv: divide by zero\n"); } if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "Exception: " TEMPLATE_STR(T) "_poly_powmod_fmpz_sliding_preinv: negative exp not implemented\n"); } if (len >= lenf) { TEMPLATE(T, poly_t) t, r; TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_divrem) (t, r, poly, f, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (res, r, e, k, f, finv, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (r, ctx); return; } if (fmpz_is_zero(e)) { if (lenf == 1) TEMPLATE(T, poly_zero)(res, ctx); else TEMPLATE(T, poly_one)(res, ctx); return; } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (fmpz_is_one(e)) { TEMPLATE(T, poly_set) (res, poly, ctx); return; } else if (*e == WORD(2)) /* NOTE: This check works */ { TEMPLATE(T, poly_mulmod) (res, poly, poly, f, ctx); return; } if (poly->length < trunc) { q = _TEMPLATE(T, vec_init) (trunc, ctx); _TEMPLATE(T, vec_set) (q, poly->coeffs, len, ctx); _TEMPLATE(T, vec_zero) (q + len, trunc - len, ctx); qcopy = 1; } else { q = poly->coeffs; } /* Determine "optimum" sliding window size */ if (k == 0) { bits = fmpz_bits(e); if (bits < 9) k = 1; else if (bits < 15) k = 2; else if (bits < 62) k = 3; else if (bits < 203) k = 4; else if (bits < 587) k = 5; else if (bits < 1560) k = 6; else k = 7; } if ((res == poly && !qcopy) || (res == f)) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (t->coeffs, q, e, k, f->coeffs, lenf, finv->coeffs, finv->length, ctx); TEMPLATE(T, poly_swap) (res, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (res, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (res->coeffs, q, e, k, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } if (qcopy) _TEMPLATE(T, vec_clear) (q, trunc, ctx); _TEMPLATE(T, poly_set_length) (res, trunc, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/powmod_ui_binexp.c000066400000000000000000000102131461254215100226610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "flint.h" #include "ulong_extras.h" void _TEMPLATE(T, poly_powmod_ui_binexp) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; TEMPLATE(T, t) invf; slong lenT, lenQ; int i; if (lenf == 2) { TEMPLATE(T, pow_ui) (res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; TEMPLATE(T, init) (invf, ctx); TEMPLATE(T, inv) (invf, f + lenf - 1, ctx); _TEMPLATE(T, vec_set) (res, poly, lenf - 1, ctx); for (i = ((int)FLINT_BIT_COUNT(e) - 2); i >= 0; i--) { _TEMPLATE(T, poly_sqr) (T, res, lenf - 1, ctx); _TEMPLATE(T, poly_divrem) (Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); if (e & (UWORD(1) << i)) { _TEMPLATE(T, poly_mul) (T, res, lenf - 1, poly, lenf - 1, ctx); _TEMPLATE(T, poly_divrem) (Q, res, T, 2 * lenf - 3, f, lenf, invf, ctx); } } TEMPLATE(T, clear) (invf, ctx); _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); } void TEMPLATE(T, poly_powmod_ui_binexp) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "(%s): Divide by zero\n", __func__); } if (len >= lenf) { TEMPLATE(T, poly_t) t, r; TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_divrem) (t, r, poly, f, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (res, r, e, f, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (r, ctx); return; } if (e == UWORD(0)) { if (lenf == 1) TEMPLATE(T, poly_zero)(res, ctx); else TEMPLATE(T, poly_one)(res, ctx); return; } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (e == UWORD(1)) { TEMPLATE(T, poly_set) (res, poly, ctx); return; } else if (e == UWORD(2)) { TEMPLATE(T, poly_mulmod) (res, poly, poly, f, ctx); return; } if (len < trunc) { q = _TEMPLATE(T, vec_init) (trunc, ctx); _TEMPLATE(T, vec_set) (q, poly->coeffs, len, ctx); _TEMPLATE(T, vec_zero) (q + len, trunc - len, ctx); qcopy = 1; } else q = poly->coeffs; if ((res == poly && !qcopy) || (res == f)) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_ui_binexp) (t->coeffs, q, e, f->coeffs, lenf, ctx); TEMPLATE(T, poly_swap) (res, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (res, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_ui_binexp) (res->coeffs, q, e, f->coeffs, lenf, ctx); } if (qcopy) _TEMPLATE(T, vec_clear) (q, trunc, ctx); _TEMPLATE(T, poly_set_length) (res, trunc, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/powmod_ui_binexp_preinv.c000066400000000000000000000107741461254215100242600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_powmod_ui_binexp_preinv) ( TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, ulong e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; slong lenT, lenQ; int i; if (lenf == 2) { TEMPLATE(T, pow_ui) (res, poly, e, ctx); return; } lenT = 2 * lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; _TEMPLATE(T, vec_set) (res, poly, lenf - 1, ctx); for (i = ((int)FLINT_BIT_COUNT(e) - 2); i >= 0; i--) { _TEMPLATE(T, poly_sqr) (T, res, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); if (e & (UWORD(1) << i)) { _TEMPLATE(T, poly_mul) (T, res, lenf - 1, poly, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); } } _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); } void TEMPLATE(T, poly_powmod_ui_binexp_preinv) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, ulong e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * q; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int qcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "(%s): Divide by zero\n", __func__); } if (len >= lenf) { TEMPLATE(T, poly_t) t, r; TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_divrem) (t, r, poly, f, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res, r, e, f, finv, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (r, ctx); return; } if (e == UWORD(0)) { if (lenf == 1) TEMPLATE(T, poly_zero)(res, ctx); else TEMPLATE(T, poly_one)(res, ctx); return; } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (e == UWORD(1)) { TEMPLATE(T, poly_set) (res, poly, ctx); return; } else if (e == UWORD(2)) { TEMPLATE(T, poly_mulmod) (res, poly, poly, f, ctx); return; } if (len < trunc) { q = _TEMPLATE(T, vec_init) (trunc, ctx); _TEMPLATE(T, vec_set) (q, poly->coeffs, len, ctx); _TEMPLATE(T, vec_zero) (q + len, trunc - len, ctx); qcopy = 1; } else q = poly->coeffs; if ((res == poly && !qcopy) || (res == f)) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_ui_binexp_preinv) (t->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); TEMPLATE(T, poly_swap) (res, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (res, 2 * lenf - 3, ctx); _TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res->coeffs, q, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } if (qcopy) _TEMPLATE(T, vec_clear) (q, trunc, ctx); _TEMPLATE(T, poly_set_length) (res, trunc, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/powmod_x_fmpz_preinv.c000066400000000000000000000131041461254215100235670ustar00rootroot00000000000000/* Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "long_extras.h" void _TEMPLATE(T, poly_powmod_x_fmpz_preinv) ( TEMPLATE(T, struct) * res, const fmpz_t e, const TEMPLATE(T, struct) * f, slong lenf, const TEMPLATE(T, struct) * finv, slong lenfinv, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * T, *Q; slong lenT, lenQ; slong i, window, l, c; lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _TEMPLATE(T, vec_init) (lenT + lenQ, ctx); Q = T + lenT; TEMPLATE(T, one) (res, ctx); _TEMPLATE(T, vec_zero) (res + 1, lenf - 2, ctx); l = z_sizeinbase(lenf - 1, 2) - 2; window = 0; window = (1 << l); c = l; i = fmpz_sizeinbase(e, 2) - 2; if (i <= l) { window = 0; window = (1 << i); c = i; l = i; } if (c == 0) { _TEMPLATE(T, poly_shift_left) (T, res, lenf - 1, window, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, ctx); c = l + 1; window = 0; } for (; i >= 0; i--) { _TEMPLATE(T, poly_sqr) (T, res, lenf - 1, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, ctx); c--; if (fmpz_tstbit(e, i)) { if (window == 0 && i <= l - 1) c = i; if (c >= 0) window = window | (1 << c); } else if (window == 0) { c = l + 1; } if (c == 0) { _TEMPLATE(T, poly_shift_left) (T, res, lenf - 1, window, ctx); _TEMPLATE(T, poly_divrem_newton_n_preinv) (Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, ctx); c = l + 1; window = 0; } } _TEMPLATE(T, vec_clear) (T, lenT + lenQ, ctx); } void TEMPLATE(T, poly_powmod_x_fmpz_preinv) (TEMPLATE(T, poly_t) res, const fmpz_t e, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) finv, const TEMPLATE(T, ctx_t) ctx) { slong lenf = f->length; slong trunc = lenf - 1; TEMPLATE(T, poly_t) tmp; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception: " TEMPLATE_STR(T) "_poly_powmod_x_preinv: divide by zero\n"); } if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "Exception: " TEMPLATE_STR(T) "_poly_powmod_x_preinv: negative exp not implemented\n"); } if (lenf == 1) { TEMPLATE(T, poly_zero) (res, ctx); return; } if (lenf == 2) { TEMPLATE(T, poly_t) r, poly; TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_init2) (poly, 2, ctx); TEMPLATE(T, poly_gen) (poly, ctx); TEMPLATE(T, poly_divrem) (tmp, r, poly, f, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res, r, e, f, finv, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (poly, ctx); return; } if (*e <= UWORD(2)) /* NOTE: This check works */ { if (*e == UWORD(0)) { TEMPLATE(T, poly_fit_length) (res, 1, ctx); TEMPLATE(T, one) (res->coeffs, ctx); _TEMPLATE(T, poly_set_length) (res, 1, ctx); } else if (*e == UWORD(1)) { TEMPLATE(T, poly_t) r; TEMPLATE(T, poly_init2) (r, 2, ctx); TEMPLATE(T, poly_gen) (r, ctx); TEMPLATE(T, poly_init) (tmp, ctx); TEMPLATE(T, poly_divrem) (tmp, res, r, f, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); TEMPLATE(T, poly_clear) (r, ctx); } else { TEMPLATE(T, poly_init2) (tmp, 3, ctx); TEMPLATE(T, poly_gen) (tmp, ctx); TEMPLATE(T, poly_mulmod) (res, tmp, tmp, f, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); } return; } if ((res == f) || (res == finv)) { TEMPLATE(T, poly_init2) (tmp, trunc, ctx); _TEMPLATE(T, poly_powmod_x_fmpz_preinv) (tmp->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); TEMPLATE(T, poly_swap) (res, tmp, ctx); TEMPLATE(T, poly_clear) (tmp, ctx); } else { TEMPLATE(T, poly_fit_length) (res, trunc, ctx); _TEMPLATE(T, poly_powmod_x_fmpz_preinv) (res->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, ctx); } _TEMPLATE(T, poly_set_length) (res, trunc, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/profile/000077500000000000000000000000001461254215100206115ustar00rootroot00000000000000flint-3.1.3/src/fq_poly_templates/profile/p-factor_xnpxp1.c000066400000000000000000000030701461254215100240060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include "profiler.h" #define nalgs 1 #define ncases 1 #define cpumin 2 int main(int argc, char** argv) { int len, ext; fmpz_t p, temp; TEMPLATE(T, poly_t) f; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_factor_t) res; timeit_t t; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); fmpz_set_str(temp, argv[3], 10); len = fmpz_get_si(temp); TEMPLATE(T, ctx_init)(ctx, p, ext, "a"); TEMPLATE(T, poly_init)(f, ctx); fmpz_one(temp); TEMPLATE(T, poly_set_coeff_fmpz)(f, len + 1, temp, ctx); TEMPLATE(T, poly_set_coeff_fmpz)(f, 1, temp, ctx); TEMPLATE(T, poly_set_coeff_fmpz)(f, 0, temp, ctx); TEMPLATE(T, poly_factor_init)(res, ctx); timeit_start(t); TEMPLATE(T, poly_factor_kaltofen_shoup)(res, f, ctx); timeit_stop(t); TEMPLATE(T, poly_factor_clear)(res, ctx); flint_printf("%wd\n", t->cpu); TEMPLATE(T, poly_clear)(f, ctx); TEMPLATE(T, ctx_clear)(ctx); fmpz_clear(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } #endif flint-3.1.3/src/fq_poly_templates/profile/p-is_irreducible.c000066400000000000000000000044141461254215100242010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include "profiler.h" #define nalgs 2 #define ncases 20 #define cpumin 2 int main(int argc, char** argv) { double s[nalgs]; int c, n, lenf, ext, reps = 0; fmpz_t p, temp; TEMPLATE(T, poly_t) f; TEMPLATE(T, ctx_t) ctx; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); lenf = atol(argv[3]); TEMPLATE(T, ctx_init)(ctx, p, ext, "a"); TEMPLATE(T, poly_init)(f, ctx); for (c = 0; c < nalgs; c++) { s[c] = 0.0; } for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; /* Construct random elements of fq */ { TEMPLATE(T, poly_randtest_monic)(f, state, lenf, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { TEMPLATE(T, poly_is_irreducible_ben_or)(f, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { TEMPLATE(T, poly_is_irreducible_ddf)(f, ctx); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { flint_printf("%20f ", s[c] / (double) reps); fflush(stdout); } printf("\n"); TEMPLATE(T, poly_clear)(f, ctx); TEMPLATE(T, ctx_clear)(ctx); fmpz_clear(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } #endif flint-3.1.3/src/fq_poly_templates/profile/p-iterated_frobenius.c000066400000000000000000000111261461254215100250700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include #include "profiler.h" #define nalgs 2 #define cpumin 2 #define ncases 1 int main(int argc, char** argv) { fmpz_t p, q; int c, n, reps = 0; slong d, lenf; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, *h, finv; TEMPLATE(T, mat_t) HH; slong i, l; double beta; double s[nalgs]; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); d = atol(argv[2]); lenf = atol(argv[3]); beta = 0.5 * (1. - (log(2) / log(lenf))); l = ceil(pow(lenf, beta)); TEMPLATE(T, ctx_init)(ctx, p, d, "a"); TEMPLATE(T, poly_init)(f, ctx); TEMPLATE(T, poly_init)(finv, ctx); fmpz_init(q); TEMPLATE(T, ctx_order)(q, ctx); if (l < 2) { printf("l < 2!\n"); } if (!(h = flint_malloc((l + 1) * sizeof(TEMPLATE(T, poly_struct))))) { printf("Exception (p-iterated_frobenius):\n"); printf("Not enough memory.\n"); flint_abort(); } for (i = 0; i < l + 1; i++) TEMPLATE(T, poly_init)(h[i], ctx); for (c = 0; c < nalgs; c++) s[c] = 0.0; for (n = 0; n < ncases; n++) { double t[nalgs]; int lo, loops = 1; /* Construct random elements of fq */ { TEMPLATE(T, poly_randtest_monic)(f, state, lenf, ctx); TEMPLATE(T, poly_reverse)(finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton)(finv, finv, f->length, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, poly_gen)(h[0], ctx); TEMPLATE(T, mat_init)(HH, n_sqrt(f->length - 1) + 1, f->length - 1, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(h[1], h[0], q, 0, f, finv, ctx); TEMPLATE(T, poly_precompute_matrix)(HH, h[1], f, finv, ctx); for (i = 2; i < l + 1; i++) TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv)(h[i], h[i - 1], HH, f, finv, ctx); TEMPLATE(T, mat_clear)(HH, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, poly_gen)(h[0], ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(h[1], h[0], q, 0, f, finv, ctx); for (i = 2; i < l + 1; i++) TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(h[i], h[i-1], q, 0, f, finv, ctx); } prof_stop(); t[1] += get_clock(0); /*t[2] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, poly_gen)(h[0], ctx); TEMPLATE(T, poly_powmod_x_fmpz_preinv)(h[1], q, f, finv, ctx); for (i = 2; i < l + 1; i++) TEMPLATE(T, poly_compose_mod_preinv)(h[i], h[i-1], h[1], f, finv, ctx); } prof_stop(); t[2] += get_clock(0); t[3] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, poly_gen)(h[0], ctx); TEMPLATE(T, poly_powmod_x_fmpz_preinv)(h[1], q, f, finv, ctx); for (i = 2; i < l + 1; i++) TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(h[i], h[i-1], q, 0, f, finv, ctx); } prof_stop(); t[3] += get_clock(0); */ for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { printf("%20f", s[c] / (double) reps); fflush(stdout); } printf("\n"); TEMPLATE(T, poly_clear)(f, ctx); TEMPLATE(T, poly_clear)(finv, ctx); for (i = 0; i < l + 1; i++) TEMPLATE(T, poly_clear)(h[i], ctx); flint_free(h); TEMPLATE(T, ctx_clear)(ctx); fmpz_clear(p); fmpz_clear(q); FLINT_TEST_CLEANUP(state); return 0; } #endif flint-3.1.3/src/fq_poly_templates/profile/p-iterated_frobenius_table.c000066400000000000000000000242611461254215100262430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include #include #include "profiler.h" #include "fmpz_mat.h" #define nalgs 2 #define cpumin 1 #define ncases 2 int get_timings(double* s, slong degree, flint_bitcnt_t bits, slong length) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, *h, finv; TEMPLATE(T, mat_t) HH; fmpz_t p, q; double beta; slong i, l; int n, c, reps = 0; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_init(q); beta = 0.5 * (1. - (log(2) / log(length))); l = ceil(pow(length, beta)); if (!(h = flint_malloc((l + 1) * sizeof(TEMPLATE(T, poly_struct))))) { flint_printf("Exception (p-iterated_frobenius):\n"); flint_printf("Not enough memory.\n"); flint_abort(); } flint_printf("Trying %d %d %d\n", degree, bits, length); for (c = 0; c < nalgs; c++) s[c] = 0.0; reps = 0; /* Compute the timings */ for (n = 0; n < ncases; n++) { double t[nalgs]; int lo, loops = 1; #ifdef FQ_ZECH_VEC_NORM do { fmpz_set_ui(p, n_randprime(state, bits, 1)); fmpz_pow_ui(q, p, degree); } while (fmpz_cmp_ui(q, 1048576) > 0); #else fmpz_set_ui(p, n_randprime(state, bits, 1)); fmpz_pow_ui(q, p, degree); #endif TEMPLATE(T, ctx_init)(ctx, p, degree, "a"); TEMPLATE(T, poly_init)(f, ctx); TEMPLATE(T, poly_init)(finv, ctx); TEMPLATE(T, ctx_order)(q, ctx); #ifdef FQ_ZECH_VEC_NORM if (fmpz_cmp_ui(q, 1048576) > 0) { flint_printf("Order too big for zech representation: "); fmpz_print(q); flint_printf("\n"); flint_abort(); } #endif for (i = 0; i < l + 1; i++) TEMPLATE(T, poly_init)(h[i], ctx); /* Construct random elements of fq */ { TEMPLATE(T, poly_randtest_monic)(f, state, length, ctx); TEMPLATE(T, poly_reverse)(finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton)(finv, finv, f->length, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, poly_gen)(h[0], ctx); TEMPLATE(T, mat_init)(HH, n_sqrt(f->length - 1) + 1, f->length - 1, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(h[1], h[0], q, 0, f, finv, ctx); TEMPLATE(T, poly_precompute_matrix)(HH, h[1], f, finv, ctx); for (i = 2; i < l + 1; i++) TEMPLATE(T, poly_compose_mod_brent_kung_precomp_preinv)(h[i], h[i - 1], HH, f, finv, ctx); TEMPLATE(T, mat_clear)(HH, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, poly_gen)(h[0], ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(h[1], h[0], q, 0, f, finv, ctx); for (i = 2; i < l + 1; i++) TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(h[i], h[i-1], q, 0, f, finv, ctx); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 2; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; TEMPLATE(T, poly_clear)(f, ctx); TEMPLATE(T, poly_clear)(finv, ctx); for (i = 0; i < l + 1; i++) TEMPLATE(T, poly_clear)(h[i], ctx); TEMPLATE(T, ctx_clear)(ctx); } for (c = 0; c < nalgs; c++) { s[c] = s[c] / (double) reps; } fmpz_clear(p); fmpz_clear(q); flint_free(h); FLINT_TEST_CLEANUP(state); return s[0] > s[1]; } long a(fmpz_mat_t array, slong i, slong j) { return fmpz_get_si(fmpz_mat_entry(array, i, j)); } int file_exists(char *filename) { struct stat buffer; return (stat (filename, &buffer) == 0); } int init_array(fmpz_mat_t array, slong max_degree, slong max_bits, slong max_length, char* filename) { int bigger_length = 0; fmpz_mat_t old_array; slong i, j; FILE * old_file; if( file_exists(filename) ) { flint_printf(filename); /* old file exists */ fmpz_mat_init(old_array, max_degree, max_bits); old_file = fopen(filename, "r"); fmpz_mat_fread(old_file, old_array); fclose(old_file); if (fmpz_get_ui(fmpz_mat_entry(old_array, 0, 2)) < max_length) bigger_length = 1; } fmpz_mat_init(array, max_degree, max_bits); max_bits = FLINT_MAX(max_bits, 3); fmpz_set_si(fmpz_mat_entry(array, 0, 0), max_degree); fmpz_set_si(fmpz_mat_entry(array, 0, 1), max_bits); fmpz_set_si(fmpz_mat_entry(array, 0, 2), max_length); if( file_exists(filename) ) { for (i = 2; i < max_degree; i++) { for (j = 0; j < max_bits; j++) { fmpz_set(fmpz_mat_entry(array, i, j), fmpz_mat_entry(old_array, i, j)); } } fmpz_mat_clear(old_array); } fmpz_mat_print_pretty(array); return bigger_length; } void write_array(fmpz_mat_t array, char * filename) { FILE * tmp; tmp = fopen(filename, "w"); fmpz_mat_fprint(tmp, array); fclose(tmp); } int main(int argc, char** argv) { flint_bitcnt_t bits, max_bits, max_bits_used, max_bits_e; int is_hit, bigger_length; slong degree, length, max_degree, max_length, imin, imax, imid, diff; fmpz_mat_t array; char* filename; double s[nalgs]; max_degree = atol(argv[1]); max_bits = atol(argv[2]); max_length = atol(argv[3]); filename = argv[4]; bigger_length = init_array(array, max_degree, max_bits, max_length, filename); max_bits_used = 0; max_bits_e = 0; for (degree = 2; degree < max_degree; degree++) { flint_printf("Degree %d\n", degree); fflush(stdout); bits = 2; length = 3; while (bits < max_bits && (max_bits_e == 0 || bits < max_bits_e) ) { if (a(array, degree, bits) != 0 || (!bigger_length && bits >= a(array, degree, 0))) { bits += 1; continue; } #ifdef FQ_ZECH_VEC_NORM /* Don't make zech fields too big */ if (degree * bits >= 20) { bits += 1; continue; } #endif /* Set the initial state */ if (bits == 2 || bits == 3) { if (degree == 2) { length = 3; } else { if (a(array, degree - 1, bits) > length) length = a(array, degree - 1, bits); } diff = length; } else { length = a(array, degree, bits - 1); diff = length - a(array, degree, bits - 2); if (diff < degree) { diff = degree; } } /* Set the min */ imax = 0; imin = length; is_hit = get_timings(s, degree, bits, imin); while (is_hit != 0) { imax = imin; imin -= 1; if (imin < 3) { break; } is_hit = get_timings(s, degree, bits, imin); } if (imin < 3) { bits += 1; continue; } /* Set the max */ if (imax == 0) { imax = FLINT_MIN(imin + 2 * diff, max_length); is_hit = get_timings(s, degree, bits, imax); while (is_hit != 1) { flint_printf("Finding max, %d\n", diff); if (imax == max_length) { imax = max_length + 1; break; } imin = imax; imax += 2 * diff; imax = FLINT_MIN(imax, max_length); is_hit = get_timings(s, degree, bits, imax); } } if (imax > max_length) { max_bits_e = bits; fmpz_set_si(fmpz_mat_entry(array, degree, 0), bits); write_array(array, filename); break; } flint_printf("Min - Max: %d - %d\n", imin, imax); while (imin < imax) { imid = imin + ((imax - imin) / 2); if (imid >= imax) { flint_printf("Error in computing midpoint\n"); flint_abort(); } is_hit = get_timings(s, degree, bits, imid); if (is_hit) { imax = imid; } else { imin = imid + 1; } } length = imin; /* Set the array */ flint_printf("%d - %d %d\n", degree, bits, length); fmpz_set_si(fmpz_mat_entry(array, degree, bits), length); fmpz_set_si(fmpz_mat_entry(array, degree, 0), bits); if (degree == 2 && bits > max_bits_used) max_bits_used = bits + 1; fflush(stdout); write_array(array, filename); bits += 1; } } fmpz_mat_print_pretty(array); fmpz_mat_clear(array); return 0; } #endif flint-3.1.3/src/fq_poly_templates/profile/p-mullow.c000066400000000000000000000050551461254215100225360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include "profiler.h" #define nalgs 2 #define ncases 10 #define cpumin 2 int main(int argc, char** argv) { double s[nalgs]; int c, n, lenf, leng, len, ext, reps = 0; fmpz_t p, temp; TEMPLATE(T, poly_t) f, g, h; TEMPLATE(T, ctx_t) ctx; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); lenf = atol(argv[3]); leng = atol(argv[4]); len = atol(argv[5]); TEMPLATE(T, ctx_init)(ctx, p, ext, "a"); TEMPLATE(T, poly_init)(f, ctx); TEMPLATE(T, poly_init)(g, ctx); TEMPLATE(T, poly_init)(h, ctx); for (c = 0; c < nalgs; c++) { s[c] = 0.0; } for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; /* Construct random elements of fq */ { TEMPLATE(T, poly_randtest_monic)(f, state, lenf, ctx); TEMPLATE(T, poly_randtest_monic)(g, state, leng, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { TEMPLATE(T, poly_mullow_classical)(h, f, g, len, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { TEMPLATE(T, poly_mullow_KS)(h, f, g, len, ctx); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { flint_printf("%20f ", s[c] / (double) reps); fflush(stdout); } printf("\n"); TEMPLATE(T, poly_clear)(h, ctx); TEMPLATE(T, poly_clear)(f, ctx); TEMPLATE(T, poly_clear)(g, ctx); TEMPLATE(T, ctx_clear)(ctx); fmpz_clear(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } #endif flint-3.1.3/src/fq_poly_templates/profile/p-sqr.c000066400000000000000000000045121461254215100220210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include "profiler.h" #define nalgs 2 #define ncases 10 #define cpumin 2 int main(int argc, char** argv) { double s[nalgs]; int c, n, lenf, ext, reps = 0; fmpz_t p, temp; TEMPLATE(T, poly_t) f, h; TEMPLATE(T, ctx_t) ctx; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); lenf = atol(argv[3]); TEMPLATE(T, ctx_init)(ctx, p, ext, "a"); TEMPLATE(T, poly_init)(f, ctx); TEMPLATE(T, poly_init)(h, ctx); for (c = 0; c < nalgs; c++) { s[c] = 0.0; } for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; /* Construct random elements of fq */ { TEMPLATE(T, poly_randtest_monic)(f, state, lenf, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { TEMPLATE(T, poly_sqr_classical)(h, f, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { TEMPLATE(T, poly_sqr_KS)(h, f, ctx); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { flint_printf("%20f ", s[c] / (double) reps); fflush(stdout); } printf("\n"); TEMPLATE(T, poly_clear)(h, ctx); TEMPLATE(T, poly_clear)(f, ctx); TEMPLATE(T, ctx_clear)(ctx); fmpz_clear(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } #endif flint-3.1.3/src/fq_poly_templates/randtest.c000066400000000000000000000026331461254215100211450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_randtest) (TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; TEMPLATE(T, poly_fit_length) (f, len, ctx); for (i = 0; i < len; i++) { TEMPLATE(T, randtest) (f->coeffs + i, state, ctx); } _TEMPLATE(T, poly_set_length) (f, len, ctx); _TEMPLATE(T, poly_normalise) (f, ctx); } void TEMPLATE(T, poly_randtest_not_zero) (TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; if (len == 0) { flint_throw(FLINT_ERROR, "(%s): len = 0\n", __func__); } TEMPLATE(T, poly_randtest) (f, state, len, ctx); for (i = 0; (i < 10) && TEMPLATE(T, poly_is_zero) (f, ctx); i++) TEMPLATE(T, poly_randtest) (f, state, len, ctx); if (TEMPLATE(T, poly_is_zero) (f, ctx)) TEMPLATE(T, poly_one) (f, ctx); } #endif flint-3.1.3/src/fq_poly_templates/randtest_irreducible.c000066400000000000000000000047551461254215100235250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_randtest_irreducible) (TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) xq, xqi, x, g_i, finv; fmpz_t q; slong i, restart; /* Compute q */ #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) fmpz_init(q); fmpz_ui_pow_ui(q, TEMPLATE(T, ctx_prime)(ctx), TEMPLATE(T, ctx_degree)(ctx)); #else fmpz_init_set(q, TEMPLATE(T, ctx_prime)(ctx)); fmpz_pow_ui(q, q, TEMPLATE(T, ctx_degree)(ctx)); #endif TEMPLATE(T, poly_init) (x, ctx); TEMPLATE(T, poly_gen) (x, ctx); TEMPLATE(T, poly_init) (xq, ctx); TEMPLATE(T, poly_init) (xqi, ctx); TEMPLATE(T, poly_init) (g_i, ctx); TEMPLATE(T, poly_init) (finv, ctx); while (1) { restart = 0; /* Generate random monic polynomial of length len */ TEMPLATE(T, poly_randtest_monic) (f, state, len, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); /* Compute xq = x^q mod f */ TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (xq, x, q, f, finv, ctx); TEMPLATE(T, poly_set) (xqi, xq, ctx); for (i = 1; i <= (len - 1) / 2; i++) { TEMPLATE(T, poly_sub) (xqi, xqi, x, ctx); TEMPLATE(T, poly_gcd) (g_i, xqi, f, ctx); TEMPLATE(T, poly_add) (xqi, xqi, x, ctx); if (!TEMPLATE(T, poly_is_one) (g_i, ctx)) { restart = 1; break; } TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (xqi, xqi, xq, f, finv, ctx); } if (!restart) { break; } } TEMPLATE(T, poly_clear) (x, ctx); TEMPLATE(T, poly_clear) (xq, ctx); TEMPLATE(T, poly_clear) (xqi, ctx); TEMPLATE(T, poly_clear) (g_i, ctx); TEMPLATE(T, poly_clear) (finv, ctx); fmpz_clear(q); } #endif flint-3.1.3/src/fq_poly_templates/randtest_monic.c000066400000000000000000000017031461254215100223270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_randtest_monic) (TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; TEMPLATE(T, poly_fit_length) (f, len, ctx); for (i = 0; i < len - 1; i++) { TEMPLATE(T, randtest) (f->coeffs + i, state, ctx); } TEMPLATE(T, one) (f->coeffs + (len - 1), ctx); _TEMPLATE(T, poly_set_length) (f, len, ctx); _TEMPLATE(T, poly_normalise) (f, ctx); } #endif flint-3.1.3/src/fq_poly_templates/realloc.c000066400000000000000000000033451461254215100207430ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_realloc) (TEMPLATE(T, poly_t) poly, slong alloc, const TEMPLATE(T, ctx_t) ctx) { slong i; if (alloc == 0) /* Clear up, reinitialise */ { TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, poly_init) (poly, ctx); } else if (poly->alloc) /* Realloc */ { for (i = alloc; i < poly->alloc; i++) TEMPLATE(T, clear) (poly->coeffs + i, ctx); poly->coeffs = (TEMPLATE(T, struct) *) flint_realloc(poly->coeffs, alloc * sizeof(TEMPLATE(T, struct))); for (i = poly->alloc; i < alloc; i++) TEMPLATE(T, init) (poly->coeffs + i, ctx); poly->length = FLINT_MIN(poly->length, alloc); _TEMPLATE(T, poly_normalise) (poly, ctx); } else /* Nothing allocated already so do it now */ { poly->coeffs = (TEMPLATE(T, struct) *) flint_malloc(alloc * sizeof(TEMPLATE(T, struct))); for (i = 0; i < alloc; i++) TEMPLATE(T, init) (poly->coeffs + i, ctx); } poly->alloc = alloc; } #endif flint-3.1.3/src/fq_poly_templates/rem.c000066400000000000000000000031631461254215100201030ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_rem)(TEMPLATE(T, struct) *R, const TEMPLATE(T, struct) *A, slong lenA, const TEMPLATE(T, struct) *B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) *Q = _TEMPLATE(T, vec_init)(lenA - lenB + 1, ctx); if (lenA < lenB) { _TEMPLATE(T, vec_set)(R, A, lenA, ctx); _TEMPLATE(T, vec_zero)(R + lenA, lenB - 1 - lenA, ctx); } else { TEMPLATE(T, struct) *T = _TEMPLATE(T, vec_init)(lenA, ctx); _TEMPLATE(T, poly_divrem)(Q, T, A, lenA, B, lenB, invB, ctx); _TEMPLATE(T, vec_set)(R, T, lenB - 1, ctx); _TEMPLATE(T, vec_clear)(T, lenA, ctx); } _TEMPLATE(T, vec_clear)(Q, lenA - lenB + 1, ctx); } void TEMPLATE(T, poly_rem)(TEMPLATE(T, poly_t) R, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) Q; TEMPLATE(T, poly_init)(Q, ctx); TEMPLATE(T, poly_divrem)(Q, R, A, B, ctx); TEMPLATE(T, poly_clear)(Q, ctx); } #endif flint-3.1.3/src/fq_poly_templates/remove.c000066400000000000000000000022661461254215100206200ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" ulong TEMPLATE(T, poly_remove) (TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) g, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_t) q, r; ulong i = 0; TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); while (1) { if (f->length < g->length) break; TEMPLATE(T, poly_divrem) (q, r, f, g, ctx); if (r->length == 0) TEMPLATE(T, poly_swap) (q, f, ctx); else break; i++; } TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); return i; } #endif flint-3.1.3/src/fq_poly_templates/reverse.c000066400000000000000000000032501461254215100207700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_reverse) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, slong len, slong n, const TEMPLATE(T, ctx_t) ctx) { if (res == poly) { slong i; for (i = 0; i < n / 2; i++) { TEMPLATE(T, struct) t = res[i]; res[i] = res[n - 1 - i]; res[n - 1 - i] = t; } for (i = 0; i < n - len; i++) TEMPLATE(T, zero) (res + i, ctx); } else { slong i; for (i = 0; i < n - len; i++) TEMPLATE(T, zero) (res + i, ctx); for (i = 0; i < len; i++) TEMPLATE(T, set) (res + (n - len) + i, poly + (len - 1) - i, ctx); } } void TEMPLATE(T, poly_reverse) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, ctx_t) ctx) { slong len = FLINT_MIN(n, poly->length); if (len == 0) { TEMPLATE(T, poly_zero) (res, ctx); return; } TEMPLATE(T, poly_fit_length) (res, n, ctx); _TEMPLATE(T, poly_reverse) (res->coeffs, poly->coeffs, len, n, ctx); _TEMPLATE(T, poly_set_length) (res, n, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/scalar_addmul_fq.c000066400000000000000000000041351461254215100226010ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE3(T, poly_scalar_addmul, T) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, is_zero) (x, ctx)) return; if (TEMPLATE(T, is_one) (x, ctx)) { _TEMPLATE(T, poly_add) (rop, rop, len, op, len, ctx); } else { slong i; TEMPLATE(T, t) t; TEMPLATE(T, init) (t, ctx); for (i = 0; i < len; i++) { TEMPLATE(T, mul) (t, op + i, x, ctx); TEMPLATE(T, add) (rop + i, rop + i, t, ctx); } TEMPLATE(T, clear) (t, ctx); } } void TEMPLATE3(T, poly_scalar_addmul, T) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { if (! (TEMPLATE(T, is_zero) (x, ctx) || TEMPLATE(T, poly_is_zero) (op, ctx))) { TEMPLATE(T, poly_fit_length) (rop, op->length, ctx); if (op->length > rop->length) _TEMPLATE(T, vec_zero) (rop->coeffs + rop->length, op->length - rop->length, ctx); _TEMPLATE3(T, poly_scalar_addmul, T) (rop->coeffs, op->coeffs, op->length, x, ctx); _TEMPLATE(T, poly_set_length) (rop, FLINT_MAX(rop->length, op->length), ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/scalar_div_fq.c000066400000000000000000000033011461254215100221070ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, TEMPLATE(poly_scalar_div, T)) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) TEMPLATE(T, div) (rop + i, op + i, x, ctx); } void TEMPLATE(T, TEMPLATE(poly_scalar_div, T)) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, is_zero) (x, ctx)) { flint_throw(FLINT_ERROR, "Exception (fq_poly_scalar_div) Division by zero"); } if (TEMPLATE(T, poly_is_zero) (op, ctx)) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, op->length, ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_div, T)) (rop->coeffs, op->coeffs, op->length, x, ctx); _TEMPLATE(T, poly_set_length) (rop, op->length, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/scalar_mul_fq.c000066400000000000000000000031331461254215100221250ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) TEMPLATE(T, mul) (rop + i, op + i, x, ctx); } void TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, is_zero) (x, ctx) || TEMPLATE(T, poly_is_zero) (op, ctx)) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, op->length, ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (rop->coeffs, op->coeffs, op->length, x, ctx); _TEMPLATE(T, poly_set_length) (rop, op->length, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/scalar_submul_fq.c000066400000000000000000000041441461254215100226420ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE3(T, poly_scalar_submul, T) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, is_zero) (x, ctx)) return; if (TEMPLATE(T, is_one) (x, ctx)) { _TEMPLATE(T, poly_sub) (rop, rop, len, op, len, ctx); } else { slong i; TEMPLATE(T, t) t; TEMPLATE(T, init) (t, ctx); for (i = 0; i < len; i++) { TEMPLATE(T, mul) (t, op + i, x, ctx); TEMPLATE(T, sub) (rop + i, rop + i, t, ctx); } TEMPLATE(T, clear) (t, ctx); } } void TEMPLATE3(T, poly_scalar_submul, T) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { if (! (TEMPLATE(T, is_zero) (x, ctx) || TEMPLATE(T, poly_is_zero) (op, ctx))) { TEMPLATE(T, poly_fit_length) (rop, op->length, ctx); if (op->length > rop->length) _TEMPLATE(T, vec_zero) (rop->coeffs + rop->length, op->length - rop->length, ctx); _TEMPLATE3(T, poly_scalar_submul, T) (rop->coeffs, op->coeffs, op->length, x, ctx); _TEMPLATE(T, poly_set_length) (rop, FLINT_MAX(rop->length, op->length), ctx); _TEMPLATE(T, poly_normalise) (rop, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/set.c000066400000000000000000000023721461254215100201140ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_set) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) TEMPLATE(T, set) (rop + i, op + i, ctx); } void TEMPLATE(T, poly_set) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { if (rop != op) /* Aliasing is trivial */ { slong i, len = op->length; TEMPLATE(T, poly_fit_length) (rop, len, ctx); _TEMPLATE(T, poly_set_length) (rop, len, ctx); for (i = 0; i < len; i++) TEMPLATE(T, set) (rop->coeffs + i, op->coeffs + i, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/set_coeff.c000066400000000000000000000033361461254215100212570ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_set_coeff) (TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, is_zero) (x, ctx)) { if (n >= poly->length) return; TEMPLATE(T, zero) (poly->coeffs + n, ctx); if (n == poly->length - 1) /* only necessary when setting leading coefficient */ _TEMPLATE(T, poly_normalise) (poly, ctx); } else { slong i; TEMPLATE(T, poly_fit_length) (poly, n + 1, ctx); if (n + 1 > poly->length) /* Insert zeros if needed */ { for (i = poly->length; i < n; i++) TEMPLATE(T, zero) (poly->coeffs + i, ctx); poly->length = n + 1; } } TEMPLATE(T, set) (poly->coeffs + n, x, ctx); } void TEMPLATE(T, poly_set_coeff_fmpz)(TEMPLATE(T, poly_t) poly, slong n, const fmpz_t x, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_fit_length)(poly, n + 1, ctx); TEMPLATE(T, set_fmpz)(poly->coeffs + n, x, ctx); if (n + 1 > poly->length) { _TEMPLATE(T, poly_set_length)(poly, n + 1, ctx); } _TEMPLATE(T, poly_normalise)(poly, ctx); } #endif flint-3.1.3/src/fq_poly_templates/set_fmpz_mod_poly.c000066400000000000000000000015571461254215100230560ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_set_fmpz_mod_poly)(TEMPLATE(T, poly_t) rop, const fmpz_mod_poly_t op, const TEMPLATE(T, ctx_t) ctx) { slong i, len = op->length; TEMPLATE(T, poly_fit_length)(rop, len, ctx); _TEMPLATE(T, poly_set_length)(rop, len, ctx); for (i = 0; i < len; i++) TEMPLATE(T, set_fmpz)(rop->coeffs + i, op->coeffs + i, ctx); } #endif flint-3.1.3/src/fq_poly_templates/set_fq.c000066400000000000000000000016411461254215100206000ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, TEMPLATE(poly_set, T)) (TEMPLATE(T, poly_t) poly, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, is_zero) (c, ctx)) { TEMPLATE(T, poly_zero) (poly, ctx); } else { TEMPLATE(T, poly_fit_length) (poly, 1, ctx); TEMPLATE(T, set) (poly->coeffs + 0, c, ctx); _TEMPLATE(T, poly_set_length) (poly, 1, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/set_length.c000066400000000000000000000014561461254215100214570ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_set_length)(TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx) { if (poly->length > len) { slong i; for (i = len; i < poly->length; i++) TEMPLATE(T, zero)(poly->coeffs + i, ctx); } poly->length = len; } #endif flint-3.1.3/src/fq_poly_templates/set_nmod_poly.c000066400000000000000000000015341461254215100221730ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_set_nmod_poly)(TEMPLATE(T, poly_t) rop, const nmod_poly_t op, const TEMPLATE(T, ctx_t) ctx) { slong i, len = op->length; TEMPLATE(T, poly_fit_length)(rop, len, ctx); _TEMPLATE(T, poly_set_length)(rop, len, ctx); for (i = 0; i < len; i++) TEMPLATE(T, set_ui)(rop->coeffs + i, op->coeffs[i], ctx); } #endif flint-3.1.3/src/fq_poly_templates/set_trunc.c000066400000000000000000000021571461254215100213300ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_set_trunc) (TEMPLATE(T, poly_t) poly1, TEMPLATE(T, poly_t) poly2, slong len, const TEMPLATE(T, ctx_t) ctx) { if (poly1 == poly2) TEMPLATE(T, poly_truncate) (poly1, len, ctx); else if (len >= poly2->length) TEMPLATE(T, poly_set) (poly1, poly2, ctx); else { slong i; TEMPLATE(T, poly_fit_length) (poly1, len, ctx); for (i = 0; i < len; i++) TEMPLATE(T, set) (poly1->coeffs + i, poly2->coeffs + i, ctx); _TEMPLATE(T, poly_set_length) (poly1, len, ctx); _TEMPLATE(T, poly_normalise) (poly1, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/shift_left.c000066400000000000000000000032171461254215100214470ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_shift_left) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, slong n, const TEMPLATE(T, ctx_t) ctx) { slong i; if (rop != op) { for (i = len; i--;) TEMPLATE(T, set) (rop + n + i, op + i, ctx); } else { for (i = len; i--;) TEMPLATE(T, swap) (rop + n + i, rop + i, ctx); } for (i = 0; i < n; i++) TEMPLATE(T, zero) (rop + i, ctx); } void TEMPLATE(T, poly_shift_left) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, slong n, const TEMPLATE(T, ctx_t) ctx) { if (n == 0) { TEMPLATE(T, poly_set) (rop, op, ctx); } else if (TEMPLATE(T, poly_is_zero) (op, ctx)) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, op->length + n, ctx); _TEMPLATE(T, poly_shift_left) (rop->coeffs, op->coeffs, op->length, n, ctx); _TEMPLATE(T, poly_set_length) (rop, op->length + n, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/shift_right.c000066400000000000000000000031201461254215100216230ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_shift_right) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, slong n, const TEMPLATE(T, ctx_t) ctx) { slong i; if (rop != op) { for (i = 0; i < len - n; i++) TEMPLATE(T, set) (rop + i, op + n + i, ctx); } else { for (i = 0; i < len - n; i++) TEMPLATE(T, swap) (rop + i, rop + n + i, ctx); } } void TEMPLATE(T, poly_shift_right) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, slong n, const TEMPLATE(T, ctx_t) ctx) { if (n == 0) { TEMPLATE(T, poly_set) (rop, op, ctx); } else if (op->length <= n) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, op->length - n, ctx); _TEMPLATE(T, poly_shift_right) (rop->coeffs, op->coeffs, op->length, n, ctx); _TEMPLATE(T, poly_set_length) (rop, op->length - n, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/sqr.c000066400000000000000000000033321461254215100201230ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_sqr) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { if (len < TEMPLATE(CAP_T, SQR_CLASSICAL_CUTOFF)) { _TEMPLATE(T, poly_sqr_classical) (rop, op, len, ctx); } #ifdef USE_SQR_REORDER else if (TEMPLATE(T, ctx_degree) (ctx) < 4) { _TEMPLATE(T, poly_sqr_reorder) (rop, op, len, ctx); } #endif else { _TEMPLATE(T, poly_sqr_KS) (rop, op, len, ctx); } } void TEMPLATE(T, poly_sqr) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { const slong rlen = 2 * op->length - 1; if (op->length == 0) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (rop == op) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, rlen, ctx); _TEMPLATE(T, poly_sqr) (t->coeffs, op->coeffs, op->length, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, rlen, ctx); _TEMPLATE(T, poly_sqr) (rop->coeffs, op->coeffs, op->length, ctx); } _TEMPLATE(T, poly_set_length) (rop, rlen, ctx); } #endif flint-3.1.3/src/fq_poly_templates/sqr_KS.c000066400000000000000000000043121461254215100205170ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "fmpz_poly.h" void _TEMPLATE(T, poly_sqr_KS) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { const slong in_len = len; const slong d = TEMPLATE(T, ctx_degree) (ctx); slong bits, i; fmpz *f, *g; TEMPLATE(CAP_T, VEC_NORM) (op, len, ctx); if (!len) { if (2 * in_len - 1 > 0) _TEMPLATE(T, poly_zero) (rop, 2 * in_len - 1, ctx); return; } bits = FLINT_BIT_COUNT(d) + FLINT_BIT_COUNT(len); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) bits += 2 * FLINT_BIT_COUNT(TEMPLATE(T, ctx_prime)(ctx)); #else bits += 2 * fmpz_bits(TEMPLATE(T, ctx_prime)(ctx)); #endif f = _fmpz_vec_init((2 * len - 1) + len); g = f + (2 * len - 1); for (i = 0; i < len; i++) { TEMPLATE(T, bit_pack) (g + i, op + i, bits, ctx); } _fmpz_poly_sqr(f, g, len); for (i = 0; i < 2 * len - 1; i++) { TEMPLATE(T, bit_unpack) (rop + i, f + i, bits, ctx); } _TEMPLATE(T, poly_zero) (rop + (2 * len - 1), 2 * (in_len - len), ctx); _fmpz_vec_clear(f, (2 * len - 1) + len); } void TEMPLATE(T, poly_sqr_KS) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { const slong len = 2 * op->length - 1; if (op->length == 0) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len, ctx); _TEMPLATE(T, poly_sqr_KS) (rop->coeffs, op->coeffs, op->length, ctx); _TEMPLATE(T, poly_set_length) (rop, len, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/sqr_classical.c000066400000000000000000000047071461254215100221500ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_sqr_classical) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { if (len == 1) { TEMPLATE(T, mul) (rop, op, op, ctx); } else { slong i; TEMPLATE(T, t) t; TEMPLATE(T, init) (t, ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (rop, op, len, op, ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (rop + len, op + 1, len - 1, op + len - 1, ctx); for (i = 1; i < len - 1; i++) _TEMPLATE(T, TEMPLATE(poly_scalar_addmul, T)) (rop + i + 1, op + 1, i - 1, op + i, ctx); for (i = 1; i < 2 * len - 2; i++) TEMPLATE(T, add) (rop + i, rop + i, rop + i, ctx); for (i = 1; i < len - 1; i++) { TEMPLATE(T, sqr) (t, op + i, ctx); TEMPLATE(T, add) (rop + 2 * i, rop + 2 * i, t, ctx); } TEMPLATE(T, clear) (t, ctx); } } void TEMPLATE(T, poly_sqr_classical) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { const slong len = 2 * op->length - 1; if (op->length == 0) { TEMPLATE(T, poly_zero) (rop, ctx); return; } if (rop == op) { TEMPLATE(T, poly_t) t; TEMPLATE(T, poly_init2) (t, len, ctx); _TEMPLATE(T, poly_sqr_classical) (t->coeffs, op->coeffs, op->length, ctx); TEMPLATE(T, poly_swap) (rop, t, ctx); TEMPLATE(T, poly_clear) (t, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len, ctx); _TEMPLATE(T, poly_sqr_classical) (rop->coeffs, op->coeffs, op->length, ctx); } _TEMPLATE(T, poly_set_length) (rop, len, ctx); } #endif flint-3.1.3/src/fq_poly_templates/sqr_reorder.c000066400000000000000000000130711461254215100216460ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T /* Inclusion of both mul_reorder.c and sqr_reorder.c can screw things up by * multiple definitions. If changes are made to this file, make sure that * proper changes are made to the other file as well. */ #define SQR_REORDER_C #include "templates.h" /* Include routines for vectors over \code{fmpz_poly_struct}, for use in the classical multiplication routine in the $X$-direction. */ #ifndef MUL_REORDER_C static fmpz_poly_struct * __vec_init(slong len) { slong i; fmpz_poly_struct *v; v = flint_malloc(len * sizeof(fmpz_poly_struct)); for (i = 0; i < len; i++) fmpz_poly_init(v + i); return v; } static fmpz_poly_struct * __vec_init2(slong len, slong n) { slong i; fmpz_poly_struct *v; v = flint_malloc(len * sizeof(fmpz_poly_struct)); for (i = 0; i < len; i++) fmpz_poly_init2(v + i, n); return v; } static void __vec_clear(fmpz_poly_struct * v, slong len) { slong i; for (i = 0; i < len; i++) fmpz_poly_clear(v + i); flint_free(v); } static void __scalar_addmul(fmpz_poly_struct * rop, const fmpz_poly_struct * op, slong len, const fmpz_poly_t x) { slong i; if (fmpz_poly_is_zero(x)) { return; } else if (fmpz_poly_is_one(x)) { for (i = 0; i < len; i++) fmpz_poly_add(rop + i, rop + i, op + i); } else { fmpz_poly_t t; fmpz_poly_init(t); for (i = 0; i < len; i++) { fmpz_poly_mul(t, op + i, x); fmpz_poly_add(rop + i, rop + i, t); } fmpz_poly_clear(t); } } static void __scalar_mul(fmpz_poly_struct * rop, const fmpz_poly_struct * op, slong len, const fmpz_poly_t x) { slong i; if (fmpz_poly_is_zero(x)) { for (i = 0; i < len; i++) fmpz_poly_zero(rop + i); } else if (fmpz_poly_is_one(x)) { for (i = 0; i < len; i++) fmpz_poly_set(rop + i, op + i); } else { for (i = 0; i < len; i++) fmpz_poly_mul(rop + i, op + i, x); } } #endif static void __sqr(fmpz_poly_struct * rop, fmpz_poly_struct * op, slong len) { if (len == 1) { fmpz_poly_sqr(rop, op); } else { slong i; fmpz_poly_t t; fmpz_poly_init(t); __scalar_mul(rop, op, len, op); __scalar_mul(rop + len, op + 1, len - 1, op + len - 1); for (i = 1; i < len - 1; i++) __scalar_addmul(rop + i + 1, op + 1, i - 1, op + i); for (i = 1; i < 2 * len - 2; i++) fmpz_poly_add(rop + i, rop + i, rop + i); for (i = 1; i < len - 1; i++) { fmpz_poly_sqr(t, op + i); fmpz_poly_add(rop + 2 * i, rop + 2 * i, t); } fmpz_poly_clear(t); } } void _TEMPLATE(T, poly_sqr_reorder) (TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op, slong len, const TEMPLATE(T, ctx_t) ctx) { const slong d = TEMPLATE(T, ctx_degree) (ctx); fmpz_poly_struct *f, *g; slong i, j, k, lenF; f = __vec_init(2 * d - 1); g = __vec_init2(d, len); /* Convert (op, len) to (g, d) */ for (i = 0; i < len; i++) for (j = 0; j < fmpz_poly_length(op + i); j++) fmpz_set((g + j)->coeffs + i, (op + i)->coeffs + j); for (j = 0; j < d; j++) { _fmpz_poly_set_length(g + j, len); _fmpz_poly_normalise(g + j); } __sqr(f, g, d); /* Normalise (f, len) */ lenF = 2 * d - 1; while ((lenF) && fmpz_poly_is_zero(f + (lenF - 1))) lenF--; /* Reduce (f, j) using polynomial operations */ if (lenF > d) { for (i = lenF - 1; i >= d; i--) { for (k = ctx->len - 2; k >= 0; k--) { fmpz_poly_scalar_submul_fmpz(f + ctx->j[k] + i - d, f + i, ctx->a + k); } fmpz_poly_zero(f + i); } } for (j = 0; j < FLINT_MIN(d, lenF); j++) fmpz_poly_scalar_mod_fmpz(f + j, f + j, TEMPLATE(T, ctx_prime) (ctx)); /* Convert (f, d) to (rop, 2 * len - 1) */ for (i = 0; i < 2 * len - 1; i++) { fmpz_poly_fit_length(rop + i, d); _fmpz_vec_zero((rop + i)->coeffs, d); } for (j = 0; j < d; j++) for (i = 0; i < fmpz_poly_length(f + j); i++) fmpz_set((rop + i)->coeffs + j, (f + j)->coeffs + i); for (i = 0; i < 2 * len - 1; i++) { _fmpz_poly_set_length(rop + i, d); _fmpz_poly_normalise(rop + i); } __vec_clear(f, 2 * d - 1); __vec_clear(g, d); } void TEMPLATE(T, poly_sqr_reorder) (TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx) { const slong len = 2 * op->length - 1; if (op->length == 0) { TEMPLATE(T, poly_zero) (rop, ctx); } else { TEMPLATE(T, poly_fit_length) (rop, len, ctx); _TEMPLATE(T, poly_sqr_reorder) (rop->coeffs, op->coeffs, op->length, ctx); _TEMPLATE(T, poly_set_length) (rop, len, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/sqrt.c000066400000000000000000000071171461254215100203140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2021, 2022 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" static inline int _TEMPLATE(T, poly_sqrt_2)(TEMPLATE(T, struct) * s, const TEMPLATE(T, struct) * p, slong len, TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 1; i < len; i += 2) if (!TEMPLATE(T, is_zero)(p + i, ctx)) return 0; for (i = 0; i < len; i += 2) TEMPLATE(T, sqrt)(s + i / 2, p + i, ctx); return 1; } int _TEMPLATE(T, poly_sqrt)(TEMPLATE(T, struct) * s, const TEMPLATE(T, struct) * p, slong len, TEMPLATE(T, ctx_t) ctx) { slong slen, i; int result; TEMPLATE(T, struct) * t; TEMPLATE(T, t) c, d; if (len % 2 == 0) return len == 0; #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) if (TEMPLATE(T, ctx_prime)(ctx) == 2) #else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0) #endif return _TEMPLATE(T, poly_sqrt_2)(s, p, len, ctx); /* valuation must be even, and then can be reduced to 0 */ while (TEMPLATE(T, is_zero)(p + 0, ctx)) { if (!TEMPLATE(T, is_zero)(p + 1, ctx)) return 0; TEMPLATE(T, zero)(s + 0, ctx); p += 2; len -= 2; s++; } TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(d, ctx); TEMPLATE(T, set)(d, p + 0, ctx); TEMPLATE(T, set)(c, d, ctx); if (!TEMPLATE(T, is_one)(c, ctx)) { if (!TEMPLATE(T, sqrt)(c, c, ctx)) { result = 0; goto cleanup; } } if (len == 1) { TEMPLATE(T, set)(s + 0, c, ctx); result = 1; goto cleanup; } slen = len / 2 + 1; t = _TEMPLATE(T, vec_init)(len, ctx); if (TEMPLATE(T, is_one)(c, ctx)) _TEMPLATE(T, poly_sqrt_series)(s, p, slen, ctx); else { TEMPLATE(T, inv)(d, d, ctx); _TEMPLATE3(T, vec_scalar_mul, T)(t, p, slen, d, ctx); _TEMPLATE(T, poly_sqrt_series)(s, t, slen, ctx); } if (!TEMPLATE(T, is_one)(c, ctx)) _TEMPLATE3(T, vec_scalar_mul, T)(s, s, slen, c, ctx); _TEMPLATE(T, poly_mulhigh)(t, s, slen, s, slen, slen, ctx); for (i = 0; i < slen; i++) TEMPLATE(T, zero)(t + i, ctx); result = _TEMPLATE(T, vec_equal)(t + slen, p + slen, len - slen, ctx); _TEMPLATE(T, vec_clear)(t, len, ctx); cleanup: TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, clear)(d, ctx); return result; } int TEMPLATE(T, poly_sqrt)(TEMPLATE(T, poly_t) b, const TEMPLATE(T, poly_t) a, TEMPLATE(T, ctx_t) ctx) { slong blen, len = a->length; int result; if (len % 2 == 0) { TEMPLATE(T, poly_zero)(b, ctx); return len == 0; } if (b == a) { TEMPLATE(T, poly_t) tmp; TEMPLATE(T, poly_init)(tmp, ctx); result = TEMPLATE(T, poly_sqrt)(tmp, a, ctx); TEMPLATE(T, poly_swap)(b, tmp, ctx); TEMPLATE(T, poly_clear)(tmp, ctx); return result; } blen = len / 2 + 1; TEMPLATE(T, poly_fit_length)(b, blen, ctx); result = _TEMPLATE(T, poly_sqrt)(b->coeffs, a->coeffs, len, ctx); if (!result) blen = 0; _TEMPLATE(T, poly_set_length)(b, blen, ctx); _TEMPLATE(T, poly_normalise)(b, ctx); return result; } #endif flint-3.1.3/src/fq_poly_templates/sqrt_series.c000066400000000000000000000040671461254215100216670ustar00rootroot00000000000000/* Copyright (C) 2011, 2021, 2022 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_sqrt_series)(TEMPLATE(T, struct) * g, const TEMPLATE(T, struct) * h, slong n, TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * t = _TEMPLATE(T, vec_init)(n, ctx); _TEMPLATE(T, poly_invsqrt_series)(t, h, n, ctx); _TEMPLATE(T, poly_mullow)(g, t, n, h, n, n, ctx); _TEMPLATE(T, vec_clear)(t, n, ctx); } void TEMPLATE(T, poly_sqrt_series)(TEMPLATE(T, poly_t) g, const TEMPLATE(T, poly_t) h, slong n, TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, struct) * g_coeffs; TEMPLATE(T, struct) * h_coeffs; TEMPLATE(T, poly_t) t1; slong hlen; hlen = h->length; if (n == 0) { flint_throw(FLINT_ERROR, "Exception (fq_poly_sqrt_series). Division by zero.\n"); } if (h->length == 0 || !TEMPLATE(T, is_one)(h->coeffs + 0, ctx)) { flint_throw(FLINT_ERROR, "Exception (fq_poly_sqrt_series). Requires constant term 1.\n"); } if (hlen < n) { h_coeffs = _TEMPLATE(T, vec_init)(n, ctx); _TEMPLATE(T, vec_set)(h_coeffs, h->coeffs, hlen, ctx); } else h_coeffs = h->coeffs; if (h == g && hlen >= n) { TEMPLATE(T, poly_init2)(t1, n, ctx); g_coeffs = t1->coeffs; } else { TEMPLATE(T, poly_fit_length)(g, n, ctx); g_coeffs = g->coeffs; } _TEMPLATE(T, poly_sqrt_series)(g_coeffs, h_coeffs, n, ctx); if (h == g && hlen >= n) { TEMPLATE(T, poly_swap)(g, t1, ctx); TEMPLATE(T, poly_clear)(t1, ctx); } g->length = n; if (hlen < n) _TEMPLATE(T, vec_clear)(h_coeffs, n, ctx); _TEMPLATE(T, poly_normalise)(g, ctx); } #endif flint-3.1.3/src/fq_poly_templates/sub.c000066400000000000000000000031521461254215100201070ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_sub) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly1, slong len1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, ctx_t) ctx) { const slong min = FLINT_MIN(len1, len2); slong i; for (i = 0; i < min; i++) TEMPLATE(T, sub) (res + i, poly1 + i, poly2 + i, ctx); if (poly1 != res) for (i = min; i < len1; i++) TEMPLATE(T, set) (res + i, poly1 + i, ctx); for (i = min; i < len2; i++) TEMPLATE(T, neg) (res + i, poly2 + i, ctx); } void TEMPLATE(T, poly_sub) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, ctx_t) ctx) { const slong max = FLINT_MAX(poly1->length, poly2->length); TEMPLATE(T, poly_fit_length) (res, max, ctx); _TEMPLATE(T, poly_sub) (res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _TEMPLATE(T, poly_set_length) (res, max, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/sub_series.c000066400000000000000000000022771461254215100214700ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_sub_series) (TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, slong n, const TEMPLATE(T, ctx_t) ctx) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); TEMPLATE(T, poly_fit_length) (res, max, ctx); _TEMPLATE(T, poly_sub) (res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); _TEMPLATE(T, poly_set_length) (res, max, ctx); _TEMPLATE(T, poly_normalise) (res, ctx); } #endif flint-3.1.3/src/fq_poly_templates/swap.c000066400000000000000000000012701461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_swap) (TEMPLATE(T, poly_t) op1, TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx) { FLINT_SWAP(TEMPLATE(T, poly_struct), *op1, *op2); } #endif flint-3.1.3/src/fq_poly_templates/test/000077500000000000000000000000001461254215100201305ustar00rootroot00000000000000flint-3.1.3/src/fq_poly_templates/test/t-add.c000066400000000000000000000166121461254215100212730ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_add, state) { int i, result; /* Check aliasing: a = a + b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_add) (c, a, b, ctx); TEMPLATE(T, poly_add) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a + b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_add) (c, a, b, ctx); TEMPLATE(T, poly_add) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a + a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_add) (c, a, a, ctx); TEMPLATE(T, poly_add) (a, a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a + b == b + a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, e; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_add) (c, a, b, ctx); TEMPLATE(T, poly_add) (e, b, a, ctx); result = (TEMPLATE(T, poly_equal) (e, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that (a + b) + c == a + (b + c) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, lhs, rhs; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (lhs, ctx); TEMPLATE(T, poly_init) (rhs, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_randtest) (c, state, len, ctx); TEMPLATE(T, poly_add) (lhs, a, b, ctx); TEMPLATE(T, poly_add) (lhs, c, lhs, ctx); TEMPLATE(T, poly_add) (rhs, b, c, ctx); TEMPLATE(T, poly_add) (rhs, a, rhs, ctx); result = (TEMPLATE(T, poly_equal) (lhs, rhs, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (lhs, ctx); TEMPLATE(T, poly_clear) (rhs, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-add_series.c000066400000000000000000000141521461254215100226420ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_add_series, state) { int i, result; /* Check aliasing: a = a + b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len, n; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_add_series) (c, a, b, n, ctx); TEMPLATE(T, poly_add_series) (a, a, b, n, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a + b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong n, len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_add_series) (c, a, b, n, ctx); TEMPLATE(T, poly_add_series) (b, a, b, n, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a + a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong n, len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_add_series) (c, a, a, n, ctx); TEMPLATE(T, poly_add_series) (a, a, a, n, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that truncate(a + b, n) = add_series(a, b, n) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong n, len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_add_series) (c, a, b, n, ctx); TEMPLATE(T, poly_add) (d, a, b, ctx); TEMPLATE(T, poly_truncate) (d, n, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-compose.c000066400000000000000000000121621461254215100222040ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_compose, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, g, h; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (h, ctx); TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (g, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_compose) (h, f, g, ctx); TEMPLATE(T, poly_compose) (f, f, g, ctx); result = (TEMPLATE(T, poly_equal) (f, h, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("f = "), TEMPLATE(T, poly_print_pretty) (f, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); flint_printf("h = "), TEMPLATE(T, poly_print_pretty) (h, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (h, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of the second argument */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, g, h; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (h, ctx); TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (g, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_compose) (h, f, g, ctx); TEMPLATE(T, poly_compose) (g, f, g, ctx); result = (TEMPLATE(T, poly_equal) (g, h, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("f = "), TEMPLATE(T, poly_print_pretty) (f, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); flint_printf("h = "), TEMPLATE(T, poly_print_pretty) (h, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (h, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare with the naive method */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, g, h, s, t; slong k; TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (h, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (g, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (h, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_one) (t, ctx); for (k = 0; k < TEMPLATE(T, poly_length) (g, ctx); k++) { TEMPLATE(T, TEMPLATE(poly_scalar_addmul, T)) (s, t, g->coeffs + k, ctx); TEMPLATE(T, poly_mul) (t, t, h, ctx); } TEMPLATE(T, poly_compose) (f, g, h, ctx); result = (TEMPLATE(T, poly_equal) (f, s, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("f = "), TEMPLATE(T, poly_print_pretty) (f, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); flint_printf("h = "), TEMPLATE(T, poly_print_pretty) (h, "X", ctx), flint_printf("\n"); flint_printf("s = "), TEMPLATE(T, poly_print_pretty) (s, "X", ctx), flint_printf("\n"); flint_printf("t = "), TEMPLATE(T, poly_print_pretty) (t, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (h, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-compose_mod.c000066400000000000000000000163001461254215100230410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_compose_mod, state) { int i; for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d, e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod) (d, a, b, c, ctx); TEMPLATE(T, poly_compose) (e, a, b, ctx); TEMPLATE(T, poly_rem) (e, e, c, ctx); if (!TEMPLATE(T, poly_equal) (d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); flint_printf("e:\n"); TEMPLATE(T, poly_print) (e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod) (a, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod) (b, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod) (c, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-compose_mod_brent_kung.c000066400000000000000000000167201461254215100252650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_compose_mod_brent_kung, state) { int i; for (i = 0; i < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d, e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (d, a, b, c, ctx); TEMPLATE(T, poly_compose) (e, a, b, ctx); TEMPLATE(T, poly_rem) (e, e, c, ctx); if (!TEMPLATE(T, poly_equal) (d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); flint_printf("e:\n"); TEMPLATE(T, poly_print) (e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (a, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (b, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung) (c, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000215771461254215100266560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_compose_mod_brent_kung_preinv, state) { int i; for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d, e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose) (e, a, b, ctx); TEMPLATE(T, poly_rem) (e, e, c, ctx); if (!TEMPLATE(T, poly_equal) (d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); flint_printf("e:\n"); TEMPLATE(T, poly_print) (e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (a, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (b, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_brent_kung_preinv) (c, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-compose_mod_horner.c000066400000000000000000000163701461254215100244250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_compose_mod_horner, state) { int i; for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d, e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod_horner) (d, a, b, c, ctx); TEMPLATE(T, poly_compose) (e, a, b, ctx); TEMPLATE(T, poly_rem) (e, e, c, ctx); if (!TEMPLATE(T, poly_equal) (d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); flint_printf("e:\n"); TEMPLATE(T, poly_print) (e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod_horner) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod_horner) (a, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod_horner) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod_horner) (b, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_compose_mod_horner) (d, a, b, c, ctx); TEMPLATE(T, poly_compose_mod_horner) (c, a, b, c, ctx); if (!TEMPLATE(T, poly_equal) (d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-compose_mod_horner_preinv.c000066400000000000000000000206561461254215100260120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_compose_mod_horner_preinv, state) { int i; for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d, e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose) (e, a, b, ctx); TEMPLATE(T, poly_rem) (e, e, c, ctx); if (!TEMPLATE(T, poly_equal) (d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); flint_printf("e:\n"); TEMPLATE(T, poly_print) (e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (a, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (b, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_horner_preinv) (c, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-compose_mod_preinv.c000066400000000000000000000206301461254215100244250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_compose_mod_preinv, state) { int i; for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d, e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose) (e, a, b, ctx); TEMPLATE(T, poly_rem) (e, e, c, ctx); if (!TEMPLATE(T, poly_equal) (d, e, ctx)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); flint_printf("e:\n"); TEMPLATE(T, poly_print) (e, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_preinv) (a, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, a, ctx)) { flint_printf("FAIL (aliasing a):\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_preinv) (b, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, b, ctx)) { flint_printf("FAIL (aliasing b)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Test aliasing of res and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (cinv, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (c, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (cinv, c, c->length, ctx); TEMPLATE(T, poly_inv_series_newton) (cinv, cinv, c->length, ctx); TEMPLATE(T, poly_rem) (a, a, c, ctx); TEMPLATE(T, poly_compose_mod_preinv) (d, a, b, c, cinv, ctx); TEMPLATE(T, poly_compose_mod_preinv) (c, a, b, c, cinv, ctx); if (!TEMPLATE(T, poly_equal) (d, c, ctx)) { flint_printf("FAIL (aliasing c)\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx); flint_printf("\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx); flint_printf("\n"); flint_printf("c:\n"); TEMPLATE(T, poly_print) (c, ctx); flint_printf("\n"); flint_printf("d:\n"); TEMPLATE(T, poly_print) (d, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (cinv, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-deflate.c000066400000000000000000000074751461254215100221560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_deflate, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { TEMPLATE(T, poly_t) poly1, poly2, poly3; TEMPLATE(T, ctx_t) ctx; ulong infl1, infl, deflation; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly2, ctx); TEMPLATE(T, poly_init) (poly3, ctx); TEMPLATE(T, poly_randtest) (poly1, state, n_randint(state, 15), ctx); if (TEMPLATE(T, poly_length) (poly1, ctx) <= 1) { if (TEMPLATE(T, poly_deflation) (poly1, ctx) != TEMPLATE(T, poly_length) (poly1, ctx)) { flint_printf ("FAIL: wrong deflation for constant polynomial\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_deflate) (poly2, poly1, n_randint(state, 5) + 1, ctx); if (!TEMPLATE(T, poly_equal) (poly2, poly1, ctx)) { flint_printf ("FAIL: constant polynomial changed on deflation\n"); fflush(stdout); flint_abort(); } } else { infl = n_randint(state, 13) + 1; infl1 = TEMPLATE(T, poly_deflation) (poly1, ctx); TEMPLATE(T, poly_inflate) (poly2, poly1, infl, ctx); deflation = TEMPLATE(T, poly_deflation) (poly2, ctx); if (deflation != infl * infl1) { flint_printf("FAIL: deflation = %wu, inflation: %wu, %wu\n", deflation, infl, infl1); flint_printf("poly1:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n\n"); flint_printf("poly2:\n"); TEMPLATE(T, poly_print) (poly2, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_deflate) (poly3, poly2, infl, ctx); if (!TEMPLATE(T, poly_equal) (poly3, poly1, ctx)) { flint_printf("FAIL: deflation = %wu, inflation: %wu, %wu\n", deflation, infl, infl1); flint_printf("Deflated polynomial not equal to input:\n"); flint_printf("poly1:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n\n"); flint_printf("poly2:\n"); TEMPLATE(T, poly_print) (poly2, ctx); flint_printf("\n\n"); flint_printf("poly3:\n"); TEMPLATE(T, poly_print) (poly3, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_deflate) (poly2, poly2, infl, ctx); if (!TEMPLATE(T, poly_equal) (poly3, poly2, ctx)) { flint_printf("FAIL: aliasing\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, poly_clear) (poly3, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-derivative.c000066400000000000000000000125701461254215100227040ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_derivative, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_set) (b, a, ctx); TEMPLATE(T, poly_derivative) (c, b, ctx); TEMPLATE(T, poly_derivative) (b, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check constants have derivative zero */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 2), ctx); TEMPLATE(T, poly_derivative) (b, a, ctx); result = (TEMPLATE(T, poly_is_zero) (b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check (f g)' == f' g + f g' */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d, lhs, rhs; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (lhs, ctx); TEMPLATE(T, poly_init) (rhs, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_mul) (lhs, a, b, ctx); TEMPLATE(T, poly_derivative) (lhs, lhs, ctx); TEMPLATE(T, poly_derivative) (c, a, ctx); TEMPLATE(T, poly_derivative) (d, b, ctx); TEMPLATE(T, poly_mul) (c, c, b, ctx); TEMPLATE(T, poly_mul) (d, a, d, ctx); TEMPLATE(T, poly_add) (rhs, c, d, ctx); result = (TEMPLATE(T, poly_equal) (lhs, rhs, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); flint_printf("lhs = "), TEMPLATE(T, poly_print_pretty) (lhs, "X", ctx), flint_printf("\n"); flint_printf("rhs = "), TEMPLATE(T, poly_print_pretty) (rhs, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (lhs, ctx); TEMPLATE(T, poly_clear) (rhs, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-div.c000066400000000000000000000122521461254215100213210ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2009 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_div, state) { int i, result; /* Compare to divrem */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, q2, r2; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (q2, ctx); TEMPLATE(T, poly_init) (r2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 100) + 1, ctx); TEMPLATE(T, poly_div) (q, a, b, ctx); TEMPLATE(T, poly_divrem) (q2, r2, a, b, ctx); result = (TEMPLATE(T, poly_equal) (q, q2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("ctx = "), TEMPLATE(T, ctx_print) (ctx), flint_printf("\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b = "), TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("q = "), TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); flint_printf("q2 = "), TEMPLATE(T, poly_print) (q2, ctx), flint_printf("\n\n"); flint_printf("r2 = "), TEMPLATE(T, poly_print) (r2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (q2, ctx); TEMPLATE(T, poly_clear) (r2, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Alias a and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 100) + 1, ctx); TEMPLATE(T, poly_div) (q, a, b, ctx); TEMPLATE(T, poly_div) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (q, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("ctx = "), TEMPLATE(T, ctx_print) (ctx), flint_printf("\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b = "), TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("q = "), TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Alias b and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 100) + 1, ctx); TEMPLATE(T, poly_div) (q, a, b, ctx); TEMPLATE(T, poly_div) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (q, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("ctx = "), TEMPLATE(T, ctx_print) (ctx), flint_printf("\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b = "), TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("q = "), TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-div_newton_n_preinv.c000066400000000000000000000162301461254215100246130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_div_newton_n_preinv, state) { int i, result; /* Check result of divrem */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r, test; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_init) (test, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 40), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 40), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_div_newton_n_preinv) (q, a, b, binv, ctx); TEMPLATE(T, poly_divrem) (test, r, a, b, ctx); result = (TEMPLATE(T, poly_equal) (q, test, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (test, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (test, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of a and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 40), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 40), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_div_newton_n_preinv) (q, a, b, binv, ctx); TEMPLATE(T, poly_div_newton_n_preinv) (a, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (a, q, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of b and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 40), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 40), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_div_newton_n_preinv) (q, a, b, binv, ctx); TEMPLATE(T, poly_div_newton_n_preinv) (b, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (b, q, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of binv and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 40), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 40), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_div_newton_n_preinv) (q, a, b, binv, ctx); TEMPLATE(T, poly_div_newton_n_preinv) (binv, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (binv, q, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (binv, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-div_series.c000066400000000000000000000050171461254215100226740ustar00rootroot00000000000000/* Copyright (C) 2009, 2014 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_div_series, state) { int i, result; /* Check A*B^{-1} * B is congruent A mod t^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; slong n = n_randint(state, 80) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (c, state, n_randint(state, 80) + 2, ctx); TEMPLATE(T, poly_randtest) (d, state, n_randint(state, 80) + 2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 80) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 80) + 1, ctx); TEMPLATE(T, randtest_not_zero) (b->coeffs + 0, state, ctx); TEMPLATE(T, poly_div_series) (c, a, b, n, ctx); TEMPLATE(T, poly_mullow) (d, c, b, n, ctx); result = (TEMPLATE(T, poly_equal_trunc) (a, d, n, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b = "), TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("c = "), TEMPLATE(T, poly_print) (c, ctx), flint_printf("\n\n"); flint_printf("d = "), TEMPLATE(T, poly_print) (d, ctx), flint_printf("\n\n"); flint_printf("ctx = "), TEMPLATE(T, ctx_print) (ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-divides.c000066400000000000000000000114701461254215100221670ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_divides, state) { int i, result; /* Check that b divides a b and that the quotient is a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, q; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 30) + 1, ctx); TEMPLATE(T, poly_mul) (c, a, b, ctx); result = TEMPLATE(T, poly_divides) (q, c, b, ctx) && TEMPLATE(T, poly_equal) (q, a, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("q = "), TEMPLATE(T, poly_print_pretty) (q, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of a and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_mul) (c, a, b, ctx); result = TEMPLATE(T, poly_divides) (c, c, b, ctx) && TEMPLATE(T, poly_equal) (c, a, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of b and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_mul) (c, a, b, ctx); result = TEMPLATE(T, poly_divides) (b, c, b, ctx) && TEMPLATE(T, poly_equal) (b, a, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-divrem.c000066400000000000000000000207551461254215100220340ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_divrem, state) { int i, result; /* Check q*b + r == a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, q, r; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_divrem) (q, r, a, b, ctx); TEMPLATE(T, poly_mul) (c, q, b, ctx); TEMPLATE(T, poly_add) (c, c, r, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("q = "), TEMPLATE(T, poly_print_pretty) (q, "X", ctx), flint_printf("\n"); flint_printf("r = "), TEMPLATE(T, poly_print_pretty) (r, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a and r */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_divrem) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem) (q, a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, r, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("q = "), TEMPLATE(T, poly_print_pretty) (q, "X", ctx), flint_printf("\n"); flint_printf("r = "), TEMPLATE(T, poly_print_pretty) (r, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b and r */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_divrem) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem) (q, b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, r, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("q = "), TEMPLATE(T, poly_print_pretty) (q, "X", ctx), flint_printf("\n"); flint_printf("r = "), TEMPLATE(T, poly_print_pretty) (r, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_divrem) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem) (a, r, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, q, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("q = "), TEMPLATE(T, poly_print_pretty) (q, "X", ctx), flint_printf("\n"); flint_printf("r = "), TEMPLATE(T, poly_print_pretty) (r, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b and q */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_divrem) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem) (b, r, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, q, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("q = "), TEMPLATE(T, poly_print_pretty) (q, "X", ctx), flint_printf("\n"); flint_printf("r = "), TEMPLATE(T, poly_print_pretty) (r, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-divrem_newton_n_preinv.c000066400000000000000000000317501461254215100253230ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_divrem_newton_n_preinv, state) { int i, result; /* Check result of divrem */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r, test; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); TEMPLATE(T, poly_init) (test, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, a, b, binv, ctx); TEMPLATE(T, poly_mul) (test, q, b, ctx); TEMPLATE(T, poly_add) (test, test, r, ctx); result = (TEMPLATE(T, poly_equal) (a, test, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (test, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, poly_clear) (test, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of a and q */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, a, b, binv, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (a, r, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (a, q, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of b and q */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, a, b, binv, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (b, r, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (b, q, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of binv and q */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, a, b, binv, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (binv, r, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (binv, q, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (binv, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of a and r */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, a, b, binv, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, a, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (a, r, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of b and r */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, a, b, binv, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, b, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (b, r, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of binv and r */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (binv, ctx); TEMPLATE(T, poly_init) (q, ctx); TEMPLATE(T, poly_init) (r, ctx); do TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); if (a->length > 2 * (b->length) - 3) TEMPLATE(T, poly_truncate) (a, 2 * (b->length) - 3, ctx); TEMPLATE(T, poly_reverse) (binv, b, b->length, ctx); TEMPLATE(T, poly_inv_series_newton) (binv, binv, b->length, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, r, a, b, binv, ctx); TEMPLATE(T, poly_divrem_newton_n_preinv) (q, binv, a, b, binv, ctx); result = (TEMPLATE(T, poly_equal) (binv, r, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (binv, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (q, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (binv, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, poly_clear) (r, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-equal_trunc.c000066400000000000000000000070211461254215100230570ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_equal_trunc, state) { int i, result; /* Compare equal polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; TEMPLATE(T, t) c; slong j, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); for (j = 0; j < n; j++) { TEMPLATE(T, poly_get_coeff) (c, a, j, ctx); TEMPLATE(T, poly_set_coeff) (b, j, c, ctx); } result = (TEMPLATE(T, poly_equal_trunc) (a, b, n, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (c, ctx); TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare unequal polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; TEMPLATE(T, t) c, d; slong j, n, m; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, init) (c, ctx); TEMPLATE(T, init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); n = n_randint(state, 100) + 1; m = n_randint(state, n); for (j = 0; j < n; j++) { TEMPLATE(T, poly_get_coeff) (c, a, j, ctx); TEMPLATE(T, poly_set_coeff) (b, j, c, ctx); } TEMPLATE(T, poly_get_coeff) (c, a, m, ctx); TEMPLATE(T, set_si) (d, 1, ctx); TEMPLATE(T, add) (c, c, d, ctx); TEMPLATE(T, poly_set_coeff) (b, m, c, ctx); result = (!TEMPLATE(T, poly_equal_trunc) (a, b, n, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (c, ctx); TEMPLATE(T, clear) (d, ctx); TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-evaluate_fq.c000066400000000000000000000102531461254215100230320ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_evaluate_fq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f; TEMPLATE(T, t) x, y, z; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, init) (y, ctx); TEMPLATE(T, init) (z, ctx); TEMPLATE(T, poly_randtest) (f, state, len, ctx); TEMPLATE(T, randtest) (x, state, ctx); TEMPLATE(T, set) (z, x, ctx); TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (y, f, x, ctx); TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (x, f, x, ctx); result = (TEMPLATE(T, equal) (x, y, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("f = "), TEMPLATE(T, poly_print_pretty) (f, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); flint_printf("y = "), TEMPLATE(T, print_pretty) (y, ctx), flint_printf("\n"); flint_printf("z = "), TEMPLATE(T, print_pretty) (z, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, clear) (y, ctx); TEMPLATE(T, clear) (z, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check (f + g)(a) == f(a) + g(a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, g, h; TEMPLATE(T, t) x, y, z; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (h, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, init) (y, ctx); TEMPLATE(T, init) (z, ctx); TEMPLATE(T, poly_randtest) (f, state, len, ctx); TEMPLATE(T, poly_randtest) (g, state, len, ctx); TEMPLATE(T, randtest) (x, state, ctx); TEMPLATE(T, poly_add) (h, f, g, ctx); TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (y, f, x, ctx); TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (z, g, x, ctx); TEMPLATE(T, add) (y, y, z, ctx); TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (z, h, x, ctx); result = (TEMPLATE(T, equal) (y, z, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("f = "), TEMPLATE(T, poly_print_pretty) (f, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); flint_printf("h = "), TEMPLATE(T, poly_print_pretty) (h, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); flint_printf("y = "), TEMPLATE(T, print_pretty) (y, ctx), flint_printf("\n"); flint_printf("z = "), TEMPLATE(T, print_pretty) (z, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (h, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, clear) (y, ctx); TEMPLATE(T, clear) (z, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-evaluate_fq_vec_fast.c000066400000000000000000000045621461254215100247120ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 William Hart Copyright (C) 2011, 2012 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE2_FUNCTION_START(T, poly_evaluate, vec_fast, state) { int i, result = 1; for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) P; TEMPLATE(T, struct) * x, * y, * z; slong j, n, npoints; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); npoints = n_randint(state, 10); n = n_randint(state, 10); TEMPLATE(T, poly_init)(P, ctx); x = _TEMPLATE(T, vec_init)(npoints, ctx); y = _TEMPLATE(T, vec_init)(npoints, ctx); z = _TEMPLATE(T, vec_init)(npoints, ctx); TEMPLATE(T, poly_randtest)(P, state, n, ctx); for (j = 0; j < npoints; j++) TEMPLATE(T, randtest)(x + j, state, ctx); TEMPLATE4(T, poly_evaluate, T, vec_iter)(y, P, x, npoints, ctx); TEMPLATE4(T, poly_evaluate, T, vec_fast)(z, P, x, npoints, ctx); result = _TEMPLATE(T, vec_equal)(y, z, npoints, ctx); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, ctx_print)(ctx); flint_printf("\nn=%wd, npoints=%wd\n\n", n, npoints); flint_printf("P: "); TEMPLATE(T, poly_print_pretty)(P, "x", ctx); flint_printf("\n\n"); for (j = 0; j < npoints; j++) TEMPLATE(T, print_pretty)(y + j, ctx), flint_printf(" "); flint_printf("\n"); for (j = 0; j < npoints; j++) TEMPLATE(T, print_pretty)(z + j, ctx), flint_printf(" "); flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(P, ctx); _TEMPLATE(T, vec_clear)(x, npoints, ctx); _TEMPLATE(T, vec_clear)(y, npoints, ctx); _TEMPLATE(T, vec_clear)(z, npoints, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-gcd.c000066400000000000000000000157631461254215100213060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_gcd, state) { int i, result; /* Check that gcd(a,a) = a (made monic) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g; len = n_randint(state, 30) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_randtest_not_zero) (a, state, len, ctx); TEMPLATE(T, poly_make_monic) (b, a, ctx); TEMPLATE(T, poly_gcd) (g, a, a, ctx); result = (TEMPLATE(T, poly_equal) (g, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Find coprime polys, multiply by another poly and check the GCD is that poly */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len, j; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, g; len = n_randint(state, 30) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_randtest_not_zero) (a, state, len, ctx); for (j = 0; (j < 100 * flint_test_multiplier()) && !TEMPLATE(T, poly_is_one) (g, ctx); j++) { TEMPLATE(T, poly_randtest_not_zero) (b, state, len, ctx); TEMPLATE(T, poly_gcd) (g, a, b, ctx); } if (!TEMPLATE(T, poly_is_one) (g, ctx)) { flint_printf("FAIL:\n"); flint_printf ("could not find coprime polynomials after %wd tries\n", j + 1); fflush(stdout); flint_abort(); } for (j = 0; (j < 100 * flint_test_multiplier()) && (c->length < 2); j++) TEMPLATE(T, poly_randtest_not_zero) (c, state, len + 2, ctx); if (c->length < 2) { flint_printf("FAIL:\n"); flint_printf ("could not find non-unit polynomial after %wd tries\n", j + 1); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_make_monic) (c, c, ctx); TEMPLATE(T, poly_mul) (a, a, c, ctx); TEMPLATE(T, poly_mul) (b, b, c, ctx); TEMPLATE(T, poly_gcd) (g, a, b, ctx); result = (TEMPLATE(T, poly_equal) (g, c, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of a and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g; len = n_randint(state, 10) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_randtest_not_zero) (a, state, len, ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, len, ctx); TEMPLATE(T, poly_gcd) (g, a, b, ctx); TEMPLATE(T, poly_gcd) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (g, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of b and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g; len = n_randint(state, 10) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_randtest_not_zero) (a, state, len, ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, len, ctx); TEMPLATE(T, poly_gcd) (g, a, b, ctx); TEMPLATE(T, poly_gcd) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (g, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("g = "), TEMPLATE(T, poly_print_pretty) (g, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-gcd_euclidean_f.c000066400000000000000000000050641461254215100236150ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_gcd_euclidean_f, state) { int i, result; /* Compare with the usual GCD function. N.B. I checked by hand that this test shows both outcomes, i.e. trivial and non-trivial factors, sufficiently frequently. */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_init_randtest_reducible)(ctx, state, 3); TEMPLATE(T, init) (f, ctx); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_gcd_euclidean_f) (f, c, a, b, ctx); if (!TEMPLATE(T, is_one) (f, ctx)) { result = 1; } else { TEMPLATE(T, poly_gcd) (d, a, b, ctx); result = TEMPLATE(T, poly_equal) (c, d, ctx); } if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "x", ctx); flint_printf("\n\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "x", ctx); flint_printf("\n\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "x", ctx); flint_printf("\n\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "x", ctx); flint_printf("\n\n"); flint_printf("f = "), TEMPLATE(T, print_pretty) (f, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, clear) (f, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-get_str.c000066400000000000000000000022311461254215100222020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_get_str, state) { int i, len; char *str; TEMPLATE(T, poly_t) a; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); for (len = 0; len < 100; len++) for (i = 0; i < 1 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_randtest) (a, state, len, ctx); str = TEMPLATE(T, poly_get_str) (a, ctx); /* flint_printf("\n\n"); */ /* TEMPLATE(T, poly_print)(a, ctx); */ /* flint_printf("\n%s\n", str); */ flint_free(str); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, ctx_clear) (ctx); TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-get_str_pretty.c000066400000000000000000000022701461254215100236140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_get_str_pretty, state) { int i, len; char *str; TEMPLATE(T, poly_t) a; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); for (len = 0; len < 100; len++) for (i = 0; i < 1 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_randtest) (a, state, len, ctx); str = TEMPLATE(T, poly_get_str_pretty) (a, "x", ctx); /* flint_printf("\n\n"); */ /* TEMPLATE(T, poly_print_pretty)(a, "x", ctx); */ /* flint_printf("\n%s\n", str); */ flint_free(str); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, ctx_clear) (ctx); TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-hamming_weight.c000066400000000000000000000062561461254215100235350ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_hamming_weight, state) { int i, result; /* Check consistency */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; slong w1, w2; TEMPLATE(T, poly_t) a, b; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_set) (b, a, ctx); w1 = TEMPLATE(T, poly_hamming_weight) (a, ctx); w2 = TEMPLATE(T, poly_hamming_weight) (b, ctx); result = (w1 == w2); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("w1 = %wd \n w2 = %wd \n", w1, w2); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that wt(a+b) \leq wt(a) + wt(b) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; slong w1, w2, wsum; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_add) (c, a, b, ctx); w1 = TEMPLATE(T, poly_hamming_weight) (a, ctx); w2 = TEMPLATE(T, poly_hamming_weight) (b, ctx); wsum = TEMPLATE(T, poly_hamming_weight) (c, ctx); result = (wsum <= w1 + w2); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("w1 = %wd \n w2 = %wd \n wsum = %wd", w1, w2, wsum); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-inflate.c000066400000000000000000000053751461254215100221710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_inflate, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { TEMPLATE(T, poly_t) poly1, poly2, poly3, xp; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) one; ulong inflation; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly1, ctx); TEMPLATE(T, poly_init) (poly2, ctx); TEMPLATE(T, poly_init) (poly3, ctx); TEMPLATE(T, poly_init) (xp, ctx); TEMPLATE(T, poly_randtest) (poly1, state, n_randint(state, 20), ctx); inflation = n_randint(state, 10); TEMPLATE(T, poly_inflate) (poly2, poly1, inflation, ctx); TEMPLATE(T, init) (one, ctx); TEMPLATE(T, one) (one, ctx); TEMPLATE(T, poly_set_coeff) (xp, inflation, one, ctx); TEMPLATE(T, poly_compose) (poly3, poly1, xp, ctx); TEMPLATE(T, clear) (one, ctx); if (!TEMPLATE(T, poly_equal) (poly2, poly3, ctx)) { flint_printf("FAIL: not equal to compose (inflation = %wu)\n", inflation); flint_printf("poly1:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n\n"); flint_printf("poly2:\n"); TEMPLATE(T, poly_print) (poly2, ctx); flint_printf("\n\n"); flint_printf("poly3:\n"); TEMPLATE(T, poly_print) (poly3, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_inflate) (poly1, poly1, inflation, ctx); if (!TEMPLATE(T, poly_equal) (poly1, poly2, ctx)) { flint_printf("FAIL: aliasing (inflation = %wu)\n", inflation); flint_printf("poly1:\n"); TEMPLATE(T, poly_print) (poly1, ctx); flint_printf("\n\n"); flint_printf("poly2:\n"); TEMPLATE(T, poly_print) (poly2, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, poly_clear) (poly3, ctx); TEMPLATE(T, poly_clear) (xp, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-inv_series_newton.c000066400000000000000000000043421461254215100243000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_inv_series_newton, state) { int i, result; /* Check Q^{-1} * Q is congruent 1 mod t^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, one; slong n = n_randint(state, 80) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (one, ctx); TEMPLATE(T, poly_randtest_not_zero) (a, state, n_randint(state, 80) + 1, ctx); TEMPLATE(T, randtest_not_zero) (a->coeffs, state, ctx); TEMPLATE(T, poly_one) (one, ctx); TEMPLATE(T, poly_inv_series_newton) (b, a, n, ctx); TEMPLATE(T, poly_mullow) (c, a, b, n, ctx); result = (TEMPLATE(T, poly_equal) (c, one, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b = "), TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("c = "), TEMPLATE(T, poly_print) (c, ctx), flint_printf("\n\n"); flint_printf("ctx = "), TEMPLATE(T, ctx_print) (ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (one, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-invsqrt_series.c000066400000000000000000000103011461254215100236100ustar00rootroot00000000000000/* Copyright (C) 2011, 2021, 2022 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_invsqrt_series, state) { int i, result; /* Check 1/g^2 = h mod x^m */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) h, g, r; slong m; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, poly_init)(h, ctx); TEMPLATE(T, poly_init)(g, ctx); TEMPLATE(T, poly_init)(r, ctx); do TEMPLATE(T, poly_randtest)(h, state, n_randint(state, 30), ctx); while (h->length == 0); TEMPLATE(T, set_ui)(c, 1, ctx); TEMPLATE(T, poly_set_coeff)(h, 0, c, ctx); m = n_randint(state, h->length) + 1; TEMPLATE(T, poly_invsqrt_series)(g, h, m, ctx); TEMPLATE(T, poly_mullow)(r, g, g, m, ctx); TEMPLATE(T, poly_inv_series)(r, r, m, ctx); TEMPLATE(T, poly_truncate)(h, m, ctx); result = TEMPLATE(T, poly_equal)(r, h, ctx); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) result = result || TEMPLATE(T, ctx_prime)(ctx) == 2; #else result = result || fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0; #endif if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print)(h, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print)(g, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print)(r, ctx), flint_printf("\n\n"); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) flint_printf("n = %wu\n", TEMPLATE(T, ctx_prime)(ctx)); #else flint_printf("n = "); fmpz_print(TEMPLATE(T, ctx_prime)(ctx)); flint_printf("\n"); #endif fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(h, ctx); TEMPLATE(T, poly_clear)(g, ctx); TEMPLATE(T, poly_clear)(r, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check aliasing of h and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) g, h; slong m; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, poly_init)(h, ctx); TEMPLATE(T, poly_init)(g, ctx); do TEMPLATE(T, poly_randtest)(h, state, n_randint(state, 20), ctx); while (h->length == 0); TEMPLATE(T, set_ui)(c, 1, ctx); TEMPLATE(T, poly_set_coeff)(h, 0, c, ctx); m = n_randint(state, h->length) + 1; TEMPLATE(T, poly_invsqrt_series)(g, h, m, ctx); TEMPLATE(T, poly_invsqrt_series)(h, h, m, ctx); result = TEMPLATE(T, poly_equal)(g, h, ctx); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) result = result || TEMPLATE(T, ctx_prime)(ctx) == 2; #else result = result || fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0; #endif if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print)(h, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print)(g, ctx), flint_printf("\n\n"); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) flint_printf("n = %wu\n", TEMPLATE(T, ctx_prime)(ctx)); #else flint_printf("n = "); fmpz_print(TEMPLATE(T, ctx_prime)(ctx)); flint_printf("\n"); #endif flint_printf("m = %wd\n", m); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(g, ctx); TEMPLATE(T, poly_clear)(h, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-make_monic.c000066400000000000000000000052721461254215100226450ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_make_monic, state) { int i, result; /* test aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_randtest_not_zero) (a, state, len, ctx); TEMPLATE(T, poly_make_monic) (b, a, ctx); TEMPLATE(T, poly_make_monic) (a, a, ctx); result = TEMPLATE(T, poly_equal) (a, b, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check new leading coeff = 1 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_randtest_not_zero) (a, state, len, ctx); TEMPLATE(T, poly_make_monic) (a, a, ctx); result = TEMPLATE(T, is_one) (TEMPLATE(T, poly_lead) (a, ctx), ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("lead ="), TEMPLATE(T, print_pretty) (TEMPLATE(T, poly_lead) (a, ctx), ctx), flint_printf("\n"); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mul.c000066400000000000000000000177421461254215100213450ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mul, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul) (c, a, b, ctx); TEMPLATE(T, poly_mul) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul) (c, a, b, ctx); TEMPLATE(T, poly_mul) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul) (c, a, a, ctx); TEMPLATE(T, poly_mul) (a, a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a * b == b * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, e; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul) (c, a, b, ctx); TEMPLATE(T, poly_mul) (e, b, a, ctx); result = (TEMPLATE(T, poly_equal) (e, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a1, a2, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a1, ctx); TEMPLATE(T, poly_init) (a2, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_randtest) (c, state, len, ctx); TEMPLATE(T, poly_randtest) (d, state, len, ctx); TEMPLATE(T, poly_mul) (a1, b, c, ctx); TEMPLATE(T, poly_mul) (a2, b, d, ctx); TEMPLATE(T, poly_add) (a1, a1, a2, ctx); TEMPLATE(T, poly_add) (c, c, d, ctx); TEMPLATE(T, poly_mul) (a2, b, c, ctx); result = (TEMPLATE(T, poly_equal) (a1, a2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a1 = "), TEMPLATE(T, poly_print_pretty) (a1, "X", ctx), flint_printf("\n"); flint_printf("a2 = "), TEMPLATE(T, poly_print_pretty) (a2, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a1, ctx); TEMPLATE(T, poly_clear) (a2, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mul_KS.c000066400000000000000000000200061461254215100217250ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mul_KS, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_KS) (c, a, b, ctx); TEMPLATE(T, poly_mul_KS) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_KS) (c, a, b, ctx); TEMPLATE(T, poly_mul_KS) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul_KS) (c, a, a, ctx); TEMPLATE(T, poly_mul_KS) (a, a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a * b == b * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, e; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_KS) (c, a, b, ctx); TEMPLATE(T, poly_mul_KS) (e, b, a, ctx); result = (TEMPLATE(T, poly_equal) (e, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a1, a2, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a1, ctx); TEMPLATE(T, poly_init) (a2, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_randtest) (c, state, len, ctx); TEMPLATE(T, poly_randtest) (d, state, len, ctx); TEMPLATE(T, poly_mul_KS) (a1, b, c, ctx); TEMPLATE(T, poly_mul_KS) (a2, b, d, ctx); TEMPLATE(T, poly_add) (a1, a1, a2, ctx); TEMPLATE(T, poly_add) (c, c, d, ctx); TEMPLATE(T, poly_mul_KS) (a2, b, c, ctx); result = (TEMPLATE(T, poly_equal) (a1, a2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a1 = "), TEMPLATE(T, poly_print_pretty) (a1, "X", ctx), flint_printf("\n"); flint_printf("a2 = "), TEMPLATE(T, poly_print_pretty) (a2, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a1, ctx); TEMPLATE(T, poly_clear) (a2, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mul_classical.c000066400000000000000000000201321461254215100233460ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mul_classical, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_classical) (c, a, b, ctx); TEMPLATE(T, poly_mul_classical) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_classical) (c, a, b, ctx); TEMPLATE(T, poly_mul_classical) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul_classical) (c, a, a, ctx); TEMPLATE(T, poly_mul_classical) (a, a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a * b == b * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, e; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_classical) (c, a, b, ctx); TEMPLATE(T, poly_mul_classical) (e, b, a, ctx); result = (TEMPLATE(T, poly_equal) (e, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a1, a2, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a1, ctx); TEMPLATE(T, poly_init) (a2, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_randtest) (c, state, len, ctx); TEMPLATE(T, poly_randtest) (d, state, len, ctx); TEMPLATE(T, poly_mul_classical) (a1, b, c, ctx); TEMPLATE(T, poly_mul_classical) (a2, b, d, ctx); TEMPLATE(T, poly_add) (a1, a1, a2, ctx); TEMPLATE(T, poly_add) (c, c, d, ctx); TEMPLATE(T, poly_mul_classical) (a2, b, c, ctx); result = (TEMPLATE(T, poly_equal) (a1, a2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a1 = "), TEMPLATE(T, poly_print_pretty) (a1, "X", ctx), flint_printf("\n"); flint_printf("a2 = "), TEMPLATE(T, poly_print_pretty) (a2, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a1, ctx); TEMPLATE(T, poly_clear) (a2, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mul_reorder.c000066400000000000000000000202341461254215100230550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mul_reorder, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_reorder) (c, a, b, ctx); TEMPLATE(T, poly_mul_reorder) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (alias a = a * b):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_reorder) (c, a, b, ctx); TEMPLATE(T, poly_mul_reorder) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL (b = a * b):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul_reorder) (c, a, a, ctx); TEMPLATE(T, poly_mul_reorder) (a, a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (alias a = a * a):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a * b == b * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, e; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_reorder) (c, a, b, ctx); TEMPLATE(T, poly_mul_reorder) (e, b, a, ctx); result = (TEMPLATE(T, poly_equal) (e, c, ctx)); if (!result) { flint_printf("FAIL (a * b == b * a):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a1, a2, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a1, ctx); TEMPLATE(T, poly_init) (a2, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_randtest) (c, state, len, ctx); TEMPLATE(T, poly_randtest) (d, state, len, ctx); TEMPLATE(T, poly_mul_reorder) (a1, b, c, ctx); TEMPLATE(T, poly_mul_reorder) (a2, b, d, ctx); TEMPLATE(T, poly_add) (a1, a1, a2, ctx); TEMPLATE(T, poly_add) (c, c, d, ctx); TEMPLATE(T, poly_mul_reorder) (a2, b, c, ctx); result = (TEMPLATE(T, poly_equal) (a1, a2, ctx)); if (!result) { flint_printf("FAIL ((b*c)+(b*d) == b*(c+d)):\n\n"); flint_printf("a1 = "), TEMPLATE(T, poly_print_pretty) (a1, "X", ctx), flint_printf("\n"); flint_printf("a2 = "), TEMPLATE(T, poly_print_pretty) (a2, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a1, ctx); TEMPLATE(T, poly_clear) (a2, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mul_univariate.c000066400000000000000000000201461461254215100235640ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mul_univariate, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_univariate) (c, a, b, ctx); TEMPLATE(T, poly_mul_univariate) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_univariate) (c, a, b, ctx); TEMPLATE(T, poly_mul_univariate) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul_univariate) (c, a, a, ctx); TEMPLATE(T, poly_mul_univariate) (a, a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a * b == b * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, e; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_mul_univariate) (c, a, b, ctx); TEMPLATE(T, poly_mul_univariate) (e, b, a, ctx); result = (TEMPLATE(T, poly_equal) (e, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a1, a2, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a1, ctx); TEMPLATE(T, poly_init) (a2, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_randtest) (c, state, len, ctx); TEMPLATE(T, poly_randtest) (d, state, len, ctx); TEMPLATE(T, poly_mul_univariate) (a1, b, c, ctx); TEMPLATE(T, poly_mul_univariate) (a2, b, d, ctx); TEMPLATE(T, poly_add) (a1, a1, a2, ctx); TEMPLATE(T, poly_add) (c, c, d, ctx); TEMPLATE(T, poly_mul_univariate) (a2, b, c, ctx); result = (TEMPLATE(T, poly_equal) (a1, a2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a1 = "), TEMPLATE(T, poly_print_pretty) (a1, "X", ctx), flint_printf("\n"); flint_printf("a2 = "), TEMPLATE(T, poly_print_pretty) (a2, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a1, ctx); TEMPLATE(T, poly_clear) (a2, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mulhigh.c000066400000000000000000000040151461254215100221720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mulhigh, state) { int i, result; /* Compare with left truncated product of a and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong j, n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); n = n_randint(state, 50); TEMPLATE(T, poly_randtest) (b, state, n, ctx); TEMPLATE(T, poly_randtest) (c, state, n, ctx); TEMPLATE(T, poly_mulhigh) (a, b, c, n, ctx); TEMPLATE(T, poly_mul) (b, b, c, ctx); for (j = 0; j < n; j++) { if (j < a->length) TEMPLATE(T, zero) (a->coeffs + j, ctx); if (j < b->length) TEMPLATE(T, zero) (b->coeffs + j, ctx); } _TEMPLATE(T, poly_normalise) (a, ctx); _TEMPLATE(T, poly_normalise) (b, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mulhigh_classical.c000066400000000000000000000125141461254215100242130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mulhigh_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong j, start; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (c, state, n_randint(state, 50), ctx); start = n_randint(state, 50); TEMPLATE(T, poly_mulhigh_classical) (a, b, c, start, ctx); TEMPLATE(T, poly_mulhigh_classical) (b, b, c, start, ctx); for (j = 0; j < start; j++) { if (j < a->length) TEMPLATE(T, zero) (a->coeffs + j, ctx); if (j < b->length) TEMPLATE(T, zero) (b->coeffs + j, ctx); } _TEMPLATE(T, poly_normalise) (a, ctx); _TEMPLATE(T, poly_normalise) (b, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong j, start; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (c, state, n_randint(state, 50), ctx); start = n_randint(state, 50); TEMPLATE(T, poly_mulhigh_classical) (a, b, c, start, ctx); TEMPLATE(T, poly_mulhigh_classical) (c, b, c, start, ctx); for (j = 0; j < start; j++) { if (j < a->length) TEMPLATE(T, zero) (a->coeffs + j, ctx); if (j < c->length) TEMPLATE(T, zero) (c->coeffs + j, ctx); } _TEMPLATE(T, poly_normalise) (a, ctx); _TEMPLATE(T, poly_normalise) (c, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (c, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare with mul_basecase */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; slong j, start; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (c, state, n_randint(state, 50), ctx); start = n_randint(state, 50); TEMPLATE(T, poly_mul_classical) (a, b, c, ctx); TEMPLATE(T, poly_mulhigh_classical) (d, b, c, start, ctx); for (j = 0; j < start; j++) { if (j < a->length) TEMPLATE(T, zero) (a->coeffs + j, ctx); if (j < d->length) TEMPLATE(T, zero) (d->coeffs + j, ctx); } _TEMPLATE(T, poly_normalise) (a, ctx); _TEMPLATE(T, poly_normalise) (d, ctx); result = (TEMPLATE(T, poly_equal) (a, d, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (c, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mullow.c000066400000000000000000000042551461254215100220620ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mullow, state) { int i, result; /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; slong n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); TEMPLATE(T, poly_mullow) (c, a, b, n, ctx); TEMPLATE(T, poly_mul) (d, a, b, ctx); TEMPLATE(T, poly_truncate) (d, n, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mullow_KS.c000066400000000000000000000042631461254215100224560ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mullow_KS, state) { int i, result; /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; slong n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); TEMPLATE(T, poly_mullow_KS) (c, a, b, n, ctx); TEMPLATE(T, poly_mul) (d, a, b, ctx); TEMPLATE(T, poly_truncate) (d, n, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mullow_classical.c000066400000000000000000000042761461254215100241030ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mullow_classical, state) { int i, result; /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; slong n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); n = n_randint(state, 50); TEMPLATE(T, poly_mullow_classical) (c, a, b, n, ctx); TEMPLATE(T, poly_mul) (d, a, b, ctx); TEMPLATE(T, poly_truncate) (d, n, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mullow_univariate.c000066400000000000000000000043031461254215100243030ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mullow_univariate, state) { int i, result; /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; slong n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); n = n_randint(state, 100); TEMPLATE(T, poly_mullow_univariate) (c, a, b, n, ctx); TEMPLATE(T, poly_mul) (d, a, b, ctx); TEMPLATE(T, poly_truncate) (d, n, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mulmod.c000066400000000000000000000164061461254215100220410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mulmod, state) { int i, result; /* Check aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, res, f; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_mulmod) (res, a, b, f, ctx); TEMPLATE(T, poly_mulmod) (a, a, b, f, ctx); result = (TEMPLATE(T, poly_equal) (res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, f, res; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_mulmod) (res, a, b, f, ctx); TEMPLATE(T, poly_mulmod) (b, a, b, f, ctx); result = (TEMPLATE(T, poly_equal) (res, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, f, res; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_mulmod) (res, a, b, f, ctx); TEMPLATE(T, poly_mulmod) (f, a, b, f, ctx); result = (TEMPLATE(T, poly_equal) (res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, res1, res2, t, f; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 1, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_mulmod) (res1, a, b, f, ctx); TEMPLATE(T, poly_mul) (res2, a, b, ctx); TEMPLATE(T, poly_divrem) (t, res2, res2, f, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-mulmod_preinv.c000066400000000000000000000266571461254215100234350ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_mulmod_preinv, state) { int i, result; /* Aliasing res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); do { TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 50), ctx); } while (TEMPLATE(T, poly_is_zero) (f, ctx)); if (a->length >= f->length) TEMPLATE(T, poly_rem) (a, a, f, ctx); if (b->length >= f->length) TEMPLATE(T, poly_rem) (b, b, f, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_mulmod_preinv) (res, a, b, f, finv, ctx); TEMPLATE(T, poly_mulmod_preinv) (a, a, b, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing res and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); do { TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 50), ctx); } while (TEMPLATE(T, poly_is_zero) (f, ctx)); if (a->length >= f->length) TEMPLATE(T, poly_rem) (a, a, f, ctx); if (b->length >= f->length) TEMPLATE(T, poly_rem) (b, b, f, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_mulmod_preinv) (res, a, b, f, finv, ctx); TEMPLATE(T, poly_mulmod_preinv) (b, a, b, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); do { TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 50), ctx); } while (TEMPLATE(T, poly_is_zero) (f, ctx)); if (a->length >= f->length) TEMPLATE(T, poly_rem) (a, a, f, ctx); if (b->length >= f->length) TEMPLATE(T, poly_rem) (b, b, f, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_mulmod_preinv) (res, a, b, f, finv, ctx); TEMPLATE(T, poly_mulmod_preinv) (f, a, b, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing res and finv */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); do { TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 50), ctx); } while (TEMPLATE(T, poly_is_zero) (f, ctx)); if (a->length >= f->length) TEMPLATE(T, poly_rem) (a, a, f, ctx); if (b->length >= f->length) TEMPLATE(T, poly_rem) (b, b, f, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_mulmod_preinv) (res, a, b, f, finv, ctx); TEMPLATE(T, poly_mulmod_preinv) (finv, a, b, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, finv, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("finv:\n"); TEMPLATE(T, poly_print) (finv, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res1, res2, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 50), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 50), ctx); do { TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 50), ctx); } while (TEMPLATE(T, poly_is_zero) (f, ctx)); if (a->length >= f->length) TEMPLATE(T, poly_rem) (a, a, f, ctx); if (b->length >= f->length) TEMPLATE(T, poly_rem) (b, b, f, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_mulmod_preinv) (res1, a, b, f, finv, ctx); TEMPLATE(T, poly_mul) (res2, a, b, ctx); TEMPLATE(T, poly_divrem) (t, res2, res2, f, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("b:\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-neg.c000066400000000000000000000053271461254215100213150ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_neg, state) { int i, result; /* Check aliasing: a = -a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_neg) (b, a, ctx); TEMPLATE(T, poly_neg) (a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that (a + (-a)) == 0 */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_neg) (b, a, ctx); TEMPLATE(T, poly_add) (a, a, b, ctx); result = (TEMPLATE(T, poly_is_zero) (a, ctx)); if (!result) { flint_printf("FAIL (a + (-a) == 0):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-pow.c000066400000000000000000000072131461254215100213450ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_pow, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; ulong exp; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); exp = n_randtest(state) % UWORD(20); TEMPLATE(T, poly_set) (b, a, ctx); TEMPLATE(T, poly_pow) (c, b, exp, ctx); TEMPLATE(T, poly_pow) (b, b, exp, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("exp = %wu\n", exp); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare with repeated multiplications by the base */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; ulong exp; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); exp = n_randtest(state) % UWORD(20); TEMPLATE(T, poly_pow) (a, b, exp, ctx); if (exp == 0) { TEMPLATE(T, poly_one) (c, ctx); } else { slong j; TEMPLATE(T, poly_set) (c, b, ctx); for (j = 1; j < exp; j++) TEMPLATE(T, poly_mul) (c, c, b, ctx); } result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("exp = %wu\n", exp); TEMPLATE(T, ctx_print) (ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-pow_trunc.c000066400000000000000000000066751461254215100225730ustar00rootroot00000000000000/* Copyright (C) 2010, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_pow_trunc, state) { int i, result; /* Check powering against naive method */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) d; slong e, trunc; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init) (d, ctx); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); e = n_randint(state, 20); trunc = n_randint(state, 30); TEMPLATE(T, poly_pow_trunc) (b, a, e, trunc, ctx); TEMPLATE(T, poly_pow) (c, a, e, ctx); TEMPLATE(T, poly_truncate) (c, trunc, ctx); TEMPLATE(T, poly_get_coeff) (d, c, 0, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx) || (a->length == 0 && e == 0 && c->length == 1 && TEMPLATE(T, is_one) (d, ctx))); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (d, ctx); TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_t) ctx; slong e, trunc; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); e = n_randint(state, 20); trunc = n_randint(state, 10); TEMPLATE(T, poly_pow_trunc) (b, a, e, trunc, ctx); TEMPLATE(T, poly_set) (c, a, ctx); TEMPLATE(T, poly_pow_trunc) (c, c, e, trunc, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-pow_trunc_binexp.c000066400000000000000000000067321461254215100241320ustar00rootroot00000000000000/* Copyright (C) 2010, 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_pow_trunc_binexp, state) { int i, result; /* Check powering against naive method */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) d; slong e, trunc; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init) (d, ctx); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); e = n_randint(state, 20); trunc = n_randint(state, 30); TEMPLATE(T, poly_pow_trunc_binexp) (b, a, e, trunc, ctx); TEMPLATE(T, poly_pow) (c, a, e, ctx); TEMPLATE(T, poly_truncate) (c, trunc, ctx); TEMPLATE(T, poly_get_coeff) (d, c, 0, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx) || (a->length == 0 && e == 0 && c->length == 1 && TEMPLATE(T, is_one) (d, ctx))); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (d, ctx); TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_t) ctx; slong e, trunc; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); e = n_randint(state, 20); trunc = n_randint(state, 20); TEMPLATE(T, poly_pow_trunc_binexp) (b, a, e, trunc, ctx); TEMPLATE(T, poly_set) (c, a, ctx); TEMPLATE(T, poly_pow_trunc_binexp) (c, c, e, trunc, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, exp = %wd, trunc = %wd\n", a->length, e, trunc); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (b, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print) (c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-powmod_fmpz_binexp.c000066400000000000000000000202321461254215100244420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_powmod_fmpz_binexp, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res, t, f; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 30); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (res, a, expz, f, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (a, a, expz, f, ctx); result = (TEMPLATE(T, poly_equal) (res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing of res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res, t, f; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 30); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (res, a, expz, f, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (f, a, expz, f, ctx); result = (TEMPLATE(T, poly_equal) (res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Compare with ui function */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, t, f; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 30); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_powmod_fmpz_binexp) (res1, a, expz, f, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (res2, a, exp, f, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, res3, res4, t, f; fmpz_t exp1, exp2, exp3; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); fmpz_init(exp1); fmpz_init(exp2); fmpz_randtest(exp1, state, 80); if (fmpz_sgn(exp1) == -1) fmpz_neg(exp1, exp1); fmpz_randtest(exp2, state, 80); if (fmpz_sgn(exp2) == -1) fmpz_neg(exp2, exp2); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (res3, ctx); TEMPLATE(T, poly_init) (res4, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (res1, a, exp1, f, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp) (res2, a, exp2, f, ctx); TEMPLATE(T, poly_mulmod) (res4, res1, res2, f, ctx); fmpz_init(exp3); fmpz_add(exp3, exp1, exp2); TEMPLATE(T, poly_powmod_fmpz_binexp) (res3, a, exp3, f, ctx); result = (TEMPLATE(T, poly_equal) (res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp1 = %{fmpz}\n", exp1); flint_printf("exp2 = %{fmpz}\n", exp2); flint_printf("exp3 = %{fmpz}\n", exp3); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); TEMPLATE(T, poly_print) (res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); TEMPLATE(T, poly_print) (res4, ctx), flint_printf("\n\n"); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (res3, ctx); TEMPLATE(T, poly_clear) (res4, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(exp1); fmpz_clear(exp2); fmpz_clear(exp3); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000224751461254215100260400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_powmod_fmpz_binexp_preinv, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res, a, expz, f, finv, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (a, a, expz, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing of res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res, a, expz, f, finv, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (f, a, expz, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Compare with ui function */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res1, a, expz, f, finv, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res2, a, exp, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, res3, res4, t, f, finv; fmpz_t exp1, exp2, exp3; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); fmpz_init(exp1); fmpz_init(exp2); fmpz_randtest(exp1, state, 100); if (fmpz_sgn(exp1) == -1) fmpz_neg(exp1, exp1); fmpz_randtest(exp2, state, 100); if (fmpz_sgn(exp2) == -1) fmpz_neg(exp2, exp2); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (res3, ctx); TEMPLATE(T, poly_init) (res4, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res1, a, exp1, f, finv, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res2, a, exp2, f, finv, ctx); TEMPLATE(T, poly_mulmod) (res4, res1, res2, f, ctx); fmpz_init(exp3); fmpz_add(exp3, exp1, exp2); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res3, a, exp3, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); TEMPLATE(T, poly_print) (res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); TEMPLATE(T, poly_print) (res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (res3, ctx); TEMPLATE(T, poly_clear) (res4, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(exp1); fmpz_clear(exp2); fmpz_clear(exp3); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000237541461254215100262050ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_powmod_fmpz_sliding_preinv, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (res, a, expz, 0, f, finv, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (a, a, expz, 0, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing of res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (res, a, expz, 0, f, finv, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (f, a, expz, 0, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Compare with binexp */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 30) + 1, ctx); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv)(res1, a, expz, 0, f, finv, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv)(res2, a, expz, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, res3, res4, t, f, finv; fmpz_t exp1, exp2, exp3; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); fmpz_init(exp1); fmpz_init(exp2); fmpz_randtest(exp1, state, 100); if (fmpz_sgn(exp1) == -1) fmpz_neg(exp1, exp1); fmpz_randtest(exp2, state, 100); if (fmpz_sgn(exp2) == -1) fmpz_neg(exp2, exp2); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (res3, ctx); TEMPLATE(T, poly_init) (res4, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 30) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (res1, a, exp1, 0, f, finv, ctx); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (res2, a, exp2, 0, f, finv, ctx); TEMPLATE(T, poly_mulmod) (res4, res1, res2, f, ctx); fmpz_init(exp3); fmpz_add(exp3, exp1, exp2); TEMPLATE(T, poly_powmod_fmpz_sliding_preinv) (res3, a, exp3, 0, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, ctx_print) (ctx); flint_printf("exp1:\n"); fmpz_print(exp1); flint_printf("\n\n"); flint_printf("exp2:\n"); fmpz_print(exp2); flint_printf("\n\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print_pretty) (f, "x", ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print_pretty) (res1, "x", ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print_pretty) (res2, "x", ctx), flint_printf("\n\n"); flint_printf("res3:\n"); TEMPLATE(T, poly_print_pretty) (res3, "x", ctx), flint_printf("\n\n"); flint_printf("res4:\n"); TEMPLATE(T, poly_print_pretty) (res4, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (res3, ctx); TEMPLATE(T, poly_clear) (res4, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(exp1); fmpz_clear(exp2); fmpz_clear(exp3); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-powmod_ui_binexp.c000066400000000000000000000176421461254215100241160ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_powmod_ui_binexp, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f; ulong exp; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (res1, a, exp, f, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (a, a, exp, f, ctx); result = (TEMPLATE(T, poly_equal) (res1, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing of res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f; ulong exp; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (res1, a, exp, f, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (f, a, exp, f, ctx); result = (TEMPLATE(T, poly_equal) (res1, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, t, f; ulong exp; int j; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 30) + 1, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (res1, a, exp, f, ctx); TEMPLATE(T, poly_one) (res2, ctx); for (j = 0; j < exp; j++) TEMPLATE(T, poly_mulmod) (res2, res2, a, f, ctx); /* NOTE: If exp is zero, then is it never reduced with respect to f */ if (exp == 0) TEMPLATE(T, poly_rem)(res2, res2, f, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, res3, res4, t, f; ulong exp1, exp2, exp3; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp1 = n_randint(state, 50); exp2 = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (res3, ctx); TEMPLATE(T, poly_init) (res4, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 30) + 1, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (res1, a, exp1, f, ctx); TEMPLATE(T, poly_powmod_ui_binexp) (res2, a, exp2, f, ctx); TEMPLATE(T, poly_mulmod) (res4, res1, res2, f, ctx); exp3 = exp1 + exp2; TEMPLATE(T, poly_powmod_ui_binexp) (res3, a, exp3, f, ctx); result = (TEMPLATE(T, poly_equal) (res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp1: %wu\n", exp1); flint_printf("exp2: %wu\n", exp2); flint_printf("exp3: %wu\n", exp3); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); TEMPLATE(T, poly_print) (res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); TEMPLATE(T, poly_print) (res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (res3, ctx); TEMPLATE(T, poly_clear) (res4, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000217061461254215100254750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_powmod_ui_binexp_preinv, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f, finv; ulong exp; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res1, a, exp, f, finv, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (a, a, exp, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res1, a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Aliasing of res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f, finv; ulong exp; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res1, a, exp, f, finv, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (f, a, exp, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res1, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* No aliasing */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, t, f, finv; ulong exp; int j; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res1, a, exp, f, finv, ctx); TEMPLATE(T, poly_one) (res2, ctx); for (j = 0; j < exp; j++) TEMPLATE(T, poly_mulmod) (res2, res2, a, f, ctx); /* NOTE: If exp is zero, then is it never reduced with respect to f */ if (exp == 0) TEMPLATE(T, poly_rem)(res2, res2, f, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^(b+c) = a^b * a^c */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, res3, res4, t, f, finv; ulong exp1, exp2, exp3; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp1 = n_randint(state, 50); exp2 = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (res3, ctx); TEMPLATE(T, poly_init) (res4, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 30) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res1, a, exp1, f, finv, ctx); TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res2, a, exp2, f, finv, ctx); TEMPLATE(T, poly_mulmod_preinv) (res4, res1, res2, f, finv, ctx); exp3 = exp1 + exp2; TEMPLATE(T, poly_powmod_ui_binexp_preinv) (res3, a, exp3, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res4, res3, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res3:\n"); TEMPLATE(T, poly_print) (res3, ctx), flint_printf("\n\n"); flint_printf("res4:\n"); TEMPLATE(T, poly_print) (res4, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (res3, ctx); TEMPLATE(T, poly_clear) (res4, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000104551461254215100250150ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_powmod_x_fmpz_preinv, state) { int i, result; /* Aliasing of res and f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) res, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 1, ctx); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_x_fmpz_preinv) (res, expz, f, finv, ctx); TEMPLATE(T, poly_powmod_x_fmpz_preinv) (f, expz, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res, f, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res:\n"); TEMPLATE(T, poly_print) (res, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } /* No aliasing -- compare with binexp */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, res2, t, f, finv; ulong exp; fmpz_t expz; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); exp = n_randint(state, 50); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (finv, ctx); TEMPLATE(T, poly_init) (res1, ctx); TEMPLATE(T, poly_init) (res2, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_gen) (a, ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 30) + 1, ctx); fmpz_init_set_ui(expz, exp); TEMPLATE(T, poly_reverse) (finv, f, f->length, ctx); TEMPLATE(T, poly_inv_series_newton) (finv, finv, f->length, ctx); TEMPLATE(T, poly_powmod_fmpz_binexp_preinv) (res1, a, expz, f, finv, ctx); TEMPLATE(T, poly_powmod_x_fmpz_preinv) (res2, expz, f, finv, ctx); result = (TEMPLATE(T, poly_equal) (res1, res2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); TEMPLATE(T, poly_print) (a, ctx), flint_printf("\n\n"); flint_printf("f:\n"); TEMPLATE(T, poly_print) (f, ctx), flint_printf("\n\n"); flint_printf("res1:\n"); TEMPLATE(T, poly_print) (res1, ctx), flint_printf("\n\n"); flint_printf("res2:\n"); TEMPLATE(T, poly_print) (res2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (finv, ctx); TEMPLATE(T, poly_clear) (res1, ctx); TEMPLATE(T, poly_clear) (res2, ctx); TEMPLATE(T, poly_clear) (t, ctx); fmpz_clear(expz); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-randtest_irreducible.c000066400000000000000000000024661461254215100247420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_randtest_irreducible, state) { int iter; for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly; slong length; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (poly, ctx); length = n_randint(state, 20) + 2; TEMPLATE(T, poly_randtest_irreducible) (poly, state, length, ctx); if (!TEMPLATE(T, poly_is_irreducible) (poly, ctx)) { flint_printf("Error: reducible polynomial created!\n"); flint_printf("poly:\n"); TEMPLATE(T, poly_print_pretty) (poly, "x", ctx); flint_printf("\n"); flint_abort(); } TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-scalar_addmul_fq.c000066400000000000000000000075421461254215100240260ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_scalar_addmul_fq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, t) x; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_set) (b, a, ctx); TEMPLATE(T, poly_set) (c, a, ctx); TEMPLATE(T, randtest(x, state, ctx)); TEMPLATE(T, TEMPLATE(poly_scalar_addmul, T)) (b, a, x, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_addmul, T)) (a, a, x, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that b += x*a is the same as c = b + x*a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, t) x; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_set) (a, c, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (c, a, x, ctx); TEMPLATE(T, poly_add) (c, b, c, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_addmul, T)) (b, a, x, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-scalar_div_fq.c000066400000000000000000000065311461254215100233370ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_scalar_div_fq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; TEMPLATE(T, t) x; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); while (TEMPLATE(T, is_zero(x, ctx))) TEMPLATE(T, randtest(x, state, ctx)); TEMPLATE(T, TEMPLATE(poly_scalar_div, T)) (b, a, x, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_div, T)) (a, a, x, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check a*x/x = a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; TEMPLATE(T, t) x; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); while (TEMPLATE(T, is_zero(x, ctx))) TEMPLATE(T, randtest(x, state, ctx)); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (b, a, x, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_div, T)) (b, b, x, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-scalar_mul_fq.c000066400000000000000000000036331461254215100233520ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_scalar_mul_fq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; TEMPLATE(T, t) x; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, randtest(x, state, ctx)); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (b, a, x, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (a, a, x, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-scalar_submul_fq.c000066400000000000000000000075421461254215100240670ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_scalar_submul_fq, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, t) x; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, randtest(x, state, ctx)); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_set) (b, a, ctx); TEMPLATE(T, poly_set) (c, a, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_submul, T)) (b, a, x, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_submul, T)) (a, a, x, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that b += x*a is the same as c = b + x*a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, t) x; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, init) (x, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_set) (a, c, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (c, a, x, ctx); TEMPLATE(T, poly_sub) (c, b, c, ctx); TEMPLATE(T, TEMPLATE(poly_scalar_submul, T)) (b, a, x, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("x = "), TEMPLATE(T, print_pretty) (x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-set_nmod_poly.c000066400000000000000000000042051461254215100234110ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "nmod_poly.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_set_nmod_poly, state) { int i, result; /* Check litfed polynomials by evaluating at random points */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) r, s; TEMPLATE(T, poly_t) a; nmod_poly_t b; ulong p; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init)(r, ctx); TEMPLATE(T, init)(s, ctx); TEMPLATE(T, poly_init)(a, ctx); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) nmod_poly_init(b, TEMPLATE(T, ctx_prime)(ctx)); #else nmod_poly_init(b, fmpz_get_ui(TEMPLATE(T, ctx_prime)(ctx))); #endif nmod_poly_randtest(b, state, len); p = n_randint(state, 10); TEMPLATE(T, poly_set_nmod_poly)(a, b, ctx); TEMPLATE(T, set_ui)(r, p, ctx); TEMPLATE3(T, poly_evaluate, T)(r, a, r, ctx); p = nmod_poly_evaluate_nmod(b, p); TEMPLATE(T, set_ui)(s, p, ctx); result = TEMPLATE(T, equal)(r, s, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), TEMPLATE(T, ctx_print(ctx)), flint_printf("\n"); flint_printf("b = "), nmod_poly_print_pretty(b, "X"), flint_printf("\n"); flint_printf("p = %u\n", p); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(r, ctx); TEMPLATE(T, clear)(s, ctx); nmod_poly_clear(b); TEMPLATE(T, poly_clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-set_trunc.c000066400000000000000000000045741461254215100225550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_set_trunc, state) { int i, result; /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d, e; slong n; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 30), ctx); n = n_randint(state, 100); TEMPLATE(T, poly_mullow) (c, a, b, n, ctx); TEMPLATE(T, poly_mul) (d, a, b, ctx); TEMPLATE(T, poly_set_trunc) (e, d, n, ctx); result = (TEMPLATE(T, poly_equal) (c, e, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-shift_left_right.c000066400000000000000000000112221461254215100240570ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_shift_left_right, state) { int i, result; /* Check aliasing for left shift */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len = n_randint(state, 30); TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong shift; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_set) (b, a, ctx); shift = n_randint(state, 30); TEMPLATE(T, poly_shift_left) (c, b, shift, ctx); TEMPLATE(T, poly_shift_left) (b, b, shift, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing for right shift */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len = n_randint(state, 30); TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong shift; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_set) (b, a, ctx); shift = n_randint(state, 30); TEMPLATE(T, poly_shift_right) (c, b, shift, ctx); TEMPLATE(T, poly_shift_right) (b, b, shift, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check shift left then right does nothing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len = n_randint(state, 100); TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong shift; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); shift = n_randint(state, 100); TEMPLATE(T, poly_shift_left) (b, a, shift, ctx); TEMPLATE(T, poly_shift_right) (c, b, shift, ctx); result = (TEMPLATE(T, poly_equal) (c, a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sqr.c000066400000000000000000000107231461254215100213450ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sqr, state) { int i, result; /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr) (c, a, ctx); TEMPLATE(T, poly_sqr) (a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^2 + a^2 == a * (a + a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr) (b, a, ctx); TEMPLATE(T, poly_add) (c, b, b, ctx); TEMPLATE(T, poly_add) (d, a, a, ctx); TEMPLATE(T, poly_mul) (d, a, d, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL (a^2 + a^2 == a(a + a)):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare mul() */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul) (b, a, a, ctx); TEMPLATE(T, poly_sqr) (c, a, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL (cmp with mul):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sqr_KS.c000066400000000000000000000107421461254215100217430ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sqr_KS, state) { int i, result; /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr_KS) (c, a, ctx); TEMPLATE(T, poly_sqr_KS) (a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^2 + a^2 == a * (a + a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr_KS) (b, a, ctx); TEMPLATE(T, poly_add) (c, b, b, ctx); TEMPLATE(T, poly_add) (d, a, a, ctx); TEMPLATE(T, poly_mul) (d, a, d, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL (a^2 + a^2 == a(a + a)):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare mul() */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 30) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul) (b, a, a, ctx); TEMPLATE(T, poly_sqr_KS) (c, a, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL (cmp with mul):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sqr_classical.c000066400000000000000000000110051461254215100233550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sqr_classical, state) { int i, result; /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr_classical) (c, a, ctx); TEMPLATE(T, poly_sqr_classical) (a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^2 + a^2 == a * (a + a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr_classical) (b, a, ctx); TEMPLATE(T, poly_add) (c, b, b, ctx); TEMPLATE(T, poly_add) (d, a, a, ctx); TEMPLATE(T, poly_mul) (d, a, d, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL (a^2 + a^2 == a(a + a)):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare mul() */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 30) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul) (b, a, a, ctx); TEMPLATE(T, poly_sqr_classical) (c, a, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL (cmp with mul):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sqr_reorder.c000066400000000000000000000107731461254215100230740ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sqr_reorder, state) { int i, result; /* Check aliasing: a = a * a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr_reorder) (c, a, ctx); TEMPLATE(T, poly_sqr_reorder) (a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a^2 + a^2 == a * (a + a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sqr_reorder) (b, a, ctx); TEMPLATE(T, poly_add) (c, b, b, ctx); TEMPLATE(T, poly_add) (d, a, a, ctx); TEMPLATE(T, poly_mul) (d, a, d, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL (a^2 + a^2 == a(a + a)):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Compare mul() */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 30) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_mul) (b, a, a, ctx); TEMPLATE(T, poly_sqr_reorder) (c, a, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL (cmp with mul):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sqrt.c000066400000000000000000000115651461254215100215360ustar00rootroot00000000000000/* Copyright (C) 2021, 2022 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sqrt, state) { int i; /* Test aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b; int square1, square2; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init)(a, ctx); TEMPLATE(T, poly_init)(b, ctx); TEMPLATE(T, poly_randtest)(a, state, 1 + n_randint(state, 20), ctx); if (n_randint(state, 2)) TEMPLATE(T, poly_mul)(a, a, a, ctx); square1 = TEMPLATE(T, poly_sqrt)(b, a, ctx); square2 = TEMPLATE(T, poly_sqrt)(a, a, ctx); if (square1 != square2 || (square1 && !TEMPLATE(T, poly_equal)(a, b, ctx))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); TEMPLATE(T, poly_print)(a, ctx); flint_printf("\n\n"); flint_printf("b: "); TEMPLATE(T, poly_print)(b, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(a, ctx); TEMPLATE(T, poly_clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Test random squares */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; int square; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init)(a, ctx); TEMPLATE(T, poly_init)(b, ctx); TEMPLATE(T, poly_init)(c, ctx); TEMPLATE(T, poly_randtest)(a, state, 1 + n_randint(state, 30), ctx); TEMPLATE(T, poly_mul)(b, a, a, ctx); square = TEMPLATE(T, poly_sqrt)(c, b, ctx); if (!square) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); TEMPLATE(T, poly_print)(a, ctx); flint_printf("\n\n"); flint_printf("b: "); TEMPLATE(T, poly_print)(b, ctx); flint_printf("\n\n"); flint_printf("c: "); TEMPLATE(T, poly_print)(c, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_mul)(c, c, c, ctx); if (!TEMPLATE(T, poly_equal)(c, b, ctx)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); TEMPLATE(T, poly_print)(a, ctx); flint_printf("\n\n"); flint_printf("b: "); TEMPLATE(T, poly_print)(b, ctx); flint_printf("\n\n"); flint_printf("c: "); TEMPLATE(T, poly_print)(c, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(a, ctx); TEMPLATE(T, poly_clear)(b, ctx); TEMPLATE(T, poly_clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Test "almost" squares */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; slong j; int square; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) t; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, init)(t, ctx); TEMPLATE(T, poly_init)(a, ctx); TEMPLATE(T, poly_init)(b, ctx); TEMPLATE(T, poly_init)(c, ctx); TEMPLATE(T, poly_randtest_not_zero)(a, state, 1 + n_randint(state, 30), ctx); TEMPLATE(T, poly_mul)(b, a, a, ctx); j = n_randint(state, TEMPLATE(T, poly_length)(b, ctx)); TEMPLATE(T, randtest)(t, state, ctx); TEMPLATE(T, set)(b->coeffs + j, t, ctx); _TEMPLATE(T, poly_normalise)(b, ctx); square = TEMPLATE(T, poly_sqrt)(c, b, ctx); if (square) { TEMPLATE(T, poly_mul)(c, c, c, ctx); if (!TEMPLATE(T, poly_equal)(c, b, ctx)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); TEMPLATE(T, poly_print)(a, ctx); flint_printf("\n\n"); flint_printf("b: "); TEMPLATE(T, poly_print)(b, ctx); flint_printf("\n\n"); flint_printf("c: "); TEMPLATE(T, poly_print)(c, ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, poly_clear)(a, ctx); TEMPLATE(T, poly_clear)(b, ctx); TEMPLATE(T, poly_clear)(c, ctx); TEMPLATE(T, clear)(t, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sqrt_series.c000066400000000000000000000105221461254215100231000ustar00rootroot00000000000000/* Copyright (C) 2011, 2021, 2022 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sqrt_series, state) { int i, result; /* Check g^2 = h mod x^m */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) h, g, r; slong m; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) one; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) if (TEMPLATE(T, ctx_prime)(ctx) != 2) { #else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) != 0) { #endif TEMPLATE(T, init)(one, ctx); TEMPLATE(T, poly_init)(h, ctx); TEMPLATE(T, poly_init)(g, ctx); TEMPLATE(T, poly_init)(r, ctx); do TEMPLATE(T, poly_randtest)(h, state, n_randint(state, 30), ctx); while (h->length == 0); TEMPLATE(T, set_ui)(one, 1, ctx); TEMPLATE(T, poly_set_coeff)(h, 0, one, ctx); m = n_randint(state, h->length) + 1; TEMPLATE(T, poly_sqrt_series)(g, h, m, ctx); TEMPLATE(T, poly_mullow)(r, g, g, m, ctx); TEMPLATE(T, poly_truncate)(h, m, ctx); result = (TEMPLATE(T, poly_equal)(r, h, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print)(h, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print)(g, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print)(r, ctx), flint_printf("\n\n"); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) flint_printf("n = %wu\n", TEMPLATE(T, ctx_prime)(ctx)); #else flint_printf("n = "); fmpz_print(TEMPLATE(T, ctx_prime)(ctx)); #endif flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(h, ctx); TEMPLATE(T, poly_clear)(g, ctx); TEMPLATE(T, poly_clear)(r, ctx); TEMPLATE(T, clear)(one, ctx); } TEMPLATE(T, ctx_clear)(ctx); } /* Check aliasing of h and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) g, h; slong m; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) one; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) if (TEMPLATE(T, ctx_prime)(ctx) != 2) { #else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) != 0) { #endif TEMPLATE(T, init)(one, ctx); TEMPLATE(T, poly_init)(h, ctx); TEMPLATE(T, poly_init)(g, ctx); do TEMPLATE(T, poly_randtest)(h, state, n_randint(state, 20), ctx); while (h->length == 0); TEMPLATE(T, set_ui)(one, 1, ctx); TEMPLATE(T, poly_set_coeff)(h, 0, one, ctx); m = n_randint(state, h->length) + 1; TEMPLATE(T, poly_sqrt_series)(g, h, m, ctx); TEMPLATE(T, poly_sqrt_series)(h, h, m, ctx); result = (TEMPLATE(T, poly_equal)(g, h, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print)(h, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print)(g, ctx), flint_printf("\n\n"); #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) flint_printf("n = %wu\n", TEMPLATE(T, ctx_prime)(ctx)); #else flint_printf("n = "); fmpz_print(TEMPLATE(T, ctx_prime)(ctx)); #endif flint_printf("m = %wd\n", m); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear)(g, ctx); TEMPLATE(T, poly_clear)(h, ctx); TEMPLATE(T, clear)(one, ctx); } TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sub.c000066400000000000000000000135371461254215100213370ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sub, state) { int i, result; /* Check aliasing: a = a - b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_sub) (c, a, b, ctx); TEMPLATE(T, poly_sub) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing a = a - b):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a - b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_sub) (c, a, b, ctx); TEMPLATE(T, poly_sub) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL (b = a - b):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a - a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_sub) (c, a, a, ctx); TEMPLATE(T, poly_sub) (a, a, a, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL (a = a - a):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that a - b == -(b - a) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, e; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (e, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); TEMPLATE(T, poly_sub) (c, a, b, ctx); TEMPLATE(T, poly_sub) (e, b, a, ctx); TEMPLATE(T, poly_neg) (e, e, ctx); result = (TEMPLATE(T, poly_equal) (e, c, ctx)); if (!result) { flint_printf("FAIL (a - b == -(b - a)):\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("e = "), TEMPLATE(T, poly_print_pretty) (e, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (e, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-sub_series.c000066400000000000000000000141521461254215100227030ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_sub_series, state) { int i, result; /* Check aliasing: a = a - b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong len, n; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_sub_series) (c, a, b, n, ctx); TEMPLATE(T, poly_sub_series) (a, a, b, n, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: b = a - b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong n, len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_sub_series) (c, a, b, n, ctx); TEMPLATE(T, poly_sub_series) (b, a, b, n, ctx); result = (TEMPLATE(T, poly_equal) (b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing: a = a - a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { slong n, len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_sub_series) (c, a, a, n, ctx); TEMPLATE(T, poly_sub_series) (a, a, a, n, ctx); result = (TEMPLATE(T, poly_equal) (a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that truncate(a - b, n) = sub_series(a, b, n) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong n, len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_randtest) (a, state, len, ctx); TEMPLATE(T, poly_randtest) (b, state, len, ctx); n = n_randint(state, 15); TEMPLATE(T, poly_sub_series) (c, a, b, n, ctx); TEMPLATE(T, poly_sub) (d, a, b, ctx); TEMPLATE(T, poly_truncate) (d, n, ctx); result = (TEMPLATE(T, poly_equal) (c, d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, poly_print_pretty) (b, "X", ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, poly_print_pretty) (c, "X", ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, poly_print_pretty) (d, "X", ctx), flint_printf("\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-xgcd.c000066400000000000000000000424761461254215100214770ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_xgcd, state) { int i, result; /* Generic case, most likely co-prime arguments ***************************** */ /* Compare with result from GCD and check correctness */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_gcd) (d, a, b, ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_mul) (v, s, a, ctx); TEMPLATE(T, poly_mul) (w, t, b, ctx); TEMPLATE(T, poly_add) (w, v, w, ctx); result = (TEMPLATE(T, poly_equal) (d, g, ctx) && TEMPLATE(T, poly_equal) (g, w, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Special case, arguments share a factor ******************************* */ /* Compare with result from GCD and check correctness */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, f, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (s, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (t, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 5), ctx); TEMPLATE(T, poly_mul) (a, a, f, ctx); TEMPLATE(T, poly_mul) (b, b, f, ctx); TEMPLATE(T, poly_gcd) (d, a, b, ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_mul) (v, s, a, ctx); TEMPLATE(T, poly_mul) (w, t, b, ctx); TEMPLATE(T, poly_add) (w, v, w, ctx); result = (TEMPLATE(T, poly_equal) (d, g, ctx) && TEMPLATE(T, poly_equal) (g, w, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (f, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of g and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd) (a, v, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, v, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, a, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of g and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd) (b, v, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, v, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, b, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of s and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd) (d, a, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, a, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of s and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd) (d, b, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, b, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of s and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd) (d, w, a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, w, ctx) && TEMPLATE(T, poly_equal) (t, a, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of t and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_xgcd) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd) (d, w, b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, w, ctx) && TEMPLATE(T, poly_equal) (t, b, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/test/t-xgcd_euclidean_f.c000066400000000000000000000500051461254215100240000ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, poly_xgcd_euclidean_f, state) { int i, result; /* Generic case, most likely co-prime arguments ***************************** */ /* Compare with result from GCD and check correctness */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, d, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest_reducible)(ctx, state, 3); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 30), ctx); TEMPLATE(T, poly_gcd_euclidean_f) (f1, d, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, g, s, t, a, b, ctx); if (!TEMPLATE(T, is_one) (f2, ctx) || !TEMPLATE(T, is_one) (f1, ctx)) { result = TEMPLATE(T, equal) (f1, f2, ctx); } else { TEMPLATE(T, poly_mul) (v, s, a, ctx); TEMPLATE(T, poly_mul) (w, t, b, ctx); TEMPLATE(T, poly_add) (w, v, w, ctx); result = (TEMPLATE(T, poly_equal) (d, g, ctx) && TEMPLATE(T, poly_equal) (g, w, ctx)); } if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, ctx_print) (ctx); TEMPLATE(T, print_pretty) (f1, ctx), flint_printf("\n\n"); TEMPLATE(T, print_pretty) (f2, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Special case, arguments share a factor ******************************* */ /* Compare with result from GCD and check correctness */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, d, f, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest_reducible)(ctx, state, 3); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (f, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, poly_randtest) (s, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (t, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 10), ctx); TEMPLATE(T, poly_randtest) (f, state, n_randint(state, 5), ctx); TEMPLATE(T, poly_mul) (a, a, f, ctx); TEMPLATE(T, poly_mul) (b, b, f, ctx); TEMPLATE(T, poly_gcd_euclidean_f) (f1, d, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, g, s, t, a, b, ctx); if (!TEMPLATE(T, is_one) (f2, ctx)) { result = TEMPLATE(T, equal) (f1, f2, ctx); } else { TEMPLATE(T, poly_mul) (v, s, a, ctx); TEMPLATE(T, poly_mul) (w, t, b, ctx); TEMPLATE(T, poly_add) (w, v, w, ctx); result = (TEMPLATE(T, poly_equal) (d, g, ctx) && TEMPLATE(T, poly_equal) (g, w, ctx)); } if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, print_pretty) (f1, ctx), flint_printf("\n\n"); TEMPLATE(T, print_pretty) (f2, ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (f, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx); flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx); flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (f, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of g and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f1, g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, a, v, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, v, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, a, ctx) && TEMPLATE(T, equal) (f1, f2, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of g and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, g, s, t, v, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (v, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f1, g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, b, v, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, v, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, b, ctx) && TEMPLATE(T, equal) (f1, f2, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (v, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (v, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of s and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f1, g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, d, a, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, a, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx) && TEMPLATE(T, equal) (f1, f2, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of s and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f1, g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, d, b, w, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, b, ctx) && TEMPLATE(T, poly_equal) (t, w, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx) && TEMPLATE(T, equal) (f1, f2, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of s and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f1, g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, d, w, a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, w, ctx) && TEMPLATE(T, poly_equal) (t, a, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx) && TEMPLATE(T, equal) (f1, f2, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* test aliasing of t and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f1, f2; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); TEMPLATE(T, poly_init) (d, ctx); TEMPLATE(T, poly_init) (w, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f1, g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean_f) (f2, d, w, b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (s, w, ctx) && TEMPLATE(T, poly_equal) (t, b, ctx) && TEMPLATE(T, poly_equal) (g, d, ctx) && TEMPLATE(T, equal) (f1, f2, ctx)); if (!result) { flint_printf("FAIL:\n"); TEMPLATE(T, poly_print_pretty) (a, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (s, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (t, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (d, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (w, "x", ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); TEMPLATE(T, poly_clear) (d, ctx); TEMPLATE(T, poly_clear) (w, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_poly_templates/tree.c000066400000000000000000000065231461254215100202620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" TEMPLATE(T, poly_struct) ** _TEMPLATE(T, poly_tree_alloc)(slong len, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, poly_struct) ** tree = NULL; if (len) { slong i, j, height = FLINT_CLOG2(len); tree = flint_malloc(sizeof(TEMPLATE(T, poly_struct) *) * (height + 1)); for (i = 0; i <= height; i++, len = (len + 1)/2) { tree[i] = flint_malloc(sizeof(TEMPLATE(T, poly_struct)) * len); for (j = 0; j < len; j++) TEMPLATE(T, poly_init)(tree[i] + j, ctx); } } return tree; } void _TEMPLATE(T, poly_tree_free)(TEMPLATE(T, poly_struct) ** tree, slong len, const TEMPLATE(T, ctx_t) ctx) { if (len) { slong i, j, height = FLINT_CLOG2(len); for (i = 0; i <= height; i++, len = (len + 1)/2) { for (j = 0; j < len; j++) TEMPLATE(T, poly_clear)(tree[i] + j, ctx); flint_free(tree[i]); } flint_free(tree); } } void _TEMPLATE(T, poly_tree_build)(TEMPLATE(T, poly_struct) ** tree, const TEMPLATE(T, struct) * roots, slong len, const TEMPLATE(T, ctx_t) ctx) { slong height, pow, left, i; TEMPLATE(T, poly_struct) * pa, * pb; if (len == 0) return; height = FLINT_CLOG2(len); /* zeroth level, (x-a) */ for (i = 0; i < len; i++) { TEMPLATE(T, poly_gen)(tree[0] + i, ctx); TEMPLATE(T, neg)((tree[0] + i)->coeffs, roots + i, ctx); } for (i = 0; i < height - 1; i++) { left = len; pow = WORD(1) << i; pa = tree[i]; pb = tree[i + 1]; while (left >= 2 * pow) { TEMPLATE(T, poly_fit_length)(pb, pa->length + (pa + 1)->length - 1, ctx); _TEMPLATE(T, poly_mul)(pb->coeffs, pa->coeffs, pa->length, (pa + 1)->coeffs, (pa + 1)->length, ctx); _TEMPLATE(T, poly_set_length)(pb, pa->length + (pa + 1)->length - 1, ctx); left -= 2 * pow; pa += 2; pb += 1; } if (left > pow) { TEMPLATE(T, poly_fit_length)(pb, pa->length + (pa + 1)->length - 1, ctx); _TEMPLATE(T, poly_mul)(pb->coeffs, pa->coeffs, pa->length, (pa + 1)->coeffs, (pa + 1)->length, ctx); _TEMPLATE(T, poly_set_length)(pb, pa->length + (pa + 1)->length - 1, ctx); } else if (left > 0) TEMPLATE(T, poly_set)(pb, pa, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/truncate.c000066400000000000000000000015421461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, poly_truncate) (TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx) { if (poly->length > len) { slong i; for (i = len; i < poly->length; i++) TEMPLATE(T, zero) (poly->coeffs + i, ctx); poly->length = len; _TEMPLATE(T, poly_normalise) (poly, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/xgcd.c000066400000000000000000000133151461254215100202450ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include "gr_poly.h" /* todo: the gr method don't accept the precomputed inverse */ slong _TEMPLATE(T, poly_xgcd) (TEMPLATE(T, struct) * G, TEMPLATE(T, struct) * S, TEMPLATE(T, struct) * T, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, ctx_t) ctx) { gr_ctx_t gr_ctx; slong cutoff; slong lenG; #if defined(FQ_NMOD_POLY_H) || defined(FQ_ZECH_POLY_H) if (FLINT_BIT_COUNT(TEMPLATE(T, ctx_prime)(ctx)) <= 8) #else if (fmpz_bits(TEMPLATE(T, ctx_prime)(ctx)) <= 8) #endif cutoff = TEMPLATE(CAP_T, POLY_SMALL_GCD_CUTOFF); else cutoff = TEMPLATE(CAP_T, POLY_GCD_CUTOFF); TEMPLATE3(_gr_ctx_init, T, from_ref)(gr_ctx, ctx); if (FLINT_MIN(lenA, lenB) < cutoff) GR_MUST_SUCCEED(_gr_poly_xgcd_euclidean(&lenG, G, S, T, A, lenA, B, lenB, gr_ctx)); else GR_MUST_SUCCEED(_gr_poly_xgcd_hgcd(&lenG, G, S, T, A, lenA, B, lenB, TEMPLATE(CAP_T, POLY_HGCD_CUTOFF), cutoff, gr_ctx)); return lenG; } void TEMPLATE(T, poly_xgcd) (TEMPLATE(T, poly_t) G, TEMPLATE(T, poly_t) S, TEMPLATE(T, poly_t) T, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { if (A->length < B->length) { TEMPLATE(T, poly_xgcd) (G, T, S, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; TEMPLATE(T, t) inv; TEMPLATE(T, init) (inv, ctx); if (lenA == 0) /* lenA = lenB = 0 */ { TEMPLATE(T, poly_zero) (G, ctx); TEMPLATE(T, poly_zero) (S, ctx); TEMPLATE(T, poly_zero) (T, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { TEMPLATE(T, inv) (inv, TEMPLATE(T, poly_lead) (A, ctx), ctx); TEMPLATE3(T, poly_scalar_mul, T) (G, A, inv, ctx); TEMPLATE(T, poly_zero) (T, ctx); TEMPLATE3(T, poly_set, T) (S, inv, ctx); } else if (lenB == 1) /* lenA >= lenB = 1 */ { TEMPLATE(T, inv)(inv, B->coeffs + 0, ctx); TEMPLATE3(T, poly_set, T) (T, inv, ctx); TEMPLATE(T, poly_one)(G, ctx); TEMPLATE(T, poly_zero)(S, ctx); } else /* lenA >= lenB >= 2 */ { TEMPLATE(T, struct) * g, *s, *t; slong lenG; if (G == A || G == B) { g = _TEMPLATE(T, vec_init) (FLINT_MIN(lenA, lenB), ctx); } else { TEMPLATE(T, poly_fit_length) (G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = _TEMPLATE(T, vec_init) (lenB, ctx); } else { TEMPLATE(T, poly_fit_length) (S, lenB, ctx); s = S->coeffs; } if (T == A || T == B) { t = _TEMPLATE(T, vec_init) (lenA, ctx); } else { TEMPLATE(T, poly_fit_length) (T, lenA, ctx); t = T->coeffs; } TEMPLATE(T, inv) (inv, TEMPLATE(T, poly_lead) (B, ctx), ctx); lenG = _TEMPLATE(T, poly_xgcd) (g, s, t, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _TEMPLATE(T, vec_clear) (G->coeffs, G->alloc, ctx); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = G->alloc; } if (S == A || S == B) { _TEMPLATE(T, vec_clear) (S->coeffs, S->alloc, ctx); S->coeffs = s; S->alloc = lenB; S->length = S->alloc; } if (T == A || T == B) { _TEMPLATE(T, vec_clear) (T->coeffs, T->alloc, ctx); T->coeffs = t; T->alloc = lenA; T->length = T->alloc; } _TEMPLATE(T, poly_set_length) (G, lenG, ctx); _TEMPLATE(T, poly_set_length) (S, FLINT_MAX(lenB - lenG, 1), ctx); _TEMPLATE(T, poly_set_length) (T, FLINT_MAX(lenA - lenG, 1), ctx); _TEMPLATE(T, poly_normalise) (S, ctx); _TEMPLATE(T, poly_normalise) (T, ctx); if (!TEMPLATE(T, is_one) (TEMPLATE(T, poly_lead) (G, ctx), ctx)) { TEMPLATE(T, inv) (inv, TEMPLATE(T, poly_lead) (G, ctx), ctx); TEMPLATE3(T, poly_scalar_mul, T) (G, G, inv, ctx); TEMPLATE3(T, poly_scalar_mul, T) (S, S, inv, ctx); TEMPLATE3(T, poly_scalar_mul, T) (T, T, inv, ctx); } } TEMPLATE(T, clear) (inv, ctx); } } #endif flint-3.1.3/src/fq_poly_templates/xgcd_euclidean_f.c000066400000000000000000000222041461254215100225600ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong _TEMPLATE(T, poly_xgcd_euclidean_f) (TEMPLATE(T, t) f, TEMPLATE(T, struct) * G, TEMPLATE(T, struct) * S, TEMPLATE(T, struct) * T, const TEMPLATE(T, struct) * A, slong lenA, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, ctx_t) ctx) { slong lenG; _TEMPLATE(T, vec_zero) (G, lenB, ctx); _TEMPLATE(T, vec_zero) (S, lenB - 1, ctx); _TEMPLATE(T, vec_zero) (T, lenA - 1, ctx); if (lenB == 1) { TEMPLATE(T, t) invB; TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, gcdinv) (f, invB, B, ctx); if (TEMPLATE(T, is_one) (f, ctx)) { TEMPLATE(T, one) (G, ctx); TEMPLATE(T, set) (T + 0, invB, ctx); lenG = 1; } else { lenG = 0; } TEMPLATE(T, clear) (invB, ctx); return lenG; } else { TEMPLATE(T, struct) * Q, *R; slong lenQ, lenR; Q = _TEMPLATE(T, vec_init) (2 * lenA, ctx); R = Q + lenA; _TEMPLATE(T, poly_divrem_f) (f, Q, R, A, lenA, B, lenB, ctx); if (!TEMPLATE(T, is_one) (f, ctx)) { _TEMPLATE(T, vec_clear) (Q, 2 * lenA, ctx); return 0; } lenR = lenB - 1; TEMPLATE(CAP_T, VEC_NORM) (R, lenR, ctx); if (lenR == 0) { _TEMPLATE(T, vec_set) (G, B, lenB, ctx); TEMPLATE(T, one) (T + 0, ctx); _TEMPLATE(T, vec_clear) (Q, 2 * lenA, ctx); return lenB; } else { TEMPLATE(T, struct) * D, *U, *V1, *V3, *W; slong lenD, lenU, lenV1, lenV3, lenW; W = _TEMPLATE(T, vec_init) (FLINT_MAX(5 * lenB, lenA + lenB), ctx); D = W + lenB; U = D + lenB; V1 = U + lenB; V3 = V1 + lenB; lenU = 0; _TEMPLATE(T, vec_set) (D, B, lenB, ctx); lenD = lenB; TEMPLATE(T, one) (V1 + 0, ctx); lenV1 = 1; lenV3 = 0; TEMPLATE(CAP_T, VEC_SWAP) (V3, lenV3, R, lenR); do { _TEMPLATE(T, poly_divrem_f) (f, Q, R, D, lenD, V3, lenV3, ctx); if (!TEMPLATE(T, is_one) (f, ctx)) goto exit; lenQ = lenD - lenV3 + 1; lenR = lenV3 - 1; TEMPLATE(CAP_T, VEC_NORM) (R, lenR, ctx); if (lenV1 >= lenQ) _TEMPLATE(T, poly_mul) (W, V1, lenV1, Q, lenQ, ctx); else _TEMPLATE(T, poly_mul) (W, Q, lenQ, V1, lenV1, ctx); lenW = lenQ + lenV1 - 1; _TEMPLATE(T, poly_sub) (U, U, lenU, W, lenW, ctx); lenU = FLINT_MAX(lenU, lenW); TEMPLATE(CAP_T, VEC_NORM) (U, lenU, ctx); TEMPLATE(CAP_T, VEC_SWAP) (U, lenU, V1, lenV1); { TEMPLATE(T, struct) * __t; slong __tn; __t = D; D = V3; V3 = R; R = __t; __tn = lenD; lenD = lenV3; lenV3 = lenR; lenR = __tn; } } while (lenV3 != 0); _TEMPLATE(T, vec_set) (G, D, lenD, ctx); _TEMPLATE(T, vec_set) (S, U, lenU, ctx); { lenQ = lenA + lenU - 1; _TEMPLATE(T, poly_mul) (Q, A, lenA, S, lenU, ctx); _TEMPLATE(T, poly_neg) (Q, Q, lenQ, ctx); _TEMPLATE(T, poly_add) (Q, G, lenD, Q, lenQ, ctx); _TEMPLATE(T, poly_divrem_f) (f, T, W, Q, lenQ, B, lenB, ctx); } exit: _TEMPLATE(T, vec_clear) (W, FLINT_MAX(5 * lenB, lenA + lenB), ctx); _TEMPLATE(T, vec_clear) (Q, 2 * lenA, ctx); return lenD; } } } void TEMPLATE(T, poly_xgcd_euclidean_f) (TEMPLATE(T, t) f, TEMPLATE(T, poly_t) G, TEMPLATE(T, poly_t) S, TEMPLATE(T, poly_t) T, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx) { if (A->length < B->length) { TEMPLATE(T, poly_xgcd_euclidean_f) (f, G, T, S, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; if (lenA == 0) /* lenA = lenB = 0 */ { TEMPLATE(T, one) (f, ctx); TEMPLATE(T, poly_zero) (G, ctx); TEMPLATE(T, poly_zero) (S, ctx); TEMPLATE(T, poly_zero) (T, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { TEMPLATE(T, t) invA; TEMPLATE(T, init) (invA, ctx); TEMPLATE(T, gcdinv) (f, invA, A->coeffs + lenA - 1, ctx); if (TEMPLATE(T, is_one) (f, ctx)) { TEMPLATE3(T, poly_scalar_mul, T) (G, A, invA, ctx); TEMPLATE(T, poly_zero) (T, ctx); TEMPLATE3(T, poly_set, T) (S, invA, ctx); } else { TEMPLATE(T, poly_zero) (G, ctx); } TEMPLATE(T, clear) (invA, ctx); } else if (lenB == 1) /* lenA >= lenB = 1 */ { TEMPLATE(T, t) invB; TEMPLATE(T, init)(invB, ctx); TEMPLATE(T, gcdinv)(f, invB, B->coeffs + 0, ctx); TEMPLATE3(T, poly_set, T) (T, invB, ctx); TEMPLATE(T, poly_one)(G, ctx); TEMPLATE(T, poly_zero)(S, ctx); TEMPLATE(T, clear)(invB, ctx); } else /* lenA >= lenB >= 2 */ { TEMPLATE(T, struct) * g, *s, *t; slong lenG; if (G == A || G == B) { g = _TEMPLATE(T, vec_init) (FLINT_MIN(lenA, lenB), ctx); } else { TEMPLATE(T, poly_fit_length) (G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = _TEMPLATE(T, vec_init) (lenB, ctx); } else { TEMPLATE(T, poly_fit_length) (S, lenB, ctx); s = S->coeffs; } if (T == A || T == B) { t = _TEMPLATE(T, vec_init) (lenA, ctx); } else { TEMPLATE(T, poly_fit_length) (T, lenA, ctx); t = T->coeffs; } lenG = _TEMPLATE(T, poly_xgcd_euclidean_f) (f, g, s, t, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _TEMPLATE(T, vec_clear) (G->coeffs, G->alloc, ctx); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = G->alloc; } if (S == A || S == B) { _TEMPLATE(T, vec_clear) (S->coeffs, S->alloc, ctx); S->coeffs = s; S->alloc = lenB; S->length = S->alloc; } if (T == A || T == B) { _TEMPLATE(T, vec_clear) (T->coeffs, T->alloc, ctx); T->coeffs = t; T->alloc = lenA; T->length = T->length; } _TEMPLATE(T, poly_set_length) (G, lenG, ctx); _TEMPLATE(T, poly_set_length) (S, FLINT_MAX(lenB - lenG, 1), ctx); _TEMPLATE(T, poly_set_length) (T, FLINT_MAX(lenA - lenG, 1), ctx); _TEMPLATE(T, poly_normalise) (S, ctx); _TEMPLATE(T, poly_normalise) (T, ctx); if (TEMPLATE(T, is_one) (f, ctx)) { if (!TEMPLATE(T, is_one) (TEMPLATE(T, poly_lead) (G, ctx), ctx)) { TEMPLATE(T, t) inv; TEMPLATE(T, init) (inv, ctx); TEMPLATE(T, inv) (inv, TEMPLATE(T, poly_lead) (G, ctx), ctx); TEMPLATE3(T, poly_scalar_mul, T) (G, G, inv, ctx); TEMPLATE3(T, poly_scalar_mul, T) (S, S, inv, ctx); TEMPLATE3(T, poly_scalar_mul, T) (T, T, inv, ctx); TEMPLATE(T, clear) (inv, ctx); } } } } } #endif flint-3.1.3/src/fq_poly_templates/zero.c000066400000000000000000000015141461254215100202750ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_zero)(TEMPLATE(T, struct) *rop, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) TEMPLATE(T, zero)(rop + i, ctx); } void TEMPLATE(T, poly_zero)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { _TEMPLATE(T, poly_set_length)(poly, 0, ctx); } #endif flint-3.1.3/src/fq_templates.h000066400000000000000000000032671461254215100162670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, gcdinv)(TEMPLATE(T, t) rop, TEMPLATE(T, t) inv, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, is_invertible)(const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, is_invertible_f)(TEMPLATE(T, t) rop, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE(T, div)(TEMPLATE(T, t) rop, const TEMPLATE(T, t) op1, const TEMPLATE(T, t) op2, const TEMPLATE(T, ctx_t) ctx); int TEMPLATE(T, multiplicative_order)(fmpz * ord, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); #ifdef B void TEMPLATE4(T, get, B, mat)(TEMPLATE(B, mat_t) col, const TEMPLATE(T, t) a, const TEMPLATE(T, ctx_t) ctx); void TEMPLATE4(T, set, B, mat)(TEMPLATE(T, t) a, const TEMPLATE(B, mat_t) col, const TEMPLATE(T, ctx_t) ctx); #endif FQ_TEMPLATES_INLINE int TEMPLATE(T, is_primitive)(const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx) { int ret; ret = TEMPLATE(T, multiplicative_order)(NULL, op, ctx) == 1; return ret; } #endif flint-3.1.3/src/fq_templates/000077500000000000000000000000001461254215100161065ustar00rootroot00000000000000flint-3.1.3/src/fq_templates/div.c000066400000000000000000000013361461254215100170370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, div)(TEMPLATE(T, t) rop, const TEMPLATE(T, t) op1, const TEMPLATE(T, t) op2, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) inv; TEMPLATE(T, init)(inv, ctx); TEMPLATE(T, inv)(inv, op2, ctx); TEMPLATE(T, mul)(rop, op1, inv, ctx); TEMPLATE(T, clear)(inv, ctx); } #endif flint-3.1.3/src/fq_templates/is_invertible.c000066400000000000000000000011031461254215100211030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, is_invertible)(const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx) { return !TEMPLATE(T, is_zero)(op, ctx); } #endif flint-3.1.3/src/fq_templates/is_invertible_f.c000066400000000000000000000013411461254215100214140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, is_invertible_f)(TEMPLATE(T, t) rop, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) inv; TEMPLATE(T, init)(inv, ctx); TEMPLATE(T, gcdinv)(rop, inv, op, ctx); TEMPLATE(T, clear)(inv, ctx); return TEMPLATE(T, is_one)(rop, ctx); } #endif flint-3.1.3/src/fq_templates/is_square.c000066400000000000000000000024531461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, is_square)(const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx) { fmpz_t ord; TEMPLATE(T, t) pow; int is_square = 0; #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) if (TEMPLATE(T, is_zero)(op, ctx) || TEMPLATE(T, is_one)(op, ctx) || TEMPLATE(T, ctx_prime)(ctx) == 2) #else if (TEMPLATE(T, is_zero)(op, ctx) || TEMPLATE(T, is_one)(op, ctx) || fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0) #endif { return 1; } fmpz_init(ord); TEMPLATE(T, init)(pow, ctx); TEMPLATE(T, ctx_order)(ord, ctx); fmpz_sub_ui(ord, ord, 1); fmpz_tdiv_q_2exp(ord, ord, 1); TEMPLATE(T, pow)(pow, op, ord, ctx); is_square = TEMPLATE(T, is_one)(pow, ctx); fmpz_clear(ord); TEMPLATE(T, clear)(pow, ctx); return is_square; } #endif flint-3.1.3/src/fq_templates/multiplicative_order.c000066400000000000000000000031161461254215100225010ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, multiplicative_order)(fmpz * ord, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx) { fmpz_t tmp; fmpz_factor_t ord_fact; TEMPLATE(T, t) one; slong i, j; int is_primitive = 1; if (ord == NULL) ord = tmp; fmpz_init(tmp); if (TEMPLATE(T, is_zero)(op, ctx)) { fmpz_zero(ord); is_primitive = 0; } else { fmpz_factor_init(ord_fact); TEMPLATE(T, init)(one, ctx); TEMPLATE(T, ctx_order)(ord, ctx); fmpz_sub_ui(ord, ord, 1); fmpz_factor(ord_fact, ord); for (i = 0; i < ord_fact->num; i++) { for (j = ord_fact->exp[i]; j > 0; j--) { fmpz_cdiv_q(ord, ord, ord_fact->p + i); TEMPLATE(T, pow)(one, op, ord, ctx); if (!TEMPLATE(T, is_one)(one, ctx)) break; is_primitive = -1; } if (j > 0) fmpz_mul(ord, ord, ord_fact->p + i); } fmpz_factor_clear(ord_fact); TEMPLATE(T, clear)(one, ctx); } fmpz_clear(tmp); return is_primitive; } #endif flint-3.1.3/src/fq_templates/sqrt.c000066400000000000000000000060721461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart Copyright (C) 2024 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, sqrt)(TEMPLATE(T, t) rop, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx) { int res = 1; if (TEMPLATE(T, is_zero)(op, ctx) || TEMPLATE(T, is_one)(op, ctx)) TEMPLATE(T, set)(rop, op, ctx); #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) else if (TEMPLATE(T, ctx_prime)(ctx) == 2) #else else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0) #endif TEMPLATE(T, pth_root)(rop, op, ctx); else { TEMPLATE(T, t) z, c, t, b, temp; fmpz_t ord, Q, Q2; flint_bitcnt_t S; slong M, i, j; TEMPLATE(T, init)(z, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(t, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(temp, ctx); fmpz_init(ord); fmpz_init(Q); fmpz_init(Q2); if (ctx->is_conway) TEMPLATE(T, gen)(z, ctx); else { flint_rand_t state; flint_randinit(state); while (TEMPLATE(T, is_square)(z, ctx)) TEMPLATE(T, rand)(z, state, ctx); flint_randclear(state); } TEMPLATE(T, ctx_order)(ord, ctx); fmpz_sub_ui(ord, ord, 1); S = fmpz_val2(ord); fmpz_tdiv_q_2exp(Q, ord, S); fmpz_add_ui(Q2, Q, 1); fmpz_tdiv_q_2exp(Q2, Q2, 1); M = S; TEMPLATE(T, pow)(c, z, Q, ctx); TEMPLATE(T, pow)(t, op, Q, ctx); TEMPLATE(T, pow)(rop, op, Q2, ctx); while (1) { if (TEMPLATE(T, is_zero)(t, ctx)) { TEMPLATE(T, zero)(rop, ctx); break; } if (TEMPLATE(T, is_one)(t, ctx)) break; i = 1; TEMPLATE(T, sqr)(temp, t, ctx); while (i < M && !TEMPLATE(T, is_one)(temp, ctx)) { TEMPLATE(T, sqr)(temp, temp, ctx); i++; } if (i == M) { res = 0; break; } TEMPLATE(T, set)(b, c, ctx); for (j = 0; j < M - i - 1; j++) TEMPLATE(T, sqr)(b, b, ctx); M = i; TEMPLATE(T, sqr)(c, b, ctx); TEMPLATE(T, mul)(t, t, c, ctx); TEMPLATE(T, mul)(rop, rop, b, ctx); } fmpz_clear(Q2); fmpz_clear(Q); fmpz_clear(ord); TEMPLATE(T, clear)(temp, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(t, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, clear)(z, ctx); } return res; } #endif flint-3.1.3/src/fq_templates/test/000077500000000000000000000000001461254215100170655ustar00rootroot00000000000000flint-3.1.3/src/fq_templates/test/t-add.c000066400000000000000000000072471461254215100202340ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, add, state) { slong ix; int result; #if defined(FQ_ZECH_H) for (ix = 0; ix < 10 * flint_test_multiplier(); ix++) #else for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) #endif { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c, x, y; int type; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); #if defined(FQ_ZECH_H) for (slong jx = 0; jx < 100; jx++) { #endif type = n_randint(state, 5); TEMPLATE(T, init)(a, ctx); if (type != 2) TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); if (type >= 3) TEMPLATE(T, init)(x, ctx); if (type == 4) TEMPLATE(T, init)(y, ctx); TEMPLATE(T, randtest)(a, state, ctx); if (type != 2) TEMPLATE(T, randtest)(b, state, ctx); if (type == 0) { /* Check aliasing: a = a + b */ TEMPLATE(T, add)(c, a, b, ctx); TEMPLATE(T, add)(a, a, b, ctx); } else if (type == 1) { /* Check aliasing: b = a + b */ TEMPLATE(T, add)(c, b, a, ctx); TEMPLATE(T, add)(a, b, a, ctx); } else if (type == 2) { /* Check aliasing: a = a + a */ TEMPLATE(T, add)(c, a, a, ctx); TEMPLATE(T, add)(a, a, a, ctx); } else if (type == 3) { /* Check that a + b == b + a */ TEMPLATE(T, add)(c, a, b, ctx); TEMPLATE(T, add)(x, b, a, ctx); FLINT_SWAP(TEMPLATE(T, struct), *a, *x); } else { /* Check that (a + b) + c == a + (b + c) */ TEMPLATE(T, randtest)(c, state, ctx); TEMPLATE(T, add)(x, a, b, ctx); TEMPLATE(T, add)(x, x, c, ctx); TEMPLATE(T, add)(y, b, c, ctx); TEMPLATE(T, add)(y, a, y, ctx); FLINT_SWAP(TEMPLATE(T, struct), *a, *x); FLINT_SWAP(TEMPLATE(T, struct), *c, *y); } result = (TEMPLATE(T, equal)(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("type = %d\n", type); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); if (type != 2) flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); if (type >= 3) flint_printf("x = "), TEMPLATE(T, print_pretty)(x, ctx), flint_printf("\n"); if (type == 4) flint_printf("y = "), TEMPLATE(T, print_pretty)(y, ctx), flint_printf("\n"); flint_abort(); } TEMPLATE(T, clear)(a, ctx); if (type != 2) TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); if (type >= 3) TEMPLATE(T, clear)(x, ctx); if (type == 4) TEMPLATE(T, clear)(y, ctx); #if defined(FQ_ZECH_H) } #endif TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-assign.c000066400000000000000000000017501461254215100207610ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, assign, state) { int i; /* Check that gen does not segfault */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) x; #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 2); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); #endif TEMPLATE(T, init)(x, ctx); TEMPLATE(T, gen)(x, ctx); TEMPLATE(T, clear)(x, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-ctx_init.c000066400000000000000000000070031461254215100213130ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" #include "ulong_extras.h" TEST_TEMPLATE_FUNCTION_START(T, ctx_init, state) { int i, k, result; for (i = 0; i < 3 * flint_test_multiplier(); i++) { #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) ulong p; #else fmpz_t p; #endif slong d; TEMPLATE(T, ctx_t) ctx; #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) p = n_randprime(state, 2 + n_randint(state, FLINT_MIN(FLINT_BITS - 1, 50)), 1); #else fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, FLINT_MIN(FLINT_BITS - 1, 50)), 1)); #endif d = n_randint(state, 20) + 1; #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_ui)(ctx, p, d, "a"); #else TEMPLATE(T, ctx_init)(ctx, p, d, "a"); #endif TEMPLATE(T, ctx_clear)(ctx); } for (i = 0; i < 3 * flint_test_multiplier(); i++) { #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) ulong p; #else fmpz_t p; #endif slong d; TEMPLATE(T, ctx_t) ctx_conway, ctx_mod; TEMPLATE(T, t) a, b, lhs, rhs; #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) p = n_randprime(state, 2 + n_randint(state, 3), 1); #else fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); #endif d = n_randint(state, 10) + 1; #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_conway_ui)(ctx_conway, p, d, "a"); #else TEMPLATE(T, ctx_init_conway)(ctx_conway, p, d, "a"); #endif #ifdef FQ_H TEMPLATE(T, ctx_init_modulus)(ctx_mod, ctx_conway->modulus, ctx_conway->ctxp, "a"); #else TEMPLATE(T, ctx_init_modulus)(ctx_mod, ctx_conway->modulus, "a"); #endif TEMPLATE(T, init)(a, ctx_conway); TEMPLATE(T, init)(b, ctx_mod); TEMPLATE(T, init)(lhs, ctx_conway); TEMPLATE(T, init)(rhs, ctx_mod); for (k = 0; k < 30; k++) { TEMPLATE(T, randtest)(a, state, ctx_conway); TEMPLATE(T, set)(b, a, ctx_mod); TEMPLATE(T, mul)(lhs, a, a, ctx_conway); TEMPLATE(T, mul)(rhs, b, b, ctx_mod); result = (TEMPLATE(T, equal)(lhs, rhs, ctx_mod)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx_conway), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx_mod), flint_printf("\n"); flint_printf("lhs = "), TEMPLATE(T, print_pretty)(lhs, ctx_conway), flint_printf("\n"); flint_printf("rhs = "), TEMPLATE(T, print_pretty)(rhs, ctx_mod), flint_printf("\n"); fflush(stdout); flint_abort(); } } TEMPLATE(T, clear)(a, ctx_conway); TEMPLATE(T, clear)(b, ctx_mod); TEMPLATE(T, clear)(lhs, ctx_conway); TEMPLATE(T, clear)(rhs, ctx_mod); TEMPLATE(T, ctx_clear)(ctx_conway); TEMPLATE(T, ctx_clear)(ctx_mod); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-div.c000066400000000000000000000035661461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, div, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c, d; #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); #endif TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(d, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest_not_zero)(b, state, ctx); TEMPLATE(T, div)(c, a, b, ctx); TEMPLATE(T, mul)(d, c, b, ctx); result = (TEMPLATE(T, equal)(a, d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, print_pretty)(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, clear)(d, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-frobenius.c000066400000000000000000000166721461254215100215020ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, frobenius, state) { int i, result; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; slong e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, set)(b, a, ctx); e = n_randint(state, 10) % TEMPLATE(T, ctx_degree)(ctx); TEMPLATE(T, frobenius)(c, b, e, ctx); TEMPLATE(T, frobenius)(b, b, e, ctx); result = (TEMPLATE(T, equal)(b, c, ctx)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check sigma^e(x) == x^{p^e} */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; slong e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); e = n_randint(state, 10) % TEMPLATE(T, ctx_degree)(ctx); TEMPLATE(T, frobenius)(b, a, e, ctx); { fmpz_t t; fmpz_init(t); #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) fmpz_ui_pow_ui(t, TEMPLATE(T, ctx_prime)(ctx), e); #else fmpz_pow_ui(t, TEMPLATE(T, ctx_prime)(ctx), e); #endif TEMPLATE(T, pow)(c, a, t, ctx); fmpz_clear(t); } result = (TEMPLATE(T, equal)(b,c,ctx)); if (!result) { flint_printf("FAIL (sigma^e(x) = x^{p^e}):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check sigma^e(x + y) = sigma^e(x) + sigma^e(y) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, s, s1, s2, lhs, rhs; slong e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(s, ctx); TEMPLATE(T, init)(s1, ctx); TEMPLATE(T, init)(s2, ctx); TEMPLATE(T, init)(lhs, ctx); TEMPLATE(T, init)(rhs, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); e = n_randint(state, 10) % TEMPLATE(T, ctx_degree)(ctx); TEMPLATE(T, add)(s, a, b, ctx); TEMPLATE(T, frobenius)(lhs, s, e, ctx); TEMPLATE(T, frobenius)(s1, a, e, ctx); TEMPLATE(T, frobenius)(s2, b, e, ctx); TEMPLATE(T, add)(rhs, s1, s2, ctx); result = (TEMPLATE(T, equal)(lhs, rhs, ctx)); if (!result) { flint_printf("FAIL (sigma(a+b) = sigma(a) + sigma(b)):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("s = "), TEMPLATE(T, print_pretty)(s, ctx), flint_printf("\n"); flint_printf("s1 = "), TEMPLATE(T, print_pretty)(s1, ctx), flint_printf("\n"); flint_printf("s2 = "), TEMPLATE(T, print_pretty)(s2, ctx), flint_printf("\n"); flint_printf("lhs = "), TEMPLATE(T, print_pretty)(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), TEMPLATE(T, print_pretty)(rhs, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(s, ctx); TEMPLATE(T, clear)(s1, ctx); TEMPLATE(T, clear)(s2, ctx); TEMPLATE(T, clear)(lhs, ctx); TEMPLATE(T, clear)(rhs, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check sigma^e(x * y) = sigma^e(x) * sigma^e(y) on Zq */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, s, s1, s2, lhs, rhs; slong e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(s, ctx); TEMPLATE(T, init)(s1, ctx); TEMPLATE(T, init)(s2, ctx); TEMPLATE(T, init)(lhs, ctx); TEMPLATE(T, init)(rhs, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); e = n_randint(state, 10) % TEMPLATE(T, ctx_degree)(ctx); TEMPLATE(T, mul)(s, a, b, ctx); TEMPLATE(T, frobenius)(lhs, s, e, ctx); TEMPLATE(T, frobenius)(s1, a, e, ctx); TEMPLATE(T, frobenius)(s2, b, e, ctx); TEMPLATE(T, mul)(rhs, s1, s2, ctx); result = (TEMPLATE(T, equal)(lhs, rhs, ctx)); if (!result) { flint_printf("FAIL (sigma(a*b) = sigma(a) * sigma(b)):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("s = "), TEMPLATE(T, print_pretty)(s, ctx), flint_printf("\n"); flint_printf("s1 = "), TEMPLATE(T, print_pretty)(s1, ctx), flint_printf("\n"); flint_printf("s2 = "), TEMPLATE(T, print_pretty)(s2, ctx), flint_printf("\n"); flint_printf("lhs = "), TEMPLATE(T, print_pretty)(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), TEMPLATE(T, print_pretty)(rhs, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(s, ctx); TEMPLATE(T, clear)(s1, ctx); TEMPLATE(T, clear)(s2, ctx); TEMPLATE(T, clear)(lhs, ctx); TEMPLATE(T, clear)(rhs, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-get_set_fmpz.c000066400000000000000000000036201461254215100221610ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, get_set_fmpz, state) { slong ix, jx; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b; fmpz_t s, t; #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); #endif TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); fmpz_init(s); fmpz_init(t); for (jx = 0; jx < 100 * flint_test_multiplier(); jx++) { TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); fmpz_randbits(t, state, 100); TEMPLATE(T, set_fmpz)(a, t, ctx); FLINT_TEST(TEMPLATE(T, get_fmpz)(s, a, ctx)); fmpz_sub(t, t, s); #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) FLINT_TEST(fmpz_divisible_ui(t, TEMPLATE(T, ctx_prime(ctx)))); #else FLINT_TEST(fmpz_divisible(t, TEMPLATE(T, ctx_prime(ctx)))); #endif if (TEMPLATE(T, get_fmpz(t, a, ctx))) { TEMPLATE(T, set_fmpz(b, t, ctx)); FLINT_TEST(TEMPLATE(T, equal)(a, b, ctx)); } } fmpz_clear(s); fmpz_clear(t); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-inv.c000066400000000000000000000054401461254215100202710ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, inv, state) { int i, result; /* Check aliasing: a = ~a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest_not_zero)(a, state, ctx); TEMPLATE(T, set)(b, a, ctx); TEMPLATE(T, inv)(c, b, ctx); TEMPLATE(T, inv)(b, b, ctx); result = (TEMPLATE(T, equal)(b, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); TEMPLATE(T, ctx_print)(ctx); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check a * ~a == 1 for units*/ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest_not_zero)(a, state, ctx); TEMPLATE(T, inv)(b, a, ctx); TEMPLATE(T, mul)(c, a, b, ctx); result = (TEMPLATE(T, is_one)(c, ctx)); if (!result) { flint_printf("FAIL (a * (~a) == 1):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-is_invertible.c000066400000000000000000000024521461254215100223330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, is_invertible, state) { slong ix; int result; for (ix = 0; ix < 300 * flint_test_multiplier(); ix++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a; #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); #endif TEMPLATE(T, init)(a, ctx); TEMPLATE(T, randtest)(a, state, ctx); result = (TEMPLATE(T, is_invertible)(a, ctx) != TEMPLATE(T, is_zero)(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); TEMPLATE(T, ctx_print)(ctx); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-is_invertible_f.c000066400000000000000000000040341461254215100226360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, is_invertible_f, state) { slong ix; int result; /* Compare with the gcdinv function. N.B. I checked by hand that this test shows both outcomes, i.e. trivial and non-trivial factors, sufficiently frequently. */ for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, ainv, f, g; #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest_reducible)(ctx, state, 1); #else TEMPLATE(T, ctx_init_randtest_reducible)(ctx, state, 0); #endif TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(f, ctx); TEMPLATE(T, init)(g, ctx); TEMPLATE(T, init)(ainv, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, gcdinv)(f, ainv, a, ctx); result = (TEMPLATE(T, is_one)(f, ctx) == TEMPLATE(T, is_invertible_f)(g, a, ctx)); result = result && TEMPLATE(T, equal)(f, g, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx); flint_printf("\n\n"); flint_printf("f = "), TEMPLATE(T, print_pretty)(f, ctx); flint_printf("\n\n"); flint_printf("g = "), TEMPLATE(T, print_pretty)(g, ctx); flint_printf("\n\n"); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(ainv, ctx); TEMPLATE(T, clear)(f, ctx); TEMPLATE(T, clear)(g, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-is_primitive.c000066400000000000000000000030721461254215100221770ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, is_primitive, state) { int i; /* Test that is_primitive gives consistent answers with multiplicative_order */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a; fmpz_t ord, field_ord; TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, randtest)(a, state, ctx); fmpz_init(ord); fmpz_init(field_ord); TEMPLATE(T, multiplicative_order)(ord, a, ctx); TEMPLATE(T, ctx_order)(field_ord, ctx); fmpz_sub(field_ord, field_ord, ord); if (TEMPLATE(T, is_primitive)(a, ctx) != fmpz_is_one(field_ord)) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); TEMPLATE(T, ctx_print)(ctx); fflush(stdout); flint_abort(); } fmpz_clear(ord); fmpz_clear(field_ord); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-is_square.c000066400000000000000000000056241461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, is_square, state) { slong ix; int result; for (ix = 0; ix < 300 * flint_test_multiplier(); ix++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b; int type; type = n_randint(state, 2); if (type == 0) #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); #endif else do #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); #endif #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) while (TEMPLATE(T, ctx_prime)(ctx) == 2); #else while (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0); #endif TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); if (type == 0) { /* Check is_square(a^2) == 1 */ TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sqr)(b, a, ctx); result = (TEMPLATE(T, is_square)(b, ctx)); if (!result) { flint_printf("FAIL (is_square(a^2)):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_abort(); } } else { /* Check non-squares */ TEMPLATE(T, t) z; TEMPLATE(T, init)(z, ctx); while (TEMPLATE(T, is_square)(z, ctx)) TEMPLATE(T, randtest)(z, state, ctx); while (TEMPLATE(T, is_zero)(a, ctx)) TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sqr)(b, a, ctx); TEMPLATE(T, mul)(b, b, z, ctx); result = (!TEMPLATE(T, is_square)(b, ctx)); if (!result) { flint_printf("FAIL (is_square(a^2)):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("z = "), TEMPLATE(T, print_pretty)(z, ctx), flint_printf("\n"); flint_abort(); } TEMPLATE(T, clear)(z, ctx); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-mul.c000066400000000000000000000147371461254215100203030ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, mul, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, mul)(c, a, b, ctx); TEMPLATE(T, mul)(a, a, b, ctx); result = (TEMPLATE(T, equal)(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, mul)(c, a, b, ctx); TEMPLATE(T, mul)(b, a, b, ctx); result = (TEMPLATE(T, equal)(b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check aliasing: a = a * a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, mul)(c, a, a, ctx); TEMPLATE(T, mul)(a, a, a, ctx); result = (TEMPLATE(T, equal)(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check that a * b == b * a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c1, c2; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c1, ctx); TEMPLATE(T, init)(c2, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, mul)(c1, a, b, ctx); TEMPLATE(T, mul)(c2, b, a, ctx); result = (TEMPLATE(T, equal)(c1, c2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c1 = "), TEMPLATE(T, print_pretty)(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), TEMPLATE(T, print_pretty)(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c1, ctx); TEMPLATE(T, clear)(c2, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check that (a * b) * c == a * (b * c) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c, lhs, rhs; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(lhs, ctx); TEMPLATE(T, init)(rhs, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, randtest)(c, state, ctx); TEMPLATE(T, mul)(lhs, a, b, ctx); TEMPLATE(T, mul)(lhs, lhs, c, ctx); TEMPLATE(T, mul)(rhs, b, c, ctx); TEMPLATE(T, mul)(rhs, a, rhs, ctx); result = (TEMPLATE(T, equal)(lhs, rhs, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("lhs = "), TEMPLATE(T, print_pretty)(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), TEMPLATE(T, print_pretty)(rhs, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, clear)(lhs, ctx); TEMPLATE(T, clear)(rhs, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-mul_fmpz.c000066400000000000000000000056571461254215100213400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" #include "fmpz_poly.h" TEST_TEMPLATE_FUNCTION_START(T, mul_fmpz, state) { int i, result; /* Check aliasing of a, b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; fmpz_t x; TEMPLATE(T, t) a, b; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); fmpz_init(x); TEMPLATE(T, randtest)(a, state, ctx); fmpz_randtest_mod_signed(x,state,TEMPLATE(T, ctx_prime)(ctx)); TEMPLATE(T, mul_fmpz)(b, a, x, ctx); TEMPLATE(T, mul_fmpz)(a, a, x, ctx); result = (TEMPLATE(T, equal)(a, b, ctx)); if (!result) { flint_printf("fail:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); fmpz_clear(x); TEMPLATE(T, ctx_clear)(ctx); } /* compare with direct multiplication */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; fmpz_t x; TEMPLATE(T, t) a, c; fmpz_poly_t b; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); fmpz_init(x); fmpz_poly_init(b); TEMPLATE(T, randtest)(a, state, ctx); fmpz_randtest_mod_signed(x,state,TEMPLATE(T, ctx_prime)(ctx)); TEMPLATE(T, mul_fmpz)(c, a, x, ctx); fmpz_poly_scalar_mul_fmpz(b,a,x); TEMPLATE(T, reduce)(b,ctx); result = (TEMPLATE(T, equal)(c, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_poly_clear(b); fmpz_clear(x); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-mul_si.c000066400000000000000000000053111461254215100207620ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "long_extras.h" #include "fmpz_poly.h" TEST_TEMPLATE_FUNCTION_START(T, mul_si, state) { int i, result; /* Check aliasing of a, b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; slong x; TEMPLATE(T, t) a, b; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, randtest)(a, state, ctx); x = z_randtest(state); TEMPLATE(T, mul_si)(b, a, x, ctx); TEMPLATE(T, mul_si)(a, a, x, ctx); result = (TEMPLATE(T, equal)(a, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("x = %wd\n",x); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* compare with direct multiplication */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; slong x; TEMPLATE(T, t) a, c; fmpz_poly_t b; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); fmpz_poly_init(b); TEMPLATE(T, randtest)(a, state, ctx); x = z_randtest(state); TEMPLATE(T, mul_si)(c, a, x, ctx); fmpz_poly_scalar_mul_si(b,a,x); TEMPLATE(T, reduce)(b,ctx); result = (TEMPLATE(T, equal)(c, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("x = %wd\n",x); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_poly_clear(b); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-mul_ui.c000066400000000000000000000053111461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "long_extras.h" #include "fmpz_poly.h" TEST_TEMPLATE_FUNCTION_START(T, mul_ui, state) { int i, result; /* Check aliasing of a, b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; ulong x; TEMPLATE(T, t) a, b; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, randtest)(a, state, ctx); x = z_randtest(state); TEMPLATE(T, mul_ui)(b, a, x, ctx); TEMPLATE(T, mul_ui)(a, a, x, ctx); result = (TEMPLATE(T, equal)(a, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("x = %wu\n",x); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* compare with direct multiplication */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; ulong x; TEMPLATE(T, t) a, c; fmpz_poly_t b; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); fmpz_poly_init(b); TEMPLATE(T, randtest)(a, state, ctx); x = z_randtest(state); TEMPLATE(T, mul_ui)(c, a, x, ctx); fmpz_poly_scalar_mul_ui(b,a,x); TEMPLATE(T, reduce)(b,ctx); result = (TEMPLATE(T, equal)(c, b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("x = %wu\n",x); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_poly_clear(b); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-multiplicative_order.c000066400000000000000000000064701461254215100237270ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, multiplicative_order, state) { slong ix; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, X; fmpz_t ord; int type; type = n_randint(state, 2); /* Test big primes and small degrees */ TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); fmpz_init(ord); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(X, ctx); if (type == 0) { /* Check that multiplicative order is a multiple of the real one */ TEMPLATE(T, randtest)(a, state, ctx); result = TEMPLATE(T, multiplicative_order)(ord, a, ctx); TEMPLATE(T, pow)(X, a, ord, ctx); if (result && !TEMPLATE(T, is_one)(X, ctx)) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("ord = "), fmpz_print(ord), flint_printf("\n"); TEMPLATE(T, ctx_print)(ctx); flint_abort(); } } else { /* Check multiplicative order is coherent with powering by p - 1 */ fmpz_t size; #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) ulong pm1; #else fmpz_t pm1; #endif fmpz_init(size); #if !(defined(FQ_NMOD_H) || defined(FQ_ZECH_H)) fmpz_init(pm1); #endif TEMPLATE(T, gen)(X, ctx); if (TEMPLATE(T, is_primitive)(X, ctx)) { #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) pm1 = TEMPLATE(T, ctx_prime)(ctx) - 1; TEMPLATE(T, pow_ui)(a, X, pm1, ctx); result = TEMPLATE(T, multiplicative_order)(ord, a, ctx); fmpz_mul_ui(ord, ord, pm1); #else fmpz_sub_ui(pm1, TEMPLATE(T, ctx_prime)(ctx), 1); TEMPLATE(T, pow)(a, X, pm1, ctx); result = TEMPLATE(T, multiplicative_order)(ord, a, ctx); fmpz_mul(ord, ord, pm1); #endif TEMPLATE(T, ctx_order)(size, ctx); fmpz_sub(size, size, ord); if (result && !fmpz_is_one(size)) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("ord = "), fmpz_print(ord), flint_printf("\n"); TEMPLATE(T, ctx_print)(ctx); flint_abort(); } } #if !(defined(FQ_NMOD_H) || defined(FQ_ZECH_H)) fmpz_clear(pm1); #endif fmpz_clear(size); } fmpz_clear(ord); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(X, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-neg.c000066400000000000000000000057221461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, neg, state) { int i, result; /* Check aliasing: a = -a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, set)(b, a, ctx); TEMPLATE(T, neg)(c, b, ctx); TEMPLATE(T, neg)(b, b, ctx); result = (TEMPLATE(T, equal)(b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check a - b == a + (-b) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c1, c2; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c1, ctx); TEMPLATE(T, init)(c2, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, sub)(c1, a, b, ctx); TEMPLATE(T, neg)(c2, b, ctx); TEMPLATE(T, add)(c2, a, c2, ctx); result = (TEMPLATE(T, equal)(c1, c2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c1 = "), TEMPLATE(T, print_pretty)(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), TEMPLATE(T, print_pretty)(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c1, ctx); TEMPLATE(T, clear)(c2, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-norm.c000066400000000000000000000045531461254215100204540ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, norm, state) { int i, result; /* Compare with product of Galois conjugates */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; fmpz_t x, y; slong j; TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); fmpz_init(x); fmpz_init(y); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, reduce)(a, ctx); TEMPLATE(T, norm)(x, a, ctx); TEMPLATE(T, one)(b, ctx); for (j = 0; j < TEMPLATE(T, ctx_degree)(ctx); j++) { TEMPLATE(T, frobenius)(c, a, j, ctx); TEMPLATE(T, mul)(b, b, c, ctx); } TEMPLATE(T, zero)(c, ctx); TEMPLATE(T, set_fmpz)(c, x, ctx); result = TEMPLATE(T, equal)(b, c, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); for (j = 0; j < TEMPLATE(T, ctx_degree)(ctx); j++) { TEMPLATE(T, frobenius)(c, a, j, ctx); flint_printf("sigma^%wd = ", j), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); } flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_clear(x); fmpz_clear(y); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-pow.c000066400000000000000000000060321461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, pow, state) { int i, result; /* Check aliasing: a = a^e */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b; fmpz_t e; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); fmpz_init(e); TEMPLATE(T, randtest)(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); TEMPLATE(T, pow)(b, a, e, ctx); TEMPLATE(T, pow)(a, a, e, ctx); result = (TEMPLATE(T, equal)(a, b, ctx)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); fmpz_clear(e); TEMPLATE(T, ctx_clear)(ctx); } /* Compare with multiplication, for integral values */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; fmpz_t e, f; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); fmpz_init(f); fmpz_init(e); TEMPLATE(T, randtest)(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); TEMPLATE(T, pow)(b, a, e, ctx); TEMPLATE(T, one)(c, ctx); for (fmpz_one(f); fmpz_cmp(f, e) <= 0; fmpz_add_ui(f, f, 1)) { TEMPLATE(T, mul)(c, c, a, ctx); } result = (TEMPLATE(T, equal)(b, c, ctx)); if (!result) { flint_printf("FAIL (cmp with mul):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("e = "), fmpz_print(e), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_clear(e); fmpz_clear(f); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-pth_root.c000066400000000000000000000034061461254215100213330ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, pth_root, state) { int i, result; /* Compare with sum of Galois conjugates */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b; #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); #endif TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, pth_root)(b, a, ctx); #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) TEMPLATE(T, pow_ui)(b, b, TEMPLATE(T, ctx_prime)(ctx), ctx); #else TEMPLATE(T, pow)(b, b, TEMPLATE(T, ctx_prime)(ctx), ctx); #endif result = TEMPLATE(T, equal)(a, b, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-sqr.c000066400000000000000000000054371461254215100203100ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, sqr, state) { int i, result; /* Check aliasing: a = a * a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sqr)(c, a, ctx); TEMPLATE(T, sqr)(a, a, ctx); result = (TEMPLATE(T, equal)(a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check a^2 + a^2 = a(a + a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c, d; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(d, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sqr)(b, a, ctx); TEMPLATE(T, add)(c, b, b, ctx); TEMPLATE(T, add)(d, a, a, ctx); TEMPLATE(T, mul)(d, a, d, ctx); result = (TEMPLATE(T, equal)(c, d, ctx)); if (!result) { flint_printf("FAIL (a^2 + a^2 == a(a + a)):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, print_pretty)(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, clear)(d, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-sqrt.c000066400000000000000000000073301461254215100204660ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, sqrt, state) { slong ix; int result; for (ix = 0; ix < 300 * flint_test_multiplier(); ix++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, c; int type; type = n_randint(state, 2); #if defined(FQ_ZECH_H) TEMPLATE(T, ctx_init_randtest)(ctx, state, 3); #else TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); #endif TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); if (type == 0) { /* Check aliasing: a = a * a */ TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sqr)(c, a, ctx); TEMPLATE(T, sqrt)(a, c, ctx); TEMPLATE(T, sqrt)(c, c, ctx); result = (TEMPLATE(T, equal)(a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_abort(); } } else { /* Check sqrt(a^2) = a and that x*a^2 is not a square */ TEMPLATE(T, t) b, d, x; TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(d, ctx); TEMPLATE(T, init)(x, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sqr)(b, a, ctx); result = TEMPLATE(T, sqrt)(c, b, ctx); TEMPLATE(T, sqr)(d, c, ctx); result = (result && TEMPLATE(T, equal)(d, b, ctx)); if (!result) { flint_printf("FAIL (sqrt(a^2) == a):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("d = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_abort(); } #if defined(FQ_NMOD_H) || defined(FQ_ZECH_H) if (ctx->is_conway && TEMPLATE(T, ctx_prime)(ctx) != 2 && !TEMPLATE(T, is_zero)(b, ctx)) #else if (ctx->is_conway && fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) != 0 && !TEMPLATE(T, is_zero)(b, ctx)) #endif { TEMPLATE(T, gen)(x, ctx); TEMPLATE(T, mul)(b, b, x, ctx); result = !TEMPLATE(T, sqrt)(c, b, ctx); /* check b is not a square */ if (!result) { flint_printf("FAIL (a^2*x is nonsquare):\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_abort(); } } TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(d, ctx); TEMPLATE(T, clear)(x, ctx); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-sub.c000066400000000000000000000150101461254215100202600ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, sub, state) { int i, result; /* Check aliasing: a = a - b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, sub)(c, a, b, ctx); TEMPLATE(T, sub)(a, a, b, ctx); result = (TEMPLATE(T, equal)(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check aliasing: b = a - b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, sub)(c, a, b, ctx); TEMPLATE(T, sub)(b, a, b, ctx); result = (TEMPLATE(T, equal)(b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check aliasing: a = a - a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, c; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sub)(c, a, a, ctx); TEMPLATE(T, sub)(a, a, a, ctx); result = (TEMPLATE(T, equal)(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check that a - b == -(b - a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c1, c2; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c1, ctx); TEMPLATE(T, init)(c2, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, sub)(c1, a, b, ctx); TEMPLATE(T, sub)(c2, b, a, ctx); TEMPLATE(T, neg)(c2, c2, ctx); result = (TEMPLATE(T, equal)(c1, c2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c1 = "), TEMPLATE(T, print_pretty)(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), TEMPLATE(T, print_pretty)(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c1, ctx); TEMPLATE(T, clear)(c2, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check that (a - b) - c == a - (b + c) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c, lhs, rhs; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(lhs, ctx); TEMPLATE(T, init)(rhs, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, randtest)(b, state, ctx); TEMPLATE(T, randtest)(c, state, ctx); TEMPLATE(T, sub)(lhs, a, b, ctx); TEMPLATE(T, sub)(lhs, lhs, c, ctx); TEMPLATE(T, add)(rhs, b, c, ctx); TEMPLATE(T, sub)(rhs, a, rhs, ctx); result = (TEMPLATE(T, equal)(lhs, rhs, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("lhs = "), TEMPLATE(T, print_pretty)(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), TEMPLATE(T, print_pretty)(rhs, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, clear)(lhs, ctx); TEMPLATE(T, clear)(rhs, ctx); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_templates/test/t-trace.c000066400000000000000000000045351461254215100205770ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" #include "fmpz.h" TEST_TEMPLATE_FUNCTION_START(T, trace, state) { slong ix; int result; /* Compare with sum of Galois conjugates */ for (ix = 0; ix < 200 * flint_test_multiplier(); ix++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c; fmpz_t x, y; slong jx; TEMPLATE(T, ctx_init_randtest)(ctx, state, 1); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); fmpz_init(x); fmpz_init(y); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, trace)(x, a, ctx); TEMPLATE(T, zero)(b, ctx); for (jx = 0; jx < TEMPLATE(T, ctx_degree)(ctx); jx++) { TEMPLATE(T, frobenius)(c, a, jx, ctx); TEMPLATE(T, add)(b, b, c, ctx); } TEMPLATE(T, zero)(c, ctx); TEMPLATE(T, set_fmpz)(c, x, ctx); result = TEMPLATE(T, equal)(b, c, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), TEMPLATE(T, print_pretty)(a, ctx), flint_printf("\n"); flint_printf("b = "), TEMPLATE(T, print_pretty)(b, ctx), flint_printf("\n"); flint_printf("c = "), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); for (jx = 0; jx < TEMPLATE(T, ctx_degree)(ctx); jx++) { TEMPLATE(T, frobenius)(c, a, jx, ctx); flint_printf("sigma^%wd = ", jx), TEMPLATE(T, print_pretty)(c, ctx), flint_printf("\n"); } flint_abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_clear(x); fmpz_clear(y); TEMPLATE(T, ctx_clear)(ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_types.h000066400000000000000000000025661461254215100154360ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_TYPES_H #define FQ_TYPES_H #include "fmpz_mod_types.h" #ifdef __cplusplus extern "C" { #endif typedef fmpz_poly_t fq_t; typedef fmpz_poly_struct fq_struct; typedef struct { fmpz_mod_ctx_t ctxp; int sparse_modulus; int is_conway; /* whether field was initialized with the Flint Conway tables (assures primitivity) */ fmpz * a; slong * j; slong len; fmpz_mod_poly_t modulus; fmpz_mod_poly_t inv; char * var; } fq_ctx_struct; typedef fq_ctx_struct fq_ctx_t[1]; typedef struct { fq_struct * entries; slong r; slong c; fq_struct ** rows; } fq_mat_struct; typedef fq_mat_struct fq_mat_t[1]; typedef struct { fq_struct * coeffs; slong alloc; slong length; } fq_poly_struct; typedef fq_poly_struct fq_poly_t[1]; typedef struct { fq_poly_struct * poly; slong * exp; slong num; slong alloc; } fq_poly_factor_struct; typedef fq_poly_factor_struct fq_poly_factor_t[1]; #ifdef __cplusplus } #endif #endif /* FQ_TYPES_H */ flint-3.1.3/src/fq_vec.h000066400000000000000000000026201461254215100150360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_VEC_H #define FQ_VEC_H #ifdef FQ_VEC_INLINES_C #define FQ_VEC_TEMPLATES_INLINE #define FQ_VEC_INLINE #else #define FQ_VEC_TEMPLATES_INLINE static inline #define FQ_VEC_INLINE static inline #endif #include "fq_types.h" #define FQ_VEC_NORM(vec, i, ctx) \ do { \ while ((i) && fq_is_zero((vec) + (i) - 1, ctx)) \ (i)--; \ } while (0) #define FQ_VEC_SWAP(vec1, len1, vec2, len2) \ do { \ fq_struct *__t; \ slong __tn; \ __t = (vec1); \ (vec1) = (vec2); \ (vec2) = __t; \ __tn = (len1); \ (len1) = (len2); \ (len2) = __tn; \ } while (0); #define T fq #define CAP_T FQ #include "fq_vec_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_vec/000077500000000000000000000000001461254215100146655ustar00rootroot00000000000000flint-3.1.3/src/fq_vec/dot.c000066400000000000000000000015751461254215100156270ustar00rootroot00000000000000/* Copyright (C) 2019 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fq.h" #include "fq_vec.h" void _fq_vec_dot(fq_t res, const fq_struct * vec1, const fq_struct * vec2, slong len2, const fq_ctx_t ctx) { slong i; fmpz_poly_t t; if (len2 == 0) { fq_zero(res, ctx); return; } fmpz_poly_init(t); fmpz_poly_mul(res, vec1 + 0, vec2 + 0); for (i = 1; i < len2; i++) { fmpz_poly_mul(t, vec1 + i, vec2 + i); fmpz_poly_add(res, res, t); } fq_reduce(res, ctx); fmpz_poly_clear(t); } flint-3.1.3/src/fq_vec/inlines.c000066400000000000000000000006501461254215100164730ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_VEC_INLINES_C #include "fq_vec.h" flint-3.1.3/src/fq_vec/test/000077500000000000000000000000001461254215100156445ustar00rootroot00000000000000flint-3.1.3/src/fq_vec/test/main.c000066400000000000000000000017751461254215100167460ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-is_zero.c" #include "t-neg.c" #include "t-sub.c" #include "t-swap.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_vec_add), TEST_FUNCTION(fq_vec_is_zero), TEST_FUNCTION(fq_vec_neg), TEST_FUNCTION(fq_vec_sub), TEST_FUNCTION(fq_vec_swap), TEST_FUNCTION(fq_vec_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_vec/test/t-add.c000066400000000000000000000010251461254215100167770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_vec/test/t-is_zero.c000066400000000000000000000010311461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/test/t-is_zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_vec/test/t-neg.c000066400000000000000000000010251461254215100170200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_vec/test/t-sub.c000066400000000000000000000010251461254215100170400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_vec/test/t-swap.c000066400000000000000000000010261461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/test/t-swap.c" #undef CAP_T #undef T flint-3.1.3/src/fq_vec/test/t-zero.c000066400000000000000000000010261461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/test/t-zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_vec_templates.h000066400000000000000000000112311461254215100171120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *******************************************************/ TEMPLATE(T, struct) * _TEMPLATE(T, vec_init)(slong len, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, vec_clear)(TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx); /* Randomisation ***********************************************************/ void _TEMPLATE(T, vec_randtest)(TEMPLATE(T, struct) * f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); /* Norms *******************************************************************/ /* Input and output ********************************************************/ #ifdef FLINT_HAVE_FILE int _TEMPLATE(T, vec_fprint)(FILE * file, const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx); #endif int _TEMPLATE(T, vec_print)(const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx); /* Conversions *************************************************************/ /* Assignment and basic manipulation ***************************************/ void _TEMPLATE(T, vec_set)(TEMPLATE(T, struct) * v, const TEMPLATE(T, struct) * f, slong len, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, vec_swap)(TEMPLATE(T, struct) * vec1, TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, vec_zero)(TEMPLATE(T, struct) * v, slong len, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, vec_neg)(TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx); /* Comparison **************************************************************/ int _TEMPLATE(T, vec_is_zero)(const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx); int _TEMPLATE(T, vec_equal)(const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len, const TEMPLATE(T, ctx_t) ctx); /* Sorting *****************************************************************/ /* Addition ****************************************************************/ void _TEMPLATE(T, vec_add)(TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, vec_sub)(TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T))(TEMPLATE(T, struct) * poly1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE(T, TEMPLATE(vec_scalar_submul, T))(TEMPLATE(T, struct) * poly1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); void _TEMPLATE3(T, vec_scalar_mul, T) (TEMPLATE(T, struct) * poly1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); /* ****************************************************************************/ void _TEMPLATE(T, vec_dot)(TEMPLATE(T, t) res, const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_vec_templates/000077500000000000000000000000001461254215100167435ustar00rootroot00000000000000flint-3.1.3/src/fq_vec_templates/add.c000066400000000000000000000014371461254215100176440ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_add) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len2; i++) TEMPLATE(T, add) (res + i, vec1 + i, vec2 + i, ctx); } #endif flint-3.1.3/src/fq_vec_templates/clear.c000066400000000000000000000012611461254215100201750ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_clear) (TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) TEMPLATE(T, clear) (vec + i, ctx); flint_free(vec); } #endif flint-3.1.3/src/fq_vec_templates/dot.c000066400000000000000000000016421461254215100177000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_dot) (TEMPLATE(T, t) res, const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx) { slong i; TEMPLATE(T, t) x; TEMPLATE(T, init) (x, ctx); TEMPLATE(T, zero) (res, ctx); for (i = 0; i < len2; i++) { TEMPLATE(T, mul) (x, vec1 + i, vec2 + i, ctx); TEMPLATE(T, add) (res, res, x, ctx); } TEMPLATE(T, clear) (x, ctx); } #endif flint-3.1.3/src/fq_vec_templates/equal.c000066400000000000000000000015101461254215100202130ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int _TEMPLATE(T, vec_equal) (const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; if (vec1 == vec2) return 1; for (i = 0; i < len; i++) if (!TEMPLATE(T, equal) (vec1 + i, vec2 + i, ctx)) return 0; return 1; } #endif flint-3.1.3/src/fq_vec_templates/init.c000066400000000000000000000012651461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" TEMPLATE(T, struct)* _TEMPLATE(T, vec_init) (slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; TEMPLATE(T, struct) * v; v = flint_malloc(len * sizeof(TEMPLATE(T, struct))); for (i = 0; i < len; i++) TEMPLATE(T, init) (v + i, ctx); return v; } #endif flint-3.1.3/src/fq_vec_templates/io.c000066400000000000000000000032541461254215100175220ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* printing *******************************************************************/ /* Recall the return value conventions for fputc (of type int) ``If there are no errors, the same character that has been written is returned. If an error occurs, EOF is returned and the error indicator is set'' where the EOF macro expands to a negative int, and fprintf (of type int) ``On success, the total number of characters written is returned. On failure, a negative number is returned.'' */ int _TEMPLATE(T, vec_fprint) (FILE * file, const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx) { int r; slong i; r = fprintf(file, WORD_FMT "d", len); if ((len > 0) && (r > 0)) { r = fputc(' ', file); for (i = 0; (i < len) && (r > 0); i++) { r = fputc(' ', file); if (r > 0) r = TEMPLATE(T, fprint) (file, vec + i, ctx); } } return r; } int _TEMPLATE(T, vec_print)(const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, vec_fprint)(stdout, vec, len, ctx); } #endif flint-3.1.3/src/fq_vec_templates/is_zero.c000066400000000000000000000013271461254215100205640ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int _TEMPLATE(T, vec_is_zero) (const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) if (!TEMPLATE(T, is_zero) (vec + i, ctx)) return 0; return 1; } #endif flint-3.1.3/src/fq_vec_templates/neg.c000066400000000000000000000013361461254215100176630ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_neg) (TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len2; i++) TEMPLATE(T, neg) (vec1 + i, vec2 + i, ctx); } #endif flint-3.1.3/src/fq_vec_templates/randtest.c000066400000000000000000000021731461254215100207360ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_randtest) (TEMPLATE(T, struct) * f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i, sparseness; if (n_randint(state, 2)) { for (i = 0; i < len; i++) TEMPLATE(T, randtest) (f + i, state, ctx); } else { sparseness = 1 + n_randint(state, FLINT_MAX(2, len)); for (i = 0; i < len; i++) { if (n_randint(state, sparseness)) TEMPLATE(T, zero) (f + i, ctx); else TEMPLATE(T, randtest) (f + i, state, ctx); } } } #endif flint-3.1.3/src/fq_vec_templates/scalar_addmul_fq.c000066400000000000000000000016771461254215100224030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE3(T, vec_scalar_addmul, T) (TEMPLATE(T, struct) * poly1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { slong i; TEMPLATE(T, t) y; TEMPLATE(T, init) (y, ctx); for (i = 0; i < len2; i++) { TEMPLATE(T, mul) (y, poly2 + i, x, ctx); TEMPLATE(T, add) (poly1 + i, poly1 + i, y, ctx); } TEMPLATE(T, clear) (y, ctx); } #endif flint-3.1.3/src/fq_vec_templates/scalar_mul_fq.c000066400000000000000000000014511461254215100217200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE3(T, vec_scalar_mul, T) (TEMPLATE(T, struct) * poly1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len2; i++) { TEMPLATE(T, mul) (poly1 + i, poly2 + i, x, ctx); } } #endif flint-3.1.3/src/fq_vec_templates/scalar_submul_fq.c000066400000000000000000000016771461254215100224440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE3(T, vec_scalar_submul, T) (TEMPLATE(T, struct) * poly1, const TEMPLATE(T, struct) * poly2, slong len2, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx) { slong i; TEMPLATE(T, t) y; TEMPLATE(T, init) (y, ctx); for (i = 0; i < len2; i++) { TEMPLATE(T, mul) (y, poly2 + i, x, ctx); TEMPLATE(T, sub) (poly1 + i, poly1 + i, y, ctx); } TEMPLATE(T, clear) (y, ctx); } #endif flint-3.1.3/src/fq_vec_templates/set.c000066400000000000000000000013361461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_set) (TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len2; i++) TEMPLATE(T, set) (vec1 + i, vec2 + i, ctx); } #endif flint-3.1.3/src/fq_vec_templates/sub.c000066400000000000000000000014371461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_sub) (TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len2; i++) TEMPLATE(T, sub) (res + i, vec1 + i, vec2 + i, ctx); } #endif flint-3.1.3/src/fq_vec_templates/swap.c000066400000000000000000000013121461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_swap) (TEMPLATE(T, struct) * vec1, TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len2; i++) TEMPLATE(T, swap) (vec1 + i, vec2 + i, ctx); } #endif flint-3.1.3/src/fq_vec_templates/test/000077500000000000000000000000001461254215100177225ustar00rootroot00000000000000flint-3.1.3/src/fq_vec_templates/test/t-add.c000066400000000000000000000054621461254215100210660ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, vec_add, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b, *c; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); c = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_randtest) (b, state, len, ctx); _TEMPLATE(T, vec_add) (c, a, b, len, ctx); _TEMPLATE(T, vec_add) (a, a, b, len, ctx); result = (_TEMPLATE(T, vec_equal) (a, c, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (c, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); _TEMPLATE(T, vec_clear) (c, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of b and c */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b, *c; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); c = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_randtest) (b, state, len, ctx); _TEMPLATE(T, vec_add) (c, a, b, len, ctx); _TEMPLATE(T, vec_add) (b, a, b, len, ctx); result = (_TEMPLATE(T, vec_equal) (b, c, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (b, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (c, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); _TEMPLATE(T, vec_clear) (c, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_vec_templates/test/t-is_zero.c000066400000000000000000000037641461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, vec_is_zero, state) { int i, result; /* Check zero vector */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_zero) (a, len, ctx); result = (_TEMPLATE(T, vec_is_zero) (a, len, ctx)); if (!result) { printf("FAIL1:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check non-zero vector */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a; slong len = n_randint(state, 100) + 1; TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); TEMPLATE(T, one) (a + (len - 1), ctx); result = (!_TEMPLATE(T, vec_is_zero) (a, len, ctx)); if (!result) { printf("FAIL2:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_vec_templates/test/t-neg.c000066400000000000000000000047471461254215100211140ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, vec_neg, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_neg) (b, a, len, ctx); _TEMPLATE(T, vec_neg) (a, a, len, ctx); result = (_TEMPLATE(T, vec_equal) (a, b, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (b, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check -(-a) == a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_neg) (b, a, len, ctx); _TEMPLATE(T, vec_neg) (b, b, len, ctx); result = (_TEMPLATE(T, vec_equal) (a, b, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (b, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_vec_templates/test/t-sub.c000066400000000000000000000100041461254215100211130ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, vec_sub, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b, *c; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); c = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_randtest) (b, state, len, ctx); _TEMPLATE(T, vec_sub) (c, a, b, len, ctx); _TEMPLATE(T, vec_sub) (a, a, b, len, ctx); result = (_TEMPLATE(T, vec_equal) (a, c, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (c, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); _TEMPLATE(T, vec_clear) (c, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check aliasing of b and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b, *c; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); c = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_randtest) (b, state, len, ctx); _TEMPLATE(T, vec_sub) (c, a, b, len, ctx); _TEMPLATE(T, vec_sub) (b, a, b, len, ctx); result = (_TEMPLATE(T, vec_equal) (b, c, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (b, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (c, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); _TEMPLATE(T, vec_clear) (c, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check a + b - b = a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b, *c, *d; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); c = _TEMPLATE(T, vec_init) (len, ctx); d = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_randtest) (b, state, len, ctx); _TEMPLATE(T, vec_add) (c, a, b, len, ctx); _TEMPLATE(T, vec_sub) (d, c, b, len, ctx); result = (_TEMPLATE(T, vec_equal) (d, a, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (d, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); _TEMPLATE(T, vec_clear) (c, len, ctx); _TEMPLATE(T, vec_clear) (d, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_vec_templates/test/t-swap.c000066400000000000000000000033771461254215100213130ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, vec_swap, state) { int i, result; for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a, *b, *c; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); b = _TEMPLATE(T, vec_init) (len, ctx); c = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_randtest) (b, state, len, ctx); _TEMPLATE(T, vec_set) (c, b, len, ctx); _TEMPLATE(T, vec_swap) (a, b, len, ctx); result = (_TEMPLATE(T, vec_equal) (a, c, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (b, len, ctx), printf("\n\n"); _TEMPLATE(T, vec_print) (c, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); _TEMPLATE(T, vec_clear) (c, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_vec_templates/test/t-zero.c000066400000000000000000000025461461254215100213150ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "test_helpers.h" #include "templates.h" TEST_TEMPLATE_FUNCTION_START(T, vec_zero, state) { int i, result; /* Check it's zero */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * a; slong len = n_randint(state, 100); TEMPLATE(T, ctx_init_randtest)(ctx, state, 0); a = _TEMPLATE(T, vec_init) (len, ctx); _TEMPLATE(T, vec_randtest) (a, state, len, ctx); _TEMPLATE(T, vec_zero) (a, len, ctx); result = (_TEMPLATE(T, vec_is_zero) (a, len, ctx)); if (!result) { printf("FAIL:\n"); _TEMPLATE(T, vec_print) (a, len, ctx), printf("\n\n"); fflush(stdout); flint_abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } TEST_FUNCTION_END(state); } #endif flint-3.1.3/src/fq_vec_templates/zero.c000066400000000000000000000012321461254215100200640ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, vec_zero) (TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < len; i++) TEMPLATE(T, zero) (vec + i, ctx); } #endif flint-3.1.3/src/fq_zech.h000066400000000000000000000220521461254215100152130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_H #define FQ_ZECH_H #ifdef FQ_ZECH_INLINES_C #define FQ_ZECH_INLINE #ifndef FQ_TEMPLATES_INLINE # define FQ_TEMPLATES_INLINE #endif #else #define FQ_ZECH_INLINE static inline #ifndef FQ_TEMPLATES_INLINE # define FQ_TEMPLATES_INLINE static inline #endif #endif #include "fq_zech_types.h" /* Data types and context ****************************************************/ #ifdef __cplusplus extern "C" { #endif void fq_zech_ctx_init_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var); int _fq_zech_ctx_init_conway_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var); void fq_zech_ctx_init_conway_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var); void fq_zech_ctx_init_random_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var); int fq_zech_ctx_init_fq_nmod_ctx_check(fq_zech_ctx_t ctx, fq_nmod_ctx_t ctxn); void fq_zech_ctx_init_fq_nmod_ctx(fq_zech_ctx_t ctx, fq_nmod_ctx_t ctxn); int fq_zech_ctx_init_modulus_check(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char * var); void fq_zech_ctx_init_modulus(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char * var); void fq_zech_ctx_init_randtest(fq_zech_ctx_t ctx, flint_rand_t state, int type); void fq_zech_ctx_init_randtest_reducible(fq_zech_ctx_t ctx, flint_rand_t state, int type); void fq_zech_ctx_clear(fq_zech_ctx_t ctx); FQ_ZECH_INLINE const nmod_poly_struct * fq_zech_ctx_modulus(const fq_zech_ctx_t ctx) { return ctx->fq_nmod_ctx->modulus; } FQ_ZECH_INLINE slong fq_zech_ctx_degree(const fq_zech_ctx_t ctx) { return ctx->fq_nmod_ctx->modulus->length - 1; } FQ_ZECH_INLINE ulong fq_zech_ctx_prime(const fq_zech_ctx_t ctx) { return ctx->fq_nmod_ctx->mod.n; } FQ_ZECH_INLINE ulong fq_zech_ctx_order_ui(const fq_zech_ctx_t ctx) { return ctx->qm1 + 1; } #ifdef FLINT_HAVE_FILE int fq_zech_ctx_fprint(FILE * file, const fq_zech_ctx_t ctx); #endif void fq_zech_ctx_print(const fq_zech_ctx_t ctx); /* Memory management *********************************************************/ FQ_ZECH_INLINE void fq_zech_init(fq_zech_t rop, const fq_zech_ctx_t ctx) { rop->value = ctx->qm1; } FQ_ZECH_INLINE void fq_zech_init2(fq_zech_t rop, const fq_zech_ctx_t ctx) { rop->value = ctx->qm1; } FQ_ZECH_INLINE void fq_zech_clear(fq_zech_t rop, const fq_zech_ctx_t ctx) { } FQ_ZECH_INLINE void fq_zech_reduce(fq_zech_t rop, const fq_zech_ctx_t ctx) { mp_limb_t order = fq_zech_ctx_order_ui(ctx); if (rop->value >= order) { rop->value -= order; } } /* Basic arithmetic **********************************************************/ void fq_zech_add(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx); void fq_zech_sub(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx); void fq_zech_sub_one(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); void fq_zech_neg(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); void fq_zech_mul(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx); void fq_zech_mul_fmpz(fq_zech_t rop, const fq_zech_t op, const fmpz_t x, const fq_zech_ctx_t ctx); void fq_zech_mul_si(fq_zech_t rop, const fq_zech_t op, slong x, const fq_zech_ctx_t ctx); void fq_zech_mul_ui(fq_zech_t rop, const fq_zech_t op, ulong x, const fq_zech_ctx_t ctx); void fq_zech_sqr(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); void fq_zech_inv(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); void _fq_zech_pow(fmpz * rop, const fmpz * op, slong len, const fmpz_t e, const fmpz * a, const slong *j, slong lena, const fmpz_t p); void fq_zech_pow(fq_zech_t rop, const fq_zech_t op1, const fmpz_t e, const fq_zech_ctx_t ctx); void fq_zech_pow_ui(fq_zech_t rop, const fq_zech_t op1, const ulong e, const fq_zech_ctx_t ctx); /* Roots *********************************************************************/ int fq_zech_sqrt(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); void fq_zech_pth_root(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); int fq_zech_is_square(const fq_zech_t op1, const fq_zech_ctx_t ctx); /* Randomisation *************************************************************/ void fq_zech_randtest(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx); void fq_zech_randtest_not_zero(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx); void fq_zech_rand(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx); void fq_zech_rand_not_zero(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx); /* Comparison ****************************************************************/ FQ_ZECH_INLINE int fq_zech_equal(const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) { return op1->value == op2->value; } FQ_ZECH_INLINE int fq_zech_is_zero(const fq_zech_t op, const fq_zech_ctx_t ctx) { return op->value == ctx->qm1; } FQ_ZECH_INLINE int fq_zech_is_one(const fq_zech_t op, const fq_zech_ctx_t ctx) { return op->value == 0; } /* Assignments and conversions ***********************************************/ FQ_ZECH_INLINE void fq_zech_set(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) { rop->value = op->value; } void fq_zech_set_fmpz(fq_zech_t rop, const fmpz_t x, const fq_zech_ctx_t ctx); void fq_zech_set_si(fq_zech_t rop, const slong x, const fq_zech_ctx_t ctx); void fq_zech_set_ui(fq_zech_t rop, const ulong x, const fq_zech_ctx_t ctx); FQ_ZECH_INLINE void fq_zech_swap(fq_zech_t op1, fq_zech_t op2, const fq_zech_ctx_t ctx) { slong temp; temp = op2->value; op2->value = op1->value; op1->value = temp; } FQ_ZECH_INLINE void fq_zech_zero(fq_zech_t rop, const fq_zech_ctx_t ctx) { rop->value = ctx->qm1; } FQ_ZECH_INLINE void fq_zech_one(fq_zech_t rop, const fq_zech_ctx_t ctx) { rop->value = 0; } FQ_ZECH_INLINE void fq_zech_gen(fq_zech_t rop, const fq_zech_ctx_t ctx) { rop->value = 1; } int fq_zech_get_fmpz(fmpz_t a, const fq_zech_t op, const fq_zech_ctx_t ctx); void fq_zech_set_fq_nmod(fq_zech_t rop, const fq_nmod_t op, const fq_zech_ctx_t ctx); void fq_zech_get_fq_nmod(fq_nmod_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); void fq_zech_get_nmod_poly(nmod_poly_t a, const fq_zech_t b, const fq_zech_ctx_t ctx); void fq_zech_set_nmod_poly(fq_zech_t a, const nmod_poly_t b, const fq_zech_ctx_t ctx); /* Output ********************************************************************/ #ifdef FLINT_HAVE_FILE int fq_zech_fprint(FILE * file, const fq_zech_t op, const fq_zech_ctx_t ctx); int fq_zech_fprint_pretty(FILE * file, const fq_zech_t op, const fq_zech_ctx_t ctx); #endif void fq_zech_print(const fq_zech_t op, const fq_zech_ctx_t ctx); void fq_zech_print_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx); char * fq_zech_get_str(const fq_zech_t op, const fq_zech_ctx_t ctx); char * fq_zech_get_str_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx); /* Special functions *********************************************************/ void fq_zech_trace(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); void fq_zech_frobenius(fq_zech_t rop, const fq_zech_t op, slong e, const fq_zech_ctx_t ctx); void fq_zech_norm(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); /* Bit packing ******************************************************/ void fq_zech_bit_pack(fmpz_t f, const fq_zech_t op, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx); void fq_zech_bit_unpack(fq_zech_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx); /* Deprecated functions ******************************************************/ void fq_zech_ctx_init(fq_zech_ctx_t, fmpz_t, slong, const char *); int _fq_zech_ctx_init_conway(fq_zech_ctx_t, fmpz_t, slong, const char *); void fq_zech_ctx_init_conway(fq_zech_ctx_t, fmpz_t, slong, const char *); void fq_zech_ctx_init_random(fq_zech_ctx_t, fmpz_t, slong, const char *); void fq_zech_ctx_order(fmpz_t, const fq_zech_ctx_t); #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #define B nmod #include "fq_templates.h" #undef B #undef CAP_T #undef T #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_zech/000077500000000000000000000000001461254215100150415ustar00rootroot00000000000000flint-3.1.3/src/fq_zech/add.c000066400000000000000000000017071461254215100157420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" void fq_zech_add(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) { mp_limb_t index, c; if (op1->value == ctx->qm1) { rop->value = op2->value; } else if (op2->value == ctx->qm1) { rop->value = op1->value; } else { index = n_submod(op1->value, op2->value, ctx->qm1); c = ctx->zech_log_table[index]; if (c != ctx->qm1) { c = n_addmod(c, op2->value, ctx->qm1); } rop->value = c; } } flint-3.1.3/src/fq_zech/bit_pack.c000066400000000000000000000013461461254215100167650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_zech.h" void fq_zech_bit_pack(fmpz_t f, const fq_zech_t op, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx) { fq_nmod_t opn; fq_nmod_init(opn, ctx->fq_nmod_ctx); fq_zech_get_fq_nmod(opn, op, ctx); fq_nmod_bit_pack(f, opn, bit_size, ctx->fq_nmod_ctx); fq_nmod_clear(opn, ctx->fq_nmod_ctx); } flint-3.1.3/src/fq_zech/bit_unpack.c000066400000000000000000000013651461254215100173310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_zech.h" void fq_zech_bit_unpack(fq_zech_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx) { fq_nmod_t ropn; fq_nmod_init(ropn, ctx->fq_nmod_ctx); fq_nmod_bit_unpack(ropn, f, bit_size, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(rop, ropn, ctx); fq_nmod_clear(ropn, ctx->fq_nmod_ctx); } flint-3.1.3/src/fq_zech/ctx.c000066400000000000000000000211051461254215100160020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_zech.h" static ulong _nmod_poly_evaluate_ui(mp_srcptr poly, slong len, ulong xd) { slong ix; ulong res; if (len == 0) return 0; res = poly[len - 1]; for (ix = len - 2; ix >= 0; ix--) { res *= xd; res += poly[ix]; } return res; } int _fq_zech_ctx_init_conway_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var) { int ret; ulong conway_poly[410]; /* Largest degree in database is 409 */ fq_nmod_ctx_struct * ctx_fq_nmod; nmod_poly_struct tmp; ret = _nmod_poly_conway(conway_poly, p, d); if (ret != 1 && ret != 0) FLINT_UNREACHABLE; if (!ret) return 0; /* We do not change ctx->is_conway */ nmod_poly_init(&tmp, p); tmp.coeffs = conway_poly; tmp.length = d + 1; ctx_fq_nmod = flint_malloc(sizeof(fq_nmod_ctx_struct)); fq_nmod_ctx_init_modulus(ctx_fq_nmod, &tmp, var); ctx->is_conway = 1; fq_zech_ctx_init_fq_nmod_ctx(ctx, ctx_fq_nmod); ctx->owns_fq_nmod_ctx = 1; /* No need to clear tmp */ return 1; } void fq_zech_ctx_init_conway_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var) { if (!_fq_zech_ctx_init_conway_ui(ctx, p, d, var)) flint_throw(FLINT_ERROR, "Exception (fq_zech_ctx_init_conway_ui). " "The polynomial for (p, d) = (%wu, %wd) is not present in the " "database.\n", p, d); } void fq_zech_ctx_init_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char *var) { if (!_fq_zech_ctx_init_conway_ui(ctx, p, d, var)) fq_zech_ctx_init_random_ui(ctx, p, d, var); } void fq_zech_ctx_init_random_ui(fq_zech_ctx_t ctx, ulong p, slong d, const char * var) { fq_nmod_ctx_struct * fq_nmod_ctx; flint_rand_t state; nmod_poly_t poly; ulong tmp_coeffs[FLINT_BITS]; /* p^d < 2^{FLINT_BITS} */ fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); flint_randinit(state); nmod_poly_init(poly, p); poly->coeffs = tmp_coeffs; poly->alloc = FLINT_BITS; /* Ensure no reallocation in nmod_poly_randtest */ poly->length = d + 1; nmod_poly_randtest_monic_primitive(poly, state, d + 1); fq_nmod_ctx_init_modulus(fq_nmod_ctx, poly, var); /* No need to clear poly */ /* No need to clear state */ fq_zech_ctx_init_fq_nmod_ctx(ctx, fq_nmod_ctx); ctx->owns_fq_nmod_ctx = 1; ctx->is_conway = 0; } int fq_zech_ctx_init_modulus_check(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char * var) { int primitive; fq_nmod_ctx_struct * fq_nmod_ctx; fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); fq_nmod_ctx_init_modulus(fq_nmod_ctx, modulus, var); primitive = fq_zech_ctx_init_fq_nmod_ctx_check(ctx, fq_nmod_ctx); ctx->owns_fq_nmod_ctx = 1; return primitive; } void fq_zech_ctx_init_modulus(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char * var) { fq_zech_ctx_init_modulus_check(ctx, modulus, var); } int fq_zech_ctx_init_fq_nmod_ctx_check(fq_zech_ctx_t ctx, fq_nmod_ctx_t ctx2) { ulong i, n; fq_nmod_t r, gen; slong up, q; ulong result; ulong j, nz; mp_ptr n_reverse_table; ctx->fq_nmod_ctx = ctx2; ctx->owns_fq_nmod_ctx = 0; up = fq_nmod_ctx_prime(ctx2); q = _n_pow_check(up, fq_nmod_ctx_degree(ctx2)); if (!q) flint_throw(FLINT_ERROR, "Exception (fq_zech_ctx_init_fq_nmod_ctx). " "Requires q < 2^FLINT_BITS\n"); ctx->p = up; ctx->ppre = n_precompute_inverse(ctx->p); ctx->qm1 = q - 1; if (up == 2) { ctx->qm1o2 = 0; } else { ctx->qm1o2 = ctx->qm1 / 2; } ctx->qm1opm1 = ctx->qm1 / (up - 1); /* 1. The field may not be defined with a Conway polynomial * 2. need to ensure prime_root is the norm of the generator * 3. so we take prime_root = (-1)^d * a_0, where d is the degree * of the minimum polynomial P of the generator, and a_0 is the constant term of * the generator. * 4. this is because if P(t) = (t-x_0)...(t-x_{d-1}), then the constant term of * P is the product of the x_i (ie the norm) and is equal to (-1)^d * a_0 */ ctx->prime_root = (fq_nmod_ctx_degree(ctx2) & 1) ? up - ctx2->a[0] : ctx2->a[0]; /* NOTE: Only malloc once for tables */ ctx->zech_log_table = flint_malloc(sizeof(ulong) * (2 * q + up)); ctx->prime_field_table = ctx->zech_log_table + q; ctx->eval_table = ctx->prime_field_table + up; n_reverse_table = flint_malloc(sizeof(ulong) * q); ctx->zech_log_table[ctx->qm1] = 0; ctx->prime_field_table[0] = ctx->qm1; for (i = 0; i < q; i++) n_reverse_table[i] = ctx->qm1; ctx->eval_table[ctx->qm1] = 0; fq_nmod_init(r, ctx->fq_nmod_ctx); fq_nmod_init(gen, ctx->fq_nmod_ctx); fq_nmod_one(r, ctx->fq_nmod_ctx); fq_nmod_gen(gen, ctx->fq_nmod_ctx); for (i = 0; i < ctx->qm1; i++) { result = _nmod_poly_evaluate_ui(r->coeffs, r->length, up); if (n_reverse_table[result] != ctx->qm1) { fq_nmod_clear(r, ctx2); fq_nmod_clear(gen, ctx2); flint_free(n_reverse_table); fq_zech_ctx_clear(ctx); return 0; /* failure: modulus not primitive */ } n_reverse_table[result] = i; ctx->eval_table[i] = result; if (r->length == 1) ctx->prime_field_table[result] = i; fq_nmod_mul(r, r, gen, ctx2); } i = 1; for (i = 0; i < q; i++) { j = n_reverse_table[i]; n = i; if (n % up == up - 1) { nz = n - up + 1; } else { nz = n + 1; } ctx->zech_log_table[j] = n_reverse_table[nz]; } fq_nmod_clear(r, ctx2); fq_nmod_clear(gen, ctx2); flint_free(n_reverse_table); return 1; /* success */ } void fq_zech_ctx_init_fq_nmod_ctx(fq_zech_ctx_t ctx, fq_nmod_ctx_t fq_nmod_ctx) { if (!fq_zech_ctx_init_fq_nmod_ctx_check(ctx, fq_nmod_ctx)) flint_throw(FLINT_ERROR, "(fq_zech_ctx_init_fq_nmod_ctx): " "Polynomial is not primitive.\n"); } void fq_zech_ctx_init_randtest(fq_zech_ctx_t ctx, flint_rand_t state, int type) { slong deg; ulong prime; /* Big prime < 2^5, big degree <= 4 */ /* Small prime < 2^4, small degree <= 3 */ switch (type) { case 0: prime = n_randprime(state, 2 + n_randint(state, 4), 1); deg = 1 + n_randint(state, 4); break; case 1: prime = n_randprime(state, 2 + n_randint(state, 4), 1); deg = 1 + n_randint(state, 3); break; case 2: prime = n_randprime(state, 2 + n_randint(state, 3), 1); deg = 1 + n_randint(state, 4); break; case 3: prime = n_randprime(state, 2 + n_randint(state, 3), 1); deg = 1 + n_randint(state, 3); break; default: FLINT_UNREACHABLE; } fq_zech_ctx_init_random_ui(ctx, prime, deg, "a"); ctx->owns_fq_nmod_ctx = 1; } void fq_zech_ctx_init_randtest_reducible(fq_zech_ctx_t ctx, flint_rand_t state, int type) { fq_zech_ctx_init_randtest(ctx, state, type); } void fq_zech_ctx_clear(fq_zech_ctx_t ctx) { /* NOTE: Only zech_log_table of the three tables was assigned by malloc */ flint_free(ctx->zech_log_table); if (ctx->owns_fq_nmod_ctx) { fq_nmod_ctx_clear(ctx->fq_nmod_ctx); flint_free(ctx->fq_nmod_ctx); } } void fq_zech_ctx_order(fmpz_t f, const fq_zech_ctx_t ctx) { fq_nmod_ctx_order(f, ctx->fq_nmod_ctx); } /* Deprecated functions ******************************************************/ void fq_zech_ctx_init(fq_zech_ctx_t ctx, fmpz_t p, slong d, const char * var) { fq_zech_ctx_init_ui(ctx, fmpz_get_ui(p), d, var); } int _fq_zech_ctx_init_conway(fq_zech_ctx_t ctx, fmpz_t p, slong d, const char * var) { return _fq_zech_ctx_init_conway_ui(ctx, fmpz_get_ui(p), d, var); } void fq_zech_ctx_init_conway(fq_zech_ctx_t ctx, fmpz_t p, slong d, const char * var) { fq_zech_ctx_init_conway_ui(ctx, fmpz_get_ui(p), d, var); } void fq_zech_ctx_init_random(fq_zech_ctx_t ctx, fmpz_t p, slong d, const char * var) { fq_zech_ctx_init_random_ui(ctx, fmpz_get_ui(p), d, var); } flint-3.1.3/src/fq_zech/embed_templates.c000066400000000000000000000014301461254215100203350ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #include "fq_zech_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_zech #define CAP_T FQ_ZECH #define B nmod #include "fq_embed_templates/embed.c" #include "fq_embed_templates/matrices.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_zech/frobenius.c000066400000000000000000000017221461254215100172030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" void fq_zech_frobenius(fq_zech_t rop, const fq_zech_t op, slong e, const fq_zech_ctx_t ctx) { double qm1_inv; slong d = fq_zech_ctx_degree(ctx); e = e % d; if (e < 0) e += d; if (fq_zech_is_zero(op, ctx)) { fq_zech_zero(rop, ctx); } else if (e == 0) { fq_zech_set(rop, op, ctx); } else { qm1_inv = n_precompute_inverse(ctx->qm1); e = n_powmod(ctx->p, e, ctx->qm1); rop->value = n_mulmod_precomp(op->value, e, ctx->qm1, qm1_inv); } } flint-3.1.3/src/fq_zech/gcdinv.c000066400000000000000000000012311461254215100164540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" void fq_zech_gcdinv(fq_zech_t rop, fq_zech_t inv, const fq_zech_t op, const fq_zech_ctx_t ctx) { if (fq_zech_is_zero(op, ctx)) { fq_zech_zero(rop, ctx); return; } fq_zech_one(rop, ctx); fq_zech_inv(inv, op, ctx); } flint-3.1.3/src/fq_zech/get_fmpz.c000066400000000000000000000011511461254215100170160ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" int fq_zech_get_fmpz(fmpz_t a, const fq_zech_t b, const fq_zech_ctx_t ctx) { ulong q = ctx->eval_table[b->value]; if (q >= ctx->p) return 0; fmpz_set_ui(a, q); return 1; } flint-3.1.3/src/fq_zech/get_fq_nmod.c000066400000000000000000000016371461254215100174760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fq_zech.h" void fq_zech_get_fq_nmod(fq_nmod_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) { slong i; mp_limb_t q, r; nmod_poly_fit_length(rop, fq_zech_ctx_degree(ctx)); nmod_poly_zero(rop); q = ctx->eval_table[op->value]; i = 0; while (q >= ctx->p) { r = n_divrem2_precomp(&q, q, ctx->p, ctx->ppre); nmod_poly_set_coeff_ui(rop, i, r); i ++; } nmod_poly_set_coeff_ui(rop, i, q); } flint-3.1.3/src/fq_zech/get_nmod_poly.c000066400000000000000000000017161461254215100200510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fq_zech.h" void fq_zech_get_nmod_poly(nmod_poly_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) { slong i; mp_limb_t q, r; rop->mod = ctx->fq_nmod_ctx->modulus->mod; nmod_poly_fit_length(rop, fq_zech_ctx_degree(ctx)); q = ctx->eval_table[op->value]; i = 0; while (q >= ctx->p) { r = n_divrem2_precomp(&q, q, ctx->p, ctx->ppre); nmod_poly_set_coeff_ui(rop, i, r); i ++; } nmod_poly_set_coeff_ui(rop, i, q); } flint-3.1.3/src/fq_zech/get_set_fmpz_mod_mat.c000066400000000000000000000021051461254215100213710ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_zech.h" void fq_zech_get_nmod_mat(nmod_mat_t col, const fq_zech_t a, const fq_zech_ctx_t ctx) { fq_nmod_t tmp; fq_nmod_init(tmp, ctx->fq_nmod_ctx); fq_zech_get_fq_nmod(tmp, a, ctx); fq_nmod_get_nmod_mat(col, tmp, ctx->fq_nmod_ctx); fq_nmod_clear(tmp, ctx->fq_nmod_ctx); } void fq_zech_set_nmod_mat(fq_zech_t a, const nmod_mat_t col, const fq_zech_ctx_t ctx) { fq_nmod_t tmp; fq_nmod_init(tmp, ctx->fq_nmod_ctx); fq_nmod_set_nmod_mat(tmp, col, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(a, tmp, ctx); fq_nmod_clear(tmp, ctx->fq_nmod_ctx); } flint-3.1.3/src/fq_zech/get_str.c000066400000000000000000000022311461254215100166520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "fq_zech.h" char * fq_zech_get_str(const fq_zech_t op, const fq_zech_ctx_t ctx) { slong num_chars = op->value == 0 ? 1 : n_clog(op->value + 1, 10); char *s = flint_malloc((num_chars + 1)* sizeof(char)); flint_sprintf(s, "%wd", op->value); return s; } char * fq_zech_get_str_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx) { char * s; if (fq_zech_is_zero(op, ctx)) { s = flint_malloc(2*sizeof(char)); flint_sprintf(s, "0"); } else { slong num_chars = op->value == 0 ? 1 : n_clog(op->value + 1, 10); s = flint_malloc((num_chars + strlen(ctx->fq_nmod_ctx->var) + 2) * sizeof(char)); flint_sprintf(s, "%s^%wd", ctx->fq_nmod_ctx->var, op->value); } return s; } flint-3.1.3/src/fq_zech/inlines.c000066400000000000000000000006521461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_INLINES_C #include "fq_zech.h" flint-3.1.3/src/fq_zech/inv.c000066400000000000000000000013461461254215100160050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" void fq_zech_inv(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) { if (fq_zech_is_zero(op, ctx)) { flint_throw(FLINT_ERROR, "Exception (fq_inv). Zero is not invertible.\n"); } if (fq_zech_is_one(op, ctx)) { fq_zech_one(rop, ctx); return; } rop->value = ctx->qm1 - op->value; } flint-3.1.3/src/fq_zech/io.c000066400000000000000000000024661461254215100156240ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fq_nmod.h" #include "fq_zech.h" /* printing *******************************************************************/ int fq_zech_ctx_fprint(FILE * file, const fq_zech_ctx_t ctx) { int r; r = flint_fprintf(file, "Zech Representation:\n"); if (r <= 0) return r; return fq_nmod_ctx_fprint(file, ctx->fq_nmod_ctx); } void fq_zech_ctx_print(const fq_zech_ctx_t ctx) { fq_zech_ctx_fprint(stdout, ctx); } int fq_zech_fprint(FILE * file, const fq_zech_t op, const fq_zech_ctx_t ctx) { return flint_fprintf(file, "%wd", op->value); } void fq_zech_print(const fq_zech_t op, const fq_zech_ctx_t ctx) { fq_zech_fprint(stdout, op, ctx); } int fq_zech_fprint_pretty(FILE * file, const fq_zech_t op, const fq_zech_ctx_t ctx) { return flint_fprintf(file, "%s^%wd", ctx->fq_nmod_ctx->var, op->value); } void fq_zech_print_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx) { fq_zech_fprint_pretty(stdout, op, ctx); } flint-3.1.3/src/fq_zech/is_square.c000066400000000000000000000011331461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" int fq_zech_is_square(const fq_zech_t op1, const fq_zech_ctx_t ctx) { if (fq_zech_is_zero(op1, ctx) || fq_zech_is_one(op1, ctx) || ctx->p == 2) return 1; return (op1->value & 1) == 0; } flint-3.1.3/src/fq_zech/mat_templates.c000066400000000000000000000056331461254215100200530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2015 Elena Sergeicheva Copyright (C) 2015, 2020, 2021 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_mod_mat.h" #include "fq_nmod.h" #include "fq_zech.h" #include "fq_zech_vec.h" #include "fq_zech_mat.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/add.c" #include "fq_mat_templates/can_solve.c" #include "fq_mat_templates/charpoly.c" #include "fq_mat_templates/clear.c" #include "fq_mat_templates/concat_horizontal.c" #include "fq_mat_templates/concat_vertical.c" #include "fq_mat_templates/equal.c" #include "fq_mat_templates/init.c" #include "fq_mat_templates/init_set.c" #include "fq_mat_templates/inv.c" #include "fq_mat_templates/io.c" #include "fq_mat_templates/is_one.c" #include "fq_mat_templates/is_zero.c" #include "fq_mat_templates/lu.c" #include "fq_mat_templates/lu_classical.c" #include "fq_mat_templates/lu_recursive.c" #include "fq_mat_templates/mat_entry_set.c" #include "fq_mat_templates/mat_invert_cols.c" #include "fq_mat_templates/mat_swap_cols.c" #include "fq_mat_templates/mat_swap_entrywise.c" #include "fq_mat_templates/minpoly.c" #include "fq_mat_templates/mul.c" #include "fq_mat_templates/mul_classical.c" #include "fq_mat_templates/mul_KS.c" #include "fq_mat_templates/mul_vec.c" #include "fq_mat_templates/neg.c" #include "fq_mat_templates/nullspace.c" #include "fq_mat_templates/one.c" #include "fq_mat_templates/randops.c" #include "fq_mat_templates/randpermdiag.c" #include "fq_mat_templates/randrank.c" #include "fq_mat_templates/randtest.c" #include "fq_mat_templates/randtril.c" #include "fq_mat_templates/randtriu.c" #include "fq_mat_templates/rank.c" #include "fq_mat_templates/reduce_row.c" #include "fq_mat_templates/rref.c" #include "fq_mat_templates/set.c" #include "fq_mat_templates/set_fmpz_mod_mat.c" #include "fq_mat_templates/set_nmod_mat.c" #include "fq_mat_templates/similarity.c" #include "fq_mat_templates/solve.c" #include "fq_mat_templates/solve_tril.c" #include "fq_mat_templates/solve_tril_classical.c" #include "fq_mat_templates/solve_tril_recursive.c" #include "fq_mat_templates/solve_triu.c" #include "fq_mat_templates/solve_triu_classical.c" #include "fq_mat_templates/solve_triu_recursive.c" #include "fq_mat_templates/sub.c" #include "fq_mat_templates/submul.c" #include "fq_mat_templates/swap.c" #include "fq_mat_templates/vec_mul.c" #include "fq_mat_templates/window_clear.c" #include "fq_mat_templates/window_init.c" #include "fq_mat_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/modulus_pow_series_inv.c000066400000000000000000000016151461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_zech.h" #include "fq_zech_embed.h" #define T fq_zech #define B nmod void TEMPLATE(T, modulus_pow_series_inv)(TEMPLATE(B, poly_t) res, const TEMPLATE(T, ctx_t) ctx, slong trunc) { TEMPLATE(B, poly_reverse)(res, TEMPLATE(T, ctx_modulus)(ctx), TEMPLATE(T, ctx_degree)(ctx) + 1); TEMPLATE(B, poly_inv_series)(res, res, trunc); } #undef B #undef T flint-3.1.3/src/fq_zech/mul.c000066400000000000000000000035611461254215100160070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq_zech.h" void fq_zech_mul(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) { if (op1->value == ctx->qm1 || op2->value == ctx->qm1) { rop->value = ctx->qm1; return; } rop->value = n_addmod(op1->value, op2->value, ctx->qm1); } void fq_zech_mul_fmpz(fq_zech_t rop, const fq_zech_t op, const fmpz_t x, const fq_zech_ctx_t ctx) { mp_limb_t ux; fmpz_t y; fmpz_init(y); fmpz_mod_ui(y, x, ctx->p); ux = fmpz_get_ui(y); fmpz_clear(y); fq_zech_mul_ui(rop, op, ux, ctx); } void fq_zech_mul_si(fq_zech_t rop, const fq_zech_t op, slong x, const fq_zech_ctx_t ctx) { mp_limb_t y; if (x == 0 || fq_zech_is_zero(op, ctx)) { fq_zech_zero(rop, ctx); return; } if (x < 0) { y = -x; fq_zech_mul_ui(rop, op, y, ctx); fq_zech_neg(rop, rop, ctx); } else { y = x; fq_zech_mul_ui(rop, op, y, ctx); } } void fq_zech_mul_ui(fq_zech_t rop, const fq_zech_t op, mp_limb_t x, const fq_zech_ctx_t ctx) { mp_limb_t b; if (x == 0 || fq_zech_is_zero(op, ctx)) { fq_zech_zero(rop, ctx); return; } b = x; if (x >= ctx->p) b = n_mod2_precomp(x, ctx->p, ctx->ppre); if (b == 0) fq_zech_zero(rop, ctx); else rop->value = n_addmod(op->value, ctx->prime_field_table[b], ctx->qm1); } flint-3.1.3/src/fq_zech/neg.c000066400000000000000000000012621461254215100157570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" void fq_zech_neg(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx) { if (op1->value == ctx->qm1) { rop->value = ctx->qm1; return; } rop->value = op1->value + ctx->qm1o2; if (rop->value >= ctx->qm1) { rop->value -= ctx->qm1; } } flint-3.1.3/src/fq_zech/norm.c000066400000000000000000000012551461254215100161630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq_zech.h" void fq_zech_norm(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) { if (fq_zech_is_zero(op, ctx)) { fmpz_zero(rop); } else { fmpz_set_ui(rop, n_powmod(ctx->prime_root, op->value, ctx->p)); } } flint-3.1.3/src/fq_zech/poly_factor_templates.c000066400000000000000000000037601461254215100216120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2019 Edouard Rousseau Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_zech.h" #include "fq_zech_vec.h" #include "fq_zech_mat.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/clear.c" #include "fq_poly_factor_templates/concat.c" #include "fq_poly_factor_templates/factor_berlekamp.c" #include "fq_poly_factor_templates/factor.c" #include "fq_poly_factor_templates/factor_cantor_zassenhaus.c" #include "fq_poly_factor_templates/factor_distinct_deg.c" #include "fq_poly_factor_templates/factor_equal_deg.c" #include "fq_poly_factor_templates/factor_equal_deg_prob.c" #include "fq_poly_factor_templates/factor_kaltofen_shoup.c" #include "fq_poly_factor_templates/factor_split_single.c" #include "fq_poly_factor_templates/factor_squarefree.c" #include "fq_poly_factor_templates/fit_length.c" #include "fq_poly_factor_templates/init.c" #include "fq_poly_factor_templates/insert.c" #include "fq_poly_factor_templates/is_irreducible_ben_or.c" #include "fq_poly_factor_templates/is_irreducible.c" #include "fq_poly_factor_templates/is_irreducible_ddf.c" #include "fq_poly_factor_templates/is_squarefree.c" #include "fq_poly_factor_templates/iterated_frobenius_preinv.c" #include "fq_poly_factor_templates/pow.c" #include "fq_poly_factor_templates/print.c" #include "fq_poly_factor_templates/print_pretty.c" #include "fq_poly_factor_templates/realloc.c" #include "fq_poly_factor_templates/roots.c" #include "fq_poly_factor_templates/set.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/poly_templates.c000066400000000000000000000120431461254215100202460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012, 2014 William Hart Copyright (C) 2013 Mike Hansen Copyright (C) 2017 Luca De Feo Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "fq_zech.h" #include "fq_zech_vec.h" #include "fq_zech_mat.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/add.c" #include "fq_poly_templates/add_series.c" #include "fq_poly_templates/add_si.c" #include "fq_poly_templates/clear.c" #include "fq_poly_templates/comparisons.c" #include "fq_poly_templates/compose.c" #include "fq_poly_templates/compose_mod.c" #include "fq_poly_templates/compose_mod_brent_kung.c" #include "fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c" #include "fq_poly_templates/compose_mod_brent_kung_preinv.c" #include "fq_poly_templates/compose_mod_horner.c" #include "fq_poly_templates/compose_mod_horner_preinv.c" #include "fq_poly_templates/compose_mod_preinv.c" #include "fq_poly_templates/deflate.c" #include "fq_poly_templates/deflation.c" #include "fq_poly_templates/derivative.c" #include "fq_poly_templates/div.c" #include "fq_poly_templates/div_newton_n_preinv.c" #include "fq_poly_templates/div_series.c" #include "fq_poly_templates/divides.c" #include "fq_poly_templates/divrem.c" #include "fq_poly_templates/divrem_f.c" #include "fq_poly_templates/divrem_newton_n_preinv.c" #include "fq_poly_templates/equal.c" #include "fq_poly_templates/equal_trunc.c" #include "fq_poly_templates/evaluate_fq.c" #include "fq_poly_templates/evaluate_fq_vec.c" #include "fq_poly_templates/evaluate_fq_vec_fast.c" #include "fq_poly_templates/evaluate_fq_vec_iter.c" #include "fq_poly_templates/fit_length.c" #include "fq_poly_templates/gcd.c" #include "fq_poly_templates/gcd_euclidean_f.c" #include "fq_poly_templates/gen.c" #include "fq_poly_templates/get_coeff.c" #include "fq_poly_templates/get_str.c" #include "fq_poly_templates/get_str_pretty.c" #include "fq_poly_templates/hamming_weight.c" #include "fq_poly_templates/inflate.c" #include "fq_poly_templates/init.c" #include "fq_poly_templates/inv_series_newton.c" #include "fq_poly_templates/invsqrt_series.c" #include "fq_poly_templates/io.c" #include "fq_poly_templates/is_gen.c" #include "fq_poly_templates/make_monic.c" #include "fq_poly_templates/mul.c" #include "fq_poly_templates/mul_classical.c" #include "fq_poly_templates/mul_KS.c" /* #include "fq_poly_templates/mul_reorder.c" */ #include "fq_poly_templates/mulhigh.c" #include "fq_poly_templates/mulhigh_classical.c" #include "fq_poly_templates/mullow.c" #include "fq_poly_templates/mullow_classical.c" #include "fq_poly_templates/mullow_KS.c" #include "fq_poly_templates/mulmod.c" #include "fq_poly_templates/mulmod_preinv.c" #include "fq_poly_templates/neg.c" #include "fq_poly_templates/normalise.c" #include "fq_poly_templates/one.c" #include "fq_poly_templates/pow.c" #include "fq_poly_templates/pow_trunc.c" #include "fq_poly_templates/pow_trunc_binexp.c" #include "fq_poly_templates/powmod_fmpz_binexp.c" #include "fq_poly_templates/powmod_fmpz_binexp_preinv.c" #include "fq_poly_templates/powmod_fmpz_sliding_preinv.c" #include "fq_poly_templates/powmod_ui_binexp.c" #include "fq_poly_templates/powmod_ui_binexp_preinv.c" #include "fq_poly_templates/powmod_x_fmpz_preinv.c" #include "fq_poly_templates/randtest.c" #include "fq_poly_templates/randtest_irreducible.c" #include "fq_poly_templates/randtest_monic.c" #include "fq_poly_templates/realloc.c" #include "fq_poly_templates/rem.c" #include "fq_poly_templates/remove.c" #include "fq_poly_templates/reverse.c" #include "fq_poly_templates/scalar_addmul_fq.c" #include "fq_poly_templates/scalar_div_fq.c" #include "fq_poly_templates/scalar_mul_fq.c" #include "fq_poly_templates/scalar_submul_fq.c" #include "fq_poly_templates/set.c" #include "fq_poly_templates/set_coeff.c" #include "fq_poly_templates/set_fmpz_mod_poly.c" #include "fq_poly_templates/set_fq.c" #include "fq_poly_templates/set_length.c" #include "fq_poly_templates/set_nmod_poly.c" #include "fq_poly_templates/set_trunc.c" #include "fq_poly_templates/shift_left.c" #include "fq_poly_templates/shift_right.c" #include "fq_poly_templates/sqr.c" #include "fq_poly_templates/sqr_classical.c" #include "fq_poly_templates/sqr_KS.c" /* #include "fq_poly_templates/sqr_reorder.c" */ #include "fq_poly_templates/sqrt.c" #include "fq_poly_templates/sqrt_series.c" #include "fq_poly_templates/sub.c" #include "fq_poly_templates/sub_series.c" #include "fq_poly_templates/swap.c" #include "fq_poly_templates/tree.c" #include "fq_poly_templates/truncate.c" #include "fq_poly_templates/xgcd.c" #include "fq_poly_templates/xgcd_euclidean_f.c" #include "fq_poly_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/pow.c000066400000000000000000000025221461254215100160130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" void fq_zech_pow(fq_zech_t rop, const fq_zech_t op, const fmpz_t e, const fq_zech_ctx_t ctx) { if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "Exception (fq_zech_pow). e < 0.\n"); } if (fmpz_is_zero(e)) { fq_zech_one(rop, ctx); } else if (fq_zech_is_zero(op, ctx)) { fq_zech_zero(rop, ctx); } else if (fmpz_is_one(e)) { fq_zech_set(rop, op, ctx); } else { fmpz_t new_e; fmpz_init(new_e); fmpz_mul_ui(new_e, e, op->value); fmpz_mod_ui(new_e, new_e, ctx->qm1); rop->value = fmpz_get_ui(new_e); fmpz_clear(new_e); } } /* TODO: Move into separate function and optimize */ void fq_zech_pow_ui(fq_zech_t rop, const fq_zech_t op, const ulong e, const fq_zech_ctx_t ctx) { fmpz_t exp; fmpz_init_set_ui(exp, e); fq_zech_pow(rop, op, exp, ctx); fmpz_clear(exp); } flint-3.1.3/src/fq_zech/pth_root.c000066400000000000000000000016211461254215100170430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" void fq_zech_pth_root(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx) { slong i, d; mp_limb_t e; double qm1inv; if (fq_zech_is_zero(op1, ctx) || fq_zech_is_one(op1, ctx)) { rop->value = op1->value; return; } d = fq_zech_ctx_degree(ctx) - 1; qm1inv = n_precompute_inverse(ctx->qm1); e = op1->value; for (i = 0; i < d; i++) { e = n_mulmod_precomp(ctx->p, e, ctx->qm1, qm1inv); } rop->value = e; } flint-3.1.3/src/fq_zech/rand.c000066400000000000000000000012721461254215100161330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" void fq_zech_rand(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) { rop->value = n_urandint(state, ctx->qm1 + 1); } void fq_zech_rand_not_zero(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) { rop->value = n_urandint(state, ctx->qm1); } flint-3.1.3/src/fq_zech/randtest.c000066400000000000000000000013271461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" void fq_zech_randtest(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) { rop->value = n_randint(state, ctx->qm1 + 1); } void fq_zech_randtest_not_zero(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx) { rop->value = n_randint(state, ctx->qm1); } flint-3.1.3/src/fq_zech/set.c000066400000000000000000000014101461254215100157740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" void fq_zech_set_si(fq_zech_t rop, const slong x, const fq_zech_ctx_t ctx) { fmpz_t xx; fmpz_init_set_si(xx, x); fq_zech_set_fmpz(rop, xx, ctx); fmpz_clear(xx); } void fq_zech_set_ui(fq_zech_t rop, const ulong x, const fq_zech_ctx_t ctx) { fmpz_t xx; fmpz_init_set_ui(xx, x); fq_zech_set_fmpz(rop, xx, ctx); fmpz_clear(xx); } flint-3.1.3/src/fq_zech/set_fmpz.c000066400000000000000000000013231461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" void fq_zech_set_fmpz(fq_zech_t rop, const fmpz_t x, const fq_zech_ctx_t ctx) { /* TODO: Clean this up */ mp_limb_t ux; fmpz_t y; fmpz_init(y); fmpz_mod_ui(y, x, ctx->p); ux = fmpz_get_ui(y); fq_zech_one(rop, ctx); fq_zech_mul_ui(rop, rop, ux, ctx); fmpz_clear(y); } flint-3.1.3/src/fq_zech/set_fq_nmod.c000066400000000000000000000014201461254215100175000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" void fq_zech_set_fq_nmod(fq_zech_t rop, const fq_nmod_t op, const fq_zech_ctx_t ctx) { mp_limb_t i; fq_zech_t t; fq_zech_zero(rop, ctx); for (i = 0; i < op->length; i++) { if (op->coeffs[i] == 0) { continue; } t->value = i; fq_zech_mul_ui(t, t, op->coeffs[i], ctx); fq_zech_add(rop, rop, t, ctx); } } flint-3.1.3/src/fq_zech/set_nmod_poly.c000066400000000000000000000016471461254215100200700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" void fq_zech_set_nmod_poly(fq_zech_t a, const nmod_poly_t b, const fq_zech_ctx_t ctx) { slong blen = b->length; const mp_limb_t * bcoeffs = b->coeffs; mp_limb_t qm1 = ctx->qm1; mp_limb_t i; fq_zech_t t; fq_zech_zero(a, ctx); for (i = 0; i < blen; i++) { if (bcoeffs[i] == 0) continue; t->value = (blen <= qm1) ? i : (i % qm1); fq_zech_mul_ui(t, t, bcoeffs[i], ctx); fq_zech_add(a, a, t, ctx); } } flint-3.1.3/src/fq_zech/sqr.c000066400000000000000000000012301461254215100160060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" void fq_zech_sqr(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) { if (op->value == ctx->qm1) { rop->value = ctx->qm1; } else { rop->value = n_addmod(op->value, op->value, ctx->qm1); } } flint-3.1.3/src/fq_zech/sqrt.c000066400000000000000000000015021461254215100161740ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" int fq_zech_sqrt(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx) { if (fq_zech_is_zero(op1, ctx) || fq_zech_is_one(op1, ctx)) { rop->value = op1->value; } else if (ctx->p == 2) { rop->value = op1->value & 1 ? (op1->value + ctx->qm1)/2 : op1->value/2; } else { if (op1->value & 1) /* not a square */ return 0; rop->value = op1->value/2; } return 1; } flint-3.1.3/src/fq_zech/sub.c000066400000000000000000000020011461254215100157670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" void fq_zech_sub(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx) { mp_limb_t index, c; if (op2->value == ctx->qm1) { rop->value = op1->value; } else if (op1->value == ctx->qm1) { fq_zech_neg(rop, op2, ctx); } else { index = n_submod(op2->value, op1->value, ctx->qm1); index = n_submod(index, ctx->qm1o2, ctx->qm1); c = ctx->zech_log_table[index]; if (c != ctx->qm1) { c = n_addmod(c, op1->value, ctx->qm1); } rop->value = c; } } flint-3.1.3/src/fq_zech/sub_one.c000066400000000000000000000011621461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" void fq_zech_sub_one(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx) { fq_zech_t one; fq_zech_init(one, ctx); fq_zech_one(one, ctx); fq_zech_sub(rop, op1, one, ctx); fq_zech_clear(one, ctx); } flint-3.1.3/src/fq_zech/templates.c000066400000000000000000000013261461254215100172050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/div.c" #include "fq_templates/is_invertible.c" #include "fq_templates/is_invertible_f.c" #include "fq_templates/multiplicative_order.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/000077500000000000000000000000001461254215100160205ustar00rootroot00000000000000flint-3.1.3/src/fq_zech/test/main.c000066400000000000000000000042661461254215100171200ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-assign.c" #include "t-ctx_init_ui.c" #include "t-div.c" #include "t-frobenius.c" #include "t-get_set_fmpz.c" #include "t-get_set_fq_nmod.c" #include "t-get_set_nmod_poly.c" #include "t-inv.c" #include "t-is_invertible.c" #include "t-is_invertible_f.c" #include "t-is_primitive.c" #include "t-is_square.c" #include "t-mul.c" #include "t-mul_fmpz.c" #include "t-multiplicative_order.c" #include "t-mul_ui.c" #include "t-neg.c" #include "t-norm.c" #include "t-pow.c" #include "t-pth_root.c" #include "t-sqr.c" #include "t-sqrt.c" #include "t-sub.c" #include "t-trace.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_zech_add), TEST_FUNCTION(fq_zech_assign), TEST_FUNCTION(fq_zech_ctx_init_ui), TEST_FUNCTION(fq_zech_div), TEST_FUNCTION(fq_zech_frobenius), TEST_FUNCTION(fq_zech_get_set_fmpz), TEST_FUNCTION(fq_zech_get_set_fq_nmod), TEST_FUNCTION(fq_zech_get_set_nmod_poly), TEST_FUNCTION(fq_zech_inv), TEST_FUNCTION(fq_zech_is_invertible), TEST_FUNCTION(fq_zech_is_invertible_f), TEST_FUNCTION(fq_zech_is_primitive), TEST_FUNCTION(fq_zech_is_square), TEST_FUNCTION(fq_zech_mul), TEST_FUNCTION(fq_zech_mul_fmpz), TEST_FUNCTION(fq_zech_multiplicative_order), TEST_FUNCTION(fq_zech_mul_ui), TEST_FUNCTION(fq_zech_neg), TEST_FUNCTION(fq_zech_norm), TEST_FUNCTION(fq_zech_pow), TEST_FUNCTION(fq_zech_pth_root), TEST_FUNCTION(fq_zech_sqr), TEST_FUNCTION(fq_zech_sqrt), TEST_FUNCTION(fq_zech_sub), TEST_FUNCTION(fq_zech_trace) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_zech/test/t-add.c000066400000000000000000000012001461254215100171460ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-assign.c000066400000000000000000000010171461254215100177100ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-assign.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-ctx_init_ui.c000066400000000000000000000062151461254215100207470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_ctx_init_ui, state) { ulong primes[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 }; slong exponents[10] = { 16, 10, 6, 5, 4, 4, 3, 3, 3, 3 }; int i, j, random; slong d; fmpz_t e; fq_nmod_ctx_struct *fq_nmod_ctx; fq_nmod_t lhs, rhs, one; fq_zech_ctx_t ctx; fmpz_init(e); for (i = 0; i < 10; i++) { for (d = 2; d < exponents[i]; d++) { for (random = 0; random <= 1; random++) { if (random) fq_zech_ctx_init_random_ui(ctx, primes[i], d, "a"); else fq_zech_ctx_init_conway_ui(ctx, primes[i], d, "a"); fq_nmod_ctx = ctx->fq_nmod_ctx; fq_nmod_init(lhs, fq_nmod_ctx); fq_nmod_init(rhs, fq_nmod_ctx); fq_nmod_init(one, fq_nmod_ctx); fq_nmod_one(one, fq_nmod_ctx); for (j = 0; j < ctx->qm1; j++) { /* Skip the cases where a^j + 1 == 0 */ if (primes[i] == 2 && i == 0) { continue; } if (j == ctx->qm1 / 2) { continue; } /* lhs = a^Z(j) */ fmpz_set_ui(e, ctx->zech_log_table[j]); fq_nmod_gen(lhs, fq_nmod_ctx); fq_nmod_pow(lhs, lhs, e, fq_nmod_ctx); /* rhs = a^j + 1 */ fmpz_set_ui(e, j); fq_nmod_gen(rhs, fq_nmod_ctx); fq_nmod_pow(rhs, rhs, e, fq_nmod_ctx); fq_nmod_add(rhs, rhs, one, fq_nmod_ctx); if (!fq_nmod_equal(lhs, rhs, fq_nmod_ctx)) { flint_printf("FAIL:\n\n"); flint_printf("K = GF(%wd^%wd)\n", primes[i], d); flint_printf("Z(%d) = %wd\n", j, ctx->zech_log_table[j]); flint_printf("LHS: "); fq_nmod_print_pretty(lhs, fq_nmod_ctx); flint_printf("\n"); flint_printf("RHS: "); fq_nmod_print_pretty(rhs, fq_nmod_ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } fq_nmod_clear(lhs, fq_nmod_ctx); fq_nmod_clear(rhs, fq_nmod_ctx); fq_nmod_clear(one, fq_nmod_ctx); fq_zech_ctx_clear(ctx); } } } fmpz_clear(e); TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-div.c000066400000000000000000000010141461254215100172030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-div.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-frobenius.c000066400000000000000000000056461461254215100204340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_frobenius, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 2); /* Check aliasing: a = frob(a, e) */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b; fmpz_t e; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fmpz_init(e); fq_zech_randtest(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); fq_zech_frobenius(b, a, fmpz_get_ui(e), ctx); fq_zech_frobenius(a, a, fmpz_get_ui(e), ctx); result = (fq_zech_equal(a, b, ctx)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fmpz_clear(e); } /* Compare with exponentiation, for integral values */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c; fmpz_t e, f; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fmpz_init(f); fmpz_init(e); fq_zech_randtest(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); fq_zech_frobenius(b, a, fmpz_get_ui(e), ctx); fmpz_ui_pow_ui(e, fq_zech_ctx_prime(ctx), fmpz_get_ui(e)); fq_zech_pow(c, a, e, ctx); result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL (cmp with pow):\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("e = "), fmpz_print(e), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); fmpz_clear(e); fmpz_clear(f); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-get_set_fmpz.c000066400000000000000000000010301461254215100211050ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-get_set_fmpz.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-get_set_fq_nmod.c000066400000000000000000000034531461254215100215670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_get_set_fq_nmod, state) { slong ix, jx; int result; for (ix = 0; ix < 200 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_t a, b; fq_nmod_t c; fq_zech_ctx_init_randtest(ctx, state, 3); fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_nmod_init(c, ctx->fq_nmod_ctx); for (jx = 0; jx < 20; jx++) { fq_zech_randtest(a, state, ctx); fq_zech_get_fq_nmod(c, a, ctx); fq_zech_set_fq_nmod(b, c, ctx); result = (fq_zech_equal(a, b, ctx)); if (!result) { flint_printf("FAIL:n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_nmod_print_pretty(c, ctx->fq_nmod_ctx), flint_printf("\n"); flint_printf("table = %wd\n", ctx->eval_table[a->value]); flint_abort(); } } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_nmod_clear(c, ctx->fq_nmod_ctx); fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-get_set_nmod_poly.c000066400000000000000000000040361461254215100221420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_get_set_nmod_poly, state) { slong i, j; fq_zech_ctx_t ctx; for (j = 0; j < 100 * flint_test_multiplier(); j++) { fq_zech_ctx_init_randtest(ctx, state, 1); for (i = 0; i < 10; i++) { fq_zech_t a, b; nmod_poly_t c, t; fq_zech_init(a, ctx); fq_zech_init(b, ctx); nmod_poly_init(c, 1); /* modulus don't care */ nmod_poly_init_mod(t, ctx->fq_nmod_ctx->modulus->mod); fq_zech_randtest(a, state, ctx); fq_zech_get_nmod_poly(c, a, ctx); nmod_poly_randtest(t, state, 20); nmod_poly_mul(t, t, ctx->fq_nmod_ctx->modulus); nmod_poly_add(c, c, t); fq_zech_set_nmod_poly(b, c, ctx); if (!fq_zech_equal(a, b, ctx)) { flint_printf("FAIL:n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), nmod_poly_print_pretty(c, "x"), flint_printf("\n"); flint_printf("table = %wd\n", ctx->eval_table[a->value]); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); nmod_poly_clear(c); nmod_poly_clear(t); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-inv.c000066400000000000000000000042071461254215100172240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_inv, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 1); for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c; int type; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_randtest_not_zero(a, state, ctx); type = n_randint(state, 2); if (type == 0) { /* Check aliasing: a = ~a */ fq_zech_set(b, a, ctx); fq_zech_inv(c, b, ctx); fq_zech_inv(b, b, ctx); result = (fq_zech_equal(b, c, ctx)); } else { /* Check a * ~a == 1 for units */ fq_zech_inv(b, a, ctx); fq_zech_mul(c, a, b, ctx); result = (fq_zech_is_one(c, ctx)); } if (!result) { flint_printf("FAIL:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); fq_zech_ctx_print(ctx); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-is_invertible.c000066400000000000000000000010261461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-is_invertible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-is_invertible_f.c000066400000000000000000000010301461254215100215620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-is_invertible_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-is_primitive.c000066400000000000000000000010251461254215100211260ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-is_primitive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-is_square.c000066400000000000000000000010231461254215100204140ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-is_square.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-mul.c000066400000000000000000000136151461254215100172300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_mul, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 1); /* Check aliasing: a = a * b */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_mul(c, a, b, ctx); fq_zech_mul(a, a, b, ctx); result = (fq_zech_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } /* Check aliasing: b = a * b */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_mul(c, a, b, ctx); fq_zech_mul(b, a, b, ctx); result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } /* Check aliasing: a = a * a */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, c; fq_zech_init(a, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_mul(c, a, a, ctx); fq_zech_mul(a, a, a, ctx); result = (fq_zech_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(c, ctx); } /* Check that a * b == b * a */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c1, c2; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c1, ctx); fq_zech_init(c2, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_mul(c1, a, b, ctx); fq_zech_mul(c2, b, a, ctx); result = (fq_zech_equal(c1, c2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c1 = "), fq_zech_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), fq_zech_print_pretty(c2, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c1, ctx); fq_zech_clear(c2, ctx); } /* Check that (a * b) * c == a * (b * c) */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c, lhs, rhs; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_init(lhs, ctx); fq_zech_init(rhs, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_randtest(c, state, ctx); fq_zech_mul(lhs, a, b, ctx); fq_zech_mul(lhs, lhs, c, ctx); fq_zech_mul(rhs, b, c, ctx); fq_zech_mul(rhs, a, rhs, ctx); result = (fq_zech_equal(lhs, rhs, ctx)); if (!result) { flint_printf("FAIL (a * b) * c == a * (b * c) :\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); flint_printf("lhs = "), fq_zech_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), fq_zech_print_pretty(rhs, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); fq_zech_clear(lhs, ctx); fq_zech_clear(rhs, ctx); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-mul_fmpz.c000066400000000000000000000072641461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_mul_fmpz, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 1); for (jx = 0; jx < 10; jx++) { fmpz_t x, p; fq_nmod_t aa, bb; fq_zech_t a, b, c; fq_nmod_init(aa, ctx->fq_nmod_ctx); fq_nmod_init(bb, ctx->fq_nmod_ctx); fmpz_init(x); fmpz_init_set_ui(p, fq_zech_ctx_prime(ctx)); fmpz_randtest_mod_signed(x, state, p); fmpz_clear(p); fq_nmod_randtest(aa, state, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(a, aa, ctx); fq_nmod_mul_fmpz(bb, aa, x, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(b, bb, ctx); fq_zech_mul_fmpz(c, a, x, ctx); result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("aa = "); fq_nmod_print_pretty(aa, ctx->fq_nmod_ctx); flint_printf("\n"); flint_printf("a = "); fq_zech_print_pretty(a, ctx); flint_printf("\n"); flint_printf("b = "); fq_zech_print_pretty(b, ctx); flint_printf("\n"); flint_printf("c = "); fq_zech_print_pretty(c, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fq_nmod_clear(bb, ctx->fq_nmod_ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); } for (jx = 0; jx < 10; jx++) { fmpz_t x, p; fq_nmod_t aa, bb; fq_zech_t a, b; fq_nmod_init(aa, ctx->fq_nmod_ctx); fq_nmod_init(bb, ctx->fq_nmod_ctx); fmpz_init(x); fmpz_init_set_ui(p, fq_zech_ctx_prime(ctx)); fmpz_randtest_mod_signed(x, state, p); fmpz_clear(p); fq_nmod_randtest(aa, state, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(a, aa, ctx); fq_nmod_mul_fmpz(bb, aa, x, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(b, bb, ctx); fq_zech_mul_fmpz(a, a, x, ctx); result = (fq_zech_equal(b, a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("aa = "); fq_nmod_print_pretty(aa, ctx->fq_nmod_ctx); flint_printf("\n"); flint_printf("a = "); fq_zech_print_pretty(a, ctx); flint_printf("\n"); flint_printf("b = "); fq_zech_print_pretty(b, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(x); fq_nmod_clear(bb, ctx->fq_nmod_ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-mul_ui.c000066400000000000000000000067601461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "fq_nmod.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_mul_ui, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 1); for (jx = 0; jx < 10; jx++) { mp_limb_t x; fq_nmod_t aa, bb; fq_zech_t a, b, c; fq_nmod_init(aa, ctx->fq_nmod_ctx); fq_nmod_init(bb, ctx->fq_nmod_ctx); x = z_randtest(state); fq_nmod_randtest(aa, state, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(a, aa, ctx); fq_nmod_mul_ui(bb, aa, x, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(b, bb, ctx); fq_zech_mul_ui(c, a, x, ctx); result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\nx = %wu\n", x); flint_printf("aa = "); fq_nmod_print_pretty(aa, ctx->fq_nmod_ctx); flint_printf("\nbb = "); fq_nmod_print_pretty(bb, ctx->fq_nmod_ctx); flint_printf("\n"); flint_printf("a = "); fq_zech_print_pretty(a, ctx); flint_printf("\n"); flint_printf("b = "); fq_zech_print_pretty(b, ctx); flint_printf("\n"); flint_printf("c = "); fq_zech_print_pretty(c, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fq_nmod_clear(bb, ctx->fq_nmod_ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); } for (jx = 0; jx < 10; jx++) { mp_limb_t x; fq_nmod_t aa, bb; fq_zech_t a, b; fq_nmod_init(aa, ctx->fq_nmod_ctx); fq_nmod_init(bb, ctx->fq_nmod_ctx); x = z_randtest(state); fq_nmod_randtest(aa, state, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(a, aa, ctx); fq_nmod_mul_ui(bb, aa, x, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(b, bb, ctx); fq_zech_mul_ui(a, a, x, ctx); result = (fq_zech_equal(b, a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("aa = "); fq_nmod_print_pretty(aa, ctx->fq_nmod_ctx); flint_printf("\n"); flint_printf("a = "); fq_zech_print_pretty(a, ctx); flint_printf("\n"); flint_printf("b = "); fq_zech_print_pretty(b, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fq_nmod_clear(bb, ctx->fq_nmod_ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-multiplicative_order.c000066400000000000000000000010351461254215100226520ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-multiplicative_order.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-neg.c000066400000000000000000000056651461254215100172120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_neg, state) { int i, j, result; fq_zech_ctx_t ctx; for (j = 0; j < 10; j++) { fq_zech_ctx_init_randtest(ctx, state, 0); /* Check aliasing: a = -a */ for (i = 0; i < 200; i++) { fq_zech_t a, b, c; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_set(b, a, ctx); fq_zech_neg(c, b, ctx); fq_zech_neg(b, b, ctx); result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL a = -a:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } /* Check a - b == a + (-b) */ for (i = 0; i < 2000; i++) { fq_zech_t a, b, c1, c2; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c1, ctx); fq_zech_init(c2, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_sub(c1, a, b, ctx); fq_zech_neg(c2, b, ctx); fq_zech_add(c2, a, c2, ctx); result = (fq_zech_equal(c1, c2, ctx)); if (!result) { flint_printf("FAIL a - b == a + (-b):\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c1 = "), fq_zech_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), fq_zech_print_pretty(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c1, ctx); fq_zech_clear(c2, ctx); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-norm.c000066400000000000000000000041221461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_norm, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 1); for (jx = 0; jx < 10; jx++) { fmpz_t t1, t2; fq_nmod_t aa; fq_zech_t a; fmpz_init(t1); fmpz_init(t2); fq_nmod_init(aa, ctx->fq_nmod_ctx); fq_zech_init(a, ctx); fq_nmod_randtest(aa, state, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(a, aa, ctx); fq_nmod_norm(t1, aa, ctx->fq_nmod_ctx); fq_zech_norm(t2, a, ctx); result = fmpz_equal(t1, t2); if (!result) { flint_printf("FAIL:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("aa = "); fq_nmod_print_pretty(aa, ctx->fq_nmod_ctx); flint_printf("\n"); flint_printf("N(aa) = "); fmpz_print(t1); flint_printf("\na = "); fq_zech_print_pretty(a, ctx); flint_printf("\n"); flint_printf("N(a) = "); fmpz_print(t2); flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); fmpz_clear(t1); fmpz_clear(t2); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-pow.c000066400000000000000000000057351461254215100172440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_pow, state) { slong ix, jx; int result; fq_zech_ctx_t ctx; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_init_randtest(ctx, state, 1); /* Check aliasing: a = a^e */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b; fmpz_t e; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fmpz_init(e); fq_zech_randtest(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); fq_zech_pow(b, a, e, ctx); fq_zech_pow(a, a, e, ctx); result = (fq_zech_equal(a, b, ctx)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fmpz_clear(e); } /* Compare with multiplication, for integral values */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c; fmpz_t e, f; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fmpz_init(f); fmpz_init(e); fq_zech_randtest(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); fq_zech_pow(b, a, e, ctx); fq_zech_one(c, ctx); for (fmpz_one(f); fmpz_cmp(f, e) <= 0; fmpz_add_ui(f, f, 1)) { fq_zech_mul(c, c, a, ctx); } result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL (cmp with mul):\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("e = "), fmpz_print(e), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); fmpz_clear(e); fmpz_clear(f); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-pth_root.c000066400000000000000000000010211461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-pth_root.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-sqr.c000066400000000000000000000051541461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_sqr, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 2); /* Check aliasing: a = a * a */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, c; fq_zech_init(a, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_sqr(c, a, ctx); fq_zech_sqr(a, a, ctx); result = (fq_zech_equal(a, c, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(c, ctx); } /* Check a^2 + a^2 = a(a + a) */ for (jx = 0; jx < 10; jx++) { fq_zech_t a, b, c, d; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_init(d, ctx); fq_zech_randtest(a, state, ctx); fq_zech_sqr(b, a, ctx); fq_zech_add(c, b, b, ctx); fq_zech_add(d, a, a, ctx); fq_zech_mul(d, a, d, ctx); result = (fq_zech_equal(c, d, ctx)); if (!result) { flint_printf("FAIL (a^2 + a^2 == a(a + a)):\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), fq_zech_print_pretty(d, ctx), flint_printf("\n"); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); fq_zech_clear(d, ctx); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-sqrt.c000066400000000000000000000010161461254215100174140ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_templates/test/t-sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech/test/t-sub.c000066400000000000000000000136711461254215100172260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_sub, state) { int j, i, result; fq_zech_ctx_t ctx; for (j = 0; j < 10; j++) { fq_zech_ctx_init_randtest(ctx, state, 0); /* Check aliasing: a = a - b */ for (i = 0; i < 200; i++) { fq_zech_t a, b, c; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_sub(c, a, b, ctx); fq_zech_sub(a, a, b, ctx); result = (fq_zech_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } /* Check aliasing: b = a - b */ for (i = 0; i < 200; i++) { fq_zech_t a, b, c; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_sub(c, a, b, ctx); fq_zech_sub(b, a, b, ctx); result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } /* Check aliasing: a = a - a */ for (i = 0; i < 2000; i++) { fq_zech_t a, c; fq_zech_init(a, ctx); fq_zech_init(c, ctx); fq_zech_randtest(a, state, ctx); fq_zech_sub(c, a, a, ctx); fq_zech_sub(a, a, a, ctx); result = (fq_zech_equal(a, c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(c, ctx); } /* Check that a - b == -(b - a) */ for (i = 0; i < 2000; i++) { fq_zech_t a, b, c1, c2; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c1, ctx); fq_zech_init(c2, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_sub(c1, a, b, ctx); fq_zech_sub(c2, b, a, ctx); fq_zech_neg(c2, c2, ctx); result = (fq_zech_equal(c1, c2, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c1 = "), fq_zech_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), fq_zech_print_pretty(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c1, ctx); fq_zech_clear(c2, ctx); } /* Check that (a - b) - c == a - (b + c) */ for (i = 0; i < 2000; i++) { fq_zech_t a, b, c, lhs, rhs; fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_zech_init(c, ctx); fq_zech_init(lhs, ctx); fq_zech_init(rhs, ctx); fq_zech_randtest(a, state, ctx); fq_zech_randtest(b, state, ctx); fq_zech_randtest(c, state, ctx); fq_zech_sub(lhs, a, b, ctx); fq_zech_sub(lhs, lhs, c, ctx); fq_zech_add(rhs, b, c, ctx); fq_zech_sub(rhs, a, rhs, ctx); result = (fq_zech_equal(lhs, rhs, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fq_zech_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), fq_zech_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); flint_printf("lhs = "), fq_zech_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), fq_zech_print_pretty(rhs, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); fq_zech_clear(lhs, ctx); fq_zech_clear(rhs, ctx); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/test/t-trace.c000066400000000000000000000040071461254215100175240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fq_nmod.h" #include "fq_zech.h" TEST_FUNCTION_START(fq_zech_trace, state) { slong ix, jx; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { fq_zech_ctx_t ctx; fq_zech_ctx_init_randtest(ctx, state, 1); for (jx = 0; jx < 10; jx++) { fmpz_t t1, t2; fq_nmod_t aa; fq_zech_t a; fmpz_init(t1); fmpz_init(t2); fq_nmod_init(aa, ctx->fq_nmod_ctx); fq_zech_init(a, ctx); fq_nmod_randtest(aa, state, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(a, aa, ctx); fq_nmod_trace(t1, aa, ctx->fq_nmod_ctx); fq_zech_trace(t2, a, ctx); result = fmpz_equal(t1, t2); if (!result) { flint_printf("FAIL:\n\n"); fq_zech_ctx_print(ctx); flint_printf("\n"); flint_printf("aa = "); fq_nmod_print_pretty(aa, ctx->fq_nmod_ctx); flint_printf("\n"); flint_printf("Tr(aa) = "); fmpz_print(t1); flint_printf("a = "); fq_zech_print_pretty(a, ctx); flint_printf("\n"); flint_printf("Tr(a) = "); fmpz_print(t2); flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(a, ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); fmpz_clear(t1); fmpz_clear(t2); } fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech/trace.c000066400000000000000000000023001461254215100162760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq_zech.h" void fq_zech_trace(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx) { mp_limb_t p_i, trace; fq_zech_t t, op_p_i; double qm1inv; if (fq_zech_is_zero(op, ctx)) { fmpz_zero(rop); return; } fq_zech_zero(t, ctx); qm1inv = n_precompute_inverse(ctx->qm1); for (p_i = 1; p_i <= ctx->qm1; p_i *= ctx->p) { /* op_q_i = op ^ (p ^ i) */ op_p_i->value = n_mulmod_precomp(op->value, p_i, ctx->qm1, qm1inv); /* t += op_p_i */ fq_zech_add(t, t, op_p_i, ctx); } if (fq_zech_is_zero(t, ctx)) { fmpz_zero(rop); } else { trace = t->value / ctx->qm1opm1; trace = n_powmod(ctx->prime_root, trace, ctx->p); fmpz_set_ui(rop, trace); } } flint-3.1.3/src/fq_zech/vec_templates.c000066400000000000000000000021501461254215100200360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fq_zech.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/add.c" #include "fq_vec_templates/clear.c" #include "fq_vec_templates/dot.c" #include "fq_vec_templates/equal.c" #include "fq_vec_templates/init.c" #include "fq_vec_templates/io.c" #include "fq_vec_templates/is_zero.c" #include "fq_vec_templates/neg.c" #include "fq_vec_templates/randtest.c" #include "fq_vec_templates/scalar_addmul_fq.c" #include "fq_vec_templates/scalar_mul_fq.c" #include "fq_vec_templates/scalar_submul_fq.c" #include "fq_vec_templates/set.c" #include "fq_vec_templates/sub.c" #include "fq_vec_templates/swap.c" #include "fq_vec_templates/zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_embed.h000066400000000000000000000021101461254215100163400ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_EMBED_H #define FQ_ZECH_EMBED_H #ifdef FQ_ZECH_EMBED_INLINES_C #define FQ_ZECH_EMBED_INLINE #define FQ_EMBED_TEMPLATES_INLINE #else #define FQ_ZECH_EMBED_INLINE static inline #define FQ_EMBED_TEMPLATES_INLINE static inline #endif #include "fq_zech_types.h" #define T fq_zech #define B nmod #include "fq_embed_templates.h" void TEMPLATE(T, modulus_pow_series_inv)(TEMPLATE(B, poly_t) res, const TEMPLATE(T, ctx_t) ctx, slong trunc); #undef B #undef T void fq_zech_modulus_derivative_inv(fq_zech_t m_prime, fq_zech_t m_prime_inv, const fq_zech_ctx_t ctx); #endif flint-3.1.3/src/fq_zech_embed/000077500000000000000000000000001461254215100161755ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_embed/composition_matrix.c000066400000000000000000000023371461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_embed.h" #include "fq_zech.h" #include "fq_zech_embed.h" void fq_zech_embed_composition_matrix_sub(nmod_mat_t matrix, const fq_zech_t gen, const fq_zech_ctx_t ctx, slong trunc) { fq_nmod_t gen_nmod; fq_nmod_ctx_struct *modulus = ctx->fq_nmod_ctx; fq_nmod_init(gen_nmod, modulus); fq_zech_get_fq_nmod(gen_nmod, gen, ctx); fq_nmod_embed_composition_matrix_sub(matrix, gen_nmod, modulus, trunc); fq_nmod_clear(gen_nmod, modulus); } void fq_zech_embed_composition_matrix(nmod_mat_t matrix, const fq_zech_t gen, const fq_zech_ctx_t ctx) { fq_zech_embed_composition_matrix_sub(matrix, gen, ctx, fq_zech_ctx_degree(ctx)); } flint-3.1.3/src/fq_zech_embed/modulus_derivative_inv.c000066400000000000000000000020111461254215100231210ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_embed.h" #include "fq_zech.h" #include "fq_zech_embed.h" void fq_zech_modulus_derivative_inv(fq_zech_t m_prime, fq_zech_t m_prime_inv, const fq_zech_ctx_t ctx) { fq_nmod_t m_nmod, m_inv_nmod; fq_nmod_init(m_nmod, ctx->fq_nmod_ctx); fq_nmod_init(m_inv_nmod, ctx->fq_nmod_ctx); fq_nmod_modulus_derivative_inv(m_nmod, m_inv_nmod, ctx->fq_nmod_ctx); fq_zech_set_fq_nmod(m_prime, m_nmod, ctx); fq_zech_set_fq_nmod(m_prime_inv, m_inv_nmod, ctx); fq_nmod_clear(m_nmod, ctx->fq_nmod_ctx); fq_nmod_clear(m_inv_nmod, ctx->fq_nmod_ctx); } flint-3.1.3/src/fq_zech_embed/mul_matrix.c000066400000000000000000000015521461254215100205250ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_embed.h" #include "fq_zech.h" #include "fq_zech_embed.h" void fq_zech_embed_mul_matrix(nmod_mat_t matrix, const fq_zech_t gen, const fq_zech_ctx_t ctx) { fq_nmod_t gen_nmod; fq_nmod_ctx_struct *modulus = ctx->fq_nmod_ctx; fq_nmod_init(gen_nmod, modulus); fq_zech_get_fq_nmod(gen_nmod, gen, ctx); fq_nmod_embed_mul_matrix(matrix, gen_nmod, modulus); fq_nmod_clear(gen_nmod, modulus); } flint-3.1.3/src/fq_zech_embed/test/000077500000000000000000000000001461254215100171545ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_embed/test/main.c000066400000000000000000000020661461254215100202500ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-composition_matrix.c" #include "t-embed.c" #include "t-embed_matrices.c" #include "t-mono_dual_matrix.c" #include "t-mul_matrix.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_zech_embed_composition_matrix), TEST_FUNCTION(fq_zech_embed), TEST_FUNCTION(fq_zech_embed_matrices), TEST_FUNCTION(fq_zech_embed_mono_dual_matrix), TEST_FUNCTION(fq_zech_embed_mul_matrix) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_zech_embed/test/t-composition_matrix.c000066400000000000000000000012321461254215100235060ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_zech.h" #include "fq_zech_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_zech #define CAP_T FQ_ZECH #define B nmod #include "fq_embed_templates/test/t-composition_matrix.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_zech_embed/test/t-embed.c000066400000000000000000000012211461254215100206310ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_zech #define CAP_T FQ_ZECH #define B nmod #include "fq_embed_templates/test/t-embed.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_zech_embed/test/t-embed_matrices.c000066400000000000000000000111461461254215100225270ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_zech.h" #include "fq_zech_embed.h" TEST_FUNCTION_START(fq_zech_embed_matrices, state) { int i, j; int primes[4] = {2, 3, 5}; int degrees[2] = {2, 3}; /* Check that isomorphism to self gives identity matrices */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_zech_ctx_t ctx; fq_zech_t gen; const nmod_poly_struct *modulus; nmod_mat_t embed, project, one; slong d; fq_zech_ctx_init_randtest(ctx, state, 3); d = fq_zech_ctx_degree(ctx); modulus = fq_zech_ctx_modulus(ctx); fq_zech_init(gen, ctx); fq_zech_gen(gen, ctx); fq_zech_pow_ui(gen, gen, fq_zech_ctx_prime(ctx), ctx); nmod_mat_init(embed, d, d, nmod_poly_modulus(modulus)); nmod_mat_init(project, d, d, nmod_poly_modulus(modulus)); nmod_mat_init(one, d, d, nmod_poly_modulus(modulus)); fq_zech_embed_matrices(embed, project, gen, ctx, gen, ctx, modulus); nmod_mat_one(one); if (!nmod_mat_equal(embed, one) || !nmod_mat_equal(project, one)) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"), fq_zech_ctx_print(ctx), flint_printf("\n"); flint_printf("x^p: "), fq_zech_print_pretty(gen, ctx), flint_printf("\n"); flint_printf("Embed\n"), nmod_mat_print_pretty(embed), flint_printf("\nProject\n"), nmod_mat_print_pretty(project), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_mat_clear(embed); nmod_mat_clear(project); nmod_mat_clear(one); fq_zech_clear(gen, ctx); fq_zech_ctx_clear(ctx); } /* Check random embedding (degrees 1..3) */ for (j = 1; j < 4; j++) { for (i = 0; i < (4 - j) * flint_test_multiplier(); i++) { fq_zech_ctx_t ctx1, ctx2; fq_zech_t gen1, gen2; nmod_poly_t minpoly; const nmod_poly_struct *modulus; nmod_poly_t modulus2; nmod_mat_t embed, project, comp, one; slong m, n; m = degrees[i % 2]; fq_zech_ctx_init_random_ui(ctx1, primes[i % 3], m, "a"); n = m*j; if (m == 1) { i--; continue; } modulus = fq_zech_ctx_modulus(ctx1); nmod_poly_init(modulus2, nmod_poly_modulus(modulus)); nmod_poly_randtest_monic_primitive(modulus2, state, n+1); fq_zech_ctx_init_modulus(ctx2, modulus2, "X"); fq_zech_init(gen1, ctx1); fq_zech_init(gen2, ctx2); nmod_poly_init(minpoly, nmod_poly_modulus(modulus)); fq_zech_embed_gens(gen1, gen2, minpoly, ctx1, ctx2); nmod_mat_init(embed, n, m, nmod_poly_modulus(modulus)); nmod_mat_init(project, m, n, nmod_poly_modulus(modulus)); nmod_mat_init(comp, m, m, nmod_poly_modulus(modulus)); nmod_mat_init(one, m, m, nmod_poly_modulus(modulus)); fq_zech_embed_matrices(embed, project, gen1, ctx1, gen2, ctx2, minpoly); nmod_mat_mul(comp, project, embed); nmod_mat_one(one); if (!nmod_mat_equal(comp, one)) { flint_printf("FAIL:\n\n"); flint_printf("CTX 1\n"), fq_zech_ctx_print(ctx1), flint_printf("\n"); flint_printf("CTX 2\n"), fq_zech_ctx_print(ctx2), flint_printf("\n"); flint_printf("Embed\n"), nmod_mat_print_pretty(embed), flint_printf("\nProject\n"), nmod_mat_print_pretty(project), flint_printf("\nComposition\n"), nmod_mat_print_pretty(comp), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_mat_clear(embed); nmod_mat_clear(project); nmod_mat_clear(comp); nmod_mat_clear(one); nmod_poly_clear(minpoly); nmod_poly_clear(modulus2); fq_zech_clear(gen1, ctx1); fq_zech_ctx_clear(ctx1); fq_zech_clear(gen2, ctx2); fq_zech_ctx_clear(ctx2); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech_embed/test/t-mono_dual_matrix.c000066400000000000000000000012301461254215100231160ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_zech.h" #include "fq_zech_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_zech #define CAP_T FQ_ZECH #define B nmod #include "fq_embed_templates/test/t-mono_dual_matrix.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_zech_embed/test/t-mul_matrix.c000066400000000000000000000012221461254215100217370ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "fq_zech.h" #include "fq_zech_embed.h" #ifdef T #undef T #endif #ifdef B #undef B #endif #define T fq_zech #define CAP_T FQ_ZECH #define B nmod #include "fq_embed_templates/test/t-mul_matrix.c" #undef B #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat.h000066400000000000000000000020621461254215100160530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_MAT_H #define FQ_ZECH_MAT_H #ifdef FQ_ZECH_MAT_INLINES_C #define FQ_MAT_TEMPLATES_INLINE #define FQ_ZECH_MAT_INLINE #else #define FQ_MAT_TEMPLATES_INLINE static inline #define FQ_ZECH_MAT_INLINE static inline #endif #include "fq_zech_types.h" /* Cutoff between classical and recursive triangular solving */ #define FQ_ZECH_MAT_SOLVE_TRI_ROWS_CUTOFF 64 #define FQ_ZECH_MAT_SOLVE_TRI_COLS_CUTOFF 64 /* Cutoff between classical and recursive LU decomposition */ #define FQ_ZECH_MAT_LU_RECURSIVE_CUTOFF 4 int FQ_ZECH_MAT_MUL_KS_CUTOFF(slong r, slong c, const fq_zech_ctx_t ctx); #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_zech_mat/000077500000000000000000000000001461254215100157025ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_mat/inlines.c000066400000000000000000000006621461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_MAT_INLINES_C #include "fq_zech_mat.h" flint-3.1.3/src/fq_zech_mat/mul_ks_cutoff.c000066400000000000000000000011451461254215100207070ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" int FQ_ZECH_MAT_MUL_KS_CUTOFF(slong r, slong c, const fq_zech_ctx_t ctx) { if (5 * FLINT_MIN(r, c) > 8 * fq_zech_ctx_degree(ctx) + 29) return 1; else return 0; } flint-3.1.3/src/fq_zech_mat/test/000077500000000000000000000000001461254215100166615ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_mat/test/main.c000066400000000000000000000054261461254215100177600ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-can_solve.c" #include "t-charpoly.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-equal.c" #include "t-inv.c" #include "t-is_zero.c" #include "t-lu_classical.c" #include "t-lu_recursive.c" #include "t-minpoly.c" #include "t-mul.c" #include "t-mul_KS.c" #include "t-mul_vec.c" #include "t-nullspace.c" #include "t-one.c" #include "t-rank.c" #include "t-rref.c" #include "t-set_fmpz_mod_mat.c" #include "t-set_nmod_mat.c" #include "t-solve.c" #include "t-solve_tril.c" #include "t-solve_tril_classical.c" #include "t-solve_tril_recursive.c" #include "t-solve_triu.c" #include "t-solve_triu_classical.c" #include "t-solve_triu_recursive.c" #include "t-submul.c" #include "t-vec_mul.c" #include "t-window_init_clear.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_zech_mat_add_sub), TEST_FUNCTION(fq_zech_mat_can_solve), TEST_FUNCTION(fq_zech_mat_charpoly), TEST_FUNCTION(fq_zech_mat_concat_horizontal), TEST_FUNCTION(fq_zech_mat_concat_vertical), TEST_FUNCTION(fq_zech_mat_equal), TEST_FUNCTION(fq_zech_mat_inv), TEST_FUNCTION(fq_zech_mat_is_zero), TEST_FUNCTION(fq_zech_mat_lu_classical), TEST_FUNCTION(fq_zech_mat_lu_recursive), TEST_FUNCTION(fq_zech_mat_minpoly), TEST_FUNCTION(fq_zech_mat_mul), TEST_FUNCTION(fq_zech_mat_mul_KS), TEST_FUNCTION(fq_zech_mat_mul_vec), TEST_FUNCTION(fq_zech_mat_nullspace), TEST_FUNCTION(fq_zech_mat_one), TEST_FUNCTION(fq_zech_mat_rank), TEST_FUNCTION(fq_zech_mat_rref), TEST_FUNCTION(fq_zech_mat_set_fmpz_mod_mat), TEST_FUNCTION(fq_zech_mat_set_nmod_mat), TEST_FUNCTION(fq_zech_mat_solve), TEST_FUNCTION(fq_zech_mat_solve_tril), TEST_FUNCTION(fq_zech_mat_solve_tril_classical), TEST_FUNCTION(fq_zech_mat_solve_tril_recursive), TEST_FUNCTION(fq_zech_mat_solve_triu), TEST_FUNCTION(fq_zech_mat_solve_triu_classical), TEST_FUNCTION(fq_zech_mat_solve_triu_recursive), TEST_FUNCTION(fq_zech_mat_submul), TEST_FUNCTION(fq_zech_mat_vec_mul), TEST_FUNCTION(fq_zech_mat_window_init_clear), TEST_FUNCTION(fq_zech_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_zech_mat/test/t-add_sub.c000066400000000000000000000010551461254215100206700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-add_sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-can_solve.c000066400000000000000000000010601461254215100212340ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-can_solve.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-charpoly.c000066400000000000000000000011101461254215100211000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-charpoly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-concat_horizontal.c000066400000000000000000000010751461254215100230110ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-concat_horizontal.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-concat_vertical.c000066400000000000000000000010731461254215100224270ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-concat_vertical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-equal.c000066400000000000000000000010531461254215100203740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-equal.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-inv.c000066400000000000000000000010511461254215100200570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-inv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-is_zero.c000066400000000000000000000010551461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-is_zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-lu_classical.c000066400000000000000000000010621461254215100217230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-lu_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-lu_recursive.c000066400000000000000000000010621461254215100217740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-lu_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-minpoly.c000066400000000000000000000011071461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-minpoly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-mul.c000066400000000000000000000010511461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-mul_KS.c000066400000000000000000000010541461254215100204600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-mul_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-mul_vec.c000066400000000000000000000011111461254215100207120ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-mul_vec.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-nullspace.c000066400000000000000000000010571461254215100212570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-nullspace.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-one.c000066400000000000000000000010521461254215100200450ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-one.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-rank.c000066400000000000000000000010521461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-rank.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-rref.c000066400000000000000000000010521461254215100202220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-rref.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-set_fmpz_mod_mat.c000066400000000000000000000010671461254215100226210ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-set_fmpz_mod_mat.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-set_nmod_mat.c000066400000000000000000000011111461254215100217310ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-set_nmod_mat.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-solve.c000066400000000000000000000010541461254215100204160ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-solve.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-solve_tril.c000066400000000000000000000010601461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-solve_tril.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-solve_tril_classical.c000066400000000000000000000010721461254215100234660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-solve_tril_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-solve_tril_recursive.c000066400000000000000000000010721461254215100235370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-solve_tril_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-solve_triu.c000066400000000000000000000010601461254215100214560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-solve_triu.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-solve_triu_classical.c000066400000000000000000000010721461254215100234770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-solve_triu_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-solve_triu_recursive.c000066400000000000000000000010721461254215100235500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-solve_triu_recursive.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-submul.c000066400000000000000000000010541461254215100205750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-submul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-vec_mul.c000066400000000000000000000011111461254215100207120ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-vec_mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-window_init_clear.c000066400000000000000000000011261461254215100227660ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-window_init_clear.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mat/test/t-zero.c000066400000000000000000000010521461254215100202430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/test/t-zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_mpoly.h000066400000000000000000000725371461254215100164500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_MPOLY_H #define FQ_ZECH_MPOLY_H #ifdef FQ_ZECH_MPOLY_INLINES_C #define FQ_ZECH_MPOLY_INLINE #else #define FQ_ZECH_MPOLY_INLINE static inline #endif #include "fq_zech_types.h" #include "fq_nmod_types.h" #include "mpoly_types.h" #ifdef __cplusplus extern "C" { #endif FQ_ZECH_MPOLY_INLINE nmod_t fq_zech_ctx_mod(const fq_zech_ctx_t ctx) { return ctx->fq_nmod_ctx->mod; } /* Type definitions *********************************************************/ /* context object for fq_zech_mpoly */ typedef struct { mpoly_ctx_t minfo; fq_zech_ctx_t fqctx; } fq_zech_mpoly_ctx_struct; typedef fq_zech_mpoly_ctx_struct fq_zech_mpoly_ctx_t[1]; /* fq_zech_mpoly_t sparse multivariates with fq_zech coefficients */ typedef struct { fq_zech_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* number of bits per exponent */ } fq_zech_mpoly_struct; typedef fq_zech_mpoly_struct fq_zech_mpoly_t[1]; /* Internal type definitions *************************************************/ /* fq_zech_mpoly_univar_t sparse univariates with multivariate coefficients */ typedef struct { fq_zech_mpoly_struct * coeffs; /* multivariate coefficients */ fmpz * exps; slong alloc; slong length; } fq_zech_mpoly_univar_struct; typedef fq_zech_mpoly_univar_struct fq_zech_mpoly_univar_t[1]; /* fq_zech_mpolyu_t sparse univariates with fq_zech_mpoly_t coefficients with uniform bits and LEX ordering */ typedef struct { fq_zech_mpoly_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* default bits to construct coeffs */ } fq_zech_mpolyu_struct; typedef fq_zech_mpolyu_struct fq_zech_mpolyu_t[1]; /* fq_zech_mpolyn_t multivariates with fq_zech_poly_t coefficients */ typedef struct { fq_zech_poly_struct * coeffs; ulong * exps; slong alloc; slong length; slong bits; } fq_zech_mpolyn_struct; typedef fq_zech_mpolyn_struct fq_zech_mpolyn_t[1]; /* fq_zech_mpolyun_t sparse univariates with fq_zech_mpolyn_t coefficients with uniform bits and LEX ordering */ typedef struct { fq_zech_mpolyn_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* default bits to construct coeffs */ } fq_zech_mpolyun_struct; typedef fq_zech_mpolyun_struct fq_zech_mpolyun_t[1]; /* fq_zech_mpoly_geobucket_t power of 4 increment */ typedef struct fq_zech_mpoly_geobucket { fq_zech_mpoly_struct polys[FLINT_BITS/2]; slong length; } fq_zech_mpoly_geobucket_struct; typedef fq_zech_mpoly_geobucket_struct fq_zech_mpoly_geobucket_t[1]; /* Context object ************************************************************/ void fq_zech_mpoly_ctx_init_deg(fq_zech_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t p, slong deg); void fq_zech_mpoly_ctx_clear(fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE slong fq_zech_mpoly_ctx_nvars(const fq_zech_mpoly_ctx_t ctx) { return ctx->minfo->nvars; } FQ_ZECH_MPOLY_INLINE ordering_t fq_zech_mpoly_ctx_ord(const fq_zech_mpoly_ctx_t ctx) { return ctx->minfo->ord; } /* Memory management ********************************************************/ void fq_zech_mpoly_init(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_init2(fq_zech_mpoly_t A, slong alloc, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_init3(fq_zech_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_realloc(fq_zech_mpoly_t A, slong alloc, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_fit_length(fq_zech_mpoly_t A, slong length, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_fit_length(fq_zech_struct ** coeff, ulong ** exps, slong * alloc, slong len, slong N, const fq_zech_ctx_t fqctx); void fq_zech_mpoly_fit_length_reset_bits(fq_zech_mpoly_t A, slong len, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_clear(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE void _fq_zech_mpoly_set_length(fq_zech_mpoly_t A, slong newlen, const fq_zech_mpoly_ctx_t ctx) { FLINT_ASSERT(newlen <= A->alloc); A->length = newlen; } FQ_ZECH_MPOLY_INLINE void fq_zech_mpoly_truncate(fq_zech_mpoly_t A, slong newlen, const fq_zech_mpoly_ctx_t ctx) { if (A->length > newlen) { A->length = newlen; } } void fq_zech_mpoly_fit_bits(fq_zech_mpoly_t A, slong bits, const fq_zech_mpoly_ctx_t ctx); /* Input/output **************************************************************/ int fq_zech_mpoly_set_str_pretty(fq_zech_mpoly_t A, const char * str, const char ** x, const fq_zech_mpoly_ctx_t ctx); char * fq_zech_mpoly_get_str_pretty(const fq_zech_mpoly_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx); #ifdef FLINT_HAVE_FILE int fq_zech_mpoly_fprint_pretty(FILE * file, const fq_zech_mpoly_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx); #endif int fq_zech_mpoly_print_pretty(const fq_zech_mpoly_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx); /* Basic manipulation *******************************************************/ void fq_zech_mpoly_gen(fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_is_gen(const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_equal(const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE void fq_zech_mpoly_swap(fq_zech_mpoly_t A, fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { FLINT_SWAP(fq_zech_mpoly_struct, *A, *B); } /* Constants *****************************************************************/ int fq_zech_mpoly_is_fq_zech(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_fq_zech(fq_zech_t c, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_fq_zech(fq_zech_mpoly_t A, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_ui(fq_zech_mpoly_t A, ulong c, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_fq_zech_gen(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_equal_fq_zech(const fq_zech_mpoly_t A, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE void fq_zech_mpoly_zero(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { _fq_zech_mpoly_set_length(A, 0, ctx); } FQ_ZECH_MPOLY_INLINE void fq_zech_mpoly_one(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { fq_zech_mpoly_set_ui(A, 1, ctx); } FQ_ZECH_MPOLY_INLINE int fq_zech_mpoly_is_zero(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return A->length == 0; } int fq_zech_mpoly_is_one(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); /* Degrees *******************************************************************/ int fq_zech_mpoly_degrees_fit_si(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_degrees_fmpz(fmpz ** degs, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_degrees_si(slong * degs, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_degree_fmpz(fmpz_t deg, const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); slong fq_zech_mpoly_degree_si(const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_total_degree_fits_si(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_total_degree_fmpz(fmpz_t td, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); slong fq_zech_mpoly_total_degree_si(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); /* Coefficients **************************************************************/ void fq_zech_mpoly_get_coeff_fq_zech_monomial(fq_zech_t c, const fq_zech_mpoly_t A, const fq_zech_mpoly_t M, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_coeff_fq_zech_monomial(fq_zech_mpoly_t A, const fq_zech_t c, const fq_zech_mpoly_t M, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_coeff_fq_zech_fmpz(fq_zech_t c, const fq_zech_mpoly_t A, fmpz * const * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_coeff_fq_zech_ui(fq_zech_t c, const fq_zech_mpoly_t A, const ulong * exp, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_set_coeff_fq_zech_fmpz(fq_zech_mpoly_t A, const fq_zech_t c, const fmpz * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_coeff_fq_zech_fmpz(fq_zech_mpoly_t A, const fq_zech_t c, fmpz * const * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_coeff_fq_zech_ui(fq_zech_mpoly_t A, const fq_zech_t c, const ulong * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_coeff_vars_ui(fq_zech_mpoly_t C, const fq_zech_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE fq_zech_struct * fq_zech_mpoly_leadcoeff( const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return A->coeffs + 0; } /* comparison ****************************************************************/ int fq_zech_mpoly_cmp(const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); /* container operations ******************************************************/ int fq_zech_mpoly_is_canonical(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE slong fq_zech_mpoly_length(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return A->length; } void fq_zech_mpoly_resize(fq_zech_mpoly_t A, slong new_length, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_term_coeff_fq_zech(fq_zech_t c, const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_term_coeff_fq_zech(fq_zech_mpoly_t A, slong i, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_term_exp_fits_ui(const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_term_exp_fits_si(const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_term_exp_fmpz(fmpz ** exp, const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_term_exp_ui(ulong * exp, const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_term_exp_si(slong * exp, const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); ulong fq_zech_mpoly_get_term_var_exp_ui(const fq_zech_mpoly_t A, slong i, slong var, const fq_zech_mpoly_ctx_t ctx); slong fq_zech_mpoly_get_term_var_exp_si(const fq_zech_mpoly_t A, slong i, slong var, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_term_exp_fmpz(fq_zech_mpoly_t A, slong i, fmpz * const * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_term_exp_ui(fq_zech_mpoly_t A, slong i, const ulong * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_term(fq_zech_mpoly_t M, const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_get_term_monomial(fq_zech_mpoly_t M, const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_push_term_fq_zech_fmpz(fq_zech_mpoly_t A, const fq_zech_t c, fmpz * const * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_push_term_fq_zech_ui(fq_zech_mpoly_t A, const fq_zech_t c, const ulong * exp, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_sort_terms(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_combine_like_terms(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_reverse(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_assert_canonical(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_radix_sort1(fq_zech_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); void _fq_zech_mpoly_radix_sort(fq_zech_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); void _fq_zech_mpoly_push_exp_ffmpz(fq_zech_mpoly_t A, const fmpz * exp, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_push_exp_pfmpz(fq_zech_mpoly_t A, fmpz * const * exp, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_push_exp_ui(fq_zech_mpoly_t A, const ulong * exp, const fq_zech_mpoly_ctx_t ctx); /* Random generation *********************************************************/ void fq_zech_mpoly_randtest_bound(fq_zech_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_randtest_bounds(fq_zech_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_randtest_bits(fq_zech_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const fq_zech_mpoly_ctx_t ctx); /* Addition/Subtraction ******************************************************/ slong _fq_zech_mpoly_add( fq_zech_struct * coeff1, ulong * exp1, fq_zech_struct * coeff2, const ulong * exp2, slong len2, fq_zech_struct * coeff3, const ulong * exp3, slong len3, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx); void fq_zech_mpoly_add_fq_zech(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_t C, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_sub_fq_zech(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_t C, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_add(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t C, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_sub(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t C, const fq_zech_mpoly_ctx_t ctx); /* Scalar operations *********************************************************/ void fq_zech_mpoly_neg(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_scalar_mul_fq_zech(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_make_monic(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_scalar_addmul_fq_zech(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t C, const fq_zech_t d, const fq_zech_mpoly_ctx_t ctx); /* Differentiation **********************************************************/ void fq_zech_mpoly_derivative(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ void fq_zech_mpoly_evaluate_one_fq_zech(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_t val, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_eval_all_fq_zech(fq_zech_t eval, const fq_zech_struct * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, fq_zech_struct * const * alphas, const mpoly_ctx_t mctx, const fq_zech_ctx_t fqctx); void fq_zech_mpoly_evaluate_all_fq_zech(fq_zech_t ev, const fq_zech_mpoly_t A, fq_zech_struct * const * vals, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_compose_fq_zech_poly(fq_zech_poly_t A, const fq_zech_mpoly_t B, fq_zech_poly_struct * const * C, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_compose_mat(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fmpz_mat_t M, const fq_zech_mpoly_ctx_t ctxB, const fq_zech_mpoly_ctx_t ctxAC); int fq_zech_mpoly_compose_fq_zech_mpoly_geobucket(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, fq_zech_mpoly_struct * const * C, const fq_zech_mpoly_ctx_t ctxB, const fq_zech_mpoly_ctx_t ctxAC); int fq_zech_mpoly_compose_fq_zech_mpoly_horner(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, fq_zech_mpoly_struct * const * C, const fq_zech_mpoly_ctx_t ctxB, const fq_zech_mpoly_ctx_t ctxAC); int fq_zech_mpoly_compose_fq_zech_mpoly(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, fq_zech_mpoly_struct * const * C, const fq_zech_mpoly_ctx_t ctxB, const fq_zech_mpoly_ctx_t ctxAC); void fq_zech_mpoly_compose_fq_zech_mpoly_gen(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const slong * c, const fq_zech_mpoly_ctx_t ctxB, const fq_zech_mpoly_ctx_t ctxAC); /* Multiplication ************************************************************/ void fq_zech_mpoly_mul(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t C, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_mul_johnson(fq_zech_mpoly_t poly1, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx); slong _fq_zech_mpoly_mul_johnson( fq_zech_struct ** coeff1, ulong ** exp1, slong * alloc, const fq_zech_struct * coeff2, const ulong * exp2, slong len2, const fq_zech_struct * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx); /* Powering ******************************************************************/ int fq_zech_mpoly_pow_fmpz(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fmpz_t k, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_pow_ui(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, ulong k, const fq_zech_mpoly_ctx_t ctx); /* Division ******************************************************************/ int fq_zech_mpoly_divides(fq_zech_mpoly_t Q, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_div(fq_zech_mpoly_t Q, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_divrem(fq_zech_mpoly_t Q, fq_zech_mpoly_t R, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_divrem_ideal(fq_zech_mpoly_struct ** Q, fq_zech_mpoly_t R, const fq_zech_mpoly_t A, fq_zech_mpoly_struct * const * B, slong len, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_divides_monagan_pearce(fq_zech_mpoly_t poly1, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_div_monagan_pearce(fq_zech_mpoly_t q, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_divrem_monagan_pearce(fq_zech_mpoly_t q, fq_zech_mpoly_t r, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_divrem_ideal_monagan_pearce( fq_zech_mpoly_struct ** q, fq_zech_mpoly_t r, const fq_zech_mpoly_t poly2, fq_zech_mpoly_struct * const * poly3, slong len, const fq_zech_mpoly_ctx_t ctx); /* GCD ***********************************************************************/ int fq_zech_mpoly_gcd(fq_zech_mpoly_t G, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); int _fq_zech_mpoly_gcd(fq_zech_mpoly_t G, flint_bitcnt_t Gbits, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_gcd_cofactors(fq_zech_mpoly_t G, fq_zech_mpoly_t Abar, fq_zech_mpoly_t Bbar, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); int _fq_zech_mpoly_gcd_cofactors( fq_zech_mpoly_t G, flint_bitcnt_t Gbits, fq_zech_mpoly_t Abar, flint_bitcnt_t Abarbits, fq_zech_mpoly_t Bbar, flint_bitcnt_t Bbarbits, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_gcd_brown(fq_zech_mpoly_t G, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_gcd_zippel(fq_zech_mpoly_t G, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_deflation(fmpz * shift, fmpz * stride, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_deflate(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fmpz * shift, const fmpz * stride, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_inflate(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fmpz * shift, const fmpz * stride, const fq_zech_mpoly_ctx_t ctx); /* Univariates ***************************************************************/ void fq_zech_mpoly_univar_init(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_univar_clear(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_univar_fit_length(fq_zech_mpoly_univar_t A, slong length, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_univar_print_pretty(const fq_zech_mpoly_univar_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_univar_assert_canonical(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_to_univar(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_from_univar_bits(fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_mpoly_univar_t B, slong var, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_from_univar(fq_zech_mpoly_t A, const fq_zech_mpoly_univar_t B, slong var, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE void fq_zech_mpoly_univar_swap(fq_zech_mpoly_univar_t A, fq_zech_mpoly_univar_t B, const fq_zech_mpoly_ctx_t ctx) { FLINT_SWAP(fq_zech_mpoly_univar_struct, *A, *B); } int fq_zech_mpoly_univar_degree_fits_si(const fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE slong fq_zech_mpoly_univar_length(const fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx) { return A->length; } slong fq_zech_mpoly_univar_get_term_exp_si(fq_zech_mpoly_univar_t A, slong i, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE void fq_zech_mpoly_univar_get_term_coeff(fq_zech_mpoly_t c, const fq_zech_mpoly_univar_t A, slong i, const fq_zech_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fq_zech_mpoly_set(c, A->coeffs + i, ctx); } FQ_ZECH_MPOLY_INLINE void fq_zech_mpoly_univar_swap_term_coeff(fq_zech_mpoly_t c, fq_zech_mpoly_univar_t A, slong i, const fq_zech_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); fq_zech_mpoly_swap(c, A->coeffs + i, ctx); } /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ int _fq_zech_mpoly_get_nmod_mpoly( nmod_mpoly_t s, const nmod_mpoly_ctx_t sctx, const fq_zech_mpoly_t t, const fq_zech_mpoly_ctx_t tctx); void _fq_zech_mpoly_set_nmod_mpoly( fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t Actx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t Bctx); void fq_zech_mpolyl_lead_coeff( fq_zech_mpoly_t c, const fq_zech_mpoly_t A, slong num_vars, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_pow_rmul(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, ulong k, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_repack_bits_inplace(fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_ctx_change_modulus(fq_zech_mpoly_ctx_t ctx, slong deg); void _fq_zech_mpoly_get_fq_nmod_mpoly( fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctxA, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctxB); void _fq_zech_mpoly_set_fq_nmod_mpoly( fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctxA, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctxB); /* mpolyu ********************************************************************/ int fq_zech_mpolyu_is_canonical(const fq_zech_mpolyu_t poly, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpolyu_init(fq_zech_mpolyu_t A, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpolyu_clear(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); void fq_zech_mpolyu_swap(fq_zech_mpolyu_t A, fq_zech_mpolyu_t B); void fq_zech_mpolyu_zero(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); int fq_zech_mpolyu_is_one(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); void fq_zech_mpolyu_print_pretty(const fq_zech_mpolyu_t poly, const char ** x, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpolyu_fit_length(fq_zech_mpolyu_t A, slong length, const fq_zech_mpoly_ctx_t uctx); void fq_zech_mpolyu_one(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_zech_mpoly/000077500000000000000000000000001461254215100162615ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_mpoly/add.c000066400000000000000000000076551461254215100171720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" slong _fq_zech_mpoly_add( fq_zech_struct * Acoeffs, ulong * Aexps, fq_zech_struct * Bcoeffs, const ulong * Bexps, slong Blen, fq_zech_struct * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fq_zech_set(Acoeffs + k, Bcoeffs + i, fqctx); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fq_zech_add(Acoeffs + k, Bcoeffs + i, Ccoeffs + j, fqctx); k += !fq_zech_is_zero(Acoeffs + k, fqctx); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fq_zech_set(Acoeffs + k, Ccoeffs + j, fqctx); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fq_zech_set(Acoeffs + k, Bcoeffs + i, fqctx); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fq_zech_set(Acoeffs + k, Ccoeffs + j, fqctx); j++; k++; } return k; } void fq_zech_mpoly_add( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t C, const fq_zech_mpoly_ctx_t ctx) { flint_bitcnt_t Abits; slong N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fq_zech_mpoly_is_zero(B, ctx)) { fq_zech_mpoly_set(A, C, ctx); return; } else if (fq_zech_mpoly_is_zero(C, ctx)) { fq_zech_mpoly_set(A, B, ctx); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fq_zech_mpoly_t T; fq_zech_mpoly_init3(T, B->length + C->length, Abits, ctx); T->length = _fq_zech_mpoly_add(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->fqctx); fq_zech_mpoly_swap(A, T, ctx); fq_zech_mpoly_clear(T, ctx); } else { fq_zech_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _fq_zech_mpoly_add(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->fqctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/fq_zech_mpoly/clear.c000066400000000000000000000013061461254215100175130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_clear(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; if (A->alloc > 0) { for (i = 0; i < A->alloc; i++) fq_zech_clear(A->coeffs + i, ctx->fqctx); flint_free(A->coeffs); flint_free(A->exps); } } flint-3.1.3/src/fq_zech_mpoly/combine_like_terms.c000066400000000000000000000031711461254215100222610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" /* assuming that the exponents are valid and sorted, put the polynomial in canonical form i.e. 2*x^e + 3*x^e -> 5x^e 2*x^e - 2*x^e -> 0 */ void fq_zech_mpoly_combine_like_terms(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong in, out, N = mpoly_words_per_exp(A->bits, ctx->minfo); out = -WORD(1); for (in = WORD(0); in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= WORD(0) && mpoly_monomial_equal(A->exps + N*out, A->exps + N*in, N)) { fq_zech_add(A->coeffs + out, A->coeffs + out, A->coeffs + in, ctx-> fqctx); } else { if (out < WORD(0) || !fq_zech_is_zero(A->coeffs + out, ctx->fqctx)) out++; if (out != in) { mpoly_monomial_set(A->exps + N*out, A->exps + N*in, N); fq_zech_swap(A->coeffs + out, A->coeffs + in, ctx-> fqctx); } } } if (out < WORD(0) || !fq_zech_is_zero(A->coeffs + out, ctx->fqctx)) out++; A->length = out; } flint-3.1.3/src/fq_zech_mpoly/ctx.c000066400000000000000000000020171461254215100172230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_ctx_init_deg(fq_zech_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t p, slong deg) { mpoly_ctx_init(ctx->minfo, nvars, ord); fq_zech_ctx_init_ui(ctx->fqctx, p, deg, "#"); } void fq_zech_mpoly_ctx_clear(fq_zech_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); fq_zech_ctx_clear(ctx->fqctx); } void fq_zech_mpoly_ctx_change_modulus(fq_zech_mpoly_ctx_t ctx, slong deg) { ulong p; p = fq_zech_ctx_mod(ctx->fqctx).n; fq_zech_ctx_clear(ctx->fqctx); fq_zech_ctx_init_ui(ctx->fqctx, p, deg, "#"); } flint-3.1.3/src/fq_zech_mpoly/degrees.c000066400000000000000000000035421461254215100200470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_degrees_fit_si(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_degrees_fit_si(A->exps, A->length, A->bits, ctx->minfo); } void fq_zech_mpoly_degrees_fmpz(fmpz ** degs, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { mpoly_degrees_pfmpz(degs, A->exps, A->length, A->bits, ctx->minfo); } void fq_zech_mpoly_degrees_si(slong * degs, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { mpoly_degrees_si(degs, A->exps, A->length, A->bits, ctx->minfo); } void fq_zech_mpoly_degree_fmpz(fmpz_t deg, const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx) { mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } slong fq_zech_mpoly_degree_si(const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx) { return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } int fq_zech_mpoly_total_degree_fits_si(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return mpoly_total_degree_fits_si(A->exps, A->length, A->bits, ctx->minfo); } void fq_zech_mpoly_total_degree_fmpz(fmpz_t td, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { mpoly_total_degree_fmpz(td, A->exps, A->length, A->bits, ctx->minfo); } slong fq_zech_mpoly_total_degree_si(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return mpoly_total_degree_si(A->exps, A->length, A->bits, ctx->minfo); } flint-3.1.3/src/fq_zech_mpoly/derivative.c000066400000000000000000000067511461254215100206000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" slong _fq_zech_mpoly_derivative(fq_zech_struct * Acoeff, ulong * Aexp, const fq_zech_struct * Bcoeff, const ulong * Bexp, slong Blen, flint_bitcnt_t bits, slong N, slong offset, slong shift, ulong * oneexp, const fq_zech_ctx_t fqctx) { slong i, Alen; /* x^c -> c*x^(c-1) */ Alen = 0; for (i = 0; i < Blen; i++) { mp_limb_t cr; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong c = (Bexp[N*i + offset] >> shift) & mask; if (c == 0) continue; NMOD_RED(cr, c, fq_zech_ctx_mod(fqctx)); if (cr == 0) continue; fq_zech_mul_ui(Acoeff + Alen, Bcoeff + i, cr, fqctx); mpoly_monomial_sub(Aexp + N*Alen, Bexp + N*i, oneexp, N); Alen++; } return Alen; } slong _fq_zech_mpoly_derivative_mp(fq_zech_struct * Acoeff, ulong * Aexp, const fq_zech_struct * Bcoeff, const ulong * Bexp, slong Blen, flint_bitcnt_t bits, slong N, slong offset, ulong * oneexp, const fq_zech_ctx_t fqctx) { slong i, Alen; fmpz_t c; fmpz_init(c); /* x^c -> c*x^(c-1) */ Alen = 0; for (i = 0; i < Blen; i++) { mp_limb_t cr; fmpz_set_ui_array(c, Bexp + N*i + offset, bits/FLINT_BITS); if (fmpz_is_zero(c)) continue; cr = fmpz_fdiv_ui(c, fq_zech_ctx_mod(fqctx).n); if (cr == 0) continue; fq_zech_mul_ui(Acoeff + Alen, Bcoeff + i, cr, fqctx); mpoly_monomial_sub_mp(Aexp + N*Alen, Bexp + N*i, oneexp, N); Alen++; } fmpz_clear(c); return Alen; } void fq_zech_mpoly_derivative(fq_zech_mpoly_t poly1, const fq_zech_mpoly_t poly2, slong var, const fq_zech_mpoly_ctx_t ctx) { slong bits, N, offset, shift; ulong * oneexp; slong len1; TMP_INIT; TMP_START; bits = poly2->bits; fq_zech_mpoly_fit_length(poly1, poly2->length, ctx); fq_zech_mpoly_fit_bits(poly1, bits, ctx); poly1->bits = bits; N = mpoly_words_per_exp(bits, ctx->minfo); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (bits <= FLINT_BITS) { mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, bits, ctx->minfo); len1 = _fq_zech_mpoly_derivative(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, shift, oneexp, ctx->fqctx); } else { offset = mpoly_gen_monomial_offset_mp(oneexp, var, bits, ctx->minfo); len1 = _fq_zech_mpoly_derivative_mp(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, oneexp, ctx->fqctx); } _fq_zech_mpoly_set_length(poly1, len1, ctx); TMP_END; } flint-3.1.3/src/fq_zech_mpoly/divides.c000066400000000000000000000012771461254215100200630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" int fq_zech_mpoly_divides(fq_zech_mpoly_t Q, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { /* nothing fancy here */ return fq_zech_mpoly_divides_monagan_pearce(Q, A, B, ctx); } flint-3.1.3/src/fq_zech_mpoly/divides_monagan_pearce.c000066400000000000000000000320751461254215100231020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" static slong _fq_zech_mpoly_divides_monagan_pearce( fq_zech_struct ** coeff1, ulong ** exp1, slong * alloc, const fq_zech_struct * coeff2, const ulong * exp2, slong len2, const fq_zech_struct * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx) { int lt_divides; slong i, j, q_len, s; slong next_loc, heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fq_zech_struct * q_coeff = * coeff1; ulong * q_exp = * exp1; ulong * exp, * exps; ulong ** exp_list; slong exp_next; fq_zech_t lc_minus_inv, pp; ulong mask; slong * hind; TMP_INIT; TMP_START; fq_zech_init(pp, fqctx); fq_zech_init(lc_minus_inv, fqctx); /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(mpoly_heap_t *)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; q_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coefficient info */ fq_zech_inv(lc_minus_inv, coeff3 + 0, fqctx); fq_zech_neg(lc_minus_inv, lc_minus_inv, fqctx); while (heap_len > 1) { _fq_zech_mpoly_fit_length(&q_coeff, &q_exp, alloc, q_len + 1, N, fqctx); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; lt_divides = mpoly_monomial_divides(q_exp + q_len*N, exp, exp3, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto not_exact_division; lt_divides = mpoly_monomial_divides_mp(q_exp + q_len*N, exp, exp3, N, bits); } fq_zech_zero(q_coeff + q_len, fqctx); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { fq_zech_sub(q_coeff + q_len, q_coeff + q_len, coeff2 + x->j, fqctx); } else { hind[x->i] |= WORD(1); fq_zech_mul(pp, coeff3 + x->i, q_coeff + x->j, fqctx); fq_zech_add(q_coeff + q_len, q_coeff + q_len, pp, fqctx); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go up */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } fq_zech_mul(q_coeff + q_len, q_coeff + q_len, lc_minus_inv, fqctx); if (fq_zech_is_zero(q_coeff + q_len, fqctx)) { continue; } if (!lt_divides || mpoly_monomial_gt(exp2 + N*(len2 - 1), exp, N, cmpmask)) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; q_len++; } cleanup: *coeff1 = q_coeff; *exp1 = q_exp; TMP_END; fq_zech_clear(pp, fqctx); fq_zech_clear(lc_minus_inv, fqctx); return q_len; not_exact_division: q_len = 0; goto cleanup; } /* return 1 if quotient is exact */ int fq_zech_mpoly_divides_monagan_pearce(fq_zech_mpoly_t poly1, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx) { slong i, N, len = 0; flint_bitcnt_t exp_bits; fmpz * max_fields2, * max_fields3; ulong * cmpmask; ulong * exp2 = poly2->exps, * exp3 = poly3->exps, * expq; int easy_exit, free2 = 0, free3 = 0; ulong mask = 0; TMP_INIT; if (poly3->length == 0) flint_throw(FLINT_DIVZERO, "Divide by zero in fq_zech_mpoly_divides_monagan_pearce"); if (poly2->length == 0) { fq_zech_mpoly_zero(poly1, ctx); return 1; } TMP_START; max_fields2 = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields3 = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(max_fields2 + i); fmpz_init(max_fields3 + i); } mpoly_max_fields_fmpz(max_fields2, poly2->exps, poly2->length, poly2->bits, ctx->minfo); mpoly_max_fields_fmpz(max_fields3, poly3->exps, poly3->length, poly3->bits, ctx->minfo); easy_exit = 0; for (i = 0; i < ctx->minfo->nfields; i++) { /* cannot be exact division if any max field from poly2 is less than corresponding max field from poly3 */ if (fmpz_cmp(max_fields2 + i, max_fields3 + i) < 0) easy_exit = 1; } exp_bits = _fmpz_vec_max_bits(max_fields2, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = FLINT_MAX(exp_bits, poly2->bits); exp_bits = FLINT_MAX(exp_bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(max_fields2 + i); fmpz_clear(max_fields3 + i); } if (easy_exit) { len = 0; goto cleanup; } N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* temporary space to check leading monomials divide */ expq = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* quick check for easy case of inexact division of leading monomials */ if (poly2->bits == poly3->bits && N == 1 && poly2->exps[0] < poly3->exps[0]) { goto cleanup; } /* ensure input exponents packed to same size as output exponents */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* check leading monomial divides exactly */ if (exp_bits <= FLINT_BITS) { /* mask with high bit of each exponent vector field set */ for (i = 0; i < FLINT_BITS/exp_bits; i++) mask = (mask << exp_bits) + (UWORD(1) << (exp_bits - 1)); if (!mpoly_monomial_divides(expq, exp2, exp3, N, mask)) { len = 0; goto cleanup; } } else { if (!mpoly_monomial_divides_mp(expq, exp2, exp3, N, exp_bits)) { len = 0; goto cleanup; } } /* deal with aliasing and divide polynomials */ if (poly1 == poly2 || poly1 == poly3) { fq_zech_mpoly_t temp; fq_zech_mpoly_init2(temp, poly2->length/poly3->length + 1, ctx); fq_zech_mpoly_fit_bits(temp, exp_bits, ctx); temp->bits = exp_bits; len = _fq_zech_mpoly_divides_monagan_pearce(&temp->coeffs, &temp->exps, &temp->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask, ctx->fqctx); fq_zech_mpoly_swap(temp, poly1, ctx); fq_zech_mpoly_clear(temp, ctx); } else { fq_zech_mpoly_fit_length(poly1, poly2->length/poly3->length + 1, ctx); fq_zech_mpoly_fit_bits(poly1, exp_bits, ctx); poly1->bits = exp_bits; len = _fq_zech_mpoly_divides_monagan_pearce(&poly1->coeffs, &poly1->exps, &poly1->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask, ctx->fqctx); } cleanup: _fq_zech_mpoly_set_length(poly1, len, ctx); if (free2) flint_free(exp2); if (free3) flint_free(exp3); TMP_END; /* division is exact if len is nonzero */ return (len != 0); } flint-3.1.3/src/fq_zech_mpoly/divrem.c000066400000000000000000000013111461254215100177070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" void fq_zech_mpoly_divrem(fq_zech_mpoly_t Q, fq_zech_mpoly_t R, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { /* nothing fancy */ fq_zech_mpoly_divrem_monagan_pearce(Q, R, A, B, ctx); } flint-3.1.3/src/fq_zech_mpoly/divrem_monagan_pearce.c000066400000000000000000000313301461254215100227320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" static slong _fq_zech_mpoly_divrem_monagan_pearce(slong * lenr, fq_zech_struct ** polyq, ulong ** expq, slong * allocq, fq_zech_struct ** polyr, ulong ** expr, slong * allocr, const fq_zech_struct * coeff2, const ulong * exp2, slong len2, const fq_zech_struct * coeff3, const ulong * exp3, slong len3, slong bits, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx) { slong i, j, q_len, r_len, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; fq_zech_struct * q_coeff = *polyq; fq_zech_struct * r_coeff = *polyr; ulong * q_exp = *expq; ulong * r_exp = *expr; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; int lt_divides; fq_zech_t lc_minus_inv, pp; TMP_INIT; TMP_START; fq_zech_init(pp, fqctx); fq_zech_init(lc_minus_inv, fqctx); /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(mpoly_heap_t *)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; q_len = WORD(0); r_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coefficient info */ fq_zech_inv(lc_minus_inv, coeff3 + 0, fqctx); fq_zech_neg(lc_minus_inv, lc_minus_inv, fqctx); while (heap_len > 1) { _fq_zech_mpoly_fit_length(&q_coeff, &q_exp, allocq, q_len + 1, N, fqctx); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow2; lt_divides = mpoly_monomial_divides(q_exp + q_len*N, exp, exp3, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow2; lt_divides = mpoly_monomial_divides_mp(q_exp + q_len*N, exp, exp3, N, bits); } fq_zech_zero(q_coeff + q_len, fqctx); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { fq_zech_sub(q_coeff + q_len, q_coeff + q_len, coeff2 + x->j, fqctx); } else { fq_zech_mul(pp, coeff3 + x->i, q_coeff + x->j, fqctx); fq_zech_add(q_coeff + q_len, q_coeff + q_len, pp, fqctx); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term */ if (fq_zech_is_zero(q_coeff + q_len, fqctx)) { continue; } if (!lt_divides) { _fq_zech_mpoly_fit_length(&r_coeff, &r_exp, allocr, r_len + 1, N, fqctx); fq_zech_neg(r_coeff + r_len, q_coeff + q_len, fqctx); mpoly_monomial_set(r_exp + r_len*N, exp, N); r_len++; continue; } fq_zech_mul(q_coeff + q_len, q_coeff + q_len, lc_minus_inv, fqctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; q_len++; } cleanup2: (*polyq) = q_coeff; (*expq) = q_exp; (*polyr) = r_coeff; (*expr) = r_exp; /* set remainder poly length */ (*lenr) = r_len; TMP_END; fq_zech_clear(pp, fqctx); fq_zech_clear(lc_minus_inv, fqctx); /* return quotient poly length */ return q_len; exp_overflow2: q_len = 0; r_len = 0; goto cleanup2; } void fq_zech_mpoly_divrem_monagan_pearce(fq_zech_mpoly_t q, fq_zech_mpoly_t r, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx) { slong exp_bits, N, lenq = 0, lenr = 0; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; ulong * cmpmask; int free2 = 0, free3 = 0; fq_zech_mpoly_t temp1, temp2; fq_zech_mpoly_struct * tq, * tr; if (poly3->length == 0) { flint_throw(FLINT_DIVZERO, "Divide by zero in nmod_mpoly_divrem_monagan_pearce"); } if (poly2->length == 0) { fq_zech_mpoly_zero(q, ctx); fq_zech_mpoly_zero(r, ctx); return; } exp_bits = FLINT_MAX(poly2->bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(exp2, exp3, N, cmpmask)) { fq_zech_mpoly_set(r, poly2, ctx); fq_zech_mpoly_zero(q, ctx); goto cleanup3; } /* take care of aliasing */ if (q == poly2 || q == poly3) { fq_zech_mpoly_init2(temp1, poly2->length/poly3->length + 1, ctx); fq_zech_mpoly_fit_bits(temp1, exp_bits, ctx); temp1->bits = exp_bits; tq = temp1; } else { fq_zech_mpoly_fit_length(q, poly2->length/poly3->length + 1, ctx); fq_zech_mpoly_fit_bits(q, exp_bits, ctx); q->bits = exp_bits; tq = q; } if (r == poly2 || r == poly3) { fq_zech_mpoly_init2(temp2, poly3->length, ctx); fq_zech_mpoly_fit_bits(temp2, exp_bits, ctx); temp2->bits = exp_bits; tr = temp2; } else { fq_zech_mpoly_fit_length(r, poly3->length, ctx); fq_zech_mpoly_fit_bits(r, exp_bits, ctx); r->bits = exp_bits; tr = r; } /* do division with remainder */ while ((lenq = _fq_zech_mpoly_divrem_monagan_pearce(&lenr, &tq->coeffs, &tq->exps, &tq->alloc, &tr->coeffs, &tr->exps, &tr->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask, ctx->fqctx)) == 0 && lenr == 0) { ulong * old_exp2 = exp2, * old_exp3 = exp3; slong old_exp_bits = exp_bits; exp_bits = mpoly_fix_bits(exp_bits + 1, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, old_exp2, old_exp_bits, poly2->length, ctx->minfo); exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, old_exp3, old_exp_bits, poly3->length, ctx->minfo); if (free2) flint_free(old_exp2); if (free3) flint_free(old_exp3); free2 = free3 = 1; fq_zech_mpoly_fit_bits(tq, exp_bits, ctx); tq->bits = exp_bits; fq_zech_mpoly_fit_bits(tr, exp_bits, ctx); tr->bits = exp_bits; } /* deal with aliasing */ if (q == poly2 || q == poly3) { fq_zech_mpoly_swap(temp1, q, ctx); fq_zech_mpoly_clear(temp1, ctx); } if (r == poly2 || r == poly3) { fq_zech_mpoly_swap(temp2, r, ctx); fq_zech_mpoly_clear(temp2, ctx); } _fq_zech_mpoly_set_length(q, lenq, ctx); _fq_zech_mpoly_set_length(r, lenr, ctx); cleanup3: if (free2) flint_free(exp2); if (free3) flint_free(exp3); flint_free(cmpmask); } flint-3.1.3/src/fq_zech_mpoly/equal.c000066400000000000000000000044271461254215100175430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" int _fq_zech_mpoly_equal(const fq_zech_struct * coeff1, const ulong * exp1, const fq_zech_struct * coeff2, const ulong * exp2, slong len, slong N, const fq_zech_mpoly_ctx_t ctx) { slong i; if (coeff1 != coeff2) { for (i = 0; i < len; i++) if (!fq_zech_equal(coeff1 + i, coeff2 + i, ctx->fqctx)) return 0; } if (exp1 != exp2) { for (i = 0; i < len; i++) if (!mpoly_monomial_equal(exp1 + N*i, exp2 + N*i, N)) return 0; } return 1; } int fq_zech_mpoly_equal(const fq_zech_mpoly_t poly1, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_ctx_t ctx) { ulong * ptr1 = poly1->exps, * ptr2 = poly2->exps; slong max_bits, N; int r, free1 = 0, free2 = 0; if (poly1 == poly2) return 1; if (poly1->length != poly2->length) return 0; max_bits = FLINT_MAX(poly1->bits, poly2->bits); N = mpoly_words_per_exp(max_bits, ctx->minfo); if (max_bits > poly1->bits) { free1 = 1; ptr1 = (ulong *) flint_malloc(N*poly1->length*sizeof(ulong)); mpoly_repack_monomials(ptr1, max_bits, poly1->exps, poly1->bits, poly1->length, ctx->minfo); } if (max_bits > poly2->bits) { free2 = 1; ptr2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(ptr2, max_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } r = _fq_zech_mpoly_equal(poly1->coeffs, ptr1, poly2->coeffs, ptr2, poly2->length, N, ctx); if (free1) flint_free(ptr1); if (free2) flint_free(ptr2); return r; } flint-3.1.3/src/fq_zech_mpoly/evaluate_all.c000066400000000000000000000052371461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void _fq_zech_mpoly_eval_all_fq_zech( fq_zech_t eval, const fq_zech_struct * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, fq_zech_struct * const * alphas, const mpoly_ctx_t mctx, const fq_zech_ctx_t fqctx) { slong i, j; slong nvars = mctx->nvars; ulong mask = (Abits <= FLINT_BITS) ? (-UWORD(1)) >> (FLINT_BITS - Abits) : 0; slong N = mpoly_words_per_exp(Abits, mctx); ulong varexp_sp; fmpz_t varexp_mp; slong * offsets, * shifts; fq_zech_t t, p; TMP_INIT; TMP_START; fmpz_init(varexp_mp); fq_zech_init(t, fqctx); fq_zech_init(p, fqctx); offsets = (slong *) TMP_ALLOC(2*nvars*sizeof(slong)); shifts = offsets + nvars; for (j = 0; j < nvars; j++) { if (Abits <= FLINT_BITS) mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, Abits, mctx); else offsets[j] = mpoly_gen_offset_mp(j, Abits, mctx); } fq_zech_zero(eval, fqctx); for (i = 0; i < Alen; i++) { fq_zech_set(t, Acoeffs + i, fqctx); if (Abits <= FLINT_BITS) { for (j = 0; j < nvars; j++) { varexp_sp = ((Aexps + N*i)[offsets[j]]>>shifts[j])&mask; fq_zech_pow_ui(p, alphas[j], varexp_sp, fqctx); fq_zech_mul(t, t, p, fqctx); } } else { for (j = 0; j < nvars; j++) { fmpz_set_ui_array(varexp_mp, Aexps + N*i + offsets[j], Abits/FLINT_BITS); fq_zech_pow(p, alphas[j], varexp_mp, fqctx); fq_zech_mul(t, t, p, fqctx); } } fq_zech_add(eval, eval, t, fqctx); } fmpz_clear(varexp_mp); fq_zech_clear(t, fqctx); fq_zech_clear(p, fqctx); TMP_END; } void fq_zech_mpoly_evaluate_all_ui(fq_zech_t eval, const fq_zech_mpoly_t A, fq_zech_struct * const * vals, const fq_zech_mpoly_ctx_t ctx) { if (fq_zech_mpoly_is_zero(A, ctx)) { fq_zech_zero(eval, ctx->fqctx); return; } _fq_zech_mpoly_eval_all_fq_zech(eval, A->coeffs, A->exps, A->length, A->bits, vals, ctx->minfo, ctx->fqctx); } flint-3.1.3/src/fq_zech_mpoly/evaluate_one.c000066400000000000000000000123301461254215100210730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" /* exponents of B are not multiprecision */ static void _fq_zech_mpoly_evaluate_one_fq_zech_sp( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_t val, const fq_zech_mpoly_ctx_t ctx) { slong i, N, off, shift; ulong * cmpmask, * one; slong Blen = B->length; const fq_zech_struct * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; fq_zech_struct * Acoeffs; ulong * Aexps; ulong mask, k; int need_sort = 0, cmp; fq_zech_t pp; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; fq_zech_init(pp, ctx->fqctx); fq_zech_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; mask = (-UWORD(1)) >> (FLINT_BITS - bits); N = mpoly_words_per_exp_sp(bits, ctx->minfo); one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; fq_zech_pow_ui(pp, val, k, ctx->fqctx); fq_zech_mul(Acoeffs + Alen, Bcoeffs + i, pp, ctx->fqctx); if (fq_zech_is_zero(Acoeffs + Alen, ctx->fqctx)) continue; mpoly_monomial_msub(Aexps + N*Alen, Bexps + N*i, k, one, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fq_zech_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen, ctx->fqctx); Alen -= fq_zech_is_zero(Acoeffs + Alen - 1, ctx->fqctx); } A->length = Alen; fq_zech_clear(pp, ctx->fqctx); TMP_END; if (need_sort) { fq_zech_mpoly_sort_terms(A, ctx); fq_zech_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fq_zech_mpoly_is_canonical(A, ctx)); } /* exponents of B are multiprecision */ static void _fq_zech_mpoly_evaluate_one_fq_zech_mp( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_t val, const fq_zech_mpoly_ctx_t ctx) { slong i, N, off; ulong * cmpmask, * one, * tmp; slong Blen = B->length; const fq_zech_struct * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; fq_zech_struct * Acoeffs; ulong * Aexps; fmpz_t k; int need_sort = 0, cmp; fq_zech_t pp; TMP_INIT; FLINT_ASSERT(B->bits > FLINT_BITS); FLINT_ASSERT((B->bits % FLINT_BITS) == 0); TMP_START; fmpz_init(k); fq_zech_init(pp, ctx->fqctx); fq_zech_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; N = mpoly_words_per_exp_mp(bits, ctx->minfo); one = (ulong *) TMP_ALLOC(3*N*sizeof(ulong)); cmpmask = one + N; tmp = cmpmask + N; off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexps + N*i + off, bits/FLINT_BITS); fq_zech_pow(pp, val, k, ctx->fqctx); fq_zech_mul(Acoeffs + Alen, Bcoeffs + i, pp, ctx->fqctx); if (fq_zech_is_zero(Acoeffs + Alen, ctx->fqctx)) continue; mpoly_monomial_mul_fmpz(tmp, one, N, k); mpoly_monomial_sub_mp(Aexps + N*Alen, Bexps + N*i, tmp, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } fq_zech_add(Acoeffs + Alen - 1, Acoeffs + Alen - 1, Acoeffs + Alen, ctx->fqctx); Alen -= fq_zech_is_zero(Acoeffs + Alen - 1, ctx->fqctx); } A->length = Alen; fq_zech_clear(pp, ctx->fqctx); fmpz_clear(k); TMP_END; if (need_sort) { fq_zech_mpoly_sort_terms(A, ctx); fq_zech_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(fq_zech_mpoly_is_canonical(A, ctx)); } void fq_zech_mpoly_evaluate_one_fq_zech( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_t val, const fq_zech_mpoly_ctx_t ctx) { if (fq_zech_mpoly_is_zero(B, ctx)) { fq_zech_mpoly_zero(A, ctx); return; } if (B->bits <= FLINT_BITS) _fq_zech_mpoly_evaluate_one_fq_zech_sp(A, B, var, val, ctx); else _fq_zech_mpoly_evaluate_one_fq_zech_mp(A, B, var, val, ctx); } flint-3.1.3/src/fq_zech_mpoly/fit_bits.c000066400000000000000000000017171461254215100202360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_fit_bits(fq_zech_mpoly_t A, slong bits, const fq_zech_mpoly_ctx_t ctx) { if (A->bits < bits) { if (A->alloc != 0) { slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong * t = (ulong *) flint_malloc(N*A->alloc*sizeof(ulong)); mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, ctx->minfo); flint_free(A->exps); A->exps = t; } A->bits = bits; } } flint-3.1.3/src/fq_zech_mpoly/fit_length.c000066400000000000000000000061631461254215100205560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void _fq_zech_mpoly_fit_length(fq_zech_struct ** coeff, ulong ** exps, slong * alloc, slong len, slong N, const fq_zech_ctx_t fqctx) { if (len > *alloc) { slong i; len = FLINT_MAX(len, 2*(*alloc)); (* coeff) = (fq_zech_struct *) flint_realloc(* coeff, len*sizeof(fq_zech_struct)); (* exps) = (ulong *) flint_realloc(*exps, len*N*sizeof(ulong)); for (i = *alloc; i < len; i++) fq_zech_init((* coeff) + i, fqctx); (* alloc) = len; } } void fq_zech_mpoly_fit_length(fq_zech_mpoly_t A, slong length, const fq_zech_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (old_alloc == 0) { A->exps = (ulong *) flint_malloc(new_alloc*N*sizeof(ulong)); A->coeffs = (fq_zech_struct *) flint_malloc(new_alloc *sizeof(fq_zech_struct)); } else { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*N*sizeof(ulong)); A->coeffs = (fq_zech_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_zech_struct)); } for (i = old_alloc; i < new_alloc; i++) { fq_zech_init(A->coeffs + i, ctx->fqctx); } A->alloc = new_alloc; } } void fq_zech_mpoly_fit_length_reset_bits( fq_zech_mpoly_t A, slong len, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx) { slong i; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong new_alloc; FLINT_ASSERT(len >= 0); if (A->alloc < len) { new_alloc = FLINT_MAX(len, 2*A->alloc); if (A->alloc > 0) { A->coeffs = (fq_zech_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_zech_struct)); A->exps = (ulong *) flint_realloc(A->exps, new_alloc*N*sizeof(ulong)); } else { A->coeffs = (fq_zech_struct *) flint_malloc(new_alloc*sizeof(fq_zech_struct)); A->exps = (ulong *) flint_malloc(new_alloc*N*sizeof(ulong)); } for (i = A->alloc; i < new_alloc; i++) fq_zech_init(A->coeffs + i, ctx->fqctx); A->alloc = new_alloc; } else if (A->bits < bits) { if (A->alloc > 0) A->exps = (ulong *) flint_realloc(A->exps, A->alloc*N*sizeof(ulong)); } A->bits = bits; } flint-3.1.3/src/fq_zech_mpoly/gcd.c000066400000000000000000000030001461254215100171530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_gcd( fq_zech_mpoly_t G, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { int success; fq_nmod_mpoly_ctx_t ctx2; fq_nmod_mpoly_t A2, B2, G2; if (fq_zech_mpoly_is_zero(A, ctx)) { if (fq_zech_mpoly_is_zero(B, ctx)) fq_zech_mpoly_zero(G, ctx); else fq_zech_mpoly_make_monic(G, B, ctx); return 1; } if (fq_zech_mpoly_is_zero(B, ctx)) { fq_zech_mpoly_make_monic(G, A, ctx); return 1; } *ctx2->minfo = *ctx->minfo; *ctx2->fqctx = *ctx->fqctx->fq_nmod_ctx; fq_nmod_mpoly_init(A2, ctx2); fq_nmod_mpoly_init(B2, ctx2); fq_nmod_mpoly_init(G2, ctx2); _fq_zech_mpoly_get_fq_nmod_mpoly(A2, ctx2, A, ctx); _fq_zech_mpoly_get_fq_nmod_mpoly(B2, ctx2, B, ctx); success = fq_nmod_mpoly_gcd(G2, A2, B2, ctx2); if (success) _fq_zech_mpoly_set_fq_nmod_mpoly(G, ctx, G2, ctx2); fq_nmod_mpoly_clear(A2, ctx2); fq_nmod_mpoly_clear(B2, ctx2); fq_nmod_mpoly_clear(G2, ctx2); return success; } flint-3.1.3/src/fq_zech_mpoly/gcd_cofactors.c000066400000000000000000000063611461254215100212330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #include "fq_nmod_mpoly.h" #include "fq_zech_mpoly.h" static void _fq_zech_vec_scalar_div_fq_zech( fq_zech_struct * A, const fq_zech_struct * B, slong len, const fq_zech_t c, const fq_zech_ctx_t fqctx) { slong i; fq_zech_t cinv; fq_zech_init(cinv, fqctx); fq_zech_inv(cinv, c, fqctx); for (i = 0; i < len; i++) fq_zech_mul(A + i, B + i, cinv, fqctx); fq_zech_clear(cinv, fqctx); } int fq_zech_mpoly_gcd_cofactors( fq_zech_mpoly_t G, fq_zech_mpoly_t Abar, fq_zech_mpoly_t Bbar, const fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { int success; fq_nmod_mpoly_ctx_t ctx2; fq_nmod_mpoly_t A2, B2, G2, Abar2, Bbar2; if (A->length == 0) { if (B->length == 0) { fq_zech_mpoly_zero(G, ctx); fq_zech_mpoly_zero(Abar, ctx); fq_zech_mpoly_zero(Bbar, ctx); return 1; } fq_zech_mpoly_set(G, B, ctx); fq_zech_mpoly_zero(Abar, ctx); fq_zech_mpoly_one(Bbar, ctx); if (!fq_zech_is_one(G->coeffs + 0, ctx->fqctx)) { _fq_zech_vec_scalar_mul_fq_zech(Bbar->coeffs, Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx->fqctx); _fq_zech_vec_scalar_div_fq_zech(G->coeffs, G->coeffs, G->length, G->coeffs + 0, ctx->fqctx); } return 1; } if (B->length == 0) { fq_zech_mpoly_set(G, A, ctx); fq_zech_mpoly_zero(Bbar, ctx); fq_zech_mpoly_one(Abar, ctx); if (!fq_zech_is_one(G->coeffs + 0, ctx->fqctx)) { _fq_zech_vec_scalar_mul_fq_zech(Abar->coeffs, Abar->coeffs, Abar->length, G->coeffs + 0, ctx->fqctx); _fq_zech_vec_scalar_div_fq_zech(G->coeffs, G->coeffs, G->length, G->coeffs + 0, ctx->fqctx); } return 1; } *ctx2->minfo = *ctx->minfo; *ctx2->fqctx = *ctx->fqctx->fq_nmod_ctx; fq_nmod_mpoly_init(A2, ctx2); fq_nmod_mpoly_init(B2, ctx2); fq_nmod_mpoly_init(G2, ctx2); fq_nmod_mpoly_init(Abar2, ctx2); fq_nmod_mpoly_init(Bbar2, ctx2); _fq_zech_mpoly_get_fq_nmod_mpoly(A2, ctx2, A, ctx); _fq_zech_mpoly_get_fq_nmod_mpoly(B2, ctx2, B, ctx); success = fq_nmod_mpoly_gcd_cofactors(G2, Abar2, Bbar2, A2, B2, ctx2); if (success) { _fq_zech_mpoly_set_fq_nmod_mpoly(G, ctx, G2, ctx2); _fq_zech_mpoly_set_fq_nmod_mpoly(Abar, ctx, Abar2, ctx2); _fq_zech_mpoly_set_fq_nmod_mpoly(Bbar, ctx, Bbar2, ctx2); } fq_nmod_mpoly_clear(A2, ctx2); fq_nmod_mpoly_clear(B2, ctx2); fq_nmod_mpoly_clear(G2, ctx2); fq_nmod_mpoly_clear(Abar2, ctx2); fq_nmod_mpoly_clear(Bbar2, ctx2); return success; } flint-3.1.3/src/fq_zech_mpoly/gen.c000066400000000000000000000020301461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_gen(fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx) { flint_bitcnt_t bits; bits = mpoly_gen_bits_required(var, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); fq_zech_mpoly_fit_length(A, 1, ctx); fq_zech_mpoly_fit_bits(A, bits, ctx); A->bits = bits; fq_zech_one(A->coeffs + 0, ctx->fqctx); if (bits <= FLINT_BITS) mpoly_gen_monomial_sp(A->exps, var, bits, ctx->minfo); else mpoly_gen_monomial_offset_mp(A->exps, var, bits, ctx->minfo); A->length = 1; } flint-3.1.3/src/fq_zech_mpoly/get_coeff_vars_ui.c000066400000000000000000000106321461254215100221000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_get_coeff_vars_ui(fq_zech_mpoly_t C, const fq_zech_mpoly_t A, const slong * vars, const ulong * exps, slong length, const fq_zech_mpoly_ctx_t ctx) { slong i, j, N; slong offset, shift; slong maxoffset, minoffset; ulong * uexp; ulong * tmask, * texp; slong nvars = ctx->minfo->nvars; fq_zech_struct * Ccoeff; ulong * Cexp; slong Calloc; slong Clen; TMP_INIT; if (C == A) { fq_zech_mpoly_t T; fq_zech_mpoly_init(T, ctx); fq_zech_mpoly_get_coeff_vars_ui(T, A, vars, exps, length, ctx); fq_zech_mpoly_swap(T, C, ctx); fq_zech_mpoly_clear(T, ctx); return; } TMP_START; uexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); for (i = 0; i < nvars; i++) { uexp[i] = 0; } for (i = 0; i < length; i++) { uexp[vars[i]] = exps[i]; } if (A->bits < mpoly_exp_bits_required_ui(uexp, ctx->minfo)) { fq_zech_mpoly_zero(C, ctx); goto cleanup; } fq_zech_mpoly_fit_bits(C, A->bits, ctx); C->bits = A->bits; N = mpoly_words_per_exp(A->bits, ctx->minfo); tmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(tmask, N); mpoly_set_monomial_ui(texp, uexp, A->bits, ctx->minfo); if (A->bits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { mpoly_gen_offset_shift_sp(&offset, &shift, vars[i], A->bits, ctx->minfo); tmask[offset] |= mask << shift; maxoffset = FLINT_MAX(maxoffset, offset); minoffset = FLINT_MIN(minoffset, offset); } FLINT_ASSERT(minoffset < N); Ccoeff = C->coeffs; Cexp = C->exps; Calloc = C->alloc; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_sp; } _fq_zech_mpoly_fit_length(&Ccoeff, &Cexp, &Calloc, Clen + 1, N, ctx->fqctx); mpoly_monomial_sub(Cexp + N*Clen, A->exps + N*i, texp, N); fq_zech_set(Ccoeff + Clen, A->coeffs + i, ctx->fqctx); Clen++; continue_outer_sp:; } C->coeffs = Ccoeff; C->exps = Cexp; C->alloc = Calloc; _fq_zech_mpoly_set_length(C, Clen, ctx); } else { ulong wpf = A->bits/FLINT_BITS; maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { offset = mpoly_gen_offset_mp(vars[i], A->bits, ctx->minfo); minoffset = FLINT_MIN(minoffset, offset); maxoffset = FLINT_MAX(maxoffset, offset + wpf - 1); for (j = 0; j < wpf; j++) tmask[offset + j] = -UWORD(1); } FLINT_ASSERT(minoffset < N); Ccoeff = C->coeffs; Cexp = C->exps; Calloc = C->alloc; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_mp; } _fq_zech_mpoly_fit_length(&Ccoeff, &Cexp, &Calloc, Clen + 1, N, ctx->fqctx); mpoly_monomial_sub_mp(Cexp + N*Clen, A->exps + N*i, texp, N); fq_zech_set(Ccoeff + Clen, A->coeffs + i, ctx->fqctx); Clen++; continue_outer_mp:; } C->coeffs = Ccoeff; C->exps = Cexp; C->alloc = Calloc; _fq_zech_mpoly_set_length(C, Clen, ctx); } cleanup: TMP_END; return; } flint-3.1.3/src/fq_zech_mpoly/get_set_fq_nmod_mpoly.c000066400000000000000000000042031461254215100230010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_zech.h" #include "n_poly.h" #include "mpoly.h" #include "fq_nmod_mpoly.h" #include "fq_zech_mpoly.h" void _fq_zech_mpoly_get_fq_nmod_mpoly( fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctxA, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctxB) { slong d = fq_nmod_ctx_degree(ctxA->fqctx); flint_bitcnt_t bits = B->bits; slong i, N = mpoly_words_per_exp(bits, ctxB->minfo); fq_nmod_t t; fq_nmod_init(t, ctxA->fqctx); FLINT_ASSERT(ctxA->minfo->ord == ctxB->minfo->ord); FLINT_ASSERT(ctxA->minfo->nvars == ctxB->minfo->nvars); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, bits, ctxA); A->length = B->length; for (i = 0; i < B->length; i++) { fq_zech_get_fq_nmod(t, B->coeffs + i, ctxB->fqctx); n_fq_set_fq_nmod(A->coeffs + d*i, t, ctxA->fqctx); } mpoly_copy_monomials(A->exps, B->exps, B->length, N); fq_nmod_clear(t, ctxA->fqctx); } void _fq_zech_mpoly_set_fq_nmod_mpoly( fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctxA, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctxB) { slong d = fq_nmod_ctx_degree(ctxB->fqctx); flint_bitcnt_t bits = B->bits; slong i, N = mpoly_words_per_exp(bits, ctxB->minfo); fq_nmod_t t; fq_nmod_init(t, ctxB->fqctx); FLINT_ASSERT(ctxA->minfo->ord == ctxB->minfo->ord); FLINT_ASSERT(ctxA->minfo->nvars == ctxB->minfo->nvars); fq_zech_mpoly_fit_length_reset_bits(A, B->length, bits, ctxA); A->length = B->length; for (i = 0; i < B->length; i++) { n_fq_get_fq_nmod(t, B->coeffs + d*i, ctxB->fqctx); fq_zech_set_fq_nmod(A->coeffs + i, t, ctxA->fqctx); } mpoly_copy_monomials(A->exps, B->exps, B->length, N); fq_nmod_clear(t, ctxB->fqctx); } flint-3.1.3/src/fq_zech_mpoly/get_set_nmod_mpoly.c000066400000000000000000000042221461254215100223140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_zech.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_zech_mpoly.h" /* TODO move this and make it faster */ static int fq_zech_get_ui(ulong * res, const fq_zech_t op, const fq_zech_ctx_t ctx) { int success; nmod_poly_t asdf; nmod_poly_init_mod(asdf, fq_zech_ctx_modulus(ctx)->mod); fq_zech_get_nmod_poly(asdf, op, ctx); success = (asdf->length <= 1); if (asdf->length == 1) *res = asdf->coeffs[0]; else *res = 0; nmod_poly_clear(asdf); return success; } int _fq_zech_mpoly_get_nmod_mpoly( nmod_mpoly_t s, const nmod_mpoly_ctx_t sctx, const fq_zech_mpoly_t t, const fq_zech_mpoly_ctx_t tctx) { slong i, N; FLINT_ASSERT(sctx->minfo->ord == tctx->minfo->ord); FLINT_ASSERT(sctx->minfo->nvars == tctx->minfo->nvars); nmod_mpoly_fit_length_reset_bits(s, t->length, t->bits, sctx); s->length = t->length; N = mpoly_words_per_exp(t->bits, tctx->minfo); mpoly_copy_monomials(s->exps, t->exps, t->length, N); for (i = 0; i < t->length; i++) { if (!fq_zech_get_ui(s->coeffs + i, t->coeffs + i, tctx->fqctx)) return 0; } return 1; } void _fq_zech_mpoly_set_nmod_mpoly( fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t Actx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t Bctx) { slong i, N; FLINT_ASSERT(Actx->minfo->ord == Bctx->minfo->ord); FLINT_ASSERT(Actx->minfo->nvars == Bctx->minfo->nvars); fq_zech_mpoly_fit_length_reset_bits(A, B->length, B->bits, Actx); A->length = B->length; N = mpoly_words_per_exp(B->bits, Bctx->minfo); mpoly_copy_monomials(A->exps, B->exps, B->length, N); for (i = 0; i < B->length; i++) fq_zech_set_ui(A->coeffs + i, B->coeffs[i], Actx->fqctx); } flint-3.1.3/src/fq_zech_mpoly/init.c000066400000000000000000000033001461254215100173640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_init(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { flint_bitcnt_t bits = mpoly_fix_bits(MPOLY_MIN_BITS, ctx->minfo); A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void fq_zech_mpoly_init3(fq_zech_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(bits, ctx->minfo); FLINT_ASSERT((MPOLY_MIN_BITS <= bits && bits <= FLINT_BITS) || (bits % FLINT_BITS) == 0); if (alloc > 0) { slong i; A->coeffs = (fq_zech_struct *) flint_malloc(alloc*sizeof(fq_zech_struct)); A->exps = (ulong *) flint_malloc(alloc*N*sizeof(ulong)); for (i = 0; i < alloc; i++) fq_zech_init(A->coeffs + i, ctx->fqctx); A->alloc = alloc; } else { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; } A->length = 0; A->bits = bits; } void fq_zech_mpoly_init2(fq_zech_mpoly_t A, slong alloc, const fq_zech_mpoly_ctx_t ctx) { flint_bitcnt_t bits = mpoly_fix_bits(MPOLY_MIN_BITS, ctx->minfo); fq_zech_mpoly_init3(A, alloc, bits, ctx); } flint-3.1.3/src/fq_zech_mpoly/io.c000066400000000000000000000052041461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" /* printing *******************************************************************/ int fq_zech_mpoly_fprint_pretty(FILE * file, const fq_zech_mpoly_t A, const char ** x_in, const fq_zech_mpoly_ctx_t ctx) { slong len = A->length; ulong * exp = A->exps; slong bits = A->bits; slong i, j, N; fmpz * exponents; int r = 0; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { r = (EOF != fputc('0', file)); return r; } #define CHECK_r if (r <= 0) goto done; N = mpoly_words_per_exp(bits, ctx->minfo); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(ctx->minfo->nvars*sizeof(char *)); for (i = 0; i < ctx->minfo->nvars; i++) { x[i] = (char *) TMP_ALLOC(((FLINT_BITS+4)/3)*sizeof(char)); flint_sprintf(x[i], "x%wd", i+1); } } exponents = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(ulong)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(exponents + i); for (i = 0; i < len; i++) { if (i > 0) { r = flint_fprintf(file, " + "); CHECK_r } r = flint_fprintf(file, "("); CHECK_r r = fq_zech_fprint_pretty(file, A->coeffs + i, ctx->fqctx); CHECK_r r = flint_fprintf(file, ")"); CHECK_r mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, ctx->minfo); for (j = 0; j < ctx->minfo->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, 1); if (cmp > 0) { r = flint_fprintf(file, "*%s^", x[j]); CHECK_r r = fmpz_fprint(file, exponents + j); CHECK_r } else if (cmp == 0) { r = flint_fprintf(file, "*%s", x[j]); CHECK_r } } } done: for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(exponents + i); TMP_END; return r; } int fq_zech_mpoly_print_pretty(const fq_zech_mpoly_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx) { return fq_zech_mpoly_fprint_pretty(stdout, A, x, ctx); } flint-3.1.3/src/fq_zech_mpoly/is_canonical.c000066400000000000000000000034361461254215100210550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_is_canonical(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { if (fq_zech_is_zero(A->coeffs + i, ctx->fqctx)) return 0; } return 1; } void fq_zech_mpoly_assert_canonical(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents out of order"); for (i = 0; i < A->length; i++) { if (fq_zech_is_zero(A->coeffs + i, ctx->fqctx)) flint_throw(FLINT_ERROR, "Polynomial has a zero coefficient"); } } flint-3.1.3/src/fq_zech_mpoly/is_fq_zech.c000066400000000000000000000013761461254215100205460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_is_fq_zech(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong N; if (A->length > 1) return 0; if (A->length < 1) return 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } flint-3.1.3/src/fq_zech_mpoly/is_one.c000066400000000000000000000013751461254215100177070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_is_one(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong N; if (A->length != 1) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return fq_zech_is_one(A->coeffs + 0, ctx->fqctx); } flint-3.1.3/src/fq_zech_mpoly/lead_coeff_vars.c000066400000000000000000000040501461254215100215260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" #include "fq_zech_mpoly_factor.h" /* leading coefficient wrt gen(0), ..., gen(num_vars-1) c will be returned with c->bits == A->bits */ void fq_zech_mpolyl_lead_coeff( fq_zech_mpoly_t c, const fq_zech_mpoly_t A, slong num_vars, const fq_zech_mpoly_ctx_t ctx) { slong i, j, off, shift; ulong old_shift, new_shift; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; ulong * cexps; slong Alen = A->length; FLINT_ASSERT(c != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); i = 0; old_shift = (Aexps + N*i)[off] >> shift; for (i = 1; i < Alen; old_shift = new_shift, i++) { new_shift = (Aexps + N*i)[off] >> shift; if (new_shift != old_shift) break; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) break; } fq_zech_mpoly_fit_length_reset_bits(c, i, A->bits, ctx); c->length = i; cexps = c->exps; for (i = 0; i < c->length; i++) fq_zech_set(c->coeffs + i, A->coeffs + i, ctx->fqctx); for (i = 0; i < c->length; i++) { for (j = 0; j < off; j++) (cexps + N*i)[j] = (Aexps + N*i)[j]; (cexps + N*i)[off] = ((-UWORD(1)) >> (FLINT_BITS - shift)) & (Aexps + N*i)[off]; for (j = off + 1; j < N; j++) (cexps + N*i)[j] = 0; } } flint-3.1.3/src/fq_zech_mpoly/make_monic.c000066400000000000000000000015711461254215100205330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_make_monic(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { fq_zech_t c; if (B->length == 0) { flint_throw(FLINT_ERROR, "Zero polynomial in fq_zech_mpoly_make_monic"); } fq_zech_init(c, ctx->fqctx); fq_zech_inv(c, B->coeffs + 0, ctx->fqctx); fq_zech_mpoly_scalar_mul_fq_zech(A, B, c, ctx); fq_zech_clear(c, ctx->fqctx); } flint-3.1.3/src/fq_zech_mpoly/mpolyu.c000066400000000000000000000110451461254215100177530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" int fq_zech_mpolyu_is_canonical(const fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->length; i++) { if ((slong)(A->exps[i]) < 0) { return 0; } if (i > 0 && A->exps[i - 1] <= A->exps[i]) { return 0; } if (!fq_zech_mpoly_is_canonical(A->coeffs + i, ctx)) { return 0; } if (fq_zech_mpoly_is_zero(A->coeffs + i, ctx)) { return 0; } } return 1; } void fq_zech_mpolyu_init(fq_zech_mpolyu_t A, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void fq_zech_mpolyu_clear(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx) { slong i; for (i = 0; i < A->alloc; i++) fq_zech_mpoly_clear(A->coeffs + i, uctx); flint_free(A->coeffs); flint_free(A->exps); } void fq_zech_mpolyu_swap(fq_zech_mpolyu_t A, fq_zech_mpolyu_t B) { fq_zech_mpolyu_struct t = *A; *A = *B; *B = t; } void fq_zech_mpolyu_zero(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx) { slong i; for (i = 0; i < A->alloc; i++) { fq_zech_mpoly_clear(A->coeffs + i, uctx); fq_zech_mpoly_init(A->coeffs + i, uctx); } A->length = 0; } int fq_zech_mpolyu_is_one(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx) { if (A->length != 1 || A->exps[0] != UWORD(0)) return 0; return fq_zech_mpoly_is_one(A->coeffs + 0, uctx); } void fq_zech_mpolyu_print_pretty(const fq_zech_mpolyu_t poly, const char ** x, const fq_zech_mpoly_ctx_t ctx) { slong i; if (poly->length == 0) flint_printf("0"); for (i = 0; i < poly->length; i++) { if (i != 0) flint_printf(" + "); flint_printf("("); fq_zech_mpoly_print_pretty(poly->coeffs + i,x,ctx); flint_printf(")*X^%wd",poly->exps[i]); } } void fq_zech_mpolyu_fit_length(fq_zech_mpolyu_t A, slong length, const fq_zech_mpoly_ctx_t uctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { if (old_alloc == 0) { A->exps = (ulong *) flint_malloc(new_alloc*sizeof(ulong)); A->coeffs = (fq_zech_mpoly_struct *) flint_malloc( new_alloc*sizeof(fq_zech_mpoly_struct)); } else { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (fq_zech_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_zech_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) { fq_zech_mpoly_init(A->coeffs + i, uctx); fq_zech_mpoly_fit_bits(A->coeffs + i, A->bits, uctx); (A->coeffs + i)->bits = A->bits; } A->alloc = new_alloc; } } void fq_zech_mpolyu_one(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx) { fq_zech_mpolyu_fit_length(A, 1, uctx); A->exps[0] = 0; fq_zech_mpoly_one(A->coeffs + 0, uctx); A->length = 1; } /* if the coefficient doesn't exist, a new one is created (and set to zero) */ fq_zech_mpoly_struct * _fq_zech_mpolyu_get_coeff(fq_zech_mpolyu_t A, ulong pow, const fq_zech_mpoly_ctx_t uctx) { slong i, j; fq_zech_mpoly_struct * xk; for (i = 0; i < A->length && A->exps[i] >= pow; i++) { if (A->exps[i] == pow) { return A->coeffs + i; } } fq_zech_mpolyu_fit_length(A, A->length + 1, uctx); for (j = A->length; j > i; j--) { A->exps[j] = A->exps[j - 1]; fq_zech_mpoly_swap(A->coeffs + j, A->coeffs + j - 1, uctx); } A->length++; A->exps[i] = pow; xk = A->coeffs + i; xk->length = 0; FLINT_ASSERT(xk->bits == A->bits); return xk; } flint-3.1.3/src/fq_zech_mpoly/mul.c000066400000000000000000000011741461254215100172250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" void fq_zech_mpoly_mul(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t C, const fq_zech_mpoly_ctx_t ctx) { /* nothing fancy for now */ fq_zech_mpoly_mul_johnson(A, B, C, ctx); } flint-3.1.3/src/fq_zech_mpoly/mul_johnson.c000066400000000000000000000226151461254215100207660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" slong _fq_zech_mpoly_mul_johnson( fq_zech_struct ** coeff1, ulong ** exp1, slong * alloc, const fq_zech_struct * coeff2, const ulong * exp2, slong len2, const fq_zech_struct * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx) { slong i, j; slong next_loc; slong Q_len = 0, heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * Q; mpoly_heap_t * x; slong len1; fq_zech_struct * p1 = * coeff1; ulong * e1 = *exp1; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; fq_zech_t pp; TMP_INIT; TMP_START; fq_zech_init(pp, fqctx); next_loc = len2 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len2 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len2*sizeof(mpoly_heap_t)); Q = (slong *) TMP_ALLOC(2*len2*sizeof(slong)); exps = (ulong *) TMP_ALLOC(len2*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len2*sizeof(ulong *)); for (i = 0; i < len2; i++) exp_list[i] = exps + i*N; hind = (slong *) TMP_ALLOC(len2*sizeof(slong)); for (i = 0; i < len2; i++) hind[i] = 1; /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; if (bits <= FLINT_BITS) mpoly_monomial_add(heap[1].exp, exp2, exp3, N); else mpoly_monomial_add_mp(heap[1].exp, exp2, exp3, N); hind[0] = 2*1 + 0; len1 = 0; while (heap_len > 1) { exp = heap[1].exp; _fq_zech_mpoly_fit_length(&p1, &e1, alloc, len1 + 1, N, fqctx); mpoly_monomial_set(e1 + len1*N, exp, N); fq_zech_zero(p1 + len1, fqctx); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; fq_zech_mul(pp, coeff2 + x->i, coeff3 + x->j, fqctx); fq_zech_add(p1 + len1, p1 + len1, pp, fqctx); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; fq_zech_mul(pp, coeff2 + x->i, coeff3 + x->j, fqctx); fq_zech_add(p1 + len1, p1 + len1, pp, fqctx); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); len1 += !fq_zech_is_zero(p1 + len1, fqctx); while (Q_len > 0) { /* take node from store */ j = Q[--Q_len]; i = Q[--Q_len]; /* should we go right? */ if ( (i + 1 < len2) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, cmpmask)) exp_next--; } /* should we go up? */ if ( (j + 1 < len3) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, cmpmask)) exp_next--; } } } (* coeff1) = p1; (* exp1) = e1; TMP_END; fq_zech_clear(pp, fqctx); return len1; } void fq_zech_mpoly_mul_johnson( fq_zech_mpoly_t poly1, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx) { slong i, N, len1 = 0; flint_bitcnt_t exp_bits; fmpz * max_fields2, * max_fields3; ulong * cmpmask; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; int free2 = 0, free3 = 0; TMP_INIT; if (poly2->length == 0 || poly3->length == 0) { fq_zech_mpoly_zero(poly1, ctx); return; } TMP_START; max_fields2 = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields3 = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(max_fields2 + i); fmpz_init(max_fields3 + i); } mpoly_max_fields_fmpz(max_fields2, poly2->exps, poly2->length, poly2->bits, ctx->minfo); mpoly_max_fields_fmpz(max_fields3, poly3->exps, poly3->length, poly3->bits, ctx->minfo); _fmpz_vec_add(max_fields2, max_fields2, max_fields3, ctx->minfo->nfields); exp_bits = _fmpz_vec_max_bits(max_fields2, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = FLINT_MAX(exp_bits, poly2->bits); exp_bits = FLINT_MAX(exp_bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(max_fields2 + i); fmpz_clear(max_fields3 + i); } N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents are packed into same sized fields as output */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } /* deal with aliasing and do multiplication */ if (poly1 == poly2 || poly1 == poly3) { fq_zech_mpoly_t temp; fq_zech_mpoly_init(temp, ctx); fq_zech_mpoly_fit_length_reset_bits(temp, poly2->length + poly3->length, exp_bits, ctx); if (poly2->length >= poly3->length) { len1 = _fq_zech_mpoly_mul_johnson(&temp->coeffs, &temp->exps, &temp->alloc, poly3->coeffs, exp3, poly3->length, poly2->coeffs, exp2, poly2->length, exp_bits, N, cmpmask, ctx->fqctx); } else { len1 = _fq_zech_mpoly_mul_johnson(&temp->coeffs, &temp->exps, &temp->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask, ctx->fqctx); } fq_zech_mpoly_swap(temp, poly1, ctx); fq_zech_mpoly_clear(temp, ctx); } else { fq_zech_mpoly_fit_length_reset_bits(poly1, poly2->length + poly3->length, exp_bits, ctx); if (poly2->length > poly3->length) { len1 = _fq_zech_mpoly_mul_johnson(&poly1->coeffs, &poly1->exps, &poly1->alloc, poly3->coeffs, exp3, poly3->length, poly2->coeffs, exp2, poly2->length, exp_bits, N, cmpmask, ctx->fqctx); } else { len1 = _fq_zech_mpoly_mul_johnson(&poly1->coeffs, &poly1->exps, &poly1->alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask, ctx->fqctx); } } if (free2) flint_free(exp2); if (free3) flint_free(exp3); _fq_zech_mpoly_set_length(poly1, len1, ctx); TMP_END; } flint-3.1.3/src/fq_zech_mpoly/neg.c000066400000000000000000000025651461254215100172060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void _fq_zech_mpoly_neg(fq_zech_struct * Acoeff, ulong * Aexp, const fq_zech_struct * Bcoeff, const ulong * Bexp, slong Blen, slong N, const fq_zech_ctx_t fqctx) { slong i; for (i = 0; i < Blen; i++) fq_zech_neg(Acoeff + i, Bcoeff + i, fqctx); if (Aexp != Bexp) { mpoly_copy_monomials(Aexp, Bexp, Blen, N); } } void fq_zech_mpoly_neg(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { slong N; fq_zech_mpoly_fit_length(A, B->length, ctx); fq_zech_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; N = mpoly_words_per_exp(B->bits, ctx->minfo); _fq_zech_mpoly_neg(A->coeffs, A->exps, B->coeffs, B->exps, B->length, N, ctx->fqctx); _fq_zech_mpoly_set_length(A, B->length, ctx); } flint-3.1.3/src/fq_zech_mpoly/pow_rmul.c000066400000000000000000000016741461254215100203010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" void fq_zech_mpoly_pow_rmul(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, ulong k, const fq_zech_mpoly_ctx_t ctx) { fq_zech_mpoly_t T; fq_zech_mpoly_init(T, ctx); if (A == B) { fq_zech_mpoly_pow_rmul(T, A, k, ctx); fq_zech_mpoly_swap(T, A, ctx); goto cleanup; } fq_zech_mpoly_one(A, ctx); while (k > 0) { fq_zech_mpoly_mul(T, A, B, ctx); fq_zech_mpoly_swap(A, T, ctx); k -= 1; } cleanup: fq_zech_mpoly_clear(T, ctx); } flint-3.1.3/src/fq_zech_mpoly/pow_ui.c000066400000000000000000000037671461254215100177440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_pow_ui(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, ulong k, const fq_zech_mpoly_ctx_t ctx) { slong i, exp_bits; fmpz * maxBfields; TMP_INIT; if (k == 0) { fq_zech_mpoly_one(A, ctx); return 1; } if (B->length == 0) { fq_zech_mpoly_zero(A, ctx); return 1; } if (k == 1) { fq_zech_mpoly_set(A, B, ctx); return 1; } if (k == 2) { fq_zech_mpoly_mul(A, B, B, ctx); return 1; } if (B->length != 1) { fq_zech_mpoly_pow_rmul(A, B, k, ctx); return 1; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_ui(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); fq_zech_mpoly_fit_length_reset_bits(A, 1, exp_bits, ctx); fq_zech_pow_ui(A->coeffs + 0, B->coeffs + 0, k, ctx->fqctx); mpoly_pack_vec_fmpz(A->exps + 0, maxBfields, exp_bits, ctx->minfo->nfields, 1); A->length = !fq_zech_is_zero(A->coeffs + 0, ctx->fqctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/fq_zech_mpoly/repack_bits.c000066400000000000000000000044271461254215100207220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_repack_bits(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, flint_bitcnt_t Abits, const fq_zech_mpoly_ctx_t ctx) { slong i; int success; fq_zech_mpoly_t T; Abits = mpoly_fix_bits(Abits, ctx->minfo); if (B->bits == Abits || B->length == 0) { fq_zech_mpoly_set(A, B, ctx); return 1; } /* must use B->alloc because we are going to swap coeff in aliasing case */ fq_zech_mpoly_init3(T, B->alloc, Abits, ctx); success = mpoly_repack_monomials(T->exps, Abits, B->exps, B->bits, B->length, ctx->minfo); if (success) { if (A == B) { fq_zech_struct * temp = A->coeffs; A->coeffs = T->coeffs; T->coeffs = temp; } else { for (i = 0; i < B->length; i++) { fq_zech_set(T->coeffs + i, B->coeffs + i, ctx->fqctx); } } _fq_zech_mpoly_set_length(T, B->length, ctx); fq_zech_mpoly_swap(A, T, ctx); } fq_zech_mpoly_clear(T, ctx); return success; } int fq_zech_mpoly_repack_bits_inplace( fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_mpoly_ctx_t ctx) { int success; ulong * texps; slong N = mpoly_words_per_exp(Abits, ctx->minfo); if (A->bits == Abits) { return 1; } if (A->alloc < 1) { A->bits = Abits; return 1; } texps = (ulong *) flint_malloc(A->alloc*N*sizeof(ulong)); success = mpoly_repack_monomials(texps, Abits, A->exps, A->bits, A->length, ctx->minfo); if (success) { ulong * t = A->exps; A->exps = texps; texps = t; A->bits = Abits; } flint_free(texps); return success; } flint-3.1.3/src/fq_zech_mpoly/scalar.c000066400000000000000000000123041461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" static slong _fq_zech_mpoly_scalar_addmul_fq_zech( fq_zech_struct * Acoeffs, ulong * Aexps, fq_zech_struct * Bcoeffs, const ulong * Bexps, slong Blen, fq_zech_struct * Ccoeffs, const ulong * Cexps, slong Clen, const fq_zech_t d, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx) { slong i = 0, j = 0, k = 0; fq_zech_t p; FLINT_ASSERT(!fq_zech_is_zero(d, fqctx)); fq_zech_init(p, fqctx); while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fq_zech_set(Acoeffs + k, Bcoeffs + i, fqctx); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fq_zech_mul(p, Ccoeffs + j, d, fqctx); fq_zech_add(Acoeffs + k, Bcoeffs + i, p, fqctx); k += !fq_zech_is_zero(Acoeffs + k, fqctx); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fq_zech_mul(Acoeffs + k, Ccoeffs + j, d, fqctx); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); fq_zech_set(Acoeffs + k, Bcoeffs + i, fqctx); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); fq_zech_mul(Acoeffs + k, Ccoeffs + j, d, fqctx); j++; k++; } fq_zech_clear(p, fqctx); return k; } void fq_zech_mpoly_scalar_addmul_fq_zech( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t C, const fq_zech_t d, const fq_zech_mpoly_ctx_t ctx) { flint_bitcnt_t Abits; slong N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (fq_zech_mpoly_is_zero(B, ctx)) { fq_zech_mpoly_scalar_mul_fq_zech(A, C, d, ctx); return; } else if (fq_zech_mpoly_is_zero(C, ctx) || fq_zech_is_zero(d, ctx->fqctx)) { fq_zech_mpoly_set(A, B, ctx); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { fq_zech_mpoly_t T; fq_zech_mpoly_init3(T, B->length + C->length, Abits, ctx); T->length = _fq_zech_mpoly_scalar_addmul_fq_zech(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, d, N, cmpmask, ctx->fqctx); fq_zech_mpoly_swap(A, T, ctx); fq_zech_mpoly_clear(T, ctx); } else { fq_zech_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _fq_zech_mpoly_scalar_addmul_fq_zech(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, d, N, cmpmask, ctx->fqctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } void fq_zech_mpoly_scalar_mul_fq_zech( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx) { slong i, N; if (fq_zech_is_zero(c, ctx->fqctx)) { fq_zech_mpoly_zero(A, ctx); return; } if (A == B) { if (fq_zech_is_one(c, ctx->fqctx)) return; } else { fq_zech_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); A->length = B->length; N = mpoly_words_per_exp(B->bits, ctx->minfo); mpoly_copy_monomials(A->exps, B->exps, B->length, N); if (fq_zech_is_one(c, ctx->fqctx)) { for (i = 0; i < B->length; i++) fq_zech_set(A->coeffs + i, B->coeffs + i, ctx->fqctx); return; } } for (i = 0; i < B->length; i++) fq_zech_mul(A->coeffs + i, B->coeffs + i, c, ctx->fqctx); } flint-3.1.3/src/fq_zech_mpoly/set.c000066400000000000000000000025611461254215100172240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void _fq_zech_mpoly_set(fq_zech_struct * coeff1, ulong * exps1, const fq_zech_struct * coeff2, const ulong * exps2, slong len2, slong N, const fq_zech_ctx_t fqctx) { slong i; if (coeff1 != coeff2) { for (i = 0; i < len2; i++) fq_zech_set(coeff1 + i, coeff2 + i, fqctx); } if (exps1 != exps2) { mpoly_copy_monomials(exps1, exps2, len2, N); } } void fq_zech_mpoly_set(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx) { slong N; N = mpoly_words_per_exp(B->bits, ctx->minfo); fq_zech_mpoly_fit_length(A, B->length, ctx); fq_zech_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; _fq_zech_mpoly_set(A->coeffs, A->exps, B->coeffs, B->exps, B->length, N, ctx->fqctx); A->length = B->length; } flint-3.1.3/src/fq_zech_mpoly/set_fq_zech.c000066400000000000000000000016251461254215100207230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_set_fq_zech(fq_zech_mpoly_t A, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (fq_zech_is_zero(c, ctx->fqctx)) { fq_zech_mpoly_zero(A, ctx); return; } fq_zech_mpoly_fit_length(A, 1, ctx); fq_zech_set(A->coeffs + 0, c, ctx->fqctx); mpoly_monomial_zero(A->exps + N*0, N); _fq_zech_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/fq_zech_mpoly/set_ui.c000066400000000000000000000016361461254215100177230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_set_ui(fq_zech_mpoly_t A, ulong c, const fq_zech_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t bits = mpoly_fix_bits(MPOLY_MIN_BITS, ctx->minfo); fq_zech_mpoly_fit_length_reset_bits(A, 1, bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); fq_zech_set_ui(A->coeffs + 0, c, ctx->fqctx); mpoly_monomial_zero(A->exps, N); A->length = !fq_zech_is_zero(A->coeffs + 0, ctx->fqctx); } flint-3.1.3/src/fq_zech_mpoly/sort_terms.c000066400000000000000000000126761461254215100206420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" /* sort terms in [left, right) by exponent assuming that bits in position >= pos are already sorted and assuming exponent vectors fit into one word and assuming that all bit positions that need to be sorted are in totalmask */ void _fq_zech_mpoly_radix_sort1(fq_zech_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask) { ulong mask, cmp; slong mid, cur; while (pos > 0) { pos--; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < FLINT_BITS); mask = UWORD(1) << pos; cmp = cmpmask & mask; /* insertion base case */ if (right - left < 20) { slong i, j; for (i = left + 1; i < right; i++) { for (j = i; j > left && mpoly_monomial_gt1(A->exps[j], A->exps[j - 1], cmpmask); j--) { fq_zech_swap(A->coeffs + j, A->coeffs + j - 1, NULL); FLINT_SWAP(ulong, A->exps[j], A->exps[j - 1]); } } return; } /* return if there is no information to sort on this bit */ if ((totalmask & mask) == 0) continue; /* find first 'zero' */ mid = left; while (mid < right && (A->exps[mid] & mask) != cmp) mid++; /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ cur = mid; while (++cur < right) { if ((A->exps[cur] & mask) != cmp) { fq_zech_swap(A->coeffs + cur, A->coeffs + mid, NULL); FLINT_SWAP(ulong, A->exps[cur], A->exps[mid]); mid++; } } if (mid - left < right - mid) { _fq_zech_mpoly_radix_sort1(A, left, mid, pos, cmpmask, totalmask); left = mid; } else { _fq_zech_mpoly_radix_sort1(A, mid, right, pos, cmpmask, totalmask); right = mid; } } } /* sort terms in [left, right) by exponent assuming that bits in position > pos are already sorted */ void _fq_zech_mpoly_radix_sort(fq_zech_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask) { ulong off, bit, mask, cmp; slong mid, check; while (pos > 0) { pos--; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < N*FLINT_BITS); off = pos/FLINT_BITS; bit = pos%FLINT_BITS; mask = UWORD(1) << bit; cmp = cmpmask[off] & mask; /* insertion base case */ if (right - left < 10) { slong i, j; for (i = left + 1; i < right; i++) { for (j = i; j > left && mpoly_monomial_gt(A->exps + N*j, A->exps + N*(j - 1), N, cmpmask); j--) { fq_zech_swap(A->coeffs + j, A->coeffs + j - 1, NULL); mpoly_monomial_swap(A->exps + N*j, A->exps + N*(j - 1), N); } } return; } /* find first 'zero' */ mid = left; while (mid < right && ((A->exps+N*mid)[off] & mask) != cmp) mid++; /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ check = mid; while (++check < right) { if (((A->exps + N*check)[off] & mask) != cmp) { fq_zech_swap(A->coeffs + check, A->coeffs + mid, NULL); mpoly_monomial_swap(A->exps + N*check, A->exps + N*mid, N); mid++; } } FLINT_ASSERT(left <= mid && mid <= right); if (mid - left < right - mid) { _fq_zech_mpoly_radix_sort(A, left, mid, pos, N, cmpmask); left = mid; } else { _fq_zech_mpoly_radix_sort(A, mid, right, pos, N, cmpmask); right = mid; } } } /* sort the terms in A by exponent assuming that the exponents are valid (other than being in order) */ void fq_zech_mpoly_sort_terms(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t pos; ulong himask, * ptempexp; TMP_INIT; TMP_START; N = mpoly_words_per_exp(A->bits, ctx->minfo); ptempexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(ptempexp, N, A->bits, ctx->minfo); himask = 0; for (i = 0; i < A->length; i++) himask |= (A->exps + N*i)[N - 1]; pos = FLINT_BIT_COUNT(himask); if (N == 1) _fq_zech_mpoly_radix_sort1(A, 0, A->length, pos, ptempexp[0], himask); else _fq_zech_mpoly_radix_sort(A, 0, A->length, (N - 1)*FLINT_BITS + pos, N, ptempexp); TMP_END; } flint-3.1.3/src/fq_zech_mpoly/sub.c000066400000000000000000000103501461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" slong _fq_zech_mpoly_sub(fq_zech_struct * coeff1, ulong * exp1, fq_zech_struct * coeff2, const ulong * exp2, slong len2, fq_zech_struct * coeff3, const ulong * exp3, slong len3, slong N, const ulong * cmpmask, const fq_zech_ctx_t fqctx) { slong i = 0, j = 0, k = 0; while (i < len2 && j < len3) { int cmp = mpoly_monomial_cmp(exp2 + i*N, exp3 + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(exp1 + k*N, exp2 + i*N, N); fq_zech_set(coeff1 + k, coeff2 + i, fqctx); i++; } else if (cmp == 0) { mpoly_monomial_set(exp1 + k*N, exp2 + i*N, N); fq_zech_sub(coeff1 + k, coeff2 + i, coeff3 + j, fqctx); k -= fq_zech_is_zero(coeff1 + k, fqctx); i++; j++; } else { mpoly_monomial_set(exp1 + k*N, exp3 + j*N, N); fq_zech_neg(coeff1 + k, coeff3 + j, fqctx); j++; } k++; } while (i < len2) { mpoly_monomial_set(exp1 + k*N, exp2 + i*N, N); fq_zech_set(coeff1 + k, coeff2 + i, fqctx); i++; k++; } while (j < len3) { mpoly_monomial_set(exp1 + k*N, exp3 + j*N, N); fq_zech_neg(coeff1 + k, coeff3 + j, fqctx); j++; k++; } return k; } void fq_zech_mpoly_sub(fq_zech_mpoly_t poly1, const fq_zech_mpoly_t poly2, const fq_zech_mpoly_t poly3, const fq_zech_mpoly_ctx_t ctx) { slong len1 = 0, max_bits, N; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; ulong * cmpmask; int free2 = 0, free3 = 0; TMP_INIT; max_bits = FLINT_MAX(poly2->bits, poly3->bits); N = mpoly_words_per_exp(max_bits, ctx->minfo); if (poly2->length == 0) { fq_zech_mpoly_neg(poly1, poly3, ctx); return; } else if (poly3->length == 0) { fq_zech_mpoly_set(poly1, poly2, ctx); return; } TMP_START; cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, max_bits, ctx->minfo); if (max_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, max_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (max_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, max_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } if (poly1 == poly2 || poly1 == poly3) { fq_zech_mpoly_t temp; fq_zech_mpoly_init2(temp, poly2->length + poly3->length, ctx); fq_zech_mpoly_fit_bits(temp, max_bits, ctx); temp->bits = max_bits; len1 = _fq_zech_mpoly_sub(temp->coeffs, temp->exps, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, N, cmpmask, ctx->fqctx); fq_zech_mpoly_swap(temp, poly1, ctx); fq_zech_mpoly_clear(temp, ctx); } else { fq_zech_mpoly_fit_length(poly1, poly2->length + poly3->length, ctx); fq_zech_mpoly_fit_bits(poly1, max_bits, ctx); poly1->bits = max_bits; len1 = _fq_zech_mpoly_sub(poly1->coeffs, poly1->exps, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, N, cmpmask, ctx->fqctx); } if (free2) flint_free(exp2); if (free3) flint_free(exp3); _fq_zech_mpoly_set_length(poly1, len1, ctx); TMP_END; } flint-3.1.3/src/fq_zech_mpoly/sub_fq_zech.c000066400000000000000000000042671461254215100207260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_sub_fq_zech(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx) { slong i, N; slong Blen = B->length; if (fq_zech_is_zero(c, ctx->fqctx)) { fq_zech_mpoly_set(A, B, ctx); return; } if (Blen == 0) { fq_zech_mpoly_set_fq_zech(A, c, ctx); FLINT_ASSERT(A->length > 0); fq_zech_neg(A->coeffs + 0, A->coeffs + 0, ctx->fqctx); return; } N = mpoly_words_per_exp(B->bits, ctx->minfo); if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { fq_zech_mpoly_fit_length(A, B->length, ctx); fq_zech_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; for (i = 0; i < Blen - 1; i++) fq_zech_set(A->coeffs + i, B->coeffs + i, ctx->fqctx); mpoly_copy_monomials(A->exps, B->exps, Blen, N); _fq_zech_mpoly_set_length(A, B->length, ctx); } fq_zech_sub(A->coeffs + Blen - 1, B->coeffs + Blen - 1, c, ctx->fqctx); if (fq_zech_is_zero(A->coeffs + Blen - 1, ctx->fqctx)) _fq_zech_mpoly_set_length(A, Blen - 1, ctx); } else { fq_zech_mpoly_fit_length(A, Blen + 1, ctx); if (A != B) { fq_zech_mpoly_fit_bits(A, B->bits, ctx); A->bits = B->bits; for (i = 0; i < Blen; i++) fq_zech_set(A->coeffs + i, B->coeffs + i, ctx->fqctx); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } mpoly_monomial_zero(A->exps + N*Blen, N); fq_zech_neg(A->coeffs + Blen, c, ctx->fqctx); _fq_zech_mpoly_set_length(A, B->length + 1, ctx); } } flint-3.1.3/src/fq_zech_mpoly/term_exp_fits.c000066400000000000000000000015461461254215100213030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_zech_mpoly.h" int fq_zech_mpoly_term_exp_fits_ui(const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_ui(A->exps, A->bits, i, ctx->minfo); } int fq_zech_mpoly_term_exp_fits_si(const fq_zech_mpoly_t A, slong i, const fq_zech_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_si(A->exps, A->bits, i, ctx->minfo); } flint-3.1.3/src/fq_zech_mpoly/univar.c000066400000000000000000000356711461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly.h" void fq_zech_mpoly_univar_init(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; } void fq_zech_mpoly_univar_clear(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; for (i = A->alloc - 1; i >= 0; i--) { fq_zech_mpoly_clear(A->coeffs + i, ctx); fmpz_clear(A->exps + i); } if (A->coeffs) flint_free(A->coeffs); if (A->exps) flint_free(A->exps); } void fq_zech_mpoly_univar_fit_length(fq_zech_mpoly_univar_t A, slong length, const fq_zech_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { if (old_alloc == 0) { A->exps = (fmpz *) flint_malloc(new_alloc*sizeof(fmpz)); A->coeffs = (fq_zech_mpoly_struct *) flint_malloc( new_alloc*sizeof(fq_zech_mpoly_struct)); } else { A->exps = (fmpz *) flint_realloc(A->exps, new_alloc*sizeof(fmpz)); A->coeffs = (fq_zech_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_zech_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) { fmpz_init(A->exps + i); fq_zech_mpoly_init(A->coeffs + i, ctx); } A->alloc = new_alloc; } } int fq_zech_mpoly_univar_degree_fits_si(const fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx) { return A->length == 0 || fmpz_fits_si(A->exps + 0); } slong fq_zech_mpoly_univar_get_term_exp_si(fq_zech_mpoly_univar_t A, slong i, const fq_zech_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); return fmpz_get_si(A->exps + i); } void fq_zech_mpoly_univar_assert_canonical(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; for (i = 0; i + 1 < A->length; i++) { if (fmpz_cmp(A->exps + i, A->exps + i + 1) <= 0 || fmpz_sgn(A->exps + i) < 0 || fmpz_sgn(A->exps + i + 1) < 0) { flint_throw(FLINT_ERROR, "Univariate polynomial exponents out of order"); } } for (i = 0; i < A->length; i++) fq_zech_mpoly_assert_canonical(A->coeffs + i, ctx); } void fq_zech_mpoly_univar_print_pretty(const fq_zech_mpoly_univar_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx) { slong i; if (A->length == 0) flint_printf("0"); for (i = 0; i < A->length; i++) { if (i != 0) flint_printf("+"); flint_printf("("); fq_zech_mpoly_print_pretty(A->coeffs + i,x,ctx); flint_printf(")*X^"); fmpz_print(A->exps + i); } } static void _tree_data_clear_sp( fq_zech_mpoly_univar_t A, mpoly_rbtree_ui_t tree, slong idx, const fq_zech_mpoly_ctx_t ctx) { mpoly_rbnode_ui_struct * nodes = tree->nodes + 2; fq_zech_mpoly_struct * data = (fq_zech_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_sp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set_ui(A->exps + A->length, nodes[idx].key); fq_zech_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fq_zech_mpoly_clear(data + idx, ctx); _tree_data_clear_sp(A, tree, nodes[idx].left, ctx); } static void _tree_data_clear_mp( fq_zech_mpoly_univar_t A, mpoly_rbtree_fmpz_t tree, slong idx, const fq_zech_mpoly_ctx_t ctx) { mpoly_rbnode_fmpz_struct * nodes = tree->nodes + 2; fq_zech_mpoly_struct * data = (fq_zech_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_mp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set(A->exps + A->length, nodes[idx].key); fq_zech_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; fq_zech_mpoly_clear(data + idx, ctx); _tree_data_clear_mp(A, tree, nodes[idx].left, ctx); } /* the coefficients of A should be constructed with the same bits as B */ void fq_zech_mpoly_to_univar(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_mpoly_ctx_t ctx) { flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong shift, off; slong Blen = B->length; const fq_zech_struct * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; slong i; int its_new; ulong * one; #define LUT_limit (48) fq_zech_mpoly_struct LUT[LUT_limit]; if (B->length == 0) { A->length = 0; return; } one = FLINT_ARRAY_ALLOC(N, ulong); if (bits <= FLINT_BITS) { slong Alen; mpoly_rbtree_ui_t tree; fq_zech_mpoly_struct * d; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); mpoly_rbtree_ui_init(tree, sizeof(fq_zech_mpoly_struct)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); for (i = 0; i < LUT_limit; i++) fq_zech_mpoly_init3(LUT + i, 4, bits, ctx); /* fill in tree/LUT from B */ for (i = 0; i < Blen; i++) { ulong k = (Bexp[N*i + off] >> shift) & mask; if (k < LUT_limit) { d = LUT + k; } else { d = mpoly_rbtree_ui_lookup(tree, &its_new, k); if (its_new) fq_zech_mpoly_init3(d, 4, bits, ctx); } fq_zech_mpoly_fit_length(d, d->length + 1, ctx); fq_zech_set(d->coeffs + d->length, Bcoeff + i, ctx->fqctx); mpoly_monomial_msub(d->exps + N*d->length, Bexp + N*i, k, one, N); d->length++; } /* clear out tree to A */ Alen = tree->length; for (i = LUT_limit - 1; i >= 0; i--) Alen += (LUT[i].length > 0); fq_zech_mpoly_univar_fit_length(A, Alen, ctx); A->length = 0; _tree_data_clear_sp(A, tree, mpoly_rbtree_ui_head(tree), ctx); for (i = LUT_limit - 1; i >= 0; i--) { d = LUT + i; if (d->length > 0) { FLINT_ASSERT(A->length < A->alloc); fmpz_set_si(A->exps + A->length, i); fq_zech_mpoly_swap(A->coeffs + A->length, d, ctx); A->length++; } fq_zech_mpoly_clear(d, ctx); } mpoly_rbtree_ui_clear(tree); } else { mpoly_rbtree_fmpz_t tree; fq_zech_mpoly_struct * d; fmpz_t k; fmpz_init(k); mpoly_rbtree_fmpz_init(tree, sizeof(fq_zech_mpoly_struct)); off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); /* fill in tree from B */ for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexp + N*i + off, bits/FLINT_BITS); d = mpoly_rbtree_fmpz_lookup(tree, &its_new, k); if (its_new) fq_zech_mpoly_init3(d, 4, bits, ctx); fq_zech_mpoly_fit_length(d, d->length + 1, ctx); fq_zech_set(d->coeffs + d->length, Bcoeff + i, ctx->fqctx); mpoly_monomial_msub_ui_array(d->exps + N*d->length, Bexp + N*i, Bexp + N*i + off, bits/FLINT_BITS, one, N); d->length++; } /* clear out tree to A */ fq_zech_mpoly_univar_fit_length(A, tree->length, ctx); A->length = 0; _tree_data_clear_mp(A, tree, mpoly_rbtree_fmpz_head(tree), ctx); fmpz_clear(k); mpoly_rbtree_fmpz_clear(tree); } flint_free(one); } /* Currently this function does not work if the coefficients depend on "var". The assertion x->next == NULL would need to be replaced by a loop. Other asserts would need to be removed as well. */ void fq_zech_mpoly_from_univar_bits(fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_mpoly_univar_t B, slong var, const fq_zech_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i; slong next_loc, heap_len = 1; ulong * cmpmask; slong total_len; mpoly_heap_s * heap; slong Alen; ulong ** Btexp; ulong * exp; ulong * one; mpoly_heap_t * chain, * x; TMP_INIT; if (B->length == 0) { fq_zech_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; A->length = 0; return; } TMP_START; /* pack everything into Abits */ one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); Btexp = (ulong **) TMP_ALLOC(B->length*sizeof(ulong*)); total_len = 0; for (i = 0; i < B->length; i++) { fq_zech_mpoly_struct * Bi = B->coeffs + i; total_len += Bi->length; Btexp[i] = Bi->exps; if (Abits != Bi->bits) { Btexp[i] = (ulong *) flint_malloc(N*Bi->length*sizeof(ulong)); if (!mpoly_repack_monomials(Btexp[i], Abits, Bi->exps, Bi->bits, Bi->length, ctx->minfo)) { FLINT_ASSERT(0 && "repack does not fit"); } } } fq_zech_mpoly_fit_length(A, total_len, ctx); fq_zech_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; next_loc = B->length + 2; heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); exp = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); Alen = 0; if (Abits <= FLINT_BITS) { mpoly_gen_monomial_sp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { FLINT_ASSERT(fmpz_fits_si(B->exps + i)); x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + i), one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fq_zech_set(A->coeffs + Alen, (B->coeffs + x->i)->coeffs + x->j, ctx->fqctx); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { FLINT_ASSERT(fmpz_fits_si(B->exps + x->i)); x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + x->i), one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } else { mpoly_gen_monomial_offset_mp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + i, one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); fq_zech_set(A->coeffs + Alen, (B->coeffs + x->i)->coeffs + x->j, ctx->fqctx); Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + x->i, one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } A->length = Alen; for (i = 0; i < B->length; i++) { if (Btexp[i] != (B->coeffs + i)->exps) flint_free(Btexp[i]); } TMP_END; } void fq_zech_mpoly_from_univar(fq_zech_mpoly_t A, const fq_zech_mpoly_univar_t B, slong var, const fq_zech_mpoly_ctx_t ctx) { slong n = ctx->minfo->nfields; flint_bitcnt_t bits; slong i; fmpz * gen_fields, * tmp_fields, * max_fields; TMP_INIT; if (B->length == 0) { fq_zech_mpoly_zero(A, ctx); return; } TMP_START; /* find bits required to represent result */ gen_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); tmp_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(gen_fields + i); fmpz_init(tmp_fields + i); fmpz_init(max_fields + i); } mpoly_gen_fields_fmpz(gen_fields, var, ctx->minfo); for (i = 0; i < B->length; i++) { fq_zech_mpoly_struct * Bi = B->coeffs + i; mpoly_max_fields_fmpz(tmp_fields, Bi->exps, Bi->length, Bi->bits, ctx->minfo); _fmpz_vec_scalar_addmul_fmpz(tmp_fields, gen_fields, n, B->exps + i); _fmpz_vec_max_inplace(max_fields, tmp_fields, n); } bits = _fmpz_vec_max_bits(max_fields, n); bits = FLINT_MAX(MPOLY_MIN_BITS, bits + 1); bits = mpoly_fix_bits(bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(gen_fields + i); fmpz_clear(tmp_fields + i); fmpz_clear(max_fields + i); } TMP_END; fq_zech_mpoly_from_univar_bits(A, bits, B, var, ctx); } flint-3.1.3/src/fq_zech_mpoly_factor.h000066400000000000000000000470231461254215100177760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_MPOLY_FACTOR_H #define FQ_ZECH_MPOLY_FACTOR_H #ifdef FQ_ZECH_MPOLY_FACTOR_INLINES_C #define FQ_ZECH_MPOLY_FACTOR_INLINE #else #define FQ_ZECH_MPOLY_FACTOR_INLINE static inline #endif #include "fq_zech_mpoly.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fq_zech_poly_struct * coeffs; slong alloc; slong length; } fq_zech_bpoly_struct; typedef fq_zech_bpoly_struct fq_zech_bpoly_t[1]; typedef struct { fq_zech_bpoly_struct * coeffs; slong alloc; slong length; } fq_zech_tpoly_struct; typedef fq_zech_tpoly_struct fq_zech_tpoly_t[1]; typedef struct { ulong * exps; fq_zech_struct * coeffs; slong length; slong alloc; } fq_zech_polyu_struct; typedef fq_zech_polyu_struct fq_zech_polyu_t[1]; typedef struct { fq_zech_poly_struct * coeffs; ulong * exps; slong length; slong alloc; } fq_zech_polyun_struct; typedef fq_zech_polyun_struct fq_zech_polyun_t[1]; /*****************************************************************************/ FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_bpoly_init(fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } void fq_zech_bpoly_clear(fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_bpoly_swap(fq_zech_bpoly_t A, fq_zech_bpoly_t B, const fq_zech_ctx_t ctx) { fq_zech_bpoly_struct t = *A; *A = *B; *B = t; } void fq_zech_bpoly_normalise(fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); void fq_zech_bpoly_realloc(fq_zech_bpoly_t A, slong len, const fq_zech_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_bpoly_fit_length(fq_zech_bpoly_t A, slong len, const fq_zech_ctx_t ctx) { if (len > A->alloc) fq_zech_bpoly_realloc(A, len, ctx); } FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_bpoly_zero(fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { A->length = 0; } FQ_ZECH_MPOLY_FACTOR_INLINE int fq_zech_bpoly_is_zero(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { return A->length == 0; } int fq_zech_bpoly_equal(const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_get_coeff(fq_zech_t c, const fq_zech_bpoly_t A, slong e0, slong e1, const fq_zech_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE slong fq_zech_bpoly_degree0(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { return A->length - 1; } slong fq_zech_bpoly_degree1(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); void fq_zech_bpoly_set_poly_var1(fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_set_poly_var0(fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_print_pretty(const fq_zech_bpoly_t A, const char * var0, const char * var1, const fq_zech_ctx_t ctx); int fq_zech_bpoly_is_canonical(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); int fq_zech_bpoly_fq_equal( const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_set_coeff_fq_zech( fq_zech_bpoly_t A, slong xi, slong yi, const fq_zech_t c, const fq_zech_ctx_t ctx); void fq_zech_bpoly_set_fq_zech_poly_var0( fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_set_fq_zech_poly_var1( fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_make_monic( fq_zech_bpoly_t A, slong order, const fq_zech_ctx_t ctx); void fq_zech_bpoly_mul( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, const fq_zech_ctx_t ctx); void fq_zech_bpoly_mul_series( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, slong order, const fq_zech_ctx_t ctx); void fq_zech_bpoly_add( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, const fq_zech_ctx_t ctx); void fq_zech_bpoly_one( fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); void fq_zech_bpoly_sub( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, const fq_zech_ctx_t ctx); void fq_zech_bpoly_derivative( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_divrem_series( fq_zech_bpoly_t Q, fq_zech_bpoly_t R, const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, slong order, const fq_zech_ctx_t ctx); int fq_zech_bpoly_divides( fq_zech_bpoly_t Q, const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_set( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); void fq_zech_bpoly_make_primitive( fq_zech_poly_t g, fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); void fq_zech_bpoly_taylor_shift_var1( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_t c_, const fq_zech_ctx_t ctx); void fq_zech_bpoly_taylor_shift_var0( fq_zech_bpoly_t A, const fq_zech_t alpha, const fq_zech_ctx_t ctx); void fq_zech_mpoly_get_fq_zech_bpoly( fq_zech_bpoly_t A, const fq_zech_mpoly_t B, slong varx, slong vary, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_fq_zech_bpoly( fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_bpoly_t B, slong varx, slong vary, const fq_zech_mpoly_ctx_t ctx); int fq_zech_bpoly_factor_smprime( fq_zech_poly_t c, fq_zech_tpoly_t F, fq_zech_bpoly_t B, int allow_shift, const fq_zech_ctx_t ctx); int fq_zech_bpoly_factor_lgprime( fq_zech_poly_t c, fq_zech_tpoly_t F, fq_zech_bpoly_t B, const fq_zech_ctx_t ctx, flint_rand_t state); /*****************************************************************************/ FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_tpoly_init(fq_zech_tpoly_t A, const fq_zech_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_tpoly_swap(fq_zech_tpoly_t A, fq_zech_tpoly_t B, const fq_zech_ctx_t ctx) { fq_zech_tpoly_struct t = *A; *A = *B; *B = t; } void fq_zech_tpoly_fit_length(fq_zech_tpoly_t A, slong len, const fq_zech_ctx_t ctx); void fq_zech_tpoly_clear(fq_zech_tpoly_t A, const fq_zech_ctx_t ctx); /*****************************************************************************/ FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_polyu_init(fq_zech_polyu_t A, const fq_zech_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->alloc = 0; } void fq_zech_polyu_clear(fq_zech_polyu_t A, const fq_zech_ctx_t ctx); void fq_zech_polyu_realloc(fq_zech_polyu_t A, slong len, const fq_zech_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_polyu_fit_length(fq_zech_polyu_t A, slong len, const fq_zech_ctx_t ctx) { FLINT_ASSERT(A->alloc >= 0); if (len > A->alloc) fq_zech_polyu_realloc(A, len, ctx); } FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_polyu_swap(fq_zech_polyu_t A, fq_zech_polyu_t B, const fq_zech_ctx_t ctx) { fq_zech_polyu_struct t = *B; *B = *A; *A = t; } void fq_zech_polyu3_print_pretty( const fq_zech_polyu_t A, const char * var0, const char * var1, const char * var2, const fq_zech_ctx_t ctx); void fq_zech_polyu3_degrees( slong * deg0, slong * deg1, slong * deg2, const fq_zech_polyu_t A); int fq_zech_polyu_is_canonical( const fq_zech_polyu_t A, const fq_zech_ctx_t ctx); /*****************************************************************************/ FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_polyun_init(fq_zech_polyun_t A, const fq_zech_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->alloc = 0; } void fq_zech_polyun_clear(fq_zech_polyun_t A, const fq_zech_ctx_t ctx); void fq_zech_polyun_realloc(fq_zech_polyun_t A, slong len, const fq_zech_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_polyun_fit_length(fq_zech_polyun_t A, slong len, const fq_zech_ctx_t ctx) { if (len > A->alloc) fq_zech_polyun_realloc(A, len, ctx); } FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_polyun_swap(fq_zech_polyun_t A, fq_zech_polyun_t B, const fq_zech_ctx_t ctx) { fq_zech_polyun_struct t = *B; *B = *A; *A = t; } void fq_zech_polyu2n_print_pretty( const fq_zech_polyun_t A, const char * var0, const char * var1, const char * varlast, const fq_zech_ctx_t ctx); void fq_zech_polyu3n_print_pretty( const fq_zech_polyun_t A, const char * var0, const char * var1, const char * var2, const char * varlast, const fq_zech_ctx_t ctx); int fq_zech_polyun_is_canonical( const fq_zech_polyun_t A, const fq_zech_ctx_t ctx); /*****************************************************************************/ int fq_zech_mpoly_is_fq_zech_poly( const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_get_fq_zech_poly( fq_zech_poly_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_set_fq_zech_poly( fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_struct * Bcoeffs, slong Blen, slong var, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_set_fq_zech_poly( fq_zech_mpoly_t A, const fq_zech_poly_t B, slong var, const fq_zech_mpoly_ctx_t ctx); /*****************************************************************************/ typedef struct { fq_zech_t constant; fq_zech_mpoly_struct * poly; fmpz * exp; slong num; slong alloc; } fq_zech_mpoly_factor_struct; typedef fq_zech_mpoly_factor_struct fq_zech_mpoly_factor_t[1]; void fq_zech_mpoly_factor_init(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_factor_realloc(fq_zech_mpoly_factor_t f, slong alloc, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_factor_fit_length(fq_zech_mpoly_factor_t f, slong len, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_factor_clear(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_factor_set(fq_zech_mpoly_factor_t a, const fq_zech_mpoly_factor_t b, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_factor_print_pretty(const fq_zech_mpoly_factor_t f, const char ** vars, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_factor_append_ui(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, ulong e, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_factor_append_fmpz(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fmpz_t e, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_factor_squarefree(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_factor(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_mpoly_factor_swap(fq_zech_mpoly_factor_t A, fq_zech_mpoly_factor_t B, const fq_zech_mpoly_ctx_t ctx) { fq_zech_mpoly_factor_struct t = *A; *A = *B; *B = t; } void fq_zech_mpoly_factor_one(fq_zech_mpoly_factor_t a, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_factor_expand(fq_zech_mpoly_t A, const fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE int fq_zech_mpoly_factor_matches(const fq_zech_mpoly_t a, const fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx) { int matches; fq_zech_mpoly_t t; fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_factor_expand(t, f, ctx); matches = fq_zech_mpoly_equal(t, a, ctx); fq_zech_mpoly_clear(t, ctx); return matches; } void _fq_zech_mpoly_get_lead0( fq_zech_mpoly_t c, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_set_lead0( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t c, const fq_zech_mpoly_ctx_t ctx); /*****************************************************************************/ typedef struct { fq_zech_mpoly_struct * coeffs; slong alloc; slong length; } fq_zech_mpolyv_struct; typedef fq_zech_mpolyv_struct fq_zech_mpolyv_t[1]; FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_mpolyv_init(fq_zech_mpolyv_t A, const fq_zech_mpoly_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FQ_ZECH_MPOLY_FACTOR_INLINE void fq_zech_mpolyv_swap(fq_zech_mpolyv_t A, fq_zech_mpolyv_t B, const fq_zech_mpoly_ctx_t ctx) { fq_zech_mpolyv_struct t = *A; *A = *B; *B = t; } void fq_zech_mpolyv_clear(fq_zech_mpolyv_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpolyv_print_pretty(const fq_zech_mpolyv_t poly, const char ** x, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpolyv_fit_length(fq_zech_mpolyv_t A, slong length, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpolyv_set_coeff( fq_zech_mpolyv_t A, slong i, fq_zech_mpoly_t c, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_to_mpolyv( fq_zech_mpolyv_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t xalpha, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_from_mpolyv( fq_zech_mpoly_t A, const fq_zech_mpolyv_t B, const fq_zech_mpoly_t xalpha, const fq_zech_mpoly_ctx_t ctx); /*****************************************************************************/ int fq_zech_mpoly_univar_content_mpoly( fq_zech_mpoly_t g, const fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_univar_divexact_mpoly( fq_zech_mpoly_univar_t A, const fq_zech_mpoly_t b, const fq_zech_mpoly_ctx_t ctx); /*****************************************************************************/ int fq_zech_mpoly_factor_lcc_wang( fq_zech_mpoly_struct * lc_divs, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_poly_t Auc, const fq_zech_bpoly_struct * Auf, slong r, const fq_zech_poly_struct * alpha, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_factor_irred_smprime_zassenhaus( fq_zech_mpolyv_t fac, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state); int fq_zech_mpoly_factor_irred_lgprime_zassenhaus( fq_zech_mpolyv_t fac, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state); int fq_zech_mpoly_factor_irred_smprime_wang( fq_zech_mpolyv_t fac, const fq_zech_mpoly_t A, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_mpoly_t lcA, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state); int fq_zech_mpoly_factor_irred_lgprime_wang( fq_zech_mpolyv_t Af, const fq_zech_mpoly_t A, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_mpoly_t lcA, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state); int fq_zech_mpoly_factor_irred_smprime_zippel( fq_zech_mpolyv_t fac, const fq_zech_mpoly_t A, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_mpoly_t lcA, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state); int fq_zech_mpoly_factor_irred_lgprime_zippel( fq_zech_mpolyv_t Af, const fq_zech_mpoly_t A, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_mpoly_t lcA, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state); /*****************************************************************************/ typedef struct { flint_bitcnt_t bits; slong w; slong r; fq_zech_poly_struct * inv_prod_dbetas; fq_zech_mpoly_struct * inv_prod_dbetas_mvar; fq_zech_poly_struct * dbetas; fq_zech_mpoly_struct * dbetas_mvar; fq_zech_mpoly_struct * prod_mbetas; fq_zech_mpolyv_struct * prod_mbetas_coeffs; fq_zech_mpoly_struct * mbetas; fq_zech_mpoly_struct * deltas; fq_zech_mpoly_struct * xalpha; fq_zech_mpoly_struct * q; fq_zech_mpoly_struct * qt; fq_zech_mpoly_struct * newt; fq_zech_mpolyv_struct * delta_coeffs; fq_zech_mpoly_t T; fq_zech_mpoly_t Q; fq_zech_mpoly_t R; } fq_zech_mpoly_pfrac_struct; typedef fq_zech_mpoly_pfrac_struct fq_zech_mpoly_pfrac_t[1]; int fq_zech_mpoly_pfrac_init( fq_zech_mpoly_pfrac_t I, flint_bitcnt_t bits, slong l, slong r, const fq_zech_mpoly_struct * betas, const fq_zech_struct * alpha, const fq_zech_mpoly_ctx_t ctx); void fq_zech_mpoly_pfrac_clear( fq_zech_mpoly_pfrac_t I, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_pfrac( slong r, fq_zech_mpoly_t t, const slong * deg, fq_zech_mpoly_pfrac_t I, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_hlift( slong m, fq_zech_mpoly_struct * f, /* length r */ slong r, const fq_zech_struct * alpha, const fq_zech_mpoly_t A, const slong * degs, const fq_zech_mpoly_ctx_t ctx); int fq_zech_bpoly_hlift2( fq_zech_bpoly_t A, /* clobbered (shifted by alpha) */ fq_zech_bpoly_t B0, fq_zech_bpoly_t B1, const fq_zech_t alpha, slong degree_inner, /* required degree in x */ const fq_zech_ctx_t ctx); int fq_zech_bpoly_hlift( slong r, fq_zech_bpoly_t A, /* clobbered (shifted by alpha) */ fq_zech_bpoly_struct * B, const fq_zech_t alpha, slong degree_inner, /* required degree in x */ const fq_zech_ctx_t ctx); int fq_zech_polyu3_hlift( slong r, fq_zech_polyun_struct * BB, fq_zech_polyu_t A, fq_zech_polyu_struct * B, const fq_zech_t beta, slong degree_inner, /* required degree in x */ const fq_zech_ctx_t ctx); int fq_zech_mpoly_factor_algo(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx, unsigned int algo); int fq_zech_mpoly_factor_zassenhaus(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_factor_wang(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); int fq_zech_mpoly_factor_zippel(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); void fq_zech_poly_product_roots_fq_zech( fq_zech_poly_t master, const fq_zech_struct * monomials, slong mlength, const fq_zech_ctx_t ctx); void _fq_zech_mpoly_monomial_evals( fq_zech_struct * E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const fq_zech_struct * alpha, slong vstart, const fq_zech_mpoly_ctx_t ctx); int _fq_zech_mpoly_eval_rest_fq_zech_poly( fq_zech_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const fq_zech_struct * Acoeffs, const ulong * Aexps, slong Alen, slong var, const fq_zech_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, const fq_zech_ctx_t ctx); void _fq_zech_mpoly_eval_to_bpoly( fq_zech_bpoly_t E, const fq_zech_mpoly_t A, const fq_zech_poly_struct * alphabetas, const fq_zech_mpoly_ctx_t ctx); void _fq_zech_mpoly_set_fq_zech_bpoly_var1_zero( fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_bpoly_t B, slong var, const fq_zech_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/fq_zech_mpoly_factor/000077500000000000000000000000001461254215100176175ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_mpoly_factor/bpoly.c000066400000000000000000000406741461254215100211230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" void fq_zech_bpoly_clear(fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { slong i; if (A->alloc > 0) { FLINT_ASSERT(A->coeffs != NULL); for (i = 0; i < A->alloc; i++) fq_zech_poly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } else { FLINT_ASSERT(A->coeffs == NULL); } } void fq_zech_bpoly_normalise(fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { while (A->length > 0 && fq_zech_poly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; } void fq_zech_bpoly_realloc(fq_zech_bpoly_t A, slong len, const fq_zech_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; if (A->alloc > 0) { A->coeffs = (fq_zech_poly_struct *) flint_realloc(A->coeffs, new_alloc * sizeof(fq_zech_poly_struct)); } else { FLINT_ASSERT(A->coeffs == NULL); A->coeffs = (fq_zech_poly_struct *) flint_malloc( new_alloc * sizeof(fq_zech_poly_struct)); } for (i = old_alloc; i < new_alloc; i++) fq_zech_poly_init(A->coeffs + i, ctx); A->alloc = len; } int fq_zech_bpoly_is_canonical(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { /* if (!fq_zech_poly_is_canonical(A->coeffs + i, ctx)) return 0; */ if (i + 1 == A->length && fq_zech_poly_is_zero(A->coeffs + i, ctx)) return 0; } return 1; } slong fq_zech_bpoly_degree1(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { slong i, len = 0; for (i = 0; i < A->length; i++) len = FLINT_MAX(len, A->coeffs[i].length); return len - 1; } int fq_zech_bpoly_equal( const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (!fq_zech_poly_equal(A->coeffs + i, B->coeffs + i, ctx)) return 0; } return 1; } void fq_zech_bpoly_get_coeff(fq_zech_t c, const fq_zech_bpoly_t A, slong e0, slong e1, const fq_zech_ctx_t ctx) { if (e0 >= A->length) fq_zech_zero(c, ctx); else fq_zech_poly_get_coeff(c, A->coeffs + e0, e1, ctx); } void fq_zech_bpoly_set_coeff_fq_zech( fq_zech_bpoly_t A, slong xi, slong yi, const fq_zech_t c, const fq_zech_ctx_t ctx) { slong i; if (xi >= A->length) { fq_zech_bpoly_fit_length(A, xi + 1, ctx); for (i = A->length; i <= xi; i++) fq_zech_poly_zero(A->coeffs + i, ctx); A->length = xi + 1; } fq_zech_poly_set_coeff(A->coeffs + xi, yi, c, ctx); fq_zech_bpoly_normalise(A, ctx); } void fq_zech_bpoly_set_fq_zech_poly_var0( fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) { slong i; fq_zech_bpoly_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) fq_zech_poly_set_fq_zech(A->coeffs + i, B->coeffs + i, ctx); A->length = B->length; fq_zech_bpoly_normalise(A, ctx); } void fq_zech_bpoly_set_fq_zech_poly_var1( fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx) { fq_zech_bpoly_fit_length(A, 1, ctx); fq_zech_poly_set(A->coeffs + 0, B, ctx); A->length = !fq_zech_poly_is_zero(A->coeffs + 0, ctx); } void fq_zech_bpoly_mul( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, const fq_zech_ctx_t ctx) { slong i, j; fq_zech_poly_t t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); if (B->length < 1 || C->length < 1) { A->length = 0; return; } fq_zech_poly_init(t, ctx); fq_zech_bpoly_fit_length(A, B->length + C->length - 1, ctx); for (i = 0; i < B->length + C->length - 1; i++) fq_zech_poly_zero(A->coeffs + i, ctx); for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { fq_zech_poly_mul(t, B->coeffs + i, C->coeffs + j, ctx); fq_zech_poly_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } fq_zech_poly_clear(t, ctx); A->length = B->length + C->length - 1; fq_zech_bpoly_normalise(A, ctx); } void fq_zech_bpoly_mul_series( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, slong order, const fq_zech_ctx_t ctx) { slong i, j; fq_zech_poly_t t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); fq_zech_poly_init(t, ctx); fq_zech_bpoly_fit_length(A, B->length + C->length - 1, ctx); for (i = 0; i < B->length + C->length - 1; i++) fq_zech_poly_zero(A->coeffs + i, ctx); for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { fq_zech_poly_mullow(t, B->coeffs + i, C->coeffs + j, order, ctx); fq_zech_poly_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } fq_zech_poly_clear(t, ctx); A->length = B->length + C->length - 1; fq_zech_bpoly_normalise(A, ctx); } void fq_zech_bpoly_add( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, const fq_zech_ctx_t ctx) { slong i; slong Alen = FLINT_MAX(B->length, C->length); fq_zech_bpoly_fit_length(A, Alen, ctx); for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) { fq_zech_poly_add(A->coeffs + i, B->coeffs + i, C->coeffs + i, ctx); } else { fq_zech_poly_set(A->coeffs + i, B->coeffs + i, ctx); } } else { FLINT_ASSERT(i < C->length); fq_zech_poly_set(A->coeffs + i, C->coeffs + i, ctx); } } A->length = Alen; fq_zech_bpoly_normalise(A, ctx); } void fq_zech_bpoly_one(fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { fq_zech_bpoly_fit_length(A, 1, ctx); A->length = 1; fq_zech_poly_one(A->coeffs + 0, ctx); } void fq_zech_bpoly_sub( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_bpoly_t C, const fq_zech_ctx_t ctx) { slong i; slong Alen = FLINT_MAX(B->length, C->length); fq_zech_bpoly_fit_length(A, Alen, ctx); for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) { fq_zech_poly_sub(A->coeffs + i, B->coeffs + i, C->coeffs + i, ctx); } else { fq_zech_poly_set(A->coeffs + i, B->coeffs + i, ctx); } } else { FLINT_ASSERT(i < C->length); fq_zech_poly_neg(A->coeffs + i, C->coeffs + i, ctx); } } A->length = Alen; fq_zech_bpoly_normalise(A, ctx); } void fq_zech_bpoly_derivative( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx) { slong i; slong Blen = B->length; fq_zech_t c; if (Blen < 2) { fq_zech_bpoly_zero(A, ctx); return; } fq_zech_init(c, ctx); fq_zech_bpoly_fit_length(A, Blen - 1, ctx); for (i = 1; i < Blen; i++) { fq_zech_set_ui(c, i, ctx); fq_zech_poly_scalar_mul_fq_zech(A->coeffs + i - 1, B->coeffs + i, c, ctx); } A->length = Blen - 1; fq_zech_bpoly_normalise(A, ctx); fq_zech_clear(c, ctx); } /* division in (Fq[y]/y^order)[x] inputs need not be reduced mod y^order */ void fq_zech_bpoly_divrem_series( fq_zech_bpoly_t Q, fq_zech_bpoly_t R, const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, slong order, const fq_zech_ctx_t ctx) { slong i, qoff; fq_zech_poly_t q, t, binv; FLINT_ASSERT(R != A); FLINT_ASSERT(R != B); FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); fq_zech_poly_init(q, ctx); fq_zech_poly_init(t, ctx); fq_zech_poly_init(binv, ctx); fq_zech_bpoly_set(R, A, ctx); for (i = 0; i < R->length; i++) fq_zech_poly_truncate(R->coeffs + i, order, ctx); fq_zech_bpoly_normalise(R, ctx); fq_zech_poly_inv_series(binv, B->coeffs + B->length - 1, order, ctx); Q->length = 0; while (R->length >= B->length) { fq_zech_poly_mullow(q, R->coeffs + R->length - 1, binv, order, ctx); for (i = 0; i < B->length; i++) { fq_zech_poly_mullow(t, B->coeffs + i, q, order, ctx); fq_zech_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { fq_zech_bpoly_fit_length(Q, qoff + 1, ctx); for (i = Q->length; i <= qoff; i++) fq_zech_poly_zero(Q->coeffs + i, ctx); Q->length = qoff + 1; } fq_zech_poly_set(Q->coeffs + qoff, q, ctx); FLINT_ASSERT(fq_zech_poly_is_zero(R->coeffs + R->length - 1, ctx)); fq_zech_bpoly_normalise(R, ctx); } fq_zech_poly_clear(q, ctx); fq_zech_poly_clear(t, ctx); fq_zech_poly_clear(binv, ctx); } int fq_zech_bpoly_divides( fq_zech_bpoly_t Q, const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx) { slong i, qoff; int divides; fq_zech_poly_t q, t; fq_zech_bpoly_t R; FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); fq_zech_poly_init(q, ctx); fq_zech_poly_init(t, ctx); fq_zech_bpoly_init(R, ctx); fq_zech_bpoly_set(R, A, ctx); Q->length = 0; while (R->length >= B->length) { fq_zech_poly_divrem(q, t, R->coeffs + R->length - 1, B->coeffs + B->length - 1, ctx); if (!fq_zech_poly_is_zero(t, ctx)) { divides = 0; goto cleanup; } for (i = 0; i < B->length; i++) { fq_zech_poly_mul(t, B->coeffs + i, q, ctx); fq_zech_poly_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { fq_zech_bpoly_fit_length(Q, qoff + 1, ctx); for (i = Q->length; i <= qoff; i++) fq_zech_poly_zero(Q->coeffs + i, ctx); Q->length = qoff + 1; } fq_zech_poly_set(Q->coeffs + qoff, q, ctx); FLINT_ASSERT(fq_zech_poly_is_zero(R->coeffs + R->length - 1, ctx)); fq_zech_bpoly_normalise(R, ctx); } divides = (R->length == 0); cleanup: fq_zech_poly_clear(q, ctx); fq_zech_poly_clear(t, ctx); fq_zech_bpoly_clear(R, ctx); return divides; } void fq_zech_bpoly_set( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx) { slong i; if (A == B) return; fq_zech_bpoly_fit_length(A, B->length, ctx); A->length = B->length; for (i = 0; i < B->length; i++) fq_zech_poly_set(A->coeffs + i, B->coeffs + i, ctx); } void fq_zech_bpoly_make_primitive( fq_zech_poly_t g, fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { slong Alen = A->length; slong i; fq_zech_poly_t q, r; fq_zech_poly_init(q, ctx); fq_zech_poly_init(r, ctx); fq_zech_poly_zero(g, ctx); for (i = 0; i < Alen; i++) { fq_zech_poly_gcd(q, g, A->coeffs + i, ctx); fq_zech_poly_swap(g, q, ctx); } for (i = 0; i < Alen; i++) { fq_zech_poly_divrem(q, r, A->coeffs + i, g, ctx); fq_zech_poly_set(A->coeffs + i, q, ctx); } /* make lc_xy(A) one */ if (Alen > 0) { fq_zech_poly_struct * Alead = A->coeffs + Alen - 1; fq_zech_struct * c_ = Alead->coeffs + Alead->length - 1; fq_zech_t c; fq_zech_init(c, ctx); if (!fq_zech_is_one(c_, ctx)) { fq_zech_poly_scalar_mul_fq_zech(g, g, c_, ctx); fq_zech_inv(c, c_, ctx); for (i = 0; i < Alen; i++) fq_zech_poly_scalar_mul_fq_zech(A->coeffs + i, A->coeffs + i, c, ctx); } fq_zech_clear(c, ctx); } fq_zech_poly_clear(q, ctx); fq_zech_poly_clear(r, ctx); } void _fq_zech_poly_taylor_shift_horner( fq_zech_struct * poly, const fq_zech_t c, slong n, const fq_zech_ctx_t ctx) { slong i, j; fq_zech_t p; fq_zech_init(p, ctx); for (i = n - 2; i >= 0; i--) { for (j = i; j < n - 1; j++) { fq_zech_mul(p, poly + (j + 1), c, ctx); fq_zech_add(poly + j, poly + j, p, ctx); } } fq_zech_clear(p, ctx); } void fq_zech_bpoly_taylor_shift_var1( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_t c, const fq_zech_ctx_t ctx) { slong i; fq_zech_bpoly_set(A, B, ctx); for (i = A->length - 1; i >= 0; i--) _fq_zech_poly_taylor_shift_horner(A->coeffs[i].coeffs, c, A->coeffs[i].length, ctx); } void fq_zech_bpoly_taylor_shift_var0( fq_zech_bpoly_t A, const fq_zech_t alpha, const fq_zech_ctx_t ctx) { slong n, i, j; fq_zech_poly_t t; if (fq_zech_is_zero(alpha, ctx)) return; fq_zech_poly_init(t, ctx); n = A->length; for (i = n - 2; i >= 0; i--) { for (j = i; j < n - 1; j++) { fq_zech_poly_scalar_mul_fq_zech(t, A->coeffs + j + 1, alpha, ctx); fq_zech_poly_add(A->coeffs + j, A->coeffs + j, t, ctx); } } fq_zech_poly_clear(t, ctx); } void fq_zech_mpoly_get_fq_zech_bpoly( fq_zech_bpoly_t A, const fq_zech_mpoly_t B, slong varx, slong vary, const fq_zech_mpoly_ctx_t ctx) { slong j; slong NB; ulong Bexpx, Bexpy; slong Boffx, Bshiftx, Boffy, Bshifty; ulong mask; FLINT_ASSERT(B->bits <= FLINT_BITS); NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); fq_zech_bpoly_zero(A, ctx->fqctx); for (j = 0; j < B->length; j++) { Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask; Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask; fq_zech_bpoly_set_coeff_fq_zech(A, Bexpx, Bexpy, B->coeffs + j, ctx->fqctx); } } void fq_zech_mpoly_set_fq_zech_bpoly( fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_bpoly_t B, slong varx, slong vary, const fq_zech_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, j; slong NA; slong Alen; fq_zech_struct * Acoeff; ulong * Aexp; slong Aalloc; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); TMP_START; Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); for (i = 0; i < n; i++) Aexps[i] = 0; NA = mpoly_words_per_exp(Abits, ctx->minfo); fq_zech_mpoly_fit_bits(A, Abits, ctx); A->bits = Abits; Acoeff = A->coeffs; Aexp = A->exps; Aalloc = A->alloc; Alen = 0; for (i = 0; i < B->length; i++) { fq_zech_poly_struct * Bc = B->coeffs + i; _fq_zech_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + Bc->length, NA, ctx->fqctx); for (j = 0; j < Bc->length; j++) { if (fq_zech_is_zero(Bc->coeffs + j, ctx->fqctx)) continue; Aexps[varx] = i; Aexps[vary] = j; fq_zech_set(Acoeff + Alen, Bc->coeffs + j, ctx->fqctx); mpoly_set_monomial_ui(Aexp + NA*Alen, Aexps, Abits, ctx->minfo); Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; A->alloc = Aalloc; A->length = Alen; TMP_END; fq_zech_mpoly_sort_terms(A, ctx); } flint-3.1.3/src/fq_zech_mpoly_factor/bpoly_factor_smprime.c000066400000000000000000000570361461254215100242150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fmpz_poly_factor.h" #include "fq_zech_poly_factor.h" #include "nmod_mpoly_factor.h" #include "fq_zech_mpoly_factor.h" int fq_zech_next(fq_zech_t x, const fq_zech_ctx_t ctx) { if (x->value < 1) return 0; x->value--; return 1; } void fq_zech_bpoly_eval_var1( fq_zech_poly_t E, const fq_zech_bpoly_t A, const fq_zech_t alpha, const fq_zech_ctx_t ctx) { slong i; fq_zech_poly_fit_length(E, A->length, ctx); for (i = 0; i < A->length; i++) fq_zech_poly_evaluate_fq_zech(E->coeffs + i, A->coeffs + i, alpha, ctx); E->length = A->length; _fq_zech_poly_normalise(E, ctx); } void fq_zech_bpoly_make_monic_series( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, slong order, const fq_zech_ctx_t ctx) { slong i; fq_zech_poly_t lcinv; FLINT_ASSERT(A != B); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(fq_zech_bpoly_is_canonical(B, ctx)); fq_zech_poly_init(lcinv, ctx); fq_zech_poly_inv_series(lcinv, B->coeffs + B->length - 1, order, ctx); fq_zech_bpoly_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) fq_zech_poly_mullow(A->coeffs + i, B->coeffs + i, lcinv, order, ctx); A->length = B->length; fq_zech_bpoly_normalise(A, ctx); fq_zech_poly_clear(lcinv, ctx); } /****************** lifting **************************************************/ static void _hensel_build_tree( slong * link, fq_zech_bpoly_struct * v, fq_zech_bpoly_struct * w, const fq_zech_poly_struct * local_facs, slong r, const fq_zech_ctx_t ctx) { slong i, j; fq_zech_poly_t d; fq_zech_poly_struct * V; fq_zech_poly_struct * W; V = FLINT_ARRAY_ALLOC(2*r - 2, fq_zech_poly_struct); W = FLINT_ARRAY_ALLOC(2*r - 2, fq_zech_poly_struct); fq_zech_poly_init(d, ctx); for (i = 0; i < 2*r - 2; i++) { fq_zech_poly_init(V + i, ctx); fq_zech_poly_init(W + i, ctx); } for (i = 0; i < r; i++) { fq_zech_poly_set(V + i, local_facs + i, ctx); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp, mind; minp = j; mind = fq_zech_poly_degree(V + j, ctx); for (s = j + 1; s < i; s++) { if (fq_zech_poly_degree(V + s, ctx) < mind) { minp = s; mind = fq_zech_poly_degree(V + s, ctx); } } fq_zech_poly_swap(V + j, V + minp, ctx); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = fq_zech_poly_degree(V + j + 1, ctx); for (s = j + 2; s < i; s++) { if (fq_zech_poly_degree(V + s, ctx) < mind) { minp = s; mind = fq_zech_poly_degree(V + s, ctx); } } fq_zech_poly_swap(V + j + 1, V + minp, ctx); FLINT_SWAP(slong, link[j + 1], link[minp]); fq_zech_poly_mul(V + i, V + j, V + j + 1, ctx); link[i] = j; } for (j = 0; j < 2*r - 2; j += 2) { fq_zech_poly_xgcd(d, W + j, W + j + 1, V + j, V + j + 1, ctx); FLINT_ASSERT(fq_zech_poly_is_one(d, ctx)); } for (j = 0; j < 2*r - 2; j++) { fq_zech_bpoly_set_fq_zech_poly_var0(v + j, V + j, ctx); fq_zech_bpoly_set_fq_zech_poly_var0(w + j, W + j, ctx); } fq_zech_poly_clear(d, ctx); for (i = 0; i < 2*r - 2; i++) { fq_zech_poly_clear(V + i, ctx); fq_zech_poly_clear(W + i, ctx); } flint_free(V); flint_free(W); } static void _hensel_lift_fac( fq_zech_bpoly_t G, fq_zech_bpoly_t H, const fq_zech_bpoly_t f, fq_zech_bpoly_t g, fq_zech_bpoly_t h, const fq_zech_bpoly_t a, const fq_zech_bpoly_t b, slong p0, slong p1, const fq_zech_ctx_t ctx) { slong i; fq_zech_bpoly_t c, t1, t2, q, r; fq_zech_bpoly_init(c, ctx); fq_zech_bpoly_init(t1, ctx); fq_zech_bpoly_init(t2, ctx); fq_zech_bpoly_init(q, ctx); fq_zech_bpoly_init(r, ctx); fq_zech_bpoly_mul(t1, g, h, ctx); fq_zech_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { #if FLINT_WANT_ASSERT { slong j; for (j = 0; j < p0; j++) { FLINT_ASSERT(j >= c->coeffs[i].length || fq_zech_is_zero(c->coeffs[i].coeffs + j, ctx)); } } #endif fq_zech_poly_shift_right(c->coeffs + i, c->coeffs + i, p0, ctx); fq_zech_poly_truncate(c->coeffs + i, p1, ctx); } fq_zech_bpoly_mul_series(t1, c, b, p1, ctx); fq_zech_bpoly_divrem_series(q, r, t1, g, p1, ctx); for (i = 0; i < r->length; i++) fq_zech_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < g->length; i++) fq_zech_poly_truncate(g->coeffs + i, p0, ctx); fq_zech_bpoly_add(t1, r, g, ctx); fq_zech_bpoly_mul_series(t2, c, a, p1, ctx); fq_zech_bpoly_divrem_series(q, r, t2, h, p1, ctx); for (i = 0; i < r->length; i++) fq_zech_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < h->length; i++) fq_zech_poly_truncate(h->coeffs + i, p0, ctx); fq_zech_bpoly_add(t2, r, h, ctx); fq_zech_bpoly_swap(G, t1, ctx); fq_zech_bpoly_swap(H, t2, ctx); #if FLINT_WANT_ASSERT { slong j; fq_zech_bpoly_mul(t1, G, H, ctx); fq_zech_bpoly_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) for (j = 0; j < p0 + p1; j++) { FLINT_ASSERT(j >= c->coeffs[i].length || fq_zech_is_zero(c->coeffs[i].coeffs + j, ctx)); } } #endif fq_zech_bpoly_clear(c, ctx); fq_zech_bpoly_clear(t1, ctx); fq_zech_bpoly_clear(t2, ctx); fq_zech_bpoly_clear(q, ctx); fq_zech_bpoly_clear(r, ctx); } static void _hensel_lift_inv( fq_zech_bpoly_t A, fq_zech_bpoly_t B, const fq_zech_bpoly_t G, const fq_zech_bpoly_t H, fq_zech_bpoly_t a, fq_zech_bpoly_t b, slong p0, slong p1, const fq_zech_ctx_t ctx) { slong i; fq_zech_bpoly_t c, t1, t2, q, r; fq_zech_bpoly_init(c, ctx); fq_zech_bpoly_init(t1, ctx); fq_zech_bpoly_init(t2, ctx); fq_zech_bpoly_init(q, ctx); fq_zech_bpoly_init(r, ctx); for (i = 0; i < b->length; i++) fq_zech_poly_truncate(b->coeffs + i, p0, ctx); for (i = 0; i < a->length; i++) fq_zech_poly_truncate(a->coeffs + i, p0, ctx); fq_zech_bpoly_mul(t1, G, a, ctx); fq_zech_bpoly_mul(t2, H, b, ctx); fq_zech_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) fq_zech_poly_neg(c->coeffs + i, c->coeffs + i, ctx); fq_zech_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); fq_zech_bpoly_normalise(c, ctx); for (i = 0; i < c->length; i++) { #if FLINT_WANT_ASSERT { slong j; for (j = 0; j < p0; j++) { FLINT_ASSERT(j >= c->coeffs[i].length || fq_zech_is_zero(c->coeffs[i].coeffs + j, ctx)); } } #endif fq_zech_poly_shift_right(c->coeffs + i, c->coeffs + i, p0, ctx); fq_zech_poly_truncate(c->coeffs + i, p1, ctx); } fq_zech_bpoly_mul_series(t1, c, b, p1, ctx); fq_zech_bpoly_divrem_series(q, r, t1, G, p1, ctx); for (i = 0; i < r->length; i++) fq_zech_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); fq_zech_bpoly_add(t1, r, b, ctx); fq_zech_bpoly_mul_series(t2, c, a, p1, ctx); fq_zech_bpoly_divrem_series(q, r, t2, H, p1, ctx); for (i = 0; i < r->length; i++) fq_zech_poly_shift_left(r->coeffs + i, r->coeffs + i, p0, ctx); fq_zech_bpoly_add(t2, r, a, ctx); fq_zech_bpoly_swap(t1, B, ctx); fq_zech_bpoly_swap(t2, A, ctx); #if FLINT_WANT_ASSERT fq_zech_bpoly_mul(t1, G, A, ctx); fq_zech_bpoly_mul(t2, H, B, ctx); fq_zech_bpoly_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) fq_zech_poly_neg(c->coeffs + i, c->coeffs + i, ctx); fq_zech_poly_add_si(c->coeffs + 0, c->coeffs + 0, 1, ctx); fq_zech_bpoly_normalise(c, ctx); { slong j; for (i = 0; i < c->length; i++) for (j = 0; j < p0 + p1; j++) { FLINT_ASSERT(j >= c->coeffs[i].length || fq_zech_is_zero(c->coeffs[i].coeffs + j, ctx)); } } #endif fq_zech_bpoly_clear(c, ctx); fq_zech_bpoly_clear(t1, ctx); fq_zech_bpoly_clear(t2, ctx); fq_zech_bpoly_clear(q, ctx); fq_zech_bpoly_clear(r, ctx); } static void _hensel_lift_tree( int opt, slong * link, fq_zech_bpoly_struct * v, fq_zech_bpoly_struct * w, const fq_zech_bpoly_t f, slong j, slong p0, slong p1, const fq_zech_ctx_t ctx) { FLINT_ASSERT(p1 <= p0); if (j < 0) return; if (opt >= 0) _hensel_lift_fac(v + j, v + j + 1, f, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); if (opt <= 0) _hensel_lift_inv(w + j, w + j + 1, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j, link[j], p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j + 1, link[j + 1], p0, p1, ctx); } typedef struct { slong * link; fq_zech_bpoly_struct ** lifted_fac; fq_zech_tpoly_t tmp; fq_zech_bpoly_t bmp; slong r; slong fac_lift_order; slong inv_lift_order; nmod_eval_interp_t E; int Eok; int use_linear; } fq_zech_bpoly_lift_struct; typedef fq_zech_bpoly_lift_struct fq_zech_bpoly_lift_t[1]; static void fq_zech_bpoly_lift_init( fq_zech_bpoly_lift_t L, const fq_zech_ctx_t ctx) { L->link = NULL; L->lifted_fac = NULL; fq_zech_tpoly_init(L->tmp, ctx); fq_zech_bpoly_init(L->bmp, ctx); L->r = 0; L->fac_lift_order = 0; L->inv_lift_order = 0; } static void fq_zech_bpoly_lift_clear( fq_zech_bpoly_lift_t L, const fq_zech_ctx_t ctx) { flint_free(L->link); flint_free(L->lifted_fac); fq_zech_tpoly_clear(L->tmp, ctx); fq_zech_bpoly_clear(L->bmp, ctx); } static void fq_zech_bpoly_lift_start( fq_zech_bpoly_lift_t L, fq_zech_poly_struct * local_facs, slong r, const fq_zech_ctx_t ctx) { slong i; L->r = r; L->lifted_fac = (fq_zech_bpoly_struct **) flint_realloc(L->lifted_fac, r*sizeof(fq_zech_bpoly_struct *)); L->fac_lift_order = 1; L->inv_lift_order = 1; { fq_zech_bpoly_struct * v, * w; L->link = (slong *) flint_realloc(L->link, (2*r - 2)*sizeof(slong)); fq_zech_tpoly_fit_length(L->tmp, 2*(2*r - 2), ctx); v = L->tmp->coeffs + 0; w = L->tmp->coeffs + (2*r - 2); _hensel_build_tree(L->link, v, w, local_facs, r, ctx); for (i = 0; i < 2*r - 2; i++) if (-L->link[i] - 1 >= 0) L->lifted_fac[-L->link[i] - 1] = v + i; return; } } static void fq_zech_bpoly_lift_continue( fq_zech_bpoly_lift_t L, const fq_zech_bpoly_t monicA, slong order, const fq_zech_ctx_t ctx) { slong i; slong r = L->r; if (order <= L->fac_lift_order) return; { fq_zech_bpoly_struct * v = L->tmp->coeffs + 0; fq_zech_bpoly_struct * w = L->tmp->coeffs + (2*r - 2); slong e[FLINT_BITS+1]; FLINT_ASSERT(1 <= L->inv_lift_order); FLINT_ASSERT(L->fac_lift_order <= 2*L->inv_lift_order); for (i = 0, e[i] = order; e[i] > L->fac_lift_order; i++) e[i+1] = (e[i] + 1)/2; e[i] = L->fac_lift_order; e[i+1] = L->inv_lift_order; if (e[i+1] < e[i]) _hensel_lift_tree(-1, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); for (i--; i > 0; i--) _hensel_lift_tree(0, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); _hensel_lift_tree(1, L->link, v, w, monicA, 2*r-4, e[1], e[0]-e[1], ctx); L->fac_lift_order = e[0]; L->inv_lift_order = e[1]; return; } } /************* lattice reduction *********************************************/ /* The rows of N, if they are 0-1, correspond to combinations of the g that give factors of A. Compute {A/g[i]*g[i]'}_i and use the CLD bounds to try to make N smaller. */ static void _lattice( nmod_mat_t N, fq_zech_bpoly_struct * const * g, slong r, slong lift_order, slong * starts, const fq_zech_bpoly_t f, const fq_zech_ctx_t ctx) { slong deg = fq_zech_ctx_degree(ctx); slong i, j, k, l; fq_zech_bpoly_t Q, R, dg; fq_zech_bpoly_struct * ld; nmod_mat_t M, T1, T2; int nlimbs; mp_limb_t * trow; nlimbs = _nmod_vec_dot_bound_limbs(r, fq_zech_ctx_mod(ctx)); trow = (mp_limb_t *) flint_malloc(r*sizeof(mp_limb_t)); fq_zech_bpoly_init(Q, ctx); fq_zech_bpoly_init(R, ctx); fq_zech_bpoly_init(dg, ctx); ld = FLINT_ARRAY_ALLOC(r, fq_zech_bpoly_struct); for (i = 0; i < r; i++) fq_zech_bpoly_init(ld + i, ctx); /* init done */ for (i = 0; i < r; i++) { fq_zech_bpoly_divrem_series(Q, R, f, g[i], lift_order, ctx); FLINT_ASSERT(R->length == 0); fq_zech_bpoly_derivative(R, g[i], ctx); fq_zech_bpoly_mul_series(ld + i, Q, R, lift_order, ctx); } for (k = 0; k + 1 < f->length; k++) { slong d = nmod_mat_nrows(N); if (lift_order <= starts[k]) continue; nmod_mat_init(M, deg*(lift_order - starts[k]), d, fq_zech_ctx_mod(ctx).n); for (j = starts[k]; j < lift_order; j++) for (l = 0; l < deg; l++) { for (i = 0; i < r; i++) { if (k >= ld[i].length || j >= ld[i].coeffs[k].length) { trow[i] = 0; } else { nmod_poly_t junk; nmod_poly_init_mod(junk, fq_zech_ctx_mod(ctx)); fq_zech_get_nmod_poly(junk, ld[i].coeffs[k].coeffs + j, ctx); trow[i] = nmod_poly_get_coeff_ui(junk, l); nmod_poly_clear(junk); } } for (i = 0; i < d; i++) nmod_mat_entry(M, (j - starts[k])*deg + l, i) = _nmod_vec_dot(trow, N->rows[i], r, fq_zech_ctx_mod(ctx), nlimbs); } nmod_mat_init_nullspace_tr(T1, M); nmod_mat_init(T2, nmod_mat_nrows(T1), nmod_mat_ncols(N), fq_zech_ctx_mod(ctx).n); nmod_mat_mul(T2, T1, N); nmod_mat_swap(T2, N); nmod_mat_rref(N); nmod_mat_clear(M); nmod_mat_clear(T1); nmod_mat_clear(T2); } flint_free(trow); fq_zech_bpoly_clear(Q, ctx); fq_zech_bpoly_clear(R, ctx); fq_zech_bpoly_clear(dg, ctx); for (i = 0; i < r; i++) fq_zech_bpoly_clear(ld + i, ctx); flint_free(ld); } /**************** recombination **********************************************/ /* First multiply the g[i] into the gprod[i] according the the rows of N. Then, run zassenhaus on the gprod[i] as factors of A. */ static int _zassenhaus( const zassenhaus_prune_t zas, slong limit, fq_zech_tpoly_t F, const fq_zech_t malpha, const nmod_mat_t N, fq_zech_bpoly_struct * const * loc_fac_org, slong r, slong order, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx) { int success; fq_zech_bpoly_t Q, R, t1, t2; fq_zech_poly_t g; slong * subset; slong i, j, s, len, d = nmod_mat_nrows(N); fq_zech_bpoly_struct * loc_fac; fq_zech_bpoly_struct * f; fq_zech_bpoly_t B_copy; FLINT_ASSERT(nmod_mat_ncols(N) == r); fq_zech_poly_init(g, ctx); fq_zech_bpoly_init(Q, ctx); fq_zech_bpoly_init(R, ctx); fq_zech_bpoly_init(t1, ctx); fq_zech_bpoly_init(t2, ctx); fq_zech_bpoly_init(B_copy, ctx); subset = FLINT_ARRAY_ALLOC(d, slong); loc_fac = FLINT_ARRAY_ALLOC(d, fq_zech_bpoly_struct); for (i = 0; i < d; i++) { subset[i] = i; fq_zech_bpoly_init(loc_fac + i, ctx); } for (i = 0; i < d; i++) { fq_zech_bpoly_one(loc_fac + i, ctx); for (j = 0; j < r; j++) { if (nmod_mat_entry(N, i, j) == 0) continue; FLINT_ASSERT(nmod_mat_entry(N, i, j) == 1); fq_zech_bpoly_mul_series(t1, loc_fac + i, loc_fac_org[j], order, ctx); fq_zech_bpoly_swap(t1, loc_fac + i, ctx); } } f = (fq_zech_bpoly_struct *) B; len = d; for (s = 1; s <= len/2; s++) { if (s > limit) { success = 0; goto cleanup; } zassenhaus_subset_first(subset, len, s); while (1) { FLINT_ASSERT(f->length > 0); fq_zech_bpoly_set_fq_zech_poly_var1(t1, f->coeffs + f->length - 1, ctx); for (i = 0; i < len; i++) { if (subset[i] >= 0) { fq_zech_bpoly_mul_series(t2, t1, loc_fac + subset[i], order, ctx); fq_zech_bpoly_swap(t1, t2, ctx); } } fq_zech_bpoly_make_primitive(g, t1, ctx); if (fq_zech_bpoly_divides(Q, f, t1, ctx)) { fq_zech_bpoly_taylor_shift_var1(t1, t1, malpha, ctx); fq_zech_tpoly_fit_length(F, F->length + 1, ctx); fq_zech_bpoly_swap(F->coeffs + F->length, t1, ctx); F->length++; f = B_copy; fq_zech_bpoly_swap(f, Q, ctx); len -= s; if (!zassenhaus_subset_next_disjoint(subset, len + s)) break; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (f->length > 1) { fq_zech_tpoly_fit_length(F, F->length + 1, ctx); fq_zech_bpoly_taylor_shift_var1(F->coeffs + F->length, f, malpha, ctx); F->length++; } else { FLINT_ASSERT(f->length == 1); FLINT_ASSERT(fq_zech_poly_is_one(f->coeffs + 0, ctx)); } success = 1; cleanup: fq_zech_poly_clear(g, ctx); fq_zech_bpoly_clear(Q, ctx); fq_zech_bpoly_clear(R, ctx); fq_zech_bpoly_clear(t1, ctx); fq_zech_bpoly_clear(t2, ctx); fq_zech_bpoly_clear(B_copy, ctx); for (i = 0; i < d; i++) fq_zech_bpoly_clear(loc_fac + i, ctx); flint_free(loc_fac); flint_free(subset); return success; } int fq_zech_bpoly_factor_smprime( fq_zech_poly_t c, fq_zech_tpoly_t F, fq_zech_bpoly_t A, int allow_shift, const fq_zech_ctx_t ctx) { int success; slong i, r; slong Alenx, Aleny; slong final_order, lift_order; slong * CLD; fq_zech_t alpha, Alc; fq_zech_poly_t Aeval; fq_zech_poly_factor_t local_fac; fq_zech_bpoly_t monicA; nmod_mat_t N; slong old_nrows; slong zas_limit; zassenhaus_prune_t zas; fq_zech_bpoly_lift_t L; fq_zech_bpoly_make_primitive(c, A, ctx); Alenx = 1 + fq_zech_bpoly_degree0(A, ctx); Aleny = 1 + fq_zech_bpoly_degree1(A, ctx); FLINT_ASSERT(Alenx > 1); fq_zech_init(alpha, ctx); fq_zech_init(Alc, ctx); fq_zech_poly_init(Aeval, ctx); fq_zech_poly_factor_init(local_fac, ctx); fq_zech_bpoly_init(monicA, ctx); nmod_mat_init(N, 0, 0, fq_zech_ctx_mod(ctx).n); CLD = FLINT_ARRAY_ALLOC(Alenx, slong); zassenhaus_prune_init(zas); fq_zech_bpoly_lift_init(L, ctx); /* TODO: CLD bounds */ for (i = 0; i < Alenx; i++) CLD[i] = Aleny; zassenhaus_prune_set_degree(zas, Alenx - 1); fq_zech_zero(alpha, ctx); goto got_alpha; next_alpha: if (!allow_shift || !fq_zech_next(alpha, ctx)) { success = 0; goto cleanup; } got_alpha: fq_zech_bpoly_eval_var1(Aeval, A, alpha, ctx); /* if killed leading coeff, get new alpha */ if (Aeval->length != Alenx) goto next_alpha; /* note the constant term of Aeval can be zero */ fq_zech_poly_factor(local_fac, Alc, Aeval, ctx); r = local_fac->num; zassenhaus_prune_start_add_factors(zas); for (i = 0; i < r; i++) zassenhaus_prune_add_factor(zas, local_fac->poly[i].length - 1, local_fac->exp[i]); zassenhaus_prune_end_add_factors(zas); /* check for irreducibility */ if ((r < 2 && local_fac->exp[0] == 1) || zassenhaus_prune_must_be_irreducible(zas)) { fq_zech_tpoly_fit_length(F, 1, ctx); fq_zech_bpoly_swap(F->coeffs + 0, A, ctx); F->length = 1; success = 1; goto cleanup; } /* if multiple factors, get new alpha */ for (i = 0; i < r; i++) { if (local_fac->exp[i] != 1) goto next_alpha; } /* done if B is constant in y */ if (Aleny < 2) { fq_zech_tpoly_fit_length(F, r, ctx); F->length = r; for (i = 0; i < r; i++) fq_zech_bpoly_set_fq_zech_poly_var0(F->coeffs + i, local_fac->poly + i, ctx); success = 1; goto cleanup; } /* precision for constructing true factors */ final_order = Aleny; fq_zech_bpoly_taylor_shift_var1(A, A, alpha, ctx); fq_zech_bpoly_lift_start(L, local_fac->poly, r, ctx); /* precision for lifted local factors */ lift_order = final_order + r; fq_zech_bpoly_make_monic_series(monicA, A, lift_order, ctx); fq_zech_bpoly_lift_continue(L, monicA, lift_order, ctx); /* the rows of N give the combinations of local factors */ nmod_mat_clear(N); nmod_mat_init(N, r, r, fq_zech_ctx_mod(ctx).n); for (i = 0; i < r; i++) nmod_mat_entry(N, i, i) = 1; /* size limit on subsets in zassenhaus combination */ zas_limit = 1; _lattice(N, L->lifted_fac, r, lift_order, CLD, A, ctx); if (!nmod_mat_is_reduced(N)) goto more; try_zas: /* zassenhaus only make sense if N is a nice 0-1 mat */ FLINT_ASSERT(nmod_mat_is_reduced(N)); /* combine local factors according the rows of N, then by subsets */ F->length = 0; fq_zech_neg(alpha, alpha, ctx); success = _zassenhaus(zas, zas_limit, F, alpha, N, L->lifted_fac, r, final_order, A, ctx); fq_zech_neg(alpha, alpha, ctx); if (success) goto cleanup; /* first attempt failed, try subsets of size 1 or 2 from now on */ zas_limit = 2; more: /* increase precision until N has fewer rows and is a nice 0-1 mat */ old_nrows = nmod_mat_nrows(N); _lattice(N, L->lifted_fac, r, lift_order, CLD, A, ctx); if (nmod_mat_nrows(N) < old_nrows && nmod_mat_is_reduced(N)) goto try_zas; lift_order += r; fq_zech_bpoly_make_monic_series(monicA, A, lift_order, ctx); fq_zech_bpoly_lift_continue(L, monicA, lift_order, ctx); goto more; cleanup: fq_zech_bpoly_lift_clear(L, ctx); flint_free(CLD); nmod_mat_clear(N); fq_zech_clear(alpha, ctx); fq_zech_clear(Alc, ctx); fq_zech_poly_clear(Aeval, ctx); fq_zech_poly_factor_clear(local_fac, ctx); fq_zech_bpoly_clear(monicA, ctx); zassenhaus_prune_clear(zas); return success; } flint-3.1.3/src/fq_zech_mpoly_factor/bpoly_hlift.c000066400000000000000000000257121461254215100223050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_mpoly_factor.h" int fq_zech_bpoly_hlift2( fq_zech_bpoly_t A, /* clobbered (shifted by alpha) */ fq_zech_bpoly_t B0, fq_zech_bpoly_t B1, const fq_zech_t alpha, slong degree_inner, /* required degree in x */ const fq_zech_ctx_t ctx) { int success; slong i, j; fq_zech_poly_t c, s, t, u, v, g; fq_zech_t malpha; FLINT_ASSERT(fq_zech_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(fq_zech_bpoly_is_canonical(B0, ctx)); FLINT_ASSERT(fq_zech_bpoly_is_canonical(B1, ctx)); if (A->length < 1 || B0->length < 1 || B1->length < 1) return -1; fq_zech_poly_init(c, ctx); fq_zech_poly_init(s, ctx); fq_zech_poly_init(t, ctx); fq_zech_poly_init(u, ctx); fq_zech_poly_init(v, ctx); fq_zech_poly_init(g, ctx); fq_zech_init(malpha, ctx); fq_zech_neg(malpha, alpha, ctx); fq_zech_bpoly_taylor_shift_var0(A, alpha, ctx); fq_zech_bpoly_taylor_shift_var0(B0, alpha, ctx); fq_zech_bpoly_taylor_shift_var0(B1, alpha, ctx); #if FLINT_WANT_ASSERT { fq_zech_poly_t T; fq_zech_poly_init(T, ctx); fq_zech_poly_mul(T, B0->coeffs + 0, B1->coeffs + 0, ctx); FLINT_ASSERT(fq_zech_poly_equal(A->coeffs + 0, T, ctx)); fq_zech_poly_clear(T, ctx); } #endif if (fq_zech_poly_degree(A->coeffs + 0, ctx) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(fq_zech_bpoly_degree1(A, ctx) == fq_zech_poly_degree(A->coeffs + 0, ctx)); fq_zech_poly_xgcd(g, s, t, B1->coeffs + 0, B0->coeffs + 0, ctx); if (!fq_zech_poly_is_one(g, ctx)) { success = -2; goto cleanup; } fq_zech_bpoly_fit_length(B0, A->length, ctx); fq_zech_bpoly_fit_length(B1, A->length, ctx); for (j = 1; j < A->length; j++) { fq_zech_poly_set(c, A->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { fq_zech_poly_mul(t, B0->coeffs + i, B1->coeffs + j - i, ctx); fq_zech_poly_sub(c, c, t, ctx); } } if (fq_zech_poly_is_zero(c, ctx)) continue; fq_zech_poly_mul(t, s, c, ctx); fq_zech_poly_divrem(g, u, t, B0->coeffs + 0, ctx); fq_zech_poly_mul(t, u, B1->coeffs + 0, ctx); fq_zech_poly_sub(c, c, t, ctx); fq_zech_poly_divrem(v, g, c, B0->coeffs + 0, ctx); if (j < B0->length) fq_zech_poly_add(B0->coeffs + j, B0->coeffs + j, u, ctx); else fq_zech_poly_set(B0->coeffs + j, u, ctx); if (j < B1->length) fq_zech_poly_add(B1->coeffs + j, B1->coeffs + j, v, ctx); else fq_zech_poly_set(B1->coeffs + j, v, ctx); if (!fq_zech_poly_is_zero(B0->coeffs + j, ctx)) B0->length = FLINT_MAX(B0->length, j + 1); if (!fq_zech_poly_is_zero(B1->coeffs + j, ctx)) B1->length = FLINT_MAX(B1->length, j + 1); if (B0->length - 1 + B1->length - 1 > A->length - 1) { success = 0; goto cleanup; } } fq_zech_bpoly_taylor_shift_var0(B0, malpha, ctx); fq_zech_bpoly_taylor_shift_var0(B1, malpha, ctx); success = 1; cleanup: if (success > 0) { fq_zech_bpoly_t tp1, tp2; fq_zech_bpoly_init(tp1, ctx); fq_zech_bpoly_init(tp2, ctx); fq_zech_bpoly_taylor_shift_var0(A, malpha, ctx); fq_zech_bpoly_mul(tp1, B0, B1, ctx); FLINT_ASSERT(fq_zech_bpoly_equal(tp1, A, ctx)); fq_zech_bpoly_clear(tp1, ctx); fq_zech_bpoly_clear(tp2, ctx); } fq_zech_poly_clear(c, ctx); fq_zech_poly_clear(s, ctx); fq_zech_poly_clear(t, ctx); fq_zech_poly_clear(u, ctx); fq_zech_poly_clear(v, ctx); fq_zech_poly_clear(g, ctx); fq_zech_clear(malpha, ctx); return success; } /* input A, B0, B1 with A(y,x) = B0(y,x) * B1(y,x) mod (y-alpha) return -1: B0(alpha,x) & B1(alpha,x) are not pairwise prime, or A(alpha,x) has wrong degree w.r.t x 0: lift of B0 and B1 to true factors is impossible 1: successfully lifted B0 and B1 to true factors without changing lc_x */ int fq_zech_bpoly_hlift( slong r, fq_zech_bpoly_t A, /* clobbered (shifted by alpha) */ fq_zech_bpoly_struct * B, const fq_zech_t alpha, slong degree_inner, /* required degree in x */ const fq_zech_ctx_t ctx) { int success; slong i, j, k, tdeg; fq_zech_poly_struct * s, * v; fq_zech_poly_t c, t, u, g1, g2; fq_zech_bpoly_struct * U; fq_zech_t malpha; FLINT_ASSERT(r > 2); FLINT_ASSERT(fq_zech_bpoly_is_canonical(A, ctx)); if (A->length < 1) return -1; for (i = 0; i < r; i++) { FLINT_ASSERT(fq_zech_bpoly_is_canonical(B + i, ctx)); if (B[i].length < 1) return -1; } U = FLINT_ARRAY_ALLOC(r, fq_zech_bpoly_struct); for (i = 0; i < r; i++) { fq_zech_bpoly_init(U + i, ctx); fq_zech_bpoly_fit_length(U + i, A->length, ctx); for (j = 0; j < A->length; j++) fq_zech_poly_zero(U[i].coeffs + j, ctx); U[i].length = A->length; fq_zech_bpoly_fit_length(B + i, A->length, ctx); } s = FLINT_ARRAY_ALLOC(r, fq_zech_poly_struct); v = FLINT_ARRAY_ALLOC(r, fq_zech_poly_struct); for (i = 0; i < r; i++) { fq_zech_poly_init(s + i, ctx); fq_zech_poly_init(v + i, ctx); } fq_zech_poly_init(c, ctx); fq_zech_poly_init(t, ctx); fq_zech_poly_init(u, ctx); fq_zech_poly_init(g1, ctx); fq_zech_poly_init(g2, ctx); fq_zech_init(malpha, ctx); fq_zech_neg(malpha, alpha, ctx); fq_zech_bpoly_taylor_shift_var0(A, alpha, ctx); for (i = 0; i < r; i++) fq_zech_bpoly_taylor_shift_var0(B + i, alpha, ctx); /* supposed to have A(alpha,x) = B0(alpha,x) * B1(alpha,x) * ... */ #if FLINT_WANT_ASSERT { fq_zech_poly_t T; fq_zech_poly_init(T, ctx); fq_zech_poly_mul(T, B[0].coeffs + 0, B[1].coeffs + 0, ctx); for (i = 2; i < r; i++) fq_zech_poly_mul(T, T, B[i].coeffs + 0, ctx); FLINT_ASSERT(fq_zech_poly_equal(A->coeffs + 0, T, ctx)); fq_zech_poly_clear(T, ctx); } #endif if (fq_zech_poly_degree(A->coeffs + 0, ctx) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(fq_zech_bpoly_degree1(A, ctx) == fq_zech_poly_degree(A->coeffs + 0, ctx)); for (i = 0; i < r; i++) { fq_zech_poly_one(t, ctx); for (j = 0; j < r; j++) { if (j != i) fq_zech_poly_mul(t, t, B[j].coeffs + 0, ctx); } fq_zech_poly_xgcd(g1, s + i, g2, t, B[i].coeffs + 0, ctx); if (!fq_zech_poly_is_one(g1, ctx)) { success = -1; goto cleanup; } } k = r - 2; fq_zech_poly_mul(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k > 0; k--) fq_zech_poly_mul(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx); for (j = 1; j < A->length; j++) { for (k = 0; k < r; k++) fq_zech_poly_zero(U[k].coeffs + j, ctx); k = r - 2; fq_zech_poly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { fq_zech_poly_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fq_zech_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (k--; k > 0; k--) { fq_zech_poly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[k].length) { fq_zech_poly_mul(t, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); fq_zech_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } } fq_zech_poly_set(c, A->coeffs + j, ctx); for (i = 0; i <= j; i++) { if (i < B[0].length) { fq_zech_poly_mul(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx); fq_zech_poly_sub(c, c, t, ctx); } } if (fq_zech_poly_is_zero(c, ctx)) continue; tdeg = 0; for (i = 0; i < r; i++) { fq_zech_poly_mul(t, s + i, c, ctx); fq_zech_poly_divrem(g1, v + i, t, B[i].coeffs + 0, ctx); while (j >= B[i].length) { fq_zech_poly_zero(B[i].coeffs + B[i].length, ctx); B[i].length++; } fq_zech_poly_add(B[i].coeffs + j, B[i].coeffs + j, v + i, ctx); fq_zech_bpoly_normalise(B + i, ctx); tdeg += B[i].length - 1; } if (tdeg >= A->length) { success = 0; goto cleanup; } k = r - 2; fq_zech_poly_mul(t, B[k].coeffs + 0, v + k + 1, ctx); fq_zech_poly_mul(u, B[k + 1].coeffs + 0, v + k, ctx); fq_zech_poly_add(t, t, u, ctx); fq_zech_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); for (k--; k > 0; k--) { fq_zech_poly_mul(u, B[k].coeffs + 0, t, ctx); fq_zech_poly_mul(t, U[k + 1].coeffs + 0, v + k, ctx); fq_zech_poly_add(t, t, u, ctx); fq_zech_poly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (i = 0; i < r; i++) fq_zech_bpoly_taylor_shift_var0(B + i, malpha, ctx); success = 1; cleanup: if (success > 0) { fq_zech_bpoly_t tp1, tp2; fq_zech_bpoly_init(tp1, ctx); fq_zech_bpoly_init(tp2, ctx); fq_zech_bpoly_taylor_shift_var0(A, malpha, ctx); fq_zech_bpoly_mul(tp1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { fq_zech_bpoly_mul(tp2, tp1, B + i, ctx); fq_zech_bpoly_swap(tp1, tp2, ctx); } FLINT_ASSERT(fq_zech_bpoly_equal(tp1, A, ctx)); fq_zech_bpoly_clear(tp1, ctx); fq_zech_bpoly_clear(tp2, ctx); } for (i = 0; i < r; i++) { fq_zech_bpoly_clear(U + i, ctx); fq_zech_poly_clear(s + i, ctx); fq_zech_poly_clear(v + i, ctx); } flint_free(U); flint_free(s); flint_free(v); fq_zech_poly_clear(c, ctx); fq_zech_poly_clear(t, ctx); fq_zech_poly_clear(u, ctx); fq_zech_poly_clear(g1, ctx); fq_zech_poly_clear(g2, ctx); fq_zech_clear(malpha, ctx); return success; } flint-3.1.3/src/fq_zech_mpoly_factor/clear.c000066400000000000000000000015201461254215100210470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_mpoly_factor.h" void fq_zech_mpoly_factor_clear( fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx) { if (f->alloc > 0) { slong i; for (i = 0; i < f->alloc; i++) { fq_zech_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } flint_free(f->poly); flint_free(f->exp); } fq_zech_clear(f->constant, ctx->fqctx); } flint-3.1.3/src/fq_zech_mpoly_factor/eval.c000066400000000000000000000143111461254215100207120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" /* only E and alphas are shifted by "var" so output is in E[0] */ int _fq_zech_mpoly_eval_rest_fq_zech_poly( fq_zech_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const fq_zech_struct * Acoeffs, const ulong * Aexps, slong Alen, slong var, const fq_zech_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, const fq_zech_ctx_t ctx) { slong v, stop; ulong next_e; FLINT_ASSERT(var < nvars); E -= var; alphas -= var; v = var; starts[v] = 0; ends[v] = Alen; fq_zech_poly_zero(E + v, ctx); if (Alen < 1) return 1; calculate: /* input: v starts[v] ends[v] */ FLINT_ASSERT(ends[v] > starts[v]); es[v] = mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]); fq_zech_poly_zero(E + v, ctx); next: FLINT_ASSERT(es[v] == (mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]))); stop = starts[v] + 1; while (stop < ends[v] && (mask & (Aexps[N*stop + offsets[v]] >> shifts[v])) == es[v]) { stop++; } stops[v] = stop; if (v + 1 < nvars) { starts[v + 1] = starts[v]; ends[v + 1] = stops[v]; v++; goto calculate; calculate_return: fq_zech_poly_add(E + v, E + v, E + v + 1, ctx); } else { fq_zech_poly_set_fq_zech(E + v + 1, Acoeffs + starts[v], ctx); fq_zech_poly_add(E + v, E + v, E + v + 1, ctx); } if (stops[v] < ends[v]) { next_e = mask & (Aexps[N*stops[v] + offsets[v]] >> shifts[v]); FLINT_ASSERT(next_e < es[v]); fq_zech_poly_pow(E + v + 1, alphas + v, es[v] - next_e, ctx); fq_zech_poly_mul(E + v, E + v, E + v + 1, ctx); es[v] = next_e; starts[v] = stops[v]; goto next; } else { fq_zech_poly_pow(E + v + 1, alphas + v, es[v], ctx); fq_zech_poly_mul(E + v, E + v, E + v + 1, ctx); } if (v > var) { v--; goto calculate_return; } return 1; } void _fq_zech_mpoly_eval_to_bpoly( fq_zech_bpoly_t E, const fq_zech_mpoly_t A, const fq_zech_poly_struct * alphabetas, const fq_zech_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong * offsets, * shifts; slong offset, shift; slong start, stop; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * starts, * ends, * stops; ulong * es; fq_zech_poly_struct * realE; E->length = 0; if (A->length < 1) return; starts = FLINT_ARRAY_ALLOC(n, slong); ends = FLINT_ARRAY_ALLOC(n, slong); stops = FLINT_ARRAY_ALLOC(n, slong); es = FLINT_ARRAY_ALLOC(n, ulong); realE = FLINT_ARRAY_ALLOC(n + 1, fq_zech_poly_struct); for (i = 0; i < n + 1; i++) fq_zech_poly_init(realE + i, ctx->fqctx); offsets = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); shifts = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); for (i = 0; i < ctx->minfo->nvars; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, A->bits, ctx->minfo); offset = offsets[0]; shift = shifts[0]; start = 0; e = mask & (A->exps[N*start + offset] >> shift); next: FLINT_ASSERT(start < A->length); FLINT_ASSERT(e == (mask & (A->exps[N*start + offset] >> shift))); stop = start + 1; while (stop < A->length && (mask & (A->exps[N*stop + offset] >> shift)) == e) stop++; fq_zech_bpoly_fit_length(E, e + 1, ctx->fqctx); while (E->length <= e) { fq_zech_poly_zero(E->coeffs + E->length, ctx->fqctx); E->length++; } _fq_zech_mpoly_eval_rest_fq_zech_poly(realE, starts, ends, stops, es, A->coeffs + start, A->exps + N*start, stop - start, 1, alphabetas, offsets, shifts, N, mask, ctx->minfo->nvars, ctx->fqctx); fq_zech_poly_set(E->coeffs + e, realE + 0, ctx->fqctx); if (stop < A->length) { FLINT_ASSERT(e > (mask & (A->exps[N*stop + offset] >> shift))); e = (mask & (A->exps[N*stop + offset] >> shift)); start = stop; goto next; } fq_zech_bpoly_normalise(E, ctx->fqctx); for (i = 0; i < n + 1; i++) fq_zech_poly_clear(realE + i, ctx->fqctx); flint_free(realE); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); } /* A = B(gen(var), 0) */ void _fq_zech_mpoly_set_fq_zech_bpoly_var1_zero( fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_bpoly_t B, slong var, const fq_zech_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; slong Blen = B->length; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += (B->coeffs[i].length > 0); fq_zech_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { FLINT_ASSERT(Alen < A->alloc); fq_zech_bpoly_get_coeff(A->coeffs + Alen, B, i, 0, ctx->fqctx); if (fq_zech_is_zero(A->coeffs + Alen, ctx->fqctx)) continue; if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } flint-3.1.3/src/fq_zech_mpoly_factor/factor.c000066400000000000000000000044441461254215100212470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" #include "fq_nmod_mpoly_factor.h" /* TODO */ int fq_zech_mpoly_factor_algo( fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i; fq_nmod_mpoly_ctx_t ctx2; fq_nmod_mpoly_t A2; fq_nmod_mpoly_factor_t f2; *ctx2->minfo = *ctx->minfo; *ctx2->fqctx = *ctx->fqctx->fq_nmod_ctx; fq_nmod_mpoly_init(A2, ctx2); fq_nmod_mpoly_factor_init(f2, ctx2); _fq_zech_mpoly_get_fq_nmod_mpoly(A2, ctx2, A, ctx); success = fq_nmod_mpoly_factor_algo(f2, A2, ctx2, algo); if (success) { fq_zech_set_fq_nmod(f->constant, f2->constant, ctx->fqctx); fq_zech_mpoly_factor_fit_length(f, f2->num, ctx); for (i = 0; i < f2->num; i++) { _fq_zech_mpoly_set_fq_nmod_mpoly(f->poly + i, ctx, f2->poly + i, ctx2); fmpz_swap(f->exp + i, f2->exp + i); } f->num = f2->num; } fq_nmod_mpoly_clear(A2, ctx2); fq_nmod_mpoly_factor_clear(f2, ctx2); return success; } int fq_zech_mpoly_factor( fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return fq_zech_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ALL); } int fq_zech_mpoly_factor_zassenhaus( fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return fq_zech_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZAS); } int fq_zech_mpoly_factor_wang( fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return fq_zech_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_WANG); } int fq_zech_mpoly_factor_zippel( fq_zech_mpoly_factor_t f, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { return fq_zech_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZIP); } flint-3.1.3/src/fq_zech_mpoly_factor/fit_length.c000066400000000000000000000012601461254215100221050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" void fq_zech_mpoly_factor_fit_length( fq_zech_mpoly_factor_t f, slong len, const fq_zech_mpoly_ctx_t ctx) { if (len > f->alloc) { if (len < 2 * f->alloc) len = 2 * f->alloc; fq_zech_mpoly_factor_realloc(f, len, ctx); } } flint-3.1.3/src/fq_zech_mpoly_factor/get_set_is_fq_nmod_poly.c000066400000000000000000000071071461254215100246630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_mpoly_factor.h" int fq_zech_mpoly_is_fq_zech_poly( const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx) { return mpoly_is_poly(A->exps, A->length, A->bits, var, ctx->minfo); } int fq_zech_mpoly_get_fq_zech_poly( fq_zech_poly_t A, const fq_zech_mpoly_t B, slong var, const fq_zech_mpoly_ctx_t ctx) { slong Blen = B->length; const fq_zech_struct * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t Bbits = B->bits; slong i, N = mpoly_words_per_exp(Bbits, ctx->minfo); ulong k; fq_zech_poly_zero(A, ctx->fqctx); if (B->length < 1) return 1; if (Bbits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - Bbits); slong off, shift; mpoly_gen_offset_shift_sp(&off, &shift, var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; fq_zech_poly_set_coeff(A, k, Bcoeffs + i, ctx->fqctx); } return 1; } else { slong j, off; ulong check, wpf = Bbits/FLINT_BITS; off = mpoly_gen_offset_mp(var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = Bexps[N*i + off + 0]; check = 0; for (j = 1; j < wpf; j++) check |= Bexps[N*i + off + j]; if (check != 0 || (slong) k < 0) return 0; fq_zech_poly_set_coeff(A, k, Bcoeffs + i, ctx->fqctx); } return 1; } } void _fq_zech_mpoly_set_fq_zech_poly( fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_struct * Bcoeffs, slong Blen, slong var, const fq_zech_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += !fq_zech_is_zero(Bcoeffs + i, ctx->fqctx); fq_zech_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { if (fq_zech_is_zero(Bcoeffs + i, ctx->fqctx)) continue; FLINT_ASSERT(Alen < A->alloc); fq_zech_set(A->coeffs + Alen, Bcoeffs + i, ctx->fqctx); if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } void fq_zech_mpoly_set_fq_zech_poly( fq_zech_mpoly_t A, const fq_zech_poly_t B, slong var, const fq_zech_mpoly_ctx_t ctx) { flint_bitcnt_t bits; if (B->length < 1) { fq_zech_mpoly_zero(A, ctx); return; } bits = mpoly_gen_pow_exp_bits_required(var, B->length - 1, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); _fq_zech_mpoly_set_fq_zech_poly(A, bits, B->coeffs, B->length, var, ctx); } flint-3.1.3/src/fq_zech_mpoly_factor/get_set_lead0.c000066400000000000000000000025361461254215100224700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" void _fq_zech_mpoly_get_lead0( fq_zech_mpoly_t c, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong dummyvars[] = {0}; ulong dummydegs[] = {0}; dummyvars[0] = 0; dummydegs[0] = fq_zech_mpoly_degree_si(A, 0, ctx); fq_zech_mpoly_get_coeff_vars_ui(c, A, dummyvars, dummydegs, 1, ctx); } void _fq_zech_mpoly_set_lead0( fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t c, const fq_zech_mpoly_ctx_t ctx) { slong deg; fq_zech_mpoly_t t, g; fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_init(g, ctx); deg = fq_zech_mpoly_degree_si(B, 0, ctx); FLINT_ASSERT(deg >= 0); fq_zech_mpoly_gen(g, 0, ctx); fq_zech_mpoly_pow_ui(g, g, deg, ctx); _fq_zech_mpoly_get_lead0(t, B, ctx); fq_zech_mpoly_sub(t, c, t, ctx); fq_zech_mpoly_mul(t, t, g, ctx); fq_zech_mpoly_add(A, B, t, ctx); fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(g, ctx); } flint-3.1.3/src/fq_zech_mpoly_factor/init.c000066400000000000000000000015111461254215100207240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_mpoly_factor.h" void fq_zech_mpoly_factor_init( fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx) { fq_zech_init(f->constant, ctx->fqctx); fq_zech_one(f->constant, ctx->fqctx); f->poly = NULL; f->exp = NULL; f->num = 0; f->alloc = 0; } void fq_zech_mpoly_factor_one(fq_zech_mpoly_factor_t a, const fq_zech_mpoly_ctx_t ctx) { fq_zech_one(a->constant, ctx->fqctx); a->num = 0; } flint-3.1.3/src/fq_zech_mpoly_factor/io.c000066400000000000000000000072071461254215100204000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" void fq_zech_mpoly_factor_print_pretty( const fq_zech_mpoly_factor_t f, const char ** vars, const fq_zech_mpoly_ctx_t ctx) { slong i; flint_printf("("); fq_zech_print_pretty(f->constant, ctx->fqctx); flint_printf(")"); for (i = 0; i < f->num; i++) { flint_printf("\n*(", i); fq_zech_mpoly_print_pretty(f->poly + i, vars, ctx); flint_printf(")^"); fmpz_print(f->exp + i); } } void fq_zech_polyu3_print_pretty( const fq_zech_polyu_t A, const char * var0, const char * var1, const char * var2, const fq_zech_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; fq_zech_print_pretty(A->coeffs + i, ctx); flint_printf("%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } void fq_zech_bpoly_print_pretty( const fq_zech_bpoly_t A, const char * var0, const char * var1, const fq_zech_ctx_t ctx) { slong i; int first; first = 1; for (i = A->length - 1; i >= 0; i--) { if (fq_zech_poly_is_zero(A->coeffs + i, ctx)) continue; if (!first) flint_printf(" + "); first = 0; flint_printf("("); fq_zech_poly_print_pretty(A->coeffs + i, var1, ctx); flint_printf(")*%s^%wd", var0, i); } if (first) flint_printf("0"); } void fq_zech_mpolyv_print_pretty( const fq_zech_mpolyv_t poly, const char ** x, const fq_zech_mpoly_ctx_t ctx) { slong i; for (i = 0; i < poly->length; i++) { flint_printf("coeff[%wd]: ", i); fq_zech_mpoly_print_pretty(poly->coeffs + i, x, ctx); flint_printf("\n"); } } void fq_zech_polyu2n_print_pretty( const fq_zech_polyun_t A, const char * var0, const char * var1, const char * varlast, const fq_zech_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); fq_zech_poly_print_pretty(A->coeffs + i, varlast, ctx); flint_printf(")*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 1, 2), var1, extract_exp(A->exps[i], 0, 2)); } if (first) flint_printf("0"); } void fq_zech_polyu3n_print_pretty( const fq_zech_polyun_t A, const char * var0, const char * var1, const char * var2, const char * varlast, const fq_zech_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); fq_zech_poly_print_pretty(A->coeffs + i, varlast, ctx); flint_printf(")*%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } flint-3.1.3/src/fq_zech_mpoly_factor/irred_smprime_wang.c000066400000000000000000000214571461254215100236510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #include "fq_zech_mpoly_factor.h" int fq_zech_mpoly_factor_irred_smprime_wang( fq_zech_mpolyv_t fac, const fq_zech_mpoly_t A, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_mpoly_t lcA, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state) { int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; fq_zech_struct * alpha; fq_zech_poly_struct * alphabetas; fq_zech_mpoly_struct * Aevals; slong * degs, * degeval; fq_zech_mpolyv_t tfac; fq_zech_mpoly_t t, Acopy; fq_zech_mpoly_struct * newA; fq_zech_poly_t Abfc; fq_zech_bpoly_t Ab; fq_zech_tpoly_t Abfp; fq_zech_mpoly_t m, mpow; fq_zech_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(fq_zech_is_one(A->coeffs + 0, ctx->fqctx)); FLINT_ASSERT(A->bits <= FLINT_BITS); fq_zech_mpoly_init(Acopy, ctx); fq_zech_mpoly_init(m, ctx); fq_zech_mpoly_init(mpow, ctx); fq_zech_mpolyv_init(new_lcs, ctx); fq_zech_mpolyv_init(lc_divs, ctx); fq_zech_poly_init(Abfc, ctx->fqctx); fq_zech_tpoly_init(Abfp, ctx->fqctx); fq_zech_bpoly_init(Ab, ctx->fqctx); degs = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); alpha = FLINT_ARRAY_ALLOC(n, fq_zech_struct); alphabetas = FLINT_ARRAY_ALLOC(n, fq_zech_poly_struct); Aevals = FLINT_ARRAY_ALLOC(n, fq_zech_mpoly_struct); for (i = 0; i < n; i++) { fq_zech_init(alpha + i, ctx->fqctx); fq_zech_poly_init(alphabetas + i, ctx->fqctx); fq_zech_mpoly_init(Aevals + i, ctx); } fq_zech_mpolyv_init(tfac, ctx); fq_zech_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; fq_zech_mpoly_degrees_si(degs, A, ctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) { fq_zech_rand(alpha + i, state, ctx->fqctx); } for (i = n - 1; i >= 0; i--) { fq_zech_mpoly_evaluate_one_fq_zech(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fq_zech_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } fq_zech_mpoly_get_fq_zech_poly(Abfc, Aevals + 0, 0, ctx); if (!fq_zech_poly_is_squarefree(Abfc, ctx->fqctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 10) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { fq_zech_poly_fit_length(alphabetas + i, alphabetas_length, ctx->fqctx); fq_zech_set(alphabetas[i].coeffs + 0, alpha + i, ctx->fqctx); for (j = 1; j < alphabetas_length; j++) fq_zech_rand(alphabetas[i].coeffs + j, state, ctx->fqctx); alphabetas[i].length = alphabetas_length; _fq_zech_poly_normalise(alphabetas + i, ctx->fqctx); } _fq_zech_mpoly_eval_to_bpoly(Ab, A, alphabetas, ctx); success = fq_zech_bpoly_factor_smprime(Abfc, Abfp, Ab, 0, ctx->fqctx); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { fq_zech_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_zech_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } fq_zech_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = fq_zech_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) fq_zech_mpoly_one(lc_divs->coeffs + i, ctx); } success = fq_zech_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = fq_zech_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } fq_zech_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fq_zech_mpoly_is_one(mpow, ctx)) { newA = (fq_zech_mpoly_struct *) A; } else { newA = Acopy; fq_zech_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } fq_zech_mpoly_degrees_si(degs, newA, ctx); fq_zech_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fq_zech_mpoly_evaluate_one_fq_zech(t, mpow, i + 1, alpha + i, ctx); fq_zech_mpoly_swap(t, mpow, ctx); fq_zech_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); } fq_zech_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fq_zech_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fq_zech_mpoly_evaluate_one_fq_zech(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fq_zech_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { fq_zech_t q; fq_zech_init(q, ctx->fqctx); FLINT_ASSERT(fq_zech_mpoly_is_fq_zech(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fq_zech_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _fq_zech_mpoly_set_fq_zech_bpoly_var1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); fq_zech_inv(q, fac->coeffs[i].coeffs + 0, ctx->fqctx); fq_zech_mul(q, q, new_lcs->coeffs[0*r + i].coeffs + 0, ctx->fqctx); fq_zech_mpoly_scalar_mul_fq_zech(fac->coeffs + i, fac->coeffs + i, q, ctx); fq_zech_clear(q, ctx->fqctx); } fq_zech_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _fq_zech_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } success = fq_zech_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); if (!success) goto next_alphabetas; fq_zech_mpolyv_swap(tfac, fac, ctx); } if (!fq_zech_mpoly_is_fq_zech(m, ctx)) { fq_zech_mpoly_univar_t u; fq_zech_mpoly_univar_init(u, ctx); for (i = 0; i < r; i++) { fq_zech_mpoly_to_univar(u, fac->coeffs + i, 0, ctx); success = fq_zech_mpoly_univar_content_mpoly(t, u, ctx); if (!success) { fq_zech_mpoly_univar_clear(u, ctx); goto cleanup; } success = fq_zech_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } fq_zech_mpoly_univar_clear(u, ctx); } for (i = 0; i < r; i++) fq_zech_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); success = 1; cleanup: fq_zech_mpolyv_clear(new_lcs, ctx); fq_zech_mpolyv_clear(lc_divs, ctx); fq_zech_bpoly_clear(Ab, ctx->fqctx); fq_zech_poly_clear(Abfc, ctx->fqctx); fq_zech_tpoly_clear(Abfp, ctx->fqctx); for (i = 0; i < n; i++) { fq_zech_mpoly_clear(Aevals + i, ctx); fq_zech_poly_clear(alphabetas + i, ctx->fqctx); } flint_free(alphabetas); flint_free(alpha); flint_free(Aevals); flint_free(degs); flint_free(degeval); fq_zech_mpolyv_clear(tfac, ctx); fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(Acopy, ctx); fq_zech_mpoly_clear(m, ctx); fq_zech_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { fq_zech_mpoly_t prod; fq_zech_mpoly_init(prod, ctx); fq_zech_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) fq_zech_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(prod, A, ctx)); fq_zech_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/fq_zech_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000264201461254215100250740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fmpz_poly_factor.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #include "fq_zech_mpoly_factor.h" /* return: 1: success 0: lift is impossible -1: failed, don't try again */ static int _try_lift( fq_zech_mpolyv_t qfac, const fq_zech_mpoly_t q, const fq_zech_mpolyv_t pfac, const fq_zech_mpoly_t p, slong m, fq_zech_struct * alpha, slong n, const fq_zech_mpoly_ctx_t ctx) { int success; slong i; slong * newdeg; fq_zech_mpoly_t lcq, lcp, t, newq; fq_zech_mpoly_univar_t u; FLINT_ASSERT(pfac->length > 1); newdeg = (slong *) flint_malloc((n + 1)*sizeof(slong)); fq_zech_mpoly_init(lcq, ctx); fq_zech_mpoly_init(lcp, ctx); fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_init(newq, ctx); fq_zech_mpoly_univar_init(u, ctx); #if FLINT_WANT_ASSERT fq_zech_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fq_zech_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(t, p, ctx)); #endif _fq_zech_mpoly_get_lead0(lcq, q, ctx); fq_zech_mpoly_evaluate_one_fq_zech(lcp, lcq, m, alpha + m - 1, ctx); FLINT_ASSERT(lcp->length > 0); fq_zech_mpoly_pow_ui(t, lcq, pfac->length - 1, ctx); fq_zech_mpoly_mul(newq, q, t, ctx); if (newq->bits > FLINT_BITS) { success = -1; goto cleanup; } fq_zech_mpoly_degrees_si(newdeg, newq, ctx); fq_zech_mpolyv_fit_length(qfac, pfac->length, ctx); qfac->length = pfac->length; for (i = 0; i < pfac->length; i++) { _fq_zech_mpoly_get_lead0(t, pfac->coeffs + i, ctx); success = fq_zech_mpoly_divides(t, lcp, t, ctx); FLINT_ASSERT(success); fq_zech_mpoly_mul(qfac->coeffs + i, pfac->coeffs + i, t, ctx); _fq_zech_mpoly_set_lead0(qfac->coeffs + i, qfac->coeffs + i, lcq, ctx); } success = fq_zech_mpoly_hlift(m, qfac->coeffs, qfac->length, alpha, newq, newdeg, ctx); if (!success) goto cleanup; for (i = 0; i < qfac->length; i++) { fq_zech_mpoly_to_univar(u, qfac->coeffs + i, 0, ctx); success = fq_zech_mpoly_univar_content_mpoly(t, u, ctx); if (!success) { success = -1; goto cleanup; } success = fq_zech_mpoly_divides(qfac->coeffs + i, qfac->coeffs + i, t, ctx); FLINT_ASSERT(success); fq_zech_mpoly_make_monic(qfac->coeffs + i, qfac->coeffs + i, ctx); } success = 1; cleanup: flint_free(newdeg); fq_zech_mpoly_clear(lcq, ctx); fq_zech_mpoly_clear(lcp, ctx); fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(newq, ctx); fq_zech_mpoly_univar_clear(u, ctx); #if FLINT_WANT_ASSERT if (success > 0) { fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_one(t, ctx); for (i = 0; i < qfac->length; i++) fq_zech_mpoly_mul(t, t, qfac->coeffs + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(t, q, ctx)); fq_zech_mpoly_clear(t, ctx); } #endif return success; } /* return: 1: success 0: failed, may try again -1: failed, don't try again */ int fq_zech_mpoly_factor_irred_smprime_zassenhaus( fq_zech_mpolyv_t fac, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state) { int tries_left = 10; int success; const slong n = ctx->minfo->nvars - 1; slong i, j, k, m, len; slong * subset; fq_zech_struct * alpha; fq_zech_mpoly_struct * Aevals; slong * deg, * degeval; fq_zech_mpolyv_t qfac, pfac, tfac, dfac; fq_zech_mpoly_t t, p, q; fq_zech_mpoly_univar_t u; fq_zech_poly_t c; fq_zech_bpoly_t B; fq_zech_tpoly_t F; subset = (slong*) flint_malloc(4*sizeof(slong)); alpha = FLINT_ARRAY_ALLOC(n, fq_zech_struct); for (i = 0; i < n; i++) fq_zech_init(alpha + i, ctx->fqctx); deg = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); Aevals = FLINT_ARRAY_ALLOC(n, fq_zech_mpoly_struct); for (i = 0; i < n; i++) fq_zech_mpoly_init(Aevals + i, ctx); fq_zech_mpolyv_init(pfac, ctx); fq_zech_mpolyv_init(qfac, ctx); fq_zech_mpolyv_init(tfac, ctx); fq_zech_mpolyv_init(dfac, ctx); fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_init(p, ctx); fq_zech_mpoly_init(q, ctx); fq_zech_mpoly_univar_init(u, ctx); fq_zech_poly_init(c, ctx->fqctx); fq_zech_bpoly_init(B, ctx->fqctx); fq_zech_tpoly_init(F, ctx->fqctx); fq_zech_mpoly_degrees_si(deg, A, ctx); goto got_alpha; next_alpha: tries_left--; if (tries_left < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) fq_zech_rand(alpha + i, state, ctx->fqctx); got_alpha: /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { fq_zech_mpoly_evaluate_one_fq_zech(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fq_zech_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) { if (degeval[j] != deg[j]) goto next_alpha; } } fq_zech_mpoly_get_fq_zech_poly(c, Aevals + 0, 0, ctx); if (!fq_zech_poly_is_squarefree(c, ctx->fqctx)) goto next_alpha; /* make evaluations primitive */ for (i = n - 1; i > 0; i--) { fq_zech_mpoly_to_univar(u, Aevals + i, 0, ctx); success = fq_zech_mpoly_univar_content_mpoly(t, u, ctx); if (!success) goto cleanup; success = fq_zech_mpoly_divides(Aevals + i, Aevals + i, t, ctx); FLINT_ASSERT(success); fq_zech_mpoly_make_monic(Aevals + i, Aevals + i, ctx); } fq_zech_mpoly_get_fq_zech_bpoly(B, Aevals + 1, 0, 1, ctx); success = fq_zech_bpoly_factor_smprime(c, F, B, 1, ctx->fqctx); if (!success) goto next_alpha; FLINT_ASSERT(fq_zech_poly_degree(c, ctx->fqctx) == 0); fq_zech_mpolyv_fit_length(pfac, F->length, ctx); pfac->length = F->length; for (i = 0; i < F->length; i++) { fq_zech_mpoly_set_fq_zech_bpoly(pfac->coeffs + i, A->bits, F->coeffs + i, 0, 1, ctx); fq_zech_mpoly_make_monic(pfac->coeffs + i, pfac->coeffs + i, ctx); } for (m = 2; m <= n; m++) { fq_zech_mpoly_set(q, m < n ? Aevals + m : A, ctx); fq_zech_mpoly_set(p, Aevals + m - 1, ctx); #if FLINT_WANT_ASSERT fq_zech_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) fq_zech_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(t, p, ctx)); #endif if (pfac->length < 2) { fq_zech_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_zech_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } success = _try_lift(qfac, q, pfac, p, m, alpha, n, ctx); if (success > 0) { fq_zech_mpolyv_swap(qfac, pfac, ctx); continue; } else if (success < 0) { goto cleanup; } if (pfac->length == 2) { fq_zech_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_zech_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } qfac->length = 0; len = pfac->length; for (k = 0; k < len; k++) subset[k] = k; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); #if FLINT_WANT_ASSERT fq_zech_mpoly_one(t, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fq_zech_mpoly_mul(t, t, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } FLINT_ASSERT(fq_zech_mpoly_equal(t, p, ctx)); #endif while (1) { fq_zech_mpolyv_fit_length(dfac, 2, ctx); dfac->length = 2; fq_zech_mpoly_one(dfac->coeffs + 0, ctx); fq_zech_mpoly_one(dfac->coeffs + 1, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; fq_zech_mpoly_mul(dfac->coeffs + in, dfac->coeffs + in, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } success = _try_lift(tfac, q, dfac, p, m, alpha, n, ctx); if (success > 0) { fq_zech_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fq_zech_mpoly_swap(qfac->coeffs + qfac->length, tfac->coeffs + 1, ctx); qfac->length++; fq_zech_mpoly_swap(q, tfac->coeffs + 0, ctx); fq_zech_mpoly_swap(p, dfac->coeffs + 0, ctx); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else if (success < 0) { success = 0; goto cleanup; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } /* remnants are irreducible */ if (!fq_zech_mpoly_is_fq_zech(q, ctx)) { fq_zech_mpolyv_fit_length(qfac, qfac->length + 1, ctx); fq_zech_mpoly_swap(qfac->coeffs + qfac->length, q, ctx); qfac->length++; } else { FLINT_ASSERT(fq_zech_mpoly_is_one(q, ctx)); } fq_zech_mpolyv_swap(qfac, pfac, ctx); } success = 1; fq_zech_mpolyv_swap(fac, pfac, ctx); cleanup: flint_free(subset); for (i = 0; i < n; i++) fq_zech_clear(alpha + i, ctx->fqctx); flint_free(alpha); for (i = 0; i < n; i++) fq_zech_mpoly_clear(Aevals + i, ctx); flint_free(Aevals); flint_free(deg); flint_free(degeval); fq_zech_mpolyv_clear(pfac, ctx); fq_zech_mpolyv_clear(qfac, ctx); fq_zech_mpolyv_clear(tfac, ctx); fq_zech_mpolyv_clear(dfac, ctx); fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(p, ctx); fq_zech_mpoly_clear(q, ctx); fq_zech_mpoly_univar_clear(u, ctx); fq_zech_poly_clear(c, ctx->fqctx); fq_zech_bpoly_clear(B, ctx->fqctx); fq_zech_tpoly_clear(F, ctx->fqctx); FLINT_ASSERT(success == 0 || success == 1); #if FLINT_WANT_ASSERT if (success) { fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_one(t, ctx); for (i = 0; i < fac->length; i++) fq_zech_mpoly_mul(t, t, fac->coeffs + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(t, A, ctx)); fq_zech_mpoly_clear(t, ctx); } #endif return success; } flint-3.1.3/src/fq_zech_mpoly_factor/irred_smprime_zippel.c000066400000000000000000001160621461254215100242150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #include "n_poly.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" static void fq_zech_mpoly_delete_duplicate_terms( fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx) { slong i, j; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); j = -1; for (i = 0; i < A->length; i++) { if (j >= 0 && mpoly_monomial_equal(A->exps + N*j, A->exps + N*i, N)) { FLINT_ASSERT(fq_zech_equal(A->coeffs + j, A->coeffs + i, ctx->fqctx)); continue; } j++; fq_zech_set(A->coeffs + j, A->coeffs + i, ctx->fqctx); mpoly_monomial_set(A->exps + N*j, A->exps + N*i, N); } j++; A->length = j; } slong fq_zech_mpolyu_find_term(const fq_zech_mpolyu_t A, ulong e) { slong i; for (i = 0; i < A->length; i++) if (A->exps[i] == e) return i; return -1; } void fq_zech_poly_product_roots(fq_zech_poly_t P, fq_zech_struct * r, slong n, const fq_zech_ctx_t fqctx) { slong i; fq_zech_poly_t B; fq_zech_t a; fq_zech_init(a, fqctx); fq_zech_poly_init(B, fqctx); fq_zech_poly_one(P, fqctx); fq_zech_poly_gen(B, fqctx); for (i = 0; i < n; i++) { fq_zech_neg(a, r + i, fqctx); fq_zech_poly_set_coeff(B, 0, a, fqctx); fq_zech_poly_mul(P, P, B, fqctx); } fq_zech_clear(a, fqctx); fq_zech_poly_clear(B, fqctx); } fq_zech_mpoly_struct * _fq_zech_mpolyu_get_coeff(fq_zech_mpolyu_t A, ulong pow, const fq_zech_mpoly_ctx_t uctx); void _fq_zech_mpoly_monomial_evals( fq_zech_struct * E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const fq_zech_struct * alpha, slong vstart, const fq_zech_mpoly_ctx_t ctx) { slong i, j; slong offset, shift; slong N = mpoly_words_per_exp_sp(Abits, ctx->minfo); slong nvars = ctx->minfo->nvars; slong * LUToffset; ulong * LUTmask; fq_zech_struct * LUTvalue; slong LUTlen; fq_zech_t xpoweval; ulong * inputexpmask; inputexpmask = FLINT_ARRAY_ALLOC(N, ulong); LUToffset = FLINT_ARRAY_ALLOC(N*FLINT_BITS, slong); LUTmask = FLINT_ARRAY_ALLOC(N*FLINT_BITS, ulong); LUTvalue = FLINT_ARRAY_ALLOC(N*FLINT_BITS, fq_zech_struct); for (i = 0; i < N*FLINT_BITS; i++) fq_zech_init(LUTvalue + i, ctx->fqctx); fq_zech_init(xpoweval, ctx->fqctx); mpoly_monomial_zero(inputexpmask, N); for (i = 0; i < Alen; i++) { for (j = 0; j < N; j++) { inputexpmask[j] |= (Aexps + N*i)[j]; } } LUTlen = 0; for (j = nvars - 1; j >= vstart; j--) { mpoly_gen_offset_shift_sp(&offset, &shift, j, Abits, ctx->minfo); fq_zech_set(xpoweval, alpha + j, ctx->fqctx); /* xpoweval = alpha[i]^(2^i) */ for (i = 0; i < Abits; i++) { LUToffset[LUTlen] = offset; LUTmask[LUTlen] = (UWORD(1) << (shift + i)); fq_zech_set(LUTvalue + LUTlen, xpoweval, ctx->fqctx); if ((inputexpmask[offset] & LUTmask[LUTlen]) != 0) LUTlen++; fq_zech_mul(xpoweval, xpoweval, xpoweval, ctx->fqctx); } } FLINT_ASSERT(LUTlen < N*FLINT_BITS); for (i = 0; i < Alen; i++) { fq_zech_one(xpoweval, ctx->fqctx); for (j = 0; j < LUTlen; j++) { if (((Aexps + N*i)[LUToffset[j]] & LUTmask[j]) != 0) { fq_zech_mul(xpoweval, xpoweval, LUTvalue + j, ctx->fqctx); } } fq_zech_set(E + i, xpoweval, ctx->fqctx); } flint_free(inputexpmask); flint_free(LUToffset); flint_free(LUTmask); flint_free(LUTvalue); } static void _fq_zech_mpoly_monomial_evals_indirect( fq_zech_struct * E, const ulong * Aexps, flint_bitcnt_t Abits, ulong * Aind, slong Alen, const fq_zech_struct * alpha, slong vstart, slong vstop, const fq_zech_mpoly_ctx_t ctx) { slong i, j; slong offset, shift; slong N = mpoly_words_per_exp_sp(Abits, ctx->minfo); slong * LUToffset; ulong * LUTmask; fq_zech_struct * LUTvalue; slong LUTlen; fq_zech_t xpoweval; ulong * inputexpmask; const ulong * thisAexp; FLINT_ASSERT(0 <= vstart); FLINT_ASSERT(vstart < vstop); FLINT_ASSERT(vstop <= ctx->minfo->nvars); inputexpmask = FLINT_ARRAY_ALLOC(N, ulong); LUToffset = FLINT_ARRAY_ALLOC(N*FLINT_BITS, slong); LUTmask = FLINT_ARRAY_ALLOC(N*FLINT_BITS, ulong); LUTvalue = FLINT_ARRAY_ALLOC(N*FLINT_BITS, fq_zech_struct); for (i = 0; i < N*FLINT_BITS; i++) fq_zech_init(LUTvalue + i, ctx->fqctx); fq_zech_init(xpoweval, ctx->fqctx); mpoly_monomial_zero(inputexpmask, N); for (i = 0; i < Alen; i++) { thisAexp = Aexps + N*Aind[i]; for (j = 0; j < N; j++) inputexpmask[j] |= thisAexp[j]; } LUTlen = 0; for (j = vstop - 1; j >= vstart; j--) { mpoly_gen_offset_shift_sp(&offset, &shift, j, Abits, ctx->minfo); fq_zech_set(xpoweval, alpha + j, ctx->fqctx); /* xpoweval = alpha[i]^(2^i) */ for (i = 0; i < Abits; i++) { LUToffset[LUTlen] = offset; LUTmask[LUTlen] = (UWORD(1) << (shift + i)); fq_zech_set(LUTvalue + LUTlen, xpoweval, ctx->fqctx); if ((inputexpmask[offset] & LUTmask[LUTlen]) != 0) LUTlen++; fq_zech_mul(xpoweval, xpoweval, xpoweval, ctx->fqctx); } } FLINT_ASSERT(LUTlen < N*FLINT_BITS); for (i = 0; i < Alen; i++) { thisAexp = Aexps + N*Aind[i]; fq_zech_one(xpoweval, ctx->fqctx); for (j = 0; j < LUTlen; j++) { if ((thisAexp[LUToffset[j]] & LUTmask[j]) != 0) { fq_zech_mul(xpoweval, xpoweval, LUTvalue + j, ctx->fqctx); } } fq_zech_set(E + i, xpoweval, ctx->fqctx); } flint_free(inputexpmask); flint_free(LUToffset); flint_free(LUTmask); flint_free(LUTvalue); } int fq_zech_zip_find_coeffs_new( fq_zech_struct * coeffs, /* length mlength */ const fq_zech_struct * monomials, /* length mlength */ slong mlength, const fq_zech_struct * evals, /* length elength */ slong elength, const fq_zech_struct * master, /* length (mlength + 1) */ fq_zech_struct * temp, /* length mlength */ const fq_zech_ctx_t ctx) { int success; slong i, j; fq_zech_t V, V0, T, S, r, p0; fq_zech_init(V, ctx); fq_zech_init(V0, ctx); fq_zech_init(T, ctx); fq_zech_init(S, ctx); fq_zech_init(r, ctx); fq_zech_init(p0, ctx); FLINT_ASSERT(elength >= mlength); for (i = 0; i < mlength; i++) { /* coeffs[i] is (coeffs(P).values)/P(roots[i]) =: V/S where P(x) = master(x)/(x-roots[i]) */ fq_zech_zero(V0, ctx); fq_zech_zero(T, ctx); fq_zech_zero(S, ctx); fq_zech_set(r, monomials + i, ctx); for (j = mlength; j > 0; j--) { fq_zech_mul(T, r, T, ctx); fq_zech_add(T, T, master + j, ctx); fq_zech_mul(S, r, S, ctx); fq_zech_add(S, S, T, ctx); fq_zech_mul(p0, evals + (j - 1), T, ctx); fq_zech_add(V0, V0, p0, ctx); } /* roots[i] should be a root of master */ #if FLINT_WANT_ASSERT fq_zech_mul(p0, r, T, ctx); fq_zech_add(p0, p0, master + 0, ctx); FLINT_ASSERT(fq_zech_is_zero(p0, ctx)); #endif fq_zech_set(V, V0, ctx); fq_zech_mul(S, S, r, ctx); if (fq_zech_is_zero(S, ctx)) { success = -1; goto cleanup; } fq_zech_inv(p0, S, ctx); fq_zech_mul(coeffs + i, V, p0, ctx); } /* check that the remaining points match */ for (j = 0; j < mlength; j++) fq_zech_pow_ui(temp + j, monomials + j, mlength, ctx); for (i = mlength; i < elength; i++) { fq_zech_zero(V0, ctx); fq_zech_zero(S, ctx); for (j = 0; j < mlength; j++) { fq_zech_mul(temp + j, temp + j, monomials + j, ctx); fq_zech_mul(p0, coeffs + j, temp + j, ctx); fq_zech_add(V0, V0, p0, ctx); } fq_zech_set(V, V0, ctx); if (!fq_zech_equal(V, evals + i, ctx)) { success = 0; goto cleanup; } } success = 1; cleanup: fq_zech_clear(V, ctx); fq_zech_clear(V0, ctx); fq_zech_clear(T, ctx); fq_zech_clear(S, ctx); fq_zech_clear(r, ctx); fq_zech_clear(p0, ctx); return success; } static void _clearit( n_polyun_t W, mpoly_rbtree_ui_t T, slong idx) { mpoly_rbnode_ui_struct * nodes = T->nodes + 2; FLINT_ASSERT(0 <= idx && idx < T->length); if (nodes[idx].right >= 0) _clearit(W, T, nodes[idx].right); FLINT_ASSERT(W->length < W->alloc); W->exps[W->length] = nodes[idx].key; W->coeffs[W->length] = ((n_poly_struct *) T->data)[idx]; W->length++; if (nodes[idx].left >= 0) _clearit(W, T, nodes[idx].left); } static void fq_zech_mpoly_set_eval_helper3( fq_zech_polyun_t EH, const fq_zech_mpoly_t A, slong yvar, const fq_zech_struct * alpha, const fq_zech_mpoly_ctx_t ctx) { slong xvar = 0; slong zvar = 1; slong i, j, n; ulong y, x, z; slong yoff, xoff, zoff; slong yshift, xshift, zshift; fq_zech_struct * p; flint_bitcnt_t bits = A->bits; slong Alen = A->length; const ulong * Aexps = A->exps; const fq_zech_struct * Acoeffs = A->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; mpoly_rbtree_ui_t W; n_polyun_init(T); mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Alen; i++) { n_poly_struct * Wc; int its_new; y = (Aexps[N*i + yoff] >> yshift) & mask; x = (Aexps[N*i + xoff] >> xshift) & mask; z = (Aexps[N*i + zoff] >> zshift) & mask; Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); fq_zech_polyun_fit_length(EH, T->length, ctx->fqctx); EH->length = T->length; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; n = T->coeffs[i].length; fq_zech_poly_fit_length(EH->coeffs + i, 3*n, ctx->fqctx); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; _fq_zech_mpoly_monomial_evals_indirect(p, Aexps, bits, ind, n, alpha, 2, yvar, ctx); for (j = n - 1; j >= 0; j--) { fq_zech_set(p + 3*j + 2, p + j, ctx->fqctx); fq_zech_set(p + 3*j + 0, p + 3*j + 2, ctx->fqctx); fq_zech_set(p + 3*j + 1, Acoeffs + ind[j], ctx->fqctx); } } n_polyun_clear(T); } /* for each term Y^y*X^x*Z^z * pol(x1,...) in B with j < deg set Y^0*X^x*Z^z in H as the monomials with the monomial evals as coeffs merge monomial sets coming from different y's (shouldn't happen) */ static slong fq_zech_mpoly_set_eval_helper_and_zip_form3( ulong * deg_, /* deg_X(B), output */ fq_zech_polyun_t EH, fq_zech_mpolyu_t H, const fq_zech_mpoly_t B, const fq_zech_struct * alpha, slong yvar, /* Y = gen(yvar) (X = gen(0), Z = gen(1))*/ const fq_zech_mpoly_ctx_t ctx) { slong xvar = 0; slong zvar = 1; slong i, j, n; ulong y, x, z; fq_zech_struct * p; fq_zech_mpoly_struct * Hc; slong old_len, zip_length = 0; flint_bitcnt_t bits = B->bits; slong Blen = B->length; const ulong * Bexps = B->exps; const fq_zech_struct * Bcoeffs = B->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; ulong deg; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == H->bits); FLINT_ASSERT(Blen > 0); /* init T */ { mpoly_rbtree_ui_t W; n_poly_struct * Wc; slong yoff, xoff, zoff; slong yshift, xshift, zshift; int its_new; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); deg = (Bexps[N*0 + xoff] >> xshift) & mask; mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Blen; i++) { y = (Bexps[N*i + yoff] >> yshift) & mask; x = (Bexps[N*i + xoff] >> xshift) & mask; z = (Bexps[N*i + zoff] >> zshift) & mask; FLINT_ASSERT(x <= deg); Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); } fq_zech_polyun_fit_length(EH, T->length, ctx->fqctx); EH->length = T->length; H->length = 0; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; y = extract_exp(EH->exps[i], 2, 3); x = extract_exp(EH->exps[i], 1, 3); z = extract_exp(EH->exps[i], 0, 3); n = T->coeffs[i].length; fq_zech_poly_fit_length(EH->coeffs + i, 3*n, ctx->fqctx); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; _fq_zech_mpoly_monomial_evals_indirect(p, Bexps, bits, ind, n, alpha, 2, yvar, ctx); if (x < deg) { FLINT_ASSERT(y == 0 && "strange but ok"); Hc = _fq_zech_mpolyu_get_coeff(H, pack_exp3(0, x, z), ctx); fq_zech_mpoly_fit_length(Hc, n, ctx); old_len = Hc->length; for (j = 0; j < n; j++) { fq_zech_set(Hc->coeffs + old_len + j, p + j, ctx->fqctx); mpoly_monomial_set(Hc->exps + N*(old_len + j), Bexps + N*ind[j], N); } Hc->length += n; zip_length = FLINT_MAX(zip_length, Hc->length); if (old_len > 0) { FLINT_ASSERT(0 && "strange but ok"); fq_zech_mpoly_sort_terms(Hc, ctx); fq_zech_mpoly_delete_duplicate_terms(Hc, ctx); } } for (j = n - 1; j >= 0; j--) { fq_zech_set(p + 3*j + 2, p + j, ctx->fqctx); fq_zech_set(p + 3*j + 0, p + 3*j + 2, ctx->fqctx); fq_zech_set(p + 3*j + 1, Bcoeffs + ind[j], ctx->fqctx); } } n_polyun_clear(T); *deg_ = deg; return zip_length; } static void fq_zech_poly_eval_step( fq_zech_t res, fq_zech_poly_t A, const fq_zech_ctx_t ctx) { slong i, Alen = A->length; fq_zech_struct * Acoeffs = A->coeffs; fq_zech_t t; FLINT_ASSERT(3*Alen <= A->alloc); if (Alen < 1) { fq_zech_zero(res, ctx); return; } fq_zech_init(t, ctx); i = 0; fq_zech_mul(res, Acoeffs + (3*i + 0), Acoeffs + (3*i + 1), ctx); fq_zech_mul(Acoeffs + (3*i + 0), Acoeffs + (3*i + 0), Acoeffs + (3*i + 2), ctx); for (i = 1; i < Alen; i++) { fq_zech_mul(t, Acoeffs + (3*i + 0), Acoeffs + (3*i + 1), ctx); fq_zech_add(res, res, t, ctx); fq_zech_mul(Acoeffs + (3*i + 0), Acoeffs + (3*i + 0), Acoeffs + (3*i + 2), ctx); } fq_zech_clear(t, ctx); } void fq_zech_polyu_eval_step( fq_zech_polyu_t E, fq_zech_polyun_t A, const fq_zech_ctx_t ctx) { slong Ai, Ei; fq_zech_polyu_fit_length(E, A->length, ctx); Ei = 0; for (Ai = 0; Ai < A->length; Ai++) { FLINT_ASSERT(Ei < E->alloc); E->exps[Ei] = A->exps[Ai]; fq_zech_poly_eval_step(E->coeffs + Ei, A->coeffs + Ai, ctx); Ei += !fq_zech_is_zero(E->coeffs + Ei, ctx); } E->length = Ei; } void fq_zech_polyu3_add_zip_limit1( fq_zech_polyun_t Z, const fq_zech_polyun_t A, const ulong deg1, slong cur_length, slong fit_length, const fq_zech_ctx_t ctx) { const fq_zech_poly_struct * Acoeffs = A->coeffs; ulong * Aexps = A->exps; fq_zech_poly_struct * Zcoeffs = Z->coeffs; ulong * Zexps = Z->exps; slong Ai, ai, Zi, j; for (Zi = 0; Zi < Z->length; Zi++) { FLINT_ASSERT(Z->coeffs[Zi].length == cur_length); } Ai = -1; ai = -1; do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = fq_zech_poly_degree(Acoeffs + Ai, ctx); Zi = 0; while (Ai < A->length && Zi < Z->length) { if (Aexps[Ai] + ai > Zexps[Zi]) { /* missing from Z */ fq_zech_polyun_fit_length(Z, Z->length + 1, ctx); Zcoeffs = Z->coeffs; Zexps = Z->exps; for (j = Z->length; j > Zi; j--) { fq_zech_poly_swap(Zcoeffs + j, Zcoeffs + j - 1, ctx); FLINT_SWAP(ulong, Zexps[j], Zexps[j - 1]); } Z->length++; Zexps[Zi] = Aexps[Ai] + ai; fq_zech_poly_fit_length(Zcoeffs + Zi, fit_length, ctx); Zcoeffs[Zi].length = cur_length; for (j = 0; j < cur_length; j++) fq_zech_zero(Zcoeffs[Zi].coeffs + j, ctx); goto in_both; } else if (Aexps[Ai] + ai < Zexps[Zi]) { /* missing from A */ FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fq_zech_zero(Zcoeffs[Zi].coeffs + cur_length, ctx); Zcoeffs[Zi].length = cur_length + 1; Zi++; } else { in_both: FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fq_zech_set(Zcoeffs[Zi].coeffs + cur_length, Acoeffs[Ai].coeffs + ai, ctx); Zcoeffs[Zi].length = cur_length + 1; Zi++; do { ai--; } while (ai >= 0 && fq_zech_is_zero(Acoeffs[Ai].coeffs + ai, ctx)); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = fq_zech_poly_degree(Acoeffs + Ai, ctx); } } } /* everything in A must be put on the end of Z */ while (Ai < A->length) { Zi = Z->length; fq_zech_polyun_fit_length(Z, Zi + A->length - Ai, ctx); Zcoeffs = Z->coeffs; Zexps = Z->exps; Zexps[Zi] = Aexps[Ai] + ai; fq_zech_poly_fit_length(Zcoeffs + Zi, fit_length, ctx); Zcoeffs[Zi].length = cur_length; for (j = 0; j < cur_length; j++) fq_zech_zero(Zcoeffs[Zi].coeffs + j, ctx); FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fq_zech_set(Zcoeffs[Zi].coeffs + cur_length, Acoeffs[Ai].coeffs + ai, ctx); Zcoeffs[Zi].length = cur_length + 1; Z->length = ++Zi; do { ai--; } while (ai >= 0 && fq_zech_is_zero(Acoeffs[Ai].coeffs + ai, ctx)); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = fq_zech_poly_degree(Acoeffs + Ai, ctx); } } /* everything in Z must have a zero appended */ while (Zi < Z->length) { FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); fq_zech_zero(Zcoeffs[Zi].coeffs + cur_length, ctx); Zcoeffs[Zi].length = cur_length + 1; Zi++; } for (Zi = 0; Zi < Z->length; Zi++) { FLINT_ASSERT(Z->coeffs[Zi].length == cur_length + 1); } } static int fq_zech_mpoly_from_zip( fq_zech_mpoly_t B, const fq_zech_polyun_t Z, fq_zech_mpolyu_t H, ulong deg, slong yvar, /* Y = gen(yvar) */ const fq_zech_mpoly_ctx_t ctx, fq_zech_polyun_t M) { int success; slong Hi, Zi, Bi, i, j; slong xvar = 0; slong zvar = 1; ulong x, y, z; flint_bitcnt_t bits = B->bits; fq_zech_struct * Bcoeffs; ulong * Bexps; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong xoff, xshift, yoff, yshift, zoff, zshift; fq_zech_mpoly_struct * Hc; slong Hlen = H->length; FLINT_ASSERT(bits == H->bits); fq_zech_polyun_fit_length(M, Hlen + 1, ctx->fqctx); for (i = 0; i <= Hlen; i++) M->coeffs[i].length = 0; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); /* x is most significant in ctx, so keeping the lc_x in B is easy */ FLINT_ASSERT(xvar == 0); for (Bi = 0; Bi < B->length; Bi++) { x = (((B->exps + N*Bi)[xoff] >> xshift) & mask); FLINT_ASSERT(x <= deg); if (x != deg) break; } for (Zi = 0; Zi < Z->length; Zi++) { y = extract_exp(Z->exps[Zi], 2, 3); x = extract_exp(Z->exps[Zi], 1, 3); z = extract_exp(Z->exps[Zi], 0, 3); FLINT_ASSERT(x < deg); Hi = fq_zech_mpolyu_find_term(H, pack_exp3(0, x, z)); if (Hi < 0) return 0; FLINT_ASSERT(Hi < Hlen); FLINT_ASSERT(H->exps[Hi] == pack_exp3(0, x, z)); Hc = H->coeffs + Hi; FLINT_ASSERT(bits == Hc->bits); FLINT_ASSERT(Hc->length > 0); fq_zech_mpoly_fit_length(B, Bi + Hc->length, ctx); Bcoeffs = B->coeffs; if (M->coeffs[Hi].length < 1) { fq_zech_poly_product_roots(M->coeffs + Hi, Hc->coeffs, Hc->length, ctx->fqctx); } fq_zech_poly_fit_length(M->coeffs + Hlen, Hc->length, ctx->fqctx); success = fq_zech_zip_find_coeffs_new(Bcoeffs + Bi, Hc->coeffs, Hc->length, Z->coeffs[Zi].coeffs, Z->coeffs[Zi].length, M->coeffs[Hi].coeffs, M->coeffs[Hlen].coeffs, ctx->fqctx); if (success < 1) return success; Bexps = B->exps; for (j = Bi, i = 0; i < Hc->length; j++, i++) { if (fq_zech_is_zero(Bcoeffs + j, ctx->fqctx)) continue; FLINT_ASSERT(Bi < B->alloc); fq_zech_set(Bcoeffs + Bi, Bcoeffs + j, ctx->fqctx); mpoly_monomial_set(Bexps + N*Bi, Hc->exps + N*i, N); (Bexps + N*Bi)[yoff] += y << yshift; Bi++; } } B->length = Bi; fq_zech_mpoly_sort_terms(B, ctx); FLINT_ASSERT(fq_zech_mpoly_is_canonical(B, ctx)); return 1; } /* bit counts of all degrees should be < FLINT_BITS/3 */ int fq_zech_mpoly_hlift_zippel( slong m, fq_zech_mpoly_struct * B, slong r, const fq_zech_struct * alpha, const fq_zech_mpoly_t A, const slong * degs, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state) { int success; slong i; slong zip_fails_remaining; slong req_zip_images, cur_zip_image; fq_zech_mpolyu_struct * H; fq_zech_polyun_struct M[1], Aeh[1], * Beh, * BBeval, * Z; fq_zech_polyu_struct Aeval[1], * Beval; fq_zech_struct * beta; flint_bitcnt_t bits = A->bits; fq_zech_mpoly_t T1, T2; ulong * Bdegs; const slong degs0 = degs[0]; FLINT_ASSERT(m > 2); FLINT_ASSERT(r > 1); FLINT_ASSERT(bits <= FLINT_BITS); #if FLINT_WANT_ASSERT { fq_zech_mpoly_t T; slong j, * check_degs = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); fq_zech_mpoly_init(T, ctx); fq_zech_mpoly_degrees_si(check_degs, A, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); fq_zech_mpoly_one(T, ctx); for (i = 0; i < r; i++) { fq_zech_mpoly_degrees_si(check_degs, B + i, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); fq_zech_mpoly_mul(T, T, B + i, ctx); } fq_zech_mpoly_sub(T, A, T, ctx); fq_zech_mpoly_evaluate_one_fq_zech(T, T, m, alpha + m - 1, ctx); FLINT_ASSERT(fq_zech_mpoly_is_zero(T, ctx)); fq_zech_mpoly_clear(T, ctx); flint_free(check_degs); } #endif beta = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, fq_zech_struct); for (i = 0; i < ctx->minfo->nvars; i++) fq_zech_init(beta + i, ctx->fqctx); Bdegs = FLINT_ARRAY_ALLOC(r, ulong); H = FLINT_ARRAY_ALLOC(r, fq_zech_mpolyu_struct); Beh = FLINT_ARRAY_ALLOC(r, fq_zech_polyun_struct); Beval = FLINT_ARRAY_ALLOC(r, fq_zech_polyu_struct); BBeval = FLINT_ARRAY_ALLOC(r, fq_zech_polyun_struct); Z = FLINT_ARRAY_ALLOC(r, fq_zech_polyun_struct); fq_zech_polyun_init(Aeh, ctx->fqctx); fq_zech_polyu_init(Aeval, ctx->fqctx); fq_zech_polyun_init(M, ctx->fqctx); for (i = 0; i < r; i++) { fq_zech_mpolyu_init(H + i, bits, ctx); fq_zech_polyun_init(Beh + i, ctx->fqctx); fq_zech_polyu_init(Beval + i, ctx->fqctx); fq_zech_polyun_init(BBeval + i, ctx->fqctx); fq_zech_polyun_init(Z + i, ctx->fqctx); } /* init done */ for (i = 0; i < r; i++) { success = fq_zech_mpoly_repack_bits_inplace(B + i, bits, ctx); if (!success) goto cleanup; } zip_fails_remaining = 3; choose_betas: /* only beta[2], beta[3], ..., beta[m - 1] will be used */ for (i = 0; i < ctx->minfo->nvars; i++) { fq_zech_rand(beta + i, state, ctx->fqctx); if (fq_zech_is_zero(beta + i, ctx->fqctx)) fq_zech_one(beta + i, ctx->fqctx); } fq_zech_mpoly_set_eval_helper3(Aeh, A, m, beta, ctx); req_zip_images = 1; for (i = 0; i < r; i++) { slong this_zip_images; this_zip_images = fq_zech_mpoly_set_eval_helper_and_zip_form3(Bdegs + i, Beh + i, H + i, B + i, beta, m, ctx); req_zip_images = FLINT_MAX(req_zip_images, this_zip_images); FLINT_ASSERT(Bdegs[i] > 0); Z[i].length = 0; } cur_zip_image = 0; next_zip_image: fq_zech_polyu_eval_step(Aeval, Aeh, ctx->fqctx); for (i = 0; i < r; i++) fq_zech_polyu_eval_step(Beval + i, Beh + i, ctx->fqctx); success = fq_zech_polyu3_hlift(r, BBeval, Aeval, Beval, alpha + m - 1, degs0, ctx->fqctx); if (success < 1) { if (--zip_fails_remaining >= 0) goto choose_betas; success = 0; goto cleanup; } for (i = 0; i < r; i++) { fq_zech_polyu3_add_zip_limit1(Z + i, BBeval + i, Bdegs[i], cur_zip_image, req_zip_images, ctx->fqctx); } cur_zip_image++; if (cur_zip_image < req_zip_images) goto next_zip_image; for (i = 0; i < r; i++) { success = fq_zech_mpoly_from_zip(B + i, Z + i, H + i, Bdegs[i], m, ctx, M); if (success < 1) { success = 0; goto cleanup; } } fq_zech_mpoly_init3(T1, A->length, bits, ctx); fq_zech_mpoly_init3(T2, A->length, bits, ctx); fq_zech_mpoly_mul(T1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { fq_zech_mpoly_mul(T2, T1, B + i, ctx); fq_zech_mpoly_swap(T1, T2, ctx); } success = fq_zech_mpoly_equal(T1, A, ctx); fq_zech_mpoly_clear(T1, ctx); fq_zech_mpoly_clear(T2, ctx); cleanup: fq_zech_polyun_clear(Aeh, ctx->fqctx); fq_zech_polyu_clear(Aeval, ctx->fqctx); fq_zech_polyun_clear(M, ctx->fqctx); for (i = 0; i < r; i++) { fq_zech_mpolyu_clear(H + i, ctx); fq_zech_polyun_clear(Beh + i, ctx->fqctx); fq_zech_polyu_clear(Beval + i, ctx->fqctx); fq_zech_polyun_clear(BBeval + i, ctx->fqctx); fq_zech_polyun_clear(Z + i, ctx->fqctx); } for (i = 0; i < ctx->minfo->nvars; i++) fq_zech_clear(beta + i, ctx->fqctx); flint_free(beta); flint_free(Bdegs); flint_free(H); flint_free(Beh); flint_free(Beval); flint_free(BBeval); flint_free(Z); return success; } /* return 1: success 0: failed -1: exception */ int fq_zech_mpoly_factor_irred_smprime_zippel( fq_zech_mpolyv_t fac, const fq_zech_mpoly_t A, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_mpoly_t lcA, const fq_zech_mpoly_ctx_t ctx, flint_rand_t state) { int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; fq_zech_struct * alpha; fq_zech_poly_struct * alphabetas; fq_zech_mpoly_struct * Aevals; slong * degs, * degeval; fq_zech_mpolyv_t tfac; fq_zech_mpoly_t t, Acopy; fq_zech_mpoly_struct * newA; fq_zech_poly_t Abfc; fq_zech_bpoly_t Ab; fq_zech_tpoly_t Abfp; fq_zech_mpoly_t m, mpow; fq_zech_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(fq_zech_is_one(A->coeffs + 0, ctx->fqctx)); FLINT_ASSERT(A->bits <= FLINT_BITS); if (fq_zech_ctx_degree(ctx->fqctx) <= n_clog(A->length, fq_zech_ctx_mod(ctx->fqctx).n)) return 0; fq_zech_mpoly_init(Acopy, ctx); fq_zech_mpoly_init(m, ctx); fq_zech_mpoly_init(mpow, ctx); fq_zech_mpolyv_init(new_lcs, ctx); fq_zech_mpolyv_init(lc_divs, ctx); fq_zech_poly_init(Abfc, ctx->fqctx); fq_zech_tpoly_init(Abfp, ctx->fqctx); fq_zech_bpoly_init(Ab, ctx->fqctx); degs = FLINT_ARRAY_ALLOC(n + 1, slong); degeval = FLINT_ARRAY_ALLOC(n + 1, slong); alpha = FLINT_ARRAY_ALLOC(n, fq_zech_struct); alphabetas = FLINT_ARRAY_ALLOC(n, fq_zech_poly_struct); Aevals = FLINT_ARRAY_ALLOC(n, fq_zech_mpoly_struct); for (i = 0; i < n; i++) { fq_zech_init(alpha + i, ctx->fqctx); fq_zech_poly_init(alphabetas + i, ctx->fqctx); fq_zech_mpoly_init(Aevals + i, ctx); } fq_zech_mpolyv_init(tfac, ctx); fq_zech_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; fq_zech_mpoly_degrees_si(degs, A, ctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) { fq_zech_rand(alpha + i, state, ctx->fqctx); if (fq_zech_is_zero(alpha + i, ctx->fqctx)) fq_zech_one(alpha + i, ctx->fqctx); } for (i = n - 1; i >= 0; i--) { fq_zech_mpoly_evaluate_one_fq_zech(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha + i, ctx); fq_zech_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } fq_zech_mpoly_get_fq_zech_poly(Abfc, Aevals + 0, 0, ctx); if (!fq_zech_poly_is_squarefree(Abfc, ctx->fqctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 5) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { fq_zech_poly_fit_length(alphabetas + i, alphabetas_length, ctx->fqctx); fq_zech_set(alphabetas[i].coeffs + 0, alpha + i, ctx->fqctx); for (j = 1; j < alphabetas_length; j++) fq_zech_rand(alphabetas[i].coeffs + j, state, ctx->fqctx); alphabetas[i].length = alphabetas_length; _fq_zech_poly_normalise(alphabetas + i, ctx->fqctx); } _fq_zech_mpoly_eval_to_bpoly(Ab, A, alphabetas, ctx); success = fq_zech_bpoly_factor_smprime(Abfc, Abfp, Ab, 0, ctx->fqctx); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { fq_zech_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; fq_zech_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } fq_zech_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = fq_zech_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) fq_zech_mpoly_one(lc_divs->coeffs + i, ctx); } success = fq_zech_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = fq_zech_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } fq_zech_mpoly_pow_ui(mpow, m, r - 1, ctx); if (fq_zech_mpoly_is_one(mpow, ctx)) { newA = (fq_zech_mpoly_struct *) A; } else { newA = Acopy; fq_zech_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } fq_zech_mpoly_degrees_si(degs, newA, ctx); for (i = 0; i < n + 1; i++) { if (FLINT_BIT_COUNT(degs[i]) >= FLINT_BITS/3) { success = -1; goto cleanup; } } fq_zech_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { fq_zech_mpoly_evaluate_one_fq_zech(t, mpow, i + 1, alpha + i, ctx); fq_zech_mpoly_swap(t, mpow, ctx); fq_zech_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); } fq_zech_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { fq_zech_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { fq_zech_mpoly_evaluate_one_fq_zech(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha + i, ctx); } } fq_zech_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { fq_zech_t q; fq_zech_init(q, ctx->fqctx); FLINT_ASSERT(fq_zech_mpoly_is_fq_zech(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(fq_zech_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _fq_zech_mpoly_set_fq_zech_bpoly_var1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); fq_zech_inv(q, fac->coeffs[i].coeffs + 0, ctx->fqctx); fq_zech_mul(q, q, new_lcs->coeffs[0*r + i].coeffs + 0, ctx->fqctx); fq_zech_mpoly_scalar_mul_fq_zech(fac->coeffs + i, fac->coeffs + i, q, ctx); fq_zech_clear(q, ctx->fqctx); } fq_zech_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _fq_zech_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } if (k > 2) { success = fq_zech_mpoly_hlift_zippel(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx, state); } else { success = fq_zech_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); } if (!success) goto next_alphabetas; fq_zech_mpolyv_swap(tfac, fac, ctx); } if (!fq_zech_mpoly_is_fq_zech(m, ctx)) { fq_zech_mpoly_univar_t u; fq_zech_mpoly_univar_init(u, ctx); for (i = 0; i < r; i++) { fq_zech_mpoly_to_univar(u, fac->coeffs + i, 0, ctx); success = fq_zech_mpoly_univar_content_mpoly(t, u, ctx); if (!success) { fq_zech_mpoly_univar_clear(u, ctx); success = -1; goto cleanup; } success = fq_zech_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } fq_zech_mpoly_univar_clear(u, ctx); } for (i = 0; i < r; i++) fq_zech_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); success = 1; cleanup: fq_zech_mpolyv_clear(new_lcs, ctx); fq_zech_mpolyv_clear(lc_divs, ctx); fq_zech_bpoly_clear(Ab, ctx->fqctx); fq_zech_poly_clear(Abfc, ctx->fqctx); fq_zech_tpoly_clear(Abfp, ctx->fqctx); for (i = 0; i < n; i++) { fq_zech_mpoly_clear(Aevals + i, ctx); fq_zech_poly_clear(alphabetas + i, ctx->fqctx); fq_zech_clear(alpha + i, ctx->fqctx); } flint_free(alphabetas); flint_free(alpha); flint_free(Aevals); flint_free(degs); flint_free(degeval); fq_zech_mpolyv_clear(tfac, ctx); fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(Acopy, ctx); fq_zech_mpoly_clear(m, ctx); fq_zech_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { fq_zech_mpoly_t prod; fq_zech_mpoly_init(prod, ctx); fq_zech_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) fq_zech_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(prod, A, ctx)); fq_zech_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/fq_zech_mpoly_factor/lcc_wang.c000066400000000000000000000110131461254215100215340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" int fq_zech_mpoly_factor_lcc_wang( fq_zech_mpoly_struct * lc_divs, const fq_zech_mpoly_factor_t lcAfac, const fq_zech_poly_t Auc, const fq_zech_bpoly_struct * Auf, slong r, const fq_zech_poly_struct * alpha, const fq_zech_mpoly_ctx_t ctx) { int success; slong i, j, k; const slong n = ctx->minfo->nvars - 1; fq_zech_poly_struct * lcAfaceval; fq_zech_poly_struct * d; fq_zech_poly_t Q, R; fq_zech_mpoly_t t; slong N, * offsets, * shifts, * starts, * ends, * stops; ulong mask, * es; fq_zech_poly_struct * T; fq_zech_poly_init(Q, ctx->fqctx); fq_zech_poly_init(R, ctx->fqctx); fq_zech_mpoly_init(t, ctx); lcAfaceval = FLINT_ARRAY_ALLOC(lcAfac->num, fq_zech_poly_struct); for (i = 0; i < lcAfac->num; i++) fq_zech_poly_init(lcAfaceval + i, ctx->fqctx); d = FLINT_ARRAY_ALLOC(lcAfac->num + 1, fq_zech_poly_struct); for (i = 0; i < lcAfac->num + 1; i++) fq_zech_poly_init(d + i, ctx->fqctx); starts = FLINT_ARRAY_ALLOC(n + 1, slong); ends = FLINT_ARRAY_ALLOC(n + 1, slong); stops = FLINT_ARRAY_ALLOC(n + 1, slong); es = FLINT_ARRAY_ALLOC(n + 1, ulong); T = FLINT_ARRAY_ALLOC(n + 2, fq_zech_poly_struct); for (i = 0; i < n + 2; i++) fq_zech_poly_init(T + i, ctx->fqctx); offsets = FLINT_ARRAY_ALLOC(n + 1, slong); shifts = FLINT_ARRAY_ALLOC(n + 1, slong); /* init done */ for (j = 0; j < lcAfac->num; j++) { fq_zech_mpoly_struct * P = lcAfac->poly + j; for (i = 0; i < n + 1; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, P->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - P->bits); N = mpoly_words_per_exp_sp(P->bits, ctx->minfo); _fq_zech_mpoly_eval_rest_fq_zech_poly(T, starts, ends, stops, es, P->coeffs, P->exps, P->length, 1, alpha, offsets, shifts, N, mask, n + 1, ctx->fqctx); fq_zech_poly_set(lcAfaceval + j, T + 0, ctx->fqctx); } fq_zech_poly_set(d + 0, Auc, ctx->fqctx); for (i = 0; i < lcAfac->num; i++) { fq_zech_poly_make_monic(Q, lcAfaceval + i, ctx->fqctx); if (fq_zech_poly_degree(Q, ctx->fqctx) < 1) { success = 0; goto cleanup; } for (j = i; j >= 0; j--) { fq_zech_poly_set(R, d + j, ctx->fqctx); while (fq_zech_poly_degree(R, ctx->fqctx) > 0) { fq_zech_poly_gcd(R, R, Q, ctx->fqctx); fq_zech_poly_divrem(Q, T + 0, Q, R, ctx->fqctx); FLINT_ASSERT(fq_zech_poly_is_zero(T + 0, ctx->fqctx)); if (fq_zech_poly_degree(Q, ctx->fqctx) < 1) { success = 0; goto cleanup; } } } fq_zech_poly_set(d + i + 1, Q, ctx->fqctx); } for (j = 0; j < r; j++) { fq_zech_mpoly_one(lc_divs + j, ctx); fq_zech_poly_mul(R, Auf[j].coeffs + Auf[j].length - 1, Auc, ctx->fqctx); for (i = lcAfac->num - 1; i >= 0; i--) { fq_zech_poly_make_monic(Q, lcAfaceval + i, ctx->fqctx); if (fq_zech_poly_degree(Q, ctx->fqctx) < 1) continue; k = fq_zech_poly_remove(R, Q, ctx->fqctx); fq_zech_mpoly_pow_ui(t, lcAfac->poly + i, k, ctx); fq_zech_mpoly_mul(lc_divs + j, lc_divs + j, t, ctx); } } success = 1; cleanup: fq_zech_poly_clear(Q, ctx->fqctx); fq_zech_poly_clear(R, ctx->fqctx); fq_zech_mpoly_clear(t, ctx); for (i = 0; i < lcAfac->num; i++) fq_zech_poly_clear(lcAfaceval + i, ctx->fqctx); flint_free(lcAfaceval); for (i = 0; i < lcAfac->num + 1; i++) fq_zech_poly_clear(d + i, ctx->fqctx); flint_free(d); for (i = 0; i < n + 2; i++) fq_zech_poly_clear(T + i, ctx->fqctx); flint_free(T); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); return success; } flint-3.1.3/src/fq_zech_mpoly_factor/mpoly_hlift.c000066400000000000000000000272271461254215100223230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" static int _hlift_quartic2( slong m, fq_zech_mpoly_struct * f, slong r, const fq_zech_struct * alpha, const fq_zech_mpoly_t A, const slong * degs, const fq_zech_mpoly_ctx_t ctx) { int success; slong i, j; fq_zech_mpoly_t Aq, t, t2, t3, xalpha; fq_zech_mpoly_struct * deltas; fq_zech_mpoly_pfrac_t I; fq_zech_mpolyv_struct B[2]; fq_zech_mpoly_struct betas[2]; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r == 2); r = 2; fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_init(t2, ctx); fq_zech_mpoly_init(t3, ctx); fq_zech_mpoly_init(xalpha, ctx); fq_zech_mpoly_init(Aq, ctx); fq_zech_mpoly_gen(xalpha, m, ctx); fq_zech_mpoly_sub_fq_zech(xalpha, xalpha, alpha + m - 1, ctx); fq_zech_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (i = 0; i < r; i++) { fq_zech_mpolyv_init(B + i, ctx); fq_zech_mpoly_repack_bits_inplace(f + i, bits, ctx); fq_zech_mpoly_to_mpolyv(B + i, f + i, xalpha, ctx); fq_zech_mpolyv_fit_length(B + i, degs[m] + 1, ctx); for (j = B[i].length; j <= degs[m]; j++) fq_zech_mpoly_zero(B[i].coeffs + j, ctx); betas[i] = B[i].coeffs[0]; } success = fq_zech_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; fq_zech_mpoly_divrem(Aq, t, A, xalpha, ctx); #if FLINT_WANT_ASSERT fq_zech_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fq_zech_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { fq_zech_mpoly_divrem(t2, t, Aq, xalpha, ctx); fq_zech_mpoly_swap(Aq, t2, ctx); for (i = 0; i <= j; i++) { fq_zech_mpoly_mul(t2, B[0].coeffs + i, B[1].coeffs + j - i, ctx); fq_zech_mpoly_sub(t3, t, t2, ctx); fq_zech_mpoly_swap(t, t3, ctx); } if (fq_zech_mpoly_is_zero(t, ctx)) continue; success = fq_zech_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fq_zech_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fq_zech_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fq_zech_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } } success = 1; cleanup: fq_zech_mpoly_pfrac_clear(I, ctx); for (i = 0; i < r; i++) { if (success) fq_zech_mpoly_from_mpolyv(f + i, B + i, xalpha, ctx); fq_zech_mpolyv_clear(B + i, ctx); } fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(t2, ctx); fq_zech_mpoly_clear(t3, ctx); fq_zech_mpoly_clear(xalpha, ctx); fq_zech_mpoly_clear(Aq, ctx); return success; } static int _hlift_quartic( slong m, fq_zech_mpoly_struct * f, slong r, const fq_zech_struct * alpha, const fq_zech_mpoly_t A, const slong * degs, const fq_zech_mpoly_ctx_t ctx) { int success; slong i, j, k; fq_zech_mpoly_t Aq, t, t1, t2, t3, xalpha; fq_zech_mpoly_struct * betas, * deltas; fq_zech_mpoly_pfrac_t I; fq_zech_mpolyv_struct * B, * U; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 2); betas = FLINT_ARRAY_ALLOC(r, fq_zech_mpoly_struct); B = FLINT_ARRAY_ALLOC(2*r, fq_zech_mpolyv_struct); U = B + r; fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_init(t1, ctx); fq_zech_mpoly_init(t2, ctx); fq_zech_mpoly_init(t3, ctx); fq_zech_mpoly_init(xalpha, ctx); fq_zech_mpoly_init(Aq, ctx); fq_zech_mpoly_gen(xalpha, m, ctx); fq_zech_mpoly_sub_fq_zech(xalpha, xalpha, alpha + m - 1, ctx); fq_zech_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (k = 0; k < r; k++) { fq_zech_mpolyv_init(U + k, ctx); fq_zech_mpolyv_fit_length(U + k, degs[m] + 1, ctx); for (j = 0; j <= degs[m]; j++) fq_zech_mpoly_zero(U[k].coeffs + j, ctx); fq_zech_mpolyv_init(B + k, ctx); fq_zech_mpoly_repack_bits_inplace(f + k, bits, ctx); fq_zech_mpoly_to_mpolyv(B + k, f + k, xalpha, ctx); fq_zech_mpolyv_fit_length(B + k, degs[m] + 1, ctx); for (j = B[k].length; j <= degs[m]; j++) fq_zech_mpoly_zero(B[k].coeffs + j, ctx); betas[k] = B[k].coeffs[0]; } success = fq_zech_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; k = r - 2; fq_zech_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k >= 1; k--) fq_zech_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx); fq_zech_mpoly_divrem(Aq, t, A, xalpha, ctx); #if FLINT_WANT_ASSERT fq_zech_mpoly_one(t2, ctx); for (i = 0; i < r; i++) fq_zech_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(fq_zech_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { k = r - 2; fq_zech_mpoly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { fq_zech_mpoly_mul(t1, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); fq_zech_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t1, ctx); } for (k--; k >= 1; k--) { fq_zech_mpoly_zero(U[k].coeffs + j, ctx); for (i = 0; i <= j; i++) { fq_zech_mpoly_mul(t1, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); fq_zech_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t1, ctx); } } fq_zech_mpoly_divrem(t2, t, Aq, xalpha, ctx); fq_zech_mpoly_swap(Aq, t2, ctx); for (i = 0; i <= j; i++) { fq_zech_mpoly_mul(t2, B[0].coeffs + i, U[1].coeffs + j - i, ctx); fq_zech_mpoly_sub(t3, t, t2, ctx); fq_zech_mpoly_swap(t, t3, ctx); } if (fq_zech_mpoly_is_zero(t, ctx)) continue; success = fq_zech_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { fq_zech_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); fq_zech_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!fq_zech_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } k = r - 2; fq_zech_mpoly_mul(t, B[k].coeffs + 0, deltas + k + 1, ctx); fq_zech_mpoly_mul(t1, deltas + k, B[k + 1].coeffs + 0, ctx); fq_zech_mpoly_add(t, t, t1, ctx); fq_zech_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); for (k--; k >= 1; k--) { fq_zech_mpoly_mul(t1, B[k].coeffs + 0, t, ctx); fq_zech_mpoly_swap(t, t1, ctx); fq_zech_mpoly_mul(t1, deltas + k, U[k + 1].coeffs + 0, ctx); fq_zech_mpoly_add(t, t, t1, ctx); fq_zech_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } success = 1; cleanup: fq_zech_mpoly_pfrac_clear(I, ctx); flint_free(betas); for (i = 0; i < r; i++) { if (success) fq_zech_mpoly_from_mpolyv(f + i, B + i, xalpha, ctx); fq_zech_mpolyv_clear(B + i, ctx); fq_zech_mpolyv_clear(U + i, ctx); } flint_free(B); fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(t1, ctx); fq_zech_mpoly_clear(t2, ctx); fq_zech_mpoly_clear(t3, ctx); fq_zech_mpoly_clear(xalpha, ctx); fq_zech_mpoly_clear(Aq, ctx); return success; } static int _hlift_quintic( slong m, fq_zech_mpoly_struct * f, slong r, const fq_zech_struct * alpha, const fq_zech_mpoly_t A, const slong * degs, const fq_zech_mpoly_ctx_t ctx) { int success; slong i, j; fq_zech_mpoly_t e, t, pow, xalpha, q; fq_zech_mpoly_struct * betas, * deltas; fq_zech_mpoly_pfrac_t I; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 1); fq_zech_mpoly_init(e, ctx); fq_zech_mpoly_init(t, ctx); fq_zech_mpoly_init(pow, ctx); fq_zech_mpoly_init(xalpha, ctx); fq_zech_mpoly_init(q, ctx); betas = (fq_zech_mpoly_struct *) flint_malloc(r*sizeof(fq_zech_mpoly_struct)); for (i = 0; i < r; i++) { fq_zech_mpoly_init(betas + i, ctx); fq_zech_mpoly_repack_bits_inplace(f + i, bits, ctx); fq_zech_mpoly_evaluate_one_fq_zech(betas + i, f + i, m, alpha + m - 1, ctx); } fq_zech_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fq_zech_mpoly_mul(t, t, f + i, ctx); fq_zech_mpoly_sub(e, A, t, ctx); fq_zech_mpoly_one(pow, ctx); fq_zech_mpoly_repack_bits_inplace(pow, bits, ctx); fq_zech_mpoly_gen(xalpha, m, ctx); fq_zech_mpoly_sub_fq_zech(xalpha, xalpha, alpha + m - 1, ctx); fq_zech_mpoly_repack_bits_inplace(xalpha, bits, ctx); fq_zech_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); deltas = I->deltas + (m - 1)*I->r; for (j = 1; j <= degs[m]; j++) { if (fq_zech_mpoly_is_zero(e, ctx)) { success = 1; goto cleanup; } fq_zech_mpoly_mul(pow, pow, xalpha, ctx); success = fq_zech_mpoly_divides(q, e, pow, ctx); FLINT_ASSERT(success); fq_zech_mpoly_evaluate_one_fq_zech(t, q, m, alpha + m - 1, ctx); success = fq_zech_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } for (i = 0; i < r; i++) { fq_zech_mpoly_mul(t, deltas + i, pow, ctx); fq_zech_mpoly_add(f + i, f + i, t, ctx); } fq_zech_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) fq_zech_mpoly_mul(t, t, f + i, ctx); fq_zech_mpoly_sub(e, A, t, ctx); } success = fq_zech_mpoly_is_zero(e, ctx); cleanup: fq_zech_mpoly_pfrac_clear(I, ctx); fq_zech_mpoly_clear(e, ctx); fq_zech_mpoly_clear(t, ctx); fq_zech_mpoly_clear(pow, ctx); fq_zech_mpoly_clear(xalpha, ctx); fq_zech_mpoly_clear(q, ctx); for (i = 0; i < r; i++) fq_zech_mpoly_clear(betas + i, ctx); flint_free(betas); return success; } /* should have A = prod_i f[i] mod (gen(m) - alpha[m-1]) */ int fq_zech_mpoly_hlift( slong m, fq_zech_mpoly_struct * f, /* length r */ slong r, const fq_zech_struct * alpha, const fq_zech_mpoly_t A, const slong * degs, const fq_zech_mpoly_ctx_t ctx) { FLINT_ASSERT(r >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (r == 2) return _hlift_quartic2(m, f, r, alpha, A, degs, ctx); else if (r < 20) return _hlift_quartic(m, f, r, alpha, A, degs, ctx); else return _hlift_quintic(m, f, r, alpha, A, degs, ctx); } flint-3.1.3/src/fq_zech_mpoly_factor/mpoly_pfrac.c000066400000000000000000000242561461254215100223070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #include "fq_zech_mpoly_factor.h" int fq_zech_mpoly_pfrac_init( fq_zech_mpoly_pfrac_t I, flint_bitcnt_t bits, slong r, slong w, const fq_zech_mpoly_struct * betas, const fq_zech_struct * alpha, const fq_zech_mpoly_ctx_t ctx) { slong success = 1; slong i, j, k; fq_zech_poly_t p; fq_zech_poly_t G, S, pq; FLINT_ASSERT(bits <= FLINT_BITS); I->bits = bits; I->r = r; I->w = w; I->dbetas = (fq_zech_poly_struct *) flint_malloc( r*sizeof(fq_zech_poly_struct)); I->inv_prod_dbetas = (fq_zech_poly_struct *) flint_malloc( r* sizeof(fq_zech_poly_struct)); I->prod_mbetas = (fq_zech_mpoly_struct *) flint_malloc( (w + 1)*r*sizeof(fq_zech_mpoly_struct)); I->prod_mbetas_coeffs = (fq_zech_mpolyv_struct *) flint_malloc( (w + 1)*r*sizeof(fq_zech_mpolyv_struct)); I->mbetas = (fq_zech_mpoly_struct *) flint_malloc( (w + 1)*r*sizeof(fq_zech_mpoly_struct)); I->deltas = (fq_zech_mpoly_struct *) flint_malloc( (w + 1)*r*sizeof(fq_zech_mpoly_struct)); I->xalpha = (fq_zech_mpoly_struct *) flint_malloc( (w + 1)*sizeof(fq_zech_mpoly_struct)); I->q = (fq_zech_mpoly_struct *) flint_malloc( (w + 1)*sizeof(fq_zech_mpoly_struct)); I->qt = (fq_zech_mpoly_struct *) flint_malloc( (w + 1)*sizeof(fq_zech_mpoly_struct)); I->newt = (fq_zech_mpoly_struct *) flint_malloc( (w + 1)*sizeof(fq_zech_mpoly_struct)); I->delta_coeffs = (fq_zech_mpolyv_struct *) flint_malloc( (w + 1)*r*sizeof(fq_zech_mpolyv_struct)); for (i = 0; i <= w; i++) { fq_zech_mpoly_init(I->xalpha + i, ctx); fq_zech_mpoly_init(I->q + i, ctx); fq_zech_mpoly_init(I->qt + i, ctx); fq_zech_mpoly_init(I->newt + i, ctx); for (j = 0; j < r; j++) { fq_zech_mpoly_init(I->deltas + i*r + j, ctx); fq_zech_mpolyv_init(I->delta_coeffs + i*r + j, ctx); } if (i < 1) continue; fq_zech_mpoly_gen(I->xalpha + i, i, ctx); fq_zech_mpoly_sub_fq_zech(I->xalpha + i, I->xalpha + i, alpha + i - 1, ctx); fq_zech_mpoly_repack_bits_inplace(I->xalpha + i, I->bits, ctx); } fq_zech_poly_init(p, ctx->fqctx); fq_zech_poly_init(G, ctx->fqctx); fq_zech_poly_init(S, ctx->fqctx); fq_zech_poly_init(pq, ctx->fqctx); /* set betas */ i = w; for (j = 0; j < r; j++) { fq_zech_mpoly_init(I->mbetas + i*r + j, ctx); fq_zech_mpoly_set(I->mbetas + i*r + j, betas + j, ctx); } for (i--; i >= 0; i--) { for (j = 0; j < r; j++) { fq_zech_mpoly_init(I->mbetas + i*r + j, ctx); fq_zech_mpoly_evaluate_one_fq_zech(I->mbetas + i*r + j, I->mbetas + (i + 1)*r + j, i + 1, alpha + i, ctx); } } for (j = 0; j < r; j++) { fq_zech_poly_init(I->dbetas + j, ctx->fqctx); if (!fq_zech_mpoly_get_fq_zech_poly(I->dbetas + j, I->mbetas + 0*r + j, 0, ctx)) { success = 0; } } /* set product of betas */ for (i = w; i >= 0; i--) { for (j = 0; j < r; j++) { fq_zech_mpoly_init(I->prod_mbetas + i*r + j, ctx); fq_zech_mpoly_one(I->prod_mbetas + i*r + j, ctx); for (k = 0; k < r; k++) { if (k == j) continue; fq_zech_mpoly_mul(I->prod_mbetas + i*r + j, I->prod_mbetas + i*r + j, I->mbetas + i*r + k, ctx); } fq_zech_mpolyv_init(I->prod_mbetas_coeffs + i*r + j, ctx); if (i > 0) { fq_zech_mpoly_to_mpolyv(I->prod_mbetas_coeffs + i*r + j, I->prod_mbetas + i*r + j, I->xalpha + i, ctx); } } } for (j = 0; j < r; j++) fq_zech_poly_init(I->inv_prod_dbetas + j, ctx->fqctx); for (j = 0; success && j < r; j++) { if (fq_zech_poly_degree(I->dbetas + j, ctx->fqctx) != fq_zech_mpoly_degree_si(betas + j, 0, ctx)) { success = 0; } } for (j = 0; success && j < r; j++) { fq_zech_poly_one(pq, ctx->fqctx); for (k = 0; k < r; k++) { if (k == j) continue; fq_zech_poly_mul(pq, pq, I->dbetas + k, ctx->fqctx); } fq_zech_poly_xgcd(G, S, I->inv_prod_dbetas + j, I->dbetas + j, pq, ctx->fqctx); if (!fq_zech_poly_is_one(G, ctx->fqctx)) { success = 0; } } fq_zech_poly_clear(p, ctx->fqctx); fq_zech_poly_clear(G, ctx->fqctx); fq_zech_poly_clear(S, ctx->fqctx); fq_zech_poly_clear(pq, ctx->fqctx); I->dbetas_mvar = (fq_zech_mpoly_struct *) flint_malloc( r*sizeof(fq_zech_mpoly_struct)); I->inv_prod_dbetas_mvar = (fq_zech_mpoly_struct *) flint_malloc( r*sizeof(fq_zech_mpoly_struct)); for (j = 0; j < r; j++) { fq_zech_mpoly_init(I->dbetas_mvar + j, ctx); fq_zech_mpoly_init(I->inv_prod_dbetas_mvar + j, ctx); _fq_zech_mpoly_set_fq_zech_poly(I->dbetas_mvar + j, I->bits, I->dbetas[j].coeffs, I->dbetas[j].length, 0, ctx); _fq_zech_mpoly_set_fq_zech_poly(I->inv_prod_dbetas_mvar + j, I->bits, I->inv_prod_dbetas[j].coeffs, I->inv_prod_dbetas[j].length, 0, ctx); } fq_zech_mpoly_init(I->T, ctx); fq_zech_mpoly_init(I->Q, ctx); fq_zech_mpoly_init(I->R, ctx); FLINT_ASSERT(success == 1); return success; } void fq_zech_mpoly_pfrac_clear(fq_zech_mpoly_pfrac_t I, const fq_zech_mpoly_ctx_t ctx) { slong i, j; for (i = 0; i <= I->w; i++) { fq_zech_mpoly_clear(I->xalpha + i, ctx); fq_zech_mpoly_clear(I->q + i, ctx); fq_zech_mpoly_clear(I->qt + i, ctx); fq_zech_mpoly_clear(I->newt + i, ctx); for (j = 0; j < I->r; j++) fq_zech_mpolyv_clear(I->delta_coeffs + i*I->r + j, ctx); } flint_free(I->xalpha); flint_free(I->q); flint_free(I->qt); flint_free(I->newt); flint_free(I->delta_coeffs); for (j = 0; j < I->r; j++) { fq_zech_poly_clear(I->inv_prod_dbetas + j, ctx->fqctx); fq_zech_poly_clear(I->dbetas + j, ctx->fqctx); for (i = 0; i <= I->w; i++) { fq_zech_mpolyv_clear(I->prod_mbetas_coeffs + i*I->r + j, ctx); fq_zech_mpoly_clear(I->prod_mbetas + i*I->r + j, ctx); fq_zech_mpoly_clear(I->mbetas + i*I->r + j, ctx); fq_zech_mpoly_clear(I->deltas + i*I->r + j, ctx); } } flint_free(I->inv_prod_dbetas); flint_free(I->dbetas); flint_free(I->prod_mbetas); flint_free(I->prod_mbetas_coeffs); flint_free(I->mbetas); flint_free(I->deltas); for (j = 0; j < I->r; j++) { fq_zech_mpoly_clear(I->dbetas_mvar + j, ctx); fq_zech_mpoly_clear(I->inv_prod_dbetas_mvar + j, ctx); } flint_free(I->dbetas_mvar); flint_free(I->inv_prod_dbetas_mvar); fq_zech_mpoly_clear(I->T, ctx); fq_zech_mpoly_clear(I->Q, ctx); fq_zech_mpoly_clear(I->R, ctx); } int fq_zech_mpoly_pfrac( slong l, fq_zech_mpoly_t t, const slong * degs, fq_zech_mpoly_pfrac_t I, const fq_zech_mpoly_ctx_t ctx) { slong i, j, k; int success; fq_zech_mpoly_struct * deltas = I->deltas + l*I->r; fq_zech_mpoly_struct * newdeltas = I->deltas + (l - 1)*I->r; fq_zech_mpoly_struct * q = I->q + l; fq_zech_mpoly_struct * qt = I->qt + l; fq_zech_mpoly_struct * newt = I->newt + l; fq_zech_mpolyv_struct * delta_coeffs = I->delta_coeffs + l*I->r; FLINT_ASSERT(l >= 0); if (!fq_zech_mpoly_repack_bits_inplace(t, I->bits, ctx)) return -1; if (l < 1) { for (i = 0; i < I->r; i++) { fq_zech_mpoly_divrem(I->Q, I->R, t, I->dbetas_mvar + i, ctx); fq_zech_mpoly_mul(I->T, I->R, I->inv_prod_dbetas_mvar + i, ctx); fq_zech_mpoly_divrem(I->Q, deltas + i, I->T, I->dbetas_mvar + i, ctx); } return 1; } for (i = 0; i < I->r; i++) delta_coeffs[i].length = 0; for (k = 0; k <= degs[l]; k++) { fq_zech_mpoly_divrem(q, newt, t, I->xalpha + l, ctx); fq_zech_mpoly_swap(t, q, ctx); for (j = 0; j < k; j++) for (i = 0; i < I->r; i++) { if (j >= delta_coeffs[i].length) continue; if (k - j >= I->prod_mbetas_coeffs[l*I->r + i].length) continue; fq_zech_mpoly_mul(qt, delta_coeffs[i].coeffs + j, I->prod_mbetas_coeffs[l*I->r + i].coeffs + k - j, ctx); fq_zech_mpoly_sub(q, newt, qt, ctx); fq_zech_mpoly_swap(newt, q, ctx); } success = fq_zech_mpoly_pfrac(l - 1, newt, degs, I, ctx); if (success < 1) return success; for (i = 0; i < I->r; i++) { if (fq_zech_mpoly_is_zero(newdeltas + i, ctx)) continue; if (k + I->prod_mbetas_coeffs[l*I->r + i].length - 1 > degs[l]) return 0; fq_zech_mpolyv_set_coeff(delta_coeffs + i, k, newdeltas + i, ctx); } } for (i = 0; i < I->r; i++) fq_zech_mpoly_from_mpolyv(deltas + i, delta_coeffs + i, I->xalpha + l, ctx); return 1; } flint-3.1.3/src/fq_zech_mpoly_factor/mpoly_univar.c000066400000000000000000000013301461254215100225040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" int fq_zech_mpoly_univar_content_mpoly( fq_zech_mpoly_t g, const fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; fq_zech_mpoly_zero(g, ctx); for (i = 0; i < A->length; i++) { if (!fq_zech_mpoly_gcd(g, g, A->coeffs + i, ctx)) return 0; } return 1; } flint-3.1.3/src/fq_zech_mpoly_factor/mpolyv.c000066400000000000000000000057641461254215100213250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" void fq_zech_mpolyv_clear(fq_zech_mpolyv_t A, const fq_zech_mpoly_ctx_t ctx) { slong i; if (A->alloc > 0) { for (i = 0; i < A->alloc; i++) fq_zech_mpoly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } } void fq_zech_mpolyv_fit_length( fq_zech_mpolyv_t A, slong length, const fq_zech_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length <= old_alloc) return; if (old_alloc > 0) { A->coeffs = (fq_zech_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_zech_mpoly_struct)); } else { A->coeffs = (fq_zech_mpoly_struct *) flint_malloc( new_alloc*sizeof(fq_zech_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) fq_zech_mpoly_init(A->coeffs + i, ctx); A->alloc = new_alloc; } void fq_zech_mpolyv_set_coeff( fq_zech_mpolyv_t A, slong i, fq_zech_mpoly_t c, /* clobbered */ const fq_zech_mpoly_ctx_t ctx) { slong j; FLINT_ASSERT(!fq_zech_mpoly_is_zero(c, ctx)); fq_zech_mpolyv_fit_length(A, i + 1, ctx); for (j = A->length; j < i; j++) fq_zech_mpoly_zero(A->coeffs + j, ctx); fq_zech_mpoly_swap(A->coeffs + i, c, ctx); A->length = FLINT_MAX(A->length, i + 1); } void fq_zech_mpoly_to_mpolyv( fq_zech_mpolyv_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_t xalpha, const fq_zech_mpoly_ctx_t ctx) { fq_zech_mpoly_t Q, T; fq_zech_mpoly_init(Q, ctx); fq_zech_mpoly_init(T, ctx); fq_zech_mpolyv_fit_length(A, 8, ctx); fq_zech_mpoly_divrem(Q, A->coeffs + 0, B, xalpha, ctx); A->length = 1; while (!fq_zech_mpoly_is_zero(Q, ctx)) { fq_zech_mpolyv_fit_length(A, A->length + 1, ctx); fq_zech_mpoly_divrem(T, A->coeffs + A->length, Q, xalpha, ctx); fq_zech_mpoly_swap(Q, T, ctx); A->length++; } while (A->length > 0 && fq_zech_mpoly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; fq_zech_mpoly_clear(Q, ctx); fq_zech_mpoly_clear(T, ctx); } void fq_zech_mpoly_from_mpolyv( fq_zech_mpoly_t A, const fq_zech_mpolyv_t B, const fq_zech_mpoly_t xalpha, const fq_zech_mpoly_ctx_t ctx) { slong i; fq_zech_mpoly_t T; fq_zech_mpoly_init(T, ctx); fq_zech_mpoly_zero(A, ctx); for (i = B->length - 1; i >= 0; i--) { fq_zech_mpoly_mul(T, A, xalpha, ctx); fq_zech_mpoly_add(A, T, B->coeffs + i, ctx); } fq_zech_mpoly_clear(T, ctx); } flint-3.1.3/src/fq_zech_mpoly_factor/polyu.c000066400000000000000000000046201461254215100211350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" void fq_zech_polyu_clear(fq_zech_polyu_t A, const fq_zech_ctx_t ctx) { if (A->alloc > 0) { flint_free(A->exps); flint_free(A->coeffs); } else { FLINT_ASSERT(A->exps == NULL); FLINT_ASSERT(A->coeffs == NULL); } } void fq_zech_polyu_realloc(fq_zech_polyu_t A, slong len, const fq_zech_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; if (old_alloc > 0) { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (fq_zech_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(fq_zech_struct)); } else { FLINT_ASSERT(A->exps == NULL); FLINT_ASSERT(A->coeffs == NULL); A->exps = (ulong *) flint_malloc(new_alloc*sizeof(ulong)); A->coeffs = (fq_zech_struct *) flint_malloc(new_alloc*sizeof(fq_zech_struct)); } for (i = old_alloc; i < new_alloc; i++) fq_zech_init(A->coeffs + i, ctx); A->alloc = new_alloc; } void fq_zech_polyu3_degrees( slong * deg0, slong * deg1, slong * deg2, const fq_zech_polyu_t A) { slong i; ulong m; ulong mask = mpoly_overflow_mask_sp(FLINT_BITS/3); if (A->length <= 0) { *deg0 = *deg1 = *deg2 = -1; return; } m = A->exps[0]; for (i = 1; i < A->length; i++) m = mpoly_monomial_max1(m, A->exps[i], FLINT_BITS/3, mask); *deg0 = extract_exp(m, 2, 3); *deg1 = extract_exp(m, 1, 3); *deg2 = extract_exp(m, 0, 3); } int fq_zech_polyu_is_canonical( const fq_zech_polyu_t A, const fq_zech_ctx_t ctx) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (fq_zech_is_zero(A->coeffs + i, ctx)) return 0; if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } flint-3.1.3/src/fq_zech_mpoly_factor/polyu3_hlift.c000066400000000000000000000334441461254215100224140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "mpoly.h" #include "fq_zech_mpoly_factor.h" #if FLINT_WANT_ASSERT static void fq_zech_polyu_set_fq_zech_polyun( fq_zech_polyu_t A, const fq_zech_polyun_t B, const fq_zech_ctx_t ctx) { slong i, j; A->length = 0; for (i = 0; i < B->length; i++) { for (j = B->coeffs[i].length - 1; j >= 0; j--) { if (fq_zech_is_zero(B->coeffs[i].coeffs + j, ctx)) continue; fq_zech_polyu_fit_length(A, A->length + 1, ctx); fq_zech_set(A->coeffs + A->length, B->coeffs[i].coeffs + j, ctx); A->exps[A->length] = B->exps[i] + j; A->length++; } } } static void fq_zech_polyu_sort_terms( fq_zech_polyu_t A, const fq_zech_ctx_t ctx) { slong i, j; for (i = 1; i < A->length; i++) for (j = i; j > 0 && A->exps[j - 1] < A->exps[j]; j--) { FLINT_SWAP(ulong, A->exps[j - 1], A->exps[j]); fq_zech_swap(A->coeffs + j - 1, A->coeffs + j, ctx); } return; } static void fq_zech_polyu_combine_like_terms( fq_zech_polyu_t A, const fq_zech_ctx_t ctx) { slong in, out; out = -1; for (in = 0; in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= 0 && A->exps[out] == A->exps[in]) { fq_zech_add(A->coeffs + out, A->coeffs + out, A->coeffs + in, ctx); } else { if (out < 0 || !fq_zech_is_zero(A->coeffs + out, ctx)) out++; if (out != in) { A->exps[out] = A->exps[in]; fq_zech_set(A->coeffs + out, A->coeffs + in, ctx); } } } if (out < 0 || !fq_zech_is_zero(A->coeffs + out, ctx)) out++; A->length = out; } static int fq_zech_polyu_equal( fq_zech_polyu_t A, fq_zech_polyu_t B, const fq_zech_ctx_t ctx) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (!fq_zech_equal(A->coeffs + i, B->coeffs + i, ctx)) return 0; if (A->exps[i] != B->exps[i]) return 0; } return 1; } static void fq_zech_polyu_mul( fq_zech_polyu_t A, const fq_zech_polyu_t B, const fq_zech_polyu_t C, const fq_zech_ctx_t ctx) { slong Ai, Bi, Ci; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); fq_zech_polyu_fit_length(A, B->length*C->length, ctx); Ai = 0; for (Bi = 0; Bi < B->length; Bi++) for (Ci = 0; Ci < C->length; Ci++) { A->exps[Ai] = B->exps[Bi] + C->exps[Ci]; fq_zech_mul(A->coeffs + Ai, B->coeffs + Bi, C->coeffs + Ci, ctx); Ai++; } A->length = Ai; fq_zech_polyu_sort_terms(A, ctx); fq_zech_polyu_combine_like_terms(A, ctx); } #endif void fq_zech_polyu3_interp_reduce_bpoly( fq_zech_bpoly_t Ap, const fq_zech_polyu_t A, const fq_zech_t alpha, const fq_zech_ctx_t ctx) { slong i; slong cur0, cur1, e0, e1, e2; fq_zech_t p, t, q; fq_zech_init(p, ctx); fq_zech_init(t, ctx); fq_zech_init(q, ctx); fq_zech_bpoly_zero(Ap, ctx); FLINT_ASSERT(A->length > 0); i = 0; cur0 = extract_exp(A->exps[i], 2, 3); cur1 = extract_exp(A->exps[i], 1, 3); e2 = extract_exp(A->exps[i], 0, 3); fq_zech_pow_ui(t, alpha, e2, ctx); fq_zech_set(q, A->coeffs + i, ctx); fq_zech_mul(t, t, q, ctx); for (i = 1; i < A->length; i++) { e0 = extract_exp(A->exps[i], 2, 3); e1 = extract_exp(A->exps[i], 1, 3); e2 = extract_exp(A->exps[i], 0, 3); FLINT_ASSERT(e0 <= cur0); if (e0 < cur0 || e1 < cur1) { fq_zech_bpoly_set_coeff_fq_zech(Ap, cur0, cur1, t, ctx); fq_zech_zero(t, ctx); } else { FLINT_ASSERT(e0 == cur0); FLINT_ASSERT(e1 == cur1); } cur0 = e0; cur1 = e1; fq_zech_pow_ui(p, alpha, e2, ctx); fq_zech_set(q, A->coeffs + i, ctx); fq_zech_mul(p, p, q, ctx); fq_zech_add(t, t, p, ctx); } fq_zech_bpoly_set_coeff_fq_zech(Ap, cur0, cur1, t, ctx); fq_zech_clear(p, ctx); fq_zech_clear(t, ctx); fq_zech_clear(q, ctx); } /* T(x0, x1, x2) is in F[x2][x0, x1] A(x0, x1) are B(x0, x1) are in F[x0, x1] set T so that T(x0, x1, x2) == A(x0, x1) mod (x2 - alpha) T(x0, x1, x2) == B(x0, x1) mod (x2 + alpha) */ void fq_zech_polyu3n_interp_lift_sm_bpoly( slong * lastdeg, fq_zech_polyun_t T, const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx) { slong lastlength = 0; slong Ti; slong Ai, j; Ti = 0; for (Ai = A->length - 1; Ai >= 0; Ai--) { fq_zech_poly_struct * Ac = A->coeffs + Ai; for (j = Ac->length - 1; j >= 0; j--) { if (fq_zech_is_zero(Ac->coeffs + j, ctx)) continue; fq_zech_polyun_fit_length(T, Ti + 1, ctx); T->exps[Ti] = pack_exp3(Ai, j, 0); fq_zech_poly_set_fq_zech(T->coeffs + Ti, Ac->coeffs + j, ctx); Ti++; lastlength = 1; } } T->length = Ti; *lastdeg = lastlength - 1; return; } /* F is in Fq[x2][x0, x1] A is in Fq[x0, x1] */ int fq_zech_polyu3n_interp_crt_sm_bpoly( slong * lastdeg, fq_zech_polyun_t F, fq_zech_polyun_t T, const fq_zech_bpoly_t A, const fq_zech_poly_t modulus, const fq_zech_t alpha, const fq_zech_ctx_t ctx) { int changed = 0; slong lastlength = 0; fq_zech_poly_struct * Tcoeffs; ulong * Texps; slong Ti; fq_zech_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; slong Flen = F->length; slong Fi; const fq_zech_poly_struct * Acoeffs = A->coeffs; slong Ai, ai; fq_zech_poly_t tp; fq_zech_t v; fq_zech_init(v, ctx); fq_zech_poly_init(tp, ctx); FLINT_ASSERT(fq_zech_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(fq_zech_polyun_is_canonical(F, ctx)); fq_zech_polyun_fit_length(T, FLINT_MAX(Flen, A->length), ctx); Tcoeffs = T->coeffs; Texps = T->exps; Ti = Fi = 0; Ai = A->length - 1; ai = (Ai < 0) ? 0 : fq_zech_poly_degree(A->coeffs + Ai, ctx); while (Fi < Flen || Ai >= 0) { if (Ti >= T->alloc) { slong extra = Flen - Fi; extra = FLINT_MAX(extra, Ai); fq_zech_polyun_fit_length(T, Ti + extra + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; } FLINT_ASSERT(Fi >= Flen || Fcoeffs[Fi].length > 0); FLINT_ASSERT(Ai < 0 || !fq_zech_is_zero(Acoeffs[Ai].coeffs + ai, ctx)); if (Fi < Flen && Ai >= 0 && Fexps[Fi] == pack_exp3(Ai, ai, 0)) { /* F term ok, A term ok */ fq_zech_poly_evaluate_fq_zech(v, Fcoeffs + Fi, alpha, ctx); fq_zech_sub(v, Acoeffs[Ai].coeffs + ai, v, ctx); if (!fq_zech_is_zero(v, ctx)) { changed = 1; fq_zech_poly_scalar_mul_fq_zech(tp, modulus, v, ctx); fq_zech_poly_add(Tcoeffs + Ti, Fcoeffs + Fi, tp, ctx); } else { fq_zech_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx); } Texps[Ti] = Fexps[Fi]; Fi++; do { ai--; } while (ai >= 0 && fq_zech_is_zero(Acoeffs[Ai].coeffs + ai, ctx)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = fq_zech_poly_degree(Acoeffs + Ai, ctx); } } else if (Fi < Flen && (Ai < 0 || Fexps[Fi] > pack_exp3(Ai, ai, 0))) { /* F term ok, A term missing */ fq_zech_poly_evaluate_fq_zech(v, Fcoeffs + Fi, alpha, ctx); if (!fq_zech_is_zero(v, ctx)) { changed = 1; fq_zech_poly_scalar_mul_fq_zech(tp, modulus, v, ctx); fq_zech_poly_sub(Tcoeffs + Ti, Fcoeffs + Fi, tp, ctx); } else { fq_zech_poly_set(Tcoeffs + Ti, Fcoeffs + Fi, ctx); } Texps[Ti] = Fexps[Fi]; Fi++; } else { FLINT_ASSERT(Ai >= 0 && (Fi >= Flen || Fexps[Fi] < pack_exp3(Ai, ai, 0))); /* F term missing, Aterm ok */ changed = 1; fq_zech_poly_scalar_mul_fq_zech(Tcoeffs + Ti, modulus, Acoeffs[Ai].coeffs + ai, ctx); Texps[Ti] = pack_exp3(Ai, ai, 0); do { ai--; } while (ai >= 0 && fq_zech_is_zero(Acoeffs[Ai].coeffs + ai, ctx)); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = fq_zech_poly_degree(Acoeffs + Ai, ctx); } } FLINT_ASSERT(!fq_zech_poly_is_zero(Tcoeffs + Ti, ctx)); lastlength = FLINT_MAX(lastlength, Tcoeffs[Ti].length); Ti++; } T->length = Ti; if (changed) fq_zech_polyun_swap(T, F, ctx); FLINT_ASSERT(fq_zech_polyun_is_canonical(F, ctx)); fq_zech_poly_clear(tp, ctx); fq_zech_clear(v, ctx); *lastdeg = lastlength - 1; return changed; } int fq_zech_next( fq_zech_t a, const fq_zech_ctx_t ctx); void fq_zech_poly_shift_left_scalar_submul( fq_zech_poly_t modulus, slong k, const fq_zech_t alpha, const fq_zech_ctx_t ctx) { fq_zech_poly_t t; fq_zech_poly_init(t, ctx); fq_zech_poly_scalar_mul_fq_zech(t, modulus, alpha, ctx); fq_zech_poly_shift_left(modulus, modulus, k, ctx); fq_zech_poly_sub(modulus, modulus, t, ctx); fq_zech_poly_clear(t, ctx); } int fq_zech_polyu3_hlift( slong r, fq_zech_polyun_struct * BB, fq_zech_polyu_t A, fq_zech_polyu_struct * B, const fq_zech_t beta, slong degree_inner, /* required degree in X (var 1) */ const fq_zech_ctx_t ctx) { int success; slong i, j; fq_zech_polyun_t T; fq_zech_bpoly_struct * Bp; fq_zech_bpoly_t Ap; fq_zech_poly_t modulus; fq_zech_t alpha; slong * BBdegZ; slong AdegY, AdegX, AdegZ; slong bad_primes_left; fq_zech_t c; fq_zech_init(c, ctx); fq_zech_init(alpha, ctx); FLINT_ASSERT(fq_zech_polyu_is_canonical(A, ctx)); for (i = 0; i < r; i++) FLINT_ASSERT(fq_zech_polyu_is_canonical(B + i, ctx)); BBdegZ = FLINT_ARRAY_ALLOC(r, slong); Bp = FLINT_ARRAY_ALLOC(r, fq_zech_bpoly_struct); for (i = 0; i < r; i++) fq_zech_bpoly_init(Bp + i, ctx); fq_zech_polyun_init(T, ctx); fq_zech_poly_init(modulus, ctx); fq_zech_bpoly_init(Ap, ctx); fq_zech_polyu3_degrees(&AdegY, &AdegX, &AdegZ, A); if (AdegX != degree_inner) { success = -1; goto cleanup; } fq_zech_poly_one(modulus, ctx); fq_zech_zero(alpha, ctx); bad_primes_left = FLINT_MAX(5, AdegZ); choose_prime: if (fq_zech_next(alpha, ctx) == 0) { success = -1; goto cleanup; } fq_zech_polyu3_interp_reduce_bpoly(Ap, A, alpha, ctx); for (i = 0; i < r; i++) fq_zech_polyu3_interp_reduce_bpoly(Bp + i, B + i, alpha, ctx); if (r < 3) success = fq_zech_bpoly_hlift2(Ap, Bp + 0, Bp + 1, beta, degree_inner, ctx); else success = fq_zech_bpoly_hlift(r, Ap, Bp, beta, degree_inner, ctx); if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } if (fq_zech_poly_degree(modulus, ctx) > 0) { fq_zech_poly_evaluate_fq_zech(c, modulus, alpha, ctx); fq_zech_inv(c, c, ctx); fq_zech_poly_scalar_mul_fq_zech(modulus, modulus, c, ctx); for (i = 0; i < r; i++) { fq_zech_polyu3n_interp_crt_sm_bpoly(BBdegZ + i, BB + i, T, Bp + i, modulus, alpha, ctx); } } else { for (i = 0; i < r; i++) { fq_zech_polyu3n_interp_lift_sm_bpoly(BBdegZ + i, BB + i, Bp + i, ctx); } } fq_zech_poly_shift_left_scalar_submul(modulus, 1, alpha, ctx); j = BBdegZ[0]; for (i = 1; i < r; i++) j += BBdegZ[i]; if (j > AdegZ) { success = 0; goto cleanup; } if (fq_zech_poly_degree(modulus, ctx) <= AdegZ) { goto choose_prime; } success = 1; cleanup: #if FLINT_WANT_ASSERT if (success == 1) { fq_zech_polyu_t T1, T2, T3; fq_zech_polyu_init(T1, ctx); fq_zech_polyu_init(T2, ctx); fq_zech_polyu_init(T3, ctx); fq_zech_polyu_set_fq_zech_polyun(T2, BB + 0, ctx); fq_zech_polyu_set_fq_zech_polyun(T3, BB + 1, ctx); fq_zech_polyu_mul(T1, T2, T3, ctx); for (i = 2; i < r; i++) { fq_zech_polyu_set_fq_zech_polyun(T3, BB + i, ctx); fq_zech_polyu_mul(T2, T1, T3, ctx); fq_zech_polyu_swap(T2, T1, ctx); } FLINT_ASSERT(fq_zech_polyu_equal(A, T1, ctx)); fq_zech_polyu_clear(T1, ctx); fq_zech_polyu_clear(T2, ctx); fq_zech_polyu_clear(T3, ctx); } #endif fq_zech_polyun_clear(T, ctx); fq_zech_bpoly_clear(Ap, ctx); for (i = 0; i < r; i++) fq_zech_bpoly_clear(Bp + i, ctx); flint_free(BBdegZ); flint_free(Bp); fq_zech_poly_clear(modulus, ctx); fq_zech_clear(alpha, ctx); fq_zech_clear(c, ctx); return success; } flint-3.1.3/src/fq_zech_mpoly_factor/polyun.c000066400000000000000000000030341461254215100213110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #include "fq_zech_mpoly_factor.h" void fq_zech_polyun_clear(fq_zech_polyun_t A, const fq_zech_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) fq_zech_poly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); flint_free(A->exps); } void fq_zech_polyun_realloc(fq_zech_polyun_t A, slong len, const fq_zech_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fq_zech_poly_struct); A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, ulong); for (i = old_alloc; i < new_alloc; i++) fq_zech_poly_init(A->coeffs + i, ctx); A->alloc = new_alloc; } int fq_zech_polyun_is_canonical( const fq_zech_polyun_t A, const fq_zech_ctx_t ctx) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (fq_zech_poly_is_zero(A->coeffs + i, ctx)) return 0; if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } flint-3.1.3/src/fq_zech_mpoly_factor/realloc.c000066400000000000000000000037271461254215100214150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_zech_mpoly_factor.h" void fq_zech_mpoly_factor_realloc(fq_zech_mpoly_factor_t f, slong alloc, const fq_zech_mpoly_ctx_t ctx) { slong i; if (alloc <= 0) { fq_zech_mpoly_factor_clear(f, ctx); fq_zech_mpoly_factor_init(f, ctx); return; } if (f->alloc > 0) { if (f->alloc > alloc) { for (i = alloc; i < f->alloc; i++) { fq_zech_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fq_zech_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fq_zech_mpoly_struct)); } else if (f->alloc < alloc) { f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (fq_zech_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(fq_zech_mpoly_struct)); for (i = f->alloc; i < alloc; i++) { fq_zech_mpoly_init(f->poly + i, ctx); fmpz_init(f->exp + i); } } } else { f->exp = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); f->poly = (fq_zech_mpoly_struct *) flint_malloc(alloc * sizeof(fq_zech_mpoly_struct)); for (i = 0; i < alloc; i++) fq_zech_mpoly_init(f->poly + i, ctx); } f->alloc = alloc; } flint-3.1.3/src/fq_zech_mpoly_factor/tpoly.c000066400000000000000000000024151461254215100211340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" void fq_zech_tpoly_fit_length(fq_zech_tpoly_t A, slong len, const fq_zech_ctx_t ctx) { slong i; if (len <= A->alloc) return; if (len < 2 * A->alloc) len = 2 * A->alloc; if (A->alloc > 0) A->coeffs = (fq_zech_bpoly_struct *) flint_realloc(A->coeffs, len * sizeof(fq_zech_bpoly_struct)); else A->coeffs = (fq_zech_bpoly_struct *) flint_malloc( len * sizeof(fq_zech_bpoly_struct)); for (i = A->alloc; i < len; i++) fq_zech_bpoly_init(A->coeffs + i, ctx); A->alloc = len; } void fq_zech_tpoly_clear(fq_zech_tpoly_t A, const fq_zech_ctx_t ctx) { if (A->alloc > 0) { slong i; for (i = 0; i < A->alloc; i++) fq_zech_bpoly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } } flint-3.1.3/src/fq_zech_poly.h000066400000000000000000000023161461254215100162570ustar00rootroot00000000000000/* Copyright (C) 2012 Andres Goens Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_POLY_H #define FQ_ZECH_POLY_H #ifdef FQ_ZECH_POLY_INLINES_C #define FQ_ZECH_POLY_INLINE #define FQ_POLY_TEMPLATES_INLINE #else #define FQ_ZECH_POLY_INLINE static inline #define FQ_POLY_TEMPLATES_INLINE static inline #endif #include "fq_zech_types.h" #define FQ_ZECH_POLY_DIVREM_DIVCONQUER_CUTOFF 16 #define FQ_ZECH_COMPOSE_MOD_LENH_CUTOFF 6 #define FQ_ZECH_COMPOSE_MOD_PREINV_LENH_CUTOFF 6 #define FQ_ZECH_SQR_CLASSICAL_CUTOFF 100 #define FQ_ZECH_MUL_CLASSICAL_CUTOFF 90 #define FQ_ZECH_MULLOW_CLASSICAL_CUTOFF 90 #define FQ_ZECH_POLY_HGCD_CUTOFF 35 #define FQ_ZECH_POLY_GCD_CUTOFF 96 #define FQ_ZECH_POLY_SMALL_GCD_CUTOFF 96 #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_zech_poly/000077500000000000000000000000001461254215100161045ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_poly/inlines.c000066400000000000000000000007071461254215100177150ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_POLY_INLINES_C #include "flint.h" #include "fq_zech_poly.h" flint-3.1.3/src/fq_zech_poly/profile/000077500000000000000000000000001461254215100175445ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_poly/profile/p-factor_kaltofen_shoup_vs_fq_nmod_poly.c000066400000000000000000000064521461254215100300110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #define nalgs 2 #define ncases 1 #define cpumin 2 int main(int argc, char** argv) { slong s[nalgs]; int c, n, len, ext, reps = 0; slong j; ulong p; fmpz_t temp; fq_zech_poly_t f, g; fq_nmod_poly_t fn; fq_zech_ctx_t ctx; fq_nmod_ctx_t ctxn; FLINT_TEST_INIT(state); p = strtoull(argv[1], NULL, 10); fmpz_init(temp); fmpz_set_str(temp, argv[2], 10); ext = fmpz_get_si(temp); fmpz_set_str(temp, argv[3], 10); len = fmpz_get_si(temp); fq_nmod_ctx_init_ui(ctxn, p, ext, "a"); fq_zech_ctx_init_fq_nmod_ctx(ctx, ctxn); fq_zech_poly_init(f, ctx); fq_zech_poly_init(g, ctx); fq_nmod_poly_init(fn, ctxn); for (c = 0; c < nalgs; c++) { s[c] = WORD(0); } for (n = 0; n < ncases; n++) { timeit_t t[nalgs]; int l, loops = 1; fq_zech_poly_factor_t res; fq_nmod_poly_factor_t resn; /* Construct random elements of fq */ { fq_zech_poly_randtest_irreducible(f, state, len + 1, ctx); fq_zech_poly_randtest_irreducible(g, state, len + 2, ctx); fq_zech_poly_mul(f, f, g, ctx); fq_zech_poly_make_monic(f, f, ctx); fq_nmod_poly_fit_length(fn, f->length, ctxn); for (j = 0; j < f->length; j++) { fq_zech_get_fq_nmod(fn->coeffs + j, f->coeffs + j, ctx); } _fq_nmod_poly_set_length(fn, f->length, ctxn); } loop: fflush(stdout); timeit_start(t[0]); for (l = 0; l < loops; l++) { fq_zech_poly_factor_init(res, ctx); fq_zech_poly_factor_kaltofen_shoup(res, f, ctx); fq_zech_poly_factor_clear(res, ctx); } timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) { fq_nmod_poly_factor_init(resn, ctxn); fq_nmod_poly_factor_kaltofen_shoup(resn, fn, ctxn); fq_nmod_poly_factor_clear(resn, ctxn); } timeit_stop(t[1]); for (c = 0; c < nalgs; c++) if (t[c]->cpu <= cpumin) { loops += 2; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]->cpu; reps += loops; } for (c = 0; c < nalgs; c++) { flint_printf("%20f ", s[c] / (double) reps); fflush(stdout); } printf("\n"); fq_zech_poly_clear(f, ctx); fq_zech_poly_clear(g, ctx); fq_nmod_poly_clear(fn, ctxn); fq_zech_ctx_clear(ctx); fq_nmod_ctx_clear(ctxn); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq_zech_poly/profile/p-factor_vs_fq_nmod.c000066400000000000000000000062371461254215100236460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "profiler.h" #define nalgs 2 #define cpumin 2 #define ncases 10 int main(int argc, char** argv) { ulong p; int c, n, reps = 0; slong d, len, i; fq_nmod_ctx_t ctx; fq_zech_ctx_t ctx_zech; fq_nmod_poly_t f, g; fq_zech_poly_t fz, gz; double s[nalgs]; FLINT_TEST_INIT(state); p = strtoull(argv[1], NULL, 10); d = atol(argv[2]); len = atol(argv[3]); fq_nmod_ctx_init_ui(ctx, p, d, "a"); fq_zech_ctx_init_fq_nmod_ctx(ctx_zech, ctx); fq_nmod_poly_init(f, ctx); fq_nmod_poly_init(g, ctx); fq_zech_poly_init(fz, ctx_zech); fq_zech_poly_init(gz, ctx_zech); for (c = 0; c < nalgs; c++) s[c] = 0.0; for (n = 0; n < ncases; n++) { double t[nalgs]; int l, loops = 1; fq_nmod_poly_factor_t res; fq_zech_poly_factor_t resz; /* Construct random elements of fq[x] */ { fq_nmod_poly_randtest_monic(f, state, len, ctx); fq_zech_poly_fit_length(fz, len, ctx_zech); for (i = 0; i < f->length; i++) fq_zech_set_fq_nmod(fz->coeffs + i, f->coeffs + i, ctx_zech); _fq_zech_poly_set_length(fz, len, ctx_zech); _fq_zech_poly_normalise(fz, ctx_zech); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { fq_nmod_poly_factor_init(res, ctx); fq_nmod_poly_factor_kaltofen_shoup(res, f, ctx); fq_nmod_poly_factor_clear(res, ctx); } prof_stop(); t[0] += get_clock(0); t[1] = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { fq_zech_poly_factor_init(resz, ctx_zech); fq_zech_poly_factor_kaltofen_shoup(resz, fz, ctx_zech); fq_zech_poly_factor_clear(resz, ctx_zech); } prof_stop(); t[1] += get_clock(0); for (c = 0; c < nalgs; c++) if (t[c] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (c = 0; c < nalgs; c++) s[c] += t[c]; reps += loops; } for (c = 0; c < nalgs; c++) { printf("%20f", s[c] / (double) reps); fflush(stdout); } printf("\n"); fq_nmod_poly_clear(f, ctx); fq_nmod_poly_clear(g, ctx); fq_zech_poly_clear(fz, ctx_zech); fq_zech_poly_clear(gz, ctx_zech); fq_nmod_ctx_clear(ctx); fq_zech_ctx_clear(ctx_zech); FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/fq_zech_poly/profile/p-factor_xnpxp1.c000066400000000000000000000012221461254215100227360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/profile/p-factor_xnpxp1.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/profile/p-is_irreducible.c000066400000000000000000000012231461254215100231270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/profile/p-is_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/profile/p-iterated_frobenius.c000066400000000000000000000012261461254215100240230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "ulong_extras.h" #include "fq_zech.h" #include "fq_zech_mat.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/profile/p-iterated_frobenius.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/profile/p-iterated_frobenius_table.c000066400000000000000000000012341461254215100251710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "ulong_extras.h" #include "fq_zech.h" #include "fq_zech_mat.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/profile/p-iterated_frobenius_table.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/profile/p-mullow.c000066400000000000000000000011271461254215100214650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/profile/p-mullow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/profile/p-sqr.c000066400000000000000000000011241461254215100207500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/profile/p-sqr.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/000077500000000000000000000000001461254215100170635ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_poly/test/main.c000066400000000000000000000131301461254215100201510ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_series.c" #include "t-compose.c" #include "t-compose_mod_brent_kung.c" #include "t-compose_mod_brent_kung_preinv.c" #include "t-compose_mod.c" #include "t-compose_mod_horner.c" #include "t-compose_mod_horner_preinv.c" #include "t-compose_mod_preinv.c" #include "t-deflate.c" #include "t-derivative.c" #include "t-div.c" #include "t-divides.c" #include "t-div_newton_n_preinv.c" #include "t-divrem.c" #include "t-divrem_newton_n_preinv.c" #include "t-div_series.c" #include "t-equal_trunc.c" #include "t-evaluate_fq.c" #include "t-evaluate_fq_vec_fast.c" #include "t-gcd.c" #include "t-gcd_euclidean_f.c" #include "t-get_str.c" #include "t-get_str_pretty.c" #include "t-hamming_weight.c" #include "t-inflate.c" #include "t-inv_series_newton.c" #include "t-invsqrt_series.c" #include "t-make_monic.c" #include "t-mul.c" #include "t-mul_classical.c" #include "t-mulhigh.c" #include "t-mulhigh_classical.c" #include "t-mul_KS.c" #include "t-mullow.c" #include "t-mullow_classical.c" #include "t-mullow_KS.c" #include "t-mulmod.c" #include "t-mulmod_preinv.c" #include "t-neg.c" #include "t-pow.c" #include "t-powmod_fmpz_binexp.c" #include "t-powmod_fmpz_binexp_preinv.c" #include "t-powmod_fmpz_sliding_preinv.c" #include "t-powmod_ui_binexp.c" #include "t-powmod_ui_binexp_preinv.c" #include "t-powmod_x_fmpz_preinv.c" #include "t-pow_trunc_binexp.c" #include "t-pow_trunc.c" #include "t-randtest_irreducible.c" #include "t-scalar_addmul_fq.c" #include "t-scalar_div_fq.c" #include "t-scalar_mul_fq.c" #include "t-scalar_submul_fq.c" #include "t-set_fmpz_mod_poly.c" #include "t-set_nmod_poly.c" #include "t-set_trunc.c" #include "t-shift_left_right.c" #include "t-sqr.c" #include "t-sqr_classical.c" #include "t-sqr_KS.c" #include "t-sqrt.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-xgcd.c" #include "t-xgcd_euclidean_f.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_zech_poly_add), TEST_FUNCTION(fq_zech_poly_add_series), TEST_FUNCTION(fq_zech_poly_compose), TEST_FUNCTION(fq_zech_poly_compose_mod_brent_kung), TEST_FUNCTION(fq_zech_poly_compose_mod_brent_kung_preinv), TEST_FUNCTION(fq_zech_poly_compose_mod), TEST_FUNCTION(fq_zech_poly_compose_mod_horner), TEST_FUNCTION(fq_zech_poly_compose_mod_horner_preinv), TEST_FUNCTION(fq_zech_poly_compose_mod_preinv), TEST_FUNCTION(fq_zech_poly_deflate), TEST_FUNCTION(fq_zech_poly_derivative), TEST_FUNCTION(fq_zech_poly_div), TEST_FUNCTION(fq_zech_poly_divides), TEST_FUNCTION(fq_zech_poly_div_newton_n_preinv), TEST_FUNCTION(fq_zech_poly_divrem), TEST_FUNCTION(fq_zech_poly_divrem_newton_n_preinv), TEST_FUNCTION(fq_zech_poly_div_series), TEST_FUNCTION(fq_zech_poly_equal_trunc), TEST_FUNCTION(fq_zech_poly_evaluate_fq), TEST_FUNCTION(fq_zech_poly_evaluate_fq_zech_vec_fast), TEST_FUNCTION(fq_zech_poly_gcd), TEST_FUNCTION(fq_zech_poly_gcd_euclidean_f), TEST_FUNCTION(fq_zech_poly_get_str), TEST_FUNCTION(fq_zech_poly_get_str_pretty), TEST_FUNCTION(fq_zech_poly_hamming_weight), TEST_FUNCTION(fq_zech_poly_inflate), TEST_FUNCTION(fq_zech_poly_inv_series_newton), TEST_FUNCTION(fq_zech_poly_invsqrt_series), TEST_FUNCTION(fq_zech_poly_make_monic), TEST_FUNCTION(fq_zech_poly_mul), TEST_FUNCTION(fq_zech_poly_mul_classical), TEST_FUNCTION(fq_zech_poly_mulhigh), TEST_FUNCTION(fq_zech_poly_mulhigh_classical), TEST_FUNCTION(fq_zech_poly_mul_KS), TEST_FUNCTION(fq_zech_poly_mullow), TEST_FUNCTION(fq_zech_poly_mullow_classical), TEST_FUNCTION(fq_zech_poly_mullow_KS), TEST_FUNCTION(fq_zech_poly_mulmod), TEST_FUNCTION(fq_zech_poly_mulmod_preinv), TEST_FUNCTION(fq_zech_poly_neg), TEST_FUNCTION(fq_zech_poly_pow), TEST_FUNCTION(fq_zech_poly_powmod_fmpz_binexp), TEST_FUNCTION(fq_zech_poly_powmod_fmpz_binexp_preinv), TEST_FUNCTION(fq_zech_poly_powmod_fmpz_sliding_preinv), TEST_FUNCTION(fq_zech_poly_powmod_ui_binexp), TEST_FUNCTION(fq_zech_poly_powmod_ui_binexp_preinv), TEST_FUNCTION(fq_zech_poly_powmod_x_fmpz_preinv), TEST_FUNCTION(fq_zech_poly_pow_trunc_binexp), TEST_FUNCTION(fq_zech_poly_pow_trunc), TEST_FUNCTION(fq_zech_poly_randtest_irreducible), TEST_FUNCTION(fq_zech_poly_scalar_addmul_fq), TEST_FUNCTION(fq_zech_poly_scalar_div_fq), TEST_FUNCTION(fq_zech_poly_scalar_mul_fq), TEST_FUNCTION(fq_zech_poly_scalar_submul_fq), TEST_FUNCTION(fq_zech_poly_set_fmpz_mod_poly), TEST_FUNCTION(fq_zech_poly_set_nmod_poly), TEST_FUNCTION(fq_zech_poly_set_trunc), TEST_FUNCTION(fq_zech_poly_shift_left_right), TEST_FUNCTION(fq_zech_poly_sqr), TEST_FUNCTION(fq_zech_poly_sqr_classical), TEST_FUNCTION(fq_zech_poly_sqr_KS), TEST_FUNCTION(fq_zech_poly_sqrt), TEST_FUNCTION(fq_zech_poly_sqrt_series), TEST_FUNCTION(fq_zech_poly_sub), TEST_FUNCTION(fq_zech_poly_sub_series), TEST_FUNCTION(fq_zech_poly_xgcd), TEST_FUNCTION(fq_zech_poly_xgcd_euclidean_f) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_zech_poly/test/t-add.c000066400000000000000000000010531461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-add_series.c000066400000000000000000000010621461254215100215710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-add_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-compose.c000066400000000000000000000010571461254215100211400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-compose.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-compose_mod.c000066400000000000000000000010631461254215100217740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-compose_mod.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000010761461254215100242160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-compose_mod_brent_kung.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000011051461254215100255720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-compose_mod_brent_kung_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-compose_mod_horner.c000066400000000000000000000010721461254215100233510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-compose_mod_horner.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-compose_mod_horner_preinv.c000066400000000000000000000011011461254215100247250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-compose_mod_horner_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-compose_mod_preinv.c000066400000000000000000000010721461254215100233570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-compose_mod_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-deflate.c000066400000000000000000000010571461254215100210770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-deflate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-derivative.c000066400000000000000000000010621461254215100216310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-derivative.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-div.c000066400000000000000000000010531461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-div.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-div_newton_n_preinv.c000066400000000000000000000010731461254215100235450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-div_newton_n_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-div_series.c000066400000000000000000000010621461254215100216230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-div_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-divides.c000066400000000000000000000010571461254215100211220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-divides.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-divrem.c000066400000000000000000000010561461254215100207600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-divrem.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000010761461254215100242540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-divrem_newton_n_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-equal_trunc.c000066400000000000000000000010631461254215100220120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-equal_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-evaluate_fq.c000066400000000000000000000010631461254215100217640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-evaluate_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-evaluate_fq_vec_fast.c000066400000000000000000000012561461254215100236420ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 William Hart Copyright (C) 2011, 2012 Fredrik Johansson Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-evaluate_fq_vec_fast.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-gcd.c000066400000000000000000000010531461254215100202240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-gcd.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-gcd_euclidean_f.c000066400000000000000000000010671461254215100225470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-gcd_euclidean_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-get_str.c000066400000000000000000000010571461254215100211420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-get_str.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-get_str_pretty.c000066400000000000000000000010661461254215100225510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-get_str_pretty.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-hamming_weight.c000066400000000000000000000010661461254215100224620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-hamming_weight.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-inflate.c000066400000000000000000000010571461254215100211150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-inflate.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-inv_series_newton.c000066400000000000000000000010711461254215100232270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-inv_series_newton.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-invsqrt_series.c000066400000000000000000000010661461254215100225530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-invsqrt_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-make_monic.c000066400000000000000000000010621461254215100215710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-make_monic.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mul.c000066400000000000000000000010531461254215100202640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mul.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mul_KS.c000066400000000000000000000010561461254215100206640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mul_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mul_classical.c000066400000000000000000000010651461254215100223050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mul_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mulhigh.c000066400000000000000000000010571461254215100211300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mulhigh.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mulhigh_classical.c000066400000000000000000000010711461254215100231420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mulhigh_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mullow.c000066400000000000000000000010561461254215100210110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mullow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mullow_KS.c000066400000000000000000000010611461254215100214020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mullow_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mullow_classical.c000066400000000000000000000010701461254215100230230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mullow_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mulmod.c000066400000000000000000000010561461254215100207670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mulmod.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-mulmod_preinv.c000066400000000000000000000010651461254215100223520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-mulmod_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-neg.c000066400000000000000000000010531461254215100202400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-pow.c000066400000000000000000000010531461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-pow.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-pow_trunc.c000066400000000000000000000010611461254215100215060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-pow_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-pow_trunc_binexp.c000066400000000000000000000010701461254215100230530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-pow_trunc_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000010721461254215100233760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-powmod_fmpz_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000011011461254215100247520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-powmod_fmpz_binexp_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000011021461254215100251170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-powmod_fmpz_sliding_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-powmod_ui_binexp.c000066400000000000000000000010701461254215100230350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-powmod_ui_binexp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000010771461254215100244270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-powmod_ui_binexp_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000010741461254215100237450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-powmod_x_fmpz_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-randtest_irreducible.c000066400000000000000000000011351461254215100236650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-randtest_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-scalar_addmul_fq.c000066400000000000000000000010701461254215100227470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-scalar_addmul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-scalar_div_fq.c000066400000000000000000000010651461254215100222670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-scalar_div_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-scalar_mul_fq.c000066400000000000000000000010651461254215100223020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-scalar_mul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-scalar_submul_fq.c000066400000000000000000000010701461254215100230100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-scalar_submul_fq.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-set_fmpz_mod_poly.c000066400000000000000000000042001461254215100232150ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "fq_zech.h" #include "fq_zech_poly.h" TEST_FUNCTION_START(fq_zech_poly_set_fmpz_mod_poly, state) { int i, result; /* Check litfed polynomials by evaluating at random points */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong len; fq_zech_ctx_t ctx; fq_zech_t r, s; fq_zech_poly_t a; fmpz_mod_poly_t b; fmpz_t p; fmpz_mod_ctx_t ctxp; len = n_randint(state, 15) + 1; fq_zech_ctx_init_randtest(ctx, state, 3); fq_zech_init(r, ctx); fq_zech_init(s, ctx); fq_zech_poly_init(a, ctx); fmpz_mod_ctx_init_ui(ctxp, fq_zech_ctx_prime(ctx)); fmpz_mod_poly_init(b, ctxp); fmpz_init(p); fmpz_mod_poly_randtest(b, state, len, ctxp); fmpz_randtest(p, state, 10); fq_zech_poly_set_fmpz_mod_poly(a, b, ctx); fq_zech_set_fmpz(r, p, ctx); fq_zech_poly_evaluate_fq_zech(r, a, r, ctx); fmpz_mod_poly_evaluate_fmpz(p, b, p, ctxp); fq_zech_set_fmpz(s, p, ctx); result = fq_zech_equal(r, s, ctx); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("CTX\n"); fq_zech_ctx_print(ctx); flint_printf("\nb = "); fmpz_mod_poly_print_pretty(b, "X", ctxp); flint_printf("\np = "); fmpz_print(p); flint_printf("\n"); fflush(stdout); flint_abort(); } fq_zech_clear(r, ctx); fq_zech_clear(s, ctx); fmpz_mod_poly_clear(b, ctxp); fmpz_mod_ctx_clear(ctxp); fmpz_clear(p); fq_zech_poly_clear(a, ctx); fq_zech_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/fq_zech_poly/test/t-set_nmod_poly.c000066400000000000000000000010651461254215100223450ustar00rootroot00000000000000/* Copyright (C) 2017 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-set_nmod_poly.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-set_trunc.c000066400000000000000000000010611461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-set_trunc.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-shift_left_right.c000066400000000000000000000010701461254215100230120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-shift_left_right.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-sqr.c000066400000000000000000000010531461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-sqr.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-sqr_KS.c000066400000000000000000000010561461254215100206740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-sqr_KS.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-sqr_classical.c000066400000000000000000000010651461254215100223150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-sqr_classical.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-sqrt.c000066400000000000000000000010541461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-sqrt.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-sqrt_series.c000066400000000000000000000010631461254215100220330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-sqrt_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-sub.c000066400000000000000000000010531461254215100202600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-sub_series.c000066400000000000000000000010621461254215100216320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-sub_series.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-xgcd.c000066400000000000000000000010541461254215100204150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-xgcd.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly/test/t-xgcd_euclidean_f.c000066400000000000000000000010701461254215100227310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/test/t-xgcd_euclidean_f.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor.h000066400000000000000000000020261461254215100176130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_POLY_FACTOR_H #define FQ_ZECH_POLY_FACTOR_H #ifdef FQ_ZECH_POLY_FACTOR_INLINES_C #define FQ_POLY_FACTOR_TEMPLATES_INLINE #define FQ_ZECH_POLY_FACTOR_INLINE #else #define FQ_POLY_FACTOR_TEMPLATES_INLINE static inline #define FQ_ZECH_POLY_FACTOR_INLINE static inline #endif #include "fq_zech_types.h" int FQ_ZECH_POLY_ITERATED_FROBENIUS_CUTOFF(const fq_zech_ctx_t ctx, slong length); #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates.h" #undef CAP_T #undef T void fq_zech_poly_factor_get_poly(fq_zech_poly_t z, const fq_zech_poly_factor_t fac, slong i, const fq_zech_ctx_t ctx); #endif flint-3.1.3/src/fq_zech_poly_factor/000077500000000000000000000000001461254215100174425ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_poly_factor/inlines.c000066400000000000000000000012621461254215100212500ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_POLY_FACTOR_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fq_zech.h" #include "fq_zech_poly.h" void fq_zech_poly_factor_get_poly(fq_zech_poly_t z, const fq_zech_poly_factor_t fac, slong i, const fq_zech_ctx_t ctx) { fq_zech_poly_set(z, fac->poly + i, ctx); } flint-3.1.3/src/fq_zech_poly_factor/iterated_frobenius_cutoff.c000066400000000000000000000013451461254215100250340ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fq_zech.h" #include "fq_zech_poly_factor.h" int FQ_ZECH_POLY_ITERATED_FROBENIUS_CUTOFF(const fq_zech_ctx_t ctx, slong length) { int result; ulong q; q = fq_zech_ctx_order_ui(ctx); if (2 * FLINT_BIT_COUNT(q) < 3 * (n_sqrt(length) + 1)) result = 1; else result = 0; return result; } flint-3.1.3/src/fq_zech_poly_factor/test/000077500000000000000000000000001461254215100204215ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_poly_factor/test/main.c000066400000000000000000000036111461254215100215120ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor_berlekamp.c" #include "t-factor.c" #include "t-factor_cantor_zassenhaus.c" #include "t-factor_distinct_deg.c" #include "t-factor_equal_deg_prob.c" #include "t-factor_kaltofen_shoup.c" #include "t-factor_split_single.c" #include "t-factor_squarefree.c" #include "t-is_irreducible_ben_or.c" #include "t-is_irreducible.c" #include "t-is_irreducible_ddf.c" #include "t-is_squarefree.c" #include "t-iterated_frobenius_preinv.c" #include "t-roots.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_zech_poly_factor_berlekamp), TEST_FUNCTION(fq_zech_poly_factor), TEST_FUNCTION(fq_zech_poly_factor_cantor_zassenhaus), TEST_FUNCTION(fq_zech_poly_factor_distinct_deg), TEST_FUNCTION(fq_zech_poly_factor_equal_deg_prob), TEST_FUNCTION(fq_zech_poly_factor_kaltofen_shoup), TEST_FUNCTION(fq_zech_poly_factor_split_single), TEST_FUNCTION(fq_zech_poly_factor_squarefree), TEST_FUNCTION(fq_zech_poly_factor_is_irreducible_ben_or), TEST_FUNCTION(fq_zech_poly_factor_is_irreducible), TEST_FUNCTION(fq_zech_poly_factor_is_irreducible_ddf), TEST_FUNCTION(fq_zech_poly_factor_is_squarefree), TEST_FUNCTION(fq_zech_poly_factor_iterated_frobenius_preinv), TEST_FUNCTION(fq_zech_poly_factor_roots) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_zech_poly_factor/test/t-factor.c000066400000000000000000000011261461254215100223040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000011401461254215100243220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor_berlekamp.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000011501461254215100261130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor_cantor_zassenhaus.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000011431461254215100250230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor_distinct_deg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000011451461254215100253350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor_equal_deg_prob.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000011451461254215100254060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor_kaltofen_shoup.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-factor_split_single.c000066400000000000000000000011501461254215100250550ustar00rootroot00000000000000/* Copyright (C) 2019 Edouard Rousseau This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor_split_single.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-factor_squarefree.c000066400000000000000000000011411461254215100245230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-factor_squarefree.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-is_irreducible.c000066400000000000000000000011361461254215100240130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-is_irreducible.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-is_irreducible_ben_or.c000066400000000000000000000011451461254215100253370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-is_irreducible_ben_or.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000011421461254215100246250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-is_irreducible_ddf.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-is_squarefree.c000066400000000000000000000011351461254215100236630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-is_squarefree.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-iterated_frobenius_preinv.c000066400000000000000000000011511461254215100262640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-iterated_frobenius_preinv.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_poly_factor/test/t-roots.c000066400000000000000000000011301461254215100221670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/test/t-roots.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_types.h000066400000000000000000000032751461254215100164450ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_TYPES_H #define FQ_ZECH_TYPES_H #include "fq_nmod_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { mp_limb_t value; } fq_zech_struct; typedef fq_zech_struct fq_zech_t[1]; typedef struct { ulong qm1; /* q - 1 */ ulong qm1o2; /* (q - 1) / 2 or 1 when p == 2 */ ulong qm1opm1; /* (q - 1) / (p - 1) */ ulong p; double ppre; ulong prime_root; /* primitive root for prime subfield */ ulong * zech_log_table; ulong * prime_field_table; ulong * eval_table; fq_nmod_ctx_struct * fq_nmod_ctx; int owns_fq_nmod_ctx; int is_conway; /* whether field was generated using Flint Conway tables (assures primitivity) */ } fq_zech_ctx_struct; typedef fq_zech_ctx_struct fq_zech_ctx_t[1]; typedef struct { fq_zech_struct * entries; slong r; slong c; fq_zech_struct ** rows; } fq_zech_mat_struct; typedef fq_zech_mat_struct fq_zech_mat_t[1]; typedef struct { fq_zech_struct * coeffs; slong alloc; slong length; } fq_zech_poly_struct; typedef fq_zech_poly_struct fq_zech_poly_t[1]; typedef struct { fq_zech_poly_struct * poly; slong * exp; slong num; slong alloc; } fq_zech_poly_factor_struct; typedef fq_zech_poly_factor_struct fq_zech_poly_factor_t[1]; #ifdef __cplusplus } #endif #endif /* FQ_ZECH_TYPES_H */ flint-3.1.3/src/fq_zech_vec.h000066400000000000000000000027141461254215100160530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FQ_ZECH_VEC_H #define FQ_ZECH_VEC_H #ifdef FQ_ZECH_VEC_INLINES_C #define FQ_VEC_TEMPLATES_INLINE #define FQ_ZECH_VEC_INLINE #else #define FQ_VEC_TEMPLATES_INLINE static inline #define FQ_ZECH_VEC_INLINE static inline #endif #include "fq_zech_types.h" #define FQ_ZECH_VEC_NORM(vec, i, ctx) \ do { \ while ((i) && fq_zech_is_zero((vec) + (i) - 1, ctx)) \ (i)--; \ } while (0) #define FQ_ZECH_VEC_SWAP(vec1, len1, vec2, len2) \ do { \ fq_zech_struct *__t; \ slong __tn; \ __t = (vec1); \ (vec1) = (vec2); \ (vec2) = __t; \ __tn = (len1); \ (len1) = (len2); \ (len2) = __tn; \ } while (0); #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates.h" #undef CAP_T #undef T #endif flint-3.1.3/src/fq_zech_vec/000077500000000000000000000000001461254215100156765ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_vec/inlines.c000066400000000000000000000006621461254215100175070ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_VEC_INLINES_C #include "fq_zech_vec.h" flint-3.1.3/src/fq_zech_vec/test/000077500000000000000000000000001461254215100166555ustar00rootroot00000000000000flint-3.1.3/src/fq_zech_vec/test/main.c000066400000000000000000000020331461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-is_zero.c" #include "t-neg.c" #include "t-sub.c" #include "t-swap.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(fq_zech_vec_add), TEST_FUNCTION(fq_zech_vec_is_zero), TEST_FUNCTION(fq_zech_vec_neg), TEST_FUNCTION(fq_zech_vec_sub), TEST_FUNCTION(fq_zech_vec_swap), TEST_FUNCTION(fq_zech_vec_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/fq_zech_vec/test/t-add.c000066400000000000000000000010511461254215100200070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/test/t-add.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_vec/test/t-is_zero.c000066400000000000000000000010551461254215100207350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/test/t-is_zero.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_vec/test/t-neg.c000066400000000000000000000010511461254215100200300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/test/t-neg.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_vec/test/t-sub.c000066400000000000000000000010511461254215100200500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/test/t-sub.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_vec/test/t-swap.c000066400000000000000000000010521461254215100202320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/test/t-swap.c" #undef CAP_T #undef T flint-3.1.3/src/fq_zech_vec/test/t-zero.c000066400000000000000000000010521461254215100202370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/test/t-zero.c" #undef CAP_T #undef T flint-3.1.3/src/generic_files/000077500000000000000000000000001461254215100162205ustar00rootroot00000000000000flint-3.1.3/src/generic_files/clz_tab.c000066400000000000000000000025221461254215100200030ustar00rootroot00000000000000/* __clz_tab -- support for longlong.h Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this file; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* N.B: This file has been adapted from code found in GMP 4.2.1. */ #include "flint.h" #ifdef NEED_CLZ_TAB const unsigned char __flint_clz_tab[128] = { 1,2,3,3,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; #else typedef int this_file_is_empty; #endif flint-3.1.3/src/generic_files/exception.c000066400000000000000000000052101461254215100203600ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD #include static pthread_once_t abort_func_init = PTHREAD_ONCE_INIT; pthread_mutex_t abort_func_lock; void __flint_set_abort_init(void) { pthread_mutex_init(&abort_func_lock, NULL); } #endif #ifdef __GNUC__ __attribute__((noreturn)) void (*abort_func)(void) = abort; #else void (*abort_func)(void) = abort; #endif void flint_set_abort(void (*func)(void)) { #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(&abort_func_init, __flint_set_abort_init); pthread_mutex_lock(&abort_func_lock); #endif #ifdef __GNUC__ # pragma GCC diagnostic push # if defined(__clang__) # pragma GCC diagnostic ignored "-Wincompatible-function-pointer-types" # elif defined(__GNUC__) # pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" # endif #endif abort_func = func; #ifdef __GNUC__ # pragma GCC diagnostic pop #endif #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(&abort_func_lock); #endif } FLINT_NORETURN void flint_abort(void) { fflush(stdout); fflush(stderr); (*abort_func)(); } void flint_throw(flint_err_t exc, const char * msg, ...) { va_list ap; va_start(ap, msg); if (exc != FLINT_TEST_FAIL) { printf("Flint exception ("); switch (exc) { case FLINT_ERROR: printf("General error"); break; case FLINT_OVERFLOW: printf("Overflow"); break; case FLINT_IMPINV: printf("Impossible inverse"); break; case FLINT_DOMERR: printf("Domain error"); break; case FLINT_DIVZERO: printf("Divide by zero"); break; case FLINT_EXPOF: printf("Exponent overflow"); break; case FLINT_INEXACT: printf("Inexact"); break; default: printf("Unknown exception"); } printf("):\n "); } else { printf("FAIL!\n\n"); } flint_vprintf(msg, ap); va_end(ap); flint_abort(); } flint-3.1.3/src/generic_files/fscanf.c000066400000000000000000000062261461254215100176320ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" int flint_fscanf(FILE * f, const char * str, ...) { va_list ap; size_t len = strlen(str); char * str2 = flint_malloc(len + 1); int * w1 = NULL, * w2 = NULL; void * w3; double * d; ulong * wu; slong * w; int args, floating; int ret; /* deal with first substring */ size_t n = strcspn(str, "%"); strncpy(str2, str, n); str2[n] = '\0'; ret = 0; if (!fread(str2, 1, n, f) && n > 0) goto cleanup; len -= n; str += n; va_start(ap, str); while (len) /* deal with fmt spec prefixed strings */ { n = strcspn(str + 2, "%") + 2; /* be sure to skip a %% */ strncpy(str2, str, n); str2[n] = '\0'; switch (str[1]) { case 'w': if (str[2] == 'x') { wu = (ulong *) va_arg(ap, ulong *); ret += fscanf(f, WORD_FMT "x", wu); if (!fread(str2 + 3, 1, n - 3, f) && n > 3) goto cleanup; } else if (str[2] == 'u') { wu = (ulong *) va_arg(ap, ulong *); ret += fscanf(f, WORD_FMT "u", wu); if (!fread(str2 + 3, 1, n - 3, f) && n > 3) goto cleanup; } else if (str[2] == 'd') { w = (slong *) va_arg(ap, slong *); ret += fscanf(f, WORD_FMT "d", w); if (!fread(str2 + 3, 1, n - 3, f) && n > 3) goto cleanup; } else { w = (slong *) va_arg(ap, slong *); ret += fscanf(f, WORD_FMT "d", w); if (!fread(str2 + 2, 1, n - 2, f) && n > 2) goto cleanup; } break; default: /* pass to printf */ args = parse_fmt(&floating, str2); if (args) { if (args == 3) w1 = va_arg(ap, int *); if (args >= 2) w2 = va_arg(ap, int *); if (floating) { d = va_arg(ap, double *); if (args == 2) ret += fscanf(f, str2, w2, d); else if (args == 3) ret += fscanf(f, str2, w1, w2, d); else ret += fscanf(f, str2, d); } else { w3 = va_arg(ap, void *); if (args == 2) ret += fscanf(f, str2, w2, w3); else if (args == 3) ret += fscanf(f, str2, w1, w2, w3); else ret += fscanf(f, str2, w3); } } else { if (!fread(str2, 1, n, f) && n > 0) /* zero args */ goto cleanup; } } len -= n; str += n; } va_end(ap); cleanup: flint_free(str2); return ret; } flint-3.1.3/src/generic_files/gettimeofday.c000066400000000000000000000020611461254215100210440ustar00rootroot00000000000000/* We only want this file if someone is using pure windows, and not MinGW */ #if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) && (defined(_WIN64) || defined(_WIN32) || defined(_MSC_VER)) #define WIN32_LEAN_AND_MEAN #include #include #include "gettimeofday.h" int gettimeofday(struct timeval *tv, struct timezone *tz) { FILETIME ft; LARGE_INTEGER li; __int64 t; static int tzflag; if(tv) { GetSystemTimeAsFileTime(&ft); li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; t = li.QuadPart; t -= EPOCHFILETIME; t /= 10; tv->tv_sec = (long)(t / 1000000); tv->tv_usec = (long)(t % 1000000); } if (tz) { if (!tzflag) { _tzset(); tzflag++; } tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } return 0; } #else typedef int this_file_is_empty; #endif /* defined(_WIN64) */ flint-3.1.3/src/generic_files/inlines.c000066400000000000000000000006461461254215100200330ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define FLINT_INLINES_C #include "flint.h" flint-3.1.3/src/generic_files/io.c000066400000000000000000001054631461254215100170040ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include /* isdigit */ #include /* intmax_t */ #include #include /* memcpy, memcmp and strchr */ #include #include /* wchar_t and wint_t */ #include "nmod_types.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpq_types.h" #include "fmpq.h" #include "arf_types.h" #include "arb.h" #include "acb.h" /* Helper functions **********************************************************/ #define STRING_SIZE(x) (sizeof(x) - 1) #define STRING_LENGTH(x) (STRING_SIZE(x) / sizeof(char)) /* NOTE: We have to be careful here to not alter `ip'. */ static inline void __arb_neg_readonly(arb_ptr op, arb_srcptr ip) { arf_ptr op_arf; op->mid = ip->mid; op->rad = ip->rad; op_arf = &(op->mid); if (arf_is_special(op_arf)) { if (arf_is_pos_inf(op_arf)) { ARF_EXP(op_arf) = ARF_EXP_NEG_INF; } else if (arf_is_neg_inf(op_arf)) { ARF_EXP(op_arf) = ARF_EXP_POS_INF; } } else { ARF_NEG(op_arf); } } static char * __mag_get_str(mag_srcptr ip, slong digits) { arf_t ip_arf; char * str; arf_init(ip_arf); arf_set_mag(ip_arf, ip); str = arf_get_str(ip_arf, digits); arf_clear(ip_arf); return str; } static int __never_is(const void * ip) { return 0; } /* is_pm1 */ static int __ulong_is_pm1(const void * ip) { return *((const ulong *) ip) == 1; } static int __arb_is_pm1(const void * ip) { return arb_is_one(ip) || arb_equal_si(ip, -1); } static int __acb_is_pm1(const void * ip) { return acb_is_one(ip) || acb_equal_si(ip, -1); } /* is_zero */ static int __ulong_is_zero(const void * ip) { return *((ulong *) ip) == 0; } /* is_neg */ static int __fmpz_is_neg(const void * ip) { return fmpz_sgn(ip) < 0; } static int __fmpq_is_neg(const void * ip) { return __fmpz_is_neg(fmpq_numref((const fmpq *) ip)); } /* NOTE: The following function is not checking if a complex number is negative * mathematically. This simply a helper function to check whether it should * prepend with a minus or plus in the polynomial printing between terms. */ static int __acb_is_neg(const void * ip) { /* We consider a complex number z negative in this sense if it is on one of * the following forms: * * - z is purely real and its real part is negative, or * * - z is purely imaginary and its imaginary part is negative. * * We could also consider it to be negative if both the real and imaginary * part are negative. However, I (Albin) do not think this is a good idea as * it makes too complex visually. */ acb_srcptr zp = ip; arb_srcptr realzp = acb_realref(zp), imagzp = acb_imagref(zp); return (arb_is_zero(imagzp) && arb_is_negative(realzp)) || (arb_is_zero(realzp) && arb_is_negative(imagzp)); } /* Base types used in vectors, matrices and polynomials **********************/ typedef enum { ulong_type = 0, fmpz_type, fmpq_type, arb_type, acb_type, slong_type, mag_type, arf_type } flint_type_t; static inline size_t flint_type_size_in_chars(flint_type_t type) { if (type == ulong_type) return sizeof(ulong) / sizeof(char); else if (type == fmpz_type) return sizeof(fmpz) / sizeof(char); else if (type == fmpq_type) return sizeof(fmpq) / sizeof(char); else if (type == arb_type) return sizeof(arb_struct) / sizeof(char); else if (type == acb_type) return sizeof(acb_struct) / sizeof(char); else if (type == slong_type) return sizeof(slong) / sizeof(char); else if (type == mag_type) return sizeof(mag_struct) / sizeof(char); else /* if (type == arf_type) */ return sizeof(arf_struct) / sizeof(char); } /* Declaring local printing functions ****************************************/ #define FLAG_NONE (0) #define FLAG_NEG (1) #define FLAG_PAREN (1 << 1) /* Indicates printing for polynomials */ #define FLAG_IS_NEG(flag) ((flag) & FLAG_NEG) #define FLAG_IS_PAREN(flag) ((flag) & FLAG_PAREN) static size_t __ulong_fprint(FILE *, const ulong *, int); static size_t __slong_fprint(FILE *, const slong *, int); static size_t __fmpz_fprint(FILE *, const fmpz *, int); static size_t __fmpq_fprint(FILE *, const fmpq *, int); static size_t __mpz_fprint(FILE *, mpz_srcptr); static size_t __mpq_fprint(FILE *, mpq_srcptr); static size_t __mag_fprint(FILE *, mag_srcptr); static size_t __arf_fprint(FILE *, arf_srcptr); static size_t __arb_fprint(FILE *, arb_srcptr, int); static size_t __acb_fprint(FILE *, acb_srcptr, int); static size_t __nmod_fprint(FILE *, nmod_t); static size_t __fmpz_mod_ctx_fprint(FILE *, const fmpz_mod_ctx_struct *); static size_t __flint_vec_fprint(FILE *, const void *, slong, flint_type_t); static size_t __flint_mat_fprint(FILE *, const void *, flint_type_t); static size_t __flint_poly_fprint(FILE *, const void *, flint_type_t); /* flint_vfprintf and friends ************************************************/ /* TODO: Add options for compact/spacious printing. */ #define IS_FLINT_BASE_TYPE(ip, str) (memcmp(ip, str, sizeof(str) - sizeof(char)) == 0) #define IS_FLINT_TYPE(ip, str) (memcmp(ip, str "}", sizeof(str)) == 0) /* Reference used for checks: https://en.cppreference.com/w/c/io/fprintf */ #define IS_PRINTF_FLAG(chr) \ ( (chr) == '-' \ || (chr) == '+' \ || (chr) == ' ' \ || (chr) == '#' \ || (chr) == '0') #define JUMP_FLAGS(str) \ do \ { \ (str)++; \ } while (IS_PRINTF_FLAG(*(str))) #define JUMP_MINIMAL_FIELD_WIDTH_WITH_POP(str, vlist) \ do \ { \ if (isdigit(*(str))) \ { \ (str)++; \ while (isdigit(*(str))) \ (str)++; \ } \ else if (*(str) == '*') \ { \ va_arg((vlist), int); \ (str)++; \ } \ } while (0) #define JUMP_PRECISION_WITH_POP(str, vlist) \ do \ { \ if (*(str) == '.') \ { \ (str)++; \ if (isdigit(*(str))) \ { \ (str)++; \ while (isdigit(*(str))) \ (str)++; \ } \ else if (*(str) == '*') \ { \ va_arg((vlist), int); \ (str)++; \ } \ } \ } while (0) #define _IS_PRINTF_INTEGERFMT(chr) \ ( (chr) == 'd' || (chr) == 'i' \ || (chr) == 'o' \ || (chr) == 'x' || (chr) == 'X' \ || (chr) == 'u') #define _IS_PRINTF_FLOATFMT(chr) \ ( (chr) == 'f' || (chr) == 'F' \ || (chr) == 'e' || (chr) == 'E' \ || (chr) == 'a' || (chr) == 'A' \ || (chr) == 'g' || (chr) == 'G') /* "Generic" ones */ #define IS_PRINTF_CHARFMT(str) \ ((str)[0] == 'h' && (str)[1] == 'h' && _IS_PRINTF_INTEGERFMT((str)[2])) #define IS_PRINTF_SHORTFMT(str) \ ((str)[0] == 'h' && _IS_PRINTF_INTEGERFMT((str)[1])) #define IS_PRINTF_INTFMT(str) \ ((str)[0] == 'c' || _IS_PRINTF_INTEGERFMT((str)[0])) #define IS_PRINTF_LONGFMT(str) \ ((str)[0] == 'l' && _IS_PRINTF_INTEGERFMT((str)[1])) #define IS_PRINTF_LONGLONGFMT(str) \ ((str)[0] == 'l' && (str)[1] == 'l' && _IS_PRINTF_INTEGERFMT((str)[2])) #define IS_PRINTF_INTMAXFMT(str) \ ((str)[0] == 'j' && _IS_PRINTF_INTEGERFMT((str)[1])) #define IS_PRINTF_SIZEFMT(str) \ ((str)[0] == 'z' && _IS_PRINTF_INTEGERFMT((str)[1])) #define IS_PRINTF_PTRDIFFFMT(str) \ ((str)[0] == 't' && _IS_PRINTF_INTEGERFMT((str)[1])) #define IS_FLINT_PRINTF_ULONGFMT(str) \ ((str)[0] == 'w' && _IS_PRINTF_INTEGERFMT((str)[1])) #define IS_PRINTF_DOUBLEFMT(str) \ (_IS_PRINTF_FLOATFMT((str)[0]) \ || ((str)[0] == 'l' && _IS_PRINTF_FLOATFMT((str)[1]))) #define IS_PRINTF_LONGDOUBLEFMT(str) \ ((str)[0] == 'L' && _IS_PRINTF_FLOATFMT((str)[1])) /* "Special" ones */ #define IS_PRINTF_POINTERFMT(str) \ ((str)[0] == 'p') #define IS_PRINTF_CHARPFMT(str) \ ((str)[0] == 's') #define IS_PRINTF_WINTFMT(str) \ ((str)[0] == 'l' && (str)[1] == 'c') #define IS_PRINTF_WCHARPFMT(str) \ ((str)[0] == 'l' && (str)[1] == 's') int flint_vfprintf(FILE * fs, const char * ip, va_list vlist) { size_t iplen; const char * ipcur; char * op, * opcur; size_t res; va_list vlist_cpy; int tmp; TMP_INIT; res = 0; iplen = strlen(ip); TMP_START; #if defined(_LONG_LONG_LIMB) /* If mp_limb_t is long long, then `%(format args...)w' -> `%(format args...)ll'. The highest ratio between length of input and output string after this conversion is 4 / 3, which is obtained if `ip = "%wd...%wd"'. */ op = TMP_ALLOC(sizeof(char) * (iplen + iplen / 3 + 1)); #else /* Same length due to length of "w" is equal to length of "l". */ op = TMP_ALLOC(sizeof(char) * (iplen + 1)); #endif opcur = op; while (1) { continue_while_from_flint_type: ipcur = ip; va_copy(vlist_cpy, vlist); continue_while: ipcur = strchr(ipcur, '%'); if (ipcur == NULL) break; /* Reached end of string */ /* Check if "%%" */ if (ipcur[1] == '%') { ipcur += 2; goto continue_while; } /* Check if "%{FLINT_TYPE}" */ if (ipcur[1] == '{') goto print_flint_type; /* Check if "%(format args...)w" */ JUMP_FLAGS(ipcur); /* NOTE: If the minimal field with and/or precision is specified, but * the format is invalid, the following pops will be invalid as well. */ JUMP_MINIMAL_FIELD_WIDTH_WITH_POP(ipcur, vlist); JUMP_PRECISION_WITH_POP(ipcur, vlist); if (IS_FLINT_PRINTF_ULONGFMT(ipcur)) { size_t cpsz; ipcur += 2; /* To include 'w' and following format specifier */ cpsz = ipcur - ip; memcpy(opcur, ip, sizeof(char) * cpsz); ip = ipcur; #if defined(_LONG_LONG_LIMB) opcur += cpsz + 1; opcur[-1] = opcur[-2]; opcur[-2] = 'l'; opcur[-3] = 'l'; #else opcur += cpsz; opcur[-2] = 'l'; #endif /* Pop entry from vlist (still present in vlist_cpy) */ va_arg(vlist, ulong); } else if (IS_PRINTF_INTFMT(ipcur) || IS_PRINTF_CHARFMT(ipcur) || IS_PRINTF_SHORTFMT(ipcur)) va_arg(vlist, int); else if (IS_PRINTF_DOUBLEFMT(ipcur)) va_arg(vlist, double); else if (IS_PRINTF_SIZEFMT(ipcur)) va_arg(vlist, size_t); else if (IS_PRINTF_CHARPFMT(ipcur)) va_arg(vlist, char *); else if (IS_PRINTF_LONGFMT(ipcur)) va_arg(vlist, long int); else if (IS_PRINTF_LONGLONGFMT(ipcur)) va_arg(vlist, long long int); else if (IS_PRINTF_INTMAXFMT(ipcur)) va_arg(vlist, intmax_t); else if (IS_PRINTF_PTRDIFFFMT(ipcur)) va_arg(vlist, ptrdiff_t); else if (IS_PRINTF_LONGDOUBLEFMT(ipcur)) va_arg(vlist, long double); else if (IS_PRINTF_POINTERFMT(ipcur)) va_arg(vlist, void *); else if (IS_PRINTF_WCHARPFMT(ipcur)) va_arg(vlist, wchar_t *); else if (IS_PRINTF_WINTFMT(ipcur)) { /* NOTE: MinGW defines wint_t as unsigned short int */ if (sizeof(wint_t) >= sizeof(int)) va_arg(vlist, wint_t); else va_arg(vlist, int); } goto continue_while; } { size_t cpsz = strlen(ip); memcpy(opcur, ip, sizeof(char) * cpsz); opcur[cpsz] = '\0'; } tmp = vfprintf(fs, op, vlist_cpy); if (tmp < 0) res = tmp; else res += tmp; end: TMP_END; va_end(vlist_cpy); return (int) res; print_flint_type: /* Print now to be able to print FLINT types */ { size_t cpsz = ipcur - ip; memcpy(opcur, ip, sizeof(char) * cpsz); opcur[cpsz] = '\0'; } tmp = vfprintf(fs, op, vlist_cpy); if (tmp < 0) { res = tmp; goto end; } else res += tmp; /* vlist_cpy is now invalid */ va_end(vlist_cpy); opcur = op; ip = ipcur + 2; /* Now `ip' points to "FLINT_TYPE..." */ if (IS_FLINT_BASE_TYPE(ip, "ulong")) { if (IS_FLINT_TYPE(ip, "ulong")) { res += fprintf(fs, WORD_FMT "u", va_arg(vlist, ulong)); ip += STRING_LENGTH("ulong}"); } else if (IS_FLINT_TYPE(ip, "ulong*")) { const ulong * vec = va_arg(vlist, const ulong *); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, ulong_type); ip += STRING_LENGTH("ulong*}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "slong")) { if (IS_FLINT_TYPE(ip, "slong")) { res += fprintf(fs, WORD_FMT "d", va_arg(vlist, slong)); ip += STRING_LENGTH("slong}"); } else if (IS_FLINT_TYPE(ip, "slong*")) { const slong * vec = va_arg(vlist, const slong *); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, slong_type); ip += STRING_LENGTH("slong*}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "nmod")) { if (IS_FLINT_TYPE(ip, "nmod")) { res += __nmod_fprint(fs, va_arg(vlist, nmod_t)); ip += STRING_LENGTH("nmod}"); } else if (IS_FLINT_TYPE(ip, "nmod_mat")) { res += __flint_mat_fprint(fs, va_arg(vlist, const nmod_mat_struct *), ulong_type); ip += STRING_LENGTH("nmod_mat}"); } else if (IS_FLINT_TYPE(ip, "nmod_poly")) { res += __flint_poly_fprint(fs, va_arg(vlist, const nmod_poly_struct *), ulong_type); ip += STRING_LENGTH("nmod_poly}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "fmpz")) /* fmpz or fmpz_mod base type */ { if (IS_FLINT_TYPE(ip, "fmpz")) { res += __fmpz_fprint(fs, va_arg(vlist, const fmpz *), FLAG_NONE); ip += STRING_LENGTH("fmpz}"); } else if (IS_FLINT_TYPE(ip, "fmpz*")) { const fmpz * vec = va_arg(vlist, const fmpz *); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, fmpz_type); ip += STRING_LENGTH("fmpz*}"); } else if (IS_FLINT_TYPE(ip, "fmpz_mat")) { res += __flint_mat_fprint(fs, va_arg(vlist, const fmpz_mat_struct *), fmpz_type); ip += STRING_LENGTH("fmpz_mat}"); } else if (IS_FLINT_TYPE(ip, "fmpz_poly")) { res += __flint_poly_fprint(fs, va_arg(vlist, const fmpz_poly_struct *), fmpz_type); ip += STRING_LENGTH("fmpz_poly}"); } else if (IS_FLINT_TYPE(ip, "fmpz_mod_ctx")) { res += __fmpz_mod_ctx_fprint(fs, va_arg(vlist, const fmpz_mod_ctx_struct *)); ip += STRING_LENGTH("fmpz_mod_ctx}"); } else if (IS_FLINT_TYPE(ip, "fmpz_mod_mat")) { /* Print as if fmpz_mat */ res += __flint_mat_fprint(fs, va_arg(vlist, const fmpz_mod_mat_struct *), fmpz_type); ip += STRING_LENGTH("fmpz_mod_mat}"); } else if (IS_FLINT_TYPE(ip, "fmpz_mod_poly")) { /* Print as if fmpz_poly */ res += __flint_poly_fprint(fs, va_arg(vlist, const fmpz_mod_poly_struct *), fmpz_type); ip += STRING_LENGTH("fmpz_mod_poly}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "fmpq")) { if (IS_FLINT_TYPE(ip, "fmpq")) { res += __fmpq_fprint(fs, va_arg(vlist, const fmpq *), FLAG_NONE); ip += STRING_LENGTH("fmpq}"); } else if (IS_FLINT_TYPE(ip, "fmpq*")) { const fmpq * vec = va_arg(vlist, const fmpq *); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, fmpq_type); ip += STRING_LENGTH("fmpq*}"); } else if (IS_FLINT_TYPE(ip, "fmpq_mat")) { res += __flint_mat_fprint(fs, va_arg(vlist, const fmpq_mat_struct *), fmpq_type); ip += STRING_LENGTH("fmpq_mat}"); } else if (IS_FLINT_TYPE(ip, "fmpq_poly")) { res += __flint_poly_fprint(fs, va_arg(vlist, const fmpq_poly_struct *), fmpq_type); ip += STRING_LENGTH("fmpq_poly}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "arf")) { if (IS_FLINT_TYPE(ip, "arf")) { res += __arf_fprint(fs, va_arg(vlist, arf_srcptr)); ip += STRING_LENGTH("arf}"); } else if (IS_FLINT_TYPE(ip, "arf*")) { arf_srcptr vec = va_arg(vlist, arf_srcptr); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, arf_type); ip += STRING_LENGTH("arf*}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "mag")) { if (IS_FLINT_TYPE(ip, "mag")) { res += __mag_fprint(fs, va_arg(vlist, mag_srcptr)); ip += STRING_LENGTH("mag}"); } else if (IS_FLINT_TYPE(ip, "mag*")) { mag_srcptr vec = va_arg(vlist, mag_srcptr); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, mag_type); ip += STRING_LENGTH("mag*}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "arb")) { if (IS_FLINT_TYPE(ip, "arb")) { res += __arb_fprint(fs, va_arg(vlist, arb_srcptr), FLAG_NONE); ip += STRING_LENGTH("arb}"); } else if (IS_FLINT_TYPE(ip, "arb*")) { arb_srcptr vec = va_arg(vlist, arb_srcptr); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, arb_type); ip += STRING_LENGTH("arb*}"); } else if (IS_FLINT_TYPE(ip, "arb_mat")) { res += __flint_mat_fprint(fs, va_arg(vlist, const arb_mat_struct *), arb_type); ip += STRING_LENGTH("arb_mat}"); } else if (IS_FLINT_TYPE(ip, "arb_poly")) { res += __flint_poly_fprint(fs, va_arg(vlist, const arb_poly_struct *), arb_type); ip += STRING_LENGTH("arb_poly}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_BASE_TYPE(ip, "acb")) { if (IS_FLINT_TYPE(ip, "acb")) { res += __acb_fprint(fs, va_arg(vlist, acb_srcptr), FLAG_NONE); ip += STRING_LENGTH("acb}"); } else if (IS_FLINT_TYPE(ip, "acb*")) { acb_srcptr vec = va_arg(vlist, acb_srcptr); slong len = va_arg(vlist, slong); res += __flint_vec_fprint(fs, vec, len, acb_type); ip += STRING_LENGTH("acb*}"); } else if (IS_FLINT_TYPE(ip, "acb_mat")) { res += __flint_mat_fprint(fs, va_arg(vlist, const acb_mat_struct *), acb_type); ip += STRING_LENGTH("acb_mat}"); } else if (IS_FLINT_TYPE(ip, "acb_poly")) { res += __flint_poly_fprint(fs, va_arg(vlist, const acb_poly_struct *), acb_type); ip += STRING_LENGTH("acb_poly}"); } else goto printpercentcurlybracket; } else if (IS_FLINT_TYPE(ip, "mpz")) { res += __mpz_fprint(fs, va_arg(vlist, mpz_srcptr)); ip += STRING_LENGTH("mpz}"); } else if (IS_FLINT_TYPE(ip, "mpq")) { res += __mpq_fprint(fs, va_arg(vlist, mpq_srcptr)); ip += STRING_LENGTH("mpq}"); } else { printpercentcurlybracket: /* Invalid use of "%{FLINT_TYPE}". As we are currently pointed to * "FLINT_TYPE}", we let fprintf take care of printing "%{". */ #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wformat" #endif tmp = fprintf(fs, "%{"); #ifdef __GNUC__ # pragma GCC diagnostic pop #endif if (tmp < 0) { res = tmp; goto end; } else res += tmp; } goto continue_while_from_flint_type; } int flint_printf(const char * str, ...) { va_list vlist; int ret; va_start(vlist, str); ret = flint_vfprintf(stdout, str, vlist); va_end(vlist); return ret; } int flint_fprintf(FILE * fs, const char * str, ...) { va_list vlist; int ret; va_start(vlist, str); ret = flint_vfprintf(fs, str, vlist); va_end(vlist); return ret; } int flint_vprintf(const char * str, va_list vlist) { return flint_vfprintf(stdout, str, vlist); } /* Type specific printing ****************************************************/ /* TODO: Move these to their respective module? */ /* TODO: Add precision input to Arb type printing functions */ /* TODO: Add option to print in different basis? */ static size_t __ulong_fprint(FILE * fs, const ulong * ip, int flag) { return fprintf(fs, WORD_FMT "u", *ip); } static size_t __slong_fprint(FILE * fs, const slong * ip, int flag) { return fprintf(fs, WORD_FMT "d", *ip); } #define BASE 10 static size_t __fmpz_fprint(FILE * fs, const fmpz * ip, int flag) { size_t res = 0; char * str; size_t skipminus = __fmpz_is_neg(ip) ? FLAG_IS_NEG(flag) : 0; str = fmpz_get_str(NULL, BASE, ip); res += fwrite(str + skipminus, sizeof(char), strlen(str + skipminus), fs); flint_free(str); return res; } #undef BASE static size_t __mpz_fprint(FILE * fs, mpz_srcptr ip) { fmpz_t fip; if ((ip->_mp_size == 1 || ip->_mp_size == -1) && ip->_mp_d[0] <= COEFF_MAX) *fip = ip->_mp_size > 0 ? ip->_mp_d[0] : -ip->_mp_d[0]; else *fip = PTR_TO_COEFF(ip); return __fmpz_fprint(fs, fip, FLAG_NONE); } static size_t __fmpq_fprint(FILE * fs, const fmpq * ip, int flag) { size_t res = 0; /* NOTE: We do not care about parentheses here, and __fmpz_fprint does not * care either. */ res += __fmpz_fprint(fs, fmpq_numref(ip), flag); if (!fmpz_is_one(fmpq_denref(ip))) { res += fwrite(" / ", sizeof(char), STRING_LENGTH(" / "), fs); res += __fmpz_fprint(fs, fmpq_denref(ip), FLAG_NONE); } return res; } static size_t __mpq_fprint(FILE * fs, mpq_srcptr ip) { fmpq_t fip; if ((ip->_mp_num._mp_size == 1 || ip->_mp_num._mp_size == -1) && ip->_mp_num._mp_d[0] <= COEFF_MAX) *fmpq_numref(fip) = ip->_mp_num._mp_size > 0 ? ip->_mp_num._mp_d[0] : -ip->_mp_num._mp_d[0]; else *fmpq_numref(fip) = PTR_TO_COEFF(&(ip->_mp_num)); if ((ip->_mp_den._mp_size == 1 || ip->_mp_den._mp_size == -1) && ip->_mp_den._mp_d[0] <= COEFF_MAX) *fmpq_denref(fip) = ip->_mp_den._mp_size > 0 ? ip->_mp_den._mp_d[0] : -ip->_mp_den._mp_d[0]; else *fmpq_denref(fip) = PTR_TO_COEFF(&(ip->_mp_den)); return __fmpq_fprint(fs, fip, FLAG_NONE); } #define DIGITS 6 static size_t __mag_fprint(FILE * fs, mag_srcptr ip) { size_t res; char * str; #if DIGITS != 6 # error Change fwrite below #endif if (mag_is_zero(ip)) return fwrite("0.00000", sizeof(char), STRING_SIZE("0.00000"), fs); str = __mag_get_str(ip, DIGITS); res = fwrite(str, sizeof(char), strlen(str), fs); flint_free(str); return res; } static size_t __arf_fprint(FILE * fs, arf_srcptr ip) { size_t res; char * str; #if DIGITS != 6 # error Change fwrite below #endif if (arf_is_zero(ip)) return fwrite("0.00000", sizeof(char), STRING_SIZE("0.00000"), fs); str = arf_get_str(ip, DIGITS); res = fwrite(str, sizeof(char), strlen(str), fs); flint_free(str); return res; } #define MAX_INT_SIZE 64 /* NOTE: If arb is an integer, we print it as one. */ static size_t __arb_fprint(FILE * fs, arb_srcptr ip, int flag) { size_t res; if (arb_is_zero(ip)) { return (fputc('0', fs) != EOF); } else if (arb_is_int(ip) && ARF_EXP(arb_midref(ip)) <= MAX_INT_SIZE) { /* NOTE: Only print as integer if ip < 2^64. */ fmpz_t fip; fmpz_init(fip); /* NOTE: The conversion should be exact, so we do not care about its * return value. */ arf_get_fmpz(fip, arb_midref(ip), ARF_RND_DOWN); /* NOTE: We do not care about parentheses here, and __fmpz_fprint does not * care either. */ res = __fmpz_fprint(fs, fip, flag); fmpz_clear(fip); } else { char * str; arb_struct ip2; if (FLAG_IS_NEG(flag)) __arb_neg_readonly(&ip2, ip); else ip2 = *ip; str = arb_get_str(&ip2, DIGITS, 0); res = fwrite(str, sizeof(char), strlen(str), fs); flint_free(str); } return res; } #undef MAX_INT_SIZE #undef DIGITS static size_t __acb_fprint(FILE * fs, acb_srcptr ip, int flag) { size_t res = 0; int realiszero, imagiszero; realiszero = arb_is_zero(acb_realref(ip)); imagiszero = arb_is_zero(acb_imagref(ip)); if (realiszero && imagiszero) return (fputc('0', fs) != EOF); /* Only print parentheses if both real and imaginary part is non-zero. */ if (FLAG_IS_PAREN(flag) && !realiszero && !imagiszero) res += (fputc('(', fs) != EOF); /* Print real part if non-zero */ if (!realiszero) res += __arb_fprint(fs, acb_realref(ip), flag); /* Print imaginary part if non-zero */ if (!imagiszero) { int imagisneg = arb_is_negative(acb_imagref(ip)); if (!realiszero) res += fwrite(FLAG_IS_NEG(flag) ^ imagisneg ? " - " : " + ", sizeof(char), STRING_SIZE(" - "), fs); /* If imaginary part of ip is \pm 1, then we only print \pm i. */ if (!__arb_is_pm1(acb_imagref(ip))) { res += __arb_fprint(fs, acb_imagref(ip), (FLAG_IS_NEG(flag) ^ imagisneg) & (~realiszero)); res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs); } res += (fputc('i', fs) != EOF); } if (FLAG_IS_PAREN(flag) && !realiszero && !imagiszero) res += (fputc(')', fs) != EOF); return res; } static size_t __nmod_fprint(FILE * fs, nmod_t ip) { return fprintf(fs, "mod " WORD_FMT "u", ip.n); } static size_t __fmpz_mod_ctx_fprint(FILE * fs, const fmpz_mod_ctx_struct * ip) { size_t res = 0; res += fwrite("mod ", sizeof(char), STRING_LENGTH("mod "), fs); res += fmpz_fprint(fs, fmpz_mod_ctx_modulus(ip)); return res; } /* Generic printing **********************************************************/ /* TODO: Add non-compact printing? For this it would be nice with option for * variable indentation and aligned columns. */ /* TODO: The square brackets used as delimiters for vectors and matrices are * also used for printing by arb_get_str. Think if we want to change something * here. */ /* TODO: Add option to specify generator for polynomials */ /* TODO: If it is possible to obtain terminal width and height, it would be nice * to be able to only print the beginning and ending element of vectors, * matrices and polynomials (such as what Julia does). This should be the * default. */ typedef size_t (* print_func_t)(FILE *, const void *, int); static print_func_t print_functions[] = { (print_func_t) __ulong_fprint, (print_func_t) __fmpz_fprint, (print_func_t) __fmpq_fprint, (print_func_t) __arb_fprint, (print_func_t) __acb_fprint, (print_func_t) __slong_fprint, /* NOTE: These print functions are only */ (print_func_t) __mag_fprint, /* used for vectors, not other composite */ (print_func_t) __arf_fprint /* types. */ }; static size_t __flint_vec_fprint(FILE * fs, const void * ip, slong len, flint_type_t type) { size_t res = 0; slong ix; const char * vec = ip; size_t type_size = flint_type_size_in_chars(type); print_func_t print = print_functions[type]; res += (fputc('[', fs) != EOF); if (len > 0) res += print(fs, vec, FLAG_NONE); for (ix = 1; ix < len; ix++) { res += fwrite(", ", sizeof(char), STRING_LENGTH(", "), fs); res += print(fs, vec + type_size * ix, FLAG_NONE); } res += (fputc(']', fs) != EOF); return res; } /* NOTE: This function relies on the fact that the layout of * [fmpz/fmpq/arb/acb]_mat_struct are all on the form (pointer, slong, slong, * pointer). */ static size_t __flint_mat_fprint(FILE * fs, const void * ip, flint_type_t type) { size_t res = 0; slong ix; slong nr, nc; const void ** rows; rows = (const void **) ((const fmpz_mat_struct *) ip)->rows; nr = ((const fmpz_mat_struct *) ip)->r; nc = ((const fmpz_mat_struct *) ip)->c; if (nr == 0 || nc == 0) return fprintf(fs, WORD_FMT "d by " WORD_FMT "d empty matrix", nr, nc); res += (fputc('[', fs) != EOF); res += __flint_vec_fprint(fs, rows[0], nc, type); for (ix = 1; ix < nr; ix++) { res += fwrite(", ", sizeof(char), STRING_LENGTH(", "), fs); res += __flint_vec_fprint(fs, rows[ix], nc, type); } res += (fputc(']', fs) != EOF); return res; } typedef int (* is_func_t)(const void *); static is_func_t is_pm1_functions[] = { __ulong_is_pm1, (is_func_t) fmpz_is_pm1, __never_is, /* is not used for fmpq */ __arb_is_pm1, __acb_is_pm1 }; static is_func_t is_zero_functions[] = { __ulong_is_zero, (is_func_t) fmpz_is_zero, __never_is, /* is not used for fmpq */ (is_func_t) arb_is_zero, (is_func_t) acb_is_zero }; static is_func_t is_neg_functions[] = { __never_is, /* is not used for ulong */ __fmpz_is_neg, __never_is, /* is not used for fmpq */ (is_func_t) arb_is_negative, __acb_is_neg }; /* NOTE: This function relies on the fact that the layout of * [fmpz/arb/acb]_poly_struct are all on the form (pointer, slong, slong) and * fmpq_poly_struct on the form (pointer, slong, slong, pointer). */ static size_t __flint_poly_fprint(FILE * fs, const void * ip, flint_type_t type) { size_t res = 0; slong ix; slong len; len = ((const fmpz_poly_struct *) ip)->length; if (len == 0) return fputc('0', fs) != EOF; if (type != fmpq_type) { size_t type_size = flint_type_size_in_chars(type); const char * coeffs = (const char *) ((const fmpz_poly_struct *) ip)->coeffs; print_func_t print = print_functions[type]; is_func_t is_pm1 = is_pm1_functions[type]; is_func_t is_zero = is_zero_functions[type]; is_func_t is_neg = is_neg_functions[type]; if (len == 1) return print(fs, coeffs, FLAG_NONE); /* Leading coefficient cannot be zero */ if (!is_pm1(coeffs + type_size * (len - 1))) { res += print(fs, coeffs + type_size * (len - 1), FLAG_PAREN); res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs); } else if (is_neg(coeffs + type_size * (len - 1))) res += (fputc('-', fs) != EOF); if (len != 2) res += fprintf(fs, "x^" WORD_FMT "d", len - 1); else res += (fputc('x', fs) != EOF); for (ix = len - 2; ix > 0; ix--) { if (!is_zero(coeffs + type_size * ix)) { res += fwrite(is_neg(coeffs + type_size * ix) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs); if (!is_pm1(coeffs + type_size * ix)) { res += print(fs, coeffs + type_size * ix, is_neg(coeffs + type_size * ix) | FLAG_PAREN); res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs); } if (ix != 1) res += fprintf(fs, "x^" WORD_FMT "d", ix); else res += (fputc('x', fs) != EOF); } } if (!is_zero(coeffs + 0)) { res += fwrite(is_neg(coeffs + 0) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs); res += print(fs, coeffs + 0, is_neg(coeffs + 0)); } } else { /* fmpq_poly is special as it is an fmpz_poly with a denomitator * strapped onto it */ const fmpz * coeffs = ((const fmpq_poly_struct *) ip)->coeffs; const fmpz * den = ((const fmpq_poly_struct *) ip)->den; fmpq_t canonical; fmpq_init(canonical); fmpq_set_fmpz_frac(canonical, coeffs + len - 1, den); if (len == 1) { res += __fmpq_fprint(fs, canonical, FLAG_NONE); fmpq_clear(canonical); return res; } /* Leading coefficient cannot be zero */ if (!fmpq_is_pm1(canonical)) { res += __fmpq_fprint(fs, canonical, FLAG_NONE); res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs); } else if (__fmpq_is_neg(canonical)) res += (fputc('-', fs) != EOF); if (len != 2) res += fprintf(fs, "x^" WORD_FMT "d", len - 1); else res += (fputc('x', fs) != EOF); for (ix = len - 2; ix > 0; ix--) { if (!fmpz_is_zero(coeffs + ix)) { fmpq_set_fmpz_frac(canonical, coeffs + ix, den); res += fwrite(__fmpq_is_neg(canonical) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs); if (!fmpq_is_pm1(canonical)) { res += __fmpq_fprint(fs, canonical, __fmpq_is_neg(canonical)); res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs); } if (ix != 1) res += fprintf(fs, "x^" WORD_FMT "d", ix); else res += (fputc('x', fs) != EOF); } } fmpq_set_fmpz_frac(canonical, coeffs + 0, den); if (!fmpq_is_zero(canonical)) { res += fwrite(__fmpq_is_neg(canonical) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs); res += __fmpq_fprint(fs, canonical, __fmpq_is_neg(canonical)); } fmpq_clear(canonical); } return res; } flint-3.1.3/src/generic_files/memory_manager.c000066400000000000000000000251541461254215100213750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2016 Claus Fieker Copyright (C) 2016 William Hart. Copyright (C) 2018 Daniel Schultz Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "thread_pool.h" #if FLINT_USES_GC # include #endif #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD # include #endif #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) # include #endif /* memory functions **********************************************************/ static void * _flint_malloc(size_t); static void * _flint_calloc(size_t, size_t); static void * _flint_realloc(void *, size_t); static void _flint_free(void *); static void * _flint_aligned_alloc(size_t, size_t); static void * _flint_aligned_alloc2(size_t, size_t); static void _flint_aligned_free(void *); static void _flint_aligned_free2(void *); static void * (* __flint_allocate_func)(size_t) = _flint_malloc; static void * (* __flint_callocate_func)(size_t, size_t) = _flint_calloc; static void * (* __flint_reallocate_func)(void *, size_t) = _flint_realloc; static void (* __flint_free_func)(void *) = _flint_free; #if HAVE_ALIGNED_ALLOC || HAVE__ALIGNED_MALLOC static void * (* __flint_aligned_allocate_func)(size_t, size_t) = _flint_aligned_alloc; static void (* __flint_aligned_free_func)(void *) = _flint_aligned_free; #else static void * (* __flint_aligned_allocate_func)(size_t, size_t) = _flint_aligned_alloc2; static void (* __flint_aligned_free_func)(void *) = _flint_aligned_free2; #endif FLINT_STATIC_NOINLINE void flint_memory_error(size_t size) { flint_throw(FLINT_ERROR, "Unable to allocate memory (%zu).\n", size); } FLINT_STATIC_NOINLINE void flint_aligned_memory_error(size_t alignment, size_t size) { flint_throw(FLINT_ERROR, "Unable to allocate %zu bytes with alignment %zu\n", size, alignment); } void * _flint_malloc(size_t size) { void * ptr; #if FLINT_USES_GC ptr = GC_malloc(size); #else ptr = malloc(size); #endif return ptr; } FLINT_WARN_UNUSED void * flint_malloc(size_t size) { void * ptr = (*__flint_allocate_func)(size); if (ptr == NULL) flint_memory_error(size); return ptr; } void * _flint_realloc(void * ptr, size_t size) { void * ptr2; #if FLINT_USES_GC ptr2 = GC_realloc(ptr, size); #else ptr2 = realloc(ptr, size); #endif return ptr2; } FLINT_WARN_UNUSED void * flint_realloc(void * ptr, size_t size) { void * ptr2; if (ptr) ptr2 = (*__flint_reallocate_func)(ptr, size); else ptr2 = (*__flint_allocate_func)(size); if (ptr2 == NULL) flint_memory_error(size); return ptr2; } void * _flint_calloc(size_t num, size_t size) { void * ptr; #if FLINT_USES_GC ptr = GC_malloc(num*size); #else ptr = calloc(num, size); #endif return ptr; } FLINT_WARN_UNUSED void * flint_calloc(size_t num, size_t size) { void * ptr; ptr = (*__flint_callocate_func)(num, size); if (ptr == NULL) flint_memory_error(size); return ptr; } void _flint_free(void * ptr) { #if !FLINT_USES_GC free(ptr); #endif } void flint_free(void * ptr) { (*__flint_free_func)(ptr); } void * _flint_aligned_alloc(size_t alignment, size_t size) { #if HAVE__ALIGNED_MALLOC return _aligned_malloc(size, alignment); #elif HAVE_ALIGNED_ALLOC return aligned_alloc(alignment, size); #else return NULL; #endif } /* NOTE: This function assumes alignment >= sizeof(ulong) */ void * _flint_aligned_alloc2(size_t alignment, size_t size) { size_t alloc_size; void * alloc_ptr; ulong * ret_ptr; alloc_size = size + alignment; alloc_ptr = flint_malloc(alloc_size); /* Case 1: alloc_ptr aligned with (alignment, alignment - sizeof(ulong)). We only need `size + sizeof(ulong)' bytes. Case 2: alloc_ptr aligned with (alignment, n), where 0 <= n < alignment - sizeof(ulong). We will not use the first `alignment - n - sizeof(ulong)' bytes, and hence we need `size + alignment - n - sizeof(ulong)' bytes. */ ret_ptr = (ulong *) ((((size_t) alloc_ptr) & (-alignment)) + alignment); ret_ptr[-1] = (char *) ret_ptr - (char *) alloc_ptr; return ret_ptr; } FLINT_WARN_UNUSED void * flint_aligned_alloc(size_t alignment, size_t size) { void * ptr; FLINT_ASSERT(size % alignment == 0); ptr = (*__flint_aligned_allocate_func)(alignment, size); if (ptr == NULL) flint_aligned_memory_error(alignment, size); return ptr; } void _flint_aligned_free(void * p) { #if HAVE__ALIGNED_MALLOC _aligned_free(p); #elif HAVE_ALIGNED_ALLOC free(p); #else return; #endif } void _flint_aligned_free2(void * p) { size_t * ptr = p; if (ptr != NULL) flint_free((char *) ptr - ptr[-1]); } void flint_aligned_free(void * ptr) { (*__flint_aligned_free_func)(ptr); } #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD static pthread_once_t register_initialised = PTHREAD_ONCE_INIT; pthread_mutex_t register_lock; static pthread_once_t alloc_func_init = PTHREAD_ONCE_INIT; pthread_mutex_t alloc_func_lock; void __flint_set_memory_functions_init(void) { pthread_mutex_init(&alloc_func_lock, NULL); } #endif /* aligned memory getter and setter ******************************************/ void __flint_get_all_memory_functions( void * (** alloc_func)(size_t), void * (** calloc_func)(size_t, size_t), void * (** realloc_func)(void *, size_t), void (** free_func)(void *), void * (** aligned_alloc_func)(size_t, size_t), void (** aligned_free_func)(void *)) { #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(&alloc_func_init, __flint_set_memory_functions_init); pthread_mutex_lock(&alloc_func_lock); #endif *alloc_func = __flint_allocate_func; *calloc_func = __flint_callocate_func; *realloc_func = __flint_reallocate_func; *free_func = __flint_free_func; *aligned_alloc_func = __flint_aligned_allocate_func; *aligned_free_func = __flint_aligned_free_func; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(&alloc_func_lock); #endif } void __flint_set_all_memory_functions( void * (* alloc_func)(size_t), void * (* calloc_func)(size_t, size_t), void * (* realloc_func)(void *, size_t), void (* free_func)(void *), void * (* aligned_alloc_func)(size_t, size_t), void (* aligned_free_func)(void *)) { #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(&alloc_func_init, __flint_set_memory_functions_init); pthread_mutex_lock(&alloc_func_lock); #endif __flint_allocate_func = alloc_func; __flint_callocate_func = calloc_func; __flint_reallocate_func = realloc_func; __flint_free_func = free_func; __flint_aligned_allocate_func = aligned_alloc_func; __flint_aligned_free_func = aligned_free_func; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(&alloc_func_lock); #endif } /* non-aligned memory getter and setter **************************************/ void __flint_get_memory_functions( void * (** alloc_func)(size_t), void * (** calloc_func)(size_t, size_t), void * (** realloc_func)(void *, size_t), void (** free_func)(void *)) { #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(&alloc_func_init, __flint_set_memory_functions_init); pthread_mutex_lock(&alloc_func_lock); #endif *alloc_func = __flint_allocate_func; *calloc_func = __flint_callocate_func; *realloc_func = __flint_reallocate_func; *free_func = __flint_free_func; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(&alloc_func_lock); #endif } void __flint_set_memory_functions( void * (* alloc_func)(size_t), void * (* calloc_func)(size_t, size_t), void * (* realloc_func)(void *, size_t), void (* free_func)(void *)) { #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(&alloc_func_init, __flint_set_memory_functions_init); pthread_mutex_lock(&alloc_func_lock); #endif __flint_allocate_func = alloc_func; __flint_callocate_func = calloc_func; __flint_reallocate_func = realloc_func; __flint_free_func = free_func; __flint_aligned_allocate_func = _flint_aligned_alloc2; __flint_aligned_free_func = _flint_aligned_free2; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(&alloc_func_lock); #endif } /* cleanup functions *********************************************************/ FLINT_TLS_PREFIX size_t flint_num_cleanup_functions = 0; FLINT_TLS_PREFIX flint_cleanup_function_t * flint_cleanup_functions = NULL; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD void register_init(void) { pthread_mutex_init(®ister_lock, NULL); } #endif void flint_register_cleanup_function(flint_cleanup_function_t cleanup_function) { #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(®ister_initialised, register_init); pthread_mutex_lock(®ister_lock); #endif flint_cleanup_functions = flint_realloc(flint_cleanup_functions, (flint_num_cleanup_functions + 1) * sizeof(flint_cleanup_function_t)); flint_cleanup_functions[flint_num_cleanup_functions] = cleanup_function; flint_num_cleanup_functions++; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(®ister_lock); #endif } void _fmpz_cleanup(void); void _flint_cleanup(void) { size_t i; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_lock(®ister_lock); #endif for (i = 0; i < flint_num_cleanup_functions; i++) flint_cleanup_functions[i](); flint_free(flint_cleanup_functions); flint_cleanup_functions = NULL; flint_num_cleanup_functions = 0; mpfr_free_cache(); _fmpz_cleanup(); #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(®ister_lock); #endif } void flint_cleanup(void) { #if !FLINT_REENTRANT || FLINT_USES_TLS _flint_cleanup(); #endif } void flint_cleanup_master(void) { if (global_thread_pool_initialized) { thread_pool_clear(global_thread_pool); global_thread_pool_initialized = 0; } _flint_cleanup(); } flint-3.1.3/src/generic_files/profiler.c000066400000000000000000000075151461254215100202160ustar00rootroot00000000000000/* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "profiler.h" #if (defined( _MSC_VER ) || (GMP_LIMB_BITS == 64 && defined (__amd64__)) || \ (GMP_LIMB_BITS == 32 && (defined (__i386__) || \ defined (__i486__) || defined(__amd64__)))) /* clock_last[i] is the last read clock value for clock #i. clock_accum[i] is the total time attributed to clock #i so far. These should not be read directly; use get_clock(i) instead. */ double clock_last[FLINT_NUM_CLOCKS]; double clock_accum[FLINT_NUM_CLOCKS]; void prof_repeat(double *min, double *max, profile_target_t target, void *arg) { /* Number of timings that were at least DURATION_THRESHOLD microseconds */ ulong good_count = 0; double max_time = DBL_MIN, min_time = DBL_MAX; /* First try one loop */ ulong num_trials = 4; double last_time; init_clock(0); target(arg, num_trials); last_time = get_clock(0); /* Loop until we have enough good times */ while (1) { double per_trial = last_time / num_trials; /* If the last recorded time was long enough, record it */ if (last_time > DURATION_THRESHOLD) { if (good_count) { if (per_trial > max_time) max_time = per_trial; if (per_trial < min_time) min_time = per_trial; } else max_time = min_time = per_trial; if (++good_count == 5) { /* We've got enough data */ break; } } /* Adjust num_trials so that the elapsed time gravitates towards DURATION_TARGET; num_trials can be changed by a factor of at most 25%, and must be at least 1 */ { double adjust_ratio; if (last_time < 0.0001) last_time = 0.0001; adjust_ratio = DURATION_TARGET / last_time; if (adjust_ratio > 1.25) adjust_ratio = 1.25; if (adjust_ratio < 0.75) adjust_ratio = 0.75; num_trials = (ulong) ceil(adjust_ratio * num_trials); /* Just to be safe */ if (num_trials == 0) num_trials = 1; } /* Run another trial */ init_clock(0); target(arg, num_trials); last_time = get_clock(0); } /* Store results */ if (min) *min = min_time; if (max) *max = max_time; } #endif void get_memory_usage(meminfo_t meminfo) { FILE * file = fopen("/proc/self/status", "r"); ulong result; char line[128]; while (fgets(line, 128, file) != NULL) { result = 0; if (strncmp(line, "VmSize:", 7) == 0) { flint_sscanf(line, "VmSize: %wu kB\n", &result); meminfo->size = result; } else if (strncmp(line, "VmPeak:", 7) == 0) { flint_sscanf(line, "VmPeak: %wu kB\n", &result); meminfo->peak = result; } else if (strncmp(line, "VmHWM:", 6) == 0) { flint_sscanf(line, "VmHWM: %wu kB\n", &result); meminfo->hwm = result; } else if (strncmp(line, "VmRSS:", 6) == 0) { flint_sscanf(line, "VmRSS: %wu kB\n", &result); meminfo->rss = result; } } fclose(file); } flint-3.1.3/src/generic_files/scanf.c000066400000000000000000000101251461254215100174550ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" /* return number of arguments called for by a specific format specifier */ int parse_fmt(int * floating, const char * fmt) { int args = 1; fmt++; /* skip % */ if (fmt[0] == '%') return 0; /* special case, print % */ if (fmt[0] == ' ' || fmt[0] == '+' || fmt[0] == '-') fmt++; /* skip flag */ if (fmt[0] == '*') { args++; fmt++; /* skip * */ } else while (isdigit((unsigned char) fmt[0])) fmt++; /* skip width */ if (fmt[0] == '.') { fmt++; /* skip . */ if (fmt[0] == '*') { args++; fmt++; /* skip * */ } else while (isdigit((unsigned char) fmt[0])) fmt++; /* skip precision */ } if (fmt[0] == 'h' || fmt[0] == 'l' || fmt[0] == 'L') fmt++; /* skip length */ if (fmt[0] == 'e' || fmt[0] == 'E' || fmt[0] == 'f' || fmt[0] == 'g' || fmt[0] == 'G') (*floating) = 1; else (*floating) = 0; return args; } FLINT_WARN_UNUSED int flint_scanf(const char * str, ...) { va_list ap; size_t len = strlen(str); char * str2 = flint_malloc(len + 1); int * w1 = NULL, * w2 = NULL; void * w3; double * d; ulong * wu; slong * w; int args, floating; int ret; /* deal with first substring */ size_t n = strcspn(str, "%"); strncpy(str2, str, n); str2[n] = '\0'; ret = 0; if (!fread(str2, 1, n, stdin) && n > 0) goto cleanup; len -= n; str += n; va_start(ap, str); while (len) /* deal with fmt spec prefixed strings */ { n = strcspn(str + 2, "%") + 2; /* be sure to skip a %% */ strncpy(str2, str, n); str2[n] = '\0'; switch (str[1]) { case 'w': if (str[2] == 'x') { wu = (ulong *) va_arg(ap, ulong *); ret += scanf(WORD_FMT "x", wu); if (!fread(str2 + 3, 1, n - 3, stdin) && n > 3) goto cleanup; } else if (str[2] == 'u') { wu = (ulong *) va_arg(ap, ulong *); ret += scanf(WORD_FMT "u", wu); if (!fread(str2 + 3, 1, n - 3, stdin) && n > 3) goto cleanup; } else if (str[2] == 'd') { w = (slong *) va_arg(ap, slong *); ret += scanf(WORD_FMT "d", w); if (!fread(str2 + 3, 1, n - 3, stdin) && n > 3) goto cleanup; } else { w = (slong *) va_arg(ap, slong *); ret += scanf(WORD_FMT "d", w); if (!fread(str2 + 2, 1, n - 2, stdin) && n > 2) goto cleanup; } break; default: /* pass to scanf */ args = parse_fmt(&floating, str2); if (args) { if (args == 3) w1 = va_arg(ap, int *); if (args >= 2) w2 = va_arg(ap, int *); if (floating) { d = va_arg(ap, double *); if (args == 2) ret += scanf(str2, w2, d); else if (args == 3) ret += scanf(str2, w1, w2, d); else ret += scanf(str2, d); } else { w3 = va_arg(ap, void *); if (args == 2) ret += scanf(str2, w2, w3); else if (args == 3) ret += scanf(str2, w1, w2, w3); else ret += scanf(str2, w3); } } else { if (!fread(str2, 1, n, stdin) && n > 0) /* zero args */ goto cleanup; } } len -= n; str += n; } va_end(ap); cleanup: flint_free(str2); return ret; } flint-3.1.3/src/generic_files/sprintf.c000066400000000000000000000076401461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" int flint_sprintf(char * s, const char * str, ...) { va_list ap; size_t len = strlen(str); char * str2 = flint_malloc(len + 1); int w1 = 0, w2 = 0; void * w3; double d; ulong wu; slong w; int args, floating, width = 0, have_width, digits; size_t ret; /* deal with first substring */ size_t n = strcspn(str, "%"); strncpy(str2, str, n); str2[n] = '\0'; ret = sprintf(s, "%s", str2); len -= n; str += n; va_start(ap, str); while (len) /* deal with fmt spec prefixed strings */ { have_width = 0; if (isdigit((unsigned char) str[1])) { width = atoi(str + 1); have_width = 1; digits = strspn(str + 1, "0123456789"); if (str[digits + 1] == 'w') { str += digits; len -= digits; } } n = strcspn(str + 2, "%") + 2; /* be sure to skip a %% */ strncpy(str2, str, n); str2[n] = '\0'; switch (str[1]) { case 'w': if (str[2] == 'x') { wu = (ulong) va_arg(ap, ulong); if (have_width) ret += sprintf(s + ret, WORD_WIDTH_FMT "x", width, wu); else ret += sprintf(s + ret, WORD_FMT "x", wu); ret += sprintf(s + ret, "%s", str2 + 3); } else if (str[2] == 'u') { wu = (ulong) va_arg(ap, ulong); if (have_width) ret += sprintf(s + ret, WORD_WIDTH_FMT "u", width, wu); else ret += sprintf(s + ret, WORD_FMT "u", wu); ret += sprintf(s + ret, "%s", str2 + 3); } else if (str[2] == 'd') { w = (slong) va_arg(ap, slong); if (have_width) ret += sprintf(s + ret, WORD_WIDTH_FMT "d", width, w); else ret += sprintf(s + ret, WORD_FMT "d", w); ret += sprintf(s + ret, "%s", str2 + 3); } else { w = (slong) va_arg(ap, slong); if (have_width) ret += sprintf(s + ret, WORD_WIDTH_FMT "d", width, w); else ret += sprintf(s + ret, WORD_FMT "d", w); ret += sprintf(s + ret, "%s", str2 + 2); } break; case '%': /*Special Case to handle %%*/ ret += sprintf(s+ret,"%s",str2+1); break; default: /* pass to sprintf */ args = parse_fmt(&floating, str2); if (args) { if (args == 3) w1 = va_arg(ap, int); if (args >= 2) w2 = va_arg(ap, int); if (floating) { d = va_arg(ap, double); if (args == 2) ret += sprintf(s + ret, str2, w2, d); else if (args == 3) ret += sprintf(s + ret, str2, w1, w2, d); else ret += sprintf(s + ret, str2, d); } else { w3 = va_arg(ap, void *); if (args == 2) ret += sprintf(s + ret, str2, w2, w3); else if (args == 3) ret += sprintf(s + ret, str2, w1, w2, w3); else ret += sprintf(s + ret, str2, w3); } } else ret += sprintf(s + ret, "%s", str2); /* zero args */ } len -= n; str += n; } va_end(ap); flint_free(str2); return (int) ret; } flint-3.1.3/src/generic_files/sscanf.c000066400000000000000000000071071461254215100176460ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" int flint_sscanf(const char * s, const char * str, ...) { va_list ap; int * w1 = NULL, *w2 = NULL; void ** w3; double * d; ulong * wu; slong * w; int args, floating; int ret; char *str2, *s2; size_t n, len = strlen(str); if(!strlen(s)) return 0; str2 = flint_malloc(len + 1); s2 = flint_malloc(strlen(s) + 1); /* deal with first substring */ n = strcspn(str, "%"); strncpy(str2, s, n); str2[n] = '\0'; ret = 0; len -= n; str += n; s += n; va_start(ap, str); while (len) /* deal with fmt spec prefixed strings */ { n = strcspn(str + 2, "%") + 2; /* be sure to skip a %% */ strncpy(str2, str, n); str2[n] = '\0'; switch (str[1]) { case 'w': if (str[2] == 'x') { wu = (ulong *) va_arg(ap, ulong *); ret += sscanf(s, WORD_FMT "x", wu); s += sprintf(s2, WORD_FMT "x", *wu); s += n - 3; } else if (str[2] == 'u') { wu = (ulong *) va_arg(ap, ulong *); ret += sscanf(s, WORD_FMT "u", wu); s += sprintf(s2, WORD_FMT "u", *wu); s += n - 3; } else if (str[2] == 'd') { w = (slong *) va_arg(ap, slong *); ret += sscanf(s, WORD_FMT "d", w); s += sprintf(s2, WORD_FMT "d", *w); s += n - 3; } else { w = (slong *) va_arg(ap, slong *); ret += sscanf(s, WORD_FMT "d", w); s += sprintf(s2, WORD_FMT "d", *w); s += n - 2; } break; default: /* pass to printf */ args = parse_fmt(&floating, str2); if (args) { if (args == 3) w1 = va_arg(ap, int *); if (args >= 2) w2 = va_arg(ap, int *); if (floating) { d = va_arg(ap, double *); if (args == 2) { ret += sscanf(s, str2, w2, d); s += sprintf(s2, str2, *w2, *d); } else if (args == 3) { ret += sscanf(s, str2, w1, w2, d); s += sprintf(s2, str2, *w1, *w2, *d); } else { ret += sscanf(s, str2, d); s += sprintf(s2, str2, *d); } } else { w3 = va_arg(ap, void **); if (args == 2) { ret += sscanf(s, str2, w2, w3); s += sprintf(s2, str2, *w2, *w3); } else if (args == 3) { ret += sscanf(s, str2, w1, w2, w3); s += sprintf(s2, str2, *w1, *w2, *w3); } else { ret += sscanf(s, str2, w3); s += sprintf(s2, str2, *w3); } } } else /* zero args */ s += n; } len -= n; str += n; } va_end(ap); flint_free(str2); flint_free(s2); return ret; } flint-3.1.3/src/generic_files/test_helpers.c000066400000000000000000000016711461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" double _flint_test_multiplier = -1.0; double flint_test_multiplier(void) { if (_flint_test_multiplier == -1.0) { const char * s = getenv("FLINT_TEST_MULTIPLIER"); if (s == NULL) { _flint_test_multiplier = 1.0; } else { _flint_test_multiplier = strtod(s, NULL); if (!(_flint_test_multiplier >= 0.0 && _flint_test_multiplier <= 1000.0)) _flint_test_multiplier = 1.0; } } return _flint_test_multiplier; } flint-3.1.3/src/generic_files/version.c000066400000000000000000000006621461254215100200550ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" char flint_version[]=FLINT_VERSION; flint-3.1.3/src/gettimeofday.h000066400000000000000000000010231461254215100162500ustar00rootroot00000000000000/* * timeval.h 1.0 01/12/19 * * Defines gettimeofday, timeval, etc. for Win32 * * By Wu Yongwei * */ #ifndef _TIMEVAL_H #define _TIMEVAL_H #include "flint.h" #include #define EPOCHFILETIME (116444736000000000LL) #if defined(__cplusplus) extern "C" { #endif struct timezone { int tz_minuteswest; /* minutes W of Greenwich */ int tz_dsttime; /* type of dst correction */ }; int gettimeofday(struct timeval *tv, struct timezone *tz); #if defined(__cplusplus) } #endif #endif /* _TIMEVAL_H */ flint-3.1.3/src/gmpcompat-longlong.h.in000066400000000000000000000455631461254215100200210ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GMP_COMPAT_H #define GMP_COMPAT_H #include "flint.h" #define FLINT_MPZ_REALLOC(z, len) \ ((len) > ((z)->_mp_alloc) \ ? (mp_ptr) _mpz_realloc(z, len) \ : ((z)->_mp_d)) static inline void flint_mpz_add_uiui(mpz_ptr a, mpz_srcptr b, ulong c1, ulong c0) { ulong d[2]; mpz_t c; d[0] = c0; d[1] = c1; c->_mp_d = d; c->_mp_alloc = 2; c->_mp_size = d[1] != 0 ? 2 : d[0] != 0; mpz_add(a, b, c); } static inline void flint_mpz_add_signed_uiui(mpz_ptr a, mpz_srcptr b, ulong c1, ulong c0) { ulong d[2]; ulong c2 = FLINT_SIGN_EXT(c1); mpz_t c; sub_ddmmss(d[1], d[0], c2^c1, c2^c0, c2, c2); c->_mp_d = d; c->_mp_alloc = 2; c->_mp_size = d[1] != 0 ? 2 : d[0] != 0; if (c2 != 0) c->_mp_size = -c->_mp_size; mpz_add(a, b, c); } static inline void flint_mpz_add_uiuiui(mpz_ptr a, mpz_srcptr b, ulong c2, ulong c1, ulong c0) { ulong d[3]; mpz_t c; d[0] = c0; d[1] = c1; d[2] = c2; c->_mp_d = d; c->_mp_alloc = 3; c->_mp_size = d[2] != 0 ? 3 : d[1] != 0 ? 2 : d[0] != 0; mpz_add(a, b, c); } static inline void flint_mpz_add_signed_uiuiui(mpz_ptr a, mpz_srcptr b, ulong c2, ulong c1, ulong c0) { ulong cs, d[3]; mpz_t c; c->_mp_d = d; c->_mp_alloc = 3; cs = FLINT_SIGN_EXT(c2); sub_dddmmmsss(d[2], d[1], d[0], cs^c2, cs^c1, cs^c0, cs, cs, cs); c->_mp_size = d[2] != 0 ? 3 : d[1] != 0 ? 2 : d[0] != 0; if (cs != 0) c->_mp_size = -c->_mp_size; mpz_add(a, b, c); } #define FLINT_MOCK_MPZ_UI(xxx, yyy) \ __mpz_struct (xxx)[1] = {{ 1, 0, NULL }}; \ do { \ (xxx)->_mp_d = (mp_ptr) &(yyy); \ if ((yyy) > 0) \ (xxx)->_mp_size = 1; \ }while (0) #define FLINT_MOCK_MPZ_SI(xxx, yyy) \ __mpz_struct (xxx)[1] = {{ 1, 0, NULL }}; \ do { \ (xxx)->_mp_d = (mp_ptr) &(yyy); \ if ((yyy) < 0) (xxx)->_mp_size = -1, (yyy) = -(yyy); \ else (xxx)->_mp_size = (yyy) != 0; \ } while (0) #define flint_mpz_get_si(xxx) \ ((xxx)->_mp_size == 0 ? (slong) WORD(0) : \ ((xxx)->_mp_size > 0 ? (slong) (xxx)->_mp_d[0] : (slong) -(xxx)->_mp_d[0])) #define flint_mpz_get_ui(xxx) \ ((xxx)->_mp_size == 0 ? UWORD(0) : (xxx)->_mp_d[0]) static inline void flint_mpz_set_si(mpz_ptr r, slong s) { /* GMP 6.2 lazily performs allocation, deal with that if necessary (in older GMP versions, this code is simply never triggered) */ if (r->_mp_alloc == 0) { r->_mp_d = (mp_ptr) flint_malloc(sizeof(mp_limb_t)); r->_mp_alloc = 1; } if (s < 0) { r->_mp_size = -1; r->_mp_d[0] = -s; } else { r->_mp_size = s != 0; r->_mp_d[0] = s; } } static inline void flint_mpz_set_ui(mpz_ptr r, ulong u) { /* GMP 6.2 lazily performs allocation, deal with that if necessary (in older GMP versions, this code is simply never triggered) */ if (r->_mp_alloc == 0) { r->_mp_d = (mp_ptr) flint_malloc(sizeof(mp_limb_t)); r->_mp_alloc = 1; } r->_mp_d[0] = u; r->_mp_size = u != 0; } static inline void flint_mpz_init_set_si(mpz_ptr r, slong s) { r->_mp_d = (mp_ptr) flint_malloc(sizeof(mp_limb_t)); r->_mp_alloc = 1; if (s < 0) { r->_mp_size = -1; r->_mp_d[0] = -s; } else { r->_mp_size = s != 0; r->_mp_d[0] = s; } } static inline void flint_mpz_init_set_ui(mpz_ptr r, ulong u) { r->_mp_d = (mp_ptr) flint_malloc(sizeof(mp_limb_t)); r->_mp_alloc = 1; r->_mp_d[0] = u; r->_mp_size = u != 0; } static inline void flint_mpz_add_ui(mpz_ptr a, mpz_srcptr b, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_add(a, b, tc); } static inline void flint_mpz_sub_ui(mpz_ptr a, mpz_srcptr b, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_sub(a, b, tc); } static inline void flint_mpz_mul_ui(mpz_ptr a, mpz_srcptr b, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_mul(a, b, tc); } static inline void flint_mpz_mul_si(mpz_ptr a, mpz_srcptr b, slong c) { FLINT_MOCK_MPZ_SI(tc, c); mpz_mul(a, b, tc); } static inline void flint_mpz_addmul_ui(mpz_ptr a, mpz_srcptr b, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_addmul(a, b, tc); } static inline void flint_mpz_submul_ui(mpz_ptr a, mpz_srcptr b, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_submul(a, b, tc); } static inline void flint_mpz_ui_sub(mpz_ptr a, ulong b, mpz_srcptr c) { FLINT_MOCK_MPZ_UI(tb, b); mpz_sub(a, tb, c); } static inline void flint_mpz_ui_pow_ui(mpz_ptr a, ulong b, ulong c) { FLINT_MOCK_MPZ_UI(tb, b); mpz_pow_ui(a, tb, c); } static inline void flint_mpz_divexact_ui(mpz_ptr a, mpz_srcptr b, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_divexact(a, b, tc); } static inline int flint_mpz_divisible_ui_p(mpz_srcptr a, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); return mpz_divisible_p(a, tc); } static inline int flint_mpz_congruent_ui_p(mpz_srcptr a, ulong b, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); { FLINT_MOCK_MPZ_UI(tb, b); return mpz_congruent_p(a, tb, tc); } } static inline int flint_mpz_cmp_ui(mpz_srcptr a, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); return mpz_cmp(a, tc); } static inline int flint_mpz_cmp_si(mpz_srcptr a, slong c) { FLINT_MOCK_MPZ_SI(tc, c); return mpz_cmp(a, tc); } static inline int flint_mpq_cmp_si(mpq_srcptr a, slong b, ulong c) { mpq_t tq; int res; FLINT_MOCK_MPZ_SI(tb, b); { FLINT_MOCK_MPZ_UI(tc, c); mpq_init(tq); mpq_set_num(tq, tb); mpq_set_den(tq, tc); res = mpq_cmp(a, tq); mpq_clear(tq); return res; } } static inline int flint_mpq_cmp_ui(mpq_srcptr a, ulong b, ulong c) { mpq_t tq; int res; FLINT_MOCK_MPZ_UI(tb, b); { FLINT_MOCK_MPZ_UI(tc, c); mpq_init(tq); mpq_set_num(tq, tb); mpq_set_den(tq, tc); res = mpq_cmp(a, tq); mpq_clear(tq); return res; } } static inline void flint_mpq_set_si(mpq_ptr a, slong b, ulong c) { FLINT_MOCK_MPZ_SI(tb, b); { FLINT_MOCK_MPZ_UI(tc, c); mpq_set_num(a, tb); mpq_set_den(a, tc); } } static inline void flint_mpq_set_ui(mpq_ptr a, ulong b, ulong c) { FLINT_MOCK_MPZ_UI(tb, b); { FLINT_MOCK_MPZ_UI(tc, c); mpq_set_num(a, tb); mpq_set_den(a, tc); } } static inline ulong flint_mpz_cdiv_q_ui(mpz_ptr q, mpz_srcptr n, ulong c) { if (FLINT_BIT_COUNT(c) <= 32) return (ulong) mpz_cdiv_q_ui(q, n, (unsigned long) c); else { ulong r; mpz_t rz; mpz_init(rz); FLINT_MOCK_MPZ_UI(tc, c); mpz_cdiv_qr(q, rz, n, tc); r = flint_mpz_get_ui(rz); mpz_clear(rz); return r; } } static inline ulong flint_mpz_fdiv_q_ui(mpz_ptr q, mpz_srcptr n, ulong c) { if (FLINT_BIT_COUNT(c) <= 32) return (ulong) mpz_fdiv_q_ui(q, n, (unsigned long) c); else { ulong r; mpz_t rz; mpz_init(rz); FLINT_MOCK_MPZ_UI(tc, c); mpz_fdiv_qr(q, rz, n, tc); r = flint_mpz_get_ui(rz); mpz_clear(rz); return r; } } static inline ulong flint_mpz_tdiv_q_ui(mpz_ptr q, mpz_srcptr n, ulong c) { if (FLINT_BIT_COUNT(c) <= 32) return (ulong) mpz_tdiv_q_ui(q, n, (unsigned long) c); else { ulong r; mpz_t rz; mpz_init(rz); FLINT_MOCK_MPZ_UI(tc, c); mpz_tdiv_qr(q, rz, n, tc); r = flint_mpz_get_ui(rz); mpz_clear(rz); return r; } } static inline ulong flint_mpz_cdiv_r_ui(mpz_ptr r, mpz_srcptr n, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_cdiv_r(r, n, tc); return flint_mpz_get_ui(r); } static inline ulong flint_mpz_fdiv_r_ui(mpz_ptr r, mpz_srcptr n, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_fdiv_r(r, n, tc); return flint_mpz_get_ui(r); } static inline ulong flint_mpz_tdiv_r_ui(mpz_ptr r, mpz_srcptr n, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_tdiv_r(r, n, tc); return flint_mpz_get_ui(r); } static inline ulong flint_mpz_cdiv_qr_ui(mpz_ptr q, mpz_ptr r, mpz_srcptr n, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_cdiv_qr(q, r, n, tc); return flint_mpz_get_ui(r); } static inline ulong flint_mpz_fdiv_qr_ui(mpz_ptr q, mpz_ptr r, mpz_srcptr n, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_fdiv_qr(q, r, n, tc); return flint_mpz_get_ui(r); } static inline ulong flint_mpz_tdiv_qr_ui(mpz_ptr q, mpz_ptr r, mpz_srcptr n, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_tdiv_qr(q, r, n, tc); return flint_mpz_get_ui(r); } static inline ulong flint_mpz_cdiv_ui(mpz_srcptr n, ulong c) { mpz_t r; ulong res; mpz_init(r); FLINT_MOCK_MPZ_UI(tc, c); mpz_cdiv_r(r, n, tc); res = flint_mpz_get_ui(r); mpz_clear(r); return res; } static inline ulong flint_mpz_fdiv_ui(mpz_srcptr n, ulong c) { mpz_t r; ulong res; mpz_init(r); FLINT_MOCK_MPZ_UI(tc, c); mpz_fdiv_r(r, n, tc); res = flint_mpz_get_ui(r); mpz_clear(r); return res; } static inline ulong flint_mpz_tdiv_ui(mpz_srcptr n, ulong c) { mpz_t r; ulong res; mpz_init(r); FLINT_MOCK_MPZ_UI(tc, c); mpz_tdiv_r(r, n, tc); res = flint_mpz_get_ui(r); mpz_clear(r); return res; } static inline ulong flint_mpz_mod_ui(mpz_ptr r, mpz_srcptr n, ulong c) { FLINT_MOCK_MPZ_UI(tc, c); mpz_fdiv_r(r, n, tc); return flint_mpz_get_ui(r); } static inline void flint_mpz_powm_ui(mpz_ptr r, mpz_srcptr b, ulong exp, mpz_srcptr mod) { FLINT_MOCK_MPZ_UI(texp, exp); mpz_powm(r, b, texp, mod); } static inline void flint_mpz_pow_ui(mpz_ptr r, mpz_srcptr b, ulong exp) { if (exp >= (UWORD(1) << 32)) { flint_throw(FLINT_ERROR, "Exception (flint_mpz_pow_ui). Power too large.\n"); } mpz_pow_ui(r, b, (unsigned long) exp); } static inline void flint_mpz_fac_ui(mpz_ptr r, ulong n) { if (n >= (UWORD(1) << 32)) { flint_throw(FLINT_ERROR, "Exception (flint_mpz_fac_ui). Value n too large.\n"); } mpz_fac_ui(r, (unsigned long) n); } static inline void flint_mpz_bin_uiui(mpz_ptr r, ulong n, ulong k) { if (n >= (UWORD(1) << 32)) { flint_throw(FLINT_ERROR, "Exception (flint_mpz_bin_uiui). Value n too large.\n"); } if (k >= (UWORD(1) << 32)) { flint_throw(FLINT_ERROR, "Exception (flint_mpz_bin_uiui). Value k too large.\n"); } mpz_bin_uiui(r, (unsigned long) n, (unsigned long) k); } static inline void flint_mpz_fib_ui(mpz_ptr r, ulong n) { if (n >= (UWORD(1) << 32)) { flint_throw(FLINT_ERROR, "Exception (flint_mpz_fib_ui). Value n too large.\n"); } mpz_fib_ui(r, (unsigned long) n); } /* mpf_set_si() -- Assign a float from a signed int. Copyright 1993, 1994, 1995, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. Copyright 2015 William Hart. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static inline void flint_mpf_set_si (mpf_ptr dest, slong val) { mp_size_t size; mp_limb_t vl; vl = (mp_limb_t) (val >= 0 ? val : -val); dest->_mp_d[0] = vl; size = vl != 0; dest->_mp_exp = size; dest->_mp_size = val >= 0 ? size : -size; } /* mpf_set_ui() -- Assign a float from an unsigned int. Copyright 1993, 1994, 1995, 2001, 2002, 2004 Free Software Foundation, Inc. Copyright 2015 William Hart This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static inline void flint_mpf_set_ui(mpf_ptr f, ulong val) { mp_size_t size; f->_mp_d[0] = val; size = val != 0; f->_mp_exp = f->_mp_size = size; } /* mpf_get_si -- mpf to long conversion Copyright 2001, 2002, 2004 Free Software Foundation, Inc. Copyright 2015 William Hart This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static inline slong flint_mpf_get_si (mpf_srcptr f) { mp_exp_t exp; mp_size_t size, abs_size; mp_srcptr fp; mp_limb_t fl; exp = f->_mp_exp; size = f->_mp_size; fp = f->_mp_d; /* fraction alone truncates to zero this also covers zero, since we have exp==0 for zero */ if (exp <= 0) return WORD(0); /* there are some limbs above the radix point */ fl = 0; abs_size = FLINT_ABS(size); if (abs_size >= exp) fl = fp[abs_size-exp]; if (size > 0) return fl; else /* this form necessary to correctly handle -0x80..00 */ return ~ (fl - 1); } /* mpf_cmp_ui -- Compare a float with an unsigned integer. Copyright 1993, 1994, 1995, 1999, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static inline int flint_mpf_cmp_ui(mpf_srcptr u, ulong vval) { mp_srcptr up; mp_size_t usize; mp_exp_t uexp; mp_limb_t ulimb; uexp = u->_mp_exp; usize = u->_mp_size; if (usize < 0) return -1; if (vval == 0) return usize != 0; if (uexp > 1) return 1; if (uexp < 1) return -1; up = u->_mp_d; ulimb = up[usize - 1]; usize--; if (ulimb > vval) return 1; else if (ulimb < vval) return -1; while (*up == 0) { up++; usize--; } if (usize > 0) return 1; return 0; } /* mpf_fits_s*_p -- test whether an mpf fits a C signed type. Copyright 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static inline int flint_mpf_fits_slong_p(mpf_srcptr f) { mp_size_t fs, fn; mp_srcptr fp; mp_exp_t exp; mp_limb_t fl; fs = f->_mp_size; if (fs == 0) return 1; /* zero fits */ exp = f->_mp_exp; if (exp < 1) return 1; /* -1 < f < 1 truncates to zero, so fits */ fp = f->_mp_d; fn = FLINT_ABS(fs); if (exp == 1) { fl = fp[fn-1]; } else return 0; return fl <= (fs >= 0 ? (mp_limb_t) WORD_MAX : - (mp_limb_t) WORD_MIN); } /* defined in mpn_extras.h and used by flint_mpf_get_d_2exp below */ double flint_mpn_get_d(mp_srcptr ptr, mp_size_t size, mp_size_t sign, long exp); /* double mpf_get_d_2exp (signed long int *exp, mpf_t src). Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static inline double flint_mpf_get_d_2exp(slong * exp2, mpf_srcptr src) { mp_size_t size, abs_size; mp_limb_t * ptr; int cnt; slong exp; size = src->_mp_size; if (size == 0) { *exp2 = 0; return 0.0; } ptr = src->_mp_d; abs_size = FLINT_ABS(size); cnt = flint_clz(ptr[abs_size - 1]); exp = src->_mp_exp * FLINT_BITS - cnt; *exp2 = exp; return flint_mpn_get_d (ptr, abs_size, size, (long) - (abs_size * FLINT_BITS - cnt)); } #endif flint-3.1.3/src/gmpcompat.h.in000066400000000000000000000074551461254215100162020ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GMP_COMPAT_H #define GMP_COMPAT_H #include "flint.h" #define FLINT_MPZ_REALLOC(z, len) \ ((len) > ((z)->_mp_alloc) \ ? (mp_ptr) _mpz_realloc(z, len) \ : ((z)->_mp_d)) static inline void flint_mpz_add_uiui(mpz_ptr a, mpz_srcptr b, ulong c1, ulong c0) { ulong d[2]; mpz_t c; d[0] = c0; d[1] = c1; c->_mp_d = d; c->_mp_alloc = 2; c->_mp_size = d[1] != 0 ? 2 : d[0] != 0; mpz_add(a, b, c); } static inline void flint_mpz_add_signed_uiui(mpz_ptr a, mpz_srcptr b, ulong c1, ulong c0) { ulong d[2]; ulong c2 = FLINT_SIGN_EXT(c1); mpz_t c; sub_ddmmss(d[1], d[0], c2^c1, c2^c0, c2, c2); c->_mp_d = d; c->_mp_alloc = 2; c->_mp_size = d[1] != 0 ? 2 : d[0] != 0; if (c2 != 0) c->_mp_size = -c->_mp_size; mpz_add(a, b, c); } static inline void flint_mpz_add_uiuiui(mpz_ptr a, mpz_srcptr b, ulong c2, ulong c1, ulong c0) { ulong d[3]; mpz_t c; d[0] = c0; d[1] = c1; d[2] = c2; c->_mp_d = d; c->_mp_alloc = 3; c->_mp_size = d[2] != 0 ? 3 : d[1] != 0 ? 2 : d[0] != 0; mpz_add(a, b, c); } static inline void flint_mpz_add_signed_uiuiui(mpz_ptr a, mpz_srcptr b, ulong c2, ulong c1, ulong c0) { ulong cs, d[3]; mpz_t c; c->_mp_d = d; c->_mp_alloc = 3; cs = FLINT_SIGN_EXT(c2); sub_dddmmmsss(d[2], d[1], d[0], cs^c2, cs^c1, cs^c0, cs, cs, cs); c->_mp_size = d[2] != 0 ? 3 : d[1] != 0 ? 2 : d[0] != 0; if (cs != 0) c->_mp_size = -c->_mp_size; mpz_add(a, b, c); } #define flint_mpz_get_si mpz_get_si #define flint_mpz_get_ui mpz_get_ui #define flint_mpz_set_si mpz_set_si #define flint_mpz_set_ui mpz_set_ui #define flint_mpz_init_set_si mpz_init_set_si #define flint_mpz_init_set_ui mpz_init_set_ui #define flint_mpz_add_ui mpz_add_ui #define flint_mpz_sub_ui mpz_sub_ui #define flint_mpz_mul_si mpz_mul_si #define flint_mpz_mul_ui mpz_mul_ui #define flint_mpz_addmul_ui mpz_addmul_ui #define flint_mpz_submul_ui mpz_submul_ui #define flint_mpz_ui_sub mpz_ui_sub #define flint_mpz_ui_pow_ui mpz_ui_pow_ui #define flint_mpz_cdiv_q_ui mpz_cdiv_q_ui #define flint_mpz_cdiv_r_ui mpz_cdiv_r_ui #define flint_mpz_cdiv_qr_ui mpz_cdiv_qr_ui #define flint_mpz_cdiv_ui mpz_cdiv_ui #define flint_mpz_fdiv_q_ui mpz_fdiv_q_ui #define flint_mpz_fdiv_r_ui mpz_fdiv_r_ui #define flint_mpz_fdiv_qr_ui mpz_fdiv_qr_ui #define flint_mpz_fdiv_ui mpz_fdiv_ui #define flint_mpz_tdiv_q_ui mpz_tdiv_q_ui #define flint_mpz_tdiv_r_ui mpz_tdiv_r_ui #define flint_mpz_tdiv_qr_ui mpz_tdiv_qr_ui #define flint_mpz_tdiv_ui mpz_tdiv_ui #define flint_mpz_mod_ui mpz_mod_ui #define flint_mpz_divexact_ui mpz_divexact_ui #define flint_mpz_divisible_ui_p mpz_divisible_ui_p #define flint_mpz_congruent_ui_p mpz_congruent_ui_p #define flint_mpz_powm_ui mpz_powm_ui #define flint_mpz_pow_ui mpz_pow_ui #define flint_mpz_fac_ui mpz_fac_ui #define flint_mpz_bin_uiui mpz_bin_uiui #define flint_mpz_fib_ui mpz_fib_ui #define flint_mpz_cmp_si mpz_cmp_si #define flint_mpz_cmp_ui mpz_cmp_ui #define flint_mpq_cmp_si mpq_cmp_si #define flint_mpq_cmp_ui mpq_cmp_ui #define flint_mpq_set_si mpq_set_si #define flint_mpq_set_ui mpq_set_ui #define flint_mpf_set_si mpf_set_si #define flint_mpf_set_ui mpf_set_ui #define flint_mpf_get_si mpf_get_si #define flint_mpf_cmp_ui mpf_cmp_ui #define flint_mpf_fits_slong_p mpf_fits_slong_p #define flint_mpf_get_d_2exp mpf_get_d_2exp #endif flint-3.1.3/src/gr.h000066400000000000000000002130301461254215100142020ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GR_H #define GR_H #ifdef GR_INLINES_C #define GR_INLINE #else #define GR_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif #ifndef CALCIUM_H typedef enum { T_TRUE, T_FALSE, T_UNKNOWN } truth_t; #endif GR_INLINE truth_t truth_and(truth_t x, truth_t y) { if (x == T_FALSE || y == T_FALSE) return T_FALSE; if (x == T_TRUE && y == T_TRUE) return T_TRUE; return T_UNKNOWN; } GR_INLINE truth_t truth_or(truth_t x, truth_t y) { if (x == T_TRUE || y == T_TRUE) return T_TRUE; if (x == T_FALSE && y == T_FALSE) return T_FALSE; return T_UNKNOWN; } GR_INLINE truth_t truth_not(truth_t x) { if (x == T_TRUE) return T_FALSE; if (x == T_FALSE) return T_TRUE; return T_UNKNOWN; } GR_INLINE void truth_println(truth_t x) { if (x == T_TRUE) flint_printf("T_TRUE\n"); if (x == T_FALSE) flint_printf("T_FALSE\n"); if (x == T_UNKNOWN) flint_printf("T_UNKNOWN\n"); } typedef int (*gr_funcptr)(void); /* Copied from Calcium: stream interface allows simple file or string IO. */ typedef struct { FLINT_FILE * fp; char * s; slong len; slong alloc; } gr_stream_struct; typedef gr_stream_struct gr_stream_t[1]; #ifdef FLINT_HAVE_FILE void gr_stream_init_file(gr_stream_t out, FILE * fp); #endif void gr_stream_init_str(gr_stream_t out); void gr_stream_write(gr_stream_t out, const char * s); void gr_stream_write_si(gr_stream_t out, slong x); void gr_stream_write_ui(gr_stream_t out, ulong x); void gr_stream_write_free(gr_stream_t out, char * s); void gr_stream_write_fmpz(gr_stream_t out, const fmpz_t x); #define GR_SUCCESS 0 #define GR_DOMAIN 1 #define GR_UNABLE 2 #define GR_TEST_FAIL 4 #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #define GR_MUST_SUCCEED(expr) do { if ((expr) != GR_SUCCESS) { flint_throw(FLINT_ERROR, "GR_MUST_SUCCEED failure: %s", __FILE__); } } while (0) #define GR_IGNORE(expr) do { int ___unused = (expr); (void) ___unused; } while (0) typedef void * gr_ptr; typedef const void * gr_srcptr; typedef void * gr_ctx_ptr; #define GR_ENTRY(vec, i, size) ((void *) (((char *) (vec)) + ((i) * (size)))) typedef struct { gr_ptr entries; slong alloc; slong length; } gr_vec_struct; typedef gr_vec_struct gr_vec_t[1]; GR_INLINE int gr_not_implemented(void) { return GR_UNABLE; } GR_INLINE int gr_not_in_domain(void) { return GR_DOMAIN; } typedef enum { GR_METHOD_CTX_WRITE, GR_METHOD_CTX_CLEAR, /* general ring properties */ GR_METHOD_CTX_IS_RING, GR_METHOD_CTX_IS_COMMUTATIVE_RING, GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, GR_METHOD_CTX_IS_FIELD, GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, GR_METHOD_CTX_IS_FINITE, GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, GR_METHOD_CTX_IS_ZERO_RING, /* ring properties related to orderings and norms */ GR_METHOD_CTX_IS_ORDERED_RING, /* group properties */ GR_METHOD_CTX_IS_MULTIPLICATIVE_GROUP, /* context properties represented to the representation */ GR_METHOD_CTX_IS_EXACT, /* we have no inexact elements */ GR_METHOD_CTX_IS_CANONICAL, /* we have no non-canonical representations */ GR_METHOD_CTX_IS_THREADSAFE, GR_METHOD_CTX_HAS_REAL_PREC, GR_METHOD_CTX_SET_REAL_PREC, GR_METHOD_CTX_GET_REAL_PREC, GR_METHOD_CTX_SET_GEN_NAME, GR_METHOD_CTX_SET_GEN_NAMES, GR_METHOD_INIT, GR_METHOD_CLEAR, GR_METHOD_SWAP, GR_METHOD_SET_SHALLOW, GR_METHOD_WRITE, GR_METHOD_WRITE_N, _GR_METHOD_LENGTH, GR_METHOD_RANDTEST, GR_METHOD_RANDTEST_NOT_ZERO, GR_METHOD_RANDTEST_SMALL, GR_METHOD_ZERO, GR_METHOD_ONE, GR_METHOD_NEG_ONE, GR_METHOD_IS_ZERO, GR_METHOD_IS_ONE, GR_METHOD_IS_NEG_ONE, GR_METHOD_EQUAL, GR_METHOD_SET, GR_METHOD_SET_UI, GR_METHOD_SET_SI, GR_METHOD_SET_FMPZ, GR_METHOD_SET_FMPQ, GR_METHOD_SET_D, GR_METHOD_SET_OTHER, GR_METHOD_SET_STR, GR_METHOD_GET_SI, GR_METHOD_GET_UI, GR_METHOD_GET_FMPZ, GR_METHOD_GET_FMPQ, GR_METHOD_GET_D, GR_METHOD_GET_FEXPR, GR_METHOD_GET_FEXPR_SERIALIZE, GR_METHOD_SET_FEXPR, GR_METHOD_NEG, GR_METHOD_ADD, GR_METHOD_ADD_UI, GR_METHOD_ADD_SI, GR_METHOD_ADD_FMPZ, GR_METHOD_ADD_FMPQ, GR_METHOD_ADD_OTHER, GR_METHOD_OTHER_ADD, GR_METHOD_SUB, GR_METHOD_SUB_UI, GR_METHOD_SUB_SI, GR_METHOD_SUB_FMPZ, GR_METHOD_SUB_FMPQ, GR_METHOD_SUB_OTHER, GR_METHOD_OTHER_SUB, GR_METHOD_MUL, GR_METHOD_MUL_UI, GR_METHOD_MUL_SI, GR_METHOD_MUL_FMPZ, GR_METHOD_MUL_FMPQ, GR_METHOD_MUL_OTHER, GR_METHOD_OTHER_MUL, GR_METHOD_ADDMUL, GR_METHOD_ADDMUL_UI, GR_METHOD_ADDMUL_SI, GR_METHOD_ADDMUL_FMPZ, GR_METHOD_ADDMUL_FMPQ, GR_METHOD_ADDMUL_OTHER, GR_METHOD_SUBMUL, GR_METHOD_SUBMUL_UI, GR_METHOD_SUBMUL_SI, GR_METHOD_SUBMUL_FMPZ, GR_METHOD_SUBMUL_FMPQ, GR_METHOD_SUBMUL_OTHER, GR_METHOD_FMA, GR_METHOD_FMS, GR_METHOD_FMMA, GR_METHOD_FMMS, GR_METHOD_MUL_TWO, GR_METHOD_SQR, GR_METHOD_MUL_2EXP_SI, GR_METHOD_MUL_2EXP_FMPZ, GR_METHOD_SET_FMPZ_2EXP_FMPZ, GR_METHOD_GET_FMPZ_2EXP_FMPZ, GR_METHOD_SET_FMPZ_10EXP_FMPZ, GR_METHOD_IS_INVERTIBLE, GR_METHOD_INV, GR_METHOD_DIV, GR_METHOD_DIV_UI, GR_METHOD_DIV_SI, GR_METHOD_DIV_FMPZ, GR_METHOD_DIV_FMPQ, GR_METHOD_DIV_OTHER, GR_METHOD_OTHER_DIV, GR_METHOD_DIV_NONUNIQUE, GR_METHOD_DIVIDES, GR_METHOD_DIVEXACT, GR_METHOD_DIVEXACT_UI, GR_METHOD_DIVEXACT_SI, GR_METHOD_DIVEXACT_FMPZ, GR_METHOD_DIVEXACT_FMPQ, GR_METHOD_DIVEXACT_OTHER, GR_METHOD_OTHER_DIVEXACT, GR_METHOD_POW, GR_METHOD_POW_UI, GR_METHOD_POW_SI, GR_METHOD_POW_FMPZ, GR_METHOD_POW_FMPQ, GR_METHOD_POW_OTHER, GR_METHOD_OTHER_POW, GR_METHOD_IS_SQUARE, GR_METHOD_SQRT, GR_METHOD_RSQRT, GR_METHOD_HYPOT, GR_METHOD_IS_PERFECT_POWER, GR_METHOD_FACTOR_PERFECT_POWER, GR_METHOD_ROOT_UI, GR_METHOD_EUCLIDEAN_DIV, GR_METHOD_EUCLIDEAN_REM, GR_METHOD_EUCLIDEAN_DIVREM, GR_METHOD_GCD, GR_METHOD_LCM, GR_METHOD_FACTOR, GR_METHOD_NUMERATOR, GR_METHOD_DENOMINATOR, GR_METHOD_FLOOR, GR_METHOD_CEIL, GR_METHOD_TRUNC, GR_METHOD_NINT, GR_METHOD_CMP, GR_METHOD_CMPABS, GR_METHOD_CMP_OTHER, GR_METHOD_CMPABS_OTHER, GR_METHOD_MIN, GR_METHOD_MAX, GR_METHOD_ABS, GR_METHOD_ABS2, GR_METHOD_I, GR_METHOD_CONJ, GR_METHOD_RE, GR_METHOD_IM, GR_METHOD_SGN, GR_METHOD_CSGN, GR_METHOD_ARG, GR_METHOD_POS_INF, GR_METHOD_NEG_INF, GR_METHOD_UINF, GR_METHOD_UNDEFINED, GR_METHOD_UNKNOWN, GR_METHOD_IS_INTEGER, GR_METHOD_IS_RATIONAL, GR_METHOD_IS_REAL, GR_METHOD_IS_POSITIVE_INTEGER, GR_METHOD_IS_NONNEGATIVE_INTEGER, GR_METHOD_IS_NEGATIVE_INTEGER, GR_METHOD_IS_NONPOSITIVE_INTEGER, GR_METHOD_IS_POSITIVE_REAL, GR_METHOD_IS_NONNEGATIVE_REAL, GR_METHOD_IS_NEGATIVE_REAL, GR_METHOD_IS_NONPOSITIVE_REAL, GR_METHOD_SET_INTERVAL_MID_RAD, /* todo: roots of unity */ GR_METHOD_IS_ROOT_OF_UNITY, GR_METHOD_ROOT_OF_UNITY_UI, GR_METHOD_ROOT_OF_UNITY_UI_VEC, /* Elementary transcendental functions */ GR_METHOD_PI, GR_METHOD_EXP, GR_METHOD_EXPM1, GR_METHOD_EXP_PI_I, GR_METHOD_EXP2, GR_METHOD_EXP10, GR_METHOD_LOG, GR_METHOD_LOG1P, GR_METHOD_LOG_PI_I, GR_METHOD_LOG2, GR_METHOD_LOG10, GR_METHOD_SIN, GR_METHOD_COS, GR_METHOD_SIN_COS, GR_METHOD_TAN, GR_METHOD_COT, GR_METHOD_SEC, GR_METHOD_CSC, GR_METHOD_SIN_PI, GR_METHOD_COS_PI, GR_METHOD_SIN_COS_PI, GR_METHOD_TAN_PI, GR_METHOD_COT_PI, GR_METHOD_SEC_PI, GR_METHOD_CSC_PI, GR_METHOD_SINC, GR_METHOD_SINC_PI, GR_METHOD_SINH, GR_METHOD_COSH, GR_METHOD_SINH_COSH, GR_METHOD_TANH, GR_METHOD_COTH, GR_METHOD_SECH, GR_METHOD_CSCH, GR_METHOD_ASIN, GR_METHOD_ACOS, GR_METHOD_ATAN, GR_METHOD_ATAN2, GR_METHOD_ACOT, GR_METHOD_ASEC, GR_METHOD_ACSC, GR_METHOD_ASINH, GR_METHOD_ACOSH, GR_METHOD_ATANH, GR_METHOD_ACOTH, GR_METHOD_ASECH, GR_METHOD_ACSCH, GR_METHOD_ASIN_PI, GR_METHOD_ACOS_PI, GR_METHOD_ATAN_PI, GR_METHOD_ACOT_PI, GR_METHOD_ASEC_PI, GR_METHOD_ACSC_PI, /* Combinatorial and related functions */ GR_METHOD_FAC, GR_METHOD_FAC_UI, GR_METHOD_FAC_FMPZ, GR_METHOD_FAC_VEC, GR_METHOD_RFAC, GR_METHOD_RFAC_UI, GR_METHOD_RFAC_FMPZ, GR_METHOD_RFAC_VEC, GR_METHOD_BIN, GR_METHOD_BIN_UI, GR_METHOD_BIN_UIUI, GR_METHOD_BIN_VEC, GR_METHOD_BIN_UI_VEC, GR_METHOD_RISING_UI, GR_METHOD_RISING, GR_METHOD_FALLING_UI, GR_METHOD_FALLING, GR_METHOD_GAMMA, GR_METHOD_GAMMA_FMPZ, GR_METHOD_GAMMA_FMPQ, GR_METHOD_RGAMMA, GR_METHOD_LGAMMA, GR_METHOD_DIGAMMA, GR_METHOD_BETA, GR_METHOD_DOUBLEFAC, GR_METHOD_DOUBLEFAC_UI, GR_METHOD_BARNES_G, GR_METHOD_LOG_BARNES_G, GR_METHOD_HARMONIC, GR_METHOD_HARMONIC_UI, GR_METHOD_BERNOULLI_UI, GR_METHOD_BERNOULLI_FMPZ, GR_METHOD_BERNOULLI_VEC, GR_METHOD_FIB_UI, GR_METHOD_FIB_FMPZ, GR_METHOD_FIB_VEC, GR_METHOD_STIRLING_S1U_UIUI, GR_METHOD_STIRLING_S1_UIUI, GR_METHOD_STIRLING_S2_UIUI, GR_METHOD_STIRLING_S1U_UI_VEC, GR_METHOD_STIRLING_S1_UI_VEC, GR_METHOD_STIRLING_S2_UI_VEC, GR_METHOD_EULERNUM_UI, GR_METHOD_EULERNUM_FMPZ, GR_METHOD_EULERNUM_VEC, GR_METHOD_BELLNUM_UI, GR_METHOD_BELLNUM_FMPZ, GR_METHOD_BELLNUM_VEC, GR_METHOD_PARTITIONS_UI, GR_METHOD_PARTITIONS_FMPZ, GR_METHOD_PARTITIONS_VEC, /* Orthogonal polynomials */ GR_METHOD_CHEBYSHEV_T_FMPZ, GR_METHOD_CHEBYSHEV_U_FMPZ, GR_METHOD_CHEBYSHEV_T, GR_METHOD_CHEBYSHEV_U, GR_METHOD_JACOBI_P, GR_METHOD_GEGENBAUER_C, GR_METHOD_LAGUERRE_L, GR_METHOD_HERMITE_H, GR_METHOD_LEGENDRE_P, GR_METHOD_LEGENDRE_Q, GR_METHOD_LEGENDRE_P_ROOT_UI, GR_METHOD_SPHERICAL_Y_SI, /* Misc real constants */ GR_METHOD_EULER, GR_METHOD_CATALAN, GR_METHOD_KHINCHIN, GR_METHOD_GLAISHER, GR_METHOD_LAMBERTW, GR_METHOD_LAMBERTW_FMPZ, GR_METHOD_ERF, GR_METHOD_ERFC, GR_METHOD_ERFCX, GR_METHOD_ERFI, GR_METHOD_ERFINV, GR_METHOD_ERFCINV, GR_METHOD_FRESNEL_S, GR_METHOD_FRESNEL_C, GR_METHOD_FRESNEL, GR_METHOD_GAMMA_UPPER, GR_METHOD_GAMMA_LOWER, GR_METHOD_BETA_LOWER, GR_METHOD_EXP_INTEGRAL, GR_METHOD_EXP_INTEGRAL_EI, GR_METHOD_SIN_INTEGRAL, GR_METHOD_COS_INTEGRAL, GR_METHOD_SINH_INTEGRAL, GR_METHOD_COSH_INTEGRAL, GR_METHOD_LOG_INTEGRAL, GR_METHOD_DILOG, GR_METHOD_BESSEL_J, GR_METHOD_BESSEL_Y, GR_METHOD_BESSEL_J_Y, GR_METHOD_BESSEL_I, GR_METHOD_BESSEL_I_SCALED, GR_METHOD_BESSEL_K, GR_METHOD_BESSEL_K_SCALED, GR_METHOD_AIRY, GR_METHOD_AIRY_AI, GR_METHOD_AIRY_BI, GR_METHOD_AIRY_AI_PRIME, GR_METHOD_AIRY_BI_PRIME, GR_METHOD_AIRY_AI_ZERO, GR_METHOD_AIRY_BI_ZERO, GR_METHOD_AIRY_AI_PRIME_ZERO, GR_METHOD_AIRY_BI_PRIME_ZERO, GR_METHOD_COULOMB, GR_METHOD_COULOMB_F, GR_METHOD_COULOMB_G, GR_METHOD_COULOMB_HPOS, GR_METHOD_COULOMB_HNEG, GR_METHOD_ZETA, GR_METHOD_ZETA_UI, GR_METHOD_HURWITZ_ZETA, GR_METHOD_LERCH_PHI, GR_METHOD_STIELTJES, GR_METHOD_DIRICHLET_ETA, GR_METHOD_DIRICHLET_BETA, GR_METHOD_RIEMANN_XI, GR_METHOD_ZETA_ZERO, GR_METHOD_ZETA_ZERO_VEC, GR_METHOD_ZETA_NZEROS, GR_METHOD_DIRICHLET_CHI_UI, GR_METHOD_DIRICHLET_CHI_FMPZ, GR_METHOD_DIRICHLET_L, GR_METHOD_DIRICHLET_HARDY_THETA, GR_METHOD_DIRICHLET_HARDY_Z, GR_METHOD_BERNPOLY_UI, GR_METHOD_EULERPOLY_UI, GR_METHOD_POLYLOG, GR_METHOD_POLYGAMMA, GR_METHOD_HYPGEOM_0F1, GR_METHOD_HYPGEOM_1F1, GR_METHOD_HYPGEOM_2F0, GR_METHOD_HYPGEOM_2F1, GR_METHOD_HYPGEOM_U, GR_METHOD_HYPGEOM_PFQ, GR_METHOD_JACOBI_THETA, GR_METHOD_JACOBI_THETA_1, GR_METHOD_JACOBI_THETA_2, GR_METHOD_JACOBI_THETA_3, GR_METHOD_JACOBI_THETA_4, GR_METHOD_JACOBI_THETA_Q, GR_METHOD_JACOBI_THETA_Q_1, GR_METHOD_JACOBI_THETA_Q_2, GR_METHOD_JACOBI_THETA_Q_3, GR_METHOD_JACOBI_THETA_Q_4, GR_METHOD_MODULAR_J, GR_METHOD_MODULAR_LAMBDA, GR_METHOD_MODULAR_DELTA, GR_METHOD_HILBERT_CLASS_POLY, GR_METHOD_DEDEKIND_ETA, GR_METHOD_DEDEKIND_ETA_Q, GR_METHOD_EISENSTEIN_E, GR_METHOD_EISENSTEIN_G, GR_METHOD_EISENSTEIN_G_VEC, GR_METHOD_AGM, GR_METHOD_AGM1, GR_METHOD_ELLIPTIC_K, GR_METHOD_ELLIPTIC_E, GR_METHOD_ELLIPTIC_PI, GR_METHOD_ELLIPTIC_F, GR_METHOD_ELLIPTIC_E_INC, GR_METHOD_ELLIPTIC_PI_INC, GR_METHOD_CARLSON_RF, GR_METHOD_CARLSON_RC, GR_METHOD_CARLSON_RJ, GR_METHOD_CARLSON_RG, GR_METHOD_CARLSON_RD, GR_METHOD_ELLIPTIC_ROOTS, GR_METHOD_ELLIPTIC_INVARIANTS, GR_METHOD_WEIERSTRASS_P, GR_METHOD_WEIERSTRASS_P_PRIME, GR_METHOD_WEIERSTRASS_P_INV, GR_METHOD_WEIERSTRASS_ZETA, GR_METHOD_WEIERSTRASS_SIGMA, GR_METHOD_GEN, GR_METHOD_GENS, GR_METHOD_GENS_RECURSIVE, /* Finite field methods */ GR_METHOD_CTX_FQ_PRIME, GR_METHOD_CTX_FQ_DEGREE, GR_METHOD_CTX_FQ_ORDER, GR_METHOD_FQ_FROBENIUS, GR_METHOD_FQ_MULTIPLICATIVE_ORDER, GR_METHOD_FQ_NORM, GR_METHOD_FQ_TRACE, GR_METHOD_FQ_IS_PRIMITIVE, GR_METHOD_FQ_PTH_ROOT, /* Vector methods */ GR_METHOD_VEC_INIT, GR_METHOD_VEC_CLEAR, GR_METHOD_VEC_SWAP, GR_METHOD_VEC_SET, GR_METHOD_VEC_ZERO, GR_METHOD_VEC_EQUAL, GR_METHOD_VEC_IS_ZERO, GR_METHOD_VEC_NEG, GR_METHOD_VEC_NORMALISE, GR_METHOD_VEC_NORMALISE_WEAK, GR_METHOD_VEC_ADD, GR_METHOD_VEC_SUB, GR_METHOD_VEC_MUL, GR_METHOD_VEC_DIV, GR_METHOD_VEC_DIVEXACT, GR_METHOD_VEC_POW, GR_METHOD_VEC_ADD_SCALAR, GR_METHOD_VEC_SUB_SCALAR, GR_METHOD_VEC_MUL_SCALAR, GR_METHOD_VEC_DIV_SCALAR, GR_METHOD_VEC_DIVEXACT_SCALAR, GR_METHOD_VEC_POW_SCALAR, GR_METHOD_SCALAR_ADD_VEC, GR_METHOD_SCALAR_SUB_VEC, GR_METHOD_SCALAR_MUL_VEC, GR_METHOD_SCALAR_DIV_VEC, GR_METHOD_SCALAR_DIVEXACT_VEC, GR_METHOD_SCALAR_POW_VEC, GR_METHOD_VEC_ADD_OTHER, GR_METHOD_VEC_SUB_OTHER, GR_METHOD_VEC_MUL_OTHER, GR_METHOD_VEC_DIV_OTHER, GR_METHOD_VEC_DIVEXACT_OTHER, GR_METHOD_VEC_POW_OTHER, GR_METHOD_OTHER_ADD_VEC, GR_METHOD_OTHER_SUB_VEC, GR_METHOD_OTHER_MUL_VEC, GR_METHOD_OTHER_DIV_VEC, GR_METHOD_OTHER_DIVEXACT_VEC, GR_METHOD_OTHER_POW_VEC, GR_METHOD_VEC_ADD_SCALAR_OTHER, GR_METHOD_VEC_SUB_SCALAR_OTHER, GR_METHOD_VEC_MUL_SCALAR_OTHER, GR_METHOD_VEC_DIV_SCALAR_OTHER, GR_METHOD_VEC_DIVEXACT_SCALAR_OTHER, GR_METHOD_VEC_POW_SCALAR_OTHER, GR_METHOD_SCALAR_OTHER_ADD_VEC, GR_METHOD_SCALAR_OTHER_SUB_VEC, GR_METHOD_SCALAR_OTHER_MUL_VEC, GR_METHOD_SCALAR_OTHER_DIV_VEC, GR_METHOD_SCALAR_OTHER_DIVEXACT_VEC, GR_METHOD_SCALAR_OTHER_POW_VEC, GR_METHOD_VEC_ADD_SCALAR_SI, GR_METHOD_VEC_ADD_SCALAR_UI, GR_METHOD_VEC_ADD_SCALAR_FMPZ, GR_METHOD_VEC_ADD_SCALAR_FMPQ, GR_METHOD_VEC_SUB_SCALAR_SI, GR_METHOD_VEC_SUB_SCALAR_UI, GR_METHOD_VEC_SUB_SCALAR_FMPZ, GR_METHOD_VEC_SUB_SCALAR_FMPQ, GR_METHOD_VEC_MUL_SCALAR_SI, GR_METHOD_VEC_MUL_SCALAR_UI, GR_METHOD_VEC_MUL_SCALAR_FMPZ, GR_METHOD_VEC_MUL_SCALAR_FMPQ, GR_METHOD_VEC_DIV_SCALAR_SI, GR_METHOD_VEC_DIV_SCALAR_UI, GR_METHOD_VEC_DIV_SCALAR_FMPZ, GR_METHOD_VEC_DIV_SCALAR_FMPQ, GR_METHOD_VEC_DIVEXACT_SCALAR_SI, GR_METHOD_VEC_DIVEXACT_SCALAR_UI, GR_METHOD_VEC_DIVEXACT_SCALAR_FMPZ, GR_METHOD_VEC_DIVEXACT_SCALAR_FMPQ, GR_METHOD_VEC_POW_SCALAR_SI, GR_METHOD_VEC_POW_SCALAR_UI, GR_METHOD_VEC_POW_SCALAR_FMPZ, GR_METHOD_VEC_POW_SCALAR_FMPQ, GR_METHOD_VEC_MUL_SCALAR_2EXP_SI, GR_METHOD_VEC_MUL_SCALAR_2EXP_FMPZ, GR_METHOD_VEC_ADDMUL_SCALAR, GR_METHOD_VEC_SUBMUL_SCALAR, GR_METHOD_VEC_ADDMUL_SCALAR_SI, GR_METHOD_VEC_SUBMUL_SCALAR_SI, GR_METHOD_VEC_SUM, GR_METHOD_VEC_PRODUCT, GR_METHOD_VEC_DOT, GR_METHOD_VEC_DOT_REV, GR_METHOD_VEC_DOT_UI, GR_METHOD_VEC_DOT_SI, GR_METHOD_VEC_DOT_FMPZ, GR_METHOD_VEC_SET_POWERS, GR_METHOD_VEC_RECIPROCALS, /* Polynomial methods (todo: rename -> GR_POLY) */ GR_METHOD_POLY_MULLOW, GR_METHOD_POLY_DIV, GR_METHOD_POLY_DIVREM, GR_METHOD_POLY_DIVEXACT, GR_METHOD_POLY_TAYLOR_SHIFT, GR_METHOD_POLY_INV_SERIES, GR_METHOD_POLY_INV_SERIES_BASECASE, GR_METHOD_POLY_DIV_SERIES, GR_METHOD_POLY_DIV_SERIES_BASECASE, GR_METHOD_POLY_RSQRT_SERIES, GR_METHOD_POLY_SQRT_SERIES, GR_METHOD_POLY_EXP_SERIES, GR_METHOD_POLY_FACTOR, GR_METHOD_POLY_ROOTS, GR_METHOD_POLY_ROOTS_OTHER, /* Matrix methods (todo: rename -> GR_MAT) */ GR_METHOD_MAT_MUL, GR_METHOD_MAT_LU, GR_METHOD_MAT_DET, GR_METHOD_MAT_EXP, GR_METHOD_MAT_LOG, GR_METHOD_MAT_FIND_NONZERO_PIVOT, GR_METHOD_MAT_DIAGONALIZATION, GR_METHOD_TAB_SIZE } gr_method; typedef gr_funcptr gr_static_method_table[GR_METHOD_TAB_SIZE]; typedef struct { gr_method index; gr_funcptr function; } gr_method_tab_input; void gr_method_tab_init(gr_funcptr * methods, gr_method_tab_input * tab); /* Identify specific rings/fields. */ typedef enum { GR_CTX_FMPZ, GR_CTX_FMPQ, GR_CTX_FMPZI, GR_CTX_FMPZ_MOD, GR_CTX_NMOD, GR_CTX_NMOD8, GR_CTX_NMOD32, GR_CTX_FQ, GR_CTX_FQ_NMOD, GR_CTX_FQ_ZECH, GR_CTX_NF, GR_CTX_REAL_ALGEBRAIC_QQBAR, GR_CTX_COMPLEX_ALGEBRAIC_QQBAR, GR_CTX_REAL_ALGEBRAIC_CA, GR_CTX_COMPLEX_ALGEBRAIC_CA, GR_CTX_RR_CA, GR_CTX_CC_CA, GR_CTX_COMPLEX_EXTENDED_CA, GR_CTX_RR_ARB, GR_CTX_CC_ACB, GR_CTX_REAL_FLOAT_ARF, GR_CTX_COMPLEX_FLOAT_ACF, GR_CTX_FMPZ_POLY, GR_CTX_FMPQ_POLY, GR_CTX_GR_POLY, GR_CTX_FMPZ_MPOLY, GR_CTX_GR_MPOLY, GR_CTX_FMPZ_MPOLY_Q, GR_CTX_GR_SERIES, GR_CTX_GR_SERIES_MOD, GR_CTX_GR_MAT, GR_CTX_GR_VEC, GR_CTX_PSL2Z, GR_CTX_DIRICHLET_GROUP, GR_CTX_PERM, GR_CTX_FEXPR, GR_CTX_UNKNOWN_DOMAIN, GR_CTX_WHICH_STRUCTURE_TAB_SIZE } gr_which_structure; /* large enough to hold any context data we want to store inline */ #define GR_CTX_STRUCT_DATA_BYTES (6 * sizeof(ulong)) typedef struct { char data[GR_CTX_STRUCT_DATA_BYTES]; ulong which_ring; slong sizeof_elem; gr_funcptr * methods; ulong size_limit; } gr_ctx_struct; typedef gr_ctx_struct gr_ctx_t[1]; #define GR_CTX_DATA_AS_PTR(ctx) (*(void **) (&(ctx)->data)) GR_INLINE void * gr_ctx_data_ptr(gr_ctx_t ctx) { return (void *) ctx->data; } GR_INLINE void * gr_ctx_data_as_ptr(gr_ctx_t ctx) { return (void *) GR_CTX_DATA_AS_PTR(ctx); } GR_INLINE slong gr_ctx_sizeof_ctx(void) { return sizeof(gr_ctx_struct); } GR_INLINE slong gr_ctx_sizeof_elem(gr_ctx_t ctx) { return ctx->sizeof_elem; } /* Typedefs for method function pointers. */ typedef void ((*gr_method_init_clear_op)(gr_ptr, gr_ctx_ptr)); typedef void ((*gr_method_swap_op)(gr_ptr, gr_ptr, gr_ctx_ptr)); typedef int ((*gr_method_ctx)(gr_ctx_ptr)); typedef truth_t ((*gr_method_ctx_predicate)(gr_ctx_ptr)); typedef int ((*gr_method_ctx_set_si)(gr_ctx_ptr, slong)); typedef int ((*gr_method_ctx_get_si)(slong *, gr_ctx_ptr)); typedef int ((*gr_method_ctx_stream)(gr_stream_t, gr_ctx_ptr)); typedef int ((*gr_method_ctx_set_str)(gr_ctx_ptr, const char *)); typedef int ((*gr_method_ctx_set_strs)(gr_ctx_ptr, const char **)); typedef int ((*gr_method_stream_in)(gr_stream_t, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_stream_in_si)(gr_stream_t, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_randtest)(gr_ptr, flint_rand_t state, gr_ctx_ptr)); typedef int ((*gr_method_constant_op)(gr_ptr, gr_ctx_ptr)); typedef int ((*gr_method_constant_op_get_si)(slong *, gr_ctx_ptr)); typedef int ((*gr_method_constant_op_get_fmpz)(fmpz_t, gr_ctx_ptr)); typedef void ((*gr_method_void_unary_op)(gr_ptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op)(gr_ptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_si)(gr_ptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_ui)(gr_ptr, ulong, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_fmpz)(gr_ptr, const fmpz_t, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_fmpq)(gr_ptr, const fmpq_t, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_d)(gr_ptr, double, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_other)(gr_ptr, gr_srcptr, gr_ctx_ptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_str)(gr_ptr, const char *, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_get_ui)(ulong *, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_get_si)(slong *, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_get_fmpz)(fmpz_t, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_get_fmpq)(fmpq_t, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_get_d)(double *, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_get_fmpz_fmpz)(fmpz_t, fmpz_t, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_unary_op_with_flag)(gr_ptr, gr_srcptr, int, gr_ctx_ptr)); typedef int ((*gr_method_binary_unary_op)(gr_ptr, gr_ptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_binary_unary_op_with_flag)(gr_ptr, gr_ptr, gr_srcptr, int, gr_ctx_ptr)); typedef int ((*gr_method_quaternary_unary_op)(gr_ptr, gr_ptr, gr_ptr, gr_ptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_binary_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_si)(gr_ptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_ui)(gr_ptr, gr_srcptr, ulong, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_fmpz)(gr_ptr, gr_srcptr, const fmpz_t, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_fmpz_fmpz)(gr_ptr, const fmpz_t, const fmpz_t, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_fmpz_si)(gr_ptr, const fmpz_t, slong, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_fmpq)(gr_ptr, gr_srcptr, const fmpq_t, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_other)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_ptr, gr_ctx_ptr)); typedef int ((*gr_method_other_binary_op)(gr_ptr, gr_srcptr, gr_ctx_ptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_si_binary_op)(gr_ptr, slong, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_ui_binary_op)(gr_ptr, ulong, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_fmpz_binary_op)(gr_ptr, const fmpz_t, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_fmpq_binary_op)(gr_ptr, const fmpq_t, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_ui_ui)(gr_ptr, ulong, ulong, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_ui_si)(gr_ptr, ulong, slong, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_get_int)(int *, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_other_get_int)(int *, gr_srcptr, gr_srcptr, gr_ctx_ptr, gr_ctx_ptr)); typedef int ((*gr_method_binary_binary_op)(gr_ptr, gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_binary_op_with_flag)(gr_ptr, gr_srcptr, gr_srcptr, int, gr_ctx_ptr)); typedef int ((*gr_method_binary_binary_op_ui_ui)(gr_ptr, gr_ptr, ulong, ulong, gr_ctx_ptr)); typedef int ((*gr_method_ternary_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_ternary_op_with_flag)(gr_ptr, gr_srcptr, gr_srcptr, gr_srcptr, int, gr_ctx_ptr)); typedef int ((*gr_method_ternary_unary_op)(gr_ptr, gr_ptr, gr_ptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_quaternary_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_quaternary_op_with_flag)(gr_ptr, gr_srcptr, gr_srcptr, gr_srcptr, gr_srcptr, int, gr_ctx_ptr)); typedef int ((*gr_method_quaternary_binary_op)(gr_ptr, gr_ptr, gr_ptr, gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_quaternary_ternary_op)(gr_ptr, gr_ptr, gr_ptr, gr_ptr, gr_srcptr, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_si_si_quaternary_op)(gr_ptr, slong, slong, gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef truth_t ((*gr_method_unary_predicate)(gr_srcptr, gr_ctx_ptr)); typedef truth_t ((*gr_method_binary_predicate)(gr_srcptr, gr_srcptr, gr_ctx_ptr)); typedef void ((*gr_method_vec_init_clear_op)(gr_ptr, slong, gr_ctx_ptr)); typedef void ((*gr_method_vec_swap_op)(gr_ptr, gr_ptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_constant_op)(gr_ptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_op)(gr_ptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_vec_op)(gr_ptr, gr_srcptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_scalar_op)(gr_ptr, gr_srcptr, slong, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_scalar_vec_op)(gr_ptr, gr_srcptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_op_other)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_ptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_other_op_vec)(gr_ptr, gr_srcptr, gr_ctx_ptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_op_scalar_other)(gr_ptr, gr_srcptr, slong, gr_srcptr, gr_ctx_ptr, gr_ctx_ptr)); typedef int ((*gr_method_scalar_other_op_vec)(gr_ptr, gr_srcptr, gr_ctx_ptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_scalar_op_si)(gr_ptr, gr_srcptr, slong, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_scalar_op_ui)(gr_ptr, gr_srcptr, slong, ulong, gr_ctx_ptr)); typedef int ((*gr_method_vec_scalar_op_fmpz)(gr_ptr, gr_srcptr, slong, const fmpz_t, gr_ctx_ptr)); typedef int ((*gr_method_vec_scalar_op_fmpq)(gr_ptr, gr_srcptr, slong, const fmpq_t, gr_ctx_ptr)); typedef truth_t ((*gr_method_vec_predicate)(gr_srcptr, slong, gr_ctx_ptr)); typedef truth_t ((*gr_method_vec_vec_predicate)(gr_srcptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_factor_op)(gr_ptr, gr_vec_t, gr_vec_t, gr_srcptr, int, gr_ctx_ptr)); typedef int ((*gr_method_poly_unary_trunc_op)(gr_ptr, gr_srcptr, slong, slong, gr_ctx_ptr)); typedef int ((*gr_method_poly_binary_op)(gr_ptr, gr_srcptr, slong, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_poly_binary_binary_op)(gr_ptr, gr_ptr, gr_srcptr, slong, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_poly_binary_trunc_op)(gr_ptr, gr_srcptr, slong, gr_srcptr, slong, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_ctx_op)(gr_vec_t, gr_ctx_ptr)); typedef slong ((*_gr_method_get_si_op)(gr_srcptr, gr_ctx_ptr)); #ifdef FEXPR_H typedef int ((*gr_method_get_fexpr_op)(fexpr_t, gr_srcptr, gr_ctx_ptr)); typedef int ((*gr_method_set_fexpr_op)(gr_ptr, fexpr_vec_t, gr_vec_t, const fexpr_t, gr_ctx_ptr)); #endif /* Macros to retrieve methods (with correct call signature) from context object. */ #define GR_CTX_OP(ctx, NAME) (((gr_method_ctx *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CTX_STREAM(ctx, NAME) (((gr_method_ctx_stream *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CTX_PREDICATE(ctx, NAME) (((gr_method_ctx_predicate *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CTX_SET_SI(ctx, NAME) (((gr_method_ctx_set_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CTX_GET_SI(ctx, NAME) (((gr_method_ctx_get_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CTX_SET_STR(ctx, NAME) (((gr_method_ctx_set_str *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CTX_SET_STRS(ctx, NAME) (((gr_method_ctx_set_strs *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_STREAM_IN(ctx, NAME) (((gr_method_stream_in *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_STREAM_IN_SI(ctx, NAME) (((gr_method_stream_in_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_RANDTEST(ctx, NAME) (((gr_method_randtest *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_INIT_CLEAR_OP(ctx, NAME) (((gr_method_init_clear_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_SWAP_OP(ctx, NAME) (((gr_method_swap_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CONSTANT_OP(ctx, NAME) (((gr_method_constant_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CONSTANT_OP_GET_SI(ctx, NAME) (((gr_method_constant_op_get_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_CONSTANT_OP_GET_FMPZ(ctx, NAME) (((gr_method_constant_op_get_fmpz *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VOID_UNARY_OP(ctx, NAME) (((gr_method_void_unary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP(ctx, NAME) (((gr_method_unary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_SI(ctx, NAME) (((gr_method_unary_op_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_UI(ctx, NAME) (((gr_method_unary_op_ui *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_FMPZ(ctx, NAME) (((gr_method_unary_op_fmpz *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_FMPQ(ctx, NAME) (((gr_method_unary_op_fmpq *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_D(ctx, NAME) (((gr_method_unary_op_d *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_OTHER(ctx, NAME) (((gr_method_unary_op_other *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_STR(ctx, NAME) (((gr_method_unary_op_str *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_GET_SI(ctx, NAME) (((gr_method_unary_op_get_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_GET_UI(ctx, NAME) (((gr_method_unary_op_get_ui *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_GET_FMPZ(ctx, NAME) (((gr_method_unary_op_get_fmpz *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_GET_FMPQ(ctx, NAME) (((gr_method_unary_op_get_fmpq *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_GET_D(ctx, NAME) (((gr_method_unary_op_get_d *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_GET_FMPZ_FMPZ(ctx, NAME) (((gr_method_unary_op_get_fmpz_fmpz *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_OP_WITH_FLAG(ctx, NAME) (((gr_method_unary_op_with_flag *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_UNARY_OP(ctx, NAME) (((gr_method_binary_unary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_UNARY_OP_WITH_FLAG(ctx, NAME) (((gr_method_binary_unary_op_with_flag *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_TERNARY_UNARY_OP(ctx, NAME) (((gr_method_ternary_unary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_QUATERNARY_UNARY_OP(ctx, NAME) (((gr_method_quaternary_unary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP(ctx, NAME) (((gr_method_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_SI(ctx, NAME) (((gr_method_binary_op_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_UI(ctx, NAME) (((gr_method_binary_op_ui *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_FMPZ(ctx, NAME) (((gr_method_binary_op_fmpz *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_FMPQ(ctx, NAME) (((gr_method_binary_op_fmpq *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_OTHER(ctx, NAME) (((gr_method_binary_op_other *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_FMPZ_FMPZ(ctx, NAME) (((gr_method_binary_op_fmpz_fmpz *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_FMPZ_SI(ctx, NAME) (((gr_method_binary_op_fmpz_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_UI_UI(ctx, NAME) (((gr_method_binary_op_ui_ui *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_UI_SI(ctx, NAME) (((gr_method_binary_op_ui_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_OTHER_BINARY_OP(ctx, NAME) (((gr_method_other_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_SI_BINARY_OP(ctx, NAME) (((gr_method_si_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UI_BINARY_OP(ctx, NAME) (((gr_method_ui_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_FMPZ_BINARY_OP(ctx, NAME) (((gr_method_fmpz_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_FMPQ_BINARY_OP(ctx, NAME) (((gr_method_fmpq_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_GET_INT(ctx, NAME) (((gr_method_binary_op_get_int *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_OTHER_GET_INT(ctx, NAME) (((gr_method_binary_op_other_get_int *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_BINARY_OP(ctx, NAME) (((gr_method_binary_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_UNARY_PREDICATE(ctx, NAME) (((gr_method_unary_predicate *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_PREDICATE(ctx, NAME) (((gr_method_binary_predicate *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_OP_WITH_FLAG(ctx, NAME) (((gr_method_binary_op_with_flag *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_BINARY_BINARY_OP_UI_UI(ctx, NAME) (((gr_method_binary_binary_op_ui_ui *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_TERNARY_OP(ctx, NAME) (((gr_method_ternary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_TERNARY_OP_WITH_FLAG(ctx, NAME) (((gr_method_ternary_op_with_flag *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_QUATERNARY_OP(ctx, NAME) (((gr_method_quaternary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_QUATERNARY_OP_WITH_FLAG(ctx, NAME) (((gr_method_quaternary_op_with_flag *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_QUATERNARY_BINARY_OP(ctx, NAME) (((gr_method_quaternary_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_QUATERNARY_TERNARY_OP(ctx, NAME) (((gr_method_quaternary_ternary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_SI_SI_QUATERNARY_OP(ctx, NAME) (((gr_method_si_si_quaternary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_INIT_CLEAR_OP(ctx, NAME) (((gr_method_vec_init_clear_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_SWAP_OP(ctx, NAME) (((gr_method_vec_swap_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_CONSTANT_OP(ctx, NAME) (((gr_method_vec_constant_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_OP(ctx, NAME) (((gr_method_vec_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_VEC_OP(ctx, NAME) (((gr_method_vec_vec_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_SCALAR_OP(ctx, NAME) (((gr_method_vec_scalar_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_SCALAR_VEC_OP(ctx, NAME) (((gr_method_scalar_vec_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_OP_OTHER(ctx, NAME) (((gr_method_vec_op_other *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_OTHER_OP_VEC(ctx, NAME) (((gr_method_other_op_vec *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_OP_SCALAR_OTHER(ctx, NAME) (((gr_method_vec_op_scalar_other *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_SCALAR_OTHER_OP_VEC(ctx, NAME) (((gr_method_scalar_other_op_vec *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_SCALAR_OP_SI(ctx, NAME) (((gr_method_vec_scalar_op_si *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_SCALAR_OP_UI(ctx, NAME) (((gr_method_vec_scalar_op_ui *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_SCALAR_OP_FMPZ(ctx, NAME) (((gr_method_vec_scalar_op_fmpz *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_SCALAR_OP_FMPQ(ctx, NAME) (((gr_method_vec_scalar_op_fmpq *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_PREDICATE(ctx, NAME) (((gr_method_vec_predicate *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_VEC_PREDICATE(ctx, NAME) (((gr_method_vec_vec_predicate *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_FACTOR_OP(ctx, NAME) (((gr_method_factor_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_POLY_BINARY_OP(ctx, NAME) (((gr_method_poly_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_POLY_UNARY_TRUNC_OP(ctx, NAME) (((gr_method_poly_unary_trunc_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_POLY_BINARY_BINARY_OP(ctx, NAME) (((gr_method_poly_binary_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_POLY_BINARY_TRUNC_OP(ctx, NAME) (((gr_method_poly_binary_trunc_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_CTX_OP(ctx, NAME) (((gr_method_vec_ctx_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define _GR_GET_SI_OP(ctx, NAME) (((_gr_method_get_si_op *) ctx->methods)[_GR_METHOD_ ## NAME]) #ifdef FEXPR_H #define GR_GET_FEXPR_OP(ctx, NAME) (((gr_method_get_fexpr_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_SET_FEXPR_OP(ctx, NAME) (((gr_method_set_fexpr_op *) ctx->methods)[GR_METHOD_ ## NAME]) #endif /* Wrappers to call methods. */ GR_INLINE int gr_ctx_clear(gr_ctx_t ctx) { return GR_CTX_OP(ctx, CTX_CLEAR)(ctx); } GR_INLINE int gr_ctx_write(gr_stream_t out, gr_ctx_t ctx) { return GR_CTX_STREAM(ctx, CTX_WRITE)(out, ctx); } GR_INLINE truth_t gr_ctx_is_ring(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_RING)(ctx); } GR_INLINE truth_t gr_ctx_is_commutative_ring(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_COMMUTATIVE_RING)(ctx); } GR_INLINE truth_t gr_ctx_is_integral_domain(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_INTEGRAL_DOMAIN)(ctx); } GR_INLINE truth_t gr_ctx_is_field(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_FIELD)(ctx); } GR_INLINE truth_t gr_ctx_is_zero_ring(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_ZERO_RING)(ctx); } GR_INLINE truth_t gr_ctx_is_unique_factorization_domain(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_UNIQUE_FACTORIZATION_DOMAIN)(ctx); } GR_INLINE truth_t gr_ctx_is_finite(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_FINITE)(ctx); } GR_INLINE truth_t gr_ctx_is_finite_characteristic(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_FINITE_CHARACTERISTIC)(ctx); } GR_INLINE truth_t gr_ctx_is_algebraically_closed(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_ALGEBRAICALLY_CLOSED)(ctx); } GR_INLINE truth_t gr_ctx_is_ordered_ring(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_ORDERED_RING)(ctx); } GR_INLINE truth_t gr_ctx_is_multiplicative_group(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_MULTIPLICATIVE_GROUP)(ctx); } GR_INLINE truth_t gr_ctx_is_exact(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_EXACT)(ctx); } GR_INLINE truth_t gr_ctx_is_canonical(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_CANONICAL)(ctx); } GR_INLINE truth_t gr_ctx_is_threadsafe(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_IS_THREADSAFE)(ctx); } GR_INLINE truth_t gr_ctx_has_real_prec(gr_ctx_t ctx) { return GR_CTX_PREDICATE(ctx, CTX_HAS_REAL_PREC)(ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_ctx_set_real_prec(gr_ctx_t ctx, slong prec) { return GR_CTX_SET_SI(ctx, CTX_SET_REAL_PREC)(ctx, prec); } GR_INLINE WARN_UNUSED_RESULT int gr_ctx_get_real_prec(slong * prec, gr_ctx_t ctx) { return GR_CTX_GET_SI(ctx, CTX_GET_REAL_PREC)(prec, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_ctx_set_gen_name(gr_ctx_t ctx, const char * s) { return GR_CTX_SET_STR(ctx, CTX_SET_GEN_NAME)(ctx, s); } GR_INLINE WARN_UNUSED_RESULT int gr_ctx_set_gen_names(gr_ctx_t ctx, const char ** s) { return GR_CTX_SET_STRS(ctx, CTX_SET_GEN_NAMES)(ctx, s); } GR_INLINE slong _gr_ctx_get_real_prec(gr_ctx_t ctx) { slong res = 0; GR_IGNORE(gr_ctx_get_real_prec(&res, ctx)); return res; } GR_INLINE void gr_init(gr_ptr res, gr_ctx_t ctx) { GR_INIT_CLEAR_OP(ctx, INIT)(res, ctx); } GR_INLINE void gr_clear(gr_ptr res, gr_ctx_t ctx) { GR_INIT_CLEAR_OP(ctx, CLEAR)(res, ctx); } GR_INLINE void gr_swap(gr_ptr x, gr_ptr y, gr_ctx_t ctx) { GR_SWAP_OP(ctx, SWAP)(x, y, ctx); } GR_INLINE void gr_set_shallow(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { GR_VOID_UNARY_OP(ctx, SET_SHALLOW)(res, x, ctx); } GR_INLINE void _gr_length(gr_srcptr x, gr_ctx_t ctx) { _GR_GET_SI_OP(ctx, LENGTH)(x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_randtest(gr_ptr x, flint_rand_t state, gr_ctx_t ctx) { return GR_RANDTEST(ctx, RANDTEST)(x, state, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_randtest_not_zero(gr_ptr x, flint_rand_t state, gr_ctx_t ctx) { return GR_RANDTEST(ctx, RANDTEST_NOT_ZERO)(x, state, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_randtest_small(gr_ptr x, flint_rand_t state, gr_ctx_t ctx) { return GR_RANDTEST(ctx, RANDTEST_SMALL)(x, state, ctx); } GR_INLINE /* todo: warn? */ int gr_write(gr_stream_t out, gr_srcptr x, gr_ctx_t ctx) { return GR_STREAM_IN(ctx, WRITE)(out, x, ctx); } GR_INLINE /* todo: warn? */ int gr_write_n(gr_stream_t out, gr_srcptr x, slong n, gr_ctx_t ctx) { return GR_STREAM_IN_SI(ctx, WRITE_N)(out, x, n, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_zero(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, ZERO)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_one(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, ONE)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_neg_one(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, NEG_ONE)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SET)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_si(gr_ptr res, slong x, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, SET_SI)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, SET_UI)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, SET_FMPZ)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_fmpq(gr_ptr res, const fmpq_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPQ(ctx, SET_FMPQ)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_d(gr_ptr res, double x, gr_ctx_t ctx) { return GR_UNARY_OP_D(ctx, SET_D)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_other(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { return GR_UNARY_OP_OTHER(ctx, SET_OTHER)(res, x, x_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_str(gr_ptr res, const char * x, gr_ctx_t ctx) { return GR_UNARY_OP_STR(ctx, SET_STR)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_get_si(slong * res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_SI(ctx, GET_SI)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_get_ui(ulong * res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_UI(ctx, GET_UI)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_get_fmpz(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_FMPZ(ctx, GET_FMPZ)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_get_fmpq(fmpq_t res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_FMPQ(ctx, GET_FMPQ)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_get_d(double * res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_D(ctx, GET_D)(res, x, ctx); } #define GR_FEXPR_SERIALIZE (UWORD(1) << 31) #define GR_FEXPR_COMPACT (UWORD(1) << 30) #ifdef FEXPR_H GR_INLINE WARN_UNUSED_RESULT int gr_get_fexpr(fexpr_t res, gr_srcptr x, gr_ctx_t ctx) { return GR_GET_FEXPR_OP(ctx, GET_FEXPR)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_get_fexpr_serialize(fexpr_t res, gr_srcptr x, gr_ctx_t ctx) { return GR_GET_FEXPR_OP(ctx, GET_FEXPR_SERIALIZE)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_fexpr(gr_ptr res, fexpr_vec_t inputs, gr_vec_t outputs, const fexpr_t x, gr_ctx_t ctx) { return GR_SET_FEXPR_OP(ctx, SET_FEXPR)(res, inputs, outputs, x, ctx); } #endif GR_INLINE truth_t gr_is_zero(gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_PREDICATE(ctx, IS_ZERO)(x, ctx); } GR_INLINE truth_t gr_is_one(gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_PREDICATE(ctx, IS_ONE)(x, ctx); } GR_INLINE truth_t gr_is_neg_one(gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_PREDICATE(ctx, IS_NEG_ONE)(x, ctx); } GR_INLINE truth_t gr_equal(gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_PREDICATE(ctx, EQUAL)(x, y, ctx); } GR_INLINE truth_t gr_not_equal(gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return truth_not(GR_BINARY_PREDICATE(ctx, EQUAL)(x, y, ctx)); } GR_INLINE WARN_UNUSED_RESULT int gr_neg(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, NEG)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_add(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, ADD)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_add_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, ADD_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_add_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, ADD_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_add_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, ADD_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_add_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, ADD_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_add_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, ADD_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_other_add(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { return GR_OTHER_BINARY_OP(ctx, OTHER_ADD)(res, x, x_ctx, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sub(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, SUB)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sub_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, SUB_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sub_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, SUB_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sub_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, SUB_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sub_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, SUB_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sub_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, SUB_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_other_sub(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { return GR_OTHER_BINARY_OP(ctx, OTHER_SUB)(res, x, x_ctx, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, MUL)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, MUL_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, MUL_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, MUL_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, MUL_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, MUL_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_other_mul(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { return GR_OTHER_BINARY_OP(ctx, OTHER_MUL)(res, x, x_ctx, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_addmul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, ADDMUL)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_addmul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, ADDMUL_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_addmul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, ADDMUL_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_addmul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, ADDMUL_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_addmul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, ADDMUL_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_addmul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, ADDMUL_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_submul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, SUBMUL)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_submul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, SUBMUL_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_submul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, SUBMUL_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_submul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, SUBMUL_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_submul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, SUBMUL_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_submul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, SUBMUL_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_two(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, MUL_TWO)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sqr(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SQR)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_2exp_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, MUL_2EXP_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_mul_2exp_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, MUL_2EXP_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_fmpz_2exp_fmpz(gr_ptr res, const fmpz_t x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ_FMPZ(ctx, SET_FMPZ_2EXP_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_FMPZ_FMPZ(ctx, GET_FMPZ_2EXP_FMPZ)(res1, res2, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_fmpz_10exp_fmpz(gr_ptr res, const fmpz_t x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ_FMPZ(ctx, SET_FMPZ_10EXP_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_inv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, INV)(res, x, ctx); } GR_INLINE truth_t gr_is_invertible(gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_PREDICATE(ctx, IS_INVERTIBLE)(x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_div(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, DIV)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_div_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, DIV_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_div_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, DIV_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_div_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, DIV_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_div_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, DIV_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_div_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, DIV_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_other_div(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { return GR_OTHER_BINARY_OP(ctx, OTHER_DIV)(res, x, x_ctx, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_div_nonunique(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, DIV_NONUNIQUE)(res, x, y, ctx); } GR_INLINE truth_t gr_divides(gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_PREDICATE(ctx, DIVIDES)(x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_divexact(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, DIVEXACT)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_divexact_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, DIVEXACT_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_divexact_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, DIVEXACT_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_divexact_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, DIVEXACT_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_divexact_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, DIVEXACT_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_divexact_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, DIVEXACT_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_other_divexact(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { return GR_OTHER_BINARY_OP(ctx, OTHER_DIVEXACT)(res, x, x_ctx, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_euclidean_div(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, EUCLIDEAN_DIV)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_euclidean_rem(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, EUCLIDEAN_REM)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_euclidean_divrem(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_BINARY_OP(ctx, EUCLIDEAN_DIVREM)(res1, res2, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_gcd(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, GCD)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_lcm(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, LCM)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_numerator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, NUMERATOR)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_denominator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DENOMINATOR)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_factor(gr_ptr c, gr_vec_t factors, gr_vec_t exponents, gr_srcptr x, int flags, gr_ctx_t ctx) { return GR_FACTOR_OP(ctx, FACTOR)(c, factors, exponents, x, flags, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_pow(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, POW)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_pow_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, POW_UI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_pow_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, POW_SI)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_pow_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, POW_FMPZ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_pow_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { return GR_BINARY_OP_FMPQ(ctx, POW_FMPQ)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_pow_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER(ctx, POW_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_other_pow(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { return GR_OTHER_BINARY_OP(ctx, OTHER_POW)(res, x, x_ctx, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SQRT)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_rsqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, RSQRT)(res, x, ctx); } GR_INLINE truth_t gr_is_square(gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_PREDICATE(ctx, IS_SQUARE)(x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_floor(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, FLOOR)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_ceil(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, CEIL)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_trunc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, TRUNC)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_nint(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, NINT)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_abs(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ABS)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_i(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, I)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_conj(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, CONJ)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_re(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, RE)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_im(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, IM)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_sgn(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SGN)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_csgn(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, CSGN)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_arg(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ARG)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_pos_inf(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, POS_INF)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_neg_inf(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, NEG_INF)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_uinf(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, UINF)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_undefined(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, UNDEFINED)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_unknown(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, UNKNOWN)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_cmp(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP_GET_INT(ctx, CMP)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_cmpabs(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP_GET_INT(ctx, CMPABS)(res, x, y, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_cmp_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER_GET_INT(ctx, CMP_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_cmpabs_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { return GR_BINARY_OP_OTHER_GET_INT(ctx, CMPABS_OTHER)(res, x, y, y_ctx, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_gen(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, GEN)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_gens(gr_vec_t res, gr_ctx_t ctx) { return GR_VEC_CTX_OP(ctx, GENS)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_gens_recursive(gr_vec_t res, gr_ctx_t ctx) { return GR_VEC_CTX_OP(ctx, GENS_RECURSIVE)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_ctx_fq_prime(fmpz_t res, gr_ctx_t ctx) { return GR_CONSTANT_OP_GET_FMPZ(ctx, CTX_FQ_PRIME)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_ctx_fq_degree(slong * res, gr_ctx_t ctx) { return GR_CONSTANT_OP_GET_SI(ctx, CTX_FQ_DEGREE)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_ctx_fq_order(fmpz_t res, gr_ctx_t ctx) { return GR_CONSTANT_OP_GET_FMPZ(ctx, CTX_FQ_ORDER)(res, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_fq_frobenius(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, FQ_FROBENIUS)(res, x, e, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_fq_multiplicative_order(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_FMPZ(ctx, FQ_MULTIPLICATIVE_ORDER)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_fq_norm(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_FMPZ(ctx, FQ_NORM)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_fq_trace(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP_GET_FMPZ(ctx, FQ_TRACE)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT truth_t gr_fq_is_primitive(gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_PREDICATE(ctx, FQ_IS_PRIMITIVE)(x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_fq_pth_root(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, FQ_PTH_ROOT)(res, x, ctx); } GR_INLINE WARN_UNUSED_RESULT int gr_set_interval_mid_rad(gr_ptr res, gr_srcptr m, gr_srcptr r, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, SET_INTERVAL_MID_RAD)(res, m, r, ctx); } GR_INLINE void _gr_vec_init(gr_ptr vec, slong len, gr_ctx_t ctx) { GR_VEC_INIT_CLEAR_OP(ctx, VEC_INIT)(vec, len, ctx); } GR_INLINE void _gr_vec_clear(gr_ptr vec, slong len, gr_ctx_t ctx) { GR_VEC_INIT_CLEAR_OP(ctx, VEC_CLEAR)(vec, len, ctx); } GR_INLINE void _gr_vec_swap(gr_ptr vec1, gr_ptr vec2, slong len, gr_ctx_t ctx) { GR_VEC_SWAP_OP(ctx, VEC_SWAP)(vec1, vec2, len, ctx); } /* todo: warn unused? */ int gr_ctx_print(gr_ctx_t ctx); int gr_ctx_println(gr_ctx_t ctx); int gr_print(gr_srcptr x, gr_ctx_t ctx); int gr_println(gr_srcptr x, gr_ctx_t ctx); int gr_ctx_get_str(char ** s, gr_ctx_t ctx); int gr_get_str(char ** s, gr_srcptr x, gr_ctx_t ctx); int gr_get_str_n(char ** s, gr_srcptr x, slong n, gr_ctx_t ctx); /* Macros for allocating temporary variables on the stack. */ /* todo: use vector init/clear functions when provided */ #define GR_TMP_VEC_ALLOC_MAX_STACK 1024 #define GR_TMP_ALLOC(size) (((size) <= GR_TMP_VEC_ALLOC_MAX_STACK) ? alloca(size) : flint_malloc(size)) #define GR_TMP_FREE(ptr, size) do { if ((size) > GR_TMP_VEC_ALLOC_MAX_STACK) flint_free(ptr); } while (0) #define GR_TMP_ALLOC_SMALL(size) alloca(size) #define GR_TMP_INIT_VEC(vec, len, ctx) \ do { \ gr_method_vec_init_clear_op vec_init = GR_VEC_INIT_CLEAR_OP(ctx, VEC_INIT); \ slong _gr_elem_size = (ctx)->sizeof_elem; \ (vec) = (gr_ptr) GR_TMP_ALLOC((len) * _gr_elem_size); \ vec_init((vec), (len), (ctx)); \ } while (0) #define GR_TMP_CLEAR_VEC(vec, len, ctx) \ do { \ gr_method_vec_init_clear_op vec_clear = GR_VEC_INIT_CLEAR_OP(ctx, VEC_CLEAR); \ slong _gr_elem_size = (ctx)->sizeof_elem; \ vec_clear((vec), (len), (ctx)); \ GR_TMP_FREE(vec, (len) * _gr_elem_size); \ } while (0) #define GR_TMP_INIT(x1, ctx) \ do { \ gr_method_init_clear_op init = GR_INIT_CLEAR_OP(ctx, INIT); \ slong _gr_elem_size = (ctx)->sizeof_elem; \ x1 = (gr_ptr) GR_TMP_ALLOC_SMALL(1 * _gr_elem_size); \ init(x1, (ctx)); \ } while (0) #define GR_TMP_INIT2(x1, x2, ctx) \ do { \ gr_method_init_clear_op init = GR_INIT_CLEAR_OP(ctx, INIT); \ slong _gr_elem_size = (ctx)->sizeof_elem; \ x1 = (gr_ptr) GR_TMP_ALLOC_SMALL(2 * _gr_elem_size); \ x2 = (gr_ptr) ((char *) x1 + _gr_elem_size); \ init(x1, (ctx)); \ init(x2, (ctx)); \ } while (0) #define GR_TMP_INIT3(x1, x2, x3, ctx) \ do { \ gr_method_init_clear_op init = GR_INIT_CLEAR_OP(ctx, INIT); \ slong _gr_elem_size = (ctx)->sizeof_elem; \ x1 = (gr_ptr) GR_TMP_ALLOC_SMALL(3 * _gr_elem_size); \ x2 = (gr_ptr) ((char *) x1 + _gr_elem_size); \ x3 = (gr_ptr) ((char *) x2 + _gr_elem_size); \ init(x1, (ctx)); \ init(x2, (ctx)); \ init(x3, (ctx)); \ } while (0) #define GR_TMP_INIT4(x1, x2, x3, x4, ctx) \ do { \ gr_method_init_clear_op init = GR_INIT_CLEAR_OP(ctx, INIT); \ slong _gr_elem_size = (ctx)->sizeof_elem; \ x1 = (gr_ptr) GR_TMP_ALLOC_SMALL(4 * _gr_elem_size); \ x2 = (gr_ptr) ((char *) x1 + _gr_elem_size); \ x3 = (gr_ptr) ((char *) x2 + _gr_elem_size); \ x4 = (gr_ptr) ((char *) x3 + _gr_elem_size); \ init(x1, (ctx)); \ init(x2, (ctx)); \ init(x3, (ctx)); \ init(x4, (ctx)); \ } while (0) #define GR_TMP_INIT5(x1, x2, x3, x4, x5, ctx) \ do { \ gr_method_init_clear_op init = GR_INIT_CLEAR_OP(ctx, INIT); \ slong _gr_elem_size = (ctx)->sizeof_elem; \ x1 = (gr_ptr) GR_TMP_ALLOC_SMALL(5 * _gr_elem_size); \ x2 = (gr_ptr) ((char *) x1 + _gr_elem_size); \ x3 = (gr_ptr) ((char *) x2 + _gr_elem_size); \ x4 = (gr_ptr) ((char *) x3 + _gr_elem_size); \ x5 = (gr_ptr) ((char *) x4 + _gr_elem_size); \ init(x1, (ctx)); \ init(x2, (ctx)); \ init(x3, (ctx)); \ init(x4, (ctx)); \ init(x5, (ctx)); \ } while (0) #define GR_TMP_CLEAR(x1, ctx) \ do { \ gr_method_init_clear_op clear = GR_INIT_CLEAR_OP(ctx, CLEAR); \ clear(x1, (ctx)); \ } while (0) #define GR_TMP_CLEAR2(x1, x2, ctx) \ do { \ gr_method_init_clear_op clear = GR_INIT_CLEAR_OP(ctx, CLEAR); \ clear(x1, (ctx)); \ clear(x2, (ctx)); \ } while (0) #define GR_TMP_CLEAR3(x1, x2, x3, ctx) \ do { \ gr_method_init_clear_op clear = GR_INIT_CLEAR_OP(ctx, CLEAR); \ clear(x1, (ctx)); \ clear(x2, (ctx)); \ clear(x3, (ctx)); \ } while (0) #define GR_TMP_CLEAR4(x1, x2, x3, x4, ctx) \ do { \ gr_method_init_clear_op clear = GR_INIT_CLEAR_OP(ctx, CLEAR); \ clear(x1, (ctx)); \ clear(x2, (ctx)); \ clear(x3, (ctx)); \ clear(x4, (ctx)); \ } while (0) #define GR_TMP_CLEAR5(x1, x2, x3, x4, x5, ctx) \ do { \ gr_method_init_clear_op clear = GR_INIT_CLEAR_OP(ctx, CLEAR); \ clear(x1, (ctx)); \ clear(x2, (ctx)); \ clear(x3, (ctx)); \ clear(x4, (ctx)); \ clear(x5, (ctx)); \ } while (0) GR_INLINE gr_ptr gr_heap_init(gr_ctx_t ctx) { gr_ptr ptr; ptr = (gr_ptr) flint_malloc(ctx->sizeof_elem); gr_init(ptr, ctx); return ptr; } GR_INLINE void gr_heap_clear(gr_ptr x, gr_ctx_t ctx) { gr_clear(x, ctx); flint_free(x); } GR_INLINE gr_ptr gr_heap_init_vec(slong len, gr_ctx_t ctx) { gr_ptr ptr; ptr = (gr_ptr) flint_malloc(len * ctx->sizeof_elem); _gr_vec_init(ptr, len, ctx); return ptr; } GR_INLINE void gr_heap_clear_vec(gr_ptr x, slong len, gr_ctx_t ctx) { _gr_vec_clear(x, len, ctx); flint_free(x); } truth_t gr_generic_ctx_predicate(gr_ctx_t ctx); truth_t gr_generic_ctx_predicate_true(gr_ctx_t ctx); truth_t gr_generic_ctx_predicate_false(gr_ctx_t ctx); /* Some base rings */ void gr_ctx_init_random(gr_ctx_t ctx, flint_rand_t state); void gr_ctx_init_fmpz(gr_ctx_t ctx); void gr_ctx_init_fmpq(gr_ctx_t ctx); void gr_ctx_init_fmpzi(gr_ctx_t ctx); void gr_ctx_init_fmpz_mod(gr_ctx_t ctx, const fmpz_t n); void _gr_ctx_init_fmpz_mod_from_ref(gr_ctx_t ctx, const void * fmod_ctx); void gr_ctx_fmpz_mod_set_primality(gr_ctx_t ctx, truth_t is_prime); void gr_ctx_init_nmod(gr_ctx_t ctx, ulong n); void _gr_ctx_init_nmod(gr_ctx_t ctx, void * nmod_t_ref); void gr_ctx_nmod_set_primality(gr_ctx_t ctx, truth_t is_prime); void gr_ctx_init_nmod8(gr_ctx_t ctx, unsigned char n); void gr_ctx_init_nmod32(gr_ctx_t ctx, unsigned int n); void gr_ctx_init_real_qqbar(gr_ctx_t ctx); void gr_ctx_init_complex_qqbar(gr_ctx_t ctx); void _gr_ctx_qqbar_set_limits(gr_ctx_t ctx, slong deg_limit, slong bits_limit); void gr_ctx_init_real_arb(gr_ctx_t ctx, slong prec); void gr_ctx_init_complex_acb(gr_ctx_t ctx, slong prec); void gr_ctx_init_real_float_arf(gr_ctx_t ctx, slong prec); void gr_ctx_init_complex_float_acf(gr_ctx_t ctx, slong prec); void gr_ctx_init_real_ca(gr_ctx_t ctx); void gr_ctx_init_complex_ca(gr_ctx_t ctx); void gr_ctx_init_real_algebraic_ca(gr_ctx_t ctx); void gr_ctx_init_complex_algebraic_ca(gr_ctx_t ctx); void gr_ctx_init_complex_extended_ca(gr_ctx_t ctx); void _gr_ctx_init_ca_from_ref(gr_ctx_t ctx, int which_ring, void * ca_ctx); void gr_ctx_ca_set_option(gr_ctx_t ctx, slong option, slong value); slong gr_ctx_ca_get_option(gr_ctx_t ctx, slong option); void gr_ctx_init_fq(gr_ctx_t ctx, const fmpz_t p, slong d, const char * var); void gr_ctx_init_fq_nmod(gr_ctx_t ctx, ulong p, slong d, const char * var); void gr_ctx_init_fq_zech(gr_ctx_t ctx, ulong p, slong d, const char * var); void _gr_ctx_init_fq_from_ref(gr_ctx_t ctx, const void * fq_ctx); void _gr_ctx_init_fq_nmod_from_ref(gr_ctx_t ctx, const void * fq_nmod_ctx); void _gr_ctx_init_fq_zech_from_ref(gr_ctx_t ctx, const void * fq_zech_ctx); void gr_ctx_init_fmpz_poly(gr_ctx_t ctx); void gr_ctx_init_fmpq_poly(gr_ctx_t ctx); #ifdef FMPQ_POLY_H void gr_ctx_init_nf(gr_ctx_t ctx, const fmpq_poly_t poly); void gr_ctx_init_nf_fmpz_poly(gr_ctx_t ctx, const fmpz_poly_t poly); void _gr_ctx_init_nf_from_ref(gr_ctx_t ctx, const void * nfctx); #endif /* Groups */ void gr_ctx_init_perm(gr_ctx_t ctx, ulong n); void gr_ctx_init_psl2z(gr_ctx_t ctx); int gr_ctx_init_dirichlet_group(gr_ctx_t ctx, ulong q); /* Generic polynomial ring */ typedef struct { gr_ctx_struct * base_ring; slong degree_limit; char * var; } polynomial_ctx_t; #define POLYNOMIAL_CTX(ring_ctx) ((polynomial_ctx_t *)((ring_ctx))) #define POLYNOMIAL_ELEM_CTX(ring_ctx) (POLYNOMIAL_CTX(ring_ctx)->base_ring) void gr_ctx_init_gr_poly(gr_ctx_t ctx, gr_ctx_t base_ring); /* Multivariate */ #ifdef MPOLY_H void gr_ctx_init_fmpz_mpoly(gr_ctx_t ctx, slong nvars, const ordering_t ord); void gr_ctx_init_gr_mpoly(gr_ctx_t ctx, gr_ctx_t base_ring, slong nvars, const ordering_t ord); #endif #ifdef FMPZ_MPOLY_Q_H void gr_ctx_init_fmpz_mpoly_q(gr_ctx_t ctx, slong nvars, const ordering_t ord); #endif /* Generic series */ void gr_ctx_init_gr_series(gr_ctx_t ctx, gr_ctx_t base_ring, slong prec); void gr_ctx_init_gr_series_mod(gr_ctx_t ctx, gr_ctx_t base_ring, slong mod); /* Generic vectors */ typedef struct { gr_ctx_struct * base_ring; int all_sizes; slong n; } vector_ctx_t; #define VECTOR_CTX(ring_ctx) ((vector_ctx_t *)((ring_ctx))) void gr_ctx_init_vector_gr_vec(gr_ctx_t ctx, gr_ctx_t base_ring); void gr_ctx_init_vector_space_gr_vec(gr_ctx_t ctx, gr_ctx_t base_ring, slong n); /* Generic matrix ring */ typedef struct { gr_ctx_struct * base_ring; int all_sizes; slong nrows; slong ncols; } matrix_ctx_t; #define MATRIX_CTX(ring_ctx) ((matrix_ctx_t *)((ring_ctx))) void gr_ctx_init_matrix_domain(gr_ctx_t ctx, gr_ctx_t base_ring); void gr_ctx_init_matrix_space(gr_ctx_t ctx, gr_ctx_t base_ring, slong nrows, slong ncols); GR_INLINE void gr_ctx_init_matrix_ring(gr_ctx_t ctx, gr_ctx_t base_ring, slong n) { gr_ctx_init_matrix_space(ctx, base_ring, n, n); } /* Expressions */ void gr_ctx_init_fexpr(gr_ctx_t ctx); /* Coercions */ int gr_ctx_cmp_coercion(gr_ctx_t ctx1, gr_ctx_t ctx2); /* Testing */ #define GR_TEST_VERBOSE 8 #define GR_TEST_ALWAYS_ABLE 16 /* todo: just have gr_test_structure() */ void gr_test_ring(gr_ctx_t R, slong iters, int test_flags); void gr_test_multiplicative_group(gr_ctx_t R, slong iters, int test_flags); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/gr/000077500000000000000000000000001461254215100140325ustar00rootroot00000000000000flint-3.1.3/src/gr/acb.c000066400000000000000000002134711461254215100147330ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" #include "acb.h" #include "acb_poly.h" #include "acb_mat.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #include "acb_dirichlet.h" #include "acb_modular.h" #include "acb_elliptic.h" #include "acf.h" #include "fmpzi.h" #include "qqbar.h" #include "arb_fmpz_poly.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_poly.h" typedef struct { slong prec; } gr_acb_ctx; #define ACB_CTX_PREC(ring_ctx) (((gr_acb_ctx *)((ring_ctx)))->prec) int _gr_acb_ctx_set_real_prec(gr_ctx_t ctx, slong prec) { prec = FLINT_MAX(prec, 2); prec = FLINT_MIN(prec, WORD_MAX / 8); ACB_CTX_PREC(ctx) = prec; return GR_SUCCESS; } int _gr_acb_ctx_get_real_prec(slong * res, gr_ctx_t ctx) { *res = ACB_CTX_PREC(ctx); return GR_SUCCESS; } int _gr_acb_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Complex numbers (acb, prec = "); gr_stream_write_si(out, ACB_CTX_PREC(ctx)); gr_stream_write(out, ")"); return GR_SUCCESS; } void _gr_acb_init(acb_t x, const gr_ctx_t ctx) { acb_init(x); } void _gr_acb_clear(acb_t x, const gr_ctx_t ctx) { acb_clear(x); } void _gr_acb_swap(acb_t x, acb_t y, const gr_ctx_t ctx) { acb_t t; *t = *x; *x = *y; *y = *t; } void _gr_acb_set_shallow(acb_t res, const acb_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_acb_randtest(acb_t res, flint_rand_t state, const gr_ctx_t ctx) { acb_randtest(res, state, ACB_CTX_PREC(ctx), 10); return GR_SUCCESS; } int __gr_acb_write(gr_stream_t out, const acb_t x, slong digits, int flags, const gr_ctx_t ctx) { if (arb_is_zero(acb_imagref(x))) { /* used by polynomial printing */ if (arb_is_exact(acb_realref(x))) { if (arf_is_zero(arb_midref(acb_realref(x)))) { gr_stream_write(out, "0"); return GR_SUCCESS; } else if (arf_is_one(arb_midref(acb_realref(x)))) { gr_stream_write(out, "1"); return GR_SUCCESS; } else if (arf_equal_si(arb_midref(acb_realref(x)), -1)) { gr_stream_write(out, "-1"); return GR_SUCCESS; } } gr_stream_write_free(out, arb_get_str(acb_realref(x), digits, flags)); } else if (arb_is_zero(acb_realref(x))) { gr_stream_write_free(out, arb_get_str(acb_imagref(x), digits, flags)); gr_stream_write(out, "*I"); } else { gr_stream_write(out, "("); gr_stream_write_free(out, arb_get_str(acb_realref(x), digits, flags)); if ((arb_is_exact(acb_imagref(x)) || (flags & ARB_STR_NO_RADIUS)) && arf_sgn(arb_midref(acb_imagref(x))) < 0) { arb_t t; arb_init(t); arb_neg(t, acb_imagref(x)); gr_stream_write(out, " - "); gr_stream_write_free(out, arb_get_str(t, digits, flags)); arb_clear(t); } else { gr_stream_write(out, " + "); gr_stream_write_free(out, arb_get_str(acb_imagref(x), digits, flags)); } gr_stream_write(out, "*I)"); } return GR_SUCCESS; } int _gr_acb_write(gr_stream_t out, const acb_t x, const gr_ctx_t ctx) { return __gr_acb_write(out, x, ACB_CTX_PREC(ctx) * 0.30102999566398 + 1, 0, ctx); } int _gr_acb_write_n(gr_stream_t out, gr_srcptr x, slong n, gr_ctx_t ctx) { return __gr_acb_write(out, x, FLINT_MAX(n, 1), ARB_STR_NO_RADIUS, ctx); } int _gr_acb_zero(acb_t x, const gr_ctx_t ctx) { acb_zero(x); return GR_SUCCESS; } int _gr_acb_one(acb_t x, const gr_ctx_t ctx) { acb_one(x); return GR_SUCCESS; } int _gr_acb_set_si(acb_t res, slong v, const gr_ctx_t ctx) { acb_set_si(res, v); acb_set_round(res, res, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_set_ui(acb_t res, ulong v, const gr_ctx_t ctx) { acb_set_ui(res, v); acb_set_round(res, res, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_set_fmpz(acb_t res, const fmpz_t v, const gr_ctx_t ctx) { acb_set_round_fmpz(res, v, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_set_fmpq(acb_t res, const fmpq_t v, const gr_ctx_t ctx) { acb_set_fmpq(res, v, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_set_d(acb_t res, double x, const gr_ctx_t ctx) { acb_set_d(res, x); arb_set_round(acb_realref(res), acb_realref(res), ACB_CTX_PREC(ctx)); if (!arb_is_finite(acb_realref(res))) return GR_DOMAIN; return GR_SUCCESS; } int _gr_ca_get_acb_with_prec(acb_t res, gr_srcptr x, gr_ctx_t x_ctx, slong prec); int _gr_acb_set_other(acb_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: return _gr_acb_set_fmpz(res, x, ctx); case GR_CTX_FMPQ: return _gr_acb_set_fmpq(res, x, ctx); case GR_CTX_FMPZI: arb_set_round_fmpz(acb_realref(res), fmpzi_realref((const fmpzi_struct *) x), ACB_CTX_PREC(ctx)); arb_set_round_fmpz(acb_imagref(res), fmpzi_imagref((const fmpzi_struct *) x), ACB_CTX_PREC(ctx)); return GR_SUCCESS; case GR_CTX_REAL_ALGEBRAIC_QQBAR: case GR_CTX_COMPLEX_ALGEBRAIC_QQBAR: qqbar_get_acb(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; case GR_CTX_RR_CA: case GR_CTX_REAL_ALGEBRAIC_CA: case GR_CTX_CC_CA: case GR_CTX_COMPLEX_ALGEBRAIC_CA: return _gr_ca_get_acb_with_prec(res, x, x_ctx, ACB_CTX_PREC(ctx)); case GR_CTX_REAL_FLOAT_ARF: if (arf_is_finite(x)) { arb_set_arf(acb_realref(res), x); arb_set_round(acb_realref(res), acb_realref(res), ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } else { return GR_DOMAIN; } case GR_CTX_COMPLEX_FLOAT_ACF: if (arf_is_finite(acf_realref((acf_srcptr) x)) && arf_is_finite(acf_imagref((acf_srcptr) x))) { arb_set_arf(acb_realref(res), acf_realref((acf_srcptr) x)); arb_set_arf(acb_imagref(res), acf_imagref((acf_srcptr) x)); acb_set_round(res, res, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } else { return GR_DOMAIN; } case GR_CTX_RR_ARB: arb_set_round(acb_realref(res), x, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; case GR_CTX_CC_ACB: acb_set_round(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } return gr_generic_set_other(res, x, x_ctx, ctx); } int _gr_acb_set_interval_mid_rad(acb_t res, const acb_t m, const acb_t r, const gr_ctx_t ctx) { mag_t rad1, rad2; mag_init(rad1); mag_init(rad2); arb_get_mag(rad1, acb_realref(r)); arb_get_mag(rad2, acb_imagref(r)); acb_set(res, m); arb_add_error_mag(acb_realref(res), rad1); arb_add_error_mag(acb_imagref(res), rad2); mag_clear(rad1); mag_clear(rad2); return GR_SUCCESS; } /* xxx: assumes that ctx are not read */ int _gr_arf_get_fmpz(fmpz_t res, const arf_t x, const gr_ctx_t ctx); int _gr_arf_get_si(slong * res, const arf_t x, const gr_ctx_t ctx); int _gr_arf_get_ui(ulong * res, const arf_t x, const gr_ctx_t ctx); int _gr_acb_get_fmpz(fmpz_t res, const acb_t x, const gr_ctx_t ctx) { if (!acb_is_int(x)) { if (acb_contains_int(x)) return GR_UNABLE; else return GR_DOMAIN; } return _gr_arf_get_fmpz(res, arb_midref(acb_realref(x)), NULL); } int _gr_acb_get_si(slong * res, const acb_t x, const gr_ctx_t ctx) { if (!acb_is_int(x)) { if (acb_contains_int(x)) return GR_UNABLE; else return GR_DOMAIN; } return _gr_arf_get_si(res, arb_midref(acb_realref(x)), NULL); } int _gr_acb_get_ui(ulong * res, const acb_t x, const gr_ctx_t ctx) { if (!acb_is_int(x)) { if (acb_contains_int(x)) return GR_UNABLE; else return GR_DOMAIN; } return _gr_arf_get_ui(res, arb_midref(acb_realref(x)), NULL); } int _gr_acb_get_d(double * res, const acb_t x, const gr_ctx_t ctx) { *res = arf_get_d(arb_midref(acb_realref(x)), ARF_RND_NEAR); return GR_SUCCESS; } truth_t _gr_acb_is_zero(const acb_t x, const gr_ctx_t ctx) { if (acb_is_zero(x)) return T_TRUE; if (acb_contains_zero(x)) return T_UNKNOWN; return T_FALSE; } truth_t _gr_acb_is_one(const acb_t x, const gr_ctx_t ctx) { if (acb_is_one(x)) return T_TRUE; if (arb_contains_zero(acb_imagref(x)) && arb_contains_si(acb_realref(x), 1)) return T_UNKNOWN; return T_FALSE; } truth_t _gr_acb_is_neg_one(const acb_t x, const gr_ctx_t ctx) { if (acb_equal_si(x, -1)) return T_TRUE; if (arb_contains_zero(acb_imagref(x)) && arb_contains_si(acb_realref(x), -1)) return T_UNKNOWN; return T_FALSE; } truth_t _gr_acb_equal(const acb_t x, const acb_t y, const gr_ctx_t ctx) { if (acb_is_exact(x) && acb_equal(x, y)) return T_TRUE; if (acb_overlaps(x, y)) return T_UNKNOWN; return T_FALSE; } int _gr_acb_set(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_set(res, x); return GR_SUCCESS; } int _gr_acb_neg(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_neg(res, x); return GR_SUCCESS; } int _gr_acb_add(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_add(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_add_si(acb_t res, const acb_t x, slong y, const gr_ctx_t ctx) { acb_add_si(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_add_ui(acb_t res, const acb_t x, ulong y, const gr_ctx_t ctx) { acb_add_ui(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_add_fmpz(acb_t res, const acb_t x, const fmpz_t y, const gr_ctx_t ctx) { acb_add_fmpz(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_sub(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_sub(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_sub_si(acb_t res, const acb_t x, slong y, const gr_ctx_t ctx) { acb_sub_si(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_sub_ui(acb_t res, const acb_t x, ulong y, const gr_ctx_t ctx) { acb_sub_ui(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_sub_fmpz(acb_t res, const acb_t x, const fmpz_t y, const gr_ctx_t ctx) { acb_sub_fmpz(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mul(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_mul(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mul_si(acb_t res, const acb_t x, slong y, const gr_ctx_t ctx) { acb_mul_si(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mul_ui(acb_t res, const acb_t x, ulong y, const gr_ctx_t ctx) { acb_mul_ui(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mul_fmpz(acb_t res, const acb_t x, const fmpz_t y, const gr_ctx_t ctx) { acb_mul_fmpz(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_addmul(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_addmul(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_submul(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_submul(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mul_two(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_mul_2exp_si(res, x, 1); return GR_SUCCESS; } int _gr_acb_sqr(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_sqr(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mul_2exp_si(acb_t res, const acb_t x, slong y, const gr_ctx_t ctx) { acb_mul_2exp_si(res, x, y); return GR_SUCCESS; } int _gr_acb_mul_2exp_fmpz(acb_t res, const acb_t x, const fmpz_t y, const gr_ctx_t ctx) { acb_mul_2exp_fmpz(res, x, y); return GR_SUCCESS; } int _gr_acb_set_fmpz_2exp_fmpz(acb_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { arb_set_fmpz_2exp(acb_realref(res), x, y); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, const acb_t x, const gr_ctx_t ctx) { if (!acb_is_exact(x) || !acb_is_real(x)) return GR_UNABLE; if (!acb_is_finite(x)) return GR_DOMAIN; arf_get_fmpz_2exp(res1, res2, arb_midref(acb_realref(x))); return GR_SUCCESS; } int _gr_acb_inv(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_zero(x)) { return GR_DOMAIN; } else { acb_inv(res, x, ACB_CTX_PREC(ctx)); if (acb_is_finite(res)) return GR_SUCCESS; else return GR_UNABLE; } } int _gr_acb_div(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { if (acb_is_zero(y)) { return GR_DOMAIN; } else { acb_div(res, x, y, ACB_CTX_PREC(ctx)); if (acb_is_finite(res)) return GR_SUCCESS; else return GR_UNABLE; } } int _gr_acb_div_si(acb_t res, const acb_t x, slong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { acb_div_si(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } } int _gr_acb_div_ui(acb_t res, const acb_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { acb_div_ui(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } } int _gr_acb_div_fmpz(acb_t res, const acb_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { acb_div_fmpz(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } } truth_t _gr_acb_is_invertible(const acb_t x, const gr_ctx_t ctx) { if (acb_is_zero(x)) return T_FALSE; if (acb_contains_zero(x)) return T_UNKNOWN; return T_TRUE; } int _gr_acb_pow_ui(acb_t res, const acb_t x, ulong exp, const gr_ctx_t ctx) { acb_pow_ui(res, x, exp, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_pow_si(acb_t res, const acb_t x, slong exp, const gr_ctx_t ctx) { if (exp < 0 && acb_is_zero(x)) { return GR_DOMAIN; } else if (exp < 0 && acb_contains_zero(x)) { return GR_UNABLE; } else { fmpz_t t; fmpz_init_set_si(t, exp); acb_pow_fmpz(res, x, t, ACB_CTX_PREC(ctx)); fmpz_clear(t); return GR_SUCCESS; } } int _gr_acb_pow_fmpz(acb_t res, const acb_t x, const fmpz_t exp, const gr_ctx_t ctx) { if (fmpz_sgn(exp) < 0 && acb_is_zero(x)) { return GR_DOMAIN; } else if (fmpz_sgn(exp) < 0 && acb_contains_zero(x)) { return GR_UNABLE; } else { acb_pow_fmpz(res, x, exp, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } } int _gr_acb_pow(acb_t res, const acb_t x, const acb_t exp, const gr_ctx_t ctx) { if (acb_is_int(exp)) { if (arf_sgn(arb_midref(acb_realref(exp))) < 0) { if (acb_is_zero(x)) return GR_DOMAIN; if (acb_contains_zero(x)) return GR_UNABLE; } acb_pow(res, x, exp, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (!acb_contains_zero(x) || arb_is_positive(acb_realref(exp))) { acb_pow(res, x, exp, ACB_CTX_PREC(ctx)); if (!acb_is_finite(res)) return GR_UNABLE; return GR_SUCCESS; } else if (acb_is_zero(x) && arb_is_negative(acb_realref(exp))) { return GR_DOMAIN; } else { return GR_UNABLE; } } int _gr_acb_pow_fmpq(acb_t res, const acb_t x, const fmpq_t exp, const gr_ctx_t ctx) { int status; acb_t t; acb_init(t); acb_set_fmpq(t, exp, ACB_CTX_PREC(ctx) + 20); status = _gr_acb_pow(res, x, t, ctx); acb_clear(t); return status; } truth_t _gr_acb_is_square(const acb_t x, const gr_ctx_t ctx) { return T_TRUE; } int _gr_acb_sqrt(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_sqrt(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_rsqrt(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (!acb_contains_zero(x)) { acb_rsqrt(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (acb_is_zero(x)) { return GR_DOMAIN; } else { return GR_UNABLE; } } int _gr_acb_floor(acb_t res, const acb_t x, const gr_ctx_t ctx) { arb_floor(acb_realref(res), acb_realref(x), ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_ceil(acb_t res, const acb_t x, const gr_ctx_t ctx) { arb_ceil(acb_realref(res), acb_realref(x), ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_trunc(acb_t res, const acb_t x, const gr_ctx_t ctx) { arb_trunc(acb_realref(res), acb_realref(x), ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_nint(acb_t res, const acb_t x, const gr_ctx_t ctx) { arb_zero(acb_imagref(res)); arb_nint(acb_realref(res), acb_realref(x), ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_i(acb_t res, const gr_ctx_t ctx) { acb_onei(res); return GR_SUCCESS; } int _gr_acb_abs(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_abs(acb_realref(res), x, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_conj(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_conj(res, x); return GR_SUCCESS; } int _gr_acb_re(acb_t res, const acb_t x, const gr_ctx_t ctx) { arb_set(acb_realref(res), acb_realref(x)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_im(acb_t res, const acb_t x, const gr_ctx_t ctx) { arb_set(acb_realref(res), acb_imagref(x)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } #define DEF_FUNC(fname) \ int \ _gr_acb_ ## fname(acb_t res, const acb_t x, const gr_ctx_t ctx) \ { \ acb_ ## fname(res, x, ACB_CTX_PREC(ctx)); \ return GR_SUCCESS; \ } \ #define DEF_2FUNC(fname) \ int \ _gr_acb_ ## fname(acb_t res1, acb_t res2, const acb_t x, const gr_ctx_t ctx) \ { \ acb_ ## fname(res1, res2, x, ACB_CTX_PREC(ctx)); \ return GR_SUCCESS; \ } \ #define DEF_FUNC2(fname) \ int \ _gr_acb_ ## fname(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) \ { \ acb_ ## fname(res, x, y, ACB_CTX_PREC(ctx)); \ return GR_SUCCESS; \ } \ #define DEF_FUNC_SING(fname) \ int \ _gr_acb_ ## fname(acb_t res, const acb_t x, const gr_ctx_t ctx) \ { \ acb_ ## fname(res, x, ACB_CTX_PREC(ctx)); \ return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; \ } \ #define DEF_FUNC2_SING(fname) \ int \ _gr_acb_ ## fname(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) \ { \ acb_ ## fname(res, x, y, ACB_CTX_PREC(ctx)); \ return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; \ } \ DEF_FUNC(sgn) int _gr_acb_csgn(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_csgn(acb_realref(res), x); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_arg(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_arg(acb_realref(res), x, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_pi(acb_t res, const gr_ctx_t ctx) { acb_const_pi(res, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } DEF_FUNC(exp) DEF_FUNC(expm1) DEF_FUNC(exp_pi_i) int _gr_acb_log(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_contains_zero(x)) { if (acb_is_zero(x)) return GR_DOMAIN; return GR_UNABLE; } acb_log(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_log1p(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (arb_contains_si(acb_realref(x), -1) && arb_contains_zero(acb_imagref(x))) { if (arb_equal_si(acb_realref(x), -1) && arb_is_zero(acb_imagref(x))) return GR_DOMAIN; return GR_UNABLE; } acb_log1p(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_log_pi_i(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_t t; if (acb_contains_zero(x)) { if (acb_is_zero(x)) return GR_DOMAIN; return GR_UNABLE; } acb_log(res, x, ACB_CTX_PREC(ctx)); acb_init(t); acb_const_pi(t, ACB_CTX_PREC(ctx)); acb_mul_onei(t, t); acb_div(res, res, t, ACB_CTX_PREC(ctx)); acb_clear(t); return GR_SUCCESS; } DEF_FUNC(sin) DEF_FUNC(sin_pi) DEF_FUNC(cos) DEF_FUNC(cos_pi) DEF_FUNC_SING(tan) DEF_FUNC_SING(cot) DEF_FUNC(sinc) DEF_FUNC(sinc_pi) DEF_FUNC(sinh) DEF_FUNC(cosh) DEF_FUNC_SING(tanh) DEF_FUNC_SING(coth) DEF_FUNC(asin) DEF_FUNC(acos) DEF_2FUNC(sin_cos) DEF_2FUNC(sin_cos_pi) DEF_2FUNC(sinh_cosh) int _gr_acb_atan(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (!arb_is_zero(acb_imagref(x)) && arb_contains_zero(acb_realref(x))) { if (arb_is_zero(acb_realref(x)) && (arb_is_one(acb_imagref(x)) || arb_equal_si(acb_imagref(x), -1))) return GR_DOMAIN; if (arb_contains_si(acb_imagref(x), 1) || arb_contains_si(acb_imagref(x), -1)) return GR_UNABLE; } acb_atan(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } DEF_FUNC(asinh) DEF_FUNC(acosh) DEF_FUNC_SING(atanh) int _gr_acb_lambertw(acb_t res, const acb_t x, const gr_ctx_t ctx) { fmpz_t k; fmpz_init(k); acb_lambertw(res, x, k, 0, ACB_CTX_PREC(ctx)); fmpz_clear(k); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_lambertw_fmpz(acb_t res, const acb_t x, const fmpz_t k, const gr_ctx_t ctx) { acb_lambertw(res, x, k, 0, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_erf(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_erf(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_erfc(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_erfc(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_erfi(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_erfi(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_erfinv(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_real(x)) { arb_hypgeom_erfinv(acb_realref(res), acb_realref(x), ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); } else { acb_indeterminate(res); } return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_erfcinv(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_real(x)) { arb_hypgeom_erfcinv(acb_realref(res), acb_realref(x), ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); } else { acb_indeterminate(res); } return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_fresnel_s(acb_t res, const acb_t x, int normalized, const gr_ctx_t ctx) { acb_hypgeom_fresnel(res, NULL, x, normalized, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_fresnel_c(acb_t res, const acb_t x, int normalized, const gr_ctx_t ctx) { acb_hypgeom_fresnel(NULL, res, x, normalized, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_fresnel(acb_t res1, acb_t res2, const acb_t x, int normalized, const gr_ctx_t ctx) { acb_hypgeom_fresnel(res1, res2, x, normalized, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_gamma_upper(acb_t res, const acb_t x, const acb_t y, int regularized, const gr_ctx_t ctx) { acb_hypgeom_gamma_upper(res, x, y, regularized, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_gamma_lower(acb_t res, const acb_t x, const acb_t y, int regularized, const gr_ctx_t ctx) { acb_hypgeom_gamma_lower(res, x, y, regularized, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_beta_lower(acb_t res, const acb_t x, const acb_t y, const acb_t z, int regularized, const gr_ctx_t ctx) { acb_hypgeom_beta_lower(res, x, y, z, regularized, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_exp_integral(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_expint(res, x, y, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_exp_integral_ei(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_ei(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_sin_integral(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_si(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_cos_integral(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_ci(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_sinh_integral(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_shi(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_cosh_integral(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_chi(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_log_integral(acb_t res, const acb_t x, int offset, const gr_ctx_t ctx) { acb_hypgeom_li(res, x, offset, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_dilog(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_dilog(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_gamma(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_int(x) && arb_is_nonpositive(acb_realref(x))) { return GR_DOMAIN; } else { acb_gamma(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } } int _gr_acb_gamma_fmpz(acb_t res, const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_sgn(x) > 0) { arb_gamma_fmpz(acb_realref(res), x, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_acb_gamma_fmpq(acb_t res, const fmpq_t x, const gr_ctx_t ctx) { if (!fmpz_is_one(fmpq_denref(x)) || fmpz_sgn(fmpq_numref(x)) > 0) { arb_gamma_fmpq(acb_realref(res), x, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_acb_rgamma(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_rgamma(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_lgamma(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_int(x) && arb_is_nonpositive(acb_realref(x))) { return GR_DOMAIN; } else { acb_lgamma(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } } int _gr_acb_digamma(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_int(x) && arb_is_nonpositive(acb_realref(x))) { return GR_DOMAIN; } else { acb_digamma(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } } int _gr_acb_fac_ui(acb_t res, ulong x, const gr_ctx_t ctx) { arb_fac_ui(acb_realref(res), x, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_fac_fmpz(acb_t res, const fmpz_t x, const gr_ctx_t ctx) { int status; fmpz_t t; fmpz_init(t); fmpz_add_ui(t, x, 1); status = _gr_acb_gamma_fmpz(res, t, ctx); fmpz_clear(t); return status; } int _gr_acb_rising_ui(acb_t res, const acb_t x, ulong y, const gr_ctx_t ctx) { acb_rising_ui(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_rising(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_rising(res, x, y, ACB_CTX_PREC(ctx)); if (acb_is_finite(res)) return GR_SUCCESS; else return GR_UNABLE; } int _gr_acb_barnes_g(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_int(x) && arb_is_nonpositive(acb_realref(x))) { return GR_DOMAIN; } else { acb_barnes_g(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } } int _gr_acb_log_barnes_g(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (acb_is_int(x) && arb_is_nonpositive(acb_realref(x))) { return GR_DOMAIN; } else { acb_log_barnes_g(res, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } } int _gr_acb_bessel_j(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_bessel_j(res, x, y, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_bessel_y(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_bessel_y(res, x, y, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_bessel_i(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_bessel_i(res, x, y, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_bessel_k(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_bessel_k(res, x, y, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_bessel_j_y(acb_t res1, acb_t res2, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_bessel_jy(res1, res2, x, y, ACB_CTX_PREC(ctx)); return (acb_is_finite(res1) && acb_is_finite(res2)) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_bessel_i_scaled(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_bessel_i_scaled(res, x, y, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_bessel_k_scaled(acb_t res, const acb_t x, const acb_t y, const gr_ctx_t ctx) { acb_hypgeom_bessel_k_scaled(res, x, y, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_airy(acb_t res1, acb_t res2, acb_t res3, acb_t res4, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_airy(res1, res2, res3, res4, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_airy_ai(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_airy(res, NULL, NULL, NULL, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_airy_ai_prime(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_airy(NULL, res, NULL, NULL, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_airy_bi(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_airy(NULL, NULL, res, NULL, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_airy_bi_prime(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_airy(NULL, NULL, NULL, res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_airy_ai_zero(acb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(acb_realref(res), NULL, NULL, NULL, n, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_airy_bi_zero(acb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(NULL, NULL, acb_realref(res), NULL, n, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_airy_ai_prime_zero(acb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(NULL, acb_realref(res), NULL, NULL, n, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_airy_bi_prime_zero(acb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(NULL, NULL, NULL, acb_realref(res), n, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_coulomb(acb_t res1, acb_t res2, acb_t res3, acb_t res4, const acb_t x, const acb_t y, const acb_t z, const gr_ctx_t ctx) { acb_hypgeom_coulomb(res1, res2, res3, res4, x, y, z, ACB_CTX_PREC(ctx)); return (acb_is_finite(res1) && acb_is_finite(res2) && acb_is_finite(res3) && acb_is_finite(res4)) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_coulomb_f(acb_t res, const acb_t x, const acb_t y, const acb_t z, const gr_ctx_t ctx) { acb_hypgeom_coulomb(res, NULL, NULL, NULL, x, y, z, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_coulomb_g(acb_t res, const acb_t x, const acb_t y, const acb_t z, const gr_ctx_t ctx) { acb_hypgeom_coulomb(NULL, res, NULL, NULL, x, y, z, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_coulomb_hpos(acb_t res, const acb_t x, const acb_t y, const acb_t z, const gr_ctx_t ctx) { acb_hypgeom_coulomb(NULL, NULL, res, NULL, x, y, z, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_coulomb_hneg(acb_t res, const acb_t x, const acb_t y, const acb_t z, const gr_ctx_t ctx) { acb_hypgeom_coulomb(NULL, NULL, NULL, res, x, y, z, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_chebyshev_t(acb_t res, const acb_t n, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_chebyshev_t(res, n, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_chebyshev_u(acb_t res, const acb_t n, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_chebyshev_u(res, n, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_jacobi_p(acb_t res, const acb_t n, const acb_t a, const acb_t b, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_jacobi_p(res, n, a, b, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_gegenbauer_c(acb_t res, const acb_t n, const acb_t m, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_gegenbauer_c(res, n, m, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_laguerre_l(acb_t res, const acb_t n, const acb_t m, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_laguerre_l(res, n, m, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_hermite_h(acb_t res, const acb_t n, const acb_t x, const gr_ctx_t ctx) { acb_hypgeom_hermite_h(res, n, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_legendre_p(acb_t res, const acb_t n, const acb_t m, const acb_t x, int type, const gr_ctx_t ctx) { acb_hypgeom_legendre_p(res, n, m, x, type, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_legendre_q(acb_t res, const acb_t n, const acb_t m, const acb_t x, int type, const gr_ctx_t ctx) { acb_hypgeom_legendre_q(res, n, m, x, type, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_legendre_p_root_ui(acb_t res, acb_t res2, ulong n, ulong k, const gr_ctx_t ctx) { if (k >= n) return GR_DOMAIN; arb_hypgeom_legendre_p_ui_root(acb_realref(res), res2 ? acb_realref(res2) : NULL, n, k, ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); if (res2 != NULL) arb_zero(acb_imagref(res2)); return GR_SUCCESS; } int _gr_acb_spherical_y_si(acb_t res, slong n, slong m, const acb_t theta, const acb_t phi, gr_ctx_t ctx) { acb_hypgeom_spherical_y(res, n, m, theta, phi, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_hypgeom_0f1(acb_t res, const acb_t a, const acb_t x, int flags, const gr_ctx_t ctx) { acb_hypgeom_0f1(res, a, x, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_hypgeom_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t x, int flags, const gr_ctx_t ctx) { acb_hypgeom_1f1(res, a, b, x, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_hypgeom_u(acb_t res, const acb_t a, const acb_t b, const acb_t x, int flags, const gr_ctx_t ctx) { acb_hypgeom_u(res, a, b, x, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_hypgeom_2f1(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t x, int flags, const gr_ctx_t ctx) { acb_hypgeom_2f1(res, a, b, c, x, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_hypgeom_pfq(acb_t res, const gr_vec_t a, const gr_vec_t b, const acb_t x, int flags, const gr_ctx_t ctx) { acb_hypgeom_pfq(res, a->entries, a->length, b->entries, b->length, x, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_zeta(acb_t res, const acb_t x, const gr_ctx_t ctx) { if (arb_contains_si(acb_realref(x), 1) && arb_contains_zero(acb_imagref(x))) { if (acb_is_one(x)) return GR_DOMAIN; else return GR_UNABLE; } else { acb_zeta(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } } int _gr_acb_hurwitz_zeta(acb_t res, const acb_t s, const acb_t a, const gr_ctx_t ctx) { acb_hurwitz_zeta(res, s, a, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_polylog(acb_t res, const acb_t s, const acb_t z, const gr_ctx_t ctx) { acb_polylog(res, s, z, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_polygamma(acb_t res, const acb_t s, const acb_t z, const gr_ctx_t ctx) { acb_polygamma(res, s, z, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_lerch_phi(acb_t res, const acb_t z, const acb_t s, const acb_t a, const gr_ctx_t ctx) { acb_dirichlet_lerch_phi(res, z, s, a, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_stieltjes(acb_t res, const fmpz_t n, const acb_t a, const gr_ctx_t ctx) { acb_dirichlet_stieltjes(res, n, a, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_dirichlet_eta(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_dirichlet_eta(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } /* todo int _gr_acb_dirichlet_beta(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_dirichlet_beta(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } */ int _gr_acb_riemann_xi(acb_t res, const acb_t x, const gr_ctx_t ctx) { acb_dirichlet_xi(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_zeta_zero(acb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) { return GR_UNABLE; } acb_dirichlet_zeta_zero(res, n, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_zeta_zero_vec(acb_ptr res, const fmpz_t n, slong len, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) { return GR_UNABLE; } acb_dirichlet_zeta_zeros(res, n, len, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_zeta_nzeros(acb_t res, const acb_t t, const gr_ctx_t ctx) { if (!acb_is_real(t) || !acb_is_finite(t)) return GR_UNABLE; acb_dirichlet_zeta_nzeros(acb_realref(res), acb_realref(t), ACB_CTX_PREC(ctx)); arb_zero(acb_imagref(res)); return GR_SUCCESS; } int _gr_acb_modular_j(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { acb_modular_j(res, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_modular_lambda(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { acb_modular_lambda(res, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_modular_delta(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { acb_modular_delta(res, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_dedekind_eta(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { acb_modular_eta(res, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_eisenstein_g(gr_ptr res, ulong k, gr_srcptr tau, gr_ctx_t ctx) { if (k == 0 || k % 2 == 1) return GR_DOMAIN; if (k == 2) { acb_t t; acb_init(t); acb_set_d(t, 0.5); acb_elliptic_zeta(res, t, tau, ACB_CTX_PREC(ctx)); acb_mul_2exp_si(res, res, 1); acb_clear(t); } else /* todo: better algorithm */ { acb_ptr t; t = _acb_vec_init(k / 2 - 1); acb_modular_eisenstein(t, tau, k / 2 - 1, ACB_CTX_PREC(ctx)); acb_swap((acb_ptr) res, t + (k / 2 - 2)); _acb_vec_clear(t, k / 2 - 1); } return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_eisenstein_g_vec(gr_ptr res, gr_srcptr tau, slong len, gr_ctx_t ctx) { acb_modular_eisenstein(res, tau, len, ACB_CTX_PREC(ctx)); return _arb_vec_is_finite(res, 2 * len) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_eisenstein_e(gr_ptr res, ulong k, gr_srcptr tau, gr_ctx_t ctx) { int status; status = _gr_acb_eisenstein_g(res, k, tau, ctx); if (status == GR_SUCCESS) { arb_t t; arb_init(t); arb_zeta_ui(t, k, ACB_CTX_PREC(ctx)); acb_div_arb(res, res, t, ACB_CTX_PREC(ctx)); acb_mul_2exp_si(res, res, -1); arb_clear(t); } return status; } int _gr_acb_jacobi_theta(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_modular_theta(res1, res2, res3, res4, z, tau, ACB_CTX_PREC(ctx)); return (acb_is_finite(res1) && acb_is_finite(res2) && acb_is_finite(res3) && acb_is_finite(res4)) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_jacobi_theta_1(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_modular_theta(res, t, u, v, z, tau, ACB_CTX_PREC(ctx)); acb_clear(t); acb_clear(u); acb_clear(v); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_jacobi_theta_2(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_modular_theta(t, res, u, v, z, tau, ACB_CTX_PREC(ctx)); acb_clear(t); acb_clear(u); acb_clear(v); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_jacobi_theta_3(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_modular_theta(t, u, res, v, z, tau, ACB_CTX_PREC(ctx)); acb_clear(t); acb_clear(u); acb_clear(v); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_jacobi_theta_4(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_modular_theta(t, u, v, res, z, tau, ACB_CTX_PREC(ctx)); acb_clear(t); acb_clear(u); acb_clear(v); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_k(gr_ptr res, gr_srcptr m, gr_ctx_t ctx) { acb_elliptic_k(res, m, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_e(gr_ptr res, gr_srcptr m, gr_ctx_t ctx) { acb_elliptic_e(res, m, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_pi(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_ctx_t ctx) { acb_elliptic_pi(res, n, m, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_f(gr_ptr res, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) { acb_elliptic_f(res, phi, m, pi, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_e_inc(gr_ptr res, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) { acb_elliptic_e_inc(res, phi, m, pi, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_pi_inc(gr_ptr res, gr_srcptr n, gr_srcptr phi, int pi, gr_srcptr m, gr_ctx_t ctx) { acb_elliptic_pi_inc(res, n, phi, m, pi, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_carlson_rc(gr_ptr res, gr_srcptr x, gr_srcptr y, int flags, gr_ctx_t ctx) { acb_elliptic_rf(res, x, y, y, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_carlson_rf(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) { acb_elliptic_rf(res, x, y, z, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_carlson_rg(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) { acb_elliptic_rg(res, x, y, z, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_carlson_rd(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) { acb_elliptic_rj(res, x, y, z, z, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_carlson_rj(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_srcptr w, int flags, gr_ctx_t ctx) { acb_elliptic_rj(res, x, y, z, w, flags, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_invariants(gr_ptr res1, gr_ptr res2, gr_srcptr tau, gr_ctx_t ctx) { acb_elliptic_invariants(res1, res2, tau, ACB_CTX_PREC(ctx)); return (acb_is_finite(res1) && acb_is_finite(res2)) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_elliptic_roots(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_srcptr tau, gr_ctx_t ctx) { acb_elliptic_roots(res1, res2, res3, tau, ACB_CTX_PREC(ctx)); return (acb_is_finite(res1) && acb_is_finite(res2) && acb_is_finite(res3)) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_weierstrass_p(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_elliptic_p(res, z, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_weierstrass_p_prime(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_elliptic_p_prime(res, z, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_weierstrass_p_inv(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_elliptic_inv_p(res, z, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_weierstrass_zeta(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_elliptic_zeta(res, z, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_weierstrass_sigma(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { acb_elliptic_sigma(res, z, tau, ACB_CTX_PREC(ctx)); return acb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_acb_vec_dot(acb_t res, const acb_t initial, int subtract, acb_srcptr vec1, acb_srcptr vec2, slong len, gr_ctx_t ctx) { acb_dot(res, initial, subtract, vec1, 1, vec2, 1, len, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_vec_dot_rev(acb_t res, const acb_t initial, int subtract, acb_srcptr vec1, acb_srcptr vec2, slong len, gr_ctx_t ctx) { acb_dot(res, initial, subtract, vec1, 1, vec2 + len - 1, -1, len, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_poly_mullow(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { _acb_poly_mullow(res, poly1, len1, poly2, len2, n, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_poly_taylor_shift(acb_ptr res, acb_srcptr poly, slong len, const acb_t c, gr_ctx_t ctx); /* xxx */ static int roots_accurate(acb_ptr roots, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { if (acb_rel_accuracy_bits(roots + i) < prec * 0.9) return 0; if (0) { if (mag_cmp_2exp_si(arb_radref(acb_realref(roots + i)), -prec * 0.9) > 0) return 0; if (mag_cmp_2exp_si(arb_radref(acb_imagref(roots + i)), -prec * 0.9) > 0) return 0; } } return 1; } /* hidden feature: also works with arb ctx */ int _gr_acb_poly_roots(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx) { slong prec, initial_prec, target_prec, isolated, maxiter, maxprec, deg, i; acb_ptr croots; acb_poly_t tmp; gr_ctx_t ZZ; int status = GR_UNABLE; int arb_roots; if (poly->length == 0) return GR_DOMAIN; deg = poly->length - 1; if (acb_contains_zero(((acb_srcptr) poly->coeffs) + deg)) return GR_UNABLE; gr_ctx_init_fmpz(ZZ); croots = _acb_vec_init(deg); acb_poly_init(tmp); acb_poly_fit_length(tmp, deg + 1); _acb_poly_set_length(tmp, deg + 1); target_prec = ACB_CTX_PREC(ctx); initial_prec = 32; maxprec = 2 * target_prec + 64; if (ctx->which_ring == GR_CTX_RR_ARB) arb_roots = 1; else arb_roots = 0; for (prec = initial_prec; prec <= maxprec; prec *= 2) { maxiter = FLINT_MIN(2 * deg + 32, prec); for (i = 0; i <= deg; i++) _acb_vec_set_round(tmp->coeffs, poly->coeffs, deg + 1, prec); if (prec == initial_prec) isolated = acb_poly_find_roots(croots, tmp, NULL, maxiter, prec); else isolated = acb_poly_find_roots(croots, tmp, croots, maxiter, prec); if (isolated == deg) { if (arb_roots) { status = GR_UNABLE; if (roots_accurate(croots, deg, target_prec)) { if (acb_poly_validate_real_roots(croots, tmp, prec)) status = GR_SUCCESS; } } else { status = GR_SUCCESS; if (roots_accurate(croots, deg, target_prec)) break; } } else { status = GR_UNABLE; } } if (status == GR_SUCCESS) { _acb_vec_sort_pretty(croots, deg); if (arb_roots) { gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); for (i = 0; i < deg; i++) { if (arb_contains_zero(acb_imagref(croots + i))) { fmpz one = 1; arb_set_round(acb_realref(croots + i), acb_realref(croots + i), target_prec); GR_MUST_SUCCEED(gr_vec_append(roots, acb_realref(croots + i), ctx)); GR_MUST_SUCCEED(gr_vec_append(mult, &one, ZZ)); } } } else { gr_vec_set_length(roots, deg, ctx); gr_vec_set_length(mult, deg, ZZ); for (i = 0; i < deg; i++) { acb_set_round(((acb_ptr) roots->entries) + i, croots + i, target_prec); fmpz_one(((fmpz *) mult->entries) + i); } } } acb_poly_clear(tmp); _acb_vec_clear(croots, deg); gr_ctx_clear(ZZ); return status; } int _gr_acb_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t other_ctx, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; if (other_ctx->which_ring == GR_CTX_CC_ACB) return _gr_acb_poly_roots(roots, mult, poly, flags, ctx); if (other_ctx->which_ring == GR_CTX_FMPZ) { gr_ctx_t ZZ; slong i, j, deg, deg2; acb_ptr croots; int status = GR_SUCCESS; deg = poly->length - 1; gr_ctx_init_fmpz(ZZ); gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); if (deg != 0) { fmpz_poly_factor_t fac; fmpz_poly_factor_init(fac); fmpz_poly_factor_squarefree(fac, (const fmpz_poly_struct *) poly); for (i = 0; i < fac->num; i++) { deg2 = fmpz_poly_degree(fac->p + i); croots = _acb_vec_init(deg2); arb_fmpz_poly_complex_roots(croots, fac->p + i, 0, ACB_CTX_PREC(ctx)); for (j = 0; j < deg2; j++) { fmpz m2 = fac->exp[i]; GR_MUST_SUCCEED(gr_vec_append(roots, croots + j, ctx)); GR_MUST_SUCCEED(gr_vec_append(mult, &m2, ZZ)); } _acb_vec_clear(croots, deg2); } fmpz_poly_factor_clear(fac); } gr_ctx_clear(ZZ); return status; } /* todo: first try conversion to fmpz? */ { int status; gr_poly_t tmp; gr_poly_init(tmp, ctx); status = gr_poly_set_gr_poly_other(tmp, poly, other_ctx, ctx); if (status == GR_SUCCESS) status = _gr_acb_poly_roots(roots, mult, tmp, flags, ctx); gr_poly_clear(tmp, ctx); return status; } } int _gr_acb_mat_mul(acb_mat_t res, const acb_mat_t x, const acb_mat_t y, gr_ctx_t ctx) { acb_mat_mul(res, x, y, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mat_det(acb_t res, const acb_mat_t x, gr_ctx_t ctx) { acb_mat_det(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mat_exp(acb_mat_t res, const acb_mat_t x, gr_ctx_t ctx) { if (x->r != x->c) return GR_DOMAIN; acb_mat_exp(res, x, ACB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_acb_mat_diagonalization(gr_vec_t D, acb_mat_t L, acb_mat_t R, const acb_mat_t A, int flags, gr_ctx_t ctx) { int status; slong n; acb_mat_t R_approx; n = acb_mat_nrows(A); if (n != acb_mat_ncols(A)) return GR_DOMAIN; acb_mat_init(R_approx, n, n); gr_vec_set_length(D, n, ctx); acb_mat_approx_eig_qr(D->entries, NULL, R_approx, A, NULL, 0, ACB_CTX_PREC(ctx)); status = acb_mat_eig_simple(D->entries, L, R, A, D->entries, R_approx, ACB_CTX_PREC(ctx)) ? GR_SUCCESS : GR_UNABLE; acb_mat_clear(R_approx); return status; } int _acb_methods_initialized = 0; gr_static_method_table _acb_methods; gr_method_tab_input _acb_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_acb_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_HAS_REAL_PREC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_REAL_PREC, (gr_funcptr) _gr_acb_ctx_set_real_prec}, {GR_METHOD_CTX_GET_REAL_PREC, (gr_funcptr) _gr_acb_ctx_get_real_prec}, {GR_METHOD_INIT, (gr_funcptr) _gr_acb_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_acb_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_acb_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_acb_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_acb_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_acb_write}, {GR_METHOD_WRITE_N, (gr_funcptr) _gr_acb_write_n}, {GR_METHOD_ZERO, (gr_funcptr) _gr_acb_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_acb_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_acb_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_acb_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_acb_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_acb_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_acb_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_acb_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_acb_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_acb_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_acb_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_acb_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_ring_exponents}, {GR_METHOD_SET_D, (gr_funcptr) _gr_acb_set_d}, {GR_METHOD_SET_INTERVAL_MID_RAD, (gr_funcptr) _gr_acb_set_interval_mid_rad}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_acb_get_si}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_acb_get_ui}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_acb_get_fmpz}, {GR_METHOD_GET_D, (gr_funcptr) _gr_acb_get_d}, {GR_METHOD_NEG, (gr_funcptr) _gr_acb_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_acb_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_acb_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_acb_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_acb_add_fmpz}, {GR_METHOD_SUB, (gr_funcptr) _gr_acb_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_acb_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_acb_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_acb_sub_fmpz}, {GR_METHOD_MUL, (gr_funcptr) _gr_acb_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_acb_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_acb_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_acb_mul_fmpz}, {GR_METHOD_ADDMUL, (gr_funcptr) _gr_acb_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_acb_submul}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_acb_mul_two}, {GR_METHOD_SQR, (gr_funcptr) _gr_acb_sqr}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) _gr_acb_mul_2exp_si}, {GR_METHOD_MUL_2EXP_FMPZ, (gr_funcptr) _gr_acb_mul_2exp_fmpz}, {GR_METHOD_SET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_acb_set_fmpz_2exp_fmpz}, {GR_METHOD_GET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_acb_get_fmpz_2exp_fmpz}, {GR_METHOD_DIV, (gr_funcptr) _gr_acb_div}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_acb_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_acb_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_acb_div_fmpz}, {GR_METHOD_INV, (gr_funcptr) _gr_acb_inv}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_acb_is_invertible}, {GR_METHOD_POW, (gr_funcptr) _gr_acb_pow}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_acb_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_acb_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_acb_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_acb_pow_fmpq}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_acb_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_acb_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_acb_rsqrt}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_acb_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_acb_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_acb_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_acb_nint}, {GR_METHOD_I, (gr_funcptr) _gr_acb_i}, {GR_METHOD_ABS, (gr_funcptr) _gr_acb_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_acb_conj}, {GR_METHOD_RE, (gr_funcptr) _gr_acb_re}, {GR_METHOD_IM, (gr_funcptr) _gr_acb_im}, {GR_METHOD_SGN, (gr_funcptr) _gr_acb_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_acb_csgn}, {GR_METHOD_ARG, (gr_funcptr) _gr_acb_arg}, {GR_METHOD_PI, (gr_funcptr) _gr_acb_pi}, {GR_METHOD_EXP, (gr_funcptr) _gr_acb_exp}, {GR_METHOD_EXPM1, (gr_funcptr) _gr_acb_expm1}, {GR_METHOD_EXP_PI_I, (gr_funcptr) _gr_acb_exp_pi_i}, {GR_METHOD_LOG, (gr_funcptr) _gr_acb_log}, {GR_METHOD_LOG1P, (gr_funcptr) _gr_acb_log1p}, {GR_METHOD_LOG_PI_I, (gr_funcptr) _gr_acb_log_pi_i}, {GR_METHOD_SIN, (gr_funcptr) _gr_acb_sin}, {GR_METHOD_COS, (gr_funcptr) _gr_acb_cos}, {GR_METHOD_SIN_COS, (gr_funcptr) _gr_acb_sin_cos}, {GR_METHOD_SIN_PI, (gr_funcptr) _gr_acb_sin_pi}, {GR_METHOD_COS_PI, (gr_funcptr) _gr_acb_cos_pi}, {GR_METHOD_SIN_COS_PI, (gr_funcptr) _gr_acb_sin_cos_pi}, {GR_METHOD_TAN, (gr_funcptr) _gr_acb_tan}, {GR_METHOD_COT, (gr_funcptr) _gr_acb_cot}, {GR_METHOD_SINC, (gr_funcptr) _gr_acb_sinc}, {GR_METHOD_SINC_PI, (gr_funcptr) _gr_acb_sinc_pi}, {GR_METHOD_SINH, (gr_funcptr) _gr_acb_sinh}, {GR_METHOD_COSH, (gr_funcptr) _gr_acb_cosh}, {GR_METHOD_SINH_COSH, (gr_funcptr) _gr_acb_sinh_cosh}, {GR_METHOD_TANH, (gr_funcptr) _gr_acb_tanh}, {GR_METHOD_COTH, (gr_funcptr) _gr_acb_coth}, {GR_METHOD_ASIN, (gr_funcptr) _gr_acb_asin}, {GR_METHOD_ACOS, (gr_funcptr) _gr_acb_acos}, {GR_METHOD_ATAN, (gr_funcptr) _gr_acb_atan}, {GR_METHOD_ASINH, (gr_funcptr) _gr_acb_asinh}, {GR_METHOD_ACOSH, (gr_funcptr) _gr_acb_acosh}, {GR_METHOD_ATANH, (gr_funcptr) _gr_acb_atanh}, {GR_METHOD_LAMBERTW, (gr_funcptr) _gr_acb_lambertw}, {GR_METHOD_LAMBERTW_FMPZ, (gr_funcptr) _gr_acb_lambertw_fmpz}, {GR_METHOD_FAC_UI, (gr_funcptr) _gr_acb_fac_ui}, {GR_METHOD_FAC_FMPZ, (gr_funcptr) _gr_acb_fac_fmpz}, {GR_METHOD_RISING_UI, (gr_funcptr) _gr_acb_rising_ui}, {GR_METHOD_RISING, (gr_funcptr) _gr_acb_rising}, {GR_METHOD_GAMMA, (gr_funcptr) _gr_acb_gamma}, {GR_METHOD_GAMMA_FMPZ, (gr_funcptr) _gr_acb_gamma_fmpz}, {GR_METHOD_GAMMA_FMPQ, (gr_funcptr) _gr_acb_gamma_fmpq}, {GR_METHOD_RGAMMA, (gr_funcptr) _gr_acb_rgamma}, {GR_METHOD_LGAMMA, (gr_funcptr) _gr_acb_lgamma}, {GR_METHOD_DIGAMMA, (gr_funcptr) _gr_acb_digamma}, {GR_METHOD_BARNES_G, (gr_funcptr) _gr_acb_barnes_g}, {GR_METHOD_LOG_BARNES_G, (gr_funcptr) _gr_acb_log_barnes_g}, {GR_METHOD_ERF, (gr_funcptr) _gr_acb_erf}, {GR_METHOD_ERFI, (gr_funcptr) _gr_acb_erfi}, {GR_METHOD_ERFC, (gr_funcptr) _gr_acb_erfc}, {GR_METHOD_ERFINV, (gr_funcptr) _gr_acb_erfinv}, {GR_METHOD_ERFCINV, (gr_funcptr) _gr_acb_erfcinv}, {GR_METHOD_FRESNEL_C, (gr_funcptr) _gr_acb_fresnel_c}, {GR_METHOD_FRESNEL_S, (gr_funcptr) _gr_acb_fresnel_s}, {GR_METHOD_FRESNEL, (gr_funcptr) _gr_acb_fresnel}, {GR_METHOD_GAMMA_UPPER, (gr_funcptr) _gr_acb_gamma_upper}, {GR_METHOD_GAMMA_LOWER, (gr_funcptr) _gr_acb_gamma_lower}, {GR_METHOD_BETA_LOWER, (gr_funcptr) _gr_acb_beta_lower}, {GR_METHOD_EXP_INTEGRAL, (gr_funcptr) _gr_acb_exp_integral}, {GR_METHOD_EXP_INTEGRAL_EI, (gr_funcptr) _gr_acb_exp_integral_ei}, {GR_METHOD_SIN_INTEGRAL, (gr_funcptr) _gr_acb_sin_integral}, {GR_METHOD_COS_INTEGRAL, (gr_funcptr) _gr_acb_cos_integral}, {GR_METHOD_SINH_INTEGRAL, (gr_funcptr) _gr_acb_sinh_integral}, {GR_METHOD_COSH_INTEGRAL, (gr_funcptr) _gr_acb_cosh_integral}, {GR_METHOD_LOG_INTEGRAL, (gr_funcptr) _gr_acb_log_integral}, {GR_METHOD_DILOG, (gr_funcptr) _gr_acb_dilog}, {GR_METHOD_BESSEL_J, (gr_funcptr) _gr_acb_bessel_j}, {GR_METHOD_BESSEL_Y, (gr_funcptr) _gr_acb_bessel_y}, {GR_METHOD_BESSEL_I, (gr_funcptr) _gr_acb_bessel_i}, {GR_METHOD_BESSEL_K, (gr_funcptr) _gr_acb_bessel_k}, {GR_METHOD_BESSEL_J_Y, (gr_funcptr) _gr_acb_bessel_j_y}, {GR_METHOD_BESSEL_I_SCALED, (gr_funcptr) _gr_acb_bessel_i_scaled}, {GR_METHOD_BESSEL_K_SCALED, (gr_funcptr) _gr_acb_bessel_k_scaled}, {GR_METHOD_AIRY, (gr_funcptr) _gr_acb_airy}, {GR_METHOD_AIRY_AI, (gr_funcptr) _gr_acb_airy_ai}, {GR_METHOD_AIRY_BI, (gr_funcptr) _gr_acb_airy_bi}, {GR_METHOD_AIRY_AI_PRIME, (gr_funcptr) _gr_acb_airy_ai_prime}, {GR_METHOD_AIRY_BI_PRIME, (gr_funcptr) _gr_acb_airy_bi_prime}, {GR_METHOD_AIRY_AI_ZERO, (gr_funcptr) _gr_acb_airy_ai_zero}, {GR_METHOD_AIRY_BI_ZERO, (gr_funcptr) _gr_acb_airy_bi_zero}, {GR_METHOD_AIRY_AI_PRIME_ZERO, (gr_funcptr) _gr_acb_airy_ai_prime_zero}, {GR_METHOD_AIRY_BI_PRIME_ZERO, (gr_funcptr) _gr_acb_airy_bi_prime_zero}, {GR_METHOD_COULOMB, (gr_funcptr) _gr_acb_coulomb}, {GR_METHOD_COULOMB_F, (gr_funcptr) _gr_acb_coulomb_f}, {GR_METHOD_COULOMB_G, (gr_funcptr) _gr_acb_coulomb_g}, {GR_METHOD_COULOMB_HNEG, (gr_funcptr) _gr_acb_coulomb_hneg}, {GR_METHOD_COULOMB_HPOS, (gr_funcptr) _gr_acb_coulomb_hpos}, {GR_METHOD_CHEBYSHEV_T, (gr_funcptr) _gr_acb_chebyshev_t}, {GR_METHOD_CHEBYSHEV_U, (gr_funcptr) _gr_acb_chebyshev_u}, {GR_METHOD_JACOBI_P, (gr_funcptr) _gr_acb_jacobi_p}, {GR_METHOD_GEGENBAUER_C, (gr_funcptr) _gr_acb_gegenbauer_c}, {GR_METHOD_LAGUERRE_L, (gr_funcptr) _gr_acb_laguerre_l}, {GR_METHOD_HERMITE_H, (gr_funcptr) _gr_acb_hermite_h}, {GR_METHOD_LEGENDRE_P, (gr_funcptr) _gr_acb_legendre_p}, {GR_METHOD_LEGENDRE_Q, (gr_funcptr) _gr_acb_legendre_q}, {GR_METHOD_LEGENDRE_P_ROOT_UI, (gr_funcptr) _gr_acb_legendre_p_root_ui}, {GR_METHOD_SPHERICAL_Y_SI, (gr_funcptr) _gr_acb_spherical_y_si}, {GR_METHOD_HYPGEOM_0F1, (gr_funcptr) _gr_acb_hypgeom_0f1}, {GR_METHOD_HYPGEOM_1F1, (gr_funcptr) _gr_acb_hypgeom_1f1}, {GR_METHOD_HYPGEOM_U, (gr_funcptr) _gr_acb_hypgeom_u}, {GR_METHOD_HYPGEOM_2F1, (gr_funcptr) _gr_acb_hypgeom_2f1}, {GR_METHOD_HYPGEOM_PFQ, (gr_funcptr) _gr_acb_hypgeom_pfq}, {GR_METHOD_ZETA, (gr_funcptr) _gr_acb_zeta}, {GR_METHOD_HURWITZ_ZETA, (gr_funcptr) _gr_acb_hurwitz_zeta}, {GR_METHOD_POLYLOG, (gr_funcptr) _gr_acb_polylog}, {GR_METHOD_POLYGAMMA, (gr_funcptr) _gr_acb_polygamma}, {GR_METHOD_LERCH_PHI, (gr_funcptr) _gr_acb_lerch_phi}, {GR_METHOD_STIELTJES, (gr_funcptr) _gr_acb_stieltjes}, {GR_METHOD_DIRICHLET_ETA, (gr_funcptr) _gr_acb_dirichlet_eta}, {GR_METHOD_RIEMANN_XI, (gr_funcptr) _gr_acb_riemann_xi}, {GR_METHOD_ZETA_ZERO, (gr_funcptr) _gr_acb_zeta_zero}, {GR_METHOD_ZETA_ZERO_VEC, (gr_funcptr) _gr_acb_zeta_zero_vec}, {GR_METHOD_ZETA_NZEROS, (gr_funcptr) _gr_acb_zeta_nzeros}, {GR_METHOD_MODULAR_J, (gr_funcptr) _gr_acb_modular_j}, {GR_METHOD_MODULAR_DELTA, (gr_funcptr) _gr_acb_modular_delta}, {GR_METHOD_MODULAR_LAMBDA, (gr_funcptr) _gr_acb_modular_lambda}, {GR_METHOD_DEDEKIND_ETA, (gr_funcptr) _gr_acb_dedekind_eta}, {GR_METHOD_EISENSTEIN_G, (gr_funcptr) _gr_acb_eisenstein_g}, {GR_METHOD_EISENSTEIN_E, (gr_funcptr) _gr_acb_eisenstein_e}, {GR_METHOD_EISENSTEIN_G_VEC, (gr_funcptr) _gr_acb_eisenstein_g_vec}, {GR_METHOD_ELLIPTIC_K, (gr_funcptr) _gr_acb_elliptic_k}, {GR_METHOD_ELLIPTIC_E, (gr_funcptr) _gr_acb_elliptic_e}, {GR_METHOD_ELLIPTIC_PI, (gr_funcptr) _gr_acb_elliptic_pi}, {GR_METHOD_ELLIPTIC_F, (gr_funcptr) _gr_acb_elliptic_f}, {GR_METHOD_ELLIPTIC_E_INC, (gr_funcptr) _gr_acb_elliptic_e_inc}, {GR_METHOD_ELLIPTIC_PI_INC, (gr_funcptr) _gr_acb_elliptic_pi_inc}, {GR_METHOD_CARLSON_RC, (gr_funcptr) _gr_acb_carlson_rc}, {GR_METHOD_CARLSON_RF, (gr_funcptr) _gr_acb_carlson_rf}, {GR_METHOD_CARLSON_RG, (gr_funcptr) _gr_acb_carlson_rg}, {GR_METHOD_CARLSON_RD, (gr_funcptr) _gr_acb_carlson_rd}, {GR_METHOD_CARLSON_RJ, (gr_funcptr) _gr_acb_carlson_rj}, {GR_METHOD_JACOBI_THETA, (gr_funcptr) _gr_acb_jacobi_theta}, {GR_METHOD_JACOBI_THETA_1, (gr_funcptr) _gr_acb_jacobi_theta_1}, {GR_METHOD_JACOBI_THETA_2, (gr_funcptr) _gr_acb_jacobi_theta_2}, {GR_METHOD_JACOBI_THETA_3, (gr_funcptr) _gr_acb_jacobi_theta_3}, {GR_METHOD_JACOBI_THETA_4, (gr_funcptr) _gr_acb_jacobi_theta_4}, {GR_METHOD_ELLIPTIC_INVARIANTS, (gr_funcptr) _gr_acb_elliptic_invariants}, {GR_METHOD_ELLIPTIC_ROOTS, (gr_funcptr) _gr_acb_elliptic_roots}, {GR_METHOD_WEIERSTRASS_P, (gr_funcptr) _gr_acb_weierstrass_p}, {GR_METHOD_WEIERSTRASS_P_PRIME, (gr_funcptr) _gr_acb_weierstrass_p_prime}, {GR_METHOD_WEIERSTRASS_P_INV, (gr_funcptr) _gr_acb_weierstrass_p_inv}, {GR_METHOD_WEIERSTRASS_ZETA, (gr_funcptr) _gr_acb_weierstrass_zeta}, {GR_METHOD_WEIERSTRASS_SIGMA, (gr_funcptr) _gr_acb_weierstrass_sigma}, {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_acb_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_acb_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_acb_poly_mullow}, {GR_METHOD_POLY_TAYLOR_SHIFT, (gr_funcptr) _gr_acb_poly_taylor_shift}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_acb_poly_roots}, {GR_METHOD_POLY_ROOTS_OTHER,(gr_funcptr) _gr_acb_poly_roots_other}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_acb_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) _gr_acb_mat_det}, {GR_METHOD_MAT_EXP, (gr_funcptr) _gr_acb_mat_exp}, {GR_METHOD_MAT_DIAGONALIZATION, (gr_funcptr) _gr_acb_mat_diagonalization}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_complex_acb(gr_ctx_t ctx, slong prec) { ctx->which_ring = GR_CTX_CC_ACB; ctx->sizeof_elem = sizeof(acb_struct); ctx->size_limit = WORD_MAX; ACB_CTX_PREC(ctx) = FLINT_MAX(2, FLINT_MIN(prec, WORD_MAX / 8)); ACB_CTX_PREC(ctx) = prec; ctx->methods = _acb_methods; if (!_acb_methods_initialized) { gr_method_tab_init(_acb_methods, _acb_methods_input); _acb_methods_initialized = 1; } } flint-3.1.3/src/gr/acf.c000066400000000000000000001115331461254215100147330ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" #include "acf.h" #include "acb.h" #include "arb_fmpz_poly.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_poly.h" typedef struct { slong prec; arf_rnd_t rnd; } gr_acf_ctx; #define ACF_CTX_PREC(ring_ctx) (((gr_acf_ctx *)((ring_ctx)))->prec) #define ACF_CTX_RND(ring_ctx) (((gr_acf_ctx *)((ring_ctx)))->rnd) int _gr_acf_ctx_set_real_prec(gr_ctx_t ctx, slong prec) { prec = FLINT_MAX(prec, 2); prec = FLINT_MIN(prec, WORD_MAX / 8); ACF_CTX_PREC(ctx) = prec; return GR_SUCCESS; } int _gr_acf_ctx_get_real_prec(slong * res, gr_ctx_t ctx) { *res = ACF_CTX_PREC(ctx); return GR_SUCCESS; } int _gr_acf_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Complex floating-point numbers (acf, prec = "); gr_stream_write_si(out, ACF_CTX_PREC(ctx)); gr_stream_write(out, ")"); return GR_SUCCESS; } void _gr_acf_init(acf_t x, const gr_ctx_t ctx) { acf_init(x); } void _gr_acf_clear(acf_t x, const gr_ctx_t ctx) { acf_clear(x); } void _gr_acf_swap(acf_t x, acf_t y, const gr_ctx_t ctx) { acf_t t; *t = *x; *x = *y; *y = *t; } void _gr_acf_set_shallow(acf_t res, const acf_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_acf_randtest(acf_t res, flint_rand_t state, const gr_ctx_t ctx) { arf_randtest(acf_realref(res), state, ACF_CTX_PREC(ctx), 10); arf_randtest(acf_imagref(res), state, ACF_CTX_PREC(ctx), 10); return GR_SUCCESS; } /* todo */ int _gr_acf_write(gr_stream_t out, const acf_t x, const gr_ctx_t ctx) { slong digits = ACF_CTX_PREC(ctx) * 0.30102999566398 + 1; if (arf_is_zero(acf_imagref(x))) { gr_stream_write_free(out, arf_get_str(acf_realref(x), digits)); } else if (arf_is_zero(acf_realref(x))) { gr_stream_write_free(out, arf_get_str(acf_imagref(x), digits)); gr_stream_write(out, "*I"); } else { gr_stream_write(out, "("); gr_stream_write_free(out, arf_get_str(acf_realref(x), digits)); if (arf_sgn(acf_imagref(x)) < 0) { arf_t t; arf_init_neg_shallow(t, acf_imagref(x)); gr_stream_write(out, " - "); gr_stream_write_free(out, arf_get_str(t, digits)); } else { gr_stream_write(out, " + "); gr_stream_write_free(out, arf_get_str(acf_imagref(x), digits)); } gr_stream_write(out, "*I)"); } return GR_SUCCESS; } int _gr_acf_zero(acf_t x, const gr_ctx_t ctx) { arf_zero(acf_realref(x)); arf_zero(acf_imagref(x)); return GR_SUCCESS; } int _gr_acf_one(acf_t x, const gr_ctx_t ctx) { arf_one(acf_realref(x)); arf_zero(acf_imagref(x)); return GR_SUCCESS; } int _gr_acf_set_si(acf_t res, slong v, const gr_ctx_t ctx) { arf_set_round_si(acf_realref(res), v, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_set_ui(acf_t res, ulong v, const gr_ctx_t ctx) { arf_set_round_ui(acf_realref(res), v, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_set_fmpz(acf_t res, const fmpz_t v, const gr_ctx_t ctx) { arf_set_round_fmpz(acf_realref(res), v, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_set_fmpq(acf_t res, const fmpq_t v, const gr_ctx_t ctx) { arf_set_fmpq(acf_realref(res), v, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_set_d(acf_t res, double x, const gr_ctx_t ctx) { arf_set_d(acf_realref(res), x); arf_zero(acf_imagref(res)); return GR_SUCCESS; } /* todo: set_round? */ int _gr_acf_set(acf_t res, const acf_t x, const gr_ctx_t ctx) { acf_set(res, x); return GR_SUCCESS; } /* todo int _gr_acf_set_str(acf_t res, const char * x, const gr_ctx_t ctx) { } */ int _gr_acf_set_other(acf_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: return _gr_acf_set_fmpz(res, x, ctx); case GR_CTX_FMPQ: return _gr_acf_set_fmpq(res, x, ctx); case GR_CTX_REAL_FLOAT_ARF: arf_set_round(acf_realref(res), x, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_zero(acf_imagref(res)); return GR_SUCCESS; case GR_CTX_COMPLEX_FLOAT_ACF: return _gr_acf_set(res, x, ctx); case GR_CTX_RR_ARB: arf_set_round(acf_realref(res), arb_midref((arb_srcptr) x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_zero(acf_imagref(res)); return GR_SUCCESS; case GR_CTX_CC_ACB: arf_set_round(acf_realref(res), arb_midref(acb_realref((acb_srcptr) x)), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_imagref(res), arb_midref(acb_imagref((acb_srcptr) x)), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; default: { gr_ctx_t cctx; acb_t z; int status; gr_ctx_init_complex_acb(cctx, ACF_CTX_PREC(ctx) + 20); acb_init(z); status = gr_set_other(z, x, x_ctx, cctx); if (status == GR_SUCCESS) { arf_set_round(acf_realref(res), arb_midref(acb_realref(z)), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_imagref(res), arb_midref(acb_imagref(z)), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); } acb_clear(z); gr_ctx_clear(cctx); return status; } } } int _gr_acf_get_fmpz(fmpz_t res, const acf_t x, const gr_ctx_t ctx) { if (!arf_is_zero(acf_imagref(x))) return GR_DOMAIN; if (!arf_is_int(acf_realref(x))) return GR_DOMAIN; /* todo: detect mpz overflow */ if (arf_cmpabs_2exp_si(acf_realref(x), WORD_MAX) >= 0) return GR_UNABLE; arf_get_fmpz(res, acf_realref(x), ARF_RND_DOWN); return GR_SUCCESS; } int _gr_acf_get_si(slong * res, const acf_t x, const gr_ctx_t ctx) { fmpz_t t; if (!arf_is_zero(acf_imagref(x))) return GR_DOMAIN; if (!arf_is_int(acf_realref(x))) return GR_DOMAIN; if (arf_cmp_si(acf_realref(x), WORD_MIN) < 0 || arf_cmp_si(acf_realref(x), WORD_MAX) > 0) return GR_DOMAIN; fmpz_init(t); arf_get_fmpz(t, acf_realref(x), ARF_RND_DOWN); *res = fmpz_get_si(t); fmpz_clear(t); return GR_SUCCESS; } int _gr_acf_get_ui(ulong * res, const acf_t x, const gr_ctx_t ctx) { fmpz_t t; if (!arf_is_zero(acf_imagref(x))) return GR_DOMAIN; if (!arf_is_int(acf_realref(x))) return GR_DOMAIN; if (arf_sgn(acf_realref(x)) < 0 || arf_cmp_ui(acf_realref(x), UWORD_MAX) > 0) return GR_DOMAIN; fmpz_init(t); arf_get_fmpz(t, acf_realref(x), ARF_RND_DOWN); *res = fmpz_get_ui(t); fmpz_clear(t); return GR_SUCCESS; } int _gr_acf_get_d(double * res, const acf_t x, const gr_ctx_t ctx) { if (!arf_is_zero(acf_imagref(x))) return GR_DOMAIN; *res = arf_get_d(acf_realref(x), ACF_CTX_RND(ctx)); return GR_SUCCESS; } truth_t _gr_acf_is_zero(const acf_t x, const gr_ctx_t ctx) { return (arf_is_zero(acf_realref(x)) && arf_is_zero(acf_imagref(x))) ? T_TRUE : T_FALSE; } truth_t _gr_acf_is_one(const acf_t x, const gr_ctx_t ctx) { return (arf_is_one(acf_realref(x)) && arf_is_zero(acf_imagref(x))) ? T_TRUE : T_FALSE; } truth_t _gr_acf_is_neg_one(const acf_t x, const gr_ctx_t ctx) { return (arf_equal_si(acf_realref(x), -1) && arf_is_zero(acf_imagref(x))) ? T_TRUE : T_FALSE; } truth_t _gr_acf_equal(const acf_t x, const acf_t y, const gr_ctx_t ctx) { if (arf_is_nan(acf_realref(x)) || arf_is_nan(acf_imagref(x)) || arf_is_nan(acf_realref(y)) || arf_is_nan(acf_imagref(y))) return T_FALSE; return acf_equal(x, y) ? T_TRUE : T_FALSE; } /* todo: neg_round? */ int _gr_acf_neg(acf_t res, const acf_t x, const gr_ctx_t ctx) { arf_neg(acf_realref(res), acf_realref(x)); arf_neg(acf_imagref(res), acf_imagref(x)); return GR_SUCCESS; } int _gr_acf_add(acf_t res, const acf_t x, const acf_t y, const gr_ctx_t ctx) { acf_add(res, x, y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_add_si(acf_t res, const acf_t x, slong y, const gr_ctx_t ctx) { arf_add_si(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_realref(res), acf_realref(x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_add_ui(acf_t res, const acf_t x, ulong y, const gr_ctx_t ctx) { arf_add_ui(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_realref(res), acf_realref(x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_add_fmpz(acf_t res, const acf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_add_fmpz(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_realref(res), acf_realref(x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_sub(acf_t res, const acf_t x, const acf_t y, const gr_ctx_t ctx) { acf_sub(res, x, y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_sub_si(acf_t res, const acf_t x, slong y, const gr_ctx_t ctx) { arf_sub_si(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_realref(res), acf_realref(x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_sub_ui(acf_t res, const acf_t x, ulong y, const gr_ctx_t ctx) { arf_sub_ui(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_realref(res), acf_realref(x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_sub_fmpz(acf_t res, const acf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_sub_fmpz(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_set_round(acf_realref(res), acf_realref(x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_mul(acf_t res, const acf_t x, const acf_t y, const gr_ctx_t ctx) { acf_mul(res, x, y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_mul_si(acf_t res, const acf_t x, slong y, const gr_ctx_t ctx) { arf_mul_si(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_mul_si(acf_imagref(res), acf_imagref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_mul_ui(acf_t res, const acf_t x, ulong y, const gr_ctx_t ctx) { arf_mul_ui(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_mul_ui(acf_imagref(res), acf_imagref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_mul_fmpz(acf_t res, const acf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_mul_fmpz(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_mul_fmpz(acf_imagref(res), acf_imagref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_mul_two(acf_t res, const acf_t x, const gr_ctx_t ctx) { arf_mul_2exp_si(acf_realref(res), acf_realref(x), 1); arf_mul_2exp_si(acf_imagref(res), acf_imagref(x), 1); return GR_SUCCESS; } int _gr_acf_sqr(acf_t res, const acf_t x, const gr_ctx_t ctx) { acf_mul(res, x, x, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_mul_2exp_si(acf_t res, const acf_t x, slong y, const gr_ctx_t ctx) { arf_mul_2exp_si(acf_realref(res), acf_realref(x), y); arf_mul_2exp_si(acf_imagref(res), acf_imagref(x), y); return GR_SUCCESS; } int _gr_acf_mul_2exp_fmpz(acf_t res, const acf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_mul_2exp_fmpz(acf_realref(res), acf_realref(x), y); arf_mul_2exp_fmpz(acf_imagref(res), acf_imagref(x), y); return GR_SUCCESS; } int _gr_acf_set_fmpz_2exp_fmpz(acf_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_set_fmpz_2exp(acf_realref(res), x, y); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, const acf_t x, const gr_ctx_t ctx) { if (!arf_is_zero(acf_imagref(x)) || !arf_is_finite(acf_realref(x))) return GR_DOMAIN; arf_get_fmpz_2exp(res1, res2, acf_realref(x)); return GR_SUCCESS; } int _gr_acf_inv(acf_t res, const acf_t x, const gr_ctx_t ctx) { acf_approx_inv(res, x, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_div(acf_t res, const acf_t x, const acf_t y, const gr_ctx_t ctx) { acf_approx_div(res, x, y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_div_si(acf_t res, const acf_t x, slong y, const gr_ctx_t ctx) { arf_div_si(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_div_si(acf_imagref(res), acf_imagref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_div_ui(acf_t res, const acf_t x, ulong y, const gr_ctx_t ctx) { arf_div_ui(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_div_ui(acf_imagref(res), acf_imagref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_div_fmpz(acf_t res, const acf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_div_fmpz(acf_realref(res), acf_realref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_div_fmpz(acf_imagref(res), acf_imagref(x), y, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_sqrt(acf_t res, const acf_t x, const gr_ctx_t ctx) { acf_approx_sqrt(res, x, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_pos_inf(acf_t res, const gr_ctx_t ctx) { arf_pos_inf(acf_realref(res)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_neg_inf(acf_t res, const gr_ctx_t ctx) { arf_neg_inf(acf_realref(res)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_nan(acf_t res, const gr_ctx_t ctx) { arf_nan(acf_realref(res)); arf_nan(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_abs(acf_t res, const acf_t x, const gr_ctx_t ctx) { if (arf_is_zero(acf_imagref(x))) { arf_abs(acf_realref(res), acf_realref(x)); } else if (arf_is_zero(acf_realref(x))) { arf_abs(acf_realref(res), acf_imagref(x)); } else { arf_sosq(acf_realref(res), acf_realref(x), acf_imagref(x), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_sqrt(acf_realref(res), acf_realref(res), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); } arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_conj(acf_t res, const acf_t x, const gr_ctx_t ctx) { arf_set(acf_realref(res), acf_realref(x)); arf_neg(acf_imagref(res), acf_imagref(x)); return GR_SUCCESS; } int _gr_acf_re(acf_t res, const acf_t x, const gr_ctx_t ctx) { arf_set(acf_realref(res), acf_realref(x)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_im(acf_t res, const acf_t x, const gr_ctx_t ctx) { arf_set(acf_realref(res), acf_imagref(x)); arf_zero(acf_imagref(res)); return GR_SUCCESS; } /* int _gr_acf_sgn(acf_t res, const acf_t x, const gr_ctx_t ctx) { return GR_SUCCESS; } int _gr_acf_csgn(acf_t res, const acf_t x, const gr_ctx_t ctx) { } int _gr_acf_rsqrt(acf_t res, const acf_t x, const gr_ctx_t ctx) { } int _gr_acf_floor(acf_t res, const acf_t x, const gr_ctx_t ctx) { } int _gr_acf_ceil(acf_t res, const acf_t x, const gr_ctx_t ctx) { } int _gr_acf_trunc(acf_t res, const acf_t x, const gr_ctx_t ctx) { } int _gr_acf_nint(acf_t res, const acf_t x, const gr_ctx_t ctx) { } */ /* todo: handling nan */ int _gr_acf_cmp(int * res, const acf_t x, const acf_t y, const gr_ctx_t ctx) { if (!arf_is_zero(acf_imagref(x)) || !arf_is_zero(acf_imagref(y))) return GR_DOMAIN; *res = arf_cmp(acf_realref(x), acf_realref(y)); return GR_SUCCESS; } int _gr_acf_cmpabs(int * res, const acf_t x, const acf_t y, const gr_ctx_t ctx) { if (!arf_is_zero(acf_imagref(x)) || !arf_is_zero(acf_imagref(y))) return GR_UNABLE; *res = arf_cmp(acf_realref(x), acf_realref(y)); return GR_SUCCESS; } #define ACF_FUNC_VIA_ACB(res, acb_func, x) \ acb_t r, t; \ slong prec, wp, extra; \ int status = GR_SUCCESS; \ prec = ACF_CTX_PREC(ctx); \ acb_init(r); \ *arb_midref(acb_realref(t)) = *acf_realref(x); \ *arb_midref(acb_imagref(t)) = *acf_imagref(x); \ mag_init(arb_radref(acb_realref(t))); \ mag_init(arb_radref(acb_imagref(t))); \ for (extra = 10 + prec * 0.01; ; extra += FLINT_MAX(extra, 32)) \ { \ wp = prec + extra; \ if (wp > 10 * prec + 1000) \ { \ status = GR_UNABLE; \ arf_nan(acf_realref(res)); \ arf_nan(acf_imagref(res)); \ break; \ } \ acb_func(r, t, wp); \ if (acb_rel_accuracy_bits(r) >= prec) \ { \ arf_set_round(acf_realref(res), arb_midref(acb_realref(r)), prec, ACF_CTX_RND(ctx)); \ arf_set_round(acf_imagref(res), arb_midref(acb_imagref(r)), prec, ACF_CTX_RND(ctx)); \ break; \ } \ } \ acb_clear(r); \ return status; \ #define ACF_FUNC2_VIA_ACB(res, acb_func, x, y) \ acb_t r, t, u; \ slong prec, wp, extra; \ int status = GR_SUCCESS; \ prec = ACF_CTX_PREC(ctx); \ acb_init(r); \ *arb_midref(acb_realref(t)) = *acf_realref(x); \ *arb_midref(acb_imagref(t)) = *acf_imagref(x); \ mag_init(arb_radref(acb_realref(t))); \ mag_init(arb_radref(acb_imagref(t))); \ *arb_midref(acb_realref(u)) = *acf_realref(y); \ *arb_midref(acb_imagref(u)) = *acf_imagref(y); \ mag_init(arb_radref(acb_realref(u))); \ mag_init(arb_radref(acb_imagref(u))); \ for (extra = 10 + prec * 0.01; ; extra += FLINT_MAX(extra, 32)) \ { \ wp = prec + extra; \ if (wp > 10 * prec + 1000) \ { \ status = GR_UNABLE; \ arf_nan(acf_realref(res)); \ arf_nan(acf_imagref(res)); \ break; \ } \ acb_func(r, t, u, wp); \ if (acb_rel_accuracy_bits(r) >= prec) \ { \ arf_set_round(acf_realref(res), arb_midref(acb_realref(r)), prec, ACF_CTX_RND(ctx)); \ arf_set_round(acf_imagref(res), arb_midref(acb_imagref(r)), prec, ACF_CTX_RND(ctx)); \ break; \ } \ } \ acb_clear(r); \ return status; \ /* todo: lots of special cases */ int _gr_acf_pow(acf_t res, const acf_t x, const acf_t y, const gr_ctx_t ctx) { ACF_FUNC2_VIA_ACB(res, acb_pow, x, y) } int _gr_acf_i(acf_t res, const gr_ctx_t ctx) { arf_zero(acf_realref(res)); arf_one(acf_imagref(res)); return GR_SUCCESS; } int _gr_acf_pi(acf_t res, const gr_ctx_t ctx) { arb_t t; arb_init(t); arb_const_pi(t, ACF_CTX_PREC(ctx) + 30); arf_set_round(acf_realref(res), arb_midref(t), ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); arf_zero(acf_imagref(res)); arb_clear(t); return GR_SUCCESS; } int _gr_acf_exp(acf_t res, const acf_t x, const gr_ctx_t ctx) { ACF_FUNC_VIA_ACB(res, acb_exp, x) } int _gr_acf_expm1(acf_t res, const acf_t x, const gr_ctx_t ctx) { ACF_FUNC_VIA_ACB(res, acb_expm1, x) } int _gr_acf_log(acf_t res, const acf_t x, const gr_ctx_t ctx) { ACF_FUNC_VIA_ACB(res, acb_log, x) } int _gr_acf_log1p(acf_t res, const acf_t x, const gr_ctx_t ctx) { ACF_FUNC_VIA_ACB(res, acb_log1p, x) } int _gr_acf_sin(acf_t res, const acf_t x, const gr_ctx_t ctx) { ACF_FUNC_VIA_ACB(res, acb_sin, x) } int _gr_acf_cos(acf_t res, const acf_t x, const gr_ctx_t ctx) { ACF_FUNC_VIA_ACB(res, acb_cos, x) } int _gr_acf_vec_dot(acf_t res, const acf_t initial, int subtract, acf_srcptr vec1, acf_srcptr vec2, slong len, gr_ctx_t ctx) { acf_approx_dot(res, initial, subtract, vec1, 1, vec2, 1, len, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_acf_vec_dot_rev(acf_t res, const acf_t initial, int subtract, acf_srcptr vec1, acf_srcptr vec2, slong len, gr_ctx_t ctx) { acf_approx_dot(res, initial, subtract, vec1, 1, vec2 + len - 1, -1, len, ACF_CTX_PREC(ctx), ACF_CTX_RND(ctx)); return GR_SUCCESS; } #include "gr_poly.h" #include "acb_poly.h" /* todo: test */ int _gr_acf_poly_mullow(acf_ptr res, acf_srcptr poly1, slong len1, acf_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); /* todo: tuning */ if (len1 <= 10 || len2 <= 10) { return _gr_poly_mullow_generic(res, poly1, len1, poly2, len2, n, ctx); } else { acb_ptr tmp, t1, t2, t3; slong i; int squaring = (poly1 == poly2 && len1 == len2); if (!squaring) { tmp = flint_malloc(sizeof(acb_struct) * (len1 + len2 + n)); t1 = tmp; t2 = t1 + len1; t3 = t2 + len2; } else { tmp = flint_malloc(sizeof(acb_struct) * (len1 + n)); t1 = tmp; t2 = t1; t3 = t2 + len2; } for (i = 0; i < len1; i++) { *arb_midref(acb_realref(t1 + i)) = *acf_realref(poly1 + i); *arb_midref(acb_imagref(t1 + i)) = *acf_imagref(poly1 + i); mag_init(arb_radref(acb_realref(t1 + i))); mag_init(arb_radref(acb_imagref(t1 + i))); } if (!squaring) { for (i = 0; i < len2; i++) { *arb_midref(acb_realref(t2 + i)) = *acf_realref(poly2 + i); *arb_midref(acb_imagref(t2 + i)) = *acf_imagref(poly2 + i); mag_init(arb_radref(acb_realref(t2 + i))); mag_init(arb_radref(acb_imagref(t2 + i))); } } for (i = 0; i < n; i++) { *arb_midref(acb_realref(t3 + i)) = *acf_realref(res + i); *arb_midref(acb_imagref(t3 + i)) = *acf_imagref(res + i); mag_init(arb_radref(acb_realref(t3 + i))); mag_init(arb_radref(acb_imagref(t3 + i))); } _acb_poly_mullow(t3, t1, len1, t2, len2, n, ACF_CTX_PREC(ctx)); for (i = 0; i < n; i++) { *acf_realref(res + i) = *arb_midref(acb_realref(t3 + i)); *acf_imagref(res + i) = *arb_midref(acb_imagref(t3 + i)); mag_clear(arb_radref(acb_realref(t3 + i))); mag_clear(arb_radref(acb_imagref(t3 + i))); } flint_free(tmp); return GR_SUCCESS; } } int _gr_acf_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t other_ctx, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; if (other_ctx->which_ring == GR_CTX_FMPZ) { gr_ctx_t ZZ; slong i, j, deg, deg2; acb_ptr croots; int status = GR_SUCCESS; deg = poly->length - 1; gr_ctx_init_fmpz(ZZ); gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); if (deg != 0) { fmpz_poly_factor_t fac; fmpz_poly_factor_init(fac); fmpz_poly_factor_squarefree(fac, (const fmpz_poly_struct *) poly); for (i = 0; i < fac->num; i++) { deg2 = fmpz_poly_degree(fac->p + i); croots = _acb_vec_init(deg2); arb_fmpz_poly_complex_roots(croots, fac->p + i, 0, ACF_CTX_PREC(ctx)); for (j = 0; j < deg2; j++) { acf_t t; fmpz m2 = fac->exp[i]; *acf_realref(t) = *arb_midref(acb_realref(croots + j)); *acf_imagref(t) = *arb_midref(acb_imagref(croots + j)); GR_MUST_SUCCEED(gr_vec_append(roots, t, ctx)); GR_MUST_SUCCEED(gr_vec_append(mult, &m2, ZZ)); } _acb_vec_clear(croots, deg2); } fmpz_poly_factor_clear(fac); } gr_ctx_clear(ZZ); return status; } return GR_UNABLE; } #include "gr_mat.h" #include "acb_mat.h" /* todo: test */ int _gr_acf_mat_mul(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong prec; slong cutoff; prec = ACF_CTX_PREC(ctx); /* todo: detect small-integer matrices */ if (prec <= 2 * FLINT_BITS) cutoff = 120; else if (prec <= 16 * FLINT_BITS) cutoff = 60; else cutoff = 40; if (A->r <= cutoff || A->c <= cutoff || B->c <= cutoff) { return gr_mat_mul_classical(C, A, B, ctx); } else { /* todo: direct algorithm, avoiding copies */ acb_mat_t RC, RB, RA; slong i, j; acf_t zero; acb_mat_init(RA, A->r, A->c); acb_mat_init(RB, B->r, B->c); acb_mat_init(RC, C->r, C->c); acf_init(zero); for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { *arb_midref(acb_realref(acb_mat_entry(RA, i, j))) = *acf_realref(((acf_srcptr) A->rows[i]) + j); *arb_midref(acb_imagref(acb_mat_entry(RA, i, j))) = *acf_imagref(((acf_srcptr) A->rows[i]) + j); } } for (i = 0; i < B->r; i++) { for (j = 0; j < B->c; j++) { *arb_midref(acb_realref(acb_mat_entry(RB, i, j))) = *acf_realref(((acf_srcptr) B->rows[i]) + j); *arb_midref(acb_imagref(acb_mat_entry(RB, i, j))) = *acf_imagref(((acf_srcptr) B->rows[i]) + j); } } acb_mat_approx_mul(RC, RA, RB, prec); for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { *arb_midref(acb_realref(acb_mat_entry(RA, i, j))) = *acf_realref(zero); *arb_midref(acb_imagref(acb_mat_entry(RA, i, j))) = *acf_imagref(zero); } } for (i = 0; i < B->r; i++) { for (j = 0; j < B->c; j++) { *arb_midref(acb_realref(acb_mat_entry(RB, i, j))) = *acf_realref(zero); *arb_midref(acb_imagref(acb_mat_entry(RB, i, j))) = *acf_imagref(zero); } } for (i = 0; i < C->r; i++) { for (j = 0; j < C->c; j++) { arf_swap(acf_realref(((acf_ptr) C->rows[i]) + j), arb_midref(acb_realref(acb_mat_entry(RC, i, j)))); arf_swap(acf_imagref(((acf_ptr) C->rows[i]) + j), arb_midref(acb_imagref(acb_mat_entry(RC, i, j)))); } } acb_mat_clear(RA); acb_mat_clear(RB); acb_mat_clear(RC); return GR_SUCCESS; } } /* todo: port the qr algorithm to generics; test */ int _gr_acf_mat_diagonalization(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, int flags, gr_ctx_t ctx) { int status; slong n, i, j; acb_mat_t A_acb, /* L_acb, */ R_acb; acb_ptr D_acb; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) return GR_DOMAIN; acb_mat_init(A_acb, n, n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { arf_set(arb_midref(acb_realref(acb_mat_entry(A_acb, i, j))), acf_realref(((acf_srcptr) A->rows[i]) + j)); arf_set(arb_midref(acb_imagref(acb_mat_entry(A_acb, i, j))), acf_imagref(((acf_srcptr) A->rows[i]) + j)); } } acb_mat_init(R_acb, n, n); D_acb = _acb_vec_init(n); /* if (L != NULL) acb_mat_init(L_acb, n, n); */ gr_vec_set_length(D, n, ctx); status = acb_mat_approx_eig_qr(D_acb, /* L ? L_acb : */ NULL, R_acb, A_acb, NULL, 0, ACF_CTX_PREC(ctx)) ? GR_SUCCESS : GR_UNABLE; if (status == GR_SUCCESS) { if (R != NULL) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { arf_set(acf_realref(((acf_ptr) R->rows[i]) + j), arb_midref(acb_realref(acb_mat_entry(R_acb, i, j)))); arf_set(acf_imagref(((acf_ptr) R->rows[i]) + j), arb_midref(acb_imagref(acb_mat_entry(R_acb, i, j)))); } } } /* todo: acb_mat_approx_eig_qr gives us the eigenvectors directly, but they are not scaled to give LR = 1. */ /* if (L != NULL) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { arf_set(acf_realref(((acf_ptr) L->rows[i]) + j), arb_midref(acb_realref(acb_mat_entry(L_acb, i, j)))); arf_set(acf_imagref(((acf_ptr) L->rows[i]) + j), arb_midref(acb_imagref(acb_mat_entry(L_acb, i, j)))); } } } */ if (L != NULL) { status = gr_mat_inv(L, R, ctx); } for (i = 0; i < n; i++) { arf_set(acb_realref(((acf_ptr) D->entries) + i), arb_midref(acb_realref(D_acb + i))); arf_set(acb_imagref(((acf_ptr) D->entries) + i), arb_midref(acb_imagref(D_acb + i))); } } acb_mat_clear(R_acb); acb_mat_clear(A_acb); /* if (L != NULL) acb_mat_clear(L_acb); */ return status; } int _acf_methods_initialized = 0; gr_static_method_table _acf_methods; gr_method_tab_input _acf_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_acf_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_HAS_REAL_PREC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_REAL_PREC, (gr_funcptr) _gr_acf_ctx_set_real_prec}, {GR_METHOD_CTX_GET_REAL_PREC, (gr_funcptr) _gr_acf_ctx_get_real_prec}, {GR_METHOD_INIT, (gr_funcptr) _gr_acf_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_acf_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_acf_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_acf_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_acf_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_acf_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_acf_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_acf_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_acf_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_acf_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_acf_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_acf_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_acf_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_acf_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_acf_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_acf_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_acf_set_fmpq}, {GR_METHOD_SET_D, (gr_funcptr) _gr_acf_set_d}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_ring_exponents}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_acf_set_other}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_acf_get_fmpz}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_acf_get_ui}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_acf_get_si}, {GR_METHOD_GET_D, (gr_funcptr) _gr_acf_get_d}, {GR_METHOD_NEG, (gr_funcptr) _gr_acf_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_acf_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_acf_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_acf_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_acf_add_fmpz}, {GR_METHOD_SUB, (gr_funcptr) _gr_acf_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_acf_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_acf_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_acf_sub_fmpz}, {GR_METHOD_MUL, (gr_funcptr) _gr_acf_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_acf_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_acf_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_acf_mul_fmpz}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_acf_mul_two}, /* {GR_METHOD_ADDMUL, (gr_funcptr) _gr_acf_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_acf_submul}, */ {GR_METHOD_SQR, (gr_funcptr) _gr_acf_sqr}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) _gr_acf_mul_2exp_si}, {GR_METHOD_MUL_2EXP_FMPZ, (gr_funcptr) _gr_acf_mul_2exp_fmpz}, {GR_METHOD_SET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_acf_set_fmpz_2exp_fmpz}, {GR_METHOD_GET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_acf_get_fmpz_2exp_fmpz}, {GR_METHOD_DIV, (gr_funcptr) _gr_acf_div}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_acf_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_acf_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_acf_div_fmpz}, {GR_METHOD_INV, (gr_funcptr) _gr_acf_inv}, {GR_METHOD_POW, (gr_funcptr) _gr_acf_pow}, /* {GR_METHOD_POW_UI, (gr_funcptr) _gr_acf_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_acf_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_acf_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_acf_pow_fmpq}, */ {GR_METHOD_SQRT, (gr_funcptr) _gr_acf_sqrt}, /* {GR_METHOD_RSQRT, (gr_funcptr) _gr_acf_rsqrt}, */ {GR_METHOD_POS_INF, (gr_funcptr) _gr_acf_pos_inf}, {GR_METHOD_NEG_INF, (gr_funcptr) _gr_acf_neg_inf}, {GR_METHOD_UINF, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_UNDEFINED, (gr_funcptr) _gr_acf_nan}, {GR_METHOD_UNKNOWN, (gr_funcptr) _gr_acf_nan}, /* {GR_METHOD_FLOOR, (gr_funcptr) _gr_acf_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_acf_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_acf_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_acf_nint}, */ {GR_METHOD_ABS, (gr_funcptr) _gr_acf_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_acf_conj}, {GR_METHOD_RE, (gr_funcptr) _gr_acf_re}, {GR_METHOD_IM, (gr_funcptr) _gr_acf_im}, /* {GR_METHOD_SGN, (gr_funcptr) _gr_acf_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_acf_sgn}, */ {GR_METHOD_CMP, (gr_funcptr) _gr_acf_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) _gr_acf_cmpabs}, {GR_METHOD_I, (gr_funcptr) _gr_acf_i}, {GR_METHOD_PI, (gr_funcptr) _gr_acf_pi}, {GR_METHOD_EXP, (gr_funcptr) _gr_acf_exp}, {GR_METHOD_EXPM1, (gr_funcptr) _gr_acf_expm1}, {GR_METHOD_LOG, (gr_funcptr) _gr_acf_log}, {GR_METHOD_LOG1P, (gr_funcptr) _gr_acf_log1p}, {GR_METHOD_SIN, (gr_funcptr) _gr_acf_sin}, {GR_METHOD_COS, (gr_funcptr) _gr_acf_cos}, {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_acf_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_acf_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_acf_poly_mullow}, {GR_METHOD_POLY_ROOTS_OTHER,(gr_funcptr) _gr_acf_poly_roots_other}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_acf_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) gr_mat_det_generic_field}, /* todo */ {GR_METHOD_MAT_FIND_NONZERO_PIVOT, (gr_funcptr) gr_mat_find_nonzero_pivot_large_abs}, {GR_METHOD_MAT_DIAGONALIZATION, (gr_funcptr) _gr_acf_mat_diagonalization}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_complex_float_acf(gr_ctx_t ctx, slong prec) { ctx->which_ring = GR_CTX_COMPLEX_FLOAT_ACF; ctx->sizeof_elem = sizeof(acf_struct); ctx->size_limit = WORD_MAX; ACF_CTX_PREC(ctx) = FLINT_MAX(2, FLINT_MIN(prec, WORD_MAX / 8)); ACF_CTX_RND(ctx) = ARF_RND_NEAR; ctx->methods = _acf_methods; if (!_acf_methods_initialized) { gr_method_tab_init(_acf_methods, _acf_methods_input); _acf_methods_initialized = 1; } } flint-3.1.3/src/gr/arb.c000066400000000000000000001556731461254215100147630ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" #include "fmpq.h" #include "arb_poly.h" #include "acb_poly.h" #include "arb_mat.h" #include "arb_fmpz_poly.h" #include "arb_hypgeom.h" #include "fmpzi.h" #include "qqbar.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_poly.h" typedef struct { slong prec; } gr_arb_ctx; #define ARB_CTX_PREC(ring_ctx) (((gr_arb_ctx *)((ring_ctx)))->prec) int _gr_arb_ctx_set_real_prec(gr_ctx_t ctx, slong prec) { prec = FLINT_MAX(prec, 2); prec = FLINT_MIN(prec, WORD_MAX / 8); ARB_CTX_PREC(ctx) = prec; return GR_SUCCESS; } int _gr_arb_ctx_get_real_prec(slong * res, gr_ctx_t ctx) { *res = ARB_CTX_PREC(ctx); return GR_SUCCESS; } int _gr_arb_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Real numbers (arb, prec = "); gr_stream_write_si(out, ARB_CTX_PREC(ctx)); gr_stream_write(out, ")"); return GR_SUCCESS; } void _gr_arb_init(arb_t x, const gr_ctx_t ctx) { arb_init(x); } void _gr_arb_clear(arb_t x, const gr_ctx_t ctx) { arb_clear(x); } void _gr_arb_swap(arb_t x, arb_t y, const gr_ctx_t ctx) { arb_t t; *t = *x; *x = *y; *y = *t; } void _gr_arb_set_shallow(arb_t res, const arb_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_arb_randtest(arb_t res, flint_rand_t state, const gr_ctx_t ctx) { arb_randtest(res, state, ARB_CTX_PREC(ctx), 10); return GR_SUCCESS; } /* todo */ int _gr_arb_write(gr_stream_t out, const arb_t x, const gr_ctx_t ctx) { /* used by polynomial printing */ if (arb_is_exact(x)) { if (arf_is_zero(arb_midref(x))) { gr_stream_write(out, "0"); return GR_SUCCESS; } else if (arf_is_one(arb_midref(x))) { gr_stream_write(out, "1"); return GR_SUCCESS; } else if (arf_equal_si(arb_midref(x), -1)) { gr_stream_write(out, "-1"); return GR_SUCCESS; } } gr_stream_write_free(out, arb_get_str(x, ARB_CTX_PREC(ctx) * 0.30102999566398 + 1, 0)); return GR_SUCCESS; } int _gr_arb_write_n(gr_stream_t out, gr_srcptr x, slong n, gr_ctx_t ctx) { n = FLINT_MAX(n, 1); gr_stream_write_free(out, arb_get_str(x, n, ARB_STR_NO_RADIUS)); return GR_SUCCESS; } int _gr_arb_zero(arb_t x, const gr_ctx_t ctx) { arb_zero(x); return GR_SUCCESS; } int _gr_arb_one(arb_t x, const gr_ctx_t ctx) { arb_one(x); return GR_SUCCESS; } int _gr_arb_set_si(arb_t res, slong v, const gr_ctx_t ctx) { arb_set_si(res, v); arb_set_round(res, res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_set_ui(arb_t res, ulong v, const gr_ctx_t ctx) { arb_set_ui(res, v); arb_set_round(res, res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_set_fmpz(arb_t res, const fmpz_t v, const gr_ctx_t ctx) { arb_set_round_fmpz(res, v, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_set_fmpq(arb_t res, const fmpq_t v, const gr_ctx_t ctx) { arb_set_fmpq(res, v, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_set_str(arb_t res, const char * x, gr_ctx_t ctx) { if (!arb_set_str(res, x, ARB_CTX_PREC(ctx))) return GR_SUCCESS; return gr_generic_set_str_ring_exponents(res, x, ctx); } int _gr_arb_set_d(arb_t res, double x, const gr_ctx_t ctx) { arb_set_d(res, x); arb_set_round(res, res, ARB_CTX_PREC(ctx)); if (!arb_is_finite(res)) return GR_DOMAIN; return GR_SUCCESS; } int _gr_ca_get_arb_with_prec(arb_t res, gr_srcptr x, gr_ctx_t x_ctx, slong prec); int _gr_arb_set_other(arb_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: return _gr_arb_set_fmpz(res, x, ctx); case GR_CTX_FMPQ: return _gr_arb_set_fmpq(res, x, ctx); case GR_CTX_FMPZI: if (!fmpz_is_zero(fmpzi_imagref((const fmpzi_struct *) x))) return GR_DOMAIN; arb_set_round_fmpz(res, fmpzi_realref((const fmpzi_struct *) x), ARB_CTX_PREC(ctx)); return GR_SUCCESS; case GR_CTX_REAL_ALGEBRAIC_QQBAR: qqbar_get_arb(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; case GR_CTX_COMPLEX_ALGEBRAIC_QQBAR: if (qqbar_is_real(x)) { qqbar_get_arb(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else { return GR_DOMAIN; } case GR_CTX_RR_CA: case GR_CTX_REAL_ALGEBRAIC_CA: case GR_CTX_CC_CA: case GR_CTX_COMPLEX_ALGEBRAIC_CA: return _gr_ca_get_arb_with_prec(res, x, x_ctx, ARB_CTX_PREC(ctx)); case GR_CTX_REAL_FLOAT_ARF: if (arf_is_finite(x)) { arb_set_arf(res, x); arb_set_round(res, res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else { return GR_DOMAIN; } case GR_CTX_RR_ARB: arb_set_round(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; case GR_CTX_CC_ACB: if (arb_is_zero(acb_imagref((acb_srcptr) x))) { arb_set_round(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_contains_zero(acb_imagref((acb_srcptr) x))) { return GR_UNABLE; } else { return GR_DOMAIN; } } return gr_generic_set_other(res, x, x_ctx, ctx); } int _gr_arb_set_interval_mid_rad(arb_t res, const arb_t m, const arb_t r, const gr_ctx_t ctx) { mag_t rad; mag_init(rad); arb_get_mag(rad, r); arb_set(res, m); arb_add_error_mag(res, rad); mag_clear(rad); return GR_SUCCESS; } /* xxx: assumes that ctx are not read */ int _gr_arf_get_fmpz(fmpz_t res, const arf_t x, const gr_ctx_t ctx); int _gr_arf_get_si(slong * res, const arf_t x, const gr_ctx_t ctx); int _gr_arf_get_ui(ulong * res, const arf_t x, const gr_ctx_t ctx); int _gr_arb_get_fmpz(fmpz_t res, const arb_t x, const gr_ctx_t ctx) { if (!arb_is_int(x)) { if (arb_contains_int(x)) return GR_UNABLE; else return GR_DOMAIN; } return _gr_arf_get_fmpz(res, arb_midref(x), NULL); } int _gr_arb_get_si(slong * res, const arb_t x, const gr_ctx_t ctx) { if (!arb_is_int(x)) { if (arb_contains_int(x)) return GR_UNABLE; else return GR_DOMAIN; } return _gr_arf_get_si(res, arb_midref(x), NULL); } int _gr_arb_get_ui(ulong * res, const arb_t x, const gr_ctx_t ctx) { if (!arb_is_int(x)) { if (arb_contains_int(x)) return GR_UNABLE; else return GR_DOMAIN; } return _gr_arf_get_ui(res, arb_midref(x), NULL); } int _gr_arb_get_d(double * res, const arb_t x, const gr_ctx_t ctx) { *res = arf_get_d(arb_midref(x), ARF_RND_NEAR); return GR_SUCCESS; } truth_t _gr_arb_is_zero(const arb_t x, const gr_ctx_t ctx) { if (arb_is_zero(x)) return T_TRUE; if (arb_contains_zero(x)) return T_UNKNOWN; return T_FALSE; } truth_t _gr_arb_is_one(const arb_t x, const gr_ctx_t ctx) { if (arb_is_one(x)) return T_TRUE; if (mag_is_zero(arb_radref(x))) return T_FALSE; if (arb_contains_si(x, 1)) return T_UNKNOWN; return T_FALSE; } truth_t _gr_arb_is_neg_one(const arb_t x, const gr_ctx_t ctx) { if (arb_equal_si(x, -1)) return T_TRUE; if (arb_contains_si(x, -1)) return T_UNKNOWN; return T_FALSE; } truth_t _gr_arb_equal(const arb_t x, const arb_t y, const gr_ctx_t ctx) { if (arb_is_exact(x) && arb_equal(x, y)) return T_TRUE; if (arb_overlaps(x, y)) return T_UNKNOWN; return T_FALSE; } int _gr_arb_set(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_set(res, x); return GR_SUCCESS; } int _gr_arb_neg(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_neg(res, x); return GR_SUCCESS; } int _gr_arb_add(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_add(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_add_si(arb_t res, const arb_t x, slong y, const gr_ctx_t ctx) { arb_add_si(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_add_ui(arb_t res, const arb_t x, ulong y, const gr_ctx_t ctx) { arb_add_ui(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_add_fmpz(arb_t res, const arb_t x, const fmpz_t y, const gr_ctx_t ctx) { arb_add_fmpz(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_sub(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_sub(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_sub_si(arb_t res, const arb_t x, slong y, const gr_ctx_t ctx) { arb_sub_si(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_sub_ui(arb_t res, const arb_t x, ulong y, const gr_ctx_t ctx) { arb_sub_ui(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_sub_fmpz(arb_t res, const arb_t x, const fmpz_t y, const gr_ctx_t ctx) { arb_sub_fmpz(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mul(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_mul(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mul_si(arb_t res, const arb_t x, slong y, const gr_ctx_t ctx) { arb_mul_si(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mul_ui(arb_t res, const arb_t x, ulong y, const gr_ctx_t ctx) { arb_mul_ui(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mul_fmpz(arb_t res, const arb_t x, const fmpz_t y, const gr_ctx_t ctx) { arb_mul_fmpz(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_addmul(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_addmul(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_submul(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_submul(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mul_two(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_mul_2exp_si(res, x, 1); return GR_SUCCESS; } int _gr_arb_sqr(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_sqr(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mul_2exp_si(arb_t res, const arb_t x, slong y, const gr_ctx_t ctx) { arb_mul_2exp_si(res, x, y); return GR_SUCCESS; } int _gr_arb_mul_2exp_fmpz(arb_t res, const arb_t x, const fmpz_t y, const gr_ctx_t ctx) { arb_mul_2exp_fmpz(res, x, y); return GR_SUCCESS; } int _gr_arb_set_fmpz_2exp_fmpz(arb_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { arb_set_fmpz_2exp(res, x, y); return GR_SUCCESS; } int _gr_arb_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, const arb_t x, const gr_ctx_t ctx) { if (!arb_is_exact(x)) return GR_UNABLE; if (!arb_is_finite(x)) return GR_DOMAIN; arf_get_fmpz_2exp(res1, res2, arb_midref(x)); return GR_SUCCESS; } int _gr_arb_inv(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_zero(x)) { return GR_DOMAIN; } else { arb_inv(res, x, ARB_CTX_PREC(ctx)); if (arb_is_finite(res)) return GR_SUCCESS; else return GR_UNABLE; } } int _gr_arb_div(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { if (arb_is_zero(y)) { return GR_DOMAIN; } else { arb_div(res, x, y, ARB_CTX_PREC(ctx)); if (arb_is_finite(res)) return GR_SUCCESS; else return GR_UNABLE; } } int _gr_arb_div_si(arb_t res, const arb_t x, slong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { arb_div_si(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } } int _gr_arb_div_ui(arb_t res, const arb_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { arb_div_ui(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } } int _gr_arb_div_fmpz(arb_t res, const arb_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { arb_div_fmpz(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } } truth_t _gr_arb_is_invertible(const arb_t x, const gr_ctx_t ctx) { if (arb_is_zero(x)) return T_FALSE; if (arb_contains_zero(x)) return T_UNKNOWN; return T_TRUE; } int _gr_arb_pow_ui(arb_t res, const arb_t x, ulong exp, const gr_ctx_t ctx) { arb_pow_ui(res, x, exp, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_pow_si(arb_t res, const arb_t x, slong exp, const gr_ctx_t ctx) { if (exp < 0 && arb_is_zero(x)) { return GR_DOMAIN; } else if (exp < 0 && arb_contains_zero(x)) { return GR_UNABLE; } else { fmpz_t t; fmpz_init_set_si(t, exp); arb_pow_fmpz(res, x, t, ARB_CTX_PREC(ctx)); fmpz_clear(t); return GR_SUCCESS; } } int _gr_arb_pow_fmpz(arb_t res, const arb_t x, const fmpz_t exp, const gr_ctx_t ctx) { if (fmpz_sgn(exp) < 0 && arb_is_zero(x)) { return GR_DOMAIN; } else if (fmpz_sgn(exp) < 0 && arb_contains_zero(x)) { return GR_UNABLE; } else { arb_pow_fmpz(res, x, exp, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } } int _gr_arb_pow_fmpq(arb_t res, const arb_t x, const fmpq_t exp, const gr_ctx_t ctx) { if (fmpq_sgn(exp) < 0 && arb_is_zero(x)) { return GR_DOMAIN; } else if (fmpq_sgn(exp) < 0 && arb_contains_zero(x)) { return GR_UNABLE; } else { if (fmpz_is_one(fmpq_denref(exp)) || arb_is_nonnegative(x)) { arb_pow_fmpq(res, x, exp, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_is_negative(x)) { return GR_DOMAIN; } else { return GR_UNABLE; } } } int _gr_arb_pow(arb_t res, const arb_t x, const arb_t exp, const gr_ctx_t ctx) { if (arb_is_int(exp)) { if (arf_sgn(arb_midref(exp)) < 0) { if (arb_is_zero(x)) return GR_DOMAIN; if (arb_contains_zero(x)) return GR_UNABLE; } arb_pow(res, x, exp, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_is_positive(x) || (arb_is_nonnegative(x) && arb_is_nonnegative(exp))) { arb_pow(res, x, exp, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_is_zero(x) && arb_is_negative(exp)) { return GR_DOMAIN; } else if (arb_is_negative(x) && !arb_contains_int(exp)) { return GR_DOMAIN; } else { return GR_UNABLE; } } truth_t _gr_arb_is_square(const arb_t x, const gr_ctx_t ctx) { return T_TRUE; } int _gr_arb_sqrt(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_nonnegative(x)) { arb_sqrt(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_is_negative(x)) { return GR_DOMAIN; } else { return GR_UNABLE; } } int _gr_arb_rsqrt(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_positive(x)) { arb_rsqrt(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_is_nonpositive(x)) { return GR_DOMAIN; } else { return GR_UNABLE; } } int _gr_arb_floor(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_floor(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_ceil(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_ceil(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_trunc(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_trunc(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_nint(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_nint(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_abs(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_abs(res, x); return GR_SUCCESS; } int _gr_arb_conj(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_set(res, x); return GR_SUCCESS; } int _gr_arb_im(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_zero(res); return GR_SUCCESS; } int _gr_arb_sgn(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_sgn(res, x); return GR_SUCCESS; } int _gr_arb_arg(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_nonnegative(x)) { arb_zero(res); } else if (arb_is_negative(x)) { arb_const_pi(res, ARB_CTX_PREC(ctx)); } else { arb_t t; arb_init(t); arb_const_pi(res, 2 * MAG_BITS); arb_union(res, res, t, ARB_CTX_PREC(ctx)); arb_clear(t); } return GR_SUCCESS; } int _gr_arb_cmp(int * res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { if ((arb_is_exact(x) && arb_is_exact(y)) || !arb_overlaps(x, y)) { *res = arf_cmp(arb_midref(x), arb_midref(y)); return GR_SUCCESS; } else { *res = 0; return GR_UNABLE; } } int _gr_arb_cmpabs(int * res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_t t, u; *t = *x; *u = *y; if (arf_sgn(arb_midref(t)) < 0) ARF_NEG(arb_midref(t)); if (arf_sgn(arb_midref(u)) < 0) ARF_NEG(arb_midref(u)); return _gr_arb_cmp(res, t, u, ctx); } int _gr_arb_pi(arb_t res, const gr_ctx_t ctx) { arb_const_pi(res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_euler(arb_t res, const gr_ctx_t ctx) { arb_const_euler(res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_catalan(arb_t res, const gr_ctx_t ctx) { arb_const_catalan(res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_khinchin(arb_t res, const gr_ctx_t ctx) { arb_const_khinchin(res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_glaisher(arb_t res, const gr_ctx_t ctx) { arb_const_glaisher(res, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } #define DEF_FUNC(fname) \ int \ _gr_arb_ ## fname(arb_t res, const arb_t x, const gr_ctx_t ctx) \ { \ arb_ ## fname(res, x, ARB_CTX_PREC(ctx)); \ return GR_SUCCESS; \ } \ #define DEF_2FUNC(fname) \ int \ _gr_arb_ ## fname(arb_t res1, arb_t res2, const arb_t x, const gr_ctx_t ctx) \ { \ arb_ ## fname(res1, res2, x, ARB_CTX_PREC(ctx)); \ return GR_SUCCESS; \ } \ #define DEF_FUNC2(fname) \ int \ _gr_arb_ ## fname(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) \ { \ arb_ ## fname(res, x, y, ARB_CTX_PREC(ctx)); \ return GR_SUCCESS; \ } \ #define DEF_FUNC_SING(fname) \ int \ _gr_arb_ ## fname(arb_t res, const arb_t x, const gr_ctx_t ctx) \ { \ arb_ ## fname(res, x, ARB_CTX_PREC(ctx)); \ return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; \ } \ #define DEF_FUNC2_SING(fname) \ int \ _gr_arb_ ## fname(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) \ { \ arb_ ## fname(res, x, y, ARB_CTX_PREC(ctx)); \ return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; \ } \ DEF_FUNC(exp) DEF_FUNC(expm1) DEF_FUNC_SING(log1p) int _gr_arb_log(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_positive(x)) { arb_log(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } if (arb_is_nonpositive(x)) return GR_DOMAIN; return GR_UNABLE; } DEF_FUNC(sin) DEF_FUNC(cos) DEF_2FUNC(sin_cos) DEF_FUNC_SING(tan) DEF_FUNC_SING(cot) DEF_FUNC_SING(sec) DEF_FUNC_SING(csc) DEF_FUNC(sin_pi) DEF_FUNC(cos_pi) DEF_2FUNC(sin_cos_pi) /* todo: detect exact singularities */ DEF_FUNC_SING(tan_pi) DEF_FUNC_SING(cot_pi) DEF_FUNC_SING(csc_pi) DEF_FUNC(sinc) DEF_FUNC(sinc_pi) DEF_FUNC(sinh) DEF_FUNC(cosh) DEF_2FUNC(sinh_cosh) DEF_FUNC(tanh) DEF_FUNC_SING(coth) DEF_FUNC(sech) DEF_FUNC_SING(csch) DEF_FUNC_SING(asin) DEF_FUNC_SING(acos) DEF_FUNC(atan) DEF_FUNC2(atan2) DEF_FUNC(asinh) DEF_FUNC_SING(acosh) DEF_FUNC_SING(atanh) int _gr_arb_lambertw(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_lambertw(res, x, 0, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_lambertw_fmpz(arb_t res, const arb_t x, const fmpz_t k, const gr_ctx_t ctx) { if (fmpz_is_zero(k)) arb_lambertw(res, x, 0, ARB_CTX_PREC(ctx)); else if (fmpz_equal_si(k, -1)) arb_lambertw(res, x, 1, ARB_CTX_PREC(ctx)); else return GR_DOMAIN; return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } #include "bernoulli.h" /* todo: caching, e.g. if (x <= 1000) bernoulli_cache_compute(x + 1); */ int _gr_arb_bernoulli_ui(arb_t res, ulong x, const gr_ctx_t ctx) { arb_bernoulli_ui(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_bernoulli_fmpz(arb_t res, const fmpz_t x, const gr_ctx_t ctx) { arb_bernoulli_fmpz(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_eulernum_ui(arb_t res, ulong x, const gr_ctx_t ctx) { arb_euler_number_ui(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_eulernum_fmpz(arb_t res, const fmpz_t x, const gr_ctx_t ctx) { arb_euler_number_fmpz(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_bellnum_ui(arb_t res, ulong x, const gr_ctx_t ctx) { arb_bell_ui(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_bellnum_fmpz(arb_t res, const fmpz_t x, const gr_ctx_t ctx) { arb_bell_fmpz(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_partitions_ui(arb_t res, ulong x, const gr_ctx_t ctx) { arb_partitions_ui(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_partitions_fmpz(arb_t res, const fmpz_t x, const gr_ctx_t ctx) { arb_partitions_fmpz(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_erf(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_erf(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_erfc(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_erfc(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_erfi(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_erfi(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_erfinv(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_erfinv(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_erfcinv(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_erfcinv(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_fresnel_s(arb_t res, const arb_t x, int normalized, const gr_ctx_t ctx) { arb_hypgeom_fresnel(res, NULL, x, normalized, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_fresnel_c(arb_t res, const arb_t x, int normalized, const gr_ctx_t ctx) { arb_hypgeom_fresnel(NULL, res, x, normalized, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_fresnel(arb_t res1, arb_t res2, const arb_t x, int normalized, const gr_ctx_t ctx) { arb_hypgeom_fresnel(res1, res2, x, normalized, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_gamma_upper(arb_t res, const arb_t x, const arb_t y, int regularized, const gr_ctx_t ctx) { arb_hypgeom_gamma_upper(res, x, y, regularized, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_gamma_lower(arb_t res, const arb_t x, const arb_t y, int regularized, const gr_ctx_t ctx) { arb_hypgeom_gamma_lower(res, x, y, regularized, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_beta_lower(arb_t res, const arb_t x, const arb_t y, const arb_t z, int regularized, const gr_ctx_t ctx) { arb_hypgeom_beta_lower(res, x, y, z, regularized, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_exp_integral(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_expint(res, x, y, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_exp_integral_ei(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_ei(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_sin_integral(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_si(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_cos_integral(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_ci(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_sinh_integral(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_shi(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_cosh_integral(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_chi(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_log_integral(arb_t res, const arb_t x, int offset, const gr_ctx_t ctx) { arb_hypgeom_li(res, x, offset, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_dilog(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_dilog(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_gamma(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_positive(x)) { arb_gamma(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_is_nonpositive(x) && arb_is_int(x)) { return GR_DOMAIN; } else { arb_gamma(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } } int _gr_arb_gamma_fmpz(arb_t res, const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_sgn(x) > 0) { arb_gamma_fmpz(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_arb_gamma_fmpq(arb_t res, const fmpq_t x, const gr_ctx_t ctx) { if (!fmpz_is_one(fmpq_denref(x)) || fmpz_sgn(fmpq_numref(x)) > 0) { arb_gamma_fmpq(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_arb_rgamma(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_rgamma(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_fac_ui(arb_t res, ulong x, const gr_ctx_t ctx) { arb_fac_ui(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_fac_fmpz(arb_t res, const fmpz_t x, const gr_ctx_t ctx) { int status; fmpz_t t; fmpz_init(t); fmpz_add_ui(t, x, 1); status = _gr_arb_gamma_fmpz(res, t, ctx); fmpz_clear(t); return status; } int _gr_arb_rising_ui(arb_t res, const arb_t x, ulong y, const gr_ctx_t ctx) { arb_rising_ui(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_rising(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_rising(res, x, y, ARB_CTX_PREC(ctx)); if (arb_is_finite(res)) return GR_SUCCESS; else return GR_UNABLE; } int _gr_arb_lgamma(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_positive(x)) { arb_lgamma(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } if (arb_is_nonpositive(x)) return GR_DOMAIN; return GR_UNABLE; } int _gr_arb_digamma(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_positive(x)) { arb_digamma(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } else if (arb_is_nonpositive(x) && arb_is_int(x)) { return GR_DOMAIN; } else { arb_digamma(res, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } } int _gr_arb_barnes_g(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_int(x) && arb_is_nonpositive(x)) { return GR_DOMAIN; } else { acb_t t; int status; acb_init(t); acb_set_arb(t, x); acb_barnes_g(t, t, ARB_CTX_PREC(ctx)); arb_swap(res, acb_realref(t)); status = acb_is_finite(t) ? GR_SUCCESS : GR_UNABLE; acb_clear(t); return status; } } int _gr_arb_log_barnes_g(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_is_positive(x)) { acb_t t; acb_init(t); acb_set_arb(t, x); acb_log_barnes_g(t, t, ARB_CTX_PREC(ctx)); arb_swap(res, acb_realref(t)); acb_clear(t); return GR_SUCCESS; } else if (arb_is_nonpositive(x)) { return GR_DOMAIN; } else { return GR_UNABLE; } } int _gr_arb_bessel_j(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_bessel_j(res, x, y, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_bessel_y(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_bessel_y(res, x, y, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_bessel_i(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_bessel_i(res, x, y, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_bessel_k(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_bessel_k(res, x, y, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_bessel_j_y(arb_t res1, arb_t res2, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_bessel_jy(res1, res2, x, y, ARB_CTX_PREC(ctx)); return (arb_is_finite(res1) && arb_is_finite(res2)) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_bessel_i_scaled(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_bessel_i_scaled(res, x, y, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_bessel_k_scaled(arb_t res, const arb_t x, const arb_t y, const gr_ctx_t ctx) { arb_hypgeom_bessel_k_scaled(res, x, y, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_airy(arb_t res1, arb_t res2, arb_t res3, arb_t res4, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_airy(res1, res2, res3, res4, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_ai(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_airy(res, NULL, NULL, NULL, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_ai_prime(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_airy(NULL, res, NULL, NULL, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_bi(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_airy(NULL, NULL, res, NULL, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_bi_prime(arb_t res, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_airy(NULL, NULL, NULL, res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_ai_zero(arb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(res, NULL, NULL, NULL, n, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_ai_prime_zero(arb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(NULL, res, NULL, NULL, n, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_bi_zero(arb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(NULL, NULL, res, NULL, n, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_airy_bi_prime_zero(arb_t res, const fmpz_t n, const gr_ctx_t ctx) { if (fmpz_sgn(n) <= 0) return GR_DOMAIN; arb_hypgeom_airy_zero(NULL, NULL, NULL, res, n, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_coulomb(arb_t res1, arb_t res2, arb_t res3, arb_t res4, const arb_t x, const arb_t y, const arb_t z, const gr_ctx_t ctx) { /* H+, H- are typically complex */ /* todo: document allowing NULL, or separate F+G method? */ if (res3 == NULL && res4 == NULL) { arb_hypgeom_coulomb(res1, res2, x, y, z, ARB_CTX_PREC(ctx)); return (arb_is_finite(res1) && arb_is_finite(res2)) ? GR_SUCCESS : GR_UNABLE; } else { return GR_UNABLE; } } int _gr_arb_coulomb_f(arb_t res, const arb_t x, const arb_t y, const arb_t z, const gr_ctx_t ctx) { arb_hypgeom_coulomb(res, NULL, x, y, z, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_coulomb_g(arb_t res, const arb_t x, const arb_t y, const arb_t z, const gr_ctx_t ctx) { arb_hypgeom_coulomb(NULL, res, x, y, z, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_coulomb_hpos(arb_t res, const arb_t x, const arb_t y, const arb_t z, const gr_ctx_t ctx) { return GR_UNABLE; } int _gr_arb_coulomb_hneg(arb_t res, const arb_t x, const arb_t y, const arb_t z, const gr_ctx_t ctx) { return GR_UNABLE; } int _gr_arb_chebyshev_t(arb_t res, const arb_t n, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_chebyshev_t(res, n, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_chebyshev_u(arb_t res, const arb_t n, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_chebyshev_u(res, n, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_jacobi_p(arb_t res, const arb_t n, const arb_t a, const arb_t b, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_jacobi_p(res, n, a, b, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_gegenbauer_c(arb_t res, const arb_t n, const arb_t m, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_gegenbauer_c(res, n, m, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_laguerre_l(arb_t res, const arb_t n, const arb_t m, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_laguerre_l(res, n, m, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_hermite_h(arb_t res, const arb_t n, const arb_t x, const gr_ctx_t ctx) { arb_hypgeom_hermite_h(res, n, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_legendre_p(arb_t res, const arb_t n, const arb_t m, const arb_t x, int type, const gr_ctx_t ctx) { arb_hypgeom_legendre_p(res, n, m, x, type, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_legendre_q(arb_t res, const arb_t n, const arb_t m, const arb_t x, int type, const gr_ctx_t ctx) { arb_hypgeom_legendre_q(res, n, m, x, type, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_legendre_p_root_ui(arb_t res, arb_t res2, ulong n, ulong k, const gr_ctx_t ctx) { if (k >= n) return GR_DOMAIN; arb_hypgeom_legendre_p_ui_root(res, res2, n, k, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_hypgeom_0f1(arb_t res, const arb_t a, const arb_t x, int flags, const gr_ctx_t ctx) { arb_hypgeom_0f1(res, a, x, flags, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_hypgeom_1f1(arb_t res, const arb_t a, const arb_t b, const arb_t x, int flags, const gr_ctx_t ctx) { arb_hypgeom_1f1(res, a, b, x, flags, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_hypgeom_u(arb_t res, const arb_t a, const arb_t b, const arb_t x, int flags, const gr_ctx_t ctx) { arb_hypgeom_u(res, a, b, x, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_hypgeom_2f1(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t x, int flags, const gr_ctx_t ctx) { arb_hypgeom_2f1(res, a, b, c, x, flags, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_hypgeom_pfq(arb_t res, const gr_vec_t a, const gr_vec_t b, const arb_t x, int flags, const gr_ctx_t ctx) { arb_hypgeom_pfq(res, a->entries, a->length, b->entries, b->length, x, flags, ARB_CTX_PREC(ctx)); return arb_is_finite(res) ? GR_SUCCESS : GR_UNABLE; } int _gr_arb_zeta(arb_t res, const arb_t x, const gr_ctx_t ctx) { if (arb_contains_si(x, 1)) { if (arb_is_one(x)) return GR_DOMAIN; else return GR_UNABLE; } else { arb_zeta(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } } DEF_FUNC2_SING(hurwitz_zeta) DEF_FUNC2_SING(polylog) DEF_FUNC2_SING(agm) static void arb_agm1(arb_t res, const arb_t x, slong prec) { arb_t t; arb_init(t); arb_one(t); arb_agm(res, t, x, prec); arb_clear(t); } DEF_FUNC_SING(agm1) int _gr_arb_vec_dot(arb_t res, const arb_t initial, int subtract, arb_srcptr vec1, arb_srcptr vec2, slong len, gr_ctx_t ctx) { arb_dot(res, initial, subtract, vec1, 1, vec2, 1, len, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_vec_dot_rev(arb_t res, const arb_t initial, int subtract, arb_srcptr vec1, arb_srcptr vec2, slong len, gr_ctx_t ctx) { arb_dot(res, initial, subtract, vec1, 1, vec2 + len - 1, -1, len, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_poly_mullow(arb_ptr res, arb_srcptr poly1, slong len1, arb_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { _arb_poly_mullow(res, poly1, len1, poly2, len2, n, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_poly_taylor_shift(arb_ptr res, arb_srcptr poly, slong len, const arb_t c, gr_ctx_t ctx); /* hidden feature: also works with arb ctx */ int _gr_acb_poly_roots(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx); int _gr_arb_poly_roots(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx) { int status; slong i; acb_poly_t tmp; acb_poly_init(tmp); acb_poly_fit_length(tmp, poly->length); for (i = 0; i < poly->length; i++) acb_set_arb(tmp->coeffs + i, ((arb_srcptr) poly->coeffs) + i); _acb_poly_set_length(tmp, poly->length); status = _gr_acb_poly_roots(roots, mult, (gr_poly_struct *) tmp, flags, ctx); acb_poly_clear(tmp); return status; } int _gr_arb_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t other_ctx, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; if (other_ctx->which_ring == GR_CTX_RR_ARB) { return _gr_arb_poly_roots(roots, mult, poly, flags, ctx); } if (other_ctx->which_ring == GR_CTX_FMPZ) { gr_ctx_t ZZ; slong i, j, deg, deg2; acb_ptr croots; int status = GR_SUCCESS; deg = poly->length - 1; gr_ctx_init_fmpz(ZZ); gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); if (deg != 0) { fmpz_poly_factor_t fac; fmpz_poly_factor_init(fac); fmpz_poly_factor_squarefree(fac, (const fmpz_poly_struct *) poly); for (i = 0; i < fac->num; i++) { deg2 = fmpz_poly_degree(fac->p + i); croots = _acb_vec_init(deg2); arb_fmpz_poly_complex_roots(croots, fac->p + i, 0, ARB_CTX_PREC(ctx)); for (j = 0; j < deg2; j++) { if (acb_is_real(croots + j)) { fmpz m2 = fac->exp[i]; GR_MUST_SUCCEED(gr_vec_append(roots, acb_realref(croots + j), ctx)); GR_MUST_SUCCEED(gr_vec_append(mult, &m2, ZZ)); } } _acb_vec_clear(croots, deg2); } fmpz_poly_factor_clear(fac); } gr_ctx_clear(ZZ); return status; } return GR_UNABLE; } int _gr_arb_mat_mul(arb_mat_t res, const arb_mat_t x, const arb_mat_t y, gr_ctx_t ctx) { arb_mat_mul(res, x, y, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mat_det(arb_t res, const arb_mat_t x, gr_ctx_t ctx) { arb_mat_det(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _gr_arb_mat_exp(arb_mat_t res, const arb_mat_t x, gr_ctx_t ctx) { if (x->r != x->c) return GR_DOMAIN; arb_mat_exp(res, x, ARB_CTX_PREC(ctx)); return GR_SUCCESS; } int _arb_methods_initialized = 0; gr_static_method_table _arb_methods; gr_method_tab_input _arb_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_arb_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_HAS_REAL_PREC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_REAL_PREC, (gr_funcptr) _gr_arb_ctx_set_real_prec}, {GR_METHOD_CTX_GET_REAL_PREC, (gr_funcptr) _gr_arb_ctx_get_real_prec}, {GR_METHOD_INIT, (gr_funcptr) _gr_arb_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_arb_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_arb_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_arb_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_arb_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_arb_write}, {GR_METHOD_WRITE_N, (gr_funcptr) _gr_arb_write_n}, {GR_METHOD_ZERO, (gr_funcptr) _gr_arb_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_arb_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_arb_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_arb_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_arb_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_arb_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_arb_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_arb_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_arb_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_arb_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_arb_set_fmpq}, {GR_METHOD_SET_STR, (gr_funcptr) _gr_arb_set_str}, {GR_METHOD_SET_D, (gr_funcptr) _gr_arb_set_d}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_arb_set_other}, {GR_METHOD_SET_INTERVAL_MID_RAD, (gr_funcptr) _gr_arb_set_interval_mid_rad}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_arb_get_si}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_arb_get_ui}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_arb_get_fmpz}, {GR_METHOD_GET_D, (gr_funcptr) _gr_arb_get_d}, {GR_METHOD_NEG, (gr_funcptr) _gr_arb_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_arb_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_arb_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_arb_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_arb_add_fmpz}, {GR_METHOD_SUB, (gr_funcptr) _gr_arb_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_arb_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_arb_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_arb_sub_fmpz}, {GR_METHOD_MUL, (gr_funcptr) _gr_arb_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_arb_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_arb_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_arb_mul_fmpz}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_arb_mul_two}, {GR_METHOD_ADDMUL, (gr_funcptr) _gr_arb_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_arb_submul}, {GR_METHOD_SQR, (gr_funcptr) _gr_arb_sqr}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) _gr_arb_mul_2exp_si}, {GR_METHOD_MUL_2EXP_FMPZ, (gr_funcptr) _gr_arb_mul_2exp_fmpz}, {GR_METHOD_SET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_arb_set_fmpz_2exp_fmpz}, {GR_METHOD_GET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_arb_get_fmpz_2exp_fmpz}, {GR_METHOD_DIV, (gr_funcptr) _gr_arb_div}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_arb_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_arb_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_arb_div_fmpz}, {GR_METHOD_INV, (gr_funcptr) _gr_arb_inv}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_arb_is_invertible}, {GR_METHOD_POW, (gr_funcptr) _gr_arb_pow}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_arb_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_arb_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_arb_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_arb_pow_fmpq}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_arb_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_arb_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_arb_rsqrt}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_arb_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_arb_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_arb_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_arb_nint}, {GR_METHOD_ABS, (gr_funcptr) _gr_arb_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_arb_conj}, {GR_METHOD_RE, (gr_funcptr) _gr_arb_set}, {GR_METHOD_IM, (gr_funcptr) _gr_arb_im}, {GR_METHOD_SGN, (gr_funcptr) _gr_arb_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_arb_sgn}, {GR_METHOD_ARG, (gr_funcptr) _gr_arb_arg}, {GR_METHOD_CMP, (gr_funcptr) _gr_arb_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) _gr_arb_cmpabs}, {GR_METHOD_I, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_PI, (gr_funcptr) _gr_arb_pi}, {GR_METHOD_EULER, (gr_funcptr) _gr_arb_euler}, {GR_METHOD_CATALAN, (gr_funcptr) _gr_arb_catalan}, {GR_METHOD_KHINCHIN, (gr_funcptr) _gr_arb_khinchin}, {GR_METHOD_GLAISHER, (gr_funcptr) _gr_arb_glaisher}, {GR_METHOD_EXP, (gr_funcptr) _gr_arb_exp}, {GR_METHOD_EXPM1, (gr_funcptr) _gr_arb_expm1}, {GR_METHOD_LOG, (gr_funcptr) _gr_arb_log}, {GR_METHOD_LOG1P, (gr_funcptr) _gr_arb_log1p}, {GR_METHOD_SIN, (gr_funcptr) _gr_arb_sin}, {GR_METHOD_COS, (gr_funcptr) _gr_arb_cos}, {GR_METHOD_SIN_COS, (gr_funcptr) _gr_arb_sin_cos}, {GR_METHOD_TAN, (gr_funcptr) _gr_arb_tan}, {GR_METHOD_COT, (gr_funcptr) _gr_arb_cot}, {GR_METHOD_SEC, (gr_funcptr) _gr_arb_sec}, {GR_METHOD_CSC, (gr_funcptr) _gr_arb_csc}, {GR_METHOD_SIN_PI, (gr_funcptr) _gr_arb_sin_pi}, {GR_METHOD_COS_PI, (gr_funcptr) _gr_arb_cos_pi}, {GR_METHOD_SIN_COS_PI, (gr_funcptr) _gr_arb_sin_cos_pi}, {GR_METHOD_TAN_PI, (gr_funcptr) _gr_arb_tan_pi}, {GR_METHOD_COT_PI, (gr_funcptr) _gr_arb_cot_pi}, {GR_METHOD_CSC_PI, (gr_funcptr) _gr_arb_csc_pi}, {GR_METHOD_SINC, (gr_funcptr) _gr_arb_sinc}, {GR_METHOD_SINC_PI, (gr_funcptr) _gr_arb_sinc_pi}, {GR_METHOD_ASIN, (gr_funcptr) _gr_arb_asin}, {GR_METHOD_ACOS, (gr_funcptr) _gr_arb_acos}, {GR_METHOD_ATAN, (gr_funcptr) _gr_arb_atan}, {GR_METHOD_ATAN2, (gr_funcptr) _gr_arb_atan2}, {GR_METHOD_SINH, (gr_funcptr) _gr_arb_sinh}, {GR_METHOD_COSH, (gr_funcptr) _gr_arb_cosh}, {GR_METHOD_SINH_COSH, (gr_funcptr) _gr_arb_sinh_cosh}, {GR_METHOD_TANH, (gr_funcptr) _gr_arb_tanh}, {GR_METHOD_COTH, (gr_funcptr) _gr_arb_coth}, {GR_METHOD_SECH, (gr_funcptr) _gr_arb_sech}, {GR_METHOD_CSCH, (gr_funcptr) _gr_arb_csch}, {GR_METHOD_ATANH, (gr_funcptr) _gr_arb_atanh}, {GR_METHOD_ASINH, (gr_funcptr) _gr_arb_asinh}, {GR_METHOD_ACOSH, (gr_funcptr) _gr_arb_acosh}, {GR_METHOD_LAMBERTW, (gr_funcptr) _gr_arb_lambertw}, {GR_METHOD_LAMBERTW_FMPZ, (gr_funcptr) _gr_arb_lambertw_fmpz}, {GR_METHOD_FAC_UI, (gr_funcptr) _gr_arb_fac_ui}, {GR_METHOD_FAC_FMPZ, (gr_funcptr) _gr_arb_fac_fmpz}, {GR_METHOD_RISING_UI, (gr_funcptr) _gr_arb_rising_ui}, {GR_METHOD_RISING, (gr_funcptr) _gr_arb_rising}, {GR_METHOD_GAMMA, (gr_funcptr) _gr_arb_gamma}, {GR_METHOD_GAMMA_FMPZ, (gr_funcptr) _gr_arb_gamma_fmpz}, {GR_METHOD_GAMMA_FMPQ, (gr_funcptr) _gr_arb_gamma_fmpq}, {GR_METHOD_RGAMMA, (gr_funcptr) _gr_arb_rgamma}, {GR_METHOD_LGAMMA, (gr_funcptr) _gr_arb_lgamma}, {GR_METHOD_DIGAMMA, (gr_funcptr) _gr_arb_digamma}, {GR_METHOD_BARNES_G, (gr_funcptr) _gr_arb_barnes_g}, {GR_METHOD_LOG_BARNES_G, (gr_funcptr) _gr_arb_log_barnes_g}, {GR_METHOD_BERNOULLI_UI, (gr_funcptr) _gr_arb_bernoulli_ui}, {GR_METHOD_BERNOULLI_FMPZ, (gr_funcptr) _gr_arb_bernoulli_fmpz}, {GR_METHOD_EULERNUM_UI, (gr_funcptr) _gr_arb_eulernum_ui}, {GR_METHOD_EULERNUM_FMPZ, (gr_funcptr) _gr_arb_eulernum_fmpz}, {GR_METHOD_BELLNUM_UI, (gr_funcptr) _gr_arb_bellnum_ui}, {GR_METHOD_BELLNUM_FMPZ, (gr_funcptr) _gr_arb_bellnum_fmpz}, {GR_METHOD_PARTITIONS_UI, (gr_funcptr) _gr_arb_partitions_ui}, {GR_METHOD_PARTITIONS_FMPZ, (gr_funcptr) _gr_arb_partitions_fmpz}, {GR_METHOD_ERF, (gr_funcptr) _gr_arb_erf}, {GR_METHOD_ERFI, (gr_funcptr) _gr_arb_erfi}, {GR_METHOD_ERFC, (gr_funcptr) _gr_arb_erfc}, {GR_METHOD_ERFINV, (gr_funcptr) _gr_arb_erfinv}, {GR_METHOD_ERFCINV, (gr_funcptr) _gr_arb_erfcinv}, {GR_METHOD_FRESNEL_C, (gr_funcptr) _gr_arb_fresnel_c}, {GR_METHOD_FRESNEL_S, (gr_funcptr) _gr_arb_fresnel_s}, {GR_METHOD_FRESNEL, (gr_funcptr) _gr_arb_fresnel}, {GR_METHOD_GAMMA_UPPER, (gr_funcptr) _gr_arb_gamma_upper}, {GR_METHOD_GAMMA_LOWER, (gr_funcptr) _gr_arb_gamma_lower}, {GR_METHOD_BETA_LOWER, (gr_funcptr) _gr_arb_beta_lower}, {GR_METHOD_EXP_INTEGRAL, (gr_funcptr) _gr_arb_exp_integral}, {GR_METHOD_EXP_INTEGRAL_EI, (gr_funcptr) _gr_arb_exp_integral_ei}, {GR_METHOD_SIN_INTEGRAL, (gr_funcptr) _gr_arb_sin_integral}, {GR_METHOD_COS_INTEGRAL, (gr_funcptr) _gr_arb_cos_integral}, {GR_METHOD_SINH_INTEGRAL, (gr_funcptr) _gr_arb_sinh_integral}, {GR_METHOD_COSH_INTEGRAL, (gr_funcptr) _gr_arb_cosh_integral}, {GR_METHOD_LOG_INTEGRAL, (gr_funcptr) _gr_arb_log_integral}, {GR_METHOD_DILOG, (gr_funcptr) _gr_arb_dilog}, {GR_METHOD_BESSEL_J, (gr_funcptr) _gr_arb_bessel_j}, {GR_METHOD_BESSEL_Y, (gr_funcptr) _gr_arb_bessel_y}, {GR_METHOD_BESSEL_I, (gr_funcptr) _gr_arb_bessel_i}, {GR_METHOD_BESSEL_K, (gr_funcptr) _gr_arb_bessel_k}, {GR_METHOD_BESSEL_J_Y, (gr_funcptr) _gr_arb_bessel_j_y}, {GR_METHOD_BESSEL_I_SCALED, (gr_funcptr) _gr_arb_bessel_i_scaled}, {GR_METHOD_BESSEL_K_SCALED, (gr_funcptr) _gr_arb_bessel_k_scaled}, {GR_METHOD_AIRY, (gr_funcptr) _gr_arb_airy}, {GR_METHOD_AIRY_AI, (gr_funcptr) _gr_arb_airy_ai}, {GR_METHOD_AIRY_BI, (gr_funcptr) _gr_arb_airy_bi}, {GR_METHOD_AIRY_AI_PRIME, (gr_funcptr) _gr_arb_airy_ai_prime}, {GR_METHOD_AIRY_BI_PRIME, (gr_funcptr) _gr_arb_airy_bi_prime}, {GR_METHOD_AIRY_AI_ZERO, (gr_funcptr) _gr_arb_airy_ai_zero}, {GR_METHOD_AIRY_BI_ZERO, (gr_funcptr) _gr_arb_airy_bi_zero}, {GR_METHOD_AIRY_AI_PRIME_ZERO, (gr_funcptr) _gr_arb_airy_ai_prime_zero}, {GR_METHOD_AIRY_BI_PRIME_ZERO, (gr_funcptr) _gr_arb_airy_bi_prime_zero}, {GR_METHOD_COULOMB, (gr_funcptr) _gr_arb_coulomb}, {GR_METHOD_COULOMB_F, (gr_funcptr) _gr_arb_coulomb_f}, {GR_METHOD_COULOMB_G, (gr_funcptr) _gr_arb_coulomb_g}, {GR_METHOD_COULOMB_HNEG, (gr_funcptr) _gr_arb_coulomb_hneg}, {GR_METHOD_COULOMB_HPOS, (gr_funcptr) _gr_arb_coulomb_hpos}, {GR_METHOD_CHEBYSHEV_T, (gr_funcptr) _gr_arb_chebyshev_t}, {GR_METHOD_CHEBYSHEV_U, (gr_funcptr) _gr_arb_chebyshev_u}, {GR_METHOD_JACOBI_P, (gr_funcptr) _gr_arb_jacobi_p}, {GR_METHOD_GEGENBAUER_C, (gr_funcptr) _gr_arb_gegenbauer_c}, {GR_METHOD_LAGUERRE_L, (gr_funcptr) _gr_arb_laguerre_l}, {GR_METHOD_HERMITE_H, (gr_funcptr) _gr_arb_hermite_h}, {GR_METHOD_LEGENDRE_P, (gr_funcptr) _gr_arb_legendre_p}, {GR_METHOD_LEGENDRE_Q, (gr_funcptr) _gr_arb_legendre_q}, {GR_METHOD_LEGENDRE_P_ROOT_UI, (gr_funcptr) _gr_arb_legendre_p_root_ui}, {GR_METHOD_HYPGEOM_0F1, (gr_funcptr) _gr_arb_hypgeom_0f1}, {GR_METHOD_HYPGEOM_1F1, (gr_funcptr) _gr_arb_hypgeom_1f1}, {GR_METHOD_HYPGEOM_U, (gr_funcptr) _gr_arb_hypgeom_u}, {GR_METHOD_HYPGEOM_2F1, (gr_funcptr) _gr_arb_hypgeom_2f1}, {GR_METHOD_HYPGEOM_PFQ, (gr_funcptr) _gr_arb_hypgeom_pfq}, {GR_METHOD_ZETA, (gr_funcptr) _gr_arb_zeta}, {GR_METHOD_POLYLOG, (gr_funcptr) _gr_arb_polylog}, {GR_METHOD_HURWITZ_ZETA, (gr_funcptr) _gr_arb_hurwitz_zeta}, {GR_METHOD_AGM, (gr_funcptr) _gr_arb_agm}, {GR_METHOD_AGM1, (gr_funcptr) _gr_arb_agm1}, {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_arb_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_arb_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_arb_poly_mullow}, {GR_METHOD_POLY_TAYLOR_SHIFT, (gr_funcptr) _gr_arb_poly_taylor_shift}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_arb_poly_roots}, {GR_METHOD_POLY_ROOTS_OTHER,(gr_funcptr) _gr_arb_poly_roots_other}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_arb_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) _gr_arb_mat_det}, {GR_METHOD_MAT_EXP, (gr_funcptr) _gr_arb_mat_exp}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_real_arb(gr_ctx_t ctx, slong prec) { ctx->which_ring = GR_CTX_RR_ARB; ctx->sizeof_elem = sizeof(arb_struct); ctx->size_limit = WORD_MAX; ARB_CTX_PREC(ctx) = FLINT_MAX(2, FLINT_MIN(prec, WORD_MAX / 8)); ctx->methods = _arb_methods; if (!_arb_methods_initialized) { gr_method_tab_init(_arb_methods, _arb_methods_input); _arb_methods_initialized = 1; } } flint-3.1.3/src/gr/arf.c000066400000000000000000001041141461254215100147470ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" #include "arb_poly.h" #include "acb.h" #include "arb_fmpz_poly.h" #include "gr.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_generic.h" typedef struct { slong prec; arf_rnd_t rnd; } gr_arf_ctx; #define ARF_CTX_PREC(ring_ctx) (((gr_arf_ctx *)((ring_ctx)))->prec) #define ARF_CTX_RND(ring_ctx) (((gr_arf_ctx *)((ring_ctx)))->rnd) int _gr_arf_ctx_set_real_prec(gr_ctx_t ctx, slong prec) { prec = FLINT_MAX(prec, 2); prec = FLINT_MIN(prec, WORD_MAX / 8); ARF_CTX_PREC(ctx) = prec; return GR_SUCCESS; } int _gr_arf_ctx_get_real_prec(slong * res, gr_ctx_t ctx) { *res = ARF_CTX_PREC(ctx); return GR_SUCCESS; } int _gr_arf_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Floating-point numbers (arf, prec = "); gr_stream_write_si(out, ARF_CTX_PREC(ctx)); gr_stream_write(out, ")"); return GR_SUCCESS; } void _gr_arf_init(arf_t x, const gr_ctx_t ctx) { arf_init(x); } void _gr_arf_clear(arf_t x, const gr_ctx_t ctx) { arf_clear(x); } void _gr_arf_swap(arf_t x, arf_t y, const gr_ctx_t ctx) { arf_t t; *t = *x; *x = *y; *y = *t; } void _gr_arf_set_shallow(arf_t res, const arf_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_arf_randtest(arf_t res, flint_rand_t state, const gr_ctx_t ctx) { arf_randtest(res, state, ARF_CTX_PREC(ctx), 10); return GR_SUCCESS; } /* todo */ int _gr_arf_write(gr_stream_t out, const arf_t x, const gr_ctx_t ctx) { gr_stream_write_free(out, arf_get_str(x, ARF_CTX_PREC(ctx) * 0.30102999566398 + 1)); return GR_SUCCESS; } int _gr_arf_zero(arf_t x, const gr_ctx_t ctx) { arf_zero(x); return GR_SUCCESS; } int _gr_arf_one(arf_t x, const gr_ctx_t ctx) { arf_one(x); return GR_SUCCESS; } int _gr_arf_set_si(arf_t res, slong v, const gr_ctx_t ctx) { arf_set_round_si(res, v, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_set_ui(arf_t res, ulong v, const gr_ctx_t ctx) { arf_set_round_ui(res, v, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_set_fmpz(arf_t res, const fmpz_t v, const gr_ctx_t ctx) { arf_set_round_fmpz(res, v, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_set_fmpq(arf_t res, const fmpq_t v, const gr_ctx_t ctx) { arf_set_fmpq(res, v, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_set_d(arf_t res, double x, const gr_ctx_t ctx) { arf_set_d(res, x); return GR_SUCCESS; } /* todo: set_round? */ int _gr_arf_set(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_set(res, x); return GR_SUCCESS; } int _gr_arf_set_str(arf_t res, const char * x, gr_ctx_t ctx) { int status; arb_t t; arb_init(t); if (!arb_set_str(t, x, ARF_CTX_PREC(ctx) + 20)) { arf_set_round(res, arb_midref(t), ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); status = GR_SUCCESS; } else { status = gr_generic_set_str_ring_exponents(res, x, ctx); } arb_clear(t); return status; } int _gr_arf_set_other(arf_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: return _gr_arf_set_fmpz(res, x, ctx); case GR_CTX_FMPQ: return _gr_arf_set_fmpq(res, x, ctx); case GR_CTX_REAL_FLOAT_ARF: return _gr_arf_set(res, x, ctx); case GR_CTX_RR_ARB: return _gr_arf_set(res, arb_midref((arb_srcptr) x), ctx); default: { gr_ctx_t cctx; acb_t z; int status; gr_ctx_init_complex_acb(cctx, ARF_CTX_PREC(ctx) + 20); acb_init(z); status = gr_set_other(z, x, x_ctx, cctx); if (status == GR_SUCCESS) { if (acb_is_real(z)) status = _gr_arf_set(res, arb_midref(acb_realref(z)), ctx); else status = GR_DOMAIN; } acb_clear(z); gr_ctx_clear(cctx); return status; } } } int _gr_arf_get_fmpz(fmpz_t res, const arf_t x, const gr_ctx_t ctx) { if (!arf_is_int(x)) return GR_DOMAIN; /* todo: detect mpz overflow */ if (arf_cmpabs_2exp_si(x, WORD_MAX) >= 0) return GR_UNABLE; arf_get_fmpz(res, x, ARF_RND_DOWN); return GR_SUCCESS; } int _gr_arf_get_si(slong * res, const arf_t x, const gr_ctx_t ctx) { fmpz_t t; if (!arf_is_int(x)) return GR_DOMAIN; if (arf_cmp_si(x, WORD_MIN) < 0 || arf_cmp_si(x, WORD_MAX) > 0) return GR_DOMAIN; fmpz_init(t); arf_get_fmpz(t, x, ARF_RND_DOWN); *res = fmpz_get_si(t); fmpz_clear(t); return GR_SUCCESS; } int _gr_arf_get_ui(ulong * res, const arf_t x, const gr_ctx_t ctx) { fmpz_t t; if (!arf_is_int(x)) return GR_DOMAIN; if (arf_sgn(x) < 0 || arf_cmp_ui(x, UWORD_MAX) > 0) return GR_DOMAIN; fmpz_init(t); arf_get_fmpz(t, x, ARF_RND_DOWN); *res = fmpz_get_ui(t); fmpz_clear(t); return GR_SUCCESS; } int _gr_arf_get_d(double * res, const arf_t x, const gr_ctx_t ctx) { *res = arf_get_d(x, ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_get_fmpq(fmpq_t res, const arf_t x, const gr_ctx_t ctx) { if (!arf_is_finite(x)) return GR_DOMAIN; if (!ARF_IS_LAGOM(x)) return GR_UNABLE; arf_get_fmpq(res, x); return GR_SUCCESS; } truth_t _gr_arf_is_zero(const arf_t x, const gr_ctx_t ctx) { return arf_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_arf_is_one(const arf_t x, const gr_ctx_t ctx) { return arf_is_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_arf_is_neg_one(const arf_t x, const gr_ctx_t ctx) { return arf_equal_si(x, -1) ? T_TRUE : T_FALSE; } truth_t _gr_arf_equal(const arf_t x, const arf_t y, const gr_ctx_t ctx) { if (arf_is_nan(x) || arf_is_nan(y)) return T_FALSE; return arf_equal(x, y) ? T_TRUE : T_FALSE; } /* todo: neg_round? */ int _gr_arf_neg(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_neg(res, x); return GR_SUCCESS; } int _gr_arf_add(arf_t res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { arf_add(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_add_si(arf_t res, const arf_t x, slong y, const gr_ctx_t ctx) { arf_add_si(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_add_ui(arf_t res, const arf_t x, ulong y, const gr_ctx_t ctx) { arf_add_ui(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_add_fmpz(arf_t res, const arf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_add_fmpz(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_sub(arf_t res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { arf_sub(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_sub_si(arf_t res, const arf_t x, slong y, const gr_ctx_t ctx) { arf_sub_si(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_sub_ui(arf_t res, const arf_t x, ulong y, const gr_ctx_t ctx) { arf_sub_ui(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_sub_fmpz(arf_t res, const arf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_sub_fmpz(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_mul(arf_t res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { arf_mul(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_mul_si(arf_t res, const arf_t x, slong y, const gr_ctx_t ctx) { arf_mul_si(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_mul_ui(arf_t res, const arf_t x, ulong y, const gr_ctx_t ctx) { arf_mul_ui(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_mul_fmpz(arf_t res, const arf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_mul_fmpz(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_addmul(arf_t res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { arf_addmul(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_submul(arf_t res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { arf_submul(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_mul_two(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_mul_2exp_si(res, x, 1); return GR_SUCCESS; } int _gr_arf_sqr(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_mul(res, x, x, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_mul_2exp_si(arf_t res, const arf_t x, slong y, const gr_ctx_t ctx) { arf_mul_2exp_si(res, x, y); return GR_SUCCESS; } int _gr_arf_mul_2exp_fmpz(arf_t res, const arf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_mul_2exp_fmpz(res, x, y); return GR_SUCCESS; } int _gr_arf_set_fmpz_2exp_fmpz(arf_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_set_fmpz_2exp(res, x, y); return GR_SUCCESS; } int _gr_arf_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, const arf_t x, const gr_ctx_t ctx) { if (!arf_is_finite(x)) return GR_DOMAIN; arf_get_fmpz_2exp(res1, res2, x); return GR_SUCCESS; } int _gr_arf_inv(arf_t res, const arf_t x, const gr_ctx_t ctx) { /* todo */ arf_ui_div(res, 1, x, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_div(arf_t res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { arf_div(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_div_si(arf_t res, const arf_t x, slong y, const gr_ctx_t ctx) { arf_div_si(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_div_ui(arf_t res, const arf_t x, ulong y, const gr_ctx_t ctx) { arf_div_ui(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_div_fmpz(arf_t res, const arf_t x, const fmpz_t y, const gr_ctx_t ctx) { arf_div_fmpz(res, x, y, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_sqrt(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_sqrt(res, x, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_pos_inf(arf_t res, const gr_ctx_t ctx) { arf_pos_inf(res); return GR_SUCCESS; } int _gr_arf_neg_inf(arf_t res, const gr_ctx_t ctx) { arf_neg_inf(res); return GR_SUCCESS; } int _gr_arf_nan(arf_t res, const gr_ctx_t ctx) { arf_nan(res); return GR_SUCCESS; } int _gr_arf_abs(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_abs(res, x); return GR_SUCCESS; } int _gr_arf_conj(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_set(res, x); return GR_SUCCESS; } int _gr_arf_im(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_zero(res); return GR_SUCCESS; } /* todo: sign of nan? */ int _gr_arf_sgn(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_set_si(res, arf_sgn(x)); return GR_SUCCESS; } int _gr_arf_rsqrt(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_rsqrt(res, x, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_floor(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_floor(res, x); return GR_SUCCESS; } int _gr_arf_ceil(arf_t res, const arf_t x, const gr_ctx_t ctx) { arf_ceil(res, x); return GR_SUCCESS; } int _gr_arf_trunc(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_int(x) || arf_is_special(x)) { arf_set(res, x); } else { fmpz_t t; fmpz_init(t); arf_get_fmpz(t, x, ARF_RND_DOWN); arf_set_fmpz(res, t); fmpz_clear(t); } return GR_SUCCESS; } int _gr_arf_nint(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_int(x) || arf_is_special(x)) { arf_set(res, x); } else { fmpz_t t; fmpz_init(t); arf_get_fmpz(t, x, ARF_RND_NEAR); arf_set_fmpz(res, t); fmpz_clear(t); } return GR_SUCCESS; } /* todo: handling nan */ int _gr_arf_cmp(int * res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { *res = arf_cmp(x, y); return GR_SUCCESS; } int _gr_arf_cmpabs(int * res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { *res = arf_cmpabs(x, y); return GR_SUCCESS; } #define ARF_FUNC_VIA_ARB(res, arb_func, x) \ arb_t r, t; \ slong prec, wp, extra; \ int status = GR_SUCCESS; \ prec = ARF_CTX_PREC(ctx); \ arb_init(r); \ *arb_midref(t) = *x; \ mag_init(arb_radref(t)); \ for (extra = 10 + prec * 0.01; ; extra += FLINT_MAX(extra, 32)) \ { \ wp = prec + extra; \ if (wp > 10 * prec + 1000) \ { \ status = GR_UNABLE; \ arf_nan(res); \ break; \ } \ arb_func(r, t, wp); \ if (arb_rel_accuracy_bits(r) >= prec) \ { \ arf_set_round(res, arb_midref(r), prec, ARF_CTX_RND(ctx)); \ break; \ } \ } \ arb_clear(r); \ return status; \ #define ARF_FUNC2_VIA_ARB(res, arb_func, x, y) \ arb_t r, t, u; \ slong prec, wp, extra; \ int status = GR_SUCCESS; \ prec = ARF_CTX_PREC(ctx); \ arb_init(r); \ *arb_midref(t) = *x; \ mag_init(arb_radref(t)); \ *arb_midref(u) = *y; \ mag_init(arb_radref(u)); \ for (extra = 10 + prec * 0.01; ; extra += FLINT_MAX(extra, 32)) \ { \ wp = prec + extra; \ if (wp > 10 * prec + 1000) \ { \ status = GR_UNABLE; \ arf_nan(res); \ break; \ } \ arb_func(r, t, u, wp); \ if (arb_rel_accuracy_bits(r) >= prec) \ { \ arf_set_round(res, arb_midref(r), prec, ARF_CTX_RND(ctx)); \ break; \ } \ } \ arb_clear(r); \ return status; \ /* todo: lots of special cases */ int _gr_arf_pow(arf_t res, const arf_t x, const arf_t y, const gr_ctx_t ctx) { if (!arf_is_finite(x) || !arf_is_finite(y) || (arf_is_zero(x) && arf_sgn(y) < 0) || (arf_sgn(x) < 0 && !arf_is_int(y))) { arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC2_VIA_ARB(res, arb_pow, x, y) } } int _gr_arf_pi(arf_t res, const gr_ctx_t ctx) { arb_t t; arb_init(t); arb_const_pi(t, ARF_CTX_PREC(ctx) + 30); arf_set_round(res, arb_midref(t), ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); arb_clear(t); return GR_SUCCESS; } int _gr_arf_exp(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_one(res); else if (arf_is_pos_inf(x)) arf_pos_inf(res); else if (arf_is_neg_inf(x)) arf_zero(res); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_exp, x) } } int _gr_arf_expm1(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_zero(res); else if (arf_is_pos_inf(x)) arf_pos_inf(res); else if (arf_is_neg_inf(x)) arf_set_si(res, -1); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_expm1, x) } } int _gr_arf_log(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_neg_inf(res); else if (arf_is_pos_inf(x)) arf_pos_inf(res); else arf_nan(res); return GR_SUCCESS; } else if (arf_sgn(x) < 0) { arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_log, x) } } int _gr_arf_log1p(arf_t res, const arf_t x, const gr_ctx_t ctx) { int cmp; if (arf_is_special(x)) { if (arf_is_zero(x)) arf_zero(res); else if (arf_is_pos_inf(x)) arf_pos_inf(res); else arf_nan(res); return GR_SUCCESS; } cmp = arf_cmp_si(x, -1); if (cmp == 0) { arf_neg_inf(res); return GR_SUCCESS; } if (cmp < 0) { arf_nan(res); return GR_SUCCESS; } { ARF_FUNC_VIA_ARB(res, arb_log1p, x) } } int _gr_arf_sin(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_zero(res); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_sin, x) } } int _gr_arf_cos(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_one(res); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_cos, x) } } int _gr_arf_tan(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_zero(res); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_tan, x) } } int _gr_arf_atan(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) { arf_zero(res); } else if (arf_is_pos_inf(x)) { _gr_arf_pi(res, ctx); arf_mul_2exp_si(res, res, -1); } else if (arf_is_neg_inf(x)) { _gr_arf_pi(res, ctx); arf_mul_2exp_si(res, res, -1); arf_neg(res, res); } else { arf_nan(res); } return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_atan, x) } } int _gr_arf_sinh(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_zero(res); else if (arf_is_inf(x)) arf_set(res, x); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_sinh, x) } } int _gr_arf_cosh(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_one(res); else if (arf_is_inf(x)) arf_pos_inf(res); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_cosh, x) } } int _gr_arf_tanh(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_zero(res); else if (arf_is_inf(x)) arf_set_si(res, arf_sgn(x)); else arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_tanh, x) } } /* todo: configurable function to return pole */ int _gr_arf_gamma(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (arf_is_special(x)) { if (arf_is_zero(x)) arf_pos_inf(res); else if (arf_is_pos_inf(x)) arf_pos_inf(res); else arf_nan(res); return GR_SUCCESS; } else if (arf_sgn(x) < 0 && arf_is_int(x)) { arf_pos_inf(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_gamma, x) } } int _gr_arf_zeta(arf_t res, const arf_t x, const gr_ctx_t ctx) { if (!arf_is_finite(x)) { if (arf_is_pos_inf(x)) arf_one(res); else arf_nan(res); return GR_SUCCESS; } else if (arf_is_one(x)) { arf_nan(res); return GR_SUCCESS; } else { ARF_FUNC_VIA_ARB(res, arb_zeta, x) } } /* for benchmarking int _gr_arf_vec_add(arf_ptr res, arf_srcptr vec1, arf_srcptr vec2, slong len, gr_ctx_t ctx) { slong i; slong prec = ARF_CTX_PREC(ctx); arf_rnd_t rnd = ARF_CTX_RND(ctx); for (i = 0; i < len; i++) arf_add(res + i, vec1 + i, vec2 + i, prec, rnd); return GR_SUCCESS; } int _gr_arf_vec_sub(arf_ptr res, arf_srcptr vec1, arf_srcptr vec2, slong len, gr_ctx_t ctx) { slong i; slong prec = ARF_CTX_PREC(ctx); arf_rnd_t rnd = ARF_CTX_RND(ctx); for (i = 0; i < len; i++) arf_sub(res + i, vec1 + i, vec2 + i, prec, rnd); return GR_SUCCESS; } */ int _gr_arf_vec_dot(arf_t res, const arf_t initial, int subtract, arf_srcptr vec1, arf_srcptr vec2, slong len, gr_ctx_t ctx) { arf_approx_dot(res, initial, subtract, vec1, 1, vec2, 1, len, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } int _gr_arf_vec_dot_rev(arf_t res, const arf_t initial, int subtract, arf_srcptr vec1, arf_srcptr vec2, slong len, gr_ctx_t ctx) { arf_approx_dot(res, initial, subtract, vec1, 1, vec2 + len - 1, -1, len, ARF_CTX_PREC(ctx), ARF_CTX_RND(ctx)); return GR_SUCCESS; } #include "gr_poly.h" #include "acb_poly.h" /* todo: test */ int _gr_arf_poly_mullow(arf_ptr res, arf_srcptr poly1, slong len1, arf_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); /* todo: tuning */ if (len1 <= 10 || len2 <= 10) { return _gr_poly_mullow_generic(res, poly1, len1, poly2, len2, n, ctx); } else { arb_ptr tmp, t1, t2, t3; slong i; int squaring = (poly1 == poly2 && len1 == len2); if (!squaring) { tmp = flint_malloc(sizeof(arb_struct) * (len1 + len2 + n)); t1 = tmp; t2 = t1 + len1; t3 = t2 + len2; } else { tmp = flint_malloc(sizeof(arb_struct) * (len1 + n)); t1 = tmp; t2 = t1; t3 = t2 + len2; } for (i = 0; i < len1; i++) { *arb_midref(t1 + i) = *(poly1 + i); mag_init(arb_radref(t1 + i)); } if (!squaring) { for (i = 0; i < len2; i++) { *arb_midref(t2 + i) = *(poly2 + i); mag_init(arb_radref(t2 + i)); } } for (i = 0; i < n; i++) { *arb_midref(t3 + i) = *(res + i); mag_init(arb_radref(t3 + i)); } _arb_poly_mullow(t3, t1, len1, t2, len2, n, ARF_CTX_PREC(ctx)); for (i = 0; i < n; i++) { *(res + i) = *arb_midref(t3 + i); mag_clear(arb_radref(t3 + i)); } flint_free(tmp); return GR_SUCCESS; } } /* todo: real-only roots in arb */ int _gr_arf_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t other_ctx, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; if (other_ctx->which_ring == GR_CTX_FMPZ) { gr_ctx_t ZZ; slong i, j, deg, deg2; acb_ptr croots; int status = GR_SUCCESS; deg = poly->length - 1; gr_ctx_init_fmpz(ZZ); gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); if (deg != 0) { fmpz_poly_factor_t fac; fmpz_poly_factor_init(fac); fmpz_poly_factor_squarefree(fac, (const fmpz_poly_struct *) poly); for (i = 0; i < fac->num; i++) { deg2 = fmpz_poly_degree(fac->p + i); croots = _acb_vec_init(deg2); arb_fmpz_poly_complex_roots(croots, fac->p + i, 0, ARF_CTX_PREC(ctx)); for (j = 0; j < deg2; j++) { if (acb_is_real(croots + j)) { fmpz m2 = fac->exp[i]; GR_MUST_SUCCEED(gr_vec_append(roots, arb_midref(acb_realref(croots + j)), ctx)); GR_MUST_SUCCEED(gr_vec_append(mult, &m2, ZZ)); } } _acb_vec_clear(croots, deg2); } fmpz_poly_factor_clear(fac); } gr_ctx_clear(ZZ); return status; } return GR_UNABLE; } #include "gr_mat.h" #include "arb_mat.h" /* todo: test */ int _gr_arf_mat_mul(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong prec; slong cutoff; prec = ARF_CTX_PREC(ctx); /* todo: detect small-integer matrices */ if (prec <= 2 * FLINT_BITS) cutoff = 120; else if (prec <= 16 * FLINT_BITS) cutoff = 60; else cutoff = 40; if (A->r <= cutoff || A->c <= cutoff || B->c <= cutoff) { return gr_mat_mul_classical(C, A, B, ctx); } else { /* todo: direct algorithm, avoiding copies */ arb_mat_t RC, RB, RA; slong i, j; arf_t zero; arb_mat_init(RA, A->r, A->c); arb_mat_init(RB, B->r, B->c); arb_mat_init(RC, C->r, C->c); arf_init(zero); for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) *arb_midref(arb_mat_entry(RA, i, j)) = ((arf_srcptr) A->rows[i])[j]; for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) *arb_midref(arb_mat_entry(RB, i, j)) = ((arf_srcptr) B->rows[i])[j]; arb_mat_approx_mul(RC, RA, RB, prec); for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) *arb_midref(arb_mat_entry(RA, i, j)) = *zero; for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) *arb_midref(arb_mat_entry(RB, i, j)) = *zero; for (i = 0; i < C->r; i++) for (j = 0; j < C->c; j++) arf_swap(((arf_ptr) C->rows[i]) + j, arb_midref(arb_mat_entry(RC, i, j))); arb_mat_clear(RA); arb_mat_clear(RB); arb_mat_clear(RC); return GR_SUCCESS; } } int _arf_methods_initialized = 0; gr_static_method_table _arf_methods; gr_method_tab_input _arf_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_arf_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_HAS_REAL_PREC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_REAL_PREC, (gr_funcptr) _gr_arf_ctx_set_real_prec}, {GR_METHOD_CTX_GET_REAL_PREC, (gr_funcptr) _gr_arf_ctx_get_real_prec}, {GR_METHOD_INIT, (gr_funcptr) _gr_arf_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_arf_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_arf_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_arf_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_arf_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_arf_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_arf_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_arf_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_arf_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_arf_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_arf_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_arf_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_arf_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_arf_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_arf_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_arf_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_arf_set_fmpq}, {GR_METHOD_SET_D, (gr_funcptr) _gr_arf_set_d}, {GR_METHOD_SET_STR, (gr_funcptr) _gr_arf_set_str}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_arf_set_other}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_arf_get_fmpz}, {GR_METHOD_GET_FMPQ, (gr_funcptr) _gr_arf_get_fmpq}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_arf_get_ui}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_arf_get_si}, {GR_METHOD_GET_D, (gr_funcptr) _gr_arf_get_d}, {GR_METHOD_NEG, (gr_funcptr) _gr_arf_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_arf_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_arf_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_arf_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_arf_add_fmpz}, {GR_METHOD_SUB, (gr_funcptr) _gr_arf_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_arf_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_arf_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_arf_sub_fmpz}, {GR_METHOD_MUL, (gr_funcptr) _gr_arf_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_arf_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_arf_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_arf_mul_fmpz}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_arf_mul_two}, {GR_METHOD_ADDMUL, (gr_funcptr) _gr_arf_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_arf_submul}, {GR_METHOD_SQR, (gr_funcptr) _gr_arf_sqr}, {GR_METHOD_DIV, (gr_funcptr) _gr_arf_div}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_arf_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_arf_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_arf_div_fmpz}, {GR_METHOD_INV, (gr_funcptr) _gr_arf_inv}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) _gr_arf_mul_2exp_si}, {GR_METHOD_MUL_2EXP_FMPZ, (gr_funcptr) _gr_arf_mul_2exp_fmpz}, {GR_METHOD_SET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_arf_set_fmpz_2exp_fmpz}, {GR_METHOD_GET_FMPZ_2EXP_FMPZ, (gr_funcptr) _gr_arf_get_fmpz_2exp_fmpz}, {GR_METHOD_POW, (gr_funcptr) _gr_arf_pow}, /* {GR_METHOD_POW_UI, (gr_funcptr) _gr_arf_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_arf_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_arf_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_arf_pow_fmpq}, */ {GR_METHOD_SQRT, (gr_funcptr) _gr_arf_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_arf_rsqrt}, {GR_METHOD_POS_INF, (gr_funcptr) _gr_arf_pos_inf}, {GR_METHOD_NEG_INF, (gr_funcptr) _gr_arf_neg_inf}, {GR_METHOD_UINF, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_UNDEFINED, (gr_funcptr) _gr_arf_nan}, {GR_METHOD_UNKNOWN, (gr_funcptr) _gr_arf_nan}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_arf_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_arf_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_arf_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_arf_nint}, {GR_METHOD_ABS, (gr_funcptr) _gr_arf_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_arf_conj}, {GR_METHOD_RE, (gr_funcptr) _gr_arf_set}, {GR_METHOD_IM, (gr_funcptr) _gr_arf_im}, {GR_METHOD_SGN, (gr_funcptr) _gr_arf_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_arf_sgn}, {GR_METHOD_CMP, (gr_funcptr) _gr_arf_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) _gr_arf_cmpabs}, {GR_METHOD_I, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_PI, (gr_funcptr) _gr_arf_pi}, {GR_METHOD_EXP, (gr_funcptr) _gr_arf_exp}, {GR_METHOD_EXPM1, (gr_funcptr) _gr_arf_expm1}, {GR_METHOD_LOG, (gr_funcptr) _gr_arf_log}, {GR_METHOD_LOG1P, (gr_funcptr) _gr_arf_log1p}, {GR_METHOD_SIN, (gr_funcptr) _gr_arf_sin}, {GR_METHOD_COS, (gr_funcptr) _gr_arf_cos}, {GR_METHOD_TAN, (gr_funcptr) _gr_arf_tan}, {GR_METHOD_SINH, (gr_funcptr) _gr_arf_sinh}, {GR_METHOD_COSH, (gr_funcptr) _gr_arf_cosh}, {GR_METHOD_TANH, (gr_funcptr) _gr_arf_tanh}, {GR_METHOD_ATAN, (gr_funcptr) _gr_arf_atan}, {GR_METHOD_GAMMA, (gr_funcptr) _gr_arf_gamma}, {GR_METHOD_ZETA, (gr_funcptr) _gr_arf_zeta}, /* {GR_METHOD_VEC_ADD, (gr_funcptr) _gr_arf_vec_add}, {GR_METHOD_VEC_SUB, (gr_funcptr) _gr_arf_vec_sub}, */ {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_arf_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_arf_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_arf_poly_mullow}, {GR_METHOD_POLY_ROOTS_OTHER,(gr_funcptr) _gr_arf_poly_roots_other}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_arf_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) gr_mat_det_generic_field}, {GR_METHOD_MAT_FIND_NONZERO_PIVOT, (gr_funcptr) gr_mat_find_nonzero_pivot_large_abs}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_real_float_arf(gr_ctx_t ctx, slong prec) { ctx->which_ring = GR_CTX_REAL_FLOAT_ARF; ctx->sizeof_elem = sizeof(arf_struct); ctx->size_limit = WORD_MAX; ARF_CTX_PREC(ctx) = FLINT_MAX(2, FLINT_MIN(prec, WORD_MAX / 8)); ARF_CTX_RND(ctx) = ARF_RND_NEAR; ctx->methods = _arf_methods; if (!_arf_methods_initialized) { gr_method_tab_init(_arf_methods, _arf_methods_input); _arf_methods_initialized = 1; } } flint-3.1.3/src/gr/ca.c000066400000000000000000001337311461254215100145710ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpzi.h" #include "ca.h" #include "ca_mat.h" #include "ca_poly.h" #include "fexpr.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_special.h" #define GR_CA_CTX(ring_ctx) ((ca_ctx_struct *)(GR_CTX_DATA_AS_PTR(ring_ctx))) int _gr_ca_ctx_write(gr_stream_t out, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_RR_CA) gr_stream_write(out, "Real numbers (ca)"); else if (ctx->which_ring == GR_CTX_CC_CA) gr_stream_write(out, "Complex numbers (ca)"); else if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) gr_stream_write(out, "Real algebraic numbers (ca)"); else if (ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) gr_stream_write(out, "Complex algebraic numbers (ca)"); else if (ctx->which_ring == GR_CTX_COMPLEX_EXTENDED_CA) gr_stream_write(out, "Complex numbers + extended values (ca)"); return GR_SUCCESS; } void gr_ctx_ca_set_option(gr_ctx_t ctx, slong option, slong value) { ca_ctx_set_option(GR_CA_CTX(ctx), option, value); } slong gr_ctx_ca_get_option(gr_ctx_t ctx, slong option) { return ca_ctx_get_option(GR_CA_CTX(ctx), option); } void _gr_ca_init(ca_t x, gr_ctx_t ctx) { ca_init(x, GR_CA_CTX(ctx)); } void _gr_ca_clear(ca_t x, gr_ctx_t ctx) { ca_clear(x, GR_CA_CTX(ctx)); } void _gr_ca_swap(ca_t x, ca_t y, gr_ctx_t ctx) { ca_t t; *t = *x; *x = *y; *y = *t; } void _gr_ca_set_shallow(ca_t res, const ca_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ /* todo: faster real/algebraic constructions */ int _gr_ca_randtest(ca_t res, flint_rand_t state, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_COMPLEX_EXTENDED_CA) { ca_randtest_special(res, state, 2, 10, GR_CA_CTX(ctx)); } else { ca_randtest(res, state, 2, 10, GR_CA_CTX(ctx)); if (ctx->which_ring == GR_CTX_RR_CA) { if (ca_check_is_real(res, GR_CA_CTX(ctx)) != T_TRUE) { ca_randtest_rational(res, state, 10, GR_CA_CTX(ctx)); } } else if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) { if (ca_check_is_real(res, GR_CA_CTX(ctx)) != T_TRUE || ca_check_is_algebraic(res, GR_CA_CTX(ctx)) != T_TRUE) { ca_randtest_rational(res, state, 10, GR_CA_CTX(ctx)); } } else if (ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { if (ca_check_is_algebraic(res, GR_CA_CTX(ctx)) != T_TRUE) { ca_randtest_rational(res, state, 10, GR_CA_CTX(ctx)); } } } return GR_SUCCESS; } /* todo */ int _gr_ca_write(gr_stream_t out, const ca_t x, gr_ctx_t ctx) { gr_stream_write_free(out, ca_get_str(x, GR_CA_CTX(ctx))); return GR_SUCCESS; } int _gr_ca_zero(ca_t x, gr_ctx_t ctx) { ca_zero(x, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_one(ca_t x, gr_ctx_t ctx) { ca_one(x, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_set_si(ca_t res, slong v, gr_ctx_t ctx) { ca_set_si(res, v, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_set_ui(ca_t res, ulong v, gr_ctx_t ctx) { ca_set_ui(res, v, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_set_fmpz(ca_t res, const fmpz_t v, gr_ctx_t ctx) { ca_set_fmpz(res, v, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_set_fmpq(ca_t res, const fmpq_t v, gr_ctx_t ctx) { ca_set_fmpq(res, v, GR_CA_CTX(ctx)); return GR_SUCCESS; } void ca_set_fmpzi(ca_t res, const fmpzi_t x, ca_ctx_t ctx) { if (fmpz_is_zero(fmpzi_imagref(x))) { ca_set_fmpz(res, fmpzi_realref(x), ctx); } else { ca_i(res, ctx); ca_mul_fmpz(res, res, fmpzi_imagref(x), ctx); ca_add_fmpz(res, res, fmpzi_realref(x), ctx); } } int _gr_ca_set_other(ca_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { slong target = ctx->which_ring; switch (x_ctx->which_ring) { case GR_CTX_FMPZ: ca_set_fmpz(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; case GR_CTX_FMPQ: ca_set_fmpq(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; case GR_CTX_FMPZI: if (target == GR_CTX_CC_CA || target == GR_CTX_COMPLEX_ALGEBRAIC_CA || target == GR_CTX_COMPLEX_EXTENDED_CA || fmpz_is_zero(fmpzi_imagref((const fmpzi_struct *) x))) { ca_set_fmpzi(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; } else { return GR_DOMAIN; } case GR_CTX_REAL_ALGEBRAIC_QQBAR: ca_set_qqbar(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; case GR_CTX_COMPLEX_ALGEBRAIC_QQBAR: if (target == GR_CTX_CC_CA || target == GR_CTX_COMPLEX_ALGEBRAIC_CA || target == GR_CTX_COMPLEX_EXTENDED_CA || qqbar_is_real(x)) { ca_set_qqbar(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; } else { return GR_DOMAIN; } case GR_CTX_REAL_ALGEBRAIC_CA: ca_transfer(res, GR_CA_CTX(ctx), x, GR_CA_CTX(x_ctx)); return GR_SUCCESS; case GR_CTX_COMPLEX_ALGEBRAIC_CA: { truth_t ok = T_UNKNOWN; if (target == GR_CTX_CC_CA || target == GR_CTX_COMPLEX_ALGEBRAIC_CA || target == GR_CTX_COMPLEX_EXTENDED_CA) { ok = T_TRUE; } else if (target == GR_CTX_RR_CA) { ok = ca_check_is_real(x, GR_CA_CTX(x_ctx)); } else if (target == GR_CTX_REAL_ALGEBRAIC_CA) { ok = truth_and(ca_check_is_algebraic(x, GR_CA_CTX(x_ctx)), ca_check_is_real(x, GR_CA_CTX(x_ctx))); } if (ok == T_TRUE) { ca_transfer(res, GR_CA_CTX(ctx), x, GR_CA_CTX(x_ctx)); return GR_SUCCESS; } return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } case GR_CTX_RR_CA: { truth_t ok = T_UNKNOWN; if (target == GR_CTX_RR_CA || target == GR_CTX_CC_CA || target == GR_CTX_COMPLEX_EXTENDED_CA) { ok = T_TRUE; } else if (target == GR_CTX_REAL_ALGEBRAIC_CA || target == GR_CTX_COMPLEX_ALGEBRAIC_CA) { ok = ca_check_is_algebraic(x, GR_CA_CTX(x_ctx)); } if (ok == T_TRUE) { ca_transfer(res, GR_CA_CTX(ctx), x, GR_CA_CTX(x_ctx)); return GR_SUCCESS; } return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } case GR_CTX_CC_CA: { truth_t ok = T_UNKNOWN; if (target == GR_CTX_CC_CA || target == GR_CTX_COMPLEX_EXTENDED_CA) { ok = T_TRUE; } else if (target == GR_CTX_RR_CA) { ok = ca_check_is_real(x, GR_CA_CTX(x_ctx)); } else if (target == GR_CTX_COMPLEX_ALGEBRAIC_CA) { ok = ca_check_is_algebraic(x, GR_CA_CTX(x_ctx)); } else if (target == GR_CTX_REAL_ALGEBRAIC_CA) { ok = truth_and(ca_check_is_algebraic(x, GR_CA_CTX(x_ctx)), ca_check_is_real(x, GR_CA_CTX(x_ctx))); } if (ok == T_TRUE) { ca_transfer(res, GR_CA_CTX(ctx), x, GR_CA_CTX(x_ctx)); return GR_SUCCESS; } return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } case GR_CTX_COMPLEX_EXTENDED_CA: { truth_t ok = T_UNKNOWN; if (target == GR_CTX_COMPLEX_EXTENDED_CA) { ok = T_TRUE; } else { if (ca_check_is_undefined(x, GR_CA_CTX(x_ctx)) == T_TRUE || ca_check_is_infinity(x, GR_CA_CTX(x_ctx)) == T_TRUE) { ok = T_FALSE; } else if (ca_is_unknown(x, GR_CA_CTX(x_ctx))) { ok = T_UNKNOWN; } else { if (target == GR_CTX_RR_CA) { ok = ca_check_is_real(x, GR_CA_CTX(x_ctx)); } else if (target == GR_CTX_COMPLEX_ALGEBRAIC_CA) { ok = ca_check_is_algebraic(x, GR_CA_CTX(x_ctx)); } else if (target == GR_CTX_REAL_ALGEBRAIC_CA) { ok = truth_and(ca_check_is_algebraic(x, GR_CA_CTX(x_ctx)), ca_check_is_real(x, GR_CA_CTX(x_ctx))); } else { ok = T_TRUE; } } } if (ok == T_TRUE) { ca_transfer(res, GR_CA_CTX(ctx), x, GR_CA_CTX(x_ctx)); return GR_SUCCESS; } return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } } return gr_generic_set_other(res, x, x_ctx, ctx); } int _gr_ca_get_arb_with_prec(arb_t res, gr_srcptr x, gr_ctx_t x_ctx, slong prec) { int status = GR_UNABLE; truth_t ok; acb_t t; acb_init(t); /* todo: when to use accurate_parts? */ ca_get_acb(t, x, prec, GR_CA_CTX(x_ctx)); if (x_ctx->which_ring == GR_CTX_RR_CA || x_ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || (arb_is_zero(acb_imagref(t)) && arb_is_finite(acb_realref(t)))) { status = GR_SUCCESS; } else { ok = ca_check_is_real(x, GR_CA_CTX(x_ctx)); if (ok == T_TRUE) status = GR_SUCCESS; else status = (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } if (status == GR_SUCCESS) arb_set_round(res, acb_realref(t), prec); acb_clear(t); return status; } int _gr_ca_get_acb_with_prec(acb_t res, gr_srcptr x, gr_ctx_t x_ctx, slong prec) { if (x_ctx->which_ring == GR_CTX_COMPLEX_EXTENDED_CA) { if (ca_check_is_undefined(x, GR_CA_CTX(x_ctx)) == T_TRUE || ca_check_is_infinity(x, GR_CA_CTX(x_ctx)) == T_TRUE) return GR_DOMAIN; if (ca_is_unknown(x, GR_CA_CTX(x_ctx))) return GR_UNABLE; } /* todo: when to use accurate_parts? */ ca_get_acb(res, x, prec, GR_CA_CTX(x_ctx)); acb_set_round(res, res, prec); return GR_SUCCESS; } int _gr_ca_get_fmpz(fmpz_t res, const ca_t x, gr_ctx_t ctx) { truth_t integer; /* todo: avoid duplicate computation */ integer = ca_check_is_integer(x, GR_CA_CTX(ctx)); if (integer == T_TRUE) return ca_get_fmpz(res, x, GR_CA_CTX(ctx)) ? GR_SUCCESS : GR_UNABLE; else if (integer == T_FALSE) return GR_DOMAIN; else return GR_UNABLE; } int _gr_ca_get_si(slong * res, const ca_t x, gr_ctx_t ctx) { fmpz_t n; int status; fmpz_init(n); status = _gr_ca_get_fmpz(n, x, ctx); if (status == GR_SUCCESS) { if (fmpz_fits_si(n)) *res = fmpz_get_si(n); else status = GR_DOMAIN; } fmpz_clear(n); return status; } int _gr_ca_get_ui(ulong * res, const ca_t x, gr_ctx_t ctx) { fmpz_t n; int status; fmpz_init(n); status = _gr_ca_get_fmpz(n, x, ctx); if (status == GR_SUCCESS) { if (fmpz_sgn(n) >= 0 && fmpz_cmp_ui(n, UWORD_MAX) <= 0) *res = fmpz_get_ui(n); else status = GR_DOMAIN; } fmpz_clear(n); return status; } int _gr_ca_get_d(double * res, gr_srcptr x, gr_ctx_t ctx) { arb_t t; int status = GR_UNABLE; arb_init(t); status = _gr_ca_get_arb_with_prec(t, x, ctx, 64); if (status == GR_SUCCESS) *res = arf_get_d(arb_midref(t), ARF_RND_NEAR); arb_clear(t); return status; } int _gr_ca_get_fmpq(fmpq_t res, const ca_t x, gr_ctx_t ctx) { truth_t rational; /* todo: avoid duplicate computation */ rational = ca_check_is_rational(x, GR_CA_CTX(ctx)); if (rational == T_TRUE) return ca_get_fmpq(res, x, GR_CA_CTX(ctx)) ? GR_SUCCESS : GR_UNABLE; else if (rational == T_FALSE) return GR_DOMAIN; else return GR_UNABLE; } int _gr_ca_get_fexpr(fexpr_t res, const ca_t x, gr_ctx_t ctx) { ca_get_fexpr(res, x, 0, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_get_fexpr_serialize(fexpr_t res, const ca_t x, gr_ctx_t ctx) { ca_get_fexpr(res, x, CA_FEXPR_SERIALIZATION, GR_CA_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_ca_is_zero(const ca_t x, gr_ctx_t ctx) { return ca_check_is_zero(x, GR_CA_CTX(ctx)); } truth_t _gr_ca_is_one(const ca_t x, gr_ctx_t ctx) { return ca_check_is_one(x, GR_CA_CTX(ctx)); } truth_t _gr_ca_is_neg_one(const ca_t x, gr_ctx_t ctx) { return ca_check_is_neg_one(x, GR_CA_CTX(ctx)); } truth_t _gr_ca_equal(const ca_t x, const ca_t y, gr_ctx_t ctx) { return ca_check_equal(x, y, GR_CA_CTX(ctx)); } int _gr_ca_set(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_set(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_neg(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_neg(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_add(ca_t res, const ca_t x, const ca_t y, gr_ctx_t ctx) { ca_add(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_add_si(ca_t res, const ca_t x, slong y, gr_ctx_t ctx) { ca_add_si(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_add_ui(ca_t res, const ca_t x, ulong y, gr_ctx_t ctx) { ca_add_ui(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_add_fmpz(ca_t res, const ca_t x, const fmpz_t y, gr_ctx_t ctx) { ca_add_fmpz(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_add_fmpq(ca_t res, const ca_t x, const fmpq_t y, gr_ctx_t ctx) { ca_add_fmpq(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_sub(ca_t res, const ca_t x, const ca_t y, gr_ctx_t ctx) { ca_sub(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_sub_si(ca_t res, const ca_t x, slong y, gr_ctx_t ctx) { ca_sub_si(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_sub_ui(ca_t res, const ca_t x, ulong y, gr_ctx_t ctx) { ca_sub_ui(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_sub_fmpz(ca_t res, const ca_t x, const fmpz_t y, gr_ctx_t ctx) { ca_sub_fmpz(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_sub_fmpq(ca_t res, const ca_t x, const fmpq_t y, gr_ctx_t ctx) { ca_sub_fmpq(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_mul(ca_t res, const ca_t x, const ca_t y, gr_ctx_t ctx) { ca_mul(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_mul_si(ca_t res, const ca_t x, slong y, gr_ctx_t ctx) { ca_mul_si(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_mul_ui(ca_t res, const ca_t x, ulong y, gr_ctx_t ctx) { ca_mul_ui(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_mul_fmpz(ca_t res, const ca_t x, const fmpz_t y, gr_ctx_t ctx) { ca_mul_fmpz(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_mul_fmpq(ca_t res, const ca_t x, const fmpq_t y, gr_ctx_t ctx) { ca_mul_fmpq(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } static int handle_possible_special_value(ca_t res, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_COMPLEX_EXTENDED_CA) return GR_SUCCESS; if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; if (ca_is_special(res, GR_CA_CTX(ctx))) { ca_unknown(res, GR_CA_CTX(ctx)); /* don't output an invalid element */ return GR_DOMAIN; } return GR_SUCCESS; } #define DEF_SPECIAL(name) \ int \ _gr_ca_ ## name(ca_t res, gr_ctx_t ctx) \ { \ if (ctx->which_ring != GR_CTX_COMPLEX_EXTENDED_CA) \ return GR_DOMAIN; \ ca_ ## name(res, GR_CA_CTX(ctx)); \ return GR_SUCCESS; \ } DEF_SPECIAL(pos_inf) DEF_SPECIAL(neg_inf) DEF_SPECIAL(uinf) DEF_SPECIAL(undefined) DEF_SPECIAL(unknown) int _gr_ca_inv(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_inv(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_div(ca_t res, const ca_t x, const ca_t y, gr_ctx_t ctx) { ca_div(res, x, y, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_div_si(ca_t res, const ca_t x, slong y, gr_ctx_t ctx) { ca_div_si(res, x, y, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_div_ui(ca_t res, const ca_t x, ulong y, gr_ctx_t ctx) { ca_div_ui(res, x, y, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_div_fmpz(ca_t res, const ca_t x, const fmpz_t y, gr_ctx_t ctx) { ca_div_fmpz(res, x, y, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_div_fmpq(ca_t res, const ca_t x, const fmpq_t y, gr_ctx_t ctx) { ca_div_fmpq(res, x, y, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } truth_t _gr_ca_is_invertible(const ca_t x, gr_ctx_t ctx) { return truth_not(ca_check_is_zero(x, GR_CA_CTX(ctx))); } int _gr_ca_pow_ui(ca_t res, const ca_t x, ulong exp, gr_ctx_t ctx) { ca_pow_ui(res, x, exp, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_pow_si(ca_t res, const ca_t x, slong exp, gr_ctx_t ctx) { ca_pow_si(res, x, exp, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_pow_fmpz(ca_t res, const ca_t x, const fmpz_t exp, gr_ctx_t ctx) { ca_pow_fmpz(res, x, exp, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_pow_fmpq(ca_t res, const ca_t x, const fmpq_t exp, gr_ctx_t ctx) { ca_pow_fmpq(res, x, exp, GR_CA_CTX(ctx)); if (ctx->which_ring == GR_CTX_RR_CA || ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) { truth_t real; real = ca_check_is_real(res, GR_CA_CTX(ctx)); if (real == T_UNKNOWN) return GR_UNABLE; if (real == T_FALSE) return GR_DOMAIN; } return handle_possible_special_value(res, ctx); } int _gr_ca_pow(ca_t res, const ca_t x, const ca_t exp, gr_ctx_t ctx) { ca_pow(res, x, exp, GR_CA_CTX(ctx)); if (ctx->which_ring == GR_CTX_RR_CA || ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) { truth_t real; real = ca_check_is_real(res, GR_CA_CTX(ctx)); if (real == T_UNKNOWN) return GR_UNABLE; if (real == T_FALSE) return GR_DOMAIN; } if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t algebraic; algebraic = ca_check_is_algebraic(res, GR_CA_CTX(ctx)); if (algebraic == T_UNKNOWN) return GR_UNABLE; if (algebraic == T_FALSE) return GR_DOMAIN; } return handle_possible_special_value(res, ctx); } truth_t _gr_ca_is_square(const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_RR_CA || ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) { return truth_not(ca_check_is_negative_real(x, GR_CA_CTX(ctx))); } else { return T_TRUE; } } int _gr_ca_sqrt(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_sqrt(res, x, GR_CA_CTX(ctx)); if (ctx->which_ring == GR_CTX_RR_CA || ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) { truth_t real; real = ca_check_is_real(res, GR_CA_CTX(ctx)); if (real == T_UNKNOWN) return GR_UNABLE; if (real == T_FALSE) return GR_DOMAIN; } return handle_possible_special_value(res, ctx); } int _gr_ca_rsqrt(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_sqrt(res, x, GR_CA_CTX(ctx)); ca_inv(res, res, GR_CA_CTX(ctx)); if (ctx->which_ring == GR_CTX_RR_CA || ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) { truth_t real; real = ca_check_is_real(res, GR_CA_CTX(ctx)); if (real == T_UNKNOWN) return GR_UNABLE; if (real == T_FALSE) return GR_DOMAIN; } return handle_possible_special_value(res, ctx); } int _gr_ca_floor(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_floor(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } int _gr_ca_ceil(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_ceil(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } /* todo: trunc, nint in calcium */ int _gr_ca_trunc(ca_t res, const ca_t x, gr_ctx_t ctx) { acb_t t; int status; acb_init(t); ca_get_acb(t, x, 64, GR_CA_CTX(ctx)); if (arf_cmpabs_2exp_si(arb_midref(acb_realref(t)), -1) < 0 && mag_cmp_2exp_si(arb_radref(acb_realref(t)), -1) < 0) { ca_zero(res, GR_CA_CTX(ctx)); status = GR_SUCCESS; } else if (arb_is_positive(acb_realref(t))) { status = _gr_ca_floor(res, x, ctx); } else if (arb_is_negative(acb_realref(t))) { status = _gr_ca_ceil(res, x, ctx); } else { status = GR_UNABLE; } acb_clear(t); return status; } /* todo: fast numerical path */ int _gr_ca_nint(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ca_check_is_integer(x, GR_CA_CTX(ctx)) == T_TRUE) { ca_set(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; } else { ca_t t; truth_t integer; int status = GR_SUCCESS; ca_init(t, GR_CA_CTX(ctx)); ca_set_d(t, 0.5, GR_CA_CTX(ctx)); ca_add(t, x, t, GR_CA_CTX(ctx)); ca_re(t, t, GR_CA_CTX(ctx)); ca_floor(res, t, GR_CA_CTX(ctx)); integer = ca_check_is_integer(t, GR_CA_CTX(ctx)); if (integer == T_TRUE) { fmpz_t m; fmpz_init(m); if (ca_get_fmpz(m, t, GR_CA_CTX(ctx))) { if (fmpz_is_odd(m)) ca_sub_ui(res, res, 1, GR_CA_CTX(ctx)); } else { status = GR_UNABLE; } fmpz_clear(m); } else if (integer == T_UNKNOWN) { status = GR_UNABLE; } ca_clear(t, GR_CA_CTX(ctx)); return status; } } int _gr_ca_i(ca_t res, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_RR_CA) return GR_DOMAIN; ca_i(res, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } int _gr_ca_abs(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_abs(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } int _gr_ca_conj(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_conj(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } /* todo: exploit when we know that the field is real */ int _gr_ca_re(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_re(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } /* todo: exploit when we know that the field is real */ int _gr_ca_im(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_im(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } int _gr_ca_sgn(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_sgn(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } int _gr_ca_csgn(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_csgn(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } int _gr_ca_arg(ca_t res, const ca_t x, gr_ctx_t ctx) { ca_arg(res, x, GR_CA_CTX(ctx)); if (ca_is_unknown(res, GR_CA_CTX(ctx))) return GR_UNABLE; return GR_SUCCESS; } #define CMP_UNDEFINED -2 #define CMP_UNKNOWN -3 int _ca_cmp(const ca_t x, const ca_t y, ca_ctx_t ctx); int _gr_ca_cmp(int * res, const ca_t x, const ca_t y, gr_ctx_t ctx) { int cmp = _ca_cmp(x, y, GR_CA_CTX(ctx)); if (cmp == CMP_UNKNOWN) return GR_UNABLE; if (cmp == CMP_UNDEFINED) return GR_DOMAIN; *res = cmp; return GR_SUCCESS; } int _gr_ca_pi(ca_t res, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) return GR_DOMAIN; ca_pi(res, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } int _gr_ca_exp(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_one(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_exp(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_sinh(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { int status = GR_SUCCESS; gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_exp(t, x, ctx); status |= gr_inv(u, t, ctx); status |= gr_sub(res, t, u, ctx); status |= gr_mul_2exp_si(res, res, -1, ctx); GR_TMP_CLEAR2(t, u, ctx); return status | handle_possible_special_value(res, ctx); } } int _gr_ca_cosh(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_one(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { int status = GR_SUCCESS; gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_exp(t, x, ctx); status |= gr_inv(u, t, ctx); status |= gr_add(res, t, u, ctx); status |= gr_mul_2exp_si(res, res, -1, ctx); GR_TMP_CLEAR2(t, u, ctx); return status | handle_possible_special_value(res, ctx); } } int _gr_ca_tanh(ca_t res, const ca_t x, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_sinh(t, x, ctx); status |= gr_cosh(u, x, ctx); status |= gr_div(res, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status | handle_possible_special_value(res, ctx); } int _gr_ca_coth(ca_t res, const ca_t x, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_sinh(t, x, ctx); status |= gr_cosh(u, x, ctx); status |= gr_div(res, u, t, ctx); GR_TMP_CLEAR2(t, u, ctx); return status | handle_possible_special_value(res, ctx); } int _gr_ca_log(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_one(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_log(res, x, GR_CA_CTX(ctx)); if (ctx->which_ring == GR_CTX_RR_CA) { truth_t ok = ca_check_is_real(res, GR_CA_CTX(ctx)); if (ok == T_TRUE) return GR_SUCCESS; return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } return handle_possible_special_value(res, ctx); } } int _gr_ca_atan(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_atan(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_sin(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_sin(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_cos(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_one(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_cos(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_tan(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_tan(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_cot(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { return GR_DOMAIN; } else { ca_cot(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_asin(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_asin(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_acos(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_one(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return (ok == T_FALSE) ? GR_DOMAIN : GR_UNABLE; } else { ca_acos(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_erf(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return GR_UNABLE; } else { ca_erf(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_erfi(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_zero(res, ctx); return GR_UNABLE; } else { ca_erfi(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_erfc(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_zero(x, GR_CA_CTX(ctx)); if (ok == T_TRUE) return _gr_ca_one(res, ctx); return GR_UNABLE; } else { ca_erfc(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_gamma(ca_t res, const ca_t x, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) { truth_t ok = ca_check_is_integer(x, GR_CA_CTX(ctx)); if (ok != T_TRUE) return GR_UNABLE; } { ca_gamma(res, x, GR_CA_CTX(ctx)); return handle_possible_special_value(res, ctx); } } int _gr_ca_poly_mullow(ca_ptr res, ca_srcptr poly1, slong len1, ca_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { _ca_poly_mullow(res, poly1, len1, poly2, len2, n, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_poly_roots(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx) { int status = GR_SUCCESS; ca_vec_t ca_roots; ulong * exp; slong deg; gr_ctx_t ZZ; slong i; fmpz_t exp_z; if (poly->length == 0) return GR_DOMAIN; deg = poly->length - 1; gr_ctx_init_fmpz(ZZ); fmpz_init(exp_z); ca_vec_init(ca_roots, 0, GR_CA_CTX(ctx)); exp = flint_malloc(sizeof(ulong) * deg); if (ca_poly_roots(ca_roots, exp, (const ca_poly_struct *) poly, GR_CA_CTX(ctx))) { gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); for (i = 0; i < ca_roots->length; i++) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || ctx->which_ring == GR_CTX_RR_CA) { truth_t is_real = ca_check_is_real(ca_roots->entries + i, GR_CA_CTX(ctx)); if (is_real == T_FALSE) continue; if (is_real == T_UNKNOWN) { status = GR_UNABLE; break; } } fmpz_set_ui(exp_z, exp[i]); status |= gr_vec_append(roots, ca_roots->entries + i, ctx); status |= gr_vec_append(mult, exp_z, ZZ); } } else { status = GR_UNABLE; gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); } ca_vec_clear(ca_roots, GR_CA_CTX(ctx)); flint_free(exp); gr_ctx_clear(ZZ); fmpz_clear(exp_z); /* if (status == GR_SUCCESS) { _acb_vec_sort_pretty(croots, deg); if (arb_roots) { for (i = 0; i < deg; i++) { if (arb_contains_zero(acb_imagref(croots + i))) { fmpz one = 1; arb_set_round(acb_realref(croots + i), acb_realref(croots + i), target_prec); GR_MUST_SUCCEED(gr_vec_append(roots, acb_realref(croots + i), ctx)); GR_MUST_SUCCEED(gr_vec_append(mult, &one, ZZ)); } } } else { gr_vec_set_length(roots, deg, ctx); gr_vec_set_length(mult, deg, ZZ); for (i = 0; i < deg; i++) { acb_set_round(((acb_ptr) roots->entries) + i, croots + i, target_prec); fmpz_one(((fmpz *) mult->entries) + i); } } } acb_poly_clear(tmp); _acb_vec_clear(croots, deg); gr_ctx_clear(ZZ); return status; */ return status; } int _gr_ca_mat_mul(ca_mat_t res, const ca_mat_t x, const ca_mat_t y, gr_ctx_t ctx) { ca_mat_mul(res, x, y, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_mat_det(ca_t res, const ca_mat_t x, gr_ctx_t ctx) { ca_mat_det(res, x, GR_CA_CTX(ctx)); return GR_SUCCESS; } int _gr_ca_ctx_clear(gr_ctx_t ctx) { ca_ctx_clear(GR_CA_CTX(ctx)); flint_free(GR_CA_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_ca_ctx_is_field(gr_ctx_t ctx) { return (ctx->which_ring == GR_CTX_COMPLEX_EXTENDED_CA) ? T_FALSE : T_TRUE; } truth_t _gr_ca_ctx_is_algebraically_closed(gr_ctx_t ctx) { return (ctx->which_ring == GR_CTX_CC_CA || ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_CA) ? T_TRUE : T_FALSE; } truth_t _gr_ca_ctx_is_ordered_ring(gr_ctx_t ctx) { return (ctx->which_ring == GR_CTX_RR_CA || ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA) ? T_TRUE : T_FALSE; } int _gr_ca_mat_find_nonzero_pivot(slong * pivot_row, ca_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx) { truth_t ok; ok = ca_mat_find_pivot(pivot_row, mat, start_row, end_row, column, GR_CA_CTX(ctx)); if (ok == T_TRUE) return GR_SUCCESS; else if (ok == T_FALSE) return GR_DOMAIN; else return GR_UNABLE; } int _ca_methods_initialized = 0; FLINT_DLL gr_static_method_table _ca_methods; gr_method_tab_input _ca_methods_input[] = { {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_ca_ctx_clear}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_ca_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) _gr_ca_ctx_is_field}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) _gr_ca_ctx_is_field}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) _gr_ca_ctx_is_field}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) _gr_ca_ctx_is_field}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) _gr_ca_ctx_is_field}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) _gr_ca_ctx_is_algebraically_closed}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) _gr_ca_ctx_is_ordered_ring}, /* important */ {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_INIT, (gr_funcptr) _gr_ca_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_ca_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_ca_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_ca_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_ca_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_ca_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_ca_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_ca_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_ca_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_ca_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_ca_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_ca_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_ca_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_ca_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_ca_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_ca_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_ca_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_ca_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_ring_exponents}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_ca_get_si}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_ca_get_ui}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_ca_get_fmpz}, {GR_METHOD_GET_FMPQ, (gr_funcptr) _gr_ca_get_fmpq}, {GR_METHOD_GET_D, (gr_funcptr) _gr_ca_get_d}, {GR_METHOD_GET_FEXPR, (gr_funcptr) _gr_ca_get_fexpr}, {GR_METHOD_GET_FEXPR_SERIALIZE, (gr_funcptr) _gr_ca_get_fexpr_serialize}, {GR_METHOD_NEG, (gr_funcptr) _gr_ca_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_ca_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_ca_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_ca_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_ca_add_fmpz}, {GR_METHOD_ADD_FMPQ, (gr_funcptr) _gr_ca_add_fmpq}, {GR_METHOD_SUB, (gr_funcptr) _gr_ca_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_ca_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_ca_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_ca_sub_fmpz}, {GR_METHOD_SUB_FMPQ, (gr_funcptr) _gr_ca_sub_fmpq}, {GR_METHOD_MUL, (gr_funcptr) _gr_ca_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_ca_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_ca_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_ca_mul_fmpz}, {GR_METHOD_MUL_FMPQ, (gr_funcptr) _gr_ca_mul_fmpq}, {GR_METHOD_DIV, (gr_funcptr) _gr_ca_div}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_ca_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_ca_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_ca_div_fmpz}, {GR_METHOD_DIV_FMPQ, (gr_funcptr) _gr_ca_div_fmpq}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_ca_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_ca_inv}, {GR_METHOD_POW, (gr_funcptr) _gr_ca_pow}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_ca_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_ca_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_ca_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_ca_pow_fmpq}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_ca_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_ca_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_ca_rsqrt}, {GR_METHOD_POS_INF, (gr_funcptr) _gr_ca_pos_inf}, {GR_METHOD_NEG_INF, (gr_funcptr) _gr_ca_neg_inf}, {GR_METHOD_UINF, (gr_funcptr) _gr_ca_uinf}, {GR_METHOD_UNDEFINED, (gr_funcptr) _gr_ca_undefined}, {GR_METHOD_UNKNOWN, (gr_funcptr) _gr_ca_unknown}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_ca_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_ca_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_ca_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_ca_nint}, {GR_METHOD_I, (gr_funcptr) _gr_ca_i}, {GR_METHOD_ABS, (gr_funcptr) _gr_ca_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_ca_conj}, {GR_METHOD_RE, (gr_funcptr) _gr_ca_re}, {GR_METHOD_IM, (gr_funcptr) _gr_ca_im}, {GR_METHOD_SGN, (gr_funcptr) _gr_ca_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_ca_csgn}, {GR_METHOD_ARG, (gr_funcptr) _gr_ca_arg}, {GR_METHOD_CMP, (gr_funcptr) _gr_ca_cmp}, {GR_METHOD_PI, (gr_funcptr) _gr_ca_pi}, {GR_METHOD_EXP, (gr_funcptr) _gr_ca_exp}, {GR_METHOD_LOG, (gr_funcptr) _gr_ca_log}, {GR_METHOD_SIN, (gr_funcptr) _gr_ca_sin}, {GR_METHOD_COS, (gr_funcptr) _gr_ca_cos}, {GR_METHOD_TAN, (gr_funcptr) _gr_ca_tan}, {GR_METHOD_COT, (gr_funcptr) _gr_ca_cot}, {GR_METHOD_SINH, (gr_funcptr) _gr_ca_sinh}, {GR_METHOD_COSH, (gr_funcptr) _gr_ca_cosh}, {GR_METHOD_TANH, (gr_funcptr) _gr_ca_tanh}, {GR_METHOD_COTH, (gr_funcptr) _gr_ca_coth}, {GR_METHOD_ATAN, (gr_funcptr) _gr_ca_atan}, {GR_METHOD_ASIN, (gr_funcptr) _gr_ca_asin}, {GR_METHOD_ACOS, (gr_funcptr) _gr_ca_acos}, {GR_METHOD_ERF, (gr_funcptr) _gr_ca_erf}, {GR_METHOD_ERFC, (gr_funcptr) _gr_ca_erfc}, {GR_METHOD_ERFI, (gr_funcptr) _gr_ca_erfi}, {GR_METHOD_GAMMA, (gr_funcptr) _gr_ca_gamma}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_ca_poly_mullow}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_ca_poly_roots}, /* {GR_METHOD_POLY_ROOTS_OTHER,(gr_funcptr) _gr_ca_poly_roots_other}, */ {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_ca_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) _gr_ca_mat_det}, {GR_METHOD_MAT_FIND_NONZERO_PIVOT, (gr_funcptr) _gr_ca_mat_find_nonzero_pivot}, {0, (gr_funcptr) NULL}, }; void _gr_ctx_init_ca(gr_ctx_t ctx, int which_ring) { ctx->which_ring = which_ring; ctx->sizeof_elem = sizeof(ca_struct); ctx->size_limit = WORD_MAX; GR_CTX_DATA_AS_PTR(ctx) = flint_malloc(sizeof(ca_ctx_struct)); ca_ctx_init(GR_CA_CTX(ctx)); ctx->methods = _ca_methods; if (!_ca_methods_initialized) { gr_method_tab_init(_ca_methods, _ca_methods_input); _ca_methods_initialized = 1; } } /* ca_ctx is a (ca_ctx_struct *) */ void _gr_ctx_init_ca_from_ref(gr_ctx_t ctx, int which_ring, void * ca_ctx) { ctx->which_ring = which_ring; ctx->sizeof_elem = sizeof(ca_struct); ctx->size_limit = WORD_MAX; GR_CTX_DATA_AS_PTR(ctx) = ca_ctx; ctx->methods = _ca_methods; if (!_ca_methods_initialized) { gr_method_tab_init(_ca_methods, _ca_methods_input); _ca_methods_initialized = 1; } } void gr_ctx_init_real_ca(gr_ctx_t ctx) { _gr_ctx_init_ca(ctx, GR_CTX_RR_CA); } void gr_ctx_init_complex_ca(gr_ctx_t ctx) { _gr_ctx_init_ca(ctx, GR_CTX_CC_CA); } void gr_ctx_init_real_algebraic_ca(gr_ctx_t ctx) { _gr_ctx_init_ca(ctx, GR_CTX_REAL_ALGEBRAIC_CA); } void gr_ctx_init_complex_algebraic_ca(gr_ctx_t ctx) { _gr_ctx_init_ca(ctx, GR_CTX_COMPLEX_ALGEBRAIC_CA); } void gr_ctx_init_complex_extended_ca(gr_ctx_t ctx) { _gr_ctx_init_ca(ctx, GR_CTX_COMPLEX_EXTENDED_CA); } flint-3.1.3/src/gr/cmp_coercion.c000066400000000000000000000016641461254215100166450ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr.h" /* todo: deal correctly with nested structures */ int gr_ctx_cmp_coercion(gr_ctx_t ctx1, gr_ctx_t ctx2) { if (ctx1->which_ring < ctx2->which_ring) return -1; if (ctx1->which_ring > ctx2->which_ring) return 1; if (ctx1->which_ring == GR_CTX_GR_POLY) { return gr_ctx_cmp_coercion(POLYNOMIAL_ELEM_CTX(ctx1), POLYNOMIAL_ELEM_CTX(ctx2)); } if (ctx1->which_ring == GR_CTX_GR_MAT) { return gr_ctx_cmp_coercion(MATRIX_CTX(ctx1)->base_ring, MATRIX_CTX(ctx2)->base_ring); } return 1; } flint-3.1.3/src/gr/dirichlet.c000066400000000000000000000157541461254215100161610ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "dirichlet.h" #include "gr.h" #define DIRICHLET_CTX(ctx) ((dirichlet_group_struct *) (GR_CTX_DATA_AS_PTR(ctx))) int _gr_dirichlet_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Dirichlet group modulo "); gr_stream_write_ui(out, DIRICHLET_CTX(ctx)->q); gr_stream_write(out, " (dirichlet_char)"); return GR_SUCCESS; } void _gr_dirichlet_ctx_clear(gr_ctx_t ctx) { if (DIRICHLET_CTX(ctx) != NULL) /* in case init failed */ { dirichlet_group_clear(DIRICHLET_CTX(ctx)); flint_free(DIRICHLET_CTX(ctx)); } } int _gr_dirichlet_init(dirichlet_char_t res, gr_ctx_t ctx) { dirichlet_char_init(res, DIRICHLET_CTX(ctx)); return GR_SUCCESS; } int _gr_dirichlet_clear(dirichlet_char_t res, gr_ctx_t ctx) { dirichlet_char_clear(res); return GR_SUCCESS; } void _gr_dirichlet_swap(dirichlet_char_t x, dirichlet_char_t y, gr_ctx_t ctx) { dirichlet_char_struct t = *x; *x = *y; *y = t; } void _dirichlet_char_print(gr_stream_t out, const dirichlet_group_t G, const dirichlet_char_t x) { gr_stream_write(out, "chi_"); gr_stream_write_ui(out, G->q); gr_stream_write(out, "("); gr_stream_write_ui(out, G->q == 1 ? 1 : x->n); gr_stream_write(out, ", .)"); /* slong k; gr_stream_write(out, "Character "); gr_stream_write_ui(out, G->q == 1 ? 1 : x->n); gr_stream_write(out, " ["); for (k = 0; k < G->num; k++) { gr_stream_write_ui(out, x->log[k]); if (k + 1 < G->num) gr_stream_write(out, ", "); } gr_stream_write(out, "]"); */ } int _gr_dirichlet_write(gr_stream_t out, dirichlet_char_t x, gr_ctx_t ctx) { _dirichlet_char_print(out, DIRICHLET_CTX(ctx), x); return GR_SUCCESS; } int _gr_dirichlet_randtest(dirichlet_char_t res, flint_rand_t state, gr_ctx_t ctx) { ulong phi, i; phi = DIRICHLET_CTX(ctx)->phi_q; i = n_randint(state, phi); dirichlet_char_index(res, DIRICHLET_CTX(ctx), i); return GR_SUCCESS; } truth_t _gr_dirichlet_equal(const dirichlet_char_t x, const dirichlet_char_t y, gr_ctx_t ctx) { /* fixme: arb code is inconsistent about reducing mod 1 */ if (DIRICHLET_CTX(ctx)->q == 1) return T_TRUE; return dirichlet_char_eq(x, y) ? T_TRUE : T_FALSE; } int _gr_dirichlet_set(dirichlet_char_t res, const dirichlet_char_t x, gr_ctx_t ctx) { dirichlet_char_set(res, DIRICHLET_CTX(ctx), x); return GR_SUCCESS; } int _gr_dirichlet_one(dirichlet_char_t res, gr_ctx_t ctx) { dirichlet_char_one(res, DIRICHLET_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_dirichlet_is_one(const dirichlet_char_t x, gr_ctx_t ctx) { return dirichlet_char_is_principal(DIRICHLET_CTX(ctx), x) ? T_TRUE : T_FALSE; } int _gr_dirichlet_mul(dirichlet_char_t res, const dirichlet_char_t x, const dirichlet_char_t y, gr_ctx_t ctx) { dirichlet_char_mul(res, DIRICHLET_CTX(ctx), x, y); return GR_SUCCESS; } int _gr_dirichlet_pow_ui(dirichlet_char_t res, const dirichlet_char_t x, ulong exp, gr_ctx_t ctx) { dirichlet_char_pow(res, DIRICHLET_CTX(ctx), x, exp); return GR_SUCCESS; } void _dirichlet_char_pow_fmpz(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const fmpz_t n) { ulong k; ulong nred; for (k = 0; k < G->num ; k++) { nred = fmpz_fdiv_ui(n, G->P[k].phi.n); c->log[k] = nmod_mul(a->log[k], nred, G->P[k].phi); } if (fmpz_sgn(n) >= 0 && 0) /* todo: which is faster? */ c->n = nmod_pow_fmpz(a->n, n, G->mod); else _dirichlet_char_exp(c, G); } int _gr_dirichlet_pow_fmpz(dirichlet_char_t res, const dirichlet_char_t x, const fmpz_t exp, gr_ctx_t ctx) { _dirichlet_char_pow_fmpz(res, DIRICHLET_CTX(ctx), x, exp); return GR_SUCCESS; } int _gr_dirichlet_pow_si(dirichlet_char_t res, const dirichlet_char_t x, slong exp, gr_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_si(t, exp); _dirichlet_char_pow_fmpz(res, DIRICHLET_CTX(ctx), x, t); fmpz_clear(t); return GR_SUCCESS; } /* todo */ int _gr_dirichlet_inv(dirichlet_char_t res, const dirichlet_char_t x, gr_ctx_t ctx) { return _gr_dirichlet_pow_si(res, x, -1, ctx); } /* todo: should be generic. also want left division */ int _gr_dirichlet_div(dirichlet_char_t res, const dirichlet_char_t x, const dirichlet_char_t y, gr_ctx_t ctx) { dirichlet_char_t t; dirichlet_char_init(t, DIRICHLET_CTX(ctx)); _gr_dirichlet_inv(t, y, ctx); dirichlet_char_mul(res, DIRICHLET_CTX(ctx), x, t); dirichlet_char_clear(t); return GR_SUCCESS; } int _dirichlet_methods_initialized = 0; gr_static_method_table _dirichlet_methods; gr_method_tab_input _dirichlet_methods_input[] = { {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_MULTIPLICATIVE_GROUP, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_dirichlet_ctx_write}, {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_dirichlet_ctx_clear}, {GR_METHOD_INIT, (gr_funcptr) _gr_dirichlet_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_dirichlet_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_dirichlet_swap}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_dirichlet_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_dirichlet_write}, {GR_METHOD_ONE, (gr_funcptr) _gr_dirichlet_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_dirichlet_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_dirichlet_set}, {GR_METHOD_MUL, (gr_funcptr) _gr_dirichlet_mul}, {GR_METHOD_INV, (gr_funcptr) _gr_dirichlet_inv}, {GR_METHOD_DIV, (gr_funcptr) _gr_dirichlet_div}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_dirichlet_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_dirichlet_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_dirichlet_pow_fmpz}, {0, (gr_funcptr) NULL}, }; int gr_ctx_init_dirichlet_group(gr_ctx_t ctx, ulong q) { if (q == 0) return GR_DOMAIN; ctx->which_ring = GR_CTX_DIRICHLET_GROUP; ctx->sizeof_elem = sizeof(dirichlet_char_struct); ctx->size_limit = WORD_MAX; GR_CTX_DATA_AS_PTR(ctx) = flint_malloc(sizeof(dirichlet_group_struct)); if (!dirichlet_group_init(DIRICHLET_CTX(ctx), q)) { flint_free(GR_CTX_DATA_AS_PTR(ctx)); return GR_UNABLE; } ctx->methods = _dirichlet_methods; if (!_dirichlet_methods_initialized) { gr_method_tab_init(_dirichlet_methods, _dirichlet_methods_input); _dirichlet_methods_initialized = 1; } return GR_SUCCESS; } flint-3.1.3/src/gr/fexpr.c000066400000000000000000000174471461254215100153370ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #include "gr.h" int _gr_fexpr_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Symbolic expressions (fexpr)"); return GR_SUCCESS; } void _gr_fexpr_init(fexpr_t x, const gr_ctx_t ctx) { fexpr_init(x); } void _gr_fexpr_clear(fexpr_t x, const gr_ctx_t ctx) { fexpr_clear(x); } void _gr_fexpr_swap(fexpr_t x, fexpr_t y, const gr_ctx_t ctx) { fexpr_t t; *t = *x; *x = *y; *y = *t; } void _gr_fexpr_set_shallow(fexpr_t res, const fexpr_t x, const gr_ctx_t ctx) { *res = *x; } /* todo */ int _gr_fexpr_randtest(fexpr_t res, flint_rand_t state, const gr_ctx_t ctx) { fexpr_set_si(res, -5 + (slong) n_randint(state, 10)); return GR_SUCCESS; } int _gr_fexpr_write(gr_stream_t out, const fexpr_t x, const gr_ctx_t ctx) { gr_stream_write_free(out, fexpr_get_str(x)); return GR_SUCCESS; } int _gr_fexpr_zero(fexpr_t x, const gr_ctx_t ctx) { fexpr_zero(x); return GR_SUCCESS; } int _gr_fexpr_one(fexpr_t x, const gr_ctx_t ctx) { fexpr_set_si(x, 1); return GR_SUCCESS; } int _gr_fexpr_set_si(fexpr_t res, slong v, const gr_ctx_t ctx) { fexpr_set_si(res, v); return GR_SUCCESS; } int _gr_fexpr_set_ui(fexpr_t res, ulong v, const gr_ctx_t ctx) { fexpr_set_ui(res, v); return GR_SUCCESS; } int _gr_fexpr_set_fmpz(fexpr_t res, const fmpz_t v, const gr_ctx_t ctx) { fexpr_set_fmpz(res, v); return GR_SUCCESS; } int _gr_fexpr_set_fmpq(fexpr_t res, const fmpq_t v, const gr_ctx_t ctx) { fexpr_set_fmpq(res, v); return GR_SUCCESS; } int _gr_fexpr_set_other(fexpr_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ctx_t ctx) { return gr_get_fexpr(res, x, x_ctx); } int _gr_fexpr_set(fexpr_t res, const fexpr_t x, const gr_ctx_t ctx) { fexpr_set(res, x); return GR_SUCCESS; } int _gr_fexpr_set_d(fexpr_t res, double x, const gr_ctx_t ctx) { fexpr_set_d(res, x); return GR_SUCCESS; } int _gr_fexpr_get_fmpz(fmpz_t res, const fexpr_t x, const gr_ctx_t ctx) { if (fexpr_get_fmpz(res, x)) return GR_SUCCESS; else return GR_UNABLE; } truth_t _gr_fexpr_is_zero(const fexpr_t x, const gr_ctx_t ctx) { return fexpr_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_fexpr_is_one(const fexpr_t x, const gr_ctx_t ctx) { return fexpr_equal_ui(x, 1) ? T_TRUE : T_FALSE; } truth_t _gr_fexpr_is_neg_one(const fexpr_t x, const gr_ctx_t ctx) { return fexpr_equal_si(x, -1) ? T_TRUE : T_FALSE; } truth_t _gr_fexpr_equal(const fexpr_t x, const fexpr_t y, const gr_ctx_t ctx) { return fexpr_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_fexpr_neg(fexpr_t res, const fexpr_t x, const gr_ctx_t ctx) { fexpr_neg(res, x); return GR_SUCCESS; } int _gr_fexpr_add(fexpr_t res, const fexpr_t x, const fexpr_t y, const gr_ctx_t ctx) { fexpr_add(res, x, y); return GR_SUCCESS; } int _gr_fexpr_sub(fexpr_t res, const fexpr_t x, const fexpr_t y, const gr_ctx_t ctx) { fexpr_sub(res, x, y); return GR_SUCCESS; } int _gr_fexpr_mul(fexpr_t res, const fexpr_t x, const fexpr_t y, const gr_ctx_t ctx) { fexpr_mul(res, x, y); return GR_SUCCESS; } int _gr_fexpr_inv(fexpr_t res, const fexpr_t x, const gr_ctx_t ctx) { fexpr_t b; fexpr_init(b); fexpr_set_si(b, -1); fexpr_pow(res, x, b); fexpr_clear(b); return GR_SUCCESS; } int _gr_fexpr_div(fexpr_t res, const fexpr_t x, const fexpr_t y, const gr_ctx_t ctx) { fexpr_div(res, x, y); return GR_SUCCESS; } int _gr_fexpr_pow(fexpr_t res, const fexpr_t x, const fexpr_t y, const gr_ctx_t ctx) { fexpr_pow(res, x, y); return GR_SUCCESS; } int _gr_fexpr_pow_ui(fexpr_t res, const fexpr_t x, ulong exp, const gr_ctx_t ctx) { fexpr_t b; fexpr_init(b); fexpr_set_ui(b, exp); fexpr_pow(res, x, b); fexpr_clear(b); return GR_SUCCESS; } int _gr_fexpr_pow_si(fexpr_t res, const fexpr_t x, slong exp, const gr_ctx_t ctx) { fexpr_t b; fexpr_init(b); fexpr_set_si(b, exp); fexpr_pow(res, x, b); fexpr_clear(b); return GR_SUCCESS; } int _gr_fexpr_pow_fmpz(fexpr_t res, const fexpr_t x, const fmpz_t exp, const gr_ctx_t ctx) { fexpr_t b; fexpr_init(b); fexpr_set_fmpz(b, exp); fexpr_pow(res, x, b); fexpr_clear(b); return GR_SUCCESS; } int _gr_fexpr_pow_fmpq(fexpr_t res, const fexpr_t x, const fmpq_t exp, const gr_ctx_t ctx) { fexpr_t b; fexpr_init(b); fexpr_set_fmpq(b, exp); fexpr_pow(res, x, b); fexpr_clear(b); return GR_SUCCESS; } int _gr_fexpr_pi(fexpr_t res, const gr_ctx_t ctx) { fexpr_set_symbol_builtin(res, FEXPR_Pi); return GR_SUCCESS; } int _gr_fexpr_i(fexpr_t res, const gr_ctx_t ctx) { fexpr_set_symbol_builtin(res, FEXPR_NumberI); return GR_SUCCESS; } int _fexpr_methods_initialized = 0; gr_static_method_table _fexpr_methods; gr_method_tab_input _fexpr_methods_input[] = { {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fexpr_ctx_write}, {GR_METHOD_INIT, (gr_funcptr) _gr_fexpr_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fexpr_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fexpr_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fexpr_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fexpr_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fexpr_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fexpr_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fexpr_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fexpr_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fexpr_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_fexpr_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fexpr_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fexpr_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fexpr_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fexpr_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fexpr_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_fexpr_set_fmpq}, {GR_METHOD_SET_D, (gr_funcptr) _gr_fexpr_set_d}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fexpr_set_other}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_fexpr_get_fmpz}, {GR_METHOD_NEG, (gr_funcptr) _gr_fexpr_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fexpr_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_fexpr_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fexpr_mul}, {GR_METHOD_DIV, (gr_funcptr) _gr_fexpr_div}, {GR_METHOD_DIVEXACT, (gr_funcptr) _gr_fexpr_div}, {GR_METHOD_INV, (gr_funcptr) _gr_fexpr_inv}, {GR_METHOD_POW, (gr_funcptr) _gr_fexpr_pow}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fexpr_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_fexpr_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fexpr_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_fexpr_pow_fmpq}, {GR_METHOD_I, (gr_funcptr) _gr_fexpr_i}, {GR_METHOD_PI, (gr_funcptr) gr_not_in_domain}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fexpr(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_FEXPR; ctx->sizeof_elem = sizeof(fexpr_struct); ctx->size_limit = WORD_MAX; ctx->methods = _fexpr_methods; if (!_fexpr_methods_initialized) { gr_method_tab_init(_fexpr_methods, _fexpr_methods_input); _fexpr_methods_initialized = 1; } } flint-3.1.3/src/gr/fmpq.c000066400000000000000000000656511461254215100151560ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gmpcompat.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "fmpq.h" #include "fmpq_mat.h" #include "fexpr.h" #include "qqbar.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_fmpq_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Rational field (fmpq)"); return GR_SUCCESS; } void _gr_fmpq_init(fmpq_t x, const gr_ctx_t ctx) { fmpq_init(x); } void _gr_fmpq_clear(fmpq_t x, const gr_ctx_t ctx) { fmpq_clear(x); } void _gr_fmpq_swap(fmpq_t x, fmpq_t y, const gr_ctx_t ctx) { fmpq_t t; *t = *x; *x = *y; *y = *t; } void _gr_fmpq_set_shallow(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_fmpq_randtest(fmpq_t res, flint_rand_t state, const gr_ctx_t ctx) { switch (n_randint(state, 4)) { case 0: fmpq_randtest(res, state, 100); break; default: fmpq_randtest(res, state, 10); } return GR_SUCCESS; } int _gr_fmpq_write(gr_stream_t out, const fmpq_t x, const gr_ctx_t ctx) { gr_stream_write_fmpz(out, fmpq_numref(x)); if (!fmpz_is_one(fmpq_denref(x))) { gr_stream_write(out, "/"); gr_stream_write_fmpz(out, fmpq_denref(x)); } return GR_SUCCESS; } int _gr_fmpq_zero(fmpq_t x, const gr_ctx_t ctx) { fmpq_zero(x); return GR_SUCCESS; } int _gr_fmpq_one(fmpq_t x, const gr_ctx_t ctx) { fmpq_one(x); return GR_SUCCESS; } int _gr_fmpq_set_si(fmpq_t res, slong v, const gr_ctx_t ctx) { fmpq_set_si(res, v, 1); return GR_SUCCESS; } int _gr_fmpq_set_ui(fmpq_t res, ulong v, const gr_ctx_t ctx) { fmpq_set_ui(res, v, 1); return GR_SUCCESS; } int _gr_fmpq_set_fmpz(fmpq_t res, const fmpz_t v, const gr_ctx_t ctx) { fmpz_set(fmpq_numref(res), v); fmpz_one(fmpq_denref(res)); return GR_SUCCESS; } #include "arf.h" int _gr_fmpq_set_d(fmpq_t res, double x, const gr_ctx_t ctx) { arf_t t; if (x != x || x == HUGE_VAL || x == -HUGE_VAL) return GR_DOMAIN; /* todo - direct impl */ arf_init(t); arf_set_d(t, x); arf_get_fmpq(res, t); arf_clear(t); return GR_SUCCESS; } int _gr_fmpq_set_other(fmpq_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: fmpq_set_fmpz(res, x); return GR_SUCCESS; case GR_CTX_FMPQ: fmpq_set(res, x); return GR_SUCCESS; case GR_CTX_REAL_ALGEBRAIC_QQBAR: case GR_CTX_COMPLEX_ALGEBRAIC_QQBAR: if (qqbar_is_rational(x)) { qqbar_get_fmpq(res, x); return GR_SUCCESS; } return GR_DOMAIN; } /* handles fexpr */ return gr_generic_set_other(res, x, x_ctx, ctx); } int _gr_fmpq_get_ui(ulong * res, const fmpq_t x, const gr_ctx_t ctx) { if (!fmpz_is_one(fmpq_denref(x))) return GR_DOMAIN; if (fmpz_sgn(fmpq_numref(x)) < 0 || fmpz_cmp_ui(fmpq_numref(x), UWORD_MAX) > 0) return GR_DOMAIN; *res = fmpz_get_ui(fmpq_numref(x)); return GR_SUCCESS; } int _gr_fmpq_get_si(slong * res, const fmpq_t x, const gr_ctx_t ctx) { if (!fmpz_is_one(fmpq_denref(x))) return GR_DOMAIN; if (!fmpz_fits_si(fmpq_numref(x))) return GR_DOMAIN; *res = fmpz_get_si(fmpq_numref(x)); return GR_SUCCESS; } int _gr_fmpq_get_fmpz(fmpz_t res, const fmpq_t x, const gr_ctx_t ctx) { if (!fmpz_is_one(fmpq_denref(x))) return GR_DOMAIN; fmpz_set(res, fmpq_numref(x)); return GR_SUCCESS; } int _gr_fmpq_get_d(double * res, const fmpq_t x, const gr_ctx_t ctx) { *res = fmpq_get_d(x); return GR_SUCCESS; } int _gr_fmpq_get_fexpr(fexpr_t res, const fmpq_t x, const gr_ctx_t ctx) { fexpr_set_fmpq(res, x); return GR_SUCCESS; } truth_t _gr_fmpq_is_zero(const fmpq_t x, const gr_ctx_t ctx) { return fmpq_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpq_is_one(const fmpq_t x, const gr_ctx_t ctx) { return fmpq_is_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpq_is_neg_one(const fmpq_t x, const gr_ctx_t ctx) { return ((*fmpq_numref(x) == -1) && fmpz_is_one(fmpq_denref(x))) ? T_TRUE : T_FALSE; } truth_t _gr_fmpq_equal(const fmpq_t x, const fmpq_t y, const gr_ctx_t ctx) { return fmpq_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_fmpq_set(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpq_set(res, x); return GR_SUCCESS; } int _gr_fmpq_neg(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpq_neg(res, x); return GR_SUCCESS; } int _gr_fmpq_add(fmpq_t res, const fmpq_t x, const fmpq_t y, const gr_ctx_t ctx) { fmpq_add(res, x, y); return GR_SUCCESS; } int _gr_fmpq_add_si(fmpq_t res, const fmpq_t x, slong y, const gr_ctx_t ctx) { fmpq_add_si(res, x, y); return GR_SUCCESS; } int _gr_fmpq_add_ui(fmpq_t res, const fmpq_t x, ulong y, const gr_ctx_t ctx) { fmpq_add_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpq_sub(fmpq_t res, const fmpq_t x, const fmpq_t y, const gr_ctx_t ctx) { fmpq_sub(res, x, y); return GR_SUCCESS; } int _gr_fmpq_mul(fmpq_t res, const fmpq_t x, const fmpq_t y, const gr_ctx_t ctx) { fmpq_mul(res, x, y); return GR_SUCCESS; } int _gr_fmpq_mul_si(fmpq_t res, const fmpq_t x, slong y, const gr_ctx_t ctx) { fmpq_mul_si(res, x, y); return GR_SUCCESS; } int _gr_fmpq_inv(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { if (fmpq_is_zero(x)) { return GR_DOMAIN; } else { fmpq_inv(res, x); return GR_SUCCESS; } } int _gr_fmpq_div(fmpq_t res, const fmpq_t x, const fmpq_t y, const gr_ctx_t ctx) { if (fmpq_is_zero(y)) { return GR_DOMAIN; } else { fmpq_div(res, x, y); return GR_SUCCESS; } } truth_t _gr_fmpq_is_invertible(const fmpq_t x, const gr_ctx_t ctx) { return (!fmpq_is_zero(x)) ? T_TRUE : T_FALSE; } int _gr_fmpq_pow_ui(fmpq_t res, const fmpq_t x, ulong exp, const gr_ctx_t ctx) { fmpq_pow_si(res, x, exp); return GR_SUCCESS; } int _gr_fmpq_pow_si(fmpq_t res, const fmpq_t x, slong exp, const gr_ctx_t ctx) { if (fmpq_is_one(x)) { fmpq_one(res); return GR_SUCCESS; } else if (fmpz_equal_si(fmpq_numref(x), -1) && fmpz_is_one(fmpq_denref(x))) { if (exp % 2) fmpq_set_si(res, -1, 1); else fmpq_one(res); return GR_SUCCESS; } else if (fmpq_is_zero(x)) { if (exp > 0) { fmpq_zero(res); return GR_SUCCESS; } else { return GR_DOMAIN; } } else { fmpq_pow_si(res, x, exp); return GR_SUCCESS; } } int _gr_fmpq_pow_fmpz(fmpq_t res, const fmpq_t x, const fmpz_t exp, const gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*exp)) { return _gr_fmpq_pow_si(res, x, *exp, ctx); } else if (fmpq_is_one(x)) { fmpq_one(res); return GR_SUCCESS; } else if (fmpz_equal_si(fmpq_numref(x), -1) && fmpz_is_one(fmpq_denref(x))) { if (fmpz_is_odd(exp)) fmpq_set_si(res, -1, 1); else fmpq_one(res); return GR_SUCCESS; } else if (fmpq_is_zero(x)) { if (fmpz_sgn(exp) > 0) { fmpq_zero(res); return GR_SUCCESS; } else { return GR_DOMAIN; } } else { return GR_UNABLE; } } /* TODO: exploit fmpz_root return value in qqbar nth root as well */ int _gr_fmpq_pow_fmpq(fmpq_t res, const fmpq_t x, const fmpq_t exp, const gr_ctx_t ctx) { if (fmpz_is_one(fmpq_denref(exp))) { return _gr_fmpq_pow_fmpz(res, x, fmpq_numref(exp), ctx); } else if (fmpq_is_one(x) || fmpq_is_zero(exp)) { return _gr_fmpq_one(res, ctx); } else if (fmpq_is_zero(x)) { if (fmpq_sgn(exp) > 0) return _gr_fmpq_zero(res, ctx); else return GR_DOMAIN; } else if (COEFF_IS_MPZ(*fmpq_denref(exp))) { return GR_UNABLE; } else if (fmpq_sgn(x) < 0 && fmpz_is_even(fmpq_denref(exp))) { return GR_DOMAIN; } else { int status; ulong n; fmpq_t t; fmpq_init(t); n = *fmpq_denref(exp); if (fmpz_root(fmpq_numref(t), fmpq_numref(x), n) && fmpz_root(fmpq_denref(t), fmpq_denref(x), n)) status = _gr_fmpq_pow_fmpz(res, t, fmpq_numref(exp), ctx); else status = GR_DOMAIN; fmpq_clear(t); return status; } } truth_t _gr_fmpq_is_square(const fmpq_t x, const gr_ctx_t ctx) { return (fmpz_is_square(fmpq_numref(x)) && fmpz_is_square(fmpq_denref(x))) ? T_TRUE : T_FALSE; } int _gr_fmpq_sqrt(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { if (fmpq_sgn(x) < 0) return GR_DOMAIN; if (fmpz_root(fmpq_numref(res), fmpq_numref(x), 2) && fmpz_root(fmpq_denref(res), fmpq_denref(x), 2)) { return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpq_rsqrt(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { if (fmpq_sgn(x) <= 0) return GR_DOMAIN; if (fmpz_root(fmpq_numref(res), fmpq_numref(x), 2) && fmpz_root(fmpq_denref(res), fmpq_denref(x), 2)) { fmpq_inv(res, res); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpq_factor(gr_ptr c, gr_vec_t factors, gr_vec_t exponents, const fmpq_t x, int flags, gr_ctx_t ctx) { fmpz_factor_t nfac, dfac; slong i, n, num_num, num_den; fmpq * fmpq_factors; gr_ctx_t ZZ; fmpz_factor_init(nfac); fmpz_factor_init(dfac); fmpz_factor(nfac, fmpq_numref(x)); fmpz_factor(dfac, fmpq_denref(x)); num_num = nfac->num; num_den = dfac->num; fmpq_set_si(c, nfac->sign, 1); n = num_num + num_den; gr_ctx_init_fmpz(ZZ); gr_vec_set_length(factors, n, ctx); gr_vec_set_length(exponents, n, ZZ); fmpq_factors = factors->entries; for (i = 0; i < num_num; i++) { fmpz_swap(fmpq_numref(fmpq_factors + i), nfac->p + i); fmpz_one(fmpq_denref(fmpq_factors + i)); fmpz_set_ui((fmpz *) (exponents->entries) + i, nfac->exp[i]); } for (i = 0; i < dfac->num; i++) { fmpz_swap(fmpq_numref(fmpq_factors + num_num + i), dfac->p + i); fmpz_one(fmpq_denref(fmpq_factors + num_num + i)); fmpz_neg_ui((fmpz *) (exponents->entries) + num_num + i, dfac->exp[i]); } fmpz_factor_clear(nfac); fmpz_factor_clear(dfac); gr_ctx_clear(ZZ); return GR_SUCCESS; } int _gr_fmpq_numerator(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpz_set(fmpq_numref(res), fmpq_numref(x)); fmpz_one(fmpq_denref(res)); return GR_SUCCESS; } int _gr_fmpq_denominator(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpz_set(fmpq_numref(res), fmpq_denref(x)); fmpz_one(fmpq_denref(res)); return GR_SUCCESS; } int _gr_fmpq_floor(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpz_fdiv_q(fmpq_numref(res), fmpq_numref(x), fmpq_denref(x)); fmpz_one(fmpq_denref(res)); return GR_SUCCESS; } int _gr_fmpq_ceil(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpz_cdiv_q(fmpq_numref(res), fmpq_numref(x), fmpq_denref(x)); fmpz_one(fmpq_denref(res)); return GR_SUCCESS; } int _gr_fmpq_trunc(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpz_tdiv_q(fmpq_numref(res), fmpq_numref(x), fmpq_denref(x)); fmpz_one(fmpq_denref(res)); return GR_SUCCESS; } int _gr_fmpq_nint(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { if (fmpz_is_one(fmpq_denref(x))) { fmpq_set(res, x); } else { /* nint(x) = floor(x+0.5) - isint((2*x-1)/4) */ fmpq_t t; fmpq_init(t); fmpq_set_si(t, 1, 2); fmpq_add(t, x, t); fmpz_fdiv_q(fmpq_numref(res), fmpq_numref(t), fmpq_denref(t)); if (fmpz_is_one(fmpq_denref(t)) && fmpz_is_odd(fmpq_numref(t))) fmpq_sub_ui(res, res, 1); fmpq_clear(t); } return GR_SUCCESS; } int _gr_fmpq_abs(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpq_abs(res, x); return GR_SUCCESS; } int _gr_fmpq_im(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpq_zero(res); return GR_SUCCESS; } int _gr_fmpq_sgn(fmpq_t res, const fmpq_t x, const gr_ctx_t ctx) { fmpq_set_si(res, fmpq_sgn(x), 1); return GR_SUCCESS; } int _gr_fmpq_cmp(int * res, const fmpq_t x, const fmpq_t y, const gr_ctx_t ctx) { int cmp = fmpq_cmp(x, y); if (cmp < 0) cmp = -1; if (cmp > 0) cmp = 1; *res = cmp; return GR_SUCCESS; } /* todo: fast flint code */ int _gr_fmpq_cmpabs(int * res, const fmpq_t x, const fmpq_t y, const gr_ctx_t ctx) { fmpq_t t, u; int cmp; fmpq_init(t); fmpq_init(u); fmpq_abs(t, x); fmpq_abs(u, y); cmp = fmpq_cmp(t, u); fmpq_clear(t); fmpq_clear(u); if (cmp < 0) cmp = -1; if (cmp > 0) cmp = 1; *res = cmp; return GR_SUCCESS; } int _gr_fmpq_vec_is_zero(const fmpq * vec, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) if (!fmpq_is_zero(vec + i)) return T_FALSE; return T_TRUE; } int _gr_fmpq_vec_equal(const fmpq * vec1, const fmpq * vec2, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) if (!fmpq_equal(vec1 + i, vec2 + i)) return T_FALSE; return T_TRUE; } static int _fmpq_vec_is_fmpz_vec(const fmpq * vec, slong len) { slong i; for (i = 0; i < len; i++) if (!fmpz_is_one(fmpq_denref(vec + i))) return 0; return 1; } int _gr_fmpq_vec_sum(fmpq_t res, const fmpq * vec, slong len, gr_ctx_t ctx) { if (len <= 2) { if (len == 2) fmpq_add(res, vec + 0, vec + 1); else if (len == 1) fmpq_set(res, vec); else fmpq_zero(res); } else if (_fmpq_vec_is_fmpz_vec(vec, len)) { ulong hi, lo; slong i; fmpz f; __mpz_struct * f_mpz; __mpz_struct * res_mpz = NULL; hi = lo = 0; for (i = 0; i < len; i++) { f = *fmpq_numref(vec + i); if (!COEFF_IS_MPZ(f)) { if (f >= 0) add_ssaaaa(hi, lo, hi, lo, 0, f); else sub_ddmmss(hi, lo, hi, lo, 0, -f); } else { f_mpz = COEFF_TO_PTR(f); if (res_mpz == NULL) { res_mpz = _fmpz_promote(fmpq_numref(res)); mpz_set(res_mpz, f_mpz); } else { mpz_add(res_mpz, res_mpz, f_mpz); } } } if (res_mpz == NULL) { fmpz_set_signed_uiui(fmpq_numref(res), hi, lo); } else { if (hi != 0 || lo != 0) flint_mpz_add_signed_uiui(res_mpz, res_mpz, hi, lo); _fmpz_demote_val(fmpq_numref(res)); } fmpz_one(fmpq_denref(res)); } else { slong i; if (len > 500) return _gr_vec_sum_bsplit_parallel(res, vec, len, 100, ctx); if (len > 20) return _gr_vec_sum_bsplit(res, vec, len, 20, ctx); fmpq_add(res, vec, vec + 1); for (i = 2; i < len; i++) fmpq_add(res, res, vec + i); } return GR_SUCCESS; } static void _fmpq_vec_get_fmpz_vec_den(fmpz * c, fmpz_t den, const fmpq * vec, slong len) { slong i; fmpz_one(den); if (_fmpq_vec_is_fmpz_vec(vec, len)) { for (i = 0; i < len; i++) fmpz_set(c + i, fmpq_numref(vec + i)); } else { for (i = 0; i < len; i++) fmpz_lcm(den, den, fmpq_denref(vec + i)); for (i = 0; i < len; i++) { fmpz_divexact(c + i, den, fmpq_denref(vec + i)); fmpz_mul(c + i, c + i, fmpq_numref(vec + i)); } } } static void _fmpq_vec_set_fmpz_vec_div_fmpz(fmpq * res, const fmpz * v, const fmpz_t den, slong len) { slong i; if (fmpz_is_one(den)) { for (i = 0; i < len; i++) { fmpz_set(fmpq_numref(res + i), v + i); fmpz_one(fmpq_denref(res + i)); } } else { for (i = 0; i < len; i++) fmpq_set_fmpz_frac(res + i, v + i, den); } } int _gr_fmpq_poly_mullow(fmpq * res, const fmpq * poly1, slong len1, const fmpq * poly2, slong len2, slong n, gr_ctx_t ctx) { fmpz *z1, *z2, *z3; fmpz_t den1, den2; /* Todo: handle mixed cases */ if (_fmpq_vec_is_fmpz_vec(poly1, len1) && _fmpq_vec_is_fmpz_vec(poly2, len2)) { slong i; z1 = flint_malloc((len1 + len2 + n) * sizeof(fmpz)); z2 = z1 + len1; z3 = z2 + len2; for (i = 0; i < len1; i++) z1[i] = *fmpq_numref(poly1 + i); for (i = 0; i < len2; i++) z2[i] = *fmpq_numref(poly2 + i); for (i = 0; i < n; i++) z3[i] = *fmpq_numref(res + i); if (len1 >= len2) _fmpz_poly_mullow(z3, z1, len1, z2, len2, n); else _fmpz_poly_mullow(z3, z2, len2, z1, len1, n); for (i = 0; i < n; i++) { *fmpq_numref(res + i) = z3[i]; fmpz_one(fmpq_denref(res + i)); } flint_free(z1); } else { fmpz_init(den1); fmpz_init(den2); z1 = _fmpz_vec_init(len1 + len2 + n); z2 = z1 + len1; z3 = z2 + len2; _fmpq_vec_get_fmpz_vec_den(z1, den1, poly1, len1); _fmpq_vec_get_fmpz_vec_den(z2, den2, poly2, len2); fmpz_mul(den1, den1, den2); if (len1 >= len2) _fmpz_poly_mullow(z3, z1, len1, z2, len2, n); else _fmpz_poly_mullow(z3, z2, len2, z1, len1, n); _fmpq_vec_set_fmpz_vec_div_fmpz(res, z3, den1, n); _fmpz_vec_clear(z1, len1 + len2 + n); fmpz_clear(den1); fmpz_clear(den2); } return GR_SUCCESS; } int _gr_fmpq_poly_roots(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx) { gr_ctx_t ZZ; gr_poly_t f; fmpz_t den; slong len = poly->length; if (len == 0) return GR_DOMAIN; gr_ctx_init_fmpz(ZZ); f->coeffs = _fmpz_vec_init(len); fmpz_init(den); _fmpq_vec_get_fmpz_vec_den(f->coeffs, den, poly->coeffs, len); f->length = f->alloc = poly->length; GR_MUST_SUCCEED(gr_poly_roots_other(roots, mult, f, ZZ, flags, ctx)); _fmpz_vec_clear(f->coeffs, len); fmpz_clear(den); gr_ctx_clear(ZZ); return GR_SUCCESS; } int _gr_fmpq_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t other_ctx, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; if (other_ctx->which_ring == GR_CTX_FMPQ) return _gr_fmpq_poly_roots(roots, mult, poly, flags, ctx); if (other_ctx->which_ring == GR_CTX_FMPZ) { gr_ctx_t ZZ; int status = GR_SUCCESS; slong deg; deg = poly->length - 1; gr_ctx_init_fmpz(ZZ); if (deg == 0) { gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); } else /* todo: special cases */ { /* todo: better algorithm */ fmpz_poly_factor_t fac; slong i, j, num; fmpq * res_entries; fmpz * mult_entries; fmpz_poly_factor_init(fac); fmpz_poly_factor(fac, (const fmpz_poly_struct *) poly); num = 0; for (i = 0; i < fac->num; i++) if (fac->p[i].length == 2) num++; gr_vec_set_length(roots, num, ctx); gr_vec_set_length(mult, num, ZZ); res_entries = roots->entries; mult_entries = mult->entries; for (i = j = 0; i < fac->num; i++) { if (fac->p[i].length == 2) { fmpz_neg(fmpq_numref(res_entries + j), fac->p[i].coeffs); fmpz_swap(fmpq_denref(res_entries + j), fac->p[i].coeffs + 1); if (fmpz_sgn(fmpq_denref(res_entries + j)) <= 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); fmpz_set_ui(mult_entries + j, fac->exp[i]); j++; } } fmpz_poly_factor_clear(fac); } gr_ctx_clear(ZZ); return status; } return GR_UNABLE; } int _gr_fmpq_mat_mul(fmpq_mat_t res, const fmpq_mat_t x, const fmpq_mat_t y, gr_ctx_t ctx) { fmpq_mat_mul(res, x, y); return GR_SUCCESS; } int _gr_fmpq_mat_det(fmpq_t res, const fmpq_mat_t x, const gr_ctx_t ctx) { fmpq_mat_det(res, x); return GR_SUCCESS; } int _fmpq_methods_initialized = 0; gr_static_method_table _fmpq_methods; gr_method_tab_input _fmpq_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpq_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpq_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpq_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpq_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpq_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpq_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpq_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpq_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpq_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpq_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpq_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_fmpq_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpq_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpq_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpq_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpq_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpq_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_fmpq_set}, {GR_METHOD_SET_D, (gr_funcptr) _gr_fmpq_set_d}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fmpq_set_other}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_fmpq_get_si}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_fmpq_get_ui}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_fmpq_get_fmpz}, {GR_METHOD_GET_FMPQ, (gr_funcptr) _gr_fmpq_set}, {GR_METHOD_GET_D, (gr_funcptr) _gr_fmpq_get_d}, {GR_METHOD_GET_FEXPR, (gr_funcptr) _gr_fmpq_get_fexpr}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpq_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpq_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_fmpq_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_fmpq_add_si}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpq_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpq_mul}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpq_mul_si}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpq_div}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpq_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpq_inv}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpq_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_fmpq_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpq_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_fmpq_pow_fmpq}, {GR_METHOD_POW, (gr_funcptr) _gr_fmpq_pow_fmpq}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpq_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpq_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_fmpq_rsqrt}, {GR_METHOD_FACTOR, (gr_funcptr) _gr_fmpq_factor}, {GR_METHOD_NUMERATOR, (gr_funcptr) _gr_fmpq_numerator}, {GR_METHOD_DENOMINATOR, (gr_funcptr) _gr_fmpq_denominator}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_fmpq_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_fmpq_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_fmpq_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_fmpq_nint}, {GR_METHOD_I, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_PI, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_ABS, (gr_funcptr) _gr_fmpq_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_fmpq_set}, {GR_METHOD_RE, (gr_funcptr) _gr_fmpq_set}, {GR_METHOD_IM, (gr_funcptr) _gr_fmpq_im}, {GR_METHOD_SGN, (gr_funcptr) _gr_fmpq_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_fmpq_sgn}, {GR_METHOD_CMP, (gr_funcptr) _gr_fmpq_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) _gr_fmpq_cmpabs}, {GR_METHOD_VEC_IS_ZERO, (gr_funcptr) _gr_fmpq_vec_is_zero}, {GR_METHOD_VEC_EQUAL, (gr_funcptr) _gr_fmpq_vec_equal}, {GR_METHOD_VEC_SUM, (gr_funcptr) _gr_fmpq_vec_sum}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_fmpq_poly_mullow}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_fmpq_poly_roots}, {GR_METHOD_POLY_ROOTS_OTHER,(gr_funcptr) _gr_fmpq_poly_roots_other}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_fmpq_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) _gr_fmpq_mat_det}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpq(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_FMPQ; ctx->sizeof_elem = sizeof(fmpq); ctx->size_limit = WORD_MAX; ctx->methods = _fmpq_methods; if (!_fmpq_methods_initialized) { gr_method_tab_init(_fmpq_methods, _fmpq_methods_input); _fmpq_methods_initialized = 1; } } flint-3.1.3/src/gr/fmpq_poly.c000066400000000000000000000464331461254215100162160ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_poly.h" #include "gr.h" #include "gr_poly.h" #include "gr_vec.h" #include "gr_generic.h" int _gr_fmpq_poly_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Polynomials over rationals (fmpq_poly)"); return GR_SUCCESS; } void _gr_fmpq_poly_init(fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_init(x); } void _gr_fmpq_poly_clear(fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_clear(x); } void _gr_fmpq_poly_swap(fmpq_poly_t x, fmpq_poly_t y, const gr_ctx_t ctx) { fmpq_poly_t t; *t = *x; *x = *y; *y = *t; } void _gr_fmpq_poly_set_shallow(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_fmpq_poly_randtest(fmpq_poly_t res, flint_rand_t state, const gr_ctx_t ctx) { if (n_randint(state, 10) == 0) fmpq_poly_randtest(res, state, 4, 100); else fmpq_poly_randtest(res, state, 5, 10); return GR_SUCCESS; } int _gr_fmpq_poly_write(gr_stream_t out, const fmpq_poly_t x, const gr_ctx_t ctx) { gr_stream_write_free(out, fmpq_poly_get_str_pretty(x, "x")); return GR_SUCCESS; } int _gr_fmpq_poly_zero(fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_zero(x); return GR_SUCCESS; } int _gr_fmpq_poly_one(fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_one(x); return GR_SUCCESS; } int _gr_fmpq_poly_gen(fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_zero(x); fmpq_poly_set_coeff_ui(x, 1, 1); return GR_SUCCESS; } int _gr_fmpq_poly_set_si(fmpq_poly_t res, slong v, const gr_ctx_t ctx) { fmpq_poly_set_si(res, v); return GR_SUCCESS; } int _gr_fmpq_poly_set_ui(fmpq_poly_t res, ulong v, const gr_ctx_t ctx) { fmpq_poly_set_ui(res, v); return GR_SUCCESS; } int _gr_fmpq_poly_set_fmpz(fmpq_poly_t res, const fmpz_t v, const gr_ctx_t ctx) { fmpq_poly_set_fmpz(res, v); return GR_SUCCESS; } int _gr_fmpq_poly_set_other(fmpq_poly_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ctx_t ctx) { if (x_ctx->which_ring == GR_CTX_FMPZ) { fmpq_poly_set_fmpz(res, x); return GR_SUCCESS; } if (x_ctx->which_ring == GR_CTX_FMPZ_POLY) { fmpq_poly_set_fmpz_poly(res, x); return GR_SUCCESS; } if (x_ctx->which_ring == GR_CTX_FMPQ) { fmpq_poly_set_fmpq(res, x); return GR_SUCCESS; } if (x_ctx->which_ring == GR_CTX_FMPQ_POLY) { fmpq_poly_set(res, x); return GR_SUCCESS; } if (x_ctx->which_ring == GR_CTX_GR_POLY) { if (POLYNOMIAL_ELEM_CTX(x_ctx)->which_ring == GR_CTX_FMPZ) { fmpq_poly_set_fmpz_poly(res, x); return GR_SUCCESS; } else { gr_ctx_t QQ; gr_poly_t poly; int status; gr_ctx_init_fmpq(QQ); /* no need to free */ gr_poly_init(poly, QQ); status = gr_poly_set_gr_poly_other(poly, x, POLYNOMIAL_ELEM_CTX(x_ctx), QQ); if (status == GR_SUCCESS) { fmpq_poly_fit_length(res, poly->length); _fmpq_vec_get_fmpz_vec_fmpz(res->coeffs, res->den, poly->coeffs, poly->length); _fmpq_poly_set_length(res, poly->length); } gr_poly_clear(poly, QQ); return status; } } if (x_ctx->which_ring == GR_CTX_GR_VEC) { gr_ctx_t QQ; gr_poly_t tmp, poly; int status; tmp->coeffs = ((gr_vec_struct *) x)->entries; tmp->length = ((gr_vec_struct *) x)->length; gr_ctx_init_fmpq(QQ); /* no need to free */ gr_poly_init(poly, QQ); status = gr_poly_set_gr_poly_other(poly, tmp, VECTOR_CTX(x_ctx)->base_ring, QQ); if (status == GR_SUCCESS) { fmpq_poly_fit_length(res, poly->length); _fmpq_vec_get_fmpz_vec_fmpz(res->coeffs, res->den, poly->coeffs, poly->length); _fmpq_poly_set_length(res, poly->length); } gr_poly_clear(poly, QQ); return status; } return GR_UNABLE; } int _gr_fmpq_poly_get_ui(ulong * res, const fmpq_poly_t x, const gr_ctx_t ctx) { if (fmpq_poly_length(x) == 0) { *res = 0; return GR_SUCCESS; } if (fmpq_poly_length(x) == 1 && fmpz_is_one(x->den)) { if (fmpz_sgn(x->coeffs) < 0 || fmpz_cmp_ui(x->coeffs, UWORD_MAX) > 0) { return GR_DOMAIN; } else { *res = fmpz_get_ui(x->coeffs); return GR_SUCCESS; } } return GR_DOMAIN; } int _gr_fmpq_poly_get_si(slong * res, const fmpq_poly_t x, const gr_ctx_t ctx) { if (fmpq_poly_length(x) == 0) { *res = 0; return GR_SUCCESS; } if (fmpq_poly_length(x) == 1 && fmpz_is_one(x->den)) { if (!fmpz_fits_si(x->coeffs)) { return GR_DOMAIN; } else { *res = fmpz_get_si(x->coeffs); return GR_SUCCESS; } } return GR_DOMAIN; } int _gr_fmpq_poly_get_fmpz(fmpz_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { if (fmpq_poly_length(x) == 0) { fmpz_zero(res); return GR_SUCCESS; } if (fmpq_poly_length(x) == 1 && fmpz_is_one(x->den)) { fmpz_set(res, x->coeffs); return GR_SUCCESS; } return GR_DOMAIN; } int _gr_fmpq_poly_get_fmpq(fmpq_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { if (fmpq_poly_length(x) == 0) { fmpq_zero(res); return GR_SUCCESS; } if (fmpq_poly_length(x) == 1) { fmpz_set(fmpq_numref(res), x->coeffs); fmpz_set(fmpq_denref(res), x->den); return GR_SUCCESS; } return GR_DOMAIN; } truth_t _gr_fmpq_poly_is_zero(const fmpq_poly_t x, const gr_ctx_t ctx) { return fmpq_poly_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpq_poly_is_one(const fmpq_poly_t x, const gr_ctx_t ctx) { return fmpq_poly_is_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpq_poly_is_neg_one(const fmpq_poly_t x, const gr_ctx_t ctx) { return (x->length == 1 && x->coeffs[0] == -1 && fmpz_is_one(x->den)) ? T_TRUE : T_FALSE; } truth_t _gr_fmpq_poly_equal(const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { return fmpq_poly_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_fmpq_poly_set(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_set(res, x); return GR_SUCCESS; } int _gr_fmpq_poly_neg(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_neg(res, x); return GR_SUCCESS; } int _gr_fmpq_poly_add(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { fmpq_poly_add(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_sub(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { fmpq_poly_sub(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_mul(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { fmpq_poly_mul(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_mul_ui(fmpq_poly_t res, const fmpq_poly_t x, ulong y, const gr_ctx_t ctx) { fmpq_poly_scalar_mul_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_mul_si(fmpq_poly_t res, const fmpq_poly_t x, slong y, const gr_ctx_t ctx) { fmpq_poly_scalar_mul_si(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_mul_fmpz(fmpq_poly_t res, const fmpq_poly_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpq_poly_scalar_mul_fmpz(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_mul_two(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { /* fmpq_poly_scalar_mul_2exp(res, x, 1); */ fmpq_poly_scalar_mul_ui(res, x, 2); return GR_SUCCESS; } int _gr_fmpq_poly_sqr(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_mul(res, x, x); return GR_SUCCESS; } int _gr_fmpq_poly_inv(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { if (x->length == 1) { fmpq_poly_inv(res, x); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpq_poly_div(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { if (fmpq_poly_is_zero(y)) { return GR_DOMAIN; } else { if (fmpq_poly_divides(res, x, y)) return GR_SUCCESS; else return GR_DOMAIN; } } int _gr_fmpq_poly_divexact(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { if (fmpq_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpq_poly_div(res, x, y); return GR_SUCCESS; } } int _gr_fmpq_poly_divexact_ui(fmpq_poly_t res, const fmpq_poly_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpq_poly_scalar_div_ui(res, x, y); return GR_SUCCESS; } } int _gr_fmpq_poly_divexact_si(fmpq_poly_t res, const fmpq_poly_t x, slong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpq_poly_scalar_div_si(res, x, y); return GR_SUCCESS; } } int _gr_fmpq_poly_divexact_fmpz(fmpq_poly_t res, const fmpq_poly_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { fmpq_poly_scalar_div_fmpz(res, x, y); return GR_SUCCESS; } } truth_t _gr_fmpq_poly_is_invertible(const fmpq_poly_t x, const gr_ctx_t ctx) { return (x->length == 1) ? T_TRUE : T_FALSE; } /* todo: efficient algo */ truth_t _gr_fmpq_poly_divides(const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { truth_t res; fmpq_poly_t tmp; fmpq_poly_init(tmp); res = fmpq_poly_divides(tmp, y, x) ? T_TRUE : T_FALSE; fmpq_poly_clear(tmp); return res; } int _gr_fmpq_poly_euclidean_div(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { if (fmpq_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpq_poly_div(res, x, y); return GR_SUCCESS; } } int _gr_fmpq_poly_euclidean_rem(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { if (fmpq_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpq_poly_rem(res, x, y); return GR_SUCCESS; } } int _gr_fmpq_poly_euclidean_divrem(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { if (fmpq_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpq_poly_divrem(res1, res2, x, y); return GR_SUCCESS; } } int _gr_fmpq_poly_gcd(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { fmpq_poly_gcd(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_lcm(fmpq_poly_t res, const fmpq_poly_t x, const fmpq_poly_t y, const gr_ctx_t ctx) { fmpq_poly_lcm(res, x, y); return GR_SUCCESS; } int _gr_fmpq_poly_pow_ui(fmpq_poly_t res, const fmpq_poly_t x, ulong exp, const gr_ctx_t ctx) { fmpq_poly_pow(res, x, exp); return GR_SUCCESS; } int _gr_fmpq_poly_pow_si(fmpq_poly_t res, const fmpq_poly_t x, slong exp, const gr_ctx_t ctx) { if (exp < 0) { if (x->length == 1) { fmpq_poly_inv(res, x); fmpq_poly_pow(res, res, -exp); return GR_SUCCESS; } return GR_DOMAIN; } else { return _gr_fmpq_poly_pow_ui(res, x, exp, ctx); } } int _gr_fmpq_poly_pow_fmpz(fmpq_poly_t res, const fmpq_poly_t x, const fmpz_t exp, gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*exp)) { return _gr_fmpq_poly_pow_si(res, x, *exp, ctx); } else if (fmpq_poly_is_one(x) || gr_is_neg_one(x, ctx) == T_TRUE) { if (fmpq_poly_is_one(x) || fmpz_is_even(exp)) fmpq_poly_one(res); else fmpq_poly_set_si(res, -1); return GR_SUCCESS; } else if (fmpq_poly_is_zero(x) && fmpz_sgn(exp) > 0) { fmpq_poly_zero(res); return GR_SUCCESS; } else if (fmpz_sgn(exp) < 0) { return GR_DOMAIN; } else { return GR_UNABLE; } } int _gr_fmpq_poly_numerator(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_set(res, x); fmpz_one(fmpq_poly_denref(res)); return GR_SUCCESS; } int _gr_fmpq_poly_denominator(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { fmpq_poly_set_fmpz(res, fmpq_poly_denref(x)); return GR_SUCCESS; } /* todo: fmpq_poly_sqrt, fmpq_poly_is_square truth_t _gr_fmpq_poly_is_square(const fmpq_poly_t x, const gr_ctx_t ctx) { truth_t res; fmpq_poly_t tmp; fmpq_poly_init(tmp); res = fmpq_poly_sqrt(tmp, x) ? T_TRUE : T_FALSE; fmpq_poly_clear(tmp); return res; } int _gr_fmpq_poly_sqrt(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { if (fmpq_poly_sqrt(res, x)) { return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpq_poly_rsqrt(fmpq_poly_t res, const fmpq_poly_t x, const gr_ctx_t ctx) { return GR_UNABLE; } */ int _fmpq_poly_methods_initialized = 0; gr_static_method_table _fmpq_poly_methods; gr_method_tab_input _fmpq_poly_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpq_poly_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpq_poly_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpq_poly_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpq_poly_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpq_poly_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpq_poly_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpq_poly_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpq_poly_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpq_poly_one}, {GR_METHOD_GEN, (gr_funcptr) _gr_fmpq_poly_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpq_poly_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpq_poly_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_fmpq_poly_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpq_poly_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpq_poly_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpq_poly_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpq_poly_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpq_poly_set_fmpz}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fmpq_poly_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_fmpq_poly_get_ui}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_fmpq_poly_get_si}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_fmpq_poly_get_fmpz}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpq_poly_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpq_poly_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpq_poly_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpq_poly_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fmpq_poly_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpq_poly_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fmpq_poly_mul_fmpz}, /* {GR_METHOD_ADDMUL_UI, (gr_funcptr) _gr_fmpq_poly_addmul_ui}, */ /* {GR_METHOD_ADDMUL_SI, (gr_funcptr) _gr_fmpq_poly_addmul_si}, */ /* {GR_METHOD_ADDMUL_FMPZ, (gr_funcptr) _gr_fmpq_poly_addmul_fmpz}, */ /* {GR_METHOD_SUBMUL_UI, (gr_funcptr) _gr_fmpq_poly_submul_ui}, */ /* {GR_METHOD_SUBMUL_SI, (gr_funcptr) _gr_fmpq_poly_submul_si}, */ /* {GR_METHOD_SUBMUL_FMPZ, (gr_funcptr) _gr_fmpq_poly_submul_fmpz}, */ {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_fmpq_poly_mul_two}, {GR_METHOD_SQR, (gr_funcptr) _gr_fmpq_poly_sqr}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpq_poly_div}, {GR_METHOD_DIVEXACT, (gr_funcptr) _gr_fmpq_poly_divexact}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_fmpq_poly_divexact_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_fmpq_poly_divexact_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_fmpq_poly_divexact_fmpz}, {GR_METHOD_DIVEXACT_UI, (gr_funcptr) _gr_fmpq_poly_divexact_ui}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) _gr_fmpq_poly_divexact_si}, {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) _gr_fmpq_poly_divexact_fmpz}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpq_poly_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpq_poly_inv}, {GR_METHOD_DIVIDES, (gr_funcptr) _gr_fmpq_poly_divides}, {GR_METHOD_EUCLIDEAN_DIV, (gr_funcptr) _gr_fmpq_poly_euclidean_div}, {GR_METHOD_EUCLIDEAN_REM, (gr_funcptr) _gr_fmpq_poly_euclidean_rem}, {GR_METHOD_EUCLIDEAN_DIVREM,(gr_funcptr) _gr_fmpq_poly_euclidean_divrem}, {GR_METHOD_GCD, (gr_funcptr) _gr_fmpq_poly_gcd}, {GR_METHOD_LCM, (gr_funcptr) _gr_fmpq_poly_lcm}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpq_poly_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_fmpq_poly_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpq_poly_pow_fmpz}, {GR_METHOD_NUMERATOR, (gr_funcptr) _gr_fmpq_poly_numerator}, {GR_METHOD_DENOMINATOR, (gr_funcptr) _gr_fmpq_poly_denominator}, /* {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpq_poly_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpq_poly_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_fmpq_poly_rsqrt}, */ {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpq_poly(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_FMPQ_POLY; ctx->sizeof_elem = sizeof(fmpq_poly_struct); ctx->size_limit = WORD_MAX; ctx->methods = _fmpq_poly_methods; if (!_fmpq_poly_methods_initialized) { gr_method_tab_init(_fmpq_poly_methods, _fmpq_poly_methods_input); _fmpq_poly_methods_initialized = 1; } } flint-3.1.3/src/gr/fmpz.c000066400000000000000000000672271461254215100151700ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fexpr.h" #include "qqbar.h" #include "fmpz_factor.h" #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpq.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_special.h" #include "gmpcompat.h" int _gr_fmpz_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Integer ring (fmpz)"); return GR_SUCCESS; } void _gr_fmpz_init(fmpz_t x, const gr_ctx_t ctx) { fmpz_init(x); } void _gr_fmpz_clear(fmpz_t x, const gr_ctx_t ctx) { fmpz_clear(x); } void _gr_fmpz_swap(fmpz_t x, fmpz_t y, const gr_ctx_t ctx) { fmpz_t t; *t = *x; *x = *y; *y = *t; } void _gr_fmpz_set_shallow(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_fmpz_randtest(fmpz_t res, flint_rand_t state, const gr_ctx_t ctx) { switch (n_randint(state, 4)) { case 0: fmpz_randtest(res, state, 100); break; default: fmpz_randtest(res, state, 10); } return GR_SUCCESS; } int _gr_fmpz_write(gr_stream_t out, const fmpz_t x, const gr_ctx_t ctx) { gr_stream_write_fmpz(out, x); return GR_SUCCESS; } int _gr_fmpz_zero(fmpz_t x, const gr_ctx_t ctx) { fmpz_zero(x); return GR_SUCCESS; } int _gr_fmpz_one(fmpz_t x, const gr_ctx_t ctx) { fmpz_one(x); return GR_SUCCESS; } int _gr_fmpz_set_si(fmpz_t res, slong v, const gr_ctx_t ctx) { fmpz_set_si(res, v); return GR_SUCCESS; } int _gr_fmpz_set_ui(fmpz_t res, ulong v, const gr_ctx_t ctx) { fmpz_set_ui(res, v); return GR_SUCCESS; } int _gr_fmpz_set_fmpz(fmpz_t res, const fmpz_t v, const gr_ctx_t ctx) { fmpz_set(res, v); return GR_SUCCESS; } int _gr_fmpz_set_fmpq(fmpz_t res, const fmpq_t v, const gr_ctx_t ctx) { if (fmpz_is_one(fmpq_denref(v))) { fmpz_set(res, fmpq_numref(v)); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpz_set_d(fmpz_t res, double x, const gr_ctx_t ctx) { if (x != x || x == HUGE_VAL || x == -HUGE_VAL) return GR_DOMAIN; if (x != floor(x)) return GR_DOMAIN; fmpz_set_d(res, x); return GR_SUCCESS; } int _gr_fmpz_set_other(fmpz_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: fmpz_set(res, x); return GR_SUCCESS; case GR_CTX_FMPQ: return _gr_fmpz_set_fmpq(res, x, ctx); case GR_CTX_REAL_ALGEBRAIC_QQBAR: case GR_CTX_COMPLEX_ALGEBRAIC_QQBAR: if (qqbar_is_integer(x)) { qqbar_get_fmpz(res, x); return GR_SUCCESS; } return GR_DOMAIN; } /* handles fexpr */ return gr_generic_set_other(res, x, x_ctx, ctx); } int _gr_fmpz_set_str(fmpz_t res, const char * x, gr_ctx_t ctx) { if (!fmpz_set_str(res, x, 10)) return GR_SUCCESS; return gr_generic_set_str(res, x, ctx); } int _gr_fmpz_get_ui(ulong * res, const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_sgn(x) < 0 || fmpz_cmp_ui(x, UWORD_MAX) > 0) return GR_DOMAIN; *res = fmpz_get_ui(x); return GR_SUCCESS; } int _gr_fmpz_get_si(slong * res, const fmpz_t x, const gr_ctx_t ctx) { if (!fmpz_fits_si(x)) return GR_DOMAIN; *res = fmpz_get_si(x); return GR_SUCCESS; } int _gr_fmpz_get_d(double * res, const fmpz_t x, const gr_ctx_t ctx) { *res = fmpz_get_d(x); return GR_SUCCESS; } int _gr_fmpz_get_fmpq(fmpq_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpq_set_fmpz(res, x); return GR_SUCCESS; } int _gr_fmpz_get_fexpr(fexpr_t res, const fmpz_t x, const gr_ctx_t ctx) { fexpr_set_fmpz(res, x); return GR_SUCCESS; } truth_t _gr_fmpz_is_zero(const fmpz_t x, const gr_ctx_t ctx) { return fmpz_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_is_one(const fmpz_t x, const gr_ctx_t ctx) { return fmpz_is_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_is_neg_one(const fmpz_t x, const gr_ctx_t ctx) { return (*x == -1) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_equal(const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { return fmpz_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_fmpz_set(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_set(res, x); return GR_SUCCESS; } int _gr_fmpz_neg(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_neg(res, x); return GR_SUCCESS; } int _gr_fmpz_add(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_add(res, x, y); return GR_SUCCESS; } int _gr_fmpz_add_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { fmpz_add_si(res, x, y); return GR_SUCCESS; } int _gr_fmpz_add_ui(fmpz_t res, const fmpz_t x, ulong y, const gr_ctx_t ctx) { fmpz_add_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_sub(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_sub(res, x, y); return GR_SUCCESS; } int _gr_fmpz_sub_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { fmpz_sub_si(res, x, y); return GR_SUCCESS; } int _gr_fmpz_sub_ui(fmpz_t res, const fmpz_t x, ulong y, const gr_ctx_t ctx) { fmpz_sub_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_mul(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_mul(res, x, y); return GR_SUCCESS; } int _gr_fmpz_mul_ui(fmpz_t res, const fmpz_t x, ulong y, const gr_ctx_t ctx) { fmpz_mul_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_mul_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { fmpz_mul_si(res, x, y); return GR_SUCCESS; } int _gr_fmpz_addmul(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_addmul(res, x, y); return GR_SUCCESS; } int _gr_fmpz_addmul_ui(fmpz_t res, const fmpz_t x, ulong y, const gr_ctx_t ctx) { fmpz_addmul_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_addmul_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { fmpz_addmul_si(res, x, y); return GR_SUCCESS; } int _gr_fmpz_submul(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_submul(res, x, y); return GR_SUCCESS; } int _gr_fmpz_submul_ui(fmpz_t res, const fmpz_t x, ulong y, const gr_ctx_t ctx) { fmpz_submul_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_submul_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { fmpz_submul_si(res, x, y); return GR_SUCCESS; } int _gr_fmpz_mul_two(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_mul_2exp(res, x, 1); return GR_SUCCESS; } int _gr_fmpz_sqr(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_mul(res, x, x); return GR_SUCCESS; } int _gr_fmpz_mul_2exp_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { if (y >= 0) { fmpz_mul_2exp(res, x, y); return GR_SUCCESS; } else if (fmpz_is_zero(x)) { fmpz_zero(res); return GR_SUCCESS; } else { ulong val; ulong v = -(ulong) y; val = fmpz_val2(x); if (val >= v) { fmpz_tdiv_q_2exp(res, x, v); return GR_SUCCESS; } else { return GR_DOMAIN; } } } int _gr_fmpz_mul_2exp_fmpz(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(x)) { fmpz_zero(res); return GR_SUCCESS; } if (COEFF_IS_MPZ(*y)) return GR_UNABLE; return _gr_fmpz_mul_2exp_si(res, x, *y, ctx); } int _gr_fmpz_inv(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_is_pm1(x)) { fmpz_set(res, x); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpz_div(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { if (fmpz_divides(res, x, y)) return GR_SUCCESS; else return GR_DOMAIN; } } int _gr_fmpz_divexact(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { fmpz_divexact(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_divexact_ui(fmpz_t res, const fmpz_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpz_divexact_ui(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_divexact_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpz_divexact_si(res, x, y); return GR_SUCCESS; } } truth_t _gr_fmpz_is_invertible(const fmpz_t x, const gr_ctx_t ctx) { return fmpz_is_pm1(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_divides(const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { return fmpz_divisible(y, x) ? T_TRUE : T_FALSE; } int _gr_fmpz_euclidean_div(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { fmpz_fdiv_q(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_euclidean_rem(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { fmpz_fdiv_r(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_euclidean_divrem(fmpz_t res1, fmpz_t res2, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { fmpz_fdiv_qr(res1, res2, x, y); return GR_SUCCESS; } } int _gr_fmpz_gcd(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_gcd(res, x, y); return GR_SUCCESS; } int _gr_fmpz_lcm(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_lcm(res, x, y); return GR_SUCCESS; } int _gr_fmpz_factor(gr_ptr c, gr_vec_t factors, gr_vec_t exponents, gr_srcptr x, int flags, gr_ctx_t ctx) { fmpz_factor_t fac; slong i; fmpz_factor_init(fac); fmpz_factor(fac, x); fmpz_set_si(c, fac->sign); gr_vec_set_length(factors, fac->num, ctx); gr_vec_set_length(exponents, fac->num, ctx); for (i = 0; i < fac->num; i++) { fmpz_swap((fmpz *) (factors->entries) + i, fac->p + i); fmpz_set_ui((fmpz *) (exponents->entries) + i, fac->exp[i]); } fmpz_factor_clear(fac); return GR_SUCCESS; } int _gr_fmpz_pow_ui(fmpz_t res, const fmpz_t x, ulong exp, const gr_ctx_t ctx) { fmpz_pow_ui(res, x, exp); return GR_SUCCESS; } int _gr_fmpz_pow_si(fmpz_t res, const fmpz_t x, slong exp, const gr_ctx_t ctx) { if (exp < 0) { if (fmpz_is_pm1(x)) { if (fmpz_is_one(x) || exp % 2 == 0) fmpz_one(res); else fmpz_set_si(res, -1); return GR_SUCCESS; } return GR_DOMAIN; } else { return _gr_fmpz_pow_ui(res, x, exp, ctx); } } int _gr_fmpz_pow_fmpz(fmpz_t res, const fmpz_t x, const fmpz_t exp, const gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*exp)) { return _gr_fmpz_pow_si(res, x, *exp, ctx); } else if (fmpz_is_pm1(x)) { if (fmpz_is_one(x) || fmpz_is_even(exp)) fmpz_one(res); else fmpz_set_si(res, -1); return GR_SUCCESS; } else if (fmpz_is_zero(x) && fmpz_sgn(exp) > 0) { fmpz_zero(res); return GR_SUCCESS; } else if (fmpz_sgn(exp) < 0) { return GR_DOMAIN; } else { return GR_UNABLE; } } truth_t _gr_fmpz_is_square(const fmpz_t x, const gr_ctx_t ctx) { return fmpz_is_square(x) ? T_TRUE : T_FALSE; } int _gr_fmpz_sqrt(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_sgn(x) < 0) return GR_DOMAIN; if (fmpz_root(res, x, 2)) { return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpz_rsqrt(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_is_one(x)) { fmpz_one(res); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpz_abs(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_abs(res, x); return GR_SUCCESS; } int _gr_fmpz_im(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_zero(res); return GR_SUCCESS; } int _gr_fmpz_sgn(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_set_si(res, fmpz_sgn(x)); return GR_SUCCESS; } int _gr_fmpz_cmp(int * res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { int cmp = fmpz_cmp(x, y); if (cmp < 0) cmp = -1; if (cmp > 0) cmp = 1; *res = cmp; return GR_SUCCESS; } int _gr_fmpz_cmpabs(int * res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { int cmp = fmpz_cmpabs(x, y); if (cmp < 0) cmp = -1; if (cmp > 0) cmp = 1; *res = cmp; return GR_SUCCESS; } int _gr_fmpz_fib_ui(fmpz_t res, ulong n, gr_ctx_t ctx) { if (n <= 1000000) { fmpz_fib_ui(res, n); return GR_SUCCESS; } else { return gr_generic_fib_ui(res, n, ctx); } } int _gr_fmpz_fib_fmpz(fmpz_t res, const fmpz_t n, gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*n)) { slong i = *n; if (i >= 0) { return _gr_fmpz_fib_ui(res, i, ctx); } else { int status = _gr_fmpz_fib_ui(res, -i, ctx); if (!(i & 1)) fmpz_neg(res, res); return status; } } return GR_UNABLE; } /* experimental: inlining for small values */ static void _fmpz_add_inline(fmpz_t z, const fmpz_t x, const fmpz_t y) { fmpz f, g; f = *x; g = *y; if (!COEFF_IS_MPZ(f) && !COEFF_IS_MPZ(g)) fmpz_set_si(z, f + g); else fmpz_add(z, x, y); } static void _fmpz_sub_inline(fmpz_t z, const fmpz_t x, const fmpz_t y) { fmpz f, g; f = *x; g = *y; if (!COEFF_IS_MPZ(f) && !COEFF_IS_MPZ(g)) fmpz_set_si(z, f - g); else fmpz_sub(z, x, y); } int _gr_fmpz_vec_is_zero(const fmpz * vec, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) if (!fmpz_is_zero(vec + i)) return T_FALSE; return T_TRUE; } int _gr_fmpz_vec_equal(const fmpz * vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) { fmpz a, b; a = vec1[i]; b = vec2[i]; if (a != b) { if (!COEFF_IS_MPZ(a) || !COEFF_IS_MPZ(b) || mpz_cmp(COEFF_TO_PTR(a), COEFF_TO_PTR(b)) != 0) return T_FALSE; } } return T_TRUE; } int _gr_fmpz_vec_add(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) _fmpz_add_inline(res + i, vec1 + i, vec2 + i); return GR_SUCCESS; } int _gr_fmpz_vec_sub(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) _fmpz_sub_inline(res + i, vec1 + i, vec2 + i); return GR_SUCCESS; } int _gr_fmpz_vec_sum(fmpz_t res, const fmpz * vec, slong len, gr_ctx_t ctx) { if (len <= 2) { if (len == 2) fmpz_add(res, vec + 0, vec + 1); else if (len == 1) fmpz_set(res, vec); else fmpz_zero(res); } else { ulong hi, lo; slong i; fmpz f; __mpz_struct * f_mpz; __mpz_struct * res_mpz = NULL; hi = lo = 0; for (i = 0; i < len; i++) { f = vec[i]; if (!COEFF_IS_MPZ(f)) { if (f >= 0) add_ssaaaa(hi, lo, hi, lo, 0, f); else sub_ddmmss(hi, lo, hi, lo, 0, -f); } else { f_mpz = COEFF_TO_PTR(f); if (res_mpz == NULL) { res_mpz = _fmpz_promote(res); mpz_set(res_mpz, f_mpz); } else { mpz_add(res_mpz, res_mpz, f_mpz); } } } if (res_mpz == NULL) { fmpz_set_signed_uiui(res, hi, lo); } else { if (hi != 0 || lo != 0) flint_mpz_add_signed_uiui(res_mpz, res_mpz, hi, lo); _fmpz_demote_val(res); } } return GR_SUCCESS; } int _gr_fmpz_vec_dot(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { _fmpz_vec_dot_general(res, initial, subtract, vec1, vec2, 0, len); return GR_SUCCESS; } int _gr_fmpz_vec_dot_rev(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { _fmpz_vec_dot_general(res, initial, subtract, vec1, vec2, 1, len); return GR_SUCCESS; } int _gr_fmpz_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n, gr_ctx_t ctx) { if (len1 >= len2) _fmpz_poly_mullow(res, poly1, len1, poly2, len2, n); else _fmpz_poly_mullow(res, poly2, len2, poly1, len1, n); return GR_SUCCESS; } /* integer roots of integer polynomial */ int _gr_fmpz_roots_gr_poly(gr_vec_t roots, gr_vec_t mult, const fmpz_poly_t poly, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; /* normally we need a separate context object for the exponents here, but since the coefficient ring is fmpz, we can use the same object */ if (poly->length == 1) { gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ctx); } else if (poly->length == 2) { fmpz_t t; fmpz_init(t); if (fmpz_divides(t, poly->coeffs + 0, poly->coeffs + 1)) { gr_vec_set_length(roots, 1, ctx); gr_vec_set_length(mult, 1, ctx); fmpz_neg(roots->entries, t); fmpz_one(mult->entries); } else { gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ctx); } fmpz_clear(t); } else { /* todo: better algorithm */ fmpz_poly_factor_t fac; slong i, j, num; fmpz_poly_factor_init(fac); fmpz_poly_factor(fac, poly); num = 0; for (i = 0; i < fac->num; i++) if (fac->p[i].length == 2 && fmpz_is_one(fac->p[i].coeffs + 1)) num++; gr_vec_set_length(roots, num, ctx); gr_vec_set_length(mult, num, ctx); for (i = j = 0; i < fac->num; i++) { if (fac->p[i].length == 2 && fmpz_is_one(fac->p[i].coeffs + 1)) { fmpz_neg(((fmpz *) roots->entries) + j, fac->p[i].coeffs); fmpz_set_ui(((fmpz *) mult->entries) + j, fac->exp[i]); j++; } } fmpz_poly_factor_clear(fac); } return GR_SUCCESS; } int _gr_fmpz_roots_gr_poly_other(gr_vec_t roots, gr_vec_t mult, /* const gr_poly_t */ const void * poly, gr_ctx_t other_ctx, int flags, gr_ctx_t ctx) { if (other_ctx->which_ring == GR_CTX_FMPZ) return _gr_fmpz_roots_gr_poly(roots, mult, poly, flags, ctx); return GR_UNABLE; } int _gr_fmpz_mat_mul(fmpz_mat_t res, const fmpz_mat_t x, const fmpz_mat_t y, gr_ctx_t ctx) { fmpz_mat_mul(res, x, y); return GR_SUCCESS; } int _gr_fmpz_mat_det(fmpz_t res, const fmpz_mat_t x, const gr_ctx_t ctx) { fmpz_mat_det(res, x); return GR_SUCCESS; } int _fmpz_methods_initialized = 0; gr_static_method_table _fmpz_methods; gr_method_tab_input _fmpz_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpz_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpz_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpz_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpz_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpz_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpz_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpz_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpz_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpz_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpz_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpz_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_fmpz_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpz_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpz_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpz_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpz_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_fmpz_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fmpz_set_other}, {GR_METHOD_SET_D, (gr_funcptr) _gr_fmpz_set_d}, {GR_METHOD_SET_STR, (gr_funcptr) _gr_fmpz_set_str}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_GET_FMPQ, (gr_funcptr) _gr_fmpz_get_fmpq}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_fmpz_get_ui}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_fmpz_get_si}, {GR_METHOD_GET_D, (gr_funcptr) _gr_fmpz_get_d}, {GR_METHOD_GET_FEXPR, (gr_funcptr) _gr_fmpz_get_fexpr}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpz_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpz_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_fmpz_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_fmpz_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_fmpz_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpz_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_fmpz_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_fmpz_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_fmpz_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpz_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fmpz_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpz_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fmpz_mul}, {GR_METHOD_ADDMUL, (gr_funcptr) _gr_fmpz_addmul}, {GR_METHOD_ADDMUL_UI, (gr_funcptr) _gr_fmpz_addmul_ui}, {GR_METHOD_ADDMUL_SI, (gr_funcptr) _gr_fmpz_addmul_si}, {GR_METHOD_ADDMUL_FMPZ, (gr_funcptr) _gr_fmpz_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_fmpz_submul}, {GR_METHOD_SUBMUL_UI, (gr_funcptr) _gr_fmpz_submul_ui}, {GR_METHOD_SUBMUL_SI, (gr_funcptr) _gr_fmpz_submul_si}, {GR_METHOD_SUBMUL_FMPZ, (gr_funcptr) _gr_fmpz_submul}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_fmpz_mul_two}, {GR_METHOD_SQR, (gr_funcptr) _gr_fmpz_sqr}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) _gr_fmpz_mul_2exp_si}, {GR_METHOD_MUL_2EXP_FMPZ, (gr_funcptr) _gr_fmpz_mul_2exp_fmpz}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpz_div}, {GR_METHOD_DIVEXACT, (gr_funcptr) _gr_fmpz_divexact}, {GR_METHOD_DIVEXACT_UI, (gr_funcptr) _gr_fmpz_divexact_ui}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) _gr_fmpz_divexact_si}, {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) _gr_fmpz_divexact}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpz_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpz_inv}, {GR_METHOD_DIVIDES, (gr_funcptr) _gr_fmpz_divides}, {GR_METHOD_EUCLIDEAN_DIV, (gr_funcptr) _gr_fmpz_euclidean_div}, {GR_METHOD_EUCLIDEAN_REM, (gr_funcptr) _gr_fmpz_euclidean_rem}, {GR_METHOD_EUCLIDEAN_DIVREM,(gr_funcptr) _gr_fmpz_euclidean_divrem}, {GR_METHOD_GCD, (gr_funcptr) _gr_fmpz_gcd}, {GR_METHOD_LCM, (gr_funcptr) _gr_fmpz_lcm}, {GR_METHOD_FACTOR, (gr_funcptr) _gr_fmpz_factor}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpz_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_fmpz_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpz_pow_fmpz}, {GR_METHOD_POW, (gr_funcptr) _gr_fmpz_pow_fmpz}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpz_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpz_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_fmpz_rsqrt}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_CEIL, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_NINT, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_I, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_PI, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_ABS, (gr_funcptr) _gr_fmpz_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_RE, (gr_funcptr) _gr_fmpz_set}, {GR_METHOD_IM, (gr_funcptr) _gr_fmpz_im}, {GR_METHOD_SGN, (gr_funcptr) _gr_fmpz_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_fmpz_sgn}, {GR_METHOD_CMP, (gr_funcptr) _gr_fmpz_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) _gr_fmpz_cmpabs}, {GR_METHOD_FIB_UI, (gr_funcptr) _gr_fmpz_fib_ui}, {GR_METHOD_FIB_FMPZ, (gr_funcptr) _gr_fmpz_fib_fmpz}, {GR_METHOD_VEC_IS_ZERO, (gr_funcptr) _gr_fmpz_vec_is_zero}, {GR_METHOD_VEC_EQUAL, (gr_funcptr) _gr_fmpz_vec_equal}, {GR_METHOD_VEC_ADD, (gr_funcptr) _gr_fmpz_vec_add}, {GR_METHOD_VEC_SUB, (gr_funcptr) _gr_fmpz_vec_sub}, {GR_METHOD_VEC_SUM, (gr_funcptr) _gr_fmpz_vec_sum}, {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_fmpz_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_fmpz_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_fmpz_poly_mullow}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_fmpz_roots_gr_poly}, {GR_METHOD_POLY_ROOTS_OTHER,(gr_funcptr) _gr_fmpz_roots_gr_poly_other}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_fmpz_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) _gr_fmpz_mat_det}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpz(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_FMPZ; ctx->sizeof_elem = sizeof(fmpz); ctx->size_limit = WORD_MAX; ctx->methods = _fmpz_methods; if (!_fmpz_methods_initialized) { gr_method_tab_init(_fmpz_methods, _fmpz_methods_input); _fmpz_methods_initialized = 1; } } flint-3.1.3/src/gr/fmpz_mod.c000066400000000000000000000534571461254215100160270ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_mat.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #include "gr.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_mat.h" typedef struct { fmpz_mod_ctx_struct * ctx; truth_t is_prime; fmpz a; /* when used as finite field with defining polynomial x - a */ } _gr_fmpz_mod_ctx_struct; #define FMPZ_MOD_CTX(ring_ctx) ((((_gr_fmpz_mod_ctx_struct *)(ring_ctx))->ctx)) #define FMPZ_MOD_IS_PRIME(ring_ctx) (((_gr_fmpz_mod_ctx_struct *)(ring_ctx))->is_prime) #define FMPZ_MOD_CTX_A(ring_ctx) (&((((_gr_fmpz_mod_ctx_struct *)(ring_ctx))->a))) int _gr_fmpz_mod_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Integers mod "); gr_stream_write_fmpz(out, FMPZ_MOD_CTX(ctx)->n); gr_stream_write(out, " (fmpz)"); return GR_SUCCESS; } void _gr_fmpz_mod_ctx_clear(gr_ctx_t ctx) { fmpz_mod_ctx_clear(FMPZ_MOD_CTX(ctx)); flint_free(FMPZ_MOD_CTX(ctx)); fmpz_clear(FMPZ_MOD_CTX_A(ctx)); } truth_t _gr_fmpz_mod_ctx_is_field(gr_ctx_t ctx) { /* if (FMPZ_MOD_IS_PRIME(ctx) == T_UNKNOWN) FMPZ_MOD_IS_PRIME(ctx) = fmpz_is_prime(FMPZ_MOD_CTX(ctx)->n) ? T_TRUE : T_FALSE; */ return FMPZ_MOD_IS_PRIME(ctx); } void _gr_fmpz_mod_init(fmpz_t x, const gr_ctx_t ctx) { fmpz_init(x); } void _gr_fmpz_mod_clear(fmpz_t x, const gr_ctx_t ctx) { fmpz_clear(x); } void _gr_fmpz_mod_swap(fmpz_t x, fmpz_t y, const gr_ctx_t ctx) { fmpz_t t; *t = *x; *x = *y; *y = *t; } void _gr_fmpz_mod_set_shallow(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { *res = *x; } int _gr_fmpz_mod_randtest(fmpz_t res, flint_rand_t state, const gr_ctx_t ctx) { fmpz_mod_rand(res, state, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_write(gr_stream_t out, const fmpz_t x, const gr_ctx_t ctx) { gr_stream_write_fmpz(out, x); return GR_SUCCESS; } int _gr_fmpz_mod_zero(fmpz_t x, const gr_ctx_t ctx) { fmpz_zero(x); return GR_SUCCESS; } int _gr_fmpz_mod_one(fmpz_t x, const gr_ctx_t ctx) { if (fmpz_is_one(FMPZ_MOD_CTX(ctx)->n)) fmpz_zero(x); else fmpz_one(x); return GR_SUCCESS; } int _gr_fmpz_mod_set_si(fmpz_t res, slong v, const gr_ctx_t ctx) { fmpz_mod_set_si(res, v, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_set_ui(fmpz_t res, ulong v, const gr_ctx_t ctx) { fmpz_mod_set_ui(res, v, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } /* todo: public interface */ #define NMOD_CTX_REF(ring_ctx) (((nmod_t *)((ring_ctx)))) #define NMOD_CTX(ring_ctx) (*NMOD_CTX_REF(ring_ctx)) int _gr_fmpz_mod_set_other(fmpz_t res, gr_ptr v, gr_ctx_t v_ctx, const gr_ctx_t ctx) { if (v_ctx->which_ring == GR_CTX_FMPZ_MOD) { if (!fmpz_equal(FMPZ_MOD_CTX(ctx)->n, FMPZ_MOD_CTX(v_ctx)->n)) return GR_DOMAIN; fmpz_set(res, v); return GR_SUCCESS; } if (v_ctx->which_ring == GR_CTX_NMOD) { if (!fmpz_equal_ui(FMPZ_MOD_CTX(ctx)->n, NMOD_CTX(v_ctx).n)) return GR_DOMAIN; fmpz_set_ui(res, * (ulong *) v); return GR_SUCCESS; } return GR_UNABLE; } int _gr_fmpz_mod_set_fmpz(fmpz_t res, const fmpz_t v, const gr_ctx_t ctx) { fmpz_mod_set_fmpz(res, v, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_fmpz_mod_is_zero(const fmpz_t x, const gr_ctx_t ctx) { return fmpz_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_mod_is_one(const fmpz_t x, const gr_ctx_t ctx) { return fmpz_mod_is_one(x, FMPZ_MOD_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_mod_is_neg_one(const fmpz_t x, const gr_ctx_t ctx) { truth_t res; fmpz_t t; fmpz_init(t); fmpz_mod_set_si(t, -1, FMPZ_MOD_CTX(ctx)); res = fmpz_equal(t, x) ? T_TRUE : T_FALSE; fmpz_clear(t); return res; } truth_t _gr_fmpz_mod_equal(const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { return fmpz_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_fmpz_mod_set(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_set(res, x); return GR_SUCCESS; } int _gr_fmpz_mod_neg(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_mod_neg(res, x, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_add(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_mod_add(res, x, y, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_add_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { fmpz_mod_add_si(res, x, y, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_add_ui(fmpz_t res, const fmpz_t x, ulong y, const gr_ctx_t ctx) { fmpz_mod_add_ui(res, x, y, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_sub(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_mod_sub(res, x, y, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_mul(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { #if 1 fmpz_mod_mul(res, x, y, FMPZ_MOD_CTX(ctx)); #else fmpz_mul(res, x, y); fmpz_mod(res, res, FMPZ_MOD_CTX(ctx)->n); #endif return GR_SUCCESS; } int _gr_fmpz_mod_mul_si(fmpz_t res, const fmpz_t x, slong y, const gr_ctx_t ctx) { fmpz_mod_mul_si(res, x, y, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_addmul(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_mul(t, x, y); fmpz_add(t, t, res); fmpz_mod_set_fmpz(res, t, FMPZ_MOD_CTX(ctx)); fmpz_clear(t); return GR_SUCCESS; } int _gr_fmpz_mod_submul(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_mul(t, x, y); fmpz_sub(t, res, t); fmpz_mod_set_fmpz(res, t, FMPZ_MOD_CTX(ctx)); fmpz_clear(t); return GR_SUCCESS; } int _gr_fmpz_mod_mul_two(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_mod_add(res, x, x, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_sqr(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { fmpz_mod_mul(res, x, x, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_inv(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { /* todo: also check for -1 when fast? */ if (fmpz_is_one(x)) { fmpz_one(res); return GR_SUCCESS; } else if (fmpz_is_zero(x)) { fmpz_zero(res); return fmpz_is_one(FMPZ_MOD_CTX(ctx)->n) ? GR_SUCCESS : GR_DOMAIN; } else { int status; fmpz_t d; fmpz_init(d); fmpz_gcdinv(d, res, x, FMPZ_MOD_CTX(ctx)->n); if (fmpz_is_one(d)) status = GR_SUCCESS; else status = GR_DOMAIN; fmpz_clear(d); return status; } } int _gr_fmpz_mod_div(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { int status; fmpz_t t; fmpz_init(t); status = _gr_fmpz_mod_inv(t, y, ctx); if (status == GR_SUCCESS) fmpz_mod_mul(res, x, t, FMPZ_MOD_CTX(ctx)); else fmpz_zero(res); fmpz_clear(t); return status; } int _gr_fmpz_mod_div_nonunique(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { int status; #if 1 status = fmpz_mod_divides(res, x, y, FMPZ_MOD_CTX(ctx)) ? GR_SUCCESS : GR_DOMAIN; #else if (FMPZ_MOD_IS_PRIME(ctx) != T_TRUE) { status = fmpz_mod_divides(res, x, y, FMPZ_MOD_CTX(ctx)) ? GR_SUCCESS : GR_DOMAIN; } else { fmpz_t t; fmpz_init(t); status = _gr_fmpz_mod_inv(t, y, ctx); if (status == GR_SUCCESS) fmpz_mod_mul(res, x, t, FMPZ_MOD_CTX(ctx)); else fmpz_zero(res); fmpz_clear(t); } #endif return status; } truth_t _gr_fmpz_mod_divides(const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx) { truth_t res; fmpz_t t; fmpz_init(t); res = fmpz_mod_divides(t, y, x, FMPZ_MOD_CTX(ctx)) ? T_TRUE : T_FALSE; fmpz_clear(t); return res; } truth_t _gr_fmpz_mod_is_invertible(const fmpz_t x, const gr_ctx_t ctx) { return fmpz_mod_is_invertible(x, FMPZ_MOD_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fmpz_mod_pow_ui(fmpz_t res, const fmpz_t x, ulong exp, const gr_ctx_t ctx) { fmpz_mod_pow_ui(res, x, exp, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_pow_fmpz(fmpz_t res, const fmpz_t x, const fmpz_t exp, const gr_ctx_t ctx) { return fmpz_mod_pow_fmpz(res, x, exp, FMPZ_MOD_CTX(ctx)) ? GR_SUCCESS : GR_DOMAIN; } int _gr_fmpz_mod_sqrt(fmpz_t res, const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_is_zero(x) || fmpz_is_one(x)) { fmpz_set(res, x); return GR_SUCCESS; } else if (FMPZ_MOD_IS_PRIME(ctx) == T_TRUE) { return fmpz_sqrtmod(res, x, FMPZ_MOD_CTX(ctx)->n) ? GR_SUCCESS : GR_DOMAIN; } else { /* todo: implement the general case */ return GR_UNABLE; } } truth_t _gr_fmpz_mod_is_square(const fmpz_t x, const gr_ctx_t ctx) { if (fmpz_is_zero(x) || fmpz_is_one(x)) { return T_TRUE; } else if (FMPZ_MOD_IS_PRIME(ctx) == T_TRUE) { fmpz_t t; truth_t ans; fmpz_init(t); ans = fmpz_sqrtmod(t, x, FMPZ_MOD_CTX(ctx)->n) ? T_TRUE : T_FALSE; fmpz_clear(t); return ans; } else { /* todo: implement the general case */ return T_UNKNOWN; } } /* todo: len 1 */ int _gr_fmpz_mod_vec_dot(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { if (len <= 0) { if (initial == NULL) fmpz_zero(res); else fmpz_set(res, initial); return GR_SUCCESS; } _fmpz_vec_dot_general(res, initial, subtract, vec1, vec2, 0, len); fmpz_mod_set_fmpz(res, res, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } /* todo: len 1 */ int _gr_fmpz_mod_vec_dot_rev(fmpz_t res, const fmpz_t initial, int subtract, const fmpz * vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { if (len <= 0) { if (initial == NULL) fmpz_zero(res); else fmpz_set(res, initial); return GR_SUCCESS; } _fmpz_vec_dot_general(res, initial, subtract, vec1, vec2, 1, len); fmpz_mod_set_fmpz(res, res, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_vec_addmul_scalar(fmpz * res, const fmpz * vec, slong len, const fmpz_t c, gr_ctx_t ctx) { _fmpz_mod_vec_scalar_addmul_fmpz_mod(res, vec, len, c, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mod_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n, gr_ctx_t ctx) { if (len1 >= len2) _fmpz_mod_poly_mullow(res, poly1, len1, poly2, len2, n, FMPZ_MOD_CTX(ctx)); else _fmpz_mod_poly_mullow(res, poly2, len2, poly1, len1, n, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } /* fixme: duplicate _fmpz_mod_poly methods for error handling */ int _gr_fmpz_mod_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, gr_ctx_t ctx) { if (lenB <= 30 || lenA - lenB <= 5) { fmpz_t invB; int status; fmpz_init(invB); status = _gr_fmpz_mod_inv(invB, B + lenB - 1, ctx); if (status == GR_SUCCESS) _fmpz_mod_poly_divrem_basecase(Q, R, A, lenA, B, lenB, invB, FMPZ_MOD_CTX(ctx)); fmpz_clear(invB); return status; } else { return _gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, ctx); } } #define TUNE_TAB_SIZE 23 static const int tuning_bit_steps[TUNE_TAB_SIZE] = { 32, 45, 64, 91, 128, 181, 256, 362, 512, 724, 1024, 1448, 2048, 2896, 4096, 5793, 8192, 11585, 16384, 23170, 32768, 46341, 65536}; static const short inv_series_cutoff_tab[TUNE_TAB_SIZE] = {21, 14, 40, 39, 48, 60, 89, 72, 72, 54, 48, 39, 32, 24, 24, 20, 17, 18, 16, 15, 13, 12, 14, }; static const short div_series_cutoff_tab[TUNE_TAB_SIZE] = {23, 21, 52, 50, 66, 101, 106, 97, 106, 72, 60, 50, 44, 35, 38, 30, 26, 22, 20, 18, 16, 14, 22, }; static const slong find_cutoff(const short * tab, slong b) { slong i; i = 0; while (i + 1 < TUNE_TAB_SIZE && tuning_bit_steps[i + 1] <= b) i++; return tab[i]; } int _gr_fmpz_mod_poly_inv_series(fmpz * Q, const fmpz * B, slong lenB, slong len, gr_ctx_t ctx) { slong cutoff, bits; lenB = FLINT_MIN(len, lenB); if (lenB <= 20) return _gr_poly_inv_series_basecase(Q, B, lenB, len, ctx); bits = fmpz_bits(fmpz_mod_ctx_modulus(FMPZ_MOD_CTX(ctx))); cutoff = find_cutoff(inv_series_cutoff_tab, bits); if (lenB <= cutoff) return _gr_poly_inv_series_basecase(Q, B, lenB, len, ctx); else return _gr_poly_inv_series_newton(Q, B, lenB, len, cutoff, ctx); } /* todo: the fmpz_mod_poly module has better basecase code */ int _gr_fmpz_mod_poly_div_series(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, slong len, gr_ctx_t ctx) { slong cutoff, bits; lenA = FLINT_MIN(len, lenA); lenB = FLINT_MIN(len, lenB); if (lenB <= 20) return _gr_poly_div_series_basecase(Q, A, lenA, B, lenB, len, ctx); bits = fmpz_bits(fmpz_mod_ctx_modulus(FMPZ_MOD_CTX(ctx))); cutoff = find_cutoff(div_series_cutoff_tab, bits); if (lenB <= cutoff) return _gr_poly_div_series_basecase(Q, A, lenA, B, lenB, len, ctx); else return _gr_poly_div_series_newton(Q, A, lenA, B, lenB, len, cutoff, ctx); } /* todo: also need the _other version ... ? */ /* todo: implement generically */ int _gr_fmpz_mod_roots_gr_poly(gr_vec_t roots, gr_vec_t mult, const fmpz_mod_poly_t poly, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; { gr_ctx_t ZZ; fmpz_mod_poly_factor_t fac; slong i, num; int status = GR_SUCCESS; gr_ctx_init_fmpz(ZZ); fmpz_mod_poly_factor_init(fac, FMPZ_MOD_CTX(ctx)); if (gr_ctx_is_field(ctx) == T_TRUE) { fmpz_mod_poly_roots(fac, poly, 1, FMPZ_MOD_CTX(ctx)); } else { fmpz_factor_t nfac; fmpz_factor_init(nfac); fmpz_factor(nfac, FMPZ_MOD_CTX(ctx)->n); num = 0; for (i = 0; i < nfac->num; i++) num += nfac->exp[i]; if (num > 20) { status = GR_UNABLE; } else { if (!fmpz_mod_poly_roots_factored_with_length_limit(fac, poly, 1, 1000000, nfac, FMPZ_MOD_CTX(ctx))) status = GR_UNABLE; } fmpz_factor_clear(nfac); } if (status == GR_SUCCESS) { num = fac->num; gr_vec_set_length(roots, num, ctx); gr_vec_set_length(mult, num, ZZ); for (i = 0; i < num; i++) { fmpz_mod_neg(gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs, FMPZ_MOD_CTX(ctx)); /* work around flint bug: factors can be non-monic */ if (!fmpz_mod_is_one(fac->poly[i].coeffs + 1, FMPZ_MOD_CTX(ctx))) status |= _gr_fmpz_mod_div(gr_vec_entry_ptr(roots, i, ctx), gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs + 1, ctx); fmpz_set_ui(((fmpz *) mult->entries) + i, fac->exp[i]); } } fmpz_mod_poly_factor_clear(fac, FMPZ_MOD_CTX(ctx)); gr_ctx_clear(ZZ); return status; } } int _gr_fmpz_mod_mat_mul(fmpz_mod_mat_t res, const fmpz_mod_mat_t x, const fmpz_mod_mat_t y, gr_ctx_t ctx) { fmpz_mat_mul(res, x, y); _fmpz_mod_mat_reduce(res, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } /* todo: tune cutoff for different bit sizes */ /* also tune cutoff for triangular solving */ int _gr_fmpz_mod_mat_lu(slong * rank, slong * P, fmpz_mod_mat_t LU, const fmpz_mod_mat_t A, int rank_check, gr_ctx_t ctx) { return gr_mat_lu_recursive(rank, P, (gr_mat_struct *) LU, (const gr_mat_struct *) A, rank_check, 8, ctx); } int _gr_fmpz_mod_mat_det(fmpz_t res, const fmpz_mod_mat_t mat, gr_ctx_t ctx) { fmpz_mod_mat_det(res, mat, FMPZ_MOD_CTX(ctx)); return GR_SUCCESS; } int _fmpz_mod_methods_initialized = 0; gr_static_method_table _fmpz_mod_methods; gr_method_tab_input _fmpz_mod_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpz_mod_ctx_write}, {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_fmpz_mod_ctx_clear}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) _gr_fmpz_mod_ctx_is_field}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) _gr_fmpz_mod_ctx_is_field}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) _gr_fmpz_mod_ctx_is_field}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpz_mod_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpz_mod_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpz_mod_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpz_mod_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpz_mod_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpz_mod_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpz_mod_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpz_mod_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpz_mod_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpz_mod_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_fmpz_mod_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpz_mod_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpz_mod_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpz_mod_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpz_mod_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpz_mod_set_fmpz}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fmpz_mod_set_other}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpz_mod_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpz_mod_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_fmpz_mod_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_fmpz_mod_add_si}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpz_mod_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpz_mod_mul}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpz_mod_mul_si}, {GR_METHOD_ADDMUL, (gr_funcptr) _gr_fmpz_mod_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_fmpz_mod_submul}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_fmpz_mod_mul_two}, {GR_METHOD_SQR, (gr_funcptr) _gr_fmpz_mod_sqr}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpz_mod_div}, {GR_METHOD_DIV_NONUNIQUE, (gr_funcptr) _gr_fmpz_mod_div_nonunique}, {GR_METHOD_DIVIDES, (gr_funcptr) _gr_fmpz_mod_divides}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpz_mod_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpz_mod_inv}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpz_mod_pow_ui}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpz_mod_pow_fmpz}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpz_mod_sqrt}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpz_mod_is_square}, {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_fmpz_mod_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_fmpz_mod_vec_dot_rev}, {GR_METHOD_VEC_ADDMUL_SCALAR, (gr_funcptr) _gr_fmpz_mod_vec_addmul_scalar}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_fmpz_mod_poly_mullow}, {GR_METHOD_POLY_INV_SERIES, (gr_funcptr) _gr_fmpz_mod_poly_inv_series}, {GR_METHOD_POLY_DIV_SERIES, (gr_funcptr) _gr_fmpz_mod_poly_div_series}, {GR_METHOD_POLY_DIVREM, (gr_funcptr) _gr_fmpz_mod_poly_divrem}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_fmpz_mod_roots_gr_poly}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_fmpz_mod_mat_mul}, {GR_METHOD_MAT_LU, (gr_funcptr) _gr_fmpz_mod_mat_lu}, {GR_METHOD_MAT_DET, (gr_funcptr) _gr_fmpz_mod_mat_det}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpz_mod(gr_ctx_t ctx, const fmpz_t n) { ctx->which_ring = GR_CTX_FMPZ_MOD; ctx->sizeof_elem = sizeof(fmpz); FMPZ_MOD_CTX(ctx) = flint_malloc(sizeof(fmpz_mod_ctx_struct)); fmpz_mod_ctx_init(FMPZ_MOD_CTX(ctx), n); FMPZ_MOD_IS_PRIME(ctx) = T_UNKNOWN; fmpz_init(FMPZ_MOD_CTX_A(ctx)); ctx->size_limit = WORD_MAX; ctx->methods = _fmpz_mod_methods; if (!_fmpz_mod_methods_initialized) { gr_method_tab_init(_fmpz_mod_methods, _fmpz_mod_methods_input); _fmpz_mod_methods_initialized = 1; } } void _gr_ctx_init_fmpz_mod_from_ref(gr_ctx_t ctx, const void * fctx) { ctx->which_ring = GR_CTX_FMPZ_MOD; ctx->sizeof_elem = sizeof(fmpz); FMPZ_MOD_CTX(ctx) = (fmpz_mod_ctx_struct *) fctx; FMPZ_MOD_IS_PRIME(ctx) = T_UNKNOWN; fmpz_init(FMPZ_MOD_CTX_A(ctx)); ctx->size_limit = WORD_MAX; ctx->methods = _fmpz_mod_methods; if (!_fmpz_mod_methods_initialized) { gr_method_tab_init(_fmpz_mod_methods, _fmpz_mod_methods_input); _fmpz_mod_methods_initialized = 1; } } void gr_ctx_fmpz_mod_set_primality(gr_ctx_t ctx, truth_t is_prime) { FMPZ_MOD_IS_PRIME(ctx) = is_prime; } flint-3.1.3/src/gr/fmpz_mpoly.c000066400000000000000000000435451461254215100164050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "fmpz_mpoly_factor.h" #include "gr.h" #include "gr_vec.h" #include "gr_generic.h" typedef struct { fmpz_mpoly_ctx_t mctx; char ** vars; } _gr_fmpz_mpoly_ctx_t; #define MPOLYNOMIAL_CTX(ring_ctx) ((_gr_fmpz_mpoly_ctx_t *)(GR_CTX_DATA_AS_PTR(ring_ctx))) #define MPOLYNOMIAL_MCTX(ring_ctx) (MPOLYNOMIAL_CTX(ring_ctx)->mctx) int _gr_fmpz_mpoly_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Ring of multivariate polynomials over Integer ring (fmpz)"); gr_stream_write(out, " in "); gr_stream_write_si(out, MPOLYNOMIAL_MCTX(ctx)->minfo->nvars); gr_stream_write(out, " variables"); if (MPOLYNOMIAL_MCTX(ctx)->minfo->ord == ORD_LEX) gr_stream_write(out, ", lex order"); else if (MPOLYNOMIAL_MCTX(ctx)->minfo->ord == ORD_DEGLEX) gr_stream_write(out, ", deglex order"); else if (MPOLYNOMIAL_MCTX(ctx)->minfo->ord == ORD_DEGREVLEX) gr_stream_write(out, ", degrevlex order"); return GR_SUCCESS; } void _gr_fmpz_mpoly_ctx_clear(gr_ctx_t ctx) { if (MPOLYNOMIAL_CTX(ctx)->vars != NULL) { slong i; for (i = 0; i < MPOLYNOMIAL_MCTX(ctx)->minfo->nvars; i++) flint_free(MPOLYNOMIAL_CTX(ctx)->vars[i]); flint_free(MPOLYNOMIAL_CTX(ctx)->vars); } fmpz_mpoly_ctx_clear(MPOLYNOMIAL_MCTX(ctx)); flint_free(GR_CTX_DATA_AS_PTR(ctx)); } int _gr_fmpz_mpoly_ctx_set_gen_names(gr_ctx_t ctx, const char ** s) { slong i, nvars, len; nvars = MPOLYNOMIAL_MCTX(ctx)->minfo->nvars; if (MPOLYNOMIAL_CTX(ctx)->vars == NULL) { MPOLYNOMIAL_CTX(ctx)->vars = flint_malloc(nvars * sizeof(char *)); for (i = 0; i < nvars; i++) MPOLYNOMIAL_CTX(ctx)->vars[i] = NULL; } else { for (i = 0; i < nvars; i++) flint_free(MPOLYNOMIAL_CTX(ctx)->vars[i]); } for (i = 0; i < nvars; i++) { len = strlen(s[i]); MPOLYNOMIAL_CTX(ctx)->vars[i] = flint_realloc(MPOLYNOMIAL_CTX(ctx)->vars[i], len + 1); memcpy(MPOLYNOMIAL_CTX(ctx)->vars[i], s[i], len + 1); } return GR_SUCCESS; } void _gr_fmpz_mpoly_init(fmpz_mpoly_t res, gr_ctx_t ctx) { fmpz_mpoly_init(res, MPOLYNOMIAL_MCTX(ctx)); } void _gr_fmpz_mpoly_clear(fmpz_mpoly_t res, gr_ctx_t ctx) { fmpz_mpoly_clear(res, MPOLYNOMIAL_MCTX(ctx)); } void _gr_fmpz_mpoly_swap(fmpz_mpoly_t poly1, fmpz_mpoly_t poly2, gr_ctx_t ctx) { fmpz_mpoly_swap(poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); } void _gr_fmpz_mpoly_set_shallow(fmpz_mpoly_t res, const fmpz_mpoly_t poly, gr_ctx_t ctx) { *res = *poly; } int _gr_fmpz_mpoly_randtest(fmpz_mpoly_t res, flint_rand_t state, gr_ctx_t ctx) { slong bits; if (n_randint(state, 10) != 0) bits = 10; else bits = 100; fmpz_mpoly_randtest_bits(res, state, n_randint(state, 5), bits, 1 + n_randint(state, 3), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_randtest_small(fmpz_mpoly_t res, flint_rand_t state, gr_ctx_t ctx) { fmpz_mpoly_randtest_bits(res, state, n_randint(state, 3), 3, 1 + n_randint(state, 3), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } slong _gr_fmpz_mpoly_length(const fmpz_mpoly_t x, gr_ctx_t ctx) { return x->length; } int _gr_fmpz_mpoly_write(gr_stream_t out, fmpz_mpoly_t poly, gr_ctx_t ctx) { gr_stream_write_free(out, fmpz_mpoly_get_str_pretty(poly, (const char **) MPOLYNOMIAL_CTX(ctx)->vars, MPOLYNOMIAL_MCTX(ctx))); return GR_SUCCESS; } truth_t _gr_fmpz_mpoly_equal(const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, gr_ctx_t ctx) { return fmpz_mpoly_equal(poly1, poly2, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_mpoly_is_zero(const fmpz_mpoly_t poly, gr_ctx_t ctx) { return fmpz_mpoly_is_zero(poly, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_mpoly_is_one(const fmpz_mpoly_t poly, gr_ctx_t ctx) { return fmpz_mpoly_is_one(poly, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fmpz_mpoly_zero(fmpz_mpoly_t res, gr_ctx_t ctx) { fmpz_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_one(fmpz_mpoly_t res, gr_ctx_t ctx) { fmpz_mpoly_one(res, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_gens(gr_vec_t res, gr_ctx_t ctx) { slong i, n; n = MPOLYNOMIAL_MCTX(ctx)->minfo->nvars; gr_vec_set_length(res, n, ctx); for (i = 0; i < n; i++) fmpz_mpoly_gen(((fmpz_mpoly_struct *) res->entries) + i, i, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_set(fmpz_mpoly_t res, const fmpz_mpoly_t mat, gr_ctx_t ctx) { fmpz_mpoly_set(res, mat, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_set_si(fmpz_mpoly_t res, slong v, gr_ctx_t ctx) { fmpz_mpoly_set_si(res, v, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_set_ui(fmpz_mpoly_t res, ulong v, gr_ctx_t ctx) { fmpz_mpoly_set_ui(res, v, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_set_fmpz(fmpz_mpoly_t res, const fmpz_t v, gr_ctx_t ctx) { fmpz_mpoly_set_fmpz(res, v, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_set_fmpq(fmpz_mpoly_t res, const fmpq_t v, gr_ctx_t ctx) { if (!fmpz_is_one(fmpq_denref(v))) return GR_DOMAIN; fmpz_mpoly_set_fmpz(res, fmpq_numref(v), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_set_other(fmpz_mpoly_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { if (x_ctx->which_ring == GR_CTX_FMPZ_MPOLY) { /* fmpz_mpoly_set_fmpz_poly */ if (MPOLYNOMIAL_MCTX(ctx)->minfo->nvars == MPOLYNOMIAL_MCTX(x_ctx)->minfo->nvars && MPOLYNOMIAL_MCTX(ctx)->minfo->ord == MPOLYNOMIAL_MCTX(x_ctx)->minfo->ord) { fmpz_mpoly_set(res, x, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } } return gr_generic_set_other(res, x, x_ctx, ctx); } int _gr_fmpz_mpoly_neg(fmpz_mpoly_t res, const fmpz_mpoly_t mat, gr_ctx_t ctx) { fmpz_mpoly_neg(res, mat, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_add(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, gr_ctx_t ctx) { if (poly1->length + poly2->length > ctx->size_limit) { fmpz_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx)); return GR_UNABLE; } fmpz_mpoly_add(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_add_si(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, slong c, gr_ctx_t ctx) { fmpz_mpoly_add_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_add_ui(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, ulong c, gr_ctx_t ctx) { fmpz_mpoly_add_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_add_fmpz(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_t c, gr_ctx_t ctx) { fmpz_mpoly_add_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_sub(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, gr_ctx_t ctx) { if (poly1->length + poly2->length > ctx->size_limit) { fmpz_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx)); return GR_UNABLE; } fmpz_mpoly_sub(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_sub_si(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, slong c, gr_ctx_t ctx) { fmpz_mpoly_sub_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_sub_ui(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, ulong c, gr_ctx_t ctx) { fmpz_mpoly_sub_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_sub_fmpz(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_t c, gr_ctx_t ctx) { fmpz_mpoly_sub_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_mul(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, gr_ctx_t ctx) { if (poly1->length * poly2->length > ctx->size_limit) /* todo: * can overflow */ { fmpz_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx)); return GR_UNABLE; } fmpz_mpoly_mul(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_mul_si(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, slong c, gr_ctx_t ctx) { fmpz_mpoly_scalar_mul_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_mul_ui(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, ulong c, gr_ctx_t ctx) { fmpz_mpoly_scalar_mul_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_mul_fmpz(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_t c, gr_ctx_t ctx) { fmpz_mpoly_scalar_mul_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_div(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, gr_ctx_t ctx) { if (poly2->length == 0) return GR_DOMAIN; if (fmpz_mpoly_divides(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; else return GR_DOMAIN; } int _gr_fmpz_mpoly_divexact(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, gr_ctx_t ctx) { if (poly2->length == 0) return GR_DOMAIN; fmpz_mpoly_div(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_divexact_si(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, slong c, gr_ctx_t ctx) { if (c == 0) return GR_DOMAIN; fmpz_mpoly_scalar_divexact_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_divexact_ui(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, ulong c, gr_ctx_t ctx) { if (c == 0) return GR_DOMAIN; fmpz_mpoly_scalar_divexact_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_divexact_fmpz(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_t c, gr_ctx_t ctx) { if (fmpz_is_zero(c)) return GR_DOMAIN; fmpz_mpoly_scalar_divexact_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } truth_t _gr_fmpz_mpoly_is_invertible(const fmpz_mpoly_t c, gr_ctx_t ctx) { if (c->length == 1 && fmpz_mpoly_is_fmpz(c, MPOLYNOMIAL_MCTX(ctx)) && fmpz_is_pm1(c->coeffs)) return T_TRUE; return T_FALSE; } int _gr_fmpz_mpoly_inv(fmpz_mpoly_t res, const fmpz_mpoly_t c, gr_ctx_t ctx) { if (c->length == 1 && fmpz_mpoly_is_fmpz(c, MPOLYNOMIAL_MCTX(ctx)) && fmpz_is_pm1(c->coeffs)) { fmpz_mpoly_set(res, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } return GR_DOMAIN; } int _gr_fmpz_mpoly_pow_ui(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, ulong c, gr_ctx_t ctx) { /* todo: size limit */ if (fmpz_mpoly_pow_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; else return GR_UNABLE; } int _gr_fmpz_mpoly_pow_fmpz(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_t c, gr_ctx_t ctx) { /* todo: size limit */ if (fmpz_sgn(c) < 0) { int status; status = gr_inv(res, poly1, ctx); if (status == GR_SUCCESS) { fmpz_t e; fmpz_init(e); fmpz_neg(e, c); status = _gr_fmpz_mpoly_pow_fmpz(res, res, e, ctx); fmpz_clear(e); } return status; } if (fmpz_mpoly_pow_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; else return GR_UNABLE; } truth_t _gr_fmpz_mpoly_is_square(const fmpz_mpoly_t poly, gr_ctx_t ctx) { return fmpz_mpoly_is_square(poly, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fmpz_mpoly_sqrt(fmpz_mpoly_t res, const fmpz_mpoly_t poly, gr_ctx_t ctx) { if (fmpz_mpoly_sqrt(res, poly, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; else return GR_DOMAIN; } int _gr_fmpz_mpoly_gcd(fmpz_mpoly_t res, const fmpz_mpoly_t poly1, const fmpz_mpoly_t poly2, gr_ctx_t ctx) { if (fmpz_mpoly_gcd(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; return GR_DOMAIN; } int _gr_fmpz_mpoly_factor(fmpz_mpoly_t c, gr_vec_t factors, gr_vec_t exponents, gr_srcptr x, int flags, gr_ctx_t ctx) { fmpz_mpoly_factor_t fac; gr_ctx_t ZZ; slong i; int status = GR_SUCCESS; fmpz_mpoly_factor_init(fac, MPOLYNOMIAL_MCTX(ctx)); if (fmpz_mpoly_factor(fac, x, MPOLYNOMIAL_MCTX(ctx))) { fmpz_mpoly_set_fmpz(c, fac->constant, MPOLYNOMIAL_MCTX(ctx)); gr_ctx_init_fmpz(ZZ); gr_vec_set_length(factors, fac->num, ctx); gr_vec_set_length(exponents, fac->num, ZZ); for (i = 0; i < fac->num; i++) { fmpz_mpoly_swap((fmpz_mpoly_struct *) (factors->entries) + i, fac->poly + i, MPOLYNOMIAL_MCTX(ctx)); fmpz_swap((fmpz *) (exponents->entries) + i, fac->exp + i); } gr_ctx_clear(ZZ); } else { status = GR_UNABLE; } fmpz_mpoly_factor_clear(fac, MPOLYNOMIAL_MCTX(ctx)); return status; } int _gr_fmpz_mpoly_methods_initialized = 0; gr_static_method_table _gr_fmpz_mpoly_methods; gr_method_tab_input _gr_fmpz_mpoly_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpz_mpoly_ctx_write}, {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_fmpz_mpoly_ctx_clear}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_GEN_NAMES, (gr_funcptr) _gr_fmpz_mpoly_ctx_set_gen_names}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpz_mpoly_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpz_mpoly_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpz_mpoly_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpz_mpoly_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpz_mpoly_randtest}, {GR_METHOD_RANDTEST_SMALL, (gr_funcptr) _gr_fmpz_mpoly_randtest_small}, {_GR_METHOD_LENGTH, (gr_funcptr) _gr_fmpz_mpoly_length}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpz_mpoly_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpz_mpoly_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpz_mpoly_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpz_mpoly_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpz_mpoly_is_one}, {GR_METHOD_GENS, (gr_funcptr) _gr_fmpz_mpoly_gens}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpz_mpoly_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpz_mpoly_set}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpz_mpoly_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpz_mpoly_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_fmpz_mpoly_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fmpz_mpoly_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpz_mpoly_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpz_mpoly_add}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_fmpz_mpoly_add_si}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_fmpz_mpoly_add_ui}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_add_fmpz}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpz_mpoly_sub}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_fmpz_mpoly_sub_si}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_fmpz_mpoly_sub_ui}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_sub_fmpz}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpz_mpoly_mul}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpz_mpoly_mul_si}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fmpz_mpoly_mul_ui}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_mul_fmpz}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpz_mpoly_div}, {GR_METHOD_DIVEXACT, (gr_funcptr) _gr_fmpz_mpoly_divexact}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) _gr_fmpz_mpoly_divexact_si}, {GR_METHOD_DIVEXACT_UI, (gr_funcptr) _gr_fmpz_mpoly_divexact_ui}, {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_divexact_fmpz}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpz_mpoly_inv}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpz_mpoly_is_invertible}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpz_mpoly_pow_ui}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_pow_fmpz}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpz_mpoly_sqrt}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpz_mpoly_is_square}, {GR_METHOD_GCD, (gr_funcptr) _gr_fmpz_mpoly_gcd}, {GR_METHOD_FACTOR, (gr_funcptr) _gr_fmpz_mpoly_factor}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpz_mpoly(gr_ctx_t ctx, slong nvars, const ordering_t ord) { ctx->which_ring = GR_CTX_FMPZ_MPOLY; ctx->sizeof_elem = sizeof(fmpz_mpoly_struct); GR_CTX_DATA_AS_PTR(ctx) = flint_malloc(sizeof(_gr_fmpz_mpoly_ctx_t)); ctx->size_limit = WORD_MAX; fmpz_mpoly_ctx_init(MPOLYNOMIAL_MCTX(ctx), nvars, ord); MPOLYNOMIAL_CTX(ctx)->vars = NULL; ctx->methods = _gr_fmpz_mpoly_methods; if (!_gr_fmpz_mpoly_methods_initialized) { gr_method_tab_init(_gr_fmpz_mpoly_methods, _gr_fmpz_mpoly_methods_input); _gr_fmpz_mpoly_methods_initialized = 1; } } flint-3.1.3/src/gr/fmpz_mpoly_q.c000066400000000000000000000466441461254215100167300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_mpoly_q.h" #include "gr.h" #include "gr_vec.h" #include "gr_generic.h" typedef struct { fmpz_mpoly_ctx_t mctx; char ** vars; } _gr_fmpz_mpoly_ctx_t; #define MPOLYNOMIAL_CTX(ring_ctx) ((_gr_fmpz_mpoly_ctx_t *)(GR_CTX_DATA_AS_PTR(ring_ctx))) #define MPOLYNOMIAL_MCTX(ring_ctx) (MPOLYNOMIAL_CTX(ring_ctx)->mctx) int _gr_fmpz_mpoly_q_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Fraction field of multivariate polynomials over Integer ring (fmpz)"); gr_stream_write(out, " in "); gr_stream_write_si(out, MPOLYNOMIAL_MCTX(ctx)->minfo->nvars); gr_stream_write(out, " variables"); if (MPOLYNOMIAL_MCTX(ctx)->minfo->ord == ORD_LEX) gr_stream_write(out, ", lex order"); else if (MPOLYNOMIAL_MCTX(ctx)->minfo->ord == ORD_DEGLEX) gr_stream_write(out, ", deglex order"); else if (MPOLYNOMIAL_MCTX(ctx)->minfo->ord == ORD_DEGREVLEX) gr_stream_write(out, ", degrevlex order"); return GR_SUCCESS; } /* Some methods are identical to their fmpz_mpoly counterparts */ void _gr_fmpz_mpoly_ctx_clear(gr_ctx_t ctx); int _gr_fmpz_mpoly_ctx_set_gen_names(gr_ctx_t ctx, const char ** s); #define _gr_fmpz_mpoly_q_ctx_clear _gr_fmpz_mpoly_ctx_clear #define _gr_fmpz_mpoly_q_ctx_set_gen_names _gr_fmpz_mpoly_ctx_set_gen_names void _gr_fmpz_mpoly_q_init(fmpz_mpoly_q_t res, gr_ctx_t ctx) { fmpz_mpoly_q_init(res, MPOLYNOMIAL_MCTX(ctx)); } void _gr_fmpz_mpoly_q_clear(fmpz_mpoly_q_t res, gr_ctx_t ctx) { fmpz_mpoly_q_clear(res, MPOLYNOMIAL_MCTX(ctx)); } void _gr_fmpz_mpoly_q_swap(fmpz_mpoly_q_t poly1, fmpz_mpoly_q_t poly2, gr_ctx_t ctx) { fmpz_mpoly_q_swap(poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); } void _gr_fmpz_mpoly_q_set_shallow(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly, gr_ctx_t ctx) { *res = *poly; } int _gr_fmpz_mpoly_q_randtest(fmpz_mpoly_q_t res, flint_rand_t state, gr_ctx_t ctx) { slong bits; if (n_randint(state, 10) != 0) bits = 10; else bits = 100; fmpz_mpoly_q_randtest(res, state, n_randint(state, 5), bits, 1 + n_randint(state, 3), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_randtest_small(fmpz_mpoly_q_t res, flint_rand_t state, gr_ctx_t ctx) { fmpz_mpoly_q_randtest(res, state, n_randint(state, 3), 3, 1 + n_randint(state, 3), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } slong _gr_fmpz_mpoly_q_length(const fmpz_mpoly_q_t x, gr_ctx_t ctx) { return fmpz_mpoly_q_numref(x)->length + fmpz_mpoly_q_denref(x)->length; } int _gr_fmpz_mpoly_q_write(gr_stream_t out, fmpz_mpoly_q_t f, gr_ctx_t ctx) { if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(f), MPOLYNOMIAL_MCTX(ctx))) { gr_stream_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_numref(f), (const char **) MPOLYNOMIAL_CTX(ctx)->vars, MPOLYNOMIAL_MCTX(ctx))); } else if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(f), MPOLYNOMIAL_MCTX(ctx))) { gr_stream_write(out, "("); gr_stream_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_numref(f), (const char **) MPOLYNOMIAL_CTX(ctx)->vars, MPOLYNOMIAL_MCTX(ctx))); gr_stream_write(out, ")/"); gr_stream_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_denref(f), (const char **) MPOLYNOMIAL_CTX(ctx)->vars, MPOLYNOMIAL_MCTX(ctx))); } else { gr_stream_write(out, "("); gr_stream_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_numref(f), (const char **) MPOLYNOMIAL_CTX(ctx)->vars, MPOLYNOMIAL_MCTX(ctx))); gr_stream_write(out, ")/("); gr_stream_write_free(out, fmpz_mpoly_get_str_pretty(fmpz_mpoly_q_denref(f), (const char **) MPOLYNOMIAL_CTX(ctx)->vars, MPOLYNOMIAL_MCTX(ctx))); gr_stream_write(out, ")"); } return GR_SUCCESS; } truth_t _gr_fmpz_mpoly_q_equal(const fmpz_mpoly_q_t poly1, const fmpz_mpoly_q_t poly2, gr_ctx_t ctx) { return fmpz_mpoly_q_equal(poly1, poly2, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_mpoly_q_is_zero(const fmpz_mpoly_q_t poly, gr_ctx_t ctx) { return fmpz_mpoly_q_is_zero(poly, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_mpoly_q_is_one(const fmpz_mpoly_q_t poly, gr_ctx_t ctx) { return fmpz_mpoly_q_is_one(poly, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fmpz_mpoly_q_zero(fmpz_mpoly_q_t res, gr_ctx_t ctx) { fmpz_mpoly_q_zero(res, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_one(fmpz_mpoly_q_t res, gr_ctx_t ctx) { fmpz_mpoly_q_one(res, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_gens(gr_vec_t res, gr_ctx_t ctx) { slong i, n; n = MPOLYNOMIAL_MCTX(ctx)->minfo->nvars; gr_vec_set_length(res, n, ctx); for (i = 0; i < n; i++) fmpz_mpoly_q_gen(((fmpz_mpoly_q_struct *) res->entries) + i, i, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_set(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t mat, gr_ctx_t ctx) { fmpz_mpoly_q_set(res, mat, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_set_si(fmpz_mpoly_q_t res, slong v, gr_ctx_t ctx) { fmpz_mpoly_q_set_si(res, v, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_set_ui(fmpz_mpoly_q_t res, ulong v, gr_ctx_t ctx) { fmpz_mpoly_set_ui(fmpz_mpoly_q_numref(res), v, MPOLYNOMIAL_MCTX(ctx)); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_set_fmpz(fmpz_mpoly_q_t res, const fmpz_t v, gr_ctx_t ctx) { fmpz_mpoly_q_set_fmpz(res, v, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_set_fmpq(fmpz_mpoly_q_t res, const fmpq_t v, gr_ctx_t ctx) { fmpz_mpoly_q_set_fmpq(res, v, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_neg(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t mat, gr_ctx_t ctx) { fmpz_mpoly_q_neg(res, mat, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_add(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_mpoly_q_t poly2, gr_ctx_t ctx) { fmpz_mpoly_q_add(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_add_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, slong c, gr_ctx_t ctx) { fmpz_mpoly_q_add_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } /* int _gr_fmpz_mpoly_q_add_ui(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, ulong c, gr_ctx_t ctx) { fmpz_mpoly_q_add_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } */ int _gr_fmpz_mpoly_q_add_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_t c, gr_ctx_t ctx) { fmpz_mpoly_q_add_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_add_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpq_t c, gr_ctx_t ctx) { fmpz_mpoly_q_add_fmpq(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_sub(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_mpoly_q_t poly2, gr_ctx_t ctx) { fmpz_mpoly_q_sub(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_sub_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, slong c, gr_ctx_t ctx) { fmpz_mpoly_q_sub_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } /* int _gr_fmpz_mpoly_q_sub_ui(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, ulong c, gr_ctx_t ctx) { fmpz_mpoly_q_sub_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } */ int _gr_fmpz_mpoly_q_sub_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_t c, gr_ctx_t ctx) { fmpz_mpoly_q_sub_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_sub_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpq_t c, gr_ctx_t ctx) { fmpz_mpoly_q_sub_fmpq(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_mul(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_mpoly_q_t poly2, gr_ctx_t ctx) { fmpz_mpoly_q_mul(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_mul_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, slong c, gr_ctx_t ctx) { fmpz_mpoly_q_mul_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } /* int _gr_fmpz_mpoly_q_mul_ui(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, ulong c, gr_ctx_t ctx) { fmpz_mpoly_q_mul_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } */ int _gr_fmpz_mpoly_q_mul_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_t c, gr_ctx_t ctx) { fmpz_mpoly_q_mul_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_mul_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpq_t c, gr_ctx_t ctx) { fmpz_mpoly_q_mul_fmpq(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_div(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_mpoly_q_t poly2, gr_ctx_t ctx) { if (fmpz_mpoly_q_is_zero(poly2, MPOLYNOMIAL_MCTX(ctx))) return GR_DOMAIN; fmpz_mpoly_q_div(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_div_si(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, slong c, gr_ctx_t ctx) { if (c == 0) return GR_DOMAIN; fmpz_mpoly_q_div_si(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } /* int _gr_fmpz_mpoly_q_div_ui(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, ulong c, gr_ctx_t ctx) { if (c == 0) return GR_DOMAIN; fmpz_mpoly_q_div_ui(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } */ int _gr_fmpz_mpoly_q_div_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_t c, gr_ctx_t ctx) { if (fmpz_is_zero(c)) return GR_DOMAIN; fmpz_mpoly_q_div_fmpz(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_div_fmpq(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpq_t c, gr_ctx_t ctx) { if (fmpq_is_zero(c)) return GR_DOMAIN; fmpz_mpoly_q_div_fmpq(res, poly1, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } truth_t _gr_fmpz_mpoly_q_is_invertible(const fmpz_mpoly_q_t c, gr_ctx_t ctx) { return fmpz_mpoly_q_is_zero(c, MPOLYNOMIAL_MCTX(ctx)) ? T_FALSE : T_TRUE; } int _gr_fmpz_mpoly_q_inv(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t c, gr_ctx_t ctx) { if (!fmpz_mpoly_q_is_zero(c, MPOLYNOMIAL_MCTX(ctx))) { fmpz_mpoly_q_inv(res, c, MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } return GR_DOMAIN; } int _gr_fmpz_mpoly_q_pow_ui(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, ulong c, gr_ctx_t ctx) { if (fmpz_mpoly_pow_ui(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(poly1), c, MPOLYNOMIAL_MCTX(ctx)) && fmpz_mpoly_pow_ui(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(poly1), c, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; else return GR_UNABLE; } int _gr_fmpz_mpoly_q_pow_fmpz(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_t c, gr_ctx_t ctx) { if (fmpz_sgn(c) < 0) { int status; status = gr_inv(res, poly1, ctx); if (status == GR_SUCCESS) { fmpz_t e; fmpz_init(e); fmpz_neg(e, c); status = _gr_fmpz_mpoly_q_pow_fmpz(res, res, e, ctx); fmpz_clear(e); } return status; } if (fmpz_mpoly_pow_fmpz(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(poly1), c, MPOLYNOMIAL_MCTX(ctx)) && fmpz_mpoly_pow_fmpz(fmpz_mpoly_q_denref(res), fmpz_mpoly_q_denref(poly1), c, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; else return GR_UNABLE; } int _gr_fmpz_mpoly_q_numerator(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const gr_ctx_t ctx) { fmpz_mpoly_set(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_numref(x), MPOLYNOMIAL_MCTX(ctx)); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } int _gr_fmpz_mpoly_q_denominator(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t x, const gr_ctx_t ctx) { fmpz_mpoly_set(fmpz_mpoly_q_numref(res), fmpz_mpoly_q_denref(x), MPOLYNOMIAL_MCTX(ctx)); fmpz_mpoly_one(fmpz_mpoly_q_denref(res), MPOLYNOMIAL_MCTX(ctx)); return GR_SUCCESS; } /* truth_t _gr_fmpz_mpoly_q_is_square(const fmpz_mpoly_q_t poly, gr_ctx_t ctx) { return fmpz_mpoly_q_is_square(poly, MPOLYNOMIAL_MCTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fmpz_mpoly_q_sqrt(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly, gr_ctx_t ctx) { if (fmpz_mpoly_q_sqrt(res, poly, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; else return GR_DOMAIN; } int _gr_fmpz_mpoly_q_gcd(fmpz_mpoly_q_t res, const fmpz_mpoly_q_t poly1, const fmpz_mpoly_q_t poly2, gr_ctx_t ctx) { if (fmpz_mpoly_q_gcd(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx))) return GR_SUCCESS; return GR_DOMAIN; } */ /* int _gr_fmpz_mpoly_q_factor(fmpz_mpoly_q_t c, gr_vec_t factors, gr_vec_t exponents, gr_srcptr x, int flags, gr_ctx_t ctx) { fmpz_mpoly_q_factor_t fac; gr_ctx_t ZZ; slong i; int status = GR_SUCCESS; fmpz_mpoly_q_factor_init(fac, MPOLYNOMIAL_MCTX(ctx)); if (fmpz_mpoly_q_factor(fac, x, MPOLYNOMIAL_MCTX(ctx))) { fmpz_mpoly_q_set_fmpz(c, fac->constant, MPOLYNOMIAL_MCTX(ctx)); gr_ctx_init_fmpz(ZZ); gr_vec_set_length(factors, fac->num, ctx); gr_vec_set_length(exponents, fac->num, ZZ); for (i = 0; i < fac->num; i++) { fmpz_mpoly_q_swap((fmpz_mpoly_q_struct *) (factors->entries) + i, fac->poly + i, MPOLYNOMIAL_MCTX(ctx)); fmpz_swap((fmpz *) (exponents->entries) + i, fac->exp + i); } gr_ctx_clear(ZZ); } else { status = GR_UNABLE; } fmpz_mpoly_q_factor_clear(fac, MPOLYNOMIAL_MCTX(ctx)); return status; } */ int _gr_fmpz_mpoly_q_methods_initialized = 0; gr_static_method_table _gr_fmpz_mpoly_q_methods; gr_method_tab_input _gr_fmpz_mpoly_q_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpz_mpoly_q_ctx_write}, {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_fmpz_mpoly_q_ctx_clear}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_GEN_NAMES, (gr_funcptr) _gr_fmpz_mpoly_q_ctx_set_gen_names}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpz_mpoly_q_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpz_mpoly_q_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpz_mpoly_q_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpz_mpoly_q_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpz_mpoly_q_randtest}, {GR_METHOD_RANDTEST_SMALL, (gr_funcptr) _gr_fmpz_mpoly_q_randtest_small}, {_GR_METHOD_LENGTH, (gr_funcptr) _gr_fmpz_mpoly_q_length}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpz_mpoly_q_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpz_mpoly_q_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpz_mpoly_q_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpz_mpoly_q_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpz_mpoly_q_is_one}, {GR_METHOD_GENS, (gr_funcptr) _gr_fmpz_mpoly_q_gens}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpz_mpoly_q_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpz_mpoly_q_set}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpz_mpoly_q_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpz_mpoly_q_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_q_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_fmpz_mpoly_q_set_fmpq}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpz_mpoly_q_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpz_mpoly_q_add}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_fmpz_mpoly_q_add_si}, /* {GR_METHOD_ADD_UI, (gr_funcptr) _gr_fmpz_mpoly_q_add_ui}, */ {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_q_add_fmpz}, {GR_METHOD_ADD_FMPQ, (gr_funcptr) _gr_fmpz_mpoly_q_add_fmpq}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpz_mpoly_q_sub}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_fmpz_mpoly_q_sub_si}, /* {GR_METHOD_SUB_UI, (gr_funcptr) _gr_fmpz_mpoly_q_sub_ui}, */ {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_q_sub_fmpz}, {GR_METHOD_SUB_FMPQ, (gr_funcptr) _gr_fmpz_mpoly_q_sub_fmpq}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpz_mpoly_q_mul}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpz_mpoly_q_mul_si}, /* {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fmpz_mpoly_q_mul_ui}, */ {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_q_mul_fmpz}, {GR_METHOD_MUL_FMPQ, (gr_funcptr) _gr_fmpz_mpoly_q_mul_fmpq}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpz_mpoly_q_div}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_fmpz_mpoly_q_div_si}, /* {GR_METHOD_DIV_UI, (gr_funcptr) _gr_fmpz_mpoly_q_div_ui}, */ {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_q_div_fmpz}, {GR_METHOD_DIV_FMPQ, (gr_funcptr) _gr_fmpz_mpoly_q_div_fmpq}, {GR_METHOD_DIVEXACT, (gr_funcptr) _gr_fmpz_mpoly_q_div}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) _gr_fmpz_mpoly_q_div_si}, /* {GR_METHOD_DIVEXACT_UI, (gr_funcptr) _gr_fmpz_mpoly_q_div_ui}, */ {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_q_div_fmpz}, {GR_METHOD_DIVEXACT_FMPQ, (gr_funcptr) _gr_fmpz_mpoly_q_div_fmpq}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpz_mpoly_q_inv}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpz_mpoly_q_is_invertible}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpz_mpoly_q_pow_ui}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpz_mpoly_q_pow_fmpz}, {GR_METHOD_NUMERATOR, (gr_funcptr) _gr_fmpz_mpoly_q_numerator}, {GR_METHOD_DENOMINATOR, (gr_funcptr) _gr_fmpz_mpoly_q_denominator}, /* {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpz_mpoly_q_sqrt}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpz_mpoly_q_is_square}, {GR_METHOD_GCD, (gr_funcptr) _gr_fmpz_mpoly_q_gcd}, {GR_METHOD_FACTOR, (gr_funcptr) _gr_fmpz_mpoly_q_factor}, */ {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpz_mpoly_q(gr_ctx_t ctx, slong nvars, const ordering_t ord) { ctx->which_ring = GR_CTX_FMPZ_MPOLY_Q; ctx->sizeof_elem = sizeof(fmpz_mpoly_q_struct); GR_CTX_DATA_AS_PTR(ctx) = flint_malloc(sizeof(_gr_fmpz_mpoly_ctx_t)); ctx->size_limit = WORD_MAX; fmpz_mpoly_ctx_init(MPOLYNOMIAL_MCTX(ctx), nvars, ord); MPOLYNOMIAL_CTX(ctx)->vars = NULL; ctx->methods = _gr_fmpz_mpoly_q_methods; if (!_gr_fmpz_mpoly_q_methods_initialized) { gr_method_tab_init(_gr_fmpz_mpoly_q_methods, _gr_fmpz_mpoly_q_methods_input); _gr_fmpz_mpoly_q_methods_initialized = 1; } } flint-3.1.3/src/gr/fmpz_poly.c000066400000000000000000000530641461254215100162250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_poly.h" #include "gr.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_generic.h" #include "fmpz_poly_factor.h" #include "fmpz_mpoly.h" #define FMPZ_POLY_CTX(ctx) POLYNOMIAL_CTX(ctx) #define FMPZ_POLY_CTX_VAR(ctx) (FMPZ_POLY_CTX(ctx)->var) static const char * default_var = "x"; void _gr_fmpz_poly_ctx_clear(gr_ctx_t ctx) { if (FMPZ_POLY_CTX_VAR(ctx) != default_var) flint_free(FMPZ_POLY_CTX_VAR(ctx)); } int _gr_fmpz_poly_ctx_set_gen_name(gr_ctx_t ctx, const char * s) { slong len; len = strlen(s); if (FMPZ_POLY_CTX_VAR(ctx) == default_var) FMPZ_POLY_CTX_VAR(ctx) = NULL; FMPZ_POLY_CTX_VAR(ctx) = flint_realloc(FMPZ_POLY_CTX_VAR(ctx), len + 1); memcpy(FMPZ_POLY_CTX_VAR(ctx), s, len + 1); return GR_SUCCESS; } int _gr_fmpz_poly_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Polynomials over integers (fmpz_poly)"); return GR_SUCCESS; } void _gr_fmpz_poly_init(fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_init(x); } void _gr_fmpz_poly_clear(fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_clear(x); } void _gr_fmpz_poly_swap(fmpz_poly_t x, fmpz_poly_t y, const gr_ctx_t ctx) { fmpz_poly_t t; *t = *x; *x = *y; *y = *t; } void _gr_fmpz_poly_set_shallow(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_fmpz_poly_randtest(fmpz_poly_t res, flint_rand_t state, const gr_ctx_t ctx) { if (n_randint(state, 10) == 0) fmpz_poly_randtest(res, state, 4, 100); else fmpz_poly_randtest(res, state, 5, 10); return GR_SUCCESS; } int _gr_fmpz_poly_write(gr_stream_t out, const fmpz_poly_t x, const gr_ctx_t ctx) { const char * var = FMPZ_POLY_CTX_VAR(ctx); if (var == NULL) var = "x"; gr_stream_write_free(out, fmpz_poly_get_str_pretty(x, var)); return GR_SUCCESS; } int _gr_fmpz_poly_zero(fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_zero(x); return GR_SUCCESS; } int _gr_fmpz_poly_one(fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_one(x); return GR_SUCCESS; } int _gr_fmpz_poly_gen(fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_zero(x); fmpz_poly_set_coeff_ui(x, 1, 1); return GR_SUCCESS; } int _gr_fmpz_poly_set_si(fmpz_poly_t res, slong v, const gr_ctx_t ctx) { fmpz_poly_set_si(res, v); return GR_SUCCESS; } int _gr_fmpz_poly_set_ui(fmpz_poly_t res, ulong v, const gr_ctx_t ctx) { fmpz_poly_set_ui(res, v); return GR_SUCCESS; } int _gr_fmpz_poly_set_fmpz(fmpz_poly_t res, const fmpz_t v, const gr_ctx_t ctx) { fmpz_poly_set_fmpz(res, v); return GR_SUCCESS; } int _gr_fmpz_poly_set_other(fmpz_poly_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ctx_t ctx) { if (x_ctx->which_ring == GR_CTX_FMPZ) { fmpz_poly_set_fmpz(res, x); return GR_SUCCESS; } if (x_ctx->which_ring == GR_CTX_FMPZ_POLY) { fmpz_poly_set(res, x); return GR_SUCCESS; } if (x_ctx->which_ring == GR_CTX_FMPQ) { if (fmpz_is_one(fmpq_denref((fmpq *) x))) { fmpz_poly_set_fmpz(res, fmpq_numref((fmpq *) x)); return GR_SUCCESS; } return GR_DOMAIN; } if (x_ctx->which_ring == GR_CTX_FMPQ_POLY) { if (fmpz_is_one(((fmpq_poly_struct *) x)->den)) { fmpq_poly_get_numerator(res, x); return GR_SUCCESS; } return GR_DOMAIN; } if (x_ctx->which_ring == GR_CTX_GR_POLY) { if (POLYNOMIAL_ELEM_CTX(x_ctx)->which_ring == GR_CTX_FMPZ) { fmpz_poly_set(res, x); return GR_SUCCESS; } else { gr_ctx_t ZZ; gr_ctx_init_fmpz(ZZ); /* no need to free */ return gr_poly_set_gr_poly_other((gr_poly_struct *) res, x, POLYNOMIAL_ELEM_CTX(x_ctx), ZZ); } } if (x_ctx->which_ring == GR_CTX_GR_VEC) { gr_ctx_t ZZ; gr_poly_t tmp; tmp->coeffs = ((gr_vec_struct *) x)->entries; tmp->length = ((gr_vec_struct *) x)->length; gr_ctx_init_fmpz(ZZ); /* no need to free */ return gr_poly_set_gr_poly_other((gr_poly_struct *) res, tmp, VECTOR_CTX(x_ctx)->base_ring, ZZ); } return GR_UNABLE; } int _gr_fmpz_poly_set_str(fmpz_poly_t res, const char * x, const gr_ctx_t ctx) { fmpz_mpoly_ctx_t fctx; fmpz_mpoly_t f; int status; const char * vars[] = { "x" }; fmpz_mpoly_ctx_init(fctx, 1, ORD_LEX); fmpz_mpoly_init(f, fctx); if (!fmpz_mpoly_set_str_pretty(f, x, vars, fctx)) { fmpz_mpoly_get_fmpz_poly(res, f, 0, fctx); status = GR_SUCCESS; } else { status = GR_UNABLE; } fmpz_mpoly_clear(f, fctx); fmpz_mpoly_ctx_clear(fctx); return status; } int _gr_fmpz_poly_get_ui(ulong * res, const fmpz_poly_t x, const gr_ctx_t ctx) { if (fmpz_poly_length(x) == 0) { *res = 0; return GR_SUCCESS; } if (fmpz_poly_length(x) == 1) { if (fmpz_sgn(x->coeffs) < 0 || fmpz_cmp_ui(x->coeffs, UWORD_MAX) > 0) { return GR_DOMAIN; } else { *res = fmpz_get_ui(x->coeffs); return GR_SUCCESS; } } return GR_DOMAIN; } int _gr_fmpz_poly_get_si(slong * res, const fmpz_poly_t x, const gr_ctx_t ctx) { if (fmpz_poly_length(x) == 0) { *res = 0; return GR_SUCCESS; } if (fmpz_poly_length(x) == 1) { if (!fmpz_fits_si(x->coeffs)) { return GR_DOMAIN; } else { *res = fmpz_get_si(x->coeffs); return GR_SUCCESS; } } return GR_DOMAIN; } int _gr_fmpz_poly_get_fmpz(fmpz_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { if (fmpz_poly_length(x) == 0) { fmpz_zero(res); return GR_SUCCESS; } if (fmpz_poly_length(x) == 1) { fmpz_set(res, x->coeffs); return GR_SUCCESS; } return GR_DOMAIN; } int _gr_fmpz_poly_get_fmpq(fmpq_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { if (fmpz_poly_length(x) == 0) { fmpq_zero(res); return GR_SUCCESS; } if (fmpz_poly_length(x) == 1) { fmpq_set_fmpz(res, x->coeffs); return GR_SUCCESS; } return GR_DOMAIN; } truth_t _gr_fmpz_poly_is_zero(const fmpz_poly_t x, const gr_ctx_t ctx) { return fmpz_poly_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_poly_is_one(const fmpz_poly_t x, const gr_ctx_t ctx) { return fmpz_poly_is_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_poly_is_neg_one(const fmpz_poly_t x, const gr_ctx_t ctx) { return (x->length == 1 && x->coeffs[0] == -1) ? T_TRUE : T_FALSE; } truth_t _gr_fmpz_poly_equal(const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { return fmpz_poly_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_fmpz_poly_set(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_set(res, x); return GR_SUCCESS; } int _gr_fmpz_poly_neg(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_neg(res, x); return GR_SUCCESS; } int _gr_fmpz_poly_add(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { fmpz_poly_add(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_sub(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { fmpz_poly_sub(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_mul(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { fmpz_poly_mul(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_mul_ui(fmpz_poly_t res, const fmpz_poly_t x, ulong y, const gr_ctx_t ctx) { fmpz_poly_scalar_mul_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_mul_si(fmpz_poly_t res, const fmpz_poly_t x, slong y, const gr_ctx_t ctx) { fmpz_poly_scalar_mul_si(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_mul_fmpz(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_poly_scalar_mul_fmpz(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_addmul_ui(fmpz_poly_t res, const fmpz_poly_t x, ulong y, const gr_ctx_t ctx) { fmpz_poly_scalar_addmul_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_addmul_si(fmpz_poly_t res, const fmpz_poly_t x, slong y, const gr_ctx_t ctx) { fmpz_poly_scalar_addmul_si(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_addmul_fmpz(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_poly_scalar_addmul_fmpz(res, x, y); return GR_SUCCESS; } /* todo int _gr_fmpz_poly_submul_ui(fmpz_poly_t res, const fmpz_poly_t x, ulong y, const gr_ctx_t ctx) { fmpz_poly_scalar_submul_ui(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_submul_si(fmpz_poly_t res, const fmpz_poly_t x, slong y, const gr_ctx_t ctx) { if (y >= 0) fmpz_poly_scalar_addmul_ui(res, x, y); else fmpz_poly_scalar_submul_ui(res, x, -y); return GR_SUCCESS; } */ int _gr_fmpz_poly_submul_fmpz(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_poly_scalar_submul_fmpz(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_mul_two(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_scalar_mul_2exp(res, x, 1); return GR_SUCCESS; } int _gr_fmpz_poly_sqr(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { fmpz_poly_sqr(res, x); return GR_SUCCESS; } int _gr_fmpz_poly_inv(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { if (fmpz_poly_is_unit(x)) { fmpz_poly_set(res, x); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpz_poly_div(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { if (fmpz_poly_is_zero(y)) { return GR_DOMAIN; } else { if (fmpz_poly_divides(res, x, y)) return GR_SUCCESS; else return GR_DOMAIN; } } int _gr_fmpz_poly_divexact(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { if (fmpz_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpz_poly_divexact(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_poly_divexact_ui(fmpz_poly_t res, const fmpz_poly_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpz_poly_scalar_divexact_ui(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_poly_divexact_si(fmpz_poly_t res, const fmpz_poly_t x, slong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpz_poly_scalar_divexact_si(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_poly_divexact_fmpz(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { fmpz_poly_scalar_divexact_fmpz(res, x, y); return GR_SUCCESS; } } truth_t _gr_fmpz_poly_is_invertible(const fmpz_poly_t x, const gr_ctx_t ctx) { return fmpz_poly_is_unit(x) ? T_TRUE : T_FALSE; } /* todo: efficient algo */ truth_t _gr_fmpz_poly_divides(const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { truth_t res; fmpz_poly_t tmp; if (fmpz_poly_is_zero(y)) return T_TRUE; if (fmpz_poly_is_zero(x)) return T_FALSE; fmpz_poly_init(tmp); res = fmpz_poly_divides(tmp, y, x) ? T_TRUE : T_FALSE; fmpz_poly_clear(tmp); return res; } int _gr_fmpz_poly_euclidean_div(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { if (fmpz_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpz_poly_div(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_poly_euclidean_rem(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { if (fmpz_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpz_poly_rem(res, x, y); return GR_SUCCESS; } } int _gr_fmpz_poly_euclidean_divrem(fmpz_poly_t res1, fmpz_poly_t res2, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { if (fmpz_poly_is_zero(y)) { return GR_DOMAIN; } else { fmpz_poly_divrem(res1, res2, x, y); return GR_SUCCESS; } } int _gr_fmpz_poly_gcd(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { fmpz_poly_gcd(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_lcm(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_poly_t y, const gr_ctx_t ctx) { fmpz_poly_lcm(res, x, y); return GR_SUCCESS; } int _gr_fmpz_poly_pow_ui(fmpz_poly_t res, const fmpz_poly_t x, ulong exp, const gr_ctx_t ctx) { fmpz_poly_pow(res, x, exp); return GR_SUCCESS; } int _gr_fmpz_poly_pow_si(fmpz_poly_t res, const fmpz_poly_t x, slong exp, const gr_ctx_t ctx) { if (exp < 0) { if (fmpz_poly_is_unit(x)) { if (fmpz_poly_is_one(x) || exp % 2 == 0) fmpz_poly_one(res); else fmpz_poly_set_si(res, -1); return GR_SUCCESS; } return GR_DOMAIN; } else { return _gr_fmpz_poly_pow_ui(res, x, exp, ctx); } } int _gr_fmpz_poly_pow_fmpz(fmpz_poly_t res, const fmpz_poly_t x, const fmpz_t exp, const gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*exp)) { return _gr_fmpz_poly_pow_si(res, x, *exp, ctx); } else if (fmpz_poly_is_unit(x)) { if (fmpz_poly_is_one(x) || fmpz_is_even(exp)) fmpz_poly_one(res); else fmpz_poly_set_si(res, -1); return GR_SUCCESS; } else if (fmpz_poly_is_zero(x) && fmpz_sgn(exp) > 0) { fmpz_poly_zero(res); return GR_SUCCESS; } else if (fmpz_sgn(exp) < 0) { return GR_DOMAIN; } else { return GR_UNABLE; } } truth_t _gr_fmpz_poly_is_square(const fmpz_poly_t x, const gr_ctx_t ctx) { /* todo: fmpz_poly_is_square */ truth_t res; fmpz_poly_t tmp; fmpz_poly_init(tmp); res = fmpz_poly_sqrt(tmp, x) ? T_TRUE : T_FALSE; fmpz_poly_clear(tmp); return res; } int _gr_fmpz_poly_sqrt(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { if (fmpz_poly_sqrt(res, x)) { return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpz_poly_rsqrt(fmpz_poly_t res, const fmpz_poly_t x, const gr_ctx_t ctx) { if (fmpz_poly_is_one(x)) { fmpz_poly_one(res); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpz_poly_factor(fmpz_poly_t c, gr_vec_t factors, gr_vec_t exponents, gr_srcptr x, int flags, gr_ctx_t ctx) { fmpz_poly_factor_t fac; gr_ctx_t ZZ; slong i; fmpz_poly_factor_init(fac); fmpz_poly_factor(fac, x); fmpz_poly_set_fmpz(c, &fac->c); gr_ctx_init_fmpz(ZZ); gr_vec_set_length(factors, fac->num, ctx); gr_vec_set_length(exponents, fac->num, ZZ); for (i = 0; i < fac->num; i++) { fmpz_poly_swap((fmpz_poly_struct *) (factors->entries) + i, fac->p + i); fmpz_set_ui((fmpz *) (exponents->entries) + i, fac->exp[i]); } gr_ctx_clear(ZZ); fmpz_poly_factor_clear(fac); return GR_SUCCESS; } int _fmpz_poly_methods_initialized = 0; gr_static_method_table _fmpz_poly_methods; gr_method_tab_input _fmpz_poly_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpz_poly_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_GEN_NAME, (gr_funcptr) _gr_fmpz_poly_ctx_set_gen_name}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpz_poly_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpz_poly_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpz_poly_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpz_poly_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpz_poly_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpz_poly_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpz_poly_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpz_poly_one}, {GR_METHOD_GEN, (gr_funcptr) _gr_fmpz_poly_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpz_poly_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpz_poly_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_fmpz_poly_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpz_poly_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpz_poly_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpz_poly_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpz_poly_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpz_poly_set_fmpz}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fmpz_poly_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) _gr_fmpz_poly_set_str}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_fmpz_poly_get_ui}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_fmpz_poly_get_si}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_fmpz_poly_get_fmpz}, {GR_METHOD_GET_FMPQ, (gr_funcptr) _gr_fmpz_poly_get_fmpq}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpz_poly_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpz_poly_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpz_poly_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpz_poly_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fmpz_poly_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpz_poly_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fmpz_poly_mul_fmpz}, {GR_METHOD_ADDMUL_UI, (gr_funcptr) _gr_fmpz_poly_addmul_ui}, {GR_METHOD_ADDMUL_SI, (gr_funcptr) _gr_fmpz_poly_addmul_si}, {GR_METHOD_ADDMUL_FMPZ, (gr_funcptr) _gr_fmpz_poly_addmul_fmpz}, /* {GR_METHOD_SUBMUL_UI, (gr_funcptr) _gr_fmpz_poly_submul_ui}, */ /* {GR_METHOD_SUBMUL_SI, (gr_funcptr) _gr_fmpz_poly_submul_si}, */ {GR_METHOD_SUBMUL_FMPZ, (gr_funcptr) _gr_fmpz_poly_submul_fmpz}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_fmpz_poly_mul_two}, {GR_METHOD_SQR, (gr_funcptr) _gr_fmpz_poly_sqr}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpz_poly_div}, {GR_METHOD_DIVEXACT, (gr_funcptr) _gr_fmpz_poly_divexact}, {GR_METHOD_DIVEXACT_UI, (gr_funcptr) _gr_fmpz_poly_divexact_ui}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) _gr_fmpz_poly_divexact_si}, {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) _gr_fmpz_poly_divexact_fmpz}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpz_poly_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpz_poly_inv}, {GR_METHOD_DIVIDES, (gr_funcptr) _gr_fmpz_poly_divides}, {GR_METHOD_EUCLIDEAN_DIV, (gr_funcptr) _gr_fmpz_poly_euclidean_div}, {GR_METHOD_EUCLIDEAN_REM, (gr_funcptr) _gr_fmpz_poly_euclidean_rem}, {GR_METHOD_EUCLIDEAN_DIVREM,(gr_funcptr) _gr_fmpz_poly_euclidean_divrem}, {GR_METHOD_GCD, (gr_funcptr) _gr_fmpz_poly_gcd}, {GR_METHOD_LCM, (gr_funcptr) _gr_fmpz_poly_lcm}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpz_poly_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_fmpz_poly_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpz_poly_pow_fmpz}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpz_poly_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpz_poly_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_fmpz_poly_rsqrt}, {GR_METHOD_FACTOR, (gr_funcptr) _gr_fmpz_poly_factor}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpz_poly(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_FMPZ_POLY; ctx->sizeof_elem = sizeof(fmpz_poly_struct); ctx->size_limit = WORD_MAX; ctx->methods = _fmpz_poly_methods; POLYNOMIAL_CTX(ctx)->base_ring = NULL; POLYNOMIAL_CTX(ctx)->degree_limit = WORD_MAX; POLYNOMIAL_CTX(ctx)->var = (char *) default_var; if (!_fmpz_poly_methods_initialized) { gr_method_tab_init(_fmpz_poly_methods, _fmpz_poly_methods_input); _fmpz_poly_methods_initialized = 1; } } flint-3.1.3/src/gr/fmpzi.c000066400000000000000000000636631461254215100153410ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "fexpr.h" #include "qqbar.h" #include "fmpzi.h" #include "gr.h" #include "gr_generic.h" int _gr_fmpzi_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Gaussian integer ring (fmpzi)"); return GR_SUCCESS; } void _gr_fmpzi_init(fmpzi_t x, const gr_ctx_t ctx) { fmpzi_init(x); } void _gr_fmpzi_clear(fmpzi_t x, const gr_ctx_t ctx) { fmpzi_clear(x); } void _gr_fmpzi_swap(fmpzi_t x, fmpzi_t y, const gr_ctx_t ctx) { fmpzi_t t; *t = *x; *x = *y; *y = *t; } void _gr_fmpzi_set_shallow(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_fmpzi_randtest(fmpzi_t res, flint_rand_t state, const gr_ctx_t ctx) { switch (n_randint(state, 4)) { case 0: fmpzi_randtest(res, state, 100); break; default: fmpzi_randtest(res, state, 10); } return GR_SUCCESS; } int _gr_fmpzi_write(gr_stream_t out, const fmpzi_t x, const gr_ctx_t ctx) { if (fmpz_is_zero(fmpzi_imagref(x))) { gr_stream_write_fmpz(out, fmpzi_realref(x)); } else if (fmpz_is_zero(fmpzi_realref(x))) { if (fmpz_is_one(fmpzi_imagref(x))) gr_stream_write(out, "I"); else if (fmpz_equal_si(fmpzi_imagref(x), -1)) gr_stream_write(out, "-I"); else { gr_stream_write_fmpz(out, fmpzi_imagref(x)); gr_stream_write(out, "*I"); } } else { gr_stream_write(out, "("); gr_stream_write_fmpz(out, fmpzi_realref(x)); if (fmpz_is_one(fmpzi_imagref(x))) gr_stream_write(out, "+I)"); else if (fmpz_equal_si(fmpzi_imagref(x), -1)) gr_stream_write(out, "-I)"); else { if (fmpz_sgn(fmpzi_imagref(x)) > 0) gr_stream_write(out, "+"); gr_stream_write_fmpz(out, fmpzi_imagref(x)); gr_stream_write(out, "*I)"); } } return GR_SUCCESS; } int _gr_fmpzi_zero(fmpzi_t x, const gr_ctx_t ctx) { fmpzi_zero(x); return GR_SUCCESS; } int _gr_fmpzi_one(fmpzi_t x, const gr_ctx_t ctx) { fmpzi_one(x); return GR_SUCCESS; } int _gr_fmpzi_set_si(fmpzi_t res, slong v, const gr_ctx_t ctx) { fmpz_set_si(fmpzi_realref(res), v); fmpz_zero(fmpzi_imagref(res)); return GR_SUCCESS; } int _gr_fmpzi_set_ui(fmpzi_t res, ulong v, const gr_ctx_t ctx) { fmpz_set_ui(fmpzi_realref(res), v); fmpz_zero(fmpzi_imagref(res)); return GR_SUCCESS; } int _gr_fmpzi_set_fmpz(fmpzi_t res, const fmpz_t v, const gr_ctx_t ctx) { fmpz_set(fmpzi_realref(res), v); fmpz_zero(fmpzi_imagref(res)); return GR_SUCCESS; } int _gr_fmpzi_set_fmpq(fmpzi_t res, const fmpq_t v, const gr_ctx_t ctx) { if (fmpz_is_one(fmpq_denref(v))) { fmpz_set(fmpzi_realref(res), fmpq_numref(v)); fmpz_zero(fmpzi_imagref(res)); return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_fmpzi_set(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { fmpzi_set(res, x); return GR_SUCCESS; } /* todo: move */ int fmpzi_set_qqbar(fmpzi_t res, const qqbar_t x) { if (qqbar_is_integer(x)) { qqbar_get_fmpz(fmpzi_realref(res), x); fmpz_zero(fmpzi_imagref(res)); return 1; } else { /* a + bi ==> X^2 - 2aX + (a^2+b^2) */ if (qqbar_is_algebraic_integer(x) && qqbar_degree(x) == 2 && fmpz_is_even(QQBAR_COEFFS(x) + 1) && fmpz_sgn(QQBAR_COEFFS(x)) > 0) { fmpz_tdiv_q_2exp(fmpzi_realref(res), QQBAR_COEFFS(x) + 1, 1); fmpz_neg(fmpzi_realref(res), fmpzi_realref(res)); fmpz_mul(fmpzi_imagref(res), fmpzi_realref(res), fmpzi_realref(res)); fmpz_sub(fmpzi_imagref(res), QQBAR_COEFFS(x), fmpzi_imagref(res)); /* todo: combined square root / check */ if (fmpz_is_square(fmpzi_imagref(res))) { fmpz_sqrt(fmpzi_imagref(res), fmpzi_imagref(res)); if (qqbar_sgn_im(x) < 0) fmpz_neg(fmpzi_imagref(res), fmpzi_imagref(res)); return 1; } } return 0; } } int _gr_fmpzi_set_d(fmpzi_t res, double x, const gr_ctx_t ctx) { if (x != x || x == HUGE_VAL || x == -HUGE_VAL) return GR_DOMAIN; if (x != floor(x)) return GR_DOMAIN; fmpz_set_d(fmpzi_realref(res), x); fmpz_zero(fmpzi_imagref(res)); return GR_SUCCESS; } int _gr_fmpzi_set_other(fmpzi_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: return _gr_fmpzi_set_fmpz(res, x, ctx); case GR_CTX_FMPQ: return _gr_fmpzi_set_fmpq(res, x, ctx); case GR_CTX_FMPZI: return _gr_fmpzi_set(res, x, ctx); case GR_CTX_REAL_ALGEBRAIC_QQBAR: case GR_CTX_COMPLEX_ALGEBRAIC_QQBAR: return fmpzi_set_qqbar(res, x) ? GR_SUCCESS : GR_DOMAIN; } return GR_UNABLE; } int _gr_fmpzi_get_fmpz(fmpz_t res, const fmpzi_t x, const gr_ctx_t ctx) { if (!fmpz_is_zero(fmpzi_imagref(x))) return GR_DOMAIN; fmpz_set(res, fmpzi_realref(x)); return GR_SUCCESS; } int _gr_fmpzi_get_fmpq(fmpq_t res, const fmpzi_t x, const gr_ctx_t ctx) { if (!fmpz_is_zero(fmpzi_imagref(x))) return GR_DOMAIN; fmpq_set_fmpz(res, fmpzi_realref(x)); return GR_SUCCESS; } /* todo: qqbar should call an fmpzi method rather than vice versa */ void qqbar_set_fmpzi(qqbar_t res, const fmpzi_t x); int _gr_fmpzi_get_fexpr(fexpr_t res, const fmpzi_t x, const gr_ctx_t ctx) { qqbar_t t; int status; qqbar_init(t); qqbar_set_fmpzi(t, x); status = qqbar_get_fexpr_formula(res, t, QQBAR_FORMULA_GAUSSIANS) ? GR_SUCCESS : GR_UNABLE; qqbar_clear(t); return status; } int _gr_fmpzi_get_ui(ulong * res, const fmpzi_t x, const gr_ctx_t ctx) { if (!fmpz_is_zero(fmpzi_imagref(x))) return GR_DOMAIN; if (fmpz_sgn(fmpzi_realref(x)) < 0 || fmpz_cmp_ui(fmpzi_realref(x), UWORD_MAX) > 0) return GR_DOMAIN; *res = fmpz_get_ui(fmpzi_realref(x)); return GR_SUCCESS; } int _gr_fmpzi_get_si(slong * res, const fmpzi_t x, const gr_ctx_t ctx) { if (!fmpz_is_zero(fmpzi_imagref(x))) return GR_DOMAIN; if (!fmpz_fits_si(fmpzi_realref(x))) return GR_DOMAIN; *res = fmpz_get_si(fmpzi_realref(x)); return GR_SUCCESS; } int _gr_fmpzi_get_d(double * res, const fmpzi_t x, const gr_ctx_t ctx) { if (!fmpz_is_zero(fmpzi_imagref(x))) return GR_DOMAIN; *res = fmpz_get_d(fmpzi_realref(x)); return GR_SUCCESS; } truth_t _gr_fmpzi_is_zero(const fmpzi_t x, const gr_ctx_t ctx) { return fmpzi_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpzi_is_one(const fmpzi_t x, const gr_ctx_t ctx) { return fmpzi_is_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpzi_is_neg_one(const fmpzi_t x, const gr_ctx_t ctx) { return (fmpz_is_zero(fmpzi_imagref(x)) && *fmpzi_realref(x) == -1) ? T_TRUE : T_FALSE; } truth_t _gr_fmpzi_equal(const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { return fmpzi_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_fmpzi_neg(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { fmpzi_neg(res, x); return GR_SUCCESS; } int _gr_fmpzi_add(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { fmpzi_add(res, x, y); return GR_SUCCESS; } int _gr_fmpzi_add_si(fmpzi_t res, const fmpzi_t x, slong y, const gr_ctx_t ctx) { fmpz_add_si(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_set(fmpzi_imagref(res), fmpzi_imagref(x)); return GR_SUCCESS; } int _gr_fmpzi_add_ui(fmpzi_t res, const fmpzi_t x, ulong y, const gr_ctx_t ctx) { fmpz_add_ui(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_set(fmpzi_imagref(res), fmpzi_imagref(x)); return GR_SUCCESS; } int _gr_fmpzi_add_fmpz(fmpzi_t res, const fmpzi_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_add(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_set(fmpzi_imagref(res), fmpzi_imagref(x)); return GR_SUCCESS; } int _gr_fmpzi_sub(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { fmpzi_sub(res, x, y); return GR_SUCCESS; } int _gr_fmpzi_sub_si(fmpzi_t res, const fmpzi_t x, slong y, const gr_ctx_t ctx) { fmpz_sub_si(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_set(fmpzi_imagref(res), fmpzi_imagref(x)); return GR_SUCCESS; } int _gr_fmpzi_sub_ui(fmpzi_t res, const fmpzi_t x, ulong y, const gr_ctx_t ctx) { fmpz_sub_ui(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_set(fmpzi_imagref(res), fmpzi_imagref(x)); return GR_SUCCESS; } int _gr_fmpzi_sub_fmpz(fmpzi_t res, const fmpzi_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_sub(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_set(fmpzi_imagref(res), fmpzi_imagref(x)); return GR_SUCCESS; } int _gr_fmpzi_mul(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { fmpzi_mul(res, x, y); return GR_SUCCESS; } int _gr_fmpzi_mul_ui(fmpzi_t res, const fmpzi_t x, ulong y, const gr_ctx_t ctx) { fmpz_mul_ui(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_mul_ui(fmpzi_imagref(res), fmpzi_imagref(x), y); return GR_SUCCESS; } int _gr_fmpzi_mul_si(fmpzi_t res, const fmpzi_t x, slong y, const gr_ctx_t ctx) { fmpz_mul_si(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_mul_si(fmpzi_imagref(res), fmpzi_imagref(x), y); return GR_SUCCESS; } int _gr_fmpzi_mul_fmpz(fmpzi_t res, const fmpzi_t x, const fmpz_t y, const gr_ctx_t ctx) { fmpz_mul(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_mul(fmpzi_imagref(res), fmpzi_imagref(x), y); return GR_SUCCESS; } /* todo: addmul, submul */ int _gr_fmpzi_mul_two(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { fmpz_mul_2exp(fmpzi_realref(res), fmpzi_realref(x), 1); fmpz_mul_2exp(fmpzi_imagref(res), fmpzi_imagref(x), 1); return GR_SUCCESS; } int _gr_fmpzi_sqr(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { fmpzi_mul(res, x, x); return GR_SUCCESS; } int _gr_fmpzi_mul_2exp_si(fmpzi_t res, const fmpzi_t x, slong y, const gr_ctx_t ctx) { if (y >= 0) { fmpz_mul_2exp(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_mul_2exp(fmpzi_imagref(res), fmpzi_imagref(x), y); return GR_SUCCESS; } else if (fmpzi_is_zero(x)) { fmpzi_zero(res); return GR_SUCCESS; } else { ulong val; ulong v = -(ulong) y; if (!fmpz_is_zero(fmpzi_realref(x))) { val = fmpz_val2(fmpzi_realref(x)); if (val < v) return GR_DOMAIN; } if (!fmpz_is_zero(fmpzi_imagref(x))) { val = fmpz_val2(fmpzi_imagref(x)); if (val < v) return GR_DOMAIN; } fmpz_tdiv_q_2exp(fmpzi_realref(res), fmpzi_realref(x), v); fmpz_tdiv_q_2exp(fmpzi_imagref(res), fmpzi_imagref(x), v); return GR_SUCCESS; } } int _gr_fmpzi_mul_2exp_fmpz(fmpzi_t res, const fmpzi_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpzi_is_zero(x)) { fmpzi_zero(res); return GR_SUCCESS; } if (COEFF_IS_MPZ(*y)) return GR_UNABLE; return _gr_fmpzi_mul_2exp_si(res, x, *y, ctx); } int _gr_fmpzi_inv(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { if (fmpzi_is_unit(x)) { if (fmpz_is_zero(fmpzi_imagref(x))) fmpzi_set(res, x); else fmpzi_neg(res, x); return GR_SUCCESS; } else { return GR_DOMAIN; } } /* todo: division optimizations (real/imag values, divexact, divisibility checking...) */ int _gr_fmpzi_div(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { if (fmpzi_is_zero(y)) { return GR_DOMAIN; } else { fmpzi_t r; int status; fmpzi_init(r); fmpzi_divrem_approx(res, r, x, y); status = fmpzi_is_zero(r) ? GR_SUCCESS : GR_DOMAIN; fmpzi_clear(r); return status; } } int _gr_fmpzi_divexact(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { if (fmpzi_is_zero(y)) { return GR_DOMAIN; } else { fmpzi_divexact(res, x, y); return GR_SUCCESS; } } int _gr_fmpzi_divexact_ui(fmpzi_t res, const fmpzi_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpz_divexact_ui(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_divexact_ui(fmpzi_imagref(res), fmpzi_imagref(x), y); return GR_SUCCESS; } } int _gr_fmpzi_divexact_si(fmpzi_t res, const fmpzi_t x, slong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { fmpz_divexact_si(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_divexact_si(fmpzi_imagref(res), fmpzi_imagref(x), y); return GR_SUCCESS; } } int _gr_fmpzi_divexact_fmpz(fmpzi_t res, const fmpzi_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { fmpz_divexact(fmpzi_realref(res), fmpzi_realref(x), y); fmpz_divexact(fmpzi_imagref(res), fmpzi_imagref(x), y); return GR_SUCCESS; } } truth_t _gr_fmpzi_is_invertible(const fmpzi_t x, const gr_ctx_t ctx) { return fmpzi_is_unit(x) ? T_TRUE : T_FALSE; } truth_t _gr_fmpzi_divides(const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { fmpzi_t q, r; truth_t result; if (fmpzi_is_zero(y)) return T_TRUE; if (fmpzi_is_zero(x)) return T_FALSE; fmpzi_init(q); fmpzi_init(r); fmpzi_divrem_approx(q, r, y, x); result = fmpzi_is_zero(r) ? T_TRUE : T_FALSE; fmpzi_clear(q); fmpzi_clear(r); return result; } int _gr_fmpzi_euclidean_div(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { if (fmpzi_is_zero(y)) { return GR_DOMAIN; } else { fmpzi_t r; fmpzi_init(r); fmpzi_divrem(res, r, x, y); fmpzi_clear(r); return GR_SUCCESS; } } int _gr_fmpzi_euclidean_rem(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { if (fmpzi_is_zero(y)) { return GR_DOMAIN; } else { fmpzi_t q; fmpzi_init(q); fmpzi_divrem(q, res, x, y); fmpzi_clear(q); return GR_SUCCESS; } } int _gr_fmpzi_euclidean_divrem(fmpzi_t res1, fmpzi_t res2, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { if (fmpzi_is_zero(y)) { return GR_DOMAIN; } else { fmpzi_divrem(res1, res2, x, y); return GR_SUCCESS; } } int _gr_fmpzi_gcd(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { fmpzi_gcd(res, x, y); return GR_SUCCESS; } int _gr_fmpzi_lcm(fmpzi_t res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { if (fmpzi_is_zero(x) || fmpzi_is_zero(y)) { fmpzi_zero(res); } else { fmpzi_t g; fmpzi_init(g); fmpzi_gcd(g, x, y); fmpzi_mul(res, x, y); if (!fmpzi_is_one(g)) fmpzi_divexact(res, res, g); /* is this what we want? */ fmpzi_canonicalise_unit(res, res); fmpzi_clear(g); } return GR_SUCCESS; } int _gr_fmpzi_pow_ui(fmpzi_t res, const fmpzi_t x, ulong exp, const gr_ctx_t ctx) { fmpzi_pow_ui(res, x, exp); return GR_SUCCESS; } int _gr_fmpzi_pow_si(fmpzi_t res, const fmpzi_t x, slong exp, const gr_ctx_t ctx) { if (exp < 0) { if (!fmpzi_is_unit(x)) return GR_DOMAIN; exp = exp & 3; } return _gr_fmpzi_pow_ui(res, x, exp, ctx); } int _gr_fmpzi_pow_fmpz(fmpzi_t res, const fmpzi_t x, const fmpz_t exp, const gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*exp)) { return _gr_fmpzi_pow_si(res, x, *exp, ctx); } else if (fmpzi_is_unit(x)) { fmpzi_pow_ui(res, x, fmpz_fdiv_ui(exp, 4)); return GR_SUCCESS; } else if (fmpzi_is_zero(x)) { if (fmpz_sgn(exp) > 0) { fmpzi_zero(res); return GR_SUCCESS; } return GR_DOMAIN; } else if (fmpz_sgn(exp) < 0) { return GR_DOMAIN; } else { return GR_UNABLE; } } int _gr_fmpzi_pow(fmpzi_t res, const fmpzi_t x, const fmpzi_t exp, const gr_ctx_t ctx) { if (fmpz_is_zero(fmpzi_imagref(exp))) { return _gr_fmpzi_pow_fmpz(res, x, fmpzi_realref(exp), ctx); } else if (fmpzi_is_zero(x)) { if (fmpz_sgn(fmpzi_realref(exp)) > 0) { fmpzi_zero(res); return GR_SUCCESS; } else { return GR_DOMAIN; } } else if (fmpzi_is_one(x)) { fmpzi_one(res); return GR_SUCCESS; } else { return GR_DOMAIN; } } /* int _gr_fmpzi_pow_fmpq(fmpzi_t res, const fmpzi_t x, const fmpq_t exp, const gr_ctx_t ctx) { if (fmpz_is_one(fmpq_denref(exp))) { return _gr_fmpzi_pow_fmpz(res, x, fmpq_numref(exp), ctx); } else { qqbar_t t; int status; fmpzi_get_qqbar(t, x); if (qqbar_pow_fmpq(t, t, exp) && fmpzi_set_qqbar(res, t)) status = GR_SUCCESS; else status = GR_UNABLE; qqbar_clear(t); return status; } } */ /* truth_t _gr_fmpzi_is_square(const fmpzi_t x, const gr_ctx_t ctx) { return fmpzi_is_square(x) ? T_TRUE : T_FALSE; } int _gr_fmpzi_sqrt(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { } int _gr_fmpzi_rsqrt(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { } int _gr_fmpzi_abs(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { } */ int _gr_fmpzi_i(fmpzi_t res, const gr_ctx_t ctx) { fmpz_zero(fmpzi_realref(res)); fmpz_one(fmpzi_imagref(res)); return GR_SUCCESS; } int _gr_fmpzi_conj(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { fmpz_set(fmpzi_realref(res), fmpzi_realref(x)); fmpz_neg(fmpzi_imagref(res), fmpzi_imagref(x)); return GR_SUCCESS; } int _gr_fmpzi_re(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { fmpz_set(fmpzi_realref(res), fmpzi_realref(x)); fmpz_zero(fmpzi_imagref(res)); return GR_SUCCESS; } int _gr_fmpzi_im(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { fmpz_set(fmpzi_realref(res), fmpzi_imagref(x)); fmpz_zero(fmpzi_imagref(res)); return GR_SUCCESS; } /* int _gr_fmpzi_sgn(fmpzi_t res, const fmpzi_t x, const gr_ctx_t ctx) { } int _gr_fmpzi_cmp(int * res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { } int _gr_fmpzi_cmpabs(int * res, const fmpzi_t x, const fmpzi_t y, const gr_ctx_t ctx) { } */ int _fmpzi_methods_initialized = 0; gr_static_method_table _fmpzi_methods; gr_method_tab_input _fmpzi_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fmpzi_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fmpzi_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpzi_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fmpzi_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fmpzi_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fmpzi_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fmpzi_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fmpzi_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fmpzi_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fmpzi_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fmpzi_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_fmpzi_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fmpzi_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fmpzi_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fmpzi_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fmpzi_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fmpzi_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_fmpzi_set_fmpq}, {GR_METHOD_SET_D, (gr_funcptr) _gr_fmpzi_set_d}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fmpzi_set_other}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_fmpzi_get_fmpz}, {GR_METHOD_GET_FMPQ, (gr_funcptr) _gr_fmpzi_get_fmpq}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_fmpzi_get_ui}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_fmpzi_get_si}, {GR_METHOD_GET_D, (gr_funcptr) _gr_fmpzi_get_d}, {GR_METHOD_GET_FEXPR, (gr_funcptr) _gr_fmpzi_get_fexpr}, {GR_METHOD_NEG, (gr_funcptr) _gr_fmpzi_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fmpzi_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_fmpzi_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_fmpzi_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_fmpzi_add_fmpz}, {GR_METHOD_SUB, (gr_funcptr) _gr_fmpzi_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_fmpzi_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_fmpzi_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_fmpzi_sub_fmpz}, {GR_METHOD_MUL, (gr_funcptr) _gr_fmpzi_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fmpzi_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fmpzi_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fmpzi_mul_fmpz}, /* {GR_METHOD_ADDMUL, (gr_funcptr) _gr_fmpzi_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_fmpzi_submul}, */ {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_fmpzi_mul_two}, {GR_METHOD_SQR, (gr_funcptr) _gr_fmpzi_sqr}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) _gr_fmpzi_mul_2exp_si}, {GR_METHOD_MUL_2EXP_FMPZ, (gr_funcptr) _gr_fmpzi_mul_2exp_fmpz}, {GR_METHOD_DIV, (gr_funcptr) _gr_fmpzi_div}, {GR_METHOD_DIVEXACT, (gr_funcptr) _gr_fmpzi_divexact}, {GR_METHOD_DIVEXACT_UI, (gr_funcptr) _gr_fmpzi_divexact_ui}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) _gr_fmpzi_divexact_si}, {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) _gr_fmpzi_divexact_fmpz}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fmpzi_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fmpzi_inv}, {GR_METHOD_DIVIDES, (gr_funcptr) _gr_fmpzi_divides}, {GR_METHOD_EUCLIDEAN_DIV, (gr_funcptr) _gr_fmpzi_euclidean_div}, {GR_METHOD_EUCLIDEAN_REM, (gr_funcptr) _gr_fmpzi_euclidean_rem}, {GR_METHOD_EUCLIDEAN_DIVREM,(gr_funcptr) _gr_fmpzi_euclidean_divrem}, {GR_METHOD_GCD, (gr_funcptr) _gr_fmpzi_gcd}, {GR_METHOD_LCM, (gr_funcptr) _gr_fmpzi_lcm}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fmpzi_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_fmpzi_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fmpzi_pow_fmpz}, /* {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_fmpzi_pow_fmpq}, */ {GR_METHOD_POW, (gr_funcptr) _gr_fmpzi_pow}, /* {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fmpzi_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fmpzi_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_fmpzi_rsqrt}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_fmpzi_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_fmpzi_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_fmpzi_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_fmpzi_nint}, */ {GR_METHOD_GEN, (gr_funcptr) _gr_fmpzi_i}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_I, (gr_funcptr) _gr_fmpzi_i}, {GR_METHOD_PI, (gr_funcptr) gr_not_in_domain}, /* {GR_METHOD_ABS, (gr_funcptr) _gr_fmpzi_abs}, */ {GR_METHOD_CONJ, (gr_funcptr) _gr_fmpzi_conj}, {GR_METHOD_RE, (gr_funcptr) _gr_fmpzi_re}, {GR_METHOD_IM, (gr_funcptr) _gr_fmpzi_im}, /* {GR_METHOD_SGN, (gr_funcptr) _gr_fmpzi_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_fmpzi_csgn}, {GR_METHOD_CMP, (gr_funcptr) _gr_fmpzi_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) _gr_fmpzi_cmpabs}, {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_fmpzi_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_fmpzi_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_fmpzi_poly_mullow}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_fmpzi_mat_mul}, {GR_METHOD_MAT_DET, (gr_funcptr) _gr_fmpzi_mat_det}, */ {0, (gr_funcptr) NULL}, }; void gr_ctx_init_fmpzi(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_FMPZI; ctx->sizeof_elem = sizeof(fmpzi_struct); ctx->size_limit = WORD_MAX; ctx->methods = _fmpzi_methods; if (!_fmpzi_methods_initialized) { gr_method_tab_init(_fmpzi_methods, _fmpzi_methods_input); _fmpzi_methods_initialized = 1; } } flint-3.1.3/src/gr/fq.c000066400000000000000000000472551461254215100146210ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "fq.h" #include "fq_poly.h" #include "fq_mat.h" #include "fq_poly_factor.h" #include "gr_vec.h" #include "gr_generic.h" #define FQ_CTX(ring_ctx) ((fq_ctx_struct *)(GR_CTX_DATA_AS_PTR(ring_ctx))) void _gr_fq_ctx_clear(gr_ctx_t ctx) { fq_ctx_clear(FQ_CTX(ctx)); flint_free(GR_CTX_DATA_AS_PTR(ctx)); } int _gr_fq_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Finite field (fq)"); return GR_SUCCESS; } void _gr_fq_init(fq_t x, const gr_ctx_t ctx) { fq_init(x, FQ_CTX(ctx)); } void _gr_fq_clear(fq_t x, const gr_ctx_t ctx) { fq_clear(x, FQ_CTX(ctx)); } void _gr_fq_swap(fq_t x, fq_t y, const gr_ctx_t ctx) { fq_t t; *t = *x; *x = *y; *y = *t; } void _gr_fq_set_shallow(fq_t res, const fq_t x, const gr_ctx_t ctx) { *res = *x; } int _gr_fq_randtest(fq_t res, flint_rand_t state, const gr_ctx_t ctx) { fq_randtest(res, state, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_write(gr_stream_t out, const fq_t x, const gr_ctx_t ctx) { gr_stream_write_free(out, fq_get_str_pretty(x, FQ_CTX(ctx))); return GR_SUCCESS; } int _gr_fq_zero(fq_t x, const gr_ctx_t ctx) { fq_zero(x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_one(fq_t x, const gr_ctx_t ctx) { fq_one(x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_set_si(fq_t res, slong v, const gr_ctx_t ctx) { fq_set_si(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_set_ui(fq_t res, ulong v, const gr_ctx_t ctx) { fq_set_ui(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_set_fmpz(fq_t res, const fmpz_t v, const gr_ctx_t ctx) { fq_set_fmpz(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_set_other(fq_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: fq_set_fmpz(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } return GR_UNABLE; } truth_t _gr_fq_is_zero(const fq_t x, const gr_ctx_t ctx) { return fq_is_zero(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fq_is_one(const fq_t x, const gr_ctx_t ctx) { return fq_is_one(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fq_equal(const fq_t x, const fq_t y, const gr_ctx_t ctx) { return fq_equal(x, y, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_set(fq_t res, const fq_t x, const gr_ctx_t ctx) { fq_set(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_neg(fq_t res, const fq_t x, const gr_ctx_t ctx) { fq_neg(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_add(fq_t res, const fq_t x, const fq_t y, const gr_ctx_t ctx) { fq_add(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_sub(fq_t res, const fq_t x, const fq_t y, const gr_ctx_t ctx) { fq_sub(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_mul(fq_t res, const fq_t x, const fq_t y, const gr_ctx_t ctx) { fq_mul(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_mul_si(fq_t res, const fq_t x, slong y, const gr_ctx_t ctx) { fq_mul_si(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_mul_ui(fq_t res, const fq_t x, ulong y, const gr_ctx_t ctx) { fq_mul_ui(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_mul_fmpz(fq_t res, const fq_t x, const fmpz_t y, const gr_ctx_t ctx) { fq_mul_fmpz(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_si_mul(fq_t res, slong y, const fq_t x, const gr_ctx_t ctx) { fq_mul_si(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_ui_mul(fq_t res, ulong y, const fq_t x, const gr_ctx_t ctx) { fq_mul_ui(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_fmpz_mul(fq_t res, const fmpz_t y, const fq_t x, const gr_ctx_t ctx) { fq_mul_fmpz(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_inv(fq_t res, const fq_t x, const gr_ctx_t ctx) { if (fq_is_zero(x, FQ_CTX(ctx))) { return GR_DOMAIN; } else { fq_inv(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } } int _gr_fq_div(fq_t res, const fq_t x, const fq_t y, const gr_ctx_t ctx) { if (fq_is_zero(y, FQ_CTX(ctx))) { return GR_DOMAIN; } else { fq_t t; fq_init(t, FQ_CTX(ctx)); fq_inv(t, y, FQ_CTX(ctx)); fq_mul(res, x, t, FQ_CTX(ctx)); fq_clear(t, FQ_CTX(ctx)); return GR_SUCCESS; } } int _gr_fq_sqr(fq_t res, const fq_t x, const gr_ctx_t ctx) { fq_sqr(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_pow_ui(fq_t res, const fq_t x, ulong y, const gr_ctx_t ctx) { fq_pow_ui(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_pow_fmpz(fq_t res, const fq_t x, const fmpz_t y, gr_ctx_t ctx) { if (fmpz_sgn(y) < 0) { return gr_generic_pow_fmpz(res, x, y, ctx); } else { fq_pow(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } } truth_t _gr_fq_is_invertible(const fq_t x, const gr_ctx_t ctx) { return (!fq_is_zero(x, FQ_CTX(ctx))) ? T_TRUE : T_FALSE; } truth_t _gr_fq_is_square(const fq_t x, const gr_ctx_t ctx) { return fq_is_square(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_sqrt(fq_t res, const fq_t x, const gr_ctx_t ctx) { if (fq_sqrt(res, x, FQ_CTX(ctx))) { return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_ctx_fq_prime(fmpz_t p, gr_ctx_t ctx) { fmpz_set(p, fq_ctx_prime(FQ_CTX(ctx))); return GR_SUCCESS; } int _gr_ctx_fq_degree(slong * deg, gr_ctx_t ctx) { *deg = fq_ctx_degree(FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_ctx_fq_order(fmpz_t q, gr_ctx_t ctx) { fq_ctx_order(q, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_gen(gr_ptr res, gr_ctx_t ctx) { fq_gen(res, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_frobenius(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx) { fq_frobenius(res, x, e, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_multiplicative_order(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { int ret; ret = fq_multiplicative_order(res, x, FQ_CTX(ctx)); if (ret == 1) return GR_SUCCESS; /* todo: better solution? */ return GR_DOMAIN; } int _gr_fq_norm(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { fq_norm(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_trace(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { fq_trace(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_fq_is_primitive(gr_srcptr x, gr_ctx_t ctx) { return fq_is_primitive(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_pth_root(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { fq_pth_root(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_vec_dot(fq_struct * res, const fq_struct * initial, int subtract, const fq_struct * vec1, const fq_struct * vec2, slong len, gr_ctx_t ctx) { slong i; fmpz * s, * t; slong slen, tlen, len1, len2; slong plen; if (len <= 0) { if (initial == NULL) fq_zero(res, FQ_CTX(ctx)); else fq_set(res, initial, FQ_CTX(ctx)); return GR_SUCCESS; } plen = FQ_CTX(ctx)->modulus->length; t = GR_TMP_ALLOC((4 * plen) * sizeof(fmpz)); s = t + 2 * plen; for (i = 0; i < 4 * plen; i++) fmpz_init(t + i); len1 = vec1[0].length; len2 = vec2[0].length; if (len1 == 0 || len2 == 0) { slen = 0; } else { slen = len1 + len2 - 1; if (len1 >= len2) _fmpz_poly_mul(s, vec1[0].coeffs, len1, vec2[0].coeffs, len2); else _fmpz_poly_mul(s, vec2[0].coeffs, len2, vec1[0].coeffs, len1); } for (i = 1; i < len; i++) { len1 = vec1[i].length; len2 = vec2[i].length; if (len1 != 0 && len2 != 0) { tlen = len1 + len2 - 1; if (len1 >= len2) _fmpz_poly_mul(t, vec1[i].coeffs, len1, vec2[i].coeffs, len2); else _fmpz_poly_mul(t, vec2[i].coeffs, len2, vec1[i].coeffs, len1); _fmpz_poly_add(s, s, slen, t, tlen); slen = FLINT_MAX(slen, tlen); } } if (initial == NULL) { if (subtract) _fmpz_vec_neg(s, s, slen); } else { len2 = initial->length; if (subtract) _fmpz_poly_sub(s, initial->coeffs, len2, s, slen); else _fmpz_poly_add(s, initial->coeffs, len2, s, slen); slen = FLINT_MAX(slen, len2); } while (slen > 0 && fmpz_is_zero(s + slen - 1)) slen--; _fq_reduce(s, slen, FQ_CTX(ctx)); slen = FLINT_MIN(slen, plen - 1); while (slen > 0 && fmpz_is_zero(s + slen - 1)) slen--; fmpz_poly_fit_length(res, slen); _fmpz_vec_set(res->coeffs, s, slen); /* todo: swap */ _fmpz_poly_set_length(res, slen); for (i = 0; i < 4 * plen; i++) fmpz_clear(t + i); GR_TMP_FREE(t, (4 * plen) * sizeof(fmpz)); return GR_SUCCESS; } int _gr_fq_vec_dot_rev(fq_struct * res, const fq_struct * initial, int subtract, const fq_struct * vec1, const fq_struct * vec2, slong len, gr_ctx_t ctx) { slong i; fmpz * s, * t; slong slen, tlen, len1, len2; slong plen; if (len <= 0) { if (initial == NULL) fq_zero(res, FQ_CTX(ctx)); else fq_set(res, initial, FQ_CTX(ctx)); return GR_SUCCESS; } plen = FQ_CTX(ctx)->modulus->length; t = GR_TMP_ALLOC((4 * plen) * sizeof(fmpz)); s = t + 2 * plen; for (i = 0; i < 4 * plen; i++) fmpz_init(t + i); len1 = vec1[0].length; len2 = vec2[len - 1].length; if (len1 == 0 || len2 == 0) { slen = 0; } else { slen = len1 + len2 - 1; if (len1 >= len2) _fmpz_poly_mul(s, vec1[0].coeffs, len1, vec2[len - 1].coeffs, len2); else _fmpz_poly_mul(s, vec2[len - 1].coeffs, len2, vec1[0].coeffs, len1); } for (i = 1; i < len; i++) { len1 = vec1[i].length; len2 = vec2[len - 1 - i].length; if (len1 != 0 && len2 != 0) { tlen = len1 + len2 - 1; if (len1 >= len2) _fmpz_poly_mul(t, vec1[i].coeffs, len1, vec2[len - 1 - i].coeffs, len2); else _fmpz_poly_mul(t, vec2[len - 1 - i].coeffs, len2, vec1[i].coeffs, len1); _fmpz_poly_add(s, s, slen, t, tlen); slen = FLINT_MAX(slen, tlen); } } if (initial == NULL) { if (subtract) _fmpz_vec_neg(s, s, slen); } else { len2 = initial->length; if (subtract) _fmpz_poly_sub(s, initial->coeffs, len2, s, slen); else _fmpz_poly_add(s, initial->coeffs, len2, s, slen); slen = FLINT_MAX(slen, len2); } while (slen > 0 && fmpz_is_zero(s + slen - 1)) slen--; _fq_reduce(s, slen, FQ_CTX(ctx)); slen = FLINT_MIN(slen, plen - 1); while (slen > 0 && fmpz_is_zero(s + slen - 1)) slen--; fmpz_poly_fit_length(res, slen); _fmpz_vec_set(res->coeffs, s, slen); /* todo: swap */ _fmpz_poly_set_length(res, slen); for (i = 0; i < 4 * plen; i++) fmpz_clear(t + i); GR_TMP_FREE(t, (4 * plen) * sizeof(fmpz)); return GR_SUCCESS; } /* todo: _fq_poly_mullow should do the right thing */ int _gr_fq_poly_mullow(fq_struct * res, const fq_struct * poly1, slong len1, const fq_struct * poly2, slong len2, slong n, gr_ctx_t ctx) { if (len1 + len2 - 1 == n) { if (poly1 == poly2 && len1 == len2) _fq_poly_sqr(res, poly1, len1, FQ_CTX(ctx)); else if (len1 >= len2) _fq_poly_mul(res, poly1, len1, poly2, len2, FQ_CTX(ctx)); else _fq_poly_mul(res, poly2, len2, poly1, len1, FQ_CTX(ctx)); } else { if (len1 >= len2) _fq_poly_mullow(res, poly1, len1, poly2, len2, n, FQ_CTX(ctx)); else _fq_poly_mullow(res, poly2, len2, poly1, len1, n, FQ_CTX(ctx)); } return GR_SUCCESS; } /* todo: also need the _other version ... ? */ /* todo: implement generically */ int _gr_fq_roots_gr_poly(gr_vec_t roots, gr_vec_t mult, const fq_poly_t poly, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; { gr_ctx_t ZZ; fq_poly_factor_t fac; slong i, num; gr_ctx_init_fmpz(ZZ); fq_poly_factor_init(fac, FQ_CTX(ctx)); fq_poly_roots(fac, poly, 1, FQ_CTX(ctx)); num = fac->num; gr_vec_set_length(roots, num, ctx); gr_vec_set_length(mult, num, ZZ); for (i = 0; i < num; i++) { fq_neg(gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs, FQ_CTX(ctx)); /* work around flint bug: factors can be non-monic */ if (!fq_is_one(fac->poly[i].coeffs + 1, FQ_CTX(ctx))) fq_div(gr_vec_entry_ptr(roots, i, ctx), gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs + 1, FQ_CTX(ctx)); fmpz_set_ui(((fmpz *) mult->entries) + i, fac->exp[i]); } fq_poly_factor_clear(fac, FQ_CTX(ctx)); gr_ctx_clear(ZZ); } return GR_SUCCESS; } int _gr_fq_mat_mul(fq_mat_t res, const fq_mat_t x, const fq_mat_t y, gr_ctx_t ctx) { fq_mat_mul(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _fq_methods_initialized = 0; gr_static_method_table _fq_methods; gr_method_tab_input _fq_methods_input[] = { {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_fq_ctx_clear}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fq_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fq_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fq_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fq_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fq_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fq_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fq_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fq_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fq_one}, {GR_METHOD_GEN, (gr_funcptr) _gr_fq_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fq_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fq_is_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fq_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fq_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fq_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fq_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fq_set_fmpz}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_fq_set_other}, {GR_METHOD_NEG, (gr_funcptr) _gr_fq_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fq_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_fq_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fq_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fq_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fq_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fq_mul_fmpz}, /* {GR_METHOD_SI_MUL, (gr_funcptr) _gr_fq_si_mul}, {GR_METHOD_UI_MUL, (gr_funcptr) _gr_fq_ui_mul}, {GR_METHOD_FMPZ_MUL, (gr_funcptr) _gr_fq_fmpz_mul}, */ /* {GR_METHOD_MUL_OTHER, (gr_funcptr) _gr_fq_mul_other}, {GR_METHOD_OTHER_MUL, (gr_funcptr) _gr_fq_other_mul}, */ {GR_METHOD_SQR, (gr_funcptr) _gr_fq_sqr}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fq_pow_ui}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fq_pow_fmpz}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fq_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fq_inv}, {GR_METHOD_DIV, (gr_funcptr) _gr_fq_div}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fq_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fq_sqrt}, {GR_METHOD_CTX_FQ_PRIME, (gr_funcptr) _gr_ctx_fq_prime}, {GR_METHOD_CTX_FQ_DEGREE, (gr_funcptr) _gr_ctx_fq_degree}, {GR_METHOD_CTX_FQ_ORDER, (gr_funcptr) _gr_ctx_fq_order}, {GR_METHOD_FQ_FROBENIUS, (gr_funcptr) _gr_fq_frobenius}, {GR_METHOD_FQ_MULTIPLICATIVE_ORDER, (gr_funcptr) _gr_fq_multiplicative_order}, {GR_METHOD_FQ_NORM, (gr_funcptr) _gr_fq_norm}, {GR_METHOD_FQ_TRACE, (gr_funcptr) _gr_fq_trace}, {GR_METHOD_FQ_IS_PRIMITIVE, (gr_funcptr) _gr_fq_is_primitive}, {GR_METHOD_FQ_PTH_ROOT, (gr_funcptr) _gr_fq_pth_root}, {GR_METHOD_VEC_DOT, (gr_funcptr) _gr_fq_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _gr_fq_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_fq_poly_mullow}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_fq_roots_gr_poly}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_fq_mat_mul}, {0, (gr_funcptr) NULL}, }; void _gr_ctx_init_fq_from_ref(gr_ctx_t ctx, const void * fq_ctx) { ctx->which_ring = GR_CTX_FQ; ctx->sizeof_elem = sizeof(fq_struct); GR_CTX_DATA_AS_PTR(ctx) = (fq_ctx_struct *) fq_ctx; ctx->size_limit = WORD_MAX; ctx->methods = _fq_methods; if (!_fq_methods_initialized) { gr_method_tab_init(_fq_methods, _fq_methods_input); _fq_methods_initialized = 1; } } void gr_ctx_init_fq(gr_ctx_t ctx, const fmpz_t p, slong d, const char * var) { fq_ctx_struct * fq_ctx; fq_ctx = flint_malloc(sizeof(fq_ctx_struct)); fq_ctx_init(fq_ctx, p, d, var == NULL ? "a" : var); _gr_ctx_init_fq_from_ref(ctx, fq_ctx); } int gr_ctx_init_fq_modulus_fmpz_mod_poly(gr_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var) { fq_ctx_struct * fq_ctx; fq_ctx = flint_malloc(sizeof(fq_ctx_struct)); fq_ctx_init_modulus(fq_ctx, modulus, mod_ctx, var == NULL ? "a" : var); _gr_ctx_init_fq_from_ref(ctx, fq_ctx); return GR_SUCCESS; } int gr_ctx_init_fq_modulus_nmod_poly(gr_ctx_t ctx, const nmod_poly_t modulus, const char * var) { fmpz_mod_ctx_t fmod_ctx; fmpz_mod_poly_t fmod; fmpz_t p; int status; fmpz_init_set_ui(p, modulus->mod.n); fmpz_mod_ctx_init(fmod_ctx, p); fmpz_mod_poly_init(fmod, fmod_ctx); fmpz_mod_poly_set_nmod_poly(fmod, modulus); status = gr_ctx_init_fq_modulus_fmpz_mod_poly(ctx, fmod, fmod_ctx, var); fmpz_mod_poly_clear(fmod, fmod_ctx); fmpz_mod_ctx_clear(fmod_ctx); fmpz_clear(p); return status; } flint-3.1.3/src/gr/fq_nmod.c000066400000000000000000000474521461254215100156350ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq.h" #include "fq_nmod.h" #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_generic.h" #define FQ_CTX(ring_ctx) ((fq_nmod_ctx_struct *)(GR_CTX_DATA_AS_PTR(ring_ctx))) void _gr_fq_nmod_ctx_clear(gr_ctx_t ctx) { fq_nmod_ctx_clear(FQ_CTX(ctx)); flint_free(GR_CTX_DATA_AS_PTR(ctx)); } int _gr_fq_nmod_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Finite field (fq_nmod)"); return GR_SUCCESS; } void _gr_fq_nmod_init(fq_nmod_t x, const gr_ctx_t ctx) { fq_nmod_init(x, FQ_CTX(ctx)); } void _gr_fq_nmod_clear(fq_nmod_t x, const gr_ctx_t ctx) { fq_nmod_clear(x, FQ_CTX(ctx)); } void _gr_fq_nmod_swap(fq_nmod_t x, fq_nmod_t y, const gr_ctx_t ctx) { fq_nmod_t t; *t = *x; *x = *y; *y = *t; } void _gr_fq_nmod_set_shallow(fq_nmod_t res, const fq_nmod_t x, const gr_ctx_t ctx) { *res = *x; } int _gr_fq_nmod_randtest(fq_nmod_t res, flint_rand_t state, const gr_ctx_t ctx) { fq_nmod_randtest(res, state, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_write(gr_stream_t out, const fq_nmod_t x, const gr_ctx_t ctx) { gr_stream_write_free(out, fq_nmod_get_str_pretty(x, FQ_CTX(ctx))); return GR_SUCCESS; } int _gr_fq_nmod_zero(fq_nmod_t x, const gr_ctx_t ctx) { fq_nmod_zero(x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_one(fq_nmod_t x, const gr_ctx_t ctx) { fq_nmod_one(x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_set_si(fq_nmod_t res, slong v, const gr_ctx_t ctx) { fq_nmod_set_si(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_set_ui(fq_nmod_t res, ulong v, const gr_ctx_t ctx) { fq_nmod_set_ui(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_set_fmpz(fq_nmod_t res, const fmpz_t v, const gr_ctx_t ctx) { fq_nmod_set_fmpz(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_fq_nmod_is_zero(const fq_nmod_t x, const gr_ctx_t ctx) { return fq_nmod_is_zero(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fq_nmod_is_one(const fq_nmod_t x, const gr_ctx_t ctx) { return fq_nmod_is_one(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fq_nmod_equal(const fq_nmod_t x, const fq_nmod_t y, const gr_ctx_t ctx) { return fq_nmod_equal(x, y, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_nmod_set(fq_nmod_t res, const fq_nmod_t x, const gr_ctx_t ctx) { fq_nmod_set(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_neg(fq_nmod_t res, const fq_nmod_t x, const gr_ctx_t ctx) { fq_nmod_neg(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_add(fq_nmod_t res, const fq_nmod_t x, const fq_nmod_t y, const gr_ctx_t ctx) { fq_nmod_add(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_sub(fq_nmod_t res, const fq_nmod_t x, const fq_nmod_t y, const gr_ctx_t ctx) { fq_nmod_sub(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_mul(fq_nmod_t res, const fq_nmod_t x, const fq_nmod_t y, const gr_ctx_t ctx) { fq_nmod_mul(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_mul_si(fq_nmod_t res, const fq_nmod_t x, slong y, const gr_ctx_t ctx) { fq_nmod_mul_si(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_mul_ui(fq_nmod_t res, const fq_nmod_t x, ulong y, const gr_ctx_t ctx) { fq_nmod_mul_ui(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_mul_fmpz(fq_nmod_t res, const fq_nmod_t x, const fmpz_t y, const gr_ctx_t ctx) { fq_nmod_mul_fmpz(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_inv(fq_nmod_t res, const fq_nmod_t x, const gr_ctx_t ctx) { if (fq_nmod_is_zero(x, FQ_CTX(ctx))) { return GR_DOMAIN; } else { fq_nmod_inv(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } } int _gr_fq_nmod_div(fq_nmod_t res, const fq_nmod_t x, const fq_nmod_t y, const gr_ctx_t ctx) { if (fq_nmod_is_zero(y, FQ_CTX(ctx))) { return GR_DOMAIN; } else { fq_nmod_t t; fq_nmod_init(t, FQ_CTX(ctx)); fq_nmod_inv(t, y, FQ_CTX(ctx)); fq_nmod_mul(res, x, t, FQ_CTX(ctx)); fq_nmod_clear(t, FQ_CTX(ctx)); return GR_SUCCESS; } } int _gr_fq_nmod_sqr(fq_nmod_t res, const fq_nmod_t x, const gr_ctx_t ctx) { fq_nmod_sqr(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_pow_ui(fq_nmod_t res, const fq_nmod_t x, ulong y, const gr_ctx_t ctx) { fq_nmod_pow_ui(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_pow_fmpz(fq_nmod_t res, const fq_nmod_t x, const fmpz_t y, gr_ctx_t ctx) { if (fmpz_sgn(y) < 0) { return gr_generic_pow_fmpz(res, x, y, ctx); } else { fq_nmod_pow(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } } truth_t _gr_fq_nmod_is_invertible(const fq_nmod_t x, const gr_ctx_t ctx) { return (!fq_nmod_is_zero(x, FQ_CTX(ctx))) ? T_TRUE : T_FALSE; } truth_t _gr_fq_nmod_is_square(const fq_nmod_t x, const gr_ctx_t ctx) { return fq_nmod_is_square(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_nmod_sqrt(fq_nmod_t res, const fq_nmod_t x, const gr_ctx_t ctx) { if (fq_nmod_sqrt(res, x, FQ_CTX(ctx))) { return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_ctx_fq_nmod_prime(ulong * p, gr_ctx_t ctx) { *p = fq_nmod_ctx_prime(FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_ctx_fq_nmod_degree(slong * deg, gr_ctx_t ctx) { *deg = fq_nmod_ctx_degree(FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_ctx_fq_nmod_order(fmpz_t q, gr_ctx_t ctx) { fq_nmod_ctx_order(q, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_gen(gr_ptr res, gr_ctx_t ctx) { fq_nmod_gen(res, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_frobenius(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx) { fq_nmod_frobenius(res, x, e, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_multiplicative_order(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { int ret; ret = fq_nmod_multiplicative_order(res, x, FQ_CTX(ctx)); if (ret == 1) return GR_SUCCESS; /* todo: better solution? */ return GR_DOMAIN; } int _gr_fq_nmod_norm(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { fq_nmod_norm(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_nmod_trace(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { fq_nmod_trace(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_fq_nmod_is_primitive(gr_srcptr x, gr_ctx_t ctx) { return fq_nmod_is_primitive(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_nmod_pth_root(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { fq_nmod_pth_root(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } /* todo: basecase multiplication without reductions */ int __gr_fq_nmod_vec_dot(fq_nmod_struct * res, const fq_nmod_struct * initial, int subtract, const fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len, gr_ctx_t ctx) { slong i; mp_ptr s, t; slong slen, tlen, len1, len2; slong plen; nmod_t mod; if (len <= 0) { if (initial == NULL) fq_nmod_zero(res, FQ_CTX(ctx)); else fq_nmod_set(res, initial, FQ_CTX(ctx)); return GR_SUCCESS; } plen = FQ_CTX(ctx)->modulus->length; t = GR_TMP_ALLOC((4 * plen) * sizeof(mp_limb_t)); s = t + 2 * plen; mod = FQ_CTX(ctx)->mod; len1 = vec1[0].length; len2 = vec2[0].length; if (len1 == 0 || len2 == 0) { slen = 0; } else { slen = len1 + len2 - 1; if (len1 >= len2) _nmod_poly_mul(s, vec1[0].coeffs, len1, vec2[0].coeffs, len2, mod); else _nmod_poly_mul(s, vec2[0].coeffs, len2, vec1[0].coeffs, len1, mod); } for (i = 1; i < len; i++) { len1 = vec1[i].length; len2 = vec2[i].length; if (len1 != 0 && len2 != 0) { tlen = len1 + len2 - 1; if (len1 >= len2) _nmod_poly_mul(t, vec1[i].coeffs, len1, vec2[i].coeffs, len2, mod); else _nmod_poly_mul(t, vec2[i].coeffs, len2, vec1[i].coeffs, len1, mod); _nmod_poly_add(s, s, slen, t, tlen, mod); slen = FLINT_MAX(slen, tlen); } } if (initial == NULL) { if (subtract) _nmod_vec_neg(s, s, slen, mod); } else { len2 = initial->length; if (subtract) _nmod_poly_sub(s, initial->coeffs, len2, s, slen, mod); else _nmod_poly_add(s, initial->coeffs, len2, s, slen, mod); slen = FLINT_MAX(slen, len2); } while (slen > 0 && s[slen - 1] == 0) slen--; _fq_nmod_reduce(s, slen, FQ_CTX(ctx)); slen = FLINT_MIN(slen, plen - 1); while (slen > 0 && s[slen - 1] == 0) slen--; nmod_poly_fit_length(res, slen); _nmod_vec_set(res->coeffs, s, slen); _nmod_poly_set_length(res, slen); GR_TMP_FREE(t, (4 * plen) * sizeof(mp_limb_t)); return GR_SUCCESS; } /* todo: basecase multiplication without reductions */ int __gr_fq_nmod_vec_dot_rev(fq_nmod_struct * res, const fq_nmod_struct * initial, int subtract, const fq_nmod_struct * vec1, const fq_nmod_struct * vec2, slong len, gr_ctx_t ctx) { slong i; mp_ptr s, t; slong slen, tlen, len1, len2; slong plen; nmod_t mod; if (len <= 0) { if (initial == NULL) fq_nmod_zero(res, FQ_CTX(ctx)); else fq_nmod_set(res, initial, FQ_CTX(ctx)); return GR_SUCCESS; } plen = FQ_CTX(ctx)->modulus->length; t = GR_TMP_ALLOC((4 * plen) * sizeof(mp_limb_t)); s = t + 2 * plen; mod = FQ_CTX(ctx)->mod; len1 = vec1[0].length; len2 = vec2[len - 1].length; if (len1 == 0 || len2 == 0) { slen = 0; } else { slen = len1 + len2 - 1; if (len1 >= len2) _nmod_poly_mul(s, vec1[0].coeffs, len1, vec2[len - 1].coeffs, len2, mod); else _nmod_poly_mul(s, vec2[len - 1].coeffs, len2, vec1[0].coeffs, len1, mod); } for (i = 1; i < len; i++) { len1 = vec1[i].length; len2 = vec2[len - 1 - i].length; if (len1 != 0 && len2 != 0) { tlen = len1 + len2 - 1; if (len1 >= len2) _nmod_poly_mul(t, vec1[i].coeffs, len1, vec2[len - 1 - i].coeffs, len2, mod); else _nmod_poly_mul(t, vec2[len - 1 - i].coeffs, len2, vec1[i].coeffs, len1, mod); _nmod_poly_add(s, s, slen, t, tlen, mod); slen = FLINT_MAX(slen, tlen); } } if (initial == NULL) { if (subtract) _nmod_vec_neg(s, s, slen, mod); } else { len2 = initial->length; if (subtract) _nmod_poly_sub(s, initial->coeffs, len2, s, slen, mod); else _nmod_poly_add(s, initial->coeffs, len2, s, slen, mod); slen = FLINT_MAX(slen, len2); } while (slen > 0 && s[slen - 1] == 0) slen--; _fq_nmod_reduce(s, slen, FQ_CTX(ctx)); slen = FLINT_MIN(slen, plen - 1); while (slen > 0 && s[slen - 1] == 0) slen--; nmod_poly_fit_length(res, slen); _nmod_vec_set(res->coeffs, s, slen); _nmod_poly_set_length(res, slen); GR_TMP_FREE(t, (4 * plen) * sizeof(mp_limb_t)); return GR_SUCCESS; } /* todo: _fq_nmod_poly_mullow should do the right thing */ int _gr_fq_nmod_poly_mullow(fq_nmod_struct * res, const fq_nmod_struct * poly1, slong len1, const fq_nmod_struct * poly2, slong len2, slong n, gr_ctx_t ctx) { if (len1 + len2 - 1 == n) { if (poly1 == poly2 && len1 == len2) _fq_nmod_poly_sqr(res, poly1, len1, FQ_CTX(ctx)); else if (len1 >= len2) _fq_nmod_poly_mul(res, poly1, len1, poly2, len2, FQ_CTX(ctx)); else _fq_nmod_poly_mul(res, poly2, len2, poly1, len1, FQ_CTX(ctx)); } else { if (len1 >= len2) _fq_nmod_poly_mullow(res, poly1, len1, poly2, len2, n, FQ_CTX(ctx)); else _fq_nmod_poly_mullow(res, poly2, len2, poly1, len1, n, FQ_CTX(ctx)); } return GR_SUCCESS; } /* todo: also need the _other version ... ? */ /* todo: implement generically */ int _gr_fq_nmod_roots_gr_poly(gr_vec_t roots, gr_vec_t mult, const fq_nmod_poly_t poly, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; { gr_ctx_t ZZ; fq_nmod_poly_factor_t fac; slong i, num; gr_ctx_init_fmpz(ZZ); fq_nmod_poly_factor_init(fac, FQ_CTX(ctx)); fq_nmod_poly_roots(fac, poly, 1, FQ_CTX(ctx)); num = fac->num; gr_vec_set_length(roots, num, ctx); gr_vec_set_length(mult, num, ZZ); for (i = 0; i < num; i++) { fq_nmod_neg(gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs, FQ_CTX(ctx)); /* work around flint bug: factors can be non-monic */ if (!fq_nmod_is_one(fac->poly[i].coeffs + 1, FQ_CTX(ctx))) fq_nmod_div(gr_vec_entry_ptr(roots, i, ctx), gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs + 1, FQ_CTX(ctx)); fmpz_set_ui(((fmpz *) mult->entries) + i, fac->exp[i]); } fq_nmod_poly_factor_clear(fac, FQ_CTX(ctx)); gr_ctx_clear(ZZ); } return GR_SUCCESS; } int _gr_fq_nmod_mat_mul(fq_nmod_mat_t res, const fq_nmod_mat_t x, const fq_nmod_mat_t y, gr_ctx_t ctx) { fq_nmod_mat_mul(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _fq_nmod_methods_initialized = 0; gr_static_method_table _fq_nmod_methods; gr_method_tab_input _fq_nmod_methods_input[] = { {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_fq_nmod_ctx_clear}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fq_nmod_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fq_nmod_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fq_nmod_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fq_nmod_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fq_nmod_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fq_nmod_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fq_nmod_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fq_nmod_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fq_nmod_one}, {GR_METHOD_GEN, (gr_funcptr) _gr_fq_nmod_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fq_nmod_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fq_nmod_is_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fq_nmod_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fq_nmod_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fq_nmod_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fq_nmod_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fq_nmod_set_fmpz}, {GR_METHOD_NEG, (gr_funcptr) _gr_fq_nmod_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fq_nmod_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_fq_nmod_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fq_nmod_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fq_nmod_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fq_nmod_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fq_nmod_mul_fmpz}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fq_nmod_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fq_nmod_inv}, {GR_METHOD_DIV, (gr_funcptr) _gr_fq_nmod_div}, {GR_METHOD_SQR, (gr_funcptr) _gr_fq_nmod_sqr}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_fq_nmod_pow_ui}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_fq_nmod_pow_fmpz}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fq_nmod_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fq_nmod_sqrt}, {GR_METHOD_CTX_FQ_PRIME, (gr_funcptr) _gr_ctx_fq_nmod_prime}, {GR_METHOD_CTX_FQ_DEGREE, (gr_funcptr) _gr_ctx_fq_nmod_degree}, {GR_METHOD_CTX_FQ_ORDER, (gr_funcptr) _gr_ctx_fq_nmod_order}, {GR_METHOD_FQ_FROBENIUS, (gr_funcptr) _gr_fq_nmod_frobenius}, {GR_METHOD_FQ_MULTIPLICATIVE_ORDER, (gr_funcptr) _gr_fq_nmod_multiplicative_order}, {GR_METHOD_FQ_NORM, (gr_funcptr) _gr_fq_nmod_norm}, {GR_METHOD_FQ_TRACE, (gr_funcptr) _gr_fq_nmod_trace}, {GR_METHOD_FQ_IS_PRIMITIVE, (gr_funcptr) _gr_fq_nmod_is_primitive}, {GR_METHOD_FQ_PTH_ROOT, (gr_funcptr) _gr_fq_nmod_pth_root}, {GR_METHOD_VEC_DOT, (gr_funcptr) __gr_fq_nmod_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) __gr_fq_nmod_vec_dot_rev}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_fq_nmod_poly_mullow}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_fq_nmod_roots_gr_poly}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_fq_nmod_mat_mul}, {0, (gr_funcptr) NULL}, }; void _gr_ctx_init_fq_nmod_from_ref(gr_ctx_t ctx, const void * fq_nmod_ctx) { ctx->which_ring = GR_CTX_FQ_NMOD; ctx->sizeof_elem = sizeof(fq_nmod_struct); GR_CTX_DATA_AS_PTR(ctx) = (fq_nmod_ctx_struct *) fq_nmod_ctx; ctx->size_limit = WORD_MAX; ctx->methods = _fq_nmod_methods; if (!_fq_nmod_methods_initialized) { gr_method_tab_init(_fq_nmod_methods, _fq_nmod_methods_input); _fq_nmod_methods_initialized = 1; } } void gr_ctx_init_fq_nmod(gr_ctx_t ctx, ulong p, slong d, const char * var) { fq_nmod_ctx_struct * fq_nmod_ctx; fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); fq_nmod_ctx_init_ui(fq_nmod_ctx, p, d, var == NULL ? "a" : var); _gr_ctx_init_fq_nmod_from_ref(ctx, fq_nmod_ctx); } int gr_ctx_init_fq_nmod_modulus_nmod_poly(gr_ctx_t ctx, const nmod_poly_t modulus, const char * var) { fq_nmod_ctx_struct * fq_nmod_ctx; fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); fq_nmod_ctx_init_modulus(fq_nmod_ctx, modulus, var == NULL ? "a" : var); _gr_ctx_init_fq_nmod_from_ref(ctx, fq_nmod_ctx); return GR_SUCCESS; } int gr_ctx_init_fq_nmod_modulus_fmpz_mod_poly(gr_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var) { nmod_poly_t nmodulus; int status; if (!fmpz_abs_fits_ui(mod_ctx->n)) return GR_UNABLE; nmod_poly_init(nmodulus, fmpz_get_ui(mod_ctx->n)); fmpz_mod_poly_get_nmod_poly(nmodulus, modulus); status = gr_ctx_init_fq_nmod_modulus_nmod_poly(ctx, nmodulus, var); nmod_poly_clear(nmodulus); return status; } flint-3.1.3/src/gr/fq_zech.c000066400000000000000000000436311461254215100156240ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "fq_zech.h" #include "fq_zech_vec.h" #include "fq_zech_poly.h" #include "fq_zech_poly_factor.h" #include "fq_zech_mat.h" #include "nmod_poly.h" #include "fmpz_mod_poly.h" #include "gr.h" #include "gr_vec.h" #include "gr_generic.h" #define FQ_CTX(ring_ctx) ((fq_zech_ctx_struct *)(GR_CTX_DATA_AS_PTR(ring_ctx))) /* todo: lots of inlining */ void _gr_fq_zech_ctx_clear(gr_ctx_t ctx) { fq_zech_ctx_clear(FQ_CTX(ctx)); flint_free(GR_CTX_DATA_AS_PTR(ctx)); } int _gr_fq_zech_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Finite field (fq_zech)"); return GR_SUCCESS; } void _gr_fq_zech_init(fq_zech_t x, const gr_ctx_t ctx) { fq_zech_init(x, FQ_CTX(ctx)); } void _gr_fq_zech_clear(fq_zech_t x, const gr_ctx_t ctx) { fq_zech_clear(x, FQ_CTX(ctx)); } void _gr_fq_zech_swap(fq_zech_t x, fq_zech_t y, const gr_ctx_t ctx) { fq_zech_t t; *t = *x; *x = *y; *y = *t; } void _gr_fq_zech_set_shallow(fq_zech_t res, const fq_zech_t x, const gr_ctx_t ctx) { *res = *x; } int _gr_fq_zech_randtest(fq_zech_t res, flint_rand_t state, const gr_ctx_t ctx) { fq_zech_randtest(res, state, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_write(gr_stream_t out, const fq_zech_t x, const gr_ctx_t ctx) { gr_stream_write_free(out, fq_zech_get_str_pretty(x, FQ_CTX(ctx))); return GR_SUCCESS; } int _gr_fq_zech_zero(fq_zech_t x, const gr_ctx_t ctx) { fq_zech_zero(x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_one(fq_zech_t x, const gr_ctx_t ctx) { fq_zech_one(x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_set_si(fq_zech_t res, slong v, const gr_ctx_t ctx) { fq_zech_set_si(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_set_ui(fq_zech_t res, ulong v, const gr_ctx_t ctx) { fq_zech_set_ui(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_set_fmpz(fq_zech_t res, const fmpz_t v, const gr_ctx_t ctx) { fq_zech_set_fmpz(res, v, FQ_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_fq_zech_is_zero(const fq_zech_t x, const gr_ctx_t ctx) { return fq_zech_is_zero(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fq_zech_is_one(const fq_zech_t x, const gr_ctx_t ctx) { return fq_zech_is_one(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_fq_zech_equal(const fq_zech_t x, const fq_zech_t y, const gr_ctx_t ctx) { return fq_zech_equal(x, y, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_zech_set(fq_zech_t res, const fq_zech_t x, const gr_ctx_t ctx) { fq_zech_set(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_neg(fq_zech_t res, const fq_zech_t x, const gr_ctx_t ctx) { fq_zech_neg(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_add(fq_zech_t res, const fq_zech_t x, const fq_zech_t y, const gr_ctx_t ctx) { fq_zech_add(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_sub(fq_zech_t res, const fq_zech_t x, const fq_zech_t y, const gr_ctx_t ctx) { fq_zech_sub(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_mul(fq_zech_t res, const fq_zech_t x, const fq_zech_t y, const gr_ctx_t ctx) { fq_zech_mul(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_mul_si(fq_zech_t res, const fq_zech_t x, slong y, const gr_ctx_t ctx) { fq_zech_mul_si(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_mul_ui(fq_zech_t res, const fq_zech_t x, ulong y, const gr_ctx_t ctx) { fq_zech_mul_ui(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_mul_fmpz(fq_zech_t res, const fq_zech_t x, const fmpz_t y, const gr_ctx_t ctx) { fq_zech_mul_fmpz(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_inv(fq_zech_t res, const fq_zech_t x, const gr_ctx_t ctx) { if (fq_zech_is_zero(x, FQ_CTX(ctx))) { return GR_DOMAIN; } else { fq_zech_inv(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } } int _gr_fq_zech_div(fq_zech_t res, const fq_zech_t x, const fq_zech_t y, const gr_ctx_t ctx) { if (fq_zech_is_zero(y, FQ_CTX(ctx))) { return GR_DOMAIN; } else { fq_zech_t t; fq_zech_init(t, FQ_CTX(ctx)); fq_zech_inv(t, y, FQ_CTX(ctx)); fq_zech_mul(res, x, t, FQ_CTX(ctx)); fq_zech_clear(t, FQ_CTX(ctx)); return GR_SUCCESS; } } int _gr_fq_zech_sqr(fq_zech_t res, const fq_zech_t x, const gr_ctx_t ctx) { fq_zech_sqr(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_pow_ui(fq_zech_t res, const fq_zech_t x, ulong y, const gr_ctx_t ctx) { fq_zech_pow_ui(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_pow_fmpz(fq_zech_t res, const fq_zech_t x, const fmpz_t y, gr_ctx_t ctx) { if (fmpz_sgn(y) < 0) { return gr_generic_pow_fmpz(res, x, y, ctx); } else { fq_zech_pow(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } } truth_t _gr_fq_zech_is_invertible(const fq_zech_t x, const gr_ctx_t ctx) { return (!fq_zech_is_zero(x, FQ_CTX(ctx))) ? T_TRUE : T_FALSE; } truth_t _gr_fq_zech_is_square(const fq_zech_t x, const gr_ctx_t ctx) { return fq_zech_is_square(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_zech_sqrt(fq_zech_t res, const fq_zech_t x, const gr_ctx_t ctx) { if (fq_zech_sqrt(res, x, FQ_CTX(ctx))) { return GR_SUCCESS; } else { return GR_DOMAIN; } } int _gr_ctx_fq_zech_prime(ulong * p, gr_ctx_t ctx) { *p = fq_zech_ctx_prime(FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_ctx_fq_zech_degree(slong * deg, gr_ctx_t ctx) { *deg = fq_zech_ctx_degree(FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_ctx_fq_zech_order(ulong * q, gr_ctx_t ctx) { *q = fq_zech_ctx_order_ui(FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_gen(gr_ptr res, gr_ctx_t ctx) { fq_zech_gen(res, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_frobenius(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx) { fq_zech_frobenius(res, x, e, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_multiplicative_order(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { int ret; ret = fq_zech_multiplicative_order(res, x, FQ_CTX(ctx)); if (ret == 1) return GR_SUCCESS; /* todo: better solution? */ return GR_DOMAIN; } int _gr_fq_zech_norm(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { fq_zech_norm(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_trace(fmpz_t res, gr_srcptr x, gr_ctx_t ctx) { fq_zech_trace(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_fq_zech_is_primitive(gr_srcptr x, gr_ctx_t ctx) { return fq_zech_is_primitive(x, FQ_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_fq_zech_pth_root(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { fq_zech_pth_root(res, x, FQ_CTX(ctx)); return GR_SUCCESS; } void _gr_fq_zech_vec_init(fq_zech_struct * vec, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) fq_zech_init(vec + i, FQ_CTX(ctx)); } void _gr_fq_zech_vec_clear(fq_zech_struct * vec, slong len, gr_ctx_t ctx) { } void _gr_fq_zech_vec_swap(fq_zech_struct * vec1, fq_zech_struct * vec2, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) fq_zech_swap(vec1 + i, vec2 + i, FQ_CTX(ctx)); } int _gr_fq_zech_vec_set(fq_zech_struct * res, const fq_zech_struct * vec, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) res[i] = vec[i]; return GR_SUCCESS; } int _gr_fq_zech_vec_normalise(slong * res, const fq_zech_struct * vec, slong len, gr_ctx_t ctx) { while (len > 0 && fq_zech_is_zero(vec + len - 1, FQ_CTX(ctx))) len--; res[0] = len; return GR_SUCCESS; } slong _gr_fq_zech_vec_normalise_weak(const fq_zech_struct * vec, slong len, gr_ctx_t ctx) { while (len > 0 && fq_zech_is_zero(vec + len - 1, FQ_CTX(ctx))) len--; return len; } int _gr_fq_zech_vec_mul_scalar(fq_zech_struct * res, const fq_zech_struct * vec, slong len, const fq_zech_t x, gr_ctx_t ctx) { _fq_zech_vec_scalar_mul_fq_zech(res, vec, len, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_vec_addmul_scalar(fq_zech_struct * res, const fq_zech_struct * vec, slong len, const fq_zech_t x, gr_ctx_t ctx) { /* the poly method checks for special cases. worth it? */ _fq_zech_poly_scalar_addmul_fq_zech(res, vec, len, x, FQ_CTX(ctx)); return GR_SUCCESS; } int _gr_fq_zech_vec_submul_scalar(fq_zech_struct * res, const fq_zech_struct * vec, slong len, const fq_zech_t x, gr_ctx_t ctx) { /* the poly method checks for special cases. worth it? */ _fq_zech_poly_scalar_submul_fq_zech(res, vec, len, x, FQ_CTX(ctx)); return GR_SUCCESS; } /* todo: _fq_zech_poly_mullow should do the right thing */ int _gr_fq_zech_poly_mullow(fq_zech_struct * res, const fq_zech_struct * poly1, slong len1, const fq_zech_struct * poly2, slong len2, slong n, gr_ctx_t ctx) { if (len1 + len2 - 1 == n) { if (poly1 == poly2 && len1 == len2) _fq_zech_poly_sqr(res, poly1, len1, FQ_CTX(ctx)); else if (len1 >= len2) _fq_zech_poly_mul(res, poly1, len1, poly2, len2, FQ_CTX(ctx)); else _fq_zech_poly_mul(res, poly2, len2, poly1, len1, FQ_CTX(ctx)); } else { if (len1 >= len2) _fq_zech_poly_mullow(res, poly1, len1, poly2, len2, n, FQ_CTX(ctx)); else _fq_zech_poly_mullow(res, poly2, len2, poly1, len1, n, FQ_CTX(ctx)); } return GR_SUCCESS; } /* todo: also need the _other version ... ? */ /* todo: implement generically */ int _gr_fq_zech_roots_gr_poly(gr_vec_t roots, gr_vec_t mult, const fq_zech_poly_t poly, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; { gr_ctx_t ZZ; fq_zech_poly_factor_t fac; slong i, num; gr_ctx_init_fmpz(ZZ); fq_zech_poly_factor_init(fac, FQ_CTX(ctx)); fq_zech_poly_roots(fac, poly, 1, FQ_CTX(ctx)); num = fac->num; gr_vec_set_length(roots, num, ctx); gr_vec_set_length(mult, num, ZZ); for (i = 0; i < num; i++) { fq_zech_neg(gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs, FQ_CTX(ctx)); /* work around flint bug: factors can be non-monic */ if (!fq_zech_is_one(fac->poly[i].coeffs + 1, FQ_CTX(ctx))) fq_zech_div(gr_vec_entry_ptr(roots, i, ctx), gr_vec_entry_ptr(roots, i, ctx), fac->poly[i].coeffs + 1, FQ_CTX(ctx)); fmpz_set_ui(((fmpz *) mult->entries) + i, fac->exp[i]); } fq_zech_poly_factor_clear(fac, FQ_CTX(ctx)); gr_ctx_clear(ZZ); } return GR_SUCCESS; } int _gr_fq_zech_mat_mul(fq_zech_mat_t res, const fq_zech_mat_t x, const fq_zech_mat_t y, gr_ctx_t ctx) { fq_zech_mat_mul(res, x, y, FQ_CTX(ctx)); return GR_SUCCESS; } int _fq_zech_methods_initialized = 0; gr_static_method_table _fq_zech_methods; gr_method_tab_input _fq_zech_methods_input[] = { {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_fq_zech_ctx_clear}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_fq_zech_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_fq_zech_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_fq_zech_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_fq_zech_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_fq_zech_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_fq_zech_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_fq_zech_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_fq_zech_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_fq_zech_one}, {GR_METHOD_GEN, (gr_funcptr) _gr_fq_zech_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_fq_zech_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_fq_zech_is_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_fq_zech_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_fq_zech_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_fq_zech_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_fq_zech_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_fq_zech_set_fmpz}, {GR_METHOD_NEG, (gr_funcptr) _gr_fq_zech_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_fq_zech_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_fq_zech_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_fq_zech_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_fq_zech_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_fq_zech_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_fq_zech_mul_fmpz}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_fq_zech_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_fq_zech_inv}, {GR_METHOD_DIV, (gr_funcptr) _gr_fq_zech_div}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fq_zech_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fq_zech_sqrt}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_fq_zech_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_fq_zech_sqrt}, {GR_METHOD_CTX_FQ_PRIME, (gr_funcptr) _gr_ctx_fq_zech_prime}, {GR_METHOD_CTX_FQ_DEGREE, (gr_funcptr) _gr_ctx_fq_zech_degree}, {GR_METHOD_CTX_FQ_ORDER, (gr_funcptr) _gr_ctx_fq_zech_order}, {GR_METHOD_FQ_FROBENIUS, (gr_funcptr) _gr_fq_zech_frobenius}, {GR_METHOD_FQ_MULTIPLICATIVE_ORDER, (gr_funcptr) _gr_fq_zech_multiplicative_order}, {GR_METHOD_FQ_NORM, (gr_funcptr) _gr_fq_zech_norm}, {GR_METHOD_FQ_TRACE, (gr_funcptr) _gr_fq_zech_trace}, {GR_METHOD_FQ_IS_PRIMITIVE, (gr_funcptr) _gr_fq_zech_is_primitive}, {GR_METHOD_FQ_PTH_ROOT, (gr_funcptr) _gr_fq_zech_pth_root}, {GR_METHOD_VEC_INIT, (gr_funcptr) _gr_fq_zech_vec_init}, {GR_METHOD_VEC_CLEAR, (gr_funcptr) _gr_fq_zech_vec_clear}, {GR_METHOD_VEC_SET, (gr_funcptr) _gr_fq_zech_vec_set}, {GR_METHOD_VEC_SWAP, (gr_funcptr) _gr_fq_zech_vec_swap}, {GR_METHOD_VEC_NORMALISE, (gr_funcptr) _gr_fq_zech_vec_normalise}, {GR_METHOD_VEC_NORMALISE_WEAK, (gr_funcptr) _gr_fq_zech_vec_normalise_weak}, {GR_METHOD_VEC_MUL_SCALAR, (gr_funcptr) _gr_fq_zech_vec_mul_scalar}, {GR_METHOD_VEC_ADDMUL_SCALAR, (gr_funcptr) _gr_fq_zech_vec_addmul_scalar}, {GR_METHOD_VEC_SUBMUL_SCALAR, (gr_funcptr) _gr_fq_zech_vec_submul_scalar}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_fq_zech_poly_mullow}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_fq_zech_roots_gr_poly}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_fq_zech_mat_mul}, {0, (gr_funcptr) NULL}, }; void _gr_ctx_init_fq_zech_from_ref(gr_ctx_t ctx, const void * fq_zech_ctx) { ctx->which_ring = GR_CTX_FQ_ZECH; ctx->sizeof_elem = sizeof(fq_zech_struct); GR_CTX_DATA_AS_PTR(ctx) = (fq_zech_ctx_struct *) fq_zech_ctx; ctx->size_limit = WORD_MAX; ctx->methods = _fq_zech_methods; if (!_fq_zech_methods_initialized) { gr_method_tab_init(_fq_zech_methods, _fq_zech_methods_input); _fq_zech_methods_initialized = 1; } } void gr_ctx_init_fq_zech(gr_ctx_t ctx, ulong p, slong d, const char * var) { fq_zech_ctx_struct * fq_zech_ctx; fq_zech_ctx = flint_malloc(sizeof(fq_zech_ctx_struct)); fq_zech_ctx_init_ui(fq_zech_ctx, p, d, var == NULL ? "a" : var); _gr_ctx_init_fq_zech_from_ref(ctx, fq_zech_ctx); } int gr_ctx_init_fq_zech_modulus_nmod_poly(gr_ctx_t ctx, const nmod_poly_t modulus, const char * var) { fq_zech_ctx_struct * fq_zech_ctx; fq_nmod_ctx_struct * fq_nmod_ctx; fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); fq_zech_ctx = flint_malloc(sizeof(fq_zech_ctx_struct)); fq_nmod_ctx_init_modulus(fq_nmod_ctx, modulus, var == NULL ? "a" : var); if (fq_zech_ctx_init_fq_nmod_ctx_check(fq_zech_ctx, fq_nmod_ctx)) { fq_zech_ctx->owns_fq_nmod_ctx = 1; _gr_ctx_init_fq_zech_from_ref(ctx, fq_zech_ctx); return GR_SUCCESS; } else { fq_nmod_ctx_clear(fq_nmod_ctx); flint_free(fq_nmod_ctx); return GR_DOMAIN; } } int gr_ctx_init_fq_zech_modulus_fmpz_mod_poly(gr_ctx_t ctx, const fmpz_mod_poly_t modulus, fmpz_mod_ctx_t mod_ctx, const char * var) { nmod_poly_t nmodulus; int status; if (!fmpz_abs_fits_ui(mod_ctx->n)) return GR_UNABLE; nmod_poly_init(nmodulus, fmpz_get_ui(mod_ctx->n)); fmpz_mod_poly_get_nmod_poly(nmodulus, modulus); status = gr_ctx_init_fq_zech_modulus_nmod_poly(ctx, nmodulus, var); nmod_poly_clear(nmodulus); return status; } flint-3.1.3/src/gr/init_random.c000066400000000000000000000140721461254215100165050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" #include "long_extras.h" #include "mpoly.h" #include "gr.h" /* For random composite rings, some base rings that don't require memory allocation. */ static gr_ctx_struct _gr_some_base_rings[11]; static gr_ctx_struct * _gr_random_base_ring(flint_rand_t state) { gr_ctx_init_fmpz(_gr_some_base_rings + 0); gr_ctx_init_nmod(_gr_some_base_rings + 1, 1); gr_ctx_init_nmod(_gr_some_base_rings + 2, 2); gr_ctx_init_nmod(_gr_some_base_rings + 3, 11); gr_ctx_init_nmod(_gr_some_base_rings + 4, 12); gr_ctx_init_nmod(_gr_some_base_rings + 5, 257); gr_ctx_init_fmpq(_gr_some_base_rings + 6); gr_ctx_init_real_arb(_gr_some_base_rings + 7, 64); gr_ctx_init_real_arb(_gr_some_base_rings + 8, 256); gr_ctx_init_complex_acb(_gr_some_base_rings + 9, 64); gr_ctx_init_complex_acb(_gr_some_base_rings + 10, 256); return _gr_some_base_rings + n_randint(state, sizeof(_gr_some_base_rings) / sizeof(gr_ctx_struct)); } void gr_ctx_init_random_ring_composite(gr_ctx_t ctx, flint_rand_t state) { gr_ctx_struct * base_ring = _gr_random_base_ring(state); switch (n_randint(state, 5)) { case 0: gr_ctx_init_gr_poly(ctx, base_ring); break; case 1: gr_ctx_init_gr_mpoly(ctx, base_ring, n_randint(state, 3), mpoly_ordering_randtest(state)); break; case 2: gr_ctx_init_gr_poly(ctx, base_ring); /* this currently breaks some tests gr_ctx_init_gr_series(ctx, base_ring, n_randint(state, 6)); */ break; case 3: gr_ctx_init_gr_poly(ctx, base_ring); /* this currently breaks some tests gr_ctx_init_gr_series_mod(ctx, base_ring, n_randint(state, 6)); break; */ case 4: gr_ctx_init_vector_space_gr_vec(ctx, base_ring, n_randint(state, 4)); break; /* this will break tests that currently assume commutativity case 5: gr_ctx_init_matrix_ring(ctx, base_ring, n_randint(state, 4)); break; */ } } void gr_ctx_init_random_ring_integers_mod(gr_ctx_t ctx, flint_rand_t state) { fmpz_t t; switch (n_randint(state, 4)) { case 0: gr_ctx_init_nmod8(ctx, n_randtest(state) % 255 + 1); break; case 1: gr_ctx_init_nmod32(ctx, n_randtest(state) % UWORD(4294967295) + 1); break; case 2: gr_ctx_init_nmod(ctx, n_randtest_not_zero(state)); break; case 3: fmpz_init(t); fmpz_randtest_not_zero(t, state, 100); fmpz_abs(t, t); gr_ctx_init_fmpz_mod(ctx, t); fmpz_clear(t); break; } } void gr_ctx_init_random_ring_finite_field(gr_ctx_t ctx, flint_rand_t state) { fmpz_t t; fmpz_init(t); switch (n_randint(state, 3)) { case 0: gr_ctx_init_fq_nmod(ctx, n_randtest_prime(state, 0), 1 + n_randint(state, 4), NULL); break; case 1: gr_ctx_init_fq_zech(ctx, n_randprime(state, 4, 0), 1 + n_randint(state, 3), NULL); break; case 2: fmpz_randprime(t, state, 2 + n_randint(state, 100), 0); gr_ctx_init_fq(ctx, t, 1 + n_randint(state, 4), NULL); break; } fmpz_clear(t); } void gr_ctx_init_random_ring_number_field(gr_ctx_t ctx, flint_rand_t state) { fmpz_poly_t g; fmpq_poly_t f; fmpz_poly_init(g); fmpq_poly_init(f); do { fmpz_poly_randtest_irreducible(g, state, 2 + n_randint(state, 5), 1 + n_randint(state, 10)); } while (g->length < 2); fmpq_poly_set_fmpz_poly(f, g); fmpq_poly_scalar_div_ui(f, f, 1 + n_randtest(state) % 256); gr_ctx_init_nf(ctx, f); fmpz_poly_clear(g); fmpq_poly_clear(f); } void gr_ctx_init_random_ring_real_complex_ball(gr_ctx_t ctx, flint_rand_t state) { if (n_randint(state, 2)) gr_ctx_init_real_arb(ctx, 2 + n_randint(state, 200)); else gr_ctx_init_complex_acb(ctx, 2 + n_randint(state, 200)); } void gr_ctx_init_random_ring_real_complex_exact(gr_ctx_t ctx, flint_rand_t state) { switch (n_randint(state, 4)) { case 0: gr_ctx_init_real_ca(ctx); break; case 1: gr_ctx_init_complex_ca(ctx); break; case 2: gr_ctx_init_real_algebraic_ca(ctx); break; case 3: gr_ctx_init_complex_algebraic_ca(ctx); break; /* slow -- we'll want to enable these selectively case 4: gr_ctx_init_real_qqbar(ctx); break; case 5: gr_ctx_init_complex_qqbar(ctx); break; */ } } void gr_ctx_init_random(gr_ctx_t ctx, flint_rand_t state) { switch (n_randint(state, 11)) { case 0: case 1: case 2: gr_ctx_init_fmpz(ctx); break; case 3: gr_ctx_init_fmpq(ctx); break; case 4: gr_ctx_init_fmpzi(ctx); break; case 5: gr_ctx_init_random_ring_integers_mod(ctx, state); break; case 6: gr_ctx_init_random_ring_finite_field(ctx, state); break; case 7: gr_ctx_init_random_ring_number_field(ctx, state); break; case 8: gr_ctx_init_random_ring_real_complex_ball(ctx, state); break; case 9: gr_ctx_init_random_ring_real_complex_exact(ctx, state); break; case 10: gr_ctx_init_random_ring_composite(ctx, state); break; } /* flint_printf(" "); gr_ctx_println(ctx); */ } flint-3.1.3/src/gr/inlines.c000066400000000000000000000007131461254215100156400ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define GR_INLINES_C #include "fexpr.h" #include "gr.h" #undef GR_INLINES_C flint-3.1.3/src/gr/io.c000066400000000000000000000063541461254215100146150ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "gr.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy # define strlen __builtin_strlen #else # include #endif /* todo: error handling */ void gr_stream_init_file(gr_stream_t out, FILE * fp) { out->fp = (FLINT_FILE *) fp; out->s = NULL; } void gr_stream_init_str(gr_stream_t out) { out->fp = NULL; out->s = flint_malloc(16); out->s[0] = '\0'; out->len = 0; out->alloc = 16; } void gr_stream_write(gr_stream_t out, const char * s) { if (out->fp != NULL) { fprintf((FILE *) out->fp, "%s", s); } else { slong len, alloc; len = strlen(s); alloc = out->len + len + 1; if (alloc > out->alloc) { alloc = FLINT_MAX(alloc, out->alloc * 2); out->s = flint_realloc(out->s, alloc); out->alloc = alloc; } memcpy(out->s + out->len, s, len + 1); out->len += len; } } void gr_stream_write_si(gr_stream_t out, slong x) { if (out->fp != NULL) { flint_fprintf((FILE *) out->fp, "%wd", x); } else { char tmp[22]; sprintf(tmp, WORD_FMT "d", x); gr_stream_write(out, tmp); } } void gr_stream_write_ui(gr_stream_t out, ulong x) { if (out->fp != NULL) { flint_fprintf((FILE *) out->fp, "%wu", x); } else { char tmp[22]; sprintf(tmp, WORD_FMT "u", x); gr_stream_write(out, tmp); } } void gr_stream_write_free(gr_stream_t out, char * s) { gr_stream_write(out, s); flint_free(s); } void gr_stream_write_fmpz(gr_stream_t out, const fmpz_t x) { gr_stream_write_free(out, fmpz_get_str(NULL, 10, x)); } int gr_ctx_print(gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); gr_ctx_write(out, ctx); return GR_SUCCESS; } int gr_ctx_println(gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); gr_ctx_write(out, ctx); gr_stream_write(out, "\n"); return GR_SUCCESS; } int gr_print(gr_srcptr x, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); gr_write(out, x, ctx); return GR_SUCCESS; } int gr_println(gr_srcptr x, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); gr_write(out, x, ctx); gr_stream_write(out, "\n"); return GR_SUCCESS; } int gr_ctx_get_str(char ** s, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_str(out); gr_ctx_write(out, ctx); *s = out->s; return GR_SUCCESS; } int gr_get_str(char ** s, gr_srcptr x, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_str(out); gr_write(out, x, ctx); *s = out->s; return GR_SUCCESS; } int gr_get_str_n(char ** s, gr_srcptr x, slong n, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_str(out); gr_write_n(out, x, n, ctx); *s = out->s; return GR_SUCCESS; } flint-3.1.3/src/gr/matrix.c000066400000000000000000000363631461254215100155150ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Matrices over generic rings */ #include "fmpz.h" #include "fmpq.h" #include "gr.h" #include "gr_mat.h" /* todo: for matrix "ring", verify that element domain is a ring */ /* todo: recycle storage? */ void _gr_mat_resize(gr_mat_t mat, slong r, slong c, gr_ctx_t ctx) { gr_mat_clear(mat, ctx); gr_mat_init(mat, r, c, ctx); } int _gr_mat_check_resize(gr_mat_t mat, slong r, slong c, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) { _gr_mat_resize(mat, r, c, MATRIX_CTX(ctx)->base_ring); return GR_SUCCESS; } else { if (r != MATRIX_CTX(ctx)->nrows || c != MATRIX_CTX(ctx)->ncols) return GR_DOMAIN; if (mat->r != r || mat->c != c) _gr_mat_resize(mat, r, c, MATRIX_CTX(ctx)->base_ring); return GR_SUCCESS; } } void matrix_init(gr_mat_t res, gr_ctx_t ctx) { gr_mat_init(res, MATRIX_CTX(ctx)->nrows, MATRIX_CTX(ctx)->ncols, MATRIX_CTX(ctx)->base_ring); } int matrix_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_ctx_ptr elem_ctx = MATRIX_CTX(ctx)->base_ring; if (MATRIX_CTX(ctx)->all_sizes) { gr_stream_write(out, "Matrices (any shape) over "); } else { if (gr_ctx_is_ring(ctx) == T_TRUE) gr_stream_write(out, "Ring of "); else gr_stream_write(out, "Space of "); gr_stream_write_si(out, MATRIX_CTX(ctx)->nrows); gr_stream_write(out, " x "); gr_stream_write_si(out, MATRIX_CTX(ctx)->ncols); gr_stream_write(out, " "); gr_stream_write(out, "matrices over "); } gr_ctx_write(out, elem_ctx); return GR_SUCCESS; } truth_t matrix_ctx_is_ring(gr_ctx_t ctx) { int shape_ok = (!MATRIX_CTX(ctx)->all_sizes && MATRIX_CTX(ctx)->nrows == MATRIX_CTX(ctx)->ncols); if (!shape_ok) return T_FALSE; if (MATRIX_CTX(ctx)->nrows == 0) return T_TRUE; return gr_ctx_is_ring(MATRIX_CTX(ctx)->base_ring); } truth_t matrix_ctx_is_commutative_ring(gr_ctx_t ctx) { int shape_ok = (!MATRIX_CTX(ctx)->all_sizes && MATRIX_CTX(ctx)->nrows == MATRIX_CTX(ctx)->ncols); if (!shape_ok) return T_FALSE; if (MATRIX_CTX(ctx)->nrows == 0) return T_TRUE; if (MATRIX_CTX(ctx)->nrows == 1) return gr_ctx_is_commutative_ring(MATRIX_CTX(ctx)->base_ring); return gr_ctx_is_zero_ring(MATRIX_CTX(ctx)->base_ring); } /* todo: public */ truth_t gr_ctx_matrix_is_fixed_size(gr_ctx_t ctx) { return (MATRIX_CTX(ctx)->all_sizes) ? T_FALSE : T_TRUE; } truth_t matrix_ctx_is_threadsafe(gr_ctx_t ctx) { return gr_ctx_is_threadsafe(MATRIX_CTX(ctx)->base_ring); } void matrix_clear(gr_mat_t res, gr_ctx_t ctx) { gr_mat_clear(res, MATRIX_CTX(ctx)->base_ring); } void matrix_swap(gr_mat_t mat1, gr_mat_t mat2, gr_ctx_t ctx) { gr_mat_swap(mat1, mat2, MATRIX_CTX(ctx)->base_ring); } void matrix_set_shallow(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { *res = *mat; } int matrix_write(gr_stream_t out, gr_mat_t mat, gr_ctx_t ctx) { return gr_mat_write(out, mat, MATRIX_CTX(ctx)->base_ring); } int matrix_randtest(gr_mat_t res, flint_rand_t state, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) _gr_mat_resize(res, n_randint(state, 7), n_randint(state, 7), MATRIX_CTX(ctx)->base_ring); return gr_mat_randtest(res, state, MATRIX_CTX(ctx)->base_ring); } truth_t matrix_equal(const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { return gr_mat_equal(mat1, mat2, MATRIX_CTX(ctx)->base_ring); } int matrix_set(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { if (res->r != mat->r || res->c != mat->c) _gr_mat_resize(res, mat->r, mat->c, MATRIX_CTX(ctx)->base_ring); return gr_mat_set(res, mat, MATRIX_CTX(ctx)->base_ring); } int matrix_set_si(gr_mat_t res, slong v, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) return GR_DOMAIN; return gr_mat_set_si(res, v, MATRIX_CTX(ctx)->base_ring); } int matrix_set_ui(gr_mat_t res, ulong v, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) return GR_DOMAIN; return gr_mat_set_ui(res, v, MATRIX_CTX(ctx)->base_ring); } int matrix_set_fmpz(gr_mat_t res, const fmpz_t v, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) return GR_DOMAIN; return gr_mat_set_fmpz(res, v, MATRIX_CTX(ctx)->base_ring); } int matrix_set_fmpq(gr_mat_t res, const fmpq_t v, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) return GR_DOMAIN; return gr_mat_set_fmpq(res, v, MATRIX_CTX(ctx)->base_ring); } int matrix_set_other(gr_mat_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { if (x_ctx == ctx) { return matrix_set(res, x, ctx); } else if (x_ctx == MATRIX_CTX(ctx)->base_ring) { if (MATRIX_CTX(ctx)->all_sizes) return GR_DOMAIN; return gr_mat_set_scalar(res, x, x_ctx); } else if (x_ctx->which_ring == GR_CTX_GR_MAT) { const gr_mat_struct * xmat = x; slong i, j; int status; slong sz, xsz; if (res->r != xmat->r || res->c != xmat->c) { if (MATRIX_CTX(ctx)->all_sizes) _gr_mat_resize(res, xmat->r, xmat->c, MATRIX_CTX(ctx)->base_ring); else return GR_DOMAIN; } sz = MATRIX_CTX(ctx)->base_ring->sizeof_elem; xsz = MATRIX_CTX(x_ctx)->base_ring->sizeof_elem; for (i = 0; i < xmat->r; i++) { for (j = 0; j < xmat->c; j++) { status = gr_set_other(GR_MAT_ENTRY(res, i, j, sz), GR_MAT_ENTRY(xmat, i, j, xsz), MATRIX_CTX(x_ctx)->base_ring, MATRIX_CTX(ctx)->base_ring); if (status != GR_SUCCESS) return status; } } return GR_SUCCESS; } else { int status = GR_SUCCESS; gr_ptr tmp; if (MATRIX_CTX(ctx)->all_sizes) return GR_UNABLE; GR_TMP_INIT(tmp, MATRIX_CTX(ctx)->base_ring); status = gr_set_other(tmp, x, x_ctx, MATRIX_CTX(ctx)->base_ring); if (status == GR_SUCCESS) status = gr_mat_set_scalar(res, tmp, MATRIX_CTX(ctx)->base_ring); GR_TMP_CLEAR(tmp, MATRIX_CTX(ctx)->base_ring); return status; } } int matrix_zero(gr_mat_t res, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) return GR_DOMAIN; return gr_mat_zero(res, MATRIX_CTX(ctx)->base_ring); } int matrix_one(gr_mat_t res, gr_ctx_t ctx) { if (MATRIX_CTX(ctx)->all_sizes) return GR_DOMAIN; return gr_mat_one(res, MATRIX_CTX(ctx)->base_ring); } truth_t matrix_is_zero(const gr_mat_t mat, gr_ctx_t ctx) { return gr_mat_is_zero(mat, MATRIX_CTX(ctx)->base_ring); } truth_t matrix_is_one(const gr_mat_t mat, gr_ctx_t ctx) { return gr_mat_is_one(mat, MATRIX_CTX(ctx)->base_ring); } truth_t matrix_is_neg_one(const gr_mat_t mat, gr_ctx_t ctx) { return gr_mat_is_neg_one(mat, MATRIX_CTX(ctx)->base_ring); } int matrix_neg(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { if (res->r != mat->r || res->c != mat->c) _gr_mat_resize(res, mat->r, mat->c, MATRIX_CTX(ctx)->base_ring); return gr_mat_neg(res, mat, MATRIX_CTX(ctx)->base_ring); } int matrix_add(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { if (mat1->r != mat2->r || mat1->c != mat2->c) return GR_DOMAIN; if (res->r != mat1->r || res->c != mat1->c) _gr_mat_resize(res, mat1->r, mat1->c, MATRIX_CTX(ctx)->base_ring); return gr_mat_add(res, mat1, mat2, MATRIX_CTX(ctx)->base_ring); } int matrix_sub(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { if (mat1->r != mat2->r || mat1->c != mat2->c) return GR_DOMAIN; if (res->r != mat1->r || res->c != mat1->c) _gr_mat_resize(res, mat1->r, mat1->c, MATRIX_CTX(ctx)->base_ring); return gr_mat_sub(res, mat1, mat2, MATRIX_CTX(ctx)->base_ring); } int matrix_mul(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { if (mat1->c != mat2->r) return GR_DOMAIN; if (res->r != mat1->r || res->c != mat2->c) { if (res == mat1 || res == mat2) { int status; gr_mat_t tmp; gr_mat_init(tmp, mat1->r, mat2->c, MATRIX_CTX(ctx)->base_ring); status = matrix_mul(tmp, mat1, mat2, ctx); gr_mat_swap(res, tmp, MATRIX_CTX(ctx)->base_ring); gr_mat_clear(tmp, MATRIX_CTX(ctx)->base_ring); return status; } else { _gr_mat_resize(res, mat1->r, mat2->c, MATRIX_CTX(ctx)->base_ring); } } return gr_mat_mul_classical(res, mat1, mat2, MATRIX_CTX(ctx)->base_ring); } /* todo: fmpz etc */ int matrix_mul_other(gr_mat_t res, const gr_mat_t mat, gr_ptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { if (y_ctx == ctx) { return matrix_mul(res, mat, y, ctx); } else if (y_ctx == MATRIX_CTX(ctx)->base_ring) { int status = GR_SUCCESS; if (res->r != mat->r || res->c != mat->c) status = _gr_mat_check_resize(res, mat->r, mat->c, ctx); if (status != GR_SUCCESS) return status; /* todo: resizing */ return gr_mat_mul_scalar(res, mat, y, y_ctx); } else if (y_ctx->which_ring == GR_CTX_GR_MAT) { int status; gr_mat_t tmp; gr_mat_init(tmp, ((gr_mat_struct *) y)->r, ((gr_mat_struct *) y)->c, MATRIX_CTX(ctx)->base_ring); status = matrix_set_other(tmp, y, y_ctx, ctx); if (status == GR_SUCCESS) { status = matrix_mul(res, mat, tmp, ctx); } gr_mat_clear(tmp, MATRIX_CTX(ctx)->base_ring); return status; } else { int status; gr_ptr c; GR_TMP_INIT(c, MATRIX_CTX(ctx)->base_ring); status = gr_set_other(c, y, y_ctx, MATRIX_CTX(ctx)->base_ring); if (status == GR_SUCCESS) { if (res->r != mat->r || res->c != mat->c) status = _gr_mat_check_resize(res, mat->r, mat->c, ctx); if (status == GR_SUCCESS) status = gr_mat_mul_scalar(res, mat, c, MATRIX_CTX(ctx)->base_ring); } GR_TMP_CLEAR(c, MATRIX_CTX(ctx)->base_ring); return status; } return GR_UNABLE; } /* todo: fmpz etc */ int matrix_div_other(gr_mat_t res, const gr_mat_t mat, gr_ptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { /* todo: matrix-matrix division ? */ if (y_ctx == MATRIX_CTX(ctx)->base_ring) { int status = GR_SUCCESS; if (res->r != mat->r || res->c != mat->c) status = _gr_mat_check_resize(res, mat->r, mat->c, ctx); if (status != GR_SUCCESS) return status; return gr_mat_div_scalar(res, mat, y, y_ctx); } else { int status; gr_ptr c; GR_TMP_INIT(c, MATRIX_CTX(ctx)->base_ring); status = gr_set_other(c, y, y_ctx, MATRIX_CTX(ctx)->base_ring); if (status == GR_SUCCESS) { if (res->r != mat->r || res->c != mat->c) status = _gr_mat_check_resize(res, mat->r, mat->c, ctx); if (status == GR_SUCCESS) status = gr_mat_div_scalar(res, mat, c, MATRIX_CTX(ctx)->base_ring); } GR_TMP_CLEAR(c, MATRIX_CTX(ctx)->base_ring); return status; } return GR_UNABLE; } int matrix_inv(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { if (mat->r != mat->c) return GR_DOMAIN; if (res->r != mat->r || res->c != mat->c) _gr_mat_resize(res, mat->r, mat->r, MATRIX_CTX(ctx)->base_ring); return gr_mat_inv(res, mat, MATRIX_CTX(ctx)->base_ring); } int matrix_exp(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { if (res->r != mat->r || res->c != mat->c) _gr_mat_resize(res, mat->r, mat->c, MATRIX_CTX(ctx)->base_ring); return gr_mat_exp(res, mat, MATRIX_CTX(ctx)->base_ring); } int matrix_log(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { if (res->r != mat->r || res->c != mat->c) _gr_mat_resize(res, mat->r, mat->c, MATRIX_CTX(ctx)->base_ring); return gr_mat_log(res, mat, MATRIX_CTX(ctx)->base_ring); } int _gr_mat_methods_initialized = 0; gr_static_method_table _gr_mat_methods; gr_method_tab_input _gr_mat_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) matrix_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) matrix_ctx_is_ring}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) matrix_ctx_is_commutative_ring}, {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) matrix_ctx_is_threadsafe}, {GR_METHOD_INIT, (gr_funcptr) matrix_init}, {GR_METHOD_CLEAR, (gr_funcptr) matrix_clear}, {GR_METHOD_SWAP, (gr_funcptr) matrix_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) matrix_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) matrix_randtest}, {GR_METHOD_WRITE, (gr_funcptr) matrix_write}, {GR_METHOD_ZERO, (gr_funcptr) matrix_zero}, {GR_METHOD_ONE, (gr_funcptr) matrix_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) matrix_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) matrix_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) matrix_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) matrix_equal}, {GR_METHOD_SET, (gr_funcptr) matrix_set}, {GR_METHOD_SET_UI, (gr_funcptr) matrix_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) matrix_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) matrix_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) matrix_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) matrix_set_other}, {GR_METHOD_NEG, (gr_funcptr) matrix_neg}, {GR_METHOD_ADD, (gr_funcptr) matrix_add}, {GR_METHOD_SUB, (gr_funcptr) matrix_sub}, {GR_METHOD_MUL, (gr_funcptr) matrix_mul}, {GR_METHOD_MUL_OTHER, (gr_funcptr) matrix_mul_other}, {GR_METHOD_DIV_OTHER, (gr_funcptr) matrix_div_other}, {GR_METHOD_INV, (gr_funcptr) matrix_inv}, {GR_METHOD_EXP, (gr_funcptr) matrix_exp}, {GR_METHOD_LOG, (gr_funcptr) matrix_log}, {0, (gr_funcptr) NULL}, }; void _gr_ctx_init_matrix(gr_ctx_t ctx, gr_ctx_t base_ring, int all_sizes, slong nrows, slong ncols) { ctx->which_ring = GR_CTX_GR_MAT; ctx->sizeof_elem = sizeof(gr_mat_struct); ctx->size_limit = WORD_MAX; if (nrows < 0 || ncols < 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); MATRIX_CTX(ctx)->base_ring = (gr_ctx_struct *) base_ring; MATRIX_CTX(ctx)->all_sizes = all_sizes; MATRIX_CTX(ctx)->nrows = nrows; MATRIX_CTX(ctx)->ncols = ncols; ctx->methods = _gr_mat_methods; if (!_gr_mat_methods_initialized) { gr_method_tab_init(_gr_mat_methods, _gr_mat_methods_input); _gr_mat_methods_initialized = 1; } } void gr_ctx_init_matrix_domain(gr_ctx_t ctx, gr_ctx_t base_ring) { _gr_ctx_init_matrix(ctx, base_ring, 1, 0, 0); } void gr_ctx_init_matrix_space(gr_ctx_t ctx, gr_ctx_t base_ring, slong nrows, slong ncols) { _gr_ctx_init_matrix(ctx, base_ring, 0, nrows, ncols); } flint-3.1.3/src/gr/mpoly.c000066400000000000000000000261201461254215100153370ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Multivariate polynomials over generic rings */ #include "gr.h" #include "gr_mpoly.h" #include "gr_generic.h" typedef struct { gr_ctx_struct * base_ring; mpoly_ctx_t mctx; char ** vars; } _gr_gr_mpoly_ctx_t; #define MPOLYNOMIAL_CTX(ring_ctx) ((_gr_gr_mpoly_ctx_t *)(GR_CTX_DATA_AS_PTR(ring_ctx))) #define MPOLYNOMIAL_ELEM_CTX(ring_ctx) (MPOLYNOMIAL_CTX(ring_ctx)->base_ring) #define MPOLYNOMIAL_MCTX(ring_ctx) (MPOLYNOMIAL_CTX(ring_ctx)->mctx) int _gr_gr_mpoly_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Ring of multivariate polynomials over "); gr_ctx_write(out, MPOLYNOMIAL_ELEM_CTX(ctx)); gr_stream_write(out, " in "); gr_stream_write_si(out, MPOLYNOMIAL_MCTX(ctx)->nvars); gr_stream_write(out, " variables"); if (MPOLYNOMIAL_MCTX(ctx)->ord == ORD_LEX) gr_stream_write(out, ", lex order"); else if (MPOLYNOMIAL_MCTX(ctx)->ord == ORD_DEGLEX) gr_stream_write(out, ", deglex order"); else if (MPOLYNOMIAL_MCTX(ctx)->ord == ORD_DEGREVLEX) gr_stream_write(out, ", degrevlex order"); return GR_SUCCESS; } void _gr_gr_mpoly_ctx_clear(gr_ctx_t ctx) { if (MPOLYNOMIAL_CTX(ctx)->vars != NULL) { slong i; for (i = 0; i < MPOLYNOMIAL_MCTX(ctx)->nvars; i++) flint_free(MPOLYNOMIAL_CTX(ctx)->vars[i]); flint_free(MPOLYNOMIAL_CTX(ctx)->vars); } mpoly_ctx_clear(MPOLYNOMIAL_MCTX(ctx)); flint_free(GR_CTX_DATA_AS_PTR(ctx)); } int _gr_gr_mpoly_ctx_set_gen_names(gr_ctx_t ctx, const char ** s) { slong i, nvars, len; nvars = MPOLYNOMIAL_MCTX(ctx)->nvars; if (MPOLYNOMIAL_CTX(ctx)->vars == NULL) { MPOLYNOMIAL_CTX(ctx)->vars = flint_malloc(nvars * sizeof(char *)); for (i = 0; i < nvars; i++) MPOLYNOMIAL_CTX(ctx)->vars[i] = NULL; } else { for (i = 0; i < nvars; i++) flint_free(MPOLYNOMIAL_CTX(ctx)->vars[i]); } for (i = 0; i < nvars; i++) { len = strlen(s[i]); MPOLYNOMIAL_CTX(ctx)->vars[i] = flint_realloc(MPOLYNOMIAL_CTX(ctx)->vars[i], len + 1); memcpy(MPOLYNOMIAL_CTX(ctx)->vars[i], s[i], len + 1); } return GR_SUCCESS; } truth_t _gr_gr_mpoly_ctx_is_commutative_ring(gr_ctx_t ctx) { return gr_ctx_is_commutative_ring(MPOLYNOMIAL_ELEM_CTX(ctx)); } truth_t _gr_gr_mpoly_ctx_is_integral_domain(gr_ctx_t ctx) { return gr_ctx_is_integral_domain(MPOLYNOMIAL_ELEM_CTX(ctx)); } truth_t _gr_gr_mpoly_ctx_is_field(gr_ctx_t ctx) { if (MPOLYNOMIAL_MCTX(ctx)->nvars == 0) return gr_ctx_is_field(MPOLYNOMIAL_ELEM_CTX(ctx)); return T_FALSE; } truth_t _gr_gr_mpoly_ctx_is_threadsafe(gr_ctx_t ctx) { return gr_ctx_is_threadsafe(MPOLYNOMIAL_ELEM_CTX(ctx)); } void _gr_gr_mpoly_init(gr_mpoly_t res, gr_ctx_t ctx) { gr_mpoly_init(res, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } void _gr_gr_mpoly_clear(gr_mpoly_t res, gr_ctx_t ctx) { gr_mpoly_clear(res, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } void _gr_gr_mpoly_swap(gr_mpoly_t poly1, gr_mpoly_t poly2, gr_ctx_t ctx) { gr_mpoly_swap(poly1, poly2, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } void _gr_gr_mpoly_set_shallow(gr_mpoly_t res, const gr_mpoly_t poly, gr_ctx_t ctx) { *res = *poly; } int _gr_gr_mpoly_randtest(gr_mpoly_t res, flint_rand_t state, gr_ctx_t ctx) { return gr_mpoly_randtest_bits(res, state, n_randint(state, 5), 1 + n_randint(state, 3), MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } slong _gr_gr_mpoly_length(const gr_mpoly_t x, gr_ctx_t ctx) { return x->length; } int _gr_gr_mpoly_write(gr_stream_t out, gr_mpoly_t poly, gr_ctx_t ctx) { return gr_mpoly_write_pretty(out, poly, (const char **) MPOLYNOMIAL_CTX(ctx)->vars, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } truth_t _gr_gr_mpoly_equal(const gr_mpoly_t poly1, const gr_mpoly_t poly2, gr_ctx_t ctx) { return gr_mpoly_equal(poly1, poly2, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } truth_t _gr_gr_mpoly_is_zero(const gr_mpoly_t poly, gr_ctx_t ctx) { return gr_mpoly_is_zero(poly, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } truth_t _gr_gr_mpoly_is_one(const gr_mpoly_t poly, gr_ctx_t ctx) { return gr_mpoly_is_one(poly, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_gens(gr_vec_t res, gr_ctx_t ctx) { slong i, n; int status = GR_SUCCESS; n = MPOLYNOMIAL_MCTX(ctx)->nvars; gr_vec_set_length(res, n, ctx); for (i = 0; i < n; i++) status |= gr_mpoly_gen(((gr_mpoly_struct *) res->entries) + i, i, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); return status; } int _gr_gr_mpoly_gens_recursive(gr_vec_t vec, gr_ctx_t ctx) { int status; gr_vec_t vec1; slong i, n, m; /* Get generators of the element ring */ gr_vec_init(vec1, 0, MPOLYNOMIAL_ELEM_CTX(ctx)); status = gr_gens_recursive(vec1, MPOLYNOMIAL_ELEM_CTX(ctx)); n = vec1->length; m = MPOLYNOMIAL_MCTX(ctx)->nvars; gr_vec_set_length(vec, n + m, ctx); /* Promote to polynomials */ for (i = 0; i < n; i++) { status |= gr_mpoly_set_scalar(gr_vec_entry_ptr(vec, i, ctx), gr_vec_entry_srcptr(vec1, i, MPOLYNOMIAL_ELEM_CTX(ctx)), MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } for (i = 0; i < m; i++) { status |= gr_mpoly_gen(((gr_mpoly_struct *) vec->entries) + n + i, i, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } gr_vec_clear(vec1, MPOLYNOMIAL_ELEM_CTX(ctx)); return status; } int _gr_gr_mpoly_zero(gr_mpoly_t res, gr_ctx_t ctx) { return gr_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_one(gr_mpoly_t res, gr_ctx_t ctx) { return gr_mpoly_one(res, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_set(gr_mpoly_t res, const gr_mpoly_t mat, gr_ctx_t ctx) { return gr_mpoly_set(res, mat, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_set_si(gr_mpoly_t res, slong v, gr_ctx_t ctx) { return gr_mpoly_set_si(res, v, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_set_ui(gr_mpoly_t res, ulong v, gr_ctx_t ctx) { return gr_mpoly_set_ui(res, v, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_set_fmpz(gr_mpoly_t res, const fmpz_t v, gr_ctx_t ctx) { return gr_mpoly_set_fmpz(res, v, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_set_fmpq(gr_mpoly_t res, const fmpq_t v, gr_ctx_t ctx) { return gr_mpoly_set_fmpq(res, v, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_neg(gr_mpoly_t res, const gr_mpoly_t mat, gr_ctx_t ctx) { return gr_mpoly_neg(res, mat, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_add(gr_mpoly_t res, const gr_mpoly_t poly1, const gr_mpoly_t poly2, gr_ctx_t ctx) { if (poly1->length + poly2->length > ctx->size_limit) return GR_UNABLE | gr_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); return gr_mpoly_add(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_sub(gr_mpoly_t res, const gr_mpoly_t poly1, const gr_mpoly_t poly2, gr_ctx_t ctx) { if (poly1->length + poly2->length > ctx->size_limit) return GR_UNABLE | gr_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); return gr_mpoly_sub(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr_gr_mpoly_mul(gr_mpoly_t res, const gr_mpoly_t poly1, const gr_mpoly_t poly2, gr_ctx_t ctx) { if (poly1->length * poly2->length > ctx->size_limit) return GR_UNABLE | gr_mpoly_zero(res, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); return gr_mpoly_mul(res, poly1, poly2, MPOLYNOMIAL_MCTX(ctx), MPOLYNOMIAL_ELEM_CTX(ctx)); } int _gr__gr_gr_mpoly_methods_initialized = 0; gr_static_method_table _gr__gr_gr_mpoly_methods; gr_method_tab_input _gr__gr_gr_mpoly_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_gr_mpoly_ctx_write}, {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_gr_mpoly_ctx_clear}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, /* todo: matrices over semirings? */ {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) _gr_gr_mpoly_ctx_is_commutative_ring}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) _gr_gr_mpoly_ctx_is_integral_domain}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) _gr_gr_mpoly_ctx_is_field}, {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) _gr_gr_mpoly_ctx_is_threadsafe}, {GR_METHOD_CTX_SET_GEN_NAMES, (gr_funcptr) _gr_gr_mpoly_ctx_set_gen_names}, {GR_METHOD_INIT, (gr_funcptr) _gr_gr_mpoly_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_gr_mpoly_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_gr_mpoly_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_gr_mpoly_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_gr_mpoly_randtest}, {_GR_METHOD_LENGTH, (gr_funcptr) _gr_gr_mpoly_length}, {GR_METHOD_WRITE, (gr_funcptr) _gr_gr_mpoly_write}, {GR_METHOD_GENS, (gr_funcptr) _gr_gr_mpoly_gens}, {GR_METHOD_GENS_RECURSIVE, (gr_funcptr) _gr_gr_mpoly_gens_recursive}, {GR_METHOD_ZERO, (gr_funcptr) _gr_gr_mpoly_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_gr_mpoly_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_gr_mpoly_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_gr_mpoly_is_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_gr_mpoly_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_gr_mpoly_set}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_gr_mpoly_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_gr_mpoly_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_gr_mpoly_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_gr_mpoly_set_fmpq}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions}, {GR_METHOD_NEG, (gr_funcptr) _gr_gr_mpoly_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_gr_mpoly_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_gr_mpoly_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_gr_mpoly_mul}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_gr_mpoly(gr_ctx_t ctx, gr_ctx_t base_ring, slong nvars, const ordering_t ord) { ctx->which_ring = GR_CTX_GR_MPOLY; ctx->sizeof_elem = sizeof(gr_mpoly_struct); GR_CTX_DATA_AS_PTR(ctx) = flint_malloc(sizeof(_gr_gr_mpoly_ctx_t)); ctx->size_limit = WORD_MAX; MPOLYNOMIAL_ELEM_CTX(ctx) = base_ring; mpoly_ctx_init(MPOLYNOMIAL_MCTX(ctx), nvars, ord); MPOLYNOMIAL_CTX(ctx)->vars = NULL; ctx->methods = _gr__gr_gr_mpoly_methods; if (!_gr__gr_gr_mpoly_methods_initialized) { gr_method_tab_init(_gr__gr_gr_mpoly_methods, _gr__gr_gr_mpoly_methods_input); _gr__gr_gr_mpoly_methods_initialized = 1; } } flint-3.1.3/src/gr/nf.c000066400000000000000000000407531461254215100146120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fexpr.h" #include "fmpz.h" #include "nf.h" #include "nf_elem.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_generic.h" typedef struct { nf_struct * nf; char * var; } _gr_nf_ctx_t; #define NF_CTX(ctx) (((_gr_nf_ctx_t *)(ctx))->nf) #define NF_VAR(ctx) (((_gr_nf_ctx_t *)(ctx))->var) static const char * default_var = "a"; int _gr_nf_ctx_write(gr_stream_t out, const gr_ctx_t ctx) { gr_stream_write(out, "Number field "); gr_stream_write_free(out, fmpq_poly_get_str_pretty(NF_CTX(ctx)->pol, NF_VAR(ctx))); return GR_SUCCESS; } int _gr_nf_ctx_set_gen_name(gr_ctx_t ctx, const char * s) { slong len; len = strlen(s); if (NF_VAR(ctx) == default_var) NF_VAR(ctx) = NULL; NF_VAR(ctx) = flint_realloc(NF_VAR(ctx), len + 1); memcpy(NF_VAR(ctx), s, len + 1); return GR_SUCCESS; } void _gr_nf_ctx_clear(gr_ctx_t ctx) { nf_clear(NF_CTX(ctx)); flint_free(NF_CTX(ctx)); if (NF_VAR(ctx) != default_var) flint_free(NF_VAR(ctx)); } void _gr_nf_init(nf_elem_t x, const gr_ctx_t ctx) { nf_elem_init(x, NF_CTX(ctx)); } void _gr_nf_clear(nf_elem_t x, const gr_ctx_t ctx) { nf_elem_clear(x, NF_CTX(ctx)); } void _gr_nf_swap(nf_elem_t x, nf_elem_t y, const gr_ctx_t ctx) { nf_elem_t t; *t = *x; *x = *y; *y = *t; } void _gr_nf_set_shallow(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { *res = *x; } int _gr_nf_randtest(nf_elem_t res, flint_rand_t state, const gr_ctx_t ctx) { switch (n_randint(state, 10)) { case 0: nf_elem_randtest(res, state, 100, NF_CTX(ctx)); break; default: nf_elem_randtest(res, state, 10, NF_CTX(ctx)); } return GR_SUCCESS; } int _gr_nf_write(gr_stream_t out, const nf_elem_t x, const gr_ctx_t ctx) { gr_stream_write_free(out, nf_elem_get_str_pretty(x, NF_VAR(ctx), NF_CTX(ctx))); return GR_SUCCESS; } int _gr_nf_gen(nf_elem_t x, const gr_ctx_t ctx) { nf_elem_gen(x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_zero(nf_elem_t x, const gr_ctx_t ctx) { nf_elem_zero(x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_one(nf_elem_t x, const gr_ctx_t ctx) { nf_elem_one(x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_set_si(nf_elem_t res, slong v, const gr_ctx_t ctx) { nf_elem_set_si(res, v, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_set_ui(nf_elem_t res, ulong v, const gr_ctx_t ctx) { nf_elem_set_ui(res, v, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_set_fmpz(nf_elem_t res, const fmpz_t v, const gr_ctx_t ctx) { nf_elem_set_fmpz(res, v, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_set_fmpq(nf_elem_t res, const fmpq_t v, const gr_ctx_t ctx) { nf_elem_set_fmpq(res, v, NF_CTX(ctx)); return GR_SUCCESS; } int gr_generic_set_other(gr_ptr res, gr_srcptr x, gr_ctx_t xctx, gr_ctx_t ctx); int _gr_nf_set_other(nf_elem_t res, gr_ptr v, gr_ctx_t v_ctx, gr_ctx_t ctx) { if (v_ctx->which_ring == GR_CTX_NF && ctx->which_ring == GR_CTX_NF) { if (fmpq_poly_equal(NF_CTX(v_ctx)->pol, NF_CTX(ctx)->pol)) { nf_elem_set(res, v, NF_CTX(ctx)); return GR_SUCCESS; } /* else if (nf_elem_is_rational(v, NF_CTX(v_ctx))) { fmpq_t t; fmpq_init(t); nf_elem_get_fmpq(t, v, NF_CTX(v_ctx)); nf_elem_set_fmpq(res, t, NF_CTX(ctx)); fmpq_clear(t); } */ else { return GR_UNABLE; } } return gr_generic_set_other(res, v, v_ctx, ctx); } void fexpr_set_nf_elem(fexpr_t res, const nf_elem_t a, const nf_t nf, const fexpr_t var); int _gr_nf_get_fexpr(fexpr_t res, const nf_elem_t a, const gr_ctx_t ctx) { fexpr_t var; fexpr_init(var); fexpr_set_symbol_str(var, NF_VAR(ctx)); fexpr_set_nf_elem(res, a, NF_CTX(ctx), var); fexpr_clear(var); return GR_SUCCESS; } int _gr_nf_set_fexpr(nf_elem_t res, fexpr_vec_t inp, gr_vec_t out, const fexpr_t expr, gr_ctx_t ctx) { fexpr_t var; nf_elem_t gen; int status; fexpr_init(var); fexpr_set_symbol_str(var, NF_VAR(ctx)); nf_elem_init(gen, NF_CTX(ctx)); nf_elem_gen(gen, NF_CTX(ctx)); /* todo: pop after use? */ fexpr_vec_append(inp, var); GR_MUST_SUCCEED(gr_vec_append(out, gen, ctx)); fexpr_clear(var); nf_elem_clear(gen, NF_CTX(ctx)); status = gr_generic_set_fexpr(res, inp, out, expr, ctx); return status; } truth_t _gr_nf_is_zero(const nf_elem_t x, const gr_ctx_t ctx) { return nf_elem_is_zero(x, NF_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_nf_is_one(const nf_elem_t x, const gr_ctx_t ctx) { return nf_elem_is_one(x, NF_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_nf_is_neg_one(const nf_elem_t x, const gr_ctx_t ctx) { return nf_elem_equal_si(x, -1, NF_CTX(ctx)) ? T_TRUE : T_FALSE; } truth_t _gr_nf_equal(const nf_elem_t x, const nf_elem_t y, const gr_ctx_t ctx) { return nf_elem_equal(x, y, NF_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_nf_set(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { nf_elem_set(res, x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_neg(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { nf_elem_neg(res, x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_add(nf_elem_t res, const nf_elem_t x, const nf_elem_t y, const gr_ctx_t ctx) { nf_elem_add(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_add_si(nf_elem_t res, const nf_elem_t x, slong y, const gr_ctx_t ctx) { nf_elem_add_si(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } /* int _gr_nf_add_ui(nf_elem_t res, const nf_elem_t x, ulong y, const gr_ctx_t ctx) { nf_elem_add_ui(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } */ int _gr_nf_add_fmpz(nf_elem_t res, const nf_elem_t x, const fmpz_t y, const gr_ctx_t ctx) { nf_elem_add_fmpz(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_add_fmpq(nf_elem_t res, const nf_elem_t x, const fmpq_t y, const gr_ctx_t ctx) { nf_elem_add_fmpq(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_sub(nf_elem_t res, const nf_elem_t x, const nf_elem_t y, const gr_ctx_t ctx) { nf_elem_sub(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_sub_si(nf_elem_t res, const nf_elem_t x, slong y, const gr_ctx_t ctx) { nf_elem_sub_si(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } /* int _gr_nf_sub_ui(nf_elem_t res, const nf_elem_t x, ulong y, const gr_ctx_t ctx) { nf_elem_sub_ui(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } */ int _gr_nf_sub_fmpz(nf_elem_t res, const nf_elem_t x, const fmpz_t y, const gr_ctx_t ctx) { nf_elem_sub_fmpz(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_sub_fmpq(nf_elem_t res, const nf_elem_t x, const fmpq_t y, const gr_ctx_t ctx) { nf_elem_sub_fmpq(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_mul(nf_elem_t res, const nf_elem_t x, const nf_elem_t y, const gr_ctx_t ctx) { nf_elem_mul(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_mul_si(nf_elem_t res, const nf_elem_t x, slong y, const gr_ctx_t ctx) { nf_elem_scalar_mul_si(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } /* int _gr_nf_mul_ui(nf_elem_t res, const nf_elem_t x, ulong y, const gr_ctx_t ctx) { nf_elem_scalar_mul_ui(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } */ int _gr_nf_mul_fmpz(nf_elem_t res, const nf_elem_t x, const fmpz_t y, const gr_ctx_t ctx) { nf_elem_scalar_mul_fmpz(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_mul_fmpq(nf_elem_t res, const nf_elem_t x, const fmpq_t y, const gr_ctx_t ctx) { nf_elem_scalar_mul_fmpq(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_mul_two(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { nf_elem_add(res, x, x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_sqr(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { nf_elem_mul(res, x, x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_inv(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { if (nf_elem_is_zero(x, NF_CTX(ctx))) return GR_DOMAIN; nf_elem_inv(res, x, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_div(nf_elem_t res, const nf_elem_t x, const nf_elem_t y, const gr_ctx_t ctx) { if (nf_elem_is_zero(y, NF_CTX(ctx))) return GR_DOMAIN; nf_elem_div(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_div_si(nf_elem_t res, const nf_elem_t x, slong y, const gr_ctx_t ctx) { if (y == 0) return GR_DOMAIN; nf_elem_scalar_div_si(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } /* int _gr_nf_div_ui(nf_elem_t res, const nf_elem_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) return GR_DOMAIN; nf_elem_scalar_div_ui(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } */ int _gr_nf_div_fmpz(nf_elem_t res, const nf_elem_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) return GR_DOMAIN; nf_elem_scalar_div_fmpz(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_div_fmpq(nf_elem_t res, const nf_elem_t x, const fmpq_t y, const gr_ctx_t ctx) { if (fmpq_is_zero(y)) return GR_DOMAIN; nf_elem_scalar_div_fmpq(res, x, y, NF_CTX(ctx)); return GR_SUCCESS; } truth_t _gr_nf_is_invertible(const nf_elem_t x, const gr_ctx_t ctx) { return nf_elem_is_zero(x, NF_CTX(ctx)) ? T_FALSE : T_TRUE; } int _gr_nf_pow_ui(nf_elem_t res, const nf_elem_t x, ulong exp, const gr_ctx_t ctx) { nf_elem_pow(res, x, exp, NF_CTX(ctx)); return GR_SUCCESS; } int _gr_nf_numerator(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { if (NF_CTX(ctx)->flag & NF_LINEAR) { fmpz_set(LNF_ELEM_NUMREF(res), LNF_ELEM_NUMREF(x)); fmpz_one(LNF_ELEM_DENREF(res)); } else if (NF_CTX(ctx)->flag & NF_QUADRATIC) { fmpz_set(QNF_ELEM_NUMREF(res), QNF_ELEM_NUMREF(x)); fmpz_set(QNF_ELEM_NUMREF(res) + 1, QNF_ELEM_NUMREF(x) + 1); fmpz_one(QNF_ELEM_DENREF(res)); } else { fmpq_poly_set(NF_ELEM(res), NF_ELEM(x)); fmpz_one(NF_ELEM_DENREF(res)); } return GR_SUCCESS; } int _gr_nf_denominator(nf_elem_t res, const nf_elem_t x, const gr_ctx_t ctx) { if (NF_CTX(ctx)->flag & NF_LINEAR) { fmpz_set(LNF_ELEM_NUMREF(res), LNF_ELEM_DENREF(x)); fmpz_one(LNF_ELEM_DENREF(res)); } else if (NF_CTX(ctx)->flag & NF_QUADRATIC) { fmpz_set(QNF_ELEM_NUMREF(res), QNF_ELEM_DENREF(x)); fmpz_zero(QNF_ELEM_NUMREF(res) + 1); fmpz_one(QNF_ELEM_DENREF(res)); } else { fmpq_poly_set_fmpz(NF_ELEM(res), NF_ELEM_DENREF(x)); fmpz_one(NF_ELEM_DENREF(res)); } return GR_SUCCESS; } /* todo: dot products, without intermediate reductions? */ /* todo: polynomial multiplication, etc. */ int _nf_methods_initialized = 0; gr_static_method_table _nf_methods; gr_method_tab_input _nf_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_nf_ctx_write}, {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_nf_ctx_clear}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_SET_GEN_NAME, (gr_funcptr) _gr_nf_ctx_set_gen_name}, {GR_METHOD_INIT, (gr_funcptr) _gr_nf_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_nf_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_nf_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_nf_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_nf_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_nf_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_nf_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_nf_one}, {GR_METHOD_GEN, (gr_funcptr) _gr_nf_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_nf_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_nf_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_nf_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_nf_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_nf_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_nf_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_nf_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_nf_set_fmpz}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_nf_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions}, {GR_METHOD_SET_FEXPR, (gr_funcptr) _gr_nf_set_fexpr}, {GR_METHOD_GET_FEXPR, (gr_funcptr) _gr_nf_get_fexpr}, {GR_METHOD_NEG, (gr_funcptr) _gr_nf_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_nf_add}, /* {GR_METHOD_ADD_UI, (gr_funcptr) _gr_nf_add_ui}, */ {GR_METHOD_ADD_SI, (gr_funcptr) _gr_nf_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_nf_add_fmpz}, {GR_METHOD_ADD_FMPQ, (gr_funcptr) _gr_nf_add_fmpq}, {GR_METHOD_SUB, (gr_funcptr) _gr_nf_sub}, /* {GR_METHOD_SUB_UI, (gr_funcptr) _gr_nf_sub_ui}, */ {GR_METHOD_SUB_SI, (gr_funcptr) _gr_nf_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_nf_sub_fmpz}, {GR_METHOD_SUB_FMPQ, (gr_funcptr) _gr_nf_sub_fmpq}, {GR_METHOD_MUL, (gr_funcptr) _gr_nf_mul}, /* {GR_METHOD_MUL_UI, (gr_funcptr) _gr_nf_mul_ui}, */ {GR_METHOD_MUL_SI, (gr_funcptr) _gr_nf_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_nf_mul_fmpz}, {GR_METHOD_MUL_FMPQ, (gr_funcptr) _gr_nf_mul_fmpq}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_nf_mul_two}, {GR_METHOD_SQR, (gr_funcptr) _gr_nf_sqr}, {GR_METHOD_DIV, (gr_funcptr) _gr_nf_div}, /* {GR_METHOD_DIV_UI, (gr_funcptr) _gr_nf_div_ui}, */ {GR_METHOD_DIV_SI, (gr_funcptr) _gr_nf_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_nf_div_fmpz}, {GR_METHOD_DIV_FMPQ, (gr_funcptr) _gr_nf_div_fmpq}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_nf_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_nf_inv}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_nf_pow_ui}, {GR_METHOD_NUMERATOR, (gr_funcptr) _gr_nf_numerator}, {GR_METHOD_DENOMINATOR, (gr_funcptr) _gr_nf_denominator}, {0, (gr_funcptr) NULL}, }; /* todo: verify irreducibility? */ void gr_ctx_init_nf(gr_ctx_t ctx, const fmpq_poly_t poly) { ctx->which_ring = GR_CTX_NF; ctx->sizeof_elem = sizeof(nf_elem_struct); ctx->size_limit = WORD_MAX; NF_CTX(ctx) = flint_malloc(sizeof(nf_struct)); nf_init(NF_CTX(ctx), poly); NF_VAR(ctx) = (char *) default_var; ctx->methods = _nf_methods; if (!_nf_methods_initialized) { gr_method_tab_init(_nf_methods, _nf_methods_input); _nf_methods_initialized = 1; } } void gr_ctx_init_nf_fmpz_poly(gr_ctx_t ctx, const fmpz_poly_t poly) { fmpq_poly_t f; fmpz one = 1; f->coeffs = poly->coeffs; f->alloc = poly->alloc; f->length = poly->length; *f->den = one; gr_ctx_init_nf(ctx, f); } void _gr_ctx_init_nf_from_ref(gr_ctx_t ctx, const void * nfctx) { ctx->which_ring = GR_CTX_NF; ctx->sizeof_elem = sizeof(nf_elem_struct); ctx->size_limit = WORD_MAX; NF_CTX(ctx) = (nf_struct *) nfctx; NF_VAR(ctx) = (char *) default_var; ctx->methods = _nf_methods; if (!_nf_methods_initialized) { gr_method_tab_init(_nf_methods, _nf_methods_input); _nf_methods_initialized = 1; } } flint-3.1.3/src/gr/nmod.c000066400000000000000000001220331461254215100151340ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "gr.h" #include "gr_vec.h" #include "gr_mat.h" #include "gr_poly.h" #include "gr_generic.h" typedef struct { nmod_t nmod; ulong a; /* when used as finite field with defining polynomial x - a */ truth_t is_prime; } _gr_nmod_ctx_struct; #define NMOD_CTX_REF(ring_ctx) (&((((_gr_nmod_ctx_struct *)(ring_ctx))->nmod))) #define NMOD_CTX(ring_ctx) (*NMOD_CTX_REF(ring_ctx)) #define NMOD_IS_PRIME(ring_ctx) (((_gr_nmod_ctx_struct *)(ring_ctx))->is_prime) /* when used as finite field when defining polynomial x - a, allow storing the coefficient a */ #define NMOD_CTX_A(ring_ctx) (&((((_gr_nmod_ctx_struct *)(ring_ctx))->a))) void _gr_nmod_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Integers mod "); gr_stream_write_ui(out, NMOD_CTX(ctx).n); gr_stream_write(out, " (_gr_nmod)"); } truth_t _gr_nmod_ctx_is_field(const gr_ctx_t ctx) { if (NMOD_IS_PRIME(ctx) != T_UNKNOWN) return NMOD_IS_PRIME(ctx); return n_is_prime(NMOD_CTX(ctx).n) ? T_TRUE : T_FALSE; } void _gr_nmod_init(ulong * x, const gr_ctx_t ctx) { x[0] = 0; } void _gr_nmod_clear(ulong * x, const gr_ctx_t ctx) { } void _gr_nmod_swap(ulong * x, ulong * y, const gr_ctx_t ctx) { ulong t; t = *x; *x = *y; *y = t; } void _gr_nmod_set_shallow(ulong * res, const ulong * x, const gr_ctx_t ctx) { *res = *x; } int _gr_nmod_randtest(ulong * res, flint_rand_t state, const gr_ctx_t ctx) { res[0] = n_randtest(state) % NMOD_CTX(ctx).n; return GR_SUCCESS; } int _gr_nmod_write(gr_stream_t out, const ulong * x, const gr_ctx_t ctx) { gr_stream_write_ui(out, x[0]); return GR_SUCCESS; } int _gr_nmod_zero(ulong * x, const gr_ctx_t ctx) { x[0] = 0; return GR_SUCCESS; } int _gr_nmod_one(ulong * x, const gr_ctx_t ctx) { x[0] = (NMOD_CTX(ctx).n != 1); return GR_SUCCESS; } int _gr_nmod_set_si(ulong * res, slong v, const gr_ctx_t ctx) { res[0] = nmod_set_si(v, NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_set_ui(ulong * res, ulong v, const gr_ctx_t ctx) { res[0] = nmod_set_ui(v, NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_set_fmpz(ulong * res, const fmpz_t v, const gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); res[0] = fmpz_get_nmod(v, mod); return GR_SUCCESS; } int _gr_nmod_inv(ulong * res, const ulong * x, const gr_ctx_t ctx) { ulong r, g; /* todo: also handle -1 fast? */ if (x[0] == 1) { res[0] = x[0]; return GR_SUCCESS; } g = n_gcdinv(&r, x[0], NMOD_CTX(ctx).n); if (g == 1) { res[0] = r; return GR_SUCCESS; } else { res[0] = 0; return GR_DOMAIN; } } #include "fmpz_mod.h" /* todo: public interface */ typedef struct { fmpz_mod_ctx_struct ctx; truth_t is_prime; } fmpz_mod_ctx_extended_struct; #define FMPZ_MOD_CTX(ring_ctx) (&(((fmpz_mod_ctx_extended_struct *)(GR_CTX_DATA_AS_PTR(ring_ctx)))->ctx)) int _gr_nmod_set_other(ulong * res, gr_ptr v, gr_ctx_t v_ctx, const gr_ctx_t ctx) { if (v_ctx->which_ring == GR_CTX_NMOD) { if (NMOD_CTX(ctx).n != NMOD_CTX(v_ctx).n) return GR_DOMAIN; *res = *((ulong *) v); return GR_SUCCESS; } if (v_ctx->which_ring == GR_CTX_FMPZ_MOD) { if (!fmpz_equal_ui(FMPZ_MOD_CTX(v_ctx)->n, NMOD_CTX(ctx).n)) return GR_DOMAIN; res[0] = fmpz_get_ui(v); return GR_SUCCESS; } if (v_ctx->which_ring == GR_CTX_FMPZ) { res[0] = fmpz_get_nmod(v, NMOD_CTX(ctx)); return GR_SUCCESS; } if (v_ctx->which_ring == GR_CTX_FMPQ) { ulong a, b; int status; const fmpq * q = v; if (fmpz_is_one(fmpq_denref(q))) { res[0] = fmpz_get_nmod(fmpq_numref(q), NMOD_CTX(ctx)); } else { b = fmpz_get_nmod(fmpq_denref(q), NMOD_CTX(ctx)); status = _gr_nmod_inv(&b, &b, ctx); if (status != GR_SUCCESS) return status; a = fmpz_get_nmod(fmpq_numref(q), NMOD_CTX(ctx)); res[0] = nmod_mul(a, b, NMOD_CTX(ctx)); } return GR_SUCCESS; } return GR_UNABLE; } truth_t _gr_nmod_is_zero(const ulong * x, const gr_ctx_t ctx) { return (x[0] == 0) ? T_TRUE : T_FALSE; } truth_t _gr_nmod_is_one(const ulong * x, const gr_ctx_t ctx) { return (x[0] == (NMOD_CTX(ctx).n != 1)) ? T_TRUE : T_FALSE; } truth_t _gr_nmod_is_neg_one(const ulong * x, const gr_ctx_t ctx) { return (x[0] == NMOD_CTX(ctx).n - 1) ? T_TRUE : T_FALSE; } truth_t _gr_nmod_equal(const ulong * x, const ulong * y, const gr_ctx_t ctx) { return (x[0] == y[0]) ? T_TRUE : T_FALSE; } int _gr_nmod_set(ulong * res, const ulong * x, const gr_ctx_t ctx) { res[0] = x[0]; return GR_SUCCESS; } int _gr_nmod_neg(ulong * res, const ulong * x, const gr_ctx_t ctx) { res[0] = nmod_neg(x[0], NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_add(ulong * res, const ulong * x, const ulong * y, const gr_ctx_t ctx) { res[0] = nmod_add(x[0], y[0], NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_add_ui(ulong * res, const ulong * x, ulong y, const gr_ctx_t ctx) { res[0] = nmod_add(x[0], nmod_set_ui(y, NMOD_CTX(ctx)), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_add_si(ulong * res, const ulong * x, slong y, const gr_ctx_t ctx) { res[0] = nmod_add(x[0], nmod_set_si(y, NMOD_CTX(ctx)), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_sub(ulong * res, const ulong * x, const ulong * y, const gr_ctx_t ctx) { res[0] = nmod_sub(x[0], y[0], NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_sub_ui(ulong * res, const ulong * x, ulong y, const gr_ctx_t ctx) { res[0] = nmod_sub(x[0], nmod_set_ui(y, NMOD_CTX(ctx)), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_sub_si(ulong * res, const ulong * x, slong y, const gr_ctx_t ctx) { res[0] = nmod_sub(x[0], nmod_set_si(y, NMOD_CTX(ctx)), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_mul(ulong * res, const ulong * x, const ulong * y, const gr_ctx_t ctx) { res[0] = nmod_mul(x[0], y[0], NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_mul_ui(ulong * res, const ulong * x, ulong y, const gr_ctx_t ctx) { /* res[0] = nmod_mul(x[0], nmod_set_ui(y, NMOD_CTX(ctx)), NMOD_CTX(ctx)); */ res[0] = n_mulmod2_preinv(x[0], y, NMOD_CTX(ctx).n, NMOD_CTX(ctx).ninv); return GR_SUCCESS; } int _gr_nmod_mul_si(ulong * res, const ulong * x, slong y, const gr_ctx_t ctx) { /* res[0] = nmod_mul(x[0], nmod_set_si(y, NMOD_CTX(ctx)), NMOD_CTX(ctx)); */ if (y >= 0) res[0] = n_mulmod2_preinv(x[0], y, NMOD_CTX(ctx).n, NMOD_CTX(ctx).ninv); else res[0] = nmod_neg(n_mulmod2_preinv(x[0], -y, NMOD_CTX(ctx).n, NMOD_CTX(ctx).ninv), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_mul_fmpz(ulong * res, const ulong * x, const fmpz_t y, const gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*y)) { if (*y >= 0) res[0] = n_mulmod2_preinv(x[0], *y, NMOD_CTX(ctx).n, NMOD_CTX(ctx).ninv); else res[0] = nmod_neg(n_mulmod2_preinv(x[0], -*y, NMOD_CTX(ctx).n, NMOD_CTX(ctx).ninv), NMOD_CTX(ctx)); } else { res[0] = nmod_mul(x[0], fmpz_get_nmod(y, NMOD_CTX(ctx)), NMOD_CTX(ctx)); } return GR_SUCCESS; } int _gr_nmod_addmul(ulong * res, const ulong * x, const ulong * y, const gr_ctx_t ctx) { ulong r = res[0]; NMOD_ADDMUL(r, x[0], y[0], NMOD_CTX(ctx)); res[0] = r; return GR_SUCCESS; } int _gr_nmod_submul(ulong * res, const ulong * x, const ulong * y, const gr_ctx_t ctx) { ulong r = res[0]; ulong t = nmod_neg(y[0], NMOD_CTX(ctx)); NMOD_ADDMUL(r, x[0], t, NMOD_CTX(ctx)); res[0] = r; return GR_SUCCESS; } int _gr_nmod_mul_two(ulong * res, const ulong * x, const gr_ctx_t ctx) { return _gr_nmod_add(res, x, x, ctx); } int _gr_nmod_sqr(ulong * res, const ulong * x, const gr_ctx_t ctx) { return _gr_nmod_mul(res, x, x, ctx); } int _gr_nmod_div(ulong * res, const ulong * x, const ulong * y, const gr_ctx_t ctx) { ulong t; int status; status = _gr_nmod_inv(&t, y, ctx); if (status == GR_SUCCESS) _gr_nmod_mul(res, x, &t, ctx); return status; } int _gr_nmod_div_si(ulong * res, const ulong * x, slong y, const gr_ctx_t ctx) { ulong c = nmod_set_si(y, NMOD_CTX(ctx)); return _gr_nmod_div(res, x, &c, ctx); } int _gr_nmod_div_ui(ulong * res, const ulong * x, ulong y, const gr_ctx_t ctx) { ulong c = nmod_set_ui(y, NMOD_CTX(ctx)); return _gr_nmod_div(res, x, &c, ctx); } int _gr_nmod_div_fmpz(ulong * res, const ulong * x, const fmpz_t y, const gr_ctx_t ctx) { ulong c = fmpz_get_nmod(y, NMOD_CTX(ctx)); return _gr_nmod_div(res, x, &c, ctx); } truth_t _gr_nmod_is_invertible(const ulong * x, const gr_ctx_t ctx) { ulong r, g; g = n_gcdinv(&r, x[0], NMOD_CTX(ctx).n); return (g == 1) ? T_TRUE : T_FALSE; } truth_t _gr_nmod_divides(const ulong * x, const ulong * y, const gr_ctx_t ctx) { ulong t; return nmod_divides(&t, y[0], x[0], NMOD_CTX(ctx)) ? T_TRUE : T_FALSE; } int _gr_nmod_div_nonunique(ulong * res, const ulong * x, const ulong * y, const gr_ctx_t ctx) { ulong t; int status; status = _gr_nmod_inv(&t, y, ctx); if (status == GR_SUCCESS) { _gr_nmod_mul(res, x, &t, ctx); } else { status = nmod_divides(res, *x, *y, NMOD_CTX(ctx)) ? GR_SUCCESS : GR_DOMAIN; } return status; } int _gr_nmod_mul_2exp_si(ulong * res, ulong * x, slong y, const gr_ctx_t ctx) { ulong c, m = NMOD_CTX(ctx).n; if (y >= 0) { if (y < FLINT_BITS) { c = UWORD(1) << y; if (c >= m) NMOD_RED(c, c, NMOD_CTX(ctx)); } else { /* accidentally also works when mod <= 2 */ c = nmod_pow_ui(2, y, NMOD_CTX(ctx)); } } else { if (m % 2 == 0) { if (m == 1) { res[0] = 0; return GR_SUCCESS; } return GR_DOMAIN; } /* quickly construct 1/2 */ c = (m - 1) / 2 + 1; c = nmod_pow_ui(c, -y, NMOD_CTX(ctx)); } res[0] = nmod_mul(x[0], c, NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_sqrt(ulong * res, const ulong * x, gr_ctx_t ctx) { if (x[0] <= 1) { res[0] = x[0]; return GR_SUCCESS; } /* todo: implement the general case */ if (gr_ctx_is_field(ctx) != T_TRUE) return GR_UNABLE; res[0] = n_sqrtmod(x[0], NMOD_CTX(ctx).n); if (res[0] == 0) return GR_DOMAIN; else return GR_SUCCESS; } truth_t _gr_nmod_is_square(const ulong * x, gr_ctx_t ctx) { ulong y; if (x[0] <= 1) return T_TRUE; /* todo: implement the general case */ if (gr_ctx_is_field(ctx) != T_TRUE) return T_UNKNOWN; y = n_sqrtmod(x[0], NMOD_CTX(ctx).n); if (y == 0) return T_FALSE; else return T_TRUE; } int _gr_nmod_pow_ui(ulong * res, const ulong * x, ulong y, const gr_ctx_t ctx) { res[0] = nmod_pow_ui(x[0], y, NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_pow_fmpz(ulong * res, const ulong * x, const fmpz_t y, gr_ctx_t ctx) { if (fmpz_sgn(y) < 0) { return gr_generic_pow_fmpz(res, x, y, ctx); } else { res[0] = nmod_pow_fmpz(x[0], y, NMOD_CTX(ctx)); return GR_SUCCESS; } } void _gr_nmod_vec_init(ulong * res, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) res[i] = 0; } void _gr_nmod_vec_clear(ulong * res, slong len, gr_ctx_t ctx) { } int _gr_nmod_vec_set(ulong * res, const ulong * vec, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) res[i] = vec[i]; return GR_SUCCESS; } int _gr_nmod_vec_normalise(slong * res, const ulong * vec, slong len, gr_ctx_t ctx) { while (len > 0 && vec[len - 1] == 0) len--; res[0] = len; return GR_SUCCESS; } slong _gr_nmod_vec_normalise_weak(const ulong * vec, slong len, gr_ctx_t ctx) { while (len > 0 && vec[len - 1] == 0) len--; return len; } int _gr_nmod_vec_neg(ulong * res, const ulong * vec, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD_CTX(ctx); for (i = 0; i < len; i++) res[i] = nmod_neg(vec[i], mod); return GR_SUCCESS; } int _gr_nmod_vec_add(ulong * res, const ulong * vec1, const ulong * vec2, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD_CTX(ctx); for (i = 0; i < len; i++) res[i] = nmod_add(vec1[i], vec2[i], mod); return GR_SUCCESS; } int _gr_nmod_vec_sub(ulong * res, const ulong * vec1, const ulong * vec2, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD_CTX(ctx); for (i = 0; i < len; i++) res[i] = nmod_sub(vec1[i], vec2[i], mod); return GR_SUCCESS; } static inline void _nmod_vec_scalar_mul_nmod_fullword_inline(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; for (i = 0; i < len; i++) NMOD_MUL_FULLWORD(res[i], vec[i], c, mod); } static inline void _nmod_vec_scalar_mul_nmod_generic_inline(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; for (i = 0; i < len; i++) NMOD_MUL_PRENORM(res[i], vec[i], c << mod.norm, mod); } static inline void _nmod_vec_scalar_mul_nmod_inline(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { if (NMOD_BITS(mod) == FLINT_BITS) _nmod_vec_scalar_mul_nmod_fullword_inline(res, vec, len, c, mod); else if (len > 10) _nmod_vec_scalar_mul_nmod_shoup(res, vec, len, c, mod); else _nmod_vec_scalar_mul_nmod_generic_inline(res, vec, len, c, mod); } int _gr_nmod_vec_mul_scalar(ulong * res, const ulong * vec1, slong len, const ulong * c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_mul_nmod_inline(res, vec1, len, c[0], mod); return GR_SUCCESS; } int _gr_nmod_vec_mul_scalar_si(ulong * res, const ulong * vec1, slong len, slong c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_mul_nmod_inline(res, vec1, len, nmod_set_si(c, mod), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_vec_mul_scalar_ui(ulong * res, const ulong * vec1, slong len, ulong c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_mul_nmod_inline(res, vec1, len, nmod_set_ui(c, mod), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_vec_mul_scalar_fmpz(ulong * res, const ulong * vec1, slong len, const fmpz_t c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_mul_nmod(res, vec1, len, fmpz_get_nmod(c, mod), NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_vec_mul_scalar_2exp_si(ulong * res, const ulong * vec1, slong len, slong c, gr_ctx_t ctx) { ulong t[1]; int status = GR_SUCCESS; if (c == 1) return _gr_nmod_vec_add(res, vec1, vec1, len, ctx); status |= _gr_nmod_one(t, ctx); status |= _gr_nmod_mul_2exp_si(t, t, c, ctx); status |= _gr_nmod_vec_mul_scalar(res, vec1, len, t, ctx); return status; } int _gr_nmod_vec_addmul_scalar(ulong * res, const ulong * vec1, slong len, const ulong * c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_addmul_nmod(res, vec1, len, c[0], mod); return GR_SUCCESS; } int _gr_nmod_vec_submul_scalar(ulong * res, const ulong * vec1, slong len, const ulong * c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_addmul_nmod(res, vec1, len, nmod_neg(c[0], mod), mod); return GR_SUCCESS; } int _gr_nmod_vec_addmul_scalar_si(ulong * res, const ulong * vec1, slong len, slong c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_addmul_nmod(res, vec1, len, nmod_set_si(c, mod), mod); return GR_SUCCESS; } int _gr_nmod_vec_submul_scalar_si(ulong * res, const ulong * vec1, slong len, slong c, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); _nmod_vec_scalar_addmul_nmod(res, vec1, len, nmod_neg(nmod_set_si(c, mod), mod), mod); return GR_SUCCESS; } int _gr_nmod_vec_sum(ulong * res, const ulong * vec, slong len, gr_ctx_t ctx) { ulong hi, lo; slong i; nmod_t mod = NMOD_CTX(ctx); if (len < 10) { lo = 0; for (i = 0; i < len; i++) lo = nmod_add(lo, vec[i], mod); } else { umul_ppmm(hi, lo, mod.n, len); if (hi == 0) { lo = vec[0]; for (i = 1; i < len; i++) lo += vec[i]; NMOD_RED(lo, lo, mod); } else { lo = vec[0]; hi = 0; for (i = 1; i < len; i++) add_ssaaaa(hi, lo, hi, lo, 0, vec[i]); NMOD2_RED2(lo, hi, lo, mod); } } res[0] = lo; return GR_SUCCESS; } int _gr_nmod_vec_product(ulong * res, const ulong * vec, slong len, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); if (len <= 2) { if (len == 2) res[0] = nmod_mul(vec[0], vec[1], mod); else if (len == 1) res[0] = vec[0]; else res[0] = (mod.n != 1); } else { ulong p; slong i; if (mod.norm == 0) { p = _nmod_mul_fullword(vec[0], vec[1], mod); for (i = 2; i < len; i++) p = _nmod_mul_fullword(p, vec[i], mod); } else { p = nmod_mul(vec[0], vec[1], mod); for (i = 2; i < len; i++) p = nmod_mul(p, vec[i], mod); } res[0] = p; } return GR_SUCCESS; } int __gr_nmod_vec_dot(ulong * res, const ulong * initial, int subtract, const ulong * vec1, const ulong * vec2, slong len, gr_ctx_t ctx) { slong i; ulong s; int nlimbs; nmod_t mod; if (len <= 1) { if (len == 2) /* todo: fmma */ { mod = NMOD_CTX(ctx); s = nmod_mul(vec1[0], vec2[0], mod); s = nmod_addmul(s, vec1[1], vec2[1], mod); } else if (len == 1) { mod = NMOD_CTX(ctx); s = nmod_mul(vec1[0], vec2[0], mod); } else { if (initial == NULL) _gr_nmod_zero(res, ctx); else _gr_nmod_set(res, initial, ctx); return GR_SUCCESS; } } else { mod = NMOD_CTX(ctx); if (len <= 16) { if (mod.n <= UWORD(1) << (FLINT_BITS / 2 - 2)) nlimbs = 1; if (mod.n <= UWORD(1) << (FLINT_BITS - 2)) nlimbs = 2; else nlimbs = 3; } else { nlimbs = _nmod_vec_dot_bound_limbs(len, mod); } NMOD_VEC_DOT(s, i, len, vec1[i], vec2[i], mod, nlimbs); } if (initial == NULL) { if (subtract) s = nmod_neg(s, mod); } else { if (subtract) s = nmod_sub(initial[0], s, mod); else s = nmod_add(initial[0], s, mod); } *res = s; return GR_SUCCESS; } int __gr_nmod_vec_dot_rev(ulong * res, const ulong * initial, int subtract, const ulong * vec1, const ulong * vec2, slong len, gr_ctx_t ctx) { slong i; ulong s; int nlimbs; nmod_t mod; if (len <= 1) { if (len == 2) /* todo: fmma */ { mod = NMOD_CTX(ctx); s = nmod_mul(vec1[0], vec2[1], mod); s = nmod_addmul(s, vec1[1], vec2[0], mod); } else if (len == 1) { mod = NMOD_CTX(ctx); s = nmod_mul(vec1[0], vec2[0], mod); } else { if (initial == NULL) _gr_nmod_zero(res, ctx); else _gr_nmod_set(res, initial, ctx); return GR_SUCCESS; } } else { mod = NMOD_CTX(ctx); if (len <= 16) { if (mod.n <= UWORD(1) << (FLINT_BITS / 2 - 2)) nlimbs = 1; if (mod.n <= UWORD(1) << (FLINT_BITS - 2)) nlimbs = 2; else nlimbs = 3; } else { nlimbs = _nmod_vec_dot_bound_limbs(len, mod); } NMOD_VEC_DOT(s, i, len, vec1[i], vec2[len - 1 - i], mod, nlimbs); } if (initial == NULL) { if (subtract) s = nmod_neg(s, mod); } else { if (subtract) s = nmod_sub(initial[0], s, mod); else s = nmod_add(initial[0], s, mod); } *res = s; return GR_SUCCESS; } /* todo: better algorithms for large len */ int _gr_nmod_vec_reciprocals(ulong * res, slong len, gr_ctx_t ctx) { nmod_t mod = NMOD_CTX(ctx); slong k; ulong c2; if (len <= 1) { res[0] = (mod.n != 1); return GR_SUCCESS; } if (mod.n <= len || mod.n % 2 == 0) return GR_DOMAIN; res[0] = 1; res[1] = c2 = (mod.n - 1) / 2 + 1;; for (k = 3; k <= len; k += 2) { if (n_gcdinv(res + k - 1, k, mod.n) != 1) return GR_DOMAIN; } for (k = 4; k <= len; k += 2) res[k - 1] = nmod_mul(res[k / 2 - 1], c2, mod); return GR_SUCCESS; } int _gr_nmod_poly_mullow(ulong * res, const ulong * poly1, slong len1, const ulong * poly2, slong len2, slong n, gr_ctx_t ctx) { if (len1 + len2 - 1 == n) { if (len1 >= len2) _nmod_poly_mul(res, poly1, len1, poly2, len2, NMOD_CTX(ctx)); else _nmod_poly_mul(res, poly2, len2, poly1, len1, NMOD_CTX(ctx)); } else { if (len1 >= len2) _nmod_poly_mullow(res, poly1, len1, poly2, len2, n, NMOD_CTX(ctx)); else _nmod_poly_mullow(res, poly2, len2, poly1, len1, n, NMOD_CTX(ctx)); } return GR_SUCCESS; } /* fixme: duplicates _nmod_poly_divrem for error handling */ int _gr_nmod_poly_divrem(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, gr_ctx_t ctx) { if (lenA <= 20 || lenB <= 8 || lenA - lenB <= 6 || (NMOD_BITS(NMOD_CTX(ctx)) <= 61 && lenA <= 40) || (NMOD_BITS(NMOD_CTX(ctx)) <= 29 && lenA <= 70)) { mp_limb_t invB; int status; status = _gr_nmod_inv(&invB, &B[lenB - 1], ctx); if (status != GR_SUCCESS) return status; _nmod_poly_divrem_basecase_preinv1(Q, R, A, lenA, B, lenB, invB, NMOD_CTX(ctx)); return status; } else { #ifdef FLINT_HAVE_FFT_SMALL return _gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, ctx); #else if (NMOD_BITS(NMOD_CTX(ctx)) >= 16 && lenB >= 1024 && lenA <= 16384) return _gr_poly_divrem_divconquer(Q, R, A, lenA, B, lenB, 16, ctx); else return _gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, ctx); #endif } } int _gr_nmod_poly_divexact(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, gr_ctx_t ctx) { slong lenQ = lenA - lenB + 1; if (lenB <= 40 || lenQ <= 20) return _gr_poly_divexact_basecase(Q, A, lenA, B, lenB, ctx); else if (lenB <= 60 || lenQ <= 60) return _gr_poly_divexact_basecase_bidirectional(Q, A, lenA, B, lenB, ctx); else return _gr_poly_divexact_bidirectional(Q, A, lenA, B, lenB, ctx); } /* basecase -> Newton cutoffs */ /* todo: better unbalanced tuning */ #ifdef FLINT_HAVE_FFT_SMALL static const short inv_series_cutoff_tab[64] = {36, 37, 40, 44, 42, 46, 50, 81, 97, 106, 133, 152, 292, 279, 279, 191, 191, 191, 191, 200, 191, 407, 388, 407, 407, 407, 407, 407, 266, 292, 292, 292, 231, 242, 279, 279, 292, 292, 279, 292, 292, 279, 292, 292, 292, 370, 370, 370, 370, 370, 370, 388, 407, 448, 427, 407, 427, 427, 427, 427, 388, 370, 370, 353, }; #else static const short inv_series_cutoff_tab[64] = {38, 36, 38, 36, 41, 48, 49, 54, 60, 102, 112, 150, 165, 172, 210, 272, 339, 378, 385, 442, 468, 557, 596, 621, 710, 746, 756, 978, 768, 679, 700, 696, 620, 619, 642, 766, 901, 883, 924, 997, 979, 1028, 1101, 1094, 1152, 1169, 1279, 1311, 1284, 1381, 1418, 1513, 1540, 1598, 1692, 1846, 1883, 1942, 1963, 1803, 1788, 1861, 1881, 1920, }; #endif void _nmod_poly_inv_series_basecase_preinv1(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, mp_limb_t q, nmod_t mod); int _gr_nmod_poly_inv_series_basecase(ulong * res, const ulong * f, slong flen, slong n, gr_ctx_t ctx) { mp_limb_t q; q = f[0]; if (q != 1) { if (n_gcdinv(&q, q, NMOD_CTX(ctx).n) != 1) return GR_DOMAIN; } _nmod_poly_inv_series_basecase_preinv1(res, f, flen, n, q, NMOD_CTX(ctx)); return GR_SUCCESS; } int _gr_nmod_poly_inv_series(ulong * res, const ulong * f, slong flen, slong n, gr_ctx_t ctx) { slong cutoff; flen = FLINT_MIN(flen, n); cutoff = inv_series_cutoff_tab[NMOD_BITS(NMOD_CTX(ctx)) - 1]; if (flen < cutoff) return _gr_poly_inv_series_basecase(res, f, flen, n, ctx); else return _gr_poly_inv_series_newton(res, f, flen, n, cutoff, ctx); } void _nmod_poly_div_series_basecase_preinv1(mp_ptr Qinv, mp_srcptr P, slong Plen, mp_srcptr Q, slong Qlen, slong n, mp_limb_t q, nmod_t mod); int _gr_nmod_poly_div_series_basecase(ulong * res, const ulong * f, slong flen, const ulong * g, slong glen, slong n, gr_ctx_t ctx) { mp_limb_t q; q = g[0]; if (q != 1) { if (n_gcdinv(&q, q, NMOD_CTX(ctx).n) != 1) return GR_DOMAIN; } _nmod_poly_div_series_basecase_preinv1(res, f, flen, g, glen, n, q, NMOD_CTX(ctx)); return GR_SUCCESS; } /* todo: unbalanced cutoffs */ #ifdef FLINT_HAVE_FFT_SMALL static const short div_series_cutoff_tab[64] = { 85, 81, 85, 89, 106, 145, 166, 182, 210, 337, 321, 321, 306, 321, 321, 306, 321, 321, 321, 306, 626, 597, 597, 597, 597, 597, 597, 597, 370, 388, 388, 407, 321, 321, 321, 321, 321, 337, 321, 337, 321, 321, 337, 321, 337, 427, 427, 448, 427, 427, 448, 448, 470, 470, 470, 470, 470, 470, 493, 470, 427, 470, 448, 448, }; #else static const short div_series_cutoff_tab[64] = { 64, 64, 63, 65, 77, 84, 140, 158, 197, 208, 276, 243, 348, 358, 450, 560, 585, 692, 749, 787, 864, 922, 914, 1239, 1454, 1424, 1449, 1327, 1115, 1174, 1250, 1282, 961, 981, 1000, 1091, 1138, 1222, 1205, 1374, 1397, 1420, 1446, 1486, 1513, 1763, 1782, 1890, 2047, 2071, 2075, 2271, 2192, 2307, 2407, 2324, 2308, 2958, 3001, 2816, 2747, 2985, 2970, 2871, }; #endif int _gr_nmod_poly_div_series(ulong * res, const ulong * f, slong flen, const ulong * g, slong glen, slong n, gr_ctx_t ctx) { slong cutoff; flen = FLINT_MIN(flen, n); glen = FLINT_MIN(glen, n); cutoff = div_series_cutoff_tab[NMOD_BITS(NMOD_CTX(ctx)) - 1]; if (glen < cutoff) return _gr_poly_div_series_basecase(res, f, flen, g, glen, n, ctx); else return _gr_poly_div_series_newton(res, f, flen, g, glen, n, cutoff, ctx); } /* todo: unbalanced cutoffs */ #ifdef FLINT_HAVE_FFT_SMALL static const short rsqrt_series_cutoff_tab[64] = {3, 22, 24, 42, 36, 40, 44, 52, 89, 106, 139, 166, 174, 200, 191, 200, 191, 191, 191, 200, 306, 370, 353, 337, 337, 370, 370, 370, 292, 292, 279, 292, 231, 231, 220, 279, 292, 292, 279, 292, 292, 279, 292, 292, 292, 370, 370, 370, 370, 370, 370, 388, 407, 448, 427, 407, 427, 427, 427, 427, 388, 370, 370, 353, }; #else static const short rsqrt_series_cutoff_tab[64] = {6, 22, 22, 24, 27, 28, 28, 58, 77, 96, 116, 160, 232, 270, 315, 387, 402, 472, 502, 580, 627, 760, 824, 940, 988, 1018, 1155, 1182, 938, 932, 925, 1016, 836, 891, 915, 960, 1038, 1101, 1203, 1236, 1255, 1311, 1386, 1422, 1489, 1592, 1624, 1879, 1828, 2055, 2227, 2369, 2156, 2361, 2415, 2472, 2581, 2719, 2679, 2302, 2199, 2455, 2440, 2356, }; #endif int _gr_nmod_poly_rsqrt_series(ulong * res, const ulong * f, slong flen, slong n, gr_ctx_t ctx) { slong cutoff; flen = FLINT_MIN(flen, n); cutoff = rsqrt_series_cutoff_tab[NMOD_BITS(NMOD_CTX(ctx)) - 1]; if (flen < cutoff) return _gr_poly_rsqrt_series_basecase(res, f, flen, n, ctx); else return _gr_poly_rsqrt_series_newton(res, f, flen, n, cutoff, ctx); } #ifdef FLINT_HAVE_FFT_SMALL static const short sqrt_series_cutoff_tab[] = { 32767, 1353, 1353, 919, 1289, 1228, 1491, 1228, 1491, 1289, 1420, 1420, 1228, 1289, 1420, 1353, 1289, 1289, 1353, 4345, 4345, 2423, 2544, 4345, 4562, 2423, 4345, 2671, 1725, 1811, 1725, 3577, 1643, 1643, 1725, 1725, 1725, 3407, 3407, 1725, 1643, 1811, 3407, 3407, 4562, 3755, 3755, 3577, 3577, 4562, 3755, 3942, 3755, 3755, 4562, 4562, 4562, 4562, 3755, 3245, 3245, 2944, 3091, 2423, }; #else static const short sqrt_series_cutoff_tab[] = { 32767, 632, 732, 928, 1443, 1731, 2364, 2490, 2893, 3173, 5316, 5412, 5727, 6123, 6613, 7290, 7572, 8023, 9114, 9105, 8656, 10645, 11290, 13223, 11507, 15489, 12328, 9338, 9517, 9795, 9596, 13162, 10168, 8013, 9949, 10654, 9932, 12222, 11287, 11623, 11971, 12577, 12207, 13886, 14160, 12200, 13207, 15943, 15320, 14290, 15933, 15463, 14281, 15457, 15302, 17929, 18106, 17058, 14844, 17740, 17916, 18640, 18093, 18638, }; #endif /* todo: unbalanced cutoffs */ int _gr_nmod_poly_sqrt_series(ulong * res, const ulong * f, slong flen, slong n, gr_ctx_t ctx) { slong cutoff; flen = FLINT_MIN(flen, n); cutoff = sqrt_series_cutoff_tab[NMOD_BITS(NMOD_CTX(ctx)) - 1]; if (flen < cutoff) return _gr_poly_sqrt_series_basecase(res, f, flen, n, ctx); else return _gr_poly_sqrt_series_newton(res, f, flen, n, cutoff, ctx); } #ifdef FLINT_HAVE_FFT_SMALL static const short exp_series_mul_cutoff_tab[] = { 470, 470, 470, 470, 470, 470, 470, 470, 470, 266, 266, 231, 279, 292, 292, 266, 266, 254, 266, 266, 448, 470, 470, 448, 448, 470, 493, 470, 337, 321, 427, 321, 292, 292, 292, 292, 292, 292, 279, 292, 292, 292, 279, 279, 292, 448, 448, 427, 448, 448, 448, 448, 448, 448, 427, 448, 427, 448, 448, 448, 353, 407, 407, 353, }; #else static const short exp_series_mul_cutoff_tab[] = { 4, 4, 6, 12, 18, 38, 56, 57, 97, 121, 144, 145, 187, 228, 216, 286, 315, 426, 505, 547, 620, 631, 649, 781, 931, 810, 950, 1066, 838, 714, 880, 931, 698, 598, 590, 620, 731, 782, 780, 848, 976, 1005, 978, 1006, 1046, 1040, 1203, 1296, 1342, 1327, 1389, 1555, 1568, 1644, 1676, 1725, 1692, 1793, 2014, 1904, 2021, 2086, 2030, 2198, }; #endif #ifdef FLINT_HAVE_FFT_SMALL static const short exp_series_newton_cutoff_tab[64] = { 470, 470, 470, 470, 470, 470, 517, 597, 689, 759, 689, 723, 626, 723, 723, 723, 723, 723, 723, 723, 1289, 1491, 1353, 1353, 1353, 1353, 1353, 1353, 964, 964, 1115, 1115, 835, 876, 876, 919, 876, 919, 919, 876, 919, 876, 835, 919, 919, 1228, 1170, 1289, 1228, 1228, 1353, 1353, 1353, 1228, 1228, 1228, 1289, 1353, 1228, 1170, 1115, 1115, 1170, 1353, }; #else static const short exp_series_newton_cutoff_tab[64] = { 4, 4, 6, 12, 18, 38, 68, 132, 258, 522, 1033, 1288, 1322, 1494, 1775, 2074, 2404, 2534, 2887, 3017, 3343, 3234, 3550, 4263, 3813, 4534, 5398, 4048, 3381, 3607, 3811, 3724, 2962, 3095, 3268, 3253, 3469, 3664, 4108, 4219, 4043, 4402, 4434, 4377, 4583, 4802, 5030, 5430, 5366, 5407, 5341, 6363, 6415, 6343, 6395, 6444, 6433, 6358, 6939, 6794, 6782, 6837, 6758, 6680, }; #endif int _gr_nmod_poly_exp_series(ulong * res, const ulong * f, slong flen, slong n, gr_ctx_t ctx) { slong cutoff1, cutoff2; flen = FLINT_MIN(flen, n); cutoff1 = exp_series_mul_cutoff_tab[NMOD_BITS(NMOD_CTX(ctx)) - 1]; if (flen < cutoff1) return _gr_poly_exp_series_basecase(res, f, flen, n, ctx); cutoff2 = exp_series_newton_cutoff_tab[NMOD_BITS(NMOD_CTX(ctx)) - 1]; if (flen < cutoff2) return _gr_poly_exp_series_basecase_mul(res, f, flen, n, ctx); return _gr_poly_exp_series_newton(res, NULL, f, flen, n, cutoff2, ctx); } int _gr_nmod_roots_gr_poly(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; { gr_poly_t z_poly; gr_vec_t z_roots; gr_ctx_t z_ctx; slong i; int status = GR_SUCCESS; fmpz_t t; fmpz_init(t); fmpz_set_ui(t, NMOD_CTX(ctx).n); gr_ctx_init_fmpz_mod(z_ctx, t); gr_poly_init(z_poly, z_ctx); gr_vec_init(z_roots, 0, z_ctx); status |= gr_poly_set_gr_poly_other(z_poly, poly, ctx, z_ctx); status |= gr_poly_roots(z_roots, mult, z_poly, flags, z_ctx); if (status == GR_SUCCESS) { gr_vec_set_length(roots, z_roots->length, ctx); for (i = 0; i < z_roots->length; i++) status |= gr_set_other(gr_vec_entry_ptr(roots, i, ctx), gr_vec_entry_ptr(z_roots, i, z_ctx), z_ctx, ctx); } gr_poly_clear(z_poly, z_ctx); gr_vec_clear(z_roots, z_ctx); gr_ctx_clear(z_ctx); fmpz_clear(t); return status; } } int _gr_nmod_mat_mul(gr_mat_t res, const gr_mat_t x, const gr_mat_t y, gr_ctx_t ctx) { nmod_mat_t R, X, Y; nmod_mat_struct *XX, *YY; R->entries = res->entries; R->rows = (mp_ptr *) res->rows; R->r = res->r; R->c = res->c; R->mod = NMOD_CTX(ctx); if (res == x) { XX = R; } else { X->entries = x->entries; X->rows = (mp_ptr *) x->rows; X->r = x->r; X->c = x->c; X->mod = NMOD_CTX(ctx); XX = X; } if (res == y) { YY = R; } else if (x == y) { YY = XX; } else { Y->entries = y->entries; Y->rows = (mp_ptr *) y->rows; Y->r = y->r; Y->c = y->c; Y->mod = NMOD_CTX(ctx); YY = Y; } nmod_mat_mul(R, XX, YY); return GR_SUCCESS; } int __gr_nmod_methods_initialized = 0; gr_static_method_table __gr_nmod_methods; gr_method_tab_input __gr_nmod_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_nmod_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) _gr_nmod_ctx_is_field}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) _gr_nmod_ctx_is_field}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_nmod_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_nmod_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_nmod_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_nmod_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_nmod_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_nmod_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_nmod_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_nmod_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_nmod_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_nmod_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_nmod_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_nmod_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_nmod_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_nmod_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_nmod_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_nmod_set_fmpz}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_nmod_set_other}, {GR_METHOD_NEG, (gr_funcptr) _gr_nmod_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_nmod_add}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_nmod_add_si}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_nmod_add_ui}, {GR_METHOD_SUB, (gr_funcptr) _gr_nmod_sub}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_nmod_sub_si}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_nmod_sub_ui}, {GR_METHOD_MUL, (gr_funcptr) _gr_nmod_mul}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_nmod_mul_si}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_nmod_mul_ui}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_nmod_mul_fmpz}, {GR_METHOD_ADDMUL, (gr_funcptr) _gr_nmod_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) _gr_nmod_submul}, {GR_METHOD_MUL_TWO, (gr_funcptr) _gr_nmod_mul_two}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) _gr_nmod_mul_2exp_si}, {GR_METHOD_SQR, (gr_funcptr) _gr_nmod_sqr}, {GR_METHOD_DIV, (gr_funcptr) _gr_nmod_div}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_nmod_div_si}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_nmod_div_ui}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_nmod_div_fmpz}, {GR_METHOD_DIV_NONUNIQUE, (gr_funcptr) _gr_nmod_div_nonunique}, {GR_METHOD_DIVIDES, (gr_funcptr) _gr_nmod_divides}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_nmod_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_nmod_inv}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_nmod_pow_ui}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_nmod_pow_fmpz}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_nmod_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_nmod_sqrt}, {GR_METHOD_VEC_INIT, (gr_funcptr) _gr_nmod_vec_init}, {GR_METHOD_VEC_CLEAR, (gr_funcptr) _gr_nmod_vec_clear}, {GR_METHOD_VEC_SET, (gr_funcptr) _gr_nmod_vec_set}, {GR_METHOD_VEC_NORMALISE, (gr_funcptr) _gr_nmod_vec_normalise}, {GR_METHOD_VEC_NORMALISE_WEAK, (gr_funcptr) _gr_nmod_vec_normalise_weak}, {GR_METHOD_VEC_NEG, (gr_funcptr) _gr_nmod_vec_neg}, {GR_METHOD_VEC_ADD, (gr_funcptr) _gr_nmod_vec_add}, {GR_METHOD_VEC_SUB, (gr_funcptr) _gr_nmod_vec_sub}, {GR_METHOD_VEC_MUL_SCALAR, (gr_funcptr) _gr_nmod_vec_mul_scalar}, {GR_METHOD_VEC_MUL_SCALAR_SI, (gr_funcptr) _gr_nmod_vec_mul_scalar_si}, {GR_METHOD_VEC_MUL_SCALAR_UI, (gr_funcptr) _gr_nmod_vec_mul_scalar_ui}, {GR_METHOD_VEC_MUL_SCALAR_FMPZ, (gr_funcptr) _gr_nmod_vec_mul_scalar_fmpz}, {GR_METHOD_VEC_MUL_SCALAR_2EXP_SI, (gr_funcptr) _gr_nmod_vec_mul_scalar_2exp_si}, {GR_METHOD_VEC_ADDMUL_SCALAR, (gr_funcptr) _gr_nmod_vec_addmul_scalar}, {GR_METHOD_VEC_ADDMUL_SCALAR_SI, (gr_funcptr) _gr_nmod_vec_addmul_scalar_si}, {GR_METHOD_VEC_SUBMUL_SCALAR, (gr_funcptr) _gr_nmod_vec_submul_scalar}, {GR_METHOD_VEC_SUBMUL_SCALAR_SI, (gr_funcptr) _gr_nmod_vec_submul_scalar_si}, {GR_METHOD_VEC_SUB, (gr_funcptr) _gr_nmod_vec_sub}, {GR_METHOD_VEC_SUM, (gr_funcptr) _gr_nmod_vec_sum}, {GR_METHOD_VEC_PRODUCT, (gr_funcptr) _gr_nmod_vec_product}, {GR_METHOD_VEC_DOT, (gr_funcptr) __gr_nmod_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) __gr_nmod_vec_dot_rev}, {GR_METHOD_VEC_RECIPROCALS, (gr_funcptr) _gr_nmod_vec_reciprocals}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_nmod_poly_mullow}, {GR_METHOD_POLY_DIVREM, (gr_funcptr) _gr_nmod_poly_divrem}, {GR_METHOD_POLY_DIVEXACT, (gr_funcptr) _gr_nmod_poly_divexact}, {GR_METHOD_POLY_INV_SERIES, (gr_funcptr) _gr_nmod_poly_inv_series}, {GR_METHOD_POLY_INV_SERIES_BASECASE, (gr_funcptr) _gr_nmod_poly_inv_series_basecase}, {GR_METHOD_POLY_DIV_SERIES, (gr_funcptr) _gr_nmod_poly_div_series}, {GR_METHOD_POLY_DIV_SERIES_BASECASE, (gr_funcptr) _gr_nmod_poly_div_series_basecase}, {GR_METHOD_POLY_RSQRT_SERIES, (gr_funcptr) _gr_nmod_poly_rsqrt_series}, {GR_METHOD_POLY_SQRT_SERIES, (gr_funcptr) _gr_nmod_poly_sqrt_series}, {GR_METHOD_POLY_EXP_SERIES, (gr_funcptr) _gr_nmod_poly_exp_series}, {GR_METHOD_POLY_ROOTS, (gr_funcptr) _gr_nmod_roots_gr_poly}, {GR_METHOD_MAT_MUL, (gr_funcptr) _gr_nmod_mat_mul}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_nmod(gr_ctx_t ctx, ulong n) { ctx->which_ring = GR_CTX_NMOD; ctx->sizeof_elem = sizeof(ulong); ctx->size_limit = WORD_MAX; NMOD_IS_PRIME(ctx) = T_UNKNOWN; nmod_init(NMOD_CTX_REF(ctx), n); ctx->methods = __gr_nmod_methods; if (!__gr_nmod_methods_initialized) { gr_method_tab_init(__gr_nmod_methods, __gr_nmod_methods_input); __gr_nmod_methods_initialized = 1; } } void _gr_ctx_init_nmod(gr_ctx_t ctx, void * nmod_t_ref) { ctx->which_ring = GR_CTX_NMOD; ctx->sizeof_elem = sizeof(ulong); ctx->size_limit = WORD_MAX; NMOD_IS_PRIME(ctx) = T_UNKNOWN; *NMOD_CTX_REF(ctx) = ((nmod_t *) nmod_t_ref)[0]; ctx->methods = __gr_nmod_methods; if (!__gr_nmod_methods_initialized) { gr_method_tab_init(__gr_nmod_methods, __gr_nmod_methods_input); __gr_nmod_methods_initialized = 1; } } void gr_ctx_nmod_set_primality(gr_ctx_t ctx, truth_t is_prime) { NMOD_IS_PRIME(ctx) = is_prime; } flint-3.1.3/src/gr/nmod32.c000066400000000000000000000337601461254215100153110ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq.h" #include "nmod.h" #include "nmod_vec.h" #include "gr.h" #include "gr_mat.h" #define NMOD32_CTX_REF(ring_ctx) (((nmod_t *)((ring_ctx)))) #define NMOD32_CTX(ring_ctx) (*NMOD32_CTX_REF(ring_ctx)) typedef unsigned int nmod32_struct; typedef nmod32_struct nmod32_t[1]; void nmod32_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Integers mod "); gr_stream_write_ui(out, NMOD32_CTX(ctx).n); gr_stream_write(out, " (nmod32)"); } /* we don't want to call n_is_prime because this predicate should be fast. allow storing a flag in the context object? */ truth_t nmod32_ctx_is_field(const gr_ctx_t ctx) { return T_UNKNOWN; } void nmod32_init(nmod32_t x, const gr_ctx_t ctx) { x[0] = 0; } void nmod32_clear(nmod32_t x, const gr_ctx_t ctx) { } void nmod32_swap(nmod32_t x, nmod32_t y, const gr_ctx_t ctx) { nmod32_t t; *t = *x; *x = *y; *y = *t; } void nmod32_set_shallow(nmod32_t res, const nmod32_t x, const gr_ctx_t ctx) { *res = *x; } int nmod32_randtest(nmod32_t res, flint_rand_t state, const gr_ctx_t ctx) { res[0] = n_randtest(state) % NMOD32_CTX(ctx).n; return GR_SUCCESS; } int nmod32_write(gr_stream_t out, const nmod32_t x, const gr_ctx_t ctx) { gr_stream_write_ui(out, x[0]); return GR_SUCCESS; } int nmod32_zero(nmod32_t x, const gr_ctx_t ctx) { x[0] = 0; return GR_SUCCESS; } int nmod32_one(nmod32_t x, const gr_ctx_t ctx) { x[0] = (NMOD32_CTX(ctx).n != 1); return GR_SUCCESS; } int nmod32_set_si(nmod32_t res, slong v, const gr_ctx_t ctx) { ulong t; nmod_t mod = NMOD32_CTX(ctx); t = FLINT_ABS(v); NMOD_RED(t, t, mod); if (v < 0) t = nmod_neg(t, mod); res[0] = t; return GR_SUCCESS; } int nmod32_set_ui(nmod32_t res, ulong v, const gr_ctx_t ctx) { ulong t; nmod_t mod = NMOD32_CTX(ctx); NMOD_RED(t, v, mod); res[0] = t; return GR_SUCCESS; } int nmod32_set_fmpz(nmod32_t res, const fmpz_t v, const gr_ctx_t ctx) { nmod_t mod = NMOD32_CTX(ctx); res[0] = fmpz_get_nmod(v, mod); return GR_SUCCESS; } truth_t nmod32_is_zero(const nmod32_t x, const gr_ctx_t ctx) { return (x[0] == 0) ? T_TRUE : T_FALSE; } truth_t nmod32_is_one(const nmod32_t x, const gr_ctx_t ctx) { return (x[0] == (NMOD32_CTX(ctx).n != 1)) ? T_TRUE : T_FALSE; } truth_t nmod32_is_neg_one(const nmod32_t x, const gr_ctx_t ctx) { return (x[0] == NMOD32_CTX(ctx).n - 1) ? T_TRUE : T_FALSE; } truth_t nmod32_equal(const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { return (x[0] == y[0]) ? T_TRUE : T_FALSE; } int nmod32_set(nmod32_t res, const nmod32_t x, const gr_ctx_t ctx) { res[0] = x[0]; return GR_SUCCESS; } int nmod32_neg(nmod32_t res, const nmod32_t x, const gr_ctx_t ctx) { res[0] = nmod_neg(x[0], NMOD32_CTX(ctx)); return GR_SUCCESS; } int nmod32_add(nmod32_t res, const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { res[0] = nmod_add(x[0], y[0], NMOD32_CTX(ctx)); return GR_SUCCESS; } int nmod32_add_si(nmod32_t res, const nmod32_t x, slong y, const gr_ctx_t ctx) { nmod32_t t; nmod32_set_si(t, y, ctx); return nmod32_add(res, x, t, ctx); } int nmod32_sub(nmod32_t res, const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { res[0] = nmod_sub(x[0], y[0], NMOD32_CTX(ctx)); return GR_SUCCESS; } int nmod32_mul(nmod32_t res, const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { res[0] = nmod_mul(x[0], y[0], NMOD32_CTX(ctx)); return GR_SUCCESS; } int nmod32_mul_si(nmod32_t res, const nmod32_t x, slong y, const gr_ctx_t ctx) { nmod32_t t; nmod32_set_si(t, y, ctx); return nmod32_mul(res, x, t, ctx); } int nmod32_addmul(nmod32_t res, const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { ulong r = res[0]; NMOD_ADDMUL(r, x[0], y[0], NMOD32_CTX(ctx)); res[0] = r; return GR_SUCCESS; } int nmod32_submul(nmod32_t res, const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { ulong r = res[0]; ulong t = nmod_neg(y[0], NMOD32_CTX(ctx)); NMOD_ADDMUL(r, x[0], t, NMOD32_CTX(ctx)); res[0] = r; return GR_SUCCESS; } int nmod32_mul_two(nmod32_t res, const nmod32_t x, const gr_ctx_t ctx) { return nmod32_add(res, x, x, ctx); } int nmod32_sqr(nmod32_t res, const nmod32_t x, const gr_ctx_t ctx) { return nmod32_mul(res, x, x, ctx); } int nmod32_inv(nmod32_t res, const nmod32_t x, const gr_ctx_t ctx) { ulong r, g; /* todo: also handle -1 fast? */ if (x[0] == 1) { res[0] = x[0]; return GR_SUCCESS; } g = n_gcdinv(&r, x[0], NMOD32_CTX(ctx).n); if (g == 1) { res[0] = r; return GR_SUCCESS; } else { res[0] = 0; return GR_DOMAIN; } } int nmod32_div(nmod32_t res, const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { nmod32_t t; int status; status = nmod32_inv(t, y, ctx); if (status == GR_SUCCESS) nmod32_mul(res, x, t, ctx); return status; } int nmod32_div_si(nmod32_t res, const nmod32_t x, slong y, const gr_ctx_t ctx) { nmod32_t t; nmod32_set_si(t, y, ctx); return nmod32_div(res, x, t, ctx); } int nmod32_div_ui(nmod32_t res, const nmod32_t x, ulong y, const gr_ctx_t ctx) { nmod32_t t; nmod32_set_ui(t, y, ctx); return nmod32_div(res, x, t, ctx); } int nmod32_div_fmpz(nmod32_t res, const nmod32_t x, const fmpz_t y, const gr_ctx_t ctx) { nmod32_t t; nmod32_set_fmpz(t, y, ctx); return nmod32_div(res, x, t, ctx); } truth_t nmod32_is_invertible(const nmod32_t x, const gr_ctx_t ctx) { ulong r, g; g = n_gcdinv(&r, x[0], NMOD32_CTX(ctx).n); return (g == 1) ? T_TRUE : T_FALSE; } truth_t nmod32_divides(const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { ulong t; return nmod_divides(&t, y[0], x[0], NMOD32_CTX(ctx)) ? T_TRUE : T_FALSE; } int nmod32_div_nonunique(nmod32_t res, const nmod32_t x, const nmod32_t y, const gr_ctx_t ctx) { nmod32_t t; int status; status = nmod32_inv(t, y, ctx); if (status == GR_SUCCESS) { nmod32_mul(res, x, t, ctx); } else { ulong t2; status = nmod_divides(&t2, x[0], y[0], NMOD32_CTX(ctx)) ? GR_SUCCESS : GR_DOMAIN; res[0] = t2; } return status; } void _nmod32_vec_init(nmod32_struct * res, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) res[i] = 0; } void _nmod32_vec_clear(nmod32_struct * res, slong len, gr_ctx_t ctx) { } int _nmod32_vec_set(nmod32_struct * res, const nmod32_struct * vec, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) res[i] = vec[i]; return GR_SUCCESS; } int _nmod32_vec_neg(nmod32_struct * res, const nmod32_struct * vec, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD32_CTX(ctx); for (i = 0; i < len; i++) res[i] = nmod_neg(vec[i], mod); return GR_SUCCESS; } int _nmod32_vec_add(nmod32_struct * res, const nmod32_struct * vec1, const nmod32_struct * vec2, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD32_CTX(ctx); for (i = 0; i < len; i++) #if FLINT_BITS == 64 res[i] = _nmod_add(vec1[i], vec2[i], mod); #else res[i] = nmod_add(vec1[i], vec2[i], mod); #endif return GR_SUCCESS; } int _nmod32_vec_sub(nmod32_struct * res, const nmod32_struct * vec1, const nmod32_struct * vec2, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD32_CTX(ctx); for (i = 0; i < len; i++) #if FLINT_BITS == 64 res[i] = _nmod_sub(vec1[i], vec2[i], mod); #else res[i] = nmod_sub(vec1[i], vec2[i], mod); #endif return GR_SUCCESS; } /* todo: overflow checks */ int _nmod32_vec_dot(nmod32_t res, const nmod32_t initial, int subtract, const nmod32_struct * vec1, const nmod32_struct * vec2, slong len, gr_ctx_t ctx) { slong i; ulong n, s; if (len <= 0) { if (initial == NULL) nmod32_zero(res, ctx); else nmod32_set(res, initial, ctx); return GR_SUCCESS; } n = NMOD32_CTX(ctx).n; if (initial == NULL) { s = 0; } else { if (subtract) s = n_negmod(initial[0], n); else s = initial[0]; } { ulong ss; int nlimbs; nlimbs = _nmod_vec_dot_bound_limbs(len, NMOD32_CTX(ctx)); NMOD_VEC_DOT(ss, i, len, (ulong) vec1[i], (ulong) vec2[i], NMOD32_CTX(ctx), nlimbs); s = n_addmod(s, ss, n); } nmod32_set_ui(res, s, ctx); if (subtract && res[0] != 0) res[0] = (n - res[0]); return GR_SUCCESS; } /* todo: overflow checks */ int _nmod32_vec_dot_rev(nmod32_t res, const nmod32_t initial, int subtract, const nmod32_struct * vec1, const nmod32_struct * vec2, slong len, gr_ctx_t ctx) { slong i; ulong n, s; if (len <= 0) { if (initial == NULL) nmod32_zero(res, ctx); else nmod32_set(res, initial, ctx); return GR_SUCCESS; } n = NMOD32_CTX(ctx).n; if (initial == NULL) { s = 0; } else { if (subtract) s = n_negmod(initial[0], n); else s = initial[0]; } { ulong ss; int nlimbs; nlimbs = _nmod_vec_dot_bound_limbs(len, NMOD32_CTX(ctx)); NMOD_VEC_DOT(ss, i, len, (ulong) vec1[i], (ulong) vec2[len - 1 - i], NMOD32_CTX(ctx), nlimbs); s = n_addmod(s, ss, n); } nmod32_set_ui(res, s, ctx); if (subtract && res[0] != 0) res[0] = (n - res[0]); return GR_SUCCESS; } /* todo: tuning for rectangular matrices */ int _nmod32_mat_mul(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { if (A->r >= 256 && A->c >= 256 && B->c >= 256) return gr_mat_mul_strassen(C, A, B, ctx); else return gr_mat_mul_classical(C, A, B, ctx); } int _nmod32_methods_initialized = 0; gr_static_method_table _nmod32_methods; gr_method_tab_input _nmod32_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) nmod32_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) nmod32_ctx_is_field}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) nmod32_ctx_is_field}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) nmod32_init}, {GR_METHOD_CLEAR, (gr_funcptr) nmod32_clear}, {GR_METHOD_SWAP, (gr_funcptr) nmod32_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) nmod32_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) nmod32_randtest}, {GR_METHOD_WRITE, (gr_funcptr) nmod32_write}, {GR_METHOD_ZERO, (gr_funcptr) nmod32_zero}, {GR_METHOD_ONE, (gr_funcptr) nmod32_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) nmod32_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) nmod32_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) nmod32_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) nmod32_equal}, {GR_METHOD_SET, (gr_funcptr) nmod32_set}, {GR_METHOD_SET_SI, (gr_funcptr) nmod32_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) nmod32_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) nmod32_set_fmpz}, {GR_METHOD_NEG, (gr_funcptr) nmod32_neg}, {GR_METHOD_ADD, (gr_funcptr) nmod32_add}, {GR_METHOD_ADD_SI, (gr_funcptr) nmod32_add_si}, {GR_METHOD_SUB, (gr_funcptr) nmod32_sub}, {GR_METHOD_MUL, (gr_funcptr) nmod32_mul}, {GR_METHOD_MUL_SI, (gr_funcptr) nmod32_mul_si}, {GR_METHOD_ADDMUL, (gr_funcptr) nmod32_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) nmod32_submul}, {GR_METHOD_MUL_TWO, (gr_funcptr) nmod32_mul_two}, {GR_METHOD_SQR, (gr_funcptr) nmod32_sqr}, {GR_METHOD_DIV, (gr_funcptr) nmod32_div}, {GR_METHOD_DIV_SI, (gr_funcptr) nmod32_div_si}, {GR_METHOD_DIV_UI, (gr_funcptr) nmod32_div_ui}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) nmod32_div_fmpz}, {GR_METHOD_DIV_NONUNIQUE, (gr_funcptr) nmod32_div_nonunique}, {GR_METHOD_DIVIDES, (gr_funcptr) nmod32_divides}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) nmod32_is_invertible}, {GR_METHOD_INV, (gr_funcptr) nmod32_inv}, {GR_METHOD_VEC_INIT, (gr_funcptr) _nmod32_vec_init}, {GR_METHOD_VEC_CLEAR, (gr_funcptr) _nmod32_vec_clear}, {GR_METHOD_VEC_SET, (gr_funcptr) _nmod32_vec_set}, {GR_METHOD_VEC_NEG, (gr_funcptr) _nmod32_vec_neg}, {GR_METHOD_VEC_ADD, (gr_funcptr) _nmod32_vec_add}, {GR_METHOD_VEC_SUB, (gr_funcptr) _nmod32_vec_sub}, {GR_METHOD_VEC_DOT, (gr_funcptr) _nmod32_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _nmod32_vec_dot_rev}, {GR_METHOD_MAT_MUL, (gr_funcptr) _nmod32_mat_mul}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_nmod32(gr_ctx_t ctx, unsigned int n) { ctx->which_ring = GR_CTX_NMOD32; ctx->sizeof_elem = sizeof(nmod32_struct); ctx->size_limit = WORD_MAX; nmod_init(NMOD32_CTX_REF(ctx), n); ctx->methods = _nmod32_methods; if (!_nmod32_methods_initialized) { gr_method_tab_init(_nmod32_methods, _nmod32_methods_input); _nmod32_methods_initialized = 1; } } flint-3.1.3/src/gr/nmod8.c000066400000000000000000000352221461254215100152270ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq.h" #include "nmod.h" #include "nmod_vec.h" #include "gr.h" #include "gr_mat.h" #define NMOD8_CTX_REF(ring_ctx) (((nmod_t *)((ring_ctx)))) #define NMOD8_CTX(ring_ctx) (*NMOD8_CTX_REF(ring_ctx)) typedef unsigned char nmod8_struct; typedef nmod8_struct nmod8_t[1]; void nmod8_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Integers mod "); gr_stream_write_ui(out, NMOD8_CTX(ctx).n); gr_stream_write(out, " (nmod8)"); } /* todo: n_is_prime is fast, but this should still be cached or use a fixed table lookup */ truth_t nmod8_ctx_is_field(const gr_ctx_t ctx) { return n_is_prime(NMOD8_CTX(ctx).n) ? T_TRUE : T_FALSE; } void nmod8_init(nmod8_t x, const gr_ctx_t ctx) { x[0] = 0; } void nmod8_clear(nmod8_t x, const gr_ctx_t ctx) { } void nmod8_swap(nmod8_t x, nmod8_t y, const gr_ctx_t ctx) { nmod8_t t; *t = *x; *x = *y; *y = *t; } void nmod8_set_shallow(nmod8_t res, const nmod8_t x, const gr_ctx_t ctx) { *res = *x; } int nmod8_randtest(nmod8_t res, flint_rand_t state, const gr_ctx_t ctx) { res[0] = n_randtest(state) % NMOD8_CTX(ctx).n; return GR_SUCCESS; } int nmod8_write(gr_stream_t out, const nmod8_t x, const gr_ctx_t ctx) { gr_stream_write_ui(out, x[0]); return GR_SUCCESS; } int nmod8_zero(nmod8_t x, const gr_ctx_t ctx) { x[0] = 0; return GR_SUCCESS; } int nmod8_one(nmod8_t x, const gr_ctx_t ctx) { x[0] = (NMOD8_CTX(ctx).n != 1); return GR_SUCCESS; } int nmod8_set_si(nmod8_t res, slong v, const gr_ctx_t ctx) { ulong t; nmod_t mod = NMOD8_CTX(ctx); t = FLINT_ABS(v); NMOD_RED(t, t, mod); if (v < 0) t = nmod_neg(t, mod); res[0] = t; return GR_SUCCESS; } int nmod8_set_ui(nmod8_t res, ulong v, const gr_ctx_t ctx) { ulong t; nmod_t mod = NMOD8_CTX(ctx); NMOD_RED(t, v, mod); res[0] = t; return GR_SUCCESS; } int nmod8_set_fmpz(nmod8_t res, const fmpz_t v, const gr_ctx_t ctx) { nmod_t mod = NMOD8_CTX(ctx); res[0] = fmpz_get_nmod(v, mod); return GR_SUCCESS; } truth_t nmod8_is_zero(const nmod8_t x, const gr_ctx_t ctx) { return (x[0] == 0) ? T_TRUE : T_FALSE; } truth_t nmod8_is_one(const nmod8_t x, const gr_ctx_t ctx) { return (x[0] == (NMOD8_CTX(ctx).n != 1)) ? T_TRUE : T_FALSE; } truth_t nmod8_is_neg_one(const nmod8_t x, const gr_ctx_t ctx) { return (x[0] == NMOD8_CTX(ctx).n - 1) ? T_TRUE : T_FALSE; } truth_t nmod8_equal(const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { return (x[0] == y[0]) ? T_TRUE : T_FALSE; } int nmod8_set(nmod8_t res, const nmod8_t x, const gr_ctx_t ctx) { res[0] = x[0]; return GR_SUCCESS; } int nmod8_neg(nmod8_t res, const nmod8_t x, const gr_ctx_t ctx) { res[0] = nmod_neg(x[0], NMOD8_CTX(ctx)); return GR_SUCCESS; } int nmod8_add(nmod8_t res, const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { res[0] = nmod_add(x[0], y[0], NMOD8_CTX(ctx)); return GR_SUCCESS; } int nmod8_add_si(nmod8_t res, const nmod8_t x, slong y, const gr_ctx_t ctx) { nmod8_t t; nmod8_set_si(t, y, ctx); return nmod8_add(res, x, t, ctx); } int nmod8_sub(nmod8_t res, const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { res[0] = nmod_sub(x[0], y[0], NMOD8_CTX(ctx)); return GR_SUCCESS; } int nmod8_mul(nmod8_t res, const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { res[0] = nmod_mul(x[0], y[0], NMOD8_CTX(ctx)); return GR_SUCCESS; } int nmod8_mul_si(nmod8_t res, const nmod8_t x, slong y, const gr_ctx_t ctx) { nmod8_t t; nmod8_set_si(t, y, ctx); return nmod8_mul(res, x, t, ctx); } int nmod8_addmul(nmod8_t res, const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { ulong r = res[0]; NMOD_ADDMUL(r, x[0], y[0], NMOD8_CTX(ctx)); res[0] = r; return GR_SUCCESS; } int nmod8_submul(nmod8_t res, const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { ulong r = res[0]; ulong t = nmod_neg(y[0], NMOD8_CTX(ctx)); NMOD_ADDMUL(r, x[0], t, NMOD8_CTX(ctx)); res[0] = r; return GR_SUCCESS; } int nmod8_mul_two(nmod8_t res, const nmod8_t x, const gr_ctx_t ctx) { return nmod8_add(res, x, x, ctx); } int nmod8_sqr(nmod8_t res, const nmod8_t x, const gr_ctx_t ctx) { return nmod8_mul(res, x, x, ctx); } int nmod8_inv(nmod8_t res, const nmod8_t x, const gr_ctx_t ctx) { ulong r, g; /* todo: also handle -1 fast? */ if (x[0] == 1) { res[0] = x[0]; return GR_SUCCESS; } g = n_gcdinv(&r, x[0], NMOD8_CTX(ctx).n); if (g == 1) { res[0] = r; return GR_SUCCESS; } else { res[0] = 0; return GR_DOMAIN; } } int nmod8_div(nmod8_t res, const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { nmod8_t t; int status; status = nmod8_inv(t, y, ctx); if (status == GR_SUCCESS) nmod8_mul(res, x, t, ctx); return status; } int nmod8_div_si(nmod8_t res, const nmod8_t x, slong y, const gr_ctx_t ctx) { nmod8_t t; nmod8_set_si(t, y, ctx); return nmod8_div(res, x, t, ctx); } int nmod8_div_ui(nmod8_t res, const nmod8_t x, ulong y, const gr_ctx_t ctx) { nmod8_t t; nmod8_set_ui(t, y, ctx); return nmod8_div(res, x, t, ctx); } int nmod8_div_fmpz(nmod8_t res, const nmod8_t x, const fmpz_t y, const gr_ctx_t ctx) { nmod8_t t; nmod8_set_fmpz(t, y, ctx); return nmod8_div(res, x, t, ctx); } truth_t nmod8_is_invertible(const nmod8_t x, const gr_ctx_t ctx) { ulong r, g; g = n_gcdinv(&r, x[0], NMOD8_CTX(ctx).n); return (g == 1) ? T_TRUE : T_FALSE; } truth_t nmod8_divides(const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { ulong t; return nmod_divides(&t, y[0], x[0], NMOD8_CTX(ctx)) ? T_TRUE : T_FALSE; } int nmod8_div_nonunique(nmod8_t res, const nmod8_t x, const nmod8_t y, const gr_ctx_t ctx) { nmod8_t t; int status; status = nmod8_inv(t, y, ctx); if (status == GR_SUCCESS) { nmod8_mul(res, x, t, ctx); } else { ulong t2; status = nmod_divides(&t2, x[0], y[0], NMOD8_CTX(ctx)) ? GR_SUCCESS : GR_DOMAIN; res[0] = t2; } return status; } void _nmod8_vec_init(nmod8_struct * res, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) res[i] = 0; } void _nmod8_vec_clear(nmod8_struct * res, slong len, gr_ctx_t ctx) { } int _nmod8_vec_set(nmod8_struct * res, const nmod8_struct * vec, slong len, gr_ctx_t ctx) { slong i; for (i = 0; i < len; i++) res[i] = vec[i]; return GR_SUCCESS; } int _nmod8_vec_neg(nmod8_struct * res, const nmod8_struct * vec, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD8_CTX(ctx); for (i = 0; i < len; i++) res[i] = nmod_neg(vec[i], mod); return GR_SUCCESS; } int _nmod8_vec_add(nmod8_struct * res, const nmod8_struct * vec1, const nmod8_struct * vec2, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD8_CTX(ctx); for (i = 0; i < len; i++) res[i] = _nmod_add(vec1[i], vec2[i], mod); return GR_SUCCESS; } int _nmod8_vec_sub(nmod8_struct * res, const nmod8_struct * vec1, const nmod8_struct * vec2, slong len, gr_ctx_t ctx) { slong i; nmod_t mod = NMOD8_CTX(ctx); for (i = 0; i < len; i++) res[i] = nmod_sub(vec1[i], vec2[i], mod); return GR_SUCCESS; } int _nmod8_vec_dot(nmod8_t res, const nmod8_t initial, int subtract, const nmod8_struct * vec1, const nmod8_struct * vec2, slong len, gr_ctx_t ctx) { slong i; ulong n, s; if (len <= 0) { if (initial == NULL) nmod8_zero(res, ctx); else nmod8_set(res, initial, ctx); return GR_SUCCESS; } n = NMOD8_CTX(ctx).n; if (initial == NULL) { s = 0; } else { if (subtract) s = n_negmod(initial[0], n); else s = initial[0]; } if (len < 65536) { unsigned int ss = 0; for (i = 0; i + 4 < len; i += 4) { s += (unsigned int) vec1[i + 0] * (unsigned int) vec2[i + 0]; s += (unsigned int) vec1[i + 1] * (unsigned int) vec2[i + 1]; s += (unsigned int) vec1[i + 2] * (unsigned int) vec2[i + 2]; s += (unsigned int) vec1[i + 3] * (unsigned int) vec2[i + 3]; } for ( ; i < len; i++) s += (unsigned int) vec1[i] * (unsigned int) vec2[i]; s += ss; } else { ulong ss; int nlimbs; nlimbs = _nmod_vec_dot_bound_limbs(len, NMOD8_CTX(ctx)); NMOD_VEC_DOT(ss, i, len, (ulong) vec1[i], (ulong) vec2[i], NMOD8_CTX(ctx), nlimbs); s = n_addmod(s, ss, n); } nmod8_set_ui(res, s, ctx); if (subtract && res[0] != 0) res[0] = (n - res[0]); return GR_SUCCESS; } int _nmod8_vec_dot_rev(nmod8_t res, const nmod8_t initial, int subtract, const nmod8_struct * vec1, const nmod8_struct * vec2, slong len, gr_ctx_t ctx) { slong i; ulong n, s; if (len <= 0) { if (initial == NULL) nmod8_zero(res, ctx); else nmod8_set(res, initial, ctx); return GR_SUCCESS; } n = NMOD8_CTX(ctx).n; if (initial == NULL) { s = 0; } else { if (subtract) s = n_negmod(initial[0], n); else s = initial[0]; } if (len < 65536) { unsigned int ss = 0; for (i = 0; i + 4 < len; i += 4) { s += (unsigned int) vec1[i + 0] * (unsigned int) vec2[len - 1 - i - 0]; s += (unsigned int) vec1[i + 1] * (unsigned int) vec2[len - 1 - i - 1]; s += (unsigned int) vec1[i + 2] * (unsigned int) vec2[len - 1 - i - 2]; s += (unsigned int) vec1[i + 3] * (unsigned int) vec2[len - 1 - i - 3]; } for ( ; i < len; i++) s += (unsigned int) vec1[i] * (unsigned int) vec2[len - 1 - i]; s += ss; } else { ulong ss; int nlimbs; nlimbs = _nmod_vec_dot_bound_limbs(len, NMOD8_CTX(ctx)); NMOD_VEC_DOT(ss, i, len, (ulong) vec1[i], (ulong) vec2[len - 1 - i], NMOD8_CTX(ctx), nlimbs); s = n_addmod(s, ss, n); } nmod8_set_ui(res, s, ctx); if (subtract && res[0] != 0) res[0] = (n - res[0]); return GR_SUCCESS; } /* todo: tuning for rectangular matrices */ int _nmod8_mat_mul(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { if (A->r >= 256 && A->c >= 256 && B->c >= 256) return gr_mat_mul_strassen(C, A, B, ctx); else return gr_mat_mul_classical(C, A, B, ctx); } int _nmod8_methods_initialized = 0; gr_static_method_table _nmod8_methods; gr_method_tab_input _nmod8_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) nmod8_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) nmod8_ctx_is_field}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) nmod8_ctx_is_field}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) nmod8_init}, {GR_METHOD_CLEAR, (gr_funcptr) nmod8_clear}, {GR_METHOD_SWAP, (gr_funcptr) nmod8_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) nmod8_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) nmod8_randtest}, {GR_METHOD_WRITE, (gr_funcptr) nmod8_write}, {GR_METHOD_ZERO, (gr_funcptr) nmod8_zero}, {GR_METHOD_ONE, (gr_funcptr) nmod8_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) nmod8_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) nmod8_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) nmod8_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) nmod8_equal}, {GR_METHOD_SET, (gr_funcptr) nmod8_set}, {GR_METHOD_SET_SI, (gr_funcptr) nmod8_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) nmod8_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) nmod8_set_fmpz}, {GR_METHOD_NEG, (gr_funcptr) nmod8_neg}, {GR_METHOD_ADD, (gr_funcptr) nmod8_add}, {GR_METHOD_ADD_SI, (gr_funcptr) nmod8_add_si}, {GR_METHOD_SUB, (gr_funcptr) nmod8_sub}, {GR_METHOD_MUL, (gr_funcptr) nmod8_mul}, {GR_METHOD_MUL_SI, (gr_funcptr) nmod8_mul_si}, {GR_METHOD_ADDMUL, (gr_funcptr) nmod8_addmul}, {GR_METHOD_SUBMUL, (gr_funcptr) nmod8_submul}, {GR_METHOD_MUL_TWO, (gr_funcptr) nmod8_mul_two}, {GR_METHOD_SQR, (gr_funcptr) nmod8_sqr}, {GR_METHOD_DIV, (gr_funcptr) nmod8_div}, {GR_METHOD_DIV_SI, (gr_funcptr) nmod8_div_si}, {GR_METHOD_DIV_UI, (gr_funcptr) nmod8_div_ui}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) nmod8_div_fmpz}, {GR_METHOD_DIV_NONUNIQUE, (gr_funcptr) nmod8_div_nonunique}, {GR_METHOD_DIVIDES, (gr_funcptr) nmod8_divides}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) nmod8_is_invertible}, {GR_METHOD_INV, (gr_funcptr) nmod8_inv}, {GR_METHOD_VEC_INIT, (gr_funcptr) _nmod8_vec_init}, {GR_METHOD_VEC_CLEAR, (gr_funcptr) _nmod8_vec_clear}, {GR_METHOD_VEC_SET, (gr_funcptr) _nmod8_vec_set}, {GR_METHOD_VEC_NEG, (gr_funcptr) _nmod8_vec_neg}, {GR_METHOD_VEC_ADD, (gr_funcptr) _nmod8_vec_add}, {GR_METHOD_VEC_SUB, (gr_funcptr) _nmod8_vec_sub}, {GR_METHOD_VEC_DOT, (gr_funcptr) _nmod8_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) _nmod8_vec_dot_rev}, {GR_METHOD_MAT_MUL, (gr_funcptr) _nmod8_mat_mul}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_nmod8(gr_ctx_t ctx, unsigned char n) { ctx->which_ring = GR_CTX_NMOD8; ctx->sizeof_elem = sizeof(nmod8_struct); ctx->size_limit = WORD_MAX; nmod_init(NMOD8_CTX_REF(ctx), n); ctx->methods = _nmod8_methods; if (!_nmod8_methods_initialized) { gr_method_tab_init(_nmod8_methods, _nmod8_methods_input); _nmod8_methods_initialized = 1; } } flint-3.1.3/src/gr/perm.c000066400000000000000000000137771461254215100151600ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "fmpz.h" #include "fmpz_mat.h" #include "gr.h" #define PERM_N(ctx) (*((ulong *) (ctx))) typedef struct { slong * entries; } perm_struct; typedef perm_struct perm_t[1]; int _gr_perm_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Symmetric group S_"); gr_stream_write_ui(out, PERM_N(ctx)); gr_stream_write(out, " (perm)"); return GR_SUCCESS; } int _gr_perm_init(perm_t res, gr_ctx_t ctx) { res->entries = _perm_init(PERM_N(ctx)); return GR_SUCCESS; } int _gr_perm_clear(perm_t res, gr_ctx_t ctx) { _perm_clear(res->entries); return GR_SUCCESS; } void _gr_perm_swap(perm_t x, perm_t y, gr_ctx_t ctx) { perm_struct t = *x; *x = *y; *y = t; } int _gr_perm_write(gr_stream_t out, perm_t x, gr_ctx_t ctx) { slong i; gr_stream_write(out, "["); for (i = 0; i < PERM_N(ctx); i++) { gr_stream_write_si(out, x->entries[i]); if (i + 1 < PERM_N(ctx)) gr_stream_write(out, ", "); } gr_stream_write(out, "]"); return GR_SUCCESS; } int _gr_perm_randtest(perm_t res, flint_rand_t state, gr_ctx_t ctx) { _perm_randtest(res->entries, PERM_N(ctx), state); return GR_SUCCESS; } truth_t _gr_perm_equal(const perm_t x, const perm_t y, gr_ctx_t ctx) { return _perm_equal(x->entries, y->entries, PERM_N(ctx)) ? T_TRUE : T_FALSE; } int _gr_perm_set(perm_t res, const perm_t x, gr_ctx_t ctx) { _perm_set(res->entries, x->entries, PERM_N(ctx)); return GR_SUCCESS; } int _gr_perm_set_other(perm_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { if (x_ctx->which_ring == GR_CTX_PERM) { if (PERM_N(x_ctx) == PERM_N(ctx)) return _gr_perm_set(res, x, ctx); return GR_DOMAIN; } else if (x_ctx->which_ring == GR_CTX_GR_MAT && MATRIX_CTX(x_ctx)->base_ring->which_ring == GR_CTX_FMPZ) { slong i, j, n, c; const fmpz_mat_struct * mat = x; n = PERM_N(ctx); /* todo: factor out mat_is_permutation method */ if (fmpz_mat_nrows(mat) != n || fmpz_mat_ncols(mat) != n) return GR_DOMAIN; for (i = 0; i < n; i++) { c = 0; for (j = 0; j < n; j++) { if (fmpz_is_zero(fmpz_mat_entry(mat, i, j))) continue; c++; if (c != 1 || !fmpz_is_one(fmpz_mat_entry(mat, i, j))) return GR_DOMAIN; } if (c == 0) return GR_DOMAIN; } for (i = 0; i < n; i++) { c = 0; for (j = 0; j < n; j++) { if (fmpz_is_zero(fmpz_mat_entry(mat, j, i))) continue; c++; if (c != 1) return GR_DOMAIN; } if (c == 0) return GR_DOMAIN; } for (i = 0; i < n; i++) for (j = 0; j < n; j++) { if (fmpz_is_one(fmpz_mat_entry(mat, i, j))) { res->entries[i] = j; break; } } return GR_SUCCESS; } else { return GR_UNABLE; } } int _gr_perm_one(perm_t res, gr_ctx_t ctx) { _perm_one(res->entries, PERM_N(ctx)); return GR_SUCCESS; } truth_t _gr_perm_is_one(const perm_t x, gr_ctx_t ctx) { slong i, n = PERM_N(ctx); for (i = 0; i < n; i++) if (x->entries[i] != i) return T_FALSE; return T_UNKNOWN; } int _gr_perm_mul(perm_t res, const perm_t x, const perm_t y, gr_ctx_t ctx) { _perm_compose(res->entries, x->entries, y->entries, PERM_N(ctx)); return GR_SUCCESS; } /* todo: should be generic. also want left division */ int _gr_perm_div(perm_t res, const perm_t x, const perm_t y, gr_ctx_t ctx) { slong n = PERM_N(ctx); slong * t; t = _perm_init(n); _perm_inv(t, y->entries, n); _perm_compose(res->entries, x->entries, t, n); _perm_clear(t); return GR_SUCCESS; } int _gr_perm_inv(perm_t res, const perm_t x, gr_ctx_t ctx) { _perm_inv(res->entries, x->entries, PERM_N(ctx)); return GR_SUCCESS; } /* todo: parity */ int _perm_methods_initialized = 0; gr_static_method_table _perm_methods; gr_method_tab_input _perm_methods_input[] = { {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_MULTIPLICATIVE_GROUP, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_perm_ctx_write}, {GR_METHOD_INIT, (gr_funcptr) _gr_perm_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_perm_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_perm_swap}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_perm_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_perm_write}, {GR_METHOD_ONE, (gr_funcptr) _gr_perm_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_perm_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_perm_set}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_perm_set_other}, {GR_METHOD_MUL, (gr_funcptr) _gr_perm_mul}, {GR_METHOD_INV, (gr_funcptr) _gr_perm_inv}, {GR_METHOD_DIV, (gr_funcptr) _gr_perm_div}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_perm(gr_ctx_t ctx, ulong n) { ctx->which_ring = GR_CTX_PERM; ctx->sizeof_elem = sizeof(perm_struct); ctx->size_limit = WORD_MAX; PERM_N(ctx) = n; ctx->methods = _perm_methods; if (!_perm_methods_initialized) { gr_method_tab_init(_perm_methods, _perm_methods_input); _perm_methods_initialized = 1; } } flint-3.1.3/src/gr/polynomial.c000066400000000000000000000402611461254215100163640ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Polynomials over generic rings */ #include #include #include "fmpz.h" #include "ulong_extras.h" #include "gr.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_generic.h" #ifdef __GNUC__ # define strcmp __builtin_strcmp #else # include #endif static const char * default_var = "x"; void polynomial_init(gr_poly_t res, gr_ctx_t ctx) { gr_poly_init(res, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Ring of polynomials over "); gr_ctx_write(out, POLYNOMIAL_ELEM_CTX(ctx)); return GR_SUCCESS; } int _gr_gr_poly_ctx_set_gen_name(gr_ctx_t ctx, const char * s) { slong len; len = strlen(s); if (POLYNOMIAL_CTX(ctx)->var == default_var) POLYNOMIAL_CTX(ctx)->var = NULL; POLYNOMIAL_CTX(ctx)->var = flint_realloc(POLYNOMIAL_CTX(ctx)->var, len + 1); memcpy(POLYNOMIAL_CTX(ctx)->var, s, len + 1); return GR_SUCCESS; } void polynomial_ctx_clear(gr_ctx_t ctx) { if (POLYNOMIAL_CTX(ctx)->var != default_var) { flint_free(POLYNOMIAL_CTX(ctx)->var); } } truth_t polynomial_ctx_is_ring(gr_ctx_t ctx) { return gr_ctx_is_ring(POLYNOMIAL_ELEM_CTX(ctx)); } truth_t polynomial_ctx_is_commutative_ring(gr_ctx_t ctx) { return gr_ctx_is_commutative_ring(POLYNOMIAL_ELEM_CTX(ctx)); } truth_t polynomial_ctx_is_integral_domain(gr_ctx_t ctx) { return gr_ctx_is_integral_domain(POLYNOMIAL_ELEM_CTX(ctx)); } truth_t polynomial_ctx_is_threadsafe(gr_ctx_t ctx) { return gr_ctx_is_threadsafe(POLYNOMIAL_ELEM_CTX(ctx)); } void polynomial_clear(gr_poly_t res, gr_ctx_t ctx) { gr_poly_clear(res, POLYNOMIAL_ELEM_CTX(ctx)); } void polynomial_swap(gr_poly_t poly1, gr_poly_t poly2, gr_ctx_t ctx) { gr_poly_swap(poly1, poly2, POLYNOMIAL_ELEM_CTX(ctx)); } void polynomial_set_shallow(gr_poly_t res, const gr_poly_t x, const gr_ctx_t ctx) { *res = *x; } int polynomial_write(gr_stream_t out, gr_poly_t poly, gr_ctx_t ctx) { /* todo */ if (poly->length == 0) { gr_stream_write(out, "0"); return GR_SUCCESS; } return gr_poly_write(out, poly, POLYNOMIAL_CTX(ctx)->var, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_randtest(gr_poly_t res, flint_rand_t state, gr_ctx_t ctx) { return gr_poly_randtest(res, state, n_randint(state, 5), POLYNOMIAL_ELEM_CTX(ctx)); } truth_t polynomial_equal(const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { return gr_poly_equal(poly1, poly2, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_set(gr_poly_t res, const gr_poly_t mat, gr_ctx_t ctx) { return gr_poly_set(res, mat, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_set_si(gr_poly_t res, slong v, gr_ctx_t ctx) { return gr_poly_set_si(res, v, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_set_ui(gr_poly_t res, ulong v, gr_ctx_t ctx) { return gr_poly_set_ui(res, v, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_set_fmpz(gr_poly_t res, const fmpz_t v, gr_ctx_t ctx) { return gr_poly_set_fmpz(res, v, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_set_fmpq(gr_poly_t res, const fmpq_t v, gr_ctx_t ctx) { return gr_poly_set_fmpq(res, v, POLYNOMIAL_ELEM_CTX(ctx)); } #include "fmpz_poly.h" int polynomial_set_other(gr_poly_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { if (x_ctx == ctx) { return polynomial_set(res, x, ctx); } else if (x_ctx == POLYNOMIAL_ELEM_CTX(ctx)) { return gr_poly_set_scalar(res, x, x_ctx); } else if (x_ctx->which_ring == GR_CTX_GR_POLY && !strcmp(POLYNOMIAL_CTX(x_ctx)->var, POLYNOMIAL_CTX(ctx)->var)) { return gr_poly_set_gr_poly_other(res, x, POLYNOMIAL_ELEM_CTX(x_ctx), POLYNOMIAL_ELEM_CTX(ctx)); } else if (x_ctx->which_ring == GR_CTX_FMPZ_POLY) { return gr_poly_set_fmpz_poly(res, x, POLYNOMIAL_ELEM_CTX(ctx)); } else if (x_ctx->which_ring == GR_CTX_FMPQ_POLY) { return gr_poly_set_fmpq_poly(res, x, POLYNOMIAL_ELEM_CTX(ctx)); } else if (x_ctx->which_ring == GR_CTX_GR_VEC) { gr_poly_t tmp; tmp->coeffs = ((gr_vec_struct *) x)->entries; tmp->length = ((gr_vec_struct *) x)->length; return gr_poly_set_gr_poly_other(res, tmp, VECTOR_CTX(x_ctx)->base_ring, POLYNOMIAL_ELEM_CTX(ctx)); } else { int status = GR_SUCCESS; gr_poly_fit_length(res, 1, POLYNOMIAL_ELEM_CTX(ctx)); status = gr_set_other(res->coeffs, x, x_ctx, POLYNOMIAL_ELEM_CTX(ctx)); if (status == GR_SUCCESS) { _gr_poly_set_length(res, 1, POLYNOMIAL_ELEM_CTX(ctx)); _gr_poly_normalise(res, POLYNOMIAL_ELEM_CTX(ctx)); } else _gr_poly_set_length(res, 0, POLYNOMIAL_ELEM_CTX(ctx)); return status; } } int polynomial_set_interval_mid_rad(gr_poly_t res, const gr_poly_t m, const gr_poly_t r, gr_ctx_t ctx) { if (r->length == 0) { return gr_poly_set(res, m, POLYNOMIAL_ELEM_CTX(ctx)); } else { slong i, mlen, rlen, len; int status = GR_SUCCESS; gr_ptr zero = NULL; gr_ctx_ptr cctx = POLYNOMIAL_ELEM_CTX(ctx); if (res == r) { gr_poly_t t; gr_poly_init(t, cctx); status = polynomial_set_interval_mid_rad(t, m, r, ctx); gr_poly_swap(res, t, cctx); gr_poly_clear(t, cctx); return status; } mlen = m->length; rlen = r->length; len = FLINT_MAX(mlen, rlen); gr_poly_fit_length(res, len, cctx); _gr_poly_set_length(res, len, cctx); for (i = 0; i < len; i++) { if (i < mlen && i < rlen) { status |= gr_set_interval_mid_rad(gr_poly_entry_ptr(res, i, cctx), gr_poly_entry_srcptr(m, i, cctx), gr_poly_entry_srcptr(r, i, cctx), cctx); } else if (i < mlen) { status |= gr_set(gr_poly_entry_ptr(res, i, cctx), gr_poly_entry_srcptr(m, i, cctx), cctx); } else if (i < rlen) { if (zero == NULL) zero = gr_heap_init(cctx); status |= gr_set_interval_mid_rad(gr_poly_entry_ptr(res, i, cctx), zero, gr_poly_entry_srcptr(r, i, cctx), cctx); } } if (zero != NULL) gr_heap_clear(zero, cctx); _gr_poly_normalise(res, cctx); return status; } } int polynomial_zero(gr_poly_t res, gr_ctx_t ctx) { return gr_poly_zero(res, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_one(gr_poly_t res, gr_ctx_t ctx) { return gr_poly_one(res, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_neg_one(gr_poly_t res, gr_ctx_t ctx) { return gr_poly_neg_one(res, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_i(gr_poly_t res, gr_ctx_t ctx) { int status; gr_poly_fit_length(res, 1, POLYNOMIAL_ELEM_CTX(ctx)); _gr_poly_set_length(res, 1, POLYNOMIAL_ELEM_CTX(ctx)); status = gr_i(res->coeffs, POLYNOMIAL_ELEM_CTX(ctx)); _gr_poly_normalise(res, POLYNOMIAL_ELEM_CTX(ctx)); return status; } int polynomial_gen(gr_poly_t res, gr_ctx_t ctx) { return gr_poly_gen(res, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_gens_recursive(gr_vec_t vec, gr_ctx_t ctx) { int status; gr_vec_t vec1; slong i, n; /* Get generators of the element ring */ gr_vec_init(vec1, 0, POLYNOMIAL_ELEM_CTX(ctx)); status = gr_gens_recursive(vec1, POLYNOMIAL_ELEM_CTX(ctx)); n = vec1->length; gr_vec_set_length(vec, n + 1, ctx); /* Promote to polynomials */ for (i = 0; i < n; i++) status |= gr_poly_set_scalar(gr_vec_entry_ptr(vec, i, ctx), gr_vec_entry_srcptr(vec1, i, POLYNOMIAL_ELEM_CTX(ctx)), POLYNOMIAL_ELEM_CTX(ctx)); status |= gr_poly_gen(gr_vec_entry_ptr(vec, n, ctx), POLYNOMIAL_ELEM_CTX(ctx)); gr_vec_clear(vec1, POLYNOMIAL_ELEM_CTX(ctx)); return status; } /* truth_t polynomial_is_zero(const gr_poly_t poly, gr_ctx_t ctx) { return gr_poly_is_zero(poly, POLYNOMIAL_ELEM_CTX(ctx)); } truth_t polynomial_is_one(const gr_poly_t poly, gr_ctx_t ctx) { return gr_poly_is_one(poly, POLYNOMIAL_ELEM_CTX(ctx)); } truth_t polynomial_is_neg_one(const gr_poly_t poly, gr_ctx_t ctx) { return gr_poly_is_neg_one(poly, POLYNOMIAL_ELEM_CTX(ctx)); } */ int polynomial_neg(gr_poly_t res, const gr_poly_t mat, gr_ctx_t ctx) { return gr_poly_neg(res, mat, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_add(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { return gr_poly_add(res, poly1, poly2, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_sub(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { return gr_poly_sub(res, poly1, poly2, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_mul(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { if (POLYNOMIAL_CTX(ctx)->degree_limit != WORD_MAX) { if (poly1->length != 0 && poly2->length != 0 && poly1->length + poly2->length > POLYNOMIAL_CTX(ctx)->degree_limit) return GR_UNABLE; } return gr_poly_mul(res, poly1, poly2, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_div(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, const gr_ctx_t ctx) { if (y->length == 1) { if (res == y) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, POLYNOMIAL_ELEM_CTX(ctx)); status |= gr_set(t, y->coeffs, POLYNOMIAL_ELEM_CTX(ctx)); status |= gr_poly_div_scalar(res, x, t, POLYNOMIAL_ELEM_CTX(ctx)); GR_TMP_CLEAR(t, POLYNOMIAL_ELEM_CTX(ctx)); return status; } else { return gr_poly_div_scalar(res, x, y->coeffs, POLYNOMIAL_ELEM_CTX(ctx)); } } else { gr_poly_t r; int status; gr_poly_init(r, POLYNOMIAL_ELEM_CTX(ctx)); status = gr_poly_divrem(res, r, x, y, POLYNOMIAL_ELEM_CTX(ctx)); if (status == GR_SUCCESS) { truth_t is_zero = gr_poly_is_zero(r, POLYNOMIAL_ELEM_CTX(ctx)); if (is_zero == T_FALSE) status = GR_DOMAIN; if (is_zero == T_UNKNOWN) status = GR_UNABLE; } gr_poly_clear(r, POLYNOMIAL_ELEM_CTX(ctx)); return status; } } int polynomial_euclidean_div(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, const gr_ctx_t ctx) { gr_poly_t r; int status; gr_poly_init(r, POLYNOMIAL_ELEM_CTX(ctx)); status = gr_poly_divrem(res, r, x, y, POLYNOMIAL_ELEM_CTX(ctx)); gr_poly_clear(r, POLYNOMIAL_ELEM_CTX(ctx)); return status; } int polynomial_euclidean_rem(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, const gr_ctx_t ctx) { gr_poly_t q; int status; gr_poly_init(q, POLYNOMIAL_ELEM_CTX(ctx)); status = gr_poly_divrem(q, res, x, y, POLYNOMIAL_ELEM_CTX(ctx)); gr_poly_clear(q, POLYNOMIAL_ELEM_CTX(ctx)); return status; } int polynomial_euclidean_divrem(gr_poly_t res1, gr_poly_t res2, const gr_poly_t x, const gr_poly_t y, const gr_ctx_t ctx) { return gr_poly_divrem(res1, res2, x, y, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_inv(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) { return gr_poly_inv(res, poly, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_pow_ui(gr_poly_t res, const gr_poly_t poly, ulong exp, gr_ctx_t ctx) { return gr_poly_pow_ui(res, poly, exp, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_pow_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t exp, gr_ctx_t ctx) { return gr_poly_pow_fmpz(res, poly, exp, POLYNOMIAL_ELEM_CTX(ctx)); } int polynomial_pow_si(gr_poly_t res, const gr_poly_t poly, slong exp, gr_ctx_t ctx) { int status; fmpz_t t; fmpz_init_set_si(t, exp); status = gr_poly_pow_fmpz(res, poly, t, POLYNOMIAL_ELEM_CTX(ctx)); fmpz_clear(t); return status; } int polynomial_gcd(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, const gr_ctx_t ctx) { return gr_poly_gcd(res, x, y, POLYNOMIAL_ELEM_CTX(ctx)); } int _gr_poly_methods_initialized = 0; gr_static_method_table _gr_poly_methods; gr_method_tab_input _gr_poly_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) polynomial_ctx_write}, {GR_METHOD_CTX_CLEAR, (gr_funcptr) polynomial_ctx_clear}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) polynomial_ctx_is_ring}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) polynomial_ctx_is_commutative_ring}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) polynomial_ctx_is_integral_domain}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) polynomial_ctx_is_threadsafe}, {GR_METHOD_CTX_SET_GEN_NAME, (gr_funcptr) _gr_gr_poly_ctx_set_gen_name}, {GR_METHOD_INIT, (gr_funcptr) polynomial_init}, {GR_METHOD_CLEAR, (gr_funcptr) polynomial_clear}, {GR_METHOD_SWAP, (gr_funcptr) polynomial_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) polynomial_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) polynomial_randtest}, {GR_METHOD_WRITE, (gr_funcptr) polynomial_write}, {GR_METHOD_ZERO, (gr_funcptr) polynomial_zero}, {GR_METHOD_ONE, (gr_funcptr) polynomial_one}, {GR_METHOD_NEG_ONE, (gr_funcptr) polynomial_neg_one}, {GR_METHOD_I, (gr_funcptr) polynomial_i}, {GR_METHOD_GEN, (gr_funcptr) polynomial_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_GENS_RECURSIVE, (gr_funcptr) polynomial_gens_recursive}, /* {GR_METHOD_IS_ZERO, (gr_funcptr) polynomial_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) polynomial_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) polynomial_is_neg_one}, */ {GR_METHOD_EQUAL, (gr_funcptr) polynomial_equal}, {GR_METHOD_SET, (gr_funcptr) polynomial_set}, {GR_METHOD_SET_UI, (gr_funcptr) polynomial_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) polynomial_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) polynomial_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) polynomial_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) polynomial_set_other}, {GR_METHOD_SET_INTERVAL_MID_RAD, (gr_funcptr) polynomial_set_interval_mid_rad}, /* todo: we actually want parse using sparse polynomials before converting to the dense representation, to avoid O(n^2) behavior */ {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions}, {GR_METHOD_NEG, (gr_funcptr) polynomial_neg}, {GR_METHOD_ADD, (gr_funcptr) polynomial_add}, {GR_METHOD_SUB, (gr_funcptr) polynomial_sub}, {GR_METHOD_MUL, (gr_funcptr) polynomial_mul}, {GR_METHOD_POW_UI, (gr_funcptr) polynomial_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) polynomial_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) polynomial_pow_fmpz}, {GR_METHOD_DIV, (gr_funcptr) polynomial_div}, {GR_METHOD_INV, (gr_funcptr) polynomial_inv}, {GR_METHOD_EUCLIDEAN_DIV, (gr_funcptr) polynomial_euclidean_div}, {GR_METHOD_EUCLIDEAN_REM, (gr_funcptr) polynomial_euclidean_rem}, {GR_METHOD_EUCLIDEAN_DIVREM, (gr_funcptr) polynomial_euclidean_divrem}, {GR_METHOD_GCD, (gr_funcptr) polynomial_gcd}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_gr_poly(gr_ctx_t ctx, gr_ctx_t base_ring) { ctx->which_ring = GR_CTX_GR_POLY; ctx->sizeof_elem = sizeof(gr_poly_struct); ctx->size_limit = WORD_MAX; POLYNOMIAL_CTX(ctx)->base_ring = (gr_ctx_struct *) base_ring; POLYNOMIAL_CTX(ctx)->degree_limit = WORD_MAX; POLYNOMIAL_CTX(ctx)->var = (char *) default_var; ctx->methods = _gr_poly_methods; if (!_gr_poly_methods_initialized) { gr_method_tab_init(_gr_poly_methods, _gr_poly_methods_input); _gr_poly_methods_initialized = 1; } } flint-3.1.3/src/gr/psl2z.c000066400000000000000000000122461461254215100152550ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "acb_modular.h" #include "gr.h" int _gr_psl2z_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Modular group (psl2z)"); return GR_SUCCESS; } int _gr_psl2z_init(psl2z_t res, gr_ctx_t ctx) { psl2z_init(res); return GR_SUCCESS; } int _gr_psl2z_clear(psl2z_t res, gr_ctx_t ctx) { psl2z_clear(res); return GR_SUCCESS; } void _gr_psl2z_swap(psl2z_t x, psl2z_t y, gr_ctx_t ctx) { psl2z_swap(x, y); } int _gr_psl2z_write(gr_stream_t out, psl2z_t x, gr_ctx_t ctx) { gr_stream_write(out, "[["); gr_stream_write_fmpz(out, &x->a); gr_stream_write(out, ", "); gr_stream_write_fmpz(out, &x->b); gr_stream_write(out, "], ["); gr_stream_write_fmpz(out, &x->c); gr_stream_write(out, ", "); gr_stream_write_fmpz(out, &x->d); gr_stream_write(out, "]]"); return GR_SUCCESS; } int _gr_psl2z_randtest(psl2z_t res, flint_rand_t state, gr_ctx_t ctx) { if (n_randint(state, 4)) psl2z_randtest(res, state, 8); else psl2z_randtest(res, state, 1 + n_randint(state, 100)); return GR_SUCCESS; } truth_t _gr_psl2z_equal(const psl2z_t x, const psl2z_t y, gr_ctx_t ctx) { return psl2z_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_psl2z_set(psl2z_t res, const psl2z_t x, gr_ctx_t ctx) { psl2z_set(res, x); return GR_SUCCESS; } int _gr_psl2z_set_other(psl2z_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { if (x_ctx->which_ring == GR_CTX_PSL2Z) { psl2z_set(res, x); return GR_SUCCESS; } else if (x_ctx->which_ring == GR_CTX_GR_MAT && MATRIX_CTX(x_ctx)->base_ring->which_ring == GR_CTX_FMPZ) { fmpz_t det; if (fmpz_mat_nrows(x) != 2 || fmpz_mat_ncols(x) != 2) return GR_DOMAIN; fmpz_init(det); fmpz_mat_det(det, x); if (fmpz_is_one(det)) { fmpz_set(&res->a, fmpz_mat_entry(x, 0, 0)); fmpz_set(&res->b, fmpz_mat_entry(x, 0, 1)); fmpz_set(&res->c, fmpz_mat_entry(x, 1, 0)); fmpz_set(&res->d, fmpz_mat_entry(x, 1, 1)); if (fmpz_sgn(&res->c) < 0 || (fmpz_is_zero(&res->c) && fmpz_sgn(&res->d) < 0)) { fmpz_neg(&res->a, &res->a); fmpz_neg(&res->b, &res->b); fmpz_neg(&res->c, &res->c); fmpz_neg(&res->d, &res->d); } fmpz_clear(det); return GR_SUCCESS; } else { fmpz_clear(det); return GR_DOMAIN; } } else { return GR_UNABLE; } } int _gr_psl2z_one(psl2z_t res, gr_ctx_t ctx) { psl2z_one(res); return GR_SUCCESS; } truth_t _gr_psl2z_is_one(const psl2z_t x, gr_ctx_t ctx) { return psl2z_is_one(x) ? T_TRUE : T_FALSE; } int _gr_psl2z_mul(psl2z_t res, const psl2z_t x, const psl2z_t y, gr_ctx_t ctx) { psl2z_mul(res, x, y); return GR_SUCCESS; } /* todo: should be generic. also want left division */ int _gr_psl2z_div(psl2z_t res, const psl2z_t x, const psl2z_t y, gr_ctx_t ctx) { psl2z_t t; psl2z_init(t); psl2z_inv(t, y); psl2z_mul(res, x, t); psl2z_clear(t); return GR_SUCCESS; } int _gr_psl2z_inv(psl2z_t res, const psl2z_t x, gr_ctx_t ctx) { psl2z_inv(res, x); return GR_SUCCESS; } int _psl2z_methods_initialized = 0; gr_static_method_table _psl2z_methods; gr_method_tab_input _psl2z_methods_input[] = { {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_MULTIPLICATIVE_GROUP, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_psl2z_ctx_write}, {GR_METHOD_INIT, (gr_funcptr) _gr_psl2z_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_psl2z_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_psl2z_swap}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_psl2z_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_psl2z_write}, {GR_METHOD_ONE, (gr_funcptr) _gr_psl2z_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_psl2z_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_psl2z_set}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_psl2z_set_other}, {GR_METHOD_MUL, (gr_funcptr) _gr_psl2z_mul}, {GR_METHOD_INV, (gr_funcptr) _gr_psl2z_inv}, {GR_METHOD_DIV, (gr_funcptr) _gr_psl2z_div}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_psl2z(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_PSL2Z; ctx->sizeof_elem = sizeof(psl2z_struct); ctx->size_limit = WORD_MAX; ctx->methods = _psl2z_methods; if (!_psl2z_methods_initialized) { gr_method_tab_init(_psl2z_methods, _psl2z_methods_input); _psl2z_methods_initialized = 1; } } flint-3.1.3/src/gr/qqbar.c000066400000000000000000001043741461254215100153150ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_poly_factor.h" #include "fmpq.h" #include "fmpzi.h" #include "fexpr.h" #include "qqbar.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_poly.h" #include "ca.h" typedef struct { /* todo: use which_ring */ int real_only; /* field restricted to real algebraics instead of complex? */ slong deg_limit; /* todo */ slong bits_limit; /* todo */ } gr_qqbar_ctx; #define QQBAR_CTX(ring_ctx) ((gr_qqbar_ctx *)(ring_ctx)) void _gr_ctx_qqbar_set_limits(gr_ctx_t ctx, slong deg_limit, slong bits_limit) { QQBAR_CTX(ctx)->deg_limit = (deg_limit >= 0) ? deg_limit : WORD_MAX; QQBAR_CTX(ctx)->bits_limit = (bits_limit >= 0) ? bits_limit : WORD_MAX; } int _gr_qqbar_ctx_write(gr_stream_t out, gr_ctx_t ctx) { if (QQBAR_CTX(ctx)->real_only) gr_stream_write(out, "Real algebraic numbers (qqbar)"); else gr_stream_write(out, "Complex algebraic numbers (qqbar)"); if (QQBAR_CTX(ctx)->deg_limit != WORD_MAX) { gr_stream_write(out, ", deg_limit = "); gr_stream_write_si(out, QQBAR_CTX(ctx)->deg_limit); } if (QQBAR_CTX(ctx)->bits_limit != WORD_MAX) { gr_stream_write(out, ", bits_limit = "); gr_stream_write_si(out, QQBAR_CTX(ctx)->bits_limit); } return GR_SUCCESS; } void _gr_qqbar_init(qqbar_t x, const gr_ctx_t ctx) { qqbar_init(x); } void _gr_qqbar_clear(qqbar_t x, const gr_ctx_t ctx) { qqbar_clear(x); } void _gr_qqbar_swap(qqbar_t x, qqbar_t y, const gr_ctx_t ctx) { qqbar_t t; *t = *x; *x = *y; *y = *t; } void _gr_qqbar_set_shallow(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { *res = *x; } /* todo: limits */ int _gr_qqbar_randtest(qqbar_t res, flint_rand_t state, const gr_ctx_t ctx) { slong deg_limit, bits_limit; int rcase; rcase = n_randint(state, 10); if (rcase == 0) { deg_limit = 4; bits_limit = 10; } else if (rcase <= 3) { deg_limit = 2; bits_limit = 10; } else { deg_limit = 1; bits_limit = 10; } if (QQBAR_CTX(ctx)->real_only) qqbar_randtest_real(res, state, deg_limit, bits_limit); else qqbar_randtest(res, state, deg_limit, bits_limit); return GR_SUCCESS; } /* todo: different styles */ void qqbar_get_decimal_root_nearest(char ** re_s, char ** im_s, const qqbar_t x, slong default_digits); int _gr_qqbar_write(gr_stream_t out, const qqbar_t x, const gr_ctx_t ctx) { char *re_s, *im_s; if (qqbar_is_rational(x)) { fmpq_t t; fmpq_init(t); qqbar_get_fmpq(t, x); gr_stream_write_fmpz(out, fmpq_numref(t)); if (!fmpz_is_one(fmpq_denref(t))) { gr_stream_write(out, "/"); gr_stream_write_fmpz(out, fmpq_denref(t)); } fmpq_clear(t); } else { qqbar_get_decimal_root_nearest(&re_s, &im_s, x, 6); gr_stream_write(out, "Root a = "); if (re_s != NULL) { gr_stream_write_free(out, re_s); } if (im_s != NULL) { if (re_s != NULL) { if (im_s[0] == '-') { gr_stream_write(out, " - "); gr_stream_write(out, im_s + 1); flint_free(im_s); } else { gr_stream_write(out, " + "); gr_stream_write_free(out, im_s); } } else { gr_stream_write_free(out, im_s); } gr_stream_write(out, "*I"); } gr_stream_write(out, " of "); gr_stream_write_free(out, fmpz_poly_get_str_pretty(QQBAR_POLY(x), "a")); } return GR_SUCCESS; } int _gr_qqbar_zero(qqbar_t x, const gr_ctx_t ctx) { qqbar_zero(x); return GR_SUCCESS; } int _gr_qqbar_one(qqbar_t x, const gr_ctx_t ctx) { qqbar_one(x); return GR_SUCCESS; } int _gr_qqbar_set_si(qqbar_t res, slong v, const gr_ctx_t ctx) { qqbar_set_si(res, v); return GR_SUCCESS; } int _gr_qqbar_set_ui(qqbar_t res, ulong v, const gr_ctx_t ctx) { qqbar_set_ui(res, v); return GR_SUCCESS; } int _gr_qqbar_set_fmpz(qqbar_t res, const fmpz_t v, const gr_ctx_t ctx) { qqbar_set_fmpz(res, v); return GR_SUCCESS; } int _gr_qqbar_set_fmpq(qqbar_t res, const fmpq_t v, const gr_ctx_t ctx) { qqbar_set_fmpq(res, v); return GR_SUCCESS; } int _gr_qqbar_set_d(qqbar_t res, double v, const gr_ctx_t ctx) { if (qqbar_set_d(res, v)) return GR_SUCCESS; else return GR_DOMAIN; } truth_t _gr_qqbar_is_zero(const qqbar_t x, const gr_ctx_t ctx) { return qqbar_is_zero(x) ? T_TRUE : T_FALSE; } truth_t _gr_qqbar_is_one(const qqbar_t x, const gr_ctx_t ctx) { return qqbar_is_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_qqbar_is_neg_one(const qqbar_t x, const gr_ctx_t ctx) { return qqbar_is_neg_one(x) ? T_TRUE : T_FALSE; } truth_t _gr_qqbar_equal(const qqbar_t x, const qqbar_t y, const gr_ctx_t ctx) { return qqbar_equal(x, y) ? T_TRUE : T_FALSE; } int _gr_qqbar_set(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_set(res, x); return GR_SUCCESS; } /* todo: move */ void qqbar_set_fmpzi(qqbar_t res, const fmpzi_t x) { if (fmpz_is_zero(fmpzi_imagref(x))) { qqbar_set_fmpz(res, fmpzi_realref(x)); } else { fmpz_poly_fit_length(QQBAR_POLY(res), 3); _fmpz_poly_set_length(QQBAR_POLY(res), 3); fmpzi_norm(QQBAR_COEFFS(res), x); fmpz_mul_si(QQBAR_COEFFS(res) + 1, fmpzi_realref(x), -2); fmpz_one(QQBAR_COEFFS(res) + 2); arb_set_round_fmpz(acb_realref(QQBAR_ENCLOSURE(res)), fmpzi_realref(x), QQBAR_DEFAULT_PREC); arb_set_round_fmpz(acb_imagref(QQBAR_ENCLOSURE(res)), fmpzi_imagref(x), QQBAR_DEFAULT_PREC); } } int _gr_qqbar_set_other(qqbar_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { switch (x_ctx->which_ring) { case GR_CTX_FMPZ: qqbar_set_fmpz(res, x); return GR_SUCCESS; case GR_CTX_FMPQ: qqbar_set_fmpq(res, x); return GR_SUCCESS; case GR_CTX_FMPZI: if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_QQBAR && !fmpz_is_zero(fmpzi_imagref((const fmpzi_struct *) x))) return GR_DOMAIN; qqbar_set_fmpzi(res, x); return GR_SUCCESS; case GR_CTX_REAL_ALGEBRAIC_QQBAR: case GR_CTX_COMPLEX_ALGEBRAIC_QQBAR: if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_QQBAR && !qqbar_is_real(x)) return GR_DOMAIN; qqbar_set(res, x); return GR_SUCCESS; /* todo: all cases */ case GR_CTX_RR_CA: case GR_CTX_CC_CA: case GR_CTX_REAL_ALGEBRAIC_CA: case GR_CTX_COMPLEX_ALGEBRAIC_CA: case GR_CTX_COMPLEX_EXTENDED_CA: if (!ca_get_qqbar(res, x, gr_ctx_data_as_ptr(x_ctx))) return GR_UNABLE; if (ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_QQBAR || x_ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_CA || x_ctx->which_ring == GR_CTX_RR_CA) return GR_SUCCESS; if (!qqbar_is_real(res)) { qqbar_zero(res); return GR_DOMAIN; } return GR_SUCCESS; } return gr_generic_set_other(res, x, x_ctx, ctx); } int _gr_qqbar_get_fmpz(fmpz_t res, const qqbar_t x, const gr_ctx_t ctx) { if (!qqbar_is_integer(x)) return GR_DOMAIN; qqbar_get_fmpz(res, x); return GR_SUCCESS; } int _gr_qqbar_get_ui(ulong * res, const qqbar_t x, const gr_ctx_t ctx) { fmpz_t t; int status; if (!qqbar_is_integer(x)) return GR_DOMAIN; fmpz_init(t); qqbar_get_fmpz(t, x); if (fmpz_sgn(t) < 0 || fmpz_cmp_ui(t, UWORD_MAX) > 0) { status = GR_DOMAIN; } else { *res = fmpz_get_ui(t); status = GR_SUCCESS; } fmpz_clear(t); return status; } int _gr_qqbar_get_si(slong * res, const qqbar_t x, const gr_ctx_t ctx) { fmpz_t t; int status; if (!qqbar_is_integer(x)) return GR_DOMAIN; fmpz_init(t); qqbar_get_fmpz(t, x); if (!fmpz_fits_si(t)) { status = GR_DOMAIN; } else { *res = fmpz_get_si(t); status = GR_SUCCESS; } fmpz_clear(t); return status; } int _gr_qqbar_get_fmpq(fmpq_t res, const qqbar_t x, const gr_ctx_t ctx) { if (!qqbar_is_rational(x)) return GR_DOMAIN; qqbar_get_fmpq(res, x); return GR_SUCCESS; } int _gr_qqbar_get_d(double * res, const qqbar_t x, const gr_ctx_t ctx) { arb_t t; if (!qqbar_is_real(x)) return GR_DOMAIN; arb_init(t); qqbar_get_arb(t, x, 64); *res = arf_get_d(arb_midref(t), ARF_RND_NEAR); arb_clear(t); return GR_SUCCESS; } int _gr_qqbar_get_fexpr(fexpr_t res, const qqbar_t x, const gr_ctx_t ctx) { if (!qqbar_get_fexpr_formula(res, x, QQBAR_FORMULA_GAUSSIANS | QQBAR_FORMULA_QUADRATICS)) qqbar_get_fexpr_root_nearest(res, x); return GR_SUCCESS; } int _gr_qqbar_get_fexpr_serialize(fexpr_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_get_fexpr_repr(res, x); return GR_SUCCESS; } /* todo */ int _gr_qqbar_set_fexpr(gr_ptr res, fexpr_vec_t inputs, gr_vec_t outputs, const fexpr_t x, gr_ctx_t ctx) { if (qqbar_set_fexpr(res, x)) { if (QQBAR_CTX(ctx)->real_only && !qqbar_is_real(res)) return GR_DOMAIN; else return GR_SUCCESS; } else { return gr_generic_set_fexpr(res, inputs, outputs, x, ctx); } } int _gr_qqbar_neg(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_neg(res, x); return GR_SUCCESS; } int _gr_qqbar_add(qqbar_t res, const qqbar_t x, const qqbar_t y, const gr_ctx_t ctx) { if (QQBAR_CTX(ctx)->deg_limit != WORD_MAX || QQBAR_CTX(ctx)->bits_limit != WORD_MAX) if (!qqbar_binop_within_limits(x, y, QQBAR_CTX(ctx)->deg_limit, QQBAR_CTX(ctx)->bits_limit)) return GR_UNABLE; qqbar_add(res, x, y); return GR_SUCCESS; } int _gr_qqbar_add_si(qqbar_t res, const qqbar_t x, slong y, const gr_ctx_t ctx) { qqbar_add_si(res, x, y); return GR_SUCCESS; } int _gr_qqbar_add_ui(qqbar_t res, const qqbar_t x, ulong y, const gr_ctx_t ctx) { qqbar_add_ui(res, x, y); return GR_SUCCESS; } int _gr_qqbar_add_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y, const gr_ctx_t ctx) { qqbar_add_fmpz(res, x, y); return GR_SUCCESS; } int _gr_qqbar_add_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y, const gr_ctx_t ctx) { qqbar_add_fmpq(res, x, y); return GR_SUCCESS; } int _gr_qqbar_sub(qqbar_t res, const qqbar_t x, const qqbar_t y, const gr_ctx_t ctx) { if (QQBAR_CTX(ctx)->deg_limit != WORD_MAX || QQBAR_CTX(ctx)->bits_limit != WORD_MAX) if (!qqbar_binop_within_limits(x, y, QQBAR_CTX(ctx)->deg_limit, QQBAR_CTX(ctx)->bits_limit)) return GR_UNABLE; qqbar_sub(res, x, y); return GR_SUCCESS; } int _gr_qqbar_sub_si(qqbar_t res, const qqbar_t x, slong y, const gr_ctx_t ctx) { qqbar_sub_si(res, x, y); return GR_SUCCESS; } int _gr_qqbar_sub_ui(qqbar_t res, const qqbar_t x, ulong y, const gr_ctx_t ctx) { qqbar_sub_ui(res, x, y); return GR_SUCCESS; } int _gr_qqbar_sub_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y, const gr_ctx_t ctx) { qqbar_sub_fmpz(res, x, y); return GR_SUCCESS; } int _gr_qqbar_sub_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y, const gr_ctx_t ctx) { qqbar_sub_fmpq(res, x, y); return GR_SUCCESS; } int _gr_qqbar_mul(qqbar_t res, const qqbar_t x, const qqbar_t y, const gr_ctx_t ctx) { if (QQBAR_CTX(ctx)->deg_limit != WORD_MAX || QQBAR_CTX(ctx)->bits_limit != WORD_MAX) if (!qqbar_binop_within_limits(x, y, QQBAR_CTX(ctx)->deg_limit, QQBAR_CTX(ctx)->bits_limit)) return GR_UNABLE; qqbar_mul(res, x, y); return GR_SUCCESS; } int _gr_qqbar_mul_si(qqbar_t res, const qqbar_t x, slong y, const gr_ctx_t ctx) { qqbar_mul_si(res, x, y); return GR_SUCCESS; } int _gr_qqbar_mul_ui(qqbar_t res, const qqbar_t x, ulong y, const gr_ctx_t ctx) { qqbar_mul_ui(res, x, y); return GR_SUCCESS; } int _gr_qqbar_mul_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y, const gr_ctx_t ctx) { qqbar_mul_fmpz(res, x, y); return GR_SUCCESS; } int _gr_qqbar_mul_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y, const gr_ctx_t ctx) { qqbar_mul_fmpq(res, x, y); return GR_SUCCESS; } int _gr_qqbar_inv(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { if (qqbar_is_zero(x)) { return GR_DOMAIN; } else { qqbar_inv(res, x); return GR_SUCCESS; } } int _gr_qqbar_div(qqbar_t res, const qqbar_t x, const qqbar_t y, const gr_ctx_t ctx) { if (qqbar_is_zero(y)) { return GR_DOMAIN; } else { if (QQBAR_CTX(ctx)->deg_limit != WORD_MAX || QQBAR_CTX(ctx)->bits_limit != WORD_MAX) if (!qqbar_binop_within_limits(x, y, QQBAR_CTX(ctx)->deg_limit, QQBAR_CTX(ctx)->bits_limit)) return GR_UNABLE; qqbar_div(res, x, y); return GR_SUCCESS; } } int _gr_qqbar_div_si(qqbar_t res, const qqbar_t x, slong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { qqbar_div_si(res, x, y); return GR_SUCCESS; } } int _gr_qqbar_div_ui(qqbar_t res, const qqbar_t x, ulong y, const gr_ctx_t ctx) { if (y == 0) { return GR_DOMAIN; } else { qqbar_div_ui(res, x, y); return GR_SUCCESS; } } int _gr_qqbar_div_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y, const gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return GR_DOMAIN; } else { qqbar_div_fmpz(res, x, y); return GR_SUCCESS; } } int _gr_qqbar_div_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y, const gr_ctx_t ctx) { if (fmpq_is_zero(y)) { return GR_DOMAIN; } else { qqbar_div_fmpq(res, x, y); return GR_SUCCESS; } } truth_t _gr_qqbar_is_invertible(const qqbar_t x, const gr_ctx_t ctx) { return !qqbar_is_zero(x) ? T_TRUE : T_FALSE; } int _gr_qqbar_pow_ui(qqbar_t res, const qqbar_t x, ulong exp, const gr_ctx_t ctx) { if (QQBAR_CTX(ctx)->bits_limit != WORD_MAX && !(exp == 0 || exp == 1)) { slong ebits = FLINT_BIT_COUNT(exp); if (qqbar_is_zero(x) || qqbar_is_one(x)) { qqbar_set(res, x); return GR_SUCCESS; } if (qqbar_is_neg_one(x)) { if (exp % 2 == 0) qqbar_one(res); else qqbar_set(res, x); return GR_SUCCESS; } if (ebits > SMALL_FMPZ_BITCOUNT_MAX) return GR_UNABLE; if ((double) exp * qqbar_height_bits(x) > QQBAR_CTX(ctx)->bits_limit) return GR_UNABLE; } qqbar_pow_ui(res, x, exp); return GR_SUCCESS; } int _gr_qqbar_pow_si(qqbar_t res, const qqbar_t x, slong exp, const gr_ctx_t ctx) { if (exp < 0 && qqbar_is_zero(x)) { return GR_DOMAIN; } else { if (QQBAR_CTX(ctx)->bits_limit != WORD_MAX && !(exp == 0 || exp == 1 || exp == -1)) { slong ebits = FLINT_BIT_COUNT(FLINT_ABS(exp)); if (qqbar_is_zero(x) || qqbar_is_one(x)) { qqbar_set(res, x); return GR_SUCCESS; } if (qqbar_is_neg_one(x)) { if (exp % 2 == 0) qqbar_one(res); else qqbar_set(res, x); return GR_SUCCESS; } if (ebits > SMALL_FMPZ_BITCOUNT_MAX) return GR_UNABLE; if ((double) FLINT_ABS(exp) * qqbar_height_bits(x) > QQBAR_CTX(ctx)->bits_limit) return GR_UNABLE; } qqbar_pow_si(res, x, exp); return GR_SUCCESS; } } int _gr_qqbar_pow_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t exp, const gr_ctx_t ctx) { if (fmpz_sgn(exp) < 0 && qqbar_is_zero(x)) { return GR_DOMAIN; } else { if (QQBAR_CTX(ctx)->bits_limit != WORD_MAX && !(fmpz_is_zero(exp) || fmpz_is_pm1(exp))) { slong ebits = fmpz_bits(exp); if (qqbar_is_zero(x) || qqbar_is_one(x)) { qqbar_set(res, x); return GR_SUCCESS; } if (qqbar_is_neg_one(x)) { if (fmpz_is_even(exp)) qqbar_one(res); else qqbar_set(res, x); return GR_SUCCESS; } if (ebits > SMALL_FMPZ_BITCOUNT_MAX) return GR_UNABLE; if ((double) FLINT_ABS(*exp) * qqbar_height_bits(x) > QQBAR_CTX(ctx)->bits_limit) return GR_UNABLE; } qqbar_pow_fmpz(res, x, exp); return GR_SUCCESS; } } int _gr_qqbar_pow_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t exp, const gr_ctx_t ctx) { if (fmpq_sgn(exp) < 0 && qqbar_is_zero(x)) { return GR_DOMAIN; } else { qqbar_pow_fmpq(res, x, exp); /* todo: don't compute */ if (QQBAR_CTX(ctx)->real_only && !qqbar_is_real(res)) { qqbar_zero(res); return GR_DOMAIN; } else { return GR_SUCCESS; } } } int _gr_qqbar_pow(qqbar_t res, const qqbar_t x, const qqbar_t exp, const gr_ctx_t ctx) { if (qqbar_pow(res, x, exp)) { if (QQBAR_CTX(ctx)->real_only && !qqbar_is_real(res)) { qqbar_zero(res); return GR_DOMAIN; } else { return GR_SUCCESS; } } else { return GR_DOMAIN; } } truth_t _gr_qqbar_is_square(const qqbar_t x, const gr_ctx_t ctx) { if (QQBAR_CTX(ctx)->real_only) return (qqbar_sgn_re(x) >= 0) ? T_TRUE : T_FALSE; else return T_TRUE; } int _gr_qqbar_sqrt(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { if (QQBAR_CTX(ctx)->real_only && qqbar_sgn_re(x) < 0) { return GR_DOMAIN; } else { qqbar_sqrt(res, x); return GR_SUCCESS; } } int _gr_qqbar_rsqrt(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { if (qqbar_is_zero(x) || (QQBAR_CTX(ctx)->real_only && qqbar_sgn_re(x) < 0)) { return GR_DOMAIN; } else { qqbar_rsqrt(res, x); return GR_SUCCESS; } } int _gr_qqbar_numerator(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_numerator(res, x); return GR_SUCCESS; } int _gr_qqbar_denominator(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { fmpz_t t; fmpz_init(t); qqbar_denominator(t, x); qqbar_set_fmpz(res, t); fmpz_clear(t); return GR_SUCCESS; } /* todo: could special-case rationals */ int _gr_qqbar_floor(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { if (qqbar_is_integer(x)) { qqbar_set(res, x); } else { fmpz_t n; fmpz_init(n); qqbar_floor(n, x); qqbar_set_fmpz(res, n); fmpz_clear(n); } return GR_SUCCESS; } int _gr_qqbar_ceil(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { if (qqbar_is_integer(x)) { qqbar_set(res, x); } else { fmpz_t n; fmpz_init(n); qqbar_ceil(n, x); qqbar_set_fmpz(res, n); fmpz_clear(n); } return GR_SUCCESS; } int _gr_qqbar_trunc(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { if (qqbar_is_integer(x)) { qqbar_set(res, x); } else { int sgn = qqbar_sgn_re(x); if (sgn == 0) { qqbar_zero(res); } else { fmpz_t n; fmpz_init(n); if (sgn > 0) qqbar_floor(n, x); else qqbar_ceil(n, x); qqbar_set_fmpz(res, n); fmpz_clear(n); } } return GR_SUCCESS; } /* todo: fast numerical path */ int _gr_qqbar_nint(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { if (qqbar_is_integer(x)) { qqbar_set(res, x); } else { qqbar_t t; fmpz_t n; qqbar_init(t); fmpz_init(n); qqbar_set_d(t, 0.5); qqbar_add(t, x, t); qqbar_floor(n, t); if (arb_contains_int(acb_realref(QQBAR_ENCLOSURE(t)))) { qqbar_re(t, t); if (qqbar_is_integer(t)) { fmpz_t m; fmpz_init(m); qqbar_get_fmpz(m, t); if (fmpz_is_odd(m)) fmpz_sub_ui(n, n, 1); fmpz_clear(m); } } qqbar_set_fmpz(res, n); fmpz_clear(n); qqbar_clear(t); } return GR_SUCCESS; } int _gr_qqbar_i(qqbar_t res, const gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_QQBAR) return GR_DOMAIN; qqbar_i(res); return GR_SUCCESS; } int _gr_qqbar_abs(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_abs(res, x); return GR_SUCCESS; } /* todo: exploit when we know that the field is real */ int _gr_qqbar_conj(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_conj(res, x); return GR_SUCCESS; } /* todo: exploit when we know that the field is real */ int _gr_qqbar_re(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_re(res, x); return GR_SUCCESS; } /* todo: exploit when we know that the field is real */ int _gr_qqbar_im(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_im(res, x); return GR_SUCCESS; } int _gr_qqbar_sgn(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_sgn(res, x); return GR_SUCCESS; } int _gr_qqbar_csgn(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) { qqbar_set_si(res, qqbar_csgn(x)); return GR_SUCCESS; } int _gr_qqbar_cmp(int * res, const qqbar_t x, const qqbar_t y, const gr_ctx_t ctx) { if (!qqbar_is_real(x) || !qqbar_is_real(y)) return GR_DOMAIN; *res = qqbar_cmp_re(x, y); return GR_SUCCESS; } int _gr_qqbar_cmpabs(int * res, const qqbar_t x, const qqbar_t y, const gr_ctx_t ctx) { *res = qqbar_cmpabs(x, y); return GR_SUCCESS; } /* todo: 2 pi reduction for bignum numerators */ #define TRIG(fn, real_check) \ int \ _gr_qqbar_ ## fn(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) \ { \ if (!qqbar_is_rational(x)) \ { \ return GR_DOMAIN; \ } \ else if (COEFF_IS_MPZ(QQBAR_COEFFS(x)[0]) || COEFF_IS_MPZ(QQBAR_COEFFS(x)[1])) \ { \ return GR_UNABLE; \ } \ else \ { \ slong p = -QQBAR_COEFFS(x)[0], q = QQBAR_COEFFS(x)[1]; \ if (q > QQBAR_CTX(ctx)->deg_limit) \ return GR_UNABLE; \ qqbar_ ## fn(res, p, q); \ if (real_check && QQBAR_CTX(ctx)->real_only && !qqbar_is_real(res)) \ return GR_DOMAIN; \ return GR_SUCCESS; \ } \ } #define TRIG2(fn) \ int \ _gr_qqbar_ ## fn(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) \ { \ if (!qqbar_is_rational(x)) \ { \ return GR_DOMAIN; \ } \ else if (COEFF_IS_MPZ(QQBAR_COEFFS(x)[0]) || COEFF_IS_MPZ(QQBAR_COEFFS(x)[1])) \ { \ return GR_UNABLE; \ } \ else \ { \ slong p = -QQBAR_COEFFS(x)[0], q = QQBAR_COEFFS(x)[1]; \ if (q > QQBAR_CTX(ctx)->deg_limit) \ return GR_UNABLE; \ return qqbar_ ## fn(res, p, q) ? GR_SUCCESS : GR_DOMAIN; \ } \ } #define TRIG3(fn) \ int \ _gr_qqbar_ ## fn(qqbar_t res, const qqbar_t x, const gr_ctx_t ctx) \ { \ fmpq_t t; \ slong p; \ ulong q; \ if (!qqbar_ ## fn(&p, &q, x)) \ return GR_DOMAIN; \ *fmpq_numref(t) = p; \ *fmpq_denref(t) = q; \ qqbar_set_fmpq(res, t); \ return GR_SUCCESS; \ } TRIG(exp_pi_i, 1) TRIG(sin_pi, 0) TRIG(cos_pi, 0) TRIG2(tan_pi) TRIG2(cot_pi) TRIG2(sec_pi) TRIG2(csc_pi) TRIG3(log_pi_i) TRIG3(asin_pi) TRIG3(acos_pi) TRIG3(atan_pi) TRIG3(acot_pi) TRIG3(asec_pi) TRIG3(acsc_pi) /* todo: root of unity / is_root_of_unity */ /* todo: exploit when we know that the field is real */ /* todo: quickly skip nonreal roots over the real algebraic numbers */ int _gr_qqbar_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t other_ctx, int flags, gr_ctx_t ctx) { if (poly->length == 0) return GR_DOMAIN; if (other_ctx->which_ring == GR_CTX_FMPZ) { gr_ctx_t ZZ; slong i, j, deg, deg2; qqbar_struct * croots; int status = GR_SUCCESS; deg = poly->length - 1; gr_ctx_init_fmpz(ZZ); gr_vec_set_length(roots, 0, ctx); gr_vec_set_length(mult, 0, ZZ); if (deg != 0) { fmpz_poly_factor_t fac; fmpz_poly_factor_init(fac); fmpz_poly_factor(fac, (const fmpz_poly_struct *) poly); for (i = 0; i < fac->num; i++) { deg2 = fmpz_poly_degree(fac->p + i); croots = _qqbar_vec_init(deg2); qqbar_roots_fmpz_poly(croots, fac->p + i, QQBAR_ROOTS_IRREDUCIBLE); for (j = 0; j < deg2; j++) { fmpz m2 = fac->exp[i]; if (QQBAR_CTX(ctx)->real_only && !qqbar_is_real(croots + j)) continue; GR_MUST_SUCCEED(gr_vec_append(roots, croots + j, ctx)); GR_MUST_SUCCEED(gr_vec_append(mult, &m2, ZZ)); } _qqbar_vec_clear(croots, deg2); } fmpz_poly_factor_clear(fac); } /* todo: qqbar_cmp_root_order, but must sort exponents as well */ gr_ctx_clear(ZZ); return status; } return GR_UNABLE; } truth_t _gr_qqbar_ctx_is_algebraically_closed(gr_ctx_t ctx) { return (ctx->which_ring == GR_CTX_COMPLEX_ALGEBRAIC_QQBAR) ? T_TRUE : T_FALSE; } truth_t _gr_qqbar_ctx_is_ordered_ring(gr_ctx_t ctx) { return (ctx->which_ring == GR_CTX_REAL_ALGEBRAIC_QQBAR) ? T_TRUE : T_FALSE; } int _qqbar_methods_initialized = 0; gr_static_method_table _qqbar_methods; gr_method_tab_input _qqbar_methods_input[] = { {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_qqbar_ctx_write}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate_false}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) _gr_qqbar_ctx_is_algebraically_closed}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) _gr_qqbar_ctx_is_ordered_ring}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_INIT, (gr_funcptr) _gr_qqbar_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_qqbar_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_qqbar_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_qqbar_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_qqbar_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_qqbar_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_qqbar_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_qqbar_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_qqbar_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_qqbar_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) _gr_qqbar_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_qqbar_equal}, {GR_METHOD_SET, (gr_funcptr) _gr_qqbar_set}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_qqbar_set_si}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_qqbar_set_ui}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_qqbar_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_qqbar_set_fmpq}, {GR_METHOD_SET_D, (gr_funcptr) _gr_qqbar_set_d}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_qqbar_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_ring_exponents}, {GR_METHOD_GET_SI, (gr_funcptr) _gr_qqbar_get_si}, {GR_METHOD_GET_UI, (gr_funcptr) _gr_qqbar_get_ui}, {GR_METHOD_GET_FMPZ, (gr_funcptr) _gr_qqbar_get_fmpz}, {GR_METHOD_GET_FMPQ, (gr_funcptr) _gr_qqbar_get_fmpq}, {GR_METHOD_GET_D, (gr_funcptr) _gr_qqbar_get_d}, {GR_METHOD_GET_FEXPR, (gr_funcptr) _gr_qqbar_get_fexpr}, {GR_METHOD_GET_FEXPR_SERIALIZE, (gr_funcptr) _gr_qqbar_get_fexpr_serialize}, {GR_METHOD_SET_FEXPR, (gr_funcptr) _gr_qqbar_set_fexpr}, {GR_METHOD_NEG, (gr_funcptr) _gr_qqbar_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_qqbar_add}, {GR_METHOD_ADD_UI, (gr_funcptr) _gr_qqbar_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) _gr_qqbar_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_qqbar_add_fmpz}, {GR_METHOD_ADD_FMPQ, (gr_funcptr) _gr_qqbar_add_fmpq}, {GR_METHOD_SUB, (gr_funcptr) _gr_qqbar_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) _gr_qqbar_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) _gr_qqbar_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) _gr_qqbar_sub_fmpz}, {GR_METHOD_SUB_FMPQ, (gr_funcptr) _gr_qqbar_sub_fmpq}, {GR_METHOD_MUL, (gr_funcptr) _gr_qqbar_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) _gr_qqbar_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) _gr_qqbar_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) _gr_qqbar_mul_fmpz}, {GR_METHOD_MUL_FMPQ, (gr_funcptr) _gr_qqbar_mul_fmpq}, {GR_METHOD_DIV, (gr_funcptr) _gr_qqbar_div}, {GR_METHOD_DIV_UI, (gr_funcptr) _gr_qqbar_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) _gr_qqbar_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) _gr_qqbar_div_fmpz}, {GR_METHOD_DIV_FMPQ, (gr_funcptr) _gr_qqbar_div_fmpq}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) _gr_qqbar_is_invertible}, {GR_METHOD_INV, (gr_funcptr) _gr_qqbar_inv}, {GR_METHOD_POW, (gr_funcptr) _gr_qqbar_pow}, {GR_METHOD_POW_UI, (gr_funcptr) _gr_qqbar_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) _gr_qqbar_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) _gr_qqbar_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) _gr_qqbar_pow_fmpq}, {GR_METHOD_IS_SQUARE, (gr_funcptr) _gr_qqbar_is_square}, {GR_METHOD_SQRT, (gr_funcptr) _gr_qqbar_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_qqbar_rsqrt}, {GR_METHOD_NUMERATOR, (gr_funcptr) _gr_qqbar_numerator}, {GR_METHOD_DENOMINATOR, (gr_funcptr) _gr_qqbar_denominator}, {GR_METHOD_FLOOR, (gr_funcptr) _gr_qqbar_floor}, {GR_METHOD_CEIL, (gr_funcptr) _gr_qqbar_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) _gr_qqbar_trunc}, {GR_METHOD_NINT, (gr_funcptr) _gr_qqbar_nint}, {GR_METHOD_CMP, (gr_funcptr) _gr_qqbar_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) _gr_qqbar_cmpabs}, {GR_METHOD_I, (gr_funcptr) _gr_qqbar_i}, {GR_METHOD_ABS, (gr_funcptr) _gr_qqbar_abs}, {GR_METHOD_CONJ, (gr_funcptr) _gr_qqbar_conj}, {GR_METHOD_RE, (gr_funcptr) _gr_qqbar_re}, {GR_METHOD_IM, (gr_funcptr) _gr_qqbar_im}, {GR_METHOD_SGN, (gr_funcptr) _gr_qqbar_sgn}, {GR_METHOD_CSGN, (gr_funcptr) _gr_qqbar_csgn}, {GR_METHOD_PI, (gr_funcptr) gr_not_in_domain}, {GR_METHOD_EXP_PI_I, (gr_funcptr) _gr_qqbar_exp_pi_i}, {GR_METHOD_SIN_PI, (gr_funcptr) _gr_qqbar_sin_pi}, {GR_METHOD_COS_PI, (gr_funcptr) _gr_qqbar_cos_pi}, {GR_METHOD_TAN_PI, (gr_funcptr) _gr_qqbar_tan_pi}, {GR_METHOD_COT_PI, (gr_funcptr) _gr_qqbar_cot_pi}, {GR_METHOD_SEC_PI, (gr_funcptr) _gr_qqbar_sec_pi}, {GR_METHOD_CSC_PI, (gr_funcptr) _gr_qqbar_csc_pi}, {GR_METHOD_LOG_PI_I, (gr_funcptr) _gr_qqbar_log_pi_i}, {GR_METHOD_ASIN_PI, (gr_funcptr) _gr_qqbar_asin_pi}, {GR_METHOD_ACOS_PI, (gr_funcptr) _gr_qqbar_acos_pi}, {GR_METHOD_ATAN_PI, (gr_funcptr) _gr_qqbar_atan_pi}, {GR_METHOD_ACOT_PI, (gr_funcptr) _gr_qqbar_acot_pi}, {GR_METHOD_ASEC_PI, (gr_funcptr) _gr_qqbar_asec_pi}, {GR_METHOD_ACSC_PI, (gr_funcptr) _gr_qqbar_acsc_pi}, {GR_METHOD_POLY_ROOTS_OTHER, (gr_funcptr) _gr_qqbar_poly_roots_other}, {0, (gr_funcptr) NULL}, }; void gr_ctx_init_real_qqbar(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_REAL_ALGEBRAIC_QQBAR; ctx->sizeof_elem = sizeof(qqbar_struct); ctx->size_limit = WORD_MAX; QQBAR_CTX(ctx)->real_only = 1; QQBAR_CTX(ctx)->deg_limit = WORD_MAX; QQBAR_CTX(ctx)->bits_limit = WORD_MAX; ctx->methods = _qqbar_methods; if (!_qqbar_methods_initialized) { gr_method_tab_init(_qqbar_methods, _qqbar_methods_input); _qqbar_methods_initialized = 1; } } void gr_ctx_init_complex_qqbar(gr_ctx_t ctx) { ctx->which_ring = GR_CTX_COMPLEX_ALGEBRAIC_QQBAR; ctx->sizeof_elem = sizeof(qqbar_struct); ctx->size_limit = WORD_MAX; QQBAR_CTX(ctx)->real_only = 0; QQBAR_CTX(ctx)->deg_limit = WORD_MAX; QQBAR_CTX(ctx)->bits_limit = WORD_MAX; ctx->methods = _qqbar_methods; if (!_qqbar_methods_initialized) { gr_method_tab_init(_qqbar_methods, _qqbar_methods_input); _qqbar_methods_initialized = 1; } } flint-3.1.3/src/gr/series.c000066400000000000000000002105621461254215100154760ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_generic.h" #ifdef __GNUC__ # define strcmp __builtin_strcmp #else # include #endif /* arb wrappers todo: elementary functions; pfq, coulomb, zeta/dirichlet deflated */ static const char * default_var = "x"; int gr_poly_add_series(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); gr_poly_fit_length(res, max, ctx); status |= _gr_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); _gr_poly_set_length(res, max, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_sub_series(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); gr_poly_fit_length(res, max, ctx); status |= _gr_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); _gr_poly_set_length(res, max, ctx); _gr_poly_normalise(res, ctx); return status; } #define SERIES_ERR_EXACT WORD_MAX #define SERIES_ERR_MAX WORD_MAX / 4 typedef struct { gr_poly_struct poly; slong error; } gr_series_struct; typedef gr_series_struct gr_series_t[1]; typedef struct { slong mod; /* exact truncation */ slong prec; /* default approximate truncation */ } gr_series_ctx_struct; typedef gr_series_ctx_struct gr_series_ctx_t[1]; void gr_series_init(gr_series_t res, gr_series_ctx_t sctx, gr_ctx_t cctx) { gr_poly_init(&res->poly, cctx); res->error = SERIES_ERR_EXACT; } void gr_series_clear(gr_series_t res, gr_series_ctx_t sctx, gr_ctx_t cctx) { gr_poly_clear(&res->poly, cctx); } int gr_series_zero(gr_series_t res, gr_series_ctx_t sctx, gr_ctx_t cctx) { res->error = SERIES_ERR_EXACT; return gr_poly_zero(&res->poly, cctx); } void gr_series_swap(gr_series_t x, gr_series_t y, gr_series_ctx_t sctx, gr_ctx_t cctx) { gr_series_t tmp; *tmp = *x; *x = *y; *y = *tmp; } int gr_series_randtest(gr_series_t res, flint_rand_t state, slong len, gr_series_ctx_t sctx, gr_ctx_t cctx) { int status = gr_poly_randtest(&res->poly, state, len, cctx); len = FLINT_MAX(len, 0); len = FLINT_MIN(len, SERIES_ERR_MAX); if (n_randint(state, 2)) res->error = SERIES_ERR_EXACT; else res->error = n_randint(state, len + 1); return status; } int gr_series_write(gr_stream_t out, const gr_series_t x, const char * var, gr_series_ctx_t sctx, gr_ctx_t cctx) { gr_poly_write(out, &x->poly, var, cctx); if (x->error != SERIES_ERR_EXACT) { gr_stream_write(out, " + O("); gr_stream_write(out, var); gr_stream_write(out, "^"); gr_stream_write_si(out, x->error); gr_stream_write(out, ")"); } if (sctx->mod != SERIES_ERR_EXACT) { gr_stream_write(out, " (mod "); gr_stream_write(out, var); gr_stream_write(out, "^"); gr_stream_write_si(out, sctx->mod); gr_stream_write(out, ")"); } return GR_SUCCESS; } int gr_series_one(gr_series_t res, gr_series_ctx_t sctx, gr_ctx_t cctx) { if (sctx->mod == 0) { res->error = SERIES_ERR_EXACT; return gr_poly_zero(&res->poly, cctx); } else if (sctx->prec == 0) { res->error = 0; return gr_poly_zero(&res->poly, cctx); } else { res->error = SERIES_ERR_EXACT; return gr_poly_one(&res->poly, cctx); } } /* todo: truncate without set */ int gr_series_set(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { int status = GR_SUCCESS; slong len, trunc; res->error = x->error; status |= gr_poly_set(&res->poly, &x->poly, cctx); trunc = FLINT_MIN(sctx->prec, sctx->mod); trunc = FLINT_MIN(trunc, res->error); len = res->poly.length; if (len > trunc) { if (len <= sctx->mod) res->error = SERIES_ERR_EXACT; if (len > sctx->prec) res->error = FLINT_MIN(res->error, sctx->prec); status |= gr_poly_truncate(&res->poly, &res->poly, trunc, cctx); } return status; } int gr_series_gen(gr_series_t res, gr_series_ctx_t sctx, gr_ctx_t cctx) { int status = GR_SUCCESS; status |= gr_poly_zero(&res->poly, cctx); status |= gr_poly_set_coeff_ui(&res->poly, 1, 1, cctx); res->error = SERIES_ERR_EXACT; /* force truncation if needed */ status |= gr_series_set(res, res, sctx, cctx); return status; } /* todo: truncate before neg */ int gr_series_neg(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { int status = GR_SUCCESS; slong len, trunc; res->error = x->error; status |= gr_poly_neg(&res->poly, &x->poly, cctx); trunc = FLINT_MIN(sctx->prec, sctx->mod); trunc = FLINT_MIN(trunc, res->error); len = res->poly.length; if (len > trunc) { if (len <= sctx->mod) res->error = SERIES_ERR_EXACT; if (len > sctx->prec) res->error = FLINT_MIN(res->error, sctx->prec); status |= gr_poly_truncate(&res->poly, &res->poly, trunc, cctx); } return status; } int gr_series_set_gr_poly(gr_series_t res, const gr_poly_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { gr_series_t tmp; tmp->poly = *x; tmp->error = SERIES_ERR_EXACT; return gr_series_set(res, tmp, sctx, cctx); } int gr_series_set_scalar(gr_series_t res, gr_srcptr x, gr_series_ctx_t sctx, gr_ctx_t cctx) { if (gr_is_zero(x, cctx) == T_TRUE) { return gr_series_zero(res, sctx, cctx); } else { gr_series_t tmp; tmp->poly.coeffs = (gr_ptr) x; tmp->poly.length = 1; tmp->poly.alloc = 1; tmp->error = SERIES_ERR_EXACT; return gr_series_set(res, tmp, sctx, cctx); } } int gr_series_set_si(gr_series_t res, slong c, gr_series_ctx_t sctx, gr_ctx_t cctx) { if (c == 0) { return gr_series_zero(res, sctx, cctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, cctx); status |= gr_set_si(t, c, cctx); status |= gr_series_set_scalar(res, t, sctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } int gr_series_set_ui(gr_series_t res, ulong c, gr_series_ctx_t sctx, gr_ctx_t cctx) { if (c == 0) { return gr_series_zero(res, sctx, cctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, cctx); status |= gr_set_ui(t, c, cctx); status |= gr_series_set_scalar(res, t, sctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } int gr_series_set_fmpz(gr_series_t res, const fmpz_t c, gr_series_ctx_t sctx, gr_ctx_t cctx) { if (fmpz_is_zero(c)) { return gr_series_zero(res, sctx, cctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, cctx); status |= gr_set_fmpz(t, c, cctx); status |= gr_series_set_scalar(res, t, sctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } /* todo: division by zero valid mod x^0? */ int gr_series_set_fmpq(gr_series_t res, const fmpq_t c, gr_series_ctx_t sctx, gr_ctx_t cctx) { if (fmpq_is_zero(c)) { return gr_series_zero(res, sctx, cctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, cctx); status |= gr_set_fmpq(t, c, cctx); status |= gr_series_set_scalar(res, t, sctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } truth_t gr_series_is_zero(const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { truth_t is_zero; is_zero = gr_poly_is_zero(&x->poly, cctx); if (is_zero == T_FALSE) return T_FALSE; if (x->error == SERIES_ERR_EXACT && is_zero == T_TRUE) return T_TRUE; return T_UNKNOWN; } /* todo: recursive version */ int gr_series_make_exact(gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { x->error = SERIES_ERR_EXACT; return GR_SUCCESS; } truth_t _gr_poly_equal2(gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { truth_t eq, eq2; slong sz = ctx->sizeof_elem; eq = _gr_vec_equal(poly1, poly2, len2, ctx); if (len1 == len2 || eq == T_FALSE) return eq; eq2 = _gr_vec_is_zero(GR_ENTRY(poly1, len2, sz), len1 - len2, ctx); return truth_and(eq, eq2); } truth_t gr_series_is_one(const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { truth_t is_zero, is_one; slong xlen = x->poly.length; if (x->error <= 0) return T_UNKNOWN; if (sctx->mod == 0) return T_TRUE; if (xlen == 0) { /* deal with characteristic 0 */ if (gr_ctx_is_finite_characteristic(cctx) != T_FALSE) { gr_ptr tmp; GR_TMP_INIT(tmp, cctx); is_one = gr_is_one(tmp, cctx); GR_TMP_CLEAR(tmp, cctx); return is_one; } return T_FALSE; } is_one = gr_is_one(x->poly.coeffs, cctx); if (is_one == T_FALSE) return T_FALSE; if (xlen >= 2) { is_zero = _gr_vec_is_zero(GR_ENTRY(x->poly.coeffs, 1, cctx->sizeof_elem), FLINT_MIN(xlen - 1, x->error - 1), cctx); if (is_zero == T_FALSE) return T_FALSE; } else { is_zero = T_TRUE; } if (x->error == SERIES_ERR_EXACT && is_zero == T_TRUE && is_one == T_TRUE) return T_TRUE; return T_UNKNOWN; } truth_t gr_series_equal(const gr_series_t x, const gr_series_t y, gr_series_ctx_t sctx, gr_ctx_t cctx) { truth_t equal; slong len, xlen, ylen, xerr, yerr, err; xlen = x->poly.length; ylen = y->poly.length; xerr = x->error; yerr = y->error; err = FLINT_MIN(xerr, yerr); len = FLINT_MAX(xlen, ylen); len = FLINT_MIN(len, sctx->mod); len = FLINT_MIN(len, err); /* compare exactly or within the error bound */ if (xlen >= ylen) equal = _gr_poly_equal2(x->poly.coeffs, FLINT_MIN(xlen, len), y->poly.coeffs, FLINT_MIN(ylen, len), cctx); else equal = _gr_poly_equal2(y->poly.coeffs, FLINT_MIN(ylen, len), x->poly.coeffs, FLINT_MIN(xlen, len), cctx); if (equal == T_FALSE) return T_FALSE; /* terms >= x^mod are zero by definition */ if (err >= sctx->mod && equal == T_TRUE) return T_TRUE; return T_UNKNOWN; } int gr_series_add(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong len, xlen, ylen, xerr, yerr, err; int status = GR_SUCCESS; xlen = x->poly.length; ylen = y->poly.length; xerr = x->error; yerr = y->error; err = FLINT_MIN(xerr, yerr); /* length of the polynomial sum, ignoring errors */ len = FLINT_MAX(xlen, ylen); /* the result will be truncated */ if (len > sctx->prec) err = FLINT_MIN(err, sctx->prec); len = FLINT_MIN(len, sctx->mod); len = FLINT_MIN(len, sctx->prec); len = FLINT_MIN(len, err); /* terms >= x^mod are zero by definition */ if (err >= sctx->mod) err = SERIES_ERR_EXACT; res->error = err; status |= gr_poly_add_series(&res->poly, &x->poly, &y->poly, len, cctx); return status; } int gr_series_sub(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong len, xlen, ylen, xerr, yerr, err; int status = GR_SUCCESS; xlen = x->poly.length; ylen = y->poly.length; xerr = x->error; yerr = y->error; err = FLINT_MIN(xerr, yerr); /* length of the polynomial sum, ignoring errors */ len = FLINT_MAX(xlen, ylen); /* the result will be truncated */ if (len > sctx->prec) err = FLINT_MIN(err, sctx->prec); len = FLINT_MIN(len, sctx->mod); len = FLINT_MIN(len, sctx->prec); len = FLINT_MIN(len, err); /* terms >= x^mod are zero by definition */ if (err >= sctx->mod) err = SERIES_ERR_EXACT; res->error = err; status |= gr_poly_sub_series(&res->poly, &x->poly, &y->poly, len, cctx); return status; } int gr_series_mul(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong len, xlen, ylen, xerr, yerr, err; int status = GR_SUCCESS; xlen = x->poly.length; ylen = y->poly.length; xerr = x->error; yerr = y->error; err = FLINT_MIN(xerr, yerr); if (xlen == 0 && xerr == SERIES_ERR_EXACT) return gr_series_zero(res, sctx, cctx); if (ylen == 0 && yerr == SERIES_ERR_EXACT) return gr_series_zero(res, sctx, cctx); /* length of the polynomial product, ignoring errors */ if (xlen == 0 || ylen == 0) len = 0; else len = xlen + ylen - 1; /* the result will be truncated */ if (len > sctx->prec) err = FLINT_MIN(err, sctx->prec); len = FLINT_MIN(len, sctx->mod); len = FLINT_MIN(len, sctx->prec); len = FLINT_MIN(len, err); /* terms >= x^mod are zero by definition */ if (err >= sctx->mod) err = SERIES_ERR_EXACT; res->error = err; status |= gr_poly_mullow(&res->poly, &x->poly, &y->poly, len, cctx); return status; } int gr_series_inv(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong len, xlen, xerr, err; int status = GR_SUCCESS; xlen = x->poly.length; xerr = x->error; err = xerr; if (xlen == 0 && sctx->mod == 0) return gr_series_zero(res, sctx, cctx); if (xlen == 0 && xerr == SERIES_ERR_EXACT) { truth_t zero = gr_ctx_is_zero_ring(cctx); if (zero == T_TRUE) return gr_series_zero(res, sctx, cctx); if (zero == T_UNKNOWN) return GR_UNABLE; return GR_DOMAIN; } if (xlen == 0 || xerr == 0) return GR_UNABLE; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; /* terms >= x^mod are zero by definition */ if (err >= sctx->mod) err = SERIES_ERR_EXACT; res->error = err; status |= gr_poly_inv_series(&res->poly, &x->poly, len, cctx); return status; } /* todo: handle valuations */ int gr_series_div(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong len, ylen, xerr, yerr, err; int status = GR_SUCCESS; ylen = y->poly.length; xerr = x->error; yerr = y->error; if (ylen == 0 && yerr == SERIES_ERR_EXACT) return GR_DOMAIN; if (ylen == 0 || yerr == 0) return GR_UNABLE; err = FLINT_MIN(xerr, yerr); err = FLINT_MIN(err, sctx->prec); len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); /* terms >= x^mod are zero by definition */ if (err >= sctx->mod) err = SERIES_ERR_EXACT; res->error = err; status |= gr_poly_div_series(&res->poly, &x->poly, &y->poly, len, cctx); return status; } int gr_series_sqrt(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong len, xlen, xerr, err; int status = GR_SUCCESS; xlen = x->poly.length; xerr = x->error; err = xerr; if (xlen == 0 && xerr == SERIES_ERR_EXACT) return gr_series_zero(res, sctx, cctx); if (xlen == 0 || xerr == 0) return GR_UNABLE; if (xlen > 1 && gr_is_zero(x->poly.coeffs, cctx) != T_FALSE) return GR_UNABLE; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; /* terms >= x^mod are zero by definition */ if (err >= sctx->mod) err = SERIES_ERR_EXACT; res->error = err; status |= gr_poly_sqrt_series(&res->poly, &x->poly, len, cctx); return status; } #define UNARY_POLY_WRAPPER(func) \ int \ gr_series_ ## func(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) \ { \ slong len, xlen, xerr, err; \ int status = GR_SUCCESS; \ \ xlen = x->poly.length; \ xerr = x->error; \ err = xerr; \ \ len = FLINT_MIN(sctx->mod, sctx->prec); \ len = FLINT_MIN(len, err); \ err = len; \ \ if (xlen <= 1 && xerr == SERIES_ERR_EXACT) \ { \ len = FLINT_MIN(len, 1); \ err = SERIES_ERR_EXACT; \ } \ \ if (err >= sctx->mod) \ err = SERIES_ERR_EXACT; \ \ res->error = err; \ status |= gr_poly_ ## func ## _series(&res->poly, &x->poly, len, cctx); \ return status; \ } \ UNARY_POLY_WRAPPER(exp) UNARY_POLY_WRAPPER(log) UNARY_POLY_WRAPPER(rsqrt) UNARY_POLY_WRAPPER(tan) UNARY_POLY_WRAPPER(asin) UNARY_POLY_WRAPPER(acos) UNARY_POLY_WRAPPER(atan) UNARY_POLY_WRAPPER(asinh) UNARY_POLY_WRAPPER(acosh) UNARY_POLY_WRAPPER(atanh) #include "arb_poly.h" #include "acb_poly.h" #include "arb_hypgeom.h" #include "acb_hypgeom.h" #include "acb_dirichlet.h" #include "acb_elliptic.h" #include "acb_modular.h" #define ARB_WRAPPER(func, arb_func, acb_func) \ int \ gr_series_ ## func(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) \ { \ slong xlen, len, xerr, err; \ slong prec; \ int status = GR_SUCCESS; \ \ if (cctx->which_ring != GR_CTX_RR_ARB && cctx->which_ring != GR_CTX_CC_ACB) \ return GR_UNABLE; \ \ xlen = x->poly.length; \ xerr = x->error; \ err = xerr; \ \ len = FLINT_MIN(sctx->mod, sctx->prec); \ len = FLINT_MIN(len, err); \ err = len; \ \ if (err >= sctx->mod) \ err = SERIES_ERR_EXACT; \ \ if (xlen <= 1 && xerr == SERIES_ERR_EXACT) \ { \ len = FLINT_MIN(len, 1); \ err = SERIES_ERR_EXACT; \ } \ \ res->error = err; \ \ prec = _gr_ctx_get_real_prec(cctx); \ \ if (cctx->which_ring == GR_CTX_RR_ARB) \ { \ arb_func((arb_poly_struct *) &res->poly, (arb_poly_struct *) &x->poly, len, prec); \ if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, res->poly.length)) \ status = GR_UNABLE; \ } \ else \ { \ acb_func((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, len, prec); \ if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) \ status = GR_UNABLE; \ } \ \ return status; \ } \ ARB_WRAPPER(gamma, arb_poly_gamma_series, acb_poly_gamma_series) ARB_WRAPPER(rgamma, arb_poly_rgamma_series, acb_poly_rgamma_series) ARB_WRAPPER(lgamma, arb_poly_lgamma_series, acb_poly_lgamma_series) ARB_WRAPPER(digamma, arb_poly_digamma_series, acb_poly_digamma_series) ARB_WRAPPER(erf, arb_hypgeom_erf_series, acb_hypgeom_erf_series) ARB_WRAPPER(erfc, arb_hypgeom_erfc_series, acb_hypgeom_erfc_series) ARB_WRAPPER(erfi, arb_hypgeom_erfi_series, acb_hypgeom_erfi_series) ARB_WRAPPER(exp_integral_ei, arb_hypgeom_ei_series, acb_hypgeom_ei_series) ARB_WRAPPER(cos_integral, arb_hypgeom_ci_series, acb_hypgeom_ci_series) ARB_WRAPPER(cosh_integral, arb_hypgeom_chi_series, acb_hypgeom_chi_series) ARB_WRAPPER(sin_integral, arb_hypgeom_si_series, acb_hypgeom_si_series) ARB_WRAPPER(sinh_integral, arb_hypgeom_shi_series, acb_hypgeom_shi_series) int gr_series_fresnel(gr_series_t res1, gr_series_t res2, const gr_series_t x, int normalized, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_RR_ARB && cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } if (res1 != NULL) res1->error = err; if (res2 != NULL) res2->error = err; prec = _gr_ctx_get_real_prec(cctx); if (cctx->which_ring == GR_CTX_RR_ARB) { arb_hypgeom_fresnel_series(res1 ? (arb_poly_struct *) &res1->poly : NULL, res2 ? (arb_poly_struct *) &res2->poly : NULL, (arb_poly_struct *) &x->poly, normalized, len, prec); if (res1 && !_arb_vec_is_finite((arb_ptr) res1->poly.coeffs, res1->poly.length)) status = GR_UNABLE; if (res2 && !_arb_vec_is_finite((arb_ptr) res2->poly.coeffs, res2->poly.length)) status = GR_UNABLE; } else { acb_hypgeom_fresnel_series(res1 ? (acb_poly_struct *) &res1->poly : NULL, res2 ? (acb_poly_struct *) &res2->poly : NULL, (acb_poly_struct *) &x->poly, normalized, len, prec); if (res1 && !_arb_vec_is_finite((arb_ptr) res1->poly.coeffs, 2 * res1->poly.length)) status = GR_UNABLE; if (res2 && !_arb_vec_is_finite((arb_ptr) res2->poly.coeffs, 2 * res2->poly.length)) status = GR_UNABLE; } return status; } int gr_series_fresnel_s(gr_series_t res, const gr_series_t x, int normalized, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_fresnel(res, NULL, x, normalized, sctx, cctx); } int gr_series_fresnel_c(gr_series_t res, const gr_series_t x, int normalized, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_fresnel(NULL, res, x, normalized, sctx, cctx); } int gr_series_airy(gr_series_t res1, gr_series_t res2, gr_series_t res3, gr_series_t res4, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_RR_ARB && cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } if (res1 != NULL) res1->error = err; if (res2 != NULL) res2->error = err; if (res3 != NULL) res3->error = err; if (res4 != NULL) res4->error = err; prec = _gr_ctx_get_real_prec(cctx); if (cctx->which_ring == GR_CTX_RR_ARB) { arb_hypgeom_airy_series(res1 ? (arb_poly_struct *) &res1->poly : NULL, res2 ? (arb_poly_struct *) &res2->poly : NULL, res3 ? (arb_poly_struct *) &res3->poly : NULL, res4 ? (arb_poly_struct *) &res4->poly : NULL, (arb_poly_struct *) &x->poly, len, prec); if (res1 && !_arb_vec_is_finite((arb_ptr) res1->poly.coeffs, res1->poly.length)) status = GR_UNABLE; if (res2 && !_arb_vec_is_finite((arb_ptr) res2->poly.coeffs, res2->poly.length)) status = GR_UNABLE; if (res3 && !_arb_vec_is_finite((arb_ptr) res3->poly.coeffs, res3->poly.length)) status = GR_UNABLE; if (res4 && !_arb_vec_is_finite((arb_ptr) res4->poly.coeffs, res4->poly.length)) status = GR_UNABLE; } else { acb_hypgeom_airy_series(res1 ? (acb_poly_struct *) &res1->poly : NULL, res2 ? (acb_poly_struct *) &res2->poly : NULL, res3 ? (acb_poly_struct *) &res3->poly : NULL, res4 ? (acb_poly_struct *) &res4->poly : NULL, (acb_poly_struct *) &x->poly, len, prec); if (res1 && !_arb_vec_is_finite((arb_ptr) res1->poly.coeffs, 2 * res1->poly.length)) status = GR_UNABLE; if (res2 && !_arb_vec_is_finite((arb_ptr) res2->poly.coeffs, 2 * res2->poly.length)) status = GR_UNABLE; if (res3 && !_arb_vec_is_finite((arb_ptr) res3->poly.coeffs, 2 * res3->poly.length)) status = GR_UNABLE; if (res4 && !_arb_vec_is_finite((arb_ptr) res4->poly.coeffs, 2 * res4->poly.length)) status = GR_UNABLE; } return status; } int gr_series_airy_ai(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_airy(res, NULL, NULL, NULL, x, sctx, cctx); } int gr_series_airy_ai_prime(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_airy(NULL, res, NULL, NULL, x, sctx, cctx); } int gr_series_airy_bi(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_airy(NULL, NULL, res, NULL, x, sctx, cctx); } int gr_series_airy_bi_prime(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_airy(NULL, NULL, NULL, res, x, sctx, cctx); } int gr_series_log_integral(gr_series_t res, const gr_series_t x, int offset, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_RR_ARB && cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } res->error = err; prec = _gr_ctx_get_real_prec(cctx); if (cctx->which_ring == GR_CTX_RR_ARB) { arb_hypgeom_li_series((arb_poly_struct *) &res->poly, (arb_poly_struct *) &x->poly, offset, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, res->poly.length)) status = GR_UNABLE; \ } else { acb_hypgeom_li_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, offset, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; } return status; } int gr_series_gamma_upper(gr_series_t res, const gr_series_t s, const gr_series_t x, int regularized, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_RR_ARB && cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } /* we only handle constant s */ if (len >= 2 && s->poly.length >= 2) return GR_UNABLE; res->error = err; prec = _gr_ctx_get_real_prec(cctx); if (cctx->which_ring == GR_CTX_RR_ARB) { arb_t t; arb_init(t); arb_poly_get_coeff_arb(t, (arb_poly_struct *) &s->poly, 0); arb_hypgeom_gamma_upper_series((arb_poly_struct *) &res->poly, t, (arb_poly_struct *) &x->poly, regularized, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, res->poly.length)) status = GR_UNABLE; arb_clear(t); } else { acb_t t; acb_init(t); acb_poly_get_coeff_acb(t, (acb_poly_struct *) &s->poly, 0); acb_hypgeom_gamma_upper_series((acb_poly_struct *) &res->poly, t, (acb_poly_struct *) &x->poly, regularized, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; acb_clear(t); } return status; } int gr_series_gamma_lower(gr_series_t res, const gr_series_t s, const gr_series_t x, int regularized, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_RR_ARB && cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } /* we only handle constant s */ if (len >= 2 && s->poly.length >= 2) return GR_UNABLE; res->error = err; prec = _gr_ctx_get_real_prec(cctx); if (cctx->which_ring == GR_CTX_RR_ARB) { arb_t t; arb_init(t); arb_poly_get_coeff_arb(t, (arb_poly_struct *) &s->poly, 0); arb_hypgeom_gamma_lower_series((arb_poly_struct *) &res->poly, t, (arb_poly_struct *) &x->poly, regularized, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, res->poly.length)) status = GR_UNABLE; arb_clear(t); } else { acb_t t; acb_init(t); acb_poly_get_coeff_acb(t, (acb_poly_struct *) &s->poly, 0); acb_hypgeom_gamma_lower_series((acb_poly_struct *) &res->poly, t, (acb_poly_struct *) &x->poly, regularized, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; acb_clear(t); } return status; } int gr_series_beta_lower(gr_series_t res, const gr_series_t a, const gr_series_t b, const gr_series_t x, int regularized, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_RR_ARB && cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } /* we only handle constant a, b */ if (len >= 2 && a->poly.length >= 2) return GR_UNABLE; if (len >= 2 && b->poly.length >= 2) return GR_UNABLE; res->error = err; prec = _gr_ctx_get_real_prec(cctx); if (cctx->which_ring == GR_CTX_RR_ARB) { arb_t t, u; arb_init(t); arb_init(u); arb_poly_get_coeff_arb(t, (arb_poly_struct *) &a->poly, 0); arb_poly_get_coeff_arb(u, (arb_poly_struct *) &b->poly, 0); arb_hypgeom_beta_lower_series((arb_poly_struct *) &res->poly, t, u, (arb_poly_struct *) &x->poly, regularized, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, res->poly.length)) status = GR_UNABLE; arb_clear(t); arb_clear(u); } else { acb_t t, u; acb_init(t); acb_init(u); acb_poly_get_coeff_acb(t, (acb_poly_struct *) &a->poly, 0); acb_poly_get_coeff_acb(u, (acb_poly_struct *) &b->poly, 0); acb_hypgeom_beta_lower_series((acb_poly_struct *) &res->poly, t, u, (acb_poly_struct *) &x->poly, regularized, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; acb_clear(t); acb_clear(u); } return status; } int gr_series_polylog(gr_series_t res, const gr_series_t s, const gr_series_t z, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = s->poly.length; xerr = s->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } /* we only handle constant z */ if (len >= 2 && z->poly.length >= 2) return GR_UNABLE; res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_t t; acb_init(t); acb_poly_get_coeff_acb(t, (acb_poly_struct *) &z->poly, 0); acb_poly_polylog_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &s->poly, t, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; acb_clear(t); } return status; } int gr_series_hurwitz_zeta(gr_series_t res, const gr_series_t s, const gr_series_t z, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = s->poly.length; xerr = s->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } /* we only handle constant z */ if (len >= 2 && z->poly.length >= 2) return GR_UNABLE; res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_t t; acb_init(t); acb_poly_get_coeff_acb(t, (acb_poly_struct *) &z->poly, 0); acb_poly_zeta_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &s->poly, t, 0, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; acb_clear(t); } return status; } int gr_series_dirichlet_l(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_dirichlet_l_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, G, chi, 0, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; } return status; } int gr_series_dirichlet_hardy_theta(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_dirichlet_hardy_theta_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, G, chi, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; } return status; } int gr_series_dirichlet_hardy_z(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_dirichlet_hardy_z_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, G, chi, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; } return status; } int gr_series_jacobi_theta(gr_series_t res1, gr_series_t res2, gr_series_t res3, gr_series_t res4, const gr_series_t x, const gr_series_t tau, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } /* we only handle constant z */ if (len >= 2 && tau->poly.length >= 2) return GR_UNABLE; if (res1 != NULL) res1->error = err; if (res2 != NULL) res2->error = err; if (res3 != NULL) res3->error = err; if (res4 != NULL) res4->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_t t; acb_init(t); acb_poly_get_coeff_acb(t, (acb_poly_struct *) &tau->poly, 0); acb_modular_theta_series(res1 ? (acb_poly_struct *) &res1->poly : NULL, res2 ? (acb_poly_struct *) &res2->poly : NULL, res3 ? (acb_poly_struct *) &res3->poly : NULL, res4 ? (acb_poly_struct *) &res4->poly : NULL, (acb_poly_struct *) &x->poly, t, len, prec); if (res1 && !_arb_vec_is_finite((arb_ptr) res1->poly.coeffs, 2 * res1->poly.length)) status = GR_UNABLE; if (res2 && !_arb_vec_is_finite((arb_ptr) res2->poly.coeffs, 2 * res2->poly.length)) status = GR_UNABLE; if (res3 && !_arb_vec_is_finite((arb_ptr) res3->poly.coeffs, 2 * res3->poly.length)) status = GR_UNABLE; if (res4 && !_arb_vec_is_finite((arb_ptr) res4->poly.coeffs, 2 * res4->poly.length)) status = GR_UNABLE; acb_clear(t); } return status; } int gr_series_jacobi_theta_1(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_jacobi_theta(res, NULL, NULL, NULL, x, tau, sctx, cctx); } int gr_series_jacobi_theta_2(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_jacobi_theta(NULL, res, NULL, NULL, x, tau, sctx, cctx); } int gr_series_jacobi_theta_3(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_jacobi_theta(NULL, NULL, res, NULL, x, tau, sctx, cctx); } int gr_series_jacobi_theta_4(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_series_ctx_t sctx, gr_ctx_t cctx) { return gr_series_jacobi_theta(NULL, NULL, NULL, res, x, tau, sctx, cctx); } int gr_series_agm1(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_poly_agm1_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; } return status; } int gr_series_elliptic_k(gr_series_t res, const gr_series_t x, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_poly_elliptic_k_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; } return status; } int gr_series_weierstrass_p(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong xlen, len, xerr, err; slong prec; int status = GR_SUCCESS; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; xlen = x->poly.length; xerr = x->error; err = xerr; len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; if (xlen <= 1 && xerr == SERIES_ERR_EXACT) { len = FLINT_MIN(len, 1); err = SERIES_ERR_EXACT; } /* we only handle constant tau */ if (len >= 2 && tau->poly.length >= 2) return GR_UNABLE; res->error = err; prec = _gr_ctx_get_real_prec(cctx); { acb_t t; acb_init(t); acb_poly_get_coeff_acb(t, (acb_poly_struct *) &tau->poly, 0); acb_elliptic_p_series((acb_poly_struct *) &res->poly, (acb_poly_struct *) &x->poly, t, len, prec); if (!_arb_vec_is_finite((arb_ptr) res->poly.coeffs, 2 * res->poly.length)) status = GR_UNABLE; acb_clear(t); } return status; } typedef struct { gr_series_struct * entries; slong alloc; slong length; } gr_series_vec_struct; typedef gr_series_vec_struct gr_series_vec_t[1]; int gr_series_hypgeom_pfq(gr_series_t res, const gr_series_vec_t a, const gr_series_vec_t b, const gr_series_t x, int regularized, gr_series_ctx_t sctx, gr_ctx_t cctx) { slong len, err, i; slong prec; slong p, q, pp, qq; int have_one; int status = GR_SUCCESS; acb_poly_struct *aa, *bb; if (cctx->which_ring != GR_CTX_CC_ACB) return GR_UNABLE; p = a->length; q = b->length; err = x->error; for (i = 0; i < p; i++) err = FLINT_MIN(err, a->entries[i].error); for (i = 0; i < q; i++) err = FLINT_MIN(err, b->entries[i].error); len = FLINT_MIN(sctx->mod, sctx->prec); len = FLINT_MIN(len, err); err = len; if (err >= sctx->mod) err = SERIES_ERR_EXACT; aa = GR_TMP_ALLOC(sizeof(acb_poly_struct) * (p + q + 1)); have_one = 0; for (i = 0; i < p; i++) { if (!have_one && acb_poly_is_one((acb_poly_struct *) (&a->entries[i].poly))) { have_one = 1; continue; } aa[i - have_one].coeffs = a->entries[i].poly.coeffs; aa[i - have_one].alloc = a->entries[i].poly.alloc; aa[i - have_one].length = a->entries[i].poly.length; } if (have_one) { pp = p - 1; qq = q; bb = aa + pp; } else { pp = p; qq = q + 1; bb = aa + pp; acb_poly_init(bb + qq - 1); acb_poly_one(bb + qq - 1); } for (i = 0; i < q; i++) { bb[i].coeffs = b->entries[i].poly.coeffs; bb[i].alloc = b->entries[i].poly.alloc; bb[i].length = b->entries[i].poly.length; } prec = _gr_ctx_get_real_prec(cctx); res->error = err; acb_hypgeom_pfq_series_direct((acb_poly_struct *) &res->poly, aa, pp, bb, qq, (const acb_poly_struct *) &x->poly, regularized, -1, len, prec); if (!_acb_vec_is_finite((acb_ptr) res->poly.coeffs, res->poly.length)) status = GR_UNABLE; if (!have_one) acb_poly_clear(bb + qq - 1); GR_TMP_FREE(aa, sizeof(acb_poly_struct) * (p + q + 1)); return status; } typedef struct { gr_ctx_struct * base_ring; gr_series_ctx_struct sctx; char * var; } series_ctx_t; #define SERIES_CTX(ring_ctx) ((series_ctx_t *)((ring_ctx))) #define SERIES_ELEM_CTX(ring_ctx) (SERIES_CTX(ring_ctx)->base_ring) #define SERIES_SCTX(ring_ctx) (&(((series_ctx_t *)((ring_ctx)))->sctx)) static void _gr_gr_series_ctx_clear(gr_ctx_t ctx) { if (SERIES_CTX(ctx)->var != default_var) { flint_free(SERIES_CTX(ctx)->var); } } static int _gr_gr_series_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_stream_write(out, "Power series over "); gr_ctx_write(out, SERIES_ELEM_CTX(ctx)); if (ctx->which_ring == GR_CTX_GR_SERIES_MOD) { gr_stream_write(out, " mod "); gr_stream_write(out, SERIES_CTX(ctx)->var); gr_stream_write(out, "^"); gr_stream_write_si(out, SERIES_SCTX(ctx)->mod); } gr_stream_write(out, " with precision "); gr_stream_write(out, "O("); gr_stream_write(out, SERIES_CTX(ctx)->var); gr_stream_write(out, "^"); gr_stream_write_si(out, SERIES_SCTX(ctx)->prec); gr_stream_write(out, ")"); return GR_SUCCESS; } truth_t _gr_gr_series_ctx_is_ring(gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_GR_SERIES_MOD && SERIES_SCTX(ctx)->mod == 0) return T_TRUE; return gr_ctx_is_ring(SERIES_ELEM_CTX(ctx)); } truth_t _gr_gr_series_ctx_is_commutative_ring(gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_GR_SERIES_MOD && SERIES_SCTX(ctx)->mod == 0) return T_TRUE; return gr_ctx_is_commutative_ring(SERIES_ELEM_CTX(ctx)); } static void _gr_gr_series_init(gr_series_t res, gr_ctx_t ctx) { gr_series_init(res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static void _gr_gr_series_clear(gr_series_t res, gr_ctx_t ctx) { gr_series_clear(res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static void _gr_gr_series_swap(gr_series_t x, gr_series_t y, gr_ctx_t ctx) { gr_series_swap(x, y, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_zero(gr_series_t res, gr_ctx_t ctx) { return gr_series_zero(res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_randtest(gr_series_t res, flint_rand_t state, gr_ctx_t ctx) { return gr_series_randtest(res, state, 6, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_write(gr_stream_t out, const gr_series_t x, gr_ctx_t ctx) { return gr_series_write(out, x, SERIES_CTX(ctx)->var, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_one(gr_series_t res, gr_ctx_t ctx) { return gr_series_one(res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_gen(gr_series_t res, gr_ctx_t ctx) { return gr_series_gen(res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } int _gr_gr_series_ctx_set_gen_name(gr_ctx_t ctx, const char * s) { slong len; len = strlen(s); if (SERIES_CTX(ctx)->var == default_var) SERIES_CTX(ctx)->var = NULL; SERIES_CTX(ctx)->var = flint_realloc(SERIES_CTX(ctx)->var, len + 1); memcpy(SERIES_CTX(ctx)->var, s, len + 1); return GR_SUCCESS; } static int _gr_gr_series_gens_recursive(gr_vec_t vec, gr_ctx_t ctx) { int status; gr_vec_t vec1; slong i, n; /* Get generators of the element ring */ gr_vec_init(vec1, 0, SERIES_ELEM_CTX(ctx)); status = gr_gens_recursive(vec1, SERIES_ELEM_CTX(ctx)); n = vec1->length; gr_vec_set_length(vec, n + 1, ctx); /* Promote to series */ for (i = 0; i < n; i++) status |= gr_poly_set_scalar(gr_vec_entry_ptr(vec, i, ctx), gr_vec_entry_srcptr(vec1, i, SERIES_ELEM_CTX(ctx)), SERIES_ELEM_CTX(ctx)); status |= gr_poly_gen(gr_vec_entry_ptr(vec, n, ctx), SERIES_ELEM_CTX(ctx)); gr_vec_clear(vec1, SERIES_ELEM_CTX(ctx)); return status; } static int _gr_gr_series_set(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_set(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static void _gr_gr_series_set_shallow(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { *res = *x; } static int _gr_gr_series_set_si(gr_series_t res, slong c, gr_ctx_t ctx) { return gr_series_set_si(res, c, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_set_ui(gr_series_t res, ulong c, gr_ctx_t ctx) { return gr_series_set_ui(res, c, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_set_fmpz(gr_series_t res, const fmpz_t c, gr_ctx_t ctx) { return gr_series_set_fmpz(res, c, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_set_fmpq(gr_series_t res, const fmpq_t c, gr_ctx_t ctx) { return gr_series_set_fmpq(res, c, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static truth_t _gr_gr_series_is_zero(const gr_series_t x, gr_ctx_t ctx) { return gr_series_is_zero(x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static truth_t _gr_gr_series_is_one(const gr_series_t x, gr_ctx_t ctx) { return gr_series_is_one(x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static truth_t _gr_gr_series_equal(const gr_series_t x, const gr_series_t y, gr_ctx_t ctx) { return gr_series_equal(x, y, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_neg(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_neg(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_add(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx) { return gr_series_add(res, x, y, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_sub(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx) { return gr_series_sub(res, x, y, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_mul(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx) { return gr_series_mul(res, x, y, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_inv(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_inv(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_div(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx) { return gr_series_div(res, x, y, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_sqrt(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_sqrt(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_rsqrt(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_rsqrt(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_exp(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_exp(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_log(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_log(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_tan(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_tan(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_asin(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_asin(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_acos(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_acos(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_atan(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_atan(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_asinh(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_asinh(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_acosh(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_acosh(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_atanh(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_atanh(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_gamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_gamma(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_rgamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_rgamma(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_lgamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_lgamma(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_digamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_digamma(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_erf(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_erf(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_erfc(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_erfc(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_erfi(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_erfi(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_fresnel(gr_series_t res1, gr_series_t res2, const gr_series_t x, int normalized, gr_ctx_t ctx) { return gr_series_fresnel(res1, res2, x, normalized, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_fresnel_s(gr_series_t res, const gr_series_t x, int normalized, gr_ctx_t ctx) { return gr_series_fresnel_s(res, x, normalized, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_fresnel_c(gr_series_t res, const gr_series_t x, int normalized, gr_ctx_t ctx) { return gr_series_fresnel_c(res, x, normalized, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_airy(gr_series_t res1, gr_series_t res2, gr_series_t res3, gr_series_t res4, const gr_series_t x, gr_ctx_t ctx) { return gr_series_airy(res1, res2, res3, res4, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_airy_ai(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_airy_ai(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_airy_ai_prime(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_airy_ai_prime(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_airy_bi(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_airy_bi(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_airy_bi_prime(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_airy_bi_prime(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_exp_integral_ei(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_erf(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_cos_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_cos_integral(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_cosh_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_cosh_integral(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_sin_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_sin_integral(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_sinh_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_sinh_integral(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_log_integral(gr_series_t res, const gr_series_t x, int offset, gr_ctx_t ctx) { return gr_series_log_integral(res, x, offset, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_gamma_upper(gr_series_t res, const gr_series_t x, const gr_series_t y, int regularized, gr_ctx_t ctx) { return gr_series_gamma_upper(res, x, y, regularized, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_gamma_lower(gr_series_t res, const gr_series_t x, const gr_series_t y, int regularized, gr_ctx_t ctx) { return gr_series_gamma_lower(res, x, y, regularized, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_beta_lower(gr_series_t res, const gr_series_t a, const gr_series_t b, const gr_series_t x, int regularized, gr_ctx_t ctx) { return gr_series_beta_lower(res, a, b, x, regularized, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_hypgeom_pfq(gr_series_t res, const gr_series_vec_t a, const gr_series_vec_t b, const gr_series_t x, int regularized, gr_ctx_t ctx) { return gr_series_hypgeom_pfq(res, a, b, x, regularized, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_polylog(gr_series_t res, const gr_series_t s, const gr_series_t z, gr_ctx_t ctx) { return gr_series_polylog(res, s, z, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_hurwitz_zeta(gr_series_t res, const gr_series_t s, const gr_series_t z, gr_ctx_t ctx) { return gr_series_hurwitz_zeta(res, s, z, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_dirichlet_l(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t s, const gr_series_t z, gr_ctx_t ctx) { return gr_series_dirichlet_l(res, G, chi, s, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_dirichlet_hardy_theta(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t s, const gr_series_t z, gr_ctx_t ctx) { return gr_series_dirichlet_hardy_theta(res, G, chi, s, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_dirichlet_hardy_z(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t s, const gr_series_t z, gr_ctx_t ctx) { return gr_series_dirichlet_hardy_z(res, G, chi, s, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_jacobi_theta(gr_series_t res1, gr_series_t res2, gr_series_t res3, gr_series_t res4, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx) { return gr_series_jacobi_theta(res1, res2, res3, res4, x, tau, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_jacobi_theta_1(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx) { return gr_series_jacobi_theta_1(res, x, tau, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_jacobi_theta_2(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx) { return gr_series_jacobi_theta_2(res, x, tau, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_jacobi_theta_3(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx) { return gr_series_jacobi_theta_3(res, x, tau, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_jacobi_theta_4(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx) { return gr_series_jacobi_theta_4(res, x, tau, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_agm1(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_agm1(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_elliptic_k(gr_series_t res, const gr_series_t x, gr_ctx_t ctx) { return gr_series_elliptic_k(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_weierstrass_p(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx) { return gr_series_weierstrass_p(res, x, tau, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } static int _gr_gr_series_set_other(gr_series_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { if (x_ctx == ctx) { return _gr_gr_series_set(res, x, ctx); } else if (x_ctx == SERIES_ELEM_CTX(ctx)) { return gr_series_set_scalar(res, x, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); } else if ((x_ctx->which_ring == GR_CTX_GR_SERIES || x_ctx->which_ring == GR_CTX_GR_SERIES_MOD) && !strcmp(SERIES_CTX(x_ctx)->var, SERIES_CTX(ctx)->var)) { int status = GR_SUCCESS; /* todo: check compatibility? */ status |= gr_poly_set_gr_poly_other(&res->poly, &((gr_series_struct *) x)->poly, SERIES_ELEM_CTX(x_ctx), SERIES_ELEM_CTX(ctx)); res->error = ((gr_series_struct *) x)->error; /* possible truncation */ status |= gr_series_set(res, res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); return status; } else if (x_ctx->which_ring == GR_CTX_GR_POLY && !strcmp(POLYNOMIAL_CTX(x_ctx)->var, SERIES_CTX(ctx)->var)) { int status = GR_SUCCESS; /* todo: check compatibility? */ status |= gr_poly_set_gr_poly_other(&res->poly, x, SERIES_ELEM_CTX(x_ctx), SERIES_ELEM_CTX(ctx)); res->error = SERIES_ERR_EXACT; /* possible truncation */ status |= gr_series_set(res, res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); return status; } else { int status = GR_SUCCESS; gr_poly_fit_length(&res->poly, 1, SERIES_ELEM_CTX(ctx)); status = gr_set_other(res->poly.coeffs, x, x_ctx, SERIES_ELEM_CTX(ctx)); if (status == GR_SUCCESS) { _gr_poly_set_length(&res->poly, 1, SERIES_ELEM_CTX(ctx)); _gr_poly_normalise(&res->poly, SERIES_ELEM_CTX(ctx)); } else _gr_poly_set_length(&res->poly, 0, SERIES_ELEM_CTX(ctx)); res->error = SERIES_ERR_EXACT; /* possible truncation */ status |= gr_series_set(res, res, SERIES_SCTX(ctx), SERIES_ELEM_CTX(ctx)); return status; } return GR_UNABLE; } int _gr_series_methods_initialized = 0; gr_static_method_table _gr_series_methods; gr_method_tab_input _gr_series_methods_input[] = { {GR_METHOD_CTX_CLEAR, (gr_funcptr) _gr_gr_series_ctx_clear}, {GR_METHOD_CTX_WRITE, (gr_funcptr) _gr_gr_series_ctx_write}, {GR_METHOD_CTX_SET_GEN_NAME, (gr_funcptr) _gr_gr_series_ctx_set_gen_name}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) _gr_gr_series_ctx_is_ring}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) _gr_gr_series_ctx_is_commutative_ring}, {GR_METHOD_INIT, (gr_funcptr) _gr_gr_series_init}, {GR_METHOD_CLEAR, (gr_funcptr) _gr_gr_series_clear}, {GR_METHOD_SWAP, (gr_funcptr) _gr_gr_series_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) _gr_gr_series_set_shallow}, {GR_METHOD_RANDTEST, (gr_funcptr) _gr_gr_series_randtest}, {GR_METHOD_WRITE, (gr_funcptr) _gr_gr_series_write}, {GR_METHOD_ZERO, (gr_funcptr) _gr_gr_series_zero}, {GR_METHOD_ONE, (gr_funcptr) _gr_gr_series_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) _gr_gr_series_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) _gr_gr_series_is_one}, {GR_METHOD_EQUAL, (gr_funcptr) _gr_gr_series_equal}, {GR_METHOD_GEN, (gr_funcptr) _gr_gr_series_gen}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens_single}, {GR_METHOD_GENS_RECURSIVE, (gr_funcptr) _gr_gr_series_gens_recursive}, {GR_METHOD_SET, (gr_funcptr) _gr_gr_series_set}, {GR_METHOD_SET_UI, (gr_funcptr) _gr_gr_series_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) _gr_gr_series_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) _gr_gr_series_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) _gr_gr_series_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) _gr_gr_series_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions}, {GR_METHOD_NEG, (gr_funcptr) _gr_gr_series_neg}, {GR_METHOD_ADD, (gr_funcptr) _gr_gr_series_add}, {GR_METHOD_SUB, (gr_funcptr) _gr_gr_series_sub}, {GR_METHOD_MUL, (gr_funcptr) _gr_gr_series_mul}, {GR_METHOD_INV, (gr_funcptr) _gr_gr_series_inv}, {GR_METHOD_DIV, (gr_funcptr) _gr_gr_series_div}, {GR_METHOD_DIV, (gr_funcptr) _gr_gr_series_div}, {GR_METHOD_SQRT, (gr_funcptr) _gr_gr_series_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) _gr_gr_series_rsqrt}, {GR_METHOD_EXP, (gr_funcptr) _gr_gr_series_exp}, {GR_METHOD_LOG, (gr_funcptr) _gr_gr_series_log}, {GR_METHOD_TAN, (gr_funcptr) _gr_gr_series_tan}, {GR_METHOD_ASIN, (gr_funcptr) _gr_gr_series_asin}, {GR_METHOD_ACOS, (gr_funcptr) _gr_gr_series_acos}, {GR_METHOD_ATAN, (gr_funcptr) _gr_gr_series_atan}, {GR_METHOD_ASINH, (gr_funcptr) _gr_gr_series_asinh}, {GR_METHOD_ACOSH, (gr_funcptr) _gr_gr_series_acosh}, {GR_METHOD_ATANH, (gr_funcptr) _gr_gr_series_atanh}, {GR_METHOD_GAMMA, (gr_funcptr) _gr_gr_series_gamma}, {GR_METHOD_RGAMMA, (gr_funcptr) _gr_gr_series_rgamma}, {GR_METHOD_LGAMMA, (gr_funcptr) _gr_gr_series_lgamma}, {GR_METHOD_DIGAMMA, (gr_funcptr) _gr_gr_series_digamma}, {GR_METHOD_ERF, (gr_funcptr) _gr_gr_series_erf}, {GR_METHOD_ERFC, (gr_funcptr) _gr_gr_series_erfc}, {GR_METHOD_ERFI, (gr_funcptr) _gr_gr_series_erfi}, {GR_METHOD_FRESNEL, (gr_funcptr) _gr_gr_series_fresnel}, {GR_METHOD_FRESNEL_S, (gr_funcptr) _gr_gr_series_fresnel_s}, {GR_METHOD_FRESNEL_C, (gr_funcptr) _gr_gr_series_fresnel_c}, {GR_METHOD_AIRY, (gr_funcptr) _gr_gr_series_airy}, {GR_METHOD_AIRY_AI, (gr_funcptr) _gr_gr_series_airy_ai}, {GR_METHOD_AIRY_AI_PRIME, (gr_funcptr) _gr_gr_series_airy_ai_prime}, {GR_METHOD_AIRY_BI, (gr_funcptr) _gr_gr_series_airy_bi}, {GR_METHOD_AIRY_BI_PRIME, (gr_funcptr) _gr_gr_series_airy_bi_prime}, {GR_METHOD_EXP_INTEGRAL_EI, (gr_funcptr) _gr_gr_series_exp_integral_ei}, {GR_METHOD_COS_INTEGRAL, (gr_funcptr) _gr_gr_series_cos_integral}, {GR_METHOD_COSH_INTEGRAL, (gr_funcptr) _gr_gr_series_cosh_integral}, {GR_METHOD_SIN_INTEGRAL, (gr_funcptr) _gr_gr_series_sin_integral}, {GR_METHOD_SINH_INTEGRAL, (gr_funcptr) _gr_gr_series_sinh_integral}, {GR_METHOD_LOG_INTEGRAL, (gr_funcptr) _gr_gr_series_log_integral}, {GR_METHOD_GAMMA_UPPER, (gr_funcptr) _gr_gr_series_gamma_upper}, {GR_METHOD_GAMMA_LOWER, (gr_funcptr) _gr_gr_series_gamma_lower}, {GR_METHOD_BETA_LOWER, (gr_funcptr) _gr_gr_series_beta_lower}, {GR_METHOD_HYPGEOM_PFQ, (gr_funcptr) _gr_gr_series_hypgeom_pfq}, {GR_METHOD_HURWITZ_ZETA, (gr_funcptr) _gr_gr_series_hurwitz_zeta}, {GR_METHOD_POLYLOG, (gr_funcptr) _gr_gr_series_polylog}, {GR_METHOD_DIRICHLET_L, (gr_funcptr) _gr_gr_series_dirichlet_l}, {GR_METHOD_DIRICHLET_HARDY_Z, (gr_funcptr) _gr_gr_series_dirichlet_hardy_z}, {GR_METHOD_DIRICHLET_HARDY_THETA, (gr_funcptr) _gr_gr_series_dirichlet_hardy_theta}, {GR_METHOD_JACOBI_THETA, (gr_funcptr) _gr_gr_series_jacobi_theta}, {GR_METHOD_JACOBI_THETA_1, (gr_funcptr) _gr_gr_series_jacobi_theta_1}, {GR_METHOD_JACOBI_THETA_2, (gr_funcptr) _gr_gr_series_jacobi_theta_2}, {GR_METHOD_JACOBI_THETA_3, (gr_funcptr) _gr_gr_series_jacobi_theta_3}, {GR_METHOD_JACOBI_THETA_4, (gr_funcptr) _gr_gr_series_jacobi_theta_4}, {GR_METHOD_AGM1, (gr_funcptr) _gr_gr_series_agm1}, {GR_METHOD_ELLIPTIC_K, (gr_funcptr) _gr_gr_series_elliptic_k}, {GR_METHOD_WEIERSTRASS_P, (gr_funcptr) _gr_gr_series_weierstrass_p}, {0, (gr_funcptr) NULL}, }; static inline void _gr_ctx_init_gr_series(gr_ctx_t ctx, gr_ctx_t base_ring, int kind, slong mod, slong prec) { ctx->which_ring = kind; ctx->sizeof_elem = sizeof(gr_series_struct); ctx->size_limit = WORD_MAX; SERIES_CTX(ctx)->base_ring = (gr_ctx_struct *) base_ring; SERIES_CTX(ctx)->var = (char *) default_var; SERIES_CTX(ctx)->sctx.mod = mod; SERIES_CTX(ctx)->sctx.prec = prec; ctx->methods = _gr_series_methods; if (!_gr_series_methods_initialized) { gr_method_tab_init(_gr_series_methods, _gr_series_methods_input); _gr_series_methods_initialized = 1; } } void gr_ctx_init_gr_series(gr_ctx_t ctx, gr_ctx_t base_ring, slong prec) { _gr_ctx_init_gr_series(ctx, base_ring, GR_CTX_GR_SERIES, SERIES_ERR_EXACT, FLINT_MIN(FLINT_MAX(0, prec), SERIES_ERR_MAX)); } void gr_ctx_init_gr_series_mod(gr_ctx_t ctx, gr_ctx_t base_ring, slong mod) { if (mod >= SERIES_ERR_EXACT) flint_throw(FLINT_ERROR, "(%s)\n", __func__); _gr_ctx_init_gr_series(ctx, base_ring, GR_CTX_GR_SERIES_MOD, FLINT_MAX(0, mod), mod); } flint-3.1.3/src/gr/test/000077500000000000000000000000001461254215100150115ustar00rootroot00000000000000flint-3.1.3/src/gr/test/main.c000066400000000000000000000064641461254215100161130ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "mpoly.h" #include "fmpz_mpoly_q.h" #include "nf.h" #include "gr.h" /* Include functions *********************************************************/ #include "t-acb.c" #include "t-arb.c" #include "t-ca.c" #include "t-dirichlet.c" #include "t-fmpq.c" #include "t-fmpq_poly.c" #include "t-fmpz.c" #include "t-fmpzi.c" #include "t-fmpz_mod.c" #include "t-fmpz_mpoly.c" #include "t-fmpz_mpoly_q.c" #include "t-fmpz_poly.c" #include "t-fq.c" #include "t-fq_nmod.c" #include "t-fq_zech.c" #include "t-matrix_acb.c" #include "t-matrix_arb.c" #include "t-matrix_fmpq.c" #include "t-matrix_fmpz.c" #include "t-matrix_nmod8.c" #include "t-mpoly_nmod8.c" #include "t-nf.c" #include "t-nmod32.c" #include "t-nmod8.c" #include "t-nmod.c" #include "t-perm.c" #include "t-polynomial_acb.c" #include "t-polynomial_arb.c" #include "t-polynomial_fmpq.c" #include "t-polynomial_fmpz.c" #include "t-polynomial_nmod8.c" #include "t-psl2z.c" #include "t-qqbar.c" #include "t-series_acb.c" #include "t-series_arb.c" #include "t-series_fmpq.c" #include "t-series_fmpz.c" #include "t-series_nmod8.c" #include "t-vector_acb.c" #include "t-vector_arb.c" #include "t-vector_fmpz.c" #include "t-vector_fmpq.c" #include "t-vector_nmod.c" #include "t-vector_nmod8.c" #include "t-vector_nmod32.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(gr_acb), TEST_FUNCTION(gr_arb), TEST_FUNCTION(gr_ca), TEST_FUNCTION(gr_dirichlet), TEST_FUNCTION(gr_fmpq), TEST_FUNCTION(gr_fmpq_poly), TEST_FUNCTION(gr_fmpz), TEST_FUNCTION(gr_fmpzi), TEST_FUNCTION(gr_fmpz_mod), TEST_FUNCTION(gr_fmpz_mpoly), TEST_FUNCTION(gr_fmpz_mpoly_q), TEST_FUNCTION(gr_fmpz_poly), TEST_FUNCTION(gr_fq), TEST_FUNCTION(gr_fq_nmod), TEST_FUNCTION(gr_fq_zech), TEST_FUNCTION(gr_matrix_acb), TEST_FUNCTION(gr_matrix_arb), TEST_FUNCTION(gr_matrix_fmpq), TEST_FUNCTION(gr_matrix_fmpz), TEST_FUNCTION(gr_matrix_nmod8), TEST_FUNCTION(gr_mpoly_nmod8), TEST_FUNCTION(gr_nf), TEST_FUNCTION(gr_nmod32), TEST_FUNCTION(gr_nmod8), TEST_FUNCTION(gr_nmod), TEST_FUNCTION(gr_perm), TEST_FUNCTION(gr_polynomial_acb), TEST_FUNCTION(gr_polynomial_arb), TEST_FUNCTION(gr_polynomial_fmpq), TEST_FUNCTION(gr_polynomial_fmpz), TEST_FUNCTION(gr_polynomial_nmod8), TEST_FUNCTION(gr_psl2z), TEST_FUNCTION(gr_qqbar), TEST_FUNCTION(gr_series_acb), TEST_FUNCTION(gr_series_arb), TEST_FUNCTION(gr_series_fmpq), TEST_FUNCTION(gr_series_fmpz), TEST_FUNCTION(gr_series_nmod8), TEST_FUNCTION(gr_vector_acb), TEST_FUNCTION(gr_vector_arb), TEST_FUNCTION(gr_vector_fmpz), TEST_FUNCTION(gr_vector_fmpq), TEST_FUNCTION(gr_vector_nmod), TEST_FUNCTION(gr_vector_nmod8), TEST_FUNCTION(gr_vector_nmod32), }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/gr/test/t-acb.c000066400000000000000000000013111461254215100161370ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_acb, state) { gr_ctx_t CC; int flags = 0; slong prec; for (prec = 64; prec <= 256; prec *= 2) { gr_ctx_init_complex_acb(CC, prec); gr_test_ring(CC, 1000, flags); gr_ctx_clear(CC); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-arb.c000066400000000000000000000013061461254215100161620ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_arb, state) { gr_ctx_t RR; int flags = 0; slong prec; for (prec = 64; prec <= 256; prec *= 2) { gr_ctx_init_real_arb(RR, prec); gr_test_ring(RR, 1000, flags); gr_ctx_clear(RR); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-ca.c000066400000000000000000000016751461254215100160120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_ca, state) { gr_ctx_t RR, CC, QQbar_real, QQbar; int flags = 0; gr_ctx_init_real_ca(RR); gr_test_ring(RR, 100, flags); gr_ctx_clear(RR); gr_ctx_init_complex_ca(CC); gr_test_ring(CC, 100, flags); gr_ctx_clear(CC); gr_ctx_init_real_algebraic_ca(QQbar_real); gr_test_ring(QQbar_real, 100, flags); gr_ctx_clear(QQbar_real); gr_ctx_init_complex_algebraic_ca(QQbar); gr_test_ring(QQbar, 100, flags); gr_ctx_clear(QQbar); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-dirichlet.c000066400000000000000000000020551461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_dirichlet, state) { gr_ctx_t G; int flags = GR_TEST_ALWAYS_ABLE; ulong q; for (q = 1; q <= 100; q++) { GR_MUST_SUCCEED(gr_ctx_init_dirichlet_group(G, q)); gr_test_multiplicative_group(G, 100, flags); gr_ctx_clear(G); } { slong iter; for (iter = 0; iter < 100; iter++) { q = n_randtest(state); if (gr_ctx_init_dirichlet_group(G, q) == GR_SUCCESS) { gr_test_multiplicative_group(G, 100, flags); gr_ctx_clear(G); } } } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpq.c000066400000000000000000000012271461254215100163630ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpq, state) { gr_ctx_t QQ; int flags = GR_TEST_ALWAYS_ABLE; gr_ctx_init_fmpq(QQ); QQ->size_limit = 1000; gr_test_ring(QQ, 10000, flags); gr_ctx_clear(QQ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpq_poly.c000066400000000000000000000012111461254215100174170ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpq_poly, state) { gr_ctx_t QQx; int flags = GR_TEST_ALWAYS_ABLE; gr_ctx_init_fmpq_poly(QQx); gr_test_ring(QQx, 1000, flags); gr_ctx_clear(QQx); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpz.c000066400000000000000000000020371461254215100163740ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpz, state) { gr_ctx_t ZZ; int flags = GR_TEST_ALWAYS_ABLE; gr_ctx_init_fmpz(ZZ); ZZ->size_limit = 1000; gr_test_ring(ZZ, 100000, flags); { fmpz * a, *b; a = gr_heap_init(ZZ); b = gr_heap_init(ZZ); fmpz_set_str(a, "1000000000000000000000", 10); fmpz_set_str(b, "1000000000000000000001", 10); if (gr_sub(b, b, a, ZZ) != GR_SUCCESS || gr_is_one(b, ZZ) != T_TRUE) flint_abort(); gr_heap_clear(a, ZZ); gr_heap_clear(b, ZZ); } gr_ctx_clear(ZZ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpz_mod.c000066400000000000000000000030261461254215100172320ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpz_mod, state) { gr_ctx_t ZZn; fmpz_t n; slong iter; int flags = GR_TEST_ALWAYS_ABLE; fmpz_init(n); for (iter = 0; iter < 1000; iter++) { fmpz_randtest_not_zero(n, state, 200); fmpz_abs(n, n); gr_ctx_init_fmpz_mod(ZZn, n); if (n_randint(state, 2)) gr_ctx_fmpz_mod_set_primality(ZZn, fmpz_is_probabprime(n) ? T_TRUE : T_FALSE); gr_test_ring(ZZn, 10, flags); gr_ctx_clear(ZZn); } for (iter = 0; iter < 100; iter++) { fmpz_randtest_not_zero(n, state, 200); fmpz_abs(n, n); gr_ctx_init_fmpz_mod(ZZn, n); if (n_randint(state, 2)) gr_ctx_fmpz_mod_set_primality(ZZn, fmpz_is_probabprime(n) ? T_TRUE : T_FALSE); gr_test_ring(ZZn, 100, flags); gr_ctx_clear(ZZn); } /* test huge preinvn code */ { fmpz_randbits(n, state, 72000); fmpz_abs(n, n); gr_ctx_init_fmpz_mod(ZZn, n); gr_test_ring(ZZn, 10, flags); gr_ctx_clear(ZZn); } fmpz_clear(n); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpz_mpoly.c000066400000000000000000000014621461254215100176150ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpz_mpoly, state) { gr_ctx_t ZZxy; slong iter; int flags = 0; for (iter = 0; iter < 10; iter++) { gr_ctx_init_fmpz_mpoly(ZZxy, n_randint(state, 3), mpoly_ordering_randtest(state)); ZZxy->size_limit = 100; gr_test_ring(ZZxy, 100, flags); gr_ctx_clear(ZZxy); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpz_mpoly_q.c000066400000000000000000000015201461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "fmpz_mpoly_q.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpz_mpoly_q, state) { gr_ctx_t ZZxy; slong iter; int flags = 0; for (iter = 0; iter < 10; iter++) { gr_ctx_init_fmpz_mpoly_q(ZZxy, n_randint(state, 3), mpoly_ordering_randtest(state)); ZZxy->size_limit = 100; gr_test_ring(ZZxy, 100, flags); gr_ctx_clear(ZZxy); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpz_poly.c000066400000000000000000000012121461254215100174310ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpz_poly, state) { gr_ctx_t ZZx; int flags = GR_TEST_ALWAYS_ABLE; gr_ctx_init_fmpz_poly(ZZx); gr_test_ring(ZZx, 1000, flags); gr_ctx_clear(ZZx); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fmpzi.c000066400000000000000000000012401461254215100165400ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_fmpzi, state) { gr_ctx_t ZZi; int flags = GR_TEST_ALWAYS_ABLE; gr_ctx_init_fmpzi(ZZi); ZZi->size_limit = 1000; gr_test_ring(ZZi, 100000, flags); gr_ctx_clear(ZZi); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fq.c000066400000000000000000000016101461254215100160220ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "gr.h" TEST_FUNCTION_START(gr_fq, state) { gr_ctx_t Fq; fmpz_t p; slong d; slong iter; int flags = GR_TEST_ALWAYS_ABLE; fmpz_init(p); for (iter = 0; iter < 30; iter++) { fmpz_randprime(p, state, 2 + n_randint(state, 100), 0); d = 1 + n_randint(state, 5); gr_ctx_init_fq(Fq, p, d, "a"); gr_test_ring(Fq, 100, flags); gr_ctx_clear(Fq); } fmpz_clear(p); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fq_nmod.c000066400000000000000000000015731461254215100170470ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_fq_nmod, state) { gr_ctx_t Fq; ulong p; slong d; slong iter; int flags = GR_TEST_ALWAYS_ABLE; for (iter = 0; iter < 30; iter++) { p = n_randprime(state, 2 + n_randint(state, FLINT_BITS - 1), 0); d = 1 + n_randint(state, 5); gr_ctx_init_fq_nmod(Fq, p, d, "a"); gr_test_ring(Fq, 100, flags); gr_ctx_clear(Fq); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-fq_zech.c000066400000000000000000000015561461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_fq_zech, state) { gr_ctx_t Fq; ulong p; slong d; slong iter; int flags = GR_TEST_ALWAYS_ABLE; for (iter = 0; iter < 30; iter++) { p = n_randprime(state, 2 + n_randint(state, 3), 0); d = 1 + n_randint(state, 5); gr_ctx_init_fq_zech(Fq, p, d, "a"); gr_test_ring(Fq, 100, flags); gr_ctx_clear(Fq); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-matrix_acb.c000066400000000000000000000014311461254215100175260ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_matrix_acb, state) { gr_ctx_t CC, MatCC; slong n; int flags = 0; gr_ctx_init_complex_acb(CC, 64); for (n = 0; n <= 5; n++) { gr_ctx_init_matrix_ring(MatCC, CC, n); gr_test_ring(MatCC, n <= 2 ? 100 : 10, flags); gr_ctx_clear(MatCC); } gr_ctx_clear(CC); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-matrix_arb.c000066400000000000000000000014261461254215100175510ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_matrix_arb, state) { gr_ctx_t RR, MatRR; slong n; int flags = 0; gr_ctx_init_real_arb(RR, 64); for (n = 0; n <= 5; n++) { gr_ctx_init_matrix_ring(MatRR, RR, n); gr_test_ring(MatRR, n <= 2 ? 100 : 10, flags); gr_ctx_clear(MatRR); } gr_ctx_clear(RR); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-matrix_fmpq.c000066400000000000000000000014511461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_matrix_fmpq, state) { gr_ctx_t QQ, MatQQ; slong n; int flags = 0; gr_ctx_init_fmpq(QQ); QQ->size_limit = 200; for (n = 0; n <= 5; n++) { gr_ctx_init_matrix_ring(MatQQ, QQ, n); gr_test_ring(MatQQ, n <= 2 ? 100 : 10, flags); gr_ctx_clear(MatQQ); } gr_ctx_clear(QQ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-matrix_fmpz.c000066400000000000000000000014521461254215100177600ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_matrix_fmpz, state) { gr_ctx_t ZZ, MatZZ; slong n; int flags = 0; gr_ctx_init_fmpz(ZZ); ZZ->size_limit = 1000; for (n = 0; n <= 8; n++) { gr_ctx_init_matrix_ring(MatZZ, ZZ, n); gr_test_ring(MatZZ, n <= 2 ? 100 : 10, flags); gr_ctx_clear(MatZZ); } gr_ctx_clear(ZZ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-matrix_nmod8.c000066400000000000000000000021571461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_matrix_nmod8, state) { gr_ctx_t ZZn, MatZZn; slong iter, n; int flags = 0; for (iter = 0; iter < 50; iter++) { gr_ctx_init_nmod8(ZZn, 1 + n_randtest(state) % 255); for (n = 0; n <= 4; n++) { gr_ctx_init_matrix_ring(MatZZn, ZZn, n); gr_test_ring(MatZZn, n <= 2 ? 100 : 10, flags); gr_ctx_clear(MatZZn); } if (iter % 5 == 0) { gr_ctx_init_matrix_ring(MatZZn, ZZn, n_randint(state, 40)); gr_test_ring(MatZZn, 10, flags); gr_ctx_clear(MatZZn); } gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-mpoly_nmod8.c000066400000000000000000000016261461254215100176700ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "gr.h" TEST_FUNCTION_START(gr_mpoly_nmod8, state) { gr_ctx_t ZZn, ZZnx; slong iter; int flags = 0; for (iter = 0; iter < 50; iter++) { gr_ctx_init_nmod8(ZZn, 1 + n_randtest(state) % 255); gr_ctx_init_gr_mpoly(ZZnx, ZZn, n_randint(state, 3), mpoly_ordering_randtest(state)); ZZnx->size_limit = 100; gr_test_ring(ZZnx, 100, flags); gr_ctx_clear(ZZnx); gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-nf.c000066400000000000000000000022131461254215100160170ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "gr.h" TEST_FUNCTION_START(gr_nf, state) { gr_ctx_t QQa; fmpq_poly_t f; fmpz_poly_t g; slong iter; int flags = GR_TEST_ALWAYS_ABLE; fmpq_poly_init(f); fmpz_poly_init(g); for (iter = 0; iter < 30; iter++) { do { fmpz_poly_randtest_irreducible(g, state, 2 + n_randint(state, 5), 1 + n_randint(state, 10)); } while (g->length < 2); fmpq_poly_set_fmpz_poly(f, g); fmpq_poly_scalar_div_ui(f, f, 1 + n_randtest(state) % 256); gr_ctx_init_nf(QQa, f); gr_test_ring(QQa, 100, flags); gr_ctx_clear(QQa); } fmpq_poly_clear(f); fmpz_poly_clear(g); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-nmod.c000066400000000000000000000016161461254215100163570ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_nmod, state) { gr_ctx_t ZZn; int flags = GR_TEST_ALWAYS_ABLE; slong iter; ulong n; for (iter = 0; iter < 100; iter++) { n = n_randtest_not_zero(state); gr_ctx_init_nmod(ZZn, n); if (n_randint(state, 2)) gr_ctx_nmod_set_primality(ZZn, n_is_prime(n) ? T_TRUE : T_FALSE); gr_test_ring(ZZn, 100, flags); gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-nmod32.c000066400000000000000000000020021461254215100165120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_nmod32, state) { gr_ctx_t ZZn; int flags = GR_TEST_ALWAYS_ABLE; ulong n; int i; for (i = 0; i < 100; i++) { n = (unsigned int) n_randtest(state); if (n == 0) n = 1; gr_ctx_init_nmod32(ZZn, n); gr_test_ring(ZZn, 100, flags); gr_ctx_clear(ZZn); } gr_ctx_init_nmod32(ZZn, UWORD(4294967291)); gr_test_ring(ZZn, 10000, flags); gr_ctx_clear(ZZn); gr_ctx_init_nmod32(ZZn, UWORD(4294967295)); gr_test_ring(ZZn, 10000, flags); gr_ctx_clear(ZZn); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-nmod8.c000066400000000000000000000016011461254215100164410ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_nmod8, state) { gr_ctx_t ZZn; int flags = GR_TEST_ALWAYS_ABLE; ulong n; for (n = 1; n < 256; n++) { gr_ctx_init_nmod8(ZZn, n); gr_test_ring(ZZn, 100, flags); gr_ctx_clear(ZZn); } gr_ctx_init_nmod8(ZZn, 107); gr_test_ring(ZZn, 10000, flags); gr_ctx_clear(ZZn); gr_ctx_init_nmod8(ZZn, 10); gr_test_ring(ZZn, 10000, flags); gr_ctx_clear(ZZn); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-perm.c000066400000000000000000000013141461254215100163600ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_perm, state) { gr_ctx_t G; int flags = GR_TEST_ALWAYS_ABLE; ulong n; for (n = 0; n <= 20; n++) { gr_ctx_init_perm(G, n); gr_test_multiplicative_group(G, 100, flags); gr_ctx_clear(G); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-polynomial_acb.c000066400000000000000000000013271461254215100204110ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_polynomial_acb, state) { gr_ctx_t CC, CCx; int flags = 0; gr_ctx_init_complex_acb(CC, 64); gr_ctx_init_gr_poly(CCx, CC); CCx->size_limit = 50; gr_test_ring(CCx, 1000, flags); gr_ctx_clear(CCx); gr_ctx_clear(CC); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-polynomial_arb.c000066400000000000000000000013241461254215100204250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_polynomial_arb, state) { gr_ctx_t RR, RRx; int flags = 0; gr_ctx_init_real_arb(RR, 64); gr_ctx_init_gr_poly(RRx, RR); RRx->size_limit = 50; gr_test_ring(RRx, 1000, flags); gr_ctx_clear(RRx); gr_ctx_clear(RR); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-polynomial_fmpq.c000066400000000000000000000013471461254215100206310ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_polynomial_fmpq, state) { gr_ctx_t QQ, QQx; int flags = 0; gr_ctx_init_fmpq(QQ); QQ->size_limit = 100; gr_ctx_init_gr_poly(QQx, QQ); QQx->size_limit = 30; gr_test_ring(QQx, 1000, flags); gr_ctx_clear(QQx); gr_ctx_clear(QQ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-polynomial_fmpz.c000066400000000000000000000013471461254215100206420ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_polynomial_fmpz, state) { gr_ctx_t ZZ, ZZx; int flags = 0; gr_ctx_init_fmpz(ZZ); ZZ->size_limit = 200; gr_ctx_init_gr_poly(ZZx, ZZ); ZZx->size_limit = 30; gr_test_ring(ZZx, 1000, flags); gr_ctx_clear(ZZx); gr_ctx_clear(ZZ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-polynomial_nmod8.c000066400000000000000000000015531461254215100207120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_polynomial_nmod8, state) { gr_ctx_t ZZn, ZZnx; slong iter; int flags = 0; for (iter = 0; iter < 50; iter++) { gr_ctx_init_nmod8(ZZn, 1 + n_randtest(state) % 255); gr_ctx_init_gr_poly(ZZnx, ZZn); ZZnx->size_limit = 30; gr_test_ring(ZZnx, 1000, flags); gr_ctx_clear(ZZnx); gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-psl2z.c000066400000000000000000000012321461254215100164660ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_psl2z, state) { gr_ctx_t PSL2Z; int flags = GR_TEST_ALWAYS_ABLE; gr_ctx_init_psl2z(PSL2Z); gr_test_multiplicative_group(PSL2Z, 10000, flags); gr_ctx_clear(PSL2Z); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-qqbar.c000066400000000000000000000014151461254215100165250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_qqbar, state) { gr_ctx_t QQbar_real, QQbar; int flags = GR_TEST_ALWAYS_ABLE; gr_ctx_init_real_qqbar(QQbar_real); gr_test_ring(QQbar_real, 100, flags); gr_ctx_clear(QQbar_real); gr_ctx_init_complex_qqbar(QQbar); gr_test_ring(QQbar, 100, flags); gr_ctx_clear(QQbar); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-series_acb.c000066400000000000000000000020671461254215100175220ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_series_acb, state) { gr_ctx_t CCn, CCnx; int flags = 0; slong i; for (i = 0; i < 5; i++) { gr_ctx_init_complex_acb(CCn, 2 + n_randint(state, 200)); gr_ctx_init_gr_series(CCnx, CCn, i); gr_test_ring(CCnx, 100, flags); gr_ctx_clear(CCnx); gr_ctx_clear(CCn); } for (i = 0; i < 5; i++) { gr_ctx_init_complex_acb(CCn, 2 + n_randint(state, 200)); gr_ctx_init_gr_series_mod(CCnx, CCn, i); gr_test_ring(CCnx, 100, flags); gr_ctx_clear(CCnx); gr_ctx_clear(CCn); } gr_ctx_clear(CCn); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-series_arb.c000066400000000000000000000020611461254215100175330ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_series_arb, state) { gr_ctx_t RRn, RRnx; int flags = 0; slong i; for (i = 0; i < 5; i++) { gr_ctx_init_real_arb(RRn, 2 + n_randint(state, 200)); gr_ctx_init_gr_series(RRnx, RRn, i); gr_test_ring(RRnx, 100, flags); gr_ctx_clear(RRnx); gr_ctx_clear(RRn); } for (i = 0; i < 5; i++) { gr_ctx_init_real_arb(RRn, 2 + n_randint(state, 200)); gr_ctx_init_gr_series_mod(RRnx, RRn, i); gr_test_ring(RRnx, 100, flags); gr_ctx_clear(RRnx); gr_ctx_clear(RRn); } gr_ctx_clear(RRn); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-series_fmpq.c000066400000000000000000000016201461254215100177320ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_series_fmpq, state) { gr_ctx_t QQ, QQx; int flags = 0; slong i; gr_ctx_init_fmpq(QQ); for (i = 0; i < 5; i++) { gr_ctx_init_gr_series(QQx, QQ, i); gr_test_ring(QQx, 100, flags); gr_ctx_clear(QQx); } for (i = 0; i < 5; i++) { gr_ctx_init_gr_series_mod(QQx, QQ, i); gr_test_ring(QQx, 100, flags); gr_ctx_clear(QQx); } gr_ctx_clear(QQ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-series_fmpz.c000066400000000000000000000016201461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_series_fmpz, state) { gr_ctx_t ZZ, ZZx; int flags = 0; slong i; gr_ctx_init_fmpz(ZZ); for (i = 0; i < 5; i++) { gr_ctx_init_gr_series(ZZx, ZZ, i); gr_test_ring(ZZx, 100, flags); gr_ctx_clear(ZZx); } for (i = 0; i < 5; i++) { gr_ctx_init_gr_series_mod(ZZx, ZZ, i); gr_test_ring(ZZx, 100, flags); gr_ctx_clear(ZZx); } gr_ctx_clear(ZZ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-series_nmod8.c000066400000000000000000000020631461254215100200160ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_series_nmod8, state) { gr_ctx_t ZZn, ZZnx; int flags = 0; slong i; for (i = 0; i < 5; i++) { gr_ctx_init_nmod8(ZZn, 1 + n_randtest(state) % 255); gr_ctx_init_gr_series(ZZnx, ZZn, i); gr_test_ring(ZZnx, 100, flags); gr_ctx_clear(ZZnx); gr_ctx_clear(ZZn); } for (i = 0; i < 5; i++) { gr_ctx_init_nmod8(ZZn, 1 + n_randtest(state) % 255); gr_ctx_init_gr_series_mod(ZZnx, ZZn, i); gr_test_ring(ZZnx, 100, flags); gr_ctx_clear(ZZnx); gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-vector_acb.c000066400000000000000000000014231461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_vector_acb, state) { gr_ctx_t CC, VecCC; slong n; int flags = 0; gr_ctx_init_complex_acb(CC, 64); for (n = 0; n <= 4; n++) { gr_ctx_init_vector_space_gr_vec(VecCC, CC, n); gr_test_ring(VecCC, 100, flags); gr_ctx_clear(VecCC); } gr_ctx_clear(CC); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-vector_arb.c000066400000000000000000000014201461254215100175410ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_vector_arb, state) { gr_ctx_t RR, VecRR; slong n; int flags = 0; gr_ctx_init_real_arb(RR, 64); for (n = 0; n <= 4; n++) { gr_ctx_init_vector_space_gr_vec(VecRR, RR, n); gr_test_ring(VecRR, 100, flags); gr_ctx_clear(VecRR); } gr_ctx_clear(RR); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-vector_fmpq.c000066400000000000000000000014441461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_vector_fmpq, state) { gr_ctx_t QQ, VecQQ; slong n; int flags = 0; gr_ctx_init_fmpz(QQ); QQ->size_limit = 1000; for (n = 0; n <= 4; n++) { gr_ctx_init_vector_space_gr_vec(VecQQ, QQ, n); gr_test_ring(VecQQ, 100, flags); gr_ctx_clear(VecQQ); } gr_ctx_clear(QQ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-vector_fmpz.c000066400000000000000000000014441461254215100177570ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr.h" TEST_FUNCTION_START(gr_vector_fmpz, state) { gr_ctx_t ZZ, VecZZ; slong n; int flags = 0; gr_ctx_init_fmpz(ZZ); ZZ->size_limit = 1000; for (n = 0; n <= 4; n++) { gr_ctx_init_vector_space_gr_vec(VecZZ, ZZ, n); gr_test_ring(VecZZ, 100, flags); gr_ctx_clear(VecZZ); } gr_ctx_clear(ZZ); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-vector_nmod.c000066400000000000000000000016371461254215100177440ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_vector_nmod, state) { gr_ctx_t ZZn, VecZZn; slong iter, n; int flags = 0; for (iter = 0; iter < 100; iter++) { gr_ctx_init_nmod(ZZn, n_randtest_not_zero(state)); for (n = 0; n <= 4; n++) { gr_ctx_init_vector_space_gr_vec(VecZZn, ZZn, n); gr_test_ring(VecZZn, 10, flags); gr_ctx_clear(VecZZn); } gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-vector_nmod32.c000066400000000000000000000016621461254215100201070ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_vector_nmod32, state) { gr_ctx_t ZZn, VecZZn; slong iter, n; int flags = 0; for (iter = 0; iter < 100; iter++) { gr_ctx_init_nmod32(ZZn, 1 + n_randtest(state) % UWORD(4294967295)); for (n = 0; n <= 4; n++) { gr_ctx_init_vector_space_gr_vec(VecZZn, ZZn, n); gr_test_ring(VecZZn, 10, flags); gr_ctx_clear(VecZZn); } gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test/t-vector_nmod8.c000066400000000000000000000016421461254215100200300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr.h" TEST_FUNCTION_START(gr_vector_nmod8, state) { gr_ctx_t ZZn, VecZZn; slong iter, n; int flags = 0; for (iter = 0; iter < 100; iter++) { gr_ctx_init_nmod8(ZZn, 1 + n_randtest(state) % 255); for (n = 0; n <= 4; n++) { gr_ctx_init_vector_space_gr_vec(VecZZn, ZZn, n); gr_test_ring(VecZZn, 10, flags); gr_ctx_clear(VecZZn); } gr_ctx_clear(ZZn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr/test_ring.c000066400000000000000000003165531461254215100162110ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "long_extras.h" #include "fexpr.h" #include "fmpq.h" #include "gr.h" #include "gr_vec.h" #include "gr_mat.h" #include "gr_poly.h" typedef int ((*gr_test_function)(gr_ctx_t, flint_rand_t, int)); int gr_test_binary_op_aliasing(gr_ctx_t R, int (*gr_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), flint_rand_t state, int test_flags) { int status, alias; gr_ptr x, y, xy1, xy2; GR_TMP_INIT4(x, y, xy1, xy2, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); status = GR_SUCCESS; status |= gr_op(xy1, x, y, R); alias = n_randint(state, 4); switch (alias) { case 0: status |= gr_set(xy2, x, R); status |= gr_op(xy1, x, y, R); status |= gr_op(xy2, xy2, y, R); break; case 1: status |= gr_set(xy2, y, R); status |= gr_op(xy1, x, y, R); status |= gr_op(xy2, x, xy2, R); break; case 2: status |= gr_set(y, x, R); status |= gr_op(xy1, x, y, R); status |= gr_op(xy2, x, x, R); break; default: status |= gr_set(y, x, R); status |= gr_set(xy2, x, R); status |= gr_op(xy1, x, y, R); status |= gr_op(xy2, xy2, xy2, R); } if (status == GR_SUCCESS && gr_equal(xy1, xy2, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("alias: %d\n", alias); flint_printf("x = "); gr_println(x, R); flint_printf("y = "); gr_println(y, R); flint_printf("y (op) y (1) = "); gr_println(xy1, R); flint_printf("x (op) y (2) = "); gr_println(xy2, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xy1, xy2, R); return status; } int gr_test_set_ui(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr xa, xb, xc, xa_xb; ulong a, b, c; do { a = n_randtest(state); b = n_randtest(state); c = a + b; } while (c < a); GR_TMP_INIT4(xa, xb, xc, xa_xb, R); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); status = GR_SUCCESS; status |= gr_set_ui(xa, a, R); status |= gr_set_ui(xb, b, R); status |= gr_set_ui(xc, c, R); status |= gr_add(xa_xb, xa, xb, R); if (status == GR_SUCCESS && gr_equal(xc, xa_xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && a == 1 && gr_is_one(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && a == 0 && gr_is_zero(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && b == 1 && gr_is_one(xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && b == 0 && gr_is_zero(xb, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("c = %wu\n", c); flint_printf("xa = "); gr_println(xa, R); flint_printf("xb = "); gr_println(xb, R); flint_printf("xc = "); gr_println(xc, R); flint_printf("xa + xb = "); gr_println(xa_xb, R); flint_printf("\n"); } GR_TMP_CLEAR4(xa, xb, xc, xa_xb, R); return status; } int gr_test_set_si(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr xa, xb, xc, xa_xb; slong a, b, c; do { a = z_randtest(state); b = z_randtest(state); } while (z_add_checked(&c, a, b)); GR_TMP_INIT4(xa, xb, xc, xa_xb, R); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); status = GR_SUCCESS; status |= gr_set_si(xa, a, R); status |= gr_set_si(xb, b, R); status |= gr_set_si(xc, c, R); status |= gr_add(xa_xb, xa, xb, R); if (status == GR_SUCCESS && gr_equal(xc, xa_xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && a == 1 && gr_is_one(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && a == 0 && gr_is_zero(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && b == 1 && gr_is_one(xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && b == 0 && gr_is_zero(xb, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("a = %wd\n", a); flint_printf("b = %wd\n", b); flint_printf("c = %wd\n", c); flint_printf("xa = "); gr_println(xa, R); flint_printf("xb = "); gr_println(xb, R); flint_printf("xc = "); gr_println(xc, R); flint_printf("xa + xb = "); gr_println(xa_xb, R); flint_printf("\n"); } GR_TMP_CLEAR4(xa, xb, xc, xa_xb, R); return status; } int gr_test_set_fmpz(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr xa, xb, xc, xa_xb; fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 100); fmpz_add(c, a, b); GR_TMP_INIT4(xa, xb, xc, xa_xb, R); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); status = GR_SUCCESS; status |= gr_set_fmpz(xa, a, R); status |= gr_set_fmpz(xb, b, R); status |= gr_set_fmpz(xc, c, R); status |= gr_add(xa_xb, xa, xb, R); if (status == GR_SUCCESS && gr_equal(xc, xa_xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpz_is_one(a) && gr_is_one(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpz_is_zero(a) && gr_is_zero(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpz_is_one(b) && gr_is_one(xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpz_is_zero(b) && gr_is_zero(xb, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n"); flint_printf("xa = "); gr_println(xa, R); flint_printf("xb = "); gr_println(xb, R); flint_printf("xc = "); gr_println(xc, R); flint_printf("xa + xb = "); gr_println(xa_xb, R); flint_printf("\n"); } GR_TMP_CLEAR4(xa, xb, xc, xa_xb, R); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); return status; } int gr_test_set_fmpq(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr xa, xb, xc, xa_xb; fmpq_t a, b, c; fmpq_init(a); fmpq_init(b); fmpq_init(c); fmpq_randtest(a, state, 100); fmpq_randtest(b, state, 100); fmpq_add(c, a, b); GR_TMP_INIT4(xa, xb, xc, xa_xb, R); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); status = GR_SUCCESS; status |= gr_set_fmpq(xa, a, R); status |= gr_set_fmpq(xb, b, R); status |= gr_set_fmpq(xc, c, R); status |= gr_add(xa_xb, xa, xb, R); if (status == GR_SUCCESS && gr_equal(xc, xa_xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpq_is_one(a) && gr_is_one(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpq_is_zero(a) && gr_is_zero(xa, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpq_is_one(b) && gr_is_one(xb, R) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && fmpq_is_zero(b) && gr_is_zero(xb, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("a = "); fmpq_print(a); flint_printf("\n"); flint_printf("b = "); fmpq_print(b); flint_printf("\n"); flint_printf("c = "); fmpq_print(c); flint_printf("\n"); flint_printf("xa = "); gr_println(xa, R); flint_printf("xb = "); gr_println(xb, R); flint_printf("xc = "); gr_println(xc, R); flint_printf("xa + xb = "); gr_println(xa_xb, R); flint_printf("\n"); } GR_TMP_CLEAR4(xa, xb, xc, xa_xb, R); fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); return status; } int gr_test_get_ui(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y; ulong a; GR_TMP_INIT2(x, y, R); status = GR_SUCCESS; if (n_randint(state, 2)) { GR_MUST_SUCCEED(gr_randtest(x, state, R)); } else { a = n_randtest(state); status |= gr_set_ui(x, a, R); a = n_randtest(state); } status |= gr_get_ui(&a, x, R); if (status == GR_SUCCESS) { status |= gr_set_ui(y, a, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = "); gr_println(x, R); flint_printf("a = %wu\n", a); flint_printf("y = "); gr_println(y, R); flint_printf("\n"); } GR_TMP_CLEAR2(x, y, R); return status; } int gr_test_get_si(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y; slong a; GR_TMP_INIT2(x, y, R); status = GR_SUCCESS; if (n_randint(state, 2)) { GR_MUST_SUCCEED(gr_randtest(x, state, R)); } else { a = n_randtest(state); status |= gr_set_si(x, a, R); a = n_randtest(state); } status |= gr_get_si(&a, x, R); if (status == GR_SUCCESS) { status |= gr_set_si(y, a, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = "); gr_println(x, R); flint_printf("a = %wd\n", a); flint_printf("y = "); gr_println(y, R); flint_printf("\n"); } GR_TMP_CLEAR2(x, y, R); return status; } int gr_test_get_fmpz(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y; fmpz_t a; GR_TMP_INIT2(x, y, R); fmpz_init(a); status = GR_SUCCESS; if (n_randint(state, 2)) { GR_MUST_SUCCEED(gr_randtest(x, state, R)); } else { fmpz_randtest(a, state, 100); status |= gr_set_fmpz(x, a, R); fmpz_randtest(a, state, 100); } status |= gr_get_fmpz(a, x, R); if (status == GR_SUCCESS) { status |= gr_set_fmpz(y, a, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = "); gr_println(x, R); flint_printf("a = \n"); fmpz_print(a); flint_printf("\n"); flint_printf("y = "); gr_println(y, R); flint_printf("\n"); } GR_TMP_CLEAR2(x, y, R); fmpz_clear(a); return status; } int gr_test_get_fmpq(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y; fmpq_t a; GR_TMP_INIT2(x, y, R); fmpq_init(a); status = GR_SUCCESS; if (n_randint(state, 2)) { GR_MUST_SUCCEED(gr_randtest(x, state, R)); } else { fmpq_randtest(a, state, 100); status |= gr_set_fmpq(x, a, R); fmpq_randtest(a, state, 100); } status |= gr_get_fmpq(a, x, R); if (status == GR_SUCCESS) { status |= gr_set_fmpq(y, a, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = "); gr_println(x, R); flint_printf("a = \n"); fmpq_print(a); flint_printf("\n"); flint_printf("y = "); gr_println(y, R); flint_printf("\n"); } GR_TMP_CLEAR2(x, y, R); fmpq_clear(a); return status; } int gr_test_get_fmpz_2exp_fmpz(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y; fmpz_t a, b; GR_TMP_INIT2(x, y, R); fmpz_init(a); fmpz_init(b); status = GR_SUCCESS; if (n_randint(state, 2)) { GR_MUST_SUCCEED(gr_randtest(x, state, R)); } else { fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 10); status |= gr_set_fmpz_2exp_fmpz(x, a, b, R); fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 10); } status |= gr_get_fmpz_2exp_fmpz(a, b, x, R); if (status == GR_SUCCESS) { status |= gr_set_fmpz_2exp_fmpz(y, a, b, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = "); gr_println(x, R); flint_printf("a = \n"); fmpz_print(a); flint_printf("\n"); flint_printf("b = \n"); fmpz_print(b); flint_printf("\n"); flint_printf("y = "); gr_println(y, R); flint_printf("\n"); } GR_TMP_CLEAR2(x, y, R); fmpz_clear(a); fmpz_clear(b); return status; } int gr_test_get_set_fexpr(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y; fexpr_t expr; GR_TMP_INIT2(x, y, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); fexpr_init(expr); status |= gr_get_fexpr(expr, x, R); if (status == GR_SUCCESS) { fexpr_vec_t inp; gr_vec_t out; fexpr_vec_init(inp, 0); gr_vec_init(out, 0, R); status |= gr_set_fexpr(y, inp, out, expr, R); fexpr_vec_clear(inp); gr_vec_clear(out, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) { status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("get_set_fexpr\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); fexpr_print(expr); flint_printf("\n"); flint_printf("y = \n"); gr_println(y, R); flint_printf("\n"); } GR_TMP_CLEAR2(x, y, R); fexpr_clear(expr); return status; } int gr_test_ctx_get_str(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; char * s; status = gr_ctx_get_str(&s, R); if (status != GR_SUCCESS) { status = GR_TEST_FAIL; flint_printf("ctx_get_str\n"); } flint_free(s); return status; } int gr_test_get_set_str(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y; char * s; GR_TMP_INIT2(x, y, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); status |= gr_get_str(&s, x, R); if (status == GR_SUCCESS) { status |= gr_set_str(y, s, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) { status = GR_TEST_FAIL; } } else { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("get_set_str\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); if (s == NULL) flint_printf("(NULL)\n"); else flint_printf("%s\n", s); flint_printf("y = \n"); gr_println(y, R); flint_printf("\n"); } flint_free(s); GR_TMP_CLEAR2(x, y, R); return status; } int gr_test_set_other(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y, z, xy, x2, y2, z2, t2; gr_ctx_t R2; gr_ctx_init_random(R2, state); GR_TMP_INIT4(x, y, z, xy, R); GR_TMP_INIT4(x2, y2, z2, t2, R2); status |= gr_randtest(x2, state, R2); status |= gr_randtest(y2, state, R2); status |= gr_add(z2, x2, y2, R2); status |= gr_set_other(x, x2, R2, R); status |= gr_set_other(y, y2, R2, R); status |= gr_set_other(z, z2, R2, R); status |= gr_add(xy, x, y, R); /* check that the conversion is homomorphic */ if (status == GR_SUCCESS && gr_equal(xy, z, R) == T_FALSE) status = GR_TEST_FAIL; /* test the reverse conversions */ if (status == GR_SUCCESS && gr_set_other(t2, x, R, R2) == GR_SUCCESS && gr_equal(x2, t2, R2) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && gr_set_other(t2, y, R, R2) == GR_SUCCESS && gr_equal(y2, t2, R2) == T_FALSE) status = GR_TEST_FAIL; if (status == GR_SUCCESS && gr_set_other(t2, xy, R, R2) == GR_SUCCESS && gr_equal(z2, t2, R2) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("gr_test_set_other\n"); gr_ctx_println(R); gr_ctx_println(R2); flint_printf("x2 = \n"); gr_println(x2, R2); flint_printf("y2 = \n"); gr_println(y2, R2); flint_printf("z2 = \n"); gr_println(z2, R2); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("z = \n"); gr_println(z, R); flint_printf("xy = \n"); gr_println(xy, R); flint_printf("t2 = \n"); gr_println(t2, R2); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, z, xy, R); GR_TMP_CLEAR4(x2, y2, z2, t2, R2); gr_ctx_clear(R2); return status; } int gr_test_mul_2exp_si(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, r1, r2; slong y; GR_TMP_INIT3(x, r1, r2, R); status = GR_SUCCESS; GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(r1, state, R)); y = n_randint(state, 200) - 100; if (n_randint(state, 2)) { status |= gr_mul_2exp_si(r1, x, y, R); } else { status |= gr_set(r1, x, R); status |= gr_mul_2exp_si(r1, r1, y, R); } if (n_randint(state, 2)) { status |= gr_set_ui(r2, 2, R); status |= gr_pow_si(r2, r2, y, R); status |= gr_mul(r2, x, r2, R); } else { status |= gr_set_ui(r2, 2, R); status |= gr_pow_si(r2, r2, -y, R); status |= gr_div(r2, x, r2, R); } if (status == GR_SUCCESS && gr_equal(r1, r2, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = "); gr_println(x, R); flint_printf("y = %wd\n", y); flint_printf("r1 = "); gr_println(r1, R); flint_printf("r2 = "); gr_println(r2, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, r1, r2, R); return status; } int gr_test_mul_2exp_fmpz(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, r1, r2; fmpz_t y; GR_TMP_INIT3(x, r1, r2, R); fmpz_init(y); status = GR_SUCCESS; GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(r1, state, R)); if (gr_ctx_is_finite(R) == T_TRUE) fmpz_randbits(y, state, 100); else fmpz_randbits(y, state, 8); if (n_randint(state, 2)) { status |= gr_mul_2exp_fmpz(r1, x, y, R); } else { status |= gr_set(r1, x, R); status |= gr_mul_2exp_fmpz(r1, r1, y, R); } if (n_randint(state, 2)) { status |= gr_set_ui(r2, 2, R); status |= gr_pow_fmpz(r2, r2, y, R); status |= gr_mul(r2, x, r2, R); } else { status |= gr_set_ui(r2, 2, R); fmpz_neg(y, y); status |= gr_pow_fmpz(r2, r2, y, R); fmpz_neg(y, y); status |= gr_div(r2, x, r2, R); } if (status == GR_SUCCESS && gr_equal(r1, r2, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = "); gr_println(x, R); flint_printf("y = "); fmpz_print(y); flint_printf("\n"); flint_printf("r1 = "); gr_println(r1, R); flint_printf("r2 = "); gr_println(r2, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, r1, r2, R); fmpz_clear(y); return status; } int gr_test_binary_op_type_variants(gr_ctx_t R, const char * opname, int (*gr_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), int (*gr_op_ui)(gr_ptr, gr_srcptr, ulong, gr_ctx_t), int (*gr_op_si)(gr_ptr, gr_srcptr, slong, gr_ctx_t), int (*gr_op_fmpz)(gr_ptr, gr_srcptr, const fmpz_t, gr_ctx_t), int (*gr_op_fmpq)(gr_ptr, gr_srcptr, const fmpq_t, gr_ctx_t), int fused, int small_test_values, flint_rand_t state, int test_flags) { int status, alias, which; gr_ptr x, y, xy1, xy2; ulong uy; slong sy; fmpz_t zy; fmpq_t qy; GR_TMP_INIT4(x, y, xy1, xy2, R); fmpz_init(zy); fmpq_init(qy); which = 0; if (small_test_values) { uy = n_randint(state, 6); sy = -5 + (slong) n_randint(state, 11); fmpz_randtest(zy, state, 3); fmpq_randtest(qy, state, 3); } else { uy = n_randtest(state); sy = (slong) n_randtest(state); fmpz_randtest(zy, state, 100); fmpq_randtest(qy, state, 100); } for (which = 0; which < 4; which++) { status = GR_SUCCESS; alias = n_randint(state, 2); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(xy1, state, R)); if (fused && alias) GR_MUST_SUCCEED(gr_set(xy2, x, R)); else if (fused) GR_MUST_SUCCEED(gr_set(xy2, xy1, R)); else GR_MUST_SUCCEED(gr_randtest(xy2, state, R)); if (alias) GR_MUST_SUCCEED(gr_set(xy1, x, R)); if (which == 0) { if (alias) status |= gr_op_ui(xy1, xy1, uy, R); else status |= gr_op_ui(xy1, x, uy, R); status |= gr_set_ui(y, uy, R); if (status == GR_SUCCESS) status |= gr_op(xy2, x, y, R); } else if (which == 1) { if (alias) status |= gr_op_si(xy1, xy1, sy, R); else status |= gr_op_si(xy1, x, sy, R); status |= gr_set_si(y, sy, R); if (status == GR_SUCCESS) status |= gr_op(xy2, x, y, R); } else if (which == 2) { if (alias) status |= gr_op_fmpz(xy1, xy1, zy, R); else status |= gr_op_fmpz(xy1, x, zy, R); status |= gr_set_fmpz(y, zy, R); if (status == GR_SUCCESS) status |= gr_op(xy2, x, y, R); } else { if (alias) status |= gr_op_fmpq(xy1, xy1, qy, R); else status |= gr_op_fmpq(xy1, x, qy, R); status |= gr_set_fmpq(y, qy, R); if (status == GR_SUCCESS) status |= gr_op(xy2, x, y, R); } if (status == GR_SUCCESS && gr_equal(xy1, xy2, R) == T_FALSE) { status = GR_TEST_FAIL; break; } } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("%s\n", opname); gr_ctx_println(R); flint_printf("which: %d\n", which); flint_printf("alias: %d\n", alias); flint_printf("x = "); gr_println(x, R); flint_printf("y = "); gr_println(y, R); flint_printf("y (op) y (1) = "); gr_println(xy1, R); flint_printf("x (op) y (2) = "); gr_println(xy2, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xy1, xy2, R); fmpz_clear(zy); fmpq_clear(qy); return status; } int gr_test_binary_op_associative(gr_ctx_t R, int (*gr_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), flint_rand_t state, int test_flags) { int status; gr_ptr x, y, z; gr_ptr xy, yz, xy_z, x_yz; GR_TMP_INIT3(x, y, z, R); GR_TMP_INIT4(xy, yz, xy_z, x_yz, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(z, state, R)); GR_MUST_SUCCEED(gr_randtest(xy, state, R)); GR_MUST_SUCCEED(gr_randtest(yz, state, R)); status = GR_SUCCESS; status |= gr_op(xy, x, y, R); status |= gr_op(yz, y, z, R); status |= gr_op(xy_z, xy, z, R); status |= gr_op(x_yz, x, yz, R); if (status == GR_SUCCESS && gr_equal(xy_z, x_yz, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("z = \n"); gr_println(z, R); flint_printf("x (op) y = \n"); gr_println(xy, R); flint_printf("y (op) z = \n"); gr_println(yz, R); flint_printf("(x (op) y) (op) z = \n"); gr_println(xy_z, R); flint_printf("x (op) (y (op) z) = \n"); gr_println(x_yz, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, y, z, R); GR_TMP_CLEAR4(xy, yz, xy_z, x_yz, R); return status; } int gr_test_binary_op_commutative(gr_ctx_t R, int (*gr_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), flint_rand_t state, int test_flags) { int status; gr_ptr x, y, xy, yx; GR_TMP_INIT4(x, y, xy, yx, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); status = GR_SUCCESS; status |= gr_op(xy, x, y, R); status |= gr_op(yx, y, x, R); if (status == GR_SUCCESS && gr_equal(xy, yx, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("y (op) y = \n"); gr_println(xy, R); flint_printf("y (op) x = \n"); gr_println(yx, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xy, yx, R); return status; } /* test x op (y op2 z) = (x op y) op2 (x op z) */ int gr_test_binary_op_left_distributive(gr_ctx_t R, int (*gr_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), int (*gr_op2)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), flint_rand_t state, int test_flags) { int status; gr_ptr x, y, z, yz, x_yz, xy, xz, xy_xz; GR_TMP_INIT4(x, y, z, yz, R); GR_TMP_INIT4(x_yz, xy, xz, xy_xz, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(z, state, R)); status = GR_SUCCESS; status |= gr_op2(yz, y, z, R); status |= gr_op(x_yz, x, yz, R); status |= gr_op(xy, x, y, R); status |= gr_op(xz, x, z, R); status |= gr_op2(xy_xz, xy, xz, R); if (status == GR_SUCCESS && gr_equal(x_yz, xy_xz, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("y (op2) z = \n"); gr_println(yz, R); flint_printf("x (op) (y (op2) z) = \n"); gr_println(x_yz, R); flint_printf("x (op) y = \n"); gr_println(xy, R); flint_printf("x (op) z = \n"); gr_println(xz, R); flint_printf("(x op y) (op2) (x op z) = \n"); gr_println(xy_xz, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, z, yz, R); GR_TMP_CLEAR4(x_yz, xy, xz, xy_xz, R); return status; } /* test (y op2 z) op x = (y op x) op2 (z op x) */ int gr_test_binary_op_right_distributive(gr_ctx_t R, int (*gr_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), int (*gr_op2)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), flint_rand_t state, int test_flags) { int status; gr_ptr x, y, z, yz, yz_x, yx, zx, yx_zx; GR_TMP_INIT4(x, y, z, yz, R); GR_TMP_INIT4(yz_x, yx, zx, yx_zx, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(z, state, R)); status = GR_SUCCESS; status |= gr_op2(yz, y, z, R); status |= gr_op(yz_x, yz, x, R); status |= gr_op(yx, y, x, R); status |= gr_op(zx, z, x, R); status |= gr_op2(yx_zx, yx, zx, R); if (status == GR_SUCCESS && gr_equal(yz_x, yx_zx, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("y (op2) z = \n"); gr_println(yz, R); flint_printf("(y (op2) z) op x = \n"); gr_println(yz_x, R); flint_printf("y (op) x = \n"); gr_println(yz, R); flint_printf("z (op) x = \n"); gr_println(zx, R); flint_printf("(y op x) (op2) (z op x) = \n"); gr_println(yx_zx, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, z, yz, R); GR_TMP_CLEAR4(yz_x, yx, zx, yx_zx, R); return status; } int gr_test_init_clear(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a, b, c, d, e; status = GR_SUCCESS; GR_TMP_INIT(a, R); status |= gr_randtest(a, state, R); GR_TMP_CLEAR(a, R); GR_TMP_INIT2(a, b, R); status |= gr_randtest(a, state, R); status |= gr_randtest(b, state, R); GR_TMP_CLEAR2(a, b, R); GR_TMP_INIT3(a, b, c, R); status |= gr_randtest(a, state, R); status |= gr_randtest(b, state, R); status |= gr_randtest(c, state, R); GR_TMP_CLEAR3(a, b, c, R); GR_TMP_INIT4(a, b, c, d, R); status |= gr_randtest(a, state, R); status |= gr_randtest(b, state, R); status |= gr_randtest(c, state, R); status |= gr_randtest(d, state, R); GR_TMP_CLEAR4(a, b, c, d, R); GR_TMP_INIT5(a, b, c, d, e, R); status |= gr_randtest(a, state, R); status |= gr_randtest(b, state, R); status |= gr_randtest(c, state, R); status |= gr_randtest(d, state, R); status |= gr_randtest(e, state, R); GR_TMP_CLEAR5(a, b, c, d, e, R); if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; return status; } int gr_test_equal(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a, b; truth_t equal0, equal1; status = GR_SUCCESS; GR_TMP_INIT2(a, b, R); status |= gr_randtest(a, state, R); status |= gr_set(b, a, R); equal0 = gr_equal(a, a, R); equal1 = gr_equal(a, b, R); if (status == GR_SUCCESS && (equal0 == T_FALSE || equal1 == T_FALSE)) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if (status == GR_TEST_FAIL) { flint_printf("FAIL: equal\n"); gr_ctx_println(R); flint_printf("a = "); gr_println(a, R); flint_printf("(a == a) = "); truth_println(equal0); flint_printf("b = "); gr_println(b, R); flint_printf("(a == b) = "); truth_println(equal1); } GR_TMP_CLEAR2(a, b, R); return status; } int gr_test_swap(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a, b, c, d; truth_t equal0, equal1, equal2, equal3, equal4; status = GR_SUCCESS; GR_TMP_INIT4(a, b, c, d, R); status |= gr_randtest(a, state, R); status |= gr_randtest(b, state, R); status |= gr_set(c, a, R); status |= gr_set(d, b, R); gr_swap(a, a, R); equal0 = gr_equal(a, c, R); gr_swap(a, b, R); equal1 = gr_equal(b, c, R); equal2 = gr_equal(a, d, R); gr_swap(a, b, R); equal3 = gr_equal(a, c, R); equal4 = gr_equal(b, d, R); if (status == GR_SUCCESS && (equal0 == T_FALSE || equal1 == T_FALSE || equal2 == T_FALSE || equal3 == T_FALSE || equal4 == T_FALSE)) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; GR_TMP_CLEAR4(a, b, c, d, R); return status; } int gr_test_zero_one(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a; truth_t equal; status = GR_SUCCESS; GR_TMP_INIT(a, R); status |= gr_randtest(a, state, R); status |= gr_zero(a, R); equal = gr_is_zero(a, R); if (status == GR_SUCCESS && equal == T_FALSE) status = GR_TEST_FAIL; status |= gr_randtest(a, state, R); status |= gr_one(a, R); equal = gr_is_one(a, R); if (status == GR_SUCCESS && equal == T_FALSE) { flint_printf("FAILL is_one\n"); gr_ctx_println(R); gr_println(a, R); status = GR_TEST_FAIL; } status |= gr_randtest(a, state, R); status |= gr_one(a, R); status |= gr_neg(a, a, R); equal = gr_is_neg_one(a, R); if (status == GR_SUCCESS && equal == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; GR_TMP_CLEAR(a, R); return status; } int gr_test_randtest_not_zero(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a; truth_t is_zero; status = GR_SUCCESS; GR_TMP_INIT(a, R); status |= gr_randtest_not_zero(a, state, R); if (status == GR_SUCCESS) { is_zero = gr_is_zero(a, R); if (status == GR_SUCCESS && is_zero == T_TRUE) status = GR_TEST_FAIL; } GR_TMP_CLEAR(a, R); return status; } int gr_test_one(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a; truth_t equal; status = GR_SUCCESS; GR_TMP_INIT(a, R); status |= gr_randtest(a, state, R); status |= gr_one(a, R); equal = gr_is_one(a, R); if (status == GR_SUCCESS && equal == T_FALSE) status = GR_TEST_FAIL; status |= gr_randtest(a, state, R); status |= gr_one(a, R); status |= gr_inv(a, a, R); if (status == GR_SUCCESS && equal == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; GR_TMP_CLEAR(a, R); return status; } int gr_test_add_associative(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_associative(R, gr_add, state, test_flags); } int gr_test_neg(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y, xy; GR_TMP_INIT3(x, y, xy, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(xy, state, R)); status = GR_SUCCESS; /* check x + (-x) = 0 */ status |= gr_neg(y, x, R); status |= gr_add(xy, x, y, R); if (status == GR_SUCCESS && gr_is_zero(xy, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("x + y = \n"); gr_println(xy, R); flint_printf("\n"); } /* check -(-x) = x, plus aliasing */ status |= gr_neg(y, y, R); if (status == GR_SUCCESS && gr_equal(x, y, R) == T_FALSE) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, y, xy, R); return status; } int gr_test_add_commutative(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_commutative(R, gr_add, state, test_flags); } int gr_test_add_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_aliasing(R, gr_add, state, test_flags); } int gr_test_add_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_type_variants(R, "add", gr_add, gr_add_ui, gr_add_si, gr_add_fmpz, gr_add_fmpq, 0, 0, state, test_flags); } int gr_test_sub_equal_neg_add(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y, neg_y, x_sub_y, x_neg_y; GR_TMP_INIT5(x, y, neg_y, x_sub_y, x_neg_y, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(neg_y, state, R)); GR_MUST_SUCCEED(gr_randtest(x_sub_y, state, R)); GR_MUST_SUCCEED(gr_randtest(x_neg_y, state, R)); status = GR_SUCCESS; status |= gr_sub(x_sub_y, x, y, R); status |= gr_neg(neg_y, y, R); status |= gr_add(x_neg_y, x, neg_y, R); if (status == GR_SUCCESS && gr_equal(x_sub_y, x_neg_y, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("-y = \n"); gr_println(neg_y, R); flint_printf("x - y = \n"); gr_println(x_sub_y, R); flint_printf("x + (-y) = \n"); gr_println(x_neg_y, R); flint_printf("\n"); } GR_TMP_CLEAR5(x, y, neg_y, x_sub_y, x_neg_y, R); return status; } int gr_test_sub_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_aliasing(R, gr_sub, state, test_flags); } int gr_test_sub_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_type_variants(R, "sub", gr_sub, gr_sub_ui, gr_sub_si, gr_sub_fmpz, gr_sub_fmpq, 0, 0, state, test_flags); } int gr_test_mul_associative(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_associative(R, gr_mul, state, test_flags); } int gr_test_mul_commutative(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_commutative(R, gr_mul, state, test_flags); } int gr_test_mul_left_distributive(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_left_distributive(R, gr_mul, gr_add, state, test_flags); } int gr_test_mul_right_distributive(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_right_distributive(R, gr_mul, gr_add, state, test_flags); } int gr_test_mul_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_aliasing(R, gr_mul, state, test_flags); } int gr_test_mul_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_type_variants(R, "mul", gr_mul, gr_mul_ui, gr_mul_si, gr_mul_fmpz, gr_mul_fmpq, 0, 0, state, test_flags); } int gr_test_addmul_submul(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; int which; gr_ptr x, y, z, t; GR_TMP_INIT4(x, y, z, t, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(z, state, R)); status = GR_SUCCESS; which = n_randint(state, 10); switch (which) { case 0: status |= gr_mul(t, y, z, R); status |= gr_add(t, x, t, R); status |= gr_addmul(x, y, z, R); break; case 1: status |= gr_mul(t, y, y, R); status |= gr_add(t, x, t, R); status |= gr_addmul(x, y, y, R); break; case 2: status |= gr_mul(t, x, z, R); status |= gr_add(t, x, t, R); status |= gr_addmul(x, x, z, R); break; case 3: status |= gr_mul(t, y, x, R); status |= gr_add(t, x, t, R); status |= gr_addmul(x, y, x, R); break; case 4: status |= gr_mul(t, x, x, R); status |= gr_add(t, x, t, R); status |= gr_addmul(x, x, x, R); break; case 5: status |= gr_mul(t, y, z, R); status |= gr_sub(t, x, t, R); status |= gr_submul(x, y, z, R); break; case 6: status |= gr_mul(t, y, y, R); status |= gr_sub(t, x, t, R); status |= gr_submul(x, y, y, R); break; case 7: status |= gr_mul(t, x, z, R); status |= gr_sub(t, x, t, R); status |= gr_submul(x, x, z, R); break; case 8: status |= gr_mul(t, y, x, R); status |= gr_sub(t, x, t, R); status |= gr_submul(x, y, x, R); break; case 9: status |= gr_mul(t, x, x, R); status |= gr_sub(t, x, t, R); status |= gr_submul(x, x, x, R); break; default: break; } if (status == GR_SUCCESS && gr_equal(x, t, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("which = %d\n", which); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("z = \n"); gr_println(z, R); flint_printf("t = \n"); gr_println(t, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, z, t, R); return status; } int gr_test_addmul_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_type_variants(R, "addmul", gr_addmul, gr_addmul_ui, gr_addmul_si, gr_addmul_fmpz, gr_addmul_fmpq, 1, 0, state, test_flags); } int gr_test_submul_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_type_variants(R, "submul", gr_submul, gr_submul_ui, gr_submul_si, gr_submul_fmpz, gr_submul_fmpq, 1, 0, state, test_flags); } int gr_test_div_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_aliasing(R, gr_div, state, test_flags); } int gr_test_div_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_type_variants(R, "div", gr_div, gr_div_ui, gr_div_si, gr_div_fmpz, gr_div_fmpq, 0, 0, state, test_flags); } int gr_test_is_invertible(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; truth_t invertible = T_UNKNOWN; gr_ptr x, x_inv; GR_TMP_INIT2(x, x_inv, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); status = GR_SUCCESS; status |= gr_inv(x_inv, x, R); if (status != GR_UNABLE) { invertible = gr_is_invertible(x, R); if ((status == GR_SUCCESS && invertible == T_FALSE) || (status == GR_DOMAIN && invertible == T_TRUE)) { status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("x ^ -1 = \n"); gr_println(x_inv, R); flint_printf("status = %d, invertible = %d\n", status, invertible); flint_printf("\n"); } GR_TMP_CLEAR2(x, x_inv, R); return status; } int gr_test_inv_involution(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, x_inv, x_inv_inv; GR_TMP_INIT3(x, x_inv, x_inv_inv, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(x_inv, state, R)); GR_MUST_SUCCEED(gr_randtest(x_inv_inv, state, R)); status = GR_SUCCESS; status |= gr_inv(x_inv, x, R); status |= gr_inv(x_inv_inv, x_inv, R); if (status == GR_SUCCESS && gr_equal(x, x_inv_inv, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("x ^ -1 = \n"); gr_println(x_inv, R); flint_printf("(x ^ -1) ^ -1 = \n"); gr_println(x_inv_inv, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, x_inv, x_inv_inv, R); return status; } int gr_test_inv_multiplication(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; truth_t equal1, equal2; gr_ptr x, x_inv, x_inv_x, x_x_inv; GR_TMP_INIT4(x, x_inv, x_inv_x, x_x_inv, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(x_inv, state, R)); GR_MUST_SUCCEED(gr_randtest(x_inv_x, state, R)); GR_MUST_SUCCEED(gr_randtest(x_x_inv, state, R)); /* todo: split status */ status = GR_SUCCESS; status |= gr_inv(x_inv, x, R); status |= gr_mul(x_inv_x, x_inv, x, R); status |= gr_mul(x_x_inv, x, x_inv, R); equal1 = gr_is_one(x_inv_x, R); equal2 = gr_is_one(x_x_inv, R); if (status == GR_SUCCESS && (equal1 == T_FALSE || equal2 == T_FALSE)) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("x ^ -1 = \n"); gr_println(x_inv, R); flint_printf("(x ^ -1) * x = \n"); gr_println(x_inv_x, R); flint_printf("x * (x ^ -1) = \n"); gr_println(x_x_inv, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, x_inv, x_inv_x, x_x_inv, R); return status; } int gr_test_div_right_distributive(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_right_distributive(R, gr_div, gr_add, state, test_flags); } int gr_test_div_then_mul(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y, xy, xyy; GR_TMP_INIT4(x, y, xy, xyy, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(xy, state, R)); GR_MUST_SUCCEED(gr_randtest(xyy, state, R)); status = GR_SUCCESS; status |= gr_div(xy, x, y, R); status |= gr_mul(xyy, xy, y, R); if (status == GR_SUCCESS && gr_equal(x, xyy, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("x / y = \n"); gr_println(xy, R); flint_printf("(x / y) * y = \n"); gr_println(xyy, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xy, xyy, R); return status; } int gr_test_mul_then_div(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, y, xy, xyy; GR_TMP_INIT4(x, y, xy, xyy, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(xy, state, R)); GR_MUST_SUCCEED(gr_randtest(xyy, state, R)); status = GR_SUCCESS; status |= gr_mul(xy, x, y, R); status |= gr_div(xyy, xy, y, R); if (status == GR_SUCCESS && gr_equal(x, xyy, R) == T_FALSE && gr_ctx_is_integral_domain(R) == T_TRUE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("x * y = \n"); gr_println(xy, R); flint_printf("(x * y) / y = \n"); gr_println(xyy, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xy, xyy, R); return status; } int gr_test_divexact(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; int aliasing; gr_ptr x, y, xy, q; GR_TMP_INIT4(x, y, xy, q, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); aliasing = n_randint(state, 3); status = GR_SUCCESS; status |= gr_mul(xy, x, y, R); if (aliasing == 0) { status |= gr_divexact(q, xy, y, R); } else if (aliasing == 1) { status |= gr_set(q, xy, R); status |= gr_divexact(q, q, y, R); } else { status |= gr_set(q, y, R); status |= gr_divexact(q, xy, q, R); } if (status == GR_SUCCESS && gr_equal(q, x, R) == T_FALSE && gr_ctx_is_integral_domain(R) == T_TRUE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("aliasing = %d\n", aliasing); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("xy = \n"); gr_println(xy, R); flint_printf("q = \n"); gr_println(q, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xy, q, R); return status; } /* todo: fmpq */ int gr_test_divexact_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { int status, alias, which; gr_ptr x, xy, q; ulong uy; slong sy; fmpz_t zy; GR_TMP_INIT3(x, xy, q, R); fmpz_init(zy); which = 0; uy = n_randtest(state); sy = (slong) n_randtest(state); fmpz_randtest(zy, state, 100); for (which = 0; which < 4; which++) { GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(q, state, R)); status = GR_SUCCESS; alias = n_randint(state, 2); if (which == 0) { status |= gr_mul_ui(xy, x, uy, R); if (alias) { status |= gr_set(q, xy, R); status |= gr_divexact_ui(q, q, uy, R); } else { status |= gr_divexact_ui(q, xy, uy, R); } } else if (which == 1) { status |= gr_mul_si(xy, x, sy, R); if (alias) { status |= gr_set(q, xy, R); status |= gr_divexact_si(q, q, sy, R); } else { status |= gr_divexact_si(q, xy, sy, R); } } else { status |= gr_mul_fmpz(xy, x, zy, R); if (alias) { status |= gr_set(q, xy, R); status |= gr_divexact_fmpz(q, q, zy, R); } else { status |= gr_divexact_fmpz(q, xy, zy, R); } } if (status == GR_SUCCESS && gr_equal(q, x, R) == T_FALSE && gr_ctx_is_integral_domain(R) == T_TRUE) { status = GR_TEST_FAIL; break; } } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("which: %d\n", which); flint_printf("alias: %d\n", alias); flint_printf("x = "); gr_println(x, R); flint_printf("xy = "); gr_println(xy, R); flint_printf("q = "); gr_println(q, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, xy, q, R); fmpz_clear(zy); return status; } int gr_test_div_nonunique(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; int status2 = GR_SUCCESS; int status3 = GR_SUCCESS; int status4 = GR_SUCCESS; int status5 = GR_SUCCESS; gr_ptr x, y, xy, z, q; GR_TMP_INIT5(x, y, xy, z, q, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); status |= gr_mul(xy, x, y, R); if (status == GR_SUCCESS) { status2 = gr_div_nonunique(q, xy, x, R); if (status2 == GR_DOMAIN) { status = GR_TEST_FAIL; } else if (status2 == GR_SUCCESS) { status2 = gr_mul(z, q, x, R); if (status2 == GR_SUCCESS && gr_equal(z, xy, R) == T_FALSE) status = GR_TEST_FAIL; } status3 = gr_div_nonunique(q, xy, y, R); if (status3 == GR_DOMAIN) { status = GR_TEST_FAIL; } else if (status3 == GR_SUCCESS) { status3 = gr_mul(z, q, y, R); if (status3 == GR_SUCCESS && gr_equal(z, xy, R) == T_FALSE) status = GR_TEST_FAIL; } status4 = gr_div_nonunique(z, x, y, R); if (status4 == GR_DOMAIN) { /* if claimed non-divisible, verify that div claims the same */ status5 = gr_div(z, x, y, R); if (status5 == GR_SUCCESS) status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("div_nonunique\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("xy = \n"); gr_println(xy, R); flint_printf("z = \n"); gr_println(z, R); flint_printf("status = %d, %d, %d, %d, %d\n", status, status2, status3, status4, status5); flint_printf("\n"); } GR_TMP_CLEAR5(x, y, xy, z, q, R); return status; } int gr_test_div_nonunique_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_aliasing(R, gr_div_nonunique, state, test_flags); } int gr_test_divides(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; int status2 = GR_SUCCESS; int status3 = GR_SUCCESS; int status4 = GR_SUCCESS; truth_t x_divides = T_UNKNOWN, y_divides = T_UNKNOWN; gr_ptr x, y, xy, z; GR_TMP_INIT4(x, y, xy, z, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); status |= gr_mul(xy, x, y, R); if (status == GR_SUCCESS) { x_divides = gr_divides(x, xy, R); y_divides = gr_divides(y, xy, R); if (x_divides == T_FALSE || y_divides == T_FALSE) { status = GR_TEST_FAIL; } if (gr_ctx_is_integral_domain(R) == T_TRUE) { if (gr_is_zero(x, R) == T_FALSE) { status2 = gr_divexact(z, xy, x, R); if (status2 == GR_DOMAIN) status = GR_TEST_FAIL; } if (gr_is_zero(y, R) == T_FALSE) { status3 = gr_divexact(z, xy, y, R); if (status3 == GR_DOMAIN) status = GR_TEST_FAIL; } } } if (status == GR_SUCCESS) { truth_t d = gr_divides(x, y, R); /* if claimed non-divisible, verify that div claims the same */ if (d == T_FALSE) { status4 = gr_div(z, y, x, R); if (status4 == GR_SUCCESS) status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("divides\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("xy = \n"); gr_println(xy, R); flint_printf("x divides = "); truth_println(x_divides); flint_printf("y divides = "); truth_println(y_divides); flint_printf("status = %d, %d, %d, %d\n", status, status2, status3, status4); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xy, z, R); return status; } int gr_test_pow_ui_exponent_addition(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; ulong a, b; gr_ptr x, xa, xb, xab, xaxb; GR_TMP_INIT5(x, xa, xb, xab, xaxb, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); GR_MUST_SUCCEED(gr_randtest(xb, state, R)); GR_MUST_SUCCEED(gr_randtest(xab, state, R)); GR_MUST_SUCCEED(gr_randtest(xaxb, state, R)); if (gr_ctx_is_finite(R) == T_TRUE) { do { a = n_randtest(state); b = n_randtest(state); } while (a + b < a); } else { a = n_randtest(state) % 20; b = n_randtest(state) % 20; } status = GR_SUCCESS; status |= gr_pow_ui(xa, x, a, R); status |= gr_pow_ui(xb, x, b, R); status |= gr_pow_ui(xab, x, a + b, R); status |= gr_mul(xaxb, xa, xb, R); if (status == GR_SUCCESS && gr_equal(xab, xaxb, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("x ^ a = \n"); gr_println(xa, R); flint_printf("x ^ b = \n"); gr_println(xb, R); flint_printf("x ^ (a + b) = \n"); gr_println(xab, R); flint_printf("(x ^ a) * (x ^ b) = \n"); gr_println(xaxb, R); flint_printf("\n"); } GR_TMP_CLEAR5(x, xa, xb, xab, xaxb, R); return status; } int gr_test_pow_ui_base_scalar_multiplication(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; ulong a; slong y; gr_ptr x, xa, ya, xya, xaya; GR_TMP_INIT3(x, xa, ya, R); GR_TMP_INIT2(xya, xaya, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); GR_MUST_SUCCEED(gr_randtest(ya, state, R)); y = n_randtest(state); if (gr_ctx_is_finite(R) == T_TRUE) a = n_randtest(state); else a = n_randtest(state) % 20; status = GR_SUCCESS; status |= gr_pow_ui(xa, x, a, R); status |= gr_set_si(ya, y, R); status |= gr_pow_ui(ya, ya, a, R); status |= gr_set_si(xya, y, R); status |= gr_mul(xya, x, xya, R); /* todo mul_si */ status |= gr_pow_ui(xya, xya, a, R); status |= gr_mul(xaya, xa, ya, R); if (status == GR_SUCCESS && gr_equal(xya, xaya, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = %wd\n", y); flint_printf("a = %wu\n", a); flint_printf("x ^ a = \n"); gr_println(xa, R); flint_printf("y ^ a = \n"); gr_println(ya, R); flint_printf("(x * y) ^ a = \n"); gr_println(xya, R); flint_printf("(x ^ a) * (y ^ a) = \n"); gr_println(xaya, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, xa, ya, R); GR_TMP_CLEAR2(xya, xaya, R); return status; } int gr_test_pow_ui_base_multiplication(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; ulong a; gr_ptr x, y, xa, ya, xya, xaya; GR_TMP_INIT4(x, y, xa, ya, R); GR_TMP_INIT2(xya, xaya, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); GR_MUST_SUCCEED(gr_randtest(ya, state, R)); if (gr_ctx_is_finite(R) == T_TRUE) a = n_randtest(state); else a = n_randtest(state) % 20; status = GR_SUCCESS; status |= gr_pow_ui(xa, x, a, R); status |= gr_pow_ui(ya, y, a, R); status |= gr_mul(xya, x, y, R); status |= gr_pow_ui(xya, xya, a, R); status |= gr_mul(xaya, xa, ya, R); if (status == GR_SUCCESS && gr_equal(xya, xaya, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("a = %wu\n", a); flint_printf("x ^ a = \n"); gr_println(xa, R); flint_printf("y ^ a = \n"); gr_println(ya, R); flint_printf("(x * y) ^ a = \n"); gr_println(xya, R); flint_printf("(x ^ a) * (y ^ a) = \n"); gr_println(xaya, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, xa, ya, R); GR_TMP_CLEAR2(xya, xaya, R); return status; } int gr_test_pow_ui_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; ulong a; gr_ptr x, xa1, xa2; GR_TMP_INIT3(x, xa1, xa2, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(xa1, state, R)); if (gr_ctx_is_finite(R) == T_TRUE) a = n_randtest(state); else a = n_randtest(state) % 20; status = GR_SUCCESS; status |= gr_pow_ui(xa1, x, a, R); status |= gr_set(xa2, x, R); status |= gr_pow_ui(xa2, xa2, a, R); if (status == GR_SUCCESS && gr_equal(xa1, xa2, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("a = %wu\n", a); flint_printf("x ^ a (1) = \n"); gr_println(xa1, R); flint_printf("x ^ a (2) = \n"); gr_println(xa2, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, xa1, xa2, R); return status; } int gr_test_pow_fmpz_exponent_addition(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; fmpz_t a, b, ab; gr_ptr x, xa, xb, xab, xaxb; GR_TMP_INIT5(x, xa, xb, xab, xaxb, R); fmpz_init(a); fmpz_init(b); fmpz_init(ab); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); GR_MUST_SUCCEED(gr_randtest(xb, state, R)); GR_MUST_SUCCEED(gr_randtest(xab, state, R)); GR_MUST_SUCCEED(gr_randtest(xaxb, state, R)); if (gr_ctx_is_finite(R) == T_TRUE) { fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 100); } else if (n_randint(state, 20) == 0) { if (gr_set_si(x, -1 + (slong) n_randint(state, 3), R) != GR_SUCCESS) /* allow using for groups */ GR_MUST_SUCCEED(gr_one(x, R)); fmpz_randtest(a, state, 100); fmpz_randtest(b, state, 100); } else { fmpz_randtest(a, state, 4); fmpz_randtest(b, state, 4); } fmpz_add(ab, a, b); status = GR_SUCCESS; status |= gr_pow_fmpz(xa, x, a, R); status |= gr_pow_fmpz(xb, x, b, R); status |= gr_pow_fmpz(xab, x, ab, R); status |= gr_mul(xaxb, xa, xb, R); if (status == GR_SUCCESS && gr_equal(xab, xaxb, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("a = "); fmpz_print(a); flint_printf("\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n"); flint_printf("x ^ a = \n"); gr_println(xa, R); flint_printf("x ^ b = \n"); gr_println(xb, R); flint_printf("x ^ (a + b) = \n"); gr_println(xab, R); flint_printf("(x ^ a) * (x ^ b) = \n"); gr_println(xaxb, R); flint_printf("\n"); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(ab); GR_TMP_CLEAR5(x, xa, xb, xab, xaxb, R); return status; } int gr_test_pow_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, a, xa1, xa2; GR_TMP_INIT4(x, a, xa1, xa2, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(xa1, state, R)); GR_MUST_SUCCEED(gr_randtest_small(a, state, R)); status = GR_SUCCESS; switch (n_randint(state, 3)) { case 0: status |= gr_set(xa2, x, R); status |= gr_pow(xa2, xa2, a, R); break; case 1: status |= gr_set(xa2, a, R); status |= gr_pow(xa2, x, xa2, R); break; default: status |= gr_set(xa2, a, R); status |= gr_set(x, a, R); status |= gr_pow(xa2, xa2, xa2, R); } status |= gr_pow(xa1, x, a, R); if (status == GR_SUCCESS && gr_equal(xa1, xa2, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("a = \n"); gr_println(a, R); flint_printf("x ^ a (1) = \n"); gr_println(xa1, R); flint_printf("x ^ a (2) = \n"); gr_println(xa2, R); flint_printf("\n"); } GR_TMP_CLEAR4(x, a, xa1, xa2, R); return status; } int gr_test_pow_exponent_addition(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a, b, ab; gr_ptr x, xa, xb, xab, xaxb; GR_TMP_INIT5(x, xa, xb, xab, xaxb, R); GR_TMP_INIT3(a, b, ab, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(xa, state, R)); GR_MUST_SUCCEED(gr_randtest(xb, state, R)); GR_MUST_SUCCEED(gr_randtest(xab, state, R)); GR_MUST_SUCCEED(gr_randtest(xaxb, state, R)); GR_MUST_SUCCEED(gr_randtest_small(a, state, R)); GR_MUST_SUCCEED(gr_randtest_small(b, state, R)); status = GR_SUCCESS; status |= gr_add(ab, a, b, R); status |= gr_pow(xa, x, a, R); status |= gr_pow(xb, x, b, R); status |= gr_pow(xab, x, ab, R); status |= gr_mul(xaxb, xa, xb, R); if (status == GR_SUCCESS && gr_equal(xab, xaxb, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("a = \n"); gr_println(a, R); flint_printf("b = \n"); gr_println(b, R); flint_printf("a + b = \n"); gr_println(ab, R); flint_printf("x ^ a = \n"); gr_println(xa, R); flint_printf("x ^ b = \n"); gr_println(xb, R); flint_printf("x ^ (a + b) = \n"); gr_println(xab, R); flint_printf("(x ^ a) * (x ^ b) = \n"); gr_println(xaxb, R); flint_printf("\n"); } GR_TMP_CLEAR5(x, xa, xb, xab, xaxb, R); GR_TMP_CLEAR3(a, b, ab, R); return status; } int gr_test_pow_type_variants(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_binary_op_type_variants(R, "pow", gr_pow, gr_pow_ui, gr_pow_si, gr_pow_fmpz, gr_pow_fmpq, 0, 1, state, test_flags); } int gr_test_sqrt(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y, y2; int perfect; GR_TMP_INIT3(x, y, y2, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); perfect = n_randint(state, 2); if (perfect) status |= gr_sqr(x, x, R); if (n_randint(state, 2)) { status |= gr_set(y, x, R); status |= gr_sqrt(y, y, R); } else { status |= gr_sqrt(y, x, R); } status |= gr_sqr(y2, y, R); if (status == GR_SUCCESS && gr_equal(y2, x, R) == T_FALSE) { status = GR_TEST_FAIL; } if (status == GR_DOMAIN && perfect) { status = GR_TEST_FAIL; } if (status == GR_SUCCESS && perfect && gr_is_square(x, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("FAIL: sqrt\n"); flint_printf("R = "); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("y ^ 2 = \n"); gr_println(y2, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, y, y2, R); return status; } int gr_test_rsqrt(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y, z; int perfect; GR_TMP_INIT3(x, y, z, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); perfect = n_randint(state, 2); if (perfect) status |= gr_sqr(x, x, R); if (n_randint(state, 2)) { status |= gr_set(y, x, R); status |= gr_rsqrt(y, y, R); } else { status |= gr_rsqrt(y, x, R); } status |= gr_inv(z, y, R); status |= gr_sqr(z, z, R); if (status == GR_SUCCESS && gr_equal(z, x, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("FAIL: rsqrt\n"); flint_printf("R = "); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("1 / y ^ 2 = \n"); gr_println(z, R); flint_printf("\n"); } GR_TMP_CLEAR3(x, y, z, R); return status; } int gr_test_ordered_ring_cmp(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y, z, xz, yz, zero, xy; int cmp1, cmp2, cmp3; GR_TMP_INIT5(x, y, z, xz, yz, R); GR_TMP_INIT2(zero, xy, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); GR_MUST_SUCCEED(gr_randtest(z, state, R)); /* cmp(x, y) = -cmp(y, x) */ status |= gr_cmp(&cmp1, x, y, R); status |= gr_cmp(&cmp2, y, x, R); if (status == GR_SUCCESS && cmp1 != -cmp2) { status = GR_TEST_FAIL; } /* x <= y --> x + z <= y + z */ status |= gr_add(xz, x, z, R); status |= gr_add(yz, y, z, R); status |= gr_cmp(&cmp1, x, y, R); status |= gr_cmp(&cmp2, xz, yz, R); if (status == GR_SUCCESS && cmp1 != cmp2) { status = GR_TEST_FAIL; } /* 0 <= x and 0 <= y --> 0 <= xy */ status |= gr_cmp(&cmp1, zero, x, R); status |= gr_cmp(&cmp2, zero, y, R); status |= gr_mul(xy, x, y, R); status |= gr_cmp(&cmp3, zero, xy, R); if (status == GR_SUCCESS && cmp1 <= 0 && cmp2 <= 0 && cmp3 > 0) { status = GR_TEST_FAIL; } if (status & GR_DOMAIN && !(status & GR_UNABLE)) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("FAIL: ordered_ring_cmp\n"); flint_printf("R = "); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("z = \n"); gr_println(z, R); flint_printf("x + z = \n"); gr_println(xz, R); flint_printf("y + z = \n"); gr_println(yz, R); flint_printf("xy = \n"); gr_println(xy, R); flint_printf("cmp = %d, %d, %d\n", cmp1, cmp2, cmp3); flint_printf("\n"); } GR_TMP_CLEAR5(x, y, z, xz, yz, R); GR_TMP_CLEAR2(zero, xy, R); return status; } int gr_test_ordered_ring_cmpabs(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y, ax, ay; int cmp1, cmp2; GR_TMP_INIT4(x, y, ax, ay, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); status |= gr_abs(ax, x, R); status |= gr_abs(ay, y, R); status |= gr_cmpabs(&cmp1, x, y, R); status |= gr_cmp(&cmp2, ax, ay, R); if (status == GR_SUCCESS && cmp1 != cmp2) { status = GR_TEST_FAIL; } if (status & GR_DOMAIN && !(status & GR_UNABLE)) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("R = "); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("ax = \n"); gr_println(ax, R); flint_printf("ay = \n"); gr_println(ay, R); flint_printf("cmp = %d, %d\n", cmp1, cmp2); flint_printf("\n"); } GR_TMP_CLEAR4(x, y, ax, ay, R); return status; } int gr_test_complex_parts(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, a, b, ab, i; GR_TMP_INIT5(x, a, b, ab, i, R); status = gr_i(i, R); if (status == GR_SUCCESS) { int which_test = n_randint(state, 3); GR_MUST_SUCCEED(gr_randtest(x, state, R)); if (which_test == 0) { /* check x == re(x) + im(x)*i */ status |= gr_re(a, x, R); status |= gr_im(b, x, R); status |= gr_mul(ab, b, i, R); status |= gr_add(ab, a, ab, R); } else if (which_test == 1) { /* check x == abs(x) * sgn(x) */ status |= gr_abs(a, x, R); status |= gr_sgn(b, x, R); status |= gr_mul(ab, a, b, R); } else { /* check x == re(conj(x)) - im(conj(x))*i */ status |= gr_conj(a, x, R); status |= gr_re(a, a, R); status |= gr_conj(b, x, R); status |= gr_im(b, b, R); status |= gr_mul(ab, b, i, R); status |= gr_sub(ab, a, ab, R); } if (status == GR_SUCCESS && gr_equal(x, ab, R) == T_FALSE) { status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); gr_ctx_println(R); flint_printf("x = \n"); gr_println(x, R); flint_printf("a = \n"); gr_println(a, R); flint_printf("b = \n"); gr_println(b, R); flint_printf("ab = \n"); gr_println(ab, R); flint_printf("\n"); } GR_TMP_CLEAR5(x, a, b, ab, i, R); return status; } int gr_test_gcd(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a, f, g, d, t; int aliasing; GR_TMP_INIT5(a, f, g, d, t, R); status = GR_SUCCESS; status |= gr_randtest(a, state, R); status |= gr_randtest(f, state, R); status |= gr_randtest(g, state, R); status |= gr_mul(f, a, f, R); status |= gr_mul(g, g, a, R); aliasing = n_randint(state, 3); if (status == GR_SUCCESS) { if (aliasing == 0) { status |= gr_gcd(d, f, g, R); } else if (aliasing == 1) { status |= gr_set(d, f, R); status |= gr_gcd(d, d, g, R); } else if (aliasing == 2) { status |= gr_set(d, g, R); status |= gr_gcd(d, f, d, R); } if (status == GR_SUCCESS && gr_divides(a, d, R) == T_FALSE) { status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("gcd\n"); gr_ctx_println(R); flint_printf("aliasing = %d\n", aliasing); flint_printf("a = "); gr_println(a, R); flint_printf("f = "); gr_println(f, R); flint_printf("g = "); gr_println(g, R); flint_printf("gcd = "); gr_println(d, R); flint_printf("\n"); } GR_TMP_CLEAR5(a, f, g, d, t, R); return status; } /* verify that LCM(a, b) GCD(a, b) ~ a b */ int gr_test_lcm(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a, b, x, y, ab, xy; int aliasing; GR_TMP_INIT3(a, b, ab, R); GR_TMP_INIT3(x, y, xy, R); status = GR_SUCCESS; status |= gr_randtest(a, state, R); status |= gr_randtest(b, state, R); status |= gr_randtest(x, state, R); status |= gr_randtest(y, state, R); aliasing = n_randint(state, 3); if (aliasing == 0) { status |= gr_lcm(x, a, b, R); } else if (aliasing == 1) { status |= gr_set(x, a, R); status |= gr_lcm(x, x, b, R); } else if (aliasing == 2) { status |= gr_set(x, b, R); status |= gr_lcm(x, a, x, R); } status |= gr_gcd(y, a, b, R); status |= gr_mul(ab, a, b, R); status |= gr_mul(xy, x, y, R); if (status == GR_SUCCESS) { if (gr_divides(xy, ab, R) == T_FALSE || gr_divides(ab, xy, R) == T_FALSE) { status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("lcm\n"); gr_ctx_println(R); flint_printf("aliasing = %d\n", aliasing); flint_printf("a = "); gr_println(a, R); flint_printf("b = "); gr_println(b, R); flint_printf("x = "); gr_println(x, R); flint_printf("y = "); gr_println(y, R); flint_printf("ab = "); gr_println(ab, R); flint_printf("xy = "); gr_println(xy, R); flint_printf("\n"); } GR_TMP_CLEAR3(a, b, ab, R); GR_TMP_CLEAR3(x, y, xy, R); return status; } int gr_test_numerator_denominator(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr a, p, q, aq; GR_TMP_INIT4(a, p, q, aq, R); status = GR_SUCCESS; status |= gr_randtest(a, state, R); status |= gr_randtest(p, state, R); status |= gr_randtest(q, state, R); status |= gr_numerator(p, a, R); status |= gr_denominator(q, a, R); if (status == GR_SUCCESS) { status |= gr_mul(aq, a, q, R); if (status == GR_SUCCESS && gr_equal(aq, p, R) == T_FALSE) { status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("numerator_denominator\n"); gr_ctx_println(R); flint_printf("a = "); gr_println(a, R); flint_printf("p = "); gr_println(p, R); flint_printf("q = "); gr_println(q, R); flint_printf("aq = "); gr_println(aq, R); flint_printf("\n"); } GR_TMP_CLEAR4(a, p, q, aq, R); return status; } int gr_test_factor(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_ptr x, c, t, u; gr_ctx_t ZZ; gr_vec_t fac, exp; slong i; GR_TMP_INIT4(x, c, t, u, R); gr_ctx_init_fmpz(ZZ); gr_vec_init(fac, n_randint(state, 3), R); gr_vec_init(exp, n_randint(state, 3), ZZ); status = GR_SUCCESS; status |= gr_randtest_small(x, state, R); if (n_randint(state, 2)) { status |= gr_randtest_small(t, state, R); status |= gr_mul(x, x, t, R); } status |= gr_factor(c, fac, exp, x, 0, R); if (status == GR_SUCCESS) { if (fac->length != exp->length) { status = GR_TEST_FAIL; } else { status |= gr_set(u, c, R); for (i = 0; i < fac->length; i++) { status |= gr_pow_fmpz(t, gr_vec_entry_srcptr(fac, i, R), gr_vec_entry_srcptr(exp, i, ZZ), R); status |= gr_mul(u, u, t, R); } if (status == GR_SUCCESS && gr_equal(x, u, R) == T_FALSE) { status = GR_TEST_FAIL; } } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("factor\n"); flint_printf("x = "); gr_println(x, R); flint_printf("c = "); gr_println(c, R); flint_printf("fac = "); gr_vec_print(fac, R); flint_printf("\n"); flint_printf("exp = "); gr_vec_print(exp, ZZ); flint_printf("\n"); flint_printf("\n"); } } GR_TMP_CLEAR4(x, c, t, u, R); gr_ctx_clear(ZZ); gr_vec_clear(fac, R); gr_vec_clear(exp, ZZ); return status; } int gr_test_vec_binary_op(gr_ctx_t R, const char * opname, int (*gr_op)(gr_ptr, gr_srcptr, gr_srcptr, gr_ctx_t), int (*_gr_vec_op)(gr_ptr, gr_srcptr, gr_srcptr, slong, gr_ctx_t), flint_rand_t state, int test_flags) { int status, aliasing; slong i, len; gr_ptr x, y, xy1, xy2; len = n_randint(state, 5); GR_TMP_INIT_VEC(x, len, R); GR_TMP_INIT_VEC(y, len, R); GR_TMP_INIT_VEC(xy1, len, R); GR_TMP_INIT_VEC(xy2, len, R); GR_MUST_SUCCEED(_gr_vec_randtest(x, state, len, R)); GR_MUST_SUCCEED(_gr_vec_randtest(y, state, len, R)); GR_MUST_SUCCEED(_gr_vec_randtest(xy1, state, len, R)); GR_MUST_SUCCEED(_gr_vec_randtest(xy2, state, len, R)); status = GR_SUCCESS; aliasing = n_randint(state, 4); switch (aliasing) { case 0: status |= _gr_vec_set(xy1, x, len, R); status |= _gr_vec_op(xy1, xy1, y, len, R); break; case 1: status |= _gr_vec_set(xy1, y, len, R); status |= _gr_vec_op(xy1, x, xy1, len, R); break; case 2: status |= _gr_vec_set(y, x, len, R); status |= _gr_vec_set(xy1, x, len, R); status |= _gr_vec_op(xy1, xy1, xy1, len, R); break; default: status |= _gr_vec_op(xy1, x, y, len, R); } for (i = 0; i < len; i++) status |= gr_op(GR_ENTRY(xy2, i, R->sizeof_elem), GR_ENTRY(x, i, R->sizeof_elem), GR_ENTRY(y, i, R->sizeof_elem), R); if (status == GR_SUCCESS && _gr_vec_equal(xy1, xy2, len, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("%s\n", opname); gr_ctx_println(R); flint_printf("aliasing: %d\n", aliasing); _gr_vec_print(xy1, len, R); flint_printf("\n"); _gr_vec_print(xy2, len, R); flint_printf("\n"); } GR_TMP_CLEAR_VEC(x, len, R); GR_TMP_CLEAR_VEC(y, len, R); GR_TMP_CLEAR_VEC(xy1, len, R); GR_TMP_CLEAR_VEC(xy2, len, R); return status; } int gr_test_vec_add(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_vec_binary_op(R, "vec_add", gr_add, _gr_vec_add, state, test_flags); } int gr_test_vec_sub(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_vec_binary_op(R, "vec_sub", gr_sub, _gr_vec_sub, state, test_flags); } int gr_test_vec_mul(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_vec_binary_op(R, "vec_mul", gr_mul, _gr_vec_mul, state, test_flags); } int gr_test_vec_div(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_vec_binary_op(R, "vec_div", gr_div, _gr_vec_div, state, test_flags); } int gr_test_vec_divexact(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_vec_binary_op(R, "vec_divexact", gr_divexact, _gr_vec_divexact, state, test_flags); } int gr_test_vec_pow(gr_ctx_t R, flint_rand_t state, int test_flags) { return gr_test_vec_binary_op(R, "vec_pow", gr_pow, _gr_vec_pow, state, test_flags); } int gr_generic_vec_dot(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx); int gr_test_vec_dot(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; slong len; gr_ptr x, y, a, s, t; int initial, alias, subtract, reverse; len = n_randint(state, 5); initial = n_randint(state, 2); alias = n_randint(state, 2); subtract = n_randint(state, 2); reverse = n_randint(state, 2); GR_TMP_INIT_VEC(x, len, R); GR_TMP_INIT_VEC(y, len, R); GR_TMP_INIT3(a, s, t, R); GR_MUST_SUCCEED(_gr_vec_randtest(x, state, len, R)); GR_MUST_SUCCEED(_gr_vec_randtest(y, state, len, R)); GR_MUST_SUCCEED(gr_randtest(a, state, R)); GR_MUST_SUCCEED(gr_randtest(s, state, R)); GR_MUST_SUCCEED(gr_randtest(t, state, R)); status = GR_SUCCESS; if (initial && alias) { GR_MUST_SUCCEED(gr_set(s, a, R)); GR_MUST_SUCCEED(gr_set(t, a, R)); } if (reverse) { status |= _gr_vec_dot_rev(s, initial ? (alias ? s : a) : NULL, subtract, x, y, len, R); status |= _gr_poly_reverse(y, y, len, len, R); status |= gr_generic_vec_dot(t, initial ? (alias ? t : a) : NULL, subtract, x, y, len, R); status |= _gr_poly_reverse(y, y, len, len, R); } else { status |= _gr_vec_dot(s, initial ? (alias ? s : a) : NULL, subtract, x, y, len, R); status |= gr_generic_vec_dot(t, initial ? (alias ? t : a) : NULL, subtract, x, y, len, R); } if (status == GR_SUCCESS && gr_equal(s, t, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("dot\n"); gr_ctx_println(R); flint_printf("alias: %d\n", alias); flint_printf("initial: %d\n", initial); flint_printf("subtract: %d\n", subtract); flint_printf("reverse: %d\n", reverse); _gr_vec_print(x, len, R); flint_printf("\n"); _gr_vec_print(y, len, R); flint_printf("\n"); gr_println(a, R); gr_println(s, R); gr_println(t, R); } GR_TMP_CLEAR_VEC(x, len, R); GR_TMP_CLEAR_VEC(y, len, R); GR_TMP_CLEAR3(a, s, t, R); return status; } /* (AB)C = A(BC) */ int gr_test_mat_mul_classical_associative(gr_ctx_t R, flint_rand_t state, int test_flags) { int status; gr_mat_t A, B, C, AB, BC, AB_C, A_BC; slong m, n, p, q; if (gr_ctx_is_finite(R) == T_TRUE) { m = n_randint(state, 5); n = n_randint(state, 5); p = n_randint(state, 5); q = n_randint(state, 5); } else { m = n_randint(state, 3); n = n_randint(state, 3); p = n_randint(state, 3); q = n_randint(state, 3); } gr_mat_init(A, m, n, R); gr_mat_init(B, n, p, R); gr_mat_init(C, p, q, R); gr_mat_init(AB, m, p, R); gr_mat_init(BC, n, q, R); gr_mat_init(AB_C, m, q, R); gr_mat_init(A_BC, m, q, R); GR_MUST_SUCCEED(gr_mat_randtest(A, state, R)); GR_MUST_SUCCEED(gr_mat_randtest(B, state, R)); GR_MUST_SUCCEED(gr_mat_randtest(C, state, R)); GR_MUST_SUCCEED(gr_mat_randtest(AB, state, R)); GR_MUST_SUCCEED(gr_mat_randtest(BC, state, R)); GR_MUST_SUCCEED(gr_mat_randtest(AB_C, state, R)); GR_MUST_SUCCEED(gr_mat_randtest(A_BC, state, R)); status = GR_SUCCESS; status |= gr_mat_mul_classical(AB, A, B, R); status |= gr_mat_mul_classical(BC, B, C, R); status |= gr_mat_mul_classical(AB_C, AB, C, R); status |= gr_mat_mul_classical(A_BC, A, BC, R); if (status == GR_SUCCESS && gr_mat_equal(AB_C, A_BC, R) == T_FALSE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { /* todo: vec print */ flint_printf("\n"); flint_printf("A = \n"); gr_mat_print(A, R); flint_printf("\n"); flint_printf("B = \n"); gr_mat_print(B, R); flint_printf("\n"); flint_printf("C = \n"); gr_mat_print(C, R); flint_printf("\n"); flint_printf("AB = \n"); gr_mat_print(AB, R); flint_printf("\n"); flint_printf("BC = \n"); gr_mat_print(BC, R); flint_printf("\n"); flint_printf("AB * C = \n"); gr_mat_print(AB_C, R); flint_printf("\n"); flint_printf("A * BC = \n"); gr_mat_print(A_BC, R); flint_printf("\n"); flint_printf("\n"); } gr_mat_clear(A, R); gr_mat_clear(B, R); gr_mat_clear(C, R); gr_mat_clear(AB, R); gr_mat_clear(BC, R); gr_mat_clear(A_BC, R); gr_mat_clear(AB_C, R); return status; } int gr_test_integral_domain(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y, z; GR_TMP_INIT3(x, y, z, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); GR_MUST_SUCCEED(gr_randtest(y, state, R)); status |= gr_mul(z, x, y, R); if (status == GR_SUCCESS && gr_is_zero(x, R) == T_FALSE && gr_is_zero(y, R) == T_FALSE && gr_is_zero(z, R) == T_TRUE) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_ALWAYS_ABLE) && (status & GR_UNABLE)) status = GR_TEST_FAIL; if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("z = \n"); gr_println(z, R); flint_printf("\n"); } if (gr_ctx_is_commutative_ring(R) == T_FALSE) { flint_printf("integral domain is not a commutative ring\n"); flint_printf("\n"); status = GR_TEST_FAIL; } GR_TMP_CLEAR3(x, y, z, R); return status; } int gr_test_field(gr_ctx_t R, flint_rand_t state, int test_flags) { int status = GR_SUCCESS; gr_ptr x, y, z; GR_TMP_INIT3(x, y, z, R); GR_MUST_SUCCEED(gr_randtest(x, state, R)); if (gr_is_zero(x, R) == T_FALSE) { if (gr_is_invertible(x, R) == T_FALSE) { status = GR_TEST_FAIL; } if (gr_inv(y, x, R) == GR_DOMAIN) { status = GR_TEST_FAIL; } if (gr_div(z, y, x, R) == GR_DOMAIN) { status = GR_TEST_FAIL; } if ((test_flags & GR_TEST_VERBOSE) || status == GR_TEST_FAIL) { flint_printf("\n"); flint_printf("x = \n"); gr_println(x, R); flint_printf("y = \n"); gr_println(y, R); flint_printf("z = \n"); gr_println(z, R); flint_printf("\n"); } } if (gr_ctx_is_commutative_ring(R) == T_FALSE) { flint_printf("field is not a commutative ring\n"); flint_printf("\n"); status = GR_TEST_FAIL; } if (gr_ctx_is_integral_domain(R) == T_FALSE) { flint_printf("field is not an integral domain\n"); flint_printf("\n"); status = GR_TEST_FAIL; } GR_TMP_CLEAR3(x, y, z, R); return status; } void gr_test_iter(gr_ctx_t R, flint_rand_t state, const char * descr, gr_test_function func, slong iters, int test_flags) { slong iter, count_success, count_unable, count_domain; int status; timeit_t timer; count_success = 0; count_unable = 0; count_domain = 0; if (test_flags & GR_TEST_VERBOSE) { flint_printf("%s ... ", descr); fflush(stdout); } timeit_start(timer); for (iter = 0; iter < iters; iter++) { /* flint_printf("iter %ld\n", iter); */ status = func(R, state, test_flags & ~GR_TEST_VERBOSE); if (status == GR_SUCCESS) count_success++; if (status & GR_UNABLE) count_unable++; if (status & GR_DOMAIN) count_domain++; if (status & GR_TEST_FAIL) { flint_throw(FLINT_ERROR, "\nFAIL\n"); } } timeit_stop(timer); if (test_flags & GR_TEST_VERBOSE) { flint_printf("PASS (%wd successful, %wd domain, %wd unable, 0 wrong, %.3g cpu, %.3g wall)\n", count_success, count_domain, count_unable, timer->cpu*0.001, timer->wall*0.001); } } void gr_test_ring(gr_ctx_t R, slong iters, int test_flags) { timeit_t timer; flint_rand_t state; slong vec_iters = iters / 10 + 1; /* test_flags |= GR_TEST_VERBOSE; */ if (test_flags & GR_TEST_VERBOSE) { timeit_start(timer); flint_printf("===============================================================================\n"); flint_printf("Testing "); gr_ctx_println(R); flint_printf("-------------------------------------------------------------------------------\n"); } flint_randinit(state); /* if (gr_ctx_is_ring(R) != T_TRUE) flint_abort(); */ gr_test_iter(R, state, "ctx_get_str", gr_test_ctx_get_str, 1, test_flags); gr_test_iter(R, state, "init/clear", gr_test_init_clear, iters, test_flags); gr_test_iter(R, state, "equal", gr_test_equal, iters, test_flags); gr_test_iter(R, state, "swap", gr_test_swap, iters, test_flags); gr_test_iter(R, state, "zero_one", gr_test_zero_one, iters, test_flags); gr_test_iter(R, state, "randtest_not_zero", gr_test_randtest_not_zero, iters, test_flags); gr_test_iter(R, state, "neg", gr_test_neg, iters, test_flags); gr_test_iter(R, state, "set_ui", gr_test_set_ui, iters, test_flags); gr_test_iter(R, state, "set_si", gr_test_set_si, iters, test_flags); gr_test_iter(R, state, "set_fmpz", gr_test_set_fmpz, iters, test_flags); gr_test_iter(R, state, "set_fmpq", gr_test_set_fmpq, iters, test_flags); gr_test_iter(R, state, "set_other", gr_test_set_other, iters, test_flags); gr_test_iter(R, state, "get_ui", gr_test_get_ui, iters, test_flags); gr_test_iter(R, state, "get_si", gr_test_get_si, iters, test_flags); gr_test_iter(R, state, "get_fmpz", gr_test_get_fmpz, iters, test_flags); gr_test_iter(R, state, "get_fmpq", gr_test_get_fmpq, iters, test_flags); gr_test_iter(R, state, "get_fmpz_2exp_fmpz", gr_test_get_fmpz_2exp_fmpz, iters, test_flags); gr_test_iter(R, state, "get_set_fexpr", gr_test_get_set_fexpr, iters, test_flags); gr_test_iter(R, state, "get_set_str", gr_test_get_set_str, iters, test_flags); gr_test_iter(R, state, "add: associative", gr_test_add_associative, iters, test_flags); gr_test_iter(R, state, "add: commutative", gr_test_add_commutative, iters, test_flags); gr_test_iter(R, state, "add: aliasing", gr_test_add_aliasing, iters, test_flags); gr_test_iter(R, state, "sub: equal neg add", gr_test_sub_equal_neg_add, iters, test_flags); gr_test_iter(R, state, "sub: aliasing", gr_test_sub_aliasing, iters, test_flags); gr_test_iter(R, state, "add: ui/si/fmpz/fmpq", gr_test_add_type_variants, iters, test_flags); gr_test_iter(R, state, "sub: ui/si/fmpz/fmpq", gr_test_sub_type_variants, iters, test_flags); gr_test_iter(R, state, "mul: ui/si/fmpz/fmpq", gr_test_mul_type_variants, iters, test_flags); gr_test_iter(R, state, "div: ui/si/fmpz/fmpq", gr_test_div_type_variants, iters, test_flags); gr_test_iter(R, state, "mul: associative", gr_test_mul_associative, iters, test_flags); if (gr_ctx_is_commutative_ring(R) == T_TRUE) gr_test_iter(R, state, "mul: commutative", gr_test_mul_commutative, iters, test_flags); gr_test_iter(R, state, "mul: aliasing", gr_test_mul_aliasing, iters, test_flags); gr_test_iter(R, state, "mul: left distributive", gr_test_mul_left_distributive, iters, test_flags); gr_test_iter(R, state, "mul: right distributive", gr_test_mul_right_distributive, iters, test_flags); gr_test_iter(R, state, "mul_2exp_si", gr_test_mul_2exp_si, iters, test_flags); gr_test_iter(R, state, "mul_2exp_fmpz", gr_test_mul_2exp_fmpz, iters, test_flags); gr_test_iter(R, state, "addmul/submul", gr_test_addmul_submul, iters, test_flags); gr_test_iter(R, state, "addmul: ui/si/fmpz/fmpq", gr_test_addmul_type_variants, iters, test_flags); gr_test_iter(R, state, "submul: ui/si/fmpz/fmpq", gr_test_submul_type_variants, iters, test_flags); if (gr_ctx_is_integral_domain(R) == T_TRUE) gr_test_iter(R, state, "integral_domain", gr_test_integral_domain, iters, test_flags); if (gr_ctx_is_field(R) == T_TRUE) gr_test_iter(R, state, "field", gr_test_integral_domain, iters, test_flags); if (gr_ctx_is_integral_domain(R) == T_TRUE) gr_test_iter(R, state, "div: distributive", gr_test_div_right_distributive, iters, test_flags); gr_test_iter(R, state, "div: aliasing", gr_test_div_aliasing, iters, test_flags); gr_test_iter(R, state, "div: div then mul", gr_test_div_then_mul, iters, test_flags); gr_test_iter(R, state, "div: mul then div", gr_test_mul_then_div, iters, test_flags); gr_test_iter(R, state, "div_nonunique", gr_test_div_nonunique, iters, test_flags); gr_test_iter(R, state, "div_nonunique: aliasing", gr_test_div_nonunique_aliasing, iters, test_flags); gr_test_iter(R, state, "divides", gr_test_divides, iters, test_flags); gr_test_iter(R, state, "inv: multiplication", gr_test_inv_multiplication, iters, test_flags); gr_test_iter(R, state, "inv: involution", gr_test_inv_involution, iters, test_flags); gr_test_iter(R, state, "is_invertible", gr_test_is_invertible, iters, test_flags); gr_test_iter(R, state, "divexact", gr_test_divexact, iters, test_flags); gr_test_iter(R, state, "divexact: ui/si/fmpz", gr_test_divexact_type_variants, iters, test_flags); gr_test_iter(R, state, "pow_ui: exponent addition", gr_test_pow_ui_exponent_addition, iters, test_flags); gr_test_iter(R, state, "pow_ui: base scalar multiplication", gr_test_pow_ui_base_scalar_multiplication, iters, test_flags); if (gr_ctx_is_commutative_ring(R) == T_TRUE) gr_test_iter(R, state, "pow_ui: base multiplication", gr_test_pow_ui_base_multiplication, iters, test_flags); gr_test_iter(R, state, "pow_ui: aliasing", gr_test_pow_ui_exponent_addition, iters, test_flags); gr_test_iter(R, state, "pow_fmpz: exponent addition", gr_test_pow_fmpz_exponent_addition, iters, test_flags); gr_test_iter(R, state, "sqrt", gr_test_sqrt, iters, test_flags & (~GR_TEST_ALWAYS_ABLE)); gr_test_iter(R, state, "rsqrt", gr_test_rsqrt, iters, test_flags & (~GR_TEST_ALWAYS_ABLE)); gr_test_iter(R, state, "pow: aliasing", gr_test_pow_aliasing, iters, test_flags & (~GR_TEST_ALWAYS_ABLE)); gr_test_iter(R, state, "pow: exponent addition", gr_test_pow_exponent_addition, iters, test_flags & (~GR_TEST_ALWAYS_ABLE)); gr_test_iter(R, state, "pow: ui/si/fmpz/fmpq", gr_test_pow_type_variants, iters, test_flags & (~GR_TEST_ALWAYS_ABLE)); if (gr_ctx_is_ordered_ring(R) == T_TRUE) { gr_test_iter(R, state, "ordered_ring_cmp", gr_test_ordered_ring_cmp, iters, test_flags); gr_test_iter(R, state, "ordered_ring_cmpabs", gr_test_ordered_ring_cmpabs, iters, test_flags); } gr_test_iter(R, state, "numerator_denominator", gr_test_numerator_denominator, iters, test_flags); gr_test_iter(R, state, "complex_parts", gr_test_complex_parts, iters, test_flags); if (gr_ctx_is_unique_factorization_domain(R) == T_TRUE) { gr_test_iter(R, state, "gcd", gr_test_gcd, iters, test_flags); gr_test_iter(R, state, "lcm", gr_test_lcm, iters, test_flags); gr_test_iter(R, state, "factor", gr_test_factor, iters, test_flags); } gr_test_iter(R, state, "vec_add", gr_test_vec_add, vec_iters, test_flags); gr_test_iter(R, state, "vec_sub", gr_test_vec_sub, vec_iters, test_flags); gr_test_iter(R, state, "vec_mul", gr_test_vec_mul, vec_iters, test_flags); gr_test_iter(R, state, "vec_div", gr_test_vec_div, vec_iters, test_flags); gr_test_iter(R, state, "vec_divexact", gr_test_vec_divexact, vec_iters, test_flags); /* gr_test_iter(R, state, "vec_pow", gr_test_vec_pow, vec_iters, test_flags & (~GR_TEST_ALWAYS_ABLE)); large elements */ gr_test_iter(R, state, "vec_dot", gr_test_vec_dot, iters, test_flags); gr_test_iter(R, state, "mat_mul_classical: associative", gr_test_mat_mul_classical_associative, iters, test_flags); flint_randclear(state); if (test_flags & GR_TEST_VERBOSE) { timeit_stop(timer); flint_printf("-------------------------------------------------------------------------------\n"); flint_printf("Tests finished in %.3g cpu, %.3g wall\n", timer->cpu*0.001, timer->wall*0.001); flint_printf("===============================================================================\n\n"); } } void gr_test_multiplicative_group(gr_ctx_t R, slong iters, int test_flags) { timeit_t timer; flint_rand_t state; /* test_flags |= GR_TEST_VERBOSE; */ if (test_flags & GR_TEST_VERBOSE) { timeit_start(timer); flint_printf("===============================================================================\n"); flint_printf("Testing "); gr_ctx_println(R); flint_printf("-------------------------------------------------------------------------------\n"); } flint_randinit(state); /* if (gr_ctx_is_multiplicative_group(R) != T_TRUE) flint_abort(); */ gr_test_iter(R, state, "ctx_get_str", gr_test_ctx_get_str, 1, test_flags); gr_test_iter(R, state, "init/clear", gr_test_init_clear, iters, test_flags); gr_test_iter(R, state, "swap", gr_test_swap, iters, test_flags); gr_test_iter(R, state, "get_set_fexpr", gr_test_get_set_fexpr, iters, test_flags); gr_test_iter(R, state, "get_set_str", gr_test_get_set_str, iters, test_flags); gr_test_iter(R, state, "one", gr_test_one, iters, test_flags); gr_test_iter(R, state, "mul: associative", gr_test_mul_associative, iters, test_flags); /* if (gr_ctx_is_abelian_group(R) == T_TRUE) gr_test_iter(R, state, "mul: commutative", gr_test_mul_commutative, iters, test_flags); */ gr_test_iter(R, state, "mul: aliasing", gr_test_mul_aliasing, iters, test_flags); gr_test_iter(R, state, "div: div then mul", gr_test_div_then_mul, iters, test_flags); gr_test_iter(R, state, "div: mul then div", gr_test_mul_then_div, iters, test_flags); gr_test_iter(R, state, "inv: multiplication", gr_test_inv_multiplication, iters, test_flags); gr_test_iter(R, state, "inv: involution", gr_test_inv_involution, iters, test_flags); gr_test_iter(R, state, "pow_ui: exponent addition", gr_test_pow_ui_exponent_addition, iters, test_flags); gr_test_iter(R, state, "pow_ui: aliasing", gr_test_pow_ui_exponent_addition, iters, test_flags); gr_test_iter(R, state, "pow_fmpz: exponent addition", gr_test_pow_fmpz_exponent_addition, iters, test_flags); gr_test_iter(R, state, "get_set_fexpr", gr_test_get_set_fexpr, iters, test_flags); flint_randclear(state); if (test_flags & GR_TEST_VERBOSE) { timeit_stop(timer); flint_printf("-------------------------------------------------------------------------------\n"); flint_printf("Tests finished in %.3g cpu, %.3g wall\n", timer->cpu*0.001, timer->wall*0.001); flint_printf("===============================================================================\n\n"); } } flint-3.1.3/src/gr/vector.c000066400000000000000000000560611461254215100155100ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Vectors over generic rings */ #include "ulong_extras.h" #include "fmpz.h" #include "gr.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_special.h" #define ENTRY_CTX(ctx) (VECTOR_CTX(ctx)->base_ring) int _gr_vec_check_resize(gr_vec_t res, slong n, gr_ctx_t ctx) { if (VECTOR_CTX(ctx)->all_sizes) { gr_vec_set_length(res, n, ENTRY_CTX(ctx)); return GR_SUCCESS; } else { if (n != VECTOR_CTX(ctx)->n) return GR_DOMAIN; gr_vec_set_length(res, n, ENTRY_CTX(ctx)); return GR_SUCCESS; } } void vector_gr_vec_init(gr_vec_t res, gr_ctx_t ctx) { gr_vec_init(res, VECTOR_CTX(ctx)->n, ENTRY_CTX(ctx)); } int vector_gr_vec_ctx_write(gr_stream_t out, gr_ctx_t ctx) { gr_ctx_ptr elem_ctx = ENTRY_CTX(ctx); if (VECTOR_CTX(ctx)->all_sizes) { gr_stream_write(out, "Vectors (any length) over "); } else { gr_stream_write(out, "Space of length "); gr_stream_write_si(out, VECTOR_CTX(ctx)->n); gr_stream_write(out, " vectors over "); } gr_ctx_write(out, elem_ctx); return GR_SUCCESS; } truth_t vector_ctx_is_ring(gr_ctx_t ctx) { if (VECTOR_CTX(ctx)->all_sizes) return T_FALSE; if (VECTOR_CTX(ctx)->n == 0) return T_TRUE; return gr_ctx_is_ring(ENTRY_CTX(ctx)); } truth_t vector_ctx_is_commutative_ring(gr_ctx_t ctx) { if (VECTOR_CTX(ctx)->all_sizes) return T_FALSE; if (VECTOR_CTX(ctx)->n == 0) return T_TRUE; return gr_ctx_is_commutative_ring(ENTRY_CTX(ctx)); } /* todo: public */ truth_t gr_ctx_vector_gr_vec_is_fixed_size(gr_ctx_t ctx) { return (VECTOR_CTX(ctx)->all_sizes) ? T_FALSE : T_TRUE; } truth_t vector_ctx_is_threadsafe(gr_ctx_t ctx) { return gr_ctx_is_threadsafe(ENTRY_CTX(ctx)); } void vector_gr_vec_clear(gr_vec_t res, gr_ctx_t ctx) { gr_vec_clear(res, ENTRY_CTX(ctx)); } void vector_gr_vec_swap(gr_vec_t vec1, gr_vec_t vec2, gr_ctx_t ctx) { gr_poly_swap((gr_poly_struct *) vec1, (gr_poly_struct *) vec2, ENTRY_CTX(ctx)); } int vector_gr_vec_write(gr_stream_t out, gr_vec_t vec, gr_ctx_t ctx) { return gr_vec_write(out, vec, ENTRY_CTX(ctx)); } int vector_gr_vec_randtest(gr_vec_t res, flint_rand_t state, gr_ctx_t ctx) { slong i, n; int status; if (VECTOR_CTX(ctx)->all_sizes) { n = n_randint(state, 7); gr_vec_set_length(res, n, ENTRY_CTX(ctx)); } else n = res->length; status = GR_SUCCESS; for (i = 0; i < n; i++) status |= gr_randtest(gr_vec_entry_ptr(res, i, ENTRY_CTX(ctx)), state, ENTRY_CTX(ctx)); return status; } truth_t gr_generic_vec_equal(gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx); truth_t vector_gr_vec_equal(const gr_vec_t vec1, const gr_vec_t vec2, gr_ctx_t ctx) { slong len1, len2; len1 = vec1->length; len2 = vec2->length; if (len1 != len2) return T_FALSE; return _gr_vec_equal(vec1->entries, vec2->entries, len1, ENTRY_CTX(ctx)); } int vector_gr_vec_set(gr_vec_t res, const gr_vec_t vec, gr_ctx_t ctx) { return gr_vec_set(res, vec, ENTRY_CTX(ctx)); } /* todo: move out */ static int _gr_vec_set_ui(gr_ptr res, slong len, ulong x, gr_ctx_t ctx) { gr_method_unary_op_ui f = GR_UNARY_OP_UI(ctx, SET_UI); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= f(GR_ENTRY(res, i, sz), x, ctx); return status; } static int _gr_vec_set_si(gr_ptr res, slong len, slong x, gr_ctx_t ctx) { gr_method_unary_op_si f = GR_UNARY_OP_SI(ctx, SET_SI); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= f(GR_ENTRY(res, i, sz), x, ctx); return status; } static int _gr_vec_set_fmpz(gr_ptr res, slong len, const fmpz_t x, gr_ctx_t ctx) { gr_method_unary_op_fmpz f = GR_UNARY_OP_FMPZ(ctx, SET_FMPZ); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= f(GR_ENTRY(res, i, sz), x, ctx); return status; } static int _gr_vec_set_fmpq(gr_ptr res, slong len, const fmpq_t x, gr_ctx_t ctx) { gr_method_unary_op_fmpq f = GR_UNARY_OP_FMPQ(ctx, SET_FMPQ); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= f(GR_ENTRY(res, i, sz), x, ctx); return status; } static int _gr_vec_set_d(gr_ptr res, slong len, double x, gr_ctx_t ctx) { gr_method_unary_op_d f = GR_UNARY_OP_D(ctx, SET_D); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= f(GR_ENTRY(res, i, sz), x, ctx); return status; } int vector_gr_vec_set_ui(gr_vec_t res, ulong x, gr_ctx_t ctx) { slong len = VECTOR_CTX(ctx)->n; if (VECTOR_CTX(ctx)->all_sizes) return GR_DOMAIN; /* should not be needed; just a precaution (might want an assert) */ if (res->length != len) gr_vec_set_length(res, len, ENTRY_CTX(ctx)); return _gr_vec_set_ui(res->entries, len, x, ENTRY_CTX(ctx)); } int vector_gr_vec_set_si(gr_vec_t res, slong x, gr_ctx_t ctx) { slong len = VECTOR_CTX(ctx)->n; if (VECTOR_CTX(ctx)->all_sizes) return GR_DOMAIN; /* should not be needed; just a precaution (might want an assert) */ if (res->length != len) gr_vec_set_length(res, len, ENTRY_CTX(ctx)); return _gr_vec_set_si(res->entries, len, x, ENTRY_CTX(ctx)); } int vector_gr_vec_set_fmpz(gr_vec_t res, const fmpz_t x, gr_ctx_t ctx) { slong len = VECTOR_CTX(ctx)->n; if (VECTOR_CTX(ctx)->all_sizes) return GR_DOMAIN; /* should not be needed; just a precaution (might want an assert) */ if (res->length != len) gr_vec_set_length(res, len, ENTRY_CTX(ctx)); return _gr_vec_set_fmpz(res->entries, len, x, ENTRY_CTX(ctx)); } int vector_gr_vec_set_fmpq(gr_vec_t res, const fmpq_t x, gr_ctx_t ctx) { slong len = VECTOR_CTX(ctx)->n; if (VECTOR_CTX(ctx)->all_sizes) return GR_DOMAIN; /* should not be needed; just a precaution (might want an assert) */ if (res->length != len) gr_vec_set_length(res, len, ENTRY_CTX(ctx)); return _gr_vec_set_fmpq(res->entries, len, x, ENTRY_CTX(ctx)); } int vector_gr_vec_set_d(gr_vec_t res, double x, gr_ctx_t ctx) { slong len = VECTOR_CTX(ctx)->n; if (VECTOR_CTX(ctx)->all_sizes) return GR_DOMAIN; /* should not be needed; just a precaution (might want an assert) */ if (res->length != len) gr_vec_set_length(res, len, ENTRY_CTX(ctx)); return _gr_vec_set_d(res->entries, len, x, ENTRY_CTX(ctx)); } /* todo: convert from matrices, ...? */ int vector_gr_vec_set_other(gr_vec_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { if (x_ctx == ctx) { return vector_gr_vec_set(res, x, ctx); } else if (x_ctx->which_ring == GR_CTX_GR_VEC) { const gr_vec_struct * xvec = x; slong i; int status = GR_SUCCESS; slong sz, xsz; if (res->length != xvec->length) { if (VECTOR_CTX(ctx)->all_sizes) gr_vec_set_length(res, xvec->length, ENTRY_CTX(ctx)); else return GR_DOMAIN; } sz = ENTRY_CTX(ctx)->sizeof_elem; xsz = ENTRY_CTX(x_ctx)->sizeof_elem; for (i = 0; i < res->length; i++) { status = gr_set_other(GR_ENTRY(res->entries, i, sz), GR_ENTRY(xvec->entries, i, xsz), ENTRY_CTX(x_ctx), ENTRY_CTX(ctx)); if (status != GR_SUCCESS) return status; } return GR_SUCCESS; } return GR_UNABLE; } int vector_gr_vec_neg(gr_vec_t res, const gr_vec_t src, gr_ctx_t ctx) { return gr_poly_neg((gr_poly_struct *) res, (gr_poly_struct *) src, ENTRY_CTX(ctx)); } int vector_gr_vec_zero(gr_vec_t res, gr_ctx_t ctx) \ { slong xlen = VECTOR_CTX(ctx)->n; \ if (VECTOR_CTX(ctx)->all_sizes) \ return GR_DOMAIN; /* should not be needed; just a precaution (might want an assert) */ if (res->length != xlen) gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); return _gr_vec_zero(res->entries, xlen, ENTRY_CTX(ctx)); } static int _gr_vec_apply_const(gr_ptr res, gr_method_constant_op f, slong len, gr_ctx_t ctx) { int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= f(GR_ENTRY(res, i, sz), ctx); return status; } static truth_t _gr_vec_all_binary_predicate(gr_method_binary_predicate f, gr_srcptr x, gr_srcptr y, slong len, gr_ctx_t ctx) { truth_t res, res1; slong i, sz; sz = ctx->sizeof_elem; res = T_TRUE; for (i = 0; i < len; i++) { res1 = f(GR_ENTRY(x, i, sz), GR_ENTRY(y, i, sz), ctx); if (res1 == T_FALSE) return T_FALSE; if (res1 == T_UNKNOWN) res = T_UNKNOWN; } return res; } truth_t vector_gr_vec_divides(const gr_vec_t x, const gr_vec_t y, gr_ctx_t ctx) { if (x->length != y->length) return T_FALSE; return _gr_vec_all_binary_predicate(GR_BINARY_PREDICATE(ENTRY_CTX(ctx), DIVIDES), x->entries, y->entries, x->length, ENTRY_CTX(ctx)); } #define DEF_CONSTANT_OP_FROM_OP(op, OP) \ int \ vector_gr_vec_ ## op(gr_vec_t res, gr_ctx_t ctx) \ { \ slong xlen = VECTOR_CTX(ctx)->n; \ \ if (VECTOR_CTX(ctx)->all_sizes) \ return GR_DOMAIN;\ \ gr_method_constant_op f = GR_CONSTANT_OP(ENTRY_CTX(ctx), OP); \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_apply_const(res->entries, f, xlen, ENTRY_CTX(ctx)); \ } \ DEF_CONSTANT_OP_FROM_OP(one, ONE) DEF_CONSTANT_OP_FROM_OP(neg_one, NEG_ONE) DEF_CONSTANT_OP_FROM_OP(i, I) DEF_CONSTANT_OP_FROM_OP(pi, PI) static int _gr_vec_apply_unary(gr_ptr res, gr_method_unary_op f, gr_srcptr src, slong len, gr_ctx_t ctx) { int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= f(GR_ENTRY(res, i, sz), GR_ENTRY(src, i, sz), ctx); return status; } #define DEF_UNARY_OP_FROM_ENTRY_OP(op, OP) \ int \ vector_gr_vec_ ## op(gr_vec_t res, const gr_vec_t x, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ gr_method_unary_op f = GR_UNARY_OP(ENTRY_CTX(ctx), OP); \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_apply_unary(res->entries, f, x->entries, xlen, ENTRY_CTX(ctx)); \ } \ DEF_UNARY_OP_FROM_ENTRY_OP(inv, INV) DEF_UNARY_OP_FROM_ENTRY_OP(sqrt, SQRT) DEF_UNARY_OP_FROM_ENTRY_OP(rsqrt, RSQRT) DEF_UNARY_OP_FROM_ENTRY_OP(floor, FLOOR) DEF_UNARY_OP_FROM_ENTRY_OP(ceil, CEIL) DEF_UNARY_OP_FROM_ENTRY_OP(trunc, TRUNC) DEF_UNARY_OP_FROM_ENTRY_OP(nint, NINT) DEF_UNARY_OP_FROM_ENTRY_OP(abs, ABS) DEF_UNARY_OP_FROM_ENTRY_OP(conj, CONJ) DEF_UNARY_OP_FROM_ENTRY_OP(re, RE) DEF_UNARY_OP_FROM_ENTRY_OP(im, IM) DEF_UNARY_OP_FROM_ENTRY_OP(sgn, SGN) DEF_UNARY_OP_FROM_ENTRY_OP(csgn, CSGN) DEF_UNARY_OP_FROM_ENTRY_OP(exp, EXP) DEF_UNARY_OP_FROM_ENTRY_OP(log, LOG) #define DEF_BINARY_OP(op) \ int \ vector_gr_vec_ ## op(gr_vec_t res, const gr_vec_t x, const gr_vec_t y, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ \ if (xlen != y->length) \ return GR_DOMAIN; \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_## op(res->entries, x->entries, y->entries, xlen, ENTRY_CTX(ctx)); \ } \ \ int \ vector_gr_vec_ ## op ## _si(gr_vec_t res, const gr_vec_t x, slong c, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_ ## op ## _scalar_si(res->entries, x->entries, xlen, c, ENTRY_CTX(ctx)); \ } \ \ int \ vector_gr_vec_ ## op ## _ui(gr_vec_t res, const gr_vec_t x, ulong c, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_ ## op ## _scalar_ui(res->entries, x->entries, xlen, c, ENTRY_CTX(ctx)); \ } \ \ int \ vector_gr_vec_ ## op ## _fmpz(gr_vec_t res, const gr_vec_t x, const fmpz_t c, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_ ## op ## _scalar_fmpz(res->entries, x->entries, xlen, c, ENTRY_CTX(ctx)); \ } \ \ int \ vector_gr_vec_ ## op ## _fmpq(gr_vec_t res, const gr_vec_t x, const fmpq_t c, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_ ## op ## _scalar_fmpq(res->entries, x->entries, xlen, c, ENTRY_CTX(ctx)); \ } \ \ int \ vector_gr_vec_ ## op ## _other(gr_vec_t res, const gr_vec_t x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ \ if (y_ctx == ctx) \ { \ return vector_gr_vec_ ## op(res, x, y, ctx); \ } \ else if (y_ctx == ENTRY_CTX(ctx)) \ { \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, y_ctx); \ \ return _gr_vec_ ## op ## _scalar(res->entries, x->entries, xlen, y, y_ctx); \ } \ else if (y_ctx->which_ring == GR_CTX_GR_VEC) \ { \ const gr_vec_struct * yvec = y; \ gr_ctx_struct * entry_ctx = ENTRY_CTX(ctx); \ gr_ctx_struct * y_entry_ctx = ENTRY_CTX(y_ctx); \ \ if (xlen != yvec->length) \ return GR_DOMAIN; \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, entry_ctx); \ \ return _gr_vec_ ## op ## _other(res->entries, x->entries, yvec->entries, y_entry_ctx, xlen, entry_ctx); \ } \ else \ { \ gr_ctx_struct * entry_ctx = ENTRY_CTX(ctx); \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, entry_ctx); \ \ return _gr_vec_ ## op ## _scalar_other(res->entries, x->entries, xlen, y, y_ctx, entry_ctx); \ } \ } \ int \ vector_gr_vec_other_ ## op(gr_vec_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_vec_t y, gr_ctx_t ctx) \ { \ slong ylen = y->length; \ \ if (x_ctx == ctx) \ { \ return vector_gr_vec_ ## op(res, x, y, ctx); \ } \ else if (x_ctx == ENTRY_CTX(ctx)) \ { \ if (res->length != ylen) \ gr_vec_set_length(res, ylen, x_ctx); \ \ return _gr_scalar_ ## op ## _vec(res->entries, x, y->entries, ylen, x_ctx); \ } \ else if (x_ctx->which_ring == GR_CTX_GR_VEC) \ { \ const gr_vec_struct * xvec = x; \ gr_ctx_struct * entry_ctx = ENTRY_CTX(ctx); \ gr_ctx_struct * x_entry_ctx = ENTRY_CTX(x_ctx); \ \ if (ylen != xvec->length) \ return GR_DOMAIN; \ \ if (res->length != ylen) \ gr_vec_set_length(res, ylen, entry_ctx); \ \ return _gr_other_ ## op ## _vec(res->entries, xvec->entries, x_entry_ctx, y->entries, ylen, entry_ctx); \ } \ else \ { \ gr_ctx_struct * entry_ctx = ENTRY_CTX(ctx); \ \ if (res->length != ylen) \ gr_vec_set_length(res, ylen, entry_ctx); \ \ return _gr_scalar_other_ ## op ## _vec(res->entries, x, x_ctx, y->entries, ylen, entry_ctx); \ } \ } \ DEF_BINARY_OP(add) DEF_BINARY_OP(sub) DEF_BINARY_OP(mul) DEF_BINARY_OP(div) DEF_BINARY_OP(divexact) DEF_BINARY_OP(pow) #define DEF_BINARY_OP_NO_TYPE_VARIANTS(op) \ int \ vector_gr_vec_ ## op(gr_vec_t res, const gr_vec_t x, const gr_vec_t y, gr_ctx_t ctx) \ { \ slong xlen = x->length; \ \ if (xlen != y->length) \ return GR_DOMAIN; \ \ if (res->length != xlen) \ gr_vec_set_length(res, xlen, ENTRY_CTX(ctx)); \ \ return _gr_vec_## op(res->entries, x->entries, y->entries, xlen, ENTRY_CTX(ctx)); \ } \ int _gr_vec_div_nonunique(gr_ptr res, gr_srcptr x, gr_srcptr y, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i; for (i = 0; i < len; i++) status |= gr_div_nonunique(GR_ENTRY(res, i, sz), GR_ENTRY(x, i, sz), GR_ENTRY(y, i, sz), ctx); return status; } DEF_BINARY_OP_NO_TYPE_VARIANTS(div_nonunique) /* todo: all versions */ int gr_generic_mul_ui_via_ZZ(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { gr_ctx_t ZZ; fmpz_t t; int status; gr_ctx_init_fmpz(ZZ); /* no need to clear */ fmpz_init_set_ui(t, y); status = gr_mul_other(res, x, t, ZZ, ctx); fmpz_clear(t); return status; } int _gr_vec_methods_initialized = 0; gr_static_method_table _gr_vec_methods; gr_method_tab_input _gr_vec_methods_input[] = { {GR_METHOD_CTX_IS_RING, (gr_funcptr) vector_ctx_is_ring}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) vector_ctx_is_commutative_ring}, {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) vector_ctx_is_threadsafe}, {GR_METHOD_CTX_WRITE, (gr_funcptr) vector_gr_vec_ctx_write}, {GR_METHOD_INIT, (gr_funcptr) vector_gr_vec_init}, {GR_METHOD_CLEAR, (gr_funcptr) vector_gr_vec_clear}, {GR_METHOD_SWAP, (gr_funcptr) vector_gr_vec_swap}, {GR_METHOD_RANDTEST, (gr_funcptr) vector_gr_vec_randtest}, {GR_METHOD_WRITE, (gr_funcptr) vector_gr_vec_write}, {GR_METHOD_EQUAL, (gr_funcptr) vector_gr_vec_equal}, {GR_METHOD_SET, (gr_funcptr) vector_gr_vec_set}, {GR_METHOD_SET_OTHER, (gr_funcptr) vector_gr_vec_set_other}, {GR_METHOD_SET_UI, (gr_funcptr) vector_gr_vec_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) vector_gr_vec_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) vector_gr_vec_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) vector_gr_vec_set_fmpq}, {GR_METHOD_SET_D, (gr_funcptr) vector_gr_vec_set_d}, {GR_METHOD_ZERO, (gr_funcptr) vector_gr_vec_zero}, {GR_METHOD_ONE, (gr_funcptr) vector_gr_vec_one}, {GR_METHOD_NEG_ONE, (gr_funcptr) vector_gr_vec_neg_one}, {GR_METHOD_NEG, (gr_funcptr) vector_gr_vec_neg}, {GR_METHOD_ADD, (gr_funcptr) vector_gr_vec_add}, {GR_METHOD_ADD_UI, (gr_funcptr) vector_gr_vec_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) vector_gr_vec_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) vector_gr_vec_add_fmpz}, {GR_METHOD_ADD_FMPQ, (gr_funcptr) vector_gr_vec_add_fmpq}, {GR_METHOD_ADD_OTHER, (gr_funcptr) vector_gr_vec_add_other}, {GR_METHOD_OTHER_ADD, (gr_funcptr) vector_gr_vec_other_add}, {GR_METHOD_SUB, (gr_funcptr) vector_gr_vec_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) vector_gr_vec_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) vector_gr_vec_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) vector_gr_vec_sub_fmpz}, {GR_METHOD_SUB_FMPQ, (gr_funcptr) vector_gr_vec_sub_fmpq}, {GR_METHOD_SUB_OTHER, (gr_funcptr) vector_gr_vec_sub_other}, {GR_METHOD_OTHER_SUB, (gr_funcptr) vector_gr_vec_other_sub}, {GR_METHOD_MUL, (gr_funcptr) vector_gr_vec_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) vector_gr_vec_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) vector_gr_vec_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) vector_gr_vec_mul_fmpz}, {GR_METHOD_MUL_FMPQ, (gr_funcptr) vector_gr_vec_mul_fmpq}, {GR_METHOD_MUL_OTHER, (gr_funcptr) vector_gr_vec_mul_other}, {GR_METHOD_OTHER_MUL, (gr_funcptr) vector_gr_vec_other_mul}, {GR_METHOD_INV, (gr_funcptr) vector_gr_vec_inv}, {GR_METHOD_DIV, (gr_funcptr) vector_gr_vec_div}, {GR_METHOD_DIV_UI, (gr_funcptr) vector_gr_vec_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) vector_gr_vec_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) vector_gr_vec_div_fmpz}, {GR_METHOD_DIV_FMPQ, (gr_funcptr) vector_gr_vec_div_fmpq}, {GR_METHOD_DIV_OTHER, (gr_funcptr) vector_gr_vec_div_other}, {GR_METHOD_OTHER_DIV, (gr_funcptr) vector_gr_vec_other_div}, {GR_METHOD_DIV_NONUNIQUE, (gr_funcptr) vector_gr_vec_div_nonunique}, {GR_METHOD_DIVIDES, (gr_funcptr) vector_gr_vec_divides}, {GR_METHOD_DIVEXACT, (gr_funcptr) vector_gr_vec_divexact}, {GR_METHOD_DIVEXACT_UI, (gr_funcptr) vector_gr_vec_divexact_ui}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) vector_gr_vec_divexact_si}, {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) vector_gr_vec_divexact_fmpz}, {GR_METHOD_DIVEXACT_FMPQ, (gr_funcptr) vector_gr_vec_divexact_fmpq}, {GR_METHOD_DIVEXACT_OTHER, (gr_funcptr) vector_gr_vec_divexact_other}, {GR_METHOD_OTHER_DIVEXACT, (gr_funcptr) vector_gr_vec_other_divexact}, {GR_METHOD_POW, (gr_funcptr) vector_gr_vec_pow}, {GR_METHOD_POW_UI, (gr_funcptr) vector_gr_vec_pow_ui}, {GR_METHOD_POW_SI, (gr_funcptr) vector_gr_vec_pow_si}, {GR_METHOD_POW_FMPZ, (gr_funcptr) vector_gr_vec_pow_fmpz}, {GR_METHOD_POW_FMPQ, (gr_funcptr) vector_gr_vec_pow_fmpq}, {GR_METHOD_POW_OTHER, (gr_funcptr) vector_gr_vec_pow_other}, {GR_METHOD_OTHER_POW, (gr_funcptr) vector_gr_vec_other_pow}, {GR_METHOD_SQRT, (gr_funcptr) vector_gr_vec_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) vector_gr_vec_rsqrt}, {GR_METHOD_FLOOR, (gr_funcptr) vector_gr_vec_floor}, {GR_METHOD_CEIL, (gr_funcptr) vector_gr_vec_ceil}, {GR_METHOD_TRUNC, (gr_funcptr) vector_gr_vec_trunc}, {GR_METHOD_NINT, (gr_funcptr) vector_gr_vec_nint}, {GR_METHOD_ABS, (gr_funcptr) vector_gr_vec_abs}, {GR_METHOD_CONJ, (gr_funcptr) vector_gr_vec_conj}, {GR_METHOD_RE, (gr_funcptr) vector_gr_vec_re}, {GR_METHOD_IM, (gr_funcptr) vector_gr_vec_im}, {GR_METHOD_SGN, (gr_funcptr) vector_gr_vec_sgn}, {GR_METHOD_CSGN, (gr_funcptr) vector_gr_vec_csgn}, {GR_METHOD_I, (gr_funcptr) vector_gr_vec_i}, {GR_METHOD_PI, (gr_funcptr) vector_gr_vec_pi}, {GR_METHOD_EXP, (gr_funcptr) vector_gr_vec_exp}, {GR_METHOD_LOG, (gr_funcptr) vector_gr_vec_log}, {0, (gr_funcptr) NULL}, }; void _gr_ctx_init_vector(gr_ctx_t ctx, gr_ctx_t base_ring, int all_sizes, slong n) { ctx->which_ring = GR_CTX_GR_VEC; ctx->sizeof_elem = sizeof(gr_vec_struct); ctx->size_limit = WORD_MAX; if (n < 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); VECTOR_CTX(ctx)->base_ring = (gr_ctx_struct *) base_ring; VECTOR_CTX(ctx)->all_sizes = all_sizes; VECTOR_CTX(ctx)->n = n; ctx->methods = _gr_vec_methods; if (!_gr_vec_methods_initialized) { gr_method_tab_init(_gr_vec_methods, _gr_vec_methods_input); _gr_vec_methods_initialized = 1; } } void gr_ctx_init_vector_gr_vec(gr_ctx_t ctx, gr_ctx_t base_ring) { _gr_ctx_init_vector(ctx, base_ring, 1, 0); } void gr_ctx_init_vector_space_gr_vec(gr_ctx_t ctx, gr_ctx_t base_ring, slong n) { _gr_ctx_init_vector(ctx, base_ring, 0, n); } flint-3.1.3/src/gr_generic.h000066400000000000000000000600471461254215100157060ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GR_GENERIC_H #define GR_GENERIC_H #ifdef GR_GENERIC_INLINES_C #define GR_GENERIC_INLINE #else #define GR_GENERIC_INLINE static inline #endif #include "flint.h" #include "gr.h" #ifdef __cplusplus extern "C" { #endif #define GR_GENERIC_DEBUG_RINGS 0 #if GR_GENERIC_DEBUG_RINGS void gr_generic_init(void) { flint_throw(FLINT_ERROR, "ctx must implement init()\n"); } void gr_generic_clear(void) { flint_throw(FLINT_ERROR, "ctx must implement clear()\n"); } void gr_generic_swap(void) { flint_throw(FLINT_ERROR, "ctx must implement swap()\n"); } void gr_generic_randtest(void) { flint_throw(FLINT_ERROR, "ctx must implement randtest()\n"); } void gr_generic_write(void) { flint_throw(FLINT_ERROR, "ctx must implement write()\n"); } void gr_generic_zero(void) { flint_throw(FLINT_ERROR, "ctx must implement zero()\n"); } void gr_generic_one(void) { flint_throw(FLINT_ERROR, "ctx must implement one()\n"); } void gr_generic_equal(void) { flint_throw(FLINT_ERROR, "ctx must implement equal()\n"); } void gr_generic_set(void) { flint_throw(FLINT_ERROR, "ctx must implement set()\n"); } void gr_generic_set_si(void) { flint_throw(FLINT_ERROR, "ctx must implement set_si()\n"); } void gr_generic_set_ui(void) { flint_throw(FLINT_ERROR, "ctx must implement set_ui()\n"); } void gr_generic_set_fmpz(void) { flint_throw(FLINT_ERROR, "ctx must implement set_fmpz()\n"); } void gr_generic_neg(void) { flint_throw(FLINT_ERROR, "ctx must implement neg()\n"); } void gr_generic_add(void) { flint_throw(FLINT_ERROR, "ctx must implement add()\n"); } void gr_generic_sub(void) { flint_throw(FLINT_ERROR, "ctx must implement sub()\n"); } void gr_generic_mul(void) { flint_throw(FLINT_ERROR, "ctx must implement mul()\n"); } #else #define gr_generic_init gr_not_implemented #define gr_generic_clear gr_not_implemented #define gr_generic_swap gr_not_implemented #define gr_generic_randtest gr_not_implemented #define gr_generic_write gr_not_implemented #define gr_generic_zero gr_not_implemented #define gr_generic_one gr_not_implemented #define gr_generic_equal gr_not_implemented #define gr_generic_set gr_not_implemented #define gr_generic_set_si gr_not_implemented #define gr_generic_set_ui gr_not_implemented #define gr_generic_set_fmpz gr_not_implemented #define gr_generic_neg gr_not_implemented #define gr_generic_add gr_not_implemented #define gr_generic_sub gr_not_implemented #define gr_generic_mul gr_not_implemented #endif /* some useful generic functions, currently not overloadable */ #ifdef FMPZ_POLY_H WARN_UNUSED_RESULT int _gr_fmpz_poly_evaluate_horner(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_fmpz_poly_evaluate_horner(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_fmpz_poly_evaluate_rectangular(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_fmpz_poly_evaluate_rectangular(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_fmpz_poly_evaluate(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_fmpz_poly_evaluate(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx); #endif #ifdef FMPZ_MPOLY_H WARN_UNUSED_RESULT int gr_fmpz_mpoly_evaluate_iter(gr_ptr res, const fmpz_mpoly_t pol, gr_srcptr x, const fmpz_mpoly_ctx_t mctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_fmpz_mpoly_evaluate_horner(gr_ptr res, const fmpz_mpoly_t pol, gr_srcptr x, const fmpz_mpoly_ctx_t mctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_fmpz_mpoly_evaluate(gr_ptr res, const fmpz_mpoly_t f, gr_srcptr x, const fmpz_mpoly_ctx_t mctx, gr_ctx_t ctx); #endif truth_t gr_generic_ctx_predicate(gr_ctx_t ctx); truth_t gr_generic_ctx_predicate_true(gr_ctx_t ctx); truth_t gr_generic_ctx_predicate_false(gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_ctx_clear(gr_ctx_t ctx); void gr_generic_set_shallow(gr_ptr res, gr_srcptr x, const gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_write_n(gr_stream_t out, gr_srcptr x, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_randtest_not_zero(gr_ptr x, flint_rand_t state, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_randtest_small(gr_ptr x, flint_rand_t state, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_gens(gr_vec_t vec, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_gens_single(gr_vec_t vec, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_gens_recursive(gr_vec_t vec, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t gr_generic_is_zero(gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t gr_generic_is_one(gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t gr_generic_is_neg_one(gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_neg_one(gr_ptr res, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_set_other(gr_ptr res, gr_srcptr x, gr_ctx_t xctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_set_fmpq(gr_ptr res, const fmpq_t y, gr_ctx_t ctx); #define GR_PARSE_BALANCE_ADDITIONS 1 #define GR_PARSE_RING_EXPONENTS 2 WARN_UNUSED_RESULT int gr_generic_set_str_expr(gr_ptr res, const char * s, int flags, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_set_str(gr_ptr res, const char * s, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_set_str_balance_additions(gr_ptr res, const char * s, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_set_str_ring_exponents(gr_ptr res, const char * s, gr_ctx_t ctx); #ifdef FEXPR_H WARN_UNUSED_RESULT int gr_generic_set_fexpr(gr_ptr res, fexpr_vec_t inputs, gr_vec_t outputs, const fexpr_t expr, gr_ctx_t ctx); #endif WARN_UNUSED_RESULT int gr_generic_add_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_add_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_add_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_add_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_add_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_add(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sub_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sub_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sub_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sub_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sub_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_sub(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_mul(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_addmul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_addmul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_addmul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_addmul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_addmul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_addmul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_submul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_submul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_submul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_submul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_submul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_submul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_two(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sqr(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_2exp_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_mul_2exp_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_set_fmpz_2exp_fmpz(gr_ptr res, const fmpz_t x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, gr_ptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_set_fmpz_10exp_fmpz(gr_ptr res, const fmpz_t x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_inv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t gr_generic_is_invertible(gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_div_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_div_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_div_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_div_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_div_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_div(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_divexact(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_fmpz_sliding(gr_ptr f, gr_srcptr g, const fmpz_t pow, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_ui_sliding(gr_ptr f, gr_srcptr g, ulong pow, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_fmpz_binexp(gr_ptr res, gr_srcptr x, const fmpz_t exp, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_ui_binexp(gr_ptr res, gr_srcptr x, ulong e, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t e, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_si(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_ui(gr_ptr res, gr_srcptr x, ulong e, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_pow(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_numerator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_denominator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t gr_generic_is_square(gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_rsqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_cmp(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_cmpabs(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_cmp_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_cmpabs_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bernoulli_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bernoulli_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bernoulli_vec(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_eulernum_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_eulernum_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_eulernum_vec(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_stirling_s1u_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_stirling_s1_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_stirling_s2_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_stirling_s1u_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_stirling_s1_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_stirling_s2_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx); void gr_generic_vec_init(gr_ptr vec, slong len, gr_ctx_t ctx); void gr_generic_vec_clear(gr_ptr vec, slong len, gr_ctx_t ctx); void gr_generic_vec_swap(gr_ptr vec1, gr_ptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_zero(gr_ptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_set(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_neg(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_normalise(slong * res, gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT slong gr_generic_vec_normalise_weak(gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_scalar_2exp_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_scalar_addmul(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_scalar_submul(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_scalar_addmul_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_scalar_submul_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t gr_generic_vec_equal(gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_is_zero(gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_dot(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_dot_rev(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_dot_ui(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const ulong * vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_dot_si(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const slong * vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_dot_fmpz(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const fmpz * vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_set_powers(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_reciprocals(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_fmpz_sliding(gr_ptr f, gr_srcptr g, const fmpz_t pow, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_ui_sliding(gr_ptr f, gr_srcptr g, ulong pow, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_fmpz_binexp(gr_ptr res, gr_srcptr x, const fmpz_t exp, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_pow_ui_binexp(gr_ptr res, gr_srcptr x, ulong e, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_add_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_sub_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_mul_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_div_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_pow_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_add_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_sub_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_mul_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_div_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_divexact_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_other_pow_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_add_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_sub_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_mul_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_div_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_divexact_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_vec_pow_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_other_add_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_other_sub_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_other_mul_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_other_div_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_other_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_scalar_other_pow_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/gr_generic/000077500000000000000000000000001461254215100155265ustar00rootroot00000000000000flint-3.1.3/src/gr_generic/fmpz_mpoly_evaluate.c000066400000000000000000000274001461254215100217570ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fmpz_mpoly.h" #include "gr.h" #include "gr_generic.h" /* The conversion to Horner form can be stated as recursive. However, the call stack has depth proportial to the length of the input polynomial in the worst case. Therefore, we must convert it to an iterative algorithm. The procedure is HornerForm(f): if f is simple to evaluate return eval(f) else choose a variable v and the smallest non zero exponent e appearing in the terms of f write f = q * v^e + r where r is independent of the variable v return HornerForm(q) * v^e + HornerForm(r) */ typedef struct { slong f; slong r; slong v_var; fmpz_t v_exp; /* will be managed as stack grows / shrinks */ int ret; } stack_entry_struct; typedef stack_entry_struct stack_entry_t[1]; /* A = A * X^pow */ /* todo: cache squares, ...? */ static int _gr_pmul(gr_ptr A, gr_srcptr X, const fmpz_t pow, gr_ptr T, gr_ctx_t ctx) { if (fmpz_is_one(pow)) { return gr_mul(A, A, X, ctx); } else { int status; status = gr_pow_fmpz(T, X, pow, ctx); status |= gr_mul(A, A, T, ctx); return status; } } int gr_fmpz_mpoly_evaluate_horner(gr_ptr A, const fmpz_mpoly_t B, gr_srcptr C, const fmpz_mpoly_ctx_t ctxB, gr_ctx_t ctx) { int ret; slong nvars = ctxB->minfo->nvars; slong i, j, k, cur, next, f, r, f_prev, r_prev, v; slong sp, rp; stack_entry_struct * stack; gr_ptr regs; gr_ptr temp; slong * rtypes; ulong totalcounts, maxcounts; ulong * counts; slong Blen = B->length; slong * Blist; const fmpz * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fmpz * Buexp; fmpz * mdegs; fmpz_t score, tz; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; TMP_INIT; if (Blen == 0) { return gr_zero(A, ctx); } if (Blen == 1 && fmpz_mpoly_is_fmpz(B, ctxB)) { return gr_set_fmpz(A, B->coeffs, ctx); } /* flint_printf("========================== HORNER %wd ==========================\n", Blen); */ FLINT_ASSERT(Blen > 0); TMP_START; fmpz_init(score); fmpz_init(tz); /* unpack B exponents */ Buexp = _fmpz_vec_init(nvars*Blen); for (i = 0; i < Blen; i++) mpoly_get_monomial_ffmpz(Buexp + nvars*i, Bexp + BN*i, Bbits, ctxB->minfo); counts = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); mdegs = _fmpz_vec_init(nvars); /* stack */ sp = -WORD(1); /* start with empty stack */ stack = (stack_entry_struct *) TMP_ALLOC(nvars*(Blen + 1)*sizeof(stack_entry_struct)); Blist = (slong *) TMP_ALLOC(Blen*sizeof(slong)); /* registers of grs */ rp = 0; rtypes = (slong *) TMP_ALLOC((nvars + 1)*sizeof(slong)); GR_TMP_INIT_VEC(regs, nvars, ctx); GR_TMP_INIT(temp, ctx); /* polynomials will be stored as link lists */ for (i = 0; i + 1 < Blen; i++) Blist[i] = i + 1; Blist[i] = -WORD(1); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 0; (stack + sp)->f = 0; HornerForm: f = (stack + sp)->f; FLINT_ASSERT(f != -WORD(1)); /* f is not supposed to be zero */ /* obtain a count of the number of terms containing each variable */ for (i = 0; i < nvars; i++) { counts[i] = 0; fmpz_set_si(mdegs + i, -WORD(1)); } for (j = f; j != -WORD(1); j = Blist[j]) { for (i = 0; i < nvars; i++) { if (!fmpz_is_zero(Buexp + nvars*j + i )) { counts[i]++; if (fmpz_sgn(mdegs + i) < 0 || fmpz_cmp(mdegs + i, Buexp + nvars*j + i) > 0) { fmpz_set(mdegs + i, Buexp + nvars*j + i); } } } } totalcounts = 0; maxcounts = 0; v = -WORD(1); for (i = 0; i < nvars; i++) { maxcounts = FLINT_MAX(maxcounts, counts[i]); totalcounts += counts[i]; if (counts[i] != 0) v = i; } /* handle simple cases */ if (totalcounts == 0) { FLINT_ASSERT(Blist[f] == -WORD(1)); /* f should have had only one term */ rtypes[rp] = f; goto HornerFormReturn; } else if (totalcounts == 1) { FLINT_ASSERT(!fmpz_is_zero(Buexp + nvars*f + v)); /* this term should not be a scalar */ status |= gr_pow_fmpz(GR_ENTRY(regs, rp, sz), GR_ENTRY(C, v, sz), Buexp + nvars*f + v, ctx); status |= gr_mul_fmpz(GR_ENTRY(regs, rp, sz), GR_ENTRY(regs, rp, sz), Bcoeff + f, ctx); if (Blist[f] != -WORD(1)) /* if f has a second term */ { /* this term should be a scalar */ FLINT_ASSERT(fmpz_is_zero(Buexp + nvars*Blist[f] + v)); status |= gr_add_fmpz(GR_ENTRY(regs, rp, sz), GR_ENTRY(regs, rp, sz), Bcoeff + Blist[f], ctx); } rtypes[rp] = -WORD(1); goto HornerFormReturn; } /* pick best power to pull out */ k = 0; if (maxcounts == 1) { fmpz_set_si(score, -WORD(1)); for (i = 0; i < nvars; i++) { if (counts[i] == 1 && (fmpz_sgn(score) < 0 || fmpz_cmp(mdegs + i, score) < 0)) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_set(score, mdegs + i); k = i; } } } else { fmpz_zero(score); for (i = 0; i < nvars; i++) { if (counts[i] > 1) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_mul_ui(tz, mdegs + i, counts[i] - 1); if (fmpz_cmp(tz, score) > 0) { fmpz_swap(score, tz); k = i; } } } } /* set variable power v */ (stack + sp)->v_var = k; fmpz_set((stack + sp)->v_exp, mdegs + k); /* scan f and split into q and v with f = q*v + r then set f = q */ r = -WORD(1); cur = f; f_prev = -WORD(1); r_prev = -WORD(1); while (cur != -WORD(1)) { next = Blist[cur]; if (fmpz_is_zero(Buexp + nvars*cur + k)) { if (f_prev == -WORD(1)) f = Blist[cur]; else Blist[f_prev] = Blist[cur]; if (r_prev == -WORD(1)) r = cur; else Blist[r_prev] = cur; Blist[cur] = -WORD(1); r_prev = cur; } else { /* mdegs[k] should be minimum non zero exponent */ fmpz_sub(Buexp + nvars*cur + k, Buexp + nvars*cur + k, mdegs + k); FLINT_ASSERT(fmpz_sgn(Buexp + nvars*cur + k) >= 0); f_prev = cur; } cur = next; } (stack + sp)->r = r; /* convert the quotient */ sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 1; (stack + sp)->f = f; goto HornerForm; HornerForm1: /* convert the remainder */ r = (stack + sp)->r; if (r != -WORD(1)) { /* remainder is non zero */ rp++; FLINT_ASSERT(0 <= rp && rp <= nvars); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 2; (stack + sp)->f = r; goto HornerForm; HornerForm2: if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] == -WORD(1)) { /* both quotient and remainder are polynomials */ status |= _gr_pmul(GR_ENTRY(regs, rp - 1, sz), GR_ENTRY(C, (stack + sp)->v_var, sz), (stack + sp)->v_exp, temp, ctx); status |= gr_add(temp, GR_ENTRY(regs, rp - 1, sz), GR_ENTRY(regs, rp, sz), ctx); gr_swap(temp, GR_ENTRY(regs, rp - 1, sz), ctx); } else if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] != -WORD(1)) { /* quotient is a polynomial, remainder is a scalar */ status |= _gr_pmul(GR_ENTRY(regs, rp - 1, sz), GR_ENTRY(C, (stack + sp)->v_var, sz), (stack + sp)->v_exp, temp, ctx); status |= gr_add_fmpz(GR_ENTRY(regs, rp - 1, sz), GR_ENTRY(regs, rp - 1, sz), Bcoeff + rtypes[rp], ctx); } else if (rtypes[rp - 1] != -WORD(1) && rtypes[rp] == -WORD(1)) { /* quotient is a scalar, remainder is a polynomial */ status |= gr_pow_fmpz(temp, GR_ENTRY(C, (stack + sp)->v_var, sz), (stack + sp)->v_exp, ctx); status |= gr_mul_fmpz(temp, temp, Bcoeff + rtypes[rp - 1], ctx); status |= gr_add(GR_ENTRY(regs, rp - 1, sz), temp, GR_ENTRY(regs, rp, sz), ctx); } else { /* quotient is a scalar, remainder is a scalar */ FLINT_ASSERT(0); /* this should have been handled by simple case */ } rp--; FLINT_ASSERT(0 <= rp && rp <= nvars); } else { /* remainder is zero */ FLINT_ASSERT(rtypes[rp] == -WORD(1)); /* quotient is not a scalar */ /* quotient is a polynomial */ status |= _gr_pmul(GR_ENTRY(regs, rp, sz), GR_ENTRY(C, (stack + sp)->v_var, sz), (stack + sp)->v_exp, temp, ctx); } rtypes[rp] = -WORD(1); HornerFormReturn: ret = (stack + sp)->ret; fmpz_clear((stack + sp)->v_exp); sp--; if (ret == 1) goto HornerForm1; if (ret == 2) goto HornerForm2; FLINT_ASSERT(rp == 0); FLINT_ASSERT(sp == -WORD(1)); if (rtypes[rp] == -WORD(1)) { gr_swap(A, GR_ENTRY(regs, rp, sz), ctx); } else { status |= gr_set_fmpz(A, Bcoeff + rtypes[rp], ctx); } GR_TMP_CLEAR_VEC(regs, nvars, ctx); GR_TMP_CLEAR(temp, ctx); fmpz_clear(score); fmpz_clear(tz); _fmpz_vec_clear(mdegs, nvars); _fmpz_vec_clear(Buexp, nvars*Blen); TMP_END; return status; } /* todo: accept fmpz exponents */ int gr_fmpz_mpoly_evaluate_iter(gr_ptr res, const fmpz_mpoly_t pol, gr_srcptr x, const fmpz_mpoly_ctx_t ctx, gr_ctx_t cactx) { slong i, j, len, nvars; gr_ptr s, t, u; ulong * exp; int status = GR_SUCCESS; slong sz = cactx->sizeof_elem; len = fmpz_mpoly_length(pol, ctx); if (len == 0) return gr_zero(res, cactx); if (len == 1 && fmpz_mpoly_is_fmpz(pol, ctx)) return gr_set_fmpz(res, pol->coeffs, cactx); nvars = ctx->minfo->nvars; exp = flint_malloc(sizeof(ulong) * nvars); GR_TMP_INIT3(s, t, u, cactx); for (i = 0; i < len; i++) { fmpz_mpoly_get_term_exp_ui(exp, pol, i, ctx); status |= gr_one(t, cactx); for (j = 0; j < nvars; j++) { if (exp[j] == 1) { status |= gr_mul(t, t, GR_ENTRY(x, j, sz), cactx); } else if (exp[j] >= 2) { status |= gr_pow_ui(u, GR_ENTRY(x, j, sz), exp[j], cactx); status |= gr_mul(t, t, u, cactx); } } status |= gr_mul_fmpz(t, t, pol->coeffs + i, cactx); status |= gr_add(s, s, t, cactx); } gr_swap(res, s, cactx); flint_free(exp); GR_TMP_CLEAR3(s, t, u, cactx); return status; } int gr_fmpz_mpoly_evaluate(gr_ptr res, const fmpz_mpoly_t f, gr_srcptr x, const fmpz_mpoly_ctx_t ctx, gr_ctx_t cactx) { if (f->length <= 1 && f->bits <= FLINT_BITS) return gr_fmpz_mpoly_evaluate_iter(res, f, x, ctx, cactx); else return gr_fmpz_mpoly_evaluate_horner(res, f, x, ctx, cactx); } flint-3.1.3/src/gr_generic/fmpz_poly_evaluate.c000066400000000000000000000016511461254215100216020ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "gr.h" #include "gr_generic.h" /* todo: divconquer algorithm */ /* todo: algorithm selection */ int _gr_fmpz_poly_evaluate(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx) { if (len <= 6) return _gr_fmpz_poly_evaluate_horner(res, f, len, x, ctx); else return _gr_fmpz_poly_evaluate_rectangular(res, f, len, x, ctx); } int gr_fmpz_poly_evaluate(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx) { return _gr_fmpz_poly_evaluate(res, f->coeffs, f->length, x, ctx); } flint-3.1.3/src/gr_generic/fmpz_poly_evaluate_horner.c000066400000000000000000000027171461254215100231630ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "gr.h" #include "gr_generic.h" int _gr_fmpz_poly_evaluate_horner(gr_ptr res, const fmpz * f, slong len, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) { return gr_zero(res, ctx); } else if (len == 1 || gr_is_zero(x, ctx) == T_TRUE) { return gr_set_fmpz(res, f, ctx); } else if (len == 2) { status |= gr_mul_fmpz(res, x, f + 1, ctx); status |= gr_add_fmpz(res, res, f + 0, ctx); return status; } else { slong i = len - 1; gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_set_fmpz(u, f + i, ctx); for (i = len - 2; i >= 0; i--) { status |= gr_mul(t, u, x, ctx); status |= gr_add_fmpz(u, t, f + i, ctx); } gr_swap(res, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } } int gr_fmpz_poly_evaluate_horner(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx) { return _gr_fmpz_poly_evaluate_horner(res, f->coeffs, f->length, x, ctx); } flint-3.1.3/src/gr_generic/fmpz_poly_evaluate_rectangular.c000066400000000000000000000033011461254215100241630ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_poly.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" int _gr_fmpz_poly_evaluate_rectangular(gr_ptr res, const fmpz * poly, slong len, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i, m, r; gr_ptr xs, s, t, c; slong sz = ctx->sizeof_elem; if (len <= 2) return _gr_fmpz_poly_evaluate_horner(res, poly, len, x, ctx); m = n_sqrt(len) + 1; r = (len + m - 1) / m; GR_TMP_INIT_VEC(xs, m + 1, ctx); GR_TMP_INIT3(s, t, c, ctx); status = _gr_vec_set_powers(xs, x, m + 1, ctx); status |= gr_set_fmpz(res, poly + (r - 1) * m, ctx); status |= _gr_vec_dot_fmpz(res, res, 0, GR_ENTRY(xs, 1, sz), poly + (r - 1) * m + 1, len - (r - 1) * m - 1, ctx); for (i = r - 2; i >= 0; i--) { status |= gr_set_fmpz(s, poly + i * m, ctx); status |= _gr_vec_dot_fmpz(s, s, 0, GR_ENTRY(xs, 1, sz), poly + i * m + 1, m - 1, ctx); status |= gr_mul(res, res, GR_ENTRY(xs, m, sz), ctx); status |= gr_add(res, res, s, ctx); } GR_TMP_CLEAR_VEC(xs, m + 1, ctx); GR_TMP_CLEAR3(s, t, c, ctx); return status; } int gr_fmpz_poly_evaluate_rectangular(gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx) { return _gr_fmpz_poly_evaluate_rectangular(res, f->coeffs, f->length, x, ctx); } flint-3.1.3/src/gr_generic/generic.c000066400000000000000000002323501461254215100173130ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb.h" #include "arith.h" #include "bernoulli.h" #include "fexpr.h" #include "gr.h" #include "gr_generic.h" #include "gr_vec.h" #include "gr_mat.h" #include "gr_poly.h" #include "gr_special.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy #else # include #endif int gr_generic_ctx_clear(gr_ctx_t ctx) { return GR_SUCCESS; } truth_t gr_generic_ctx_predicate(gr_ctx_t ctx) { return T_UNKNOWN; } truth_t gr_generic_ctx_predicate_true(gr_ctx_t ctx) { return T_TRUE; } truth_t gr_generic_ctx_predicate_false(gr_ctx_t ctx) { return T_FALSE; } truth_t gr_generic_ctx_is_zero_ring(gr_ctx_t ctx) { gr_ptr t; int status; truth_t res; if (gr_ctx_is_integral_domain(ctx) == T_TRUE) { return T_FALSE; } else { GR_TMP_INIT(t, ctx); status = gr_one(t, ctx); if (status & GR_UNABLE) res = T_UNKNOWN; else if (status & GR_DOMAIN) res = T_FALSE; else res = gr_is_zero(t, ctx); } GR_TMP_CLEAR(t, ctx); return res; } void gr_generic_set_shallow(gr_ptr res, gr_srcptr x, const gr_ctx_t ctx) { memcpy(res, x, ctx->sizeof_elem); } int gr_generic_write_n(gr_stream_t out, gr_srcptr x, slong n, gr_ctx_t ctx) { return gr_write(out, x, ctx); } int gr_generic_randtest_not_zero(gr_ptr x, flint_rand_t state, gr_ctx_t ctx) { slong i; truth_t is_zero; int status = GR_SUCCESS; for (i = 0; i < 5; i++) { status |= gr_randtest(x, state, ctx); is_zero = gr_is_zero(x, ctx); if (is_zero == T_FALSE) return GR_SUCCESS; } if (n_randint(state, 2)) status |= gr_one(x, ctx); else status |= gr_neg_one(x, ctx); /* unused */ (void) status; is_zero = gr_is_zero(x, ctx); if (is_zero == T_FALSE) return GR_SUCCESS; /* We are in the zero ring */ if (is_zero == T_TRUE) return GR_DOMAIN; return GR_UNABLE; } int gr_generic_randtest_small(gr_ptr x, flint_rand_t state, gr_ctx_t ctx) { int status = GR_SUCCESS; if (gr_gen(x, ctx) != GR_SUCCESS || n_randint(state, 2) == 0) status |= gr_zero(x, ctx); status |= gr_mul_si(x, x, -3 + (slong) n_randint(state, 7), ctx); status |= gr_add_si(x, x, -3 + (slong) n_randint(state, 7), ctx); if (n_randint(state, 4) == 0) status |= gr_div_ui(x, x, 1 + n_randint(state, 4), ctx); if (status != GR_SUCCESS) status = gr_set_si(x, -3 + (slong) n_randint(state, 7), ctx); return status; } slong _gr_generic_length(gr_srcptr x, gr_ctx_t ctx) { return 0; } int gr_generic_gens(gr_vec_t vec, gr_ctx_t ctx) { gr_vec_set_length(vec, 0, ctx); return GR_SUCCESS; } int gr_generic_gens_single(gr_vec_t vec, gr_ctx_t ctx) { gr_vec_set_length(vec, 1, ctx); return gr_gen(vec->entries, ctx); } int gr_generic_gens_recursive(gr_vec_t vec, gr_ctx_t ctx) { return gr_gens(vec, ctx); } /* Generic arithmetic functions */ truth_t gr_generic_is_zero(gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; truth_t eq; GR_TMP_INIT(t, ctx); eq = gr_equal(x, t, ctx); GR_TMP_CLEAR(t, ctx); return eq; } truth_t gr_generic_is_one(gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; truth_t eq; GR_TMP_INIT(t, ctx); if (gr_one(t, ctx) == GR_SUCCESS) eq = gr_equal(x, t, ctx); else eq = T_UNKNOWN; GR_TMP_CLEAR(t, ctx); return eq; } truth_t gr_generic_is_neg_one(gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; truth_t eq; GR_TMP_INIT(t, ctx); if (gr_neg_one(t, ctx) == GR_SUCCESS) eq = gr_equal(x, t, ctx); else eq = T_UNKNOWN; GR_TMP_CLEAR(t, ctx); return eq; } int gr_generic_neg_one(gr_ptr res, gr_ctx_t ctx) { int status; status = gr_one(res, ctx); status |= gr_neg(res, res, ctx); return status; } int gr_generic_set_other(gr_ptr res, gr_srcptr x, gr_ctx_t xctx, gr_ctx_t ctx) { if (xctx == ctx) { return gr_set(res, x, ctx); } else if (xctx->which_ring == GR_CTX_FMPZ) { return gr_set_fmpz(res, x, ctx); } else if (xctx->which_ring == GR_CTX_FMPQ) { return gr_set_fmpq(res, x, ctx); } else if (xctx->which_ring == GR_CTX_FEXPR) { gr_vec_t vec; fexpr_vec_t fvec; int status; fexpr_vec_init(fvec, 0); gr_vec_init(vec, 0, ctx); status = gr_set_fexpr(res, fvec, vec, x, ctx); gr_vec_clear(vec, ctx); fexpr_vec_clear(fvec); return status; } else { return GR_UNABLE; } } int gr_generic_set_fmpq(gr_ptr res, const fmpq_t y, gr_ctx_t ctx) { gr_ptr t, u; int status; status = GR_SUCCESS; GR_TMP_INIT2(t, u, ctx); status |= gr_set_fmpz(t, fmpq_numref(y), ctx); status |= gr_set_fmpz(u, fmpq_denref(y), ctx); if (status == GR_SUCCESS) status = gr_inv(u, u, ctx); if (status == GR_SUCCESS) status = gr_mul(res, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } int gr_generic_add_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_fmpz(t, y, ctx); if (status == GR_SUCCESS) status = gr_add(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_add_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { fmpz_t t; int status; fmpz_init(t); fmpz_set_ui(t, y); status = gr_add_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_add_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { fmpz_t t; int status; fmpz_init(t); fmpz_set_si(t, y); status = gr_add_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_add_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_fmpq(t, y, ctx); if (status == GR_SUCCESS) status = gr_add(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_add_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); if (status == GR_SUCCESS) status = gr_add(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_other_add(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, x, x_ctx, ctx); if (status == GR_SUCCESS) status = gr_add(res, t, y, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_sub_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { int status; fmpz_t t; fmpz_init(t); fmpz_neg_ui(t, y); status = gr_add_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_sub_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { int status; fmpz_t t; fmpz_init(t); fmpz_set_si(t, y); fmpz_neg(t, t); status = gr_add_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_sub_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { int status; fmpz_t t; fmpz_init(t); fmpz_neg(t, y); status = gr_add_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_sub_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { int status; fmpq_t t; fmpq_init(t); fmpq_neg(t, y); status = gr_add_fmpq(res, x, t, ctx); fmpq_clear(t); return status; } int gr_generic_sub_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); if (status == GR_SUCCESS) status = gr_sub(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_other_sub(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, x, x_ctx, ctx); if (status == GR_SUCCESS) status = gr_sub(res, t, y, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_mul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_fmpz(t, y, ctx); if (status == GR_SUCCESS) status = gr_mul(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_mul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { fmpz_t t; int status; fmpz_init(t); fmpz_set_ui(t, y); status = gr_mul_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_mul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { fmpz_t t; int status; fmpz_init(t); fmpz_set_si(t, y); status = gr_mul_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_mul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_fmpq(t, y, ctx); if (status == GR_SUCCESS) status = gr_mul(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_mul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); if (status == GR_SUCCESS) status = gr_mul(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_other_mul(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, x, x_ctx, ctx); if (status == GR_SUCCESS) status = gr_mul(res, t, y, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_addmul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul(t, x, y, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_addmul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_ui(t, x, y, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_addmul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_si(t, x, y, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_addmul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_fmpz(t, x, y, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_addmul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_fmpq(t, x, y, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_addmul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); if (status == GR_SUCCESS) status = gr_addmul(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_submul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul(t, x, y, ctx); status |= gr_sub(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_submul_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_ui(t, x, y, ctx); status |= gr_sub(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_submul_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_si(t, x, y, ctx); status |= gr_sub(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_submul_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_fmpz(t, x, y, ctx); status |= gr_sub(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_submul_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_mul_fmpq(t, x, y, ctx); status |= gr_sub(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_submul_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); if (status == GR_SUCCESS) status = gr_submul(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_mul_two(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return gr_add(res, x, x, ctx); } int gr_generic_sqr(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return gr_mul(res, x, x, ctx); } int gr_generic_mul_2exp_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { if (y == 0) { return gr_set(res, x, ctx); } else { gr_ptr t; int status; GR_TMP_INIT(t, ctx); status = gr_set_ui(t, 2, ctx); if (y >= 0) { status |= gr_pow_ui(t, t, y, ctx); status |= gr_mul(res, x, t, ctx); } else { status |= gr_pow_ui(t, t, -y, ctx); status |= gr_div(res, x, t, ctx); } GR_TMP_CLEAR(t, ctx); return status; } } int gr_generic_mul_2exp_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return gr_set(res, x, ctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status = gr_set_ui(t, 2, ctx); if (fmpz_sgn(y) > 0) { status |= gr_pow_fmpz(t, t, y, ctx); status |= gr_mul(res, x, t, ctx); } else { fmpz_t u; fmpz_init(u); fmpz_neg(u, y); status |= gr_pow_fmpz(t, t, u, ctx); status |= gr_div(res, x, t, ctx); fmpz_clear(u); } GR_TMP_CLEAR(t, ctx); return status; } } int gr_generic_set_fmpz_2exp_fmpz(gr_ptr res, const fmpz_t x, const fmpz_t y, gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return gr_set_fmpz(res, x, ctx); } else { int status; status = gr_set_ui(res, 2, ctx); status |= gr_pow_fmpz(res, res, y, ctx); status |= gr_mul_fmpz(res, res, x, ctx); return status; } } int gr_generic_get_fmpz_2exp_fmpz(fmpz_t res1, fmpz_t res2, gr_ptr x, gr_ctx_t ctx) { int status; fmpq_t v; fmpq_init(v); status = gr_get_fmpq(v, x, ctx); if (status == GR_SUCCESS) { slong nbits, dbits; dbits = fmpz_val2(fmpq_denref(v)); fmpz_tdiv_q_2exp(fmpq_denref(v), fmpq_denref(v), dbits); if (fmpz_is_one(fmpq_denref(v))) { nbits = fmpz_val2(fmpq_numref(v)); fmpz_tdiv_q_2exp(fmpq_numref(v), fmpq_numref(v), nbits); fmpz_swap(res1, fmpq_numref(v)); fmpz_set_si(res2, nbits - dbits); } else { status = GR_DOMAIN; } } fmpq_clear(v); return status; } int gr_generic_set_fmpz_10exp_fmpz(gr_ptr res, const fmpz_t x, const fmpz_t y, gr_ctx_t ctx) { if (fmpz_is_zero(y)) { return gr_set_fmpz(res, x, ctx); } else if (fmpz_is_zero(x)) { return gr_zero(res, ctx); } else { gr_ptr t; int status; GR_TMP_INIT(t, ctx); status = gr_set_ui(t, 10, ctx); if (fmpz_sgn(y) > 0) { status |= gr_pow_fmpz(t, t, y, ctx); status |= gr_set_fmpz(res, x, ctx); status |= gr_mul(res, res, t, ctx); } else { fmpz_t e; fmpz_init(e); fmpz_neg(e, y); status |= gr_pow_fmpz(t, t, e, ctx); status |= gr_set_fmpz(res, x, ctx); status |= gr_div(res, res, t, ctx); fmpz_clear(e); } GR_TMP_CLEAR(t, ctx); return status; } } int gr_generic_get_fexpr_serialize(fexpr_t res, gr_srcptr x, gr_ctx_t ctx) { return gr_get_fexpr(res, x, ctx); } int gr_generic_inv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_one(x, ctx) == T_TRUE) return gr_one(res, ctx); if (gr_is_neg_one(x, ctx) == T_TRUE) return gr_neg_one(res, ctx); /* todo: dubious in the zero ring, if comparing with 1 above somehow failed */ if (gr_is_zero(x, ctx) == T_TRUE) return GR_DOMAIN; return GR_UNABLE; } truth_t gr_generic_is_invertible(gr_srcptr x, gr_ctx_t ctx) { if (gr_is_one(x, ctx) == T_TRUE) return T_TRUE; if (gr_is_neg_one(x, ctx) == T_TRUE) return T_TRUE; /* todo: dubious in the zero ring, if comparing with 1 above somehow failed */ if (gr_is_zero(x, ctx) == T_TRUE) return T_FALSE; return T_UNKNOWN; } int gr_generic_div_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_fmpz(t, y, ctx); if (status == GR_SUCCESS) status = gr_div(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_div_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { fmpz_t t; int status; fmpz_init(t); fmpz_set_ui(t, y); status = gr_div_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_div_si(gr_ptr res, gr_srcptr x, slong y, gr_ctx_t ctx) { fmpz_t t; int status; fmpz_init(t); fmpz_set_si(t, y); status = gr_div_fmpz(res, x, t, ctx); fmpz_clear(t); return status; } int gr_generic_div_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { fmpq_t t; int status; if (fmpq_is_zero(y)) /* for non-rings? */ { gr_ptr t; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_fmpq(t, y, ctx); if (status == GR_SUCCESS) status = gr_div(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } fmpq_init(t); fmpq_inv(t, y); status = gr_mul_fmpq(res, x, t, ctx); fmpq_clear(t); return status; } int gr_generic_div_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); if (status == GR_SUCCESS) status = gr_div(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_other_div(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, x, x_ctx, ctx); if (status == GR_SUCCESS) status = gr_div(res, t, y, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_divexact(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return gr_div(res, x, y, ctx); } truth_t gr_generic_div_nonunique(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { truth_t zero; int status; /* 0 = q * y has 0 as a solution, even if y = 0 */ zero = gr_is_zero(x, ctx); if (zero == T_TRUE) { status = gr_zero(res, ctx); return (status == GR_SUCCESS) ? T_TRUE : T_UNKNOWN; } status = gr_div(res, x, y, ctx); if (status == GR_SUCCESS) return T_TRUE; /* In an integral domain, div should find the unique quotient or assert that none exists. */ if (gr_ctx_is_integral_domain(ctx) == T_TRUE) return status; /* The ring would need to implement this case. */ return GR_UNABLE; } truth_t gr_generic_divides(gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; truth_t zero; int status; zero = gr_is_zero(y, ctx); if (zero == T_TRUE) return T_TRUE; GR_TMP_INIT(t, ctx); status = gr_div(t, y, x, ctx); GR_TMP_CLEAR(t, ctx); if (status == GR_SUCCESS) return T_TRUE; if (gr_ctx_is_integral_domain(ctx) != T_TRUE) return T_UNKNOWN; if (status == GR_DOMAIN) return T_FALSE; return T_UNKNOWN; } /* at least catch square roots -- todo: generalize to nth roots */ int gr_generic_pow_fmpq(gr_ptr res, gr_srcptr x, const fmpq_t y, gr_ctx_t ctx) { if (fmpz_is_one(fmpq_denref(y))) { return gr_pow_fmpz(res, x, fmpq_numref(y), ctx); } else if (*fmpq_denref(y) == 2) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); if (fmpz_sgn(fmpq_numref(y)) > 0) { status |= gr_sqrt(t, x, ctx); if (status == GR_SUCCESS) status |= gr_pow_fmpz(res, t, fmpq_numref(y), ctx); } else { status |= gr_rsqrt(t, x, ctx); if (status == GR_SUCCESS) { fmpz_t e; fmpz_init(e); fmpz_neg(e, fmpq_numref(y)); status |= gr_pow_fmpz(res, t, e, ctx); fmpz_clear(e); } } if (status != GR_SUCCESS) status = GR_UNABLE; GR_TMP_CLEAR(t, ctx); return status; } else { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_fmpq(t, y, ctx); if (status == GR_SUCCESS) status = gr_pow(res, x, t, ctx); else status = GR_UNABLE; GR_TMP_CLEAR(t, ctx); return status; } } int gr_generic_pow_other(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { if (y_ctx->which_ring == GR_CTX_FMPZ) { return gr_pow_fmpz(res, x, y, ctx); } else if (y_ctx->which_ring == GR_CTX_FMPQ) { return gr_pow_fmpq(res, x, y, ctx); } else { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); if (status == GR_SUCCESS) status = gr_pow(res, x, t, ctx); else status = GR_UNABLE; GR_TMP_CLEAR(t, ctx); return status; } } int gr_generic_other_pow(gr_ptr res, gr_srcptr x, gr_ctx_t x_ctx, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, x, x_ctx, ctx); if (status == GR_SUCCESS) status = gr_pow(res, t, y, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_numerator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return gr_set(res, x, ctx); } int gr_generic_denominator(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return gr_one(res, ctx); } truth_t gr_generic_is_square(gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return T_TRUE; if (gr_is_one(x, ctx) == T_TRUE) return T_TRUE; return GR_UNABLE; } int gr_generic_sqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res, ctx); if (gr_is_one(x, ctx) == T_TRUE) return gr_one(res, ctx); return GR_UNABLE; } int gr_generic_rsqrt(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return GR_DOMAIN; if (gr_is_one(x, ctx) == T_TRUE) return gr_one(res, ctx); { int status; status = gr_sqrt(res, x, ctx); if (status == GR_SUCCESS) { status = gr_inv(res, res, ctx); if (status == GR_SUCCESS) return status; } } return GR_UNABLE; } int gr_generic_cmp(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_UNABLE; } int gr_generic_cmpabs(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t, u; int status = GR_SUCCESS; GR_TMP_INIT2(t, u, ctx); status |= gr_abs(t, x, ctx); status |= gr_abs(u, y, ctx); status |= gr_cmp(res, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } int gr_generic_cmp_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); status |= gr_cmp(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_cmpabs_other(int * res, gr_srcptr x, gr_srcptr y, gr_ctx_t y_ctx, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_other(t, y, y_ctx, ctx); status |= gr_cmpabs(res, x, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_bernoulli_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPQ) { if (0 && n <= 1000) bernoulli_cache_compute(n + 1); bernoulli_fmpq_ui(res, n); return GR_SUCCESS; } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_bernoulli_ui(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else /* compute via fmpq */ { int status; fmpq_t t; fmpq_init(t); if (0 && n <= 1000) bernoulli_cache_compute(n + 1); bernoulli_fmpq_ui(t, n); status = gr_set_fmpq(res, t, ctx); fmpq_clear(t); return status; } } int gr_generic_bernoulli_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*n) && *n >= 0) { return gr_bernoulli_ui(res, *n, ctx); } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_bernoulli_fmpz(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else { return GR_UNABLE; } } int gr_generic_bernoulli_vec(gr_ptr res, slong len, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPQ) { if (0 && len <= 3000) { slong i; bernoulli_cache_compute(len); for (i = 0; i < len; i++) bernoulli_fmpq_ui(((fmpq *) res) + i, i); } else { /* todo: read as many as already cached ... */ bernoulli_fmpq_vec_no_cache(res, 0, len); } return GR_SUCCESS; } if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute numerically via arb */ { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); if (len > prec) { slong i, sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ctx_t RR; arb_t t; gr_ctx_init_real_arb(RR, prec); arb_init(t); for (i = 0; i < len; i++) { arb_bernoulli_ui(t, i, prec); status |= gr_set_other(GR_ENTRY(res, i, sz), t, RR, ctx); } arb_clear(t); gr_ctx_clear(RR); return status; } } /* compute exactly via Q */ { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_ctx_t QQ; fmpq * t; gr_ctx_init_fmpq(QQ); GR_TMP_INIT_VEC(t, len, QQ); if (0 && len <= 3000) { slong i; bernoulli_cache_compute(len); for (i = 0; i < len; i++) bernoulli_fmpq_ui(t + i, i); } else { /* todo: read as many as already cached ... */ bernoulli_fmpq_vec_no_cache(t, 0, len); } for (i = 0; i < len && status == GR_SUCCESS; i++) status |= gr_set_fmpq(GR_ENTRY(res, i, sz), t + i, ctx); GR_TMP_CLEAR_VEC(t, len, QQ); gr_ctx_clear(QQ); return status; } } void arb_fmpz_euler_number_ui(fmpz_t res, ulong n); int gr_generic_eulernum_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arb_fmpz_euler_number_ui(res, n); return GR_SUCCESS; } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_eulernum_ui(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else /* compute via fmpz */ { int status; fmpz_t t; fmpz_init(t); arb_fmpz_euler_number_ui(t, n); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } int gr_generic_eulernum_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*n) && *n >= 0) { return gr_eulernum_ui(res, *n, ctx); } else if (fmpz_sgn(n) < 0) { return GR_DOMAIN; } else if (fmpz_is_odd(n)) { return gr_zero(res, ctx); } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_eulernum_fmpz(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else { return GR_UNABLE; } } int gr_generic_eulernum_vec(gr_ptr res, slong len, gr_ctx_t ctx) { /* todo: arb based fmpz algorithm similar to bernoulli */ if (ctx->which_ring == GR_CTX_FMPZ) { arith_euler_number_vec(res, len); return GR_SUCCESS; } if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute numerically via arb */ { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); if (len > prec) { slong i, sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ctx_t RR; arb_t t; gr_ctx_init_real_arb(RR, prec); arb_init(t); for (i = 0; i < len; i++) { arb_euler_number_ui(t, i, prec); status |= gr_set_other(GR_ENTRY(res, i, sz), t, RR, ctx); } arb_clear(t); gr_ctx_clear(RR); return status; } } /* compute exactly via Z */ { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_ctx_t ZZ; fmpz * t; gr_ctx_init_fmpq(ZZ); GR_TMP_INIT_VEC(t, len, ZZ); arith_euler_number_vec(t, len); for (i = 0; i < len && status == GR_SUCCESS; i++) status |= gr_set_fmpz(GR_ENTRY(res, i, sz), t + i, ctx); GR_TMP_CLEAR_VEC(t, len, ZZ); gr_ctx_clear(ZZ); return status; } } int gr_generic_stirling_s1u_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_stirling_number_1u(res, x, y); return GR_SUCCESS; } else { int status; fmpz_t t; fmpz_init(t); arith_stirling_number_1u(t, x, y); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } int gr_generic_stirling_s1_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_stirling_number_1(res, x, y); return GR_SUCCESS; } else { int status; fmpz_t t; fmpz_init(t); arith_stirling_number_1(t, x, y); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } int gr_generic_stirling_s2_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_stirling_number_2(res, x, y); return GR_SUCCESS; } else { int status; fmpz_t t; fmpz_init(t); arith_stirling_number_2(t, x, y); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } int gr_generic_stirling_s1u_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_stirling_number_1u_vec(res, x, len); return GR_SUCCESS; } else { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_ctx_t ZZ; fmpz * t; gr_ctx_init_fmpz(ZZ); GR_TMP_INIT_VEC(t, len, ZZ); arith_stirling_number_1u_vec(t, x, len); /* todo: vector method */ for (i = 0; i < len; i++) status |= gr_set_fmpz(GR_ENTRY(res, i, sz), t + i, ctx); GR_TMP_CLEAR_VEC(t, len, ZZ); gr_ctx_clear(ZZ); return status; } } int gr_generic_stirling_s1_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_stirling_number_1_vec(res, x, len); return GR_SUCCESS; } else { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_ctx_t ZZ; fmpz * t; gr_ctx_init_fmpz(ZZ); GR_TMP_INIT_VEC(t, len, ZZ); arith_stirling_number_1_vec(t, x, len); /* todo: vector method */ for (i = 0; i < len; i++) status |= gr_set_fmpz(GR_ENTRY(res, i, sz), t + i, ctx); GR_TMP_CLEAR_VEC(t, len, ZZ); gr_ctx_clear(ZZ); return status; } } int gr_generic_stirling_s2_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_stirling_number_2_vec(res, x, len); return GR_SUCCESS; } else { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_ctx_t ZZ; fmpz * t; gr_ctx_init_fmpz(ZZ); GR_TMP_INIT_VEC(t, len, ZZ); arith_stirling_number_2_vec(t, x, len); /* todo: vector method */ for (i = 0; i < len; i++) status |= gr_set_fmpz(GR_ENTRY(res, i, sz), t + i, ctx); GR_TMP_CLEAR_VEC(t, len, ZZ); gr_ctx_clear(ZZ); return status; } } /* Generic vector functions */ void gr_generic_vec_init(gr_ptr vec, slong len, gr_ctx_t ctx) { gr_method_init_clear_op init = GR_INIT_CLEAR_OP(ctx, INIT); slong i, sz; sz = ctx->sizeof_elem; for (i = 0; i < len; i++) init(GR_ENTRY(vec, i, sz), ctx); } void gr_generic_vec_clear(gr_ptr vec, slong len, gr_ctx_t ctx) { gr_method_init_clear_op clear = GR_INIT_CLEAR_OP(ctx, CLEAR); slong i, sz; sz = ctx->sizeof_elem; for (i = 0; i < len; i++) clear(GR_ENTRY(vec, i, sz), ctx); } void gr_generic_vec_swap(gr_ptr vec1, gr_ptr vec2, slong len, gr_ctx_t ctx) { gr_method_swap_op swap = GR_SWAP_OP(ctx, SWAP); slong i, sz; sz = ctx->sizeof_elem; for (i = 0; i < len; i++) swap(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), ctx); } int gr_generic_vec_zero(gr_ptr vec, slong len, gr_ctx_t ctx) { gr_method_constant_op zero = GR_CONSTANT_OP(ctx, ZERO); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= zero(GR_ENTRY(vec, i, sz), ctx); return status; } int gr_generic_vec_set(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) { gr_method_unary_op set = GR_UNARY_OP(ctx, SET); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= set(GR_ENTRY(res, i, sz), GR_ENTRY(src, i, sz), ctx); return status; } int gr_generic_vec_neg(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) { gr_method_unary_op neg = GR_UNARY_OP(ctx, NEG); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= neg(GR_ENTRY(res, i, sz), GR_ENTRY(src, i, sz), ctx); return status; } int gr_generic_vec_normalise(slong * res, gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_unary_predicate is_zero = GR_UNARY_PREDICATE(ctx, IS_ZERO); truth_t eq; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; while (len > 0) { eq = is_zero(GR_ENTRY(vec, len - 1, sz), ctx); if (eq == T_FALSE) break; if (eq == T_UNKNOWN) { status = GR_UNABLE; break; } len--; } *res = len; return status; } slong gr_generic_vec_normalise_weak(gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_unary_predicate is_zero = GR_UNARY_PREDICATE(ctx, IS_ZERO); truth_t eq; slong sz = ctx->sizeof_elem; while (len > 0) { eq = is_zero(GR_ENTRY(vec, len - 1, sz), ctx); if (eq != T_TRUE) break; len--; } return len; } #define BINARY_OP(OP, op) \ int \ gr_generic_vec_ ## op(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) \ { \ gr_method_binary_op op = GR_BINARY_OP(ctx, OP); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(res, i, sz), GR_ENTRY(src1, i, sz), GR_ENTRY(src2, i, sz), ctx); \ \ return status; \ } \ \ int \ gr_generic_vec_ ## op ## _scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) \ { \ gr_method_binary_op op = GR_BINARY_OP(ctx, OP); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), c, ctx); \ \ return status; \ } \ \ int \ gr_generic_vec_ ## op ## _scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) \ { \ gr_method_binary_op_si op = GR_BINARY_OP_SI(ctx, OP ## _SI); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), c, ctx); \ \ return status; \ } \ \ int \ gr_generic_vec_ ## op ## _scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) \ { \ gr_method_binary_op_ui op = GR_BINARY_OP_UI(ctx, OP ## _UI); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), c, ctx); \ \ return status; \ } \ \ int \ gr_generic_vec_ ## op ## _scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) \ { \ gr_method_binary_op_fmpz op = GR_BINARY_OP_FMPZ(ctx, OP ## _FMPZ); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), c, ctx); \ \ return status; \ } \ \ int \ gr_generic_vec_ ## op ## _scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) \ { \ gr_method_binary_op_fmpq op = GR_BINARY_OP_FMPQ(ctx, OP ## _FMPQ); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), c, ctx); \ \ return status; \ } \ \ int \ gr_generic_scalar_ ## op ## _vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) \ { \ gr_method_binary_op op = GR_BINARY_OP(ctx, OP); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(vec1, i, sz), c, GR_ENTRY(vec2, i, sz), ctx); \ \ return status; \ } \ int \ gr_generic_vec_ ## op ## _other(gr_ptr res, gr_srcptr src1, gr_srcptr src2, gr_ctx_t src2_ctx, slong len, gr_ctx_t ctx) \ { \ gr_method_binary_op_other op = GR_BINARY_OP_OTHER(ctx, OP ## _OTHER); \ int status; \ slong i, sz, sz2; \ \ sz = ctx->sizeof_elem; \ sz2 = src2_ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(res, i, sz), GR_ENTRY(src1, i, sz), GR_ENTRY(src2, i, sz2), src2_ctx, ctx); \ \ return status; \ } \ \ int \ gr_generic_other_ ## op ## _vec(gr_ptr res, gr_srcptr src1, gr_ctx_t src1_ctx, gr_srcptr src2, slong len, gr_ctx_t ctx) \ { \ gr_method_other_binary_op op = GR_OTHER_BINARY_OP(ctx, OTHER_ ## OP); \ int status; \ slong i, sz, sz1; \ \ sz = ctx->sizeof_elem; \ sz1 = src1_ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(res, i, sz), GR_ENTRY(src1, i, sz1), src1_ctx, GR_ENTRY(src2, i, sz), ctx); \ \ return status; \ } \ \ int \ gr_generic_vec_ ## op ## _scalar_other(gr_ptr res, gr_srcptr src1, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) \ { \ gr_method_binary_op_other op = GR_BINARY_OP_OTHER(ctx, OP ## _OTHER); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(res, i, sz), GR_ENTRY(src1, i, sz), c, cctx, ctx); \ \ return status; \ } \ int \ gr_generic_scalar_other_ ## op ## _vec(gr_ptr res, gr_srcptr c, gr_ctx_t cctx, gr_srcptr src1, slong len, gr_ctx_t ctx) \ { \ gr_method_other_binary_op op = GR_OTHER_BINARY_OP(ctx, OTHER_ ## OP); \ int status; \ slong i, sz; \ \ sz = ctx->sizeof_elem; \ status = GR_SUCCESS; \ \ for (i = 0; i < len; i++) \ status |= op(GR_ENTRY(res, i, sz), c, cctx, GR_ENTRY(src1, i, sz), ctx); \ \ return status; \ } \ BINARY_OP(ADD, add) BINARY_OP(SUB, sub) BINARY_OP(MUL, mul) BINARY_OP(DIV, div) BINARY_OP(DIVEXACT, divexact) BINARY_OP(POW, pow) int gr_generic_vec_mul_scalar_2exp_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { gr_method_binary_op_si op = GR_BINARY_OP_SI(ctx, MUL_2EXP_SI); int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) status |= op(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), c, ctx); return status; } int gr_generic_vec_scalar_addmul(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; gr_ptr t; sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); for (i = 0; i < len; i++) { status |= mul(t, GR_ENTRY(vec2, i, sz), c, ctx); status |= add(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec1, i, sz), t, ctx); } GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_vec_scalar_submul(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_binary_op sub = GR_BINARY_OP(ctx, SUB); int status; slong i, sz; gr_ptr t; sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); for (i = 0; i < len; i++) { status |= mul(t, GR_ENTRY(vec2, i, sz), c, ctx); status |= sub(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec1, i, sz), t, ctx); } GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_vec_scalar_addmul_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { gr_method_binary_op_si mul_si = GR_BINARY_OP_SI(ctx, MUL_SI); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; gr_ptr t; sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); for (i = 0; i < len; i++) { status |= mul_si(t, GR_ENTRY(vec2, i, sz), c, ctx); status |= add(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec1, i, sz), t, ctx); } GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_vec_scalar_submul_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { gr_method_binary_op_si mul_si = GR_BINARY_OP_SI(ctx, MUL_SI); gr_method_binary_op sub = GR_BINARY_OP(ctx, SUB); int status; slong i, sz; gr_ptr t; sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); for (i = 0; i < len; i++) { status |= mul_si(t, GR_ENTRY(vec2, i, sz), c, ctx); status |= sub(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec1, i, sz), t, ctx); } GR_TMP_CLEAR(t, ctx); return status; } truth_t gr_generic_vec_equal(gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) { gr_method_binary_predicate equal = GR_BINARY_PREDICATE(ctx, EQUAL); truth_t eq, this_eq; slong i, sz; sz = ctx->sizeof_elem; eq = T_TRUE; for (i = 0; i < len; i++) { this_eq = equal(GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } return eq; } int gr_generic_vec_is_zero(gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_unary_predicate is_zero = GR_UNARY_PREDICATE(ctx, IS_ZERO); truth_t eq, this_eq; slong i, sz; sz = ctx->sizeof_elem; eq = T_TRUE; for (i = 0; i < len; i++) { this_eq = is_zero(GR_ENTRY(vec, i, sz), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } return eq; } int gr_generic_vec_dot(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; gr_ptr t; if (len <= 0) { if (initial == NULL) return gr_zero(res, ctx); else return gr_set(res, initial, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); if (initial == NULL) { status |= mul(res, vec1, vec2, ctx); } else { if (subtract) status |= gr_neg(res, initial, ctx); else status |= gr_set(res, initial, ctx); status |= mul(t, vec1, vec2, ctx); status |= add(res, res, t, ctx); } for (i = 1; i < len; i++) { status |= mul(t, GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz), ctx); status |= add(res, res, t, ctx); } if (subtract) status |= gr_neg(res, res, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_vec_dot_rev(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; gr_ptr t; if (len <= 0) { if (initial == NULL) return gr_zero(res, ctx); else return gr_set(res, initial, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); if (initial == NULL) { status |= mul(res, vec1, GR_ENTRY(vec2, len - 1, sz), ctx); } else { if (subtract) status |= gr_neg(res, initial, ctx); else status |= gr_set(res, initial, ctx); status |= mul(t, vec1, GR_ENTRY(vec2, len - 1, sz), ctx); status |= add(res, res, t, ctx); } for (i = 1; i < len; i++) { status |= mul(t, GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, len - 1 - i, sz), ctx); status |= add(res, res, t, ctx); } if (subtract) status |= gr_neg(res, res, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_vec_dot_ui(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const ulong * vec2, slong len, gr_ctx_t ctx) { gr_method_binary_op_ui mul_ui = GR_BINARY_OP_UI(ctx, MUL_UI); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; gr_ptr t; if (len <= 0) { if (initial == NULL) return gr_zero(res, ctx); else return gr_set(res, initial, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); if (initial == NULL) { status |= mul_ui(res, vec1, vec2[0], ctx); } else { if (subtract) status |= gr_neg(res, initial, ctx); else status |= gr_set(res, initial, ctx); status |= mul_ui(t, vec1, vec2[0], ctx); status |= add(res, res, t, ctx); } for (i = 1; i < len; i++) { status |= mul_ui(t, GR_ENTRY(vec1, i, sz), vec2[i], ctx); status |= add(res, res, t, ctx); } if (subtract) status |= gr_neg(res, res, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_vec_dot_si(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const slong * vec2, slong len, gr_ctx_t ctx) { gr_method_binary_op_si mul_si = GR_BINARY_OP_SI(ctx, MUL_SI); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; gr_ptr t; if (len <= 0) { if (initial == NULL) return gr_zero(res, ctx); else return gr_set(res, initial, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); if (initial == NULL) { status |= mul_si(res, vec1, vec2[0], ctx); } else { if (subtract) status |= gr_neg(res, initial, ctx); else status |= gr_set(res, initial, ctx); status |= mul_si(t, vec1, vec2[0], ctx); status |= add(res, res, t, ctx); } for (i = 1; i < len; i++) { status |= mul_si(t, GR_ENTRY(vec1, i, sz), vec2[i], ctx); status |= add(res, res, t, ctx); } if (subtract) status |= gr_neg(res, res, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_vec_dot_fmpz(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { gr_method_binary_op_fmpz mul_fmpz = GR_BINARY_OP_FMPZ(ctx, MUL_FMPZ); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; gr_ptr t; if (len <= 0) { if (initial == NULL) return gr_zero(res, ctx); else return gr_set(res, initial, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); if (initial == NULL) { status |= mul_fmpz(res, vec1, vec2, ctx); } else { if (subtract) status |= gr_neg(res, initial, ctx); else status |= gr_set(res, initial, ctx); status |= mul_fmpz(t, vec1, vec2, ctx); status |= add(res, res, t, ctx); } for (i = 1; i < len; i++) { status |= mul_fmpz(t, GR_ENTRY(vec1, i, sz), vec2 + i, ctx); status |= add(res, res, t, ctx); } if (subtract) status |= gr_neg(res, res, ctx); GR_TMP_CLEAR(t, ctx); return status; } /* todo: when to multiply repeatedly by x vs squaring? */ int gr_generic_vec_set_powers(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_unary_op sqr = GR_UNARY_OP(ctx, SQR); int status = GR_SUCCESS; slong i; slong sz = ctx->sizeof_elem;; for (i = 0; i < len; i++) { if (i == 0) status |= gr_one(GR_ENTRY(res, i, sz), ctx); else if (i == 1) status |= gr_set(GR_ENTRY(res, i, sz), x, ctx); else if (i % 2 == 0) status |= sqr(GR_ENTRY(res, i, sz), GR_ENTRY(res, i / 2, sz), ctx); else status |= mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), x, ctx); } return status; } int gr_generic_vec_reciprocals(gr_ptr res, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i; slong sz = ctx->sizeof_elem;; for (i = 0; i < len && status == GR_SUCCESS; i++) { status |= gr_set_ui(GR_ENTRY(res, i, sz), i + 1, ctx); status |= gr_inv(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), ctx); } return status; } /* Generic method implementations */ const gr_method_tab_input _gr_generic_methods[] = { {GR_METHOD_CTX_CLEAR, (gr_funcptr) gr_generic_ctx_clear}, {GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_COMMUTATIVE_RING, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_INTEGRAL_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_FIELD, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_UNIQUE_FACTORIZATION_DOMAIN, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_FINITE, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_FINITE_CHARACTERISTIC, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_ALGEBRAICALLY_CLOSED, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_ZERO_RING, (gr_funcptr) gr_generic_ctx_is_zero_ring}, {GR_METHOD_CTX_IS_ORDERED_RING, (gr_funcptr) gr_generic_ctx_predicate}, /* should be true for most rings */ {GR_METHOD_CTX_IS_THREADSAFE, (gr_funcptr) gr_generic_ctx_predicate_true}, {GR_METHOD_CTX_IS_EXACT, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_CTX_IS_CANONICAL, (gr_funcptr) gr_generic_ctx_predicate}, {GR_METHOD_INIT, (gr_funcptr) gr_generic_init}, {GR_METHOD_CLEAR, (gr_funcptr) gr_generic_clear}, {GR_METHOD_SWAP, (gr_funcptr) gr_generic_swap}, {GR_METHOD_SET_SHALLOW, (gr_funcptr) gr_generic_set_shallow}, {_GR_METHOD_LENGTH, (gr_funcptr) _gr_generic_length}, {GR_METHOD_WRITE, (gr_funcptr) gr_generic_write}, {GR_METHOD_WRITE_N, (gr_funcptr) gr_generic_write_n}, {GR_METHOD_RANDTEST, (gr_funcptr) gr_generic_randtest}, {GR_METHOD_RANDTEST_NOT_ZERO, (gr_funcptr) gr_generic_randtest_not_zero}, {GR_METHOD_RANDTEST_SMALL, (gr_funcptr) gr_generic_randtest_small}, {GR_METHOD_GENS, (gr_funcptr) gr_generic_gens}, {GR_METHOD_GENS_RECURSIVE, (gr_funcptr) gr_generic_gens_recursive}, {GR_METHOD_ZERO, (gr_funcptr) gr_generic_zero}, {GR_METHOD_ONE, (gr_funcptr) gr_generic_one}, {GR_METHOD_NEG_ONE, (gr_funcptr) gr_generic_neg_one}, {GR_METHOD_IS_ZERO, (gr_funcptr) gr_generic_is_zero}, {GR_METHOD_IS_ONE, (gr_funcptr) gr_generic_is_one}, {GR_METHOD_IS_NEG_ONE, (gr_funcptr) gr_generic_is_neg_one}, {GR_METHOD_EQUAL, (gr_funcptr) gr_generic_equal}, {GR_METHOD_SET, (gr_funcptr) gr_generic_set}, {GR_METHOD_SET_UI, (gr_funcptr) gr_generic_set_ui}, {GR_METHOD_SET_SI, (gr_funcptr) gr_generic_set_si}, {GR_METHOD_SET_FMPZ, (gr_funcptr) gr_generic_set_fmpz}, {GR_METHOD_SET_FMPQ, (gr_funcptr) gr_generic_set_fmpq}, {GR_METHOD_SET_OTHER, (gr_funcptr) gr_generic_set_other}, {GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str}, {GR_METHOD_GET_FEXPR_SERIALIZE, (gr_funcptr) gr_generic_get_fexpr_serialize}, {GR_METHOD_SET_FEXPR, (gr_funcptr) gr_generic_set_fexpr}, {GR_METHOD_NEG, (gr_funcptr) gr_generic_neg}, {GR_METHOD_ADD, (gr_funcptr) gr_generic_add}, {GR_METHOD_ADD_UI, (gr_funcptr) gr_generic_add_ui}, {GR_METHOD_ADD_SI, (gr_funcptr) gr_generic_add_si}, {GR_METHOD_ADD_FMPZ, (gr_funcptr) gr_generic_add_fmpz}, {GR_METHOD_ADD_FMPQ, (gr_funcptr) gr_generic_add_fmpq}, {GR_METHOD_ADD_OTHER, (gr_funcptr) gr_generic_add_other}, {GR_METHOD_OTHER_ADD, (gr_funcptr) gr_generic_other_add}, {GR_METHOD_SUB, (gr_funcptr) gr_generic_sub}, {GR_METHOD_SUB_UI, (gr_funcptr) gr_generic_sub_ui}, {GR_METHOD_SUB_SI, (gr_funcptr) gr_generic_sub_si}, {GR_METHOD_SUB_FMPZ, (gr_funcptr) gr_generic_sub_fmpz}, {GR_METHOD_SUB_FMPQ, (gr_funcptr) gr_generic_sub_fmpq}, {GR_METHOD_SUB_OTHER, (gr_funcptr) gr_generic_sub_other}, {GR_METHOD_OTHER_SUB, (gr_funcptr) gr_generic_other_sub}, {GR_METHOD_MUL, (gr_funcptr) gr_generic_mul}, {GR_METHOD_MUL_UI, (gr_funcptr) gr_generic_mul_ui}, {GR_METHOD_MUL_SI, (gr_funcptr) gr_generic_mul_si}, {GR_METHOD_MUL_FMPZ, (gr_funcptr) gr_generic_mul_fmpz}, {GR_METHOD_MUL_FMPQ, (gr_funcptr) gr_generic_mul_fmpq}, {GR_METHOD_MUL_OTHER, (gr_funcptr) gr_generic_mul_other}, {GR_METHOD_OTHER_MUL, (gr_funcptr) gr_generic_other_mul}, {GR_METHOD_ADDMUL, (gr_funcptr) gr_generic_addmul}, {GR_METHOD_ADDMUL_UI, (gr_funcptr) gr_generic_addmul_ui}, {GR_METHOD_ADDMUL_SI, (gr_funcptr) gr_generic_addmul_si}, {GR_METHOD_ADDMUL_FMPZ, (gr_funcptr) gr_generic_addmul_fmpz}, {GR_METHOD_ADDMUL_FMPQ, (gr_funcptr) gr_generic_addmul_fmpq}, {GR_METHOD_ADDMUL_OTHER, (gr_funcptr) gr_generic_addmul_other}, {GR_METHOD_SUBMUL, (gr_funcptr) gr_generic_submul}, {GR_METHOD_SUBMUL_UI, (gr_funcptr) gr_generic_submul_ui}, {GR_METHOD_SUBMUL_SI, (gr_funcptr) gr_generic_submul_si}, {GR_METHOD_SUBMUL_FMPZ, (gr_funcptr) gr_generic_submul_fmpz}, {GR_METHOD_SUBMUL_FMPQ, (gr_funcptr) gr_generic_submul_fmpq}, {GR_METHOD_SUBMUL_OTHER, (gr_funcptr) gr_generic_submul_other}, {GR_METHOD_MUL_TWO, (gr_funcptr) gr_generic_mul_two}, {GR_METHOD_SQR, (gr_funcptr) gr_generic_sqr}, {GR_METHOD_MUL_2EXP_SI, (gr_funcptr) gr_generic_mul_2exp_si}, {GR_METHOD_MUL_2EXP_FMPZ, (gr_funcptr) gr_generic_mul_2exp_fmpz}, {GR_METHOD_SET_FMPZ_2EXP_FMPZ, (gr_funcptr) gr_generic_set_fmpz_2exp_fmpz}, {GR_METHOD_GET_FMPZ_2EXP_FMPZ, (gr_funcptr) gr_generic_get_fmpz_2exp_fmpz}, {GR_METHOD_SET_FMPZ_10EXP_FMPZ, (gr_funcptr) gr_generic_set_fmpz_10exp_fmpz}, {GR_METHOD_DIV_UI, (gr_funcptr) gr_generic_div_ui}, {GR_METHOD_DIV_SI, (gr_funcptr) gr_generic_div_si}, {GR_METHOD_DIV_FMPZ, (gr_funcptr) gr_generic_div_fmpz}, {GR_METHOD_DIV_FMPQ, (gr_funcptr) gr_generic_div_fmpq}, {GR_METHOD_DIV_OTHER, (gr_funcptr) gr_generic_div_other}, {GR_METHOD_OTHER_DIV, (gr_funcptr) gr_generic_other_div}, {GR_METHOD_DIVEXACT, (gr_funcptr) gr_generic_divexact}, {GR_METHOD_DIVEXACT_UI, (gr_funcptr) gr_generic_div_ui}, {GR_METHOD_DIVEXACT_SI, (gr_funcptr) gr_generic_div_si}, {GR_METHOD_DIVEXACT_FMPZ, (gr_funcptr) gr_generic_div_fmpz}, {GR_METHOD_DIVEXACT_FMPQ, (gr_funcptr) gr_generic_div_fmpq}, {GR_METHOD_DIVEXACT_OTHER, (gr_funcptr) gr_generic_div_other}, {GR_METHOD_OTHER_DIVEXACT, (gr_funcptr) gr_generic_other_div}, {GR_METHOD_DIV_NONUNIQUE, (gr_funcptr) gr_generic_div_nonunique}, {GR_METHOD_DIVIDES, (gr_funcptr) gr_generic_divides}, {GR_METHOD_IS_INVERTIBLE, (gr_funcptr) gr_generic_is_invertible}, {GR_METHOD_INV, (gr_funcptr) gr_generic_inv}, {GR_METHOD_POW_SI, (gr_funcptr) gr_generic_pow_si}, {GR_METHOD_POW_UI, (gr_funcptr) gr_generic_pow_ui}, {GR_METHOD_POW_FMPZ, (gr_funcptr) gr_generic_pow_fmpz}, {GR_METHOD_POW_OTHER, (gr_funcptr) gr_generic_pow_other}, {GR_METHOD_POW_FMPQ, (gr_funcptr) gr_generic_pow_fmpq}, {GR_METHOD_OTHER_POW, (gr_funcptr) gr_generic_other_pow}, {GR_METHOD_IS_SQUARE, (gr_funcptr) gr_generic_is_square}, {GR_METHOD_SQRT, (gr_funcptr) gr_generic_sqrt}, {GR_METHOD_RSQRT, (gr_funcptr) gr_generic_rsqrt}, {GR_METHOD_NUMERATOR, (gr_funcptr) gr_generic_numerator}, {GR_METHOD_DENOMINATOR, (gr_funcptr) gr_generic_denominator}, {GR_METHOD_CMP, (gr_funcptr) gr_generic_cmp}, {GR_METHOD_CMPABS, (gr_funcptr) gr_generic_cmpabs}, {GR_METHOD_CMP_OTHER, (gr_funcptr) gr_generic_cmp_other}, {GR_METHOD_CMPABS_OTHER, (gr_funcptr) gr_generic_cmpabs_other}, {GR_METHOD_EXP, (gr_funcptr) gr_generic_exp}, {GR_METHOD_EXPM1, (gr_funcptr) gr_generic_expm1}, {GR_METHOD_EXP2, (gr_funcptr) gr_generic_exp2}, {GR_METHOD_EXP10, (gr_funcptr) gr_generic_exp10}, {GR_METHOD_LOG, (gr_funcptr) gr_generic_log}, {GR_METHOD_LOG1P, (gr_funcptr) gr_generic_log1p}, {GR_METHOD_LOG2, (gr_funcptr) gr_generic_log2}, {GR_METHOD_LOG10, (gr_funcptr) gr_generic_log10}, {GR_METHOD_SIN, (gr_funcptr) gr_generic_sin}, {GR_METHOD_COS, (gr_funcptr) gr_generic_cos}, {GR_METHOD_SIN_COS, (gr_funcptr) gr_generic_sin_cos}, {GR_METHOD_TAN, (gr_funcptr) gr_generic_tan}, {GR_METHOD_ASIN, (gr_funcptr) gr_generic_asin}, {GR_METHOD_ATAN, (gr_funcptr) gr_generic_atan}, {GR_METHOD_ASINH, (gr_funcptr) gr_generic_asinh}, {GR_METHOD_ATANH, (gr_funcptr) gr_generic_atanh}, {GR_METHOD_ACOT, (gr_funcptr) gr_generic_acot}, {GR_METHOD_ASEC, (gr_funcptr) gr_generic_asec}, {GR_METHOD_ACSC, (gr_funcptr) gr_generic_acsc}, {GR_METHOD_ACOTH, (gr_funcptr) gr_generic_acoth}, {GR_METHOD_ASECH, (gr_funcptr) gr_generic_asech}, {GR_METHOD_ACSCH, (gr_funcptr) gr_generic_acsch}, {GR_METHOD_FAC, (gr_funcptr) gr_generic_fac}, {GR_METHOD_FAC_UI, (gr_funcptr) gr_generic_fac_ui}, {GR_METHOD_FAC_FMPZ, (gr_funcptr) gr_generic_fac_fmpz}, {GR_METHOD_FAC_VEC, (gr_funcptr) gr_generic_fac_vec}, {GR_METHOD_RFAC, (gr_funcptr) gr_generic_rfac}, {GR_METHOD_RFAC_UI, (gr_funcptr) gr_generic_rfac_ui}, {GR_METHOD_RFAC_FMPZ, (gr_funcptr) gr_generic_rfac_fmpz}, {GR_METHOD_RFAC_VEC, (gr_funcptr) gr_generic_rfac_vec}, {GR_METHOD_RISING, (gr_funcptr) gr_generic_rising}, {GR_METHOD_RISING_UI, (gr_funcptr) gr_generic_rising_ui}, {GR_METHOD_FALLING, (gr_funcptr) gr_generic_falling}, {GR_METHOD_FALLING_UI, (gr_funcptr) gr_generic_falling_ui}, {GR_METHOD_BIN, (gr_funcptr) gr_generic_bin}, {GR_METHOD_BIN_UI, (gr_funcptr) gr_generic_bin_ui}, {GR_METHOD_BIN_UIUI, (gr_funcptr) gr_generic_bin_uiui}, {GR_METHOD_BIN_VEC, (gr_funcptr) gr_generic_bin_vec}, {GR_METHOD_BIN_UI_VEC, (gr_funcptr) gr_generic_bin_ui_vec}, {GR_METHOD_DOUBLEFAC, (gr_funcptr) gr_generic_doublefac}, {GR_METHOD_DOUBLEFAC_UI, (gr_funcptr) gr_generic_doublefac_ui}, {GR_METHOD_HARMONIC, (gr_funcptr) gr_generic_harmonic}, {GR_METHOD_HARMONIC_UI, (gr_funcptr) gr_generic_harmonic_ui}, {GR_METHOD_BETA, (gr_funcptr) gr_generic_beta}, {GR_METHOD_BERNOULLI_UI, (gr_funcptr) gr_generic_bernoulli_ui}, {GR_METHOD_BERNOULLI_FMPZ, (gr_funcptr) gr_generic_bernoulli_fmpz}, {GR_METHOD_BERNOULLI_VEC, (gr_funcptr) gr_generic_bernoulli_vec}, {GR_METHOD_EULERNUM_UI, (gr_funcptr) gr_generic_eulernum_ui}, {GR_METHOD_EULERNUM_FMPZ, (gr_funcptr) gr_generic_eulernum_fmpz}, {GR_METHOD_EULERNUM_VEC, (gr_funcptr) gr_generic_eulernum_vec}, {GR_METHOD_FIB_UI, (gr_funcptr) gr_generic_fib_ui}, {GR_METHOD_FIB_FMPZ, (gr_funcptr) gr_generic_fib_fmpz}, {GR_METHOD_FIB_VEC, (gr_funcptr) gr_generic_fib_vec}, {GR_METHOD_BELLNUM_UI, (gr_funcptr) gr_generic_bellnum_ui}, {GR_METHOD_BELLNUM_FMPZ, (gr_funcptr) gr_generic_bellnum_fmpz}, {GR_METHOD_BELLNUM_VEC, (gr_funcptr) gr_generic_bellnum_vec}, {GR_METHOD_PARTITIONS_UI, (gr_funcptr) gr_generic_partitions_ui}, {GR_METHOD_PARTITIONS_FMPZ, (gr_funcptr) gr_generic_partitions_fmpz}, {GR_METHOD_PARTITIONS_VEC, (gr_funcptr) gr_generic_partitions_vec}, {GR_METHOD_STIRLING_S1U_UIUI, (gr_funcptr) gr_generic_stirling_s1u_uiui}, {GR_METHOD_STIRLING_S1_UIUI, (gr_funcptr) gr_generic_stirling_s1_uiui}, {GR_METHOD_STIRLING_S2_UIUI, (gr_funcptr) gr_generic_stirling_s2_uiui}, {GR_METHOD_STIRLING_S1U_UI_VEC, (gr_funcptr) gr_generic_stirling_s1u_ui_vec}, {GR_METHOD_STIRLING_S1_UI_VEC, (gr_funcptr) gr_generic_stirling_s1_ui_vec}, {GR_METHOD_STIRLING_S2_UI_VEC, (gr_funcptr) gr_generic_stirling_s2_ui_vec}, {GR_METHOD_ERFCX, (gr_funcptr) gr_generic_erfcx}, {GR_METHOD_CHEBYSHEV_T_FMPZ, (gr_funcptr) gr_generic_chebyshev_t_fmpz}, {GR_METHOD_CHEBYSHEV_U_FMPZ, (gr_funcptr) gr_generic_chebyshev_u_fmpz}, {GR_METHOD_HILBERT_CLASS_POLY, (gr_funcptr) gr_generic_hilbert_class_poly}, {GR_METHOD_VEC_INIT, (gr_funcptr) gr_generic_vec_init}, {GR_METHOD_VEC_CLEAR, (gr_funcptr) gr_generic_vec_clear}, {GR_METHOD_VEC_SWAP, (gr_funcptr) gr_generic_vec_swap}, {GR_METHOD_VEC_ZERO, (gr_funcptr) gr_generic_vec_zero}, {GR_METHOD_VEC_SET, (gr_funcptr) gr_generic_vec_set}, {GR_METHOD_VEC_NEG, (gr_funcptr) gr_generic_vec_neg}, {GR_METHOD_VEC_NORMALISE, (gr_funcptr) gr_generic_vec_normalise}, {GR_METHOD_VEC_NORMALISE_WEAK, (gr_funcptr) gr_generic_vec_normalise_weak}, {GR_METHOD_VEC_ADD, (gr_funcptr) gr_generic_vec_add}, {GR_METHOD_VEC_SUB, (gr_funcptr) gr_generic_vec_sub}, {GR_METHOD_VEC_MUL, (gr_funcptr) gr_generic_vec_mul}, {GR_METHOD_VEC_DIV, (gr_funcptr) gr_generic_vec_div}, {GR_METHOD_VEC_DIVEXACT, (gr_funcptr) gr_generic_vec_divexact}, {GR_METHOD_VEC_POW, (gr_funcptr) gr_generic_vec_pow}, {GR_METHOD_VEC_ADD_SCALAR, (gr_funcptr) gr_generic_vec_add_scalar}, {GR_METHOD_VEC_SUB_SCALAR, (gr_funcptr) gr_generic_vec_sub_scalar}, {GR_METHOD_VEC_MUL_SCALAR, (gr_funcptr) gr_generic_vec_mul_scalar}, {GR_METHOD_VEC_DIV_SCALAR, (gr_funcptr) gr_generic_vec_div_scalar}, {GR_METHOD_VEC_DIVEXACT_SCALAR, (gr_funcptr) gr_generic_vec_divexact_scalar}, {GR_METHOD_VEC_POW_SCALAR, (gr_funcptr) gr_generic_vec_pow_scalar}, {GR_METHOD_VEC_ADD_SCALAR_SI, (gr_funcptr) gr_generic_vec_add_scalar_si}, {GR_METHOD_VEC_SUB_SCALAR_SI, (gr_funcptr) gr_generic_vec_sub_scalar_si}, {GR_METHOD_VEC_MUL_SCALAR_SI, (gr_funcptr) gr_generic_vec_mul_scalar_si}, {GR_METHOD_VEC_DIV_SCALAR_SI, (gr_funcptr) gr_generic_vec_div_scalar_si}, {GR_METHOD_VEC_DIVEXACT_SCALAR_SI, (gr_funcptr) gr_generic_vec_divexact_scalar_si}, {GR_METHOD_VEC_POW_SCALAR_SI, (gr_funcptr) gr_generic_vec_pow_scalar_si}, {GR_METHOD_VEC_ADD_SCALAR_UI, (gr_funcptr) gr_generic_vec_add_scalar_ui}, {GR_METHOD_VEC_SUB_SCALAR_UI, (gr_funcptr) gr_generic_vec_sub_scalar_ui}, {GR_METHOD_VEC_MUL_SCALAR_UI, (gr_funcptr) gr_generic_vec_mul_scalar_ui}, {GR_METHOD_VEC_DIV_SCALAR_UI, (gr_funcptr) gr_generic_vec_div_scalar_ui}, {GR_METHOD_VEC_DIVEXACT_SCALAR_UI, (gr_funcptr) gr_generic_vec_divexact_scalar_ui}, {GR_METHOD_VEC_POW_SCALAR_UI, (gr_funcptr) gr_generic_vec_pow_scalar_ui}, {GR_METHOD_VEC_ADD_SCALAR_FMPZ, (gr_funcptr) gr_generic_vec_add_scalar_fmpz}, {GR_METHOD_VEC_SUB_SCALAR_FMPZ, (gr_funcptr) gr_generic_vec_sub_scalar_fmpz}, {GR_METHOD_VEC_MUL_SCALAR_FMPZ, (gr_funcptr) gr_generic_vec_mul_scalar_fmpz}, {GR_METHOD_VEC_DIV_SCALAR_FMPZ, (gr_funcptr) gr_generic_vec_div_scalar_fmpz}, {GR_METHOD_VEC_DIVEXACT_SCALAR_FMPZ,(gr_funcptr) gr_generic_vec_divexact_scalar_fmpz}, {GR_METHOD_VEC_POW_SCALAR_FMPZ, (gr_funcptr) gr_generic_vec_pow_scalar_fmpz}, {GR_METHOD_VEC_ADD_SCALAR_FMPQ, (gr_funcptr) gr_generic_vec_add_scalar_fmpq}, {GR_METHOD_VEC_SUB_SCALAR_FMPQ, (gr_funcptr) gr_generic_vec_sub_scalar_fmpq}, {GR_METHOD_VEC_MUL_SCALAR_FMPQ, (gr_funcptr) gr_generic_vec_mul_scalar_fmpq}, {GR_METHOD_VEC_DIV_SCALAR_FMPQ, (gr_funcptr) gr_generic_vec_div_scalar_fmpq}, {GR_METHOD_VEC_DIVEXACT_SCALAR_FMPQ,(gr_funcptr) gr_generic_vec_divexact_scalar_fmpq}, {GR_METHOD_VEC_POW_SCALAR_FMPQ, (gr_funcptr) gr_generic_vec_pow_scalar_fmpq}, {GR_METHOD_SCALAR_ADD_VEC, (gr_funcptr) gr_generic_scalar_add_vec}, {GR_METHOD_SCALAR_SUB_VEC, (gr_funcptr) gr_generic_scalar_sub_vec}, {GR_METHOD_SCALAR_MUL_VEC, (gr_funcptr) gr_generic_scalar_mul_vec}, {GR_METHOD_SCALAR_DIV_VEC, (gr_funcptr) gr_generic_scalar_div_vec}, {GR_METHOD_SCALAR_DIVEXACT_VEC, (gr_funcptr) gr_generic_scalar_divexact_vec}, {GR_METHOD_SCALAR_POW_VEC, (gr_funcptr) gr_generic_scalar_pow_vec}, {GR_METHOD_VEC_ADD_OTHER, (gr_funcptr) gr_generic_vec_add_other}, {GR_METHOD_VEC_SUB_OTHER, (gr_funcptr) gr_generic_vec_sub_other}, {GR_METHOD_VEC_MUL_OTHER, (gr_funcptr) gr_generic_vec_mul_other}, {GR_METHOD_VEC_DIV_OTHER, (gr_funcptr) gr_generic_vec_div_other}, {GR_METHOD_VEC_DIVEXACT_OTHER, (gr_funcptr) gr_generic_vec_divexact_other}, {GR_METHOD_VEC_POW_OTHER, (gr_funcptr) gr_generic_vec_pow_other}, {GR_METHOD_OTHER_ADD_VEC, (gr_funcptr) gr_generic_other_add_vec}, {GR_METHOD_OTHER_SUB_VEC, (gr_funcptr) gr_generic_other_sub_vec}, {GR_METHOD_OTHER_MUL_VEC, (gr_funcptr) gr_generic_other_mul_vec}, {GR_METHOD_OTHER_DIV_VEC, (gr_funcptr) gr_generic_other_div_vec}, {GR_METHOD_OTHER_DIVEXACT_VEC, (gr_funcptr) gr_generic_other_divexact_vec}, {GR_METHOD_OTHER_POW_VEC, (gr_funcptr) gr_generic_other_pow_vec}, {GR_METHOD_VEC_ADD_SCALAR_OTHER, (gr_funcptr) gr_generic_vec_add_scalar_other}, {GR_METHOD_VEC_SUB_SCALAR_OTHER, (gr_funcptr) gr_generic_vec_sub_scalar_other}, {GR_METHOD_VEC_MUL_SCALAR_OTHER, (gr_funcptr) gr_generic_vec_mul_scalar_other}, {GR_METHOD_VEC_DIV_SCALAR_OTHER, (gr_funcptr) gr_generic_vec_div_scalar_other}, {GR_METHOD_VEC_DIVEXACT_SCALAR_OTHER, (gr_funcptr) gr_generic_vec_divexact_scalar_other}, {GR_METHOD_VEC_POW_SCALAR_OTHER, (gr_funcptr) gr_generic_vec_pow_scalar_other}, {GR_METHOD_SCALAR_OTHER_ADD_VEC, (gr_funcptr) gr_generic_scalar_other_add_vec}, {GR_METHOD_SCALAR_OTHER_SUB_VEC, (gr_funcptr) gr_generic_scalar_other_sub_vec}, {GR_METHOD_SCALAR_OTHER_MUL_VEC, (gr_funcptr) gr_generic_scalar_other_mul_vec}, {GR_METHOD_SCALAR_OTHER_DIV_VEC, (gr_funcptr) gr_generic_scalar_other_div_vec}, {GR_METHOD_SCALAR_OTHER_DIVEXACT_VEC, (gr_funcptr) gr_generic_scalar_other_divexact_vec}, {GR_METHOD_VEC_MUL_SCALAR_2EXP_SI, (gr_funcptr) gr_generic_vec_mul_scalar_2exp_si}, {GR_METHOD_VEC_ADDMUL_SCALAR, (gr_funcptr) gr_generic_vec_scalar_addmul}, {GR_METHOD_VEC_SUBMUL_SCALAR, (gr_funcptr) gr_generic_vec_scalar_submul}, {GR_METHOD_VEC_ADDMUL_SCALAR_SI, (gr_funcptr) gr_generic_vec_scalar_addmul_si}, {GR_METHOD_VEC_SUBMUL_SCALAR_SI, (gr_funcptr) gr_generic_vec_scalar_submul_si}, {GR_METHOD_VEC_EQUAL, (gr_funcptr) gr_generic_vec_equal}, {GR_METHOD_VEC_IS_ZERO, (gr_funcptr) gr_generic_vec_is_zero}, {GR_METHOD_VEC_SUM, (gr_funcptr) _gr_vec_sum_generic}, {GR_METHOD_VEC_PRODUCT, (gr_funcptr) _gr_vec_product_generic}, {GR_METHOD_VEC_DOT, (gr_funcptr) gr_generic_vec_dot}, {GR_METHOD_VEC_DOT_REV, (gr_funcptr) gr_generic_vec_dot_rev}, {GR_METHOD_VEC_DOT_UI, (gr_funcptr) gr_generic_vec_dot_ui}, {GR_METHOD_VEC_DOT_SI, (gr_funcptr) gr_generic_vec_dot_si}, {GR_METHOD_VEC_DOT_FMPZ, (gr_funcptr) gr_generic_vec_dot_fmpz}, {GR_METHOD_VEC_RECIPROCALS, (gr_funcptr) gr_generic_vec_reciprocals}, {GR_METHOD_VEC_SET_POWERS, (gr_funcptr) gr_generic_vec_set_powers}, {GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_poly_mullow_generic}, {GR_METHOD_POLY_DIV, (gr_funcptr) _gr_poly_div_generic}, {GR_METHOD_POLY_DIVREM, (gr_funcptr) _gr_poly_divrem_generic}, {GR_METHOD_POLY_DIVEXACT, (gr_funcptr) _gr_poly_divexact_generic}, {GR_METHOD_POLY_TAYLOR_SHIFT, (gr_funcptr) _gr_poly_taylor_shift_generic}, {GR_METHOD_POLY_INV_SERIES, (gr_funcptr) _gr_poly_inv_series_generic}, {GR_METHOD_POLY_INV_SERIES_BASECASE,(gr_funcptr) _gr_poly_inv_series_basecase_generic}, {GR_METHOD_POLY_DIV_SERIES, (gr_funcptr) _gr_poly_div_series_generic}, {GR_METHOD_POLY_DIV_SERIES_BASECASE,(gr_funcptr) _gr_poly_div_series_basecase_generic}, {GR_METHOD_POLY_RSQRT_SERIES, (gr_funcptr) _gr_poly_rsqrt_series_generic}, {GR_METHOD_POLY_SQRT_SERIES, (gr_funcptr) _gr_poly_sqrt_series_generic}, {GR_METHOD_POLY_EXP_SERIES, (gr_funcptr) _gr_poly_exp_series_generic}, {GR_METHOD_MAT_MUL, (gr_funcptr) gr_mat_mul_generic}, {GR_METHOD_MAT_LU, (gr_funcptr) gr_mat_lu_generic}, {GR_METHOD_MAT_DET, (gr_funcptr) gr_mat_det_generic}, {GR_METHOD_MAT_EXP, (gr_funcptr) gr_mat_exp_jordan}, {GR_METHOD_MAT_LOG, (gr_funcptr) gr_mat_log_jordan}, {GR_METHOD_MAT_FIND_NONZERO_PIVOT, (gr_funcptr) gr_mat_find_nonzero_pivot_generic}, {GR_METHOD_MAT_DIAGONALIZATION, (gr_funcptr) gr_mat_diagonalization_generic}, {0, (gr_funcptr) NULL}, }; void gr_method_tab_init(gr_funcptr * methods, gr_method_tab_input * tab) { slong i; /* Write to a temporary table so that gr_not_implemented entries do not overwrite proper entries if there are multiple threads trying to init the same table simultaneously. */ gr_static_method_table tmp; for (i = 0; i < GR_METHOD_TAB_SIZE; i++) tmp[i] = (gr_funcptr) gr_not_implemented; /* Assign generic methods as fallbacks */ for (i = 0; ; i++) { if (_gr_generic_methods[i].function == NULL) break; if (_gr_generic_methods[i].index >= GR_METHOD_TAB_SIZE) flint_throw(FLINT_ERROR, "(%s)\n", __func__); tmp[_gr_generic_methods[i].index] = _gr_generic_methods[i].function; } for (i = 0; ; i++) { if (tab[i].function == NULL) break; if (tab[i].index >= GR_METHOD_TAB_SIZE) flint_throw(FLINT_ERROR, "(%s)\n", __func__); tmp[tab[i].index] = tab[i].function; } memcpy(methods, tmp, sizeof(gr_static_method_table)); } flint-3.1.3/src/gr_generic/generic_pow.c000066400000000000000000000206201461254215100201730ustar00rootroot00000000000000/* Copyright (C) 2015 Vladimir Glazachev Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr.h" #include "gr_generic.h" /* Returns smallest integer k satisfying: log(n) < (k * (k + 1) * 2^(2 * k)) / (2^(k + 1) - k - 2) + 1 */ static ulong sliding_select_k(ulong bits) { if (bits <= 8) return 1; if (bits <= 24) return 2; if (bits <= 69) return 3; if (bits <= 196) return 4; if (bits <= 538) return 5; if (bits <= 1433) return 6; if (bits <= 3714) return 7; if (bits <= 9399) return 8; if (bits <= 23290) return 9; if (bits <= 56651) return 10; return 11; } #define MPN_TSTBIT(x, xn, b) (((b) / FLINT_BITS >= ((xn))) ? 0 : ((x[(b) / FLINT_BITS] >> ((b) % FLINT_BITS)) & UWORD(1))) /* todo: avoid swaps (or perform pointer swaps) */ /* note: supports aliasing */ static int _gr_pow_mpn_sliding(gr_ptr f, gr_srcptr g, mp_srcptr exp, mp_size_t en, gr_ctx_t ctx) { slong h, k, value; slong i, j, alloc; gr_ptr temp; fmpz * g_powers; slong sz = ctx->sizeof_elem; mp_bitcnt_t ebits; int status = GR_SUCCESS; ebits = (en - 1) * FLINT_BITS + FLINT_BIT_COUNT(exp[en - 1]); /* selects optimal k value for n */ k = sliding_select_k(ebits); /* g_powers store odd powers of g up to 2^k - 1; g_powers[(i + 1) / 2] = g^i */ alloc = (WORD(1) << (k - 1)) + 1; GR_TMP_INIT_VEC(g_powers, alloc + 1, ctx); temp = GR_ENTRY(g_powers, alloc, sz); /* temp = g * g */ status |= gr_sqr(temp, g, ctx); status |= gr_one(GR_ENTRY(g_powers, 0, sz), ctx); status |= gr_set(GR_ENTRY(g_powers, 1, sz), g, ctx); /* sets g_powers[i] = g^2 * g_powers[i - 1] */ for (i = 2; i <= WORD(1) << (k - 1); i++) status |= gr_mul(GR_ENTRY(g_powers, i, sz), GR_ENTRY(g_powers, i - 1, sz), temp, ctx); status |= gr_one(f, ctx); i = ebits - 1; /* working with pow = (e_l, e_{l-1}, ... , e_0) in 2 base */ while (i >= 0) { if (!MPN_TSTBIT(exp, en, i)) { status |= gr_sqr(temp, f, ctx); gr_swap(f, temp, ctx); i--; } else { /* finds length of chain; chain is length of longest bitstring less then k ending on 1 */ j = FLINT_MAX(i - k + 1, 0); while (MPN_TSTBIT(exp, en, j) == 0 && j <= i) j++; /* f = f^(2^(i - j + 1)) */ for (h = 0; h < i - j + 1; h++) { status |= gr_sqr(temp, f, ctx); gr_swap(f, temp, ctx); } /* value = binary number (e_i, ... , e_j) */ value = 0; for (h = 0; h < i - j + 1; h++) value += MPN_TSTBIT(exp, en, j + h) << h; /* f = f * g^value */ status |= gr_mul(temp, f, GR_ENTRY(g_powers, (value + 1) / 2, sz), ctx); gr_swap(f, temp, ctx); /* increase i */ i = j - 1; } } GR_TMP_CLEAR_VEC(g_powers, alloc + 1, ctx); return status; } int gr_generic_pow_fmpz_sliding(gr_ptr f, gr_srcptr g, const fmpz_t pow, gr_ctx_t ctx) { if (fmpz_sgn(pow) < 0) return GR_UNABLE; if (fmpz_is_zero(pow)) return gr_one(f, ctx); if (!COEFF_IS_MPZ(*pow)) { ulong t = *pow; return _gr_pow_mpn_sliding(f, g, &t, 1, ctx); } else { return _gr_pow_mpn_sliding(f, g, COEFF_TO_PTR(*pow)->_mp_d, COEFF_TO_PTR(*pow)->_mp_size, ctx); } } int gr_generic_pow_ui_sliding(gr_ptr f, gr_srcptr g, ulong pow, gr_ctx_t ctx) { if (pow == 0) return gr_one(f, ctx); else return _gr_pow_mpn_sliding(f, g, &pow, 1, ctx); } /* Assumes exp >= 2; res and tmp not not aliased with x. */ int _gr_generic_pow_ui_binexp(gr_ptr res, gr_ptr tmp, gr_srcptr x, ulong exp, gr_ctx_t ctx) { gr_ptr R, S, T; gr_method_unary_op sqr = GR_UNARY_OP(ctx, SQR); gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); int status; int zeros; ulong bit; status = GR_SUCCESS; /* Determine parity due to swaps */ zeros = 0; bit = exp; while (bit > 1) { zeros += !(bit & 1); bit >>= 1; } if (zeros % 2) { R = res; S = tmp; } else { R = tmp; S = res; } bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2); status |= sqr(R, x, ctx); if (bit & exp) { status |= mul(S, R, x, ctx); T = R; R = S; S = T; } while (bit >>= 1) { status |= sqr(S, R, ctx); if (bit & exp) { status |= mul(R, S, x, ctx); } else { T = R; R = S; S = T; } } return status; } static int gr_generic_pow3(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status; if (res == x) { gr_ptr t; GR_TMP_INIT(t, ctx); status = gr_sqr(t, x, ctx); status |= gr_mul(res, t, x, ctx); GR_TMP_CLEAR(t, ctx); } else { status = gr_sqr(res, x, ctx); status |= gr_mul(res, res, x, ctx); } return status; } static int gr_generic_pow4(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status; status = gr_sqr(res, x, ctx); status |= gr_sqr(res, res, ctx); return status; } /* todo: optimize swaps */ int gr_generic_pow_fmpz_binexp(gr_ptr res, gr_srcptr x, const fmpz_t exp, gr_ctx_t ctx) { gr_ptr t, u; gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_unary_op sqr = GR_UNARY_OP(ctx, SQR); gr_method_swap_op swap = GR_SWAP_OP(ctx, SWAP); int status; slong i; if (*exp == 0) return gr_one(res, ctx); else if (*exp == 1) return gr_set(res, x, ctx); else if (*exp == 2) return gr_sqr(res, x, ctx); else if (*exp == 3) return gr_generic_pow3(res, x, ctx); else if (*exp == 4) return gr_generic_pow4(res, x, ctx); if (fmpz_sgn(exp) < 0) return GR_UNABLE; status = GR_SUCCESS; GR_TMP_INIT2(t, u, ctx); status |= gr_set(t, x, ctx); for (i = fmpz_bits(exp) - 2; i >= 0; i--) { status |= sqr(u, t, ctx); if (fmpz_tstbit(exp, i)) status |= mul(t, u, x, ctx); else swap(t, u, ctx); } swap(res, t, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } int gr_generic_pow_ui_binexp(gr_ptr res, gr_srcptr x, ulong e, gr_ctx_t ctx) { int status; gr_ptr t, u; if (e == 0) return gr_one(res, ctx); else if (e == 1) return gr_set(res, x, ctx); else if (e == 2) return gr_sqr(res, x, ctx); else if (e == 3) return gr_generic_pow3(res, x, ctx); else if (e == 4) return gr_generic_pow4(res, x, ctx); if (res == x) { GR_TMP_INIT2(t, u, ctx); status = gr_set(u, x, ctx); status |= _gr_generic_pow_ui_binexp(res, t, u, e, ctx); GR_TMP_CLEAR2(t, u, ctx); } else { GR_TMP_INIT(t, ctx); status = _gr_generic_pow_ui_binexp(res, t, x, e, ctx); GR_TMP_CLEAR(t, ctx); } return status; } int gr_generic_pow_ui(gr_ptr res, gr_srcptr x, ulong e, gr_ctx_t ctx) { return gr_generic_pow_ui_binexp(res, x, e, ctx); } int gr_generic_pow_si(gr_ptr res, gr_srcptr x, slong e, gr_ctx_t ctx) { if (e >= 0) { return gr_pow_ui(res, x, e, ctx); } else { int status; status = gr_inv(res, x, ctx); if (status == GR_SUCCESS && e != -1) status = gr_pow_ui(res, res, -e, ctx); return status; } } int gr_generic_pow_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t e, gr_ctx_t ctx) { int status; if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); /* todo: some heuristic for when we want to invert before/after powering */ status = gr_inv(res, x, ctx); if (status == GR_SUCCESS) status = gr_generic_pow_fmpz(res, res, f, ctx); fmpz_clear(f); return status; } return gr_generic_pow_fmpz_binexp(res, x, e, ctx); } flint-3.1.3/src/gr_generic/set_fexpr.c000066400000000000000000000230341461254215100176730ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fexpr.h" #include "fexpr_builtin.h" #include "qqbar.h" #include "gr.h" #include "gr_vec.h" #include "gr_special.h" #define BINARY_OP(gr_func) \ if (nargs == 2) \ { \ GR_TMP_INIT(t, ctx); \ fexpr_view_arg(arg, expr, 0); \ status = gr_set_fexpr(res, inputs, outputs, arg, ctx); \ if (status == GR_SUCCESS) \ { \ fexpr_view_next(arg); \ status = gr_set_fexpr(t, inputs, outputs, arg, ctx); \ if (status == GR_SUCCESS) \ status = gr_func(res, res, t, ctx); \ } \ GR_TMP_CLEAR(t, ctx); \ return status; \ } \ return GR_DOMAIN; \ #define BINARY_OP_WITH_FMPZ(gr_func, gr_func_fmpz) \ if (nargs == 2) \ { \ GR_TMP_INIT(t, ctx); \ fexpr_view_arg(arg, expr, 0); \ status = gr_set_fexpr(res, inputs, outputs, arg, ctx); \ if (status == GR_SUCCESS) \ { \ fexpr_view_next(arg); \ if (fexpr_is_integer(arg)) \ { \ fmpz_t n; \ fmpz_init(n); \ fexpr_get_fmpz(n, arg); \ status = gr_func_fmpz(res, res, n, ctx); \ fmpz_clear(n); \ } \ else \ { \ status = gr_set_fexpr(t, inputs, outputs, arg, ctx); \ if (status == GR_SUCCESS) \ status = gr_func(res, res, t, ctx); \ } \ } \ GR_TMP_CLEAR(t, ctx); \ return status; \ } \ return GR_DOMAIN; \ #define UNARY_OP(gr_func) \ if (nargs == 1) \ { \ fexpr_view_arg(arg, expr, 0); \ status = gr_set_fexpr(res, inputs, outputs, arg, ctx); \ if (status == GR_SUCCESS) \ status = gr_func(res, res, ctx); \ return status; \ } \ return GR_DOMAIN; \ #define NARY_OP(gr_func, gr_empty_func) \ if (nargs == 0) \ return gr_empty_func(res, ctx); \ fexpr_view_arg(arg, expr, 0); \ status = gr_set_fexpr(res, inputs, outputs, arg, ctx); \ if (status == GR_SUCCESS && nargs > 1) \ { \ /* todo: divide and conquer */ \ GR_TMP_INIT(t, ctx); \ for (i = 1; i < nargs && status == GR_SUCCESS; i++) \ { \ fexpr_view_next(arg); \ status = gr_set_fexpr(t, inputs, outputs, arg, ctx); \ if (status == GR_SUCCESS) \ status = gr_func(res, res, t, ctx); \ } \ GR_TMP_CLEAR(t, ctx); \ } \ return status; \ int gr_generic_set_fexpr(gr_ptr res, fexpr_vec_t inputs, gr_vec_t outputs, const fexpr_t expr, gr_ctx_t ctx) { int status = GR_SUCCESS; if (fexpr_is_integer(expr)) { fmpz_t t; fmpz_init(t); fexpr_get_fmpz(t, expr); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } if (fexpr_is_any_builtin_symbol(expr)) { slong op = FEXPR_BUILTIN_ID(expr->data[0]); switch (op) { case FEXPR_Pi: return gr_pi(res, ctx); case FEXPR_NumberI: return gr_i(res, ctx); case FEXPR_NumberE: status |= gr_one(res, ctx); status |= gr_exp(res, res, ctx); return status; case FEXPR_Euler: return gr_euler(res, ctx); case FEXPR_GoldenRatio: /* todo: have a builtin */ status |= gr_set_ui(res, 5, ctx); status |= gr_sqrt(res, res, ctx); status |= gr_add_ui(res, res, 1, ctx); status |= gr_div_ui(res, res, 2, ctx); return status; case FEXPR_CatalanConstant: return gr_catalan(res, ctx); case FEXPR_KhinchinConstant: return gr_khinchin(res, ctx); case FEXPR_GlaisherConstant: return gr_glaisher(res, ctx); case FEXPR_Infinity: return gr_pos_inf(res, ctx); case FEXPR_UnsignedInfinity: return gr_uinf(res, ctx); case FEXPR_Undefined: return gr_undefined(res, ctx); case FEXPR_Unknown: return gr_unknown(res, ctx); } return GR_UNABLE; } if (fexpr_is_symbol(expr)) { slong i, num_defs; num_defs = inputs->length; /* Treat local definitions as a stack, more recent ones overriding older ones */ for (i = num_defs - 1; i >= 0; i--) { if (fexpr_equal(expr, fexpr_vec_entry(inputs, i))) { return gr_set(res, gr_vec_entry_srcptr(outputs, i, ctx), ctx); } } return GR_UNABLE; } if (fexpr_is_any_builtin_call(expr)) { fexpr_t func, arg; slong op, i, nargs; int status; gr_ptr t; nargs = fexpr_nargs(expr); fexpr_view_func(func, expr); op = FEXPR_BUILTIN_ID(func->data[0]); /* Parse local definitions */ if (op == FEXPR_Where) { slong num_previous_defs; num_previous_defs = inputs->length; status = GR_SUCCESS; /* Parse in reverse order; this assumes definitions are in the form x = f(y,z), y = g(z), z = h which is what gr_get_fexpr currently generates. Should this work in both directions (or any order)? */ for (i = nargs - 1; i >= 1; i--) { fexpr_t defn, symbol, value; fexpr_view_arg(defn, expr, i); if (!fexpr_is_builtin_call(defn, FEXPR_Def) || fexpr_nargs(defn) != 2) { status = GR_DOMAIN; break; } fexpr_view_arg(symbol, defn, 0); fexpr_view_arg(value, defn, 1); status = gr_set_fexpr(res, inputs, outputs, value, ctx); if (status != GR_SUCCESS) break; fexpr_vec_append(inputs, symbol); status = gr_vec_append(outputs, res, ctx); if (status != GR_SUCCESS) break; } if (status == GR_SUCCESS) { fexpr_view_arg(arg, expr, 0); status = gr_set_fexpr(res, inputs, outputs, arg, ctx); } /* We are done with the local definitions, so erase anything new. */ fexpr_vec_set_length(inputs, num_previous_defs); gr_vec_set_length(outputs, num_previous_defs, ctx); return status; } switch (op) { /* todo: generalize to non-algebraics; handle large decimals efficiently */ case FEXPR_Decimal: case FEXPR_PolynomialRootIndexed: case FEXPR_PolynomialRootNearest: case FEXPR_AlgebraicNumberSerialized: { qqbar_t a; qqbar_init(a); status = qqbar_set_fexpr(a, expr); if (status == GR_SUCCESS) { gr_ctx_t QQbar; gr_ctx_init_complex_qqbar(QQbar); /* no need to free */ status = gr_set_other(res, a, QQbar, ctx); } qqbar_clear(a); return status; } case FEXPR_Pos: UNARY_OP(gr_set) case FEXPR_Neg: UNARY_OP(gr_neg) case FEXPR_Sub: BINARY_OP(gr_sub) case FEXPR_Div: BINARY_OP(gr_div) case FEXPR_Pow: BINARY_OP_WITH_FMPZ(gr_pow, gr_pow_fmpz) case FEXPR_Sqrt: UNARY_OP(gr_sqrt) case FEXPR_Exp: UNARY_OP(gr_exp) case FEXPR_Log: UNARY_OP(gr_log) case FEXPR_Sin: UNARY_OP(gr_sin) case FEXPR_Cos: UNARY_OP(gr_cos) case FEXPR_Tan: UNARY_OP(gr_tan) case FEXPR_Cot: UNARY_OP(gr_cot) case FEXPR_Atan: UNARY_OP(gr_atan) case FEXPR_Acos: UNARY_OP(gr_acos) case FEXPR_Asin: UNARY_OP(gr_asin) case FEXPR_Sign: UNARY_OP(gr_sgn) case FEXPR_Csgn: UNARY_OP(gr_csgn) case FEXPR_Arg: UNARY_OP(gr_arg) case FEXPR_Abs: UNARY_OP(gr_abs) case FEXPR_Re: UNARY_OP(gr_re) case FEXPR_Im: UNARY_OP(gr_im) case FEXPR_Conjugate: UNARY_OP(gr_conj) case FEXPR_Floor: UNARY_OP(gr_floor) case FEXPR_Ceil: UNARY_OP(gr_ceil) case FEXPR_Gamma: UNARY_OP(gr_gamma) case FEXPR_Erf: UNARY_OP(gr_erf) case FEXPR_Erfc: UNARY_OP(gr_erfc) case FEXPR_Erfi: UNARY_OP(gr_erfi) case FEXPR_Add: NARY_OP(gr_add, gr_zero) case FEXPR_Mul: NARY_OP(gr_mul, gr_one) case FEXPR_GCD: NARY_OP(gr_gcd, gr_zero) } } return 0; } /* int gr_set_fexpr(gr_ptr res, const fexpr_t expr, gr_ctx_t ctx) { int status; fexpr_vec_t inputs; gr_vec_t outputs; fexpr_vec_init(inputs, 0); gr_vec_init(outputs, 0, ctx); status = _gr_set_fexpr(res, inputs, outputs, expr, ctx); fexpr_vec_clear(inputs); gr_vec_clear(outputs, ctx); return status; } */ flint-3.1.3/src/gr_generic/set_str_expr.c000066400000000000000000000545741461254215100204320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "mpoly.h" #include "gr.h" #include "gr_special.h" #include "gr_vec.h" #include "gr_generic.h" #define PREC_LOWEST 0 #define PREC_PLUS 1 #define PREC_MINUS 1 #define PREC_PLUSMINUS 1 #define PREC_TIMES 2 #define PREC_DIVIDES 2 #define PREC_UPLUS 3 #define PREC_UMINUS 3 #define PREC_UPLUSMINUS 3 #define PREC_POWER 4 #define PREC_HIGHEST 255 #define OP_TIMES 0 #define OP_PLUS 1 #define OP_MINUS 2 #define OP_DIVIDES 3 #define OP_LROUND 4 #define OP_POWER 5 #define OP_PLUSMINUS 6 #define FIX_INFIX 0 #define FIX_PREFIX 1 #define FIX_POSTFIX 2 #define FIX_MATCHFIX 3 typedef struct { gr_ctx_struct * R; slong * stack; slong stack_len; slong stack_alloc; char * estore; slong estore_len; slong estore_alloc; void * tmp; string_with_length_struct * terminal_strings; char * terminal_values; slong terminals_alloc; slong terminals_len; int flags; _gr_method_get_si_op size_func; } gr_parse_struct; typedef gr_parse_struct gr_parse_t[1]; void _gr_parse_init(gr_parse_t E); void _gr_parse_clear(gr_parse_t E); void _gr_parse_add_terminal(gr_parse_t E, const char * s, const void * v); int _gr_parse_parse(gr_parse_t E, void * res, const char * s, slong len); FLINT_FORCE_INLINE int _is_op(slong a) { return a >= 0; } FLINT_FORCE_INLINE slong _op_make(slong name, slong fix, slong prec) { return (prec << 10) + (fix << 8) + (name << 0); } FLINT_FORCE_INLINE slong _op_prec(slong a) { return (ulong)(a) >> 10; } FLINT_FORCE_INLINE slong _op_fix(slong a) { return ((ulong)(a) >> 8) & 3; } FLINT_FORCE_INLINE slong _op_name(slong a) { return a&255; } /* initialize the R member first */ void _gr_parse_init(gr_parse_t E) { slong i; E->flags = 0; E->size_func = (_gr_method_get_si_op) _gr_length; E->stack_len = 0; E->stack_alloc = 20; E->stack = FLINT_ARRAY_ALLOC(E->stack_alloc, slong); E->estore_len = 0; E->estore_alloc = 10; E->estore = gr_heap_init_vec(E->estore_alloc, E->R); E->terminals_len = 0; E->terminals_alloc = 5; E->terminal_values = gr_heap_init_vec(E->terminals_alloc, E->R); E->terminal_strings = FLINT_ARRAY_ALLOC(E->terminals_alloc, string_with_length_struct); for (i = 0; i < E->terminals_alloc; i++) { E->terminal_strings[i].str = NULL; E->terminal_strings[i].str_len = 0; } } void _gr_parse_clear(gr_parse_t E) { slong i; flint_free(E->stack); gr_heap_clear_vec(E->estore, E->estore_alloc, E->R); gr_heap_clear_vec(E->terminal_values, E->terminals_alloc, E->R); for (i = 0; i < E->terminals_alloc; i++) flint_free(E->terminal_strings[i].str); flint_free(E->terminal_strings); } void _gr_parse_add_terminal(gr_parse_t E, const char * s, const void * val) { slong l, n = E->terminals_len; slong sz = E->R->sizeof_elem; if (n + 1 > E->terminals_alloc) { slong i = E->terminals_alloc; slong new_alloc = FLINT_MAX(n + 1, i + i/2); E->terminal_strings = (string_with_length_struct *) flint_realloc( E->terminal_strings, new_alloc* sizeof(string_with_length_struct)); E->terminal_values = (char *) flint_realloc(E->terminal_values, sz * new_alloc); for ( ; i < new_alloc; i++) { E->terminal_strings[i].str = NULL; E->terminal_strings[i].str_len = 0; gr_init(GR_ENTRY(E->terminal_values, i, sz), E->R); } E->terminals_alloc = new_alloc; } l = strlen(s); E->terminal_strings[n].str_len = l; E->terminal_strings[n].str = (char *) flint_realloc(E->terminal_strings[n].str, l + 1); memcpy(E->terminal_strings[n].str, s, l + 1); GR_MUST_SUCCEED(gr_set(GR_ENTRY(E->terminal_values, n, sz), val, E->R)); E->terminals_len = n + 1; while (n > 0 && E->terminal_strings[n-1].str_len < E->terminal_strings[n].str_len) { FLINT_SWAP(char *, E->terminal_strings[n-1].str, E->terminal_strings[n].str); FLINT_SWAP(slong, E->terminal_strings[n-1].str_len, E->terminal_strings[n].str_len); gr_swap(GR_ENTRY(E->terminal_values, n - 1, sz), GR_ENTRY(E->terminal_values, n, sz), E->R); n--; } } static int gr_parse_top_is_expr(const gr_parse_t E) { return E->stack_len > 0 && !_is_op(E->stack[E->stack_len - 1]); } static void * gr_parse_top_expr(gr_parse_t E) { slong sz = E->R->sizeof_elem; FLINT_ASSERT(E->stack_len > 0); FLINT_ASSERT(E->stack[E->stack_len - 1] < 0); return GR_ENTRY(E->estore, -1 - E->stack[E->stack_len - 1], sz); } static void _gr_parse_push_op(gr_parse_t E, slong op) { FLINT_ASSERT(_is_op(op)); _slong_array_fit_length(&E->stack, &E->stack_alloc, E->stack_len + 1); E->stack[E->stack_len] = op; E->stack_len++; } /* if the top is not an expr, push the tmp, otherwise fail */ static int _gr_parse_push_expr(gr_parse_t E) { slong sz = E->R->sizeof_elem; if (gr_parse_top_is_expr(E)) return -1; if (E->estore_len + 1 > E->estore_alloc) { slong i = E->estore_alloc; slong new_alloc = FLINT_MAX(E->estore_len + 1, i + i/2); E->estore = flint_realloc(E->estore, new_alloc*sz); for ( ; i < new_alloc; i++) gr_init(GR_ENTRY(E->estore, i, sz), E->R); E->estore_alloc = new_alloc; } _slong_array_fit_length(&E->stack, &E->stack_alloc, E->stack_len + 1); E->stack[E->stack_len] = -1 - E->estore_len; E->stack_len++; gr_swap(GR_ENTRY(E->estore, E->estore_len, sz), E->tmp, E->R); E->estore_len++; return 0; } /* if the top is an expr, pop it, otherwise fail */ static int _gr_parse_pop_expr(gr_parse_t E) { slong sz = E->R->sizeof_elem; if (!gr_parse_top_is_expr(E)) return -1; gr_swap(E->tmp, GR_ENTRY(E->estore, -1 - E->stack[E->stack_len - 1], sz), E->R); E->estore_len--; E->stack_len--; return 0; } /* if the top is an operation op, pop it, otherwise fail */ static int _gr_parse_pop_op(gr_parse_t E, slong op) { slong n = E->stack_len - 1; if (n < 0 || !_is_op(E->stack[n]) || _op_name(E->stack[n]) != op) return -1; E->stack_len = n; return 0; } /* pop ops with precedence > prec */ static int _gr_parse_pop_prec(gr_parse_t E, slong prec) { slong n, n1, n2, n3, p, l1, l3; slong sz = E->R->sizeof_elem; if (E->stack_len < 1) return -1; again: n = E->stack_len; if (n < 2) return 0; n1 = E->stack[n-1]; n2 = E->stack[n-2]; if (_is_op(n1) || !_is_op(n2)) return 0; n1 = -1-n1; p = _op_prec(n2); if (p < prec) return 0; if (_op_fix(n2) == FIX_INFIX) { n3 = E->stack[n-3]; FLINT_ASSERT(!_is_op(n3)); n3 = -1 - n3; FLINT_ASSERT(n1 == n3 + 1); if (_op_name(n2) == OP_TIMES) { if (GR_SUCCESS != gr_mul(E->tmp, GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n1, sz), E->R)) { return -1; } gr_swap(GR_ENTRY(E->estore, n3, sz), E->tmp, E->R); E->estore_len -= 1; E->stack_len -= 2; } else if (_op_name(n2) == OP_PLUS) { if (E->flags & GR_PARSE_BALANCE_ADDITIONS) { l1 = E->size_func(GR_ENTRY(E->estore, n1, sz), E->R); l3 = E->size_func(GR_ENTRY(E->estore, n3, sz), E->R); } else { l1 = l3 = 0; } do_plus: if (l1 > l3) { FLINT_SWAP(slong, l3, l1); gr_swap(GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n1, sz), E->R); } if (p > prec || 2*l1 >= l3) { if (GR_SUCCESS != gr_add(GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n1, sz), E->R)) { return -1; } E->estore_len -= 1; E->stack_len -= 2; } else { return 0; } } else if (_op_name(n2) == OP_MINUS) { if (E->flags & GR_PARSE_BALANCE_ADDITIONS) { l1 = E->size_func(GR_ENTRY(E->estore, n1, sz), E->R); l3 = E->size_func(GR_ENTRY(E->estore, n3, sz), E->R); } else { l1 = l3 = 0; } if (4*l1 >= l3 || 4*l3 >= l1) { if (GR_SUCCESS != gr_sub(GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n1, sz), E->R)) { return -1; } E->estore_len -= 1; E->stack_len -= 2; } else { if (GR_SUCCESS != gr_neg(GR_ENTRY(E->estore, n1, sz), GR_ENTRY(E->estore, n1, sz), E->R)) { return -1; } E->stack[n-2] = _op_make(OP_PLUS, FIX_INFIX, PREC_PLUS); goto do_plus; } } else if (_op_name(n2) == OP_DIVIDES) { /* NOTE: if divides and times have the same precedence and the multiplications were to be delayed as the addition are, then there would have to be more shenenigans here. */ if (GR_SUCCESS != gr_div(E->tmp, GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n1, sz), E->R)) { return -1; } gr_swap(GR_ENTRY(E->estore, n3, sz), E->tmp, E->R); E->estore_len -= 1; E->stack_len -= 2; } else if (_op_name(n2) == OP_POWER) { if (GR_SUCCESS != gr_pow(E->tmp, GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n1, sz), E->R)) { return -1; } gr_swap(GR_ENTRY(E->estore, n3, sz), E->tmp, E->R); E->estore_len -= 1; E->stack_len -= 2; } else if (_op_name(n2) == OP_PLUSMINUS) { if (GR_SUCCESS != gr_set_interval_mid_rad(E->tmp, GR_ENTRY(E->estore, n3, sz), GR_ENTRY(E->estore, n1, sz), E->R)) { return -1; } gr_swap(GR_ENTRY(E->estore, n3, sz), E->tmp, E->R); E->estore_len -= 1; E->stack_len -= 2; } else { flint_throw(FLINT_ERROR, "_pop_stack: internal error"); } goto again; } else if (_op_fix(n2) == FIX_PREFIX) { if (_op_name(n2) == OP_MINUS) { if (GR_SUCCESS != gr_neg(GR_ENTRY(E->estore, n1, sz), GR_ENTRY(E->estore, n1, sz), E->R)) return -1; } else if (_op_name(n2) == OP_PLUSMINUS) { gr_ptr zero; GR_TMP_INIT(zero, E->R); if (GR_SUCCESS != gr_set_interval_mid_rad(GR_ENTRY(E->estore, n1, sz), zero, GR_ENTRY(E->estore, n1, sz), E->R)) { GR_TMP_CLEAR(zero, E->R); return -1; } GR_TMP_CLEAR(zero, E->R); } E->stack[n-2] = -1-n1; E->stack_len -= 1; goto again; } else { return 0; } } static const char * _parse_int(fmpz_t c, const char * s, const char * end) { char * buffer, * v; const char * send = s + 1; TMP_INIT; while (send < end && '0' <= *send && *send <= '9') send++; switch (send - s) { case 1: fmpz_set_ui(c, s[0] - '0'); s += 1; break; case 2: fmpz_set_ui(c, (s[0] - '0') * 10 + (s[1] - '0')); s += 2; break; case 3: fmpz_set_ui(c, (s[0] - '0') * 100 + (s[1] - '0') * 10 + (s[2] - '0')); s += 3; break; default: TMP_START; v = buffer = (char *) TMP_ALLOC((send - s + 1)*sizeof(char)); while (s < send) *v++ = *s++; *v++ = '\0'; fmpz_set_str(c, buffer, 10); TMP_END; } return s; } FLINT_FORCE_INLINE int is_digit(int c) { return '0' <= c && c <= '9'; } static const char * _parse_decimal(fmpz_t c, fmpz_t d, const char * s, const char * end) { char * buffer; slong int_digits = 1; slong frac_digits = 0; slong exp_digits = 0; slong i; int exp_minus = 0; const char * s_frac = s; const char * s_exp = s; TMP_INIT; TMP_START; while (s + int_digits < end && is_digit(s[int_digits])) int_digits++; s_frac = s + int_digits; if (s_frac < end && s_frac[0] == '.') { /* skip the . */ s_frac++; frac_digits = 0; while (s_frac + frac_digits < end && is_digit(s_frac[frac_digits])) frac_digits++; s_exp = s_frac + frac_digits; } else { s_exp = s + int_digits; } if (s_exp + 1 < end && (s_exp[0] == 'e' || s_exp[0] == 'E') && (is_digit(s_exp[1]) || (s_exp + 2 < end && (s_exp[1] == '+' || s_exp[1] == '-') && is_digit(s_exp[2])))) { /* skip the e or E */ s_exp++; if (s_exp[0] == '-') { exp_minus = 1; s_exp++; } else if (s_exp[0] == '+') { s_exp++; } exp_digits = 1; while (s_exp + exp_digits < end && is_digit(s_exp[exp_digits])) exp_digits++; } buffer = TMP_ALLOC((FLINT_MAX(int_digits + frac_digits, exp_digits) + 1) * sizeof(char)); if (exp_digits) { for (i = 0; i < exp_digits; i++) buffer[i] = s_exp[i]; buffer[exp_digits] = '\0'; fmpz_set_str(d, buffer, 10); if (exp_minus) fmpz_neg(d, d); } else { fmpz_zero(d); } for (i = 0; i < int_digits; i++) buffer[i] = s[i]; if (frac_digits) { for (i = 0; i < frac_digits; i++) buffer[int_digits + i] = s_frac[i]; fmpz_sub_ui(d, d, frac_digits); } buffer[int_digits + frac_digits] = '\0'; fmpz_set_str(c, buffer, 10); TMP_END; return s_exp + exp_digits; } int _gr_parse_parse(gr_parse_t E, void * poly, const char * s, slong slen) { const char * send = s + slen; fmpz_t c, d; int ret; fmpz_init(c); fmpz_init(d); E->tmp = poly; while (s < send) { if ('0' <= *s && *s <= '9') { #if 1 s = _parse_decimal(c, d, s, send); if (fmpz_is_zero(d)) { if (GR_SUCCESS != gr_set_fmpz(E->tmp, c, E->R)) goto failed; if (_gr_parse_push_expr(E)) goto failed; } else { if (GR_SUCCESS != gr_set_fmpz_10exp_fmpz(E->tmp, c, d, E->R)) goto failed; if (_gr_parse_push_expr(E)) goto failed; } #else s = _parse_int(c, s, send); if (GR_SUCCESS != gr_set_fmpz(E->tmp, c, E->R)) goto failed; if (_gr_parse_push_expr(E)) goto failed; #endif } else if (*s == '^') { if (E->flags & GR_PARSE_RING_EXPONENTS) { if (!gr_parse_top_is_expr(E)) goto failed; if (_gr_parse_pop_prec(E, PREC_POWER)) goto failed; _gr_parse_push_op(E, _op_make(OP_POWER, FIX_INFIX, PREC_POWER)); s++; } else { if (++s >= send || !('0' <= *s && *s <= '9')) goto failed; s = _parse_int(c, s, send); if (_gr_parse_pop_prec(E, PREC_POWER)) goto failed; if (!gr_parse_top_is_expr(E)) goto failed; if (GR_SUCCESS != gr_pow_fmpz(gr_parse_top_expr(E), gr_parse_top_expr(E), c, E->R)) goto failed; } } else if (*s == '*') { if (!gr_parse_top_is_expr(E)) goto failed; if (_gr_parse_pop_prec(E, PREC_TIMES)) goto failed; _gr_parse_push_op(E, _op_make(OP_TIMES, FIX_INFIX, PREC_TIMES)); s++; } else if (*s == '+') { if (s + 2 < send && s[1] == '/' && s[2] == '-') { if (!gr_parse_top_is_expr(E)) { _gr_parse_push_op(E, _op_make(OP_PLUSMINUS, FIX_PREFIX, PREC_UPLUSMINUS)); } else { if (_gr_parse_pop_prec(E, PREC_PLUSMINUS)) goto failed; _gr_parse_push_op(E, _op_make(OP_PLUSMINUS, FIX_INFIX, PREC_PLUSMINUS)); } s += 3; } else { if (!gr_parse_top_is_expr(E)) { _gr_parse_push_op(E, _op_make(OP_PLUS, FIX_PREFIX, PREC_UPLUS)); } else { if (_gr_parse_pop_prec(E, PREC_PLUS)) goto failed; _gr_parse_push_op(E, _op_make(OP_PLUS, FIX_INFIX, PREC_PLUS)); } s++; } } else if (*s == '-') { if (!gr_parse_top_is_expr(E)) { _gr_parse_push_op(E, _op_make(OP_MINUS, FIX_PREFIX, PREC_UMINUS)); } else { if (_gr_parse_pop_prec(E, PREC_MINUS)) goto failed; _gr_parse_push_op(E, _op_make(OP_MINUS, FIX_INFIX, PREC_MINUS)); } s++; } else if (*s == '/') { if (!gr_parse_top_is_expr(E)) goto failed; if (_gr_parse_pop_prec(E, PREC_DIVIDES)) goto failed; _gr_parse_push_op(E, _op_make(OP_DIVIDES, FIX_INFIX, PREC_DIVIDES)); s++; } else if (*s == ' ') { s++; } else if (*s == '(' || *s == '[') { if (gr_parse_top_is_expr(E)) goto failed; _gr_parse_push_op(E, _op_make(OP_LROUND, FIX_MATCHFIX, PREC_LOWEST)); s++; } else if (*s == ')' || *s == ']') { if (_gr_parse_pop_prec(E, PREC_LOWEST)) goto failed; if (_gr_parse_pop_expr(E)) goto failed; if (_gr_parse_pop_op(E, OP_LROUND)) goto failed; if (_gr_parse_push_expr(E)) goto failed; s++; } else { slong k; for (k = 0; k < E->terminals_len; k++) { slong l = E->terminal_strings[k].str_len; if (0 == strncmp(s, E->terminal_strings[k].str, l)) { GR_MUST_SUCCEED(gr_set(E->tmp, GR_ENTRY(E->terminal_values, k, E->R->sizeof_elem), E->R)); if (_gr_parse_push_expr(E)) goto failed; s += l; goto continue_outer; } } /* some builtin constants (for R and C) */ /* todo: builtin functions */ if (0 == strncmp(s, "pi", 2) || 0 == strncmp(s, "Pi", 2)) { if (GR_SUCCESS != gr_pi(E->tmp, E->R)) goto failed; if (_gr_parse_push_expr(E)) goto failed; s += 2; goto continue_outer; } if (0 == strncmp(s, "i", 1) || 0 == strncmp(s, "I", 1)) { if (GR_SUCCESS != gr_i(E->tmp, E->R)) goto failed; if (_gr_parse_push_expr(E)) goto failed; s += 1; goto continue_outer; } goto failed; } continue_outer:; } if (_gr_parse_pop_prec(E, PREC_LOWEST)) goto failed; if (_gr_parse_pop_expr(E)) goto failed; if (E->stack_len != 0) goto failed; ret = 0; done: fmpz_clear(c); fmpz_clear(d); return ret; failed: ret = -1; goto done; } int gr_generic_set_str_expr(gr_ptr res, const char * s, int flags, gr_ctx_t ctx) { gr_parse_t parse; gr_vec_t gens; slong i; char * g; int status; /* Quickly see if we simply have an integer literal, e.g. 0 */ fmpz_t c; fmpz_init(c); if (!fmpz_set_str(c, s, 10)) { status = gr_set_fmpz(res, c, ctx); } else { parse->R = ctx; _gr_parse_init(parse); parse->flags = flags; gr_vec_init(gens, 0, ctx); if (gr_gens_recursive(gens, ctx) == GR_SUCCESS) { for (i = 0; i < gens->length; i++) { GR_MUST_SUCCEED(gr_get_str(&g, gr_vec_entry_srcptr(gens, i, ctx), ctx)); /* todo: version that consumes s and x */ _gr_parse_add_terminal(parse, g, gr_vec_entry_srcptr(gens, i, ctx)); flint_free(g); } } gr_vec_clear(gens, ctx); status = _gr_parse_parse(parse, res, s, strlen(s)) ? GR_UNABLE : GR_SUCCESS; _gr_parse_clear(parse); } fmpz_clear(c); return status; } int gr_generic_set_str(gr_ptr res, const char * s, gr_ctx_t ctx) { return gr_generic_set_str_expr(res, s, 0, ctx); } int gr_generic_set_str_balance_additions(gr_ptr res, const char * s, gr_ctx_t ctx) { return gr_generic_set_str_expr(res, s, GR_PARSE_BALANCE_ADDITIONS, ctx); } int gr_generic_set_str_ring_exponents(gr_ptr res, const char * s, gr_ctx_t ctx) { return gr_generic_set_str_expr(res, s, GR_PARSE_RING_EXPONENTS, ctx); } flint-3.1.3/src/gr_generic/test/000077500000000000000000000000001461254215100165055ustar00rootroot00000000000000flint-3.1.3/src/gr_generic/test/main.c000066400000000000000000000017551461254215100176050ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_poly.h" #include "fmpz_mpoly.h" #include "gr_generic.h" /* Include functions *********************************************************/ #include "t-fmpz_mpoly_evaluate.c" #include "t-fmpz_poly_evaluate.c" #include "t-pow.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(gr_generic_fmpz_mpoly_evaluate), TEST_FUNCTION(gr_generic_fmpz_poly_evaluate), TEST_FUNCTION(gr_generic_pow) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/gr_generic/test/t-fmpz_mpoly_evaluate.c000066400000000000000000000064151461254215100232020ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" #include "gr.h" #include "gr_vec.h" #include "gr_generic.h" TEST_FUNCTION_START(gr_generic_fmpz_mpoly_evaluate, state) { slong iter; slong count_success = 0, count_unable = 0, count_domain = 0; for (iter = 0; iter < 10000; iter++) { int status = GR_SUCCESS; gr_ctx_t ctx; slong i, n; fmpz_mpoly_ctx_t mctx; fmpz_mpoly_t f, g, h; gr_ptr x; gr_ptr fx, gx, hx, y; slong sz; gr_ctx_init_random(ctx, state); sz = ctx->sizeof_elem; n = 1 + n_randint(state, 5); fmpz_mpoly_ctx_init(mctx, n, ORD_LEX); fmpz_mpoly_init(f, mctx); fmpz_mpoly_init(g, mctx); fmpz_mpoly_init(h, mctx); x = gr_heap_init_vec(n, ctx); fx = gr_heap_init(ctx); gx = gr_heap_init(ctx); hx = gr_heap_init(ctx); y = gr_heap_init(ctx); status |= _gr_vec_randtest(x, state, n, ctx); fmpz_mpoly_randtest_bound(f, state, 1 + n_randint(state, 30), 10, 1 + n_randint(state, 6), mctx); fmpz_mpoly_randtest_bound(g, state, 1 + n_randint(state, 30), 10, 1 + n_randint(state, 6), mctx); fmpz_mpoly_add(h, f, g, mctx); status |= gr_fmpz_mpoly_evaluate(fx, f, x, mctx, ctx); status |= gr_fmpz_mpoly_evaluate(gx, g, x, mctx, ctx); status |= gr_fmpz_mpoly_evaluate(hx, h, x, mctx, ctx); status |= gr_add(y, fx, gx, ctx); if (status == GR_SUCCESS && gr_equal(y, hx, ctx) == T_FALSE) { flint_printf("FAIL!\n"); flint_printf("f = "); fmpz_mpoly_print_pretty(f, NULL, mctx); flint_printf("\n\n"); flint_printf("g = "); fmpz_mpoly_print_pretty(g, NULL, mctx); flint_printf("\n\n"); flint_printf("h = "); fmpz_mpoly_print_pretty(h, NULL, mctx); flint_printf("\n\n"); for (i = 0; i < n; i++) { flint_printf("x%wd = ", i + 1); gr_print(GR_ENTRY(x, i, sz), ctx); flint_printf("\n\n"); } flint_printf("fx = "); gr_print(fx, ctx); flint_printf("\n\n"); flint_printf("gx = "); gr_print(gx, ctx); flint_printf("\n\n"); flint_printf("hx = "); gr_print(hx, ctx); flint_printf("\n\n"); flint_printf("y = "); gr_print(y, ctx); flint_printf("\n\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); fmpz_mpoly_clear(f, mctx); fmpz_mpoly_clear(g, mctx); fmpz_mpoly_clear(h, mctx); fmpz_mpoly_ctx_clear(mctx); gr_heap_clear_vec(x, n, ctx); gr_heap_clear(fx, ctx); gr_heap_clear(gx, ctx); gr_heap_clear(hx, ctx); gr_heap_clear(y, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_generic/test/t-fmpz_poly_evaluate.c000066400000000000000000000073031461254215100230220ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_poly.h" #include "gr.h" #include "gr_vec.h" #include "gr_generic.h" static int evaluate(flint_rand_t state, gr_ptr res, const fmpz_poly_t f, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; switch (n_randint(state, 4)) { case 0: status |= gr_fmpz_poly_evaluate(res, f, x, ctx); break; case 1: status |= gr_set(res, x, ctx); status |= gr_fmpz_poly_evaluate(res, f, res, ctx); break; case 2: status |= gr_fmpz_poly_evaluate_horner(res, f, x, ctx); break; case 3: status |= gr_set(res, x, ctx); status |= gr_fmpz_poly_evaluate_horner(res, f, res, ctx); break; case 4: status |= gr_fmpz_poly_evaluate_rectangular(res, f, x, ctx); break; default: status |= gr_set(res, x, ctx); status |= gr_fmpz_poly_evaluate_rectangular(res, f, res, ctx); break; } return status; } TEST_FUNCTION_START(gr_generic_fmpz_poly_evaluate, state) { slong iter; slong count_success = 0, count_unable = 0, count_domain = 0; for (iter = 0; iter < 10000; iter++) { int status = GR_SUCCESS; gr_ctx_t ctx; fmpz_poly_t f, g, h; gr_ptr x; gr_ptr fx, gx, hx, y; gr_ctx_init_random(ctx, state); fmpz_poly_init(f); fmpz_poly_init(g); fmpz_poly_init(h); x = gr_heap_init(ctx); fx = gr_heap_init(ctx); gx = gr_heap_init(ctx); hx = gr_heap_init(ctx); y = gr_heap_init(ctx); GR_MUST_SUCCEED(gr_randtest(x, state, ctx)); fmpz_poly_randtest(f, state, 1 + n_randint(state, 30), 1 + n_randint(state, 100)); fmpz_poly_randtest(g, state, 1 + n_randint(state, 30), 1 + n_randint(state, 100)); fmpz_poly_add(h, f, g); status |= evaluate(state, fx, f, x, ctx); status |= evaluate(state, gx, g, x, ctx); status |= evaluate(state, hx, h, x, ctx); status |= gr_add(y, fx, gx, ctx); if (status == GR_SUCCESS && gr_equal(y, hx, ctx) == T_FALSE) { flint_printf("FAIL!\n"); flint_printf("f = "); fmpz_poly_print(f); flint_printf("\n\n"); flint_printf("g = "); fmpz_poly_print(g); flint_printf("\n\n"); flint_printf("h = "); fmpz_poly_print(h); flint_printf("\n\n"); flint_printf("x = "); gr_print(x, ctx); flint_printf("\n\n"); flint_printf("fx = "); gr_print(fx, ctx); flint_printf("\n\n"); flint_printf("gx = "); gr_print(gx, ctx); flint_printf("\n\n"); flint_printf("hx = "); gr_print(hx, ctx); flint_printf("\n\n"); flint_printf("y = "); gr_print(y, ctx); flint_printf("\n\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); gr_heap_clear(x, ctx); gr_heap_clear(fx, ctx); gr_heap_clear(gx, ctx); gr_heap_clear(hx, ctx); gr_heap_clear(y, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_generic/test/t-pow.c000066400000000000000000000047371461254215100177320ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "ulong_extras.h" #include "gr.h" #include "gr_generic.h" /* todo: have a proper interface to test a given powering function */ int gr_test_pow_ui_exponent_addition(gr_ctx_t R, flint_rand_t state, int test_flags); int gr_test_pow_ui_base_scalar_multiplication(gr_ctx_t R, flint_rand_t state, int test_flags); int gr_test_pow_ui_base_multiplication(gr_ctx_t R, flint_rand_t state, int test_flags); int gr_test_pow_ui_aliasing(gr_ctx_t R, flint_rand_t state, int test_flags); int gr_test_pow_fmpz_exponent_addition(gr_ctx_t R, flint_rand_t state, int test_flags); TEST_FUNCTION_START(gr_generic_pow, state) { gr_ctx_t ZZn; ulong n; fmpz_t m; int status = GR_SUCCESS; for (n = 0; n < 1000 * flint_test_multiplier(); n++) { fmpz_init(m); fmpz_randtest_not_zero(m, state, 100); fmpz_abs(m, m); gr_ctx_init_fmpz_mod(ZZn, m); ZZn->methods[GR_METHOD_POW_UI] = (gr_funcptr) gr_generic_pow_ui_binexp; ZZn->methods[GR_METHOD_POW_FMPZ] = (gr_funcptr) gr_generic_pow_fmpz_binexp; status |= gr_test_pow_ui_exponent_addition(ZZn, state, 0); status |= gr_test_pow_ui_base_scalar_multiplication(ZZn, state, 0); status |= gr_test_pow_ui_base_multiplication(ZZn, state, 0); status |= gr_test_pow_ui_aliasing(ZZn, state, 0); status |= gr_test_pow_fmpz_exponent_addition(ZZn, state, 0); ZZn->methods[GR_METHOD_POW_UI] = (gr_funcptr) gr_generic_pow_ui_sliding; ZZn->methods[GR_METHOD_POW_FMPZ] = (gr_funcptr) gr_generic_pow_fmpz_sliding; status |= gr_test_pow_ui_exponent_addition(ZZn, state, 0); status |= gr_test_pow_ui_base_scalar_multiplication(ZZn, state, 0); status |= gr_test_pow_ui_base_multiplication(ZZn, state, 0); status |= gr_test_pow_ui_aliasing(ZZn, state, 0); status |= gr_test_pow_fmpz_exponent_addition(ZZn, state, 0); if (status & GR_TEST_FAIL) { fflush(stdout); flint_abort(); } gr_ctx_clear(ZZn); fmpz_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat.h000066400000000000000000000414401461254215100150470ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GR_MAT_H #define GR_MAT_H #ifdef GR_MAT_INLINES_C #define GR_MAT_INLINE #else #define GR_MAT_INLINE static inline #endif #include "gr.h" #include "gr_poly.h" #ifdef __cplusplus extern "C" { #endif typedef struct { gr_ptr entries; slong r; slong c; gr_ptr * rows; } gr_mat_struct; typedef gr_mat_struct gr_mat_t[1]; #define GR_MAT_ENTRY(mat,i,j,sz) GR_ENTRY((mat)->rows[i], j, sz) #define gr_mat_nrows(mat, ctx) ((mat)->r) #define gr_mat_ncols(mat, ctx) ((mat)->c) GR_MAT_INLINE gr_ptr gr_mat_entry_ptr(gr_mat_t mat, slong i, slong j, gr_ctx_t ctx) { return GR_MAT_ENTRY(mat, i, j, ctx->sizeof_elem); } GR_MAT_INLINE gr_srcptr gr_mat_entry_srcptr(const gr_mat_t mat, slong i, slong j, gr_ctx_t ctx) { return GR_MAT_ENTRY(mat, i, j, ctx->sizeof_elem); } /* Generics */ typedef int ((*gr_method_mat_unary_op_get_scalar)(gr_ptr, const gr_mat_t, gr_ctx_ptr)); typedef int ((*gr_method_mat_unary_op)(gr_mat_t, const gr_mat_t, gr_ctx_ptr)); typedef int ((*gr_method_mat_binary_op)(gr_mat_t, const gr_mat_t, const gr_mat_t, gr_ctx_ptr)); typedef int ((*gr_method_mat_pivot_op)(slong *, gr_mat_t, slong, slong, slong, gr_ctx_ptr)); typedef int ((*gr_method_mat_diagonalization_op)(gr_vec_t, gr_mat_t, gr_mat_t, const gr_mat_t, int, gr_ctx_ptr)); typedef int ((*gr_method_mat_lu_op)(slong *, slong *, gr_mat_t, const gr_mat_t, int, gr_ctx_ptr)); #define GR_MAT_UNARY_OP_GET_SCALAR(ctx, NAME) (((gr_method_mat_unary_op_get_scalar *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_MAT_UNARY_OP(ctx, NAME) (((gr_method_mat_unary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_MAT_BINARY_OP(ctx, NAME) (((gr_method_mat_binary_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_MAT_PIVOT_OP(ctx, NAME) (((gr_method_mat_pivot_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_MAT_DIAGONALIZATION_OP(ctx, NAME) (((gr_method_mat_diagonalization_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_MAT_LU_OP(ctx, NAME) (((gr_method_mat_lu_op *) ctx->methods)[GR_METHOD_ ## NAME]) void gr_mat_init(gr_mat_t mat, slong rows, slong cols, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_init_set(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx); void gr_mat_clear(gr_mat_t mat, gr_ctx_t ctx); GR_MAT_INLINE void gr_mat_swap(gr_mat_t mat1, gr_mat_t mat2, gr_ctx_t ctx) { FLINT_SWAP(gr_mat_struct, *mat1, *mat2); } WARN_UNUSED_RESULT int gr_mat_swap_rows(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_invert_rows(gr_mat_t mat, slong * perm, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_swap_cols(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_invert_cols(gr_mat_t mat, slong * perm, gr_ctx_t ctx); void gr_mat_window_init(gr_mat_t window, const gr_mat_t mat, slong r1, slong c1, slong r2, slong c2, gr_ctx_t ctx); GR_MAT_INLINE void gr_mat_window_clear(gr_mat_t window, gr_ctx_t ctx) { flint_free(window->rows); } WARN_UNUSED_RESULT int gr_mat_concat_horizontal(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_concat_vertical(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx); int gr_mat_write(gr_stream_t out, const gr_mat_t mat, gr_ctx_t ctx); int gr_mat_print(const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_randtest(gr_mat_t mat, flint_rand_t state, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_randops(gr_mat_t mat, flint_rand_t state, slong count, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_randpermdiag(int * parity, gr_mat_t mat, flint_rand_t state, gr_ptr diag, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_randrank(gr_mat_t mat, flint_rand_t state, slong rank, gr_ctx_t ctx); GR_MAT_INLINE truth_t gr_mat_is_empty(const gr_mat_t mat, gr_ctx_t ctx) { return ((mat->r == 0) || (mat->c == 0)) ? T_TRUE : T_FALSE; } GR_MAT_INLINE truth_t gr_mat_is_square(const gr_mat_t mat, gr_ctx_t ctx) { return (mat->r == mat->c) ? T_TRUE : T_FALSE; } truth_t gr_mat_equal(const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx); truth_t gr_mat_is_zero(const gr_mat_t mat, gr_ctx_t ctx); truth_t gr_mat_is_one(const gr_mat_t mat, gr_ctx_t ctx); truth_t gr_mat_is_neg_one(const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_zero(gr_mat_t res, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_one(gr_mat_t res, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_scalar(gr_mat_t res, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_ui(gr_mat_t res, ulong v, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_si(gr_mat_t res, slong v, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_fmpz(gr_mat_t res, const fmpz_t v, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_fmpq(gr_mat_t res, const fmpq_t v, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_fmpz_mat(gr_mat_t res, const fmpz_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_fmpq_mat(gr_mat_t res, const fmpq_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_neg(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_swap_entrywise(gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_add(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_sub(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx); /* todo: test, wrap; div; more conversions */ WARN_UNUSED_RESULT int gr_mat_add_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_sub_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_mul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_addmul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_submul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_div_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_mul_classical(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_mul_strassen(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_mul_generic(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_mul(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); /* todo */ GR_MAT_INLINE WARN_UNUSED_RESULT int gr_mat_sqr(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { return gr_mat_mul(res, mat, mat, ctx); } WARN_UNUSED_RESULT int _gr_mat_gr_poly_evaluate(gr_mat_t y, gr_srcptr poly, slong len, const gr_mat_t x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_gr_poly_evaluate(gr_mat_t res, const gr_poly_t f, const gr_mat_t a, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_find_nonzero_pivot_large_abs(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_find_nonzero_pivot_generic(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_find_nonzero_pivot(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_lu_recursive(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_lu_classical(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_lu_generic(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_lu(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_fflu(slong * res_rank, slong * P, gr_mat_t LU, gr_ptr den, const gr_mat_t A, int rank_check, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_fflu(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_lu(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_fflu_precomp(gr_mat_t X, const slong * perm, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_lu_precomp(gr_mat_t X, const slong * perm, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_den_fflu(gr_mat_t X, gr_ptr den, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_den(gr_mat_t X, gr_ptr den, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_solve_field(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det_berkowitz(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det_fflu(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det_lu(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det_cofactor(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det_generic_field(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det_generic_integral_domain(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det_generic(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_det(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_inv(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_adjugate_charpoly(gr_mat_t adj, gr_ptr det, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_adjugate_cofactor(gr_mat_t adj, gr_ptr det, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_adjugate(gr_mat_t adj, gr_ptr det, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rank_lu(slong * rank, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rank_fflu(slong * rank, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rank(slong * rank, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rref_lu(slong * res_rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rref_fflu(slong * res_rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rref(slong * res_rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rref_den_fflu(slong * res_rank, gr_mat_t R, gr_ptr den, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_rref_den(slong * res_rank, gr_mat_t R, gr_ptr den, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nullspace(gr_mat_t X, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_ones(gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_pascal(gr_mat_t mat, int triangular, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_stirling(gr_mat_t mat, int kind, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_hilbert(gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_hadamard(gr_mat_t mat, gr_ctx_t ctx); /* todo: dft, dct */ WARN_UNUSED_RESULT int gr_mat_transpose(gr_mat_t B, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_tril_classical(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_tril_recursive(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_tril(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_triu_classical(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_triu_recursive(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_nonsingular_solve_triu(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_trace(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_berkowitz(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly_berkowitz(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_danilevsky_inplace(gr_ptr res, gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_danilevsky(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly_danilevsky(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_faddeev(gr_ptr res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly_faddeev(gr_poly_t res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_faddeev_bsgs(gr_ptr res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly_faddeev_bsgs(gr_poly_t res, gr_mat_t adj, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_from_hessenberg(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly_from_hessenberg(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_gauss(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly_gauss(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly_householder(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly_householder(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_mat_charpoly(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_charpoly(gr_poly_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_hessenberg(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_hessenberg_gauss(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_hessenberg_householder(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx); truth_t gr_mat_is_hessenberg(const gr_mat_t mat, gr_ctx_t ctx); int gr_mat_reduce_row(slong * column, gr_mat_t A, slong * P, slong * L, slong m, gr_ctx_t ctx); int gr_mat_apply_row_similarity(gr_mat_t A, slong r, gr_ptr d, gr_ctx_t ctx); int gr_mat_minpoly_field(gr_poly_t p, const gr_mat_t X, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_eigenvalues(gr_vec_t lambda, gr_vec_t mult, const gr_mat_t mat, int flags, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_eigenvalues_other(gr_vec_t lambda, gr_vec_t mult, const gr_mat_t mat, gr_ctx_t mat_ctx, int flags, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_diagonalization_precomp(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, const gr_vec_t eigenvalues, const gr_vec_t mult, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_diagonalization_generic(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, int flags, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_diagonalization(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, int flags, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_set_jordan_blocks(gr_mat_t mat, const gr_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_jordan_blocks(gr_vec_t lambda, slong * num_blocks, slong * block_lambda, slong * block_size, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_jordan_transformation(gr_mat_t mat, const gr_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_jordan_form(gr_mat_t J, gr_mat_t P, const gr_mat_t A, gr_ctx_t ctx); truth_t gr_mat_is_scalar(const gr_mat_t mat, gr_ctx_t ctx); truth_t gr_mat_is_diagonal(const gr_mat_t mat, gr_ctx_t ctx); truth_t gr_mat_is_lower_triangular(const gr_mat_t mat, gr_ctx_t ctx); truth_t gr_mat_is_upper_triangular(const gr_mat_t mat, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_mul_diag(gr_mat_t C, const gr_mat_t A, const gr_vec_t D, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_diag_mul(gr_mat_t C, const gr_vec_t D, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_exp_jordan(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_exp(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_log_jordan(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_mat_log(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/gr_mat/000077500000000000000000000000001461254215100146735ustar00rootroot00000000000000flint-3.1.3/src/gr_mat/add.c000066400000000000000000000017231461254215100155720ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_add(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { int status; slong i, r, c; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (r != gr_mat_nrows(mat1, ctx) || c != gr_mat_ncols(mat1, ctx) || r != gr_mat_nrows(mat2, ctx) || c != gr_mat_ncols(mat2, ctx)) { return GR_DOMAIN; } status = GR_SUCCESS; for (i = 0; i < r; i++) { status |= _gr_vec_add(res->rows[i], mat1->rows[i], mat2->rows[i], c, ctx); } return status; } flint-3.1.3/src/gr_mat/add_scalar.c000066400000000000000000000023601461254215100171150ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_add_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx) { slong i, j, r, c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (res == mat) { for (i = 0; i < FLINT_MIN(r, c); i++) status |= gr_add(GR_MAT_ENTRY(res, i, i, sz), GR_MAT_ENTRY(res, i, i, sz), x, ctx); } else { for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { /* todo: vectorize */ if (i == j) status |= gr_add(GR_MAT_ENTRY(res, i, j, sz), GR_MAT_ENTRY(mat, i, j, sz), x, ctx); else status |= gr_set(GR_MAT_ENTRY(res, i, j, sz), GR_MAT_ENTRY(mat, i, j, sz), ctx); } } } return status; } flint-3.1.3/src/gr_mat/addmul_scalar.c000066400000000000000000000014141461254215100176320ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_addmul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx) { slong i, r, c; int status = GR_SUCCESS; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (c != 0) for (i = 0; i < r; i++) status |= _gr_vec_addmul_scalar(res->rows[i], mat->rows[i], c, x, ctx); return status; } flint-3.1.3/src/gr_mat/adjugate.c000066400000000000000000000012101461254215100166150ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_adjugate(gr_mat_t adj, gr_ptr det, const gr_mat_t A, gr_ctx_t ctx) { if (gr_mat_nrows(A, ctx) <= 5) return gr_mat_adjugate_cofactor(adj, det, A, ctx); else return gr_mat_adjugate_charpoly(adj, det, A, ctx); } flint-3.1.3/src/gr_mat/adjugate_charpoly.c000066400000000000000000000023601461254215100205250ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_adjugate_charpoly(gr_mat_t adj, gr_ptr det, const gr_mat_t A, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_ptr pol; slong n; slong sz = ctx->sizeof_elem; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) return GR_DOMAIN; if (n == 0) { return gr_one(det, ctx); } else { GR_TMP_INIT_VEC(pol, n + 1, ctx); status |= _gr_mat_charpoly(pol, A, ctx); if (n % 2) status |= gr_neg(det, pol, ctx); else gr_swap(det, pol, ctx); /* todo: verify that _gr_mat_gr_poly_evaluate supports aliasing */ status |= _gr_mat_gr_poly_evaluate(adj, GR_ENTRY(pol, 1, sz), n, A, ctx); if (n % 2 == 0) status |= gr_mat_neg(adj, adj, ctx); GR_TMP_CLEAR_VEC(pol, n + 1, ctx); } return status; } flint-3.1.3/src/gr_mat/adjugate_cofactor.c000066400000000000000000000054621461254215100205120ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_adjugate_cofactor(gr_mat_t adj, gr_ptr det, const gr_mat_t A, gr_ctx_t ctx) { gr_mat_t T; slong i, j, n, a, b; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) return GR_DOMAIN; if (n == 0) { status |= gr_one(det, ctx); return status; } if (n == 1) { status |= gr_set(det, GR_MAT_ENTRY(A, 0, 0, sz), ctx); status |= gr_one(GR_MAT_ENTRY(adj, 0, 0, sz), ctx); return status; } if (n == 2) { gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_mul(t, GR_MAT_ENTRY(A, 0, 0, sz), GR_MAT_ENTRY(A, 1, 1, sz), ctx); status |= gr_mul(u, GR_MAT_ENTRY(A, 0, 1, sz), GR_MAT_ENTRY(A, 1, 0, sz), ctx); status |= gr_set(GR_MAT_ENTRY(adj, 0, 0, sz), GR_MAT_ENTRY(A, 1, 1, sz), ctx); status |= gr_neg(GR_MAT_ENTRY(adj, 0, 1, sz), GR_MAT_ENTRY(A, 0, 1, sz), ctx); status |= gr_neg(GR_MAT_ENTRY(adj, 1, 0, sz), GR_MAT_ENTRY(A, 1, 0, sz), ctx); status |= gr_set(GR_MAT_ENTRY(adj, 1, 1, sz), GR_MAT_ENTRY(A, 0, 0, sz), ctx); status |= gr_sub(det, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } if (adj == A) { gr_mat_init(T, n, n, ctx); status |= gr_mat_adjugate_cofactor(T, det, A, ctx); gr_mat_swap(adj, T, ctx); gr_mat_clear(T, ctx); return status; } /* todo: shallow copies */ gr_mat_init(T, n - 1, n - 1, ctx); status |= gr_zero(det, ctx); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { for (a = 0; a < n; a++) { for (b = 0; b < n; b++) { if (a != i && b != j) { status |= gr_set(GR_MAT_ENTRY(T, a - (a > i), b - (b > j), sz), GR_MAT_ENTRY(A, a, b, sz), ctx); } } } status |= gr_mat_det(GR_MAT_ENTRY(adj, i, j, sz), T, ctx); if ((i + j) & 1) status |= gr_neg(GR_MAT_ENTRY(adj, i, j, sz), GR_MAT_ENTRY(adj, i, j, sz), ctx); if (i == 0) { status |= gr_addmul(det, GR_MAT_ENTRY(adj, i, j, sz), GR_MAT_ENTRY(A, i, j, sz), ctx); } } } status |= gr_mat_transpose(adj, adj, ctx); gr_mat_clear(T, ctx); return status; } flint-3.1.3/src/gr_mat/apply_row_similarity.c000066400000000000000000000023621461254215100213240ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_apply_row_similarity(gr_mat_t A, slong r, gr_ptr d, gr_ctx_t ctx) { int status = GR_SUCCESS; slong n = A->r, i, j; slong sz = ctx->sizeof_elem; if (A->r != A->c || r < 0 || r > A->r) return GR_DOMAIN; for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) status |= gr_addmul(GR_MAT_ENTRY(A, i, j, sz), GR_MAT_ENTRY(A, i, r, sz), d, ctx); for (j = r + 1; j < n; j++) status |= gr_addmul(GR_MAT_ENTRY(A, i, j, sz), GR_MAT_ENTRY(A, i, r, sz), d, ctx); } for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) status |= gr_submul(GR_MAT_ENTRY(A, r, i, sz), GR_MAT_ENTRY(A, j, i, sz), d, ctx); for (j = r + 1; j < n; j++) status |= gr_submul(GR_MAT_ENTRY(A, r, i, sz), GR_MAT_ENTRY(A, j, i, sz), d, ctx); } return status; } flint-3.1.3/src/gr_mat/charpoly.c000066400000000000000000000016501461254215100166620ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: algorithm selection */ int _gr_mat_charpoly(gr_ptr cp, const gr_mat_t mat, gr_ctx_t ctx) { return _gr_mat_charpoly_berkowitz(cp, mat, ctx); } int gr_mat_charpoly(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx) { int status; if (mat->r != mat->c) return GR_DOMAIN; gr_poly_fit_length(cp, mat->r + 1, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly(cp->coeffs, mat, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } flint-3.1.3/src/gr_mat/charpoly_berkowitz.c000066400000000000000000000061321461254215100207620ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int _gr_mat_charpoly_berkowitz(gr_ptr cp, const gr_mat_t mat, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; slong n = mat->r; int status; status = GR_SUCCESS; if (n == 0) { status |= gr_one(cp, ctx); } else if (n == 1) { status |= gr_neg(cp, mat->rows[0], ctx); status |= gr_one(GR_ENTRY(cp, 1, sz), ctx); } else if (n == 2) { status |= gr_mat_det_cofactor(cp, mat, ctx); status |= gr_add(GR_ENTRY(cp, 1, sz), GR_MAT_ENTRY(mat, 0, 0, sz), GR_MAT_ENTRY(mat, 1, 1, sz), ctx); status |= gr_neg(GR_ENTRY(cp, 1, sz), GR_ENTRY(cp, 1, sz), ctx); status |= gr_one(GR_ENTRY(cp, 2, sz), ctx); } else { slong i, k, t; gr_ptr a, A, s; GR_TMP_INIT_VEC(a, n * n, ctx); A = GR_ENTRY(a, (n - 1) * n, sz); status |= _gr_vec_zero(cp, n + 1, ctx); status |= gr_neg(cp, GR_MAT_ENTRY(mat, 0, 0, sz), ctx); for (t = 1; t < n; t++) { for (i = 0; i <= t; i++) { status |= gr_set(GR_ENTRY(a, 0 * n + i, sz), GR_MAT_ENTRY(mat, i, t, sz), ctx); } status |= gr_set(A, GR_MAT_ENTRY(mat, t, t, sz), ctx); for (k = 1; k < t; k++) { for (i = 0; i <= t; i++) { s = GR_ENTRY(a, k * n + i, sz); status |= _gr_vec_dot(s, NULL, 0, mat->rows[i], GR_ENTRY(a, (k - 1) * n, sz), t + 1, ctx); } status |= gr_set(GR_ENTRY(A, k, sz), GR_ENTRY(a, k * n + t, sz), ctx); } status |= _gr_vec_dot(GR_ENTRY(A, t, sz), NULL, 0, mat->rows[t], GR_ENTRY(a, (t - 1) * n, sz), t + 1, ctx); for (k = 0; k <= t; k++) { status |= _gr_vec_dot_rev(GR_ENTRY(cp, k, sz), GR_ENTRY(cp, k, sz), 1, A, cp, k, ctx); status |= gr_sub(GR_ENTRY(cp, k, sz), GR_ENTRY(cp, k, sz), GR_ENTRY(A, k, sz), ctx); } } /* Shift all coefficients up by one */ for (i = n; i > 0; i--) gr_swap(GR_ENTRY(cp, i, sz), GR_ENTRY(cp, (i - 1), sz), ctx); status |= gr_one(cp, ctx); status |= _gr_poly_reverse(cp, cp, n + 1, n + 1, ctx); GR_TMP_CLEAR_VEC(a, n * n, ctx); } return status; } int gr_mat_charpoly_berkowitz(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx) { int status; if (mat->r != mat->c) return GR_DOMAIN; gr_poly_fit_length(cp, mat->r + 1, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly_berkowitz(cp->coeffs, mat, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } flint-3.1.3/src/gr_mat/charpoly_danilevsky.c000066400000000000000000000162731461254215100211220ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" #include "gr_poly.h" int gr_generic_addmul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); /* todo: use dot products */ int _gr_mat_charpoly_danilevsky_inplace(gr_ptr p, gr_mat_t A, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); gr_method_binary_op addmul = GR_BINARY_OP(ctx, ADDMUL); slong n, n_input; slong i, j, k; gr_ptr V, W, T; gr_ptr t, b; gr_ptr c, h; truth_t is_zero; slong plen; slong sz = ctx->sizeof_elem; int have_addmul; int status = GR_SUCCESS; #define MAT_ENTRY(i, j) GR_MAT_ENTRY(A, i, j, sz) #define POL_ENTRY(i) GR_ENTRY(p, i, sz) have_addmul = (addmul != (gr_method_binary_op) gr_generic_addmul); #define ADDMUL(z, x, y) \ if (have_addmul) \ { \ status |= addmul(z, x, y, ctx); \ } \ else \ { \ status |= mul(c, x, y, ctx); \ status |= add(z, z, c, ctx); \ } \ n = n_input = A->r; if (n == 0) return gr_one(POL_ENTRY(0), ctx); if (n == 1) { status |= gr_neg(POL_ENTRY(0), MAT_ENTRY(0, 0), ctx); status |= gr_one(POL_ENTRY(1), ctx); return status; } GR_TMP_INIT2(c, h, ctx); GR_TMP_INIT_VEC(t, n_input + 1, ctx); GR_TMP_INIT_VEC(b, n_input + 1, ctx); GR_TMP_INIT_VEC(V, n_input, ctx); GR_TMP_INIT_VEC(W, n_input, ctx); GR_TMP_INIT_VEC(T, n_input, ctx); status |= gr_one(p, ctx); i = 1; plen = 1; while (i < n) { status |= gr_set(h, MAT_ENTRY(n - i, n - i - 1), ctx); while (1) { is_zero = gr_is_zero(h, ctx); if (is_zero == T_FALSE) break; if (is_zero == T_UNKNOWN) { status = GR_UNABLE; goto cleanup; } k = 1; while (k < n - i) { is_zero = gr_is_zero(MAT_ENTRY(n - i, n - i - k - 1), ctx); if (is_zero == T_FALSE) break; if (is_zero == T_UNKNOWN) { status = GR_UNABLE; goto cleanup; } k++; } if (k == n - i) { status |= gr_one(GR_ENTRY(b, i, sz), ctx); for (k = 1; k <= i; k++) status |= gr_neg(GR_ENTRY(b, k - 1, sz), MAT_ENTRY(n - i, n - k), ctx); status |= _gr_poly_mul(t, p, plen, b, i + 1, ctx); plen += i; _gr_vec_swap(p, t, plen, ctx); n -= i; i = 1; if (n == 1) { status |= gr_one(GR_ENTRY(b, 1, sz), ctx); status |= gr_neg(b, MAT_ENTRY(0, 0), ctx); status |= _gr_poly_mul(t, p, plen, b, 2, ctx); plen += 1; _gr_vec_swap(p, t, plen, ctx); goto cleanup; } } else { gr_ptr ptr; ptr = A->rows[n - i - k - 1]; A->rows[n - i - k - 1] = A->rows[n - i - 1]; A->rows[n - i - 1] = ptr; for (j = 1; j <= n - i + 1; j++) { gr_swap(MAT_ENTRY(j - 1, n - i - k - 1), MAT_ENTRY(j - 1, n - i - 1), ctx); } } status |= gr_set(h, MAT_ENTRY(n - i, n - i - 1), ctx); } status |= gr_neg(h, h, ctx); status |= gr_inv(h, h, ctx); if (status != GR_SUCCESS) goto cleanup; for (j = 1; j <= n; j++) { status |= mul(GR_ENTRY(V, j - 1, sz), MAT_ENTRY(n - i, j - 1), h, ctx); status |= gr_set(GR_ENTRY(W, j - 1, sz), MAT_ENTRY(n - i, j - 1), ctx); } status |= gr_neg(h, h, ctx); for (j = 1; j <= n - i; j++) { for (k = 1; k <= n - i - 1; k++) { ADDMUL(MAT_ENTRY(j - 1, k - 1), MAT_ENTRY(j - 1, n - i - 1), GR_ENTRY(V, k - 1, sz)) } for (k = n - i + 1; k <= n; k++) { ADDMUL(MAT_ENTRY(j - 1, k - 1), MAT_ENTRY(j - 1, n - i - 1), GR_ENTRY(V, k - 1, sz)) } status |= mul(MAT_ENTRY(j - 1, n - i - 1), MAT_ENTRY(j - 1, n - i - 1), h, ctx); } /* todo: rewrite as dot */ for (j = 1; j <= n - i - 1; j++) { status |= mul(MAT_ENTRY(n - i - 1, j - 1), MAT_ENTRY(n - i - 1, j - 1), GR_ENTRY(W, n - i - 1, sz), ctx); for (k = 1; k < n - i; k++) { ADDMUL(MAT_ENTRY(n - i - 1, j - 1), MAT_ENTRY(k - 1, j - 1), GR_ENTRY(W, k - 1, sz)) } } /* todo: rewrite as dot */ for (j = n - i; j <= n - 1; j++) { status |= mul(MAT_ENTRY(n - i - 1, j - 1), MAT_ENTRY(n - i - 1, j - 1), GR_ENTRY(W, n - i - 1, sz), ctx); for (k = 1; k < n - i; k++) { ADDMUL(MAT_ENTRY(n - i - 1, j - 1), MAT_ENTRY(k - 1, j - 1), GR_ENTRY(W, k - 1, sz)) } status |= add(MAT_ENTRY(n - i - 1, j - 1), MAT_ENTRY(n - i - 1, j - 1), GR_ENTRY(W, j, sz), ctx); } status |= mul(MAT_ENTRY(n - i - 1, n - 1), MAT_ENTRY(n - i - 1, n - 1), GR_ENTRY(W, n - i - 1, sz), ctx); /* todo: rewrite as dot */ for (k = 1; k < n - i; k++) { ADDMUL(MAT_ENTRY(n - i - 1, n - 1), MAT_ENTRY(k - 1, n - 1), GR_ENTRY(W, k - 1, sz)) } i++; } status |= gr_one(GR_ENTRY(b, n, sz), ctx); for (i = 1; i <= n; i++) status |= gr_neg(GR_ENTRY(b, i - 1, sz), MAT_ENTRY(0, n - i), ctx); status |= _gr_poly_mul(t, p, plen, b, n + 1, ctx); plen += n; _gr_vec_swap(p, t, plen, ctx); cleanup: GR_TMP_CLEAR2(c, h, ctx); GR_TMP_CLEAR_VEC(t, n_input + 1, ctx); GR_TMP_CLEAR_VEC(b, n_input + 1, ctx); GR_TMP_CLEAR_VEC(V, n_input, ctx); GR_TMP_CLEAR_VEC(W, n_input, ctx); GR_TMP_CLEAR_VEC(T, n_input, ctx); return status; } int _gr_mat_charpoly_danilevsky(gr_ptr p, const gr_mat_t mat, gr_ctx_t ctx) { gr_mat_t T; int status = GR_SUCCESS; if (mat->r != mat->c) return GR_DOMAIN; gr_mat_init(T, mat->r, mat->c, ctx); status |= gr_mat_set(T, mat, ctx); status |= _gr_mat_charpoly_danilevsky_inplace(p, T, ctx); gr_mat_clear(T, ctx); return status; } int gr_mat_charpoly_danilevsky(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx) { int status; gr_poly_fit_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly_danilevsky(cp->coeffs, mat, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } flint-3.1.3/src/gr_mat/charpoly_faddeev.c000066400000000000000000000045651461254215100203500ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: when adj != A, could save memory by using as temporary */ int _gr_mat_charpoly_faddeev(gr_ptr c, gr_mat_t adj, const gr_mat_t A, gr_ctx_t ctx) { gr_mat_t B, C; slong n, k; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; n = A->r; if (n == 0) return gr_one(c, ctx); if (n == 1) { status |= gr_neg(c, GR_MAT_ENTRY(A, 0, 0, sz), ctx); status |= gr_one(GR_ENTRY(c, 1, sz), ctx); if (adj != NULL) status |= gr_mat_one(adj, ctx); return status; } gr_mat_init(B, n, n, ctx); gr_mat_init(C, n, n, ctx); status |= gr_one(GR_ENTRY(c, n, sz), ctx); status |= gr_mat_trace(GR_ENTRY(c, n - 1, sz), A, ctx); status |= gr_neg(GR_ENTRY(c, n - 1, sz), GR_ENTRY(c, n - 1, sz), ctx); status |= gr_mat_add_scalar(B, A, GR_ENTRY(c, n - 1, sz), ctx); for (k = 2; k < n; k++) { status |= gr_mat_mul(C, A, B, ctx); status |= gr_mat_trace(GR_ENTRY(c, n - k, sz), C, ctx); status |= gr_div_si(GR_ENTRY(c, n - k, sz), GR_ENTRY(c, n - k, sz), -k, ctx); if (status != GR_SUCCESS) goto cleanup; status |= gr_mat_add_scalar(B, C, GR_ENTRY(c, n - k, sz), ctx); } status |= gr_mat_mul(C, A, B, ctx); status |= gr_mat_trace(c, C, ctx); status |= gr_div_si(c, c, -n, ctx); if (adj != NULL) { if (n % 2) status |= gr_mat_set(adj, B, ctx); else status |= gr_mat_neg(adj, B, ctx); } cleanup: gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); return status; } int gr_mat_charpoly_faddeev(gr_poly_t cp, gr_mat_t adjugate, const gr_mat_t mat, gr_ctx_t ctx) { int status; if (mat->r != mat->c) return GR_DOMAIN; gr_poly_fit_length(cp, mat->r + 1, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly_faddeev(cp->coeffs, adjugate, mat, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } flint-3.1.3/src/gr_mat/charpoly_faddeev_bsgs.c000066400000000000000000000114101461254215100213510ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "gr_vec.h" #include "gr_mat.h" static int gr_mat_trace_prod(gr_ptr res, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong n, i, j; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; n = A->r; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (i == 0 && j == 0) status |= gr_mul(res, GR_MAT_ENTRY(A, 0, 0, sz), GR_MAT_ENTRY(B, 0, 0, sz), ctx); else status |= gr_addmul(res, GR_MAT_ENTRY(A, i, j, sz), GR_MAT_ENTRY(B, j, i, sz), ctx); } } return status; } static int gr_mat_trace_prod2(gr_ptr res, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong n, i; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; n = A->r; for (i = 0; i < n; i++) status |= _gr_vec_dot(res, ((i == 0) ? NULL : res), 0, GR_MAT_ENTRY(A, i, 0, sz), GR_MAT_ENTRY(B, i, 0, sz), n, ctx); return status; } int _gr_mat_charpoly_faddeev_bsgs(gr_ptr c, gr_mat_t adj, const gr_mat_t A, gr_ctx_t ctx) { gr_mat_t B, C; gr_ptr t; gr_mat_struct * Apow; slong n, m, k, j, i, m_orig; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; n = A->r; if (n == 0) return gr_one(c, ctx); if (n == 1) { status |= gr_neg(c, GR_MAT_ENTRY(A, 0, 0, sz), ctx); status |= gr_one(GR_ENTRY(c, 1, sz), ctx); if (adj != NULL) status |= gr_mat_one(adj, ctx); return status; } m_orig = m = n_sqrt(n); Apow = flint_malloc(sizeof(gr_mat_struct) * (m + 1)); t = flint_malloc(sz * (m + 1)); _gr_vec_init(t, m + 1, ctx); for (k = 0; k <= m; k++) gr_mat_init(Apow + k, n, n, ctx); status |= gr_mat_set(Apow + 1, A, ctx); for (k = 2; k <= m; k++) status |= gr_mat_mul(Apow + k, Apow + k - 1, Apow + 1, ctx); for (k = 1; k <= m; k++) status |= gr_mat_trace(GR_ENTRY(t, k, sz), Apow + k, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(C, n, n, ctx); status |= gr_one(GR_ENTRY(c, n, sz), ctx); status |= gr_mat_trace(GR_ENTRY(c, n - 1, sz), A, ctx); status |= gr_neg(GR_ENTRY(c, n - 1, sz), GR_ENTRY(c, n - 1, sz), ctx); status |= gr_mat_add_scalar(B, A, GR_ENTRY(c, n - 1, sz), ctx); k = 2; while (k <= n - 1) { m = FLINT_MIN(m, n - k); status |= gr_mat_transpose(B, B, ctx); status |= gr_mat_trace_prod2(GR_ENTRY(c, n - k, sz), A, B, ctx); status |= gr_div_si(GR_ENTRY(c, n - k, sz), GR_ENTRY(c, n - k, sz), -k, ctx); if (status != GR_SUCCESS) goto cleanup; for (j = 1; j < m; j++) { status |= gr_mat_trace_prod2(GR_ENTRY(c, n - k - j, sz), Apow + j + 1, B, ctx); for (i = 0; i < j; i++) status |= gr_addmul(GR_ENTRY(c, n - k - j, sz), GR_ENTRY(t, j - i, sz), GR_ENTRY(c, n - k - i, sz), ctx); status |= gr_div_si(GR_ENTRY(c, n - k - j, sz), GR_ENTRY(c, n - k - j, sz), -k - j, ctx); if (status != GR_SUCCESS) goto cleanup; } status |= gr_mat_transpose(B, B, ctx); status |= gr_mat_mul(C, Apow + m, B, ctx); gr_mat_swap(B, C, ctx); for (j = 0; j < m; j++) { if (m - j - 1 == 0) status |= gr_mat_add_scalar(B, B, GR_ENTRY(c, n - k - j, sz), ctx); else status |= gr_mat_addmul_scalar(B, Apow + m - j - 1, GR_ENTRY(c, n - k - j, sz), ctx); } k += m; } status |= gr_mat_trace_prod(c, A, B, ctx); status |= gr_div_si(c, c, -n, ctx); if (adj != NULL) { if (n % 2) status |= gr_mat_set(adj, B, ctx); else status |= gr_mat_neg(adj, B, ctx); } cleanup: for (k = 0; k <= m_orig; k++) gr_mat_clear(Apow + k, ctx); flint_free(Apow); _gr_vec_clear(t, m_orig + 1, ctx); flint_free(t); gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); return status; } int gr_mat_charpoly_faddeev_bsgs(gr_poly_t cp, gr_mat_t adjugate, const gr_mat_t mat, gr_ctx_t ctx) { int status; if (mat->r != mat->c) return GR_DOMAIN; gr_poly_fit_length(cp, mat->r + 1, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly_faddeev_bsgs(cp->coeffs, adjugate, mat, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } flint-3.1.3/src/gr_mat/charpoly_hessenberg.c000066400000000000000000000076671461254215100211050ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" #include "gr_poly.h" /* todo: optimize; rewrite using underscore methods */ int _gr_mat_charpoly_from_hessenberg(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) { slong n; gr_poly_struct * P; gr_poly_t x, v; gr_ptr t, u; slong i, m; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; n = mat->r; gr_poly_init(x, ctx); gr_poly_init(v, ctx); GR_TMP_INIT2(t, u, ctx); P = flint_malloc(sizeof(gr_poly_struct) * (n + 1)); for (i = 0; i <= n; i++) gr_poly_init(P + i, ctx); status |= gr_poly_one(P, ctx); status |= gr_poly_set_coeff_si(x, 1, 1, ctx); for (m = 1; m <= n; m++) { /* P[m] = (x - A[m-1, m-1])*P[m-1] */ status |= gr_poly_set_scalar(v, GR_MAT_ENTRY(mat, m - 1, m - 1, sz), ctx); status |= gr_poly_sub(v, x, v, ctx); status |= gr_poly_mul(P + m, v, P + m - 1, ctx); status |= gr_one(t, ctx); for (i = 1; i < m; i++) { status |= gr_mul(t, t, GR_MAT_ENTRY(mat, m - i + 1 - 1, m - i - 1, sz), ctx); status |= gr_poly_mul_scalar(v, P + m - i - 1, GR_MAT_ENTRY(mat, m - i - 1, m - 1, sz), ctx); status |= gr_poly_mul_scalar(v, v, t, ctx); status |= gr_poly_sub(P + m, P + m, v, ctx); } } /* for the zero ring (?) */ status |= _gr_vec_zero(res, n + 1, ctx); /* res = P[n] */ status |= _gr_vec_set(res, (P + n)->coeffs, FLINT_MIN(n + 1, (P + n)->length), ctx); for (i = 0; i <= n; i++) gr_poly_clear(P + i, ctx); flint_free(P); gr_poly_clear(x, ctx); gr_poly_clear(v, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } int gr_mat_charpoly_from_hessenberg(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx) { int status; if (mat->r != mat->c) return GR_DOMAIN; gr_poly_fit_length(cp, mat->r + 1, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly_from_hessenberg(cp->coeffs, mat, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } int _gr_mat_charpoly_gauss(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) { gr_mat_t t; int status; gr_mat_init(t, mat->r, mat->r, ctx); status = gr_mat_hessenberg_gauss(t, mat, ctx); if (status == GR_SUCCESS) status = _gr_mat_charpoly_from_hessenberg(res, t, ctx); gr_mat_clear(t, ctx); return status; } int gr_mat_charpoly_gauss(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx) { int status; if (mat->r != mat->c) return GR_DOMAIN; gr_poly_fit_length(cp, mat->r + 1, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly_gauss(cp->coeffs, mat, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } int _gr_mat_charpoly_householder(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) { gr_mat_t t; int status; gr_mat_init(t, mat->r, mat->r, ctx); status = gr_mat_hessenberg_householder(t, mat, ctx); if (status == GR_SUCCESS) status = _gr_mat_charpoly_from_hessenberg(res, t, ctx); gr_mat_clear(t, ctx); return status; } int gr_mat_charpoly_householder(gr_poly_t cp, const gr_mat_t mat, gr_ctx_t ctx) { int status; if (mat->r != mat->c) return GR_DOMAIN; gr_poly_fit_length(cp, mat->r + 1, ctx); _gr_poly_set_length(cp, mat->r + 1, ctx); status = _gr_mat_charpoly_householder(cp->coeffs, mat, ctx); _gr_poly_normalise(cp, ctx); /* only needed for the zero ring */ return status; } flint-3.1.3/src/gr_mat/clear.c000066400000000000000000000012621461254215100161260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" void gr_mat_clear(gr_mat_t mat, gr_ctx_t ctx) { if (mat->entries != NULL) { _gr_vec_clear(mat->entries, mat->r * mat->c, ctx); flint_free(mat->entries); flint_free(mat->rows); } else if (mat->r != 0) { flint_free(mat->rows); } } flint-3.1.3/src/gr_mat/concat_horizontal.c000066400000000000000000000020021461254215100205510ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_concat_horizontal(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i; slong r1 = mat1->r; slong c1 = mat1->c; slong c2 = mat2->c; slong sz = ctx->sizeof_elem; if (mat1->r != mat2->r || res->c != mat1->c + mat2->c) return GR_DOMAIN; for (i = 0; i < r1; i++) { if (c1 > 0) status |= _gr_vec_set(res->rows[i], mat1->rows[i], c1, ctx); if (c2 > 0) status |= _gr_vec_set(GR_ENTRY(res->rows[i], c1, sz), mat2->rows[i], c2, ctx); } return status; } flint-3.1.3/src/gr_mat/concat_vertical.c000066400000000000000000000017371461254215100202070ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_concat_vertical(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; if (mat1->c != mat2->c || res->r != mat1->r + mat2->r) return GR_DOMAIN; if (c1 > 0) { for (i = 0; i < r1; i++) status |= _gr_vec_set(res->rows[i], mat1->rows[i], c1, ctx); for (i = 0; i < r2; i++) status |= _gr_vec_set(res->rows[i + r1], mat2->rows[i], c1, ctx); } return status; } flint-3.1.3/src/gr_mat/det.c000066400000000000000000000021641461254215100156160ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_det_generic_field(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) { if (A->r <= 4) return gr_mat_det_cofactor(res, A, ctx); else return gr_mat_det_lu(res, A, ctx); } int gr_mat_det_generic_integral_domain(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) { if (A->r <= 4) return gr_mat_det_cofactor(res, A, ctx); else return gr_mat_det_fflu(res, A, ctx); } int gr_mat_det_generic(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) { if (A->r <= 4) return gr_mat_det_cofactor(res, A, ctx); else return gr_mat_det_berkowitz(res, A, ctx); } int gr_mat_det(gr_ptr res, const gr_mat_t x, gr_ctx_t ctx) { return GR_MAT_UNARY_OP_GET_SCALAR(ctx, MAT_DET)(res, x, ctx); } flint-3.1.3/src/gr_mat/det_berkowitz.c000066400000000000000000000014131461254215100177120ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_det_berkowitz(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) { gr_ptr t; slong n; int status = GR_SUCCESS; n = A->r; GR_TMP_INIT_VEC(t, n + 1, ctx); status |= _gr_mat_charpoly_berkowitz(t, A, ctx); gr_swap(res, t, ctx); if (n % 2) status |= gr_neg(res, res, ctx); GR_TMP_CLEAR_VEC(t, n + 1, ctx); return status; } flint-3.1.3/src/gr_mat/det_cofactor.c000066400000000000000000000071621461254215100175010ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" #define E(i,j) GR_MAT_ENTRY(A, i, j, sz) /* todo: use provided addmul/fmms */ static int gr_fmms(gr_ptr x, gr_ptr tmp, const gr_ptr a, const gr_ptr b, const gr_ptr c, const gr_ptr d, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_mul(tmp, a, b, ctx); status |= gr_mul(x, c, d, ctx); status |= gr_sub(x, tmp, x, ctx); return status; } static int _gr_addmul(gr_ptr x, gr_ptr tmp, const gr_ptr a, const gr_ptr b, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_mul(tmp, a, b, ctx); status |= gr_add(x, x, tmp, ctx); return status; } static int _gr_mat_det_2x2(gr_ptr det, const gr_mat_t A, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_ptr t; slong sz = ctx->sizeof_elem; GR_TMP_INIT(t, ctx); status |= gr_fmms(det, t, E(0,0), E(1,1), E(0,1), E(1,0), ctx); GR_TMP_CLEAR(t, ctx); return status; } static int _gr_mat_det_cofactor_3x3(gr_ptr det, const gr_mat_t A, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_ptr t, u; slong sz = ctx->sizeof_elem; GR_TMP_INIT2(t, u, ctx); status |= gr_fmms(t, u, E(1,0), E(2,1), E(1,1), E(2,0), ctx); status |= gr_mul(det, t, E(0,2), ctx); status |= gr_fmms(t, u, E(1,2), E(2,0), E(1,0), E(2,2), ctx); status |= _gr_addmul(det, u, t, E(0,1), ctx); status |= gr_fmms(t, u, E(1,1), E(2,2), E(1,2), E(2,1), ctx); status |= _gr_addmul(det, u, t, E(0,0), ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } static int _gr_mat_det_cofactor_4x4(gr_ptr det, const gr_mat_t A, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_ptr a, b, t; slong sz = ctx->sizeof_elem; GR_TMP_INIT3(a, b, t, ctx); status |= gr_fmms(a, t, E(0,3), E(1,2), E(0,2), E(1,3), ctx); status |= gr_fmms(b, t, E(2,1), E(3,0), E(2,0), E(3,1), ctx); status |= gr_mul(det, a, b, ctx); status |= gr_fmms(a, t, E(0,1), E(1,3), E(0,3), E(1,1), ctx); status |= gr_fmms(b, t, E(2,2), E(3,0), E(2,0), E(3,2), ctx); status |= _gr_addmul(det, t, a, b, ctx); status |= gr_fmms(a, t, E(0,2), E(1,1), E(0,1), E(1,2), ctx); status |= gr_fmms(b, t, E(2,3), E(3,0), E(2,0), E(3,3), ctx); status |= _gr_addmul(det, t, a, b, ctx); status |= gr_fmms(a, t, E(0,3), E(1,0), E(0,0), E(1,3), ctx); status |= gr_fmms(b, t, E(2,2), E(3,1), E(2,1), E(3,2), ctx); status |= _gr_addmul(det, t, a, b, ctx); status |= gr_fmms(a, t, E(0,0), E(1,2), E(0,2), E(1,0), ctx); status |= gr_fmms(b, t, E(2,3), E(3,1), E(2,1), E(3,3), ctx); status |= _gr_addmul(det, t, a, b, ctx); status |= gr_fmms(a, t, E(0,1), E(1,0), E(0,0), E(1,1), ctx); status |= gr_fmms(b, t, E(2,3), E(3,2), E(2,2), E(3,3), ctx); status |= _gr_addmul(det, t, a, b, ctx); GR_TMP_CLEAR3(a, b, t, ctx); return status; } int gr_mat_det_cofactor(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) { slong n; n = A->r; if (n != A->c) return GR_DOMAIN; if (n == 0) return gr_one(res, ctx); else if (n == 1) return gr_set(res, A->rows[0], ctx); else if (n == 2) return _gr_mat_det_2x2(res, A, ctx); else if (n == 3) return _gr_mat_det_cofactor_3x3(res, A, ctx); else if (n == 4) return _gr_mat_det_cofactor_4x4(res, A, ctx); else return GR_UNABLE; } flint-3.1.3/src/gr_mat/det_fflu.c000066400000000000000000000022231461254215100166260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_det_fflu(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) { slong * P; gr_mat_t T; slong n, rank; int status; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) return GR_DOMAIN; if (n == 0) return gr_one(res, ctx); P = _perm_init(n); gr_mat_init(T, n, n, ctx); status = gr_mat_fflu(&rank, P, T, res, A, 1, ctx); if (status == GR_SUCCESS) { if (rank == 0) { status |= gr_zero(res, ctx); } else { if (_perm_parity(P, n)) status |= gr_neg(res, res, ctx); } } else { status |= GR_UNABLE; } gr_mat_clear(T, ctx); _perm_clear(P); return status; } flint-3.1.3/src/gr_mat/det_lu.c000066400000000000000000000025531461254215100163200ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_det_lu(gr_ptr res, const gr_mat_t A, gr_ctx_t ctx) { slong * P; gr_mat_t T; slong n, rank; int status; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) return GR_DOMAIN; if (n == 0) return gr_one(res, ctx); P = _perm_init(n); gr_mat_init(T, n, n, ctx); status = gr_mat_lu(&rank, P, T, A, 1, ctx); if (status == GR_SUCCESS) { if (rank == 0) { status |= gr_zero(res, ctx); } else { slong i, sz = ctx->sizeof_elem; status |= gr_set(res, GR_MAT_ENTRY(T, 0, 0, sz), ctx); for (i = 1; i < n; i++) status |= gr_mul(res, res, GR_MAT_ENTRY(T, i, i, sz), ctx); if (_perm_parity(P, n)) status |= gr_neg(res, res, ctx); } } else { status |= GR_UNABLE; } gr_mat_clear(T, ctx); _perm_clear(P); return status; } flint-3.1.3/src/gr_mat/diag_mul.c000066400000000000000000000017051461254215100166230ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_diag_mul(gr_mat_t C, const gr_vec_t D, const gr_mat_t A, gr_ctx_t ctx) { slong ar, ac, i, sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_srcptr Dptr = D->entries; ar = gr_mat_nrows(A, ctx); ac = gr_mat_ncols(A, ctx); if (ac != D->length || ar != gr_mat_nrows(C, ctx) || ac != gr_mat_ncols(C, ctx)) return GR_DOMAIN; for (i = 0; i < ar; i++) status |= _gr_scalar_mul_vec(GR_MAT_ENTRY(C, i, 0, sz), GR_ENTRY(Dptr, i, sz), GR_MAT_ENTRY(A, i, 0, sz), ac, ctx); return status; } flint-3.1.3/src/gr_mat/diagonalization.c000066400000000000000000000065761461254215100202310ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_diagonalization_precomp(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, const gr_vec_t eigenvalues, const gr_vec_t mult, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_mat_t AIe, b; const fmpz * am = mult->entries; slong i, j, k, n; slong nullity, added, deg; if (gr_mat_is_square(A, ctx) != T_TRUE) return GR_DOMAIN; n = gr_mat_nrows(A, ctx); if (L != NULL && R == NULL) { gr_mat_t tmpR; gr_mat_init(tmpR, n, n, ctx); status = gr_mat_diagonalization_precomp(D, L, tmpR, A, eigenvalues, mult, ctx); gr_mat_clear(tmpR, ctx); return status; } gr_vec_set_length(D, n, ctx); /* todo: resize L, R if needed */ deg = 0; for (i = 0; i < eigenvalues->length; i++) deg += am[i]; if (deg != n) return GR_DOMAIN; gr_mat_init(AIe, n, n, ctx); gr_mat_init(b, 0, 0, ctx); status |= _gr_vec_zero(D->entries, n, ctx); added = 0; for (i = 0; i < eigenvalues->length; i++) { status |= gr_mat_set(AIe, A, ctx); for (j = 0; j < n; j++) status |= gr_sub(gr_mat_entry_ptr(AIe, j, j, ctx), gr_mat_entry_ptr(AIe, j, j, ctx), gr_vec_entry_ptr((gr_vec_struct *) eigenvalues, i, ctx), ctx); status |= gr_mat_nullspace(b, AIe, ctx); if (status != GR_SUCCESS) { status = GR_UNABLE; break; } nullity = gr_mat_ncols(b, ctx); if (nullity != am[i]) { status = GR_DOMAIN; break; } for (j = 0; j < am[i]; j++) { status |= gr_set(gr_vec_entry_ptr(D, added + j, ctx), gr_vec_entry_ptr((gr_vec_struct *) eigenvalues, i, ctx), ctx); if (R != NULL) { for (k = 0; k < n; k++) status |= gr_set(gr_mat_entry_ptr(R, k, added + j, ctx), gr_mat_entry_ptr(b, k, j, ctx), ctx); } } added += am[i]; } if (status == GR_SUCCESS && L != NULL) status = gr_mat_inv(L, R, ctx); gr_mat_clear(AIe, ctx); gr_mat_clear(b, ctx); return status; } int gr_mat_diagonalization_generic(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, int flags, gr_ctx_t ctx) { int status; gr_ctx_t ZZ; gr_vec_t eigenvalues, mult; if (gr_mat_is_square(A, ctx) != T_TRUE) return GR_DOMAIN; gr_ctx_init_fmpz(ZZ); gr_vec_init(eigenvalues, 0, ctx); gr_vec_init(mult, 0, ZZ); if (gr_mat_eigenvalues(eigenvalues, mult, A, flags, ctx) == GR_SUCCESS) { status = gr_mat_diagonalization_precomp(D, L, R, A, eigenvalues, mult, ctx); } else { status = GR_UNABLE; } gr_vec_clear(eigenvalues, ctx); gr_vec_clear(mult, ZZ); gr_ctx_clear(ZZ); return status; } int gr_mat_diagonalization(gr_vec_t D, gr_mat_t L, gr_mat_t R, const gr_mat_t A, int flags, gr_ctx_t ctx) { return GR_MAT_DIAGONALIZATION_OP(ctx, MAT_DIAGONALIZATION)(D, L, R, A, flags, ctx); } flint-3.1.3/src/gr_mat/div_scalar.c000066400000000000000000000016131461254215100171470ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: use a vector function; preinvert when appropriate */ int gr_mat_div_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx) { slong i, j, r, c; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (c != 0) for (i = 0; i < r; i++) for (j = 0; j < c; j++) status |= gr_div(GR_MAT_ENTRY(res, i, j, sz), GR_MAT_ENTRY(mat, i, j, sz), x, ctx); return status; } flint-3.1.3/src/gr_mat/eigenvalues.c000066400000000000000000000021701461254215100173460ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_eigenvalues(gr_vec_t lambda, gr_vec_t mult, const gr_mat_t mat, int flags, gr_ctx_t ctx) { int status; gr_poly_t cp; gr_poly_init(cp, ctx); status = gr_mat_charpoly(cp, mat, ctx); if (status == GR_SUCCESS) status = gr_poly_roots(lambda, mult, cp, 0, ctx); gr_poly_clear(cp, ctx); return status; } int gr_mat_eigenvalues_other(gr_vec_t lambda, gr_vec_t mult, const gr_mat_t mat, gr_ctx_t mat_ctx, int flags, gr_ctx_t ctx) { int status; gr_poly_t cp; gr_poly_init(cp, mat_ctx); status = gr_mat_charpoly(cp, mat, mat_ctx); if (status == GR_SUCCESS) status = gr_poly_roots_other(lambda, mult, cp, mat_ctx, 0, ctx); gr_poly_clear(cp, mat_ctx); return status; } flint-3.1.3/src/gr_mat/equal.c000066400000000000000000000020331461254215100161440ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" truth_t gr_mat_equal(const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { truth_t eq, this_eq; slong i, r, c; r = gr_mat_nrows(mat1, ctx); c = gr_mat_ncols(mat1, ctx); if (r != gr_mat_nrows(mat2, ctx) || c != gr_mat_ncols(mat2, ctx)) { return T_FALSE; } if (r == 0 || c == 0) return T_TRUE; eq = T_TRUE; for (i = 0; i < r; i++) { this_eq = _gr_vec_equal(mat1->rows[i], mat2->rows[i], c, ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } return eq; } flint-3.1.3/src/gr_mat/exp.c000066400000000000000000000056011461254215100156350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_mat.h" int gr_mat_exp_jordan(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i, j, len, n; gr_mat_t P, Q, J; gr_vec_t lambda, f_lambda; slong num_blocks, num_lambda, offset; slong * block_lambda, * block_size; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) return GR_DOMAIN; if (n == 0) return GR_SUCCESS; gr_mat_init(P, n, n, ctx); gr_mat_init(Q, n, n, ctx); gr_mat_init(J, n, n, ctx); block_lambda = flint_malloc(sizeof(slong) * n); block_size = flint_malloc(sizeof(slong) * n); gr_vec_init(lambda, 0, ctx); gr_vec_init(f_lambda, 0, ctx); status |= gr_mat_jordan_blocks(lambda, &num_blocks, block_lambda, block_size, A, ctx); if (status != GR_SUCCESS) goto cleanup; num_lambda = gr_vec_length(lambda, ctx); status |= gr_mat_jordan_transformation(P, lambda, num_blocks, block_lambda, block_size, A, ctx); if (status != GR_SUCCESS) goto cleanup; status |= gr_mat_inv(Q, P, ctx); if (status != GR_SUCCESS) goto cleanup; /* Evaluate Jordan blocks and build matrix */ gr_vec_set_length(f_lambda, num_lambda, ctx); for (i = 0; i < num_lambda && status == GR_SUCCESS; i++) status |= gr_exp(gr_vec_entry_ptr(f_lambda, i, ctx), gr_vec_entry_srcptr(lambda, i, ctx), ctx); offset = 0; for (i = 0; i < num_blocks; i++) { len = block_size[i]; status |= gr_set(gr_mat_entry_ptr(J, offset, offset, ctx), gr_vec_entry_srcptr(f_lambda, block_lambda[i], ctx), ctx); if (len > 1) { for (j = 1; j < len; j++) status |= gr_div_ui(gr_mat_entry_ptr(J, offset, offset + j, ctx), gr_mat_entry_srcptr(J, offset, offset + j - 1, ctx), FLINT_MAX(j, 1), ctx); for (j = 1; j < len; j++) status |= _gr_vec_set(gr_mat_entry_ptr(J, offset + j, offset + j, ctx), gr_mat_entry_srcptr(J, offset + j - 1, offset + j - 1, ctx), len - j, ctx); } offset += block_size[i]; } status |= gr_mat_mul(res, P, J, ctx); status |= gr_mat_mul(res, res, Q, ctx); cleanup: gr_mat_clear(P, ctx); gr_mat_clear(Q, ctx); gr_mat_clear(J, ctx); gr_vec_clear(lambda, ctx); gr_vec_clear(f_lambda, ctx); flint_free(block_lambda); flint_free(block_size); return status; } int gr_mat_exp(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) { return GR_MAT_UNARY_OP(ctx, MAT_EXP)(res, A, ctx); } flint-3.1.3/src/gr_mat/fflu.c000066400000000000000000000072451461254215100160030ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" static void _gr_mat_swap_rows(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx) { if (r != s) { gr_ptr u; slong t; if (perm != NULL) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } u = mat->rows[s]; mat->rows[s] = mat->rows[r]; mat->rows[r] = u; } } int gr_mat_fflu(slong * res_rank, slong * P, gr_mat_t LU, gr_ptr den, const gr_mat_t A, int rank_check, gr_ctx_t ctx) { gr_ptr d, e; gr_ptr * a; slong i, j, k, m, n, r, rank, row, col, sz; int status = GR_SUCCESS; int pivot_status; if (gr_mat_is_empty(A, ctx) == T_TRUE) { *res_rank = 0; return gr_one(den, ctx); } if (gr_ctx_is_integral_domain(ctx) != T_TRUE) return GR_UNABLE; GR_TMP_INIT2(d, e, ctx); m = gr_mat_nrows(A, ctx); n = gr_mat_ncols(A, ctx); sz = ctx->sizeof_elem; status |= gr_mat_set(LU, A, ctx); a = LU->rows; #define ENTRY(i, j) GR_ENTRY(a[i], j, sz) rank = row = col = 0; for (i = 0; i < m; i++) P[i] = i; gr_init(d, ctx); gr_init(e, ctx); while (row < m && col < n) { pivot_status = gr_mat_find_nonzero_pivot(&r, LU, row, m, col, ctx); /* We don't know whether there is a nonzero pivot element, so we can't determine the rank. */ if (pivot_status == GR_UNABLE) { status = GR_UNABLE; break; } /* There is certainly no nonzero pivot element. */ if (pivot_status == GR_DOMAIN) { /* We proved that the matrix is rank-deficient, accomplishing the goal. */ if (rank_check) { status = GR_SUCCESS; rank = 0; break; } /* Continue with next column. */ col++; continue; } rank++; if (r != row) _gr_mat_swap_rows(LU, P, row, r, ctx); /* Todo: when the pivot element is invertible, make use of that property. status |= gr_inv(d, GR_ENTRY(a[row], col, sz), ctx); if (status != GR_SUCCESS) break; */ for (j = row + 1; j < m; j++) { /* status |= gr_mul(e, ENTRY(j, col), d, ctx); status |= gr_neg(e, e, ctx); status |= _gr_vec_addmul_scalar(ENTRY(j, col + 1), ENTRY(row, col + 1), n - col - 1, e, ctx); status |= gr_zero(ENTRY(j, col), ctx); status |= gr_neg(ENTRY(j, rank - 1), e, ctx); */ for (k = col + 1; k < n; k++) { status |= gr_mul(ENTRY(j, k), ENTRY(j, k), ENTRY(row, col), ctx); status |= gr_mul(e, ENTRY(j, col), ENTRY(row, k), ctx); status |= gr_sub(ENTRY(j, k), ENTRY(j, k), e, ctx); if (row > 0) { status |= gr_divexact(ENTRY(j, k), ENTRY(j, k), den, ctx); if (status != GR_SUCCESS) goto cleanup; } } } status |= gr_set(den, ENTRY(row, col), ctx); row++; col++; } cleanup: GR_TMP_CLEAR2(d, e, ctx); *res_rank = rank; return status; } flint-3.1.3/src/gr_mat/find_nonzero_pivot.c000066400000000000000000000046731461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_find_nonzero_pivot_large_abs(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx) { slong best_row, i; int unknown; int cmp, comp_ok; truth_t is_zero; slong sz; if (end_row <= start_row) return GR_DOMAIN; best_row = -1; unknown = 0; sz = ctx->sizeof_elem; for (i = start_row; i < end_row; i++) { is_zero = gr_is_zero(GR_MAT_ENTRY(mat, i, column, sz), ctx); if (is_zero == T_FALSE) { if (best_row == -1) { best_row = i; } else { comp_ok = gr_cmpabs(&cmp, GR_MAT_ENTRY(mat, i, column, sz), GR_MAT_ENTRY(mat, best_row, column, sz), ctx); if (comp_ok == GR_SUCCESS && cmp > 0) best_row = i; } } if (is_zero == T_UNKNOWN) unknown = 1; } if (best_row == -1) { *pivot_row = -1; if (unknown) return GR_UNABLE; else return GR_DOMAIN; } else { *pivot_row = best_row; return GR_SUCCESS; } } int gr_mat_find_nonzero_pivot_generic(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx) { slong i; int unknown; truth_t is_zero; slong sz; if (end_row <= start_row) return GR_DOMAIN; unknown = 0; sz = ctx->sizeof_elem; for (i = start_row; i < end_row; i++) { is_zero = gr_is_zero(GR_MAT_ENTRY(mat, i, column, sz), ctx); if (is_zero == T_FALSE) { *pivot_row = i; return GR_SUCCESS; } if (is_zero == T_UNKNOWN) unknown = 1; } if (unknown) return GR_UNABLE; else return GR_DOMAIN; } int gr_mat_find_nonzero_pivot(slong * pivot_row, gr_mat_t mat, slong start_row, slong end_row, slong column, gr_ctx_t ctx) { return GR_MAT_PIVOT_OP(ctx, MAT_FIND_NONZERO_PIVOT)(pivot_row, mat, start_row, end_row, column, ctx); } flint-3.1.3/src/gr_mat/gr_poly_evaluate.c000066400000000000000000000050331461254215100204010ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "gr_mat.h" /* todo: rewrite scalar operations using dots? */ /* todo: other algorithms (+ memory efficiency) */ int _gr_mat_gr_poly_evaluate(gr_mat_t y, gr_srcptr poly, slong len, const gr_mat_t x, gr_ctx_t ctx) { slong i, j, m, r, n; gr_mat_struct * xs; gr_mat_t s, t; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; n = gr_mat_nrows(x, ctx); if (n != gr_mat_ncols(x, ctx)) return GR_DOMAIN; if (len == 0) { return gr_mat_zero(y, ctx); } if (len == 1) { return gr_mat_set_scalar(y, poly, ctx); } if (len == 2) { status |= gr_mat_mul_scalar(y, x, GR_ENTRY(poly, 1, sz), ctx); status |= gr_mat_add_scalar(y, y, poly, ctx); return status; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = flint_malloc(sizeof(gr_mat_struct) * (m + 1)); for (i = 0; i <= m; i++) { gr_mat_init(xs + i, n, n, ctx); if (i == 0) status |= gr_mat_one(xs + i, ctx); else if (i == 1) status |= gr_mat_set(xs + i, x, ctx); else status |= gr_mat_mul(xs + i, xs + i - 1, x, ctx); /* todo: squaring when that is better */ } gr_mat_init(s, n, n, ctx); gr_mat_init(t, n, n, ctx); status |= gr_mat_set_scalar(y, GR_ENTRY(poly, (r - 1) * m, sz), ctx); for (j = 1; (r - 1) * m + j < len; j++) status |= gr_mat_addmul_scalar(y, xs + j, GR_ENTRY(poly, (r - 1) * m + j, sz), ctx); for (i = r - 2; i >= 0; i--) { status |= gr_mat_set_scalar(s, GR_ENTRY(poly, i * m, sz), ctx); for (j = 1; j < m; j++) status |= gr_mat_addmul_scalar(s, xs + j, GR_ENTRY(poly, i * m + j, sz), ctx); status |= gr_mat_mul(y, y, xs + m, ctx); status |= gr_mat_add(y, y, s, ctx); } for (i = 0; i <= m; i++) gr_mat_clear(xs + i, ctx); flint_free(xs); gr_mat_clear(s, ctx); gr_mat_clear(t, ctx); return status; } int gr_mat_gr_poly_evaluate(gr_mat_t res, const gr_poly_t f, const gr_mat_t a, gr_ctx_t ctx) { return _gr_mat_gr_poly_evaluate(res, f->coeffs, f->length, a, ctx); } flint-3.1.3/src/gr_mat/hadamard.c000066400000000000000000000021131461254215100165750ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "gr_mat.h" /* todo: could reimplement the generic construction here, for reduced memory usage in small rings. todo: could wrap/reimplement fmpz_mat_is_hadamard */ int gr_mat_hadamard(gr_mat_t mat, gr_ctx_t ctx) { slong n; int status = GR_SUCCESS; fmpz_mat_t tmp; n = mat->r; if (n != mat->c) return GR_DOMAIN; if (n <= 1) return gr_mat_one(mat, ctx); if (n > 2 && n % 4 != 0) return GR_DOMAIN; fmpz_mat_init(tmp, n, n); status = fmpz_mat_hadamard(tmp) ? GR_SUCCESS : GR_UNABLE; if (status == GR_SUCCESS) status = gr_mat_set_fmpz_mat(mat, tmp, ctx); fmpz_mat_clear(tmp); return status; } flint-3.1.3/src/gr_mat/hessenberg.c000066400000000000000000000010611461254215100171620ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: algorithm selection */ int gr_mat_hessenberg(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { return gr_mat_hessenberg_gauss(res, mat, ctx); } flint-3.1.3/src/gr_mat/hessenberg_gauss.c000066400000000000000000000075521461254215100203770ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_generic_addmul(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); /* swap (a, b) and (c, d) using (t, u) as tmp space */ static void gr_swap2(gr_ptr a, gr_ptr b, gr_ptr c, gr_ptr d, gr_ptr t, gr_ptr u, gr_ctx_t ctx) { gr_swap(t, a, ctx); gr_swap(u, b, ctx); gr_swap(a, c, ctx); gr_swap(b, d, ctx); gr_swap(c, t, ctx); gr_swap(d, u, ctx); } int gr_mat_hessenberg_gauss(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); gr_method_binary_op addmul = GR_BINARY_OP(ctx, ADDMUL); slong n, m, i, j; gr_ptr h, u, t; truth_t is_zero; int have_addmul; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; n = mat->r; if (n != mat->c) return GR_DOMAIN; status |= gr_mat_set(res, mat, ctx); #define MAT_ENTRY(i, j) GR_MAT_ENTRY(res, i, j, sz) have_addmul = (addmul != (gr_method_binary_op) gr_generic_addmul); #define ADDMUL(z, x, y) \ if (have_addmul) \ { \ status |= addmul(z, x, y, ctx); \ } \ else \ { \ status |= mul(t, x, y, ctx); \ status |= add(z, z, t, ctx); \ } \ if (n <= 2) return GR_SUCCESS; GR_TMP_INIT3(h, u, t, ctx); for (m = 2; m < n; m++) { i = m + 1; while (i <= n) { is_zero = gr_is_zero(MAT_ENTRY(i - 1, m - 1 - 1), ctx); if (is_zero == T_UNKNOWN) { status = GR_UNABLE; goto cleanup; } if (is_zero == T_FALSE) break; i += 1; } if (i != n + 1) { is_zero = gr_is_zero(MAT_ENTRY(m - 1, m - 1 - 1), ctx); if (is_zero == T_UNKNOWN) { status = GR_UNABLE; goto cleanup; } if (is_zero == T_FALSE) i = m; status |= gr_inv(h, MAT_ENTRY(i - 1, m - 1 - 1), ctx); if (status != GR_SUCCESS) goto cleanup; status |= gr_neg(h, h, ctx); if (i > m) { for (j = m - 1; j < n + 1; j++) gr_swap2(MAT_ENTRY(i - 1, j - 1), MAT_ENTRY(m - 1, j - 1), MAT_ENTRY(m - 1, j - 1), MAT_ENTRY(i - 1, j - 1), t, u, ctx); for (j = 1; j < n + 1; j++) gr_swap2(MAT_ENTRY(j - 1, i - 1), MAT_ENTRY(j - 1, m - 1), MAT_ENTRY(j - 1, m - 1), MAT_ENTRY(j - 1, i - 1), t, u, ctx); } for (i = m + 1; i < n + 1; i++) { is_zero = gr_is_zero(MAT_ENTRY(i - 1, m - 1 - 1), ctx); if (is_zero == T_UNKNOWN) { status = GR_UNABLE; goto cleanup; } if (is_zero == T_FALSE) { status |= gr_mul(u, MAT_ENTRY(i - 1, m - 1 - 1), h, ctx); for (j = m; j < n + 1; j++) ADDMUL(MAT_ENTRY(i - 1, j - 1), u, MAT_ENTRY(m - 1, j - 1)); status |= gr_neg(u, u, ctx); for (j = 1; j < n + 1; j++) ADDMUL(MAT_ENTRY(j - 1, m - 1), u, MAT_ENTRY(j - 1, i - 1)); status |= gr_zero(MAT_ENTRY(i - 1, m - 1 - 1), ctx); } } } } cleanup: GR_TMP_CLEAR3(h, u, t, ctx); return status; } flint-3.1.3/src/gr_mat/hessenberg_householder.c000066400000000000000000000064421461254215100215730ustar00rootroot00000000000000/* Copyright (C) 2013 Timo Hartmann Copyright (C) 2018, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: optimize; use dot/norm functions */ /* todo: numerical improvements */ int gr_mat_hessenberg_householder(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { slong n; gr_ptr T; gr_ptr H, G, F, f, ff; slong i, j, k; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; n = mat->r; if (n != mat->c) return GR_DOMAIN; status |= gr_mat_set(res, mat, ctx); #define MAT_ENTRY(i, j) GR_MAT_ENTRY(res, i, j, sz) GR_TMP_INIT_VEC(T, n, ctx); GR_TMP_INIT5(H, G, F, f, ff, ctx); for (i = n - 1; i >= 2; i--) { status |= gr_zero(H, ctx); for (k = 0; k < i; k++) { status |= gr_conj(ff, MAT_ENTRY(i, k), ctx); status |= gr_addmul(H, MAT_ENTRY(i, k), ff, ctx); } status |= gr_set(F, MAT_ENTRY(i, i - 1), ctx); status |= gr_abs(f, F, ctx); status |= gr_sqrt(G, H, ctx); status |= gr_neg(MAT_ENTRY(i, i - 1), G, ctx); status |= gr_div(ff, F, f, ctx); status |= gr_mul(GR_ENTRY(T, i, sz), G, ff, ctx); status |= gr_add(GR_ENTRY(T, i, sz), GR_ENTRY(T, i, sz), F, ctx); status |= gr_mul(MAT_ENTRY(i, i - 1), MAT_ENTRY(i, i - 1), ff, ctx); status |= gr_addmul(H, G, f, ctx); status |= gr_rsqrt(H, H, ctx); status |= gr_mul(GR_ENTRY(T, i, sz), GR_ENTRY(T, i, sz), H, ctx); if (status != GR_SUCCESS) goto cleanup; for (k = 0; k < i - 1; k++) status |= gr_mul(MAT_ENTRY(i, k), MAT_ENTRY(i, k), H, ctx); for (j = 0; j < i; j++) { status |= gr_conj(ff, GR_ENTRY(T, i, sz), ctx); status |= gr_mul(G, ff, MAT_ENTRY(j, i - 1), ctx); for (k = 0; k < i - 1; k++) { status |= gr_conj(ff, MAT_ENTRY(i, k), ctx); status |= gr_addmul(G, ff, MAT_ENTRY(j, k), ctx); } status |= gr_submul(MAT_ENTRY(j, i - 1), G, GR_ENTRY(T, i, sz), ctx); for (k = 0; k < i - 1; k++) status |= gr_submul(MAT_ENTRY(j, k), G, MAT_ENTRY(i, k), ctx); } for (j = 0; j < n; j++) { status |= gr_mul(G, GR_ENTRY(T, i, sz), MAT_ENTRY(i - 1, j), ctx); for (k = 0; k < i - 1; k++) status |= gr_addmul(G, MAT_ENTRY(i, k), MAT_ENTRY(k, j), ctx); status |= gr_conj(ff, GR_ENTRY(T, i, sz), ctx); status |= gr_submul(MAT_ENTRY(i - 1, j), G, ff, ctx); for (k = 0; k < i - 1; k++) { status |= gr_conj(ff, MAT_ENTRY(i, k), ctx); status |= gr_submul(MAT_ENTRY(k, j), G, ff, ctx); } } } for (i = 0; i < n; i++) for (j = i + 2; j < n; j++) status |= gr_zero(MAT_ENTRY(j, i), ctx); cleanup: GR_TMP_CLEAR_VEC(T, n, ctx); GR_TMP_CLEAR5(H, G, F, f, ff, ctx); return status; } flint-3.1.3/src/gr_mat/hilbert.c000066400000000000000000000016511461254215100164730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_hilbert(gr_mat_t mat, gr_ctx_t ctx) { slong R, C, i, j; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; R = gr_mat_nrows(mat, ctx); C = gr_mat_ncols(mat, ctx); /* todo: exploit symmetry */ for (i = 0; i < R; i++) { for (j = 0; j < C; j++) { status |= gr_one(GR_MAT_ENTRY(mat, i, j, sz), ctx); status |= gr_div_ui(GR_MAT_ENTRY(mat, i, j, sz), GR_MAT_ENTRY(mat, i, j, sz), i + j + 1, ctx); } } return status; } flint-3.1.3/src/gr_mat/init.c000066400000000000000000000020601461254215100160000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" void gr_mat_init(gr_mat_t mat, slong rows, slong cols, gr_ctx_t ctx) { slong i, sz; sz = ctx->sizeof_elem; if (rows != 0) mat->rows = flint_malloc(rows * sizeof(gr_ptr)); else mat->rows = NULL; if (rows != 0 && cols != 0) { mat->entries = (gr_ptr) flint_malloc(flint_mul_sizes(rows, cols) * sz); _gr_vec_init(mat->entries, rows * cols, ctx); for (i = 0; i < rows; i++) mat->rows[i] = GR_ENTRY(mat->entries, i * cols, sz); } else { mat->entries = NULL; for (i = 0; i < rows; i++) mat->rows[i] = NULL; } mat->r = rows; mat->c = cols; } flint-3.1.3/src/gr_mat/init_set.c000066400000000000000000000011661461254215100166610ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_init_set(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { slong r, c; r = gr_mat_nrows(mat, ctx); c = gr_mat_ncols(mat, ctx); gr_mat_init(res, r, c, ctx); return gr_mat_set(res, mat, ctx); } flint-3.1.3/src/gr_mat/inlines.c000066400000000000000000000007041461254215100165010ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define GR_MAT_INLINES_C #include "gr_mat.h" #undef GR_MAT_INLINES_C flint-3.1.3/src/gr_mat/inv.c000066400000000000000000000015531461254215100156370ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_inv(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { gr_mat_t T; int status = GR_SUCCESS; slong n = mat->r; if (n != mat->c) return GR_DOMAIN; if (n == 0) return GR_SUCCESS; if (n == 1) return gr_inv(res->rows[0], mat->rows[0], ctx); gr_mat_init(T, n, n, ctx); status |= gr_mat_one(T, ctx); status |= gr_mat_nonsingular_solve(res, mat, T, ctx); gr_mat_clear(T, ctx); return status; } flint-3.1.3/src/gr_mat/invert_cols.c000066400000000000000000000017021461254215100173660ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_invert_cols(gr_mat_t mat, slong * perm, gr_ctx_t ctx) { if (gr_mat_is_empty(mat, ctx) == T_FALSE) { slong sz = ctx->sizeof_elem; slong t, i; slong c = mat->c; slong k = mat->c / 2; if (perm != NULL) for (i = 0; i < k; i++) FLINT_SWAP(slong, perm[i], perm[c - i - 1]); for (t = 0; t < mat->r; t++) for (i = 0; i < k; i++) gr_swap(GR_MAT_ENTRY(mat, t, i, sz), GR_MAT_ENTRY(mat, t, c - i - 1, sz), ctx); } return GR_SUCCESS; } flint-3.1.3/src/gr_mat/invert_rows.c000066400000000000000000000012401461254215100174150ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_invert_rows(gr_mat_t mat, slong * perm, gr_ctx_t ctx) { int status = GR_SUCCESS; slong r = gr_mat_nrows(mat, ctx); slong i; for (i = 0; i < r / 2; i++) status |= gr_mat_swap_rows(mat, perm, i, r - i - 1, ctx); return status; } flint-3.1.3/src/gr_mat/io.c000066400000000000000000000012201461254215100154410ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gr_mat.h" /* printing *******************************************************************/ int gr_mat_print(const gr_mat_t mat, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); return gr_mat_write(out, mat, ctx); } flint-3.1.3/src/gr_mat/is_diagonal.c000066400000000000000000000026161461254215100173150ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" truth_t gr_mat_is_diagonal(const gr_mat_t mat, gr_ctx_t ctx) { gr_method_vec_predicate is_zero = GR_VEC_PREDICATE(ctx, VEC_IS_ZERO); slong ar, ac, i, sz = ctx->sizeof_elem; truth_t eq, this_eq; ar = gr_mat_nrows(mat, ctx); ac = gr_mat_ncols(mat, ctx); if (ar == 0 || ac == 0 || (ar == 1 && ac == 1)) return T_TRUE; eq = T_TRUE; for (i = 0; i < ar; i++) { /* upper triangular */ if (i >= 1) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, 0, sz), FLINT_MIN(i, ac), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } /* lower triangular */ if (i < ac - 1) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, i + 1, sz), ac - i - 1, ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } } return eq; } flint-3.1.3/src/gr_mat/is_hessenberg.c000066400000000000000000000017701461254215100176640ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" truth_t gr_mat_is_hessenberg(const gr_mat_t mat, gr_ctx_t ctx) { gr_method_vec_predicate is_zero = GR_VEC_PREDICATE(ctx, VEC_IS_ZERO); slong ar, ac, i, sz = ctx->sizeof_elem; truth_t eq, this_eq; ar = gr_mat_nrows(mat, ctx); ac = gr_mat_ncols(mat, ctx); if (ar <= 2 || ac == 0) return T_TRUE; eq = T_TRUE; for (i = 2; i < ar; i++) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, 0, sz), FLINT_MIN(i - 1, ac), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } return eq; } flint-3.1.3/src/gr_mat/is_lower_triangular.c000066400000000000000000000020131461254215100211060ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" truth_t gr_mat_is_lower_triangular(const gr_mat_t mat, gr_ctx_t ctx) { gr_method_vec_predicate is_zero = GR_VEC_PREDICATE(ctx, VEC_IS_ZERO); slong ar, ac, i, sz = ctx->sizeof_elem; truth_t eq, this_eq; ar = gr_mat_nrows(mat, ctx); ac = gr_mat_ncols(mat, ctx); if (ar == 0 || ac == 0) return T_TRUE; eq = T_TRUE; for (i = 0; i < FLINT_MIN(ar, ac - 1); i++) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, i + 1, sz), ac - i - 1, ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } return eq; } flint-3.1.3/src/gr_mat/is_neg_one.c000066400000000000000000000033431461254215100171470ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" truth_t gr_mat_is_neg_one(const gr_mat_t mat, gr_ctx_t ctx) { gr_method_vec_predicate is_zero = GR_VEC_PREDICATE(ctx, VEC_IS_ZERO); gr_method_unary_predicate is_neg_one = GR_UNARY_PREDICATE(ctx, IS_NEG_ONE); truth_t eq, this_eq; slong i, ar, ac, sz; ar = gr_mat_nrows(mat, ctx); ac = gr_mat_ncols(mat, ctx); if (ar == 0 || ac == 0) return T_TRUE; sz = ctx->sizeof_elem; eq = T_TRUE; for (i = 0; i < ar; i++) { /* upper triangular */ if (i >= 1) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, 0, sz), FLINT_MIN(i, ac), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } /* main diagonal */ if (i < ac) { this_eq = is_neg_one(GR_MAT_ENTRY(mat, i, i, sz), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } /* lower triangular */ if (i < ac - 1) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, i + 1, sz), ac - i - 1, ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } } return eq; } flint-3.1.3/src/gr_mat/is_one.c000066400000000000000000000033231461254215100163140ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" truth_t gr_mat_is_one(const gr_mat_t mat, gr_ctx_t ctx) { gr_method_vec_predicate is_zero = GR_VEC_PREDICATE(ctx, VEC_IS_ZERO); gr_method_unary_predicate is_one = GR_UNARY_PREDICATE(ctx, IS_ONE); truth_t eq, this_eq; slong i, ar, ac, sz; ar = gr_mat_nrows(mat, ctx); ac = gr_mat_ncols(mat, ctx); if (ar == 0 || ac == 0) return T_TRUE; sz = ctx->sizeof_elem; eq = T_TRUE; for (i = 0; i < ar; i++) { /* upper triangular */ if (i >= 1) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, 0, sz), FLINT_MIN(i, ac), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } /* main diagonal */ if (i < ac) { this_eq = is_one(GR_MAT_ENTRY(mat, i, i, sz), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } /* lower triangular */ if (i < ac - 1) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, i + 1, sz), ac - i - 1, ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } } return eq; } flint-3.1.3/src/gr_mat/is_scalar.c000066400000000000000000000017571461254215100170110ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" truth_t gr_mat_is_scalar(const gr_mat_t mat, gr_ctx_t ctx) { truth_t eq, this_eq; slong i, ar, ac, sz; ar = gr_mat_nrows(mat, ctx); ac = gr_mat_ncols(mat, ctx); sz = ctx->sizeof_elem; eq = gr_mat_is_diagonal(mat, ctx); if (eq != T_FALSE) { for (i = 1; i < FLINT_MIN(ar, ac); i++) { this_eq = gr_equal(GR_MAT_ENTRY(mat, i, i, sz), GR_MAT_ENTRY(mat, 0, 0, sz), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } } return eq; } flint-3.1.3/src/gr_mat/is_upper_triangular.c000066400000000000000000000017721461254215100211240ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" truth_t gr_mat_is_upper_triangular(const gr_mat_t mat, gr_ctx_t ctx) { gr_method_vec_predicate is_zero = GR_VEC_PREDICATE(ctx, VEC_IS_ZERO); slong ar, ac, i, sz = ctx->sizeof_elem; truth_t eq, this_eq; ar = gr_mat_nrows(mat, ctx); ac = gr_mat_ncols(mat, ctx); if (ar == 0 || ac == 0) return T_TRUE; eq = T_TRUE; for (i = 1; i < ar; i++) { this_eq = is_zero(GR_MAT_ENTRY(mat, i, 0, sz), FLINT_MIN(i, ac), ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } return eq; } flint-3.1.3/src/gr_mat/is_zero.c000066400000000000000000000016041461254215100165120ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" truth_t gr_mat_is_zero(const gr_mat_t mat, gr_ctx_t ctx) { truth_t eq, this_eq; slong i, r, c; r = gr_mat_nrows(mat, ctx); c = gr_mat_ncols(mat, ctx); if (r == 0 || c == 0) return T_TRUE; eq = T_TRUE; for (i = 0; i < r; i++) { this_eq = _gr_vec_is_zero(mat->rows[i], c, ctx); if (this_eq == T_FALSE) return T_FALSE; if (this_eq == T_UNKNOWN) eq = T_UNKNOWN; } return eq; } flint-3.1.3/src/gr_mat/jordan_blocks.c000066400000000000000000000110451461254215100176520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_set_jordan_blocks(gr_mat_t mat, const gr_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i, j, n, count; n = gr_mat_nrows(mat, ctx); if (n != gr_mat_ncols(mat, ctx)) { /* matrix must be square */ return GR_DOMAIN; } count = 0; for (i = 0; i < num_blocks; i++) count += block_size[i]; if (count != n) { /* sum of block sizes does not agree with size of output matrix */ return GR_DOMAIN; } status |= gr_mat_zero(mat, ctx); count = 0; for (i = 0; i < num_blocks; i++) { for (j = 0; j < block_size[i]; j++) { status |= gr_set(gr_mat_entry_ptr(mat, count + j, count + j, ctx), gr_vec_entry_srcptr(lambda, block_lambda[i], ctx), ctx); if (j < block_size[i] - 1) status |= gr_one(gr_mat_entry_ptr(mat, count + j, count + j + 1, ctx), ctx); } count += block_size[i]; } return status; } int gr_mat_jordan_blocks(gr_vec_t lambda, slong * num_blocks, slong * block_lambda, slong * block_size, const gr_mat_t A, gr_ctx_t ctx) { slong i, j, k, n; slong * ranks, * diagram; slong ranks_len, rank; fmpz * exp; slong exp_i; int status = GR_SUCCESS; gr_ctx_t ZZ; gr_vec_t mult; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) { /* matrix must be square */ return GR_DOMAIN; } ranks = flint_malloc(sizeof(slong) * (n + 1)); diagram = flint_malloc(sizeof(slong) * n); gr_ctx_init_fmpz(ZZ); gr_vec_init(mult, 0, ZZ); status |= gr_mat_eigenvalues(lambda, mult, A, 0, ctx); if (status == GR_SUCCESS) { exp = mult->entries; *num_blocks = 0; for (i = 0; (status == GR_SUCCESS) && i < gr_vec_length(lambda, ctx); i++) { exp_i = exp[i]; if (exp_i == 1) { block_lambda[*num_blocks] = i; block_size[*num_blocks] = 1; *num_blocks += 1; } else { gr_mat_t B, C; gr_mat_init(B, n, n, ctx); gr_mat_init(C, n, n, ctx); for (j = 0; j < n; j++) for (k = 0; k < n; k++) if (j == k) status |= gr_sub(gr_mat_entry_ptr(B, j, j, ctx), gr_mat_entry_srcptr(A, j, j, ctx), gr_vec_entry_srcptr(lambda, i, ctx), ctx); else status |= gr_set(gr_mat_entry_ptr(B, j, k, ctx), gr_mat_entry_srcptr(A, j, k, ctx), ctx); status |= gr_mat_set(C, B, ctx); status |= gr_mat_rank(&rank, C, ctx); ranks_len = 2; ranks[0] = n; ranks[1] = rank; j = 0; while ((status == GR_SUCCESS) && (ranks[j] > ranks[j + 1] && ranks[j + 1] + exp_i > n)) { status |= gr_mat_mul(C, B, C, ctx); status |= gr_mat_rank(&rank, C, ctx); ranks[ranks_len] = rank; j++; ranks_len++; } if (status == GR_SUCCESS) { /* Ferrer's diagram of an integer partition */ for (j = 0; j < ranks_len - 1; j++) diagram[j] = ranks[j] - ranks[j + 1]; /* Transpose Ferrer's diagram */ for (j = 1; j <= diagram[0]; j++) { slong c = 0; for (k = 0; k < ranks_len - 1; k++) c += (diagram[k] >= j); block_lambda[*num_blocks] = i; block_size[*num_blocks] = c; *num_blocks += 1; } } gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); } } } gr_vec_clear(mult, ZZ); gr_ctx_clear(ZZ); flint_free(ranks); flint_free(diagram); return status; } flint-3.1.3/src/gr_mat/jordan_form.c000066400000000000000000000027461461254215100173500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_jordan_form(gr_mat_t J, gr_mat_t P, const gr_mat_t A, gr_ctx_t ctx) { gr_vec_t lambda; slong n; slong num_blocks, * block_size, * block_lambda; int status = GR_SUCCESS; n = gr_mat_nrows(A, ctx); if (J == A || P == A) { gr_mat_t T; gr_mat_init(T, n, n, ctx); status |= gr_mat_set(T, A, ctx); status |= gr_mat_jordan_form(J, P, T, ctx); gr_mat_clear(T, ctx); return status; } gr_vec_init(lambda, 0, ctx); block_lambda = flint_malloc(sizeof(slong) * n); block_size = flint_malloc(sizeof(slong) * n); status = gr_mat_jordan_blocks(lambda, &num_blocks, block_lambda, block_size, A, ctx); if ((status == GR_SUCCESS) && P != NULL) status |= gr_mat_jordan_transformation(P, lambda, num_blocks, block_lambda, block_size, A, ctx); if (status == GR_SUCCESS) status |= gr_mat_set_jordan_blocks(J, lambda, num_blocks, block_lambda, block_size, ctx); gr_vec_clear(lambda, ctx); flint_free(block_lambda); flint_free(block_size); return status; } flint-3.1.3/src/gr_mat/jordan_transformation.c000066400000000000000000000254621461254215100214530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" /* The algorithm is taken from jordan_form() in Sage */ /* Find a row vector v in the row span of V but not in the row span of W. Returns the index of such a vector. Returns -1 on failure. */ static slong vector_in_difference(const gr_mat_t V, const gr_mat_t W, gr_ctx_t ctx) { gr_mat_t U; gr_ptr v; gr_ptr t, u; slong i, j, k, l, n, found, rank; truth_t is_zero; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (gr_mat_nrows(V, ctx) == 0) return -1; if (gr_mat_nrows(W, ctx) == 0) return 0; n = gr_mat_ncols(W, ctx); found = -1; gr_mat_init(U, gr_mat_nrows(W, ctx), n, ctx); GR_TMP_INIT_VEC(v, n, ctx); GR_TMP_INIT2(t, u, ctx); if (gr_mat_rref(&rank, U, W, ctx) == GR_SUCCESS) { for (i = 0; i < gr_mat_nrows(V, ctx); i++) /* for candidate v in V */ { /* Copy of v for reduction */ GR_MUST_SUCCEED(_gr_vec_set(v, gr_mat_entry_srcptr(V, i, 0, ctx), n, ctx)); /* Reduce v by the rows in W */ for (j = 0; j < rank; j++) /* for each w in W */ { for (k = 0; k < n; k++) /* find pivot element in w */ { is_zero = gr_is_zero(gr_mat_entry_srcptr(U, j, k, ctx), ctx); if (is_zero == T_UNKNOWN) goto cleanup; /* reduce by this row */ if (is_zero == T_FALSE) { status |= gr_div(t, GR_ENTRY(v, k, sz), gr_mat_entry_srcptr(U, j, k, ctx), ctx); for (l = 0; l < n; l++) { if (l == k) status |= gr_zero(GR_ENTRY(v, l, sz), ctx); else { status |= gr_mul(u, t, gr_mat_entry_srcptr(U, j, l, ctx), ctx); status |= gr_sub(GR_ENTRY(v, l, sz), GR_ENTRY(v, l, sz), u, ctx); } } break; } } } if (status != GR_SUCCESS) goto cleanup; is_zero = _gr_vec_is_zero(v, n, ctx); if (is_zero == T_UNKNOWN) goto cleanup; if (is_zero == T_FALSE) { found = i; break; } } } cleanup: gr_mat_clear(U, ctx); GR_TMP_CLEAR_VEC(v, n, ctx); GR_TMP_CLEAR2(t, u, ctx); return found; } /* note: doesn't support aliasing */ static int _gr_mat_mul_vec(gr_ptr res, const gr_mat_t mat, gr_srcptr v, gr_ctx_t ctx) { slong i; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; for (i = 0; i < gr_mat_nrows(mat, ctx); i++) { status |= _gr_vec_dot(GR_ENTRY(res, i, sz), NULL, 0, gr_mat_entry_srcptr(mat, i, 0, ctx), v, gr_mat_ncols(mat, ctx), ctx); } return status; } static void gr_mat_transpose_resize(gr_mat_t B, const gr_mat_t A, gr_ctx_t ctx) { gr_mat_t T; gr_mat_init(T, gr_mat_ncols(A, ctx), gr_mat_nrows(A, ctx), ctx); GR_MUST_SUCCEED(gr_mat_transpose(T, A, ctx)); gr_mat_swap(B, T, ctx); gr_mat_clear(T, ctx); } static int gr_mat_pow_ui_binexp(gr_mat_t res, const gr_mat_t A, ulong n, gr_ctx_t ctx) { gr_ctx_t mctx; int status; gr_ctx_init_matrix_ring(mctx, ctx, gr_mat_nrows(A, ctx)); status = gr_pow_ui(res, A, n, mctx); gr_ctx_clear(mctx); return status; } /* todo: special-case num_lambda == n (diagonalization) */ /* todo: also, for each vector */ /* todo: aliasing */ int gr_mat_jordan_transformation(gr_mat_t mat, const gr_vec_t lambda, slong num_blocks, slong * block_lambda, slong * block_size, const gr_mat_t A, gr_ctx_t ctx) { slong num_lambda, i, j, k, l, m, n, output_block, column_offset; slong *sizes, *counts; gr_mat_t B, Y, V1, V2, V1ker, V2ker; slong size, num_sizes, count, y_rows, v_index; int * written; int status; n = gr_mat_nrows(A, ctx); if (n == 0) return GR_SUCCESS; num_lambda = gr_vec_length(lambda, ctx); /* Special-case diagonalization with distinct eigenvalues. */ /* TODO: also special-case eigenvalues with multiplicity 1 below. */ if (num_lambda == n) { status = GR_SUCCESS; gr_mat_init(B, n, n, ctx); gr_mat_init(Y, 0, 0, ctx); for (i = 0; i < n; i++) { /* B = A - lambda */ for (j = 0; j < n; j++) for (k = 0; k < n; k++) if (j == k) status |= gr_sub(gr_mat_entry_ptr(B, j, j, ctx), gr_mat_entry_srcptr(A, j, j, ctx), gr_vec_entry_srcptr(lambda, block_lambda[i], ctx), ctx); else status |= gr_set(gr_mat_entry_ptr(B, j, k, ctx), gr_mat_entry_srcptr(A, j, k, ctx), ctx); status |= gr_mat_nullspace(Y, B, ctx); if (status != GR_SUCCESS) break; if (gr_mat_ncols(Y, ctx) != 1) { /* should not happen */ status = GR_UNABLE; } for (j = 0; j < n; j++) status |= gr_set(gr_mat_entry_ptr(mat, j, i, ctx), gr_mat_entry_srcptr(Y, j, 0, ctx), ctx); } gr_mat_clear(B, ctx); gr_mat_clear(Y, ctx); return status; } sizes = flint_malloc(sizeof(slong) * n); counts = flint_malloc(sizeof(slong) * n); written = flint_calloc(num_blocks, sizeof(int)); gr_mat_init(B, n, n, ctx); gr_mat_init(Y, 0, n, ctx); gr_mat_init(V1, n, n, ctx); gr_mat_init(V2, n, n, ctx); gr_mat_init(V1ker, 0, 0, ctx); gr_mat_init(V2ker, 0, 0, ctx); status = GR_SUCCESS; for (i = 0; i < num_lambda; i++) { /* B = A - lambda */ for (j = 0; j < n; j++) for (k = 0; k < n; k++) if (j == k) status |= gr_sub(gr_mat_entry_ptr(B, j, j, ctx), gr_mat_entry_srcptr(A, j, j, ctx), gr_vec_entry_srcptr(lambda, i, ctx), ctx); else status |= gr_set(gr_mat_entry_ptr(B, j, k, ctx), gr_mat_entry_srcptr(A, j, k, ctx), ctx); /* Group blocks as (block size, count) */ /* Todo: does this need to be sorted? */ num_sizes = 0; for (j = 0; j < num_blocks; j++) { if (block_lambda[j] == i) { for (k = 0; k < num_sizes; k++) { if (sizes[k] == block_size[j]) { counts[k]++; break; } } if (k == num_sizes) { sizes[num_sizes] = block_size[j]; counts[num_sizes] = 1; num_sizes++; } } } /* Y = matrix of row vectors spanning the Jordan chains for this eigenvalue. */ gr_mat_clear(Y, ctx); gr_mat_init(Y, n, n, ctx); y_rows = 0; /* Iterate over (block size, count) */ for (j = 0; j < num_sizes; j++) { size = sizes[j]; count = counts[j]; /* should not happen */ if (size == 0) { status = GR_UNABLE; goto cleanup; } /* Find elements in ker(B^size) - ker(B^(size-1)) */ status |= gr_mat_pow_ui_binexp(V2, B, size - 1, ctx); status |= gr_mat_mul(V1, B, V2, ctx); status |= gr_mat_nullspace(V1ker, V1, ctx); if (status != GR_SUCCESS) goto cleanup; status |= gr_mat_nullspace(V2ker, V2, ctx); if (status != GR_SUCCESS) goto cleanup; /* rows instead of columns */ gr_mat_transpose_resize(V1ker, V1ker, ctx); gr_mat_transpose_resize(V2ker, V2ker, ctx); for (k = 0; k < count; k++) { /* Concatenate V2ker with Y */ gr_mat_t V2kerY; gr_mat_init(V2kerY, gr_mat_nrows(V2ker, ctx) + y_rows, n, ctx); for (m = 0; m < gr_mat_nrows(V2ker, ctx); m++) status |= _gr_vec_set(gr_mat_entry_ptr(V2kerY, m, 0, ctx), gr_mat_entry_srcptr(V2ker, m, 0, ctx), n, ctx); for (m = 0; m < y_rows; m++) status |= _gr_vec_set(gr_mat_entry_ptr(V2kerY, gr_mat_nrows(V2ker, ctx) + m, 0, ctx), gr_mat_entry_srcptr(Y, m, 0, ctx), n, ctx); v_index = vector_in_difference(V1ker, V2kerY, ctx); gr_mat_clear(V2kerY, ctx); if (v_index == -1) { status = GR_UNABLE; goto cleanup; } /* Position in output matrix to write chain. */ column_offset = 0; output_block = 0; while (1) { if (block_lambda[output_block] == i && block_size[output_block] == size && !written[output_block]) { written[output_block] = 1; break; } else { column_offset += block_size[output_block]; output_block++; } } /* chain = [v, B*v, ..., B^(size-1)*v] */ status |= _gr_vec_set(gr_mat_entry_ptr(Y, y_rows, 0, ctx), gr_mat_entry_srcptr(V1ker, v_index, 0, ctx), n, ctx); for (m = 1; m < size; m++) { status |= _gr_mat_mul_vec(gr_mat_entry_ptr(Y, y_rows + m, 0, ctx), B, gr_mat_entry_srcptr(Y, y_rows + m - 1, 0, ctx), ctx); } y_rows += size; /* Insert chain in the output matrix */ for (m = 0; m < size; m++) { for (l = 0; l < n; l++) status |= gr_set(gr_mat_entry_ptr(mat, l, column_offset + m, ctx), gr_mat_entry_srcptr(Y, y_rows - 1 - m, l, ctx), ctx); } } } } cleanup: flint_free(sizes); flint_free(counts); gr_mat_clear(B, ctx); gr_mat_clear(Y, ctx); gr_mat_clear(V1, ctx); gr_mat_clear(V2, ctx); gr_mat_clear(V1ker, ctx); gr_mat_clear(V2ker, ctx); flint_free(written); return status; } flint-3.1.3/src/gr_mat/log.c000066400000000000000000000073211461254215100156230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_mat.h" int gr_mat_log_jordan(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) { truth_t is_zero; int status = GR_SUCCESS; slong i, j, len, n; gr_mat_t P, Q, J; gr_ptr t; gr_vec_t lambda, f_lambda; slong num_blocks, num_lambda, offset; slong * block_lambda, * block_size; n = gr_mat_nrows(A, ctx); if (n != gr_mat_ncols(A, ctx)) return GR_DOMAIN; if (n == 0) return GR_SUCCESS; gr_mat_init(P, n, n, ctx); gr_mat_init(Q, n, n, ctx); gr_mat_init(J, n, n, ctx); GR_TMP_INIT(t, ctx); block_lambda = flint_malloc(sizeof(slong) * n); block_size = flint_malloc(sizeof(slong) * n); gr_vec_init(lambda, 0, ctx); gr_vec_init(f_lambda, 0, ctx); status |= gr_mat_jordan_blocks(lambda, &num_blocks, block_lambda, block_size, A, ctx); if (status != GR_SUCCESS) goto cleanup; num_lambda = gr_vec_length(lambda, ctx); /* Zero must not be an eigenvalue */ for (i = 0; i < num_lambda; i++) { is_zero = gr_is_zero(gr_vec_entry_srcptr(lambda, i, ctx), ctx); if (is_zero == T_UNKNOWN) { status = GR_UNABLE; goto cleanup; } if (is_zero == T_TRUE) { status = GR_DOMAIN; goto cleanup; } } status |= gr_mat_jordan_transformation(P, lambda, num_blocks, block_lambda, block_size, A, ctx); if (status != GR_SUCCESS) goto cleanup; status |= gr_mat_inv(Q, P, ctx); if (status != GR_SUCCESS) goto cleanup; /* Evaluate Jordan blocks and build matrix */ gr_vec_set_length(f_lambda, num_lambda, ctx); for (i = 0; i < num_lambda && status == GR_SUCCESS; i++) status |= gr_log(gr_vec_entry_ptr(f_lambda, i, ctx), gr_vec_entry_srcptr(lambda, i, ctx), ctx); offset = 0; for (i = 0; i < num_blocks; i++) { len = block_size[i]; status |= gr_set(gr_mat_entry_ptr(J, offset, offset, ctx), gr_vec_entry_srcptr(f_lambda, block_lambda[i], ctx), ctx); if (len > 1) { status |= gr_inv(t, gr_vec_entry_srcptr(lambda, block_lambda[i], ctx), ctx); status |= gr_set(gr_mat_entry_ptr(J, offset, offset + 1, ctx), t, ctx); status |= gr_neg(t, t, ctx); for (j = 2; j < len; j++) status |= gr_mul(gr_mat_entry_ptr(J, offset, offset + j, ctx), gr_mat_entry_srcptr(J, offset, offset + j - 1, ctx), t, ctx); for (j = 2; j < len; j++) status |= gr_div_ui(gr_mat_entry_ptr(J, offset, offset + j, ctx), gr_mat_entry_srcptr(J, offset, offset + j, ctx), j, ctx); for (j = 1; j < len; j++) status |= _gr_vec_set(gr_mat_entry_ptr(J, offset + j, offset + j, ctx), gr_mat_entry_srcptr(J, offset + j - 1, offset + j - 1, ctx), len - j, ctx); } offset += block_size[i]; } status |= gr_mat_mul(res, P, J, ctx); status |= gr_mat_mul(res, res, Q, ctx); cleanup: gr_mat_clear(P, ctx); gr_mat_clear(Q, ctx); gr_mat_clear(J, ctx); gr_vec_clear(lambda, ctx); gr_vec_clear(f_lambda, ctx); GR_TMP_CLEAR(t, ctx); flint_free(block_lambda); flint_free(block_size); return status; } int gr_mat_log(gr_mat_t res, const gr_mat_t A, gr_ctx_t ctx) { return GR_MAT_UNARY_OP(ctx, MAT_LOG)(res, A, ctx); } flint-3.1.3/src/gr_mat/lu.c000066400000000000000000000013701461254215100154600ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you grn redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_lu_generic(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx) { return gr_mat_lu_recursive(rank, P, LU, A, rank_check, 4, ctx); } int gr_mat_lu(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx) { return GR_MAT_LU_OP(ctx, MAT_LU)(rank, P, LU, A, rank_check, ctx); } flint-3.1.3/src/gr_mat/lu_classical.c000066400000000000000000000057121461254215100175020ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" static void _gr_mat_swap_rows(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx) { if (r != s) { gr_ptr u; slong t; if (perm != NULL) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } u = mat->rows[s]; mat->rows[s] = mat->rows[r]; mat->rows[r] = u; } } int gr_mat_lu_classical(slong * res_rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, gr_ctx_t ctx) { gr_ptr d, e; gr_ptr * a; slong i, j, m, n, r, rank, row, col, sz; int status = GR_SUCCESS; int pivot_status; if (gr_mat_is_empty(A, ctx) == T_TRUE) { *res_rank = 0; return GR_SUCCESS; } GR_TMP_INIT2(d, e, ctx); m = gr_mat_nrows(A, ctx); n = gr_mat_ncols(A, ctx); sz = ctx->sizeof_elem; status |= gr_mat_set(LU, A, ctx); a = LU->rows; rank = row = col = 0; for (i = 0; i < m; i++) P[i] = i; while (row < m && col < n) { pivot_status = gr_mat_find_nonzero_pivot(&r, LU, row, m, col, ctx); /* We don't know whether there is a nonzero pivot element, so we can't determine the rank. */ if (pivot_status == GR_UNABLE) { status = GR_UNABLE; break; } /* There is certainly no nonzero pivot element. */ if (pivot_status == GR_DOMAIN) { /* We proved that the matrix is rank-deficient, accomplishing the goal. */ if (rank_check) { status = GR_SUCCESS; rank = 0; break; } /* Continue with next column. */ col++; continue; } rank++; if (r != row) _gr_mat_swap_rows(LU, P, row, r, ctx); /* Must be able to invert pivot element. */ status |= gr_inv(d, GR_ENTRY(a[row], col, sz), ctx); if (status != GR_SUCCESS) break; for (j = row + 1; j < m; j++) { status |= gr_mul(e, GR_ENTRY(a[j], col, sz), d, ctx); status |= gr_neg(e, e, ctx); if (n - col - 1 > 0) status |= _gr_vec_addmul_scalar(GR_ENTRY(a[j], col + 1, sz), GR_ENTRY(a[row], col + 1, sz), n - col - 1, e, ctx); status |= gr_zero(GR_ENTRY(a[j], col, sz), ctx); status |= gr_neg(GR_ENTRY(a[j], rank - 1, sz), e, ctx); } row++; col++; } GR_TMP_CLEAR2(d, e, ctx); *res_rank = rank; return status; } flint-3.1.3/src/gr_mat/lu_recursive.c000066400000000000000000000071721461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" static void _apply_permutation(slong * AP, gr_mat_t A, slong * P, slong n, slong offset) { if (n != 0) { gr_ptr * Atmp; slong *APtmp; slong i; /* todo: stack alloc */ Atmp = flint_malloc(sizeof(gr_ptr) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } int gr_mat_lu_recursive(slong * rank, slong * P, gr_mat_t LU, const gr_mat_t A, int rank_check, slong cutoff, gr_ctx_t ctx) { slong i, j, m, n, r1, r2, n1; gr_mat_t A0, A1, A00, A01, A10, A11; slong *P1; int status = GR_SUCCESS; m = A->r; n = A->c; if (m < cutoff || n < cutoff) return gr_mat_lu_classical(rank, P, LU, A, rank_check, ctx); if (LU != A) status |= gr_mat_set(LU, A, ctx); n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; r1 = r2 = 0; P1 = flint_malloc(sizeof(slong) * m); gr_mat_window_init(A0, LU, 0, 0, m, n1, ctx); gr_mat_window_init(A1, LU, 0, n1, m, n, ctx); status |= gr_mat_lu_recursive(&r1, P1, A0, A0, rank_check, cutoff, ctx); if (status != GR_SUCCESS) goto cleanup1; /* We proved that the matrix is rank-deficient, accomplishing the goal. */ if (rank_check && r1 != n1) { r1 = r2 = 0; goto cleanup1; } if (r1 != 0) { _apply_permutation(P, LU, P1, m, 0); } gr_mat_window_init(A00, LU, 0, 0, r1, r1, ctx); gr_mat_window_init(A10, LU, r1, 0, m, r1, ctx); gr_mat_window_init(A01, LU, 0, n1, r1, n, ctx); gr_mat_window_init(A11, LU, r1, n1, m, n, ctx); if (r1 != 0) { gr_mat_t T; gr_mat_init(T, A10->r, A01->c, ctx); status |= gr_mat_nonsingular_solve_tril(A01, A00, A01, 1, ctx); status |= gr_mat_mul(T, A10, A01, ctx); status |= gr_mat_sub(A11, A11, T, ctx); gr_mat_clear(T, ctx); } status |= gr_mat_lu_recursive(&r2, P1, A11, A11, rank_check, cutoff, ctx); if (status != GR_SUCCESS) goto cleanup2; /* We proved that the matrix is rank-deficient, accomplishing the goal. */ if (rank_check && (r1 + r2 < FLINT_MIN(m, n))) { r1 = r2 = 0; goto cleanup2; } _apply_permutation(P, LU, P1, m - r1, r1); /* Compress L */ if (r1 != n1) { slong sz = ctx->sizeof_elem; for (i = 0; i < m - r1; i++) { gr_ptr row = LU->rows[r1 + i]; for (j = 0; j < FLINT_MIN(i, r2); j++) { status |= gr_set(GR_ENTRY(row, r1 + j, sz), GR_ENTRY(row, n1 + j, sz), ctx); status |= gr_zero(GR_ENTRY(row, n1 + j, sz), ctx); } } } cleanup2: gr_mat_window_clear(A00, ctx); gr_mat_window_clear(A10, ctx); gr_mat_window_clear(A01, ctx); gr_mat_window_clear(A11, ctx); cleanup1: flint_free(P1); gr_mat_window_clear(A0, ctx); gr_mat_window_clear(A1, ctx); *rank = r1 + r2; return status; } flint-3.1.3/src/gr_mat/minpoly_field.c000066400000000000000000000120421461254215100176700ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" #include "gr_mat.h" int gr_mat_reduce_row(slong * column, gr_mat_t A, slong * P, slong * L, slong m, gr_ctx_t ctx); int gr_mat_minpoly_field(gr_poly_t p, const gr_mat_t X, gr_ctx_t ctx) { slong n = X->r, i, j, c, c1, c2, r1, r2; slong * P1, * P2, * L1, * L2; gr_mat_t A, B, v; int first_poly = 1, indep = 1; gr_poly_t b, g, r; gr_ptr t, h; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; TMP_INIT; if (X->r != X->c) return GR_DOMAIN; if (n == 0) return gr_poly_one(p, ctx); if (n == 1) { gr_poly_fit_length(p, 2, ctx); status |= gr_neg(GR_ENTRY(p->coeffs, 0, sz), GR_MAT_ENTRY(X, 0, 0, sz), ctx); status |= gr_one(GR_ENTRY(p->coeffs, 1, sz), ctx); _gr_poly_set_length(p, 2, ctx); return status; } TMP_START; GR_TMP_INIT2(t, h, ctx); gr_init(h, ctx); gr_poly_init(b, ctx); gr_poly_init(g, ctx); gr_poly_init(r, ctx); gr_mat_init(A, n + 1, 2*n + 1, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(v, n, 1, ctx); status |= gr_poly_one(p, ctx); L1 = (slong *) TMP_ALLOC((n + 1)*sizeof(slong)); L2 = (slong *) TMP_ALLOC(n*sizeof(slong)); P1 = (slong *) TMP_ALLOC((2*n + 1)*sizeof(slong)); P2 = (slong *) TMP_ALLOC(n*sizeof(slong)); for (i = 1; i <= n + 1; i++) L1[i - 1] = n + i; for (i = 1; i <= n; i++) L2[i - 1] = n; for (i = 1; i < n; i++) P2[i] = -1; P2[0] = 0; r2 = c2 = 0; first_poly = 1; while (r2 < n) { for (i = 0; i < 2*n + 1; i++) P1[i] = -1; for (i = 0; i < n; i++) { status |= gr_zero(GR_MAT_ENTRY(v, i, 0, sz), ctx); status |= gr_zero(GR_MAT_ENTRY(B, r2, i, sz), ctx); status |= gr_zero(GR_MAT_ENTRY(A, 0, i, sz), ctx); } P1[c2] = 0; P2[c2] = r2; status |= gr_one(GR_MAT_ENTRY(v, c2, 0, sz), ctx); status |= gr_one(GR_MAT_ENTRY(B, r2, c2, sz), ctx); status |= gr_one(GR_MAT_ENTRY(A, 0, c2, sz), ctx); status |= gr_one(GR_MAT_ENTRY(A, 0, n, sz), ctx); indep = 1; r1 = 0; c1 = -1; while (c1 < n && r1 < n) { r1++; r2 = indep ? r2 + 1 : r2; status |= gr_mat_mul(v, X, v, ctx); for (i = 0; i < n; i++) status |= gr_set(GR_MAT_ENTRY(A, r1, i, sz), GR_MAT_ENTRY(v, i, 0, sz), ctx); for (i = n; i < n + r1; i++) status |= gr_zero(GR_MAT_ENTRY(A, r1, i, sz), ctx); status |= gr_one(GR_MAT_ENTRY(A, r1, n + r1, sz), ctx); if (status != GR_SUCCESS) goto cleanup; status |= gr_mat_reduce_row(&c1, A, P1, L1, r1, ctx); if (status != GR_SUCCESS) goto cleanup; if (indep && r2 < n && !first_poly) { for (i = 0; i < n; i++) status |= gr_set(GR_MAT_ENTRY(B, r2, i, sz), GR_MAT_ENTRY(v, i, 0, sz), ctx); status |= gr_mat_reduce_row(&c, B, P2, L2, r2, ctx); if (status != GR_SUCCESS) goto cleanup; indep = (c != -1); } } if (first_poly) { for (i = 0; i < n; i++) P2[i] = P1[i]; r2 = r1; } c = -1; for (i = c2 + 1; i < n; i++) { if (P2[i] == -1) { c = i; break; } } c2 = c; gr_poly_fit_length(b, r1 + 1, ctx); status |= gr_inv(h, GR_MAT_ENTRY(A, r1, n + r1, sz), ctx); for (i = 0; i < r1 + 1; i++) { status |= gr_mul(t, GR_MAT_ENTRY(A, r1, n + i, sz), h, ctx); status |= gr_poly_set_coeff_scalar(b, i, t, ctx); } _gr_poly_set_length(b, r1 + 1, ctx); /* todo: poly_divexact */ /* todo: compute as (p * b) / g or (p / g) * b or p * (g / b) ? */ status |= gr_poly_gcd(g, p, b, ctx); status |= gr_poly_mul(p, p, b, ctx); status |= gr_poly_divrem(p, r, p, g, ctx); if (first_poly && r2 < n) { for (i = 0; i < r1; i++) { for (j = 0; j < n; j++) status |= gr_set(GR_MAT_ENTRY(B, i, j, sz), GR_MAT_ENTRY(A, i, j, sz), ctx); } } first_poly = 0; } cleanup: gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(v, ctx); gr_poly_clear(b, ctx); gr_poly_clear(g, ctx); gr_poly_clear(r, ctx); GR_TMP_CLEAR2(t, h, ctx); TMP_END; return status; } flint-3.1.3/src/gr_mat/mul.c000066400000000000000000000012531461254215100156350ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_mul_generic(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { return gr_mat_mul_classical(C, A, B, ctx); } int gr_mat_mul(gr_mat_t res, const gr_mat_t x, const gr_mat_t y, gr_ctx_t ctx) { return GR_MAT_BINARY_OP(ctx, MAT_MUL)(res, x, y, ctx); } flint-3.1.3/src/gr_mat/mul_classical.c000066400000000000000000000064311461254215100176560ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gr_vec.h" #include "gr_mat.h" int gr_mat_mul_classical(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong ar, ac, br, bc, i, j, sz; int status; ar = gr_mat_nrows(A, ctx); ac = gr_mat_ncols(A, ctx); br = gr_mat_nrows(B, ctx); bc = gr_mat_ncols(B, ctx); if (ac != br || ar != gr_mat_nrows(C, ctx) || bc != gr_mat_ncols(C, ctx)) return GR_DOMAIN; if (br == 0) { return gr_mat_zero(C, ctx); } status = GR_SUCCESS; if (A == C || B == C) { gr_mat_t T; gr_mat_init(T, ar, bc, ctx); status |= gr_mat_mul_classical(T, A, B, ctx); status |= gr_mat_swap_entrywise(T, C, ctx); gr_mat_clear(T, ctx); return status; } sz = ctx->sizeof_elem; if (br == 1) { for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { status |= gr_mul(GR_MAT_ENTRY(C, i, j, sz), GR_MAT_ENTRY(A, i, 0, sz), GR_MAT_ENTRY(B, 0, j, sz), ctx); } } } else { gr_ptr tmp; gr_method_void_unary_op set_shallow = GR_VOID_UNARY_OP(ctx, SET_SHALLOW); TMP_INIT; TMP_START; tmp = TMP_ALLOC(sz * br * bc); /* Make a shallow transpose so that we can use dot products. Inline common sizes. (Caution: are we sure about the alignment? Some asserts would be nice here.) Todo: we may want inlining in nonsingular_solve etc. as well. */ for (i = 0; i < br; i++) { for (j = 0; j < bc; j++) { switch (sz) { #if 0 case 1: ((int8_t *) GR_ENTRY(tmp, j * br + i, 1))[0] = ((int8_t *) GR_MAT_ENTRY(B, i, j, 1))[0]; break; case 2: ((int16_t *) GR_ENTRY(tmp, j * br + i, 2))[0] = ((int16_t *) GR_MAT_ENTRY(B, i, j, 2))[0]; break; case 4: ((int32_t *) GR_ENTRY(tmp, j * br + i, 4))[0] = ((int32_t *) GR_MAT_ENTRY(B, i, j, 4))[0]; break; #if FLINT_BITS == 64 case 8: ((int64_t *) GR_ENTRY(tmp, j * br + i, 8))[0] = ((int64_t *) GR_MAT_ENTRY(B, i, j, 8))[0]; break; #endif #endif default: set_shallow(GR_ENTRY(tmp, j * br + i, sz), GR_MAT_ENTRY(B, i, j, sz), ctx); } } } for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { status |= _gr_vec_dot(GR_MAT_ENTRY(C, i, j, sz), NULL, 0, GR_MAT_ENTRY(A, i, 0, sz), GR_ENTRY(tmp, j * br, sz), br, ctx); } } TMP_END; } return status; } flint-3.1.3/src/gr_mat/mul_diag.c000066400000000000000000000016561461254215100166300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_mul_diag(gr_mat_t C, const gr_mat_t A, const gr_vec_t D, gr_ctx_t ctx) { slong ar, ac, i, sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_srcptr Dptr = D->entries; ar = gr_mat_nrows(A, ctx); ac = gr_mat_ncols(A, ctx); if (ar != D->length || ar != gr_mat_nrows(C, ctx) || ac != gr_mat_ncols(C, ctx)) return GR_DOMAIN; for (i = 0; i < ar; i++) status |= _gr_vec_mul(GR_MAT_ENTRY(C, i, 0, sz), GR_MAT_ENTRY(A, i, 0, sz), Dptr, ac, ctx); return status; } flint-3.1.3/src/gr_mat/mul_scalar.c000066400000000000000000000014061461254215100171620ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_mul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx) { slong i, r, c; int status = GR_SUCCESS; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (c != 0) for (i = 0; i < r; i++) status |= _gr_vec_mul_scalar(res->rows[i], mat->rows[i], c, x, ctx); return status; } flint-3.1.3/src/gr_mat/mul_strassen.c000066400000000000000000000123331461254215100175600ustar00rootroot00000000000000/* Copyright (C) 2008, Martin Albrecht Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" #include "fmpz_mat.h" /* todo: optimize for small matrices */ /* todo: bodrato squaring */ /* todo: use fused add-mul operations when supported by the matrix interface in the future */ /* The implemented sequence is not Strassen's nor Winograd's, but the sequence proposed by Bodrato, which is equivalent to Winograd's, and can be easily adapted to compute the square of a matrix. */ int gr_mat_mul_strassen(gr_mat_t C, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong ar, ac, br, bc; slong anr, anc, bnr, bnc; int status = GR_SUCCESS; gr_mat_t A11, A12, A21, A22; gr_mat_t B11, B12, B21, B22; gr_mat_t C11, C12, C21, C22; gr_mat_t X1, X2; ar = A->r; ac = A->c; br = B->r; bc = B->c; if (ar <= 1 || ac <= 1 || bc <= 1) { return gr_mat_mul_classical(C, A, B, ctx); } if (ac != br || ar != C->r || bc != C->c) { return GR_DOMAIN; } if (A == C || B == C) { gr_mat_t T; gr_mat_init(T, ar, bc, ctx); status |= gr_mat_mul_strassen(T, A, B, ctx); status |= gr_mat_swap_entrywise(T, C, ctx); gr_mat_clear(T, ctx); return status; } anr = ar / 2; anc = ac / 2; bnr = anc; bnc = bc / 2; gr_mat_window_init(A11, A, 0, 0, anr, anc, ctx); gr_mat_window_init(A12, A, 0, anc, anr, 2 * anc, ctx); gr_mat_window_init(A21, A, anr, 0, 2 * anr, anc, ctx); gr_mat_window_init(A22, A, anr, anc, 2 * anr, 2 * anc, ctx); gr_mat_window_init(B11, B, 0, 0, bnr, bnc, ctx); gr_mat_window_init(B12, B, 0, bnc, bnr, 2 * bnc, ctx); gr_mat_window_init(B21, B, bnr, 0, 2 * bnr, bnc, ctx); gr_mat_window_init(B22, B, bnr, bnc, 2 * bnr, 2 * bnc, ctx); gr_mat_window_init(C11, C, 0, 0, anr, bnc, ctx); gr_mat_window_init(C12, C, 0, bnc, anr, 2 * bnc, ctx); gr_mat_window_init(C21, C, anr, 0, 2 * anr, bnc, ctx); gr_mat_window_init(C22, C, anr, bnc, 2 * anr, 2 * bnc, ctx); gr_mat_init(X1, anr, FLINT_MAX(bnc, anc), ctx); gr_mat_init(X2, anc, bnc, ctx); X1->c = anc; status |= gr_mat_add(X1, A22, A12, ctx); status |= gr_mat_add(X2, B22, B12, ctx); status |= gr_mat_mul(C21, X1, X2, ctx); status |= gr_mat_sub(X1, A22, A21, ctx); status |= gr_mat_sub(X2, B22, B21, ctx); status |= gr_mat_mul(C22, X1, X2, ctx); status |= gr_mat_add(X1, X1, A12, ctx); status |= gr_mat_add(X2, X2, B12, ctx); status |= gr_mat_mul(C11, X1, X2, ctx); status |= gr_mat_sub(X1, X1, A11, ctx); status |= gr_mat_mul(C12, X1, B12, ctx); X1->c = bnc; status |= gr_mat_mul(X1, A12, B21, ctx); status |= gr_mat_add(C11, C11, X1, ctx); status |= gr_mat_add(C12, C12, C22, ctx); status |= gr_mat_sub(C12, C11, C12, ctx); status |= gr_mat_sub(C11, C21, C11, ctx); status |= gr_mat_sub(X2, X2, B11, ctx); status |= gr_mat_mul(C21, A21, X2, ctx); gr_mat_clear(X2, ctx); status |= gr_mat_sub(C21, C11, C21, ctx); status |= gr_mat_add(C22, C22, C11, ctx); status |= gr_mat_mul(C11, A11, B11, ctx); status |= gr_mat_add(C11, X1, C11, ctx); X1->c = FLINT_MAX(bnc, anc); gr_mat_clear(X1, ctx); gr_mat_window_clear(A11, ctx); gr_mat_window_clear(A12, ctx); gr_mat_window_clear(A21, ctx); gr_mat_window_clear(A22, ctx); gr_mat_window_clear(B11, ctx); gr_mat_window_clear(B12, ctx); gr_mat_window_clear(B21, ctx); gr_mat_window_clear(B22, ctx); gr_mat_window_clear(C11, ctx); gr_mat_window_clear(C12, ctx); gr_mat_window_clear(C21, ctx); gr_mat_window_clear(C22, ctx); if (bc > 2 * bnc) { gr_mat_t Bc, Cc; gr_mat_window_init(Bc, B, 0, 2 * bnc, ac, bc, ctx); gr_mat_window_init(Cc, C, 0, 2 * bnc, ar, bc, ctx); status |= gr_mat_mul(Cc, A, Bc, ctx); gr_mat_window_clear(Bc, ctx); gr_mat_window_clear(Cc, ctx); } if (ar > 2 * anr) { gr_mat_t Ar, Cr; gr_mat_window_init(Ar, A, 2 * anr, 0, ar, ac, ctx); gr_mat_window_init(Cr, C, 2 * anr, 0, ar, bc, ctx); status |= gr_mat_mul(Cr, Ar, B, ctx); gr_mat_window_clear(Ar, ctx); gr_mat_window_clear(Cr, ctx); } if (ac > 2 * anc) { gr_mat_t Ac, Br, Cb, tmp; slong mt, nt; gr_mat_window_init(Ac, A, 0, 2 * anc, 2 * anr, ac, ctx); gr_mat_window_init(Br, B, 2 * bnr, 0, ac, 2 * bnc, ctx); gr_mat_window_init(Cb, C, 0, 0, 2 * anr, 2 * bnc, ctx); mt = Ac->r; nt = Br->c; gr_mat_init(tmp, mt, nt, ctx); status |= gr_mat_mul(tmp, Ac, Br, ctx); status |= gr_mat_add(Cb, Cb, tmp, ctx); gr_mat_clear(tmp, ctx); gr_mat_window_clear(Ac, ctx); gr_mat_window_clear(Br, ctx); gr_mat_window_clear(Cb, ctx); } return status; } flint-3.1.3/src/gr_mat/neg.c000066400000000000000000000015341461254215100156130ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_neg(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { int status; slong i, r, c; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (r != gr_mat_nrows(mat, ctx) || c != gr_mat_ncols(mat, ctx)) { return GR_DOMAIN; } status = GR_SUCCESS; for (i = 0; i < r; i++) { status |= _gr_vec_neg(res->rows[i], mat->rows[i], c, ctx); } return status; } flint-3.1.3/src/gr_mat/nonsingular_solve.c000066400000000000000000000014031461254215100206040ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: solve_adjugate for n <= 4 */ /* todo: algorithm selection */ int gr_mat_nonsingular_solve(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { if (gr_ctx_is_field(ctx) == T_TRUE || gr_ctx_is_exact(ctx) == T_FALSE) return gr_mat_nonsingular_solve_lu(X, A, B, ctx); else return gr_mat_nonsingular_solve_fflu(X, A, B, ctx); } flint-3.1.3/src/gr_mat/nonsingular_solve_den.c000066400000000000000000000011661461254215100214400ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" /* todo: algorithm selection */ int gr_mat_nonsingular_solve_den(gr_mat_t X, gr_ptr den, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { return gr_mat_nonsingular_solve_den_fflu(X, den, A, B, ctx); } flint-3.1.3/src/gr_mat/nonsingular_solve_den_fflu.c000066400000000000000000000021341461254215100224500ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_nonsingular_solve_den_fflu(gr_mat_t X, gr_ptr den, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { int status = GR_SUCCESS; slong rank, n, m, *perm; gr_mat_t LU; n = gr_mat_nrows(A, ctx); m = gr_mat_ncols(X, ctx); if (n == 0) return GR_SUCCESS; perm = _perm_init(n); gr_mat_init(LU, n, n, ctx); status = gr_mat_fflu(&rank, perm, LU, den, A, 1, ctx); if (status == GR_SUCCESS && rank == n) { if (m != 0) status |= gr_mat_nonsingular_solve_fflu_precomp(X, perm, LU, B, ctx); } else { status |= GR_DOMAIN; } gr_mat_clear(LU, ctx); _perm_clear(perm); return status; } flint-3.1.3/src/gr_mat/nonsingular_solve_fflu.c000066400000000000000000000015371461254215100216300ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_nonsingular_solve_fflu(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { int status; gr_ptr den; slong m; GR_TMP_INIT(den, ctx); status = gr_mat_nonsingular_solve_den_fflu(X, den, A, B, ctx); m = gr_mat_ncols(X, ctx); if (status == GR_SUCCESS) { if (m != 0) status |= gr_mat_div_scalar(X, X, den, ctx); } GR_TMP_CLEAR(den, ctx); return status; } flint-3.1.3/src/gr_mat/nonsingular_solve_fflu_precomp.c000066400000000000000000000060641461254215100233550ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: check that dimensions are compatible */ int gr_mat_nonsingular_solve_fflu_precomp(gr_mat_t X, const slong * perm, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong i, j, k, c, n, m; gr_ptr t; n = gr_mat_nrows(X, ctx); m = gr_mat_ncols(X, ctx); if (X == B) { gr_method_void_unary_op set_shallow = GR_VOID_UNARY_OP(ctx, SET_SHALLOW); /* todo: don't use malloc */ gr_ptr tmp = flint_malloc(sz * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) set_shallow(GR_ENTRY(tmp, i, sz), GR_MAT_ENTRY(B, perm[i], c, sz), ctx); for (i = 0; i < n; i++) set_shallow(GR_MAT_ENTRY(X, i, c, sz), GR_ENTRY(tmp, i, sz), ctx); } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { status |= gr_set(GR_MAT_ENTRY(X, i, c, sz), GR_MAT_ENTRY(B, perm[i], c, sz), ctx); } } } { GR_TMP_INIT(t, ctx); /* todo: use submul */ /* todo: use divexact? */ for (k = 0; k < m; k++) { /* Fraction-free forward substitution */ for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { status |= gr_mul(GR_MAT_ENTRY(X, j, k, sz), GR_MAT_ENTRY(X, j, k, sz), GR_MAT_ENTRY(A, i, i, sz), ctx); status |= gr_mul(t, GR_MAT_ENTRY(A, j, i, sz), GR_MAT_ENTRY(X, i, k, sz), ctx); status |= gr_sub(GR_MAT_ENTRY(X, j, k, sz), GR_MAT_ENTRY(X, j, k, sz), t, ctx); if (i > 0) status |= gr_div(GR_MAT_ENTRY(X, j, k, sz), GR_MAT_ENTRY(X, j, k, sz), GR_MAT_ENTRY(A, i-1, i-1, sz), ctx); } } /* Fraction-free back substitution */ for (i = n - 2; i >= 0; i--) { status |= gr_mul(GR_MAT_ENTRY(X, i, k, sz), GR_MAT_ENTRY(X, i, k, sz), GR_MAT_ENTRY(A, n-1, n-1, sz), ctx); for (j = i + 1; j < n; j++) { status |= gr_mul(t, GR_MAT_ENTRY(X, j, k, sz), GR_MAT_ENTRY(A, i, j, sz), ctx); status |= gr_sub(GR_MAT_ENTRY(X, i, k, sz), GR_MAT_ENTRY(X, i, k, sz), t, ctx); } status |= gr_div(GR_MAT_ENTRY(X, i, k, sz), GR_MAT_ENTRY(X, i, k, sz), GR_MAT_ENTRY(A, i, i, sz), ctx); } } /* status |= gr_mat_div_scalar(X, X, den, ctx); */ GR_TMP_CLEAR(t, ctx); } return status; } flint-3.1.3/src/gr_mat/nonsingular_solve_lu.c000066400000000000000000000021011461254215100213000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_nonsingular_solve_lu(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { int status = GR_SUCCESS; slong rank, n, m, *perm; gr_mat_t LU; n = gr_mat_nrows(A, ctx); m = gr_mat_ncols(X, ctx); if (n == 0) return GR_SUCCESS; perm = _perm_init(n); gr_mat_init(LU, n, n, ctx); status = gr_mat_lu(&rank, perm, LU, A, 1, ctx); if (status == GR_SUCCESS && rank == n) { if (m != 0) status |= gr_mat_nonsingular_solve_lu_precomp(X, perm, LU, B, ctx); } else { status |= GR_DOMAIN; } gr_mat_clear(LU, ctx); _perm_clear(perm); return status; } flint-3.1.3/src/gr_mat/nonsingular_solve_lu_precomp.c000066400000000000000000000031521461254215100230340ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: check that dimensions are compatible */ int gr_mat_nonsingular_solve_lu_precomp(gr_mat_t X, const slong * perm, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong i, c, n, m; n = gr_mat_nrows(X, ctx); m = gr_mat_ncols(X, ctx); if (X == B) { gr_method_void_unary_op set_shallow = GR_VOID_UNARY_OP(ctx, SET_SHALLOW); gr_ptr tmp = flint_malloc(sz * n); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) set_shallow(GR_ENTRY(tmp, i, sz), GR_MAT_ENTRY(B, perm[i], c, sz), ctx); for (i = 0; i < n; i++) set_shallow(GR_MAT_ENTRY(X, i, c, sz), GR_ENTRY(tmp, i, sz), ctx); } flint_free(tmp); } else { for (c = 0; c < m; c++) { for (i = 0; i < n; i++) { status |= gr_set(GR_MAT_ENTRY(X, i, c, sz), GR_MAT_ENTRY(B, perm[i], c, sz), ctx); } } } /* todo: inline for small n? */ status |= gr_mat_nonsingular_solve_tril(X, A, X, 1, ctx); status |= gr_mat_nonsingular_solve_triu(X, A, X, 0, ctx); return status; } flint-3.1.3/src/gr_mat/nonsingular_solve_tril.c000066400000000000000000000103301461254215100216350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" /* todo: efficient column extraction */ int gr_mat_nonsingular_solve_tril_classical(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx) { slong i, j, n, m; gr_ptr tmp; gr_ptr inv = NULL; /* silence compiler warning */ gr_ptr s; int use_division = 0; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_method_void_unary_op set_shallow = GR_VOID_UNARY_OP(ctx, SET_SHALLOW); n = L->r; m = B->c; if (!unit) { GR_TMP_INIT_VEC(inv, n, ctx); for (i = 0; i < n; i++) { status = gr_inv(GR_ENTRY(inv, i, sz), GR_MAT_ENTRY(L, i, i, sz), ctx); if (status != GR_SUCCESS) { use_division = 1; status = GR_SUCCESS; break; } } } GR_TMP_INIT(s, ctx); tmp = flint_malloc(sz * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) set_shallow(GR_ENTRY(tmp, j, sz), GR_MAT_ENTRY(X, j, i, sz), ctx); for (j = 0; j < n; j++) { status |= _gr_vec_dot(s, GR_MAT_ENTRY(B, j, i, sz), 1, GR_MAT_ENTRY(L, j, 0, sz), tmp, j, ctx); if (!unit) { if (use_division) status |= gr_div(GR_ENTRY(tmp, j, sz), s, GR_MAT_ENTRY(L, j, j, sz), ctx); else status |= gr_mul(GR_ENTRY(tmp, j, sz), s, GR_ENTRY(inv, j, sz), ctx); } else gr_swap(GR_ENTRY(tmp, j, sz), s, ctx); if (status != GR_SUCCESS) { for (j = 0; j < n; j++) set_shallow(GR_MAT_ENTRY(X, j, i, sz), GR_ENTRY(tmp, j, sz), ctx); goto cleanup; } } for (j = 0; j < n; j++) set_shallow(GR_MAT_ENTRY(X, j, i, sz), GR_ENTRY(tmp, j, sz), ctx); } cleanup: if (!unit) { GR_TMP_CLEAR_VEC(inv, n, ctx); } flint_free(tmp); GR_TMP_CLEAR(s, ctx); return status; } int gr_mat_nonsingular_solve_tril_recursive(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx) { gr_mat_t LA, LC, LD, XX, XY, BX, BY, T; slong r, n, m; int status = GR_SUCCESS; n = L->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return GR_SUCCESS; /* Denoting inv(M) by M^, we have: [A 0]^ [X] == [A^ 0 ] [X] == [A^ X] [C D] [Y] == [-D^ C A^ D^] [Y] == [D^ (Y - C A^ X)] */ gr_mat_window_init(LA, L, 0, 0, r, r, ctx); gr_mat_window_init(LC, L, r, 0, n, r, ctx); gr_mat_window_init(LD, L, r, r, n, n, ctx); gr_mat_window_init(BX, B, 0, 0, r, m, ctx); gr_mat_window_init(BY, B, r, 0, n, m, ctx); gr_mat_window_init(XX, X, 0, 0, r, m, ctx); gr_mat_window_init(XY, X, r, 0, n, m, ctx); status |= gr_mat_nonsingular_solve_tril(XX, LA, BX, unit, ctx); if (status == GR_SUCCESS) { /* submul(XY, BY, LC, XX); */ gr_mat_init(T, LC->r, BX->c, ctx); status |= gr_mat_mul(T, LC, XX, ctx); status |= gr_mat_sub(XY, BY, T, ctx); gr_mat_clear(T, ctx); status |= gr_mat_nonsingular_solve_tril(XY, LD, XY, unit, ctx); } gr_mat_window_clear(LA, ctx); gr_mat_window_clear(LC, ctx); gr_mat_window_clear(LD, ctx); gr_mat_window_clear(BX, ctx); gr_mat_window_clear(BY, ctx); gr_mat_window_clear(XX, ctx); gr_mat_window_clear(XY, ctx); return status; } int gr_mat_nonsingular_solve_tril(gr_mat_t X, const gr_mat_t L, const gr_mat_t B, int unit, gr_ctx_t ctx) { /* todo: tune thresholds */ if (B->r < 10 || B->c < 10) return gr_mat_nonsingular_solve_tril_classical(X, L, B, unit, ctx); else return gr_mat_nonsingular_solve_tril_recursive(X, L, B, unit, ctx); } flint-3.1.3/src/gr_mat/nonsingular_solve_triu.c000066400000000000000000000103351461254215100216530ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" /* todo: efficient column extraction */ int gr_mat_nonsingular_solve_triu_classical(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx) { slong i, j, n, m; gr_ptr tmp; gr_ptr inv = NULL; /* silence compiler warning */ gr_ptr s; int use_division = 0; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_method_void_unary_op set_shallow = GR_VOID_UNARY_OP(ctx, SET_SHALLOW); n = U->r; m = B->c; if (!unit) { GR_TMP_INIT_VEC(inv, n, ctx); for (i = 0; i < n; i++) { status = gr_inv(GR_ENTRY(inv, i, sz), GR_MAT_ENTRY(U, i, i, sz), ctx); if (status != GR_SUCCESS) { use_division = 1; status = GR_SUCCESS; break; } } } GR_TMP_INIT(s, ctx); tmp = flint_malloc(sz * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) set_shallow(GR_ENTRY(tmp, j, sz), GR_MAT_ENTRY(X, j, i, sz), ctx); for (j = n - 1; j >= 0; j--) { status |= _gr_vec_dot(s, GR_MAT_ENTRY(B, j, i, sz), 1, GR_MAT_ENTRY(U, j, j + 1, sz), GR_ENTRY(tmp, j + 1, sz), n - j - 1, ctx); if (!unit) { if (use_division) status |= gr_div(GR_ENTRY(tmp, j, sz), s, GR_MAT_ENTRY(U, j, j, sz), ctx); else status |= gr_mul(GR_ENTRY(tmp, j, sz), s, GR_ENTRY(inv, j, sz), ctx); } else gr_swap(GR_ENTRY(tmp, j, sz), s, ctx); if (status != GR_SUCCESS) { for (j = 0; j < n; j++) set_shallow(GR_MAT_ENTRY(X, j, i, sz), GR_ENTRY(tmp, j, sz), ctx); goto cleanup; } } for (j = 0; j < n; j++) set_shallow(GR_MAT_ENTRY(X, j, i, sz), GR_ENTRY(tmp, j, sz), ctx); } cleanup: if (!unit) { GR_TMP_CLEAR_VEC(inv, n, ctx); } flint_free(tmp); GR_TMP_CLEAR(s, ctx); return status; } int gr_mat_nonsingular_solve_triu_recursive(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx) { gr_mat_t UA, UB, UD, XX, XY, BX, BY, T; slong r, n, m; int status = GR_SUCCESS; n = U->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return GR_SUCCESS; /* Denoting inv(M) by M^, we have: [A B]^ [X] == [A^ (X - B D^ Y)] [0 D] [Y] == [ D^ Y ] */ gr_mat_window_init(UA, U, 0, 0, r, r, ctx); gr_mat_window_init(UB, U, 0, r, r, n, ctx); gr_mat_window_init(UD, U, r, r, n, n, ctx); gr_mat_window_init(BX, B, 0, 0, r, m, ctx); gr_mat_window_init(BY, B, r, 0, n, m, ctx); gr_mat_window_init(XX, X, 0, 0, r, m, ctx); gr_mat_window_init(XY, X, r, 0, n, m, ctx); status |= gr_mat_nonsingular_solve_triu(XY, UD, BY, unit, ctx); if (status == GR_SUCCESS) { /* gr_mat_submul(XX, BX, UB, XY); */ gr_mat_init(T, UB->r, XY->c, ctx); status |= gr_mat_mul(T, UB, XY, ctx); status |= gr_mat_sub(XX, BX, T, ctx); gr_mat_clear(T, ctx); status |= gr_mat_nonsingular_solve_triu(XX, UA, XX, unit, ctx); } gr_mat_window_clear(UA, ctx); gr_mat_window_clear(UB, ctx); gr_mat_window_clear(UD, ctx); gr_mat_window_clear(BX, ctx); gr_mat_window_clear(BY, ctx); gr_mat_window_clear(XX, ctx); gr_mat_window_clear(XY, ctx); return status; } int gr_mat_nonsingular_solve_triu(gr_mat_t X, const gr_mat_t U, const gr_mat_t B, int unit, gr_ctx_t ctx) { /* todo: tune thresholds */ if (B->r < 10 || B->c < 10) return gr_mat_nonsingular_solve_triu_classical(X, U, B, unit, ctx); else return gr_mat_nonsingular_solve_triu_recursive(X, U, B, unit, ctx); } flint-3.1.3/src/gr_mat/nullspace.c000066400000000000000000000064211461254215100170300ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_nullspace(gr_mat_t X, const gr_mat_t A, gr_ctx_t ctx) { slong i, j, k, m, n, rank, nullity; slong *p; slong *pivots; slong *nonpivots; gr_mat_t tmp; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_ptr den; int with_den; m = gr_mat_nrows(A, ctx); n = gr_mat_ncols(A, ctx); p = flint_malloc(sizeof(slong) * FLINT_MAX(m, n)); gr_mat_init(tmp, m, n, ctx); GR_TMP_INIT(den, ctx); with_den = gr_ctx_is_field(ctx) == T_FALSE && gr_ctx_is_integral_domain(ctx) == T_TRUE; if (with_den) { status |= gr_mat_rref_den(&rank, tmp, den, A, ctx); } else { status |= gr_mat_rref(&rank, tmp, A, ctx); } nullity = n - rank; if (status != GR_SUCCESS) goto cleanup; /* todo: have a resize function */ gr_mat_clear(X, ctx); gr_mat_init(X, n, nullity, ctx); if (rank == 0) { for (i = 0; i < nullity; i++) status |= gr_one(GR_MAT_ENTRY(X, i, i, sz), ctx); } else if (nullity) { pivots = p; /* length = rank */ nonpivots = p + rank; /* length = nullity */ for (i = j = k = 0; i < rank; i++) { while (1) { /* Todo: this should not be T_UNKNOWN. Should we save the pivot data in the lu algorithm? */ truth_t is_zero = gr_is_zero(GR_MAT_ENTRY(tmp, i, j, sz), ctx); if (is_zero == T_FALSE) { break; } else if (is_zero == T_TRUE) { nonpivots[k] = j; k++; j++; } else { status = GR_UNABLE; goto cleanup; } } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } if (with_den) { /* if we did not keep den, equivalently den = tmp[0, pivots[0]] here */ for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) status |= gr_neg(GR_MAT_ENTRY(X, pivots[j], i, sz), GR_MAT_ENTRY(tmp, j, nonpivots[i], sz), ctx); status |= gr_set(GR_MAT_ENTRY(X, nonpivots[i], + i, sz), den, ctx); } } else { for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) status |= gr_neg(GR_MAT_ENTRY(X, pivots[j], i, sz), GR_MAT_ENTRY(tmp, j, nonpivots[i], sz), ctx); status |= gr_one(GR_MAT_ENTRY(X, nonpivots[i], i, sz), ctx); } } } cleanup: flint_free(p); gr_mat_clear(tmp, ctx); GR_TMP_CLEAR(den, ctx); return status; } flint-3.1.3/src/gr_mat/one.c000066400000000000000000000014221461254215100156170ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_one(gr_mat_t res, gr_ctx_t ctx) { int status; slong i, r, c, sz; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); sz = ctx->sizeof_elem; status = gr_mat_zero(res, ctx); if (r > 0 && c > 0) { for (i = 0; i < FLINT_MIN(r, c); i++) status |= gr_one(GR_MAT_ENTRY(res, i, i, sz), ctx); } return status; } flint-3.1.3/src/gr_mat/ones.c000066400000000000000000000013521461254215100160040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_ones(gr_mat_t mat, gr_ctx_t ctx) { slong R, C, i, j; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; R = gr_mat_nrows(mat, ctx); C = gr_mat_ncols(mat, ctx); for (i = 0; i < R; i++) for (j = 0; j < C; j++) status |= gr_one(GR_MAT_ENTRY(mat, i, j, sz), ctx); return status; } flint-3.1.3/src/gr_mat/pascal.c000066400000000000000000000043051461254215100163040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: optimize for fmpz */ int gr_mat_pascal(gr_mat_t mat, int triangular, gr_ctx_t ctx) { slong R, C, i, j; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; #define ENTRY(i, j) GR_MAT_ENTRY(mat, i, j, sz) R = gr_mat_nrows(mat, ctx); C = gr_mat_ncols(mat, ctx); if (R == 0 || C == 0) return status; if (triangular == 1) { for (i = 1; i < R; i++) for (j = 0; j < i && j < C; j++) status |= gr_zero(ENTRY(i, j), ctx); for (j = 0; j < C; j++) status |= gr_one(ENTRY(0, j), ctx); for (i = 1; i < R && i < C; i++) status |= gr_one(ENTRY(i, i), ctx); for (i = 1; i < R; i++) for (j = i + 1; j < C; j++) status |= gr_add(ENTRY(i, j), ENTRY(i, j - 1), ENTRY(i - 1, j - 1), ctx); } else if (triangular == -1) { for (i = 0; i < R; i++) for (j = i + 1; j < C; j++) status |= gr_zero(ENTRY(i, j), ctx); for (i = 0; i < R; i++) status |= gr_one(ENTRY(i, 0), ctx); for (i = 1; i < R && i < C; i++) status |= gr_one(ENTRY(i, i), ctx); for (i = 2; i < R; i++) for (j = 1; j < i && j < C; j++) status |= gr_add(ENTRY(i, j), ENTRY(i - 1, j - 1), ENTRY(i - 1, j), ctx); } else if (triangular == 0) { for (j = 0; j < C; j++) status |= gr_one(ENTRY(0, j), ctx); for (i = 1; i < R; i++) status |= gr_one(ENTRY(i, 0), ctx); for (i = 1; i < R; i++) for (j = 1; j < C; j++) status |= gr_add(ENTRY(i, j), ENTRY(i, j - 1), ENTRY(i - 1, j), ctx); } else { status = GR_DOMAIN; } return status; } flint-3.1.3/src/gr_mat/randops.c000066400000000000000000000034271461254215100165130ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_randops(gr_mat_t mat, flint_rand_t state, slong count, gr_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (mat->r == 0 || mat->c == 0) return GR_SUCCESS; for (c = 0; c < count; c++) { if (n_randint(state, 2)) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) status |= gr_add(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); else for (k = 0; k < n; k++) status |= gr_sub(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); } else { if ((i = n_randint(state, n)) == (j = n_randint(state, n))) continue; if (n_randint(state, 2)) for (k = 0; k < m; k++) status |= gr_add(GR_MAT_ENTRY(mat, k, j, sz), GR_MAT_ENTRY(mat, k, j, sz), GR_MAT_ENTRY(mat, k, i, sz), ctx); else for (k = 0; k < m; k++) status |= gr_sub(GR_MAT_ENTRY(mat, k, j, sz), GR_MAT_ENTRY(mat, k, j, sz), GR_MAT_ENTRY(mat, k, i, sz), ctx); } } return status; } flint-3.1.3/src/gr_mat/randpermdiag.c000066400000000000000000000021431461254215100174740ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_randpermdiag(int * _parity, gr_mat_t mat, flint_rand_t state, gr_ptr diag, slong n, gr_ctx_t ctx) { int parity; slong i; slong *rows; slong *cols; int status = GR_SUCCESS; if (n > mat->r || n > mat->c) return GR_DOMAIN; rows = _perm_init(mat->r); cols = _perm_init(mat->c); parity = _perm_randtest(rows, mat->r, state); parity ^= _perm_randtest(cols, mat->c, state); status |= gr_mat_zero(mat, ctx); for (i = 0; i < n; i++) status |= gr_set(gr_mat_entry_ptr(mat, rows[i], cols[i], ctx), GR_ENTRY(diag, i, ctx->sizeof_elem), ctx); _perm_clear(rows); _perm_clear(cols); *_parity = parity; return status; } flint-3.1.3/src/gr_mat/randrank.c000066400000000000000000000017031461254215100166400ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_randrank(gr_mat_t mat, flint_rand_t state, slong rank, gr_ctx_t ctx) { slong i; gr_ptr diag; int status = GR_SUCCESS; int parity; if (rank < 0 || rank > mat->r || rank > mat->c) return GR_DOMAIN; GR_TMP_INIT_VEC(diag, rank, ctx); for (i = 0; i < rank; i++) status |= gr_randtest_not_zero(GR_ENTRY(diag, i, ctx->sizeof_elem), state, ctx); status |= gr_mat_randpermdiag(&parity, mat, state, diag, rank, ctx); GR_TMP_CLEAR_VEC(diag, rank, ctx); return status; } flint-3.1.3/src/gr_mat/randtest.c000066400000000000000000000014351461254215100166660ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" /* todo: want to try different algorithms here */ int gr_mat_randtest(gr_mat_t mat, flint_rand_t state, gr_ctx_t ctx) { int status; slong i, r, c; r = gr_mat_nrows(mat, ctx); c = gr_mat_ncols(mat, ctx); status = GR_SUCCESS; for (i = 0; i < r; i++) { status |= _gr_vec_randtest(mat->rows[i], state, c, ctx); } return status; } flint-3.1.3/src/gr_mat/rank.c000066400000000000000000000013261461254215100157740ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" /* todo: different algorithms */ int gr_mat_rank(slong * rank, const gr_mat_t A, gr_ctx_t ctx) { truth_t dom; dom = gr_ctx_is_integral_domain(ctx); if (dom == T_TRUE) return gr_mat_rank_fflu(rank, A, ctx); if (dom == T_FALSE) return GR_DOMAIN; return GR_UNABLE; } flint-3.1.3/src/gr_mat/rank_fflu.c000066400000000000000000000020601461254215100170040ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_rank_fflu(slong * rank, const gr_mat_t A, gr_ctx_t ctx) { slong n, m; slong * P; int status; gr_mat_t T; gr_ptr den; n = gr_mat_nrows(A, ctx); m = gr_mat_ncols(A, ctx); if (n == 0 || m == 0) { *rank = 0; return GR_SUCCESS; } else { GR_TMP_INIT(den, ctx); gr_mat_init(T, n, m, ctx); P = _perm_init(n); status = gr_mat_fflu(rank, P, T, den, A, 0, ctx); gr_mat_clear(T, ctx); _perm_clear(P); GR_TMP_CLEAR(den, ctx); if (status != GR_SUCCESS) status |= GR_UNABLE; return status; } } flint-3.1.3/src/gr_mat/rank_lu.c000066400000000000000000000017261461254215100165000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_rank_lu(slong * rank, const gr_mat_t A, gr_ctx_t ctx) { slong n, m; slong * P; int status; gr_mat_t T; n = gr_mat_nrows(A, ctx); m = gr_mat_ncols(A, ctx); if (n == 0 || m == 0) { *rank = 0; return GR_SUCCESS; } else { gr_mat_init(T, n, m, ctx); P = _perm_init(n); status = gr_mat_lu(rank, P, T, A, 0, ctx); gr_mat_clear(T, ctx); _perm_clear(P); if (status != GR_SUCCESS) status |= GR_UNABLE; return status; } } flint-3.1.3/src/gr_mat/reduce_row.c000066400000000000000000000034771461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_reduce_row(slong * column, gr_mat_t A, slong * P, slong * L, slong m, gr_ctx_t ctx) { int status = GR_SUCCESS; slong n = A->c, i, j, r; gr_ptr h; truth_t is_zero; slong sz = ctx->sizeof_elem; *column = -1; GR_TMP_INIT(h, ctx); for (i = 0; i < n; i++) { is_zero = gr_is_zero(GR_MAT_ENTRY(A, m, i, sz), ctx); if (is_zero == T_UNKNOWN) { status |= GR_UNABLE; break; } if (is_zero == T_FALSE) { r = P[i]; if (r != -1) { for (j = i + 1; j < L[r]; j++) { status |= gr_mul(h, GR_MAT_ENTRY(A, r, j, sz), GR_MAT_ENTRY(A, m, i, sz), ctx); status |= gr_sub(GR_MAT_ENTRY(A, m, j, sz), GR_MAT_ENTRY(A, m, j, sz), h, ctx); } status |= gr_zero(GR_MAT_ENTRY(A, m, i, sz), ctx); } else { status |= gr_inv(h, GR_MAT_ENTRY(A, m, i, sz), ctx); status |= gr_one(GR_MAT_ENTRY(A, m, i, sz), ctx); for (j = i + 1; j < L[m]; j++) status |= gr_mul(GR_MAT_ENTRY(A, m, j, sz), GR_MAT_ENTRY(A, m, j, sz), h, ctx); P[i] = m; *column = i; break; } } } GR_TMP_CLEAR(h, ctx); return status; } flint-3.1.3/src/gr_mat/rref.c000066400000000000000000000010501461254215100157710ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_rref(slong * res_rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx) { return gr_mat_rref_lu(res_rank, R, A, ctx); } flint-3.1.3/src/gr_mat/rref_den.c000066400000000000000000000011031461254215100166160ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_rref_den(slong * res_rank, gr_mat_t R, gr_ptr den, const gr_mat_t A, gr_ctx_t ctx) { return gr_mat_rref_den_fflu(res_rank, R, den, A, ctx); } flint-3.1.3/src/gr_mat/rref_fflu.c000066400000000000000000000107111461254215100170110ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" static int _gr_mat_rref_fflu(slong * res_rank, gr_mat_t R, gr_ptr den, const gr_mat_t A, int divided, gr_ctx_t ctx) { slong i, j, k, m, n, rank; slong *pivots; slong *nonpivots; slong *P; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (gr_mat_is_zero(A, ctx) == T_TRUE) { *res_rank = 0; status |= gr_one(den, ctx); return status; } P = _perm_init(gr_mat_nrows(A, ctx)); status |= gr_mat_fflu(&rank, P, R, den, A, 0, ctx); _perm_clear(P); if (status != GR_SUCCESS) return status; m = gr_mat_nrows(R, ctx); n = gr_mat_ncols(R, ctx); /* clear bottom */ for (i = rank; i < m; i++) for (j = 0; j < n; j++) status |= gr_zero(GR_MAT_ENTRY(R, i, j, sz), ctx); /* Convert row echelon form to reduced row echelon form */ if (rank > 1) { gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); pivots = flint_malloc(sizeof(slong) * n); nonpivots = pivots + rank; for (i = j = k = 0; i < rank; i++) { while (1) { /* Todo: this should not be T_UNKNOWN. Should we save the pivot data in the lu algorithm? */ truth_t is_zero = gr_is_zero(GR_MAT_ENTRY(R, i, j, sz), ctx); if (is_zero == T_FALSE) { break; } else if (is_zero == T_TRUE) { nonpivots[k] = j; k++; j++; } else { status = GR_UNABLE; goto cleanup1; } } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (k = 0; k < n - rank; k++) { for (i = rank - 2; i >= 0; i--) { status |= gr_mul(t, den, GR_MAT_ENTRY(R, i, nonpivots[k], sz), ctx); for (j = i + 1; j < rank; j++) { /* should be submul */ status |= gr_mul(u, GR_MAT_ENTRY(R, i, pivots[j], sz), GR_MAT_ENTRY(R, j, nonpivots[k], sz), ctx); status |= gr_sub(t, t, u, ctx); } /* should be divexact */ status |= gr_div(GR_MAT_ENTRY(R, i, nonpivots[k], sz), t, GR_MAT_ENTRY(R, i, pivots[i], sz), ctx); } } /* clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { if (i == j) if (divided) status |= gr_one(GR_MAT_ENTRY(R, j, pivots[i], sz), ctx); else status |= gr_set(GR_MAT_ENTRY(R, j, pivots[i], sz), den, ctx); else status |= gr_zero(GR_MAT_ENTRY(R, j, pivots[i], sz), ctx); } } /* divide out denominator */ if (divided && gr_is_one(den, ctx) != T_TRUE) for (i = 0; i < rank; i++) for (j = 0; j < n - rank; j++) status |= gr_div(GR_MAT_ENTRY(R, i, nonpivots[j], sz), GR_MAT_ENTRY(R, i, nonpivots[j], sz), den, ctx); cleanup1: flint_free(pivots); GR_TMP_CLEAR2(t, u, ctx); } else if (rank == 1 && divided && gr_is_one(den, ctx) != T_TRUE) { for (i = 0; i < n; i++) status |= gr_div(GR_MAT_ENTRY(R, 0, i, sz), GR_MAT_ENTRY(R, 0, i, sz), den, ctx); } *res_rank = rank; return status; } int gr_mat_rref_den_fflu(slong * res_rank, gr_mat_t R, gr_ptr den, const gr_mat_t A, gr_ctx_t ctx) { return _gr_mat_rref_fflu(res_rank, R, den, A, 0, ctx); } int gr_mat_rref_fflu(slong * res_rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx) { int status; gr_ptr den; GR_TMP_INIT(den, ctx); status = _gr_mat_rref_fflu(res_rank, R, den, A, 1, ctx); GR_TMP_CLEAR(den, ctx); return status; } flint-3.1.3/src/gr_mat/rref_lu.c000066400000000000000000000067561461254215100165130ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "gr_mat.h" int gr_mat_rref_lu(slong * res_rank, gr_mat_t R, const gr_mat_t A, gr_ctx_t ctx) { slong i, j, k, n, rank; slong *pivots; slong *nonpivots; slong *P; gr_mat_t U, V; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (gr_mat_is_zero(A, ctx) == T_TRUE) { *res_rank = 0; return GR_SUCCESS; } /* Todo: fast path for nrows == 1 */ n = A->c; P = _perm_init(gr_mat_nrows(A, ctx)); status = gr_mat_lu(&rank, P, R, A, 0, ctx); _perm_clear(P); if (status != GR_SUCCESS) return status; if (rank == 0) { *res_rank = 0; return GR_SUCCESS; } /* Clear L */ for (i = 0; i < A->r; i++) for (j = 0; j < FLINT_MIN(i, rank); j++) status |= gr_zero(GR_MAT_ENTRY(R, i, j, sz), ctx); /* We now reorder U to proper upper triangular form U | V with U full-rank triangular, set V = U^(-1) V, and then put the column back in the original order. An improvement for some matrices would be to compress V by discarding columns containing nothing but zeros. */ gr_mat_init(U, rank, rank, ctx); gr_mat_init(V, rank, n - rank, ctx); pivots = flint_malloc(sizeof(slong) * rank); nonpivots = flint_malloc(sizeof(slong) * (n - rank)); for (i = j = k = 0; i < rank; i++) { while (1) { /* Todo: this should not be T_UNKNOWN. Should we save the pivot data in the lu algorithm? */ truth_t is_zero = gr_is_zero(GR_MAT_ENTRY(R, i, j, sz), ctx); if (is_zero == T_FALSE) { break; } else if (is_zero == T_TRUE) { nonpivots[k] = j; k++; j++; } else { status = GR_UNABLE; goto cleanup1; } } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (i = 0; i < rank; i++) for (j = 0; j <= i; j++) status |= gr_set(GR_MAT_ENTRY(U, j, i, sz), GR_MAT_ENTRY(R, j, pivots[i], sz), ctx); for (i = 0; i < n - rank; i++) for (j = 0; j < rank; j++) status |= gr_set(GR_MAT_ENTRY(V, j, i, sz), GR_MAT_ENTRY(R, j, nonpivots[i], sz), ctx); status |= gr_mat_nonsingular_solve_triu(V, U, V, 0, ctx); /* Clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j <= i; j++) { if (i == j) status |= gr_one(GR_MAT_ENTRY(R, j, pivots[i], sz), ctx); else status |= gr_zero(GR_MAT_ENTRY(R, j, pivots[i], sz), ctx); } } /* Write back the actual content */ for (i = 0; i < n - rank; i++) for (j = 0; j < rank; j++) status |= gr_set(GR_MAT_ENTRY(R, j, nonpivots[i], sz), GR_MAT_ENTRY(V, j, i, sz), ctx); cleanup1: gr_mat_clear(U, ctx); gr_mat_clear(V, ctx); flint_free(pivots); flint_free(nonpivots); *res_rank = rank; return status; } flint-3.1.3/src/gr_mat/set.c000066400000000000000000000016141461254215100156340ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_set(gr_mat_t res, const gr_mat_t mat, gr_ctx_t ctx) { int status; slong i, r, c; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (r != gr_mat_nrows(mat, ctx) || c != gr_mat_ncols(mat, ctx)) { return GR_DOMAIN; } status = GR_SUCCESS; if (res != mat) { for (i = 0; i < r; i++) { status |= _gr_vec_set(res->rows[i], mat->rows[i], c, ctx); } } return status; } flint-3.1.3/src/gr_mat/set_fmpq.c000066400000000000000000000016451461254215100166630ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_set_fmpq(gr_mat_t res, const fmpq_t v, gr_ctx_t ctx) { int status; slong i, r, c, sz; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); sz = ctx->sizeof_elem; status = gr_mat_zero(res, ctx); if (r > 0 && c > 0) { status |= gr_set_fmpq(GR_MAT_ENTRY(res, 0, 0, sz), v, ctx); for (i = 1; i < FLINT_MIN(r, c); i++) status |= gr_set(GR_MAT_ENTRY(res, i, i, sz), GR_MAT_ENTRY(res, 0, 0, sz), ctx); } return status; } flint-3.1.3/src/gr_mat/set_fmpq_mat.c000066400000000000000000000015031461254215100175150ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" #include "gr_mat.h" int gr_mat_set_fmpq_mat(gr_mat_t res, const fmpq_mat_t mat, gr_ctx_t ctx) { slong i, j; slong m = mat->r; slong n = mat->c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { status |= gr_set_fmpq(GR_MAT_ENTRY(res, i, j, sz), fmpq_mat_entry(mat, i, j), ctx); } } return status; } flint-3.1.3/src/gr_mat/set_fmpz.c000066400000000000000000000016451461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_set_fmpz(gr_mat_t res, const fmpz_t v, gr_ctx_t ctx) { int status; slong i, r, c, sz; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); sz = ctx->sizeof_elem; status = gr_mat_zero(res, ctx); if (r > 0 && c > 0) { status |= gr_set_fmpz(GR_MAT_ENTRY(res, 0, 0, sz), v, ctx); for (i = 1; i < FLINT_MIN(r, c); i++) status |= gr_set(GR_MAT_ENTRY(res, i, i, sz), GR_MAT_ENTRY(res, 0, 0, sz), ctx); } return status; } flint-3.1.3/src/gr_mat/set_fmpz_mat.c000066400000000000000000000015031461254215100175260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "gr_mat.h" int gr_mat_set_fmpz_mat(gr_mat_t res, const fmpz_mat_t mat, gr_ctx_t ctx) { slong i, j; slong m = mat->r; slong n = mat->c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { status |= gr_set_fmpz(GR_MAT_ENTRY(res, i, j, sz), fmpz_mat_entry(mat, i, j), ctx); } } return status; } flint-3.1.3/src/gr_mat/set_scalar.c000066400000000000000000000015511461254215100171610ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_set_scalar(gr_mat_t res, gr_srcptr v, gr_ctx_t ctx) { int status; slong i, r, c, sz; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); sz = ctx->sizeof_elem; status = gr_mat_zero(res, ctx); if (r > 0 && c > 0) { status |= gr_set(GR_MAT_ENTRY(res, 0, 0, sz), v, ctx); for (i = 1; i < FLINT_MIN(r, c); i++) status |= gr_set(GR_MAT_ENTRY(res, i, i, sz), v, ctx); } return status; } flint-3.1.3/src/gr_mat/set_si.c000066400000000000000000000016321461254215100163270ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_set_si(gr_mat_t res, slong v, gr_ctx_t ctx) { int status; slong i, r, c, sz; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); sz = ctx->sizeof_elem; status = gr_mat_zero(res, ctx); if (r > 0 && c > 0) { status |= gr_set_si(GR_MAT_ENTRY(res, 0, 0, sz), v, ctx); for (i = 1; i < FLINT_MIN(r, c); i++) status |= gr_set(GR_MAT_ENTRY(res, i, i, sz), GR_MAT_ENTRY(res, 0, 0, sz), ctx); } return status; } flint-3.1.3/src/gr_mat/set_ui.c000066400000000000000000000016321461254215100163310ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_set_ui(gr_mat_t res, ulong v, gr_ctx_t ctx) { int status; slong i, r, c, sz; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); sz = ctx->sizeof_elem; status = gr_mat_zero(res, ctx); if (r > 0 && c > 0) { status |= gr_set_ui(GR_MAT_ENTRY(res, 0, 0, sz), v, ctx); for (i = 1; i < FLINT_MIN(r, c); i++) status |= gr_set(GR_MAT_ENTRY(res, i, i, sz), GR_MAT_ENTRY(res, 0, 0, sz), ctx); } return status; } flint-3.1.3/src/gr_mat/solve_field.c000066400000000000000000000101751461254215100173360ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann Copyright (C) 2020 William Hart Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_solve_field(gr_mat_t X, const gr_mat_t A, const gr_mat_t B, gr_ctx_t ctx) { slong i, j, k, col, *pivots, rank, *perm; gr_mat_t LU, LU2, PB; int status = GR_SUCCESS; truth_t is_zero; if (A->r != B->r || A->c != X->r || X->c != B->c) { return GR_DOMAIN; } if (A->r == 0 || B->c == 0) { return gr_mat_zero(X, ctx); } if (A->c == 0) { status = gr_mat_zero(X, ctx); if (status != GR_SUCCESS) return status; is_zero = gr_mat_is_zero(B, ctx); if (is_zero == T_TRUE) return GR_SUCCESS; if (is_zero == T_FALSE) return GR_DOMAIN; return GR_UNABLE; } status |= gr_mat_init_set(LU, A, ctx); perm = flint_malloc(sizeof(slong) * A->r); for (i = 0; i < A->r; i++) perm[i] = i; status |= gr_mat_lu(&rank, perm, LU, LU, 0, ctx); if (status != GR_SUCCESS) goto cleanup1; gr_mat_window_init(PB, B, 0, 0, B->r, B->c, ctx); for (i = 0; i < B->r; i++) PB->rows[i] = B->rows[perm[i]]; gr_mat_init(LU2, rank, rank, ctx); pivots = flint_malloc(sizeof(slong) * rank); col = 0; for (i = 0; i < rank; i++) { while (1) { is_zero = gr_is_zero(gr_mat_entry_ptr(LU, i, col, ctx), ctx); if (is_zero == T_UNKNOWN) { status = GR_UNABLE; goto cleanup; } if (is_zero == T_TRUE) { col++; } else { break; } } pivots[i] = col; for (j = 0; j < rank; j++) status |= gr_set(gr_mat_entry_ptr(LU2, j, i, ctx), gr_mat_entry_ptr(LU, j, col, ctx), ctx); col++; } X->r = rank; PB->r = rank; LU->r = rank; status |= gr_mat_nonsingular_solve_tril(X, LU, PB, 1, ctx); if (status != GR_SUCCESS) goto cleanup; LU->r = A->r; if (A->r > rank) { gr_mat_t P; truth_t equal; LU->rows += rank; LU->r = A->r - rank; X->r = LU->c; gr_mat_init(P, LU->r, B->c, ctx); status |= gr_mat_mul(P, LU, X, ctx); PB->r = LU->r; PB->rows += rank; equal = gr_mat_equal(P, PB, ctx); PB->rows -= rank; gr_mat_clear(P, ctx); LU->rows -= rank; LU->r = A->r; if (equal == T_UNKNOWN) { X->r = A->c; status |= GR_UNABLE; goto cleanup; } if (status == GR_SUCCESS && equal == T_FALSE) { /* restore original size of X */ X->r = A->c; status = GR_DOMAIN; status |= gr_mat_zero(X, ctx); goto cleanup; } } status |= gr_mat_nonsingular_solve_triu(X, LU2, X, 0, ctx); if (status != GR_SUCCESS) { X->r = A->c; goto cleanup; } /* restore original size of X */ X->r = A->c; k = rank - 1; for (i = A->c - 1; i >= 0; i--) { if (k < 0 || i != pivots[k]) { for (j = 0; j < B->c; j++) status |= gr_zero(gr_mat_entry_ptr(X, i, j, ctx), ctx); } else { for (j = 0; j < B->c; j++) status |= gr_set(gr_mat_entry_ptr(X, i, j, ctx), gr_mat_entry_ptr(X, k, j, ctx), ctx); k--; } } cleanup: gr_mat_clear(LU2, ctx); PB->r = B->r; gr_mat_window_clear(PB, ctx); flint_free(pivots); cleanup1: /* restore original size of LU */ LU->r = A->r; gr_mat_clear(LU, ctx); flint_free(perm); return status; } flint-3.1.3/src/gr_mat/stirling.c000066400000000000000000000070271461254215100167000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" /* todo: optimize for fmpz */ #define ENTRY(vec, i) GR_ENTRY(vec, i, sz) static int _stirling_number_1u_vec_next(gr_ptr row, gr_srcptr prev, slong n, slong klen, gr_ctx_t ctx) { slong k; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (klen > n) status |= gr_one(ENTRY(row, n), ctx); if (n != 0 && klen != 0) status |= gr_zero(row, ctx); for (k = FLINT_MIN(n, klen) - 1; k >= 1; k--) { status |= gr_mul_ui(ENTRY(row, k), ENTRY(prev, k), n - 1, ctx); status |= gr_add(ENTRY(row, k), ENTRY(prev, k - 1), ENTRY(row, k), ctx); } for (k = n + 1; k < klen; k++) status |= gr_zero(ENTRY(row, k), ctx); return status; } static int _stirling_number_1_vec_next(gr_ptr row, gr_srcptr prev, slong n, slong klen, gr_ctx_t ctx) { slong k; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (klen > n) status |= gr_one(ENTRY(row, n), ctx); if (n != 0 && klen != 0) status |= gr_zero(row, ctx); for (k = FLINT_MIN(n, klen) - 1; k >= 1; k--) { status |= gr_mul_ui(ENTRY(row, k), ENTRY(prev, k), n - 1, ctx); status |= gr_sub(ENTRY(row, k), ENTRY(prev, k - 1), ENTRY(row, k), ctx); } for (k = n + 1; k < klen; k++) status |= gr_zero(ENTRY(row, k), ctx); return status; } static int _stirling_number_2_vec_next(gr_ptr row, gr_srcptr prev, slong n, slong klen, gr_ctx_t ctx) { slong k; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (klen > n) status |= gr_one(ENTRY(row, n), ctx); if (n != 0 && klen != 0) status |= gr_zero(row, ctx); for (k = FLINT_MIN(n, klen) - 1; k >= 1; k--) { status |= gr_mul_ui(ENTRY(row, k), ENTRY(prev, k), k, ctx); status |= gr_add(ENTRY(row, k), ENTRY(prev, k - 1), ENTRY(row, k), ctx); } for (k = n + 1; k < klen; k++) status |= gr_zero(ENTRY(row, k), ctx); return status; } static int _stirling_matrix_1u(gr_mat_t mat, gr_ctx_t ctx) { slong n; int status = GR_SUCCESS; if (mat->c != 0) for (n = 0; n < mat->r; n++) status |= _stirling_number_1u_vec_next(mat->rows[n], mat->rows[n - (n != 0)], n, mat->c, ctx); return status; } static int _stirling_matrix_1(gr_mat_t mat, gr_ctx_t ctx) { slong n; int status = GR_SUCCESS; if (mat->c != 0) for (n = 0; n < mat->r; n++) status |= _stirling_number_1_vec_next(mat->rows[n], mat->rows[n - (n != 0)], n, mat->c, ctx); return status; } static int _stirling_matrix_2(gr_mat_t mat, gr_ctx_t ctx) { slong n; int status = GR_SUCCESS; if (mat->c != 0) for (n = 0; n < mat->r; n++) status |= _stirling_number_2_vec_next(mat->rows[n], mat->rows[n - (n != 0)], n, mat->c, ctx); return status; } int gr_mat_stirling(gr_mat_t mat, int kind, gr_ctx_t ctx) { if (kind == 0) return _stirling_matrix_1u(mat, ctx); else if (kind == 1) return _stirling_matrix_1(mat, ctx); else if (kind == 2) return _stirling_matrix_2(mat, ctx); else return GR_DOMAIN; } flint-3.1.3/src/gr_mat/sub.c000066400000000000000000000017231461254215100156330ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_sub(gr_mat_t res, const gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { int status; slong i, r, c; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (r != gr_mat_nrows(mat1, ctx) || c != gr_mat_ncols(mat1, ctx) || r != gr_mat_nrows(mat2, ctx) || c != gr_mat_ncols(mat2, ctx)) { return GR_DOMAIN; } status = GR_SUCCESS; for (i = 0; i < r; i++) { status |= _gr_vec_sub(res->rows[i], mat1->rows[i], mat2->rows[i], c, ctx); } return status; } flint-3.1.3/src/gr_mat/sub_scalar.c000066400000000000000000000023601461254215100171560ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_sub_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx) { slong i, j, r, c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (res == mat) { for (i = 0; i < FLINT_MIN(r, c); i++) status |= gr_sub(GR_MAT_ENTRY(res, i, i, sz), GR_MAT_ENTRY(res, i, i, sz), x, ctx); } else { for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { /* todo: vectorize */ if (i == j) status |= gr_sub(GR_MAT_ENTRY(res, i, j, sz), GR_MAT_ENTRY(mat, i, j, sz), x, ctx); else status |= gr_set(GR_MAT_ENTRY(res, i, j, sz), GR_MAT_ENTRY(mat, i, j, sz), ctx); } } } return status; } flint-3.1.3/src/gr_mat/submul_scalar.c000066400000000000000000000014141461254215100176730ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_submul_scalar(gr_mat_t res, const gr_mat_t mat, gr_srcptr x, gr_ctx_t ctx) { slong i, r, c; int status = GR_SUCCESS; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); if (c != 0) for (i = 0; i < r; i++) status |= _gr_vec_submul_scalar(res->rows[i], mat->rows[i], c, x, ctx); return status; } flint-3.1.3/src/gr_mat/swap_cols.c000066400000000000000000000015421461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_swap_cols(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx) { /* todo: bounds checking */ if (r != s && gr_mat_is_empty(mat, ctx) == T_FALSE) { slong t; slong sz = ctx->sizeof_elem; if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); for (t = 0; t < mat->r; t++) gr_swap(GR_MAT_ENTRY(mat, t, r, sz), GR_MAT_ENTRY(mat, t, s, sz), ctx); } return GR_SUCCESS; } flint-3.1.3/src/gr_mat/swap_entrywise.c000066400000000000000000000015321461254215100201230ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_swap_entrywise(gr_mat_t mat1, const gr_mat_t mat2, gr_ctx_t ctx) { int status; slong i, r, c; r = gr_mat_nrows(mat1, ctx); c = gr_mat_ncols(mat1, ctx); if (r != gr_mat_nrows(mat2, ctx) || c != gr_mat_ncols(mat2, ctx)) { return GR_DOMAIN; } status = GR_SUCCESS; for (i = 0; i < r; i++) _gr_vec_swap(mat1->rows[i], mat2->rows[i], c, ctx); return status; } flint-3.1.3/src/gr_mat/swap_rows.c000066400000000000000000000013521461254215100170640ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_swap_rows(gr_mat_t mat, slong * perm, slong r, slong s, gr_ctx_t ctx) { /* todo: bounds checking */ if (r != s && gr_mat_is_empty(mat, ctx) == T_FALSE) { if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(gr_ptr, mat->rows[r], mat->rows[s]); } return GR_SUCCESS; } flint-3.1.3/src/gr_mat/test/000077500000000000000000000000001461254215100156525ustar00rootroot00000000000000flint-3.1.3/src/gr_mat/test/main.c000066400000000000000000000066751461254215100167600ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-adjugate.c" #include "t-charpoly_danilevsky.c" #include "t-charpoly_faddeev_bsgs.c" #include "t-charpoly_faddeev.c" #include "t-charpoly_gauss.c" #include "t-charpoly_householder.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-det_berkowitz.c" #include "t-det_cofactor.c" #include "t-det_fflu.c" #include "t-det_lu.c" #include "t-diagonalization.c" #include "t-hadamard.c" #include "t-hessenberg.c" #include "t-hessenberg_gauss.c" #include "t-hessenberg_householder.c" #include "t-inv.c" #include "t-invert_rows_cols.c" #include "t-lu.c" #include "t-lu_classical.c" #include "t-lu_recursive.c" #include "t-minpoly_field.c" #include "t-mul_strassen.c" #include "t-nullspace.c" #include "t-properties.c" #include "t-randrank.c" #include "t-rank.c" #include "t-rank_fflu.c" #include "t-rank_lu.c" #include "t-rref_den_fflu.c" #include "t-rref_fflu.c" #include "t-rref_lu.c" #include "t-solve.c" #include "t-solve_den.c" #include "t-solve_den_fflu.c" #include "t-solve_fflu.c" #include "t-solve_field.c" #include "t-solve_lu.c" #include "t-solve_tril.c" #include "t-solve_triu.c" #include "t-window_init_clear.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(gr_mat_adjugate), TEST_FUNCTION(gr_mat_charpoly_danilevsky), TEST_FUNCTION(gr_mat_charpoly_faddeev_bsgs), TEST_FUNCTION(gr_mat_charpoly_faddeev), TEST_FUNCTION(gr_mat_charpoly_gauss), TEST_FUNCTION(gr_mat_charpoly_householder), TEST_FUNCTION(gr_mat_concat_horizontal), TEST_FUNCTION(gr_mat_concat_vertical), TEST_FUNCTION(gr_mat_det_berkowitz), TEST_FUNCTION(gr_mat_det_cofactor), TEST_FUNCTION(gr_mat_det_fflu), TEST_FUNCTION(gr_mat_det_lu), TEST_FUNCTION(gr_mat_diagonalization), TEST_FUNCTION(gr_mat_hadamard), TEST_FUNCTION(gr_mat_hessenberg), TEST_FUNCTION(gr_mat_hessenberg_gauss), TEST_FUNCTION(gr_mat_hessenberg_householder), TEST_FUNCTION(gr_mat_inv), TEST_FUNCTION(gr_mat_invert_rows_cols), TEST_FUNCTION(gr_mat_lu), TEST_FUNCTION(gr_mat_lu_classical), TEST_FUNCTION(gr_mat_lu_recursive), TEST_FUNCTION(gr_mat_minpoly_field), TEST_FUNCTION(gr_mat_mul_strassen), TEST_FUNCTION(gr_mat_nullspace), TEST_FUNCTION(gr_mat_properties), TEST_FUNCTION(gr_mat_randrank), TEST_FUNCTION(gr_mat_rank), TEST_FUNCTION(gr_mat_rank_fflu), TEST_FUNCTION(gr_mat_rank_lu), TEST_FUNCTION(gr_mat_rref_den_fflu), TEST_FUNCTION(gr_mat_rref_fflu), TEST_FUNCTION(gr_mat_rref_lu), TEST_FUNCTION(gr_mat_solve), TEST_FUNCTION(gr_mat_solve_den), TEST_FUNCTION(gr_mat_solve_den_fflu), TEST_FUNCTION(gr_mat_solve_fflu), TEST_FUNCTION(gr_mat_solve_field), TEST_FUNCTION(gr_mat_solve_lu), TEST_FUNCTION(gr_mat_solve_tril), TEST_FUNCTION(gr_mat_solve_triu), TEST_FUNCTION(gr_mat_window_init_clear) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/gr_mat/test/t-adjugate.c000066400000000000000000000044731461254215100200530ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_adjugate, state, count_success, count_domain, count_unable) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B, C; gr_ptr d, e; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 5); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(C, n, n, ctx); d = gr_heap_init(ctx); e = gr_heap_init(ctx); GR_MUST_SUCCEED(gr_mat_randtest(A, state, ctx)); status |= gr_mat_adjugate_cofactor(B, d, A, ctx); status |= gr_mat_adjugate_charpoly(C, e, A, ctx); if (status == GR_SUCCESS && (gr_mat_equal(B, C, ctx) == T_FALSE || gr_equal(d, e, ctx) == T_FALSE)) { flint_printf("FAIL\n"); flint_printf("A = "), gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "), gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "), gr_mat_print(C, ctx); flint_printf("\n"); flint_printf("d = "), gr_print(d, ctx); flint_printf("\n"); flint_printf("e = "), gr_print(e, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); gr_heap_clear(d, ctx); gr_heap_clear(e, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_domain, count_unable); } flint-3.1.3/src/gr_mat/test/t-charpoly_danilevsky.c000066400000000000000000000042451461254215100223360ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_charpoly_danilevsky, state, count_success, count_domain, count_unable) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A; gr_poly_t f, g; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 8); gr_mat_init(A, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); gr_poly_randtest(f, state, n_randint(state, 10), ctx); gr_poly_randtest(g, state, n_randint(state, 10), ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); status |= gr_mat_charpoly_danilevsky(g, A, ctx); if (status == GR_SUCCESS && gr_poly_equal(f, g, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_domain, count_unable); } flint-3.1.3/src/gr_mat/test/t-charpoly_faddeev.c000066400000000000000000000045561461254215100215700ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_charpoly_faddeev, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A; gr_poly_t f, g; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 8); gr_mat_init(A, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); gr_poly_randtest(f, state, n_randint(state, 10), ctx); gr_poly_randtest(g, state, n_randint(state, 10), ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); status |= gr_mat_charpoly_faddeev(g, NULL, A, ctx); /* todo: check adjugate */ /* todo: check validity even in other cases? */ if (gr_ctx_is_integral_domain(ctx) == T_TRUE) { if (status == GR_SUCCESS && gr_poly_equal(f, g, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-charpoly_faddeev_bsgs.c000066400000000000000000000045701461254215100226020ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_charpoly_faddeev_bsgs, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A; gr_poly_t f, g; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 8); gr_mat_init(A, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); gr_poly_randtest(f, state, n_randint(state, 10), ctx); gr_poly_randtest(g, state, n_randint(state, 10), ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); status |= gr_mat_charpoly_faddeev_bsgs(g, NULL, A, ctx); /* todo: check adjugate */ /* todo: check validity even in other cases? */ if (gr_ctx_is_integral_domain(ctx) == T_TRUE) { if (status == GR_SUCCESS && gr_poly_equal(f, g, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-charpoly_gauss.c000066400000000000000000000042331461254215100213040ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_charpoly_gauss, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A; gr_poly_t f, g; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 8); gr_mat_init(A, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); gr_poly_randtest(f, state, n_randint(state, 10), ctx); gr_poly_randtest(g, state, n_randint(state, 10), ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); status |= gr_mat_charpoly_gauss(g, A, ctx); if (status == GR_SUCCESS && gr_poly_equal(f, g, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-charpoly_householder.c000066400000000000000000000042471461254215100225100ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_charpoly_householder, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A; gr_poly_t f, g; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 8); gr_mat_init(A, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); gr_poly_randtest(f, state, n_randint(state, 10), ctx); gr_poly_randtest(g, state, n_randint(state, 10), ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); status |= gr_mat_charpoly_householder(g, A, ctx); if (status == GR_SUCCESS && gr_poly_equal(f, g, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-concat_horizontal.c000066400000000000000000000034501461254215100220010ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_concat_horizontal, state) { slong iter; for (iter = 0; iter < 100; iter++) { int status = GR_SUCCESS; gr_ctx_t ctx; gr_mat_t A, B, C; gr_mat_t window1, window2; slong c1, c2, r1; gr_ctx_init_random(ctx, state); c1 = n_randint(state, 5); c2 = n_randint(state, 5); r1 = n_randint(state, 5); gr_mat_init(A, r1, c1, ctx); gr_mat_init(B, r1, c2, ctx); gr_mat_init(C, r1, (c1 + c2), ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_randtest(C, state, ctx); status |= gr_mat_concat_horizontal(C, A, B, ctx); gr_mat_window_init(window1, C, 0, 0, r1, c1, ctx); gr_mat_window_init(window2, C, 0, c1, r1, (c1 + c2), ctx); if (status == GR_SUCCESS) { if (gr_mat_equal(window1, A, ctx) == T_FALSE || gr_mat_equal(window2, B, ctx) == T_FALSE) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } } gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); gr_mat_window_clear(window1, ctx); gr_mat_window_clear(window2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-concat_vertical.c000066400000000000000000000034461461254215100214260ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_concat_vertical, state) { slong iter; for (iter = 0; iter < 100; iter++) { int status = GR_SUCCESS; gr_ctx_t ctx; gr_mat_t A, B, C; gr_mat_t window1, window2; slong r1, r2, c1; gr_ctx_init_random(ctx, state); r1 = n_randint(state, 5); r2 = n_randint(state, 5); c1 = n_randint(state, 5); gr_mat_init(A, r1, c1, ctx); gr_mat_init(B, r2, c1, ctx); gr_mat_init(C, (r1 + r2), c1, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_randtest(C, state, ctx); status |= gr_mat_concat_horizontal(C, A, B, ctx); gr_mat_window_init(window1, C, 0, 0, r1, c1, ctx); gr_mat_window_init(window2, C, r1, 0, (r1 + r2), c1, ctx); if (status == GR_SUCCESS) { if (gr_mat_equal(window1, A, ctx) == T_FALSE || gr_mat_equal(window2, B, ctx) == T_FALSE) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } } gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); gr_mat_window_clear(window1, ctx); gr_mat_window_clear(window2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-det_berkowitz.c000066400000000000000000000055571461254215100211470ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_det_berkowitz, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B, AB; gr_ptr detA, detB, detAB, detAdetB; /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 7); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(AB, n, n, ctx); detA = gr_heap_init(ctx); detB = gr_heap_init(ctx); detAB = gr_heap_init(ctx); detAdetB = gr_heap_init(ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_mul(AB, A, B, ctx); status |= gr_mat_det_berkowitz(detA, A, ctx); status |= gr_mat_det_berkowitz(detB, B, ctx); status |= gr_mat_det_berkowitz(detAB, AB, ctx); status |= gr_mul(detAdetB, detA, detB, ctx); if (status == GR_SUCCESS && gr_equal(detAB, detAdetB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); gr_mat_print(AB, ctx); flint_printf("\n"); flint_printf("detA = "); gr_print(detA, ctx); flint_printf("\n"); flint_printf("detB = "); gr_print(detB, ctx); flint_printf("\n"); flint_printf("detAB = "); gr_print(detAB, ctx); flint_printf("\n"); flint_printf("detAdetB = "); gr_print(detAdetB, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(AB, ctx); gr_heap_clear(detA, ctx); gr_heap_clear(detB, ctx); gr_heap_clear(detAB, ctx); gr_heap_clear(detAdetB, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-det_cofactor.c000066400000000000000000000055531461254215100207230ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_det_cofactor, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B, AB; gr_ptr detA, detB, detAB, detAdetB; /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 7); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(AB, n, n, ctx); detA = gr_heap_init(ctx); detB = gr_heap_init(ctx); detAB = gr_heap_init(ctx); detAdetB = gr_heap_init(ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_mul(AB, A, B, ctx); status |= gr_mat_det_cofactor(detA, A, ctx); status |= gr_mat_det_cofactor(detB, B, ctx); status |= gr_mat_det_cofactor(detAB, AB, ctx); status |= gr_mul(detAdetB, detA, detB, ctx); if (status == GR_SUCCESS && gr_equal(detAB, detAdetB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); gr_mat_print(AB, ctx); flint_printf("\n"); flint_printf("detA = "); gr_print(detA, ctx); flint_printf("\n"); flint_printf("detB = "); gr_print(detB, ctx); flint_printf("\n"); flint_printf("detAB = "); gr_print(detAB, ctx); flint_printf("\n"); flint_printf("detAdetB = "); gr_print(detAdetB, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(AB, ctx); gr_heap_clear(detA, ctx); gr_heap_clear(detB, ctx); gr_heap_clear(detAB, ctx); gr_heap_clear(detAdetB, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-det_fflu.c000066400000000000000000000055331461254215100200550ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_det_fflu, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B, AB; gr_ptr detA, detB, detAB, detAdetB; /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 7); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(AB, n, n, ctx); detA = gr_heap_init(ctx); detB = gr_heap_init(ctx); detAB = gr_heap_init(ctx); detAdetB = gr_heap_init(ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_mul(AB, A, B, ctx); status |= gr_mat_det_fflu(detA, A, ctx); status |= gr_mat_det_fflu(detB, B, ctx); status |= gr_mat_det_fflu(detAB, AB, ctx); status |= gr_mul(detAdetB, detA, detB, ctx); if (status == GR_SUCCESS && gr_equal(detAB, detAdetB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); gr_mat_print(AB, ctx); flint_printf("\n"); flint_printf("detA = "); gr_print(detA, ctx); flint_printf("\n"); flint_printf("detB = "); gr_print(detB, ctx); flint_printf("\n"); flint_printf("detAB = "); gr_print(detAB, ctx); flint_printf("\n"); flint_printf("detAdetB = "); gr_print(detAdetB, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(AB, ctx); gr_heap_clear(detA, ctx); gr_heap_clear(detB, ctx); gr_heap_clear(detAB, ctx); gr_heap_clear(detAdetB, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-det_lu.c000066400000000000000000000073151461254215100175410ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_det_lu, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 10000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B, AB; gr_ptr detA, detB, detAB, detAdetB; /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 7); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(AB, n, n, ctx); detA = gr_heap_init(ctx); detB = gr_heap_init(ctx); detAB = gr_heap_init(ctx); detAdetB = gr_heap_init(ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_mul(AB, A, B, ctx); status |= gr_mat_det_lu(detA, A, ctx); status |= gr_mat_det_lu(detB, B, ctx); status |= gr_mat_det_lu(detAB, AB, ctx); status |= gr_mul(detAdetB, detA, detB, ctx); if (status == GR_SUCCESS && gr_equal(detAB, detAdetB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); gr_mat_print(AB, ctx); flint_printf("\n"); flint_printf("detA = "); gr_print(detA, ctx); flint_printf("\n"); flint_printf("detB = "); gr_print(detB, ctx); flint_printf("\n"); flint_printf("detAB = "); gr_print(detAB, ctx); flint_printf("\n"); flint_printf("detAdetB = "); gr_print(detAdetB, ctx); flint_printf("\n"); flint_abort(); } if ((status & GR_DOMAIN) && !(status & GR_UNABLE)) { flint_printf("FAIL (flags)\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); gr_mat_print(AB, ctx); flint_printf("\n"); flint_abort(); } status |= gr_mat_det_lu(detB, A, ctx); if (status == GR_SUCCESS && gr_equal(detA, detB, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("detA = "); gr_print(detA, ctx); flint_printf("\n"); flint_printf("detB = "); gr_print(detB, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(AB, ctx); gr_heap_clear(detA, ctx); gr_heap_clear(detB, ctx); gr_heap_clear(detAB, ctx); gr_heap_clear(detAdetB, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-diagonalization.c000066400000000000000000000106461461254215100214420ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "gr_vec.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_diagonalization, state) { slong iter; /* todo: test non-diagonalizable matrices */ /* todo: test aliasing */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { gr_ctx_t ctx; gr_mat_t A, L, R, B, LR; gr_vec_t D; slong n; int status = GR_SUCCESS; int haveL, haveR; gr_ctx_init_random(ctx, state); n = n_randint(state, 5); haveL = n_randint(state, 2); haveR = n_randint(state, 2); gr_mat_init(A, n, n, ctx); gr_mat_init(L, n, n, ctx); gr_mat_init(R, n, n, ctx); gr_vec_init(D, n, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(LR, n, n, ctx); if (n <= 2) { status |= gr_mat_randtest(A, state, ctx); } else { fmpq_mat_t T; fmpq_mat_init(T, n, n); fmpq_mat_randtest(T, state, 1); status |= gr_mat_set_fmpq_mat(A, T, ctx); fmpq_mat_clear(T); } /* status |= gr_vec_randtest(D, state, ctx); */ status |= gr_mat_randtest(L, state, ctx); status |= gr_mat_randtest(R, state, ctx); status |= gr_mat_diagonalization(D, haveL ? L : NULL, haveR ? R : NULL, A, 0, ctx); if (status == GR_SUCCESS) { if (haveL && haveR) { status = gr_mat_mul(LR, L, R, ctx); if (status == GR_SUCCESS && gr_mat_is_one(LR, ctx) == T_FALSE) { flint_printf("FAIL: L*R != 1\n"); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("D: "); gr_vec_print(D, ctx); flint_printf("\n"); flint_printf("L: "); gr_mat_print(L, ctx); flint_printf("\n"); flint_printf("R: "); gr_mat_print(R, ctx); flint_printf("\n"); flint_printf("LR: "); gr_mat_print(LR, ctx); flint_printf("\n"); flint_abort(); } } else if (haveL || haveR) { if (haveL) status |= gr_mat_inv(R, L, ctx); else status |= gr_mat_inv(L, R, ctx); if (status == GR_DOMAIN && gr_ctx_is_field(ctx) == T_TRUE) { flint_printf("FAIL (inversion of R or L)\n"); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("D: "); gr_vec_print(D, ctx); flint_printf("\n"); flint_printf("L: "); gr_mat_print(L, ctx); flint_printf("\n"); flint_printf("R: "); gr_mat_print(R, ctx); flint_printf("\n"); flint_abort(); } } if ((haveL || haveR) && status == GR_SUCCESS) { /* gr_ctx_println(ctx); gr_mat_print(A, ctx); printf("\n\n"); */ status |= gr_mat_mul_diag(B, R, D, ctx); status |= gr_mat_mul(B, B, L, ctx); if (status == GR_SUCCESS && gr_mat_equal(A, B, ctx) == T_FALSE) { flint_printf("FAIL: RDL != A\n"); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("D: "); gr_vec_print(D, ctx); flint_printf("\n"); flint_printf("L: "); gr_mat_print(L, ctx); flint_printf("\n"); flint_printf("R: "); gr_mat_print(R, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_abort(); } } } gr_mat_clear(A, ctx); gr_vec_clear(D, ctx); gr_mat_clear(L, ctx); gr_mat_clear(R, ctx); gr_mat_clear(B, ctx); gr_mat_clear(LR, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-hadamard.c000066400000000000000000000041741461254215100200260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_GR_FUNCTION_START(gr_mat_hadamard, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, B, C; slong n; int status = GR_SUCCESS; if (n_randint(state, 20) == 0) { gr_ctx_init_fmpz(ctx); n = 4 * n_randint(state, 30); } else { gr_ctx_init_random(ctx, state); n = n_randint(state, 20); } gr_mat_init(A, n, n, ctx); GR_MUST_SUCCEED(gr_mat_randtest(A, state, ctx)); status = gr_mat_hadamard(A, ctx); if (status == GR_SUCCESS) { gr_mat_init(B, n, n, ctx); gr_mat_init(C, n, n, ctx); status |= gr_mat_transpose(B, A, ctx); status |= gr_mat_mul(C, A, B, ctx); status |= gr_mat_set_ui(B, n, ctx); if (status == GR_SUCCESS && gr_mat_equal(C, B, ctx) == T_FALSE) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("C: "); gr_mat_print(C, ctx); flint_printf("\n"); flint_abort(); } gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-hessenberg.c000066400000000000000000000046111461254215100204060ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_hessenberg, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B; gr_poly_t f, g; /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 7); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_hessenberg(B, A, ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); if (n_randint(state, 2)) status |= gr_mat_charpoly_from_hessenberg(g, B, ctx); else status |= gr_mat_charpoly_berkowitz(g, B, ctx); if (status == GR_SUCCESS && (gr_poly_equal(f, g, ctx) == T_FALSE || gr_mat_is_hessenberg(B, ctx) == T_FALSE)) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-hessenberg_gauss.c000066400000000000000000000046261461254215100216160ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_hessenberg_gauss, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B; gr_poly_t f, g; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 8); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_hessenberg_gauss(B, A, ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); if (n_randint(state, 2)) status |= gr_mat_charpoly_from_hessenberg(g, B, ctx); else status |= gr_mat_charpoly_berkowitz(g, B, ctx); if (status == GR_SUCCESS && (gr_poly_equal(f, g, ctx) == T_FALSE || gr_mat_is_hessenberg(B, ctx) == T_FALSE)) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-hessenberg_householder.c000066400000000000000000000046421461254215100230130ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_hessenberg_householder, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B; gr_poly_t f, g; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 8); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_poly_init(f, ctx); gr_poly_init(g, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_hessenberg_householder(B, A, ctx); status |= gr_mat_charpoly_berkowitz(f, A, ctx); if (n_randint(state, 2)) status |= gr_mat_charpoly_from_hessenberg(g, B, ctx); else status |= gr_mat_charpoly_berkowitz(g, B, ctx); if (status == GR_SUCCESS && (gr_poly_equal(f, g, ctx) == T_FALSE || gr_mat_is_hessenberg(B, ctx) == T_FALSE)) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-inv.c000066400000000000000000000054721461254215100170630ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_inv, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; slong n; gr_ctx_t ctx; gr_mat_t A, B, AB; gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } n = n_randint(state, 6); gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, n, ctx); gr_mat_init(AB, n, n, ctx); GR_MUST_SUCCEED(gr_mat_randtest(A, state, ctx)); GR_MUST_SUCCEED(gr_mat_randtest(B, state, ctx)); status = gr_mat_inv(B, A, ctx); if ((status & GR_DOMAIN) && !(status & GR_UNABLE) && gr_ctx_is_integral_domain(ctx) == T_TRUE) { gr_ptr det; int status2; det = gr_heap_init(ctx); status2 = gr_mat_det(det, A, ctx); if (status2 == GR_SUCCESS && gr_is_invertible(det, ctx) == T_TRUE) { flint_printf("FAIL (invertible)\n"); gr_ctx_println(ctx); flint_printf("A = "), gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "), gr_print(det, ctx); flint_printf("\n"); flint_abort(); } gr_heap_clear(det, ctx); } if (status == GR_SUCCESS) { status = gr_mat_mul(AB, A, B, ctx); if (status == GR_SUCCESS && gr_mat_is_one(AB, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = "), gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "), gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("AB = "), gr_mat_print(AB, ctx); flint_printf("\n"); flint_abort(); } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(AB, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-invert_rows_cols.c000066400000000000000000000034641461254215100216670ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_invert_rows_cols, state) { slong iter; for (iter = 0; iter < 100; iter++) { slong m, n, i, j; gr_ctx_t ctx; gr_mat_t A; gr_mat_t B; gr_ctx_init_random(ctx, state); m = n_randint(state, 20); n = n_randint(state, 20); gr_mat_init(A, m, n, ctx); gr_mat_init(B, m, n, ctx); if (gr_mat_randtest(A, state, ctx) == GR_SUCCESS && gr_mat_set(B, A, ctx) == GR_SUCCESS) { GR_MUST_SUCCEED(gr_mat_invert_rows(A, NULL, ctx)); GR_MUST_SUCCEED(gr_mat_invert_cols(A, NULL, ctx)); for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (gr_equal(gr_mat_entry_ptr(B, i, j, ctx), gr_mat_entry_ptr(A, A->r - i - 1, A->c - j - 1, ctx), ctx) == T_FALSE) { flint_printf("FAIL: B != A\n"); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("B:\n"); gr_mat_print(B, ctx); fflush(stdout); flint_abort(); } } } } gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-lu.c000066400000000000000000000162631461254215100167070ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "gr_mat.h" /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef perm #define perm perm void perm(gr_mat_t A, slong * P) { slong i; gr_ptr * tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(gr_ptr) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, gr_mat_t LU, const gr_mat_t A, slong rank, gr_ctx_t ctx) { gr_mat_t B, L, U; slong m, n, i, j; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; m = A->r; n = A->c; gr_mat_init(B, m, n, ctx); gr_mat_init(L, m, m, ctx); gr_mat_init(U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (gr_is_zero(GR_MAT_ENTRY(LU, i, j, sz), ctx) != T_TRUE) { flint_printf("FAIL: wrong shape!\n"); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) status |= gr_set(GR_MAT_ENTRY(L, i, j, sz), GR_MAT_ENTRY(LU, i, j, sz), ctx); if (i < rank) status |= gr_one(GR_MAT_ENTRY(L, i, i, sz), ctx); for (j = i; j < n; j++) status |= gr_set(GR_MAT_ENTRY(U, i, j, sz), GR_MAT_ENTRY(LU, i, j, sz), ctx); } status |= gr_mat_mul(B, L, U, ctx); perm(B, P); if (status == GR_SUCCESS && gr_mat_equal(A, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("LU:\n"); gr_mat_print(LU, ctx); flint_printf("B:\n"); gr_mat_print(B, ctx); flint_abort(); } gr_mat_clear(B, ctx); gr_mat_clear(L, ctx); gr_mat_clear(U, ctx); } #endif /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef _gr_mat_randrank #define _gr_mat_randrank _gr_mat_randrank void _gr_mat_randrank(gr_mat_t mat, flint_rand_t state, slong rank, slong bits, gr_ctx_t ctx) { fmpz_mat_t A; fmpz_mat_init(A, mat->r, mat->c); fmpz_mat_randrank(A, state, rank, bits); GR_MUST_SUCCEED(gr_mat_set_fmpz_mat(mat, A, ctx)); fmpz_mat_clear(A); } #endif TEST_FUNCTION_START(gr_mat_lu, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong m, n, r, d, rank; slong * P; int status; if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx); else gr_ctx_init_fmpq(ctx); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { gr_mat_init(A, m, n, ctx); gr_mat_init(LU, m, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * m); status = gr_mat_lu(&rank, P, LU, A, 0, ctx); if (status == GR_SUCCESS) { if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); gr_mat_print(A, ctx); flint_printf("LU:"); gr_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong m, n, r, d, rank; slong * P; int status; gr_ctx_init_random(ctx, state); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { gr_mat_init(A, m, n, ctx); gr_mat_init(LU, m, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * m); status = gr_mat_lu(&rank, P, LU, A, 0, ctx); if (status == GR_SUCCESS) { if (rank > r) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); gr_mat_print(A, ctx); flint_printf("LU:"); gr_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } /* Test rank check for square matrices */ for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong n, r, d, rank; slong * P; int status; if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx); else gr_ctx_init_fmpq(ctx); n = n_randint(state, 10); for (r = 0; r <= n; r++) { gr_mat_init(A, n, n, ctx); gr_mat_init(LU, n, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*n*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * n); status = gr_mat_lu(&rank, P, LU, A, 1, ctx); if (status == GR_SUCCESS) { if ((rank == 0) != (r < n || n == 0)) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("rank check\n"); flint_printf("r = %wd, rank = %wd\n", r, rank); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("LU:\n"); gr_mat_print(LU, ctx); flint_abort(); } if (rank != 0) check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-lu_classical.c000066400000000000000000000163331461254215100207230ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "gr_mat.h" /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef perm #define perm perm void perm(gr_mat_t A, slong * P) { slong i; gr_ptr * tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(gr_ptr) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, gr_mat_t LU, const gr_mat_t A, slong rank, gr_ctx_t ctx) { gr_mat_t B, L, U; slong m, n, i, j; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; m = A->r; n = A->c; gr_mat_init(B, m, n, ctx); gr_mat_init(L, m, m, ctx); gr_mat_init(U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (gr_is_zero(GR_MAT_ENTRY(LU, i, j, sz), ctx) != T_TRUE) { flint_printf("FAIL: wrong shape!\n"); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) status |= gr_set(GR_MAT_ENTRY(L, i, j, sz), GR_MAT_ENTRY(LU, i, j, sz), ctx); if (i < rank) status |= gr_one(GR_MAT_ENTRY(L, i, i, sz), ctx); for (j = i; j < n; j++) status |= gr_set(GR_MAT_ENTRY(U, i, j, sz), GR_MAT_ENTRY(LU, i, j, sz), ctx); } status |= gr_mat_mul(B, L, U, ctx); perm(B, P); if (status == GR_SUCCESS && gr_mat_equal(A, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("LU:\n"); gr_mat_print(LU, ctx); flint_printf("B:\n"); gr_mat_print(B, ctx); flint_abort(); } gr_mat_clear(B, ctx); gr_mat_clear(L, ctx); gr_mat_clear(U, ctx); } #endif /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef _gr_mat_randrank #define _gr_mat_randrank _gr_mat_randrank void _gr_mat_randrank(gr_mat_t mat, flint_rand_t state, slong rank, slong bits, gr_ctx_t ctx) { fmpz_mat_t A; fmpz_mat_init(A, mat->r, mat->c); fmpz_mat_randrank(A, state, rank, bits); GR_MUST_SUCCEED(gr_mat_set_fmpz_mat(mat, A, ctx)); fmpz_mat_clear(A); } #endif TEST_FUNCTION_START(gr_mat_lu_classical, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong m, n, r, d, rank; slong * P; int status; if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx); else gr_ctx_init_fmpq(ctx); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { gr_mat_init(A, m, n, ctx); gr_mat_init(LU, m, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * m); status = gr_mat_lu_classical(&rank, P, LU, A, 0, ctx); if (status == GR_SUCCESS) { if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); gr_mat_print(A, ctx); flint_printf("LU:"); gr_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong m, n, r, d, rank; slong * P; int status; gr_ctx_init_random(ctx, state); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { gr_mat_init(A, m, n, ctx); gr_mat_init(LU, m, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * m); status = gr_mat_lu_classical(&rank, P, LU, A, 0, ctx); if (status == GR_SUCCESS) { if (rank > r) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); gr_mat_print(A, ctx); flint_printf("LU:"); gr_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } /* Test rank check for square matrices */ for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong n, r, d, rank; slong * P; int status; if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx); else gr_ctx_init_fmpq(ctx); n = n_randint(state, 10); for (r = 0; r <= n; r++) { gr_mat_init(A, n, n, ctx); gr_mat_init(LU, n, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*n*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * n); status = gr_mat_lu_classical(&rank, P, LU, A, 1, ctx); if (status == GR_SUCCESS) { if ((rank == 0) != (r < n || n == 0)) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("rank check\n"); flint_printf("r = %wd, rank = %wd\n", r, rank); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("LU:\n"); gr_mat_print(LU, ctx); flint_abort(); } if (rank != 0) check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-lu_recursive.c000066400000000000000000000167021461254215100207740ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "gr_mat.h" /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef perm #define perm perm void perm(gr_mat_t A, slong * P) { slong i; gr_ptr * tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(gr_ptr) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef check #define check check void check(slong * P, gr_mat_t LU, const gr_mat_t A, slong rank, gr_ctx_t ctx) { gr_mat_t B, L, U; slong m, n, i, j; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; m = A->r; n = A->c; gr_mat_init(B, m, n, ctx); gr_mat_init(L, m, m, ctx); gr_mat_init(U, m, n, ctx); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) { for (j = i; j < n; j++) { if (gr_is_zero(GR_MAT_ENTRY(LU, i, j, sz), ctx) != T_TRUE) { flint_printf("FAIL: wrong shape!\n"); flint_abort(); } } } for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) status |= gr_set(GR_MAT_ENTRY(L, i, j, sz), GR_MAT_ENTRY(LU, i, j, sz), ctx); if (i < rank) status |= gr_one(GR_MAT_ENTRY(L, i, i, sz), ctx); for (j = i; j < n; j++) status |= gr_set(GR_MAT_ENTRY(U, i, j, sz), GR_MAT_ENTRY(LU, i, j, sz), ctx); } status |= gr_mat_mul(B, L, U, ctx); perm(B, P); if (status == GR_SUCCESS && gr_mat_equal(A, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("LU:\n"); gr_mat_print(LU, ctx); flint_printf("B:\n"); gr_mat_print(B, ctx); flint_abort(); } gr_mat_clear(B, ctx); gr_mat_clear(L, ctx); gr_mat_clear(U, ctx); } #endif /* Defined in t-lu.c, t-lu_classical.c, t-lu_recursive.c */ #ifndef _gr_mat_randrank #define _gr_mat_randrank _gr_mat_randrank void _gr_mat_randrank(gr_mat_t mat, flint_rand_t state, slong rank, slong bits, gr_ctx_t ctx) { fmpz_mat_t A; fmpz_mat_init(A, mat->r, mat->c); fmpz_mat_randrank(A, state, rank, bits); GR_MUST_SUCCEED(gr_mat_set_fmpz_mat(mat, A, ctx)); fmpz_mat_clear(A); } #endif TEST_FUNCTION_START(gr_mat_lu_recursive, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong m, n, r, d, rank; slong * P; int status; slong cutoff; if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx); else gr_ctx_init_fmpq(ctx); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { cutoff = 2 + n_randint(state, 5); gr_mat_init(A, m, n, ctx); gr_mat_init(LU, m, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * m); status = gr_mat_lu_recursive(&rank, P, LU, A, 0, cutoff, ctx); if (status == GR_SUCCESS) { if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); gr_mat_print(A, ctx); flint_printf("LU:"); gr_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong m, n, r, d, rank; slong * P; int status; slong cutoff; gr_ctx_init_random(ctx, state); m = n_randint(state, 10); n = n_randint(state, 10); for (r = 0; r <= FLINT_MIN(m, n); r++) { cutoff = 2 + n_randint(state, 5); gr_mat_init(A, m, n, ctx); gr_mat_init(LU, m, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * m); status = gr_mat_lu_recursive(&rank, P, LU, A, 0, cutoff, ctx); if (status == GR_SUCCESS) { if (rank > r) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); gr_mat_print(A, ctx); flint_printf("LU:"); gr_mat_print(LU, ctx); flint_abort(); } check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } /* Test rank check for square matrices */ for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, LU; slong n, r, d, rank; slong * P; int status; slong cutoff; if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx); else gr_ctx_init_fmpq(ctx); n = n_randint(state, 10); for (r = 0; r <= n; r++) { cutoff = 2 + n_randint(state, 5); gr_mat_init(A, n, n, ctx); gr_mat_init(LU, n, n, ctx); _gr_mat_randrank(A, state, r, 5, ctx); if (n_randint(state, 2)) { d = n_randint(state, 2*n*n + 1); GR_MUST_SUCCEED(gr_mat_randops(A, state, d, ctx)); } P = flint_malloc(sizeof(slong) * n); status = gr_mat_lu_recursive(&rank, P, LU, A, 1, cutoff, ctx); if (status == GR_SUCCESS) { if ((rank == 0) != (r < n || n == 0)) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("rank check\n"); flint_printf("r = %wd, rank = %wd\n", r, rank); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("LU:\n"); gr_mat_print(LU, ctx); flint_abort(); } if (rank != 0) check(P, LU, A, rank, ctx); } gr_mat_clear(A, ctx); gr_mat_clear(LU, ctx); flint_free(P); } gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-minpoly_field.c000066400000000000000000000112451461254215100211140ustar00rootroot00000000000000/* Copyright (C) 2010, 2022 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" /* #include "fq.h" */ FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_minpoly_field, state, count_success, count_unable, count_domain) { slong iter; /* minpoly(A) divides charpoly(A) */ for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A; gr_poly_t p1, p2, q, r; slong m, n; int status = GR_SUCCESS; /* while (1) { gr_ctx_init_random(ctx, state); if (gr_ctx_is_field(ctx) == T_TRUE) break; gr_ctx_clear(ctx); } */ gr_ctx_init_random(ctx, state); if (ctx->methods == _ca_methods) { m = n_randint(state, 4); n = m; } else { m = n_randint(state, 10); n = m; } gr_poly_init(p1, ctx); gr_poly_init(p2, ctx); gr_poly_init(q, ctx); gr_poly_init(r, ctx); gr_mat_init(A, m, n, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_charpoly(p1, A, ctx); status |= gr_mat_minpoly_field(p2, A, ctx); if ((gr_ctx_is_field(ctx) == T_TRUE && status == GR_DOMAIN) || (ctx->which_ring == GR_CTX_FMPQ && status != GR_SUCCESS)) { flint_printf("FAIL:\n"); flint_printf("expected success\n"); gr_ctx_println(ctx); gr_mat_print(A, ctx); fflush(stdout); flint_abort(); } status |= gr_poly_divrem(q, r, p1, p2, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(r, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("minpoly(A) doesn't divide charpoly(A).\n"); fflush(stdout); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_poly_clear(p1, ctx); gr_poly_clear(p2, ctx); gr_poly_clear(q, ctx); gr_poly_clear(r, ctx); gr_ctx_clear(ctx); } /* minpoly(P^{-1}AP) == minpoly(A) */ for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; gr_ctx_t ctx; gr_mat_t A, B; gr_poly_t p1, p2; gr_ptr t; slong j, k, m, n; gr_ctx_init_random(ctx, state); if (ctx->methods == _ca_methods) { m = n_randint(state, 4); n = m; } else { m = n_randint(state, 10); n = m; } t = gr_heap_init(ctx); gr_poly_init(p1, ctx); gr_poly_init(p2, ctx); gr_mat_init(A, m, n, ctx); gr_mat_init(B, m, n, ctx); status |= gr_mat_randtest(A, state, ctx); for (j = 0; j < n / 2; j++) { for (k = 0; k < n / 2; k++) { status |= gr_zero(gr_mat_entry_ptr(A, j + n / 2, k, ctx), ctx); status |= gr_zero(gr_mat_entry_ptr(A, j, k + n / 2, ctx), ctx); status |= gr_set(gr_mat_entry_ptr(A, j + n / 2, k + n / 2, ctx), gr_mat_entry_ptr(A, j, k, ctx), ctx); } } status |= gr_mat_set(B, A, ctx); status |= gr_mat_minpoly_field(p1, A, ctx); if (status == GR_SUCCESS) { for (j = 0; j < n; j++) { status |= gr_set_si(t, n_randint(state, 6) - 3, ctx); status |= gr_mat_apply_row_similarity(B, n_randint(state, n), t, ctx); } status |= gr_mat_minpoly_field(p2, B, ctx); if (status == GR_SUCCESS && gr_poly_equal(p1, p2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("minpoly(P^{-1}AP) != minpoly(A).\n"); fflush(stdout); flint_abort(); } } gr_heap_clear(t, ctx); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_poly_clear(p1, ctx); gr_poly_clear(p2, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-mul_strassen.c000066400000000000000000000046021461254215100210000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_mul_strassen, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, B, C, D; slong a, b, c; int status = GR_SUCCESS; if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx); else gr_ctx_init_nmod(ctx, n_randtest_not_zero(state)); a = n_randint(state, 8); b = n_randint(state, 8); c = n_randint(state, 8); gr_mat_init(A, a, b, ctx); gr_mat_init(B, b, c, ctx); gr_mat_init(C, a, c, ctx); gr_mat_init(D, a, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_randtest(C, state, ctx); status |= gr_mat_randtest(D, state, ctx); if (b == c && n_randint(state, 2)) { status |= gr_mat_set(C, A, ctx); status |= gr_mat_mul_strassen(C, C, B, ctx); } else if (a == b && n_randint(state, 2)) { status |= gr_mat_set(C, B, ctx); status |= gr_mat_mul_strassen(C, A, C, ctx); } else { status |= gr_mat_mul_strassen(C, A, B, ctx); } status |= gr_mat_mul_classical(D, A, B, ctx); if (status != GR_SUCCESS && gr_mat_equal(C, D, ctx) == T_FALSE) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B:\n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("C:\n"); gr_mat_print(C, ctx); flint_printf("\n\n"); flint_printf("D:\n"); gr_mat_print(D, ctx); flint_printf("\n\n"); flint_abort(); } gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); gr_mat_clear(D, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-nullspace.c000066400000000000000000000063721461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_GR_FUNCTION_START(gr_mat_nullspace, state, count_success, count_unable, count_domain) { slong iter; /* Check that random row/column operations preserve rank */ for (iter = 0; iter < 10000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, AX; slong r, c, rank, nullity; int status = GR_SUCCESS; int status2 = GR_SUCCESS; gr_ctx_init_random(ctx, state); r = n_randint(state, 6); c = n_randint(state, 6); gr_mat_init(A, r, c, ctx); gr_mat_init(X, 0, 0, ctx); GR_MUST_SUCCEED(gr_mat_randtest(A, state, ctx)); status = gr_mat_nullspace(X, A, ctx); if (status == GR_SUCCESS) { status2 = gr_mat_rank(&rank, A, ctx); if (status2 == GR_SUCCESS) { nullity = c - rank; if (nullity != gr_mat_ncols(X, ctx)) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("r = %wd, c = %wd\n", r, c); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("X: "); gr_mat_print(X, ctx); flint_printf("\n"); flint_printf("rank = %wd, nullity = %wd\n\n", rank, nullity); flint_abort(); } gr_mat_init(AX, r, nullity, ctx); status2 |= gr_mat_mul(AX, A, X, ctx); if (status2 == GR_SUCCESS && gr_mat_is_zero(AX, ctx) == T_FALSE) { flint_printf("FAIL (2):\n"); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("X: "); gr_mat_print(X, ctx); flint_printf("\n"); flint_printf("AX: "); gr_mat_print(AX, ctx); flint_printf("\n"); flint_printf("rank = %wd, nullity = %wd\n\n", rank, nullity); flint_abort(); } status2 |= gr_mat_rank(&nullity, X, ctx); if (status2 == GR_SUCCESS && nullity != gr_mat_ncols(X, ctx)) { flint_printf("FAIL (3):\n"); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("X: "); gr_mat_print(X, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank, nullity); flint_abort(); } gr_mat_clear(AX, ctx); } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(X, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-properties.c000066400000000000000000000153021461254215100204540ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_properties, state) { slong iter; for (iter = 0; iter < 10000; iter++) { int status = GR_SUCCESS; slong i, j, m, n; gr_ctx_t ctx; gr_mat_t A, B; truth_t eq1, eq2; gr_ctx_init_fmpz(ctx); m = n_randint(state, 5); n = n_randint(state, 5); gr_mat_init(A, m, n, ctx); gr_mat_init(B, m, n, ctx); GR_MUST_SUCCEED(gr_mat_randtest(A, state, ctx)); eq1 = gr_mat_is_lower_triangular(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) for (j = i + 1; j < n; j++) status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_lower_triangular)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } eq1 = gr_mat_is_upper_triangular(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) for (j = 0; j < FLINT_MIN(i, n); j++) status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_upper_triangular)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } eq1 = gr_mat_is_hessenberg(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) for (j = 0; j < FLINT_MIN(i - 1, n); j++) status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_hessenberg)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } eq1 = gr_mat_is_diagonal(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) for (j = 0; j < n; j++) if (i != j) status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_diagonal)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } eq1 = gr_mat_is_zero(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) for (j = 0; j < n; j++) status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_zero)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } eq1 = gr_mat_is_one(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) for (j = 0; j < n; j++) if (i == j) status |= gr_one(gr_mat_entry_ptr(B, i, j, ctx), ctx); else status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_one)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } eq1 = gr_mat_is_neg_one(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) for (j = 0; j < n; j++) if (i == j) status |= gr_neg_one(gr_mat_entry_ptr(B, i, j, ctx), ctx); else status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_neg_one)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } eq1 = gr_mat_is_scalar(A, ctx); status = gr_mat_set(B, A, ctx); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) if (i != j) status |= gr_zero(gr_mat_entry_ptr(B, i, j, ctx), ctx); if (i > 0 && i < n) status |= gr_set(gr_mat_entry_ptr(B, i, i, ctx), gr_mat_entry_ptr(B, 0, 0, ctx), ctx); } eq2 = gr_mat_equal(A, B, ctx); if (status == GR_SUCCESS && ((eq1 == T_TRUE && eq2 == T_FALSE) || (eq1 == T_FALSE && eq2 == T_TRUE))) { flint_printf("FAIL (is_scalar)\n"); printf("A = "); gr_mat_print(A, ctx); printf("\n"); printf("B = "); gr_mat_print(B, ctx); printf("\n"); truth_println(eq1); truth_println(eq2); flint_abort(); } gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-randrank.c000066400000000000000000000030151461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_randrank, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A; slong rank1, rank2, r, c; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); if (gr_ctx_is_integral_domain(ctx) == T_TRUE) { r = n_randint(state, 6); c = n_randint(state, 6); gr_mat_init(A, r, c, ctx); rank1 = n_randint(state, 6); status |= gr_mat_randrank(A, state, rank1, ctx); status |= gr_mat_rank(&rank2, A, ctx); if (status == GR_SUCCESS) { if (rank1 != rank2) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } gr_mat_clear(A, ctx); } gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-rank.c000066400000000000000000000040451461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_GR_FUNCTION_START(gr_mat_rank, state, count_success, count_unable, count_domain) { slong iter; /* Check that random row/column operations preserve rank */ for (iter = 0; iter < 10000; iter++) { gr_ctx_t ctx; gr_mat_t A, B; slong rank1, rank2, r, c; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); r = n_randint(state, 6); c = n_randint(state, 6); gr_mat_init(A, r, c, ctx); gr_mat_init(B, r, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_set(B, A, ctx); status |= gr_mat_randops(B, state, 1 + n_randint(state, 20), ctx); status |= gr_mat_rank(&rank1, A, ctx); if (status == GR_SUCCESS) { status |= gr_mat_rank(&rank2, B, ctx); if (status == GR_SUCCESS) { if (rank1 != rank2) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-rank_fflu.c000066400000000000000000000042761461254215100202370ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_GR_FUNCTION_START(gr_mat_rank_fflu, state, count_success, count_unable, count_domain) { slong iter; /* Check that random row/column operations preserve rank */ for (iter = 0; iter < 10000; iter++) { gr_ctx_t ctx; gr_mat_t A, B; slong rank1, rank2, r, c; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); r = n_randint(state, 5); c = n_randint(state, 5); gr_mat_init(A, r, c, ctx); gr_mat_init(B, r, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_set(B, A, ctx); status |= gr_mat_randops(B, state, 1 + n_randint(state, 20), ctx); status |= gr_mat_rank_fflu(&rank1, A, ctx); if (status == GR_SUCCESS) { if (gr_ctx_is_integral_domain(ctx) == T_TRUE) { status |= gr_mat_rank_fflu(&rank2, B, ctx); if (status == GR_SUCCESS) { if (rank1 != rank2) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-rank_lu.c000066400000000000000000000040561461254215100177170ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_GR_FUNCTION_START(gr_mat_rank_lu, state, count_success, count_unable, count_domain) { slong iter; /* Check that random row/column operations preserve rank */ for (iter = 0; iter < 10000; iter++) { gr_ctx_t ctx; gr_mat_t A, B; slong rank1, rank2, r, c; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); r = n_randint(state, 5); c = n_randint(state, 5); gr_mat_init(A, r, c, ctx); gr_mat_init(B, r, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_set(B, A, ctx); status |= gr_mat_randops(B, state, 1 + n_randint(state, 20), ctx); status |= gr_mat_rank_lu(&rank1, A, ctx); if (status == GR_SUCCESS) { status |= gr_mat_rank_lu(&rank2, B, ctx); if (status == GR_SUCCESS) { if (rank1 != rank2) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-rref_den_fflu.c000066400000000000000000000070061461254215100210620ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" /* Defined in t-rref_den_fflu.c, t-rref_fflu.c and t-rref_lu.c */ #ifndef gr_mat_randrowops #define gr_mat_randrowops gr_mat_randrowops /* todo: make a function */ int gr_mat_randrowops(gr_mat_t mat, flint_rand_t state, slong count, gr_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (mat->r == 0 || mat->c == 0) return GR_SUCCESS; for (c = 0; c < count; c++) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) status |= gr_add(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); else for (k = 0; k < n; k++) status |= gr_sub(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); } return status; } #endif TEST_GR_FUNCTION_START(gr_mat_rref_den_fflu, state, count_success, count_unable, count_domain) { slong iter; /* Check that random row/column operations preserve rank */ for (iter = 0; iter < 10000; iter++) { gr_ctx_t ctx; gr_mat_t A, B, R, R2; gr_ptr den; slong rank1, rank2, r, c; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); r = n_randint(state, 6); c = n_randint(state, 6); gr_mat_init(A, r, c, ctx); gr_mat_init(B, r, c, ctx); gr_mat_init(R, r, c, ctx); gr_mat_init(R2, r, c, ctx); den = gr_heap_init(ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_set(B, A, ctx); status |= gr_mat_randrowops(B, state, 1 + n_randint(state, 20), ctx); status |= gr_mat_rref_fflu(&rank1, R, A, ctx); if (status == GR_SUCCESS) { status |= gr_mat_rref_den_fflu(&rank2, R2, den, B, ctx); status |= gr_mat_div_scalar(R2, R2, den, ctx); if (status == GR_SUCCESS) { if (rank1 != rank2 || gr_mat_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("R: "); gr_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); gr_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(R, ctx); gr_mat_clear(R2, ctx); gr_heap_clear(den, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-rref_fflu.c000066400000000000000000000065501461254215100202370ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" /* Defined in t-rref_den_fflu.c, t-rref_fflu.c and t-rref_lu.c */ #ifndef gr_mat_randrowops #define gr_mat_randrowops gr_mat_randrowops /* todo: make a function */ int gr_mat_randrowops(gr_mat_t mat, flint_rand_t state, slong count, gr_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (mat->r == 0 || mat->c == 0) return GR_SUCCESS; for (c = 0; c < count; c++) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) status |= gr_add(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); else for (k = 0; k < n; k++) status |= gr_sub(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); } return status; } #endif TEST_GR_FUNCTION_START(gr_mat_rref_fflu, state, count_success, count_unable, count_domain) { slong iter; /* Check that random row/column operations preserve rank */ for (iter = 0; iter < 10000; iter++) { gr_ctx_t ctx; gr_mat_t A, B, R, R2; slong rank1, rank2, r, c; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); r = n_randint(state, 6); c = n_randint(state, 6); gr_mat_init(A, r, c, ctx); gr_mat_init(B, r, c, ctx); gr_mat_init(R, r, c, ctx); gr_mat_init(R2, r, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_set(B, A, ctx); status |= gr_mat_randrowops(B, state, 1 + n_randint(state, 20), ctx); status |= gr_mat_rref_fflu(&rank1, R, A, ctx); if (status == GR_SUCCESS) { status |= gr_mat_rref_fflu(&rank2, R2, B, ctx); if (status == GR_SUCCESS) { if (rank1 != rank2 || gr_mat_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("R: "); gr_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); gr_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(R, ctx); gr_mat_clear(R2, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-rref_lu.c000066400000000000000000000065421461254215100177240ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" /* Defined in t-rref_den_fflu.c, t-rref_fflu.c and t-rref_lu.c */ #ifndef gr_mat_randrowops #define gr_mat_randrowops gr_mat_randrowops /* todo: make a function */ int gr_mat_randrowops(gr_mat_t mat, flint_rand_t state, slong count, gr_ctx_t ctx) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (mat->r == 0 || mat->c == 0) return GR_SUCCESS; for (c = 0; c < count; c++) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) status |= gr_add(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); else for (k = 0; k < n; k++) status |= gr_sub(GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, j, k, sz), GR_MAT_ENTRY(mat, i, k, sz), ctx); } return status; } #endif TEST_GR_FUNCTION_START(gr_mat_rref_lu, state, count_success, count_unable, count_domain) { slong iter; /* Check that random row/column operations preserve rank */ for (iter = 0; iter < 10000; iter++) { gr_ctx_t ctx; gr_mat_t A, B, R, R2; slong rank1, rank2, r, c; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); r = n_randint(state, 6); c = n_randint(state, 6); gr_mat_init(A, r, c, ctx); gr_mat_init(B, r, c, ctx); gr_mat_init(R, r, c, ctx); gr_mat_init(R2, r, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_set(B, A, ctx); status |= gr_mat_randrowops(B, state, 1 + n_randint(state, 20), ctx); status |= gr_mat_rref_lu(&rank1, R, A, ctx); if (status == GR_SUCCESS) { status |= gr_mat_rref_lu(&rank2, R2, B, ctx); if (status == GR_SUCCESS) { if (rank1 != rank2 || gr_mat_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL:\n"); gr_ctx_println(ctx); flint_printf("A: "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B: "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("R: "); gr_mat_print(R, ctx); flint_printf("\n"); flint_printf("R2: "); gr_mat_print(R2, ctx); flint_printf("\n"); flint_printf("rank = %wd, %wd\n\n", rank1, rank2); flint_abort(); } } } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(R, ctx); gr_mat_clear(R2, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-solve.c000066400000000000000000000061111461254215100174060ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_solve, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, B, AX; slong n, c; int status = GR_SUCCESS; n = n_randint(state, 6); c = n_randint(state, 6); /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, c, ctx); gr_mat_init(X, n, c, ctx); gr_mat_init(AX, n, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_nonsingular_solve(X, A, B, ctx); if (status == GR_SUCCESS) { status |= gr_mat_mul(AX, A, X, ctx); if (status == GR_SUCCESS && gr_mat_equal(AX, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = \n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); gr_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("AX = \n"); gr_mat_print(AX, ctx); flint_printf("\n\n"); flint_abort(); } } else if ((status & GR_DOMAIN) && !(status & GR_UNABLE) && gr_ctx_is_integral_domain(ctx) == T_TRUE) { gr_ptr det; int status2; det = gr_heap_init(ctx); status2 = gr_mat_det_berkowitz(det, A, ctx); if (status2 == GR_SUCCESS && gr_is_invertible(det, ctx) == T_TRUE) { flint_printf("FAIL (singular)\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); gr_print(det, ctx); flint_printf("\n"); flint_abort(); } gr_heap_clear(det, ctx); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(AX, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-solve_den.c000066400000000000000000000064701461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_solve_den, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, B, AX, Bden; gr_ptr den; slong n, c; int status = GR_SUCCESS; n = n_randint(state, 6); c = n_randint(state, 6); /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, c, ctx); gr_mat_init(X, n, c, ctx); gr_mat_init(AX, n, c, ctx); gr_mat_init(Bden, n, c, ctx); den = gr_heap_init(ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_nonsingular_solve_den(X, den, A, B, ctx); if (status == GR_SUCCESS) { status |= gr_mat_mul(AX, A, X, ctx); status |= gr_mat_mul_scalar(Bden, B, den, ctx); if (status == GR_SUCCESS && gr_mat_equal(AX, Bden, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = \n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); gr_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("AX = \n"); gr_mat_print(AX, ctx); flint_printf("\n\n"); flint_abort(); } } else if ((status & GR_DOMAIN) && !(status & GR_UNABLE) && gr_ctx_is_integral_domain(ctx) == T_TRUE) { gr_ptr det; int status2; det = gr_heap_init(ctx); status2 = gr_mat_det_berkowitz(det, A, ctx); if (status2 == GR_SUCCESS && gr_is_invertible(det, ctx) == T_TRUE) { flint_printf("FAIL (singular)\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); gr_print(det, ctx); flint_printf("\n"); flint_abort(); } gr_heap_clear(det, ctx); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_heap_clear(den, ctx); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(AX, ctx); gr_mat_clear(Bden, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-solve_den_fflu.c000066400000000000000000000065021461254215100212540ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_solve_den_fflu, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, B, AX, Bden; gr_ptr den; slong n, c; int status = GR_SUCCESS; n = n_randint(state, 6); c = n_randint(state, 6); /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, c, ctx); gr_mat_init(X, n, c, ctx); gr_mat_init(AX, n, c, ctx); gr_mat_init(Bden, n, c, ctx); den = gr_heap_init(ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_nonsingular_solve_den_fflu(X, den, A, B, ctx); if (status == GR_SUCCESS) { status |= gr_mat_mul(AX, A, X, ctx); status |= gr_mat_mul_scalar(Bden, B, den, ctx); if (status == GR_SUCCESS && gr_mat_equal(AX, Bden, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = \n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); gr_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("AX = \n"); gr_mat_print(AX, ctx); flint_printf("\n\n"); flint_abort(); } } else if ((status & GR_DOMAIN) && !(status & GR_UNABLE) && gr_ctx_is_integral_domain(ctx) == T_TRUE) { gr_ptr det; int status2; det = gr_heap_init(ctx); status2 = gr_mat_det_berkowitz(det, A, ctx); if (status2 == GR_SUCCESS && gr_is_invertible(det, ctx) == T_TRUE) { flint_printf("FAIL (singular)\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); gr_print(det, ctx); flint_printf("\n"); flint_abort(); } gr_heap_clear(det, ctx); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_heap_clear(den, ctx); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(AX, ctx); gr_mat_clear(Bden, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-solve_fflu.c000066400000000000000000000061241461254215100204260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_solve_fflu, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, B, AX; slong n, c; int status = GR_SUCCESS; n = n_randint(state, 6); c = n_randint(state, 6); /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, c, ctx); gr_mat_init(X, n, c, ctx); gr_mat_init(AX, n, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_nonsingular_solve_fflu(X, A, B, ctx); if (status == GR_SUCCESS) { status |= gr_mat_mul(AX, A, X, ctx); if (status == GR_SUCCESS && gr_mat_equal(AX, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = \n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); gr_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("AX = \n"); gr_mat_print(AX, ctx); flint_printf("\n\n"); flint_abort(); } } else if ((status & GR_DOMAIN) && !(status & GR_UNABLE) && gr_ctx_is_integral_domain(ctx) == T_TRUE) { gr_ptr det; int status2; det = gr_heap_init(ctx); status2 = gr_mat_det_berkowitz(det, A, ctx); if (status2 == GR_SUCCESS && gr_is_invertible(det, ctx) == T_TRUE) { flint_printf("FAIL (singular)\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); gr_print(det, ctx); flint_printf("\n"); flint_abort(); } gr_heap_clear(det, ctx); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(AX, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-solve_field.c000066400000000000000000000111751461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson Copyright (C) 2013 Mike Hansen Copyright (C) 2018 Tommy Hofmann Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "fq_nmod_mat.h" TEST_FUNCTION_START(gr_mat_solve_field, state) { gr_ctx_t ctx; gr_mat_t A, X, X2, B, AX; slong i, k, m, n; int status; /* test random systems */ for (i = 0; i < 1000; i++) { status = GR_SUCCESS; gr_ctx_init_random(ctx, state); /* gr_ctx_init_fmpq(ctx); fmpz p = 17; gr_ctx_init_fq_nmod(ctx, &p, 1, "a"); */ m = n_randint(state, 6); n = n_randint(state, 6); k = n_randint(state, 6); gr_mat_init(A, m, k, ctx); gr_mat_init(B, m, n, ctx); gr_mat_init(X, k, n, ctx); gr_mat_init(AX, m, n, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(B, state, ctx); /* gr_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), ctx); if (n_randint(state, 2)) gr_mat_randops(A, 1+n_randint(state, 1+m*m), state, ctx); */ status |= gr_mat_solve_field(X, A, B, ctx); status |= gr_mat_mul(AX, A, X, ctx); if ((status == GR_SUCCESS && gr_mat_equal(AX, B, ctx) == T_FALSE)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("B:\n"); gr_mat_print(B, ctx); flint_printf("X:\n"); gr_mat_print(X, ctx); flint_printf("AX:\n"); gr_mat_print(AX, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || ctx->which_ring == GR_CTX_FQ || ctx->which_ring == GR_CTX_FQ_NMOD || ctx->which_ring == GR_CTX_FQ_ZECH) && status == GR_UNABLE) { flint_printf("FAIL: unable over exact field\n"); fflush(stdout); flint_abort(); } gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(AX, ctx); gr_ctx_clear(ctx); } /* test random solvable systems */ for (i = 0; i < 1000; i++) { status = GR_SUCCESS; /* fmpz p = 17; gr_ctx_init_fq_nmod(ctx, &p, 1, "a"); */ while (1) { gr_ctx_init_random(ctx, state); if (gr_ctx_is_field(ctx) == T_TRUE) break; gr_ctx_clear(ctx); } m = n_randint(state, 6); n = n_randint(state, 6); k = n_randint(state, 6); gr_mat_init(A, m, k, ctx); gr_mat_init(B, m, n, ctx); gr_mat_init(X, k, n, ctx); gr_mat_init(X2, k, n, ctx); gr_mat_init(AX, m, n, ctx); /* status |= gr_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1), ctx); */ status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X2, state, ctx); status |= gr_mat_mul(B, A, X2, ctx); status |= gr_mat_solve_field(X, A, B, ctx); status |= gr_mat_mul(AX, A, X, ctx); if (status == GR_DOMAIN || (status == GR_SUCCESS && gr_mat_equal(AX, B, ctx) == T_FALSE)) { flint_printf("FAIL:\n"); flint_printf("status = %d\n", status); flint_printf("AX != B!\n"); flint_printf("A:\n"); gr_mat_print(A, ctx); flint_printf("B:\n"); gr_mat_print(B, ctx); flint_printf("X:\n"); gr_mat_print(X, ctx); flint_printf("AX:\n"); gr_mat_print(AX, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || ctx->which_ring == GR_CTX_FQ || ctx->which_ring == GR_CTX_FQ_NMOD || ctx->which_ring == GR_CTX_FQ_ZECH) && status == GR_UNABLE) { flint_printf("FAIL: unable over exact field\n"); fflush(stdout); flint_abort(); } gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(X2, ctx); gr_mat_clear(AX, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/test/t-solve_lu.c000066400000000000000000000061061461254215100201120ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_solve_lu, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, B, AX; slong n, c; int status = GR_SUCCESS; n = n_randint(state, 6); c = n_randint(state, 6); /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_mat_init(A, n, n, ctx); gr_mat_init(B, n, c, ctx); gr_mat_init(X, n, c, ctx); gr_mat_init(AX, n, c, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X, state, ctx); status |= gr_mat_randtest(B, state, ctx); status |= gr_mat_nonsingular_solve_lu(X, A, B, ctx); if (status == GR_SUCCESS) { status |= gr_mat_mul(AX, A, X, ctx); if (status == GR_SUCCESS && gr_mat_equal(AX, B, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = \n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); gr_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("AX = \n"); gr_mat_print(AX, ctx); flint_printf("\n\n"); flint_abort(); } } else if ((status & GR_DOMAIN) && !(status & GR_UNABLE) && gr_ctx_is_field(ctx) == T_TRUE) { gr_ptr det; int status2; det = gr_heap_init(ctx); status2 = gr_mat_det_berkowitz(det, A, ctx); if (status2 == GR_SUCCESS && gr_is_invertible(det, ctx) == T_TRUE) { flint_printf("FAIL (singular)\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("det = "); gr_print(det, ctx); flint_printf("\n"); flint_abort(); } gr_heap_clear(det, ctx); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(AX, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-solve_tril.c000066400000000000000000000064241461254215100204470ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_solve_tril, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, B, Y; slong rows, cols, i, j; int unit; int status = GR_SUCCESS; slong sz; rows = n_randint(state, 15); cols = n_randint(state, 15); unit = n_randint(state, 2); /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } sz = ctx->sizeof_elem; gr_mat_init(A, rows, rows, ctx); gr_mat_init(B, rows, cols, ctx); gr_mat_init(X, rows, cols, ctx); gr_mat_init(Y, rows, cols, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X, state, ctx); status |= gr_mat_randtest(Y, state, ctx); for (i = 0; i < rows; i++) { if (unit) status |= gr_one(GR_MAT_ENTRY(A, i, i, sz), ctx); else status |= gr_set_ui(GR_MAT_ENTRY(A, i, i, sz), 1 + n_randint(state, 100), ctx); for (j = i + 1; j < rows; j++) status |= gr_zero(GR_MAT_ENTRY(A, i, j, sz), ctx); } status |= gr_mat_mul(B, A, X, ctx); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) status |= gr_set_ui(GR_MAT_ENTRY(A, i, i, sz), 1 + n_randint(state, 100), ctx); } /* Check Y = A^(-1) * (A * X) = X */ if (n_randint(state, 2)) { status |= gr_mat_nonsingular_solve_tril(Y, A, B, unit, ctx); } else { status |= gr_mat_set(Y, B, ctx); status |= gr_mat_nonsingular_solve_tril(Y, A, Y, unit, ctx); } if (status == GR_SUCCESS && gr_mat_equal(Y, X, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = \n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); gr_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("Y = \n"); gr_mat_print(Y, ctx); flint_printf("\n\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(Y, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-solve_triu.c000066400000000000000000000064151461254215100204600ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_GR_FUNCTION_START(gr_mat_solve_triu, state, count_success, count_unable, count_domain) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_mat_t A, X, B, Y; slong rows, cols, i, j; int unit; int status = GR_SUCCESS; slong sz; rows = n_randint(state, 15); cols = n_randint(state, 15); unit = n_randint(state, 2); /* Hack: avoid because slow */ gr_ctx_init_random(ctx, state); while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } sz = ctx->sizeof_elem; gr_mat_init(A, rows, rows, ctx); gr_mat_init(B, rows, cols, ctx); gr_mat_init(X, rows, cols, ctx); gr_mat_init(Y, rows, cols, ctx); status |= gr_mat_randtest(A, state, ctx); status |= gr_mat_randtest(X, state, ctx); status |= gr_mat_randtest(Y, state, ctx); for (i = 0; i < rows; i++) { if (unit) status |= gr_one(GR_MAT_ENTRY(A, i, i, sz), ctx); else status |= gr_set_ui(GR_MAT_ENTRY(A, i, i, sz), 1 + n_randint(state, 100), ctx); for (j = 0; j < i; j++) status |= gr_zero(GR_MAT_ENTRY(A, i, j, sz), ctx); } status |= gr_mat_mul(B, A, X, ctx); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) status |= gr_set_ui(GR_MAT_ENTRY(A, i, i, sz), 1 + n_randint(state, 100), ctx); } /* Check Y = A^(-1) * (A * X) = X */ if (n_randint(state, 2)) { status |= gr_mat_nonsingular_solve_triu(Y, A, B, unit, ctx); } else { status |= gr_mat_set(Y, B, ctx); status |= gr_mat_nonsingular_solve_triu(Y, A, Y, unit, ctx); } if (status == GR_SUCCESS && gr_mat_equal(Y, X, ctx) == T_FALSE) { flint_printf("FAIL\n"); gr_ctx_println(ctx); flint_printf("A = \n"); gr_mat_print(A, ctx); flint_printf("\n\n"); flint_printf("B = \n"); gr_mat_print(B, ctx); flint_printf("\n\n"); flint_printf("X = \n"); gr_mat_print(X, ctx); flint_printf("\n\n"); flint_printf("Y = \n"); gr_mat_print(Y, ctx); flint_printf("\n\n"); flint_abort(); } count_success += (status == GR_SUCCESS); count_domain += ((status & GR_DOMAIN) != 0); count_unable += ((status & GR_UNABLE) != 0); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(X, ctx); gr_mat_clear(Y, ctx); gr_ctx_clear(ctx); } TEST_GR_FUNCTION_END(state, count_success, count_unable, count_domain); } flint-3.1.3/src/gr_mat/test/t-window_init_clear.c000066400000000000000000000034151461254215100217620ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mat.h" TEST_FUNCTION_START(gr_mat_window_init_clear, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; slong r, c, r1, r2, c1, c2; gr_ctx_t ctx; gr_mat_t A, B, C; gr_ctx_init_random(ctx, state); r = n_randint(state, 8); c = n_randint(state, 8); r2 = n_randint(state, r + 1); r1 = n_randint(state, r2 + 1); c2 = n_randint(state, c + 1); c1 = n_randint(state, c2 + 1); gr_mat_init(A, r, c, ctx); gr_mat_window_init(B, A, r1, c1, r2, c2, ctx); GR_MUST_SUCCEED(gr_mat_randtest(A, state, ctx)); GR_MUST_SUCCEED(gr_mat_randtest(B, state, ctx)); gr_mat_window_init(C, A, r1, c1, r2, c2, ctx); status = gr_mat_one(C, ctx); if (status == GR_SUCCESS && gr_mat_is_one(C, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("A = "); gr_mat_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_mat_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_mat_print(C, ctx); flint_printf("\n"); flint_abort(); } gr_mat_window_clear(B, ctx); gr_mat_window_clear(C, ctx); gr_mat_clear(A, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mat/trace.c000066400000000000000000000017201461254215100161350ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_trace(gr_ptr res, const gr_mat_t mat, gr_ctx_t ctx) { slong i, r, c; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; r = mat->r; c = mat->c; if (r != c) return GR_DOMAIN; if (r == 0) return gr_zero(res, ctx); if (r == 1) return gr_set(res, GR_MAT_ENTRY(mat, 0, 0, sz), ctx); status |= gr_add(res, GR_MAT_ENTRY(mat, 0, 0, sz), GR_MAT_ENTRY(mat, 1, 1, sz), ctx); for (i = 2; i < r; i++) status |= gr_add(res, res, GR_MAT_ENTRY(mat, i, i, sz), ctx); return status; } flint-3.1.3/src/gr_mat/transpose.c000066400000000000000000000022611461254215100170560ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_transpose(gr_mat_t B, const gr_mat_t A, gr_ctx_t ctx) { slong i, j; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (B->r != A->c || B->c != A->r) return GR_DOMAIN; if (A->r == 0 || A->c == 0) return GR_SUCCESS; if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < A->r - 1; i++) { for (j = i + 1; j < A->c; j++) { gr_swap(GR_MAT_ENTRY(A, i, j, sz), GR_MAT_ENTRY(A, j, i, sz), ctx); } } } else /* Not aliased; general case */ { for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) status |= gr_set(GR_MAT_ENTRY(B, i, j, sz), GR_MAT_ENTRY(A, j, i, sz), ctx); } return status; } flint-3.1.3/src/gr_mat/window_init.c000066400000000000000000000014421461254215100173720ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" void gr_mat_window_init(gr_mat_t window, const gr_mat_t mat, slong r1, slong c1, slong r2, slong c2, gr_ctx_t ctx) { slong i, sz = ctx->sizeof_elem; window->entries = NULL; window->rows = flint_malloc((r2 - r1) * sizeof(gr_ptr)); for (i = 0; i < r2 - r1; i++) window->rows[i] = GR_ENTRY(mat->rows[r1 + i], c1, sz); window->r = r2 - r1; window->c = c2 - c1; } flint-3.1.3/src/gr_mat/write.c000066400000000000000000000021461461254215100161740ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mat.h" int gr_mat_write(gr_stream_t out, const gr_mat_t mat, gr_ctx_t ctx) { int status; slong r, c; slong i, j; slong sz; sz = ctx->sizeof_elem; r = gr_mat_nrows(mat, ctx); c = gr_mat_ncols(mat, ctx); status = GR_SUCCESS; gr_stream_write(out, "["); for (i = 0; i < r; i++) { gr_stream_write(out, "["); for (j = 0; j < c; j++) { status |= gr_write(out, GR_MAT_ENTRY(mat, i, j, sz), ctx); if (j < c - 1) gr_stream_write(out, ", "); } if (i < r - 1) gr_stream_write(out, "],\n"); else gr_stream_write(out, "]"); } gr_stream_write(out, "]"); return status; } flint-3.1.3/src/gr_mat/zero.c000066400000000000000000000013101461254215100160110ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_mat.h" int gr_mat_zero(gr_mat_t res, gr_ctx_t ctx) { int status; slong i, r, c; r = gr_mat_nrows(res, ctx); c = gr_mat_ncols(res, ctx); status = GR_SUCCESS; for (i = 0; i < r; i++) { status |= _gr_vec_zero(res->rows[i], c, ctx); } return status; } flint-3.1.3/src/gr_mpoly.h000066400000000000000000000221171461254215100154260ustar00rootroot00000000000000/* Copyright (C) 2016-2017 William Hart Copyright (C) 2017-2020 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GR_MPOLY_H #define GR_MPOLY_H #ifdef GR_MPOLY_INLINES_C #define GR_MPOLY_INLINE #else #define GR_MPOLY_INLINE static inline #endif #include "mpoly.h" #include "gr_vec.h" #ifdef __cplusplus extern "C" { #endif typedef struct { gr_ptr coeffs; ulong * exps; slong length; flint_bitcnt_t bits; /* number of bits per exponent */ slong coeffs_alloc; /* abs size in mp_limb_t units */ slong exps_alloc; /* abs size in ulong units */ } gr_mpoly_struct; typedef gr_mpoly_struct gr_mpoly_t[1]; /* Memory management */ GR_MPOLY_INLINE void gr_mpoly_init(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->bits = MPOLY_MIN_BITS; A->coeffs_alloc = 0; A->exps_alloc = 0; } void gr_mpoly_init3(gr_mpoly_t A, slong alloc, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx); void gr_mpoly_init2( gr_mpoly_t A, slong alloc, const mpoly_ctx_t mctx, gr_ctx_t cctx); GR_MPOLY_INLINE void gr_mpoly_clear(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { _gr_vec_clear(A->coeffs, A->coeffs_alloc, cctx); if (A->coeffs_alloc > 0) flint_free(A->coeffs); if (A->exps_alloc > 0) flint_free(A->exps); } void _gr_mpoly_fit_length( gr_ptr * coeffs, slong * coeffs_alloc, ulong ** exps, slong * exps_alloc, slong N, slong length, gr_ctx_t cctx); void gr_mpoly_fit_length(gr_mpoly_t A, slong len, const mpoly_ctx_t mctx, gr_ctx_t cctx); void gr_mpoly_fit_bits(gr_mpoly_t A, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx); void gr_mpoly_fit_length_fit_bits( gr_mpoly_t A, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx); void gr_mpoly_fit_length_reset_bits( gr_mpoly_t A, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx); /* todo: when to zero out coefficients? */ GR_MPOLY_INLINE void _gr_mpoly_set_length(gr_mpoly_t A, slong newlen, const mpoly_ctx_t mctx, gr_ctx_t cctx) { FLINT_ASSERT(newlen <= A->coeffs_alloc); FLINT_ASSERT(mpoly_words_per_exp(A->bits, mctx)*newlen <= A->exps_alloc); A->length = newlen; } /* Basic manipulation */ GR_MPOLY_INLINE void gr_mpoly_swap(gr_mpoly_t A, gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) { FLINT_SWAP(gr_mpoly_struct, *A, *B); } WARN_UNUSED_RESULT int gr_mpoly_set(gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx); GR_MPOLY_INLINE WARN_UNUSED_RESULT int gr_mpoly_zero(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { _gr_mpoly_set_length(A, 0, mctx, cctx); return GR_SUCCESS; } GR_MPOLY_INLINE truth_t gr_mpoly_is_zero(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { if (A->length == 0) return T_TRUE; /* todo: skip when we have canonical representation */ return _gr_vec_is_zero(A->coeffs, A->length, cctx); } WARN_UNUSED_RESULT int gr_mpoly_gen(gr_mpoly_t A, slong var, const mpoly_ctx_t mctx, gr_ctx_t cctx); truth_t gr_mpoly_is_gen(const gr_mpoly_t A, slong var, const mpoly_ctx_t mctx, gr_ctx_t cctx); truth_t gr_mpoly_equal(const gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx); /* Container operations */ void _gr_mpoly_push_exp_ui(gr_mpoly_t A, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_push_term_scalar_ui(gr_mpoly_t A, gr_srcptr c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); void _gr_mpoly_push_exp_fmpz(gr_mpoly_t A, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_push_term_scalar_fmpz(gr_mpoly_t A, gr_srcptr c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); void gr_mpoly_sort_terms(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_combine_like_terms(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx); truth_t gr_mpoly_is_canonical(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx); void gr_mpoly_assert_canonical(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx); /* Random generation */ int gr_mpoly_randtest_bits(gr_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const mpoly_ctx_t mctx, gr_ctx_t cctx); /* Input and output */ int gr_mpoly_write_pretty(gr_stream_t out, const gr_mpoly_t A, const char ** x_in, const mpoly_ctx_t mctx, gr_ctx_t cctx); int gr_mpoly_print_pretty(const gr_mpoly_t A, const char ** x_in, const mpoly_ctx_t mctx, gr_ctx_t cctx); /* Constants */ WARN_UNUSED_RESULT int gr_mpoly_set_scalar(gr_mpoly_t A, gr_srcptr c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_ui(gr_mpoly_t A, ulong c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_si(gr_mpoly_t A, slong c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_fmpz(gr_mpoly_t A, const fmpz_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_fmpq(gr_mpoly_t A, const fmpq_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx); GR_MPOLY_INLINE WARN_UNUSED_RESULT int gr_mpoly_one(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { return gr_mpoly_set_ui(A, 1, mctx, cctx); } /* todo: efficient version */ GR_MPOLY_INLINE truth_t gr_mpoly_is_one(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { gr_mpoly_t t; truth_t res = T_UNKNOWN; gr_mpoly_init(t, mctx, cctx); if (gr_mpoly_one(t, mctx, cctx) == GR_SUCCESS) res = gr_mpoly_equal(A, t, mctx, cctx); gr_mpoly_clear(t, mctx, cctx); return res; } /* Coefficient/exponent access */ WARN_UNUSED_RESULT int gr_mpoly_get_coeff_scalar_fmpz(gr_ptr c, const gr_mpoly_t A, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_get_coeff_scalar_ui(gr_ptr c, const gr_mpoly_t A, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_scalar_fmpz(gr_mpoly_t A, gr_srcptr c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_ui_fmpz(gr_mpoly_t A, ulong c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_si_fmpz(gr_mpoly_t A, slong c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_fmpz_fmpz(gr_mpoly_t A, const fmpz_t c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_fmpq_fmpz(gr_mpoly_t A, const fmpq_t c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_scalar_ui(gr_mpoly_t poly, gr_srcptr c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_ui_ui(gr_mpoly_t A, ulong c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_si_ui(gr_mpoly_t A, slong c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_fmpz_ui(gr_mpoly_t A, const fmpz_t c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_set_coeff_fmpq_ui(gr_mpoly_t A, const fmpq_t c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx); /* Arithmetic */ WARN_UNUSED_RESULT int gr_mpoly_neg(gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_add(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_sub(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul(gr_mpoly_t poly1, const gr_mpoly_t poly2, const gr_mpoly_t poly3, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul_johnson(gr_mpoly_t poly1, const gr_mpoly_t poly2, const gr_mpoly_t poly3, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul_monomial(gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul_scalar(gr_mpoly_t A, const gr_mpoly_t B, gr_srcptr c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul_si(gr_mpoly_t A, const gr_mpoly_t B, slong c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul_ui(gr_mpoly_t A, const gr_mpoly_t B, ulong c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul_fmpz(gr_mpoly_t A, const gr_mpoly_t B, const fmpz_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx); WARN_UNUSED_RESULT int gr_mpoly_mul_fmpq(gr_mpoly_t A, const gr_mpoly_t B, const fmpq_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/gr_mpoly/000077500000000000000000000000001461254215100152525ustar00rootroot00000000000000flint-3.1.3/src/gr_mpoly/add.c000066400000000000000000000103551461254215100161520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" slong _gr_mpoly_add( slong * Alen, gr_ptr Acoeffs, ulong * Aexps, gr_srcptr Bcoeffs, const ulong * Bexps, slong Blen, gr_srcptr Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, gr_ctx_t fctx) { gr_method_binary_op add = GR_BINARY_OP(fctx, ADD); gr_method_unary_op set = GR_UNARY_OP(fctx, SET); slong sz = fctx->sizeof_elem; slong i = 0, j = 0, k = 0; int status = GR_SUCCESS; while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); status |= set(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Bcoeffs, i, sz), fctx); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); status |= add(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Bcoeffs, i, sz), GR_ENTRY(Ccoeffs, j, sz), fctx); k += (gr_is_zero(GR_ENTRY(Acoeffs, k, sz), fctx) != T_TRUE); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); status |= set(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Ccoeffs, j, sz), fctx); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); status |= set(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Bcoeffs, i, sz), fctx); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); status |= set(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Ccoeffs, j, sz), fctx); j++; k++; } *Alen = k; return status; } int gr_mpoly_add( gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong Abits, N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; int status = GR_SUCCESS; TMP_INIT; if (B->length == 0) return gr_mpoly_set(A, C, mctx, cctx); if (C->length == 0) return gr_mpoly_set(A, B, mctx, cctx); TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, mctx); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, mctx); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, mctx); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, mctx); } if (A == B || A == C) { gr_mpoly_t T; gr_mpoly_init3(T, B->length + C->length, Abits, mctx, cctx); status = _gr_mpoly_add(&T->length, T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, cctx); gr_mpoly_swap(A, T, mctx, cctx); gr_mpoly_clear(T, mctx, cctx); } else { gr_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, mctx, cctx); status = _gr_mpoly_add(&A->length, A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, cctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; return status; } flint-3.1.3/src/gr_mpoly/combine_like_terms.c000066400000000000000000000034311461254215100212510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" /* assuming that the exponents are valid and sorted, put the polynomial in canonical form i.e. 2*x^e + 3*x^e -> 5x^e 2*x^e - 2*x^e -> 0 */ int gr_mpoly_combine_like_terms( gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { gr_method_binary_op add = GR_BINARY_OP(cctx, ADD); gr_method_swap_op swap = GR_SWAP_OP(cctx, SWAP); gr_method_unary_predicate is_zero = GR_UNARY_PREDICATE(cctx, IS_ZERO); int status = GR_SUCCESS; slong in, out, N; slong sz = cctx->sizeof_elem; N = mpoly_words_per_exp(A->bits, mctx); out = -WORD(1); for (in = 0; in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= 0 && mpoly_monomial_equal(A->exps + N*out, A->exps + N*in, N)) { status |= add(GR_ENTRY(A->coeffs, out, sz), GR_ENTRY(A->coeffs, out, sz), GR_ENTRY(A->coeffs, in, sz), cctx); } else { if (out < 0 || is_zero(GR_ENTRY(A->coeffs, out, sz), cctx) != T_TRUE) out++; if (out != in) { mpoly_monomial_set(A->exps + N*out, A->exps + N*in, N); swap(GR_ENTRY(A->coeffs, out, sz), GR_ENTRY(A->coeffs, in, sz), cctx); } } } if (out < 0 || is_zero(GR_ENTRY(A->coeffs, out, sz), cctx) != T_TRUE) out++; A->length = out; return status; } flint-3.1.3/src/gr_mpoly/equal.c000066400000000000000000000022611461254215100165260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" /* todo: proper algorithm */ truth_t gr_mpoly_equal( const gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) { truth_t eq; gr_mpoly_t t; if (A == B) return T_TRUE; /* todo: if canonical representation */ /* if (A->length != B->length) return T_FALSE; ... _gr_vec_equal(A->coeffs, B->coeffs, A->length) ... return (0 == mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, A->length, ctx->minfo)) ? T_TRUE : T_FALSE; */ gr_mpoly_init(t, mctx, cctx); if (gr_mpoly_sub(t, A, B, mctx, cctx) == GR_SUCCESS) eq = gr_mpoly_is_zero(t, mctx, cctx); else eq = T_UNKNOWN; gr_mpoly_clear(t, mctx, cctx); return eq; } flint-3.1.3/src/gr_mpoly/fit_bits.c000066400000000000000000000016461461254215100172300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" void gr_mpoly_fit_bits(gr_mpoly_t A, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) { if (A->bits < bits) { if (A->exps_alloc != 0) { slong N = mpoly_words_per_exp(bits, mctx); ulong * t = (ulong *) flint_malloc(N*A->exps_alloc*sizeof(ulong)); mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, mctx); flint_free(A->exps); A->exps = t; A->exps_alloc = N*A->exps_alloc; } A->bits = bits; } } flint-3.1.3/src/gr_mpoly/fit_length.c000066400000000000000000000025741461254215100175510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" void _gr_mpoly_fit_length( gr_ptr * coeffs, slong * coeffs_alloc, ulong ** exps, slong * exps_alloc, slong N, slong length, gr_ctx_t cctx) { if (length > *coeffs_alloc) { slong old_alloc = *coeffs_alloc; slong new_alloc = FLINT_MAX(length, old_alloc*2); slong sz = cctx->sizeof_elem; *coeffs_alloc = new_alloc; *coeffs = (gr_ptr) flint_realloc(*coeffs, new_alloc*sz); _gr_vec_init(GR_ENTRY(*coeffs, old_alloc, sz), new_alloc - old_alloc, cctx); } if (N*length > *exps_alloc) { *exps_alloc = FLINT_MAX(N*length, *exps_alloc*2); *exps = (ulong *) flint_realloc(*exps, *exps_alloc*sizeof(ulong)); } } void gr_mpoly_fit_length( gr_mpoly_t A, slong len, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N = mpoly_words_per_exp(A->bits, mctx); _gr_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, len, cctx); } flint-3.1.3/src/gr_mpoly/fit_length_fit_bits.c000066400000000000000000000033241461254215100214260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" void gr_mpoly_fit_length_fit_bits( gr_mpoly_t A, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N = mpoly_words_per_exp(A->bits, mctx); if (len > A->coeffs_alloc) { slong old_alloc = A->coeffs_alloc; slong new_alloc = FLINT_MAX(len, 2*old_alloc); slong sz = cctx->sizeof_elem; A->coeffs_alloc = new_alloc; A->coeffs = (gr_ptr) flint_realloc(A->coeffs, new_alloc*sz); _gr_vec_init(GR_ENTRY(A->coeffs, old_alloc, sz), new_alloc - old_alloc, cctx); } if (bits > A->bits) { slong newN = mpoly_words_per_exp(bits, mctx); slong new_exps_alloc = newN*len; ulong * t; if (len < 1) { A->bits = bits; return; } t = (ulong *) flint_malloc(new_exps_alloc*sizeof(ulong)); if (A->length > 0) mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, mctx); if (A->exps_alloc > 0) flint_free(A->exps); A->exps = t; A->exps_alloc = new_exps_alloc; A->bits = bits; } else { if (N*len > A->exps_alloc) { A->exps_alloc = FLINT_MAX(N*len, 2*A->exps_alloc); A->exps = flint_realloc(A->exps, A->exps_alloc*sizeof(ulong)); } } } flint-3.1.3/src/gr_mpoly/fit_length_reset_bits.c000066400000000000000000000013431461254215100217650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" void gr_mpoly_fit_length_reset_bits( gr_mpoly_t A, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N = mpoly_words_per_exp(bits, mctx); _gr_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, len, cctx); A->bits = bits; } flint-3.1.3/src/gr_mpoly/gen.c000066400000000000000000000035241461254215100161730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" int gr_mpoly_gen( gr_mpoly_t A, slong var, const mpoly_ctx_t mctx, gr_ctx_t cctx) { flint_bitcnt_t bits; int status = GR_SUCCESS; if (var >= mctx->nvars || var < 0) return GR_DOMAIN; bits = mpoly_gen_bits_required(var, mctx); bits = mpoly_fix_bits(bits, mctx); gr_mpoly_fit_length_reset_bits(A, 1, bits, mctx, cctx); if (bits <= FLINT_BITS) mpoly_gen_monomial_sp(A->exps, var, bits, mctx); else mpoly_gen_monomial_offset_mp(A->exps, var, bits, mctx); status |= gr_one(A->coeffs, cctx); _gr_mpoly_set_length(A, gr_is_zero(A->coeffs, cctx) != T_TRUE, mctx, cctx); return status; } truth_t gr_mpoly_is_gen(const gr_mpoly_t A, slong var, const mpoly_ctx_t mctx, gr_ctx_t cctx) { truth_t res; if (var >= mctx->nvars || mctx->nvars == 0) return T_FALSE; /* Check for any generator */ if (var < 0) var = -1; if (A->length == 1) { res = mpoly_is_gen(A->exps, var, A->bits, mctx) ? T_TRUE : T_FALSE; if (res != T_TRUE) return res; res = gr_is_one(A->coeffs, cctx); } else { /* todo: cheaper check when possible */ gr_mpoly_t t; gr_mpoly_init(t, mctx, cctx); if (gr_mpoly_gen(t, var, mctx, cctx) != GR_SUCCESS) res = T_UNKNOWN; else res = gr_mpoly_equal(A, t, mctx, cctx); gr_mpoly_clear(t, mctx, cctx); } return res; } flint-3.1.3/src/gr_mpoly/get_coeff_scalar_fmpz.c000066400000000000000000000024601461254215100217220ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_mpoly.h" /* todo: should have an mpoly_monomial_index_pfmpz function */ int gr_mpoly_get_coeff_scalar_fmpz(gr_ptr c, const gr_mpoly_t A, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; slong index; fmpz ** exp_ptr; slong i; TMP_INIT; for (i = 0; i < mctx->nvars; i++) { if (fmpz_sgn(exp + i) < 0) return GR_DOMAIN; } TMP_START; exp_ptr = (fmpz **) TMP_ALLOC(sizeof(fmpz *) * mctx->nvars); for (i = 0; i < mctx->nvars; i++) exp_ptr[i] = (fmpz *) (exp + i); index = mpoly_monomial_index_pfmpz(A->exps, A->bits, A->length, exp_ptr, mctx); if (index < 0) { status = gr_zero(c, cctx); } else { FLINT_ASSERT(index < A->length); status = gr_set(c, GR_ENTRY(A->coeffs, index, cctx->sizeof_elem), cctx); } TMP_END; return status; } flint-3.1.3/src/gr_mpoly/get_coeff_scalar_ui.c000066400000000000000000000016341461254215100213650ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" /* todo: should have an mpoly_monomial_index_pfmpz function */ int gr_mpoly_get_coeff_scalar_ui(gr_ptr c, const gr_mpoly_t A, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong index; index = mpoly_monomial_index_ui(A->exps, A->bits, A->length, exp, mctx); if (index < 0) { return gr_zero(c, cctx); } else { FLINT_ASSERT(index < A->length); return gr_set(c, GR_ENTRY(A->coeffs, index, cctx->sizeof_elem), cctx); } } flint-3.1.3/src/gr_mpoly/init.c000066400000000000000000000023241461254215100163620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" void gr_mpoly_init3( gr_mpoly_t A, slong alloc, flint_bitcnt_t bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N = mpoly_words_per_exp(bits, mctx); if (alloc > 0) { A->coeffs_alloc = alloc; A->coeffs = (gr_ptr) flint_malloc(alloc * cctx->sizeof_elem); _gr_vec_init(A->coeffs, alloc, cctx); A->exps_alloc = N * alloc; A->exps = FLINT_ARRAY_ALLOC(A->exps_alloc, ulong); } else { A->coeffs = NULL; A->exps = NULL; A->coeffs_alloc = 0; A->exps_alloc = 0; } A->length = 0; A->bits = bits; } void gr_mpoly_init2( gr_mpoly_t A, slong alloc, const mpoly_ctx_t mctx, gr_ctx_t cctx) { flint_bitcnt_t bits = mpoly_fix_bits(MPOLY_MIN_BITS, mctx); gr_mpoly_init3(A, alloc, bits, mctx, cctx); } flint-3.1.3/src/gr_mpoly/inlines.c000066400000000000000000000007121461254215100170570ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define GR_MPOLY_INLINES_C #include "gr_mpoly.h" #undef GR_MPOLY_INLINES_C flint-3.1.3/src/gr_mpoly/is_canonical.c000066400000000000000000000042161461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" truth_t gr_mpoly_is_canonical(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N = mpoly_words_per_exp(A->bits, mctx); slong i; truth_t ok; if (A->length > A->coeffs_alloc) return T_FALSE; if (N * A->length > A->exps_alloc) return T_FALSE; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, mctx)) return T_FALSE; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, mctx)) return T_FALSE; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, mctx)) return T_FALSE; ok = T_TRUE; for (i = 0; i < A->length; i++) ok = truth_and(ok, truth_not(gr_is_zero(GR_ENTRY(A->coeffs, i, cctx->sizeof_elem), cctx))); return ok; } void gr_mpoly_assert_canonical(const gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N = mpoly_words_per_exp(A->bits, mctx); slong i; if (A->length > A->coeffs_alloc) flint_throw(FLINT_ERROR, "Polynomial coefficient allocation is bad"); if (N * A->length > A->exps_alloc) flint_throw(FLINT_ERROR, "Polynomial exponent allocation is bad"); if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, mctx)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, mctx)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, mctx)) flint_throw(FLINT_ERROR, "Polynomial exponents out of order"); for (i = 0; i < A->length; i++) { if (gr_is_zero(GR_ENTRY(A->coeffs, i, cctx->sizeof_elem), cctx) == T_TRUE) flint_throw(FLINT_ERROR, "Polynomial has a zero coefficient"); } } flint-3.1.3/src/gr_mpoly/mul.c000066400000000000000000000012101461254215100162050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" int gr_mpoly_mul(gr_mpoly_t poly1, const gr_mpoly_t poly2, const gr_mpoly_t poly3, const mpoly_ctx_t mctx, gr_ctx_t cctx) { return gr_mpoly_mul_johnson(poly1, poly2, poly3, mctx, cctx); } flint-3.1.3/src/gr_mpoly/mul_johnson.c000066400000000000000000000244751461254215100177650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "gr_mpoly.h" int _gr_mpoly_mul_johnson( slong * res_len, gr_ptr * coeff1, ulong ** exp1, slong * alloc, slong * exps_alloc, gr_srcptr coeff2, const ulong * exp2, slong len2, gr_srcptr coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, gr_ctx_t cctx) { gr_method_binary_op mul = GR_BINARY_OP(cctx, MUL); gr_method_binary_op add = GR_BINARY_OP(cctx, ADD); slong i, j; slong next_loc; slong Q_len = 0, heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * Q; mpoly_heap_t * x; slong len1; gr_ptr p1 = * coeff1; ulong * e1 = *exp1; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; gr_ptr pp; slong sz = cctx->sizeof_elem; int status = GR_SUCCESS; TMP_INIT; TMP_START; GR_TMP_INIT(pp, cctx); next_loc = len2 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len2 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len2*sizeof(mpoly_heap_t)); Q = (slong *) TMP_ALLOC(2*len2*sizeof(slong)); exps = (ulong *) TMP_ALLOC(len2*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len2*sizeof(ulong *)); for (i = 0; i < len2; i++) exp_list[i] = exps + i*N; hind = (slong *) TMP_ALLOC(len2*sizeof(slong)); for (i = 0; i < len2; i++) hind[i] = 1; /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; if (bits <= FLINT_BITS) mpoly_monomial_add(heap[1].exp, exp2, exp3, N); else mpoly_monomial_add_mp(heap[1].exp, exp2, exp3, N); hind[0] = 2*1 + 0; len1 = 0; while (heap_len > 1) { exp = heap[1].exp; _gr_mpoly_fit_length(&p1, alloc, &e1, exps_alloc, N, len1 + 1, cctx); mpoly_monomial_set(e1 + len1*N, exp, N); status |= gr_zero(GR_ENTRY(p1, len1, sz), cctx); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; /* todo: use addmul when better */ status |= mul(pp, GR_ENTRY(coeff2, x->i, sz), GR_ENTRY(coeff3, x->j, sz), cctx); status |= add(GR_ENTRY(p1, len1, sz), GR_ENTRY(p1, len1, sz), pp, cctx); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; /* todo: use addmul when better */ status |= mul(pp, GR_ENTRY(coeff2, x->i, sz), GR_ENTRY(coeff3, x->j, sz), cctx); status |= add(GR_ENTRY(p1, len1, sz), GR_ENTRY(p1, len1, sz), pp, cctx); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); len1 += (gr_is_zero(GR_ENTRY(p1, len1, sz), cctx) != T_TRUE); while (Q_len > 0) { /* take node from store */ j = Q[--Q_len]; i = Q[--Q_len]; /* should we go right? */ if ( (i + 1 < len2) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, cmpmask)) exp_next--; } /* should we go up? */ if ( (j + 1 < len3) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, cmpmask)) exp_next--; } } } (* coeff1) = p1; (* exp1) = e1; TMP_END; GR_TMP_CLEAR(pp, cctx); *res_len = len1; return status; } int gr_mpoly_mul_johnson( gr_mpoly_t poly1, const gr_mpoly_t poly2, const gr_mpoly_t poly3, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong i, N, len1 = 0; flint_bitcnt_t exp_bits; fmpz * max_fields2, * max_fields3; ulong * cmpmask; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; int free2 = 0, free3 = 0; int status = GR_SUCCESS; TMP_INIT; if (poly2->length == 0 || poly3->length == 0) { return gr_mpoly_zero(poly1, mctx, cctx); } if (poly3->length == 1) { return gr_mpoly_mul_monomial(poly1, poly2, poly3, mctx, cctx); } /* todo: could have a version of mul_monomial for the noncommutative case */ if (poly2->length == 1 && gr_ctx_is_commutative_ring(cctx) == T_TRUE) { return gr_mpoly_mul_monomial(poly1, poly3, poly2, mctx, cctx); } TMP_START; max_fields2 = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); max_fields3 = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) { fmpz_init(max_fields2 + i); fmpz_init(max_fields3 + i); } mpoly_max_fields_fmpz(max_fields2, poly2->exps, poly2->length, poly2->bits, mctx); mpoly_max_fields_fmpz(max_fields3, poly3->exps, poly3->length, poly3->bits, mctx); _fmpz_vec_add(max_fields2, max_fields2, max_fields3, mctx->nfields); exp_bits = _fmpz_vec_max_bits(max_fields2, mctx->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = FLINT_MAX(exp_bits, poly2->bits); exp_bits = FLINT_MAX(exp_bits, poly3->bits); exp_bits = mpoly_fix_bits(exp_bits, mctx); for (i = 0; i < mctx->nfields; i++) { fmpz_clear(max_fields2 + i); fmpz_clear(max_fields3 + i); } N = mpoly_words_per_exp(exp_bits, mctx); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, mctx); /* ensure input exponents are packed into same sized fields as output */ if (exp_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, exp_bits, poly2->exps, poly2->bits, poly2->length, mctx); } if (exp_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, exp_bits, poly3->exps, poly3->bits, poly3->length, mctx); } /* deal with aliasing and do multiplication */ if (poly1 == poly2 || poly1 == poly3) { gr_mpoly_t temp; gr_mpoly_init(temp, mctx, cctx); gr_mpoly_fit_length_reset_bits(temp, poly2->length + poly3->length, exp_bits, mctx, cctx); if (poly2->length >= poly3->length) { status = _gr_mpoly_mul_johnson(&len1, &temp->coeffs, &temp->exps, &temp->coeffs_alloc, &temp->exps_alloc, poly3->coeffs, exp3, poly3->length, poly2->coeffs, exp2, poly2->length, exp_bits, N, cmpmask, cctx); } else { status = _gr_mpoly_mul_johnson(&len1, &temp->coeffs, &temp->exps, &temp->coeffs_alloc, &temp->exps_alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask, cctx); } gr_mpoly_swap(temp, poly1, mctx, cctx); gr_mpoly_clear(temp, mctx, cctx); } else { gr_mpoly_fit_length_reset_bits(poly1, poly2->length + poly3->length, exp_bits, mctx, cctx); if (poly2->length > poly3->length) { status = _gr_mpoly_mul_johnson(&len1, &poly1->coeffs, &poly1->exps, &poly1->coeffs_alloc, &poly1->exps_alloc, poly3->coeffs, exp3, poly3->length, poly2->coeffs, exp2, poly2->length, exp_bits, N, cmpmask, cctx); } else { status = _gr_mpoly_mul_johnson(&len1, &poly1->coeffs, &poly1->exps, &poly1->coeffs_alloc, &poly1->exps_alloc, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, exp_bits, N, cmpmask, cctx); } } if (free2) flint_free(exp2); if (free3) flint_free(exp3); _gr_mpoly_set_length(poly1, len1, mctx, cctx); TMP_END; return status; } flint-3.1.3/src/gr_mpoly/mul_monomial.c000066400000000000000000000073621461254215100201160ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" int gr_mpoly_mul_monomial( gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong i, N, Alen, Blen = B->length; ulong ofmask; flint_bitcnt_t Abits; ulong * Aexps, * Bexps = B->exps, * Cexps = C->exps; gr_ptr Ccoeff0; int freeCcoeff0 = 0, overflowed = 0; int status = GR_SUCCESS; TMP_INIT; FLINT_ASSERT(C->length == 1); if (A == C) { GR_TMP_INIT(Ccoeff0, cctx); status |= gr_set(Ccoeff0, C->coeffs, cctx); freeCcoeff0 = 1; } else { Ccoeff0 = C->coeffs; } if (C->exps[0] == 0 && mpoly_monomial_is_zero(C->exps, mpoly_words_per_exp(C->bits, mctx))) { status |= gr_mpoly_mul_scalar(A, B, Ccoeff0, mctx, cctx); goto cleanup_C; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, mctx); if (A == C || Abits != C->bits) { Cexps = TMP_ARRAY_ALLOC(N, ulong); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, 1, mctx); } if (A == B) { /* inplace operation on A */ gr_mpoly_fit_bits(A, Abits, mctx, cctx); Bexps = Aexps = A->exps; } else { if (Abits != B->bits) { Bexps = TMP_ARRAY_ALLOC(N*Blen, ulong); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, Blen, mctx); } gr_mpoly_fit_length_reset_bits(A, Blen, Abits, mctx, cctx); Aexps = A->exps; } if (Abits > FLINT_BITS) { for (i = 0; i < Blen; i++) mpoly_monomial_add_mp(Aexps + N*i, Bexps + N*i, Cexps + N*0, N); for (i = 0; !overflowed && i < Blen; i++) overflowed = mpoly_monomial_overflows_mp(Aexps + N*i, N, Abits); } else { for (i = 0; i < Blen; i++) mpoly_monomial_add(Aexps + N*i, Bexps + N*i, Cexps + N*0, N); ofmask = mpoly_overflow_mask_sp(Abits); for (i = 0; !overflowed && i < Blen; i++) overflowed = mpoly_monomial_overflows(Aexps + N*i, N, ofmask); } TMP_END; /* slightly dirty: repack monomials can handle 1-bit overflown fields */ if (overflowed) { ulong * newAexps; flint_bitcnt_t newAbits = mpoly_fix_bits(Abits + 1, mctx); N = mpoly_words_per_exp(newAbits, mctx); newAexps = FLINT_ARRAY_ALLOC(N*A->coeffs_alloc, ulong); mpoly_repack_monomials(newAexps, newAbits, A->exps, Abits, Blen, mctx); flint_free(A->exps); A->exps = newAexps; A->bits = newAbits; A->exps_alloc = N*A->coeffs_alloc; } /* todo: when we can verify (quickly) that C is invertible */ #if 0 status |= _gr_vec_mul_scalar(A->coeffs, B->coeffs, Blen, Ccoeff0, cctx); _gr_mpoly_set_length(A, Blen, mctx, cctx); #else { slong sz = cctx->sizeof_elem; Alen = 0; for (i = 0; i < Blen; i++) { mpoly_monomial_set(A->exps + N*Alen, A->exps + N*i, N); status |= gr_mul(GR_ENTRY(A->coeffs, Alen, sz), GR_ENTRY(B->coeffs, i, sz), Ccoeff0, cctx); Alen += (gr_is_zero(GR_ENTRY(A->coeffs, Alen, sz), cctx) != T_TRUE); } A->length = Alen; } #endif cleanup_C: if (freeCcoeff0) GR_TMP_CLEAR(Ccoeff0, cctx); return status; } flint-3.1.3/src/gr_mpoly/mul_scalar.c000066400000000000000000000066371461254215100175540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "gr_mpoly.h" /* c is assumed to be reduced mod n */ int gr_mpoly_mul_scalar( gr_mpoly_t A, const gr_mpoly_t B, gr_srcptr c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong i, N; slong Alen; slong Blen = B->length; ulong * Aexp; const ulong * Bexp; fmpz * Acoeff; const fmpz * Bcoeff; int status = GR_SUCCESS; slong sz = cctx->sizeof_elem; if (Blen == 0 || gr_is_zero(c, cctx) == T_TRUE) { return gr_mpoly_zero(A, mctx, cctx); } /* todo if (gr_is_one(c) == T_TRUE || (Blen > 10 && gr_is_invertible(c, cctx) == T_TRUE)) { return gr_mpoly_scalar_mul_gr_invertible(A, B, c, ctx); } */ N = mpoly_words_per_exp(B->bits, mctx); gr_mpoly_fit_length_reset_bits(A, B->length, B->bits, mctx, cctx); Aexp = A->exps; Bexp = B->exps; Acoeff = A->coeffs; Bcoeff = B->coeffs; Alen = 0; for (i = 0; i < Blen; i++) { mpoly_monomial_set(Aexp + N*Alen, Bexp + N*i, N); status |= gr_mul(GR_ENTRY(Acoeff, Alen, sz), GR_ENTRY(Bcoeff, i, sz), c, cctx); Alen += (gr_is_zero(GR_ENTRY(Acoeff, Alen, sz), cctx) != T_TRUE); } A->length = Alen; return status; } int gr_mpoly_mul_si( gr_mpoly_t A, const gr_mpoly_t B, slong c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { if (c == 0 || B->length == 0) { return gr_mpoly_zero(A, mctx, cctx); } else { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_si(t, c, cctx); status |= gr_mpoly_mul_scalar(A, B, t, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } int gr_mpoly_mul_ui( gr_mpoly_t A, const gr_mpoly_t B, ulong c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { if (c == 0 || B->length == 0) { return gr_mpoly_zero(A, mctx, cctx); } else { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_ui(t, c, cctx); status |= gr_mpoly_mul_scalar(A, B, t, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } int gr_mpoly_mul_fmpz( gr_mpoly_t A, const gr_mpoly_t B, const fmpz_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { if (fmpz_is_zero(c) || B->length == 0) { return gr_mpoly_zero(A, mctx, cctx); } else { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_fmpz(t, c, cctx); status |= gr_mpoly_mul_scalar(A, B, t, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } int gr_mpoly_mul_fmpq( gr_mpoly_t A, const gr_mpoly_t B, const fmpq_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { if (fmpq_is_zero(c) || B->length == 0) { return gr_mpoly_zero(A, mctx, cctx); } else { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_fmpq(t, c, cctx); status |= gr_mpoly_mul_scalar(A, B, t, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } } flint-3.1.3/src/gr_mpoly/neg.c000066400000000000000000000016201461254215100161660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" int gr_mpoly_neg( gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N; slong Blen = B->length; int status = GR_SUCCESS; if (A != B) { N = mpoly_words_per_exp(B->bits, mctx); gr_mpoly_fit_length_reset_bits(A, Blen, B->bits, mctx, cctx); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } status = _gr_vec_neg(A->coeffs, B->coeffs, Blen, cctx); _gr_mpoly_set_length(A, Blen, mctx, cctx); return status; } flint-3.1.3/src/gr_mpoly/push_term.c000066400000000000000000000037041461254215100174300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" void _gr_mpoly_push_exp_ui( gr_mpoly_t A, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ui(exp, mctx); exp_bits = mpoly_fix_bits(exp_bits, mctx); gr_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, mctx, cctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, mctx); mpoly_set_monomial_ui(A->exps + N*old_length, exp, A->bits, mctx); } int gr_mpoly_push_term_scalar_ui( gr_mpoly_t A, gr_srcptr c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { _gr_mpoly_push_exp_ui(A, exp, mctx, cctx); return gr_set(GR_ENTRY(A->coeffs, A->length - 1, cctx->sizeof_elem), c, cctx); } void _gr_mpoly_push_exp_fmpz( gr_mpoly_t A, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ffmpz(exp, mctx); exp_bits = mpoly_fix_bits(exp_bits, mctx); gr_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, mctx, cctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, mctx); mpoly_set_monomial_ffmpz(A->exps + N*old_length, exp, A->bits, mctx); } int gr_mpoly_push_term_scalar_fmpz( gr_mpoly_t A, gr_srcptr c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { _gr_mpoly_push_exp_fmpz(A, exp, mctx, cctx); return gr_set(GR_ENTRY(A->coeffs, A->length - 1, cctx->sizeof_elem), c, cctx); } flint-3.1.3/src/gr_mpoly/randtest_bits.c000066400000000000000000000025421461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_mpoly.h" int gr_mpoly_randtest_bits(gr_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong i, j, nvars = mctx->nvars; fmpz * exp; int status = GR_SUCCESS; TMP_INIT; TMP_START; exp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exp + j); status = gr_mpoly_zero(A, mctx, cctx); gr_mpoly_fit_length_reset_bits(A, 0, MPOLY_MIN_BITS, mctx, cctx); for (i = 0; i < length; i++) { mpoly_monomial_randbits_fmpz(exp, state, exp_bits, mctx); _gr_mpoly_push_exp_fmpz(A, exp, mctx, cctx); status |= gr_randtest(GR_ENTRY(A->coeffs, A->length - 1, cctx->sizeof_elem), state, cctx); } gr_mpoly_sort_terms(A, mctx, cctx); status |= gr_mpoly_combine_like_terms(A, mctx, cctx); for (j = 0; j < nvars; j++) fmpz_clear(exp + j); TMP_END; return status; } flint-3.1.3/src/gr_mpoly/randtest_bound.c000066400000000000000000000023431461254215100204330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" int gr_mpoly_randtest_bound(gr_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong i, j, nvars = mctx->nvars; ulong * exp; int status = GR_SUCCESS; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); status = gr_mpoly_zero(A, mctx, cctx); gr_mpoly_fit_length_reset_bits(A, 0, MPOLY_MIN_BITS, mctx, cctx); for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bound); _gr_mpoly_push_exp_ui(A, exp, mctx, cctx); status |= gr_randtest(GR_ENTRY(A->coeffs, A->length - 1, cctx->sizeof_elem), state, cctx); } gr_mpoly_sort_terms(A, mctx, cctx); status |= gr_mpoly_combine_like_terms(A, mctx, cctx); TMP_END; return status; } flint-3.1.3/src/gr_mpoly/set.c000066400000000000000000000016151461254215100162140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" int gr_mpoly_set( gr_mpoly_t A, const gr_mpoly_t B, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong N; int status = GR_SUCCESS; if (A == B) return GR_SUCCESS; N = mpoly_words_per_exp(B->bits, mctx); gr_mpoly_fit_length_reset_bits(A, B->length, B->bits, mctx, cctx); status = _gr_vec_set(A->coeffs, B->coeffs, B->length, cctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); _gr_mpoly_set_length(A, B->length, mctx, cctx); return status; } flint-3.1.3/src/gr_mpoly/set_coeff_scalar_fmpz.c000066400000000000000000000100051461254215100217300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_mpoly.h" int gr_mpoly_set_coeff_scalar_fmpz( gr_mpoly_t A, gr_srcptr c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { flint_bitcnt_t exp_bits; slong i, N, index; ulong * cmpmask; ulong * packed_exp; int exists; int status = GR_SUCCESS; slong sz = cctx->sizeof_elem; TMP_INIT; for (i = 0; i < mctx->nvars; i++) { if (fmpz_sgn(exp + i) < 0) return GR_DOMAIN; } TMP_START; exp_bits = mpoly_exp_bits_required_ffmpz(exp, mctx); exp_bits = mpoly_fix_bits(exp_bits, mctx); gr_mpoly_fit_length_fit_bits(A, A->length, exp_bits, mctx, cctx); N = mpoly_words_per_exp(A->bits, mctx); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, A->bits, mctx); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, A->bits, mctx); exists = mpoly_monomial_exists(&index, A->exps, packed_exp, A->length, N, cmpmask); if (!exists) { if (gr_is_zero(c, cctx) != T_TRUE) /* make new term only if coeff is nonzero*/ { gr_mpoly_fit_length(A, A->length + 1, mctx, cctx); for (i = A->length; i >= index + 1; i--) { gr_swap(GR_ENTRY(A->coeffs, i, sz), GR_ENTRY(A->coeffs, i - 1, sz), cctx); mpoly_monomial_set(A->exps + N*i, A->exps + N*(i - 1), N); } status |= gr_set(GR_ENTRY(A->coeffs, index, sz), c, cctx); mpoly_monomial_set(A->exps + N*index, packed_exp, N); A->length++; } } else if (gr_is_zero(c, cctx) == T_TRUE) /* zero coeff, remove term */ { /* todo: zero out removed coefficient for deallocation? */ for (i = index; i < A->length - 1; i++) { gr_swap(GR_ENTRY(A->coeffs, i, sz), GR_ENTRY(A->coeffs, i + 1, sz), cctx); mpoly_monomial_set(A->exps + N*i, A->exps + N*(i + 1), N); } A->length--; } else /* term with that monomial exists, coeff is nonzero */ { status |= gr_set(GR_ENTRY(A->coeffs, index, sz), c, cctx); } TMP_END; return status; } int gr_mpoly_set_coeff_ui_fmpz( gr_mpoly_t A, ulong c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_ui(t, c, cctx); status |= gr_mpoly_set_coeff_scalar_fmpz(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } int gr_mpoly_set_coeff_si_fmpz( gr_mpoly_t A, slong c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_si(t, c, cctx); status |= gr_mpoly_set_coeff_scalar_fmpz(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } int gr_mpoly_set_coeff_fmpz_fmpz( gr_mpoly_t A, const fmpz_t c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_fmpz(t, c, cctx); status |= gr_mpoly_set_coeff_scalar_fmpz(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } int gr_mpoly_set_coeff_fmpq_fmpz( gr_mpoly_t A, const fmpq_t c, const fmpz * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_fmpq(t, c, cctx); if (status == GR_SUCCESS) status |= gr_mpoly_set_coeff_scalar_fmpz(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } flint-3.1.3/src/gr_mpoly/set_coeff_scalar_ui.c000066400000000000000000000045071461254215100214030ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_mpoly.h" int gr_mpoly_set_coeff_scalar_ui(gr_mpoly_t poly, gr_srcptr c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong i, nvars = mctx->nvars; fmpz * newexp; int status; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); status = gr_mpoly_set_coeff_scalar_fmpz(poly, c, newexp, mctx, cctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; return status; } int gr_mpoly_set_coeff_ui_ui( gr_mpoly_t A, ulong c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_ui(t, c, cctx); status |= gr_mpoly_set_coeff_scalar_ui(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } int gr_mpoly_set_coeff_si_ui( gr_mpoly_t A, slong c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_si(t, c, cctx); status |= gr_mpoly_set_coeff_scalar_ui(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } int gr_mpoly_set_coeff_fmpz_ui( gr_mpoly_t A, const fmpz_t c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_fmpz(t, c, cctx); status |= gr_mpoly_set_coeff_scalar_ui(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } int gr_mpoly_set_coeff_fmpq_ui( gr_mpoly_t A, const fmpq_t c, const ulong * exp, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; gr_ptr t; GR_TMP_INIT(t, cctx); status = gr_set_fmpq(t, c, cctx); if (status == GR_SUCCESS) status |= gr_mpoly_set_coeff_scalar_ui(A, t, exp, mctx, cctx); GR_TMP_CLEAR(t, cctx); return status; } flint-3.1.3/src/gr_mpoly/set_scalar.c000066400000000000000000000055301461254215100175410ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "gr_mpoly.h" int gr_mpoly_set_scalar(gr_mpoly_t A, gr_srcptr c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; if (gr_is_zero(c, cctx) == T_TRUE) return gr_mpoly_zero(A, mctx, cctx); gr_mpoly_fit_length(A, 1, mctx, cctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, mctx)); status = gr_set(A->coeffs, c, cctx); _gr_mpoly_set_length(A, 1, mctx, cctx); return status; } int gr_mpoly_set_ui(gr_mpoly_t A, ulong c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; if (c == 0) return gr_mpoly_zero(A, mctx, cctx); gr_mpoly_fit_length(A, 1, mctx, cctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, mctx)); status = gr_set_ui(A->coeffs, c, cctx); if (gr_is_zero(A->coeffs, cctx) == T_TRUE) _gr_mpoly_set_length(A, 0, mctx, cctx); else _gr_mpoly_set_length(A, 1, mctx, cctx); return status; } int gr_mpoly_set_si(gr_mpoly_t A, slong c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; if (c == 0) return gr_mpoly_zero(A, mctx, cctx); gr_mpoly_fit_length(A, 1, mctx, cctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, mctx)); status = gr_set_si(A->coeffs, c, cctx); if (gr_is_zero(A->coeffs, cctx) == T_TRUE) _gr_mpoly_set_length(A, 0, mctx, cctx); else _gr_mpoly_set_length(A, 1, mctx, cctx); return status; } int gr_mpoly_set_fmpz(gr_mpoly_t A, const fmpz_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; if (fmpz_is_zero(c)) return gr_mpoly_zero(A, mctx, cctx); gr_mpoly_fit_length(A, 1, mctx, cctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, mctx)); status = gr_set_fmpz(A->coeffs, c, cctx); if (gr_is_zero(A->coeffs, cctx) == T_TRUE) _gr_mpoly_set_length(A, 0, mctx, cctx); else _gr_mpoly_set_length(A, 1, mctx, cctx); return status; } int gr_mpoly_set_fmpq(gr_mpoly_t A, const fmpq_t c, const mpoly_ctx_t mctx, gr_ctx_t cctx) { int status; if (fmpq_is_zero(c)) return gr_mpoly_zero(A, mctx, cctx); gr_mpoly_fit_length(A, 1, mctx, cctx); mpoly_monomial_zero(A->exps, mpoly_words_per_exp(A->bits, mctx)); status = gr_set_fmpq(A->coeffs, c, cctx); if (gr_is_zero(A->coeffs, cctx) == T_TRUE) _gr_mpoly_set_length(A, 0, mctx, cctx); else _gr_mpoly_set_length(A, 1, mctx, cctx); return status; } flint-3.1.3/src/gr_mpoly/sort_terms.c000066400000000000000000000140371461254215100176240ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" /* sort terms in [left, right) by exponent assuming that bits in position >= pos are already sorted and assuming exponent vectors fit into one word and assuming that all bit positions that need to be sorted are in totalmask */ void _gr_mpoly_radix_sort1( gr_ptr Acoeffs, ulong * Aexps, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask, gr_ctx_t cctx) { ulong mask, cmp; slong mid, cur; slong sz = cctx->sizeof_elem; gr_method_swap_op swap = GR_SWAP_OP(cctx, SWAP); while (pos > 0) { pos--; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < FLINT_BITS); mask = UWORD(1) << pos; cmp = cmpmask & mask; /* insertion base case */ if (right - left < 10) { slong i, j; for (i = left + 1; i < right; i++) { for (j = i; j > left && mpoly_monomial_gt1(Aexps[j], Aexps[j - 1], cmpmask); j--) { swap(GR_ENTRY(Acoeffs, j, sz), GR_ENTRY(Acoeffs, j - 1, sz), cctx); FLINT_SWAP(ulong, Aexps[j], Aexps[j - 1]); } } return; } /* return if there is no information to sort on this bit */ if ((totalmask & mask) == 0) continue; /* find first 'zero' */ mid = left; while (mid < right && (Aexps[mid] & mask) != cmp) mid++; /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ cur = mid; while (++cur < right) { if ((Aexps[cur] & mask) != cmp) { swap(GR_ENTRY(Acoeffs, cur, sz), GR_ENTRY(Acoeffs, mid, sz), cctx); FLINT_SWAP(ulong, Aexps[cur], Aexps[mid]); mid++; } } if (mid - left < right - mid) { _gr_mpoly_radix_sort1(Acoeffs, Aexps, left, mid, pos, cmpmask, totalmask, cctx); left = mid; } else { _gr_mpoly_radix_sort1(Acoeffs, Aexps, mid, right, pos, cmpmask, totalmask, cctx); right = mid; } } } /* sort terms in [left, right) by exponent assuming that bits in position >= pos are already sorted */ void _gr_mpoly_radix_sort( gr_ptr Acoeffs, ulong * Aexps, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask, gr_ctx_t cctx) { ulong off, bit, mask, cmp; slong mid, check; slong sz = cctx->sizeof_elem; gr_method_swap_op swap = GR_SWAP_OP(cctx, SWAP); while (pos > 0) { pos--; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < N*FLINT_BITS); off = pos/FLINT_BITS; bit = pos%FLINT_BITS; mask = UWORD(1) << bit; cmp = cmpmask[off] & mask; /* insertion base case */ if (right - left < 20) { slong i, j; for (i = left + 1; i < right; i++) { for (j = i; j > left && mpoly_monomial_gt(Aexps + N*j, Aexps + N*(j - 1), N, cmpmask); j--) { swap(GR_ENTRY(Acoeffs, j, sz), GR_ENTRY(Acoeffs, j - 1, sz), cctx); mpoly_monomial_swap(Aexps + N*j, Aexps + N*(j - 1), N); } } return; } /* find first 'zero' */ mid = left; while (mid < right && ((Aexps+N*mid)[off] & mask) != cmp) mid++; /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ check = mid; while (++check < right) { if (((Aexps + N*check)[off] & mask) != cmp) { swap(GR_ENTRY(Acoeffs, check, sz), GR_ENTRY(Acoeffs, mid, sz), cctx); mpoly_monomial_swap(Aexps + N*check, Aexps + N*mid, N); mid++; } } FLINT_ASSERT(left <= mid && mid <= right); if (mid - left < right - mid) { _gr_mpoly_radix_sort(Acoeffs, Aexps, left, mid, pos, N, cmpmask, cctx); left = mid; } else { _gr_mpoly_radix_sort(Acoeffs, Aexps, mid, right, pos, N, cmpmask, cctx); right = mid; } } } /* sort the terms in A by exponent assuming that the exponents are valid (other than being in order) */ void gr_mpoly_sort_terms(gr_mpoly_t A, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong i, N; flint_bitcnt_t pos; gr_ptr Acoeffs = A->coeffs; ulong * Aexps = A->exps; ulong himask, * ptempexp; TMP_INIT; TMP_START; N = mpoly_words_per_exp(A->bits, mctx); ptempexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(ptempexp, N, A->bits, mctx); himask = 0; for (i = 0; i < A->length; i++) himask |= (Aexps + N*i)[N - 1]; pos = FLINT_BIT_COUNT(himask); if (N == 1) _gr_mpoly_radix_sort1(Acoeffs, Aexps, 0, A->length, pos, ptempexp[0], himask, cctx); else _gr_mpoly_radix_sort(Acoeffs, Aexps, 0, A->length, (N - 1)*FLINT_BITS + pos, N, ptempexp, cctx); TMP_END; } flint-3.1.3/src/gr_mpoly/sub.c000066400000000000000000000104421461254215100162100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_mpoly.h" slong _gr_mpoly_sub( slong * Alen, gr_ptr Acoeffs, ulong * Aexps, gr_srcptr Bcoeffs, const ulong * Bexps, slong Blen, gr_srcptr Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, gr_ctx_t fctx) { gr_method_binary_op sub = GR_BINARY_OP(fctx, SUB); gr_method_unary_op set = GR_UNARY_OP(fctx, SET); gr_method_unary_op neg = GR_UNARY_OP(fctx, NEG); slong sz = fctx->sizeof_elem; slong i = 0, j = 0, k = 0; int status = GR_SUCCESS; while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); status |= set(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Bcoeffs, i, sz), fctx); i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); status |= sub(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Bcoeffs, i, sz), GR_ENTRY(Ccoeffs, j, sz), fctx); k += (gr_is_zero(GR_ENTRY(Acoeffs, k, sz), fctx) != T_TRUE); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); status |= neg(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Ccoeffs, j, sz), fctx); j++; k++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); status |= set(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Bcoeffs, i, sz), fctx); i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); status |= neg(GR_ENTRY(Acoeffs, k, sz), GR_ENTRY(Ccoeffs, j, sz), fctx); j++; k++; } *Alen = k; return status; } int gr_mpoly_sub( gr_mpoly_t A, const gr_mpoly_t B, const gr_mpoly_t C, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong Abits, N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; int status = GR_SUCCESS; TMP_INIT; if (B->length == 0) return gr_mpoly_neg(A, C, mctx, cctx); if (C->length == 0) return gr_mpoly_set(A, B, mctx, cctx); TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, mctx); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, mctx); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, mctx); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, mctx); } if (A == B || A == C) { gr_mpoly_t T; gr_mpoly_init3(T, B->length + C->length, Abits, mctx, cctx); status = _gr_mpoly_sub(&T->length, T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, cctx); gr_mpoly_swap(A, T, mctx, cctx); gr_mpoly_clear(T, mctx, cctx); } else { gr_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, mctx, cctx); status = _gr_mpoly_sub(&A->length, A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, cctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; return status; } flint-3.1.3/src/gr_mpoly/test/000077500000000000000000000000001461254215100162315ustar00rootroot00000000000000flint-3.1.3/src/gr_mpoly/test/main.c000066400000000000000000000020071461254215100173200ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-gen.c" #include "t-get_set_coeff.c" #include "t-mul_johnson.c" #include "t-mul_monomial.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(gr_mpoly_add_sub), TEST_FUNCTION(gr_mpoly_gen), TEST_FUNCTION(gr_mpoly_get_set_coeff), TEST_FUNCTION(gr_mpoly_mul_johnson), TEST_FUNCTION(gr_mpoly_mul_monomial) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/gr_mpoly/test/t-add_sub.c000066400000000000000000000360531461254215100202460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mpoly.h" TEST_FUNCTION_START(gr_mpoly_add_sub, state) { slong i, j; /* Check (f + g) - g = f */ for (i = 0; i < 100; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 20); gr_mpoly_init(f, mctx, cctx); gr_mpoly_init(g, mctx, cctx); gr_mpoly_init(h, mctx, cctx); gr_mpoly_init(k, mctx, cctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { status = GR_SUCCESS; status |= gr_mpoly_randtest_bits(f, state, len1, exp_bits1, mctx, cctx); status |= gr_mpoly_randtest_bits(g, state, len2, exp_bits2, mctx, cctx); status |= gr_mpoly_randtest_bits(h, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_add(h, g, f, mctx, cctx); status |= gr_mpoly_sub(k, h, g, mctx, cctx); if (status == GR_SUCCESS) { gr_mpoly_assert_canonical(h, mctx, cctx); gr_mpoly_assert_canonical(k, mctx, cctx); } if (status == GR_SUCCESS && gr_mpoly_equal(f, k, mctx, cctx) == T_FALSE) { flint_printf("FAIL: Check (f + g) - g = f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g = "); gr_mpoly_print_pretty(g, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f + g = "); gr_mpoly_print_pretty(h, NULL, mctx, cctx); flint_printf("\n"); flint_printf("(f + g) - g = "); gr_mpoly_print_pretty(k, NULL, mctx, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, mctx, cctx); gr_mpoly_clear(g, mctx, cctx); gr_mpoly_clear(h, mctx, cctx); gr_mpoly_clear(k, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } /* Check f + g = g + f */ for (i = 0; i < 10; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 20); gr_mpoly_init(f, mctx, cctx); gr_mpoly_init(g, mctx, cctx); gr_mpoly_init(h, mctx, cctx); gr_mpoly_init(k, mctx, cctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { status = GR_SUCCESS; status |= gr_mpoly_randtest_bits(f, state, len1, exp_bits1, mctx, cctx); status |= gr_mpoly_randtest_bits(g, state, len2, exp_bits2, mctx, cctx); status |= gr_mpoly_randtest_bits(h, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_add(h, f, g, mctx, cctx); status |= gr_mpoly_add(k, g, f, mctx, cctx); if (status == GR_SUCCESS && gr_mpoly_equal(h, k, mctx, cctx) == T_FALSE) { flint_printf("FAIL: Check (f + g) = (g + f)\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g = "); gr_mpoly_print_pretty(g, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f + g = "); gr_mpoly_print_pretty(h, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g + f = "); gr_mpoly_print_pretty(k, NULL, mctx, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, mctx, cctx); gr_mpoly_clear(g, mctx, cctx); gr_mpoly_clear(h, mctx, cctx); gr_mpoly_clear(k, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } /* Check f - g = -g + f */ for (i = 0; i < 10; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 20); gr_mpoly_init(f, mctx, cctx); gr_mpoly_init(g, mctx, cctx); gr_mpoly_init(h, mctx, cctx); gr_mpoly_init(k, mctx, cctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { status = GR_SUCCESS; status |= gr_mpoly_randtest_bits(f, state, len1, exp_bits1, mctx, cctx); status |= gr_mpoly_randtest_bits(g, state, len2, exp_bits2, mctx, cctx); status |= gr_mpoly_randtest_bits(h, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_sub(h, f, g, mctx, cctx); status |= gr_mpoly_neg(k, g, mctx, cctx); status |= gr_mpoly_add(k, k, f, mctx, cctx); if (status == GR_SUCCESS && gr_mpoly_equal(h, k, mctx, cctx) == T_FALSE) { flint_printf("FAIL: Check f - g = -g + f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g = "); gr_mpoly_print_pretty(g, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f - g = "); gr_mpoly_print_pretty(h, NULL, mctx, cctx); flint_printf("\n"); flint_printf("-g + f = "); gr_mpoly_print_pretty(k, NULL, mctx, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, mctx, cctx); gr_mpoly_clear(g, mctx, cctx); gr_mpoly_clear(h, mctx, cctx); gr_mpoly_clear(k, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } /* Check f + (g + h) = (f + g) + h */ for (i = 0; i < 10; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 20); gr_mpoly_init(f, mctx, cctx); gr_mpoly_init(g, mctx, cctx); gr_mpoly_init(h, mctx, cctx); gr_mpoly_init(k1, mctx, cctx); gr_mpoly_init(k2, mctx, cctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { status = GR_SUCCESS; status |= gr_mpoly_randtest_bits(f, state, len1, exp_bits1, mctx, cctx); status |= gr_mpoly_randtest_bits(g, state, len2, exp_bits2, mctx, cctx); status |= gr_mpoly_randtest_bits(h, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k1, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k2, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_add(k1, g, h, mctx, cctx); status |= gr_mpoly_add(k1, f, k1, mctx, cctx); status |= gr_mpoly_add(k2, f, g, mctx, cctx); status |= gr_mpoly_add(k2, k2, h, mctx, cctx); if (status == GR_SUCCESS && gr_mpoly_equal(k1, k2, mctx, cctx) == T_FALSE) { flint_printf("FAIL Check f + (g + h) = (f + g) + h\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g = "); gr_mpoly_print_pretty(g, NULL, mctx, cctx); flint_printf("\n"); flint_printf("h = "); gr_mpoly_print_pretty(h, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f + (g + h) = "); gr_mpoly_print_pretty(k1, NULL, mctx, cctx); flint_printf("\n"); flint_printf("(f + g) + h = "); gr_mpoly_print_pretty(k2, NULL, mctx, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, mctx, cctx); gr_mpoly_clear(g, mctx, cctx); gr_mpoly_clear(h, mctx, cctx); gr_mpoly_clear(k1, mctx, cctx); gr_mpoly_clear(k2, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } /* Check f - (g + h) = (f - g) - h */ for (i = 0; i < 100; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h, k1, k2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 20); gr_mpoly_init(f, mctx, cctx); gr_mpoly_init(g, mctx, cctx); gr_mpoly_init(h, mctx, cctx); gr_mpoly_init(k1, mctx, cctx); gr_mpoly_init(k2, mctx, cctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { status = GR_SUCCESS; status |= gr_mpoly_randtest_bits(f, state, len1, exp_bits1, mctx, cctx); status |= gr_mpoly_randtest_bits(g, state, len2, exp_bits2, mctx, cctx); status |= gr_mpoly_randtest_bits(h, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k1, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k2, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_add(k1, g, h, mctx, cctx); status |= gr_mpoly_sub(k1, f, k1, mctx, cctx); status |= gr_mpoly_sub(k2, f, g, mctx, cctx); status |= gr_mpoly_sub(k2, k2, h, mctx, cctx); if (status == GR_SUCCESS && gr_mpoly_equal(k1, k2, mctx, cctx) == T_FALSE) { flint_printf("FAIL Check f + (g + h) = (f + g) + h\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g = "); gr_mpoly_print_pretty(g, NULL, mctx, cctx); flint_printf("\n"); flint_printf("h = "); gr_mpoly_print_pretty(h, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f + (g + h) = "); gr_mpoly_print_pretty(k1, NULL, mctx, cctx); flint_printf("\n"); flint_printf("(f + g) + h = "); gr_mpoly_print_pretty(k2, NULL, mctx, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, mctx, cctx); gr_mpoly_clear(g, mctx, cctx); gr_mpoly_clear(h, mctx, cctx); gr_mpoly_clear(k1, mctx, cctx); gr_mpoly_clear(k2, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } #if 0 /* Check aliasing */ for (i = 0; i < 100; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; gr_mpoly_ctx_init_rand_bits(ctx, state, 20, 200); gr_mpoly_init(f, ctx); gr_mpoly_init(g, ctx); gr_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { gr_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); gr_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); gr_mpoly_randtest_bits(h, state, len, exp_bits, ctx); gr_mpoly_set(h, f, ctx); gr_mpoly_add(f, f, g, ctx); gr_mpoly_assert_canonical(f, ctx); gr_mpoly_sub(f, f, g, ctx); gr_mpoly_assert_canonical(f, ctx); if (!gr_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check aliasing first arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } gr_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); gr_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); gr_mpoly_randtest_bits(h, state, len, exp_bits, ctx); if ((j % 2) == 0) { gr_mpoly_add(h, g, f, ctx); gr_mpoly_assert_canonical(h, ctx); gr_mpoly_add(f, g, f, ctx); gr_mpoly_assert_canonical(f, ctx); } else { gr_mpoly_sub(h, g, f, ctx); gr_mpoly_assert_canonical(h, ctx); gr_mpoly_sub(f, g, f, ctx); gr_mpoly_assert_canonical(f, ctx); } if (!gr_mpoly_equal(f, h, ctx)) { flint_printf("FAIL: Check aliasing second arg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, ctx); gr_mpoly_clear(g, ctx); gr_mpoly_clear(h, ctx); gr_mpoly_ctx_clear(ctx); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mpoly/test/t-gen.c000066400000000000000000000074501461254215100174150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mpoly.h" TEST_FUNCTION_START(gr_mpoly_gen, state) { slong iter; for (iter = 0; iter < 100; iter++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f1, f2; slong len, k1, k2; flint_bitcnt_t exp_bits; int status; truth_t eq1, eq2, eq3, eq4; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 10); gr_mpoly_init(f1, mctx, cctx); gr_mpoly_init(f2, mctx, cctx); len = n_randint(state, 10); exp_bits = n_randint(state, 100) + 2; status = gr_mpoly_zero(f1, mctx, cctx); status = gr_mpoly_one(f2, mctx, cctx); if (gr_mpoly_equal(f1, f2, mctx, cctx) != T_TRUE) { gr_mpoly_randtest_bits(f1, state, len, exp_bits, mctx, cctx); gr_mpoly_randtest_bits(f2, state, len, exp_bits, mctx, cctx); k1 = n_randint(state, FLINT_MAX(1, mctx->nvars)); k2 = n_randint(state, FLINT_MAX(1, mctx->nvars)); status = GR_SUCCESS; status |= gr_mpoly_gen(f1, k1, mctx, cctx); gr_mpoly_assert_canonical(f1, mctx, cctx); status |= gr_mpoly_gen(f2, k2, mctx, cctx); gr_mpoly_assert_canonical(f2, mctx, cctx); eq1 = gr_mpoly_is_gen(f1, k1, mctx, cctx); eq2 = gr_mpoly_is_gen(f1, -1, mctx, cctx); eq3 = gr_mpoly_is_gen(f2, k2, mctx, cctx); eq4 = gr_mpoly_is_gen(f2, -1, mctx, cctx); if (status == GR_SUCCESS && (eq1 == T_FALSE || eq2 == T_FALSE || eq3 == T_FALSE || eq4 == T_FALSE)) { flint_printf("FAIL\n"); gr_ctx_println(cctx); flint_printf("nvars = %wd\n", mctx->nvars); flint_printf("f1 = "); gr_mpoly_print_pretty(f1, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f2 = "); gr_mpoly_print_pretty(f2, NULL, mctx, cctx); flint_printf("\n"); flint_printf("k1 = %wd\n", k1); flint_printf("k2 = %wd\n", k2); flint_printf("eq = %d %d %d %d\n", eq1, eq2, eq3, eq4); fflush(stdout); flint_abort(); } if (n_randint(state, 2)) status |= gr_mpoly_add(f1, f1, f2, mctx, cctx); else status |= gr_mpoly_mul(f1, f1, f2, mctx, cctx); eq1 = gr_mpoly_is_gen(f1, k1, mctx, cctx); eq2 = gr_mpoly_is_gen(f1, k2, mctx, cctx); eq3 = gr_mpoly_is_gen(f1, -1, mctx, cctx); if (status == GR_SUCCESS && (eq1 == T_TRUE || eq2 == T_TRUE || eq3 == T_TRUE)) { flint_printf("FAIL\n"); gr_ctx_println(cctx); flint_printf("nvars = %wd\n", mctx->nvars); flint_printf("f1 = "); gr_mpoly_print_pretty(f1, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f2 = "); gr_mpoly_print_pretty(f2, NULL, mctx, cctx); flint_printf("\n"); flint_printf("k1 = %wd\n", k1); flint_printf("k2 = %wd\n", k2); flint_printf("eq = %d %d %d\n", eq1, eq2, eq3); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f1, mctx, cctx); gr_mpoly_clear(f2, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mpoly/test/t-get_set_coeff.c000066400000000000000000000102471461254215100214360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "gr_mpoly.h" TEST_FUNCTION_START(gr_mpoly_get_set_coeff, state) { slong i, j; for (i = 0; i < 100; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f; gr_ptr c, d; slong len, k; flint_bitcnt_t exp_bits; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 20); gr_mpoly_init(f, mctx, cctx); c = gr_heap_init(cctx); d = gr_heap_init(cctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; GR_MUST_SUCCEED(gr_mpoly_randtest_bits(f, state, len, exp_bits, mctx, cctx)); for (j = 0; j < 10; j++) { ulong * exp = FLINT_ARRAY_ALLOC(mctx->nvars, ulong); status = GR_SUCCESS; GR_MUST_SUCCEED(gr_randtest(c, state, cctx)); for (k = 0; k < mctx->nvars; k++) exp[k] = n_randtest(state); status |= gr_mpoly_set_coeff_scalar_ui(f, c, exp, mctx, cctx); gr_mpoly_assert_canonical(f, mctx, cctx); status |= gr_mpoly_get_coeff_scalar_ui(d, f, exp, mctx, cctx); if (status == GR_SUCCESS && gr_equal(c, d, cctx) == T_FALSE) { flint_printf("FAIL: scalar_ui\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("c = "); gr_print(c, cctx); flint_printf("\n"); flint_printf("d = "); gr_print(d, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(exp); } gr_mpoly_clear(f, mctx, cctx); gr_heap_clear(c, cctx); gr_heap_clear(d, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } for (i = 0; i < 100; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f; gr_ptr c, d; slong len; flint_bitcnt_t exp_bits; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 20); gr_mpoly_init(f, mctx, cctx); c = gr_heap_init(cctx); d = gr_heap_init(cctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; GR_MUST_SUCCEED(gr_mpoly_randtest_bits(f, state, len, exp_bits, mctx, cctx)); for (j = 0; j < 10; j++) { fmpz * exp = _fmpz_vec_init(mctx->nvars); status = GR_SUCCESS; GR_MUST_SUCCEED(gr_randtest(c, state, cctx)); _fmpz_vec_randtest(exp, state, mctx->nvars, exp_bits); status |= gr_mpoly_set_coeff_scalar_fmpz(f, c, exp, mctx, cctx); gr_mpoly_assert_canonical(f, mctx, cctx); status |= gr_mpoly_get_coeff_scalar_fmpz(d, f, exp, mctx, cctx); if (status == GR_SUCCESS && gr_equal(c, d, cctx) == T_FALSE) { flint_printf("FAIL: scalar_fmpz\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("c = "); gr_print(c, cctx); flint_printf("\n"); flint_printf("d = "); gr_print(d, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } _fmpz_vec_clear(exp, mctx->nvars); } gr_mpoly_clear(f, mctx, cctx); gr_heap_clear(c, cctx); gr_heap_clear(d, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mpoly/test/t-mul_johnson.c000066400000000000000000000100261461254215100211700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mpoly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_mpoly_mul_johnson, state) { slong i, j; /* Check f*(g + h) = f*g + f*h */ for (i = 0; i < 100; i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h, k1, k2, t; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 4); gr_mpoly_init(f, mctx, cctx); gr_mpoly_init(g, mctx, cctx); gr_mpoly_init(h, mctx, cctx); gr_mpoly_init(k1, mctx, cctx); gr_mpoly_init(k2, mctx, cctx); gr_mpoly_init(t, mctx, cctx); if (cctx->methods == _ca_methods) { len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10); } else { len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); } exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; /* todo: assert_canonical */ for (j = 0; j < 10; j++) { status = GR_SUCCESS; status |= gr_mpoly_randtest_bits(f, state, len1, exp_bits1, mctx, cctx); status |= gr_mpoly_randtest_bits(g, state, len2, exp_bits2, mctx, cctx); status |= gr_mpoly_randtest_bits(h, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k1, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k2, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_add(k1, g, h, mctx, cctx); if (n_randint(state, 2)) status |= gr_mpoly_mul_johnson(k1, f, k1, mctx, cctx); else status |= gr_mpoly_mul_johnson(k1, k1, f, mctx, cctx); if (status == GR_SUCCESS) gr_mpoly_assert_canonical(k1, mctx, cctx); status |= gr_mpoly_mul_johnson(k2, f, g, mctx, cctx); if (status == GR_SUCCESS) gr_mpoly_assert_canonical(k2, mctx, cctx); status |= gr_mpoly_mul_johnson(t, f, h, mctx, cctx); if (status == GR_SUCCESS) gr_mpoly_assert_canonical(t, mctx, cctx); status |= gr_mpoly_add(k2, k2, t, mctx, cctx); if (status == GR_SUCCESS && gr_mpoly_equal(k1, k2, mctx, cctx) == T_FALSE) { flint_printf("FAIL: Check (f + g) - g = f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g = "); gr_mpoly_print_pretty(g, NULL, mctx, cctx); flint_printf("\n"); flint_printf("h = "); gr_mpoly_print_pretty(h, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f * (g + h) = "); gr_mpoly_print_pretty(k1, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f * g + f * h = "); gr_mpoly_print_pretty(k2, NULL, mctx, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, mctx, cctx); gr_mpoly_clear(g, mctx, cctx); gr_mpoly_clear(h, mctx, cctx); gr_mpoly_clear(k1, mctx, cctx); gr_mpoly_clear(k2, mctx, cctx); gr_mpoly_clear(t, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mpoly/test/t-mul_monomial.c000066400000000000000000000100401461254215100213210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gr_mpoly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_mpoly_mul_monomial, state) { slong i, j; /* Check f*(g + h) = f*g + f*h */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { gr_ctx_t cctx; mpoly_ctx_t mctx; gr_mpoly_t f, g, h, k1, k2, t; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; int status; gr_ctx_init_random(cctx, state); mpoly_ctx_init_rand(mctx, state, 4); gr_mpoly_init(f, mctx, cctx); gr_mpoly_init(g, mctx, cctx); gr_mpoly_init(h, mctx, cctx); gr_mpoly_init(k1, mctx, cctx); gr_mpoly_init(k2, mctx, cctx); gr_mpoly_init(t, mctx, cctx); if (cctx->methods == _ca_methods) { len = n_randint(state, 10); len1 = n_randint(state, 10); } else { len = n_randint(state, 100); len1 = n_randint(state, 100); } exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; /* todo: aliasing tests */ for (j = 0; j < 10; j++) { status = GR_SUCCESS; status |= gr_mpoly_randtest_bits(f, state, len1, exp_bits1, mctx, cctx); status |= gr_mpoly_randtest_bits(g, state, 1, exp_bits2, mctx, cctx); status |= gr_mpoly_randtest_bits(h, state, 1, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k1, state, len, exp_bits, mctx, cctx); status |= gr_mpoly_randtest_bits(k2, state, len, exp_bits, mctx, cctx); if (g->length != 1 || h->length != 1) continue; status |= gr_mpoly_add(k1, g, h, mctx, cctx); if (n_randint(state, 2)) status |= gr_mpoly_mul_johnson(k1, f, k1, mctx, cctx); else status |= gr_mpoly_mul_johnson(k1, k1, f, mctx, cctx); if (status == GR_SUCCESS) gr_mpoly_assert_canonical(k1, mctx, cctx); status |= gr_mpoly_mul_monomial(k2, f, g, mctx, cctx); if (status == GR_SUCCESS) gr_mpoly_assert_canonical(k2, mctx, cctx); status |= gr_mpoly_mul_monomial(t, f, h, mctx, cctx); if (status == GR_SUCCESS) gr_mpoly_assert_canonical(t, mctx, cctx); status |= gr_mpoly_add(k2, k2, t, mctx, cctx); if (status == GR_SUCCESS && gr_mpoly_equal(k1, k2, mctx, cctx) == T_FALSE) { flint_printf("FAIL: Check (f + g) - g = f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); gr_ctx_println(cctx); flint_printf("f = "); gr_mpoly_print_pretty(f, NULL, mctx, cctx); flint_printf("\n"); flint_printf("g = "); gr_mpoly_print_pretty(g, NULL, mctx, cctx); flint_printf("\n"); flint_printf("h = "); gr_mpoly_print_pretty(h, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f * (g + h) = "); gr_mpoly_print_pretty(k1, NULL, mctx, cctx); flint_printf("\n"); flint_printf("f * g + f * h = "); gr_mpoly_print_pretty(k2, NULL, mctx, cctx); flint_printf("\n"); fflush(stdout); flint_abort(); } } gr_mpoly_clear(f, mctx, cctx); gr_mpoly_clear(g, mctx, cctx); gr_mpoly_clear(h, mctx, cctx); gr_mpoly_clear(k1, mctx, cctx); gr_mpoly_clear(k2, mctx, cctx); gr_mpoly_clear(t, mctx, cctx); mpoly_ctx_clear(mctx); gr_ctx_clear(cctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_mpoly/write.c000066400000000000000000000114061461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2022, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz.h" #include "fmpz_vec.h" #include "gr_mpoly.h" static char * _gr_mpoly_default_vars[8] = { "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8" }; static int want_parens(const char * s) { if (s[0] == '(' || s[0] == '[' || s[0] == '{') return 0; if (s[0] == '-') s++; while (s[0] != '\0') { if (!isalnum(s[0]) && s[0] != '.') return 1; s++; } return 0; } /* todo: error handling */ int gr_mpoly_write_pretty(gr_stream_t out, const gr_mpoly_t A, const char ** x_in, const mpoly_ctx_t mctx, gr_ctx_t cctx) { slong len = A->length; ulong * exp = A->exps; slong bits = A->bits; slong i, j, N; fmpz * exponents; char * s; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { gr_stream_write(out, "0"); return GR_SUCCESS; } N = mpoly_words_per_exp(bits, mctx); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(mctx->nvars*sizeof(char *)); if (mctx->nvars <= 8) { for (i = 0; i < mctx->nvars; i++) x[i] = _gr_mpoly_default_vars[i]; } else { slong per_var = 22; char * tmp = TMP_ALLOC(mctx->nvars * per_var); for (i = 0; i < mctx->nvars; i++) { x[i] = tmp + per_var * i; flint_sprintf(x[i], "x%wd", i+1); } } } exponents = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(ulong)); for (i = 0; i < mctx->nvars; i++) fmpz_init(exponents + i); for (i = 0; i < len; i++) { int removed_coeff = 0; gr_get_str(&s, GR_ENTRY(A->coeffs, i, cctx->sizeof_elem), cctx); if (!strcmp(s, "1")) { flint_free(s); if (i > 0) gr_stream_write(out, " + "); removed_coeff = 1; } else if (!strcmp(s, "-1")) { flint_free(s); if (i > 0) gr_stream_write(out, " - "); else gr_stream_write(out, "-"); removed_coeff = -1; } else { if (want_parens(s)) { if (i > 0) gr_stream_write(out, " + "); gr_stream_write(out, "("); gr_stream_write_free(out, s); gr_stream_write(out, ")"); } else { if (i > 0 && s[0] == '-') { gr_stream_write(out, " - "); gr_stream_write(out, s + 1); flint_free(s); } else { if (i > 0) gr_stream_write(out, " + "); gr_stream_write_free(out, s); } } } mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, mctx); if (_fmpz_vec_is_zero(exponents, mctx->nvars)) { if (removed_coeff != 0) gr_stream_write(out, "1"); } else { int have_printed_var = 0; for (j = 0; j < mctx->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, 1); if (cmp > 0) { if (have_printed_var || !removed_coeff) gr_stream_write(out, "*"); gr_stream_write(out, x[j]); gr_stream_write(out, "^"); gr_stream_write_fmpz(out, exponents + j); have_printed_var = 1; } else if (cmp == 0) { if (have_printed_var || !removed_coeff) gr_stream_write(out, "*"); gr_stream_write(out, x[j]); have_printed_var = 1; } } } } for (i = 0; i < mctx->nvars; i++) fmpz_clear(exponents + i); TMP_END; return GR_SUCCESS; } int gr_mpoly_print_pretty(const gr_mpoly_t A, const char ** x_in, const mpoly_ctx_t mctx, gr_ctx_t cctx) { gr_stream_t out; gr_stream_init_file(out, stdout); return gr_mpoly_write_pretty(out, A, x_in, mctx, cctx); } flint-3.1.3/src/gr_poly.h000066400000000000000000001040611461254215100152500ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GR_POLY_H #define GR_POLY_H #ifdef GR_POLY_INLINES_C #define GR_POLY_INLINE #else #define GR_POLY_INLINE static inline #endif #include "fmpz_types.h" #include "fmpq_types.h" #include "gr.h" #ifdef __cplusplus extern "C" { #endif /* fixme: compatible with flint polys but not with arb, ... */ typedef struct { gr_ptr coeffs; slong alloc; slong length; } gr_poly_struct; typedef gr_poly_struct gr_poly_t[1]; void gr_poly_init(gr_poly_t poly, gr_ctx_t ctx); void gr_poly_init2(gr_poly_t poly, slong len, gr_ctx_t ctx); void gr_poly_clear(gr_poly_t poly, gr_ctx_t ctx); GR_POLY_INLINE gr_ptr gr_poly_entry_ptr(gr_poly_t poly, slong i, gr_ctx_t ctx) { return GR_ENTRY(poly->coeffs, i, ctx->sizeof_elem); } GR_POLY_INLINE gr_srcptr gr_poly_entry_srcptr(const gr_poly_t poly, slong i, gr_ctx_t ctx) { return GR_ENTRY(poly->coeffs, i, ctx->sizeof_elem); } GR_POLY_INLINE slong gr_poly_length(const gr_poly_t poly, gr_ctx_t ctx) { return poly->length; } GR_POLY_INLINE void gr_poly_swap(gr_poly_t poly1, gr_poly_t poly2, gr_ctx_t ctx) { FLINT_SWAP(gr_poly_struct, *poly1, *poly2); } void gr_poly_fit_length(gr_poly_t poly, slong len, gr_ctx_t ctx); void _gr_poly_set_length(gr_poly_t poly, slong len, gr_ctx_t ctx); void _gr_poly_normalise(gr_poly_t poly, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_reverse(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_reverse(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_truncate(gr_poly_t poly, const gr_poly_t src, slong newlen, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int gr_poly_zero(gr_poly_t poly, gr_ctx_t ctx) { _gr_poly_set_length(poly, 0, ctx); return GR_SUCCESS; } WARN_UNUSED_RESULT int gr_poly_one(gr_poly_t poly, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_neg_one(gr_poly_t poly, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_gen(gr_poly_t poly, gr_ctx_t ctx); int gr_poly_write(gr_stream_t out, const gr_poly_t poly, const char * x, gr_ctx_t ctx); int gr_poly_print(const gr_poly_t poly, gr_ctx_t ctx); int gr_poly_randtest(gr_poly_t poly, flint_rand_t state, slong len, gr_ctx_t ctx); truth_t _gr_poly_equal(gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); truth_t gr_poly_equal(const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx); truth_t gr_poly_is_zero(const gr_poly_t poly, gr_ctx_t ctx); truth_t gr_poly_is_one(const gr_poly_t poly, gr_ctx_t ctx); truth_t gr_poly_is_gen(const gr_poly_t poly, gr_ctx_t ctx); truth_t gr_poly_is_scalar(const gr_poly_t poly, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_scalar(gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_si(gr_poly_t poly, slong x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_ui(gr_poly_t poly, ulong x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_fmpz(gr_poly_t poly, const fmpz_t x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_fmpq(gr_poly_t poly, const fmpq_t x, gr_ctx_t ctx); /* todo: test */ WARN_UNUSED_RESULT int gr_poly_set_fmpz_poly(gr_poly_t res, const fmpz_poly_t src, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_fmpq_poly(gr_poly_t res, const fmpq_poly_t src, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_gr_poly_other(gr_poly_t res, const gr_poly_t x, gr_ctx_t x_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_coeff_scalar(gr_poly_t poly, slong n, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_coeff_si(gr_poly_t poly, slong n, slong x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_coeff_ui(gr_poly_t poly, slong n, ulong x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_coeff_fmpz(gr_poly_t poly, slong n, const fmpz_t x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_set_coeff_fmpq(gr_poly_t poly, slong n, const fmpq_t x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_get_coeff_scalar(gr_ptr res, const gr_poly_t poly, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_neg(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_add(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_add(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_sub(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_sub(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_mul(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_mul(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_mullow_generic(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_mullow(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong len, gr_ctx_t ctx) { return GR_POLY_BINARY_TRUNC_OP(ctx, POLY_MULLOW)(res, poly1, len1, poly2, len2, len, ctx); } WARN_UNUSED_RESULT int gr_poly_mullow(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_mul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx); /* powering */ WARN_UNUSED_RESULT int _gr_poly_pow_series_ui_binexp(gr_ptr res, gr_srcptr f, slong flen, ulong exp, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_pow_series_ui_binexp(gr_poly_t res, const gr_poly_t poly, ulong exp, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_pow_series_ui(gr_ptr res, gr_srcptr f, slong flen, ulong exp, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_pow_series_ui(gr_poly_t res, const gr_poly_t poly, ulong exp, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_pow_ui_binexp(gr_ptr res, gr_srcptr f, slong flen, ulong exp, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_pow_ui_binexp(gr_poly_t res, const gr_poly_t poly, ulong exp, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_pow_ui(gr_ptr res, gr_srcptr f, slong flen, ulong exp, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_pow_ui(gr_poly_t res, const gr_poly_t poly, ulong exp, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_pow_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t exp, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_pow_series_fmpq_recurrence(gr_ptr h, gr_srcptr f, slong flen, const fmpq_t exp, slong len, int precomp, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_pow_series_fmpq_recurrence(gr_poly_t res, const gr_poly_t poly, const fmpq_t exp, slong len, gr_ctx_t ctx); /* shifting */ WARN_UNUSED_RESULT int _gr_poly_shift_left(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_shift_left(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_shift_right(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_shift_right(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx); /* division */ WARN_UNUSED_RESULT int gr_poly_div_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_inv(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divrem_basecase_preinv1(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divrem_basecase_noinv(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divrem_basecase(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divrem_basecase(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divrem_divconquer_preinv1(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divrem_divconquer_noinv(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divrem_divconquer(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divrem_divconquer(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divrem_newton(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divrem_newton(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_divrem(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { return GR_POLY_BINARY_BINARY_OP(ctx, POLY_DIVREM)(Q, R, A, lenA, B, lenB, ctx); } WARN_UNUSED_RESULT int _gr_poly_divrem_generic(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divrem(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_divconquer_preinv1(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_divconquer_noinv(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_divconquer(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_divconquer(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_basecase_preinv1(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_basecase_noinv(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_basecase(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_newton(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_newton(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_div(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { return GR_POLY_BINARY_OP(ctx, POLY_DIV)(Q, A, lenA, B, lenB, ctx); } WARN_UNUSED_RESULT int _gr_poly_div_generic(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_rem(gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_rem(gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); /* todo: div with fast divisibility checking; rem; divexact */ WARN_UNUSED_RESULT int _gr_poly_inv_series_newton(gr_ptr Qinv, gr_srcptr Q, slong Qlen, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_inv_series_newton(gr_poly_t Qinv, const gr_poly_t Q, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_inv_series_basecase_preinv1(gr_ptr res, gr_srcptr A, slong Alen, gr_srcptr Ainv, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_inv_series_basecase_generic(gr_ptr Qinv, gr_srcptr Q, slong Qlen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_inv_series_basecase(gr_poly_t Qinv, const gr_poly_t Q, slong len, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_inv_series_basecase(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return GR_POLY_UNARY_TRUNC_OP(ctx, POLY_INV_SERIES_BASECASE)(res, f, flen, len, ctx); } GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_inv_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return GR_POLY_UNARY_TRUNC_OP(ctx, POLY_INV_SERIES)(res, f, flen, len, ctx); } WARN_UNUSED_RESULT int _gr_poly_inv_series_generic(gr_ptr Qinv, gr_srcptr Q, slong Qlen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_inv_series(gr_poly_t Qinv, const gr_poly_t Q, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_series_newton(gr_ptr res, gr_srcptr B, slong Blen, gr_srcptr A, slong Alen, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_series_newton(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_series_divconquer(gr_ptr res, gr_srcptr B, slong Blen, gr_srcptr A, slong Alen, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_series_divconquer(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_series_basecase_generic(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_series_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_series_basecase_preinv1(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_srcptr Binv, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_series_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_div_series_invmul(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_series_invmul(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_div_series_basecase(gr_ptr res, gr_srcptr f, slong flen, gr_srcptr g, slong glen, slong len, gr_ctx_t ctx) { return GR_POLY_BINARY_TRUNC_OP(ctx, POLY_DIV_SERIES_BASECASE)(res, f, flen, g, glen, len, ctx); } GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_div_series(gr_ptr res, gr_srcptr f, slong flen, gr_srcptr g, slong glen, slong len, gr_ctx_t ctx) { return GR_POLY_BINARY_TRUNC_OP(ctx, POLY_DIV_SERIES)(res, f, flen, g, glen, len, ctx); } WARN_UNUSED_RESULT int _gr_poly_div_series_generic(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_div_series(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divexact_basecase_bidirectional(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divexact_basecase_bidirectional(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divexact_bidirectional(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divexact_bidirectional(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divexact_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divexact_basecase(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divexact_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_divexact(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { return GR_POLY_BINARY_OP(ctx, POLY_DIVEXACT)(Q, A, lenA, B, lenB, ctx); } WARN_UNUSED_RESULT int _gr_poly_divexact_generic(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divexact(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divexact_series_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_divexact_series_basecase(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_divexact_series_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_sqrt_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_sqrt_series_newton(gr_poly_t res, const gr_poly_t f, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_sqrt_series_basecase(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_sqrt_series_basecase(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_sqrt_series_miller(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_sqrt_series_miller(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_sqrt_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return GR_POLY_UNARY_TRUNC_OP(ctx, POLY_SQRT_SERIES)(res, f, flen, len, ctx); } WARN_UNUSED_RESULT int _gr_poly_sqrt_series_generic(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_sqrt_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_rsqrt_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_rsqrt_series_newton(gr_poly_t res, const gr_poly_t f, slong len, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_rsqrt_series_basecase(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_rsqrt_series_basecase(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_rsqrt_series_miller(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_rsqrt_series_miller(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_rsqrt_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return GR_POLY_UNARY_TRUNC_OP(ctx, POLY_RSQRT_SERIES)(res, f, flen, len, ctx); } WARN_UNUSED_RESULT int _gr_poly_rsqrt_series_generic(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_rsqrt_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_rectangular(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_rectangular(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_modular(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_modular(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_horner(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_horner(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate(gr_ptr res, const gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_other_horner(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_other_horner(gr_ptr res, const gr_poly_t f, gr_srcptr a, gr_ctx_t a_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_other_rectangular(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_other_rectangular(gr_ptr res, const gr_poly_t f, gr_srcptr a, gr_ctx_t a_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_other(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_other(gr_ptr res, const gr_poly_t f, gr_srcptr a, gr_ctx_t a_ctx, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_taylor_shift_horner(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_taylor_shift_horner(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_taylor_shift_divconquer(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_taylor_shift_divconquer(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_taylor_shift_convolution(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_taylor_shift_convolution(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_taylor_shift_generic(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_taylor_shift(gr_ptr res, gr_srcptr f, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, POLY_TAYLOR_SHIFT)(res, f, len, c, ctx); } WARN_UNUSED_RESULT int _gr_poly_taylor_shift(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_taylor_shift(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_compose_horner(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_compose_horner(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_compose_divconquer(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_compose_divconquer(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_compose(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_compose(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_compose_series_horner(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_compose_series_horner(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_compose_series_brent_kung(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_compose_series_brent_kung(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_compose_series_divconquer(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_compose_series_divconquer(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_compose_series(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_compose_series(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_revert_series_lagrange(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_revert_series_lagrange(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_revert_series_lagrange_fast(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_revert_series_lagrange_fast(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_revert_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_revert_series_newton(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_revert_series(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_revert_series(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_derivative(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_derivative(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_nth_derivative(gr_ptr res, gr_srcptr poly, ulong n, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_nth_derivative(gr_poly_t res, const gr_poly_t poly, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_integral(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_integral(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_make_monic(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_make_monic(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t _gr_poly_is_monic(gr_srcptr poly, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT truth_t gr_poly_is_monic(const gr_poly_t res, gr_ctx_t ctx); /* GCD, resultant */ WARN_UNUSED_RESULT int _gr_poly_hgcd(gr_ptr r, slong * sgn, gr_ptr * M, slong * lenM, gr_ptr A, slong * lenA, gr_ptr B, slong * lenB, gr_srcptr a, slong lena, gr_srcptr b, slong lenb, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_gcd_hgcd(gr_ptr G, slong * _lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong inner_cutoff, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_gcd_hgcd(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, slong inner_cutoff, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_gcd_euclidean(gr_ptr G, slong * lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_gcd_euclidean(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_gcd(gr_ptr G, slong * lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_gcd(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_xgcd_euclidean(slong * lenG, gr_ptr G, gr_ptr S, gr_ptr T, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_xgcd_euclidean(gr_poly_t G, gr_poly_t S, gr_poly_t T, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_xgcd_hgcd(slong * Glen, gr_ptr G, gr_ptr S, gr_ptr T, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong hgcd_cutoff, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_xgcd_hgcd(gr_poly_t G, gr_poly_t S, gr_poly_t T, const gr_poly_t A, const gr_poly_t B, slong hgcd_cutoff, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_resultant_euclidean(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_resultant_euclidean(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_resultant_hgcd(gr_ptr res, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong inner_cutoff, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_resultant_hgcd(gr_ptr r, const gr_poly_t f, const gr_poly_t g, slong inner_cutoff, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_resultant_sylvester(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_resultant_sylvester(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_resultant_small(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_resultant_small(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_resultant(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_resultant(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx); /* Multipoint evaluation/interpolation */ gr_ptr * _gr_poly_tree_alloc(slong len, gr_ctx_t ctx); void _gr_poly_tree_free(gr_ptr * tree, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_tree_build(gr_ptr * tree, gr_srcptr roots, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_vec_fast_precomp(gr_ptr vs, gr_srcptr poly, slong plen, gr_ptr * tree, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_vec_fast(gr_ptr ys, gr_srcptr poly, slong plen, gr_srcptr xs, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_vec_fast(gr_vec_t ys, const gr_poly_t poly, const gr_vec_t xs, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_evaluate_vec_iter(gr_ptr ys, gr_srcptr poly, slong plen, gr_srcptr xs, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_evaluate_vec_iter(gr_vec_t ys, const gr_poly_t poly, const gr_vec_t xs, gr_ctx_t ctx); /* Squarefree factorization */ int gr_poly_factor_squarefree(gr_ptr c, gr_vec_t fac, gr_vec_t exp, const gr_poly_t F, gr_ctx_t ctx); int gr_poly_squarefree_part(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx); /* Roots */ typedef int ((*gr_poly_roots_op)(gr_vec_t, gr_vec_t, const gr_poly_t, int, gr_ctx_ptr)); #define GR_POLY_ROOTS_OP(ctx, NAME) (((gr_poly_roots_op *) ctx->methods)[GR_METHOD_ ## NAME]) GR_POLY_INLINE WARN_UNUSED_RESULT int gr_poly_roots(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, int flags, gr_ctx_t ctx) { return GR_POLY_ROOTS_OP(ctx, POLY_ROOTS)(roots, mult, poly, flags, ctx); } typedef int ((*gr_poly_roots_op_other)(gr_vec_t, gr_vec_t, const gr_poly_t, gr_ctx_ptr, int, gr_ctx_ptr)); #define GR_POLY_ROOTS_OP_OTHER(ctx, NAME) (((gr_poly_roots_op_other *) ctx->methods)[GR_METHOD_ ## NAME]) GR_POLY_INLINE WARN_UNUSED_RESULT int gr_poly_roots_other(gr_vec_t roots, gr_vec_t mult, const gr_poly_t poly, gr_ctx_t poly_ctx, int flags, gr_ctx_t ctx) { return GR_POLY_ROOTS_OP_OTHER(ctx, POLY_ROOTS_OTHER)(roots, mult, poly, poly_ctx, flags, ctx); } WARN_UNUSED_RESULT int _gr_poly_asin_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_asin_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_asinh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_asinh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_acos_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_acos_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_acosh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_acosh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_atan_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_atan_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_atanh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_atanh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_log_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_log_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_log1p_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_log1p_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_exp_series_basecase(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_exp_series_basecase(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_exp_series_basecase_mul(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_exp_series_basecase_mul(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_exp_series_newton(gr_ptr f, gr_ptr g, gr_srcptr h, slong hlen, slong n, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_exp_series_newton(gr_poly_t f, const gr_poly_t h, slong n, slong cutoff, gr_ctx_t ctx); GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_exp_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return GR_POLY_UNARY_TRUNC_OP(ctx, POLY_EXP_SERIES)(res, f, flen, len, ctx); } WARN_UNUSED_RESULT int _gr_poly_exp_series_generic(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_exp_series(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_sin_cos_series_basecase(gr_ptr s, gr_ptr c, gr_srcptr h, slong hlen, slong n, int times_pi, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_sin_cos_series_basecase(gr_poly_t s, gr_poly_t c, const gr_poly_t h, slong n, int times_pi, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_sin_cos_series_tangent(gr_ptr s, gr_ptr c, gr_srcptr h, slong hlen, slong n, int times_pi, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_sin_cos_series_tangent(gr_poly_t s, gr_poly_t c, const gr_poly_t h, slong n, int times_pi, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_tan_series_basecase(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_tan_series_basecase(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_tan_series_newton(gr_ptr f, gr_srcptr h, slong hlen, slong n, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_tan_series_newton(gr_poly_t f, const gr_poly_t h, slong n, slong cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_poly_tan_series(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_poly_tan_series(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/gr_poly/000077500000000000000000000000001461254215100150755ustar00rootroot00000000000000flint-3.1.3/src/gr_poly/add.c000066400000000000000000000026051461254215100157740ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_add(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { slong sz; int status; slong min = FLINT_MIN(len1, len2); status = _gr_vec_add(res, poly1, poly2, min, ctx); if (len1 > min) { sz = ctx->sizeof_elem; status |= _gr_vec_set(GR_ENTRY(res, min, sz), GR_ENTRY(poly1, min, sz), len1 - min, ctx); } if (len2 > min) { sz = ctx->sizeof_elem; status |= _gr_vec_set(GR_ENTRY(res, min, sz), GR_ENTRY(poly2, min, sz), len2 - min, ctx); } return status; } int gr_poly_add(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { int status; slong max = FLINT_MAX(poly1->length, poly2->length); gr_poly_fit_length(res, max, ctx); status = _gr_poly_add(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _gr_poly_set_length(res, max, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/asin_series.c000066400000000000000000000154351461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_poly.h" static int _gr_poly_inv_trig_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx, int function) { gr_ptr c; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; flen = FLINT_MIN(flen, len); if (flen == 0) return GR_UNABLE; GR_TMP_INIT(c, ctx); status |= (((gr_method_unary_op *) ctx->methods)[function])(c, f, ctx); if (status == GR_SUCCESS) { if (flen == 1) { status |= _gr_vec_zero(GR_ENTRY(res, 1, sz), len - 1, ctx); } else { gr_ptr t, u; slong ulen; ulen = FLINT_MIN(len, 2 * flen - 1); GR_TMP_INIT_VEC(t, len + ulen, ctx); u = GR_ENTRY(t, len, sz); /* asin(f(x)) = integral(f'(x)/sqrt(1-f(x)^2)) */ /* acos(f(x)) = integral(-f'(x)/sqrt(1-f(x)^2)) */ /* asinh(f(x)) = integral(f'(x)/sqrt(f(x)^2+1)) */ /* acosh(f(x)) = integral(f'(x)/sqrt(f(x)^2-1)) */ /* atan(f(x)) = integral(f'(x)/(1+f(x)^2)) */ /* atanh(f(x)) = integral(f'(x)/(1-f(x)^2)) */ status |= _gr_poly_mullow(u, f, flen, f, flen, ulen, ctx); if (function == GR_METHOD_ASINH || function == GR_METHOD_ATAN) status |= gr_add_ui(u, u, 1, ctx); else status |= gr_sub_ui(u, u, 1, ctx); if (function == GR_METHOD_ASIN || function == GR_METHOD_ACOS || function == GR_METHOD_ATANH) status |= _gr_vec_neg(u, u, ulen, ctx); if (function == GR_METHOD_ATAN || function == GR_METHOD_ATANH) { status |= _gr_poly_derivative(t, f, flen, ctx); status |= _gr_poly_div_series(res, t, flen - 1, u, ulen, len, ctx); } else { status |= _gr_poly_rsqrt_series(t, u, ulen, len, ctx); status |= _gr_poly_derivative(u, f, flen, ctx); status |= _gr_poly_mullow(res, t, len, u, flen - 1, len, ctx); } status |= _gr_poly_integral(res, res, len, ctx); if (function == GR_METHOD_ACOS) status |= _gr_vec_neg(res, res, len, ctx); GR_TMP_CLEAR_VEC(t, len + ulen, ctx); } gr_swap(res, c, ctx); } GR_TMP_CLEAR(c, ctx); return status; } int _gr_poly_asin_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return _gr_poly_inv_trig_series(res, f, flen, len, ctx, GR_METHOD_ASIN); } int _gr_poly_acos_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return _gr_poly_inv_trig_series(res, f, flen, len, ctx, GR_METHOD_ACOS); } int _gr_poly_asinh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return _gr_poly_inv_trig_series(res, f, flen, len, ctx, GR_METHOD_ASINH); } int _gr_poly_acosh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return _gr_poly_inv_trig_series(res, f, flen, len, ctx, GR_METHOD_ACOSH); } int _gr_poly_atan_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return _gr_poly_inv_trig_series(res, f, flen, len, ctx, GR_METHOD_ATAN); } int _gr_poly_atanh_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return _gr_poly_inv_trig_series(res, f, flen, len, ctx, GR_METHOD_ATANH); } int gr_poly_asin_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_asin_series(res->coeffs, f->coeffs, flen, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_asinh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_asinh_series(res->coeffs, f->coeffs, flen, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_acos_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); if (flen == 0) { status |= gr_zero(res->coeffs, ctx); status |= _gr_poly_acos_series(res->coeffs, res->coeffs, 1, len, ctx); } else { status |= _gr_poly_acos_series(res->coeffs, f->coeffs, flen, len, ctx); } _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_acosh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); if (flen == 0) { status |= gr_zero(res->coeffs, ctx); status |= _gr_poly_acosh_series(res->coeffs, res->coeffs, 1, len, ctx); } else { status |= _gr_poly_acosh_series(res->coeffs, f->coeffs, flen, len, ctx); } _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_atan_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_atan_series(res->coeffs, f->coeffs, flen, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_atanh_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_atanh_series(res->coeffs, f->coeffs, flen, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/clear.c000066400000000000000000000011151461254215100163250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" void gr_poly_clear(gr_poly_t poly, gr_ctx_t ctx) { if (poly->coeffs != NULL) { _gr_vec_clear(poly->coeffs, poly->alloc, ctx); flint_free(poly->coeffs); } } flint-3.1.3/src/gr_poly/compose.c000066400000000000000000000070311461254215100167070ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* compose by poly2 = a*x^n + c, no aliasing; n >= 1 */ int _gr_poly_compose_axnc(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr c, gr_srcptr a, slong n, gr_ctx_t ctx) { slong i, sz = ctx->sizeof_elem; int status; /* shift by c (c = 0 case will be fast) */ status = _gr_poly_taylor_shift(res, poly1, len1, c, ctx); /* multiply by powers of a */ if (gr_is_one(a, ctx) != T_TRUE) { if (gr_is_neg_one(a, ctx) == T_TRUE) { for (i = 1; i < len1; i += 2) status |= gr_neg(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), ctx); } else if (len1 == 2) { status |= gr_mul(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), a, ctx); } else { gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_set(t, a, ctx); for (i = 1; i < len1; i++) { status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), t, ctx); if (i + 1 < len1) status |= gr_mul(t, t, a, ctx); } GR_TMP_CLEAR(t, ctx); } } /* stretch */ for (i = len1 - 1; i >= 1 && n > 1; i--) { gr_swap(GR_ENTRY(res, i * n, sz), GR_ENTRY(res, i, sz), ctx); status |= _gr_vec_zero(GR_ENTRY(res, (i - 1) * n + 1, sz), n - 1, ctx); } return status; } int _gr_poly_compose(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { slong sz; if (len1 == 1) return gr_set(res, poly1, ctx); if (len2 == 1) return _gr_poly_evaluate(res, poly1, len1, poly2, ctx); sz = ctx->sizeof_elem; if (_gr_vec_is_zero(GR_ENTRY(poly2, 1, sz), len2 - 2, ctx) == T_TRUE) return _gr_poly_compose_axnc(res, poly1, len1, poly2, GR_ENTRY(poly2, len2 - 1, sz), len2 - 1, ctx); if (len1 <= 7) return _gr_poly_compose_horner(res, poly1, len1, poly2, len2, ctx); return _gr_poly_compose_divconquer(res, poly1, len1, poly2, len2, ctx); } int gr_poly_compose(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { return gr_poly_zero(res, ctx); } else if (len1 == 1 || len2 == 0) { return gr_poly_set_scalar(res, poly1->coeffs, ctx); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; int status; if (res != poly1 && res != poly2) { gr_poly_fit_length(res, lenr, ctx); status = _gr_poly_compose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); } else { gr_poly_t t; gr_poly_init2(t, lenr, ctx); status = _gr_poly_compose(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } _gr_poly_set_length(res, lenr, ctx); _gr_poly_normalise(res, ctx); return status; } } flint-3.1.3/src/gr_poly/compose_divconquer.c000066400000000000000000000123361461254215100211520ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: use TMP temporaries */ int _gr_poly_compose_divconquer(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { slong i, j, k, n; slong *hlen, alloc, powlen; gr_ptr v, pow, temp; gr_ptr * h; slong sz; int status; if (len1 == 1) return gr_set(res, poly1, ctx); if (len2 == 1) return _gr_poly_evaluate(res, poly1, len1, poly2, ctx); if (len1 == 2) return _gr_poly_compose_horner(res, poly1, len1, poly2, len2, ctx); sz = ctx->sizeof_elem; status = GR_SUCCESS; /* Initialisation */ hlen = (slong *) flint_malloc(((len1 + 1) / 2) * sizeof(slong)); for (k = 1; (2 << k) < len1; k++) ; hlen[0] = hlen[1] = ((1 << k) - 1) *(len2 - 1) + 1; for (i = k - 1; i > 0; i--) { slong hi = (len1 + (1 << i) - 1) / (1 << i); for (n = (hi + 1) / 2; n < hi; n++) hlen[n] = ((1 << i) - 1) * (len2 - 1) + 1; } powlen = (1 << k) * (len2 - 1) + 1; alloc = 0; for (i = 0; i < (len1 + 1) / 2; i++) alloc += hlen[i]; GR_TMP_INIT_VEC(v, alloc + 2 * powlen, ctx); h = (gr_ptr *) flint_malloc(((len1 + 1) / 2) * sizeof(gr_ptr)); h[0] = v; for (i = 0; i < (len1 - 1) / 2; i++) { h[i + 1] = GR_ENTRY(h[i], hlen[i], sz); hlen[i] = 0; } hlen[(len1 - 1) / 2] = 0; pow = GR_ENTRY(v, alloc, sz); temp = GR_ENTRY(pow, powlen, sz); /* Let's start the actual work */ for (i = 0, j = 0; i < len1 / 2; i++, j += 2) { if (gr_is_zero(GR_ENTRY(poly1, j + 1, sz), ctx) != T_TRUE) { status |= _gr_vec_mul_scalar(h[i], poly2, len2, GR_ENTRY(poly1, j + 1, sz), ctx); status |= gr_add(h[i], h[i], GR_ENTRY(poly1, j, sz), ctx); hlen[i] = len2; } else if (gr_is_zero(GR_ENTRY(poly1, j, sz), ctx) != T_TRUE) { status |= gr_set(h[i], GR_ENTRY(poly1, j, sz), ctx); hlen[i] = 1; } } if ((len1 & WORD(1))) { if (gr_is_zero(GR_ENTRY(poly1, j, sz), ctx) != T_TRUE) { status |= gr_set(h[i], GR_ENTRY(poly1, j, sz), ctx); hlen[i] = 1; } } status |= _gr_poly_mul(pow, poly2, len2, poly2, len2, ctx); powlen = 2 * len2 - 1; for (n = (len1 + 1) / 2; n > 2; n = (n + 1) / 2) { if (hlen[1] > 0) { slong templen = powlen + hlen[1] - 1; status |= _gr_poly_mul(temp, pow, powlen, h[1], hlen[1], ctx); status |= _gr_poly_add(h[0], temp, templen, h[0], hlen[0], ctx); hlen[0] = FLINT_MAX(hlen[0], templen); } for (i = 1; i < n / 2; i++) { if (hlen[2*i + 1] > 0) { status |= _gr_poly_mul(h[i], pow, powlen, h[2*i + 1], hlen[2*i + 1], ctx); hlen[i] = hlen[2*i + 1] + powlen - 1; } else { hlen[i] = 0; } status |= _gr_poly_add(h[i], h[i], hlen[i], h[2*i], hlen[2*i], ctx); hlen[i] = FLINT_MAX(hlen[i], hlen[2*i]); } if ((n & WORD(1))) { status |= _gr_vec_set(h[i], h[2*i], hlen[2*i], ctx); hlen[i] = hlen[2*i]; } status |= _gr_poly_mul(temp, pow, powlen, pow, powlen, ctx); powlen += powlen - 1; { gr_ptr t = pow; pow = temp; temp = t; } } status |= _gr_poly_mul(res, pow, powlen, h[1], hlen[1], ctx); status |= _gr_vec_add(res, res, h[0], hlen[0], ctx); GR_TMP_CLEAR_VEC(v, alloc + 2 * powlen, ctx); flint_free(h); flint_free(hlen); return status; } int gr_poly_compose_divconquer(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { return gr_poly_zero(res, ctx); } else if (len1 == 1 || len2 == 0) { return gr_poly_set_scalar(res, poly1->coeffs, ctx); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; int status; if (res != poly1 && res != poly2) { gr_poly_fit_length(res, lenr, ctx); status = _gr_poly_compose_divconquer(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); } else { gr_poly_t t; gr_poly_init2(t, lenr, ctx); status = _gr_poly_compose_divconquer(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } _gr_poly_set_length(res, lenr, ctx); _gr_poly_normalise(res, ctx); return status; } } flint-3.1.3/src/gr_poly/compose_horner.c000066400000000000000000000061051461254215100202650ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_compose_horner(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len1 == 1) { return gr_set(res, poly1, ctx); } else if (len2 == 1) { return _gr_poly_evaluate(res, poly1, len1, poly2, ctx); } else if (len1 == 2) { slong sz = ctx->sizeof_elem; status |= _gr_vec_mul_scalar(res, poly2, len2, GR_ENTRY(poly1, 1, sz), ctx); status |= gr_add(res, res, poly1, ctx); return status; } else { slong alloc = (len1 - 1) * (len2 - 1) + 1; slong i = len1 - 1, lenr = len2; slong sz = ctx->sizeof_elem; gr_ptr t, t1, t2; GR_TMP_INIT_VEC(t, alloc, ctx); if (len1 % 2 == 0) { t1 = res; t2 = t; } else { t1 = t; t2 = res; } /* Perform the first two steps as one, "res = a(m) * poly2 + a(m-1)". */ status |= _gr_vec_mul_scalar(t1, poly2, len2, GR_ENTRY(poly1, i, sz), ctx); i--; status |= gr_add(t1, t1, GR_ENTRY(poly1, i, sz), ctx); while (i--) { status |= _gr_poly_mul(t2, t1, lenr, poly2, len2, ctx); lenr += len2 - 1; { void *t_ = t1; t1 = t2; t2 = t_; } status |= gr_add(t1, t1, GR_ENTRY(poly1, i, sz), ctx); } GR_TMP_CLEAR_VEC(t, alloc, ctx); return status; } } int gr_poly_compose_horner(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { return gr_poly_zero(res, ctx); } else if (len1 == 1 || len2 == 0) { return gr_poly_set_scalar(res, poly1->coeffs, ctx); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; int status; if (res != poly1 && res != poly2) { gr_poly_fit_length(res, lenr, ctx); status = _gr_poly_compose_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); } else { gr_poly_t t; gr_poly_init2(t, lenr, ctx); status = _gr_poly_compose_horner(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } _gr_poly_set_length(res, lenr, ctx); _gr_poly_normalise(res, ctx); return status; } } flint-3.1.3/src/gr_poly/compose_series.c000066400000000000000000000107671461254215100202730ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_compose_series(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) { status |= gr_set(res, poly1, ctx); } else if (n == 2) { status |= gr_set(res, poly1, ctx); status |= gr_mul(GR_ENTRY(res, 1, sz), GR_ENTRY(poly1, 1, sz), GR_ENTRY(poly2, 1, sz), ctx); } else if (len1 == 1 || len2 == 1) { status |= gr_set(res, poly1, ctx); status |= _gr_vec_zero(GR_ENTRY(res, 1, sz), n - 1, ctx); } else if (n == 3) { status |= gr_set(res, poly1, ctx); status |= gr_mul(GR_ENTRY(res, 1, sz), GR_ENTRY(poly1, 1, sz), GR_ENTRY(poly2, 1, sz), ctx); if (len1 == 2 && len2 == 3) { status |= gr_mul(GR_ENTRY(res, 2, sz), GR_ENTRY(poly1, 1, sz), GR_ENTRY(poly2, 2, sz), ctx); } else { status |= gr_sqr(GR_ENTRY(res, 2, sz), GR_ENTRY(poly2, 1, sz), ctx); status |= gr_mul(GR_ENTRY(res, 2, sz), GR_ENTRY(res, 2, sz), GR_ENTRY(poly1, 2, sz), ctx); if (len2 == 3) status |= gr_addmul(GR_ENTRY(res, 2, sz), GR_ENTRY(poly1, 1, sz), GR_ENTRY(poly2, 2, sz), ctx); } } else if (_gr_vec_is_zero(GR_ENTRY(poly2, 1, sz), len2 - 2, ctx) == T_TRUE) /* poly2 is a monomial */ { slong i, j; gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_set(t, GR_ENTRY(poly2, len2 - 1, sz), ctx); status |= gr_set(res, poly1, ctx); for (i = 1, j = len2 - 1; i < len1 && j < n; i++, j += len2 - 1) { status |= gr_mul(GR_ENTRY(res, j, sz), GR_ENTRY(poly1, i, sz), t, ctx); if (i + 1 < len1 && j + len2 - 1 < n) status |= gr_mul(t, t, GR_ENTRY(poly2, len2 - 1, sz), ctx); } if (len2 != 2) for (i = 1; i < n; i++) if (i % (len2 - 1) != 0) status |= gr_zero(GR_ENTRY(res, i, sz), ctx); GR_TMP_CLEAR(t, ctx); } else if (len1 <= 7 || n <= 7) { status |= _gr_poly_compose_series_horner(res, poly1, len1, poly2, len2, n, ctx); } else if (len1 * len1 < n || (len1 - 1) * (len2 - 1) + 1 < 4 * n) /* todo: tune these cutoffs */ { status |= _gr_poly_compose_series_divconquer(res, poly1, len1, poly2, len2, n, ctx); } else { status |= _gr_poly_compose_series_brent_kung(res, poly1, len1, poly2, len2, n, ctx); } return status; } int gr_poly_compose_series(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; int status; if (len2 != 0) { truth_t is_zero = gr_is_zero(poly2->coeffs, ctx); if (is_zero == T_FALSE) return GR_DOMAIN; if (is_zero == T_UNKNOWN) return GR_UNABLE; } if (len1 == 0 || n == 0) return gr_poly_zero(res, ctx); if (len2 == 0 || len1 == 1) return gr_poly_set_scalar(res, poly1->coeffs, ctx); lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { gr_poly_fit_length(res, lenr, ctx); status = _gr_poly_compose_series(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(res, lenr, ctx); _gr_poly_normalise(res, ctx); } else { gr_poly_t t; gr_poly_init2(t, lenr, ctx); status = _gr_poly_compose_series(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(t, lenr, ctx); _gr_poly_normalise(t, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } return status; } flint-3.1.3/src/gr_poly/compose_series_brent_kung.c000066400000000000000000000075231461254215100225050ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2012, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_mat.h" int _gr_poly_compose_series_brent_kung(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_mat_t A, B, C; gr_ptr t, h; slong i, m; if (n == 1) return gr_set(res, poly1, ctx); m = n_sqrt(n) + 1; gr_mat_init(A, m, n, ctx); gr_mat_init(B, m, m, ctx); gr_mat_init(C, m, n, ctx); GR_TMP_INIT_VEC(h, 2 * n, ctx); t = GR_ENTRY(h, n, sz); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) status |= _gr_vec_set(B->rows[i], GR_ENTRY(poly1, i * m, sz), m, ctx); status |= _gr_vec_set(B->rows[i], GR_ENTRY(poly1, i * m, sz), len1 % m, ctx); /* Set rows of A to powers of poly2 */ status |= gr_one(A->rows[0], ctx); status |= _gr_vec_set(A->rows[1], poly2, len2, ctx); /* Prefer squaring for powers? todo: the ring should know */ if (len2 >= n && (gr_ctx_is_finite(ctx) == T_TRUE || gr_ctx_has_real_prec(ctx) == T_TRUE)) { for (i = 2; i < m; i++) status |= _gr_poly_mullow(A->rows[i], A->rows[(i + 1) / 2], n, A->rows[i / 2], n, n, ctx); } else { for (i = 2; i < m; i++) status |= _gr_poly_mullow(A->rows[i], A->rows[i - 1], n, poly2, len2, n, ctx); } status |= gr_mat_mul(C, B, A, ctx); /* Evaluate block composition using the Horner scheme */ status |= _gr_vec_set(res, C->rows[m - 1], n, ctx); status |= _gr_poly_mullow(h, A->rows[m - 1], n, poly2, len2, n, ctx); for (i = m - 2; i >= 0; i--) { status |= _gr_poly_mullow(t, res, n, h, n, n, ctx); status |= _gr_poly_add(res, t, n, C->rows[i], n, ctx); } GR_TMP_CLEAR_VEC(h, 2 * n, ctx); gr_mat_clear(A, ctx); gr_mat_clear(B, ctx); gr_mat_clear(C, ctx); return status; } int gr_poly_compose_series_brent_kung(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; int status; if (len2 != 0) { truth_t is_zero = gr_is_zero(poly2->coeffs, ctx); if (is_zero == T_FALSE) return GR_DOMAIN; if (is_zero == T_UNKNOWN) return GR_UNABLE; } if (len1 == 0 || n == 0) return gr_poly_zero(res, ctx); if (len2 == 0 || len1 == 1) return gr_poly_set_scalar(res, poly1->coeffs, ctx); lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { gr_poly_fit_length(res, lenr, ctx); status = _gr_poly_compose_series_brent_kung(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(res, lenr, ctx); _gr_poly_normalise(res, ctx); } else { gr_poly_t t; gr_poly_init2(t, lenr, ctx); status = _gr_poly_compose_series_brent_kung(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(t, lenr, ctx); _gr_poly_normalise(t, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } return status; } flint-3.1.3/src/gr_poly/compose_series_divconquer.c000066400000000000000000000130021461254215100225130ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" #include "nmod_poly.h" int _gr_poly_compose_series_divconquer(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong N, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong i, j, k, n; slong *hlen, alloc, powlen; gr_ptr v, *h, pow, temp; if (len1 <= 2 || len2 == 1) return _gr_poly_compose_series_horner(res, poly1, len1, poly2, len2, N, ctx); /* Initialisation */ hlen = (slong *) flint_malloc(((len1 + 1) / 2) * sizeof(slong)); for (k = 1; (2 << k) < len1; k++) ; hlen[0] = hlen[1] = FLINT_MIN(N, ((1 << k) - 1) * (len2 - 1) + 1); for (i = k - 1; i > 0; i--) { slong hi = (len1 + (1 << i) - 1) / (1 << i); slong t = FLINT_MIN(N, ((1 << i) - 1) * (len2 - 1) + 1); for (n = (hi + 1) / 2; n < hi; n++) hlen[n] = t; } powlen = FLINT_MIN(N, (1 << k) * (len2 - 1) + 1); alloc = 0; for (i = 0; i < (len1 + 1) / 2; i++) alloc += hlen[i]; GR_TMP_INIT_VEC(v, alloc + 2 * powlen, ctx); h = (gr_ptr *) flint_malloc(((len1 + 1) / 2) * sizeof(mp_ptr)); h[0] = v; for (i = 0; i < (len1 - 1) / 2; i++) { h[i + 1] = GR_ENTRY(h[i], hlen[i], sz); hlen[i] = 0; } hlen[(len1 - 1) / 2] = 0; pow = GR_ENTRY(v, alloc, sz); temp = GR_ENTRY(pow, powlen, sz); /* Let's start the actual work */ /* Note: compose_divconquer checks for zero coefficients here. This does not work here if poly1 has been truncated. */ for (i = 0, j = 0; i < len1 / 2; i++, j += 2) { status |= _gr_vec_mul_scalar(h[i], poly2, len2, GR_ENTRY(poly1, j + 1, sz), ctx); status |= gr_add(h[i], h[i], GR_ENTRY(poly1, j, sz), ctx); hlen[i] = len2; } if ((len1 & WORD(1))) { status |= gr_set(h[i], GR_ENTRY(poly1, j, sz), ctx); hlen[i] = 1; } powlen = FLINT_MIN(N, 2 * len2 - 1); status |= _gr_poly_mullow(pow, poly2, len2, poly2, len2, powlen, ctx); for (n = (len1 + 1) / 2; n > 2; n = (n + 1) / 2) { if (hlen[1] > 0) { slong templen = FLINT_MIN(N, powlen + hlen[1] - 1); status |= _gr_poly_mullow(temp, pow, powlen, h[1], hlen[1], templen, ctx); status |= _gr_poly_add(h[0], temp, templen, h[0], hlen[0], ctx); hlen[0] = FLINT_MAX(hlen[0], templen); } for (i = 1; i < n / 2; i++) { if (hlen[2*i + 1] > 0) { hlen[i] = FLINT_MIN(N, hlen[2*i + 1] + powlen - 1); status |= _gr_poly_mullow(h[i], pow, powlen, h[2*i + 1], hlen[2*i + 1], hlen[i], ctx); } else { hlen[i] = 0; } status |= _gr_poly_add(h[i], h[i], hlen[i], h[2*i], hlen[2*i], ctx); hlen[i] = FLINT_MAX(hlen[i], hlen[2*i]); } if ((n & WORD(1))) { hlen[i] = FLINT_MIN(N, hlen[2*i]); status |= _gr_vec_set(h[i], h[2*i], hlen[i], ctx); } status |= _gr_poly_mullow(temp, pow, powlen, pow, powlen, FLINT_MIN(N, 2 * powlen - 1), ctx); powlen = FLINT_MIN(N, 2 * powlen - 1); { gr_ptr t = pow; pow = temp; temp = t; } } status |= _gr_poly_mullow(res, pow, powlen, h[1], hlen[1], FLINT_MIN(N, powlen + hlen[1] - 1), ctx); status |= _gr_vec_add(res, res, h[0], hlen[0], ctx); GR_TMP_CLEAR_VEC(v, alloc + 2 * powlen, ctx); flint_free(h); flint_free(hlen); return status; } int gr_poly_compose_series_divconquer(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; int status; if (len2 != 0) { truth_t is_zero = gr_is_zero(poly2->coeffs, ctx); if (is_zero == T_FALSE) return GR_DOMAIN; if (is_zero == T_UNKNOWN) return GR_UNABLE; } if (len1 == 0 || n == 0) return gr_poly_zero(res, ctx); if (len2 == 0 || len1 == 1) return gr_poly_set_scalar(res, poly1->coeffs, ctx); lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { gr_poly_fit_length(res, lenr, ctx); status = _gr_poly_compose_series_divconquer(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(res, lenr, ctx); _gr_poly_normalise(res, ctx); } else { gr_poly_t t; gr_poly_init2(t, lenr, ctx); status = _gr_poly_compose_series_divconquer(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(t, lenr, ctx); _gr_poly_normalise(t, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } return status; } flint-3.1.3/src/gr_poly/compose_series_horner.c000066400000000000000000000060711461254215100216410ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_compose_series_horner(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { slong i = len1 - 1; slong lenr; slong sz = ctx->sizeof_elem; gr_ptr t; int status = GR_SUCCESS; if (n == 1) return gr_set(res, poly1, ctx); lenr = len2; status |= _gr_vec_mul_scalar(res, poly2, len2, GR_ENTRY(poly1, i, sz), ctx); i--; status |= gr_add(res, res, GR_ENTRY(poly1, i, sz), ctx); if (i > 0) { GR_TMP_INIT_VEC(t, n, ctx); while (i > 0) { i--; if (lenr + len2 - 1 < n) { status |= _gr_poly_mul(t, res, lenr, poly2, len2, ctx); lenr = lenr + len2 - 1; } else { status |= _gr_poly_mullow(t, res, lenr, poly2, len2, n, ctx); lenr = n; } status |= _gr_poly_add(res, t, lenr, GR_ENTRY(poly1, i, sz), 1, ctx); } GR_TMP_CLEAR_VEC(t, n, ctx); } status |= _gr_vec_zero(GR_ENTRY(res, lenr, sz), n - lenr, ctx); return status; } int gr_poly_compose_series_horner(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; int status; if (len2 != 0) { truth_t is_zero = gr_is_zero(poly2->coeffs, ctx); if (is_zero == T_FALSE) return GR_DOMAIN; if (is_zero == T_UNKNOWN) return GR_UNABLE; } if (len1 == 0 || n == 0) return gr_poly_zero(res, ctx); if (len2 == 0 || len1 == 1) return gr_poly_set_scalar(res, poly1->coeffs, ctx); lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { gr_poly_fit_length(res, lenr, ctx); status = _gr_poly_compose_series_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(res, lenr, ctx); _gr_poly_normalise(res, ctx); } else { gr_poly_t t; gr_poly_init2(t, lenr, ctx); status = _gr_poly_compose_series_horner(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, ctx); _gr_poly_set_length(t, lenr, ctx); _gr_poly_normalise(t, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } return status; } flint-3.1.3/src/gr_poly/derivative.c000066400000000000000000000024211461254215100174020ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo: overloadable function */ int _gr_poly_derivative(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx) { gr_method_binary_op_ui mul_ui = GR_BINARY_OP_UI(ctx, MUL_UI); slong i; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; for (i = 1; i < len; i++) status |= mul_ui(GR_ENTRY(res, i - 1, sz), GR_ENTRY(poly, i, sz), i, ctx); return status; } int gr_poly_derivative(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) { int status; slong len = poly->length; if (len <= 1) { status = gr_poly_zero(res, ctx); } else { gr_poly_fit_length(res, len - 1, ctx); status = _gr_poly_derivative(res->coeffs, poly->coeffs, len, ctx); _gr_poly_set_length(res, len - 1, ctx); /* todo: only call in nonzero characteristic */ _gr_poly_normalise(res, ctx); } return status; } flint-3.1.3/src/gr_poly/div.c000066400000000000000000000040521461254215100160240ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: tuning */ #define DIVCONQUER_CUTOFF 10 int _gr_poly_div_generic(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { int status; if (lenB <= DIVCONQUER_CUTOFF || lenA - lenB <= DIVCONQUER_CUTOFF) { status = _gr_poly_div_basecase(Q, A, lenA, B, lenB, ctx); } else { status = _gr_poly_div_newton(Q, A, lenA, B, lenB, ctx); /* Newton requires invertible lc(B); basecase and divide-and-conquer may yet succeed without it. */ if (status == GR_DOMAIN) status = _gr_poly_div_divconquer_noinv(Q, A, lenA, B, lenB, DIVCONQUER_CUTOFF, ctx); } return status; } int gr_poly_div(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_div(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_div(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_basecase.c000066400000000000000000000073321461254215100176560ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_div_basecase_preinv1(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_srcptr invB, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong Qlen; int is_one; slong i, l; if (Blen == 1) return _gr_vec_mul_scalar(Q, A, Alen, invB, ctx); Qlen = Alen - Blen + 1; is_one = (gr_is_one(invB, ctx) == T_TRUE); status |= gr_mul(GR_ENTRY(Q, Qlen - 1, sz), GR_ENTRY(A, Alen - 1, sz), invB, ctx); for (i = 1; i < Qlen; i++) { l = FLINT_MIN(i, Blen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(A, Alen - 1 - i, sz), 1, GR_ENTRY(B, Blen - 1 - l, sz), GR_ENTRY(Q, Qlen - i, sz), l, ctx); if (!is_one) status |= gr_mul(GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(Q, Qlen - 1 - i, sz), invB, ctx); } return status; } int _gr_poly_div_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong Qlen; slong i, l; if (Blen == 1) return _gr_vec_div_scalar(Q, A, Alen, B, ctx); Qlen = Alen - Blen + 1; status = gr_div(GR_ENTRY(Q, Qlen - 1, sz), GR_ENTRY(A, Alen - 1, sz), GR_ENTRY(B, Blen - 1, sz), ctx); for (i = 1; status == GR_SUCCESS && i < Qlen; i++) { l = FLINT_MIN(i, Blen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(A, Alen - 1 - i, sz), 1, GR_ENTRY(B, Blen - 1 - l, sz), GR_ENTRY(Q, Qlen - i, sz), l, ctx); status |= gr_div(GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(B, Blen - 1, sz), ctx); } return status; } int _gr_poly_div_basecase(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_ptr invB; GR_TMP_INIT(invB, ctx); /* todo: we sometimes want to keep dividing, e.g. over RR with small coefficient */ status = gr_inv(invB, GR_ENTRY(B, Blen - 1, sz), ctx); /* constant is a unit; can multiply by inverse */ if (status == GR_SUCCESS) status = _gr_poly_div_basecase_preinv1(Q, A, Alen, B, Blen, invB, ctx); else status = _gr_poly_div_basecase_noinv(Q, A, Alen, B, Blen, ctx); GR_TMP_CLEAR(invB, ctx); return status; } int gr_poly_div_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_div_basecase(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_div_basecase(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_divconquer.c000066400000000000000000000171521461254215100202700ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2011 William Hart Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_divrem_divconquer_recursive(gr_ptr Q, gr_ptr BQ, gr_ptr W, gr_srcptr A, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx); int _gr_poly_div_divconquer_recursive(gr_ptr Q, gr_ptr W, gr_srcptr A, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (lenB < FLINT_MAX(2, cutoff)) { if (invB == NULL) return _gr_poly_div_basecase_noinv(Q, A, 2 * lenB - 1, B, lenB, ctx); else return _gr_poly_div_basecase_preinv1(Q, A, 2 * lenB - 1, B, lenB, invB, ctx); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; gr_ptr W1 = W; gr_ptr W2 = GR_ENTRY(W, lenB, sz); gr_srcptr p1 = GR_ENTRY(A, 2 * n2, sz); gr_srcptr p2; gr_srcptr d1 = GR_ENTRY(B, n2, sz); gr_srcptr d2 = B; gr_srcptr d3 = GR_ENTRY(B, n1, sz); gr_ptr q1 = GR_ENTRY(Q, n2, sz); gr_ptr q2 = Q; gr_ptr d1q1 = W2; gr_ptr d2q1, t; /* Set q1 to p1 div d1, a 2 n1 - 1 by n1 division so q1 ends up being of length n1; low(d1q1) = d1 q1 is of length n1 - 1 */ status |= _gr_poly_divrem_divconquer_recursive(q1, d1q1, W1, p1, d1, n1, invB, cutoff, ctx); /* Compute bottom n1 + n2 - 1 coeffs of d2q1 = d2 q1 */ d2q1 = W1; status |= _gr_poly_mullow(d2q1, q1, n1, d2, n2, n1 + n2 - 1, ctx); /* Compute dq1 = d1 q1 x^n2 + d2 q1, of length n1 + n2 - 1 Split it into a segment of length n1 - 1 at which is ignored and a piece of length n2 at BQ. */ if (n2 > n1 - 1) status |= gr_set(W1, GR_ENTRY(d2q1, n1 - 1, sz), ctx); status |= _gr_poly_add(GR_ENTRY(W1, n2 - (n1 - 1), sz), d1q1, n1 - 1, GR_ENTRY(d2q1, n2, sz), n1 - 1, ctx); /* Compute t = A/x^n2 - dq1, which has length 2 n1 + n2 - 1, but we are not interested in the top n1 coeffs as they will be zero, so this has effective length n1 + n2 - 1 For the following division, we want to set {p2, 2 n2 - 1} to the top 2 n2 - 1 coeffs of this Since the bottom n2 - 1 coeffs of p2 are irrelevant for the division, we in fact set {t, n2} to the relevant coeffs */ t = W1; status |= _gr_poly_sub(t, GR_ENTRY(A, n2 + (n1 - 1), sz), n2, t, n2, ctx); p2 = GR_ENTRY(t, - (n2 - 1), sz); /* Compute q2 = t div d3, a 2 n2 - 1 by n2 division, so q2 will have length n2; */ status |= _gr_poly_div_divconquer_recursive(q2, W2, p2, d3, n2, invB, cutoff, ctx); /* Note Q = q1 x^n2 + q2 */ return status; } } static int __gr_poly_div_divconquer(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (lenA < 2 * lenB - 1) { /* Convert unbalanced division into a 2 n1 - 1 by n1 division */ const slong n1 = lenA - lenB + 1; const slong n2 = lenB - n1; gr_srcptr p1 = GR_ENTRY(A, n2, sz); gr_srcptr d1 = GR_ENTRY(B, n2, sz); gr_ptr W; GR_TMP_INIT_VEC(W, 2 * lenB, ctx); status |= _gr_poly_div_divconquer_recursive(Q, W, p1, d1, n1, invB, cutoff, ctx); GR_TMP_CLEAR_VEC(W, 2 * lenB, ctx); } else /* lenA = 2 * lenB - 1 */ { gr_ptr W; GR_TMP_INIT_VEC(W, 2 * lenB, ctx); status |= _gr_poly_div_divconquer_recursive(Q, W, A, B, lenB, invB, cutoff, ctx); GR_TMP_CLEAR_VEC(W, 2 * lenB, ctx); } return status; } /* needed due to partial overlap */ static int _gr_vec_sub_dec(gr_ptr a, gr_srcptr b, gr_srcptr c, slong n, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong i; for (i = n - 1; i >= 0; i--) status |= gr_sub(GR_ENTRY(a, i, sz), GR_ENTRY(b, i, sz), GR_ENTRY(c, i, sz), ctx); return status; } int _gr_poly_div_divconquer_preinv1(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) { if (lenA <= 2 * lenB - 1) { return __gr_poly_div_divconquer(Q, A, lenA, B, lenB, invB, cutoff, ctx); } else /* lenA > 2 * lenB - 1 */ { gr_ptr S, T, R; slong shift, next, n = 2 * lenB - 1; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; GR_TMP_INIT_VEC(S, 3 * n, ctx); T = GR_ENTRY(S, n, sz); R = GR_ENTRY(T, n, sz); shift = lenA - n; status |= _gr_vec_set(S, GR_ENTRY(A, shift, sz), n, ctx); while (lenA >= n) { shift = lenA - n; status |= _gr_poly_divrem_divconquer_recursive(GR_ENTRY(Q, shift, sz), T, R, S, B, lenB, invB, cutoff, ctx); next = FLINT_MIN(lenB, shift); status |= _gr_vec_sub_dec(GR_ENTRY(S, next, sz), S, T, lenB - 1, ctx); status |= _gr_vec_set(S, GR_ENTRY(A, shift - next, sz), next, ctx); lenA -= lenB; } if (lenA >= lenB) status |= __gr_poly_div_divconquer(Q, S, lenA, B, lenB, invB, cutoff, ctx); GR_TMP_CLEAR_VEC(S, 3 * n, ctx); return status; } } int _gr_poly_div_divconquer_noinv(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) { return _gr_poly_div_divconquer_preinv1(Q, A, lenA, B, lenB, NULL, cutoff, ctx); } int _gr_poly_div_divconquer(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ptr invB; GR_TMP_INIT(invB, ctx); status = gr_inv(invB, GR_ENTRY(B, lenB - 1, sz), ctx); if (status == GR_SUCCESS) status = _gr_poly_div_divconquer_preinv1(Q, A, lenA, B, lenB, invB, cutoff, ctx); else status = _gr_poly_div_divconquer_noinv(Q, A, lenA, B, lenB, cutoff, ctx); GR_TMP_CLEAR(invB, ctx); return status; } int gr_poly_div_divconquer(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong cutoff, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_div_divconquer(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, cutoff, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_div_divconquer(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, cutoff, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_newton.c000066400000000000000000000051321461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: public vec function */ void _gr_vec_reverse_shallow(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_void_unary_op set_shallow = GR_VOID_UNARY_OP(ctx, SET_SHALLOW); slong sz = ctx->sizeof_elem; slong i; for (i = 0; i < len; i++) set_shallow(GR_ENTRY(res, i, sz), GR_ENTRY(vec, len - 1 - i, sz), ctx); } int _gr_poly_div_newton(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong lenQ, lenB2, alloc; gr_ptr Arev, Brev; lenQ = lenA - lenB + 1; alloc = lenQ + FLINT_MIN(lenB, lenQ); Arev = GR_TMP_ALLOC(alloc * sz); Brev = GR_ENTRY(Arev, lenQ, sz); _gr_vec_reverse_shallow(Arev, GR_ENTRY(A, lenA - lenQ, sz), lenQ, ctx); if (lenB >= lenQ) { _gr_vec_reverse_shallow(Brev, GR_ENTRY(B, lenB - lenQ, sz), lenQ, ctx); lenB2 = lenQ; } else { _gr_vec_reverse_shallow(Brev, B, lenB, ctx); lenB2 = lenB; } status |= _gr_poly_div_series(Q, Arev, lenQ, Brev, lenB2, lenQ, ctx); status |= _gr_poly_reverse(Q, Q, lenQ, lenQ, ctx); GR_TMP_FREE(Arev, alloc * sz); return status; } int gr_poly_div_newton(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_div_newton(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_div_newton(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_scalar.c000066400000000000000000000016051461254215100173520ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int gr_poly_div_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) { int status; slong len = poly->length; if (len == 0 && gr_is_zero(c, ctx) == T_FALSE) return gr_poly_zero(res, ctx); if (res != poly) { gr_poly_fit_length(res, len, ctx); _gr_poly_set_length(res, len, ctx); } status = _gr_vec_div_scalar(res->coeffs, poly->coeffs, len, c, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/div_series.c000066400000000000000000000041041461254215100173740ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" #define DEFAULT_CUTOFF 8 int _gr_poly_div_series_generic(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) { int status; /* todo */ if (FLINT_MIN(Blen, len) <= DEFAULT_CUTOFF || ctx->methods[GR_METHOD_POLY_MULLOW] == (gr_funcptr) _gr_poly_mullow_generic) { status = _gr_poly_div_series_basecase(Q, A, Alen, B, Blen, len, ctx); } else { status = _gr_poly_div_series_newton(Q, A, Alen, B, Blen, len, DEFAULT_CUTOFF, ctx); /* Newton requires invertible constant term of B; basecase and divide-and-conquer may yet succeed without it. */ if (status == GR_DOMAIN) status = _gr_poly_div_series_divconquer(Q, A, Alen, B, Blen, len, DEFAULT_CUTOFF, ctx); } return status; } int gr_poly_div_series(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(Q, ctx); if (B->length == 0) return GR_DOMAIN; if (A->length == 0) { truth_t is_zero = gr_poly_is_zero(B, ctx); if (is_zero == T_FALSE) return gr_poly_zero(Q, ctx); return GR_UNABLE; } if (Q == A || Q == B) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_div_series(t, A, B, len, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Q, len, ctx); status = _gr_poly_div_series(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, len, ctx); _gr_poly_set_length(Q, len, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_series_basecase.c000066400000000000000000000156661461254215100212410ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_div_series_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i, l; if (len == 0) return GR_SUCCESS; if (Blen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); if (Blen == 1) { status |= _gr_vec_div_scalar(Q, A, Alen, B, ctx); status |= _gr_vec_zero(GR_ENTRY(Q, Alen, sz), len - Alen, ctx); return status; } if (len == 2) { if (Alen == 1) { status |= gr_div(Q, A, B, ctx); status |= gr_div(GR_ENTRY(Q, 1, sz), Q, B, ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), GR_ENTRY(B, 1, sz), ctx); status |= gr_neg(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), ctx); } else { status |= gr_div(Q, A, B, ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), Q, GR_ENTRY(B, 1, sz), ctx); status |= gr_sub(GR_ENTRY(Q, 1, sz), GR_ENTRY(A, 1, sz), GR_ENTRY(Q, 1, sz), ctx); status |= gr_div(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), B, ctx); } return status; } status = gr_div(Q, A, B, ctx); if (status == GR_SUCCESS) { for (i = 1; i < len; i++) { l = FLINT_MIN(i, Blen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(Q, i, sz), (i < Alen) ? GR_ENTRY(A, i, sz) : NULL, 1, GR_ENTRY(B, 1, sz), GR_ENTRY(Q, i - l, sz), l, ctx); status |= gr_div(GR_ENTRY(Q, i, sz), GR_ENTRY(Q, i, sz), B, ctx); if (status != GR_SUCCESS) break; } } return status; } int _gr_poly_div_series_basecase_preinv1(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_srcptr Binv, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i, l; int is_one; if (len == 0) return GR_SUCCESS; if (Blen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); if (Blen == 1) { status |= _gr_vec_mul_scalar(Q, A, Alen, Binv, ctx); status |= _gr_vec_zero(GR_ENTRY(Q, Alen, sz), len - Alen, ctx); return status; } if (len == 2) { if (Alen == 1) { status |= gr_mul(Q, A, Binv, ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), Q, Binv, ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), GR_ENTRY(B, 1, sz), ctx); status |= gr_neg(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), ctx); } else { status |= gr_mul(Q, A, Binv, ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), Q, GR_ENTRY(B, 1, sz), ctx); status |= gr_sub(GR_ENTRY(Q, 1, sz), GR_ENTRY(A, 1, sz), GR_ENTRY(Q, 1, sz), ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), Binv, ctx); } return status; } is_one = (gr_is_one(Binv, ctx) == T_TRUE); status |= gr_mul(Q, A, Binv, ctx); for (i = 1; i < len; i++) { l = FLINT_MIN(i, Blen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(Q, i, sz), (i < Alen) ? GR_ENTRY(A, i, sz) : NULL, 1, GR_ENTRY(B, 1, sz), GR_ENTRY(Q, i - l, sz), l, ctx); if (!is_one) status |= gr_mul(GR_ENTRY(Q, i, sz), GR_ENTRY(Q, i, sz), Binv, ctx); } return status; } int _gr_poly_div_series_basecase_generic(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len == 0) return GR_SUCCESS; if (Blen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); if (Blen == 1) { status |= _gr_vec_div_scalar(Q, A, Alen, B, ctx); status |= _gr_vec_zero(GR_ENTRY(Q, Alen, sz), len - Alen, ctx); return status; } if (len == 2) { /* todo: in appropriate cases, don't do a division */ if (Alen == 1) { status |= gr_div(Q, A, B, ctx); status |= gr_div(GR_ENTRY(Q, 1, sz), Q, B, ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), GR_ENTRY(B, 1, sz), ctx); status |= gr_neg(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), ctx); } else { status |= gr_div(Q, A, B, ctx); status |= gr_mul(GR_ENTRY(Q, 1, sz), Q, GR_ENTRY(B, 1, sz), ctx); status |= gr_sub(GR_ENTRY(Q, 1, sz), GR_ENTRY(A, 1, sz), GR_ENTRY(Q, 1, sz), ctx); status |= gr_div(GR_ENTRY(Q, 1, sz), GR_ENTRY(Q, 1, sz), B, ctx); } return status; } /* useful to detect? monomial / series */ #if 0 if (_gr_vec_is_zero(A, Alen - 1, ctx) == T_TRUE) { status = _gr_poly_inv_series(GR_ENTRY(Q, Alen - 1, sz), B, Blen, len - (Alen - 1), ctx); if (status == GR_SUCCESS) { status |= _gr_vec_mul_scalar(GR_ENTRY(Q, Alen - 1, sz), GR_ENTRY(Q, Alen - 1, sz), len - (Alen - 1), GR_ENTRY(A, Alen - 1, sz), ctx); status |= _gr_vec_zero(Q, Alen - 1, ctx); return status; } else { status = GR_SUCCESS; } } #endif { gr_ptr q; GR_TMP_INIT(q, ctx); status = gr_inv(q, B, ctx); if (status == GR_SUCCESS) status = _gr_poly_div_series_basecase_preinv1(Q, A, Alen, B, Blen, q, len, ctx); else status = _gr_poly_div_series_basecase_noinv(Q, A, Alen, B, Blen, len, ctx); GR_TMP_CLEAR(q, ctx); } return status; } int gr_poly_div_series_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(Q, ctx); if (B->length == 0) return GR_DOMAIN; if (A->length == 0) { truth_t is_zero = gr_poly_is_zero(B, ctx); if (is_zero == T_FALSE) return gr_poly_zero(Q, ctx); return GR_UNABLE; } if (Q == A || Q == B) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_div_series_basecase(t, A, B, len, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Q, len, ctx); status = _gr_poly_div_series_basecase(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, len, ctx); _gr_poly_set_length(Q, len, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_series_divconquer.c000066400000000000000000000043731461254215100216430ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2019 William Hart Copyright (C) 2014, 2021, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_div_series_divconquer(gr_ptr res, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, slong cutoff, gr_ctx_t ctx) { gr_ptr Arev, Brev; slong Arevlen; int status = GR_SUCCESS; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); Arevlen = Blen + len - 1; /* todo: algorithm without zero padding */ /* todo: shallow reversals */ GR_TMP_INIT_VEC(Arev, Arevlen, ctx); GR_TMP_INIT_VEC(Brev, Blen, ctx); status |= _gr_poly_reverse(Arev, A, Alen, Arevlen, ctx); status |= _gr_poly_reverse(Brev, B, Blen, Blen, ctx); status |= _gr_poly_div_divconquer(res, Arev, Arevlen, Brev, Blen, cutoff, ctx); status |= _gr_poly_reverse(res, res, len, len, ctx); GR_TMP_CLEAR_VEC(Arev, Arevlen, ctx); GR_TMP_CLEAR_VEC(Brev, Blen, ctx); return status; } int gr_poly_div_series_divconquer(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(Q, ctx); if (B->length == 0) return GR_DOMAIN; if (A->length == 0) { truth_t is_zero = gr_poly_is_zero(B, ctx); if (is_zero == T_FALSE) return gr_poly_zero(Q, ctx); return GR_UNABLE; } if (Q == A || Q == B) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_div_series_divconquer(t, A, B, len, cutoff, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Q, len, ctx); status = _gr_poly_div_series_divconquer(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, len, cutoff, ctx); _gr_poly_set_length(Q, len, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_series_invmul.c000066400000000000000000000034721461254215100207750ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2019 William Hart Copyright (C) 2014, 2021, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_div_series_invmul(gr_ptr res, gr_srcptr B, slong Blen, gr_srcptr A, slong Alen, slong len, gr_ctx_t ctx) { gr_ptr Ainv; int status = GR_SUCCESS; GR_TMP_INIT_VEC(Ainv, len, ctx); status |= _gr_poly_inv_series(Ainv, A, Alen, len, ctx); if (status == GR_SUCCESS) status |= _gr_poly_mullow(res, Ainv, len, B, Blen, len, ctx); GR_TMP_CLEAR_VEC(Ainv, len, ctx); return status; } int gr_poly_div_series_invmul(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(Q, ctx); if (B->length == 0) return GR_DOMAIN; if (A->length == 0) { truth_t is_zero = gr_poly_is_zero(B, ctx); if (is_zero == T_FALSE) return gr_poly_zero(Q, ctx); return GR_UNABLE; } if (Q == A || Q == B) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_div_series_invmul(t, A, B, len, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Q, len, ctx); status = _gr_poly_div_series_invmul(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, len, ctx); _gr_poly_set_length(Q, len, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/div_series_newton.c000066400000000000000000000065611461254215100207770ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2019 William Hart Copyright (C) 2014, 2021, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_div_series_newton(gr_ptr res, gr_srcptr B, slong Blen, gr_srcptr A, slong Alen, slong len, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong i, m, n, Anlen, Wlen, W2len, alloc; gr_ptr W, T; slong a[FLINT_BITS]; if (len == 0) return GR_SUCCESS; if (Alen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); /* not supported by the following code */ if (Alen == 1) return _gr_poly_div_series_basecase(res, B, Blen, A, Alen, len, ctx); cutoff = FLINT_MAX(cutoff, 2); a[i = 0] = n = len; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); status |= _gr_poly_inv_series_basecase(res, A, Alen, n, ctx); if (status != GR_SUCCESS) return status; alloc = len + (len + 1) / 2; GR_TMP_INIT_VEC(W, alloc, ctx); T = GR_ENTRY(W, len, sz); for (i--; i >= 1; i--) { m = n; n = a[i]; Anlen = FLINT_MIN(Alen, n); Wlen = FLINT_MIN(Anlen + m - 1, n); W2len = Wlen - m; status |= _gr_poly_mullow(W, A, Anlen, res, m, Wlen, ctx); if (W2len != 0) status |= _gr_poly_mullow(GR_ENTRY(res, m, sz), res, m, GR_ENTRY(W, m, sz), W2len, n - m, ctx); status |= _gr_vec_neg(GR_ENTRY(res, m, sz), GR_ENTRY(res, m, sz), n - m, ctx); } m = (len + 1) / 2; n = len; Anlen = FLINT_MIN(Alen, n); Wlen = FLINT_MIN(Anlen + m - 1, n); /* Karp-Markstein */ status |= _gr_poly_mullow(T, res, m, B, Blen, m, ctx); status |= _gr_poly_mullow(W, A, Anlen, T, m, Wlen, ctx); status |= _gr_poly_sub(GR_ENTRY(W, m, sz), GR_ENTRY(B, m, sz), FLINT_MAX(0, FLINT_MIN(Blen - m, n - m)), GR_ENTRY(W, m, sz), n - m, ctx); status |= _gr_poly_mullow(GR_ENTRY(res, m, sz), res, m, GR_ENTRY(W, m, sz), n - m, n - m, ctx); _gr_vec_swap(res, T, m, ctx); GR_TMP_CLEAR_VEC(W, alloc, ctx); return status; } int gr_poly_div_series_newton(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(Q, ctx); if (B->length == 0) return GR_DOMAIN; if (A->length == 0) { truth_t is_zero = gr_poly_is_zero(B, ctx); if (is_zero == T_FALSE) return gr_poly_zero(Q, ctx); return GR_UNABLE; } if (Q == A || Q == B) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_div_series_newton(t, A, B, len, cutoff, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Q, len, ctx); status = _gr_poly_div_series_newton(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, len, cutoff, ctx); _gr_poly_set_length(Q, len, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/divexact.c000066400000000000000000000032051461254215100170500ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_divexact_generic(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { if (lenB <= 2) return _gr_poly_divexact_basecase(Q, A, lenA, B, lenB, ctx); else return _gr_poly_divexact_bidirectional(Q, A, lenA, B, lenB, ctx); } int gr_poly_divexact(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_divexact(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_divexact(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/divexact_basecase.c000066400000000000000000000061651461254215100207060ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_divexact_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong Qlen; slong i, l; if (Blen == 1) return _gr_vec_div_scalar(Q, A, Alen, B, ctx); Qlen = Alen - Blen + 1; status = gr_divexact(GR_ENTRY(Q, Qlen - 1, sz), GR_ENTRY(A, Alen - 1, sz), GR_ENTRY(B, Blen - 1, sz), ctx); for (i = 1; status == GR_SUCCESS && i < Qlen; i++) { l = FLINT_MIN(i, Blen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(A, Alen - 1 - i, sz), 1, GR_ENTRY(B, Blen - 1 - l, sz), GR_ENTRY(Q, Qlen - i, sz), l, ctx); status |= gr_divexact(GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(Q, Qlen - 1 - i, sz), GR_ENTRY(B, Blen - 1, sz), ctx); } return status; } int _gr_poly_divexact_basecase(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_ptr invB; /* note: if we wanted to be clever, we could pick a pair of coefficients such that the division is easy */ if (Alen == Blen) return gr_divexact(Q, GR_ENTRY(A, Alen - 1, sz), GR_ENTRY(B, Blen - 1, sz), ctx); GR_TMP_INIT(invB, ctx); /* todo: we sometimes want to keep dividing, e.g. over RR with small coefficient */ status = gr_inv(invB, GR_ENTRY(B, Blen - 1, sz), ctx); /* constant is a unit; can multiply by inverse */ if (status == GR_SUCCESS) status = _gr_poly_div_basecase_preinv1(Q, A, Alen, B, Blen, invB, ctx); else status = _gr_poly_divexact_basecase_noinv(Q, A, Alen, B, Blen, ctx); GR_TMP_CLEAR(invB, ctx); return status; } int gr_poly_divexact_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_divexact_basecase(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_divexact_basecase(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/divexact_bidirectional.c000066400000000000000000000111231461254215100217360ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" static int __gr_poly_divexact_bidirectional(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, int basecase, gr_ctx_t ctx) { slong lenQ, len_lo, len_hi; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; /* See if we can divide from the bottom. */ while (lenB > 1) { truth_t is_zero; is_zero = gr_is_zero(B, ctx); if (is_zero == T_FALSE) break; /* We cannot tell if the low coefficient of B is zero, so series division will not work. However, dividing from the top might still be possible. */ if (is_zero == T_UNKNOWN) { if (basecase) return _gr_poly_divexact_basecase(Q, A, lenA, B, lenB, ctx); else return _gr_poly_div(Q, A, lenA, B, lenB, ctx); } /* Discard trailing zero coefficient. B is assumed to divide A, there is a corresponding zero coefficient in A, which we don't need to check since the contract for divexact allows returning nonsense in case of an inexact division. */ B = GR_ENTRY(B, 1, sz); A = GR_ENTRY(A, 1, sz); lenB--; lenA--; } if (lenB == 1) { return _gr_vec_divexact_scalar(Q, A, lenA, B, ctx); } lenQ = lenA - lenB + 1; len_hi = lenQ / 2; len_lo = lenQ - len_hi; if (basecase) { status |= _gr_poly_divexact_series_basecase(Q, A, lenA, B, lenB, len_lo, ctx); status |= _gr_poly_divexact_basecase(GR_ENTRY(Q, len_lo, sz), GR_ENTRY(A, len_lo, sz), lenA - len_lo, B, lenB, ctx); } else { status |= _gr_poly_div_series(Q, A, lenA, B, lenB, len_lo, ctx); status |= _gr_poly_div(GR_ENTRY(Q, len_lo, sz), GR_ENTRY(A, len_lo, sz), lenA - len_lo, B, lenB, ctx); } return status; } int _gr_poly_divexact_bidirectional(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { return __gr_poly_divexact_bidirectional(Q, A, lenA, B, lenB, 0, ctx); } int _gr_poly_divexact_basecase_bidirectional(gr_ptr Q, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { return __gr_poly_divexact_bidirectional(Q, A, lenA, B, lenB, 1, ctx); } int gr_poly_divexact_bidirectional(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_divexact_bidirectional(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_divexact_bidirectional(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } int gr_poly_divexact_basecase_bidirectional(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong Alen, Blen, Qlen; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; Alen = A->length; Blen = B->length; if (Blen == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, Blen - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (Alen < Blen) return gr_poly_zero(Q, ctx); Qlen = Alen - Blen + 1; if (Q == A || Q == B) { gr_poly_t t; gr_poly_init2(t, Qlen, ctx); status = _gr_poly_divexact_bidirectional(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(Q, Qlen, ctx); status = _gr_poly_divexact_bidirectional(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(Q, Qlen, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/divexact_series_basecase.c000066400000000000000000000064311461254215100222540ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_divexact_series_basecase_noinv(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i, l; if (len == 0) return GR_SUCCESS; if (Blen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); if (Blen == 1) { status |= _gr_vec_divexact_scalar(Q, A, Alen, B, ctx); status |= _gr_vec_zero(GR_ENTRY(Q, Alen, sz), len - Alen, ctx); return status; } status = gr_divexact(Q, A, B, ctx); if (status == GR_SUCCESS) { for (i = 1; i < len; i++) { l = FLINT_MIN(i, Blen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(Q, i, sz), (i < Alen) ? GR_ENTRY(A, i, sz) : NULL, 1, GR_ENTRY(B, 1, sz), GR_ENTRY(Q, i - l, sz), l, ctx); status |= gr_divexact(GR_ENTRY(Q, i, sz), GR_ENTRY(Q, i, sz), B, ctx); if (status != GR_SUCCESS) break; } } return status; } int _gr_poly_divexact_series_basecase(gr_ptr Q, gr_srcptr A, slong Alen, gr_srcptr B, slong Blen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len == 0) return GR_SUCCESS; if (Blen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); Blen = FLINT_MIN(Blen, len); if (Blen == 1) { status |= _gr_vec_divexact_scalar(Q, A, Alen, B, ctx); status |= _gr_vec_zero(GR_ENTRY(Q, Alen, sz), len - Alen, ctx); return status; } { gr_ptr q; GR_TMP_INIT(q, ctx); status = gr_inv(q, B, ctx); if (status == GR_SUCCESS) status |= _gr_poly_div_series_basecase_preinv1(Q, A, Alen, B, Blen, q, len, ctx); else status = _gr_poly_divexact_series_basecase_noinv(Q, A, Alen, B, Blen, len, ctx); GR_TMP_CLEAR(q, ctx); } return status; } int gr_poly_divexact_series_basecase(gr_poly_t Q, const gr_poly_t A, const gr_poly_t B, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(Q, ctx); if (B->length == 0) return GR_DOMAIN; if (A->length == 0) { truth_t is_zero = gr_poly_is_zero(B, ctx); if (is_zero == T_FALSE) return gr_poly_zero(Q, ctx); return GR_UNABLE; } if (Q == A || Q == B) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_divexact_series_basecase(t, A, B, len, ctx); gr_poly_swap(Q, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Q, len, ctx); status = _gr_poly_divexact_series_basecase(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, len, ctx); _gr_poly_set_length(Q, len, ctx); _gr_poly_normalise(Q, ctx); return status; } flint-3.1.3/src/gr_poly/divrem.c000066400000000000000000000051551461254215100165350ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo: tuning */ #define DIVCONQUER_CUTOFF 10 /* todo: distinguish rings / fields */ int _gr_poly_divrem_generic(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { int status; if (lenB == 1 || lenA - lenB == 1) return _gr_poly_divrem_basecase(Q, R, A, lenA, B, lenB, ctx); status = _gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, ctx); /* Newton requires invertible lc(B); basecase and divide-and-conquer may yet succeed without it. */ if (status == GR_DOMAIN) { if (lenB <= DIVCONQUER_CUTOFF || lenA - lenB <= DIVCONQUER_CUTOFF) status = _gr_poly_divrem_basecase_noinv(Q, R, A, lenA, B, lenB, ctx); else status = _gr_poly_divrem_divconquer_noinv(Q, R, A, lenA, B, lenB, DIVCONQUER_CUTOFF, ctx); } return status; } int gr_poly_divrem(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; slong sz = ctx->sizeof_elem; gr_poly_t tQ, tR; gr_ptr q, r; int status = GR_SUCCESS; if (lenB == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, lenB - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (lenA < lenB) { status |= gr_poly_set(R, A, ctx); status |= gr_poly_zero(Q, ctx); return status; } if (Q == A || Q == B) { gr_poly_init2(tQ, lenQ, ctx); q = tQ->coeffs; } else { gr_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { gr_poly_init2(tR, lenB - 1, ctx); r = tR->coeffs; } else { gr_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } status |= _gr_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, ctx); if (Q == A || Q == B) { gr_poly_swap(tQ, Q, ctx); gr_poly_clear(tQ, ctx); } if (R == B) { gr_poly_swap(tR, R, ctx); gr_poly_clear(tR, ctx); } _gr_poly_set_length(Q, lenQ, ctx); _gr_poly_set_length(R, lenB - 1, ctx); _gr_poly_normalise(R, ctx); return status; } flint-3.1.3/src/gr_poly/divrem_basecase.c000066400000000000000000000106111461254215100203540ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_divrem_basecase_preinv1(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ptr W; slong iQ, iR; if (R != A) { /* cannot use R as it might not have enough space */ GR_TMP_INIT_VEC(W, lenA, ctx); status |= _gr_vec_set(W, A, lenA, ctx); } else { W = R; } for (iQ = lenA - lenB, iR = lenA - 1; iQ >= 0; iQ--, iR--) { if (gr_is_zero(GR_ENTRY(W, iR, sz), ctx) == T_TRUE) { status |= gr_zero(GR_ENTRY(Q, iQ, sz), ctx); } else { status |= gr_mul(GR_ENTRY(Q, iQ, sz), GR_ENTRY(W, iR, sz), invB, ctx); status |= _gr_vec_submul_scalar(GR_ENTRY(W, iQ, sz), B, lenB, GR_ENTRY(Q, iQ, sz), ctx); } } if (R != A) { _gr_vec_swap(R, W, lenB - 1, ctx); GR_TMP_CLEAR_VEC(W, lenA, ctx); } return status; } int _gr_poly_divrem_basecase_noinv(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ptr W; slong iQ, iR; if (R != A) { /* cannot use R as it might not have enough space */ GR_TMP_INIT_VEC(W, lenA, ctx); status |= _gr_vec_set(W, A, lenA, ctx); } else { W = R; } for (iQ = lenA - lenB, iR = lenA - 1; iQ >= 0; iQ--, iR--) { if (gr_is_zero(GR_ENTRY(W, iR, sz), ctx) == T_TRUE) { status |= gr_zero(GR_ENTRY(Q, iQ, sz), ctx); } else { status |= gr_div(GR_ENTRY(Q, iQ, sz), GR_ENTRY(W, iR, sz), GR_ENTRY(B, lenB - 1, sz), ctx); if (status != GR_SUCCESS) break; status |= _gr_vec_submul_scalar(GR_ENTRY(W, iQ, sz), B, lenB, GR_ENTRY(Q, iQ, sz), ctx); } } if (R != A) { _gr_vec_swap(R, W, lenB - 1, ctx); GR_TMP_CLEAR_VEC(W, lenA, ctx); } return status; } int _gr_poly_divrem_basecase(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ptr invB; GR_TMP_INIT(invB, ctx); status = gr_inv(invB, GR_ENTRY(B, lenB - 1, sz), ctx); if (status == GR_SUCCESS) status = _gr_poly_divrem_basecase_preinv1(Q, R, A, lenA, B, lenB, invB, ctx); else status = _gr_poly_divrem_basecase_noinv(Q, R, A, lenA, B, lenB, ctx); GR_TMP_CLEAR(invB, ctx); return status; } int gr_poly_divrem_basecase(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; slong sz = ctx->sizeof_elem; gr_poly_t tQ, tR; gr_ptr q, r; int status = GR_SUCCESS; if (lenB == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, lenB - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (lenA < lenB) { status |= gr_poly_set(R, A, ctx); status |= gr_poly_zero(Q, ctx); return status; } if (Q == A || Q == B) { gr_poly_init2(tQ, lenQ, ctx); q = tQ->coeffs; } else { gr_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { gr_poly_init2(tR, lenB - 1, ctx); r = tR->coeffs; } else { gr_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } status |= _gr_poly_divrem_basecase(q, r, A->coeffs, lenA, B->coeffs, lenB, ctx); if (Q == A || Q == B) { gr_poly_swap(tQ, Q, ctx); gr_poly_clear(tQ, ctx); } if (R == B) { gr_poly_swap(tR, R, ctx); gr_poly_clear(tR, ctx); } _gr_poly_set_length(Q, lenQ, ctx); _gr_poly_set_length(R, lenB - 1, ctx); _gr_poly_normalise(R, ctx); return status; } flint-3.1.3/src/gr_poly/divrem_divconquer.c000066400000000000000000000226621461254215100207760ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_divrem_divconquer_recursive(gr_ptr Q, gr_ptr BQ, gr_ptr W, gr_srcptr A, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (lenB < FLINT_MAX(2, cutoff)) { status |= _gr_vec_zero(BQ, lenB - 1, ctx); status |= _gr_vec_set(GR_ENTRY(BQ, lenB - 1, sz), GR_ENTRY(A, lenB - 1, sz), lenB, ctx); if (invB == NULL) status |= _gr_poly_divrem_basecase_noinv(Q, BQ, BQ, 2 * lenB - 1, B, lenB, ctx); else status |= _gr_poly_divrem_basecase_preinv1(Q, BQ, BQ, 2 * lenB - 1, B, lenB, invB, ctx); status |= _gr_vec_neg(BQ, BQ, lenB - 1, ctx); status |= _gr_vec_set(GR_ENTRY(BQ, lenB - 1, sz), GR_ENTRY(A, lenB - 1, sz), lenB, ctx); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; gr_ptr W1 = W; gr_ptr W2 = GR_ENTRY(W, lenB, sz); gr_srcptr p1 = GR_ENTRY(A, 2 * n2, sz); gr_srcptr p2; gr_srcptr d1 = GR_ENTRY(B, n2, sz); gr_srcptr d2 = B; gr_srcptr d3 = GR_ENTRY(B, n1, sz); gr_srcptr d4 = B; gr_ptr q1 = GR_ENTRY(Q, n2, sz); gr_ptr q2 = Q; gr_ptr dq1 = GR_ENTRY(BQ, n2, sz); gr_ptr d1q1 = GR_ENTRY(BQ, 2 * n2, sz); gr_ptr d2q1, d3q2, d4q2, t; /* Set q1 to p1 div d1, a 2 n1 - 1 by n1 division so q1 ends up being of length n1; d1q1 = d1 q1 is of length 2 n1 - 1 */ status |= _gr_poly_divrem_divconquer_recursive(q1, d1q1, W1, p1, d1, n1, invB, cutoff, ctx); /* Compute d2q1 = d2 q1, of length lenB - 1 */ d2q1 = W1; status |= _gr_poly_mul(d2q1, q1, n1, d2, n2, ctx); /* Compute dq1 = d1 q1 x^n2 + d2 q1, of length 2 n1 + n2 - 1 */ _gr_vec_swap(dq1, d2q1, n2, ctx); status |= _gr_poly_add(GR_ENTRY(dq1, n2, sz), GR_ENTRY(dq1, n2, sz), n1 - 1, GR_ENTRY(d2q1, n2, sz), n1 - 1, ctx); /* Compute t = A/x^n2 - dq1, which has length 2 n1 + n2 - 1, but we are not interested in the top n1 coeffs as they will be zero, so this has effective length n1 + n2 - 1 For the following division, we want to set {p2, 2 n2 - 1} to the top 2 n2 - 1 coeffs of this Since the bottom n2 - 1 coeffs of p2 are irrelevant for the division, we in fact set {t, n2} to the relevant coeffs */ t = BQ; status |= _gr_poly_sub(t, GR_ENTRY(A, n2 + (n1 - 1), sz), n2, GR_ENTRY(dq1, (n1 - 1), sz), n2, ctx); p2 = GR_ENTRY(t, - (n2 - 1), sz); /* Compute q2 = t div d3, a 2 n2 - 1 by n2 division, so q2 will have length n2; let d3q2 = d3 q2, of length 2 n2 - 1 */ d3q2 = W1; status |= _gr_poly_divrem_divconquer_recursive(q2, d3q2, W2, p2, d3, n2, invB, cutoff, ctx); /* Compute d4q2 = d4 q2, of length n1 + n2 - 1 = lenB - 1 */ d4q2 = W2; status |= _gr_poly_mul(d4q2, d4, n1, q2, n2, ctx); /* Compute dq2 = d3q2 x^n1 + d4q2, of length n1 + 2 n2 - 1 */ _gr_vec_swap(BQ, d4q2, n2, ctx); status |= _gr_poly_add(GR_ENTRY(BQ, n2, sz), GR_ENTRY(BQ, n2, sz), n1 - 1, GR_ENTRY(d4q2, n2, sz), n1 - 1, ctx); status |= _gr_poly_add(GR_ENTRY(BQ, n1, sz), GR_ENTRY(BQ, n1, sz), 2 * n2 - 1, d3q2, 2 * n2 - 1, ctx); /* Note Q = q1 x^n2 + q2, and BQ = dq1 x^n2 + dq2 */ } return status; } static int __gr_poly_divrem_divconquer(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (lenA < 2 * lenB - 1) { /* Convert unbalanced division into a 2 n1 - 1 by n1 division */ const slong n1 = lenA - lenB + 1; const slong n2 = lenB - n1; gr_srcptr p1 = GR_ENTRY(A, n2, sz); gr_srcptr d1 = GR_ENTRY(B, n2, sz); gr_srcptr d2 = B; gr_ptr W, d1q1, d2q1; GR_TMP_INIT_VEC(W, (2 * n1 - 1) + lenB - 1, ctx); d1q1 = GR_ENTRY(R, n2, sz); d2q1 = GR_ENTRY(W, (2 * n1 - 1), sz); status |= _gr_poly_divrem_divconquer_recursive(Q, d1q1, W, p1, d1, n1, invB, cutoff, ctx); /* Compute d2q1 = Q d2, of length lenB - 1 */ if (n1 >= n2) status |= _gr_poly_mul(d2q1, Q, n1, d2, n2, ctx); else status |= _gr_poly_mul(d2q1, d2, n2, Q, n1, ctx); /* Compute BQ = d1q1 * x^n1 + d2q1, of length lenB - 1; then compute R = A - BQ */ _gr_vec_swap(R, d2q1, n2, ctx); status |= _gr_poly_add(GR_ENTRY(R, n2, sz), GR_ENTRY(R, n2, sz), n1 - 1, GR_ENTRY(d2q1, n2, sz), n1 - 1, ctx); status |= _gr_poly_sub(R, A, lenA, R, lenA, ctx); GR_TMP_CLEAR_VEC(W, (2 * n1 - 1) + lenB - 1, ctx); } else /* lenA = 2 * lenB - 1 */ { gr_ptr W; GR_TMP_INIT_VEC(W, lenA, ctx); status |= _gr_poly_divrem_divconquer_recursive(Q, R, W, A, B, lenB, invB, cutoff, ctx); status |= _gr_poly_sub(R, A, lenB - 1, R, lenB - 1, ctx); GR_TMP_CLEAR_VEC(W, lenA, ctx); } return status; } int _gr_poly_divrem_divconquer_preinv1(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_srcptr invB, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (lenA <= 2 * lenB - 1) { gr_ptr W; /* todo: the fq version avoids this temporary, writing directly to R */ GR_TMP_INIT_VEC(W, lenA, ctx); status |= __gr_poly_divrem_divconquer(Q, W, A, lenA, B, lenB, invB, cutoff, ctx); _gr_vec_swap(R, W, lenB - 1, ctx); GR_TMP_CLEAR_VEC(W, lenA, ctx); } else /* lenA > 2 * lenB - 1 */ { slong shift, n = 2 * lenB - 1, len1; gr_ptr QB, W, S; len1 = 2 * n + lenA; GR_TMP_INIT_VEC(W, len1, ctx); S = GR_ENTRY(W, 2 * n, sz); status |= _gr_vec_set(S, A, lenA, ctx); QB = GR_ENTRY(W, n, sz); while (lenA >= n) { shift = lenA - n; status |= _gr_poly_divrem_divconquer_recursive(GR_ENTRY(Q, shift, sz), QB, W, GR_ENTRY(S, shift, sz), B, lenB, invB, cutoff, ctx); status |= _gr_poly_sub(GR_ENTRY(S, shift, sz), GR_ENTRY(S, shift, sz), n, QB, n, ctx); lenA -= lenB; } if (lenA >= lenB) { status |= __gr_poly_divrem_divconquer(Q, W, S, lenA, B, lenB, invB, cutoff, ctx); _gr_vec_swap(W, S, lenA, ctx); } _gr_vec_swap(R, S, lenB - 1, ctx); GR_TMP_CLEAR_VEC(W, len1, ctx); } return status; } int _gr_poly_divrem_divconquer_noinv(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) { return _gr_poly_divrem_divconquer_preinv1(Q, R, A, lenA, B, lenB, NULL, cutoff, ctx); } int _gr_poly_divrem_divconquer(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ptr invB; GR_TMP_INIT(invB, ctx); status = gr_inv(invB, GR_ENTRY(B, lenB - 1, sz), ctx); if (status == GR_SUCCESS) status = _gr_poly_divrem_divconquer_preinv1(Q, R, A, lenA, B, lenB, invB, cutoff, ctx); else status = _gr_poly_divrem_divconquer_noinv(Q, R, A, lenA, B, lenB, cutoff, ctx); GR_TMP_CLEAR(invB, ctx); return status; } int gr_poly_divrem_divconquer(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, slong cutoff, gr_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; slong sz = ctx->sizeof_elem; gr_poly_t tQ, tR; gr_ptr q, r; int status = GR_SUCCESS; if (lenB == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, lenB - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (lenA < lenB) { status |= gr_poly_set(R, A, ctx); status |= gr_poly_zero(Q, ctx); return status; } if (Q == A || Q == B) { gr_poly_init2(tQ, lenQ, ctx); q = tQ->coeffs; } else { gr_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { gr_poly_init2(tR, lenB - 1, ctx); r = tR->coeffs; } else { gr_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } status |= _gr_poly_divrem_divconquer(q, r, A->coeffs, lenA, B->coeffs, lenB, cutoff, ctx); if (Q == A || Q == B) { gr_poly_swap(tQ, Q, ctx); gr_poly_clear(tQ, ctx); } if (R == B) { gr_poly_swap(tR, R, ctx); gr_poly_clear(tR, ctx); } _gr_poly_set_length(Q, lenQ, ctx); _gr_poly_set_length(R, lenB - 1, ctx); _gr_poly_normalise(R, ctx); return status; } flint-3.1.3/src/gr_poly/divrem_newton.c000066400000000000000000000051641461254215100201270ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_divrem_newton(gr_ptr Q, gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { int status = GR_SUCCESS; const slong lenQ = lenA - lenB + 1; status |= _gr_poly_div_newton(Q, A, lenA, B, lenB, ctx); if (lenB > 1 && status == GR_SUCCESS) { if (R == A) { gr_ptr W; GR_TMP_INIT_VEC(W, lenB - 1, ctx); status |= _gr_poly_mullow(W, Q, lenQ, B, lenB - 1, lenB - 1, ctx); status |= _gr_vec_sub(R, A, W, lenB - 1, ctx); GR_TMP_CLEAR_VEC(W, lenB - 1, ctx); } else { status |= _gr_poly_mullow(R, Q, lenQ, B, lenB - 1, lenB - 1, ctx); status |= _gr_vec_sub(R, A, R, lenB - 1, ctx); } } return status; } int gr_poly_divrem_newton(gr_poly_t Q, gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; slong sz = ctx->sizeof_elem; gr_poly_t tQ, tR; gr_ptr q, r; int status = GR_SUCCESS; if (lenB == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, lenB - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (lenA < lenB) { status |= gr_poly_set(R, A, ctx); status |= gr_poly_zero(Q, ctx); return status; } if (Q == A || Q == B) { gr_poly_init2(tQ, lenQ, ctx); q = tQ->coeffs; } else { gr_poly_fit_length(Q, lenQ, ctx); q = Q->coeffs; } if (R == B) { gr_poly_init2(tR, lenB - 1, ctx); r = tR->coeffs; } else { gr_poly_fit_length(R, lenB - 1, ctx); r = R->coeffs; } status |= _gr_poly_divrem_newton(q, r, A->coeffs, lenA, B->coeffs, lenB, ctx); if (Q == A || Q == B) { gr_poly_swap(tQ, Q, ctx); gr_poly_clear(tQ, ctx); } else { _gr_poly_set_length(Q, lenQ, ctx); } if (R == B) { gr_poly_swap(tR, R, ctx); gr_poly_clear(tR, ctx); } _gr_poly_set_length(Q, lenQ, ctx); _gr_poly_set_length(R, lenB - 1, ctx); _gr_poly_normalise(R, ctx); return status; } flint-3.1.3/src/gr_poly/equal.c000066400000000000000000000021531461254215100163510ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" truth_t _gr_poly_equal(gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { truth_t eq, eq2; slong sz = ctx->sizeof_elem; eq = _gr_vec_equal(poly1, poly2, len2, ctx); if (len1 == len2 || eq == T_FALSE) return eq; eq2 = _gr_vec_is_zero(GR_ENTRY(poly1, len2, sz), len1 - len2, ctx); return truth_and(eq, eq2); } truth_t gr_poly_equal(const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { slong len1 = poly1->length; slong len2 = poly2->length; if (len1 >= len2) return _gr_poly_equal(poly1->coeffs, len1, poly2->coeffs, len2, ctx); else return _gr_poly_equal(poly2->coeffs, len2, poly1->coeffs, len1, ctx); } flint-3.1.3/src/gr_poly/evaluate.c000066400000000000000000000012771461254215100170560ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_evaluate(gr_ptr y, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t ctx) { return _gr_poly_evaluate_horner(y, f, len, x, ctx); } int gr_poly_evaluate(gr_ptr res, const gr_poly_t f, gr_srcptr a, gr_ctx_t ctx) { return _gr_poly_evaluate(res, f->coeffs, f->length, a, ctx); } flint-3.1.3/src/gr_poly/evaluate_horner.c000066400000000000000000000027551461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_evaluate_horner(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) { return gr_zero(res, ctx); } else if (len == 1 || gr_is_zero(x, ctx) == T_TRUE) { return gr_set(res, f, ctx); } else if (len == 2) { slong sz = ctx->sizeof_elem; status |= gr_mul(res, x, GR_ENTRY(f, 1, sz), ctx); status |= gr_add(res, res, f, ctx); return status; } else { slong i = len - 1; slong sz = ctx->sizeof_elem; gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_set(u, GR_ENTRY(f, i, sz), ctx); for (i = len - 2; i >= 0; i--) { status |= gr_mul(t, u, x, ctx); status |= gr_add(u, GR_ENTRY(f, i, sz), t, ctx); } gr_swap(res, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } } int gr_poly_evaluate_horner(gr_ptr res, const gr_poly_t f, gr_srcptr a, gr_ctx_t ctx) { return _gr_poly_evaluate_horner(res, f->coeffs, f->length, a, ctx); } flint-3.1.3/src/gr_poly/evaluate_modular.c000066400000000000000000000046211461254215100205750ustar00rootroot00000000000000/* Copyright (C) 2023 David Berghaus This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_evaluate_modular(gr_ptr y, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_method_void_unary_op set_shallow = GR_VOID_UNARY_OP(ctx, SET_SHALLOW); if (len <= 2) { if (len == 0) return gr_zero(y, ctx); if (len == 1) return gr_set(y, poly, ctx); status |= gr_mul(y, x, GR_ENTRY(poly, 1, sz), ctx); status |= gr_add(y, y, GR_ENTRY(poly, 0, sz), ctx); } else { slong i, j, k, coeff_index, l, m; gr_ptr xs, ys, tmp, partial_results; k = n_sqrt(len)+1; j = (len + k - 1) / k; TMP_INIT; TMP_START; tmp = TMP_ALLOC(sz * k); GR_TMP_INIT_VEC(xs, j + 1, ctx); GR_TMP_INIT_VEC(ys, k, ctx); GR_TMP_INIT_VEC(partial_results, j, ctx); status |= _gr_vec_set_powers(xs, x, j + 1, ctx); status |= _gr_vec_set_powers(ys, GR_ENTRY(xs, j, sz), k, ctx); for (l = 0; l < j; l++) { i = 0; /* Count number of coeffs in this row */ for (m = 0; m < k; m++) { coeff_index = j*m+l; if (coeff_index < len) { set_shallow(GR_ENTRY(tmp, m, sz), GR_ENTRY(poly, coeff_index, sz), ctx); i++; } else { break; } } status |= _gr_vec_dot(GR_ENTRY(partial_results, l, sz), NULL, 0, tmp, ys, i, ctx); } status |=_gr_vec_dot(y, NULL, 0, partial_results, xs, j, ctx); GR_TMP_CLEAR_VEC(xs, j + 1, ctx); GR_TMP_CLEAR_VEC(ys, k, ctx); GR_TMP_CLEAR_VEC(partial_results, j, ctx); TMP_END; } return status; } int gr_poly_evaluate_modular(gr_ptr res, const gr_poly_t f, gr_srcptr x, gr_ctx_t ctx) { return _gr_poly_evaluate_modular(res, f->coeffs, f->length, x, ctx); } flint-3.1.3/src/gr_poly/evaluate_other.c000066400000000000000000000014111461254215100202450ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_evaluate_other(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { return _gr_poly_evaluate_other_horner(res, f, len, x, x_ctx, ctx); } int gr_poly_evaluate_other(gr_ptr res, const gr_poly_t f, gr_srcptr a, gr_ctx_t a_ctx, gr_ctx_t ctx) { return _gr_poly_evaluate_other(res, f->coeffs, f->length, a, a_ctx, ctx); } flint-3.1.3/src/gr_poly/evaluate_other_horner.c000066400000000000000000000031631461254215100216300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_evaluate_other_horner(gr_ptr res, gr_srcptr f, slong len, const gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) { return gr_zero(res, x_ctx); } else if (len == 1 || gr_is_zero(x, x_ctx) == T_TRUE) { return gr_set_other(res, f, ctx, x_ctx); } else if (len == 2) { slong sz = ctx->sizeof_elem; status |= gr_mul_other(res, x, GR_ENTRY(f, 1, sz), ctx, x_ctx); status |= gr_add_other(res, res, f, ctx, x_ctx); return status; } else { slong i = len - 1; slong sz = ctx->sizeof_elem; gr_ptr t, u; GR_TMP_INIT2(t, u, x_ctx); status |= gr_set_other(u, GR_ENTRY(f, i, sz), ctx, x_ctx); for (i = len - 2; i >= 0; i--) { status |= gr_mul(t, u, x, x_ctx); status |= gr_add_other(u, t, GR_ENTRY(f, i, sz), ctx, x_ctx); } gr_swap(res, u, x_ctx); GR_TMP_CLEAR2(t, u, x_ctx); return status; } } int gr_poly_evaluate_other_horner(gr_ptr res, const gr_poly_t f, gr_srcptr a, gr_ctx_t a_ctx, gr_ctx_t ctx) { return _gr_poly_evaluate_other_horner(res, f->coeffs, f->length, a, a_ctx, ctx); } flint-3.1.3/src/gr_poly/evaluate_other_rectangular.c000066400000000000000000000064051461254215100226440ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" /* todo: move me */ int gr_dot_other(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx2, gr_ctx_t ctx) { int status; slong i, sz, sz2; gr_ptr t; if (len <= 0) { if (initial == NULL) return gr_zero(res, ctx); else return gr_set(res, initial, ctx); } sz = ctx->sizeof_elem; sz2 = ctx2->sizeof_elem; status = GR_SUCCESS; GR_TMP_INIT(t, ctx); if (initial == NULL) { status |= gr_mul_other(res, vec1, vec2, ctx2, ctx); } else { if (subtract) status |= gr_neg(res, initial, ctx); else status |= gr_set(res, initial, ctx); status |= gr_mul_other(t, vec1, vec2, ctx2, ctx); status |= gr_add(res, res, t, ctx); } for (i = 1; i < len; i++) { status |= gr_mul_other(t, GR_ENTRY(vec1, i, sz), GR_ENTRY(vec2, i, sz2), ctx2, ctx); status |= gr_add(res, res, t, ctx); } if (subtract) status |= gr_neg(res, res, ctx); GR_TMP_CLEAR(t, ctx); return status; } int _gr_poly_evaluate_other_rectangular(gr_ptr y, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; slong x_sz = x_ctx->sizeof_elem; int status = GR_SUCCESS; if (len <= 2) { if (len == 0) return gr_zero(y, x_ctx); if (len == 1) return gr_set_other(y, poly, ctx, x_ctx); status |= gr_mul_other(y, x, GR_ENTRY(poly, 1, sz), ctx, x_ctx); status |= gr_add_other(y, y, GR_ENTRY(poly, 0, sz), ctx, x_ctx); return status; } else { slong i, m, r; gr_ptr xs; gr_ptr s, t, c; m = n_sqrt(len) + 1; r = (len + m - 1) / m; GR_TMP_INIT_VEC(xs, m + 1, x_ctx); GR_TMP_INIT3(s, t, c, x_ctx); status |= _gr_vec_set_powers(xs, x, m + 1, x_ctx); status |= gr_dot_other(y, NULL, 0, GR_ENTRY(xs, 1, x_sz), GR_ENTRY(poly, (r - 1) * m + 1, sz), len - (r - 1) * m - 1, ctx, x_ctx); status |= gr_add_other(y, y, GR_ENTRY(poly, (r - 1) * m, sz), ctx, x_ctx); for (i = r - 2; i >= 0; i--) { status |= gr_dot_other(s, NULL, 0, GR_ENTRY(xs, 1, x_sz), GR_ENTRY(poly, i * m + 1, sz), m - 1, ctx, x_ctx); status |= gr_add_other(s, s, GR_ENTRY(poly, i * m, sz), ctx, x_ctx); status |= gr_mul(y, y, GR_ENTRY(xs, m, x_sz), x_ctx); status |= gr_add(y, y, s, x_ctx); } GR_TMP_CLEAR_VEC(xs, m + 1, x_ctx); GR_TMP_CLEAR3(s, t, c, x_ctx); return status; } } int gr_poly_evaluate_other_rectangular(gr_ptr res, const gr_poly_t f, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx) { return _gr_poly_evaluate_other_rectangular(res, f->coeffs, f->length, x, x_ctx, ctx); } flint-3.1.3/src/gr_poly/evaluate_rectangular.c000066400000000000000000000036451461254215100214460ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_evaluate_rectangular(gr_ptr y, gr_srcptr poly, slong len, gr_srcptr x, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (len <= 2) { if (len == 0) return gr_zero(y, ctx); if (len == 1) return gr_set(y, poly, ctx); status |= gr_mul(y, x, GR_ENTRY(poly, 1, sz), ctx); status |= gr_add(y, y, GR_ENTRY(poly, 0, sz), ctx); return status; } else { slong i, m, r; gr_ptr xs; gr_ptr s, t, c; m = n_sqrt(len) + 1; r = (len + m - 1) / m; GR_TMP_INIT_VEC(xs, m + 1, ctx); GR_TMP_INIT3(s, t, c, ctx); status |= _gr_vec_set_powers(xs, x, m + 1, ctx); status |= _gr_vec_dot(y, GR_ENTRY(poly, (r - 1) * m, sz), 0, GR_ENTRY(xs, 1, sz), GR_ENTRY(poly, (r - 1) * m + 1, sz), len - (r - 1) * m - 1, ctx); for (i = r - 2; i >= 0; i--) { status |= _gr_vec_dot(s, GR_ENTRY(poly, i * m, sz), 0, GR_ENTRY(xs, 1, sz), GR_ENTRY(poly, i * m + 1, sz), m - 1, ctx); status |= gr_mul(y, y, GR_ENTRY(xs, m, sz), ctx); status |= gr_add(y, y, s, ctx); } GR_TMP_CLEAR_VEC(xs, m + 1, ctx); GR_TMP_CLEAR3(s, t, c, ctx); return status; } } int gr_poly_evaluate_rectangular(gr_ptr res, const gr_poly_t f, gr_srcptr x, gr_ctx_t ctx) { return _gr_poly_evaluate_rectangular(res, f->coeffs, f->length, x, ctx); } flint-3.1.3/src/gr_poly/evaluate_vec_fast.c000066400000000000000000000170061461254215100207250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: multithread */ gr_ptr * _gr_poly_tree_alloc(slong len, gr_ctx_t ctx) { gr_ptr * tree = NULL; if (len) { slong i, height = FLINT_CLOG2(len); tree = flint_malloc(sizeof(gr_ptr) * (height + 1)); for (i = 0; i <= height; i++) { slong n = len + (len >> i) + 1; tree[i] = flint_malloc(n * ctx->sizeof_elem); _gr_vec_init(tree[i], n, ctx); } } return tree; } void _gr_poly_tree_free(gr_ptr * tree, slong len, gr_ctx_t ctx) { if (len) { slong i, height = FLINT_CLOG2(len); for (i = 0; i <= height; i++) { slong n = len + (len >> i) + 1; _gr_vec_clear(tree[i], n, ctx); flint_free(tree[i]); } flint_free(tree); } } int _gr_poly_mul_monic(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len1 + len2 - 2 > 0) status |= _gr_poly_mullow(res, poly1, len1, poly2, len2, len1 + len2 - 2, ctx); status |= gr_one(GR_ENTRY(res, len1 + len2 - 2, ctx->sizeof_elem), ctx); return status; } int _gr_poly_tree_build(gr_ptr * tree, gr_srcptr roots, slong len, gr_ctx_t ctx) { slong height, pow, left, i; gr_ptr pa, pb; gr_srcptr a, b; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (len == 0) return GR_SUCCESS; height = FLINT_CLOG2(len); /* zeroth level, (x-a) */ for (i = 0; i < len; i++) { status |= gr_one(GR_ENTRY(tree[0], 2 * i + 1, sz), ctx); status |= gr_neg(GR_ENTRY(tree[0], 2 * i, sz), GR_ENTRY(roots, i, sz), ctx); } /* first level, (x-a)(x-b) = x^2 + (-a-b)*x + a*b */ if (height > 1) { pa = tree[1]; for (i = 0; i < len / 2; i++) { a = GR_ENTRY(roots, 2 * i, sz); b = GR_ENTRY(roots, 2 * i + 1, sz); status |= gr_mul(GR_ENTRY(pa, (3 * i), sz), a, b, ctx); status |= gr_add(GR_ENTRY(pa, (3 * i + 1), sz), a, b, ctx); status |= gr_neg(GR_ENTRY(pa, (3 * i + 1), sz), GR_ENTRY(pa, (3 * i + 1), sz), ctx); status |= gr_one(GR_ENTRY(pa, (3 * i + 2), sz), ctx); } if (len & 1) { status |= gr_neg(GR_ENTRY(pa, 3 * (len / 2), sz), GR_ENTRY(roots, len - 1, sz), ctx); status |= gr_one(GR_ENTRY(pa, 3 * (len / 2) + 1, sz), ctx); } } for (i = 1; i < height - 1; i++) { left = len; pow = WORD(1) << i; pa = tree[i]; pb = tree[i + 1]; while (left >= 2 * pow) { status |= _gr_poly_mul_monic(pb, pa, pow + 1, GR_ENTRY(pa, pow + 1, sz), pow + 1, ctx); left -= 2 * pow; pa = GR_ENTRY(pa, 2 * pow + 2, sz); pb = GR_ENTRY(pb, 2 * pow + 1, sz); } if (left > pow) { status |= _gr_poly_mul_monic(pb, pa, pow + 1, GR_ENTRY(pa, pow + 1, sz), left - pow + 1, ctx); } else if (left > 0) { status |= _gr_vec_set(pb, pa, left + 1, ctx); } } return status; } /* This gives some speedup for small lengths. */ static inline int _gr_poly_rem_2(gr_ptr q, gr_ptr r, gr_srcptr a, slong al, gr_srcptr b, slong bl, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (al == 2) { status |= gr_mul(r, GR_ENTRY(a, 1, sz), b, ctx); status |= gr_sub(r, a, r, ctx); } else { status |= _gr_poly_divrem(q, r, a, al, b, bl, ctx); } return status; } int _gr_poly_evaluate_vec_fast_precomp(gr_ptr vs, gr_srcptr poly, slong plen, gr_ptr * tree, slong len, gr_ctx_t ctx) { slong height, i, j, pow, left; slong tree_height; slong tlen, alloc, qalloc; gr_ptr tmp, q, t, u, swap, pa, pb, pc; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; /* avoid worrying about some degenerate cases */ if (len < 2 || plen < 2) { if (len == 1) { gr_ptr tmp; GR_TMP_INIT(tmp, ctx); status |= gr_neg(tmp, tree[0], ctx); status |= _gr_poly_evaluate(vs, poly, plen, tmp, ctx); GR_TMP_CLEAR(tmp, ctx); } else if (len != 0 && plen == 0) { status |= _gr_vec_zero(vs, len, ctx); } else if (len != 0 && plen == 1) { for (i = 0; i < len; i++) status |= gr_set(GR_ENTRY(vs, i, sz), poly, ctx); } return status; } left = len; /* Initial reduction. We allow the polynomial to be larger or smaller than the number of points. */ height = FLINT_BIT_COUNT(plen - 1) - 1; tree_height = FLINT_CLOG2(len); while (height >= tree_height) height--; pow = WORD(1) << height; /* Maximum temp space for q (todo: could use dedicated rem instead of divrem methods where more efficient). */ qalloc = pow; for (i = j = 0; i < len; i += pow, j += (pow + 1)) { tlen = ((i + pow) <= len) ? pow : len % pow; qalloc = FLINT_MAX(qalloc, plen - tlen); } alloc = 2 * len + qalloc; GR_TMP_INIT_VEC(tmp, alloc, ctx); t = tmp; u = GR_ENTRY(t, len, sz); q = GR_ENTRY(u, len, sz); for (i = j = 0; i < len; i += pow, j += (pow + 1)) { tlen = ((i + pow) <= len) ? pow : len % pow; status |= _gr_poly_divrem(q, GR_ENTRY(t, i, sz), poly, plen, GR_ENTRY(tree[height], j, sz), tlen + 1, ctx); } for (i = height - 1; i >= 0; i--) { pow = WORD(1) << i; left = len; pa = tree[i]; pb = t; pc = u; while (left >= 2 * pow) { status |= _gr_poly_rem_2(q, pc, pb, 2 * pow, pa, pow + 1, ctx); status |= _gr_poly_rem_2(q, GR_ENTRY(pc, pow, sz), pb, 2 * pow, GR_ENTRY(pa, pow + 1, sz), pow + 1, ctx); pa = GR_ENTRY(pa, 2 * pow + 2, sz); pb = GR_ENTRY(pb, 2 * pow, sz); pc = GR_ENTRY(pc, 2 * pow, sz); left -= 2 * pow; } if (left > pow) { status |= _gr_poly_divrem(q, pc, pb, left, pa, pow + 1, ctx); status |= _gr_poly_divrem(q, GR_ENTRY(pc, pow, sz), pb, left, GR_ENTRY(pa, pow + 1, sz), left - pow + 1, ctx); } else if (left > 0) status |= _gr_vec_set(pc, pb, left, ctx); swap = t; t = u; u = swap; } _gr_vec_swap(vs, t, len, ctx); GR_TMP_CLEAR_VEC(tmp, alloc, ctx); return status; } int _gr_poly_evaluate_vec_fast(gr_ptr ys, gr_srcptr poly, slong plen, gr_srcptr xs, slong n, gr_ctx_t ctx) { gr_ptr * tree; int status = GR_SUCCESS; tree = _gr_poly_tree_alloc(n, ctx); status |= _gr_poly_tree_build(tree, xs, n, ctx); status |= _gr_poly_evaluate_vec_fast_precomp(ys, poly, plen, tree, n, ctx); _gr_poly_tree_free(tree, n, ctx); return status; } int gr_poly_evaluate_vec_fast(gr_vec_t ys, const gr_poly_t poly, const gr_vec_t xs, gr_ctx_t ctx) { gr_vec_set_length(ys, xs->length, ctx); return _gr_poly_evaluate_vec_fast(ys->entries, poly->coeffs, poly->length, xs->entries, xs->length, ctx); } flint-3.1.3/src/gr_poly/evaluate_vec_iter.c000066400000000000000000000017651461254215100207400ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_evaluate_vec_iter(gr_ptr ys, gr_srcptr poly, slong plen, gr_srcptr xs, slong n, gr_ctx_t ctx) { slong i; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; for (i = 0; i < n; i++) status |= _gr_poly_evaluate(GR_ENTRY(ys, i, sz), poly, plen, GR_ENTRY(xs, i, sz), ctx); return status; } int gr_poly_evaluate_vec_iter(gr_vec_t ys, const gr_poly_t poly, const gr_vec_t xs, gr_ctx_t ctx) { gr_vec_set_length(ys, xs->length, ctx); return _gr_poly_evaluate_vec_iter(ys->entries, poly->coeffs, poly->length, xs->entries, xs->length, ctx); } flint-3.1.3/src/gr_poly/exp_series.c000066400000000000000000000025511461254215100174120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo */ int _gr_poly_exp_series_generic(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) { hlen = FLINT_MIN(hlen, n); if (n < 10 || hlen < 10 || ctx->methods[GR_METHOD_POLY_MULLOW] == (gr_funcptr) _gr_poly_mullow_generic) { return _gr_poly_exp_series_basecase(f, h, hlen, n, ctx); } else if (n < 30 && hlen > 0.9 * n) { return _gr_poly_exp_series_basecase_mul(f, h, hlen, n, ctx); } else { return _gr_poly_exp_series_newton(f, NULL, h, hlen, n, 30, ctx); } } int gr_poly_exp_series(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen = h->length; if (n == 0) return gr_poly_zero(f, ctx); if (hlen == 0) return gr_poly_one(f, ctx); gr_poly_fit_length(f, n, ctx); status |= _gr_poly_exp_series(f->coeffs, h->coeffs, hlen, n, ctx); _gr_poly_set_length(f, n, ctx); _gr_poly_normalise(f, ctx); return status; } flint-3.1.3/src/gr_poly/exp_series_basecase.c000066400000000000000000000077021461254215100212430ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_poly.h" /* Assumes: f[0] = exp(h[0]) hprime[k] = (k+1) * h[k+1] */ int _gr_poly_exp_series_basecase_rec_precomp1(gr_ptr f, gr_srcptr hprime, slong hlen, slong n, gr_ctx_t ctx) { slong k, l; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; status |= gr_mul(GR_ENTRY(f, 1, sz), f, hprime, ctx); if (n == 2) return status; for (k = 2; k < n && status == GR_SUCCESS; k++) { l = FLINT_MIN(k, hlen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(f, k, sz), NULL, 0, hprime, GR_ENTRY(f, k - l, sz), l, ctx); status |= gr_div_ui(GR_ENTRY(f, k, sz), GR_ENTRY(f, k, sz), k, ctx); } return status; } /* Assumes: f[0] = exp(h[0]) f[k-1] = 1/k, k >= 2 hprime[k] = (k+1) * h[k+1] */ int _gr_poly_exp_series_basecase_rec_precomp2(gr_ptr f, gr_srcptr hprime, slong hlen, slong n, gr_ctx_t ctx) { slong k, l; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ptr t; status |= gr_mul(GR_ENTRY(f, 1, sz), f, hprime, ctx); if (n == 2) return status; GR_TMP_INIT(t, ctx); for (k = 2; k < n && status == GR_SUCCESS; k++) { l = FLINT_MIN(k, hlen - 1); status |= _gr_vec_dot_rev(t, NULL, 0, hprime, GR_ENTRY(f, k - l, sz), l, ctx); status |= gr_mul(GR_ENTRY(f, k, sz), GR_ENTRY(f, k, sz), t, ctx); } GR_TMP_CLEAR(t, ctx); return status; } int _gr_poly_exp_series_basecase(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; hlen = FLINT_MIN(hlen, n); status = gr_exp(f, h, ctx); if (status != GR_SUCCESS) return status; if (hlen == 1) return _gr_vec_zero(GR_ENTRY(f, 1, sz), n - 1, ctx); if (n == 1) return status; if (n == 2) { status |= gr_mul(GR_ENTRY(f, 1, sz), f, GR_ENTRY(h, 1, sz), ctx); return status; } if (_gr_vec_is_zero(GR_ENTRY(h, 1, sz), hlen - 2, ctx) == T_TRUE) /* h = a + bx^d */ { slong i, j, d = hlen - 1; gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_set(t, GR_ENTRY(h, d, sz), ctx); for (i = 1, j = d; j < n && status == GR_SUCCESS; j += d, i++) { status |= gr_mul(GR_ENTRY(f, j, sz), GR_ENTRY(f, j - d, sz), t, ctx); status |= gr_div_ui(GR_ENTRY(f, j, sz), GR_ENTRY(f, j, sz), i, ctx); status |= _gr_vec_zero(GR_ENTRY(f, j - d + 1, sz), hlen - 2, ctx); } status |= _gr_vec_zero(GR_ENTRY(f, j - d + 1, sz), n - (j - d + 1), ctx); GR_TMP_CLEAR(t, ctx); return status; } GR_TMP_INIT_VEC(t, hlen - 1, ctx); status |= _gr_poly_derivative(t, h, hlen, ctx); if (n < 450 || gr_ctx_is_finite_characteristic(ctx) != T_TRUE) { status |= _gr_poly_exp_series_basecase_rec_precomp1(f, t, hlen, n, ctx); } else { status |= _gr_vec_reciprocals(GR_ENTRY(f, 1, sz), n - 1, ctx); status |= _gr_poly_exp_series_basecase_rec_precomp2(f, t, hlen, n, ctx); } GR_TMP_CLEAR_VEC(t, hlen - 1, ctx); return status; } int gr_poly_exp_series_basecase(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen = h->length; if (n == 0) return gr_poly_zero(f, ctx); if (hlen == 0) return gr_poly_one(f, ctx); gr_poly_fit_length(f, n, ctx); status |= _gr_poly_exp_series_basecase(f->coeffs, h->coeffs, hlen, n, ctx); _gr_poly_set_length(f, n, ctx); _gr_poly_normalise(f, ctx); return status; } flint-3.1.3/src/gr_poly/exp_series_basecase_mul.c000066400000000000000000000040621461254215100221140ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* exp(a + b*x^m) = exp(a) * (1 + b + b^2*x^(2m)/2) */ /* idea: for the Newton basecase, simultaneously compute exp(-a) * (1 + b - b^2*x^(2m)) ? */ int _gr_poly_exp_series_basecase_mul(gr_ptr f, gr_srcptr h, slong hlen, slong n, gr_ctx_t ctx) { slong m, v; gr_ptr t, u; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; hlen = FLINT_MIN(n, hlen); m = (n + 2) / 3; v = m * 2; if (hlen - m < 1 || n - v < 1 || hlen - v < 1) return _gr_poly_exp_series_basecase(f, h, hlen, n, ctx); GR_TMP_INIT_VEC(t, 2 * n - m, ctx); u = GR_ENTRY(t, n, sz); status |= _gr_poly_mullow(t, GR_ENTRY(h, m, sz), hlen - m, GR_ENTRY(h, m, sz), hlen - m, n - v, ctx); status |= _gr_vec_mul_scalar_2exp_si(t, t, n - v, -1, ctx); status |= _gr_vec_set(u, GR_ENTRY(h, m, sz), v - m, ctx); status |= _gr_poly_add(GR_ENTRY(u, v - m, sz), t, n - v, GR_ENTRY(h, v, sz), hlen - v, ctx); status |= _gr_poly_exp_series_basecase(f, h, m, n, ctx); status |= _gr_poly_mullow(t, f, n, u, n - m, n - m, ctx); status |= _gr_poly_add(GR_ENTRY(f, m, sz), GR_ENTRY(f, m, sz), n - m, t, n - m, ctx); GR_TMP_CLEAR_VEC(t, 2 * n - m, ctx); return status; } int gr_poly_exp_series_basecase_mul(gr_poly_t f, const gr_poly_t h, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen = h->length; if (n == 0) return gr_poly_zero(f, ctx); if (hlen == 0) return gr_poly_one(f, ctx); gr_poly_fit_length(f, n, ctx); status |= _gr_poly_exp_series_basecase_mul(f->coeffs, h->coeffs, hlen, n, ctx); _gr_poly_set_length(f, n, ctx); _gr_poly_normalise(f, ctx); return status; } flint-3.1.3/src/gr_poly/exp_series_newton.c000066400000000000000000000104601461254215100210020ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* c_k x^k -> c_k x^k / (m+k) */ /* todo: optimize */ int _gr_poly_integral_offset(gr_ptr res, gr_srcptr poly, slong len, slong m, gr_ctx_t ctx) { int status = GR_SUCCESS; slong k; gr_ptr t; slong sz = ctx->sizeof_elem; if (gr_ctx_is_finite_characteristic(ctx) == T_TRUE) { GR_TMP_INIT(t, ctx); status |= gr_one(t, ctx); for (k = len - 1; k >= 0; k--) { status |= gr_mul(GR_ENTRY(res, k, sz), GR_ENTRY(poly, k, sz), t, ctx); status |= gr_mul_ui(t, t, m + k, ctx); } status |= gr_inv(t, t, ctx); /* early return? */ for (k = 0; k < len; k++) { status |= gr_mul(GR_ENTRY(res, k, sz), GR_ENTRY(res, k, sz), t, ctx); status |= gr_mul_ui(t, t, m + k, ctx); } GR_TMP_CLEAR(t, ctx); } else { for (k = 0; k < len; k++) status |= gr_div_ui(GR_ENTRY(res, k, sz), GR_ENTRY(poly, k, sz), m + k, ctx); } return status; } int _gr_poly_exp_series_newton(gr_ptr f, gr_ptr g, gr_srcptr h, slong hlen, slong len, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong a[FLINT_BITS]; slong n, i, m, l, r; gr_ptr t, hprime; int inverse; cutoff = FLINT_MAX(cutoff, 2); hlen = FLINT_MIN(hlen, len); if (hlen <= 1 || len <= 1) { status |= _gr_poly_exp_series_basecase(f, h, hlen, len, ctx); if (g != NULL) status |= _gr_poly_inv_series(g, f, len, len, ctx); return status; } /* If g is provided, we compute g = exp(-h), and we can use g as scratch space. Otherwise, we still need to compute exp(-h) to length (n+1)/2 for intermediate use, and we still need n coefficients of scratch space. */ inverse = (g != NULL); if (!inverse) { GR_TMP_INIT_VEC(g, len, ctx); } hlen = FLINT_MIN(hlen, len); GR_TMP_INIT_VEC(t, len, ctx); GR_TMP_INIT_VEC(hprime, hlen - 1, ctx); status |= _gr_poly_derivative(hprime, h, hlen, ctx); a[i = 0] = n = len; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); /* f := exp(h) + O(x^n), g := exp(-h) + O(x^n) */ status |= _gr_poly_exp_series_basecase_mul(f, h, hlen, n, ctx); status |= _gr_poly_inv_series(g, f, n, n, ctx); for (i--; i >= 0; i--) { m = n; /* previous length */ n = a[i]; /* new length */ l = FLINT_MIN(hlen, n) - 1; r = FLINT_MIN(l + m - 1, n - 1); status |= _gr_poly_mullow(t, hprime, l, f, m, r, ctx); status |= _gr_poly_mullow(GR_ENTRY(g, m, sz), g, n - m, GR_ENTRY(t, m - 1, sz), r + 1 - m, n - m, ctx); status |= _gr_poly_integral_offset(GR_ENTRY(g, m, sz), GR_ENTRY(g, m, sz), n - m, m, ctx); status |= _gr_poly_mullow(GR_ENTRY(f, m, sz), f, n - m, GR_ENTRY(g, m, sz), n - m, n - m, ctx); /* g := exp(-h) + O(x^n); not needed if we only want exp(x) */ if (i != 0 || inverse) { status |= _gr_poly_mullow(t, f, n, g, m, n, ctx); status |= _gr_poly_mullow(GR_ENTRY(g, m, sz), g, m, GR_ENTRY(t, m, sz), n - m, n - m, ctx); status |= _gr_vec_neg(GR_ENTRY(g, m, sz), GR_ENTRY(g, m, sz), n - m, ctx); } } GR_TMP_CLEAR_VEC(hprime, hlen - 1, ctx); GR_TMP_CLEAR_VEC(t, len, ctx); if (!inverse) { GR_TMP_CLEAR_VEC(g, len, ctx); } return status; } int gr_poly_exp_series_newton(gr_poly_t f, const gr_poly_t h, slong n, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen = h->length; if (n == 0) return gr_poly_zero(f, ctx); if (hlen == 0) return gr_poly_one(f, ctx); gr_poly_fit_length(f, n, ctx); status |= _gr_poly_exp_series_newton(f->coeffs, NULL, h->coeffs, hlen, n, cutoff, ctx); _gr_poly_set_length(f, n, ctx); _gr_poly_normalise(f, ctx); return status; } flint-3.1.3/src/gr_poly/factor_squarefree.c000066400000000000000000000100541461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_vec.h" #include "gr_poly.h" int gr_poly_factor_squarefree(gr_ptr c, gr_vec_t fac, gr_vec_t exp, const gr_poly_t F, gr_ctx_t ctx) { gr_poly_t f, d, t1; gr_poly_t v, w, s; slong i; int status = GR_SUCCESS; fmpz_t e; gr_ctx_t poly_ctx, fmpz_ctx; /* todo */ if (gr_ctx_is_finite_characteristic(ctx) != T_FALSE) return GR_UNABLE; /* for vector of polynomials */ gr_ctx_init_gr_poly(poly_ctx, ctx); /* for vector of exponents */ gr_ctx_init_fmpz(fmpz_ctx); if (F->length == 0) { status |= gr_zero(c, ctx); gr_vec_set_length(fac, 0, poly_ctx); gr_vec_set_length(exp, 0, fmpz_ctx); gr_ctx_clear(poly_ctx); gr_ctx_clear(fmpz_ctx); return GR_SUCCESS; } status |= gr_poly_get_coeff_scalar(c, F, F->length - 1, ctx); if (gr_is_zero(c, ctx) != T_FALSE) { gr_ctx_clear(poly_ctx); gr_ctx_clear(fmpz_ctx); return GR_UNABLE; } if (F->length == 1) { gr_vec_set_length(fac, 0, poly_ctx); gr_vec_set_length(exp, 0, fmpz_ctx); gr_ctx_clear(poly_ctx); gr_ctx_clear(fmpz_ctx); return GR_SUCCESS; } fmpz_init(e); gr_poly_init(f, ctx); gr_poly_init(d, ctx); gr_poly_init(t1, ctx); gr_poly_init(v, ctx); gr_poly_init(w, ctx); gr_poly_init(s, ctx); status |= gr_poly_make_monic(f, F, ctx); status |= gr_poly_derivative(t1, f, ctx); status |= gr_poly_gcd(d, f, t1, ctx); if (status != GR_SUCCESS) { status = GR_UNABLE; goto cleanup; } gr_vec_set_length(fac, 0, ctx); gr_vec_set_length(exp, 0, ctx); if (d->length == 1) { status |= gr_vec_append(fac, f, poly_ctx); fmpz_one(e); status |= gr_vec_append(exp, e, fmpz_ctx); } else { /* todo: should be divexact over field */ status |= gr_poly_divrem(v, s, f, d, ctx); status |= gr_poly_divrem(w, s, t1, d, ctx); if (status != GR_SUCCESS) goto cleanup; /* invariant: v is monic, so we don't need to check if it is proper */ for (i = 1; ; i++) { status |= gr_poly_derivative(t1, v, ctx); status |= gr_poly_sub(s, w, t1, ctx); /* check if polynomial is proper */ if (s->length != 0 && gr_is_zero(gr_poly_entry_ptr(s, s->length - 1, ctx), ctx) != T_FALSE) { status = GR_UNABLE; goto cleanup; } if (s->length == 0) { if (v->length > 1) { status |= gr_vec_append(fac, v, poly_ctx); fmpz_set_ui(e, i); /* append_ui? */ status |= gr_vec_append(exp, e, fmpz_ctx); } break; } status |= gr_poly_gcd(d, v, s, ctx); if (status != GR_SUCCESS) goto cleanup; /* should be divexact over field */ status |= gr_poly_divrem(v, t1, v, d, ctx); status |= gr_poly_divrem(w, t1, s, d, ctx); if (status != GR_SUCCESS) goto cleanup; if (d->length > 1) { status |= gr_vec_append(fac, d, poly_ctx); fmpz_set_ui(e, i); /* append_ui? */ status |= gr_vec_append(exp, e, fmpz_ctx); } } } cleanup: gr_poly_clear(f, ctx); gr_poly_clear(d, ctx); gr_poly_clear(t1, ctx); gr_poly_clear(v, ctx); gr_poly_clear(w, ctx); gr_poly_clear(s, ctx); fmpz_clear(e); gr_ctx_clear(poly_ctx); gr_ctx_clear(fmpz_ctx); return status; } flint-3.1.3/src/gr_poly/fit_length.c000066400000000000000000000014461461254215100173710ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" void gr_poly_fit_length(gr_poly_t poly, slong len, gr_ctx_t ctx) { slong alloc = poly->alloc; if (len > alloc) { slong sz = ctx->sizeof_elem; if (len < 2 * alloc) len = 2 * alloc; poly->coeffs = flint_realloc(poly->coeffs, len * sz); _gr_vec_init(GR_ENTRY(poly->coeffs, poly->alloc, sz), len - alloc, ctx); poly->alloc = len; } } flint-3.1.3/src/gr_poly/gcd.c000066400000000000000000000047511461254215100160050ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo: over appropriate domains, make_monic -> extract content; unit */ /* todo: extract powers of x (see fmpz_poly_gcd) */ /* assumes lenA >= lenB >= 1, and both A and B have nonzero leading coefficient */ int _gr_poly_gcd(gr_ptr G, slong * lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { if (_gr_poly_gcd_euclidean(G, lenG, A, lenA, B, lenB, ctx) == GR_SUCCESS) return GR_SUCCESS; return GR_UNABLE; } int gr_poly_gcd(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenG; slong sz = ctx->sizeof_elem; gr_ptr g; int status; if (A->length == 0 && B->length == 0) return gr_poly_zero(G, ctx); if (A->length == 0) return gr_poly_make_monic(G, B, ctx); if (B->length == 0) return gr_poly_make_monic(G, A, ctx); if (A->length < B->length) return gr_poly_gcd(G, B, A, ctx); if (gr_is_zero(GR_ENTRY(A->coeffs, A->length - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(B->coeffs, B->length - 1, sz), ctx) != T_FALSE) { return GR_UNABLE; } /* lenA >= lenB >= 1 */ if (G == A || G == B) { g = flint_malloc(FLINT_MIN(lenA, lenB) * sz); _gr_vec_init(g, FLINT_MIN(lenA, lenB), ctx); } else { gr_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } status = _gr_poly_gcd(g, &lenG, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _gr_vec_clear(G->coeffs, G->alloc, ctx); flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _gr_poly_set_length(G, lenG, ctx); if (status == GR_SUCCESS && lenG != 0) { if (lenG == 1) status = gr_one(G->coeffs, ctx); else status = gr_poly_make_monic(G, G, ctx); } return status; } flint-3.1.3/src/gr_poly/gcd_euclidean.c000066400000000000000000000103421461254215100200070ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Andres Goens Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: over appropriate domains, make_monic -> extract content; unit */ #define GR_VEC_SWAP(vec1, len1, vec2, len2) \ do { \ gr_ptr __t; \ slong __tn; \ __t = (vec1); \ (vec1) = (vec2); \ (vec2) = __t; \ __tn = (len1); \ (len1) = (len2); \ (len2) = __tn; \ } while (0); /* assumes lenA >= lenB >= 1, and both A and B have nonzero leading coefficient */ int _gr_poly_gcd_euclidean(gr_ptr G, slong * lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { const slong lenW = FLINT_MAX(lenA - lenB + 1, lenB) + lenA + 2 * lenB; gr_ptr Q, R1, R2, R3, T, W; slong lenR2, lenR3; slong sz = ctx->sizeof_elem; int status; if (lenB == 1) { *lenG = 1; return gr_one(G, ctx); } status = GR_SUCCESS; /* lenA >= lenB > 1 */ GR_TMP_INIT_VEC(W, lenW, ctx); Q = W; R1 = GR_ENTRY(W, FLINT_MAX(lenA - lenB + 1, lenB), sz); R2 = GR_ENTRY(R1, lenA, sz); R3 = GR_ENTRY(R2, lenB, sz); status |= _gr_poly_divrem(Q, R1, A, lenA, B, lenB, ctx); lenR3 = lenB - 1; status |= _gr_vec_normalise(&lenR3, R1, lenR3, ctx); if (status != GR_SUCCESS) { *lenG = 0; goto cleanup; } if (lenR3 == 0) { status |= _gr_vec_set(G, B, lenB, ctx); *lenG = lenB; goto cleanup; } T = R3; R3 = R1; R1 = T; status |= _gr_vec_set(R2, B, lenB, ctx); lenR2 = lenB; do { status |= _gr_poly_divrem(Q, R2, R2, lenR2, R3, lenR3, ctx); lenR2 = lenR3 - 1; status |= _gr_vec_normalise(&lenR2, R2, lenR2, ctx); if (status != GR_SUCCESS) { *lenG = 0; goto cleanup; } GR_VEC_SWAP(R2, lenR2, R3, lenR3); } while (lenR3 > 0); _gr_vec_swap(G, R2, lenR2, ctx); *lenG = lenR2; cleanup: GR_TMP_CLEAR_VEC(W, lenW, ctx); return status; } int gr_poly_gcd_euclidean(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong lenA = A->length, lenB = B->length, lenG; slong sz = ctx->sizeof_elem; gr_ptr g; int status; if (A->length == 0 && B->length == 0) return gr_poly_zero(G, ctx); if (A->length == 0) return gr_poly_make_monic(G, B, ctx); if (B->length == 0) return gr_poly_make_monic(G, A, ctx); if (A->length < B->length) return gr_poly_gcd_euclidean(G, B, A, ctx); if (gr_is_zero(GR_ENTRY(A->coeffs, A->length - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(B->coeffs, B->length - 1, sz), ctx) != T_FALSE) { return GR_UNABLE; } /* lenA >= lenB >= 1 */ if (G == A || G == B) { g = flint_malloc(FLINT_MIN(lenA, lenB) * sz); _gr_vec_init(g, FLINT_MIN(lenA, lenB), ctx); } else { gr_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } status = _gr_poly_gcd_euclidean(g, &lenG, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _gr_vec_clear(G->coeffs, G->alloc, ctx); flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = FLINT_MIN(lenA, lenB); } _gr_poly_set_length(G, lenG, ctx); if (status == GR_SUCCESS && lenG != 0) { if (lenG == 1) status = gr_one(G->coeffs, ctx); else status = gr_poly_make_monic(G, G, ctx); } return status; } flint-3.1.3/src/gr_poly/gcd_hgcd.c000066400000000000000000000117551461254215100167740ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" #include "gr_vec.h" #define GR_VEC_NORM(status, R, lenR, sz, ctx) \ do { \ (void) sz; \ (status) |= _gr_vec_normalise(&(lenR), (R), (lenR), (ctx)); \ } while (0) #define __set(B, lenB, A, lenA) \ do { \ status |= _gr_vec_set((B), (A), (lenA), ctx); \ (lenB) = (lenA); \ } while (0) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ status |= _gr_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), ctx); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ GR_VEC_NORM(status, R, lenR, sz, ctx); \ } \ else \ { \ status |= _gr_vec_set((R), (A), (lenA), ctx); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) /* XXX: Incidentally, this implementation currently supports aliasing. But since this may change in the future, no function other than gr_poly_gcd_hgcd() should rely on this. */ int _gr_poly_gcd_hgcd(gr_ptr G, slong * _lenG, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong lenG, lenJ, lenR, lenQ; slong sz = ctx->sizeof_elem; slong alloc = 2 * lenB + lenA; gr_ptr J, R, Q; if (lenB > lenA) flint_throw(FLINT_ERROR, "(%s)\n", __func__); GR_TMP_INIT_VEC(J, alloc, ctx); R = GR_ENTRY(J, lenB, sz); Q = GR_ENTRY(R, lenB, sz); __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB); (void) lenQ; /* unused */ if (lenR == 0) { __set(G, lenG, B, lenB); } else { status |= _gr_poly_hgcd(NULL, NULL, NULL, NULL, G, &(lenG), J, &(lenJ), B, lenB, R, lenR, inner_cutoff, ctx); while (lenJ != 0) { /* todo: only rem */ __divrem(Q, lenQ, R, lenR, G, lenG, J, lenJ); (void) lenQ; /* unused */ if (lenR == 0) { __set(G, lenG, J, lenJ); break; } if (lenJ < cutoff) { status |= _gr_poly_gcd_euclidean(G, &lenG, J, lenJ, R, lenR, ctx); break; } status |= _gr_poly_hgcd(NULL, NULL, NULL, NULL, G, &(lenG), J, &(lenJ), J, lenJ, R, lenR, inner_cutoff, ctx); } } GR_TMP_CLEAR_VEC(J, alloc, ctx); *_lenG = lenG; return status; } int gr_poly_gcd_hgcd(gr_poly_t G, const gr_poly_t A, const gr_poly_t B, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) { if (A->length < B->length) { return gr_poly_gcd_hgcd(G, B, A, inner_cutoff, cutoff, ctx); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; gr_poly_t tG; gr_ptr g; int status = GR_SUCCESS; if (lenA == 0) /* lenA = lenB = 0 */ { return gr_poly_zero(G, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { return gr_poly_make_monic(G, A, ctx); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { gr_poly_init2(tG, FLINT_MIN(lenA, lenB), ctx); g = tG->coeffs; } else { gr_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } status = _gr_poly_gcd_hgcd(g, &lenG, A->coeffs, lenA, B->coeffs, lenB, inner_cutoff, cutoff, ctx); if (G == A || G == B) { gr_poly_swap(tG, G, ctx); gr_poly_clear(tG, ctx); } G->length = lenG; if (G->length == 1) status |= gr_one(G->coeffs, ctx); else status |= gr_poly_make_monic(G, G, ctx); return status; } } } flint-3.1.3/src/gr_poly/gen.c000066400000000000000000000011201461254215100160040ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int gr_poly_gen(gr_poly_t res, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_poly_zero(res, ctx); status |= gr_poly_set_coeff_ui(res, 1, 1, ctx); return status; } flint-3.1.3/src/gr_poly/get_coeff_scalar.c000066400000000000000000000012141461254215100205050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int gr_poly_get_coeff_scalar(gr_ptr res, const gr_poly_t poly, slong i, gr_ctx_t ctx) { if (i < 0 || i >= poly->length) return gr_zero(res, ctx); else return gr_set(res, GR_ENTRY(poly->coeffs, i, ctx->sizeof_elem), ctx); } flint-3.1.3/src/gr_poly/hgcd.c000066400000000000000000000564261461254215100161630ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" #include "gr_vec.h" typedef struct { gr_ptr res; gr_ptr lc; slong len0; slong len1; slong off; } gr_poly_res_struct; typedef gr_poly_res_struct gr_poly_res_t[1]; #define OFFSET(x, i) GR_ENTRY((x), (i), sz) #define GR_VEC_NORM(status, R, lenR, sz, ctx) \ do { \ (void) sz; \ (status) |= _gr_vec_normalise(&(lenR), (R), (lenR), (ctx)); \ } while (0) /* We define a whole bunch of macros here which essentially provide the gr_poly functionality as far as the setting of coefficient data and lengths is concerned, but which do not do any separate memory allocation. None of these macros support aliasing. */ #define __attach_shift(B, lenB, A, lenA, m) \ do { \ (B) = OFFSET(A, m); \ (lenB) = ((lenA) >= (m)) ? (lenA) - (m) : 0; \ } while (0) #define __attach_truncate(B, lenB, A, lenA, m) \ do { \ (B) = (A); \ (lenB) = ((lenA) < (m)) ? (lenA) : (m); \ } while (0) #define __set(B, lenB, A, lenA) \ do { \ status |= _gr_vec_set((B), (A), (lenA), ctx); \ (lenB) = (lenA); \ } while (0) #define __swap(u, l, v, m) \ do { \ { gr_ptr _; _ = (u), (u) = (v), (v) = _;} \ { slong _; _ = (l), (l) = (m), (m) = _;} \ } while (0) #define __add(C, lenC, A, lenA, B, lenB) \ do { \ status |= _gr_poly_add((C), (A), (lenA), (B), (lenB), ctx); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ GR_VEC_NORM(status, C, lenC, sz, ctx); \ } while (0) #define __sub(C, lenC, A, lenA, B, lenB) \ do { \ status |= _gr_poly_sub((C), (A), (lenA), (B), (lenB), ctx); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ GR_VEC_NORM(status, C, lenC, sz, ctx); \ } while (0) #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ status |= _gr_poly_mul((C), (A), (lenA), (B), (lenB), ctx); \ else \ status |= _gr_poly_mul((C), (B), (lenB), (A), (lenA), ctx); \ (lenC) = (lenA) + (lenB) - 1; \ } \ else \ { \ (lenC) = 0; \ } \ } while (0) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ status |= _gr_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), ctx); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ GR_VEC_NORM(status, R, lenR, sz, ctx); \ } \ else \ { \ status |= _gr_vec_set((R), (A), (lenA), ctx); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) static inline int __mat_one(gr_ptr * M, slong * lenM, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_one(M[0], ctx); status |= gr_one(M[3], ctx); lenM[0] = 1; lenM[1] = 0; lenM[2] = 0; lenM[3] = 1; return status; } /* Computes the matrix product C of the two 2x2 matrices A and B, using classical multiplication. Does not support aliasing. Expects T to be temporary space sufficient for any of the polynomial products involved. */ static int __mat_mul_classical(gr_ptr * C, slong * lenC, gr_ptr * A, slong * lenA, gr_ptr * B, slong * lenB, gr_ptr T, gr_ctx_t ctx) { slong lenT; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; __mul(C[0], lenC[0], A[0], lenA[0], B[0], lenB[0]); __mul(T, lenT, A[1], lenA[1], B[2], lenB[2]); __add(C[0], lenC[0], C[0], lenC[0], T, lenT); __mul(C[1], lenC[1], A[0], lenA[0], B[1], lenB[1]); __mul(T, lenT, A[1], lenA[1], B[3], lenB[3]); __add(C[1], lenC[1], C[1], lenC[1], T, lenT); __mul(C[2], lenC[2], A[2], lenA[2], B[0], lenB[0]); __mul(T, lenT, A[3], lenA[3], B[2], lenB[2]); __add(C[2], lenC[2], C[2], lenC[2], T, lenT); __mul(C[3], lenC[3], A[2], lenA[2], B[1], lenB[1]); __mul(T, lenT, A[3], lenA[3], B[3], lenB[3]); __add(C[3], lenC[3], C[3], lenC[3], T, lenT); return status; } /* Computes the matrix product C of the two 2x2 matrices A and B, using Strassen multiplication. Does not support aliasing. Expects T0, T1 to be temporary space sufficient for any of the polynomial products involved. */ static int __mat_mul_strassen(gr_ptr * C, slong * lenC, gr_ptr * A, slong * lenA, gr_ptr * B, slong * lenB, gr_ptr T0, gr_ptr T1, gr_ctx_t ctx) { slong lenT0, lenT1; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; __sub(T0, lenT0, A[0], lenA[0], A[2], lenA[2]); __sub(T1, lenT1, B[3], lenB[3], B[1], lenB[1]); __mul(C[2], lenC[2], T0, lenT0, T1, lenT1); __add(T0, lenT0, A[2], lenA[2], A[3], lenA[3]); __sub(T1, lenT1, B[1], lenB[1], B[0], lenB[0]); __mul(C[3], lenC[3], T0, lenT0, T1, lenT1); __sub(T0, lenT0, T0, lenT0, A[0], lenA[0]); __sub(T1, lenT1, B[3], lenB[3], T1, lenT1); __mul(C[1], lenC[1], T0, lenT0, T1, lenT1); __sub(T0, lenT0, A[1], lenA[1], T0, lenT0); __mul(C[0], lenC[0], T0, lenT0, B[3], lenB[3]); __mul(T0, lenT0, A[0], lenA[0], B[0], lenB[0]); __add(C[1], lenC[1], T0, lenT0, C[1], lenC[1]); __add(C[2], lenC[2], C[1], lenC[1], C[2], lenC[2]); __add(C[1], lenC[1], C[1], lenC[1], C[3], lenC[3]); __add(C[3], lenC[3], C[2], lenC[2], C[3], lenC[3]); __add(C[1], lenC[1], C[1], lenC[1], C[0], lenC[0]); __sub(T1, lenT1, T1, lenT1, B[2], lenB[2]); __mul(C[0], lenC[0], A[3], lenA[3], T1, lenT1); __sub(C[2], lenC[2], C[2], lenC[2], C[0], lenC[0]); __mul(C[0], lenC[0], A[1], lenA[1], B[2], lenB[2]); __add(C[0], lenC[0], C[0], lenC[0], T0, lenT0); return status; } /* Computs the matrix product C of the two 2x2 matrices A and B, using either classical or Strassen multiplication depending on the degrees of the input polynomials. Does not support aliasing. Expects T0, T1 to be temporary space sufficient for any of the polynomial products involved. */ static int __mat_mul(gr_ptr * C, slong * lenC, gr_ptr * A, slong * lenA, gr_ptr * B, slong * lenB, gr_ptr T0, gr_ptr T1, gr_ctx_t ctx) { slong min = lenA[0]; min = FLINT_MIN(min, lenA[1]); min = FLINT_MIN(min, lenA[2]); min = FLINT_MIN(min, lenA[3]); min = FLINT_MIN(min, lenB[0]); min = FLINT_MIN(min, lenB[1]); min = FLINT_MIN(min, lenB[2]); min = FLINT_MIN(min, lenB[3]); if (min < 20) { return __mat_mul_classical(C, lenC, A, lenA, B, lenB, T0, ctx); } else { return __mat_mul_strassen(C, lenC, A, lenA, B, lenB, T0, T1, ctx); } } /* HGCD Iterative step. Only supports aliasing in {*A,a} and {*B,b}. Assumes that lena > lenb > 0. Assumes that the pointers {*A, *B, *T} as well as {M + 0, M + 1, M + 2, M + 3, t} may be swapped. With the underlying HGCD implementation in mind, this is to say that the blocks of memory implicitly reserved for these pointers probably should have the same size. Expects {*A, *B, *T} to be of size at least lena, {M + 0, M + 1, M + 2, M + 3, *t} and Q of size at least (lena + 1)/2. */ int _gr_poly_hgcd_recursive_iter( slong * ans_sgn, gr_ptr * M, slong * lenM, gr_ptr * A, slong * lenA, gr_ptr * B, slong * lenB, gr_srcptr a, slong lena, gr_srcptr b, slong lenb, gr_ptr Q, gr_ptr * T, gr_ptr * t, gr_ctx_t ctx, gr_poly_res_t res) { const slong m = lena / 2; slong sgn = 1; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; GR_VEC_NORM(status, b, lenb, sz, ctx); __mat_one(M, lenM, ctx); __set(*A, *lenA, a, lena); __set(*B, *lenB, b, lenb); while (*lenB >= m + 1) { slong lenQ, lenT, lent; if (res != NULL) status |= gr_set(res->lc, OFFSET(*B, *lenB - 1), ctx); __divrem(Q, lenQ, *T, lenT, *A, *lenA, *B, *lenB); if (res != NULL) { if (lenT >= m + 1) { if (lenT >= 1) { status |= gr_pow_ui(res->lc, res->lc, *lenA - lenT, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); if ((((*lenA + res->off) | (*lenB + res->off)) & 1) == 0) status |= gr_neg(res->res, res->res, ctx); } else { if (*lenB == 1) { status |= gr_pow_ui(res->lc, res->lc, *lenA - 1, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); } else status |= gr_zero(res->res, ctx); } } else { res->len0 = *lenA; res->len1 = *lenB; } } __swap(*B, *lenB, *T, lenT); __swap(*A, *lenA, *T, lenT); __mul(*T, lenT, Q, lenQ, M[2], lenM[2]); __add(*t, lent, M[3], lenM[3], *T, lenT); __swap(M[3], lenM[3], M[2], lenM[2]); __swap(M[2], lenM[2], *t, lent); __mul(*T, lenT, Q, lenQ, M[0], lenM[0]); __add(*t, lent, M[1], lenM[1], *T, lenT); __swap(M[1], lenM[1], M[0], lenM[0]); __swap(M[0], lenM[0], *t, lent); sgn = -sgn; } *ans_sgn = sgn; return status; } /* Assumes that lena > lenb > 0. The current implementation requires P to point to a memory pool of size at least 6 lena + 10 (lena + 1)/2 just in this iteration. Supports aliasing only between {*A, a} and {*B, b}. Only computes the matrix {M, lenM} if flag is non-zero, in which case these arrays are supposed to be sufficiently allocated. Does not permute the pointers in {M, lenM}. When flag is zero, the first two arguments are allowed to be NULL. */ int _gr_poly_hgcd_recursive( slong * ans_sgn, gr_ptr * M, slong * lenM, gr_ptr A, slong * lenA, gr_ptr B, slong * lenB, gr_srcptr a, slong lena, gr_srcptr b, slong lenb, gr_ptr P, gr_ctx_t ctx, slong cutoff, int flag, gr_poly_res_t res) { const slong m = lena / 2; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (lenb < m + 1) { if (flag) { __mat_one(M, lenM, ctx); } __set(A, *lenA, a, lena); __set(B, *lenB, b, lenb); *ans_sgn = 1; return status; } else { /* Readonly pointers */ gr_ptr a0, b0, s, t, a4, b4, c0, d0; slong lena0, lenb0, lens, lent, lena4, lenb4, lenc0, lend0; /* Pointers to independently allocated memory */ gr_ptr a2, b2, a3, b3, q, d, T0, T1; slong lena2, lenb2, lena3, lenb3, lenq, lend, lenT0; gr_ptr R[4], S[4]; slong lenR[4], lenS[4]; slong sgnR, sgnS; a2 = P; b2 = OFFSET(a2, lena); a3 = OFFSET(b2, lena); b3 = OFFSET(a3, lena); q = OFFSET(b3, lena); d = OFFSET(q, (lena + 1) / 2); T0 = OFFSET(d, lena); T1 = OFFSET(T0, lena); R[0] = OFFSET(T1, (lena + 1) / 2); R[1] = OFFSET(R[0], (lena + 1) / 2); R[2] = OFFSET(R[1], (lena + 1) / 2); R[3] = OFFSET(R[2], (lena + 1) / 2); S[0] = OFFSET(R[3], (lena + 1) / 2); S[1] = OFFSET(S[0], (lena + 1) / 2); S[2] = OFFSET(S[1], (lena + 1) / 2); S[3] = OFFSET(S[2], (lena + 1) / 2); P = OFFSET(P, 6 * lena + 10 * (lena + 1) / 2); __attach_shift(a0, lena0, (gr_ptr) a, lena, m); __attach_shift(b0, lenb0, (gr_ptr) b, lenb, m); if (res != NULL) { status |= gr_set(res->lc, OFFSET(b, lenb - 1), ctx); res->len0 -= m; res->len1 -= m; res->off += m; } if (lena0 < cutoff) status |= _gr_poly_hgcd_recursive_iter(&sgnR, R, lenR, &a3, &lena3, &b3, &lenb3, a0, lena0, b0, lenb0, q, &T0, &T1, ctx, res); else status |= _gr_poly_hgcd_recursive(&sgnR, R, lenR, a3, &lena3, b3, &lenb3, a0, lena0, b0, lenb0, P, ctx, cutoff, 1, res); if (res != NULL) { res->off -= m; res->len0 += m; res->len1 += m; } __attach_truncate(s, lens, (gr_ptr) a, lena, m); __attach_truncate(t, lent, (gr_ptr) b, lenb, m); __mul(b2, lenb2, R[2], lenR[2], s, lens); __mul(T0, lenT0, R[0], lenR[0], t, lent); if (sgnR < 0) __sub(b2, lenb2, b2, lenb2, T0, lenT0); else __sub(b2, lenb2, T0, lenT0, b2, lenb2); status |= _gr_vec_zero(OFFSET(b2, lenb2), m + lenb3 - lenb2, ctx); __attach_shift(b4, lenb4, b2, lenb2, m); __add(b4, lenb4, b4, lenb4, b3, lenb3); lenb2 = FLINT_MAX(m + lenb3, lenb2); GR_VEC_NORM(status, b2, lenb2, sz, ctx); __mul(a2, lena2, R[3], lenR[3], s, lens); __mul(T0, lenT0, R[1], lenR[1], t, lent); if (sgnR < 0) __sub(a2, lena2, T0, lenT0, a2, lena2); else __sub(a2, lena2, a2, lena2, T0, lenT0); status |= _gr_vec_zero(OFFSET(a2, lena2), m + lena3 - lena2, ctx); __attach_shift(a4, lena4, a2, lena2, m); __add(a4, lena4, a4, lena4, a3, lena3); lena2 = FLINT_MAX(m + lena3, lena2); GR_VEC_NORM(status, a2, lena2, sz, ctx); if (lenb2 < m + 1) { __set(A, *lenA, a2, lena2); __set(B, *lenB, b2, lenb2); if (flag) { __set(M[0], lenM[0], R[0], lenR[0]); __set(M[1], lenM[1], R[1], lenR[1]); __set(M[2], lenM[2], R[2], lenR[2]); __set(M[3], lenM[3], R[3], lenR[3]); } *ans_sgn = sgnR; return status; } else { slong k = 2 * m - lenb2 + 1; if (res != NULL) { if (lenb2 < lenb) /* ensure something happened */ { if (lenb2 >= 1) { status |= gr_pow_ui(res->lc, res->lc, res->len0 - lenb2, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); if ((((res->len0 + res->off) | (res->len1 + res->off)) & 1) == 0) { status |= gr_neg(res->res, res->res, ctx); } } else { if (res->len1 == 1) { status |= gr_pow_ui(res->lc, res->lc, res->len0 - 1, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); } else { status |= gr_zero(res->res, ctx); } } } status |= gr_set(res->lc, OFFSET(b2, lenb2 - 1), ctx); res->len0 = lena2; res->len1 = lenb2; } __divrem(q, lenq, d, lend, a2, lena2, b2, lenb2); __attach_shift(c0, lenc0, b2, lenb2, k); __attach_shift(d0, lend0, d, lend, k); if (res != NULL) { if (lend >= m + 1) { if (lend >= 1) { status |= gr_pow_ui(res->lc, res->lc, lena2 - lend, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); if ((((lena2 + res->off) | (lenb2 + res->off)) & 1) == 0) status |= gr_neg(res->res, res->res, ctx); } else { if (lenb2 == 1) { status |= gr_pow_ui(res->lc, res->lc, lena2 - 1, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); } else status |= gr_zero(res->res, ctx); } res->len0 = lenb2; res->len1 = lend; } res->len0 -= k; res->len1 -= k; res->off += k; } if (lenc0 < cutoff) status |= _gr_poly_hgcd_recursive_iter(&sgnS, S, lenS, &a3, &lena3, &b3, &lenb3, c0, lenc0, d0, lend0, a2, &T0, &T1, ctx, res); /* a2 as temp */ else status |= _gr_poly_hgcd_recursive(&sgnS, S, lenS, a3, &lena3, b3, &lenb3, c0, lenc0, d0, lend0, P, ctx, cutoff, 1, res); if (res != NULL) { res->len0 += k; res->len1 += k; res->off -= k; } __attach_truncate(s, lens, b2, lenb2, k); __attach_truncate(t, lent, d, lend, k); __mul(B, *lenB, S[2], lenS[2], s, lens); __mul(T0, lenT0, S[0], lenS[0], t, lent); if (sgnS < 0) __sub(B, *lenB, B, *lenB, T0, lenT0); else __sub(B, *lenB, T0, lenT0, B, *lenB); status |= _gr_vec_zero(OFFSET(B, *lenB), k + lenb3 - *lenB, ctx); __attach_shift(b4, lenb4, B, *lenB, k); __add(b4, lenb4, b4, lenb4, b3, lenb3); *lenB = FLINT_MAX(k + lenb3, *lenB); GR_VEC_NORM(status, B, *lenB, sz, ctx); __mul(A, *lenA, S[3], lenS[3], s, lens); __mul(T0, lenT0, S[1], lenS[1], t, lent); if (sgnS < 0) __sub(A, *lenA, T0, lenT0, A, *lenA); else __sub(A, *lenA, A, *lenA, T0, lenT0); status |= _gr_vec_zero(OFFSET(A, *lenA), k + lena3 - *lenA, ctx); __attach_shift(a4, lena4, A, *lenA, k); __add(a4, lena4, a4, lena4, a3, lena3); *lenA = FLINT_MAX(k + lena3, *lenA); GR_VEC_NORM(status, A, *lenA, sz, ctx); if (flag) { __swap(S[0], lenS[0], S[2], lenS[2]); __swap(S[1], lenS[1], S[3], lenS[3]); __mul(T0, lenT0, S[2], lenS[2], q, lenq); __add(S[0], lenS[0], S[0], lenS[0], T0, lenT0); __mul(T0, lenT0, S[3], lenS[3], q, lenq); __add(S[1], lenS[1], S[1], lenS[1], T0, lenT0); __mat_mul(M, lenM, R, lenR, S, lenS, a2, b2, ctx); } *ans_sgn = -(sgnR * sgnS); return status; } } } /* XXX: Currently supports aliasing between {A,a} and {B,b}. */ int _gr_poly_hgcd(gr_ptr r, slong * sgn, gr_ptr * M, slong * lenM, gr_ptr A, slong * lenA, gr_ptr B, slong * lenB, gr_srcptr a, slong lena, gr_srcptr b, slong lenb, slong cutoff, gr_ctx_t ctx) { slong lenW = 22 * lena + 16 * (FLINT_CLOG2(lena) + 1); slong sgnM; gr_ptr W; int status = GR_SUCCESS; gr_poly_res_t res; slong sz = ctx->sizeof_elem; if (lena == 0 || lenb == 0) { if (sgn != NULL) *sgn = 0; *lenA = *lenB = 0; if (lenM != NULL) lenM[0] = lenM[1] = lenM[2] = lenM[3] = 0; return GR_DOMAIN; } if (r != NULL) { GR_TMP_INIT2(res->res, res->lc, ctx); status |= gr_set(res->res, r, ctx); status |= gr_set(res->lc, GR_ENTRY(b, lenb - 1, sz), ctx); res->len0 = lena; res->len1 = lenb; res->off = 0; } if (lenb < lena / 2 + 1) lenW = 0; GR_TMP_INIT_VEC(W, lenW, ctx); if (M == NULL) { status = _gr_poly_hgcd_recursive(&sgnM, NULL, NULL, A, lenA, B, lenB, a, lena, b, lenb, W, ctx, cutoff, 0, r == NULL ? NULL : res); } else { status = _gr_poly_hgcd_recursive(&sgnM, M, lenM, A, lenA, B, lenB, a, lena, b, lenb, W, ctx, cutoff, 1, r == NULL ? NULL : res); } if (r != NULL) { if (*lenB < lenb) /* make sure something happened */ { if (*lenB >= 1) { status |= gr_pow_ui(res->lc, res->lc, res->len0 - *lenB, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); if (((res->len0 | res->len1) & 1) == 0) status |= gr_neg(res->res, res->res, ctx); } else { if (res->len1 == 1) { status |= gr_pow_ui(res->lc, res->lc, res->len0 - 1, ctx); status |= gr_mul(res->res, res->res, res->lc, ctx); } else status |= gr_zero(res->res, ctx); } } status |= gr_set(r, res->res, ctx); GR_TMP_CLEAR2(res->res, res->lc, ctx); } GR_TMP_CLEAR_VEC(W, lenW, ctx); if (sgn != NULL) *sgn = sgnM; return status; } flint-3.1.3/src/gr_poly/init.c000066400000000000000000000012231461254215100162020ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" void gr_poly_init(gr_poly_t poly, gr_ctx_t ctx) { poly->coeffs = NULL; poly->length = 0; poly->alloc = 0; } void gr_poly_init2(gr_poly_t poly, slong len, gr_ctx_t ctx) { gr_poly_init(poly, ctx); gr_poly_fit_length(poly, len, ctx); } flint-3.1.3/src/gr_poly/inlines.c000066400000000000000000000001101461254215100166720ustar00rootroot00000000000000#define GR_POLY_INLINES_C #include "gr_poly.h" #undef GR_POLY_INLINES_C flint-3.1.3/src/gr_poly/integral.c000066400000000000000000000021141461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_integral(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx) { slong k = len - 1; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; for (k = len - 1; k > 0 && status == GR_SUCCESS; k--) status |= gr_div_ui(GR_ENTRY(res, k, sz), GR_ENTRY(poly, k - 1, sz), k, ctx); status |= gr_zero(res, ctx); return status; } int gr_poly_integral(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) { int status; gr_poly_fit_length(res, poly->length + 1, ctx); status = _gr_poly_integral(res->coeffs, poly->coeffs, poly->length + 1, ctx); _gr_poly_set_length(res, poly->length + 1, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/inv.c000066400000000000000000000017051461254215100160400ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int gr_poly_inv(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) { if (poly->length == 0) { if (gr_ctx_is_zero_ring(ctx) == T_TRUE) return gr_poly_zero(res, ctx); else return GR_DOMAIN; } else if (poly->length == 1) { int status; gr_poly_fit_length(res, 1, ctx); status = gr_inv(res->coeffs, poly->coeffs, ctx); _gr_poly_set_length(res, 1, ctx); _gr_poly_normalise(res, ctx); return status; } else { return GR_DOMAIN; } } flint-3.1.3/src/gr_poly/inv_series.c000066400000000000000000000030451461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_inv_series_generic(gr_ptr Qinv, gr_srcptr Q, slong Qlen, slong len, gr_ctx_t ctx) { /* todo */ if (Qlen <= 8 || ctx->methods[GR_METHOD_POLY_MULLOW] == (gr_funcptr) _gr_poly_mullow_generic) { return _gr_poly_inv_series_basecase(Qinv, Q, Qlen, len, ctx); } else { return _gr_poly_inv_series_newton(Qinv, Q, Qlen, len, FLINT_MIN(10, len / 2), ctx); } } int gr_poly_inv_series(gr_poly_t Qinv, const gr_poly_t Q, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong Qlen; if (len == 0) return gr_poly_zero(Qinv, ctx); Qlen = Q->length; if (Qlen == 0) return GR_DOMAIN; if (Qlen == 1) len = 1; if (Qinv == Q) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_inv_series(t, Q, len, ctx); gr_poly_swap(Qinv, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Qinv, len, ctx); status |= _gr_poly_inv_series(Qinv->coeffs, Q->coeffs, Q->length, len, ctx); _gr_poly_set_length(Qinv, len, ctx); _gr_poly_normalise(Qinv, ctx); return status; } flint-3.1.3/src/gr_poly/inv_series_basecase.c000066400000000000000000000104041461254215100212340ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* Ainv is the inverse constant term of A; it is allowed to be aliased with res[0]. */ int _gr_poly_inv_series_basecase_preinv1(gr_ptr res, gr_srcptr A, slong Alen, gr_srcptr Ainv, slong len, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (len == 0) return GR_SUCCESS; if (Alen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); if (Ainv != res) status |= gr_set(res, Ainv, ctx); if (Alen == 1) { status |= _gr_vec_zero(GR_ENTRY(res, 1, sz), len - 1, ctx); } else if (len == 2) { status |= gr_mul(GR_ENTRY(res, 1, sz), res, res, ctx); status |= gr_mul(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), GR_ENTRY(A, 1, sz), ctx); status |= gr_neg(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), ctx); } else if (Alen == 2 || _gr_vec_is_zero(GR_ENTRY(A, 1, sz), Alen - 2, ctx) == T_TRUE) { /* Special-case binomials */ /* todo: implement using vector functions (geometric series + inflate) */ slong i, j, step; step = Alen - 1; if (gr_is_one(res, ctx) == T_TRUE) { status |= gr_neg(GR_ENTRY(res, step, sz), GR_ENTRY(A, step, sz), ctx); for (i = 2 * step; i < len; i += step) status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - step, sz), GR_ENTRY(res, step, sz), ctx); } else if (gr_is_neg_one(res, ctx) == T_TRUE) { status |= gr_neg(GR_ENTRY(res, step, sz), GR_ENTRY(A, step, sz), ctx); for (i = 2 * step; i < len; i += step) status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - step, sz), GR_ENTRY(A, step, sz), ctx); } else { gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_mul(t, res, GR_ENTRY(A, step, sz), ctx); status |= gr_neg(t, t, ctx); for (i = step; i < len; i += step) status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - step, sz), t, ctx); GR_TMP_CLEAR(t, ctx); } for (i = 0; i < len; i += step) for (j = i + 1; j < FLINT_MIN(len, i + step); j++) status |= gr_zero(GR_ENTRY(res, j, sz), ctx); } else { int is_one; slong i, l; is_one = (gr_is_one(res, ctx) == T_TRUE); for (i = 1; i < len; i++) { l = FLINT_MIN(i, Alen - 1); status |= _gr_vec_dot_rev(GR_ENTRY(res, i, sz), NULL, 1, GR_ENTRY(A, 1, sz), GR_ENTRY(res, i - l, sz), l, ctx); if (!is_one) status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), res, ctx); } } return status; } int _gr_poly_inv_series_basecase_generic(gr_ptr res, gr_srcptr A, slong Alen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; if (len == 0) return GR_SUCCESS; if (Alen == 0) return GR_DOMAIN; Alen = FLINT_MIN(Alen, len); status = gr_inv(res, A, ctx); if (status != GR_SUCCESS) return status; return _gr_poly_inv_series_basecase_preinv1(res, A, Alen, res, len, ctx); } int gr_poly_inv_series_basecase(gr_poly_t res, const gr_poly_t A, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong Alen; if (len == 0) return gr_poly_zero(res, ctx); Alen = A->length; if (Alen == 0) return GR_DOMAIN; if (Alen == 1) len = 1; if (res == A) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_inv_series_basecase(t, A, len, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_inv_series_basecase(res->coeffs, A->coeffs, A->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/inv_series_newton.c000066400000000000000000000047001461254215100210020ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_inv_series_newton(gr_ptr Qinv, gr_srcptr Q, slong Qlen, slong len, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong i, m, n, Qnlen, Wlen, W2len; gr_ptr W; slong a[FLINT_BITS]; if (len == 0) return GR_SUCCESS; if (Qlen == 0) return GR_DOMAIN; Qlen = FLINT_MIN(Qlen, len); if (len < cutoff) return _gr_poly_inv_series_basecase(Qinv, Q, Qlen, len, ctx); cutoff = FLINT_MAX(cutoff, 2); a[i = 0] = n = len; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); status |= _gr_poly_inv_series_basecase(Qinv, Q, Qlen, n, ctx); if (status != GR_SUCCESS) return status; GR_TMP_INIT_VEC(W, len, ctx); for (i--; i >= 0; i--) { m = n; n = a[i]; Qnlen = FLINT_MIN(Qlen, n); Wlen = FLINT_MIN(Qnlen + m - 1, n); W2len = Wlen - m; status |= _gr_poly_mullow(W, Q, Qnlen, Qinv, m, Wlen, ctx); /* should be mulmid */ status |= _gr_poly_mullow(GR_ENTRY(Qinv, m, sz), Qinv, m, GR_ENTRY(W, m, sz), W2len, n - m, ctx); status |= _gr_vec_neg(GR_ENTRY(Qinv, m, sz), GR_ENTRY(Qinv, m, sz), n - m, ctx); } GR_TMP_CLEAR_VEC(W, len, ctx); return status; } int gr_poly_inv_series_newton(gr_poly_t Qinv, const gr_poly_t Q, slong len, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong Qlen; if (len == 0) return gr_poly_zero(Qinv, ctx); Qlen = Q->length; if (Qlen == 0) return GR_DOMAIN; if (Qlen == 1) len = 1; if (Qinv == Q) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_inv_series_newton(t, Q, len, cutoff, ctx); gr_poly_swap(Qinv, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(Qinv, len, ctx); status |= _gr_poly_inv_series_newton(Qinv->coeffs, Q->coeffs, Q->length, len, cutoff, ctx); _gr_poly_set_length(Qinv, len, ctx); _gr_poly_normalise(Qinv, ctx); return status; } flint-3.1.3/src/gr_poly/is_gen.c000066400000000000000000000020541461254215100165060ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo: faster code when possible */ truth_t gr_poly_is_gen(const gr_poly_t poly, gr_ctx_t ctx) { gr_ptr tmp; gr_poly_t gen; truth_t res; slong sz = ctx->sizeof_elem; GR_TMP_INIT_VEC(tmp, 2, ctx); if (gr_one(GR_ENTRY(tmp, 1, sz), ctx) != GR_SUCCESS) { res = T_UNKNOWN; } else { res = gr_is_zero(GR_ENTRY(tmp, 1, sz), ctx); if (res != T_UNKNOWN) { gen->coeffs = tmp; gen->length = (res == T_TRUE) ? 1 : 2; gen->alloc = gen->length; res = gr_poly_equal(poly, gen, ctx); } } GR_TMP_CLEAR_VEC(tmp, 2, ctx); return res; } flint-3.1.3/src/gr_poly/is_monic.c000066400000000000000000000020041461254215100170350ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" truth_t _gr_poly_is_monic(gr_srcptr poly, slong len, gr_ctx_t ctx) { gr_srcptr lead; slong sz = ctx->sizeof_elem; truth_t is_one, is_zero; if (len == 0) return T_FALSE; lead = GR_ENTRY(poly, len - 1, sz); is_one = gr_is_one(lead, ctx); if (is_one == T_TRUE) return T_TRUE; /* in case of unnormalized input */ is_zero = gr_is_zero(lead, ctx); if (is_one == T_FALSE && is_zero == T_FALSE) return T_FALSE; return T_UNKNOWN; } truth_t gr_poly_is_monic(const gr_poly_t res, gr_ctx_t ctx) { return _gr_poly_is_monic(res->coeffs, res->length, ctx); } flint-3.1.3/src/gr_poly/is_one.c000066400000000000000000000015251461254215100165200ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo: faster code when possible */ truth_t gr_poly_is_one(const gr_poly_t poly, gr_ctx_t ctx) { gr_ptr tmp; gr_poly_t one; truth_t res; GR_TMP_INIT(tmp, ctx); if (gr_one(tmp, ctx) != GR_SUCCESS) { res = T_UNKNOWN; } else { one->coeffs = tmp; one->length = 1; one->alloc = 1; res = gr_poly_equal(poly, one, ctx); } GR_TMP_CLEAR(tmp, ctx); return res; } flint-3.1.3/src/gr_poly/is_scalar.c000066400000000000000000000012131461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" truth_t gr_poly_is_scalar(const gr_poly_t poly, gr_ctx_t ctx) { slong len = poly->length; if (len <= 1) return T_TRUE; return _gr_vec_is_zero(GR_ENTRY(poly->coeffs, 1, ctx->sizeof_elem), len - 1, ctx); } flint-3.1.3/src/gr_poly/is_zero.c000066400000000000000000000011771461254215100167210ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: faster code when possible */ truth_t gr_poly_is_zero(const gr_poly_t poly, gr_ctx_t ctx) { if (poly->length == 0) return T_TRUE; return _gr_vec_is_zero(poly->coeffs, poly->length, ctx); } flint-3.1.3/src/gr_poly/log1p_series.c000066400000000000000000000057371461254215100176510ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_special.h" #include "gr_poly.h" int _gr_poly_log1p_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { gr_ptr a; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len == 0) return GR_SUCCESS; flen = FLINT_MIN(flen, len); GR_TMP_INIT(a, ctx); status |= gr_log1p(a, f, ctx); if (flen == 1) { status |= _gr_vec_zero(GR_ENTRY(res, 1, sz), len - 1, ctx); } else if (len == 2) { status |= gr_add_ui(res, f, 1, ctx); status |= gr_div(GR_ENTRY(res, 1, sz), GR_ENTRY(f, 1, sz), res, ctx); } else if (flen == 2 || _gr_vec_is_zero(GR_ENTRY(f, 1, sz), flen - 2, ctx) == T_TRUE) /* f = a + bx^d */ { slong i, j, d = flen - 1; status |= gr_add_ui(res, f, 1, ctx); for (i = 1, j = d; j < len; j += d, i++) { if (i == 1) status |= gr_div(GR_ENTRY(res, j, sz), GR_ENTRY(f, d, sz), res, ctx); else status |= gr_mul(GR_ENTRY(res, j, sz), GR_ENTRY(res, j - d, sz), GR_ENTRY(res, d, sz), ctx); status |= _gr_vec_zero(GR_ENTRY(res, j - d + 1, sz), flen - 2, ctx); } status |= _gr_vec_zero(GR_ENTRY(res, j - d + 1, sz), len - (j - d + 1), ctx); for (i = 2, j = 2 * d; j < len; j += d, i++) status |= gr_div_si(GR_ENTRY(res, j, sz), GR_ENTRY(res, j, sz), i % 2 ? i : -i, ctx); } else { gr_ptr f_diff, f_inv; slong alloc; alloc = len + (flen - 1); GR_TMP_INIT_VEC(f_inv, alloc, ctx); f_diff = GR_ENTRY(f_inv, len, sz); if (status == GR_SUCCESS) { status |= _gr_poly_derivative(f_diff, f, flen, ctx); status |= gr_add_ui(res, f, 1, ctx); status |= _gr_vec_set(GR_ENTRY(res, 1, sz), GR_ENTRY(f, 1, sz), flen - 1, ctx); status |= _gr_poly_div_series(f_inv, f_diff, flen - 1, res, flen, len, ctx); status |= _gr_poly_integral(res, f_inv, len, ctx); } GR_TMP_CLEAR_VEC(f_inv, alloc, ctx); } gr_swap(res, a, ctx); GR_TMP_CLEAR(a, ctx); return status; } int gr_poly_log1p_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_log1p_series(res->coeffs, f->coeffs, f->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/log_series.c000066400000000000000000000056761461254215100174120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_special.h" #include "gr_poly.h" int _gr_poly_log_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len == 0) return GR_SUCCESS; flen = FLINT_MIN(flen, len); if (flen == 1) { status |= gr_log(res, f, ctx); status |= _gr_vec_zero(GR_ENTRY(res, 1, sz), len - 1, ctx); } else if (len == 2) { status |= gr_div(GR_ENTRY(res, 1, sz), GR_ENTRY(f, 1, sz), f, ctx); status |= gr_log(res, f, ctx); } else if (flen == 2 || _gr_vec_is_zero(GR_ENTRY(f, 1, sz), flen - 2, ctx) == T_TRUE) /* f = a + bx^d */ { slong i, j, d = flen - 1; for (i = 1, j = d; j < len; j += d, i++) { if (i == 1) status |= gr_div(GR_ENTRY(res, j, sz), GR_ENTRY(f, d, sz), f, ctx); else status |= gr_mul(GR_ENTRY(res, j, sz), GR_ENTRY(res, j - d, sz), GR_ENTRY(res, d, sz), ctx); status |= _gr_vec_zero(GR_ENTRY(res, j - d + 1, sz), flen - 2, ctx); } status |= _gr_vec_zero(GR_ENTRY(res, j - d + 1, sz), len - (j - d + 1), ctx); for (i = 2, j = 2 * d; j < len; j += d, i++) status |= gr_div_si(GR_ENTRY(res, j, sz), GR_ENTRY(res, j, sz), i % 2 ? i : -i, ctx); status |= gr_log(res, f, ctx); /* done last to allow aliasing */ } else { gr_ptr f_diff, f_inv; gr_ptr a; slong alloc; alloc = (len - 1) + (flen - 1) + 1; GR_TMP_INIT_VEC(f_inv, alloc, ctx); f_diff = GR_ENTRY(f_inv, len - 1, sz); a = GR_ENTRY(f_diff, flen - 1, sz); status |= gr_log(a, f, ctx); if (status == GR_SUCCESS) { status |= _gr_poly_derivative(f_diff, f, flen, ctx); status |= _gr_poly_div_series(f_inv, f_diff, flen - 1, f, flen, len - 1, ctx); status |= _gr_poly_integral(res, f_inv, len, ctx); gr_swap(res, a, ctx); } GR_TMP_CLEAR_VEC(f_inv, alloc, ctx); } return status; } int gr_poly_log_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (len == 0) return gr_poly_zero(res, ctx); if (flen == 0) return GR_DOMAIN; if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_log_series(res->coeffs, f->coeffs, f->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/make_monic.c000066400000000000000000000040261461254215100173450ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* fixme: might return GR_DOMAIN where GR_UNABLE might be more appropriate, in cases where we have an unnormalized input over an inexact/uncomputable domain */ int _gr_poly_make_monic(gr_ptr res, gr_srcptr poly, slong len, gr_ctx_t ctx) { gr_srcptr lead; gr_ptr inv; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (len == 0) return GR_DOMAIN; lead = GR_ENTRY(poly, len - 1, sz); if (gr_is_one(lead, ctx) == T_TRUE) { status = _gr_vec_set(res, poly, len - 1, ctx); } else if (gr_is_neg_one(lead, ctx) == T_TRUE) { status = _gr_vec_neg(res, poly, len - 1, ctx); } else { GR_TMP_INIT(inv, ctx); /* try to multiply by inverse */ status |= gr_inv(inv, lead, ctx); if (status == GR_SUCCESS) { status = _gr_vec_mul_scalar(res, poly, len - 1, inv, ctx); } else { /* otherwise try dividing */ status = _gr_vec_div_scalar(res, poly, len - 1, lead, ctx); } GR_TMP_CLEAR(inv, ctx); } if (status == GR_SUCCESS) status = gr_one(GR_ENTRY(res, len - 1, sz), ctx); return status; } int gr_poly_make_monic(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx) { if (res != src) { int status; gr_poly_fit_length(res, src->length, ctx); status = _gr_poly_make_monic(res->coeffs, src->coeffs, src->length, ctx); _gr_poly_set_length(res, src->length, ctx); return status; } else { return _gr_poly_make_monic(res->coeffs, src->coeffs, src->length, ctx); } } flint-3.1.3/src/gr_poly/mul.c000066400000000000000000000026751461254215100160500ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_mul(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { return _gr_poly_mullow(res, poly1, len1, poly2, len2, len1 + len2 - 1, ctx); } int gr_poly_mul(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { slong len_out; int status; if (poly1->length == 0 || poly2->length == 0) return gr_poly_zero(res, ctx); len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { gr_poly_t t; gr_poly_init2(t, len_out, ctx); status = _gr_poly_mul(t->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(res, len_out, ctx); status = _gr_poly_mul(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); } _gr_poly_set_length(res, len_out, ctx); _gr_poly_normalise(res, ctx); /* needed for non-integral domains */ return status; } flint-3.1.3/src/gr_poly/mul_scalar.c000066400000000000000000000016041461254215100173640ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int gr_poly_mul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx) { int status; slong len = poly->length; if (len == 0 || gr_is_zero(c, ctx) == T_TRUE) return gr_poly_zero(res, ctx); if (res != poly) { gr_poly_fit_length(res, len, ctx); _gr_poly_set_length(res, len, ctx); } status = _gr_vec_mul_scalar(res->coeffs, poly->coeffs, len, c, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/mullow.c000066400000000000000000000072751461254215100165730ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_mullow_generic(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx) { int status; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) return gr_mul(res, poly1, poly2, ctx); if (len1 == 1) return _gr_vec_mul_scalar(res, poly2, n, poly1, ctx); if (len2 == 1) return _gr_vec_mul_scalar(res, poly1, n, poly2, ctx); /* Squaring */ if (poly1 == poly2 && len1 == len2) { slong i, start, stop, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; /* todo: double, square, addmul */ status |= gr_sqr(res, poly1, ctx); status |= gr_mul(GR_ENTRY(res, 1, sz), poly1, GR_ENTRY(poly1, 1, sz), ctx); status |= gr_mul_two(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), ctx); for (i = 2; i < FLINT_MIN(n, 2 * len1 - 3); i++) { start = FLINT_MAX(0, i - len1 + 1); stop = FLINT_MIN(len1 - 1, (i + 1) / 2 - 1); status |= _gr_vec_dot_rev(GR_ENTRY(res, i, sz), NULL, 0, GR_ENTRY(poly1, start, sz), GR_ENTRY(poly1, i - stop, sz), stop - start + 1, ctx); status |= gr_mul_two(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), ctx); if (i % 2 == 0 && i / 2 < len1) /* should be addsqr? */ status |= gr_addmul(GR_ENTRY(res, i, sz), GR_ENTRY(poly1, i / 2, sz), GR_ENTRY(poly1, i / 2, sz), ctx); } if (len1 > 2 && n >= 2 * len1 - 2) { status |= gr_mul(GR_ENTRY(res, 2 * len1 - 3, sz), GR_ENTRY(poly1, len1 - 1, sz), GR_ENTRY(poly1, len1 - 2, sz), ctx); status |= gr_mul_two(GR_ENTRY(res, 2 * len1 - 3, sz), GR_ENTRY(res, 2 * len1 - 3, sz), ctx); } if (n >= 2 * len1 - 1) status |= gr_sqr(GR_ENTRY(res, 2 * len1 - 2, sz), GR_ENTRY(poly1, len1 - 1, sz), ctx); return status; } else { slong i, top1, top2, sz; sz = ctx->sizeof_elem; status = gr_mul(res, poly1, poly2, ctx); for (i = 1; i < n; i++) { top1 = FLINT_MIN(len1 - 1, i); top2 = FLINT_MIN(len2 - 1, i); status |= _gr_vec_dot_rev(GR_ENTRY(res, i, sz), NULL, 0, GR_ENTRY(poly1, i - top2, sz), GR_ENTRY(poly2, i - top1, sz), top1 + top2 - i + 1, ctx); } return status; } } int gr_poly_mullow(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx) { slong len_out; int status; if (poly1->length == 0 || poly2->length == 0 || n == 0) return gr_poly_zero(res, ctx); len_out = poly1->length + poly2->length - 1; n = FLINT_MIN(n, len_out); if (res == poly1 || res == poly2) { gr_poly_t t; gr_poly_init2(t, n, ctx); status = _gr_poly_mullow(t->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(res, n, ctx); status = _gr_poly_mullow(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, ctx); } _gr_poly_set_length(res, n, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/neg.c000066400000000000000000000015101461254215100160070ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int gr_poly_neg(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx) { if (res != src) { int status; gr_poly_fit_length(res, src->length, ctx); status = _gr_vec_neg(res->coeffs, src->coeffs, src->length, ctx); _gr_poly_set_length(res, src->length, ctx); return status; } else { return _gr_vec_neg(res->coeffs, src->coeffs, src->length, ctx); } } flint-3.1.3/src/gr_poly/neg_one.c000066400000000000000000000010761461254215100166570ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int gr_poly_neg_one(gr_poly_t res, gr_ctx_t ctx) { gr_poly_fit_length(res, 1, ctx); _gr_poly_set_length(res, 1, ctx); return gr_neg_one(res->coeffs, ctx); } flint-3.1.3/src/gr_poly/normalise.c000066400000000000000000000015341461254215100172350ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" void _gr_poly_normalise(gr_poly_t poly, gr_ctx_t ctx) { slong i, sz; truth_t eq; i = poly->length - 1; sz = ctx->sizeof_elem; while (i >= 0) { eq = gr_is_zero(GR_ENTRY(poly->coeffs, i, sz), ctx); if (eq == T_TRUE) { GR_MUST_SUCCEED(gr_zero(GR_ENTRY(poly->coeffs, i, sz), ctx)); i--; } else { break; } } poly->length = i + 1; } flint-3.1.3/src/gr_poly/nth_derivative.c000066400000000000000000000040341461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2023 Joel Dahne This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_poly.h" int _gr_poly_nth_derivative(gr_ptr res, gr_srcptr poly, ulong n, slong len, gr_ctx_t ctx) { gr_method_binary_op_fmpz mul_fmpz = GR_BINARY_OP_FMPZ(ctx, MUL_FMPZ); fmpz_t c; slong i; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; /* todo: optimize for small n so that c fits in ulong */ /* todo: optimize for large n and finite characteristic or precision */ fmpz_init(c); fmpz_fac_ui(c, n); status |= mul_fmpz(GR_ENTRY(res, 0, sz), GR_ENTRY(poly, n, sz), c, ctx); for (i = n + 1; i < len; i ++) { fmpz_divexact_ui(c, c, i - n); fmpz_mul_ui(c, c, i); status |= mul_fmpz(GR_ENTRY(res, i - n, sz), GR_ENTRY(poly, i, sz), c, ctx); } fmpz_clear(c); return status; } int gr_poly_nth_derivative(gr_poly_t res, const gr_poly_t poly, ulong n, gr_ctx_t ctx) { int status; const slong len = poly->length; if (len <= n) { status = gr_poly_zero(res, ctx); } else if (n == 0) { status = gr_poly_set(res, poly, ctx); } else if (n == 1) { gr_poly_fit_length(res, len - 1, ctx); status = _gr_poly_derivative(res->coeffs, poly->coeffs, len, ctx); _gr_poly_set_length(res, len - 1, ctx); /* todo: only call in nonzero characteristic */ _gr_poly_normalise(res, ctx); } else { gr_poly_fit_length(res, len - n, ctx); status = _gr_poly_nth_derivative(res->coeffs, poly->coeffs, n, len, ctx); _gr_poly_set_length(res, len - n, ctx); /* todo: only call in nonzero characteristic */ _gr_poly_normalise(res, ctx); } return status; } flint-3.1.3/src/gr_poly/one.c000066400000000000000000000010661461254215100160250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int gr_poly_one(gr_poly_t res, gr_ctx_t ctx) { gr_poly_fit_length(res, 1, ctx); _gr_poly_set_length(res, 1, ctx); return gr_one(res->coeffs, ctx); } flint-3.1.3/src/gr_poly/pow_fmpz.c000066400000000000000000000023211461254215100171000ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_poly.h" int gr_poly_pow_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t exp, gr_ctx_t ctx) { if (fmpz_is_zero(exp)) { return gr_poly_one(res, ctx); } else if (poly->length == 0) { if (fmpz_sgn(exp) < 0) return GR_DOMAIN; else return gr_poly_zero(res, ctx); } else if (poly->length == 1) { int status; gr_poly_fit_length(res, 1, ctx); status = gr_pow_fmpz(res->coeffs, poly->coeffs, exp, ctx); _gr_poly_set_length(res, 1, ctx); _gr_poly_normalise(res, ctx); return status; } else { if (fmpz_sgn(exp) < 0) return GR_DOMAIN; if (COEFF_IS_MPZ(*exp)) return GR_UNABLE; return gr_poly_pow_ui(res, poly, *exp, ctx); } } flint-3.1.3/src/gr_poly/pow_series_fmpq_recurrence.c000066400000000000000000000112151461254215100226600ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "fmpq.h" #include "gr_vec.h" #include "gr_poly.h" /* Implements the recurrence https://en.wikipedia.org/wiki/Formal_power_series#Operations_on_formal_power_series */ int _gr_poly_pow_series_fmpq_recurrence(gr_ptr h, gr_srcptr f, slong flen, const fmpq_t g, slong len, int precomp, gr_ctx_t ctx) { gr_ptr a, b, s, t; slong i, l, alloc; slong sz = ctx->sizeof_elem; int use_divexact; int precomp_constant_term; int precomp_reciprocals; int status = GR_SUCCESS; flen = FLINT_MIN(flen, len); precomp_constant_term = ((precomp & 1) != 0); precomp_reciprocals = ((precomp & 2) != 0); if (!precomp_constant_term) { status |= gr_pow_fmpq(h, f, g, ctx); if (status != GR_SUCCESS) return status; } if (flen == 1) return _gr_vec_zero(GR_ENTRY(h, 1, sz), len - 1, ctx); use_divexact = (fmpz_is_one(fmpq_denref(g)) && (gr_ctx_is_integral_domain(ctx) == T_TRUE) && (gr_ctx_is_finite_characteristic(ctx) == T_FALSE)); alloc = 2 * flen + 2; GR_TMP_INIT_VEC(a, alloc, ctx); b = GR_ENTRY(a, flen, sz); s = GR_ENTRY(b, flen, sz); t = GR_ENTRY(s, 1, sz); /* b[k] = f[k] * q */ if (fmpz_is_one(fmpq_denref(g))) status |= _gr_vec_set(b, f, flen, ctx); /* else if (*fmpq_denref(g) == 2) -- todo: implement status |= _gr_vec_mul_two(b, f, flen, ctx); */ else status |= _gr_vec_mul_scalar_fmpz(b, f, flen, fmpq_denref(g), ctx); /* a[k-1] = f[k] * (k * p) */ status |= _gr_poly_derivative(a, f, flen, ctx); if (!fmpz_is_one(fmpq_numref(g))) { if (*fmpq_numref(g) == -1) status |= _gr_vec_neg(a, a, flen - 1, ctx); else status |= _gr_vec_mul_scalar_fmpz(a, a, flen - 1, fmpq_numref(g), ctx); } if (precomp_reciprocals) status |= gr_inv(b, b, ctx); for (i = 1; i < len && status == GR_SUCCESS; i++) { l = FLINT_MIN(i, flen - 1); status |= _gr_vec_sub(GR_ENTRY(a, 0, sz), GR_ENTRY(a, 0, sz), GR_ENTRY(b, 1, sz), FLINT_MIN(i, flen) - 1, ctx); status |= _gr_vec_dot_rev(s, NULL, 0, GR_ENTRY(a, 0, sz), GR_ENTRY(h, i - l, sz), l, ctx); /* h[i] = s / (i * (q * f[0])) */ if (!precomp_reciprocals) { status |= gr_mul_ui(t, b, i, ctx); if (use_divexact) status |= gr_divexact(GR_ENTRY(h, i, sz), s, t, ctx); else status |= gr_div(GR_ENTRY(h, i, sz), s, t, ctx); } else { /* h[i] = s * (i^(-1) * (q * f[0])^(-1)) */ status |= gr_mul(t, b, GR_ENTRY(h, i, sz), ctx); status |= gr_mul(GR_ENTRY(h, i, sz), s, t, ctx); } } GR_TMP_CLEAR_VEC(a, alloc, ctx); return status; } int gr_poly_pow_series_fmpq_recurrence(gr_poly_t res, const gr_poly_t poly, const fmpq_t exp, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong flen; flen = poly->length; len = FLINT_MAX(len, 0); flen = FLINT_MIN(flen, len); if (fmpq_is_zero(exp)) { if (len == 0) return gr_poly_zero(res, ctx); else return gr_poly_one(res, ctx); } else if (flen == 0) { if (fmpz_sgn(fmpq_numref(exp)) < 0) return GR_DOMAIN; else return gr_poly_zero(res, ctx); } else { if (flen == 1) len = 1; else if (fmpz_is_one(fmpq_denref(exp)) && !COEFF_IS_MPZ(*fmpq_numref(exp)) && *fmpq_numref(exp) > 0) len = poly_pow_length(flen, *fmpq_numref(exp), len); if (res != poly) { gr_poly_fit_length(res, len, ctx); status |= _gr_poly_pow_series_fmpq_recurrence(res->coeffs, poly->coeffs, flen, exp, len, 0, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); } else { gr_poly_t t; gr_poly_init2(t, len, ctx); status |= _gr_poly_pow_series_fmpq_recurrence(t->coeffs, poly->coeffs, flen, exp, len, 0, ctx); _gr_poly_set_length(t, len, ctx); _gr_poly_normalise(t, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } return status; } } flint-3.1.3/src/gr_poly/pow_series_ui.c000066400000000000000000000013671461254215100201240ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_pow_series_ui(gr_ptr res, gr_srcptr f, slong flen, ulong exp, slong len, gr_ctx_t ctx) { return _gr_poly_pow_series_ui_binexp(res, f, flen, exp, len, ctx); } int gr_poly_pow_series_ui(gr_poly_t res, const gr_poly_t poly, ulong exp, slong len, gr_ctx_t ctx) { return gr_poly_pow_series_ui_binexp(res, poly, exp, len, ctx); } flint-3.1.3/src/gr_poly/pow_series_ui_binexp.c000066400000000000000000000071061461254215100214660ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_poly.h" #include "gr_vec.h" #include "gr_poly.h" #define MUL(z, zlen, x, xlen, y, ylen, trunc, ctx) \ do { \ slong slen = FLINT_MIN(xlen + ylen - 1, trunc); \ status |= _gr_poly_mullow(z, x, xlen, y, ylen, slen, ctx); \ zlen = slen; \ } while (0) int _gr_poly_pow_series_ui_binexp(gr_ptr res, gr_srcptr f, slong flen, ulong exp, slong len, gr_ctx_t ctx) { gr_ptr v, R, S, T; slong rlen; ulong bit; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (exp <= 1) { if (exp == 0) return gr_one(res, ctx); else return _gr_vec_set(res, f, len, ctx); } /* (f * x^r)^m = x^(rm) * f^m */ while (flen > 1 && gr_is_zero(f, ctx) == T_TRUE) { if (((ulong) len) > exp) { status |= _gr_vec_zero(res, exp, ctx); len -= exp; res = GR_ENTRY(res, exp, sz); } else { status |= _gr_vec_zero(res, len, ctx); return status; } f = GR_ENTRY(f, 1, sz); flen--; } if (exp == 2) { status |= _gr_poly_mullow(res, f, flen, f, flen, len, ctx); return status; } if (flen == 1) { status |= gr_pow_ui(res, f, exp, ctx); return status; } GR_TMP_INIT_VEC(v, len, ctx); bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2); if (n_zerobits(exp) % 2) { R = res; S = v; } else { R = v; S = res; } MUL(R, rlen, f, flen, f, flen, len, ctx); if (bit & exp) { MUL(S, rlen, R, rlen, f, flen, len, ctx); T = R; R = S; S = T; } while (bit >>= 1) { if (bit & exp) { MUL(S, rlen, R, rlen, R, rlen, len, ctx); MUL(R, rlen, S, rlen, f, flen, len, ctx); } else { MUL(S, rlen, R, rlen, R, rlen, len, ctx); T = R; R = S; S = T; } } GR_TMP_CLEAR_VEC(v, len, ctx); return status; } int gr_poly_pow_series_ui_binexp(gr_poly_t res, const gr_poly_t poly, ulong exp, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong flen, rlen; flen = poly->length; len = FLINT_MAX(len, 0); if (exp == 0 && len != 0) { return gr_poly_one(res, ctx); } else if (flen == 0 || len == 0) { return gr_poly_zero(res, ctx); } else { rlen = poly_pow_length(flen, exp, len); if (res != poly) { gr_poly_fit_length(res, rlen, ctx); status |= _gr_poly_pow_series_ui_binexp(res->coeffs, poly->coeffs, flen, exp, rlen, ctx); _gr_poly_set_length(res, rlen, ctx); _gr_poly_normalise(res, ctx); } else { gr_poly_t t; gr_poly_init2(t, rlen, ctx); status |= _gr_poly_pow_series_ui_binexp(t->coeffs, poly->coeffs, flen, exp, rlen, ctx); _gr_poly_set_length(t, rlen, ctx); _gr_poly_normalise(t, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } return status; } } flint-3.1.3/src/gr_poly/pow_ui.c000066400000000000000000000012731461254215100165460ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_pow_ui(gr_ptr res, gr_srcptr f, slong flen, ulong exp, gr_ctx_t ctx) { return _gr_poly_pow_ui_binexp(res, f, flen, exp, ctx); } int gr_poly_pow_ui(gr_poly_t res, const gr_poly_t poly, ulong exp, gr_ctx_t ctx) { return gr_poly_pow_ui_binexp(res, poly, exp, ctx); } flint-3.1.3/src/gr_poly/pow_ui_binexp.c000066400000000000000000000033311461254215100201100ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_pow_ui_binexp(gr_ptr res, gr_srcptr f, slong flen, ulong exp, gr_ctx_t ctx) { return _gr_poly_pow_series_ui_binexp(res, f, flen, exp, exp * (flen - 1) + 1, ctx); } int gr_poly_pow_ui_binexp(gr_poly_t res, const gr_poly_t poly, ulong exp, gr_ctx_t ctx) { int status = GR_SUCCESS; slong flen, rlen; flen = poly->length; if (exp == 0) { return gr_poly_one(res, ctx); } else if (flen == 0) { return gr_poly_zero(res, ctx); } else { ulong hi, lo; umul_ppmm(hi, lo, exp, flen - 1); if (hi != 0 || lo >= WORD_MAX) return GR_UNABLE; rlen = lo + 1; if (res != poly) { gr_poly_fit_length(res, rlen, ctx); status |= _gr_poly_pow_ui_binexp(res->coeffs, poly->coeffs, flen, exp, ctx); _gr_poly_set_length(res, rlen, ctx); _gr_poly_normalise(res, ctx); } else { gr_poly_t t; gr_poly_init2(t, rlen, ctx); status |= _gr_poly_pow_ui_binexp(t->coeffs, poly->coeffs, flen, exp, ctx); _gr_poly_set_length(t, rlen, ctx); _gr_poly_normalise(t, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } return status; } } flint-3.1.3/src/gr_poly/randtest.c000066400000000000000000000013421461254215100170650ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int gr_poly_randtest(gr_poly_t poly, flint_rand_t state, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_poly_fit_length(poly, len, ctx); status |= _gr_vec_randtest(poly->coeffs, state, len, ctx); _gr_poly_set_length(poly, len, ctx); _gr_poly_normalise(poly, ctx); return status; } flint-3.1.3/src/gr_poly/rem.c000066400000000000000000000032671461254215100160340ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_rem(gr_ptr R, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { int status; gr_ptr Q; slong lenQ = lenA - lenB + 1; if (lenB == 1) return GR_SUCCESS; GR_TMP_INIT_VEC(Q, lenQ, ctx); status = _gr_poly_divrem(Q, R, A, lenA, B, lenB, ctx); GR_TMP_CLEAR_VEC(Q, lenQ, ctx); return status; } int gr_poly_rem(gr_poly_t R, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { slong lenA = A->length, lenB = B->length; slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; if (lenB == 0) return GR_DOMAIN; if (gr_is_zero(GR_ENTRY(B->coeffs, lenB - 1, sz), ctx) != T_FALSE) return GR_UNABLE; if (lenA < lenB) { status |= gr_poly_set(R, A, ctx); return status; } if (R == B) { gr_poly_t t; gr_poly_init2(t, lenB - 1, ctx); status = _gr_poly_rem(t->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); gr_poly_swap(R, t, ctx); gr_poly_clear(t, ctx); } else { gr_poly_fit_length(R, lenB - 1, ctx); status = _gr_poly_rem(R->coeffs, A->coeffs, A->length, B->coeffs, B->length, ctx); } _gr_poly_set_length(R, lenB - 1, ctx); _gr_poly_normalise(R, ctx); return status; } flint-3.1.3/src/gr_poly/resultant.c000066400000000000000000000042401461254215100172620ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* Important: fmpz_mod_poly currently relies on these tuning values. If the are changed to accommodate other rings, fmpz_mod_poly_resultant should override the tuning values. */ #define HGCD_CUTOFF 200 #define HGCD_INNER_CUTOFF 100 int _gr_poly_resultant(gr_ptr res, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { int status = GR_SUCCESS; if (_gr_poly_resultant_small(res, A, lenA, B, lenB, ctx) == GR_SUCCESS) return GR_SUCCESS; if (FLINT_MIN(lenA, lenB) >= HGCD_CUTOFF && gr_ctx_is_finite(ctx) == T_TRUE) status = _gr_poly_resultant_hgcd(res, A, lenA, B, lenB, HGCD_INNER_CUTOFF, HGCD_CUTOFF, ctx); else status = _gr_poly_resultant_euclidean(res, A, lenA, B, lenB, ctx); /* A division-free algorithm should succeed */ if (status != GR_SUCCESS) status = _gr_poly_resultant_sylvester(res, A, lenA, B, lenB, ctx); return status; } int gr_poly_resultant(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) { slong len1 = f->length; slong len2 = g->length; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len1 == 0 || len2 == 0) { return gr_zero(r, ctx); } if (gr_is_zero(GR_ENTRY(f->coeffs, len1 - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(g->coeffs, len2 - 1, sz), ctx) != T_FALSE) { return GR_UNABLE; } if (len1 >= len2) { status |= _gr_poly_resultant(r, f->coeffs, len1, g->coeffs, len2, ctx); } else { status |= _gr_poly_resultant(r, g->coeffs, len2, f->coeffs, len1, ctx); if (((len1 | len2) & 1) == 0) status |= gr_neg(r, r, ctx); } return status; } flint-3.1.3/src/gr_poly/resultant_euclidean.c000066400000000000000000000064011461254215100212740ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" #define GR_VEC_NORM(status, R, lenR, sz, ctx) \ do { \ (void) sz; \ (status) |= _gr_vec_normalise(&(lenR), (R), (lenR), (ctx)); \ } while (0) int _gr_poly_resultant_euclidean(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { gr_ptr u, v, r, t, w, q; slong l0, l1, l2; gr_ptr lc; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len2 == 1) return _gr_poly_resultant_small(res, poly1, len1, poly2, len2, ctx); /* todo: we can skip the q tmp allocation when we have a dedicated rem() */ GR_TMP_INIT_VEC(w, 4 * len1 + 1, ctx); q = w; u = GR_ENTRY(q, len1, sz); v = GR_ENTRY(u, len1, sz); r = GR_ENTRY(v, len1, sz); lc = GR_ENTRY(r, len1, sz); status |= gr_one(res, ctx); status |= _gr_vec_set(u, poly1, len1, ctx); status |= _gr_vec_set(v, poly2, len2, ctx); l1 = len1; l2 = len2; do { l0 = l1; l1 = l2; status |= gr_set(lc, GR_ENTRY(v, l1 - 1, sz), ctx); /* todo: just rem */ status |= _gr_poly_divrem(q, r, u, l0, v, l1, ctx); if (status != GR_SUCCESS) break; l2 = l1 - 1; GR_VEC_NORM(status, r, l2, sz, ctx); { t = u; u = v; v = r; r = t; } if (l2 >= 1) { status |= gr_pow_ui(lc, lc, l0 - l2, ctx); status |= gr_mul(res, res, lc, ctx); if (((l0 | l1) & 1) == 0) status |= gr_neg(res, res, ctx); } else { if (l1 == 1) { status |= gr_pow_ui(lc, lc, l0 - 1, ctx); status |= gr_mul(res, res, lc, ctx); } else { status |= gr_zero(res, ctx); } } } while (l2 > 0); GR_TMP_CLEAR_VEC(w, 4 * len1 + 1, ctx); return status; } int gr_poly_resultant_euclidean(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) { slong len1 = f->length; slong len2 = g->length; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len1 == 0 || len2 == 0) { return gr_zero(r, ctx); } if (gr_is_zero(GR_ENTRY(f->coeffs, len1 - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(g->coeffs, len2 - 1, sz), ctx) != T_FALSE) { return GR_UNABLE; } if (len1 >= len2) { status |= _gr_poly_resultant_euclidean(r, f->coeffs, len1, g->coeffs, len2, ctx); } else { status |= _gr_poly_resultant_euclidean(r, g->coeffs, len2, f->coeffs, len1, ctx); if (((len1 | len2) & 1) == 0) status |= gr_neg(r, r, ctx); } return status; } flint-3.1.3/src/gr_poly/resultant_hgcd.c000066400000000000000000000132561461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" #define GR_VEC_NORM(status, R, lenR, sz, ctx) \ do { \ (void) sz; \ (status) |= _gr_vec_normalise(&(lenR), (R), (lenR), (ctx)); \ } while (0) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ status |= _gr_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), ctx); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ GR_VEC_NORM(status, R, lenR, sz, ctx); \ } \ else \ { \ status |= _gr_vec_set((R), (A), (lenA), ctx); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) /* XXX: Incidentally, this implementation currently supports aliasing. But since this may change in the future, no function other than gr_poly_resultant_hgcd() should rely on this. */ int _gr_poly_resultant_hgcd(gr_ptr res, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) { slong len1 = FLINT_MIN(lenA, lenB), len2 = 2 * lenB; gr_ptr G, J, R, Q, lc; slong lenG, lenJ, lenR, lenQ; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; GR_TMP_INIT_VEC(G, len1, ctx); GR_TMP_INIT_VEC(J, len2, ctx); GR_TMP_INIT(lc, ctx); R = GR_ENTRY(J, lenB, sz); /* todo: avoid Q alloc when we have rem */ GR_TMP_INIT_VEC(Q, lenA, ctx); status |= gr_one(res, ctx); status |= gr_set(lc, GR_ENTRY(B, lenB - 1, sz), ctx); /* todo: only rem */ __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB); (void) lenQ; if (status != GR_SUCCESS) goto cleanup; if (lenR == 0) { if (lenB == 1) { status |= gr_pow_ui(lc, lc, lenA - 1, ctx); status |= gr_mul(res, res, lc, ctx); } else status |= gr_zero(res, ctx); } else { status |= gr_pow_ui(lc, lc, lenA - lenR, ctx); status |= gr_mul(res, res, lc, ctx); if (((lenA | lenB) & 1) == 0) status |= gr_neg(res, res, ctx); status |= _gr_poly_hgcd(res, NULL, NULL, NULL, G, &(lenG), J, &(lenJ), B, lenB, R, lenR, inner_cutoff, ctx); if (status != GR_SUCCESS) goto cleanup; while (lenJ != 0) { status |= gr_set(lc, GR_ENTRY(J, lenJ - 1, sz), ctx); /* todo: only rem */ __divrem(Q, lenQ, R, lenR, G, lenG, J, lenJ); (void) lenQ; if (status != GR_SUCCESS) goto cleanup; if (lenR == 0) { if (lenJ == 1) { status |= gr_pow_ui(lc, lc, lenG - 1, ctx); status |= gr_mul(res, res, lc, ctx); } else { status |= gr_zero(res, ctx); } break; } else { status |= gr_pow_ui(lc, lc, lenG - lenR, ctx); status |= gr_mul(res, res, lc, ctx); if (((lenG | lenJ) & 1) == 0) status |= gr_neg(res, res, ctx); } if (lenJ < cutoff) { gr_ptr r; GR_TMP_INIT(r, ctx); status |= _gr_poly_resultant_euclidean(r, J, lenJ, R, lenR, ctx); status |= gr_mul(res, res, r, ctx); GR_TMP_CLEAR(r, ctx); break; } status |= _gr_poly_hgcd(res, NULL, NULL, NULL, G, &(lenG), J, &(lenJ), J, lenJ, R, lenR, inner_cutoff, ctx); } } cleanup: GR_TMP_CLEAR_VEC(J, len2, ctx); GR_TMP_CLEAR_VEC(G, len1, ctx); GR_TMP_CLEAR(lc, ctx); GR_TMP_CLEAR_VEC(Q, lenA, ctx); return status; } int gr_poly_resultant_hgcd(gr_ptr r, const gr_poly_t f, const gr_poly_t g, slong inner_cutoff, slong cutoff, gr_ctx_t ctx) { slong len1 = f->length; slong len2 = g->length; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len1 == 0 || len2 == 0) { return gr_zero(r, ctx); } if (gr_is_zero(GR_ENTRY(f->coeffs, len1 - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(g->coeffs, len2 - 1, sz), ctx) != T_FALSE) { return GR_UNABLE; } if (len1 >= len2) { status |= _gr_poly_resultant_hgcd(r, f->coeffs, len1, g->coeffs, len2, inner_cutoff, cutoff, ctx); } else { status |= _gr_poly_resultant_hgcd(r, g->coeffs, len2, f->coeffs, len1, inner_cutoff, cutoff, ctx); if (((len1 | len2) & 1) == 0) status |= gr_neg(r, r, ctx); } return status; } flint-3.1.3/src/gr_poly/resultant_small.c000066400000000000000000000122201461254215100204470ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_resultant_small(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { if (poly1 == poly2 && len1 == len2) { return gr_zero(res, ctx); } else if (len2 == 1) { if (len1 == 1) return gr_one(res, ctx); else if (len1 == 2) return gr_set(res, poly2, ctx); else return gr_pow_ui(res, poly2, len1 - 1, ctx); } else if (len1 == 2 && len2 == 2) { /* resultant(a0 + a1*x, b0 + b1*x) = a1*b0 - a0*b1 */ /* todo: use gr_fmms when available */ gr_ptr t, u; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; GR_TMP_INIT2(t, u, ctx); status |= gr_mul(t, GR_ENTRY(poly1, 1, sz), GR_ENTRY(poly2, 0, sz), ctx); status |= gr_mul(u, GR_ENTRY(poly1, 0, sz), GR_ENTRY(poly2, 1, sz), ctx); status |= gr_sub(res, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } else if (len1 == 3 && len2 == 2) { /* res(a0 + a1*x + a2*x**2, b0 + b1*x) = b1*(a0*b1 - a1*b0) + a2*b0^2 */ gr_ptr t, u; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; GR_TMP_INIT2(t, u, ctx); status |= gr_mul(t, GR_ENTRY(poly1, 0, sz), GR_ENTRY(poly2, 1, sz), ctx); status |= gr_mul(u, GR_ENTRY(poly1, 1, sz), GR_ENTRY(poly2, 0, sz), ctx); status |= gr_sub(t, t, u, ctx); status |= gr_mul(t, t, GR_ENTRY(poly2, 1, sz), ctx); status |= gr_sqr(u, GR_ENTRY(poly2, 0, sz), ctx); status |= gr_mul(u, u, GR_ENTRY(poly1, 2, sz), ctx); status |= gr_add(res, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); return status; } else if (len2 == 2) { gr_ptr t, u, v; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i; GR_TMP_INIT_VEC(t, len1 + 2, ctx); u = GR_ENTRY(t, len1, sz); v = GR_ENTRY(t, len1 + 1, sz); status |= _gr_vec_set_powers(t, poly2, len1, ctx); status |= gr_neg(u, GR_ENTRY(poly2, 1, sz), ctx); status |= gr_set(v, u, ctx); for (i = 1; i < len1; i++) { status |= gr_mul(GR_ENTRY(t, len1 - i - 1, sz), GR_ENTRY(t, len1 - i - 1, sz), u, ctx); if (i < len1 - 1) status |= gr_mul(u, u, v, ctx); } status |= _gr_vec_dot(res, NULL, 0, poly1, t, len1, ctx); GR_TMP_CLEAR_VEC(t, len1 + 2, ctx); return status; } else if (len1 == 3 && len2 == 3) { /* res(a0 + a1*x + a2*x^2, b0 + b1*x + b2*x^2, x) = t0=a0*a2; t1=b0*b2; t2=a0*b2; t3=a2*b0; t7=a1*b1; t0*(b1**2-2*t1) + t1*a1**2 + t2*(t2-t7) + t3*(t3-t7) */ gr_ptr t; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; GR_TMP_INIT_VEC(t, 8, ctx); status |= gr_mul(GR_ENTRY(t, 0, sz), GR_ENTRY(poly1, 0, sz), GR_ENTRY(poly1, 2, sz), ctx); status |= gr_mul(GR_ENTRY(t, 1, sz), GR_ENTRY(poly2, 0, sz), GR_ENTRY(poly2, 2, sz), ctx); status |= gr_mul(GR_ENTRY(t, 2, sz), GR_ENTRY(poly1, 0, sz), GR_ENTRY(poly2, 2, sz), ctx); status |= gr_mul(GR_ENTRY(t, 3, sz), GR_ENTRY(poly1, 2, sz), GR_ENTRY(poly2, 0, sz), ctx); status |= gr_mul(GR_ENTRY(t, 7, sz), GR_ENTRY(poly1, 1, sz), GR_ENTRY(poly2, 1, sz), ctx); status |= gr_sqr(GR_ENTRY(t, 4, sz), GR_ENTRY(poly2, 1, sz), ctx); status |= gr_submul_ui(GR_ENTRY(t, 4, sz), GR_ENTRY(t, 1, sz), 2, ctx); status |= gr_sqr(GR_ENTRY(t, 5, sz), GR_ENTRY(poly1, 1, sz), ctx); status |= gr_sub(GR_ENTRY(t, 6, sz), GR_ENTRY(t, 2, sz), GR_ENTRY(t, 7, sz), ctx); status |= gr_sub(GR_ENTRY(t, 7, sz), GR_ENTRY(t, 3, sz), GR_ENTRY(t, 7, sz), ctx); status |= _gr_vec_dot(res, NULL, 0, t, GR_ENTRY(t, 4, sz), 4, ctx); GR_TMP_CLEAR_VEC(t, 8, ctx); return status; } else { return GR_UNABLE; } } int gr_poly_resultant_small(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) { slong len1 = f->length; slong len2 = g->length; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len1 == 0 || len2 == 0) { return gr_zero(r, ctx); } if (gr_is_zero(GR_ENTRY(f->coeffs, len1 - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(g->coeffs, len2 - 1, sz), ctx) != T_FALSE) { return GR_UNABLE; } if (len1 >= len2) { status |= _gr_poly_resultant_small(r, f->coeffs, len1, g->coeffs, len2, ctx); } else { status |= _gr_poly_resultant_small(r, g->coeffs, len2, f->coeffs, len1, ctx); if (((len1 | len2) & 1) == 0) status |= gr_neg(r, r, ctx); } return status; } flint-3.1.3/src/gr_poly/resultant_sylvester.c000066400000000000000000000036151461254215100214070ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" #include "gr_mat.h" int _gr_poly_resultant_sylvester(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { slong d, e, i; int status = GR_SUCCESS; gr_mat_t M; d = len1 - 1; e = len2 - 1; gr_mat_init(M, d + e, d + e, ctx); for (i = 0; i < e; i++) status |= _gr_poly_reverse(gr_mat_entry_ptr(M, i, i, ctx), poly1, len1, len1, ctx); for (i = 0; i < d; i++) status |= _gr_poly_reverse(gr_mat_entry_ptr(M, e + i, i, ctx), poly2, len2, len2, ctx); status |= gr_mat_det(res, M, ctx); gr_mat_clear(M, ctx); return status; } int gr_poly_resultant_sylvester(gr_ptr r, const gr_poly_t f, const gr_poly_t g, gr_ctx_t ctx) { slong len1 = f->length; slong len2 = g->length; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (len1 == 0 || len2 == 0) { return gr_zero(r, ctx); } if (gr_is_zero(GR_ENTRY(f->coeffs, len1 - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(g->coeffs, len2 - 1, sz), ctx) != T_FALSE) { return GR_UNABLE; } if (len1 >= len2) { status |= _gr_poly_resultant_sylvester(r, f->coeffs, len1, g->coeffs, len2, ctx); } else { status |= _gr_poly_resultant_sylvester(r, g->coeffs, len2, f->coeffs, len1, ctx); if (((len1 | len2) & 1) == 0) status |= gr_neg(r, r, ctx); } return status; } flint-3.1.3/src/gr_poly/reverse.c000066400000000000000000000027531461254215100167230ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_reverse(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (res == poly) { slong i; for (i = 0; i < n / 2; i++) gr_swap(GR_ENTRY(res, i, sz), GR_ENTRY(res, n - 1 - i, sz), ctx); for (i = 0; i < n - len; i++) status |= gr_zero(GR_ENTRY(res, i, sz), ctx); } else { slong i; for (i = 0; i < n - len; i++) status |= gr_zero(GR_ENTRY(res, i, sz), ctx); for (i = 0; i < len; i++) status |= gr_set(GR_ENTRY(res, (n - len) + i, sz), GR_ENTRY(poly, (len - 1) - i, sz), ctx); } return status; } int gr_poly_reverse(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx) { slong len = FLINT_MIN(n, poly->length); int status; if (len == 0) return gr_poly_zero(res, ctx); gr_poly_fit_length(res, n, ctx); status = _gr_poly_reverse(res->coeffs, poly->coeffs, len, n, ctx); _gr_poly_set_length(res, n, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/revert_series.c000066400000000000000000000200011461254215100201130ustar00rootroot00000000000000/* Copyright (C) 2011, 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" #include "ulong_extras.h" #define SPECIAL_CASES \ if (flen <= 1) \ return GR_DOMAIN; \ is_zero = gr_is_zero(f, ctx); \ if (is_zero == T_UNKNOWN) \ return GR_UNABLE; \ if (is_zero == T_FALSE) \ return GR_DOMAIN; \ if (n <= 2) \ { \ if (n >= 1) \ status |= gr_zero(res, ctx); \ if (n == 2) \ status |= gr_inv(GR_ENTRY(res, 1, sz), GR_ENTRY(f, 1, sz), ctx); \ return status; \ } int _gr_poly_revert_series_lagrange(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) { slong i; gr_ptr R, S, T; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; truth_t is_zero; SPECIAL_CASES GR_TMP_INIT_VEC(R, 3 * (n - 1), ctx); S = GR_ENTRY(R, n - 1, sz); T = GR_ENTRY(S, n - 1, sz); status |= gr_zero(res, ctx); status |= _gr_poly_inv_series(R, GR_ENTRY(f, 1, sz), FLINT_MIN(flen, n) - 1, n - 1, ctx); /* Inverting leading coefficient failed => domain error */ if (status != GR_SUCCESS) goto cleanup; status |= gr_set(GR_ENTRY(res, 1, sz), GR_ENTRY(R, 0, sz), ctx); status |= _gr_vec_set(S, R, n - 1, ctx); for (i = 2; i < n; i++) { status |= _gr_poly_mullow(T, S, n - 1, R, n - 1, n - 1, ctx); status |= gr_div_ui(GR_ENTRY(res, i, sz), GR_ENTRY(T, i - 1, sz), i, ctx); FLINT_SWAP(gr_ptr, S, T); } /* Dividing by i failed in finite characteristic */ if (status != GR_SUCCESS) status = GR_UNABLE; cleanup: GR_TMP_CLEAR_VEC(R, 3 * (n - 1), ctx); return status; } /* pointer to (x/f)^i */ #define Ri(ii) GR_ENTRY(R, (n-1)*((ii)-1), sz) int _gr_poly_revert_series_lagrange_fast(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) { slong i, j, m; gr_ptr R, S, T, t; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; truth_t is_zero; SPECIAL_CASES m = n_sqrt(n); GR_TMP_INIT_VEC(R, (n - 1) * (m + 2) + 1, ctx); S = GR_ENTRY(R, (n - 1) * m, sz); T = GR_ENTRY(S, n - 1, sz); t = GR_ENTRY(T, n - 1, sz); status |= gr_zero(res, ctx); status |= _gr_poly_inv_series(Ri(1), GR_ENTRY(f, 1, sz), FLINT_MIN(flen, n) - 1, n - 1, ctx); /* Inverting leading coefficient failed => domain error */ if (status != GR_SUCCESS) goto cleanup; /* TODO: when do we prefer squaring for powers? (see also compose_series_brent_kung) */ for (i = 2; i <= m; i++) status |= _gr_poly_mullow(Ri(i), Ri((i + 1) / 2), n - 1, Ri(i / 2), n - 1, n - 1, ctx); status |= gr_set(GR_ENTRY(res, 1, sz), Ri(1), ctx); for (i = 2; i < m; i++) status |= gr_div_ui(GR_ENTRY(res, i, sz), GR_ENTRY(Ri(i), i - 1, sz), i, ctx); status |= _gr_vec_set(S, Ri(m), n - 1, ctx); for (i = m; i < n; i += m) { status |= gr_div_ui(GR_ENTRY(res, i, sz), GR_ENTRY(S, i - 1, sz), i, ctx); for (j = 1; j < m && i + j < n; j++) { status |= _gr_vec_dot_rev(t, NULL, 0, S, Ri(j), i + j, ctx); status |= gr_div_ui(GR_ENTRY(res, i + j, sz), t, i + j, ctx); } if (i + 1 < n) { status |= _gr_poly_mullow(T, S, n - 1, Ri(m), n - 1, n - 1, ctx); FLINT_SWAP(gr_ptr, S, T); } } /* Dividing by i failed in finite characteristic */ if (status != GR_SUCCESS) status = GR_UNABLE; cleanup: GR_TMP_CLEAR_VEC(R, (n - 1) * (m + 2) + 1, ctx); return status; } /* Currently, we choose this so that the basecase succeeds in small characteristic. */ #define NEWTON_CUTOFF 2 int _gr_poly_revert_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) { slong i, k, a[FLINT_BITS]; gr_ptr T, U, V; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; truth_t is_zero; SPECIAL_CASES GR_TMP_INIT_VEC(T, 3 * n, ctx); U = GR_ENTRY(T, n, sz); V = GR_ENTRY(U, n, sz); k = n; for (i = 1; (WORD(1) << i) < k; i++); a[i = 0] = k; while (k > NEWTON_CUTOFF) a[++i] = (k = (k + 1) / 2); status |= _gr_poly_revert_series_lagrange(res, f, flen, k, ctx); if (status != GR_SUCCESS) goto cleanup; status |= _gr_vec_zero(GR_ENTRY(res, k, sz), n - k, ctx); for (i--; i >= 0; i--) { k = a[i]; status |= _gr_poly_compose_series(T, f, FLINT_MIN(flen, k), res, k, k, ctx); status |= _gr_poly_derivative(U, T, k, ctx); status |= gr_zero(GR_ENTRY(U, k - 1, sz), ctx); status |= gr_zero(GR_ENTRY(T, 1, sz), ctx); status |= _gr_poly_div_series(V, T, k, U, k, k, ctx); status |= _gr_poly_derivative(T, res, k, ctx); status |= _gr_poly_mullow(U, V, k, T, k, k, ctx); status |= _gr_vec_sub(res, res, U, k, ctx); } cleanup: GR_TMP_CLEAR_VEC(T, 3 * n, ctx); return status; } int _gr_poly_revert_series(gr_ptr res, gr_srcptr f, slong flen, slong n, gr_ctx_t ctx) { int status; status = _gr_poly_revert_series_lagrange_fast(res, f, flen, n, ctx); /* Newton may succeed where Lagrange fails in finite characteristic */ if (status == GR_UNABLE) status = _gr_poly_revert_series_newton(res, f, flen, n, ctx); return status; } int gr_poly_revert_series_lagrange(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (res != f) { gr_poly_fit_length(res, n, ctx); status |= _gr_poly_revert_series_lagrange(res->coeffs, f->coeffs, flen, n, ctx); } else { gr_poly_t t; gr_poly_init2(t, n, ctx); status |= _gr_poly_revert_series_lagrange(t->coeffs, f->coeffs, flen, n, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } _gr_poly_set_length(res, n, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_revert_series_lagrange_fast(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (res != f) { gr_poly_fit_length(res, n, ctx); status |= _gr_poly_revert_series_lagrange_fast(res->coeffs, f->coeffs, flen, n, ctx); } else { gr_poly_t t; gr_poly_init2(t, n, ctx); status |= _gr_poly_revert_series_lagrange_fast(t->coeffs, f->coeffs, flen, n, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } _gr_poly_set_length(res, n, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_revert_series_newton(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (res != f) { gr_poly_fit_length(res, n, ctx); status |= _gr_poly_revert_series_newton(res->coeffs, f->coeffs, flen, n, ctx); } else { gr_poly_t t; gr_poly_init2(t, n, ctx); status |= _gr_poly_revert_series_newton(t->coeffs, f->coeffs, flen, n, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } _gr_poly_set_length(res, n, ctx); _gr_poly_normalise(res, ctx); return status; } int gr_poly_revert_series(gr_poly_t res, const gr_poly_t f, slong n, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (res != f) { gr_poly_fit_length(res, n, ctx); status |= _gr_poly_revert_series(res->coeffs, f->coeffs, flen, n, ctx); } else { gr_poly_t t; gr_poly_init2(t, n, ctx); status |= _gr_poly_revert_series(t->coeffs, f->coeffs, flen, n, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); } _gr_poly_set_length(res, n, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/rsqrt_series.c000066400000000000000000000027531461254215100177750ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_rsqrt_series_generic(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { if (flen <= 8 || ctx->methods[GR_METHOD_POLY_MULLOW] == (gr_funcptr) _gr_poly_mullow_generic) return _gr_poly_rsqrt_series_basecase(res, f, flen, len, ctx); else return _gr_poly_rsqrt_series_newton(res, f, flen, len, FLINT_MIN(10, len / 2), ctx); } int gr_poly_rsqrt_series(gr_poly_t res, const gr_poly_t h, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; if (len == 0) return gr_poly_zero(res, ctx); hlen = h->length; if (hlen == 0) return GR_DOMAIN; if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_rsqrt_series(t, h, len, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_rsqrt_series(res->coeffs, h->coeffs, h->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/rsqrt_series_basecase.c000066400000000000000000000051701461254215100216170ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: use _gr_poly_pow_series_fmpq_recurrence if possible, when flen is short */ int _gr_poly_rsqrt_series_basecase(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; if (flen == 1) { status |= gr_rsqrt(res, f, ctx); if (status != GR_SUCCESS) return status; status |= _gr_vec_zero(GR_ENTRY(res, 1, sz), len - 1, ctx); } else if (len == 2) { status |= gr_rsqrt(res, f, ctx); if (status != GR_SUCCESS) return status; status |= gr_mul(GR_ENTRY(res, 1, sz), res, GR_ENTRY(f, 1, sz), ctx); status |= gr_div(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), GR_ENTRY(f, 0, sz), ctx); status |= gr_mul_2exp_si(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), -1, ctx); status |= gr_neg(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), ctx); } else { gr_ptr t; GR_TMP_INIT_VEC(t, len, ctx); /* todo: when is it better and valid to invert first? */ /* todo: somehow use gr_rsqrt() for the constant term? */ /* todo: might want to call inv_series rather than inv_series_basecase here; the cutoff could be much lower than that for sqrt */ status |= _gr_poly_sqrt_series_basecase(t, f, flen, len, ctx); status |= _gr_poly_inv_series_basecase(res, t, len, len, ctx); GR_TMP_CLEAR_VEC(t, len, ctx); } return status; } int gr_poly_rsqrt_series_basecase(gr_poly_t res, const gr_poly_t h, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; if (len == 0) return gr_poly_zero(res, ctx); hlen = h->length; if (hlen == 0) return GR_DOMAIN; if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_rsqrt_series_basecase(t, h, len, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_rsqrt_series_basecase(res->coeffs, h->coeffs, h->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/rsqrt_series_miller.c000066400000000000000000000035721461254215100213410ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_rsqrt_series_miller(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; fmpq_t q; status |= gr_rsqrt(res, f, ctx); if (status != GR_SUCCESS) return status; *fmpq_numref(q) = -1; *fmpq_denref(q) = 2; if (gr_ctx_is_finite_characteristic(ctx) == T_TRUE) { status |= _gr_vec_reciprocals(GR_ENTRY(res, 1, sz), len - 1, ctx); if (status == GR_SUCCESS) status |= _gr_poly_pow_series_fmpq_recurrence(res, f, flen, q, len, 3, ctx); } else { status = _gr_poly_pow_series_fmpq_recurrence(res, f, flen, q, len, 1, ctx); } return status; } int gr_poly_rsqrt_series_miller(gr_poly_t res, const gr_poly_t h, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; if (len == 0) return gr_poly_zero(res, ctx); hlen = h->length; if (hlen == 0) return GR_DOMAIN; if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_rsqrt_series_miller(t, h, len, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_rsqrt_series_miller(res->coeffs, h->coeffs, h->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/rsqrt_series_newton.c000066400000000000000000000055541461254215100213710ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_rsqrt_series_newton(gr_ptr g, gr_srcptr h, slong hlen, slong len, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong a[FLINT_BITS]; slong i, m, n; hlen = FLINT_MIN(hlen, len); if (len == 0) return GR_SUCCESS; cutoff = FLINT_MAX(cutoff, 2); a[i = 0] = n = len; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); status |= _gr_poly_rsqrt_series_basecase(g, h, FLINT_MIN(hlen, n), n, ctx); if (status != GR_SUCCESS) return status; /* Alternative: if the basecase fails in small characteristic, fall back to doing Newton iteration all the way. */ #if 0 if (status != GR_SUCCESS) { if (n == 1) return status; else return _gr_poly_rsqrt_series_newton(g, h, hlen, len, 2, ctx); } #endif if (len > n) { gr_ptr t, u; slong tlen, ulen; GR_TMP_INIT_VEC(t, 2 * len, ctx); u = GR_ENTRY(t, len, sz); for (i--; i >= 0; i--) { m = n; n = a[i]; tlen = FLINT_MIN(2 * m - 1, n); ulen = FLINT_MIN(n, m + tlen - 1); status |= _gr_poly_mullow(t, g, m, g, m, tlen, ctx); status |= _gr_poly_mullow(u, g, m, t, tlen, ulen, ctx); status |= _gr_poly_mullow(t, u, ulen, h, FLINT_MIN(hlen, n), n, ctx); /* should be mulmid */ status |= _gr_vec_mul_scalar_2exp_si(GR_ENTRY(g, m, sz), GR_ENTRY(t, m, sz), n - m, -1, ctx); status |= _gr_vec_neg(GR_ENTRY(g, m, sz), GR_ENTRY(g, m, sz), n - m, ctx); } GR_TMP_CLEAR_VEC(t, 2 * len, ctx); } return status; } int gr_poly_rsqrt_series_newton(gr_poly_t res, const gr_poly_t h, slong len, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; if (len == 0) return gr_poly_zero(res, ctx); hlen = h->length; if (hlen == 0) return GR_DOMAIN; if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_rsqrt_series_newton(t, h, len, cutoff, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_rsqrt_series_newton(res->coeffs, h->coeffs, h->length, len, cutoff, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/set.c000066400000000000000000000013621461254215100160360ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int gr_poly_set(gr_poly_t res, const gr_poly_t src, gr_ctx_t ctx) { int status = GR_SUCCESS; if (res != src) { gr_poly_fit_length(res, src->length, ctx); status = _gr_vec_set(res->coeffs, src->coeffs, src->length, ctx); _gr_poly_set_length(res, src->length, ctx); } return status; } flint-3.1.3/src/gr_poly/set_coeff_scalar.c000066400000000000000000000053731461254215100205330ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int gr_poly_set_coeff_scalar(gr_poly_t poly, slong n, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { status |= _gr_vec_zero(GR_ENTRY(poly->coeffs, poly->length, sz), n - poly->length, ctx); poly->length = n + 1; } status |= gr_set(GR_ENTRY(poly->coeffs, n, sz), x, ctx); _gr_poly_normalise(poly, ctx); return status; } int gr_poly_set_coeff_si(gr_poly_t poly, slong n, slong x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { status |= _gr_vec_zero(GR_ENTRY(poly->coeffs, poly->length, sz), n - poly->length, ctx); poly->length = n + 1; } status |= gr_set_si(GR_ENTRY(poly->coeffs, n, sz), x, ctx); _gr_poly_normalise(poly, ctx); return status; } int gr_poly_set_coeff_ui(gr_poly_t poly, slong n, ulong x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { status |= _gr_vec_zero(GR_ENTRY(poly->coeffs, poly->length, sz), n - poly->length, ctx); poly->length = n + 1; } status |= gr_set_ui(GR_ENTRY(poly->coeffs, n, sz), x, ctx); _gr_poly_normalise(poly, ctx); return status; } int gr_poly_set_coeff_fmpz(gr_poly_t poly, slong n, const fmpz_t x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { status |= _gr_vec_zero(GR_ENTRY(poly->coeffs, poly->length, sz), n - poly->length, ctx); poly->length = n + 1; } status |= gr_set_fmpz(GR_ENTRY(poly->coeffs, n, sz), x, ctx); _gr_poly_normalise(poly, ctx); return status; } int gr_poly_set_coeff_fmpq(gr_poly_t poly, slong n, const fmpq_t x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_poly_fit_length(poly, n + 1, ctx); if (n + 1 > poly->length) { status |= _gr_vec_zero(GR_ENTRY(poly->coeffs, poly->length, sz), n - poly->length, ctx); poly->length = n + 1; } status |= gr_set_fmpq(GR_ENTRY(poly->coeffs, n, sz), x, ctx); _gr_poly_normalise(poly, ctx); return status; } flint-3.1.3/src/gr_poly/set_fmpq_poly.c000066400000000000000000000026171461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq_poly.h" #include "gr_vec.h" #include "gr_poly.h" int gr_poly_set_fmpq_poly(gr_poly_t res, const fmpq_poly_t src, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i, len = src->length; const fmpz * coeffs = src->coeffs; gr_ptr res_coeffs; if (len == 0) return gr_poly_zero(res, ctx); /* todo: len == 1 -> set_fmpq */ gr_poly_fit_length(res, len, ctx); res_coeffs = res->coeffs; for (i = 0; i < len; i++) status |= gr_set_fmpz(GR_ENTRY(res_coeffs, i, sz), coeffs + i, ctx); if (!fmpz_is_one(fmpq_poly_denref(src))) { gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_set_fmpz(t, fmpq_poly_denref(src), ctx); status |= gr_inv(t, t, ctx); if (status == GR_SUCCESS) status |= _gr_vec_mul_scalar(res_coeffs, res_coeffs, len, t, ctx); GR_TMP_CLEAR(t, ctx); } _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/set_fmpz_poly.c000066400000000000000000000017031461254215100201340ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "gr_poly.h" int gr_poly_set_fmpz_poly(gr_poly_t res, const fmpz_poly_t src, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i, len = src->length; gr_ptr res_coeffs; if (len == 0) return gr_poly_zero(res, ctx); gr_poly_fit_length(res, len, ctx); res_coeffs = res->coeffs; for (i = 0; i < len; i++) status |= gr_set_fmpz(GR_ENTRY(res_coeffs, i, sz), src->coeffs + i, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/set_gr_poly_other.c000066400000000000000000000027451461254215100210000ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int gr_poly_set_gr_poly_other(gr_poly_t res, const gr_poly_t x, gr_ctx_t x_ctx, gr_ctx_t ctx) { int status = GR_SUCCESS; slong x_sz = x_ctx->sizeof_elem; slong sz = ctx->sizeof_elem; slong i, len = gr_poly_length(x, x_ctx); if (len == 0) { /* Before converting the zero polynomial to the zero polynomial, make sure that 0 -> 0 is a legal conversion between the base rings. */ gr_ptr c, d; GR_TMP_INIT(c, x_ctx); GR_TMP_INIT(d, ctx); status |= gr_poly_zero(res, ctx); status |= gr_set_other(d, c, x_ctx, ctx); GR_TMP_CLEAR(c, x_ctx); GR_TMP_CLEAR(d, ctx); } else { gr_poly_fit_length(res, len, ctx); _gr_poly_set_length(res, len, ctx); for (i = 0; i < len; i++) { status |= gr_set_other(GR_ENTRY(res->coeffs, i, sz), GR_ENTRY(x->coeffs, i, x_sz), x_ctx, ctx); } if (status == GR_SUCCESS) _gr_poly_normalise(res, ctx); else _gr_poly_set_length(res, 0, ctx); } return status; } flint-3.1.3/src/gr_poly/set_length.c000066400000000000000000000012371461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" void _gr_poly_set_length(gr_poly_t poly, slong len, gr_ctx_t ctx) { if (poly->length > len) { GR_MUST_SUCCEED(_gr_vec_zero(GR_ENTRY(poly->coeffs, len, ctx->sizeof_elem), poly->length - len, ctx)); } poly->length = len; } flint-3.1.3/src/gr_poly/set_scalar.c000066400000000000000000000044111461254215100173610ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpq.h" #include "gr_poly.h" int gr_poly_set_scalar(gr_poly_t poly, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) { return gr_poly_zero(poly, ctx); } else { int status; gr_poly_fit_length(poly, 1, ctx); status = gr_set(poly->coeffs, x, ctx); _gr_poly_set_length(poly, 1, ctx); return status; } } int gr_poly_set_si(gr_poly_t poly, slong x, gr_ctx_t ctx) { if (x == 0) { return gr_poly_zero(poly, ctx); } else { int status; gr_poly_fit_length(poly, 1, ctx); status = gr_set_si(poly->coeffs, x, ctx); _gr_poly_set_length(poly, 1, ctx); _gr_poly_normalise(poly, ctx); return status; } } int gr_poly_set_ui(gr_poly_t poly, ulong x, gr_ctx_t ctx) { if (x == 0) { return gr_poly_zero(poly, ctx); } else { int status; gr_poly_fit_length(poly, 1, ctx); status = gr_set_ui(poly->coeffs, x, ctx); _gr_poly_set_length(poly, 1, ctx); _gr_poly_normalise(poly, ctx); return status; } } int gr_poly_set_fmpz(gr_poly_t poly, const fmpz_t x, gr_ctx_t ctx) { if (fmpz_is_zero(x)) { return gr_poly_zero(poly, ctx); } else { int status; gr_poly_fit_length(poly, 1, ctx); status = gr_set_fmpz(poly->coeffs, x, ctx); _gr_poly_set_length(poly, 1, ctx); _gr_poly_normalise(poly, ctx); return status; } } int gr_poly_set_fmpq(gr_poly_t poly, const fmpq_t x, gr_ctx_t ctx) { if (fmpq_is_zero(x)) { return gr_poly_zero(poly, ctx); } else { int status; gr_poly_fit_length(poly, 1, ctx); status = gr_set_fmpq(poly->coeffs, x, ctx); _gr_poly_set_length(poly, 1, ctx); _gr_poly_normalise(poly, ctx); return status; } } flint-3.1.3/src/gr_poly/shift_left.c000066400000000000000000000026471461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_shift_left(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i; /* Copy in reverse to avoid writing over unshifted coefficients */ if (res != poly) { for (i = len; i--; ) status |= gr_set(GR_ENTRY(res, n + i, sz), GR_ENTRY(poly, i, sz), ctx); } else { for (i = len; i--; ) gr_swap(GR_ENTRY(res, n + i, sz), GR_ENTRY(res, i, sz), ctx); } status |= _gr_vec_zero(res, n, ctx); return status; } int gr_poly_shift_left(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; if (n == 0) return gr_poly_set(res, poly, ctx); if (poly->length == 0) return gr_poly_zero(res, ctx); gr_poly_fit_length(res, poly->length + n, ctx); status |= _gr_poly_shift_left(res->coeffs, poly->coeffs, poly->length, n, ctx); _gr_poly_set_length(res, poly->length + n, ctx); return status; } flint-3.1.3/src/gr_poly/shift_right.c000066400000000000000000000026311461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_shift_right(gr_ptr res, gr_srcptr poly, slong len, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i; /* Copy in forward order to avoid writing over unshifted coefficients */ if (res != poly) { for (i = 0; i < len - n; i++) status |= gr_set(GR_ENTRY(res, i, sz), GR_ENTRY(poly, n + i, sz), ctx); } else { for (i = 0; i < len - n; i++) gr_swap(GR_ENTRY(res, i, sz), GR_ENTRY(res, n + i, sz), ctx); } return status; } int gr_poly_shift_right(gr_poly_t res, const gr_poly_t poly, slong n, gr_ctx_t ctx) { int status = GR_SUCCESS; if (n == 0) return gr_poly_set(res, poly, ctx); if (poly->length <= n) return gr_poly_zero(res, ctx); gr_poly_fit_length(res, poly->length - n, ctx); status |= _gr_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n, ctx); _gr_poly_set_length(res, poly->length - n, ctx); return status; } flint-3.1.3/src/gr_poly/sin_cos_series_basecase.c000066400000000000000000000052001461254215100220730ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_sin_cos_series_basecase(gr_ptr s, gr_ptr c, gr_srcptr h, slong hlen, slong n, int times_pi, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong k, alen = FLINT_MIN(n, hlen); gr_ptr a, t, u; hlen = FLINT_MIN(hlen, n); if (times_pi) status |= gr_sin_cos_pi(s, c, h, ctx); else status |= gr_sin_cos(s, c, h, ctx); if (hlen == 1) { status |= _gr_vec_zero(GR_ENTRY(s, 1, sz), n - 1, ctx); status |= _gr_vec_zero(GR_ENTRY(c, 1, sz), n - 1, ctx); return status; } GR_TMP_INIT_VEC(a, alen + 2, ctx); t = GR_ENTRY(a, alen, sz); u = GR_ENTRY(t, 1, sz); for (k = 1; k < alen; k++) status |= gr_mul_ui(GR_ENTRY(a, k, sz), GR_ENTRY(h, k, sz), k, ctx); if (times_pi) { status |= gr_pi(t, ctx); status |= _gr_vec_mul_scalar(GR_ENTRY(a, 1, sz), GR_ENTRY(a, 1, sz), alen - 1, t, ctx); } for (k = 1; k < n; k++) { slong l = FLINT_MIN(k, hlen - 1); status |= _gr_vec_dot_rev(t, NULL, 1, GR_ENTRY(a, 1, sz), GR_ENTRY(s, k - l, sz), l, ctx); status |= _gr_vec_dot_rev(u, NULL, 0, GR_ENTRY(a, 1, sz), GR_ENTRY(c, k - l, sz), l, ctx); status |= gr_div_ui(GR_ENTRY(c, k, sz), t, k, ctx); status |= gr_div_ui(GR_ENTRY(s, k, sz), u, k, ctx); } GR_TMP_CLEAR_VEC(a, alen + 2, ctx); return status; } int gr_poly_sin_cos_series_basecase(gr_poly_t s, gr_poly_t c, const gr_poly_t h, slong n, int times_pi, gr_ctx_t ctx) { slong hlen = h->length; int status = GR_SUCCESS; if (n == 0) { status |= gr_poly_zero(s, ctx); status |= gr_poly_zero(c, ctx); return status; } if (hlen == 0) { status |= gr_poly_zero(s, ctx); status |= gr_poly_one(c, ctx); return status; } if (hlen == 1) n = 1; gr_poly_fit_length(s, n, ctx); gr_poly_fit_length(c, n, ctx); status |= _gr_poly_sin_cos_series_basecase(s->coeffs, c->coeffs, h->coeffs, hlen, n, times_pi, ctx); _gr_poly_set_length(s, n, ctx); _gr_poly_normalise(s, ctx); _gr_poly_set_length(c, n, ctx); _gr_poly_normalise(c, ctx); return status; } flint-3.1.3/src/gr_poly/sin_cos_series_tangent.c000066400000000000000000000071601461254215100217740ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_sin_cos_series_tangent(gr_ptr s, gr_ptr c, gr_srcptr h, slong hlen, slong len, int times_pi, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ptr t, u, v, s0, c0; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { if (times_pi) status |= gr_sin_cos_pi(s, c, h, ctx); else status |= gr_sin_cos(s, c, h, ctx); status |= _gr_vec_zero(GR_ENTRY(s, 1, sz), len - 1, ctx); status |= _gr_vec_zero(GR_ENTRY(c, 1, sz), len - 1, ctx); return status; } /* sin(x) = 2*tan(x/2)/(1+tan(x/2)^2) cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2) */ GR_TMP_INIT_VEC(t, 3 * len + 2, ctx); u = GR_ENTRY(t, len, sz); v = GR_ENTRY(u, len, sz); s0 = GR_ENTRY(v, len, sz); c0 = GR_ENTRY(s0, 1, sz); /* sin, cos of h0 */ if (times_pi) status |= gr_sin_cos_pi(s0, c0, h, ctx); else status |= gr_sin_cos(s0, c0, h, ctx); /* t = tan((h-h0)/2) */ status |= gr_zero(u, ctx); status |= _gr_vec_mul_scalar_2exp_si(GR_ENTRY(u, 1, sz), GR_ENTRY(h, 1, sz), hlen - 1, -1, ctx); if (times_pi) { status |= gr_pi(t, ctx); status |= _gr_vec_mul_scalar(GR_ENTRY(u, 1, sz), GR_ENTRY(u, 1, sz), hlen - 1, t, ctx); } status |= _gr_poly_tan_series(t, u, hlen, len, ctx); /* v = 1 + t^2 */ status |= _gr_poly_mullow(v, t, len, t, len, len, ctx); status |= gr_add_ui(v, v, 1, ctx); /* u = 1/(1+t^2) */ status |= _gr_poly_inv_series(u, v, len, len, ctx); /* sine */ status |= _gr_poly_mullow(s, t, len, u, len, len, ctx); status |= _gr_vec_mul_scalar_2exp_si(s, s, len, 1, ctx); /* cosine */ status |= gr_sub_ui(v, v, 2, ctx); status |= _gr_vec_neg(v, v, len, ctx); status |= _gr_poly_mullow(c, v, len, u, len, len, ctx); /* sin(h0 + h1) = cos(h0) sin(h1) + sin(h0) cos(h1) cos(h0 + h1) = cos(h0) cos(h1) - sin(h0) sin(h1) */ if (gr_is_zero(s0, ctx) != T_TRUE) { status |= _gr_vec_mul_scalar(t, s, len, c0, ctx); status |= _gr_vec_mul_scalar(u, c, len, s0, ctx); status |= _gr_vec_mul_scalar(v, s, len, s0, ctx); status |= _gr_vec_add(s, t, u, len, ctx); status |= _gr_vec_mul_scalar(t, c, len, c0, ctx); status |= _gr_vec_sub(c, t, v, len, ctx); } GR_TMP_CLEAR_VEC(t, 3 * len + 2, ctx); return status; } int gr_poly_sin_cos_series_tangent(gr_poly_t s, gr_poly_t c, const gr_poly_t h, slong n, int times_pi, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen = h->length; if (n == 0) { status |= gr_poly_zero(s, ctx); status |= gr_poly_zero(c, ctx); return status; } if (hlen == 0) { status |= gr_poly_zero(s, ctx); status |= gr_poly_one(c, ctx); return status; } gr_poly_fit_length(s, n, ctx); gr_poly_fit_length(c, n, ctx); status |= _gr_poly_sin_cos_series_tangent(s->coeffs, c->coeffs, h->coeffs, hlen, n, times_pi, ctx); _gr_poly_set_length(s, n, ctx); _gr_poly_normalise(s, ctx); _gr_poly_set_length(c, n, ctx); _gr_poly_normalise(c, ctx); return status; } flint-3.1.3/src/gr_poly/sqrt_series.c000066400000000000000000000026401461254215100176060ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo: characteristic 2, ... */ int _gr_poly_sqrt_series_generic(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { int status; status = _gr_poly_sqrt_series_newton(res, f, flen, len, 2, ctx); if (status != GR_SUCCESS && gr_ctx_is_field(ctx) == T_FALSE) return GR_UNABLE; return status; } int gr_poly_sqrt_series(gr_poly_t res, const gr_poly_t h, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; hlen = h->length; if (hlen == 0 || len == 0) return gr_poly_zero(res, ctx); if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_sqrt_series(t, h, len, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_sqrt_series(res->coeffs, h->coeffs, h->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/sqrt_series_basecase.c000066400000000000000000000077451461254215100214470ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: with a slight rewrite, could allow aliasing */ /* todo: use _gr_poly_pow_series_fmpq_recurrence if possible, when flen is short */ int _gr_poly_sqrt_series_basecase(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; flen = FLINT_MIN(flen, len); status |= gr_sqrt(res, f, ctx); if (status != GR_SUCCESS) return status; if (flen == 1) { status |= _gr_vec_zero(GR_ENTRY(res, 1, sz), len - 1, ctx); } else if (len == 2) { status |= gr_mul(GR_ENTRY(res, 1, sz), res, GR_ENTRY(f, 1, sz), ctx); status |= gr_div(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), GR_ENTRY(f, 0, sz), ctx); status |= gr_mul_2exp_si(GR_ENTRY(res, 1, sz), GR_ENTRY(res, 1, sz), -1, ctx); } else { int is_one, have_inv; gr_ptr rinv = NULL; slong i, l; is_one = (gr_is_one(res, ctx) == T_TRUE); if (!is_one) { GR_TMP_INIT(rinv, ctx); have_inv = (gr_inv(rinv, res, ctx) == GR_SUCCESS); } for (i = 1; i < len; i++) { gr_srcptr initial = GR_ENTRY(res, i, sz); l = (i - 1) / 2; if (i % 2 == 1) { if (i < flen) status |= gr_mul_2exp_si(GR_ENTRY(res, i, sz), GR_ENTRY(f, i, sz), -1, ctx); else initial = NULL; } else { status |= gr_sqr(GR_ENTRY(res, i, sz), GR_ENTRY(res, i / 2, sz), ctx); if (i < flen) status |= gr_sub(GR_ENTRY(res, i, sz), GR_ENTRY(f, i, sz), GR_ENTRY(res, i, sz), ctx); else status |= gr_neg(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), ctx); status |= gr_mul_2exp_si(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), -1, ctx); } if (status != GR_SUCCESS) break; status |= _gr_vec_dot_rev(GR_ENTRY(res, i, sz), initial, 1, GR_ENTRY(res, 1, sz), GR_ENTRY(res, i - l, sz), l, ctx); if (!is_one) { #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif if (have_inv) { #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), rinv, ctx); } else { status |= gr_div(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), res, ctx); if (status != GR_SUCCESS) break; } } } if (!is_one) { GR_TMP_CLEAR(rinv, ctx); } } return status; } int gr_poly_sqrt_series_basecase(gr_poly_t res, const gr_poly_t h, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; hlen = h->length; if (hlen == 0 || len == 0) return gr_poly_zero(res, ctx); if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_sqrt_series_basecase(t, h, len, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_sqrt_series_basecase(res->coeffs, h->coeffs, h->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/sqrt_series_miller.c000066400000000000000000000035141461254215100211530ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_sqrt_series_miller(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; fmpq_t q; status |= gr_sqrt(res, f, ctx); if (status != GR_SUCCESS) return status; *fmpq_numref(q) = 1; *fmpq_denref(q) = 2; if (gr_ctx_is_finite_characteristic(ctx) == T_TRUE) { status |= _gr_vec_reciprocals(GR_ENTRY(res, 1, sz), len - 1, ctx); if (status == GR_SUCCESS) status |= _gr_poly_pow_series_fmpq_recurrence(res, f, flen, q, len, 3, ctx); } else { status = _gr_poly_pow_series_fmpq_recurrence(res, f, flen, q, len, 1, ctx); } return status; } int gr_poly_sqrt_series_miller(gr_poly_t res, const gr_poly_t h, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; hlen = h->length; if (hlen == 0 || len == 0) return gr_poly_zero(res, ctx); if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_sqrt_series(t, h, len, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_sqrt_series_miller(res->coeffs, h->coeffs, h->length, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/sqrt_series_newton.c000066400000000000000000000063021461254215100211770ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_sqrt_series_newton(gr_ptr g, gr_srcptr h, slong hlen, slong len, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong a[FLINT_BITS]; slong i, m, n, alloc; gr_ptr t, u, v; slong tlen, ulen; hlen = FLINT_MIN(hlen, len); if (len == 0) return GR_SUCCESS; if (len < cutoff) return _gr_poly_sqrt_series_basecase(g, h, hlen, len, ctx); cutoff = FLINT_MAX(cutoff, 2); a[i = 0] = n = len; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); status |= _gr_poly_rsqrt_series_basecase(g, h, FLINT_MIN(hlen, n), n, ctx); if (status != GR_SUCCESS) return status; alloc = 2 * len + (len + 1) / 2; GR_TMP_INIT_VEC(t, alloc, ctx); u = GR_ENTRY(t, len, sz); v = GR_ENTRY(u, len, sz); for (i--; i >= 1; i--) { m = n; n = a[i]; tlen = FLINT_MIN(2 * m - 1, n); ulen = FLINT_MIN(n, m + tlen - 1); status |= _gr_poly_mullow(t, g, m, g, m, tlen, ctx); status |= _gr_poly_mullow(u, g, m, t, tlen, ulen, ctx); status |= _gr_poly_mullow(t, u, ulen, h, FLINT_MIN(hlen, n), n, ctx); /* should be mulmid */ status |= _gr_vec_mul_scalar_2exp_si(GR_ENTRY(g, m, sz), GR_ENTRY(t, m, sz), n - m, -1, ctx); status |= _gr_vec_neg(GR_ENTRY(g, m, sz), GR_ENTRY(g, m, sz), n - m, ctx); } m = (len + 1) / 2; n = len; /* Karp-Markstein */ /* todo: cleanup; improve allocations? */ tlen = FLINT_MIN(2 * m - 1, n); status |= _gr_poly_mullow(v, g, m, h, hlen, m, ctx); status |= _gr_poly_mullow(t, v, m, v, m, tlen, ctx); status |= _gr_poly_sub(GR_ENTRY(u, m, sz), GR_ENTRY(h, m, sz), FLINT_MAX(0, FLINT_MIN(hlen - m, n - m)), GR_ENTRY(t, m, sz), FLINT_MAX(0, FLINT_MIN(tlen - m, n - m)), ctx); status |= _gr_poly_mullow(t, g, m, GR_ENTRY(u, m, sz), n - m, n - m, ctx); status |= _gr_vec_mul_scalar_2exp_si(GR_ENTRY(g, m, sz), t, n - m, -1, ctx); _gr_vec_swap(g, v, m, ctx); GR_TMP_CLEAR_VEC(t, alloc, ctx); return status; } int gr_poly_sqrt_series_newton(gr_poly_t res, const gr_poly_t h, slong len, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong hlen; hlen = h->length; if (hlen == 0 || len == 0) return gr_poly_zero(res, ctx); if (hlen == 1) len = 1; if (res == h) { gr_poly_t t; gr_poly_init(t, ctx); status = gr_poly_sqrt_series_newton(t, h, len, cutoff, ctx); gr_poly_swap(res, t, ctx); gr_poly_clear(t, ctx); return status; } gr_poly_fit_length(res, len, ctx); status |= _gr_poly_sqrt_series_newton(res->coeffs, h->coeffs, h->length, len, cutoff, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/squarefree_part.c000066400000000000000000000027461461254215100204420ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int gr_poly_squarefree_part(gr_poly_t res, const gr_poly_t poly, gr_ctx_t ctx) { gr_poly_t t; int status = GR_SUCCESS; /* todo */ if (gr_ctx_is_field(ctx) != T_TRUE || gr_ctx_is_finite_characteristic(ctx) != T_FALSE) return GR_UNABLE; if (poly->length <= 1) return gr_poly_one(res, ctx); if (poly->length == 2) { status |= gr_poly_make_monic(res, poly, ctx); if (status != GR_SUCCESS) return GR_UNABLE; } gr_poly_init(t, ctx); status |= gr_poly_derivative(t, poly, ctx); status |= gr_poly_gcd(t, poly, t, ctx); if (status == GR_SUCCESS) { if (t->length == 1) /* gcd = 1 */ { status |= gr_poly_make_monic(res, poly, ctx); } else { /* should be divexact */ status |= gr_poly_divrem(res, t, poly, t, ctx); if (status == GR_SUCCESS) status |= gr_poly_make_monic(res, res, ctx); } } gr_poly_clear(t, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; return status; } flint-3.1.3/src/gr_poly/sub.c000066400000000000000000000026051461254215100160350ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_sub(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx) { slong sz; int status; slong min = FLINT_MIN(len1, len2); status = _gr_vec_sub(res, poly1, poly2, min, ctx); if (len1 > min) { sz = ctx->sizeof_elem; status |= _gr_vec_set(GR_ENTRY(res, min, sz), GR_ENTRY(poly1, min, sz), len1 - min, ctx); } if (len2 > min) { sz = ctx->sizeof_elem; status |= _gr_vec_neg(GR_ENTRY(res, min, sz), GR_ENTRY(poly2, min, sz), len2 - min, ctx); } return status; } int gr_poly_sub(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx) { int status; slong max = FLINT_MAX(poly1->length, poly2->length); gr_poly_fit_length(res, max, ctx); status = _gr_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, ctx); _gr_poly_set_length(res, max, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/tan_series.c000066400000000000000000000017761461254215100174100ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" int _gr_poly_tan_series(gr_ptr res, gr_srcptr f, slong flen, slong len, gr_ctx_t ctx) { return _gr_poly_tan_series_newton(res, f, flen, len, 20, ctx); } int gr_poly_tan_series(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_tan_series(res->coeffs, f->coeffs, flen, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/tan_series_basecase.c000066400000000000000000000036001461254215100212220ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_tan_series_basecase(gr_ptr g, gr_srcptr h, slong hlen, slong len, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { status |= gr_tan(g, h, ctx); status |= _gr_vec_zero(GR_ENTRY(g, 1, sz), len - 1, ctx); } else if (len == 2) { gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_tan(g, h, ctx); status |= gr_mul(t, g, g, ctx); status |= gr_add_ui(t, t, 1, ctx); status |= gr_mul(GR_ENTRY(g, 1, sz), t, GR_ENTRY(h, 1, sz), ctx); /* safe since hlen >= 2 */ GR_TMP_CLEAR(t, ctx); } else { gr_ptr t, u; GR_TMP_INIT_VEC(t, 2 * len, ctx); u = GR_ENTRY(t, len, sz); status |= _gr_poly_sin_cos_series_basecase(t, u, h, hlen, len, 0, ctx); status |= _gr_poly_div_series(g, t, len, u, len, len, ctx); GR_TMP_CLEAR_VEC(t, 2 * len, ctx); } return status; } int gr_poly_tan_series_basecase(gr_poly_t res, const gr_poly_t f, slong len, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_tan_series_basecase(res->coeffs, f->coeffs, flen, len, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/tan_series_newton.c000066400000000000000000000041401461254215100207660ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_poly.h" int _gr_poly_tan_series_newton(gr_ptr res, gr_srcptr f, slong flen, slong len, slong cutoff, gr_ctx_t ctx) { slong sz = ctx->sizeof_elem; int status = GR_SUCCESS; slong i, m, n; gr_ptr t, u; slong a[FLINT_BITS]; flen = FLINT_MIN(flen, len); if (len < cutoff) return _gr_poly_tan_series_basecase(res, f, flen, len, ctx); cutoff = FLINT_MAX(cutoff, 2); a[i = 0] = n = len; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); status |= _gr_poly_tan_series_basecase(res, f, flen, n, ctx); if (status != GR_SUCCESS) return status; GR_TMP_INIT_VEC(t, 2 * len, ctx); u = GR_ENTRY(t, len, sz); for (i--; i >= 0; i--) { m = n; n = a[i]; status |= _gr_poly_mullow(u, res, m, res, m, n, ctx); status |= gr_add_ui(u, u, 1, ctx); status |= _gr_poly_atan_series(t, res, m, n, ctx); status |= _gr_poly_sub(GR_ENTRY(t, m, sz), GR_ENTRY(f, m, sz), FLINT_MAX(0, flen - m), GR_ENTRY(t, m, sz), n - m, ctx); status |= _gr_poly_mullow(GR_ENTRY(res, m, sz), u, n, GR_ENTRY(t, m, sz), n - m, n - m, ctx); } GR_TMP_CLEAR_VEC(t, 2 * len, ctx); return status; } int gr_poly_tan_series_newton(gr_poly_t res, const gr_poly_t f, slong len, slong cutoff, gr_ctx_t ctx) { slong flen = f->length; int status = GR_SUCCESS; if (flen == 0 || len == 0) return gr_poly_zero(res, ctx); if (flen == 1) len = 1; gr_poly_fit_length(res, len, ctx); status |= _gr_poly_tan_series_newton(res->coeffs, f->coeffs, flen, len, cutoff, ctx); _gr_poly_set_length(res, len, ctx); _gr_poly_normalise(res, ctx); return status; } flint-3.1.3/src/gr_poly/taylor_shift.c000066400000000000000000000017461461254215100177600ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" /* todo: algorithm selection */ int _gr_poly_taylor_shift_generic(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) { if (len <= 20) return _gr_poly_taylor_shift_horner(res, poly, len, c, ctx); else return _gr_poly_taylor_shift_divconquer(res, poly, len, c, ctx); } int gr_poly_taylor_shift(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx) { int status = GR_SUCCESS; if (res != f) status |= gr_poly_set(res, f, ctx); status |= _gr_poly_taylor_shift(res->coeffs, res->coeffs, res->length, c, ctx); return status; } flint-3.1.3/src/gr_poly/taylor_shift_convolution.c000066400000000000000000000057701461254215100224200ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: generalize */ #include "arb.h" #include "acb.h" static int want_division(gr_srcptr f, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_RR_ARB) return arb_bits(f) <= 0.25 * _gr_ctx_get_real_prec(ctx); if (ctx->which_ring == GR_CTX_CC_ACB) return acb_bits(f) <= 0.25 * _gr_ctx_get_real_prec(ctx); return 0; } int _gr_poly_taylor_shift_convolution(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong i, n = len - 1; gr_ptr f, d, t, u; if (res != poly) status |= _gr_vec_set(res, poly, len, ctx); if (gr_is_zero(c, ctx) == T_TRUE || len <= 1) return status; GR_TMP_INIT_VEC(t, 2 * len + 2, ctx); u = GR_ENTRY(t, len, sz); f = GR_ENTRY(u, len, sz); d = GR_ENTRY(f, 1, sz); status |= gr_one(f, ctx); /* todo: vector function for Borel transform */ for (i = 2; i <= n; i++) { status |= gr_mul_ui(f, f, i, ctx); status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), f, ctx); } status |= _gr_poly_reverse(res, res, len, len, ctx); status |= gr_one(GR_ENTRY(t, n, sz), ctx); for (i = n; i > 0; i--) status |= gr_mul_ui(GR_ENTRY(t, i - 1, sz), GR_ENTRY(t, i, sz), i, ctx); if (gr_is_neg_one(c, ctx) == T_TRUE) { for (i = 1; i <= n; i += 2) status |= gr_neg(GR_ENTRY(t, i, sz), GR_ENTRY(t, i, sz), ctx); } else if (gr_is_one(c, ctx) != T_TRUE) { status |= gr_set(d, c, ctx); for (i = 1; i <= n; i++) { status |= gr_mul(GR_ENTRY(t, i, sz), GR_ENTRY(t, i, sz), d, ctx); status |= gr_mul(d, d, c, ctx); } } status |= _gr_poly_mullow(u, res, len, t, len, len, ctx); status |= gr_mul(f, f, f, ctx); if (want_division(f, ctx)) { for (i = 0; i <= n; i++) status |= gr_div(GR_ENTRY(u, i, sz), GR_ENTRY(u, i, sz), f, ctx); status |= gr_one(f, ctx); } else { status |= gr_inv(f, f, ctx); } for (i = n; i >= 0; i--) { status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(u, n - i, sz), f, ctx); status |= gr_mul_ui(f, f, (i == 0) ? 1 : i, ctx); } GR_TMP_CLEAR_VEC(t, 2 * len + 2, ctx); return status; } int gr_poly_taylor_shift_convolution(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx) { int status = GR_SUCCESS; if (res != f) status |= gr_poly_set(res, f, ctx); status |= _gr_poly_taylor_shift_convolution(res->coeffs, res->coeffs, res->length, c, ctx); return status; } flint-3.1.3/src/gr_poly/taylor_shift_divconquer.c000066400000000000000000000030051461254215100222050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: fmpz_poly has a better algorithm (assuming that generating binomial coefficients is fast) */ int _gr_poly_taylor_shift_divconquer(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) { int status; slong sz = ctx->sizeof_elem; status = GR_SUCCESS; if (res != poly) status |= _gr_vec_set(res, poly, len, ctx); if (len <= 1 || gr_is_zero(c, ctx) == T_TRUE) return status; if (len == 2) return gr_addmul(res, GR_ENTRY(res, 1, sz), c, ctx); { gr_ptr t; GR_TMP_INIT_VEC(t, 2, ctx); status |= gr_set(t, c, ctx); status |= gr_one(GR_ENTRY(t, 1, sz), ctx); status |= _gr_poly_compose_divconquer(res, res, len, t, 2, ctx); GR_TMP_CLEAR_VEC(t, 2, ctx); return status; } } int gr_poly_taylor_shift_divconquer(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx) { int status = GR_SUCCESS; if (res != f) status |= gr_poly_set(res, f, ctx); status |= _gr_poly_taylor_shift_divconquer(res->coeffs, res->coeffs, res->length, c, ctx); return status; } flint-3.1.3/src/gr_poly/taylor_shift_horner.c000066400000000000000000000037531461254215100213350ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" /* todo: use vector functions when overlap behavior is guaranteed? */ int _gr_poly_taylor_shift_horner(gr_ptr res, gr_srcptr poly, slong len, gr_srcptr c, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i, j; slong sz = ctx->sizeof_elem; if (res != poly) status |= _gr_vec_set(res, poly, len, ctx); if (gr_is_one(c, ctx) == T_TRUE) { gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); for (i = len - 2; i >= 0; i--) for (j = i; j < len - 1; j++) status |= add(GR_ENTRY(res, j, sz), GR_ENTRY(res, j, sz), GR_ENTRY(res, j + 1, sz), ctx); } else if (gr_is_neg_one(c, ctx) == T_TRUE) { gr_method_binary_op sub = GR_BINARY_OP(ctx, SUB); for (i = len - 2; i >= 0; i--) for (j = i; j < len - 1; j++) status |= sub(GR_ENTRY(res, j, sz), GR_ENTRY(res, j, sz), GR_ENTRY(res, j + 1, sz), ctx); } else if (gr_is_zero(c, ctx) != T_TRUE) { /* todo: when we have generic addmul, use a temporary */ gr_method_binary_op addmul = GR_BINARY_OP(ctx, ADDMUL); for (i = len - 2; i >= 0; i--) for (j = i; j < len - 1; j++) status |= addmul(GR_ENTRY(res, j, sz), GR_ENTRY(res, j + 1, sz), c, ctx); } return status; } int gr_poly_taylor_shift_horner(gr_poly_t res, const gr_poly_t f, gr_srcptr c, gr_ctx_t ctx) { int status = GR_SUCCESS; if (res != f) status |= gr_poly_set(res, f, ctx); status |= _gr_poly_taylor_shift_horner(res->coeffs, res->coeffs, res->length, c, ctx); return status; } flint-3.1.3/src/gr_poly/test/000077500000000000000000000000001461254215100160545ustar00rootroot00000000000000flint-3.1.3/src/gr_poly/test/main.c000066400000000000000000000106151461254215100171470ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-atan_series.c" #include "t-compose.c" #include "t-compose_divconquer.c" #include "t-compose_horner.c" #include "t-compose_series.c" #include "t-div_basecase.c" #include "t-div.c" #include "t-div_divconquer.c" #include "t-divexact.c" #include "t-div_newton.c" #include "t-divrem_basecase.c" #include "t-divrem.c" #include "t-divrem_divconquer.c" #include "t-divrem_newton.c" #include "t-div_series.c" #include "t-evaluate.c" #include "t-evaluate_horner.c" #include "t-evaluate_modular.c" #include "t-evaluate_other.c" #include "t-evaluate_other_rectangular.c" #include "t-evaluate_rectangular.c" #include "t-evaluate_vec_fast.c" #include "t-exp_series.c" #include "t-factor_squarefree.c" #include "t-gcd.c" #include "t-gcd_euclidean.c" #include "t-gcd_hgcd.c" #include "t-hgcd.c" #include "t-integral.c" #include "t-inv_series.c" #include "t-log_series.c" #include "t-make_monic.c" #include "t-nth_derivative.c" #include "t-pow_series_fmpq.c" #include "t-pow_series_ui.c" #include "t-pow_ui.c" #include "t-rem.c" #include "t-resultant.c" #include "t-resultant_euclidean.c" #include "t-resultant_hgcd.c" #include "t-resultant_sylvester.c" #include "t-revert_series.c" #include "t-roots.c" #include "t-roots_other.c" #include "t-rsqrt_series.c" #include "t-shift_left_right.c" #include "t-sqrt_series.c" #include "t-squarefree_part.c" #include "t-taylor_shift.c" #include "t-taylor_shift_convolution.c" #include "t-taylor_shift_divconquer.c" #include "t-taylor_shift_horner.c" #include "t-xgcd_euclidean.c" #include "t-xgcd_hgcd.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(gr_poly_atan_series), TEST_FUNCTION(gr_poly_compose), TEST_FUNCTION(gr_poly_compose_divconquer), TEST_FUNCTION(gr_poly_compose_horner), TEST_FUNCTION(gr_poly_compose_series), TEST_FUNCTION(gr_poly_div_basecase), TEST_FUNCTION(gr_poly_div), TEST_FUNCTION(gr_poly_div_divconquer), TEST_FUNCTION(gr_poly_divexact), TEST_FUNCTION(gr_poly_div_newton), TEST_FUNCTION(gr_poly_divrem_basecase), TEST_FUNCTION(gr_poly_divrem), TEST_FUNCTION(gr_poly_divrem_divconquer), TEST_FUNCTION(gr_poly_divrem_newton), TEST_FUNCTION(gr_poly_div_series), TEST_FUNCTION(gr_poly_evaluate), TEST_FUNCTION(gr_poly_evaluate_horner), TEST_FUNCTION(gr_poly_evaluate_modular), TEST_FUNCTION(gr_poly_evaluate_other), TEST_FUNCTION(gr_poly_evaluate_other_rectangular), TEST_FUNCTION(gr_poly_evaluate_rectangular), TEST_FUNCTION(gr_poly_evaluate_vec_fast), TEST_FUNCTION(gr_poly_exp_series), TEST_FUNCTION(gr_poly_factor_squarefree), TEST_FUNCTION(gr_poly_gcd), TEST_FUNCTION(gr_poly_gcd_euclidean), TEST_FUNCTION(gr_poly_gcd_hgcd), TEST_FUNCTION(gr_poly_hgcd), TEST_FUNCTION(gr_poly_integral), TEST_FUNCTION(gr_poly_inv_series), TEST_FUNCTION(gr_poly_log_series), TEST_FUNCTION(gr_poly_make_monic), TEST_FUNCTION(gr_poly_nth_derivative), TEST_FUNCTION(gr_poly_pow_series_fmpq), TEST_FUNCTION(gr_poly_pow_series_ui), TEST_FUNCTION(gr_poly_pow_ui), TEST_FUNCTION(gr_poly_rem), TEST_FUNCTION(gr_poly_resultant), TEST_FUNCTION(gr_poly_resultant_euclidean), TEST_FUNCTION(gr_poly_resultant_hgcd), TEST_FUNCTION(gr_poly_resultant_sylvester), TEST_FUNCTION(gr_poly_revert_series), TEST_FUNCTION(gr_poly_roots), TEST_FUNCTION(gr_poly_roots_other), TEST_FUNCTION(gr_poly_rsqrt_series), TEST_FUNCTION(gr_poly_shift_left_right), TEST_FUNCTION(gr_poly_sqrt_series), TEST_FUNCTION(gr_poly_squarefree_part), TEST_FUNCTION(gr_poly_taylor_shift), TEST_FUNCTION(gr_poly_taylor_shift_convolution), TEST_FUNCTION(gr_poly_taylor_shift_divconquer), TEST_FUNCTION(gr_poly_taylor_shift_horner), TEST_FUNCTION(gr_poly_xgcd_euclidean), TEST_FUNCTION(gr_poly_xgcd_hgcd) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/gr_poly/test/t-atan_series.c000066400000000000000000000063651461254215100207700ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_atan_series(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; gr_poly_t a, b, c, d; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(a, ctx); gr_poly_init(b, ctx); gr_poly_init(c, ctx); gr_poly_init(d, ctx); n = n_randint(state, 5); GR_MUST_SUCCEED(gr_poly_randtest(a, state, 8, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(b, state, 8, ctx)); switch (which) { case 0: status |= gr_poly_atan_series(b, a, n, ctx); break; case 1: status |= gr_poly_set(b, a, ctx); status |= gr_poly_atan_series(b, b, n, ctx); break; case 2: status |= gr_poly_atanh_series(b, a, n, ctx); break; case 3: status |= gr_poly_set(b, a, ctx); status |= gr_poly_atanh_series(b, b, n, ctx); break; default: flint_abort(); } if (status == GR_SUCCESS) { /* Check 2 atan(a) = atan(2a/(1-a^2)) + C */ /* 2 atanh(a) = atanh(2a/(1+a^2)) + C */ status |= gr_poly_mullow(c, a, a, n, ctx); status |= gr_poly_one(d, ctx); if (which == 0 || which == 1) status |= gr_poly_sub(c, d, c, ctx); else status |= gr_poly_add(c, d, c, ctx); status |= gr_poly_add(d, a, a, ctx); /* todo: should have mul_2exp / mul_two */ status |= gr_poly_div_series(c, d, c, n, ctx); if (which == 0 || which == 1) status |= gr_poly_atan_series(c, c, n, ctx); else status |= gr_poly_atanh_series(c, c, n, ctx); status |= gr_poly_add(d, b, b, ctx); /* todo: also check the first coefficient */ status |= gr_poly_set_coeff_si(c, 0, 0, ctx); status |= gr_poly_set_coeff_si(d, 0, 0, ctx); if (status == GR_SUCCESS && gr_poly_equal(c, d, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("which = %d, n = %wd\n", which, n); flint_printf("a = "); gr_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); gr_poly_print(b, ctx); flint_printf("\n\n"); flint_printf("c = "); gr_poly_print(c, ctx); flint_printf("\n\n"); flint_printf("d = "); gr_poly_print(d, ctx); flint_printf("\n\n"); flint_abort(); } } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_poly_clear(c, ctx); gr_poly_clear(d, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_atan_series, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_atan_series(state, n_randint(state, 4)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-compose.c000066400000000000000000000056411461254215100201340ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_compose, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, FG; gr_poly_t x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); gr_poly_init(x, ctx); gr_poly_init(Fx, ctx); gr_poly_init(Gx, ctx); gr_poly_init(FxGx, ctx); gr_poly_init(FGx, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(x, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(Fx, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_compose(Fx, F, x, ctx); status |= gr_poly_set(Gx, x, ctx); /* test aliasing */ status |= gr_poly_compose(Gx, G, Gx, ctx); status |= gr_poly_add(FxGx, Fx, Gx, ctx); status |= gr_poly_compose_horner(FGx, FG, x, ctx); /* also compare with Horner */ if (status == GR_SUCCESS && gr_poly_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_poly_print(x, ctx); flint_printf("\n"); flint_printf("Fx = "); gr_poly_print(Fx, ctx); flint_printf("\n"); flint_printf("Gx = "); gr_poly_print(Gx, ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_poly_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); gr_poly_print(FGx, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_poly_clear(x, ctx); gr_poly_clear(Fx, ctx); gr_poly_clear(Gx, ctx); gr_poly_clear(FxGx, ctx); gr_poly_clear(FGx, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-compose_divconquer.c000066400000000000000000000056461461254215100224000ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_compose_divconquer, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, FG; gr_poly_t x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); gr_poly_init(x, ctx); gr_poly_init(Fx, ctx); gr_poly_init(Gx, ctx); gr_poly_init(FxGx, ctx); gr_poly_init(FGx, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(x, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(Fx, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_compose_divconquer(Fx, F, x, ctx); status |= gr_poly_set(Gx, x, ctx); /* test aliasing */ status |= gr_poly_compose_divconquer(Gx, G, Gx, ctx); status |= gr_poly_add(FxGx, Fx, Gx, ctx); status |= gr_poly_compose_divconquer(FGx, FG, x, ctx); if (status == GR_SUCCESS && gr_poly_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_poly_print(x, ctx); flint_printf("\n"); flint_printf("Fx = "); gr_poly_print(Fx, ctx); flint_printf("\n"); flint_printf("Gx = "); gr_poly_print(Gx, ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_poly_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); gr_poly_print(FGx, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_poly_clear(x, ctx); gr_poly_clear(Fx, ctx); gr_poly_clear(Gx, ctx); gr_poly_clear(FxGx, ctx); gr_poly_clear(FGx, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-compose_horner.c000066400000000000000000000056261461254215100215140ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_compose_horner, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, FG; gr_poly_t x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); /* Hack: avoid because slow */ while (ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); gr_poly_init(x, ctx); gr_poly_init(Fx, ctx); gr_poly_init(Gx, ctx); gr_poly_init(FxGx, ctx); gr_poly_init(FGx, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(x, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_randtest(Fx, state, 1 + n_randint(state, 12), ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_compose_horner(Fx, F, x, ctx); status |= gr_poly_set(Gx, x, ctx); /* test aliasing */ status |= gr_poly_compose_horner(Gx, G, Gx, ctx); status |= gr_poly_add(FxGx, Fx, Gx, ctx); status |= gr_poly_compose_horner(FGx, FG, x, ctx); if (status == GR_SUCCESS && gr_poly_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_poly_print(x, ctx); flint_printf("\n"); flint_printf("Fx = "); gr_poly_print(Fx, ctx); flint_printf("\n"); flint_printf("Gx = "); gr_poly_print(Gx, ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_poly_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); gr_poly_print(FGx, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_poly_clear(x, ctx); gr_poly_clear(Fx, ctx); gr_poly_clear(Gx, ctx); gr_poly_clear(FxGx, ctx); gr_poly_clear(FGx, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-compose_series.c000066400000000000000000000110011461254215100214710ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_compose_series(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; gr_poly_t A, B, C, D, E, F; int status = GR_SUCCESS; if (n_randint(state, 4) == 0) gr_ctx_init_random(ctx, state); else gr_ctx_init_fmpz(ctx); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(D, ctx); gr_poly_init(E, ctx); gr_poly_init(F, ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 20); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(B, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(C, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_set_coeff_si(B, 0, 0, ctx)); switch (which) { case 0: status |= gr_poly_compose_series_horner(C, A, B, n, ctx); break; case 1: status |= gr_poly_set(C, A, ctx); status |= gr_poly_compose_series_horner(C, C, B, n, ctx); break; case 2: status |= gr_poly_set(C, B, ctx); status |= gr_poly_compose_series_horner(C, A, C, n, ctx); break; case 3: status |= gr_poly_compose_series_brent_kung(C, A, B, n, ctx); break; case 4: status |= gr_poly_set(C, A, ctx); status |= gr_poly_compose_series_brent_kung(C, C, B, n, ctx); break; case 5: status |= gr_poly_set(C, B, ctx); status |= gr_poly_compose_series_brent_kung(C, A, C, n, ctx); break; case 6: status |= gr_poly_compose_series_divconquer(C, A, B, n, ctx); break; case 7: status |= gr_poly_set(C, A, ctx); status |= gr_poly_compose_series_divconquer(C, C, B, n, ctx); break; case 8: status |= gr_poly_set(C, B, ctx); status |= gr_poly_compose_series_divconquer(C, A, C, n, ctx); break; case 9: status |= gr_poly_compose_series(C, A, B, n, ctx); break; case 10: status |= gr_poly_set(C, A, ctx); status |= gr_poly_compose_series(C, C, B, n, ctx); break; case 11: status |= gr_poly_set(C, B, ctx); status |= gr_poly_compose_series(C, A, C, n, ctx); break; default: flint_abort(); } if (status == GR_SUCCESS) { /* compare with naive composition */ slong i; for (i = 0; i < FLINT_MIN(A->length, n); i++) { if (i == 0) status |= gr_poly_one(E, ctx); else status |= gr_poly_mullow(E, E, B, n, ctx); status |= gr_poly_mul_scalar(F, E, gr_poly_entry_ptr(A, i, ctx), ctx); status |= gr_poly_add(D, D, F, ctx); } status |= gr_poly_truncate(D, D, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(C, D, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("which = %d\n\n", which); gr_ctx_println(ctx); flint_printf("n = %wd\n", n); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("D = "); gr_poly_print(D, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(D, ctx); gr_poly_clear(E, ctx); gr_poly_clear(F, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_compose_series, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { test_compose_series(state, n_randint(state, 12)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-div.c000066400000000000000000000056451461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_div, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, Q2; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(Q2, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 6), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 4)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div(Q, Q, B, ctx); break; case 1: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_div(Q, A, B, ctx); break; case 3: status |= gr_poly_set(A, B, ctx); status |= gr_poly_div(Q, A, A, ctx); break; case 4: status |= gr_poly_set(A, B, ctx); status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div(Q, Q, Q, ctx); break; default: status |= gr_poly_div(Q, A, B, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_divrem(Q2, R, A, B, ctx); if (status == GR_SUCCESS && gr_poly_equal(Q, Q2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("Q2 = "); gr_poly_print(Q2, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(Q2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-div_basecase.c000066400000000000000000000057331461254215100211010ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_div_basecase, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, Q2; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(Q2, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 6), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 4)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div_basecase(Q, Q, B, ctx); break; case 1: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_div_basecase(Q, A, B, ctx); break; case 3: status |= gr_poly_set(A, B, ctx); status |= gr_poly_div_basecase(Q, A, A, ctx); break; case 4: status |= gr_poly_set(A, B, ctx); status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div_basecase(Q, Q, Q, ctx); break; default: status |= gr_poly_div_basecase(Q, A, B, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_divrem(Q2, R, A, B, ctx); if (status == GR_SUCCESS && gr_poly_equal(Q, Q2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("Q2 = "); gr_poly_print(Q2, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(Q2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-div_divconquer.c000066400000000000000000000061141461254215100215040ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_div_divconquer, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, Q2; slong cutoff; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(Q2, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 6), ctx); cutoff = n_randint(state, 10); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 4)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div_divconquer(Q, Q, B, cutoff, ctx); break; case 1: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_div_divconquer(Q, A, B, cutoff, ctx); break; case 3: status |= gr_poly_set(A, B, ctx); status |= gr_poly_div_divconquer(Q, A, A, cutoff, ctx); break; case 4: status |= gr_poly_set(A, B, ctx); status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div_divconquer(Q, Q, Q, cutoff, ctx); break; default: status |= gr_poly_div_divconquer(Q, A, B, cutoff, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_divrem(Q2, R, A, B, ctx); if (status == GR_SUCCESS && gr_poly_equal(Q, Q2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("Q2 = "); gr_poly_print(Q2, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(Q2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-div_newton.c000066400000000000000000000057171461254215100206470ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_div_newton, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, Q2; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(Q2, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 6), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 4)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div_newton(Q, Q, B, ctx); break; case 1: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_div_newton(Q, A, B, ctx); break; case 3: status |= gr_poly_set(A, B, ctx); status |= gr_poly_div_newton(Q, A, A, ctx); break; case 4: status |= gr_poly_set(A, B, ctx); status |= gr_poly_set(Q, A, ctx); status |= gr_poly_div_newton(Q, Q, Q, ctx); break; default: status |= gr_poly_div_newton(Q, A, B, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_divrem(Q2, R, A, B, ctx); if (status == GR_SUCCESS && gr_poly_equal(Q, Q2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("Q2 = "); gr_poly_print(Q2, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(Q2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-div_series.c000066400000000000000000000107641461254215100206250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_div_series(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; gr_poly_t A, B, C, D, E; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(D, ctx); gr_poly_init(E, ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 20); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(B, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(C, state, 1 + n_randint(state, 20), ctx)); /* todo: randomly make exact multiple? */ switch (which) { case 0: status |= gr_poly_div_series_basecase(C, A, B, n, ctx); break; case 1: status |= gr_poly_set(C, A, ctx); status |= gr_poly_div_series_basecase(C, C, B, n, ctx); break; case 2: status |= gr_poly_set(C, B, ctx); status |= gr_poly_div_series_basecase(C, A, C, n, ctx); break; case 3: status |= gr_poly_div_series_newton(C, A, B, n, n_randint(state, 20), ctx); break; case 4: status |= gr_poly_set(C, A, ctx); status |= gr_poly_div_series_newton(C, C, B, n, n_randint(state, 20), ctx); break; case 5: status |= gr_poly_set(C, B, ctx); status |= gr_poly_div_series_newton(C, A, C, n, n_randint(state, 20), ctx); break; case 6: status |= gr_poly_div_series(C, A, B, n, ctx); break; case 7: status |= gr_poly_set(C, A, ctx); status |= gr_poly_div_series(C, C, B, n, ctx); break; case 8: status |= gr_poly_set(C, B, ctx); status |= gr_poly_div_series(C, A, C, n, ctx); break; case 9: status |= gr_poly_div_series_invmul(C, A, B, n, ctx); break; case 10: status |= gr_poly_set(C, A, ctx); status |= gr_poly_div_series_invmul(C, C, B, n, ctx); break; case 11: status |= gr_poly_set(C, B, ctx); status |= gr_poly_div_series_invmul(C, A, C, n, ctx); break; case 12: status |= gr_poly_div_series_divconquer(C, A, B, n, n_randint(state, 20), ctx); break; case 13: status |= gr_poly_set(C, A, ctx); status |= gr_poly_div_series_divconquer(C, C, B, n, n_randint(state, 20), ctx); break; case 14: status |= gr_poly_set(C, B, ctx); status |= gr_poly_div_series_divconquer(C, A, C, n, n_randint(state, 20), ctx); break; default: flint_abort(); } if (status == GR_SUCCESS) { status |= gr_poly_mullow(D, C, B, n, ctx); status |= gr_poly_truncate(E, A, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(D, E, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("which = %d, n = %wd\n\n", which, n); gr_ctx_println(ctx); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n\n"); flint_printf("D = "); gr_poly_print(D, ctx); flint_printf("\n\n"); flint_printf("E = "); gr_poly_print(E, ctx); flint_printf("\n\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(D, ctx); gr_poly_clear(E, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_div_series, state) { slong iter; for (iter = 0; iter < 10000; iter++) { test_div_series(state, n_randint(state, 15)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-divexact.c000066400000000000000000000101011461254215100202610ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_divexact, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, Q2; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(Q2, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); if (gr_poly_is_zero(B, ctx) == T_FALSE) { status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q2, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_mul(A, Q2, B, ctx); switch (n_randint(state, 12)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divexact(Q, Q, B, ctx); break; case 1: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divexact(Q, A, B, ctx); break; case 2: status |= gr_poly_divexact(Q, A, B, ctx); break; case 3: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divexact_basecase(Q, Q, B, ctx); break; case 4: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divexact_basecase(Q, A, B, ctx); break; case 5: status |= gr_poly_divexact_basecase(Q, A, B, ctx); break; case 6: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divexact_bidirectional(Q, Q, B, ctx); break; case 7: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divexact_bidirectional(Q, A, B, ctx); break; case 8: status |= gr_poly_divexact_bidirectional(Q, A, B, ctx); break; case 9: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divexact_basecase_bidirectional(Q, Q, B, ctx); break; case 10: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divexact_basecase_bidirectional(Q, A, B, ctx); break; default: status |= gr_poly_divexact_basecase_bidirectional(Q, A, B, ctx); break; } if (gr_ctx_is_integral_domain(ctx) == T_TRUE && ((status == GR_SUCCESS && gr_poly_equal(Q, Q2, ctx) == T_FALSE) || status == GR_DOMAIN || (ctx->which_ring == GR_CTX_FMPZ && status != GR_SUCCESS))) { flint_printf("FAIL\n\n"); flint_printf("%d\n", status); gr_ctx_println(ctx); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("Q2 = "); gr_poly_print(Q2, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(Q2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-divrem.c000066400000000000000000000060371461254215100177550ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_divrem, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, QBR; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(QBR, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 6), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 5)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divrem(Q, R, Q, B, ctx); break; case 1: status |= gr_poly_set(R, A, ctx); status |= gr_poly_divrem(Q, R, R, B, ctx); break; case 2: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divrem(Q, R, A, Q, ctx); break; case 3: status |= gr_poly_set(R, B, ctx); status |= gr_poly_divrem(Q, R, A, R, ctx); break; default: status |= gr_poly_divrem(Q, R, A, B, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_mul(QBR, Q, B, ctx); status |= gr_poly_add(QBR, QBR, R, ctx); if (status == GR_SUCCESS && gr_poly_equal(QBR, A, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("R = "); gr_poly_print(R, ctx); flint_printf("\n"); flint_printf("Q*B + R = "); gr_poly_print(QBR, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(QBR, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-divrem_basecase.c000066400000000000000000000061251461254215100216010ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_divrem_basecase, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, QBR; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(QBR, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 6), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 5)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divrem_basecase(Q, R, Q, B, ctx); break; case 1: status |= gr_poly_set(R, A, ctx); status |= gr_poly_divrem_basecase(Q, R, R, B, ctx); break; case 2: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divrem_basecase(Q, R, A, Q, ctx); break; case 3: status |= gr_poly_set(R, B, ctx); status |= gr_poly_divrem_basecase(Q, R, A, R, ctx); break; default: status |= gr_poly_divrem_basecase(Q, R, A, B, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_mul(QBR, Q, B, ctx); status |= gr_poly_add(QBR, QBR, R, ctx); if (status == GR_SUCCESS && gr_poly_equal(QBR, A, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("R = "); gr_poly_print(R, ctx); flint_printf("\n"); flint_printf("Q*B + R = "); gr_poly_print(QBR, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(QBR, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-divrem_divconquer.c000066400000000000000000000063471461254215100222200ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_divrem_divconquer, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, QBR; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(QBR, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 20), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 20), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 20), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 20), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 5)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divrem_divconquer(Q, R, Q, B, 1 + n_randint(state, 10), ctx); break; case 1: status |= gr_poly_set(R, A, ctx); status |= gr_poly_divrem_divconquer(Q, R, R, B, 1 + n_randint(state, 10), ctx); break; case 2: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divrem_divconquer(Q, R, A, Q, 1 + n_randint(state, 10), ctx); break; case 3: status |= gr_poly_set(R, B, ctx); status |= gr_poly_divrem_divconquer(Q, R, A, R, 1 + n_randint(state, 10), ctx); break; default: status |= gr_poly_divrem_divconquer(Q, R, A, B, 1 + n_randint(state, 10), ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_mul(QBR, Q, B, ctx); status |= gr_poly_add(QBR, QBR, R, ctx); if (status == GR_SUCCESS && gr_poly_equal(QBR, A, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("R = "); gr_poly_print(R, ctx); flint_printf("\n"); flint_printf("Q*B + R = "); gr_poly_print(QBR, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(QBR, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-divrem_newton.c000066400000000000000000000061151461254215100213440ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_divrem_newton, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, QBR; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(QBR, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 20), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 20), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 20), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 20), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 5)) { case 0: status |= gr_poly_set(Q, A, ctx); status |= gr_poly_divrem_newton(Q, R, Q, B, ctx); break; case 1: status |= gr_poly_set(R, A, ctx); status |= gr_poly_divrem_newton(Q, R, R, B, ctx); break; case 2: status |= gr_poly_set(Q, B, ctx); status |= gr_poly_divrem_newton(Q, R, A, Q, ctx); break; case 3: status |= gr_poly_set(R, B, ctx); status |= gr_poly_divrem_newton(Q, R, A, R, ctx); break; default: status |= gr_poly_divrem_newton(Q, R, A, B, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_mul(QBR, Q, B, ctx); status |= gr_poly_add(QBR, QBR, R, ctx); if (status == GR_SUCCESS && gr_poly_equal(QBR, A, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); flint_printf("R = "); gr_poly_print(R, ctx); flint_printf("\n"); flint_printf("Q*B + R = "); gr_poly_print(QBR, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(QBR, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-evaluate.c000066400000000000000000000046371461254215100203010ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_evaluate, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, FG; gr_ptr x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); x = gr_heap_init(ctx); Fx = gr_heap_init(ctx); Gx = gr_heap_init(ctx); FxGx = gr_heap_init(ctx); FGx = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(x, state, ctx); status |= gr_randtest(Fx, state, ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_evaluate(Fx, F, x, ctx); status |= gr_set(Gx, x, ctx); /* test aliasing */ status |= gr_poly_evaluate(Gx, G, Gx, ctx); status |= gr_add(FxGx, Fx, Gx, ctx); status |= gr_poly_evaluate(FGx, FG, x, ctx); if (status == GR_SUCCESS && gr_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_print(x, ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); gr_print(FGx, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_heap_clear(x, ctx); gr_heap_clear(Fx, ctx); gr_heap_clear(Gx, ctx); gr_heap_clear(FxGx, ctx); gr_heap_clear(FGx, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-evaluate_horner.c000066400000000000000000000046731461254215100216560ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_evaluate_horner, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, FG; gr_ptr x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); x = gr_heap_init(ctx); Fx = gr_heap_init(ctx); Gx = gr_heap_init(ctx); FxGx = gr_heap_init(ctx); FGx = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(x, state, ctx); status |= gr_randtest(Fx, state, ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_evaluate_horner(Fx, F, x, ctx); status |= gr_set(Gx, x, ctx); /* test aliasing */ status |= gr_poly_evaluate_horner(Gx, G, Gx, ctx); status |= gr_add(FxGx, Fx, Gx, ctx); status |= gr_poly_evaluate_horner(FGx, FG, x, ctx); if (status == GR_SUCCESS && gr_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_print(x, ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); gr_print(FGx, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_heap_clear(x, ctx); gr_heap_clear(Fx, ctx); gr_heap_clear(Gx, ctx); gr_heap_clear(FxGx, ctx); gr_heap_clear(FGx, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-evaluate_modular.c000066400000000000000000000046771461254215100220300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_evaluate_modular, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, FG; gr_ptr x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); x = gr_heap_init(ctx); Fx = gr_heap_init(ctx); Gx = gr_heap_init(ctx); FxGx = gr_heap_init(ctx); FGx = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(x, state, ctx); status |= gr_randtest(Fx, state, ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_evaluate_modular(Fx, F, x, ctx); status |= gr_set(Gx, x, ctx); /* test aliasing */ status |= gr_poly_evaluate_modular(Gx, G, Gx, ctx); status |= gr_add(FxGx, Fx, Gx, ctx); status |= gr_poly_evaluate_modular(FGx, FG, x, ctx); if (status == GR_SUCCESS && gr_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_print(x, ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); gr_print(FGx, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_heap_clear(x, ctx); gr_heap_clear(Fx, ctx); gr_heap_clear(Gx, ctx); gr_heap_clear(FxGx, ctx); gr_heap_clear(FGx, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-evaluate_other.c000066400000000000000000000050761461254215100215000ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_evaluate_other, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx, x_ctx; gr_poly_t F, G, FG; gr_ptr x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); gr_ctx_init_random(x_ctx, state); gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); x = gr_heap_init(x_ctx); Fx = gr_heap_init(x_ctx); Gx = gr_heap_init(x_ctx); FxGx = gr_heap_init(x_ctx); FGx = gr_heap_init(x_ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(x, state, x_ctx); status |= gr_randtest(Fx, state, x_ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_evaluate_other(Fx, F, x, x_ctx, ctx); status |= gr_set(Gx, x, x_ctx); /* test aliasing */ status |= gr_poly_evaluate_other(Gx, G, Gx, x_ctx, ctx); status |= gr_add(FxGx, Fx, Gx, x_ctx); status |= gr_poly_evaluate_other(FGx, FG, x, x_ctx, ctx); if (status == GR_SUCCESS && gr_equal(FxGx, FGx, x_ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_print(x, x_ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_print(FxGx, x_ctx); flint_printf("\n"); flint_printf("FGx = "); gr_print(FGx, x_ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_heap_clear(x, x_ctx); gr_heap_clear(Fx, x_ctx); gr_heap_clear(Gx, x_ctx); gr_heap_clear(FxGx, x_ctx); gr_heap_clear(FGx, x_ctx); gr_ctx_clear(ctx); gr_ctx_clear(x_ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-evaluate_other_rectangular.c000066400000000000000000000051561461254215100240660ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_evaluate_other_rectangular, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx, x_ctx; gr_poly_t F, G, FG; gr_ptr x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); gr_ctx_init_random(x_ctx, state); gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); x = gr_heap_init(x_ctx); Fx = gr_heap_init(x_ctx); Gx = gr_heap_init(x_ctx); FxGx = gr_heap_init(x_ctx); FGx = gr_heap_init(x_ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(x, state, x_ctx); status |= gr_randtest(Fx, state, x_ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_evaluate_other_rectangular(Fx, F, x, x_ctx, ctx); status |= gr_set(Gx, x, x_ctx); /* test aliasing */ status |= gr_poly_evaluate_other_rectangular(Gx, G, Gx, x_ctx, ctx); status |= gr_add(FxGx, Fx, Gx, x_ctx); status |= gr_poly_evaluate_other_rectangular(FGx, FG, x, x_ctx, ctx); if (status == GR_SUCCESS && gr_equal(FxGx, FGx, x_ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_print(x, x_ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_print(FxGx, x_ctx); flint_printf("\n"); flint_printf("FGx = "); gr_print(FGx, x_ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_heap_clear(x, x_ctx); gr_heap_clear(Fx, x_ctx); gr_heap_clear(Gx, x_ctx); gr_heap_clear(FxGx, x_ctx); gr_heap_clear(FGx, x_ctx); gr_ctx_clear(ctx); gr_ctx_clear(x_ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-evaluate_rectangular.c000066400000000000000000000047171461254215100226670ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_evaluate_rectangular, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, FG; gr_ptr x, Fx, Gx, FxGx, FGx; /* Test F(x) + G(x) = (F + G)(x) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(FG, ctx); x = gr_heap_init(ctx); Fx = gr_heap_init(ctx); Gx = gr_heap_init(ctx); FxGx = gr_heap_init(ctx); FGx = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(x, state, ctx); status |= gr_randtest(Fx, state, ctx); status |= gr_poly_add(FG, F, G, ctx); status |= gr_poly_evaluate_rectangular(Fx, F, x, ctx); status |= gr_set(Gx, x, ctx); /* test aliasing */ status |= gr_poly_evaluate_rectangular(Gx, G, Gx, ctx); status |= gr_add(FxGx, Fx, Gx, ctx); status |= gr_poly_evaluate_rectangular(FGx, FG, x, ctx); if (status == GR_SUCCESS && gr_equal(FxGx, FGx, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("x = "); gr_print(x, ctx); flint_printf("\n"); flint_printf("FxGx = "); gr_print(FxGx, ctx); flint_printf("\n"); flint_printf("FGx = "); gr_print(FGx, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(FG, ctx); gr_heap_clear(x, ctx); gr_heap_clear(Fx, ctx); gr_heap_clear(Gx, ctx); gr_heap_clear(FxGx, ctx); gr_heap_clear(FGx, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-evaluate_vec_fast.c000066400000000000000000000041571461254215100221500ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_evaluate_vec_fast, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status = GR_SUCCESS; gr_ctx_t ctx; gr_poly_t f; gr_vec_t x, y, z; slong n, m; gr_ctx_init_random(ctx, state); if (ctx->methods == _ca_methods) { n = n_randint(state, 8); m = n_randint(state, 8); } else { n = n_randint(state, 30); m = n_randint(state, 30); } gr_poly_init(f, ctx); gr_vec_init(x, n, ctx); gr_vec_init(y, n, ctx); gr_vec_init(z, n, ctx); status |= gr_poly_randtest(f, state, m, ctx); status |= _gr_vec_randtest(x->entries, state, n, ctx); status |= _gr_vec_randtest(y->entries, state, n, ctx); status |= gr_poly_evaluate_vec_fast(y, f, x, ctx); status |= gr_poly_evaluate_vec_iter(z, f, x, ctx); if (status == GR_SUCCESS && _gr_vec_equal(y->entries, z->entries, n, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("x = "); gr_vec_print(x, ctx); flint_printf("\n"); flint_printf("y = "); gr_vec_print(y, ctx); flint_printf("\n"); flint_printf("z = "); gr_vec_print(z, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(f, ctx); gr_vec_clear(x, ctx); gr_vec_clear(y, ctx); gr_vec_clear(z, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-exp_series.c000066400000000000000000000114051461254215100206300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_exp_series(flint_rand_t state) { gr_ctx_t ctx; slong i, len1, len2, len3, n; gr_poly_t a, b, ab, fa, fb, fab, fafb; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(a, ctx); gr_poly_init(b, ctx); gr_poly_init(ab, ctx); gr_poly_init(fa, ctx); gr_poly_init(fb, ctx); gr_poly_init(fab, ctx); gr_poly_init(fafb, ctx); if (ctx->methods == _ca_methods) { len1 = n_randint(state, 5); len2 = n_randint(state, 5); len3 = n_randint(state, 5); } else { len1 = n_randint(state, 20); len2 = n_randint(state, 20); len3 = n_randint(state, 20); } GR_MUST_SUCCEED(gr_poly_randtest(a, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(b, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(fa, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(fb, state, 1 + n_randint(state, 20), ctx)); if (n_randint(state, 4) != 0) status |= gr_poly_set_coeff_si(a, 0, 0, ctx); if (n_randint(state, 4) != 0) status |= gr_poly_set_coeff_si(b, 0, 0, ctx); status |= gr_poly_add(ab, a, b, ctx); for (i = 0; i < 3 && status == GR_SUCCESS; i++) { gr_ptr x, y; if (i == 0) { x = a; y = fa; n = len1; } else if (i == 1) { x = b; y = fb; n = len2; } else { x = ab; y = fab; n = len3; } switch (n_randint(state, 8)) { case 0: status |= gr_poly_exp_series(y, x, n, ctx); break; case 1: status |= gr_poly_set(y, x, ctx); status |= gr_poly_exp_series(y, y, n, ctx); break; case 2: status |= gr_poly_exp_series_basecase(y, x, n, ctx); break; case 3: status |= gr_poly_set(y, x, ctx); status |= gr_poly_exp_series_basecase(y, y, n, ctx); break; case 4: status |= gr_poly_exp_series_basecase_mul(y, x, n, ctx); break; case 5: status |= gr_poly_set(y, x, ctx); status |= gr_poly_exp_series_basecase_mul(y, y, n, ctx); break; case 6: status |= gr_poly_exp_series_newton(y, x, n, n_randint(state, 20), ctx); break; case 7: status |= gr_poly_set(y, x, ctx); status |= gr_poly_exp_series_newton(y, y, n, n_randint(state, 20), ctx); break; default: flint_abort(); } } if (status == GR_SUCCESS) { status |= gr_poly_mullow(fafb, fa, fb, FLINT_MIN(FLINT_MIN(len1, len2), len3), ctx); status |= gr_poly_truncate(fab, fab, FLINT_MIN(FLINT_MIN(len1, len2), len3), ctx); if (status == GR_SUCCESS && gr_poly_equal(fafb, fab, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("len1 = %wd, len2 = %wd, len3 = %wd\n", len1, len2, len3); flint_printf("a = "); gr_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); gr_poly_print(b, ctx); flint_printf("\n\n"); flint_printf("ab = "); gr_poly_print(ab, ctx); flint_printf("\n\n"); flint_printf("fa = "); gr_poly_print(fa, ctx); flint_printf("\n\n"); flint_printf("fb = "); gr_poly_print(fb, ctx); flint_printf("\n\n"); flint_printf("fab = "); gr_poly_print(fab, ctx); flint_printf("\n\n"); flint_printf("fafb = "); gr_poly_print(fafb, ctx); flint_printf("\n\n"); flint_abort(); } } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_poly_clear(ab, ctx); gr_poly_clear(fa, ctx); gr_poly_clear(fb, ctx); gr_poly_clear(fab, ctx); gr_poly_clear(fafb, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_exp_series, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_exp_series(state); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-factor_squarefree.c000066400000000000000000000131471461254215100221670ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_factor_squarefree, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_poly_t A, B, C, P, Q, G1, G2, G3; gr_ptr c; gr_vec_t F; gr_ctx_t poly_ctx, fmpz_ctx; ulong ea, eb, ec, maxexp; fmpz * expc; gr_vec_t exp; slong i, j; int status = GR_SUCCESS; int attempts = 0; gr_ctx_init_random(ctx, state); while (gr_ctx_is_field(ctx) != T_TRUE || ctx->methods == _ca_methods) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_ctx_init_gr_poly(poly_ctx, ctx); gr_ctx_init_fmpz(fmpz_ctx); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(G1, ctx); gr_poly_init(G2, ctx); gr_poly_init(G3, ctx); gr_poly_init(P, ctx); gr_poly_init(Q, ctx); gr_vec_init(F, 0, poly_ctx); gr_vec_init(exp, 0, fmpz_ctx); c = gr_heap_init(ctx); attempts = 0; do { attempts++; if (ctx->methods == _ca_methods) { ea = 1 + n_randint(state, 2); eb = 1 + n_randint(state, 2); ec = 1 + n_randint(state, 2); status |= gr_poly_randtest(A, state, 2, ctx); status |= gr_poly_randtest(B, state, 2, ctx); status |= gr_poly_randtest(C, state, 2, ctx); } else { ea = 1 + n_randint(state, 2); eb = 1 + n_randint(state, 2); ec = 1 + n_randint(state, 4); status |= gr_poly_randtest(A, state, 3, ctx); status |= gr_poly_randtest(B, state, 3, ctx); status |= gr_poly_randtest(C, state, 3, ctx); } if (ctx->which_ring != GR_CTX_FMPQ && attempts > 4) { status = GR_UNABLE; break; } } while (A->length < 2 || B->length < 2 || C->length < 2 || gr_poly_gcd(G1, A, B, ctx) != GR_SUCCESS || (gr_poly_is_one(G1, ctx) != T_TRUE) || gr_poly_gcd(G2, A, C, ctx) != GR_SUCCESS || (gr_poly_is_one(G2, ctx) != T_TRUE) || gr_poly_gcd(G3, B, C, ctx) != GR_SUCCESS || (gr_poly_is_one(G3, ctx) != T_TRUE)); status |= gr_poly_one(P, ctx); for (i = 0; i < ea; i++) status |= gr_poly_mul(P, P, A, ctx); for (i = 0; i < eb; i++) status |= gr_poly_mul(P, P, B, ctx); for (i = 0; i < ec; i++) status |= gr_poly_mul(P, P, C, ctx); status |= gr_poly_factor_squarefree(c, F, exp, P, ctx); if (ctx->which_ring == GR_CTX_FMPQ && status != GR_SUCCESS) { flint_printf("FAIL (unexpected failure)\n\n"); flint_printf("P = "); gr_poly_print(P, ctx); flint_printf("\n"); flint_abort(); } if (status == GR_SUCCESS) { expc = exp->entries; /* printf("LENGTHS %ld %ld\n", F->length, exp->length); gr_vec_print(F, poly_ctx); printf("\n\n"); gr_vec_print(exp, fmpz_ctx); printf("\n\n"); */ status |= gr_poly_one(Q, ctx); for (i = 0; i < F->length; i++) for (j = 0; j < expc[i]; j++) status |= gr_poly_mul(Q, Q, gr_vec_entry_ptr(F, i, poly_ctx), ctx); status |= gr_poly_mul_scalar(Q, Q, c, ctx); maxexp = 0; for (i = 0; i < F->length; i++) maxexp = FLINT_MAX(maxexp, expc[i]); if (status == GR_SUCCESS && (gr_poly_equal(P, Q, ctx) == T_FALSE || maxexp < FLINT_MAX(FLINT_MAX(ea, eb), ec))) { flint_printf("FAIL (product)\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("ea = %wu\n\n", ea); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("eb = %wu\n\n", eb); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("ec = %wu\n\n", ec); flint_printf("P = "); gr_poly_print(P, ctx); flint_printf("\n"); flint_printf("Q = "); gr_poly_print(Q, ctx); flint_printf("\n"); for (i = 0; i < F->length; i++) { flint_printf("Multiplicity %wu: ", exp[i]); gr_poly_print(gr_vec_entry_ptr(F, i, poly_ctx), ctx); } flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(G1, ctx); gr_poly_clear(G2, ctx); gr_poly_clear(G3, ctx); gr_poly_clear(P, ctx); gr_poly_clear(Q, ctx); gr_vec_clear(F, poly_ctx); gr_vec_clear(exp, fmpz_ctx); gr_heap_clear(c, ctx); gr_ctx_clear(poly_ctx); gr_ctx_clear(fmpz_ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-gcd.c000066400000000000000000000125221461254215100172200ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_gcd, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_poly_t A, B, C, AC, BC, MC, G; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(AC, ctx); gr_poly_init(BC, ctx); gr_poly_init(MC, ctx); gr_poly_init(G, ctx); n = 6; if (ctx->which_ring == GR_CTX_CC_CA || ctx->which_ring == GR_CTX_RR_CA) n = 3; status = gr_poly_randtest(A, state, n, ctx); status |= gr_poly_randtest(B, state, n, ctx); status |= gr_poly_gcd(G, A, B, ctx); if (status == GR_SUCCESS) { if (gr_poly_is_zero(G, ctx) == T_FALSE) { status |= gr_poly_divrem(AC, BC, A, G, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(BC, ctx) == T_FALSE) { flint_printf("FAIL: gcd does not divide A\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } status |= gr_poly_divrem(AC, BC, B, G, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(BC, ctx) == T_FALSE) { flint_printf("FAIL: gcd does not divide B\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } } if (status == GR_SUCCESS && gr_poly_is_one(G, ctx) == T_TRUE) { status |= gr_poly_randtest(C, state, n, ctx); status |= gr_poly_mul(AC, A, C, ctx); status |= gr_poly_mul(BC, B, C, ctx); switch (n_randint(state, 3)) { case 0: status |= gr_poly_set(G, AC, ctx); status |= gr_poly_gcd(G, G, BC, ctx); break; case 1: status |= gr_poly_set(G, BC, ctx); status |= gr_poly_gcd(G, AC, G, ctx); break; default: status |= gr_poly_gcd(G, AC, BC, ctx); break; } if (status == GR_SUCCESS) { if (gr_poly_is_zero(C, ctx) == T_FALSE) { status |= gr_poly_make_monic(MC, C, ctx); if (status == GR_SUCCESS && gr_poly_equal(MC, G, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } } } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } status = gr_poly_randtest(A, state, n, ctx); status |= gr_poly_gcd(G, A, A, ctx); if (status == GR_SUCCESS) { status |= gr_poly_make_monic(B, A, ctx); if (status == GR_SUCCESS && gr_poly_equal(G, B, ctx) == T_FALSE) { flint_printf("FAIL (self)\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(AC, ctx); gr_poly_clear(BC, ctx); gr_poly_clear(MC, ctx); gr_poly_clear(G, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-gcd_euclidean.c000066400000000000000000000126161461254215100212350ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_gcd_euclidean, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_poly_t A, B, C, AC, BC, MC, G; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(AC, ctx); gr_poly_init(BC, ctx); gr_poly_init(MC, ctx); gr_poly_init(G, ctx); n = 6; if (ctx->which_ring == GR_CTX_CC_CA || ctx->which_ring == GR_CTX_RR_CA) n = 3; status = gr_poly_randtest(A, state, n, ctx); status |= gr_poly_randtest(B, state, n, ctx); status |= gr_poly_gcd_euclidean(G, A, B, ctx); if (status == GR_SUCCESS) { if (gr_poly_is_zero(G, ctx) == T_FALSE) { status |= gr_poly_divrem(AC, BC, A, G, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(BC, ctx) == T_FALSE) { flint_printf("FAIL: gcd does not divide A\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } status |= gr_poly_divrem(AC, BC, B, G, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(BC, ctx) == T_FALSE) { flint_printf("FAIL: gcd does not divide B\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } } if (status == GR_SUCCESS && gr_poly_is_one(G, ctx) == T_TRUE) { status |= gr_poly_randtest(C, state, n, ctx); status |= gr_poly_mul(AC, A, C, ctx); status |= gr_poly_mul(BC, B, C, ctx); switch (n_randint(state, 3)) { case 0: status |= gr_poly_set(G, AC, ctx); status |= gr_poly_gcd_euclidean(G, G, BC, ctx); break; case 1: status |= gr_poly_set(G, BC, ctx); status |= gr_poly_gcd_euclidean(G, AC, G, ctx); break; default: status |= gr_poly_gcd_euclidean(G, AC, BC, ctx); break; } if (status == GR_SUCCESS) { if (gr_poly_is_zero(C, ctx) == T_FALSE) { status |= gr_poly_make_monic(MC, C, ctx); if (status == GR_SUCCESS && gr_poly_equal(MC, G, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } } } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } status = gr_poly_randtest(A, state, n, ctx); status |= gr_poly_gcd_euclidean(G, A, A, ctx); if (status == GR_SUCCESS) { status |= gr_poly_make_monic(B, A, ctx); if (status == GR_SUCCESS && gr_poly_equal(G, B, ctx) == T_FALSE) { flint_printf("FAIL (self)\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(AC, ctx); gr_poly_clear(BC, ctx); gr_poly_clear(MC, ctx); gr_poly_clear(G, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-gcd_hgcd.c000066400000000000000000000132061461254215100202050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_gcd_hgcd, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_poly_t A, B, C, AC, BC, MC, G; int status = GR_SUCCESS; slong n, cutoff1, cutoff2; while (1) { gr_ctx_init_random(ctx, state); if (gr_ctx_is_finite(ctx) == T_TRUE) break; else gr_ctx_clear(ctx); } gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(AC, ctx); gr_poly_init(BC, ctx); gr_poly_init(MC, ctx); gr_poly_init(G, ctx); n = n_randint(state, 100); cutoff1 = n_randint(state, 100); cutoff2 = n_randint(state, 100); status = gr_poly_randtest(A, state, n, ctx); status |= gr_poly_randtest(B, state, n, ctx); status |= gr_poly_gcd_hgcd(G, A, B, cutoff1, cutoff2, ctx); if (status == GR_SUCCESS) { if (gr_poly_is_zero(G, ctx) == T_FALSE) { status |= gr_poly_divrem(AC, BC, A, G, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(BC, ctx) == T_FALSE) { flint_printf("FAIL: gcd does not divide A\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } status |= gr_poly_divrem(AC, BC, B, G, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(BC, ctx) == T_FALSE) { flint_printf("FAIL: gcd does not divide B\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } } if (status == GR_SUCCESS && gr_poly_is_one(G, ctx) == T_TRUE) { status |= gr_poly_randtest(C, state, n, ctx); status |= gr_poly_mul(AC, A, C, ctx); status |= gr_poly_mul(BC, B, C, ctx); switch (n_randint(state, 3)) { case 0: status |= gr_poly_set(G, AC, ctx); status |= gr_poly_gcd_hgcd(G, G, BC, cutoff1, cutoff2, ctx); break; case 1: status |= gr_poly_set(G, BC, ctx); status |= gr_poly_gcd_hgcd(G, AC, G, cutoff1, cutoff2, ctx); break; default: status |= gr_poly_gcd_hgcd(G, AC, BC, cutoff1, cutoff2, ctx); break; } if (status == GR_SUCCESS) { if (gr_poly_is_zero(C, ctx) == T_FALSE) { status |= gr_poly_make_monic(MC, C, ctx); if (status == GR_SUCCESS && gr_poly_equal(MC, G, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } } } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } status = gr_poly_randtest(A, state, n, ctx); status |= gr_poly_gcd_hgcd(G, A, A, cutoff1, cutoff2, ctx); if (status == GR_SUCCESS) { status |= gr_poly_make_monic(B, A, ctx); if (status == GR_SUCCESS && gr_poly_equal(G, B, ctx) == T_FALSE) { flint_printf("FAIL (self)\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(AC, ctx); gr_poly_clear(BC, ctx); gr_poly_clear(MC, ctx); gr_poly_clear(G, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-hgcd.c000066400000000000000000000154071461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" #define __swap(u, l, v, m) \ do { \ { gr_ptr _; _ = (u), (u) = (v), (v) = _;} \ { slong _; _ = (l), (l) = (m), (m) = _;} \ } while (0) #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ status |= _gr_poly_mul((C), (A), (lenA), (B), (lenB), ctx); \ else \ status |= _gr_poly_mul((C), (B), (lenB), (A), (lenA), ctx); \ (lenC) = (lenA) + (lenB) - 1; \ } \ else \ { \ (lenC) = 0; \ } \ } while (0) TEST_FUNCTION_START(gr_poly_hgcd, state) { int i, result; /* Find coprime polys, multiply by another poly and check the GCD is that poly */ for (i = 0; i < 1000; i++) { gr_poly_t a, b, c, d, c1, d1, s, t; gr_ctx_t ctx; gr_ptr M[4]; slong lenM[4]; slong sgnM; slong cutoff; int status = GR_SUCCESS; slong sz; while (1) { gr_ctx_init_random(ctx, state); if (gr_ctx_is_finite(ctx) == T_TRUE) break; else gr_ctx_clear(ctx); } sz = ctx->sizeof_elem; gr_poly_init(a, ctx); gr_poly_init(b, ctx); gr_poly_init(c, ctx); gr_poly_init(d, ctx); gr_poly_init(c1, ctx); gr_poly_init(d1, ctx); gr_poly_init(s, ctx); gr_poly_init(t, ctx); do { status |= gr_poly_randtest(a, state, n_randint(state, 100) + 1, ctx); status |= gr_poly_randtest(b, state, n_randint(state, 100) + 1, ctx); /* escape the zero ring */ GR_IGNORE(gr_poly_one(c, ctx)); if (gr_poly_is_zero(c, ctx) != T_FALSE) break; } while (a->length == 0 || b->length == 0 || a->length == b->length); cutoff = n_randint(state, 100); if (a->length < b->length) gr_poly_swap(a, b, ctx); M[0] = flint_malloc(a->length * sz); M[1] = flint_malloc(a->length * sz); M[2] = flint_malloc(a->length * sz); M[3] = flint_malloc(a->length * sz); _gr_vec_init(M[0], a->length, ctx); _gr_vec_init(M[1], a->length, ctx); _gr_vec_init(M[2], a->length, ctx); _gr_vec_init(M[3], a->length, ctx); gr_poly_fit_length(c, a->length, ctx); gr_poly_fit_length(d, b->length, ctx); status |= _gr_poly_hgcd(NULL, &sgnM, M, lenM, c->coeffs, &(c->length), d->coeffs, &(d->length), a->coeffs, a->length, b->coeffs, b->length, cutoff, ctx); gr_poly_fit_length(s, 2 * a->length, ctx); gr_poly_fit_length(t, 2 * a->length, ctx); /* [c1,d1] := sgnM * M^{-1} [a,b] */ { __swap(M[0], lenM[0], M[3], lenM[3]); status |= _gr_vec_neg(M[1], M[1], lenM[1], ctx); status |= _gr_vec_neg(M[2], M[2], lenM[2], ctx); __mul(s->coeffs, s->length, M[0], lenM[0], a->coeffs, a->length); __mul(t->coeffs, t->length, M[1], lenM[1], b->coeffs, b->length); status |= gr_poly_add(c1, s, t, ctx); __mul(s->coeffs, s->length, M[2], lenM[2], a->coeffs, a->length); __mul(t->coeffs, t->length, M[3], lenM[3], b->coeffs, b->length); status |= gr_poly_add(d1, s, t, ctx); } if (sgnM < 0) { status |= gr_poly_neg(c1, c1, ctx); status |= gr_poly_neg(d1, d1, ctx); } if (status != GR_SUCCESS && gr_ctx_is_field(ctx) == T_TRUE) { flint_printf("FAIL: unexpected status %d\n", status); gr_ctx_println(ctx); flint_printf("a = "), gr_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), gr_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), gr_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("d = "), gr_poly_print(d, ctx), flint_printf("\n\n"); flint_printf("c1 = "), gr_poly_print(c1, ctx), flint_printf("\n\n"); flint_printf("d1 = "), gr_poly_print(d1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } if (status == GR_SUCCESS) { result = (gr_poly_equal(c, c1, ctx) == T_TRUE && gr_poly_equal(d, d1, ctx) == T_TRUE); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), gr_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), gr_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), gr_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("d = "), gr_poly_print(d, ctx), flint_printf("\n\n"); flint_printf("c1 = "), gr_poly_print(c1, ctx), flint_printf("\n\n"); flint_printf("d1 = "), gr_poly_print(d1, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } _gr_vec_clear(M[0], a->length, ctx); _gr_vec_clear(M[1], a->length, ctx); _gr_vec_clear(M[2], a->length, ctx); _gr_vec_clear(M[3], a->length, ctx); flint_free(M[0]); flint_free(M[1]); flint_free(M[2]); flint_free(M[3]); gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_poly_clear(c, ctx); gr_poly_clear(d, ctx); gr_poly_clear(c1, ctx); gr_poly_clear(d1, ctx); gr_poly_clear(s, ctx); gr_poly_clear(t, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-integral.c000066400000000000000000000041541461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_integral, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, G, Gprime; /* check derivative(integral(f)) == f */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(G, ctx); gr_poly_init(Gprime, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(G, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Gprime, state, 1 + n_randint(state, 6), ctx); if (n_randint(state, 2)) { status |= gr_poly_integral(G, F, ctx); } else { status |= gr_poly_set(G, F, ctx); status |= gr_poly_integral(G, G, ctx); } if (n_randint(state, 2)) { status |= gr_poly_derivative(Gprime, G, ctx); } else { status |= gr_poly_set(Gprime, G, ctx); status |= gr_poly_derivative(Gprime, Gprime, ctx); } if (status == GR_SUCCESS && gr_poly_equal(F, Gprime, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("G = "); gr_poly_print(G, ctx); flint_printf("\n"); flint_printf("Gprime = "); gr_poly_print(Gprime, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(G, ctx); gr_poly_clear(Gprime, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-inv_series.c000066400000000000000000000057151461254215100206370ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_inv_series(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; gr_poly_t A, B, AB, one; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(AB, ctx); gr_poly_init(one, ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 20); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 20, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(B, state, 20, ctx)); switch (which) { case 0: status |= gr_poly_inv_series(B, A, n, ctx); break; case 1: status |= gr_poly_set(B, A, ctx); status |= gr_poly_inv_series(B, B, n, ctx); break; case 2: status |= gr_poly_inv_series_basecase(B, A, n, ctx); break; case 3: status |= gr_poly_set(B, A, ctx); status |= gr_poly_inv_series_basecase(B, B, n, ctx); break; case 4: status |= gr_poly_inv_series_newton(B, A, n, n_randint(state, 20), ctx); break; case 5: status |= gr_poly_set(B, A, ctx); status |= gr_poly_inv_series_newton(B, B, n, n_randint(state, 20), ctx); break; default: flint_abort(); } if (status == GR_SUCCESS) { status |= gr_poly_mullow(AB, A, B, n, ctx); status |= gr_poly_one(one, ctx); status |= gr_poly_truncate(one, one, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(AB, one, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("which = %d\n\n", which); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("AB = "); gr_poly_print(AB, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(AB, ctx); gr_poly_clear(one, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_inv_series, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_inv_series(state, 0); test_inv_series(state, 1); test_inv_series(state, 2); test_inv_series(state, 3); test_inv_series(state, 4); test_inv_series(state, 5); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-log_series.c000066400000000000000000000071741461254215100206250ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_log_series(flint_rand_t state) { gr_ctx_t ctx; slong n; gr_poly_t a, b, ab, fa, fb, fafb, fab; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(a, ctx); gr_poly_init(b, ctx); gr_poly_init(ab, ctx); gr_poly_init(fa, ctx); gr_poly_init(fb, ctx); gr_poly_init(fafb, ctx); gr_poly_init(fab, ctx); n = n_randint(state, 10); GR_MUST_SUCCEED(gr_poly_randtest(a, state, 10, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(b, state, 10, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(fa, state, 10, ctx)); if (n_randint(state, 2)) status |= gr_poly_set_coeff_ui(a, 0, 1, ctx); if (n_randint(state, 2)) status |= gr_poly_set_coeff_ui(b, 0, 1, ctx); status |= gr_poly_log_series(fa, a, n, ctx); status |= gr_poly_log_series(fb, b, n, ctx); if (status == GR_SUCCESS) { status |= gr_poly_add(fafb, fa, fb, ctx); status |= gr_poly_mullow(ab, a, b, n, ctx); status |= gr_poly_set(fab, ab, ctx); /* also test aliasing */ status |= gr_poly_log_series(fab, fab, n, ctx); /* todo: also test constant terms */ status |= gr_poly_set_coeff_si(fab, 0, 0, ctx); status |= gr_poly_set_coeff_si(fafb, 0, 0, ctx); if (status == GR_SUCCESS && gr_poly_equal(fab, fafb, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("n = %wd\n", n); flint_printf("a = "); gr_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); gr_poly_print(b, ctx); flint_printf("\n\n"); flint_printf("fa = "); gr_poly_print(fa, ctx); flint_printf("\n\n"); flint_printf("fb = "); gr_poly_print(fb, ctx); flint_printf("\n\n"); flint_printf("ab = "); gr_poly_print(ab, ctx); flint_printf("\n\n"); flint_printf("fafb = "); gr_poly_print(fafb, ctx); flint_printf("\n\n"); flint_printf("fab = "); gr_poly_print(fab, ctx); flint_printf("\n\n"); flint_abort(); } status |= gr_poly_log_series(fb, a, n + n_randint(state, 3), ctx); status |= gr_poly_truncate(fb, fb, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(fa, fb, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("n = %wd\n", n); flint_printf("a = "); gr_poly_print(a, ctx); flint_printf("\n\n"); flint_printf("b = "); gr_poly_print(b, ctx); flint_printf("\n\n"); flint_printf("fa = "); gr_poly_print(fa, ctx); flint_printf("\n\n"); flint_printf("fb = "); gr_poly_print(fb, ctx); flint_printf("\n\n"); flint_abort(); } } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_poly_clear(ab, ctx); gr_poly_clear(fa, ctx); gr_poly_clear(fb, ctx); gr_poly_clear(fafb, ctx); gr_poly_clear(fab, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_log_series, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_log_series(state); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-make_monic.c000066400000000000000000000045771461254215100206000ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_make_monic, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t f, fc, g, h; gr_ptr c; gr_ctx_init_random(ctx, state); gr_poly_init(f, ctx); gr_poly_init(fc, ctx); gr_poly_init(g, ctx); gr_poly_init(h, ctx); c = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(f, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(fc, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(g, state, 1 + n_randint(state, 6), ctx); status |= gr_randtest(c, state, ctx); status |= gr_poly_mul_scalar(fc, f, c, ctx); if (n_randint(state, 2)) { status |= gr_poly_make_monic(g, f, ctx); } else { status |= gr_poly_set(g, f, ctx); status |= gr_poly_make_monic(g, g, ctx); } if (status == GR_SUCCESS && gr_poly_is_monic(g, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } status |= gr_poly_make_monic(h, fc, ctx); if (status == GR_SUCCESS && gr_poly_equal(g, h, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_printf("h = "); gr_poly_print(h, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(fc, ctx); gr_poly_clear(g, ctx); gr_poly_clear(h, ctx); gr_heap_clear(c, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-nth_derivative.c000066400000000000000000000034441461254215100215010ustar00rootroot00000000000000/* Copyright (C) 2023 Joel Dahne This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "flint.h" #include "gr_poly.h" #include "ulong_extras.h" TEST_FUNCTION_START(gr_poly_nth_derivative, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; ulong nth; slong j; gr_ctx_t ctx; gr_poly_t a, b; gr_ctx_init_random(ctx, state); gr_poly_init(a, ctx); gr_poly_init(b, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(a, state, n_randint(state, 30), ctx); status |= gr_poly_randtest(b, state, n_randint(state, 30), ctx); nth = n_randint(state, 30); if (n_randint(state, 2)) { status |= gr_poly_nth_derivative(b, a, nth, ctx); } else { status |= gr_poly_set(b, a, ctx); status |= gr_poly_nth_derivative(b, b, nth, ctx); } /* Compute derivative iteratively */ for (j = 0; j < nth; j ++) status |= gr_poly_derivative(a, a, ctx); if (status == GR_SUCCESS && gr_poly_equal(a, b, ctx) == T_FALSE) { flint_printf("FAIL:\n"); flint_printf("a = "); gr_poly_print(a, ctx); flint_printf("\n"); flint_printf("b = "); gr_poly_print(b, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-pow_series_fmpq.c000066400000000000000000000114421461254215100216650ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; /* Defined in t-pow_series_fmpq.c, t-pow_series_ui.c and t-pow_ui.c */ #define test test_pow_series_fmpq int test(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); if (n_randint(state, 2)) { /* check (A^(p/q))^q = A^p */ fmpq_t p, q, pq; gr_poly_t A, Apq, Apqq, Ap; gr_poly_init(A, ctx); gr_poly_init(Apq, ctx); gr_poly_init(Apqq, ctx); gr_poly_init(Ap, ctx); fmpq_init(pq); fmpq_init(p); fmpq_init(q); fmpq_randtest(pq, state, 4); fmpq_set_fmpz(p, fmpq_numref(pq)); fmpq_set_fmpz(q, fmpq_denref(pq)); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 10); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 10, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(Apq, state, 10, ctx)); status |= gr_poly_pow_series_fmpq_recurrence(Apq, A, pq, n, ctx); if (status == GR_SUCCESS) status |= gr_poly_pow_series_fmpq_recurrence(Apqq, Apq, q, n, ctx); if (status == GR_SUCCESS) status |= gr_poly_pow_series_fmpq_recurrence(Ap, A, p, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(Apqq, Ap, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("pq = "); fmpq_print(pq); printf("\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("Apq = "); gr_poly_print(Apq, ctx); flint_printf("\n"); flint_printf("Apqq = "); gr_poly_print(Apqq, ctx); flint_printf("\n"); flint_printf("Ap = "); gr_poly_print(Ap, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(A, ctx); gr_poly_clear(Apq, ctx); gr_poly_clear(Apqq, ctx); gr_poly_clear(Ap, ctx); fmpq_clear(pq); fmpq_clear(p); fmpq_clear(q); } else { /* check A^p A^q = A^(p+q) */ fmpq_t p, q, pq; gr_poly_t A, Ap, Aq, Apq, ApAq; gr_poly_init(A, ctx); gr_poly_init(Ap, ctx); gr_poly_init(Aq, ctx); gr_poly_init(Apq, ctx); gr_poly_init(ApAq, ctx); fmpq_init(pq); fmpq_init(p); fmpq_init(q); fmpq_randtest(p, state, 4); fmpq_randtest(q, state, 4); fmpq_add(pq, p, q); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 10); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 10, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(Aq, state, 10, ctx)); status |= gr_poly_set(Ap, A, ctx); /* aliasing */ status |= gr_poly_pow_series_fmpq_recurrence(Ap, Ap, p, n + n_randint(state, 3), ctx); if (status == GR_SUCCESS) status |= gr_poly_pow_series_fmpq_recurrence(Aq, A, q, n + n_randint(state, 3), ctx); if (status == GR_SUCCESS) status |= gr_poly_pow_series_fmpq_recurrence(Apq, A, pq, n, ctx); if (status == GR_SUCCESS) status |= gr_poly_mullow(ApAq, Ap, Aq, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(Apq, ApAq, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("p = "); fmpq_print(p); printf("\n"); flint_printf("q = "); fmpq_print(q); printf("\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("Ap = "); gr_poly_print(Ap, ctx); flint_printf("\n"); flint_printf("Aq = "); gr_poly_print(Aq, ctx); flint_printf("\n"); flint_printf("Apq = "); gr_poly_print(Apq, ctx); flint_printf("\n"); flint_printf("ApAq = "); gr_poly_print(ApAq, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(A, ctx); gr_poly_clear(Ap, ctx); gr_poly_clear(Aq, ctx); gr_poly_clear(Apq, ctx); gr_poly_clear(ApAq, ctx); fmpq_clear(pq); fmpq_clear(p); fmpq_clear(q); } gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_pow_series_fmpq, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test(state, 0); } TEST_FUNCTION_END(state); } #undef test flint-3.1.3/src/gr_poly/test/t-pow_series_ui.c000066400000000000000000000055141461254215100213420ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" /* Defined in t-pow_series_fmpq.c, t-pow_series_ui.c and t-pow_ui.c */ #define test test_pow_series_ui int test(flint_rand_t state, int which) { gr_ctx_t ctx; /* Test A^n * A^m = A^(n+m) */ gr_poly_t A, An, Am, AnAm, Anm; ulong n, m; slong len; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(An, ctx); gr_poly_init(Am, ctx); gr_poly_init(AnAm, ctx); gr_poly_init(Anm, ctx); n = n_randint(state, 5); m = n_randint(state, 5); len = n_randint(state, 10); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 8, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(An, state, 8, ctx)); if (which == 0) { status |= gr_poly_pow_series_ui(An, A, n, len + n_randint(state, 5), ctx); status |= gr_poly_set(Am, A, ctx); status |= gr_poly_pow_series_ui(Am, Am, m, len + n_randint(state, 5), ctx); status |= gr_poly_mullow(AnAm, An, Am, len, ctx); status |= gr_poly_pow_series_ui(Anm, A, n + m, len, ctx); } else { status |= gr_poly_pow_series_ui_binexp(An, A, n, len + n_randint(state, 5), ctx); status |= gr_poly_set(Am, A, ctx); status |= gr_poly_pow_series_ui_binexp(Am, Am, m, len + n_randint(state, 5), ctx); status |= gr_poly_mullow(AnAm, An, Am, len, ctx); status |= gr_poly_pow_series_ui_binexp(Anm, A, n + m, len, ctx); } if (status == GR_SUCCESS && gr_poly_equal(AnAm, Anm, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("n = %wu, m = %wu, len = %wd\n", n, m, len); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("An = "); gr_poly_print(An, ctx); flint_printf("\n"); flint_printf("Am = "); gr_poly_print(Am, ctx); flint_printf("\n"); flint_printf("AnAm = "); gr_poly_print(AnAm, ctx); flint_printf("\n"); flint_printf("Anm = "); gr_poly_print(Anm, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(A, ctx); gr_poly_clear(An, ctx); gr_poly_clear(Am, ctx); gr_poly_clear(AnAm, ctx); gr_poly_clear(Anm, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_pow_series_ui, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test(state, n_randint(state, 2)); } TEST_FUNCTION_END(state); } #undef test flint-3.1.3/src/gr_poly/test/t-pow_ui.c000066400000000000000000000050671461254215100177730ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" /* Defined in t-pow_series_fmpq.c, t-pow_series_ui.c and t-pow_ui.c */ #define test test_pow_ui int test(flint_rand_t state, int which) { gr_ctx_t ctx; /* Test A^n * A^m = A^(n+m) */ gr_poly_t A, An, Am, AnAm, Anm; ulong n, m; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(An, ctx); gr_poly_init(Am, ctx); gr_poly_init(AnAm, ctx); gr_poly_init(Anm, ctx); n = n_randint(state, 5); m = n_randint(state, 5); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 8, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(An, state, 8, ctx)); if (which == 0) { status |= gr_poly_pow_ui(An, A, n, ctx); status |= gr_poly_set(Am, A, ctx); status |= gr_poly_pow_ui(Am, Am, m, ctx); status |= gr_poly_mul(AnAm, An, Am, ctx); status |= gr_poly_pow_ui(Anm, A, n + m, ctx); } else { status |= gr_poly_pow_ui_binexp(An, A, n, ctx); status |= gr_poly_set(Am, A, ctx); status |= gr_poly_pow_ui_binexp(Am, Am, m, ctx); status |= gr_poly_mul(AnAm, An, Am, ctx); status |= gr_poly_pow_ui_binexp(Anm, A, n + m, ctx); } if (gr_poly_equal(AnAm, Anm, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); gr_ctx_println(ctx); flint_printf("n = %wu, m = %wu\n", n, m); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("An = "); gr_poly_print(An, ctx); flint_printf("\n"); flint_printf("Am = "); gr_poly_print(Am, ctx); flint_printf("\n"); flint_printf("AnAm = "); gr_poly_print(AnAm, ctx); flint_printf("\n"); flint_printf("Anm = "); gr_poly_print(Anm, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(A, ctx); gr_poly_clear(An, ctx); gr_poly_clear(Am, ctx); gr_poly_clear(AnAm, ctx); gr_poly_clear(Anm, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_pow_ui, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test(state, n_randint(state, 2)); } TEST_FUNCTION_END(state); } #undef test flint-3.1.3/src/gr_poly/test/t-rem.c000066400000000000000000000056451461254215100172560ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_rem, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t A, B, Q, R, R2; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(Q, ctx); gr_poly_init(R, ctx); gr_poly_init(R2, ctx); status = GR_SUCCESS; status |= gr_poly_randtest(A, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(B, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(Q, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_randtest(R, state, 1 + n_randint(state, 6), ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(A, A, B, ctx); status |= gr_poly_add(A, A, R, ctx); } /* test aliasing */ switch (n_randint(state, 4)) { case 0: status |= gr_poly_set(R, A, ctx); status |= gr_poly_rem(R, R, B, ctx); break; case 1: status |= gr_poly_set(R, B, ctx); status |= gr_poly_rem(R, A, B, ctx); break; case 3: status |= gr_poly_set(A, B, ctx); status |= gr_poly_rem(R, A, A, ctx); break; case 4: status |= gr_poly_set(A, B, ctx); status |= gr_poly_set(R, A, ctx); status |= gr_poly_rem(R, R, R, ctx); break; default: status |= gr_poly_rem(R, A, B, ctx); break; } if (status == GR_SUCCESS) { status |= gr_poly_divrem(Q, R2, A, B, ctx); if (status == GR_SUCCESS && gr_poly_equal(R, R2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("R = "); gr_poly_print(R, ctx); flint_printf("\n"); flint_printf("R2 = "); gr_poly_print(R2, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(Q, ctx); gr_poly_clear(R, ctx); gr_poly_clear(R2, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-resultant.c000066400000000000000000000133271461254215100205100ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_resultant, state) { slong iter; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ /* Also compare with euclidean */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { gr_ctx_t ctx; gr_poly_t f, g; gr_ptr x, y; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); if (ctx->methods == _ca_methods) n = n_randint(state, 3); else n = n_randint(state, 6); gr_poly_init(f, ctx); gr_poly_init(g, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_resultant(x, f, g, ctx); status |= gr_poly_resultant(y, g, f, ctx); if (((f->length - 1) * (g->length - 1)) % 2) status |= gr_neg(y, y, ctx); if (status == GR_SUCCESS && gr_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPZ || ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } status |= gr_poly_resultant_euclidean(y, f, g, ctx); if (status == GR_SUCCESS && gr_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL vs euclidean:\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_ctx_clear(ctx); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { gr_ctx_t ctx; gr_poly_t f, fh, h, g; gr_ptr x, y, z, yz; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); if (ctx->methods == _ca_methods) n = n_randint(state, 3); else n = n_randint(state, 6); gr_poly_init(f, ctx); gr_poly_init(fh, ctx); gr_poly_init(g, ctx); gr_poly_init(h, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); z = gr_heap_init(ctx); yz = gr_heap_init(ctx); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_randtest(h, state, n, ctx); status |= gr_poly_resultant(y, f, g, ctx); status |= gr_poly_resultant(z, h, g, ctx); status |= gr_mul(yz, y, z, ctx); status |= gr_poly_mul(fh, f, h, ctx); status |= gr_poly_resultant(x, fh, g, ctx); if (status == GR_SUCCESS && gr_ctx_is_field(ctx) == T_TRUE && gr_equal(x, yz, ctx) == T_FALSE) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); gr_ctx_println(ctx); printf("f = "); gr_poly_print(f, ctx), flint_printf("\n\n"); printf("g = "); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("h = "); gr_poly_print(h, ctx), flint_printf("\n\n"); printf("fh = "); gr_poly_print(fh, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); printf("z = "); gr_println(z, ctx); printf("yz = "); gr_println(yz, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); gr_poly_print(h, ctx), flint_printf("\n\n"); gr_poly_print(fh, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(fh, ctx); gr_poly_clear(g, ctx); gr_poly_clear(h, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_heap_clear(z, ctx); gr_heap_clear(yz, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-resultant_euclidean.c000066400000000000000000000122461461254215100225200ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_resultant_euclidean, state) { slong iter; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_poly_t f, g; gr_ptr x, y; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); gr_poly_init(f, ctx); gr_poly_init(g, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 3); else n = n_randint(state, 6); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_resultant_euclidean(x, f, g, ctx); status |= gr_poly_resultant_euclidean(y, g, f, ctx); if (((f->length - 1) * (g->length - 1)) % 2) status |= gr_neg(y, y, ctx); if (status == GR_SUCCESS && gr_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_ctx_clear(ctx); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx; gr_poly_t f, fh, h, g; gr_ptr x, y, z, yz; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); gr_poly_init(f, ctx); gr_poly_init(fh, ctx); gr_poly_init(g, ctx); gr_poly_init(h, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); z = gr_heap_init(ctx); yz = gr_heap_init(ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 3); else n = n_randint(state, 6); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_randtest(h, state, n, ctx); status |= gr_poly_resultant_euclidean(y, f, g, ctx); status |= gr_poly_resultant_euclidean(z, h, g, ctx); status |= gr_mul(yz, y, z, ctx); status |= gr_poly_mul(fh, f, h, ctx); status |= gr_poly_resultant_euclidean(x, fh, g, ctx); if (status == GR_SUCCESS && gr_ctx_is_field(ctx) == T_TRUE && gr_equal(x, yz, ctx) == T_FALSE) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); gr_ctx_println(ctx); printf("f = "); gr_poly_print(f, ctx), flint_printf("\n\n"); printf("g = "); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("h = "); gr_poly_print(h, ctx), flint_printf("\n\n"); printf("fh = "); gr_poly_print(fh, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); printf("z = "); gr_println(z, ctx); printf("yz = "); gr_println(yz, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); gr_poly_print(h, ctx), flint_printf("\n\n"); gr_poly_print(fh, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(fh, ctx); gr_poly_clear(g, ctx); gr_poly_clear(h, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_heap_clear(z, ctx); gr_heap_clear(yz, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-resultant_hgcd.c000066400000000000000000000165341461254215100215000ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_resultant_hgcd, state) { slong iter; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ /* Also compare with euclidean */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { gr_ctx_t ctx; gr_poly_t f, g; gr_ptr x, y; int status = GR_SUCCESS; slong n, cutoff1, cutoff2; int huge; huge = n_randint(state, 2); if (huge) { while (1) { gr_ctx_init_random(ctx, state); if (gr_ctx_is_finite(ctx) == T_TRUE) break; else gr_ctx_clear(ctx); } } else { gr_ctx_init_random(ctx, state); } if (huge) { n = n_randint(state, 100); cutoff1 = n_randint(state, 100); cutoff2 = n_randint(state, 100); } else if (ctx->which_ring == GR_CTX_CC_CA || ctx->which_ring == GR_CTX_RR_CA) { n = n_randint(state, 3); cutoff1 = n_randint(state, 3); cutoff2 = n_randint(state, 3); } else { n = n_randint(state, 6); cutoff1 = n_randint(state, 6); cutoff2 = n_randint(state, 6); } gr_poly_init(f, ctx); gr_poly_init(g, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_resultant_hgcd(x, f, g, cutoff1, cutoff2, ctx); status |= gr_poly_resultant_hgcd(y, g, f, cutoff1, cutoff2, ctx); if (((f->length - 1) * (g->length - 1)) % 2) status |= gr_neg(y, y, ctx); if (status == GR_SUCCESS && gr_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } status |= gr_poly_resultant_euclidean(y, f, g, ctx); if (status == GR_SUCCESS && gr_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL vs euclidean:\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_ctx_clear(ctx); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { gr_ctx_t ctx; gr_poly_t f, fh, h, g; gr_ptr x, y, z, yz; int status = GR_SUCCESS; slong n, cutoff1, cutoff2; int huge; huge = n_randint(state, 2); if (huge) { while (1) { gr_ctx_init_random(ctx, state); if (gr_ctx_is_finite(ctx) == T_TRUE) break; else gr_ctx_clear(ctx); } } else { gr_ctx_init_random(ctx, state); } if (huge) { n = n_randint(state, 100); cutoff1 = n_randint(state, 100); cutoff2 = n_randint(state, 100); } else if (ctx->methods == _ca_methods) { n = n_randint(state, 3); cutoff1 = n_randint(state, 3); cutoff2 = n_randint(state, 3); } else { n = n_randint(state, 6); cutoff1 = n_randint(state, 6); cutoff2 = n_randint(state, 6); } gr_poly_init(f, ctx); gr_poly_init(fh, ctx); gr_poly_init(g, ctx); gr_poly_init(h, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); z = gr_heap_init(ctx); yz = gr_heap_init(ctx); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_randtest(h, state, n, ctx); status |= gr_poly_resultant_hgcd(y, f, g, cutoff1, cutoff2, ctx); status |= gr_poly_resultant_hgcd(z, h, g, cutoff1, cutoff2, ctx); status |= gr_mul(yz, y, z, ctx); status |= gr_poly_mul(fh, f, h, ctx); status |= gr_poly_resultant_hgcd(x, fh, g, cutoff1, cutoff2, ctx); if (status == GR_SUCCESS && gr_ctx_is_field(ctx) == T_TRUE && gr_equal(x, yz, ctx) == T_FALSE) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); gr_ctx_println(ctx); printf("f = "); gr_poly_print(f, ctx), flint_printf("\n\n"); printf("g = "); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("h = "); gr_poly_print(h, ctx), flint_printf("\n\n"); printf("fh = "); gr_poly_print(fh, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); printf("z = "); gr_println(z, ctx); printf("yz = "); gr_println(yz, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); gr_poly_print(h, ctx), flint_printf("\n\n"); gr_poly_print(fh, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(fh, ctx); gr_poly_clear(g, ctx); gr_poly_clear(h, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_heap_clear(z, ctx); gr_heap_clear(yz, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-resultant_sylvester.c000066400000000000000000000134231461254215100226250ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_resultant_sylvester, state) { slong iter; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ /* Also compare with euclidean */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { gr_ctx_t ctx; gr_poly_t f, g; gr_ptr x, y; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); if (ctx->methods == _ca_methods) n = n_randint(state, 3); else n = n_randint(state, 6); gr_poly_init(f, ctx); gr_poly_init(g, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_resultant_sylvester(x, f, g, ctx); status |= gr_poly_resultant_sylvester(y, g, f, ctx); if (((f->length - 1) * (g->length - 1)) % 2) status |= gr_neg(y, y, ctx); if (status == GR_SUCCESS && gr_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPZ || ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } status |= gr_poly_resultant_euclidean(y, f, g, ctx); if (status == GR_SUCCESS && gr_equal(x, y, ctx) == T_FALSE) { flint_printf("FAIL vs euclidean:\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(g, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_ctx_clear(ctx); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { gr_ctx_t ctx; gr_poly_t f, fh, h, g; gr_ptr x, y, z, yz; int status = GR_SUCCESS; slong n; gr_ctx_init_random(ctx, state); if (ctx->methods == _ca_methods) n = n_randint(state, 3); else n = n_randint(state, 6); gr_poly_init(f, ctx); gr_poly_init(fh, ctx); gr_poly_init(g, ctx); gr_poly_init(h, ctx); x = gr_heap_init(ctx); y = gr_heap_init(ctx); z = gr_heap_init(ctx); yz = gr_heap_init(ctx); status |= gr_poly_randtest(f, state, n, ctx); status |= gr_poly_randtest(g, state, n, ctx); status |= gr_poly_randtest(h, state, n, ctx); status |= gr_poly_resultant_sylvester(y, f, g, ctx); status |= gr_poly_resultant_sylvester(z, h, g, ctx); status |= gr_mul(yz, y, z, ctx); status |= gr_poly_mul(fh, f, h, ctx); status |= gr_poly_resultant_sylvester(x, fh, g, ctx); if (status == GR_SUCCESS && gr_ctx_is_field(ctx) == T_TRUE && gr_equal(x, yz, ctx) == T_FALSE) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); gr_ctx_println(ctx); printf("f = "); gr_poly_print(f, ctx), flint_printf("\n\n"); printf("g = "); gr_poly_print(g, ctx), flint_printf("\n\n"); printf("h = "); gr_poly_print(h, ctx), flint_printf("\n\n"); printf("fh = "); gr_poly_print(fh, ctx), flint_printf("\n\n"); printf("x = "); gr_println(x, ctx); printf("y = "); gr_println(y, ctx); printf("z = "); gr_println(z, ctx); printf("yz = "); gr_println(yz, ctx); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_ctx_println(ctx); gr_poly_print(f, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); gr_poly_print(h, ctx), flint_printf("\n\n"); gr_poly_print(fh, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } gr_poly_clear(f, ctx); gr_poly_clear(fh, ctx); gr_poly_clear(g, ctx); gr_poly_clear(h, ctx); gr_heap_clear(x, ctx); gr_heap_clear(y, ctx); gr_heap_clear(z, ctx); gr_heap_clear(yz, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-revert_series.c000066400000000000000000000071261461254215100213500ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_revert_series(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; gr_poly_t A, B, C, D; int status = GR_SUCCESS; if (n_randint(state, 4) == 0) gr_ctx_init_random(ctx, state); else gr_ctx_init_fmpz(ctx); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(D, ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 20); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(B, state, 1 + n_randint(state, 20), ctx)); GR_MUST_SUCCEED(gr_poly_randtest(C, state, 1 + n_randint(state, 20), ctx)); if (n_randint(state, 10) != 0) GR_MUST_SUCCEED(gr_poly_set_coeff_si(A, 0, 0, ctx)); if (n_randint(state, 2)) GR_MUST_SUCCEED(gr_poly_set_coeff_si(A, 1, 1, ctx)); switch (which) { case 0: status |= gr_poly_revert_series_lagrange(B, A, n, ctx); break; case 1: status |= gr_poly_set(B, A, ctx); status |= gr_poly_revert_series_lagrange(B, B, n, ctx); break; case 2: status |= gr_poly_revert_series_newton(B, A, n, ctx); break; case 3: status |= gr_poly_set(B, A, ctx); status |= gr_poly_revert_series_newton(B, B, n, ctx); break; case 4: status |= gr_poly_revert_series_lagrange_fast(B, A, n, ctx); break; case 5: status |= gr_poly_set(B, A, ctx); status |= gr_poly_revert_series_lagrange_fast(B, B, n, ctx); break; case 6: status |= gr_poly_revert_series(B, A, n, ctx); break; case 7: status |= gr_poly_set(B, A, ctx); status |= gr_poly_revert_series(B, B, n, ctx); break; default: flint_abort(); } if (status == GR_SUCCESS) { status |= gr_poly_compose_series(C, A, B, n, ctx); status |= gr_poly_gen(D, ctx); status |= gr_poly_truncate(D, D, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(C, D, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("which = %d\n\n", which); gr_ctx_println(ctx); flint_printf("n = %wd\n", n); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_printf("D = "); gr_poly_print(D, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(D, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_revert_series, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { test_revert_series(state, n_randint(state, 8)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-roots.c000066400000000000000000000120021461254215100176220ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "gr_vec.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_roots, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { int status; gr_ctx_t ctx, ZZ; gr_poly_t f, g, h, q, r; gr_vec_t roots, mult; slong i, j, expected_mult; int init_from_roots; gr_ctx_init_random(ctx, state); gr_ctx_init_fmpz(ZZ); gr_poly_init(f, ctx); gr_vec_init(roots, 0, ctx); gr_vec_init(mult, 0, ZZ); status = GR_SUCCESS; init_from_roots = n_randint(state, 2); expected_mult = n_randint(state, 4); if (init_from_roots) { gr_ptr c = gr_heap_init(ctx); status |= gr_randtest_not_zero(c, state, ctx); if (status == GR_SUCCESS) { gr_poly_init(h, ctx); status |= gr_poly_set_scalar(f, c, ctx); for (i = 0; i < expected_mult; i++) { status |= gr_poly_set_scalar(h, c, ctx); status |= gr_poly_neg(h, h, ctx); status |= gr_poly_set_coeff_si(h, 1, 1, ctx); status |= gr_poly_mul(f, f, h, ctx); if (n_randint(state, 3) == 0) { status |= gr_poly_mul(f, f, h, ctx); expected_mult++; } } gr_poly_clear(h, ctx); } else { init_from_roots = 0; } gr_heap_clear(c, ctx); } if (!init_from_roots) status |= gr_poly_randtest(f, state, 1 + n_randint(state, 6), ctx); status |= gr_poly_roots(roots, mult, f, 0, ctx); if (status == GR_SUCCESS) { gr_poly_init(g, ctx); gr_poly_init(h, ctx); gr_poly_init(q, ctx); gr_poly_init(r, ctx); status |= gr_poly_one(g, ctx); if (gr_ctx_is_integral_domain(ctx) == T_TRUE) { for (i = 0; i < roots->length; i++) { /* (x-r) */ status |= gr_poly_set_scalar(h, gr_vec_entry_ptr(roots, i, ctx), ctx); status |= gr_poly_neg(h, h, ctx); status |= gr_poly_set_coeff_si(h, 1, 1, ctx); for (j = 0; j < fmpz_get_si(gr_vec_entry_ptr(mult, i, ZZ)); j++) status |= gr_poly_mul(g, g, h, ctx); } status |= gr_poly_divrem(q, r, f, g, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(r, ctx) == T_FALSE) { flint_printf("FAIL: product of factors does not divide polynomial\n\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } if (status == GR_SUCCESS && init_from_roots && g->length != f->length) { flint_printf("FAIL: wrong multiplicity for polynomial that splits\n\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } } else { for (i = 0; i < roots->length; i++) { gr_ptr c = gr_heap_init(ctx); status |= gr_poly_evaluate(c, f, gr_vec_entry_ptr(roots, i, ctx), ctx); if (status == GR_SUCCESS && gr_is_zero(c, ctx) == T_FALSE) { flint_printf("FAIL: f(r) != 0\n\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("r = "); gr_print(gr_vec_entry_ptr(roots, i, ctx), ctx); flint_printf("\n"); flint_printf("r = "); gr_print(c, ctx); flint_printf("\n"); flint_abort(); } gr_heap_clear(c, ctx); } } gr_poly_clear(g, ctx); gr_poly_clear(h, ctx); gr_poly_clear(q, ctx); gr_poly_clear(r, ctx); } gr_poly_clear(f, ctx); gr_vec_clear(roots, ctx); gr_vec_clear(mult, ZZ); gr_ctx_clear(ctx); gr_ctx_clear(ZZ); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-roots_other.c000066400000000000000000000060201461254215100210260ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "gr_vec.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_roots_other, state) { slong iter; for (iter = 0; iter < 10000; iter++) { int status; gr_ctx_t ctx, ctx_other, ZZ; gr_poly_t f, f_other, g, h, q, r; gr_vec_t roots, mult; slong i, j; gr_ctx_init_random(ctx, state); if (n_randint(state, 2)) gr_ctx_init_fmpz(ctx_other); else gr_ctx_init_random(ctx_other, state); gr_ctx_init_fmpz(ZZ); gr_poly_init(f, ctx); gr_poly_init(f_other, ctx_other); gr_vec_init(roots, 0, ctx); gr_vec_init(mult, 0, ZZ); status = GR_SUCCESS; status |= gr_poly_randtest(f_other, state, 1 + n_randint(state, 6), ctx_other); status |= gr_poly_roots_other(roots, mult, f_other, ctx_other, 0, ctx); if (status == GR_SUCCESS) { status |= gr_poly_set_gr_poly_other(f, f_other, ctx_other, ctx); if (status == GR_SUCCESS) { gr_poly_init(g, ctx); gr_poly_init(h, ctx); gr_poly_init(q, ctx); gr_poly_init(r, ctx); status |= gr_poly_one(g, ctx); for (i = 0; i < roots->length; i++) { /* (x-r) */ status |= gr_poly_set_scalar(h, gr_vec_entry_ptr(roots, i, ctx), ctx); status |= gr_poly_neg(h, h, ctx); status |= gr_poly_set_coeff_si(h, 1, 1, ctx); for (j = 0; j < fmpz_get_si(gr_vec_entry_ptr(mult, i, ZZ)); j++) status |= gr_poly_mul(g, g, h, ctx); } status |= gr_poly_divrem(q, r, f, g, ctx); if (status == GR_SUCCESS && gr_poly_is_zero(r, ctx) == T_FALSE) { flint_printf("FAIL: product of factors does not divide polynomial\n\n"); flint_printf("f = "); gr_poly_print(f, ctx); flint_printf("\n"); flint_printf("g = "); gr_poly_print(g, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(g, ctx); gr_poly_clear(h, ctx); gr_poly_clear(q, ctx); gr_poly_clear(r, ctx); } } gr_poly_clear(f, ctx); gr_poly_clear(f_other, ctx_other); gr_vec_clear(roots, ctx); gr_vec_clear(mult, ZZ); gr_ctx_clear(ctx); gr_ctx_clear(ctx_other); gr_ctx_clear(ZZ); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-rsqrt_series.c000066400000000000000000000062571461254215100212200ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_rsqrt_series(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; gr_poly_t A, B, C; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 20); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 20, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(B, state, 20, ctx)); if (n_randint(state, 2)) { status |= gr_poly_mullow(A, A, A, n_randint(state, 20), ctx); status |= gr_poly_inv_series(A, A, n_randint(state, 20), ctx); } switch (which) { case 0: status |= gr_poly_rsqrt_series(B, A, n, ctx); break; case 1: status |= gr_poly_set(B, A, ctx); status |= gr_poly_rsqrt_series(B, B, n, ctx); break; case 2: status |= gr_poly_rsqrt_series_basecase(B, A, n, ctx); break; case 3: status |= gr_poly_set(B, A, ctx); status |= gr_poly_rsqrt_series_basecase(B, B, n, ctx); break; case 4: status |= gr_poly_rsqrt_series_newton(B, A, n, n_randint(state, 20), ctx); break; case 5: status |= gr_poly_set(B, A, ctx); status |= gr_poly_rsqrt_series_newton(B, B, n, n_randint(state, 20), ctx); break; case 6: status |= gr_poly_rsqrt_series_miller(B, A, n, ctx); break; case 7: status |= gr_poly_set(B, A, ctx); status |= gr_poly_rsqrt_series_miller(B, B, n, ctx); break; default: flint_abort(); } if (status == GR_SUCCESS) { status |= gr_poly_mullow(C, B, B, n, ctx); status |= gr_poly_inv_series(C, C, n, ctx); status |= gr_poly_truncate(A, A, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(C, A, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("which = %d\n\n", which); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_rsqrt_series, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_rsqrt_series(state, n_randint(state, 8)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-shift_left_right.c000066400000000000000000000070041461254215100220060ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_shift_left_right, state) { int i; /* Check aliasing of a and b for left shift */ for (i = 0; i < 100; i++) { gr_ctx_t ctx; gr_poly_t a, b; int status = GR_SUCCESS; slong shift = n_randint(state, 5); gr_ctx_init_random(ctx, state); gr_poly_init(a, ctx); gr_poly_init(b, ctx); status |= gr_poly_randtest(a, state, n_randint(state, 5), ctx); status |= gr_poly_randtest(b, state, n_randint(state, 5), ctx); status |= gr_poly_shift_left(b, a, shift, ctx); status |= gr_poly_shift_left(a, a, shift, ctx); if (status == GR_SUCCESS && gr_poly_equal(a, b, ctx) == T_FALSE) { flint_printf("FAIL (alias left):\n"); gr_poly_print(a, ctx), flint_printf("\n\n"); gr_poly_print(b, ctx), flint_printf("\n\n"); flint_abort(); } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_ctx_clear(ctx); } /* Check aliasing of a and b for right shift */ for (i = 0; i < 100; i++) { gr_ctx_t ctx; gr_poly_t a, b; int status = GR_SUCCESS; slong shift = n_randint(state, 5); gr_ctx_init_random(ctx, state); gr_poly_init(a, ctx); gr_poly_init(b, ctx); status |= gr_poly_randtest(a, state, n_randint(state, 5), ctx); status |= gr_poly_randtest(b, state, n_randint(state, 5), ctx); status |= gr_poly_shift_right(b, a, shift, ctx); status |= gr_poly_shift_right(a, a, shift, ctx); if (status == GR_SUCCESS && gr_poly_equal(a, b, ctx) == T_FALSE) { flint_printf("FAIL (alias right):\n"); gr_poly_print(a, ctx), flint_printf("\n\n"); gr_poly_print(b, ctx), flint_printf("\n\n"); flint_abort(); } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_ctx_clear(ctx); } /* Check shift left then right does nothing */ for (i = 0; i < 100; i++) { gr_ctx_t ctx; gr_poly_t a, b, c; int status = GR_SUCCESS; slong shift = n_randint(state, 5); gr_ctx_init_random(ctx, state); gr_poly_init(a, ctx); gr_poly_init(b, ctx); gr_poly_init(c, ctx); status |= gr_poly_randtest(a, state, n_randint(state, 5), ctx); status |= gr_poly_randtest(b, state, n_randint(state, 5), ctx); status |= gr_poly_randtest(c, state, n_randint(state, 5), ctx); status |= gr_poly_shift_left(b, a, shift, ctx); status |= gr_poly_shift_right(c, b, shift, ctx); if (status == GR_SUCCESS && gr_poly_equal(c, a, ctx) == T_FALSE) { flint_printf("FAIL:\n"); gr_poly_print(a, ctx), flint_printf("\n\n"); gr_poly_print(b, ctx), flint_printf("\n\n"); gr_poly_print(c, ctx), flint_printf("\n\n"); flint_abort(); } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_poly_clear(c, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-sqrt_series.c000066400000000000000000000060351461254215100210300ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; int test_sqrt_series(flint_rand_t state, int which) { gr_ctx_t ctx; slong n; gr_poly_t A, B, C; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); if (ctx->methods == _ca_methods) n = n_randint(state, 5); else n = n_randint(state, 20); GR_MUST_SUCCEED(gr_poly_randtest(A, state, 20, ctx)); GR_MUST_SUCCEED(gr_poly_randtest(B, state, 20, ctx)); if (n_randint(state, 2)) status |= gr_poly_mullow(A, A, A, n_randint(state, 20), ctx); switch (which) { case 0: status |= gr_poly_sqrt_series(B, A, n, ctx); break; case 1: status |= gr_poly_set(B, A, ctx); status |= gr_poly_sqrt_series(B, B, n, ctx); break; case 2: status |= gr_poly_sqrt_series_basecase(B, A, n, ctx); break; case 3: status |= gr_poly_set(B, A, ctx); status |= gr_poly_sqrt_series_basecase(B, B, n, ctx); break; case 4: status |= gr_poly_sqrt_series_newton(B, A, n, n_randint(state, 20), ctx); break; case 5: status |= gr_poly_set(B, A, ctx); status |= gr_poly_sqrt_series_newton(B, B, n, n_randint(state, 20), ctx); break; case 6: status |= gr_poly_sqrt_series_miller(B, A, n, ctx); break; case 7: status |= gr_poly_set(B, A, ctx); status |= gr_poly_sqrt_series_miller(B, B, n, ctx); break; default: flint_abort(); } if (status == GR_SUCCESS) { status |= gr_poly_mullow(C, B, B, n, ctx); status |= gr_poly_truncate(A, A, n, ctx); if (status == GR_SUCCESS && gr_poly_equal(C, A, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("which = %d\n\n", which); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_abort(); } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_poly_sqrt_series, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_sqrt_series(state, n_randint(state, 8)); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-squarefree_part.c000066400000000000000000000051561461254215100216600ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_vec.h" #include "gr_poly.h" FLINT_DLL extern gr_static_method_table _ca_methods; TEST_FUNCTION_START(gr_poly_squarefree_part, state) { slong iter; for (iter = 0; iter < 1000; iter++) { gr_ctx_t ctx, poly_ctx, fmpz_ctx; gr_poly_t A, B, C; gr_ptr c; gr_vec_t F, exp; slong i; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); while (gr_ctx_is_field(ctx) != T_TRUE) { gr_ctx_clear(ctx); gr_ctx_init_random(ctx, state); } gr_ctx_init_gr_poly(poly_ctx, ctx); gr_ctx_init_fmpz(fmpz_ctx); gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_vec_init(F, 0, poly_ctx); gr_vec_init(exp, 0, fmpz_ctx); c = gr_heap_init(ctx); if (ctx->methods == _ca_methods) status |= gr_poly_randtest(A, state, 3, ctx); else status |= gr_poly_randtest(A, state, 10, ctx); status |= gr_poly_factor_squarefree(c, F, exp, A, ctx); if (status == GR_SUCCESS) { status |= gr_poly_squarefree_part(B, A, ctx); if (status == GR_SUCCESS) { status |= gr_poly_one(C, ctx); for (i = 0; i < F->length; i++) status |= gr_poly_mul(C, C, gr_vec_entry_ptr(F, i, poly_ctx), ctx); if (status == GR_SUCCESS && gr_poly_equal(B, C, ctx) == T_FALSE) { flint_printf("FAIL (product)\n\n"); flint_printf("A = "); gr_poly_print(A, ctx); flint_printf("\n"); flint_printf("B = "); gr_poly_print(B, ctx); flint_printf("\n"); flint_printf("C = "); gr_poly_print(C, ctx); flint_printf("\n"); flint_abort(); } } } gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_vec_clear(F, poly_ctx); gr_vec_clear(exp, fmpz_ctx); gr_heap_clear(c, ctx); gr_ctx_clear(poly_ctx); gr_ctx_clear(fmpz_ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-taylor_shift.c000066400000000000000000000046731461254215100212020ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_taylor_shift, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, Fc, Fcd1, Fcd2; gr_ptr c, d, cd; /* check F(x+c)(x+d) = F(x+c+d) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(Fc, ctx); gr_poly_init(Fcd1, ctx); gr_poly_init(Fcd2, ctx); c = gr_heap_init(ctx); d = gr_heap_init(ctx); cd = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(Fc, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(c, state, ctx); status |= gr_randtest(d, state, ctx); status |= gr_add(cd, c, d, ctx); status |= gr_poly_taylor_shift(Fc, F, c, ctx); status |= gr_poly_taylor_shift(Fcd1, Fc, d, ctx); status |= gr_poly_set(Fcd2, F, ctx); /* also test aliasing */ status |= gr_poly_taylor_shift(Fcd2, Fcd2, cd, ctx); if (status == GR_SUCCESS && gr_poly_equal(Fcd1, Fcd2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("c = "); gr_println(c, ctx); flint_printf("d = "); gr_println(d, ctx); flint_printf("cd = "); gr_println(cd, ctx); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("Fc = "); gr_poly_print(Fc, ctx); flint_printf("\n"); flint_printf("Fcd1 = "); gr_poly_print(Fcd1, ctx); flint_printf("\n"); flint_printf("Fcd2 = "); gr_poly_print(Fcd2, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(Fc, ctx); gr_poly_clear(Fcd1, ctx); gr_poly_clear(Fcd2, ctx); gr_heap_clear(c, ctx); gr_heap_clear(d, ctx); gr_heap_clear(cd, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-taylor_shift_convolution.c000066400000000000000000000047531461254215100236400ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_taylor_shift_convolution, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, Fc, Fcd1, Fcd2; gr_ptr c, d, cd; /* check F(x+c)(x+d) = F(x+c+d) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(Fc, ctx); gr_poly_init(Fcd1, ctx); gr_poly_init(Fcd2, ctx); c = gr_heap_init(ctx); d = gr_heap_init(ctx); cd = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(Fc, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(c, state, ctx); status |= gr_randtest(d, state, ctx); status |= gr_add(cd, c, d, ctx); status |= gr_poly_taylor_shift_convolution(Fc, F, c, ctx); status |= gr_poly_taylor_shift_convolution(Fcd1, Fc, d, ctx); status |= gr_poly_set(Fcd2, F, ctx); /* also test aliasing */ status |= gr_poly_taylor_shift_convolution(Fcd2, Fcd2, cd, ctx); if (status == GR_SUCCESS && gr_poly_equal(Fcd1, Fcd2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("c = "); gr_println(c, ctx); flint_printf("d = "); gr_println(d, ctx); flint_printf("cd = "); gr_println(cd, ctx); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("Fc = "); gr_poly_print(Fc, ctx); flint_printf("\n"); flint_printf("Fcd1 = "); gr_poly_print(Fcd1, ctx); flint_printf("\n"); flint_printf("Fcd2 = "); gr_poly_print(Fcd2, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(Fc, ctx); gr_poly_clear(Fcd1, ctx); gr_poly_clear(Fcd2, ctx); gr_heap_clear(c, ctx); gr_heap_clear(d, ctx); gr_heap_clear(cd, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-taylor_shift_divconquer.c000066400000000000000000000047471461254215100234430ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_taylor_shift_divconquer, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, Fc, Fcd1, Fcd2; gr_ptr c, d, cd; /* check F(x+c)(x+d) = F(x+c+d) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(Fc, ctx); gr_poly_init(Fcd1, ctx); gr_poly_init(Fcd2, ctx); c = gr_heap_init(ctx); d = gr_heap_init(ctx); cd = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(Fc, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(c, state, ctx); status |= gr_randtest(d, state, ctx); status |= gr_add(cd, c, d, ctx); status |= gr_poly_taylor_shift_divconquer(Fc, F, c, ctx); status |= gr_poly_taylor_shift_divconquer(Fcd1, Fc, d, ctx); status |= gr_poly_set(Fcd2, F, ctx); /* also test aliasing */ status |= gr_poly_taylor_shift_divconquer(Fcd2, Fcd2, cd, ctx); if (status == GR_SUCCESS && gr_poly_equal(Fcd1, Fcd2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("c = "); gr_println(c, ctx); flint_printf("d = "); gr_println(d, ctx); flint_printf("cd = "); gr_println(cd, ctx); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("Fc = "); gr_poly_print(Fc, ctx); flint_printf("\n"); flint_printf("Fcd1 = "); gr_poly_print(Fcd1, ctx); flint_printf("\n"); flint_printf("Fcd2 = "); gr_poly_print(Fcd2, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(Fc, ctx); gr_poly_clear(Fcd1, ctx); gr_poly_clear(Fcd2, ctx); gr_heap_clear(c, ctx); gr_heap_clear(d, ctx); gr_heap_clear(cd, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-taylor_shift_horner.c000066400000000000000000000047271461254215100225570ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_taylor_shift_horner, state) { slong iter; for (iter = 0; iter < 1000; iter++) { int status; gr_ctx_t ctx; gr_poly_t F, Fc, Fcd1, Fcd2; gr_ptr c, d, cd; /* check F(x+c)(x+d) = F(x+c+d) */ gr_ctx_init_random(ctx, state); gr_poly_init(F, ctx); gr_poly_init(Fc, ctx); gr_poly_init(Fcd1, ctx); gr_poly_init(Fcd2, ctx); c = gr_heap_init(ctx); d = gr_heap_init(ctx); cd = gr_heap_init(ctx); status = GR_SUCCESS; status |= gr_poly_randtest(F, state, 1 + n_randint(state, 10), ctx); status |= gr_poly_randtest(Fc, state, 1 + n_randint(state, 10), ctx); status |= gr_randtest(c, state, ctx); status |= gr_randtest(d, state, ctx); status |= gr_add(cd, c, d, ctx); status |= gr_poly_taylor_shift_horner(Fc, F, c, ctx); status |= gr_poly_taylor_shift_horner(Fcd1, Fc, d, ctx); status |= gr_poly_set(Fcd2, F, ctx); /* also test aliasing */ status |= gr_poly_taylor_shift_horner(Fcd2, Fcd2, cd, ctx); if (status == GR_SUCCESS && gr_poly_equal(Fcd1, Fcd2, ctx) == T_FALSE) { flint_printf("FAIL\n\n"); flint_printf("c = "); gr_println(c, ctx); flint_printf("d = "); gr_println(d, ctx); flint_printf("cd = "); gr_println(cd, ctx); flint_printf("F = "); gr_poly_print(F, ctx); flint_printf("\n"); flint_printf("Fc = "); gr_poly_print(Fc, ctx); flint_printf("\n"); flint_printf("Fcd1 = "); gr_poly_print(Fcd1, ctx); flint_printf("\n"); flint_printf("Fcd2 = "); gr_poly_print(Fcd2, ctx); flint_printf("\n"); flint_abort(); } gr_poly_clear(F, ctx); gr_poly_clear(Fc, ctx); gr_poly_clear(Fcd1, ctx); gr_poly_clear(Fcd2, ctx); gr_heap_clear(c, ctx); gr_heap_clear(d, ctx); gr_heap_clear(cd, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-xgcd_euclidean.c000066400000000000000000000115241461254215100214220ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_xgcd_euclidean, state) { int i; /* Compare with result from GCD and check correctness */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { gr_ctx_t ctx; gr_poly_t a, b, d, g, s, t, v, w; int status = GR_SUCCESS; int aliasing; slong n; gr_ctx_init_random(ctx, state); if (gr_ctx_is_finite(ctx) == T_TRUE && n_randint(state, 2) == 0) n = 20; else if (ctx->which_ring == GR_CTX_CC_CA || ctx->which_ring == GR_CTX_RR_CA) n = 4; else n = 6; gr_poly_init(a, ctx); gr_poly_init(b, ctx); gr_poly_init(d, ctx); gr_poly_init(g, ctx); gr_poly_init(s, ctx); gr_poly_init(t, ctx); gr_poly_init(v, ctx); gr_poly_init(w, ctx); status |= gr_poly_randtest(a, state, n_randint(state, n), ctx); status |= gr_poly_randtest(b, state, n_randint(state, n), ctx); /* common factor */ if (n_randint(state, 2)) { status |= gr_poly_randtest(t, state, n_randint(state, n), ctx); status |= gr_poly_mul(a, a, t, ctx); status |= gr_poly_mul(b, b, t, ctx); } status |= gr_poly_randtest(g, state, 3, ctx); status |= gr_poly_randtest(s, state, 3, ctx); status |= gr_poly_randtest(t, state, 3, ctx); aliasing = n_randint(state, 8); switch (aliasing) { case 0: status |= gr_poly_xgcd_euclidean(g, s, t, a, b, ctx); break; case 1: status |= gr_poly_set(g, a, ctx); status |= gr_poly_xgcd_euclidean(g, s, t, g, b, ctx); break; case 2: status |= gr_poly_set(s, a, ctx); status |= gr_poly_xgcd_euclidean(g, s, t, s, b, ctx); break; case 3: status |= gr_poly_set(t, a, ctx); status |= gr_poly_xgcd_euclidean(g, s, t, t, b, ctx); break; case 4: status |= gr_poly_set(g, b, ctx); status |= gr_poly_xgcd_euclidean(g, s, t, a, g, ctx); break; case 5: status |= gr_poly_set(s, b, ctx); status |= gr_poly_xgcd_euclidean(g, s, t, a, s, ctx); break; case 6: status |= gr_poly_set(t, b, ctx); status |= gr_poly_xgcd_euclidean(g, s, t, a, t, ctx); break; case 7: status |= gr_poly_set(b, a, ctx); status |= gr_poly_xgcd_euclidean(g, s, t, a, a, ctx); break; default: break; } status |= gr_poly_gcd_euclidean(d, a, b, ctx); status |= gr_poly_mul(v, s, a, ctx); status |= gr_poly_mul(w, t, b, ctx); status |= gr_poly_add(w, v, w, ctx); if (status == GR_SUCCESS && (gr_poly_equal(d, g, ctx) == T_FALSE || gr_poly_equal(g, w, ctx) == T_FALSE)) { flint_printf("FAIL:\n"); gr_poly_print(a, ctx), flint_printf("\n\n"); gr_poly_print(b, ctx), flint_printf("\n\n"); gr_poly_print(d, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); gr_poly_print(s, ctx), flint_printf("\n\n"); gr_poly_print(t, ctx), flint_printf("\n\n"); gr_poly_print(v, ctx), flint_printf("\n\n"); gr_poly_print(w, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_poly_print(a, ctx), flint_printf("\n\n"); gr_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_poly_clear(d, ctx); gr_poly_clear(g, ctx); gr_poly_clear(s, ctx); gr_poly_clear(t, ctx); gr_poly_clear(v, ctx); gr_poly_clear(w, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/test/t-xgcd_hgcd.c000066400000000000000000000122111461254215100203700ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_poly.h" TEST_FUNCTION_START(gr_poly_xgcd_hgcd, state) { int i; /* Compare with result from GCD and check correctness */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { gr_ctx_t ctx; gr_poly_t a, b, d, g, s, t, v, w; int status = GR_SUCCESS; int aliasing; slong n, cutoff1, cutoff2; gr_ctx_init_random(ctx, state); cutoff1 = n_randint(state, 10); cutoff2 = n_randint(state, 10); if (gr_ctx_is_finite(ctx) == T_TRUE && n_randint(state, 2) == 0) { n = 100; cutoff1 = n_randint(state, 100); cutoff2 = n_randint(state, 100); } else if (ctx->which_ring == GR_CTX_CC_CA || ctx->which_ring == GR_CTX_RR_CA) n = 4; else n = 6; gr_poly_init(a, ctx); gr_poly_init(b, ctx); gr_poly_init(d, ctx); gr_poly_init(g, ctx); gr_poly_init(s, ctx); gr_poly_init(t, ctx); gr_poly_init(v, ctx); gr_poly_init(w, ctx); status |= gr_poly_randtest(a, state, n_randint(state, n), ctx); status |= gr_poly_randtest(b, state, n_randint(state, n), ctx); /* common factor */ if (n_randint(state, 2)) { status |= gr_poly_randtest(t, state, n_randint(state, n), ctx); status |= gr_poly_mul(a, a, t, ctx); status |= gr_poly_mul(b, b, t, ctx); } status |= gr_poly_randtest(g, state, 3, ctx); status |= gr_poly_randtest(s, state, 3, ctx); status |= gr_poly_randtest(t, state, 3, ctx); aliasing = n_randint(state, 8); switch (aliasing) { case 0: status |= gr_poly_xgcd_hgcd(g, s, t, a, b, cutoff1, cutoff2, ctx); break; case 1: status |= gr_poly_set(g, a, ctx); status |= gr_poly_xgcd_hgcd(g, s, t, g, b, cutoff1, cutoff2, ctx); break; case 2: status |= gr_poly_set(s, a, ctx); status |= gr_poly_xgcd_hgcd(g, s, t, s, b, cutoff1, cutoff2, ctx); break; case 3: status |= gr_poly_set(t, a, ctx); status |= gr_poly_xgcd_hgcd(g, s, t, t, b, cutoff1, cutoff2, ctx); break; case 4: status |= gr_poly_set(g, b, ctx); status |= gr_poly_xgcd_hgcd(g, s, t, a, g, cutoff1, cutoff2, ctx); break; case 5: status |= gr_poly_set(s, b, ctx); status |= gr_poly_xgcd_hgcd(g, s, t, a, s, cutoff1, cutoff2, ctx); break; case 6: status |= gr_poly_set(t, b, ctx); status |= gr_poly_xgcd_hgcd(g, s, t, a, t, cutoff1, cutoff2, ctx); break; case 7: status |= gr_poly_set(b, a, ctx); status |= gr_poly_xgcd_hgcd(g, s, t, a, a, cutoff1, cutoff2, ctx); break; default: break; } status |= gr_poly_gcd_euclidean(d, a, b, ctx); status |= gr_poly_mul(v, s, a, ctx); status |= gr_poly_mul(w, t, b, ctx); status |= gr_poly_add(w, v, w, ctx); if (status == GR_SUCCESS && (gr_poly_equal(d, g, ctx) == T_FALSE || gr_poly_equal(g, w, ctx) == T_FALSE)) { flint_printf("FAIL:\n"); gr_poly_print(a, ctx), flint_printf("\n\n"); gr_poly_print(b, ctx), flint_printf("\n\n"); gr_poly_print(d, ctx), flint_printf("\n\n"); gr_poly_print(g, ctx), flint_printf("\n\n"); gr_poly_print(s, ctx), flint_printf("\n\n"); gr_poly_print(t, ctx), flint_printf("\n\n"); gr_poly_print(v, ctx), flint_printf("\n\n"); gr_poly_print(w, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } if ((ctx->which_ring == GR_CTX_FMPQ || (ctx->which_ring == GR_CTX_NMOD8 && gr_ctx_is_field(ctx) == T_TRUE)) && status != GR_SUCCESS) { flint_printf("FAIL: did not succeed over Q or Z/pZ\n\n"); gr_poly_print(a, ctx), flint_printf("\n\n"); gr_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } gr_poly_clear(a, ctx); gr_poly_clear(b, ctx); gr_poly_clear(d, ctx); gr_poly_clear(g, ctx); gr_poly_clear(s, ctx); gr_poly_clear(t, ctx); gr_poly_clear(v, ctx); gr_poly_clear(w, ctx); gr_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_poly/truncate.c000066400000000000000000000021421461254215100170650ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_poly.h" #include "gr_vec.h" int gr_poly_truncate(gr_poly_t poly, const gr_poly_t src, slong newlen, gr_ctx_t ctx) { if (src == poly) { if (poly->length > newlen) { _gr_poly_set_length(poly, newlen, ctx); _gr_poly_normalise(poly, ctx); } return GR_SUCCESS; } else { int status = GR_SUCCESS; slong len = src->length; newlen = FLINT_MIN(newlen, src->length); gr_poly_fit_length(poly, newlen, ctx); status |= _gr_vec_set(poly->coeffs, src->coeffs, newlen, ctx); _gr_poly_set_length(poly, newlen, ctx); if (newlen < len) _gr_poly_normalise(poly, ctx); return status; } } flint-3.1.3/src/gr_poly/tune/000077500000000000000000000000001461254215100160505ustar00rootroot00000000000000flint-3.1.3/src/gr_poly/tune/cutoffs.c000066400000000000000000000240251461254215100176700ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" #include "gr_vec.h" #include "gr_poly.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "nmod_poly.h" #include "fq.h" #include "fq_nmod.h" #include "fq_zech.h" #include "profiler.h" slong next_powhalf2(slong n) { if ((n & (n - 1)) == 0) return n * 1.414213562373095 + 0.5; else return WORD(1) << FLINT_BIT_COUNT(n); } void _nmod_poly_mul_mid_default_mpn_ctx(mp_ptr res, slong zl, slong zh, mp_srcptr a, slong an, mp_srcptr b, slong bn, nmod_t mod); #define TIMEIT_END_REPEAT3(__timer, __reps, __min_time) \ } \ timeit_stop(__timer); \ if (__timer->cpu >= __min_time) \ break; \ __reps *= 10; \ } \ } while (0); #define TIMEIT_STOP_VALUES3(tcpu, twall, __min_time) \ TIMEIT_END_REPEAT3(__timer, __reps, __min_time) \ (tcpu) = __timer->cpu*0.001 / __reps; \ (twall) = __timer->wall*0.001 / __reps; \ } while (0); #if 0 #define INIT_CTX gr_ctx_init_nmod(ctx, n_nextprime(UWORD(1) << (bits - 1), 0)); #define RANDCOEFF(t, ctx) GR_IGNORE(gr_set_ui(t, n_randlimb(state), ctx)) #define STEP_BITS for (bits = 1, j = 0; bits <= 64; bits++, j++) #endif #if 1 #define INIT_CTX fmpz_t t; fmpz_init(t); fmpz_ui_pow_ui(t, 2, bits - 1); fmpz_add_ui(t, t, 1); /* fmpz_nextprime(t, t, 0); */ gr_ctx_init_fmpz_mod(ctx, t); fmpz_clear(t); #define RANDCOEFF(t, ctx) fmpz_mod_rand(t, state, gr_ctx_data_as_ptr(ctx)); #define STEP_BITS for (bits = 32, j = 0; bits <= 65536; bits = next_powhalf2(bits), j++) #endif #if 0 #define INIT_CTX fmpz_t t; fmpz_init(t); fmpz_ui_pow_ui(t, 2, bits - 1); fmpz_nextprime(t, t, 0); gr_ctx_init_fq(ctx, t, 2, "a"); fmpz_clear(t); #define RANDCOEFF(t, ctx) fq_rand(t, state, gr_ctx_data_as_ptr(ctx)); #define STEP_BITS for (bits = 100, j = 1; bits <= 100; bits *= 2, j++) #endif #if 0 #define INIT_CTX fmpz_t t; fmpz_init(t); fmpz_set_ui(t, n_nextprime(1000000, 0)); gr_ctx_init_fq_nmod(ctx, t, bits, "a"); fmpz_clear(t); #define RANDCOEFF(t, ctx) fq_nmod_rand(t, state, gr_ctx_data_as_ptr(ctx)); #define STEP_BITS for (bits = 4, j = 1; bits <= 64; bits *= 2, j++) #endif #if 0 #define INIT_CTX fmpz_t t; fmpz_init(t); fmpz_set_ui(t, 3); gr_ctx_init_fq_zech(ctx, t, bits, "a"); fmpz_clear(t); #define RANDCOEFF(t, ctx) fq_zech_rand(t, state, gr_ctx_data_as_ptr(ctx)); #define STEP_BITS for (bits = 2, j = 1; bits <= 12; bits++, j++) #endif #if 0 #define INFO "inv_series" #define SETUP random_input(A, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(A, 0, 1, ctx)); #define CASE_A GR_IGNORE(gr_poly_inv_series_basecase(B, A, len, ctx)); #define CASE_B GR_IGNORE(gr_poly_inv_series_newton(B, A, len, len, ctx)); #endif #if 0 #define INFO "div_series" #define SETUP random_input(A, state, len, ctx); \ random_input(B, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(B, 0, 1, ctx)); #define CASE_A GR_IGNORE(gr_poly_div_series_basecase(C, A, B, len, ctx)); #define CASE_B GR_IGNORE(gr_poly_div_series_newton(C, A, B, len, len, ctx)); #endif #if 0 #define INFO "rsqrt_series" #define SETUP random_input(A, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(A, 0, 1, ctx)); #define CASE_A GR_IGNORE(gr_poly_rsqrt_series_basecase(B, A, len, ctx)); #define CASE_B GR_IGNORE(gr_poly_rsqrt_series_newton(B, A, len, len, ctx)); #endif #if 0 #define INFO "sqrt_series" #define SETUP random_input(A, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(A, 0, 1, ctx)); #define CASE_A GR_IGNORE(gr_poly_sqrt_series_basecase(B, A, len, ctx)); #define CASE_B GR_IGNORE(gr_poly_sqrt_series_newton(B, A, len, len, ctx)); #endif #if 0 #define INFO "exp_series (basecase -> mul)" #define SETUP random_input(A, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(A, 0, 0, ctx)); #define CASE_A GR_IGNORE(gr_poly_exp_series_basecase(B, A, len, ctx)); #define CASE_B GR_IGNORE(gr_poly_exp_series_basecase_mul(B, A, len, ctx)); #endif #if 0 #define INFO "exp_series (mul-> newton)" #define SETUP random_input(A, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(A, 0, 0, ctx)); #define CASE_A GR_IGNORE(gr_poly_exp_series_basecase_mul(B, A, len, ctx)); #define CASE_B GR_IGNORE(gr_poly_exp_series_newton(B, A, len, len, ctx)); #endif #if 0 #define INFO "divrem" #define SETUP random_input(A, state, 2 * len, ctx); \ random_input(B, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(B, len - 1, 1, ctx)); #define CASE_A GR_IGNORE(gr_poly_divrem_basecase(C, D, A, B, ctx)); #define CASE_B GR_IGNORE(gr_poly_divrem_newton(C, D, A, B, ctx)); #endif #if 0 #define INFO "divrem (nmod basecase)" #define SETUP random_input(A, state, 2 * len, ctx); \ random_input(B, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(B, len - 1, 1, ctx)); #define CASE_A gr_poly_fit_length(C, A->length - B->length + 1, ctx); gr_poly_fit_length(D, B->length - 1, ctx); \ _nmod_poly_divrem(C->coeffs, D->coeffs, A->coeffs, A->length, B->coeffs, B->length, ((nmod_t *) gr_ctx_data_ptr(ctx))[0]); #define CASE_B GR_IGNORE(gr_poly_divrem_newton(C, D, A, B, ctx)); #endif #if 0 #define INFO "divrem (fmpz_mod basecase)" #define SETUP random_input(A, state, 2 * len, ctx); \ random_input(B, state, len, ctx); \ GR_IGNORE(gr_poly_set_coeff_si(B, len - 1, 1, ctx)); #define CASE_A GR_IGNORE(gr_poly_set(D, A, ctx)); fmpz_mod_poly_divrem_basecase(C, D, D, B, gr_ctx_data_as_ptr(ctx)); #define CASE_B GR_IGNORE(gr_poly_set(D, A, ctx)); GR_IGNORE(gr_poly_divrem_newton(C, D, D, B, ctx)); #endif #if 0 #define INFO "mul (nmod)" #define SETUP random_input(A, state, len, ctx); \ random_input(B, state, len, ctx); #define CASE_A gr_poly_fit_length(C, A->length + B->length - 1, ctx); \ _nmod_poly_mul(C->coeffs, A->coeffs, A->length, B->coeffs, B->length, ((nmod_t *) gr_ctx_data_ptr(ctx))[0]); #define CASE_B gr_poly_fit_length(C, A->length + B->length - 1, ctx); \ flint_nmod_poly_mul_mid_fft_small(C->coeffs, 0, A->length + B->length - 1, A->coeffs, A->length, B->coeffs, B->length, ((nmod_t *) gr_ctx_data_ptr(ctx))[0]); #endif #if 0 #define INFO "sqr (nmod)" #define SETUP random_input(A, state, len, ctx); \ random_input(B, state, len, ctx); #define CASE_A gr_poly_fit_length(C, A->length + A->length - 1, ctx); \ _nmod_poly_mul(C->coeffs, A->coeffs, A->length, A->coeffs, A->length, ((nmod_t *) gr_ctx_data_ptr(ctx))[0]); #define CASE_B gr_poly_fit_length(C, A->length + A->length - 1, ctx); \ flint_nmod_poly_mul_mid_fft_small(C->coeffs, 0, A->length + A->length - 1, A->coeffs, A->length, A->coeffs, A->length, ((nmod_t *) gr_ctx_data_ptr(ctx))[0]); #endif #if 0 #define INFO "mullow (nmod)" #define SETUP random_input(A, state, len, ctx); \ random_input(B, state, len, ctx); #define CASE_A gr_poly_fit_length(C, A->length + B->length - 1, ctx); \ _nmod_poly_mullow(C->coeffs, A->coeffs, A->length, B->coeffs, B->length, B->length, ((nmod_t *) gr_ctx_data_ptr(ctx))[0]); #define CASE_B gr_poly_fit_length(C, A->length + B->length - 1, ctx); \ _nmod_poly_mul_mid_default_mpn_ctx(C->coeffs, 0, B->length, A->coeffs, A->length, B->coeffs, B->length, ((nmod_t *) gr_ctx_data_ptr(ctx))[0]); #endif void random_input(gr_poly_t A, flint_rand_t state, slong len, gr_ctx_t ctx) { gr_ptr t; slong i; GR_TMP_INIT(t, ctx); for (i = 0; i < len; i++) { RANDCOEFF(t, ctx); GR_IGNORE(gr_poly_set_coeff_scalar(A, i, t, ctx)); } while (A->length != len) { RANDCOEFF(t, ctx); GR_IGNORE(gr_poly_set_coeff_scalar(A, len - 1, t, ctx)); } GR_TMP_CLEAR(t, ctx); } double get_profile(gr_ctx_t ctx, slong len) { gr_poly_t A, B, C, D; double tcpu, twall, tbase, tnew; flint_rand_t state; gr_poly_init(A, ctx); gr_poly_init(B, ctx); gr_poly_init(C, ctx); gr_poly_init(D, ctx); flint_randinit(state); SETUP TIMEIT_START CASE_A TIMEIT_STOP_VALUES3(tcpu, twall, 10.0) (void) tcpu; tbase = twall; TIMEIT_START CASE_B TIMEIT_STOP_VALUES3(tcpu, twall, 10.0) (void) tcpu; tnew = twall; printf("len %ld : %f\n", len, tbase / tnew); flint_randclear(state); gr_poly_clear(A, ctx); gr_poly_clear(B, ctx); gr_poly_clear(C, ctx); gr_poly_clear(D, ctx); return tbase / tnew; } int ok(double x) { return x >= 0.9 && x <= 1.1; } slong get_tuning(gr_ctx_t ctx, slong from) { double speedup; slong cutoff = 0, len, consecutive = 0; do { for (len = from; len <= 32767; len = FLINT_MAX(len+1, len*1.05)) { speedup = get_profile(ctx, len); if (speedup > 1.0) { consecutive++; if (consecutive == 1) cutoff = len; if (consecutive == 30) break; } else { consecutive = 0; } } } while (0 /*!ok(get_profile(ctx, len))*/); return cutoff; } int main() { gr_ctx_t ctx; slong i, results[64], j; slong bits, cutoff /*, prev_cutoff = 0 */; printf("%s\n", INFO); STEP_BITS { INIT_CTX /* cutoff = get_tuning(ctx, FLINT_MAX(prev_cutoff * 0.75 - 5, 2)); */ cutoff = get_tuning(ctx, 2); results[j] = cutoff; /* prev_cutoff = cutoff; */ flint_printf("bits = %wd cutoff = %wd accuracy = %f\n", bits, cutoff, get_profile(ctx, cutoff)); flint_printf("tab[] = {"); for (i = 0; i <= j; i++) flint_printf("%wd, ", results[i]); flint_printf("};\n"); } return 0; } flint-3.1.3/src/gr_poly/write.c000066400000000000000000000075041461254215100164010ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "gr_poly.h" #ifdef __GNUC__ # define strcmp __builtin_strcmp #else # include #endif static int want_parens(const char * s) { if (s[0] == '(' || s[0] == '[' || s[0] == '{') return 0; if (s[0] == '-') s++; while (s[0] != '\0') { if (!isalnum(s[0]) && s[0] != '.') return 1; s++; } return 0; } int gr_poly_write(gr_stream_t out, const gr_poly_t poly, const char * x, gr_ctx_t ctx) { int status; slong i, n; slong sz; char * s; int printed_previously = 0; sz = ctx->sizeof_elem; n = gr_poly_length(poly, ctx); status = GR_SUCCESS; if (n == 0) { gr_stream_write(out, "0"); return status; } for (i = 0; i < n; i++) { if (gr_is_zero(GR_ENTRY(poly->coeffs, i, sz), ctx) == T_TRUE) continue; gr_get_str(&s, GR_ENTRY(poly->coeffs, i, sz), ctx); if (i >= 1 && !strcmp(s, "1")) { flint_free(s); if (printed_previously) gr_stream_write(out, " + "); gr_stream_write(out, x); if (i >= 2) { gr_stream_write(out, "^"); gr_stream_write_si(out, i); } } else if (i >= 1 && !strcmp(s, "-1")) { flint_free(s); if (printed_previously) gr_stream_write(out, " - "); else gr_stream_write(out, "-"); gr_stream_write(out, x); if (i >= 2) { gr_stream_write(out, "^"); gr_stream_write_si(out, i); } } else { if (want_parens(s)) { if (printed_previously) gr_stream_write(out, " + "); gr_stream_write(out, "("); gr_stream_write_free(out, s); gr_stream_write(out, ")"); } else { if (printed_previously && s[0] == '-') { gr_stream_write(out, " - "); gr_stream_write(out, s + 1); flint_free(s); } else { if (printed_previously) gr_stream_write(out, " + "); gr_stream_write_free(out, s); } } if (i == 1) { gr_stream_write(out, "*"); gr_stream_write(out, x); } else if (i >= 2) { gr_stream_write(out, "*"); gr_stream_write(out, x); gr_stream_write(out, "^"); gr_stream_write_si(out, i); } } printed_previously = 1; /* gr_stream_write(out, "("); status |= gr_write(out, GR_ENTRY(poly->coeffs, i, sz), ctx); gr_stream_write(out, ")"); if (i == 1) { gr_stream_write(out, "*x"); } else if (i >= 2) { gr_stream_write(out, "*x^"); gr_stream_write_si(out, i); } if (i < n - 1) gr_stream_write(out, " + "); */ } return status; } int gr_poly_print(const gr_poly_t poly, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); return gr_poly_write(out, poly, "x", ctx); } flint-3.1.3/src/gr_poly/xgcd_euclidean.c000066400000000000000000000210271461254215100202010ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" #include "gr_poly.h" #define GR_VEC_NORM(status, R, lenR, sz, ctx) \ do { \ (void) sz; \ (status) |= _gr_vec_normalise(&(lenR), (R), (lenR), (ctx)); \ } while (0) #define GR_VEC_SWAP(vec1, len1, vec2, len2) \ do { \ gr_ptr __t; \ slong __tn; \ __t = (vec1); \ (vec1) = (vec2); \ (vec2) = __t; \ __tn = (len1); \ (len1) = (len2); \ (len2) = __tn; \ } while (0); int _gr_poly_xgcd_euclidean(slong * lenG, gr_ptr G, gr_ptr S, gr_ptr T, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; status |= _gr_vec_zero(G, lenB, ctx); status |= _gr_vec_zero(S, lenB - 1, ctx); status |= _gr_vec_zero(T, lenA - 1, ctx); if (lenB == 1) { status |= gr_set(G, B, ctx); status |= gr_one(T, ctx); *lenG = 1; } else { gr_ptr Q, R; slong lenQ, lenR; GR_TMP_INIT_VEC(Q, 2 * lenA, ctx); R = GR_ENTRY(Q, lenA, sz); /* todo: preinv1 B; use also for second division later */ status |= _gr_poly_divrem(Q, R, A, lenA, B, lenB, ctx); lenR = lenB - 1; GR_VEC_NORM(status, R, lenR, sz, ctx); if (lenR == 0) { status |= _gr_vec_set(G, B, lenB, ctx); status |= gr_one(T, ctx); GR_TMP_CLEAR_VEC(Q, 2 * lenA, ctx); *lenG = lenB; return status; } else { gr_ptr D, U, V1, V3, W; slong lenD, lenU, lenV1, lenV3, lenW; GR_TMP_INIT_VEC(W, FLINT_MAX(5 * lenB, lenA + lenB), ctx); D = GR_ENTRY(W, lenB, sz); U = GR_ENTRY(D, lenB, sz); V1 = GR_ENTRY(U, lenB, sz); V3 = GR_ENTRY(V1, lenB, sz); lenU = 0; status |= _gr_vec_set(D, B, lenB, ctx); lenD = lenB; status |= gr_one(V1, ctx); lenV1 = 1; lenV3 = 0; GR_VEC_SWAP(V3, lenV3, R, lenR); do { /* todo: in-place remainder (see fmpz_mod_poly) */ status |= _gr_poly_divrem(Q, D, D, lenD, V3, lenV3, ctx); lenQ = lenD - lenV3 + 1; lenD = lenV3 - 1; GR_VEC_NORM(status, D, lenD, sz, ctx); if (status != GR_SUCCESS) break; if (lenV1 >= lenQ) status |= _gr_poly_mul(W, V1, lenV1, Q, lenQ, ctx); else status |= _gr_poly_mul(W, Q, lenQ, V1, lenV1, ctx); lenW = lenQ + lenV1 - 1; status |= _gr_poly_sub(U, U, lenU, W, lenW, ctx); lenU = FLINT_MAX(lenU, lenW); GR_VEC_NORM(status, U, lenU, sz, ctx); if (status != GR_SUCCESS) break; GR_VEC_SWAP(U, lenU, V1, lenV1); GR_VEC_SWAP(D, lenD, V3, lenV3); } while (lenV3 != 0); status |= _gr_vec_set(G, D, lenD, ctx); status |= _gr_vec_set(S, U, lenU, ctx); if (status == GR_SUCCESS) { lenQ = lenA + lenU - 1; status |= _gr_poly_mul(Q, A, lenA, S, lenU, ctx); status |= _gr_vec_neg(Q, Q, lenQ, ctx); status |= _gr_poly_add(Q, G, lenD, Q, lenQ, ctx); /* todo: preinv1 B */ status |= _gr_poly_divrem(T, W, Q, lenQ, B, lenB, ctx); } GR_TMP_CLEAR_VEC(W, FLINT_MAX(5 * lenB, lenA + lenB), ctx); GR_TMP_CLEAR_VEC(Q, 2 * lenA, ctx); *lenG = lenD; } } return status; } int gr_poly_xgcd_euclidean(gr_poly_t G, gr_poly_t S, gr_poly_t T, const gr_poly_t A, const gr_poly_t B, gr_ctx_t ctx) { if (A->length < B->length) { return gr_poly_xgcd_euclidean(G, T, S, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_ptr t; if (lenA == 0) /* lenA = lenB = 0 */ { status |= gr_poly_zero(G, ctx); status |= gr_poly_zero(S, ctx); status |= gr_poly_zero(T, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { GR_TMP_INIT(t, ctx); status |= gr_inv(t, GR_ENTRY(A->coeffs, lenA - 1, sz), ctx); status |= gr_poly_mul_scalar(G, A, t, ctx); status |= gr_poly_zero(T, ctx); status |= gr_poly_set_scalar(S, t, ctx); GR_TMP_CLEAR(t, ctx); } else if (gr_is_zero(GR_ENTRY(A->coeffs, A->length - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(B->coeffs, B->length - 1, sz), ctx) != T_FALSE) { status |= GR_UNABLE; } else if (lenB == 1) /* lenA >= lenB = 1 */ { GR_TMP_INIT(t, ctx); status |= gr_inv(t, B->coeffs, ctx); status |= gr_poly_set_scalar(T, t, ctx); status |= gr_poly_one(G, ctx); status |= gr_poly_zero(S, ctx); GR_TMP_CLEAR(t, ctx); } else /* lenA >= lenB >= 2 */ { gr_ptr g, *s, *t; slong lenG; if (G == A || G == B) { g = flint_malloc(sz * FLINT_MIN(lenA, lenB)); _gr_vec_init(g, FLINT_MIN(lenA, lenB), ctx); } else { gr_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = flint_malloc(sz * lenB); _gr_vec_init(s, lenB, ctx); } else { gr_poly_fit_length(S, lenB, ctx); s = S->coeffs; } if (T == A || T == B) { t = flint_malloc(sz * lenA); _gr_vec_init(t, lenA, ctx); } else { gr_poly_fit_length(T, lenA, ctx); t = T->coeffs; } status |= _gr_poly_xgcd_euclidean(&lenG, g, s, t, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { _gr_vec_clear(G->coeffs, G->alloc, ctx); flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = G->alloc; } if (S == A || S == B) { _gr_vec_clear(S->coeffs, S->alloc, ctx); flint_free(S->coeffs); S->coeffs = s; S->alloc = lenB; S->length = S->alloc; } if (T == A || T == B) { _gr_vec_clear(T->coeffs, T->alloc, ctx); flint_free(T->coeffs); T->coeffs = t; T->alloc = lenA; T->length = T->alloc; } _gr_poly_set_length(G, lenG, ctx); _gr_poly_set_length(S, FLINT_MAX(lenB - lenG, 1), ctx); _gr_poly_set_length(T, FLINT_MAX(lenA - lenG, 1), ctx); _gr_poly_normalise(S, ctx); _gr_poly_normalise(T, ctx); if (status == GR_SUCCESS && gr_is_one(GR_ENTRY(G->coeffs, G->length - 1, sz), ctx) != T_TRUE) { GR_TMP_INIT(t, ctx); status |= gr_inv(t, GR_ENTRY(G->coeffs, G->length - 1, sz), ctx); status |= gr_poly_mul_scalar(G, G, t, ctx); status |= gr_poly_mul_scalar(S, S, t, ctx); status |= gr_poly_mul_scalar(T, T, t, ctx); GR_TMP_CLEAR(t, ctx); } } return status; } } flint-3.1.3/src/gr_poly/xgcd_hgcd.c000066400000000000000000000323151461254215100171570ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr.h" #include "gr_vec.h" #include "gr_poly.h" #define GR_VEC_NORM(R, lenR) \ (status) |= _gr_vec_normalise(&(lenR), (R), (lenR), (ctx)) #define __set(B, lenB, A, lenA) \ do { \ status |= _gr_vec_set((B), (A), (lenA), ctx); \ (lenB) = (lenA); \ } while (0) #define __add(C, lenC, A, lenA, B, lenB) \ do { \ status |= _gr_poly_add((C), (A), (lenA), (B), (lenB), ctx); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ GR_VEC_NORM((C), (lenC)); \ } while (0) #define __sub(C, lenC, A, lenA, B, lenB) \ do { \ status |= _gr_poly_sub((C), (A), (lenA), (B), (lenB), ctx); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ GR_VEC_NORM((C), (lenC)); \ } while (0) #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ status |= _gr_poly_mul((C), (A), (lenA), (B), (lenB), ctx); \ else \ status |= _gr_poly_mul((C), (B), (lenB), (A), (lenA), ctx); \ (lenC) = (lenA) + (lenB) - 1; \ } \ else \ { \ (lenC) = 0; \ } \ } while (0) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ status |= _gr_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), ctx); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ GR_VEC_NORM((R), (lenR)); \ } \ else \ { \ status |= _gr_vec_set((R), (A), (lenA), ctx); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) /* todo: add _gr_poly_div */ #define __div(Q, lenQ, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ status |= _gr_poly_div_newton((Q), (A), (lenA), (B), (lenB), ctx); \ (lenQ) = (lenA) - (lenB) + 1; \ } \ else \ { \ (lenQ) = 0; \ } \ } while (0) int _gr_poly_xgcd_hgcd(slong * Glen, gr_ptr G, gr_ptr S, gr_ptr T, gr_srcptr A, slong lenA, gr_srcptr B, slong lenB, slong hgcd_cutoff, slong cutoff, gr_ctx_t ctx) { int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; slong lenG, lenS, lenT; if (lenB == 1) { status |= gr_set(G, B, ctx); status |= gr_one(T, ctx); lenG = 1; lenS = 0; lenT = 1; } else { slong lenq, lenr, len1 = lenA + lenB; gr_ptr q, r, invB; GR_TMP_INIT_VEC(q, len1, ctx); r = GR_ENTRY(q, lenA, sz); GR_TMP_INIT(invB, ctx); __divrem(q, lenq, r, lenr, A, lenA, B, lenB); if (lenr == 0) { __set(G, lenG, B, lenB); status |= gr_one(T, ctx); lenS = 0; lenT = 1; } else { gr_ptr h, j, v, w, R[4], X; slong lenh, lenj, lenv, lenw, lenR[4], len2; slong sgnR; lenh = lenj = lenB; lenv = lenw = lenA + lenB - 2; lenR[0] = lenR[1] = lenR[2] = lenR[3] = (lenB + 1) / 2; len2 = 2 * lenh + 2 * lenv + 4 * lenR[0]; GR_TMP_INIT_VEC(X, len2, ctx); h = X; j = GR_ENTRY(h, lenh, sz); v = GR_ENTRY(j, lenj, sz); w = GR_ENTRY(v, lenv, sz); R[0] = GR_ENTRY(w, lenw, sz); R[1] = GR_ENTRY(R[0], lenR[0], sz); R[2] = GR_ENTRY(R[1], lenR[1], sz); R[3] = GR_ENTRY(R[2], lenR[2], sz); status |= _gr_poly_hgcd(NULL, &sgnR, R, lenR, h, &lenh, j, &lenj, B, lenB, r, lenr, hgcd_cutoff, ctx); if (sgnR > 0) { status |= _gr_vec_neg(S, R[1], lenR[1], ctx); status |= _gr_vec_set(T, R[0], lenR[0], ctx); } else { status |= _gr_vec_set(S, R[1], lenR[1], ctx); status |= _gr_vec_neg(T, R[0], lenR[0], ctx); } lenS = lenR[1]; lenT = lenR[0]; while (lenj != 0 && status == GR_SUCCESS) { __divrem(q, lenq, r, lenr, h, lenh, j, lenj); __mul(v, lenv, q, lenq, T, lenT); { slong l; _gr_vec_swap(S, T, FLINT_MAX(lenS, lenT), ctx); l = lenS; lenS = lenT; lenT = l; } if (lenr != 0) /* prevent overflow of T on last iteration */ __sub(T, lenT, T, lenT, v, lenv); else /* lenr == 0 */ { __set(G, lenG, j, lenj); goto cofactor; } if (lenj < cutoff) { gr_ptr u0 = R[0], u1 = R[1]; slong lenu0 = lenr - 1, lenu1 = lenj - 1; status |= _gr_poly_xgcd_euclidean(&lenG, G, u0, u1, j, lenj, r, lenr, ctx); GR_VEC_NORM(u0, lenu0); GR_VEC_NORM(u1, lenu1); __mul(v, lenv, S, lenS, u0, lenu0); __mul(w, lenw, T, lenT, u1, lenu1); __add(S, lenS, v, lenv, w, lenw); goto cofactor; } status |= _gr_poly_hgcd(NULL, &sgnR, R, lenR, h, &lenh, j, &lenj, j,lenj, r, lenr, hgcd_cutoff, ctx); __mul(v, lenv, R[1], lenR[1], T, lenT); __mul(w, lenw, R[2], lenR[2], S, lenS); __mul(q, lenq, S, lenS, R[3], lenR[3]); if (sgnR > 0) __sub(S, lenS, q, lenq, v, lenv); else __sub(S, lenS, v, lenv, q, lenq); __mul(q, lenq, T, lenT, R[0], lenR[0]); if (sgnR > 0) __sub(T, lenT, q, lenq, w, lenw); else __sub(T, lenT, w, lenw, q, lenq); } __set(G, lenG, h, lenh); cofactor: __mul(v, lenv, S, lenS, A, lenA); __sub(w, lenw, G, lenG, v, lenv); __div(T, lenT, w, lenw, B, lenB); GR_TMP_CLEAR_VEC(X, len2, ctx); } GR_TMP_CLEAR_VEC(q, len1, ctx); GR_TMP_CLEAR(invB, ctx); } status |= _gr_vec_zero(GR_ENTRY(S, lenS, sz), lenB - 1 - lenS, ctx); status |= _gr_vec_zero(GR_ENTRY(T, lenT, sz), lenA - 1 - lenT, ctx); *Glen = lenG; return status; } int gr_poly_xgcd_hgcd(gr_poly_t G, gr_poly_t S, gr_poly_t T, const gr_poly_t A, const gr_poly_t B, slong hgcd_cutoff, slong cutoff, gr_ctx_t ctx) { if (A->length < B->length) { return gr_poly_xgcd_hgcd(G, T, S, B, A, hgcd_cutoff, cutoff, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; int status = GR_SUCCESS; slong sz = ctx->sizeof_elem; gr_ptr t; if (lenA == 0) /* lenA = lenB = 0 */ { status |= gr_poly_zero(G, ctx); status |= gr_poly_zero(S, ctx); status |= gr_poly_zero(T, ctx); } else if (lenB == 0) /* lenA > lenB = 0 */ { GR_TMP_INIT(t, ctx); status |= gr_inv(t, GR_ENTRY(A->coeffs, lenA - 1, sz), ctx); status |= gr_poly_mul_scalar(G, A, t, ctx); status |= gr_poly_zero(T, ctx); status |= gr_poly_set_scalar(S, t, ctx); GR_TMP_CLEAR(t, ctx); } else if (gr_is_zero(GR_ENTRY(A->coeffs, A->length - 1, sz), ctx) != T_FALSE || gr_is_zero(GR_ENTRY(B->coeffs, B->length - 1, sz), ctx) != T_FALSE) { status |= GR_UNABLE; } else if (lenB == 1) /* lenA >= lenB = 1 */ { GR_TMP_INIT(t, ctx); status |= gr_inv(t, B->coeffs, ctx); status |= gr_poly_set_scalar(T, t, ctx); status |= gr_poly_one(G, ctx); status |= gr_poly_zero(S, ctx); GR_TMP_CLEAR(t, ctx); } else /* lenA >= lenB >= 2 */ { gr_ptr g, *s, *t; slong lenG; if (G == A || G == B) { g = flint_malloc(sz * FLINT_MIN(lenA, lenB)); _gr_vec_init(g, FLINT_MIN(lenA, lenB), ctx); } else { gr_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } if (S == A || S == B) { s = flint_malloc(sz * lenB); _gr_vec_init(s, lenB, ctx); } else { gr_poly_fit_length(S, lenB, ctx); s = S->coeffs; } if (T == A || T == B) { t = flint_malloc(sz * lenA); _gr_vec_init(t, lenA, ctx); } else { gr_poly_fit_length(T, lenA, ctx); t = T->coeffs; } status |= _gr_poly_xgcd_hgcd(&lenG, g, s, t, A->coeffs, lenA, B->coeffs, lenB, hgcd_cutoff, cutoff, ctx); if (G == A || G == B) { _gr_vec_clear(G->coeffs, G->alloc, ctx); flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); G->length = G->alloc; } if (S == A || S == B) { _gr_vec_clear(S->coeffs, S->alloc, ctx); flint_free(S->coeffs); S->coeffs = s; S->alloc = lenB; S->length = S->alloc; } if (T == A || T == B) { _gr_vec_clear(T->coeffs, T->alloc, ctx); flint_free(T->coeffs); T->coeffs = t; T->alloc = lenA; T->length = T->alloc; } _gr_poly_set_length(G, lenG, ctx); _gr_poly_set_length(S, FLINT_MAX(lenB - lenG, 1), ctx); _gr_poly_set_length(T, FLINT_MAX(lenA - lenG, 1), ctx); _gr_poly_normalise(S, ctx); _gr_poly_normalise(T, ctx); if (status == GR_SUCCESS && gr_is_one(GR_ENTRY(G->coeffs, G->length - 1, sz), ctx) != T_TRUE) { GR_TMP_INIT(t, ctx); status |= gr_inv(t, GR_ENTRY(G->coeffs, G->length - 1, sz), ctx); status |= gr_poly_mul_scalar(G, G, t, ctx); status |= gr_poly_mul_scalar(S, S, t, ctx); status |= gr_poly_mul_scalar(T, T, t, ctx); GR_TMP_CLEAR(t, ctx); } } return status; } } flint-3.1.3/src/gr_special.h000066400000000000000000001124451461254215100157120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GR_SPECIAL_H #define GR_SPECIAL_H #ifdef GR_SPECIAL_INLINES_C #define GR_SPECIAL_INLINE #else #define GR_SPECIAL_INLINE static inline #endif #include "gr.h" #ifdef __cplusplus extern "C" { #endif #define GR_SPECIAL_DEF GR_SPECIAL_INLINE WARN_UNUSED_RESULT GR_SPECIAL_DEF int gr_pi(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, PI)(res, ctx); } GR_SPECIAL_DEF int gr_euler(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, EULER)(res, ctx); } GR_SPECIAL_DEF int gr_catalan(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, CATALAN)(res, ctx); } GR_SPECIAL_DEF int gr_khinchin(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, KHINCHIN)(res, ctx); } GR_SPECIAL_DEF int gr_glaisher(gr_ptr res, gr_ctx_t ctx) { return GR_CONSTANT_OP(ctx, GLAISHER)(res, ctx); } GR_SPECIAL_DEF int gr_exp(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, EXP)(res, x, ctx); } GR_SPECIAL_DEF int gr_expm1(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, EXPM1)(res, x, ctx); } GR_SPECIAL_DEF int gr_exp2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, EXP2)(res, x, ctx); } GR_SPECIAL_DEF int gr_exp10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, EXP10)(res, x, ctx); } GR_SPECIAL_DEF int gr_exp_pi_i(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, EXP_PI_I)(res, x, ctx); } GR_SPECIAL_DEF int gr_log(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LOG)(res, x, ctx); } GR_SPECIAL_DEF int gr_log1p(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LOG1P)(res, x, ctx); } GR_SPECIAL_DEF int gr_log_pi_i(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LOG_PI_I)(res, x, ctx); } GR_SPECIAL_DEF int gr_log2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LOG2)(res, x, ctx); } GR_SPECIAL_DEF int gr_log10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LOG10)(res, x, ctx); } GR_SPECIAL_DEF int gr_sin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SIN)(res, x, ctx); } GR_SPECIAL_DEF int gr_cos(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COS)(res, x, ctx); } GR_SPECIAL_DEF int gr_sin_cos(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx) { return GR_BINARY_UNARY_OP(ctx, SIN_COS)(res1, res2, x, ctx); } GR_SPECIAL_DEF int gr_tan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, TAN)(res, x, ctx); } GR_SPECIAL_DEF int gr_cot(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COT)(res, x, ctx); } GR_SPECIAL_DEF int gr_sec(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SEC)(res, x, ctx); } GR_SPECIAL_DEF int gr_csc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, CSC)(res, x, ctx); } GR_SPECIAL_DEF int gr_sin_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SIN_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_cos_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COS_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_sin_cos_pi(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx) { return GR_BINARY_UNARY_OP(ctx, SIN_COS_PI)(res1, res2, x, ctx); } GR_SPECIAL_DEF int gr_tan_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, TAN_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_cot_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COT_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_sec_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SEC_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_csc_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, CSC_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_sinc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SINC)(res, x, ctx); } GR_SPECIAL_DEF int gr_sinc_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SINC_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_sinh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SINH)(res, x, ctx); } GR_SPECIAL_DEF int gr_cosh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COSH)(res, x, ctx); } GR_SPECIAL_DEF int gr_sinh_cosh(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx) { return GR_BINARY_UNARY_OP(ctx, SINH_COSH)(res1, res2, x, ctx); } GR_SPECIAL_DEF int gr_tanh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, TANH)(res, x, ctx); } GR_SPECIAL_DEF int gr_coth(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COTH)(res, x, ctx); } GR_SPECIAL_DEF int gr_sech(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SECH)(res, x, ctx); } GR_SPECIAL_DEF int gr_csch(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, CSCH)(res, x, ctx); } GR_SPECIAL_DEF int gr_asin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ASIN)(res, x, ctx); } GR_SPECIAL_DEF int gr_acos(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACOS)(res, x, ctx); } GR_SPECIAL_DEF int gr_atan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ATAN)(res, x, ctx); } GR_SPECIAL_DEF int gr_atan2(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, ATAN2)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_acot(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACOT)(res, x, ctx); } GR_SPECIAL_DEF int gr_asec(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ASEC)(res, x, ctx); } GR_SPECIAL_DEF int gr_acsc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACSC)(res, x, ctx); } GR_SPECIAL_DEF int gr_asin_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ASIN_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_acos_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACOS_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_atan_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ATAN_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_acot_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACOT_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_asec_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ASEC_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_acsc_pi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACSC_PI)(res, x, ctx); } GR_SPECIAL_DEF int gr_asinh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ASINH)(res, x, ctx); } GR_SPECIAL_DEF int gr_acosh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACOSH)(res, x, ctx); } GR_SPECIAL_DEF int gr_atanh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ATANH)(res, x, ctx); } GR_SPECIAL_DEF int gr_acoth(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACOTH)(res, x, ctx); } GR_SPECIAL_DEF int gr_asech(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ASECH)(res, x, ctx); } GR_SPECIAL_DEF int gr_acsch(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ACSCH)(res, x, ctx); } GR_SPECIAL_DEF int gr_lambertw(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LAMBERTW)(res, x, ctx); } GR_SPECIAL_DEF int gr_lambertw_fmpz(gr_ptr res, gr_srcptr x, const fmpz_t k, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ(ctx, LAMBERTW_FMPZ)(res, x, k, ctx); } GR_SPECIAL_DEF int gr_fac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, FAC)(res, x, ctx); } GR_SPECIAL_DEF int gr_fac_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, FAC_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_fac_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, FAC_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_fac_vec(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, FAC_VEC)(res, len, ctx); } GR_SPECIAL_DEF int gr_rfac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, RFAC)(res, x, ctx); } GR_SPECIAL_DEF int gr_rfac_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, RFAC_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_rfac_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, RFAC_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_rfac_vec(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, RFAC_VEC)(res, len, ctx); } GR_SPECIAL_DEF int gr_bin(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BIN)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bin_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, BIN_UI)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bin_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI_UI(ctx, BIN_UIUI)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bin_vec(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, BIN_VEC)(res, x, len, ctx); } GR_SPECIAL_DEF int gr_bin_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) { return GR_BINARY_OP_UI_SI(ctx, BIN_UI_VEC)(res, x, len, ctx); } GR_SPECIAL_DEF int gr_rising(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, RISING)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_rising_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, RISING_UI)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_falling(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, FALLING)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_falling_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI(ctx, FALLING_UI)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_gamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, GAMMA)(res, x, ctx); } GR_SPECIAL_DEF int gr_gamma_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, GAMMA_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_gamma_fmpq(gr_ptr res, const fmpq_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPQ(ctx, GAMMA_FMPQ)(res, x, ctx); } GR_SPECIAL_DEF int gr_rgamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, RGAMMA)(res, x, ctx); } GR_SPECIAL_DEF int gr_lgamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LGAMMA)(res, x, ctx); } GR_SPECIAL_DEF int gr_digamma(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DIGAMMA)(res, x, ctx); } GR_SPECIAL_DEF int gr_beta(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BETA)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_barnes_g(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, BARNES_G)(res, x, ctx); } GR_SPECIAL_DEF int gr_log_barnes_g(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, LOG_BARNES_G)(res, x, ctx); } GR_SPECIAL_DEF int gr_doublefac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DOUBLEFAC)(res, x, ctx); } GR_SPECIAL_DEF int gr_doublefac_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, DOUBLEFAC_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_harmonic(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, HARMONIC)(res, x, ctx); } GR_SPECIAL_DEF int gr_harmonic_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, HARMONIC_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_bernoulli_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, BERNOULLI_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_bernoulli_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, BERNOULLI_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_bernoulli_vec(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, BERNOULLI_VEC)(res, len, ctx); } GR_SPECIAL_DEF int gr_fib_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, FIB_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_fib_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, FIB_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_fib_vec(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, FIB_VEC)(res, len, ctx); } GR_SPECIAL_DEF int gr_eulernum_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, EULERNUM_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_eulernum_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, EULERNUM_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_eulernum_vec(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, EULERNUM_VEC)(res, len, ctx); } GR_SPECIAL_DEF int gr_bernpoly_ui(gr_ptr res, ulong n, gr_srcptr x, gr_ctx_t ctx) { return GR_UI_BINARY_OP(ctx, BERNPOLY_UI)(res, n, x, ctx); } GR_SPECIAL_DEF int gr_eulerpoly_ui(gr_ptr res, ulong n, gr_srcptr x, gr_ctx_t ctx) { return GR_UI_BINARY_OP(ctx, EULERPOLY_UI)(res, n, x, ctx); } GR_SPECIAL_DEF int gr_bellnum_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, BELLNUM_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_bellnum_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, BELLNUM_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_bellnum_vec(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, BELLNUM_VEC)(res, len, ctx); } GR_SPECIAL_DEF int gr_stirling_s1u_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI_UI(ctx, STIRLING_S1U_UIUI)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_stirling_s1_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI_UI(ctx, STIRLING_S1_UIUI)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_stirling_s2_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx) { return GR_BINARY_OP_UI_UI(ctx, STIRLING_S2_UIUI)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_stirling_s1u_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) { return GR_BINARY_OP_UI_SI(ctx, STIRLING_S1U_UI_VEC)(res, x, len, ctx); } GR_SPECIAL_DEF int gr_stirling_s1_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) { return GR_BINARY_OP_UI_SI(ctx, STIRLING_S1_UI_VEC)(res, x, len, ctx); } GR_SPECIAL_DEF int gr_stirling_s2_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx) { return GR_BINARY_OP_UI_SI(ctx, STIRLING_S2_UI_VEC)(res, x, len, ctx); } GR_SPECIAL_DEF int gr_partitions_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, PARTITIONS_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_partitions_fmpz(gr_ptr res, const fmpz_t x, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, PARTITIONS_FMPZ)(res, x, ctx); } GR_SPECIAL_DEF int gr_partitions_vec(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, PARTITIONS_VEC)(res, len, ctx); } GR_SPECIAL_DEF int gr_erf(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ERF)(res, x, ctx); } GR_SPECIAL_DEF int gr_erfc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ERFC)(res, x, ctx); } GR_SPECIAL_DEF int gr_erfcx(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ERFCX)(res, x, ctx); } GR_SPECIAL_DEF int gr_erfi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ERFI)(res, x, ctx); } GR_SPECIAL_DEF int gr_erfinv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ERFINV)(res, x, ctx); } GR_SPECIAL_DEF int gr_erfcinv(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ERFCINV)(res, x, ctx); } GR_SPECIAL_DEF int gr_fresnel_s(gr_ptr res, gr_srcptr x, int normalized, gr_ctx_t ctx) { return GR_UNARY_OP_WITH_FLAG(ctx, FRESNEL_S)(res, x, normalized, ctx); } GR_SPECIAL_DEF int gr_fresnel_c(gr_ptr res, gr_srcptr x, int normalized, gr_ctx_t ctx) { return GR_UNARY_OP_WITH_FLAG(ctx, FRESNEL_C)(res, x, normalized, ctx); } GR_SPECIAL_DEF int gr_fresnel(gr_ptr res1, gr_ptr res2, gr_srcptr x, int normalized, gr_ctx_t ctx) { return GR_BINARY_UNARY_OP_WITH_FLAG(ctx, FRESNEL)(res1, res2, x, normalized, ctx); } GR_SPECIAL_DEF int gr_gamma_upper(gr_ptr res, gr_srcptr x, gr_srcptr y, int regularized, gr_ctx_t ctx) { return GR_BINARY_OP_WITH_FLAG(ctx, GAMMA_UPPER)(res, x, y, regularized, ctx); } GR_SPECIAL_DEF int gr_gamma_lower(gr_ptr res, gr_srcptr x, gr_srcptr y, int regularized, gr_ctx_t ctx) { return GR_BINARY_OP_WITH_FLAG(ctx, GAMMA_LOWER)(res, x, y, regularized, ctx); } GR_SPECIAL_DEF int gr_beta_lower(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int regularized, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, BETA_LOWER)(res, x, y, z, regularized, ctx); } GR_SPECIAL_DEF int gr_exp_integral(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, EXP_INTEGRAL)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_exp_integral_ei(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, EXP_INTEGRAL_EI)(res, x, ctx); } GR_SPECIAL_DEF int gr_sin_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SIN_INTEGRAL)(res, x, ctx); } GR_SPECIAL_DEF int gr_cos_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COS_INTEGRAL)(res, x, ctx); } GR_SPECIAL_DEF int gr_sinh_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, SINH_INTEGRAL)(res, x, ctx); } GR_SPECIAL_DEF int gr_cosh_integral(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, COSH_INTEGRAL)(res, x, ctx); } GR_SPECIAL_DEF int gr_log_integral(gr_ptr res, gr_srcptr x, int offset, gr_ctx_t ctx) { return GR_UNARY_OP_WITH_FLAG(ctx, LOG_INTEGRAL)(res, x, offset, ctx); } GR_SPECIAL_DEF int gr_dilog(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DILOG)(res, x, ctx); } GR_SPECIAL_DEF int gr_bessel_j(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BESSEL_J)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bessel_y(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BESSEL_Y)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bessel_i(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BESSEL_I)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bessel_k(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BESSEL_K)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bessel_j_y(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_BINARY_OP(ctx, BESSEL_J_Y)(res1, res2, x, y, ctx); } GR_SPECIAL_DEF int gr_bessel_i_scaled(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BESSEL_I_SCALED)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_bessel_k_scaled(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, BESSEL_K_SCALED)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_airy(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr x, gr_ctx_t ctx) { return GR_QUATERNARY_UNARY_OP(ctx, AIRY)(res1, res2, res3, res4, x, ctx); } GR_SPECIAL_DEF int gr_airy_ai(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_AI)(res, x, ctx); } GR_SPECIAL_DEF int gr_airy_bi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_BI)(res, x, ctx); } GR_SPECIAL_DEF int gr_airy_ai_prime(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_AI_PRIME)(res, x, ctx); } GR_SPECIAL_DEF int gr_airy_bi_prime(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_BI_PRIME)(res, x, ctx); } GR_SPECIAL_DEF int gr_airy_ai_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_AI_ZERO)(res, n, ctx); } GR_SPECIAL_DEF int gr_airy_bi_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_BI_ZERO)(res, n, ctx); } GR_SPECIAL_DEF int gr_airy_ai_prime_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_AI_PRIME_ZERO)(res, n, ctx); } GR_SPECIAL_DEF int gr_airy_bi_prime_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AIRY_BI_PRIME_ZERO)(res, n, ctx); } GR_SPECIAL_DEF int gr_coulomb(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) { return GR_QUATERNARY_TERNARY_OP(ctx, COULOMB)(res1, res2, res3, res4, x, y, z, ctx); } GR_SPECIAL_DEF int gr_coulomb_f(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) { return GR_TERNARY_OP(ctx, COULOMB_F)(res, x, y, z, ctx); } GR_SPECIAL_DEF int gr_coulomb_g(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) { return GR_TERNARY_OP(ctx, COULOMB_G)(res, x, y, z, ctx); } GR_SPECIAL_DEF int gr_coulomb_hpos(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) { return GR_TERNARY_OP(ctx, COULOMB_HPOS)(res, x, y, z, ctx); } GR_SPECIAL_DEF int gr_coulomb_hneg(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) { return GR_TERNARY_OP(ctx, COULOMB_HNEG)(res, x, y, z, ctx); } GR_SPECIAL_DEF int gr_chebyshev_t_fmpz(gr_ptr res, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) { return GR_FMPZ_BINARY_OP(ctx, CHEBYSHEV_T_FMPZ)(res, n, x, ctx); } GR_SPECIAL_DEF int gr_chebyshev_t(gr_ptr res, gr_srcptr n, gr_srcptr x, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, CHEBYSHEV_T)(res, n, x, ctx); } GR_SPECIAL_DEF int gr_chebyshev_u_fmpz(gr_ptr res, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) { return GR_FMPZ_BINARY_OP(ctx, CHEBYSHEV_U_FMPZ)(res, n, x, ctx); } GR_SPECIAL_DEF int gr_chebyshev_u(gr_ptr res, gr_srcptr n, gr_srcptr x, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, CHEBYSHEV_U)(res, n, x, ctx); } GR_SPECIAL_DEF int gr_jacobi_p(gr_ptr res, gr_srcptr n, gr_srcptr a, gr_srcptr b, gr_srcptr z, gr_ctx_t ctx) { return GR_QUATERNARY_OP(ctx, JACOBI_P)(res, n, a, b, z, ctx); } GR_SPECIAL_DEF int gr_gegenbauer_c(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, gr_ctx_t ctx) { return GR_TERNARY_OP(ctx, GEGENBAUER_C)(res, n, m, z, ctx); } GR_SPECIAL_DEF int gr_laguerre_l(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, gr_ctx_t ctx) { return GR_TERNARY_OP(ctx, LAGUERRE_L)(res, n, m, z, ctx); } GR_SPECIAL_DEF int gr_hermite_h(gr_ptr res, gr_srcptr n, gr_srcptr z, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, HERMITE_H)(res, n, z, ctx); } GR_SPECIAL_DEF int gr_legendre_p(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, int type, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, LEGENDRE_P)(res, n, m, z, type, ctx); } GR_SPECIAL_DEF int gr_legendre_q(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_srcptr z, int type, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, LEGENDRE_Q)(res, n, m, z, type, ctx); } GR_SPECIAL_DEF int gr_spherical_y_si(gr_ptr res, slong n, slong m, gr_srcptr theta, gr_srcptr phi, gr_ctx_t ctx) { return GR_SI_SI_QUATERNARY_OP(ctx, SPHERICAL_Y_SI)(res, n, m, theta, phi, ctx); } GR_SPECIAL_DEF int gr_legendre_p_root_ui(gr_ptr root, gr_ptr weight, ulong n, ulong k, gr_ctx_t ctx) { return GR_BINARY_BINARY_OP_UI_UI(ctx, LEGENDRE_P_ROOT_UI)(root, weight, n, k, ctx); } typedef int ((*gr_method_pfq_op_op)(gr_ptr, const gr_vec_t, const gr_vec_t, gr_srcptr, int, gr_ctx_ptr)); #define GR_PFQ_OP(ctx, NAME) (((gr_method_pfq_op_op *) ctx->methods)[GR_METHOD_ ## NAME]) GR_SPECIAL_DEF int gr_hypgeom_0f1(gr_ptr res, gr_srcptr a, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_BINARY_OP_WITH_FLAG(ctx, HYPGEOM_0F1)(res, a, z, flags, ctx); } GR_SPECIAL_DEF int gr_hypgeom_1f1(gr_ptr res, gr_srcptr a, gr_srcptr b, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, HYPGEOM_1F1)(res, a, b, z, flags, ctx); } GR_SPECIAL_DEF int gr_hypgeom_u(gr_ptr res, gr_srcptr a, gr_srcptr b, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, HYPGEOM_U)(res, a, b, z, flags, ctx); } GR_SPECIAL_DEF int gr_hypgeom_2f1(gr_ptr res, gr_srcptr a, gr_srcptr b, gr_srcptr c, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_QUATERNARY_OP_WITH_FLAG(ctx, HYPGEOM_2F1)(res, a, b, c, z, flags, ctx); } GR_SPECIAL_DEF int gr_hypgeom_pfq(gr_ptr res, const gr_vec_t a, const gr_vec_t b, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_PFQ_OP(ctx, HYPGEOM_PFQ)(res, a, b, z, flags, ctx); } GR_SPECIAL_DEF int gr_zeta(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ZETA)(res, x, ctx); } GR_SPECIAL_DEF int gr_zeta_ui(gr_ptr res, ulong x, gr_ctx_t ctx) { return GR_UNARY_OP_UI(ctx, ZETA_UI)(res, x, ctx); } GR_SPECIAL_DEF int gr_hurwitz_zeta(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, HURWITZ_ZETA)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_polylog(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, POLYLOG)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_polygamma(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, POLYGAMMA)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_lerch_phi(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_ctx_t ctx) { return GR_TERNARY_OP(ctx, LERCH_PHI)(res, x, y, z, ctx); } GR_SPECIAL_DEF int gr_stieltjes(gr_ptr res, const fmpz_t x, gr_srcptr y, gr_ctx_t ctx) { return GR_FMPZ_BINARY_OP(ctx, STIELTJES)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_dirichlet_eta(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DIRICHLET_ETA)(res, x, ctx); } GR_SPECIAL_DEF int gr_dirichlet_beta(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DIRICHLET_BETA)(res, x, ctx); } GR_SPECIAL_DEF int gr_riemann_xi(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, RIEMANN_XI)(res, x, ctx); } GR_SPECIAL_DEF int gr_zeta_zero(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { return GR_UNARY_OP_FMPZ(ctx, ZETA_ZERO)(res, n, ctx); } GR_SPECIAL_DEF int gr_zeta_zero_vec(gr_ptr res, const fmpz_t n, slong len, gr_ctx_t ctx) { return GR_BINARY_OP_FMPZ_SI(ctx, ZETA_ZERO_VEC)(res, n, len, ctx); } GR_SPECIAL_DEF int gr_zeta_nzeros(gr_ptr res, gr_srcptr t, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ZETA_NZEROS)(res, t, ctx); } /* todo: backlund_s, etc */ #ifdef DIRICHLET_H WARN_UNUSED_RESULT int gr_dirichlet_chi_fmpz(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_dirichlet_chi_vec(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, gr_ctx_t ctx); /* todo: wrap, test */ WARN_UNUSED_RESULT int gr_dirichlet_l(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr s, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_dirichlet_l_all(gr_vec_t res, const dirichlet_group_t G, gr_srcptr s, gr_ctx_t ctx); /* todo: wrap, test */ WARN_UNUSED_RESULT int gr_dirichlet_hardy_theta(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr t, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_dirichlet_hardy_z(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr t, gr_ctx_t ctx); #endif GR_SPECIAL_DEF int gr_jacobi_theta(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_QUATERNARY_BINARY_OP(ctx, JACOBI_THETA)(res1, res2, res3, res4, z, tau, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_1(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_1)(res, z, tau, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_2(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_2)(res, z, tau, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_3(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_3)(res, z, tau, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_4(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_4)(res, z, tau, ctx); } /* GR_SPECIAL_DEF int gr_jacobi_theta_q(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_ptr res4, gr_srcptr w, gr_srcptr q, gr_ctx_t ctx) { return GR_QUATERNARY_BINARY_OP(ctx, JACOBI_THETA_Q)(res1, res2, res3, res4, w, q, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_q_1(gr_ptr res, gr_srcptr w, gr_srcptr q, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_Q_1)(res, w, q, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_q_2(gr_ptr res, gr_srcptr w, gr_srcptr q, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_Q_2)(res, w, q, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_q_3(gr_ptr res, gr_srcptr w, gr_srcptr q, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_Q_3)(res, w, q, ctx); } GR_SPECIAL_DEF int gr_jacobi_theta_q_4(gr_ptr res, gr_srcptr w, gr_srcptr q, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, JACOBI_THETA_Q_4)(res, w, q, ctx); } */ GR_SPECIAL_DEF int gr_modular_j(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, MODULAR_J)(res, tau, ctx); } GR_SPECIAL_DEF int gr_modular_lambda(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, MODULAR_LAMBDA)(res, tau, ctx); } GR_SPECIAL_DEF int gr_modular_delta(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, MODULAR_DELTA)(res, tau, ctx); } GR_SPECIAL_DEF int gr_hilbert_class_poly(gr_ptr res, slong D, gr_srcptr x, gr_ctx_t ctx) { return GR_SI_BINARY_OP(ctx, HILBERT_CLASS_POLY)(res, D, x, ctx); } GR_SPECIAL_DEF int gr_dedekind_eta(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DEDEKIND_ETA)(res, tau, ctx); } GR_SPECIAL_DEF int gr_dedekind_eta_q(gr_ptr res, gr_srcptr tau, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, DEDEKIND_ETA_Q)(res, tau, ctx); } GR_SPECIAL_DEF int gr_eisenstein_e(gr_ptr res, ulong n, gr_srcptr tau, gr_ctx_t ctx) { return GR_UI_BINARY_OP(ctx, EISENSTEIN_E)(res, n, tau, ctx); } GR_SPECIAL_DEF int gr_eisenstein_g(gr_ptr res, ulong n, gr_srcptr tau, gr_ctx_t ctx) { return GR_UI_BINARY_OP(ctx, EISENSTEIN_G)(res, n, tau, ctx); } GR_SPECIAL_DEF int gr_eisenstein_g_vec(gr_ptr res, gr_srcptr tau, slong len, gr_ctx_t ctx) { return GR_BINARY_OP_SI(ctx, EISENSTEIN_G_VEC)(res, tau, len, ctx); } GR_SPECIAL_DEF int gr_agm1(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, AGM1)(res, x, ctx); } GR_SPECIAL_DEF int gr_agm(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, AGM)(res, x, y, ctx); } GR_SPECIAL_DEF int gr_elliptic_k(gr_ptr res, gr_srcptr m, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ELLIPTIC_K)(res, m, ctx); } GR_SPECIAL_DEF int gr_elliptic_e(gr_ptr res, gr_srcptr m, gr_ctx_t ctx) { return GR_UNARY_OP(ctx, ELLIPTIC_E)(res, m, ctx); } GR_SPECIAL_DEF int gr_elliptic_pi(gr_ptr res, gr_srcptr n, gr_srcptr m, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, ELLIPTIC_PI)(res, n, m, ctx); } GR_SPECIAL_DEF int gr_elliptic_f(gr_ptr res, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) { return GR_BINARY_OP_WITH_FLAG(ctx, ELLIPTIC_F)(res, phi, m, pi, ctx); } GR_SPECIAL_DEF int gr_elliptic_e_inc(gr_ptr res, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) { return GR_BINARY_OP_WITH_FLAG(ctx, ELLIPTIC_E_INC)(res, phi, m, pi, ctx); } GR_SPECIAL_DEF int gr_elliptic_pi_inc(gr_ptr res, gr_srcptr n, gr_srcptr phi, gr_srcptr m, int pi, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, ELLIPTIC_PI_INC)(res, n, phi, m, pi, ctx); } GR_SPECIAL_DEF int gr_carlson_rc(gr_ptr res, gr_srcptr x, gr_srcptr y, int flags, gr_ctx_t ctx) { return GR_BINARY_OP_WITH_FLAG(ctx, CARLSON_RC)(res, x, y, flags, ctx); } GR_SPECIAL_DEF int gr_carlson_rf(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, CARLSON_RF)(res, x, y, z, flags, ctx); } GR_SPECIAL_DEF int gr_carlson_rd(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, CARLSON_RD)(res, x, y, z, flags, ctx); } GR_SPECIAL_DEF int gr_carlson_rg(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, int flags, gr_ctx_t ctx) { return GR_TERNARY_OP_WITH_FLAG(ctx, CARLSON_RG)(res, x, y, z, flags, ctx); } GR_SPECIAL_DEF int gr_carlson_rj(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_srcptr z, gr_srcptr w, int flags, gr_ctx_t ctx) { return GR_QUATERNARY_OP_WITH_FLAG(ctx, CARLSON_RJ)(res, x, y, z, w, flags, ctx); } GR_SPECIAL_DEF int gr_elliptic_invariants(gr_ptr res1, gr_ptr res2, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_UNARY_OP(ctx, ELLIPTIC_INVARIANTS)(res1, res2, tau, ctx); } GR_SPECIAL_DEF int gr_elliptic_roots(gr_ptr res1, gr_ptr res2, gr_ptr res3, gr_srcptr tau, gr_ctx_t ctx) { return GR_TERNARY_UNARY_OP(ctx, ELLIPTIC_ROOTS)(res1, res2, res3, tau, ctx); } GR_SPECIAL_DEF int gr_weierstrass_p(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, WEIERSTRASS_P)(res, z, tau, ctx); } GR_SPECIAL_DEF int gr_weierstrass_p_prime(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, WEIERSTRASS_P_PRIME)(res, z, tau, ctx); } GR_SPECIAL_DEF int gr_weierstrass_p_inv(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, WEIERSTRASS_P_INV)(res, z, tau, ctx); } GR_SPECIAL_DEF int gr_weierstrass_zeta(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, WEIERSTRASS_ZETA)(res, z, tau, ctx); } GR_SPECIAL_DEF int gr_weierstrass_sigma(gr_ptr res, gr_srcptr z, gr_srcptr tau, gr_ctx_t ctx) { return GR_BINARY_OP(ctx, WEIERSTRASS_SIGMA)(res, z, tau, ctx); } /* todo bernoulli eulerpoly zeta_ui_vec cyclotomic dedekind_sum moebius, ... prime_pi, primorial etc */ /* generic implementations */ WARN_UNUSED_RESULT int gr_generic_exp(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_expm1(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_exp2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_exp10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_log(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_log1p(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_log2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_log10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_cos(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_sin_cos(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_tan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_asin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_asinh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_atan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_atanh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_acot(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_asec(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_acsc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_acoth(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_asech(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_acsch(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fac_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fac_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fac_vec(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_rfac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_rfac_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_rfac_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_rfac_vec(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_rising(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_rising_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_falling(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_falling_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bin(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bin_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bin_uiui(gr_ptr res, ulong x, ulong y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bin_vec(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bin_ui_vec(gr_ptr res, ulong x, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_doublefac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_doublefac_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_harmonic(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_harmonic_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_beta(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fib2_fmpz(gr_ptr v, gr_ptr u, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fib_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fib_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_fib_vec(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bellnum_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bellnum_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_bellnum_vec(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_partitions_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_partitions_ui(gr_ptr res, ulong n, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_partitions_vec(gr_ptr res, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_chebyshev_t2_fmpz(gr_ptr a, gr_ptr b, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_chebyshev_t_fmpz(gr_ptr y, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_chebyshev_u2_fmpz(gr_ptr a, gr_ptr b, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_chebyshev_u_fmpz(gr_ptr y, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_erfcx(gr_ptr res, gr_srcptr x, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_generic_hilbert_class_poly(gr_ptr res, slong D, gr_srcptr x, gr_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/gr_special/000077500000000000000000000000001461254215100155325ustar00rootroot00000000000000flint-3.1.3/src/gr_special/bellnum.c000066400000000000000000000074431461254215100173440ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arith.h" #include "arb.h" #include "gr_special.h" /* xxx: don't define here */ #define NMOD_CTX_REF(ring_ctx) (((nmod_t *)((ring_ctx)))) #define NMOD_CTX(ring_ctx) (*NMOD_CTX_REF(ring_ctx)) int gr_generic_bellnum_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_bell_number(res, n); return GR_SUCCESS; } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_bellnum_ui(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else if (ctx->which_ring == GR_CTX_NMOD) /* todo: also others in same characteristic */ { ((ulong *) res)[0] = arith_bell_number_nmod(n, NMOD_CTX(ctx)); return GR_SUCCESS; } else /* compute via fmpz */ { int status; fmpz_t t; fmpz_init(t); arith_bell_number(t, n); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } int gr_generic_bellnum_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { if (!COEFF_IS_MPZ(*n) && *n >= 0) { return gr_bellnum_ui(res, *n, ctx); } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_bellnum_fmpz(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else { return GR_UNABLE; } } int gr_generic_bellnum_vec(gr_ptr res, slong len, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_bell_number_vec(res, len); return GR_SUCCESS; } if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute numerically via arb */ { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); if (len > prec) { slong i, sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ctx_t RR; arb_t t; gr_ctx_init_real_arb(RR, prec); arb_init(t); for (i = 0; i < len; i++) { arb_bell_ui(t, i, prec); status |= gr_set_other(GR_ENTRY(res, i, sz), t, RR, ctx); } arb_clear(t); gr_ctx_clear(RR); return status; } } if (ctx->which_ring == GR_CTX_NMOD) /* todo: also others in same characteristic */ { arith_bell_number_nmod_vec(res, len, NMOD_CTX(ctx)); return GR_SUCCESS; } /* compute exactly via Z */ { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_ctx_t ZZ; fmpz * t; gr_ctx_init_fmpz(ZZ); GR_TMP_INIT_VEC(t, len, ZZ); arith_bell_number_vec(t, len); for (i = 0; i < len && status == GR_SUCCESS; i++) status |= gr_set_fmpz(GR_ENTRY(res, i, sz), t + i, ctx); GR_TMP_CLEAR_VEC(t, len, ZZ); gr_ctx_clear(ZZ); return status; } } flint-3.1.3/src/gr_special/bin.c000066400000000000000000000211531461254215100164500ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_vec.h" #include "gr_poly.h" #include "gr_special.h" /* todo: other algorithms; specializations */ int gr_rising_ui_forward(gr_ptr res, gr_srcptr x, ulong n, gr_ctx_t ctx) { gr_ptr t; ulong k; int status = GR_SUCCESS; if (n <= 1) { if (n == 0) return gr_one(res, ctx); else return gr_set(res, x, ctx); } GR_TMP_INIT(t, ctx); status |= gr_add_ui(t, x, 1, ctx); status |= gr_mul(res, x, t, ctx); for (k = 2; k < n; k++) { status |= gr_add_ui(t, t, 1, ctx); status |= gr_mul(res, res, t, ctx); } GR_TMP_CLEAR(t, ctx); return status; } static int bsplit(gr_ptr y, gr_srcptr x, ulong a, ulong b, gr_ctx_t ctx) { int status = GR_SUCCESS; if (b - a <= 16) { if (a == 0) { status |= gr_rising_ui_forward(y, x, b, ctx); } else { status |= gr_add_ui(y, x, a, ctx); status |= gr_rising_ui_forward(y, y, b - a, ctx); } } else { gr_ptr t, u; ulong m = a + (b - a) / 2; GR_TMP_INIT2(t, u, ctx); status |= bsplit(t, x, a, m, ctx); status |= bsplit(u, x, m, b, ctx); status |= gr_mul(y, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); } return status; } int gr_generic_rising_ui(gr_ptr res, gr_srcptr x, ulong n, gr_ctx_t ctx) { return bsplit(res, x, 0, n, ctx); } int gr_generic_falling_ui(gr_ptr res, gr_srcptr x, ulong n, gr_ctx_t ctx) { if (n == 0) return gr_one(res, ctx); else { int status; status = gr_sub_ui(res, x, n - 1, ctx); status |= gr_rising_ui(res, res, n, ctx); return status; } } int gr_generic_rising(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { ulong n; if (gr_get_ui(&n, y, ctx) == GR_SUCCESS) return gr_rising_ui(res, x, n, ctx); return GR_UNABLE; } int gr_generic_falling(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_sub_ui(t, y, 1, ctx); status |= gr_sub(t, x, t, ctx); status |= gr_rising(res, t, y, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_bin_uiui(gr_ptr res, ulong n, ulong k, gr_ctx_t ctx) { int status = GR_SUCCESS; if (k == 0 || n == k) return gr_one(res, ctx); if (k > n) return gr_zero(res, ctx); if (k == 1 || n == k - 1) return gr_set_ui(res, n, ctx); if (k > n / 2) k = n - k; if (ctx->which_ring == GR_CTX_FMPZ) { fmpz_bin_uiui(res, n, k); return GR_SUCCESS; } /* todo */ if (n <= 100 || (gr_ctx_is_finite_characteristic(ctx) == T_FALSE && gr_ctx_has_real_prec(ctx) == T_FALSE)) { fmpz_t t; fmpz_init(t); fmpz_bin_uiui(t, n, k); status |= gr_set_fmpz(res, t, ctx); fmpz_clear(t); } else { gr_ptr t, u; GR_TMP_INIT2(t, u, ctx); status |= gr_set_ui(t, n, ctx); status |= gr_falling_ui(t, t, k, ctx); status |= gr_fac_ui(u, k, ctx); status |= gr_div(res, t, u, ctx); GR_TMP_CLEAR2(t, u, ctx); if (status != GR_SUCCESS) { fmpz_t t; fmpz_init(t); fmpz_bin_uiui(t, n, k); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); } } return status; } int gr_generic_bin_ui(gr_ptr res, gr_srcptr x, ulong y, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; ulong n; if (gr_get_ui(&n, x, ctx) == GR_SUCCESS) return gr_bin_uiui(res, n, y, ctx); GR_TMP_INIT(t, ctx); status |= gr_falling_ui(t, x, y, ctx); status |= gr_fac_ui(res, y, ctx); status |= gr_div(res, t, res, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_bin(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; ulong n; if (gr_get_ui(&n, y, ctx) == GR_SUCCESS) return gr_bin_ui(res, x, n, ctx); GR_TMP_INIT(t, ctx); status |= gr_falling(t, x, y, ctx); status |= gr_fac(res, y, ctx); status |= gr_div(res, t, res, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; GR_TMP_CLEAR(t, ctx); return status; } /* todo: addition basecase */ int gr_generic_bin_ui_vec(gr_ptr res, ulong n, slong len, gr_ctx_t ctx) { gr_ptr f; slong sz = ctx->sizeof_elem; slong i, m; int status = GR_SUCCESS; truth_t finite_char; if (len <= 0) return GR_SUCCESS; if (len == 1) return gr_one(res, ctx); m = FLINT_MIN(len - 1, n / 2) + 1; finite_char = gr_ctx_is_finite_characteristic(ctx); if (finite_char == T_TRUE) { status = _gr_vec_reciprocals(GR_ENTRY(res, 1, sz), m - 1, ctx); if (status == GR_SUCCESS) { gr_method_binary_op_ui mul_ui = GR_BINARY_OP_UI(ctx, MUL_UI); gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); status |= gr_one(res, ctx); for (i = 1; i < m; i++) { status |= mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), ctx); status |= mul_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), n - i + 1, ctx); } } else { GR_TMP_INIT_VEC(f, 2, ctx); status = gr_one(f, ctx); status |= gr_one(GR_ENTRY(f, 1, sz), ctx); status |= _gr_poly_pow_series_ui_binexp(res, f, 2, n, m, ctx); GR_TMP_CLEAR_VEC(f, 2, ctx); } } else { gr_method_binary_op_ui mul_ui = GR_BINARY_OP_UI(ctx, MUL_UI); gr_method_binary_op_ui div_ui = GR_BINARY_OP_UI(ctx, DIV_UI); gr_method_binary_op_ui divexact_ui = GR_BINARY_OP_UI(ctx, DIVEXACT_UI); status |= gr_one(res, ctx); if (finite_char == T_FALSE) { for (i = 1; i < m; i++) { status |= mul_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), n - i + 1, ctx); status |= divexact_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), i, ctx); } } else { for (i = 1; i < m; i++) { status |= mul_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), n - i + 1, ctx); status |= div_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), i, ctx); } } } /* todo: vec reverse */ if (m < len) { for (i = m; i <= FLINT_MIN(n, len - 1); i++) status |= gr_set(GR_ENTRY(res, i, sz), GR_ENTRY(res, n - i, sz), ctx); } if (len - 1 > n) status |= _gr_vec_zero(GR_ENTRY(res, n + 1, sz), len - 1 - n, ctx); return status; } int gr_generic_bin_vec(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx) { gr_ptr t; slong sz = ctx->sizeof_elem; slong i; int status = GR_SUCCESS; ulong n; truth_t finite_char; if (len <= 0) return GR_SUCCESS; if (len == 1) return gr_one(res, ctx); if (gr_get_ui(&n, x, ctx) == GR_SUCCESS) return gr_bin_ui_vec(res, n, len, ctx); finite_char = gr_ctx_is_finite_characteristic(ctx); GR_TMP_INIT(t, ctx); if (finite_char == T_TRUE) { status = _gr_vec_reciprocals(GR_ENTRY(res, 1, sz), len - 1, ctx); if (status == GR_SUCCESS) { status |= gr_one(res, ctx); for (i = 1; i < len; i++) { status |= gr_sub_ui(t, x, i - 1, ctx); status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), ctx); status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), t, ctx); } } else { status = GR_UNABLE; } } else { status |= gr_one(res, ctx); for (i = 1; i < len && status == GR_SUCCESS; i++) { status |= gr_sub_ui(t, x, i - 1, ctx); status |= gr_mul(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), t, ctx); status |= gr_div_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i, sz), i, ctx); } } GR_TMP_CLEAR(t, ctx); return status; } flint-3.1.3/src/gr_special/chebyshev_t.c000066400000000000000000000065241461254215100202100ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_special.h" int gr_generic_chebyshev_t2_fmpz(gr_ptr a, gr_ptr b, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong n1bits, i; fmpz_t n1; /* not implemented */ if (fmpz_sgn(n) < 0) return GR_UNABLE; status |= gr_set(a, x, ctx); status |= gr_one(b, ctx); if (fmpz_sgn(n) < 0) return GR_UNABLE; if (fmpz_is_zero(n)) { gr_swap(a, b, ctx); return status; } if (fmpz_is_one(n)) return status; fmpz_init(n1); fmpz_sub_ui(n1, n, 1); n1bits = fmpz_bits(n1); for (i = n1bits - 1; i >= 0; i--) { if (fmpz_tstbit(n1, i)) { status |= gr_mul(b, b, a, ctx); status |= gr_mul_two(b, b, ctx); status |= gr_sub(b, b, x, ctx); status |= gr_mul(a, a, a, ctx); status |= gr_mul_two(a, a, ctx); status |= gr_sub_ui(a, a, 1, ctx); } else { status |= gr_mul(a, a, b, ctx); status |= gr_mul_two(a, a, ctx); status |= gr_sub(a, a, x, ctx); status |= gr_mul(b, b, b, ctx); status |= gr_mul_two(b, b, ctx); status |= gr_sub_ui(b, b, 1, ctx); } } fmpz_clear(n1); return status; } int gr_generic_chebyshev_t_fmpz(gr_ptr y, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong nbits, i, r; fmpz_t n1; if (fmpz_is_zero(n)) return gr_one(y, ctx); if (fmpz_is_one(n)) return gr_set(y, x, ctx); if (fmpz_sgn(n) < 0) { fmpz_init(n1); fmpz_neg(n1, n); status = gr_generic_chebyshev_t_fmpz(y, n1, x, ctx); fmpz_clear(n1); return status; } if (gr_is_zero(x, ctx) == T_TRUE) { int c = fmpz_fdiv_ui(n, 4); return gr_set_si(y, (c == 0) - (c == 2), ctx); } if (gr_is_one(x, ctx) == T_TRUE) return gr_one(y, ctx); if (gr_is_neg_one(x, ctx) == T_TRUE) return fmpz_is_even(n) ? gr_one(y, ctx) : gr_neg_one(y, ctx); nbits = fmpz_bits(n); r = fmpz_val2(n); if (nbits == r + 1) { status |= gr_sqr(y, x, ctx); status |= gr_mul_two(y, y, ctx); status |= gr_sub_ui(y, y, 1, ctx); r -= 1; } else { /* we only need one value, so break out final iteration */ gr_ptr t, u; fmpz_t n1; GR_TMP_INIT2(t, u, ctx); fmpz_init(n1); fmpz_tdiv_q_2exp(n1, n, r + 1); fmpz_add_ui(n1, n1, 1); status |= gr_generic_chebyshev_t2_fmpz(t, u, n1, x, ctx); status |= gr_mul(t, t, u, ctx); status |= gr_mul_two(t, t, ctx); status |= gr_sub(y, t, x, ctx); GR_TMP_CLEAR2(t, u, ctx); fmpz_clear(n1); } for (i = 0; i < r; i++) { status |= gr_sqr(y, y, ctx); status |= gr_mul_two(y, y, ctx); status |= gr_sub_ui(y, y, 1, ctx); } return status; } flint-3.1.3/src/gr_special/chebyshev_u.c000066400000000000000000000064771461254215100202200ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_special.h" int gr_generic_chebyshev_u2_fmpz(gr_ptr a, gr_ptr b, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; slong nbits, i; gr_ptr t, u; /* not implemented */ if (fmpz_sgn(n) < 0) return GR_UNABLE; if (fmpz_is_zero(n)) { status |= gr_one(a, ctx); status |= gr_zero(b, ctx); return status; } status |= gr_mul_two(a, x, ctx); status |= gr_one(b, ctx); if (fmpz_is_one(n)) return status; nbits = fmpz_bits(n); GR_TMP_INIT2(t, u, ctx); for (i = nbits - 2; i >= 0; i--) { status |= gr_add(t, a, b, ctx); status |= gr_sub(u, a, b, ctx); if (fmpz_tstbit(n, i)) { status |= gr_submul(b, x, a, ctx); status |= gr_mul(a, a, b, ctx); status |= gr_neg(a, a, ctx); status |= gr_mul_two(a, a, ctx); status |= gr_mul(b, t, u, ctx); } else { status |= gr_submul(a, x, b, ctx); status |= gr_mul(b, a, b, ctx); status |= gr_mul_two(b, b, ctx); status |= gr_mul(a, t, u, ctx); } } GR_TMP_CLEAR2(t, u, ctx); return status; } int gr_generic_chebyshev_u_fmpz(gr_ptr y, const fmpz_t n, gr_srcptr x, gr_ctx_t ctx) { gr_ptr a, b; fmpz_t n1; int status = GR_SUCCESS; if (fmpz_is_zero(n)) return gr_one(y, ctx); if (fmpz_is_one(n)) return gr_mul_two(y, x, ctx); if (fmpz_sgn(n) < 0) { if (fmpz_equal_si(n, -1)) return gr_zero(y, ctx); fmpz_init(n1); fmpz_add_ui(n1, n, 2); fmpz_neg(n1, n1); status = gr_generic_chebyshev_u_fmpz(y, n1, x, ctx); status |= gr_neg(y, y, ctx); fmpz_clear(n1); return status; } if (gr_is_zero(x, ctx) == T_TRUE) { int c = fmpz_fdiv_ui(n, 4); return gr_set_si(y, (c == 0) - (c == 2), ctx); } if (gr_is_one(x, ctx) == T_TRUE) { fmpz_init(n1); fmpz_add_ui(n1, n, 1); status |= gr_set_fmpz(y, n1, ctx); fmpz_clear(n1); return status; } if (gr_is_neg_one(x, ctx) == T_TRUE) { fmpz_init(n1); fmpz_add_ui(n1, n, 1); if (fmpz_is_odd(n)) fmpz_neg(n1, n1); status |= gr_set_fmpz(y, n1, ctx); fmpz_clear(n1); return status; } GR_TMP_INIT2(a, b, ctx); fmpz_init(n1); fmpz_tdiv_q_2exp(n1, n, 1); status |= gr_generic_chebyshev_u2_fmpz(a, b, n1, x, ctx); if (fmpz_is_even(n)) { status |= gr_add(y, a, b, ctx); status |= gr_sub(b, a, b, ctx); status |= gr_mul(y, y, b, ctx); } else { status |= gr_submul(b, a, x, ctx); status |= gr_mul(y, a, b, ctx); status |= gr_mul_two(y, y, ctx); status |= gr_neg(y, y, ctx); } GR_TMP_CLEAR2(a, b, ctx); fmpz_clear(n1); return status; } flint-3.1.3/src/gr_special/dirichlet.c000066400000000000000000000075701461254215100176560ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "acb_dirichlet.h" #include "gr_special.h" #include "gr_vec.h" /* todo: overloads */ int gr_dirichlet_chi_fmpz(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, const fmpz_t n, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_CC_ACB) { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_dirichlet_chi(res, G, chi, fmpz_fdiv_ui(n, G->q), prec); return GR_SUCCESS; } return GR_UNABLE; } int gr_dirichlet_chi_vec(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_CC_ACB) { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_dirichlet_chi_vec(res, G, chi, len, prec); return GR_SUCCESS; } return GR_UNABLE; } int gr_dirichlet_l(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr s, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_CC_ACB) { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_dirichlet_l(res, s, G, chi, prec); return GR_SUCCESS; } if (ctx->which_ring == GR_CTX_RR_ARB) { acb_t t; slong prec; int status; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_init(t); acb_set_arb(t, s); acb_dirichlet_l(t, t, G, chi, prec); if (arb_is_zero(acb_imagref(t)) && arb_is_finite(acb_realref(t))) { arb_swap(res, acb_realref(t)); status = GR_SUCCESS; } else { status = GR_UNABLE; } acb_clear(t); return status; } return GR_UNABLE; } int gr_dirichlet_hardy_z(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr s, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_CC_ACB) { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_dirichlet_hardy_z(res, s, G, chi, 1, prec); return GR_SUCCESS; } if (ctx->which_ring == GR_CTX_RR_ARB) { acb_t t; slong prec; int status; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_init(t); acb_set_arb(t, s); acb_dirichlet_hardy_z(t, t, G, chi, 1, prec); if (arb_is_zero(acb_imagref(t)) && arb_is_finite(acb_realref(t))) { arb_swap(res, acb_realref(t)); status = GR_SUCCESS; } else { status = GR_UNABLE; } acb_clear(t); return status; } return GR_UNABLE; } int gr_dirichlet_hardy_theta(gr_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, gr_srcptr s, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_CC_ACB) { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_dirichlet_hardy_theta(res, s, G, chi, 1, prec); return GR_SUCCESS; } if (ctx->which_ring == GR_CTX_RR_ARB) { acb_t t; slong prec; int status; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); acb_init(t); acb_set_arb(t, s); acb_dirichlet_hardy_theta(t, t, G, chi, 1, prec); if (arb_is_zero(acb_imagref(t)) && arb_is_finite(acb_realref(t))) { arb_swap(res, acb_realref(t)); status = GR_SUCCESS; } else { status = GR_UNABLE; } acb_clear(t); return status; } return GR_UNABLE; } flint-3.1.3/src/gr_special/elementary.c000066400000000000000000000112451461254215100200460ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" int gr_generic_exp(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_one(res, ctx); return GR_UNABLE; } int gr_generic_expm1(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = gr_exp(res, x, ctx); status |= gr_sub_ui(res, res, 1, ctx); return status; } int gr_generic_exp2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_ui(t, 2, ctx); status |= gr_pow(res, t, x, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_exp10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_ui(t, 10, ctx); status |= gr_pow(res, t, x, ctx); GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_log(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_one(x, ctx) == T_TRUE) return gr_zero(res, ctx); return GR_UNABLE; } int gr_generic_log1p(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = gr_add_ui(res, x, 1, ctx); status |= gr_log(res, res, ctx); return status; } int gr_generic_log2(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_ui(t, 2, ctx); status |= gr_log(t, t, ctx); status |= gr_log(res, x, ctx); status |= gr_div(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; return status; } int gr_generic_log10(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_set_ui(t, 10, ctx); status |= gr_log(t, t, ctx); status |= gr_log(res, x, ctx); status |= gr_div(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; return status; } int gr_generic_sin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res, ctx); return GR_UNABLE; } int gr_generic_cos(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_one(res, ctx); return GR_UNABLE; } int gr_generic_sin_cos(gr_ptr res1, gr_ptr res2, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res1, ctx) | gr_one(res2, ctx); else return GR_UNABLE; } int gr_generic_tan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res, ctx); return GR_UNABLE; } int gr_generic_asin(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res, ctx); return GR_UNABLE; } int gr_generic_asinh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res, ctx); return GR_UNABLE; } int gr_generic_atan(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res, ctx); return GR_UNABLE; } int gr_generic_atanh(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { if (gr_is_zero(x, ctx) == T_TRUE) return gr_zero(res, ctx); return GR_UNABLE; } int gr_generic_acot(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_inv(res, x, ctx); status |= gr_atan(res, res, ctx); return status; } int gr_generic_asec(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_inv(res, x, ctx); status |= gr_acos(res, res, ctx); return status; } int gr_generic_acsc(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_inv(res, x, ctx); status |= gr_asin(res, res, ctx); return status; } int gr_generic_acoth(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_inv(res, x, ctx); status |= gr_atanh(res, res, ctx); return status; } int gr_generic_asech(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_inv(res, x, ctx); status |= gr_acosh(res, res, ctx); return status; } int gr_generic_acsch(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; status |= gr_inv(res, x, ctx); status |= gr_asinh(res, res, ctx); return status; } flint-3.1.3/src/gr_special/erf.c000066400000000000000000000015241461254215100164540ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_special.h" /* todo: numerically stable implementation for large re(x) */ int gr_generic_erfcx(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_sqr(t, x, ctx); status |= gr_exp(t, t, ctx); status |= gr_erfc(res, x, ctx); status |= gr_mul(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; return status; } flint-3.1.3/src/gr_special/fac.c000066400000000000000000000247511461254215100164400ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" #include "arith.h" #include "arb.h" #include "gr_special.h" /* todo: maybe add a second table for a second word */ #if FLINT_BITS == 64 #define FAC_TAB_SIZE 21 #else #define FAC_TAB_SIZE 13 #endif static const mp_limb_t fac_tab[] = { UWORD(1), UWORD(1), UWORD(2), UWORD(6), UWORD(24), UWORD(120), UWORD(720), UWORD(5040), UWORD(40320), UWORD(362880), UWORD(3628800), UWORD(39916800), UWORD(479001600), #if FLINT_BITS == 64 UWORD(6227020800), UWORD(87178291200), UWORD(1307674368000), UWORD(20922789888000), UWORD(355687428096000), UWORD(6402373705728000), UWORD(121645100408832000), UWORD(2432902008176640000), #endif }; /* xxx: don't define here */ #define NMOD_CTX_REF(ring_ctx) (((nmod_t *)((ring_ctx)))) #define NMOD_CTX(ring_ctx) (*NMOD_CTX_REF(ring_ctx)) int gr_generic_fac_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { fmpz_fac_ui(res, n); return GR_SUCCESS; } else if (n < FAC_TAB_SIZE) { return gr_set_ui(res, fac_tab[n], ctx); } else if (gr_ctx_is_finite_characteristic(ctx) == T_TRUE) { gr_method_binary_op_ui mul_ui = GR_BINARY_OP_UI(ctx, MUL_UI); int status = GR_SUCCESS; ulong i; if (ctx->which_ring == GR_CTX_NMOD) { ulong m = NMOD_CTX(ctx).n; /* todo: multipoint eval also for other rings */ if (n >= m) return gr_zero(res, ctx); if (n >= 2000000) return gr_set_ui(res, n_factorial_fast_mod2_preinv(n, NMOD_CTX(ctx).n, NMOD_CTX(ctx).ninv), ctx); } status |= gr_set_ui(res, fac_tab[FAC_TAB_SIZE - 1], ctx); i = FAC_TAB_SIZE; for ( ; i + 8 <= FLINT_MIN(n, UWORD(1) << (FLINT_BITS / 8)); i += 8) status |= mul_ui(res, res, i*(i+1)*(i+2)*(i+3)*(i+4)*(i+5)*(i+6)*(i+7), ctx); for ( ; i + 6 <= FLINT_MIN(n, UWORD(1) << (FLINT_BITS / 6)); i += 6) status |= mul_ui(res, res, i*(i+1)*(i+2)*(i+3)*(i+4)*(i+5), ctx); for ( ; i + 4 <= FLINT_MIN(n, UWORD(1) << (FLINT_BITS / 4)); i += 4) status |= mul_ui(res, res, i*(i+1)*(i+2)*(i+3), ctx); for ( ; i + 3 <= FLINT_MIN(n, UWORD(1) << (FLINT_BITS / 3)); i += 3) status |= mul_ui(res, res, i*(i+1)*(i+2), ctx); for ( ; i + 2 <= FLINT_MIN(n, UWORD(1) << (FLINT_BITS / 2)); i += 2) status |= mul_ui(res, res, i*(i+1), ctx); for ( ; i <= n; i += 1) status |= mul_ui(res, res, i, ctx); return status; } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_fac_ui(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else /* compute via fmpz */ { int status; fmpz_t t; fmpz_init(t); fmpz_fac_ui(t, n); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } int gr_generic_fac_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { if (*n >= 0 && *n <= COEFF_MAX) { return gr_fac_ui(res, *n, ctx); } else if (fmpz_sgn(n) < 0) { return GR_DOMAIN; } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_fac_fmpz(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else { return GR_UNABLE; } } int gr_generic_fac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { ulong n; if (gr_get_ui(&n, x, ctx) == GR_SUCCESS) { return gr_fac_ui(res, n, ctx); } else { return gr_add_ui(res, x, 1, ctx) | gr_gamma(res, res, ctx); } } int gr_generic_fac_vec(gr_ptr res, slong len, gr_ctx_t ctx) { gr_method_binary_op_ui mul_ui = GR_BINARY_OP_UI(ctx, MUL_UI); gr_method_unary_op_ui set_ui = GR_UNARY_OP_UI(ctx, SET_UI); int status = GR_SUCCESS; slong i; slong sz = ctx->sizeof_elem; for (i = 0; i < FLINT_MIN(FAC_TAB_SIZE, len); i++) status |= set_ui(GR_ENTRY(res, i, sz), fac_tab[i], ctx); /* todo: consider increasing numerical precision */ for (; i < len; i++) status |= mul_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), i, ctx); return status; } int gr_generic_rfac_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { return gr_fac_ui(res, n, ctx) | gr_inv(res, res, ctx); } int gr_generic_rfac_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { if (0 <= *n && *n <= COEFF_MAX) { return gr_rfac_ui(res, *n, ctx); } else if (fmpz_sgn(n) < 0) { return gr_zero(res, ctx); } else { fmpz_t t; int status; fmpz_init(t); fmpz_add_ui(t, n, 1); status = gr_set_fmpz(res, t, ctx) | gr_rgamma(res, res, ctx); fmpz_clear(t); return status; } } int gr_generic_rfac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { ulong n; if (gr_get_ui(&n, x, ctx) == GR_SUCCESS) { return gr_rfac_ui(res, n, ctx); } else { return gr_add_ui(res, x, 1, ctx) | gr_rgamma(res, res, ctx); } } int gr_generic_rfac_vec(gr_ptr res, slong len, gr_ctx_t ctx) { gr_method_binary_op_ui mul_ui = GR_BINARY_OP_UI(ctx, MUL_UI); int status = GR_SUCCESS; slong i; slong sz = ctx->sizeof_elem; /* todo: increase numerical precision */ if (len >= 3) { status = gr_rfac_ui(GR_ENTRY(res, len - 1, sz), len - 1, ctx); if (status == GR_SUCCESS) { for (i = len - 2; i >= 2; i--) status |= mul_ui(GR_ENTRY(res, i, sz), GR_ENTRY(res, i + 1, sz), i + 1, ctx); } } if (len >= 2) status |= gr_one(GR_ENTRY(res, 1, sz), ctx); if (len >= 1) status |= gr_one(res, ctx); /* make 1/2 exact */ if (len >= 3 && gr_ctx_has_real_prec(ctx) == T_TRUE) status |= gr_mul_2exp_si(GR_ENTRY(res, 2, sz), res, -1, ctx); return status; } /* todo: specializations (fmpz) */ /* todo: finite characteristic */ int gr_generic_doublefac_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { int status = GR_SUCCESS; if (n % 2 == 0) { status |= gr_fac_ui(res, n / 2, ctx); status |= gr_mul_2exp_si(res, res, n / 2, ctx); } else { gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_doublefac_ui(t, n - 1, ctx); status |= gr_fac_ui(res, n, ctx); status |= gr_div(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; } return status; } int gr_generic_doublefac(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; gr_ptr t, u, v; ulong n; if (gr_get_ui(&n, x, ctx) == GR_SUCCESS) return gr_doublefac_ui(res, n, ctx); /* 2^(x/2) (pi/2)^((cospi(x)-1)/4) gamma(1+x/2) */ GR_TMP_INIT3(t, u, v, ctx); status |= gr_cos_pi(t, x, ctx); status |= gr_sub_ui(t, t, 1, ctx); status |= gr_mul_2exp_si(t, t, -2, ctx); status |= gr_pi(u, ctx); status |= gr_mul_2exp_si(u, u, -1, ctx); status |= gr_pow(u, u, t, ctx); status |= gr_mul_2exp_si(t, x, -1, ctx); status |= gr_set_ui(v, 2, ctx); status |= gr_pow(t, v, t, ctx); status |= gr_mul(t, t, u, ctx); status |= gr_mul_2exp_si(u, x, -1, ctx); status |= gr_add_ui(u, u, 1, ctx); status |= gr_gamma(u, u, ctx); status |= gr_mul(res, t, u, ctx); GR_TMP_CLEAR3(t, u, v, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; return status; } /* todo: any non-stupid algorithm; at least use rising2 if nothing else */ /* todo: specializations */ int gr_generic_harmonic_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { gr_ptr s, t; ulong i; int status = GR_SUCCESS; if (n <= 1) return gr_set_ui(res, n, ctx); if (n > 100 && gr_ctx_has_real_prec(ctx) == T_TRUE) { gr_ptr t; GR_TMP_INIT(t, ctx); status |= gr_set_ui(t, n, ctx); status |= gr_add_ui(t, t, 1, ctx); status |= gr_digamma(t, t, ctx); status |= gr_euler(res, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } if (n <= 100 || gr_ctx_is_finite_characteristic(ctx) == T_FALSE) { fmpq_t t; fmpq_init(t); fmpq_harmonic_ui(t, n); status = gr_set_fmpq(res, t, ctx); fmpq_clear(t); return status; } GR_TMP_INIT2(s, t, ctx); for (i = n; i >= 1 && status == GR_SUCCESS; i--) { status |= gr_set_ui(t, i, ctx); status |= gr_inv(t, t, ctx); status |= gr_add(s, s, t, ctx); } gr_swap(res, s, ctx); GR_TMP_CLEAR2(s, t, ctx); return status; } int gr_generic_harmonic(gr_ptr res, gr_srcptr x, gr_ctx_t ctx) { ulong n; if (gr_get_ui(&n, x, ctx) == GR_SUCCESS) { return gr_harmonic_ui(res, n, ctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= gr_add_ui(t, x, 1, ctx); status |= gr_digamma(t, t, ctx); status |= gr_euler(res, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; return status; } } /* todo */ int gr_generic_beta(gr_ptr res, gr_srcptr x, gr_srcptr y, gr_ctx_t ctx) { gr_ptr t, u, v; int status = GR_SUCCESS; GR_TMP_INIT3(t, u, v, ctx); status |= gr_gamma(t, x, ctx); status |= gr_gamma(u, y, ctx); status |= gr_add(v, x, y, ctx); status |= gr_rgamma(v, v, ctx); status |= gr_mul(res, t, u, ctx); status |= gr_mul(res, res, v, ctx); GR_TMP_CLEAR3(t, u, v, ctx); if (status != GR_SUCCESS) status = GR_UNABLE; return status; } flint-3.1.3/src/gr_special/fib.c000066400000000000000000000175051461254215100164460ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gr_special.h" /* TODO: Binet formula + exp/log should be faster for huge numerical Fibonacci values */ /* TODO: single iteration applied directly to table; see fmpz_fib_ui */ /* TODO: for exact infinite rings, it is worth calling mpz_fib_ui instead of using generic code for n < 10000 or so. fmpz currently overrides the generic code, but would also help over QQ, etc. */ #if FLINT_BITS == 64 #define FIBTAB_NUM 94 #define FIBTAB_BITS 6 #else #define FIBTAB_NUM 48 #define FIBTAB_BITS 5 #endif static const ulong fibtab[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, UWORD(2971215073), #if FLINT_BITS == 64 UWORD(4807526976), UWORD(7778742049), UWORD(12586269025), UWORD(20365011074), UWORD(32951280099), UWORD(53316291173), UWORD(86267571272), UWORD(139583862445), UWORD(225851433717), UWORD(365435296162), UWORD(591286729879), UWORD(956722026041), UWORD(1548008755920), UWORD(2504730781961), UWORD(4052739537881), UWORD(6557470319842), UWORD(10610209857723), UWORD(17167680177565), UWORD(27777890035288), UWORD(44945570212853), UWORD(72723460248141), UWORD(117669030460994), UWORD(190392490709135), UWORD(308061521170129), UWORD(498454011879264), UWORD(806515533049393), UWORD(1304969544928657), UWORD(2111485077978050), UWORD(3416454622906707), UWORD(5527939700884757), UWORD(8944394323791464), UWORD(14472334024676221), UWORD(23416728348467685), UWORD(37889062373143906), UWORD(61305790721611591), UWORD(99194853094755497), UWORD(160500643816367088), UWORD(259695496911122585), UWORD(420196140727489673), UWORD(679891637638612258), UWORD(1100087778366101931), UWORD(1779979416004714189), UWORD(2880067194370816120), UWORD(4660046610375530309), UWORD(7540113804746346429), UWORD(12200160415121876738) #endif }; /* Essentially the same algorithm as https://gmplib.org/manual/Fibonacci-Numbers-Algorithm */ int gr_generic_fib2_fmpz(gr_ptr v, gr_ptr u, const fmpz_t n, gr_ctx_t ctx) { gr_method_unary_op sqr = GR_UNARY_OP(ctx, SQR); gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); gr_method_binary_op sub = GR_BINARY_OP(ctx, SUB); gr_method_binary_op_ui add_ui = GR_BINARY_OP_UI(ctx, ADD_UI); gr_method_binary_op_ui sub_ui = GR_BINARY_OP_UI(ctx, SUB_UI); gr_method_binary_op_si mul_2exp_si = GR_BINARY_OP_SI(ctx, MUL_2EXP_SI); slong bit, nbits, i; int status = GR_SUCCESS; gr_ptr t; slong real_prec = 0; mp_srcptr np; mp_limb_t ntmp; if (fmpz_sgn(n) < 0) { fmpz_t t; fmpz_init(t); fmpz_neg(t, n); fmpz_add_ui(t, t, 1); status |= gr_generic_fib2_fmpz(u, v, t, ctx); if (fmpz_is_even(t)) status |= gr_neg(u, u, ctx); else status |= gr_neg(v, v, ctx); fmpz_clear(t); return status; } nbits = fmpz_bits(n); if (nbits <= FIBTAB_BITS + 1 && *n < FIBTAB_NUM) { i = *n; status |= gr_set_ui(u, i ? fibtab[i - 1] : 1, ctx); status |= gr_set_ui(v, fibtab[i], ctx); return status; } bit = nbits - FIBTAB_BITS; { fmpz_t t; fmpz_init(t); fmpz_tdiv_q_2exp(t, n, bit); i = *t; fmpz_clear(t); } if (!COEFF_IS_MPZ(*n)) { ntmp = *n; np = &ntmp; } else np = COEFF_TO_PTR(*n)->_mp_d; if (gr_ctx_has_real_prec(ctx) == T_TRUE) { GR_IGNORE(gr_ctx_get_real_prec(&real_prec, ctx)); GR_IGNORE(gr_ctx_set_real_prec(ctx, real_prec + 2 * nbits)); } status |= gr_set_ui(u, i ? fibtab[i - 1] : 1, ctx); status |= gr_set_ui(v, fibtab[i], ctx); GR_TMP_INIT(t, ctx); while (1) { /* v = f(k), u = f(k-1) */ status |= sqr(t, v, ctx); status |= sqr(v, u, ctx); /* f(2k-1) = f(k)^2 + f(k-1)^2 */ status |= add(u, t, v, ctx); /* f(2k+1) = 4f(k)^2 - f(k-1)^2 + 2(-1)^k */ if ((np[bit / FLINT_BITS] >> (bit % FLINT_BITS)) & 1) status |= add_ui(v, v, 2, ctx); else status |= sub_ui(v, v, 2, ctx); status |= mul_2exp_si(t, t, 2, ctx); status |= sub(v, t, v, ctx); bit--; /* restore precision before the final operation */ if (bit == 0 && real_prec != 0) GR_IGNORE(gr_ctx_set_real_prec(ctx, real_prec)); /* f(2k) = f(2k+1) - f(2k-1) */ if ((np[bit / FLINT_BITS] >> (bit % FLINT_BITS)) & 1) status |= sub(u, v, u, ctx); else status |= sub(v, v, u, ctx); if (bit == 0) break; } GR_TMP_CLEAR(t, ctx); return status; } int gr_generic_fib_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { fmpz_t n2; gr_ptr u, v; int status = GR_SUCCESS; slong real_prec = 0; if (fmpz_sgn(n) < 0) { fmpz_t t; fmpz_init(t); fmpz_neg(t, n); status |= gr_generic_fib_fmpz(res, t, ctx); if (fmpz_is_even(t)) status |= gr_neg(res, res, ctx); fmpz_clear(t); return status; } if (fmpz_cmp_ui(n, FIBTAB_NUM) < 0) return gr_set_ui(res, fibtab[*n], ctx); fmpz_init(n2); GR_TMP_INIT2(u, v, ctx); fmpz_tdiv_q_2exp(n2, n, 1); if (gr_ctx_has_real_prec(ctx) == T_TRUE) { GR_IGNORE(gr_ctx_get_real_prec(&real_prec, ctx)); GR_IGNORE(gr_ctx_set_real_prec(ctx, real_prec + 10)); } status = gr_generic_fib2_fmpz(v, u, n2, ctx); if (fmpz_is_odd(n)) { /* f(2k+1) = (2f(k)+f(k-1))*(2f(k)-f(k-1)) + 2*(-1)^k */ status |= gr_mul_two(v, v, ctx); status |= gr_add(res, v, u, ctx); status |= gr_sub(u, v, u, ctx); status |= gr_mul(v, res, u, ctx); /* restore precision before last operation */ if (real_prec != 0) GR_IGNORE(gr_ctx_set_real_prec(ctx, real_prec)); if (fmpz_is_odd(n2)) status |= gr_sub_ui(res, v, 2, ctx); else status |= gr_add_ui(res, v, 2, ctx); } else { /* f(2k) = f(k)*(f(k)+2f(k-1)) */ status |= gr_mul_two(u, u, ctx); status |= gr_add(u, u, v, ctx); /* restore precision before the final operation */ if (real_prec != 0) GR_IGNORE(gr_ctx_set_real_prec(ctx, real_prec)); status |= gr_mul(res, u, v, ctx); } fmpz_clear(n2); GR_TMP_CLEAR2(u, v, ctx); return status; } int gr_generic_fib_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { fmpz_t t; int status; if (n < FIBTAB_NUM) return gr_set_ui(res, fibtab[n], ctx); fmpz_init_set_ui(t, n); status = gr_generic_fib_fmpz(res, t, ctx); fmpz_clear(t); return status; } int gr_generic_fib_vec(gr_ptr res, slong len, gr_ctx_t ctx) { gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); gr_method_unary_op_ui set_ui = GR_UNARY_OP_UI(ctx, SET_UI); int status = GR_SUCCESS; slong i; slong sz = ctx->sizeof_elem; for (i = 0; i < FLINT_MIN(FIBTAB_NUM, len); i++) status |= set_ui(GR_ENTRY(res, i, sz), fibtab[i], ctx); /* todo: consider increasing numerical precision */ for (; i < len; i++) status |= add(GR_ENTRY(res, i, sz), GR_ENTRY(res, i - 1, sz), GR_ENTRY(res, i - 2, sz), ctx); return status; } flint-3.1.3/src/gr_special/inlines.c000066400000000000000000000007201461254215100173360ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define GR_SPECIAL_INLINES_C #include "gr_special.h" #undef GR_SPECIAL_INLINES_C flint-3.1.3/src/gr_special/modular.c000066400000000000000000000021021461254215100173340ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "acb_modular.h" #include "gr_special.h" #include "gr_poly.h" #include "gr_generic.h" int gr_generic_hilbert_class_poly(gr_ptr res, slong D, gr_srcptr x, gr_ctx_t ctx) { int status = GR_SUCCESS; fmpz_poly_t t; fmpz_poly_init(t); acb_modular_hilbert_class_poly(t, D); if (t->length == 0) { status = GR_DOMAIN; } else { if (ctx->which_ring == GR_CTX_GR_POLY && gr_poly_is_gen(x, POLYNOMIAL_ELEM_CTX(ctx)) == T_TRUE) status |= gr_poly_set_fmpz_poly(res, t, POLYNOMIAL_ELEM_CTX(ctx)); else status |= gr_fmpz_poly_evaluate(res, t, x, ctx); } fmpz_poly_clear(t); return status; } flint-3.1.3/src/gr_special/partitions.c000066400000000000000000000076351461254215100201050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arith.h" #include "partitions.h" #include "arb.h" #include "gr_special.h" int gr_generic_partitions_ui(gr_ptr res, ulong n, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { partitions_fmpz_ui(res, n); return GR_SUCCESS; } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_partitions_ui(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else /* compute via fmpz */ { int status; fmpz_t t; fmpz_init(t); partitions_fmpz_ui(t, n); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } int gr_generic_partitions_fmpz(gr_ptr res, const fmpz_t n, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { partitions_fmpz_fmpz(res, n, 0); return GR_SUCCESS; } else if (fmpz_sgn(n) < 0) { return gr_zero(res, ctx); } else if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute via arb */ { gr_ctx_t RR; arb_t t; slong prec; int status = GR_SUCCESS; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); gr_ctx_init_real_arb(RR, prec); arb_init(t); status |= gr_partitions_fmpz(t, n, RR); status |= gr_set_other(res, t, RR, ctx); arb_clear(t); gr_ctx_clear(RR); return status; } else /* compute via fmpz */ { int status; fmpz_t t; fmpz_init(t); partitions_fmpz_fmpz(t, n, 0); status = gr_set_fmpz(res, t, ctx); fmpz_clear(t); return status; } } /* xxx */ #define NMOD_CTX_REF(ring_ctx) (((nmod_t *)((ring_ctx)))) #define NMOD_CTX(ring_ctx) (*NMOD_CTX_REF(ring_ctx)) int gr_generic_partitions_vec(gr_ptr res, slong len, gr_ctx_t ctx) { if (ctx->which_ring == GR_CTX_FMPZ) { arith_number_of_partitions_vec(res, len); return GR_SUCCESS; } if (ctx->which_ring == GR_CTX_NMOD) { arith_number_of_partitions_nmod_vec(res, len, NMOD_CTX(ctx)); return GR_SUCCESS; } if (gr_ctx_has_real_prec(ctx) == T_TRUE) /* compute numerically via arb */ { slong prec; GR_MUST_SUCCEED(gr_ctx_get_real_prec(&prec, ctx)); if (len > prec) /* todo: better criterion */ { slong i, sz = ctx->sizeof_elem; int status = GR_SUCCESS; gr_ctx_t RR; arb_t t; gr_ctx_init_real_arb(RR, prec); arb_init(t); for (i = 0; i < len; i++) { arb_partitions_ui(t, i, prec); status |= gr_set_other(GR_ENTRY(res, i, sz), t, RR, ctx); } arb_clear(t); gr_ctx_clear(RR); return status; } } /* compute exactly via Z */ { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_ctx_t ZZ; fmpz * t; gr_ctx_init_fmpz(ZZ); GR_TMP_INIT_VEC(t, len, ZZ); arith_number_of_partitions_vec(t, len); for (i = 0; i < len && status == GR_SUCCESS; i++) status |= gr_set_fmpz(GR_ENTRY(res, i, sz), t + i, ctx); GR_TMP_CLEAR_VEC(t, len, ZZ); gr_ctx_clear(ZZ); return status; } } flint-3.1.3/src/gr_special/test/000077500000000000000000000000001461254215100165115ustar00rootroot00000000000000flint-3.1.3/src/gr_special/test/main.c000066400000000000000000000015631461254215100176060ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-chebyshev.c" #include "t-fac.c" #include "t-fib.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(gr_special_chebyshev), TEST_FUNCTION(gr_special_fac), TEST_FUNCTION(gr_special_fib) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/gr_special/test/t-chebyshev.c000066400000000000000000000047061461254215100211050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "gr_special.h" int test_chebyshev_fmpz_rec1(flint_rand_t state) { gr_ctx_t ctx; gr_ptr ft, ft1, ft2, t, g; fmpz_t n, n1, n2; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); GR_TMP_INIT5(ft, ft1, ft2, g, t, ctx); fmpz_init(n); fmpz_init(n1); fmpz_init(n2); if (gr_ctx_has_real_prec(ctx) == T_TRUE || gr_ctx_is_finite_characteristic(ctx) == T_TRUE) fmpz_randtest(n, state, 100); else fmpz_randtest(n, state, 5); fmpz_add_ui(n1, n, 1); fmpz_add_ui(n2, n, 2); status |= gr_randtest(t, state, ctx); if (n_randint(state, 2)) { status |= gr_generic_chebyshev_t_fmpz(ft, n, t, ctx); status |= gr_generic_chebyshev_t_fmpz(ft1, n1, t, ctx); status |= gr_generic_chebyshev_t_fmpz(ft2, n2, t, ctx); } else { status |= gr_generic_chebyshev_u_fmpz(ft, n, t, ctx); status |= gr_generic_chebyshev_u_fmpz(ft1, n1, t, ctx); status |= gr_generic_chebyshev_u_fmpz(ft2, n2, t, ctx); } status |= gr_mul(g, ft1, t, ctx); status |= gr_mul_two(g, g, ctx); status |= gr_sub(g, g, ft, ctx); if (status == GR_SUCCESS && gr_equal(g, ft2, ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("n = "); fmpz_print(n); printf("\n"); printf("n1 = "); fmpz_print(n1); printf("\n"); printf("n2 = "); fmpz_print(n2); printf("\n"); printf("t = "); gr_println(t, ctx); printf("\n"); printf("ft = "); gr_println(ft, ctx); printf("\n"); printf("ft1 = "); gr_println(ft1, ctx); printf("\n"); printf("ft2 = "); gr_println(ft2, ctx); printf("\n"); printf("g = "); gr_println(g, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR5(ft, ft1, ft2, g, t, ctx); fmpz_clear(n); fmpz_clear(n1); fmpz_clear(n2); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_special_chebyshev, state) { slong iter; for (iter = 0; iter < 1000; iter++) test_chebyshev_fmpz_rec1(state); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_special/test/t-fac.c000066400000000000000000000140211461254215100176450ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "gr_special.h" int test_fac_rec1(flint_rand_t state, int which) { gr_ctx_t ctx; gr_ptr x, x1, fx, fx1, x1fx; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); GR_TMP_INIT5(x, x1, fx, fx1, x1fx, ctx); if (gr_ctx_is_exact(ctx) == T_TRUE) status |= gr_set_si(x, n_randint(state, 200) - 100, ctx); else status |= gr_randtest(x, state, ctx); status |= gr_add_ui(x1, x, 1, ctx); if (which == 0) { status |= gr_fac(fx, x, ctx); status |= gr_fac(fx1, x1, ctx); status |= gr_mul(x1fx, fx, x1, ctx); } else { status |= gr_rfac(fx, x, ctx); status |= gr_rfac(fx1, x1, ctx); status |= gr_div(x1fx, fx, x1, ctx); } if (status == GR_SUCCESS && gr_equal(fx1, x1fx, ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("x = "); gr_println(x, ctx); printf("\n"); printf("x1 = "); gr_println(x1, ctx); printf("\n"); printf("fx = "); gr_println(fx, ctx); printf("\n"); printf("fx1 = "); gr_println(fx1, ctx); printf("\n"); printf("x1fx = "); gr_println(x1fx, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR5(x, x1, fx, fx1, x1fx, ctx); gr_ctx_clear(ctx); return status; } int test_fac_fmpz_rec1(flint_rand_t state, int which) { gr_ctx_t ctx; gr_ptr fx, fx1, x1fx; fmpz_t x, x1; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); GR_TMP_INIT3(fx, fx1, x1fx, ctx); fmpz_init(x); fmpz_init(x1); if (gr_ctx_has_real_prec(ctx) == T_TRUE) { fmpz_randtest(x, state, 100); } else { if (gr_ctx_is_finite_characteristic(ctx) == T_TRUE) fmpz_randtest(x, state, 12); else fmpz_randtest(x, state, 8); } fmpz_add_ui(x1, x, 1); if (which == 0) { status |= gr_fac_fmpz(fx, x, ctx); status |= gr_fac_fmpz(fx1, x1, ctx); status |= gr_mul_fmpz(x1fx, fx, x1, ctx); } else { status |= gr_rfac_fmpz(fx, x, ctx); status |= gr_rfac_fmpz(fx1, x1, ctx); status |= gr_div_fmpz(x1fx, fx, x1, ctx); } if (status == GR_SUCCESS && gr_equal(fx1, x1fx, ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("x = "); fmpz_print(x); printf("\n"); printf("x1 = "); fmpz_print(x1); printf("\n"); printf("fx = "); gr_println(fx, ctx); printf("\n"); printf("fx1 = "); gr_println(fx1, ctx); printf("\n"); printf("x1fx = "); gr_println(x1fx, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR3(fx, fx1, x1fx, ctx); fmpz_clear(x); fmpz_clear(x1); gr_ctx_clear(ctx); return status; } int test_fac_ui_rec1(flint_rand_t state, int which) { gr_ctx_t ctx; gr_ptr fx, fx1, x1fx; ulong x, x1; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); GR_TMP_INIT3(fx, fx1, x1fx, ctx); if (gr_ctx_has_real_prec(ctx) == T_TRUE) { x = n_randtest(state); x -= (x == UWORD_MAX); } else { if (gr_ctx_is_finite_characteristic(ctx) == T_TRUE) x = n_randtest_bits(state, 12); else x = n_randtest_bits(state, 8); } x1 = x + 1; if (which == 0) { status |= gr_fac_ui(fx, x, ctx); status |= gr_fac_ui(fx1, x1, ctx); status |= gr_mul_ui(x1fx, fx, x1, ctx); } else { status |= gr_rfac_ui(fx, x, ctx); status |= gr_rfac_ui(fx1, x1, ctx); status |= gr_div_ui(x1fx, fx, x1, ctx); } if (status == GR_SUCCESS && gr_equal(fx1, x1fx, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("x = %wu", x); printf("\n"); flint_printf("x1 = %wu", x1); printf("\n"); printf("fx = "); gr_println(fx, ctx); printf("\n"); printf("fx1 = "); gr_println(fx1, ctx); printf("\n"); printf("x1fx = "); gr_println(x1fx, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR3(fx, fx1, x1fx, ctx); gr_ctx_clear(ctx); return status; } int test_fac_vec(flint_rand_t state, int which) { gr_ctx_t ctx; slong len, i; gr_ptr x, xp; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); len = n_randint(state, 100); GR_TMP_INIT_VEC(xp, len, ctx); GR_TMP_INIT(x, ctx); if (which == 0) status |= gr_fac_vec(xp, len, ctx); else status |= gr_rfac_vec(xp, len, ctx); for (i = 0; i < len; i += 1 + n_randint(state, 10)) { if (which == 0) status |= gr_fac_ui(x, i, ctx); else status |= gr_rfac_ui(x, i, ctx); if (status == GR_SUCCESS && gr_equal(x, GR_ENTRY(xp, i, ctx->sizeof_elem), ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("x = "); gr_println(x, ctx); printf("\n"); printf("xp = "); gr_println(GR_ENTRY(xp, i, ctx->sizeof_elem), ctx); printf("\n"); flint_abort(); } } GR_TMP_CLEAR(x, ctx); GR_TMP_CLEAR_VEC(xp, len, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_special_fac, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_fac_rec1(state, 0); test_fac_rec1(state, 1); } for (iter = 0; iter < 1000; iter++) { test_fac_fmpz_rec1(state, 0); test_fac_fmpz_rec1(state, 1); } for (iter = 0; iter < 1000; iter++) { test_fac_ui_rec1(state, 0); test_fac_ui_rec1(state, 1); } for (iter = 0; iter < 1000; iter++) { test_fac_vec(state, 0); test_fac_vec(state, 1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_special/test/t-fib.c000066400000000000000000000101511461254215100176540ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "gr_special.h" int test_fib_fmpz_rec1(flint_rand_t state) { gr_ctx_t ctx; gr_ptr fx, fx1, fx2, fxfx1; fmpz_t x, x1, x2; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); GR_TMP_INIT4(fx, fx1, fx2, fxfx1, ctx); fmpz_init(x); fmpz_init(x1); fmpz_init(x2); if (gr_ctx_has_real_prec(ctx) == T_TRUE || gr_ctx_is_finite_characteristic(ctx) == T_TRUE) fmpz_randtest(x, state, 100); else fmpz_randtest(x, state, 10); fmpz_add_ui(x1, x, 1); fmpz_add_ui(x2, x, 2); status |= gr_fib_fmpz(fx, x, ctx); status |= gr_fib_fmpz(fx1, x1, ctx); status |= gr_fib_fmpz(fx2, x2, ctx); status |= gr_add(fxfx1, fx, fx1, ctx); if (status == GR_SUCCESS && gr_equal(fxfx1, fx2, ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("x = "); fmpz_print(x); printf("\n"); printf("x1 = "); fmpz_print(x1); printf("\n"); printf("x2 = "); fmpz_print(x2); printf("\n"); printf("fx = "); gr_println(fx, ctx); printf("\n"); printf("fx1 = "); gr_println(fx1, ctx); printf("\n"); printf("fxfx1 = "); gr_println(fxfx1, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR4(fx, fx1, fx2, fxfx1, ctx); fmpz_clear(x); fmpz_clear(x1); fmpz_clear(x2); gr_ctx_clear(ctx); return status; } int test_fib_ui_rec1(flint_rand_t state) { gr_ctx_t ctx; gr_ptr fx, fx1, fx2, fxfx1; ulong x, x1, x2; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); GR_TMP_INIT4(fx, fx1, fx2, fxfx1, ctx); if (gr_ctx_has_real_prec(ctx) == T_TRUE || gr_ctx_is_finite_characteristic(ctx) == T_TRUE) { x = n_randtest(state); x = FLINT_MIN(x, UWORD_MAX - 2); } else { x = n_randtest_bits(state, 10); } x1 = x + 1; x2 = x + 2; status |= gr_fib_ui(fx, x, ctx); status |= gr_fib_ui(fx1, x1, ctx); status |= gr_fib_ui(fx2, x2, ctx); status |= gr_add(fxfx1, fx, fx1, ctx); if (status == GR_SUCCESS && gr_equal(fxfx1, fx2, ctx) == T_FALSE) { flint_printf("FAIL\n"); flint_printf("x = %wu", x); printf("\n"); flint_printf("x1 = %wu", x1); printf("\n"); flint_printf("x2 = %wu", x2); printf("\n"); printf("fx = "); gr_println(fx, ctx); printf("\n"); printf("fx1 = "); gr_println(fx1, ctx); printf("\n"); printf("fxfx1 = "); gr_println(fxfx1, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR4(fx, fx1, fx2, fxfx1, ctx); gr_ctx_clear(ctx); return status; } int test_fib_vec(flint_rand_t state) { gr_ctx_t ctx; slong len, i; gr_ptr x, xp; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); len = n_randint(state, 200); GR_TMP_INIT_VEC(xp, len, ctx); GR_TMP_INIT(x, ctx); status |= gr_fib_vec(xp, len, ctx); for (i = 0; i < len; i += 1 + n_randint(state, 10)) { status |= gr_fib_ui(x, i, ctx); if (status == GR_SUCCESS && gr_equal(x, GR_ENTRY(xp, i, ctx->sizeof_elem), ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("x = "); gr_println(x, ctx); printf("\n"); printf("xp = "); gr_println(GR_ENTRY(xp, i, ctx->sizeof_elem), ctx); printf("\n"); flint_abort(); } } GR_TMP_CLEAR(x, ctx); GR_TMP_CLEAR_VEC(xp, len, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_special_fib, state) { slong iter; for (iter = 0; iter < 1000; iter++) test_fib_fmpz_rec1(state); for (iter = 0; iter < 1000; iter++) test_fib_ui_rec1(state); for (iter = 0; iter < 1000; iter++) test_fib_vec(state); TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_vec.h000066400000000000000000000542751461254215100150550ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef GR_VEC_H #define GR_VEC_H #ifdef GR_VEC_INLINES_C #define GR_VEC_INLINE #else #define GR_VEC_INLINE static inline #endif #include "gr.h" #ifdef __cplusplus extern "C" { #endif void gr_vec_init(gr_vec_t vec, slong len, gr_ctx_t ctx); void gr_vec_clear(gr_vec_t vec, gr_ctx_t ctx); #define GR_VEC_ENTRY(vec, i, sz) GR_ENTRY((vec)->entries, i, sz) GR_VEC_INLINE gr_ptr gr_vec_entry_ptr(gr_vec_t vec, slong i, gr_ctx_t ctx) { return GR_VEC_ENTRY(vec, i, ctx->sizeof_elem); } GR_VEC_INLINE gr_srcptr gr_vec_entry_srcptr(const gr_vec_t vec, slong i, gr_ctx_t ctx) { return GR_VEC_ENTRY(vec, i, ctx->sizeof_elem); } GR_VEC_INLINE slong gr_vec_length(const gr_vec_t vec, gr_ctx_t ctx) { return vec->length; } void gr_vec_fit_length(gr_vec_t vec, slong len, gr_ctx_t ctx); void gr_vec_set_length(gr_vec_t vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_vec_set(gr_vec_t res, const gr_vec_t src, gr_ctx_t ctx); WARN_UNUSED_RESULT int gr_vec_append(gr_vec_t vec, gr_srcptr f, gr_ctx_t ctx); int _gr_vec_write(gr_stream_t out, gr_srcptr vec, slong len, gr_ctx_t ctx); int gr_vec_write(gr_stream_t out, const gr_vec_t vec, gr_ctx_t ctx); int _gr_vec_print(gr_srcptr vec, slong len, gr_ctx_t ctx); int gr_vec_print(const gr_vec_t vec, gr_ctx_t ctx); GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_zero(gr_ptr vec, slong len, gr_ctx_t ctx) { return GR_VEC_CONSTANT_OP(ctx, VEC_ZERO)(vec, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_set(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) { return GR_VEC_OP(ctx, VEC_SET)(res, src, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_neg(gr_ptr res, gr_srcptr src, slong len, gr_ctx_t ctx) { return GR_VEC_OP(ctx, VEC_NEG)(res, src, len, ctx); } typedef int ((*gr_method_vec_normalise_op)(slong *, gr_srcptr, slong, gr_ctx_ptr)); typedef slong ((*gr_method_vec_normalise_weak_op)(gr_srcptr, slong, gr_ctx_ptr)); #define GR_VEC_NORMALISE_OP(ctx, NAME) (((gr_method_vec_normalise_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_NORMALISE_WEAK_OP(ctx, NAME) (((gr_method_vec_normalise_weak_op *) ctx->methods)[GR_METHOD_ ## NAME]) GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_normalise(slong * res, gr_srcptr vec, slong len, gr_ctx_t ctx) { return GR_VEC_NORMALISE_OP(ctx, VEC_NORMALISE)(res, vec, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT slong _gr_vec_normalise_weak(gr_srcptr vec, slong len, gr_ctx_t ctx) { return GR_VEC_NORMALISE_WEAK_OP(ctx, VEC_NORMALISE_WEAK)(vec, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) { return GR_VEC_VEC_OP(ctx, VEC_ADD)(res, src1, src2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) { return GR_VEC_VEC_OP(ctx, VEC_SUB)(res, src1, src2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) { return GR_VEC_VEC_OP(ctx, VEC_MUL)(res, src1, src2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) { return GR_VEC_VEC_OP(ctx, VEC_DIV)(res, src1, src2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) { return GR_VEC_VEC_OP(ctx, VEC_DIVEXACT)(res, src1, src2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow(gr_ptr res, gr_srcptr src1, gr_srcptr src2, slong len, gr_ctx_t ctx) { return GR_VEC_VEC_OP(ctx, VEC_POW)(res, src1, src2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_ADD_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_SUB_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_MUL_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_DIV_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_DIVEXACT_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_POW_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_ADD_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_SUB_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_MUL_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_DIV_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_DIVEXACT_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_POW_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_UI(ctx, VEC_ADD_SCALAR_UI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_UI(ctx, VEC_SUB_SCALAR_UI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_UI(ctx, VEC_MUL_SCALAR_UI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_UI(ctx, VEC_DIV_SCALAR_UI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_UI(ctx, VEC_DIVEXACT_SCALAR_UI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow_scalar_ui(gr_ptr vec1, gr_srcptr vec2, slong len, ulong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_UI(ctx, VEC_POW_SCALAR_UI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPZ(ctx, VEC_ADD_SCALAR_FMPZ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPZ(ctx, VEC_SUB_SCALAR_FMPZ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPZ(ctx, VEC_MUL_SCALAR_FMPZ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPZ(ctx, VEC_DIV_SCALAR_FMPZ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPZ(ctx, VEC_DIVEXACT_SCALAR_FMPZ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow_scalar_fmpz(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpz_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPZ(ctx, VEC_POW_SCALAR_FMPZ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPQ(ctx, VEC_ADD_SCALAR_FMPQ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPQ(ctx, VEC_SUB_SCALAR_FMPQ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPQ(ctx, VEC_MUL_SCALAR_FMPQ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPQ(ctx, VEC_DIV_SCALAR_FMPQ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPQ(ctx, VEC_DIVEXACT_SCALAR_FMPQ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow_scalar_fmpq(gr_ptr vec1, gr_srcptr vec2, slong len, const fmpq_t c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_FMPQ(ctx, VEC_POW_SCALAR_FMPQ)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_add_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_VEC_OP(ctx, SCALAR_ADD_VEC)(vec1, c, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_sub_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_VEC_OP(ctx, SCALAR_SUB_VEC)(vec1, c, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_mul_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_VEC_OP(ctx, SCALAR_MUL_VEC)(vec1, c, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_div_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_VEC_OP(ctx, SCALAR_DIV_VEC)(vec1, c, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_VEC_OP(ctx, SCALAR_DIVEXACT_VEC)(vec1, c, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_pow_vec(gr_ptr vec1, gr_srcptr c, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_VEC_OP(ctx, SCALAR_POW_VEC)(vec1, c, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) { return GR_VEC_OP_OTHER(ctx, VEC_ADD_OTHER)(vec1, vec2, vec3, ctx3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) { return GR_VEC_OP_OTHER(ctx, VEC_SUB_OTHER)(vec1, vec2, vec3, ctx3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) { return GR_VEC_OP_OTHER(ctx, VEC_MUL_OTHER)(vec1, vec2, vec3, ctx3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) { return GR_VEC_OP_OTHER(ctx, VEC_DIV_OTHER)(vec1, vec2, vec3, ctx3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) { return GR_VEC_OP_OTHER(ctx, VEC_DIVEXACT_OTHER)(vec1, vec2, vec3, ctx3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow_other(gr_ptr vec1, gr_srcptr vec2, gr_srcptr vec3, gr_ctx_t ctx3, slong len, gr_ctx_t ctx) { return GR_VEC_OP_OTHER(ctx, VEC_POW_OTHER)(vec1, vec2, vec3, ctx3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_other_add_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) { return GR_OTHER_OP_VEC(ctx, OTHER_ADD_VEC)(vec1, vec2, ctx2, vec3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_other_sub_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) { return GR_OTHER_OP_VEC(ctx, OTHER_SUB_VEC)(vec1, vec2, ctx2, vec3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_other_mul_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) { return GR_OTHER_OP_VEC(ctx, OTHER_MUL_VEC)(vec1, vec2, ctx2, vec3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_other_div_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) { return GR_OTHER_OP_VEC(ctx, OTHER_DIV_VEC)(vec1, vec2, ctx2, vec3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_other_divexact_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) { return GR_OTHER_OP_VEC(ctx, OTHER_DIVEXACT_VEC)(vec1, vec2, ctx2, vec3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_other_pow_vec(gr_ptr vec1, gr_srcptr vec2, gr_ctx_t ctx2, gr_srcptr vec3, slong len, gr_ctx_t ctx) { return GR_OTHER_OP_VEC(ctx, OTHER_POW_VEC)(vec1, vec2, ctx2, vec3, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_add_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) { return GR_VEC_OP_SCALAR_OTHER(ctx, VEC_ADD_SCALAR_OTHER)(vec1, vec2, len, c, cctx, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sub_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) { return GR_VEC_OP_SCALAR_OTHER(ctx, VEC_SUB_SCALAR_OTHER)(vec1, vec2, len, c, cctx, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) { return GR_VEC_OP_SCALAR_OTHER(ctx, VEC_MUL_SCALAR_OTHER)(vec1, vec2, len, c, cctx, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_div_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) { return GR_VEC_OP_SCALAR_OTHER(ctx, VEC_DIV_SCALAR_OTHER)(vec1, vec2, len, c, cctx, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_divexact_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) { return GR_VEC_OP_SCALAR_OTHER(ctx, VEC_DIVEXACT_SCALAR_OTHER)(vec1, vec2, len, c, cctx, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_pow_scalar_other(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t cctx, gr_ctx_t ctx) { return GR_VEC_OP_SCALAR_OTHER(ctx, VEC_POW_SCALAR_OTHER)(vec1, vec2, len, c, cctx, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_other_add_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_OTHER_OP_VEC(ctx, SCALAR_OTHER_ADD_VEC)(vec1, c, cctx, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_other_sub_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_OTHER_OP_VEC(ctx, SCALAR_OTHER_SUB_VEC)(vec1, c, cctx, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_other_mul_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_OTHER_OP_VEC(ctx, SCALAR_OTHER_MUL_VEC)(vec1, c, cctx, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_other_div_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_OTHER_OP_VEC(ctx, SCALAR_OTHER_DIV_VEC)(vec1, c, cctx, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_other_divexact_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_OTHER_OP_VEC(ctx, SCALAR_OTHER_DIVEXACT_VEC)(vec1, c, cctx, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_scalar_other_pow_vec(gr_ptr vec1, gr_srcptr c, gr_ctx_t cctx, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_SCALAR_OTHER_OP_VEC(ctx, SCALAR_OTHER_POW_VEC)(vec1, c, cctx, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_mul_scalar_2exp_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_MUL_SCALAR_2EXP_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_addmul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_ADDMUL_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_submul_scalar(gr_ptr vec1, gr_srcptr vec2, slong len, gr_srcptr c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP(ctx, VEC_SUBMUL_SCALAR)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_addmul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_ADDMUL_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_submul_scalar_si(gr_ptr vec1, gr_srcptr vec2, slong len, slong c, gr_ctx_t ctx) { return GR_VEC_SCALAR_OP_SI(ctx, VEC_SUBMUL_SCALAR_SI)(vec1, vec2, len, c, ctx); } GR_VEC_INLINE truth_t _gr_vec_equal(gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_VEC_VEC_PREDICATE(ctx, VEC_EQUAL)(vec1, vec2, len, ctx); } GR_VEC_INLINE truth_t _gr_vec_is_zero(gr_srcptr vec, slong len, gr_ctx_t ctx) { return GR_VEC_PREDICATE(ctx, VEC_IS_ZERO)(vec, len, ctx); } typedef int ((*gr_method_vec_reduce_op)(gr_ptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_dot_op)(gr_ptr, gr_srcptr, int, gr_srcptr, gr_srcptr, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_dot_si_op)(gr_ptr, gr_srcptr, int, gr_srcptr, const slong *, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_dot_ui_op)(gr_ptr, gr_srcptr, int, gr_srcptr, const ulong *, slong, gr_ctx_ptr)); typedef int ((*gr_method_vec_dot_fmpz_op)(gr_ptr, gr_srcptr, int, gr_srcptr, const fmpz *, slong, gr_ctx_ptr)); #define GR_VEC_REDUCE_OP(ctx, NAME) (((gr_method_vec_reduce_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_DOT_OP(ctx, NAME) (((gr_method_vec_dot_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_DOT_SI_OP(ctx, NAME) (((gr_method_vec_dot_si_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_DOT_UI_OP(ctx, NAME) (((gr_method_vec_dot_ui_op *) ctx->methods)[GR_METHOD_ ## NAME]) #define GR_VEC_DOT_FMPZ_OP(ctx, NAME) (((gr_method_vec_dot_fmpz_op *) ctx->methods)[GR_METHOD_ ## NAME]) GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_sum(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { return GR_VEC_REDUCE_OP(ctx, VEC_SUM)(res, vec, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_product(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { return GR_VEC_REDUCE_OP(ctx, VEC_PRODUCT)(res, vec, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_dot(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_VEC_DOT_OP(ctx, VEC_DOT)(res, initial, subtract, vec1, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_dot_rev(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx) { return GR_VEC_DOT_OP(ctx, VEC_DOT_REV)(res, initial, subtract, vec1, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_dot_si(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const slong * vec2, slong len, gr_ctx_t ctx) { return GR_VEC_DOT_SI_OP(ctx, VEC_DOT_SI)(res, initial, subtract, vec1, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_dot_ui(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const ulong * vec2, slong len, gr_ctx_t ctx) { return GR_VEC_DOT_UI_OP(ctx, VEC_DOT_UI)(res, initial, subtract, vec1, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_dot_fmpz(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const fmpz * vec2, slong len, gr_ctx_t ctx) { return GR_VEC_DOT_FMPZ_OP(ctx, VEC_DOT_FMPZ)(res, initial, subtract, vec1, vec2, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_reciprocals(gr_ptr res, slong len, gr_ctx_t ctx) { return GR_UNARY_OP_SI(ctx, VEC_RECIPROCALS)(res, len, ctx); } GR_VEC_INLINE WARN_UNUSED_RESULT int _gr_vec_set_powers(gr_ptr res, gr_srcptr x, slong len, gr_ctx_t ctx) { return GR_VEC_OP(ctx, VEC_SET_POWERS)(res, x, len, ctx); } /* todo: could allow overloading this as well */ /* todo: worth warning about unused result? */ WARN_UNUSED_RESULT int _gr_vec_randtest(gr_ptr res, flint_rand_t state, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_sum_bsplit_parallel(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_sum_bsplit(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_sum_parallel(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_sum_serial(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_sum_generic(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_product_bsplit_parallel(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_product_bsplit(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_product_parallel(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_product_serial(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_product_generic(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx); WARN_UNUSED_RESULT int _gr_vec_step(gr_ptr vec, gr_srcptr start, gr_srcptr step, slong len, gr_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/gr_vec/000077500000000000000000000000001461254215100146675ustar00rootroot00000000000000flint-3.1.3/src/gr_vec/append.c000066400000000000000000000011561461254215100163050ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" int gr_vec_append(gr_vec_t vec, gr_srcptr f, gr_ctx_t ctx) { gr_vec_fit_length(vec, vec->length + 1, ctx); vec->length++; return gr_set(GR_ENTRY(vec->entries, vec->length - 1, ctx->sizeof_elem), f, ctx); } flint-3.1.3/src/gr_vec/clear.c000066400000000000000000000011031461254215100161140ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" void gr_vec_clear(gr_vec_t vec, gr_ctx_t ctx) { if (vec->alloc != 0) { _gr_vec_clear(vec->entries, vec->alloc, ctx); flint_free(vec->entries); } } flint-3.1.3/src/gr_vec/fit_length.c000066400000000000000000000014371461254215100171630ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" void gr_vec_fit_length(gr_vec_t vec, slong len, gr_ctx_t ctx) { slong alloc = vec->alloc; if (len > alloc) { slong sz = ctx->sizeof_elem; if (len < 2 * alloc) len = 2 * alloc; vec->entries = flint_realloc(vec->entries, len * sz); _gr_vec_init(GR_ENTRY(vec->entries, vec->alloc, sz), len - alloc, ctx); vec->alloc = len; } } flint-3.1.3/src/gr_vec/init.c000066400000000000000000000013071461254215100157770ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" void gr_vec_init(gr_vec_t vec, slong len, gr_ctx_t ctx) { vec->length = vec->alloc = len; if (len == 0) { vec->entries = NULL; } else { slong sz = ctx->sizeof_elem; vec->entries = flint_malloc(len * sz); _gr_vec_init(vec->entries, len, ctx); } } flint-3.1.3/src/gr_vec/inlines.c000066400000000000000000000007041461254215100164750ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define GR_VEC_INLINES_C #include "gr_vec.h" #undef GR_VEC_INLINES_C flint-3.1.3/src/gr_vec/product.c000066400000000000000000000106261461254215100165200ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "gr_vec.h" int _gr_vec_parallel_reduce(gr_ptr res, gr_method_vec_reduce_op basecase, gr_srcptr vec, slong n, gr_ctx_t ctx, int thread_limit, int flags); int _gr_vec_product_parallel(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { return _gr_vec_parallel_reduce(res, (gr_method_vec_reduce_op) _gr_vec_product, vec, len, ctx, -1, FLINT_PARALLEL_UNIFORM); } typedef struct { gr_srcptr vec; gr_ctx_struct * ctx; } bsplit_args_t; typedef struct { gr_ptr res; int status; } bsplit_res_t; static void bsplit_init(bsplit_res_t * x, bsplit_args_t * args) { x->res = gr_heap_init(args->ctx); x->status = GR_SUCCESS; } static void bsplit_clear(bsplit_res_t * x, bsplit_args_t * args) { gr_heap_clear(x->res, args->ctx); } static void bsplit_basecase(bsplit_res_t * res, slong a, slong b, bsplit_args_t * args) { res->status = _gr_vec_product(res->res, GR_ENTRY(args->vec, a, args->ctx->sizeof_elem), b - a, args->ctx); } static void bsplit_merge(bsplit_res_t * res, bsplit_res_t * left, bsplit_res_t * right, bsplit_args_t * args) { res->status = left->status | right->status; if (res->status == GR_SUCCESS) res->status |= gr_mul(res->res, left->res, right->res, args->ctx); } int _gr_vec_product_bsplit_parallel(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx) { bsplit_args_t args; bsplit_res_t _res; args.vec = vec; args.ctx = ctx; _res.res = res; _res.status = 0; flint_parallel_binary_splitting(&_res, (bsplit_basecase_func_t) bsplit_basecase, (bsplit_merge_func_t) bsplit_merge, sizeof(bsplit_res_t), (bsplit_init_func_t) bsplit_init, (bsplit_clear_func_t) bsplit_clear, &args, 0, len, basecase_cutoff, -1, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); return _res.status; } int _gr_vec_product_bsplit(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx) { if (len < basecase_cutoff) { return _gr_vec_product(res, vec, len, ctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= _gr_vec_product_bsplit(res, vec, len / 2, basecase_cutoff, ctx); status |= _gr_vec_product_bsplit(t, GR_ENTRY(vec, len / 2, ctx->sizeof_elem), len - len / 2, basecase_cutoff, ctx); status |= gr_mul(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } } int _gr_vec_product_serial(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); int status; slong i, sz; if (len <= 2) { if (len == 2) return mul(res, vec, GR_ENTRY(vec, 1, ctx->sizeof_elem), ctx); else if (len == 1) return gr_set(res, vec, ctx); else return gr_one(res, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; status |= mul(res, GR_ENTRY(vec, 0, sz), GR_ENTRY(vec, 1, sz), ctx); for (i = 2; i < len; i++) status |= mul(res, res, GR_ENTRY(vec, i, sz), ctx); return status; } int _gr_vec_product_generic(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_binary_op mul = GR_BINARY_OP(ctx, MUL); int status; slong i, sz; if (len <= 2) { if (len == 2) return mul(res, vec, GR_ENTRY(vec, 1, ctx->sizeof_elem), ctx); else if (len == 1) return gr_set(res, vec, ctx); else return gr_one(res, ctx); } /* Todo: algorithm selection. */ if (len > 20 && gr_ctx_is_finite(ctx) != T_TRUE) { if (len > 500 && gr_ctx_is_threadsafe(ctx) == T_TRUE) return _gr_vec_product_bsplit_parallel(res, vec, len, 500, ctx); else return _gr_vec_product_bsplit(res, vec, len, 20, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; status |= mul(res, GR_ENTRY(vec, 0, sz), GR_ENTRY(vec, 1, sz), ctx); for (i = 2; i < len; i++) status |= mul(res, res, GR_ENTRY(vec, i, sz), ctx); return status; } flint-3.1.3/src/gr_vec/randtest.c000066400000000000000000000015021461254215100166550ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "gr_vec.h" int _gr_vec_randtest(gr_ptr res, flint_rand_t state, slong len, gr_ctx_t ctx) { int status; slong i, sz; sz = ctx->sizeof_elem; status = GR_SUCCESS; for (i = 0; i < len; i++) { if (n_randint(state, 2)) status |= gr_zero(GR_ENTRY(res, i, sz), ctx); else status |= gr_randtest(GR_ENTRY(res, i, sz), state, ctx); } return status; } flint-3.1.3/src/gr_vec/set.c000066400000000000000000000012471461254215100156320ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" int gr_vec_set(gr_vec_t res, const gr_vec_t src, gr_ctx_t ctx) { int status = GR_SUCCESS; if (res != src) { gr_vec_set_length(res, src->length, ctx); status = _gr_vec_set(res->entries, src->entries, src->length, ctx); } return status; } flint-3.1.3/src/gr_vec/set_length.c000066400000000000000000000016061461254215100171720ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" void gr_vec_set_length(gr_vec_t vec, slong len, gr_ctx_t ctx) { if (vec->length > len) { /* potentially free no longer used elements */ GR_MUST_SUCCEED(_gr_vec_zero(GR_ENTRY(vec->entries, len, ctx->sizeof_elem), vec->length - len, ctx)); } else if (vec->length < len) { gr_vec_fit_length(vec, len, ctx); GR_MUST_SUCCEED(_gr_vec_zero(GR_ENTRY(vec->entries, vec->length, ctx->sizeof_elem), len - vec->length, ctx)); } vec->length = len; } flint-3.1.3/src/gr_vec/step.c000066400000000000000000000015671461254215100160170ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "gr_vec.h" /* todo: with floats, prefer multiplying to adding */ int _gr_vec_step(gr_ptr vec, gr_srcptr start, gr_srcptr step, slong len, gr_ctx_t ctx) { gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem;; if (len <= 0) return GR_SUCCESS; status |= gr_set(vec, start, ctx); for (i = 1; i < len; i++) status |= add(GR_ENTRY(vec, i, sz), GR_ENTRY(vec, i - 1, sz), step, ctx); return status; } flint-3.1.3/src/gr_vec/sum.c000066400000000000000000000165271461254215100156520ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "gr_vec.h" typedef struct { gr_method_vec_reduce_op f; gr_srcptr vec; gr_ptr res; slong a; slong b; slong step; gr_ctx_struct * ctx; int status; } work_chunk_t; static void worker(void * _work) { work_chunk_t work = *((work_chunk_t *) _work); int status = GR_SUCCESS; status |= work.f(work.res, GR_ENTRY(work.vec, work.a, work.ctx->sizeof_elem), work.b - work.a, work.ctx); work.status = status; } int _gr_vec_parallel_reduce(gr_ptr res, gr_method_vec_reduce_op basecase, gr_srcptr vec, slong n, gr_ctx_t ctx, int thread_limit, int flags) { int status = GR_SUCCESS; if (thread_limit <= 0) thread_limit = flint_get_num_threads(); thread_limit = FLINT_MIN(thread_limit, n / 2); if (thread_limit <= 1) { return basecase(res, vec, n, ctx); } else { slong i, num_threads, num_workers; thread_pool_handle * handles; num_workers = flint_request_threads(&handles, thread_limit); num_threads = num_workers + 1; if (flags & FLINT_PARALLEL_VERBOSE) flint_printf("parallel_do with num_threads = %wd\n", num_threads); if (num_workers < 1) { flint_give_back_threads(handles, num_workers); return basecase(res, vec, n, ctx); } else { work_chunk_t * work; slong chunk_size; gr_ptr results; TMP_INIT; TMP_START; work = TMP_ALLOC(num_threads * sizeof(work_chunk_t)); results = TMP_ALLOC(num_threads * ctx->sizeof_elem); _gr_vec_init(results, num_threads, ctx); chunk_size = (n + num_threads - 1) / num_threads; for (i = 0; i < num_threads; i++) { work[i].f = basecase; work[i].vec = vec; work[i].res = GR_ENTRY(results, i, ctx->sizeof_elem); work[i].a = i * chunk_size; work[i].b = FLINT_MIN((i + 1) * chunk_size, n); work[i].step = 1; work[i].ctx = ctx; work[i].status = GR_SUCCESS; } if ((flags & FLINT_PARALLEL_VERBOSE)) { for (i = 0; i < num_threads; i++) { flint_printf("thread #%wd allocated a = %wd, b = %wd, step = %wd\n", i, work[i].a, work[i].b, work[i].step); } } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, worker, &work[i]); worker(&work[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); for (i = 0; i < num_workers; i++) status |= work[i].status; status |= basecase(res, results, num_threads, ctx); _gr_vec_clear(results, num_threads, ctx); flint_give_back_threads(handles, num_workers); TMP_END; } return status; } } int _gr_vec_sum_parallel(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { return _gr_vec_parallel_reduce(res, (gr_method_vec_reduce_op) _gr_vec_sum, vec, len, ctx, -1, FLINT_PARALLEL_UNIFORM); } typedef struct { gr_srcptr vec; gr_ctx_struct * ctx; } bsplit_args_t; typedef struct { gr_ptr res; int status; } bsplit_res_t; static void bsplit_init(bsplit_res_t * x, bsplit_args_t * args) { x->res = gr_heap_init(args->ctx); x->status = GR_SUCCESS; } static void bsplit_clear(bsplit_res_t * x, bsplit_args_t * args) { gr_heap_clear(x->res, args->ctx); } static void bsplit_basecase(bsplit_res_t * res, slong a, slong b, bsplit_args_t * args) { res->status = _gr_vec_sum(res->res, GR_ENTRY(args->vec, a, args->ctx->sizeof_elem), b - a, args->ctx); } static void bsplit_merge(bsplit_res_t * res, bsplit_res_t * left, bsplit_res_t * right, bsplit_args_t * args) { res->status = left->status | right->status; if (res->status == GR_SUCCESS) res->status |= gr_add(res->res, left->res, right->res, args->ctx); } int _gr_vec_sum_bsplit_parallel(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx) { bsplit_args_t args; bsplit_res_t _res; args.vec = vec; args.ctx = ctx; _res.res = res; _res.status = 0; flint_parallel_binary_splitting(&_res, (bsplit_basecase_func_t) bsplit_basecase, (bsplit_merge_func_t) bsplit_merge, sizeof(bsplit_res_t), (bsplit_init_func_t) bsplit_init, (bsplit_clear_func_t) bsplit_clear, &args, 0, len, basecase_cutoff, -1, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); return _res.status; } int _gr_vec_sum_bsplit(gr_ptr res, gr_srcptr vec, slong len, slong basecase_cutoff, gr_ctx_t ctx) { if (len < basecase_cutoff) { return _gr_vec_sum(res, vec, len, ctx); } else { gr_ptr t; int status = GR_SUCCESS; GR_TMP_INIT(t, ctx); status |= _gr_vec_sum_bsplit(res, vec, len / 2, basecase_cutoff, ctx); status |= _gr_vec_sum_bsplit(t, GR_ENTRY(vec, len / 2, ctx->sizeof_elem), len - len / 2, basecase_cutoff, ctx); status |= gr_add(res, res, t, ctx); GR_TMP_CLEAR(t, ctx); return status; } } int _gr_vec_sum_serial(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; if (len <= 2) { if (len == 2) return add(res, vec, GR_ENTRY(vec, 1, ctx->sizeof_elem), ctx); else if (len == 1) return gr_set(res, vec, ctx); else return gr_zero(res, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; status |= add(res, GR_ENTRY(vec, 0, sz), GR_ENTRY(vec, 1, sz), ctx); for (i = 2; i < len; i++) status |= add(res, res, GR_ENTRY(vec, i, sz), ctx); return status; } int _gr_vec_sum_generic(gr_ptr res, gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_method_binary_op add = GR_BINARY_OP(ctx, ADD); int status; slong i, sz; if (len <= 2) { if (len == 2) return add(res, vec, GR_ENTRY(vec, 1, ctx->sizeof_elem), ctx); else if (len == 1) return gr_set(res, vec, ctx); else return gr_zero(res, ctx); } /* Todo: algorithm selection. Binary splitting is needed to get optimal complexity when adding fractions. The cutoff should be lower than this when we actually have fractions; on the other hand, we don't want to introduce overhead for rings with cheap addition. */ if (len > 100 && gr_ctx_is_finite(ctx) != T_TRUE) { return _gr_vec_sum_bsplit(res, vec, len, 100, ctx); } sz = ctx->sizeof_elem; status = GR_SUCCESS; status |= add(res, GR_ENTRY(vec, 0, sz), GR_ENTRY(vec, 1, sz), ctx); for (i = 2; i < len; i++) status |= add(res, res, GR_ENTRY(vec, i, sz), ctx); return status; } flint-3.1.3/src/gr_vec/test/000077500000000000000000000000001461254215100156465ustar00rootroot00000000000000flint-3.1.3/src/gr_vec/test/main.c000066400000000000000000000014611461254215100167400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-product.c" #include "t-sum.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(gr_vec_product), TEST_FUNCTION(gr_vec_sum) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/gr_vec/test/t-product.c000066400000000000000000000043631461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_vec.h" int test_product(flint_rand_t state, int which) { gr_ctx_t ctx; gr_ptr vec, x1, x2; slong len; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); if (gr_ctx_is_finite(ctx) == T_TRUE || gr_ctx_has_real_prec(ctx) == T_TRUE) len = n_randint(state, 120); else len = n_randint(state, 20); GR_TMP_INIT_VEC(vec, len, ctx); GR_TMP_INIT2(x1, x2, ctx); status |= _gr_vec_randtest(vec, state, len, ctx); status |= _gr_vec_product_serial(x1, vec, len, ctx); if (gr_ctx_is_threadsafe(ctx) == T_TRUE && n_randint(state, 4) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); switch (which) { case 0: status |= _gr_vec_product_bsplit(x2, vec, len, 2 + n_randint(state, 8), ctx); break; case 1: status |= _gr_vec_product_bsplit_parallel(x2, vec, len, 2 + n_randint(state, 8), ctx); break; case 2: status |= _gr_vec_product_parallel(x2, vec, len, ctx); break; default: status |= _gr_vec_product(x2, vec, len, ctx); break; } if (status == GR_SUCCESS && gr_equal(x1, x2, ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("which = %d\n", which); printf("vec = "); _gr_vec_print(vec, len, ctx); printf("\n"); printf("x1 = "); gr_println(x1, ctx); printf("\n"); printf("x2 = "); gr_println(x2, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR2(x1, x2, ctx); GR_TMP_CLEAR_VEC(vec, len, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_vec_product, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_product(state, 0); test_product(state, 1); test_product(state, 2); test_product(state, 3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_vec/test/t-sum.c000066400000000000000000000043071461254215100170630ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "gr_vec.h" int test_sum(flint_rand_t state, int which) { gr_ctx_t ctx; gr_ptr vec, x1, x2; slong len; int status = GR_SUCCESS; gr_ctx_init_random(ctx, state); if (gr_ctx_is_finite(ctx) == T_TRUE || gr_ctx_has_real_prec(ctx) == T_TRUE) len = n_randint(state, 120); else len = n_randint(state, 20); GR_TMP_INIT_VEC(vec, len, ctx); GR_TMP_INIT2(x1, x2, ctx); status |= _gr_vec_randtest(vec, state, len, ctx); status |= _gr_vec_sum_serial(x1, vec, len, ctx); if (gr_ctx_is_threadsafe(ctx) == T_TRUE && n_randint(state, 4) == 0) flint_set_num_threads(1 + n_randint(state, 4)); else flint_set_num_threads(1); switch (which) { case 0: status |= _gr_vec_sum_bsplit(x2, vec, len, 2 + n_randint(state, 8), ctx); break; case 1: status |= _gr_vec_sum_bsplit_parallel(x2, vec, len, 2 + n_randint(state, 8), ctx); break; case 2: status |= _gr_vec_sum_parallel(x2, vec, len, ctx); break; default: status |= _gr_vec_sum(x2, vec, len, ctx); break; } if (status == GR_SUCCESS && gr_equal(x1, x2, ctx) == T_FALSE) { flint_printf("FAIL\n"); printf("which = %d\n", which); printf("vec = "); _gr_vec_print(vec, len, ctx); printf("\n"); printf("x1 = "); gr_println(x1, ctx); printf("\n"); printf("x2 = "); gr_println(x2, ctx); printf("\n"); flint_abort(); } GR_TMP_CLEAR2(x1, x2, ctx); GR_TMP_CLEAR_VEC(vec, len, ctx); gr_ctx_clear(ctx); return status; } TEST_FUNCTION_START(gr_vec_sum, state) { slong iter; for (iter = 0; iter < 1000; iter++) { test_sum(state, 0); test_sum(state, 1); test_sum(state, 2); test_sum(state, 3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/gr_vec/write.c000066400000000000000000000023741461254215100161730ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gr_vec.h" int _gr_vec_write(gr_stream_t out, gr_srcptr vec, slong len, gr_ctx_t ctx) { int status = GR_SUCCESS; slong i, sz = ctx->sizeof_elem; gr_stream_write(out, "["); for (i = 0; i < len; i++) { status |= gr_write(out, GR_ENTRY(vec, i, sz), ctx); if (i < len - 1) gr_stream_write(out, ", "); } gr_stream_write(out, "]"); return status; } int gr_vec_write(gr_stream_t out, const gr_vec_t vec, gr_ctx_t ctx) { return _gr_vec_write(out, vec->entries, vec->length, ctx); } int _gr_vec_print(gr_srcptr vec, slong len, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); return _gr_vec_write(out, vec, len, ctx); } int gr_vec_print(const gr_vec_t vec, gr_ctx_t ctx) { gr_stream_t out; gr_stream_init_file(out, stdout); return gr_vec_write(out, vec, ctx); } flint-3.1.3/src/hypgeom.h000066400000000000000000000024221461254215100152430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef HYPGEOM_H #define HYPGEOM_H #include "fmpz_types.h" #include "arb_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz_poly_t A; fmpz_poly_t B; fmpz_poly_t P; fmpz_poly_t Q; /* precomputation data */ int have_precomputed; slong r; slong boundC; slong boundD; slong boundK; mag_t MK; } hypgeom_struct; typedef hypgeom_struct hypgeom_t[1]; void hypgeom_init(hypgeom_t hyp); void hypgeom_clear(hypgeom_t hyp); void hypgeom_precompute(hypgeom_t hyp); slong hypgeom_estimate_terms(const mag_t z, int r, slong prec); slong hypgeom_bound(mag_t error, int r, slong C, slong D, slong K, const mag_t TK, const mag_t z, slong prec); void arb_hypgeom_sum(arb_t P, arb_t Q, const hypgeom_t hyp, slong n, slong prec); void arb_hypgeom_infsum(arb_t P, arb_t Q, hypgeom_t hyp, slong target_prec, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/hypgeom/000077500000000000000000000000001461254215100150725ustar00rootroot00000000000000flint-3.1.3/src/hypgeom/bound.c000066400000000000000000000102501461254215100163430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arf.h" #include "hypgeom.h" slong hypgeom_root_bound(const mag_t z, int r) { if (r == 0) { return 0; } else { arf_t t; slong v; arf_init(t); arf_set_mag(t, z); arf_root(t, t, r, MAG_BITS, ARF_RND_UP); arf_add_ui(t, t, 1, MAG_BITS, ARF_RND_UP); v = arf_get_si(t, ARF_RND_UP); arf_clear(t); return v; } } /* Given T(K), compute bound for T(n) z^n. We need to multiply by z^n * 1/rf(K+1,m)^r * (rf(K+1,m)/rf(K+1-A,m)) * (rf(K+1-B,m)/rf(K+1-2B,m)) where m = n - K. This is equal to z^n * (K+A)! (K-2B)! (K-B+m)! ----------------------- * ((K+m)! / K!)^(1-r) (K-B)! (K-A+m)! (K-2B+m)! */ void hypgeom_term_bound(mag_t Tn, const mag_t TK, slong K, slong A, slong B, int r, const mag_t z, slong n) { mag_t t, u, num; slong m; mag_init(t); mag_init(u); mag_init(num); m = n - K; if (m < 0) { flint_throw(FLINT_ERROR, "hypgeom term bound\n"); } /* TK * z^n */ mag_pow_ui(t, z, n); mag_mul(num, TK, t); /* numerator: (K+A)! (K-2B)! (K-B+m)! */ mag_fac_ui(t, K+A); mag_mul(num, num, t); mag_fac_ui(t, K-2*B); mag_mul(num, num, t); mag_fac_ui(t, K-B+m); mag_mul(num, num, t); /* denominator: (K-B)! (K-A+m)! (K-2B+m)! */ mag_rfac_ui(t, K-B); mag_mul(num, num, t); mag_rfac_ui(t, K-A+m); mag_mul(num, num, t); mag_rfac_ui(t, K-2*B+m); mag_mul(num, num, t); /* ((K+m)! / K!)^(1-r) */ if (r == 0) { mag_fac_ui(t, K+m); mag_mul(num, num, t); mag_rfac_ui(t, K); mag_mul(num, num, t); } else if (r != 1) { mag_fac_ui(t, K); mag_rfac_ui(u, K+m); mag_mul(t, t, u); mag_pow_ui(t, t, r-1); mag_mul(num, num, t); } mag_set(Tn, num); mag_clear(t); mag_clear(u); mag_clear(num); } slong hypgeom_bound(mag_t error, int r, slong A, slong B, slong K, const mag_t TK, const mag_t z, slong tol_2exp) { mag_t Tn, t, u, one, tol, num, den; slong n, m; mag_init(Tn); mag_init(t); mag_init(u); mag_init(one); mag_init(tol); mag_init(num); mag_init(den); mag_one(one); mag_set_ui_2exp_si(tol, UWORD(1), -tol_2exp); /* approximate number of needed terms */ n = hypgeom_estimate_terms(z, r, tol_2exp); /* required for 1 + O(1/k) part to be decreasing */ n = FLINT_MAX(n, K + 1); /* required for z^k / (k!)^r to be decreasing */ m = hypgeom_root_bound(z, r); n = FLINT_MAX(n, m); /* We now have |R(k)| <= G(k) where G(k) is monotonically decreasing, and can bound the tail using a geometric series as soon as soon as G(k) < 1. */ /* bound T(n-1) */ hypgeom_term_bound(Tn, TK, K, A, B, r, z, n-1); while (1) { /* bound R(n) */ mag_mul_ui(num, z, n); mag_mul_ui(num, num, n - B); mag_set_ui_lower(den, n - A); mag_mul_ui_lower(den, den, n - 2*B); if (r != 0) { mag_set_ui_lower(u, n); mag_pow_ui_lower(u, u, r); mag_mul_lower(den, den, u); } mag_div(t, num, den); /* multiply bound for T(n-1) by bound for R(n) to bound T(n) */ mag_mul(Tn, Tn, t); /* geometric series termination check */ /* u = max(1-t, 0), rounding down [lower bound] */ mag_sub_lower(u, one, t); if (!mag_is_zero(u)) { mag_div(u, Tn, u); if (mag_cmp(u, tol) < 0) { mag_set(error, u); break; } } /* move on to next term */ n++; } mag_clear(Tn); mag_clear(t); mag_clear(u); mag_clear(one); mag_clear(tol); mag_clear(num); mag_clear(den); return n; } flint-3.1.3/src/hypgeom/estimate_terms_d.c000066400000000000000000000023741461254215100205740ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" #include "hypgeom.h" #define LOG2 0.69314718055994530942 #define EXP1 2.7182818284590452354 static inline double d_root(double x, int r) { if (r == 1) return x; if (r == 2) return sqrt(x); return pow(x, 1. / r); } slong hypgeom_estimate_terms(const mag_t z, int r, slong prec) { double y, t; t = mag_get_d(z); if (t == 0) return 1; if (r == 0) { if (t >= 1) { flint_throw(FLINT_ERROR, "z must be smaller than 1\n"); } y = (log(1-t) - prec * LOG2) / log(t) + 1; } else { y = (prec * LOG2) / (d_root(t, r) * EXP1 * r); y = (prec * LOG2) / (r * d_lambertw(y)) + 1; } if (y >= (double) (WORD_MAX / 2)) { flint_throw(FLINT_ERROR, "error: series will converge too slowly\n"); } return y; } flint-3.1.3/src/hypgeom/init.c000066400000000000000000000014731461254215100162060ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "mag.h" #include "hypgeom.h" void hypgeom_init(hypgeom_t hyp) { fmpz_poly_init(hyp->A); fmpz_poly_init(hyp->B); fmpz_poly_init(hyp->P); fmpz_poly_init(hyp->Q); mag_init(hyp->MK); hyp->have_precomputed = 0; } void hypgeom_clear(hypgeom_t hyp) { fmpz_poly_clear(hyp->A); fmpz_poly_clear(hyp->B); fmpz_poly_clear(hyp->P); fmpz_poly_clear(hyp->Q); mag_clear(hyp->MK); } flint-3.1.3/src/hypgeom/precompute.c000066400000000000000000000065501461254215100174270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "mag.h" #include "hypgeom.h" /* Compute a pure ratio P2(k)/Q2(k) for the term A(k)/B(k) * [P(1)P(2)...P(k)] / [Q(1)Q(2)...Q(k)] */ void hypgeom_standardize(fmpz_poly_t P2, fmpz_poly_t Q2, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t P, const fmpz_poly_t Q) { fmpz_t s; fmpz_poly_t T; fmpz_init(s); fmpz_poly_init(T); fmpz_set_si(s, -WORD(1)); /* P = A * B(k-1) * P */ fmpz_poly_taylor_shift(T, B, s); fmpz_poly_mul(P2, A, T); fmpz_poly_mul(P2, P2, P); /* Q = B * A(k-1) * Q */ fmpz_poly_taylor_shift(T, A, s); fmpz_poly_mul(Q2, B, T); fmpz_poly_mul(Q2, Q2, Q); fmpz_clear(s); fmpz_poly_clear(T); } /* quotient of absolute value, rounded up */ static inline void fmpz_cdiv_abs_q(fmpz_t q, const fmpz_t x, const fmpz_t y) { if (fmpz_sgn(x) == fmpz_sgn(y)) { fmpz_cdiv_q(q, x, y); } else { fmpz_fdiv_q(q, x, y); fmpz_neg(q, q); } } slong hypgeom_root_norm(const fmpz_poly_t P) { slong res, i, p; fmpz_t t, A; fmpz_init(A); fmpz_init(t); p = fmpz_poly_degree(P); fmpz_zero(A); for (i = 1; i <= p; i++) { fmpz_cdiv_abs_q(t, P->coeffs + p - i, P->coeffs + p); fmpz_root(t, t, i); fmpz_add_ui(t, t, 1); if (fmpz_cmp(t, A) > 0) fmpz_swap(t, A); } if (!fmpz_fits_si(A)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); res = fmpz_get_si(A); fmpz_clear(A); fmpz_clear(t); return res; } static inline void fmpz_poly_evaluate_si(fmpz_t y, const fmpz_poly_t poly, slong x) { fmpz_set_si(y, x); fmpz_poly_evaluate_fmpz(y, poly, y); } void _hypgeom_precompute(hypgeom_t hyp, const fmpz_poly_t P, const fmpz_poly_t Q) { slong k; fmpz_t t; fmpz_init(t); hyp->r = fmpz_poly_degree(Q) - fmpz_poly_degree(P); hyp->boundC = hypgeom_root_norm(P); hyp->boundD = hypgeom_root_norm(Q); hyp->boundK = 1 + FLINT_MAX(hyp->boundC, 2 * hyp->boundD); mag_one(hyp->MK); for (k = 1; k <= hyp->boundK; k++) { fmpz_poly_evaluate_si(t, P, k); mag_mul_fmpz(hyp->MK, hyp->MK, t); fmpz_poly_evaluate_si(t, Q, k); mag_div_fmpz(hyp->MK, hyp->MK, t); } fmpz_clear(t); } void hypgeom_precompute(hypgeom_t hyp) { if (fmpz_poly_is_one(hyp->A) && fmpz_poly_is_one(hyp->B)) { _hypgeom_precompute(hyp, hyp->P, hyp->Q); } else { fmpz_poly_t P2, Q2; fmpz_poly_init(P2); fmpz_poly_init(Q2); hypgeom_standardize(P2, Q2, hyp->A, hyp->B, hyp->P, hyp->Q); _hypgeom_precompute(hyp, P2, Q2); { fmpz_t t; fmpz_init(t); fmpz_poly_evaluate_si(t, hyp->A, 0); mag_mul_fmpz(hyp->MK, hyp->MK, t); fmpz_poly_evaluate_si(t, hyp->B, 0); mag_div_fmpz(hyp->MK, hyp->MK, t); fmpz_clear(t); } fmpz_poly_clear(P2); fmpz_poly_clear(Q2); } } flint-3.1.3/src/hypgeom/sum.c000066400000000000000000000167311461254215100160520ustar00rootroot00000000000000/* Copyright (C) 2012, 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz_poly.h" #include "arb.h" #include "hypgeom.h" static inline void fmpz_poly_evaluate_si(fmpz_t y, const fmpz_poly_t poly, slong x) { fmpz_set_si(y, x); fmpz_poly_evaluate_fmpz(y, poly, y); } static void bsplit_recursive_fmpz(fmpz_t P, fmpz_t Q, fmpz_t B, fmpz_t T, const hypgeom_t hyp, slong a, slong b, int cont) { if (b - a == 1) { if (a == 0) { fmpz_one(P); fmpz_one(Q); } else { fmpz_poly_evaluate_si(P, hyp->P, a); fmpz_poly_evaluate_si(Q, hyp->Q, a); } fmpz_poly_evaluate_si(B, hyp->B, a); fmpz_poly_evaluate_si(T, hyp->A, a); fmpz_mul(T, T, P); } else { slong m; fmpz_t P2, Q2, B2, T2; m = (a + b) / 2; fmpz_init(P2); fmpz_init(Q2); fmpz_init(B2); fmpz_init(T2); bsplit_recursive_fmpz(P, Q, B, T, hyp, a, m, 1); bsplit_recursive_fmpz(P2, Q2, B2, T2, hyp, m, b, 1); if (fmpz_is_one(B) && fmpz_is_one(B2)) { fmpz_mul(T, T, Q2); fmpz_addmul(T, P, T2); } else { fmpz_mul(T, T, B2); fmpz_mul(T, T, Q2); fmpz_mul(T2, T2, B); fmpz_addmul(T, P, T2); } fmpz_mul(B, B, B2); fmpz_mul(Q, Q, Q2); if (cont) fmpz_mul(P, P, P2); fmpz_clear(P2); fmpz_clear(Q2); fmpz_clear(B2); fmpz_clear(T2); } } typedef struct { arb_struct P; arb_struct Q; arb_struct B; arb_struct T; slong a; slong b; } bsplit_res_t; typedef struct { const hypgeom_struct * hyp; slong prec; slong a; slong b; } bsplit_args_t; static void bsplit_init(bsplit_res_t * x, void * args) { arb_init(&x->P); arb_init(&x->Q); arb_init(&x->B); arb_init(&x->T); } static void bsplit_clear(bsplit_res_t * x, void * args) { arb_clear(&x->P); arb_clear(&x->Q); arb_clear(&x->B); arb_clear(&x->T); } static void bsplit_basecase(bsplit_res_t * res, slong a, slong b, bsplit_args_t * args) { fmpz_t PP, QQ, BB, TT; int cont; fmpz_init(PP); fmpz_init(QQ); fmpz_init(BB); fmpz_init(TT); cont = (b != args->b); bsplit_recursive_fmpz(PP, QQ, BB, TT, args->hyp, a, b, cont); arb_set_fmpz(&res->P, PP); arb_set_fmpz(&res->Q, QQ); arb_set_fmpz(&res->B, BB); arb_set_fmpz(&res->T, TT); res->a = a; res->b = b; fmpz_clear(PP); fmpz_clear(QQ); fmpz_clear(BB); fmpz_clear(TT); } /* res = left */ static void bsplit_merge(bsplit_res_t * res, bsplit_res_t * left, bsplit_res_t * right, bsplit_args_t * args) { arb_ptr P = &res->P; arb_ptr Q = &res->Q; arb_ptr B = &res->B; arb_ptr T = &res->T; arb_ptr P2 = &right->P; arb_ptr Q2 = &right->Q; arb_ptr B2 = &right->B; arb_ptr T2 = &right->T; slong prec = args->prec; slong b = right->b; int cont = b != args->b; if (res != left) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (arb_is_one(B) && arb_is_one(B2)) { arb_mul(T, T, Q2, prec); arb_addmul(T, P, T2, prec); } else { arb_mul(T, T, B2, prec); arb_mul(T, T, Q2, prec); arb_mul(T2, T2, B, prec); arb_addmul(T, P, T2, prec); } arb_mul(B, B, B2, prec); arb_mul(Q, Q, Q2, prec); if (cont) arb_mul(P, P, P2, prec); res->b = right->b; } #define WANT_PARALLEL 1 static void bsplit_recursive_arb(arb_t P, arb_t Q, arb_t B, arb_t T, const hypgeom_t hyp, slong a, slong b, int cont, slong prec) { if (WANT_PARALLEL) { bsplit_res_t res; bsplit_args_t args; res.P = *P; res.Q = *Q; res.B = *B; res.T = *T; args.hyp = hyp; args.prec = prec; args.a = a; args.b = b; flint_parallel_binary_splitting(&res, (bsplit_basecase_func_t) bsplit_basecase, (bsplit_merge_func_t) bsplit_merge, sizeof(bsplit_res_t), (bsplit_init_func_t) bsplit_init, (bsplit_clear_func_t) bsplit_clear, &args, a, b, 4, -1, FLINT_PARALLEL_BSPLIT_LEFT_INPLACE); *P = res.P; *Q = res.Q; *B = res.B; *T = res.T; } else { if (b - a < 4) { fmpz_t PP, QQ, BB, TT; fmpz_init(PP); fmpz_init(QQ); fmpz_init(BB); fmpz_init(TT); bsplit_recursive_fmpz(PP, QQ, BB, TT, hyp, a, b, cont); arb_set_fmpz(P, PP); arb_set_fmpz(Q, QQ); arb_set_fmpz(B, BB); arb_set_fmpz(T, TT); fmpz_clear(PP); fmpz_clear(QQ); fmpz_clear(BB); fmpz_clear(TT); } else { slong m; arb_t P2, Q2, B2, T2; m = (a + b) / 2; arb_init(P2); arb_init(Q2); arb_init(B2); arb_init(T2); bsplit_recursive_arb(P, Q, B, T, hyp, a, m, 1, prec); bsplit_recursive_arb(P2, Q2, B2, T2, hyp, m, b, 1, prec); if (arb_is_one(B) && arb_is_one(B2)) { arb_mul(T, T, Q2, prec); arb_addmul(T, P, T2, prec); } else { arb_mul(T, T, B2, prec); arb_mul(T, T, Q2, prec); arb_mul(T2, T2, B, prec); arb_addmul(T, P, T2, prec); } arb_mul(B, B, B2, prec); arb_mul(Q, Q, Q2, prec); if (cont) arb_mul(P, P, P2, prec); arb_clear(P2); arb_clear(Q2); arb_clear(B2); arb_clear(T2); } } } void arb_hypgeom_sum(arb_t P, arb_t Q, const hypgeom_t hyp, slong n, slong prec) { if (n < 1) { arb_zero(P); arb_one(Q); } else { arb_t B, T; arb_init(B); arb_init(T); bsplit_recursive_arb(P, Q, B, T, hyp, 0, n, 0, prec); if (!arb_is_one(B)) arb_mul(Q, Q, B, prec); arb_swap(P, T); arb_clear(B); arb_clear(T); } } void arb_hypgeom_infsum(arb_t P, arb_t Q, hypgeom_t hyp, slong target_prec, slong prec) { mag_t err, z; slong n; mag_init(err); mag_init(z); mag_set_fmpz(z, hyp->P->coeffs + hyp->P->length - 1); mag_div_fmpz(z, z, hyp->Q->coeffs + hyp->Q->length - 1); if (!hyp->have_precomputed) { hypgeom_precompute(hyp); hyp->have_precomputed = 1; } n = hypgeom_bound(err, hyp->r, hyp->boundC, hyp->boundD, hyp->boundK, hyp->MK, z, target_prec); arb_hypgeom_sum(P, Q, hyp, n, prec); if (arf_sgn(arb_midref(Q)) < 0) { arb_neg(P, P); arb_neg(Q, Q); } /* We have p/q = s + err i.e. (p + q*err)/q = s */ { mag_t u; mag_init(u); arb_get_mag(u, Q); mag_mul(u, u, err); mag_add(arb_radref(P), arb_radref(P), u); mag_clear(u); } mag_clear(z); mag_clear(err); } flint-3.1.3/src/interfaces/000077500000000000000000000000001461254215100155455ustar00rootroot00000000000000flint-3.1.3/src/interfaces/doc/000077500000000000000000000000001461254215100163125ustar00rootroot00000000000000flint-3.1.3/src/interfaces/doc/interfaces.txt000066400000000000000000000065061461254215100212050ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ ******************************************************************************* NTL Interface The NTL interface allows conversion between NTL objects and FLINT objects and vice versa. NTL version 5.5.2 or later is required. ******************************************************************************* void fmpz_set_ZZ(fmpz_t rop, const ZZ& op) Converts an NTL \code{ZZ} to an \code{fmpz_t}. Assumes the \code{fmpz_t} has already been allocated to have sufficient space. void fmpz_get_ZZ(ZZ& rop, const fmpz_t op) Converts an \code{fmpz_t} to an NTL \code{ZZ}. Allocation is automatically handled. void fmpz_set_ZZ_p(fmpz_t rop, const ZZ_p& op) Converts an NTL \code{ZZ_p} to an \code{fmpz_t}. Assumes the \code{fmpz_t} has already been allocated to have sufficient space. void fmpz_get_ZZ_p(ZZ_p& rop, const fmpz_t op) Converts an \code{fmpz_t} to an NTL \code{ZZ_p}. Allocation is automatically handled. Requires that \code{ZZ_p::init()} has already been called. void fmpz_poly_get_ZZX(ZZX& rop, const fmpz_poly_t op) Converts an \code{fmpz_poly_t} to an NTL \code{ZZX}. void fmpz_poly_set_ZZX(fmpz_poly_t rop, const ZZX& op) Converts an NTL \code{ZZX} to an \code{fmpz_poly_t}. void fmpz_mod_poly_get_ZZ_pX(ZZ_pX& rop, const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx) Converts an \code{fmpz_mod_poly_t} to an NTL \code{ZZ_pX}. Requires that \code{ZZ_p::init()} has already been called. void fmpz_mod_poly_set_ZZ_pX(fmpz_mod_poly_t rop, const ZZ_pX& op, const fmpz_mod_ctx_t ctx) Converts an NTL \code{ZZ_pX} to an \code{fmpz_mod_poly_t}. void fq_get_ZZ_pE(ZZ_pE& rop, const fq_t op, const fq_ctx_t ctx) Converts an \code{fq_t} to an NTL \code{ZZ_pE}. Requires that \code{ZZ_pE::init()} has already been called. void fq_set_ZZ_pE(fq_t rop, const ZZ_pE& op, const fq_ctx_t ctx) Converts and NTL \code{ZZ_pE} to an \code{fq_t}. void fq_poly_get_ZZ_pEX(ZZ_pEX& rop, const fq_poly_t op, const fq_ctx_t ctx) Converts an \code{fq_poly_t} to an NTL \code{ZZ_pEX}. Requires that \code{ZZ_pE::init()} has already been called. void fq_poly_set_ZZ_pE(fq_poly_t rop, const ZZ_pE& op, const fq_ctx_t ctx) Converts and NTL \code{ZZ_pEX} to an \code{fq_poly_t}. void fq_get_zz_pE(zz_pE& rop, const fq_t op, const fq_ctx_t ctx) Converts an \code{fq_t} to an NTL \code{zz_pE}. Requires that \code{zz_pE::init()} has already been called. void fq_set_zz_pE(fq_t rop, const zz_pE& op, const fq_ctx_t ctx) Converts and NTL \code{zz_pE} to an \code{fq_t}. void fq_poly_get_zz_pEX(zz_pEX& rop, const fq_poly_t op, const fq_ctx_t ctx) Converts an \code{fq_poly_t} to an NTL \code{zz_pEX}. Requires that \code{zz_pE::init()} has already been called. void fq_poly_set_zz_pE(fq_poly_t rop, const zz_pE& op, const fq_ctx_t ctx) Converts and NTL \code{zz_pEX} to an \code{fq_poly_t}. flint-3.1.3/src/interfaces/test/000077500000000000000000000000001461254215100165245ustar00rootroot00000000000000flint-3.1.3/src/interfaces/test/t-NTL-interface.cpp000066400000000000000000000311531461254215100220670ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2013 Mike Hansen Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_mod.h" #include "NTL-interface.h" NTL_CLIENT TEST_FUNCTION_START(ZZ_to_fmpz, state) { int i, result; mp_bitcnt_t bits, randbits; fmpz_t int1, int2; ZZ z; /* Check conversion */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { bits = n_randint(state, 1000) + 1; randbits = n_randint(state, bits); fmpz_init(int1); fmpz_init(int2); fmpz_randbits(int1, state, randbits); fmpz_get_ZZ(z, int1); fmpz_set_ZZ(int2, z); result = fmpz_equal(int1, int2); if (!result) { flint_printf("FAIL:\n"); flint_printf("int1 = %wd ", *int1); fmpz_print(int1); flint_printf("\n"); flint_printf("int2 = %wd ", *int2); fmpz_print(int2); flint_printf("\n"); flint_abort(); } fmpz_clear(int1); fmpz_clear(int2); } TEST_FUNCTION_END(state); } TEST_FUNCTION_START(ZZX_to_fmpz_poly, state) { fmpz_poly_t f_poly1, f_poly2; slong length; mp_bitcnt_t bits; int i, result; /* Check aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { bits = n_randint(state, 1000) + 1; length = n_randint(state, 1000); fmpz_poly_init(f_poly1); fmpz_poly_init(f_poly2); ZZX ZZX_poly; fmpz_poly_randtest(f_poly1, state, length, bits); fmpz_poly_get_ZZX(ZZX_poly, f_poly1); fmpz_poly_set_ZZX(f_poly2, ZZX_poly); result = fmpz_poly_equal(f_poly1, f_poly2); if (!result) { flint_printf("FAIL:\n"); flint_printf("f_poly1 = "); fmpz_poly_print(f_poly1); flint_printf("\n"); flint_printf("f_poly2 = "); fmpz_poly_print(f_poly2); flint_printf("\n"); flint_abort(); } fmpz_poly_clear(f_poly1); fmpz_poly_clear(f_poly2); } TEST_FUNCTION_END(state); } TEST_FUNCTION_START(ZZ_pX_to_fmpz_mod_poly, state) { fmpz_t p; fmpz_mod_poly_t f_poly1, f_poly2; fmpz_mod_ctx_t ctx; slong length; int i, result; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ZZ_pX ZZ_pX_poly; ZZ mod; length = n_randint(state, 1000); fmpz_init(p); fmpz_randtest_unsigned(p, state, 2 * FLINT_BITS); fmpz_add_ui(p, p, 2); fmpz_mod_ctx_set_modulus(ctx, p); fmpz_get_ZZ(mod, p); ZZ_p::init(mod); fmpz_mod_poly_init(f_poly1, ctx); fmpz_mod_poly_init(f_poly2, ctx); fmpz_mod_poly_randtest(f_poly1, state, length, ctx); fmpz_mod_poly_get_ZZ_pX(ZZ_pX_poly, f_poly1, ctx); fmpz_mod_poly_set_ZZ_pX(f_poly2, ZZ_pX_poly, ctx); result = fmpz_mod_poly_equal(f_poly1, f_poly2, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("f_poly1 = "); fmpz_mod_poly_print(f_poly1, ctx); flint_printf("\n"); flint_printf("f_poly2 = "); fmpz_mod_poly_print(f_poly2, ctx); flint_printf("\n"); flint_abort(); } fmpz_clear(p); fmpz_mod_poly_clear(f_poly1, ctx); fmpz_mod_poly_clear(f_poly2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } TEST_FUNCTION_START(zz_pX_to_fmpz_mod_poly, state) { fmpz_mod_poly_t f_poly1, f_poly2; fmpz_mod_ctx_t ctx; slong length; int i, result; fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { zz_pX zz_pX_poly; length = n_randint(state, 1000); fmpz_mod_ctx_set_modulus_ui(ctx, n_randprime(state, 16, 1)); zz_p::init(fmpz_get_si(fmpz_mod_ctx_modulus(ctx))); fmpz_mod_poly_init(f_poly1, ctx); fmpz_mod_poly_init(f_poly2, ctx); fmpz_mod_poly_randtest(f_poly1, state, length, ctx); fmpz_mod_poly_get_zz_pX(zz_pX_poly, f_poly1, ctx); fmpz_mod_poly_set_zz_pX(f_poly2, zz_pX_poly, ctx); result = fmpz_mod_poly_equal(f_poly1, f_poly2, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("f_poly1 = "); fmpz_mod_poly_print(f_poly1, ctx); flint_printf("\n"); flint_printf("f_poly2 = "); fmpz_mod_poly_print(f_poly2, ctx); flint_printf("\n"); flint_abort(); } fmpz_mod_poly_clear(f_poly1, ctx); fmpz_mod_poly_clear(f_poly2, ctx); } fmpz_mod_ctx_clear(ctx); TEST_FUNCTION_END(state); } TEST_FUNCTION_START(ZZ_pE_to_fq, state) { fq_t f1, f2; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; fmpz_mod_ctx_init_ui(ctxp, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t fmod; slong d; ZZ prime; ZZ_pX mod; fmpz_mod_ctx_set_modulus_ui(ctxp, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; fmpz_get_ZZ(prime, fmpz_mod_ctx_modulus(ctxp)); ZZ_p::init(prime); BuildIrred(mod, d); ZZ_pE::init(mod); fmpz_mod_poly_init(fmod, ctxp); fmpz_mod_poly_set_ZZ_pX(fmod, mod, ctxp); fq_ctx_init_modulus(ctx, fmod, ctxp, "a"); ZZ_pE zzpe; fq_init(f1, ctx); fq_init(f2, ctx); fq_randtest(f1, state, ctx); fq_get_ZZ_pE(zzpe, f1, ctx); fq_set_ZZ_pE(f2, zzpe, ctx); result = fq_equal(f1, f2, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "); fmpz_print(fmpz_mod_ctx_modulus(ctxp)); flint_printf("\n"); flint_printf("mod = "); fmpz_mod_poly_print_pretty(fmod, "x", ctxp); flint_printf("\n"); flint_printf("f1 = "); fq_print_pretty(f1, ctx); flint_printf(" - %wd", f1->length); flint_printf("\n"); flint_printf("zzpe:"); cout << zzpe; flint_printf("\n"); flint_printf("f2 = "); fq_print_pretty(f2, ctx); flint_printf(" - %wd", f2->length); flint_printf("\n"); flint_abort(); } fq_clear(f1, ctx); fq_clear(f2, ctx); fq_ctx_clear(ctx); fmpz_mod_poly_clear(fmod, ctxp); } fmpz_mod_ctx_clear(ctxp); TEST_FUNCTION_END(state); } TEST_FUNCTION_START(ZZ_pEX_to_fq_poly, state) { fq_poly_t f1, f2; slong length; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; fmpz_mod_ctx_init_ui(ctxp, 2); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t fmod; slong d; ZZ prime; ZZ_pX mod; fmpz_mod_ctx_set_modulus_ui(ctxp, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; fmpz_get_ZZ(prime, fmpz_mod_ctx_modulus(ctxp)); ZZ_p::init(prime); BuildIrred(mod, d); ZZ_pE::init(mod); fmpz_mod_poly_init(fmod, ctxp); fmpz_mod_poly_set_ZZ_pX(fmod, mod, ctxp); fq_ctx_init_modulus(ctx, fmod, ctxp, "a"); ZZ_pEX zzpex; fq_poly_init(f1, ctx); fq_poly_init(f2, ctx); length = n_randint(state, 1000); fq_poly_randtest(f1, state, length, ctx); fq_poly_get_ZZ_pEX(zzpex, f1, ctx); fq_poly_set_ZZ_pEX(f2, zzpex, ctx); result = fq_poly_equal(f1, f2, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "); fmpz_print(fmpz_mod_ctx_modulus(ctxp)); flint_printf("\n"); flint_printf("mod = "); fmpz_mod_poly_print_pretty(fmod, "x", ctxp); flint_printf("\n"); flint_printf("f1 = "); fq_poly_print_pretty(f1, "x", ctx); flint_printf("\n"); flint_printf("zzpex:"); cout << zzpex; flint_printf("\n"); flint_printf("f2 = "); fq_poly_print_pretty(f2, "x", ctx); flint_printf("\n"); flint_abort(); } fq_poly_clear(f1, ctx); fq_poly_clear(f2, ctx); fq_ctx_clear(ctx); fmpz_mod_poly_clear(fmod, ctxp); } fmpz_mod_ctx_clear(ctxp); TEST_FUNCTION_END(state); } TEST_FUNCTION_START(zz_pE_to_fq, state) { fq_t f1, f2; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; fmpz_mod_ctx_init_ui(ctxp, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t fmod; slong d; zz_pX mod; fmpz_mod_ctx_set_modulus_ui(ctxp, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; zz_p::init(fmpz_get_si(fmpz_mod_ctx_modulus(ctxp))); BuildIrred(mod, d); zz_pE::init(mod); fmpz_mod_poly_init(fmod, ctxp); fmpz_mod_poly_set_zz_pX(fmod, mod, ctxp); fq_ctx_init_modulus(ctx, fmod, ctxp, "a"); zz_pE zzpe; fq_init(f1, ctx); fq_init(f2, ctx); fq_randtest(f1, state, ctx); fq_get_zz_pE(zzpe, f1, ctx); fq_set_zz_pE(f2, zzpe, ctx); result = fq_equal(f1, f2, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "); fmpz_print(fmpz_mod_ctx_modulus(ctxp)); flint_printf("\n"); flint_printf("mod = "); fmpz_mod_poly_print_pretty(fmod, "x", ctxp); flint_printf("\n"); flint_printf("f1 = "); fq_print_pretty(f1, ctx); flint_printf(" - %wd", f1->length); flint_printf("\n"); flint_printf("zzpe:"); cout << zzpe; flint_printf("\n"); flint_printf("f2 = "); fq_print_pretty(f2, ctx); flint_printf(" - %wd", f2->length); flint_printf("\n"); flint_abort(); } fq_clear(f1, ctx); fq_clear(f2, ctx); fq_ctx_clear(ctx); fmpz_mod_poly_clear(fmod, ctxp); } fmpz_mod_ctx_clear(ctxp); TEST_FUNCTION_END(state); } TEST_FUNCTION_START(zz_pEX_to_fq_poly, state) { fq_poly_t f1, f2; slong length; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; fmpz_mod_ctx_init_ui(ctxp, 2); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_mod_poly_t fmod; slong d; zz_pX mod; fmpz_mod_ctx_set_modulus_ui(ctxp, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; zz_p::init(fmpz_get_si(fmpz_mod_ctx_modulus(ctxp))); BuildIrred(mod, d); zz_pE::init(mod); fmpz_mod_poly_init(fmod, ctxp); fmpz_mod_poly_set_zz_pX(fmod, mod, ctxp); fq_ctx_init_modulus(ctx, fmod, ctxp, "a"); zz_pEX zzpex; fq_poly_init(f1, ctx); fq_poly_init(f2, ctx); length = n_randint(state, 1000); fq_poly_randtest(f1, state, length, ctx); fq_poly_get_zz_pEX(zzpex, f1, ctx); fq_poly_set_zz_pEX(f2, zzpex, ctx); result = fq_poly_equal(f1, f2, ctx); if (!result) { flint_printf("FAIL:\n"); flint_printf("p = "); fmpz_print(fmpz_mod_ctx_modulus(ctxp)); flint_printf("\n"); flint_printf("mod = "); fmpz_mod_poly_print_pretty(fmod, "x", ctxp); flint_printf("\n"); flint_printf("f1 = "); fq_poly_print_pretty(f1, "x", ctx); flint_printf("\n"); flint_printf("zzpex:"); cout << zzpex; flint_printf("\n"); flint_printf("f2 = "); fq_poly_print_pretty(f2, "x", ctx); flint_printf("\n"); flint_abort(); } fq_poly_clear(f1, ctx); fq_poly_clear(f2, ctx); fq_ctx_clear(ctx); fmpz_mod_poly_clear(fmod, ctxp); } fmpz_mod_ctx_clear(ctxp); TEST_FUNCTION_END(state); } /* ISO C++ forbids converting a string constant to char* */ char str1[] = "ZZ_to_fmpz"; char str2[] = "ZZX_to_fmpz_poly"; char str3[] = "ZZ_pX_to_fmpz_mod_poly"; char str4[] = "zz_pX_to_fmpz_mod_poly"; char str5[] = "ZZ_pE_to_fq"; char str6[] = "ZZ_pEX_to_fq_poly"; char str7[] = "zz_pE_to_fq"; char str8[] = "zz_pEX_to_fq_poly"; test_struct tests[] = { { CAT(test, ZZ_to_fmpz), str1 }, { CAT(test, ZZX_to_fmpz_poly), str2 }, { CAT(test, ZZ_pX_to_fmpz_mod_poly), str3 }, { CAT(test, zz_pX_to_fmpz_mod_poly), str4 }, { CAT(test, ZZ_pE_to_fq), str5 }, { CAT(test, ZZ_pEX_to_fq_poly), str6 }, { CAT(test, zz_pE_to_fq), str7 }, { CAT(test, zz_pEX_to_fq_poly), str8 } }; TEST_MAIN(tests) flint-3.1.3/src/limb_types.h000066400000000000000000000016611461254215100157460ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef LIMB_TYPES_H #define LIMB_TYPES_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif #define FLINT_MAX_FACTORS_IN_LIMB 15 typedef struct { int num; int exp[FLINT_MAX_FACTORS_IN_LIMB]; ulong p[FLINT_MAX_FACTORS_IN_LIMB]; } n_factor_t; typedef struct { slong small_i; slong small_num; unsigned int * small_primes; ulong sieve_a; ulong sieve_b; slong sieve_i; slong sieve_num; char * sieve; } n_primes_struct; typedef n_primes_struct n_primes_t[1]; #ifdef __cplusplus } #endif #endif /* LIMB_TYPES_H */ flint-3.1.3/src/long_extras.h000066400000000000000000000035401461254215100161220ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef LONG_EXTRAS_H #define LONG_EXTRAS_H #ifdef LONG_EXTRAS_INLINES_C #define LONG_EXTRAS_INLINE #else #define LONG_EXTRAS_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Properties ****************************************************************/ size_t z_sizeinbase(slong n, int b); /* Checked arithmetic ********************************************************/ LONG_EXTRAS_INLINE int z_mul_checked(slong * a, slong b, slong c) { /* TODO __builtin_mul_overflow */ ulong ahi, alo; smul_ppmm(ahi, alo, b, c); *a = alo; return FLINT_SIGN_EXT(alo) != ahi; } LONG_EXTRAS_INLINE int z_add_checked(slong * a, slong b, slong c) { /* TODO __builtin_add_overflow */ int of = (b > 0 && c > WORD_MAX - b) || (b < 0 && c < WORD_MIN - b); *a = b + c; return of; } LONG_EXTRAS_INLINE int z_mat22_det_is_negative(slong m11, slong m12, slong m21, slong m22) { ulong t1, t2, t3, t4; smul_ppmm(t1, t2, m11, m22); smul_ppmm(t3, t4, m12, m21); sub_ddmmss(t1, t2, t1, t2, t3, t4); return FLINT_SIGN_EXT(t1) != 0; } /* Randomisation ************************************************************/ mp_limb_signed_t z_randtest(flint_rand_t state); mp_limb_signed_t z_randtest_not_zero(flint_rand_t state); mp_limb_signed_t z_randint(flint_rand_t state, mp_limb_t limit); /*****************************************************************************/ int z_kronecker(slong a, slong n); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/long_extras/000077500000000000000000000000001461254215100157475ustar00rootroot00000000000000flint-3.1.3/src/long_extras/inlines.c000066400000000000000000000007051461254215100175560ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define LONG_EXTRAS_INLINES_C #include "flint.h" #include "long_extras.h" flint-3.1.3/src/long_extras/kronecker.c000066400000000000000000000020441461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "long_extras.h" #include "ulong_extras.h" int z_kronecker(slong a, slong n) { ulong sa = FLINT_SIGN_EXT(a); ulong ua = FLINT_ABS(a); ulong sn = FLINT_SIGN_EXT(n); ulong un = FLINT_ABS(n); int en; unsigned int r; if (a == 0) return un == 1; if (un == 0) return ua == 1; en = flint_ctz(un); /* make denominator positive */ r = sa & sn; /* make denominator odd */ un >>= en; r ^= (ua ^ (ua>>1)) & (2*en); if (en > 0 && !(ua & 1)) return 0; /* a and n both even */ /* make numerator positive */ r ^= (sa & un); return _n_jacobi_unsigned(ua, un, r); } flint-3.1.3/src/long_extras/randint.c000066400000000000000000000014121461254215100175500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" mp_limb_signed_t z_randint(flint_rand_t state, mp_limb_t limit) { mp_limb_signed_t z; if ((limit == UWORD(0)) || (limit > WORD_MAX)) limit = WORD_MAX; z = n_randlimb(state) % limit; if (n_randint(state, 2)) z = -z; return z; } flint-3.1.3/src/long_extras/randtest.c000066400000000000000000000024101461254215100177340ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "long_extras.h" mp_limb_signed_t z_randtest(flint_rand_t state) { mp_limb_t m; mp_limb_signed_t z; m = n_randlimb(state); if (m & UWORD(7)) { z = n_randbits(state, n_randint(state, FLINT_BITS)); } else { m >>= 3; switch (m % UWORD(7)) { case 0: z = 0; break; case 1: z = 1; break; case 2: z = -1; break; case 3: z = COEFF_MAX; break; case 4: z = COEFF_MIN; break; case 5: z = WORD_MAX; break; case 6: z = WORD_MIN; break; default: z = 0; } } return z; } mp_limb_signed_t z_randtest_not_zero(flint_rand_t state) { mp_limb_signed_t z; while ((z = z_randtest(state)) == 0) ; return z; } flint-3.1.3/src/long_extras/sizeinbase.c000066400000000000000000000016451461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "long_extras.h" size_t z_sizeinbase(slong n, int b) { slong c = 0; if (n == 0) { return 1; } if (n <= 0) { if (n > WORD_MIN) { n = -n; } else /* n == WORD_MIN */ { if (n % b) { n = - (n + 1); } else { n = - (n / b); c = 1; } } } for ( ; n > 0; n /= b, c++) ; return c; } flint-3.1.3/src/long_extras/test/000077500000000000000000000000001461254215100167265ustar00rootroot00000000000000flint-3.1.3/src/long_extras/test/main.c000066400000000000000000000014711461254215100200210ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-kronecker.c" #include "t-sizeinbase.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(z_kronecker), TEST_FUNCTION(z_sizeinbase) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/long_extras/test/t-kronecker.c000066400000000000000000000021211461254215100213120ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "ulong_extras.h" #include "gmpcompat.h" TEST_FUNCTION_START(z_kronecker, state) { slong i; mpz_t aa, nn; mpz_init(aa); mpz_init(nn); for (i = 0; i < 300000 * flint_test_multiplier(); i++) { slong a = z_randtest(state); slong n = z_randtest(state); if (n_randlimb(state) & 1) a = -a; if (n_randlimb(state) & 1) n = -n; flint_mpz_set_si(aa, a); flint_mpz_set_si(nn, n); if (mpz_kronecker(aa, nn) != z_kronecker(a, n)) TEST_FUNCTION_FAIL("a = %wd, n = %wd\n", a, n); } mpz_clear(aa); mpz_clear(nn); TEST_FUNCTION_END(state); } flint-3.1.3/src/long_extras/test/t-sizeinbase.c000066400000000000000000000023001461254215100214620ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "long_extras.h" #include "gmpcompat.h" TEST_FUNCTION_START(z_sizeinbase, state) { int i, result; for (i = 0; i < 100000; i++) { slong a; mpz_t b; int base; size_t r1, r2; a = z_randtest(state); flint_mpz_init_set_si(b, a); base = (int) (n_randint(state, 61) + 2); r1 = z_sizeinbase(a, base); r2 = mpz_sizeinbase(b, base); result = (r1 == r2 || r1 + 1 == r2); if (!result) TEST_FUNCTION_FAIL( "b = %{mpz}\n" "base = %d\n" "r1 = %wu\n" "r2 = %wu\n", b, base, (ulong) r1, (ulong) r2); mpz_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/longlong.h000066400000000000000000000205261461254215100154170ustar00rootroot00000000000000/* Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Copyright 2009, 2015, 2016 William Hart Copyright 2011 Fredrik Johansson Copyright 2023 Albin Ahlbäck This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this file; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* N.B: This file has been adapted from code found in GMP 4.2.1. */ #ifndef FLINT_LONGLONG_H #define FLINT_LONGLONG_H #ifdef __cplusplus extern "C" { #endif #if defined(__GNUC__) /* Trailing and leading zeros */ # ifndef _LONG_LONG_LIMB # define flint_clz __builtin_clzl # define flint_ctz __builtin_ctzl # else # define flint_clz __builtin_clzll # define flint_ctz __builtin_ctzll # endif /* Byte swap */ # define _FLINT_CAT_(X,Y) X##Y # define _FLINT_CAT(X,Y) _FLINT_CAT_(X,Y) # define byte_swap(x) do { (x) = _FLINT_CAT(__builtin_bswap, GMP_LIMB_BITS)(x); } while (0) /* Addition, subtraction and multiplication */ # if defined(__clang__) # include "longlong_asm_clang.h" # else # include "longlong_asm_gcc.h" # endif /* Division */ # include "longlong_div_gnu.h" #elif defined(_MSC_VER) # if defined(_M_X64) || defined(_M_IX86) # include "longlong_msc_x86.h" # elif defined(_M_ARM64) # include "longlong_msc_arm64.h" # endif #endif /* Generics ******************************************************************/ #define __ll_B ((ulong) 1 << (FLINT_BITS / 2)) #define __ll_lowpart(t) ((ulong) (t) & (__ll_B - 1)) #define __ll_highpart(t) ((ulong) (t) >> (FLINT_BITS / 2)) /* Trailing and leading zeros */ #if !defined(flint_ctz) # define NEED_CLZ_TAB FLINT_DLL extern const unsigned char __flint_clz_tab[128]; # define flint_clz flint_clz static inline int flint_clz(ulong x) { mp_limb_t a, xr = x; const unsigned int bits4 = FLINT_BITS / 4; if (FLINT_BITS == 32) a = xr < ((ulong) 1 << 2 * bits4) ? (xr < ((ulong) 1 << bits4) ? 1 : bits4 + 1) : (xr < ((ulong) 1 << 3 * bits4) ? 2 * bits4 + 1 : 3 * bits4 + 1); else { for (a = FLINT_BITS - 8; a > 0; a -= 8) if (((xr >> a) & 0xff) != 0) break; ++a; } return FLINT_BITS + 1 - a - __flint_clz_tab[xr >> a]; } # define flint_ctz flint_ctz static inline int flint_ctz(ulong x) { return FLINT_BITS - 1 - flint_clz(x & -x); } #endif /* Byte swap */ #if !defined(byte_swap) # if FLINT_BITS == 32 # define byte_swap(n) \ do { \ /* swap adjacent bytes */ \ (n) = ((((n) & 0xff00ff00) >> 8) | (((n) & 0x00ff00ff) << 8)); \ /* swap adjacent words */ \ (n) = (((n) >> 16) | ((n) << 16)); \ } while (0) # else # define byte_swap(n) \ do { \ /* swap adjacent bytes */ \ (n) = ((((n) & 0xff00ff00ff00ff00) >> 8) | (((n) & 0x00ff00ff00ff00ff) << 8)); \ /* swap adjacent words */ \ (n) = ((((n) & 0xffff0000ffff0000) >> 16) | (((n) & 0x0000ffff0000ffff) << 16)); \ /* swap adjacent double words */ \ (n) = (((n) >> 32) | ((n) << 32)); \ } while (0) # endif #endif /* Addition and subtraction */ #if !defined(add_ssaaaa) # define add_ssaaaa(s1, s0, a1, a0, b1, b0) \ do { \ ulong __t0 = (a0); \ (s0) = (a0) + (b0); \ (s1) = (a1) + (b1) + ((ulong) (s0) < __t0); \ } while (0) # define add_sssaaaaaa(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ do { \ mp_limb_t __t1, __t2; \ add_ssaaaa(__t1, s0, (mp_limb_t) 0, a0, (mp_limb_t) 0, b0); \ add_ssaaaa(__t2, s1, (mp_limb_t) 0, a1, (mp_limb_t) 0, b1); \ add_ssaaaa(s2, s1, (a2) + (b2), s1, __t2, __t1); \ } while (0) # define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ do { \ mp_limb_t __u2; \ add_sssaaaaaa(__u2, s1, s0, (mp_limb_t) 0, a1, a0, (mp_limb_t) 0, b1, b0); \ add_ssaaaa(s3, s2, a3, a2, b3, b2); \ add_ssaaaa(s3, s2, s3, s2, (mp_limb_t) 0, __u2); \ } while (0) # define sub_ddmmss(s1, s0, a1, a0, b1, b0) \ do { \ ulong __t0 = (a0); \ (s0) = (a0) - (b0); \ (s1) = (a1) - (b1) - ((ulong) (s0) > __t0); \ } while (0) # define sub_dddmmmsss(d2, d1, d0, m2, m1, m0, s2, s1, s0) \ do { \ mp_limb_t __t1, __t2; \ sub_ddmmss(__t1, d0, (mp_limb_t) 0, m0, (mp_limb_t) 0, s0); \ sub_ddmmss(__t2, d1, (mp_limb_t) 0, m1, (mp_limb_t) 0, s1); \ sub_ddmmss(d2, d1, (m2) - (s2), d1, -__t2, -__t1); \ } while (0) #endif /* Multiplication */ #if !defined(umul_ppmm) # define umul_ppmm(w1, w0, u, v) \ do { \ ulong __x0, __x1, __x2, __x3; \ ulong __ul, __vl, __uh, __vh; \ __ul = __ll_lowpart(u); \ __uh = __ll_highpart(u); \ __vl = __ll_lowpart(v); \ __vh = __ll_highpart(v); \ __x0 = __ul * __vl; \ __x1 = __ul * __vh; \ __x2 = __uh * __vl; \ __x3 = __uh * __vh; \ __x1 += __ll_highpart(__x0); /* this can't give carry */ \ __x1 += __x2; /* but this indeed can */ \ if (__x1 < __x2) \ __x3 += __ll_B; \ (w1) = __x3 + __ll_highpart(__x1); \ (w0) = (__x1 << (FLINT_BITS / 2)) + __ll_lowpart(__x0); \ } while (0) # define smul_ppmm(w1, w0, u, v) \ do { \ ulong __w1, __u = (u), __v = (v); \ umul_ppmm(__w1, w0, u, v); \ (w1) = __w1 - (-(__u >> (FLINT_BITS - 1)) & __v) - (-(__v >> (FLINT_BITS - 1)) & __u); \ } while (0) #endif /* Division */ #if !defined(udiv_qrnnd) # define udiv_qrnnd_int(q, r, n1, n0, d) \ do { \ ulong __d1, __d0, __q1, __q0, __r1, __r0, __m; \ FLINT_ASSERT((d) != 0); \ FLINT_ASSERT((n1) < (d)); \ __d1 = __ll_highpart (d); \ __d0 = __ll_lowpart (d); \ __q1 = (n1) / __d1; \ __r1 = (n1) - __q1 * __d1; \ __m = __q1 * __d0; \ __r1 = __r1 * __ll_B | __ll_highpart (n0); \ if (__r1 < __m) \ { \ __q1--, __r1 += (d); \ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */ \ if (__r1 < __m) \ __q1--, __r1 += (d); \ } \ __r1 -= __m; \ __q0 = __r1 / __d1; \ __r0 = __r1 - __q0 * __d1; \ __m = __q0 * __d0; \ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ if (__r0 < __m) \ { \ __q0--, __r0 += (d); \ if (__r0 >= (d)) \ if (__r0 < __m) \ __q0--, __r0 += (d); \ } \ __r0 -= __m; \ (q) = __q1 * __ll_B | __q0; \ (r) = __r0; \ } while (0) # define udiv_qrnnd(q, r, n1, n0, d) \ do { \ ulong __norm = flint_clz(d); \ if (__norm) \ { \ udiv_qrnnd_int((q), (r), ((n1) << __norm) + ((n0) >> (FLINT_BITS - __norm)), (n0) << __norm, (d) << __norm); \ (r) = ((mp_limb_t) (r) >> __norm); \ } \ else \ udiv_qrnnd_int((q), (r), (n1), (n0), (d)); \ } while (0) # define __highbit (~(ulong) 0 ^ ((~(ulong) 0) >> 1)) # define sdiv_qrnnd(q, r, n1, n0, d) \ do { \ mp_limb_t __n1, __n0, __d; \ mp_limb_t __q, __r; \ unsigned int __sgn_n = 0, __sgn_d = 0; \ if ((n1) & __highbit) \ { \ __n0 = -(n0); \ __n1 = ~(n1) + (__n0 == 0); \ __sgn_n = ~__sgn_n; \ } \ else \ { \ __n0 = (n0); \ __n1 = (n1); \ } \ if ((d) & __highbit) \ { \ __d = -(d); \ __sgn_d = ~__sgn_d; \ } \ else \ { \ __d = (d); \ } \ udiv_qrnnd(__q, __r, __n1, __n0, __d); \ q = (__sgn_n == __sgn_d) ? __q : -__q; \ r = (__sgn_n == 0) ? __r : -__r; \ } while (0) #endif #define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ do { \ ulong _n2, _n10, _nmask, _nadj, _q1; \ ulong _xh, _xl; \ _n2 = (nh); \ _n10 = (nl); \ _nmask = (slong) (_n10) >> (FLINT_BITS - 1); \ _nadj = _n10 + (_nmask & (d)); \ umul_ppmm(_xh, _xl, di, _n2 - _nmask); \ add_ssaaaa(_xh, _xl, _xh, _xl, _n2, _nadj); \ _q1 = ~_xh; \ umul_ppmm(_xh, _xl, _q1, d); \ add_ssaaaa(_xh, _xl, _xh, _xl, nh, nl); \ _xh -= (d); /* xh = 0 or -1 */ \ (r) = _xl + ((d) & _xh); \ (q) = _xh - _q1; \ } while (0) #ifdef __cplusplus } #endif #endif flint-3.1.3/src/longlong_asm_clang.h000066400000000000000000000044601461254215100174220ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef LONGLONG_ASM_H #define LONGLONG_ASM_H #if FLINT64 # define _STOR_ULONG __uint128_t # define _STOR_SLONG __int128_t #else # define _STOR_ULONG unsigned long long int # define _STOR_SLONG long long int #endif #if defined(_LONG_LONG_LIMB) # define _FLINT_ADC __builtin_addcll # define _FLINT_SBB __builtin_subcll #else # define _FLINT_ADC __builtin_addcl # define _FLINT_SBB __builtin_subcl #endif #define add_ssaaaa(s1, s0, a1, a0, b1, b0) \ do \ { \ ulong _carry; \ (s0) = _FLINT_ADC(a0, b0, 0, &_carry); \ (s1) = _FLINT_ADC(a1, b1, _carry, &_carry); \ } while (0) #define add_sssaaaaaa(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ do \ { \ ulong _carry; \ (s0) = _FLINT_ADC(a0, b0, 0, &_carry); \ (s1) = _FLINT_ADC(a1, b1, _carry, &_carry); \ (s2) = _FLINT_ADC(a2, b2, _carry, &_carry); \ } while (0) #define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ do \ { \ ulong _carry; \ (s0) = _FLINT_ADC(a0, b0, 0, &_carry); \ (s1) = _FLINT_ADC(a1, b1, _carry, &_carry); \ (s2) = _FLINT_ADC(a2, b2, _carry, &_carry); \ (s3) = _FLINT_ADC(a3, b3, _carry, &_carry); \ } while (0) #define sub_ddmmss(s1, s0, a1, a0, b1, b0) \ do \ { \ ulong _carry; \ (s0) = _FLINT_SBB(a0, b0, 0, &_carry); \ (s1) = _FLINT_SBB(a1, b1, _carry, &_carry); \ } while (0) #define sub_dddmmmsss(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ do \ { \ ulong _carry; \ (s0) = _FLINT_SBB(a0, b0, 0, &_carry); \ (s1) = _FLINT_SBB(a1, b1, _carry, &_carry); \ (s2) = _FLINT_SBB(a2, b2, _carry, &_carry); \ } while (0) #define _mul_ppmm(big_type, small_type, r1, r0, u, v) \ do \ { \ big_type __r = (big_type) ((small_type) u) * (big_type) ((small_type) v); \ (r0) = (small_type) __r; \ (r1) = (small_type) (__r >> FLINT_BITS); \ } while (0) #define umul_ppmm(r1, r0, u, v) _mul_ppmm(_STOR_ULONG, ulong, r1, r0, u, v) #define smul_ppmm(r1, r0, u, v) _mul_ppmm(_STOR_SLONG, slong, r1, r0, u, v) #endif flint-3.1.3/src/longlong_asm_gcc.h000066400000000000000000000151361461254215100170740ustar00rootroot00000000000000/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. Copyright 1991-1994, 1996, 1997, 1999-2005, 2007-2009, 2011-2020 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of either: * the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. or * the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. or both in parallel, as here. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received copies of the GNU General Public License and the GNU Lesser General Public License along with the GNU MP Library. If not, see https://www.gnu.org/licenses/. */ /* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef LONGLONG_ASM_H #define LONGLONG_ASM_H /* Machine specific operations */ #if defined (__amd64__) || (GMP_LIMB_BITS == 32 && (defined (__i386__) || defined (__i486__))) # if GMP_LIMB_BITS == 64 && defined (__amd64__) # define _ASM_ADD "addq" # define _ASM_ADC "adcq" # define _ASM_SUB "subq" # define _ASM_SBB "sbbq" # define _ASM_MUL "mulq" # define _ASM_IMUL "imulq" # define _ASM_PRE "q" # define _ASM_RME "rme" # else # define _ASM_ADD "addl" # define _ASM_ADC "adcl" # define _ASM_SUB "subl" # define _ASM_SBB "sbbl" # define _ASM_MUL "mull" # define _ASM_IMUL "imull" # define _ASM_PRE "k" # define _ASM_RME "g" # endif # define add_ssaaaa(s1, s0, a1, a0, b1, b0) \ __asm__(_ASM_ADD " %5,%" _ASM_PRE "1\n" \ "\t" _ASM_ADC " %3,%" _ASM_PRE "0" \ : "=r" (s1), "=&r" (s0) \ : "0" ((ulong)(a1)), _ASM_RME ((ulong)(b1)), \ "%1" ((ulong)(a0)), _ASM_RME ((ulong)(b0))) # define add_sssaaaaaa(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ __asm__(_ASM_ADD " %8,%" _ASM_PRE "2\n" \ "\t" _ASM_ADC " %6,%" _ASM_PRE "1\n" \ "\t" _ASM_ADC " %4,%" _ASM_PRE "0" \ : "=r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((ulong)(a2)), _ASM_RME ((ulong)(b2)), \ "1" ((ulong)(a1)), _ASM_RME ((ulong)(b1)), \ "2" ((ulong)(a0)), _ASM_RME ((ulong)(b0))) # define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ __asm__(_ASM_ADD " %11,%" _ASM_PRE"3\n" \ "\t" _ASM_ADC " %9,%" _ASM_PRE "2\n" \ "\t" _ASM_ADC " %7,%" _ASM_PRE "1\n" \ "\t" _ASM_ADC " %5,%" _ASM_PRE "0" \ : "=r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((ulong)(a3)), _ASM_RME ((ulong)(b3)), \ "1" ((ulong)(a2)), _ASM_RME ((ulong)(b2)), \ "2" ((ulong)(a1)), _ASM_RME ((ulong)(b1)), \ "3" ((ulong)(a0)), _ASM_RME ((ulong)(b0))) # define sub_ddmmss(d1, d0, m1, m0, s1, s0) \ __asm__(_ASM_SUB " %5,%" _ASM_PRE "1\n" \ "\t" _ASM_SBB " %3,%" _ASM_PRE "0" \ : "=r" (d1), "=&r" (d0) \ : "0" ((ulong)(m1)), _ASM_RME ((ulong)(s1)), \ "1" ((ulong)(m0)), _ASM_RME ((ulong)(s0))) # define sub_dddmmmsss(d2, d1, d0, m2, m1, m0, s2, s1, s0) \ __asm__(_ASM_SUB " %8,%" _ASM_PRE "2\n" \ "\t" _ASM_SBB " %6,%" _ASM_PRE "1\n" \ "\t" _ASM_SBB " %4,%" _ASM_PRE "0" \ : "=r" (d2), "=&r" (d1), "=&r" (d0) \ : "0" ((ulong)(m2)), _ASM_RME ((ulong)(s2)), \ "1" ((ulong)(m1)), _ASM_RME ((ulong)(s1)), \ "2" ((ulong)(m0)), _ASM_RME ((ulong)(s0))) # if defined(__BMI2__) && defined(__amd64__) # define umul_ppmm(w1, w0, u, v) \ __asm__("mulx\t%3, %q0, %q1" \ : "=r" (w0), "=r" (w1) \ : "%d" ((ulong)(u)), "rm" ((ulong)(v))) # else # define umul_ppmm(w1, w0, u, v) \ __asm__(_ASM_MUL " %3" \ : "=a" (w0), "=d" (w1) \ : "%0" ((ulong)(u)), "rm" ((ulong)(v))) #endif # define smul_ppmm(w1, w0, u, v) \ __asm__(_ASM_IMUL " %3" \ : "=a" (w0), "=d" (w1) \ : "%0" ((ulong)(u)), "rm" ((ulong)(v))) #elif (GMP_LIMB_BITS == 64 && defined(__aarch64__)) || (GMP_LIMB_BITS == 32 && defined(__arm__)) # define add_ssaaaa(s1, s0, a1, a0, b1, b0) \ __asm__("adds %1,%3,%5\n" \ "\tadc %0,%2,%4" \ : "=r" (s1), "=&r" (s0) \ : "r" ((ulong)(a1)), "r" ((ulong)(a0)), \ "r" ((ulong)(b1)), "rI" ((ulong)(b0)) \ : "cc") # define add_sssaaaaaa(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ __asm__("adds %2,%5,%8\n" \ "\tadcs %1,%4,%7\n" \ "\tadc %0,%3,%6" \ : "=r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((ulong)(a2)), "r" ((ulong)(a1)), "r" ((ulong)(a0)), \ "r" ((ulong)(b2)), "r" ((ulong)(b1)), "rI" ((ulong)(b0)) \ : "cc") # define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ __asm__("adds %3,%7,%11\n" \ "\tadcs %2,%6,%10\n" \ "\tadcs %1,%5,%9\n" \ "\tadc %0,%4,%8" \ : "=r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((ulong)(a3)), "r" ((ulong)(a2)), "r" ((ulong)(a1)), "r" ((ulong)(a0)), \ "r" ((ulong)(b3)), "r" ((ulong)(b2)), "r" ((ulong)(b1)), "rI" ((ulong)(b0)) \ : "cc") # define sub_ddmmss(s1, s0, a1, a0, b1, b0) \ __asm__("subs %1,%3,%5\n" \ "\tsbc %0,%2,%4" \ : "=r" (s1), "=&r" (s0) \ : "r" ((ulong)(a1)), "r" ((ulong)(a0)), \ "r" ((ulong)(b1)), "rI" ((ulong)(b0)) \ : "cc") # define sub_dddmmmsss(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ __asm__("subs %2,%5,%8\n" \ "\tsbcs %1,%4,%7\n" \ "\tsbc %0,%3,%6" \ : "=r" (s2), "=&r" (s1), "=&r" (s0) \ : "r" ((ulong)(a2)), "r" ((ulong)(a1)), "r" ((ulong)(a0)), \ "r" ((ulong)(b2)), "r" ((ulong)(b1)), "rI" ((ulong)(b0)) \ : "cc") # if defined(__arm__) # define umul_ppmm(xh, xl, a, b) \ __asm__("umull %0,%1,%2,%3" \ : "=&r" (xl), "=&r" (xh) \ : "r" (a), "r" (b)) # define smul_ppmm(xh, xl, a, b) \ __asm__("smull %0,%1,%2,%3" \ : "=&r" (xl), "=&r" (xh) \ : "r" (a), "r" (b)) # else # define umul_ppmm(xh, xl, a, b) \ __asm__("mul %0,%2,%3\n" \ "umulh %1,%2,%3" \ : "=&r" (xl), "=&r" (xh) \ : "r" (a), "r" (b)) # define smul_ppmm(xh, xl, a, b) \ __asm__("mul %0,%2,%3\n" \ "smulh %1,%2,%3" \ : "=&r" (xl), "=&r" (xh) \ : "r" (a), "r" (b)) # endif #endif #endif flint-3.1.3/src/longlong_div_gnu.h000066400000000000000000000021141461254215100171230ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef LONGLONG_DIV_H #define LONGLONG_DIV_H #if defined (__amd64__) || (GMP_LIMB_BITS == 32 && (defined (__i386__) || defined (__i486__))) # if GMP_LIMB_BITS == 64 && defined (__amd64__) # define _FLINT_ASM_DIV "divq" # define _FLINT_ASM_IDIV "idivq" # else # define _FLINT_ASM_DIV "divl" # define _FLINT_ASM_IDIV "idivl" # endif # define udiv_qrnnd(q, r, n1, n0, dx) \ __asm__ volatile (_FLINT_ASM_DIV " %4" \ : "=a" (q), "=d" (r) \ : "0" ((ulong)(n0)), "1" ((ulong)(n1)), \ "rm" ((ulong)(dx))) # define sdiv_qrnnd(q, r, n1, n0, dx) \ __asm__ volatile (_FLINT_ASM_IDIV " %4" \ : "=a" (q), "=d" (r) \ : "0" ((ulong)(n0)), "1" ((ulong)(n1)), \ "rm" ((ulong)(dx))) #endif #endif flint-3.1.3/src/longlong_msc_arm64.h000066400000000000000000000020221461254215100172610ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef LONGLONG_MSC_H #define LONGLONG_MSC_H #include #include #include /* Trailing and leading zeros */ # define flint_clz _CountLeadingZeros64 # define flint_ctz flint_ctz static inline int flint_ctz(ulong x) { unsigned long int index; _BitScanForward64(&index, x); return index; } /* Byte swap */ # define byte_swap(x) do { (x) = _byteswap_uint64(x); } while (0) /* Multiplication */ #define umul_ppmm(r1, r0, u, v) \ do \ { \ (r0) = (u) * (v); \ (r1) = __umulh(u, v); \ } while (0) #define smul_ppmm(r1, r0, u, v) \ do \ { \ (r0) = (u) * (v); \ (r1) = __mulh(u, v); \ } while (0) #endif flint-3.1.3/src/longlong_msc_x86.h000066400000000000000000000060731461254215100167670ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef LONGLONG_MSC_H #define LONGLONG_MSC_H #include #include #include #if defined(_M_IX86) || FLINT_BITS == 32 /* Trailing and leading zeros */ # define flint_clz _lzcnt_u32 # define flint_ctz _tzcnt_u32 /* Byte swap */ # define byte_swap(x) do { (x) = _byteswap_ulong(x); } while (0) /* Addition and subtraction */ # define _FLINT_ADC _addcarry_u32 # define _FLINT_SBB _subborrow_u32 /* Multiplication */ # define umul_ppmm(r1, r0, u, v) \ do \ { \ unsigned __int64 _tmp = __emulu(u, v); \ (r0) = _tmp; \ (r1) = _tmp >> 32; \ } while (0) # define smul_ppmm(r1, r0, u, v) \ do \ { \ __int64 _tmp = __emul(u, v); \ (r0) = _tmp; \ (r1) = _tmp >> 32; \ } while (0) /* Division */ # define _FLINT_DIV _udiv64 # define _FLINT_IDIV _div64 #else /* Trailing and leading zeros */ # define flint_clz _lzcnt_u64 # define flint_ctz _tzcnt_u64 /* Byte swap */ # define byte_swap(x) do { (x) = _byteswap_uint64(x); } while (0) /* Addition and subtraction */ # define _FLINT_ADC _addcarry_u64 # define _FLINT_SBB _subborrow_u64 /* Multiplication */ #define umul_ppmm(r1, r0, u, v) do { (r0) = _umul128(u, v, &(r1)); } while (0) #define smul_ppmm(r1, r0, u, v) do { (r0) = _mul128(u, v, &(r1)); } while (0) /* Division */ # define _FLINT_DIV _udiv128 # define _FLINT_IDIV _div128 #endif /* Addition and subtraction */ #define add_ssaaaa(s1, s0, a1, a0, b1, b0) \ do \ { \ unsigned char _carry; \ _carry = _FLINT_ADC(0, a0, b0, &(s0)); \ _FLINT_ADC(_carry, a1, b1, &(s1)); \ } while (0) #define add_sssaaaaaa(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ do \ { \ unsigned char _carry; \ _carry = _FLINT_ADC(0, a0, b0, &(s0)); \ _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \ _FLINT_ADC(_carry, a2, b2, &(s2)); \ } while (0) #define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ do \ { \ unsigned char _carry; \ _carry = _FLINT_ADC(0, a0, b0, &(s0)); \ _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \ _carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \ _FLINT_ADC(_carry, a3, b3, &(s3)); \ } while (0) #define sub_ddmmss(s1, s0, a1, a0, b1, b0) \ do \ { \ unsigned char _carry; \ _carry = _FLINT_SBB(0, a0, b0, &(s0)); \ _FLINT_SBB(_carry, a1, b1, &(s1)); \ } while (0) #define sub_dddmmmsss(s2, s1, s0, a2, a1, a0, b2, b1, b0) \ do \ { \ unsigned char _carry; \ _carry = _FLINT_SBB(0, a0, b0, &(s0)); \ _carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \ _FLINT_SBB(_carry, a2, b2, &(s2)); \ } while (0) /* Division */ #define udiv_qrnnd(q, r, n1, n0, dx) do { (q) = _FLINT_DIV(n1, n0, dx, &(r)); } while (0) #define sdiv_qrnnd(q, r, n1, n0, dx) do { (q) = _FLINT_IDIV(n1, n0, dx, &(r)); } while (0) #endif flint-3.1.3/src/machine_vectors.h000066400000000000000000001170711461254215100167530ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef MACHINE_VECTORS_H #define MACHINE_VECTORS_H #define ALIGN_STRUCT(x) __attribute__((aligned(x))) #include #if defined(__GNUC__) # if defined(__AVX2__) # include # elif defined(__ARM_NEON) # include # endif #elif defined(_MSC_VER) # if defined(__AVX2__) # include # elif defined(_M_ARM64) # include # endif #endif #include "flint.h" #include "templates.h" #ifdef __cplusplus extern "C" { #endif #if defined(__AVX2__) /* In general the machine vector types should either be passed by const ref or the whole function should be forced inline as some platforms have buggy pass by value. */ typedef ulong vec1n; typedef __m128i vec2n; typedef __m256i vec4n; typedef struct {__m256i e1, e2;} vec8n; typedef double vec1d; typedef __m128d vec2d; typedef __m256d vec4d; typedef struct {__m256d e1, e2;} vec8d; FLINT_FORCE_INLINE void vec4d_print(vec4d a) { #ifdef _MSC_VER double as[4]; _mm256_storeu_pd(as, a); flint_printf("{%f, %f, %f, %f}", as[0], as[1], as[2], as[3]); #else flint_printf("{%f, %f, %f, %f}", a[0], a[1], a[2], a[3]); #endif } FLINT_FORCE_INLINE void vec4n_print(vec4n a) { flint_printf("[hi %016llx_%016llx_%016llx_%016llx lo]", _mm256_extract_epi64(a, 3), _mm256_extract_epi64(a, 2), _mm256_extract_epi64(a, 1), _mm256_extract_epi64(a, 0)); } FLINT_FORCE_INLINE vec4n vec4d_convert_limited_vec4n(vec4d a) { __m256d t = _mm256_set1_pd(0x1.0p52); return _mm256_castpd_si256(_mm256_xor_pd(_mm256_add_pd(a, t), t)); } FLINT_FORCE_INLINE void vec4n_store_unaligned(ulong* z, vec4n a) { _mm256_storeu_si256((__m256i*) z, a); } FLINT_FORCE_INLINE vec4n vec4n_load_unaligned(const ulong* a) { return _mm256_loadu_si256((__m256i*) a); } FLINT_FORCE_INLINE vec8n vec8n_load_unaligned(const ulong* a) { vec8n z = {vec4n_load_unaligned(a+0), vec4n_load_unaligned(a+4)}; return z; } FLINT_FORCE_INLINE vec4d vec4n_convert_limited_vec4d(vec4n a) { __m256d t = _mm256_set1_pd(0x1.0p52); return _mm256_sub_pd(_mm256_or_pd(_mm256_castsi256_pd(a), t), t); } /* !!! the outputs are also permuted !!! */ FLINT_FORCE_INLINE vec8d _vec8i32_convert_vec8d(__m256i a) { __m256i mask = _mm256_set1_epi32(0x43300000); __m256i ak0 = _mm256_unpacklo_epi32(a, mask); __m256i ak1 = _mm256_unpackhi_epi32(a, mask); __m256d t = _mm256_set1_pd(0x1.0p52); vec8d z; z.e1 = _mm256_sub_pd(_mm256_castsi256_pd(ak0), t); z.e2 = _mm256_sub_pd(_mm256_castsi256_pd(ak1), t); return z; } /* this does not work because i must be a compile-time constant FLINT_FORCE_INLINE ulong vec4n_get_index(vec4n a, const int i) { return _mm256_extract_epi64(a, i); } */ FLINT_FORCE_INLINE vec4n vec4n_set_n4(ulong a0, ulong a1, ulong a2, ulong a3) { return _mm256_set_epi64x(a3, a2, a1, a0); } /* vec1 **************************************************/ FLINT_FORCE_INLINE vec1d vec1d_load(const double* a) { return a[0]; } FLINT_FORCE_INLINE vec1d vec1d_load_aligned(const double* a) { return a[0]; } FLINT_FORCE_INLINE vec1d vec1d_load_unaligned(const double* a) { return a[0]; } FLINT_FORCE_INLINE void vec1d_store(double* z, vec1d a) { z[0] = a; } FLINT_FORCE_INLINE void vec1d_store_aligned(double* z, vec1d a) { z[0] = a; } FLINT_FORCE_INLINE void vec1d_store_unaligned(double* z, vec1d a) { z[0] = a; } FLINT_FORCE_INLINE int vec1d_same(double a, double b) { return a == b; } FLINT_FORCE_INLINE vec1d vec1d_set_d(double a) { return a; } FLINT_FORCE_INLINE vec1d vec1d_round(vec1d a) { return rint(a); } FLINT_FORCE_INLINE vec1d vec1d_zero(void) { return 0.0; } FLINT_FORCE_INLINE vec1d vec1d_one(void) { return 1.0; } FLINT_FORCE_INLINE vec1d vec1d_add(vec1d a, vec1d b) { return a + b; } FLINT_FORCE_INLINE vec1d vec1d_sub(vec1d a, vec1d b) { return a - b; } FLINT_FORCE_INLINE vec1d vec1d_addsub(vec1d a, vec1d b) { return a - b; } FLINT_FORCE_INLINE vec1d vec1d_neg(vec1d a) { return -a; } FLINT_FORCE_INLINE vec1d vec1d_abs(vec1d a) { return fabs(a); } FLINT_FORCE_INLINE vec1d vec1d_max(vec1d a, vec1d b) { return fmax(a, b); } FLINT_FORCE_INLINE vec1d vec1d_min(vec1d a, vec1d b) { return fmin(a, b); } FLINT_FORCE_INLINE vec1d vec1d_mul(vec1d a, vec1d b) { return a*b; } FLINT_FORCE_INLINE vec1d vec1d_half(vec1d a) { return a*0.5; } FLINT_FORCE_INLINE vec1d vec1d_div(vec1d a, vec1d b) { return a/b; } FLINT_FORCE_INLINE vec1d vec1d_fmadd(vec1d a, vec1d b, vec1d c) { return fma(a, b, c); } FLINT_FORCE_INLINE vec1d vec1d_fmsub(vec1d a, vec1d b, vec1d c) { return fma(a, b, -c); } FLINT_FORCE_INLINE vec1d vec1d_fnmadd(vec1d a, vec1d b, vec1d c) { return fma(-a, b, c); } FLINT_FORCE_INLINE vec1d vec1d_fnmsub(vec1d a, vec1d b, vec1d c) { return fma(-a, b, -c); } FLINT_FORCE_INLINE vec1d vec1d_blendv(vec1d a, vec1d b, vec1d c) { return c >= 0 ? a : b; } /* [0,n] -> [-n/2, n/2] */ FLINT_FORCE_INLINE vec1d vec1d_reduce_0n_to_pmhn(vec1d a, vec1d n) { vec1d halfn = 0.5*n; return a > halfn ? a - n : a; } FLINT_FORCE_INLINE vec1d vec1d_reduce_pm1n_to_pmhn(vec1d a, vec1d n) { vec1d t = a + n; vec1d halfn = 0.5*n; if (a > halfn) return a - n; else if (t < halfn) return t; else return a; } /* [0,2n) to [0,n) */ FLINT_FORCE_INLINE vec1d vec1d_reduce_2n_to_n(vec1d a, vec1d n) { return a-n >= 0 ? a-n : a; } /* vec4 *****************************************************/ FLINT_FORCE_INLINE double vec4d_get_index(vec4d a, const int i) { #ifdef _MSC_VER double as[4]; _mm256_storeu_pd(as, a); return as[i]; #else return a[i]; #endif } FLINT_FORCE_INLINE vec4d vec4d_load(const double* a) { return _mm256_load_pd(a); } FLINT_FORCE_INLINE vec4d vec4d_load_aligned(const double* a) { return _mm256_load_pd(a); } FLINT_FORCE_INLINE vec4d vec4d_load_unaligned(const double* a) { return _mm256_loadu_pd(a); } FLINT_FORCE_INLINE void vec4d_store(double* z, vec4d a) { _mm256_store_pd(z, a); } FLINT_FORCE_INLINE void vec4d_store_aligned(double* z, vec4d a) { _mm256_store_pd(z, a); } FLINT_FORCE_INLINE void vec4d_store_unaligned(double* z, vec4d a) { _mm256_storeu_pd(z, a); } FLINT_FORCE_INLINE int vec4d_same(vec4d a, vec4d b) { #ifdef _MSC_VER double as[4], bs[4]; _mm256_storeu_pd(as, a); _mm256_storeu_pd(bs, b); return as[0] == bs[0] && as[1] == bs[1] && as[2] == bs[2] && as[3] == bs[3]; #else return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]; #endif } FLINT_FORCE_INLINE vec4d vec4d_set_d(double a) { return _mm256_set1_pd(a); } FLINT_FORCE_INLINE vec4d vec4d_set_d4(double a0, double a1, double a2, double a3) { return _mm256_set_pd(a3, a2, a1, a0); } FLINT_FORCE_INLINE vec4d vec4d_round(vec4d a) { return _mm256_round_pd(a, 4); } FLINT_FORCE_INLINE vec4d vec4d_zero(void) { return _mm256_setzero_pd(); } FLINT_FORCE_INLINE vec4d vec4d_one(void) { return vec4d_set_d(1); } FLINT_FORCE_INLINE vec4d vec4d_add(vec4d a, vec4d b) { return _mm256_add_pd(a, b); } FLINT_FORCE_INLINE vec4d vec4d_sub(vec4d a, vec4d b) { return _mm256_sub_pd(a, b); } FLINT_FORCE_INLINE vec4d vec4d_addsub(vec4d a, vec4d b) { return _mm256_addsub_pd(a, b); } FLINT_FORCE_INLINE vec4d vec4d_neg(vec4d a) { __m256d mask = _mm256_castsi256_pd(_mm256_set1_epi64x(UWORD(0x8000000000000000))); return _mm256_xor_pd(a, mask); } FLINT_FORCE_INLINE vec4d vec4d_abs(vec4d a) { __m256d mask = _mm256_castsi256_pd(_mm256_set1_epi64x(UWORD(0x7fffffffffffffff))); return _mm256_and_pd(a, mask); } FLINT_FORCE_INLINE vec4d vec4d_max(vec4d a, vec4d b) { return _mm256_max_pd(a, b); } FLINT_FORCE_INLINE vec4d vec4d_min(vec4d a, vec4d b) { return _mm256_min_pd(a, b); } FLINT_FORCE_INLINE vec4d vec4d_mul(vec4d a, vec4d b) { return _mm256_mul_pd(a, b); } FLINT_FORCE_INLINE vec4d vec4d_half(vec4d a) { return vec4d_mul(a, vec4d_set_d(0.5)); } FLINT_FORCE_INLINE vec4d vec4d_div(vec4d a, vec4d b) { return _mm256_div_pd(a, b); } FLINT_FORCE_INLINE vec4d vec4d_fmadd(vec4d a, vec4d b, vec4d c) { #ifndef AVOID_AVX2 return _mm256_fmadd_pd(a, b, c); #else return _mm256_macc_pd(a, b, c); #endif } FLINT_FORCE_INLINE vec4d vec4d_fmsub(vec4d a, vec4d b, vec4d c) { #ifndef AVOID_AVX2 return _mm256_fmsub_pd(a, b, c); #else return _mm256_msub_pd(a, b, c); #endif } FLINT_FORCE_INLINE vec4d vec4d_fnmadd(vec4d a, vec4d b, vec4d c) { #ifndef AVOID_AVX2 return _mm256_fnmadd_pd(a, b, c); #else return _mm256_nmacc_pd(a, b, c); #endif } FLINT_FORCE_INLINE vec4d vec4d_fnmsub(vec4d a, vec4d b, vec4d c) { #ifndef AVOID_AVX2 return _mm256_fnmsub_pd(a, b, c); #else return _mm256_nmsub_pd(a, b, c); #endif } FLINT_FORCE_INLINE vec4d vec4d_blendv(vec4d a, vec4d b, vec4d c) { return _mm256_blendv_pd(a, b, c); } // return {a[0], b[0], a[2], b[2]} FLINT_FORCE_INLINE vec4d vec4d_unpacklo(vec4d a, vec4d b) { return _mm256_unpacklo_pd(a, b); } // return {a[1], b[1], a[3], b[3]} FLINT_FORCE_INLINE vec4d vec4d_unpackhi(vec4d a, vec4d b) { return _mm256_unpackhi_pd(a, b); } /* permute_i0_i1_i2_i3(a): return {a[i0], a[i1], a[i2], a[i3]} */ #ifndef AVOID_AVX2 #define DEFINE_IT(i0, i1, i2, i3) \ FLINT_FORCE_INLINE vec4d CAT6(vec4d, permute, i0, i1, i2, i3)(vec4d a) { \ return _mm256_permute4x64_pd(a, i0 + 4*(i1 + 4*(i2 + 4*i3))); \ } #else #define DEFINE_IT(i0, i1, i2, i3) \ FLINT_FORCE_INLINE vec4d CAT6(vec4d, permute, i0, i1, i2, i3)(vec4d a) { \ return vec4d_set_d4(a[i0], a[i1], a[i2], a[i3]); \ } #endif DEFINE_IT(0,2,1,3) DEFINE_IT(3,1,2,0) DEFINE_IT(3,2,1,0) #undef DEFINE_IT /* permute2_i0_i1(a): return {v[i0], v[i1]} | v[0] | v[1] | v[2] | v[3] | a[0], a[1] a[2], a[3] b[0], b[1] b[2], b[3] */ #define DEFINE_IT(i0, i1) \ FLINT_FORCE_INLINE vec4d CAT4(vec4d, permute2, i0, i1)(vec4d a, vec4d b) { \ return _mm256_permute2f128_pd(a, b, i0 + 16*i1); \ } DEFINE_IT(0,2) DEFINE_IT(1,3) #undef DEFINE_IT FLINT_FORCE_INLINE vec4d vec4d_unpack_lo_permute_0_2_1_3(vec4d u, vec4d v) { return vec4d_permute_0_2_1_3(vec4d_unpacklo(u, v)); } FLINT_FORCE_INLINE vec4d vec4d_unpack_hi_permute_0_2_1_3(vec4d u, vec4d v) { return vec4d_permute_0_2_1_3(vec4d_unpackhi(u, v)); } FLINT_FORCE_INLINE vec4d vec4d_unpackhi_permute_3_1_2_0(vec4d u, vec4d v) { return vec4d_permute_3_1_2_0(vec4d_unpackhi(u, v)); } FLINT_FORCE_INLINE vec4d vec4d_unpacklo_permute_3_1_2_0(vec4d u, vec4d v) { return vec4d_permute_3_1_2_0(vec4d_unpacklo(u, v)); } /* view the 4 vectors as the rows of a 4x4 matrix */ #define VEC4D_TRANSPOSE(z0, z1, z2, z3, a0, a1, a2, a3) \ { \ vec4d _t0, _t1, _t2, _t3; \ _t0 = vec4d_unpacklo(a0, a1); \ _t1 = vec4d_unpackhi(a0, a1); \ _t2 = vec4d_unpacklo(a2, a3); \ _t3 = vec4d_unpackhi(a2, a3); \ z0 = vec4d_permute2_0_2(_t0, _t2); \ z1 = vec4d_permute2_0_2(_t1, _t3); \ z2 = vec4d_permute2_1_3(_t0, _t2); \ z3 = vec4d_permute2_1_3(_t1, _t3); \ } FLINT_FORCE_INLINE vec4d vec4d_cmp_ge(vec4d a, vec4d b) { return _mm256_cmp_pd(a, b, _CMP_GE_OQ); } FLINT_FORCE_INLINE vec4d vec4d_cmp_gt(vec4d a, vec4d b) { return _mm256_cmp_pd(a, b, _CMP_GT_OQ); } FLINT_FORCE_INLINE vec4d vec4d_reduce_0n_to_pmhn(vec4d a, vec4d n) { vec4d halfn = vec4d_half(n); return vec4d_blendv(a, vec4d_sub(a, n), vec4d_cmp_gt(a, halfn)); } FLINT_FORCE_INLINE vec4d vec4d_reduce_pm1n_to_pmhn(vec4d a, vec4d n) { vec4d halfn = vec4d_half(n); vec4d t = vec4d_blendv(n, vec4d_neg(n), a); a = vec4d_blendv(a, vec4d_sub(a, t), vec4d_cmp_gt(vec4d_abs(a), halfn)); return a; } /* [0,2n) to [0,n) */ FLINT_FORCE_INLINE vec4d vec4d_reduce_2n_to_n(vec4d a, vec4d n) { vec4d s = vec4d_sub(a, n); return vec4d_blendv(s, a, s); } /* vec8 **********************************************************************/ FLINT_FORCE_INLINE double vec8d_get_index(vec8d a, int i) { return i < 4 ? vec4d_get_index(a.e1, i) : vec4d_get_index(a.e2, i - 4); } FLINT_FORCE_INLINE vec8d vec8d_set_d(double a) { vec4d z1 = vec4d_set_d(a); vec8d z = {z1, z1}; return z; } FLINT_FORCE_INLINE vec8d vec8d_set_d8(double a0, double a1, double a2, double a3, double a4, double a5, double a6, double a7) { vec4d z1 = vec4d_set_d4(a0, a1, a2, a3); vec4d z2 = vec4d_set_d4(a4, a5, a6, a7); vec8d z = {z1, z2}; return z; } FLINT_FORCE_INLINE vec8d vec8d_load(const double* a) { vec8d z = {vec4d_load(a+0), vec4d_load(a+4)}; return z; } FLINT_FORCE_INLINE vec8d vec8d_load_aligned(const double* a) { vec8d z = {vec4d_load_aligned(a+0), vec4d_load_aligned(a+4)}; return z; } FLINT_FORCE_INLINE vec8d vec8d_load_unaligned(const double* a) { vec8d z = {vec4d_load_unaligned(a+0), vec4d_load_unaligned(a+4)}; return z; } FLINT_FORCE_INLINE void vec8d_store(double* z, vec8d a) { vec4d_store(z+0, a.e1); vec4d_store(z+4, a.e2); } FLINT_FORCE_INLINE void vec8d_store_aligned(double* z, vec8d a) { vec4d_store_aligned(z+0, a.e1); vec4d_store_aligned(z+4, a.e2); } FLINT_FORCE_INLINE void vec8d_store_unaligned(double* z, vec8d a) { vec4d_store_unaligned(z+0, a.e1); vec4d_store_unaligned(z+4, a.e2); } FLINT_FORCE_INLINE int vec8d_same(vec8d a, vec8d b) { return vec4d_same(a.e1, b.e1) && vec4d_same(a.e2, b.e2); } FLINT_FORCE_INLINE vec8d vec8n_convert_limited_vec8d(vec8n a) { vec8d z = {vec4n_convert_limited_vec4d(a.e1), vec4n_convert_limited_vec4d(a.e2)}; return z; } /* reduce_pm1no_to_0n(a, n): return a mod n in [0,n) assuming a in (-n,n) */ #define DEFINE_IT(V) \ FLINT_FORCE_INLINE V V##_reduce_pm1no_to_0n(V a, V n) { \ return V##_blendv(a, V##_add(a, n), a); \ } DEFINE_IT(vec1d) DEFINE_IT(vec4d) #undef DEFINE_IT /* reduce_to_pm1n(a, n, ninv): return a mod n in [-n,n] */ #define DEFINE_IT(V) \ FLINT_FORCE_INLINE V V##_reduce_to_pm1n(V a, V n, V ninv) { \ return V##_fnmadd(V##_round(V##_mul(a, ninv)), n, a); \ } DEFINE_IT(vec1d) DEFINE_IT(vec4d) #undef DEFINE_IT /* reduce_to_pm1n(a, n, ninv): return a mod n in (-n,n) */ #define DEFINE_IT(V) \ FLINT_FORCE_INLINE V V##_reduce_to_pm1no(V a, V n, V ninv) { \ return V##_fnmadd(V##_round(V##_mul(a, ninv)), n, a); \ } DEFINE_IT(vec1d) DEFINE_IT(vec4d) #undef DEFINE_IT /* reduce_to_0n(a, n, ninv): return a mod n in [0,n) */ #define DEFINE_IT(V) \ FLINT_FORCE_INLINE V V##_reduce_to_0n(V a, V n, V ninv) { \ return V##_reduce_pm1no_to_0n(V##_reduce_to_pm1no(a, n, ninv), n); \ } DEFINE_IT(vec1d) DEFINE_IT(vec4d) #undef DEFINE_IT #define DEFINE_IT(V) \ FLINT_FORCE_INLINE int V##_same_mod(V a, V b, V n, V ninv) { \ return V##_same(V##_reduce_to_0n(a, n, ninv), V##_reduce_to_0n(b, n, ninv)); \ } DEFINE_IT(vec1d) DEFINE_IT(vec4d) #undef DEFINE_IT /* mulmod(a, b, n, 1.0/n): return a*b mod n assuming fft_small_mulmod_satisfies_bounds(n): Products a*b in the range (-2*n^2, 2*n^2) are reduced to the range (-1*n, 1*n). Products a*b in the range (-4*n^2, 4*n^2) are reduced to the range (-3/2*n, 3/2*n). otherwise the more pessimistic: Products a*b in the range (-2*n^2, 2*n^2) are reduced to the range (-9/8*n, 9/8*n). Products a*b in the range (-4*n^2, 4*n^2) are reduced to the range (-7/4*n, 7/4*n). floating point round mode is always assumed to be set to nearest */ #define DEFINE_IT(V) \ FLINT_FORCE_INLINE V V##_mulmod(V a, V b, V n, V ninv) { \ V h = V##_mul(a, b); \ V q = V##_round(V##_mul(h, ninv)); \ V l = V##_fmsub(a, b, h); \ return V##_add(V##_fnmadd(q, n, h), l); \ } \ \ FLINT_FORCE_INLINE V V##_nmulmod(V a, V b, V n, V ninv) { \ V h = V##_mul(a, b); \ V q = V##_round(V##_mul(h, ninv)); \ V l = V##_fnmadd(a, b, h); \ return V##_sub(l, V##_fnmadd(q, n, h)); \ } DEFINE_IT(vec1d) DEFINE_IT(vec4d) #undef DEFINE_IT #define EXTEND_VEC_DEF0(U, V, f) \ FLINT_FORCE_INLINE V V##f(void) { \ U z1 = U##f(); \ U z2 = U##f(); \ V z = {z1, z2}; \ return z; \ } #define EXTEND_VEC_DEF1(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a) { \ U z1 = U##f(a.e1); \ U z2 = U##f(a.e2); \ V z = {z1, z2}; \ return z; \ } #define EXTEND_VEC_DEF2(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a, V b) { \ U z1 = U##f(a.e1, b.e1); \ U z2 = U##f(a.e2, b.e2); \ V z = {z1, z2}; \ return z; \ } #define EXTEND_VEC_DEF3(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a, V b, V c) { \ U z1 = U##f(a.e1, b.e1, c.e1); \ U z2 = U##f(a.e2, b.e2, c.e2); \ V z = {z1, z2}; \ return z; \ } #define EXTEND_VEC_DEF4(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a, V b, V c, V d) { \ U z1 = U##f(a.e1, b.e1, c.e1, d.e1); \ U z2 = U##f(a.e2, b.e2, c.e2, d.e2); \ V z = {z1, z2}; \ return z; \ } FLINT_FORCE_INLINE vec4n vec4n_set_n(ulong a) { return _mm256_set1_epi64x(a); } FLINT_FORCE_INLINE vec4n vec4n_add(vec4n a, vec4n b) { return _mm256_add_epi64(a, b); } FLINT_FORCE_INLINE vec4n vec4n_sub(vec4n a, vec4n b) { return _mm256_sub_epi64(a, b); } /* for n < 2^63 */ FLINT_FORCE_INLINE vec4n vec4n_addmod_limited(vec4n a, vec4n b, vec4n n) { vec4n s = vec4n_add(a, b); vec4n t = vec4n_sub(s, n); vec4n m = _mm256_srai_epi32(t, 31); m = _mm256_shuffle_epi32(m, 1 + 4*(1 + 4*(3 + 4*(3)))); return _mm256_blendv_epi8(t, s, m); } FLINT_FORCE_INLINE vec4n vec4n_addmod(vec4n a, vec4n b, vec4n n) { vec4n tt = vec4n_set_n(0x8000000000000000); vec4n s = vec4n_add(a, b); #if 0 vec4n m = vec4n_sub(n, tt); vec4n t0 = vec4n_sub(m, a); vec4n t1 = vec4n_sub(b, tt); vec4n t2 = vec4n_sub(t1, t0); return _mm256_blendv_epi8(s, t2, _mm256_cmpgt_epi64(t1, t0)); #else vec4n t0 = vec4n_sub(s, n); vec4n t1 = vec4n_sub(a, tt); vec4n t2 = vec4n_sub(t0, tt); return _mm256_blendv_epi8(t0, s, _mm256_cmpgt_epi64(t2, t1)); #endif } EXTEND_VEC_DEF0(vec4d, vec8d, _zero) EXTEND_VEC_DEF1(vec4d, vec8d, _neg) EXTEND_VEC_DEF1(vec4d, vec8d, _round) EXTEND_VEC_DEF2(vec4d, vec8d, _add) EXTEND_VEC_DEF2(vec4d, vec8d, _sub) EXTEND_VEC_DEF2(vec4d, vec8d, _min) EXTEND_VEC_DEF2(vec4d, vec8d, _max) EXTEND_VEC_DEF2(vec4d, vec8d, _mul) EXTEND_VEC_DEF2(vec4d, vec8d, _div) EXTEND_VEC_DEF2(vec4d, vec8d, _reduce_pm1n_to_pmhn) EXTEND_VEC_DEF2(vec4d, vec8d, _reduce_pm1no_to_0n) EXTEND_VEC_DEF2(vec4d, vec8d, _reduce_2n_to_n) EXTEND_VEC_DEF3(vec4d, vec8d, _reduce_to_pm1n) EXTEND_VEC_DEF3(vec4d, vec8d, _reduce_to_pm1no) EXTEND_VEC_DEF3(vec4d, vec8d, _reduce_to_0n) EXTEND_VEC_DEF3(vec4d, vec8d, _fmadd) EXTEND_VEC_DEF3(vec4d, vec8d, _fmsub) EXTEND_VEC_DEF3(vec4d, vec8d, _fnmadd) EXTEND_VEC_DEF3(vec4d, vec8d, _fnmsub) EXTEND_VEC_DEF3(vec4d, vec8d, _blendv) EXTEND_VEC_DEF3(vec4n, vec8n, _addmod) EXTEND_VEC_DEF3(vec4n, vec8n, _addmod_limited) EXTEND_VEC_DEF4(vec4d, vec8d, _mulmod) EXTEND_VEC_DEF4(vec4d, vec8d, _nmulmod) #undef EXTEND_VEC_DEF4 #undef EXTEND_VEC_DEF3 #undef EXTEND_VEC_DEF2 #undef EXTEND_VEC_DEF1 #undef EXTEND_VEC_DEF0 FLINT_FORCE_INLINE vec8n vec8n_set_n(ulong a) { vec4n x = vec4n_set_n(a); vec8n z = {x, x}; return z; } FLINT_FORCE_INLINE vec4n vec4n_bit_shift_right(vec4n a, ulong b) { return _mm256_srl_epi64(a, _mm_set_epi32(0,0,0,b)); } FLINT_FORCE_INLINE vec8n vec8n_bit_shift_right(vec8n a, ulong b) { vec8n z = {vec4n_bit_shift_right(a.e1, b), vec4n_bit_shift_right(a.e2, b)}; return z; } #define vec4n_bit_shift_right_32(a) vec4n_bit_shift_right((a), 32) #define vec8n_bit_shift_right_32(a) vec8n_bit_shift_right((a), 32) FLINT_FORCE_INLINE vec4n vec4n_bit_and(vec4n a, vec4n b) { return _mm256_and_si256(a, b); } FLINT_FORCE_INLINE vec8n vec8n_bit_and(vec8n a, vec8n b) { vec8n z = {vec4n_bit_and(a.e1, b.e1), vec4n_bit_and(a.e2, b.e2)}; return z; } #elif defined(__ARM_NEON) || defined(_M_ARM64) typedef ulong vec1n; typedef uint64x2_t vec2n; typedef struct {vec2n e1, e2;} vec4n; typedef struct {vec4n e1, e2;} vec8n; typedef double vec1d; typedef float64x2_t vec2d; typedef struct {vec2d e1, e2;} vec4d; typedef struct {vec4d e1, e2;} vec8d; #define EXTEND_VEC_DEF0(U, V, f) \ FLINT_FORCE_INLINE V V##f(void) { \ U z1 = U##f(); \ U z2 = U##f(); \ V z = {z1, z2}; return z; \ } #define EXTEND_VEC_DEF1(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a) { \ U z1 = U##f(a.e1); \ U z2 = U##f(a.e2); \ V z = {z1, z2}; return z; \ } #define EXTEND_VEC_DEF2(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a, V b) { \ U z1 = U##f(a.e1, b.e1); \ U z2 = U##f(a.e2, b.e2); \ V z = {z1, z2}; return z; \ } #define EXTEND_VEC_DEF3(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a, V b, V c) { \ U z1 = U##f(a.e1, b.e1, c.e1); \ U z2 = U##f(a.e2, b.e2, c.e2); \ V z = {z1, z2}; return z; \ } #define EXTEND_VEC_DEF4(U, V, f) \ FLINT_FORCE_INLINE V V##f(V a, V b, V c, V d) { \ U z1 = U##f(a.e1, b.e1, c.e1, d.e1); \ U z2 = U##f(a.e2, b.e2, c.e2, d.e2); \ V z = {z1, z2}; return z; \ } /* vec1 **************************************************/ FLINT_FORCE_INLINE vec1d vec1d_load(const double* a) { return a[0]; } FLINT_FORCE_INLINE vec1d vec1d_load_aligned(const double* a) { return a[0]; } FLINT_FORCE_INLINE vec1d vec1d_load_unaligned(const double* a) { return a[0]; } FLINT_FORCE_INLINE void vec1d_store(double* z, vec1d a) { z[0] = a; } FLINT_FORCE_INLINE void vec1d_store_aligned(double* z, vec1d a) { z[0] = a; } FLINT_FORCE_INLINE void vec1d_store_unaligned(double* z, vec1d a) { z[0] = a; } FLINT_FORCE_INLINE int vec1d_same(double a, double b) { return a == b; } FLINT_FORCE_INLINE vec1d vec1d_set_d(double a) { return a; } FLINT_FORCE_INLINE vec1d vec1d_round(vec1d a) { return rint(a); } FLINT_FORCE_INLINE vec1d vec1d_zero(void) { return 0.0; } FLINT_FORCE_INLINE vec1d vec1d_one(void) { return 1.0; } FLINT_FORCE_INLINE vec1d vec1d_add(vec1d a, vec1d b) { return a + b; } FLINT_FORCE_INLINE vec1d vec1d_sub(vec1d a, vec1d b) { return a - b; } FLINT_FORCE_INLINE vec1d vec1d_addsub(vec1d a, vec1d b) { return a - b; } FLINT_FORCE_INLINE vec1d vec1d_neg(vec1d a) { return -a; } FLINT_FORCE_INLINE vec1d vec1d_abs(vec1d a) { return fabs(a); } FLINT_FORCE_INLINE vec1d vec1d_max(vec1d a, vec1d b) { return fmax(a, b); } FLINT_FORCE_INLINE vec1d vec1d_min(vec1d a, vec1d b) { return fmin(a, b); } FLINT_FORCE_INLINE vec1d vec1d_mul(vec1d a, vec1d b) { return a*b; } FLINT_FORCE_INLINE vec1d vec1d_half(vec1d a) { return a*0.5; } FLINT_FORCE_INLINE vec1d vec1d_div(vec1d a, vec1d b) { return a/b; } FLINT_FORCE_INLINE vec1d vec1d_fmadd(vec1d a, vec1d b, vec1d c) { return fma(a, b, c); } FLINT_FORCE_INLINE vec1d vec1d_fmsub(vec1d a, vec1d b, vec1d c) { return fma(a, b, -c); } FLINT_FORCE_INLINE vec1d vec1d_fnmadd(vec1d a, vec1d b, vec1d c) { return fma(-a, b, c); } FLINT_FORCE_INLINE vec1d vec1d_fnmsub(vec1d a, vec1d b, vec1d c) { return fma(-a, b, -c); } FLINT_FORCE_INLINE vec1d vec1d_blendv(vec1d a, vec1d b, vec1d c) { return c >= 0 ? a : b; } /* [0,n] -> [-n/2, n/2] */ FLINT_FORCE_INLINE vec1d vec1d_reduce_0n_to_pmhn(vec1d a, vec1d n) { vec1d halfn = 0.5*n; return a > halfn ? a - n : a; } FLINT_FORCE_INLINE vec1d vec1d_reduce_pm1n_to_pmhn(vec1d a, vec1d n) { vec1d t = a + n; vec1d halfn = 0.5*n; if (a > halfn) return a - n; else if (t < halfn) return t; else return a; } /* vec2 **********************************************************************/ FLINT_FORCE_INLINE double vec2d_get_index(vec2d a, int i) { return a[i]; } FLINT_FORCE_INLINE vec2d vec2d_set_d2(double a0, double a1) { double ALIGN_STRUCT(16) data[2] = {a0, a1}; return vld1q_f64((float64_t *) data); } FLINT_FORCE_INLINE vec2d vec2d_set_d(double a) { return vec2d_set_d2(a, a); } FLINT_FORCE_INLINE vec2d vec2d_load(const double* a) { return vld1q_f64(a); } FLINT_FORCE_INLINE vec2d vec2d_load_unaligned(const double* a) { return vld1q_f64(a); } FLINT_FORCE_INLINE vec2d vec2d_load_aligned(const double* a) { return vld1q_f64(a); } FLINT_FORCE_INLINE void vec2d_store(double* z, vec2d a) { vst1q_f64(z, a); } FLINT_FORCE_INLINE void vec2d_store_unaligned(double* z, vec2d a) { vst1q_f64(z, a); } FLINT_FORCE_INLINE void vec2d_store_aligned(double* z, vec2d a) { vst1q_f64(z, a); } FLINT_FORCE_INLINE vec2d vec2d_zero(void) { return vec2d_set_d(0.0); } FLINT_FORCE_INLINE vec2d vec2d_one(void) { return vec2d_set_d(1.0); } FLINT_FORCE_INLINE vec2d vec2d_neg(vec2d a) { return vnegq_f64(a); } FLINT_FORCE_INLINE vec2d vec2d_abs(vec2d a) { return vabsq_f64(a); } FLINT_FORCE_INLINE vec2d vec2d_min(vec2d a, vec2d b) { return vminq_f64(a, b); } FLINT_FORCE_INLINE vec2d vec2d_max(vec2d a, vec2d b) { return vmaxq_f64(a, b); } FLINT_FORCE_INLINE vec2d vec2d_cmp_lt(vec2d a, vec2d b) { return vcvtq_f64_u64(vcltq_f64(a, b)); } FLINT_FORCE_INLINE vec2d vec2d_cmp_gt(vec2d a, vec2d b) { return vcvtq_f64_u64(vcgtq_f64(a, b)); } FLINT_FORCE_INLINE vec2d vec2d_blendv(vec2d a, vec2d b, vec2d c) { return vbslq_f64(vcvtq_u64_f64(c), b, a); } FLINT_FORCE_INLINE vec2d vec2d_add(vec2d a, vec2d b) { return vaddq_f64(a, b); } FLINT_FORCE_INLINE vec2d vec2d_sub(vec2d a, vec2d b) { return vsubq_f64(a, b); } FLINT_FORCE_INLINE vec2d vec2d_mul(vec2d a, vec2d b) { return vmulq_f64(a, b); } FLINT_FORCE_INLINE vec2d vec2d_half(vec2d a) { return vec2d_mul(a, vec2d_set_d(0.5)); } FLINT_FORCE_INLINE vec2d vec2d_fmadd(vec2d a, vec2d b, vec2d c) { return vfmaq_f64(c, a, b); } FLINT_FORCE_INLINE vec2d vec2d_fnmadd(vec2d a, vec2d b, vec2d c) { return vfmsq_f64(c, a, b); } /* these two might be slow due to the extra negation */ FLINT_FORCE_INLINE vec2d vec2d_fmsub(vec2d a, vec2d b, vec2d c) { return -vfmsq_f64(c, a, b); } FLINT_FORCE_INLINE vec2d vec2d_fnmsub(vec2d a, vec2d b, vec2d c) { return -vfmaq_f64(c, a, b); } FLINT_FORCE_INLINE vec2d vec2d_div(vec2d a, vec2d b) { return vdivq_f64(a, b); } FLINT_FORCE_INLINE vec2d vec2d_round(vec2d a) { return vrndnq_f64(a); } FLINT_FORCE_INLINE vec2d vec2d_unpacklo(vec2d a, vec2d b) { return vtrn1q_f64(a, b); } FLINT_FORCE_INLINE vec2d vec2d_unpackhi(vec2d a, vec2d b) { return vtrn2q_f64(a, b); } FLINT_FORCE_INLINE vec1d vec1d_reduce_to_pm1no(vec1d a, vec1d n, vec1d ninv) { return vec1d_fnmadd(vec1d_round(vec1d_mul(a, ninv)), n, a); } FLINT_FORCE_INLINE vec2d vec2d_reduce_to_pm1no(vec2d a, vec2d n, vec2d ninv) { return vec2d_fnmadd(vec2d_round(vec2d_mul(a, ninv)), n, a); } FLINT_FORCE_INLINE vec1d vec1d_reduce_to_pm1n(vec1d a, vec1d n, vec1d ninv) { return vec1d_fnmadd(vec1d_round(vec1d_mul(a, ninv)), n, a); } FLINT_FORCE_INLINE vec2d vec2d_reduce_to_pm1n(vec2d a, vec2d n, vec2d ninv) { return vec2d_fnmadd(vec2d_round(vec2d_mul(a, ninv)), n, a); } FLINT_FORCE_INLINE vec2d vec2d_reduce_0n_to_pmhn(vec2d a, vec2d n) { vec2d halfn = vec2d_half(n); return vec2d_blendv(a, vec2d_sub(a, n), vec2d_cmp_gt(a, halfn)); } FLINT_FORCE_INLINE vec2d vec2d_reduce_pm1n_to_pmhn(vec2d a, vec2d n) { vec2d halfn = vec2d_half(n); vec2d t = vec2d_blendv(n, vec2d_neg(n), vec2d_cmp_lt(a, vec2d_zero())); return vec2d_blendv(a, vec2d_sub(a, t), vec2d_cmp_gt(vec2d_abs(a), halfn)); } FLINT_FORCE_INLINE vec1d vec1d_reduce_pm1no_to_0n(vec1d a, vec1d n) { return a >= 0 ? a : a + n; } FLINT_FORCE_INLINE vec2d vec2d_reduce_pm1no_to_0n(vec2d a, vec2d n) { return vec2d_blendv(a, vec2d_add(a, n), vec2d_cmp_lt(a, vec2d_zero())); } FLINT_FORCE_INLINE vec1d vec1d_reduce_to_0n(vec1d a, vec1d n, vec1d ninv) { return vec1d_reduce_pm1no_to_0n(vec1d_reduce_to_pm1no(a, n, ninv), n); } FLINT_FORCE_INLINE vec2d vec2d_reduce_to_0n(vec2d a, vec2d n, vec2d ninv) { return vec2d_reduce_pm1no_to_0n(vec2d_reduce_to_pm1no(a, n, ninv), n); } /* mulmod(a, b, n, ninv): return a*b mod n in [-n,n] with assumptions */ #define DEFINE_IT(V) \ FLINT_FORCE_INLINE V V##_mulmod(V a, V b, V n, V ninv) { \ V h = V##_mul(a, b); \ V q = V##_round(V##_mul(h, ninv)); \ V l = V##_fnmadd(a, b, h); \ return V##_sub(V##_fnmadd(q, n, h), l); \ } \ \ FLINT_FORCE_INLINE V V##_nmulmod(V a, V b, V n, V ninv) { \ V h = V##_mul(a, b); \ V q = V##_round(V##_mul(h, ninv)); \ V l = V##_fnmadd(a, b, h); \ return V##_sub(l, V##_fnmadd(q, n, h)); \ } DEFINE_IT(vec1d) DEFINE_IT(vec2d) #undef DEFINE_IT /* vec4 **********************************************************************/ FLINT_FORCE_INLINE vec4d vec4d_set_vec2d2(vec2d a, vec2d b) { vec4d z = {a, b}; return z; } FLINT_FORCE_INLINE double vec4d_get_index(vec4d a, int i) { return i < 2 ? vec2d_get_index(a.e1, i) : vec2d_get_index(a.e2, i - 2); } FLINT_FORCE_INLINE vec4d vec4d_set_d4(double a0, double a1, double a2, double a3) { return vec4d_set_vec2d2(vec2d_set_d2(a0, a1), vec2d_set_d2(a2, a3)); } FLINT_FORCE_INLINE vec4d vec4d_set_d(double a) { vec2d z1 = vec2d_set_d(a); return vec4d_set_vec2d2(z1, z1); } FLINT_FORCE_INLINE void vec4d_store(double* z, vec4d a) { vec2d_store(z+0, a.e1); vec2d_store(z+2, a.e2); } FLINT_FORCE_INLINE void vec4d_store_aligned(double* z, vec4d a) { vec2d_store_aligned(z+0, a.e1); vec2d_store_aligned(z+2, a.e2); } FLINT_FORCE_INLINE void vec4d_store_unaligned(double* z, vec4d a) { vec2d_store_unaligned(z+0, a.e1); vec2d_store_unaligned(z+2, a.e2); } FLINT_FORCE_INLINE vec4d vec4d_load(const double* a) { return vec4d_set_vec2d2(vec2d_load(a+0), vec2d_load(a+2)); } FLINT_FORCE_INLINE vec4d vec4d_load_aligned(const double* a) { return vec4d_set_vec2d2(vec2d_load_aligned(a+0), vec2d_load_aligned(a+2)); } FLINT_FORCE_INLINE vec4d vec4d_load_unaligned(const double* a) { return vec4d_set_vec2d2(vec2d_load_unaligned(a+0), vec2d_load_unaligned(a+2)); } FLINT_FORCE_INLINE vec4d vec4d_permute_0_2_1_3(vec4d a) { return vec4d_set_vec2d2(vec2d_unpacklo(a.e1, a.e2), vec2d_unpackhi(a.e1, a.e2)); } FLINT_FORCE_INLINE vec4d vec4d_permute_3_2_1_0(vec4d a) { return vec4d_set_vec2d2(vextq_f64(a.e2, a.e2, 1), vextq_f64(a.e1, a.e1, 1)); } FLINT_FORCE_INLINE vec4d vec4d_permute_3_1_2_0(vec4d a) { vec2d z1 = vzip2q_f64(a.e2, a.e1); vec2d z2 = vzip1q_f64(a.e2, a.e1); return vec4d_set_vec2d2(z1, z2); } FLINT_FORCE_INLINE vec4d vec4d_permute2_0_2(vec4d a, vec4d b) { return vec4d_set_vec2d2(a.e1, b.e1); } FLINT_FORCE_INLINE vec4d vec4d_permute2_1_3(vec4d a, vec4d b) { return vec4d_set_vec2d2(a.e2, b.e2); } FLINT_FORCE_INLINE vec4d vec4d_unpack_lo_permute_0_2_1_3(vec4d u, vec4d v) { return vec4d_set_vec2d2(vec2d_unpacklo(u.e1, u.e2), vec2d_unpacklo(v.e1, v.e2)); } FLINT_FORCE_INLINE vec4d vec4d_unpack_hi_permute_0_2_1_3(vec4d u, vec4d v) { return vec4d_set_vec2d2(vec2d_unpackhi(u.e1, u.e2), vec2d_unpackhi(v.e1, v.e2)); } FLINT_FORCE_INLINE vec4d vec4d_unpackhi_permute_3_1_2_0(vec4d u, vec4d v) { return vec4d_set_vec2d2(vec2d_unpackhi(v.e2, v.e1), vec2d_unpackhi(u.e2, u.e1)); } FLINT_FORCE_INLINE vec4d vec4d_unpacklo_permute_3_1_2_0(vec4d u, vec4d v) { return vec4d_set_vec2d2(vec2d_unpacklo(v.e2, v.e1), vec2d_unpacklo(u.e2, u.e1)); } #define VEC4D_TRANSPOSE(z0, z1, z2, z3, a0, a1, a2, a3) \ { \ vec4d _t0, _t1, _t2, _t3; \ _t0 = vec4d_unpacklo(a0, a1); \ _t1 = vec4d_unpackhi(a0, a1); \ _t2 = vec4d_unpacklo(a2, a3); \ _t3 = vec4d_unpackhi(a2, a3); \ z0 = vec4d_permute2_0_2(_t0, _t2); \ z1 = vec4d_permute2_0_2(_t1, _t3); \ z2 = vec4d_permute2_1_3(_t0, _t2); \ z3 = vec4d_permute2_1_3(_t1, _t3); \ } EXTEND_VEC_DEF0(vec2d, vec4d, _zero) EXTEND_VEC_DEF0(vec2d, vec4d, _one) EXTEND_VEC_DEF1(vec2d, vec4d, _neg) EXTEND_VEC_DEF1(vec2d, vec4d, _round) EXTEND_VEC_DEF2(vec2d, vec4d, _add) EXTEND_VEC_DEF2(vec2d, vec4d, _sub) EXTEND_VEC_DEF2(vec2d, vec4d, _min) EXTEND_VEC_DEF2(vec2d, vec4d, _max) EXTEND_VEC_DEF2(vec2d, vec4d, _mul) EXTEND_VEC_DEF2(vec2d, vec4d, _div) EXTEND_VEC_DEF2(vec2d, vec4d, _reduce_pm1n_to_pmhn) EXTEND_VEC_DEF2(vec2d, vec4d, _reduce_pm1no_to_0n) EXTEND_VEC_DEF2(vec2d, vec4d, _unpacklo) EXTEND_VEC_DEF2(vec2d, vec4d, _unpackhi) EXTEND_VEC_DEF3(vec2d, vec4d, _reduce_to_pm1n) EXTEND_VEC_DEF3(vec2d, vec4d, _reduce_to_pm1no) EXTEND_VEC_DEF3(vec2d, vec4d, _reduce_to_0n) EXTEND_VEC_DEF3(vec2d, vec4d, _fmadd) EXTEND_VEC_DEF3(vec2d, vec4d, _fmsub) EXTEND_VEC_DEF3(vec2d, vec4d, _fnmadd) EXTEND_VEC_DEF3(vec2d, vec4d, _fnmsub) EXTEND_VEC_DEF3(vec2d, vec4d, _blendv) EXTEND_VEC_DEF4(vec2d, vec4d, _mulmod) EXTEND_VEC_DEF4(vec2d, vec4d, _nmulmod) /* vec8 **********************************************************************/ FLINT_FORCE_INLINE double vec8d_get_index(vec8d a, int i) { return i < 4 ? vec4d_get_index(a.e1, i) : vec4d_get_index(a.e2, i - 4); } FLINT_FORCE_INLINE vec8d vec8d_set_d8(double a0, double a1, double a2, double a3, double a4, double a5, double a6, double a7) { vec4d z1 = vec4d_set_d4(a0, a1, a2, a3); vec4d z2 = vec4d_set_d4(a4, a5, a6, a7); vec8d z = {z1, z2}; return z; } FLINT_FORCE_INLINE vec8d vec8d_set_d(double a) { vec4d z1 = vec4d_set_d(a); vec8d z = {z1, z1}; return z; } FLINT_FORCE_INLINE void vec8d_store(double* z, vec8d a) { vec4d_store(z+0, a.e1); vec4d_store(z+4, a.e2); } FLINT_FORCE_INLINE void vec8d_store_aligned(double* z, vec8d a) { vec4d_store_aligned(z+0, a.e1); vec4d_store_aligned(z+4, a.e2); } FLINT_FORCE_INLINE void vec8d_store_unaligned(double* z, vec8d a) { vec4d_store_unaligned(z+0, a.e1); vec4d_store_unaligned(z+4, a.e2); } FLINT_FORCE_INLINE vec8d vec8d_load(const double* a) { vec4d z1 = vec4d_load(a+0); vec4d z2 = vec4d_load(a+4); vec8d z = {z1, z2}; return z; } FLINT_FORCE_INLINE vec8d vec8d_load_aligned(const double* a) { vec4d z1 = vec4d_load_aligned(a+0); vec4d z2 = vec4d_load_aligned(a+4); vec8d z = {z1, z2}; return z; } FLINT_FORCE_INLINE vec8d vec8d_load_unaligned(const double* a) { vec4d z1 = vec4d_load_unaligned(a+0); vec4d z2 = vec4d_load_unaligned(a+4); vec8d z = {z1, z2}; return z; } EXTEND_VEC_DEF0(vec4d, vec8d, _zero) EXTEND_VEC_DEF0(vec4d, vec8d, _one) EXTEND_VEC_DEF1(vec4d, vec8d, _neg) EXTEND_VEC_DEF1(vec4d, vec8d, _round) EXTEND_VEC_DEF2(vec4d, vec8d, _add) EXTEND_VEC_DEF2(vec4d, vec8d, _sub) EXTEND_VEC_DEF2(vec4d, vec8d, _min) EXTEND_VEC_DEF2(vec4d, vec8d, _max) EXTEND_VEC_DEF2(vec4d, vec8d, _mul) EXTEND_VEC_DEF2(vec4d, vec8d, _div) EXTEND_VEC_DEF2(vec4d, vec8d, _reduce_pm1n_to_pmhn) EXTEND_VEC_DEF2(vec4d, vec8d, _reduce_pm1no_to_0n) EXTEND_VEC_DEF2(vec4d, vec8d, _unpacklo) EXTEND_VEC_DEF2(vec4d, vec8d, _unpackhi) EXTEND_VEC_DEF3(vec4d, vec8d, _reduce_to_pm1n) EXTEND_VEC_DEF3(vec4d, vec8d, _reduce_to_pm1no) EXTEND_VEC_DEF3(vec4d, vec8d, _reduce_to_0n) EXTEND_VEC_DEF3(vec4d, vec8d, _fmadd) EXTEND_VEC_DEF3(vec4d, vec8d, _fmsub) EXTEND_VEC_DEF3(vec4d, vec8d, _fnmadd) EXTEND_VEC_DEF3(vec4d, vec8d, _fnmsub) EXTEND_VEC_DEF3(vec4d, vec8d, _blendv) EXTEND_VEC_DEF4(vec4d, vec8d, _mulmod) EXTEND_VEC_DEF4(vec4d, vec8d, _nmulmod) FLINT_FORCE_INLINE int vec2d_same(vec2d a, vec2d b) { return a[0] == b[0] && a[1] == b[1]; } #define DEFINE_IT(V) \ FLINT_FORCE_INLINE int V##_same_mod(V a, V b, V n, V ninv) { \ return V##_same(V##_reduce_to_0n(a, n, ninv), V##_reduce_to_0n(b, n, ninv)); \ } DEFINE_IT(vec1d) DEFINE_IT(vec2d) #undef DEFINE_IT /* integer stuff *************************************************************/ FLINT_FORCE_INLINE void vec1n_store_unaligned(ulong* z, vec1n a) { z[0] = a; } FLINT_FORCE_INLINE void vec2n_store_unaligned(ulong* z, vec2n a) { vst1q_u64(z, a); } FLINT_FORCE_INLINE void vec4n_store_unaligned(ulong* z, vec4n a) { vec2n_store_unaligned(z+0, a.e1); vec2n_store_unaligned(z+2, a.e2); } FLINT_FORCE_INLINE vec1n vec1d_convert_limited_vec1n(vec1d a) { return (slong)a; } FLINT_FORCE_INLINE vec2n vec2d_convert_limited_vec2n(vec2d a) { return vcvtnq_u64_f64(a); } FLINT_FORCE_INLINE vec4n vec4d_convert_limited_vec4n(vec4d a) { vec2n z1 = vec2d_convert_limited_vec2n(a.e1); vec2n z2 = vec2d_convert_limited_vec2n(a.e2); vec4n z = {z1, z2}; return z; } FLINT_FORCE_INLINE vec2n vec2n_set_n(ulong a) { vec2n x = vdupq_n_u64(a); return x; } FLINT_FORCE_INLINE vec4n vec4n_set_n(ulong a) { vec2n x = vec2n_set_n(a); vec4n z = {x, x}; return z; } FLINT_FORCE_INLINE vec8n vec8n_set_n(ulong a) { vec4n x = vec4n_set_n(a); vec8n z = {x, x}; return z; } FLINT_FORCE_INLINE vec2n vec2n_load_unaligned(const ulong* a) { return vld1q_u64(a); } FLINT_FORCE_INLINE vec4n vec4n_load_unaligned(const ulong* a) { vec2n z1 = vec2n_load_unaligned(a+0); vec2n z2 = vec2n_load_unaligned(a+2); vec4n z = {z1, z2}; return z; } FLINT_FORCE_INLINE vec8n vec8n_load_unaligned(const ulong* a) { vec4n z1 = vec4n_load_unaligned(a+0); vec4n z2 = vec4n_load_unaligned(a+4); vec8n z = {z1, z2}; return z; } /* todo: implement using intrinsics */ FLINT_FORCE_INLINE vec1n vec1n_addmod(vec1n a, vec1n b, vec1n n) { return n - b > a ? a + b : a + b - n; } FLINT_FORCE_INLINE vec2n vec2n_addmod(vec2n a, vec2n b, vec2n n) { vec2n z = {vec1n_addmod(a[0], b[0], n[0]), vec1n_addmod(a[1], b[1], n[1])}; return z; } EXTEND_VEC_DEF3(vec2n, vec4n, _addmod) EXTEND_VEC_DEF3(vec4n, vec8n, _addmod) /* todo: optimized version */ FLINT_FORCE_INLINE vec8n vec8n_addmod_limited(vec8n a, vec8n b, vec8n n) { return vec8n_addmod(a, b, n); } FLINT_FORCE_INLINE vec2d vec2n_convert_limited_vec2d(vec2n a) { float64x2_t t = vdupq_n_f64(0x1.0p52); return vsubq_f64(vreinterpretq_f64_u64(vorrq_u64(a, vreinterpretq_u64_f64(t))), t); } FLINT_FORCE_INLINE vec4d vec4n_convert_limited_vec4d(vec4n a) { return vec4d_set_vec2d2(vec2n_convert_limited_vec2d(a.e1), vec2n_convert_limited_vec2d(a.e2)); } FLINT_FORCE_INLINE vec8d vec8d_set_vec4d2(vec4d a, vec4d b) { vec8d z = {a, b}; return z; } FLINT_FORCE_INLINE vec8d vec8n_convert_limited_vec8d(vec8n a) { return vec8d_set_vec4d2(vec4n_convert_limited_vec4d(a.e1), vec4n_convert_limited_vec4d(a.e2)); } FLINT_FORCE_INLINE vec2n vec2n_bit_and(vec2n a, vec2n b) { return vandq_u64(a, b); } EXTEND_VEC_DEF2(vec2n, vec4n, _bit_and) EXTEND_VEC_DEF2(vec4n, vec8n, _bit_and) #if 0 /* vshrq_n_u64(a, n) cannot be used because n must be a compile-time constant, and the compiler doesn't see that n is constant even if the function is forced inline. And vshlq_s64(a, vdupq_n_s64(-(slong) n)) cannot be used to emulate vshrq_n_u64(a, n) as it propagates the sign bit. */ FLINT_FORCE_INLINE vec2n vec2n_bit_shift_right(vec2n a, ulong n) { return vshrq_n_u64(a, n); } FLINT_FORCE_INLINE vec4n vec4n_bit_shift_right(vec4n a, ulong n) { vec4n z = {vec2n_bit_shift_right(a.e1, n), vec2n_bit_shift_right(a.e2, n)}; return z; } FLINT_FORCE_INLINE vec8n vec8n_bit_shift_right(vec8n a, ulong n) { vec8n z = {vec4n_bit_shift_right(a.e1, n), vec4n_bit_shift_right(a.e2, n)}; return z; } #endif FLINT_FORCE_INLINE vec2n vec2n_bit_shift_right_32(vec2n a) { return vshrq_n_u64(a, 32); } FLINT_FORCE_INLINE vec4n vec4n_bit_shift_right_32(vec4n a) { vec4n z = {vec2n_bit_shift_right_32(a.e1), vec2n_bit_shift_right_32(a.e2)}; return z; } FLINT_FORCE_INLINE vec8n vec8n_bit_shift_right_32(vec8n a) { vec8n z = {vec4n_bit_shift_right_32(a.e1), vec4n_bit_shift_right_32(a.e2)}; return z; } #undef EXTEND_VEC_DEF4 #undef EXTEND_VEC_DEF3 #undef EXTEND_VEC_DEF2 #undef EXTEND_VEC_DEF1 #undef EXTEND_VEC_DEF0 #else #error machine_vector.h not implemented #endif #ifdef __cplusplus } #endif #endif flint-3.1.3/src/mag.h000066400000000000000000000367361461254215100143560ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef MAG_H #define MAG_H #ifdef MAG_INLINES_C #define MAG_INLINE #else #define MAG_INLINE static inline #endif #include "fmpz_extras.h" #include "arb_types.h" #ifdef __cplusplus extern "C" { #endif #define LIMB_ONE ((mp_limb_t) 1) #define LIMB_ONES (-(mp_limb_t) 1) #define LIMB_TOP (((mp_limb_t) 1) << (FLINT_BITS - 1)) #define MASK_LIMB(n, c) ((n) & (LIMB_ONES << (c))) #define MAG_MAX_LAGOM_EXP (COEFF_MAX / 4) #define MAG_MIN_LAGOM_EXP (-MAG_MAX_LAGOM_EXP) #define ADD2_FAST_MAX (COEFF_MAX / 4) #define ADD2_FAST_MIN (-ADD2_FAST_MAX) /* TODO: rename these and move them to fmpz_extras */ static inline void _fmpz_set_fast(fmpz_t f, const fmpz_t g) { if (!COEFF_IS_MPZ(*f) && !COEFF_IS_MPZ(*g)) *f = *g; else fmpz_set(f, g); } static inline void _fmpz_add_fast(fmpz_t z, const fmpz_t x, slong c) { fmpz ze, xe; ze = *z; xe = *x; if (!COEFF_IS_MPZ(ze) && (xe > ADD2_FAST_MIN && xe < ADD2_FAST_MAX)) *z = xe + c; else fmpz_add_si(z, x, c); } static inline void _fmpz_add2_fast(fmpz_t z, const fmpz_t x, const fmpz_t y, slong c) { fmpz ze, xe, ye; ze = *z; xe = *x; ye = *y; if (!COEFF_IS_MPZ(ze) && (xe > ADD2_FAST_MIN && xe < ADD2_FAST_MAX) && (ye > ADD2_FAST_MIN && ye < ADD2_FAST_MAX)) { *z = xe + ye + c; } else { fmpz_add(z, x, y); fmpz_add_si(z, z, c); } } static inline void _fmpz_sub2_fast(fmpz_t z, const fmpz_t x, const fmpz_t y, slong c) { fmpz ze, xe, ye; ze = *z; xe = *x; ye = *y; if (!COEFF_IS_MPZ(ze) && (xe > ADD2_FAST_MIN && xe < ADD2_FAST_MAX) && (ye > ADD2_FAST_MIN && ye < ADD2_FAST_MAX)) { *z = xe - ye + c; } else { fmpz_sub(z, x, y); fmpz_add_si(z, z, c); } } #define MAG_EXP_POS_INF (COEFF_MIN+1) /* Finite and with lagom big exponents. */ #define MAG_IS_LAGOM(x) (MAG_EXP(x) >= MAG_MIN_LAGOM_EXP && \ MAG_EXP(x) <= MAG_MAX_LAGOM_EXP) #define MAG_EXPREF(x) (&(x)->exp) #define MAG_EXP(x) ((x)->exp) #define MAG_MAN(x) ((x)->man) #define MAG_BITS 30 #define MAG_ONE_HALF (UWORD(1) << (MAG_BITS - 1)) static inline mp_limb_t __mag_fixmul32(mp_limb_t x, mp_limb_t y) { mp_limb_t u, v; umul_ppmm(u, v, x, y); return (u << (32 - MAG_BITS)) | (v >> MAG_BITS); } #if FLINT_BITS == 64 #define MAG_FIXMUL(x, y) (((x) * (y)) >> MAG_BITS) #else #define MAG_FIXMUL(x, y) __mag_fixmul32((x), (y)) #endif #define MAG_CHECK_BITS(rr) \ if (MAG_MAN(rr) != 0 && FLINT_BIT_COUNT(MAG_MAN(rr)) != MAG_BITS) \ { \ flint_throw(FLINT_ERROR, "FAIL: wrong number of bits in mantissa!\n"); \ } /* Note: assumes mantissa either has the right number of bits, or one more bit (but in that case must not be all ones, as that would round up to one extra bit again, requiring a second correction). */ #define MAG_ADJUST_ONE_TOO_LARGE(x) \ do { \ mp_limb_t __t = MAG_MAN(x) >> MAG_BITS; \ MAG_MAN(x) = (MAG_MAN(x) >> __t) + (__t & MAG_MAN(x)); \ if (__t) \ fmpz_add_ui(MAG_EXPREF(x), MAG_EXPREF(x), __t); \ } while (0) #define MAG_FAST_ADJUST_ONE_TOO_LARGE(x) \ do { \ mp_limb_t __t = MAG_MAN(x) >> MAG_BITS; \ MAG_MAN(x) = (MAG_MAN(x) >> __t) + (__t & MAG_MAN(x)); \ MAG_EXP(x) += __t; \ } while (0) #define MAG_ADJUST_ONE_TOO_SMALL(x) \ do { \ mp_limb_t __t = !(MAG_MAN(x) >> (MAG_BITS - 1)); \ MAG_MAN(x) = (MAG_MAN(x) << __t); \ if (__t) \ fmpz_sub_ui(MAG_EXPREF(x), MAG_EXPREF(x), __t); \ } while (0) #define MAG_FAST_ADJUST_ONE_TOO_SMALL(x) \ do { \ mp_limb_t __t = !(MAG_MAN(x) >> (MAG_BITS - 1)); \ MAG_MAN(x) = (MAG_MAN(x) << __t); \ MAG_EXP(x) -= __t; \ } while (0) MAG_INLINE void mag_init(mag_t x) { fmpz_init(MAG_EXPREF(x)); MAG_MAN(x) = 0; } MAG_INLINE void mag_init_set(mag_t x, const mag_t y) { fmpz_init_set(MAG_EXPREF(x), MAG_EXPREF(y)); MAG_MAN(x) = MAG_MAN(y); } void mag_clear(mag_t x); MAG_INLINE void mag_swap(mag_t x, mag_t y) { mag_struct t = *x; *x = *y; *y = t; } MAG_INLINE void mag_set(mag_t x, const mag_t y) { _fmpz_set_fast(MAG_EXPREF(x), MAG_EXPREF(y)); x->man = y->man; } MAG_INLINE void mag_zero(mag_t x) { fmpz_zero(MAG_EXPREF(x)); MAG_MAN(x) = 0; } MAG_INLINE void mag_one(mag_t x) { fmpz_one(MAG_EXPREF(x)); MAG_MAN(x) = MAG_ONE_HALF; } MAG_INLINE int mag_is_special(const mag_t x) { return MAG_MAN(x) == 0; } MAG_INLINE int mag_is_zero(const mag_t x) { return (MAG_MAN(x) == 0) && (MAG_EXP(x) == 0); } MAG_INLINE void mag_inf(mag_t x) { fmpz_clear(MAG_EXPREF(x)); MAG_EXP(x) = MAG_EXP_POS_INF; MAG_MAN(x) = 0; } MAG_INLINE int mag_is_inf(const mag_t x) { return (MAG_MAN(x) == 0) && (MAG_EXP(x) != 0); } MAG_INLINE int mag_is_finite(const mag_t x) { return !mag_is_inf(x); } MAG_INLINE int mag_equal(const mag_t x, const mag_t y) { return (MAG_MAN(x) == MAG_MAN(y)) && fmpz_equal(MAG_EXPREF(x), MAG_EXPREF(y)); } /* general versions */ void mag_mul(mag_t z, const mag_t x, const mag_t y); void mag_mul_lower(mag_t z, const mag_t x, const mag_t y); void mag_addmul(mag_t z, const mag_t x, const mag_t y); void mag_add_2exp_fmpz(mag_t z, const mag_t x, const fmpz_t e); void mag_add(mag_t z, const mag_t x, const mag_t y); void mag_add_lower(mag_t z, const mag_t x, const mag_t y); void mag_add_ui(mag_t z, const mag_t x, ulong y); void mag_add_ui_lower(mag_t res, const mag_t x, ulong y); void mag_add_ui_2exp_si(mag_t z, const mag_t x, ulong y, slong e); void mag_div(mag_t z, const mag_t x, const mag_t y); void mag_div_lower(mag_t z, const mag_t x, const mag_t y); MAG_INLINE void mag_inv(mag_t res, const mag_t x) { mag_t t; mag_init(t); /* no need to free */ mag_one(t); mag_div(res, t, x); } MAG_INLINE void mag_inv_lower(mag_t res, const mag_t x) { mag_t t; mag_init(t); /* no need to free */ mag_one(t); mag_div_lower(res, t, x); } void mag_mul_2exp_si(mag_t z, const mag_t x, slong y); void mag_mul_2exp_fmpz(mag_t z, const mag_t x, const fmpz_t y); void mag_sub(mag_t z, const mag_t x, const mag_t y); void mag_sub_lower(mag_t z, const mag_t x, const mag_t y); /* Fast versions (no infs/nans, small exponents). Note that this applies to outputs too! */ MAG_INLINE void mag_fast_init_set(mag_t x, const mag_t y) { MAG_EXP(x) = MAG_EXP(y); MAG_MAN(x) = MAG_MAN(y); } MAG_INLINE void mag_fast_zero(mag_t x) { MAG_EXP(x) = 0; MAG_MAN(x) = 0; } MAG_INLINE int mag_fast_is_zero(const mag_t x) { return MAG_MAN(x) == 0; } MAG_INLINE void mag_fast_mul(mag_t z, const mag_t x, const mag_t y) { if (MAG_MAN(x) == 0 || MAG_MAN(y) == 0) { mag_fast_zero(z); } else { MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + LIMB_ONE; MAG_EXP(z) = MAG_EXP(x) + MAG_EXP(y); MAG_FAST_ADJUST_ONE_TOO_SMALL(z); } } MAG_INLINE void mag_fast_mul_2exp_si(mag_t z, const mag_t x, slong y) { if (MAG_MAN(x) == 0) { mag_fast_zero(z); } else { MAG_MAN(z) = MAG_MAN(x); MAG_EXP(z) = MAG_EXP(x) + y; } } MAG_INLINE void mag_fast_addmul(mag_t z, const mag_t x, const mag_t y) { if (MAG_MAN(z) == 0) { mag_fast_mul(z, x, y); } else if (MAG_MAN(x) == 0 || MAG_MAN(y) == 0) { return; } else { slong shift, e; /* x*y < 2^e */ e = MAG_EXP(x) + MAG_EXP(y); shift = MAG_EXP(z) - e; if (shift >= 0) { if (shift >= MAG_BITS) MAG_MAN(z)++; else MAG_MAN(z) = MAG_MAN(z) + (MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) >> shift) + 1; } else { shift = -shift; MAG_EXP(z) = e; if (shift >= MAG_BITS) MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + 2; else MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + (MAG_MAN(z) >> shift) + 2; MAG_FAST_ADJUST_ONE_TOO_SMALL(z); } MAG_FAST_ADJUST_ONE_TOO_LARGE(z); } } MAG_INLINE void mag_fast_add_2exp_si(mag_t z, const mag_t x, slong e) { /* Must be zero */ if (mag_is_special(x)) { MAG_MAN(z) = MAG_ONE_HALF; MAG_EXP(z) = e + 1; } else { slong shift; shift = MAG_EXP(x) - e; if (shift > 0) { MAG_EXP(z) = MAG_EXP(x); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(x) + LIMB_ONE; else MAG_MAN(z) = MAG_MAN(x) + (LIMB_ONE << (MAG_BITS - shift)); } else { shift = -shift; MAG_EXP(z) = e + 1; if (shift >= MAG_BITS) MAG_MAN(z) = MAG_ONE_HALF + LIMB_ONE; else MAG_MAN(z) = MAG_ONE_HALF + (MAG_MAN(x) >> (shift + 1)) + LIMB_ONE; } MAG_FAST_ADJUST_ONE_TOO_LARGE(z); } } /* requires that x is positive and finite */ #define MAG_SET_D_2EXP(man, exp, x, xexp) \ do { \ int __cexp; \ double __x; \ int __fix; \ mp_limb_t __man; \ __x = frexp((x), &__cexp); \ __man = (mp_limb_t)(__x * (double)(LIMB_ONE << MAG_BITS)) + 1; \ __fix = __man >> (MAG_BITS); \ __man = (__man >> __fix) + __fix; \ (man) = __man; \ (exp) = (xexp) + __cexp + __fix; \ } while (0); /* requires that x is positive and finite */ #define MAG_SET_D_2EXP_LOWER(man, exp, x, xexp) \ do { \ int __cexp; \ double __x; \ int __fix; \ mp_limb_t __man; \ __x = frexp((x), &__cexp); \ __man = (mp_limb_t)(__x * (double)(LIMB_ONE << MAG_BITS)) - 1; \ __fix = __man < MAG_ONE_HALF; \ __man = (__man << __fix); \ (man) = __man; \ (exp) = (xexp) + __cexp - __fix; \ } while (0); void mag_set_d(mag_t z, double x); void mag_set_d_lower(mag_t z, double x); void mag_set_d_2exp_fmpz(mag_t z, double c, const fmpz_t exp); void mag_set_d_2exp_fmpz_lower(mag_t z, double c, const fmpz_t exp); void mag_set_fmpz_2exp_fmpz(mag_t z, const fmpz_t man, const fmpz_t exp); void mag_randtest_special(mag_t x, flint_rand_t state, slong expbits); void mag_randtest(mag_t x, flint_rand_t state, slong expbits); #ifdef FLINT_HAVE_FILE void mag_fprint(FILE * file, const mag_t x); void mag_fprintd(FILE * file, const mag_t x, slong d); #endif void mag_print(const mag_t x); void mag_printd(const mag_t x, slong d); void mag_get_fmpq(fmpq_t y, const mag_t x); void mag_get_fmpz(fmpz_t res, const mag_t x); void mag_get_fmpz_lower(fmpz_t res, const mag_t x); int mag_cmp(const mag_t x, const mag_t y); int mag_cmp_2exp_si(const mag_t x, slong e); MAG_INLINE void mag_min(mag_t z, const mag_t x, const mag_t y) { if (mag_cmp(x, y) <= 0) mag_set(z, x); else mag_set(z, y); } MAG_INLINE void mag_max(mag_t z, const mag_t x, const mag_t y) { if (mag_cmp(x, y) >= 0) mag_set(z, x); else mag_set(z, y); } MAG_INLINE mag_ptr _mag_vec_init(slong n) { slong i; mag_ptr v = (mag_ptr) flint_malloc(sizeof(mag_struct) * n); for (i = 0; i < n; i++) mag_init(v + i); return v; } MAG_INLINE void _mag_vec_clear(mag_ptr v, slong n) { slong i; for (i = 0; i < n; i++) mag_clear(v + i); flint_free(v); } double mag_get_d(const mag_t z); double mag_get_d_log2_approx(const mag_t x); /* TODO: document */ double mag_d_log_upper_bound(double x); double mag_d_log_lower_bound(double x); void mag_log1p(mag_t z, const mag_t x); void mag_log_ui(mag_t t, ulong n); void mag_log(mag_t z, const mag_t x); void mag_log_lower(mag_t z, const mag_t x); void mag_neg_log(mag_t z, const mag_t x); void mag_neg_log_lower(mag_t z, const mag_t x); void mag_exp(mag_t y, const mag_t x); void mag_exp_lower(mag_t y, const mag_t x); void mag_expinv(mag_t res, const mag_t x); void mag_expinv_lower(mag_t y, const mag_t x); void mag_expm1(mag_t y, const mag_t x); void mag_exp_tail(mag_t z, const mag_t x, ulong N); void mag_sinh(mag_t y, const mag_t x); void mag_sinh_lower(mag_t y, const mag_t x); void mag_cosh(mag_t y, const mag_t x); void mag_cosh_lower(mag_t y, const mag_t x); void mag_pow_ui(mag_t z, const mag_t x, ulong e); void mag_pow_ui_lower(mag_t z, const mag_t x, ulong e); void mag_pow_fmpz(mag_t z, const mag_t x, const fmpz_t e); void mag_pow_fmpz_lower(mag_t z, const mag_t x, const fmpz_t e); void mag_const_pi(mag_t res); void mag_const_pi_lower(mag_t res); void mag_atan(mag_t res, const mag_t x); void mag_atan_lower(mag_t res, const mag_t x); void mag_fac_ui(mag_t z, ulong n); void mag_rfac_ui(mag_t z, ulong n); void mag_bin_uiui(mag_t res, ulong n, ulong k); /* TODO: test */ void mag_bernoulli_div_fac_ui(mag_t z, ulong n); /* TODO: test */ void mag_set_fmpz_2exp_fmpz_lower(mag_t z, const fmpz_t man, const fmpz_t exp); void mag_sqrt(mag_t y, const mag_t x); void mag_sqrt_lower(mag_t y, const mag_t x); void mag_rsqrt(mag_t y, const mag_t x); void mag_rsqrt_lower(mag_t y, const mag_t x); void mag_root(mag_t y, const mag_t x, ulong n); void mag_hypot(mag_t z, const mag_t x, const mag_t y); void mag_binpow_uiui(mag_t b, ulong m, ulong n); void mag_polylog_tail(mag_t u, const mag_t z, slong sigma, ulong d, ulong N); void mag_geom_series(mag_t res, const mag_t x, ulong n); void mag_hurwitz_zeta_uiui(mag_t res, ulong s, ulong a); void mag_set_ui(mag_t z, ulong x); void mag_set_ui_lower(mag_t z, ulong x); /* TODO: test functions below */ void mag_set_ui_2exp_si(mag_t z, ulong v, slong e); MAG_INLINE void mag_set_fmpz(mag_t z, const fmpz_t x) { fmpz_t exp; *exp = 0; mag_set_fmpz_2exp_fmpz(z, x, exp); } MAG_INLINE void mag_set_fmpz_lower(mag_t z, const fmpz_t x) { fmpz_t exp; *exp = 0; mag_set_fmpz_2exp_fmpz_lower(z, x, exp); } MAG_INLINE void mag_mul_ui(mag_t z, const mag_t x, ulong y) { mag_t t; mag_init(t); /* no need to clear */ mag_set_ui(t, y); mag_mul(z, x, t); } MAG_INLINE void mag_mul_ui_lower(mag_t z, const mag_t x, ulong y) { mag_t t; mag_init(t); /* no need to clear */ mag_set_ui_lower(t, y); mag_mul_lower(z, x, t); } MAG_INLINE void mag_mul_fmpz(mag_t z, const mag_t x, const fmpz_t y) { mag_t t; mag_init(t); mag_set_fmpz(t, y); mag_mul(z, x, t); mag_clear(t); } MAG_INLINE void mag_mul_fmpz_lower(mag_t z, const mag_t x, const fmpz_t y) { mag_t t; mag_init(t); mag_set_fmpz_lower(t, y); mag_mul_lower(z, x, t); mag_clear(t); } MAG_INLINE void mag_div_ui(mag_t z, const mag_t x, ulong y) { mag_t t; mag_init(t); /* no need to clear */ mag_set_ui_lower(t, y); mag_div(z, x, t); } MAG_INLINE void mag_div_fmpz(mag_t z, const mag_t x, const fmpz_t y) { mag_t t; mag_init(t); mag_set_fmpz_lower(t, y); mag_div(z, x, t); mag_clear(t); } MAG_INLINE slong mag_allocated_bytes(const mag_t x) { return fmpz_allocated_bytes(MAG_EXPREF(x)); } int mag_load_str(mag_t res, const char * data); char * mag_dump_str(const mag_t x); #ifdef FLINT_HAVE_FILE int mag_load_file(mag_t res, FILE * stream); int mag_dump_file(FILE * stream, const mag_t x); #endif #ifdef __cplusplus } #endif #endif flint-3.1.3/src/mag/000077500000000000000000000000001461254215100141665ustar00rootroot00000000000000flint-3.1.3/src/mag/add.c000066400000000000000000000054441461254215100150710ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_add(mag_t z, const mag_t x, const mag_t y) { if (mag_is_zero(x)) { mag_set(z, y); } else if (mag_is_zero(y)) { mag_set(z, x); } else if (mag_is_inf(x) || mag_is_inf(y)) { mag_inf(z); } else { slong shift; shift = _fmpz_sub_small(MAG_EXPREF(x), MAG_EXPREF(y)); if (shift == 0) { _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x)); MAG_MAN(z) = MAG_MAN(x) + MAG_MAN(y); MAG_ADJUST_ONE_TOO_LARGE(z); /* may need two adjustments */ } else if (shift > 0) { _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x)); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(x) + LIMB_ONE; else MAG_MAN(z) = MAG_MAN(x) + (MAG_MAN(y) >> shift) + LIMB_ONE; } else { shift = -shift; _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(y)); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(y) + LIMB_ONE; else MAG_MAN(z) = MAG_MAN(y) + (MAG_MAN(x) >> shift) + LIMB_ONE; } /* TODO: combine */ MAG_ADJUST_ONE_TOO_LARGE(z); } } void mag_add_lower(mag_t z, const mag_t x, const mag_t y) { if (mag_is_zero(x)) { mag_set(z, y); } else if (mag_is_zero(y)) { mag_set(z, x); } else if (mag_is_inf(x) || mag_is_inf(y)) { mag_inf(z); } else { slong shift; shift = _fmpz_sub_small(MAG_EXPREF(x), MAG_EXPREF(y)); if (shift == 0) { _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x)); MAG_MAN(z) = MAG_MAN(x) + MAG_MAN(y); } else if (shift > 0) { _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x)); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(x); else MAG_MAN(z) = MAG_MAN(x) + (MAG_MAN(y) >> shift); } else { shift = -shift; _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(y)); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(y); else MAG_MAN(z) = MAG_MAN(y) + (MAG_MAN(x) >> shift); } if (MAG_MAN(z) >> MAG_BITS) { MAG_MAN(z) >>= 1; _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(z), 1); } } } flint-3.1.3/src/mag/add_2exp_fmpz.c000066400000000000000000000026111461254215100170540ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_add_2exp_fmpz(mag_t z, const mag_t x, const fmpz_t e) { if (mag_is_special(x)) { if (mag_is_zero(x)) { MAG_MAN(z) = MAG_ONE_HALF; _fmpz_add_fast(MAG_EXPREF(z), e, 1); } else { mag_inf(z); } } else { slong shift; shift = _fmpz_sub_small(MAG_EXPREF(x), e); if (shift > 0) { _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x)); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_MAN(x) + LIMB_ONE; else MAG_MAN(z) = MAG_MAN(x) + (LIMB_ONE << (MAG_BITS - shift)); } else { shift = -shift; _fmpz_add_fast(MAG_EXPREF(z), e, 1); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_ONE_HALF + LIMB_ONE; else MAG_MAN(z) = MAG_ONE_HALF + (MAG_MAN(x) >> (shift + 1)) + LIMB_ONE; } MAG_ADJUST_ONE_TOO_LARGE(z); } } flint-3.1.3/src/mag/add_ui.c000066400000000000000000000013231461254215100155560ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_add_ui(mag_t y, const mag_t x, ulong k) { mag_t t; mag_init(t); /* no need to free */ mag_set_ui(t, k); mag_add(y, x, t); } void mag_add_ui_lower(mag_t res, const mag_t x, ulong k) { mag_t t; mag_init(t); mag_set_ui_lower(t, k); /* no need to free */ mag_add_lower(res, x, t); } flint-3.1.3/src/mag/add_ui_2exp_si.c000066400000000000000000000010761461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_add_ui_2exp_si(mag_t z, const mag_t x, ulong y, slong e) { mag_t t; mag_init(t); mag_set_ui_2exp_si(t, y, e); mag_add(z, x, t); mag_clear(t); } flint-3.1.3/src/mag/addmul.c000066400000000000000000000031551461254215100156040ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_addmul(mag_t z, const mag_t x, const mag_t y) { if (mag_is_zero(z)) { mag_mul(z, x, y); } else if (mag_is_inf(z) || mag_is_inf(x) || mag_is_inf(y)) { mag_inf(z); } else if (mag_is_zero(x) || mag_is_zero(y)) { return; } else { slong shift; fmpz_t e; fmpz_init(e); /* x*y < 2^e */ _fmpz_add2_fast(e, MAG_EXPREF(x), MAG_EXPREF(y), 0); shift = _fmpz_sub_small(MAG_EXPREF(z), e); if (shift >= 0) { if (shift >= MAG_BITS) MAG_MAN(z)++; else MAG_MAN(z) = MAG_MAN(z) + (MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) >> shift) + LIMB_ONE; } else { shift = -shift; fmpz_swap(MAG_EXPREF(z), e); if (shift >= MAG_BITS) MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + (2 * LIMB_ONE); else MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + (MAG_MAN(z) >> shift) + (2 * LIMB_ONE); MAG_ADJUST_ONE_TOO_SMALL(z); } MAG_ADJUST_ONE_TOO_LARGE(z); fmpz_clear(e); } } flint-3.1.3/src/mag/atan.c000066400000000000000000000052731461254215100152640ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #include "arb.h" /* for atan table */ #ifdef __GNUC__ # define ldexp __builtin_ldexp #else # include #endif static double mag_atan_d(double x) { double t, u, v; int p, q, flip; t = x; flip = 0; if (t > 1.0) { t = 1.0 / t; flip = 1; } q = ldexp(1.0, ARB_ATAN_TAB1_BITS); p = t * (1 << ARB_ATAN_TAB1_BITS); if (p == (1 << ARB_ATAN_TAB1_BITS)) p--; #if FLINT_BITS == 64 v = arb_atan_tab1[p][ARB_ATAN_TAB1_LIMBS - 1] * ldexp(1.0, -FLINT_BITS); #else v = arb_atan_tab1[p][ARB_ATAN_TAB1_LIMBS - 1] * ldexp(1.0, -FLINT_BITS) + arb_atan_tab1[p][ARB_ATAN_TAB1_LIMBS - 2] * ldexp(1.0, -2 * FLINT_BITS); #endif t = (q * t - p) / (p * t + q); /* t - t^3/3 + t^5/5 */ u = t * t; t = (t * (1.0 / 15.0)) * (15.0 - 5.0 * u + 3.0 * (u * u)); v += t; if (flip) v = 1.5707963267948966192 - v; return v; } void mag_atan(mag_t res, const mag_t x) { if (mag_is_zero(x)) { mag_zero(res); } else if (mag_cmp_2exp_si(x, MAG_BITS) > 0) { mag_const_pi(res); mag_mul_2exp_si(res, res, -1); } else if (mag_cmp_2exp_si(x, -(MAG_BITS / 2)) < 0) { mag_set(res, x); } else { double t; t = ldexp(MAG_MAN(x), MAG_EXP(x) - MAG_BITS); t = mag_atan_d(t); t = t * (1.0 + 1e-12); mag_set_d(res, t); } } void mag_atan_lower(mag_t res, const mag_t x) { if (mag_is_zero(x)) { mag_zero(res); } else if (mag_is_inf(x)) { mag_const_pi_lower(res); mag_mul_2exp_si(res, res, -1); } else if (mag_cmp_2exp_si(x, MAG_BITS) > 0) { /* atan(x) > pi/2 - 1/x */ mag_t t; mag_init(t); mag_one(t); mag_div(t, t, x); mag_const_pi_lower(res); mag_mul_2exp_si(res, res, -1); mag_sub_lower(res, res, t); mag_clear(t); } else if (mag_cmp_2exp_si(x, -MAG_BITS) < 0) { /* atan(x) > x - x^2 */ mag_t t; mag_init(t); mag_mul(t, x, x); mag_sub_lower(res, x, t); mag_clear(t); } else { double t; t = ldexp(MAG_MAN(x), MAG_EXP(x) - MAG_BITS); t = mag_atan_d(t); t = t * (1.0 - 1e-12); mag_set_d_lower(res, t); } } flint-3.1.3/src/mag/bernoulli_div_fac_ui.c000066400000000000000000000031711461254215100204770ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" const int mag_bernoulli_div_fac_ui_tab[32] = { 1, 536870912, -3, 715827883, -9, 763549742, -14, 581752185, -20, 930803495, -25, 752164440, -30, 609225645, -36, 987456906, -41, 800365631, -46, 648744507, -52, 1051701970, -57, 852476898, -62, 690991623, -67, 560096688, -73, 907994540, -78, 735992650, }; /* computes upper bound for B_n / n! */ void mag_bernoulli_div_fac_ui(mag_t z, ulong n) { if (n % 2 == 1) { if (n == 1) { mag_one(z); mag_mul_2exp_si(z, z, -1); } else { mag_zero(z); } } else if (n < 32) { _fmpz_demote(MAG_EXPREF(z)); MAG_EXP(z) = mag_bernoulli_div_fac_ui_tab[n]; MAG_MAN(z) = mag_bernoulli_div_fac_ui_tab[n + 1]; } else { /* upper bound for 1/(2pi) */ mag_set_ui_2exp_si(z, 683565276, -32); /* 2 (1/(2pi))^n */ mag_pow_ui(z, z, n); mag_mul_2exp_si(z, z, 1); /* we should multiply by an upper bound for zeta(n), but the error in the upper bound for 1/(2pi) used above is already larger than this factor when n >= 32, so there is no need */ } } flint-3.1.3/src/mag/bin_uiui.c000066400000000000000000000026471461254215100161460ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_bin_uiui(mag_t res, ulong n, ulong k) { mag_t t; if (k > n) { mag_zero(res); return; } if (k > n / 2) k = n - k; if (k == 0) { mag_one(res); return; } if (k == 1) { mag_set_ui(res, n); return; } mag_init(t); if (n < 256 && k < 256) { /* using accurate (lookup table) factorials */ mag_fac_ui(res, n); mag_rfac_ui(t, k); mag_mul(res, res, t); mag_rfac_ui(t, n - k); mag_mul(res, res, t); } else { /* binary entropy bound (n/(n-k))^(n-k) (n/k)^k = n^n / (k^k (n-k)^(n-k)) */ mag_set_ui(res, n); mag_div_ui(res, res, n - k); mag_pow_ui(res, res, n - k); /* (n/(n-k))^(n-k) is also bounded by exp(k) */ mag_set_ui(t, k); mag_exp(t, t); mag_min(res, res, t); mag_set_ui(t, n); mag_div_ui(t, t, k); mag_pow_ui(t, t, k); mag_mul(res, res, t); } mag_clear(t); } flint-3.1.3/src/mag/binpow_uiui.c000066400000000000000000000020111461254215100166550ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" /* bound (1 + 1/m)^n, m > 0, n >= 0 */ void mag_binpow_uiui(mag_t b, ulong m, ulong n) { mag_t t; if (m == 0) { mag_inf(b); return; } mag_init(t); /* bound by exp(n/m) <= 1 + (n/m) + (n/m)^2 */ if (m > n) { mag_set_ui(t, n); /* x = n/m */ mag_div_ui(t, t, m); mag_mul(b, t, t); /* x^2 */ mag_add(b, b, t); /* x */ mag_one(t); mag_add(b, b, t); /* 1 */ } else { mag_one(b); mag_div_ui(b, b, m); mag_one(t); mag_add(t, t, b); mag_pow_ui(b, t, n); } mag_clear(t); } flint-3.1.3/src/mag/clear.c000066400000000000000000000010511461254215100154150ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_clear(mag_t x) { /* fmpz_clear(), but avoids a redundant store */ if (COEFF_IS_MPZ(MAG_EXP(x))) _fmpz_clear_mpz(MAG_EXP(x)); } flint-3.1.3/src/mag/cmp.c000066400000000000000000000015361461254215100151160ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" int mag_cmp(const mag_t x, const mag_t y) { int c; if (mag_equal(x, y)) return 0; if (mag_is_special(x) || mag_is_special(y)) { if (mag_is_zero(x)) return -1; if (mag_is_zero(y)) return 1; if (mag_is_inf(x)) return 1; if (mag_is_inf(y)) return -1; } c = fmpz_cmp(MAG_EXPREF(x), MAG_EXPREF(y)); if (c == 0) return (MAG_MAN(x) < MAG_MAN(y)) ? -1 : 1; return (c < 0) ? -1 : 1; } flint-3.1.3/src/mag/cmp_2exp_si.c000066400000000000000000000021531461254215100165430ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" int mag_cmp_2exp_si(const mag_t x, slong e) { int ispow2; if (mag_is_special(x)) { if (mag_is_zero(x)) return -1; return 1; } ispow2 = (MAG_MAN(x) == MAG_ONE_HALF); /* Fast path. */ if (!COEFF_IS_MPZ(MAG_EXP(x))) { if (ispow2 && (MAG_EXP(x) - 1 == e)) return 0; else return (MAG_EXP(x) <= e) ? -1 : 1; } if (ispow2) { fmpz_t t; fmpz_init(t); fmpz_one(t); fmpz_add_si(t, t, e); if (fmpz_equal(MAG_EXPREF(x), t)) { fmpz_clear(t); return 0; } fmpz_clear(t); } return (fmpz_cmp_si(MAG_EXPREF(x), e) <= 0) ? -1 : 1; } flint-3.1.3/src/mag/const_pi.c000066400000000000000000000012041461254215100161450ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_const_pi(mag_t res) { fmpz_clear(MAG_EXPREF(res)); MAG_MAN(res) = 843314857; MAG_EXP(res) = 2; } void mag_const_pi_lower(mag_t res) { fmpz_clear(MAG_EXPREF(res)); MAG_MAN(res) = 843314856; MAG_EXP(res) = 2; } flint-3.1.3/src/mag/cosh.c000066400000000000000000000022041461254215100152640ustar00rootroot00000000000000/* Copyright (C) 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_cosh(mag_t res, const mag_t x) { if (mag_is_zero(x)) { mag_one(res); } else if (mag_is_inf(x)) { mag_inf(res); } else { mag_t t; mag_init(t); mag_exp(t, x); mag_expinv(res, x); mag_add(res, res, t); mag_mul_2exp_si(res, res, -1); mag_clear(t); } } void mag_cosh_lower(mag_t res, const mag_t x) { if (mag_is_zero(x)) { mag_one(res); } else if (mag_is_inf(x)) { mag_inf(res); } else { mag_t t; mag_init(t); mag_exp_lower(t, x); mag_expinv_lower(res, x); mag_add_lower(res, res, t); mag_mul_2exp_si(res, res, -1); mag_clear(t); } } flint-3.1.3/src/mag/d_log.c000066400000000000000000000153111461254215100154170ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" /* This is a bad implementation the logarithm function, Any decent libm should compute log() with < 1 ulp error, but we have no way to know that this is the case (the IEEE 754 and C language standards make virtually no guarantees whatsoever about transcendental functions). So here is a bad implementation which almost certainly has much worse accuracy than the libm log(), but which is simple and for which we can give an explicit error bound. The only precomputed constants are rational numbers and logarithms of rational numbers, which are easy to validate. First write x = 2^n * t with sqrt(2)/2 < t < sqrt(2) (a few ulps outside this range is fine). Then write t = m/32 + u with |u| <= 1/64. We have 23 <= m <= 45. Let v = 32*u/m (note that |v| <= 1/46). Then we have log(x) = log(2^n*t) = n*log(2) + log(t) = n*log(2) + log(m/32 + u) = n*log(2) + log(m/32 + m/32 * 32*u/m) = n*log(2) + log(m/32) + log(1 + 32*u/m) = n*log(2) + (log(m/32) + log(1 + v)) We compute log(x) as t1 + (t2 + t3) where t1 ~= n*log(2) involves two roundings, t2 involves one rounding, and t3 ~= v - [v^2/2 + ...] involves two roundings for the multiplication by 1/m, one rounding for subtraction, plus a much smaller error contribution due to the error in the approximation of the terms in brackets. Now consider the outer sum t1 + (t2 + t3). When n != 0, t1 will always be about twice as large as (t2+t3). When n = 0, t2 will always be exactly zero or about twice as large as t3. So there can be no significant cancellation, and most of the final error comes from the largest nonzero term. By inspection, the final error is clearly bounded by 10 ulp (a 3 ulp or maybe even 2 ulp bound could probably be proved with a careful calculation). Multiplying the output by 1 +/- 1e-14, we get guaranteed upper/lower bounds for the logarithm. This factor is chosen conservatively so that we get correct bounds even on x87 or if the CPU rounding mode has been changed. */ #define LOG_TAB_STEP 32 const double d_log_tab[] = { -0.6931471805599453094172, /* log(16/32) */ -0.6325225587435104668366, /* log(17/32) */ -0.5753641449035618548784, /* log(18/32) */ -0.5212969236332860870771, /* log(19/32) */ -0.4700036292457355536509, /* log(20/32) */ -0.4212134650763035505856, /* log(21/32) */ -0.374693449441410693607, /* log(22/32) */ -0.3302416868705768562794, /* log(23/32) */ -0.2876820724517809274392, /* log(24/32) */ -0.2468600779315257978846, /* log(25/32) */ -0.2076393647782445016154, /* log(26/32) */ -0.1698990367953974729004, /* log(27/32) */ -0.1335313926245226231463, /* log(28/32) */ -0.09844007281325251990289, /* log(29/32) */ -0.06453852113757117167292, /* log(30/32) */ -0.031748698314580301157, /* log(31/32) */ 0.0, /* log(32/32) */ 0.03077165866675368837103, /* log(33/32) */ 0.06062462181643484258061, /* log(34/32) */ 0.08961215868968713261995, /* log(35/32) */ 0.1177830356563834545388, /* log(36/32) */ 0.1451820098444978972819, /* log(37/32) */ 0.1718502569266592223401, /* log(38/32) */ 0.1978257433299198803626, /* log(39/32) */ 0.2231435513142097557663, /* log(40/32) */ 0.2478361639045812567806, /* log(41/32) */ 0.2719337154836417588317, /* log(42/32) */ 0.2954642128938358763867, /* log(43/32) */ 0.3184537311185346158102, /* log(44/32) */ 0.3409265869705932103051, /* log(45/32) */ 0.3629054936893684531378, /* log(46/32) */ 0.3844116989103320397348, /* log(47/32) */ }; const double d_log_inverses[] = { 0.0, 1.0, /* 1/1 */ 0.5, /* 1/2 */ 0.3333333333333333333333, /* 1/3 */ 0.25, /* 1/4 */ 0.2, /* 1/5 */ 0.1666666666666666666667, /* 1/6 */ 0.1428571428571428571429, /* 1/7 */ 0.125, /* 1/8 */ 0.1111111111111111111111, /* 1/9 */ 0.1, /* 1/10 */ 0.09090909090909090909091, /* 1/11 */ 0.08333333333333333333333, /* 1/12 */ 0.07692307692307692307692, /* 1/13 */ 0.07142857142857142857143, /* 1/14 */ 0.06666666666666666666667, /* 1/15 */ 0.0625, /* 1/16 */ 0.05882352941176470588235, /* 1/17 */ 0.05555555555555555555556, /* 1/18 */ 0.05263157894736842105263, /* 1/19 */ 0.05, /* 1/20 */ 0.04761904761904761904762, /* 1/21 */ 0.04545454545454545454545, /* 1/22 */ 0.0434782608695652173913, /* 1/23 */ 0.04166666666666666666667, /* 1/24 */ 0.04, /* 1/25 */ 0.03846153846153846153846, /* 1/26 */ 0.03703703703703703703704, /* 1/27 */ 0.03571428571428571428571, /* 1/28 */ 0.03448275862068965517241, /* 1/29 */ 0.03333333333333333333333, /* 1/30 */ 0.03225806451612903225806, /* 1/31 */ 0.03125, /* 1/32 */ 0.0303030303030303030303, /* 1/33 */ 0.02941176470588235294118, /* 1/34 */ 0.02857142857142857142857, /* 1/35 */ 0.02777777777777777777778, /* 1/36 */ 0.02702702702702702702703, /* 1/37 */ 0.02631578947368421052632, /* 1/38 */ 0.02564102564102564102564, /* 1/39 */ 0.025, /* 1/40 */ 0.02439024390243902439024, /* 1/41 */ 0.02380952380952380952381, /* 1/42 */ 0.02325581395348837209302, /* 1/43 */ 0.02272727272727272727273, /* 1/44 */ 0.02222222222222222222222, /* 1/45 */ 0.02173913043478260869565, /* 1/46 */ 0.02127659574468085106383, /* 1/47 */ }; double mag_d_bad_log(double x) { double t, u, v, t1, t2, t3; int m, n; if (x <= 0.0 || (x-x) != (x-x)) { if (x == 0.0) return -D_INF; else if (x > 0.0) return D_INF; else return D_NAN; } if (x < 1 + 1./LOG_TAB_STEP && x > 1 - 1./LOG_TAB_STEP) { return -d_polyval(d_log_inverses, 12, 1.-x); } t = frexp(x, &n); if (t < 0.7071067811865475244008) { t *= 2.0; n -= 1; } m = floor(t * LOG_TAB_STEP + 0.5); u = t * LOG_TAB_STEP - m; /* v = -u / m; */ v = -u * d_log_inverses[m]; t1 = n * (-d_log_tab[0]); t2 = d_log_tab[m - LOG_TAB_STEP / 2]; t3 = -d_polyval(d_log_inverses, 11, v); return t1 + (t2 + t3); } double mag_d_log_upper_bound(double x) { if (x >= 1.0) return mag_d_bad_log(x) * (1 + 1e-14); else return mag_d_bad_log(x) * (1 - 1e-14); } double mag_d_log_lower_bound(double x) { if (x >= 1.0) return mag_d_bad_log(x) * (1 - 1e-14); else return mag_d_bad_log(x) * (1 + 1e-14); } flint-3.1.3/src/mag/div.c000066400000000000000000000023471461254215100151220ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_div(mag_t z, const mag_t x, const mag_t y) { if (mag_is_special(x) || mag_is_special(y)) { if (mag_is_zero(y) || mag_is_inf(x)) mag_inf(z); else mag_zero(z); } else { mp_limb_t q; slong fix; #if FLINT_BITS == 64 q = (MAG_MAN(x) << MAG_BITS) / MAG_MAN(y) + 1; #else mp_limb_t hi, lo, r; lo = MAG_MAN(x) << MAG_BITS; hi = MAG_MAN(x) >> (FLINT_BITS - MAG_BITS); udiv_qrnnd(q, r, hi, lo, MAG_MAN(y)); q += 1; #endif fix = q >> MAG_BITS; q = (q >> fix) + fix; /* could overflow to next power of two */ if (q >> MAG_BITS) { q >>= 1; fix += 1; } MAG_MAN(z) = q; _fmpz_sub2_fast(MAG_EXPREF(z), MAG_EXPREF(x), MAG_EXPREF(y), fix); } } flint-3.1.3/src/mag/div_lower.c000066400000000000000000000023211461254215100163220ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_div_lower(mag_t z, const mag_t x, const mag_t y) { if (mag_is_special(x) || mag_is_special(y)) { if (mag_is_inf(x) && !mag_is_inf(y)) mag_inf(z); else mag_zero(z); } else { mp_limb_t q; slong fix; #if FLINT_BITS == 64 q = (MAG_MAN(x) << MAG_BITS) / MAG_MAN(y); #else mp_limb_t hi, lo, r; lo = MAG_MAN(x) << MAG_BITS; hi = MAG_MAN(x) >> (FLINT_BITS - MAG_BITS); udiv_qrnnd(q, r, hi, lo, MAG_MAN(y)); #endif fix = q >> MAG_BITS; q = q >> fix; /* could overflow to next power of two */ if (q >> MAG_BITS) { q >>= 1; fix += 1; } MAG_MAN(z) = q; _fmpz_sub2_fast(MAG_EXPREF(z), MAG_EXPREF(x), MAG_EXPREF(y), fix); } } flint-3.1.3/src/mag/exp.c000066400000000000000000000105141461254215100151270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" static const double inverse_factorials[] = { 1.0, 1.0, 0.5, 0.16666666666666666667, 0.041666666666666666667, 0.0083333333333333333333, 0.0013888888888888888889, 0.0001984126984126984127, 0.000024801587301587301587, 2.7557319223985890653e-6, 2.7557319223985890653e-7, 2.5052108385441718775e-8, 2.0876756987868098979e-9, 1.6059043836821614599e-10, 1.1470745597729724714e-11, 7.6471637318198164759e-13 }; /* warning: requires |x| < 2^24 or thereabout */ void _mag_exp_d(mag_t res, double x, int roundup) { double u, nlog2, eps, eps2; slong n; if (roundup) { eps = 1e-13; eps2 = 6e-13; } else { eps = -1e-13; eps2 = -6e-13; } n = floor(x * 1.4426950408889634074 + 0.5); /* does not need to be exact */ /* perturbed in opposite direction before subtraction */ if (n >= 0) nlog2 = n * 0.69314718055994530942 * (1.0 - eps); else nlog2 = n * 0.69314718055994530942 * (1.0 + eps); /* perturbed (assuming |u| < 1 for absolute error to be valid) */ u = x - nlog2 + eps; if (u >= -0.375 && u <= 0.375) u = d_polyval(inverse_factorials, 11, u) + eps2; else flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (roundup) mag_set_d(res, u); else mag_set_d_lower(res, u); MAG_EXP(res) += n; /* assumes x not too large */ } void mag_exp_huge(mag_t res, const mag_t x) { if (mag_cmp_2exp_si(x, 128) <= 0) { fmpz_t t; fmpz_init(t); mag_get_fmpz(t, x); MAG_MAN(res) = 729683223; /* upper bound for e */ fmpz_set_ui(MAG_EXPREF(res), 2); mag_pow_fmpz(res, res, t); fmpz_clear(t); } else { mag_inf(res); } } void mag_exp_huge_lower(mag_t res, const mag_t x) { fmpz_t t; fmpz_init(t); if (mag_cmp_2exp_si(x, 128) <= 0) { mag_get_fmpz_lower(t, x); } else { fmpz_one(t); fmpz_mul_2exp(t, t, 128); } MAG_MAN(res) = 729683222; /* lower bound for e */ fmpz_set_ui(MAG_EXPREF(res), 2); mag_pow_fmpz_lower(res, res, t); fmpz_clear(t); } void mag_exp(mag_t y, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_one(y); else mag_inf(y); } else if (COEFF_IS_MPZ(MAG_EXP(x))) { if (fmpz_sgn(MAG_EXPREF(x)) > 0) { mag_inf(y); } else { MAG_MAN(y) = MAG_ONE_HALF + 1; fmpz_one(MAG_EXPREF(y)); } } else { slong e = MAG_EXP(x); if (e <= -MAG_BITS) /* assumes MAG_BITS == 30 */ { MAG_MAN(y) = MAG_ONE_HALF + 1; fmpz_one(MAG_EXPREF(y)); } else if (e <= -(MAG_BITS / 2)) /* assumes MAG_BITS == 30 */ { MAG_MAN(y) = MAG_ONE_HALF + (MAG_MAN(x) >> (1-e)) + 2; fmpz_one(MAG_EXPREF(y)); } else if (e < 24) { _mag_exp_d(y, ldexp(MAG_MAN(x), e - MAG_BITS), 1); } else { mag_exp_huge(y, x); } } } void mag_exp_lower(mag_t y, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_one(y); else mag_inf(y); } else if (COEFF_IS_MPZ(MAG_EXP(x))) { if (fmpz_sgn(MAG_EXPREF(x)) > 0) mag_exp_huge_lower(y, x); else mag_one(y); } else { slong e = MAG_EXP(x); if (e <= -MAG_BITS) { mag_one(y); } else if (e <= -(MAG_BITS / 2)) { MAG_MAN(y) = MAG_ONE_HALF + (MAG_MAN(x) >> (1 - e)); fmpz_one(MAG_EXPREF(y)); } else if (e < 24) { _mag_exp_d(y, ldexp(MAG_MAN(x), e - MAG_BITS), 0); } else { mag_exp_huge_lower(y, x); } } } flint-3.1.3/src/mag/exp_tail.c000066400000000000000000000020301461254215100161320ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_exp_tail(mag_t z, const mag_t x, ulong N) { if (N == 0 || mag_is_inf(x)) { mag_exp(z, x); } else if (mag_is_zero(x)) { mag_zero(z); } else { mag_t t; mag_init(t); mag_set_ui_2exp_si(t, N, -1); /* bound by geometric series when N >= 2*x <=> N/2 >= x */ if (mag_cmp(t, x) >= 0) { /* 2 c^N / N! */ mag_pow_ui(t, x, N); mag_rfac_ui(z, N); mag_mul(z, z, t); mag_mul_2exp_si(z, z, 1); } else { mag_exp(z, x); } mag_clear(t); } } flint-3.1.3/src/mag/expinv.c000066400000000000000000000036121461254215100156450ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp #else # include #endif /* defined in exp.c */ void _mag_exp_d(mag_t res, double x, int roundup); void mag_exp_huge(mag_t res, const mag_t x); void mag_exp_huge_lower(mag_t res, const mag_t x); void mag_expinv(mag_t res, const mag_t x) { if (mag_is_zero(x)) { mag_one(res); } else if (mag_is_inf(x)) { mag_zero(res); } else if (mag_cmp_2exp_si(x, 24) >= 0) { mag_exp_huge_lower(res, x); mag_inv(res, res); } else if (COEFF_IS_MPZ(MAG_EXP(x))) { mag_one(res); } else { slong e = MAG_EXP(x); if (e <= -MAG_BITS) mag_one(res); else _mag_exp_d(res, -ldexp(MAG_MAN(x), e - MAG_BITS), 1); } } void mag_expinv_lower(mag_t res, const mag_t x) { if (mag_is_zero(x)) { mag_one(res); } else if (mag_is_inf(x)) { mag_zero(res); } else if (mag_cmp_2exp_si(x, 24) >= 0) { mag_exp_huge(res, x); mag_inv_lower(res, res); } else if (COEFF_IS_MPZ(MAG_EXP(x))) { /* 1 - eps */ MAG_MAN(res) = (1 << MAG_BITS) - 1; fmpz_zero(MAG_EXPREF(res)); } else { slong e = MAG_EXP(x); if (e < -MAG_BITS) { /* 1 - eps */ MAG_MAN(res) = (1 << MAG_BITS) - 1; fmpz_zero(MAG_EXPREF(res)); } else _mag_exp_d(res, -ldexp(MAG_MAN(x), e - MAG_BITS), 0); } } flint-3.1.3/src/mag/expm1.c000066400000000000000000000033471461254215100153730ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_expm1(mag_t y, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_zero(y); else mag_inf(y); } else if (COEFF_IS_MPZ(MAG_EXP(x))) { if (fmpz_sgn(MAG_EXPREF(x)) > 0) { mag_inf(y); } else { fmpz_set(MAG_EXPREF(y), MAG_EXPREF(x)); MAG_MAN(y) = MAG_MAN(x) + 1; MAG_ADJUST_ONE_TOO_LARGE(y); } } else { slong e = MAG_EXP(x); if (e <= -16) { fmpz_set(MAG_EXPREF(y), MAG_EXPREF(x)); if (e < -MAG_BITS) MAG_MAN(y) = MAG_MAN(x) + 1; else MAG_MAN(y) = MAG_MAN(x) + (MAG_ONE_HALF >> 15); MAG_ADJUST_ONE_TOO_LARGE(y); } else { mag_exp(y, x); /* subtract 1 */ if (e < 6) { slong e2 = MAG_EXP(y); unsigned int c; if (e2 < MAG_BITS) { /* this is correct since exp(x) >= 1 */ MAG_MAN(y) -= (MAG_ONE_HALF >> (e2 - 1)); c = MAG_BITS - FLINT_BIT_COUNT(MAG_MAN(y)); MAG_MAN(y) <<= c; MAG_EXP(y) -= c; } } } } } flint-3.1.3/src/mag/fac_ui.c000066400000000000000000000301371461254215100155640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #ifdef __GNUC__ # define ceil __builtin_ceil #else # include #endif #define MAG_FAC_TABLE_NUM 256 const int mag_fac_tab[MAG_FAC_TABLE_NUM * 2] = { 1, 536870912, 1, 536870912, 2, 536870912, 3, 805306368, 5, 805306368, 7, 1006632960, 10, 754974720, 13, 660602880, 16, 660602880, 19, 743178240, 22, 928972800, 26, 638668800, 29, 958003200, 33, 778377600, 37, 681080400, 41, 638512875, 45, 638512875, 49, 678419930, 53, 763222421, 57, 906326625, 62, 566454141, 66, 743471060, 70, 1022272707, 75, 734758508, 80, 551068881, 84, 861045127, 89, 699599166, 94, 590286796, 98, 1033001893, 103, 936157966, 108, 877648093, 113, 850221590, 118, 850221590, 123, 876791015, 128, 931590453, 133, 1018927058, 139, 573146470, 144, 662700606, 149, 786956970, 154, 959103807, 160, 599439879, 165, 768032345, 170, 1008042453, 176, 677278523, 181, 931257969, 187, 654790760, 192, 941261717, 198, 691239074, 203, 1036858610, 209, 793844874, 215, 620191308, 220, 988429896, 226, 803099291, 232, 665066600, 238, 561149944, 243, 964476466, 249, 843916908, 255, 751613496, 261, 681149731, 267, 627934908, 273, 588688976, 279, 561094181, 285, 543559988, 290, 1070133725, 296, 1070133725, 303, 543427282, 309, 560409385, 315, 586678575, 321, 623345986, 327, 672044891, 333, 735049099, 339, 815445095, 345, 917375731, 351, 1046381693, 358, 604939417, 364, 708913379, 370, 841834637, 376, 1012832298, 383, 617194682, 389, 761849685, 395, 952312106, 402, 602635005, 408, 772126100, 414, 1001351036, 421, 657136617, 427, 872759570, 434, 586385336, 440, 797117566, 447, 548018327, 453, 762087986, 459, 1071686230, 466, 761901929, 473, 547617012, 479, 795755970, 486, 584383290, 492, 867443946, 499, 650582960, 505, 986039798, 512, 754936721, 519, 583896370, 525, 912338078, 532, 719891765, 539, 573663750, 545, 923240098, 552, 750132579, 559, 615343132, 565, 1019162061, 572, 851955786, 579, 718837694, 586, 612135224, 592, 1052107416, 599, 912374400, 606, 798327600, 613, 704773585, 620, 627688974, 627, 563939312, 633, 1022140003, 640, 934299847, 647, 861307671, 654, 800746976, 661, 750700290, 668, 709646368, 675, 676381694, 682, 649960534, 689, 629649268, 696, 614891863, 703, 605284178, 710, 600555395, 717, 600555395, 724, 605247234, 731, 614704222, 738, 629111352, 745, 648771082, 752, 674113702, 759, 705712782, 766, 744306450, 773, 790825603, 780, 846430528, 787, 912557913, 794, 990980859, 802, 541942657, 809, 596983708, 816, 662278801, 823, 739889598, 830, 832375798, 837, 942925709, 845, 537762319, 852, 617586413, 859, 714084290, 866, 831238743, 873, 974107902, 881, 574571458, 888, 682303606, 895, 815566029, 902, 981227879, 910, 594102818, 917, 724062809, 924, 888108289, 932, 548129335, 939, 680879408, 946, 851099260, 953, 1070523287, 961, 677440518, 968, 862678159, 976, 552653196, 983, 712404510, 990, 923899599, 998, 602700129, 1005, 791043920, 1012, 1044425175, 1020, 693563593, 1027, 926557612, 1035, 622530896, 1042, 841389414, 1050, 571881867, 1057, 781869740, 1065, 537535447, 1072, 743310735, 1079, 1033666490, 1087, 722758991, 1094, 1016379831, 1102, 718612303, 1109, 1021776868, 1117, 730410808, 1124, 1049965536, 1132, 758764157, 1140, 551289583, 1147, 805399625, 1155, 591465350, 1162, 873335555, 1170, 648178733, 1177, 967204202, 1185, 725403152, 1193, 546885970, 1200, 828874048, 1208, 631368904, 1215, 966783634, 1223, 743970218, 1231, 575414466, 1238, 894589677, 1246, 698898186, 1254, 548744279, 1261, 865987064, 1269, 686700680, 1277, 547214604, 1284, 876398390, 1292, 705226829, 1300, 570242007, 1307, 926643260, 1315, 756517349, 1323, 620580638, 1330, 1022988396, 1338, 847162265, 1346, 704865479, 1354, 589223486, 1361, 989711324, 1369, 835068930, 1377, 707851397, 1385, 602779706, 1392, 1031318402, 1400, 886289252, 1408, 765116894, 1416, 663499806, 1424, 577970534, 1431, 1011448435, 1439, 888968351, 1447, 784792372, 1455, 695890111, 1463, 619777131, 1471, 554410011, 1478, 996205489, 1486, 898919797, 1494, 814646066, 1502, 741455208, 1510, 677736401, 1518, 622140837, 1526, 573536084, 1533, 1061937906, 1541, 987270397, 1549, 921709472, 1557, 864102630, 1565, 813471617, 1573, 768984888, 1581, 729934874, 1589, 695719177, 1597, 665824993, 1605, 639816204, 1613, 617322666, 1621, 598031333, 1629, 581678914, 1637, 568045814, 1645, 556951169, 1653, 548248807, 1661, 541824017, 1669, 537591016, 1676, 1070982102, }; const int mag_rfac_tab[MAG_FAC_TABLE_NUM * 2] = { 1, 536870912, 1, 536870912, 0, 536870912, -2, 715827883, -4, 715827883, -6, 572662307, -9, 763549742, -12, 872628277, -15, 872628277, -18, 775669579, -21, 620535663, -25, 902597328, -28, 601731552, -32, 740592680, -36, 846391634, -40, 902817743, -44, 902817743, -48, 849710817, -52, 755298504, -56, 636040846, -61, 1017665353, -65, 775364078, -69, 563901148, -74, 784558119, -79, 1046077491, -83, 669489595, -88, 823987193, -93, 976577414, -97, 558044237, -102, 615772951, -107, 656824481, -112, 678012368, -117, 678012368, -122, 657466538, -127, 618792036, -132, 565752719, -138, 1005782611, -143, 869866042, -148, 732518772, -153, 601041044, -159, 961665670, -164, 750568328, -169, 571861583, -175, 851142821, -180, 619012961, -186, 880373989, -191, 612434079, -197, 833952789, -202, 555968526, -208, 726162972, -214, 929488605, -219, 583208536, -225, 717795122, -231, 866771468, -237, 1027284702, -242, 597692918, -248, 683077620, -254, 766964346, -260, 846305485, -266, 918026288, -272, 979228041, -278, 1027386797, -284, 1060528307, -289, 538681045, -295, 538681045, -302, 1060787288, -308, 1028642219, -314, 982583612, -320, 924784576, -326, 857771201, -332, 784247955, -338, 706927734, -344, 628380208, -350, 550908676, -357, 952923115, -363, 813161058, -369, 684767207, -375, 569157159, -382, 934001491, -388, 756659436, -394, 605327549, -401, 956566990, -407, 746588871, -413, 575682985, -420, 877231215, -426, 660503503, -433, 983074981, -439, 723181595, -446, 1051900502, -452, 756422833, -458, 537900681, -465, 756607552, -472, 1052671376, -478, 724419012, -485, 986442909, -491, 664551013, -498, 886068017, -504, 584622197, -511, 763588175, -518, 987265519, -524, 631849933, -531, 800760310, -538, 1004875684, -544, 624388774, -551, 768478492, -558, 936811875, -564, 565622264, -571, 676632242, -578, 801934508, -585, 941721257, -591, 547910550, -598, 631824778, -605, 722085461, -612, 817937513, -619, 918385980, -626, 1022203525, -632, 563974359, -639, 616997589, -646, 669285520, -653, 719903753, -660, 767897336, -667, 812321149, -674, 852271370, -681, 886916547, -688, 915526759, -695, 937499401, -702, 952380344, -709, 959879401, -716, 959879401, -723, 952438476, -730, 937785576, -737, 916309571, -744, 888542614, -751, 855138756, -758, 816848961, -765, 774493830, -772, 728935369, -779, 681049104, -786, 631697720, -793, 581707253, -801, 1063693262, -808, 965622252, -815, 870420058, -822, 779117255, -829, 692548671, -836, 611353310, -844, 1071961968, -851, 933409060, -858, 807272701, -865, 693496012, -872, 591783263, -880, 1003288181, -887, 844874258, -894, 706822909, -901, 587489171, -909, 970304695, -916, 796147442, -923, 649088360, -931, 1051687470, -938, 846641485, -945, 677313188, -952, 538485019, -960, 850939290, -967, 668222264, -975, 1043078656, -982, 809176170, -989, 623943071, -997, 956463629, -1004, 728734194, -1011, 551940691, -1019, 831157747, -1026, 622153167, -1034, 925995411, -1041, 685129553, -1049, 1008006698, -1056, 737284900, -1064, 1072414399, -1071, 775531317, -1078, 557685442, -1086, 797583648, -1093, 567170594, -1101, 802186034, -1108, 564174793, -1116, 789228126, -1123, 549028262, -1131, 759736405, -1139, 1045658708, -1146, 715744998, -1154, 974631486, -1161, 660067885, -1169, 889354624, -1176, 596007287, -1184, 794676383, -1192, 1054078518, -1199, 695474487, -1207, 913033172, -1214, 596266561, -1222, 774843856, -1230, 1001818319, -1237, 644385653, -1245, 824813635, -1253, 1050508908, -1260, 665669011, -1268, 839464369, -1276, 1053445483, -1283, 657761082, -1291, 817411830, -1299, 1010905451, -1306, 622095663, -1314, 761992773, -1322, 928905476, -1329, 563506640, -1337, 680460848, -1345, 817830878, -1353, 978339742, -1360, 582453428, -1368, 690315174, -1376, 814381034, -1384, 956337361, -1391, 558955170, -1399, 650420562, -1407, 753428343, -1415, 868818269, -1423, 997387789, -1430, 569935879, -1438, 648460378, -1446, 734539189, -1454, 828378998, -1462, 930109752, -1470, 1039773347, -1477, 578656472, -1485, 641281631, -1493, 707621110, -1501, 777472121, -1509, 850567790, -1517, 926575975, -1525, 1005099363, -1532, 542838475, -1540, 583893485, -1548, 625425658, -1556, 667120702, -1564, 708642737, -1572, 749638598, -1580, 789742721, -1588, 828582526, -1596, 865784191, -1604, 900978670, -1612, 933807852, -1620, 963930686, -1628, 991029139, -1636, 1014813839, -1644, 1035029254, -1652, 1051458290, -1660, 1063926174, -1668, 1072303546, -1675, 538254329, }; void mag_fac_ui(mag_t z, ulong n) { if (n < MAG_FAC_TABLE_NUM) { _fmpz_demote(MAG_EXPREF(z)); MAG_EXP(z) = mag_fac_tab[n * 2]; MAG_MAN(z) = mag_fac_tab[n * 2 + 1]; } else { double x = n; x = ceil((((x+0.5)*mag_d_log_upper_bound(x) - x) * 1.4426950408889634074 + 2) * 1.0000001); /* x + 1 could round down for huge x, but this doesn't matter as long as the result was perturbed up above */ fmpz_set_d(MAG_EXPREF(z), x + 1); MAG_MAN(z) = MAG_ONE_HALF; } } void mag_rfac_ui(mag_t z, ulong n) { if (n < MAG_FAC_TABLE_NUM) { _fmpz_demote(MAG_EXPREF(z)); MAG_EXP(z) = mag_rfac_tab[n * 2]; MAG_MAN(z) = mag_rfac_tab[n * 2 + 1]; } else { double x = n; x = ceil((((x+0.5)*mag_d_log_lower_bound(x) - x) * 1.4426950408889634074) * -0.9999999); /* x + 1 could round down for huge x, but this doesn't matter as long as the value was perturbed up above */ fmpz_set_d(MAG_EXPREF(z), x + 1); MAG_MAN(z) = MAG_ONE_HALF; } } flint-3.1.3/src/mag/geom_series.c000066400000000000000000000016741461254215100166430ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_geom_series(mag_t res, const mag_t x, ulong n) { if (mag_is_zero(x)) { if (n == 0) mag_one(res); else mag_zero(res); } else if (mag_is_inf(x)) { mag_inf(res); } else { mag_t t; mag_init(t); mag_one(t); mag_sub_lower(t, t, x); if (mag_is_zero(t)) { mag_inf(res); } else { mag_pow_ui(res, x, n); mag_div(res, res, t); } mag_clear(t); } } flint-3.1.3/src/mag/get_d.c000066400000000000000000000015211461254215100154130ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" double mag_get_d(const mag_t z) { if (mag_is_zero(z)) { return 0.0; } else if (mag_is_inf(z)) { return D_INF; } else if (MAG_EXP(z) < -1000 || MAG_EXP(z) > 1000) { if (fmpz_sgn(MAG_EXPREF(z)) < 0) return ldexp(1.0, -1000); else return D_INF; } else { return d_mul_2exp(MAG_MAN(z), MAG_EXP(z) - MAG_BITS); } } flint-3.1.3/src/mag/get_d_log2_approx.c000066400000000000000000000021121461254215100177240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp #else # include #endif double mag_get_d_log2_approx(const mag_t x) { if (mag_is_zero(x)) { return (double) COEFF_MIN; } else if (mag_is_inf(x)) { return (double) COEFF_MAX; } else if (COEFF_IS_MPZ(MAG_EXP(x))) { if (fmpz_sgn(MAG_EXPREF(x)) < 0) return (double) COEFF_MIN; else return (double) COEFF_MAX; } else { slong e = MAG_EXP(x); if (e < -20 || e > 20) return e; else return e + 1.4426950408889634074 * mag_d_log_upper_bound(MAG_MAN(x) * ldexp(1.0, -MAG_BITS)); } } flint-3.1.3/src/mag/get_fmpq.c000066400000000000000000000010321461254215100161300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #include "arf.h" void mag_get_fmpq(fmpq_t y, const mag_t x) { arf_t t; arf_init_set_mag_shallow(t, x); arf_get_fmpq(y, t); } flint-3.1.3/src/mag/get_fmpz.c000066400000000000000000000012731461254215100161500ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #include "arf.h" void mag_get_fmpz(fmpz_t res, const mag_t x) { arf_t t; arf_init_set_mag_shallow(t, x); arf_get_fmpz(res, t, ARF_RND_UP); } void mag_get_fmpz_lower(fmpz_t res, const mag_t x) { arf_t t; arf_init_set_mag_shallow(t, x); arf_get_fmpz(res, t, ARF_RND_DOWN); } flint-3.1.3/src/mag/hurwitz_zeta_uiui.c000066400000000000000000000016071461254215100201300ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_hurwitz_zeta_uiui(mag_t res, ulong s, ulong a) { if (s <= 1 || a == 0) { mag_inf(res); } else { mag_t t, u; mag_init(t); mag_init(u); mag_one(t); mag_set_ui_lower(u, a); mag_pow_ui_lower(u, u, s - 1); mag_mul_ui_lower(res, u, a); mag_div(res, t, res); mag_mul_ui_lower(u, u, s - 1); mag_div(u, t, u); mag_add(res, res, u); mag_clear(t); mag_clear(u); } } flint-3.1.3/src/mag/hypot.c000066400000000000000000000013461461254215100155010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_hypot(mag_t z, const mag_t x, const mag_t y) { if (mag_is_zero(y)) { mag_set(z, x); } else if (mag_is_zero(x)) { mag_set(z, y); } else { mag_t t; mag_init(t); mag_mul(t, x, x); mag_addmul(t, y, y); mag_sqrt(z, t); mag_clear(t); } } flint-3.1.3/src/mag/inlines.c000066400000000000000000000006461461254215100160010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define MAG_INLINES_C #include "mag.h" flint-3.1.3/src/mag/io.c000066400000000000000000000062201461254215100147410ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson Copyright (C) 2015 Arb authors Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "mag.h" #include "arf.h" /* string *********************************************************************/ static void mag_set_arf_dump(mag_t x, const arf_t y) { if (arf_is_special(y)) { if (arf_is_zero(y)) { mag_zero(x); } else if (arf_is_pos_inf(y)) { mag_inf(x); } else { /* a mag cannot be negative infinity or NaN */ flint_throw(FLINT_ERROR, "(%s)\n", __func__); } } else { fmpz_t mantissa, exponent; fmpz_init(mantissa); fmpz_init(exponent); arf_get_fmpz_2exp(mantissa, exponent, y); if (fmpz_cmp_ui(mantissa, 1 << MAG_BITS) >= 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); mag_set_ui(x, fmpz_get_ui(mantissa)); mag_mul_2exp_fmpz(x, x, exponent); fmpz_clear(exponent); fmpz_clear(mantissa); } } int mag_load_str(mag_t x, const char* data) { int err = 0; arf_t y; arf_init(y); err = arf_load_str(y, data); if (err) { arf_clear(y); return err; } mag_set_arf_dump(x, y); arf_clear(y); return err; } char * mag_dump_str(const mag_t x) { char * res; arf_t y; arf_init_set_mag_shallow(y, x); res = arf_dump_str(y); return res; } /* printing *******************************************************************/ void mag_fprint(FILE * file, const mag_t x) { flint_fprintf(file, "("); if (mag_is_zero(x)) flint_fprintf(file, "0"); else if (mag_is_inf(x)) flint_fprintf(file, "inf"); else { fmpz_t t; fmpz_init(t); fmpz_sub_ui(t, MAG_EXPREF(x), MAG_BITS); flint_fprintf(file, "%wu * 2^", MAG_MAN(x)); fmpz_fprint(file, t); fmpz_clear(t); } flint_fprintf(file, ")"); } void mag_fprintd(FILE * file, const mag_t x, slong d) { arf_t t; arf_init(t); arf_set_mag(t, x); arf_fprintd(file, t, d); arf_clear(t); } void mag_print(const mag_t x) { mag_fprint(stdout, x); } void mag_printd(const mag_t x, slong d) { mag_fprintd(stdout, x, d); } /* file I/O *******************************************************************/ int mag_load_file(mag_t x, FILE * stream) { int err = 0; arf_t y; arf_init(y); err = arf_load_file(y, stream); if (err) { arf_clear(y); return err; } mag_set_arf_dump(x, y); arf_clear(y); return err; } int mag_dump_file(FILE * stream, const mag_t x) { int nwrite; char* data = mag_dump_str(x); nwrite = fputs(data, stream); if (nwrite == EOF) return nwrite; flint_free(data); return 0; } flint-3.1.3/src/mag/log.c000066400000000000000000000130461461254215100151170ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #ifdef __GNUC__ # define ldexp __builtin_ldexp #else # include #endif void mag_neg_log(mag_t z, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_inf(z); else mag_zero(z); } else { double t; fmpz exp = MAG_EXP(x); if (!COEFF_IS_MPZ(exp)) { if (exp >= 1) { mag_zero(z); } else if (exp > -(1000 - MAG_BITS)) { t = ldexp(MAG_MAN(x), exp - MAG_BITS); t = -mag_d_log_lower_bound(t); mag_set_d(z, t); } else { /* -log(2^(exp-1) * (2*v)) = -exp*log(2) - log(2*v), 1 <= 2v < 2 */ t = MAG_MAN(x) * ldexp(1.0, 1 - MAG_BITS); t = -mag_d_log_lower_bound(t); t -= (exp - 1) * 0.69314718055994530942; t *= (1 + 1e-13); mag_set_d(z, t); } } else if (fmpz_sgn(MAG_EXPREF(x)) > 0) { mag_zero(z); } else { mag_inv(z, x); mag_log(z, z); } } } void mag_neg_log_lower(mag_t z, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_inf(z); else mag_zero(z); } else { double t; fmpz exp = MAG_EXP(x); if (!COEFF_IS_MPZ(exp)) { if (exp >= 1) { mag_zero(z); } else if (exp > -(1000 - MAG_BITS)) { t = ldexp(MAG_MAN(x), exp - MAG_BITS); t = -mag_d_log_upper_bound(t); mag_set_d_lower(z, t); } else { /* -log(2^(exp-1) * (2*v)) = -exp*log(2) - log(2*v), 1 <= 2v < 2 */ t = MAG_MAN(x) * ldexp(1.0, 1 - MAG_BITS); t = -mag_d_log_upper_bound(t); t -= (exp - 1) * 0.69314718055994530942; t *= (1 - 1e-13); mag_set_d_lower(z, t); } } else if (fmpz_sgn(MAG_EXPREF(x)) > 0) { mag_zero(z); } else { mag_inv_lower(z, x); mag_log_lower(z, z); } } } void mag_log(mag_t z, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_zero(z); else mag_inf(z); } else { double t; fmpz exp = MAG_EXP(x); if (!COEFF_IS_MPZ(exp)) { if (exp <= 0 || (exp == 1 && MAG_MAN(x) == MAG_ONE_HALF)) { mag_zero(z); } else if (exp < 1000) /* safely within the double range */ { t = ldexp(MAG_MAN(x), exp - MAG_BITS); t = mag_d_log_upper_bound(t); mag_set_d(z, t); } else { /* log(2^(exp-1)*(2v)) = (exp-1)*log(2) + log(2v), 1 <= 2v < 2 */ t = MAG_MAN(x) * ldexp(1.0, 1 - MAG_BITS); /* exact */ t = mag_d_log_upper_bound(t); t += (exp - 1.0) * 0.69314718055994530942; t *= (1 + 1e-13); /* last step could have rounded down */ mag_set_d(z, t); } } else if (fmpz_sgn(MAG_EXPREF(x)) < 0) { mag_zero(z); } else { /* log(2^exp) = exp*log(2), log(2) < 744261118/2^30 */ fmpz_t t; fmpz_init(t); fmpz_mul_ui(t, MAG_EXPREF(x), 744261118); mag_set_fmpz(z, t); mag_mul_2exp_si(z, z, -30); fmpz_clear(t); } } } void mag_log_lower(mag_t z, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_zero(z); else mag_inf(z); } else { double t; fmpz exp = MAG_EXP(x); if (!COEFF_IS_MPZ(exp)) { if (exp <= 0 || (exp == 1 && MAG_MAN(x) == MAG_ONE_HALF)) { mag_zero(z); } else if (exp < 1000) { t = ldexp(MAG_MAN(x), exp - MAG_BITS); t = mag_d_log_lower_bound(t); mag_set_d_lower(z, t); } else { /* log(2^(exp-1) * (2*v)) = exp*log(2) + log(2*v), 1 <= 2v < 2 */ t = MAG_MAN(x) * ldexp(1.0, 1 - MAG_BITS); t = mag_d_log_lower_bound(t); t += (exp - 1) * 0.69314718055994530942; t *= (1 - 1e-13); mag_set_d_lower(z, t); } } else if (fmpz_sgn(MAG_EXPREF(x)) < 0) { mag_zero(z); } else { /* log(2^exp) = exp*log(2), log(2) > 744261117/2^30 */ fmpz_t t; fmpz_init(t); fmpz_sub_ui(t, MAG_EXPREF(x), 1); /* lower bound for x */ fmpz_mul_ui(t, t, 744261117); mag_set_fmpz_lower(z, t); mag_mul_2exp_si(z, z, -30); fmpz_clear(t); } } } flint-3.1.3/src/mag/log1p.c000066400000000000000000000032031461254215100153520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" void mag_log1p(mag_t z, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_zero(z); else mag_inf(z); } else { double t; fmpz exp = MAG_EXP(x); if (!COEFF_IS_MPZ(exp)) { /* Quick bound by x */ if (exp < -10) { mag_set(z, x); } else if (exp < 1000) { t = ldexp(MAG_MAN(x), exp - MAG_BITS); t = (1.0 + t) * (1 + 1e-14); t = mag_d_log_upper_bound(t); mag_set_d(z, t); } else { /* log(2^(exp-1) * (2*v)) = exp*log(2) + log(2*v), 1 <= 2v < 2 */ t = (MAG_MAN(x) + 1) * ldexp(1.0, 1 - MAG_BITS); t = mag_d_log_upper_bound(t); t += (exp - 1) * 0.69314718055994530942; t *= (1 + 1e-13); mag_set_d(z, t); } } else if (fmpz_sgn(MAG_EXPREF(x)) < 0) { /* Quick bound by x */ mag_set(z, x); } else { mag_add_ui(z, x, 1); mag_log(z, z); } } } flint-3.1.3/src/mag/log_ui.c000066400000000000000000000011571461254215100156140ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_log_ui(mag_t t, ulong n) { if (n <= 1) { if (n == 1) mag_zero(t); else mag_inf(t); } else { mag_set_ui(t, n-1); mag_log1p(t, t); } } flint-3.1.3/src/mag/mul.c000066400000000000000000000025231461254215100151310ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_mul(mag_t z, const mag_t x, const mag_t y) { if (mag_is_special(x) || mag_is_special(y)) { if (mag_is_inf(x) || mag_is_inf(y)) mag_inf(z); else mag_zero(z); } else { slong fix; MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + LIMB_ONE; fix = !(MAG_MAN(z) >> (MAG_BITS - 1)); MAG_MAN(z) <<= fix; _fmpz_add2_fast(MAG_EXPREF(z), MAG_EXPREF(x), MAG_EXPREF(y), -fix); } } void mag_mul_lower(mag_t z, const mag_t x, const mag_t y) { if (mag_is_special(x) || mag_is_special(y)) { if (mag_is_zero(x) || mag_is_zero(y)) mag_zero(z); else mag_inf(z); } else { slong fix; MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)); fix = !(MAG_MAN(z) >> (MAG_BITS - 1)); MAG_MAN(z) <<= fix; _fmpz_add2_fast(MAG_EXPREF(z), MAG_EXPREF(x), MAG_EXPREF(y), -fix); } } flint-3.1.3/src/mag/mul_2exp_fmpz.c000066400000000000000000000012051461254215100171170ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_mul_2exp_fmpz(mag_t z, const mag_t x, const fmpz_t y) { if (mag_is_special(x)) { mag_set(z, x); } else { _fmpz_add2_fast(MAG_EXPREF(z), MAG_EXPREF(x), y, 0); MAG_MAN(z) = MAG_MAN(x); } } flint-3.1.3/src/mag/mul_2exp_si.c000066400000000000000000000013711461254215100165620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_mul_2exp_si(mag_t z, const mag_t x, slong y) { if (mag_is_special(x)) { mag_set(z, x); } else { if (y >= ADD2_FAST_MIN && y <= ADD2_FAST_MAX) _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(x), y); else fmpz_add_si(MAG_EXPREF(z), MAG_EXPREF(x), y); MAG_MAN(z) = MAG_MAN(x); } } flint-3.1.3/src/mag/polylog_tail.c000066400000000000000000000040041461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_polylog_tail(mag_t u, const mag_t z, slong sigma, ulong d, ulong N) { mag_t TN, UN, t; if (N < 2) { mag_inf(u); return; } mag_init(TN); mag_init(UN); mag_init(t); if (mag_cmp_2exp_si(z, 0) >= 0) { mag_inf(u); } else { /* Bound T(N) */ mag_pow_ui(TN, z, N); /* multiply by log(N)^d */ if (d > 0) { mag_log_ui(t, N); mag_pow_ui(t, t, d); mag_mul(TN, TN, t); } /* multiply by 1/k^s */ if (sigma > 0) { mag_set_ui_lower(t, N); mag_pow_ui_lower(t, t, sigma); mag_div(TN, TN, t); } else if (sigma < 0) { mag_set_ui(t, N); mag_pow_ui(t, t, -sigma); mag_mul(TN, TN, t); } /* Bound U(N) */ mag_set(UN, z); /* multiply by (1 + 1/N)**S */ if (sigma < 0) { mag_binpow_uiui(t, N, -sigma); mag_mul(UN, UN, t); } /* multiply by (1 + 1/(N log(N)))^d */ if (d > 0) { ulong nl; /* rounds down */ nl = mag_d_log_lower_bound(N) * N * (1 - 1e-13); mag_binpow_uiui(t, nl, d); mag_mul(UN, UN, t); } /* T(N) / (1 - U(N)) */ if (mag_cmp_2exp_si(UN, 0) >= 0) { mag_inf(u); } else { mag_one(t); mag_sub_lower(t, t, UN); mag_div(u, TN, t); } } mag_clear(TN); mag_clear(UN); mag_clear(t); } flint-3.1.3/src/mag/pow_fmpz.c000066400000000000000000000036261461254215100162020ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_pow_fmpz(mag_t z, const mag_t x, const fmpz_t e) { if (fmpz_sgn(e) < 0) { fmpz_t t; fmpz_init(t); fmpz_neg(t, e); mag_inv(z, x); mag_pow_fmpz(z, z, t); fmpz_clear(t); } else if (!COEFF_IS_MPZ(*e)) { mag_pow_ui(z, x, fmpz_get_ui(e)); } else { mag_t y; mp_srcptr elimbs; slong i, bits; mag_init_set(y, x); bits = fmpz_bits(e); elimbs = COEFF_TO_PTR(*e)->_mp_d; for (i = bits - 2; i >= 0; i--) { mag_mul(y, y, y); if ((elimbs[i / FLINT_BITS] >> (i % FLINT_BITS)) & 1) mag_mul(y, y, x); } mag_swap(z, y); mag_clear(y); } } void mag_pow_fmpz_lower(mag_t z, const mag_t x, const fmpz_t e) { if (fmpz_sgn(e) < 0) { fmpz_t t; fmpz_init(t); fmpz_neg(t, e); mag_inv_lower(z, x); mag_pow_fmpz_lower(z, z, t); fmpz_clear(t); } else if (!COEFF_IS_MPZ(*e)) { mag_pow_ui_lower(z, x, fmpz_get_ui(e)); } else { mag_t y; mp_srcptr elimbs; slong i, bits; mag_init_set(y, x); bits = fmpz_bits(e); elimbs = COEFF_TO_PTR(*e)->_mp_d; for (i = bits - 2; i >= 0; i--) { mag_mul_lower(y, y, y); if ((elimbs[i / FLINT_BITS] >> (i % FLINT_BITS)) & 1) mag_mul_lower(y, y, x); } mag_swap(z, y); mag_clear(y); } } flint-3.1.3/src/mag/pow_ui.c000066400000000000000000000031641461254215100156400ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_pow_ui(mag_t z, const mag_t x, ulong e) { if (mag_is_inf(x)) { mag_inf(z); } else if (e <= 2) { if (e == 0) mag_one(z); else if (e == 1) mag_set(z, x); else mag_mul(z, x, x); } else { mag_t y; int i, bits; mag_init_set(y, x); bits = FLINT_BIT_COUNT(e); for (i = bits - 2; i >= 0; i--) { mag_mul(y, y, y); if (e & (UWORD(1) << i)) mag_mul(y, y, x); } mag_swap(z, y); mag_clear(y); } } void mag_pow_ui_lower(mag_t z, const mag_t x, ulong e) { if (e <= 2) { if (e == 0) mag_one(z); else if (e == 1) mag_set(z, x); else mag_mul_lower(z, x, x); } else if (mag_is_inf(x)) { mag_inf(z); } else { mag_t y; int i, bits; mag_init_set(y, x); bits = FLINT_BIT_COUNT(e); for (i = bits - 2; i >= 0; i--) { mag_mul_lower(y, y, y); if (e & (UWORD(1) << i)) mag_mul_lower(y, y, x); } mag_swap(z, y); mag_clear(y); } } flint-3.1.3/src/mag/randtest.c000066400000000000000000000024141461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_randtest_special(mag_t x, flint_rand_t state, slong expbits) { switch (n_randint(state, 32)) { case 0: mag_zero(x); break; case 1: mag_inf(x); break; case 2: MAG_MAN(x) = (LIMB_ONE << MAG_BITS) - 1; fmpz_randtest(MAG_EXPREF(x), state, expbits); break; case 3: MAG_MAN(x) = LIMB_ONE << (MAG_BITS - 1); fmpz_randtest(MAG_EXPREF(x), state, expbits); break; default: MAG_MAN(x) = (n_randtest(state) >> (FLINT_BITS - MAG_BITS)); MAG_MAN(x) |= (LIMB_ONE << (MAG_BITS - 1)); fmpz_randtest(MAG_EXPREF(x), state, expbits); } } void mag_randtest(mag_t x, flint_rand_t state, slong expbits) { mag_randtest_special(x, state, expbits); if (mag_is_inf(x)) mag_zero(x); } flint-3.1.3/src/mag/root.c000066400000000000000000000024721461254215100153220ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_root(mag_t y, const mag_t x, ulong n) { if (n == 0) { mag_inf(y); } else if (n == 1 || mag_is_special(x)) { mag_set(y, x); } else if (n == 2) { mag_sqrt(y, x); } else if (n == 4) { mag_sqrt(y, x); mag_sqrt(y, y); } else { fmpz_t e, f; fmpz_init_set_ui(e, MAG_BITS); fmpz_init(f); /* We evaluate exp(log(1+2^(kn)x)/n) 2^-k where k is chosen so that 2^(kn) x ~= 2^30. TODO: this rewriting is probably unnecessary with the new exp/log functions. */ fmpz_sub(e, e, MAG_EXPREF(x)); fmpz_cdiv_q_ui(e, e, n); fmpz_mul_ui(f, e, n); mag_mul_2exp_fmpz(y, x, f); mag_log1p(y, y); mag_div_ui(y, y, n); mag_exp(y, y); fmpz_neg(e, e); mag_mul_2exp_fmpz(y, y, e); fmpz_clear(e); fmpz_clear(f); } } flint-3.1.3/src/mag/rsqrt.c000066400000000000000000000050341461254215100155070ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #ifdef __GNUC__ # define frexp __builtin_frexp # define ldexp __builtin_ldexp # define sqrt __builtin_sqrt #else # include #endif void mag_rsqrt(mag_t y, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_inf(y); else mag_zero(y); } else { double t; fmpz e; t = MAG_MAN(x) * ldexp(1.0, -MAG_BITS); if (MAG_IS_LAGOM(x)) { e = MAG_EXP(x); if (e % 2 != 0) { e = (1 - e) >> 1; t *= 2.0; } else { e = (-e) >> 1; } t = (1.0 / sqrt(t)) * (1 + 1e-13); _fmpz_demote(MAG_EXPREF(y)); MAG_SET_D_2EXP(MAG_MAN(y), MAG_EXP(y), t, e); } else { if (fmpz_is_odd(MAG_EXPREF(x))) t *= 2.0; fmpz_fdiv_q_2exp(MAG_EXPREF(y), MAG_EXPREF(x), 1); fmpz_neg(MAG_EXPREF(y), MAG_EXPREF(y)); t = (1.0 / sqrt(t)) * (1 + 1e-13); mag_set_d_2exp_fmpz(y, t, MAG_EXPREF(y)); } } } void mag_rsqrt_lower(mag_t y, const mag_t x) { if (mag_is_special(x)) { if (mag_is_zero(x)) mag_inf(y); else mag_zero(y); } else { double t; fmpz e; t = MAG_MAN(x) * ldexp(1.0, -MAG_BITS); if (MAG_IS_LAGOM(x)) { e = MAG_EXP(x); if (e % 2 != 0) { e = (1 - e) >> 1; t *= 2.0; } else { e = (-e) >> 1; } t = (1.0 / sqrt(t)) * (1 - 1e-13); _fmpz_demote(MAG_EXPREF(y)); MAG_SET_D_2EXP_LOWER(MAG_MAN(y), MAG_EXP(y), t, e); } else { if (fmpz_is_odd(MAG_EXPREF(x))) t *= 2.0; fmpz_fdiv_q_2exp(MAG_EXPREF(y), MAG_EXPREF(x), 1); fmpz_neg(MAG_EXPREF(y), MAG_EXPREF(y)); t = (1.0 / sqrt(t)) * (1 - 1e-13); mag_set_d_2exp_fmpz_lower(y, t, MAG_EXPREF(y)); } } } flint-3.1.3/src/mag/set_d.c000066400000000000000000000020311461254215100154240ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" void mag_set_d(mag_t z, double c) { if (c < 0.0) c = -c; if (c == 0.0) { mag_zero(z); } else if ((c != c) || c == D_INF) { mag_inf(z); } else { _fmpz_demote(MAG_EXPREF(z)); MAG_SET_D_2EXP(MAG_MAN(z), MAG_EXP(z), c, 0); } } void mag_set_d_lower(mag_t z, double c) { if (c < 0.0) c = -c; if (c == 0.0 || (c != c)) { mag_zero(z); } else if (c == D_INF) { mag_inf(z); } else { _fmpz_demote(MAG_EXPREF(z)); MAG_SET_D_2EXP_LOWER(MAG_MAN(z), MAG_EXP(z), c, 0); } } flint-3.1.3/src/mag/set_d_2exp_fmpz.c000066400000000000000000000031451461254215100174250ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" void mag_set_d_2exp_fmpz(mag_t z, double c, const fmpz_t exp) { if (c < 0.0) c = -c; if (c == 0.0) { mag_zero(z); } else if ((c != c) || c == D_INF) { mag_inf(z); } else { slong cexp = *exp; if (cexp >= MAG_MIN_LAGOM_EXP && cexp <= MAG_MAX_LAGOM_EXP) { _fmpz_demote(MAG_EXPREF(z)); MAG_SET_D_2EXP(MAG_MAN(z), MAG_EXP(z), c, cexp); } else { MAG_SET_D_2EXP(MAG_MAN(z), cexp, c, 0); fmpz_add_si(MAG_EXPREF(z), exp, cexp); } } } void mag_set_d_2exp_fmpz_lower(mag_t z, double c, const fmpz_t exp) { if (c < 0.0) c = -c; if (c == 0.0 || (c != c)) { mag_zero(z); } else if (c == D_INF) { mag_inf(z); } else { slong cexp = *exp; if (cexp >= MAG_MIN_LAGOM_EXP && cexp <= MAG_MAX_LAGOM_EXP) { _fmpz_demote(MAG_EXPREF(z)); MAG_SET_D_2EXP_LOWER(MAG_MAN(z), MAG_EXP(z), c, cexp); } else { MAG_SET_D_2EXP_LOWER(MAG_MAN(z), cexp, c, 0); fmpz_add_si(MAG_EXPREF(z), exp, cexp); } } } flint-3.1.3/src/mag/set_fmpz_2exp_fmpz.c000066400000000000000000000021101461254215100201450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_set_fmpz_2exp_fmpz(mag_t z, const fmpz_t man, const fmpz_t exp) { if (fmpz_is_zero(man)) { mag_zero(z); } else { mp_limb_t m; slong cexp; m = fmpz_abs_ubound_ui_2exp(&cexp, man, MAG_BITS); MAG_MAN(z) = m; _fmpz_add_fast(MAG_EXPREF(z), exp, cexp + MAG_BITS); } } void mag_set_fmpz_2exp_fmpz_lower(mag_t z, const fmpz_t man, const fmpz_t exp) { if (fmpz_is_zero(man)) { mag_zero(z); } else { mp_limb_t m; slong cexp; m = fmpz_abs_lbound_ui_2exp(&cexp, man, MAG_BITS); MAG_MAN(z) = m; _fmpz_add_fast(MAG_EXPREF(z), exp, cexp + MAG_BITS); } } flint-3.1.3/src/mag/set_ui.c000066400000000000000000000026351461254215100156300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_set_ui(mag_t z, ulong x) { _fmpz_demote(MAG_EXPREF(z)); if (x == 0) { MAG_EXP(z) = 0; MAG_MAN(z) = 0; } else { slong bits; mp_limb_t overflow; bits = flint_clz(x); bits = FLINT_BITS - bits; if (bits <= MAG_BITS) { x = x << (MAG_BITS - bits); } else { x = (x >> (bits - MAG_BITS)) + 1; overflow = x >> MAG_BITS; bits += overflow; x >>= overflow; } MAG_EXP(z) = bits; MAG_MAN(z) = x; } } void mag_set_ui_lower(mag_t z, ulong x) { _fmpz_demote(MAG_EXPREF(z)); if (x == 0) { MAG_EXP(z) = 0; MAG_MAN(z) = 0; } else { unsigned int bits; bits = flint_clz(x); bits = FLINT_BITS - bits; if (bits <= MAG_BITS) x <<= (MAG_BITS - bits); else x >>= (bits - MAG_BITS); MAG_EXP(z) = bits; MAG_MAN(z) = x; } } flint-3.1.3/src/mag/set_ui_2exp_si.c000066400000000000000000000023351461254215100172560ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" void mag_set_ui_2exp_si(mag_t z, ulong x, slong e) { _fmpz_demote(MAG_EXPREF(z)); if (x == 0) { MAG_EXP(z) = 0; MAG_MAN(z) = 0; } else { slong bits; mp_limb_t overflow; bits = flint_clz(x); bits = FLINT_BITS - bits; if (bits <= MAG_BITS) { x = x << (MAG_BITS - bits); } else { x = (x >> (bits - MAG_BITS)) + 1; overflow = x >> MAG_BITS; bits += overflow; x >>= overflow; } if (e >= MAG_MIN_LAGOM_EXP && e <= MAG_MAX_LAGOM_EXP) { MAG_EXP(z) = bits + e; } else { fmpz_set_si(MAG_EXPREF(z), e); fmpz_add_si(MAG_EXPREF(z), MAG_EXPREF(z), bits); } MAG_MAN(z) = x; } } flint-3.1.3/src/mag/sinh.c000066400000000000000000000041011461254215100152670ustar00rootroot00000000000000/* Copyright (C) 2014, 2018 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "double_extras.h" #include "mag.h" static const double inverse_factorials[] = { 1.0, 0.16666666666666666667, 0.0083333333333333333333, 0.0001984126984126984127, 2.7557319223985890653e-6, 2.5052108385441718775e-8, 1.6059043836821614599e-10, 7.6471637318198164759e-13 }; static double _sinh(double x) { x = x * (1.0 / 27.0); x = x * d_polyval(inverse_factorials, 8, x * x); x = x * (3.0 + 4.0 * (x * x)); x = x * (3.0 + 4.0 * (x * x)); x = x * (3.0 + 4.0 * (x * x)); return x; } void mag_sinh(mag_t res, const mag_t x) { if (mag_is_special(x)) { mag_set(res, x); } else { if (mag_cmp_2exp_si(x, -30) < 0) { mag_expm1(res, x); } else if (mag_cmp_2exp_si(x, 4) > 0) { mag_exp(res, x); mag_mul_2exp_si(res, res, -1); } else { double v; v = mag_get_d(x); v = _sinh(v) * (1 + 1e-12); mag_set_d(res, v); } } } void mag_sinh_lower(mag_t res, const mag_t x) { if (mag_is_special(x)) { mag_set(res, x); } else { if (mag_cmp_2exp_si(x, -15) < 0) { mag_set(res, x); } else if (mag_cmp_2exp_si(x, 4) > 0) { mag_t t; mag_init(t); mag_exp_lower(t, x); mag_expinv(res, x); mag_sub(res, t, res); mag_mul_2exp_si(res, res, -1); mag_clear(t); } else { double v; v = mag_get_d(x); v = _sinh(v) * (1 - 1e-12); mag_set_d_lower(res, v); } } } flint-3.1.3/src/mag/sqrt.c000066400000000000000000000044001461254215100153210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #ifdef __GNUC__ # define frexp __builtin_frexp # define ldexp __builtin_ldexp # define sqrt __builtin_sqrt #else # include #endif void mag_sqrt(mag_t y, const mag_t x) { if (mag_is_special(x)) { mag_set(y, x); } else { double t; slong e; t = MAG_MAN(x) * ldexp(1.0, -MAG_BITS); if (MAG_IS_LAGOM(x)) { e = MAG_EXP(x); if (e % 2 != 0) { e = (e - 1) >> 1; t *= 2.0; } else { e >>= 1; } t = sqrt(t) * (1 + 1e-13); _fmpz_demote(MAG_EXPREF(y)); MAG_SET_D_2EXP(MAG_MAN(y), MAG_EXP(y), t, e); } else { if (fmpz_is_odd(MAG_EXPREF(x))) t *= 2.0; fmpz_fdiv_q_2exp(MAG_EXPREF(y), MAG_EXPREF(x), 1); t = sqrt(t) * (1 + 1e-13); mag_set_d_2exp_fmpz(y, t, MAG_EXPREF(y)); } } } void mag_sqrt_lower(mag_t y, const mag_t x) { if (mag_is_special(x)) { mag_set(y, x); } else { double t; slong e; t = MAG_MAN(x) * ldexp(1.0, -MAG_BITS); if (MAG_IS_LAGOM(x)) { e = MAG_EXP(x); if (e % 2 != 0) { e = (e - 1) >> 1; t *= 2.0; } else { e >>= 1; } t = sqrt(t) * (1 - 1e-13); _fmpz_demote(MAG_EXPREF(y)); MAG_SET_D_2EXP_LOWER(MAG_MAN(y), MAG_EXP(y), t, e); } else { if (fmpz_is_odd(MAG_EXPREF(x))) t *= 2.0; fmpz_fdiv_q_2exp(MAG_EXPREF(y), MAG_EXPREF(x), 1); t = sqrt(t) * (1 - 1e-13); mag_set_d_2exp_fmpz_lower(y, t, MAG_EXPREF(y)); } } } flint-3.1.3/src/mag/sub.c000066400000000000000000000021401461254215100151200ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #include "arf.h" void mag_sub(mag_t z, const mag_t x, const mag_t y) { if (mag_is_special(x) || mag_is_special(y)) { if (mag_is_inf(x)) mag_inf(z); else if (mag_is_inf(y)) mag_zero(z); else mag_set(z, x); /* x - 0 = x; max(0 - y, 0) = 0 */ } else { /* this should eventually have a proper implementation... */ arf_t t, u; arf_init(t); arf_init(u); arf_set_mag(t, x); arf_set_mag(u, y); arf_sub(t, t, u, MAG_BITS, ARF_RND_UP); if (arf_sgn(t) >= 0) arf_get_mag(z, t); else mag_zero(z); arf_clear(t); arf_clear(u); } } flint-3.1.3/src/mag/sub_lower.c000066400000000000000000000043731461254215100163420ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mag.h" #include "arf.h" void mag_sub_lower(mag_t z, const mag_t x, const mag_t y) { if (mag_is_special(x) || mag_is_special(y)) { if (mag_is_zero(y)) mag_set(z, x); else if (mag_is_zero(x) || mag_is_inf(y)) mag_zero(z); else mag_inf(z); } else { slong shift, fix; shift = _fmpz_sub_small(MAG_EXPREF(x), MAG_EXPREF(y)); /* y > x */ if (shift < 0) { mag_zero(z); } else if (shift == 0) { if (MAG_MAN(y) >= MAG_MAN(x)) { mag_zero(z); } else { MAG_MAN(z) = MAG_MAN(x) - MAG_MAN(y); fix = MAG_BITS - FLINT_BIT_COUNT(MAG_MAN(z)); MAG_MAN(z) <<= fix; _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(x), -fix); } } else { if (shift <= MAG_BITS) { mp_limb_t c = MAG_MAN(x) - (MAG_MAN(y) >> shift) - 1; /* too much cancellation -- compute precisely */ if (c < (UWORD(1) << (MAG_BITS - 4))) { arf_t t, u; arf_init(t); arf_init(u); arf_set_mag(t, x); arf_set_mag(u, y); arf_sub(t, t, u, MAG_BITS, ARF_RND_DOWN); arf_get_mag_lower(z, t); arf_clear(t); arf_clear(u); return; } MAG_MAN(z) = c; } else { MAG_MAN(z) = MAG_MAN(x) - 1; } fix = MAG_BITS - FLINT_BIT_COUNT(MAG_MAN(z)); MAG_MAN(z) <<= fix; _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(x), -fix); } } } flint-3.1.3/src/mag/test/000077500000000000000000000000001461254215100151455ustar00rootroot00000000000000flint-3.1.3/src/mag/test/main.c000066400000000000000000000070151461254215100162400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include /* Include functions *********************************************************/ #include "t-add_2exp_fmpz.c" #include "t-add.c" #include "t-addmul.c" #include "t-atan.c" #include "t-binpow_uiui.c" #include "t-bin_uiui.c" #include "t-cmp_2exp_si.c" #include "t-cmp.c" #include "t-cosh.c" #include "t-div.c" #include "t-div_lower.c" #include "t-d_log_lower_bound.c" #include "t-d_log_upper_bound.c" #include "t-dump_file.c" #include "t-dump_str.c" #include "t-exp.c" #include "t-expinv.c" #include "t-expm1.c" #include "t-exp_tail.c" #include "t-fac_ui.c" #include "t-fast_add_2exp_si.c" #include "t-fast_addmul.c" #include "t-fast_mul_2exp_si.c" #include "t-fast_mul.c" #include "t-geom_series.c" #include "t-get_d.c" #include "t-hurwitz_zeta_uiui.c" #include "t-log1p.c" #include "t-log.c" #include "t-mul_2exp_fmpz.c" #include "t-mul_2exp_si.c" #include "t-mul.c" #include "t-mul_lower.c" #include "t-neg_log.c" #include "t-polylog_tail.c" #include "t-pow_fmpz.c" #include "t-pow_ui.c" #include "t-rfac_ui.c" #include "t-root.c" #include "t-rsqrt.c" #include "t-rsqrt_lower.c" #include "t-set_d_2exp_fmpz.c" #include "t-set_d.c" #include "t-set_ui.c" #include "t-set_ui_lower.c" #include "t-sinh.c" #include "t-sqrt.c" #include "t-sqrt_lower.c" #include "t-sub.c" #include "t-sub_lower.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(mag_add_2exp_fmpz), TEST_FUNCTION(mag_add), TEST_FUNCTION(mag_addmul), TEST_FUNCTION(mag_atan), TEST_FUNCTION(mag_binpow_uiui), TEST_FUNCTION(mag_bin_uiui), TEST_FUNCTION(mag_cmp_2exp_si), TEST_FUNCTION(mag_cmp), TEST_FUNCTION(mag_cosh), TEST_FUNCTION(mag_div), TEST_FUNCTION(mag_div_lower), TEST_FUNCTION(mag_d_log_lower_bound), TEST_FUNCTION(mag_d_log_upper_bound), TEST_FUNCTION(mag_dump_file), TEST_FUNCTION(mag_dump_str), TEST_FUNCTION(mag_exp), TEST_FUNCTION(mag_expinv), TEST_FUNCTION(mag_expm1), TEST_FUNCTION(mag_exp_tail), TEST_FUNCTION(mag_fac_ui), TEST_FUNCTION(mag_fast_add_2exp_si), TEST_FUNCTION(mag_fast_addmul), TEST_FUNCTION(mag_fast_mul_2exp_si), TEST_FUNCTION(mag_fast_mul), TEST_FUNCTION(mag_geom_series), TEST_FUNCTION(mag_get_d), TEST_FUNCTION(mag_hurwitz_zeta_uiui), TEST_FUNCTION(mag_log1p), TEST_FUNCTION(mag_log), TEST_FUNCTION(mag_mul_2exp_fmpz), TEST_FUNCTION(mag_mul_2exp_si), TEST_FUNCTION(mag_mul), TEST_FUNCTION(mag_mul_lower), TEST_FUNCTION(mag_neg_log), TEST_FUNCTION(mag_polylog_tail), TEST_FUNCTION(mag_pow_fmpz), TEST_FUNCTION(mag_pow_ui), TEST_FUNCTION(mag_rfac_ui), TEST_FUNCTION(mag_root), TEST_FUNCTION(mag_rsqrt), TEST_FUNCTION(mag_rsqrt_lower), TEST_FUNCTION(mag_set_d_2exp_fmpz), TEST_FUNCTION(mag_set_d), TEST_FUNCTION(mag_set_ui), TEST_FUNCTION(mag_set_ui_lower), TEST_FUNCTION(mag_sinh), TEST_FUNCTION(mag_sqrt), TEST_FUNCTION(mag_sqrt_lower), TEST_FUNCTION(mag_sub), TEST_FUNCTION(mag_sub_lower) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/mag/test/t-add.c000066400000000000000000000064551461254215100163140ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_add, state) { slong iter; /* test mag_add */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_add(z, x, y, MAG_BITS + 10, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_add(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } /* test mag_add_lower */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_add(z2, x, y, 100, ARF_RND_DOWN); arf_mul_ui(z, z2, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z, z, -10); mag_add_lower(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-add_2exp_fmpz.c000066400000000000000000000036641461254215100203050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_add_2exp_fmpz, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, zb; fmpz_t e; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); fmpz_init(e); mag_init(xb); mag_init(zb); arf_randtest(x, state, MAG_BITS, 100); arf_abs(x, x); fmpz_randtest(e, state, 100); arf_one(y); arf_mul_2exp_fmpz(y, y, e); arf_add(z, x, y, MAG_BITS + 10, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); arf_get_mag(xb, x); mag_add_2exp_fmpz(zb, xb, e); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(zb); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-addmul.c000066400000000000000000000107241461254215100170240ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_addmul, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); mag_randtest_special(zb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_set_mag(z, zb); arf_addmul(z, x, y, MAG_BITS + 10, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_addmul(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_addmul(z, z, y, MAG_BITS + 10, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_addmul(zb, zb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_set(z, y); arf_addmul(z, x, z, MAG_BITS + 10, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, yb); mag_addmul(zb, xb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_addmul(z, z, z, MAG_BITS + 10, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_addmul(zb, zb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 3)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-atan.c000066400000000000000000000066371461254215100165110ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" #include "mag.h" void arf_atan(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_atan, x, NULL, prec, rnd); } TEST_FUNCTION_START(mag_atan, state) { slong iter; /* check atan */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 25); mag_randtest_special(yb, state, 25); mag_atan(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_atan(z, x, MAG_BITS, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_atan(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } /* check atan_lower */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 25); mag_randtest_special(yb, state, 25); mag_atan_lower(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_atan(z, x, MAG_BITS, ARF_RND_DOWN); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_atan_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-bin_uiui.c000066400000000000000000000026601461254215100173610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_bin_uiui, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; fmpz_t f; mag_t xb; ulong n, k; arf_init(x); arf_init(y); fmpz_init(f); mag_init(xb); mag_randtest_special(xb, state, 80); n = n_randtest(state) % 10000; k = n_randtest(state) % 10000; mag_bin_uiui(xb, n, k); fmpz_bin_uiui(f, n, k); arf_set_fmpz(x, f); arf_set_mag(y, xb); MAG_CHECK_BITS(xb) if (!(arf_cmpabs(y, x) >= 0)) { flint_printf("FAIL\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); fmpz_clear(f); mag_clear(xb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-binpow_uiui.c000066400000000000000000000064601461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_fmpz #define arf_pow_binexp_fmpz arf_pow_binexp_fmpz void arf_pow_binexp_fmpz(arf_t y, const arf_t b, const fmpz_t e, slong prec, arf_rnd_t rnd) { slong i, wp, bits; if (fmpz_is_zero(e)) { arf_set_ui(y, UWORD(1)); return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); arf_pow_binexp_fmpz(y, b, f, prec + 2, (rnd == ARF_RND_FLOOR || rnd == ARF_RND_DOWN) ? ARF_RND_UP : ARF_RND_DOWN); arf_ui_div(y, UWORD(1), y, prec, rnd); fmpz_clear(f); return; } if (y == b) { arf_t t; arf_init(t); arf_set(t, b); arf_pow_binexp_fmpz(y, t, e, prec, rnd); arf_clear(t); return; } arf_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { arf_mul(y, y, y, wp, rnd); if (fmpz_tstbit(e, i)) arf_mul(y, y, b, wp, rnd); } } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_ui #define arf_pow_binexp_ui arf_pow_binexp_ui void arf_pow_binexp_ui(arf_t y, const arf_t b, ulong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init_set_ui(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_si #define arf_pow_binexp_si arf_pow_binexp_si void arf_pow_binexp_si(arf_t y, const arf_t b, slong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init(f); fmpz_set_si(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif TEST_FUNCTION_START(mag_binpow_uiui, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; mag_t b; ulong m, n; arf_init(x); arf_init(y); mag_init(b); m = n_randtest(state); n = n_randtest(state); arf_one(x); arf_div_ui(x, x, m, 128, ARF_RND_UP); arf_add_ui(x, x, 1, 128, ARF_RND_UP); arf_pow_binexp_ui(x, x, n, 128, ARF_RND_UP); mag_binpow_uiui(b, m, n); arf_set_mag(y, b); MAG_CHECK_BITS(b) if (!(arf_cmpabs(x, y) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("m = %wu\n\n", m); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arf_printd(x, 10); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 10); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); mag_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-cmp.c000066400000000000000000000026651461254215100163420ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_cmp, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; mag_t xb, yb; int c1, c2; arf_init(x); arf_init(y); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); c1 = arf_cmp(x, y); c2 = mag_cmp(xb, yb); if (c1 != c2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("xb = "); mag_print(xb); flint_printf("\n\n"); flint_printf("yb = "); mag_print(yb); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-cmp_2exp_si.c000066400000000000000000000024331461254215100177640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" #include "long_extras.h" TEST_FUNCTION_START(mag_cmp_2exp_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x; mag_t xb; slong y; int c1, c2; arf_init(x); mag_init(xb); mag_randtest_special(xb, state, 100); y = z_randtest(state); arf_set_mag(x, xb); c1 = arf_cmp_2exp_si(x, y); c2 = mag_cmp_2exp_si(xb, y); if (c1 != c2) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %wd", y); flint_printf("\n\n"); flint_printf("xb = "); mag_print(xb); flint_printf("\n\n"); flint_abort(); } arf_clear(x); mag_clear(xb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-cosh.c000066400000000000000000000070271461254215100165140ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" #include "mag.h" void arf_cosh(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_cosh, x, NULL, prec, rnd); } TEST_FUNCTION_START(mag_cosh, state) { slong iter; /* test cosh */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_mul_2exp_si(xb, xb, -100 + n_randint(state,120)); mag_randtest_special(yb, state, 25); mag_cosh(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_cosh(z, x, MAG_BITS, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_cosh(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } /* test cosh_lower */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_mul_2exp_si(xb, xb, -100 + n_randint(state,120)); mag_randtest_special(yb, state, 25); mag_cosh_lower(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_cosh(z, x, MAG_BITS, ARF_RND_DOWN); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_cosh_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-d_log_lower_bound.c000066400000000000000000000046241461254215100212430ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "double_extras.h" #include "mpfr.h" #include "mag.h" /* Defined in t-d_log_lower_bound.c, t-d_log_upper_bound.c, t-set_d_2exp_fmpz.c * and t-set_d.c */ #ifndef d_randtest2 #define d_randtest2 d_randtest2 /* XXX: d_randtest is not good enough */ #define EXP_MINUS_32 2.3283064365386962891e-10 #define EXP_MINUS_64 5.42101086242752217e-20 double d_randtest2(flint_rand_t state) { mp_limb_t m1, m2; double t; if (FLINT_BITS == 64) { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); t = ((double) m1) * EXP_MINUS_64; } else { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); m2 = n_randtest(state); t = ((double) m1) * EXP_MINUS_32 + ((double) m2) * EXP_MINUS_64; } return t; } #endif TEST_FUNCTION_START(mag_d_log_lower_bound, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mpfr_t t; double x, y, z; mpfr_init2(t, 53); x = d_randtest2(state); x = ldexp(x, 100 - n_randint(state, 200)); switch (n_randint(state, 10)) { case 0: x = 1.0 + x; break; case 1: x = 1.0 - x; break; case 2: x = D_INF; break; case 3: x = 0.0; break; case 4: x = D_NAN; break; default: break; } y = mag_d_log_lower_bound(x); mpfr_set_d(t, x, MPFR_RNDD); mpfr_log(t, t, MPFR_RNDD); z = mpfr_get_d(t, MPFR_RNDD); if (y > z || fabs(y-z) > 0.000001 * fabs(z)) { flint_printf("FAIL\n"); flint_printf("x = %.20g\n", x); flint_printf("y = %.20g\n", y); flint_printf("z = %.20g\n", z); flint_abort(); } mpfr_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-d_log_upper_bound.c000066400000000000000000000046241461254215100212460ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "double_extras.h" #include "mpfr.h" #include "mag.h" /* Defined in t-d_log_lower_bound.c, t-d_log_upper_bound.c, t-set_d_2exp_fmpz.c * and t-set_d.c */ #ifndef d_randtest2 #define d_randtest2 d_randtest2 /* XXX: d_randtest is not good enough */ #define EXP_MINUS_32 2.3283064365386962891e-10 #define EXP_MINUS_64 5.42101086242752217e-20 double d_randtest2(flint_rand_t state) { mp_limb_t m1, m2; double t; if (FLINT_BITS == 64) { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); t = ((double) m1) * EXP_MINUS_64; } else { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); m2 = n_randtest(state); t = ((double) m1) * EXP_MINUS_32 + ((double) m2) * EXP_MINUS_64; } return t; } #endif TEST_FUNCTION_START(mag_d_log_upper_bound, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mpfr_t t; double x, y, z; mpfr_init2(t, 53); x = d_randtest2(state); x = ldexp(x, 100 - n_randint(state, 200)); switch (n_randint(state, 10)) { case 0: x = 1.0 + x; break; case 1: x = 1.0 - x; break; case 2: x = D_INF; break; case 3: x = 0.0; break; case 4: x = D_NAN; break; default: break; } y = mag_d_log_upper_bound(x); mpfr_set_d(t, x, MPFR_RNDD); mpfr_log(t, t, MPFR_RNDU); z = mpfr_get_d(t, MPFR_RNDD); if (y < z || fabs(y-z) > 0.000001 * fabs(z)) { flint_printf("FAIL\n"); flint_printf("x = %.20g\n", x); flint_printf("y = %.20g\n", y); flint_printf("z = %.20g\n", z); flint_abort(); } mpfr_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-div.c000066400000000000000000000035471461254215100163450ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_div, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 10); mag_randtest_special(yb, state, 10); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_div(z, x, y, MAG_BITS + 10, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_div(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-div_lower.c000066400000000000000000000035701461254215100175510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_div_lower, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 10); mag_randtest_special(yb, state, 10); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_div(z, x, y, MAG_BITS + 10, ARF_RND_DOWN); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); mag_div_lower(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z2, w) <= 0 && arf_cmpabs(w, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-dump_file.c000066400000000000000000000045771461254215100175330ustar00rootroot00000000000000/* Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb.h" TEST_FUNCTION_START(mag_dump_file, state) { slong iter; /* assume tmpfile() is broken on windows */ #if !defined(_MSC_VER) && !defined(__MINGW32__) /* just test no crashing... */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { mag_t x; FILE* tmp; mag_init(x); mag_randtest_special(x, state, 1 + n_randint(state, 100)); tmp = tmpfile(); mag_dump_file(tmp, x); fflush(tmp); rewind(tmp); mag_load_file(x, tmp); fclose(tmp); mag_clear(x); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mag_t x, y, z; int conversion_error; FILE* tmp; mag_init(x); mag_init(y); mag_init(z); mag_randtest_special(x, state, 1 + n_randint(state, 100)); mag_randtest_special(y, state, 1 + n_randint(state, 100)); mag_randtest_special(z, state, 1 + n_randint(state, 100)); tmp = tmpfile(); mag_dump_file(tmp, x); fputc(' ', tmp); mag_dump_file(tmp, y); fflush(tmp); rewind(tmp); conversion_error = mag_load_file(z, tmp); if (conversion_error || !mag_equal(x, z)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("x = "); mag_printd(x, 50); flint_printf("\n\n"); flint_printf("z = "); mag_printd(z, 50); flint_printf("\n\n"); flint_abort(); } conversion_error = mag_load_file(z, tmp); if (conversion_error || !mag_equal(y, z)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("y = "); mag_printd(y, 50); flint_printf("\n\n"); flint_printf("z = "); mag_printd(z, 50); flint_printf("\n\n"); flint_abort(); } fclose(tmp); mag_clear(x); mag_clear(y); mag_clear(z); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-dump_str.c000066400000000000000000000032311461254215100174060ustar00rootroot00000000000000/* Copyright (C) 2019 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mag.h" TEST_FUNCTION_START(mag_dump_str, state) { slong iter; /* just test no crashing... */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { mag_t x; char * s; mag_init(x); mag_randtest_special(x, state, 1 + n_randint(state, 100)); s = mag_dump_str(x); flint_free(s); mag_clear(x); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mag_t x, y; char * s; int conversion_error; mag_init(x); mag_init(y); mag_randtest_special(x, state, 1 + n_randint(state, 100)); mag_randtest_special(y, state, 1 + n_randint(state, 100)); s = mag_dump_str(x); conversion_error = mag_load_str(y, s); if (conversion_error || !mag_equal(x, y)) { flint_printf("FAIL (roundtrip) iter = %wd\n", iter); flint_printf("x = "); mag_printd(x, 50); flint_printf("\n\n"); flint_printf("s = %s", s); flint_printf("\n\n"); flint_printf("y = "); mag_printd(y, 50); flint_printf("\n\n"); flint_abort(); } flint_free(s); mag_clear(x); mag_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-exp.c000066400000000000000000000075741461254215100163630ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" #include "mag.h" /* Defined in t-exp.c and t-expinv.c */ #ifndef arf_exp #define arf_exp arf_exp void arf_exp(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_exp, x, NULL, prec, rnd); } #endif TEST_FUNCTION_START(mag_exp, state) { slong iter; /* test exp */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_randtest_special(yb, state, 0); mag_mul_2exp_si(xb, xb, -28 + n_randint(state,56)); mag_exp(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_exp(z, x, MAG_BITS, ARF_RND_UP); if (arf_cmpabs_ui(x, 1000) < 0) { arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); } else { arf_mul_2exp_si(z2, z, 2); } MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_exp(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } /* test exp_lower */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_randtest_special(yb, state, 0); mag_mul_2exp_si(xb, xb, -28 + n_randint(state,56)); mag_exp_lower(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_exp(z, x, MAG_BITS, ARF_RND_DOWN); if (arf_cmpabs_ui(x, 1000) < 0) { arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); } else { arf_mul_2exp_si(z2, z, -2); } MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_exp_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-exp_tail.c000066400000000000000000000100041461254215100173520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_fmpz #define arf_pow_binexp_fmpz arf_pow_binexp_fmpz void arf_pow_binexp_fmpz(arf_t y, const arf_t b, const fmpz_t e, slong prec, arf_rnd_t rnd) { slong i, wp, bits; if (fmpz_is_zero(e)) { arf_set_ui(y, UWORD(1)); return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); arf_pow_binexp_fmpz(y, b, f, prec + 2, (rnd == ARF_RND_FLOOR || rnd == ARF_RND_DOWN) ? ARF_RND_UP : ARF_RND_DOWN); arf_ui_div(y, UWORD(1), y, prec, rnd); fmpz_clear(f); return; } if (y == b) { arf_t t; arf_init(t); arf_set(t, b); arf_pow_binexp_fmpz(y, t, e, prec, rnd); arf_clear(t); return; } arf_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { arf_mul(y, y, y, wp, rnd); if (fmpz_tstbit(e, i)) arf_mul(y, y, b, wp, rnd); } } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_ui #define arf_pow_binexp_ui arf_pow_binexp_ui void arf_pow_binexp_ui(arf_t y, const arf_t b, ulong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init_set_ui(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_si #define arf_pow_binexp_si arf_pow_binexp_si void arf_pow_binexp_si(arf_t y, const arf_t b, slong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init(f); fmpz_set_si(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif TEST_FUNCTION_START(mag_exp_tail, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, t, y, z; fmpz_t f; mag_t xb, yb; ulong N, k; arf_init(x); arf_init(t); arf_init(y); arf_init(z); fmpz_init(f); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 6); mag_randtest_special(yb, state, 6); N = n_randint(state, 100); mag_exp_tail(yb, xb, N); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_pow_binexp_ui(t, x, N, MAG_BITS, ARF_RND_DOWN); fmpz_fac_ui(f, N); arf_div_fmpz(t, t, f, MAG_BITS, ARF_RND_DOWN); arf_set(z, t); for (k = 1; k < 50; k++) { arf_mul(t, t, x, MAG_BITS, ARF_RND_DOWN); arf_div_ui(t, t, N + k, MAG_BITS, ARF_RND_DOWN); arf_add(z, z, t, MAG_BITS, ARF_RND_DOWN); } MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("N = %wu\n\n", N); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_abort(); } mag_exp_tail(xb, xb, N); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(t); arf_clear(y); arf_clear(z); fmpz_clear(f); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-expinv.c000066400000000000000000000074751461254215100171000ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" #include "mag.h" /* Defined in t-exp.c and t-expinv.c */ #ifndef arf_exp #define arf_exp arf_exp void arf_exp(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_exp, x, NULL, prec, rnd); } #endif TEST_FUNCTION_START(mag_expinv, state) { slong iter; /* test expinv */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_randtest_special(yb, state, 0); mag_mul_2exp_si(xb, xb, -28 + n_randint(state,56)); mag_expinv(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_neg(z, x); arf_exp(z, z, MAG_BITS, ARF_RND_UP); /* this implementation is very crude */ arf_mul_2exp_si(z2, z, 2); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_expinv(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } /* test expinv_lower */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_randtest_special(yb, state, 0); mag_mul_2exp_si(xb, xb, -28 + n_randint(state,56)); mag_expinv_lower(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_neg(z, x); arf_exp(z, z, MAG_BITS, ARF_RND_DOWN); if (arf_cmpabs_ui(x, 1000) < 0) { arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); } else { arf_mul_2exp_si(z2, z, -2); } MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 10); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 10); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 10); flint_printf("\n\n"); flint_printf("z2 = "); arf_printd(z2, 10); flint_printf("\n\n"); flint_abort(); } mag_expinv_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-expm1.c000066400000000000000000000043631461254215100166120ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" #include "mag.h" void arf_expm1(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_expm1, x, NULL, prec, rnd); } TEST_FUNCTION_START(mag_expm1, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_randtest_special(yb, state, 0); mag_mul_2exp_si(xb, xb, -100 + n_randint(state,120)); mag_expm1(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_expm1(z, x, MAG_BITS, ARF_RND_UP); if (arf_cmpabs_ui(x, 1000) < 0) { arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); } else { arf_mul_2exp_si(z2, z, 2); } MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("z2 = "); arf_printd(z2, 15); flint_printf("\n\n"); flint_abort(); } mag_expm1(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-fac_ui.c000066400000000000000000000025711461254215100170050ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_fac_ui, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; fmpz_t f; mag_t xb; ulong n; arf_init(x); arf_init(y); fmpz_init(f); mag_init(xb); mag_randtest_special(xb, state, 80); n = n_randtest(state) % 2000; mag_fac_ui(xb, n); fmpz_fac_ui(f, n); arf_set_fmpz(x, f); arf_set_mag(y, xb); MAG_CHECK_BITS(xb) if (!(arf_cmpabs(y, x) >= 0)) { flint_printf("FAIL\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); fmpz_clear(f); mag_clear(xb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-fast_add_2exp_si.c000066400000000000000000000036201461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_fast_add_2exp_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, zb; slong e; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(zb); arf_randtest(x, state, MAG_BITS, 15); arf_abs(x, x); e = n_randint(state, 10000) - n_randint(state, 10000); arf_set_ui_2exp_si(y, 1, e); arf_add(z, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); arf_get_mag(xb, x); mag_fast_add_2exp_si(zb, xb, e); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-fast_addmul.c000066400000000000000000000105021461254215100200330ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_fast_addmul, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest(xb, state, 15); mag_randtest(yb, state, 15); mag_randtest(zb, state, 15); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_set_mag(z, zb); arf_addmul(z, x, y, MAG_BITS + 10, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_fast_addmul(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_addmul(z, z, y, MAG_BITS + 10, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_fast_addmul(zb, zb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_set(z, y); arf_addmul(z, x, z, MAG_BITS + 10, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, yb); mag_fast_addmul(zb, xb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_addmul(z, z, z, MAG_BITS + 10, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_fast_addmul(zb, zb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 3)\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-fast_mul.c000066400000000000000000000103521461254215100173650ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_fast_mul, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest(xb, state, 15); mag_randtest(yb, state, 15); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_mul(z, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_fast_mul(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_mul(z, z, y, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_fast_mul(zb, zb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_set(z, y); arf_mul(z, x, z, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, yb); mag_fast_mul(zb, xb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_mul(z, z, z, ARF_PREC_EXACT, ARF_RND_DOWN); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_fast_mul(zb, zb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 3)\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_printf("w = "); arf_printd(w, 15); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-fast_mul_2exp_si.c000066400000000000000000000027601461254215100210220ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_fast_mul_2exp_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z; mag_t xb, yb; slong e; arf_init(x); arf_init(y); arf_init(z); mag_init(xb); mag_init(yb); mag_randtest(xb, state, 15); e = n_randint(state, 10000) - n_randint(state, 10000); arf_set_mag(x, xb); mag_fast_mul_2exp_si(yb, xb, e); arf_mul_2exp_si(y, x, e); arf_set_mag(z, yb); MAG_CHECK_BITS(yb) if (!arf_equal(z, y)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-geom_series.c000066400000000000000000000074771461254215100200720ustar00rootroot00000000000000/* Copyright (C) 2015 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_fmpz #define arf_pow_binexp_fmpz arf_pow_binexp_fmpz void arf_pow_binexp_fmpz(arf_t y, const arf_t b, const fmpz_t e, slong prec, arf_rnd_t rnd) { slong i, wp, bits; if (fmpz_is_zero(e)) { arf_set_ui(y, UWORD(1)); return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); arf_pow_binexp_fmpz(y, b, f, prec + 2, (rnd == ARF_RND_FLOOR || rnd == ARF_RND_DOWN) ? ARF_RND_UP : ARF_RND_DOWN); arf_ui_div(y, UWORD(1), y, prec, rnd); fmpz_clear(f); return; } if (y == b) { arf_t t; arf_init(t); arf_set(t, b); arf_pow_binexp_fmpz(y, t, e, prec, rnd); arf_clear(t); return; } arf_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { arf_mul(y, y, y, wp, rnd); if (fmpz_tstbit(e, i)) arf_mul(y, y, b, wp, rnd); } } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_ui #define arf_pow_binexp_ui arf_pow_binexp_ui void arf_pow_binexp_ui(arf_t y, const arf_t b, ulong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init_set_ui(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_si #define arf_pow_binexp_si arf_pow_binexp_si void arf_pow_binexp_si(arf_t y, const arf_t b, slong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init(f); fmpz_set_si(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif TEST_FUNCTION_START(mag_geom_series, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, t, y, z; mag_t xb, yb; ulong N, k; arf_init(x); arf_init(t); arf_init(y); arf_init(z); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 6); mag_randtest_special(yb, state, 6); N = n_randint(state, 100); mag_geom_series(yb, xb, N); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_pow_binexp_ui(t, x, N, MAG_BITS, ARF_RND_DOWN); arf_set(z, t); for (k = 1; k < 50; k++) { arf_mul(t, t, x, MAG_BITS, ARF_RND_DOWN); arf_add(z, z, t, MAG_BITS, ARF_RND_DOWN); } MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("N = %wu\n\n", N); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_abort(); } mag_geom_series(xb, xb, N); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(t); arf_clear(y); arf_clear(z); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-get_d.c000066400000000000000000000034641461254215100166430ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "double_extras.h" #include "mag.h" TEST_FUNCTION_START(mag_get_d, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { mag_t x; arf_t a, b; double y; mag_init(x); arf_init(a); arf_init(b); mag_randtest_special(x, state, 1 + n_randint(state, 100)); y = mag_get_d(x); arf_set_d(a, y); arf_set_mag(b, x); if (mag_cmp_2exp_si(x, 1000) < 0 && mag_cmp_2exp_si(x, -1000) > 0) { if (!arf_equal(a, b)) { flint_printf("FAIL (equality)\n\n"); flint_printf("x = "); mag_print(x); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_abort(); } } else { if (arf_cmp(a, b) < 0) { flint_printf("FAIL (bound)\n\n"); flint_printf("x = "); mag_print(x); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_abort(); } } arf_clear(a); arf_clear(b); mag_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-hurwitz_zeta_uiui.c000066400000000000000000000035731461254215100213540ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" #include "arb.h" TEST_FUNCTION_START(mag_hurwitz_zeta_uiui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { mag_t zb; slong prec, k; ulong s, a; arb_t t, r, z; mag_init(zb); arb_init(t); arb_init(r); arb_init(z); mag_randtest_special(zb, state, 6); s = n_randtest(state); a = n_randtest(state); prec = MAG_BITS + 2 * FLINT_BIT_COUNT(s); mag_hurwitz_zeta_uiui(zb, s, a); arb_zero(r); for (k = 0; k < 50; k++) { arb_set_ui(t, a); arb_add_ui(t, t, k, prec); arb_pow_ui(t, t, s, prec); arb_inv(t, t, prec); arb_add(r, r, t, prec); } arb_zero(z); mag_set(arb_radref(z), zb); if (!arb_is_finite(z)) arb_indeterminate(z); if (!arb_contains(z, r)) { flint_printf("FAIL\n\n"); flint_printf("s = %wu\n\n", s); flint_printf("a = %wd\n\n", a); flint_printf("zb = "); mag_printd(zb, 15); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 15); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, 15); flint_printf("\n\n"); flint_abort(); } mag_clear(zb); arb_clear(t); arb_clear(r); arb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-log.c000066400000000000000000000120021461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" #include "mag.h" /* Defined in t-log.c and t-neg_log.c */ #ifndef arf_log #define arf_log arf_log void arf_log(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_log, x, NULL, prec, rnd); } #endif TEST_FUNCTION_START(mag_log, state) { slong iter; /* test log */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; fmpz_t n; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); fmpz_init(n); mag_randtest_special(xb, state, 25); mag_randtest_special(yb, state, 25); if (n_randint(state, 2)) { mag_log(yb, xb); arf_set_mag(x, xb); if (mag_cmp_2exp_si(xb, 0) <= 0) arf_zero(z); else arf_log(z, x, MAG_BITS, ARF_RND_UP); } else { arf_set_mag(x, xb); fmpz_randtest(n, state, 100); mag_mul_2exp_fmpz(xb, xb, n); mag_log(yb, xb); if (mag_cmp_2exp_si(xb, 0) <= 0) { arf_zero(z); } else { arf_log(z, x, 3 * MAG_BITS, ARF_RND_UP); arf_set_ui(z2, 2); arf_log(z2, z2, 3 * MAG_BITS, ARF_RND_UP); arf_addmul_fmpz(z, z2, n, 3 * MAG_BITS, ARF_RND_UP); } } arf_set_mag(y, yb); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_log(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); fmpz_clear(n); } /* test log_lower */ for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; fmpz_t n; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); fmpz_init(n); mag_randtest_special(xb, state, 25); mag_randtest_special(yb, state, 25); if (n_randint(state, 2)) { mag_log_lower(yb, xb); arf_set_mag(x, xb); if (mag_cmp_2exp_si(xb, 0) <= 0) arf_zero(z); else arf_log(z, x, MAG_BITS, ARF_RND_DOWN); } else { arf_set_mag(x, xb); fmpz_randtest(n, state, 100); mag_mul_2exp_fmpz(xb, xb, n); mag_log_lower(yb, xb); if (mag_cmp_2exp_si(xb, 0) <= 0) { arf_zero(z); } else { arf_log(z, x, 3 * MAG_BITS, ARF_RND_DOWN); arf_set_ui(z2, 2); arf_log(z2, z2, 3 * MAG_BITS, ARF_RND_DOWN); arf_addmul_fmpz(z, z2, n, 3 * MAG_BITS, ARF_RND_DOWN); } } arf_set_mag(y, yb); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_log_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-log1p.c000066400000000000000000000040251461254215100165750ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr.h" #include "arf.h" #include "mag.h" void arf_log1p(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_log1p, x, NULL, prec, rnd); } TEST_FUNCTION_START(mag_log1p, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 25); mag_randtest_special(yb, state, 25); mag_log1p(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_log1p(z, x, MAG_BITS, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_log1p(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-mul.c000066400000000000000000000105631461254215100163540ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_mul, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_mul(z, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_mul(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_mul(z, z, y, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_mul(zb, zb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_set(z, y); arf_mul(z, x, z, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, yb); mag_mul(zb, xb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_set(z, x); arf_mul(z, z, z, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_is_nan(z)) arf_pos_inf(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_set(zb, xb); mag_mul(zb, zb, zb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL (aliasing 3)\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-mul_2exp_fmpz.c000066400000000000000000000030141461254215100203370ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_mul_2exp_fmpz, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z; mag_t xb, yb; fmpz_t e; arf_init(x); arf_init(y); arf_init(z); fmpz_init(e); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 100); fmpz_randtest(e, state, 100); arf_set_mag(x, xb); mag_mul_2exp_fmpz(yb, xb, e); arf_mul_2exp_fmpz(y, x, e); arf_set_mag(z, yb); MAG_CHECK_BITS(yb) if (!arf_equal(z, y)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); mag_clear(xb); mag_clear(yb); fmpz_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-mul_2exp_si.c000066400000000000000000000027501461254215100200040ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" #include "long_extras.h" TEST_FUNCTION_START(mag_mul_2exp_si, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z; mag_t xb, yb; slong e; arf_init(x); arf_init(y); arf_init(z); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 100); e = z_randtest(state); arf_set_mag(x, xb); mag_mul_2exp_si(yb, xb, e); arf_mul_2exp_si(y, x, e); arf_set_mag(z, yb); MAG_CHECK_BITS(yb) if (!arf_equal(z, y)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); arf_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); arf_printd(z, 15); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-mul_lower.c000066400000000000000000000036601461254215100175640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_mul_lower, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_mul(z2, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); if (arf_is_nan(z2)) arf_zero(z2); arf_mul_ui(z, z2, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z, z, -10); mag_mul_lower(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-neg_log.c000066400000000000000000000124641461254215100171730ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" #include "mag.h" /* Defined in t-log.c and t-neg_log.c */ #ifndef arf_log #define arf_log arf_log void arf_log(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_log, x, NULL, prec, rnd); } #endif TEST_FUNCTION_START(mag_neg_log, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; fmpz_t n; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); fmpz_init(n); mag_randtest_special(xb, state, 25); mag_randtest_special(yb, state, 25); if (n_randint(state, 2)) { mag_neg_log(yb, xb); arf_set_mag(x, xb); if (mag_cmp_2exp_si(xb, 0) >= 0) arf_zero(z); else { arf_log(z, x, MAG_BITS, ARF_RND_UP); arf_neg(z, z); } } else { arf_set_mag(x, xb); fmpz_randtest(n, state, 100); mag_mul_2exp_fmpz(xb, xb, n); mag_neg_log(yb, xb); if (mag_cmp_2exp_si(xb, 0) >= 0) { arf_zero(z); } else { arf_log(z, x, 2 * MAG_BITS, ARF_RND_UP); arf_neg(z, z); arf_set_ui(z2, 2); arf_log(z2, z2, 2 * MAG_BITS, ARF_RND_UP); arf_submul_fmpz(z, z2, n, 2 * MAG_BITS, ARF_RND_UP); } } arf_set_mag(y, yb); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_neg_log(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); fmpz_clear(n); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; fmpz_t n; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); fmpz_init(n); mag_randtest_special(xb, state, 25); mag_randtest_special(yb, state, 25); if (n_randint(state, 2)) { mag_neg_log_lower(yb, xb); arf_set_mag(x, xb); if (mag_cmp_2exp_si(xb, 0) >= 0) arf_zero(z); else { arf_log(z, x, MAG_BITS, ARF_RND_DOWN); arf_neg(z, z); } } else { arf_set_mag(x, xb); fmpz_randtest(n, state, 100); mag_mul_2exp_fmpz(xb, xb, n); mag_neg_log_lower(yb, xb); if (mag_cmp_2exp_si(xb, 0) >= 0) { arf_zero(z); } else { arf_log(z, x, 2 * MAG_BITS, ARF_RND_DOWN); arf_neg(z, z); arf_set_ui(z2, 2); arf_log(z2, z2, 2 * MAG_BITS, ARF_RND_DOWN); arf_submul_fmpz(z, z2, n, 2 * MAG_BITS, ARF_RND_DOWN); } } arf_set_mag(y, yb); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_neg_log_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-polylog_tail.c000066400000000000000000000053411461254215100202530ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mag.h" #include "arb.h" TEST_FUNCTION_START(mag_polylog_tail, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { mag_t xb, yb; ulong N, k, d; slong s, prec; arb_t z, t, u, r; mag_init(xb); mag_init(yb); arb_init(z); arb_init(t); arb_init(u); arb_init(r); mag_randtest_special(xb, state, 6); mag_randtest_special(yb, state, 6); N = n_randint(state, 100); d = n_randint(state, 100); s = n_randint(state, 100) - 50; prec = 4 * MAG_BITS; mag_polylog_tail(yb, xb, s, d, N); arb_zero(z); arf_set_mag(arb_midref(z), xb); arb_zero(r); for (k = N; k < N + 100; k++) { arb_pow_ui(t, z, k, prec); arb_log_ui(u, k, prec); arb_pow_ui(u, u, d, prec); arb_mul(t, t, u, prec); arb_set_ui(u, k); if (s >= 0) { arb_pow_ui(u, u, s, prec); arb_div(t, t, u, prec); } else { arb_pow_ui(u, u, -s, prec); arb_mul(t, t, u, prec); } arb_add(r, r, t, prec); } MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) arb_zero(z); mag_set(arb_radref(z), yb); if (!arb_is_finite(z)) arb_indeterminate(z); if (!arb_contains(z, r)) { flint_printf("FAIL\n\n"); flint_printf("N = %wu\n\n", N); flint_printf("d = %wu\n\n", d); flint_printf("s = %wd\n\n", s); flint_printf("xb = "); mag_printd(xb, 15); flint_printf("\n\n"); flint_printf("yb = "); mag_printd(yb, 15); flint_printf("\n\n"); flint_printf("z = "); arb_printd(z, 15); flint_printf("\n\n"); flint_printf("r = "); arb_printd(r, 15); flint_printf("\n\n"); flint_abort(); } mag_polylog_tail(xb, xb, s, d, N); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } mag_clear(xb); mag_clear(yb); arb_clear(z); arb_clear(t); arb_clear(u); arb_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-pow_fmpz.c000066400000000000000000000126341461254215100174210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_fmpz #define arf_pow_binexp_fmpz arf_pow_binexp_fmpz void arf_pow_binexp_fmpz(arf_t y, const arf_t b, const fmpz_t e, slong prec, arf_rnd_t rnd) { slong i, wp, bits; if (fmpz_is_zero(e)) { arf_set_ui(y, UWORD(1)); return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); arf_pow_binexp_fmpz(y, b, f, prec + 2, (rnd == ARF_RND_FLOOR || rnd == ARF_RND_DOWN) ? ARF_RND_UP : ARF_RND_DOWN); arf_ui_div(y, UWORD(1), y, prec, rnd); fmpz_clear(f); return; } if (y == b) { arf_t t; arf_init(t); arf_set(t, b); arf_pow_binexp_fmpz(y, t, e, prec, rnd); arf_clear(t); return; } arf_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { arf_mul(y, y, y, wp, rnd); if (fmpz_tstbit(e, i)) arf_mul(y, y, b, wp, rnd); } } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_ui #define arf_pow_binexp_ui arf_pow_binexp_ui void arf_pow_binexp_ui(arf_t y, const arf_t b, ulong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init_set_ui(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_si #define arf_pow_binexp_si arf_pow_binexp_si void arf_pow_binexp_si(arf_t y, const arf_t b, slong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init(f); fmpz_set_si(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif TEST_FUNCTION_START(mag_pow_fmpz, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, w; mag_t xb, yb; fmpz_t e; arf_init(x); arf_init(y); arf_init(w); fmpz_init(e); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 80); mag_randtest_special(yb, state, 80); fmpz_randtest(e, state, 200); arf_set_mag(x, xb); arf_pow_binexp_fmpz(y, x, e, 2 * MAG_BITS, ARF_RND_UP); if (arf_is_nan(y)) arf_pos_inf(y); mag_pow_fmpz(yb, xb, e); arf_set_mag(w, yb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(y, w) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } mag_pow_fmpz(xb, xb, e); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); mag_print(xb); flint_printf("\n\n"); mag_print(yb); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(w); fmpz_clear(e); mag_clear(xb); mag_clear(yb); } for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, w; mag_t xb, yb; fmpz_t e; arf_init(x); arf_init(y); arf_init(w); fmpz_init(e); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 80); mag_randtest_special(yb, state, 80); fmpz_randtest(e, state, 200); arf_set_mag(x, xb); arf_pow_binexp_fmpz(y, x, e, 2 * MAG_BITS, ARF_RND_DOWN); if (arf_is_nan(y)) arf_pos_inf(y); mag_pow_fmpz_lower(yb, xb, e); arf_set_mag(w, yb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(w, y) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } mag_pow_fmpz_lower(xb, xb, e); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); mag_print(xb); flint_printf("\n\n"); mag_print(yb); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(w); fmpz_clear(e); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-pow_ui.c000066400000000000000000000122721461254215100170600ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_fmpz #define arf_pow_binexp_fmpz arf_pow_binexp_fmpz void arf_pow_binexp_fmpz(arf_t y, const arf_t b, const fmpz_t e, slong prec, arf_rnd_t rnd) { slong i, wp, bits; if (fmpz_is_zero(e)) { arf_set_ui(y, UWORD(1)); return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); arf_pow_binexp_fmpz(y, b, f, prec + 2, (rnd == ARF_RND_FLOOR || rnd == ARF_RND_DOWN) ? ARF_RND_UP : ARF_RND_DOWN); arf_ui_div(y, UWORD(1), y, prec, rnd); fmpz_clear(f); return; } if (y == b) { arf_t t; arf_init(t); arf_set(t, b); arf_pow_binexp_fmpz(y, t, e, prec, rnd); arf_clear(t); return; } arf_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { arf_mul(y, y, y, wp, rnd); if (fmpz_tstbit(e, i)) arf_mul(y, y, b, wp, rnd); } } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_ui #define arf_pow_binexp_ui arf_pow_binexp_ui void arf_pow_binexp_ui(arf_t y, const arf_t b, ulong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init_set_ui(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif /* Defined in t-binpow_uiui.c, t-exp_tail.c, t-geom_series.c, t-pow_ui.c and * t-pow_fmpz.c */ #ifndef arf_pow_binexp_si #define arf_pow_binexp_si arf_pow_binexp_si void arf_pow_binexp_si(arf_t y, const arf_t b, slong e, slong prec, arf_rnd_t rnd) { fmpz_t f; fmpz_init(f); fmpz_set_si(f, e); arf_pow_binexp_fmpz(y, b, f, prec, rnd); fmpz_clear(f); } #endif TEST_FUNCTION_START(mag_pow_ui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, w; mag_t xb, yb; ulong e; arf_init(x); arf_init(y); arf_init(w); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 80); mag_randtest_special(yb, state, 80); e = n_randtest(state); arf_set_mag(x, xb); arf_pow_binexp_ui(y, x, e, 2 * MAG_BITS, ARF_RND_UP); if (arf_is_nan(y)) arf_pos_inf(y); mag_pow_ui(yb, xb, e); arf_set_mag(w, yb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(y, w) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("e = %wu\n\n", e); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } mag_pow_ui(xb, xb, e); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("e = %wu\n\n", e); mag_print(xb); flint_printf("\n\n"); mag_print(yb); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(w); mag_clear(xb); mag_clear(yb); } for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, w; mag_t xb, yb; ulong e; arf_init(x); arf_init(y); arf_init(w); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 80); mag_randtest_special(yb, state, 80); e = n_randtest(state); arf_set_mag(x, xb); arf_pow_binexp_ui(y, x, e, 2 * MAG_BITS, ARF_RND_DOWN); if (arf_is_nan(y)) arf_pos_inf(y); mag_pow_ui_lower(yb, xb, e); arf_set_mag(w, yb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(w, y) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("e = %wu\n\n", e); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } mag_pow_ui_lower(xb, xb, e); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("e = %wu\n\n", e); mag_print(xb); flint_printf("\n\n"); mag_print(yb); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(w); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-rfac_ui.c000066400000000000000000000026541461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_rfac_ui, state) { slong iter; for (iter = 0; iter < 2000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y; fmpz_t f; mag_t xb; ulong n; arf_init(x); arf_init(y); fmpz_init(f); mag_init(xb); mag_randtest_special(xb, state, 80); n = n_randtest(state) % 2000; mag_rfac_ui(xb, n); fmpz_fac_ui(f, n); arf_one(x); arf_div_fmpz(x, x, f, 2 * MAG_BITS, ARF_RND_UP); arf_set_mag(y, xb); MAG_CHECK_BITS(xb) if (!(arf_cmpabs(y, x) >= 0)) { flint_printf("FAIL\n\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); fmpz_clear(f); mag_clear(xb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-root.c000066400000000000000000000037201461254215100165370ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_root, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; ulong n; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 1 + n_randint(state, 200)); mag_randtest_special(yb, state, 1 + n_randint(state, 200)); n = n_randint(state, 30); mag_root(yb, xb, n); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_root(z, x, n, MAG_BITS, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_root(xb, xb, n); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-rsqrt.c000066400000000000000000000036301461254215100167270ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_rsqrt, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 1 + n_randint(state, 200)); mag_randtest_special(yb, state, 1 + n_randint(state, 200)); mag_rsqrt(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_rsqrt(z, x, MAG_BITS, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_rsqrt(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-rsqrt_lower.c000066400000000000000000000036561461254215100201470ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_rsqrt_lower, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 1 + n_randint(state, 200)); mag_randtest_special(yb, state, 1 + n_randint(state, 200)); mag_rsqrt_lower(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_rsqrt(z, x, MAG_BITS, ARF_RND_DOWN); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_rsqrt_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-set_d.c000066400000000000000000000057461461254215100166640ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "double_extras.h" #include "mag.h" /* Defined in t-d_log_lower_bound.c, t-d_log_upper_bound.c, t-set_d_2exp_fmpz.c * and t-set_d.c */ #ifndef d_randtest2 #define d_randtest2 d_randtest2 /* XXX: d_randtest is not good enough */ #define EXP_MINUS_32 2.3283064365386962891e-10 #define EXP_MINUS_64 5.42101086242752217e-20 double d_randtest2(flint_rand_t state) { mp_limb_t m1, m2; double t; if (FLINT_BITS == 64) { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); t = ((double) m1) * EXP_MINUS_64; } else { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); m2 = n_randtest(state); t = ((double) m1) * EXP_MINUS_32 + ((double) m2) * EXP_MINUS_64; } return t; } #endif TEST_FUNCTION_START(mag_set_d, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t a, b, c; mag_t m; double x; arf_init(a); arf_init(b); arf_init(c); mag_init(m); x = d_randtest2(state); x = ldexp(x, 1100 - n_randint(state, 2200)); if (n_randint(state, 100) == 0) x = 0.0; if (n_randint(state, 100) == 0) x = D_INF; if (n_randint(state, 100) == 0) x = D_NAN; if (n_randint(state, 2)) x = -x; arf_set_d(a, x); mag_set_d(m, x); arf_set_mag(b, m); arf_set(c, a); arf_mul_ui(c, c, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(c, c, -10); MAG_CHECK_BITS(m) if (!(arf_cmpabs(a, b) <= 0 && arf_cmpabs(b, c) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_abort(); } mag_set_d_lower(m, x); arf_set_mag(b, m); arf_set(c, a); arf_mul_ui(c, c, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(c, c, -10); MAG_CHECK_BITS(m) if (!(arf_cmpabs(c, b) <= 0 && arf_cmpabs(b, a) <= 0)) { flint_printf("FAIL (lower)\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_abort(); } arf_clear(a); arf_clear(b); arf_clear(c); mag_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-set_d_2exp_fmpz.c000066400000000000000000000064351461254215100206520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "double_extras.h" #include "mag.h" /* Defined in t-d_log_lower_bound.c, t-d_log_upper_bound.c, t-set_d_2exp_fmpz.c * and t-set_d.c */ #ifndef d_randtest2 #define d_randtest2 d_randtest2 /* XXX: d_randtest is not good enough */ #define EXP_MINUS_32 2.3283064365386962891e-10 #define EXP_MINUS_64 5.42101086242752217e-20 double d_randtest2(flint_rand_t state) { mp_limb_t m1, m2; double t; if (FLINT_BITS == 64) { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); t = ((double) m1) * EXP_MINUS_64; } else { m1 = n_randtest(state) | (UWORD(1) << (FLINT_BITS - 1)); m2 = n_randtest(state); t = ((double) m1) * EXP_MINUS_32 + ((double) m2) * EXP_MINUS_64; } return t; } #endif TEST_FUNCTION_START(mag_set_d_2exp_fmpz, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t a, b, c; fmpz_t e; mag_t m; double x; arf_init(a); arf_init(b); arf_init(c); fmpz_init(e); mag_init(m); x = d_randtest2(state); x = ldexp(x, 1100 - n_randint(state, 2200)); if (n_randint(state, 100) == 0) x = 0.0; if (n_randint(state, 100) == 0) x = D_INF; if (n_randint(state, 100) == 0) x = D_NAN; if (n_randint(state, 2)) x = -x; fmpz_randtest(e, state, 100); arf_set_d(a, x); arf_abs(a, a); arf_mul_2exp_fmpz(a, a, e); mag_set_d_2exp_fmpz(m, x, e); arf_set_mag(b, m); arf_set(c, a); arf_mul_ui(c, c, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(c, c, -10); MAG_CHECK_BITS(m) if (!(arf_cmpabs(a, b) <= 0 && arf_cmpabs(b, c) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = %g\n\n", x); flint_printf("e = "); fmpz_print(e); flint_printf("\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_abort(); } mag_set_d_2exp_fmpz_lower(m, x, e); arf_set_mag(b, m); arf_set(c, a); arf_mul_ui(c, c, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(c, c, -10); MAG_CHECK_BITS(m) if (!(arf_cmpabs(c, b) <= 0 && arf_cmpabs(b, a) <= 0)) { flint_printf("FAIL (lower)\n\n"); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_abort(); } arf_clear(a); arf_clear(b); arf_clear(c); fmpz_clear(e); mag_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-set_ui.c000066400000000000000000000027451461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_set_ui, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t a, b, c; mag_t m; ulong x; arf_init(a); arf_init(b); arf_init(c); mag_init(m); x = n_randtest(state); arf_set_ui(a, x); mag_set_ui(m, x); arf_set_mag(b, m); arf_set(c, a); arf_mul_ui(c, c, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(c, c, -10); MAG_CHECK_BITS(m) if (!(arf_cmpabs(a, b) <= 0 && arf_cmpabs(b, c) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = %wu\n\n", x); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_abort(); } arf_clear(a); arf_clear(b); arf_clear(c); mag_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-set_ui_lower.c000066400000000000000000000027631461254215100202620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_set_ui_lower, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t a, b, c; mag_t m; ulong x; arf_init(a); arf_init(b); arf_init(c); mag_init(m); x = n_randtest(state); arf_set_ui(a, x); mag_set_ui_lower(m, x); arf_set_mag(b, m); arf_set(c, a); arf_mul_ui(c, c, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(c, c, -10); MAG_CHECK_BITS(m) if (!(arf_cmpabs(c, b) <= 0 && arf_cmpabs(b, a) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = %wu\n\n", x); flint_printf("a = "); arf_print(a); flint_printf("\n\n"); flint_printf("b = "); arf_print(b); flint_printf("\n\n"); flint_printf("c = "); arf_print(c); flint_printf("\n\n"); flint_abort(); } arf_clear(a); arf_clear(b); arf_clear(c); mag_clear(m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-sinh.c000066400000000000000000000070271461254215100165210ustar00rootroot00000000000000/* Copyright (C) 2017 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "arf.h" #include "mag.h" void arf_sinh(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { _arf_call_mpfr_func(y, NULL, (int (*)(void)) mpfr_sinh, x, NULL, prec, rnd); } TEST_FUNCTION_START(mag_sinh, state) { slong iter; /* test sinh */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_mul_2exp_si(xb, xb, -100 + n_randint(state,120)); mag_randtest_special(yb, state, 25); mag_sinh(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_sinh(z, x, MAG_BITS, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_sinh(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } /* test sinh_lower */ for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 0); mag_mul_2exp_si(xb, xb, -100 + n_randint(state,120)); mag_randtest_special(yb, state, 25); mag_sinh_lower(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_sinh(z, x, MAG_BITS, ARF_RND_DOWN); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_sinh_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-sqrt.c000066400000000000000000000036241461254215100165500ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_sqrt, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 1 + n_randint(state, 200)); mag_randtest_special(yb, state, 1 + n_randint(state, 200)); mag_sqrt(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_sqrt(z, x, MAG_BITS, ARF_RND_UP); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z, y) <= 0 && arf_cmpabs(y, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_sqrt(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-sqrt_lower.c000066400000000000000000000036521461254215100177610ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_sqrt_lower, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2; mag_t xb, yb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 1 + n_randint(state, 200)); mag_randtest_special(yb, state, 1 + n_randint(state, 200)); mag_sqrt_lower(yb, xb); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_sqrt(z, x, MAG_BITS, ARF_RND_DOWN); arf_mul_ui(z2, z, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z2, z2, -10); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) if (!(arf_cmpabs(z2, y) <= 0 && arf_cmpabs(y, z) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("z2 = "); arf_print(z2); flint_printf("\n\n"); flint_abort(); } mag_sqrt_lower(xb, xb); if (!mag_equal(xb, yb)) { flint_printf("FAIL (aliasing)\n\n"); flint_abort(); } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); mag_clear(xb); mag_clear(yb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-sub.c000066400000000000000000000045341461254215100163510ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_sub, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_sub(z, x, y, 100, ARF_RND_UP); if (arf_sgn(z) < 0) arf_zero(z); arf_mul_ui(z2, z, 1025, MAG_BITS, ARF_RND_UP); arf_mul_2exp_si(z2, z2, -10); mag_sub(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { mag_sub(xb, xb, yb); if (!mag_equal(xb, zb)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } else { mag_sub(yb, xb, yb); if (!mag_equal(yb, zb)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mag/test/t-sub_lower.c000066400000000000000000000045711461254215100175620ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arf.h" #include "mag.h" TEST_FUNCTION_START(mag_sub_lower, state) { slong iter; for (iter = 0; iter < 100000 * 0.1 * flint_test_multiplier(); iter++) { arf_t x, y, z, z2, w; mag_t xb, yb, zb; arf_init(x); arf_init(y); arf_init(z); arf_init(z2); arf_init(w); mag_init(xb); mag_init(yb); mag_init(zb); mag_randtest_special(xb, state, 100); mag_randtest_special(yb, state, 100); arf_set_mag(x, xb); arf_set_mag(y, yb); arf_sub(z2, x, y, 100, ARF_RND_DOWN); if (arf_sgn(z2) < 0) arf_zero(z2); arf_mul_ui(z, z2, 1023, MAG_BITS, ARF_RND_DOWN); arf_mul_2exp_si(z, z, -10); mag_sub_lower(zb, xb, yb); arf_set_mag(w, zb); MAG_CHECK_BITS(xb) MAG_CHECK_BITS(yb) MAG_CHECK_BITS(zb) if (!(arf_cmpabs(z, w) <= 0 && arf_cmpabs(w, z2) <= 0)) { flint_printf("FAIL\n\n"); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("w = "); arf_print(w); flint_printf("\n\n"); flint_abort(); } if (n_randint(state, 2)) { mag_sub_lower(xb, xb, yb); if (!mag_equal(xb, zb)) { flint_printf("FAIL (aliasing 1)\n\n"); flint_abort(); } } else { mag_sub_lower(yb, xb, yb); if (!mag_equal(yb, zb)) { flint_printf("FAIL (aliasing 2)\n\n"); flint_abort(); } } arf_clear(x); arf_clear(y); arf_clear(z); arf_clear(z2); arf_clear(w); mag_clear(xb); mag_clear(yb); mag_clear(zb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpf-impl.h000066400000000000000000000027611461254215100153220ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* NOTE: This module is only used for fmpz_lll and should probably be * deprecated. Corresponding source file can be found in fmpz_lll/mpf-impl.c. */ #ifndef FLINT_MPF_H #define FLINT_MPF_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif typedef __mpf_struct mpf; typedef struct { mpf * entries; slong r; slong c; flint_bitcnt_t prec; mpf ** rows; } mpf_mat_struct; typedef mpf_mat_struct mpf_mat_t[1]; mpf * _mpf_vec_init(slong len, flint_bitcnt_t prec); void _mpf_vec_clear(mpf * vec, slong len); void _mpf_vec_set_fmpz_vec(mpf * appv, const fmpz * vec, slong len); int _mpf_vec_dot2(mpf_t res, const mpf * vec1, const mpf * vec2, slong len2, flint_bitcnt_t prec); void _mpf_vec_norm2(mpf_t res, const mpf * vec, slong len, flint_bitcnt_t prec); void _mpf_vec_norm(mpf_t res, const mpf * vec, slong len); FLINT_FORCE_INLINE mpf * mpf_mat_entry(const mpf_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } void mpf_mat_init(mpf_mat_t mat, slong rows, slong cols, flint_bitcnt_t prec); void mpf_mat_clear(mpf_mat_t mat); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/mpfr_mat.h000066400000000000000000000040031461254215100153750ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef MPFR_MAT_H #define MPFR_MAT_H #ifdef MPFR_MAT_INLINES_C #define MPFR_MAT_INLINE #else #define MPFR_MAT_INLINE static inline #endif #include "flint.h" #include #ifdef __cplusplus extern "C" { #endif typedef struct { __mpfr_struct * entries; slong r; slong c; flint_bitcnt_t prec; __mpfr_struct ** rows; } mpfr_mat_struct; /* fmpz_mat_t allows reference-like semantics for fmpz_mat_struct */ typedef mpfr_mat_struct mpfr_mat_t[1]; MPFR_MAT_INLINE __mpfr_struct * mpfr_mat_entry(const mpfr_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } MPFR_MAT_INLINE slong mpfr_mat_nrows(const mpfr_mat_t mat) { return mat->r; } MPFR_MAT_INLINE slong mpfr_mat_ncols(const mpfr_mat_t mat) { return mat->c; } void mpfr_mat_init(mpfr_mat_t mat, slong rows, slong cols, mpfr_prec_t prec); void mpfr_mat_swap(mpfr_mat_t mat1, mpfr_mat_t mat2); MPFR_MAT_INLINE void mpfr_mat_swap_entrywise(mpfr_mat_t mat1, mpfr_mat_t mat2) { slong i, j; for (i = 0; i < mpfr_mat_nrows(mat1); i++) for (j = 0; j < mpfr_mat_ncols(mat1); j++) mpfr_swap(mpfr_mat_entry(mat2, i, j), mpfr_mat_entry(mat1, i, j)); } void mpfr_mat_set(mpfr_mat_t mat1, const mpfr_mat_t mat2); void mpfr_mat_clear(mpfr_mat_t mat); int mpfr_mat_equal(const mpfr_mat_t mat1, const mpfr_mat_t mat2); void mpfr_mat_zero(mpfr_mat_t mat); /* Random matrix generation *************************************************/ void mpfr_mat_randtest(mpfr_mat_t mat, flint_rand_t state); /* Multiplication */ void mpfr_mat_mul_classical(mpfr_mat_t C, const mpfr_mat_t A, const mpfr_mat_t B, mpfr_rnd_t rnd); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/mpfr_mat/000077500000000000000000000000001461254215100152275ustar00rootroot00000000000000flint-3.1.3/src/mpfr_mat/clear.c000066400000000000000000000014151461254215100164620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_mat.h" void mpfr_mat_clear(mpfr_mat_t mat) { if (mat->entries) { slong i; for (i = 0; i < mat->r * mat->c; i++) mpfr_clear(mat->entries + i); /* Clear all coefficients */ flint_free(mat->entries); /* Clean up array of entries */ flint_free(mat->rows); /* Clean up row array */ } } flint-3.1.3/src/mpfr_mat/equal.c000066400000000000000000000015541461254215100165070ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_vec.h" #include "mpfr_mat.h" int mpfr_mat_equal(const mpfr_mat_t mat1, const mpfr_mat_t mat2) { slong j; if (mat1->r != mat2->r || mat1->c != mat2->c) { return 0; } if (mat1->r == 0 || mat1->c == 0) return 1; for (j = 0; j < mat1->r; j++) { if (!_mpfr_vec_equal(mat1->rows[j], mat2->rows[j], mat1->c)) { return 0; } } return 1; } flint-3.1.3/src/mpfr_mat/init.c000066400000000000000000000021571461254215100163430ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_mat.h" void mpfr_mat_init(mpfr_mat_t mat, slong rows, slong cols, mpfr_prec_t prec) { if (rows != 0 && cols != 0) /* Allocate space for r*c small entries */ { slong i; mat->entries = (__mpfr_struct *) flint_malloc(flint_mul_sizes(rows, cols) * sizeof(__mpfr_struct)); mat->rows = (__mpfr_struct **) flint_malloc(rows * sizeof(__mpfr_struct *)); /* Initialise rows */ for (i = 0; i < rows * cols; i++) mpfr_init2(mat->entries + i, prec); for (i = 0; i < rows; i++) mat->rows[i] = mat->entries + i * cols; } else mat->entries = NULL; mat->r = rows; mat->c = cols; mat->prec = prec; } flint-3.1.3/src/mpfr_mat/mul_classical.c000066400000000000000000000032361461254215100202120ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_mat.h" void mpfr_mat_mul_classical(mpfr_mat_t C, const mpfr_mat_t A, const mpfr_mat_t B, mpfr_rnd_t rnd) { slong ar, bc, br; slong i, j, k; mpfr_t tmp; ar = A->r; br = B->r; bc = B->c; if (C == A || C == B) { mpfr_mat_t t; mpfr_mat_init(t, ar, bc, C->prec); mpfr_mat_mul_classical(t, A, B, rnd); mpfr_mat_swap_entrywise(C, t); mpfr_mat_clear(t); return; } if (C->r != ar || C->c != bc) { flint_throw(FLINT_ERROR, "(mpfr_mat_mul_classical): Incompatible dimensions.\n"); } if (br == 0) { mpfr_mat_zero(C); return; } mpfr_init2(tmp, C->prec); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { mpfr_mul(mpfr_mat_entry(C, i, j), mpfr_mat_entry(A, i, 0), mpfr_mat_entry(B, 0, j), rnd); for (k = 1; k < br; k++) { mpfr_mul(tmp, mpfr_mat_entry(A, i, k), mpfr_mat_entry(B, k, j), rnd); mpfr_add(mpfr_mat_entry(C, i, j), mpfr_mat_entry(C, i, j), tmp, rnd); } } } mpfr_clear(tmp); } flint-3.1.3/src/mpfr_mat/randtest.c000066400000000000000000000013451461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_mat.h" void mpfr_mat_randtest(mpfr_mat_t mat, flint_rand_t state) { slong r, c, i, j; r = mat->r; c = mat->c; _flint_rand_init_gmp(state); for (i = 0; i < r; i++) for (j = 0; j < c; j++) mpfr_urandomb(mpfr_mat_entry(mat, i, j), state->gmp_state); } flint-3.1.3/src/mpfr_mat/set.c000066400000000000000000000014161461254215100161700ustar00rootroot00000000000000/* Copyright (C) 2008-2009 William Hart Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_vec.h" #include "mpfr_mat.h" void mpfr_mat_set(mpfr_mat_t mat1, const mpfr_mat_t mat2) { if (mat1 != mat2) { slong i; if (mat2->r && mat2->c) for (i = 0; i < mat2->r; i++) _mpfr_vec_set(mat1->rows[i], mat2->rows[i], mat2->c); } } flint-3.1.3/src/mpfr_mat/swap.c000066400000000000000000000010651461254215100163470ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_mat.h" void mpfr_mat_swap(mpfr_mat_t mat1, mpfr_mat_t mat2) { FLINT_SWAP(mpfr_mat_struct, *mat1, *mat2); } flint-3.1.3/src/mpfr_mat/test/000077500000000000000000000000001461254215100162065ustar00rootroot00000000000000flint-3.1.3/src/mpfr_mat/test/main.c000066400000000000000000000017651461254215100173070ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-entry.c" #include "t-equal.c" #include "t-init_clear.c" #include "t-mul_classical.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(mpfr_mat_entry), TEST_FUNCTION(mpfr_mat_equal), TEST_FUNCTION(mpfr_mat_init_clear), TEST_FUNCTION(mpfr_mat_mul_classical), TEST_FUNCTION(mpfr_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/mpfr_mat/test/t-entry.c000066400000000000000000000024751461254215100177640ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr_mat.h" TEST_FUNCTION_START(mpfr_mat_entry, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpfr_mat_t A; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); mpfr_mat_init(A, rows, cols, 200); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { mpfr_set_si(mpfr_mat_entry(A, j, k), 3 * j + 7 * k, MPFR_RNDN); } } for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { if (mpfr_cmp_si(mpfr_mat_entry(A, j, k), 3 * j + 7 * k) != 0) TEST_FUNCTION_FAIL("get/set entry %wd, %wd\n", j, k); } } mpfr_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpfr_mat/test/t-equal.c000066400000000000000000000030661461254215100177270ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr_mat.h" TEST_FUNCTION_START(mpfr_mat_equal, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpfr_mat_t A, B, D, E; slong m, n, j; m = n_randint(state, 20); n = n_randint(state, 20); mpfr_mat_init(A, m, n, 200); mpfr_mat_init(B, m, n, 200); mpfr_mat_init(D, m + 1, n, 200); mpfr_mat_init(E, m, n + 1, 200); if (mpfr_mat_equal(A, D) || mpfr_mat_equal(A, E)) TEST_FUNCTION_FAIL("different dimensions should not be equal\n"); mpfr_mat_randtest(A, state); mpfr_mat_set(B, A); if (!mpfr_mat_equal(A, B)) TEST_FUNCTION_FAIL("copied matrices should be equal\n"); if (m && n) { j = n_randint(state, m * n); mpfr_add_ui(A->entries + j, A->entries + j, 1, MPFR_RNDN); if (mpfr_mat_equal(A, B)) TEST_FUNCTION_FAIL("modified matrices should not be equal\n"); } mpfr_mat_clear(A); mpfr_mat_clear(B); mpfr_mat_clear(D); mpfr_mat_clear(E); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpfr_mat/test/t-init_clear.c000066400000000000000000000017251461254215100207310ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "mpfr_mat.h" TEST_FUNCTION_START(mpfr_mat_init_clear, state) { int i; for (i = 0; i < 1000; i++) { mpfr_mat_t a; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); mp_prec_t prec = n_randint(state, 200) + MPFR_PREC_MIN; mpfr_mat_init(a, rows, cols, prec); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) mpfr_set_ui(a->rows[j] + k, 0, GMP_RNDN); mpfr_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpfr_mat/test/t-mul_classical.c000066400000000000000000000037251461254215100214350ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr_mat.h" TEST_FUNCTION_START(mpfr_mat_mul_classical, state) { slong i; /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { mpfr_mat_t A, B, C; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); mpfr_mat_init(A, m, n, 200); mpfr_mat_init(B, n, n, 200); mpfr_mat_init(C, m, n, 200); mpfr_mat_randtest(A, state); mpfr_mat_randtest(B, state); mpfr_mat_randtest(C, state); mpfr_mat_mul_classical(C, A, B, MPFR_RNDN); mpfr_mat_mul_classical(A, A, B, MPFR_RNDN); if (!mpfr_mat_equal(C, A)) TEST_FUNCTION_FAIL("aliasing failed\n"); mpfr_mat_clear(A); mpfr_mat_clear(B); mpfr_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { mpfr_mat_t A, B, C; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); mpfr_mat_init(A, m, m, 200); mpfr_mat_init(B, m, n, 200); mpfr_mat_init(C, m, n, 200); mpfr_mat_randtest(A, state); mpfr_mat_randtest(B, state); mpfr_mat_randtest(C, state); mpfr_mat_mul_classical(C, A, B, MPFR_RNDN); mpfr_mat_mul_classical(B, A, B, MPFR_RNDN); if (!mpfr_mat_equal(C, B)) TEST_FUNCTION_FAIL("aliasing failed\n"); mpfr_mat_clear(A); mpfr_mat_clear(B); mpfr_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpfr_mat/test/t-zero.c000066400000000000000000000021171461254215100175730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr_mat.h" TEST_FUNCTION_START(mpfr_mat_zero, state) { slong m, n, i, j, rep; for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { mpfr_mat_t A; m = n_randint(state, 20); n = n_randint(state, 20); mpfr_mat_init(A, m, n, 200); mpfr_mat_randtest(A, state); mpfr_mat_zero(A); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (!mpfr_zero_p(mpfr_mat_entry(A, i, j))) TEST_FUNCTION_FAIL("nonzero entry\n"); } } mpfr_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpfr_mat/zero.c000066400000000000000000000012141461254215100163500ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_vec.h" #include "mpfr_mat.h" void mpfr_mat_zero(mpfr_mat_t mat) { slong i; if (mat->c < 1) return; for (i = 0; i < mat->r; i++) _mpfr_vec_zero(mat->rows[i], mat->c); } flint-3.1.3/src/mpfr_vec.h000066400000000000000000000026251461254215100154010ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef MPFR_VEC_H #define MPFR_VEC_H #ifdef MPFR_VEC_INLINES_C #define MPFR_VEC_INLINE #else #define MPFR_VEC_INLINE static inline #endif #include #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Soon to be deprecated */ #define flint_mpfr __mpfr_struct mpfr_ptr _mpfr_vec_init(slong length, flint_bitcnt_t prec); void _mpfr_vec_clear(mpfr_ptr vec, slong length); void _mpfr_vec_randtest(mpfr_ptr f, flint_rand_t state, slong len); void _mpfr_vec_zero(mpfr_ptr vec, slong length); void _mpfr_vec_set(mpfr_ptr vec1, mpfr_srcptr vec2, slong length); int _mpfr_vec_equal(mpfr_srcptr vec1, mpfr_srcptr vec2, slong len); void _mpfr_vec_add(mpfr_ptr res, mpfr_srcptr vec1, mpfr_srcptr vec2, slong length); void _mpfr_vec_scalar_mul_2exp(mpfr_ptr res, mpfr_srcptr vec, slong length, flint_bitcnt_t exp); void _mpfr_vec_scalar_mul_mpfr(mpfr_ptr res, mpfr_srcptr vec, slong length, mpfr_t c); void _mpfr_vec_scalar_product(mpfr_t res, mpfr_srcptr vec1, mpfr_srcptr vec2, slong length); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/mpfr_vec/000077500000000000000000000000001461254215100152235ustar00rootroot00000000000000flint-3.1.3/src/mpfr_vec/add.c000066400000000000000000000011641461254215100161210ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_add(mpfr_ptr res, mpfr_srcptr vec1, mpfr_srcptr vec2, slong length) { slong i; for (i = 0; i < length; i++) mpfr_add(res + i, vec1 + i, vec2 + i, GMP_RNDN); } flint-3.1.3/src/mpfr_vec/clear.c000066400000000000000000000011131461254215100164510ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_clear(mpfr_ptr vec, slong length) { slong i; for (i = 0; i < length; i++) mpfr_clear(vec + i); flint_free(vec); } flint-3.1.3/src/mpfr_vec/equal.c000066400000000000000000000013031461254215100164730ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_vec.h" int _mpfr_vec_equal(mpfr_srcptr vec1, mpfr_srcptr vec2, slong len) { slong i; if (vec1 == vec2) return 1; for (i = 0; i < len; i++) if (!mpfr_equal_p(vec1 + i, vec2 + i)) return 0; return 1; } flint-3.1.3/src/mpfr_vec/init.c000066400000000000000000000012721461254215100163340ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" mpfr_ptr _mpfr_vec_init(slong length, flint_bitcnt_t prec) { slong i; __mpfr_struct *vec = (__mpfr_struct *) flint_malloc(length * sizeof(__mpfr_struct)); for (i = 0; i < length; i++) mpfr_init2(vec + i, prec); return vec; } flint-3.1.3/src/mpfr_vec/randtest.c000066400000000000000000000011511461254215100172110ustar00rootroot00000000000000/* Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_randtest(mpfr_ptr f, flint_rand_t state, slong len) { slong i; _flint_rand_init_gmp(state); for (i = 0; i < len; i++) mpfr_urandomb(f + i, state->gmp_state); } flint-3.1.3/src/mpfr_vec/scalar_mul_2exp.c000066400000000000000000000012001461254215100204400ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_scalar_mul_2exp(mpfr_ptr res, mpfr_srcptr vec, slong length, flint_bitcnt_t exp) { slong i; for (i = 0; i < length; i++) mpfr_mul_2exp(res + i, vec + i, exp, GMP_RNDN); } flint-3.1.3/src/mpfr_vec/scalar_mul_mpfr.c000066400000000000000000000011571461254215100205410ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_scalar_mul_mpfr(mpfr_ptr res, mpfr_srcptr vec, slong length, mpfr_t c) { slong i; for (i = 0; i < length; i++) mpfr_mul(res + i, vec + i, c, GMP_RNDN); } flint-3.1.3/src/mpfr_vec/scalar_product.c000066400000000000000000000014551461254215100204010ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_scalar_product(mpfr_t res, mpfr_srcptr vec1, mpfr_srcptr vec2, slong length) { slong i; mpfr_t tmp; mpfr_init(tmp); mpfr_mul(res, vec1, vec2, GMP_RNDN); for (i = 1; i < length; i++) { mpfr_mul(tmp, vec1 + i, vec2 + i, GMP_RNDN); mpfr_add(res, res, tmp, GMP_RNDN); } mpfr_clear(tmp); } flint-3.1.3/src/mpfr_vec/set.c000066400000000000000000000011321461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_set(mpfr_ptr vec1, mpfr_srcptr vec2, slong length) { slong i; for (i = 0; i < length; i++) mpfr_set(vec1 + i, vec2 + i, GMP_RNDN); } flint-3.1.3/src/mpfr_vec/test/000077500000000000000000000000001461254215100162025ustar00rootroot00000000000000flint-3.1.3/src/mpfr_vec/test/main.c000066400000000000000000000015071461254215100172750ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-init_clear.c" #include "t-set_equal.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(mpfr_vec_init_clear), TEST_FUNCTION(mpfr_vec_set_equal) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/mpfr_vec/test/t-init_clear.c000066400000000000000000000015661461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include #include "mpfr_vec.h" TEST_FUNCTION_START(mpfr_vec_init_clear, state) { int i; for (i = 0; i < 10000; i++) { __mpfr_struct *a; slong j, length = n_randint(state, 100); mp_prec_t prec = n_randint(state, 200) + MPFR_PREC_MIN; a = _mpfr_vec_init(length, prec); for (j = 0; j < length; j++) mpfr_set_ui(a + j, 0, GMP_RNDN); _mpfr_vec_clear(a, length); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpfr_vec/test/t-set_equal.c000066400000000000000000000040761461254215100206000ustar00rootroot00000000000000/* Copyright (C) 2009, 2010 William Hart Copyright (C) 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpfr_vec.h" TEST_FUNCTION_START(mpfr_vec_set_equal, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpfr_ptr a; slong len = n_randint(state, 100); a = _mpfr_vec_init(len, 200); _mpfr_vec_randtest(a, state, len); _mpfr_vec_set(a, a, len); result = (_mpfr_vec_equal(a, a, len)); if (!result) TEST_FUNCTION_FAIL(""); _mpfr_vec_clear(a, len); } /* Compare copied vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpfr_ptr a, b; slong len = n_randint(state, 100); a = _mpfr_vec_init(len, 200); b = _mpfr_vec_init(len, 200); _mpfr_vec_randtest(a, state, len); _mpfr_vec_set(b, a, len); result = (_mpfr_vec_equal(a, b, len)); if (!result) TEST_FUNCTION_FAIL(""); _mpfr_vec_clear(a, len); _mpfr_vec_clear(b, len); } /* Compare unequal vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpfr_ptr a, b; slong len = n_randint(state, 100) + 1; slong coeff; a = _mpfr_vec_init(len, 200); b = _mpfr_vec_init(len, 200); _mpfr_vec_randtest(a, state, len); _mpfr_vec_set(b, a, len); coeff = n_randint(state, len); mpfr_add_ui(b + coeff, b + coeff, 1, MPFR_RNDN); result = (!_mpfr_vec_equal(a, b, len)); if (!result) TEST_FUNCTION_FAIL(""); _mpfr_vec_clear(a, len); _mpfr_vec_clear(b, len); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpfr_vec/zero.c000066400000000000000000000011031461254215100163410ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_zero(mpfr_ptr vec, slong length) { slong i; for (i = 0; i < length; i++) mpfr_set_ui(vec + i, 0, GMP_RNDN); } flint-3.1.3/src/mpn_extras.h000066400000000000000000000547661461254215100157750ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson 2x2 mul code taken from MPFR 2.3.0 (Copyright (C) 1991-2007 Free Software Foundation, Inc.) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef MPN_EXTRAS_H #define MPN_EXTRAS_H #ifdef MPN_EXTRAS_INLINES_C #define MPN_EXTRAS_INLINE #else #define MPN_EXTRAS_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif #define MPN_NORM(a, an) \ do { \ while ((an) != 0 && (a)[(an) - 1] == 0) \ (an)--; \ } while (0) #define MPN_SWAP(a, an, b, bn) \ do { \ mp_ptr __t; \ mp_size_t __tn; \ __t = (a); \ (a) = (b); \ (b) = __t; \ __tn = (an); \ (an) = (bn); \ (bn) = __tn; \ } while (0) #define BITS_TO_LIMBS(b) (((b) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) /* Macros for few-limb arithmetic */ #define FLINT_MPN_MUL_2X1(r2, r1, r0, a1, a0, b0) \ do { \ mp_limb_t t1; \ umul_ppmm(r1, r0, a0, b0); \ umul_ppmm(r2, t1, a1, b0); \ add_ssaaaa(r2, r1, r2, r1, 0, t1); \ } while (0) /* todo: use optimal code here */ #define FLINT_MPN_MUL_2X2(r3, r2, r1, r0, a1, a0, b1, b0) \ do { \ mp_limb_t t1, t2, t3; \ umul_ppmm(r1, r0, a0, b0); \ umul_ppmm(r2, t1, a1, b0); \ add_ssaaaa(r2, r1, r2, r1, 0, t1); \ umul_ppmm(t1, t2, a0, b1); \ umul_ppmm(r3, t3, a1, b1); \ add_ssaaaa(r3, t1, r3, t1, 0, t3); \ add_ssaaaa(r2, r1, r2, r1, t1, t2); \ r3 += r2 < t1; \ } while (0) /* {s0,s1,s2} = u[0]v[n-1] + u[1]v[n-2] + ... */ /* Assumes n >= 2 */ #define NN_DOTREV_S3_1X1(s2, s1, s0, u, v, n) \ do { \ mp_limb_t __dt0, __dt1, __ds0, __ds1, __ds2; \ slong __i; \ FLINT_ASSERT((n) >= 2); \ umul_ppmm(__ds1, __ds0, (u)[0], (v)[(n) - 1]); \ umul_ppmm(__dt1, __dt0, (u)[1], (v)[(n) - 2]); \ add_sssaaaaaa(__ds2, __ds1, __ds0, 0, __ds1, __ds0, 0, __dt1, __dt0); \ for (__i = 2; __i < (n); __i++) \ { \ umul_ppmm(__dt1, __dt0, (u)[i], (v)[(n) - 1 - __i]); \ add_sssaaaaaa(__ds2, __ds1, __ds0, __ds2, __ds1, __ds0, 0, __dt1, __dt0); \ } \ (s0) = __ds0; (s1) = __ds1; (s2) = __ds2; \ } while (0) \ /* {r0,r1,r2} = {s0,s1,s2} + u[0]v[n-1] + u[1]v[n-2] + ... */ /* Assumes n >= 1. May have s2 != 0, but the final sum is assumed to fit in 3 limbs. */ #define NN_DOTREV_S3_A3_1X1(r2, r1, r0, s2, s1, s0, u, v, n) \ do { \ mp_limb_t __dt0, __dt1, __ds0, __ds1, __ds2; \ slong __i; \ FLINT_ASSERT((n) >= 1); \ __ds0 = (s0); __ds1 = (s1); __ds2 = (s2); \ for (__i = 0; __i < (n); __i++) \ { \ umul_ppmm(__dt1, __dt0, (u)[__i], (v)[(n) - 1 - __i]); \ add_sssaaaaaa(__ds2, __ds1, __ds0, __ds2, __ds1, __ds0, 0, __dt1, __dt0); \ } \ (r0) = __ds0; (r1) = __ds1; (r2) = __ds2; \ } while (0) \ #define NN_MUL_1X1 umul_ppmm /* {r0,r1} = {s0,s1} + x * y, with no carry-out. */ #define NN_ADDMUL_S2_A2_1X1(r1, r0, s1, s0, x, y) \ do { \ mp_limb_t __dt0, __dt1; \ umul_ppmm(__dt1, __dt0, (x), (y)); \ add_ssaaaa(r1, r0, s1, s0, __dt1, __dt0); \ } while (0); \ double flint_mpn_get_d(mp_srcptr ptr, mp_size_t size, mp_size_t sign, long exp); /* General multiplication ****************************************************/ #ifdef FLINT_HAVE_FFT_SMALL # define FLINT_FFT_MUL_THRESHOLD FLINT_FFT_SMALL_THRESHOLD # define FLINT_FFT_SQR_THRESHOLD (2 * FLINT_FFT_SMALL_THRESHOLD) #else /* FLINT's FFT can beat GMP below this threshold but apparently not consistently. Something needs retuning? */ # define FLINT_FFT_MUL_THRESHOLD 32000 # define FLINT_FFT_SQR_THRESHOLD 32000 #endif #if FLINT_HAVE_ADX # define FLINT_MPN_MUL_FUNC_TAB_WIDTH 17 # define FLINT_MPN_SQR_FUNC_TAB_WIDTH 14 # define FLINT_HAVE_MUL_FUNC(n, m) ((n) <= 16) # define FLINT_HAVE_MUL_N_FUNC(n) ((n) <= 16) # define FLINT_HAVE_SQR_FUNC(n) ((n) <= FLINT_MPN_SQR_FUNC_TAB_WIDTH) #else # define FLINT_MPN_MUL_FUNC_TAB_WIDTH 8 # define FLINT_HAVE_MUL_FUNC(n, m) ((n) <= 7 || ((n) <= 14 && (m) == 1)) # define FLINT_HAVE_MUL_N_FUNC(n) ((n) <= 7) # define FLINT_HAVE_SQR_FUNC(n) (0) #endif #define FLINT_MUL_USE_FUNC_TAB 1 typedef mp_limb_t (* flint_mpn_mul_func_t)(mp_ptr, mp_srcptr, mp_srcptr); typedef mp_limb_t (* flint_mpn_sqr_func_t)(mp_ptr, mp_srcptr); FLINT_DLL extern const flint_mpn_mul_func_t flint_mpn_mul_func_tab[][FLINT_MPN_MUL_FUNC_TAB_WIDTH]; FLINT_DLL extern const flint_mpn_mul_func_t flint_mpn_mul_n_func_tab[]; FLINT_DLL extern const flint_mpn_sqr_func_t flint_mpn_sqr_func_tab[]; mp_limb_t flint_mpn_mul_basecase(mp_ptr r, mp_srcptr x, mp_srcptr y, mp_size_t xn, mp_size_t yn); mp_limb_t flint_mpn_sqr_basecase(mp_ptr r, mp_srcptr x, mp_size_t n); void flint_mpn_mul_toom22(mp_ptr pp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn, mp_ptr scratch); mp_limb_t _flint_mpn_mul(mp_ptr r, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn); void _flint_mpn_mul_n(mp_ptr r, mp_srcptr x, mp_srcptr y, mp_size_t n); mp_limb_t _flint_mpn_sqr(mp_ptr r, mp_srcptr x, mp_size_t n); MPN_EXTRAS_INLINE mp_limb_t flint_mpn_mul(mp_ptr r, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn) { FLINT_ASSERT(xn >= yn); FLINT_ASSERT(yn >= 1); FLINT_ASSERT(r != x); FLINT_ASSERT(r != y); if (FLINT_MUL_USE_FUNC_TAB && FLINT_HAVE_MUL_FUNC(xn, yn)) return flint_mpn_mul_func_tab[xn][yn](r, x, y); else return _flint_mpn_mul(r, x, xn, y, yn); } MPN_EXTRAS_INLINE void flint_mpn_mul_n(mp_ptr r, mp_srcptr x, mp_srcptr y, mp_size_t n) { FLINT_ASSERT(n >= 1); FLINT_ASSERT(r != x); FLINT_ASSERT(r != y); if (FLINT_MUL_USE_FUNC_TAB && FLINT_HAVE_MUL_N_FUNC(n)) flint_mpn_mul_n_func_tab[n](r, x, y); else _flint_mpn_mul_n(r, x, y, n); } MPN_EXTRAS_INLINE mp_limb_t flint_mpn_sqr(mp_ptr r, mp_srcptr x, mp_size_t n) { FLINT_ASSERT(n >= 1); if (FLINT_MUL_USE_FUNC_TAB && FLINT_HAVE_SQR_FUNC(n)) { /* NOTE: Aliasing allowed */ return flint_mpn_sqr_func_tab[n](r, x); } else { FLINT_ASSERT(r != x); return _flint_mpn_sqr(r, x, n); } } /* Like flint_mpn_mul but allow operands in either order, completely inline some small products, and also check for squaring. */ #define FLINT_MPN_MUL_WITH_SPECIAL_CASES(_z, _x, _xn, _y, _yn) \ if ((_xn) == (_yn)) \ { \ if ((_xn) == 1) \ { \ umul_ppmm((_z)[1], (_z)[0], (_x)[0], (_y)[0]); \ } \ else if ((_xn) == 2) \ { \ mp_limb_t __tt_x1, __tt_x0, __tt_y1, __tt_y0; \ __tt_x0 = (_x)[0]; \ __tt_x1 = (_x)[1]; \ __tt_y0 = (_y)[0]; \ __tt_y1 = (_y)[1]; \ FLINT_MPN_MUL_2X2((_z)[3], (_z)[2], (_z)[1], (_z)[0], __tt_x1, __tt_x0, __tt_y1, __tt_y0); \ } \ else if ((_x) == (_y)) \ flint_mpn_sqr((_z), (_x), (_xn)); \ else \ flint_mpn_mul_n((_z), (_x), (_y), (_xn)); \ } \ else if ((_xn) > (_yn)) \ { \ flint_mpn_mul((_z), (_x), (_xn), (_y), (_yn)); \ } \ else \ { \ flint_mpn_mul((_z), (_y), (_yn), (_x), (_xn)); \ } /* High multiplication *******************************************************/ #define FLINT_HAVE_MULHIGH_FUNC(n) ((n) <= FLINT_MPN_MULHIGH_FUNC_TAB_WIDTH) #define FLINT_HAVE_SQRHIGH_FUNC(n) ((n) <= FLINT_MPN_SQRHIGH_FUNC_TAB_WIDTH) #define FLINT_HAVE_MULHIGH_NORMALISED_FUNC(n) ((n) <= FLINT_MPN_MULHIGH_NORMALISED_FUNC_TAB_WIDTH) struct mp_limb_pair_t { mp_limb_t m1; mp_limb_t m2; }; typedef struct mp_limb_pair_t (* flint_mpn_mulhigh_normalised_func_t)(mp_ptr, mp_srcptr, mp_srcptr); FLINT_DLL extern const flint_mpn_mul_func_t flint_mpn_mulhigh_func_tab[]; FLINT_DLL extern const flint_mpn_sqr_func_t flint_mpn_sqrhigh_func_tab[]; FLINT_DLL extern const flint_mpn_mulhigh_normalised_func_t flint_mpn_mulhigh_normalised_func_tab[]; #if FLINT_HAVE_ADX # define FLINT_MPN_MULHIGH_FUNC_TAB_WIDTH 12 # define FLINT_MPN_SQRHIGH_FUNC_TAB_WIDTH 8 # define FLINT_MPN_MULHIGH_NORMALISED_FUNC_TAB_WIDTH 12 # define FLINT_HAVE_NATIVE_MPN_MULHIGH_BASECASE 1 # define FLINT_HAVE_NATIVE_MPN_SQRHIGH_BASECASE 1 /* NOTE: This function only works for n >= 6 */ mp_limb_t _flint_mpn_mulhigh_basecase(mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); /* NOTE: These two functions only works for n >= 8 */ mp_limb_t _flint_mpn_sqrhigh_basecase_even(mp_ptr, mp_srcptr, mp_size_t); mp_limb_t _flint_mpn_sqrhigh_basecase_odd(mp_ptr, mp_srcptr, mp_size_t); /* TODO: Proceed with higher cases */ MPN_EXTRAS_INLINE mp_limb_t flint_mpn_mulhigh_basecase(mp_ptr rp, mp_srcptr xp, mp_srcptr yp, mp_size_t n) { FLINT_ASSERT(n >= 1); if (FLINT_HAVE_MULHIGH_FUNC(n)) /* NOTE: Aliasing allowed here */ return flint_mpn_mulhigh_func_tab[n](rp, xp, yp); else { FLINT_ASSERT(rp != xp && rp != yp); return _flint_mpn_mulhigh_basecase(rp, xp, yp, n); } } /* TODO: Proceed with higher cases */ MPN_EXTRAS_INLINE mp_limb_t flint_mpn_sqrhigh_basecase(mp_ptr rp, mp_srcptr xp, mp_size_t n) { FLINT_ASSERT(n >= 1); if (FLINT_HAVE_SQRHIGH_FUNC(n)) /* NOTE: Aliasing allowed here */ return flint_mpn_sqrhigh_func_tab[n](rp, xp); else { FLINT_ASSERT(rp != xp); if (n & 1) return _flint_mpn_sqrhigh_basecase_odd(rp, xp, n >> 1); else return _flint_mpn_sqrhigh_basecase_even(rp, xp, n >> 1); } } MPN_EXTRAS_INLINE struct mp_limb_pair_t flint_mpn_mulhigh_normalised(mp_ptr rp, mp_srcptr xp, mp_srcptr yp, mp_size_t n) { FLINT_ASSERT(n >= 1); if (FLINT_HAVE_MULHIGH_NORMALISED_FUNC(n)) return flint_mpn_mulhigh_normalised_func_tab[n](rp, xp, yp); else { struct mp_limb_pair_t ret; FLINT_ASSERT(rp != xp && rp != yp); /* TODO */ /* ret.m1 = flint_mpn_mulhigh(rp, xp, yp, n); */ ret.m1 = flint_mpn_mulhigh_basecase(rp, xp, yp, n); if (rp[n - 1] >> (FLINT_BITS - 1)) { ret.m2 = 0; } else { ret.m2 = 1; mpn_lshift(rp, rp, n, 1); rp[0] |= (ret.m1 >> (FLINT_BITS - 1)); ret.m1 <<= 1; } return ret; } } #else # define FLINT_MPN_MULHIGH_FUNC_TAB_WIDTH 0 # define FLINT_MPN_SQRHIGH_FUNC_TAB_WIDTH 0 # define FLINT_MPN_MULHIGH_NORMALISED_FUNC_TAB_WIDTH 0 #endif /* return the high limb of a two limb left shift by n < GMP_LIMB_BITS bits. Note: if GMP_NAIL_BITS != 0, the rest of flint is already broken anyways. */ #define MPN_LEFT_SHIFT_HI(hi, lo, n) \ ((n) > 0 ? (((hi) << (n)) | ((lo) >> (GMP_LIMB_BITS - (n)))) \ : (hi)) #define MPN_RIGHT_SHIFT_LOW(hi, lo, n) \ ((n) > 0 ? (((lo) >> (n)) | ((hi) << (GMP_LIMB_BITS - (n)))) \ : (lo)) #ifdef FLINT_HAVE_MPN_MODEXACT_1_ODD # define mpn_modexact_1_odd __gmpn_modexact_1_odd mp_limb_t mpn_modexact_1_odd(mp_srcptr, mp_size_t, mp_limb_t); MPN_EXTRAS_INLINE int flint_mpn_divisible_1_odd(mp_srcptr x, mp_size_t xsize, mp_limb_t d) { return mpn_modexact_1_odd(x, xsize, d) == 0; } #else # include "gmpcompat.h" MPN_EXTRAS_INLINE int flint_mpn_divisible_1_odd(mp_srcptr x, mp_size_t xsize, mp_limb_t d) { __mpz_struct s; s._mp_size = xsize; s._mp_d = (mp_ptr) x; return flint_mpz_divisible_ui_p(&s, d); } #endif static inline void mpn_tdiv_q(mp_ptr qp, mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn) { mp_ptr _scratch; TMP_INIT; TMP_START; _scratch = (mp_ptr) TMP_ALLOC(dn * sizeof(mp_limb_t)); mpn_tdiv_qr(qp, _scratch, 0, np, nn, dp, dn); TMP_END; } MPN_EXTRAS_INLINE int flint_mpn_zero_p(mp_srcptr x, mp_size_t xsize) { slong i; for (i = 0; i < xsize; i++) { if (x[i]) return 0; } return 1; } MPN_EXTRAS_INLINE mp_size_t flint_mpn_divexact_1(mp_ptr x, mp_size_t xsize, mp_limb_t d) { mpn_divrem_1(x, 0, x, xsize, d); if (x[xsize - 1] == UWORD(0)) xsize -= 1; return xsize; } mp_limb_t flint_mpn_sumdiff_n(mp_ptr s, mp_ptr d, mp_srcptr x, mp_srcptr y, mp_size_t n); void flint_mpn_debug(mp_srcptr x, mp_size_t xsize); mp_size_t flint_mpn_remove_2exp(mp_ptr x, mp_size_t xsize, flint_bitcnt_t *bits); mp_size_t flint_mpn_remove_power_ascending(mp_ptr x, mp_size_t xsize, mp_ptr p, mp_size_t psize, ulong *exp); int flint_mpn_factor_trial(mp_srcptr x, mp_size_t xsize, slong start, slong stop); int flint_mpn_factor_trial_tree(slong * factors, mp_srcptr x, mp_size_t xsize, slong num_primes); mp_size_t flint_mpn_fmms1(mp_ptr y, mp_limb_t a1, mp_srcptr x1, mp_limb_t a2, mp_srcptr x2, mp_size_t n); int flint_mpn_divides(mp_ptr q, mp_srcptr array1, mp_size_t limbs1, mp_srcptr arrayg, mp_size_t limbsg, mp_ptr temp); mp_size_t flint_mpn_gcd_full2(mp_ptr arrayg, mp_srcptr array1, mp_size_t limbs1, mp_srcptr array2, mp_size_t limbs2, mp_ptr temp); mp_size_t flint_mpn_gcd_full(mp_ptr arrayg, mp_srcptr array1, mp_size_t limbs1, mp_srcptr array2, mp_size_t limbs2); mp_limb_t flint_mpn_preinv1(mp_limb_t d, mp_limb_t d2); mp_limb_t flint_mpn_divrem_preinv1(mp_ptr q, mp_ptr a, mp_size_t m, mp_srcptr b, mp_size_t n, mp_limb_t dinv); #define flint_mpn_divrem21_preinv(q, a_hi, a_lo, dinv) \ do { \ mp_limb_t __q2, __q3, __q4; \ umul_ppmm((q), __q2, (a_hi), (dinv)); \ umul_ppmm(__q3, __q4, (a_lo), (dinv)); \ add_ssaaaa((q), __q2, (q), __q2, 0, __q3); \ add_ssaaaa((q), __q2, (q), __q2, (a_hi), (a_lo)); \ } while (0) void flint_mpn_mulmod_preinv1(mp_ptr r, mp_srcptr a, mp_srcptr b, mp_size_t n, mp_srcptr d, mp_limb_t dinv, ulong norm); void flint_mpn_preinvn(mp_ptr dinv, mp_srcptr d, mp_size_t n); void flint_mpn_mod_preinvn(mp_ptr r, mp_srcptr a, mp_size_t m, mp_srcptr d, mp_size_t n, mp_srcptr dinv); mp_limb_t flint_mpn_divrem_preinvn(mp_ptr q, mp_ptr r, mp_srcptr a, mp_size_t m, mp_srcptr d, mp_size_t n, mp_srcptr dinv); void flint_mpn_mulmod_preinvn(mp_ptr r, mp_srcptr a, mp_srcptr b, mp_size_t n, mp_srcptr d, mp_srcptr dinv, ulong norm); int flint_mpn_mulmod_2expp1_basecase(mp_ptr xp, mp_srcptr yp, mp_srcptr zp, int c, flint_bitcnt_t b, mp_ptr tp); MPN_EXTRAS_INLINE void flint_mpn_rrandom(mp_limb_t *rp, gmp_randstate_t state, mp_size_t n) { __mpz_struct str; str._mp_d = rp; str._mp_alloc = n; str._mp_size =n; mpz_rrandomb(&str,state,FLINT_BITS*n); } MPN_EXTRAS_INLINE void flint_mpn_urandomb(mp_limb_t *rp, gmp_randstate_t state, flint_bitcnt_t n) { __mpz_struct str; str._mp_d = rp; str._mp_alloc = (n + FLINT_BITS - 1)/FLINT_BITS; str._mp_size = (n + FLINT_BITS - 1)/FLINT_BITS; mpz_rrandomb(&str,state,n); } /****************************************************************************** Divisions where the quotient is expected to be small. All function do: input: n > d > 0 output: q = n/d, r = n%d for various small sizes of n and d. Not in a function because compiler refuses to inline eudiv_qrrnndd. Each macro takes a prefix t for its local vars. ******************************************************************************/ #define eudiv_qrnd(q, r, n, d, t) \ do { \ mp_limb_t t##q, t##a = n, t##b = d; \ \ FLINT_ASSERT(t##a > t##b); \ FLINT_ASSERT(t##b > 0); \ \ t##a -= t##b; \ for (t##q = 1; t##q < 5; t##q++) \ { \ if (t##a < t##b) \ goto t##quotient_found; \ t##a -= t##b; \ } \ t##q += t##a / t##b; \ t##a = t##a % t##b; \ \ t##quotient_found: \ \ q = t##q; \ r = t##a; \ } while (0) #define eudiv_qqrnnd(q1, q0, r0, n1, n0, d0, t) \ do { \ mp_limb_t t##a1 = n1, t##a0 = n0, t##b0 = d0; \ mp_limb_t t##q1, t##q0, t##r0, t##u; \ \ FLINT_ASSERT(t##a1 > 0 || t##a0 > t##b0); \ \ udiv_qrnnd(t##q1, t##u, 0, t##a1, t##b0); \ udiv_qrnnd(t##q0, t##r0, t##u, t##a0, t##b0); \ \ q1 = t##q1; \ q0 = t##q0; \ r0 = t##r0; \ } while (0) /* d must be normalized, i.e. d1 != 0 */ #define eudiv_qrrnndd(q0, r1, r0, n1, n0, d1, d0, t) \ do { \ int t##i; \ mp_limb_t t##a1 = n1, t##a0 = n0, t##b1 = d1, t##b0 = d0; \ mp_limb_t t##r1, t##r0, t##u2, t##u1, t##u0, t##q, t##v1, t##v0; \ \ FLINT_ASSERT(t##a1 != 0); \ FLINT_ASSERT(t##b1 != 0); \ FLINT_ASSERT(t##b1 < t##a1 || (t##b1 == t##a1 && t##b0 < t##a0)); \ \ t##q = 1; \ \ sub_ddmmss(t##r1,t##r0, t##a1,t##a0, t##b1,t##b0); \ \ t##subtract: \ \ for (t##i = 2; t##i <= 4; t##i++) \ { \ sub_dddmmmsss(t##u2,t##u1,t##u0, 0,t##r1,t##r0, 0,t##b1,t##b0); \ if (t##u2 != 0) \ goto t##quotient_found; \ t##q += 1; \ t##r0 = t##u0; \ t##r1 = t##u1; \ } \ \ if (t##r1 != 0) \ { \ int t##ncnt, t##dcnt; \ mp_limb_t t##qq = 0; \ \ t##ncnt = flint_clz(t##r1); \ t##dcnt = flint_clz(t##b1); \ t##dcnt -= t##ncnt; \ if (t##dcnt <= 0) \ goto t##subtract; \ \ t##v1 = (t##b1 << t##dcnt) | (t##b0 >> (FLINT_BITS - t##dcnt)); \ t##v0 = t##b0 << t##dcnt; \ \ do { \ sub_dddmmmsss(t##u2,t##u1,t##u0, 0,t##r1,t##r0, 0,t##v1,t##v0); \ t##qq = 2*t##qq + 1 + t##u2; \ t##r1 = t##u2 ? t##r1 : t##u1; \ t##r0 = t##u2 ? t##r0 : t##u0; \ t##v0 = (t##v1 << (FLINT_BITS - 1)) | (t##v0 >> 1); \ t##v1 = t##v1 >> 1; \ t##dcnt--; \ } while (t##dcnt >= 0); \ \ t##q += t##qq; \ } \ \ t##quotient_found: \ \ FLINT_ASSERT(t##r1 < t##b1 || (t##r1 == t##b1 && t##r0 < t##b0)); \ \ q0 = t##q; \ r0 = t##r0; \ r1 = t##r1; \ } while (0) #ifdef __cplusplus } #endif #endif flint-3.1.3/src/mpn_extras/000077500000000000000000000000001461254215100156025ustar00rootroot00000000000000flint-3.1.3/src/mpn_extras/asm-defs.m4000066400000000000000000001547571461254215100175660ustar00rootroot00000000000000divert(-1) dnl dnl m4 macros for gmp assembly code, shared by all CPUs. dnl Copyright 1999-2006, 2011 Free Software Foundation, Inc. dnl This file is part of the GNU MP Library. dnl dnl The GNU MP Library is free software; you can redistribute it and/or modify dnl it under the terms of either: dnl dnl * the GNU Lesser General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your dnl option) any later version. dnl dnl or dnl dnl * the GNU General Public License as published by the Free Software dnl Foundation; either version 2 of the License, or (at your option) any dnl later version. dnl dnl or both in parallel, as here. dnl dnl The GNU MP Library is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dnl for more details. dnl dnl You should have received copies of the GNU General Public License and the dnl GNU Lesser General Public License along with the GNU MP Library. If not, dnl see https://www.gnu.org/licenses/. dnl These macros are designed for use with any m4 and have been used on dnl GNU, FreeBSD, NetBSD, OpenBSD and SysV. dnl dnl GNU m4 and OpenBSD 2.7 m4 will give filenames and line numbers in error dnl messages. dnl dnl dnl Macros: dnl dnl Most new m4 specific macros have an "m4_" prefix to emphasise they're dnl m4 expansions. But new defining things like deflit() and defreg() are dnl named like the builtin define(), and forloop() is named following the dnl GNU m4 example on which it's based. dnl dnl GNU m4 with the -P option uses "m4_" as a prefix for builtins, but that dnl option isn't going to be used, so there's no conflict or confusion. dnl dnl dnl Comments in output: dnl dnl The m4 comment delimiters are left at # and \n, the normal assembler dnl commenting for most CPUs. m4 passes comment text through without dnl expanding macros in it, which is generally a good thing since it stops dnl unexpected expansions and possible resultant errors. dnl dnl But note that when a quoted string is being read, a # isn't special, so dnl apostrophes in comments in quoted strings must be avoided or they'll be dnl interpreted as a closing quote mark. But when the quoted text is dnl re-read # will still act like a normal comment, suppressing macro dnl expansion. dnl dnl For example, dnl dnl # apostrophes in comments that're outside quotes are ok dnl # and using macro names like PROLOGUE is ok too dnl ... dnl ifdef(`PIC',` dnl # but apostrophes aren't ok inside quotes dnl # ^--wrong dnl ... dnl # though macro names like PROLOGUE are still ok dnl ... dnl ') dnl dnl If macro expansion in a comment is wanted, use `#' in the .asm (ie. a dnl quoted hash symbol), which will turn into # in the .s but get dnl expansions done on that line. This can make the .s more readable to dnl humans, but it won't make a blind bit of difference to the assembler. dnl dnl All the above applies, mutatis mutandis, when changecom() is used to dnl select @ ! ; or whatever other commenting. dnl dnl dnl Variations in m4 affecting gmp: dnl dnl $# - When a macro is called as "foo" with no brackets, BSD m4 sets $# dnl to 1, whereas GNU or SysV m4 set it to 0. In all cases though dnl "foo()" sets $# to 1. This is worked around in various places. dnl dnl len() - When "len()" is given an empty argument, BSD m4 evaluates to dnl nothing, whereas GNU, SysV, and the new OpenBSD, evaluate to 0. dnl See m4_length() below which works around this. dnl dnl translit() - GNU m4 accepts character ranges like A-Z, and the new dnl OpenBSD m4 does under option -g, but basic BSD and SysV don't. dnl dnl popdef() - in BSD and SysV m4 popdef() takes multiple arguments and dnl pops each, but GNU m4 only takes one argument. dnl dnl push back - BSD m4 has some limits on the amount of text that can be dnl pushed back. The limit is reasonably big and so long as macros dnl don't gratuitously duplicate big arguments it isn't a problem. dnl Normally an error message is given, but sometimes it just hangs. dnl dnl eval() &,|,^ - GNU and SysV m4 have bitwise operators &,|,^ available, dnl but BSD m4 doesn't (contrary to what the man page suggests) and dnl instead ^ is exponentiation. dnl dnl eval() ?: - The C ternary operator "?:" is available in BSD m4, but not dnl in SysV or GNU m4 (as of GNU m4 1.4 and betas of 1.5). dnl dnl eval() -2^31 - BSD m4 has a bug where an eval() resulting in -2^31 dnl (ie. -2147483648) gives "-(". Using -2147483648 within an dnl expression is ok, it just can't be a final result. "-(" will of dnl course upset parsing, with all sorts of strange effects. dnl dnl eval() <<,>> - SysV m4 doesn't support shift operators in eval() (on dnl Solaris 7 /usr/xpg4/m4 has them but /usr/ccs/m4 doesn't). See dnl m4_lshift() and m4_rshift() below for workarounds. dnl dnl ifdef() - OSF 4.0 m4 considers a macro defined to a zero value `0' or dnl `00' etc as not defined. See m4_ifdef below for a workaround. dnl dnl m4wrap() sequence - in BSD m4, m4wrap() replaces any previous m4wrap() dnl string, in SysV m4 it appends to it, and in GNU m4 it prepends. dnl See m4wrap_prepend() below which brings uniformity to this. dnl dnl m4wrap() 0xFF - old versions of BSD m4 store EOF in a C "char" under an dnl m4wrap() and on systems where char is unsigned by default a dnl spurious 0xFF is output. This has been observed on recent Cray dnl Unicos Alpha, Apple MacOS X, and HPUX 11 systems. An autoconf dnl test is used to check for this, see the m4wrap handling below. It dnl might work to end the m4wrap string with a dnl to consume the dnl 0xFF, but that probably induces the offending m4's to read from an dnl already closed "FILE *", which could be bad on a glibc style dnl stdio. dnl dnl __file__,__line__ - GNU m4 and OpenBSD 2.7 m4 provide these, and dnl they're used here to make error messages more informative. GNU m4 dnl gives an unhelpful "NONE 0" in an m4wrap(), but that's worked dnl around. dnl dnl __file__ quoting - OpenBSD m4, unlike GNU m4, doesn't quote the dnl filename in __file__, so care should be taken that no macro has dnl the same name as a file, or an unwanted expansion will occur when dnl printing an error or warning. dnl dnl changecom() - BSD m4 changecom doesn't quite work like the man page dnl suggests, in particular "changecom" or "changecom()" doesn't dnl disable the comment feature, and multi-character comment sequences dnl don't seem to work. If the default `#' and newline aren't dnl suitable it's necessary to change it to something else, dnl eg. changecom(;). dnl dnl OpenBSD 2.6 m4 - in this m4, eval() rejects decimal constants containing dnl an 8 or 9, making it pretty much unusable. The bug is confined to dnl version 2.6 (it's not in 2.5, and was fixed in 2.7). dnl dnl SunOS /usr/bin/m4 - this m4 lacks a number of desired features, dnl including $# and $@, defn(), m4exit(), m4wrap(), pushdef(), dnl popdef(). /usr/5bin/m4 is a SysV style m4 which should always be dnl available, and "configure" will reject /usr/bin/m4 in favour of dnl /usr/5bin/m4 (if necessary). dnl dnl The sparc code actually has modest m4 requirements currently and dnl could manage with /usr/bin/m4, but there's no reason to put our dnl macros through contortions when /usr/5bin/m4 is available or GNU dnl m4 can be installed. ifdef(`__ASM_DEFS_M4_INCLUDED__', `m4_error(`asm-defs.m4 already included, dont include it twice ')m4exit(1)') define(`__ASM_DEFS_M4_INCLUDED__') dnl Detect and give a message about the unsuitable OpenBSD 2.6 m4. ifelse(eval(89),89,, `errprint( `This m4 doesnt accept 8 and/or 9 in constants in eval(), making it unusable. This is probably OpenBSD 2.6 m4 (September 1999). Upgrade to OpenBSD 2.7, or get a bug fix from the CVS (expr.c rev 1.9), or get GNU m4. Dont forget to configure with M4=/wherever/m4 if you install one of these in a directory not in $PATH. ')m4exit(1)') dnl Detect and give a message about the unsuitable SunOS /usr/bin/m4. dnl dnl Unfortunately this test doesn't work when m4 is run in the normal way dnl from mpn/Makefile with "m4 -DOPERATION_foo foo.asm", since the bad m4 dnl takes "-" in "-D..." to mean read stdin, so it will look like it just dnl hangs. But running "m4 asm-defs.m4" to try it out will work. dnl dnl We'd like to abort immediately on finding a problem, but unfortunately dnl the bad m4 doesn't have an m4exit(), nor does an invalid eval() kill dnl it. Unexpanded $#'s in some m4_assert_numargs() later on will comment dnl out some closing parentheses and kill it with "m4: arg stack overflow". define(m4_dollarhash_works_test,``$#'') ifelse(m4_dollarhash_works_test(x),1,, `errprint( `This m4 doesnt support $# and cant be used for GMP asm processing. If this is on SunOS, ./configure should choose /usr/5bin/m4 if you have that or can get it, otherwise install GNU m4. Dont forget to configure with M4=/wherever/m4 if you install in a directory not in $PATH. ')') undefine(`m4_dollarhash_works_test') dnl -------------------------------------------------------------------------- dnl Basic error handling things. dnl Usage: m4_dollarhash_1_if_noparen_p dnl dnl Expand to 1 if a call "foo" gives $# set to 1 (as opposed to 0 like GNU dnl and SysV m4 give). define(m4_dollarhash_1_if_noparen_test,`$#') define(m4_dollarhash_1_if_noparen_p, eval(m4_dollarhash_1_if_noparen_test==1)) undefine(`m4_dollarhash_1_if_noparen_test') dnl Usage: m4wrap_prepend(string) dnl dnl Prepend the given string to what will be expanded under m4wrap at the dnl end of input. dnl dnl This macro exists to work around variations in m4wrap() behaviour in dnl the various m4s (notes at the start of this file). Don't use m4wrap() dnl directly since it will interfere with this scheme. define(m4wrap_prepend, m4_assert_numargs(1) `define(`m4wrap_string',`$1'defn(`m4wrap_string'))') define(m4wrap_string,`') define(m4wrap_works_p, `ifelse(M4WRAP_SPURIOUS,yes,0,1)') ifelse(m4wrap_works_p,1, `m4wrap(`m4wrap_string')') dnl Usage: m4_file_and_line dnl dnl Expand to the current file and line number, if the GNU m4 extensions dnl __file__ and __line__ are available. dnl dnl In GNU m4 1.4 at the end of input when m4wrap text is expanded, dnl __file__ is NONE and __line__ is 0, which is not a helpful thing to dnl print. If m4_file_seen() has been called to note the last file seen, dnl then that file at a big line number is used, otherwise "end of input" dnl is used (although "end of input" won't parse as an error message). define(m4_file_and_line, `ifdef(`__file__', `ifelse(__file__`'__line__,`NONE0', `ifdef(`m4_file_seen_last',`m4_file_seen_last: 999999: ',`end of input: ')', `__file__: __line__: ')')') dnl Usage: m4_errprint_commas(arg,...) dnl dnl The same as errprint(), but commas are printed between arguments dnl instead of spaces. define(m4_errprint_commas, `errprint(`$1')dnl ifelse(eval($#>1),1,`errprint(`,')m4_errprint_commas(shift($@))')') dnl Usage: m4_error(args...) dnl m4_warning(args...) dnl dnl Print an error message, using m4_errprint_commas, prefixed with the dnl current filename and line number (if available). m4_error sets up to dnl give an error exit at the end of processing, m4_warning just prints. dnl These macros are the recommended way to print errors. dnl dnl The arguments here should be quoted in the usual way to prevent them dnl being expanded when the macro call is read. (m4_error takes care not dnl to do any further expansion.) dnl dnl For example, dnl dnl m4_error(`some error message dnl ') dnl dnl which prints dnl dnl foo.asm:123: some error message dnl dnl or if __file__ and __line__ aren't available dnl dnl some error message dnl dnl The "file:line:" format is a basic style, used by gcc and GNU m4, so dnl emacs and other editors will recognise it in their normal error message dnl parsing. define(m4_warning, `m4_errprint_commas(m4_file_and_line`'$@ )') define(m4_error, `define(`m4_error_occurred',1)m4_warning($@)dnl ifelse(m4wrap_works_p,0,`m4exit(1)')') define(`m4_error_occurred',0) dnl This m4wrap_prepend() is first, so it'll be executed last. m4wrap_prepend( `ifelse(m4_error_occurred,1, `m4_error(`Errors occurred during m4 processing ')m4exit(1)')') dnl Usage: m4_assert_numargs(num) dnl dnl Put this unquoted on a line on its own at the start of a macro dnl definition to add some code to check that num many arguments get passed dnl to the macro. For example, dnl dnl define(foo, dnl m4_assert_numargs(2) dnl `something `$1' and `$2' blah blah') dnl dnl Then a call like foo(one,two,three) will provoke an error like dnl dnl file:10: foo expected 2 arguments, got 3 arguments dnl dnl Here are some calls and how many arguments they're interpreted as passing. dnl dnl foo(abc,def) 2 dnl foo(xyz) 1 dnl foo() 0 dnl foo -1 dnl dnl The -1 for no parentheses at all means a macro that's meant to be used dnl that way can be checked with m4_assert_numargs(-1). For example, dnl dnl define(SPECIAL_SUFFIX, dnl m4_assert_numargs(-1) dnl `ifdef(`FOO',`_foo',`_bar')') dnl dnl But as an alternative see also deflit() below where parenthesized dnl expressions following a macro are passed through to the output. dnl dnl Note that in BSD m4 there's no way to differentiate calls "foo" and dnl "foo()", so in BSD m4 the distinction between the two isn't enforced. dnl (In GNU and SysV m4 it can be checked, and is.) dnl m4_assert_numargs is able to check its own arguments by calling dnl assert_numargs_internal directly. dnl dnl m4_doublequote($`'0) expands to ``$0'', whereas ``$`'0'' would expand dnl to `$`'0' and do the wrong thing, and likewise for $1. The same is dnl done in other assert macros. dnl dnl $`#' leaves $# in the new macro being defined, and stops # being dnl interpreted as a comment character. dnl dnl `dnl ' means an explicit dnl isn't necessary when m4_assert_numargs is dnl used. The space means that if there is a dnl it'll still work. dnl Usage: m4_doublequote(x) expands to ``x'' define(m4_doublequote, `m4_assert_numargs_internal(`$0',1,$#,len(`$1'))``$1''') define(m4_assert_numargs, `m4_assert_numargs_internal(`$0',1,$#,len(`$1'))dnl `m4_assert_numargs_internal'(m4_doublequote($`'0),$1,$`#',`len'(m4_doublequote($`'1)))`dnl '') dnl Called: m4_assert_numargs_internal(`macroname',wantargs,$#,len(`$1')) define(m4_assert_numargs_internal, `m4_assert_numargs_internal_check(`$1',`$2',m4_numargs_count(`$3',`$4'))') dnl Called: m4_assert_numargs_internal_check(`macroname',wantargs,gotargs) dnl dnl If m4_dollarhash_1_if_noparen_p (BSD m4) then gotargs can be 0 when it dnl should be -1. If wantargs is -1 but gotargs is 0 and the two can't be dnl distinguished then it's allowed to pass. dnl define(m4_assert_numargs_internal_check, `ifelse(eval($2 == $3 || ($2==-1 && $3==0 && m4_dollarhash_1_if_noparen_p)),0, `m4_error(`$1 expected 'm4_Narguments(`$2')`, got 'm4_Narguments(`$3') )')') dnl Called: m4_numargs_count($#,len(`$1')) dnl If $#==0 then -1 args, if $#==1 but len(`$1')==0 then 0 args, otherwise dnl $# args. define(m4_numargs_count, `ifelse($1,0, -1, `ifelse(eval($1==1 && $2-0==0),1, 0, $1)')') dnl Usage: m4_Narguments(N) dnl "$1 argument" or "$1 arguments" with the plural according to $1. define(m4_Narguments, `$1 argument`'ifelse(`$1',1,,s)') dnl -------------------------------------------------------------------------- dnl Additional error checking things. dnl Usage: m4_file_seen() dnl dnl Record __file__ for the benefit of m4_file_and_line in m4wrap text. dnl dnl The basic __file__ macro comes out quoted in GNU m4, like `foo.asm', dnl and m4_file_seen_last is defined like that too. dnl dnl This is used by PROLOGUE, since that's normally in the main .asm file, dnl and in particular it sets up m4wrap error checks for missing EPILOGUE. define(m4_file_seen, m4_assert_numargs(0) `ifelse(__file__,`NONE',, `define(`m4_file_seen_last',m4_doublequote(__file__))')') dnl Usage: m4_assert_onearg() dnl dnl Put this, unquoted, at the start of a macro definition to add some code dnl to check that one argument is passed to the macro, but with that dnl argument allowed to be empty. For example, dnl dnl define(foo, dnl m4_assert_onearg() dnl `blah blah $1 blah blah') dnl dnl Calls "foo(xyz)" or "foo()" are accepted. A call "foo(xyz,abc)" fails. dnl A call "foo" fails too, but BSD m4 can't detect this case (GNU and SysV dnl m4 can). define(m4_assert_onearg, m4_assert_numargs(0) `m4_assert_onearg_internal'(m4_doublequote($`'0),$`#')`dnl ') dnl Called: m4_assert_onearg(`macroname',$#) define(m4_assert_onearg_internal, `ifelse($2,1,, `m4_error(`$1 expected 1 argument, got 'm4_Narguments(`$2') )')') dnl Usage: m4_assert_numargs_range(low,high) dnl dnl Put this, unquoted, at the start of a macro definition to add some code dnl to check that between low and high many arguments get passed to the dnl macro. For example, dnl dnl define(foo, dnl m4_assert_numargs_range(3,5) dnl `mandatory $1 $2 $3 optional $4 $5 end') dnl dnl See m4_assert_numargs() for more info. define(m4_assert_numargs_range, m4_assert_numargs(2) ``m4_assert_numargs_range_internal'(m4_doublequote($`'0),$1,$2,$`#',`len'(m4_doublequote($`'1)))`dnl '') dnl Called: m4_assert_numargs_range_internal(`name',low,high,$#,len(`$1')) define(m4_assert_numargs_range_internal, m4_assert_numargs(5) `m4_assert_numargs_range_check(`$1',`$2',`$3',m4_numargs_count(`$4',`$5'))') dnl Called: m4_assert_numargs_range_check(`name',low,high,gotargs) dnl dnl If m4_dollarhash_1_if_noparen_p (BSD m4) then gotargs can be 0 when it dnl should be -1. To ensure a `high' of -1 works, a fudge is applied to dnl gotargs if it's 0 and the 0 and -1 cases can't be distinguished. dnl define(m4_assert_numargs_range_check, m4_assert_numargs(4) `ifelse(eval($2 <= $4 && ($4 - ($4==0 && m4_dollarhash_1_if_noparen_p) <= $3)),0, `m4_error(`$1 expected $2 to $3 arguments, got 'm4_Narguments(`$4') )')') dnl Usage: m4_assert_defined(symbol) dnl dnl Put this unquoted on a line of its own at the start of a macro dnl definition to add some code to check that the given symbol is defined dnl when the macro is used. For example, dnl dnl define(foo, dnl m4_assert_defined(`FOO_PREFIX') dnl `FOO_PREFIX whatever') dnl dnl This is a convenient way to check that the user or ./configure or dnl whatever has defined the things needed by a macro, as opposed to dnl silently generating garbage. define(m4_assert_defined, m4_assert_numargs(1) ``m4_assert_defined_internal'(m4_doublequote($`'0),``$1'')`dnl '') dnl Called: m4_assert_defined_internal(`macroname',`define_required') define(m4_assert_defined_internal, m4_assert_numargs(2) `m4_ifdef(`$2',, `m4_error(`$1 needs $2 defined ')')') dnl Usage: m4_not_for_expansion(`SYMBOL') dnl define_not_for_expansion(`SYMBOL') dnl dnl m4_not_for_expansion turns SYMBOL, if defined, into something which dnl will give an error if expanded. For example, dnl dnl m4_not_for_expansion(`PIC') dnl dnl define_not_for_expansion is the same, but always makes a definition. dnl dnl These are for symbols that should be tested with ifdef(`FOO',...) dnl rather than be expanded as such. They guard against accidentally dnl omitting the quotes, as in ifdef(FOO,...). Note though that they only dnl catches this when FOO is defined, so be sure to test code both with and dnl without each definition. define(m4_not_for_expansion, m4_assert_numargs(1) `ifdef(`$1',`define_not_for_expansion(`$1')')') define(define_not_for_expansion, m4_assert_numargs(1) `ifelse(defn(`$1'),,, `m4_error(``$1' has a non-empty value, maybe it shouldnt be munged with m4_not_for_expansion() ')')dnl define(`$1',`m4_not_for_expansion_internal(`$1')')') define(m4_not_for_expansion_internal, `m4_error(``$1' is not meant to be expanded, perhaps you mean `ifdef(`$1',...)' ')') dnl -------------------------------------------------------------------------- dnl Various generic m4 things. dnl Usage: m4_unquote(macro) dnl dnl Allow the argument text to be re-evaluated. This is useful for "token dnl pasting" like m4_unquote(foo`'bar). define(m4_unquote, m4_assert_onearg() `$1') dnl Usage: m4_ifdef(name,yes[,no]) dnl dnl Expand to the yes argument if name is defined, or to the no argument if dnl not. dnl dnl This is the same as the builtin "ifdef", but avoids an OSF 4.0 m4 bug dnl in which a macro with a zero value `0' or `00' etc is considered not dnl defined. dnl dnl There's no particular need to use this everywhere, only if there might dnl be a zero value. define(m4_ifdef, m4_assert_numargs_range(2,3) `ifelse(eval(ifdef(`$1',1,0)+m4_length(defn(`$1'))),0, `$3',`$2')') dnl Usage: m4_ifdef_anyof_p(`symbol',...) dnl dnl Expand to 1 if any of the symbols in the argument list are defined, or dnl to 0 if not. define(m4_ifdef_anyof_p, `ifelse(eval($#<=1 && m4_length(`$1')==0),1, 0, `ifdef(`$1', 1, `m4_ifdef_anyof_p(shift($@))')')') dnl Usage: m4_length(string) dnl dnl Determine the length of a string. This is the same as len(), but dnl always expands to a number, working around the BSD len() which dnl evaluates to nothing given an empty argument. define(m4_length, m4_assert_onearg() `eval(len(`$1')-0)') dnl Usage: m4_stringequal_p(x,y) dnl dnl Expand to 1 or 0 according as strings x and y are equal or not. define(m4_stringequal_p, `ifelse(`$1',`$2',1,0)') dnl Usage: m4_incr_or_decr(n,last) dnl dnl Do an incr(n) or decr(n), whichever is in the direction of "last". dnl Both n and last must be numbers of course. define(m4_incr_or_decr, m4_assert_numargs(2) `ifelse(eval($1<$2),1,incr($1),decr($1))') dnl Usage: forloop(i, first, last, statement) dnl dnl Based on GNU m4 examples/forloop.m4, but extended. dnl dnl statement is expanded repeatedly, with i successively defined as dnl dnl first, first+1, ..., last-1, last dnl dnl Or if first > last, then it's dnl dnl first, first-1, ..., last+1, last dnl dnl If first == last, then one expansion is done. dnl dnl A pushdef/popdef of i is done to preserve any previous definition (or dnl lack of definition). first and last are eval()ed and so can be dnl expressions. dnl dnl forloop_first is defined to 1 on the first iteration, 0 on the rest. dnl forloop_last is defined to 1 on the last iteration, 0 on the others. dnl Nested forloops are allowed, in which case forloop_first and dnl forloop_last apply to the innermost loop that's open. dnl dnl A simple example, dnl dnl forloop(i, 1, 2*2+1, `dnl dnl iteration number i ... ifelse(forloop_first,1,FIRST) dnl ') dnl "i" and "statement" are carefully quoted, but "first" and "last" are dnl just plain numbers once eval()ed. define(`forloop', m4_assert_numargs(4) `pushdef(`$1',eval(`$2'))dnl pushdef(`forloop_first',1)dnl pushdef(`forloop_last',0)dnl forloop_internal(`$1',eval(`$3'),`$4')`'dnl popdef(`forloop_first')dnl popdef(`forloop_last')dnl popdef(`$1')') dnl Called: forloop_internal(`var',last,statement) define(`forloop_internal', m4_assert_numargs(3) `ifelse($1,$2, `define(`forloop_last',1)$3', `$3`'dnl define(`forloop_first',0)dnl define(`$1',m4_incr_or_decr($1,$2))dnl forloop_internal(`$1',$2,`$3')')') dnl Usage: foreach(var,body, item1,item2,...,itemN) dnl dnl For each "item" argument, define "var" to that value and expand "body". dnl For example, dnl dnl foreach(i, `something i dnl ', one, two) dnl gives dnl something one dnl something two dnl dnl Any previous definition of "var", or lack thereof, is saved and dnl restored. Empty "item"s are not allowed. define(foreach, m4_assert_numargs_range(2,1000) `ifelse(`$3',,, `pushdef(`$1',`$3')$2`'popdef(`$1')dnl foreach(`$1',`$2',shift(shift(shift($@))))')') dnl Usage: m4_toupper(x) dnl m4_tolower(x) dnl dnl Convert the argument string to upper or lower case, respectively. dnl Only one argument accepted. dnl dnl BSD m4 doesn't take ranges like a-z in translit(), so the full alphabet dnl is written out. define(m4_alphabet_lower, `abcdefghijklmnopqrstuvwxyz') define(m4_alphabet_upper, `ABCDEFGHIJKLMNOPQRSTUVWXYZ') define(m4_toupper, m4_assert_onearg() `translit(`$1', m4_alphabet_lower, m4_alphabet_upper)') define(m4_tolower, m4_assert_onearg() `translit(`$1', m4_alphabet_upper, m4_alphabet_lower)') dnl Usage: m4_empty_if_zero(x) dnl dnl Evaluate to x, or to nothing if x is 0. x is eval()ed and so can be an dnl expression. dnl dnl This is useful for x86 addressing mode displacements since forms like dnl (%ebx) are one byte shorter than 0(%ebx). A macro `foo' for use as dnl foo(%ebx) could be defined with the following so it'll be empty if the dnl expression comes out zero. dnl dnl deflit(`foo', `m4_empty_if_zero(a+b*4-c)') dnl dnl Naturally this shouldn't be done if, say, a computed jump depends on dnl the code being a particular size. define(m4_empty_if_zero, m4_assert_onearg() `ifelse(eval($1),0,,eval($1))') dnl Usage: m4_log2(x) dnl dnl Calculate a logarithm to base 2. dnl x must be an integral power of 2, between 2**0 and 2**30. dnl x is eval()ed, so it can be an expression. dnl An error results if x is invalid. dnl dnl 2**31 isn't supported, because an unsigned 2147483648 is out of range dnl of a 32-bit signed int. Also, the bug in BSD m4 where an eval() dnl resulting in 2147483648 (or -2147483648 as the case may be) gives `-(' dnl means tests like eval(1<<31==(x)) would be necessary, but that then dnl gives an unattractive explosion of eval() error messages if x isn't dnl numeric. define(m4_log2, m4_assert_numargs(1) `m4_log2_internal(0,1,eval(`$1'))') dnl Called: m4_log2_internal(n,2**n,target) define(m4_log2_internal, m4_assert_numargs(3) `ifelse($2,$3,$1, `ifelse($1,30, `m4_error(`m4_log2() argument too big or not a power of two: $3 ')', `m4_log2_internal(incr($1),eval(2*$2),$3)')')') dnl Usage: m4_div2_towards_zero dnl dnl m4 division is probably whatever a C signed division is, and C doesn't dnl specify what rounding gets used on negatives, so this expression forces dnl a rounding towards zero. define(m4_div2_towards_zero, m4_assert_numargs(1) `eval((($1) + ((($1)<0) & ($1))) / 2)') dnl Usage: m4_lshift(n,count) dnl m4_rshift(n,count) dnl dnl Calculate n shifted left or right by count many bits. Both n and count dnl are eval()ed and so can be expressions. dnl dnl Negative counts are allowed and mean a shift in the opposite direction. dnl Negative n is allowed and right shifts will be arithmetic (meaning dnl divide by 2**count, rounding towards zero, also meaning the sign bit is dnl duplicated). dnl dnl Use these macros instead of << and >> in eval() since the basic ccs dnl SysV m4 doesn't have those operators. define(m4_rshift, m4_assert_numargs(2) `m4_lshift(`$1',-(`$2'))') define(m4_lshift, m4_assert_numargs(2) `m4_lshift_internal(eval(`$1'),eval(`$2'))') define(m4_lshift_internal, m4_assert_numargs(2) `ifelse(eval($2-0==0),1,$1, `ifelse(eval($2>0),1, `m4_lshift_internal(eval($1*2),decr($2))', `m4_lshift_internal(m4_div2_towards_zero($1),incr($2))')')') dnl Usage: m4_popcount(n) dnl dnl Expand to the number 1 bits in n. define(m4_popcount, m4_assert_numargs(1) `m4_popcount_internal(0,eval(`$1'))') dnl Called: m4_popcount_internal(count,rem) define(m4_popcount_internal, m4_assert_numargs(2) `ifelse($2,0,$1, `m4_popcount_internal(eval($1+($2%2)),eval($2/2))')') dnl Usage: m4_count_trailing_zeros(N) dnl dnl Determine the number of trailing zero bits on N. N is eval()ed and so dnl can be an expression. If N is zero an error is generated. define(m4_count_trailing_zeros, m4_assert_numargs(1) `m4_count_trailing_zeros_internal(eval(`$1'),0)') dnl Called: m4_count_trailing_zeros_internal(val,count) define(m4_count_trailing_zeros_internal, m4_assert_numargs(2) `ifelse($1,0, `m4_error(`m4_count_trailing_zeros() given a zero value')', `ifelse(eval(($1)%2),1,`$2', `m4_count_trailing_zeros_internal(eval($1/2),incr($2))')')') dnl Usage: deflit(name,value) dnl dnl Like define(), but "name" expands like a literal, rather than taking dnl arguments. For example "name(%eax)" expands to "value(%eax)". dnl dnl Limitations: dnl dnl $ characters in the value part must have quotes to stop them looking dnl like macro parameters. For example, deflit(reg,`123+$`'4+567'). See dnl defreg() below for handling simple register definitions like $7 etc. dnl dnl "name()" is turned into "name", unfortunately. In GNU and SysV m4 an dnl error is generated when this happens, but in BSD m4 it will happen dnl silently. The problem is that in BSD m4 $# is 1 in both "name" or dnl "name()", so there's no way to differentiate them. Because we want dnl plain "name" to turn into plain "value", we end up with "name()" dnl turning into plain "value" too. dnl dnl "name(foo)" will lose any whitespace after commas in "foo", for example dnl "disp(%eax, %ecx)" would become "128(%eax,%ecx)". dnl dnl These parentheses oddities shouldn't matter in assembler text, but if dnl they do the suggested workaround is to write "name ()" or "name (foo)" dnl to stop the parentheses looking like a macro argument list. If a space dnl isn't acceptable in the output, then write "name`'()" or "name`'(foo)". dnl The `' is stripped when read, but again stops the parentheses looking dnl like parameters. dnl Quoting for deflit_emptyargcheck is similar to m4_assert_numargs. The dnl stuff in the ifelse gives a $#, $1 and $@ evaluated in the new macro dnl created, not in deflit. define(deflit, m4_assert_numargs(2) `define(`$1', `deflit_emptyargcheck'(``$1'',$`#',m4_doublequote($`'1))`dnl $2`'dnl ifelse(eval($'`#>1 || m4_length('m4_doublequote($`'1)`)!=0),1,($'`@))')') dnl Called: deflit_emptyargcheck(macroname,$#,`$1') define(deflit_emptyargcheck, `ifelse(eval($2==1 && !m4_dollarhash_1_if_noparen_p && m4_length(`$3')==0),1, `m4_error(`dont use a deflit as $1() because it loses the brackets (see deflit in asm-defs.m4 for more information) ')')') dnl Usage: m4_assert(`expr') dnl dnl Test a compile-time requirement with an m4 expression. The expression dnl should be quoted, and will be eval()ed and expected to be non-zero. dnl For example, dnl dnl m4_assert(`FOO*2+6 < 14') define(m4_assert, m4_assert_numargs(1) `ifelse(eval($1),1,, `m4_error(`assertion failed: $1 ')')') dnl Usage: m4_repeat(count,text) dnl dnl Expand to the given repetitions of the given text. A zero count is dnl allowed, and expands to nothing. define(m4_repeat, m4_assert_numargs(2) `m4_repeat_internal(eval($1),`$2')') define(m4_repeat_internal, m4_assert_numargs(2) `ifelse(`$1',0,, `forloop(m4_repeat_internal_counter,1,$1,``$2'')')') dnl Usage: m4_hex_lowmask(bits) dnl dnl Generate a hex constant which is a low mask of the given number of dnl bits. For example m4_hex_lowmask(10) would give 0x3ff. define(m4_hex_lowmask, m4_assert_numargs(1) `m4_cpu_hex_constant(m4_hex_lowmask_internal1(eval(`$1')))') dnl Called: m4_hex_lowmask_internal1(bits) define(m4_hex_lowmask_internal1, m4_assert_numargs(1) `ifelse($1,0,`0', `m4_hex_lowmask_internal2(eval(($1)%4),eval(($1)/4))')') dnl Called: m4_hex_lowmask_internal(remainder,digits) define(m4_hex_lowmask_internal2, m4_assert_numargs(2) `ifelse($1,1,`1', `ifelse($1,2,`3', `ifelse($1,3,`7')')')dnl m4_repeat($2,`f')') dnl -------------------------------------------------------------------------- dnl The following m4_list functions take a list as multiple arguments. dnl Arguments are evaluated multiple times, there's no attempt at strict dnl quoting. Empty list elements are not allowed, since an empty final dnl argument is ignored. These restrictions don't affect the current uses, dnl and make the implementation easier. dnl Usage: m4_list_quote(list,...) dnl dnl Produce a list with quoted commas, so it can be a single argument dnl string. For instance m4_list_quote(a,b,c) gives dnl dnl a`,'b`,'c`,' dnl dnl This can be used to put a list in a define, dnl dnl define(foolist, m4_list_quote(a,b,c)) dnl dnl Which can then be used for instance as dnl dnl m4_list_find(target, foolist) define(m4_list_quote, `ifelse(`$1',,, `$1`,'m4_list_quote(shift($@))')') dnl Usage: m4_list_find(key,list,...) dnl dnl Evaluate to 1 or 0 according to whether key is in the list elements. define(m4_list_find, m4_assert_numargs_range(1,1000) `ifelse(`$2',,0, `ifelse(`$1',`$2',1, `m4_list_find(`$1',shift(shift($@)))')')') dnl Usage: m4_list_remove(key,list,...) dnl dnl Evaluate to the given list with `key' removed (if present). define(m4_list_remove, m4_assert_numargs_range(1,1000) `ifelse(`$2',,, `ifelse(`$1',`$2',,`$2,')dnl m4_list_remove(`$1',shift(shift($@)))')') dnl Usage: m4_list_first(list,...) dnl dnl Evaluate to the first element of the list (if any). define(m4_list_first,`$1') dnl Usage: m4_list_count(list,...) dnl dnl Evaluate to the number of elements in the list. This can't just use $# dnl because the last element might be empty. define(m4_list_count, `m4_list_count_internal(0,$@)') dnl Called: m4_list_internal(count,list,...) define(m4_list_count_internal, m4_assert_numargs_range(1,1000) `ifelse(`$2',,$1, `m4_list_count_internal(eval($1+1),shift(shift($@)))')') dnl -------------------------------------------------------------------------- dnl Various assembler things, not specific to any particular CPU. dnl dnl Usage: include_mpn(`filename') dnl dnl Like include(), but adds a path to the mpn source directory. For dnl example, dnl dnl include_mpn(`sparc64/addmul_1h.asm') define(include_mpn, m4_assert_numargs(1) m4_assert_defined(`CONFIG_TOP_SRCDIR') `include(CONFIG_TOP_SRCDIR`/mpn/$1')') dnl Usage: C comment ... dnl dnl This works like a FORTRAN-style comment character. It can be used for dnl comments to the right of assembly instructions, where just dnl would dnl remove the newline and concatenate adjacent lines. dnl dnl C and/or dnl are useful when an assembler doesn't support comments, or dnl where different assemblers for a particular CPU need different styles. dnl The intermediate ".s" files will end up with no comments, just code. dnl dnl Using C is not intended to cause offence to anyone who doesn't like dnl FORTRAN; but if that happens it's an unexpected bonus. dnl dnl During development, if comments are wanted in the .s files to help see dnl what's expanding where, C can be redefined with something like dnl dnl define(`C',`#') define(C, ` dnl') dnl Normally PIC is defined (or not) by libtool, but it doesn't set it on dnl systems which are always PIC. PIC_ALWAYS established in config.m4 dnl identifies these for us. ifelse(PIC_ALWAYS,`yes',`define(`PIC')') dnl Various possible defines passed from the Makefile that are to be tested dnl with ifdef() rather than be expanded. m4_not_for_expansion(`PIC') m4_not_for_expansion(`DLL_EXPORT') dnl aors_n m4_not_for_expansion(`OPERATION_add_n') m4_not_for_expansion(`OPERATION_sub_n') dnl aors_err1_n m4_not_for_expansion(`OPERATION_add_err1_n') m4_not_for_expansion(`OPERATION_sub_err1_n') dnl aors_err2_n m4_not_for_expansion(`OPERATION_add_err2_n') m4_not_for_expansion(`OPERATION_sub_err2_n') dnl aors_err3_n m4_not_for_expansion(`OPERATION_add_err3_n') m4_not_for_expansion(`OPERATION_sub_err3_n') dnl aorsmul_1 m4_not_for_expansion(`OPERATION_addmul_1') m4_not_for_expansion(`OPERATION_submul_1') dnl logops_n m4_not_for_expansion(`OPERATION_and_n') m4_not_for_expansion(`OPERATION_andn_n') m4_not_for_expansion(`OPERATION_nand_n') m4_not_for_expansion(`OPERATION_ior_n') m4_not_for_expansion(`OPERATION_iorn_n') m4_not_for_expansion(`OPERATION_nior_n') m4_not_for_expansion(`OPERATION_xor_n') m4_not_for_expansion(`OPERATION_xnor_n') dnl popham m4_not_for_expansion(`OPERATION_popcount') m4_not_for_expansion(`OPERATION_hamdist') dnl lorrshift m4_not_for_expansion(`OPERATION_lshift') m4_not_for_expansion(`OPERATION_rshift') dnl aorslsh1_n m4_not_for_expansion(`OPERATION_addlsh1_n') m4_not_for_expansion(`OPERATION_sublsh1_n') m4_not_for_expansion(`OPERATION_rsblsh1_n') dnl aorslsh2_n m4_not_for_expansion(`OPERATION_addlsh2_n') m4_not_for_expansion(`OPERATION_sublsh2_n') m4_not_for_expansion(`OPERATION_rsblsh2_n') dnl rsh1aors_n m4_not_for_expansion(`OPERATION_rsh1add_n') m4_not_for_expansion(`OPERATION_rsh1sub_n') dnl Usage: m4_config_gmp_mparam(`symbol') dnl dnl Check that `symbol' is defined. If it isn't, issue an error and dnl terminate immediately. The error message explains that the symbol dnl should be in config.m4, copied from gmp-mparam.h. dnl dnl Termination is immediate since missing say SQR_TOOM2_THRESHOLD can dnl lead to infinite loops and endless error messages. define(m4_config_gmp_mparam, m4_assert_numargs(1) `ifdef(`$1',, `m4_error(`$1 is not defined. "configure" should have extracted this from gmp-mparam.h and put it in config.m4 (or in _.asm for a fat binary), but somehow this has failed. ')m4exit(1)')') dnl Usage: defreg(name,reg) dnl dnl Give a name to a $ style register. For example, dnl dnl defreg(foo,$12) dnl dnl defreg() inserts an extra pair of quotes after the $ so that it's not dnl interpreted as an m4 macro parameter, ie. foo is actually $`'12. m4 dnl strips those quotes when foo is expanded. dnl dnl deflit() is used to make the new definition, so it will expand dnl literally even if followed by parentheses ie. foo(99) will become dnl $12(99). (But there's nowhere that would be used is there?) dnl dnl When making further definitions from existing defreg() macros, remember dnl to use defreg() again to protect the $ in the new definitions too. For dnl example, dnl dnl defreg(a0,$4) dnl defreg(a1,$5) dnl ... dnl dnl defreg(PARAM_DST,a0) dnl dnl This is only because a0 is expanding at the time the PARAM_DST dnl definition is made, leaving a literal $4 that must be re-quoted. On dnl the other hand in something like the following ra is only expanded when dnl ret is used and its $`'31 protection will have its desired effect at dnl that time. dnl dnl defreg(ra,$31) dnl ... dnl define(ret,`j ra') dnl dnl Note that only $n forms are meant to be used here, and something like dnl 128($30) doesn't get protected and will come out wrong. define(defreg, m4_assert_numargs(2) `deflit(`$1', substr(`$2',0,1)``''substr(`$2',1))') dnl Usage: m4_instruction_wrapper() dnl dnl Put this, unquoted, on a line on its own, at the start of a macro dnl that's a wrapper around an assembler instruction. It adds code to give dnl a descriptive error message if the macro is invoked without arguments. dnl dnl For example, suppose jmp needs to be wrapped, dnl dnl define(jmp, dnl m4_instruction_wrapper() dnl m4_assert_numargs(1) dnl `.byte 0x42 dnl .long $1 dnl nop') dnl dnl The point of m4_instruction_wrapper is to get a better error message dnl than m4_assert_numargs would give if jmp is accidentally used as plain dnl "jmp foo" instead of the intended "jmp( foo)". "jmp()" with no dnl argument also provokes the error message. dnl dnl m4_instruction_wrapper should only be used with wrapped instructions dnl that take arguments, since obviously something meant to be used as say dnl plain "ret" doesn't want to give an error when used that way. define(m4_instruction_wrapper, m4_assert_numargs(0) ``m4_instruction_wrapper_internal'(m4_doublequote($`'0),dnl ifdef(`__file__',`m4_doublequote(__file__)',``the m4 sources''),dnl $`#',m4_doublequote($`'1))`dnl'') dnl Called: m4_instruction_wrapper_internal($0,`filename',$#,$1) define(m4_instruction_wrapper_internal, `ifelse(eval($3<=1 && m4_length(`$4')==0),1, `m4_error(`$1 is a macro replacing that instruction and needs arguments, see $2 for details ')')') dnl Usage: m4_cpu_hex_constant(string) dnl dnl Expand to the string prefixed by a suitable `0x' hex marker. This dnl should be redefined as necessary for CPUs with different conventions. define(m4_cpu_hex_constant, m4_assert_numargs(1) `0x`$1'') dnl Usage: UNROLL_LOG2, UNROLL_MASK, UNROLL_BYTES dnl CHUNK_LOG2, CHUNK_MASK, CHUNK_BYTES dnl dnl When code supports a variable amount of loop unrolling, the convention dnl is to define UNROLL_COUNT to the number of limbs processed per loop. dnl When testing code this can be varied to see how much the loop overhead dnl is costing. For example, dnl dnl deflit(UNROLL_COUNT, 32) dnl dnl If the forloop() generating the unrolled loop has a pattern processing dnl more than one limb, the convention is to express this with CHUNK_COUNT. dnl For example, dnl dnl deflit(CHUNK_COUNT, 2) dnl dnl The LOG2, MASK and BYTES definitions below are derived from these COUNT dnl definitions. If COUNT is redefined, the LOG2, MASK and BYTES follow dnl the new definition automatically. dnl dnl LOG2 is the log base 2 of COUNT. MASK is COUNT-1, which can be used as dnl a bit mask. BYTES is GMP_LIMB_BYTES*COUNT, the number of bytes dnl processed in each unrolled loop. dnl dnl GMP_LIMB_BYTES is defined in a CPU specific m4 include file. It dnl exists only so the BYTES definitions here can be common to all CPUs. dnl In the actual code for a given CPU, an explicit 4 or 8 may as well be dnl used because the code is only for a particular CPU, it doesn't need to dnl be general. dnl dnl Note that none of these macros do anything except give conventional dnl names to commonly used things. You still have to write your own dnl expressions for a forloop() and the resulting address displacements. dnl Something like the following would be typical for 4 bytes per limb. dnl dnl forloop(`i',0,UNROLL_COUNT-1,` dnl deflit(`disp',eval(i*4)) dnl ... dnl ') dnl dnl Or when using CHUNK_COUNT, dnl dnl forloop(`i',0,UNROLL_COUNT/CHUNK_COUNT-1,` dnl deflit(`disp0',eval(i*CHUNK_COUNT*4)) dnl deflit(`disp1',eval(disp0+4)) dnl ... dnl ') dnl dnl Clearly `i' can be run starting from 1, or from high to low or whatever dnl best suits. deflit(UNROLL_LOG2, m4_assert_defined(`UNROLL_COUNT') `m4_log2(UNROLL_COUNT)') deflit(UNROLL_MASK, m4_assert_defined(`UNROLL_COUNT') `eval(UNROLL_COUNT-1)') deflit(UNROLL_BYTES, m4_assert_defined(`UNROLL_COUNT') m4_assert_defined(`GMP_LIMB_BYTES') `eval(UNROLL_COUNT * GMP_LIMB_BYTES)') deflit(CHUNK_LOG2, m4_assert_defined(`CHUNK_COUNT') `m4_log2(CHUNK_COUNT)') deflit(CHUNK_MASK, m4_assert_defined(`CHUNK_COUNT') `eval(CHUNK_COUNT-1)') deflit(CHUNK_BYTES, m4_assert_defined(`CHUNK_COUNT') m4_assert_defined(`GMP_LIMB_BYTES') `eval(CHUNK_COUNT * GMP_LIMB_BYTES)') dnl Usage: MPN(name) dnl dnl Add MPN_PREFIX to a name. dnl MPN_PREFIX defaults to "__gmpn_" if not defined. dnl dnl m4_unquote is used in MPN so that when it expands to say __gmpn_foo, dnl that identifier will be subject to further macro expansion. This is dnl used by some of the fat binary support for renaming symbols. ifdef(`MPN_PREFIX',, `define(`MPN_PREFIX',`__gmpn_')') define(MPN, m4_assert_numargs(1) `m4_unquote(MPN_PREFIX`'$1)') dnl Usage: mpn_add_n, etc dnl dnl Convenience definitions using MPN(), like the #defines in gmp.h. Each dnl function that might be implemented in assembler is here. define(define_mpn, m4_assert_numargs(1) `deflit(`mpn_$1',`MPN(`$1')')') define_mpn(add) define_mpn(add_1) define_mpn(add_err1_n) define_mpn(add_err2_n) define_mpn(add_err3_n) define_mpn(add_n) define_mpn(add_nc) define_mpn(addlsh1_n) define_mpn(addlsh1_nc) define_mpn(addlsh2_n) define_mpn(addlsh2_nc) define_mpn(addlsh_n) define_mpn(addlsh_nc) define_mpn(addlsh1_n_ip1) define_mpn(addlsh1_nc_ip1) define_mpn(addlsh2_n_ip1) define_mpn(addlsh2_nc_ip1) define_mpn(addlsh_n_ip1) define_mpn(addlsh_nc_ip1) define_mpn(addlsh1_n_ip2) define_mpn(addlsh1_nc_ip2) define_mpn(addlsh2_n_ip2) define_mpn(addlsh2_nc_ip2) define_mpn(addlsh_n_ip2) define_mpn(addlsh_nc_ip2) define_mpn(addmul_1) define_mpn(addmul_1c) define_mpn(addmul_2) define_mpn(addmul_3) define_mpn(addmul_4) define_mpn(addmul_5) define_mpn(addmul_6) define_mpn(addmul_7) define_mpn(addmul_8) define_mpn(addmul_2s) define_mpn(add_n_sub_n) define_mpn(add_n_sub_nc) define_mpn(addaddmul_1msb0) define_mpn(and_n) define_mpn(andn_n) define_mpn(bdiv_q_1) define_mpn(pi1_bdiv_q_1) define_mpn(bdiv_dbm1c) define_mpn(cmp) define_mpn(cnd_add_n) define_mpn(cnd_sub_n) define_mpn(com) define_mpn(copyd) define_mpn(copyi) define_mpn(count_leading_zeros) define_mpn(count_trailing_zeros) define_mpn(div_qr_1n_pi1) define_mpn(div_qr_2) define_mpn(div_qr_2n_pi1) define_mpn(div_qr_2u_pi1) define_mpn(div_qr_2n_pi2) define_mpn(div_qr_2u_pi2) define_mpn(divexact_1) define_mpn(divexact_by3c) define_mpn(divrem) define_mpn(divrem_1) define_mpn(divrem_1c) define_mpn(divrem_2) define_mpn(divrem_classic) define_mpn(divrem_newton) define_mpn(dump) define_mpn(gcd) define_mpn(gcd_1) define_mpn(gcd_11) define_mpn(gcd_22) define_mpn(gcdext) define_mpn(get_str) define_mpn(hamdist) define_mpn(invert_limb) define_mpn(invert_limb_table) define_mpn(ior_n) define_mpn(iorn_n) define_mpn(lshift) define_mpn(lshiftc) define_mpn(mod_1_1p) define_mpn(mod_1_1p_cps) define_mpn(mod_1s_2p) define_mpn(mod_1s_2p_cps) define_mpn(mod_1s_3p) define_mpn(mod_1s_3p_cps) define_mpn(mod_1s_4p) define_mpn(mod_1s_4p_cps) define_mpn(mod_1) define_mpn(mod_1c) define_mpn(mod_34lsub1) define_mpn(modexact_1_odd) define_mpn(modexact_1c_odd) define_mpn(mul) define_mpn(mul_1) define_mpn(mul_1c) define_mpn(mul_2) define_mpn(mul_3) define_mpn(mul_4) define_mpn(mul_5) define_mpn(mul_6) define_mpn(mul_basecase) define_mpn(mul_n) define_mpn(mullo_basecase) define_mpn(mulmid_basecase) define_mpn(perfect_square_p) define_mpn(popcount) define_mpn(preinv_divrem_1) define_mpn(preinv_mod_1) define_mpn(nand_n) define_mpn(neg) define_mpn(nior_n) define_mpn(powm) define_mpn(powlo) define_mpn(random) define_mpn(random2) define_mpn(redc_1) define_mpn(redc_2) define_mpn(rsblsh1_n) define_mpn(rsblsh1_nc) define_mpn(rsblsh2_n) define_mpn(rsblsh2_nc) define_mpn(rsblsh_n) define_mpn(rsblsh_nc) define_mpn(rsh1add_n) define_mpn(rsh1add_nc) define_mpn(rsh1sub_n) define_mpn(rsh1sub_nc) define_mpn(rshift) define_mpn(rshiftc) define_mpn(sbpi1_bdiv_q) define_mpn(sbpi1_bdiv_qr) define_mpn(sbpi1_bdiv_r) define_mpn(scan0) define_mpn(scan1) define_mpn(set_str) define_mpn(sqr_basecase) define_mpn(sqr_diagonal) define_mpn(sqr_diag_addlsh1) define_mpn(sub_n) define_mpn(sublsh1_n) define_mpn(sublsh1_nc) define_mpn(sublsh1_n_ip1) define_mpn(sublsh1_nc_ip1) define_mpn(sublsh2_n) define_mpn(sublsh2_nc) define_mpn(sublsh2_n_ip1) define_mpn(sublsh2_nc_ip1) define_mpn(sublsh_n) define_mpn(sublsh_nc) define_mpn(sublsh_n_ip1) define_mpn(sublsh_nc_ip1) define_mpn(sqrtrem) define_mpn(sub) define_mpn(sub_1) define_mpn(sub_err1_n) define_mpn(sub_err2_n) define_mpn(sub_err3_n) define_mpn(sub_n) define_mpn(sub_nc) define_mpn(submul_1) define_mpn(submul_1c) define_mpn(sec_tabselect) define_mpn(umul_ppmm) define_mpn(umul_ppmm_r) define_mpn(udiv_qrnnd) define_mpn(udiv_qrnnd_r) define_mpn(xnor_n) define_mpn(xor_n) dnl Defines for C global arrays and variables, with names matching what's dnl used in the C code. dnl dnl Notice that GSYM_PREFIX is included, unlike with the function defines dnl above. Also, "deflit" is used so that something like __clz_tab(%ebx) dnl comes out as __gmpn_clz_tab(%ebx), for the benefit of CPUs with that dnl style assembler syntax. deflit(__clz_tab, m4_assert_defined(`GSYM_PREFIX') `GSYM_PREFIX`'MPN(`clz_tab')') deflit(binvert_limb_table, m4_assert_defined(`GSYM_PREFIX') `GSYM_PREFIX`'__gmp_binvert_limb_table') dnl Usage: ASM_START() dnl dnl Emit any directives needed once at the start of an assembler file, like dnl ".set noreorder" or whatever. The default for this is nothing, but dnl it's redefined by CPU specific m4 files. define(ASM_START) dnl Usage: ASM_END() dnl dnl Emit any directives needed once at the end of an assembler file. The dnl default for this is nothing, but it's redefined by CPU specific m4 files. define(ASM_END) dnl Usage: PROLOGUE(foo[,param]) dnl EPILOGUE(foo) dnl dnl Emit directives to start or end a function. GSYM_PREFIX is added by dnl these macros if necessary, so the given "foo" is what the function will dnl be called in C. dnl dnl The second parameter to PROLOGUE is used only for some CPUs and should dnl be omitted if not required. dnl dnl Nested or overlapping PROLOGUE/EPILOGUE pairs are allowed, if that dnl makes sense for the system. The name given to EPILOGUE must be a dnl currently open PROLOGUE. dnl dnl If only one PROLOGUE is open then the name can be omitted from dnl EPILOGUE. This is encouraged, since it means the name only has to dnl appear in one place, not two. dnl dnl The given name "foo" is not fully quoted here, it will be macro dnl expanded more than once. This is the way the m4_list macros work, and dnl it also helps the tune/many.pl program do a renaming like dnl -D__gmpn_add_n=mpn_add_n_foo when GSYM_PREFIX is not empty. define(PROLOGUE, m4_assert_numargs_range(1,2) `m4_file_seen()dnl define(`PROLOGUE_list',m4_list_quote($1,PROLOGUE_list))dnl ifelse(`$2',, `PROLOGUE_cpu(GSYM_PREFIX`'$1)', `PROLOGUE_cpu(GSYM_PREFIX`'$1,`$2')')') define(EPILOGUE, m4_assert_numargs_range(0,1) `ifelse(`$1',, `ifelse(m4_list_count(PROLOGUE_list),0, `m4_error(`no open functions for EPILOGUE ')', `ifelse(m4_list_count(PROLOGUE_list),1, `EPILOGUE_internal(PROLOGUE_current_function)', `m4_error(`more than one open function for EPILOGUE ')')')', `EPILOGUE_internal(`$1')')') define(EPILOGUE_internal, m4_assert_numargs(1) m4_assert_defined(`EPILOGUE_cpu') `ifelse(m4_list_find($1,PROLOGUE_list),0, `m4_error(`EPILOGUE without PROLOGUE: $1 ')')dnl define(`PROLOGUE_list',m4_list_quote(m4_list_remove($1,PROLOGUE_list)))dnl EPILOGUE_cpu(GSYM_PREFIX`$1')') dnl Currently open PROLOGUEs, as a comma-separated list. define(PROLOGUE_list) dnl Called: PROLOGUE_check(list,...) dnl Check there's no remaining open PROLOGUEs at the end of input. define(PROLOGUE_check, `ifelse($1,,, `m4_error(`no EPILOGUE for: $1 ')dnl PROLOGUE_check(shift($@))')') m4wrap_prepend(`PROLOGUE_check(PROLOGUE_list)') dnl Usage: PROLOGUE_current_function dnl dnl This macro expands to the current PROLOGUE/EPILOGUE function, or the dnl most recent PROLOGUE if such pairs are nested or overlapped. define(PROLOGUE_current_function, m4_assert_numargs(-1) `m4_list_first(PROLOGUE_list)') dnl Usage: PROLOGUE_cpu(GSYM_PREFIX`'foo[,param]) dnl EPILOGUE_cpu(GSYM_PREFIX`'foo) dnl dnl These macros hold the CPU-specific parts of PROLOGUE and EPILOGUE. dnl Both are called with the function name, with GSYM_PREFIX already dnl prepended. dnl dnl The definitions here are something typical and sensible, but CPU or dnl system specific m4 files should redefine them as necessary. The dnl optional extra parameter to PROLOGUE_cpu is not expected and not dnl accepted here. define(PROLOGUE_cpu, m4_assert_numargs(1) ` TEXT ALIGN(8) GLOBL `$1' GLOBL_ATTR TYPE(`$1',`function') `$1'LABEL_SUFFIX') define(EPILOGUE_cpu, ` SIZE(`$1',.-`$1')') dnl Usage: L(name) dnl dnl Generate a local label with the given name. This is simply a dnl convenient way to add LSYM_PREFIX. dnl dnl LSYM_PREFIX might be L$, so defn() must be used to quote it or the L dnl will expand again as the L macro, making an infinite recursion. define(`L', m4_assert_numargs(1) `defn(`LSYM_PREFIX')$1') dnl Usage: LDEF(name) dnl dnl Generate a directive to define a local label. dnl dnl On systems with a fixed syntax for defining labels there's no need to dnl use this macro, it's only meant for systems where the syntax varies, dnl like hppa which is "L(foo):" with gas, but just "L(foo)" in column 0 dnl with the system `as'. dnl dnl The extra `' after LABEL_SUFFIX avoids any chance of a following dnl "(...)" being interpreted as an argument list. Not that it'd be dnl sensible to write anything like that after an LDEF(), but just in case. define(LDEF, m4_assert_numargs(1) m4_assert_defined(`LABEL_SUFFIX') `L(`$1')`'LABEL_SUFFIX`'') dnl Usage: INT32(label,value) dnl INT64(label,first,second) define(`INT32', m4_assert_defined(`W32') ` ALIGN(4) LDEF(`$1') W32 $2') define(`INT64', m4_assert_defined(`W32') ` ALIGN(8) LDEF(`$1') W32 $2 W32 $3') dnl Usage: ALIGN(bytes) dnl dnl Emit a ".align" directive. The alignment is specified in bytes, and dnl will normally need to be a power of 2. The actual ".align" generated dnl is either bytes or logarithmic according to what ./configure finds the dnl assembler needs. dnl dnl If ALIGN_FILL_0x90 is defined and equal to "yes", then ", 0x90" is dnl appended. This is for x86, see mpn/x86/README. define(ALIGN, m4_assert_numargs(1) m4_assert_defined(`ALIGN_LOGARITHMIC') `.align ifelse(ALIGN_LOGARITHMIC,yes,`m4_log2($1)',`eval($1)')dnl ifelse(ALIGN_FILL_0x90,yes,`, 0x90')') dnl Usage: MULFUNC_PROLOGUE(function function...) dnl dnl A dummy macro which is grepped for by ./configure to know what dnl functions a multi-function file is providing. Use this if there aren't dnl explicit PROLOGUE()s for each possible function. dnl dnl Multiple MULFUNC_PROLOGUEs can be used, or just one with the function dnl names separated by spaces. define(`MULFUNC_PROLOGUE', m4_assert_numargs(1) ) dnl Usage: NAILS_SUPPORT(spec spec ...) dnl dnl A dummy macro which is grepped for by ./configure to know what nails dnl are supported in an asm file. dnl dnl Ranges can be given, or just individual values. Multiple values or dnl ranges can be given, separated by spaces. Multiple NAILS_SUPPORT dnl declarations work too. Some examples, dnl dnl NAILS_SUPPORT(1-20) dnl NAILS_SUPPORT(1 6 9-12) dnl NAILS_SUPPORT(1-10 16-20) define(NAILS_SUPPORT, m4_assert_numargs(1) ) dnl Usage: ABI_SUPPORT(abi) dnl dnl A dummy macro which is grepped for by ./configure to know what ABIs dnl are supported in an asm file. dnl dnl If multiple non-standard ABIs are supported, several ABI_SUPPORT dnl declarations should be used: dnl dnl ABI_SUPPORT(FOOABI) dnl ABI_SUPPORT(BARABI) define(ABI_SUPPORT, m4_assert_numargs(1) ) dnl Usage: GMP_NUMB_MASK dnl dnl A bit mask for the number part of a limb. Eg. with 6 bit nails in a dnl 32 bit limb, GMP_NUMB_MASK would be 0x3ffffff. define(GMP_NUMB_MASK, m4_assert_numargs(-1) m4_assert_defined(`GMP_NUMB_BITS') `m4_hex_lowmask(GMP_NUMB_BITS)') dnl Usage: m4append(`variable',`value-to-append') define(`m4append', `define(`$1', defn(`$1')`$2') ' ) divert`'dnl flint-3.1.3/src/mpn_extras/broadwell/000077500000000000000000000000001461254215100175555ustar00rootroot00000000000000flint-3.1.3/src/mpn_extras/broadwell/darwin.m4000066400000000000000000000043501461254215100213050ustar00rootroot00000000000000divert(-1) dnl Copyright 2008, 2011, 2012 Free Software Foundation, Inc. dnl dnl This file is part of the GNU MP Library. dnl dnl The GNU MP Library is free software; you can redistribute it and/or modify dnl it under the terms of either: dnl dnl * the GNU Lesser General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your dnl option) any later version. dnl dnl or dnl dnl * the GNU General Public License as published by the Free Software dnl Foundation; either version 2 of the License, or (at your option) any dnl later version. dnl dnl or both in parallel, as here. dnl dnl The GNU MP Library is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dnl for more details. dnl dnl You should have received copies of the GNU General Public License and the dnl GNU Lesser General Public License along with the GNU MP Library. If not, dnl see https://www.gnu.org/licenses/. define(`DARWIN') define(`LEA',`dnl ifdef(`PIC', `lea $1(%rip), $2' , `movabs `$'$1, $2') ') dnl Usage: CALL(funcname) dnl dnl Simply override the definition in x86_64-defs.m4. define(`CALL',`call GSYM_PREFIX`'$1') define(`TCALL',`jmp GSYM_PREFIX`'$1') dnl Usage: JUMPTABSECT dnl dnl CAUTION: Do not put anything sensible here, like RODATA. That works with dnl some Darwin tool chains, but silently breaks with other. (Note that dnl putting jump tables in the text segment is a really poor idea for many PC dnl processors, since they cannot cache the same thing in both L1D and L2I.) define(`JUMPTABSECT', `.text') dnl Usage: JMPENT(targlabel,tablabel) define(`JMPENT',`dnl ifdef(`PIC', `.set $1_tmp, $1-$2 .long $1_tmp' , `.quad $1' )') dnl Target ABI macros. For Darwin we override IFELF (and leave default for dnl IFDOS and IFSTD). define(`IFELF', `') dnl Usage: PROTECT(symbol) dnl dnl Used for private GMP symbols that should never be overridden by users. dnl This can save reloc entries and improve shlib sharing as well as dnl application startup times define(`PROTECT', `.private_extern $1') divert`'dnl flint-3.1.3/src/mpn_extras/broadwell/mul_hard.asm000066400000000000000000003527471461254215100220740ustar00rootroot00000000000000dnl dnl Copyright (C) 2023 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') dnl TODO: Alot to fix here... dnl * Instead of flint_mpn_mul_M_N for hardcoded M and N, do flint_mpn_mul_M_n, dnl where n is a variable instead. This will reduce the amount of code, and dnl probably be around the same speed, although one register has to go to n dnl (%rcx). dnl * Fix latencies. dnl * Minimize 32-bit instructions by registers. dnl * Investigate partially storing in stack(?) instead of storing in registers. TEXT .macro m3_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r4 mulx (2+\ap_offset)*8(\ap), \r2, \r5 add \r3, \r1 adc \r4, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) adc $0, \r5 .endm .macro m4_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r5 mulx (2+\ap_offset)*8(\ap), \r2, \r4 add \r3, \r1 adc \r5, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r5 adc \r3, \r4 adc $0, \r5 mov \r4, (3+\res_offset)*8(\res) .endm .macro m5_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r5, \r4 mulx (2+\ap_offset)*8(\ap), \r2, \r1 add \r3, \r5 adc \r4, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r5, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r4 mulx (4+\ap_offset)*8(\ap), \r0, \r5 adc \r3, \r1 adc \r4, \r0 mov \r1, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) adc $0, \r5 .endm .macro m6_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r5 mulx (2+\ap_offset)*8(\ap), \r2, \r4 add \r3, \r1 adc \r5, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r5 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r5 adc \r3, \r1 adc $0, \r5 mov \r1, (5+\res_offset)*8(\res) .endm .macro m7_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r4 mulx (2+\ap_offset)*8(\ap), \r2, \r5 add \r3, \r1 adc \r4, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r4 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r5 adc \r4, \r0 mov \r5, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r4 mulx (6+\ap_offset)*8(\ap), \r2, \r5 adc \r3, \r1 adc \r4, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) adc $0, \r5 .endm .macro m8_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r5 mulx (2+\ap_offset)*8(\ap), \r2, \r4 add \r3, \r1 adc \r5, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r5 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r5 mulx (6+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r5 adc \r3, \r4 adc $0, \r5 mov \r4, (7+\res_offset)*8(\res) .endm .macro m9_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r5, \r4 mulx (2+\ap_offset)*8(\ap), \r2, \r1 add \r3, \r5 adc \r4, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r5, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r4 mulx (4+\ap_offset)*8(\ap), \r0, \r5 adc \r3, \r1 adc \r4, \r0 mov \r1, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r4 mulx (6+\ap_offset)*8(\ap), \r2, \r1 adc \r3, \r5 adc \r4, \r2 mov \r5, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r4 mulx (8+\ap_offset)*8(\ap), \r0, \r5 adc \r3, \r1 adc \r4, \r0 mov \r1, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) adc $0, \r5 .endm .macro m10_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r5 mulx (2+\ap_offset)*8(\ap), \r2, \r4 add \r3, \r1 adc \r5, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r5 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r5 mulx (6+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r5 mulx (8+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) mulx (9+\ap_offset)*8(\ap), \r3, \r5 adc \r3, \r1 adc $0, \r5 mov \r1, (9+\res_offset)*8(\res) .endm .macro m11_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r4 mulx (2+\ap_offset)*8(\ap), \r2, \r5 add \r3, \r1 adc \r4, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r4 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r5 adc \r4, \r0 mov \r5, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r4 mulx (6+\ap_offset)*8(\ap), \r2, \r5 adc \r3, \r1 adc \r4, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r4 mulx (8+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r5 adc \r4, \r0 mov \r5, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) mulx (9+\ap_offset)*8(\ap), \r3, \r4 mulx (10+\ap_offset)*8(\ap), \r2, \r5 adc \r3, \r1 adc \r4, \r2 mov \r1, (9+\res_offset)*8(\res) mov \r2, (10+\res_offset)*8(\res) adc $0, \r5 .endm .macro m12_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r5 mulx (2+\ap_offset)*8(\ap), \r2, \r4 add \r3, \r1 adc \r5, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r5 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r5 mulx (6+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r5 mulx (8+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) mulx (9+\ap_offset)*8(\ap), \r3, \r5 mulx (10+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (9+\res_offset)*8(\res) mov \r2, (10+\res_offset)*8(\res) mulx (11+\ap_offset)*8(\ap), \r3, \r5 adc \r3, \r4 adc $0, \r5 mov \r4, (11+\res_offset)*8(\res) .endm .macro m13_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r5, \r4 mulx (2+\ap_offset)*8(\ap), \r2, \r1 add \r3, \r5 adc \r4, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r5, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r4 mulx (4+\ap_offset)*8(\ap), \r0, \r5 adc \r3, \r1 adc \r4, \r0 mov \r1, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r4 mulx (6+\ap_offset)*8(\ap), \r2, \r1 adc \r3, \r5 adc \r4, \r2 mov \r5, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r4 mulx (8+\ap_offset)*8(\ap), \r0, \r5 adc \r3, \r1 adc \r4, \r0 mov \r1, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) mulx (9+\ap_offset)*8(\ap), \r3, \r4 mulx (10+\ap_offset)*8(\ap), \r2, \r1 adc \r3, \r5 adc \r4, \r2 mov \r5, (9+\res_offset)*8(\res) mov \r2, (10+\res_offset)*8(\res) mulx (11+\ap_offset)*8(\ap), \r3, \r4 mulx (12+\ap_offset)*8(\ap), \r0, \r5 adc \r3, \r1 adc \r4, \r0 mov \r1, (11+\res_offset)*8(\res) mov \r0, (12+\res_offset)*8(\res) adc $0, \r5 .endm .macro m14_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r5 mulx (2+\ap_offset)*8(\ap), \r2, \r4 add \r3, \r1 adc \r5, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r5 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r5 mulx (6+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r5 mulx (8+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) mulx (9+\ap_offset)*8(\ap), \r3, \r5 mulx (10+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (9+\res_offset)*8(\res) mov \r2, (10+\res_offset)*8(\res) mulx (11+\ap_offset)*8(\ap), \r3, \r5 mulx (12+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (11+\res_offset)*8(\res) mov \r0, (12+\res_offset)*8(\res) mulx (13+\ap_offset)*8(\ap), \r3, \r5 adc \r3, \r1 adc $0, \r5 mov \r1, (13+\res_offset)*8(\res) .endm .macro m15_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r4 mulx (2+\ap_offset)*8(\ap), \r2, \r5 add \r3, \r1 adc \r4, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r4 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r5 adc \r4, \r0 mov \r5, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r4 mulx (6+\ap_offset)*8(\ap), \r2, \r5 adc \r3, \r1 adc \r4, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r4 mulx (8+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r5 adc \r4, \r0 mov \r5, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) mulx (9+\ap_offset)*8(\ap), \r3, \r4 mulx (10+\ap_offset)*8(\ap), \r2, \r5 adc \r3, \r1 adc \r4, \r2 mov \r1, (9+\res_offset)*8(\res) mov \r2, (10+\res_offset)*8(\res) mulx (11+\ap_offset)*8(\ap), \r3, \r4 mulx (12+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r5 adc \r4, \r0 mov \r5, (11+\res_offset)*8(\res) mov \r0, (12+\res_offset)*8(\res) mulx (13+\ap_offset)*8(\ap), \r3, \r4 mulx (14+\ap_offset)*8(\ap), \r2, \r5 adc \r3, \r1 adc \r4, \r2 mov \r1, (13+\res_offset)*8(\res) mov \r2, (14+\res_offset)*8(\res) adc $0, \r5 .endm .macro m16_str res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5 mulx (0+\ap_offset)*8(\ap), \r0, \r3 mulx (1+\ap_offset)*8(\ap), \r1, \r5 mulx (2+\ap_offset)*8(\ap), \r2, \r4 add \r3, \r1 adc \r5, \r2 mov \r0, (0+\res_offset)*8(\res) mov \r1, (1+\res_offset)*8(\res) mov \r2, (2+\res_offset)*8(\res) mulx (3+\ap_offset)*8(\ap), \r3, \r5 mulx (4+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (3+\res_offset)*8(\res) mov \r0, (4+\res_offset)*8(\res) mulx (5+\ap_offset)*8(\ap), \r3, \r5 mulx (6+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (5+\res_offset)*8(\res) mov \r2, (6+\res_offset)*8(\res) mulx (7+\ap_offset)*8(\ap), \r3, \r5 mulx (8+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (7+\res_offset)*8(\res) mov \r0, (8+\res_offset)*8(\res) mulx (9+\ap_offset)*8(\ap), \r3, \r5 mulx (10+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (9+\res_offset)*8(\res) mov \r2, (10+\res_offset)*8(\res) mulx (11+\ap_offset)*8(\ap), \r3, \r5 mulx (12+\ap_offset)*8(\ap), \r0, \r1 adc \r3, \r4 adc \r5, \r0 mov \r4, (11+\res_offset)*8(\res) mov \r0, (12+\res_offset)*8(\res) mulx (13+\ap_offset)*8(\ap), \r3, \r5 mulx (14+\ap_offset)*8(\ap), \r2, \r4 adc \r3, \r1 adc \r5, \r2 mov \r1, (13+\res_offset)*8(\res) mov \r2, (14+\res_offset)*8(\res) mulx (15+\ap_offset)*8(\ap), \r3, \r5 adc \r3, \r4 adc $0, \r5 mov \r4, (15+\res_offset)*8(\res) .endm .macro m3 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 mulx (1+\ap_offset)*8(\ap), \scr2, \r1 mov \scr1, \res_offset*8(\res) adcx \scr2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 adcx \scr1, \r1 adcx \zero, \r2 .endm .macro m4 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 mulx (1+\ap_offset)*8(\ap), \scr2, \r1 mov \scr1, \res_offset*8(\res) adcx \scr2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 adcx \zero, \r3 .endm .macro m5 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 mulx (1+\ap_offset)*8(\ap), \scr2, \r1 mov \scr1, \res_offset*8(\res) adcx \scr2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 mulx (4+\ap_offset)*8(\ap), \scr1, \r4 adcx \scr1, \r3 adcx \zero, \r4 .endm .macro m6 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 mulx (1+\ap_offset)*8(\ap), \scr2, \r1 mov \scr1, \res_offset*8(\res) adcx \scr2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 mulx (4+\ap_offset)*8(\ap), \scr1, \r4 mulx (5+\ap_offset)*8(\ap), \scr2, \r5 adcx \scr1, \r3 adcx \scr2, \r4 adcx \zero, \r5 .endm .macro m7 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5, r6, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 mulx (1+\ap_offset)*8(\ap), \scr2, \r1 mov \scr1, \res_offset*8(\res) adcx \scr2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 mulx (4+\ap_offset)*8(\ap), \scr1, \r4 mulx (5+\ap_offset)*8(\ap), \scr2, \r5 adcx \scr1, \r3 adcx \scr2, \r4 mulx (6+\ap_offset)*8(\ap), \scr1, \r6 adcx \scr1, \r5 adcx \zero, \r6 .endm .macro m8 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5, r6, r7, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 mulx (1+\ap_offset)*8(\ap), \scr2, \r1 mov \scr1, \res_offset*8(\res) adcx \scr2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 mulx (4+\ap_offset)*8(\ap), \scr1, \r4 mulx (5+\ap_offset)*8(\ap), \scr2, \r5 adcx \scr1, \r3 adcx \scr2, \r4 mulx (6+\ap_offset)*8(\ap), \scr1, \r6 mulx (7+\ap_offset)*8(\ap), \scr2, \r7 adcx \scr1, \r5 adcx \scr2, \r6 adcx \zero, \r7 .endm .macro m3_chain res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, ip1, ip2, r0, r1, r2, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 adcx \ip1, \scr1 mov \scr1, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \scr2, \r1 adcx \scr2, \r0 adox \ip2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 adcx \scr1, \r1 adcx \zero, \r2 .endm .macro m4_chain res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, ip1, ip2, r0, r1, r2, r3, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 adcx \ip1, \scr1 mov \scr1, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \scr2, \r1 adcx \scr2, \r0 adox \ip2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 adcx \zero, \r3 .endm .macro m2_chain res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, ip1, ip2, r0, r1, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 adcx \ip1, \scr1 mov \scr1, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \scr2, \r1 adcx \scr2, \r0 adox \ip2, \r0 adcx \zero, \r1 .endm .macro m5_chain res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, ip1, ip2, r0, r1, r2, r3, r4, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 adcx \ip1, \scr1 mov \scr1, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \scr2, \r1 adcx \scr2, \r0 adox \ip2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 mulx (4+\ap_offset)*8(\ap), \scr1, \r4 adcx \scr1, \r3 adcx \zero, \r4 .endm .macro m6_chain res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, ip1, ip2, r0, r1, r2, r3, r4, r5, scr1, scr2, zero mulx (0+\ap_offset)*8(\ap), \scr1, \r0 adcx \ip1, \scr1 mov \scr1, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \scr2, \r1 adcx \scr2, \r0 adox \ip2, \r0 mulx (2+\ap_offset)*8(\ap), \scr1, \r2 mulx (3+\ap_offset)*8(\ap), \scr2, \r3 adcx \scr1, \r1 adcx \scr2, \r2 mulx (4+\ap_offset)*8(\ap), \scr1, \r4 mulx (5+\ap_offset)*8(\ap), \scr2, \r5 adcx \scr1, \r3 adcx \scr2, \r4 adcx \zero, \r5 .endm .macro am2 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, scr, zero mulx (0+\ap_offset)*8(\ap), \r2, \scr adcx \r2, \r0 mov \r0, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \r0, \r2 adcx \scr, \r1 adox \r0, \r1 adcx \zero, \r2 adox \zero, \r2 .endm .macro am3 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, scr, zero mulx (0+\ap_offset)*8(\ap), \scr, \r3 adcx \scr, \r0 mov \r0, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \r0, \scr adcx \r3, \r1 adox \r0, \r1 mulx (2+\ap_offset)*8(\ap), \r0, \r3 adcx \scr, \r2 adox \r0, \r2 adcx \zero, \r3 adox \zero, \r3 .endm .macro am4 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, scr, zero mulx (0+\ap_offset)*8(\ap), \r4, \scr adcx \r4, \r0 mov \r0, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \r0, \r4 adcx \scr, \r1 adox \r0, \r1 mulx (2+\ap_offset)*8(\ap), \r0, \scr adcx \r4, \r2 adox \r0, \r2 mulx (3+\ap_offset)*8(\ap), \r0, \r4 adcx \scr, \r3 adox \r0, \r3 adcx \zero, \r4 adox \zero, \r4 .endm .macro am5 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5, scr, zero mulx (0+\ap_offset)*8(\ap), \scr, \r5 adcx \scr, \r0 mov \r0, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \r0, \scr adcx \r5, \r1 adox \r0, \r1 mulx (2+\ap_offset)*8(\ap), \r0, \r5 adcx \scr, \r2 adox \r0, \r2 mulx (3+\ap_offset)*8(\ap), \r0, \scr adcx \r5, \r3 adox \r0, \r3 mulx (4+\ap_offset)*8(\ap), \r0, \r5 adcx \scr, \r4 adox \r0, \r4 adcx \zero, \r5 adox \zero, \r5 .endm .macro am6 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5, r6, scr, zero mulx (0+\ap_offset)*8(\ap), \r6, \scr adcx \r6, \r0 mov \r0, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \r0, \r6 adcx \scr, \r1 adox \r0, \r1 mulx (2+\ap_offset)*8(\ap), \r0, \scr adcx \r6, \r2 adox \r0, \r2 mulx (3+\ap_offset)*8(\ap), \r0, \r6 adcx \scr, \r3 adox \r0, \r3 mulx (4+\ap_offset)*8(\ap), \r0, \scr adcx \r6, \r4 adox \r0, \r4 mulx (5+\ap_offset)*8(\ap), \r0, \r6 adcx \scr, \r5 adox \r0, \r5 adcx \zero, \r6 adox \zero, \r6 .endm .macro am7 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5, r6, r7, scr, zero mulx (0+\ap_offset)*8(\ap), \scr, \r7 adcx \scr, \r0 mov \r0, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \r0, \scr adcx \r7, \r1 adox \r0, \r1 mulx (2+\ap_offset)*8(\ap), \r0, \r7 adcx \scr, \r2 adox \r0, \r2 mulx (3+\ap_offset)*8(\ap), \r0, \scr adcx \r7, \r3 adox \r0, \r3 mulx (4+\ap_offset)*8(\ap), \r0, \r7 adcx \scr, \r4 adox \r0, \r4 mulx (5+\ap_offset)*8(\ap), \r0, \scr adcx \r7, \r5 adox \r0, \r5 mulx (6+\ap_offset)*8(\ap), \r0, \r7 adcx \scr, \r6 adox \r0, \r6 adcx \zero, \r7 adox \zero, \r7 .endm .macro am8 res=%rdi, res_offset=0, ap=%rsi, ap_offset=0, r0, r1, r2, r3, r4, r5, r6, r7, r8, scr, zero mulx (0+\ap_offset)*8(\ap), \r8, \scr adcx \r8, \r0 mov \r0, \res_offset*8(\res) mulx (1+\ap_offset)*8(\ap), \r0, \r8 adcx \scr, \r1 adox \r0, \r1 mulx (2+\ap_offset)*8(\ap), \r0, \scr adcx \r8, \r2 adox \r0, \r2 mulx (3+\ap_offset)*8(\ap), \r0, \r8 adcx \scr, \r3 adox \r0, \r3 mulx (4+\ap_offset)*8(\ap), \r0, \scr adcx \r8, \r4 adox \r0, \r4 mulx (5+\ap_offset)*8(\ap), \r0, \r8 adcx \scr, \r5 adox \r0, \r5 mulx (6+\ap_offset)*8(\ap), \r0, \scr adcx \r8, \r6 adox \r0, \r6 mulx (7+\ap_offset)*8(\ap), \r0, \r8 adcx \scr, \r7 adox \r0, \r7 adcx \zero, \r8 adox \zero, \r8 .endm ALIGN(16) PROLOGUE(flint_mpn_mul_1_1) mov (%rdx), %rdx mulx 0*8(%rsi), %rcx, %rax mov %rcx, 0*8(%rdi) mov %rax, 1*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_2_1) mov 0*8(%rdx), %rdx xor %r10d, %r10d mulx 0*8(%rsi), %rcx, %r8 mulx 1*8(%rsi), %r9, %rax adcx %r9, %r8 adcx %r10, %rax mov %rcx, 0*8(%rdi) mov %r8, 1*8(%rdi) mov %rax, 2*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_2_2) mov 1*8(%rdx), %r10 mov 0*8(%rdx), %rdx xor %r11d, %r11d mulx 0*8(%rsi), %rcx, %r8 mulx 1*8(%rsi), %rax, %r9 adcx %rax, %r8 mov %rcx, 0*8(%rdi) mov %r10, %rdx mulx 0*8(%rsi), %rcx, %rax adox %rcx, %r8 adcx %rax, %r9 mov %r8, 1*8(%rdi) mulx 1*8(%rsi), %rcx, %rax adox %rcx, %r9 adcx %r11, %rax adox %r11, %rax mov %r9, 2*8(%rdi) mov %rax, 3*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_3_1) mov 0*8(%rdx), %rdx m3_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 3*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_3_2) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 1*8(%rcx), %rdx am3 %rdi, 1, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov %r8, 2*8(%rdi) mov %r9, 3*8(%rdi) mov %rax, 4*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_3_3) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 1*8(%rcx), %rdx am3 %rdi, 1, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 2*8(%rcx), %rdx am3 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %rax, 5*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_4_1) mov 0*8(%rdx), %rdx m4_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 4*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_4_2) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rsi, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp mov 1*8(%rcx), %rdx am4 %rdi, 1, %rsi, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp mov %r8, 2*8(%rdi) mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %rax, 5*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_4_3) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp mov 1*8(%rcx), %rdx am4 %rdi, 1, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp mov 2*8(%rcx), %rdx am4 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %r11, %rax, %rbx, %rbp mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rax, 6*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_4_4) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 1*8(%rcx), %rdx am4 %rdi, 1, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 2*8(%rcx), %rdx am4 %rdi, 2, %rsi, 0, %rax, %r9, %r10, %r11, %r8, %rbx, %rbp mov 3*8(%rcx), %rdx am4 %rdi, 3, %rsi, 0, %r9, %r10, %r11, %r8, %rax, %rbx, %rbp mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %r8, 6*8(%rdi) mov %rax, 7*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_5_1) mov 0*8(%rdx), %rdx m5_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 5*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_5_2) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rsi, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12 mov 1*8(%rcx), %rdx am5 %rdi, 1, %rsi, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12 mov %r8, 2*8(%rdi) mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rax, 6*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_5_3) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rcx), %rdx am5 %rdi, 1, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rcx), %rdx am5 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rax, 7*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_5_4) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rcx), %rdx am5 %rdi, 1, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rcx), %rdx am5 %rdi, 2, %rsi, 0, %rax, %r9, %r10, %r11, %rbx, %r8, %rbp, %r12 mov 3*8(%rcx), %rdx am5 %rdi, 3, %rsi, 0, %r9, %r10, %r11, %rbx, %r8, %rax, %rbp, %r12 mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %r8, 7*8(%rdi) mov %rax, 8*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_5_5) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rcx), %rdx am5 %rdi, 1, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rcx), %rdx am5 %rdi, 2, %rsi, 0, %r8, %rax, %r10, %r11, %rbx, %r9, %rbp, %r12 mov 3*8(%rcx), %rdx am5 %rdi, 3, %rsi, 0, %rax, %r10, %r11, %rbx, %r9, %r8, %rbp, %r12 mov 4*8(%rcx), %rdx am5 %rdi, 4, %rsi, 0, %r10, %r11, %rbx, %r9, %r8, %rax, %rbp, %r12 mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %r9, 7*8(%rdi) mov %r8, 8*8(%rdi) mov %rax, 9*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_6_1) mov 0*8(%rdx), %rdx m6_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 6*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_6_2) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rsi, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov 1*8(%rcx), %rdx am6 %rdi, 1, %rsi, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov %r8, 2*8(%rdi) mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rax, 7*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_6_3) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rcx), %rdx am6 %rdi, 1, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rcx), %rdx am6 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %rax, 8*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_6_4) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rcx), %rdx am6 %rdi, 1, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rcx), %rdx am6 %rdi, 2, %rsi, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r8, %r12, %r13 mov 3*8(%rcx), %rdx am6 %rdi, 3, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %r8, %rax, %r12, %r13 mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r8, 8*8(%rdi) mov %rax, 9*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_6_5) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rcx), %rdx am6 %rdi, 1, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rcx), %rdx am6 %rdi, 2, %rsi, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r9, %r12, %r13 mov 3*8(%rcx), %rdx am6 %rdi, 3, %rsi, 0, %rax, %r10, %r11, %rbx, %rbp, %r9, %r8, %r12, %r13 mov 4*8(%rcx), %rdx am6 %rdi, 4, %rsi, 0, %r10, %r11, %rbx, %rbp, %r9, %r8, %rax, %r12, %r13 mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r9, 8*8(%rdi) mov %r8, 9*8(%rdi) mov %rax, 10*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_6_6) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rcx), %rdx am6 %rdi, 1, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rcx), %rdx am6 %rdi, 2, %rsi, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r10, %r12, %r13 mov 3*8(%rcx), %rdx am6 %rdi, 3, %rsi, 0, %r9, %rax, %r11, %rbx, %rbp, %r10, %r8, %r12, %r13 mov 4*8(%rcx), %rdx am6 %rdi, 4, %rsi, 0, %rax, %r11, %rbx, %rbp, %r10, %r8, %r9, %r12, %r13 mov 5*8(%rcx), %rdx am6 %rdi, 5, %rsi, 0, %r11, %rbx, %rbp, %r10, %r8, %r9, %rax, %r12, %r13 mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r10, 8*8(%rdi) mov %r8, 9*8(%rdi) mov %r9, 10*8(%rdi) mov %rax, 11*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_7_1) mov 0*8(%rdx), %rdx m7_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 7*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_7_2) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rsi, 0, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r14 mov 1*8(%rcx), %rdx am7 %rdi, 1, %rsi, 0, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r14 mov %r8, 2*8(%rdi) mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %rax, 8*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_7_3) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rcx), %rdx am7 %rdi, 1, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rcx), %rdx am7 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r14 mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %rax, 9*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_7_4) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rcx), %rdx am7 %rdi, 1, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rcx), %rdx am7 %rdi, 2, %rsi, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r8, %r13, %r14 mov 3*8(%rcx), %rdx am7 %rdi, 3, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %r8, %rax, %r13, %r14 mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r8, 9*8(%rdi) mov %rax, 10*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_7_5) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rcx), %rdx am7 %rdi, 1, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rcx), %rdx am7 %rdi, 2, %rsi, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r9, %r13, %r14 mov 3*8(%rcx), %rdx am7 %rdi, 3, %rsi, 0, %rax, %r10, %r11, %rbx, %rbp, %r12, %r9, %r8, %r13, %r14 mov 4*8(%rcx), %rdx am7 %rdi, 4, %rsi, 0, %r10, %r11, %rbx, %rbp, %r12, %r9, %r8, %rax, %r13, %r14 mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r9, 9*8(%rdi) mov %r8, 10*8(%rdi) mov %rax, 11*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_7_6) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rcx), %rdx am7 %rdi, 1, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rcx), %rdx am7 %rdi, 2, %rsi, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r10, %r13, %r14 mov 3*8(%rcx), %rdx am7 %rdi, 3, %rsi, 0, %r9, %rax, %r11, %rbx, %rbp, %r12, %r10, %r8, %r13, %r14 mov 4*8(%rcx), %rdx am7 %rdi, 4, %rsi, 0, %rax, %r11, %rbx, %rbp, %r12, %r10, %r8, %r9, %r13, %r14 mov 5*8(%rcx), %rdx am7 %rdi, 5, %rsi, 0, %r11, %rbx, %rbp, %r12, %r10, %r8, %r9, %rax, %r13, %r14 mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r10, 9*8(%rdi) mov %r8, 10*8(%rdi) mov %r9, 11*8(%rdi) mov %rax, 12*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_7_7) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rsi, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rcx), %rdx am7 %rdi, 1, %rsi, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rcx), %rdx am7 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r11, %r13, %r14 mov 3*8(%rcx), %rdx am7 %rdi, 3, %rsi, 0, %r9, %r10, %rax, %rbx, %rbp, %r12, %r11, %r8, %r13, %r14 mov 4*8(%rcx), %rdx am7 %rdi, 4, %rsi, 0, %r10, %rax, %rbx, %rbp, %r12, %r11, %r8, %r9, %r13, %r14 mov 5*8(%rcx), %rdx am7 %rdi, 5, %rsi, 0, %rax, %rbx, %rbp, %r12, %r11, %r8, %r9, %r10, %r13, %r14 mov 6*8(%rcx), %rdx am7 %rdi, 6, %rsi, 0, %rbx, %rbp, %r12, %r11, %r8, %r9, %r10, %rax, %r13, %r14 mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r11, 9*8(%rdi) mov %r8, 10*8(%rdi) mov %r9, 11*8(%rdi) mov %r10, 12*8(%rdi) mov %rax, 13*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_1) mov 0*8(%rdx), %rdx m8_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 8*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_2) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rsi, 0, %r13, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r14, %r15 mov 1*8(%rcx), %rdx am8 %rdi, 1, %rsi, 0, %r13, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r14, %r15 mov %r8, 2*8(%rdi) mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %rax, 9*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_3) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rcx), %rdx am8 %rdi, 1, %rsi, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rcx), %rdx am8 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %rax, %r14, %r15 mov %r9, 3*8(%rdi) mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r13, 9*8(%rdi) mov %rax, 10*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_4) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rcx), %rdx am8 %rdi, 1, %rsi, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rcx), %rdx am8 %rdi, 2, %rsi, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r8, %r14, %r15 mov 3*8(%rcx), %rdx am8 %rdi, 3, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r8, %rax, %r14, %r15 mov %r10, 4*8(%rdi) mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r13, 9*8(%rdi) mov %r8, 10*8(%rdi) mov %rax, 11*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_5) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rcx), %rdx am8 %rdi, 1, %rsi, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rcx), %rdx am8 %rdi, 2, %rsi, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r14, %r15 mov 3*8(%rcx), %rdx am8 %rdi, 3, %rsi, 0, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r8, %r14, %r15 mov 4*8(%rcx), %rdx am8 %rdi, 4, %rsi, 0, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r8, %rax, %r14, %r15 mov %r11, 5*8(%rdi) mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r13, 9*8(%rdi) mov %r9, 10*8(%rdi) mov %r8, 11*8(%rdi) mov %rax, 12*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_6) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rcx), %rdx am8 %rdi, 1, %rsi, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rcx), %rdx am8 %rdi, 2, %rsi, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r14, %r15 mov 3*8(%rcx), %rdx am8 %rdi, 3, %rsi, 0, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r14, %r15 mov 4*8(%rcx), %rdx am8 %rdi, 4, %rsi, 0, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r9, %r14, %r15 mov 5*8(%rcx), %rdx am8 %rdi, 5, %rsi, 0, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r9, %rax, %r14, %r15 mov %rbx, 6*8(%rdi) mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r13, 9*8(%rdi) mov %r10, 10*8(%rdi) mov %r8, 11*8(%rdi) mov %r9, 12*8(%rdi) mov %rax, 13*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_7) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rsi, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rcx), %rdx am8 %rdi, 1, %rsi, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rcx), %rdx am8 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r14, %r15 mov 3*8(%rcx), %rdx am8 %rdi, 3, %rsi, 0, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r14, %r15 mov 4*8(%rcx), %rdx am8 %rdi, 4, %rsi, 0, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r14, %r15 mov 5*8(%rcx), %rdx am8 %rdi, 5, %rsi, 0, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r10, %r14, %r15 mov 6*8(%rcx), %rdx am8 %rdi, 6, %rsi, 0, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r10, %rax, %r14, %r15 mov %rbp, 7*8(%rdi) mov %r12, 8*8(%rdi) mov %r13, 9*8(%rdi) mov %r11, 10*8(%rdi) mov %r8, 11*8(%rdi) mov %r9, 12*8(%rdi) mov %r10, 13*8(%rdi) mov %rax, 14*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_8_8) mov %rdx, %rcx mov 0*8(%rcx), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rsi, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rcx), %rdx am8 %rdi, 1, %rsi, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rcx), %rdx am8 %rdi, 2, %rsi, 0, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13, %rbx, %r14, %r15 mov 3*8(%rcx), %rdx am8 %rdi, 3, %rsi, 0, %r9, %r10, %r11, %rax, %rbp, %r12, %r13, %rbx, %r8, %r14, %r15 mov 4*8(%rcx), %rdx am8 %rdi, 4, %rsi, 0, %r10, %r11, %rax, %rbp, %r12, %r13, %rbx, %r8, %r9, %r14, %r15 mov 5*8(%rcx), %rdx am8 %rdi, 5, %rsi, 0, %r11, %rax, %rbp, %r12, %r13, %rbx, %r8, %r9, %r10, %r14, %r15 mov 6*8(%rcx), %rdx am8 %rdi, 6, %rsi, 0, %rax, %rbp, %r12, %r13, %rbx, %r8, %r9, %r10, %r11, %r14, %r15 mov 7*8(%rcx), %rdx am8 %rdi, 7, %rsi, 0, %rbp, %r12, %r13, %rbx, %r8, %r9, %r10, %r11, %rax, %r14, %r15 mov %r12, 8*8(%rdi) mov %r13, 9*8(%rdi) mov %rbx, 10*8(%rdi) mov %r8, 11*8(%rdi) mov %r9, 12*8(%rdi) mov %r10, 13*8(%rdi) mov %r11, 14*8(%rdi) mov %rax, 15*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_1) mov 0*8(%rdx), %rdx m9_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 9*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp mov %rcx, %rdx xor %ebp, %ebp m3 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rax, %rbx, %rbp mov %r8, %rdx am3 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rax, %rbx, %rbp mov %r10, 2*8(%rdi) mov %rcx, %rdx m3_chain %rdi, 3, %rsi, 3, %r11, %rax, %r9, %r10, %rax, %rbx, %r11, %rbp mov %r8, %rdx am3 %rdi, 4, %rsi, 3, %r9, %r10, %rax, %r11, %rbx, %rbp mov %r10, 5*8(%rdi) mov %rcx, %rdx m3_chain %rdi, 6, %rsi, 6, %rax, %r11, %r9, %r10, %r11, %rbx, %rax, %rbp mov %r8, %rdx am3 %rdi, 7, %rsi, 6, %r9, %r10, %r11, %rax, %rbx, %rbp mov %r10, 8*8(%rdi) mov %r11, 9*8(%rdi) mov %rax, 10*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r9, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %rax, %r10, %r9, %r8, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %r10, %r9, %r8, %rax, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %r8, %rax, %r10, %r9, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %rax, %r10, %r9, %r8, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %r10, %r9, %r8, %rax, %r11, %rbx mov %r9, 9*8(%rdi) mov %r8, 10*8(%rdi) mov %rax, 11*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r11, %r8, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %r8, %rax, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %r10, %r11, %r8, %rax, %r9, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %r11, %r8, %rax, %r9, %r10, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %rax, %r9, %r10, %r11, %r8, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %r9, %r10, %r11, %r8, %rax, %rbx, %rbp mov %r10, 9*8(%rdi) mov %r11, 10*8(%rdi) mov %r8, 11*8(%rdi) mov %rax, 12*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %r8, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rax, %r8, %r9, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %r11, %rbx, %rax, %r8, %r9, %r10, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rbx, %rax, %r8, %r9, %r10, %r11, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r9, 9*8(%rdi) mov %r10, 10*8(%rdi) mov %r11, 11*8(%rdi) mov %rbx, 12*8(%rdi) mov %rax, 13*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r8, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rax, %rbp, %r8, %r9, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %r11, %rbx, %rax, %rbp, %r8, %r9, %r10, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rbx, %rax, %rbp, %r8, %r9, %r10, %r11, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rax, %rbp, %r8, %r9, %r10, %r11, %rbx, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov %r8, 9*8(%rdi) mov %r9, 10*8(%rdi) mov %r10, 11*8(%rdi) mov %r11, 12*8(%rdi) mov %rbx, 13*8(%rdi) mov %rax, 14*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %rbp, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %r12, %rbp, %r8, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rax, %r12, %rbp, %r8, %r9, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %r11, %rbx, %rax, %r12, %rbp, %r8, %r9, %r10, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rbx, %rax, %r12, %rbp, %r8, %r9, %r10, %r11, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rax, %r12, %rbp, %r8, %r9, %r10, %r11, %rbx, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %r12, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r13, %r14 mov %rbp, 9*8(%rdi) mov %r8, 10*8(%rdi) mov %r9, 11*8(%rdi) mov %r10, 12*8(%rdi) mov %r11, 13*8(%rdi) mov %rbx, 14*8(%rdi) mov %rax, 15*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_9_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13, %rbp, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %r12, %r13, %rbp, %r8, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rax, %r12, %r13, %rbp, %r8, %r9, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %r11, %rbx, %rax, %r12, %r13, %rbp, %r8, %r9, %r10, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rax, %r12, %r13, %rbp, %r8, %r9, %r10, %r11, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rax, %r12, %r13, %rbp, %r8, %r9, %r10, %r11, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %r12, %r13, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r14, %r15 mov %r13, 9*8(%rdi) mov %rbp, 10*8(%rdi) mov %r8, 11*8(%rdi) mov %r9, 12*8(%rdi) mov %r10, 13*8(%rdi) mov %r11, 14*8(%rdi) mov %rbx, 15*8(%rdi) mov %rax, 16*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_1) mov 0*8(%rdx), %rdx m10_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 10*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp push %r12 mov %rcx, %rdx xor %r12d, %r12d m4 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r8, %rdx am4 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r10, 2*8(%rdi) mov %r11, 3*8(%rdi) mov %rcx, %rdx m4_chain %rdi, 4, %rsi, 4, %rbx, %rax, %r9, %r10, %r11, %rax, %rbp, %rbx, %r12 mov %r8, %rdx am4 %rdi, 5, %rsi, 4, %r9, %r10, %r11, %rax, %rbx, %rbp, %r12 mov %r10, 6*8(%rdi) mov %r11, 7*8(%rdi) mov %rcx, %rdx m2_chain %rdi, 8, %rsi, 8, %rax, %rbx, %r9, %r10, %rbp, %rax, %r12 mov %r8, %rdx am2 %rdi, 9, %rsi, 8, %r9, %r10, %rax, %rbp, %r12 mov %r10, 10*8(%rdi) mov %rax, 11*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r10, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %r9, %rax, %r10, %r8, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %rax, %r10, %r8, %r9, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %r8, %r9, %rax, %r10, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %r9, %rax, %r10, %r8, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %rax, %r10, %r8, %r9, %r11, %rbx mov 9*8(%rsi), %rdx am3 %rdi, 9, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov %r8, 10*8(%rdi) mov %r9, 11*8(%rdi) mov %rax, 12*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r11, %r9, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %rax, %r10, %r11, %r9, %r8, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %r10, %r11, %r9, %r8, %rax, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %r11, %r9, %r8, %rax, %r10, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %r8, %rax, %r10, %r11, %r9, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %rax, %r10, %r11, %r9, %r8, %rbx, %rbp mov 9*8(%rsi), %rdx am4 %rdi, 9, %rcx, 0, %r10, %r11, %r9, %r8, %rax, %rbx, %rbp mov %r11, 10*8(%rdi) mov %r9, 11*8(%rdi) mov %r8, 12*8(%rdi) mov %rax, 13*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %r8, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %r8, %rax, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %r8, %rax, %r9, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %r11, %rbx, %r8, %rax, %r9, %r10, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rbx, %r8, %rax, %r9, %r10, %r11, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %r8, %rbp, %r12 mov 9*8(%rsi), %rdx am5 %rdi, 9, %rcx, 0, %r9, %r10, %r11, %rbx, %r8, %rax, %rbp, %r12 mov %r10, 10*8(%rdi) mov %r11, 11*8(%rdi) mov %rbx, 12*8(%rdi) mov %r8, 13*8(%rdi) mov %rax, 14*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r8, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %rax, %r8, %r9, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %rax, %r8, %r9, %r10, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rbx, %rbp, %rax, %r8, %r9, %r10, %r11, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rbp, %rax, %r8, %r9, %r10, %r11, %rbx, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 9*8(%rsi), %rdx am6 %rdi, 9, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r9, 10*8(%rdi) mov %r10, 11*8(%rdi) mov %r11, 12*8(%rdi) mov %rbx, 13*8(%rdi) mov %rbp, 14*8(%rdi) mov %rax, 15*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r8, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %rax, %r12, %r8, %r9, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %rax, %r12, %r8, %r9, %r10, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rbx, %rbp, %rax, %r12, %r8, %r9, %r10, %r11, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rbp, %rax, %r12, %r8, %r9, %r10, %r11, %rbx, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %rax, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %r13, %r14 mov 9*8(%rsi), %rdx am7 %rdi, 9, %rcx, 0, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r14 mov %r8, 10*8(%rdi) mov %r9, 11*8(%rdi) mov %r10, 12*8(%rdi) mov %r11, 13*8(%rdi) mov %rbx, 14*8(%rdi) mov %rbp, 15*8(%rdi) mov %rax, 16*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_10_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r12, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r12, %r8, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %rax, %r13, %r12, %r8, %r9, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %rax, %r13, %r12, %r8, %r9, %r10, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rbp, %rax, %r13, %r12, %r8, %r9, %r10, %r11, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rbp, %rax, %r13, %r12, %r8, %r9, %r10, %r11, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %rax, %r13, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %r14, %r15 mov 9*8(%rsi), %rdx am8 %rdi, 9, %rcx, 0, %r13, %r12, %r8, %r9, %r10, %r11, %rbx, %rbp, %rax, %r14, %r15 mov %r12, 10*8(%rdi) mov %r8, 11*8(%rdi) mov %r9, 12*8(%rdi) mov %r10, 13*8(%rdi) mov %r11, 14*8(%rdi) mov %rbx, 15*8(%rdi) mov %rbp, 16*8(%rdi) mov %rax, 17*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_1) mov 0*8(%rdx), %rdx m11_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 11*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp push %r12 mov %rcx, %rdx xor %r12d, %r12d m4 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r8, %rdx am4 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r10, 2*8(%rdi) mov %r11, 3*8(%rdi) mov %rcx, %rdx m4_chain %rdi, 4, %rsi, 4, %rbx, %rax, %r9, %r10, %r11, %rax, %rbp, %rbx, %r12 mov %r8, %rdx am4 %rdi, 5, %rsi, 4, %r9, %r10, %r11, %rax, %rbx, %rbp, %r12 mov %r10, 6*8(%rdi) mov %r11, 7*8(%rdi) mov %rcx, %rdx m3_chain %rdi, 8, %rsi, 8, %rax, %rbx, %r9, %r10, %r11, %rbp, %rax, %r12 mov %r8, %rdx am3 %rdi, 9, %rsi, 8, %r9, %r10, %r11, %rax, %rbp, %r12 mov %r10, 10*8(%rdi) mov %r11, 11*8(%rdi) mov %rax, 12*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %r9, %r10, %rax, %r8, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %r10, %rax, %r8, %r9, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %r9, %r10, %rax, %r8, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %r10, %rax, %r8, %r9, %r11, %rbx mov 9*8(%rsi), %rdx am3 %rdi, 9, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 10*8(%rsi), %rdx am3 %rdi, 10, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov %r9, 11*8(%rdi) mov %r10, 12*8(%rdi) mov %rax, 13*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r11, %r10, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %r9, %rax, %r11, %r10, %r8, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %rax, %r11, %r10, %r8, %r9, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %r11, %r10, %r8, %r9, %rax, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %r8, %r9, %rax, %r11, %r10, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %r9, %rax, %r11, %r10, %r8, %rbx, %rbp mov 9*8(%rsi), %rdx am4 %rdi, 9, %rcx, 0, %rax, %r11, %r10, %r8, %r9, %rbx, %rbp mov 10*8(%rsi), %rdx am4 %rdi, 10, %rcx, 0, %r11, %r10, %r8, %r9, %rax, %rbx, %rbp mov %r10, 11*8(%rdi) mov %r8, 12*8(%rdi) mov %r9, 13*8(%rdi) mov %rax, 14*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %r9, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %rax, %r10, %r11, %rbx, %r9, %r8, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %r9, %r8, %rax, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %r11, %rbx, %r9, %r8, %rax, %r10, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rbx, %r9, %r8, %rax, %r10, %r11, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %r9, %rbp, %r12 mov 9*8(%rsi), %rdx am5 %rdi, 9, %rcx, 0, %rax, %r10, %r11, %rbx, %r9, %r8, %rbp, %r12 mov 10*8(%rsi), %rdx am5 %rdi, 10, %rcx, 0, %r10, %r11, %rbx, %r9, %r8, %rax, %rbp, %r12 mov %r11, 11*8(%rdi) mov %rbx, 12*8(%rdi) mov %r9, 13*8(%rdi) mov %r8, 14*8(%rdi) mov %rax, 15*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r8, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r8, %rax, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r8, %rax, %r9, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r8, %rax, %r9, %r10, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rbx, %rbp, %r8, %rax, %r9, %r10, %r11, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rbp, %r8, %rax, %r9, %r10, %r11, %rbx, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 9*8(%rsi), %rdx am6 %rdi, 9, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r8, %r12, %r13 mov 10*8(%rsi), %rdx am6 %rdi, 10, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r8, %rax, %r12, %r13 mov %r10, 11*8(%rdi) mov %r11, 12*8(%rdi) mov %rbx, 13*8(%rdi) mov %rbp, 14*8(%rdi) mov %r8, 15*8(%rdi) mov %rax, 16*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r8, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %rax, %r8, %r9, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %rax, %r8, %r9, %r10, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %rax, %r8, %r9, %r10, %r11, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rbp, %r12, %rax, %r8, %r9, %r10, %r11, %rbx, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %r12, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r13, %r14 mov 9*8(%rsi), %rdx am7 %rdi, 9, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 10*8(%rsi), %rdx am7 %rdi, 10, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r14 mov %r9, 11*8(%rdi) mov %r10, 12*8(%rdi) mov %r11, 13*8(%rdi) mov %rbx, 14*8(%rdi) mov %rbp, 15*8(%rdi) mov %r12, 16*8(%rdi) mov %rax, 17*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_11_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %r13, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %r13, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r8, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r8, %r9, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %rax, %r13, %r8, %r9, %r10, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %rax, %r13, %r8, %r9, %r10, %r11, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rbp, %r12, %rax, %r13, %r8, %r9, %r10, %r11, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %r12, %rax, %r13, %r8, %r9, %r10, %r11, %rbx, %rbp, %r14, %r15 mov 9*8(%rsi), %rdx am8 %rdi, 9, %rcx, 0, %rax, %r13, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r14, %r15 mov 10*8(%rsi), %rdx am8 %rdi, 10, %rcx, 0, %r13, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r14, %r15 mov %r8, 11*8(%rdi) mov %r9, 12*8(%rdi) mov %r10, 13*8(%rdi) mov %r11, 14*8(%rdi) mov %rbx, 15*8(%rdi) mov %rbp, 16*8(%rdi) mov %r12, 17*8(%rdi) mov %rax, 18*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_1) mov 0*8(%rdx), %rdx m12_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 12*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp push %r12 mov %rcx, %rdx xor %r12d, %r12d m4 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r8, %rdx am4 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r10, 2*8(%rdi) mov %r11, 3*8(%rdi) mov %rcx, %rdx m4_chain %rdi, 4, %rsi, 4, %rbx, %rax, %r9, %r10, %r11, %rax, %rbp, %rbx, %r12 mov %r8, %rdx am4 %rdi, 5, %rsi, 4, %r9, %r10, %r11, %rax, %rbx, %rbp, %r12 mov %r10, 6*8(%rdi) mov %r11, 7*8(%rdi) mov %rcx, %rdx m4_chain %rdi, 8, %rsi, 8, %rax, %rbx, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12 mov %r8, %rdx am4 %rdi, 9, %rsi, 8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r10, 10*8(%rdi) mov %r11, 11*8(%rdi) mov %rbx, 12*8(%rdi) mov %rax, 13*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r8, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %r9, %r10, %r8, %rax, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %r10, %r8, %rax, %r9, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %rax, %r9, %r10, %r8, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %r9, %r10, %r8, %rax, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %r10, %r8, %rax, %r9, %r11, %rbx mov 9*8(%rsi), %rdx am3 %rdi, 9, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 10*8(%rsi), %rdx am3 %rdi, 10, %rcx, 0, %rax, %r9, %r10, %r8, %r11, %rbx mov 11*8(%rsi), %rdx am3 %rdi, 11, %rcx, 0, %r9, %r10, %r8, %rax, %r11, %rbx mov %r10, 12*8(%rdi) mov %r8, 13*8(%rdi) mov %rax, 14*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %r9, %r10, %rax, %r11, %r8, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %r10, %rax, %r11, %r8, %r9, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %rax, %r11, %r8, %r9, %r10, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %r9, %r10, %rax, %r11, %r8, %rbx, %rbp mov 9*8(%rsi), %rdx am4 %rdi, 9, %rcx, 0, %r10, %rax, %r11, %r8, %r9, %rbx, %rbp mov 10*8(%rsi), %rdx am4 %rdi, 10, %rcx, 0, %rax, %r11, %r8, %r9, %r10, %rbx, %rbp mov 11*8(%rsi), %rdx am4 %rdi, 11, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp mov %r8, 12*8(%rdi) mov %r9, 13*8(%rdi) mov %r10, 14*8(%rdi) mov %rax, 15*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %r10, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %r9, %rax, %r11, %rbx, %r10, %r8, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %rax, %r11, %rbx, %r10, %r8, %r9, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %r11, %rbx, %r10, %r8, %r9, %rax, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rbx, %r10, %r8, %r9, %rax, %r11, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %r10, %rbp, %r12 mov 9*8(%rsi), %rdx am5 %rdi, 9, %rcx, 0, %r9, %rax, %r11, %rbx, %r10, %r8, %rbp, %r12 mov 10*8(%rsi), %rdx am5 %rdi, 10, %rcx, 0, %rax, %r11, %rbx, %r10, %r8, %r9, %rbp, %r12 mov 11*8(%rsi), %rdx am5 %rdi, 11, %rcx, 0, %r11, %rbx, %r10, %r8, %r9, %rax, %rbp, %r12 mov %rbx, 12*8(%rdi) mov %r10, 13*8(%rdi) mov %r8, 14*8(%rdi) mov %r9, 15*8(%rdi) mov %rax, 16*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r9, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %rax, %r10, %r11, %rbx, %rbp, %r9, %r8, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r9, %r8, %rax, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r9, %r8, %rax, %r10, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rbx, %rbp, %r9, %r8, %rax, %r10, %r11, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rbp, %r9, %r8, %rax, %r10, %r11, %rbx, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13 mov 9*8(%rsi), %rdx am6 %rdi, 9, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r9, %r12, %r13 mov 10*8(%rsi), %rdx am6 %rdi, 10, %rcx, 0, %rax, %r10, %r11, %rbx, %rbp, %r9, %r8, %r12, %r13 mov 11*8(%rsi), %rdx am6 %rdi, 11, %rcx, 0, %r10, %r11, %rbx, %rbp, %r9, %r8, %rax, %r12, %r13 mov %r11, 12*8(%rdi) mov %rbx, 13*8(%rdi) mov %rbp, 14*8(%rdi) mov %r9, 15*8(%rdi) mov %r8, 16*8(%rdi) mov %rax, 17*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r8, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %r8, %rax, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %r8, %rax, %r9, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %r8, %rax, %r9, %r10, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r8, %rax, %r9, %r10, %r11, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rbp, %r12, %r8, %rax, %r9, %r10, %r11, %rbx, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %r12, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r13, %r14 mov 9*8(%rsi), %rdx am7 %rdi, 9, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 10*8(%rsi), %rdx am7 %rdi, 10, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r8, %r13, %r14 mov 11*8(%rsi), %rdx am7 %rdi, 11, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %r8, %rax, %r13, %r14 mov %r10, 12*8(%rdi) mov %r11, 13*8(%rdi) mov %rbx, 14*8(%rdi) mov %rbp, 15*8(%rdi) mov %r12, 16*8(%rdi) mov %r8, 17*8(%rdi) mov %rax, 18*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_12_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %rax, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %rax, %r8, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %r13, %rax, %r8, %r9, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %r13, %rax, %r8, %r9, %r10, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r13, %rax, %r8, %r9, %r10, %r11, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rbp, %r12, %r13, %rax, %r8, %r9, %r10, %r11, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %r12, %r13, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r14, %r15 mov 9*8(%rsi), %rdx am8 %rdi, 9, %rcx, 0, %r13, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r14, %r15 mov 10*8(%rsi), %rdx am8 %rdi, 10, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 11*8(%rsi), %rdx am8 %rdi, 11, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %rax, %r14, %r15 mov %r9, 12*8(%rdi) mov %r10, 13*8(%rdi) mov %r11, 14*8(%rdi) mov %rbx, 15*8(%rdi) mov %rbp, 16*8(%rdi) mov %r12, 17*8(%rdi) mov %r13, 18*8(%rdi) mov %rax, 19*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_1) mov 0*8(%rdx), %rdx m13_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 13*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp push %r12 push %r13 mov %rcx, %rdx xor %r13d, %r13d m5 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r8, %rdx am5 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r10, 2*8(%rdi) mov %r11, 3*8(%rdi) mov %rbx, 4*8(%rdi) mov %rcx, %rdx m5_chain %rdi, 5, %rsi, 5, %rbp, %rax, %r9, %r10, %r11, %rbx, %rax, %r12, %rbp, %r13 mov %r8, %rdx am5 %rdi, 6, %rsi, 5, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12, %r13 mov %r10, 7*8(%rdi) mov %r11, 8*8(%rdi) mov %rbx, 9*8(%rdi) mov %rcx, %rdx m3_chain %rdi, 10, %rsi, 10, %rax, %rbp, %r9, %r10, %r11, %r12, %rax, %r13 mov %r8, %rdx am3 %rdi, 11, %rsi, 10, %r9, %r10, %r11, %rax, %r12, %r13 mov %r10, 12*8(%rdi) mov %r11, 13*8(%rdi) mov %rax, 14*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r9, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %rax, %r10, %r9, %r8, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %r10, %r9, %r8, %rax, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %r8, %rax, %r10, %r9, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %rax, %r10, %r9, %r8, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %r10, %r9, %r8, %rax, %r11, %rbx mov 9*8(%rsi), %rdx am3 %rdi, 9, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx mov 10*8(%rsi), %rdx am3 %rdi, 10, %rcx, 0, %r8, %rax, %r10, %r9, %r11, %rbx mov 11*8(%rsi), %rdx am3 %rdi, 11, %rcx, 0, %rax, %r10, %r9, %r8, %r11, %rbx mov 12*8(%rsi), %rdx am3 %rdi, 12, %rcx, 0, %r10, %r9, %r8, %rax, %r11, %rbx mov %r9, 13*8(%rdi) mov %r8, 14*8(%rdi) mov %rax, 15*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rax, %r8, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %r10, %r11, %rax, %r8, %r9, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %r11, %rax, %r8, %r9, %r10, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %r9, %r10, %r11, %rax, %r8, %rbx, %rbp mov 9*8(%rsi), %rdx am4 %rdi, 9, %rcx, 0, %r10, %r11, %rax, %r8, %r9, %rbx, %rbp mov 10*8(%rsi), %rdx am4 %rdi, 10, %rcx, 0, %r11, %rax, %r8, %r9, %r10, %rbx, %rbp mov 11*8(%rsi), %rdx am4 %rdi, 11, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp mov 12*8(%rsi), %rdx am4 %rdi, 12, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbx, %rbp mov %r9, 13*8(%rdi) mov %r10, 14*8(%rdi) mov %r11, 15*8(%rdi) mov %rax, 16*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %r11, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %r9, %r10, %rax, %rbx, %r11, %r8, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %r10, %rax, %rbx, %r11, %r8, %r9, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %rax, %rbx, %r11, %r8, %r9, %r10, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rbx, %r11, %r8, %r9, %r10, %rax, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %r11, %rbp, %r12 mov 9*8(%rsi), %rdx am5 %rdi, 9, %rcx, 0, %r9, %r10, %rax, %rbx, %r11, %r8, %rbp, %r12 mov 10*8(%rsi), %rdx am5 %rdi, 10, %rcx, 0, %r10, %rax, %rbx, %r11, %r8, %r9, %rbp, %r12 mov 11*8(%rsi), %rdx am5 %rdi, 11, %rcx, 0, %rax, %rbx, %r11, %r8, %r9, %r10, %rbp, %r12 mov 12*8(%rsi), %rdx am5 %rdi, 12, %rcx, 0, %rbx, %r11, %r8, %r9, %r10, %rax, %rbp, %r12 mov %r11, 13*8(%rdi) mov %r8, 14*8(%rdi) mov %r9, 15*8(%rdi) mov %r10, 16*8(%rdi) mov %rax, 17*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r10, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %r9, %rax, %r11, %rbx, %rbp, %r10, %r8, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %rax, %r11, %rbx, %rbp, %r10, %r8, %r9, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r10, %r8, %r9, %rax, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rbx, %rbp, %r10, %r8, %r9, %rax, %r11, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rbp, %r10, %r8, %r9, %rax, %r11, %rbx, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13 mov 9*8(%rsi), %rdx am6 %rdi, 9, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r10, %r12, %r13 mov 10*8(%rsi), %rdx am6 %rdi, 10, %rcx, 0, %r9, %rax, %r11, %rbx, %rbp, %r10, %r8, %r12, %r13 mov 11*8(%rsi), %rdx am6 %rdi, 11, %rcx, 0, %rax, %r11, %rbx, %rbp, %r10, %r8, %r9, %r12, %r13 mov 12*8(%rsi), %rdx am6 %rdi, 12, %rcx, 0, %r11, %rbx, %rbp, %r10, %r8, %r9, %rax, %r12, %r13 mov %rbx, 13*8(%rdi) mov %rbp, 14*8(%rdi) mov %r10, 15*8(%rdi) mov %r8, 16*8(%rdi) mov %r9, 17*8(%rdi) mov %rax, 18*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r9, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %rax, %r10, %r11, %rbx, %rbp, %r12, %r9, %r8, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %r9, %r8, %rax, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %r9, %r8, %rax, %r10, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r9, %r8, %rax, %r10, %r11, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rbp, %r12, %r9, %r8, %rax, %r10, %r11, %rbx, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %r12, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r13, %r14 mov 9*8(%rsi), %rdx am7 %rdi, 9, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 10*8(%rsi), %rdx am7 %rdi, 10, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r9, %r13, %r14 mov 11*8(%rsi), %rdx am7 %rdi, 11, %rcx, 0, %rax, %r10, %r11, %rbx, %rbp, %r12, %r9, %r8, %r13, %r14 mov 12*8(%rsi), %rdx am7 %rdi, 12, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %r9, %r8, %rax, %r13, %r14 mov %r11, 13*8(%rdi) mov %rbx, 14*8(%rdi) mov %rbp, 15*8(%rdi) mov %r12, 16*8(%rdi) mov %r9, 17*8(%rdi) mov %r8, 18*8(%rdi) mov %rax, 19*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_13_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r8, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r8, %rax, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %r13, %r8, %rax, %r9, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %r13, %r8, %rax, %r9, %r10, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r13, %r8, %rax, %r9, %r10, %r11, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rbp, %r12, %r13, %r8, %rax, %r9, %r10, %r11, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %r12, %r13, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r14, %r15 mov 9*8(%rsi), %rdx am8 %rdi, 9, %rcx, 0, %r13, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r14, %r15 mov 10*8(%rsi), %rdx am8 %rdi, 10, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 11*8(%rsi), %rdx am8 %rdi, 11, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r8, %r14, %r15 mov 12*8(%rsi), %rdx am8 %rdi, 12, %rcx, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %r13, %r8, %rax, %r14, %r15 mov %r10, 13*8(%rdi) mov %r11, 14*8(%rdi) mov %rbx, 15*8(%rdi) mov %rbp, 16*8(%rdi) mov %r12, 17*8(%rdi) mov %r13, 18*8(%rdi) mov %r8, 19*8(%rdi) mov %rax, 20*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_1) mov 0*8(%rdx), %rdx m14_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 14*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp push %r12 push %r13 mov %rcx, %rdx xor %r13d, %r13d m5 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r8, %rdx am5 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r10, 2*8(%rdi) mov %r11, 3*8(%rdi) mov %rbx, 4*8(%rdi) mov %rcx, %rdx m5_chain %rdi, 5, %rsi, 5, %rbp, %rax, %r9, %r10, %r11, %rbx, %rax, %r12, %rbp, %r13 mov %r8, %rdx am5 %rdi, 6, %rsi, 5, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12, %r13 mov %r10, 7*8(%rdi) mov %r11, 8*8(%rdi) mov %rbx, 9*8(%rdi) mov %rcx, %rdx m4_chain %rdi, 10, %rsi, 10, %rax, %rbp, %r9, %r10, %r11, %rbx, %r12, %rax, %r13 mov %r8, %rdx am4 %rdi, 11, %rsi, 10, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov %r10, 12*8(%rdi) mov %r11, 13*8(%rdi) mov %rbx, 14*8(%rdi) mov %rax, 15*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r10, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %r9, %rax, %r10, %r8, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %rax, %r10, %r8, %r9, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %r8, %r9, %rax, %r10, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %r9, %rax, %r10, %r8, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %rax, %r10, %r8, %r9, %r11, %rbx mov 9*8(%rsi), %rdx am3 %rdi, 9, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov 10*8(%rsi), %rdx am3 %rdi, 10, %rcx, 0, %r8, %r9, %rax, %r10, %r11, %rbx mov 11*8(%rsi), %rdx am3 %rdi, 11, %rcx, 0, %r9, %rax, %r10, %r8, %r11, %rbx mov 12*8(%rsi), %rdx am3 %rdi, 12, %rcx, 0, %rax, %r10, %r8, %r9, %r11, %rbx mov 13*8(%rsi), %rdx am3 %rdi, 13, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx mov %r8, 14*8(%rdi) mov %r9, 15*8(%rdi) mov %rax, 16*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r11, %r8, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %r8, %rax, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %r10, %r11, %r8, %rax, %r9, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %r11, %r8, %rax, %r9, %r10, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %rax, %r9, %r10, %r11, %r8, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %r9, %r10, %r11, %r8, %rax, %rbx, %rbp mov 9*8(%rsi), %rdx am4 %rdi, 9, %rcx, 0, %r10, %r11, %r8, %rax, %r9, %rbx, %rbp mov 10*8(%rsi), %rdx am4 %rdi, 10, %rcx, 0, %r11, %r8, %rax, %r9, %r10, %rbx, %rbp mov 11*8(%rsi), %rdx am4 %rdi, 11, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp mov 12*8(%rsi), %rdx am4 %rdi, 12, %rcx, 0, %rax, %r9, %r10, %r11, %r8, %rbx, %rbp mov 13*8(%rsi), %rdx am4 %rdi, 13, %rcx, 0, %r9, %r10, %r11, %r8, %rax, %rbx, %rbp mov %r10, 14*8(%rdi) mov %r11, 15*8(%rdi) mov %r8, 16*8(%rdi) mov %rax, 17*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbx, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rax, %rbx, %r8, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %r10, %r11, %rax, %rbx, %r8, %r9, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %r11, %rax, %rbx, %r8, %r9, %r10, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rax, %rbx, %r8, %r9, %r10, %r11, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbx, %rbp, %r12 mov 9*8(%rsi), %rdx am5 %rdi, 9, %rcx, 0, %r9, %r10, %r11, %rax, %rbx, %r8, %rbp, %r12 mov 10*8(%rsi), %rdx am5 %rdi, 10, %rcx, 0, %r10, %r11, %rax, %rbx, %r8, %r9, %rbp, %r12 mov 11*8(%rsi), %rdx am5 %rdi, 11, %rcx, 0, %r11, %rax, %rbx, %r8, %r9, %r10, %rbp, %r12 mov 12*8(%rsi), %rdx am5 %rdi, 12, %rcx, 0, %rax, %rbx, %r8, %r9, %r10, %r11, %rbp, %r12 mov 13*8(%rsi), %rdx am5 %rdi, 13, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12 mov %r8, 14*8(%rdi) mov %r9, 15*8(%rdi) mov %r10, 16*8(%rdi) mov %r11, 17*8(%rdi) mov %rax, 18*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r11, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %r9, %r10, %rax, %rbx, %rbp, %r11, %r8, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %r10, %rax, %rbx, %rbp, %r11, %r8, %r9, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %rax, %rbx, %rbp, %r11, %r8, %r9, %r10, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rbx, %rbp, %r11, %r8, %r9, %r10, %rax, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rbp, %r11, %r8, %r9, %r10, %rax, %rbx, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13 mov 9*8(%rsi), %rdx am6 %rdi, 9, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r11, %r12, %r13 mov 10*8(%rsi), %rdx am6 %rdi, 10, %rcx, 0, %r9, %r10, %rax, %rbx, %rbp, %r11, %r8, %r12, %r13 mov 11*8(%rsi), %rdx am6 %rdi, 11, %rcx, 0, %r10, %rax, %rbx, %rbp, %r11, %r8, %r9, %r12, %r13 mov 12*8(%rsi), %rdx am6 %rdi, 12, %rcx, 0, %rax, %rbx, %rbp, %r11, %r8, %r9, %r10, %r12, %r13 mov 13*8(%rsi), %rdx am6 %rdi, 13, %rcx, 0, %rbx, %rbp, %r11, %r8, %r9, %r10, %rax, %r12, %r13 mov %rbp, 14*8(%rdi) mov %r11, 15*8(%rdi) mov %r8, 16*8(%rdi) mov %r9, 17*8(%rdi) mov %r10, 18*8(%rdi) mov %rax, 19*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r10, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %r9, %rax, %r11, %rbx, %rbp, %r12, %r10, %r8, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %rax, %r11, %rbx, %rbp, %r12, %r10, %r8, %r9, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %r10, %r8, %r9, %rax, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r10, %r8, %r9, %rax, %r11, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rbp, %r12, %r10, %r8, %r9, %rax, %r11, %rbx, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %r12, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r13, %r14 mov 9*8(%rsi), %rdx am7 %rdi, 9, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14 mov 10*8(%rsi), %rdx am7 %rdi, 10, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r10, %r13, %r14 mov 11*8(%rsi), %rdx am7 %rdi, 11, %rcx, 0, %r9, %rax, %r11, %rbx, %rbp, %r12, %r10, %r8, %r13, %r14 mov 12*8(%rsi), %rdx am7 %rdi, 12, %rcx, 0, %rax, %r11, %rbx, %rbp, %r12, %r10, %r8, %r9, %r13, %r14 mov 13*8(%rsi), %rdx am7 %rdi, 13, %rcx, 0, %r11, %rbx, %rbp, %r12, %r10, %r8, %r9, %rax, %r13, %r14 mov %rbx, 14*8(%rdi) mov %rbp, 15*8(%rdi) mov %r12, 16*8(%rdi) mov %r10, 17*8(%rdi) mov %r8, 18*8(%rdi) mov %r9, 19*8(%rdi) mov %rax, 20*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_14_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r8, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r8, %rax, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %r13, %r9, %r8, %rax, %r10, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r13, %r9, %r8, %rax, %r10, %r11, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rbp, %r12, %r13, %r9, %r8, %rax, %r10, %r11, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %r12, %r13, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r14, %r15 mov 9*8(%rsi), %rdx am8 %rdi, 9, %rcx, 0, %r13, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r14, %r15 mov 10*8(%rsi), %rdx am8 %rdi, 10, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 11*8(%rsi), %rdx am8 %rdi, 11, %rcx, 0, %r8, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r14, %r15 mov 12*8(%rsi), %rdx am8 %rdi, 12, %rcx, 0, %rax, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r8, %r14, %r15 mov 13*8(%rsi), %rdx am8 %rdi, 13, %rcx, 0, %r10, %r11, %rbx, %rbp, %r12, %r13, %r9, %r8, %rax, %r14, %r15 mov %r11, 14*8(%rdi) mov %rbx, 15*8(%rdi) mov %rbp, 16*8(%rdi) mov %r12, 17*8(%rdi) mov %r13, 18*8(%rdi) mov %r9, 19*8(%rdi) mov %r8, 20*8(%rdi) mov %rax, 21*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_1) mov 0*8(%rdx), %rdx m15_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 15*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp push %r12 push %r13 mov %rcx, %rdx xor %r13d, %r13d m5 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r8, %rdx am5 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r10, 2*8(%rdi) mov %r11, 3*8(%rdi) mov %rbx, 4*8(%rdi) mov %rcx, %rdx m5_chain %rdi, 5, %rsi, 5, %rbp, %rax, %r9, %r10, %r11, %rbx, %rax, %r12, %rbp, %r13 mov %r8, %rdx am5 %rdi, 6, %rsi, 5, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12, %r13 mov %r10, 7*8(%rdi) mov %r11, 8*8(%rdi) mov %rbx, 9*8(%rdi) mov %rcx, %rdx m5_chain %rdi, 10, %rsi, 10, %rax, %rbp, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13 mov %r8, %rdx am5 %rdi, 11, %rsi, 10, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13 mov %r10, 12*8(%rdi) mov %r11, 13*8(%rdi) mov %rbx, 14*8(%rdi) mov %rbp, 15*8(%rdi) mov %rax, 16*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %r9, %r10, %rax, %r8, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %r10, %rax, %r8, %r9, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %r9, %r10, %rax, %r8, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %r10, %rax, %r8, %r9, %r11, %rbx mov 9*8(%rsi), %rdx am3 %rdi, 9, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 10*8(%rsi), %rdx am3 %rdi, 10, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov 11*8(%rsi), %rdx am3 %rdi, 11, %rcx, 0, %r9, %r10, %rax, %r8, %r11, %rbx mov 12*8(%rsi), %rdx am3 %rdi, 12, %rcx, 0, %r10, %rax, %r8, %r9, %r11, %rbx mov 13*8(%rsi), %rdx am3 %rdi, 13, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx mov 14*8(%rsi), %rdx am3 %rdi, 14, %rcx, 0, %r8, %r9, %r10, %rax, %r11, %rbx mov %r9, 15*8(%rdi) mov %r10, 16*8(%rdi) mov %rax, 17*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %r8, %rax, %r10, %r11, %r9, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %rax, %r10, %r11, %r9, %r8, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %r10, %r11, %r9, %r8, %rax, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %r11, %r9, %r8, %rax, %r10, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %r8, %rax, %r10, %r11, %r9, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %rax, %r10, %r11, %r9, %r8, %rbx, %rbp mov 9*8(%rsi), %rdx am4 %rdi, 9, %rcx, 0, %r10, %r11, %r9, %r8, %rax, %rbx, %rbp mov 10*8(%rsi), %rdx am4 %rdi, 10, %rcx, 0, %r11, %r9, %r8, %rax, %r10, %rbx, %rbp mov 11*8(%rsi), %rdx am4 %rdi, 11, %rcx, 0, %r9, %r8, %rax, %r10, %r11, %rbx, %rbp mov 12*8(%rsi), %rdx am4 %rdi, 12, %rcx, 0, %r8, %rax, %r10, %r11, %r9, %rbx, %rbp mov 13*8(%rsi), %rdx am4 %rdi, 13, %rcx, 0, %rax, %r10, %r11, %r9, %r8, %rbx, %rbp mov 14*8(%rsi), %rdx am4 %rdi, 14, %rcx, 0, %r10, %r11, %r9, %r8, %rax, %rbx, %rbp mov %r11, 15*8(%rdi) mov %r9, 16*8(%rdi) mov %r8, 17*8(%rdi) mov %rax, 18*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %r8, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rax, %r8, %r9, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %r11, %rbx, %rax, %r8, %r9, %r10, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rbx, %rax, %r8, %r9, %r10, %r11, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov 9*8(%rsi), %rdx am5 %rdi, 9, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %r8, %rbp, %r12 mov 10*8(%rsi), %rdx am5 %rdi, 10, %rcx, 0, %r10, %r11, %rbx, %rax, %r8, %r9, %rbp, %r12 mov 11*8(%rsi), %rdx am5 %rdi, 11, %rcx, 0, %r11, %rbx, %rax, %r8, %r9, %r10, %rbp, %r12 mov 12*8(%rsi), %rdx am5 %rdi, 12, %rcx, 0, %rbx, %rax, %r8, %r9, %r10, %r11, %rbp, %r12 mov 13*8(%rsi), %rdx am5 %rdi, 13, %rcx, 0, %rax, %r8, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 14*8(%rsi), %rdx am5 %rdi, 14, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12 mov %r9, 15*8(%rdi) mov %r10, 16*8(%rdi) mov %r11, 17*8(%rdi) mov %rbx, 18*8(%rdi) mov %rax, 19*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbp, %rbx, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rax, %rbp, %rbx, %r8, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %r10, %r11, %rax, %rbp, %rbx, %r8, %r9, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %r11, %rax, %rbp, %rbx, %r8, %r9, %r10, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rax, %rbp, %rbx, %r8, %r9, %r10, %r11, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rbp, %rbx, %r8, %r9, %r10, %r11, %rax, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13 mov 9*8(%rsi), %rdx am6 %rdi, 9, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbp, %rbx, %r12, %r13 mov 10*8(%rsi), %rdx am6 %rdi, 10, %rcx, 0, %r9, %r10, %r11, %rax, %rbp, %rbx, %r8, %r12, %r13 mov 11*8(%rsi), %rdx am6 %rdi, 11, %rcx, 0, %r10, %r11, %rax, %rbp, %rbx, %r8, %r9, %r12, %r13 mov 12*8(%rsi), %rdx am6 %rdi, 12, %rcx, 0, %r11, %rax, %rbp, %rbx, %r8, %r9, %r10, %r12, %r13 mov 13*8(%rsi), %rdx am6 %rdi, 13, %rcx, 0, %rax, %rbp, %rbx, %r8, %r9, %r10, %r11, %r12, %r13 mov 14*8(%rsi), %rdx am6 %rdi, 14, %rcx, 0, %rbp, %rbx, %r8, %r9, %r10, %r11, %rax, %r12, %r13 mov %rbx, 15*8(%rdi) mov %r8, 16*8(%rdi) mov %r9, 17*8(%rdi) mov %r10, 18*8(%rdi) mov %r11, 19*8(%rdi) mov %rax, 20*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r11, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %r9, %r10, %rax, %rbx, %rbp, %r12, %r11, %r8, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %r10, %rax, %rbx, %rbp, %r12, %r11, %r8, %r9, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %rax, %rbx, %rbp, %r12, %r11, %r8, %r9, %r10, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r11, %r8, %r9, %r10, %rax, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rbp, %r12, %r11, %r8, %r9, %r10, %rax, %rbx, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %r12, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r13, %r14 mov 9*8(%rsi), %rdx am7 %rdi, 9, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14 mov 10*8(%rsi), %rdx am7 %rdi, 10, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r11, %r13, %r14 mov 11*8(%rsi), %rdx am7 %rdi, 11, %rcx, 0, %r9, %r10, %rax, %rbx, %rbp, %r12, %r11, %r8, %r13, %r14 mov 12*8(%rsi), %rdx am7 %rdi, 12, %rcx, 0, %r10, %rax, %rbx, %rbp, %r12, %r11, %r8, %r9, %r13, %r14 mov 13*8(%rsi), %rdx am7 %rdi, 13, %rcx, 0, %rax, %rbx, %rbp, %r12, %r11, %r8, %r9, %r10, %r13, %r14 mov 14*8(%rsi), %rdx am7 %rdi, 14, %rcx, 0, %rbx, %rbp, %r12, %r11, %r8, %r9, %r10, %rax, %r13, %r14 mov %rbp, 15*8(%rdi) mov %r12, 16*8(%rdi) mov %r11, 17*8(%rdi) mov %r8, 18*8(%rdi) mov %r9, 19*8(%rdi) mov %r10, 20*8(%rdi) mov %rax, 21*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_15_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r9, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r9, %rax, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r13, %r10, %r8, %r9, %rax, %r11, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rbp, %r12, %r13, %r10, %r8, %r9, %rax, %r11, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %r12, %r13, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r14, %r15 mov 9*8(%rsi), %rdx am8 %rdi, 9, %rcx, 0, %r13, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r14, %r15 mov 10*8(%rsi), %rdx am8 %rdi, 10, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 11*8(%rsi), %rdx am8 %rdi, 11, %rcx, 0, %r8, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r14, %r15 mov 12*8(%rsi), %rdx am8 %rdi, 12, %rcx, 0, %r9, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r14, %r15 mov 13*8(%rsi), %rdx am8 %rdi, 13, %rcx, 0, %rax, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r9, %r14, %r15 mov 14*8(%rsi), %rdx am8 %rdi, 14, %rcx, 0, %r11, %rbx, %rbp, %r12, %r13, %r10, %r8, %r9, %rax, %r14, %r15 mov %rbx, 15*8(%rdi) mov %rbp, 16*8(%rdi) mov %r12, 17*8(%rdi) mov %r13, 18*8(%rdi) mov %r10, 19*8(%rdi) mov %r8, 20*8(%rdi) mov %r9, 21*8(%rdi) mov %rax, 22*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_1) mov 0*8(%rdx), %rdx m16_str %rdi, 0, %rsi, 0, %rcx, %r8, %r9, %r10, %r11, %rax mov %rax, 16*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_2) mov 0*8(%rdx), %rcx mov 1*8(%rdx), %r8 push %rbx push %rbp push %r12 push %r13 push %r14 mov %rcx, %rdx xor %r14d, %r14d m6 %rdi, 0, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r14 mov %r8, %rdx am6 %rdi, 1, %rsi, 0, %r9, %r10, %r11, %rbx, %rbp, %r12, %rax, %r13, %r14 mov %r10, 2*8(%rdi) mov %r11, 3*8(%rdi) mov %rbx, 4*8(%rdi) mov %rbp, 5*8(%rdi) mov %rcx, %rdx m6_chain %rdi, 6, %rsi, 6, %r12, %rax, %r9, %r10, %r11, %rbx, %rbp, %rax, %r13, %r12, %r14 mov %r8, %rdx am6 %rdi, 7, %rsi, 6, %r9, %r10, %r11, %rbx, %rbp, %rax, %r12, %r13, %r14 mov %r10, 8*8(%rdi) mov %r11, 9*8(%rdi) mov %rbx, 10*8(%rdi) mov %rbp, 11*8(%rdi) mov %rcx, %rdx m4_chain %rdi, 12, %rsi, 12, %rax, %r12, %r9, %r10, %r11, %rbx, %r13, %rax, %r14 mov %r8, %rdx am4 %rdi, 13, %rsi, 12, %r9, %r10, %r11, %rbx, %rax, %r13, %r14 mov %r10, 14*8(%rdi) mov %r11, 15*8(%rdi) mov %rbx, 16*8(%rdi) mov %rax, 17*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_3) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx xor %ebx, %ebx m3 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 1*8(%rsi), %rdx am3 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 2*8(%rsi), %rdx am3 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r8, %r11, %rbx mov 3*8(%rsi), %rdx am3 %rdi, 3, %rcx, 0, %r9, %r10, %r8, %rax, %r11, %rbx mov 4*8(%rsi), %rdx am3 %rdi, 4, %rcx, 0, %r10, %r8, %rax, %r9, %r11, %rbx mov 5*8(%rsi), %rdx am3 %rdi, 5, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 6*8(%rsi), %rdx am3 %rdi, 6, %rcx, 0, %rax, %r9, %r10, %r8, %r11, %rbx mov 7*8(%rsi), %rdx am3 %rdi, 7, %rcx, 0, %r9, %r10, %r8, %rax, %r11, %rbx mov 8*8(%rsi), %rdx am3 %rdi, 8, %rcx, 0, %r10, %r8, %rax, %r9, %r11, %rbx mov 9*8(%rsi), %rdx am3 %rdi, 9, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 10*8(%rsi), %rdx am3 %rdi, 10, %rcx, 0, %rax, %r9, %r10, %r8, %r11, %rbx mov 11*8(%rsi), %rdx am3 %rdi, 11, %rcx, 0, %r9, %r10, %r8, %rax, %r11, %rbx mov 12*8(%rsi), %rdx am3 %rdi, 12, %rcx, 0, %r10, %r8, %rax, %r9, %r11, %rbx mov 13*8(%rsi), %rdx am3 %rdi, 13, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx mov 14*8(%rsi), %rdx am3 %rdi, 14, %rcx, 0, %rax, %r9, %r10, %r8, %r11, %rbx mov 15*8(%rsi), %rdx am3 %rdi, 15, %rcx, 0, %r9, %r10, %r8, %rax, %r11, %rbx mov %r10, 16*8(%rdi) mov %r8, 17*8(%rdi) mov %rax, 18*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_4) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp xor %ebp, %ebp m4 %rdi, 0, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp mov 1*8(%rsi), %rdx am4 %rdi, 1, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp mov 2*8(%rsi), %rdx am4 %rdi, 2, %rcx, 0, %r8, %r9, %rax, %r11, %r10, %rbx, %rbp mov 3*8(%rsi), %rdx am4 %rdi, 3, %rcx, 0, %r9, %rax, %r11, %r10, %r8, %rbx, %rbp mov 4*8(%rsi), %rdx am4 %rdi, 4, %rcx, 0, %rax, %r11, %r10, %r8, %r9, %rbx, %rbp mov 5*8(%rsi), %rdx am4 %rdi, 5, %rcx, 0, %r11, %r10, %r8, %r9, %rax, %rbx, %rbp mov 6*8(%rsi), %rdx am4 %rdi, 6, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp mov 7*8(%rsi), %rdx am4 %rdi, 7, %rcx, 0, %r8, %r9, %rax, %r11, %r10, %rbx, %rbp mov 8*8(%rsi), %rdx am4 %rdi, 8, %rcx, 0, %r9, %rax, %r11, %r10, %r8, %rbx, %rbp mov 9*8(%rsi), %rdx am4 %rdi, 9, %rcx, 0, %rax, %r11, %r10, %r8, %r9, %rbx, %rbp mov 10*8(%rsi), %rdx am4 %rdi, 10, %rcx, 0, %r11, %r10, %r8, %r9, %rax, %rbx, %rbp mov 11*8(%rsi), %rdx am4 %rdi, 11, %rcx, 0, %r10, %r8, %r9, %rax, %r11, %rbx, %rbp mov 12*8(%rsi), %rdx am4 %rdi, 12, %rcx, 0, %r8, %r9, %rax, %r11, %r10, %rbx, %rbp mov 13*8(%rsi), %rdx am4 %rdi, 13, %rcx, 0, %r9, %rax, %r11, %r10, %r8, %rbx, %rbp mov 14*8(%rsi), %rdx am4 %rdi, 14, %rcx, 0, %rax, %r11, %r10, %r8, %r9, %rbx, %rbp mov 15*8(%rsi), %rdx am4 %rdi, 15, %rcx, 0, %r11, %r10, %r8, %r9, %rax, %rbx, %rbp mov %r10, 16*8(%rdi) mov %r8, 17*8(%rdi) mov %r9, 18*8(%rdi) mov %rax, 19*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_5) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 xor %r12d, %r12d m5 %rdi, 0, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 1*8(%rsi), %rdx am5 %rdi, 1, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 2*8(%rsi), %rdx am5 %rdi, 2, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %r8, %rbp, %r12 mov 3*8(%rsi), %rdx am5 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %r8, %rax, %rbp, %r12 mov 4*8(%rsi), %rdx am5 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %r8, %rax, %r9, %rbp, %r12 mov 5*8(%rsi), %rdx am5 %rdi, 5, %rcx, 0, %r11, %rbx, %r8, %rax, %r9, %r10, %rbp, %r12 mov 6*8(%rsi), %rdx am5 %rdi, 6, %rcx, 0, %rbx, %r8, %rax, %r9, %r10, %r11, %rbp, %r12 mov 7*8(%rsi), %rdx am5 %rdi, 7, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 8*8(%rsi), %rdx am5 %rdi, 8, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %r8, %rbp, %r12 mov 9*8(%rsi), %rdx am5 %rdi, 9, %rcx, 0, %r9, %r10, %r11, %rbx, %r8, %rax, %rbp, %r12 mov 10*8(%rsi), %rdx am5 %rdi, 10, %rcx, 0, %r10, %r11, %rbx, %r8, %rax, %r9, %rbp, %r12 mov 11*8(%rsi), %rdx am5 %rdi, 11, %rcx, 0, %r11, %rbx, %r8, %rax, %r9, %r10, %rbp, %r12 mov 12*8(%rsi), %rdx am5 %rdi, 12, %rcx, 0, %rbx, %r8, %rax, %r9, %r10, %r11, %rbp, %r12 mov 13*8(%rsi), %rdx am5 %rdi, 13, %rcx, 0, %r8, %rax, %r9, %r10, %r11, %rbx, %rbp, %r12 mov 14*8(%rsi), %rdx am5 %rdi, 14, %rcx, 0, %rax, %r9, %r10, %r11, %rbx, %r8, %rbp, %r12 mov 15*8(%rsi), %rdx am5 %rdi, 15, %rcx, 0, %r9, %r10, %r11, %rbx, %r8, %rax, %rbp, %r12 mov %r10, 16*8(%rdi) mov %r11, 17*8(%rdi) mov %rbx, 18*8(%rdi) mov %r8, 19*8(%rdi) mov %rax, 20*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_6) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 xor %r13d, %r13d m6 %rdi, 0, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov 1*8(%rsi), %rdx am6 %rdi, 1, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov 2*8(%rsi), %rdx am6 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12, %r13 mov 3*8(%rsi), %rdx am6 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r8, %r12, %r13 mov 4*8(%rsi), %rdx am6 %rdi, 4, %rcx, 0, %r10, %r11, %rbx, %rax, %rbp, %r8, %r9, %r12, %r13 mov 5*8(%rsi), %rdx am6 %rdi, 5, %rcx, 0, %r11, %rbx, %rax, %rbp, %r8, %r9, %r10, %r12, %r13 mov 6*8(%rsi), %rdx am6 %rdi, 6, %rcx, 0, %rbx, %rax, %rbp, %r8, %r9, %r10, %r11, %r12, %r13 mov 7*8(%rsi), %rdx am6 %rdi, 7, %rcx, 0, %rax, %rbp, %r8, %r9, %r10, %r11, %rbx, %r12, %r13 mov 8*8(%rsi), %rdx am6 %rdi, 8, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov 9*8(%rsi), %rdx am6 %rdi, 9, %rcx, 0, %r8, %r9, %r10, %r11, %rbx, %rax, %rbp, %r12, %r13 mov 10*8(%rsi), %rdx am6 %rdi, 10, %rcx, 0, %r9, %r10, %r11, %rbx, %rax, %rbp, %r8, %r12, %r13 mov 11*8(%rsi), %rdx am6 %rdi, 11, %rcx, 0, %r10, %r11, %rbx, %rax, %rbp, %r8, %r9, %r12, %r13 mov 12*8(%rsi), %rdx am6 %rdi, 12, %rcx, 0, %r11, %rbx, %rax, %rbp, %r8, %r9, %r10, %r12, %r13 mov 13*8(%rsi), %rdx am6 %rdi, 13, %rcx, 0, %rbx, %rax, %rbp, %r8, %r9, %r10, %r11, %r12, %r13 mov 14*8(%rsi), %rdx am6 %rdi, 14, %rcx, 0, %rax, %rbp, %r8, %r9, %r10, %r11, %rbx, %r12, %r13 mov 15*8(%rsi), %rdx am6 %rdi, 15, %rcx, 0, %rbp, %r8, %r9, %r10, %r11, %rbx, %rax, %r12, %r13 mov %r8, 16*8(%rdi) mov %r9, 17*8(%rdi) mov %r10, 18*8(%rdi) mov %r11, 19*8(%rdi) mov %rbx, 20*8(%rdi) mov %rax, 21*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_7) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 xor %r14d, %r14d m7 %rdi, 0, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13, %r14 mov 1*8(%rsi), %rdx am7 %rdi, 1, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13, %r14 mov 2*8(%rsi), %rdx am7 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %rbx, %r13, %r14 mov 3*8(%rsi), %rdx am7 %rdi, 3, %rcx, 0, %r9, %r10, %r11, %rax, %rbp, %r12, %rbx, %r8, %r13, %r14 mov 4*8(%rsi), %rdx am7 %rdi, 4, %rcx, 0, %r10, %r11, %rax, %rbp, %r12, %rbx, %r8, %r9, %r13, %r14 mov 5*8(%rsi), %rdx am7 %rdi, 5, %rcx, 0, %r11, %rax, %rbp, %r12, %rbx, %r8, %r9, %r10, %r13, %r14 mov 6*8(%rsi), %rdx am7 %rdi, 6, %rcx, 0, %rax, %rbp, %r12, %rbx, %r8, %r9, %r10, %r11, %r13, %r14 mov 7*8(%rsi), %rdx am7 %rdi, 7, %rcx, 0, %rbp, %r12, %rbx, %r8, %r9, %r10, %r11, %rax, %r13, %r14 mov 8*8(%rsi), %rdx am7 %rdi, 8, %rcx, 0, %r12, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r13, %r14 mov 9*8(%rsi), %rdx am7 %rdi, 9, %rcx, 0, %rbx, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %r13, %r14 mov 10*8(%rsi), %rdx am7 %rdi, 10, %rcx, 0, %r8, %r9, %r10, %r11, %rax, %rbp, %r12, %rbx, %r13, %r14 mov 11*8(%rsi), %rdx am7 %rdi, 11, %rcx, 0, %r9, %r10, %r11, %rax, %rbp, %r12, %rbx, %r8, %r13, %r14 mov 12*8(%rsi), %rdx am7 %rdi, 12, %rcx, 0, %r10, %r11, %rax, %rbp, %r12, %rbx, %r8, %r9, %r13, %r14 mov 13*8(%rsi), %rdx am7 %rdi, 13, %rcx, 0, %r11, %rax, %rbp, %r12, %rbx, %r8, %r9, %r10, %r13, %r14 mov 14*8(%rsi), %rdx am7 %rdi, 14, %rcx, 0, %rax, %rbp, %r12, %rbx, %r8, %r9, %r10, %r11, %r13, %r14 mov 15*8(%rsi), %rdx am7 %rdi, 15, %rcx, 0, %rbp, %r12, %rbx, %r8, %r9, %r10, %r11, %rax, %r13, %r14 mov %r12, 16*8(%rdi) mov %rbx, 17*8(%rdi) mov %r8, 18*8(%rdi) mov %r9, 19*8(%rdi) mov %r10, 20*8(%rdi) mov %r11, 21*8(%rdi) mov %rax, 22*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mul_16_8) mov %rdx, %rcx mov 0*8(%rsi), %rdx push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 xor %r15d, %r15d m8 %rdi, 0, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 1*8(%rsi), %rdx am8 %rdi, 1, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 2*8(%rsi), %rdx am8 %rdi, 2, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r14, %r15 mov 3*8(%rsi), %rdx am8 %rdi, 3, %rcx, 0, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r14, %r15 mov 4*8(%rsi), %rdx am8 %rdi, 4, %rcx, 0, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r14, %r15 mov 5*8(%rsi), %rdx am8 %rdi, 5, %rcx, 0, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r10, %r14, %r15 mov 6*8(%rsi), %rdx am8 %rdi, 6, %rcx, 0, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r10, %rax, %r14, %r15 mov 7*8(%rsi), %rdx am8 %rdi, 7, %rcx, 0, %rbp, %r12, %r13, %r11, %r8, %r9, %r10, %rax, %rbx, %r14, %r15 mov 8*8(%rsi), %rdx am8 %rdi, 8, %rcx, 0, %r12, %r13, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r14, %r15 mov 9*8(%rsi), %rdx am8 %rdi, 9, %rcx, 0, %r13, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r14, %r15 mov 10*8(%rsi), %rdx am8 %rdi, 10, %rcx, 0, %r11, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r14, %r15 mov 11*8(%rsi), %rdx am8 %rdi, 11, %rcx, 0, %r8, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r14, %r15 mov 12*8(%rsi), %rdx am8 %rdi, 12, %rcx, 0, %r9, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r14, %r15 mov 13*8(%rsi), %rdx am8 %rdi, 13, %rcx, 0, %r10, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r14, %r15 mov 14*8(%rsi), %rdx am8 %rdi, 14, %rcx, 0, %rax, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r10, %r14, %r15 mov 15*8(%rsi), %rdx am8 %rdi, 15, %rcx, 0, %rbx, %rbp, %r12, %r13, %r11, %r8, %r9, %r10, %rax, %r14, %r15 mov %rbp, 16*8(%rdi) mov %r12, 17*8(%rdi) mov %r13, 18*8(%rdi) mov %r11, 19*8(%rdi) mov %r8, 20*8(%rdi) mov %r9, 21*8(%rdi) mov %r10, 22*8(%rdi) mov %rax, 23*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() flint-3.1.3/src/mpn_extras/broadwell/mulhigh_basecase.asm000066400000000000000000000141551461254215100235500ustar00rootroot00000000000000dnl X64-64 mpn_mullo_basecase optimised for Intel Broadwell. dnl Contributed to the GNU project by Torbjorn Granlund. dnl Copyright 2017 Free Software Foundation, Inc. dnl This file is part of the GNU MP Library. dnl dnl The GNU MP Library is free software; you can redistribute it and/or modify dnl it under the terms of either: dnl dnl * the GNU Lesser General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your dnl option) any later version. dnl dnl or dnl dnl * the GNU General Public License as published by the Free Software dnl Foundation; either version 2 of the License, or (at your option) any dnl later version. dnl dnl or both in parallel, as here. dnl dnl The GNU MP Library is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dnl for more details. dnl dnl You should have received copies of the GNU General Public License and the dnl GNU Lesser General Public License along with the GNU MP Library. If not, dnl see https://www.gnu.org/licenses/. dnl dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') define(`rp', `%rdi') define(`ap', `%rsi') define(`bp_param', `%rdx') define(`n', `%rcx') define(`bp', `%r8') define(`jmpreg', `%r9') define(`nn', `%r10') define(`m', `%r13') define(`mm', `%r14') define(`rx', `%rax') define(`r0', `%r11') define(`r1', `%rbx') define(`r2', `%rbp') define(`r3', `%r12') dnl Idea: Do similar to mpn_mullo_basecase for Skylake. TEXT ALIGN(32) PROLOGUE(_flint_mpn_mulhigh_basecase) mov bp_param, bp lea -1*8(ap,n,8), ap C ap += n - 1 push %rbx push %rbp push %r12 push %r13 push %r14 C Initial triangle C h C h x C h x x C h x x x C x x x x define(`s0', `jmpreg') define(`s1', `m') define(`s2', `mm') define(`s3', `nn') mov 0*8(bp), %rdx xor R32(s3), R32(s3) mulx -1*8(ap), rx, rx mulx 0*8(ap), s0, r0 add s0, rx adc s3, r0 mov 1*8(bp), %rdx mulx -2*8(ap), s1, s1 mulx -1*8(ap), r3, r2 mulx 0*8(ap), s0, r1 add r3, rx adc s0, r0 adc s3, r1 add s1, rx adc r2, r0 adc s3, r1 mov 2*8(bp), %rdx mulx -3*8(ap), s0, s0 mulx -2*8(ap), r3, s1 add s0, rx adc s1, r0 mulx -1*8(ap), s0, s1 mulx 0*8(ap), %rdx, r2 adc s1, r1 adc s3, r2 add r3, rx adc s0, r0 adc %rdx, r1 adc s3, r2 mov 3*8(bp), %rdx mulx -4*8(ap), s1, s1 mulx -3*8(ap), s0, s2 add s1, rx adc s2, r0 mulx -2*8(ap), s1, r3 mulx -1*8(ap), s2, s3 adc r3, r1 adc s3, r2 mulx 0*8(ap), %rdx, r3 adc $0, r3 add s0, rx adc s1, r0 adc s2, r1 mov r0, 0*8(rp) mov r1, 1*8(rp) adc %rdx, r2 adc $0, r3 mov r2, 2*8(rp) mov r3, 3*8(rp) undefine(`s0') undefine(`s1') undefine(`s2') undefine(`s3') C Addmul chains C - m = -8 * n_cur (n_cur is the 4 at the start) C - mm = -8 * (n - 1) (where n is the original n) C - n keeps track of how many loops to do in the addmul-loop. C - nn keeps track of initial n between loops. lea -1*8(,n,8), R32(mm) lea 4*8(bp), bp lea -3*8(ap), ap mov $-4*8, m C m <- -8 * 4 neg mm C mm <- -8 * (n - 1) mov 0*8(bp), %rdx xor R32(nn), R32(nn) C nn <- 0 xor R32(n), R32(n) C n <- 0 mulx -2*8(ap), r1, r1 adcx r1, rx L(f4): mulx -1*8(ap), r2, r3 mulx 0*8(ap), r0, r1 adox r2, rx adcx r3, r0 lea 3*8(ap), ap lea -5*8(rp), rp lea L(f5)(%rip), jmpreg jmp L(b4) L(f0): mulx -1*8(ap), r2, r3 mulx 0*8(ap), r0, r1 adox r2, rx adcx r3, r0 lea -1*8(ap), ap lea -1*8(rp), rp lea L(f1)(%rip), jmpreg jmp L(b0) L(f1): mulx -1*8(ap), r0, r1 mulx 0*8(ap), r2, r3 adox r0, rx adcx r1, r2 lea 1(nn), R32(nn) lea 1(n), R32(n) lea L(f2)(%rip), jmpreg jmp L(b1) L(f7): mulx -1*8(ap), r0, r1 mulx 0*8(ap), r2, r3 adox r0, rx adcx r1, r2 lea -2*8(ap), ap lea -2*8(rp), rp lea L(f0)(%rip), jmpreg jmp L(b7) L(f2): mulx -1*8(ap), r2, r3 mulx 0*8(ap), r0, r1 adox r2, rx adcx r3, r0 lea 1*8(ap), ap lea 1*8(rp), rp mulx 0*8(ap), r2, r3 lea L(f3)(%rip), jmpreg jmp L(b2) L(end): adox 0*8(rp), r2 mov r2, 0*8(rp) adox n, r3 C n = 0 adc n, r3 C n = 0 add m, ap C Reset ap mov r3, 1*8(rp) lea -1*8(m), m lea 1*8(bp), bp C Increase bp lea 2*8(rp,m), rp C Reset rp mov 0*8(bp), %rdx C Load bp cmp R32(m), R32(mm) jge L(jmp) C If |m| < |mm|: goto jmpreg, but first do high part or R32(nn), R32(n) C Reset n, CF and OF mulx -2*8(ap), r1, r1 adcx r1, rx jmp *jmpreg C If |m| > |mm|: goto fin L(jmp): jg L(fin) C If |m| = |mm|: goto jmpreg or R32(nn), R32(n) C Reset n, clear CF and OF jmp *jmpreg ALIGN(32) L(b2): adox -1*8(rp), r0 adcx r1, r2 mov r0, -1*8(rp) jrcxz L(end) C Jump if n = 0 L(b1): mulx 1*8(ap), r0, r1 adox 0*8(rp), r2 lea -1(n), R32(n) mov r2, 0*8(rp) adcx r3, r0 L(b0): mulx 2*8(ap), r2, r3 adcx r1, r2 adox 1*8(rp), r0 mov r0, 1*8(rp) L(b7): mulx 3*8(ap), r0, r1 lea 8*8(ap), ap adcx r3, r0 adox 2*8(rp), r2 mov r2, 2*8(rp) L(b6): mulx -4*8(ap), r2, r3 adox 3*8(rp), r0 adcx r1, r2 mov r0, 3*8(rp) L(b5): mulx -3*8(ap), r0, r1 adcx r3, r0 adox 4*8(rp), r2 mov r2, 4*8(rp) L(b4): mulx -2*8(ap), r2, r3 adox 5*8(rp), r0 adcx r1, r2 mov r0, 5*8(rp) L(b3): adox 6*8(rp), r2 mulx -1*8(ap), r0, r1 mov r2, 6*8(rp) lea 8*8(rp), rp adcx r3, r0 mulx 0*8(ap), r2, r3 jmp L(b2) L(f6): mulx -1*8(ap), r2, r3 mulx 0*8(ap), r0, r1 adox r2, rx adcx r3, r0 lea 5*8(ap), ap lea -3*8(rp), rp lea L(f7)(%rip), jmpreg jmp L(b6) L(f5): mulx -1*8(ap), r0, r1 mulx 0*8(ap), r2, r3 adox r0, rx adcx r1, r2 lea 4*8(ap), ap lea -4*8(rp), rp lea L(f6)(%rip), jmpreg jmp L(b5) L(f3): mulx -1*8(ap), r0, r1 mulx 0*8(ap), r2, r3 adox r0, rx adcx r1, r2 lea 2*8(ap), ap lea -6*8(rp), rp lea L(f4)(%rip), jmpreg jmp L(b3) L(fin): pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() flint-3.1.3/src/mpn_extras/broadwell/mulhigh_hard.asm000066400000000000000000000764261461254215100227310ustar00rootroot00000000000000dnl dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') dnl TODO: dnl * Do stuff in between to avoid latency penalties. dnl * Convert %rX registers using 32-bit operations to %rax, ..., %rbp dnl registers to save a few bytes. TEXT ALIGN(16) PROLOGUE(flint_mpn_mulhigh_1) mov 0*8(%rdx), %rdx mulx 0*8(%rsi), %rax, %rcx mov %rcx, 0*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_2) mov 1*8(%rdx), %r11 mov 0*8(%rdx), %rdx xor %r10d, %r10d mulx 0*8(%rsi), %r9, %rax mulx 1*8(%rsi), %r9, %rcx adcx %r9, %rax adcx %r10, %rcx mov %r11, %rdx mulx 0*8(%rsi), %r9, %r8 adcx %r9, %rax adcx %r8, %rcx mulx 1*8(%rsi), %r9, %r8 adox %r9, %rcx adox %r10, %r8 adcx %r10, %r8 mov %rcx, 0*8(%rdi) mov %r8, 1*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_3) push %rbx mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 1*8(%rsi), %r8, %rax mulx 2*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbx mulx 1*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 2*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbx adcx %r8, %rax adcx %rbx, %r10 mulx 1*8(%rsi), %r8, %rbx adox %r8, %r10 adox %rbx, %r11 mulx 2*8(%rsi), %r8, %rbx adcx %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_4) push %rbx push %rbp mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 2*8(%rsi), %r8, %rax mulx 3*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %rbx mulx 2*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 3*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbp mulx 1*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 2*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 3*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbp adcx %r8, %rax adcx %rbp, %r10 mulx 1*8(%rsi), %r8, %rbp adox %r8, %r10 adox %rbp, %r11 mulx 2*8(%rsi), %r8, %rbp adcx %r8, %r11 adcx %rbp, %rbx mulx 3*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_5) push %rbx push %rbp push %r12 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 3*8(%rsi), %r8, %rax mulx 4*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %rbx mulx 3*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 4*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %rbp mulx 2*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 3*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 4*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r12 mulx 1*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 2*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 3*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 4*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r12 adcx %r8, %rax adcx %r12, %r10 mulx 1*8(%rsi), %r8, %r12 adox %r8, %r10 adox %r12, %r11 mulx 2*8(%rsi), %r8, %r12 adcx %r8, %r11 adcx %r12, %rbx mulx 3*8(%rsi), %r8, %r12 adox %r8, %rbx adox %r12, %rbp mulx 4*8(%rsi), %r8, %r12 adcx %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_6) push %rbx push %rbp push %r12 push %r13 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 4*8(%rsi), %r8, %rax mulx 5*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %rbx mulx 4*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 5*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %rbp mulx 3*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 4*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 5*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r12 mulx 2*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 3*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 4*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 5*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r13 mulx 1*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 2*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 3*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 4*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 5*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r13 adcx %r8, %rax adcx %r13, %r10 mulx 1*8(%rsi), %r8, %r13 adox %r8, %r10 adox %r13, %r11 mulx 2*8(%rsi), %r8, %r13 adcx %r8, %r11 adcx %r13, %rbx mulx 3*8(%rsi), %r8, %r13 adox %r8, %rbx adox %r13, %rbp mulx 4*8(%rsi), %r8, %r13 adcx %r8, %rbp adcx %r13, %r12 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) mov %r13, 5*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_7) push %rbx push %rbp push %r12 push %r13 push %r14 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 5*8(%rsi), %r8, %rax mulx 6*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %rbx mulx 5*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 6*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %rbp mulx 4*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 5*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 6*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r12 mulx 3*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 4*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 5*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 6*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r13 mulx 2*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 3*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 4*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 5*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 6*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r14 mulx 1*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r10 mulx 2*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 3*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 4*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 5*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 6*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov 6*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r14 adcx %r8, %rax adcx %r14, %r10 mulx 1*8(%rsi), %r8, %r14 adox %r8, %r10 adox %r14, %r11 mulx 2*8(%rsi), %r8, %r14 adcx %r8, %r11 adcx %r14, %rbx mulx 3*8(%rsi), %r8, %r14 adox %r8, %rbx adox %r14, %rbp mulx 4*8(%rsi), %r8, %r14 adcx %r8, %rbp adcx %r14, %r12 mulx 5*8(%rsi), %r8, %r14 adox %r8, %r12 adox %r14, %r13 mulx 6*8(%rsi), %r8, %r14 adcx %r8, %r13 adcx %r9, %r14 adox %r9, %r14 mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) mov %r13, 5*8(%rdi) mov %r14, 6*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_8) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 6*8(%rsi), %r8, %rax mulx 7*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %rbx mulx 6*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 7*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %rbp mulx 5*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 6*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 7*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r12 mulx 4*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 5*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 6*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 7*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r13 mulx 3*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 4*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 5*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 6*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 7*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r14 mulx 2*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r10 mulx 3*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 4*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 5*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 6*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 7*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov 6*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r15 mulx 1*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r10 mulx 2*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 3*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 4*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 5*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 6*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 7*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %r9, %r14 adox %r9, %r14 mov 7*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r15 adcx %r8, %rax adcx %r15, %r10 mulx 1*8(%rsi), %r8, %r15 adox %r8, %r10 adox %r15, %r11 mulx 2*8(%rsi), %r8, %r15 adcx %r8, %r11 adcx %r15, %rbx mulx 3*8(%rsi), %r8, %r15 adox %r8, %rbx adox %r15, %rbp mulx 4*8(%rsi), %r8, %r15 adcx %r8, %rbp adcx %r15, %r12 mulx 5*8(%rsi), %r8, %r15 adox %r8, %r12 adox %r15, %r13 mulx 6*8(%rsi), %r8, %r15 adcx %r8, %r13 adcx %r15, %r14 mulx 7*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %r9, %r15 adox %r9, %r15 mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) mov %r13, 5*8(%rdi) mov %r14, 6*8(%rdi) mov %r15, 7*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_9) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 push %rdi mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 7*8(%rsi), %r8, %rax mulx 8*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 6*8(%rsi), %r8, %rbx mulx 7*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 8*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %rbp mulx 6*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 7*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 8*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %r12 mulx 5*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 6*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 7*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 8*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r13 mulx 4*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 5*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 6*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 7*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 8*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r14 mulx 3*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r10 mulx 4*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 6*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 7*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 8*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov 6*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r15 mulx 2*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r10 mulx 3*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 4*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 5*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 6*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 7*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 8*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %r9, %r14 adox %r9, %r14 mov 7*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi mulx 1*8(%rsi), %r8, %r15 adcx %rdi, %rax adox %r8, %rax adcx %r15, %r10 mulx 2*8(%rsi), %r8, %r15 adox %r8, %r10 adcx %r15, %r11 mulx 3*8(%rsi), %r8, %r15 adox %r8, %r11 adcx %r15, %rbx mulx 4*8(%rsi), %r8, %r15 adox %r8, %rbx adcx %r15, %rbp mulx 5*8(%rsi), %r8, %r15 adox %r8, %rbp adcx %r15, %r12 mulx 6*8(%rsi), %r8, %r15 adox %r8, %r12 adcx %r15, %r13 mulx 7*8(%rsi), %r8, %r15 adox %r8, %r13 adcx %r15, %r14 mulx 8*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %r9, %r15 adox %r9, %r15 mov 8*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi adcx %r8, %rax adcx %rdi, %r10 mulx 1*8(%rsi), %r8, %rdi adox %r8, %r10 adox %rdi, %r11 mulx 2*8(%rsi), %r8, %rdi adcx %r8, %r11 adcx %rdi, %rbx mulx 3*8(%rsi), %r8, %rdi adox %r8, %rbx adox %rdi, %rbp mulx 4*8(%rsi), %r8, %rdi adcx %r8, %rbp adcx %rdi, %r12 mulx 5*8(%rsi), %r8, %rdi adox %r8, %r12 adox %rdi, %r13 mulx 6*8(%rsi), %r8, %rdi adcx %r8, %r13 adcx %rdi, %r14 mulx 7*8(%rsi), %r8, %rdi adox %r8, %r14 adox %rdi, %r15 mulx 8*8(%rsi), %r8, %rdi adcx %r8, %r15 adcx %r9, %rdi pop %r8 adox %r9, %rdi mov %r10, 0*8(%r8) mov %r11, 1*8(%r8) mov %rbx, 2*8(%r8) mov %rbp, 3*8(%r8) mov %r12, 4*8(%r8) mov %r13, 5*8(%r8) mov %r14, 6*8(%r8) mov %r15, 7*8(%r8) mov %rdi, 8*8(%r8) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_10) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 vmovq %rsp, %xmm0 vmovq %rdi, %xmm1 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %esp, %esp mulx 8*8(%rsi), %r8, %rax mulx 9*8(%rsi), %r8, %r9 adcx %r8, %rax adcx %rsp, %r9 mov 1*8(%rcx), %rdx mulx 7*8(%rsi), %r8, %r11 mulx 8*8(%rsi), %r8, %r10 adcx %r11, %rax adox %r8, %rax adcx %r10, %r9 mulx 9*8(%rsi), %r8, %r10 adox %r8, %r9 adcx %rsp, %r10 adox %rsp, %r10 mov 2*8(%rcx), %rdx mulx 6*8(%rsi), %r8, %rbx mulx 7*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r9 mulx 8*8(%rsi), %r8, %r11 adox %r8, %r9 adcx %r11, %r10 mulx 9*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %rsp, %r11 adox %rsp, %r11 mov 3*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %rbp mulx 6*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r9 mulx 7*8(%rsi), %r8, %rbx adox %r8, %r9 adcx %rbx, %r10 mulx 8*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 9*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %rsp, %rbx adox %rsp, %rbx mov 4*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %r12 mulx 5*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r9 mulx 6*8(%rsi), %r8, %rbp adox %r8, %r9 adcx %rbp, %r10 mulx 7*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 8*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 9*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %rsp, %rbp adox %rsp, %rbp mov 5*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r13 mulx 4*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r9 mulx 5*8(%rsi), %r8, %r12 adox %r8, %r9 adcx %r12, %r10 mulx 6*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 7*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 8*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 9*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %rsp, %r12 adox %rsp, %r12 mov 6*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r14 mulx 3*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r9 mulx 4*8(%rsi), %r8, %r13 adox %r8, %r9 adcx %r13, %r10 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 6*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 7*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 8*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 9*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %rsp, %r13 adox %rsp, %r13 mov 7*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r15 mulx 2*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r9 mulx 3*8(%rsi), %r8, %r14 adox %r8, %r9 adcx %r14, %r10 mulx 4*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 5*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 6*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 7*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 8*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 9*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %rsp, %r14 adox %rsp, %r14 mov 8*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi mulx 1*8(%rsi), %r8, %r15 adcx %rdi, %rax adox %r8, %rax adcx %r15, %r9 mulx 2*8(%rsi), %r8, %r15 adox %r8, %r9 adcx %r15, %r10 mulx 3*8(%rsi), %r8, %r15 adox %r8, %r10 adcx %r15, %r11 mulx 4*8(%rsi), %r8, %r15 adox %r8, %r11 adcx %r15, %rbx mulx 5*8(%rsi), %r8, %r15 adox %r8, %rbx adcx %r15, %rbp mulx 6*8(%rsi), %r8, %r15 adox %r8, %rbp adcx %r15, %r12 mulx 7*8(%rsi), %r8, %r15 adox %r8, %r12 adcx %r15, %r13 mulx 8*8(%rsi), %r8, %r15 adox %r8, %r13 adcx %r15, %r14 mulx 9*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %rsp, %r15 adox %rsp, %r15 mov 9*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi adcx %r8, %rax adcx %rdi, %r9 mulx 1*8(%rsi), %r8, %rdi adox %r8, %r9 adox %rdi, %r10 mulx 2*8(%rsi), %r8, %rdi adcx %r8, %r10 adcx %rdi, %r11 mulx 3*8(%rsi), %r8, %rdi adox %r8, %r11 adox %rdi, %rbx mulx 4*8(%rsi), %r8, %rdi adcx %r8, %rbx adcx %rdi, %rbp mulx 5*8(%rsi), %r8, %rdi adox %r8, %rbp adox %rdi, %r12 mulx 6*8(%rsi), %r8, %rdi adcx %r8, %r12 adcx %rdi, %r13 mulx 7*8(%rsi), %r8, %rdi adox %r8, %r13 adox %rdi, %r14 mulx 8*8(%rsi), %r8, %rdi adcx %r8, %r14 adcx %rdi, %r15 mulx 9*8(%rsi), %r8, %rdi adox %r8, %r15 adcx %rsp, %rdi adox %rsp, %rdi vmovq %xmm1, %r8 vmovq %xmm0, %rsp mov %r9, 0*8(%r8) mov %r10, 1*8(%r8) mov %r11, 2*8(%r8) mov %rbx, 3*8(%r8) mov %rbp, 4*8(%r8) mov %r12, 5*8(%r8) mov %r13, 6*8(%r8) mov %r14, 7*8(%r8) mov %r15, 8*8(%r8) mov %rdi, 9*8(%r8) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_11) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 vmovq %rsp, %xmm0 vmovq %rdi, %xmm1 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %esp, %esp mulx 9*8(%rsi), %r8, %rax mulx 10*8(%rsi), %r8, %r9 adcx %r8, %rax adcx %rsp, %r9 mov 1*8(%rcx), %rdx mulx 8*8(%rsi), %r8, %r11 mulx 9*8(%rsi), %r8, %r10 adcx %r11, %rax adox %r8, %rax adcx %r10, %r9 mulx 10*8(%rsi), %r8, %r10 adox %r8, %r9 adcx %rsp, %r10 adox %rsp, %r10 mov 2*8(%rcx), %rdx mulx 7*8(%rsi), %r8, %rbx mulx 8*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r9 mulx 9*8(%rsi), %r8, %r11 adox %r8, %r9 adcx %r11, %r10 mulx 10*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %rsp, %r11 adox %rsp, %r11 mov 3*8(%rcx), %rdx mulx 6*8(%rsi), %r8, %rbp mulx 7*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r9 mulx 8*8(%rsi), %r8, %rbx adox %r8, %r9 adcx %rbx, %r10 mulx 9*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 10*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %rsp, %rbx adox %rsp, %rbx mov 4*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %r12 mulx 6*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r9 mulx 7*8(%rsi), %r8, %rbp adox %r8, %r9 adcx %rbp, %r10 mulx 8*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 9*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 10*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %rsp, %rbp adox %rsp, %rbp mov 5*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %r13 mulx 5*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r9 mulx 6*8(%rsi), %r8, %r12 adox %r8, %r9 adcx %r12, %r10 mulx 7*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 8*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 9*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 10*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %rsp, %r12 adox %rsp, %r12 mov 6*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r14 mulx 4*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r9 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r9 adcx %r13, %r10 mulx 6*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 7*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 8*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 9*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 10*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %rsp, %r13 adox %rsp, %r13 mov 7*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r15 mulx 3*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r9 mulx 4*8(%rsi), %r8, %r14 adox %r8, %r9 adcx %r14, %r10 mulx 5*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 6*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 7*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 8*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 9*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 10*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %rsp, %r14 adox %rsp, %r14 mov 8*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %rdi mulx 2*8(%rsi), %r8, %r15 adcx %rdi, %rax adox %r8, %rax adcx %r15, %r9 mulx 3*8(%rsi), %r8, %r15 adox %r8, %r9 adcx %r15, %r10 mulx 4*8(%rsi), %r8, %r15 adox %r8, %r10 adcx %r15, %r11 mulx 5*8(%rsi), %r8, %r15 adox %r8, %r11 adcx %r15, %rbx mulx 6*8(%rsi), %r8, %r15 adox %r8, %rbx adcx %r15, %rbp mulx 7*8(%rsi), %r8, %r15 adox %r8, %rbp adcx %r15, %r12 mulx 8*8(%rsi), %r8, %r15 adox %r8, %r12 adcx %r15, %r13 mulx 9*8(%rsi), %r8, %r15 adox %r8, %r13 adcx %r15, %r14 mulx 10*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %rsp, %r15 adox %rsp, %r15 mov 9*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi adcx %rdi, %rax mulx 1*8(%rsi), %r8, %rdi adox %r8, %rax adcx %rdi, %r9 mulx 2*8(%rsi), %r8, %rdi adox %r8, %r9 adcx %rdi, %r10 mulx 3*8(%rsi), %r8, %rdi adox %r8, %r10 adcx %rdi, %r11 mulx 4*8(%rsi), %r8, %rdi adox %r8, %r11 adcx %rdi, %rbx mulx 5*8(%rsi), %r8, %rdi adox %r8, %rbx adcx %rdi, %rbp mulx 6*8(%rsi), %r8, %rdi adox %r8, %rbp adcx %rdi, %r12 mulx 7*8(%rsi), %r8, %rdi adox %r8, %r12 adcx %rdi, %r13 mulx 8*8(%rsi), %r8, %rdi adox %r8, %r13 adcx %rdi, %r14 mulx 9*8(%rsi), %r8, %rdi adox %r8, %r14 adcx %rdi, %r15 mulx 10*8(%rsi), %r8, %rdi adox %r8, %r15 adcx %rsp, %rdi adox %rsp, %rdi mov 10*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rcx adcx %r8, %rax adcx %rcx, %r9 mulx 1*8(%rsi), %r8, %rcx adox %r8, %r9 adox %rcx, %r10 mulx 2*8(%rsi), %r8, %rcx adcx %r8, %r10 adcx %rcx, %r11 mulx 3*8(%rsi), %r8, %rcx adox %r8, %r11 adox %rcx, %rbx mulx 4*8(%rsi), %r8, %rcx adcx %r8, %rbx adcx %rcx, %rbp mulx 5*8(%rsi), %r8, %rcx adox %r8, %rbp adox %rcx, %r12 mulx 6*8(%rsi), %r8, %rcx adcx %r8, %r12 adcx %rcx, %r13 mulx 7*8(%rsi), %r8, %rcx adox %r8, %r13 adox %rcx, %r14 mulx 8*8(%rsi), %r8, %rcx adcx %r8, %r14 adcx %rcx, %r15 mulx 9*8(%rsi), %r8, %rcx adox %r8, %r15 adox %rcx, %rdi mulx 10*8(%rsi), %r8, %rcx adcx %r8, %rdi adcx %rsp, %rcx adox %rsp, %rcx vmovq %xmm1, %r8 vmovq %xmm0, %rsp mov %r9, 0*8(%r8) mov %r10, 1*8(%r8) mov %r11, 2*8(%r8) mov %rbx, 3*8(%r8) mov %rbp, 4*8(%r8) mov %r12, 5*8(%r8) mov %r13, 6*8(%r8) mov %r14, 7*8(%r8) mov %r15, 8*8(%r8) mov %rdi, 9*8(%r8) mov %rcx, 10*8(%r8) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_12) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 vmovq %rsp, %xmm0 vmovq %rdi, %xmm1 mov %rdx, %rcx mov 0*8(%rdx), %rdx mulx 10*8(%rsi), %rsp, %rax mulx 11*8(%rsi), %rsp, %r8 add %rsp, %rax adc $0, %r8 test %al, %al mov 1*8(%rcx), %rdx mulx 9*8(%rsi), %rsp, %r10 mulx 10*8(%rsi), %rsp, %r9 adcx %r10, %rax adox %rsp, %rax adcx %r9, %r8 mulx 11*8(%rsi), %rsp, %r9 adox %rsp, %r8 mov $0, %esp adcx %rsp, %r9 adox %rsp, %r9 mov 2*8(%rcx), %rdx mulx 8*8(%rsi), %rsp, %r11 mulx 9*8(%rsi), %rsp, %r10 adcx %r11, %rax adox %rsp, %rax adcx %r10, %r8 mulx 10*8(%rsi), %rsp, %r10 adox %rsp, %r8 adcx %r10, %r9 mulx 11*8(%rsi), %rsp, %r10 adox %rsp, %r9 mov $0, %esp adcx %rsp, %r10 adox %rsp, %r10 mov 3*8(%rcx), %rdx mulx 7*8(%rsi), %rsp, %rbx mulx 8*8(%rsi), %rsp, %r11 adcx %rbx, %rax adox %rsp, %rax adcx %r11, %r8 mulx 9*8(%rsi), %rsp, %r11 adox %rsp, %r8 adcx %r11, %r9 mulx 10*8(%rsi), %rsp, %r11 adox %rsp, %r9 adcx %r11, %r10 mulx 11*8(%rsi), %rsp, %r11 adox %rsp, %r10 mov $0, %esp adcx %rsp, %r11 adox %rsp, %r11 mov 4*8(%rcx), %rdx mulx 6*8(%rsi), %rsp, %rbp mulx 7*8(%rsi), %rsp, %rbx adcx %rbp, %rax adox %rsp, %rax adcx %rbx, %r8 mulx 8*8(%rsi), %rsp, %rbx adox %rsp, %r8 adcx %rbx, %r9 mulx 9*8(%rsi), %rsp, %rbx adox %rsp, %r9 adcx %rbx, %r10 mulx 10*8(%rsi), %rsp, %rbx adox %rsp, %r10 adcx %rbx, %r11 mulx 11*8(%rsi), %rsp, %rbx adox %rsp, %r11 mov $0, %esp adcx %rsp, %rbx adox %rsp, %rbx mov 5*8(%rcx), %rdx mulx 5*8(%rsi), %rsp, %r12 mulx 6*8(%rsi), %rsp, %rbp adcx %r12, %rax adox %rsp, %rax adcx %rbp, %r8 mulx 7*8(%rsi), %rsp, %rbp adox %rsp, %r8 adcx %rbp, %r9 mulx 8*8(%rsi), %rsp, %rbp adox %rsp, %r9 adcx %rbp, %r10 mulx 9*8(%rsi), %rsp, %rbp adox %rsp, %r10 adcx %rbp, %r11 mulx 10*8(%rsi), %rsp, %rbp adox %rsp, %r11 adcx %rbp, %rbx mulx 11*8(%rsi), %rsp, %rbp adox %rsp, %rbx mov $0, %esp adcx %rsp, %rbp adox %rsp, %rbp mov 6*8(%rcx), %rdx mulx 4*8(%rsi), %rsp, %r13 mulx 5*8(%rsi), %rsp, %r12 adcx %r13, %rax adox %rsp, %rax adcx %r12, %r8 mulx 6*8(%rsi), %rsp, %r12 adox %rsp, %r8 adcx %r12, %r9 mulx 7*8(%rsi), %rsp, %r12 adox %rsp, %r9 adcx %r12, %r10 mulx 8*8(%rsi), %rsp, %r12 adox %rsp, %r10 adcx %r12, %r11 mulx 9*8(%rsi), %rsp, %r12 adox %rsp, %r11 adcx %r12, %rbx mulx 10*8(%rsi), %rsp, %r12 adox %rsp, %rbx adcx %r12, %rbp mulx 11*8(%rsi), %rsp, %r12 adox %rsp, %rbp mov $0, %esp adcx %rsp, %r12 adox %rsp, %r12 mov 7*8(%rcx), %rdx mulx 3*8(%rsi), %rsp, %r14 mulx 4*8(%rsi), %rsp, %r13 adcx %r14, %rax adox %rsp, %rax adcx %r13, %r8 mulx 5*8(%rsi), %rsp, %r13 adox %rsp, %r8 adcx %r13, %r9 mulx 6*8(%rsi), %rsp, %r13 adox %rsp, %r9 adcx %r13, %r10 mulx 7*8(%rsi), %rsp, %r13 adox %rsp, %r10 adcx %r13, %r11 mulx 8*8(%rsi), %rsp, %r13 adox %rsp, %r11 adcx %r13, %rbx mulx 9*8(%rsi), %rsp, %r13 adox %rsp, %rbx adcx %r13, %rbp mulx 10*8(%rsi), %rsp, %r13 adox %rsp, %rbp adcx %r13, %r12 mulx 11*8(%rsi), %rsp, %r13 adox %rsp, %r12 mov $0, %esp adcx %rsp, %r13 adox %rsp, %r13 mov 8*8(%rcx), %rdx mulx 2*8(%rsi), %rsp, %r15 mulx 3*8(%rsi), %rsp, %r14 adcx %r15, %rax adox %rsp, %rax adcx %r14, %r8 mulx 4*8(%rsi), %rsp, %r14 adox %rsp, %r8 adcx %r14, %r9 mulx 5*8(%rsi), %rsp, %r14 adox %rsp, %r9 adcx %r14, %r10 mulx 6*8(%rsi), %rsp, %r14 adox %rsp, %r10 adcx %r14, %r11 mulx 7*8(%rsi), %rsp, %r14 adox %rsp, %r11 adcx %r14, %rbx mulx 8*8(%rsi), %rsp, %r14 adox %rsp, %rbx adcx %r14, %rbp mulx 9*8(%rsi), %rsp, %r14 adox %rsp, %rbp adcx %r14, %r12 mulx 10*8(%rsi), %rsp, %r14 adox %rsp, %r12 adcx %r14, %r13 mulx 11*8(%rsi), %rsp, %r14 adox %rsp, %r13 mov $0, %esp adcx %rsp, %r14 adox %rsp, %r14 mov 9*8(%rcx), %rdx mulx 1*8(%rsi), %rsp, %rdi mulx 2*8(%rsi), %rsp, %r15 adcx %rdi, %rax adox %rsp, %rax adcx %r15, %r8 mulx 3*8(%rsi), %rsp, %r15 adox %rsp, %r8 adcx %r15, %r9 mulx 4*8(%rsi), %rsp, %r15 adox %rsp, %r9 adcx %r15, %r10 mulx 5*8(%rsi), %rsp, %r15 adox %rsp, %r10 adcx %r15, %r11 mulx 6*8(%rsi), %rsp, %r15 adox %rsp, %r11 adcx %r15, %rbx mulx 7*8(%rsi), %rsp, %r15 adox %rsp, %rbx adcx %r15, %rbp mulx 8*8(%rsi), %rsp, %r15 adox %rsp, %rbp adcx %r15, %r12 mulx 9*8(%rsi), %rsp, %r15 adox %rsp, %r12 adcx %r15, %r13 mulx 10*8(%rsi), %rsp, %r15 adox %rsp, %r13 adcx %r15, %r14 mulx 11*8(%rsi), %rsp, %r15 adox %rsp, %r14 mov $0, %esp adcx %rsp, %r15 adox %rsp, %r15 mov 10*8(%rcx), %rdx mulx 0*8(%rsi), %rsp, %rdi adcx %rdi, %rax mulx 1*8(%rsi), %rsp, %rdi adox %rsp, %rax adcx %rdi, %r8 mulx 2*8(%rsi), %rsp, %rdi adox %rsp, %r8 adcx %rdi, %r9 mulx 3*8(%rsi), %rsp, %rdi adox %rsp, %r9 adcx %rdi, %r10 mulx 4*8(%rsi), %rsp, %rdi adox %rsp, %r10 adcx %rdi, %r11 mulx 5*8(%rsi), %rsp, %rdi adox %rsp, %r11 adcx %rdi, %rbx mulx 6*8(%rsi), %rsp, %rdi adox %rsp, %rbx adcx %rdi, %rbp mulx 7*8(%rsi), %rsp, %rdi adox %rsp, %rbp adcx %rdi, %r12 mulx 8*8(%rsi), %rsp, %rdi adox %rsp, %r12 adcx %rdi, %r13 mulx 9*8(%rsi), %rsp, %rdi adox %rsp, %r13 adcx %rdi, %r14 mulx 10*8(%rsi), %rsp, %rdi adox %rsp, %r14 adcx %rdi, %r15 mulx 11*8(%rsi), %rsp, %rdi adox %rsp, %r15 mov $0, %esp adcx %rsp, %rdi adox %rsp, %rdi mov 11*8(%rcx), %rdx mulx 0*8(%rsi), %rsp, %rcx adcx %rsp, %rax adcx %rcx, %r8 mulx 1*8(%rsi), %rsp, %rcx adox %rsp, %r8 adox %rcx, %r9 mulx 2*8(%rsi), %rsp, %rcx adcx %rsp, %r9 adcx %rcx, %r10 mulx 3*8(%rsi), %rsp, %rcx adox %rsp, %r10 adox %rcx, %r11 mulx 4*8(%rsi), %rsp, %rcx adcx %rsp, %r11 adcx %rcx, %rbx mulx 5*8(%rsi), %rsp, %rcx adox %rsp, %rbx adox %rcx, %rbp mulx 6*8(%rsi), %rsp, %rcx adcx %rsp, %rbp adcx %rcx, %r12 mulx 7*8(%rsi), %rsp, %rcx adox %rsp, %r12 adox %rcx, %r13 mulx 8*8(%rsi), %rsp, %rcx adcx %rsp, %r13 adcx %rcx, %r14 mulx 9*8(%rsi), %rsp, %rcx adox %rsp, %r14 adox %rcx, %r15 mulx 10*8(%rsi), %rsp, %rcx adcx %rsp, %r15 adcx %rcx, %rdi mulx 11*8(%rsi), %rsp, %rcx adox %rsp, %rdi mov $0, %esp adcx %rsp, %rcx adox %rsp, %rcx vmovq %xmm1, %rsp mov %r8, 0*8(%rsp) mov %r9, 1*8(%rsp) mov %r10, 2*8(%rsp) mov %r11, 3*8(%rsp) mov %rbx, 4*8(%rsp) mov %rbp, 5*8(%rsp) mov %r12, 6*8(%rsp) mov %r13, 7*8(%rsp) mov %r14, 8*8(%rsp) mov %r15, 9*8(%rsp) mov %rdi, 10*8(%rsp) mov %rcx, 11*8(%rsp) vmovq %xmm0, %rsp pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() flint-3.1.3/src/mpn_extras/broadwell/mulhigh_normalised_hard.asm000066400000000000000000001027401461254215100251330ustar00rootroot00000000000000dnl dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') dnl TODO: dnl * Do stuff in between to avoid latency penalties. dnl * Convert %rX registers using 32-bit operations to %rax, ..., %rbp dnl registers to save a few bytes. TEXT ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_1) mov 0*8(%rdx), %rdx mulx 0*8(%rsi), %rax, %rcx mov $0, %rdx test %rcx, %rcx setns %dl js L(1) add %rax, %rax adc %rcx, %rcx L(1): mov %rcx, 0*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_2) mov 1*8(%rdx), %r11 mov 0*8(%rdx), %rdx xor %r10d, %r10d mulx 0*8(%rsi), %r9, %rax mulx 1*8(%rsi), %r9, %rcx adcx %r9, %rax adcx %r10, %rcx mov %r11, %rdx mulx 0*8(%rsi), %r9, %r8 adcx %r9, %rax adcx %r8, %rcx mulx 1*8(%rsi), %r9, %r8 adox %r9, %rcx adox %r10, %r8 adcx %r10, %r8 mov $0, %rdx test %r8, %r8 setns %dl js L(2) add %rax, %rax adc %rcx, %rcx adc %r8, %r8 L(2): mov %rcx, 0*8(%rdi) mov %r8, 1*8(%rdi) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_3) push %rbx mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 1*8(%rsi), %r8, %rax mulx 2*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbx mulx 1*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 2*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbx adcx %r8, %rax adcx %rbx, %r10 mulx 1*8(%rsi), %r8, %rbx adox %r8, %r10 adox %rbx, %r11 mulx 2*8(%rsi), %r8, %rbx adcx %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov $0, %rdx test %rbx, %rbx setns %dl js L(3) add %rax, %rax adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx L(3): mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_4) push %rbx push %rbp mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 2*8(%rsi), %r8, %rax mulx 3*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %rbx mulx 2*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 3*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbp mulx 1*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 2*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 3*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rbp adcx %r8, %rax adcx %rbp, %r10 mulx 1*8(%rsi), %r8, %rbp adox %r8, %r10 adox %rbp, %r11 mulx 2*8(%rsi), %r8, %rbp adcx %r8, %r11 adcx %rbp, %rbx mulx 3*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov $0, %rdx test %rbp, %rbp setns %dl js L(4) add %rax, %rax adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp L(4): mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_5) push %rbx push %rbp push %r12 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 3*8(%rsi), %r8, %rax mulx 4*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %rbx mulx 3*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 4*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %rbp mulx 2*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 3*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 4*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r12 mulx 1*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 2*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 3*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 4*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r12 adcx %r8, %rax adcx %r12, %r10 mulx 1*8(%rsi), %r8, %r12 adox %r8, %r10 adox %r12, %r11 mulx 2*8(%rsi), %r8, %r12 adcx %r8, %r11 adcx %r12, %rbx mulx 3*8(%rsi), %r8, %r12 adox %r8, %rbx adox %r12, %rbp mulx 4*8(%rsi), %r8, %r12 adcx %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov $0, %rdx test %r12, %r12 setns %dl js L(5) add %rax, %rax adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 L(5): mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_6) push %rbx push %rbp push %r12 push %r13 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 4*8(%rsi), %r8, %rax mulx 5*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %rbx mulx 4*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 5*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %rbp mulx 3*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 4*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 5*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r12 mulx 2*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 3*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 4*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 5*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r13 mulx 1*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 2*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 3*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 4*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 5*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r13 adcx %r8, %rax adcx %r13, %r10 mulx 1*8(%rsi), %r8, %r13 adox %r8, %r10 adox %r13, %r11 mulx 2*8(%rsi), %r8, %r13 adcx %r8, %r11 adcx %r13, %rbx mulx 3*8(%rsi), %r8, %r13 adox %r8, %rbx adox %r13, %rbp mulx 4*8(%rsi), %r8, %r13 adcx %r8, %rbp adcx %r13, %r12 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov $0, %rdx test %r13, %r13 setns %dl js L(6) add %rax, %rax adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 adc %r13, %r13 L(6): mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) mov %r13, 5*8(%rdi) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_7) push %rbx push %rbp push %r12 push %r13 push %r14 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 5*8(%rsi), %r8, %rax mulx 6*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %rbx mulx 5*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 6*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %rbp mulx 4*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 5*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 6*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r12 mulx 3*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 4*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 5*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 6*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r13 mulx 2*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 3*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 4*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 5*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 6*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r14 mulx 1*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r10 mulx 2*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 3*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 4*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 5*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 6*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov 6*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r14 adcx %r8, %rax adcx %r14, %r10 mulx 1*8(%rsi), %r8, %r14 adox %r8, %r10 adox %r14, %r11 mulx 2*8(%rsi), %r8, %r14 adcx %r8, %r11 adcx %r14, %rbx mulx 3*8(%rsi), %r8, %r14 adox %r8, %rbx adox %r14, %rbp mulx 4*8(%rsi), %r8, %r14 adcx %r8, %rbp adcx %r14, %r12 mulx 5*8(%rsi), %r8, %r14 adox %r8, %r12 adox %r14, %r13 mulx 6*8(%rsi), %r8, %r14 adcx %r8, %r13 adcx %r9, %r14 adox %r9, %r14 mov $0, %rdx test %r14, %r14 setns %dl js L(7) add %rax, %rax adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 adc %r13, %r13 adc %r14, %r14 L(7): mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) mov %r13, 5*8(%rdi) mov %r14, 6*8(%rdi) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_8) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 6*8(%rsi), %r8, %rax mulx 7*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %rbx mulx 6*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 7*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %rbp mulx 5*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 6*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 7*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r12 mulx 4*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 5*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 6*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 7*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r13 mulx 3*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 4*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 5*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 6*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 7*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r14 mulx 2*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r10 mulx 3*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 4*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 5*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 6*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 7*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov 6*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r15 mulx 1*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r10 mulx 2*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 3*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 4*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 5*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 6*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 7*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %r9, %r14 adox %r9, %r14 mov 7*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %r15 adcx %r8, %rax adcx %r15, %r10 mulx 1*8(%rsi), %r8, %r15 adox %r8, %r10 adox %r15, %r11 mulx 2*8(%rsi), %r8, %r15 adcx %r8, %r11 adcx %r15, %rbx mulx 3*8(%rsi), %r8, %r15 adox %r8, %rbx adox %r15, %rbp mulx 4*8(%rsi), %r8, %r15 adcx %r8, %rbp adcx %r15, %r12 mulx 5*8(%rsi), %r8, %r15 adox %r8, %r12 adox %r15, %r13 mulx 6*8(%rsi), %r8, %r15 adcx %r8, %r13 adcx %r15, %r14 mulx 7*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %r9, %r15 adox %r9, %r15 mov $0, %rdx test %r15, %r15 setns %dl js L(8) add %rax, %rax adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 adc %r13, %r13 adc %r14, %r14 adc %r15, %r15 L(8): mov %r10, 0*8(%rdi) mov %r11, 1*8(%rdi) mov %rbx, 2*8(%rdi) mov %rbp, 3*8(%rdi) mov %r12, 4*8(%rdi) mov %r13, 5*8(%rdi) mov %r14, 6*8(%rdi) mov %r15, 7*8(%rdi) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_9) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 push %rdi mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %r9d, %r9d mulx 7*8(%rsi), %r8, %rax mulx 8*8(%rsi), %r8, %r10 adcx %r8, %rax adcx %r9, %r10 mov 1*8(%rcx), %rdx mulx 6*8(%rsi), %r8, %rbx mulx 7*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r10 mulx 8*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %r9, %r11 adox %r9, %r11 mov 2*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %rbp mulx 6*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r10 mulx 7*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 8*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %r9, %rbx adox %r9, %rbx mov 3*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %r12 mulx 5*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r10 mulx 6*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 7*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 8*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %r9, %rbp adox %r9, %rbp mov 4*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r13 mulx 4*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r10 mulx 5*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 6*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 7*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 8*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %r9, %r12 adox %r9, %r12 mov 5*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r14 mulx 3*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r10 mulx 4*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 6*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 7*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 8*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %r9, %r13 adox %r9, %r13 mov 6*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r15 mulx 2*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r10 mulx 3*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 4*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 5*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 6*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 7*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 8*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %r9, %r14 adox %r9, %r14 mov 7*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi mulx 1*8(%rsi), %r8, %r15 adcx %rdi, %rax adox %r8, %rax adcx %r15, %r10 mulx 2*8(%rsi), %r8, %r15 adox %r8, %r10 adcx %r15, %r11 mulx 3*8(%rsi), %r8, %r15 adox %r8, %r11 adcx %r15, %rbx mulx 4*8(%rsi), %r8, %r15 adox %r8, %rbx adcx %r15, %rbp mulx 5*8(%rsi), %r8, %r15 adox %r8, %rbp adcx %r15, %r12 mulx 6*8(%rsi), %r8, %r15 adox %r8, %r12 adcx %r15, %r13 mulx 7*8(%rsi), %r8, %r15 adox %r8, %r13 adcx %r15, %r14 mulx 8*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %r9, %r15 adox %r9, %r15 mov 8*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi adcx %r8, %rax adcx %rdi, %r10 mulx 1*8(%rsi), %r8, %rdi adox %r8, %r10 adox %rdi, %r11 mulx 2*8(%rsi), %r8, %rdi adcx %r8, %r11 adcx %rdi, %rbx mulx 3*8(%rsi), %r8, %rdi adox %r8, %rbx adox %rdi, %rbp mulx 4*8(%rsi), %r8, %rdi adcx %r8, %rbp adcx %rdi, %r12 mulx 5*8(%rsi), %r8, %rdi adox %r8, %r12 adox %rdi, %r13 mulx 6*8(%rsi), %r8, %rdi adcx %r8, %r13 adcx %rdi, %r14 mulx 7*8(%rsi), %r8, %rdi adox %r8, %r14 adox %rdi, %r15 mulx 8*8(%rsi), %r8, %rdi adcx %r8, %r15 adcx %r9, %rdi pop %r8 adox %r9, %rdi mov $0, %rdx test %rdi, %rdi setns %dl js L(9) add %rax, %rax adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 adc %r13, %r13 adc %r14, %r14 adc %r15, %r15 adc %rdi, %rdi L(9): mov %r10, 0*8(%r8) mov %r11, 1*8(%r8) mov %rbx, 2*8(%r8) mov %rbp, 3*8(%r8) mov %r12, 4*8(%r8) mov %r13, 5*8(%r8) mov %r14, 6*8(%r8) mov %r15, 7*8(%r8) mov %rdi, 8*8(%r8) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_10) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 vmovq %rsp, %xmm0 vmovq %rdi, %xmm1 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %esp, %esp mulx 8*8(%rsi), %r8, %rax mulx 9*8(%rsi), %r8, %r9 adcx %r8, %rax adcx %rsp, %r9 mov 1*8(%rcx), %rdx mulx 7*8(%rsi), %r8, %r11 mulx 8*8(%rsi), %r8, %r10 adcx %r11, %rax adox %r8, %rax adcx %r10, %r9 mulx 9*8(%rsi), %r8, %r10 adox %r8, %r9 adcx %rsp, %r10 adox %rsp, %r10 mov 2*8(%rcx), %rdx mulx 6*8(%rsi), %r8, %rbx mulx 7*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r9 mulx 8*8(%rsi), %r8, %r11 adox %r8, %r9 adcx %r11, %r10 mulx 9*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %rsp, %r11 adox %rsp, %r11 mov 3*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %rbp mulx 6*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r9 mulx 7*8(%rsi), %r8, %rbx adox %r8, %r9 adcx %rbx, %r10 mulx 8*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 9*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %rsp, %rbx adox %rsp, %rbx mov 4*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %r12 mulx 5*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r9 mulx 6*8(%rsi), %r8, %rbp adox %r8, %r9 adcx %rbp, %r10 mulx 7*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 8*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 9*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %rsp, %rbp adox %rsp, %rbp mov 5*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r13 mulx 4*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r9 mulx 5*8(%rsi), %r8, %r12 adox %r8, %r9 adcx %r12, %r10 mulx 6*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 7*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 8*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 9*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %rsp, %r12 adox %rsp, %r12 mov 6*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r14 mulx 3*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r9 mulx 4*8(%rsi), %r8, %r13 adox %r8, %r9 adcx %r13, %r10 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 6*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 7*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 8*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 9*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %rsp, %r13 adox %rsp, %r13 mov 7*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %r15 mulx 2*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r9 mulx 3*8(%rsi), %r8, %r14 adox %r8, %r9 adcx %r14, %r10 mulx 4*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 5*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 6*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 7*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 8*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 9*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %rsp, %r14 adox %rsp, %r14 mov 8*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi mulx 1*8(%rsi), %r8, %r15 adcx %rdi, %rax adox %r8, %rax adcx %r15, %r9 mulx 2*8(%rsi), %r8, %r15 adox %r8, %r9 adcx %r15, %r10 mulx 3*8(%rsi), %r8, %r15 adox %r8, %r10 adcx %r15, %r11 mulx 4*8(%rsi), %r8, %r15 adox %r8, %r11 adcx %r15, %rbx mulx 5*8(%rsi), %r8, %r15 adox %r8, %rbx adcx %r15, %rbp mulx 6*8(%rsi), %r8, %r15 adox %r8, %rbp adcx %r15, %r12 mulx 7*8(%rsi), %r8, %r15 adox %r8, %r12 adcx %r15, %r13 mulx 8*8(%rsi), %r8, %r15 adox %r8, %r13 adcx %r15, %r14 mulx 9*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %rsp, %r15 adox %rsp, %r15 mov 9*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi adcx %r8, %rax adcx %rdi, %r9 mulx 1*8(%rsi), %r8, %rdi adox %r8, %r9 adox %rdi, %r10 mulx 2*8(%rsi), %r8, %rdi adcx %r8, %r10 adcx %rdi, %r11 mulx 3*8(%rsi), %r8, %rdi adox %r8, %r11 adox %rdi, %rbx mulx 4*8(%rsi), %r8, %rdi adcx %r8, %rbx adcx %rdi, %rbp mulx 5*8(%rsi), %r8, %rdi adox %r8, %rbp adox %rdi, %r12 mulx 6*8(%rsi), %r8, %rdi adcx %r8, %r12 adcx %rdi, %r13 mulx 7*8(%rsi), %r8, %rdi adox %r8, %r13 adox %rdi, %r14 mulx 8*8(%rsi), %r8, %rdi adcx %r8, %r14 adcx %rdi, %r15 mulx 9*8(%rsi), %r8, %rdi adox %r8, %r15 adcx %rsp, %rdi adox %rsp, %rdi mov $0, %rdx test %rdi, %rdi setns %dl js L(10) add %rax, %rax adc %r9, %r9 adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 adc %r13, %r13 adc %r14, %r14 adc %r15, %r15 adc %rdi, %rdi L(10): vmovq %xmm1, %r8 vmovq %xmm0, %rsp mov %r9, 0*8(%r8) mov %r10, 1*8(%r8) mov %r11, 2*8(%r8) mov %rbx, 3*8(%r8) mov %rbp, 4*8(%r8) mov %r12, 5*8(%r8) mov %r13, 6*8(%r8) mov %r14, 7*8(%r8) mov %r15, 8*8(%r8) mov %rdi, 9*8(%r8) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_11) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 vmovq %rsp, %xmm0 vmovq %rdi, %xmm1 mov %rdx, %rcx mov 0*8(%rdx), %rdx xor %esp, %esp mulx 9*8(%rsi), %r8, %rax mulx 10*8(%rsi), %r8, %r9 adcx %r8, %rax adcx %rsp, %r9 mov 1*8(%rcx), %rdx mulx 8*8(%rsi), %r8, %r11 mulx 9*8(%rsi), %r8, %r10 adcx %r11, %rax adox %r8, %rax adcx %r10, %r9 mulx 10*8(%rsi), %r8, %r10 adox %r8, %r9 adcx %rsp, %r10 adox %rsp, %r10 mov 2*8(%rcx), %rdx mulx 7*8(%rsi), %r8, %rbx mulx 8*8(%rsi), %r8, %r11 adcx %rbx, %rax adox %r8, %rax adcx %r11, %r9 mulx 9*8(%rsi), %r8, %r11 adox %r8, %r9 adcx %r11, %r10 mulx 10*8(%rsi), %r8, %r11 adox %r8, %r10 adcx %rsp, %r11 adox %rsp, %r11 mov 3*8(%rcx), %rdx mulx 6*8(%rsi), %r8, %rbp mulx 7*8(%rsi), %r8, %rbx adcx %rbp, %rax adox %r8, %rax adcx %rbx, %r9 mulx 8*8(%rsi), %r8, %rbx adox %r8, %r9 adcx %rbx, %r10 mulx 9*8(%rsi), %r8, %rbx adox %r8, %r10 adcx %rbx, %r11 mulx 10*8(%rsi), %r8, %rbx adox %r8, %r11 adcx %rsp, %rbx adox %rsp, %rbx mov 4*8(%rcx), %rdx mulx 5*8(%rsi), %r8, %r12 mulx 6*8(%rsi), %r8, %rbp adcx %r12, %rax adox %r8, %rax adcx %rbp, %r9 mulx 7*8(%rsi), %r8, %rbp adox %r8, %r9 adcx %rbp, %r10 mulx 8*8(%rsi), %r8, %rbp adox %r8, %r10 adcx %rbp, %r11 mulx 9*8(%rsi), %r8, %rbp adox %r8, %r11 adcx %rbp, %rbx mulx 10*8(%rsi), %r8, %rbp adox %r8, %rbx adcx %rsp, %rbp adox %rsp, %rbp mov 5*8(%rcx), %rdx mulx 4*8(%rsi), %r8, %r13 mulx 5*8(%rsi), %r8, %r12 adcx %r13, %rax adox %r8, %rax adcx %r12, %r9 mulx 6*8(%rsi), %r8, %r12 adox %r8, %r9 adcx %r12, %r10 mulx 7*8(%rsi), %r8, %r12 adox %r8, %r10 adcx %r12, %r11 mulx 8*8(%rsi), %r8, %r12 adox %r8, %r11 adcx %r12, %rbx mulx 9*8(%rsi), %r8, %r12 adox %r8, %rbx adcx %r12, %rbp mulx 10*8(%rsi), %r8, %r12 adox %r8, %rbp adcx %rsp, %r12 adox %rsp, %r12 mov 6*8(%rcx), %rdx mulx 3*8(%rsi), %r8, %r14 mulx 4*8(%rsi), %r8, %r13 adcx %r14, %rax adox %r8, %rax adcx %r13, %r9 mulx 5*8(%rsi), %r8, %r13 adox %r8, %r9 adcx %r13, %r10 mulx 6*8(%rsi), %r8, %r13 adox %r8, %r10 adcx %r13, %r11 mulx 7*8(%rsi), %r8, %r13 adox %r8, %r11 adcx %r13, %rbx mulx 8*8(%rsi), %r8, %r13 adox %r8, %rbx adcx %r13, %rbp mulx 9*8(%rsi), %r8, %r13 adox %r8, %rbp adcx %r13, %r12 mulx 10*8(%rsi), %r8, %r13 adox %r8, %r12 adcx %rsp, %r13 adox %rsp, %r13 mov 7*8(%rcx), %rdx mulx 2*8(%rsi), %r8, %r15 mulx 3*8(%rsi), %r8, %r14 adcx %r15, %rax adox %r8, %rax adcx %r14, %r9 mulx 4*8(%rsi), %r8, %r14 adox %r8, %r9 adcx %r14, %r10 mulx 5*8(%rsi), %r8, %r14 adox %r8, %r10 adcx %r14, %r11 mulx 6*8(%rsi), %r8, %r14 adox %r8, %r11 adcx %r14, %rbx mulx 7*8(%rsi), %r8, %r14 adox %r8, %rbx adcx %r14, %rbp mulx 8*8(%rsi), %r8, %r14 adox %r8, %rbp adcx %r14, %r12 mulx 9*8(%rsi), %r8, %r14 adox %r8, %r12 adcx %r14, %r13 mulx 10*8(%rsi), %r8, %r14 adox %r8, %r13 adcx %rsp, %r14 adox %rsp, %r14 mov 8*8(%rcx), %rdx mulx 1*8(%rsi), %r8, %rdi mulx 2*8(%rsi), %r8, %r15 adcx %rdi, %rax adox %r8, %rax adcx %r15, %r9 mulx 3*8(%rsi), %r8, %r15 adox %r8, %r9 adcx %r15, %r10 mulx 4*8(%rsi), %r8, %r15 adox %r8, %r10 adcx %r15, %r11 mulx 5*8(%rsi), %r8, %r15 adox %r8, %r11 adcx %r15, %rbx mulx 6*8(%rsi), %r8, %r15 adox %r8, %rbx adcx %r15, %rbp mulx 7*8(%rsi), %r8, %r15 adox %r8, %rbp adcx %r15, %r12 mulx 8*8(%rsi), %r8, %r15 adox %r8, %r12 adcx %r15, %r13 mulx 9*8(%rsi), %r8, %r15 adox %r8, %r13 adcx %r15, %r14 mulx 10*8(%rsi), %r8, %r15 adox %r8, %r14 adcx %rsp, %r15 adox %rsp, %r15 mov 9*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rdi adcx %rdi, %rax mulx 1*8(%rsi), %r8, %rdi adox %r8, %rax adcx %rdi, %r9 mulx 2*8(%rsi), %r8, %rdi adox %r8, %r9 adcx %rdi, %r10 mulx 3*8(%rsi), %r8, %rdi adox %r8, %r10 adcx %rdi, %r11 mulx 4*8(%rsi), %r8, %rdi adox %r8, %r11 adcx %rdi, %rbx mulx 5*8(%rsi), %r8, %rdi adox %r8, %rbx adcx %rdi, %rbp mulx 6*8(%rsi), %r8, %rdi adox %r8, %rbp adcx %rdi, %r12 mulx 7*8(%rsi), %r8, %rdi adox %r8, %r12 adcx %rdi, %r13 mulx 8*8(%rsi), %r8, %rdi adox %r8, %r13 adcx %rdi, %r14 mulx 9*8(%rsi), %r8, %rdi adox %r8, %r14 adcx %rdi, %r15 mulx 10*8(%rsi), %r8, %rdi adox %r8, %r15 adcx %rsp, %rdi adox %rsp, %rdi mov 10*8(%rcx), %rdx mulx 0*8(%rsi), %r8, %rcx adcx %r8, %rax adcx %rcx, %r9 mulx 1*8(%rsi), %r8, %rcx adox %r8, %r9 adox %rcx, %r10 mulx 2*8(%rsi), %r8, %rcx adcx %r8, %r10 adcx %rcx, %r11 mulx 3*8(%rsi), %r8, %rcx adox %r8, %r11 adox %rcx, %rbx mulx 4*8(%rsi), %r8, %rcx adcx %r8, %rbx adcx %rcx, %rbp mulx 5*8(%rsi), %r8, %rcx adox %r8, %rbp adox %rcx, %r12 mulx 6*8(%rsi), %r8, %rcx adcx %r8, %r12 adcx %rcx, %r13 mulx 7*8(%rsi), %r8, %rcx adox %r8, %r13 adox %rcx, %r14 mulx 8*8(%rsi), %r8, %rcx adcx %r8, %r14 adcx %rcx, %r15 mulx 9*8(%rsi), %r8, %rcx adox %r8, %r15 adox %rcx, %rdi mulx 10*8(%rsi), %r8, %rcx adcx %r8, %rdi adcx %rsp, %rcx adox %rsp, %rcx mov $0, %rdx test %rcx, %rcx setns %dl js L(11) add %rax, %rax adc %r9, %r9 adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 adc %r13, %r13 adc %r14, %r14 adc %r15, %r15 adc %rdi, %rdi adc %rcx, %rcx L(11): vmovq %xmm1, %r8 vmovq %xmm0, %rsp mov %r9, 0*8(%r8) mov %r10, 1*8(%r8) mov %r11, 2*8(%r8) mov %rbx, 3*8(%r8) mov %rbp, 4*8(%r8) mov %r12, 5*8(%r8) mov %r13, 6*8(%r8) mov %r14, 7*8(%r8) mov %r15, 8*8(%r8) mov %rdi, 9*8(%r8) mov %rcx, 10*8(%r8) pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_mulhigh_normalised_12) push %rbx push %rbp push %r12 push %r13 push %r14 push %r15 vmovq %rsp, %xmm0 vmovq %rdi, %xmm1 mov %rdx, %rcx mov 0*8(%rdx), %rdx mulx 10*8(%rsi), %rsp, %rax mulx 11*8(%rsi), %rsp, %r8 add %rsp, %rax adc $0, %r8 test %al, %al mov 1*8(%rcx), %rdx mulx 9*8(%rsi), %rsp, %r10 mulx 10*8(%rsi), %rsp, %r9 adcx %r10, %rax adox %rsp, %rax adcx %r9, %r8 mulx 11*8(%rsi), %rsp, %r9 adox %rsp, %r8 mov $0, %esp adcx %rsp, %r9 adox %rsp, %r9 mov 2*8(%rcx), %rdx mulx 8*8(%rsi), %rsp, %r11 mulx 9*8(%rsi), %rsp, %r10 adcx %r11, %rax adox %rsp, %rax adcx %r10, %r8 mulx 10*8(%rsi), %rsp, %r10 adox %rsp, %r8 adcx %r10, %r9 mulx 11*8(%rsi), %rsp, %r10 adox %rsp, %r9 mov $0, %esp adcx %rsp, %r10 adox %rsp, %r10 mov 3*8(%rcx), %rdx mulx 7*8(%rsi), %rsp, %rbx mulx 8*8(%rsi), %rsp, %r11 adcx %rbx, %rax adox %rsp, %rax adcx %r11, %r8 mulx 9*8(%rsi), %rsp, %r11 adox %rsp, %r8 adcx %r11, %r9 mulx 10*8(%rsi), %rsp, %r11 adox %rsp, %r9 adcx %r11, %r10 mulx 11*8(%rsi), %rsp, %r11 adox %rsp, %r10 mov $0, %esp adcx %rsp, %r11 adox %rsp, %r11 mov 4*8(%rcx), %rdx mulx 6*8(%rsi), %rsp, %rbp mulx 7*8(%rsi), %rsp, %rbx adcx %rbp, %rax adox %rsp, %rax adcx %rbx, %r8 mulx 8*8(%rsi), %rsp, %rbx adox %rsp, %r8 adcx %rbx, %r9 mulx 9*8(%rsi), %rsp, %rbx adox %rsp, %r9 adcx %rbx, %r10 mulx 10*8(%rsi), %rsp, %rbx adox %rsp, %r10 adcx %rbx, %r11 mulx 11*8(%rsi), %rsp, %rbx adox %rsp, %r11 mov $0, %esp adcx %rsp, %rbx adox %rsp, %rbx mov 5*8(%rcx), %rdx mulx 5*8(%rsi), %rsp, %r12 mulx 6*8(%rsi), %rsp, %rbp adcx %r12, %rax adox %rsp, %rax adcx %rbp, %r8 mulx 7*8(%rsi), %rsp, %rbp adox %rsp, %r8 adcx %rbp, %r9 mulx 8*8(%rsi), %rsp, %rbp adox %rsp, %r9 adcx %rbp, %r10 mulx 9*8(%rsi), %rsp, %rbp adox %rsp, %r10 adcx %rbp, %r11 mulx 10*8(%rsi), %rsp, %rbp adox %rsp, %r11 adcx %rbp, %rbx mulx 11*8(%rsi), %rsp, %rbp adox %rsp, %rbx mov $0, %esp adcx %rsp, %rbp adox %rsp, %rbp mov 6*8(%rcx), %rdx mulx 4*8(%rsi), %rsp, %r13 mulx 5*8(%rsi), %rsp, %r12 adcx %r13, %rax adox %rsp, %rax adcx %r12, %r8 mulx 6*8(%rsi), %rsp, %r12 adox %rsp, %r8 adcx %r12, %r9 mulx 7*8(%rsi), %rsp, %r12 adox %rsp, %r9 adcx %r12, %r10 mulx 8*8(%rsi), %rsp, %r12 adox %rsp, %r10 adcx %r12, %r11 mulx 9*8(%rsi), %rsp, %r12 adox %rsp, %r11 adcx %r12, %rbx mulx 10*8(%rsi), %rsp, %r12 adox %rsp, %rbx adcx %r12, %rbp mulx 11*8(%rsi), %rsp, %r12 adox %rsp, %rbp mov $0, %esp adcx %rsp, %r12 adox %rsp, %r12 mov 7*8(%rcx), %rdx mulx 3*8(%rsi), %rsp, %r14 mulx 4*8(%rsi), %rsp, %r13 adcx %r14, %rax adox %rsp, %rax adcx %r13, %r8 mulx 5*8(%rsi), %rsp, %r13 adox %rsp, %r8 adcx %r13, %r9 mulx 6*8(%rsi), %rsp, %r13 adox %rsp, %r9 adcx %r13, %r10 mulx 7*8(%rsi), %rsp, %r13 adox %rsp, %r10 adcx %r13, %r11 mulx 8*8(%rsi), %rsp, %r13 adox %rsp, %r11 adcx %r13, %rbx mulx 9*8(%rsi), %rsp, %r13 adox %rsp, %rbx adcx %r13, %rbp mulx 10*8(%rsi), %rsp, %r13 adox %rsp, %rbp adcx %r13, %r12 mulx 11*8(%rsi), %rsp, %r13 adox %rsp, %r12 mov $0, %esp adcx %rsp, %r13 adox %rsp, %r13 mov 8*8(%rcx), %rdx mulx 2*8(%rsi), %rsp, %r15 mulx 3*8(%rsi), %rsp, %r14 adcx %r15, %rax adox %rsp, %rax adcx %r14, %r8 mulx 4*8(%rsi), %rsp, %r14 adox %rsp, %r8 adcx %r14, %r9 mulx 5*8(%rsi), %rsp, %r14 adox %rsp, %r9 adcx %r14, %r10 mulx 6*8(%rsi), %rsp, %r14 adox %rsp, %r10 adcx %r14, %r11 mulx 7*8(%rsi), %rsp, %r14 adox %rsp, %r11 adcx %r14, %rbx mulx 8*8(%rsi), %rsp, %r14 adox %rsp, %rbx adcx %r14, %rbp mulx 9*8(%rsi), %rsp, %r14 adox %rsp, %rbp adcx %r14, %r12 mulx 10*8(%rsi), %rsp, %r14 adox %rsp, %r12 adcx %r14, %r13 mulx 11*8(%rsi), %rsp, %r14 adox %rsp, %r13 mov $0, %esp adcx %rsp, %r14 adox %rsp, %r14 mov 9*8(%rcx), %rdx mulx 1*8(%rsi), %rsp, %rdi mulx 2*8(%rsi), %rsp, %r15 adcx %rdi, %rax adox %rsp, %rax adcx %r15, %r8 mulx 3*8(%rsi), %rsp, %r15 adox %rsp, %r8 adcx %r15, %r9 mulx 4*8(%rsi), %rsp, %r15 adox %rsp, %r9 adcx %r15, %r10 mulx 5*8(%rsi), %rsp, %r15 adox %rsp, %r10 adcx %r15, %r11 mulx 6*8(%rsi), %rsp, %r15 adox %rsp, %r11 adcx %r15, %rbx mulx 7*8(%rsi), %rsp, %r15 adox %rsp, %rbx adcx %r15, %rbp mulx 8*8(%rsi), %rsp, %r15 adox %rsp, %rbp adcx %r15, %r12 mulx 9*8(%rsi), %rsp, %r15 adox %rsp, %r12 adcx %r15, %r13 mulx 10*8(%rsi), %rsp, %r15 adox %rsp, %r13 adcx %r15, %r14 mulx 11*8(%rsi), %rsp, %r15 adox %rsp, %r14 mov $0, %esp adcx %rsp, %r15 adox %rsp, %r15 mov 10*8(%rcx), %rdx mulx 0*8(%rsi), %rsp, %rdi adcx %rdi, %rax mulx 1*8(%rsi), %rsp, %rdi adox %rsp, %rax adcx %rdi, %r8 mulx 2*8(%rsi), %rsp, %rdi adox %rsp, %r8 adcx %rdi, %r9 mulx 3*8(%rsi), %rsp, %rdi adox %rsp, %r9 adcx %rdi, %r10 mulx 4*8(%rsi), %rsp, %rdi adox %rsp, %r10 adcx %rdi, %r11 mulx 5*8(%rsi), %rsp, %rdi adox %rsp, %r11 adcx %rdi, %rbx mulx 6*8(%rsi), %rsp, %rdi adox %rsp, %rbx adcx %rdi, %rbp mulx 7*8(%rsi), %rsp, %rdi adox %rsp, %rbp adcx %rdi, %r12 mulx 8*8(%rsi), %rsp, %rdi adox %rsp, %r12 adcx %rdi, %r13 mulx 9*8(%rsi), %rsp, %rdi adox %rsp, %r13 adcx %rdi, %r14 mulx 10*8(%rsi), %rsp, %rdi adox %rsp, %r14 adcx %rdi, %r15 mulx 11*8(%rsi), %rsp, %rdi adox %rsp, %r15 mov $0, %esp adcx %rsp, %rdi adox %rsp, %rdi mov 11*8(%rcx), %rdx mulx 0*8(%rsi), %rsp, %rcx adcx %rsp, %rax adcx %rcx, %r8 mulx 1*8(%rsi), %rsp, %rcx adox %rsp, %r8 adox %rcx, %r9 mulx 2*8(%rsi), %rsp, %rcx adcx %rsp, %r9 adcx %rcx, %r10 mulx 3*8(%rsi), %rsp, %rcx adox %rsp, %r10 adox %rcx, %r11 mulx 4*8(%rsi), %rsp, %rcx adcx %rsp, %r11 adcx %rcx, %rbx mulx 5*8(%rsi), %rsp, %rcx adox %rsp, %rbx adox %rcx, %rbp mulx 6*8(%rsi), %rsp, %rcx adcx %rsp, %rbp adcx %rcx, %r12 mulx 7*8(%rsi), %rsp, %rcx adox %rsp, %r12 adox %rcx, %r13 mulx 8*8(%rsi), %rsp, %rcx adcx %rsp, %r13 adcx %rcx, %r14 mulx 9*8(%rsi), %rsp, %rcx adox %rsp, %r14 adox %rcx, %r15 mulx 10*8(%rsi), %rsp, %rcx adcx %rsp, %r15 adcx %rcx, %rdi mulx 11*8(%rsi), %rsp, %rcx adox %rsp, %rdi mov $0, %esp adcx %rsp, %rcx adox %rsp, %rcx mov $0, %rdx test %rcx, %rcx setns %dl js L(12) add %rax, %rax adc %r8, %r8 adc %r9, %r9 adc %r10, %r10 adc %r11, %r11 adc %rbx, %rbx adc %rbp, %rbp adc %r12, %r12 adc %r13, %r13 adc %r14, %r14 adc %r15, %r15 adc %rdi, %rdi adc %rcx, %rcx L(12): vmovq %xmm1, %rsp mov %r8, 0*8(%rsp) mov %r9, 1*8(%rsp) mov %r10, 2*8(%rsp) mov %r11, 3*8(%rsp) mov %rbx, 4*8(%rsp) mov %rbp, 5*8(%rsp) mov %r12, 6*8(%rsp) mov %r13, 7*8(%rsp) mov %r14, 8*8(%rsp) mov %r15, 9*8(%rsp) mov %rdi, 10*8(%rsp) mov %rcx, 11*8(%rsp) vmovq %xmm0, %rsp pop %r15 pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() flint-3.1.3/src/mpn_extras/broadwell/sqr_hard.asm000066400000000000000000000537441461254215100220770ustar00rootroot00000000000000dnl dnl Copyright (C) 2023, 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') define(`rp', `%rdi') define(`ap', `%rsi') define(`s0', `%rcx') define(`s1', `%r8') define(`s2', `%r9') define(`s3', `%r10') define(`s4', `%r11') define(`s5', `%rbx') define(`s6', `%rbp') define(`s7', `%r12') define(`s8', `%r13') define(`s9', `%r14') define(`s10', `%r15') define(`sx', `%rax') TEXT ALIGN(16) PROLOGUE(flint_mpn_sqr_1) mov 0*8(ap), %rdx mulx %rdx, s0, sx mov s0, 0*8(rp) mov sx, 1*8(rp) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqr_2) mov 0*8(ap), %rdx mulx 1*8(ap), s1, s2 C a0 a1 mulx %rdx, s3, s4 C a0^2 add s1, s1 adc s2, s2 mov 1*8(ap), %rdx mulx %rdx, s0, sx C a1^2 mov s3, 0*8(rp) adc $0, sx add s4, s1 adc s0, s2 adc $0, sx mov s1, 1*8(rp) mov s2, 2*8(rp) mov sx, 3*8(rp) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqr_3) mov 0*8(ap), %rdx mulx 1*8(ap), sx, s0 C a0 a1 mulx 2*8(ap), s1, s2 C a0 a2 add s0, s1 mov 1*8(ap), %rdx mulx 2*8(ap), s3, s4 C a1 a2 mov $0, R32(s0) adc s2, s3 adc s0, s4 add sx, sx adc s1, s1 adc s3, s3 adc s4, s4 mov 0*8(ap), %rdx mulx %rdx, %rdx, s2 C a0^2 adc R32(s0), R32(s0) mov %rdx, 0*8(rp) add s2, sx mov sx, 1*8(rp) mov 1*8(ap), %rdx mulx %rdx, s2, sx C a1^2 adc s2, s1 adc sx, s3 mov 2*8(ap), %rdx mulx %rdx, s2, sx C a2^2 mov s1, 2*8(rp) mov s3, 3*8(rp) adc s4, s2 adc s0, sx mov s2, 4*8(rp) mov sx, 5*8(rp) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqr_4) mov 0*8(ap), %rdx push s5 push s6 xor R32(s0), R32(s0) mulx 1*8(ap), s1, s4 C a0 a1 mulx 2*8(ap), s3, s2 C a0 a2 mulx 3*8(ap), s5, s6 C a0 a3 mov 1*8(ap), %rdx adox s4, s3 adox s2, s5 mulx 2*8(ap), s4, s2 C a1 a2 adcx s4, s5 adcx s2, s6 mulx 3*8(ap), s4, s2 C a1 a3 mov 2*8(ap), %rdx adox s4, s6 adox s0, s2 mulx 3*8(ap), %rdx, s4 C a1 a3 adc %rdx, s2 adc s0, s4 mov 0*8(ap), %rdx add s1, s1 adc s3, s3 adc s5, s5 adc s6, s6 adc s2, s2 adc s4, s4 setc R8(s0) mulx %rdx, %rdx, sx C a0^2 mov %rdx, 0*8(rp) add sx, s1 mov 1*8(ap), %rdx mov s1, 1*8(rp) mulx %rdx, %rdx, sx C a1^2 adc %rdx, s3 adc sx, s5 mov 2*8(ap), %rdx mov s3, 2*8(rp) mov s5, 3*8(rp) mulx %rdx, s1, sx C a2^2 adc s1, s6 adc sx, s2 mov 3*8(ap), %rdx mov s6, 4*8(rp) mov s2, 5*8(rp) mulx %rdx, s1, sx C a3^2 adc s1, s4 adc s0, sx mov s4, 6*8(rp) mov sx, 7*8(rp) pop s6 pop s5 ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqr_5) mov 0*8(ap), %rdx push s5 push s6 push s7 xor R32(s0), R32(s0) mulx 1*8(ap), sx, s2 C a0 a1 mulx 2*8(ap), s3, s4 C a0 a2 mulx 3*8(ap), s5, s1 C a0 a3 mulx 4*8(ap), s6, s7 C a0 a4 adcx s2, s3 adcx s4, s5 adcx s1, s6 C x, 3, 5, 6, 7 mov 1*8(ap), %rdx mulx 2*8(ap), s2, s4 C a1 a2 adcx s0, s7 adcx s2, s5 mulx 3*8(ap), s2, s1 C a1 a3 adcx s4, s6 adox s2, s6 mulx 4*8(ap), s2, s4 C a1 a4 adox s1, s7 adcx s2, s7 adcx s0, s4 C x, 3, 5, 6, 7, 4 mov 2*8(ap), %rdx mulx 3*8(ap), s1, s2 C a2 a3 adcx s1, s7 adcx s2, s4 mulx 4*8(ap), s1, s2 C a2 a4 adox s1, s4 C x, 3, 5, 6, 7, 4, 2 mov 3*8(ap), %rdx mulx 4*8(ap), %rdx, s1 C a3 a4 adox s0, s2 adc %rdx, s2 adc s0, s1 C x, 3, 5, 6, 7, 4, 2, 1 mov 0*8(ap), %rdx add sx, sx adc s3, s3 mov sx, -1*8(%rsp) adc s5, s5 adc s6, s6 mulx %rdx, %rdx, sx C a0^2 adc s7, s7 adc s4, s4 adc s2, s2 adc s1, s1 setc R8(s0) C x, 3, 5, 6, 7, 4, 2, 1, 0 mov %rdx, 0*8(rp) add -1*8(%rsp), sx mov sx, 1*8(rp) mov 1*8(ap), %rdx mulx %rdx, %rdx, sx C a1^2 adc %rdx, s3 adc sx, s5 mov s3, 2*8(rp) mov 2*8(ap), %rdx mulx %rdx, s3, sx C a2^2 mov s5, 3*8(rp) adc s3, s6 adc sx, s7 mov s6, 4*8(rp) mov 3*8(ap), %rdx mulx %rdx, s3, sx C a3^2 mov s7, 5*8(rp) adc s3, s4 adc sx, s2 mov s4, 6*8(rp) mov 4*8(ap), %rdx mulx %rdx, s3, sx C a4^2 mov s2, 7*8(rp) adc s1, s3 adc s0, sx mov s3, 8*8(rp) mov sx, 9*8(rp) pop s7 pop s6 pop s5 ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqr_6) mov 0*8(ap), %rdx push s5 push s6 push s7 push s8 push s9 xor R32(s0), R32(s0) mulx 1*8(ap), sx, s2 C a0 a1 mulx 2*8(ap), s3, s4 C a0 a2 mulx 3*8(ap), s5, s1 C a0 a3 mulx 4*8(ap), s6, s9 C a0 a4 mulx 5*8(ap), s7, s8 C a0 a5 adox s2, s3 adox s4, s5 adox s1, s6 adox s9, s7 adox s0, s8 C x, 3, 5, 6, 7, 8 mov 1*8(ap), %rdx mulx 2*8(ap), s2, s4 C a1 a2 mulx 3*8(ap), s1, s9 C a1 a3 adcx s2, s5 adcx s4, s6 adox s1, s6 adox s9, s7 mulx 4*8(ap), s2, s4 C a1 a4 mulx 5*8(ap), s1, s9 C a1 a5 adcx s2, s7 adcx s4, s8 adox s1, s8 C x, 3, 5, 6, 7, 8, 9 mov 2*8(ap), %rdx mulx 3*8(ap), s1, s2 C a2 a3 adcx s0, s9 adox s0, s9 adcx s1, s7 adcx s2, s8 mulx 4*8(ap), s4, s1 C a2 a4 mulx 5*8(ap), %rdx, s2 C a2 a5 adox s4, s8 adox s1, s9 adcx %rdx, s9 C x, 3, 5, 6, 7, 8, 9, 2 mov 3*8(ap), %rdx mulx 4*8(ap), s1, s4 C a3 a4 adcx s0, s2 adcx s1, s9 mulx 5*8(ap), %rdx, s1 C a3 a5 adcx s4, s2 adox %rdx, s2 adox s0, s1 C x, 3, 5, 6, 7, 8, 9, 2, 1 mov 4*8(ap), %rdx mulx 5*8(ap), %rdx, s4 C a4 a5 adcx %rdx, s1 adcx s0, s4 C x, 3, 5, 6, 7, 8, 9, 2, 1, 4 add sx, sx adc s3, s3 mov 0*8(ap), %rdx mov sx, -1*8(%rsp) adc s5, s5 adc s6, s6 mulx %rdx, %rdx, sx adc s7, s7 adc s8, s8 adc s9, s9 adc s2, s2 adc s1, s1 adc s4, s4 setc R8(s0) C x, 3, 5, 6, 7, 8, 9, 2, 1, 4, 0 mov %rdx, 0*8(rp) add -1*8(%rsp), sx mov sx, 1*8(rp) mov 1*8(ap), %rdx mulx %rdx, %rdx, sx C a1^2 adc %rdx, s3 adc sx, s5 mov s3, 2*8(rp) mov 2*8(ap), %rdx mulx %rdx, s3, sx C a2^2 mov s5, 3*8(rp) adc s3, s6 adc sx, s7 mov s6, 4*8(rp) mov 3*8(ap), %rdx mulx %rdx, s3, sx C a3^2 mov s7, 5*8(rp) adc s3, s8 adc sx, s9 mov s8, 6*8(rp) mov 4*8(ap), %rdx mulx %rdx, s3, sx C a4^2 mov s9, 7*8(rp) adc s3, s2 adc sx, s1 mov s2, 8*8(rp) mov 5*8(ap), %rdx mulx %rdx, s3, sx C a5^2 mov s1, 9*8(rp) adc s4, s3 adc s0, sx mov s3, 10*8(rp) mov sx, 11*8(rp) pop s9 pop s8 pop s7 pop s6 pop s5 ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqr_7) mov 0*8(ap), %rdx push s5 push s6 push s7 push s8 push s9 push s10 xor R32(s0), R32(s0) mulx 1*8(ap), sx, s1 C a0 a1 mulx 2*8(ap), s3, s2 C a0 a2 mulx 3*8(ap), s5, s4 C a0 a3 mulx 4*8(ap), s6, s10 C a0 a4 mov sx, -2*8(%rsp) adox s1, s3 adox s2, s5 mov s3, -1*8(%rsp) mulx 5*8(ap), s7, s1 C a0 a5 mulx 6*8(ap), s8, s9 C a0 a6 adox s4, s6 adox s10, s7 adox s1, s8 adox s0, s9 C (-, -,) 5, 6, 7, 8, 9 C x, 1, 2, 3, 4, 10 mov 1*8(ap), %rdx mulx 2*8(ap), sx, s1 C a1 a2 mulx 3*8(ap), s2, s3 C a1 a3 adox sx, s5 adox s1, s6 adcx s2, s6 adcx s3, s7 mulx 4*8(ap), sx, s1 C a1 a4 mulx 5*8(ap), s2, s3 C a1 a5 mulx 6*8(ap), s4, s10 C a1 a6 adox sx, s7 adox s1, s8 adcx s2, s8 adcx s3, s9 adox s4, s9 adox s0, s10 adcx s0, s10 C (-, -,) 5, 6, 7, 8, 9, 10 C x, 1, 2, 3, 4 mov 2*8(ap), %rdx mulx 3*8(ap), sx, s1 C a2 a3 mulx 4*8(ap), s2, s3 C a2 a4 adox sx, s7 adox s1, s8 adcx s2, s8 adcx s3, s9 mulx 5*8(ap), sx, s1 C a2 a5 mulx 6*8(ap), s2, s3 C a2 a6 adox sx, s9 adox s1, s10 adcx s2, s10 adcx s0, s3 adox s0, s3 C (-, -,) 5, 6, 7, 8, 9, 10, 3 C x, 1, 2, 4 mov 3*8(ap), %rdx mulx 4*8(ap), sx, s1 C a3 a4 mulx 5*8(ap), s2, s4 C a3 a5 adox sx, s9 adox s1, s10 mulx 6*8(ap), sx, s1 C a3 a6 adcx s2, s10 adcx s4, s3 adox sx, s3 adox s0, s1 C (-, -,) 5, 6, 7, 8, 9, 10, 3, 1 C x, 2, 4 mov 4*8(ap), %rdx mulx 5*8(ap), sx, s2 C a4 a5 mulx 6*8(ap), %rdx, s4 C a4 a6 adox sx, s3 adox s2, s1 adcx %rdx, s1 adox s0, s4 C (-, -,) 5, 6, 7, 8, 9, 10, 3, 1, 4 C x, 2 mov 5*8(ap), %rdx mulx 6*8(ap), sx, s2 C a5 a6 adc sx, s4 adc s0, s2 C (-, -,) 5, 6, 7, 8, 9, 10, 3, 1, 4, 2 C x shlq -2*8(%rsp) mov -1*8(%rsp), sx mov 0*8(ap), %rdx adc sx, sx adc s5, s5 mov sx, -1*8(%rsp) adc s6, s6 adc s7, s7 mulx %rdx, %rdx, sx adc s8, s8 adc s9, s9 adc s10, s10 adc s3, s3 adc s1, s1 adc s4, s4 adc s2, s2 setc R8(s0) C (-, -,) 5, 6, 7, 8, 9, 10, 3, 1, 4, 2, 0 C x add -2*8(%rsp), sx mov %rdx, 0*8(rp) mov sx, 1*8(rp) mov 1*8(ap), %rdx mulx %rdx, %rdx, sx C a1^2 adc -1*8(%rsp), %rdx mov %rdx, 2*8(rp) adc sx, s5 mov 2*8(ap), %rdx mulx %rdx, %rdx, sx C a2^2 mov s5, 3*8(rp) adc %rdx, s6 adc sx, s7 mov s6, 4*8(rp) mov 3*8(ap), %rdx mulx %rdx, s5, sx C a3^2 mov s7, 5*8(rp) adc s5, s8 adc sx, s9 mov s8, 6*8(rp) mov 4*8(ap), %rdx mulx %rdx, s5, sx C a4^2 mov s9, 7*8(rp) adc s5, s10 adc sx, s3 mov s10, 8*8(rp) mov 5*8(ap), %rdx mulx %rdx, s5, sx C a5^2 mov s3, 9*8(rp) adc s5, s1 adc sx, s4 mov s1, 10*8(rp) mov 6*8(ap), %rdx mulx %rdx, s3, sx C a6^2 mov s4, 11*8(rp) adc s2, s3 adc s0, sx mov s3, 12*8(rp) mov sx, 13*8(rp) pop s10 pop s9 pop s8 pop s7 pop s6 pop s5 ret EPILOGUE() define(`m0',`-4*8(%rsp)') define(`m1',`-3*8(%rsp)') define(`m2',`-2*8(%rsp)') define(`m3',`-1*8(%rsp)') ALIGN(16) PROLOGUE(flint_mpn_sqr_8) mov 0*8(ap), %rdx push s5 push s6 push s7 push s8 push s9 push s10 mulx 1*8(ap), sx, s1 C a0 a1 mulx 2*8(ap), s3, s7 C a0 a2 mulx 3*8(ap), s5, s4 C a0 a3 mulx 4*8(ap), s6, s2 C a0 a4 mov sx, m0 add s1, s3 adc s7, s5 mov s3, m1 mulx 5*8(ap), s7, sx C a0 a5 mulx 6*8(ap), s8, s1 C a0 a6 mulx 7*8(ap), s9, s10 C a0 a7 adc s4, s6 adc s2, s7 adc sx, s8 adc s1, s9 adc $0, s10 C (m0, m1,) 5, 6, 7, 8, 9, 10 C x, 1, 2, 3, 4 xor R32(s0), R32(s0) mov 1*8(ap), %rdx mulx 2*8(ap), s1, s2 C a1 a2 mulx 3*8(ap), s3, s4 C a1 a3 adox s1, s5 adox s2, s6 adcx s3, s6 adcx s4, s7 mulx 4*8(ap), s1, s2 C a1 a4 mulx 5*8(ap), s3, s4 C a1 a5 mov s5, m2 mov s6, m3 adox s1, s7 adox s2, s8 adcx s3, s8 adcx s4, s9 mulx 6*8(ap), s1, s2 C a1 a6 mulx 7*8(ap), s3, s4 C a1 a7 adox s1, s9 adox s2, s10 adcx s3, s10 adcx s0, s4 adox s0, s4 C (m0, m1, m2, m3,) 7, 8, 9, 10, 4 C x, 1, 2, 3, 5, 6 mov 2*8(ap), %rdx mulx 3*8(ap), sx, s1 C a2 a3 mulx 4*8(ap), s2, s3 C a2 a4 mulx 5*8(ap), s5, s6 C a2 a5 adox sx, s7 adox s1, s8 adcx s2, s8 adcx s3, s9 adox s5, s9 adox s6, s10 mulx 6*8(ap), sx, s1 C a2 a6 mulx 7*8(ap), s2, s3 C a2 a7 adcx sx, s10 adcx s1, s4 adox s2, s4 adox s0, s3 adcx s0, s3 C (m0, m1, m2, m3,) 7, 8, 9, 10, 4, 3 C x, 1, 2, 5, 6 mov 3*8(ap), %rdx mulx 4*8(ap), sx, s1 C a3 a4 mulx 5*8(ap), s2, s5 C a3 a5 adox sx, s9 adox s1, s10 adcx s2, s10 adcx s5, s4 mulx 6*8(ap), sx, s1 C a3 a6 mulx 7*8(ap), s2, s5 C a3 a7 adox sx, s4 adox s1, s3 adcx s2, s3 adcx s0, s5 adox s0, s5 C (m0, m1, m2, m3,) 7, 8, 9, 10, 4, 3, 5 C x, 1, 2, 6 mov 4*8(ap), %rdx mulx 5*8(ap), s2, s6 C a4 a5 mulx 6*8(ap), sx, s1 C a4 a6 adcx s2, s4 adcx s6, s3 adox sx, s3 adox s1, s5 mulx 7*8(ap), s2, s6 C a4 a7 adcx s2, s5 adcx s0, s6 C (m0, m1, m2, m3,) 7, 8, 9, 10, 4, 3, 5, 6 C x, 1, 2 mov 5*8(ap), %rdx mulx 6*8(ap), sx, s1 C a5 a6 mulx 7*8(ap), %rdx, s2 C a5 a7 adcx sx, s5 adcx s1, s6 adox %rdx, s6 adox s0, s2 C (m0, m1, m2, m3,) 7, 8, 9, 10, 4, 3, 5, 6, 2 C x, 1 mov 6*8(ap), %rdx mulx 7*8(ap), sx, s1 C a6 a7 adcx sx, s2 adcx s0, s1 C (m0, m1, m2, m3,) 7, 8, 9, 10, 4, 3, 5, 6, 2, 1 C x mov 0*8(ap), %rdx mulx %rdx, %rdx, sx C a0^2 mov %rdx, 0*8(rp) adox m0, sx adcx m0, sx mov sx, 1*8(rp) mov 1*8(ap), %rdx mulx %rdx, %rdx, sx C a1^2 adox m1, %rdx adcx m1, %rdx adox m2, sx adcx m2, sx mov %rdx, 2*8(rp) mov sx, 3*8(rp) mov 2*8(ap), %rdx mulx %rdx, %rdx, sx C a2^2 adox m3, %rdx adcx m3, %rdx adox s7, sx adcx s7, sx mov %rdx, 4*8(rp) mov sx, 5*8(rp) mov 3*8(ap), %rdx mulx %rdx, s7, sx C a3^2 adox s8, s7 adcx s8, s7 adox s9, sx adcx s9, sx mov s7, 6*8(rp) mov sx, 7*8(rp) mov 4*8(ap), %rdx mulx %rdx, s8, s9 C a4^2 adox s10, s8 adcx s10, s8 adox s4, s9 adcx s4, s9 mov s8, 8*8(rp) mov s9, 9*8(rp) mov 5*8(ap), %rdx mulx %rdx, s7, sx C a5^2 adox s3, s7 adcx s3, s7 adox s5, sx adcx s5, sx mov s7, 10*8(rp) mov sx, 11*8(rp) mov 6*8(ap), %rdx mulx %rdx, s8, s9 C a6^2 adox s6, s8 adcx s6, s8 adox s2, s9 adcx s2, s9 mov s8, 12*8(rp) mov s9, 13*8(rp) mov 7*8(ap), %rdx mulx %rdx, s3, sx C a7^2 adox s1, s3 adcx s1, s3 adox s0, sx adcx s0, sx mov s3, 14*8(rp) mov sx, 15*8(rp) pop s10 pop s9 pop s8 pop s7 pop s6 pop s5 ret EPILOGUE() undefine(`m0') undefine(`m1') undefine(`m2') undefine(`m3') define(`m',`eval($1-16)*8(%rsp)') ALIGN(16) PROLOGUE(flint_mpn_sqr_9) push s5 push s6 push s7 push s8 mov 0*8(ap), %rdx mulx 1*8(ap), sx, s0 C a0 a1 mulx 2*8(ap), s1, s2 C a0 a2 mulx 3*8(ap), s3, s4 C a0 a3 mulx 4*8(ap), s5, s6 C a0 a4 mulx 5*8(ap), s7, s8 C a0 a5 add s0, s1 adc s2, s3 movq $0, m(-1) mov sx, m(0) mov s1, m(1) adc s4, s5 adc s6, s7 mulx 6*8(ap), sx, s0 C a0 a6 mulx 7*8(ap), s1, s2 C a0 a7 mulx 8*8(ap), s4, s6 C a0 a8 adc s8, sx adc s0, s1 adc s2, s4 adc $0, s6 C m(0:1), 3, 5, 7, x, 1, 4, 6 C 2, 8 xor R32(s0), R32(s0) mov 1*8(ap), %rdx mulx 2*8(ap), s2, s8 C a1 a2 adox s2, s3 adox s8, s5 mulx 3*8(ap), s2, s8 C a1 a3 mov s3, m(2) adcx s2, s5 adcx s8, s7 mov s5, m(3) mulx 4*8(ap), s3, s2 C a1 a4 mulx 5*8(ap), s8, s5 C a1 a5 adox s3, s7 adox s2, sx adcx s8, sx adcx s5, s1 mulx 6*8(ap), s3, s2 C a1 a6 mulx 7*8(ap), s8, s5 C a1 a7 adox s3, s1 adox s2, s4 mulx 8*8(ap), s3, s2 C a1 a8 adcx s8, s4 adcx s5, s6 adox s3, s6 adox s0, s2 adcx s0, s2 C m(0:3), 7, x, 1, 4, 6, 2 C 3, 5, 8 mov 2*8(ap), %rdx mulx 3*8(ap), s3, s5 C a2 a3 adox s3, s7 adox s5, sx mov s7, m(4) mulx 4*8(ap), s8, s3 C a2 a4 mulx 5*8(ap), s5, s7 C a2 a5 adcx s8, sx adcx s3, s1 adox s5, s1 adox s7, s4 mov sx, m(5) mulx 6*8(ap), s8, s3 C a2 a6 mulx 7*8(ap), s5, s7 C a2 a7 adcx s8, s4 adcx s3, s6 adox s5, s6 adox s7, s2 mulx 8*8(ap), s8, s3 C a2 a8 adcx s8, s2 adcx s0, s3 adox s0, s3 C m(0:5), 1, 4, 6, 2, 3 C x, 5, 7, 8 mov 3*8(ap), %rdx mulx 4*8(ap), sx, s5 C a3 a4 mulx 5*8(ap), s7, s8 C a3 a5 adox sx, s1 adox s5, s4 adcx s7, s4 adcx s8, s6 mov s1, m(6) mov s4, m(7) mulx 6*8(ap), sx, s5 C a3 a6 mulx 7*8(ap), s7, s8 C a3 a7 mulx 8*8(ap), s1, s4 C a3 a8 adox sx, s6 adox s5, s2 adcx s7, s2 adcx s8, s3 adox s1, s3 adox s0, s4 adcx s0, s4 C m(0:7), 6, 2, 3, 4 C x, 1, 5, 7, 8 mov 4*8(ap), %rdx mulx 5*8(ap), sx, s1 C a4 a5 mulx 6*8(ap), s5, s7 C a4 a6 adox sx, s6 adox s1, s2 adcx s5, s2 adcx s7, s3 mov s6, m(8) mov s2, m(9) mulx 7*8(ap), sx, s1 C a4 a7 mulx 8*8(ap), s5, s7 C a4 a8 adox sx, s3 adox s1, s4 adcx s5, s4 adcx s0, s7 adox s0, s7 C m(0:9), 3, 4, 7 C x, 1, 2, 5, 6, 8 mov 5*8(ap), %rdx mulx 6*8(ap), sx, s1 C a5 a6 mulx 7*8(ap), s2, s5 C a5 a7 mulx 8*8(ap), s6, s8 C a5 a8 adox sx, s3 adox s1, s4 adcx s2, s4 adcx s5, s7 adox s6, s7 adox s0, s8 mov s3, m(10) mov s4, m(11) C m(0:11), 7, 8 C x, 1, 2, 3, 4, 5, 6 mov 6*8(ap), %rdx mulx 7*8(ap), sx, s1 C a6 a7 mulx 8*8(ap), s2, s3 C a6 a8 adox sx, s7 adox s1, s8 adox s0, s3 adc s2, s8 C m(0:13), 3 C x, 1, 2, 4, 5, 6, 7, 8 mov 7*8(ap), %rdx mulx 8*8(ap), sx, s1 C a7 a8 mov s7, m(12) mov s8, m(13) adc sx, s3 adc s0, s1 mov s3, m(14) mov s1, m(15) C m(0:15) (, 1) C x, 0, 2, 3, 4, 5, 6, 7, 8 mov 0*8(ap), %rdx mulx %rdx, sx, s0 C a0^2 vmovdqu m(0), %ymm0 vmovdqu m(-1), %ymm1 vmovdqu m(4), %ymm2 vmovdqu m(3), %ymm3 vmovdqu m(8), %ymm4 vmovdqu m(7), %ymm5 vmovdqu m(12), %ymm6 vmovdqu m(11), %ymm7 mov 1*8(ap), %rdx mulx %rdx, s2, s3 C a1^2 vpsllq $1, %ymm0, %ymm0 vpsrlq $63, %ymm1, %ymm1 vpsllq $1, %ymm2, %ymm2 vpsrlq $63, %ymm3, %ymm3 vpsllq $1, %ymm4, %ymm4 vpsrlq $63, %ymm5, %ymm5 mov 2*8(ap), %rdx mulx %rdx, s4, s5 C a2^2 vpsllq $1, %ymm6, %ymm6 vpsrlq $63, %ymm7, %ymm7 vpor %ymm1, %ymm0, %ymm0 vpor %ymm3, %ymm2, %ymm2 vpor %ymm5, %ymm4, %ymm4 vpor %ymm7, %ymm6, %ymm6 vmovdqu %ymm0, m(0) vmovdqu %ymm2, m(4) vmovdqu %ymm4, m(8) vmovdqu %ymm6, m(12) mov 3*8(ap), %rdx mulx %rdx, s6, s7 C a3^2 C m(0:15), 1 C x, 0, 2, 3, 4, 5, 6, 7, 8 shr $63, s1 mov sx, 0*8(rp) add m(0), s0 mov s0, 1*8(rp) adc m(1), s2 adc m(2), s3 mov s2, 2*8(rp) adc m(3), s4 mov s3, 3*8(rp) adc m(4), s5 mov s4, 4*8(rp) adc m(5), s6 mov s5, 5*8(rp) adc m(6), s7 mov 4*8(ap), %rdx mulx %rdx, sx, s0 C a4^2 mov s6, 6*8(rp) adc m(7), sx mov s7, 7*8(rp) adc m(8), s0 mov 5*8(ap), %rdx mulx %rdx, s2, s3 C a5^2 mov sx, 8*8(rp) adc m(9), s2 mov s0, 9*8(rp) adc m(10), s3 mov 6*8(ap), %rdx mulx %rdx, s4, s5 C a6^2 mov s2, 10*8(rp) adc m(11), s4 mov s3, 11*8(rp) adc m(12), s5 mov 7*8(ap), %rdx mulx %rdx, s6, s7 C a7^2 mov s4, 12*8(rp) adc m(13), s6 mov s5, 13*8(rp) adc m(14), s7 mov 8*8(ap), %rdx mulx %rdx, s0, sx C a8^2 mov s6, 14*8(rp) adc m(15), s0 mov s7, 15*8(rp) adc s1, sx mov s0, 16*8(rp) mov sx, 17*8(rp) vzeroupper pop s8 pop s7 pop s6 pop s5 ret EPILOGUE() undefine(`m') define(`m',`eval($1-16)*8(%rsp)') define(`r',`eval($1+8)*8(rp)') ALIGN(16) PROLOGUE(flint_mpn_sqr_10) push s5 push s6 push s7 push s8 push s9 mov 0*8(ap), %rdx mulx 1*8(ap), sx, s0 C a0 a1 mulx 2*8(ap), s1, s2 C a0 a2 mulx 3*8(ap), s3, s4 C a0 a3 mulx 4*8(ap), s5, s6 C a0 a4 mulx 5*8(ap), s7, s8 C a0 a5 lea -8*8(rp), rp add s0, s1 adc s2, s3 movq $0, m(-1) mov sx, m(0) mov s1, m(1) adc s4, s5 adc s6, s7 mulx 6*8(ap), sx, s0 C a0 a6 mulx 7*8(ap), s1, s2 C a0 a7 mulx 8*8(ap), s4, s6 C a0 a8 adc s8, sx adc s0, s1 mulx 9*8(ap), s9, s8 C a0 a9 adc s2, s4 adc s6, s9 adc $0, s8 C m(0:1), 3, 5, 7, x, 1, 4, 9, 8 C 2, 6 xor R32(s0), R32(s0) mov 1*8(ap), %rdx mulx 2*8(ap), s2, s6 C a1 a2 adox s2, s3 adox s6, s5 mulx 3*8(ap), s2, s6 C a1 a3 mov s3, m(2) adcx s2, s5 adcx s6, s7 mov s5, m(3) mulx 4*8(ap), s3, s2 C a1 a4 mulx 5*8(ap), s6, s5 C a1 a5 adox s3, s7 adox s2, sx adcx s6, sx adcx s5, s1 mulx 6*8(ap), s3, s2 C a1 a6 mulx 7*8(ap), s6, s5 C a1 a7 adox s3, s1 adox s2, s4 adcx s6, s4 adcx s5, s9 mulx 8*8(ap), s3, s2 C a1 a8 mulx 9*8(ap), s6, s5 C a1 a9 adox s3, s9 adox s2, s8 adcx s6, s8 adox s0, s5 adcx s0, s5 C m(0:3), 7, x, 1, 4, 9, 8, 5 C 2, 3, 6 mov 2*8(ap), %rdx mulx 3*8(ap), s2, s3 C a2 a3 adox s2, s7 adox s3, sx mov s7, m(4) mulx 4*8(ap), s6, s2 C a2 a4 mulx 5*8(ap), s3, s7 C a2 a5 adcx s6, sx adcx s2, s1 adox s3, s1 adox s7, s4 mov sx, m(5) mulx 6*8(ap), s6, s2 C a2 a6 mulx 7*8(ap), s3, s7 C a2 a7 adcx s6, s4 adcx s2, s9 adox s3, s9 adox s7, s8 mulx 8*8(ap), s6, s2 C a2 a8 mulx 9*8(ap), s3, s7 C a2 a9 adcx s6, s8 adcx s2, s5 adox s3, s5 adox s0, s7 adcx s0, s7 C m(0:5), 1, 4, 9, 8, 5, 7 C x, 2, 3, 6 mov 3*8(ap), %rdx mulx 4*8(ap), sx, s2 C a3 a4 mulx 5*8(ap), s3, s6 C a3 a5 adox sx, s1 adox s2, s4 adcx s3, s4 adcx s6, s9 mov s1, m(6) mov s4, m(7) mulx 6*8(ap), sx, s2 C a3 a6 mulx 7*8(ap), s3, s6 C a3 a7 adox sx, s9 adox s2, s8 adcx s3, s8 adcx s6, s5 mulx 8*8(ap), sx, s2 C a3 a8 mulx 9*8(ap), s3, s6 C a3 a9 adox sx, s5 adox s2, s7 adcx s3, s7 adcx s0, s6 adox s0, s6 C m(0:7), 9, 8, 5, 7, 6 C x, 1, 2, 3, 4 mov 4*8(ap), %rdx mulx 5*8(ap), sx, s1 C a4 a5 mulx 6*8(ap), s2, s3 C a4 a6 adox sx, s9 adox s1, s8 adcx s2, s8 adcx s3, s5 mov s9, m(8) mov s8, m(9) mulx 7*8(ap), sx, s1 C a4 a7 mulx 8*8(ap), s2, s3 C a4 a8 mulx 9*8(ap), s9, s8 C a4 a9 adox sx, s5 adox s1, s7 adcx s2, s7 adcx s3, s6 adox s9, s6 adox s0, s8 adcx s0, s8 C m(0:9), 5, 7, 6, 8 C x, 1, 2, 3, 4, 9 mov 5*8(ap), %rdx mulx 6*8(ap), sx, s1 C a5 a6 mulx 7*8(ap), s2, s3 C a5 a7 mulx 8*8(ap), s4, s9 C a5 a8 adox sx, s5 adox s1, s7 adcx s2, s7 adcx s3, s6 mulx 9*8(ap), sx, s1 C a5 a9 mov s5, m(10) mov s7, m(11) adox s4, s6 adox s9, s8 adcx sx, s8 adcx s0, s1 adox s0, s1 C m(0:11), 6, 8, 1 C x, 2, 3, 4, 5, 7, 9 mov 6*8(ap), %rdx mulx 7*8(ap), sx, s2 C a6 a7 mulx 8*8(ap), s3, s4 C a6 a8 mulx 9*8(ap), s5, s7 C a6 a9 adox sx, s6 adox s2, s8 adcx s3, s8 adcx s4, s1 adox s5, s1 adox s0, s7 C m(0:13), 1, 7 C x, 2, 3, 4, 5, 6, 8, 9 mov 7*8(ap), %rdx mulx 8*8(ap), sx, s2 C a7 a8 mulx 9*8(ap), s3, s4 C a7 a9 mov s6, m(12) mov s8, m(13) adox sx, s1 adox s2, s7 adox s0, s4 adc s3, s7 C m(0:15), (7), 4 C x, 1, 2, 3, 5, 6, 8, 9 mov 8*8(ap), %rdx mulx 9*8(ap), sx, s2 C a7 a9 mov s1, m(14) mov s7, m(15) adc sx, s4 adc s0, s2 C m(0:15), (7), 4, 2 C x, 1, 3, 5, 6, 8, 9 vmovdqu m(0), %ymm0 vmovdqu m(-1), %ymm1 vmovdqu m(4), %ymm2 vmovdqu m(3), %ymm3 vmovdqu m(8), %ymm4 vmovdqu m(7), %ymm5 vmovdqu m(12), %ymm6 vmovdqu m(11), %ymm7 vpsllq $1, %ymm0, %ymm0 vpsrlq $63, %ymm1, %ymm1 vpsllq $1, %ymm2, %ymm2 vpsrlq $63, %ymm3, %ymm3 vpsllq $1, %ymm4, %ymm4 vpsrlq $63, %ymm5, %ymm5 vpsllq $1, %ymm6, %ymm6 vpsrlq $63, %ymm7, %ymm7 vpor %ymm1, %ymm0, %ymm0 vpor %ymm3, %ymm2, %ymm2 vpor %ymm5, %ymm4, %ymm4 vpor %ymm7, %ymm6, %ymm6 vmovdqu %ymm0, m(0) vmovdqu %ymm2, m(4) vmovdqu %ymm4, m(8) vmovdqu %ymm6, m(12) mov $63, R32(sx) mov $1, R32(s5) mov 0*8(ap), %rdx mulx %rdx, s8, s9 C a0^2 shrx sx, s7, s7 shrx sx, s4, s1 shrx sx, s2, s3 shlx s5, s4, s4 shlx s5, s2, s2 mov 1*8(ap), %rdx mulx %rdx, s0, sx C a1^2 or s7, s4 or s1, s2 C m(0:15), 4, 2, 3 C x, 0, 1, 5, 6, 7, 8, 9 add m(0), s9 mov s8, r(0) mov s9, r(1) adc m(1), s0 adc m(2), sx mov 2*8(ap), %rdx mulx %rdx, s1, s5 C a2^2 mov s0, r(2) mov sx, r(3) adc m(3), s1 adc m(4), s5 mov 3*8(ap), %rdx mulx %rdx, s6, s7 C a3^2 mov s1, r(4) mov s5, r(5) adc m(5), s6 adc m(6), s7 mov 4*8(ap), %rdx mulx %rdx, s8, s9 C a4^2 mov s6, r(6) mov s7, r(7) adc m(7), s8 adc m(8), s9 mov 5*8(ap), %rdx mulx %rdx, s0, sx C a5^2 mov s8, r(8) mov s9, r(9) adc m(9), s0 adc m(10), sx mov 6*8(ap), %rdx mulx %rdx, s1, s5 C a6^2 mov s0, r(10) mov sx, r(11) adc m(11), s1 adc m(12), s5 mov 7*8(ap), %rdx mulx %rdx, s6, s7 C a7^2 mov s1, r(12) mov s5, r(13) adc m(13), s6 adc m(14), s7 mov 8*8(ap), %rdx mulx %rdx, s8, s9 C a8^2 mov s6, r(14) mov s7, r(15) adc m(15), s8 adc s4, s9 mov 9*8(ap), %rdx mulx %rdx, s0, sx C a9^2 mov s8, r(16) mov s9, r(17) adc s2, s0 adc s3, sx vzeroupper mov s0, r(18) mov sx, r(19) pop s9 pop s8 pop s7 pop s6 pop s5 ret EPILOGUE() undefine(`m') undefine(`r') flint-3.1.3/src/mpn_extras/broadwell/sqrhigh_basecase_even.asm000066400000000000000000000200761461254215100245740ustar00rootroot00000000000000dnl X64-64 mpn_mullo_basecase optimised for Intel Broadwell. dnl Contributed to the GNU project by Torbjorn Granlund. dnl Copyright 2017 Free Software Foundation, Inc. dnl This file is part of the GNU MP Library. dnl dnl The GNU MP Library is free software; you can redistribute it and/or modify dnl it under the terms of either: dnl dnl * the GNU Lesser General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your dnl option) any later version. dnl dnl or dnl dnl * the GNU General Public License as published by the Free Software dnl Foundation; either version 2 of the License, or (at your option) any dnl later version. dnl dnl or both in parallel, as here. dnl dnl The GNU MP Library is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dnl for more details. dnl dnl You should have received copies of the GNU General Public License and the dnl GNU Lesser General Public License along with the GNU MP Library. If not, dnl see https://www.gnu.org/licenses/. dnl dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') define(`rp', `%rdi') define(`ap_param', `%rsi') define(`no2_param',`%rdx') define(`ap', `%r8') define(`no2', `%rcx') define(`ix', `no2') define(`ix_save', `ap_param') define(`mx', `%rbx') define(`mx_final', `%rbp') define(`jmpreg', `%r14') define(`rx', `%rax') define(`r0', `%r9') define(`r1', `%r10') define(`r2', `%r11') define(`r3a', `%r12') define(`r3b', `%r13') dnl - Use mx_final as a comparison against m to see when to do final iteration dnl and when to jump to diagonal. dnl - Use mx to reset ap. Increases by 2*8 in between each loop. dnl - Use ix for loop variable (should be rcx). dnl - Use ix_save for saving initial n in between each loop. dnl - jmpreg for jumping to the next label dnl Scheme for even n dnl dnl n = 10: dnl 0 1 2 3 4 5 6 7 8 9 dnl 0 dnl 1 dnl 2 dnl 3 dnl 4 e dnl 5 h x d dnl 6 h x x x d dnl 7 h x x x x x d dnl 8 h x x x x x x x d dnl 9 x x x x x x x x x d dnl dnl n = 12: dnl 0 1 2 3 4 5 6 7 8 9 0 1 dnl 0 dnl 1 dnl 2 dnl 3 dnl 4 dnl 5 e dnl 6 h x d dnl 7 h x x x d dnl 8 h x x x x x d dnl 9 h x x x x x x x d dnl 10 h x x x x x x x x x d dnl 11 x x x x x x x x x x x d TEXT ALIGN(32) PROLOGUE(_flint_mpn_sqrhigh_basecase_even) mov R32(no2_param), R32(no2) lea (ap_param,no2_param,8), ap C ap += no2 where no2 = n / 2 push %rbx push %rbp push %r12 push %r13 push %r14 C Initial triangle C C v--< (no2, no2 - 1) in matrix C h x C h x x x C h x x x x x define(`sx', `rx') define(`s0', `r0') define(`s1', `r1') define(`s2', `r2') define(`s3', `mx') define(`s4', `r3a') define(`s5', `r3b') define(`s6', `jmpreg') define(`s7', `mx_final') define(`s8', `ix_save') mov 0*8(ap), %rdx mulx -2*8(ap), sx, sx mulx -1*8(ap), s1, s0 add s1, sx adc $0, s0 C x, 0 mov 1*8(ap), %rdx mulx -3*8(ap), s3, s3 mulx -2*8(ap), s4, s5 mulx -1*8(ap), s6, s1 mulx 0*8(ap), s7, s2 add s3, sx adc s5, s0 adc $0, s1 add s4, sx adc s6, s0 adc s7, s1 adc $0, s2 C x, 0, 1, 2 mov 2*8(ap), %rdx mulx -4*8(ap), s3, s3 mulx -3*8(ap), s7, s4 mulx -2*8(ap), s8, s5 add s7, s3 adc s8, s4 mulx -1*8(ap), s7, s6 adc s7, s5 adc $0, s6 xor R32(s8), R32(s8) add s3, sx adc s4, s0 adc s5, s1 adc s6, s2 mulx 0*8(ap), s5, s3 mulx 1*8(ap), s6, s4 adc s6, s3 adc s8, s4 adc s5, s2 adc s8, s3 adc s8, s4 C x, 0, 1, 2, 3, 4 mov s0, 0*8(rp) mov s1, 1*8(rp) mov s2, 2*8(rp) mov s3, 3*8(rp) mov s4, 4*8(rp) undefine(`sx') undefine(`s0') undefine(`s1') undefine(`s2') undefine(`s3') undefine(`s4') undefine(`s5') undefine(`s6') undefine(`s7') undefine(`s8') C Addmul chain for lower mid triangle into rp C C mx = -7 * 8 C mx_final = -(2 * no2 - 3) * 8 C ix = 0 C ix_save = 0 NOTE: It is already zero lea (,no2,2), R32(mx_final) lea -5*8(ap), ap lea -3*8(,mx_final,8), R32(mx_final) mov 8*8(ap), %rdx mulx 0*8(ap), r1, r1 mulx 1*8(ap), r2, r3a neg mx_final xor R32(ix), R32(ix) C Also resets flags adcx r1, rx movq $-7*8, mx adox r2, rx C jmp L(e4) L(e4): lea -2*8(ap), ap lea -4*8(rp), rp lea L(e6)(%rip), jmpreg jmp L(b4) L(e6): lea -2*8(rp), rp mov r3a, r3b lea L(e0)(%rip), jmpreg lea 1(ix_save), ix_save jmp L(b6) nop; nop; nop; nop C Must for relative 8-bit jump to L(fnd) L(fnd): adox ix, r2 adox ix, r3b adc ix, r3b mov r2, 1*8(rp) mov r3b, 2*8(rp) mov 3*8(ap), %rdx C Load second factor cmp R32(mx), R32(mx_final) lea (ap,mx), ap C Reset ap lea 3*8(rp,mx), rp C Reset rp jg L(msh) je L(kmp) mulx 0*8(ap), ix, ix L(kmp): mulx 1*8(ap), r2, r3a test %al, %al adcx ix, rx lea -2*8(mx), mx mov R32(ix_save), R32(ix) adox r2, rx jmp *jmpreg L(e0): lea 2*8(ap), ap lea L(e2)(%rip), jmpreg C jmp L(b0) ALIGN(32) L(b0): mulx 0*8(ap), r0, r1 mulx 1*8(ap), r2, r3b adcx r3a, r0 adox 0*8(rp), r0 adcx r1, r2 mov r0, 0*8(rp) jrcxz L(fnd) lea -1(ix), ix adox 1*8(rp), r2 mov r2, 1*8(rp) L(b6): mulx 2*8(ap), r0, r1 mulx 3*8(ap), r2, r3a adox 2*8(rp), r0 adox 3*8(rp), r2 adcx r3b, r0 adcx r1, r2 mov r0, 2*8(rp) mov r2, 3*8(rp) L(b4): mulx 4*8(ap), r0, r1 mulx 5*8(ap), r2, r3b adox 4*8(rp), r0 adox 5*8(rp), r2 adcx r3a, r0 adcx r1, r2 mov r0, 4*8(rp) mov r2, 5*8(rp) lea 8*8(ap), ap L(b2): mulx -2*8(ap), r0, r1 mulx -1*8(ap), r2, r3a adox 6*8(rp), r0 adox 7*8(rp), r2 adcx r3b, r0 lea 8*8(rp), rp adcx r1, r2 mov r0, -2*8(rp) mov r2, -1*8(rp) jmp L(b0) L(e2): lea 4*8(ap), ap lea -6*8(rp), rp mov r3a, r3b lea L(e4)(%rip), jmpreg jmp L(b2) define(`r3', `jmpreg') define(`ld0', `r3a') define(`ld1', `r3b') define(`ld2', `mx') define(`ld3', `ix_save') C Left shift rp by one and add diagonal L(msh): neg mx_final lea L(etab)(%rip), ld2 shr $4, R32(mx_final) mov 0*8(rp), ld0 inc R32(mx_final) mov 1*8(rp), ld1 lea 3*8(ap,mx_final,8), ap or R32(mx_final), R32(ix) shr $2, R32(ix) and $3, R32(mx_final) C Also reset flags mov -1*8(ap), %rdx mulx %rdx, r1, r1 ifdef(`PIC', ` movslq (ld2,mx_final,4), mx_final lea (mx_final,ld2), ld2 ',`') mov 0*8(ap), %rdx mulx %rdx, r2, r3 adox rx, rx adox ld0, ld0 adcx r1, rx adox ld1, ld1 adcx r2, ld0 adcx r3, ld1 mov ld0, 0*8(rp) ifdef(`PIC', ` jmp *ld2 ',` jmp *(ld2,mx_final,8) ') L(ep3): lea -1*8(ap), ap lea -2*8(rp), rp mov ld1, ld3 jmp L(es3) L(ep2): lea 2*8(ap), ap lea -4*8(rp), rp jmp L(es2) L(ep1): lea 1*8(ap), ap lea 2*8(rp), rp mov ld1, ld3 jmp L(es1) ALIGN(32) L(ep0): # Do nothing L(es0): mov 1*8(ap), %rdx mov 2*8(rp), ld2 mov 3*8(rp), ld3 mulx %rdx, r2, r3 lea -1(ix), R32(ix) adox ld2, ld2 adox ld3, ld3 mov ld1, 1*8(rp) adcx r2, ld2 adcx r3, ld3 mov ld2, 2*8(rp) L(es3): mov 2*8(ap), %rdx mov 4*8(rp), ld0 mov 5*8(rp), ld1 mov ld3, 3*8(rp) mulx %rdx, r0, r1 adox ld0, ld0 adox ld1, ld1 lea 4*8(ap), ap adcx r0, ld0 adcx r1, ld1 mov ld0, 4*8(rp) L(es2): mov -1*8(ap), %rdx mov 6*8(rp), ld2 mov 7*8(rp), ld3 mov ld1, 5*8(rp) mulx %rdx, r2, r3 adox ld2, ld2 adox ld3, ld3 lea 8*8(rp), rp adcx r2, ld2 adcx r3, ld3 mov ld2, -2*8(rp) L(es1): mov 0*8(ap), %rdx mov 0*8(rp), ld0 mov 1*8(rp), ld1 mov ld3, -1*8(rp) mulx %rdx, r0, r1 adox ld0, ld0 jrcxz L(gin) adox ld1, ld1 adcx r0, ld0 adcx r1, ld1 mov ld0, 0*8(rp) jmp L(es0) L(gin): adox ix, r1 C ix = 0 adc r0, ld0 adc ix, r1 mov ld0, 0*8(rp) mov r1, 1*8(rp) undefine(`r3') undefine(`ld0') undefine(`ld1') undefine(`ld2') undefine(`ld3') pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret JUMPTABSECT ALIGN(8) L(etab):JMPENT( L(ep0), L(etab)) JMPENT( L(ep1), L(etab)) JMPENT( L(ep2), L(etab)) JMPENT( L(ep3), L(etab)) TEXT EPILOGUE() flint-3.1.3/src/mpn_extras/broadwell/sqrhigh_basecase_odd.asm000066400000000000000000000200601461254215100243760ustar00rootroot00000000000000dnl X64-64 mpn_mullo_basecase optimised for Intel Broadwell. dnl Contributed to the GNU project by Torbjorn Granlund. dnl Copyright 2017 Free Software Foundation, Inc. dnl This file is part of the GNU MP Library. dnl dnl The GNU MP Library is free software; you can redistribute it and/or modify dnl it under the terms of either: dnl dnl * the GNU Lesser General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your dnl option) any later version. dnl dnl or dnl dnl * the GNU General Public License as published by the Free Software dnl Foundation; either version 2 of the License, or (at your option) any dnl later version. dnl dnl or both in parallel, as here. dnl dnl The GNU MP Library is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dnl for more details. dnl dnl You should have received copies of the GNU General Public License and the dnl GNU Lesser General Public License along with the GNU MP Library. If not, dnl see https://www.gnu.org/licenses/. dnl dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') define(`rp', `%rdi') define(`ap_param', `%rsi') define(`no2_param',`%rdx') define(`ap', `%r8') define(`no2', `%rcx') define(`ix', `no2') define(`ix_save', `ap_param') define(`mx', `%rbx') define(`mx_final', `%rbp') define(`jmpreg', `%r14') define(`rx', `%rax') define(`r0', `%r9') define(`r1', `%r10') define(`r2', `%r11') define(`r3a', `%r12') define(`r3b', `%r13') dnl - Use mx_final as a comparison against m to see when to do final iteration dnl and when to jump to diagonal. dnl - Use mx to reset ap. Increases by 2*8 in between each loop. dnl - Use ix for loop variable (should be rcx). dnl - Use ix_save for saving initial n in between each loop. dnl - jmpreg for jumping to the next label dnl Scheme for odd n dnl dnl n = 9: dnl 0 1 2 3 4 5 6 7 8 dnl 0 dnl 1 dnl 2 dnl 3 dnl 4 h d dnl 5 h x x d dnl 6 h x x x x d dnl 7 h x x x x x x d dnl 8 x x x x x x x x d dnl dnl n = 11: dnl 0 1 2 3 4 5 6 7 8 9 10 dnl 0 dnl 1 dnl 2 dnl 3 dnl 4 dnl 5 h d dnl 6 h x x d dnl 7 h x x x x d dnl 8 h x x x x x x d dnl 9 h x x x x x x x x d dnl 10 x x x x x x x x x x d TEXT ALIGN(32) PROLOGUE(_flint_mpn_sqrhigh_basecase_odd) mov R32(no2_param), R32(no2) lea (ap_param,no2_param,8), ap C ap += no2 where no2 = (n - 1) / 2 push %rbx push %rbp push %r12 push %r13 push %r14 C Initial triangle C C v--< Top is (no2, no2 - 1) in matrix C h C h x x C h x x x x define(`sx', `rx') define(`s0', `r0') define(`s1', `r1') define(`s2', `r2') define(`s3', `mx') define(`s4', `r3a') define(`s5', `r3b') define(`s6', `jmpreg') define(`s7', `mx_final') define(`zr', `ix_save') mov 0*8(ap), %rdx mulx -1*8(ap), sx, sx C x mov 1*8(ap), %rdx xor R32(zr), R32(zr) mulx -2*8(ap), s2, s2 mulx -1*8(ap), s3, s0 mulx 0*8(ap), s4, s1 add s2, sx adc zr, s0 add s3, sx adc s4, s0 adc zr, s1 C x, 0, 1 mov 2*8(ap), %rdx mulx -3*8(ap), s4, s4 mulx -2*8(ap), s2, s5 mulx -1*8(ap), s3, s6 add s2, s4 adc s3, s5 mulx 0*8(ap), s7, s2 mulx 1*8(ap), %rdx, s3 adc s7, s6 adc %rdx, s2 adc zr, s3 add s4, sx adc s5, s0 adc s6, s1 mov s0, 0*8(rp) mov s1, 1*8(rp) adc zr, s2 adc zr, s3 mov s2, 2*8(rp) mov s3, 3*8(rp) C x, 0, 1, 2, 3 undefine(`sx') undefine(`s0') undefine(`s1') undefine(`s2') undefine(`s3') undefine(`s4') undefine(`s5') undefine(`s6') undefine(`s7') undefine(`zr') C Addmul chain for lower mid triangle into rp C C In the initial loop, we want to do 7 multiplications, of which one is C a half-multiplication (only upper result). Throughout all loops, the C first two multiplications contribute to rx, so these has to be C gathered. Moreover, the last multiplication is "disjoint" from rp, so C this cannot be in the loop as we have to add two zeroes here. C C mx = -7 * 8 C mx_final = -(no2 * 2 - 1) * 8 C ix = 0 C ix_save = 0 NOTE: It is already zero lea -4*8(ap), ap lea (,no2,2), R32(mx_final) mov 7*8(ap), %rdx lea -1*8(,mx_final,8), R32(mx_final) mulx 0*8(ap), r1, r1 mulx 1*8(ap), r2, r3a neg mx_final xor R32(ix), R32(ix) C ix <- 0 and reset flags adcx r1, rx movq $-7*8, mx adox r2, rx C jmp L(f4) L(f4): lea -2*8(ap), ap lea -4*8(rp), rp lea L(f6)(%rip), jmpreg jmp L(a4) L(f6): lea -2*8(rp), rp mov r3a, r3b lea L(f0)(%rip), jmpreg lea 1(ix_save), ix_save jmp L(a6) L(end): adox r3a, r0 adox ix, r1 adc ix, r0 adc ix, r1 mov r0, 0*8(rp) mov r1, 1*8(rp) mov 2*8(ap), %rdx C Load second factor cmp R32(mx), R32(mx_final) lea (ap,mx), ap C Reset ap lea 3*8(rp,mx), rp C Reset rp jg L(lsh) je L(jmp) mulx 0*8(ap), ix, ix L(jmp): mulx 1*8(ap), r2, r3a test %al, %al adcx ix, rx lea -2*8(mx), mx mov R32(ix_save), R32(ix) adox r2, rx jmp *jmpreg L(f0): lea 2*8(ap), ap lea L(f2)(%rip), jmpreg C jmp L(a0) ALIGN(32) L(a0): mulx 0*8(ap), r0, r1 jrcxz L(end) mulx 1*8(ap), r2, r3b adox 0*8(rp), r0 lea -1(ix), ix adox 1*8(rp), r2 adcx r3a, r0 adcx r1, r2 mov r0, 0*8(rp) mov r2, 1*8(rp) L(a6): mulx 2*8(ap), r0, r1 mulx 3*8(ap), r2, r3a adox 2*8(rp), r0 adox 3*8(rp), r2 adcx r3b, r0 adcx r1, r2 mov r0, 2*8(rp) mov r2, 3*8(rp) L(a4): mulx 4*8(ap), r0, r1 mulx 5*8(ap), r2, r3b adox 4*8(rp), r0 adox 5*8(rp), r2 adcx r3a, r0 adcx r1, r2 mov r0, 4*8(rp) mov r2, 5*8(rp) lea 8*8(ap), ap L(a2): mulx -2*8(ap), r0, r1 mulx -1*8(ap), r2, r3a adox 6*8(rp), r0 adox 7*8(rp), r2 adcx r3b, r0 lea 8*8(rp), rp adcx r1, r2 mov r0, -2*8(rp) mov r2, -1*8(rp) jmp L(a0) L(f2): lea 4*8(ap), ap lea -6*8(rp), rp mov r3a, r3b lea L(f4)(%rip), jmpreg jmp L(a2) define(`r3', `jmpreg') define(`ld0', `r3a') define(`ld1', `r3b') define(`ld2', `mx') define(`ld3', `ix_save') C Left shift rp by one and add diagonal L(lsh): neg mx_final lea L(dtab)(%rip), ld2 shr $4, R32(mx_final) inc R32(mx_final) lea 2*8(ap,mx_final,8), ap mov 0*8(rp), ld1 or R32(mx_final), R32(ix) shr $2, R32(ix) and $3, R32(mx_final) C Also reset flags mov 0*8(ap), %rdx mulx %rdx, r0, r1 ifdef(`PIC', ` movslq (ld2,mx_final,4), mx_final ',`') adox rx, rx adox ld1, ld1 ifdef(`PIC', ` lea (mx_final,ld2), ld2 ',`') adcx r0, rx adcx r1, ld1 ifdef(`PIC', ` jmp *ld2 ',` jmp *(ld2,mx_final,8) ') L(dp3): lea -1*8(ap), ap lea -2*8(rp), rp mov ld1, ld3 jmp L(ds3) L(dp2): lea 2*8(ap), ap lea -4*8(rp), rp jmp L(ds2) L(dp1): lea 1*8(ap), ap lea 2*8(rp), rp mov ld1, ld3 jmp L(ds1) ALIGN(32) L(dp0): C Do nothing L(ds0): mov 1*8(ap), %rdx mov 1*8(rp), ld2 mov 2*8(rp), ld3 mulx %rdx, r2, r3 lea -1(ix), R32(ix) adox ld2, ld2 adox ld3, ld3 mov ld1, 0*8(rp) adcx r2, ld2 adcx r3, ld3 mov ld2, 1*8(rp) L(ds3): mov 2*8(ap), %rdx mov 3*8(rp), ld0 mov 4*8(rp), ld1 mov ld3, 2*8(rp) mulx %rdx, r0, r1 adox ld0, ld0 adox ld1, ld1 lea 4*8(ap), ap adcx r0, ld0 adcx r1, ld1 mov ld0, 3*8(rp) L(ds2): mov -1*8(ap), %rdx mov 5*8(rp), ld2 mov 6*8(rp), ld3 mov ld1, 4*8(rp) mulx %rdx, r2, r3 adox ld2, ld2 adox ld3, ld3 lea 8*8(rp), rp adcx r2, ld2 adcx r3, ld3 mov ld2, -3*8(rp) L(ds1): mov 0*8(ap), %rdx mov -1*8(rp), ld0 mov 0*8(rp), ld1 mov ld3, -2*8(rp) mulx %rdx, r0, r1 adox ld0, ld0 jrcxz L(fin) adox ld1, ld1 adcx r0, ld0 adcx r1, ld1 mov ld0, -1*8(rp) jmp L(ds0) L(fin): adox ix, r1 C ix = 0 adc r0, ld0 adc ix, r1 mov ld0, -1*8(rp) mov r1, 0*8(rp) undefine(`r3') undefine(`ld0') undefine(`ld1') undefine(`ld2') undefine(`ld3') pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret JUMPTABSECT ALIGN(8) L(dtab):JMPENT( L(dp0), L(dtab)) JMPENT( L(dp1), L(dtab)) JMPENT( L(dp2), L(dtab)) JMPENT( L(dp3), L(dtab)) TEXT EPILOGUE() flint-3.1.3/src/mpn_extras/broadwell/sqrhigh_hard.asm000066400000000000000000000211131461254215100227200ustar00rootroot00000000000000dnl dnl Copyright (C) 2024 Albin Ahlbäck dnl dnl This file is part of FLINT. dnl dnl FLINT is free software: you can redistribute it and/or modify it under dnl the terms of the GNU Lesser General Public License (LGPL) as published dnl by the Free Software Foundation; either version 3 of the License, or dnl (at your option) any later version. See . dnl include(`config.m4') define(`rp', `%rdi') define(`ap', `%rsi') define(`s0', `%rax') define(`s1', `%rcx') define(`s2', `%r8') define(`s3', `%r9') define(`s4', `%r10') define(`s5', `%r11') define(`s6', `%rbx') define(`s7', `%rbp') define(`s8', `%r12') define(`s9', `%r13') define(`s10', `%r14') TEXT ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_1) mov 0*8(ap), %rdx mulx %rdx, s0, s1 mov s1, 0*8(rp) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_2) mov 0*8(ap), %rdx mulx 1*8(ap), s3, s4 mulx %rdx, s0, s0 mov 1*8(ap), %rdx add s3, s0 mulx %rdx, s1, s2 adc s4, s1 adc $0, s2 add s3, s0 adc s4, s1 adc $0, s2 mov s1, 0*8(rp) mov s2, 1*8(rp) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_3) C 0 1 2 C 0 C 1 h d C 2 x x d mov 1*8(ap), %rdx mulx 0*8(ap), s1, s1 C a1 a0 mulx %rdx, s0, s2 C a1^2 mov 2*8(ap), %rdx mulx 0*8(ap), s3, s4 C a2 a0 mulx 1*8(ap), s5, ap C a2 a1 add s1, s3 adc s5, s4 adc $0, ap xor R32(s1), R32(s1) add s3, s3 adc s4, s4 adc ap, ap adc s1, s1 add s3, s0 adc s4, s2 mulx %rdx, s3, s4 C a2^2 mov s2, 0*8(rp) adc ap, s3 adc s1, s4 mov s3, 1*8(rp) mov s4, 2*8(rp) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_4) C 0 1 2 3 C 0 C 1 e C 2 h x d C 3 x x x d mov 2*8(ap), %rdx mulx 0*8(ap), s0, s0 C a2 a0 mulx 1*8(ap), s3, s2 C a2 a1 add s3, s0 adc $0, s2 C 0, 2 mov 3*8(ap), %rdx mulx 0*8(ap), s1, s4 C a3 a0 mulx 1*8(ap), s3, s5 C a3 a1 add s1, s0 adc s4, s2 adc $0, s5 xor R32(s1), R32(s1) add s3, s2 mulx 2*8(ap), %rdx, s4 C a3 a2 adc %rdx, s5 adc s1, s4 C 0, 2, 5, 4 add s0, s0 adc s2, s2 adc s5, s5 adc s4, s4 adc R32(s1), R32(s1) C 0, 2, 5, 4, 1 mov 1*8(ap), %rdx mulx %rdx, s3, s3 C a1^2 add s3, s0 mov 2*8(ap), %rdx mulx %rdx, %rdx, s3 C a2^2 adc %rdx, s2 adc s3, s5 mov 3*8(ap), %rdx mov s2, 0*8(rp) mov s5, 1*8(rp) mulx %rdx, %rdx, s3 C a3^2 adc %rdx, s4 adc s3, s1 mov s4, 2*8(rp) mov s1, 3*8(rp) ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_5) C 0 1 2 3 4 C 0 C 1 C 2 h d C 3 h x x d C 4 x x x x d push %rbx push %rbp mov 2*8(ap), %rdx mulx 1*8(ap), s0, s0 C a2 a1 C 0 xor R32(s1), R32(s1) mov 3*8(ap), %rdx mulx 0*8(ap), s5, s5 C a3 a0 mulx 1*8(ap), s2, s3 C a3 a1 mulx 2*8(ap), s6, s4 C a3 a2 add s5, s0 adc s6, s3 adc s1, s4 add s2, s0 adc s1, s3 adc s1, s4 C 0, 3, 4 mov 4*8(ap), %rdx mulx 0*8(ap), s7, s2 C a4 a0 mulx 1*8(ap), s6, s5 C a4 a1 add s7, s0 adc s2, s3 mulx 2*8(ap), s7, s2 C a4 a2 adc s5, s4 adc s1, s2 add s6, s3 adc s7, s4 mulx 3*8(ap), %rdx, s5 C a4 a3 adc %rdx, s2 adc s1, s5 C 0, 3, 4, 2, 5 add s0, s0 adc s3, s3 adc s4, s4 adc s2, s2 adc s5, s5 adc R32(s1), R32(s1) C 0, 3, 4, 2, 5, 1 mov 2*8(ap), %rdx mulx %rdx, s6, s7 C a2^2 add s6, s0 adc s7, s3 mov 3*8(ap), %rdx mov s3, 0*8(rp) mulx %rdx, s6, s7 C a3^2 adc s6, s4 adc s7, s2 mov 4*8(ap), %rdx mov s4, 1*8(rp) mov s2, 2*8(rp) mulx %rdx, s6, s7 C a4^2 adc s6, s5 adc s7, s1 mov s5, 3*8(rp) mov s1, 4*8(rp) pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_6) C 0 1 2 3 4 5 C 0 C 1 C 2 e C 3 h x d C 4 h x x x d C 5 x x x x x d push %rbx push %rbp push %r12 mov 3*8(ap), %rdx xor R32(s1), R32(s1) mulx 1*8(ap), s0, s0 C a3 a1 mulx 2*8(ap), s2, s3 C a3 a2 add s2, s0 adc s1, s3 C 0, 3 mov 4*8(ap), %rdx mulx 0*8(ap), s4, s4 C a4 a0 mulx 1*8(ap), s2, s5 C a4 a1 mulx 2*8(ap), s6, s7 C a4 a2 mulx 3*8(ap), %rdx, s8 C a4 a3 add s4, s0 adc s5, s3 adc s1, s7 add s2, s0 adc s6, s3 adc %rdx, s7 adc s1, s8 C 0, 3, 7, 8 mov 5*8(ap), %rdx test %al, %al mulx 0*8(ap), s2, s4 C a5 a0 mulx 1*8(ap), s5, s6 C a5 a1 adox s2, s0 adox s4, s3 adcx s5, s3 adcx s6, s7 mulx 2*8(ap), s2, s4 C a5 a2 mulx 3*8(ap), s5, s6 C a5 a3 adox s2, s7 adox s4, s8 adox s1, s6 adc s5, s8 mulx 4*8(ap), %rdx, s4 C a5 a4 adc %rdx, s6 adc s1, s4 C 0, 3, 7, 8, 6, 4 add s0, s0 mov 2*8(ap), %rdx adc s3, s3 adc s7, s7 adc s8, s8 adc s6, s6 adc s4, s4 adc R32(s1), R32(s1) C 0, 3, 7, 8, 6, 4, 1 C (2, 5) mulx %rdx, s2, s2 C a2^2 mov 3*8(ap), %rdx add s2, s0 mulx %rdx, s2, s5 C a3^2 adc s2, s3 adc s5, s7 mov 4*8(ap), %rdx mov s3, 0*8(rp) mulx %rdx, s2, s5 C a4^2 mov s7, 1*8(rp) mov 5*8(ap), %rdx adc s2, s8 adc s5, s6 mov s8, 2*8(rp) mulx %rdx, s2, s5 C a5^2 mov s6, 3*8(rp) adc s2, s4 adc s5, s1 mov s4, 4*8(rp) mov s1, 5*8(rp) pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_7) C 0 1 2 3 4 5 6 C 0 C 1 C 2 C 3 h d C 4 h x x d C 5 h x x x x d C 6 x x x x x x d push %rbx push %rbp push %r12 push %r13 mov 3*8(ap), %rdx mulx 2*8(ap), s0, s0 C a3 a2 C 0 xor R32(s1), R32(s1) mov 4*8(ap), %rdx mulx 1*8(ap), s5, s5 C a4 a1 mulx 2*8(ap), s2, s3 C a4 a2 mulx 3*8(ap), s6, s4 C a4 a3 add s5, s0 adc s1, s3 add s2, s0 adc s6, s3 adc s1, s4 C 0, 3, 4 mov 5*8(ap), %rdx mulx 0*8(ap), s8, s8 C a5 a0 mulx 1*8(ap), s2, s6 C a5 a1 mulx 2*8(ap), s5, s7 C a5 a2 add s2, s0 adc s5, s3 mulx 3*8(ap), s9, s2 C a5 a3 mulx 4*8(ap), %rdx, s5 C a5 a4 adc s9, s4 adc s1, s2 add s8, s0 adc s6, s3 adc s7, s4 adc %rdx, s2 adc s1, s5 C 0, 3, 4, 2, 5 mov 6*8(ap), %rdx test %al, %al mulx 0*8(ap), s6, s7 C a6 a0 mulx 1*8(ap), s8, s9 C a6 a1 adcx s6, s0 adox s7, s3 adcx s8, s3 adox s9, s4 mulx 2*8(ap), s6, s7 C a6 a2 mulx 3*8(ap), s8, s9 C a6 a3 adcx s6, s4 adox s7, s2 adcx s8, s2 adox s9, s5 mulx 4*8(ap), s6, s7 C a6 a4 mulx 5*8(ap), s8, s9 C a6 a5 adox s1, s7 adc s6, s5 adc s8, s7 adc s1, s9 C 0, 3, 4, 2, 5, 7, 9 add s0, s0 adc s3, s3 adc s4, s4 adc s2, s2 adc s5, s5 adc s7, s7 adc s9, s9 adc R32(s1), R32(s1) C 0, 3, 4, 2, 5, 7, 9, 1 mov 3*8(ap), %rdx mulx %rdx, %rdx, s6 C a3^2 add %rdx, s0 adc s6, s3 mov 4*8(ap), %rdx mulx %rdx, %rdx, s6 C a4^2 mov s3, 0*8(rp) adc %rdx, s4 adc s6, s2 mov 5*8(ap), %rdx mulx %rdx, s3, s6 C a5^2 mov s4, 1*8(rp) mov s2, 2*8(rp) adc s3, s5 adc s6, s7 mov 6*8(ap), %rdx mulx %rdx, s3, s6 C a6^2 mov s5, 3*8(rp) mov s7, 4*8(rp) adc s3, s9 adc s6, s1 mov s9, 5*8(rp) mov s1, 6*8(rp) pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() ALIGN(16) PROLOGUE(flint_mpn_sqrhigh_8) C 0 1 2 3 4 5 6 7 C 0 C 1 C 2 C 3 e C 4 h x d C 5 h x x x d C 6 h x x x x x d C 7 x x x x x x x d push %rbx push %rbp push %r12 push %r13 push %r14 xor R32(s1), R32(s1) mov 4*8(ap), %rdx mulx 2*8(ap), s0, s0 C a4 a2 mulx 3*8(ap), s4, s3 C a4 a3 add s4, s0 adc s1, s3 C 0, 3 mov 5*8(ap), %rdx mulx 1*8(ap), s2, s2 C a5 a1 mulx 2*8(ap), s4, s5 C a5 a2 mulx 3*8(ap), s6, s8 C a5 a3 mulx 4*8(ap), s7, s9 C a5 a4 add s2, s0 adc s5, s3 adc s1, s8 add s4, s0 adc s6, s3 adc s7, s8 adc s1, s9 C 0, 3, 8, 9 mov 6*8(ap), %rdx test %al, %al mulx 0*8(ap), s4, s4 C a6 a0 mulx 1*8(ap), s5, s2 C a6 a1 adox s4, s0 adcx s5, s0 adox s2, s3 mulx 2*8(ap), s4, s7 C a6 a2 mulx 3*8(ap), s5, s2 C a6 a3 adcx s4, s3 adox s7, s8 adcx s5, s8 adox s2, s9 mulx 4*8(ap), s4, s7 C a6 a4 mulx 5*8(ap), s5, s2 C a6 a5 adcx s4, s9 adox s1, s7 adcx s5, s7 adcx s1, s2 C 0, 3, 8, 9, 7, 2 mov 7*8(ap), %rdx mulx 0*8(ap), s6, s5 C a7 a0 mulx 1*8(ap), s10, s4 C a7 a1 adcx s6, s0 adox s5, s3 adcx s10, s3 adox s4, s8 mulx 2*8(ap), s6, s5 C a7 a2 mulx 3*8(ap), s10, s4 C a7 a3 adcx s6, s8 adox s5, s9 mulx 4*8(ap), s6, s5 C a7 a4 adcx s10, s9 adox s4, s7 adcx s6, s7 adox s5, s2 mulx 5*8(ap), s10, s4 C a7 a5 mulx 6*8(ap), s6, s5 C a7 a6 adox s1, s4 adc s10, s2 adc s6, s4 adc s1, s5 C 0, 3, 8, 9, 7, 2, 4, 5 add s0, s0 adc s3, s3 adc s8, s8 adc s9, s9 adc s7, s7 adc s2, s2 adc s4, s4 adc s5, s5 adc R32(s1), R32(s1) C 0, 3, 8, 9, 7, 2, 4, 5, 1 mov 3*8(ap), %rdx mulx %rdx, s6, s6 C a3^2 add s6, s0 mov 4*8(ap), %rdx mulx %rdx, s10, s6 C a4^2 adc s10, s3 adc s6, s8 mov 5*8(ap), %rdx mulx %rdx, s10, s6 C a5^2 mov s3, 0*8(rp) mov s8, 1*8(rp) adc s10, s9 adc s6, s7 mov 6*8(ap), %rdx mulx %rdx, s10, s6 C a6^2 mov s9, 2*8(rp) mov s7, 3*8(rp) adc s10, s2 adc s6, s4 mov 7*8(ap), %rdx mulx %rdx, s10, s6 C a7^2 mov s2, 4*8(rp) mov s4, 5*8(rp) adc s10, s5 adc s6, s1 mov s5, 6*8(rp) mov s1, 7*8(rp) pop %r14 pop %r13 pop %r12 pop %rbp pop %rbx ret EPILOGUE() flint-3.1.3/src/mpn_extras/broadwell/x86_64-defs.m4000066400000000000000000000222171461254215100217000ustar00rootroot00000000000000divert(-1) dnl m4 macros for amd64 assembler. dnl Copyright 1999-2005, 2008, 2009, 2011-2013, 2017 Free Software Foundation, dnl Inc. dnl This file is part of the GNU MP Library. dnl dnl The GNU MP Library is free software; you can redistribute it and/or modify dnl it under the terms of either: dnl dnl * the GNU Lesser General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your dnl option) any later version. dnl dnl or dnl dnl * the GNU General Public License as published by the Free Software dnl Foundation; either version 2 of the License, or (at your option) any dnl later version. dnl dnl or both in parallel, as here. dnl dnl The GNU MP Library is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dnl for more details. dnl dnl You should have received copies of the GNU General Public License and the dnl GNU Lesser General Public License along with the GNU MP Library. If not, dnl see https://www.gnu.org/licenses/. dnl Called: PROLOGUE_cpu(GSYM_PREFIX`'foo) dnl dnl In the amd64 code we use explicit TEXT and ALIGN() calls in the code, dnl since different alignments are wanted in various circumstances. So for dnl instance, dnl dnl TEXT dnl ALIGN(16) dnl PROLOGUE(mpn_add_n) dnl ... dnl EPILOGUE() define(`PROLOGUE_cpu', m4_assert_numargs(1) ` GLOBL $1 TYPE($1,`function') COFF_TYPE($1) $1: ') dnl Usage: COFF_TYPE(GSYM_PREFIX`'foo) dnl dnl Emit COFF style ".def ... .endef" type information for a function, when dnl supported. The argument should include any GSYM_PREFIX. dnl dnl See autoconf macro GMP_ASM_COFF_TYPE for HAVE_COFF_TYPE. define(COFF_TYPE, m4_assert_numargs(1) m4_assert_defined(`HAVE_COFF_TYPE') `ifelse(HAVE_COFF_TYPE,yes, `.def $1 .scl 2 .type 32 .endef')') dnl Usage: ASSERT([cond][,instructions]) dnl dnl If WANT_ASSERT is 1, output the given instructions and expect the given dnl flags condition to then be satisfied. For example, dnl dnl ASSERT(ne, `cmpq %rax, %rbx') dnl dnl The instructions can be omitted to just assert a flags condition with dnl no extra calculation. For example, dnl dnl ASSERT(nc) dnl dnl When `instructions' is not empty, a pushfq/popfq is added for dnl convenience to preserve the flags, but the instructions themselves must dnl preserve any registers that matter. dnl dnl The condition can be omitted to just output the given instructions when dnl assertion checking is wanted. In this case the pushf/popf is omitted. dnl For example, dnl dnl ASSERT(, `movq %rax, VAR_KEEPVAL') define(ASSERT, m4_assert_numargs_range(1,2) m4_assert_defined(`WANT_ASSERT') `ifelse(WANT_ASSERT,1, `ifelse(`$1',, ` $2', `ifelse(`$2',,, ` pushfq') $2 `j$1' L(ASSERT_ok`'ASSERT_counter) ud2 C assertion failed L(ASSERT_ok`'ASSERT_counter): ifelse(`$2',,,` popfq') define(`ASSERT_counter',incr(ASSERT_counter))')')') define(ASSERT_counter,1) dnl LEA - load effective address dnl dnl FIXME: We should never create a GOT entry and therefore use the simpler 2nd dnl variant always. We need to understand what happens for not-yet-hidden dnl symbols first. dnl define(`LEA',`dnl ifdef(`PIC', `mov $1@GOTPCREL(%rip), $2' , `lea $1(%rip), $2') ') define(`DEF_OBJECT', m4_assert_numargs_range(2,3) ` ifelse($#,3,`$3',`RODATA') ALIGN($2) $1: ') define(`END_OBJECT', m4_assert_numargs(1) ` SIZE(`$1',.-`$1')') define(`R32', `ifelse($1,`%rax',`%eax', $1,`%rbx',`%ebx', $1,`%rcx',`%ecx', $1,`%rdx',`%edx', $1,`%rsi',`%esi', $1,`%rdi',`%edi', $1,`%rbp',`%ebp', $1,`%r8',`m4_warning(`R32(%r8) does not yield minimal instruction size.')%r8d', $1,`%r9',`m4_warning(`R32(%r9) does not yield minimal instruction size.')%r9d', $1,`%r10',`m4_warning(`R32(%r10) does not yield minimal instruction size.')%r10d', $1,`%r11',`m4_warning(`R32(%r11) does not yield minimal instruction size.')%r11d', $1,`%r12',`m4_warning(`R32(%r12) does not yield minimal instruction size.')%r12d', $1,`%r13',`m4_warning(`R32(%r13) does not yield minimal instruction size.')%r13d', $1,`%r14',`m4_warning(`R32(%r14) does not yield minimal instruction size.')%r14d', $1,`%r15',`m4_warning(`R32(%r15) does not yield minimal instruction size.')%r15d')') define(`R8', `ifelse($1,`%rax',`%al', $1,`%rbx',`%bl', $1,`%rcx',`%cl', $1,`%rdx',`%dl', $1,`%rsi',`%sil', $1,`%rdi',`%dil', $1,`%rbp',`%bpl', $1,`%r8',`m4_warning(`R8(%r8) does not yield minimal instruction size.')%r8b', $1,`%r9',`m4_warning(`R8(%r9) does not yield minimal instruction size.')%r9b', $1,`%r10',`m4_warning(`R8(%r10) does not yield minimal instruction size.')%r10b', $1,`%r11',`m4_warning(`R8(%r11) does not yield minimal instruction size.')%r11b', $1,`%r12',`m4_warning(`R8(%r12) does not yield minimal instruction size.')%r12b', $1,`%r13',`m4_warning(`R8(%r13) does not yield minimal instruction size.')%r13b', $1,`%r14',`m4_warning(`R8(%r14) does not yield minimal instruction size.')%r14b', $1,`%r15',`m4_warning(`R8(%r15) does not yield minimal instruction size.')%r15b')') dnl Usage: CALL(funcname) dnl define(`CALL',`dnl ifdef(`PIC', `call GSYM_PREFIX`'$1@PLT' , `call GSYM_PREFIX`'$1' )') define(`TCALL',`dnl ifdef(`PIC', `jmp GSYM_PREFIX`'$1@PLT' , `jmp GSYM_PREFIX`'$1' )') define(`JUMPTABSECT', `.section .data.rel.ro.local,"a",@progbits') dnl Usage: JMPENT(targlabel,tablabel) define(`JMPENT',`dnl ifdef(`PIC', `.long $1-$2'dnl , `.quad $1'dnl )') dnl These macros are defined just for DOS64, where they provide calling dnl sequence glue code. define(`FUNC_ENTRY',`') define(`FUNC_EXIT',`') dnl Target ABI macros. define(`IFDOS', `') define(`IFSTD', `$1') define(`IFELF', `$1') dnl Usage: PROTECT(symbol) dnl dnl Used for private GMP symbols that should never be overridden by users. dnl This can save reloc entries and improve shlib sharing as well as dnl application startup times define(`PROTECT', `.hidden $1') dnl Usage: x86_lookup(target, key,value, key,value, ...) dnl dnl Look for `target' among the `key' parameters. dnl dnl x86_lookup expands to the corresponding `value', or generates an error dnl if `target' isn't found. define(x86_lookup, m4_assert_numargs_range(1,999) `ifelse(eval($#<3),1, `m4_error(`unrecognised part of x86 instruction: $1 ')', `ifelse(`$1',`$2', `$3', `x86_lookup(`$1',shift(shift(shift($@))))')')') dnl Usage: x86_opcode_regxmm(reg) dnl dnl Validate the given xmm register, and return its number, 0 to 7. define(x86_opcode_regxmm, m4_assert_numargs(1) `x86_lookup(`$1',x86_opcode_regxmm_list)') define(x86_opcode_regxmm_list, ``%xmm0',0, `%xmm1',1, `%xmm2',2, `%xmm3',3, `%xmm4',4, `%xmm5',5, `%xmm6',6, `%xmm7',7, `%xmm8',8, `%xmm9',9, `%xmm10',10, `%xmm11',11, `%xmm12',12, `%xmm13',13, `%xmm14',14, `%xmm15',15') dnl Usage: palignr($imm,%srcreg,%dstreg) dnl dnl Emit a palignr instruction, using a .byte sequence, since obsolete but dnl still distributed versions of gas don't know SSSE3 instructions. define(`palignr', m4_assert_numargs(3) `.byte 0x66,dnl ifelse(eval(x86_opcode_regxmm($3) >= 8 || x86_opcode_regxmm($2) >= 8),1, `eval(0x40+x86_opcode_regxmm($3)/8*4+x86_opcode_regxmm($2)/8),')dnl 0x0f,0x3a,0x0f,dnl eval(0xc0+x86_opcode_regxmm($3)%8*8+x86_opcode_regxmm($2)%8),dnl substr($1,1)') dnl Usage dnl dnl regnum(op) raw operand index (so slightly misnamed) dnl regnumh(op) high bit of register operand nimber dnl ix(op) 0 for reg operand, 1 for plain pointer operand. dnl define(`regnum',`x86_lookup(`$1',oplist)') define(`regnumh',`eval(regnum($1)/8 & 1)') define(`ix',`eval(regnum($1)/16)') define(`oplist', ``%rax', 0, `%rcx', 1, `%rdx', 2, `%rbx', 3, `%rsp', 4, `%rbp', 5, `%rsi', 6, `%rdi', 7, `%r8', 8, `%r9', 9, `%r10', 10, `%r11', 11, `%r12', 12, `%r13', 13, `%r14', 14, `%r15', 15, `(%rax)',16, `(%rcx)',17, `(%rdx)',18, `(%rbx)',19, `(%rsp)',20, `(%rbp)',21, `(%rsi)',22, `(%rdi)',23, `(%r8)', 24, `(%r9)', 25, `(%r10)',26, `(%r11)',27, `(%r12)',28, `(%r13)',29, `(%r14)',30, `(%r15)',31') dnl Usage (by mulx, shlx, shrx) dnl dnl reg1,reg2,reg3,opc1,opc2 dnl dnl or dnl dnl (reg1),reg2,reg3,opc1,opc2 dnl dnl where reg1 is any register but rsp,rbp,r12,r13, or dnl dnl or dnl dnl off,(reg1),reg2,reg3,opc1,opc2 dnl dnl where reg1 is any register but rsp,r12. dnl dnl The exceptions are due to special coding needed for some registers; rsp dnl and r12 need an extra byte 0x24 at the end while rbp and r13 lack the dnl offset-less form. dnl dnl Other addressing forms are not handled. Invalid forms are not properly dnl detected. Offsets that don't fit one byte are not handled correctly. define(`c4_helper',`dnl .byte 0xc4`'dnl ifelse(`$#',5,`dnl ,eval(0xe2^32*regnumh($1)^128*regnumh($3))`'dnl ,eval(0x$4-8*regnum($2))`'dnl ,0x$5`'dnl ,eval(0xc0+(7 & regnum($1))+8*(7 & regnum($3))-0xc0*ix($1))`'dnl ',`$#',6,`dnl ,eval(0xe2^32*regnumh($2)^128*regnumh($4))`'dnl ,eval(0x$5-8*regnum($3))`'dnl ,0x$6`'dnl ,eval(0x40+(7 & regnum($2))+8*(7 & regnum($4)))`'dnl ,eval(($1 + 256) % 256)`'dnl ')') divert`'dnl flint-3.1.3/src/mpn_extras/debug.c000066400000000000000000000015661461254215100170440ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" void flint_mpn_debug(mp_srcptr x, mp_size_t xsize) { int i, j; char byte[9]; byte[8] = 0; flint_printf("\n"); for (i = 0; i < xsize; i++) { flint_printf("DIGIT %3d/%wd: ", i, xsize); for (j = 0; j < FLINT_BITS; j++) { byte[j % 8] = (x[i] & (UWORD(1)<. */ #include "flint.h" #include "fmpz.h" #include "mpn_extras.h" int flint_mpn_divides(mp_ptr q, mp_srcptr array1, mp_size_t limbs1, mp_srcptr arrayg, mp_size_t limbsg, mp_ptr temp) { mpn_tdiv_qr(q, temp, 0, array1, limbs1, arrayg, limbsg); while ((limbsg) && temp[limbsg - 1] == 0) limbsg--; return (limbsg == 0); } flint-3.1.3/src/mpn_extras/divrem_preinv1.c000066400000000000000000000023471461254215100207060ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" #if !defined(_MSC_VER) #pragma GCC diagnostic ignored "-Wunused-variable" #endif mp_limb_t flint_mpn_divrem_preinv1(mp_ptr q, mp_ptr a, mp_size_t m, mp_srcptr b, mp_size_t n, mp_limb_t dinv) { mp_limb_t ret; mp_size_t i; /* ensure { a + i, n } < { b, n } */ if ((ret = (mpn_cmp(a + m - n, b, n) >= 0))) mpn_sub_n(a + m - n, a + m - n, b, n); for (i = m - 1; i >= n; i--) { flint_mpn_divrem21_preinv(q[i - n], a[i], a[i - 1], dinv); FLINT_ASSERT(n > 0); a[i] -= mpn_submul_1(a + i - n, b, n, q[i - n]); if (mpn_cmp(a + i - n, b, n) >= 0 || a[i] != 0) { q[i - n]++; a[i] -= mpn_sub_n(a + i - n, a + i - n, b, n); } } return ret; } #if !defined(_MSC_VER) #pragma GCC diagnostic warning "-Wunused-variable" #endif flint-3.1.3/src/mpn_extras/divrem_preinvn.c000066400000000000000000000042561461254215100210040ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" /* TODO: speedup mpir's mullow and mulhigh and use instead of mul/mul_n */ mp_limb_t flint_mpn_divrem_preinvn(mp_ptr qp, mp_ptr rp, mp_srcptr ap, mp_size_t m, mp_srcptr d, mp_size_t n, mp_srcptr dinv) { mp_limb_t cy, hi = 0; mp_ptr t, q, r, a; mp_size_t size; TMP_INIT; a = (mp_ptr) ap + m - 2*n; r = rp + m - 2*n; /* check if top n limbs of a exceed d */ if (mpn_cmp(a + n, d, n) >= 0) { mpn_sub_n(r + n, a + n, d, n); hi = 1; } else if (r != a) mpn_copyi(r + n, a + n, n); q = qp + m - 2*n; TMP_START; t = TMP_ALLOC(2*n*sizeof(mp_limb_t)); /* 2n by n division */ while (m >= 2*n) { flint_mpn_mul_n(t, dinv, r + n, n); cy = mpn_add_n(q, t + n, r + n, n); flint_mpn_mul_n(t, d, q, n); cy = r[n] - t[n] - mpn_sub_n(r, a, t, n); while (cy > 0) { cy -= mpn_sub_n(r, r, d, n); mpn_add_1(q, q, n, 1); } if (mpn_cmp(r, d, n) >= 0) { mpn_sub_n(r, r, d, n); mpn_add_1(q, q, n, 1); } m -= n; r -= n; a -= n; q -= n; } size = m - n; /* m by n division with 2n > m > n */ if (size) { if (rp != ap) mpn_copyi(rp, ap, size); flint_mpn_mul(t, dinv, n, rp + n, size); cy = mpn_add_n(qp, t + n, rp + n, size); flint_mpn_mul(t, d, n, qp, size); if (cy) mpn_add_n(t + size, t + size, d, n + 1 - size); cy = rp[n] - t[n] - mpn_sub_n(rp, rp, t, n); while (cy > 0) { cy -= mpn_sub_n(rp, rp, d, n); mpn_add_1(qp, qp, size, 1); } if (mpn_cmp(rp, d, n) >= 0) { mpn_sub_n(rp, rp, d, n); mpn_add_1(qp, qp, size, 1); } } TMP_END; return hi; } flint-3.1.3/src/mpn_extras/factor_trial.c000066400000000000000000000014531461254215100204220ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "mpn_extras.h" #include "ulong_extras.h" int flint_mpn_factor_trial(mp_srcptr x, mp_size_t xsize, slong start, slong stop) { slong i; const mp_limb_t * primes; primes = n_primes_arr_readonly(stop); for (i = start; i < stop; i++) { if (flint_mpn_divisible_1_odd(x, xsize, primes[i])) return i; } return 0; } flint-3.1.3/src/mpn_extras/factor_trial_tree.c000066400000000000000000000146621461254215100214470ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD #include static pthread_once_t _factor_trial_initialised = PTHREAD_ONCE_INIT; pthread_mutex_t _factor_trial_lock; #endif FLINT_TLS_PREFIX mp_ptr _factor_trial_tree[16 - (FLINT_BITS/32)]; FLINT_TLS_PREFIX int _factor_trial_tree_initialised = 0; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD void _tree_mutex_init(void) { pthread_mutex_init(&_factor_trial_lock, NULL); } #endif void _cleanup_trial_tree(void) { slong i; for (i = 0; i < 13 - (FLINT_BITS/32); i++) flint_free(_factor_trial_tree[i]); _factor_trial_tree_initialised = 0; } void _factor_trial_tree_init(void) { slong i, j, k, m, n; const mp_limb_t * primes; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(&_factor_trial_initialised, _tree_mutex_init); pthread_mutex_lock(&_factor_trial_lock); #endif if (!_factor_trial_tree_initialised) { primes = n_primes_arr_readonly(3512); flint_register_cleanup_function(_cleanup_trial_tree); /* Initialise mpn's in tree, each of which is thought of as an array of products of primes Note there are 3512 primes less than 32768 */ for (i = 0; i < 13 - (FLINT_BITS/32); i++) { _factor_trial_tree[i] = (mp_ptr) flint_malloc(4096/(FLINT_BITS/16)*sizeof(mp_limb_t)); } /* initialise products in first layer of tree */ for (i = 0, j = 0; i < 3512; i+=(FLINT_BITS/16), j++) { #if FLINT64 _factor_trial_tree[0][j] = primes[i]*primes[i + 1]*primes[i + 2]*primes[i + 3]; #else _factor_trial_tree[0][j] = primes[i]*primes[i + 1]; #endif } m = 0; /* level in tree that has been computed already */ n = 1; /* number of words per entry in that level */ k = 3512/(FLINT_BITS/16); /* number of entries on that level */ /* compute remaining levels of tree */ for ( ; m < 12 - (FLINT_BITS/32); m++, n*=2, k=(k+1)/2) { /* multiply entries in pairs */ for (i = 0, j = 0; j < k/2; j++, i+=(2*n)) { flint_mpn_mul_n(_factor_trial_tree[m + 1] + i, _factor_trial_tree[m] + i, _factor_trial_tree[m] + i + n, n); } if ((k % 2) == 1) /* copy across last entry if k is odd */ { mpn_copyi(_factor_trial_tree[m + 1] + i, _factor_trial_tree[m] + i, n); flint_mpn_zero(_factor_trial_tree[m + 1] + i + n, n); } } _factor_trial_tree_initialised = 1; } #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(&_factor_trial_lock); #endif } int flint_mpn_factor_trial_tree(slong * factors, mp_srcptr x, mp_size_t xsize, slong num_primes) { slong i, j, m, n, n2, nmax; const mp_limb_t * primes; mp_ptr gtemp; /* temporary space for recursive gcd's */ mp_ptr temp; /* temporary space for flint_mpn_gcd_full2 */ slong rlimbs[13 - (FLINT_BITS/32)]; /* gcd lengths at each level */ slong idx[13 - (FLINT_BITS/32)]; /* indexes of entries at each level */ slong offset; /* offset into gtemp */ slong valid_level; /* last level with valid gcd computed */ int numfacs = 0; /* number of prime factors found */ int gcd1; /* whether we hit gcd = 1, can prune this branch of tree */ _factor_trial_tree_init(); primes = n_primes_arr_readonly(num_primes); gtemp = (mp_ptr) flint_malloc((3*4096/(FLINT_BITS/16) + xsize)*sizeof(mp_limb_t)); temp = gtemp + 2*4096/(FLINT_BITS/16); /* compute gcd of x with top level in tree */ m = FLINT_MAX(FLINT_BIT_COUNT(num_primes) - (FLINT_BITS/32), 0); /* top level in tree */ n = 4096/(FLINT_BITS/16); /* number of words of integer in tree */ for (i = 12 - (FLINT_BITS/32); i > m; i--) n /= 2; n2 = n; /* number of words per entry at this level */ nmax = n; /* save for later */ MPN_NORM(_factor_trial_tree[m] + 0, n); if (n == 0) /* nothing to be done */ { flint_free(gtemp); return 0; } rlimbs[m] = flint_mpn_gcd_full2(gtemp, x, xsize, _factor_trial_tree[m] + 0, n, temp); if (rlimbs[m] == 1 && gtemp[0] == 1) /* gcd is 1, no factors found */ { flint_free(gtemp); return 0; } /* set indexes into arrays of entries at each level */ for (j = 0; j < m; j++) idx[j] = -WORD(1); idx[m] = 0; valid_level = m; /* last level with valid gcd */ /* compute gcd with each entry at bottom level of tree */ for (i = 0; i < (num_primes + (FLINT_BITS/16) - 1)/(FLINT_BITS/16); i++) { gcd1 = 0; n2 = nmax; /* number of words per entry */ offset = 0; /* offset into gtemp */ /* compute gcd's down the tree for this i */ for (j = m; j >= 0; j--) { /* must update indexes for current i */ if ((idx[j] & 1) != ((i >> j) & 1)) idx[j]++; /* see if we need to compute new gcd for this level */ if (!gcd1 && (valid_level > j || (idx[j] & 1) != ((i >> j) & 1))) { n = n2; MPN_NORM(_factor_trial_tree[j] + idx[j]*n2, n); rlimbs[j] = flint_mpn_gcd_full2(gtemp + offset, _factor_trial_tree[j] + idx[j]*n2, n, gtemp + offset - 2*n2, rlimbs[j + 1], temp); valid_level = j; if (rlimbs[j] == 1 && gtemp[offset] == 1) gcd1 = 1; } offset += n2; n2/=2; } if (!gcd1) { for (j = 0; j < FLINT_BITS/16; j++) { /* check divisibility by primes with index 4*i + j */ if (flint_mpn_divisible_1_odd(x, xsize, primes[(FLINT_BITS/16)*i + j])) factors[numfacs++] = (FLINT_BITS/16)*i + j; } } } flint_free(gtemp); return numfacs; } flint-3.1.3/src/mpn_extras/fmms1.c000066400000000000000000000017561461254215100170020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "mpn_extras.h" /* Try to compute y = a1*x1 - a2*x2 where x1 and x2 both have n > 0 limbs. If y is negative or does not fit into n limbs, the return is -1. Otherwise, the return is the size of y. */ mp_size_t flint_mpn_fmms1(mp_ptr y, mp_limb_t a1, mp_srcptr x1, mp_limb_t a2, mp_srcptr x2, mp_size_t n) { mp_limb_t h0, h1; FLINT_ASSERT(n > 0); h0 = mpn_mul_1(y, x1, n, a1); h1 = mpn_submul_1(y, x2, n, a2); if (h1 != h0) return -1; while (n > 0 && y[n - 1] == 0) n--; return n; } flint-3.1.3/src/mpn_extras/gcd_full.c000066400000000000000000000046271461254215100175360ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "mpn_extras.h" mp_size_t flint_mpn_gcd_full2(mp_ptr arrayg, mp_srcptr array1, mp_size_t limbs1, mp_srcptr array2, mp_size_t limbs2, mp_ptr temp) { mp_size_t s1 = 0, s2 = 0, m, b1, b2, mb, len1, len2, leng; mp_ptr in1, in2; mp_limb_t cy; /* find maximum power of 2 dividing inputs */ b1 = mpn_scan1(array1 + s1, 0); b2 = mpn_scan1(array2 + s2, 0); /* get bit shifts [0, FLINT_BITS) and limb shifts */ mb = FLINT_MIN(b1, b2) % FLINT_BITS; s1 = b1 / FLINT_BITS; b1 = b1 % FLINT_BITS; len1 = limbs1 - s1; s2 = b2 / FLINT_BITS; b2 = b2 % FLINT_BITS; len2 = limbs2 - s2; m = FLINT_MIN(s1, s2); /* this many output limbs will be zero */ flint_mpn_zero(arrayg, m); /* set in1 to shifted array1 */ if (temp != NULL) in1 = temp; else in1 = flint_malloc(len1*sizeof(mp_limb_t)); if (b1 == 0) flint_mpn_copyi(in1, array1 + s1, len1); else mpn_rshift(in1, array1 + s1, len1, b1); len1 -= (in1[len1 - 1] == 0); /* set in2 to shifted array2 */ if (temp != NULL) in2 = temp + len1; else in2 = flint_malloc(len2*sizeof(mp_limb_t)); if (b2 == 0) flint_mpn_copyi(in2, array2 + s2, len2); else mpn_rshift(in2, array2 + s2, len2, b2); len2 -= (in2[len2 - 1] == 0); /* compute gcd of shifted values */ if (len1 >= len2) leng = mpn_gcd(arrayg + m, in1, len1, in2, len2); else leng = mpn_gcd(arrayg + m, in2, len2, in1, len1); if (mb) /* shift back by mb bits */ { cy = mpn_lshift(arrayg + m, arrayg + m, leng, mb); if (cy) arrayg[m + leng++] = cy; } /* clean up */ if (temp == NULL) { flint_free(in1); flint_free(in2); } /* return total number of limbs in output */ return m + leng; } mp_size_t flint_mpn_gcd_full(mp_ptr arrayg, mp_srcptr array1, mp_size_t limbs1, mp_srcptr array2, mp_size_t limbs2) { return flint_mpn_gcd_full2(arrayg, array1, limbs1, array2, limbs2, NULL); } flint-3.1.3/src/mpn_extras/get_d.c000066400000000000000000000157431461254215100170420ustar00rootroot00000000000000/* mpn_get_d -- limbs to double conversion. THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN FUTURE GNU MP RELEASES. Copyright 2003, 2004 Free Software Foundation, Inc. Copyright 2021 William Hart (adaption to Flint) This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #define CONST_1024 (1024) #define CONST_NEG_1023 (-1023) #define CONST_NEG_1022_SUB_53 (-1022 - 53) /* Return the value {ptr,size}*2^exp, and negative if sign<0. Must have size>=1, and a non-zero high limb ptr[size-1]. {ptr,size} is truncated towards zero. This is consistent with other gmp conversions, like mpz_set_f or mpz_set_q, and is easy to implement and test. In the past conversions had attempted (imperfectly) to let the hardware float rounding mode take effect, but that gets tricky since multiple roundings need to be avoided, or taken into account, and denorms mean the effective precision of the mantissa is not constant. (For reference, mpz_get_d on IEEE systems was ok, except it operated on the absolute value. mpf_get_d and mpq_get_d suffered from multiple roundings and from not always using enough bits to get the rounding right.) It's felt that GMP is not primarily concerned with hardware floats, and really isn't enhanced by getting involved with hardware rounding modes (which could even be some weird unknown style), so something unambiguous and straightforward is best. The IEEE code below is the usual case, it knows either a 32-bit or 64-bit limb and is done with shifts and masks. The 64-bit case in particular should come out nice and compact. The generic code works one bit at a time, which will be quite slow, but should support any binary-based "double" and be safe against any rounding mode. Note in particular it works on IEEE systems too. Traps: Hardware traps for overflow to infinity, underflow to zero, or unsupported denorms may or may not be taken. The IEEE code works bitwise and so probably won't trigger them, the generic code works by float operations and so probably will. This difference might be thought less than ideal, but again its felt straightforward code is better than trying to get intimate with hardware exceptions (of perhaps unknown nature). Not done: mpz_get_d in the past handled size==1 with a cast limb->double. This might still be worthwhile there (for up to the mantissa many bits), but for mpn_get_d here, the cost of applying "exp" to the resulting exponent would probably use up any benefit a cast may have over bit twiddling. Also, if the exponent is pushed into denorm range then bit twiddling is the only option, to ensure the desired truncation is obtained. Other: For reference, note that HPPA 8000, 8200, 8500 and 8600 trap FCNV,UDW,DBL to the kernel for values >= 2^63. This makes it slow, and worse the Linux kernel (what versions?) apparently uses untested code in its trap handling routines, and gets the sign wrong. We don't use such a limb to double cast, neither in the IEEE or generic code. */ #include "flint.h" /* assumes unsigned int is at least 32 bits */ #if defined (FLINT_BIG_ENDIAN) && FLINT_BIG_ENDIAN == 1 union ieee_double_extract { struct { unsigned int sig:1; unsigned int exp:11; unsigned int manh:20; unsigned int manl:32; } s; double d; }; #else union ieee_double_extract { struct { unsigned int manl:32; unsigned int manh:20; unsigned int exp:11; unsigned int sig:1; } s; double d; }; #endif double flint_mpn_get_d(mp_srcptr ptr, mp_size_t size, mp_size_t sign, long exp) { FLINT_ASSERT (size >= 0); FLINT_ASSERT (size == 0 || ptr[size-1] != 0); if (size == 0) return 0.0; /* Adjust exp to a radix point just above {ptr,size}, guarding against overflow. After this exp can of course be reduced to anywhere within the {ptr,size} region without underflow. */ if ((unsigned long) (FLINT_BITS * size) > (unsigned long) (LONG_MAX - exp)) { goto ieee_infinity; /* generic */ exp = LONG_MAX; } else { exp += FLINT_BITS * size; } #define ONE_LIMB (FLINT_BITS == 64) #define TWO_LIMBS (FLINT_BITS == 32) { union ieee_double_extract u; mp_limb_t m0, m1, m2, rmask; int lshift, rshift; m0 = ptr[size-1]; /* high limb */ m1 = (size >= 2 ? ptr[size-2] : 0); /* second highest limb */ lshift = flint_clz(m0); /* relative to just under high non-zero bit */ exp -= lshift + 1; if (ONE_LIMB) { /* lshift to have high of m0 non-zero, and collapse nails */ rshift = FLINT_BITS - lshift; rmask = lshift == 0 ? 0 : UWORD_MAX; m0 = (m0 << lshift) | ((m1 >> rshift) & rmask); /* rshift back to have bit 53 of m0 the high non-zero */ m0 >>= 11; } else /* TWO_LIMBS */ { m2 = (size >= 3 ? ptr[size-3] : 0); /* third highest limb */ /* lshift to have high of m0:m1 non-zero, collapse nails from m0 */ rshift = FLINT_BITS - lshift; rmask = (lshift == 0 ? 0 : UWORD_MAX); m0 = (m0 << lshift) | ((m1 >> rshift) & rmask); m1 = (m1 << lshift) | ((m2 >> rshift) & rmask); /* rshift back to have bit 53 of m0:m1 the high non-zero */ m1 = (m1 >> 11) | (m0 << (FLINT_BITS-11)); m0 >>= 11; } if (exp >= CONST_1024) { /* overflow, return infinity */ ieee_infinity: m0 = 0; m1 = 0; exp = 1024; } else if (exp <= CONST_NEG_1023) { if (exp <= CONST_NEG_1022_SUB_53) return 0.0; /* denorm underflows to zero */ rshift = -1022 - exp; FLINT_ASSERT (rshift > 0 && rshift < 53); if (ONE_LIMB) { m0 >>= rshift; } else /* TWO_LIMBS */ { if (rshift >= 32) { m1 = m0; m0 = 0; rshift -= 32; } lshift = FLINT_BITS - rshift; m1 = (m1 >> rshift) | (rshift == 0 ? 0 : m0 << lshift); m0 >>= rshift; } exp = -1023; } if (ONE_LIMB) { #if FLINT_BITS > 32 /* avoid compiler warning about big shift */ u.s.manh = m0 >> 32; #endif u.s.manl = m0; } else /* TWO_LIMBS */ { u.s.manh = m0; u.s.manl = m1; } u.s.exp = exp + 1023; u.s.sig = (sign < 0); return u.d; } } flint-3.1.3/src/mpn_extras/mod_preinvn.c000066400000000000000000000036241461254215100202730ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" /* TODO: speedup mpir's mullow and mulhigh and use instead of mul/mul_n */ void flint_mpn_mod_preinvn(mp_ptr rp, mp_srcptr ap, mp_size_t m, mp_srcptr d, mp_size_t n, mp_srcptr dinv) { mp_limb_t cy; mp_ptr t, r, a; mp_size_t size; TMP_INIT; a = (mp_ptr) ap + m - 2*n; r = rp + m - 2*n; /* check if top n limbs of a exceed d */ if (mpn_cmp(a + n, d, n) >= 0) mpn_sub_n(r + n, a + n, d, n); else if (r != a) mpn_copyi(r + n, a + n, n); TMP_START; t = TMP_ALLOC(3*n*sizeof(mp_limb_t)); /* 2n by n division */ while (m >= 2*n) { flint_mpn_mul_n(t, dinv, r + n, n); cy = mpn_add_n(t + 2*n, t + n, r + n, n); flint_mpn_mul_n(t, d, t + 2*n, n); cy = r[n] - t[n] - mpn_sub_n(r, a, t, n); while (cy > 0) cy -= mpn_sub_n(r, r, d, n); if (mpn_cmp(r, d, n) >= 0) mpn_sub_n(r, r, d, n); m -= n; r -= n; a -= n; } size = m - n; /* m by n division with 2n > m > n */ if (size) { if (rp != ap) mpn_copyi(rp, ap, size); flint_mpn_mul(t, dinv, n, rp + n, size); cy = mpn_add_n(t + 2*n, t + n, rp + n, size); flint_mpn_mul(t, d, n, t + 2*n, size); if (cy) mpn_add_n(t + size, t + size, d, n + 1 - size); cy = rp[n] - t[n] - mpn_sub_n(rp, rp, t, n); while (cy > 0) cy -= mpn_sub_n(rp, rp, d, n); if (mpn_cmp(rp, d, n) >= 0) mpn_sub_n(rp, rp, d, n); } TMP_END; } flint-3.1.3/src/mpn_extras/mul.c000066400000000000000000000057271461254215100165560ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck Copyright (C) 2023, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" void __gmpn_mul_basecase(mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #if FLINT_HAVE_ADX /* We don't call mpn_mul_basecase directly because our own basecases already cover small operands. */ #define WANT_GMP_MUL_BASECASE 0 #define BASECASE_LIMIT 0 /* toom22 on top our own basecase beats GMP up to some point */ #define WANT_TOOM22 1 #define TOOM22_LIMIT 230 #else /* As fallback where we don't have our own mul_basecase: */ /* GMP's MUL_TOOM22_THRESHOLD is >= 16 on most machines */ #define WANT_GMP_MUL_BASECASE 1 #define BASECASE_LIMIT 16 #define WANT_TOOM22 0 #define TOOM22_LIMIT 0 #endif #ifdef FLINT_HAVE_FFT_SMALL #include "fft_small.h" #define FFT_MUL mpn_mul_default_mpn_ctx #else #include "fft.h" #define FFT_MUL flint_mpn_mul_fft_main #endif mp_limb_t _flint_mpn_mul(mp_ptr r, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn) { /* Experimental: strip trailing zeros. Normally this should be handled by the caller where appropriate, but there can be situations where it helps to do so here. */ /* while (xn > 1 && x[0] == 0) { xn--; x++; r[0] = 0; r++; } while (yn > 1 && y[0] == 0) { yn--; y++; r[0] = 0; r++; } if (xn < yn) { FLINT_SWAP(mp_srcptr, x, y); FLINT_SWAP(mp_size_t, xn, yn); } */ if (WANT_GMP_MUL_BASECASE && xn <= BASECASE_LIMIT) __gmpn_mul_basecase(r, x, xn, y, yn); else if (yn == 1) r[xn + yn - 1] = mpn_mul_1(r, x, xn, y[0]); else if (WANT_TOOM22 && yn <= TOOM22_LIMIT && 5 * yn >= 4 * xn) flint_mpn_mul_toom22(r, x, xn, y, yn, NULL); else if (yn < FLINT_FFT_MUL_THRESHOLD) mpn_mul(r, x, xn, y, yn); else FFT_MUL(r, x, xn, y, yn); return r[xn + yn - 1]; } void _flint_mpn_mul_n(mp_ptr r, mp_srcptr x, mp_srcptr y, mp_size_t n) { if (WANT_GMP_MUL_BASECASE && n <= BASECASE_LIMIT) __gmpn_mul_basecase(r, x, n, y, n); else if (WANT_TOOM22 && n <= TOOM22_LIMIT) flint_mpn_mul_toom22(r, x, n, y, n, NULL); else if (n < FLINT_FFT_MUL_THRESHOLD) mpn_mul_n(r, x, y, n); else FFT_MUL(r, x, n, y, n); } mp_limb_t _flint_mpn_sqr(mp_ptr r, mp_srcptr x, mp_size_t n) { /* We cannot call __gmpn_sqr_basecase directly because it may not support n above a certain size. */ if (n < FLINT_FFT_SQR_THRESHOLD) mpn_sqr(r, x, n); else { /* TODO: Don't do a full multiplication here. */ FFT_MUL(r, x, n, x, n); } return r[2 * n - 1]; } flint-3.1.3/src/mpn_extras/mul_basecase.c000066400000000000000000001127511461254215100204000ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #if FLINT_HAVE_ADX mp_limb_t flint_mpn_mul_1_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_2_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_2_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_3_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_3_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_3_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_4_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_4_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_4_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_4_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_5_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_5_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_5_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_5_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_5_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_6_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_6_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_6_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_6_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_6_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_6_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_9_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_10_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_11_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_12_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_13_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_14_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_15_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_16_8(mp_ptr, mp_srcptr, mp_srcptr); static mp_limb_t _flint_mpn_mul_n_9(mp_ptr res, mp_srcptr u, mp_srcptr v, mp_size_t n) { flint_mpn_mul_func_tab[n][8](res, u, v); res[n + 8] = mpn_addmul_1(res + 8, u, n, v[8]); return res[n + 8]; } static mp_limb_t _flint_mpn_mul_n_10(mp_ptr res, mp_srcptr u, mp_srcptr v, mp_size_t n) { flint_mpn_mul_func_tab[n][8](res, u, v); res[n + 8] = mpn_addmul_1(res + 8, u, n, v[8]); res[n + 9] = mpn_addmul_1(res + 9, u, n, v[9]); return res[n + 9]; } static mp_limb_t _flint_mpn_mul_n_11(mp_ptr res, mp_srcptr u, mp_srcptr v, mp_size_t n) { flint_mpn_mul_func_tab[n][8](res, u, v); res[n + 8] = mpn_addmul_1(res + 8, u, n, v[8]); res[n + 9] = mpn_addmul_1(res + 9, u, n, v[9]); res[n + 10] = mpn_addmul_1(res + 10, u, n, v[10]); return res[n + 10]; } static mp_limb_t _flint_mpn_mul_n_12(mp_ptr res, mp_srcptr u, mp_srcptr v, mp_size_t n) { flint_mpn_mul_func_tab[n][8](res, u, v); res[n + 8] = mpn_addmul_1(res + 8, u, n, v[8]); res[n + 9] = mpn_addmul_1(res + 9, u, n, v[9]); res[n + 10] = mpn_addmul_1(res + 10, u, n, v[10]); res[n + 11] = mpn_addmul_1(res + 11, u, n, v[11]); return res[n + 11]; } static mp_limb_t _flint_mpn_mul_n_13(mp_ptr res, mp_srcptr u, mp_srcptr v, mp_size_t n) { flint_mpn_mul_func_tab[n][8](res, u, v); res[n + 8] = mpn_addmul_1(res + 8, u, n, v[8]); res[n + 9] = mpn_addmul_1(res + 9, u, n, v[9]); res[n + 10] = mpn_addmul_1(res + 10, u, n, v[10]); res[n + 11] = mpn_addmul_1(res + 11, u, n, v[11]); res[n + 12] = mpn_addmul_1(res + 12, u, n, v[12]); return res[n + 12]; } static mp_limb_t _flint_mpn_mul_n_14(mp_ptr res, mp_srcptr u, mp_srcptr v, mp_size_t n) { flint_mpn_mul_func_tab[n][8](res, u, v); res[n + 8] = mpn_addmul_1(res + 8, u, n, v[8]); res[n + 9] = mpn_addmul_1(res + 9, u, n, v[9]); res[n + 10] = mpn_addmul_1(res + 10, u, n, v[10]); res[n + 11] = mpn_addmul_1(res + 11, u, n, v[11]); res[n + 12] = mpn_addmul_1(res + 12, u, n, v[12]); res[n + 13] = mpn_addmul_1(res + 13, u, n, v[13]); return res[n + 13]; } mp_limb_t flint_mpn_mul_9_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 9); } mp_limb_t flint_mpn_mul_10_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 10); } mp_limb_t flint_mpn_mul_11_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 11); } mp_limb_t flint_mpn_mul_12_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 12); } mp_limb_t flint_mpn_mul_13_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 13); } mp_limb_t flint_mpn_mul_14_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 14); } mp_limb_t flint_mpn_mul_15_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 15); } mp_limb_t flint_mpn_mul_16_9(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_9(res, u, v, 16); } mp_limb_t flint_mpn_mul_10_10(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_10(res, u, v, 10); } mp_limb_t flint_mpn_mul_11_10(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_10(res, u, v, 11); } mp_limb_t flint_mpn_mul_12_10(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_10(res, u, v, 12); } mp_limb_t flint_mpn_mul_13_10(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_10(res, u, v, 13); } mp_limb_t flint_mpn_mul_14_10(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_10(res, u, v, 14); } mp_limb_t flint_mpn_mul_15_10(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_10(res, u, v, 15); } mp_limb_t flint_mpn_mul_16_10(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_10(res, u, v, 16); } mp_limb_t flint_mpn_mul_11_11(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_11(res, u, v, 11); } mp_limb_t flint_mpn_mul_12_11(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_11(res, u, v, 12); } mp_limb_t flint_mpn_mul_13_11(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_11(res, u, v, 13); } mp_limb_t flint_mpn_mul_14_11(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_11(res, u, v, 14); } mp_limb_t flint_mpn_mul_15_11(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_11(res, u, v, 15); } mp_limb_t flint_mpn_mul_16_11(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_11(res, u, v, 16); } mp_limb_t flint_mpn_mul_12_12(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_12(res, u, v, 12); } mp_limb_t flint_mpn_mul_13_12(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_12(res, u, v, 13); } mp_limb_t flint_mpn_mul_14_12(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_12(res, u, v, 14); } mp_limb_t flint_mpn_mul_15_12(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_12(res, u, v, 15); } mp_limb_t flint_mpn_mul_16_12(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_12(res, u, v, 16); } mp_limb_t flint_mpn_mul_13_13(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_13(res, u, v, 13); } mp_limb_t flint_mpn_mul_14_13(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_13(res, u, v, 14); } mp_limb_t flint_mpn_mul_15_13(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_13(res, u, v, 15); } mp_limb_t flint_mpn_mul_16_13(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_13(res, u, v, 16); } mp_limb_t flint_mpn_mul_14_14(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_14(res, u, v, 14); } mp_limb_t flint_mpn_mul_15_14(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_14(res, u, v, 15); } mp_limb_t flint_mpn_mul_16_14(mp_ptr res, mp_srcptr u, mp_srcptr v) { return _flint_mpn_mul_n_14(res, u, v, 16); } mp_limb_t flint_mpn_mul_15_15(mp_ptr res, mp_srcptr u, mp_srcptr v) { #if 1 mp_limb_t tmp[22], cy; flint_mpn_mul_15_8(res, u, v); flint_mpn_mul_15_7(tmp, u, v + 8); cy = mpn_add_n(res + 8, res + 8, tmp, 15); mpn_add_1(res + 23, tmp + 15, 7, cy); #else mp_limb_t tmp[31]; flint_mpn_mul_toom22(res, u, 15, v, 15, tmp); #endif return res[29]; } mp_limb_t flint_mpn_mul_16_15(mp_ptr res, mp_srcptr u, mp_srcptr v) { #if 0 mp_limb_t tmp[23], cy; flint_mpn_mul_16_8(res, u, v); flint_mpn_mul_16_7(tmp, u, v + 8); cy = mpn_add_n(res + 8, res + 8, tmp, 16); mpn_add_1(res + 24, tmp + 16, 7, cy); #else mp_limb_t tmp[33]; flint_mpn_mul_toom22(res, u, 16, v, 15, tmp); #endif return res[30]; } mp_limb_t flint_mpn_mul_16_16(mp_ptr res, mp_srcptr u, mp_srcptr v) { #if 0 mp_limb_t tmp[24], cy; flint_mpn_mul_16_8(res, u, v); flint_mpn_mul_16_8(tmp, u, v + 8); cy = mpn_add_n(res + 8, res + 8, tmp, 16); mpn_add_1(res + 24, tmp + 16, 8, cy); #else mp_limb_t tmp[33]; flint_mpn_mul_toom22(res, u, 16, v, 16, tmp); #endif return res[31]; } #else mp_limb_t flint_mpn_mul_1_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { NN_MUL_1X1(res[1], res[0], u[0], v[0]); return res[1]; } mp_limb_t flint_mpn_mul_2_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(res[2], res[1], 0, a, u[1], v0); return res[2]; } mp_limb_t flint_mpn_mul_2_2(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; mp_limb_t w[2]; w[0] = v[0]; w[1] = v[1]; NN_MUL_1X1(a, res[0], u[0], w[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, w, 2); NN_ADDMUL_S2_A2_1X1(res[3], res[2], b, a, u[1], w[1]); return res[3]; } mp_limb_t flint_mpn_mul_3_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(res[3], res[2], 0, a, u[2], v0); return res[3]; } mp_limb_t flint_mpn_mul_3_2(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; mp_limb_t w[2]; w[0] = v[0]; w[1] = v[1]; NN_MUL_1X1(a, res[0], u[0], w[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u + 1, w, 2); NN_ADDMUL_S2_A2_1X1(res[4], res[3], b, a, u[2], w[1]); return res[4]; } mp_limb_t flint_mpn_mul_3_3(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 1, v + 1, 2); NN_ADDMUL_S2_A2_1X1(res[5], res[4], b, a, u[2], v[2]); return res[5]; } mp_limb_t flint_mpn_mul_4_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(res[4], res[3], 0, a, u[3], v0); return res[4]; } mp_limb_t flint_mpn_mul_4_2(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; mp_limb_t w[2]; w[0] = v[0]; w[1] = v[1]; NN_MUL_1X1(a, res[0], u[0], w[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u + 1, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 2, w, 2); NN_ADDMUL_S2_A2_1X1(res[5], res[4], b, a, u[3], w[1]); return res[5]; } mp_limb_t flint_mpn_mul_4_3(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 1, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 2, v + 1, 2); NN_ADDMUL_S2_A2_1X1(res[6], res[5], b, a, u[3], v[2]); return res[6]; } mp_limb_t flint_mpn_mul_4_4(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 1, v + 1, 3); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 2, v + 2, 2); NN_ADDMUL_S2_A2_1X1(res[7], res[6], b, a, u[3], v[3]); return res[7]; } mp_limb_t flint_mpn_mul_5_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(res[5], res[4], 0, a, u[4], v0); return res[5]; } mp_limb_t flint_mpn_mul_5_2(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; mp_limb_t w[2]; w[0] = v[0]; w[1] = v[1]; NN_MUL_1X1(a, res[0], u[0], w[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u + 1, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 2, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 3, w, 2); NN_ADDMUL_S2_A2_1X1(res[6], res[5], b, a, u[4], w[1]); return res[6]; } mp_limb_t flint_mpn_mul_5_3(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 1, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 2, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 3, v + 1, 2); NN_ADDMUL_S2_A2_1X1(res[7], res[6], b, a, u[4], v[2]); return res[7]; } mp_limb_t flint_mpn_mul_5_4(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 1, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 2, v + 1, 3); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 3, v + 2, 2); NN_ADDMUL_S2_A2_1X1(res[8], res[7], b, a, u[4], v[3]); return res[8]; } mp_limb_t flint_mpn_mul_5_5(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 1, v + 1, 4); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 2, v + 2, 3); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 3, v + 3, 2); NN_ADDMUL_S2_A2_1X1(res[9], res[8], b, a, u[4], v[4]); return res[9]; } mp_limb_t flint_mpn_mul_6_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(res[6], res[5], 0, a, u[5], v0); return res[6]; } mp_limb_t flint_mpn_mul_6_2(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; mp_limb_t w[2]; w[0] = v[0]; w[1] = v[1]; NN_MUL_1X1(a, res[0], u[0], w[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u + 1, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 2, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 3, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 4, w, 2); NN_ADDMUL_S2_A2_1X1(res[7], res[6], b, a, u[5], w[1]); return res[7]; } mp_limb_t flint_mpn_mul_6_3(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 1, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 2, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 3, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 4, v + 1, 2); NN_ADDMUL_S2_A2_1X1(res[8], res[7], b, a, u[5], v[2]); return res[8]; } mp_limb_t flint_mpn_mul_6_4(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 1, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 2, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 3, v + 1, 3); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 4, v + 2, 2); NN_ADDMUL_S2_A2_1X1(res[9], res[8], b, a, u[5], v[3]); return res[9]; } mp_limb_t flint_mpn_mul_6_5(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 1, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 2, v + 1, 4); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 3, v + 2, 3); NN_DOTREV_S3_A3_1X1(b, a, res[8], 0, b, a, u + 4, v + 3, 2); NN_ADDMUL_S2_A2_1X1(res[10], res[9], b, a, u[5], v[4]); return res[10]; } mp_limb_t flint_mpn_mul_6_6(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u, v, 6); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 1, v + 1, 5); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 2, v + 2, 4); NN_DOTREV_S3_A3_1X1(b, a, res[8], 0, b, a, u + 3, v + 3, 3); NN_DOTREV_S3_A3_1X1(b, a, res[9], 0, b, a, u + 4, v + 4, 2); NN_ADDMUL_S2_A2_1X1(res[11], res[10], b, a, u[5], v[5]); return res[11]; } mp_limb_t flint_mpn_mul_7_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(res[7], res[6], 0, a, u[6], v0); return res[7]; } mp_limb_t flint_mpn_mul_7_2(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; mp_limb_t w[2]; w[0] = v[0]; w[1] = v[1]; NN_MUL_1X1(a, res[0], u[0], w[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u + 1, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 2, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 3, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 4, w, 2); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 5, w, 2); NN_ADDMUL_S2_A2_1X1(res[8], res[7], b, a, u[6], w[1]); return res[8]; } mp_limb_t flint_mpn_mul_7_3(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u + 1, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 2, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 3, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 4, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 5, v + 1, 2); NN_ADDMUL_S2_A2_1X1(res[9], res[8], b, a, u[6], v[2]); return res[9]; } mp_limb_t flint_mpn_mul_7_4(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u + 1, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 2, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 3, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 4, v + 1, 3); NN_DOTREV_S3_A3_1X1(b, a, res[8], 0, b, a, u + 5, v + 2, 2); NN_ADDMUL_S2_A2_1X1(res[10], res[9], b, a, u[6], v[3]); return res[10]; } mp_limb_t flint_mpn_mul_7_5(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u + 1, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 2, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 3, v + 1, 4); NN_DOTREV_S3_A3_1X1(b, a, res[8], 0, b, a, u + 4, v + 2, 3); NN_DOTREV_S3_A3_1X1(b, a, res[9], 0, b, a, u + 5, v + 3, 2); NN_ADDMUL_S2_A2_1X1(res[11], res[10], b, a, u[6], v[4]); return res[11]; } mp_limb_t flint_mpn_mul_7_6(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u, v, 6); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u + 1, v, 6); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 2, v + 1, 5); NN_DOTREV_S3_A3_1X1(b, a, res[8], 0, b, a, u + 3, v + 2, 4); NN_DOTREV_S3_A3_1X1(b, a, res[9], 0, b, a, u + 4, v + 3, 3); NN_DOTREV_S3_A3_1X1(b, a, res[10], 0, b, a, u + 5, v + 4, 2); NN_ADDMUL_S2_A2_1X1(res[12], res[11], b, a, u[6], v[5]); return res[12]; } mp_limb_t flint_mpn_mul_7_7(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t b, a; NN_MUL_1X1(a, res[0], u[0], v[0]); NN_DOTREV_S3_A3_1X1(b, a, res[1], 0, 0, a, u, v, 2); NN_DOTREV_S3_A3_1X1(b, a, res[2], 0, b, a, u, v, 3); NN_DOTREV_S3_A3_1X1(b, a, res[3], 0, b, a, u, v, 4); NN_DOTREV_S3_A3_1X1(b, a, res[4], 0, b, a, u, v, 5); NN_DOTREV_S3_A3_1X1(b, a, res[5], 0, b, a, u, v, 6); NN_DOTREV_S3_A3_1X1(b, a, res[6], 0, b, a, u, v, 7); NN_DOTREV_S3_A3_1X1(b, a, res[7], 0, b, a, u + 1, v + 1, 6); NN_DOTREV_S3_A3_1X1(b, a, res[8], 0, b, a, u + 2, v + 2, 5); NN_DOTREV_S3_A3_1X1(b, a, res[9], 0, b, a, u + 3, v + 3, 4); NN_DOTREV_S3_A3_1X1(b, a, res[10], 0, b, a, u + 4, v + 4, 3); NN_DOTREV_S3_A3_1X1(b, a, res[11], 0, b, a, u + 5, v + 5, 2); NN_ADDMUL_S2_A2_1X1(res[13], res[12], b, a, u[6], v[6]); return res[13]; } mp_limb_t flint_mpn_mul_8_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(a, res[6], 0, a, u[6], v0); NN_ADDMUL_S2_A2_1X1(res[8], res[7], 0, a, u[7], v0); return res[8]; } mp_limb_t flint_mpn_mul_9_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(a, res[6], 0, a, u[6], v0); NN_ADDMUL_S2_A2_1X1(a, res[7], 0, a, u[7], v0); NN_ADDMUL_S2_A2_1X1(res[9], res[8], 0, a, u[8], v0); return res[9]; } mp_limb_t flint_mpn_mul_10_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(a, res[6], 0, a, u[6], v0); NN_ADDMUL_S2_A2_1X1(a, res[7], 0, a, u[7], v0); NN_ADDMUL_S2_A2_1X1(a, res[8], 0, a, u[8], v0); NN_ADDMUL_S2_A2_1X1(res[10], res[9], 0, a, u[9], v0); return res[10]; } mp_limb_t flint_mpn_mul_11_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(a, res[6], 0, a, u[6], v0); NN_ADDMUL_S2_A2_1X1(a, res[7], 0, a, u[7], v0); NN_ADDMUL_S2_A2_1X1(a, res[8], 0, a, u[8], v0); NN_ADDMUL_S2_A2_1X1(a, res[9], 0, a, u[9], v0); NN_ADDMUL_S2_A2_1X1(res[11], res[10], 0, a, u[10], v0); return res[11]; } mp_limb_t flint_mpn_mul_12_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(a, res[6], 0, a, u[6], v0); NN_ADDMUL_S2_A2_1X1(a, res[7], 0, a, u[7], v0); NN_ADDMUL_S2_A2_1X1(a, res[8], 0, a, u[8], v0); NN_ADDMUL_S2_A2_1X1(a, res[9], 0, a, u[9], v0); NN_ADDMUL_S2_A2_1X1(a, res[10], 0, a, u[10], v0); NN_ADDMUL_S2_A2_1X1(res[12], res[11], 0, a, u[11], v0); return res[12]; } mp_limb_t flint_mpn_mul_13_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(a, res[6], 0, a, u[6], v0); NN_ADDMUL_S2_A2_1X1(a, res[7], 0, a, u[7], v0); NN_ADDMUL_S2_A2_1X1(a, res[8], 0, a, u[8], v0); NN_ADDMUL_S2_A2_1X1(a, res[9], 0, a, u[9], v0); NN_ADDMUL_S2_A2_1X1(a, res[10], 0, a, u[10], v0); NN_ADDMUL_S2_A2_1X1(a, res[11], 0, a, u[11], v0); NN_ADDMUL_S2_A2_1X1(res[13], res[12], 0, a, u[12], v0); return res[13]; } mp_limb_t flint_mpn_mul_14_1(mp_ptr res, mp_srcptr u, mp_srcptr v) { mp_limb_t a, v0 = v[0]; NN_MUL_1X1(a, res[0], u[0], v0); NN_ADDMUL_S2_A2_1X1(a, res[1], 0, a, u[1], v0); NN_ADDMUL_S2_A2_1X1(a, res[2], 0, a, u[2], v0); NN_ADDMUL_S2_A2_1X1(a, res[3], 0, a, u[3], v0); NN_ADDMUL_S2_A2_1X1(a, res[4], 0, a, u[4], v0); NN_ADDMUL_S2_A2_1X1(a, res[5], 0, a, u[5], v0); NN_ADDMUL_S2_A2_1X1(a, res[6], 0, a, u[6], v0); NN_ADDMUL_S2_A2_1X1(a, res[7], 0, a, u[7], v0); NN_ADDMUL_S2_A2_1X1(a, res[8], 0, a, u[8], v0); NN_ADDMUL_S2_A2_1X1(a, res[9], 0, a, u[9], v0); NN_ADDMUL_S2_A2_1X1(a, res[10], 0, a, u[10], v0); NN_ADDMUL_S2_A2_1X1(a, res[11], 0, a, u[11], v0); NN_ADDMUL_S2_A2_1X1(a, res[12], 0, a, u[12], v0); NN_ADDMUL_S2_A2_1X1(res[14], res[13], 0, a, u[13], v0); return res[14]; } #endif #define _MUL(mx, nx) flint_mpn_mul_##mx##_##nx #define MUL(mx, nx) _MUL(mx, nx) #if FLINT_HAVE_ADX const flint_mpn_mul_func_t flint_mpn_mul_func_tab[][FLINT_MPN_MUL_FUNC_TAB_WIDTH] = { {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 1,1), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 2,1), MUL( 2,2), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 3,1), MUL( 3,2), MUL( 3,3), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 4,1), MUL( 4,2), MUL( 4,3), MUL( 4,4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 5,1), MUL( 5,2), MUL( 5,3), MUL( 5,4), MUL( 5,5), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 6,1), MUL( 6,2), MUL( 6,3), MUL( 6,4), MUL( 6,5), MUL( 6,6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 7,1), MUL( 7,2), MUL( 7,3), MUL( 7,4), MUL( 7,5), MUL( 7,6), MUL( 7,7), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 8,1), MUL( 8,2), MUL( 8,3), MUL( 8,4), MUL( 8,5), MUL( 8,6), MUL( 8,7), MUL( 8,8), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 9,1), MUL( 9,2), MUL( 9,3), MUL( 9,4), MUL( 9,5), MUL( 9,6), MUL( 9,7), MUL( 9,8), MUL( 9,9), NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(10,1), MUL(10,2), MUL(10,3), MUL(10,4), MUL(10,5), MUL(10,6), MUL(10,7), MUL(10,8), MUL(10,9), MUL(10,10), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(11,1), MUL(11,2), MUL(11,3), MUL(11,4), MUL(11,5), MUL(11,6), MUL(11,7), MUL(11,8), MUL(11,9), MUL(11,10), MUL(11,11), NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(12,1), MUL(12,2), MUL(12,3), MUL(12,4), MUL(12,5), MUL(12,6), MUL(12,7), MUL(12,8), MUL(12,9), MUL(12,10), MUL(12,11), MUL(12,12), NULL, NULL, NULL, NULL}, {NULL, MUL(13,1), MUL(13,2), MUL(13,3), MUL(13,4), MUL(13,5), MUL(13,6), MUL(13,7), MUL(13,8), MUL(13,9), MUL(13,10), MUL(13,11), MUL(13,12), MUL(13,13), NULL, NULL, NULL}, {NULL, MUL(14,1), MUL(14,2), MUL(14,3), MUL(14,4), MUL(14,5), MUL(14,6), MUL(14,7), MUL(14,8), MUL(14,9), MUL(14,10), MUL(14,11), MUL(14,12), MUL(14,13), MUL(14,14), NULL, NULL}, {NULL, MUL(15,1), MUL(15,2), MUL(15,3), MUL(15,4), MUL(15,5), MUL(15,6), MUL(15,7), MUL(15,8), MUL(15,9), MUL(15,10), MUL(15,11), MUL(15,12), MUL(15,13), MUL(15,14), MUL(15,15), NULL}, {NULL, MUL(16,1), MUL(16,2), MUL(16,3), MUL(16,4), MUL(16,5), MUL(16,6), MUL(16,7), MUL(16,8), MUL(16,9), MUL(16,10), MUL(16,11), MUL(16,12), MUL(16,13), MUL(16,14), MUL(16,15), MUL(16,16)}, }; const flint_mpn_mul_func_t flint_mpn_mul_n_func_tab[] = { NULL, MUL( 1, 1), MUL( 2, 2), MUL( 3, 3), MUL( 4, 4), MUL( 5, 5), MUL( 6, 6), MUL( 7, 7), MUL( 8, 8), MUL( 9, 9), MUL( 10, 10), MUL( 11, 11), MUL( 12, 12), MUL( 13, 13), MUL( 14, 14), MUL( 15, 15), MUL( 16, 16), }; #else const flint_mpn_mul_func_t flint_mpn_mul_func_tab[][FLINT_MPN_MUL_FUNC_TAB_WIDTH] = { {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 1,1), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 2,1), MUL( 2,2), NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 3,1), MUL( 3,2), MUL( 3,3), NULL, NULL, NULL, NULL}, {NULL, MUL( 4,1), MUL( 4,2), MUL( 4,3), MUL( 4,4), NULL, NULL, NULL}, {NULL, MUL( 5,1), MUL( 5,2), MUL( 5,3), MUL( 5,4), MUL( 5,5), NULL, NULL}, {NULL, MUL( 6,1), MUL( 6,2), MUL( 6,3), MUL( 6,4), MUL( 6,5), MUL( 6,6), NULL}, {NULL, MUL( 7,1), MUL( 7,2), MUL( 7,3), MUL( 7,4), MUL( 7,5), MUL( 7,6), MUL( 7,7)}, {NULL, MUL( 8,1), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL( 9,1), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(10,1), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(11,1), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(12,1), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(13,1), NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, MUL(14,1), NULL, NULL, NULL, NULL, NULL, NULL}, }; const flint_mpn_mul_func_t flint_mpn_mul_n_func_tab[] = { NULL, MUL( 1, 1), MUL( 2, 2), MUL( 3, 3), MUL( 4, 4), MUL( 5, 5), MUL( 6, 6), MUL( 7, 7), }; #endif mp_limb_t flint_mpn_mul_basecase(mp_ptr r, mp_srcptr x, mp_srcptr y, mp_size_t xn, mp_size_t yn) { return flint_mpn_mul_func_tab[xn][yn](r, x, y); } flint-3.1.3/src/mpn_extras/mul_toom22.c000066400000000000000000000160161461254215100177510ustar00rootroot00000000000000/* Copyright 2006-2010, 2012, 2014, 2018, 2020 Free Software Foundation, Inc. Contributed to the GNU project by Torbjorn Granlund. Copyright 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* mpn_toom22_mul -- Multiply {ap,an} and {bp,bn} where an >= bn. Or more accurately, bn <= an < 2bn. Contributed to the GNU project by Torbjorn Granlund. THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE. IT IS ONLY SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE. Copyright 2006-2010, 2012, 2014, 2018, 2020 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of either: * the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. or * the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. or both in parallel, as here. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received copies of the GNU General Public License and the GNU Lesser General Public License along with the GNU MP Library. If not, see https://www.gnu.org/licenses/. */ #include "flint.h" #include "mpn_extras.h" /* Unoptimized */ #define MPN_INCR_U(ptr, size, n) mpn_add_1((ptr), (ptr), (size), (n)) /* Evaluate in: -1, 0, +inf <-s--><--n--> ____ ______ |_a1_|___a0_| |b1_|___b0_| <-t-><--n--> v0 = a0 * b0 # A(0)*B(0) vm1 = (a0- a1)*(b0- b1) # A(-1)*B(-1) vinf= a1 * b1 # A(inf)*B(inf) */ #define TOOM22_MUL_N_REC(p, a, b, n, ws) \ do { \ if (FLINT_HAVE_MUL_N_FUNC(n)) \ flint_mpn_mul_n_func_tab[n](p, a, b); \ else \ flint_mpn_mul_toom22(p, a, n, b, n, ws); \ } while (0) /* Normally, this calls mul_basecase or toom22_mul. But when when the fraction MUL_TOOM33_THRESHOLD / MUL_TOOM22_THRESHOLD is large, an initially small relative unbalance will become a larger and larger relative unbalance with each recursion (the difference s-t will be invariant over recursive calls). Therefore, we need to call toom32_mul. FIXME: Suppress depending on MUL_TOOM33_THRESHOLD / MUL_TOOM22_THRESHOLD and on MUL_TOOM22_THRESHOLD. */ #define TOOM22_MUL_REC(p, a, an, b, bn, ws) \ do { \ if (FLINT_HAVE_MUL_FUNC(an, bn)) \ flint_mpn_mul_func_tab[an][bn](p, a, b); \ else if (bn <= 12 || 4 * an >= 5 * bn) \ flint_mpn_mul(p, a, an, b, bn); \ else \ flint_mpn_mul_toom22(p, a, an, b, bn, ws); \ } while (0) /* else if (4 * an < 5 * bn) \ mpn_toom22_mul (p, a, an, b, bn, ws); \ else \ mpn_toom32_mul (p, a, an, b, bn, ws); \ */ /* Needed scratch space is 2*(an + k), where k is the recursion depth. */ void flint_mpn_mul_toom22(mp_ptr pp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn, mp_ptr scratch) { mp_size_t n, s, t; int vm1_neg; mp_limb_t cy, cy2; mp_ptr asm1; mp_ptr bsm1; TMP_INIT; TMP_START; if (scratch == NULL) { scratch = TMP_ALLOC(sizeof(mp_limb_t) * (2 * ((an) + FLINT_BITS))); } #define a0 ap #define a1 (ap + n) #define b0 bp #define b1 (bp + n) s = an >> 1; n = an - s; t = bn - n; FLINT_ASSERT(an >= bn); FLINT_ASSERT(0 < s && s <= n && (n - s) == (an & 1)); FLINT_ASSERT(0 < t && t <= s); asm1 = pp; bsm1 = pp + n; vm1_neg = 0; /* Compute asm1. */ if ((an & 1) == 0) /* s == n */ { if (mpn_cmp(a0, a1, n) < 0) { mpn_sub_n(asm1, a1, a0, n); vm1_neg = 1; } else { mpn_sub_n(asm1, a0, a1, n); } } else /* n - s == 1 */ { if (a0[s] == 0 && mpn_cmp(a0, a1, s) < 0) { mpn_sub_n(asm1, a1, a0, s); asm1[s] = 0; vm1_neg = 1; } else { asm1[s] = a0[s] - mpn_sub_n(asm1, a0, a1, s); } } /* Compute bsm1. */ if (t == n) { if (mpn_cmp(b0, b1, n) < 0) { mpn_sub_n(bsm1, b1, b0, n); vm1_neg ^= 1; } else { mpn_sub_n(bsm1, b0, b1, n); } } else { if (flint_mpn_zero_p(b0 + t, n - t) && mpn_cmp(b0, b1, t) < 0) { mpn_sub_n(bsm1, b1, b0, t); flint_mpn_zero(bsm1 + t, n - t); vm1_neg ^= 1; } else { mpn_sub(bsm1, b0, n, b1, t); } } #define v0 pp /* 2n */ #define vinf (pp + 2 * n) /* s+t */ #define vm1 scratch /* 2n */ #define scratch_out scratch + 2 * n /* vm1, 2n limbs */ TOOM22_MUL_N_REC (vm1, asm1, bsm1, n, scratch_out); if (s > t) TOOM22_MUL_REC(vinf, a1, s, b1, t, scratch_out); else TOOM22_MUL_N_REC(vinf, a1, b1, s, scratch_out); /* v0, 2n limbs */ TOOM22_MUL_N_REC(v0, ap, bp, n, scratch_out); /* H(v0) + L(vinf) */ cy = mpn_add_n(pp + 2 * n, v0 + n, vinf, n); /* L(v0) + (H(v0) + L(vinf)) */ cy2 = cy + mpn_add_n(pp + n, pp + 2 * n, v0, n); /* (H(v0) + L(vinf)) + H(vinf) */ cy += mpn_add(pp + 2 * n, pp + 2 * n, n, vinf + n, s + t - n); if (vm1_neg) { cy += mpn_add_n(pp + n, pp + n, vm1, 2 * n); } else { cy -= mpn_sub_n(pp + n, pp + n, vm1, 2 * n); if (FLINT_UNLIKELY(cy + 1 == 0)) /* cy is negative */ { /* The total contribution of v0+vinf-vm1 can not be negative. */ #if FLINT_WANT_ASSERT /* The borrow in cy stops the propagation of the carry cy2, */ FLINT_ASSERT(cy2 == 1); cy += mpn_add_1(pp + 2 * n, pp + 2 * n, n, cy2); FLINT_ASSERT (cy == 0); #else /* we simply fill the area with zeros. */ flint_mpn_zero(pp + 2 * n, n); FLINT_ASSERT(s + t == n || flint_mpn_zero_p(pp + 3 * n, s + t - n)); #endif goto cleanup; } } FLINT_ASSERT(cy <= 2); FLINT_ASSERT(cy2 <= 2); MPN_INCR_U(pp + 2 * n, s + t, cy2); /* if s+t==n, cy is zero, but we should not access pp[3*n] at all. */ MPN_INCR_U(pp + 3 * n, s + t - n, cy); cleanup: TMP_END; } flint-3.1.3/src/mpn_extras/mulhigh.c000066400000000000000000000073301461254215100174060ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #if FLINT_HAVE_ADX mp_limb_t flint_mpn_mulhigh_1(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_8(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_9(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_10(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_11(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mulhigh_12(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_1(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_2(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_3(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_4(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_5(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_6(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_7(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_8(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_9(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_10(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_11(mp_ptr, mp_srcptr, mp_srcptr); struct mp_limb_pair_t flint_mpn_mulhigh_normalised_12(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_1(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_2(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_3(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_4(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_5(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_6(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_7(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqrhigh_8(mp_ptr, mp_srcptr); const flint_mpn_mul_func_t flint_mpn_mulhigh_func_tab[] = { NULL, flint_mpn_mulhigh_1, flint_mpn_mulhigh_2, flint_mpn_mulhigh_3, flint_mpn_mulhigh_4, flint_mpn_mulhigh_5, flint_mpn_mulhigh_6, flint_mpn_mulhigh_7, flint_mpn_mulhigh_8, flint_mpn_mulhigh_9, flint_mpn_mulhigh_10, flint_mpn_mulhigh_11, flint_mpn_mulhigh_12 }; const flint_mpn_mulhigh_normalised_func_t flint_mpn_mulhigh_normalised_func_tab[] = { NULL, flint_mpn_mulhigh_normalised_1, flint_mpn_mulhigh_normalised_2, flint_mpn_mulhigh_normalised_3, flint_mpn_mulhigh_normalised_4, flint_mpn_mulhigh_normalised_5, flint_mpn_mulhigh_normalised_6, flint_mpn_mulhigh_normalised_7, flint_mpn_mulhigh_normalised_8, flint_mpn_mulhigh_normalised_9, flint_mpn_mulhigh_normalised_10, flint_mpn_mulhigh_normalised_11, flint_mpn_mulhigh_normalised_12 }; const flint_mpn_sqr_func_t flint_mpn_sqrhigh_func_tab[] = { NULL, flint_mpn_sqrhigh_1, flint_mpn_sqrhigh_2, flint_mpn_sqrhigh_3, flint_mpn_sqrhigh_4, flint_mpn_sqrhigh_5, flint_mpn_sqrhigh_6, flint_mpn_sqrhigh_7, flint_mpn_sqrhigh_8 }; #else typedef int this_file_is_empty; #endif flint-3.1.3/src/mpn_extras/mulmod_2expp1_basecase.c000066400000000000000000000045131461254215100222730ustar00rootroot00000000000000/* Copyright 2009 Jason Moxham This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" /* ret + (xp,n) = (yp,n)*(zp,n) % 2^b+1 needs (tp,2n) temp space, everything reduced mod 2^b inputs, outputs are fully reduced NOTE: 2n is not the same as 2b rounded up to nearest limb */ static inline int flint_mpn_mulmod_2expp1_internal(mp_ptr xp, mp_srcptr yp, mp_srcptr zp, flint_bitcnt_t b, mp_ptr tp) { mp_size_t n, k; mp_limb_t c; n = BITS_TO_LIMBS(b); k = GMP_NUMB_BITS * n - b; if (yp == zp) flint_mpn_sqr(tp, yp, n); else flint_mpn_mul_n(tp, yp, zp, n); if (k == 0) { c = mpn_sub_n(xp, tp, tp + n, n); return mpn_add_1 (xp, xp, n, c); } c = tp[n - 1]; tp[n - 1] &= GMP_NUMB_MASK >> k; #if HAVE_NATIVE_mpn_sublsh_nc c = mpn_sublsh_nc (xp, tp, tp + n, n, k, c); #else { mp_limb_t c1; c1 = mpn_lshift (tp + n, tp + n, n, k); tp[n] |= c >> (GMP_NUMB_BITS - k); c = mpn_sub_n (xp, tp, tp + n, n) + c1; } #endif c = mpn_add_1 (xp, xp, n, c); xp[n - 1] &= GMP_NUMB_MASK >> k; return c; } /* c is the top bits of the inputs, must be fully reduced */ int flint_mpn_mulmod_2expp1_basecase (mp_ptr xp, mp_srcptr yp, mp_srcptr zp, int c, flint_bitcnt_t b, mp_ptr tp) { int cy, cz; mp_size_t n, k; cy = c & 2; cz = c & 1; n = BITS_TO_LIMBS(b); k = GMP_NUMB_BITS * n - b; if (cy == 0) { if (cz == 0) { c = flint_mpn_mulmod_2expp1_internal(xp, yp, zp, b, tp); } else { c = mpn_neg(xp, yp, n); c = mpn_add_1 (xp, xp, n, c); xp[n - 1] &= GMP_NUMB_MASK >> k; } } else { if (cz == 0) { c = mpn_neg(xp, zp, n); c = mpn_add_1(xp, xp, n, c); xp[n - 1] &= GMP_NUMB_MASK >> k; } else { c = 0; xp[0] = 1; flint_mpn_zero(xp + 1, n - 1); } } return c; } flint-3.1.3/src/mpn_extras/mulmod_preinv1.c000066400000000000000000000025601461254215100207120ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" #if !defined(_MSC_VER) #pragma GCC diagnostic ignored "-Wunused-variable" #endif void flint_mpn_mulmod_preinv1(mp_ptr r, mp_srcptr a, mp_srcptr b, mp_size_t n, mp_srcptr d, mp_limb_t dinv, ulong norm) { mp_limb_t q; mp_limb_t ts[150]; mp_ptr t; slong i; FLINT_ASSERT(n > 0); if (n <= 30) t = ts; else t = flint_malloc(5*n*sizeof(mp_limb_t)); if (a == b) flint_mpn_sqr(t, a, n); else flint_mpn_mul_n(t, a, b, n); if (norm) mpn_rshift(t, t, 2*n, norm); for (i = 2*n - 1; i >= n; i--) { flint_mpn_divrem21_preinv(q, t[i], t[i - 1], dinv); t[i] -= mpn_submul_1(t + i - n, d, n, q); if (mpn_cmp(t + i - n, d, n) >= 0 || t[i] != 0) { q++; t[i] -= mpn_sub_n(t + i - n, t + i - n, d, n); } } mpn_copyi(r, t, n); if (n > 30) flint_free(t); } #if !defined(_MSC_VER) #pragma GCC diagnostic warning "-Wunused-variable" #endif flint-3.1.3/src/mpn_extras/mulmod_preinvn.c000066400000000000000000000057301461254215100210110ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" /* TODO: speedup mpir's mullow and mulhigh and use instead of mul/mul_n */ void flint_mpn_mulmod_preinvn(mp_ptr r, mp_srcptr a, mp_srcptr b, mp_size_t n, mp_srcptr d, mp_srcptr dinv, ulong norm) { mp_limb_t cy, p1, p2, b0, b1; mp_ptr t; TMP_INIT; TMP_START; t = TMP_ALLOC(5*n*sizeof(mp_limb_t)); if (n == 2) { if (norm) { /* mpn_rshift(b, b, n, norm) */ b0 = (b[0] >> norm) | (b[1] << (FLINT_BITS - norm)); b1 = b[1] >> norm; } else { b0 = b[0]; b1 = b[1]; } /* mpn_mul_n(t, a, b, n) */ umul_ppmm(t[1], t[0], a[0], b0); umul_ppmm(t[3], t[2], a[1], b1); umul_ppmm(p2, p1, a[0], b1); add_sssaaaaaa(t[3], t[2], t[1], t[3], t[2], t[1], 0, p2, p1); umul_ppmm(p2, p1, a[1], b0); add_sssaaaaaa(t[3], t[2], t[1], t[3], t[2], t[1], 0, p2, p1); /* mpn_mul_n(t + 3*n, t + n, dinv, n) */ umul_ppmm(t[7], t[6], t[2], dinv[0]); umul_ppmm(t[9], t[8], t[3], dinv[1]); umul_ppmm(p2, p1, t[2], dinv[1]); add_sssaaaaaa(t[9], t[8], t[7], t[9], t[8], t[7], 0, p2, p1); umul_ppmm(p2, p1, t[3], dinv[0]); add_sssaaaaaa(t[9], t[8], t[7], t[9], t[8], t[7], 0, p2, p1); /* mpn_add_n(t + 4*n, t + 4*n, t + n, n) */ add_ssaaaa(t[9], t[8], t[9], t[8], t[3], t[2]); /* mpn_mul_n(t + 2*n, t + 4*n, d, n) */ umul_ppmm(t[5], t[4], t[8], d[0]); t[6] = t[9]*d[1]; umul_ppmm(p2, p1, t[8], d[1]); add_ssaaaa(t[6], t[5], t[6], t[5], p2, p1); umul_ppmm(p2, p1, t[9], d[0]); add_ssaaaa(t[6], t[5], t[6], t[5], p2, p1); /* cy = t[n] - t[3*n] - mpn_sub_n(r, t, t + 2*n, n) */ sub_dddmmmsss(cy, r[1], r[0], t[2], t[1], t[0], t[6], t[5], t[4]); while (cy > 0) { /* cy -= mpn_sub_n(r, r, d, n) */ sub_dddmmmsss(cy, r[1], r[0], cy, r[1], r[0], 0, d[1], d[0]); } if ((r[1] > d[1]) || (r[1] == d[1] && r[0] >= d[0])) { /* mpn_sub_n(r, r, d, n) */ sub_ddmmss(r[1], r[0], r[1], r[0], d[1], d[0]); } } else { if (a == b) flint_mpn_sqr(t, a, n); else flint_mpn_mul_n(t, a, b, n); if (norm) mpn_rshift(t, t, 2*n, norm); flint_mpn_mul_n(t + 3*n, t + n, dinv, n); mpn_add_n(t + 4*n, t + 4*n, t + n, n); flint_mpn_mul_n(t + 2*n, t + 4*n, d, n); cy = t[n] - t[3*n] - mpn_sub_n(r, t, t + 2*n, n); while (cy > 0) cy -= mpn_sub_n(r, r, d, n); if (mpn_cmp(r, d, n) >= 0) mpn_sub_n(r, r, d, n); } TMP_END; } flint-3.1.3/src/mpn_extras/preinv1.c000066400000000000000000000016531461254215100173370ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" mp_limb_t flint_mpn_preinv1(mp_limb_t d1, mp_limb_t d2) { mp_limb_t q, r[2], p[2], cy; if (d2 + 1 == 0 && d1 + 1 == 0) return 0; if (d1 + 1 == 0) q = ~d1, r[1] = ~d2; else udiv_qrnnd(q, r[1], ~d1, ~d2, d1 + 1); if (d2 + 1 == 0) return q; r[0] = 0; umul_ppmm(p[1], p[0], q, ~d2); cy = mpn_add_n(r, r, p, 2); p[0] = d2 + 1, p[1] = d1 + (d2 + 1 == 0); while (cy || mpn_cmp(r, p, 2) >= 0) { q++; cy -= mpn_sub_n(r, r, p, 2); } return q; } flint-3.1.3/src/mpn_extras/preinvn.c000066400000000000000000000016601461254215100174320ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" void flint_mpn_preinvn(mp_ptr dinv, mp_srcptr d, mp_size_t n) { mp_ptr q, r, d1; d1 = flint_malloc(n*sizeof(mp_limb_t)); if (mpn_add_1(d1, d, n, 1)) /* check for d + 1 == 0 */ { mpn_zero(dinv, n); flint_free(d1); return; } r = flint_malloc((2*n + 1)*sizeof(mp_limb_t)); q = flint_malloc((n + 2)*sizeof(mp_limb_t)); mpn_zero(r, 2*n); r[2*n] = 1; mpn_tdiv_qr(q, r, 0, r, 2*n + 1, d1, n); mpn_copyi(dinv, q, n); flint_free(r); flint_free(q); flint_free(d1); } flint-3.1.3/src/mpn_extras/profile/000077500000000000000000000000001461254215100172425ustar00rootroot00000000000000flint-3.1.3/src/mpn_extras/profile/p-mul_basecase.c000066400000000000000000000034431461254215100222720ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "profiler.h" #define mpn_mul_basecase __gmpn_mul_basecase void mpn_mul_basecase(mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); int main(void) { mp_limb_t res1[24]; mp_limb_t res2[24]; mp_limb_t ap[16]; mp_limb_t bp[8]; slong mx, nx; flint_printf(" "); for (nx = 1; nx <= 8; nx++) flint_printf("%6wd ", nx); flint_printf("\n\n"); for (mx = 1; mx <= 16; mx++) { if (FLINT_HAVE_MUL_FUNC(mx, 1)) { flint_printf("m = %2wd:", mx); for (nx = 1; nx <= FLINT_MIN(mx, WORD(8)); nx++) { double t1, t2, __attribute__((unused)) __; if (FLINT_HAVE_MUL_FUNC(mx, nx)) { mpn_random2(ap, mx); mpn_random2(bp, nx); TIMEIT_START mpn_mul_basecase(res1, ap, mx, bp, nx); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START flint_mpn_mul_basecase(res2, ap, bp, mx, nx); TIMEIT_STOP_VALUES(__, t2) flint_printf("%7.2fx", t1 / t2); if (mpn_cmp(res1, res2, mx + nx) != 0) flint_abort(); } } flint_printf("\n\n"); } } flint_cleanup_master(); return 0; } flint-3.1.3/src/mpn_extras/profile/p-mul_n.c000066400000000000000000000042031461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" #include "profiler.h" #define MAXN 16 #define MAXN2 256 int main(void) { flint_rand_t state; mp_limb_t x[MAXN2], y[MAXN2], r[2 * MAXN2], s[2 * MAXN2]; slong i, n, m; double t1, t2, __attribute__((unused)) __; flint_randinit(state); { for (i = 0; i < MAXN; i++) { x[i] = n_randtest(state); y[i] = n_randtest(state); } flint_printf("mpn_mul_n vs flint_mpn_mul_n\n\n"); for (n = 1; n <= MAXN2; n = (n <= MAXN ? n + 1 : n * 1.2)) { flint_printf("n = %wd ", n); TIMEIT_START #if 0 __gmpn_mul_basecase(r, x, n, y, n); #else mpn_mul_n(r, x, y, n); #endif TIMEIT_STOP_VALUES(__, t1) TIMEIT_START flint_mpn_mul_n(s, x, y, n); TIMEIT_STOP_VALUES(__, t2) flint_printf("%g %g %.2f\n", t1, t2, t1 / t2); if (mpn_cmp(r, s, 2 * n) != 0) flint_abort(); } flint_printf("mpn_mul vs flint_mpn_mul\n\n"); for (n = 1; n <= MAXN2; n = (n <= MAXN ? n + 1 : n * 1.2)) { flint_printf("n = %wd ", n); for (m = 1; m <= n; m = (m <= MAXN ? m + 1 : m * 1.2)) { TIMEIT_START mpn_mul(r, x, n, y, m); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START flint_mpn_mul(s, x, n, y, m); TIMEIT_STOP_VALUES(__, t2) flint_printf("%.2f ", t1 / t2); if (mpn_cmp(r, s, n + m) != 0) flint_abort(); } flint_printf("\n"); } } flint_randclear(state); flint_cleanup_master(); return 0; } flint-3.1.3/src/mpn_extras/profile/p-mulhigh_basecase.c000066400000000000000000000040711461254215100231300ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "profiler.h" #if !FLINT_HAVE_ADX # error #endif #define mpn_mul_basecase __gmpn_mul_basecase void mpn_mul_basecase(mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); void mpfr_mulhigh_n(mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); int main(void) { #define N_MIN 1 #define N_MAX 64 mp_limb_t rf[N_MAX]; mp_limb_t rg[2 * N_MAX]; mp_limb_t rm[2 * N_MAX]; mp_limb_t xp[N_MAX]; mp_limb_t yp[N_MAX]; mp_size_t n; flint_printf("Best of mpn_mul_n, mpn_mul_basecase and mpfr_mulhigh_n\nagainst flint_mpn_mulhigh_basecase:\n"); for (n = N_MIN; n <= N_MAX; n++) { double t1, t2, t3, t4, tmin, __attribute__((unused)) __; int type; flint_printf("n = %2wd:", n); mpn_random2(xp, n); mpn_random2(yp, n); TIMEIT_START flint_mpn_mulhigh_basecase(rf, xp, yp, n); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START mpn_mul_basecase(rg, xp, n, yp, n); TIMEIT_STOP_VALUES(__, t2) TIMEIT_START mpn_mul_n(rg, xp, yp, n); TIMEIT_STOP_VALUES(__, t3) TIMEIT_START mpfr_mulhigh_n(rm, xp, yp, n); TIMEIT_STOP_VALUES(__, t4) if (t2 < t3) { tmin = t2; type = 2; } else { tmin = t3; type = 3; } if (tmin < t4) ; else { tmin = t4; type = 4; } flint_printf("%7.2fx (%s)\n", tmin / t1, (type == 2) ? "mpn_mul_basecase" : (type == 3) ? "mpn_mul_n" : "mpfr_mulhigh_n"); } flint_cleanup_master(); return 0; } #undef N_MIN #undef N_MAX flint-3.1.3/src/mpn_extras/profile/p-mulhigh_normalised.c000066400000000000000000000026131461254215100235170ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "profiler.h" #define N_MAX FLINT_MPN_MULHIGH_NORMALISED_FUNC_TAB_WIDTH int main(void) { mp_limb_t rn[N_MAX]; mp_limb_t ru[N_MAX]; mp_limb_t xp[N_MAX]; mp_limb_t yp[N_MAX]; mp_size_t n; flint_printf("Times: Normalised / Unnormalised\n"); for (n = 1; n <= N_MAX; n++) { flint_printf("n = %2wd:", n); for (slong ix = 0; ix < 10; ix++) { double t1, t2, __attribute__((unused)) __; mpn_random2(xp, n); mpn_random2(yp, n); xp[n - 1] |= (UWORD(1) << (FLINT_BITS - 1)); yp[n - 1] |= (UWORD(1) << (FLINT_BITS - 1)); TIMEIT_START flint_mpn_mulhigh_basecase(ru, xp, yp, n); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START flint_mpn_mulhigh_normalised(rn, xp, yp, n); TIMEIT_STOP_VALUES(__, t2) flint_printf("%7.2fx", t2 / t1); } flint_printf("\n"); } flint_cleanup_master(); return 0; } flint-3.1.3/src/mpn_extras/profile/p-mulmod_preinvn.c000066400000000000000000000077661461254215100227210ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "mpn_extras.h" #include "ulong_extras.h" #define mock_mulmod_preinvn(rxx, axx, bxx, nnn, nxx, ninv, norm) \ do { \ mp_ptr __t; \ TMP_INIT; \ \ TMP_START; \ __t = TMP_ALLOC(3*(nnn)*sizeof(mp_limb_t)); \ \ mpn_mul_n(__t, axx, bxx, nnn); \ if (norm) \ mpn_rshift(__t, __t, 2*(nnn), norm); \ \ mpn_tdiv_qr(__t + 2*(nnn), rxx, 0, __t, 2*(nnn), nxx, nnn); \ TMP_END; \ } while (0) typedef struct { slong limbs; int algo; } info_t; void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong size = info->limbs, i, j; int algo = info->algo; int scale = 200; mpz_t a, b, d, r2; gmp_randstate_t st; mp_ptr dinv; flint_bitcnt_t norm; FLINT_TEST_INIT(state); mpz_init(a); mpz_init(b); mpz_init(d); /* don't init r2 */ gmp_randinit_default(st); for (i = 0; i < count; i++) { mpz_rrandomb(a, st, size*FLINT_BITS); mpz_rrandomb(b, st, size*FLINT_BITS); do { mpz_rrandomb(d, st, size*FLINT_BITS); } while (mpz_sgn(d) == 0); /* reduce a, b mod d */ mpz_fdiv_r(a, a, d); mpz_fdiv_r(b, b, d); /* normalise */ norm = flint_clz(d->_mp_d[d->_mp_size - 1]); mpz_mul_2exp(a, a, norm); mpz_mul_2exp(b, b, norm); mpz_mul_2exp(d, d, norm); dinv = flint_malloc(size*sizeof(mp_limb_t)); flint_mpn_preinvn(dinv, d->_mp_d, size); r2->_mp_d = flint_malloc(size*sizeof(mp_limb_t)); prof_start(); if (algo == 1) { for (j = 0; j < scale; j++) { flint_mpn_mulmod_preinvn(r2->_mp_d, a->_mp_d, b->_mp_d, size, d->_mp_d, dinv, norm); } } else { for (j = 0; j < scale; j++) { mock_mulmod_preinvn(r2->_mp_d, a->_mp_d, b->_mp_d, size, d->_mp_d, dinv, norm); } } prof_stop(); flint_free(r2->_mp_d); flint_free(dinv); } mpz_clear(a); mpz_clear(b); mpz_clear(d); /* don't init r2 */ gmp_randclear(st); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("1: With precomputed inverse\n"); printf("2: Without precomputed inverse\n\n"); for (k = 1; k <= 10000; k = (slong) ceil(1.1*k)) { info.limbs = k; info.algo = 1; scale = 200; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("1: limbs %wd, min %.3g ms, max %.3g ms\n", info.limbs, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); info.algo = 2; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("2: limbs %wd, min %.3g ms, max %.3g ms\n\n", info.limbs, ((min/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0, ((max/(double)FLINT_CLOCK_SCALE_FACTOR)/scale)/2400000.0 ); } return 0; } flint-3.1.3/src/mpn_extras/profile/p-sqr_basecase.c000066400000000000000000000027671461254215100223120ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "mpn_extras.h" #include "profiler.h" #define mpn_sqr_basecase __gmpn_sqr_basecase void mpn_sqr_basecase(mp_ptr, mp_srcptr, mp_size_t); #define N_MAX FLINT_MPN_SQR_FUNC_TAB_WIDTH static void measure(mp_ptr rp1, mp_ptr rp2, mp_ptr ap, slong mx) { double t1, t2, FLINT_SET_BUT_UNUSED(__); if (FLINT_HAVE_SQR_FUNC(mx)) { flint_printf("m = %2wd:", mx); mpn_random2(ap, mx); TIMEIT_START mpn_sqr_basecase(rp1, ap, mx); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START flint_mpn_sqr(rp2, ap, mx); TIMEIT_STOP_VALUES(__, t2) flint_printf("%7.2fx\n", t1 / t2); } } int main(int argc, char ** argv) { mp_limb_t res1[2 * N_MAX]; mp_limb_t res2[2 * N_MAX]; mp_limb_t ap[N_MAX]; slong mx; if (argc == 2) { measure(res1, res2, ap, strtol(argv[1], NULL, 10)); goto end; } flint_printf("mpn_sqr_basecase / flint_mpn_sqr\n"); for (mx = 1; mx <= N_MAX; mx++) measure(res1, res2, ap, mx); end: flint_cleanup_master(); return 0; } flint-3.1.3/src/mpn_extras/profile/p-sqrhigh_basecase.c000066400000000000000000000023541461254215100231420ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "profiler.h" #if !FLINT_HAVE_ADX # error #endif #define N_MIN 1 #define N_MAX 128 #define mpn_sqr_basecase __gmpn_sqr_basecase void mpn_sqr_basecase(mp_ptr, mp_srcptr, mp_size_t); int main(void) { mp_limb_t rf[N_MAX]; mp_limb_t rg[2 * N_MAX]; mp_limb_t xp[N_MAX]; mp_size_t n; flint_printf("mpn_sqr_basecase / flint_mpn_sqrhigh_basecase:\n"); for (n = N_MIN; n <= N_MAX; n++) { double t1, t2, __attribute__((unused)) __; flint_printf("n = %2wd:", n); mpn_random2(xp, n); TIMEIT_START flint_mpn_sqrhigh_basecase(rf, xp, n); TIMEIT_STOP_VALUES(__, t1) TIMEIT_START flint_mpn_sqr(rg, xp, n); TIMEIT_STOP_VALUES(__, t2) flint_printf("%7.2fx\n", t2 / t1); } flint_cleanup_master(); return 0; } #undef N_MAX #undef N_MIN flint-3.1.3/src/mpn_extras/remove_2exp.c000066400000000000000000000020271461254215100202020ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpn_extras.h" mp_size_t flint_mpn_remove_2exp(mp_ptr x, mp_size_t xsize, flint_bitcnt_t *bits) { mp_size_t shift_limbs, reduced_size; flint_bitcnt_t shift_bits; *bits = mpn_scan1(x, 0); if (*bits == 0) return xsize; shift_limbs = *bits / FLINT_BITS; shift_bits = *bits % FLINT_BITS; reduced_size = xsize - shift_limbs; if (shift_bits) { mpn_rshift(x, x + shift_limbs, reduced_size, shift_bits); if (x[reduced_size - 1] == 0) reduced_size -= 1; } else { flint_mpn_copyi(x, x + shift_limbs, reduced_size); } return reduced_size; } flint-3.1.3/src/mpn_extras/remove_power.c000066400000000000000000000047231461254215100204650ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "mpn_extras.h" mp_size_t flint_mpn_remove_power_ascending(mp_ptr x, mp_size_t xsize, mp_ptr p, mp_size_t psize, ulong *exp) { int i, maxi; mp_ptr div; mp_ptr rem; mp_ptr square[FLINT_BITS]; mp_size_t square_size[FLINT_BITS]; mp_size_t sqsize; *exp = 0; if (psize > xsize) return xsize; maxi = 0; square[0] = p; square_size[0] = psize; /* Most likely less memory will be needed, but this way we avoid reallocations */ div = flint_malloc(sizeof(mp_limb_t) * xsize); rem = flint_malloc(sizeof(mp_limb_t) * xsize); /* Remove ascending powers */ for (i = 0; i < FLINT_BITS && xsize >= square_size[i]; i++) { mpn_tdiv_qr(div, rem, 0, x, xsize, square[i], square_size[i]); if (!flint_mpn_zero_p(rem, square_size[i])) { i -= 1; break; } *exp += (1 << i); xsize = xsize - square_size[i] + 1; if (div[xsize-1] == 0) xsize--; flint_mpn_copyi(x, div, xsize); /* Form next square if needed */ sqsize = square_size[i] * 2; if (sqsize - 1 > xsize) break; maxi = i + 1; square[i + 1] = flint_malloc(sizeof(mp_limb_t) * sqsize); flint_mpn_sqr(square[i + 1], square[i], square_size[i]); if (square[i + 1][sqsize - 1] == 0) sqsize -= 1; square_size[i + 1] = sqsize; } /* Remove descending powers */ for ( ; i >= 0; i--) { if (xsize >= square_size[i]) { mpn_tdiv_qr(div, rem, 0, x, xsize, square[i], square_size[i]); if (flint_mpn_zero_p(rem, square_size[i])) { *exp += (1 << i); xsize = xsize - square_size[i] + 1; if (div[xsize-1] == 0) xsize--; flint_mpn_copyi(x, div, xsize); } } } for (i = 1; i <= maxi; i++) flint_free(square[i]); flint_free(div); flint_free(rem); return xsize; } flint-3.1.3/src/mpn_extras/sqr_basecase.c000066400000000000000000000060731461254215100204070ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #if FLINT_HAVE_ADX mp_limb_t flint_mpn_sqr_1(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_2(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_3(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_4(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_5(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_6(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_7(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_8(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_9(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_sqr_10(mp_ptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_2(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_3(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_4(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_5(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_6(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_7_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_mul_8_7(mp_ptr, mp_srcptr, mp_srcptr); mp_limb_t flint_mpn_sqr_11(mp_ptr res, mp_srcptr x) { mp_limb_t t[14]; flint_mpn_sqr_7(res, x); flint_mpn_sqr_4(res + 14, x + 7); flint_mpn_mul_7_4(t, x, x + 7); t[11] = 0; t[12] = 0; t[13] = 0; res[21] += mpn_addmul_1(res + 7, t, 14, 2); return res[21]; } mp_limb_t flint_mpn_sqr_12(mp_ptr res, mp_srcptr x) { mp_limb_t t[12]; mp_limb_t cy; flint_mpn_sqr_7(res, x); flint_mpn_sqr_5(res + 14, x + 7); flint_mpn_mul_7_5(t, x, x + 7); cy = mpn_addmul_1(res + 7, t, 12, 2); mpn_add_1(res + 19, res + 19, 5, cy); return res[23]; } mp_limb_t flint_mpn_sqr_13(mp_ptr res, mp_srcptr x) { mp_limb_t t[13]; mp_limb_t cy; flint_mpn_sqr_7(res, x); flint_mpn_sqr_6(res + 14, x + 7); flint_mpn_mul_7_6(t, x, x + 7); cy = mpn_addmul_1(res + 7, t, 13, 2); mpn_add_1(res + 20, res + 20, 6, cy); return res[25]; } mp_limb_t flint_mpn_sqr_14(mp_ptr res, mp_srcptr x) { mp_limb_t t[14]; mp_limb_t cy; flint_mpn_sqr_7(res, x); flint_mpn_sqr_7(res + 14, x + 7); flint_mpn_mul_7_7(t, x, x + 7); cy = mpn_addmul_1(res + 7, t, 14, 2); mpn_add_1(res + 21, res + 21, 7, cy); return res[27]; } const flint_mpn_sqr_func_t flint_mpn_sqr_func_tab[] = { NULL, flint_mpn_sqr_1, flint_mpn_sqr_2, flint_mpn_sqr_3, flint_mpn_sqr_4, flint_mpn_sqr_5, flint_mpn_sqr_6, flint_mpn_sqr_7, flint_mpn_sqr_8, flint_mpn_sqr_9, flint_mpn_sqr_10, flint_mpn_sqr_11, flint_mpn_sqr_12, flint_mpn_sqr_13, flint_mpn_sqr_14 }; #else /* Currently generic C code performs worse than GMP. */ const flint_mpn_sqr_func_t flint_mpn_sqr_func_tab[] = { NULL, }; #endif mp_limb_t flint_mpn_sqr_basecase(mp_ptr r, mp_srcptr x, mp_size_t n) { return flint_mpn_sqr_func_tab[n](r, x); } flint-3.1.3/src/mpn_extras/sumdiff_n.c000066400000000000000000000020611461254215100177170ustar00rootroot00000000000000/* Copyright (C) 2009, 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" mp_limb_t flint_mpn_sumdiff_n(mp_ptr s, mp_ptr d, mp_srcptr x, mp_srcptr y, mp_size_t n) { mp_limb_t ret; mp_ptr t; if (n == 0) return 0; if ((s == x && d == y) || (s == y && d == x)) { t = (mp_ptr) flint_malloc(n * sizeof(mp_limb_t)); ret = mpn_sub_n(t, x, y, n); ret += 2 * mpn_add_n(s, x, y, n); flint_mpn_copyi(d, t, n); flint_free(t); return ret; } if (s == x || s == y) { ret = mpn_sub_n(d, x, y, n); ret += 2 * mpn_add_n(s, x, y, n); return ret; } ret = 2 * mpn_add_n(s, x, y, n); ret += mpn_sub_n(d, x, y, n); return ret; } flint-3.1.3/src/mpn_extras/test/000077500000000000000000000000001461254215100165615ustar00rootroot00000000000000flint-3.1.3/src/mpn_extras/test/main.c000066400000000000000000000037601461254215100176570ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-divides.c" #include "t-divrem_preinv1.c" #include "t-divrem_preinvn.c" #include "t-fmms1.c" #include "t-gcd_full.c" #include "t-mod_preinvn.c" #include "t-mul.c" #include "t-mul_n.c" #include "t-mul_basecase.c" #include "t-mul_toom22.c" #include "t-mulhigh_basecase.c" #include "t-mulhigh_normalised.c" #include "t-mulmod_2expp1.c" #include "t-mulmod_preinv1.c" #include "t-mulmod_preinvn.c" #include "t-remove_2exp.c" #include "t-remove_power.c" #include "t-sqr_basecase.c" #include "t-sqrhigh_basecase.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(flint_mpn_divides), TEST_FUNCTION(flint_mpn_divrem_preinv1), TEST_FUNCTION(flint_mpn_divrem_preinvn), TEST_FUNCTION(flint_mpn_fmms1), TEST_FUNCTION(flint_mpn_gcd_full), TEST_FUNCTION(flint_mpn_mod_preinvn), TEST_FUNCTION(flint_mpn_mul), TEST_FUNCTION(flint_mpn_mul_n), TEST_FUNCTION(flint_mpn_mul_basecase), TEST_FUNCTION(flint_mpn_mul_toom22), TEST_FUNCTION(flint_mpn_mulhigh_basecase), TEST_FUNCTION(flint_mpn_mulhigh_normalised), TEST_FUNCTION(flint_mpn_mulmod_2expp1), TEST_FUNCTION(flint_mpn_mulmod_preinv1), TEST_FUNCTION(flint_mpn_mulmod_preinvn), TEST_FUNCTION(flint_mpn_remove_2exp), TEST_FUNCTION(flint_mpn_remove_power), TEST_FUNCTION(flint_mpn_sqr_basecase), TEST_FUNCTION(flint_mpn_sqrhigh_basecase) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/mpn_extras/test/t-divides.c000066400000000000000000000056671461254215100206330ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_divides, state) { int i, result; mpz_t a, b, c, g, s; mp_ptr temp; gmp_randstate_t st; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(s); /* don't init g */ gmp_randinit_default(st); /* check if b divides a*b */ for (i = 0; i < 10000; i++) { do { mpz_urandomb(a, st, n_randint(state, 200)); } while (mpz_sgn(a) == 0); do { mpz_urandomb(b, st, n_randint(state, 200)); } while (mpz_sgn(b) == 0); do { mpz_urandomb(c, st, n_randint(state, 200)); } while (mpz_sgn(c) == 0); mpz_mul(c, a, b); g->_mp_d = flint_malloc((c->_mp_size - b->_mp_size + 1)*sizeof(mp_limb_t)); temp = flint_malloc(b->_mp_size * sizeof(mp_limb_t)); result = flint_mpn_divides(g->_mp_d, c->_mp_d, c->_mp_size, b->_mp_d, b->_mp_size, temp); g->_mp_size = c->_mp_size - b->_mp_size + 1; g->_mp_size -= (g->_mp_d[g->_mp_size - 1] == 0); result &= (mpz_cmp(g, a) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n", c, a, b); flint_free(g->_mp_d); flint_free(temp); } /* check b does not divide a*b + s for s < b */ for (i = 0; i < 10000; i++) { do { mpz_urandomb(a, st, n_randint(state, 200)); } while (mpz_sgn(a) == 0); do { mpz_urandomb(b, st, n_randint(state, 200) + 2); } while (mpz_sgn(b) == 0 || b->_mp_size == 1); do { mpz_urandomb(c, st, n_randint(state, 200)); } while (mpz_sgn(c) == 0); do { mpz_urandomb(s, st, n_randint(state, b->_mp_size)); } while (mpz_sgn(s) == 0); mpz_mul(c, a, b); mpz_add(c, c, s); g->_mp_d = flint_malloc((c->_mp_size - b->_mp_size + 1)*sizeof(mp_limb_t)); temp = flint_malloc(b->_mp_size * sizeof(mp_limb_t)); result = !flint_mpn_divides(g->_mp_d, c->_mp_d, c->_mp_size, b->_mp_d, b->_mp_size, temp); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n", c, a, b, s); flint_free(g->_mp_d); flint_free(temp); } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(s); /* don't clear g */ gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-divrem_preinv1.c000066400000000000000000000044321461254215100221230ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_divrem_preinv1, state) { int i, result; mpz_t a, a2, b, q, r, q2; gmp_randstate_t st; mp_limb_t d1, d2, inv; slong s1, s2; mpz_init(a); mpz_init(a2); mpz_init(b); mpz_init(q); mpz_init(r); gmp_randinit_default(st); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { do { mpz_rrandomb(a, st, n_randint(state, 200)); do { mpz_rrandomb(b, st, n_randint(state, 200)); } while (mpz_sgn(b) == 0); s1 = a->_mp_size; s2 = b->_mp_size; } while (s1 < s2 || s2 < 2); mpz_set(a2, a); /* normalise b */ b->_mp_d[b->_mp_size - 1] |= ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1)); d1 = b->_mp_d[b->_mp_size - 1]; d2 = b->_mp_d[b->_mp_size - 2]; mpz_fdiv_qr(q, r, a, b); inv = flint_mpn_preinv1(d1, d2); q2->_mp_d = flint_malloc((s1 - s2 + 1)*sizeof(mp_limb_t)); q2->_mp_d[s1 - s2] = flint_mpn_divrem_preinv1(q2->_mp_d, a2->_mp_d, a2->_mp_size, b->_mp_d, b->_mp_size, inv); /* normalise */ s1 -= (s2 - 1); while (s1 && q2->_mp_d[s1 - 1] == 0) s1--; q2->_mp_size = s1; q2->_mp_alloc = s1; while (s2 && a2->_mp_d[s2 - 1] == 0) s2--; a2->_mp_size = s2; result = (mpz_cmp(q, q2) == 0 && mpz_cmp(a2, r) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n", a, b, q, r, q2, a2); flint_free(q2->_mp_d); } mpz_clear(a); mpz_clear(a2); mpz_clear(b); mpz_clear(q); mpz_clear(r); /* don't clear g */ gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-divrem_preinvn.c000066400000000000000000000104161461254215100222170ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_divrem_preinvn, state) { int i, result; mpz_t a, d, q1, q2, r1, r2; gmp_randstate_t st; mp_ptr dinv; mp_size_t size, size2; flint_bitcnt_t norm; mpz_init(a); mpz_init(d); mpz_init(q1); mpz_init(r1); /* don't init r2, q2 */ gmp_randinit_default(st); /* test flint_mpn_divrem_preinvn alias r and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { size = n_randint(state, 200) + 1; size2 = n_randint(state, 200) + size; mpz_rrandomb(a, st, size2*FLINT_BITS); do { mpz_rrandomb(d, st, size*FLINT_BITS); } while (mpz_sgn(d) == 0); /* normalise */ norm = flint_clz(d->_mp_d[d->_mp_size - 1]); mpz_mul_2exp(d, d, norm); mpz_mul_2exp(a, a, norm); size2 = a->_mp_size; /* allocate space */ q2->_mp_size = size2 - size + 1; q2->_mp_d = flint_malloc(q2->_mp_size*sizeof(mp_limb_t)); /* reduce a mod d */ mpz_fdiv_qr(q1, r1, a, d); dinv = flint_malloc(size*sizeof(mp_limb_t)); flint_mpn_preinvn(dinv, d->_mp_d, size); q2->_mp_d[q2->_mp_size - 1] = flint_mpn_divrem_preinvn(q2->_mp_d, a->_mp_d, a->_mp_d, size2, d->_mp_d, size, dinv); /* normalise */ while (size && a->_mp_d[size - 1] == 0) size--; a->_mp_size = size; size2 = q2->_mp_size; while (size2 && q2->_mp_d[size2 - 1] == 0) size2--; q2->_mp_size = size2; result = (mpz_cmp(r1, a) == 0 && mpz_cmp(q1, q2) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "size = %wd\n" "size2 = %wd\n", a, d, r1, q1, q2, size, size2); flint_free(dinv); flint_free(q2->_mp_d); } /* test flint_mpn_divrem_preinvn */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { size = n_randint(state, 200) + 1; size2 = n_randint(state, 200) + size; mpz_rrandomb(a, st, size2*FLINT_BITS); do { mpz_rrandomb(d, st, size*FLINT_BITS); } while (mpz_sgn(d) == 0); /* normalise */ norm = flint_clz(d->_mp_d[d->_mp_size - 1]); mpz_mul_2exp(d, d, norm); mpz_mul_2exp(a, a, norm); size2 = a->_mp_size; /* allocate space */ q2->_mp_size = size2 - size + 1; q2->_mp_d = flint_malloc(q2->_mp_size*sizeof(mp_limb_t)); r2->_mp_size = size2; r2->_mp_d = flint_malloc(r2->_mp_size*sizeof(mp_limb_t)); /* reduce a mod d */ mpz_fdiv_qr(q1, r1, a, d); dinv = flint_malloc(size*sizeof(mp_limb_t)); flint_mpn_preinvn(dinv, d->_mp_d, size); q2->_mp_d[q2->_mp_size - 1] = flint_mpn_divrem_preinvn(q2->_mp_d, r2->_mp_d, a->_mp_d, size2, d->_mp_d, size, dinv); /* normalise */ while (size && r2->_mp_d[size - 1] == 0) size--; r2->_mp_size = size; size2 = q2->_mp_size; while (size2 && q2->_mp_d[size2 - 1] == 0) size2--; q2->_mp_size = size2; result = (mpz_cmp(r1, r2) == 0 && mpz_cmp(q1, q2) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "size = %wd\n" "size2 = %wd\n", a, d, r1, r2, q1, q2, size, size2); flint_free(dinv); flint_free(q2->_mp_d); flint_free(r2->_mp_d); } mpz_clear(a); mpz_clear(d); mpz_clear(q1); mpz_clear(r1); /* don't clear r2, q2 */ gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-fmms1.c000066400000000000000000000040171461254215100202130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "fmpz.h" TEST_FUNCTION_START(flint_mpn_fmms1, state) { slong i, j; fmpz_t X1, X2, Y, T; mp_limb_t * y, a1, * x1, a2, * x2; mp_size_t yn, n; fmpz_init(X1); fmpz_init(X2); fmpz_init(Y); fmpz_init(T); for (i = 0; i < 10000*flint_test_multiplier(); i++) { n = n_randint(state, 100) + 1; x1 = (mp_limb_t *) flint_malloc(n*sizeof(mp_limb_t)); x2 = (mp_limb_t *) flint_malloc(n*sizeof(mp_limb_t)); y = (mp_limb_t *) flint_malloc(n*sizeof(mp_limb_t)); a1 = n_randtest(state); a2 = n_randtest(state); for (j = 0; j < n; j++) { x1[j] = n_randtest(state); x2[j] = n_randtest(state); } fmpz_set_ui_array(X1, x1, n); fmpz_set_ui_array(X2, x2, n); fmpz_mul_ui(Y, X1, a1); fmpz_submul_ui(Y, X2, a2); yn = flint_mpn_fmms1(y, a1, x1, a2, x2, n); if (yn > 0) { fmpz_set_ui_array(T, y, yn); if (y[yn - 1] == 0 || !fmpz_equal(T, Y)) TEST_FUNCTION_FAIL("check positive answer, i = %wd\n", i); } else if (yn == 0) { if (!fmpz_is_zero(Y)) TEST_FUNCTION_FAIL("check zero answer, i = %wd\n", i); } else { if (fmpz_sgn(Y) >= 0 && fmpz_size(Y) <= n) TEST_FUNCTION_FAIL("check failed answer, i = %wd\n", i); } flint_free(x1); flint_free(x2); flint_free(y); } fmpz_clear(X1); fmpz_clear(X2); fmpz_clear(Y); fmpz_clear(T); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-gcd_full.c000066400000000000000000000034551461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_gcd_full, state) { int i, result; mpz_t a, b, c, g; gmp_randstate_t st; slong s1, s2; mpz_init(a); mpz_init(b); mpz_init(c); /* don't init g */ gmp_randinit_default(st); for (i = 0; i < 10000; i++) { do { mpz_urandomb(a, st, n_randint(state, 200)); } while (mpz_sgn(a) == 0); do { mpz_urandomb(b, st, n_randint(state, 200)); } while (mpz_sgn(b) == 0); do { mpz_urandomb(c, st, n_randint(state, 200)); } while (mpz_sgn(c) == 0); mpz_mul(a, a, c); mpz_mul(b, b, c); mpz_mul_2exp(a, a, n_randint(state, 200)); mpz_mul_2exp(b, b, n_randint(state, 200)); mpz_gcd(c, a, b); s1 = (mpz_sizeinbase(a, 2) - 1)/FLINT_BITS + 1; s2 = (mpz_sizeinbase(b, 2) - 1)/FLINT_BITS + 1; g->_mp_d = flint_malloc(FLINT_MIN(s1, s2)*sizeof(mp_limb_t)); g->_mp_size = flint_mpn_gcd_full(g->_mp_d, a->_mp_d, a->_mp_size, b->_mp_d, b->_mp_size); result = (mpz_cmp(g, c) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n", g, c); flint_free(g->_mp_d); } mpz_clear(a); mpz_clear(b); mpz_clear(c); /* don't clear g */ gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-mod_preinvn.c000066400000000000000000000065551461254215100215210ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_mod_preinvn, state) { int i, result; mpz_t a, d, r1, r2; gmp_randstate_t st; mp_ptr dinv; mp_size_t size, size2; flint_bitcnt_t norm; mpz_init(a); mpz_init(d); mpz_init(r1); /* don't init r2 */ gmp_randinit_default(st); /* test flint_mpn_mod_preinvn */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { size = n_randint(state, 200) + 1; size2 = n_randint(state, 200) + size; mpz_rrandomb(a, st, size2*FLINT_BITS); do { mpz_rrandomb(d, st, size*FLINT_BITS); } while (mpz_sgn(d) == 0); /* normalise */ norm = flint_clz(d->_mp_d[d->_mp_size - 1]); mpz_mul_2exp(d, d, norm); mpz_mul_2exp(a, a, norm); size2 = a->_mp_size; /* make space for r */ r2->_mp_size = size2; r2->_mp_d = flint_malloc(r2->_mp_size*sizeof(mp_limb_t)); /* reduce a mod d */ mpz_fdiv_r(r1, a, d); dinv = flint_malloc(size*sizeof(mp_limb_t)); flint_mpn_preinvn(dinv, d->_mp_d, size); flint_mpn_mod_preinvn(r2->_mp_d, a->_mp_d, size2, d->_mp_d, size, dinv); /* normalise */ while (size && r2->_mp_d[size - 1] == 0) size--; r2->_mp_size = size; result = (mpz_cmp(r1, r2) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "size = %wd\n" "size2 = %wd\n", a, d, r1, size, size2); flint_free(dinv); flint_free(r2->_mp_d); } /* test flint_mpn_mod_preinvn alias r and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { size = n_randint(state, 200) + 1; size2 = n_randint(state, 200) + size; mpz_rrandomb(a, st, size2*FLINT_BITS); do { mpz_rrandomb(d, st, size*FLINT_BITS); } while (mpz_sgn(d) == 0); /* normalise */ norm = flint_clz(d->_mp_d[d->_mp_size - 1]); mpz_mul_2exp(d, d, norm); mpz_mul_2exp(a, a, norm); size2 = a->_mp_size; /* reduce a mod d */ mpz_fdiv_r(r1, a, d); dinv = flint_malloc(size*sizeof(mp_limb_t)); flint_mpn_preinvn(dinv, d->_mp_d, size); flint_mpn_mod_preinvn(a->_mp_d, a->_mp_d, size2, d->_mp_d, size, dinv); /* normalise */ while (size && a->_mp_d[size - 1] == 0) size--; a->_mp_size = size; result = (mpz_cmp(r1, a) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "size = %wd\n" "size2 = %wd\n", a, d, r1, size, size2); flint_free(dinv); } mpz_clear(a); mpz_clear(d); mpz_clear(r1); /* don't clear r2 */ gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-mul.c000066400000000000000000000032571461254215100177720ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_mul, state) { slong iter; for (iter = 0; iter < 100000 * flint_test_multiplier(); iter++) { slong i, n, m; mp_ptr X, Y, R1, R2; mp_limb_t ret1, ret2; n = 1 + n_randint(state, 15); if (n_randint(state, 10000) == 0) n = 1 + n_randint(state, 1000); m = 1 + n_randint(state, n); X = flint_malloc(sizeof(mp_limb_t) * n); Y = flint_malloc(sizeof(mp_limb_t) * m); R1 = flint_malloc(sizeof(mp_limb_t) * (n + m)); R2 = flint_malloc(sizeof(mp_limb_t) * (n + m)); mpn_random2(X, n); mpn_random2(Y, m); for (i = 0; i < n + m; i++) R1[i] = n_randtest(state); ret1 = flint_mpn_mul(R1, X, n, Y, m); ret2 = mpn_mul(R2, X, n, Y, m); if (mpn_cmp(R1, R2, n + m) != 0 || ret1 != ret2) TEST_FUNCTION_FAIL( "n = %wd\n" "X = %{ulong*}\n" "Y = %{ulong*}\n" "R1 = %{ulong*}\n" "R2 = %{ulong*}\n", n, X, n, Y, m, R1, n + m, R2, n + m); flint_free(X); flint_free(Y); flint_free(R1); flint_free(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-mul_basecase.c000066400000000000000000000033331461254215100216130ustar00rootroot00000000000000/* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #if FLINT_HAVE_ADX TEST_FUNCTION_START(flint_mpn_mul_basecase, state) { slong ix; for (ix = 0; ix < 100000 * flint_test_multiplier(); ix++) { mp_limb_t res1[32] = {UWORD(0)}; mp_limb_t res2[32] = {UWORD(0)}; mp_limb_t ret1, ret2; mp_limb_t ap[16]; mp_limb_t bp[16]; slong alen, blen; alen = 1 + n_randint(state, 16); blen = 1 + n_randint(state, FLINT_MIN(alen, WORD(16))); mpn_random2(ap, alen); mpn_random2(bp, blen); ret1 = flint_mpn_mul_basecase(res1, ap, bp, alen, blen); ret2 = mpn_mul(res2, ap, alen, bp, blen); if (mpn_cmp(res1, res2, alen + blen) || ret1 != ret2) TEST_FUNCTION_FAIL( "ix = %wd\n" "alen = %wd\n" "blen = %wd\n" "ap = %{ulong*}\n" "bp = %{ulong*}\n" "ret1 = %wu\n" "ret2 = %wu\n" "Got: %{ulong*}\n" "Expected: %{ulong*}\n", ix, alen, blen, ap, alen, bp, blen, ret1, ret2, res1, alen + blen, res2, alen + blen); } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(flint_mpn_mul_basecase, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/mpn_extras/test/t-mul_n.c000066400000000000000000000031071461254215100203010ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_mul_n, state) { slong iter; for (iter = 0; iter < 100000 * flint_test_multiplier(); iter++) { slong i, n; mp_ptr X, Y, R1, R2; n = 1 + n_randint(state, 15); if (n_randint(state, 10000) == 0) n = 1 + n_randint(state, 1000); X = flint_malloc(sizeof(mp_limb_t) * n); Y = flint_malloc(sizeof(mp_limb_t) * n); R1 = flint_malloc(sizeof(mp_limb_t) * 2 * n); R2 = flint_malloc(sizeof(mp_limb_t) * 2 * n); mpn_random2(X, n); mpn_random2(Y, n); for (i = 0; i < 2 * n; i++) R1[i] = n_randtest(state); flint_mpn_mul_n(R1, X, Y, n); mpn_mul_n(R2, X, Y, n); if (mpn_cmp(R1, R2, 2 * n) != 0) TEST_FUNCTION_FAIL( "n = %wd\n" "X = %{ulong*}\n" "Y = %{ulong*}\n" "R1 = %{ulong*}\n" "R2 = %{ulong*}\n", n, X, n, Y, n, R1, 2 * n, R2, 2 * n); flint_free(X); flint_free(Y); flint_free(R1); flint_free(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-mul_toom22.c000066400000000000000000000031701461254215100211660ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_mul_toom22, state) { slong iter; for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { slong i, n, m; mp_ptr X, Y, R1, R2; do { n = 1 + n_randint(state, 300); m = 1 + n_randint(state, n); } while (m <= n / 2 + 2); X = flint_malloc(sizeof(mp_limb_t) * n); Y = flint_malloc(sizeof(mp_limb_t) * n); R1 = flint_malloc(sizeof(mp_limb_t) * (2 * n)); R2 = flint_malloc(sizeof(mp_limb_t) * (2 * n)); mpn_random2(X, n); mpn_random2(Y, m); for (i = 0; i < n + m; i++) R1[i] = n_randtest(state); flint_mpn_mul_toom22(R1, X, n, Y, m, NULL); mpn_mul(R2, X, n, Y, m); if (mpn_cmp(R1, R2, n + m) != 0) TEST_FUNCTION_FAIL( "n = %wd\n" "X = %{ulong*}\n" "Y = %{ulong*}\n" "R1 = %{ulong*}\n" "R2 = %{ulong*}\n", n, X, n, Y, m, R1, n + m, R2, n + m); flint_free(X); flint_free(Y); flint_free(R1); flint_free(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-mulhigh_basecase.c000066400000000000000000000051541461254215100224560ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" /* TODO: Remove this preprocessor conditional */ #if FLINT_HAVE_NATIVE_MPN_MULHIGH_BASECASE #define N_MIN 1 #define N_MAX 64 TEST_FUNCTION_START(flint_mpn_mulhigh_basecase, state) { slong ix; int result; for (ix = 0; ix < 100000 * flint_test_multiplier(); ix++) { mp_limb_t rp[N_MAX + 1]; mp_limb_t rp_upperbound[2 * N_MAX]; mp_limb_t rp_lowerbound[2 * N_MAX]; mp_limb_t borrow; mp_limb_t xp[N_MAX]; mp_limb_t yp[N_MAX]; mp_size_t n; mp_limb_t lb; n = N_MIN + n_randint(state, N_MAX - N_MIN + 1); mpn_random2(xp, N_MAX); mpn_random2(yp, N_MAX); rp[0] = flint_mpn_mulhigh_basecase(rp + 1, xp, yp, n); /* Check upper bound */ flint_mpn_mul_n(rp_upperbound, xp, yp, n); result = (mpn_cmp(rp, rp_upperbound + n - 1, n + 1) <= 0); if (!result) TEST_FUNCTION_FAIL( "rp > rp_upperbound\n" "ix = %wd\n" "n = %wd\n" "xp = %{ulong*}\n" "yp = %{ulong*}\n" "rp = %{ulong*}\n" "rp_upperbound = %{ulong*}\n", ix, n, xp, n, yp, n, rp, n + 1, rp_upperbound + n - 1, n + 1); /* Check lower bound */ lb = n + 2; memcpy(rp_lowerbound, rp_upperbound, 2 * n * sizeof(mp_limb_t)); borrow = mpn_sub_1(rp_lowerbound + n - 1, rp_lowerbound + n - 1, n + 1, lb); if (borrow) mpn_zero(rp_lowerbound, 2 * n); result = (mpn_cmp(rp, rp_lowerbound + n - 1, n + 1) >= 0); if (!result) TEST_FUNCTION_FAIL( "rp < rp_lowerbound\n" "ix = %wd\n" "n = %wd\n" "xp = %{ulong*}\n" "yp = %{ulong*}\n" "rp = %{ulong*}\n" "rp_lowerbound = %{ulong*}\n", ix, n, xp, n, yp, n, rp, n + 1, rp_lowerbound + n - 1, n + 1); } TEST_FUNCTION_END(state); } # undef N_MIN # undef N_MAX #else TEST_FUNCTION_START(flint_mpn_mulhigh_basecase, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/mpn_extras/test/t-mulhigh_normalised.c000066400000000000000000000061341461254215100230440ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" /* TODO: Remove this preprocessor conditional */ #if FLINT_HAVE_ADX # define N_MAX 64 TEST_FUNCTION_START(flint_mpn_mulhigh_normalised, state) { slong ix; int result; for (ix = 0; ix < 100000 * flint_test_multiplier(); ix++) { mp_limb_t rp_n[N_MAX + 1] = {UWORD(0)}; mp_limb_t rp_u[N_MAX + 1] = {UWORD(0)}; mp_limb_t xp[N_MAX]; mp_limb_t yp[N_MAX]; mp_size_t n; struct mp_limb_pair_t res_norm; mp_limb_t retlimb, normalised; n = 1 + n_randint(state, N_MAX); mpn_random2(xp, n); mpn_random2(yp, n); xp[n - 1] |= (UWORD(1) << (FLINT_BITS - 1)); yp[n - 1] |= (UWORD(1) << (FLINT_BITS - 1)); rp_u[0] = flint_mpn_mulhigh_basecase(rp_u + 1, xp, yp, n); res_norm = flint_mpn_mulhigh_normalised(rp_n + 1, xp, yp, n); retlimb = res_norm.m1; normalised = res_norm.m2; rp_n[0] = retlimb; result = ((rp_n[n] & (UWORD(1) << (FLINT_BITS - 1))) != UWORD(0)); if (!result) TEST_FUNCTION_FAIL( "Top bit not set in normalised result\n" "ix = %wd\n" "n = %wd\n" "xp = %{ulong*}\n" "yp = %{ulong*}\n" "rp_n = %{ulong*}\n" "rp_u = %{ulong*}\n", ix, n, xp, n, yp, n, rp_n, n + 1, rp_u, n + 1); if (normalised) { result = (mpn_lshift(rp_u, rp_u, n + 1, 1) == 0); result = result && (mpn_cmp(rp_n, rp_u, n + 1) == 0); if (!result) TEST_FUNCTION_FAIL( "rp_n != rp_u << 1 when normalised\n" "ix = %wd\n" "n = %wd\n" "xp = %{ulong*}\n" "yp = %{ulong*}\n" "rp_n = %{ulong*}\n" "rp_u = %{ulong*}\n", ix, n, xp, n, yp, n, rp_n, n + 1, rp_u, n + 1); } else { result = (mpn_cmp(rp_n, rp_u, n + 1) == 0); if (!result) TEST_FUNCTION_FAIL( "rp_n != rp_u when unnormalised\n" "ix = %wd\n" "n = %wd\n" "xp = %{ulong*}\n" "yp = %{ulong*}\n" "rp_n = %{ulong*}\n" "rp_u = %{ulong*}\n", ix, n, xp, n, yp, n, rp_n, n + 1, rp_u, n + 1); } } TEST_FUNCTION_END(state); } # undef N_MAX #else TEST_FUNCTION_START(flint_mpn_mulhigh_normalised, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/mpn_extras/test/t-mulmod_2expp1.c000066400000000000000000000127401461254215100216660ustar00rootroot00000000000000/* Copyright (C) 2009 Jason Moxham Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_mulmod_2expp1, state) { ulong xn, yn, b, zn, c, dn; gmp_randstate_t rands; int k, cc; mp_limb_t xp[10000], dp[10000], qp[10000], yp[10000]; mp_limb_t rp[10000], zp[10000], tp[10000], tb; int result = 1; gmp_randinit_default(rands); b = 1; tb = 1; tb <<= b; for ( ; b < 600; b++, tb*=2) { xn = BITS_TO_LIMBS(b); k = xn*GMP_NUMB_BITS - b; if (tb == 0 || tb > GMP_NUMB_MASK) tb=1; mpn_zero(dp, xn); mpn_com(dp, dp, xn); dp[xn-1] &= GMP_NUMB_MASK >> k; /* dp is 2^b-1 */ dn = xn; dp[xn] = mpn_add_1(dp, dp, xn, 2); if (dp[dn] != 0) dn++; /* dp is 2^b+1 */ for (c = 0; c < 20; c++) { mpn_random2(xp, xn); mpn_random2(yp, xn); xp[xn-1] &= GMP_NUMB_MASK >> k; yp[xn-1] &= GMP_NUMB_MASK >> k; mpn_mul_n(zp, xp, yp, xn); zn = xn*2; MPN_NORM(zp, zn); if (zn >= dn) mpn_tdiv_qr(qp, rp, 0, zp, zn, dp, dn); else mpn_copyi(rp, zp, dn); cc = tp[xn] = flint_mpn_mulmod_2expp1_basecase(tp, xp, yp, 0, b, qp); if (cc != 0 && dn == xn) tp[xn-1] |= tb; result = (mpn_cmp(tp, rp, dn) == 0); if (!result) TEST_FUNCTION_FAIL("b = %wd\n", b); } } b = 1; tb = 1; tb <<= b; for ( ; b < 600; b++, tb*=2) { xn = BITS_TO_LIMBS(b); k = xn*GMP_NUMB_BITS - b; if (tb == 0 || tb > GMP_NUMB_MASK) tb = 1; mpn_zero(dp, xn); mpn_com(dp, dp, xn); dp[xn-1] &= GMP_NUMB_MASK >> k; /* dp is 2^b-1 */ dn = xn; dp[xn] = mpn_add_1(dp, dp, xn, 2); if (dp[dn] != 0) dn++; /* dp is 2^b+1 */ for (c = 0; c < 20; c++) { mpn_random2(xp, xn); mpn_zero(yp, xn); /* set yp to 2^b */ xp[xn-1] &= GMP_NUMB_MASK >> k; yp[xn-1] &= GMP_NUMB_MASK >> k; yn = xn; if (tb == 1) yn++; yp[yn-1] = tb; mpn_mul(zp, yp, yn, xp, xn); zn = xn*2; MPN_NORM(zp, zn); mpn_zero(yp, xn); /* set yp to 2^b */ if (zn >= dn) mpn_tdiv_qr(qp, rp, 0, zp, zn, dp, dn); else mpn_copyi(rp, zp, dn); cc = tp[xn] = flint_mpn_mulmod_2expp1_basecase(tp, xp, yp, 1, b, qp); if (cc != 0 && dn == xn) tp[xn-1] |= tb; result = (mpn_cmp(tp, rp, dn) == 0); if (!result) TEST_FUNCTION_FAIL("b = %wd\n", b); } } b = 1; tb = 1; tb <<= b; for ( ; b < 600; b++, tb*=2) { xn = BITS_TO_LIMBS(b); k = xn*GMP_NUMB_BITS - b; if (tb == 0 || tb > GMP_NUMB_MASK) tb = 1; mpn_zero(dp, xn); mpn_com(dp, dp, xn); dp[xn-1] &= GMP_NUMB_MASK >> k; /* dp is 2^b-1 */ dn = xn; dp[xn] = mpn_add_1(dp, dp, xn, 2); if (dp[dn] != 0) dn++; /* dp is 2^b+1 */ for (c = 0; c < 20; c++) { mpn_random2(xp, xn); mpn_zero(yp, xn); /* set yp to 2^b */ xp[xn-1] &= GMP_NUMB_MASK >> k; yp[xn-1] &= GMP_NUMB_MASK >> k; yn = xn; if (tb == 1) yn++; yp[yn-1] = tb; mpn_mul(zp, yp, yn, xp, xn); zn = xn*2; MPN_NORM(zp, zn); mpn_zero(yp, xn); /* set yp to 2^b */ if (zn >= dn) mpn_tdiv_qr(qp, rp, 0, zp, zn, dp, dn); else mpn_copyi(rp, zp, dn); cc = tp[xn] = flint_mpn_mulmod_2expp1_basecase(tp, yp, xp, 2, b, qp); if (cc != 0 && dn == xn) tp[xn-1] |= tb; result = (mpn_cmp(tp, rp, dn) == 0); if (!result) TEST_FUNCTION_FAIL("b = %wd\n", b); } } rp[0] = 1; mpn_zero(rp + 1, 1000); b = 1; tb = 1; tb <<= b; for ( ; b < 600; b++, tb*=2) { xn = BITS_TO_LIMBS(b); k = xn*GMP_NUMB_BITS - b; if (tb == 0 || tb > GMP_NUMB_MASK) tb = 1; mpn_zero(dp, xn); mpn_com(dp, dp, xn); dp[xn-1] &= GMP_NUMB_MASK >> k; /* dp is 2^b-1 */ dn = xn; dp[xn] = mpn_add_1(dp, dp, xn, 2); if (dp[dn] != 0) dn++; /* dp is 2^b+1 */ for (c = 0; c < 1; c++) { mpn_zero(xp, xn); mpn_zero(yp, xn); /* set xp, yp to 2^b */ xp[xn-1] &= GMP_NUMB_MASK >> k; yp[xn-1] &= GMP_NUMB_MASK >> k; cc = tp[xn] = flint_mpn_mulmod_2expp1_basecase(tp, yp, xp, 3, b, qp); if (cc != 0 && dn == xn) tp[xn-1] |= tb; result = (mpn_cmp(tp, rp, dn) == 0); if (!result) TEST_FUNCTION_FAIL("b = %wd\n", b); } } gmp_randclear(rands); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-mulmod_preinv1.c000066400000000000000000000043301461254215100221270ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_mulmod_preinv1, state) { int i, result; mpz_t a, b, d, r1, r2; gmp_randstate_t st; mp_limb_t d1, d2, dinv; mp_size_t size; flint_bitcnt_t norm; mpz_init(a); mpz_init(b); mpz_init(d); mpz_init(r1); /* don't init r2 */ gmp_randinit_default(st); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { size = n_randint(state, 200) + 2; mpz_rrandomb(a, st, size*FLINT_BITS); mpz_rrandomb(b, st, size*FLINT_BITS); do { mpz_rrandomb(d, st, size*FLINT_BITS); } while (mpz_sgn(d) == 0); /* reduce a, b mod d */ mpz_fdiv_r(a, a, d); mpz_fdiv_r(b, b, d); mpz_mul(r1, a, b); mpz_fdiv_r(r1, r1, d); /* normalise */ norm = flint_clz(d->_mp_d[d->_mp_size - 1]); mpz_mul_2exp(a, a, norm); mpz_mul_2exp(b, b, norm); mpz_mul_2exp(d, d, norm); d1 = d->_mp_d[size - 1]; d2 = d->_mp_d[size - 2]; dinv = flint_mpn_preinv1(d1, d2); r2->_mp_d = flint_malloc(size*sizeof(mp_limb_t)); flint_mpn_mulmod_preinv1(r2->_mp_d, a->_mp_d, b->_mp_d, size, d->_mp_d, dinv, norm); /* normalise */ while (size && r2->_mp_d[size - 1] == 0) size--; r2->_mp_size = size; r2->_mp_alloc = size; result = (mpz_cmp(r1, r2) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n", a, b, d, r1, r2); flint_free(r2->_mp_d); } mpz_clear(a); mpz_clear(b); mpz_clear(d); mpz_clear(r1); /* don't init r2 */ gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-mulmod_preinvn.c000066400000000000000000000047121461254215100222300ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_mulmod_preinvn, state) { int i, result; mpz_t a, b, d, r1, r2; gmp_randstate_t st; mp_ptr dinv; mp_size_t size, size_d; flint_bitcnt_t norm; mpz_init(a); mpz_init(b); mpz_init(d); mpz_init(r1); /* don't init r2 */ gmp_randinit_default(st); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { size = n_randint(state, 200) + 1; mpz_rrandomb(a, st, size); mpz_rrandomb(b, st, size); do { mpz_rrandomb(d, st, size); } while (mpz_sgn(d) == 0); size_d = d->_mp_size; /* reduce a, b mod d */ mpz_fdiv_r(a, a, d); mpz_fdiv_r(b, b, d); mpz_mul(r1, a, b); mpz_fdiv_r(r1, r1, d); /* normalise */ norm = flint_clz(d->_mp_d[size_d - 1]); mpz_mul_2exp(a, a, norm); mpz_mul_2exp(b, b, norm); mpz_mul_2exp(d, d, norm); dinv = flint_malloc(size_d*sizeof(mp_limb_t)); flint_mpn_preinvn(dinv, d->_mp_d, size_d); r2->_mp_d = flint_malloc(size_d*sizeof(mp_limb_t)); flint_mpn_mulmod_preinvn(r2->_mp_d, a->_mp_d, b->_mp_d, size_d, d->_mp_d, dinv, norm); /* normalise */ r2->_mp_alloc = size_d; while (size_d && r2->_mp_d[size_d - 1] == 0) size_d--; r2->_mp_size = size_d; mpz_div_2exp(r2, r2, norm); mpz_div_2exp(a, a, norm); mpz_div_2exp(b, b, norm); mpz_div_2exp(d, d, norm); result = (mpz_cmp(r1, r2) == 0); if (!result) TEST_FUNCTION_FAIL( "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "%{mpz}\n" "size_d = %wd\n", a, b, d, r1, r2, size_d); if (r2->_mp_alloc) flint_free(r2->_mp_d); flint_free(dinv); } mpz_clear(a); mpz_clear(b); mpz_clear(d); mpz_clear(r1); /* don't init r2 */ gmp_randclear(st); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-remove_2exp.c000066400000000000000000000021541461254215100214230ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_remove_2exp, state) { int zero, nonzero; flint_bitcnt_t check; mpz_t a; mpz_t b; mpz_init(a); mpz_init(b); for (zero=0; zero<300; zero++) { for (nonzero=0; nonzero<300; nonzero++) { flint_mpz_set_ui(a, 1); mpz_setbit(a, nonzero); mpz_set(b, a); mpz_mul_2exp(a, a, zero); a->_mp_size = flint_mpn_remove_2exp(a->_mp_d, a->_mp_size, &check); if (check != zero || mpz_cmp(a,b)) TEST_FUNCTION_FAIL("%d %d \n", zero, nonzero); } } mpz_clear(a); mpz_clear(b); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-remove_power.c000066400000000000000000000032561461254215100217050ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "mpn_extras.h" TEST_FUNCTION_START(flint_mpn_remove_power, state) { int dp[] = {3, 10, 7429, 0}; int * dpp = dp; int d = dp[0]; do { int i, j; ulong exp, exact; mpz_t a, a2, b, c; mpz_init(a); mpz_init(a2); mpz_init(b); mpz_init(c); for (i=0; i<100; i++) { for (j=1; j<100; j++) { exact = i / j; flint_mpz_set_ui(a, d); flint_mpz_pow_ui(a, a, i); mpz_set(a2, a); flint_mpz_set_ui(b, d); flint_mpz_pow_ui(b, b, j); a->_mp_size = flint_mpn_remove_power_ascending(a->_mp_d, a->_mp_size, b->_mp_d, b->_mp_size, &exp); flint_mpz_pow_ui(b, b, exact); mpz_tdiv_q(c, a2, b); if (exp != i/j || mpz_cmp(a, c)) { gmp_printf("%d^%d / %d^%d\n", d, i, d, j); fflush(stdout); flint_abort(); } } } mpz_clear(a); mpz_clear(a2); mpz_clear(b); mpz_clear(c); dpp++; d = *dpp; } while (d); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpn_extras/test/t-sqr_basecase.c000066400000000000000000000027731461254215100216320ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #if FLINT_HAVE_ADX # define N_MAX FLINT_MPN_SQR_FUNC_TAB_WIDTH TEST_FUNCTION_START(flint_mpn_sqr_basecase, state) { slong ix; for (ix = 0; ix < 100000 * flint_test_multiplier(); ix++) { mp_limb_t res1[2 * N_MAX] = {UWORD(0)}; mp_limb_t res2[2 * N_MAX] = {UWORD(0)}; mp_limb_t ret1; mp_limb_t ap[N_MAX]; slong alen; alen = 1 + n_randint(state, N_MAX); mpn_random2(ap, alen); ret1 = flint_mpn_sqr(res1, ap, alen); mpn_sqr(res2, ap, alen); if (mpn_cmp(res1, res2, 2 * alen) || ret1 != res1[2 * alen - 1]) TEST_FUNCTION_FAIL( "ix = %wd\n" "alen = %wd\n" "ap = %{ulong*}\n" "ret1 = %wu\n" "Got: %{ulong*}\n" "Expected: %{ulong*}\n", ix, alen, ap, alen, ret1, res1, 2 * alen, res2, 2 * alen); } TEST_FUNCTION_END(state); } # undef N_MAX #else TEST_FUNCTION_START(flint_mpn_sqr_basecase, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/mpn_extras/test/t-sqrhigh_basecase.c000066400000000000000000000031231461254215100224600ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" /* TODO: Remove this preprocessor conditional */ #if FLINT_HAVE_NATIVE_MPN_SQRHIGH_BASECASE # define N_MIN 1 # define N_MAX 64 TEST_FUNCTION_START(flint_mpn_sqrhigh_basecase, state) { slong ix; int result; for (ix = 0; ix < 100000 * flint_test_multiplier(); ix++) { mp_limb_t rp1[N_MAX + 1]; mp_limb_t rp2[N_MAX + 1]; mp_limb_t xp[N_MAX]; mp_size_t n; n = N_MIN + n_randint(state, N_MAX - N_MIN + 1); mpn_random2(xp, n); rp1[0] = flint_mpn_mulhigh_basecase(rp1 + 1, xp, xp, n); rp2[0] = flint_mpn_sqrhigh_basecase(rp2 + 1, xp, n); result = (mpn_cmp(rp1, rp2, n + 1) == 0); if (!result) TEST_FUNCTION_FAIL( "Wrong result!\n" "ix = %wd\n" "n = %wd\n" "xp = %{ulong*}\n" "Expected: %{ulong*}\n" "Got: %{ulong*}\n", ix, n, xp, n, rp1, n + 1, rp2, n + 1); } TEST_FUNCTION_END(state); } # undef N_MIN # undef N_MAX #else TEST_FUNCTION_START(flint_mpn_sqrhigh_basecase, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/mpoly.h000066400000000000000000001322411461254215100147360ustar00rootroot00000000000000/* Copyright (C) 2016-2017 William Hart Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef MPOLY_H #define MPOLY_H #ifdef MPOLY_INLINES_C #define MPOLY_INLINE #else #define MPOLY_INLINE static inline #endif #include #include "mpoly_types.h" #ifdef __cplusplus extern "C" { #endif /* choose m so that (m + 1)/(n - m) ~= la/lb, i.e. m = (n*la - lb)/(la + lb) */ FLINT_FORCE_INLINE slong mpoly_divide_threads(slong n, double la, double lb) { double m_double = (n*la - lb)/(la + lb); slong m = m_double + (2*m_double > n ? -0.5 : 0.5); /* input must satisfy */ FLINT_ASSERT(n > 0); if (m <= 0) m = 0; if (m >= n - 1) m = n - 1; /* output must satisfy */ FLINT_ASSERT(m >= 0); FLINT_ASSERT(m < n); return m; } /* context *******************************************************************/ void mpoly_ctx_init(mpoly_ctx_t ctx, slong nvars, const ordering_t ord); void mpoly_ctx_init_rand(mpoly_ctx_t mctx, flint_rand_t state, slong max_nvars); void mpoly_monomial_randbits_fmpz(fmpz * exp, flint_rand_t state, flint_bitcnt_t exp_bits, const mpoly_ctx_t mctx); void mpoly_ctx_clear(mpoly_ctx_t mctx); /* number of words used by an exponent vector packed into "bits" bits: we must have either (mp) bits > FLINT_BITS and bits % FLINT_BITS == 0, or (sp) MPOLY_MIN_BITS <= bits <= FLINT_BITS */ FLINT_FORCE_INLINE slong mpoly_words_per_exp_sp(flint_bitcnt_t bits, const mpoly_ctx_t mctx) { FLINT_ASSERT(0 < bits); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(mctx->lut_words_per_exp[bits - 1] == (mctx->nfields - 1)/(FLINT_BITS/bits) + 1); return mctx->lut_words_per_exp[bits - 1]; } FLINT_FORCE_INLINE slong mpoly_words_per_exp_mp(flint_bitcnt_t bits, const mpoly_ctx_t mctx) { FLINT_ASSERT(bits % FLINT_BITS == 0); return bits/FLINT_BITS*mctx->nfields; } FLINT_FORCE_INLINE slong mpoly_words_per_exp(flint_bitcnt_t bits, const mpoly_ctx_t mctx) { if (bits <= FLINT_BITS) return mpoly_words_per_exp_sp(bits, mctx); else return mpoly_words_per_exp_mp(bits, mctx); } /* If "bits" is simply the number of bits needed to pack an exponent vector, possibly upgrade it so that it is either (mp) a multiple of FLINT_BITS in the mp case, or (sp) as big as possible without increasing words_per_exp in the sp case The upgrade in (mp) is manditory, while the upgrade in (sp) is simply nice. */ FLINT_FORCE_INLINE flint_bitcnt_t mpoly_fix_bits(flint_bitcnt_t bits, const mpoly_ctx_t mctx) { FLINT_ASSERT(bits > 0); if (bits <= FLINT_BITS) return mctx->lut_fix_bits[bits - 1]; else return (bits + FLINT_BITS - 1)/FLINT_BITS*FLINT_BITS; } /* heaps *********************************************************************/ typedef struct mpoly_heap_t { ulong i; ulong j; struct mpoly_heap_t * next; } mpoly_heap_t; typedef struct mpoly_nheap_t { ulong i; ulong j; struct mpoly_nheap_t * next; slong p; } mpoly_nheap_t; typedef struct mpoly_heap1_s { ulong exp; void * next; } mpoly_heap1_s; typedef struct mpoly_heap_s { ulong * exp; void * next; } mpoly_heap_s; /* trees *********************************************************************/ /* red-black with ui keys */ typedef struct { ulong key; slong up; slong left; slong right; int color; } mpoly_rbnode_ui_struct; typedef struct { slong length; mpoly_rbnode_ui_struct * nodes; slong node_alloc; char * data; slong data_alloc; slong data_size; } mpoly_rbtree_ui_struct; typedef mpoly_rbtree_ui_struct mpoly_rbtree_ui_t[1]; void mpoly_rbtree_ui_init(mpoly_rbtree_ui_t T, slong data_size); void mpoly_rbtree_ui_clear(mpoly_rbtree_ui_t T); void * mpoly_rbtree_ui_lookup(mpoly_rbtree_ui_t T, int * its_new, ulong key); FLINT_FORCE_INLINE slong mpoly_rbtree_ui_head(const mpoly_rbtree_ui_t T) { FLINT_ASSERT(T->nodes[1].left >= 0 || T->length < 1); return T->nodes[1].left; } /* red-black with fmpz keys */ typedef struct { fmpz_t key; slong up; slong left; slong right; int color; } mpoly_rbnode_fmpz_struct; typedef struct { slong length; mpoly_rbnode_fmpz_struct * nodes; slong node_alloc; char * data; slong data_alloc; slong data_size; } mpoly_rbtree_fmpz_struct; typedef mpoly_rbtree_fmpz_struct mpoly_rbtree_fmpz_t[1]; void mpoly_rbtree_fmpz_init(mpoly_rbtree_fmpz_t T, slong data_size); void mpoly_rbtree_fmpz_clear(mpoly_rbtree_fmpz_t T); void * mpoly_rbtree_fmpz_lookup(mpoly_rbtree_fmpz_t T, int * its_new, const fmpz_t key); FLINT_FORCE_INLINE slong mpoly_rbtree_fmpz_head(const mpoly_rbtree_fmpz_t T) { FLINT_ASSERT(T->nodes[1].left >= 0 || T->length < 1); return T->nodes[1].left; } /* Orderings *****************************************************************/ MPOLY_INLINE ordering_t mpoly_ordering_randtest(flint_rand_t state) { return (ordering_t) n_randint(state, MPOLY_NUM_ORDERINGS); } MPOLY_INLINE int mpoly_ordering_isdeg(const mpoly_ctx_t mctx) { return mctx->ord == ORD_DEGLEX || mctx->ord == ORD_DEGREVLEX; } MPOLY_INLINE int mpoly_ordering_isrev(const mpoly_ctx_t mctx) { return mctx->ord == ORD_DEGREVLEX; } void mpoly_ordering_print(ordering_t ord); /* Monomials ****************************************************************/ FLINT_FORCE_INLINE void mpoly_monomial_zero(ulong * exp_ptr, slong N) { slong i; for (i = 0; i < N; i++) exp_ptr[i] = 0; } FLINT_FORCE_INLINE void mpoly_monomial_add(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp_ptr[i] = exp2[i] + exp3[i]; } FLINT_FORCE_INLINE void mpoly_monomial_add_mp(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) { mpn_add_n(exp_ptr, exp2, exp3, N); } FLINT_FORCE_INLINE void mpoly_monomial_sub(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp_ptr[i] = exp2[i] - exp3[i]; } FLINT_FORCE_INLINE void mpoly_monomial_sub_mp(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N) { mpn_sub_n(exp_ptr, exp2, exp3, N); } FLINT_FORCE_INLINE void mpoly_monomial_madd(ulong * exp1, const ulong * exp2, ulong scalar, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp1[i] = exp2[i] + scalar*exp3[i]; } FLINT_FORCE_INLINE void mpoly_monomial_madd_mp(ulong * exp1, const ulong * exp2, ulong scalar, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp1[i] = exp2[i]; mpn_addmul_1(exp1, exp3, N, scalar); } FLINT_FORCE_INLINE void mpoly_monomial_madd_inplace_mp(ulong * exp12, ulong scalar, const ulong * exp3, slong N) { mpn_addmul_1(exp12, exp3, N, scalar); } FLINT_FORCE_INLINE void mpoly_monomial_msub(ulong * exp1, const ulong * exp2, ulong scalar, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp1[i] = exp2[i] - scalar*exp3[i]; } FLINT_FORCE_INLINE void mpoly_monomial_msub_mp(ulong * exp1, const ulong * exp2, ulong scalar, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp1[i] = exp2[i]; FLINT_ASSERT(N > 0); mpn_submul_1(exp1, exp3, N, scalar); } FLINT_FORCE_INLINE void mpoly_monomial_msub_ui_array(ulong * exp1, const ulong * exp2, const ulong * scalar, slong scalar_limbs, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp1[i] = exp2[i]; FLINT_ASSERT(scalar_limbs <= N); for (i = 0; i < scalar_limbs; i++) { FLINT_ASSERT(N > i); mpn_submul_1(exp1 + i, exp3, N - i, scalar[i]); } } FLINT_FORCE_INLINE void mpoly_monomial_madd_ui_array(ulong * exp1, const ulong * exp2, const ulong * scalar, slong scalar_limbs, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp1[i] = exp2[i]; FLINT_ASSERT(scalar_limbs <= N); for (i = 0; i < scalar_limbs; i++) mpn_addmul_1(exp1 + i, exp3, N - i, scalar[i]); } FLINT_FORCE_INLINE void mpoly_monomial_madd_fmpz(ulong * exp1, const ulong * exp2, const fmpz_t scalar, const ulong * exp3, slong N) { if (COEFF_IS_MPZ(*scalar)) { __mpz_struct * mpz = COEFF_TO_PTR(*scalar); mpoly_monomial_madd_ui_array(exp1, exp2, mpz->_mp_d, mpz->_mp_size, exp3, N); } else { mpoly_monomial_madd_mp(exp1, exp2, *scalar, exp3, N); } } /* mask with high bit set in each field of exponent vector */ FLINT_FORCE_INLINE ulong mpoly_overflow_mask_sp(flint_bitcnt_t bits) { flint_bitcnt_t i; ulong mask = 0; FLINT_ASSERT(bits <= FLINT_BITS); mask = (UWORD(1) << (bits - 1)); for (i = bits; i < FLINT_BITS; i += bits) mask = (mask << bits) + (UWORD(1) << (bits - 1)); return mask; } FLINT_FORCE_INLINE ulong mpoly_monomial_max1(ulong exp2, ulong exp3, flint_bitcnt_t bits, ulong mask) { ulong s, m, exp1; s = mask + exp2 - exp3; m = mask & s; m = m - (m >> (bits - 1)); exp1 = exp3 + (s & m); return exp1; } FLINT_FORCE_INLINE void mpoly_monomial_max(ulong * exp1, const ulong * exp2, const ulong * exp3, flint_bitcnt_t bits, slong N, ulong mask) { ulong i, s, m; for (i = 0; i < N; i++) { s = mask + exp2[i] - exp3[i]; m = mask & s; m = m - (m >> (bits - 1)); exp1[i] = exp3[i] + (s & m); } } FLINT_FORCE_INLINE ulong mpoly_monomial_min1(ulong exp2, ulong exp3, flint_bitcnt_t bits, ulong mask) { ulong s, m, exp1; s = mask + exp2 - exp3; m = mask & s; m = m - (m >> (bits - 1)); exp1 = exp2 - (s & m); return exp1; } FLINT_FORCE_INLINE void mpoly_monomial_min(ulong * exp1, const ulong * exp2, const ulong * exp3, flint_bitcnt_t bits, slong N, ulong mask) { ulong i, s, m; for (i = 0; i < N; i++) { s = mask + exp2[i] - exp3[i]; m = mask & s; m = m - (m >> (bits - 1)); exp1[i] = exp2[i] - (s & m); } } FLINT_FORCE_INLINE void mpoly_monomial_max_mp(ulong * exp1, const ulong * exp2, const ulong * exp3, flint_bitcnt_t bits, slong N) { slong i, j; for (i = 0; i < N; i += bits/FLINT_BITS) { const ulong * t = exp2; for (j = bits/FLINT_BITS - 1; j >= 0; j--) { if (exp3[i + j] != exp2[i + j]) { if (exp3[i + j] > exp2[i + j]) t = exp3; break; } } for (j = 0; j < bits/FLINT_BITS; j++) { exp1[i + j] = t[i + j]; } } } FLINT_FORCE_INLINE void mpoly_monomial_min_mp(ulong * exp1, const ulong * exp2, const ulong * exp3, flint_bitcnt_t bits, slong N) { slong i, j; for (i = 0; i < N; i += bits/FLINT_BITS) { const ulong * t = exp2; for (j = bits/FLINT_BITS - 1; j >= 0; j--) { if (exp3[i + j] != exp2[i + j]) { if (exp3[i + j] < exp2[i + j]) t = exp3; break; } } for (j = 0; j < bits/FLINT_BITS; j++) { exp1[i + j] = t[i + j]; } } } FLINT_FORCE_INLINE int mpoly_monomial_overflows(ulong * exp2, slong N, ulong mask) { slong i; for (i = 0; i < N; i++) { if ((exp2[i] & mask) != 0) return 1; } return 0; } FLINT_FORCE_INLINE int mpoly_monomial_overflows_mp(ulong * exp_ptr, slong N, flint_bitcnt_t bits) { slong i = bits/FLINT_BITS - 1; do { if ((slong)(exp_ptr[i]) < 0) return 1; i += bits/FLINT_BITS; } while (i < N); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_overflows1(ulong exp, ulong mask) { return (exp & mask) != 0; } FLINT_FORCE_INLINE int mpoly_monomial_divides(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N, ulong mask) { slong i; for (i = 0; i < N; i++) { exp_ptr[i] = exp2[i] - exp3[i]; if ((exp_ptr[i] & mask) != 0) return 0; } return 1; } FLINT_FORCE_INLINE int mpoly_monomial_halves(ulong * exp_ptr, const ulong * exp2, slong N, ulong mask) { slong i; for (i = 0; i < N; i++) { if (exp2[i] & 1) return 0; exp_ptr[i] = exp2[i] >> 1; if (exp_ptr[i] & mask) return 0; } return 1; } FLINT_FORCE_INLINE int mpoly_monomial_divides_mp(ulong * exp_ptr, const ulong * exp2, const ulong * exp3, slong N, flint_bitcnt_t bits) { slong i; mpn_sub_n(exp_ptr, exp2, exp3, N); i = bits/FLINT_BITS - 1; do { if ((slong)(exp_ptr[i]) < 0) return 0; i += bits/FLINT_BITS; } while (i < N); return 1; } FLINT_FORCE_INLINE int mpoly_monomial_halves_mp(ulong * exp_ptr, const ulong * exp2, slong N, flint_bitcnt_t bits) { slong i; ulong bw; bw = mpn_rshift(exp_ptr, exp2, N, 1); if (bw != 0) return 0; i = bits/FLINT_BITS - 1; do { if ((slong)(exp_ptr[i]) < 0) return 0; i += bits/FLINT_BITS; } while (i < N); return 1; } FLINT_FORCE_INLINE int mpoly_monomial_divides_test(const ulong * exp2, const ulong * exp3, slong N, ulong mask) { slong i; for (i = 0; i < N; i++) if (((exp2[i] - exp3[i]) & mask) != 0) return 0; return 1; } FLINT_FORCE_INLINE int mpoly_monomial_divides_mp_test(const ulong * exp2, const ulong * exp3, slong N, flint_bitcnt_t bits) { slong i, j; i = 0; do { for (j = bits/FLINT_BITS - 1; j >= 0; j--) { if (exp2[i + j] > exp3[i + j]) break; if (exp2[i + j] < exp3[i + j]) return 0; } i += bits/FLINT_BITS; } while (i < N); return 1; } FLINT_FORCE_INLINE int mpoly_monomial_divides1(ulong * exp_ptr, const ulong exp2, const ulong exp3, ulong mask) { (*exp_ptr) = exp2 - exp3; if (((exp2 - exp3) & mask) != 0) return 0; return 1; } FLINT_FORCE_INLINE int mpoly_monomial_halves1(ulong * exp_ptr, const ulong exp2, ulong mask) { if (exp2 & 1) return 0; (*exp_ptr) = exp2 >> 1; if (((exp2 >> 1) & mask) != 0) return 0; return 1; } FLINT_FORCE_INLINE void mpoly_monomial_set(ulong * exp2, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp2[i] = exp3[i]; } FLINT_FORCE_INLINE void mpoly_monomial_set_extra(ulong * exp2, const ulong * exp3, slong N, slong offset, ulong extra) { slong i; for (i = 0; i < N; i++) { exp2[i] = exp3[i] + (i == offset ? extra : 0); } } FLINT_FORCE_INLINE void mpoly_copy_monomials(ulong * exp1, const ulong * exp2, slong len, slong N) { if (len > 0) memcpy(exp1, exp2, N*len*sizeof(ulong)); } FLINT_FORCE_INLINE void mpoly_monomial_swap(ulong * exp2, ulong * exp3, slong N) { slong i; ulong t; for (i = 0; i < N; i++) { t = exp2[i]; exp2[i] = exp3[i]; exp3[i] = t; } } FLINT_FORCE_INLINE void mpoly_monomial_mul_ui(ulong * exp2, const ulong * exp3, slong N, ulong c) { slong i; for (i = 0; i < N; i++) exp2[i] = exp3[i]*c; } FLINT_FORCE_INLINE void mpoly_monomial_mul_ui_mp(ulong * exp2, const ulong * exp3, slong N, ulong c) { FLINT_ASSERT(N > 0); mpn_mul_1(exp2, exp3, N, c); } void mpoly_monomial_mul_fmpz(ulong * exp2, const ulong * exp3, slong N, const fmpz_t c); FLINT_FORCE_INLINE int mpoly_monomial_is_zero(const ulong * exp, slong N) { slong i; for (i = 0; i < N; i++) { if (exp[i] != 0) return 0; } return 1; } FLINT_FORCE_INLINE int mpoly_monomial_equal(const ulong * exp2, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) { if (exp2[i] != exp3[i]) return 0; } return 1; } FLINT_FORCE_INLINE int mpoly_monomial_equal_extra(const ulong * exp2, const ulong * exp3, slong N, slong offset, ulong extra) { slong i; for (i = 0; i < N; i++) { ulong e3 = exp3[i] + ((i == offset) ? extra : 0); if (exp2[i] != e3) return 0; } return 1; } FLINT_FORCE_INLINE int mpoly_monomial_cmp1(ulong a, ulong b, ulong cmpmask) { if ((a^cmpmask) != (b^cmpmask)) { if ((a^cmpmask) > (b^cmpmask)) return 1; else return -1; } return 0; } FLINT_FORCE_INLINE int mpoly_monomial_gt1(ulong a, ulong b, ulong cmpmask) { return (a^cmpmask) > (b^cmpmask); } FLINT_FORCE_INLINE int mpoly_monomial_ge1(ulong a, ulong b, ulong cmpmask) { return (a^cmpmask) >= (b^cmpmask); } FLINT_FORCE_INLINE int mpoly_monomial_lt(const ulong * exp3, const ulong * exp2, slong N, const ulong * cmpmask) { slong i = N - 1; do { if (exp2[i] != exp3[i]) { return (exp3[i]^cmpmask[i]) < (exp2[i]^cmpmask[i]); } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_gt(const ulong * exp3, const ulong * exp2, slong N, const ulong * cmpmask) { slong i = N - 1; do { if (exp2[i] != exp3[i]) { return (exp3[i]^cmpmask[i]) > (exp2[i]^cmpmask[i]); } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_lt_nomask(const ulong * exp2, const ulong * exp3, slong N) { slong i = N - 1; do { if (exp2[i] != exp3[i]) { return exp2[i] < exp3[i]; } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_gt_nomask(const ulong * exp2, const ulong * exp3, slong N) { slong i = N - 1; do { if (exp2[i] != exp3[i]) { return exp2[i] > exp3[i]; } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_lt_nomask_extra(const ulong * exp2, const ulong * exp3, slong N, slong offset, ulong extra) { slong i = N - 1; do { ulong e3 = exp3[i] + ((i == offset) ? extra : 0); if (exp2[i] != e3) { return exp2[i] < e3; } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_gt_nomask_extra(const ulong * exp2, const ulong * exp3, slong N, slong offset, ulong extra) { slong i = N - 1; do { ulong e3 = exp3[i] + ((i == offset) ? extra : 0); if (exp2[i] != e3) { return exp2[i] > e3; } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_cmp(const ulong * exp2, const ulong * exp3, slong N, const ulong * cmpmask) { slong i = N - 1; do { if (exp2[i] != exp3[i]) { if ((exp2[i]^cmpmask[i]) > (exp3[i]^cmpmask[i])) return 1; else return -1; } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_cmp_nomask(const ulong * exp2, const ulong * exp3, slong N) { slong i = N - 1; do { if (exp2[i] != exp3[i]) { if (exp2[i] > exp3[i]) return 1; else return -1; } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_cmp_nomask_extra(const ulong * exp2, const ulong * exp3, slong N, slong offset, ulong extra) { slong i = N - 1; do { ulong e3 = exp3[i] + ((i == offset) ? extra : 0); if (exp2[i] != e3) { if (exp2[i] > e3) return 1; else return -1; } } while (--i >= 0); return 0; } FLINT_FORCE_INLINE int mpoly_monomial_divides_tight(slong e1, slong e2, slong * prods, slong num) { slong j; for (j = 0; j < num; j++) { slong d1 = (e1 % prods[j + 1])/prods[j]; slong d2 = (e2 % prods[j + 1])/prods[j]; if (d1 < d2) return 0; } return 1; } MPOLY_INLINE void mpoly_max_degrees_tight(slong * max_exp, ulong * exps, slong len, slong * prods, slong num) { slong i, j; for (j = 0; j < num; j++) max_exp[j] = 0; for (i = 0; i < len; i++) { for (j = 0; j < num; j++) { slong d1 = (exps[i] % prods[j + 1])/prods[j]; if (d1 > max_exp[j]) max_exp[j] = d1; } } } /* ceiling(log_4(x)) - 1 */ FLINT_FORCE_INLINE slong mpoly_geobucket_clog4(slong x) { if (x <= 4) return 0; /* FLINT_BIT_COUNT returns unsigned int. Signed division is not defined. Do the calculation with unsigned ints and then convert to slong. */ return (slong)((FLINT_BIT_COUNT(x - 1) - UWORD(1))/(UWORD(2))); } /* single-limb packings ******************************************************/ FLINT_FORCE_INLINE ulong pack_exp2(ulong e0, ulong e1) { return (e0 << (1*(FLINT_BITS/2))) + (e1 << (0*(FLINT_BITS/2))); } FLINT_FORCE_INLINE ulong pack_exp3(ulong e0, ulong e1, ulong e2) { return (e0 << (2*(FLINT_BITS/3))) + (e1 << (1*(FLINT_BITS/3))) + (e2 << (0*(FLINT_BITS/3))); } FLINT_FORCE_INLINE ulong extract_exp(ulong e, int idx, int nvars) { return (e >> (idx*(FLINT_BITS/nvars))) & ((-UWORD(1)) >> (FLINT_BITS - FLINT_BITS/nvars)); } ulong _mpoly_bidegree(const ulong * Aexps, flint_bitcnt_t Abits, const mpoly_ctx_t mctx); /* generators ****************************************************************/ void mpoly_gen_fields_ui(ulong * exp, slong var, const mpoly_ctx_t mctx); void mpoly_gen_fields_fmpz(fmpz * exp, slong var, const mpoly_ctx_t mctx); flint_bitcnt_t mpoly_gen_bits_required(slong var, const mpoly_ctx_t mctx); /* return the index in the fields where the generator of index v is stored */ FLINT_FORCE_INLINE slong mpoly_gen_index(slong v, const mpoly_ctx_t mctx) { return mctx->rev ? v : mctx->nvars - 1 - v; } void mpoly_gen_offset_shift_sp(slong * offset, slong * shift, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_gen_monomial_offset_shift_sp(ulong * mexp, slong * offset, slong * shift, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_gen_monomial_sp(ulong * oneexp, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); slong mpoly_gen_offset_mp(slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); slong mpoly_gen_monomial_offset_mp(ulong * mexp, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_compose_mat_gen(fmpz_mat_t M, const slong * c, const mpoly_ctx_t mctxB, const mpoly_ctx_t mctxAC); void mpoly_compose_mat_fill_column(fmpz_mat_t M, const ulong * Cexp, flint_bitcnt_t Cbits, slong Bvar, const mpoly_ctx_t mctxB, const mpoly_ctx_t mctxAC); /* Monomial arrays ***********************************************************/ void mpoly_get_cmpmask(ulong * cmpmask, slong N, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_get_ovfmask(ulong * ovfmask, slong N, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int mpoly_monomials_cmp(const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong length, const mpoly_ctx_t mctx); flint_bitcnt_t mpoly_exp_bits_required_ui(const ulong * user_exp, const mpoly_ctx_t mctx); flint_bitcnt_t mpoly_exp_bits_required_ffmpz(const fmpz * user_exp, const mpoly_ctx_t mctx); flint_bitcnt_t mpoly_exp_bits_required_pfmpz(fmpz * const * user_exp, const mpoly_ctx_t mctx); FLINT_FORCE_INLINE flint_bitcnt_t mpoly_gen_pow_exp_bits_required(slong v, ulong e, const mpoly_ctx_t mctx) { return 1 + FLINT_BIT_COUNT(e); /* only lex and deg supported */ } int mpoly_is_poly(const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, slong var, const mpoly_ctx_t mctx); void mpoly_pack_vec_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len); void mpoly_pack_vec_fmpz(ulong * exp1, const fmpz * exp2, flint_bitcnt_t bits, slong nfields, slong len); void mpoly_unpack_vec_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len); void mpoly_unpack_vec_fmpz(fmpz * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len); void mpoly_get_monomial_ui_unpacked_ffmpz(ulong * user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx); void mpoly_get_monomial_ffmpz_unpacked_ffmpz(fmpz * user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx); void mpoly_get_monomial_pfmpz_unpacked_ffmpz(fmpz ** user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx); void mpoly_get_monomial_ui_unpacked_ui(ulong * user_exps, const ulong * poly_exps, const mpoly_ctx_t mctx); void mpoly_get_monomial_ui_sp(ulong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_get_monomial_ui_mp(ulong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_get_monomial_si_mp(slong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); MPOLY_INLINE void mpoly_get_monomial_ui(ulong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { if (bits <= FLINT_BITS) mpoly_get_monomial_ui_sp(user_exps, poly_exps, bits, mctx); else mpoly_get_monomial_ui_mp(user_exps, poly_exps, bits, mctx); } MPOLY_INLINE void mpoly_get_monomial_si(slong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { /* if bits <= FLINT_BITS and poly_exps is canonical, everything should be ok */ if (bits <= FLINT_BITS) mpoly_get_monomial_ui_sp((ulong *) user_exps, poly_exps, bits, mctx); else mpoly_get_monomial_si_mp(user_exps, poly_exps, bits, mctx); } ulong mpoly_get_monomial_var_exp_ui_sp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); ulong mpoly_get_monomial_var_exp_ui_mp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); slong mpoly_get_monomial_var_exp_si_mp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); MPOLY_INLINE ulong mpoly_get_monomial_var_exp_ui(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { if (bits <= FLINT_BITS) return mpoly_get_monomial_var_exp_ui_sp(poly_exps, var, bits, mctx); else return mpoly_get_monomial_var_exp_ui_mp(poly_exps, var, bits, mctx); } MPOLY_INLINE slong mpoly_get_monomial_var_exp_si(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { if (bits <= FLINT_BITS) return (slong) mpoly_get_monomial_var_exp_ui_sp(poly_exps, var, bits, mctx); else return mpoly_get_monomial_var_exp_si_mp(poly_exps, var, bits, mctx); } void mpoly_get_monomial_ffmpz(fmpz * exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_get_monomial_pfmpz(fmpz ** exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_set_monomial_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_set_monomial_ffmpz(ulong * exp1, const fmpz * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_set_monomial_pfmpz(ulong * exp1, fmpz * const * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int mpoly_repack_monomials(ulong * exps1, flint_bitcnt_t bits1, const ulong * exps2, flint_bitcnt_t bits2, slong len, const mpoly_ctx_t mctx); void mpoly_pack_monomials_tight(ulong * exp1, const ulong * exp2, slong len, const slong * mults, slong num, slong bits); void mpoly_unpack_monomials_tight(ulong * e1, ulong * e2, slong len, slong * mults, slong num, slong bits); int mpoly_monomial_exists(slong * index, const ulong * poly_exps, const ulong * exp, slong len, slong N, const ulong * cmpmask); slong mpoly_monomial_index1_nomask(ulong * Aexps, slong Alen, ulong e); slong mpoly_monomial_index_ui(const ulong * Aexp, flint_bitcnt_t Abits, slong Alength, const ulong * exp, const mpoly_ctx_t mctx); slong mpoly_monomial_index_pfmpz(const ulong * Aexp, flint_bitcnt_t Abits, slong Alength, fmpz * const * exp, const mpoly_ctx_t mctx); slong mpoly_monomial_index_monomial(const ulong * Aexp, flint_bitcnt_t Abits, slong Alength, const ulong * Mexp, flint_bitcnt_t Mbits, const mpoly_ctx_t mctx); void mpoly_min_fields_ui_sp(ulong * min_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_min_fields_fmpz(fmpz * min_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_max_fields_ui_sp(ulong * max_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_max_fields_fmpz(fmpz * max_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int mpoly_degrees_fit_si(const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_degrees_si(slong * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_degrees_si_threaded(slong * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, const thread_pool_handle * handles, slong num_handles); void mpoly_degrees_ffmpz(fmpz * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_degrees_pfmpz(fmpz ** user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); slong mpoly_degree_si(const ulong * poly_exps, slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx); void mpoly_degree_fmpz(fmpz_t deg, const ulong * poly_exps, slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx); int mpoly_total_degree_fits_si(const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); slong mpoly_total_degree_si(const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_total_degree_fmpz(fmpz_t totdeg, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_total_degree_fmpz_ref(fmpz_t totdeg, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_used_vars_or(int * used, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int mpoly_monomial_cmp_general(ulong * Aexp, flint_bitcnt_t Abits, ulong * Bexp, flint_bitcnt_t Bbits, const mpoly_ctx_t mctx); void mpoly_search_monomials( slong ** e_ind, ulong * e, slong * e_score, slong * t1, slong * t2, slong *t3, slong lower, slong upper, const ulong * a, slong a_len, const ulong * b, slong b_len, slong N, const ulong * cmpmask); void mpoly_main_variable_split_LEX(slong * ind, ulong * pexp, const ulong * Aexp, slong l1, slong Alen, const ulong * mults, slong num, slong Abits); void mpoly_main_variable_split_DEG(slong * ind, ulong * pexp, const ulong * Aexp, slong l1, slong Alen, ulong deg, slong num, slong Abits); int mpoly_term_exp_fits_si(ulong * exps, flint_bitcnt_t bits, slong n, const mpoly_ctx_t mctx); int mpoly_term_exp_fits_ui(ulong * exps, flint_bitcnt_t bits, slong n, const mpoly_ctx_t mctx); int mpoly_is_gen(ulong * exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int mpoly_monomials_valid_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int mpoly_monomials_overflow_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); int mpoly_monomials_inorder_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); void mpoly_reverse(ulong * Aexp, const ulong * Bexp, slong len, slong N); void mpoly_monomials_deflation(fmpz * shift, fmpz * stride, const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const mpoly_ctx_t mctx); void mpoly_monomials_deflate(ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength, const fmpz * shift, const fmpz * stride, const mpoly_ctx_t mctx); void mpoly_monomials_inflate(ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength, const fmpz * shift, const fmpz * stride, const mpoly_ctx_t mctx); void _mpoly_gen_shift_right(ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx); void _mpoly_gen_shift_right_fmpz(ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, const fmpz_t amount, const mpoly_ctx_t mctx); void _mpoly_gen_shift_left(ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx); void mpoly_monomials_shift_right_ui(ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const ulong * user_exps, const mpoly_ctx_t mctx); void mpoly_monomials_shift_right_ffmpz(ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const fmpz * user_exps, const mpoly_ctx_t mctx); void mpoly1_fill_marks(ulong ** Dcoeffs, slong * Dlen, slong * Dalloc, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx); void mpoly2_fill_marks(ulong ** Dcoeffs, slong * Dlen, slong * Dalloc, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx); void mpoly_to_mpolyl_perm_deflate( ulong * Aexps, flint_bitcnt_t Abits, const mpoly_ctx_t Actx, ulong * Bexps, flint_bitcnt_t Bbits, const mpoly_ctx_t Bctx, slong length, const slong * perm, const ulong * shift, const ulong * stride); void mpoly_from_mpolyl_perm_inflate( ulong * Bexps, flint_bitcnt_t Bbits, const mpoly_ctx_t Bctx, ulong * Aexps, flint_bitcnt_t Abits, const mpoly_ctx_t Actx, slong length, const slong * perm, const ulong * shift, const ulong * stride); /* gcd ***********************************************************************/ #define MPOLY_GCD_USE_HENSEL 1 #define MPOLY_GCD_USE_BROWN 2 #define MPOLY_GCD_USE_ZIPPEL 4 #define MPOLY_GCD_USE_ZIPPEL2 8 #define MPOLY_GCD_USE_PRS 16 #define MPOLY_GCD_USE_ALL 31 void mpoly_gcd_info_init(mpoly_gcd_info_t I, slong nvars); void mpoly_gcd_info_clear(mpoly_gcd_info_t I); void mpoly_gcd_info_limits(ulong * Amax_exp, ulong * Amin_exp, slong * Amax_exp_count, slong * Amin_exp_count, const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const mpoly_ctx_t mctx); void mpoly_gcd_info_stride(ulong * strides, const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const ulong * Amax_exp, const ulong * Amin_exp, const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength, const ulong * Bmax_exp, const ulong * Bmin_exp, const mpoly_ctx_t mctx); void mpoly_gcd_info_set_perm(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); slong mpoly_gcd_info_get_brown_upper_limit(const mpoly_gcd_info_t I, slong var, slong bound); void mpoly_gcd_info_measure_hensel(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); void mpoly_gcd_info_measure_brown(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); void mpoly_gcd_info_measure_bma(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); void mpoly_gcd_info_measure_zippel(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); void mpoly_gcd_info_measure_zippel2(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); int mpoly_monomial_cofactors(fmpz * Abarexps, fmpz * Bbarexps, const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong length, const mpoly_ctx_t mctx); /* factoring ****************************************************************/ #define MPOLY_FACTOR_USE_ZAS 1 #define MPOLY_FACTOR_USE_WANG 2 #define MPOLY_FACTOR_USE_ZIP 4 #define MPOLY_FACTOR_USE_ALL 7 int mpoly_is_proved_not_square(const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, slong N, ulong * t); void mpoly_remove_var_powers(fmpz * var_powers, ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx); slong _mpoly_compress_exps(slong * V, slong * D, slong * deg, slong * S, slong n, slong l); int mpoly_test_irreducible(ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t ctx); int _mpoly_test_irreducible(slong * Aexps, slong stride, slong Alen, slong nvars, flint_rand_t state, slong tries_left); void mpoly_compression_init(mpoly_compression_t M); void mpoly_compression_clear(mpoly_compression_t M); void mpoly_compression_set(mpoly_compression_t M, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx); void mpoly_bivar_cld_bounds(slong * l, slong n); FLINT_FORCE_INLINE void _slong_array_fit_length(slong ** array, slong * alloc, slong len) { if (len <= *alloc) return; len = FLINT_MAX(len, *alloc + *alloc/4 + 1); *alloc = len; *array = (slong *) flint_realloc(*array, len*sizeof(slong)); } /* Heap **********************************************************************/ #define HEAP_LEFT(i) (2*(i)) #define HEAP_RIGHT(i) (2*(i) + 1) #define HEAP_PARENT(i) ((i)/2) #define HEAP_ASSIGN(h, c1, c2) \ do { \ (h).exp = (c1); \ (h).next = (c2); \ } while (0) void * _mpoly_heap_pop1(mpoly_heap1_s * heap, slong * heap_len, ulong maskhi); void _mpoly_heap_insert1(mpoly_heap1_s * heap, ulong exp, void * x, slong * next_loc, slong * heap_len, ulong maskhi); void * _mpoly_heap_pop(mpoly_heap_s * heap, slong * heap_len, slong N, const ulong * cmpmask); int _mpoly_heap_insert(mpoly_heap_s * heap, ulong * exp, void * x, slong * next_loc, slong * heap_len, slong N, const ulong * cmpmask); /* generic parsing ***********************************************************/ typedef struct { char * coeffs; fmpz * exps; slong length; slong alloc; } mpoly_univar_struct; typedef mpoly_univar_struct mpoly_univar_t[1]; void * mpoly_void_ring_elem_init(mpoly_void_ring_t R); void mpoly_void_ring_elem_clear(void * a, mpoly_void_ring_t R); void mpoly_univar_init(mpoly_univar_t A, mpoly_void_ring_t R); void mpoly_univar_clear(mpoly_univar_t A, mpoly_void_ring_t R); void mpoly_univar_swap(mpoly_univar_t A, mpoly_univar_t B); void mpoly_univar_fit_length(mpoly_univar_t A, slong len, mpoly_void_ring_t R); void mpoly_univar_init2(mpoly_univar_t A, slong len, mpoly_void_ring_t R); int mpoly_univar_pseudo_gcd_ducos(mpoly_univar_t G, mpoly_univar_t B, mpoly_univar_t A, mpoly_void_ring_t R); int mpoly_univar_resultant(void * r, mpoly_univar_t fx, mpoly_univar_t gx, mpoly_void_ring_t R); int mpoly_univar_discriminant(void * d, mpoly_univar_t fx, mpoly_void_ring_t R); typedef struct { char * str; slong str_len; } string_with_length_struct; typedef struct { mpoly_void_ring_t R; slong * stack; slong stack_len; slong stack_alloc; char * estore; slong estore_len; slong estore_alloc; void * tmp; string_with_length_struct * terminal_strings; char * terminal_values; slong terminals_alloc; slong terminals_len; } mpoly_parse_struct; typedef mpoly_parse_struct mpoly_parse_t[1]; void mpoly_parse_init(mpoly_parse_t E); void mpoly_parse_clear(mpoly_parse_t E); void mpoly_parse_add_terminal(mpoly_parse_t E, const char * s, const void * v); int mpoly_parse_parse(mpoly_parse_t E, void * res, const char * s, slong len); /* chunking */ /* Set i1[i] to the index of the i-th "coefficient" in variable k of num variables, each taking the given number of bits in the exponent. This assumes there are l1 "coefficients" in a list of len1 exponents. Note this doesn't currently mask the relevant bits. */ MPOLY_INLINE void mpoly_main_variable_terms1(slong * i1, slong * n1, const ulong * exp1, slong l1, slong len1, slong k, slong num, slong bits) { slong i, j = 0; slong shift = bits*(k - 1); i1[0] = 0; for (i = 0; i < l1 - 1; i++) { while (j < len1 && (l1 - i - 1) == (slong) (exp1[j] >> shift)) j++; i1[i + 1] = j; n1[i] = j - i1[i]; } n1[l1 - 1] = len1 - j; } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/mpoly/000077500000000000000000000000001461254215100145625ustar00rootroot00000000000000flint-3.1.3/src/mpoly/bidegree.c000066400000000000000000000016511461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* deg_gen(0) and deg_gen(1) of lt(A) packed into one ulong */ ulong _mpoly_bidegree( const ulong * Aexps, flint_bitcnt_t Abits, const mpoly_ctx_t mctx) { slong off0, shift0, off1, shift1; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); FLINT_ASSERT(mctx->ord == ORD_LEX); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, Abits, mctx); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, Abits, mctx); return pack_exp2((Aexps[off0] >> shift0) & mask, (Aexps[off1] >> shift1) & mask); } flint-3.1.3/src/mpoly/bivar_cld_bounds.c000066400000000000000000000040001461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "long_extras.h" /* for f in F[y][x] of degree n - 1 in x on input: l[i] = 1 + deg_y(coeff(f, x^i)) for 0 <= i <= n on output: l[i] > deg_y(coeff(f*g_x/g, x^i)) for any divisor g of f algo is a 2x scan to find the upper hull and then to fill in the output */ void mpoly_bivar_cld_bounds(slong * l, slong n) { slong * P; slong Plen = 0; slong i, j, x0, y0, x1, y1; TMP_INIT; FLINT_ASSERT(n > 0); TMP_START; P = (slong *) TMP_ALLOC(2*n*sizeof(slong)); n--; P[0] = n; P[1] = l[n]; Plen = 1; for (i = n - 1; i >= 0; i--) { if (l[i] < 1) continue; x0 = i; y0 = l[i]; while (Plen >= 2 && !z_mat22_det_is_negative( P[2*(Plen - 1) + 0] - x0, P[2*(Plen - 1) + 1] - y0, P[2*(Plen - 2) + 0] - x0, P[2*(Plen - 2) + 1] - y0)) Plen--; P[2*Plen + 0] = x0; P[2*Plen + 1] = y0; Plen++; } i = Plen - 1; x0 = P[2*i + 0]; y0 = P[2*i + 1]; for (j = 1; j <= x0; j++) l[j - 1] = j < x0 ? 0 : y0; FLINT_ASSERT(j == x0 + 1); while (i > 0) { x1 = P[2*(i - 1) + 0]; y1 = P[2*(i - 1) + 1]; for ( ; j <= x1; j++) { ulong t1, t2, t3, t4; FLINT_ASSERT(x0 < j && j <= x1); umul_ppmm(t1, t2, j - x0, y1); umul_ppmm(t3, t4, x1 - j, y0); add_ssaaaa(t1, t2, t1, t2, t3, t4); udiv_qrnnd(l[j - 1], t3, t1, t2, x1 - x0); } x0 = x1; y0 = y1; i--; } FLINT_ASSERT(j == n + 1); l[j - 1] = 0; TMP_END; } flint-3.1.3/src/mpoly/cmp_general.c000066400000000000000000000063741461254215100172140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* !!! this file DOES need to change with new orderings */ int mpoly_monomial_cmp_general(ulong * Aexp, flint_bitcnt_t Abits, ulong * Bexp, flint_bitcnt_t Bbits, const mpoly_ctx_t mctx) { slong N; if (Abits == Bbits) { /* common case */ N = mpoly_words_per_exp(Abits, mctx); if (!mctx->rev) { /* ORD_DEGREVLEX and ORD_DEG_LEX */ return mpoly_monomial_cmp_nomask(Aexp, Bexp, N); } else { /* ORD_DEGREVLEX */ slong i = N - 1; if (Abits <= FLINT_BITS) { /* compare the highest word */ ulong fpw = FLINT_BITS/Abits; ulong himask = (UWORD(1) << (mctx->nvars%fpw*Abits)) - UWORD(1); if (Aexp[i] != Bexp[i]) { if ((Aexp[i]^himask) > (Bexp[i]^himask)) return 1; else return -1; } i--; } else { /* compare the degree field with usual comparison */ ulong wpf = Abits/FLINT_BITS; do { if (Aexp[i] != Bexp[i]) { if (Aexp[i] > Bexp[i]) return 1; else return -1; } i--; } while (--wpf != 0); } /* compare the remaining fields with reversed comparisons */ for (; i >= 0; i--) { if (Aexp[i] != Bexp[i]) { if (Aexp[i] < Bexp[i]) return 1; else return -1; } } return 0; } } else { int cmp; flint_bitcnt_t newbits; ulong * newAexp, * newBexp, * cmpmask; TMP_INIT; TMP_START; if (Abits > Bbits) { newbits = Abits; N = mpoly_words_per_exp(newbits, mctx); newAexp = Aexp; newBexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_repack_monomials(newBexp, newbits, Bexp, Bbits, 1, mctx); } else { FLINT_ASSERT(Abits < Bbits); newbits = Bbits; N = mpoly_words_per_exp(newbits, mctx); newBexp = Bexp; newAexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_repack_monomials(newAexp, newbits, Aexp, Abits, 1, mctx); } cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, newbits, mctx); cmp = mpoly_monomial_cmp(newAexp, newBexp, N, cmpmask); TMP_END; return cmp; } } flint-3.1.3/src/mpoly/compose_mat.c000066400000000000000000000045521461254215100172420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "mpoly.h" /* Fill the compose matrix for the T_mpoly_compose_T_mpoly_gen functions */ void mpoly_compose_mat_gen(fmpz_mat_t M, const slong * c, const mpoly_ctx_t mctxB, const mpoly_ctx_t mctxAC) { slong i, gi, j; fmpz * t; FLINT_ASSERT(fmpz_mat_nrows(M) == mctxAC->nfields + 1); FLINT_ASSERT(fmpz_mat_ncols(M) == mctxB->nfields); fmpz_mat_zero(M); t = _fmpz_vec_init(mctxAC->nfields); for (i = 0; i < mctxB->nvars; i++) { gi = mpoly_gen_index(i, mctxB); if (0 <= c[i] && c[i] < mctxAC->nfields) { mpoly_gen_fields_fmpz(t, c[i], mctxAC); for (j = 0; j < mctxAC->nfields; j++) fmpz_swap(fmpz_mat_entry(M, j, gi), t + j); } else { /* c[i] corresponds to zero */ fmpz_one(fmpz_mat_entry(M, mctxAC->nfields, gi)); } } _fmpz_vec_clear(t, mctxAC->nfields); } /* Fill the column of the compose matrix for the variable Bvar assuming Bvar maps to the monomial in (Cexps, Cbits). NULL may be passed in for Cexp to indicate that Bbar maps to 0. */ void mpoly_compose_mat_fill_column(fmpz_mat_t M, const ulong * Cexp, flint_bitcnt_t Cbits, slong Bvar, const mpoly_ctx_t mctxB, const mpoly_ctx_t mctxAC) { slong Bidx = mpoly_gen_index(Bvar, mctxB); slong j; fmpz * t; if (Cexp == NULL) { j = mctxAC->nfields; fmpz_one(fmpz_mat_entry(M, j, Bidx)); for (j--; j >= 0; j--) fmpz_zero(fmpz_mat_entry(M, j, Bidx)); return; } t = _fmpz_vec_init(mctxAC->nfields); mpoly_unpack_vec_fmpz(t, Cexp, Cbits, mctxAC->nfields, 1); j = mctxAC->nfields; fmpz_zero(fmpz_mat_entry(M, j, Bidx)); for (j--; j >= 0; j--) fmpz_swap(fmpz_mat_entry(M, j, Bidx), t + j); _fmpz_vec_clear(t, mctxAC->nfields); } flint-3.1.3/src/mpoly/compression.c000066400000000000000000000213051461254215100172700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "long_extras.h" /* input is S and the sizes n, l outputs S', V, D, deg satisfy det(V) = +- 1 V.S'[i] + D = S[i] deg[j] = max_j S[i][j] 0 = min_j S[i][j] where S'[i] / S[i] is the i^th row of S' / S */ slong _mpoly_compress_exps( slong * V, /* n*n matrix */ slong * D, /* n vector */ slong * deg, /* n vector */ slong * S, /* lxn matrix */ slong n, slong l) { slong mind, maxd, tot; slong * minp = FLINT_ARRAY_ALLOC(n, slong); slong * maxp = FLINT_ARRAY_ALLOC(n, slong); slong * minn = FLINT_ARRAY_ALLOC(n, slong); slong * maxn = FLINT_ARRAY_ALLOC(n, slong); slong * perm = FLINT_ARRAY_ALLOC(n, slong); slong * tmp = maxn; slong i, j, k, m; slong best_loc_i, best_loc_j, best_min, best_deg; fmpz_t this_prod, best_prod; fmpz_init(this_prod); fmpz_init(best_prod); FLINT_ASSERT(n > 0); FLINT_ASSERT(l > 1); for (i = 0; i < n; i++) for (j = 0; j < n; j++) V[i*n + j] = (i == j); for (j = 0; j < n; j++) minp[j] = maxp[j] = S[0*n + j]; for (i = 1; i < l; i++) for (j = 0; j < n; j++) { minp[j] = FLINT_MIN(minp[j], S[i*n + j]); maxp[j] = FLINT_MAX(maxp[j], S[i*n + j]); } for (j = 0; j < n; j++) { D[j] = minp[j]; deg[j] = 1 + maxp[j] - minp[j]; } for (i = 0; i < l; i++) for (j = 0; j < n; j++) S[i*n + j] -= D[j]; tot = 0; for (j = 0; j < n; j++) { if (z_add_checked(&tot, tot, deg[j])) goto done; } again: fmpz_one(best_prod); for (j = 0; j < n; j++) fmpz_mul_si(best_prod, best_prod, deg[j]); best_loc_i = -1; best_loc_j = -1; best_min = 0; for (i = 0; i < n; i++) { slong this_best_j, this_best_min = WORD_MAX, this_best_deg; mind = WORD_MAX; maxd = WORD_MIN; for (j = 0; j < n; j++) { minp[j] = minn[j] = WORD_MAX; maxp[j] = maxn[j] = WORD_MIN; } for (k = 0; k < l; k++) { slong * Sk = S + k*n; tot = 0; for (j = 0; j < n; j++) { tot += Sk[j]; minp[j] = FLINT_MIN(minp[j], Sk[i] + Sk[j]); maxp[j] = FLINT_MAX(maxp[j], Sk[i] + Sk[j]); minn[j] = FLINT_MIN(minn[j], Sk[i] - Sk[j]); maxn[j] = FLINT_MAX(maxn[j], Sk[i] - Sk[j]); } mind = FLINT_MIN(mind, tot); maxd = FLINT_MAX(maxd, tot); } this_best_deg = deg[i]; this_best_j = n + 1; /* something > n */ if (1 + maxd - mind < this_best_deg) { this_best_j = 0; this_best_min = mind; this_best_deg = 1 + maxd - mind; } for (j = 0; j < n; j++) { if (j == i) continue; if (1 + maxp[j] - minp[j] < this_best_deg) { this_best_j = 1 + j; this_best_min = minp[j]; this_best_deg = 1 + maxp[j] - minp[j]; } if (1 + maxn[j] - minn[j] < this_best_deg) { this_best_j = -1 - j; this_best_min = minn[j]; this_best_deg = 1 + maxn[j] - minn[j]; } } if (this_best_j > n) continue; fmpz_set_si(this_prod, this_best_deg); for (j = 0; j < n; j++) if (j != i) fmpz_mul_si(this_prod, this_prod, deg[j]); if (fmpz_cmp(this_prod, best_prod) < 0) { fmpz_swap(best_prod, this_prod); best_loc_i = i; best_loc_j = this_best_j; best_min = this_best_min; best_deg = this_best_deg; } } if (best_loc_i >= 0) { i = best_loc_i; j = best_loc_j; deg[i] = best_deg; if (j < 0) { j = -j - 1; for (k = 0; k < l; k++) S[k*n + i] += -S[k*n + j] - best_min; for (k = 0; k < n; k++) { D[k] += best_min*V[k*n + i]; V[k*n + j] += V[k*n + i]; } } else if (j > 0) { j = j - 1; for (k = 0; k < l; k++) S[k*n + i] += S[k*n + j] - best_min; for (k = 0; k < n; k++) { D[k] += best_min*V[k*n + i]; V[k*n + j] += -V[k*n + i]; } } else { for (k = 0; k < l; k++) { slong tot = 0; for (j = 0; j < n; j++) tot += S[k*n + j]; S[k*n + i] = tot - best_min; } for (k = 0; k < n; k++) { D[k] += best_min*V[k*n + i]; for (j = 0; j < n; j++) if (j != i) V[k*n + j] += -V[k*n + i]; } } goto again; } done: for (i = 0; i < n; i++) tmp[i] = i; for (i = 1; i < n; i++) for (j = i; j > 0 && deg[tmp[j]] < deg[tmp[j - 1]]; j--) FLINT_SWAP(slong, tmp[j], tmp[j - 1]); m = 1; while (m < n && deg[tmp[n - (m + 1)]] > 1) m++; for (i = 0; i < n; i++) perm[i] = (i < m) ? tmp[n - m + i] : tmp[i - m]; for (i = 0; i < n; i++) tmp[i] = deg[perm[i]] - 1; for (i = 0; i < n; i++) deg[i] = tmp[i]; for (k = 0; k < l; k++) { slong * Sk = S + k*n; for (i = 0; i < n; i++) tmp[i] = Sk[perm[i]]; for (i = 0; i < n; i++) Sk[i] = tmp[i]; } for (k = 0; k < n; k++) { slong * Vk = V + k*n; for (i = 0; i < n; i++) tmp[i] = Vk[perm[i]]; for (i = 0; i < n; i++) Vk[i] = tmp[i]; } flint_free(minp); flint_free(maxp); flint_free(minn); flint_free(maxn); flint_free(perm); fmpz_clear(this_prod); fmpz_clear(best_prod); return m; } void mpoly_compression_init(mpoly_compression_t M) { M->mvars = 0; M->nvars = 0; M->exps = NULL; M->exps_alloc = 0; M->rest = NULL; M->rest_alloc = 0; M->umat = NULL; M->deltas = NULL; M->degs = NULL; M->is_trivial = 0; M->is_perm = 0; M->is_irred = 0; } void mpoly_compression_clear(mpoly_compression_t M) { flint_free(M->exps); flint_free(M->rest); } void mpoly_compression_set( mpoly_compression_t M, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx) { slong i, j, one_total; slong N = mpoly_words_per_exp_sp(Abits, mctx); slong nvars = mctx->nvars; ulong * Mexps; int overflowed; slong sum_deg, tries; flint_rand_t state; M->nvars = nvars; _slong_array_fit_length(&M->rest, &M->rest_alloc, (nvars + 2)*nvars); M->umat = M->rest; M->deltas = M->umat + nvars*nvars; M->degs = M->deltas + nvars; _slong_array_fit_length(&M->exps, &M->exps_alloc, Alen*nvars); Mexps = (ulong *) M->exps; for (i = 0; i < Alen; i++) mpoly_get_monomial_ui_sp(Mexps + nvars*i, Aexps + N*i, Abits, mctx); M->mvars = _mpoly_compress_exps(M->umat, M->deltas, M->degs, M->exps, nvars, Alen); FLINT_ASSERT(M->mvars > 0); M->is_trivial = (M->mvars == nvars) && (mctx->ord == ORD_LEX); M->is_perm = 1; one_total = 0; for (i = 0; i < nvars; i++) for (j = 0; j < nvars; j++) { if (M->umat[i*nvars + j] == 1) { one_total++; if (i != j) M->is_trivial = 0; } else if (M->umat[i*nvars + j] == 0) { if (i == j) M->is_trivial = 0; } else { M->is_trivial = 0; M->is_perm = 0; } } if (one_total != M->nvars) M->is_perm = 0; flint_randinit(state); sum_deg = 1; overflowed = 0; for (j = 0; j < M->mvars; j++) { if (z_add_checked(&sum_deg, sum_deg, M->degs[j])) { overflowed = 1; break; } } tries = 12; if (!overflowed) tries -= Alen/sum_deg/2; M->is_irred = _mpoly_test_irreducible(M->exps, nvars, Alen, M->mvars, state, tries); flint_randclear(state); } flint-3.1.3/src/mpoly/ctx.c000066400000000000000000000040721461254215100155270ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void mpoly_ctx_init(mpoly_ctx_t mctx, slong nvars, const ordering_t ord) { flint_bitcnt_t bits; mctx->ord = ord; if (nvars > 0) { mctx->nvars = nvars; switch (ord) { case ORD_LEX: mctx->deg = 0; mctx->rev = 0; break; case ORD_DEGLEX: mctx->deg = 1; mctx->rev = 0; break; case ORD_DEGREVLEX: mctx->deg = 1; mctx->rev = 1; break; default: flint_throw(FLINT_ERROR, "Invalid ordering in mpoly_ctx_init"); } } else { mctx->nvars = 0; mctx->deg = 1; /* degree field will always be zero */ mctx->rev = 0; } mctx->nfields = mctx->nvars + mctx->deg; for (bits = 1; bits <= FLINT_BITS; bits++) { mctx->lut_words_per_exp[bits - 1] = (mctx->nfields - 1)/(FLINT_BITS/bits) + 1; } for (bits = 1; bits <= FLINT_BITS; bits++) { flint_bitcnt_t new_bits = FLINT_MAX(bits, MPOLY_MIN_BITS); while (new_bits < FLINT_BITS && mctx->lut_words_per_exp[new_bits - 1] == mctx->lut_words_per_exp[new_bits]) { new_bits++; } mctx->lut_fix_bits[bits - 1] = new_bits; } } void mpoly_ctx_clear(mpoly_ctx_t mctx) { return; } void mpoly_ctx_init_rand(mpoly_ctx_t mctx, flint_rand_t state, slong max_nvars) { ordering_t ord; slong nvars; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, max_nvars + 1); mpoly_ctx_init(mctx, nvars, ord); } flint-3.1.3/src/mpoly/degrees.c000066400000000000000000000160331461254215100163470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "fmpz.h" #include "mpoly.h" slong mpoly_degree_si(const ulong * exps, slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx) { if (len == 0) return -WORD(1); /* sometimes we don't have to look very far */ if (mctx->ord == ORD_LEX && var == 0) len = 1; if (bits <= FLINT_BITS) { slong r; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong offset, shift, N, i; mpoly_gen_offset_shift_sp(&offset, &shift, var, bits, mctx); N = mpoly_words_per_exp_sp(bits, mctx); i = 0; r = (exps[N*i + offset] >> shift) & mask; for (i = 1; i < len; i++) { ulong k = (exps[N*i + offset] >> shift) & mask; if (r < k) r = k; } return r; } else { slong * degs, r; TMP_INIT; TMP_START; degs = (slong *) TMP_ALLOC(mctx->nvars*sizeof(slong)); mpoly_degrees_si(degs, exps, len, bits, mctx); r = degs[var]; TMP_END; return r; } } void mpoly_degree_fmpz(fmpz_t deg, const ulong * exps, slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx) { slong i; fmpz * degs; TMP_INIT; TMP_START; degs = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(degs + i); mpoly_degrees_ffmpz(degs, exps, len, bits, mctx); fmpz_swap(deg, degs + var); for (i = 0; i < mctx->nvars; i++) fmpz_clear(degs + i); TMP_END; } /* this file does not need to change with new orderings */ void mpoly_degrees_si( slong * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i; fmpz * max_fields; TMP_INIT; if (len == 0) { for (i = 0; i < mctx->nvars; i++) user_degs[i] = -WORD(1); return; } TMP_START; max_fields = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) fmpz_init(max_fields + i); mpoly_max_fields_fmpz(max_fields, poly_exps, len, bits, mctx); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)user_degs, max_fields, mctx); for (i = 0; i < mctx->nfields; i++) fmpz_clear(max_fields + i); TMP_END; } typedef struct { slong * degs; const ulong * start; slong length; flint_bitcnt_t bits; const mpoly_ctx_struct * mctx; } _degrees_si_arg_struct; static void _worker_degrees_si(void * varg) { _degrees_si_arg_struct * arg = (_degrees_si_arg_struct *) varg; mpoly_degrees_si(arg->degs, arg->start, arg->length, arg->bits, arg->mctx); } void mpoly_degrees_si_threaded( slong * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx, const thread_pool_handle * handles, slong num_handles) { slong i, j; slong num_threads; _degrees_si_arg_struct * args; slong start, stop; slong N = mpoly_words_per_exp(bits, mctx); slong * degs_array; if (len == 0) { for (j = 0; j < mctx->nvars; j++) user_degs[j] = -WORD(1); return; } num_threads = num_handles + 1; degs_array = (slong *) flint_malloc(num_threads*mctx->nvars*sizeof(slong)); args = (_degrees_si_arg_struct *) flint_malloc( num_threads * sizeof(_degrees_si_arg_struct)); start = 0; for (i = 0; i < num_threads; i++) { args[i].degs = degs_array + i*mctx->nvars; args[i].start = poly_exps + N*start; stop = len*(i+1)/num_threads; stop = FLINT_MAX(stop, start); stop = FLINT_MIN(stop, len); args[i].length = stop - start; args[i].bits = bits; args[i].mctx = mctx; start = stop; } for (i = 0; i < num_handles; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, _worker_degrees_si, args + i); } i = num_handles; mpoly_degrees_si(user_degs, args[i].start, args[i].length, bits, mctx); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); for (j = 0; j < mctx->nvars; j++) { user_degs[j] = FLINT_MAX(user_degs[j], args[i].degs[j]); } } flint_free(degs_array); flint_free(args); } void mpoly_degrees_ffmpz( fmpz * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i; fmpz * max_fields; TMP_INIT; if (len == 0) { for (i = 0; i < mctx->nvars; i++) fmpz_set_si(user_degs + i, -WORD(1)); return; } TMP_START; max_fields = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) fmpz_init(max_fields + i); mpoly_max_fields_fmpz(max_fields, poly_exps, len, bits, mctx); mpoly_get_monomial_ffmpz_unpacked_ffmpz(user_degs, max_fields, mctx); for (i = 0; i < mctx->nfields; i++) fmpz_clear(max_fields + i); TMP_END; } void mpoly_degrees_pfmpz( fmpz ** user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i; fmpz * max_fields; TMP_INIT; if (len == 0) { for (i = 0; i < mctx->nvars; i++) fmpz_set_si(user_degs[i], -WORD(1)); return; } TMP_START; max_fields = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) fmpz_init(max_fields + i); mpoly_max_fields_fmpz(max_fields, poly_exps, len, bits, mctx); mpoly_get_monomial_pfmpz_unpacked_ffmpz(user_degs, max_fields, mctx); for (i = 0; i < mctx->nfields; i++) fmpz_clear(max_fields + i); TMP_END; } int mpoly_degrees_fit_si(const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, j, N; int ret; fmpz * tmp_exps; TMP_INIT; if (len == 0) { return 1; } TMP_START; tmp_exps = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (j = 0; j < mctx->nvars; j++) { fmpz_init(tmp_exps + j); } N = mpoly_words_per_exp(bits, mctx); ret = 1; for (i = 0; i < len; i++) { mpoly_get_monomial_ffmpz(tmp_exps, poly_exps + N*i, bits, mctx); for (j = 0; j < mctx->nvars; j++) { if (!fmpz_fits_si(tmp_exps + j)) { ret = 0; break; } } } for (j = 0; j < mctx->nvars; j++) fmpz_clear(tmp_exps + j); TMP_END; return ret; } flint-3.1.3/src/mpoly/doc/000077500000000000000000000000001461254215100153275ustar00rootroot00000000000000flint-3.1.3/src/mpoly/doc/MPolyAlgorithms.tex000066400000000000000000001563711461254215100211600ustar00rootroot00000000000000\documentclass[11pt,reqno]{amsart} \usepackage{amsmath, amssymb, amsthm} \usepackage{graphicx} \usepackage{xtab} \usepackage{color} \usepackage{hyperref} \usepackage[linesnumbered,ruled]{algorithm2e} \SetKw{KwGoTo}{goto} \numberwithin{equation}{section} \newtheorem{theorem}{Theorem}[section] \newtheorem{definition}[theorem]{Definition} \newtheorem{lemma}[theorem]{Lemma} \newtheorem{remark}[theorem]{Remark} \newtheorem{entry}[theorem]{Entry} \newtheorem{corollary}[theorem]{Corollary} \newtheorem{proposition}[theorem]{Proposition} \newtheorem{example}[theorem]{Example} \newtheorem{myalgorithm}[theorem]{Algorithm} \addtolength{\textwidth}{1.5in} \addtolength{\hoffset}{-0.75in} %\addtolength{\textheight}{0.6in} %\addtolength{\voffset}{-0.3in} \newcommand\T{\rule{0pt}{4.0ex}} % Top strut \newcommand\B{\rule[-2.5ex]{0pt}{0pt}} % Bottom strut \newcommand{\smat}[4] {(\begin{smallmatrix} #1 & #2 \\ #3 & #4 \end{smallmatrix} )} \newcommand{\mattt}[4] { \left(\begin{array}{cc} #1 & #2 \\ #3 & #4 \end{array} \right)} \newcommand{\matto}[2] { \left(\begin{array}{cc} #1 \\ #2 \end{array} \right)} \newcommand{\schar}[2] {( \begin{smallmatrix} #1 \\ #2 \end{smallmatrix})} \newcommand{\op}[1] { \operatorname{ #1 }} \newcommand{\olbbH}[0] { \overline{\mathbb{H}}} \newcommand{\olbbQ}[0] { \overline{\mathbb{Q}}} \newcommand{\olG}[0] { \overline{\Gamma}} \newcommand{\bbH}[0] { \mathbb{H}} \newcommand{\bbC}[0] { \mathbb{C}} \newcommand{\bbZ}[0] { \mathbb{Z}} \newcommand{\bbF}[0] { \mathbb{F}} \newcommand{\bbQ}[0] { \mathbb{Q}} \newcommand{\bbR}[0] { \mathbb{R}} \newcommand{\gok}[0] { \mathfrak{k}} \newcommand{\goe}[0] { \mathfrak{e}} \newcommand{\goR}[0] { \mathfrak{R}} \title{Algorithms for Multivariate Polynomials} \author{Daniel Schultz} \begin{document} \begin{abstract} Algorithms for multivariate polynomials in flint are discussed. \end{abstract} \maketitle \section{Introduction} A polynomial $A \in R[x_1,\dots,x_n]$ is representation as a sums of terms \begin{equation*} A = t_1 + \cdots + t_a \end{equation*} where the terms are ordered as $t_1 > t_2 > \cdots > t_a$ according to some term ordering. The basic operations of addition and subtraction are then equivalent to a merge operation and run in time proportional to the sum of the input term counts. \section{Monomial Representation} The {\tt mpoly} module implements the low level packing and unpacking of exponents for multivariate polynomials. If the variables in the polynomial are, say, $x$, $y$ and $z$ with $x > y > z$ in the monomial ordering, then the monomial $x^a y^b z^c$ is represented as the array $\{a, b, c\}$ from the user's perspective. Polynomial exponents are stored in packed format. This means that monomials are actually stored as an array of integer 'fields' that may be packed within a machine word or across multiple machine words if needed. This facilitates basic operations on the monomials, and we make the following assumptions about the correspondence between the variables' exponents and the fields in the packing: \begin{enumerate} \item {The monomial ordering is a total ordering, i.e. 1 is the smallest.} \item{Multiplication of monomials corresponds to field-wise addition.} \item{Monomials can be compared by comparing their packed representation possibly with an xor mask on certain fields.} \item{The exponent of each variable is itself one of the fields.} \item{The fields are all non-negative.} \end{enumerate} For the three supported ordering {\tt ORD\_LEX}, {\tt ORD\_DEGLEX}, and {\tt ORD\_DEGREVLEX}, the monomial $x^a y^b z^c$ is converted into fields in the following ways (the least significant field is on the left, the most significant is on the right), and the comparison mask is shown below. \begin{verbatim} ORD_LEX: | c | b | a | ( 3 fields) 000 000 000 ORD_DEGLEX: | c | b | a | a+b+c | ( 4 fields) 000 000 000 00000 ORD_DEGREVLEX: | a | b | c | a+b+c | ( 4 fields) 111 111 111 0000000 \end{verbatim} If one wanted to support, for example, a block ordering which was {\tt ORD\_DEGLEX} in $x, y$ and {\tt ORD\_DEGREVLEX} in $z, w$ with $x>y>z>w$, the monomial $x^a y^b z^c w^d$ would need to be stored as \begin{verbatim} | c | d | c+d | b | a | a+b | (6 fields) 111 111 00000 000 000 00000 \end{verbatim} No such interface is currently implemented. There is no limit to the size of the fields. The fields themselves are packed to a uniform bit width, usually denoted by {\tt bits} in the functions. This bit count should contain an extra sign bit used for overflow detection. Thus, if the maximum field is $15$, then the fields only fit into a packing with {\tt bits >= 5}. The total number of machine words taken by an exponent packed into fields is usually denoted by {\tt N} in the code. If {\tt bits <= FLINT\_BITS} then precisely a maximum of {\tt floor(FLINT\_BITS/bits)} number of fields may be packed into a single word. Within a word, the packing is from low to high, and unused fields (as well as unused bits) at the top of the word are zero. \section{Multiplication} \subsection{Dense multiplication in $\bbZ[x_1,\dots,x_n]$ or $\bbZ_p[x_1,\dots,x_n]$}\ Given $A(x_1,\dots,x_n), B(x_1,\dots,x_n) \in R[x_1,\dots,x_n]$, set $r_i = 1 + \op{deg}_{x_i}(a) + \op{deg}_{x_i}(b)$. The Kronecker substitution \begin{equation*} x_1 \to x, \quad x_2 \to x^{r_1}, \quad x_3 \to x^{r_1 r_2}, \quad \dots, \quad x_n \to x^{r_1 \cdots r_{n-1}} \end{equation*} gives two univariate polynomials to multiply in $\bbZ[x]$ or $\bbZ_p[x]$. This Kronecker substitution is chosen so that it can be reversed to find $A \cdot B \in R[x_1,\dots,x_n]$ from the univariate product. The flint functions {\tt \_mpoly\_mul\_\{dense|array\}} implement such techniques. The {\tt dense} functions use the ordinary polynomial multiplication functions while the {\tt array} functions use a multiply and accumulate technique that might be better for semi-sparse polynomials. \subsection{Sparse multiplication in $\bbZ[x_1,\dots,x_n]$ or $\bbZ_p[x_1,\dots,x_n]$}\ Given $A = t_1 + \cdots + t_a, B = s_1 + \cdots + s_b, \in R[x_1,\dots,x_n]$, we need to calculate all products $t_i s_j$, sort them, and combine like terms. This is done using a heap in the functions {\tt \_mpoly\_mul\_johnson} as in \cite{Johnson}. The essential idea is to read off the product terms in order from a heap. The heap never needs to become too large if one uses the relations \begin{equation*} t_i s_j > t_{i+1} s_j, \quad t_i s_j > t_i s_{j+1}\text{.} \end{equation*} \section{Division} The techniques used for multiplication (Kronecker substitutions in the dense case and heaps in the sparse case) apply to division as well. \section{Powering} Implements a corrected version of an algorithm called FPS in \cite{FPS}. The basic idea is to map the problem to $R[x]$ via a Kronecker substitution and use a recursion for the coefficients of $f^k$ derived from \begin{equation*} f (f^k)' = k f' (f^k)\text{.} \end{equation*} Since solving for the coefficients of $f^k$ involves division, this requires some modification for $R=\bbZ_p$. \section{Interpolation} All of the interpolation methods for $f(x_1, \dots, x_n) \in R[x_1, \dots, x_n]$ require strict degree bounds $r_i$ with $\op{deg}_{x_i}(f) < r_i$. \subsection{Dense Newton Interpolation} Straightforward, variable-by-variable, recursive, dense interpolation. Number of probes to $f$ is $\prod_i r_i$. There is only one problem with this approach. \begin{itemize} \item insufficient evaluation points \end{itemize} \subsection{Sparse Zippel Interpolation} Similar to Newton interpolation, but we use the assumption that monomials don't disappear under evaluation. For example, suppose $r_x, r_y, r_z$ are the strict degree bounds. We first find $f(x,1,1)$ using dense interpolation with $r_x$ values of $x$, say $x_1, \dots, x_{r_x},$. If \begin{equation*} f(x,1,1) = x^5 + 2x^2 + 1\text{,} \end{equation*} we make the assumption that \begin{equation*} f(x,y,1) = a_1(y)x^5 + a_2(y)x^2 + a_3(y)\text{,} \end{equation*} and proceed to interpolate the $a_i(y)$ using dense univariate interpolation in $y$. We need $r_y$ values of $y$, say $y_1, \dots, y_{r_y}$. For each of these values $y=y_i$ we can find the coefficients (?) in \begin{equation*} f(x,y_i,1) = (?) x^5 + (?) x^2 + (?) \end{equation*} by plugging in \emph{three} random values of $x$ and solving the linear system. To find $f(x,y,1)$ at this point the number of probes to $f$ we have used is $r_x + 3r_y$, which is probably fewer than $r_x r_y$. Now suppose we obtain \begin{equation*} f(x,y,1) = y^2 x^5 + x^2 + y^7 x^2 + y^3. \end{equation*} Make the assumption \begin{equation*} f(x,y,z) = b_1(z)y^2 x^5 + b_2(z)x^2 + b_3(z)y^7 x^2 + b_4(z)y^3\text{,} \end{equation*} and interpolate the $b_i(z)$ using dense univariate interpolation in $z$. We need $r_z$ values of $z$, say $z_1, \dots, z_{r_z}$. For each of these values $z=z_i$ we can find the coefficients (?) in \begin{equation*} f(x,y,z) = (?)y^2 x^5 + (?)x^2 + (?)y^7 x^2 + (?)y^3 \end{equation*} by plugging in \emph{four} random pairs of values of $(x,y)$ and solving the linear system. To find $f(x,y,z)$ at this point the number of probes to $f$ we have used is $r_x + 3r_y + 4r_z$, which is probably fewer than $r_x r_y r_z$. This approach has an additional problems. \begin{itemize} \item insufficient evaluation points \item inconsistent/underdetermined linear equations \item associated linear algebra costs \end{itemize} \subsection{Sparse Interpolation with the Berlekamp-Massey Algorithm} Given the strict degree bounds $r_i$, in order to interpolate $f(x_1, \dots, x_n)$ it suffices to interpolate $f(\xi, \xi^{r_1}, \xi^{r_1 r_2}, \dots, \xi^{r_1 \cdots r_{n-1}})$, which is a univarate with degree bound $\prod_i r_i$. If $t$ is the number of terms of $f$, then we can summarize the probe counts of the three methods. \begin{enumerate} \item dense: $\prod_i r_i$ \item zippel: approximately $t \cdot \sum_i r_i$. \item bma: $2t$. \end{enumerate} This approach has problems too. \begin{itemize} \item insufficient evaluation points \item costs of the associated linear algebra and discrete logarithms. \end{itemize} Since the presentation in \cite{BMAR} is overly complicated and does not deal with the half gcd, it seems reasonable to review the Berlekamp-Massey Algorithm here. Given a formal power series \begin{equation*} \frac{a_1}{x} + \frac{a_2}{x^2} + \frac{a_3}{x^3} + \cdots\text{,} \quad a_i \in \bbF \end{equation*} vanishing at $x = \infty$ and the fact that this power series represents a rational function, we are interested in computing this rational function. The following theorem says that we can use the extended euclidean algorithm and stop when the first remainder of degree $<\frac{n}{2}$ is obtained. \begin{theorem} Suppose that \begin{equation*} \frac{a_1}{x} + \frac{a_2}{x^2} + \frac{a_3}{x^3} + \cdots = -\frac{\bar{u}}{\bar{v}} \end{equation*} for some $\bar{u}, \bar{v} \in \bbF[x]$ with $\op{deg}(\bar{u}) < \op{deg}(\bar{v}) \le \frac{n}{2}$. Suppose further that \begin{equation} \label{equ_bma1} u x^{n} + v (a_1 x^{n-1} + a_2 x^{n-2} + \cdots + a_{n-1} x + a_{n}) = r \end{equation} for some $u, v, r \in \bbF[x]$ with $\op{deg}(u) < \op{deg}(v) \le \frac{n}{2}$ and $\op{deg}(r) < \frac{n}{2}$ and $\op{deg}(r) < \op{deg}(v)$. Then, \begin{equation*} \frac{\bar{u}}{\bar{v}} = \frac{u}{v}\text{.} \end{equation*} \end{theorem} \begin{proof} Dividing both sides of \eqref{equ_bma1} by $v x^{n}$ shows that \begin{equation*} \frac{\bar{u}}{\bar{v}} = \frac{u}{v} + O \left( \frac{1}{x^{n+1}}\right)\text{,} \end{equation*} which, on account of the degree bounds $\op{deg}(\bar{v}), \op{deg}(v) \le \frac{n}{2}$, proves the equality. \end{proof} This reconstruction may be applied to reconstruct an $f(\xi) = c_1 \xi^{e_1} + \cdots + c_t \xi^{e_t} \in \bbF[\xi]$ from the sequence of evaluation points \begin{equation*} a_i = f(\alpha^{s+i-1})\text{,} \quad \alpha \neq 0, \quad s \in \bbZ\text{,} \end{equation*} for in this case we have \begin{equation*} \frac{a_1}{x} + \frac{a_2}{x^2} + \frac{a_3}{x^3} + \cdots = \frac{c_1\alpha^{e_1 s}}{x - \alpha^{e_1}} + \cdots + \frac{c_t\alpha^{e_t s}}{x - \alpha^{e_t}}\text{.} \end{equation*} If this rational function is known and the $e_i$ can be found, then $f$ is known as well. The main problem with this approach is that the term bound $t$ is not known in advance. The approach we take is to calculate the $v$ in \eqref{equ_bma1} for some $n$ points $a_1, \dots, a_{n}$. Then, we add another $m$ points to form the sequence $a_1, \dots, a_{n+m}$ and calculate the corresponding $v'$. If $v=v'$, then it is likely that $v$ is the correct denominator. The extent to which previous computations may be reused is addressed in Theorem \ref{thm_nm}. We follow \cite{YAP} for the presentation of the half gcd. An elementary matrix is one of the form $\smat{0}{1}{1}{q}$ for $\deg(q) > 0$ and a regular matrix is a product of zero or more elementary matrices. The notation $U \overset{M}{\longrightarrow} V$ shall mean that $M$ is a regular matrix and $U=MV$. If $\deg(A)>\deg(B)$ then $\op{hgcd}(A,B)$ is defined (see \cite{YAP}) as the (unique) regular matrix $M$ such that \begin{gather*} \matto{A}{B} \overset{M}{\longrightarrow} \matto{C'}{D'}\text{,}\\ \deg(C') \ge \frac{\deg(A)}{2} > \deg(D')\text{.} \end{gather*} \begin{theorem} \label{thm_correctness} Suppose that \begin{align*} \matto{A_0}{B_0} &\overset{M}{\longrightarrow} \matto{A_0'}{B_0'}\\ \op{deg}(A_0') &> \deg(B_0')\\ \op{deg}(A_0) &\le 2 \op{deg}(A_0') \end{align*} Then, for any $A_1$, $B_1$ with $\deg(A_1),\deg(B_1) < m$, \begin{align*} \matto{A_0 x^m + A_1}{B_0 x^m + B_1} &\overset{M}{\longrightarrow} \matto{A'}{B'}\\ \op{deg}(A') &= m + \op{deg}(A_0')\\ \op{deg}(B') &\le m + \op{max}( \deg(B_0'), \deg(A_0')-1)\\ \op{deg}(B') &\le m + \op{max}( \deg(B_0'), \frac{\deg(A_0)}{2}-1) \end{align*} for some $A', B'$. \end{theorem} \begin{proof} This is a trivial rearrangement of Lemma 1 in \cite{YAP}. \end{proof} \begin{theorem} \label{thm_nm} Suppose $\deg(s_n) < n$, $\deg(s_m) < m$ and \begin{gather*} \matto{x^n}{s_n} \overset{M}{\longrightarrow} \matto{r_0}{r_1}\\ \deg(r_0) \ge \frac{n}{2} > \deg(r_1) \end{gather*} Then, a regular matrix $M'$ (and thus $r_0', r_1'$) such that \begin{gather*} \matto{x^{n+m}}{s_n x^m + s_m} \overset{M'}{\longrightarrow} \matto{r_0'}{r_1'}\\ \deg(r_0') \ge \frac{n+m}{2} > \deg(r_1') \end{gather*} may be calculated as follows. Define $A', B'$ by \begin{equation*} \matto{x^{n+m}}{s_n x^m + s_m} \overset{M}{\longrightarrow} \matto{A'}{B'} \end{equation*} It will be the case that $\deg(A') \ge \frac{n+m}{2}$. If $\frac{n+m}{2} > \deg(B')$, return with $M'=M$. Otherwise set $C = B'$, $D = \op{rem}(A',B')$ and $q=\op{quo}(A',B')$. Define $k := n + m - \deg(C)$. It will be the case that $0 < k \le \deg(C)$. Return with \begin{equation*} M' = M \cdot \mattt{0}{1}{1}{q} \cdot \op{hgcd} \matto{\op{quo}(C,x^k)}{\op{quo}(D,x^k)} \end{equation*} \end{theorem} \begin{proof} By Theorem \ref{thm_correctness}, $\deg(A') = m + \deg(r_0) \ge m + \frac{n}{2} \ge \frac{n+m}{2}$. Now suppose $\frac{n+m}{2} \le \deg(B')$, from which the assertion $k \le \deg(C)$ follows automatically. By Theorem \ref{thm_correctness}, $\deg(B') \le m + \max(\deg(r_1), \deg(r_0) - 1) < m + n$. Thus, the assertion $0 < k$ is proved. Finally, suppose \begin{gather*} \matto{C_0 := \op{quo}(C,x^k)}{D_0 := \op{quo}(D,x^k)} \overset{H}{\longrightarrow} \matto{C_0'}{D_0'}\text{,}\\ \deg(C_0') \ge \frac{\deg(C_0)}{2} > \deg(D_0')\text{.} \end{gather*} If $C', D'$ are defined by \begin{equation*} \matto{C}{D} \overset{H}{\longrightarrow} \matto{C'}{D'}\text{,} \end{equation*} it suffices to prove that $\deg(C') \ge \frac{n+m}{2} > \deg(D')$. By Theorem \ref{thm_correctness}, \begin{align*} \deg(C') &= k + \deg(C_0')\\ &\ge k + \frac{\deg(C_0)}{2}\\ &= k + \frac{\deg(C) - k}{2}\\ &= \frac{n+m}{2}\text{.} \end{align*} Also by Theorem \ref{thm_correctness}, \begin{align*} \deg(D') &\le k + \max(\deg(D_0'), \frac{\deg(C_0)}{2} - 1)\\ & < k + \max(\frac{\deg(C_0)}{2}, \frac{\deg(C_0)}{2})\\ &= \frac{n+m}{2}\text{.} \end{align*} \end{proof} \section{Greatest Common Divisor} \subsection{Dense GCD in $\bbZ_p[x_1,\dots,x_n]$}\ Brown's algorithm \cite{Brown} is used here. This comes in two versions - a small prime version and a large prime version. These refer not to the size of the $p$'s involved, but rather to the field from which evaluation points are chosen: it can either be $\bbF_p$ or an extension of $\bbF_p$. The small prime version interpolates in each variable by choosing evaluation points from $\bbF_p$. If this fails, then the large prime method uses interpolation in $\bbF_p/(f(x_n))[x_1,\dots,x_{n-1}]$, i.e. $\bbF_q[x_1,\dots,x_{n-1}]$, for sufficiently many irreducible $f(x) \in \bbZ_p[x]$. No explicit divisibility checks need to be performed because the cofactors are reconstructed along with the GCD. \subsection{Dense GCD in $\bbZ[x_1,\dots,x_n]$}\ We simply reconstruct the GCD from its image in $\bbZ_p[x_1,\dots,x_n]$ for sufficiently many $p$. Only large $p$'s are used, and dense GCD's in $\bbZ_p[x_1,\dots,x_n]$ only use the small prime version. Each image GCD in $\bbZ_p$ is correct and Brown's coefficient bounds \cite{Brown} are used instead of a divisibility check. Some pseudocode is in Section \ref{Pseudocode}. \subsection{Sparse GCD in $R[x_1,\dots,x_n]$}\ Assuming that we have a gcd algorithm for $R[x_1,\dots,x_m]$, we can view the inputs as elements of $R[x_1,\dots,x_m][x_{m+1},\dots,x_n]$ and use interpolation to extend this algorithm from $m$ variables to $n$ variables. Brown's algorithm corresponds to taking $m=n-1$, using univariate interpolation for the extension of $n-1$ variables to $n$ variables, and recursively solving the $n-1$ variable gcd problem with the Euclidean algorithm as the base case. Taking $m=1$ gives Zippel's approach \cite{ZIPPEL}. If the inputs are made primitive with respect to $x_1,\dots,x_m$ by factoring out polynomials in $R[x_{m+1},\dots,x_n]$, the gcd of the leading coefficients of the input with respect to $x_1,\dots,x_m$ may be imposed as the leading coefficient of the interpolated gcd. Finally, if the primitive part with respect to $x_1,\dots,x_m$ of this interpolated gcd divides both inputs, it must be the true gcd. Of note here is an algorithm stated slightly incorrectly in \cite{SULING} and \cite{LINZIP}; The basic idea is to reconstruct the correct leading term of the gcd $\in R[x_1,\dots,x_m]$ using some linear algebra directly instead of constructing some known multiple and then removing content. This is in {\tt fmpz\_mpolyl\_gcd\_zippel} and a rough overview is: \ \\ {\tt fmpz\_mpolyl\_gcdm\_zippel}($A, B \in \bbZ_p[x_1,\dots,x_n][X]$, $n \ge 1$):\\ \indent $\left[\begin{tabular}{l} The GCD is assumed to have no content w.r.t. $X$ (content in $\bbZ[x_1, \dots, x_n]$)\\ Pick a prime $p$ and call {\tt nmod\_polyl\_gcdp\_zippel} to get an probable image of $G \mod p$ \\ Assume that the true gcd $G$ over $\bbZ$ has the same monomials as this image mod $p$.\\ Pick more primes $p$ and call {\tt nmod\_mpolyl\_gcds\_zippel} to get more images of $G \mod p$. \\ Combine the images via chinese remaindering and test divisibility. \end{tabular}\right.$ \ \\ The ``p'' versions produce a correct gcd when the inputs have no content in $\bbF_p[x_1,\dots,x_n]$. \ \\ {\tt nmod\_mpolyl\_gcdp\_zippel}($A, B \in \bbF_p[x_1,\dots,x_n][X]$, $n \ge 1$):\\ \indent $\left[\begin{tabular}{l} If the GCD has content w.r.t. $X, x_1, \dots, x_1$ (content in $\bbF_p[x_n]$), fail.\\ Pick an evaluation point $x_n \to \alpha$ for $\alpha \in \bbF_p$.\\ (1) Call {\tt nmod\_mpolyl\_gcdp\_zippel} recursively on the evaluated inputs in $\bbF_p[x_1,\dots,x_{n-1}][X]$.\\ Record the form $f$ of the GCD obtained for step (2) below.\\ Pick severial evaluation points $x_n \to \alpha$ for $\alpha \in \bbF_q$.\\ (2) Call {\tt [fq\_]nmod\_mpoly\_gcds\_zippel} on the evaluated inputs in $\bbF_q[x_1,\dots,x_{n-1}][X]$.\\ Combine the answer from (1) and the answers from (2) via interpolation in $x_n$.\\ Check divisibility on the proposed interpolated GCD. \end{tabular}\right.$ \ \\ The ``s'' versions are the heart of Zippel's sparse interpolation. \ \\ {\tt nmod\_mpolyl\_gcds\_zippel}($A, B \in \bbF_q[x_1,\dots,x_n][X]$, assumed monomial form $f$ of gcd):\\ \indent $\left[\begin{tabular}{l} Via evaluations of the form $(x_1,\dots,x_n) \to (\alpha_1,\dots,\alpha_n) \in \bbF_p^n$,\\ and GCD computations in $\bbF_p[X]$, and linear algebra, try to compute the coefficients \\of the assumed form $f$ to match the GCD of the inputs (up to scalar multiples in $\bbF_p$). \end{tabular}\right.$ \subsection{PRS} The PRS algorithm works over any gcd domain $R$. It starts with a primitive input with respect to some main variable and calculates a pseudo gcd with a pseudo remainder sequence. Content is removed from the pseudo gcd to produce the true gcd by a recursive call. The final content can be computed without expensive recursive calls to gcd in the case when we know the leading or trailing coefficient in the main variable must be a monomial in the remaining variables. This algorithm has been discarded because it is so bad but may be reintroduced for low degrees. \subsection{Hensel Lifting} The gcd can also be calculated using Hensel lifting \cite{EZGCD}. The gcd of the resulting univariates when all variables but one are substituted away gives two factorizations which can be lifted to obtain the multivariate gcd. \section{Factorization} \subsection{Squarefree Factorization in $K[x_1,\dots,x_n]$} \label{section_sqfr} By taking derivatives and greatest common divisors, we may assume that the input polynomial is squarefree and primitive with respect to each variable. Thus in characteristic zero the input polynomial $f \in K[x_1,\dots,x_n]$ may be assumed to satisfy \begin{equation*} \forall_i \quad f_{x_i} \neq 0 \quad \text{and} \quad \gcd(f,f_{x_i}) = 1\text{.} \end{equation*} Over a finite field ($K=\mathbb{F}_q$) of characteristic $p$, we have the slightly weaker conditions \begin{equation} \label{sqrfp_cond} \begin{alignedat}{3} &f_{x_1} \ne 0 \quad &\text{and}& \quad \gcd(f,f_{x_1}) = 1\\ \forall_{i>1} \quad &f_{x_i} = 0 \quad &\text{or}& \quad \gcd(f,f_{x_i}) = 1 \end{alignedat} \end{equation} While we could apply the factorization algorithms directly to this $f$ with $x_1$ as the main variable, it is possible to a bit better when some of the other derivatives vanish. \begin{theorem} With the assumption \ref{sqrfp_cond} on $f$ and prime powers $p^{e_2},\dots,p^{e_n}$ and a deflated polynomial $g$ with \begin{equation*} g(x_1,x_2^{p^{e_2}},\dots, x_n^{p^{e_n}}) = f(x_1,x_2,\dots,x_n)\text{,} \end{equation*} the factorization of $f$ is the inflated factorization of $g$. \end{theorem} The proof follows by induction from the following lemma: the polynomials $g(x_1,x_2, x_3,\dots, x_n)$ and $g(x_1,x_2^p, x_3,\dots, x_n)$ have the same factorization (up to inflation $x_2 \to x_2^p$). \begin{lemma} If $p = \operatorname{char}(K) > 0$ and $f(x,y) \in K[x,y] \setminus (K[x] \cup K[y])$ is irreducible and $f(x^p,y)$ is squarefree, then $f(x^p,y)$ is irreducible. \end{lemma} \begin{proof} Suppose that $f(x^p,y)=g(x,y)h(x,y)$ for $g,h \not \in K$. Since $f(x^p,y)$ is squarefree, $g$ and $h$ are squarefree, and there are $s, t \in K(y)[x]$ with $1=sg+th$. By differentiating $f(x^p,y)=g(x,y)h(x,y)$, we obtain $0=h g_x + g h_x$, which when combined with $1=sg+th$ gives $h(t h_x - s g_x)=h_x$. This implies that $h_x=0$ and in turn that $g_x=0$, which implies that $f(x,y)$ is reducible, a contradiction. \end{proof} \subsection{Factorization in $R[x]$} \subsubsection{Quadratic over characteristic $\ne 2$} The primitive polynomial $ax^2+bx+c$ factors if and only if $b^2-4ac$ is a square in $R$, in which case the factors are the primitive parts of $2ax+b\pm \sqrt{b^2-4ac}$. \subsubsection{Quadratic in $R[X]$ for $R=\mathbb{F}_{2^k}[x_1,\dots,x_n]$} We wish to determine if $X^2+AX+B$ has a root in $R$. Since $X_0+A$ is a root if $X_0$ is, at least one of the two roots does not have $\operatorname{lt}(A)$ as a term. (It very well may be the case that both roots have a monomial matching $\operatorname{lm}(A)$, but then both corresponding coefficients must be different from the leading coffcient of $A$). Therefore, we make the important assumption that \emph{we are searching for a root $X_0$ with $\operatorname{lt}(A)$ not a term of $X_0$}. Let $m$ denote the leading term of $X_0$. By taking leading terms in $X_0^2+AX_0+B$ and applying the assumption, we have \begin{equation*} \operatorname{lt}(m^2+\operatorname{lt}(A)m) = \operatorname{lt}(B)\text{,} \quad \text{and} \quad m \neq \operatorname{lt}(A)\text{.} \end{equation*} For any specific given terms $\operatorname{lt}(A)$, $\operatorname{lt}(B)$, this equation is easy to solve for $m$ or to determine that there is no solution. \begin{align*} \operatorname{lm}(m)>\operatorname{lm}(A)&: \quad m = \sqrt{\operatorname{lt}(B)}\\ \operatorname{lm}(m)=\operatorname{lm}(A)&: \quad m = \zeta /\operatorname{lc}(A)\sqrt{\operatorname{lm}(B)}\text{,} \quad \zeta^2+\zeta =\operatorname{lc}(B)/\operatorname{lc}(A)^2\\ \operatorname{lm}(m)<\operatorname{lm}(A)&: \quad m = \operatorname{lt}(B)/\operatorname{lt}(A) \end{align*} Once $m$ is found, the equation satisfied by $X_0-m$ has the same $A$ and a new $B$ with a smaller leading monomial. In this way the solution may be written down in order, and this process is a simplification of Sections 4 and 5 in \cite{QuadraticFactor}, which does not present a sparse algorithm due to the many (possibly disastrous) divisions performed. The quadratic $\zeta^2+\zeta+c \in \mathbb{F}_{2^k}$ has a root if and only if $\operatorname{Tr}(c)=0$, in which case $c=\sum_{i=1}^{k-1}c^{2^i}\sum_{j=0}^{i-1}u^{2^j}$ is a root where $u$ is any element of $\mathbb{F}_{2^k}$ with $\operatorname{Tr}(u)=1$. If $\mathbb{F}_{2^k} = \mathbb{F}_2[\theta]/P(\theta)$, then $u=1/(\theta P'(\theta))$ will do. \subsubsection{Cubic over $\mathbb{Z}$} To factor a cubic over $\mathbb{Z}$, we first find the roots over the more friendly ring $\mathbb{Z}_2$ and then test these roots over $\mathbb{Z}$. Since it is easy to bound the roots over $\mathbb{Z}$, the roots over $\mathbb{Z}_2$ only need to be calculated to some finite precision $p$, that is, to order $O(2^p)$. Factor $x^3+2^\alpha ax+2^\beta b $ over $\mathbb{Z}_2$ where $\alpha, \beta\geq 0$ and $a, b$ are odd integers: \begin{enumerate} \item $2\beta=3\alpha$: irreducible, as replacing $x\leftarrow 2^{\beta/3}y$ has no roots modulo $2$ for $y$. \item $ 2\beta< 3\alpha$: \begin{enumerate} \item $3\nmid \beta$: irreducible as all roots have valuation $\beta/3$. \item $3\mid \beta$: Replacing $x\leftarrow 2^{\beta/3}y$ gives $y^3+2^{\alpha-2\beta/3}a y+b=0$, which factors as $(y^2+y+1)(y+1)=0$ modulo $2$. Hence there is a unique root in $\mathbb{Z}_2$, and this root has valuation $\beta/3$. \end{enumerate} \item $2\beta > 3\alpha$: Replacing $x\leftarrow 2^{\beta-\alpha}y$ gives $2^{2\beta-3\alpha}y^3+ay+b=0$, which has $y=1$ mod $2$ as a root. This gives a factorization $$2^{2\beta-3\alpha}y^3+ay+b=(y+r)(2^{2\beta-3\alpha}y^2-2^{2\beta-3\alpha}ry+s)$$ for some odd $r, s\in \mathbb{Z}_2$. This becomes $$ (x+2^{\beta-\alpha}r)(x^2-2^{\beta-\alpha}rx+2^\alpha s)=0$$ \begin{enumerate} \item $2\nmid \alpha$: quadratic is irreducible and $-2^{\beta-\alpha}r$ is the only root. \item $2\mid \alpha$: assuming the square roots exist, the roots of the quadratic, which have valuation $\alpha/2$, are \begin{equation*} 2^{\beta-\alpha-1}r \pm 2^{\alpha/2} \sqrt{2^{2\beta-3\alpha-2}r^2-s} \end{equation*} If $r$ and $s$ are calculated to some absolute precision $O(2^p)$, then this expression is also known to absolute precision $O(2^p)$ except when $\alpha=0$ and $\beta=1$, in which case the square root loses more than one bit of precision. \end{enumerate} \end{enumerate} \subsection{Factorization in $K[x,y]$} For $K=\mathbb{Q}$, an irreducible bivariate polynomial $f(x,y)$ remains irreducible modulo $y=y_0$ for a generic $y_0 \in \mathbb{Q}$. Hence, all of the difficult recombination may be pushed to the univariate factorization. When $K=\mathbb{F}_q$ the recombination in \cite{GlobalFactor} is necessary. \subsubsection{Bivariate factorization over $\mathbb{Q}$} We begin with $f(x,y)$ satisfying \begin{enumerate} \item $f(x,y) \in \mathbb{Z}[x,y]$ and $f(x,0) \in \mathbb{Z}[x]$ are squarefree so that we can lift. \item $f(x,y)$ is primitive with respect to $x$ (i.e. $\op{cont}_x(f) \in \mathbb{Z}[y]$ is $1$) so that any factor is also primitive with respect to $x$. \item $\op{deg}_x (f(x,y)) = \op{deg}_x (f(x,0))$ (i.e. $\op{lc}_x(f)$ does not vanish at $y=0$) so that we can make $f$ monic. \end{enumerate} Let \begin{equation*} \tilde{f}(x,y) = f(x,y) / \op{lc}_x (f(x,y)) \in \mathbb{Q}[[y]][x] \end{equation*} be the monic version of $f$ computed to precision $O(y^{1 + \op{deg}_y f})$. We can factor $\tilde{f}(x,0) \in \mathbb{Q}[x]$ by a univariate algorithm and lift the factors to produce an irreducible factorization in $\mathbb{Q}[[y]][x]$ as \begin{equation*} \tilde{f}(x,y) = \prod_{i=1}^{l} \tilde{f}_i(x,y)\text{.} \end{equation*} The $\tilde{f}_i(x,y)$ are also monic and need to be computed to precision $O(y^{1 + \op{deg}_y f})$. For each subset $S$ of $\{1,\dots, l\}$, we then have the candidate true factor \begin{equation*} \op{ppart}_x \left(\op{lc}_x(f) \prod_{i \in S} \tilde{f}_i(x,y) \right)\text{,} \end{equation*} where, before taking the primitive part, the elements of $\mathbb{Q}[[y]][x]$ must be mapped to $\mathbb{Q}[y][x]$ via remainder upon division by $y^{1 + \op{deg}_y f}$. Since we are only interested in candidate factors over $\mathbb{Z}$, $\mathbb{Q}$ may be replaced by $\mathbb{Z}/p^k \mathbb{Z}$ for appropriate $p^k$ (in particular $p \nmid \op{lc}_x (f(x,0))$). The coefficients in $\mathbb{Z}/p^k \mathbb{Z}$ must then be mapped to $\mathbb{Z}$ via the symmetric remainder before taking the primitive part. \subsubsection{Bivariate Factorization over $\mathbb{F}_q$} We begin with $f(x,y) \in \mathbb{F}_q[x,y]$ and an irreducible $\alpha(y) \in \mathbb{F}_q[y]$ (with $\mathbb{F}_{q^k} := \mathbb{F}_q[y]/\alpha(y)$) such that \begin{enumerate} \item $\alpha(y)$ does not divide $\op{lc}_x f(x,y)$ so that we can make $f$ monic. \item $f(x,y) \bmod \alpha(y) \in \mathbb{F}_{q^k}[x]$ is squarefree so that we can lift. \item $f(x,y)$ is primitive with respect to $x$. \end{enumerate} The irreducible factorization of $f(x,y) \bmod \alpha(y)$ can be lifted to a monic factorization in $\mathbb{F}_q[[\alpha(y)]][x]$. With the help of some linear algebra over $\mathbb{F}_p$ these factors can be recombined into true factors. \subsection{Factorization in $R[x_1,\dots,x_n][X]$} Factoring of a multivariate squarefree primitive polynomial $f$ over $R[x_1,...,x_n][X]$ (satisfying the assumptions of Section \ref{section_sqfr} works by reducing $f$ modulo the ideal \begin{equation*} \langle x_1 = \alpha_1, x_2 = \alpha_2, \dots, x_n = \alpha_n \rangle \end{equation*} for some $\alpha_i \in R$, factoring the resulting univariate into, say, $r$, factors, and then lifting the univariate factorization to a multivariate factorization. The evaluation points must be good in the sense that $f(\alpha_1, \dots, \alpha_n, X)$ is squarefree and has the same degree as $f(x_1, \dots, x_n, X)$ in $X$. This lifting process does not change the leading coefficients in $X$, hence it is necessary that the leading coefficients be ``correct" before the lifting. In the most general setting, we can determine $d_i \in R[x_1,...,x_n]$, such that it is known that $d_i$ divides the leading coefficient of the $i$-th lifted factor. Then, before lifting, we compute $m=\operatorname{lc}_X(f)/(d_1 \cdots d_r)$, impose a leading coefficient of $d_i m$ on the $i$-th factor, and multiply $f$ by $m^{r-1}$. If the lifting succeeds, then the actual factors can be obtained by taking principle parts. Doing no work to precompute leading coefficients corresponds to taking $d_i=1$, which can obviously lead to large swells. \subsubsection{Wang's leading coefficient computation} Wang \cite{WANG} has a good solution to the leading coefficient problem over $\mathbb{Z}$. The idea can be illustrated by a simple example. \begin{equation*} (2x_1^3 x_2+2x_1^3 x_2)X^2 + \cdots = (2x_1(x_1+x_2)X+x_1)(x_1 x_2 X + 6) \end{equation*} First the irreducible factorization of the leading coefficient is computed \begin{equation*} (2x_1^2 x_2+2x_1^2 x_2)=2x_1^2x_2(x_1+x_2) \end{equation*} Next, an evaluation point $x_i=\alpha_i$ such that there exists primes $p_i$ such that \begin{align*} &p_3 \mid \alpha_1 + \alpha_2, \quad p_3 \nmid \alpha_2, \quad p_3 \nmid \alpha_1,\\ &p_2 \mid \alpha_2, \quad p_2 \nmid \alpha_1,\\ &p_1 \mid \alpha_1 \end{align*} Lets take $\alpha_1=10, \alpha_2=14$ and $p_1=5, p_2=7, p_3=3$. The univariate factorization comes out as \begin{equation*} 20(48X+1)(70X + 3) \end{equation*} What is of interest here is the leading coefficients of the primitive factors over $\mathbb{Z}$. From $p_3=3$ we can correctly distribute $x_1+x_2$ to the first multivariate factor. From $p_2=7$ we can distribute $x_2^2$ to both factors, and from $p_1=5$, we can distribute $x_1$ to the second factor. When $R$ is a finite field, there is no useful notion of ``prime''. Furthermore, the probability that an irreducible univariate factorization can be lifted to a multivariate factorization is low and sometimes zero. Hence this does not work as stated. One may replace $R$ by $R[Y]$ for an auxiliary indeterminate $Y$ and consider polynomial substitutions of the form \begin{align*} x_1 &= \alpha_1 + \beta_1 Y + \gamma_1 Y^2 + \cdots\\ x_2 &= \alpha_2 + \beta_2 Y + \gamma_2 Y^2 + \cdots\\ &\cdots\\ x_n &= \alpha_n + \beta_n Y + \gamma_n Y^2 + \cdots\text{.} \end{align*} The base case factorization is now not $R[X]$ but $R[Y][X]$. The points $\alpha_1, ..., \alpha_n$ still need to be good because the lifting will ultimately begin with univariates. However, the univariate factors come not from an irreducible univariate factorization, but from the $Y=0$ image of a bivariate factorization, which should greatly increases the changes of success in the lifting. \subsubsection{Kaltofen's leading coefficient computation} In this recursive approach \cite{KALTOFEN}, after substituting away all but \emph{two} of the variables, the bivariate polynomial is factored and the leading coefficients of the bivariate factors can be lifted against the leading cofficient of the original polynomial. Since only squarefree lifting is implemented, it is actually the squarefree parts of everything that are lifted. \subsubsection{Dense Hensel lifting} Some pseudocode is in Section \ref{Pseudocode}. Of note here is that when lifting over $\mathbb{Z}$, we do not lift over $\mathbb{Z}/p^k\mathbb{Z}$ as Wang \cite{WANG} advises but do the lifting directly over $\mathbb{Z}$. \subsubsection{Sparse Hensel lifting} Sparse Zippel interpolation applies directly to the lifting proceedure (\cite{SHLZIP}, \cite{SHL}). Suppose we have a given factorization into three factors $A$, $B$, $C$, \begin{equation*} F(x_1, x_2, x_3, x_4) = (A B C)(x_1, x_2, \alpha_3, \alpha_4) \mod \langle x_3 =\alpha_3, x_4=\alpha_4 \rangle\text{,} \end{equation*} and we would like to lift this to a factorization modulo only $\langle x_4=\alpha_4 \rangle$. This amounts to finding $A(x_1, x_2, x_3, \alpha_4)$ (ditto for $B$ and $C$ as well). If we apply Zippel's probabalistic assumption that no new monomial in $x_1$ and $x_2$ appear when lifting from $A(x_1, x_2, \alpha_3, \alpha_4)$ to $A(x_1, x_2, x_3, \alpha_4)$, then the latter can be guessed by evaluation and interpolation using a basecase bivariate lifter. In general, the lifting of $x_m = \alpha_m$ can be accomplished using a basecase lifter in any number of variables in the interval $[2,m-1]$: currently the basecase always uses $2$ variables and Algorithm \ref{algo_mlift} or \ref{algo_mlift2}. \section{Absolute Factorization} The goal of absolute factorization is to take an irreducible $f \in R[x_1, \dots, x_n]$ and either determine that $f$ is absolutely irreducible or provide a factorization \begin{equation*} f = g h \text{,} \quad g, h \in R'[x_1, \dots, x_n] \end{equation*} where $g$ is absolutely irreducible. $h$ may or may not be absolutely irreducible: it is simply the product of the rest. \subsection{Absolute Irreduciblity Testing} Here we follow Gao \cite{GAO}. For a multivariate polynomial $f = \sum_{\bold{i} \in \mathbb{Z}^n}{c_{\bold{i}} \, \pmb{x}^{\bold{i}}}$, the Newton polygon $N(f)$ is defined to be the convex hull of $\{\bold{i} \in \mathbb{Z}^n | c_{\bold{i}} \ne 0\}$ in $\mathbb{R}^n$. Since $N(fg) = N(f) + N(g)$ where $+$ denotes the Minkowski sum, if $N(f)$ is indecomposable, then $f$ is absolutely irreducible. Although indecomposability testing is hard, Gao gives a reasonable algorithm in two dimensions \cite{GAO2}, that is, for bivariate polynomials, and projects higher dimensional polytopes onto a two-dimensional ``shadow'' to test them for indecomposability. If $f \in K[\pmb{x}]$ happens to be irreducible over $K$ but not over the algebraic closure $\overline{K}$, then $N(f)$ will never be sufficient to prove the irreducibility over $K$. In the case that we are able to prove that $f$ is irreducible over $K$ using other methods, $N(f)$ can still be used to obtain some information on the degree of an extension of $K$ needed to factor $f$ absolutely. An absolute factorization of an irreducible $f(\pmb{x}) \in K[\pmb{x}]$ looks like \begin{equation*} f(\pmb{x}) = \operatorname{resultant}_{\alpha} (u(\alpha), g(\alpha, \pmb{x})) \end{equation*} for some irreducible $u(\alpha) \in K[\alpha]$ of degree, say, $m$. Since all $m$ of the $g(\alpha, \pmb{x})$ have the same Newton polygon, it follows that $N(f)=m\cdot N(g)$, and thus $m$ divides the coordinates of every vertex in $N(f)$. This can severely limit the possibilities for the extension degree required for an absolute factorization. \subsection{Bivariate Absolute Factorization over $\mathbb{Q}$} The idea here is that an absolutely irreducible $g(x,y) \in \overline{\mathbb{Q}}[x,y]$ remains absolutely irreducible in $\overline{\mathbb{F}}_p[x,y]$ for generic $p$. Assume that $f(x,y) \in \mathbb{Q}[y][x]$ is irreducible. Pick a good $\alpha \in \mathbb{Q}$ and a good rational prime $p$. The definition of ``good'' is that none of the following steps or assumptions fail. Determine an $\mathbb{F}_q = \mathbb{F}_{p^?}$ such that $f(x,\alpha)$ splits completely into distinct linear irreducibles: \begin{equation*} \frac{f(x,\alpha)}{\operatorname{lc}_x(f(x,y)) |_{y=\alpha}} = \prod_i x - r_i \text{ in } \mathbb{F}_q[x]\text{.} \end{equation*} Lift this to power series: \begin{equation*} \frac{f(x,y)}{\operatorname{lc}_x(f(x,y))} = \prod_i x - r_i(y) \text{ in } \mathbb{F}_q[[y-\alpha]][x]\text{.} \end{equation*} Do some linear algebra to recombine the factors into a real factorization: \begin{equation*} f(x,y) = \prod_j g_j(x,y) \text{ in } \mathbb{F}_q[y][x]\text{.} \end{equation*} The $g_i(x,y) \in \mathbb{F}_q[y][x]$ are absolutely irreducible. It might be possible to reduce the size of $q$ at this point. We then try to lift this to a factorization in $\mathbb{Q}_q[y][x]$: \begin{equation*} f(x,y) = \prod_j \widetilde{g}_j(x,y) \text{ in } \mathbb{Q}_q[y][x]\text{.} \end{equation*} In order to attemp this lift the $\operatorname{lc}_x(\widetilde{g}_j(x,y)) \in \mathbb{Q}_q[y]$ must be correct before starting. Assume $\operatorname{lc}_x(f(x,y))$ is monic in $y$, and that its squarefree part remains squarefree modulo $p$. Then, the squarefree factors of the $\operatorname{lc}_x \widetilde{g}_j(x,y)$ can be lifted and we can recover the monic $\operatorname{lc}_x(\widetilde{g}_j(x,y)) \in \mathbb{Q}_q[y]$. Finally, we map $\widetilde{g}_1(x,y)$ to some number field $K[x,y]$ (so that the other $\widetilde{g}_j(x,y)$ are its conjugates) and test divisibility $g_1|f$. \subsection{Bivariate Absolute Factorization over $\mathbb{F}_q$} \subsection{Multivariate Absolute Factorization} For absolutely factoring an irreducible in $R[x_1,\dots,x_n][X]$, the plan is to substitute good auxiliary polynomials \begin{align*} x_1 &= \alpha_1 + \beta_1 Y + \gamma_1 Y^2 + \cdots\\ x_2 &= \alpha_2 + \beta_2 Y + \gamma_2 Y^2 + \cdots\\ &\cdots\\ x_n &= \alpha_n + \beta_n Y + \gamma_n Y^2 + \cdots\text{,} \end{align*} and absolutely factor the resulting bivariate in $R[X,Y]$, and then lift the $Y=0$ images of the two factors back to a multivariate factorization. This would require the fact that an absolutely irreducible multivariate remains an absolutely irreducible bivariate under a generic substitution of this form. \begin{thebibliography}{99} \bibitem{Brown} W. S. Brown. On Euclid’s Algorithm and theComputation of Polynomial Greatest Common Divisors. J. ACM 18 (1971), 478-504. \bibitem{Johnson} Johnson, S.C.: Sparse polynomial arithmetic. ACM SIGSAM Bulletin 8 (3), pp. 63--71, 1974 \bibitem{FPS} Monagan M., Pearce R.: Sparse polynomial powering using heaps. Computer Algebra in Scientific Computing, Springer, 2012, s.236-247. \bibitem{ZIPPEL} Zippel, R.E.: Probabilistic algorithms for sparse polynomials. Lecture Notes in Computer Science. 72. pp. 216--226. 1979 \bibitem{SHLZIP} Zippel, R.E.: Newton’s iteration and the sparse Hensel algorithm. Proceedings of SYMSAC ’81, pp. 68--72. ACM Press (1981) \bibitem{SHL} Monagan M., Tuncer B., The complexity of sparse Hensel lifting and sparse polynomial factorization. Journal of Symbolic Computation. 99. pp. 189--230. 2020 \bibitem{LINZIP} J. de Kleine, M. Monagan and A. Wittkopf, Algorithms for the non-monic case of the sparse modular GCD algorithm. Proceedings of ISSAC ’05, ACM Press, pp. 124--131. 2005 \bibitem{SULING} Yang, Suling. Computing the Greatest Common Divisor of Multivariate Polynomials over Finite Fields. http://www.cecm.sfu.ca/CAG/theses/suling.pdf \bibitem{BMAR} The Berlekamp-Massey Algorithm revisited, N. B. Atti, G. M. Diaz–Toca, H. Lombardi, 9 March 2006 \bibitem{YAP} A Unified Approach to HGCD Algorithms for polynomials and integers by Klaus Thull , Chee K. Yap \bibitem{GlobalFactor} Factoring polynomials over global fields Belabas, Karim; van Hoeij, Mark; Klüners, Jürgen; Steel, Allan Journal de théorie des nombres de Bordeaux, Volume 21 (2009) no. 1, p. 15-39 \bibitem{EZGCD} P. S. Wang, The EEZ-GCD Algorithm, ACM SIGSAM Bulletin 14, pp. 50--60, 1980 \bibitem{WANG} P. S. Wang, An improved multivariate polynomial factoring algorithm. Mathematics of Computation 32, no. 144, 1215--1231, 1978 \bibitem{GAO} S. Gao, Absolute irreducibility of polynomials via Newton polytopes, Journal of Algebra 237 (2001), 501--520. \bibitem{GAO2} S. Gao and A.G.B. Lauder, Decomposition of polytopes and polynomials, Discrete and Computational Geometry 26 (2001), 89--104. \bibitem{QuadraticFactor} Jørgen Cherly, Luis Gallardo, Leonid Vaserstein and Ethel Wheland: Solving Quadratic Equations over Polynomial Rings of Characteristic Two. Publicacions Matemàtiques, Vol. 42, No. 1 (1998), pp. 131-142 \bibitem{KALTOFEN} E. Kaltofen. Sparse Hensel lifting. In EUROCAL 85 European Conf. Comput. Algebra Proc. Vol. 2, pages 4–17, 1985 \end{thebibliography} \section{Pseudocode} \label{Pseudocode} \subsection{gcd} For the dense gcd over finite fields, if one runs out of primes of the form $x-\alpha$, instead of failing it is possible to use any irreducible polynomial in place of $x-\alpha$ in Algorithm \ref{algo_brownp}, and this would constitute the large prime version of the algorithm. \begin{algorithm}[H] \DontPrintSemicolon \KwIn{ \begin{enumerate} \item $A,B \in \mathbb{F}_q[x][x_1, \dots, x_n]$ neither is zero \end{enumerate} } \KwOut{ \begin{enumerate} \item monic $G= \op{gcd}(A,B)$, $\bar{A}=A/G$, $\bar{B}=B/G$ \end{enumerate} } \lIf{$n=0$}{\textbf{return} using univariate arithmetic} set $cA= \op{cont}_{x_1,\dots, x_n}(A)$ and $ cB=\op{cont}_{x_1, \dots, x_n}(B) \in \mathbb{F}_p[x]$\; set $A= A/cA$ and $B=B/cB$ \tcp*{content $cA, cB, \dots$ is always monic} set $cG= \op{gcd}(cA, cB)$, $c\bar{A}=cA/cG$ and $c\bar{B}=cB/cG$\; set $\gamma=\op{gcd}(\op{lc}_{x_1,\dots, x_n}(A),\op{lc}_{x_1,\dots, x_n}(B))\in \mathbb{F}_q[x]$\; set $bound= 1+ \op{deg}_{x}\gamma+ \max(\op{deg}_x(A), \op{deg}_x(B))$, and set $m=1\in \mathbb{F}_p[x]$\; \texttt{pick a prime}: \tcp*{primes are $(x-\alpha)$} choose a new $\alpha\in \mathbb{F}_q$ else \textbf{return} FAIL\; set $\gamma^*=\gamma\op{mod} {(x-\alpha)}$\; set $A^*=A \op{mod} (x-\alpha)$ and $B^*=B\op{mod} (x-\alpha)\in \mathbb{F}_q[x_n][x_1,\dots,x_{n-1}]$\; \lIf{$\gamma^*=0$}{\textbf{goto} \texttt{pick a prime}} set $(G^*,\bar{A}^*, \bar{B}^*)= \textbf{brownp}(A^*,B^*)$ or \textbf{goto} \texttt{pick a prime} if the call failed\; \lIf{$G^*=1$} {set $G=1, A=\bar{A},B=\bar{B}$, \textbf{goto} \texttt{put content}} \If{$\op{deg}_x(m)>0$} {\lIf{$\op{lm}_{x_1, \dots,x_n}(G^*)<\op{lm}_{x_1, \dots,x_n}(G)$}{set $m=1$}\lIf{$\op{lm}_{x_1, \dots,x_n}(G^*)>\op{lm}_{x_1, \dots,x_n}(G)$}{\textbf{goto} \texttt{pick a prime}} } set $\bar{A}=\op{crt}(\bar{A} \op{mod} m,\ \bar{A}^* \op{mod} \ (x-\alpha))$ and $\bar{B}=\op{crt}(\bar{B} \op{mod} m,\ \bar{B}^* \op{mod} \ (x-\alpha))$\; \label{algo_brownp_abcrt} \If{$\bar{A}$ did not change and, with $T=\bar{A}/\op{cont}_{x_1, \dots, x_n}(\bar{A})$, $T\mid A$ and $A/T\mid B$ \label{algo_brownp_astab}} { set $G=A/T$, $\bar{A}=T$ and $\bar{B}={B}/G$, \textbf{goto} \texttt{fix lcs} } set $G=\op{crt}(G \op{mod} m,\ \gamma^*\cdot G^* \op{mod} \ (x-\alpha))$ and $m= m \cdot (x-\alpha)$\; \label{algo_brownp_gcrt} \If{$G$ did not change and, with $T=G/\op{cont}_{x_1,\dots,x_n}(G)$, $T \mid A$ and $T\mid B$ \label{algo_brownp_gstab}}{set $G=T$, $\bar{A}=\bar{A}/G$ and $\bar{B}=B/G$, \textbf{goto} \texttt{fix lcs}} \lIf{$\op{deg}_x(m)< bound$}{\textbf{goto} \texttt{pick a prime}} \lIf{$\op{deg}_x\gamma+\op{deg}_xA=\op{deg}_xG+\op{deg}_x\bar{A}$ and $\op{deg}_x\gamma+\op{deg}_xB=\op{deg}_xG+\op{deg}_x\bar{B}$}{\textbf{goto} \texttt{success}} set $m=1$, \textbf{goto} \texttt{pick a prime} \texttt{success:}\; set $G=G/\op{cont}_{x_1,\dots, x_n}(G)$, $A=A/\op{lc}_{x_1,\dots, x_n}(G)$ and $B=B/\op{lc}_{x_1,\dots, x_n}(G)$\; \texttt{put content:}\; set $G=G \cdot cG$, $\bar{A}=\bar{A}\cdot c\bar{A}$ and $\bar{B}=\bar{B}\cdot c\bar{B}$\; \Return{$(G, \bar{A}, \bar{B})$}\; \texttt{fix lcs:}\; with $\delta = \op{lc}_{x,x_1,\dots, x_n}(G)$, set $G=\delta^{-1} G$, $A=\delta A$ and $B=\delta B$, \textbf{goto} \texttt{put content} \caption{$\textbf{brownp}$ dense gcd over finite field} \label{algo_brownp} \end{algorithm} On lines \ref{algo_brownp_abcrt} and \ref{algo_brownp_gcrt}, the inputs $G, \bar{A}, \bar{B}$ are undefined only when $m=1$, in which case the $\op{crt}$ ignores them anyways. There should also be a check analogous to line \ref{algo_brownp_astab} for the stabilization of $\bar{B}$. This was omitted simply due to space constraints. Finally, the stability checks in lines \ref{algo_brownp_astab} and \ref{algo_brownp_gstab} (and the missing one for $\bar{B}$) are completely optional and may be executed or skipped on every iteration at the user's discretion. Similarly to the previous algorithm, divisibility checks could be performed over the integers as well. \begin{algorithm}[H] \DontPrintSemicolon \KwIn{ $n \ge 1$ \begin{enumerate} \item $A,B \in \mathbb{Z}[x_1, \dots, x_n]$ neither is zero \end{enumerate} } \KwOut{ \begin{enumerate} \item unit normal $G= \op{gcd}(A,B)$, $\bar{A}=A/G$, $\bar{B}=B/G$ \end{enumerate} } set $cA= \op{cont}_{x_1,\dots, x_n}(A)$ and $cB=\op{cont}_{x_1, \dots, x_n}(B) \in \mathbb{Z}$\; set $A= A/cA$ and $B=B/cB$ \tcp*{content $cA, cB, \dots$ is always positive} set $cG= \op{gcd}(cA, cB)$, $c\bar{A}=cA/cG$ and $c\bar{B}=cB/cG$\; set $\gamma=\op{gcd}(\op{lc}_{x_1,\dots, x_n}(A),\op{lc}_{x_1,\dots, x_n}(B))\in \mathbb{Z}[x]$\; set $bound= 2 \cdot \gamma \cdot \max(|A|_{\infty}, |B|_{\infty})$, and set $m=1 \in \mathbb{Z}$\; \texttt{pick a prime}: \tcp*{primes are numbers} choose a new prime $p \in \mathbb{Z}$ else \textbf{return} FAIL\; set $\gamma^*=\gamma\op{mod} p$\; set $A^*=A \op{mod} p$ and $B^*=B\op{mod} p\in \mathbb{F}_p[x_n][x_1,\dots,x_{n-1}]$\; \lIf{$\gamma^*=0$}{\textbf{goto} \texttt{pick a prime}} set $(G^*,\bar{A}^*, \bar{B}^*)= \textbf{brownp}(A^*,B^*)$ or \textbf{goto} \texttt{pick a prime} if the call failed\; \lIf{$G^*=1$} {set $G=1, A=\bar{A},B=\bar{B}$, \textbf{goto} \texttt{put content}} \If{$m>1$} {\lIf{$\op{lm}_{x_1, \dots,x_n}(G^*)<\op{lm}_{x_1, \dots,x_n}(G)$}{set $m=1$}\lIf{$\op{lm}_{x_1, \dots,x_n}(G^*)>\op{lm}_{x_1, \dots,x_n}(G)$}{\textbf{goto} \texttt{pick a prime}} } set $\bar{A}=\op{crt}(\bar{A} \op{mod} m,\ \bar{A}^* \op{mod} p)$ and $\bar{B}=\op{crt}(\bar{B} \op{mod} m,\ \bar{B}^* \op{mod} p)$\; set $G=\op{crt}(G \op{mod} m,\ \gamma^*\cdot G^* \op{mod} p)$ and $m= m \cdot p$\; \lIf{$m< bound$}{\textbf{goto} \texttt{pick a prime}} set $hA = \min(|G|_1 \cdot |\bar{A}|_\infty, |G|_\infty \cdot |\bar{A}|_1)$ \tcp*{upper bound on $|G\cdot\bar{A}|_\infty$} set $hB = \min(|G|_1 \cdot |\bar{B}|_\infty, |G|_\infty \cdot |\bar{B}|_1)$ \tcp*{upper bound on $|G\cdot\bar{B}|_\infty$} \lIf{$hA < m$ and $hB < m$}{\textbf{goto} \texttt{success}} \textbf{goto }\texttt{pick a prime} \texttt{success:}\; set $G=G/\op{cont}_{x_1,\dots, x_n}(G)$, $A=A/\op{lc}_{x_1,\dots, x_n}(G)$ and $B=B/\op{lc}_{x_1,\dots, x_n}(G)$\; \texttt{put content:}\; set $G=G \cdot cG$, $\bar{A}=\bar{A}\cdot c\bar{A}$ and $\bar{B}=\bar{B}\cdot c\bar{B}$\; \Return{$(G, \bar{A}, \bar{B})$}\; \caption{$\textbf{brownm}$ dense gcd over integers} \label{algo_brownm} \end{algorithm} \subsection{factoring} The lifting algorithms with be stated with $3$ factors. The expression $[(x-\alpha)^k] f(x)$ denotes the $k^{\text{th}}$ Taylor coefficient of $f(x)$ when expanded about $x=\alpha$. That is, \begin{equation*} [(x-\alpha)^k] f(x) = c_k \quad \text{ when } \quad f(x) = \sum_{k} c_k (x-\alpha)^k\text{.} \end{equation*} \begin{algorithm}[H] \DontPrintSemicolon \KwIn{ $m \ge 2$ \begin{enumerate} \item $(\alpha_1, \dots, \alpha_m) \in R^m$ \item $A \in R[x_1, \dots, x_m][X]$ with $A(X, \alpha_1, \dots, \alpha_m)$ squarefree \item $(B_1, B_2, B_3) \in R[x_1, \dots, x_m][X]$ (however, all but the leading coefficients of each $B_i$ are in $R[x_1, \dots, x_{m-1}]$) such that $A(X, x_1, \dots, x_{m-1}, \alpha_m) = (B_1 B_2 B_3)(X, x_1, \dots, x_{m-1}, \alpha_m)$ \end{enumerate} } \KwOut{ \begin{enumerate} \item $(B_1, B_2, B_3) \in R[x_1, \dots, x_m][X]$ such that $A(X, x_1, \dots, x_m) = (B_1 B_2 B_3)(X, x_1, \dots, x_m)$ or FAIL \end{enumerate} } set $e = A - B_1 B_2 B_3$ \tcp*{current error} set $\beta_i = B_i(X, x_1, \dots, x_{m-1}, \alpha_m) \in R[x_1, \dots, x_{m-1}][X]$\; \For{$j=1$ \KwTo $\op{deg}_{x_m}(A)$} { assert that $e$ is divisible by $(x_m - \alpha_m)^j$\; set $t =$ taylor coefficient of $(x_m - \alpha_m)^j$ in $e$ \tcp*{ $t \in R[x_1, \dots, x_{m-1}][X]$} $(\delta_1, \delta_2, \delta_3) = \textbf{pfrac}(t, (\beta_1, \beta_2, \beta_3),(\alpha_1, \dots,\alpha_{m-1}), (\op{deg}_{x_1}A, \dots, \op{deg}_{x_{m-1}}A))$ \; \tcp*{solve $t = \delta_1 \beta_2 \beta_3 + \delta_2 \beta_1 \beta_3 + \delta_3 \beta_1 \beta_2$} \lIf{the solved failed}{\Return{FAIL}} set $B_i = B_i + \delta_i (x_m - \alpha_m)^j$ for each $i$\; set $e = A - B_1 B_2 B_3$ } \leIf{$e=0$}{ \Return{$(B_1, B_2, B_3)$} } { \Return{FAIL} } \caption{$\textbf{hlift}$ (Multivariate Hensel Lifting - Quintic version)} \label{algo_mlift} \end{algorithm} Since the solutions $\delta_i$ must satisfy $\op{deg}_{X} \delta_i < \op{deg}_{X} B_i$, the leading coefficients of the $B_i$ will not be changed by Algorithm \ref{algo_mlift}. This quintic version updates the error inefficiently via \begin{align*} B_i &= B_i \delta_i(x_m - \alpha_m)^j\text{,} \\ e &= A - B_1 B_2 B_3\text{.} \end{align*} If the number of factors is not too high, the space requirements of calculating only the required Taylor coefficient of $e$ are not too great. Again, this is stated for three factors. \newpage \begin{algorithm}[H] \DontPrintSemicolon \KwIn{ $m \ge 2$ \begin{enumerate} \item $(\alpha_1, \dots, \alpha_m) \in R^m$ \item $F \in R[x_1, \dots, x_m][X]$ with $F(X, \alpha_1, \dots, \alpha_m)$ squarefree \item $(A, B, C) \in R[x_1, \dots, x_m][X]$ (however, all but the leading coefficients of each $A,B,C$ are in $R[x_1, \dots, x_{m-1}]$) such that $F(X, x_1, \dots, x_{m-1}, \alpha_m) = (A B C)(X, x_1, \dots, x_{m-1}, \alpha_m)$ \end{enumerate} } \KwOut{ \begin{enumerate} \item $(A, B, C) \in R[x_1, \dots, x_m][X]$ such that $F(X, x_1, \dots, x_m) = (A B C)(X, x_1, \dots, x_m)$ or FAIL \end{enumerate} } set $a_0 = [(x_m - \alpha_m)^0] A$ and set $dA = 0$\; set $b_0 = [(x_m - \alpha_m)^0] B$ and set $dB = 0$\; set $c_0 = [(x_m - \alpha_m)^0] C$ and set $dC = 0$\; \For{$d=1$ \KwTo $\op{deg}_{x_m}(A)$} { set $t = [(x_m - \alpha_m)^d]F - \sum_{\substack{i+j+k=d \\ i \le dA, \ j \le dB, \ k \le dC}} a_i b_j c_k$\; use \textbf{pfrac} to find $a_d, b_d, c_d$ from $t=a_d b_0 c_0+a_0 b_d c_0+a_0 b_0 c_d$\; \lIf{the solved failed}{\Return{FAIL}} set $a_d = a_d + [(x_m - \alpha_m)^d]A$\; set $b_d = b_d + [(x_m - \alpha_m)^d]B$\; set $c_d = c_d + [(x_m - \alpha_m)^d]C$\; \lIf{ $a_d \neq 0$}{set $dA = d$} \lIf{ $b_d \neq 0$}{set $dB = d$} \lIf{ $c_d \neq 0$}{set $dC = d$} \lIf{$dA + dB + dC > \op{deg}_{x_m}(A)$}{\Return{FAIL}} } assert that $dA + dB + dC = \op{deg}_{x_m}(A)$\; set $A = \sum_{i=0}^{dA} a_i (x_m - \alpha_m)^i$\; set $B = \sum_{i=0}^{dB} b_i (x_m - \alpha_m)^i$\; set $C = \sum_{i=0}^{dC} c_i (x_m - \alpha_m)^i$\; \Return{(A,B,C)} \caption{$\textbf{hlift}$ (Multivariate Hensel Lifting - Quartic version)} \label{algo_mlift2} \end{algorithm} Finally the main work horse. It is easy to solve $t=\delta_1\beta_2\beta_3+\delta_2\beta_1\beta_3+\delta_3\beta_1\beta_2$ in $\op{frac}(R)(x_1,\dots,x_{m-1})[X]$ with pseudo remainder sequences -- since $\delta_i= t(\beta_j\beta_k)^{-1}\pmod {\beta_i}$ -- and check if the $\delta_i$'s are defined in $R[x_1,\dots, x_{m-1}][X]$. However, as intermediate expression swell is a problem in this approach. We will use a different algorithm that is akin to a dense interpolation of the solution. \begin{algorithm}[H] \DontPrintSemicolon \KwIn{ $l\geq 0$ \begin{enumerate} \item $t\in R[x_1,\dots, x_l][X]$ \item $(\beta_1,\beta_2,\beta_3)$, $\text{where } \beta_i\in R[x_1,\dots, x_{l}][X],$ $ \beta_i \text{ pairwise coprime in } \op{frac}{(R)}(x_1,\dots,x_{l})[X]$ \item $(\alpha_1,\dots,\alpha_l) \in R^l$ \item $(d_1,\dots, d_l)\in \mathbb{N}^l$ degree bounds \end{enumerate} } \KwOut{ \begin{enumerate} \item $(\delta_1,\delta_2,\delta_3), \delta_i\in R[x_1,\dots, x_r][X]\text{ such that }t=\delta_1\beta_2\beta_3+\delta_2\beta_1\beta_3+\delta_3\beta_1\beta_2$ and $\op{deg}_{X}\delta_i<\op{deg}_{X}\beta_i$ or \it{FAIL} \end{enumerate} } \eIf{$r=0$}{ set $\delta_i=t(\beta_j\beta_k)^{-1}\pmod {\beta_i} $ in $\op{frac}(R)[X]$\\ \leIf{ each $\delta_i\in R[X]$}{ \Return{$(\delta_1,\delta_2,\delta_3)$} } { \Return{FAIL} } } { set $\tilde{\beta}_i(X)=\beta_i(X,x_1,\dots,x_{r-1},\alpha_l)\in R[x_1,\dots,x_{l-1}][X]$\; set $\delta_i=0$ for each $i$\; set $e=t$\; \For{$j=0$ \KwTo $d_r$} { assert that $e$ is divisible by $(x_r - \alpha_r)^j$\; set $\tilde{t}=$ taylor coefficient of $(x_r-\alpha_r)^j$ in $e$\; set $(\tilde{\delta_1},\tilde{\delta}_2, \tilde{\delta}_3 )=\textbf{pfrac}(\tilde{t},(\alpha_1,\dots, \alpha_{l-1}),(\tilde{\beta}_1,\tilde{\beta}_2, \tilde{\beta}_3),(d_1,\dots, d_{l-1}))$\; \lIf{the solved failed}{\Return{FAIL}} set $\delta_i=\delta_i+\tilde{\delta}_i(x_r-\alpha_r)^j$\; set $e=t-(\delta_1\beta_2\beta_3+\delta_2\beta_1\beta_3+\delta_3\beta_1\beta_2)$ } \leIf{$e=0$}{ \Return{$(\delta_1, \delta_2, \delta_3)$} } { \Return{FAIL} } } \caption{\textbf{pfrac} (Multivariate partial fraction solver)} \label{algo_pfrac} \end{algorithm} \end{document} flint-3.1.3/src/mpoly/exp_bits_required.c000066400000000000000000000055461461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* !!! this file DOES need to change with new orderings */ /* compute number of bits required to store user_exp in packed format the returned number of bits includes space for a zero'd signed bit */ flint_bitcnt_t mpoly_exp_bits_required_ui(const ulong * user_exp, const mpoly_ctx_t mctx) { slong i, nfields = mctx->nfields; ulong max = 0; if (mctx->deg) { for (i = 0; i < nfields - 1; i++) { max += user_exp[i]; if (max < user_exp[i]) return 2*FLINT_BITS; } } else { for (i = 0; i < nfields; i++) { max |= user_exp[i]; } } return 1 + FLINT_BIT_COUNT(max); } /* compute number of bits required to store user_exp in packed format the returned number of bits includes space for a zero'd signed bit */ flint_bitcnt_t mpoly_exp_bits_required_ffmpz(const fmpz * user_exp, const mpoly_ctx_t mctx) { slong i, nvars = mctx->nvars; flint_bitcnt_t exp_bits; if (mctx->deg) { fmpz_t deg; fmpz_init(deg); for (i = 0; i < nvars; i++) { fmpz_add(deg, deg, user_exp + i); } exp_bits = 1 + fmpz_bits(deg); fmpz_clear(deg); } else { exp_bits = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t this_bits = fmpz_bits(user_exp + i); exp_bits = FLINT_MAX(exp_bits, this_bits); } exp_bits += 1; } return exp_bits; } /* compute number of bits required to store user_exp in packed format the returned number of bits includes space for a zero'd signed bit */ flint_bitcnt_t mpoly_exp_bits_required_pfmpz(fmpz * const * user_exp, const mpoly_ctx_t mctx) { slong i, nvars = mctx->nvars; flint_bitcnt_t exp_bits; if (mctx->deg) { fmpz_t deg; fmpz_init(deg); for (i = 0; i < nvars; i++) { fmpz_add(deg, deg, user_exp[i]); } exp_bits = 1 + fmpz_bits(deg); fmpz_clear(deg); } else { exp_bits = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t this_bits = fmpz_bits(user_exp[i]); exp_bits = FLINT_MAX(exp_bits, this_bits); } exp_bits += 1; } return exp_bits; } flint-3.1.3/src/mpoly/fill_marks.c000066400000000000000000000066071461254215100170620ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* Fill in the indices that partition A into univariate chunks. D will be allocated to at least one more than its length so that D->coeffs[D->length] = Alen */ void mpoly1_fill_marks( ulong ** Dcoeffs, slong * Dlength, slong * Dalloc, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx) { slong off0, shift0; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong i, N = mpoly_words_per_exp_sp(Abits, mctx); ulong e0; FLINT_ASSERT(mctx->ord == ORD_LEX); FLINT_ASSERT(mctx->nvars >= 1); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, Abits, mctx); *Dlength = 0; i = 0; while (i < Alen) { if (*Dalloc < *Dlength + 1) { *Dalloc = FLINT_MAX(*Dlength + 1, *Dalloc + *Dalloc/2); *Dcoeffs = FLINT_ARRAY_REALLOC(*Dcoeffs, *Dalloc, ulong); } (*Dcoeffs)[*Dlength] = i; *Dlength = *Dlength + 1; e0 = (Aexps[N*i + off0] >> shift0) & mask; while (1) { i++; if (i >= Alen) break; if (((Aexps[N*i + off0] >> shift0) & mask) != e0) break; } } if (*Dalloc < *Dlength + 1) { *Dalloc = FLINT_MAX(*Dlength + 1, *Dalloc + *Dalloc/2); *Dcoeffs = FLINT_ARRAY_REALLOC(*Dcoeffs, *Dalloc, ulong); } (*Dcoeffs)[*Dlength] = Alen; } /* Fill in the indices that partition A into bivariate chunks. D will be allocated to at least one more than its length so that D->coeffs[D->length] = Alen */ void mpoly2_fill_marks( ulong ** Dcoeffs, slong * Dlength, slong * Dalloc, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx) { slong off0, off1, shift0, shift1; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong i, N = mpoly_words_per_exp_sp(Abits, mctx); ulong e0, e1; FLINT_ASSERT(mctx->ord == ORD_LEX); FLINT_ASSERT(mctx->nvars >= 2); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, Abits, mctx); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, Abits, mctx); *Dlength = 0; i = 0; while (i < Alen) { if (*Dalloc < *Dlength + 1) { *Dalloc = FLINT_MAX(*Dlength + 1, *Dalloc + *Dalloc/2); *Dcoeffs = FLINT_ARRAY_REALLOC(*Dcoeffs, *Dalloc, ulong); } (*Dcoeffs)[*Dlength] = i; *Dlength = *Dlength + 1; e0 = (Aexps[N*i + off0] >> shift0) & mask; e1 = (Aexps[N*i + off1] >> shift1) & mask; while (1) { i++; if (i >= Alen) break; if (((Aexps[N*i + off0] >> shift0) & mask) != e0) break; if (((Aexps[N*i + off1] >> shift1) & mask) != e1) break; } } if (*Dalloc < *Dlength + 1) { *Dalloc = FLINT_MAX(*Dlength + 1, *Dalloc + *Dalloc/2); *Dcoeffs = FLINT_ARRAY_REALLOC(*Dcoeffs, *Dalloc, ulong); } (*Dcoeffs)[*Dlength] = Alen; } flint-3.1.3/src/mpoly/gcd_info.c000066400000000000000000000472621461254215100165110ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpoly.h" void mpoly_gcd_info_init(mpoly_gcd_info_t I, slong nvars) { char * d; FLINT_ASSERT(nvars > 0); d = (char *) flint_malloc(nvars*(10*sizeof(ulong) + 12*sizeof(slong))); I->data = d; I->Amax_exp = (ulong *) d; d += nvars*sizeof(ulong); I->Amin_exp = (ulong *) d; d += nvars*sizeof(ulong); I->Astride = (ulong *) d; d += nvars*sizeof(ulong); I->Adeflate_deg = (slong *) d; d += nvars*sizeof(slong); I->Alead_count = (slong *) d; d += nvars*sizeof(slong); I->Atail_count = (slong *) d; d += nvars*sizeof(slong); I->Bmax_exp = (ulong *) d; d += nvars*sizeof(ulong); I->Bmin_exp = (ulong *) d; d += nvars*sizeof(ulong); I->Bstride = (ulong *) d; d += nvars*sizeof(ulong); I->Bdeflate_deg = (slong *) d; d += nvars*sizeof(slong); I->Blead_count = (slong *) d; d += nvars*sizeof(slong); I->Btail_count = (slong *) d; d += nvars*sizeof(slong); I->Gmin_exp = (ulong *) d; d += nvars*sizeof(ulong); I->Abarmin_exp = (ulong *) d; d += nvars*sizeof(ulong); I->Bbarmin_exp = (ulong *) d; d += nvars*sizeof(ulong); I->Gstride = (ulong *) d; d += nvars*sizeof(ulong); I->Gdeflate_deg_bound = (slong *) d; d += nvars*sizeof(slong); I->Gterm_count_est = (slong *) d; d += nvars*sizeof(slong); I->hensel_perm = (slong *) d; d += nvars*sizeof(slong); I->brown_perm = (slong *) d; d += nvars*sizeof(slong); I->zippel_perm = (slong *) d; d += nvars*sizeof(slong); I->zippel2_perm = (slong *) d; d += nvars*sizeof(slong); } void mpoly_gcd_info_clear(mpoly_gcd_info_t I) { flint_free(I->data); } /* Scan A and fill in the min and max exponents of each variable along with the count of terms attached to each. */ void mpoly_gcd_info_limits(ulong * Amax_exp, ulong * Amin_exp, slong * Amax_exp_count, slong * Amin_exp_count, const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const mpoly_ctx_t mctx) { ulong * exps; slong i, j, N; slong nvars = mctx->nvars; TMP_INIT; FLINT_ASSERT(Alength > 0); FLINT_ASSERT(Abits <= FLINT_BITS); TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); N = mpoly_words_per_exp(Abits, mctx); i = 0; mpoly_get_monomial_ui(exps, Aexps + N*i, Abits, mctx); for (j = 0; j < nvars; j++) { Amin_exp[j] = exps[j]; Amax_exp[j] = exps[j]; Amin_exp_count[j] = 1; Amax_exp_count[j] = 1; } for (i = 1; i < Alength; i++) { mpoly_get_monomial_ui(exps, Aexps + N*i, Abits, mctx); for (j = 0; j < nvars; j++) { if (Amin_exp[j] > exps[j]) { Amin_exp[j] = exps[j]; Amin_exp_count[j] = 1; } else if (Amin_exp[j] == exps[j]) { Amin_exp_count[j] += 1; } if (Amax_exp[j] < exps[j]) { Amax_exp[j] = exps[j]; Amax_exp_count[j] = 1; } else if (Amax_exp[j] == exps[j]) { Amax_exp_count[j] += 1; } } } TMP_END; } /* For each variable v, let SA[v] be the set of exponents of variable v in A. Ditto for SB[v]. The function computes strides[v] = GCD(SA[v] - min(SA[v]), SB[v] - min(SB[v])) It is assumed that {A|B}{max|min}_exp are correct. */ void mpoly_gcd_info_stride(ulong * strides, const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const ulong * Amax_exp, const ulong * Amin_exp, const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength, const ulong * Bmax_exp, const ulong * Bmin_exp, const mpoly_ctx_t mctx) { slong i, j, NA, NB; slong nvars = mctx->nvars; ulong mask; ulong * exps; TMP_INIT; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(Bbits <= FLINT_BITS); for (j = 0; j < nvars; j++) { strides[j] = n_gcd(Amax_exp[j] - Amin_exp[j], Bmax_exp[j] - Bmin_exp[j]); } TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, mctx); for (i = 0; i < Alength; i++) { mpoly_get_monomial_ui(exps, Aexps + NA*i, Abits, mctx); mask = 0; for (j = 0; j < nvars; j++) { strides[j] = n_gcd(strides[j], exps[j] - Amin_exp[j]); mask |= strides[j]; } if (mask < UWORD(2)) { goto cleanup; } } NB = mpoly_words_per_exp(Bbits, mctx); for (i = 0; i < Blength; i++) { mpoly_get_monomial_ui(exps, Bexps + NB*i, Bbits, mctx); mask = 0; for (j = 0; j < nvars; j++) { strides[j] = n_gcd(strides[j], exps[j] - Bmin_exp[j]); mask |= strides[j]; } if (mask < UWORD(2)) { goto cleanup; } } cleanup: TMP_END; return; } void mpoly_gcd_info_set_perm( mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx) { slong j, m; I->Adensity = Alength; I->Bdensity = Blength; m = 0; for (j = 0; j < mctx->nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j]) { FLINT_ASSERT(I->Gstride[j] != UWORD(0)); FLINT_ASSERT((I->Amax_exp[j] - I->Amin_exp[j]) % I->Gstride[j] == 0); FLINT_ASSERT((I->Bmax_exp[j] - I->Bmin_exp[j]) % I->Gstride[j] == 0); I->Adensity /= UWORD(1) + (ulong)(I->Adeflate_deg[j]); I->Bdensity /= UWORD(1) + (ulong)(I->Bdeflate_deg[j]); I->hensel_perm[m] = j; I->brown_perm[m] = j; I->zippel_perm[m] = j; I->zippel2_perm[m] = j; m++; } else { FLINT_ASSERT(I->Amax_exp[j] == I->Amin_exp[j]); FLINT_ASSERT(I->Bmax_exp[j] == I->Bmin_exp[j]); } } I->mvars = m; I->can_use = 0; } void mpoly_gcd_info_measure_hensel( mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx) { slong i, k; slong m = I->mvars; slong * perm = I->hensel_perm; flint_bitcnt_t abits, bbits; double te, tg, ta, tb; double stgab, mtgab, iblend, eblend; /* need at least 2 variables */ if (m < 2) return; abits = FLINT_BIT_COUNT(Alength); bbits = FLINT_BIT_COUNT(Blength); te = tg = ta = tb = 1; for (i = 0; i < m; i++) { double x; k = perm[i]; if (abits + FLINT_BIT_COUNT(I->Adeflate_deg[k]) > FLINT_BITS || bbits + FLINT_BIT_COUNT(I->Bdeflate_deg[k]) > FLINT_BITS) { /* each variable is eventually converted to dense storage */ return; } te *= 1 + FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); x = I->Gdeflate_deg_bound[k]; tg *= 1 + x + 0.005*x*x; x = FLINT_MAX(0, I->Adeflate_deg[k] - I->Gdeflate_deg_bound[k]); ta *= 1 + x + 0.005*x*x; x = FLINT_MAX(0, I->Bdeflate_deg[k] - I->Gdeflate_deg_bound[k]); tb *= 1 + x + 0.005*x*x; } iblend = 1; eblend = 1; stgab = tg + ta + tb; mtgab = FLINT_MIN(tg, ta); mtgab = FLINT_MIN(mtgab, tb); I->can_use |= MPOLY_GCD_USE_HENSEL; I->hensel_time = 0.005*te*(I->Adensity + I->Bdensity)*eblend + 0.004*(iblend*stgab + (1 - iblend)*mtgab); } /* limit past which we should not test divisibility */ slong mpoly_gcd_info_get_brown_upper_limit( const mpoly_gcd_info_t I, slong var, slong bound) { if (I == NULL || !I->Gdeflate_deg_bounds_are_nice) { return 0; } else { slong k, max; slong density; slong limit; FLINT_ASSERT(var < I->mvars); k = I->brown_perm[var]; max = FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); bound = FLINT_MAX(bound, 1 + max); density = 0.5*(I->Adensity + I->Bdensity); limit = bound*((1.125 - density)*(1.125 - density))*0.375; return FLINT_MIN(limit, bound/2); } } void mpoly_gcd_info_measure_brown( mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx) { slong i, k; slong m = I->mvars; slong * perm = I->brown_perm; flint_bitcnt_t abits, bbits; double te, tg, ta, tb; double stgab, mtgab, iblend, eblend; /* need at least 2 variables */ if (m < 2) return; abits = FLINT_BIT_COUNT(Alength); bbits = FLINT_BIT_COUNT(Blength); te = tg = ta = tb = 1; for (i = 0; i < m; i++) { double x; k = perm[i]; if (abits + FLINT_BIT_COUNT(I->Adeflate_deg[k]) > FLINT_BITS || bbits + FLINT_BIT_COUNT(I->Bdeflate_deg[k]) > FLINT_BITS) { /* each variable is eventually converted to dense storage */ return; } te *= 1 + FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); x = I->Gdeflate_deg_bound[k]; tg *= 1 + x + 0.005*x*x; x = FLINT_MAX(0, I->Adeflate_deg[k] - I->Gdeflate_deg_bound[k]); ta *= 1 + x + 0.005*x*x; x = FLINT_MAX(0, I->Bdeflate_deg[k] - I->Gdeflate_deg_bound[k]); tb *= 1 + x + 0.005*x*x; } iblend = 1; eblend = 1; if (I->Gdeflate_deg_bounds_are_nice) { slong k = perm[m - 1]; slong limit = mpoly_gcd_info_get_brown_upper_limit(I, m - 1, 0); slong expected_stab; expected_stab = FLINT_MIN(I->Adeflate_deg[k], I->Bdeflate_deg[k]); expected_stab = expected_stab - I->Gdeflate_deg_bound[k]; expected_stab = FLINT_MIN(expected_stab, I->Gdeflate_deg_bound[k]); if (expected_stab < limit) { slong bound = 1 + FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); iblend = (I->Adensity + I->Bdensity); iblend = FLINT_MIN(iblend, 1); iblend = FLINT_MAX(iblend, 0.01); eblend = 0.25 + 0.75*(double)(expected_stab)/(double)(bound); } } stgab = tg + ta + tb; mtgab = FLINT_MIN(tg, ta); mtgab = FLINT_MIN(mtgab, tb); I->can_use |= MPOLY_GCD_USE_BROWN; I->brown_time = 0.005*te*(I->Adensity + I->Bdensity)*eblend + 0.004*(iblend*stgab + (1 - iblend)*mtgab); } void mpoly_gcd_info_measure_bma( mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx) { slong i, j, k; slong m = I->mvars; slong * perm = I->zippel2_perm; slong max_main_degree; double Glength, Glead_count_X, Gtail_count_X, Glead_count_Y, Gtail_count_Y; double evals, bivar, reconstruct; /* need at least 3 variables */ if (m < 3) return; /* figure out the two main variables y_0, y_1 */ for (k = 0; k < 2; k++) { slong main_var; ulong count, deg, new_count, new_deg; main_var = k; j = perm[main_var]; count = FLINT_MIN(I->Alead_count[j], I->Blead_count[j]); deg = FLINT_MAX(I->Adeflate_deg[j], I->Bdeflate_deg[j]); for (i = k + 1; i < m; i++) { j = perm[i]; new_count = FLINT_MIN(I->Alead_count[j], I->Blead_count[j]); new_deg = FLINT_MAX(I->Adeflate_deg[j], I->Bdeflate_deg[j]); if (new_deg + new_count/256 < deg + count/256) { count = new_count; deg = new_deg; main_var = i; } } if (main_var != k) { slong t = perm[main_var]; perm[main_var] = perm[k]; perm[k] = t; } } max_main_degree = 0; for (i = 0; i < 2; i++) { k = perm[i]; max_main_degree = FLINT_MAX(max_main_degree, I->Adeflate_deg[k]); max_main_degree = FLINT_MAX(max_main_degree, I->Bdeflate_deg[k]); } /* two main variables must be packed into bits = FLINT_BITS/2 */ if (FLINT_BIT_COUNT(max_main_degree) >= FLINT_BITS/2) return; /* estimate length of gcd */ Glength = 0.5*(I->Adensity + I->Bdensity); for (i = 0; i < m; i++) { k = perm[i]; Glength *= UWORD(1) + (ulong)(I->Gdeflate_deg_bound[k]); } /* estimate number of lead/tail terms of G wrt X,Y */ { double a, b; double Alead_density_X, Atail_density_X; double Blead_density_X, Btail_density_X; double Alead_density_Y, Atail_density_Y; double Blead_density_Y, Btail_density_Y; k = perm[0]; a = I->Adensity*(UWORD(1) + (ulong)(I->Adeflate_deg[k]))/Alength; b = I->Bdensity*(UWORD(1) + (ulong)(I->Bdeflate_deg[k]))/Blength; Alead_density_X = a*I->Alead_count[k]; Atail_density_X = a*I->Atail_count[k]; Blead_density_X = b*I->Blead_count[k]; Btail_density_X = b*I->Btail_count[k]; k = perm[1]; a = I->Adensity*(UWORD(1) + (ulong)(I->Adeflate_deg[k]))/Alength; b = I->Bdensity*(UWORD(1) + (ulong)(I->Bdeflate_deg[k]))/Blength; Alead_density_Y = a*I->Alead_count[k]; Atail_density_Y = a*I->Atail_count[k]; Blead_density_Y = b*I->Blead_count[k]; Btail_density_Y = b*I->Btail_count[k]; Glead_count_X = 0.5*(Alead_density_X + Blead_density_X); Gtail_count_X = 0.5*(Atail_density_X + Btail_density_X); Glead_count_Y = 0.5*(Alead_density_Y + Blead_density_Y); Gtail_count_Y = 0.5*(Atail_density_Y + Btail_density_Y); for (i = 0; i < m; i++) { k = perm[i]; if (i != 0) { Glead_count_X *= UWORD(1) + (ulong)(I->Gdeflate_deg_bound[k]); Gtail_count_X *= UWORD(1) + (ulong)(I->Gdeflate_deg_bound[k]); } if (i != 1) { Glead_count_Y *= UWORD(1) + (ulong)(I->Gdeflate_deg_bound[k]); Gtail_count_Y *= UWORD(1) + (ulong)(I->Gdeflate_deg_bound[k]); } } } /* evaluations needed is the max length of the coefficients of G wrt X,Y */ { double Gmax_terms_X, Gmax_terms_Y; k = perm[0]; Gmax_terms_X = Glength/(UWORD(1) + (ulong)(I->Gterm_count_est[k])); Gmax_terms_X = FLINT_MAX(Gmax_terms_X, Glead_count_X); Gmax_terms_X = FLINT_MAX(Gmax_terms_X, Gtail_count_X); Gmax_terms_X = FLINT_MAX(Gmax_terms_X, 1); k = perm[1]; Gmax_terms_Y = Glength/(UWORD(1) + (ulong)(I->Gterm_count_est[k])); Gmax_terms_Y = FLINT_MAX(Gmax_terms_Y, Glead_count_Y); Gmax_terms_Y = FLINT_MAX(Gmax_terms_Y, Gtail_count_Y); Gmax_terms_Y = FLINT_MAX(Gmax_terms_Y, 1); evals = Gmax_terms_X*Gmax_terms_Y/(1 + Glength); } /* time for bivar gcd */ { double te, tg, ta, tb; te = tg = ta = tb = 1; for (i = 0; i < 2; i++) { k = perm[i]; /* already checked reasonable degrees with max_main_degree above */ te *= 1 + FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); tg *= 1 + I->Gdeflate_deg_bound[k]; ta *= 1 + FLINT_MAX(0, I->Adeflate_deg[k] - I->Gdeflate_deg_bound[k]); tb *= 1 + FLINT_MAX(0, I->Bdeflate_deg[k] - I->Gdeflate_deg_bound[k]); } bivar = te + (tg + ta + tb)*0.1; } /* time for reconstruction */ { reconstruct = I->Gterm_count_est[perm[0]]; reconstruct += I->Gterm_count_est[perm[1]]; reconstruct = Glength*Glength/(1 + reconstruct); } I->can_use |= MPOLY_GCD_USE_ZIPPEL2; I->zippel2_time = 0.00000002*bivar*evals*(Alength + Blength) + 0.0003*reconstruct; } void mpoly_gcd_info_measure_zippel( mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx) { slong i, j, k; slong m = I->mvars; slong * perm = I->zippel_perm; /* need at least two variables */ if (m < 2) return; /* figure out a main variable y_0 */ { slong main_var; ulong count, deg, new_count, new_deg; main_var = 0; j = I->zippel_perm[main_var]; count = FLINT_MIN(I->Atail_count[j], I->Alead_count[j]); count = FLINT_MIN(count, I->Btail_count[j]); count = FLINT_MIN(count, I->Blead_count[j]); deg = FLINT_MAX(I->Adeflate_deg[j], I->Bdeflate_deg[j]); for (i = 1; i < m; i++) { j = perm[i]; new_count = FLINT_MIN(I->Atail_count[j], I->Alead_count[j]); new_count = FLINT_MIN(new_count, I->Btail_count[j]); new_count = FLINT_MIN(new_count, I->Blead_count[j]); new_deg = FLINT_MAX(I->Adeflate_deg[j], I->Bdeflate_deg[j]); if (new_count < count || (new_count == count && new_deg < deg)) { count = new_count; deg = new_deg; main_var = i; } } if (main_var != 0) { slong t = perm[main_var]; perm[main_var] = perm[0]; perm[0] = t; } } /* sort with hope that ddeg(G,y_1) >= ddeg(G,y_2) ... >= ddeg(G,y_m) */ for (k = 1; k + 1 < m; k++) { slong var; ulong deg, new_deg; var = k; j = perm[var]; deg = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); for (i = k + 1; i < m; i++) { j = perm[i]; new_deg = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); if (new_deg > deg) { deg = new_deg; var = i; } } if (var != k) { slong t = I->zippel_perm[var]; perm[var] = perm[k]; perm[k] = t; } } I->can_use |= MPOLY_GCD_USE_ZIPPEL; I->zippel_time = 0.3456; } void mpoly_gcd_info_measure_zippel2( mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx) { slong i, j, k; slong m = I->mvars; slong * perm = I->zippel2_perm; slong max_main_degree; /* need at least 3 variables */ if (m < 3) return; /* figure out the two main variables y_0, y_1 */ #define NEEDS_SWAP \ FLINT_MIN(I->Adeflate_deg[perm[j]], I->Bdeflate_deg[perm[j]]) < \ FLINT_MIN(I->Adeflate_deg[perm[j-1]], I->Bdeflate_deg[perm[j-1]]) \ for (i = 1; i < m; i++) for (j = i; j > 0 && NEEDS_SWAP; j--) FLINT_SWAP(slong, perm[j], perm[j - 1]); #define NEEDS_SWAP2 \ FLINT_MIN(I->Adeflate_deg[perm[j]], I->Bdeflate_deg[perm[j]]) > \ FLINT_MIN(I->Adeflate_deg[perm[j-1]], I->Bdeflate_deg[perm[j-1]]) \ for (i = 3; i < m; i++) for (j = i; j > 2 && NEEDS_SWAP; j--) FLINT_SWAP(slong, perm[j], perm[j - 1]); max_main_degree = 0; for (i = 0; i < 2; i++) { k = perm[i]; max_main_degree = FLINT_MAX(max_main_degree, I->Adeflate_deg[k]); max_main_degree = FLINT_MAX(max_main_degree, I->Bdeflate_deg[k]); } /* two main variables must be packed into bits = FLINT_BITS/2 */ if (FLINT_BIT_COUNT(max_main_degree) >= FLINT_BITS/2) return; I->can_use |= MPOLY_GCD_USE_ZIPPEL2; I->zippel2_time = 0.243; } flint-3.1.3/src/mpoly/gen_bits_required.c000066400000000000000000000012241461254215100204170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* !!! this file DOES need to change with new orderings */ /* bits required to represent the generator of index var */ flint_bitcnt_t mpoly_gen_bits_required(slong var, const mpoly_ctx_t mctx) { return MPOLY_MIN_BITS; /* 2 bits suffice in every case */ } flint-3.1.3/src/mpoly/gen_fields.c000066400000000000000000000023741461254215100170330ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* !!! this file DOES need to change with new orderings */ /* get the (unpacked) fields for the generator of index var */ void mpoly_gen_fields_ui(ulong * gexp, slong var, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong nfields = mctx->nfields; int deg = mctx->deg; int rev = mctx->rev; slong i; for (i = 0; i < nfields; i++) gexp[i] = WORD(0); gexp[rev ? var : nvars - 1 - var] = WORD(1); if (deg) gexp[nvars] = WORD(1); } void mpoly_gen_fields_fmpz(fmpz * gexp, slong var, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong nfields = mctx->nfields; int deg = mctx->deg; int rev = mctx->rev; slong i; for (i = 0; i < nfields; i++) fmpz_zero(gexp + i); fmpz_one(gexp + (rev ? var : nvars - 1 - var)); if (deg) fmpz_one(gexp + nvars); } flint-3.1.3/src/mpoly/gen_monomial_offset_shift.c000066400000000000000000000066521461254215100221460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* !!! this file DOES need to change with new orderings */ /* get the offset and shift where variable var is stored in packed form */ void mpoly_gen_offset_shift_sp(slong * offset, slong * shift, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; ulong fpw = FLINT_BITS/bits; ulong idx; FLINT_ASSERT(0 <= var && var < nvars); FLINT_ASSERT(bits <= FLINT_BITS); idx = var; if (!mctx->rev) idx = nvars - 1 - var; *offset = idx/fpw; *shift = idx%fpw*bits; } /* additionally get the monomial as well */ void mpoly_gen_monomial_offset_shift_sp(ulong * mexp, slong * offset, slong * shift, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { ulong idx; ulong nvars = mctx->nvars; ulong fpw = FLINT_BITS/bits; slong i, N; FLINT_ASSERT(0 <= var && var < nvars); FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(bits, mctx); for (i = 0; i < N; i++) mexp[i] = 0; idx = var; if (!mctx->rev) idx = nvars - 1 - var; *offset = idx/fpw; *shift = idx%fpw*bits; mexp[idx/fpw] |= UWORD(1) << (idx%fpw*bits); if (mctx->deg) mexp[nvars/fpw] |= UWORD(1) << (nvars%fpw*bits); } /* just get the monomial */ void mpoly_gen_monomial_sp(ulong * mexp, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { ulong nvars = mctx->nvars; ulong fpw = FLINT_BITS/bits; ulong idx = var; slong i, N; FLINT_ASSERT(0 <= var && var < nvars); FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(bits, mctx); for (i = 0; i < N; i++) mexp[i] = 0; idx = var; if (!mctx->rev) idx = nvars - 1 - var; mexp[idx/fpw] |= UWORD(1) << (idx%fpw*bits); if (mctx->deg) mexp[nvars/fpw] |= UWORD(1) << (nvars%fpw*bits); } /* get the offset where the variable of index var is stored */ slong mpoly_gen_offset_mp(slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; ulong wpf = bits/FLINT_BITS; ulong idx; FLINT_ASSERT(0 <= var && var < nvars); FLINT_ASSERT(bits > FLINT_BITS); FLINT_ASSERT(bits % FLINT_BITS == WORD(0)); idx = var; if (!mctx->rev) idx = nvars - 1 - idx; return idx*wpf; } /* additionally get the monomial as well */ slong mpoly_gen_monomial_offset_mp(ulong * mexp, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { ulong nvars = mctx->nvars; ulong wpf = bits/FLINT_BITS; ulong idx; slong i, N, offset; FLINT_ASSERT(0 <= var && var < nvars); FLINT_ASSERT(bits > FLINT_BITS); FLINT_ASSERT(bits % FLINT_BITS == WORD(0)); N = mpoly_words_per_exp_mp(bits, mctx); for (i = 0; i < N; i++) mexp[i] = 0; idx = var; if (!mctx->rev) idx = nvars - 1 - var; offset = idx*wpf; mexp[idx*wpf] = UWORD(1); if (mctx->deg) mexp[nvars*wpf] = UWORD(1); return offset; } flint-3.1.3/src/mpoly/gen_shift_left_right.c000066400000000000000000000064001461254215100211030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* shift_right (resp. left) divides (resp. multiplies) A in place by x^amount, where x is the variable of index var. No reallocation on Abits is performed: The shift right version asserts that the division was exact, and the shift left version tries to assert that the result fits in the same number of bits. */ void _mpoly_gen_shift_right(ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx) { slong i, N; ulong *one; #if FLINT_WANT_ASSERT ulong mask; #endif TMP_INIT; FLINT_ASSERT(Abits <= FLINT_BITS); #if FLINT_WANT_ASSERT mask = 0; for (i = 0; i < FLINT_BITS/Abits; i++) mask = (mask << Abits) + (UWORD(1) << (Abits - 1)); #endif TMP_START; N = mpoly_words_per_exp(Abits, mctx); one = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_sp(one, var, Abits, mctx); for (i = 0; i < Alength; i++) { mpoly_monomial_msub(Aexp + N*i, Aexp + N*i, amount, one, N); FLINT_ASSERT(!mpoly_monomial_overflows(Aexp + N*i, N, mask)); } TMP_END; } void _mpoly_gen_shift_right_fmpz( ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, const fmpz_t amount, const mpoly_ctx_t mctx) { slong i, N; ulong * gen; TMP_INIT; FLINT_ASSERT(fmpz_sgn(amount) >= 0); if (fmpz_is_zero(amount)) return; TMP_START; N = mpoly_words_per_exp(Abits, mctx); gen = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits > FLINT_BITS) { mpoly_gen_monomial_offset_mp(gen, var, Abits, mctx); mpoly_monomial_mul_fmpz(gen, gen, N, amount); for (i = 0; i < Alength; i++) mpoly_monomial_sub_mp(Aexp + N*i, Aexp + N*i, gen, N); } else { mpoly_gen_monomial_sp(gen, var, Abits, mctx); FLINT_ASSERT(fmpz_abs_fits_ui(amount)); mpoly_monomial_mul_ui(gen, gen, N, fmpz_get_ui(amount)); for (i = 0; i < Alength; i++) mpoly_monomial_sub(Aexp + N*i, Aexp + N*i, gen, N); } TMP_END; } void _mpoly_gen_shift_left(ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx) { slong i, N; ulong *one; #if FLINT_WANT_ASSERT ulong mask; #endif TMP_INIT; FLINT_ASSERT(Abits <= FLINT_BITS); #if FLINT_WANT_ASSERT mask = 0; for (i = 0; i < FLINT_BITS/Abits; i++) mask = (mask << Abits) + (UWORD(1) << (Abits - 1)); #endif TMP_START; N = mpoly_words_per_exp(Abits, mctx); one = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_sp(one, var, Abits, mctx); for (i = 0; i < Alength; i++) { mpoly_monomial_madd(Aexp + N*i, Aexp + N*i, amount, one, N); FLINT_ASSERT(!mpoly_monomial_overflows(Aexp + N*i, N, mask)); } TMP_END; } flint-3.1.3/src/mpoly/get_cmpmask.c000066400000000000000000000023301461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void mpoly_get_cmpmask(ulong * cmpmask, slong N, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i; if (mctx->rev) { /* DEGREVLEX has a bit set everywhere except the in most significant field */ if (bits <= FLINT_BITS) { for (i = 0; i + 1 < N; i++) cmpmask[i] = -UWORD(1); cmpmask[N - 1] = (UWORD(1) << (mctx->nvars%(FLINT_BITS/bits)*bits)) - UWORD(1); } else { for (i = 0; i < N - bits/FLINT_BITS; i++) cmpmask[i] = -UWORD(1); for (; i < N; i++) cmpmask[i] = UWORD(0); } } else { /* LEX and DEGLEX use a clear mask */ for (i = 0; i < N; i++) cmpmask[i] = UWORD(0); } } flint-3.1.3/src/mpoly/get_monomial.c000066400000000000000000000146031461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* !!! this file DOES need to change with new orderings */ /* poly_exps (when unpacked) must contain the exponent of each variable in some field. These functions should place the exponent of each variable in the corresponding entry of user_exps. */ void mpoly_get_monomial_ui_unpacked_ffmpz(ulong * user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx) { slong i; /* poly_exps is already unpacked, just read of the correct fields */ for (i = 0; i < mctx->nvars; i++) { slong off = mctx->rev ? i : mctx->nvars - 1 - i; FLINT_ASSERT(fmpz_abs_fits_ui(poly_exps + off)); user_exps[i] = fmpz_get_ui(poly_exps + off); } } void mpoly_get_monomial_ffmpz_unpacked_ffmpz(fmpz * user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx) { slong i; /* poly_exps is already unpacked, just read of the correct fields */ for (i = 0; i < mctx->nvars; i++) { slong off = mctx->rev ? i : mctx->nvars - 1 - i; fmpz_set(user_exps + i, poly_exps + off); } } void mpoly_get_monomial_pfmpz_unpacked_ffmpz(fmpz ** user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx) { slong i; /* poly_exps is already unpacked, just read of the correct fields */ for (i = 0; i < mctx->nvars; i++) { slong off = mctx->rev ? i : mctx->nvars - 1 - i; fmpz_set(user_exps[i], poly_exps + off); } } void mpoly_get_monomial_ui_unpacked_ui(ulong * user_exps, const ulong * poly_exps, const mpoly_ctx_t mctx) { slong i; /* poly_exps is already unpacked, just read of the correct fields */ for (i = 0; i < mctx->nvars; i++) { slong off = mctx->rev ? i : mctx->nvars - 1 - i; user_exps[i] = poly_exps[off]; } } void mpoly_get_monomial_ui_sp(ulong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong i, shift; ulong u, mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * exp1; const ulong * exp2; slong dir; FLINT_ASSERT(bits <= FLINT_BITS); exp2 = poly_exps; exp1 = user_exps + nvars - 1; dir = -WORD(1); if (mctx->rev) { exp1 = user_exps; dir = UWORD(1); } if (nvars < 1) return; i = 0; u = *exp2++; shift = 0; *exp1 = u & mask; exp1 += dir; u = u >> bits; /* number of bits to encode 0th field */ shift += bits; /* number of bits to encode 0th field */ while (++i < nvars) { if (shift + bits > FLINT_BITS) { u = *exp2++; shift = 0; } *exp1 = u & mask; exp1 += dir; u = u >> bits; /* number of bits to encode ith field */ shift += bits; /* number of bits to encode ith field */ } } void mpoly_get_monomial_ui_mp(ulong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong i, j; ulong * exp1; const ulong * exp2; ulong words_per_field = bits/FLINT_BITS; ulong check_mask; slong dir; FLINT_ASSERT(bits%FLINT_BITS == 0); FLINT_ASSERT(bits > FLINT_BITS); exp2 = poly_exps; exp1 = user_exps + nvars - 1; dir = -WORD(1); if (mctx->rev) { exp1 = user_exps; dir = UWORD(1); } check_mask = 0; for (i = 0; i < nvars; i++) { *exp1 = *exp2; exp1 += dir; for (j = 1; j < words_per_field; j++) check_mask |= exp2[j]; exp2 += words_per_field; } if (check_mask != 0) flint_throw(FLINT_ERROR, "Exponent vector does not fit a ulong."); } void mpoly_get_monomial_si_mp(slong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong i, j; slong * exp1; const ulong * exp2; ulong words_per_field = bits/FLINT_BITS; ulong check_mask; slong dir; FLINT_ASSERT(bits%FLINT_BITS == 0); FLINT_ASSERT(bits > FLINT_BITS); exp2 = poly_exps; exp1 = user_exps + nvars - 1; dir = -WORD(1); if (mctx->rev) { exp1 = user_exps; dir = UWORD(1); } check_mask = 0; for (i = 0; i < nvars; i++) { *exp1 = (slong) *exp2; exp1 += dir; check_mask |= FLINT_SIGN_EXT(exp2[0]); for (j = 1; j < words_per_field; j++) check_mask |= exp2[j]; exp2 += words_per_field; } if (check_mask != 0) flint_throw(FLINT_ERROR, "Exponent vector does not fit an slong."); } void mpoly_get_monomial_ffmpz(fmpz * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, nvars = mctx->nvars; fmpz * tmp_exps; TMP_INIT; TMP_START; tmp_exps = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) fmpz_init(tmp_exps + i); mpoly_unpack_vec_fmpz(tmp_exps, poly_exps, bits, mctx->nfields, 1); for (i = 0; i < nvars; i++) fmpz_swap(user_exps + i, tmp_exps + (mctx->rev ? i : nvars - 1 - i)); for (i = 0; i < mctx->nfields; i++) fmpz_clear(tmp_exps + i); TMP_END; } void mpoly_get_monomial_pfmpz(fmpz ** user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, nvars = mctx->nvars; fmpz * tmp_exps; TMP_INIT; TMP_START; tmp_exps = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) fmpz_init(tmp_exps + i); mpoly_unpack_vec_fmpz(tmp_exps, poly_exps, bits, mctx->nfields, 1); for (i = 0; i < nvars; i++) fmpz_swap(user_exps[i], tmp_exps + (mctx->rev ? i : nvars - 1 - i)); for (i = 0; i < mctx->nfields; i++) fmpz_clear(tmp_exps + i); TMP_END; } flint-3.1.3/src/mpoly/get_monomial_var.c000066400000000000000000000034541461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpoly.h" /* this file does not need to change with new orderings */ ulong mpoly_get_monomial_var_exp_ui_sp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong offset, shift; mpoly_gen_offset_shift_sp(&offset, &shift, var, bits, mctx); return (poly_exps[offset] >> shift) & ((-UWORD(1)) >> (FLINT_BITS - bits)); } ulong mpoly_get_monomial_var_exp_ui_mp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong offset; slong j; ulong wpf = bits/FLINT_BITS; ulong r, check; offset = mpoly_gen_offset_mp(var, bits, mctx); r = poly_exps[offset + 0]; check = 0; for (j = 1; j < wpf; j++) check |= poly_exps[offset + j]; if (check != 0) flint_throw(FLINT_ERROR, "Exponent does not fit a ulong."); return r; } slong mpoly_get_monomial_var_exp_si_mp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong offset; slong j; ulong wpf = bits/FLINT_BITS; ulong r, check; offset = mpoly_gen_offset_mp(var, bits, mctx); r = poly_exps[offset + 0]; check = FLINT_SIGN_EXT(r); for (j = 1; j < wpf; j++) check |= poly_exps[offset + j]; if (check != 0) flint_throw(FLINT_ERROR, "Exponent does not fit an slong."); return (slong) r; } flint-3.1.3/src/mpoly/heap_insert.c000066400000000000000000000027471461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" int _mpoly_heap_insert(mpoly_heap_s * heap, ulong * exp, void * x, slong * next_loc, slong * heap_len, slong N, const ulong * cmpmask) { slong i = *heap_len, j, n = *heap_len; if (i != 1 && mpoly_monomial_equal(exp, heap[1].exp, N)) { ((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[1].next; heap[1].next = x; return 0; } if (*next_loc < *heap_len) { if (mpoly_monomial_equal(exp, heap[*next_loc].exp, N)) { ((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[*next_loc].next; heap[*next_loc].next = x; return 0; } } while ((j = HEAP_PARENT(i)) >= 1) { if (!mpoly_monomial_gt(exp, heap[j].exp, N, cmpmask)) break; i = j; } if (j >= 1 && mpoly_monomial_equal(exp, heap[j].exp, N)) { ((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[j].next; heap[j].next = x; *next_loc = j; return 0; } (*heap_len)++; while (n > i) { heap[n] = heap[HEAP_PARENT(n)]; n = HEAP_PARENT(n); } HEAP_ASSIGN(heap[i], exp, x); return 1; } flint-3.1.3/src/mpoly/heap_insert1.c000066400000000000000000000026411461254215100173130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void _mpoly_heap_insert1(mpoly_heap1_s * heap, ulong exp, void * x, slong * next_loc, slong * heap_len, ulong maskhi) { slong i = *heap_len, j, n = *heap_len; if (i != 1 && exp == heap[1].exp) { ((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[1].next; heap[1].next = x; return; } if (*next_loc < *heap_len) { if (exp == heap[*next_loc].exp) { ((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[*next_loc].next; heap[*next_loc].next = x; return; } } while ((j = HEAP_PARENT(i)) >= 1) { if (exp == heap[j].exp) { ((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[j].next; heap[j].next = x; *next_loc = j; return; } else if ((exp^maskhi) > (heap[j].exp^maskhi)) i = j; else break; } (*heap_len)++; while (n > i) { heap[n] = heap[HEAP_PARENT(n)]; n = HEAP_PARENT(n); } HEAP_ASSIGN(heap[i], exp, x); } flint-3.1.3/src/mpoly/heap_pop.c000066400000000000000000000021431461254215100165210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void * _mpoly_heap_pop(mpoly_heap_s * heap, slong * heap_len, slong N, const ulong * cmpmask) { ulong * exp; slong i, j, s = --(*heap_len); mpoly_heap_t * x = (mpoly_heap_t *) heap[1].next; i = 1; j = 2; while (j < s) { if (!mpoly_monomial_gt(heap[j].exp, heap[j + 1].exp, N, cmpmask)) j++; heap[i] = heap[j]; i = j; j = HEAP_LEFT(j); } /* insert last element into heap[i] */ exp = heap[s].exp; j = HEAP_PARENT(i); while (i > 1 && mpoly_monomial_gt(exp, heap[j].exp, N, cmpmask)) { heap[i] = heap[j]; i = j; j = HEAP_PARENT(j); } heap[i] = heap[s]; return x; } flint-3.1.3/src/mpoly/heap_pop1.c000066400000000000000000000017441461254215100166100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void * _mpoly_heap_pop1(mpoly_heap1_s * heap, slong * heap_len, ulong maskhi) { ulong exp; slong i, j, s = --(*heap_len); void * x = heap[1].next; i = 1; j = 2; while (j < s) { if ((heap[j].exp^maskhi) <= (heap[j + 1].exp^maskhi)) j++; heap[i] = heap[j]; i = j; j = HEAP_LEFT(j); } /* insert last element into heap[i] */ exp = heap[s].exp; j = HEAP_PARENT(i); while (i > 1 && (exp^maskhi) > (heap[j].exp^maskhi)) { heap[i] = heap[j]; i = j; j = HEAP_PARENT(j); } heap[i] = heap[s]; return x; } flint-3.1.3/src/mpoly/inlines.c000066400000000000000000000006461461254215100163750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define MPOLY_INLINES_C #include "mpoly.h" flint-3.1.3/src/mpoly/io.c000066400000000000000000000013351461254215100153370ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "mpoly.h" void mpoly_ordering_print(ordering_t ord) { switch (ord) { case ORD_LEX: printf("lex"); break; case ORD_DEGLEX: printf("deglex"); break; case ORD_DEGREVLEX: printf("degrevlex"); break; default: printf("Unknown ordering in mpoly_ordering_print."); } } flint-3.1.3/src/mpoly/is_gen.c000066400000000000000000000031431461254215100161730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" int mpoly_is_gen(ulong * exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { int ret; slong i; fmpz * unpacked_exps; TMP_INIT; TMP_START; unpacked_exps = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(unpacked_exps + i); mpoly_get_monomial_ffmpz(unpacked_exps, exps, bits, mctx); if (var >= 0) { ret = 1; for (i = 0; i < mctx->nvars; i++) { if (!fmpz_equal_si(unpacked_exps + i, i == var)) { ret = 0; break; } } } else { int count = 0; for (i = 0; i < mctx->nvars; i++) { if (fmpz_is_one(unpacked_exps + i)) { count++; if (count > 1) break; } else if (!fmpz_is_zero(unpacked_exps + i)) { count = 2; break; } } ret = (count == 1); } for (i = 0; i < mctx->nvars; i++) fmpz_clear(unpacked_exps + i); TMP_END; return ret; } flint-3.1.3/src/mpoly/is_poly.c000066400000000000000000000023431461254215100164060ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* TODO: this could a bit faster */ int mpoly_is_poly( const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, slong var, const mpoly_ctx_t mctx) { int ret = 1; slong i, j; slong N = mpoly_words_per_exp(Abits, mctx); slong nvars = mctx->nvars; fmpz * t; TMP_INIT; TMP_START; t = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init(t + i); for (i = 0; i < Alen; i++) { mpoly_get_monomial_ffmpz(t, Aexps + N*i, Abits, mctx); for (j = 0; j < nvars; j++) { if (j != var && !fmpz_is_zero(t + j)) { ret = 0; goto cleanup; } } } cleanup: for (i = 0; i < nvars; i++) fmpz_clear(t + i); TMP_END; return ret; } flint-3.1.3/src/mpoly/is_proved_not_square.c000066400000000000000000000023431461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* this file does not need to change with new orderings */ /* try to prove A is not a square */ int mpoly_is_proved_not_square( const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, slong N, ulong * t) /* temp of size N */ { slong i; if (Alen < 1) return 0; /* check for odd degrees & check total degree too in degree orderings */ mpoly_monomial_set(t, Aexps + N*0, N); if (Abits <= FLINT_BITS) { ulong mask = mpoly_overflow_mask_sp(Abits); for (i = 1; i < Alen; i++) mpoly_monomial_max(t, t, Aexps + N*i, Abits, N, mask); return !mpoly_monomial_halves(t, t, N, mask); } else { for (i = 1; i < Alen; i++) mpoly_monomial_max_mp(t, t, Aexps + N*i, Abits, N); return !mpoly_monomial_halves_mp(t, t, N, Abits); } } flint-3.1.3/src/mpoly/main_variable_split.c000066400000000000000000000030301461254215100207260ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void mpoly_main_variable_split_LEX(slong * ind, ulong * pexp, const ulong * Aexp, slong l1, slong Alen, const ulong * mults, slong num, slong Abits) { slong i, j = 0, s = 0; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - Abits); for (i = 0; i < Alen; i++) { slong top = Aexp[i] >> (Abits*num); while (s < l1 - top) ind[s++] = i; e = 0; for (j = num - 1; j >= 0; j--) { e = (e * mults[j]) + ((Aexp[i] >> (j*Abits)) & mask); } pexp[i] = e; } while (s <= l1) ind[s++] = Alen; } void mpoly_main_variable_split_DEG(slong * ind, ulong * pexp, const ulong * Aexp, slong l1, slong Alen, ulong deg, slong num, slong Abits) { slong i, j = 0, s = 0; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - Abits); for (i = 0; i < Alen; i++) { slong top = Aexp[i] >> (Abits*num); while (s < l1 - top) ind[s++] = i; e = 0; for (j = num - 1; j >= 1; j--) e = (e * deg) + ((Aexp[i] >> (j*Abits)) & mask); pexp[i] = e; } while (s <= l1) ind[s++] = Alen; } flint-3.1.3/src/mpoly/max_fields.c000066400000000000000000000036211461254215100170430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* this file does not need to change with new orderings */ /* unpack the field-wise maximum of poly_exps into max_fields */ void mpoly_max_fields_ui_sp(ulong * max_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, N; ulong * pmax, mask; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(bits, mctx); mask = mpoly_overflow_mask_sp(bits); TMP_START; pmax = (ulong *) TMP_ALLOC(N*sizeof(ulong)); for (i = 0; i < N; i++) pmax[i] = 0; for (i = 0; i < len; i++) mpoly_monomial_max(pmax, pmax, poly_exps + N*i, bits, N, mask); mpoly_unpack_vec_ui(max_fields, pmax, bits, mctx->nfields, 1); TMP_END; } void mpoly_max_fields_fmpz(fmpz * max_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, N; ulong * pmax, mask; TMP_INIT; TMP_START; N = mpoly_words_per_exp(bits, mctx); pmax = (ulong *) TMP_ALLOC(N*sizeof(ulong)); for (i = 0; i < N; i++) pmax[i] = 0; if (bits <= FLINT_BITS) { mask = mpoly_overflow_mask_sp(bits); for (i = 0; i < len; i++) mpoly_monomial_max(pmax, pmax, poly_exps + N*i, bits, N, mask); } else { for (i = 0; i < len; i++) mpoly_monomial_max_mp(pmax, pmax, poly_exps + N*i, bits, N); } mpoly_unpack_vec_fmpz(max_fields, pmax, bits, mctx->nfields, 1); TMP_END; } flint-3.1.3/src/mpoly/min_fields.c000066400000000000000000000052451461254215100170450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* this file does not need to change with new orderings */ /* unpack the field-wise minimum of poly_exps into min_fields */ void mpoly_min_fields_ui_sp(ulong * min_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, N; ulong * pmin, mask; TMP_INIT; FLINT_ASSERT(len > 0); FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(bits, mctx); mask = mpoly_overflow_mask_sp(bits); TMP_START; pmin = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_set(pmin, poly_exps + N*(len - 1), N); if (!mpoly_monomial_is_zero(pmin, N)) { for (i = 0; i < len - 1; i++) mpoly_monomial_min(pmin, pmin, poly_exps + N*i, bits, N, mask); } /* GCC really wants to complain about this one */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif mpoly_unpack_vec_ui(min_fields, pmin, bits, mctx->nfields, 1); #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif TMP_END; } void mpoly_min_fields_fmpz(fmpz * min_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, N; ulong * pmin, mask; TMP_INIT; FLINT_ASSERT(len > 0); TMP_START; N = mpoly_words_per_exp(bits, mctx); pmin = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_set(pmin, poly_exps + N*(len - 1), N); if (!mpoly_monomial_is_zero(pmin, N)) { if (bits <= FLINT_BITS) { mask = mpoly_overflow_mask_sp(bits); for (i = 0; i < len - 1; i++) mpoly_monomial_min(pmin, pmin, poly_exps + N*i, bits, N, mask); } else { for (i = 0; i < len - 1; i++) mpoly_monomial_min_mp(pmin, pmin, poly_exps + N*i, bits, N); } } /* GCC really wants to complain about this one */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif mpoly_unpack_vec_fmpz(min_fields, pmin, bits, mctx->nfields, 1); #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif TMP_END; } flint-3.1.3/src/mpoly/monomial_cofactors.c000066400000000000000000000053241461254215100206100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" /* If monomials can be factored of A and B leaving identical exponents, store the monomials in Abarexps and Bbarsexps and return 1. Otherwise, return 0. */ int mpoly_monomial_cofactors( fmpz * Abarexps, fmpz * Bbarexps, const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong length, const mpoly_ctx_t mctx) { int success; slong i, j; slong nvars = mctx->nvars; slong NA = mpoly_words_per_exp(Abits, mctx); slong NB = mpoly_words_per_exp(Bbits, mctx); fmpz * Aexp, * Bexp, * minAexp, * minBexp; fmpz_t t1, t2; TMP_INIT; FLINT_ASSERT(length > 0); fmpz_init(t1); fmpz_init(t2); TMP_START; Aexp = (fmpz *) TMP_ALLOC(4*nvars*sizeof(fmpz)); Bexp = Aexp + 1*nvars; minAexp = Aexp + 2*nvars; minBexp = Aexp + 3*nvars; for (j = 0; j < nvars; j++) { fmpz_init(Aexp + j); fmpz_init(Bexp + j); fmpz_init(minAexp + j); fmpz_init(minBexp + j); } /* {A|B}barexps holds the leading exponents */ mpoly_get_monomial_ffmpz(Abarexps, Aexps + NA*0, Abits, mctx); mpoly_get_monomial_ffmpz(Bbarexps, Bexps + NB*0, Bbits, mctx); _fmpz_vec_set(minAexp, Abarexps, nvars); _fmpz_vec_set(minBexp, Bbarexps, nvars); for (i = 0; i < length; i++) { mpoly_get_monomial_ffmpz(Aexp, Aexps + NA*i, Abits, mctx); mpoly_get_monomial_ffmpz(Bexp, Bexps + NB*i, Bbits, mctx); _fmpz_vec_min_inplace(minAexp, Aexp, nvars); _fmpz_vec_min_inplace(minBexp, Bexp, nvars); for (j = 0; j < nvars; j++) { fmpz_add(t1, Abarexps + j, Bexp + j); fmpz_add(t2, Bbarexps + j, Aexp + j); success = fmpz_equal(t1, t2); if (!success) goto cleanup; } } /* put {A|B}'s cofactor monomial in {A|B}barexps */ _fmpz_vec_max(Bbarexps, minAexp, minBexp, nvars); _fmpz_vec_sub(Abarexps, Bbarexps, minBexp, nvars); _fmpz_vec_sub(Bbarexps, Bbarexps, minAexp, nvars); success = 1; cleanup: for (j = 0; j < nvars; j++) { fmpz_clear(Aexp + j); fmpz_clear(Bexp + j); fmpz_clear(minAexp + j); fmpz_clear(minBexp + j); } TMP_END; fmpz_clear(t1); fmpz_clear(t2); return success; } flint-3.1.3/src/mpoly/monomial_exists.c000066400000000000000000000043721461254215100201460ustar00rootroot00000000000000/* Copyright (C) 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpoly.h" int mpoly_monomial_exists1(slong * index, const ulong * poly_exps, const ulong exp, slong len, ulong maskhi) { slong n = len; slong i = 0; if ((exp^maskhi) > (poly_exps[0]^maskhi)) /* greater than first term */ { (*index) = 0; return 0; } while (n > 1) /* do binary search */ { slong half = n/2; /* if in first half */ if ((exp^maskhi) > (poly_exps[i + half]^maskhi)) n = half; else /* in second half */ { n -= half; i += half; } } /* if equal to term at index i */ if (exp == poly_exps[i]) { (*index) = i; return 1; } else /* less than term at index i, but doesn't exist */ { (*index) = i + 1; return 0; } } int mpoly_monomial_exists(slong * index, const ulong * poly_exps, const ulong * exp, slong len, slong N, const ulong * cmpmask) { slong n = len; slong i = 0; if (len == 0) /* no terms to search */ { (*index) = 0; return 0; } /* specialised version if exponent vectors are one word */ if (N == 1) return mpoly_monomial_exists1(index, poly_exps, *exp, len, cmpmask[0]); if (mpoly_monomial_gt(exp, poly_exps, N, cmpmask)) /* greater than first term */ { (*index) = 0; return 0; } while (n > 1) /* do binary search */ { slong half = n/2; /* if in first half */ if (mpoly_monomial_gt(exp, poly_exps + (i + half)*N, N, cmpmask)) n = half; else /* in second half */ { n -= half; i += half; } } /* if equal to term at index i */ if (mpoly_monomial_equal(exp, poly_exps + i*N, N)) { (*index) = i; return 1; } else /* less than term at index i, but doesn't exist */ { (*index) = i + 1; return 0; } } flint-3.1.3/src/mpoly/monomial_index.c000066400000000000000000000073711461254215100177400ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* this file does not need to change with new orderings */ slong mpoly_monomial_index1_nomask(ulong * Aexps, slong Alen, ulong e) { slong start = 0, i, stop = Alen; again: if (stop - start < 8) { for (i = start; i < stop; i++) { if (Aexps[i] == e) return i; } return -1; } i = (start + stop)/2; FLINT_ASSERT(Aexps[start] > Aexps[i]); FLINT_ASSERT(stop >= Alen || Aexps[stop] < Aexps[i]); if (Aexps[i] < e) { stop = i; goto again; } else if (Aexps[i] > e) { start = i; goto again; } return i; } slong mpoly_monomial_index_ui(const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const ulong * exp, const mpoly_ctx_t mctx) { slong N, index; ulong * cmpmask, * packed_exp; flint_bitcnt_t exp_bits; int exists; TMP_INIT; exp_bits = mpoly_exp_bits_required_ui(exp, mctx); if (exp_bits > Abits) return -WORD(1); TMP_START; N = mpoly_words_per_exp(Abits, mctx); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, mctx); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ui(packed_exp, exp, Abits, mctx); exists = mpoly_monomial_exists(&index, Aexps, packed_exp, Alength, N, cmpmask); TMP_END; if (!exists) return -WORD(1); else return index; } slong mpoly_monomial_index_pfmpz(const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, fmpz * const * exp, const mpoly_ctx_t mctx) { slong N, index; ulong * cmpmask, * packed_exp; flint_bitcnt_t exp_bits; int exists; TMP_INIT; exp_bits = mpoly_exp_bits_required_pfmpz(exp, mctx); if (exp_bits > Abits) return -WORD(1); TMP_START; N = mpoly_words_per_exp(Abits, mctx); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, mctx); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_pfmpz(packed_exp, exp, Abits, mctx); exists = mpoly_monomial_exists(&index, Aexps, packed_exp, Alength, N, cmpmask); TMP_END; if (!exists) return -WORD(1); else return index; } slong mpoly_monomial_index_monomial(const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const ulong * Mexp, flint_bitcnt_t Mbits, const mpoly_ctx_t mctx) { slong N, index; ulong * cmpmask, * pexp; int exists, could_repack; TMP_INIT; TMP_START; N = mpoly_words_per_exp(Abits, mctx); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, mctx); if (Mbits == Abits) { exists = mpoly_monomial_exists(&index, Aexps, Mexp, Alength, N, cmpmask); } else { pexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); could_repack = mpoly_repack_monomials(pexp, Abits, Mexp, Mbits, 1, mctx); if (!could_repack) { FLINT_ASSERT(Mbits > Abits); exists = 0; index = -WORD(1); goto clean_up; } exists = mpoly_monomial_exists(&index, Aexps, pexp, Alength, N, cmpmask); } clean_up: TMP_END; if (!exists) return -WORD(1); else return index; } flint-3.1.3/src/mpoly/monomial_mul_fmpz.c000066400000000000000000000032441461254215100204550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #if FLINT_WANT_ASSERT # include "fmpz.h" #endif void mpoly_monomial_mul_fmpz(ulong * exp2, const ulong * exp3, slong N, const fmpz_t c) { FLINT_ASSERT(fmpz_sgn(c) >= 0); if (!COEFF_IS_MPZ(*c)) { FLINT_ASSERT(N > 0); mpn_mul_1(exp2, exp3, N, *c); } else { slong i, cn; ulong * cp; cn = COEFF_TO_PTR(*c)->_mp_size; cp = COEFF_TO_PTR(*c)->_mp_d; FLINT_ASSERT(0 < cn); FLINT_ASSERT(cn <= N); if (exp2 != exp3) { FLINT_ASSERT(N > 0); mpn_mul_1(exp2, exp3, N, cp[0]); for (i = 1; i < cn; i++) { FLINT_ASSERT(N > i); mpn_addmul_1(exp2 + i, exp3, N - i, cp[i]); } } else { ulong * t; TMP_INIT; TMP_START; t = TMP_ALLOC(N*sizeof(ulong)); FLINT_ASSERT(N > 0); mpn_mul_1(t, exp3, N, cp[0]); for (i = 1; i < cn; i++) { FLINT_ASSERT(N > i); mpn_addmul_1(t + i, exp3, N - i, cp[i]); } for (i = 0; i < N; i++) exp2[i] = t[i]; TMP_END; } } } flint-3.1.3/src/mpoly/monomials_cmp.c000066400000000000000000000063231461254215100175670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* this file does not need to change with new orderings */ static int _mpoly_monomials_cmp_repack_bits( const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong length, const mpoly_ctx_t mctx) { int cmp = 0; ulong * newAexps, * cmpmask; slong NA = mpoly_words_per_exp(Abits, mctx); slong NB = mpoly_words_per_exp(Bbits, mctx); const slong max_limit = 32; slong i, j, limit; TMP_INIT; FLINT_ASSERT(Abits <= Bbits); FLINT_ASSERT(NA <= NB); TMP_START; /* repack first monomial, then the next two, then the next four, ... */ cmpmask = (ulong *) TMP_ALLOC(NB*sizeof(ulong)); newAexps = (ulong *) TMP_ALLOC(max_limit*NB*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, NB, Bbits, mctx); i = 0; limit = 1; try_again: if (i + limit <= length) { FLINT_ASSERT(limit <= max_limit); mpoly_repack_monomials(newAexps, Bbits, Aexps + NA*i, Abits, limit, mctx); for (j = 0; j < limit; j++, i++) { cmp = mpoly_monomial_cmp(newAexps + NB*j, Bexps + NB*i, NB, cmpmask); if (cmp != 0) goto cleanup; } limit = FLINT_MIN(2*limit, max_limit); goto try_again; } FLINT_ASSERT(length - i <= max_limit); mpoly_repack_monomials(newAexps, Bbits, Aexps + NA*i, Abits, length - i, mctx); for (j = 0; i < length; j++, i++) { cmp = mpoly_monomial_cmp(newAexps + NB*j, Bexps + NB*i, NB, cmpmask); if (cmp != 0) goto cleanup; } cleanup: TMP_END; return cmp; } /* cmp two exponent matrices of the same length */ int mpoly_monomials_cmp( const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong length, const mpoly_ctx_t mctx) { int cmp = 0; slong i, N; ulong * cmpmask, cmpmask1; TMP_INIT; FLINT_ASSERT(length >= 0); if (Abits < Bbits) { return _mpoly_monomials_cmp_repack_bits(Aexps, Abits, Bexps, Bbits, length, mctx); } else if (Abits > Bbits) { return -_mpoly_monomials_cmp_repack_bits(Bexps, Bbits, Aexps, Abits, length, mctx); } N = mpoly_words_per_exp(Abits, mctx); if (N == 1) { mpoly_get_cmpmask(&cmpmask1, 1, Abits, mctx); for (i = 0; i < length && cmp == 0; i++) cmp = mpoly_monomial_cmp1(Aexps[i], Bexps[i], cmpmask1); } else { TMP_START; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, mctx); for (i = 0; i < length && cmp == 0; i++) cmp = mpoly_monomial_cmp(Aexps + N*i, Bexps + N*i, N, cmpmask); TMP_END; } return cmp; } flint-3.1.3/src/mpoly/monomials_deflate.c000066400000000000000000000031641461254215100204140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" void mpoly_monomials_deflate(ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength, const fmpz * shift, const fmpz * stride, const mpoly_ctx_t mctx) { slong i, j; slong NA, NB; slong nvars = mctx->nvars; fmpz * exps; TMP_INIT; TMP_START; exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exps + j); NA = mpoly_words_per_exp(Abits, mctx); NB = mpoly_words_per_exp(Bbits, mctx); for (i = 0; i < Blength; i++) { mpoly_get_monomial_ffmpz(exps, Bexps + NB*i, Bbits, mctx); for (j = 0; j < nvars; j++) { fmpz_sub(exps + j, exps + j, shift + j); /* stride + j is allowed to be zero */ if (!fmpz_is_zero(exps + j)) { FLINT_ASSERT(fmpz_divisible(exps + j, stride + j)); fmpz_divexact(exps + j, exps + j, stride + j); } } FLINT_ASSERT(Abits >= mpoly_exp_bits_required_ffmpz(exps, mctx)); mpoly_set_monomial_ffmpz(Aexps + NA*i, exps, Abits, mctx); } for (j = 0; j < nvars; j++) fmpz_clear(exps + j); TMP_END; } flint-3.1.3/src/mpoly/monomials_deflation.c000066400000000000000000000032161461254215100207530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" void mpoly_monomials_deflation(fmpz * shift, fmpz * stride, const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const mpoly_ctx_t mctx) { slong i, j; slong NA; slong nvars = mctx->nvars; fmpz_t d; fmpz * exps; TMP_INIT; for (j = 0; j < nvars; j++) fmpz_zero(stride + j); if (Alength == 0) { /* undefined case */ for (j = 0; j < nvars; j++) fmpz_zero(shift + j); return; } TMP_START; exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exps + j); fmpz_init(d); NA = mpoly_words_per_exp(Abits, mctx); i = Alength - 1; mpoly_get_monomial_ffmpz(shift, Aexps + NA*i, Abits, mctx); for (i--; i >= 0; i--) { mpoly_get_monomial_ffmpz(exps, Aexps + NA*i, Abits, mctx); for (j = 0; j < nvars; j++) { fmpz_sub(d, exps + j, shift + j); fmpz_gcd(stride + j, stride + j, d); if (fmpz_sgn(d) < 0) fmpz_swap(shift + j, exps + j); } } for (j = 0; j < nvars; j++) fmpz_clear(exps + j); fmpz_clear(d); TMP_END; } flint-3.1.3/src/mpoly/monomials_inflate.c000066400000000000000000000026601461254215100204320ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" void mpoly_monomials_inflate(ulong * Aexps, flint_bitcnt_t Abits, const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength, const fmpz * shift, const fmpz * stride, const mpoly_ctx_t mctx) { slong i, j; slong NA, NB; slong nvars = mctx->nvars; fmpz * exps; TMP_INIT; TMP_START; exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exps + j); NA = mpoly_words_per_exp(Abits, mctx); NB = mpoly_words_per_exp(Bbits, mctx); for (i = 0; i < Blength; i++) { mpoly_get_monomial_ffmpz(exps, Bexps + NB*i, Bbits, mctx); for (j = 0; j < nvars; j++) { fmpz_mul(exps + j, exps + j, stride + j); fmpz_add(exps + j, exps + j, shift + j); } FLINT_ASSERT(Abits >= mpoly_exp_bits_required_ffmpz(exps, mctx)); mpoly_set_monomial_ffmpz(Aexps + NA*i, exps, Abits, mctx); } for (j = 0; j < nvars; j++) fmpz_clear(exps + j); TMP_END; } flint-3.1.3/src/mpoly/monomials_inorder_test.c000066400000000000000000000016731461254215100215140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" int mpoly_monomials_inorder_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong N, i; ulong * cmpmask; N = mpoly_words_per_exp(bits, mctx); cmpmask = flint_malloc((N + 1)*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, mctx); for (i = 0; i + 1 < len; i++) { if (!mpoly_monomial_gt(exps + i*N, exps + (i + 1)*N, N, cmpmask)) { flint_free(cmpmask); return 0; } } flint_free(cmpmask); return 1; } flint-3.1.3/src/mpoly/monomials_overflow_test.c000066400000000000000000000017461461254215100217160ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" int mpoly_monomials_overflow_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong N, i; N = mpoly_words_per_exp(bits, mctx); if (bits <= FLINT_BITS) { ulong mask = mpoly_overflow_mask_sp(bits); for (i = 0; i < len; i++) if (mpoly_monomial_overflows(exps + i*N, N, mask)) return 1; } else { for (i = 0; i < len; i++) if (mpoly_monomial_overflows_mp(exps + i*N, N, bits)) return 1; } return 0; } flint-3.1.3/src/mpoly/monomials_shift_right_ui.c000066400000000000000000000043701461254215100220170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void mpoly_monomials_shift_right_ui(ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const ulong * user_exps, const mpoly_ctx_t mctx) { slong i; slong N = mpoly_words_per_exp(Abits, mctx); ulong * texps; TMP_INIT; TMP_START; texps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ui(texps, user_exps, Abits, mctx); if (Abits <= FLINT_BITS) { #if FLINT_WANT_ASSERT ulong mask = mpoly_overflow_mask_sp(Abits); #endif for (i = 0; i < Alength; i++) { mpoly_monomial_sub(Aexps + N*i, Aexps + N*i, texps, N); FLINT_ASSERT(!mpoly_monomial_overflows(Aexps + N*i, N, mask)); } } else { for (i = 0; i < Alength; i++) { mpoly_monomial_sub_mp(Aexps + N*i, Aexps + N*i, texps, N); FLINT_ASSERT(!mpoly_monomial_overflows_mp(Aexps + N*i, N, Abits)); } } TMP_END; } void mpoly_monomials_shift_right_ffmpz(ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const fmpz * user_exps, const mpoly_ctx_t mctx) { slong i; slong N = mpoly_words_per_exp(Abits, mctx); ulong * texps; TMP_INIT; TMP_START; texps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(texps, user_exps, Abits, mctx); if (Abits <= FLINT_BITS) { #if FLINT_WANT_ASSERT ulong mask = mpoly_overflow_mask_sp(Abits); #endif for (i = 0; i < Alength; i++) { mpoly_monomial_sub(Aexps + N*i, Aexps + N*i, texps, N); FLINT_ASSERT(!mpoly_monomial_overflows(Aexps + N*i, N, mask)); } } else { for (i = 0; i < Alength; i++) { mpoly_monomial_sub_mp(Aexps + N*i, Aexps + N*i, texps, N); FLINT_ASSERT(!mpoly_monomial_overflows_mp(Aexps + N*i, N, Abits)); } } TMP_END; } flint-3.1.3/src/mpoly/monomials_valid_test.c000066400000000000000000000024521461254215100211450ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" int mpoly_monomials_valid_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { int ret = 1; slong N, i, j; fmpz * fields; TMP_INIT; if (!mctx->deg) return ret; TMP_START; fields = TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (j = 0; j < mctx->nfields; j++) fmpz_init(fields + j); N = mpoly_words_per_exp(bits, mctx); for (i = 0; i < len; i++) { mpoly_unpack_vec_fmpz(fields, exps + i*N, bits, mctx->nfields, 1); for (j = 0; j < mctx->nvars; j++) { fmpz_sub(fields + mctx->nvars, fields + mctx->nvars, fields + j); } if (!fmpz_is_zero(fields + mctx->nvars)) { ret = 0; break; } } for (j = 0; j < mctx->nfields; j++) fmpz_clear(fields + j); TMP_END; return ret; } flint-3.1.3/src/mpoly/pack_monomials_tight.c000066400000000000000000000016631461254215100211270ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpoly.h" void mpoly_pack_monomials_tight(ulong * exp1, const ulong * exp2, slong len, const slong * mults, slong nfields, slong bits) { slong i, j, shift; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - bits); for (i = 0; i < len; i++) { shift = (nfields - 1)*bits; e = (exp2[i] >> shift) & mask; for (j = nfields - 2; j >= 0; j--) { shift -= bits; e *= mults[j]; e += (exp2[i] >> shift) & mask; } exp1[i] = e; } } flint-3.1.3/src/mpoly/pack_vec.c000066400000000000000000000063621461254215100165100ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* this file DOES NOT need to change with new orderings */ void mpoly_pack_vec_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len) { if (bits <= FLINT_BITS) { slong i, j; for (j = 0; j < len; j++) { ulong v = 0; slong shift = 0; i = 0; v |= *exp2++ << shift; shift += bits; /* number of bits to encode 0th field */ while (++i < nfields) { if (shift + bits > FLINT_BITS) { *exp1++ = v; v = 0; shift = 0; } v |= *exp2++ << shift; shift += bits; /* number of bits to encode ith field */ } *exp1++ = v; } } else { slong j; ulong words_per_field = bits/FLINT_BITS; FLINT_ASSERT(bits%FLINT_BITS == 0); for (j = 0; j < len*nfields; j++, exp2++) { ulong size = 0; *exp1++ = *exp2; size++; while (size++ < words_per_field) *exp1++ = 0; } } } void mpoly_pack_vec_fmpz(ulong * exp1, const fmpz * exp2, flint_bitcnt_t bits, slong nfields, slong len) { if (bits <= FLINT_BITS) { slong i, j; for (j = 0; j < len; j++) { ulong v = 0; slong shift = 0; i = 0; FLINT_ASSERT(fmpz_abs_fits_ui(exp2)); v |= fmpz_get_ui(exp2++) << shift; shift += bits; /* number of bits to encode 0th field */ while (++i < nfields) { if (shift + bits > FLINT_BITS) { *exp1++ = v; v = 0; shift = 0; } FLINT_ASSERT(fmpz_abs_fits_ui(exp2)); v |= fmpz_get_ui(exp2++) << shift; shift += bits; /* number of bits to encode ith field */ } *exp1++ = v; } } else { slong j; ulong words_per_field = bits/FLINT_BITS; FLINT_ASSERT(bits%FLINT_BITS == 0); for (j = 0; j < len*nfields; j++, exp2++) { ulong size = 0; if (fmpz_abs_fits_ui(exp2)) { *exp1++ = fmpz_get_ui(exp2); size++; } else { __mpz_struct * mpz = COEFF_TO_PTR(*exp2); FLINT_ASSERT(mpz->_mp_size <= words_per_field); while (size < mpz->_mp_size) *exp1++ = mpz->_mp_d[size++]; } while (size++ < words_per_field) *exp1++ = 0; } } } flint-3.1.3/src/mpoly/parse_pretty.c000066400000000000000000000334021461254215100174510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "mpoly.h" #define PREC_LOWEST 0 #define PREC_PLUS 1 #define PREC_MINUS 1 #define PREC_TIMES 2 #define PREC_DIVIDES 2 #define PREC_UPLUS 3 #define PREC_UMINUS 3 #define PREC_POWER 4 #define PREC_HIGHEST 255 #define OP_TIMES 0 #define OP_PLUS 1 #define OP_MINUS 2 #define OP_DIVIDES 3 #define OP_LROUND 4 #define FIX_INFIX 0 #define FIX_PREFIX 1 #define FIX_POSTFIX 2 #define FIX_MATCHFIX 3 static int _is_op(slong a) { return a >= 0; } static slong _op_make(slong name, slong fix, slong prec) { return (prec << 10) + (fix << 8) + (name << 0); } static slong _op_prec(slong a) { return (ulong)(a) >> 10; } static slong _op_fix(slong a) { return ((ulong)(a) >> 8) & 3; } static slong _op_name(slong a) { return a&255; } /* initialize the R member first */ void mpoly_parse_init(mpoly_parse_t E) { slong i; E->stack_len = 0; E->stack_alloc = 20; E->stack = FLINT_ARRAY_ALLOC(E->stack_alloc, slong); E->estore_len = 0; E->estore_alloc = 10; E->estore = flint_malloc(E->estore_alloc*E->R->elem_size); for (i = 0; i < E->estore_alloc; i++) E->R->init(E->estore + i*E->R->elem_size, E->R->ctx); E->terminals_len = 0; E->terminals_alloc = 5; E->terminal_strings = FLINT_ARRAY_ALLOC(E->terminals_alloc, string_with_length_struct); E->terminal_values = FLINT_ARRAY_ALLOC(E->terminals_alloc*E->R->elem_size, char); for (i = 0; i < E->terminals_alloc; i++) { E->terminal_strings[i].str = NULL; E->terminal_strings[i].str_len = 0; E->R->init(E->terminal_values + E->R->elem_size*i, E->R->ctx); } } void mpoly_parse_clear(mpoly_parse_t E) { slong i; flint_free(E->stack); for (i = 0; i < E->estore_alloc; i++) E->R->clear(E->estore + E->R->elem_size*i, E->R->ctx); flint_free(E->estore); for (i = 0; i < E->terminals_alloc; i++) { flint_free(E->terminal_strings[i].str); E->R->clear(E->terminal_values + E->R->elem_size*i, E->R->ctx); } flint_free(E->terminal_strings); flint_free(E->terminal_values); } void mpoly_parse_add_terminal(mpoly_parse_t E, const char * s, const void * val) { slong l, n = E->terminals_len; if (n + 1 > E->terminals_alloc) { slong i = E->terminals_alloc; slong new_alloc = FLINT_MAX(n + 1, i + i/2); E->terminal_strings = (string_with_length_struct *) flint_realloc( E->terminal_strings, new_alloc* sizeof(string_with_length_struct)); E->terminal_values = (char *) flint_realloc(E->terminal_values, E->R->elem_size*new_alloc); for ( ; i < new_alloc; i++) { E->terminal_strings[i].str = NULL; E->terminal_strings[i].str_len = 0; E->R->init(E->terminal_values + E->R->elem_size*i, E->R->ctx); } E->terminals_alloc = new_alloc; } l = strlen(s); E->terminal_strings[n].str_len = l; E->terminal_strings[n].str = (char *) flint_realloc(E->terminal_strings[n].str, l + 1); memcpy(E->terminal_strings[n].str, s, l + 1); E->R->set(E->terminal_values + E->R->elem_size*n, val, E->R->ctx); E->terminals_len = n + 1; while (n > 0 && E->terminal_strings[n-1].str_len < E->terminal_strings[n].str_len) { FLINT_SWAP(char *, E->terminal_strings[n-1].str, E->terminal_strings[n].str); FLINT_SWAP(slong, E->terminal_strings[n-1].str_len, E->terminal_strings[n].str_len); E->R->swap(E->terminal_values + E->R->elem_size*(n-1), E->terminal_values + E->R->elem_size*n, E->R->ctx); n--; } } static int mpoly_parse_top_is_expr(const mpoly_parse_t E) { return E->stack_len > 0 && !_is_op(E->stack[E->stack_len - 1]); } static void * mpoly_parse_top_expr(mpoly_parse_t E) { FLINT_ASSERT(E->stack_len > 0); FLINT_ASSERT(E->stack[E->stack_len - 1] < 0); return E->estore + E->R->elem_size*(-1 - E->stack[E->stack_len - 1]); } static void mpoly_parse_push_op(mpoly_parse_t E, slong op) { FLINT_ASSERT(_is_op(op)); _slong_array_fit_length(&E->stack, &E->stack_alloc, E->stack_len + 1); E->stack[E->stack_len] = op; E->stack_len++; } /* if the top is not an expr, push the tmp, otherwise fail */ static int mpoly_parse_push_expr(mpoly_parse_t E) { if (mpoly_parse_top_is_expr(E)) return -1; if (E->estore_len + 1 > E->estore_alloc) { slong i = E->estore_alloc; slong new_alloc = FLINT_MAX(E->estore_len + 1, i + i/2); E->estore = flint_realloc(E->estore, new_alloc*E->R->elem_size); for ( ; i < new_alloc; i++) E->R->init(E->estore + E->R->elem_size*i, E->R->ctx); E->estore_alloc = new_alloc; } _slong_array_fit_length(&E->stack, &E->stack_alloc, E->stack_len + 1); E->stack[E->stack_len] = -1 - E->estore_len; E->stack_len++; E->R->swap(E->estore + E->R->elem_size*E->estore_len, E->tmp, E->R->ctx); E->estore_len++; return 0; } /* if the top is an expr, pop it, otherwise fail */ static int mpoly_parse_pop_expr(mpoly_parse_t E) { if (!mpoly_parse_top_is_expr(E)) return -1; E->R->swap(E->tmp, E->estore + E->R->elem_size*(-1 - E->stack[E->stack_len - 1]), E->R->ctx); E->estore_len--; E->stack_len--; return 0; } /* if the top is an operation op, pop it, otherwise fail */ static int mpoly_parse_pop_op(mpoly_parse_t E, slong op) { slong n = E->stack_len - 1; if (n < 0 || !_is_op(E->stack[n]) || _op_name(E->stack[n]) != op) return -1; E->stack_len = n; return 0; } /* pop ops with precedence > prec */ static int mpoly_parse_pop_prec(mpoly_parse_t E, slong prec) { slong n, n1, n2, n3, p, l1, l3; if (E->stack_len < 1) return -1; again: n = E->stack_len; if (n < 2) return 0; n1 = E->stack[n-1]; n2 = E->stack[n-2]; if (_is_op(n1) || !_is_op(n2)) return 0; n1 = -1-n1; p = _op_prec(n2); if (p < prec) return 0; if (_op_fix(n2) == FIX_INFIX) { n3 = E->stack[n-3]; FLINT_ASSERT(!_is_op(n3)); n3 = -1 - n3; FLINT_ASSERT(n1 == n3 + 1); if (_op_name(n2) == OP_TIMES) { E->R->mul(E->tmp, E->estore + E->R->elem_size*n3, E->estore + E->R->elem_size*n1, E->R->ctx); E->R->swap(E->estore + E->R->elem_size*n3, E->tmp, E->R->ctx); E->estore_len -= 1; E->stack_len -= 2; } else if (_op_name(n2) == OP_PLUS) { l1 = E->R->length(E->estore + E->R->elem_size*n1, E->R->ctx); l3 = E->R->length(E->estore + E->R->elem_size*n3, E->R->ctx); do_plus: if (l1 > l3) { FLINT_SWAP(slong, l3, l1); E->R->swap(E->estore + E->R->elem_size*n3, E->estore + E->R->elem_size*n1, E->R->ctx); } if (p > prec || 2*l1 >= l3) { E->R->add(E->estore + E->R->elem_size*n3, E->estore + E->R->elem_size*n3, E->estore + E->R->elem_size*n1, E->R->ctx); E->estore_len -= 1; E->stack_len -= 2; } else { return 0; } } else if (_op_name(n2) == OP_MINUS) { l1 = E->R->length(E->estore + E->R->elem_size*n1, E->R->ctx); l3 = E->R->length(E->estore + E->R->elem_size*n3, E->R->ctx); if (4*l1 >= l3 || 4*l3 >= l1) { E->R->sub(E->estore + E->R->elem_size*n3, E->estore + E->R->elem_size*n3, E->estore + E->R->elem_size*n1, E->R->ctx); E->estore_len -= 1; E->stack_len -= 2; } else { E->R->neg(E->estore + E->R->elem_size*n1, E->estore + E->R->elem_size*n1, E->R->ctx); E->stack[n-2] = _op_make(OP_PLUS, FIX_INFIX, PREC_PLUS); goto do_plus; } } else if (_op_name(n2) == OP_DIVIDES) { /* NOTE: if divides and times have the same precedence and the multiplications were to be delayed as the addition are, then there would have to be more shenenigans here. */ if (!E->R->divides(E->tmp, E->estore + E->R->elem_size*n3, E->estore + E->R->elem_size*n1, E->R->ctx)) { return -1; } E->R->swap(E->estore + E->R->elem_size*n3, E->tmp, E->R->ctx); E->estore_len -= 1; E->stack_len -= 2; } else { flint_throw(FLINT_ERROR, "_pop_stack: internal error"); } goto again; } else if (_op_fix(n2) == FIX_PREFIX) { if (_op_name(n2) == OP_MINUS) E->R->neg(E->estore + E->R->elem_size*n1, E->estore + E->R->elem_size*n1, E->R->ctx); E->stack[n-2] = -1-n1; E->stack_len -= 1; goto again; } else { return 0; } } static const char * _parse_int(fmpz_t c, const char * s, const char * end) { char * buffer, * v; const char * send = s + 1; TMP_INIT; while (send < end && '0' <= *send && *send <= '9') send++; TMP_START; v = buffer = (char *) TMP_ALLOC((send - s + 1)*sizeof(char)); while (s < send) *v++ = *s++; *v++ = '\0'; fmpz_set_str(c, buffer, 10); TMP_END; return s; } int mpoly_parse_parse(mpoly_parse_t E, void * poly, const char * s, slong slen) { const char * send = s + slen; fmpz_t c; int ret; fmpz_init(c); E->tmp = poly; while (s < send) { if ('0' <= *s && *s <= '9') { s = _parse_int(c, s, send); E->R->set_fmpz(E->tmp, c, E->R->ctx); if (mpoly_parse_push_expr(E)) goto failed; } else if (*s == '^') { if (++s >= send || !('0' <= *s && *s <= '9')) goto failed; s = _parse_int(c, s, send); if (mpoly_parse_pop_prec(E, PREC_POWER)) goto failed; if (!mpoly_parse_top_is_expr(E)) goto failed; if (!E->R->pow_fmpz(mpoly_parse_top_expr(E), mpoly_parse_top_expr(E), c, E->R->ctx)) goto failed; } else if (*s == '*') { if (!mpoly_parse_top_is_expr(E)) goto failed; if (mpoly_parse_pop_prec(E, PREC_TIMES)) goto failed; mpoly_parse_push_op(E, _op_make(OP_TIMES, FIX_INFIX, PREC_TIMES)); s++; } else if (*s == '+') { if (!mpoly_parse_top_is_expr(E)) { mpoly_parse_push_op(E, _op_make(OP_PLUS, FIX_PREFIX, PREC_UPLUS)); } else { if (mpoly_parse_pop_prec(E, PREC_PLUS)) goto failed; mpoly_parse_push_op(E, _op_make(OP_PLUS, FIX_INFIX, PREC_PLUS)); } s++; } else if (*s == '-') { if (!mpoly_parse_top_is_expr(E)) { mpoly_parse_push_op(E, _op_make(OP_MINUS, FIX_PREFIX, PREC_UMINUS)); } else { if (mpoly_parse_pop_prec(E, PREC_MINUS)) goto failed; mpoly_parse_push_op(E, _op_make(OP_MINUS, FIX_INFIX, PREC_MINUS)); } s++; } else if (*s == '/') { if (!mpoly_parse_top_is_expr(E)) goto failed; if (mpoly_parse_pop_prec(E, PREC_DIVIDES)) goto failed; mpoly_parse_push_op(E, _op_make(OP_DIVIDES, FIX_INFIX, PREC_DIVIDES)); s++; } else if (*s == ' ') { s++; } else if (*s == '(') { if (mpoly_parse_top_is_expr(E)) goto failed; mpoly_parse_push_op(E, _op_make(OP_LROUND, FIX_MATCHFIX, PREC_LOWEST)); s++; } else if (*s == ')') { if (mpoly_parse_pop_prec(E, PREC_LOWEST)) goto failed; if (mpoly_parse_pop_expr(E)) goto failed; if (mpoly_parse_pop_op(E, OP_LROUND)) goto failed; if (mpoly_parse_push_expr(E)) goto failed; s++; } else { slong k; for (k = 0; k < E->terminals_len; k++) { slong l = E->terminal_strings[k].str_len; if (0 == strncmp(s, E->terminal_strings[k].str, l)) { E->R->set(E->tmp, E->terminal_values + E->R->elem_size*k, E->R->ctx); if (mpoly_parse_push_expr(E)) goto failed; s += l; goto continue_outer; } } goto failed; } continue_outer:; } if (mpoly_parse_pop_prec(E, PREC_LOWEST)) goto failed; if (mpoly_parse_pop_expr(E)) goto failed; if (E->stack_len != 0) goto failed; ret = 0; done: fmpz_clear(c); return ret; failed: ret = -1; goto done; } flint-3.1.3/src/mpoly/profile/000077500000000000000000000000001461254215100162225ustar00rootroot00000000000000flint-3.1.3/src/mpoly/profile/p-test_irreducible.c000066400000000000000000000067321461254215100221630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" #include "profiler.h" int main(void) { slong i, j, k, total_time; timeit_t timer; flint_rand_t state; flint_randinit(state); flint_printf("------------------------------\n"); total_time = 0; timeit_start(timer); for (i = 0; i < 20000; i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len1, len2; flint_bitcnt_t bits1, bits2; if (0 == i%1000) { flint_printf("%wd ", i); fflush(stdout); } fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len1 = n_randint(state, 10) + 2; len2 = n_randint(state, 10) + 2; bits1 = n_randint(state, 9) + 1; bits2 = n_randint(state, 9) + 1; fmpz_mpoly_randtest_bits(h, state, len1, 10, bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, 10, bits2, ctx); fmpz_mpoly_mul(f, h, g, ctx); if (mpoly_test_irreducible(f->exps, f->bits, f->length, ctx->minfo) && h->length > 1 && g->length > 1) { flint_printf("FAIL: check reducible input\n"); flint_printf("f: "); fmpz_mpoly_print_pretty(f, NULL, ctx); flint_printf("\n"); flint_printf("g: "); fmpz_mpoly_print_pretty(g, NULL, ctx); flint_printf("\n"); flint_printf("h: "); fmpz_mpoly_print_pretty(h, NULL, ctx); flint_printf("\n"); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } timeit_stop(timer); total_time += timer->wall; flint_printf("\nreducible time: %wd ms\n\n", timer->wall); flint_printf("------------------------------\n"); total_time = 0; for (i = 2; i <= 16; i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; slong tot = 0, pos = 0; ulong * bounds = FLINT_ARRAY_ALLOC(i, ulong); fmpz_mpoly_ctx_init(ctx, i, ORD_LEX); fmpz_mpoly_init(f, ctx); timeit_start(timer); for (j = 0; j < 1000; j++) { flint_bitcnt_t bits = n_randint(state, 5) + 3; slong len = 10; for (k = 0; k < i; k++) { bounds[k] = n_urandint(state, UWORD(1) << bits) + 2; len += 3 + n_urandint(state, 2*bounds[k]); } fmpz_mpoly_randtest_bounds(f, state, len, 10, bounds, ctx); tot += 1; pos += mpoly_test_irreducible(f->exps, f->bits, f->length, ctx->minfo); } timeit_stop(timer); total_time += timer->wall; flint_printf("%wd vars: %f percent %wd ms\n", i, (double)(pos)/(double)(tot)*100, timer->wall); flint_free(bounds); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } flint_printf("irreducible time: %wd ms\n\n", total_time); flint_randclear(state); return 0; } flint-3.1.3/src/mpoly/randbits_fmpz.c000066400000000000000000000022411461254215100175670ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* this file DOES NOT need to change with new orderings */ /* Get a user exponent "exp"' such that it can be packed into "exp_bits" bits. The count "exp_bits" includes the extra bits for the sign. */ void mpoly_monomial_randbits_fmpz(fmpz * exp, flint_rand_t state, flint_bitcnt_t exp_bits, const mpoly_ctx_t mctx) { slong j; flint_bitcnt_t newbits = exp_bits; while (newbits != (flint_bitcnt_t)(0)) { for (j = 0; j < mctx->nvars; j++) { fmpz_randtest_unsigned(exp + j, state, newbits); } if (mpoly_exp_bits_required_ffmpz(exp, mctx) <= exp_bits) return; newbits--; } for (j = 0; j < mctx->nvars; j++) { fmpz_zero(exp + j); } } flint-3.1.3/src/mpoly/rbtree.c000066400000000000000000000247311461254215100162200ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* red-black tree with ui keys ***********************************************/ void mpoly_rbtree_ui_init(mpoly_rbtree_ui_t T, slong data_size) { mpoly_rbnode_ui_struct * nodes; T->length = 0; T->node_alloc = 2; T->nodes = FLINT_ARRAY_ALLOC(T->node_alloc, mpoly_rbnode_ui_struct); T->data = NULL; T->data_alloc = 0; T->data_size = data_size; nodes = T->nodes + 2; /* pointer to head */ nodes[-1].up = -2; nodes[-1].left = -2; /* head */ nodes[-1].right = -2; nodes[-1].key = 0; nodes[-1].color = 0; /* null node */ nodes[-2].up = -2; nodes[-2].left = -2; nodes[-2].right = -2; nodes[-2].key = 0; nodes[-2].color = 0; } /* the memory management of the data chunks must be done prior */ void mpoly_rbtree_ui_clear(mpoly_rbtree_ui_t T) { FLINT_ASSERT(T->node_alloc > 0); flint_free(T->nodes); flint_free(T->data); } static void mpoly_rbtree_ui_fit_length(mpoly_rbtree_ui_t T, slong len) { slong dsize = T->data_size; if (len + 2 > T->node_alloc) { slong new_alloc = FLINT_MAX(len + 2, 2*T->node_alloc); T->nodes = FLINT_ARRAY_REALLOC(T->nodes, new_alloc, mpoly_rbnode_ui_struct); T->node_alloc = new_alloc; } if (dsize*len > T->data_alloc) { slong new_alloc = FLINT_MAX(dsize*len, 2*T->data_alloc); T->data = FLINT_ARRAY_REALLOC(T->data, new_alloc, char); T->data_alloc = new_alloc; } } /* If the key rcx exists, a pointer to its data will be returned and new will be set to 0. Otherwise, a pointer to a new data chunk is returned and new is set to 1. */ void * mpoly_rbtree_ui_lookup(mpoly_rbtree_ui_t T, int * new, ulong rcx) { slong dsize = T->data_size; mpoly_rbnode_ui_struct * nodes = T->nodes + 2; slong rax, rdx, r8, r9, r10, r11; slong n = T->length; r10 = nodes[-1].left; if (n < 1) { mpoly_rbtree_ui_fit_length(T, 1); nodes = T->nodes + 2; rax = 0; nodes[rax].up = -1; nodes[rax].left = -2; nodes[rax].right = -2; nodes[rax].color = 0; nodes[rax].key = rcx; T->length = 1; *new = 1; nodes[-1].left = rax; return T->data + dsize*rax; } Compare: FLINT_ASSERT(r10 >= 0); r8 = nodes[r10].left; r9 = nodes[r10].right; if (rcx < nodes[r10].key) goto GoLeft; if (rcx > nodes[r10].key) goto GoRight; rax = r10; * new = 0; return T->data + dsize*rax; GoLeft: if (r8 < 0) { FLINT_ASSERT(r8 == -2); goto MakeNewLeft; } r10 = r8; goto Compare; GoRight: if (r9 < 0) { FLINT_ASSERT(r9 == -2); goto MakeNewRight; } r10 = r9; goto Compare; MakeNewLeft: mpoly_rbtree_ui_fit_length(T, n + 1); nodes = T->nodes + 2; rdx = n; nodes[r10].left = rdx; goto FixTree; MakeNewRight: mpoly_rbtree_ui_fit_length(T, n + 1); nodes = T->nodes + 2; rdx = n; nodes[r10].right = rdx; FixTree: nodes[rdx].up = r10; nodes[rdx].left = -2; nodes[rdx].right = -2; nodes[rdx].color = 1; nodes[rdx].key = rcx; T->length = n + 1; *new = 1; rax = rdx; FixNode: /*Case1:*/ r8 = nodes[rdx].up; if (r8 < 0) { FLINT_ASSERT(r8 == -1); FLINT_ASSERT(nodes[-1].left == rdx); nodes[rdx].color = 0; return T->data + dsize*rax; } /*Case2:*/ if (nodes[r8].color == 0) return T->data + dsize*rax; /*Case3:*/ r9 = nodes[r8].up; r10 = nodes[r9].left; r11 = nodes[r9].right; if (r8 == r10) r10 = r11; if (r10 < 0 || nodes[r10].color == 0) goto Case4; rdx = r9; nodes[r8].color = 0; nodes[r9].color = 1; nodes[r10].color = 0; goto FixNode; Case4: r10 = nodes[r9].up; /*Case4A:*/ if (rdx != nodes[r8].right || r8 != nodes[r9].left) goto Case4B; r11 = nodes[rdx].left; nodes[r9].left = rdx; nodes[rdx].left = r8; nodes[r8].right = r11; nodes[r8].up = rdx; nodes[rdx].up = r9; nodes[r11].up = r8; goto Case4Done; Case4B: if (rdx != nodes[r8].left || r8 != nodes[r9].right) goto Case5; r11 = nodes[rdx].right; nodes[r9].right = rdx; nodes[rdx].right = r8; nodes[r8].left = r11; nodes[r8].up = rdx; nodes[rdx].up = r9; nodes[r11].up = r8; Case4Done: FLINT_SWAP(slong, rdx, r8); Case5: if (nodes[r10].right == r9) nodes[r10].right = r8; if (nodes[r10].left == r9) nodes[r10].left = r8; nodes[r8].up = r10; nodes[r8].color = 0; nodes[r9].up = r8; nodes[r9].color = 1; r11 = nodes[r8].right; r10 = nodes[r8].left; if (rdx == r10) { nodes[r8].right = r9; nodes[r9].left = r11; nodes[r11].up = r9; } else { nodes[r8].left = r9; nodes[r9].right = r10; nodes[r10].up = r9; } return T->data + dsize*rax; } /* red-black tree with fmpz keys *********************************************/ void mpoly_rbtree_fmpz_init(mpoly_rbtree_fmpz_t T, slong data_size) { mpoly_rbnode_fmpz_struct * nodes; T->length = 0; T->node_alloc = 2; T->nodes = FLINT_ARRAY_ALLOC(T->node_alloc, mpoly_rbnode_fmpz_struct); T->data = NULL; T->data_alloc = 0; T->data_size = data_size; nodes = T->nodes + 2; /* pointer to head */ nodes[-1].up = -2; nodes[-1].left = -2; /* head */ nodes[-1].right = -2; fmpz_init(nodes[-1].key); nodes[-1].color = 0; /* null node */ nodes[-2].up = -2; nodes[-2].left = -2; nodes[-2].right = -2; fmpz_init(nodes[-2].key); nodes[-2].color = 0; } /* the memory management of the data chunks must be done prior */ void mpoly_rbtree_fmpz_clear(mpoly_rbtree_fmpz_t T) { slong i; FLINT_ASSERT(T->node_alloc > 0); for (i = 0; i < T->node_alloc; i++) fmpz_clear(T->nodes[i].key); flint_free(T->nodes); flint_free(T->data); } static void mpoly_rbtree_fmpz_fit_length(mpoly_rbtree_fmpz_t T, slong len) { slong i, dsize = T->data_size; if (len + 2 > T->node_alloc) { slong new_alloc = FLINT_MAX(len + 2, 2*T->node_alloc); T->nodes = FLINT_ARRAY_REALLOC(T->nodes, new_alloc, mpoly_rbnode_fmpz_struct); for (i = T->node_alloc; i < new_alloc; i++) fmpz_init(T->nodes[i].key); T->node_alloc = new_alloc; } if (dsize*len > T->data_alloc) { slong new_alloc = FLINT_MAX(dsize*len, 2*T->data_alloc); T->data = FLINT_ARRAY_REALLOC(T->data, new_alloc, char); T->data_alloc = new_alloc; } } /* If the key rcx exists, a pointer to its data will be returned and new will be set to 0. Otherwise, a pointer to a new data chunk is returned and new is set to 1. */ void * mpoly_rbtree_fmpz_lookup(mpoly_rbtree_fmpz_t T, int * new, const fmpz_t rcx) { slong dsize = T->data_size; mpoly_rbnode_fmpz_struct * nodes = T->nodes + 2; slong rax, rdx, r8, r9, r10, r11; slong n = T->length; int cmp; r10 = nodes[-1].left; if (n < 1) { mpoly_rbtree_fmpz_fit_length(T, 1); nodes = T->nodes + 2; rax = 0; nodes[rax].up = -1; nodes[rax].left = -2; nodes[rax].right = -2; nodes[rax].color = 0; fmpz_set(nodes[rax].key, rcx); T->length = 1; *new = 1; nodes[-1].left = rax; return T->data + dsize*rax; } Compare: FLINT_ASSERT(r10 >= 0); r8 = nodes[r10].left; r9 = nodes[r10].right; cmp = fmpz_cmp(rcx, nodes[r10].key); if (cmp < 0) goto GoLeft; if (cmp > 0) goto GoRight; rax = r10; * new = 0; return T->data + dsize*rax; GoLeft: if (r8 < 0) { FLINT_ASSERT(r8 == -2); goto MakeNewLeft; } r10 = r8; goto Compare; GoRight: if (r9 < 0) { FLINT_ASSERT(r9 == -2); goto MakeNewRight; } r10 = r9; goto Compare; MakeNewLeft: mpoly_rbtree_fmpz_fit_length(T, n + 1); nodes = T->nodes + 2; rdx = n; nodes[r10].left = rdx; goto FixTree; MakeNewRight: mpoly_rbtree_fmpz_fit_length(T, n + 1); nodes = T->nodes + 2; rdx = n; nodes[r10].right = rdx; FixTree: nodes[rdx].up = r10; nodes[rdx].left = -2; nodes[rdx].right = -2; nodes[rdx].color = 1; fmpz_set(nodes[rdx].key, rcx); T->length = n + 1; *new = 1; rax = rdx; FixNode: /*Case1:*/ r8 = nodes[rdx].up; if (r8 < 0) { FLINT_ASSERT(r8 == -1); FLINT_ASSERT(nodes[-1].left == rdx); nodes[rdx].color = 0; return T->data + dsize*rax; } /*Case2:*/ if (nodes[r8].color == 0) return T->data + dsize*rax; /*Case3:*/ r9 = nodes[r8].up; r10 = nodes[r9].left; r11 = nodes[r9].right; if (r8 == r10) r10 = r11; if (r10 < 0 || nodes[r10].color == 0) goto Case4; rdx = r9; nodes[r8].color = 0; nodes[r9].color = 1; nodes[r10].color = 0; goto FixNode; Case4: r10 = nodes[r9].up; /*Case4A:*/ if (rdx != nodes[r8].right || r8 != nodes[r9].left) goto Case4B; r11 = nodes[rdx].left; nodes[r9].left = rdx; nodes[rdx].left = r8; nodes[r8].right = r11; nodes[r8].up = rdx; nodes[rdx].up = r9; nodes[r11].up = r8; goto Case4Done; Case4B: if (rdx != nodes[r8].left || r8 != nodes[r9].right) goto Case5; r11 = nodes[rdx].right; nodes[r9].right = rdx; nodes[rdx].right = r8; nodes[r8].left = r11; nodes[r8].up = rdx; nodes[rdx].up = r9; nodes[r11].up = r8; Case4Done: FLINT_SWAP(slong, rdx, r8); Case5: if (nodes[r10].right == r9) nodes[r10].right = r8; if (nodes[r10].left == r9) nodes[r10].left = r8; nodes[r8].up = r10; nodes[r8].color = 0; nodes[r9].up = r8; nodes[r9].color = 1; r11 = nodes[r8].right; r10 = nodes[r8].left; if (rdx == r10) { nodes[r8].right = r9; nodes[r9].left = r11; nodes[r11].up = r9; } else { nodes[r8].left = r9; nodes[r9].right = r10; nodes[r10].up = r9; } return T->data + dsize*rax; } flint-3.1.3/src/mpoly/remove_var_powers.c000066400000000000000000000032151461254215100204730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* this file does not need to change with new orderings */ /* set the array var_powers to the exponents on the monomial content of A and divide A by this monomial content */ void mpoly_remove_var_powers( fmpz * var_powers, ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx) { slong i, N = mpoly_words_per_exp(Abits, mctx); fmpz * minfields; ulong * minexp; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; minexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); minfields = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) fmpz_init(minfields + i); mpoly_min_fields_fmpz(minfields, Aexps, Alen, Abits, mctx); mpoly_get_monomial_ffmpz_unpacked_ffmpz(var_powers, minfields, mctx); mpoly_set_monomial_ffmpz(minexp, var_powers, Abits, mctx); if (!mpoly_monomial_is_zero(minexp, N)) { if (Abits <= FLINT_BITS) { for (i = 0; i < Alen; i++) mpoly_monomial_sub(Aexps + N*i, Aexps + N*i, minexp, N); } else { for (i = 0; i < Alen; i++) mpoly_monomial_sub_mp(Aexps + N*i, Aexps + N*i, minexp, N); } } TMP_END; } flint-3.1.3/src/mpoly/repack_monomials.c000066400000000000000000000070261461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" /* exps2 = packed vectors to unpack bits2 = bits per field in exps2 len = number of packed vectors to unpack nfields = number of elements in each vector exps1 = destination for unpacked vector bits1 = number of bits desired in return packed vector return 1 if the repacking was successful, 0 if it failed */ int mpoly_repack_monomials(ulong * exps1, flint_bitcnt_t bits1, const ulong * exps2, flint_bitcnt_t bits2, slong len, const mpoly_ctx_t mctx) { int success; slong i, j; slong nfields = mctx->nfields; slong N2 = mpoly_words_per_exp(bits2, mctx); slong N1 = mpoly_words_per_exp(bits1, mctx); TMP_INIT; if (bits1 == bits2) { for (i = 0; i < N2*len; i++) exps1[i] = exps2[i]; return 1; } TMP_START; if (bits1 > bits2) { success = 1; if (bits1 <= FLINT_BITS && bits2 <= FLINT_BITS) { ulong * tmp_exps = (ulong *) TMP_ALLOC(nfields*sizeof(ulong)); for (i = 0; i < len; i++) { mpoly_unpack_vec_ui(tmp_exps, exps2 + N2*i, bits2, nfields, 1); mpoly_pack_vec_ui(exps1 + N1*i, tmp_exps, bits1, nfields, 1); } } else { fmpz * tmp_exps = (fmpz *) TMP_ALLOC(nfields*sizeof(fmpz)); for (i = 0; i < nfields; i++) fmpz_init(tmp_exps + i); for (i = 0; i < len; i++) { mpoly_unpack_vec_fmpz(tmp_exps, exps2 + N2*i, bits2, nfields, 1); mpoly_pack_vec_fmpz(exps1 + N1*i, tmp_exps, bits1, nfields, 1); } for (i = 0; i < nfields; i++) fmpz_clear(tmp_exps + i); } } else { success = 0; if (bits1 <= FLINT_BITS && bits2 <= FLINT_BITS) { ulong mask = (-UWORD(1)) << (bits1 - 1); ulong * tmp_exps = (ulong *) TMP_ALLOC(nfields*sizeof(ulong)); for (i = 0; i < len; i++) { mpoly_unpack_vec_ui(tmp_exps, exps2 + N2*i, bits2, nfields, 1); for (j = 0; j < nfields; j++) { if (tmp_exps[j] & mask) goto cleanup; } mpoly_pack_vec_ui(exps1 + N1*i, tmp_exps, bits1, nfields, 1); } success = 1; } else { fmpz * tmp_exps = (fmpz *) TMP_ALLOC(nfields*sizeof(fmpz)); for (i = 0; i < nfields; i++) fmpz_init(tmp_exps + i); for (i = 0; i < len; i++) { mpoly_unpack_vec_fmpz(tmp_exps, exps2 + N2*i, bits2, nfields, 1); if (_fmpz_vec_max_bits(tmp_exps, nfields) >= bits1) goto cleanup1; mpoly_pack_vec_fmpz(exps1 + N1*i, tmp_exps, bits1, nfields, 1); } success = 1; cleanup1: for (i = 0; i < nfields; i++) fmpz_clear(tmp_exps + i); } } cleanup: TMP_END; return success; } flint-3.1.3/src/mpoly/reverse.c000066400000000000000000000014401461254215100164000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void mpoly_reverse(ulong * Aexp, const ulong * Bexp, slong len, slong N) { slong i; if (Aexp == Bexp) { for (i = 0; i < len/2; i++) { mpoly_monomial_swap(Aexp + N*i, Aexp + N*(len - i - 1), N); } } else { for (i = 0; i < len; i++) { mpoly_monomial_set(Aexp + N*i, Bexp + N*(len - i - 1), N); } } } flint-3.1.3/src/mpoly/search_monomials.c000066400000000000000000000162121461254215100202530ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* a and b are arrays of packed monomials define score(e) = (# cross products in a X b <= e) finds a monomial e such that lower <= score(e) <= upper or is as close as possible and store its score in e_score e is written in the same format as a and b three arrays find, gind, and hind, each of length a_len are need for working space the return pointer is one of find, gind, or hind the elements of this array are indices into b where the first monomial <= e was found */ void mpoly_search_monomials( slong ** e_ind, ulong * e, slong * e_score, slong * find, slong * gind, slong * hind, slong lower, slong upper, const ulong * a, slong a_len, const ulong * b, slong b_len, slong N, const ulong * cmpmask) { slong i, j, x; slong maxdiff, maxind; /* for each i, there is an integer 0 <= find[i] <= blen such that a[i] + b[find[i]-1] < fexp <= a[i] + b[find[i]] ( If fexp < a[0] + b[blen-1] then find[i] is blen. Similaryly if fexp >= a[i] + b[0], then find[i] is 0 ) fscore is score(fexp) ditto for g and h We always maintain paths f, h, g with corresponding exponents fexp > hexp > gexp. These paths are non-increasing. Example: b_len | | g=> |___________ | _ | _ h => |_ _______ | ______________ | _____ f => |_______ | _______ 0 +--------------______ 0 a_len */ slong fscore, gscore, hscore, tscore; ulong * fexp, * gexp, * hexp, * texp; slong * tind; ulong * temp_exp; FLINT_ASSERT(a_len > 0); FLINT_ASSERT(b_len > 0); FLINT_ASSERT(lower <= upper); /* set f to correspond to an upperbound on all products */ fscore = a_len * b_len; fexp = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_monomial_add_mp(fexp, a + 0*N, b + 0*N, N); for (i = 0; i < a_len; i++) find[i] = 0; /* set g to correspond to a lowerbound on all products */ gscore = 1; gexp = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_monomial_add_mp(gexp, a + (a_len - 1)*N, b + (b_len - 1)*N, N); for (i = 0; i < a_len; i++) gind[i] = b_len; gind[a_len - 1] = b_len - 1; /* just allocate h */ hexp = (ulong *) flint_malloc(N*sizeof(ulong)); temp_exp = (ulong *) flint_malloc(N*sizeof(ulong)); /* early exit */ if (fscore == gscore) goto return_f; /* main loop */ while (gscore < lower && upper < fscore) { /* find the index 'maxind' where gind[i] - find[i] is largest */ maxdiff = -1; maxind = -1; for (i = 0; i < a_len; i++) { if (maxdiff < gind[i] - find[i]) { maxdiff = gind[i] - find[i]; maxind = i; } } if (maxdiff == 0) { /* f and g are the same path */ break; } else if (maxdiff == 1) { /* there may or may not be another path between */ maxind = -1; for (i = 0; i < a_len; i++) { if (gind[i] > find[i]) { mpoly_monomial_add_mp(temp_exp, a + i*N, b + find[i]*N, N); if (mpoly_monomial_equal(temp_exp, fexp, N) == 0) { maxind = i; hind[maxind] = find[i]; mpoly_monomial_add_mp(hexp, a + maxind*N, b + hind[maxind]*N, N); } } } if (maxind == -1) /* there is no path between */ break; } else { /* there is definitely a path between */ hind[maxind] = (gind[maxind] + find[maxind])/2; } /* the point (maxind, hind[maxind)) is now set to a bisector get the corresponding monomial into hexp */ mpoly_monomial_add_mp(hexp, a + maxind*N, b + hind[maxind]*N, N); FLINT_ASSERT(mpoly_monomial_lt(hexp, fexp, N, cmpmask)); FLINT_ASSERT(mpoly_monomial_lt(gexp, hexp, N, cmpmask)); /* find new path for h through the point */ hscore = gscore + gind[maxind] - hind[maxind]; /* find new path for h to the right of the point */ for (i = maxind + 1; i < a_len; i++) { x = find[i]; for (j = FLINT_MIN(hind[i-1], gind[i]) - 1; j >= find[i]; j--) { mpoly_monomial_add_mp(temp_exp, a + i*N, b + j*N, N); if (mpoly_monomial_lt(hexp, temp_exp, N, cmpmask)) { x = j + 1; break; } } hind[i] = x; hscore += gind[i] - hind[i]; } /* find new path for h to the left of the point */ for (i = maxind - 1; i >= 0; i--) { x = FLINT_MAX(hind[i+1], find[i]); for (j = FLINT_MAX(hind[i+1], find[i]); j < gind[i]; j++) { mpoly_monomial_add_mp(temp_exp, a + i*N, b + j*N, N); if (mpoly_monomial_lt(hexp, temp_exp, N, cmpmask)) x = j + 1; else break; } hind[i] = x; hscore += gind[i] - hind[i]; } if (hscore <= upper) { tind = gind; tscore = gscore; texp = gexp; gind = hind; gscore = hscore; gexp = hexp; hind = tind; hscore = tscore; hexp = texp; } else { tind = find; tscore = fscore; texp = fexp; find = hind; fscore = hscore; fexp = hexp; hind = tind; hscore = tscore; hexp = texp; } } /* upper and lower bounds are out of range */ if (fscore <= lower) goto return_f; else if (gscore >= upper) goto return_g; /* found something in range */ else if (fscore <= upper) goto return_f; else if (gscore >= lower) goto return_g; /* could not get in range - choose closest one */ else if (fscore - upper < lower - gscore) goto return_f; else goto return_g; return_g: mpoly_monomial_set(e, gexp, N); *e_score = gscore; tind = gind; goto cleanup; return_f: mpoly_monomial_set(e, fexp, N); *e_score = fscore; tind = find; cleanup: flint_free(temp_exp); flint_free(hexp); flint_free(gexp); flint_free(fexp); * e_ind = tind; } flint-3.1.3/src/mpoly/set_monomial.c000066400000000000000000000063111461254215100174150ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" /* !!! this file DOES need to change with new orderings */ void mpoly_set_monomial_ui(ulong * poly_exps, const ulong * user_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong nfields = mctx->nfields; slong i = 0; ulong * tmp_exps, degree; fmpz * big_exps; TMP_INIT; TMP_START; tmp_exps = (ulong *) TMP_ALLOC(nfields*sizeof(ulong)); degree = 0; for (i = 0; i < nvars; i++) { degree += user_exps[i]; if (mctx->deg && degree < user_exps[i]) goto big_case; tmp_exps[mctx->rev ? i : nvars - 1 - i] = user_exps[i]; } if (mctx->deg) tmp_exps[nvars] = degree; mpoly_pack_vec_ui(poly_exps, tmp_exps, bits, nfields, 1); done: TMP_END; return; big_case: big_exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(big_exps + i, user_exps[i]); mpoly_set_monomial_ffmpz(poly_exps, big_exps, bits, mctx); for (i = 0; i < nvars; i++) fmpz_clear(big_exps + i); goto done; } void mpoly_set_monomial_ffmpz(ulong * poly_exps, const fmpz * user_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong nfields = mctx->nfields; slong i = 0; fmpz * tmp_exps; fmpz_t degree; TMP_INIT; TMP_START; fmpz_init_set_ui(degree, 0); tmp_exps = (fmpz *) TMP_ALLOC(nfields*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_add(degree, degree, user_exps + i); fmpz_init_set(tmp_exps + (mctx->rev ? i : nvars - 1 - i), user_exps + i); } if (mctx->deg) fmpz_init_set(tmp_exps + nvars, degree); mpoly_pack_vec_fmpz(poly_exps, tmp_exps, bits, nfields, 1); fmpz_clear(degree); for (i = 0; i < nvars; i++) fmpz_clear(tmp_exps + i); if (mctx->deg) fmpz_clear(tmp_exps + nvars); TMP_END; } void mpoly_set_monomial_pfmpz(ulong * poly_exps, fmpz * const * user_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong nvars = mctx->nvars; slong nfields = mctx->nfields; slong i = 0; fmpz * tmp_exps; fmpz_t degree; TMP_INIT; TMP_START; fmpz_init_set_ui(degree, 0); tmp_exps = (fmpz *) TMP_ALLOC(nfields*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_add(degree, degree, user_exps[i]); fmpz_init_set(tmp_exps + (mctx->rev ? i : nvars - 1 - i), user_exps[i]); } if (mctx->deg) fmpz_init_set(tmp_exps + nvars, degree); mpoly_pack_vec_fmpz(poly_exps, tmp_exps, bits, nfields, 1); fmpz_clear(degree); for (i = 0; i < nvars; i++) fmpz_clear(tmp_exps + i); if (mctx->deg) fmpz_clear(tmp_exps + nvars); TMP_END; } flint-3.1.3/src/mpoly/term_exp_fits.c000066400000000000000000000033471461254215100176050ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" int mpoly_term_exp_fits_ui(ulong * exps, flint_bitcnt_t bits, slong n, const mpoly_ctx_t mctx) { slong i, N; int ret; fmpz * unpacked_exps; TMP_INIT; TMP_START; unpacked_exps = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(unpacked_exps + i); N = mpoly_words_per_exp(bits, mctx); mpoly_get_monomial_ffmpz(unpacked_exps, exps + N*n, bits, mctx); ret = 1; for (i = 0; i < mctx->nvars; i++) { ret = ret && fmpz_abs_fits_ui(unpacked_exps + i); fmpz_clear(unpacked_exps + i); } TMP_END; return ret; } int mpoly_term_exp_fits_si(ulong * exps, flint_bitcnt_t bits, slong n, const mpoly_ctx_t mctx) { slong i, N; int ret; fmpz * unpacked_exps; TMP_INIT; TMP_START; unpacked_exps = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(unpacked_exps + i); N = mpoly_words_per_exp(bits, mctx); mpoly_get_monomial_ffmpz(unpacked_exps, exps + N*n, bits, mctx); ret = 1; for (i = 0; i < mctx->nvars; i++) { ret = ret && fmpz_fits_si(unpacked_exps + i); fmpz_clear(unpacked_exps + i); } TMP_END; return ret; } flint-3.1.3/src/mpoly/test/000077500000000000000000000000001461254215100155415ustar00rootroot00000000000000flint-3.1.3/src/mpoly/test/main.c000066400000000000000000000022761461254215100166400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-max_degrees_tight.c" #include "t-max_fields.c" #include "t-monomial_halves.c" #include "t-pack_unpack.c" #include "t-pack_unpack_tight.c" #include "t-search_monomials.c" #include "t-test_irreducible.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(mpoly_max_degrees_tight), TEST_FUNCTION(mpoly_max_fields), TEST_FUNCTION(mpoly_monomial_halves), TEST_FUNCTION(mpoly_pack_unpack), TEST_FUNCTION(mpoly_pack_unpack_tight), TEST_FUNCTION(mpoly_search_monomials), TEST_FUNCTION(mpoly_test_irreducible) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/mpoly/test/t-max_degrees_tight.c000066400000000000000000000056411461254215100216360ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" TEST_FUNCTION_START(mpoly_max_degrees_tight, state) { slong k, i, j, length, nfields, bits1, bits2; slong * bases, * max, * max2, * prods; ulong * a, * b, * c, * t; ulong max_length, max_fields; max_length = 100; max_fields = FLINT_BITS/8; /* exponents should fit in one word */ a = flint_malloc(max_length*max_fields*sizeof(ulong)); b = flint_malloc(max_length*max_fields*sizeof(ulong)); c = flint_malloc(max_length*max_fields*sizeof(ulong)); t = flint_malloc(max_length*sizeof(ulong)); bases = (slong *) flint_malloc(max_fields*sizeof(slong)); prods = (slong *) flint_malloc((max_fields + 1)*sizeof(slong)); max = (slong *) flint_malloc(max_fields*sizeof(ulong)); max2 = (slong *) flint_malloc(max_fields*sizeof(ulong)); for (k = 0; k < 1000 * flint_test_multiplier(); k++) { /* do FLINT_BITS => bits1 => tight packing => bits2 => FLINT_BITS and compare */ for (bits1 = 8; bits1 <= FLINT_BITS; bits1 *= 2) for (bits2 = bits1; bits2 <= FLINT_BITS; bits2 *= 2) { length = n_randint(state, max_length) + 1; nfields = n_randint(state, FLINT_BITS/FLINT_MAX(bits1, bits2)) + 1; for (j = 0; j < nfields; j++) max[j] = 0; for (j = 0; j < nfields; j++) bases[j] = n_randint(state, 200) + 1; prods[0] = 1; for (i = 0; i < nfields; i++) prods[i + 1] = prods[i]*bases[i]; for (i = 0; i < nfields*length; i += nfields) for (j = 0; j < nfields; j++) { a[i + j] = n_randint(state, bases[j]); max[j] = FLINT_MAX(max[j], a[i + j]); } mpoly_pack_vec_ui(b, a, bits1, nfields, length); mpoly_pack_monomials_tight(t, b, length, bases, nfields, bits1); mpoly_unpack_monomials_tight(c, t, length, bases, nfields, bits2); mpoly_max_degrees_tight(max2, t, length, prods, nfields); for (j = 0; j < nfields; j++) if (max[j] != max2[j]) { flint_printf("FAIL\nmax_degrees_tight"); fflush(stdout); flint_abort(); } } } flint_free(max2); flint_free(max); flint_free(prods); flint_free(bases); flint_free(t); flint_free(c); flint_free(b); flint_free(a); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpoly/test/t-max_fields.c000066400000000000000000000045071461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" TEST_FUNCTION_START(mpoly_max_fields, state) { slong k, i, j, length, nfields, bits; ulong * a, * b, * max, * max2; ulong max_length, max_fields; max_length = 100; max_fields = 20; a = (ulong *) flint_malloc(max_length*max_fields*sizeof(ulong)); b = (ulong *) flint_malloc(max_length*max_fields*sizeof(ulong)); max = (ulong *) flint_malloc(max_fields*sizeof(ulong)); max2 = (ulong *) flint_malloc(max_fields*sizeof(ulong)); for (k = 0; k < 100 * flint_test_multiplier(); k++) { /* calculate the maximum by hand using FLINT_BITS then pack FLINT_BITS => bits and compare the output */ for (bits = 8; bits <= FLINT_BITS; bits += 1) { mpoly_ctx_t mctx; length = n_randint(state, max_length) + 1; nfields = n_randint(state, max_fields) + 1; mpoly_ctx_init(mctx, nfields, ORD_LEX); for (j = 0; j < nfields; j++) max[j] = 0; for (i = 0; i < nfields*length; i += nfields) { for (j = 0; j < nfields; j++) { a[i + j] = n_randint(state, 0); a[i + j] &= (UWORD(1) << (bits - 1)) - 1; max[j] = FLINT_MAX(max[j], a[i + j]); } } /* FLINT_BITS => bits */ mpoly_pack_vec_ui(b, a, bits, nfields, length); mpoly_max_fields_ui_sp(max2, b, length, bits, mctx); for (i = 0; i < nfields; i++) if (max[i] != max2[i]) { printf("FAIL\n"); flint_printf("bits = %wd, nfields = %wd\n", bits, nfields); fflush(stdout); flint_abort(); } } } flint_free(max2); flint_free(max); flint_free(b); flint_free(a); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpoly/test/t-monomial_halves.c000066400000000000000000000067741461254215100213410ustar00rootroot00000000000000/* Copyright (C) 2022 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" TEST_FUNCTION_START(mpoly_monomial_halves, state) { slong i; for (i = 0; i < 10000*flint_test_multiplier(); i++) { mpoly_ctx_t ctx; slong N, v, nvars = 1 + n_randint(state, 20); fmpz* e; ulong* e1, * e2; flint_bitcnt_t bits; int all_are_even, res; mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state)); e = _fmpz_vec_init(nvars); _fmpz_vec_randtest_unsigned(e, state, nvars, n_randint(state, 200)); bits = mpoly_exp_bits_required_ffmpz(e, ctx); bits = mpoly_fix_bits(bits, ctx); N = mpoly_words_per_exp(bits, ctx); e1 = FLINT_ARRAY_ALLOC(N, ulong); e2 = FLINT_ARRAY_ALLOC(N, ulong); mpoly_set_monomial_ffmpz(e1, e, bits, ctx); if (bits <= FLINT_BITS) res = mpoly_monomial_overflows(e1, N, mpoly_overflow_mask_sp(bits)); else res = mpoly_monomial_overflows_mp(e1, N, bits); if (res) { flint_printf("FAIL: input should not overflow\n"); fflush(stdout); flint_abort(); } all_are_even = 1; for (v = 0; v < nvars; v++) if (fmpz_is_odd(e + v)) all_are_even = 0; if (bits <= FLINT_BITS) res = mpoly_monomial_halves(e2, e1, N, mpoly_overflow_mask_sp(bits)); else res = mpoly_monomial_halves_mp(e2, e1, N, bits); if (all_are_even) { if (!res) { flint_printf("FAIL: should have been able to halve exponent\n"); flint_printf("nvars = %wd, bits = %wu\n", nvars, bits); fflush(stdout); flint_abort(); } if (bits <= FLINT_BITS) res = mpoly_monomial_overflows(e2, N, mpoly_overflow_mask_sp(bits)); else res = mpoly_monomial_overflows_mp(e2, N, bits); if (res) { flint_printf("FAIL: half overflows\n"); flint_printf("nvars = %wd, bits = %wu\n", nvars, bits); fflush(stdout); flint_abort(); } if (bits <= FLINT_BITS) mpoly_monomial_add(e2, e2, e2, N); else mpoly_monomial_add_mp(e2, e2, e2, N); res = mpoly_monomial_equal(e1, e2, N); if (!res) { flint_printf("FAIL: double of half doesn't match\n"); flint_printf("nvars = %wd, bits = %wu\n", nvars, bits); fflush(stdout); flint_abort(); } } else { if (res) { flint_printf("FAIL: shouldn't have been able to halve exponent\n"); flint_printf("nvars = %wd, bits = %wu\n", nvars, bits); fflush(stdout); flint_abort(); } } mpoly_ctx_clear(ctx); _fmpz_vec_clear(e, nvars); flint_free(e1); flint_free(e2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpoly/test/t-pack_unpack.c000066400000000000000000000064121461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "mpoly.h" TEST_FUNCTION_START(mpoly_pack_unpack, state) { slong k, i, length, nfields, bits1, bits2; ulong * a, * b, * c, * d; ulong max_length, max_fields; max_length = 50; max_fields = 20; a = flint_malloc(max_length*max_fields*sizeof(ulong)); b = flint_malloc(max_length*max_fields*sizeof(ulong)); c = flint_malloc(max_length*max_fields*sizeof(ulong)); d = flint_malloc(max_length*max_fields*sizeof(ulong)); for (k = 0; k < 10 * flint_test_multiplier(); k++) { /* do FLINT_BITS => bits1 => FLINT_BITS and compare */ for (bits1 = 8; bits1 <= FLINT_BITS; bits1 += 1) { length = n_randint(state, max_length) + 1; nfields = n_randint(state, max_fields) + 1; for (i = 0; i < length*nfields; i++) a[i] = n_randint(state, 0) & (l_shift(UWORD(1), bits1) - 1); mpoly_pack_vec_ui(b, a, bits1, nfields, length); mpoly_unpack_vec_ui(c, b, bits1, nfields, length); for (i = 0; i < length*nfields; i++) if (a[i] != c[i]) { printf("FAIL\n"); flint_printf("bits1 = %wd fields = %wd len = %wd\n", bits1, nfields, length); fflush(stdout); flint_abort(); } } } for (k = 0; k < 1 * flint_test_multiplier(); k++) { /* do FLINT_BITS => bits1 => bits2 => FLINT_BITS and compare */ for (bits1 = MPOLY_MIN_BITS; bits1 <= FLINT_BITS; bits1 += 1) { for (bits2 = MPOLY_MIN_BITS; bits2 <= FLINT_BITS; bits2 += 1) { ulong mask = (l_shift(UWORD(1), bits1 - 1) - 1) & (l_shift(UWORD(1), bits2 - 1) - 1); mpoly_ctx_t mctx; length = n_randint(state, max_length) + 1; nfields = n_randint(state, max_fields) + 1; mpoly_ctx_init(mctx, nfields, ORD_LEX); for (i = 0; i < length*nfields; i++) { /* leave room for sign bit in the repacking */ a[i] = n_randlimb(state) & mask; } mpoly_repack_monomials(b, bits1, a, FLINT_BITS, length, mctx); mpoly_repack_monomials(c, bits2, b, bits1, length, mctx); mpoly_repack_monomials(d, FLINT_BITS, c, bits2, length, mctx); for (i = 0; i < length*nfields; i++) { if (a[i] != d[i]) { printf("FAIL\n"); flint_printf("bits1 = %wd, bits2 = %wd\n", bits1, bits2); fflush(stdout); flint_abort(); } } mpoly_ctx_clear(mctx); } } } flint_free(d); flint_free(c); flint_free(b); flint_free(a); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpoly/test/t-pack_unpack_tight.c000066400000000000000000000047611461254215100216340ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" TEST_FUNCTION_START(mpoly_pack_unpack_tight, state) { slong k, i, j, length, nfields, bits1, bits2; slong * bases; ulong * a, * b, * c, * d, * t; ulong max_length, max_fields; max_length = 50; max_fields = FLINT_BITS/8; /* exponents should fit in one word */ a = flint_malloc(max_length*max_fields*sizeof(ulong)); b = flint_malloc(max_length*max_fields*sizeof(ulong)); c = flint_malloc(max_length*max_fields*sizeof(ulong)); d = flint_malloc(max_length*max_fields*sizeof(ulong)); t = flint_malloc(max_length*sizeof(ulong)); bases = flint_malloc(max_fields*sizeof(slong)); for (k = 0; k < 20 * flint_test_multiplier(); k++) { /* do FLINT_BITS => bits1 => tight packing => bits2 => FLINT_BITS and compare */ for (bits1 = 8; bits1 <= FLINT_BITS; bits1 += 1) for (bits2 = 8; bits2 <= FLINT_BITS; bits2 += 1) { length = n_randint(state, max_length) + 1; nfields = n_randint(state, FLINT_BITS/FLINT_MAX(bits1, bits2)) + 1; for (j = 0; j < nfields; j++) bases[j] = n_randint(state, 200) + 1; for (i = 0; i < length; i += 1) for (j = 0; j < nfields; j++) a[nfields*i + j] = n_randint(state, bases[j]); mpoly_pack_vec_ui(b, a, bits1, nfields, length); mpoly_pack_monomials_tight(t, b, length, bases, nfields, bits1); mpoly_unpack_monomials_tight(c, t, length, bases, nfields, bits2); mpoly_unpack_vec_ui(d, c, bits2, nfields, length); for (i = 0; i < length*nfields; i++) if (a[i] != d[i]) { printf("FAIL\nunpack_monomials_tight\n"); flint_printf("bits1 = %wd, bits2 = %wd\n", bits1, bits2); fflush(stdout); flint_abort(); } } } flint_free(bases); flint_free(t); flint_free(d); flint_free(c); flint_free(b); flint_free(a); TEST_FUNCTION_END(state); } flint-3.1.3/src/mpoly/test/t-search_monomials.c000066400000000000000000000136761461254215100215060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(mpoly_search_monomials, state) { int i, j, k; /* get two random polys and test output of search */ for (k = 0; k < 1000*flint_test_multiplier(); k++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g; slong len1, len2; slong coeff_bits, exp_bits1, exp_bits2, fg_bits; ulong * e, * fexp, * gexp, * temp; slong e_score, * e_ind, *t1, *t2, *t3, score, x; slong lower, upper, N; ulong * cmpmask; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); len1 = n_randint(state, 100) + 1; len2 = n_randint(state, 100) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; coeff_bits = n_randint(state, 100) + 1; do { fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits1, ctx); fmpz_mpoly_assert_canonical(f, ctx); } while (f->length == 0); do { fmpz_mpoly_randtest_bits(g, state, len2, coeff_bits, exp_bits2, ctx); fmpz_mpoly_assert_canonical(g, ctx); } while (g->length == 0); fg_bits = FLINT_MAX(f->bits, g->bits); N = mpoly_words_per_exp(fg_bits, ctx->minfo); cmpmask = (ulong*) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, fg_bits, ctx->minfo); fexp = (ulong *) flint_malloc(f->length*N*sizeof(ulong)); gexp = (ulong *) flint_malloc(g->length*N*sizeof(ulong)); e = (ulong *) flint_malloc(N*sizeof(ulong)); temp = (ulong *) flint_malloc(N*sizeof(ulong)); t1 = (slong *) flint_malloc(f->length*N*sizeof(slong)); t2 = (slong *) flint_malloc(f->length*N*sizeof(slong)); t3 = (slong *) flint_malloc(f->length*N*sizeof(slong)); mpoly_repack_monomials(fexp, fg_bits, f->exps, f->bits, f->length, ctx->minfo); mpoly_repack_monomials(gexp, fg_bits, g->exps, g->bits, g->length, ctx->minfo); lower = n_randint(state, f->length*g->length); upper = n_randint(state, f->length*g->length); if (upper < lower) { x = lower; lower = upper; upper = x; } mpoly_search_monomials(&e_ind, e, &e_score, t1, t2, t3, lower, upper, fexp, f->length, gexp, g->length, N, cmpmask); /* make sure that e_ind is correct for e */ score = 0; for (i = 0; i < f->length; i++) { x = 0; for (j = 0; j < g->length; j++) { mpoly_monomial_add_mp(temp, fexp + i*N, gexp + j*N, N); if (mpoly_monomial_lt(e, temp, N, cmpmask)) { x = j + 1; } } if (x != e_ind[i]) { flint_printf("e_ind is not right x=%wd, e_ind[%wd]=%wd\n",x,i,e_ind[i]); flint_printf("lower = %wd upper = %wd\n",lower,upper); fmpz_mpoly_print_pretty(f,NULL,ctx);printf("\n\n"); fmpz_mpoly_print_pretty(g,NULL,ctx);printf("\n\n"); fflush(stdout); flint_abort(); } score += g->length - x; } /* make sure that e_score is correct for e */ if (score != e_score) { printf("e_score is not right\n"); fflush(stdout); flint_abort(); } /* if e_score is outside of [lower,upper] check that nothing closer works */ if (e_score < lower || e_score > upper) { slong returned_error, new_error, i1, j1; ulong * temp1; temp1 = (ulong *) flint_malloc(N*sizeof(ulong)); returned_error = e_score < lower ? lower - e_score : e_score - upper; for (i1 = 0; i1 < f->length; i1++) { for (j1 = 0; j1 < g->length; j1++) { mpoly_monomial_add_mp(temp1, fexp + i1*N, gexp + j1*N, N); score = 0; for (i = 0; i < f->length; i++) { x = 0; for (j = 0; j < g->length; j++) { mpoly_monomial_add_mp(temp, fexp + i*N, gexp + j*N, N); if (mpoly_monomial_lt(temp1, temp, N, cmpmask)) { x = j + 1; } } score += g->length - x; } if (!(score < lower || score > upper)) { printf("returned score is outside, but score inside exists\n"); fflush(stdout); flint_abort(); } new_error = score < lower ? lower - score : score - upper; if (new_error < returned_error) { printf("returned score is not closest possible\n"); fflush(stdout); flint_abort(); } } } flint_free(temp1); } flint_free(cmpmask); flint_free(fexp); flint_free(gexp); flint_free(temp); flint_free(t3); flint_free(t2); flint_free(t1); flint_free(e); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpoly/test/t-test_irreducible.c000066400000000000000000000075471461254215100215130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "fmpz_mpoly.h" TEST_FUNCTION_START(mpoly_test_irreducible, state) { slong i; { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; fmpz_mpoly_ctx_init(ctx, 8, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_set_str_pretty(f, "x1^809*x2^75*x3^384*x4^324*x5^74*x6^788*x7^83*x8^414+" "x1^805*x2^343*x3^595*x4^246*x5^32*x6^90*x7^473*x8^591+" "x1^718*x2^108*x3^680*x4^368*x5^358*x8^276+" "x1^683*x2^533*x4^649*x5^619*x6^136*x7^223*x8^610+" "x2^617*x3^777*x4^799*x5^443*x6^545*x7^166*x8^216+" "x1^485*x2^646*x3^424*x4^265*x5^416*x6^400*x7^278+" "x1^336*x2^149*x3^361*x4^691*x5^629*x6^282*x7^530*x8^259+" "x1^266*x3^258*x5^422*x6^637*x7^244*x8^236+" "x1^74*x2^812*x3^162*x4^417*x5^71*x6^188*x7^258*x8^637+" "x1^37*x2^604*x3^94*x4^474*x6^853*x7^521*x8^250", NULL, ctx); if (!mpoly_test_irreducible(f->exps, f->bits, f->length, ctx->minfo)) { flint_printf("FAIL: check 8 variable example\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; const char * vars[] = {"x", "y"}; fmpz_mpoly_ctx_init(ctx, 2, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_set_str_pretty(f, "y^2639+x^4432*y^2436+x^400*y^1827+x^1300", vars, ctx); if (!mpoly_test_irreducible(f->exps, f->bits, f->length, ctx->minfo)) { flint_printf("FAIL: check 2 variable example 1\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_set_str_pretty(f, "y^5481+x^2*y^5477+x^4167*y^4366+x^2700", vars, ctx); if (!mpoly_test_irreducible(f->exps, f->bits, f->length, ctx->minfo)) { flint_printf("FAIL: check 2 variable example 1\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } for (i = 0; i < 500*flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; slong len1, len2; flint_bitcnt_t bits1, bits2; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); len1 = n_randint(state, 10) + 2; len2 = n_randint(state, 10) + 2; bits1 = n_randint(state, 9) + 1; bits2 = n_randint(state, 9) + 1; fmpz_mpoly_randtest_bits(h, state, len1, 10, bits1, ctx); fmpz_mpoly_randtest_bits(g, state, len2, 10, bits2, ctx); fmpz_mpoly_mul(f, h, g, ctx); if (mpoly_test_irreducible(f->exps, f->bits, f->length, ctx->minfo) && h->length > 1 && g->length > 1) { flint_printf("FAIL: check reducible input\n"); flint_printf("f: "); fmpz_mpoly_print_pretty(f, NULL, ctx); flint_printf("\n"); flint_printf("g: "); fmpz_mpoly_print_pretty(g, NULL, ctx); flint_printf("\n"); flint_printf("h: "); fmpz_mpoly_print_pretty(h, NULL, ctx); flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/mpoly/test_irreducible.c000066400000000000000000000525461461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "long_extras.h" #include "fmpz.h" #include "mpoly.h" typedef struct { slong x; slong y; } point2d; static int _point2d_cmp(slong x1, slong y1, slong x2, slong y2) { if (x1 < x2) return -1; if (x1 > x2) return 1; if (y1 < y2) return -1; if (y1 > y2) return 1; return 0; } static int point2d_cmp(const point2d * p, const point2d * q) { return _point2d_cmp(p->x, p->y, q->x, q->y); } /* Standing on O and looking at A, is B strictly to the left? i.e. (A.y - O.y) * (B.x - O.x) - (A.x - O.x) * (B.y - O.y) < 0 */ static int _is_ccw(point2d O, point2d A, point2d B) { return z_mat22_det_is_negative(A.y - O.y, A.x - O.x, B.y - O.y, B.x - O.x); } typedef struct { point2d * points; slong length; slong alloc; } point2d_set_struct; typedef point2d_set_struct point2d_set_t[1]; #if FLINT_WANT_ASSERT static int point2d_set_is_canonical(const point2d_set_t A) { slong i; for (i = 1; i < A->length; i++) { if (point2d_cmp(A->points + i, A->points + i - 1) <= 0) return 0; } return 1; } #endif static void point2d_set_init(point2d_set_t A) { A->points = NULL; A->length = 0; A->alloc = 0; } static void point2d_set_clear(point2d_set_t A) { if (A->alloc > 0) flint_free(A->points); } static void point2d_set_swap(point2d_set_t A, point2d_set_t B) { point2d_set_struct t = *B; *B = *A; *A = t; } static void point2d_set_fit_length(point2d_set_t A, slong len) { if (len > A->alloc) { len = FLINT_MAX(len, 2*A->alloc); A->points = (point2d *) flint_realloc(A->points, len*sizeof(point2d)); A->alloc = len; } } static void point2d_set_sort(point2d_set_t A) { qsort(A->points, A->length, sizeof(point2d), (int(*)(const void*,const void*))point2d_cmp); } /* P is a sorted array of nP distinct points compute the points on a ccw traversal of the convex hull via Andrew's monotone chain convex hull algorithm */ static slong convex_hull_ccw(slong * idxs, const point2d * P, slong nP) { slong i, j, k = 0; if (nP < 3) { for (i = 0; i < nP; i++) idxs[i] = i; return nP; } for (i = 0; i < nP; i++) { while (k >= 2 && !_is_ccw(P[idxs[k - 2]], P[idxs[k - 1]], P[i])) k--; idxs[k++] = i; } for (i = nP - 1, j = k + 1; i > 0; i--) { while (k >= j && !_is_ccw(P[idxs[k - 2]], P[idxs[k - 1]], P[i - 1])) k--; idxs[k++] = i - 1; } return k - 1; } static int _is_in_polygon( point2d * V, /* ccw polygon is V[0] -> ... -> V[nV-1] -> V[0] */ slong nV, point2d p) { slong i, a, b, c; #if FLINT_WANT_ASSERT int check; i = nV - 1; check = !_is_ccw(V[0], V[i], p); for (i = nV - 2; i >= 0; i--) check &= !_is_ccw(V[i + 1], V[i], p); #endif again: FLINT_ASSERT(nV >= 3); if (nV < 8) { i = nV - 1; if (_is_ccw(V[0], V[i], p)) { FLINT_ASSERT(check == 0); return 0; } for (i = nV - 2; i >= 0; i--) { if (_is_ccw(V[i + 1], V[i], p)) { FLINT_ASSERT(check == 0); return 0; } } FLINT_ASSERT(check == 1); return 1; } a = nV/4; b = nV/2; c = nV - nV/4; if (_is_ccw(V[a], V[0], p)) { V += 0; nV = 1 + a; goto again; } if (_is_ccw(V[b], V[a], p)) { V += a; nV = 1 + b - a; goto again; } if (_is_ccw(V[c], V[b], p)) { V += b; nV = 1 + c - b; goto again; } if (!_is_ccw(V[0], V[c], p)) { FLINT_ASSERT(check == 1); return 1; } if (!_is_ccw(V[nV - 1], V[c], p)) { FLINT_ASSERT(check == !_is_ccw(V[0], V[nV - 1], p)); return !_is_ccw(V[0], V[nV - 1], p); } V += c; nV = nV - c; if (nV >= 3) goto again; FLINT_ASSERT(nV == 2); FLINT_ASSERT(check == 0); return 0; } /* T = A union ((B + s) intersect V) */ static void point2d_set_merge_shift( point2d_set_t T, const point2d_set_t A, const point2d_set_t B, slong sx, slong sy, point2d * V, slong nV) { point2d * Apoints, * Bpoints, * Tpoints; slong Alen = A->length; slong Blen = B->length; slong i, j, k; FLINT_ASSERT(T != A); FLINT_ASSERT(T != B); point2d_set_fit_length(T, Alen + Blen); Apoints = A->points; Bpoints = B->points; Tpoints = T->points; i = j = k = 0; while (i < Alen && j < Blen) { slong Bsx = Bpoints[j].x + sx; slong Bsy = Bpoints[j].y + sy; int cmp = _point2d_cmp(Apoints[i].x, Apoints[i].y, Bsx, Bsy); if (cmp < 0) { Tpoints[k] = Apoints[i]; i++; k++; } else if (cmp == 0) { Tpoints[k] = Apoints[i]; i++; j++; k++; } else { Tpoints[k].x = Bsx; Tpoints[k].y = Bsy; j++; k += _is_in_polygon(V, nV, Tpoints[k]); } } while (i < Alen) { Tpoints[k] = Apoints[i]; i++; k++; } while (j < Blen) { Tpoints[k].x = Bpoints[j].x + sx; Tpoints[k].y = Bpoints[j].y + sy; j++; k += _is_in_polygon(V, nV, Tpoints[k]); } T->length = k; FLINT_ASSERT(point2d_set_is_canonical(T)); } /* T = A union B */ static void point2d_set_merge( point2d_set_t T, const point2d_set_t A, const point2d_set_t B) { point2d * Apoints, * Bpoints, * Tpoints; slong Alen = A->length; slong Blen = B->length; slong i, j, k; FLINT_ASSERT(T != A); FLINT_ASSERT(T != B); point2d_set_fit_length(T, Alen + Blen); Apoints = A->points; Bpoints = B->points; Tpoints = T->points; i = j = k = 0; while (i < Alen && j < Blen) { int cmp = _point2d_cmp(Apoints[i].x, Apoints[i].y, Bpoints[j].x, Bpoints[j].y); if (cmp < 0) { Tpoints[k] = Apoints[i]; i++; k++; } else if (cmp == 0) { Tpoints[k] = Apoints[i]; i++; j++; k++; } else { Tpoints[k] = Bpoints[j]; j++; k += 1; } } while (i < Alen) { Tpoints[k] = Apoints[i]; i++; k++; } while (j < Blen) { Tpoints[k] = Bpoints[j]; j++; k += 1; } T->length = k; FLINT_ASSERT(point2d_set_is_canonical(T)); } #if FLINT_WANT_ASSERT static int point2d_set_contains(const point2d_set_t A, slong x, slong y) { slong lo = 0; slong mid; slong hi = A->length; const point2d * Apoints = A->points; int cmp; again: if (hi - lo < 8) { for ( ; lo < hi; lo++) { if (Apoints[lo].x == x && Apoints[lo].y == y) return 1; } return 0; } mid = lo + (hi - lo)/2; cmp = _point2d_cmp(Apoints[mid].x, Apoints[mid].y, x, y); if (cmp == 0) return 1; if (cmp < 0) lo = mid; else hi = mid; goto again; } #endif /* is A intersect B empty? */ int point2d_set_disjoint( const point2d_set_t A, const point2d_set_t B) { point2d * Apoints = A->points; point2d * Bpoints = B->points; slong Alen = A->length; slong Blen = B->length; slong lo, mid, hi; int cmp; #if FLINT_WANT_ASSERT int check = 1; for (lo = 0; lo < Blen; lo++) check &= !point2d_set_contains(A, Bpoints[lo].x, Bpoints[lo].y); #endif again: if (Alen < 1 || Blen < 1) { FLINT_ASSERT(check == 1); return 1; } if (Alen < Blen) { FLINT_SWAP(slong, Alen, Blen); { point2d * T = Apoints; Apoints = Bpoints; Bpoints = T; } } cmp = point2d_cmp(&Bpoints[0], &Apoints[0]); if (cmp == 0) { FLINT_ASSERT(check == 0); return 0; } if (cmp < 0) { Bpoints += 1; Blen -= 1; goto again; } /* throw out everything from A that is < B[0] if A contains B[0], return 0 */ lo = 0; hi = Alen - 1; cmp = point2d_cmp(&Bpoints[0], &Apoints[hi]); if (cmp >= 0) { FLINT_ASSERT(cmp == check); return cmp; } search: FLINT_ASSERT(point2d_cmp(&Apoints[lo], &Bpoints[0]) < 0); FLINT_ASSERT(point2d_cmp(&Bpoints[0], &Apoints[hi]) < 0); if (hi - lo < 8) { for (lo++ ; lo < hi; lo++) { cmp = point2d_cmp(&Bpoints[0], &Apoints[lo]); if (cmp == 0) { FLINT_ASSERT(check == 0); return 0; } if (cmp < 0) break; } Apoints += lo; Alen -= lo; Bpoints += 1; Blen -= 1; goto again; } mid = lo + (hi - lo)/2; cmp = point2d_cmp(&Apoints[mid], &Bpoints[0]); if (cmp == 0) { FLINT_ASSERT(check == 0); return 0; } if (cmp < 0) lo = mid; else hi = mid; goto search; } /* ccw polygon is V[0] -> ... -> V[nV-1] -> V[0] |verts coordinates| < 2^(FLINT_BITS - 3) */ static int convex_hull_is_indecomposable( point2d * V, slong nV, ulong bound, point2d_set_t Ai, /* tmp storage */ point2d_set_t Aim1, point2d_set_t T, point2d_set_t S, point2d * E, /* tmp of length nV */ slong * Egcd) /* tmp of length nV */ { slong i, j, k, g, prevx, prevy; ulong prod_hi, prod_lo; FLINT_ASSERT(nV >= 3); if (nV == 3) { ulong g = FLINT_ABS(V[2].x - V[0].x); g = n_gcd(g, FLINT_ABS(V[2].y - V[0].y)); g = n_gcd(g, FLINT_ABS(V[1].x - V[0].x)); g = n_gcd(g, FLINT_ABS(V[1].y - V[0].y)); return g == 1; } /* since |V[i]| < 2^(FLINT_BITS - 3), all |E[i]| < 2^(SMALL_FMPZ_BITCOUNT_MAX) and no addition V[i] + E[j] will overflow */ prevx = V[0].x; prevy = V[0].y; g = 0; prod_hi = 0; prod_lo = 1; for (i = nV - 1; i >= 0; i--) { E[i].x = prevx - V[i].x; E[i].y = prevy - V[i].y; prevx = V[i].x; prevy = V[i].y; Egcd[i] = n_gcd(FLINT_ABS(E[i].x), FLINT_ABS(E[i].y)); E[i].x /= Egcd[i]; E[i].y /= Egcd[i]; g = n_gcd(g, Egcd[i]); umul_ppmm(prod_hi, prod_lo, prod_lo, Egcd[i]); if (prod_hi != 0) return -1; } if (g > 1) return 0; if (prod_lo > bound) return -1; /* S = {V[0] + j*E[nV-1]}_j */ point2d_set_fit_length(S, Egcd[nV - 1]); for (j = 0; j < Egcd[nV - 1]; j++) { S->points[j].x = V[0].x - j*E[nV - 1].x; S->points[j].y = V[0].y - j*E[nV - 1].y; } S->length = Egcd[nV - 1]; point2d_set_sort(S); /* A_{i-1} is empty */ Aim1->length = 0; for (i = 0; i < nV - 1; i++) { point2d_set_fit_length(Ai, Egcd[i]); k = 0; for (j = 1; j <= Egcd[i]; j++) { Ai->points[k].x = V[0].x + j*E[i].x; Ai->points[k].y = V[0].y + j*E[i].y; if (!_is_in_polygon(V, nV, Ai->points[k])) break; k++; } Ai->length = k; point2d_set_sort(Ai); if (Aim1->length > 0) { point2d_set_merge(T, Ai, Aim1); point2d_set_swap(Ai, T); for (j = 1; j <= Egcd[i]; j++) { point2d_set_merge_shift(T, Ai, Aim1, j*E[i].x, j*E[i].y, V, nV); point2d_set_swap(Ai, T); if (!point2d_set_disjoint(Ai, S)) return 0; } } else { if (!point2d_set_disjoint(Ai, S)) return 0; } point2d_set_swap(Aim1, Ai); } return 1; } static void z_rand_vec_primitive( slong * v, slong len, flint_rand_t state, mp_limb_t bound) { slong i, g; again: g = 0; for (i = 0; i < len; i++) { v[i] = z_randint(state, bound); g = n_gcd(g, FLINT_ABS(v[i])); } if (g == 0) goto again; if (g == 1) return; for (i = 0; i < len; i++) v[i] /= g; } static int _test_indecomposable2( slong * a, slong * b, slong n) { slong i; ulong g = 0; for (i = 0; i < n; i++) g = n_gcd(g, FLINT_ABS(a[i] - b[i])); return g == 1; } static int _test_colinear( slong * a, slong * b, slong * c, slong n) { slong i; int result; fmpz_t tn, td, sn, sd, g; fmpz_init(tn); fmpz_init(td); fmpz_init(sn); fmpz_init(sd); fmpz_init(g); for (i = 0; i < n; i++) { fmpz_set_si(sn, a[i]); fmpz_sub_si(sn, sn, c[i]); fmpz_set_si(sd, a[i]); fmpz_sub_si(sd, sd, b[i]); fmpz_gcd(g, sn, sd); if (fmpz_is_zero(g)) continue; if (fmpz_sgn(sd) < 0) fmpz_neg(g, g); fmpz_divexact(sn, sn, g); fmpz_divexact(sd, sd, g); if (fmpz_is_zero(td)) { fmpz_swap(td, sd); fmpz_swap(tn, sn); } else if (!fmpz_equal(sd, td) || !fmpz_equal(sn, tn)) { result = 4; goto cleanup; } } if (fmpz_is_zero(td)) result = 0; else if (fmpz_sgn(tn) < 0) result = 1; else if (fmpz_cmp(tn, td) > 0) result = 2; else result = 3; cleanup: fmpz_clear(tn); fmpz_clear(td); fmpz_clear(sn); fmpz_clear(sd); fmpz_clear(g); return result; } static int _test_indecomposable3( slong * a, slong * b, slong * c, slong n) { slong i; ulong g; switch (_test_colinear(a, b, c, n)) { case 0: return 0; case 1: return _test_indecomposable2(c, b, n); case 2: return _test_indecomposable2(a, c, n); case 3: return _test_indecomposable2(a, b, n); default: break; } g = 0; for (i = 0; i < n; i++) { g = n_gcd(g, FLINT_ABS(a[i] - b[i])); g = n_gcd(g, FLINT_ABS(a[i] - c[i])); } return g == 1; } /* Fast Absolute Irreducibility Testing via Newton Polytopes Shuhong Gao and Alan G.B. Lauderz Aexps is the Alen x nvars exponent matrix with the entry A[i,j] at Aexps[i*stride + j] */ int _mpoly_test_irreducible( slong * Aexps, slong stride, slong Alen, slong nvars, flint_rand_t state, slong tries_left) /* what they call the "projection bound" */ { int success; slong i, j, newlen, hull_len; ulong matrix_bound = 2; ulong memory_bound = 1000; ulong max_memory_bound = UWORD(1) << (20 + FLINT_BITS/8); slong * rowx; slong * rowy; point2d * points; slong * dups; slong * hull_idxs; slong hull_idxs_alloc; point2d * hull_points; slong hull_points_alloc; point2d_set_t T1, T2, T3, T4; if (Alen < 2 || nvars < 2) return 0; if (Alen == 2) return _test_indecomposable2(Aexps + 0*stride, Aexps + 1*stride, nvars); if (Alen == 3) return _test_indecomposable3(Aexps + 0*stride, Aexps + 1*stride, Aexps + 2*stride, nvars); if (tries_left <= 0) return 0; rowx = FLINT_ARRAY_ALLOC(2*nvars, slong); rowy = rowx + nvars; points = FLINT_ARRAY_ALLOC(Alen, point2d); dups = FLINT_ARRAY_ALLOC(Alen, slong); hull_idxs_alloc = 10; hull_idxs = FLINT_ARRAY_ALLOC(hull_idxs_alloc, slong); hull_points_alloc = 4; hull_points = FLINT_ARRAY_ALLOC(hull_points_alloc, point2d); point2d_set_init(T1); point2d_set_init(T2); point2d_set_init(T3); point2d_set_init(T4); again: if (--tries_left < 0) { success = 0; goto cleanup; } memory_bound = FLINT_MIN(max_memory_bound, memory_bound/8*9); matrix_bound += 1; if (nvars == 2) { tries_left = 0; memory_bound = max_memory_bound; for (i = 0; i < Alen; i++) { slong lox = Aexps[i*stride + 0]; slong loy = Aexps[i*stride + 1]; if (FLINT_MIN(lox, loy) <= -(WORD(1) << (FLINT_BITS - 3)) || FLINT_MAX(lox, loy) >= WORD(1) << (FLINT_BITS - 3)) { success = 0; goto cleanup; } points[i].x = lox; points[i].y = loy; } } else { z_rand_vec_primitive(rowx, nvars, state, matrix_bound); z_rand_vec_primitive(rowy, nvars, state, matrix_bound); for (i = 0; i < Alen; i++) { ulong x2, x1, x0, y2, y1, y0, p2, p1, p0; x2 = x1 = x0 = y2 = y1 = y0 = 0; for (j = 0; j < nvars; j++) { smul_ppmm(p1, p0, Aexps[i*stride + j], rowx[j]); p2 = FLINT_SIGN_EXT(p1); add_sssaaaaaa(x2, x1, x0, x2, x1, x0, p2, p1, p0); smul_ppmm(p1, p0, Aexps[i*stride + j], rowy[j]); p2 = FLINT_SIGN_EXT(p1); add_sssaaaaaa(y2, y1, y0, y2, y1, y0, p2, p1, p0); } if (x2 != FLINT_SIGN_EXT(x0) || x1 != FLINT_SIGN_EXT(x0) || y2 != FLINT_SIGN_EXT(y0) || y1 != FLINT_SIGN_EXT(y0)) { goto again; } points[i].x = x0; points[i].y = y0; if (points[i].x <= -(WORD(1) << (FLINT_BITS - 3)) || points[i].y <= -(WORD(1) << (FLINT_BITS - 3)) || points[i].x >= WORD(1) << (FLINT_BITS - 3) || points[i].y >= WORD(1) << (FLINT_BITS - 3)) { goto again; } } } qsort(points, Alen, sizeof(point2d), (int(*)(const void*,const void*))point2d_cmp); /* delete duplicates and track which are duplicated */ dups[0] = 0; newlen = 1; for (i = 1; i < Alen; i++) { if (point2d_cmp(&points[newlen - 1], &points[i]) == 0) { dups[newlen - 1] = 1; } else { dups[newlen] = 0; points[newlen] = points[i]; newlen++; } } /* find indices of convex hull */ if (newlen + 1 > hull_idxs_alloc) { hull_idxs_alloc = newlen + 1; hull_idxs = (slong *) flint_realloc(hull_idxs, hull_idxs_alloc*sizeof(slong)); } hull_len = convex_hull_ccw(hull_idxs, points, newlen); if (hull_len < 3) goto again; /* ensure no duplicates on hull */ if (hull_len + 1 > hull_points_alloc) { hull_points_alloc = hull_len + 1; hull_points = (point2d *) flint_realloc(hull_points, hull_points_alloc*sizeof(point2d)); } for (i = 0; i < hull_len; i++) { hull_points[i] = points[hull_idxs[i]]; if (dups[hull_idxs[i]] != 0) goto again; } /* check indecomposability with a bound on the memory usage */ success = convex_hull_is_indecomposable(hull_points, hull_len, memory_bound, T1, T2, T3, T4, points, dups); if (success < 1) { if (success < 0) memory_bound = FLINT_MIN(max_memory_bound, memory_bound/8*9); goto again; } success = 1; cleanup: point2d_set_clear(T1); point2d_set_clear(T2); point2d_set_clear(T3); point2d_set_clear(T4); flint_free(rowx); flint_free(points); flint_free(dups); flint_free(hull_idxs); flint_free(hull_points); return success; } int mpoly_test_irreducible( ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t ctx) { int result, overflowed; slong n = ctx->nvars; slong i, j, N, sum_deg, tries; slong * uexps, * max_exps; flint_rand_t state; if (Abits > FLINT_BITS || Alen < 2) return 0; flint_randinit(state); uexps = FLINT_ARRAY_ALLOC(n*Alen, slong); max_exps = FLINT_ARRAY_ALLOC(n, slong); for (j = 0; j < n; j++) max_exps[j] = 0; N = mpoly_words_per_exp(Abits, ctx); for (i = 0; i < Alen; i++) { mpoly_get_monomial_ui_sp((ulong *)uexps + n*i, Aexps + N*i, Abits, ctx); for (j = 0; j < n; j++) max_exps[j] = FLINT_MAX(max_exps[j], uexps[n*i + j]); } sum_deg = 1; overflowed = 0; for (j = 0; j < n; j++) { if (z_add_checked(&sum_deg, sum_deg, max_exps[j])) { overflowed = 1; break; } } tries = 12; if (!overflowed) tries -= Alen/sum_deg/2; result = _mpoly_test_irreducible(uexps, n, Alen, n, state, tries); flint_randclear(state); flint_free(max_exps); flint_free(uexps); return result; } flint-3.1.3/src/mpoly/to_from_mpolyl.c000066400000000000000000000062031461254215100177700ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* this file does not need to change with new orderings */ /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k < m + 2 l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void mpoly_from_mpolyl_perm_inflate( ulong * Bexps, flint_bitcnt_t Bbits, const mpoly_ctx_t Bctx, ulong * Aexps, flint_bitcnt_t Abits, const mpoly_ctx_t Actx, slong length, const slong * perm, const ulong * shift, const ulong * stride) { slong i, k, l; slong n = Bctx->nvars; slong m = Actx->nvars; slong NB = mpoly_words_per_exp_sp(Bbits, Bctx); slong NA = mpoly_words_per_exp_sp(Abits, Actx); ulong * aexps, * bexps; TMP_INIT; FLINT_ASSERT(Actx->ord == ORD_LEX); FLINT_ASSERT(Bbits <= FLINT_BITS); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; aexps = TMP_ARRAY_ALLOC(m + n, ulong); bexps = aexps + m; for (i = 0; i < length; i++) { mpoly_get_monomial_ui(aexps, Aexps + NA*i, Abits, Actx); for (l = 0; l < n; l++) { bexps[l] = shift[l]; } for (k = 0; k < m; k++) { l = perm[k]; bexps[l] += stride[l]*aexps[k]; } mpoly_set_monomial_ui(Bexps + NB*i, bexps, Bbits, Bctx); } TMP_END; } void mpoly_to_mpolyl_perm_deflate( ulong * Aexps, flint_bitcnt_t Abits, const mpoly_ctx_t Actx, ulong * Bexps, flint_bitcnt_t Bbits, const mpoly_ctx_t Bctx, slong length, const slong * perm, const ulong * shift, const ulong * stride) { slong j, k, l; slong m = Actx->nvars; slong n = Bctx->nvars; slong NA = mpoly_words_per_exp_sp(Abits, Actx); slong NB = mpoly_words_per_exp_sp(Bbits, Bctx); ulong * aexps, * bexps; TMP_INIT; FLINT_ASSERT(Actx->ord == ORD_LEX); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(Bbits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; aexps = TMP_ARRAY_ALLOC(m + n, ulong); bexps = aexps + m; for (j = 0; j < length; j++) { mpoly_get_monomial_ui(bexps, Bexps + NB*j, Bbits, Bctx); for (k = 0; k < m; k++) { l = perm[k]; if (stride[l] == 1) { aexps[k] = (bexps[l] - shift[l]); } else { FLINT_ASSERT(stride[l] != 0); FLINT_ASSERT(((bexps[l] - shift[l]) % stride[l]) == 0); aexps[k] = (bexps[l] - shift[l]) / stride[l]; } } mpoly_set_monomial_ui(Aexps + NA*j, aexps, Abits, Actx); } TMP_END; } flint-3.1.3/src/mpoly/total_degree.c000066400000000000000000000062341461254215100173710ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" int mpoly_total_degree_fits_si(const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { int r; fmpz_t td; fmpz_init(td); mpoly_total_degree_fmpz(td, exps, len, bits, mctx); r = fmpz_fits_si(td); fmpz_clear(td); return r; } slong mpoly_total_degree_si(const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong r; fmpz_t td; fmpz_init(td); mpoly_total_degree_fmpz(td, exps, len, bits, mctx); r = fmpz_get_si(td); fmpz_clear(td); return r; } void mpoly_total_degree_fmpz(fmpz_t totdeg, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, j, N; fmpz_t tot; fmpz * tmp_exps; TMP_INIT; N = mpoly_words_per_exp(bits, mctx); fmpz_set_si(totdeg, -WORD(1)); TMP_START; tmp_exps = (fmpz *) TMP_ALLOC(mctx->nfields*sizeof(fmpz)); for (i = 0; i < mctx->nfields; i++) fmpz_init(tmp_exps + i); if (mctx->ord == ORD_DEGLEX || mctx->ord == ORD_DEGREVLEX) { /* total degree is in first term if it exists */ if (len > 0) { mpoly_unpack_vec_fmpz(tmp_exps, exps + N*0, bits, mctx->nfields, 1); fmpz_swap(totdeg, tmp_exps + mctx->nvars); } } else { /* general case that works for any ordering */ fmpz_init(tot); for (i = 0; i < len; i++) { mpoly_get_monomial_ffmpz(tmp_exps, exps + N*i, bits, mctx); fmpz_zero(tot); for (j = 0; j < mctx->nvars; j++) fmpz_add(tot, tot, tmp_exps + j); if (fmpz_cmp(totdeg, tot) < 0) fmpz_swap(totdeg, tot); } fmpz_clear(tot); } for (j = 0; j < mctx->nfields; j++) fmpz_clear(tmp_exps + j); TMP_END; return; } /* reference implementation */ void mpoly_total_degree_fmpz_ref(fmpz_t totdeg, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx) { slong i, j, N; fmpz_t tot; fmpz * tmp_exps; TMP_INIT; fmpz_set_si(totdeg, -WORD(1)); TMP_START; fmpz_init(tot); tmp_exps = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (j = 0; j < mctx->nvars; j++) fmpz_init(tmp_exps + j); N = mpoly_words_per_exp(bits, mctx); for (i = 0; i < len; i++) { mpoly_get_monomial_ffmpz(tmp_exps, exps + N*i, bits, mctx); fmpz_zero(tot); for (j = 0; j < mctx->nvars; j++) fmpz_add(tot, tot, tmp_exps + j); if (fmpz_cmp(totdeg, tot) < 0) fmpz_swap(totdeg, tot); } fmpz_clear(tot); for (j = 0; j < mctx->nvars; j++) fmpz_clear(tmp_exps + j); TMP_END; } flint-3.1.3/src/mpoly/univar.c000066400000000000000000000616371461254215100162470ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "fmpz_mod_mpoly.h" static void _fmpz_max(fmpz_t a, const fmpz_t b, const fmpz_t c) { fmpz_set(a, fmpz_cmp(b, c) > 0 ? b : c); } #define COEFF(A, i) ((void*)(A->coeffs + (i)*R->elem_size)) #define IS_ZERO(A) (R->is_zero(A, R->ctx)) #define ZERO(A) (R->zero(A, R->ctx)) #define ONE(A) (R->one(A, R->ctx)) #define SET(A, B) (R->set(A, B, R->ctx)) #define SWAP(A, B) (R->swap(A, B, R->ctx)) #define NEG(A, B) (R->neg(A, B, R->ctx)) #define ADD(A, B, C) (R->add(A, B, C, R->ctx)) #define SUB(A, B, C) (R->sub(A, B, C, R->ctx)) #define MUL_FMPZ(A, B, C) (R->mul_fmpz(A, B, C, R->ctx)) #define MUL(A, B, C) (R->mul(A, B, C, R->ctx)) #define DIVEXACT(A, B, C) (R->divexact(A, B, C, R->ctx)) #define DIVIDES(A, B, C) (R->divides(A, B, C, R->ctx)) #define POW_FMPZ(A, B, C) (R->pow_fmpz(A, B, C, R->ctx)) void * mpoly_void_ring_elem_init(mpoly_void_ring_t R) { void * a = flint_malloc(R->elem_size); R->init(a, R->ctx); return a; } void mpoly_void_ring_elem_clear(void * a, mpoly_void_ring_t R) { R->clear(a, R->ctx); flint_free(a); } void mpoly_univar_init(mpoly_univar_t A, mpoly_void_ring_t R) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; } void mpoly_univar_clear(mpoly_univar_t A, mpoly_void_ring_t R) { slong i; for (i = 0; i < A->alloc; i++) { R->clear(COEFF(A, i), R->ctx); fmpz_clear(A->exps + i); } flint_free(A->coeffs); flint_free(A->exps); } void mpoly_univar_swap(mpoly_univar_t A, mpoly_univar_t B) { mpoly_univar_struct t = *B; *B = *A; *A = t; } void mpoly_univar_fit_length(mpoly_univar_t A, slong len, mpoly_void_ring_t R) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, 2*A->alloc); if (len <= old_alloc) return; A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, fmpz); A->coeffs = flint_realloc(A->coeffs, new_alloc*R->elem_size); for (i = old_alloc; i < new_alloc; i++) { fmpz_init(A->exps + i); R->init(COEFF(A, i), R->ctx); } A->alloc = new_alloc; } void mpoly_univar_init2(mpoly_univar_t A, slong len, mpoly_void_ring_t R) { mpoly_univar_init(A, R); mpoly_univar_fit_length(A, len, R); } /* A = prem(A, -B) C is used for working space */ void mpoly_univar_prem( mpoly_univar_t A, const mpoly_univar_t B, mpoly_univar_t C, mpoly_void_ring_t R) { slong i, j; fmpz_t z1, delta, delta_org; void * u = mpoly_void_ring_elem_init(R); void * v = mpoly_void_ring_elem_init(R); FLINT_ASSERT(A != B); FLINT_ASSERT(B != C); FLINT_ASSERT(C != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(fmpz_cmp(A->exps + 0, B->exps + 0) >= 0); fmpz_init(z1); fmpz_init(delta); fmpz_init(delta_org); fmpz_sub(delta_org, A->exps + 0, B->exps + 0); fmpz_add_ui(delta_org, delta_org, 1); looper: if (A->length < 1) goto done; fmpz_sub(delta, A->exps + 0, B->exps + 0); if (fmpz_sgn(delta) < 0) goto done; i = 1; j = 1; C->length = 0; while (i < A->length || j < B->length) { mpoly_univar_fit_length(C, C->length + 1, R); if (j < B->length) fmpz_add(z1, B->exps + j, delta); if (i < A->length && j < B->length && fmpz_equal(A->exps + i, z1)) { MUL(u, COEFF(A, i), COEFF(B, 0)); MUL(v, COEFF(A, 0), COEFF(B, j)); SUB(COEFF(C, C->length), v, u); fmpz_set(C->exps + C->length, A->exps + i); i++; j++; } else if (i < A->length && (j >= B->length || fmpz_cmp(A->exps + i, z1) > 0)) { MUL(COEFF(C, C->length), COEFF(A, i), COEFF(B, 0)); NEG(COEFF(C, C->length), COEFF(C, C->length)); fmpz_set(C->exps + C->length, A->exps + i); i++; } else { FLINT_ASSERT(j < B->length && (i >= A->length || fmpz_cmp(A->exps + i, z1) < 0)); MUL(COEFF(C, C->length), COEFF(A, 0), COEFF(B, j)); fmpz_set(C->exps + C->length, z1); j++; } C->length += !IS_ZERO(COEFF(C, C->length)); } mpoly_univar_swap(A, C); fmpz_sub_ui(delta_org, delta_org, 1); goto looper; done: FLINT_ASSERT(fmpz_sgn(delta_org) >= 0); if (!fmpz_is_zero(delta_org)) { NEG(v, COEFF(B, 0)); POW_FMPZ(u, v, delta_org); for (i = 0; i < A->length; i++) MUL(COEFF(A, i), COEFF(A, i), u); } mpoly_void_ring_elem_clear(u, R); mpoly_void_ring_elem_clear(v, R); fmpz_clear(z1); fmpz_clear(delta); fmpz_clear(delta_org); } /* G = pseudo-gcd of B and A = last nonzero subresultant polynomial starting with B and A B and A are clobbered */ int mpoly_univar_pseudo_gcd_ducos( mpoly_univar_t G, mpoly_univar_t B, mpoly_univar_t A, mpoly_void_ring_t R) { slong i, j, k, aJ, ae; fmpz_t n, d, e, J, z1, alpha; int iexists, jexists, kexists; void * u, * v, * w, * s; mpoly_univar_t C, D, H, T; mpoly_univar_struct * last; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(fmpz_cmp(B->exps + 0, A->exps + 0) >= 0); FLINT_ASSERT(fmpz_sgn(A->exps + 0) >= 0); if (fmpz_is_zero(A->exps + 0)) { mpoly_univar_fit_length(G, 1, R); G->length = 1; fmpz_zero(G->exps + 0); return POW_FMPZ(COEFF(G, 0), COEFF(A, 0), B->exps + 0); } fmpz_init(n); fmpz_init(d); fmpz_init(e); fmpz_init(J); fmpz_init(z1); fmpz_init(alpha); u = mpoly_void_ring_elem_init(R); v = mpoly_void_ring_elem_init(R); w = mpoly_void_ring_elem_init(R); s = mpoly_void_ring_elem_init(R); i = FLINT_MAX(B->length, A->length); mpoly_univar_init2(C, i + 1, R); mpoly_univar_init2(D, i + 1, R); mpoly_univar_init2(H, i + 1, R); mpoly_univar_init2(T, i + 1, R); last = A; fmpz_sub(z1, B->exps + 0, A->exps + 0); POW_FMPZ(s, A->coeffs + 0, z1); mpoly_univar_prem(B, A, D, R); looper: if (B->length < 1) goto done; fmpz_set(d, A->exps + 0); fmpz_set(e, B->exps + 0); last = B; fmpz_sub(z1, d, e); if (fmpz_is_one(z1)) { if (fmpz_is_zero(e)) goto done; /* D = (B[e]*A - A[e]*B)/A[d] */ /* i j */ i = 1; j = 1; if (A->length > 1 && fmpz_equal(A->exps + 1, e)) i++; else j = B->length; D->length = 0; while (i < A->length || j < B->length) { mpoly_univar_fit_length(D, D->length + 1, R); if (i < A->length && j < B->length && fmpz_equal(A->exps + i, B->exps + j)) { MUL(u, COEFF(A, i), COEFF(B, 0)); MUL(v, COEFF(A, 1), COEFF(B, j)); SUB(w, u, v); DIVEXACT(COEFF(D, D->length), w, COEFF(A, 0)); fmpz_set(D->exps + D->length, A->exps + i); i++; j++; } else if (i < A->length && (j >= B->length || fmpz_cmp(A->exps + i, B->exps + j) > 0)) { MUL(u, COEFF(A, i), COEFF(B, 0)); DIVEXACT(COEFF(D, D->length), u, COEFF(A, 0)); fmpz_set(D->exps + D->length, A->exps + i); i++; } else { FLINT_ASSERT((j < B->length && (i >= A->length || fmpz_cmp(B->exps + j, A->exps + i) > 0))); MUL(v, COEFF(A, 1), COEFF(B, j)); DIVEXACT(COEFF(D, D->length), v, COEFF(A, 0)); NEG(COEFF(D, D->length), COEFF(D, D->length)); fmpz_set(D->exps + D->length, B->exps + j); j++; } D->length += !IS_ZERO(COEFF(D, D->length)); } /* A = (B[e]*(D - B*x) + B[e-1]*B)/s */ /* i j k */ i = 0; fmpz_sub_ui(z1, e, 1); if (B->length > 1 && fmpz_equal(B->exps + 1, z1)) { j = 2; k = 1; } else { j = 1; k = B->length; } A->length = 0; while (i < D->length || j < B->length || k < B->length) { fmpz * exp; mpoly_univar_fit_length(A, A->length + 1, R); exp = A->exps + A->length; fmpz_zero(exp); if (i < D->length) _fmpz_max(exp, exp, D->exps + i); if (j < B->length) { fmpz_add_ui(z1, B->exps + j, 1); _fmpz_max(exp, exp, z1); } if (k < B->length) _fmpz_max(exp, exp, B->exps + k); iexists = (i < D->length) && fmpz_equal(exp, D->exps + i); jexists = (j < B->length) && fmpz_equal(exp, z1); kexists = (k < B->length) && fmpz_equal(exp, B->exps + k); FLINT_ASSERT(iexists || jexists || kexists); if (iexists) { if (jexists) { SUB(w, COEFF(D, i), COEFF(B, j)); MUL(u, COEFF(B, 0), w); } else { MUL(u, COEFF(B, 0), COEFF(D, i)); } if (kexists) { MUL(v, COEFF(B, 1), COEFF(B, k)); ADD(w, u, v); DIVEXACT(COEFF(A, A->length), w, s); } else { DIVEXACT(COEFF(A, A->length), u, s); } } else { if (kexists) { MUL(u, COEFF(B, 1), COEFF(B, k)); if (jexists) { MUL(v, COEFF(B, 0), COEFF(B, j)); SUB(w, u, v); DIVEXACT(COEFF(A, A->length), w, s); } else { DIVEXACT(COEFF(A, A->length), u, s); } } else { MUL(u, COEFF(B, 0), COEFF(B, j)); DIVEXACT(COEFF(A, A->length), u, s); NEG(COEFF(A, A->length), COEFF(A, A->length)); } } A->length += !IS_ZERO(COEFF(A, A->length)); i += iexists; j += jexists; k += kexists; } mpoly_univar_swap(A, B); SET(s, COEFF(A, 0)); last = A; } else { fmpz_sub(n, d, e); fmpz_sub_ui(n, n, 1); fmpz_one(alpha); while (fmpz_add(z1, alpha, alpha), fmpz_cmp(z1, n) <= 0) fmpz_set(alpha, z1); SET(u, COEFF(B, 0)); fmpz_sub(n, n, alpha); while (fmpz_cmp_ui(alpha, 1) > 0) { fmpz_tdiv_q_2exp(alpha, alpha, 1); MUL(v, u, u); DIVEXACT(u, v, s); if (fmpz_cmp(n, alpha) >= 0) { MUL(v, u, COEFF(B, 0)); DIVEXACT(u, v, s); fmpz_sub(n, n, alpha); } } mpoly_univar_fit_length(C, B->length, R); for (i = 0; i < B->length; i++) { MUL(v, u, COEFF(B, i)); DIVEXACT(COEFF(C, i), v, s); fmpz_set(C->exps + i, B->exps + i); } C->length = B->length; last = C; if (fmpz_is_zero(e)) goto done; /* H = C - C[e]*x^e */ mpoly_univar_fit_length(H, C->length, R); for (i = 1; i < C->length; i++) { SET(COEFF(H, i - 1), COEFF(C, i)); fmpz_set(H->exps + i - 1, C->exps + i); } H->length = C->length - 1; /* D = C[e]*A - A[e]*H (truncated to powers of x < e) */ i = 0; j = H->length; ae = A->length; while (i < A->length && fmpz_cmp(A->exps + i, e) >= 0) { if (fmpz_equal(A->exps + i, e)) { j = 0; ae = i; } i++; } D->length = 0; while (i < A->length || j < H->length) { mpoly_univar_fit_length(D, D->length + 1, R); if (i < A->length && j < H->length && fmpz_equal(A->exps + i, H->exps + j)) { MUL(u, COEFF(A, i), COEFF(C, 0)); MUL(v, COEFF(A, ae), COEFF(H, j)); SUB(COEFF(D, D->length), u, v); fmpz_set(D->exps + D->length, A->exps + i); i++; j++; } else if (i < A->length && (j >= H->length || fmpz_cmp(A->exps + i, H->exps + j) > 0)) { MUL(COEFF(D, D->length), COEFF(A, i), COEFF(C, 0)); fmpz_set(D->exps + D->length, A->exps + i); i++; } else { FLINT_ASSERT(j < H->length && (i >= A->length || fmpz_cmp(H->exps + j, A->exps + i) > 0)); MUL(COEFF(D, D->length), COEFF(A, ae), COEFF(H, j)); NEG(COEFF(D, D->length), COEFF(D, D->length)); fmpz_set(D->exps + D->length, H->exps + j); j++; } D->length += !IS_ZERO(COEFF(D, D->length)); } for (fmpz_add_ui(J, e, 1); fmpz_cmp(J, d) < 0; fmpz_add_ui(J, J, 1)) { if (H->length < 1) break; /* H = H*x - H[e-1]*B/B[e] */ fmpz_sub_ui(z1, e, 1); if (fmpz_equal(H->exps + 0, z1)) { i = 1; j = 1; T->length = 0; while (i < H->length || j < B->length) { mpoly_univar_fit_length(T, T->length + 1, R); if (i < H->length) fmpz_add_ui(z1, H->exps + i, 1); if (i < H->length && j < B->length && fmpz_equal(z1, B->exps + j)) { MUL(u, COEFF(H, 0), COEFF(B, j)); DIVEXACT(v, u, COEFF(B, 0)); SUB(COEFF(T, T->length), COEFF(H, i), v); fmpz_set(T->exps + T->length, B->exps + j); i++; j++; } else if (i < H->length && (j >= B->length || fmpz_cmp(z1, B->exps + j) > 0)) { SET(COEFF(T, T->length), COEFF(H, i)); fmpz_set(T->exps + T->length, z1); i++; } else { FLINT_ASSERT(j < B->length && (i >= H->length || fmpz_cmp(z1, B->exps + j) < 0)); MUL(u, COEFF(H, 0), COEFF(B, j)); DIVEXACT(COEFF(T, T->length), u, COEFF(B, 0)); NEG(COEFF(T, T->length), COEFF(T, T->length)); fmpz_set(T->exps + T->length, B->exps + j); j++; } T->length += !IS_ZERO(COEFF(T, T->length)); } mpoly_univar_swap(H, T); } else { FLINT_ASSERT(fmpz_cmp(H->exps + 0, z1) < 0); for (i = 0; i < H->length; i++) fmpz_add_ui(H->exps + i, H->exps + i, 1); } /* find coefficient of x^J in A */ aJ = 0; while (aJ < A->length && !fmpz_equal(A->exps + aJ, J)) aJ++; if (aJ >= A->length) continue; /* D = D - A[J]*H */ i = 0; j = 0; T->length = 0; while (i < D->length || j < H->length) { mpoly_univar_fit_length(T, T->length + 1, R); if (i < D->length && j < H->length && fmpz_equal(D->exps + i, H->exps + j)) { MUL(u, COEFF(H, j), COEFF(A, aJ)); SUB(COEFF(T, T->length), COEFF(D, i), u); fmpz_set(T->exps + T->length, D->exps + i); i++; j++; } else if (i < D->length && (j >= H->length || fmpz_cmp(D->exps + i, H->exps + j) > 0)) { SET(COEFF(T, T->length), COEFF(D, i)); fmpz_set(T->exps + T->length, D->exps + i); i++; } else { FLINT_ASSERT(j < H->length && (i >= D->length || fmpz_cmp(D->exps + i, H->exps + j) < 0)); MUL(COEFF(T, T->length), COEFF(H, j), COEFF(A, aJ)); NEG(COEFF(T, T->length), COEFF(T, T->length)); fmpz_set(T->exps + T->length, H->exps + j); j++; } T->length += !IS_ZERO(COEFF(T, T->length)); } mpoly_univar_swap(D, T); } /* B = (-1)^(d-e+1) * (B[e]*(D/A[d] - H*x) + H[e-1]*B)/s */ i = 0; fmpz_sub_ui(z1, e, 1); if (H->length > 0 && fmpz_equal(H->exps + 0, z1)) { j = 1; k = 1; } else { j = 0; k = B->length; } T->length = 0; while (i < D->length || j < H->length || k < B->length) { fmpz * exp; mpoly_univar_fit_length(T, T->length + 1, R); exp = T->exps + T->length; fmpz_zero(exp); if (i < D->length) _fmpz_max(exp, exp, D->exps + i); if (j < H->length) { fmpz_add_ui(z1, H->exps + j, 1); _fmpz_max(exp, exp, z1); } if (k < B->length) _fmpz_max(exp, exp, B->exps + k); iexists = (i < D->length && fmpz_equal(exp, D->exps + i)); jexists = (j < H->length && fmpz_equal(exp, z1)); kexists = (k < B->length && fmpz_equal(exp, B->exps + k)); FLINT_ASSERT(iexists || jexists || kexists); if (iexists) { if (jexists) { DIVEXACT(u, COEFF(D, i), COEFF(A, 0)); SUB(w, u, COEFF(H, j)); MUL(u, COEFF(B, 0), w); } else { DIVEXACT(u, COEFF(D, i), COEFF(A, 0)); MUL(u, COEFF(B, 0), u); } if (kexists) { MUL(v, COEFF(H, 0), COEFF(B, k)); ADD(w, u, v); DIVEXACT(COEFF(T, T->length), w, s); } else { DIVEXACT(COEFF(T, T->length), u, s); } } else { if (kexists) { MUL(u, COEFF(H, 0), COEFF(B, k)); if (jexists) { MUL(v, COEFF(B, 0), COEFF(H, j)); SUB(w, u, v); DIVEXACT(COEFF(T, T->length), w, s); } else { DIVEXACT(COEFF(T, T->length), u, s); } } else { MUL(u, COEFF(B, 0), COEFF(H, j)); DIVEXACT(COEFF(T, T->length), u, s); NEG(COEFF(T, T->length), COEFF(T, T->length)); } } if (((fmpz_get_ui(d) - fmpz_get_ui(e)) & 1) == 0) NEG(COEFF(T, T->length), COEFF(T, T->length)); T->length += !IS_ZERO(COEFF(T, T->length)); i += iexists; j += jexists; k += kexists; } mpoly_univar_swap(B, T); mpoly_univar_swap(A, C); SET(s, COEFF(A, 0)); last = A; } goto looper; done: mpoly_univar_swap(G, last); fmpz_clear(n); fmpz_clear(d); fmpz_clear(e); fmpz_clear(J); fmpz_clear(z1); fmpz_clear(alpha); mpoly_void_ring_elem_clear(u, R); mpoly_void_ring_elem_clear(v, R); mpoly_void_ring_elem_clear(w, R); mpoly_void_ring_elem_clear(s, R); mpoly_univar_clear(C, R); mpoly_univar_clear(D, R); mpoly_univar_clear(H, R); mpoly_univar_clear(T, R); return 1; } void mpoly_univar_derivative( mpoly_univar_t A, const mpoly_univar_t B, mpoly_void_ring_t R) { slong Ai, Bi; mpoly_univar_fit_length(A, B->length, R); Ai = 0; for (Bi = 0; Bi < B->length; Bi++) { if (fmpz_sgn(B->exps + Bi) <= 0) continue; MUL_FMPZ(COEFF(A, Ai), COEFF(B, Bi), B->exps + Bi); fmpz_sub_ui(A->exps + Ai, B->exps + Bi, 1); Ai += !IS_ZERO(COEFF(A, Ai)); } A->length = Ai; } /* fx and gx are clobbered */ int mpoly_univar_resultant( void * r, mpoly_univar_t fx, mpoly_univar_t gx, mpoly_void_ring_t R) { int success, change_sign; mpoly_univar_t rx; mpoly_univar_struct * F, * G; if (fx->length < 1 || gx->length < 1) { ZERO(r); return 1; } mpoly_univar_init(rx, R); if (fmpz_cmp(fx->exps + 0, gx->exps + 0) < 0) { change_sign = 1 & fmpz_get_ui(fx->exps + 0) & fmpz_get_ui(gx->exps + 0); F = gx; G = fx; } else { change_sign = 0; F = fx; G = gx; } if (fmpz_is_zero(G->exps + 0)) { success = POW_FMPZ(r, COEFF(G, 0), F->exps + 0); } else { success = mpoly_univar_pseudo_gcd_ducos(rx, F, G, R); if (success && rx->length == 1 && fmpz_is_zero(rx->exps + 0)) SWAP(r, COEFF(rx, 0)); else ZERO(r); } if (success && change_sign) NEG(r, r); mpoly_univar_clear(rx, R); return success; } /* fx is clobbered */ int mpoly_univar_discriminant( void * d, mpoly_univar_t fx, mpoly_void_ring_t R) { int success; mpoly_univar_t rx, fxp; if (fx->length < 1 || fmpz_cmp_ui(fx->exps + fx->length - 1, 1) > 0) { /* the discriminant of the zero polynomial should be zero */ ZERO(d); return 1; } if (fmpz_is_zero(fx->exps + 0)) { /* the discriminant of the constant polynomial a should be 1/a^2 */ ONE(d); success = DIVIDES(d, d, COEFF(fx, 0)); if (success) MUL(d, d, d); return success; } if (fmpz_is_one(fx->exps + 0)) { /* the discriminant of a linear polynomial should be 1 */ ONE(d); return 1; } /* the discriminant is (-1)^(n*(n-1)/2)*res(f,f')*a_n^(n-m-2), m=deg(f') */ mpoly_univar_init(rx, R); mpoly_univar_init(fxp, R); mpoly_univar_derivative(fxp, fx, R); if (fxp->length < 1) { ZERO(d); success = 1; } else { int change_sign = fmpz_get_ui(fx->exps + 0) & 2; fmpz_t exp_diff; void * u; fmpz_init(exp_diff); fmpz_sub(exp_diff, fx->exps + 0, fxp->exps + 0); fmpz_sub_ui(exp_diff, exp_diff, 2); u = mpoly_void_ring_elem_init(R); SET(u, COEFF(fx, 0)); /* will be clobbered */ success = mpoly_univar_pseudo_gcd_ducos(rx, fx, fxp, R); if (success && rx->length == 1 && fmpz_is_zero(rx->exps + 0)) { if (change_sign != 0) NEG(COEFF(rx, 0), COEFF(rx, 0)); if (fmpz_sgn(exp_diff) < 0) { FLINT_ASSERT(fmpz_equal_si(exp_diff, -1)); DIVEXACT(d, COEFF(rx, 0), u); } else { success = POW_FMPZ(u, u, exp_diff); if (success) MUL(d, COEFF(rx, 0), u); } } else { ZERO(d); } fmpz_clear(exp_diff); mpoly_void_ring_elem_clear(u, R); } mpoly_univar_clear(rx, R); mpoly_univar_clear(fxp, R); return success; } flint-3.1.3/src/mpoly/unpack_monomials_tight.c000066400000000000000000000017201461254215100214640ustar00rootroot00000000000000/* Copyright (C) 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpoly.h" void mpoly_unpack_monomials_tight(ulong * e1, ulong * e2, slong len, slong * mults, slong num, slong bits) { slong i, j; ulong exp; slong * prods; TMP_INIT; TMP_START; prods = (slong *) TMP_ALLOC((num + 1)*sizeof(slong)); prods[0] = 1; for (i = 1; i <= num; i++) prods[i] = mults[i - 1]*prods[i - 1]; for (i = 0; i < len; i++) { exp = 0; for (j = 0; j < num; j++) exp += (e2[i] % prods[j + 1])/prods[j] << bits*j; e1[i] = exp; } TMP_END; } flint-3.1.3/src/mpoly/unpack_vec.c000066400000000000000000000065321461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" void mpoly_unpack_vec_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len) { if (bits < FLINT_BITS) { slong i, j, shift; ulong u, mask = (-UWORD(1)) >> (FLINT_BITS - bits); for (j = 0; j < len; j++) { i = 0; u = *exp2++; shift = 0; *exp1++ = u & mask; u = u >> bits; /* number of bits to encode 0th field */ shift += bits; /* number of bits to encode 0th field */ while (++i < nfields) { if (shift + bits > FLINT_BITS) { u = *exp2++; shift = 0; } *exp1++ = u & mask; u = u >> bits; /* number of bits to encode ith field */ shift += bits; /* number of bits to encode ith field */ } } } else { slong j; ulong words_per_field = bits/FLINT_BITS; FLINT_ASSERT(bits%FLINT_BITS == 0); for (j = 0; j < len*nfields; j++, exp2 += words_per_field) { *exp1++ = *exp2; } } } void mpoly_unpack_vec_fmpz(fmpz * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len) { if (bits < FLINT_BITS) { slong i, j, shift; ulong u, mask = (-UWORD(1)) >> (FLINT_BITS - bits); for (j = 0; j < len; j++) { i = 0; u = *exp2++; shift = 0; fmpz_set_ui(exp1++, u & mask); u = u >> bits; /* number of bits to encode 0th field */ shift += bits; /* number of bits to encode 0th field */ while (++i < nfields) { if (shift + bits > FLINT_BITS) { u = *exp2++; shift = 0; } fmpz_set_ui(exp1++, u & mask); u = u >> bits; /* number of bits to encode ith field */ shift += bits; /* number of bits to encode ith field */ } } } else { slong j; ulong words_per_field = bits/FLINT_BITS; FLINT_ASSERT(bits%FLINT_BITS == 0); for (j = 0; j < len*nfields; j++, exp2 += words_per_field) { ulong size = words_per_field; while (size > 1 && exp2[size - 1] == 0) size--; if (size == 1) { fmpz_set_ui(exp1, exp2[0]); } else { __mpz_struct * mpz = _fmpz_promote(exp1); if (mpz->_mp_alloc < words_per_field) mpz_realloc2(mpz, bits); mpz->_mp_size = size; flint_mpn_copyi(mpz->_mp_d, exp2, size); } exp1++; } } } flint-3.1.3/src/mpoly/used_vars.c000066400000000000000000000073201461254215100167230ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "mpoly.h" /* this file DOES need to change with new orderings !!! */ static void mpoly_used_vars_or_sp( int * used, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx) { slong Ai, i, j, m, dir; slong N = mpoly_words_per_exp(Abits, mctx); slong nvars = mctx->nvars; ulong * t; slong Aimod, Amodulus = n_sqrt(Alen); ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); ulong u; flint_bitcnt_t shift; const ulong * exp2; TMP_INIT; TMP_START; t = TMP_ARRAY_ALLOC(N, ulong); mpoly_monomial_zero(t, N); m = 0; for (Aimod = 0; Aimod < Amodulus; Aimod++) { while (m < nvars && used[m]) m++; /* all variables in [0, m) are used */ if (m >= nvars) goto cleanup; for (Ai = Aimod; Ai < Alen; Ai += Amodulus) { for (j = 0; j < N; j++) t[j] |= Aexps[N*Ai + j]; } j = mctx->rev ? 0 : nvars - 1; dir = mctx->rev ? 1 : -1; /* unpack vec pt */ exp2 = t; i = 0; u = *exp2++; shift = 0; FLINT_ASSERT(0 <= j && j < nvars); used[j] |= (u & mask) != 0; j += dir; u = u >> Abits; /* number of bits to encode 0th field */ shift += Abits; /* number of bits to encode 0th field */ while (++i < nvars) { if (shift + Abits > FLINT_BITS) { u = *exp2++; shift = 0; } FLINT_ASSERT(0 <= j && j < nvars); used[j] |= (u & mask) != 0; j += dir; u = u >> Abits; /* number of bits to encode ith field */ shift += Abits; /* number of bits to encode ith field */ } } cleanup: TMP_END; } static void mpoly_used_vars_or_mp( int * used, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx) { slong Ai, i, j, m; slong N = mpoly_words_per_exp(Abits, mctx); slong wpf = Abits/FLINT_BITS; slong nvars = mctx->nvars; slong Aimod, Amodulus = n_sqrt(Alen); FLINT_ASSERT(Abits%FLINT_BITS == 0); m = 0; for (Aimod = 0; Aimod < Amodulus; Aimod++) { while (m < nvars && used[m]) m++; /* all variables in [0, m) are used */ if (m >= nvars) return; if (mctx->rev) { for (Ai = Aimod; Ai < Alen; Ai += Amodulus) { for (j = m; j < nvars; j++) for (i = 0; i < wpf && !used[j]; i++) used[j] |= Aexps[N*Ai + wpf*j + i] != 0; } } else { for (Ai = Aimod; Ai < Alen; Ai += Amodulus) { for (j = m; j < nvars; j++) for (i = wpf - 1; i >= 0 && !used[j]; i--) used[j] |= Aexps[N*Ai + wpf*(nvars - 1 - j) + i] != 0; } } } } /* update used by or'ing it with the used variables in A */ void mpoly_used_vars_or( int * used, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx) { if (Abits <= FLINT_BITS) mpoly_used_vars_or_sp(used, Aexps, Alen, Abits, mctx); else mpoly_used_vars_or_mp(used, Aexps, Alen, Abits, mctx); } flint-3.1.3/src/mpoly_types.h000066400000000000000000000120141461254215100161550ustar00rootroot00000000000000/* Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef MPOLY_TYPES_H #define MPOLY_TYPES_H #include "fmpz_mod_types.h" #include "fq_nmod_types.h" #include "n_poly_types.h" #ifdef __cplusplus extern "C" { #endif #define MPOLY_MIN_BITS (UWORD(8)) /* minimum number of bits to pack into */ typedef enum { ORD_LEX, ORD_DEGLEX, ORD_DEGREVLEX } ordering_t; #define MPOLY_NUM_ORDERINGS 3 typedef struct { slong nvars; /* number of variables */ slong nfields; /* number of fields in exponent vector */ ordering_t ord; /* monomial ordering */ int deg; /* is ord a degree ordering? */ int rev; /* is ord a reversed ordering? */ slong lut_words_per_exp[FLINT_BITS]; unsigned char lut_fix_bits[FLINT_BITS]; /* FLINT_BITS < 256 */ } mpoly_ctx_struct; typedef mpoly_ctx_struct mpoly_ctx_t[1]; typedef struct { mpoly_ctx_t minfo; nmod_t mod; } nmod_mpoly_ctx_struct; typedef nmod_mpoly_ctx_struct nmod_mpoly_ctx_t[1]; typedef struct { mpoly_ctx_t minfo; } fmpz_mpoly_ctx_struct; typedef fmpz_mpoly_ctx_struct fmpz_mpoly_ctx_t[1]; typedef struct { fmpz_mpoly_ctx_t zctx; } fmpq_mpoly_ctx_struct; typedef fmpq_mpoly_ctx_struct fmpq_mpoly_ctx_t[1]; typedef struct { mpoly_ctx_t minfo; fmpz_mod_ctx_t ffinfo; } fmpz_mod_mpoly_ctx_struct; typedef fmpz_mod_mpoly_ctx_struct fmpz_mod_mpoly_ctx_t[1]; typedef struct { mpoly_ctx_t minfo; fq_nmod_ctx_t fqctx; } fq_nmod_mpoly_ctx_struct; typedef fq_nmod_mpoly_ctx_struct fq_nmod_mpoly_ctx_t[1]; typedef struct { slong elem_size; const void * ctx; void (*init)(void *, const void *); void (*clear)(void *, const void *); int (*is_zero)(const void *, const void *); void (*zero)(void *, const void *); void (*one)(void *, const void *); void (*set_fmpz)(void *, const fmpz_t, const void *); void (*set)(void *, const void *, const void *); void (*swap)(void *, void *, const void *); void (*neg)(void *, const void *, const void *); void (*add)(void *, const void *, const void *, const void *); void (*sub)(void *, const void *, const void *, const void *); void (*mul_fmpz)(void *, const void *, const fmpz_t, const void *); void (*mul)(void *, const void *, const void *, const void *); void (*divexact)(void *, const void *, const void *, const void *); int (*divides)(void *, const void *, const void *, const void *); int (*pow_fmpz)(void *, const void *, const fmpz_t, const void *); slong (*length)(const void *, const void *); } mpoly_void_ring_t[1]; typedef struct { ulong * Amax_exp; ulong * Amin_exp; ulong * Astride; slong * Adeflate_deg; slong * Alead_count; slong * Atail_count; ulong * Bmax_exp; ulong * Bmin_exp; ulong * Bstride; slong * Bdeflate_deg; slong * Blead_count; slong * Btail_count; ulong * Gmin_exp; ulong * Abarmin_exp; ulong * Bbarmin_exp; ulong * Gstride; slong * Gterm_count_est; slong * Gdeflate_deg_bound; flint_bitcnt_t Gbits, Abarbits, Bbarbits; slong mvars; slong Adeflate_tdeg; slong Bdeflate_tdeg; double Adensity; double Bdensity; double hensel_time, brown_time, zippel_time, zippel2_time; slong * hensel_perm, * brown_perm, * zippel_perm, * zippel2_perm; unsigned int can_use; int Gdeflate_deg_bounds_are_nice; /* all of Gdeflate_deg_bound came from real gcd computations */ char * data; } mpoly_gcd_info_struct; typedef mpoly_gcd_info_struct mpoly_gcd_info_t[1]; typedef struct { slong mvars; slong nvars; slong * exps; slong exps_alloc; slong * rest; slong rest_alloc; slong * umat; slong * deltas; slong * degs; int is_trivial; int is_perm; int is_irred; } mpoly_compression_struct; typedef mpoly_compression_struct mpoly_compression_t[1]; /* nmod_mpolyn_t multivariates with n_poly_t coefficients */ typedef struct { n_poly_struct * coeffs; ulong * exps; slong alloc; slong length; slong bits; } nmod_mpolyn_struct; typedef nmod_mpolyn_struct nmod_mpolyn_t[1]; /* nmod_mpolyun_t sparse univariates with nmod_mpolyn_t coefficients with uniform bits and LEX ordering */ typedef struct { nmod_mpolyn_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* default bits to construct coeffs */ } nmod_mpolyun_struct; typedef nmod_mpolyun_struct nmod_mpolyun_t[1]; typedef enum { nmod_gcds_success, nmod_gcds_form_main_degree_too_high, nmod_gcds_form_wrong, nmod_gcds_no_solution, nmod_gcds_scales_not_found, nmod_gcds_eval_point_not_found, nmod_gcds_eval_gcd_deg_too_high } nmod_gcds_ret_t; #ifdef __cplusplus } #endif #endif /* MPOLY_TYPES_H */ flint-3.1.3/src/n_poly.h000066400000000000000000001361011461254215100150750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef N_POLY_H #define N_POLY_H #include "nmod_types.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fq_nmod_types.h" #include "n_poly_types.h" #ifdef __cplusplus extern "C" { #endif #if !defined(FQ_NMOD_H) # define fq_nmod_ctx_degree(ctx) ((ctx)->modulus->length - 1) #endif /* n_polyun stack */ typedef struct { n_polyun_struct ** array; slong alloc; slong top; } n_polyun_stack_struct; typedef n_polyun_stack_struct n_polyun_stack_t[1]; typedef struct { n_poly_stack_t poly_stack; n_polyun_stack_t polyun_stack; } n_poly_polyun_stack_struct; typedef n_poly_polyun_stack_struct n_poly_polyun_stack_t[1]; /*****************************************************************************/ FLINT_FORCE_INLINE void n_poly_init(n_poly_t A) { A->length = 0; A->alloc = 0; A->coeffs = NULL; } FLINT_FORCE_INLINE void n_poly_init2(n_poly_t A, slong alloc) { A->length = 0; A->alloc = alloc; A->coeffs = NULL; if (alloc > 0) A->coeffs = (mp_limb_t *) flint_malloc(alloc*sizeof(mp_limb_t)); } FLINT_FORCE_INLINE void n_poly_clear(n_poly_t A) { FLINT_ASSERT(A->alloc != 0 || A->coeffs == NULL); if (A->alloc > 0) flint_free(A->coeffs); } int n_poly_is_canonical(const n_poly_t A); void n_poly_realloc(n_poly_t A, slong len); void n_poly_print_pretty(const n_poly_t A, const char * x); FLINT_FORCE_INLINE void n_poly_fit_length(n_poly_t A, slong len) { if (len > A->alloc) n_poly_realloc(A, len); } FLINT_FORCE_INLINE void nmod_poly_mock(nmod_poly_t a, const n_poly_t b, nmod_t mod) { a->coeffs = b->coeffs; a->length = b->length; a->alloc = b->alloc; a->mod = mod; } FLINT_FORCE_INLINE void n_poly_mock(n_poly_t a, const nmod_poly_t b) { a->coeffs = b->coeffs; a->length = b->length; a->alloc = b->alloc; } FLINT_FORCE_INLINE void n_poly_set(n_poly_t A, const n_poly_t B) { n_poly_fit_length(A, B->length); flint_mpn_copyi(A->coeffs, B->coeffs, B->length); A->length = B->length; } FLINT_FORCE_INLINE void n_poly_swap(n_poly_t A, n_poly_t B) { FLINT_SWAP(n_poly_struct, *A, *B); } FLINT_FORCE_INLINE void _n_poly_normalise(n_poly_t A) { while (A->length > 0 && A->coeffs[A->length - 1] == 0) A->length--; } FLINT_FORCE_INLINE slong n_poly_degree(const n_poly_t A) { FLINT_ASSERT(A->length >= 0); return A->length - 1; } FLINT_FORCE_INLINE int n_poly_is_one(const n_poly_t A) { return A->length == 1 && A->coeffs[0] == 1; } FLINT_FORCE_INLINE mp_limb_t n_poly_lead(const n_poly_t A) { FLINT_ASSERT(A->length > 0); return A->coeffs[A->length - 1]; } FLINT_FORCE_INLINE void n_poly_one(n_poly_t A) { n_poly_fit_length(A, 1); A->length = 1; A->coeffs[0] = 1; } FLINT_FORCE_INLINE void n_poly_set_ui(n_poly_t A, mp_limb_t c) { n_poly_fit_length(A, 1); A->coeffs[0] = c; A->length = (c != 0); } FLINT_FORCE_INLINE int n_poly_is_zero(const n_poly_t poly) { return poly->length == 0; } FLINT_FORCE_INLINE void n_poly_zero(n_poly_t res) { res->length = 0; } FLINT_FORCE_INLINE int n_poly_equal(const n_poly_t a, const n_poly_t b) { if (a->length != b->length) return 0; if (a != b) { if (!_nmod_vec_equal(a->coeffs, b->coeffs, a->length)) return 0; } return 1; } /*****************************************************************************/ int n_poly_mod_is_canonical(const n_poly_t A, nmod_t mod); FLINT_FORCE_INLINE void n_poly_mod_make_monic(n_poly_t A, const n_poly_t B, nmod_t mod) { FLINT_ASSERT(B->length > 0); n_poly_fit_length(A, B->length); A->length = B->length; _nmod_poly_make_monic(A->coeffs, B->coeffs, B->length, mod); } FLINT_FORCE_INLINE void n_poly_mod_taylor_shift(n_poly_t g, mp_limb_t c, nmod_t mod) { _nmod_poly_taylor_shift(g->coeffs, c, g->length, mod); } FLINT_FORCE_INLINE ulong n_poly_get_coeff(const n_poly_t poly, slong j) { return (j >= poly->length) ? 0 : poly->coeffs[j]; } FLINT_FORCE_INLINE void n_poly_set_coeff_nonzero(n_poly_t A, slong j, ulong c) { FLINT_ASSERT(c != 0); if (j >= A->length) { n_poly_fit_length(A, j + 1); flint_mpn_zero(A->coeffs + A->length, j - A->length); A->length = j + 1; } A->coeffs[j] = c; } void n_poly_set_coeff(n_poly_t A, slong e, ulong c); void n_poly_mod_set_coeff_ui(n_poly_t A, slong j, ulong c, nmod_t mod); FLINT_FORCE_INLINE void n_poly_set_nmod_poly(n_poly_t a, const nmod_poly_t b) { n_poly_fit_length(a, b->length); flint_mpn_copyi(a->coeffs, b->coeffs, b->length); a->length = b->length; } FLINT_FORCE_INLINE void nmod_poly_set_n_poly(nmod_poly_t a, const n_poly_t b) { nmod_poly_fit_length(a, b->length); flint_mpn_copyi(a->coeffs, b->coeffs, b->length); a->length = b->length; } FLINT_FORCE_INLINE void n_poly_shift_left(n_poly_t A, const n_poly_t B, slong k) { n_poly_fit_length(A, B->length + k); _nmod_poly_shift_left(A->coeffs, B->coeffs, B->length, k); A->length = B->length + k; } FLINT_FORCE_INLINE void n_poly_shift_right(n_poly_t res, const n_poly_t poly, slong k) { if (k >= poly->length) { res->length = 0; } else { const slong len = poly->length - k; n_poly_fit_length(res, len); _nmod_poly_shift_right(res->coeffs, poly->coeffs, len, k); res->length = len; } } FLINT_FORCE_INLINE void n_poly_truncate(n_poly_t poly, slong len) { if (poly->length > len) { poly->length = len; _n_poly_normalise(poly); } } FLINT_FORCE_INLINE void _n_poly_mod_scalar_mul_nmod(n_poly_t A, const n_poly_t B, mp_limb_t c, nmod_t mod) { FLINT_ASSERT(B->length <= B->alloc); n_poly_fit_length(A, B->length); _nmod_vec_scalar_mul_nmod(A->coeffs, B->coeffs, B->length, c, mod); A->length = B->length; } FLINT_FORCE_INLINE void _n_poly_mod_scalar_mul_nmod_inplace(n_poly_t A, mp_limb_t c, nmod_t mod) { _nmod_vec_scalar_mul_nmod(A->coeffs, A->coeffs, A->length, c, mod); } void n_poly_mod_scalar_mul_ui(n_poly_t A, const n_poly_t B, mp_limb_t c, nmod_t ctx); mp_limb_t n_poly_mod_eval_step2(n_poly_t Acur, const n_poly_t Ainc, nmod_t mod); FLINT_FORCE_INLINE mp_limb_t n_poly_mod_evaluate_nmod(const n_poly_t A, mp_limb_t c, nmod_t mod) { return _nmod_poly_evaluate_nmod(A->coeffs, A->length, c, mod); } FLINT_FORCE_INLINE void n_poly_mod_neg(n_poly_t A, const n_poly_t B, nmod_t mod) { n_poly_fit_length(A, B->length); _nmod_vec_neg(A->coeffs, B->coeffs, B->length, mod); A->length = B->length; } FLINT_FORCE_INLINE void n_poly_mod_add(n_poly_t A, const n_poly_t B, const n_poly_t C, nmod_t mod) { slong Alen = FLINT_MAX(B->length, C->length); n_poly_fit_length(A, Alen); _nmod_poly_add(A->coeffs, B->coeffs, B->length, C->coeffs, C->length, mod); A->length = Alen; _n_poly_normalise(A); } void n_poly_mod_add_ui(n_poly_t res, const n_poly_t poly, ulong c, nmod_t ctx); FLINT_FORCE_INLINE void n_poly_mod_sub(n_poly_t A, const n_poly_t B, const n_poly_t C, nmod_t mod) { slong Alen = FLINT_MAX(B->length, C->length); n_poly_fit_length(A, Alen); _nmod_poly_sub(A->coeffs, B->coeffs, B->length, C->coeffs, C->length, mod); A->length = Alen; _n_poly_normalise(A); } FLINT_FORCE_INLINE void n_poly_mod_product_roots_nmod_vec(n_poly_t A, mp_srcptr r, slong n, nmod_t mod) { n_poly_fit_length(A, n + 1); A->length = n + 1; _nmod_poly_product_roots_nmod_vec(A->coeffs, r, n, mod); } void n_poly_mod_shift_left_scalar_addmul(n_poly_t A, slong k, mp_limb_t c, nmod_t mod); void n_poly_mod_addmul_linear(n_poly_t A, const n_poly_t B, const n_poly_t C, mp_limb_t d1, mp_limb_t d0, nmod_t mod); void n_poly_mod_scalar_addmul_nmod(n_poly_t A, const n_poly_t B, const n_poly_t C, mp_limb_t d0, nmod_t ctx); mp_limb_t _n_poly_eval_pow(n_poly_t P, n_poly_t alphapow, int nlimbs, nmod_t ctx); mp_limb_t n_poly_mod_eval_pow(n_poly_t P, n_poly_t alphapow, nmod_t ctx); void n_poly_mod_eval2_pow(mp_limb_t * vp, mp_limb_t * vm, const n_poly_t P, n_poly_t alphapow, nmod_t ctx); mp_limb_t n_poly_mod_div_root(n_poly_t Q, const n_poly_t A, mp_limb_t c, nmod_t ctx); FLINT_FORCE_INLINE void _n_poly_mod_mul(n_poly_t A, const n_poly_t B, const n_poly_t C, nmod_t ctx) { slong Blen = B->length; slong Clen = C->length; slong Alen = Blen + Clen - 1; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); if (Clen < 1 || Blen < 1) { A->length = 0; return; } n_poly_fit_length(A, Alen); A->length = Alen; if (Blen >= Clen) _nmod_poly_mul(A->coeffs, B->coeffs, Blen, C->coeffs, Clen, ctx); else _nmod_poly_mul(A->coeffs, C->coeffs, Clen, B->coeffs, Blen, ctx); } FLINT_FORCE_INLINE void _n_poly_mod_div(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t mod) { const slong lenA = A->length, lenB = B->length; FLINT_ASSERT(lenB > 0); FLINT_ASSERT(Q != A && Q != B); if (lenA < lenB) { n_poly_zero(Q); return; } n_poly_fit_length(Q, lenA - lenB + 1); _nmod_poly_div(Q->coeffs, A->coeffs, lenA, B->coeffs, lenB, mod); Q->length = lenA - lenB + 1; } FLINT_FORCE_INLINE void _n_poly_mod_divexact(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t mod) { const slong lenA = A->length, lenB = B->length; FLINT_ASSERT(lenB > 0); FLINT_ASSERT(Q != A && Q != B); if (lenA < lenB) { n_poly_zero(Q); return; } n_poly_fit_length(Q, lenA - lenB + 1); _nmod_poly_divexact(Q->coeffs, A->coeffs, lenA, B->coeffs, lenB, mod); Q->length = lenA - lenB + 1; } FLINT_FORCE_INLINE void _n_poly_mod_rem(n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t mod) { const slong lenA = A->length, lenB = B->length; FLINT_ASSERT(R != A && R != B); FLINT_ASSERT(lenB > 0); if (lenA < lenB) { n_poly_set(R, A); return; } n_poly_fit_length(R, lenB - 1); _nmod_poly_rem(R->coeffs, A->coeffs, lenA, B->coeffs, lenB, mod); R->length = lenB - 1; _n_poly_normalise(R); } FLINT_FORCE_INLINE void _n_poly_mod_divrem(n_poly_t Q, n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t mod) { const slong lenA = A->length, lenB = B->length; FLINT_ASSERT(lenB > 0); FLINT_ASSERT(Q != A && Q != B); FLINT_ASSERT(R != A && R != B); if (lenA < lenB) { n_poly_set(R, A); n_poly_zero(Q); return; } n_poly_fit_length(Q, lenA - lenB + 1); n_poly_fit_length(R, lenB - 1); _nmod_poly_divrem(Q->coeffs, R->coeffs, A->coeffs, lenA, B->coeffs, lenB, mod); Q->length = lenA - lenB + 1; R->length = lenB - 1; _n_poly_normalise(R); } ulong n_poly_mod_remove(n_poly_t f, const n_poly_t p, nmod_t ctx); void n_poly_mod_pow(n_poly_t res, const n_poly_t poly, ulong e, nmod_t ctx); void n_poly_mod_mul(n_poly_t A, const n_poly_t B, const n_poly_t C, nmod_t mod); void n_poly_mod_mullow(n_poly_t A, const n_poly_t B, const n_poly_t C, slong n, nmod_t mod); void n_poly_mod_div(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t mod); void n_poly_mod_rem(n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t mod); void n_poly_mod_divrem(n_poly_t Q, n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t mod); void n_poly_mod_divexact(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t mod); void n_poly_mod_mulmod(n_poly_t res, const n_poly_t poly1, const n_poly_t poly2, const n_poly_t f, nmod_t mod); int n_poly_mod_invmod(n_poly_t A, const n_poly_t B, const n_poly_t P, nmod_t mod); void n_poly_mod_gcd(n_poly_t G, const n_poly_t A, const n_poly_t B, nmod_t mod); void n_poly_mod_xgcd(n_poly_t G, n_poly_t S, n_poly_t T, const n_poly_t A, const n_poly_t B, nmod_t mod); void n_poly_mod_inv_series(n_poly_t Qinv, const n_poly_t Q, slong n, nmod_t mod); void n_poly_mod_div_series(n_poly_t Q, const n_poly_t A, const n_poly_t B, slong order, nmod_t ctx); void n_poly_reverse(n_poly_t output, const n_poly_t input, slong m); void n_poly_mod_mulmod_preinv(n_poly_t A, const n_poly_t B, const n_poly_t C, const n_poly_t M, const n_poly_t Minv, nmod_t ctx); /*****************************************************************************/ FLINT_FORCE_INLINE nmod_t fq_nmod_ctx_mod(const fq_nmod_ctx_t ctx) { return ctx->modulus->mod; } FLINT_FORCE_INLINE int _n_fq_is_zero(const mp_limb_t * a, slong d) { do { if (a[--d] != 0) return 0; } while (d > 0); return 1; } FLINT_FORCE_INLINE void _n_fq_zero(mp_limb_t * a, slong d) { slong i; for (i = 0; i < d; i++) a[i] = 0; } FLINT_FORCE_INLINE int _n_fq_is_one(const mp_limb_t * a, slong d) { slong i; if (a[0] != 1) return 0; for (i = 1; i < d; i++) if (a[i] != 0) return 0; return 1; } FLINT_FORCE_INLINE int _n_fq_is_ui(const mp_limb_t * a, slong d) { slong i; for (i = 1; i < d; i++) if (a[i] != 0) return 0; return 1; } FLINT_FORCE_INLINE int n_fq_is_one(const mp_limb_t * a, const fq_nmod_ctx_t ctx) { return _n_fq_is_one(a, fq_nmod_ctx_degree(ctx)); } FLINT_FORCE_INLINE void _n_fq_one(mp_limb_t * a, slong d) { slong i; a[0] = 1; for (i = 1; i < d; i++) a[i] = 0; } FLINT_FORCE_INLINE void _n_fq_set_nmod(mp_limb_t * a, mp_limb_t b, slong d) { slong i; a[0] = b; for (i = 1; i < d; i++) a[i] = 0; } void n_fq_gen( mp_limb_t * a, const fq_nmod_ctx_t ctx); FLINT_FORCE_INLINE void _n_fq_set( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ slong d) { slong i = 0; do { a[i] = b[i]; i++; } while (i < d); } FLINT_FORCE_INLINE void _n_fq_swap( mp_limb_t * a, /* length d */ mp_limb_t * b, /* length d */ slong d) { slong i = 0; do { FLINT_SWAP(mp_limb_t, a[i], b[i]); i++; } while (i < d); } FLINT_FORCE_INLINE int _n_fq_equal( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ slong d) { slong i = 0; do { if (a[i] != b[i]) return 0; } while (++i < d); return 1; } int n_fq_equal_fq_nmod( const mp_limb_t * a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); int n_fq_is_canonical( const mp_limb_t * a, const fq_nmod_ctx_t ctx); void n_fq_randtest_not_zero( mp_limb_t * a, flint_rand_t state, const fq_nmod_ctx_t ctx); char * n_fq_get_str_pretty( const mp_limb_t * a, const fq_nmod_ctx_t ctx); #ifdef FLINT_HAVE_FILE int n_fq_fprint_pretty(FILE * file, const mp_limb_t * a, const fq_nmod_ctx_t ctx); #endif void n_fq_print_pretty(const mp_limb_t * a, const fq_nmod_ctx_t ctx); void n_fq_get_fq_nmod( fq_nmod_t a, const mp_limb_t * b, const fq_nmod_ctx_t ctx); void n_fq_set_fq_nmod( mp_limb_t * a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); void n_fq_get_n_poly( n_poly_t a, const mp_limb_t * b, const fq_nmod_ctx_t ctx); void _n_fq_set_n_poly( mp_limb_t * a, const mp_limb_t * bcoeffs, slong blen, const fq_nmod_ctx_t ctx); void n_fq_add_si( mp_limb_t * a, const mp_limb_t * b, slong c, const fq_nmod_ctx_t ctx); FLINT_FORCE_INLINE void n_fq_add( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(d > 0); _nmod_vec_add(a, b, c, d, ctx->modulus->mod); } void n_fq_add_fq_nmod( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_t c, const fq_nmod_ctx_t ctx); void n_fq_sub_fq_nmod( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_t c, const fq_nmod_ctx_t ctx); FLINT_FORCE_INLINE void n_fq_sub( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(d > 0); _nmod_vec_sub(a, b, c, d, ctx->modulus->mod); } FLINT_FORCE_INLINE void _n_fq_add( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d, nmod_t mod) { FLINT_ASSERT(d > 0); _nmod_vec_add(a, b, c, d, mod); } FLINT_FORCE_INLINE void _n_fq_sub( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d, nmod_t mod) { FLINT_ASSERT(d > 0); _nmod_vec_sub(a, b, c, d, mod); } FLINT_FORCE_INLINE void _n_fq_neg( mp_limb_t * a, const mp_limb_t * b, slong d, nmod_t mod) { FLINT_ASSERT(d > 0); _nmod_vec_neg(a, b, d, mod); } void _n_fq_mul_ui( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ mp_limb_t c, slong d, nmod_t mod); void _n_fq_madd2( mp_limb_t * a, /* length 2d-1 */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const fq_nmod_ctx_t ctx, mp_limb_t * t); /* length 2d */ void _n_fq_mul2( mp_limb_t * t, /* length 2d-1 */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const fq_nmod_ctx_t ctx); #define N_FQ_REDUCE_ITCH 2 void _n_fq_reduce( mp_limb_t * a, mp_limb_t * b, slong blen, const fq_nmod_ctx_t ctx, mp_limb_t * t); /* same itch as reduce */ FLINT_FORCE_INLINE void _n_fq_reduce2( mp_limb_t * a, /* length d */ mp_limb_t * b, /* length 2d-1 */ const fq_nmod_ctx_t ctx, mp_limb_t * t) /* length 2d */ { slong blen = 2*fq_nmod_ctx_degree(ctx) - 1; FLINT_ASSERT(a != b); while (blen > 0 && b[blen - 1] == 0) blen--; _n_fq_reduce(a, b, blen, ctx, t); } #define N_FQ_MUL_ITCH 4 FLINT_FORCE_INLINE void _n_fq_mul( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const fq_nmod_ctx_t ctx, mp_limb_t * t) /* length 4d */ { slong d = fq_nmod_ctx_degree(ctx); _n_fq_mul2(t, b, c, ctx); _n_fq_reduce2(a, t, ctx, t + 2*d); } FLINT_FORCE_INLINE void _n_fq_addmul( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const mp_limb_t * e, /* length d */ const fq_nmod_ctx_t ctx, mp_limb_t * t) /* length 4d */ { slong d = fq_nmod_ctx_degree(ctx); _n_fq_mul2(t, c, e, ctx); _nmod_vec_add(t, t, b, d, ctx->mod); _n_fq_reduce2(a, t, ctx, t + 2*d); } #define N_FQ_LAZY_ITCH 6 int _n_fq_dot_lazy_size(slong len, const fq_nmod_ctx_t ctx); void _n_fq_reduce2_lazy1( mp_limb_t * a, /* length 6d, 2d used */ slong d, nmod_t ctx); void _n_fq_madd2_lazy1( mp_limb_t * a, /* length 6d, 2d used */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d); void _n_fq_mul2_lazy1( mp_limb_t * a, /* length 6d, 2d used */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d); void _n_fq_reduce2_lazy2( mp_limb_t * a, /* length 6d, 4d used */ slong d, nmod_t ctx); void _n_fq_madd2_lazy2( mp_limb_t * a, /* length 6d, 4d used */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d); void _n_fq_mul2_lazy2( mp_limb_t * a, /* length 6d, 4d used */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d); void _n_fq_reduce2_lazy3( mp_limb_t * a, /* length 6d */ slong d, nmod_t ctx); void _n_fq_madd2_lazy3( mp_limb_t * a, /* length 6d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d); void _n_fq_mul2_lazy3( mp_limb_t * a, /* length 6d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d); #define N_FQ_INV_ITCH 1 void _n_fq_inv( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_ctx_t ctx, mp_limb_t * t); #define N_FQ_MUL_INV_ITCH FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_INV_ITCH) void _n_fq_pow_ui( mp_limb_t * a, const mp_limb_t * b, ulong e, const fq_nmod_ctx_t ctx); void n_fq_pow_fmpz( mp_limb_t * a, const mp_limb_t * b, const fmpz_t e, const fq_nmod_ctx_t ctx); void n_fq_mul( mp_limb_t * a, const mp_limb_t * b, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_mul_fq_nmod( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_t c, const fq_nmod_ctx_t ctx); void n_fq_addmul( mp_limb_t * a, const mp_limb_t * b, const mp_limb_t * c, const mp_limb_t * d, const fq_nmod_ctx_t ctx); void n_fq_inv( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_ctx_t ctx); void n_fq_pow_ui( mp_limb_t * a, const mp_limb_t * b, ulong e, const fq_nmod_ctx_t ctx); /*****************************************************************************/ #define N_FQ_POLY_DIVREM_DIVCONQUER_CUTOFF 20 #define n_fq_poly_init n_poly_init #define n_fq_poly_clear n_poly_clear #define n_fq_poly_degree n_poly_degree #define n_fq_poly_zero n_poly_zero #define n_fq_poly_is_zero n_poly_is_zero #define n_fq_poly_swap n_poly_swap #define n_fq_bpoly_init n_bpoly_init #define n_fq_bpoly_clear n_bpoly_clear #define n_fq_bpoly_zero n_bpoly_zero #define n_fq_bpoly_fit_length n_bpoly_fit_length #define n_fq_bpoly_normalise n_bpoly_normalise #define n_fq_polyun_init n_polyun_init #define n_fq_polyun_clear n_polyun_clear #define n_fq_bpoly_degree1 n_bpoly_degree1 #define n_fq_bpoly_degree0 n_bpoly_degree0 void n_fq_poly_init2(n_fq_poly_t A, slong alloc, const fq_nmod_ctx_t ctx); void _n_fq_poly_one(n_fq_poly_t A, slong d); FLINT_FORCE_INLINE void n_fq_poly_one(n_fq_poly_t A, const fq_nmod_ctx_t ctx) { _n_fq_poly_one(A, fq_nmod_ctx_degree(ctx)); } int n_fq_poly_is_one(n_fq_poly_t A, const fq_nmod_ctx_t ctx); int n_fq_poly_is_canonical( const n_fq_poly_t a, const fq_nmod_ctx_t ctx); FLINT_FORCE_INLINE void _n_fq_poly_normalise(n_fq_poly_t A, slong d) { while (A->length > 0 && _n_fq_is_zero(A->coeffs + d*(A->length - 1), d)) A->length--; } void n_fq_poly_print_pretty( const n_fq_poly_t A, const char * x, const fq_nmod_ctx_t ctx); int n_fq_poly_equal( const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_set( n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_randtest( n_fq_poly_t A, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx); void n_fq_poly_make_monic( n_fq_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_get_coeff_n_fq( mp_limb_t * c, const n_poly_t A, slong e, const fq_nmod_ctx_t ctx); void n_fq_poly_get_coeff_fq_nmod( fq_nmod_t c, const n_poly_t A, slong e, const fq_nmod_ctx_t ctx); void n_fq_poly_set_coeff_n_fq( n_poly_t A, slong j, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_poly_set_coeff_fq_nmod( n_poly_t A, slong j, const fq_nmod_t c, const fq_nmod_ctx_t ctx); void n_fq_poly_scalar_mul_n_fq( n_poly_t A, const n_poly_t B, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_poly_scalar_mul_ui( n_poly_t A, const n_poly_t B, ulong c, const fq_nmod_ctx_t ctx); void n_fq_poly_scalar_addmul_n_fq( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, const mp_limb_t * d, const fq_nmod_ctx_t ctx); void n_fq_poly_shift_left_scalar_submul( n_poly_t A, slong k, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_poly_evaluate_fq_nmod( fq_nmod_t e, const n_poly_t A, const fq_nmod_t c, const fq_nmod_ctx_t ctx); void n_fq_poly_evaluate_n_fq( mp_limb_t * e, const n_poly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_poly_get_fq_nmod_poly( fq_nmod_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_set_fq_nmod_poly( n_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_set_n_fq( n_poly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_poly_set_fq_nmod( n_poly_t A, const fq_nmod_t c, const fq_nmod_ctx_t ctx); void n_fq_poly_shift_right( n_poly_t A, const n_poly_t B, slong n, const fq_nmod_ctx_t ctx); void n_fq_poly_shift_left( n_poly_t A, const n_poly_t B, slong n, const fq_nmod_ctx_t ctx); void n_fq_poly_truncate( n_poly_t A, slong len, const fq_nmod_ctx_t ctx); void n_fq_poly_add( n_poly_t A, const n_poly_t B, const n_poly_t C, const fq_nmod_ctx_t ctx); void n_fq_poly_sub( n_poly_t A, const n_poly_t B, const n_poly_t C, const fq_nmod_ctx_t ctx); void n_fq_poly_neg( n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_add_si( n_poly_t A, const n_poly_t B, slong c, const fq_nmod_ctx_t ctx); void _n_fq_poly_mul_( mp_limb_t * A, const mp_limb_t * B, slong Blen, const mp_limb_t * C, slong Clen, const fq_nmod_ctx_t ctx, n_poly_stack_t St); void n_fq_poly_mul_( n_poly_t A, const n_poly_t B, const n_poly_t C, const fq_nmod_ctx_t ctx, n_poly_stack_t St); void n_fq_poly_mul( n_poly_t A, const n_poly_t B, const n_poly_t C, const fq_nmod_ctx_t ctx); void n_fq_poly_pow( n_poly_t A, const n_poly_t B, ulong e, const fq_nmod_ctx_t ctx); ulong n_fq_poly_remove( n_poly_t f, const n_poly_t g, const fq_nmod_ctx_t ctx); void n_fq_poly_divrem_divconquer_( n_poly_t Q, n_poly_t R, const n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx, n_poly_stack_t St); FLINT_FORCE_INLINE void n_fq_poly_divrem_( n_poly_t Q, n_poly_t R, const n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { n_fq_poly_divrem_divconquer_(Q, R, A, B, ctx, St); } void n_fq_poly_divrem( n_poly_t Q, n_poly_t R, const n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_gcd( n_poly_t G, const n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_gcd_( n_poly_t G, const n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx, n_poly_stack_t St); void n_fq_poly_xgcd( n_poly_t G, n_poly_t S, n_poly_t T, const n_poly_t B, const n_poly_t C, const fq_nmod_ctx_t ctx); void n_fq_poly_mulmod( n_poly_t A, const n_poly_t B, const n_poly_t C, const n_poly_t M, const fq_nmod_ctx_t ctx); void n_fq_poly_rem( n_poly_t R, const n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_poly_mullow( n_poly_t A, const n_poly_t B, const n_poly_t C, slong order, const fq_nmod_ctx_t ctx); void n_fq_poly_inv_series( n_poly_t A, const n_poly_t B, slong order, const fq_nmod_ctx_t ctx); void n_fq_poly_eval_pow( mp_limb_t * ev, const n_fq_poly_t A, n_fq_poly_t alphapow, const fq_nmod_ctx_t ctx); /*****************************************************************************/ FLINT_FORCE_INLINE void n_bpoly_init(n_bpoly_t A) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } void n_bpoly_clear(n_bpoly_t A); FLINT_FORCE_INLINE void n_bpoly_swap(n_bpoly_t A, n_bpoly_t B) { n_bpoly_struct t = *A; *A = *B; *B = t; } void n_bpoly_print_pretty(const n_bpoly_t A, const char * xvar, const char * yvar); FLINT_FORCE_INLINE void n_bpoly_normalise(n_bpoly_t A) { while (A->length > 0 && n_poly_is_zero(A->coeffs + A->length - 1)) A->length--; } void n_bpoly_realloc(n_bpoly_t A, slong len); FLINT_FORCE_INLINE void n_bpoly_fit_length(n_bpoly_t A, slong len) { if (len > A->alloc) n_bpoly_realloc(A, len); } FLINT_FORCE_INLINE void n_bpoly_zero(n_bpoly_t A) { A->length = 0; } FLINT_FORCE_INLINE int n_bpoly_is_zero(const n_bpoly_t A) { return A->length == 0; } void _n_bpoly_set(n_bpoly_t A, const n_bpoly_t B); FLINT_FORCE_INLINE void n_bpoly_set(n_bpoly_t A, const n_bpoly_t B) { if (A != B) _n_bpoly_set(A, B); } void n_bpoly_one(n_bpoly_t A); int n_bpoly_equal(const n_bpoly_t A, const n_bpoly_t B); void n_bpoly_set_coeff(n_bpoly_t A, slong e0, slong e1, mp_limb_t c); void n_bpoly_set_coeff_nonzero(n_bpoly_t A, slong e0, slong e1, mp_limb_t c); void n_bpoly_mod_derivative_gen0(n_bpoly_t A, const n_bpoly_t B, nmod_t ctx); FLINT_FORCE_INLINE mp_limb_t n_bpoly_get_coeff(const n_bpoly_t A, slong e0, slong e1) { if (e0 >= A->length) return 0; else return n_poly_get_coeff(A->coeffs + e0, e1); } FLINT_FORCE_INLINE slong n_bpoly_degree0(const n_bpoly_t A) { return A->length - 1; } slong n_bpoly_degree1(const n_bpoly_t A); void n_bpoly_set_poly_gen1(n_bpoly_t A, const n_poly_t B); void n_bpoly_set_poly_gen0(n_bpoly_t A, const n_poly_t B); /*****************************************************************************/ int n_bpoly_mod_is_canonical(const n_bpoly_t A, nmod_t mod); FLINT_FORCE_INLINE ulong n_bpoly_bidegree(const n_bpoly_t A) { ulong x, y; FLINT_ASSERT(A->length > 0); x = A->length - 1; y = A->coeffs[x].length - 1; return (x << (FLINT_BITS/2)) + y; } void n_bpoly_scalar_mul_nmod(n_bpoly_t A, mp_limb_t c, nmod_t ctx); void n_bpoly_mod_content_last(n_poly_t g, const n_bpoly_t A, nmod_t ctx); void n_bpoly_mod_divexact_last(n_bpoly_t A, const n_poly_t b, nmod_t ctx); void n_bpoly_mod_mul_last(n_bpoly_t A, const n_poly_t b, nmod_t ctx); void n_bpoly_mod_taylor_shift_gen1(n_bpoly_t A, const n_bpoly_t B, mp_limb_t c, nmod_t ctx); void n_bpoly_mod_taylor_shift_gen0(n_bpoly_t A, mp_limb_t c, nmod_t ctx); void n_bpoly_mod_add(n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t ctx); void n_bpoly_mod_sub(n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t ctx); void n_bpoly_mod_make_primitive(n_poly_t g, n_bpoly_t A, nmod_t ctx); void n_bpoly_mod_mul(n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t ctx); int n_bpoly_mod_divides(n_bpoly_t Q, const n_bpoly_t A, const n_bpoly_t B, nmod_t ctx); void n_bpoly_mod_mul_series(n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, slong order, nmod_t ctx); void n_bpoly_mod_divrem_series(n_bpoly_t Q, n_bpoly_t R, const n_bpoly_t A, const n_bpoly_t B, slong order, nmod_t ctx); void n_bpoly_mod_interp_reduce_2sm_poly(n_poly_t Ap, n_poly_t Am, const n_bpoly_t A, n_poly_t alphapow, nmod_t mod); void n_bpoly_mod_interp_lift_2sm_poly(slong * deg1, n_bpoly_t T, const n_poly_t A, const n_poly_t B, mp_limb_t alpha, nmod_t mod); int n_bpoly_mod_interp_crt_2sm_poly(slong * deg1, n_bpoly_t F, n_bpoly_t T, n_poly_t A, n_poly_t B, const n_poly_t modulus, n_poly_t alphapow, nmod_t mod); int n_bpoly_mod_gcd_brown_smprime(n_bpoly_t G, n_bpoly_t Abar, n_bpoly_t Bbar, n_bpoly_t A, n_bpoly_t B, nmod_t ctx, n_poly_bpoly_stack_t Sp); int n_polyu1n_mod_gcd_brown_smprime(n_polyun_t G, n_polyun_t Abar, n_polyun_t Bbar,n_polyun_t A, n_polyun_t B, nmod_t ctx, n_poly_polyun_stack_t St); /*****************************************************************************/ int n_fq_bpoly_equal( const n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx); void n_fq_bpoly_get_coeff_n_fq( mp_limb_t * c, const n_bpoly_t A, slong e0, slong e1, const fq_nmod_ctx_t ctx); void n_fq_bpoly_set_coeff_n_fq( n_fq_bpoly_t A, slong e0, slong e1, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_bpoly_get_coeff_fq_nmod( fq_nmod_t c, const n_bpoly_t A, slong e0, slong e1, const fq_nmod_ctx_t ctx); void n_fq_bpoly_set_fq_nmod_poly_gen0( n_bpoly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_bpoly_set_n_fq_poly_gen0( n_bpoly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_bpoly_set_n_fq_poly_gen1( n_bpoly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); void n_fq_bpoly_derivative_gen0( n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx); void n_fq_bpoly_scalar_mul_n_fq( n_fq_bpoly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx); void n_fq_bpoly_taylor_shift_gen1_fq_nmod( n_bpoly_t A, const n_bpoly_t B, const fq_nmod_t c_, const fq_nmod_ctx_t ctx); void n_fq_bpoly_taylor_shift_gen0_fq_nmod( n_bpoly_t A, const fq_nmod_t alpha, const fq_nmod_ctx_t ctx); void n_fq_bpoly_taylor_shift_gen0_n_fq( n_fq_bpoly_t A, const mp_limb_t * alpha, const fq_nmod_ctx_t ctx); int n_fq_bpoly_gcd_brown_smprime( n_fq_bpoly_t G, n_fq_bpoly_t Abar, n_fq_bpoly_t Bbar, n_fq_bpoly_t A, n_fq_bpoly_t B, const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t Sp); void n_fq_bpoly_print_pretty( const n_fq_bpoly_t A, const char * xvar, const char * yvar, const fq_nmod_ctx_t ctx); void n_fq_bpoly_one(n_fq_bpoly_t A, const fq_nmod_ctx_t ctx); void n_fq_bpoly_set(n_fq_bpoly_t A, const n_fq_bpoly_t B, const fq_nmod_ctx_t ctx); int n_fq_bpoly_is_canonical(const n_fq_bpoly_t A, const fq_nmod_ctx_t ctx); /*****************************************************************************/ FLINT_FORCE_INLINE void n_tpoly_init(n_tpoly_t A) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FLINT_FORCE_INLINE void n_tpoly_swap(n_tpoly_t A, n_tpoly_t B) { n_tpoly_struct t = *A; *A = *B; *B = t; } void n_tpoly_fit_length(n_tpoly_t A, slong len); void n_tpoly_clear(n_tpoly_t A); /*****************************************************************************/ FLINT_FORCE_INLINE void n_polyu_init(n_polyu_t A) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->alloc = 0; } void n_polyu_clear(n_polyu_t A); void n_polyu_realloc(n_polyu_t A, slong len); FLINT_FORCE_INLINE void n_polyu_fit_length(n_polyu_t A, slong len) { FLINT_ASSERT(A->alloc >= 0); if (len > A->alloc) n_polyu_realloc(A, len); } FLINT_FORCE_INLINE void n_polyu_swap(n_polyu_t A, n_polyu_t B) { n_polyu_struct T = *B; *B = *A; *A = T; } void n_polyu3_print_pretty(const n_polyu_t A, const char * gen0, const char * gen1, const char * var2); void n_polyu3_degrees(slong * deg0, slong * deg1, slong * deg2, const n_polyu_t A); /*****************************************************************************/ void nmod_pow_cache_start(mp_limb_t b, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct); mp_limb_t nmod_pow_cache_mulpow_ui(mp_limb_t a, ulong e, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, nmod_t ctx); mp_limb_t nmod_pow_cache_mulpow_neg_ui(mp_limb_t a, ulong e, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, nmod_t ctx); mp_limb_t nmod_pow_cache_mulpow_fmpz(mp_limb_t a, const fmpz_t e, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, nmod_t ctx); void n_fq_pow_cache_start_n_fq( const mp_limb_t * b, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, const fq_nmod_ctx_t ctx); void n_fq_pow_cache_start_fq_nmod( const fq_nmod_t b, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, const fq_nmod_ctx_t ctx); void n_fq_pow_cache_mulpow_ui( mp_limb_t * r, const mp_limb_t * a, ulong e, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, const fq_nmod_ctx_t ctx); void n_fq_pow_cache_mulpow_neg_ui( mp_limb_t * r, const mp_limb_t * a, ulong e, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, const fq_nmod_ctx_t ctx); void n_fq_pow_cache_mulpow_fmpz( mp_limb_t * r, const mp_limb_t * a, const fmpz_t e, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct, const fq_nmod_ctx_t ctx); /*****************************************************************************/ void nmod_eval_interp_init(nmod_eval_interp_t E); void nmod_eval_interp_clear(nmod_eval_interp_t E); int nmod_eval_interp_set_degree_modulus( nmod_eval_interp_t E, slong deg, nmod_t ctx); FLINT_FORCE_INLINE slong nmod_eval_interp_eval_length(nmod_eval_interp_t E) { return 1 + E->radix*E->d; } void nmod_eval_interp_to_coeffs_poly( n_poly_t a, const n_poly_t v, nmod_eval_interp_t E, nmod_t ctx); void nmod_eval_interp_from_coeffs_poly( n_poly_t v, const n_poly_t a, nmod_eval_interp_t E, nmod_t ctx); void nmod_eval_interp_to_coeffs_n_fq_poly( n_fq_poly_t a, const n_fq_poly_t v, nmod_eval_interp_t E, const fq_nmod_ctx_t ctx); void nmod_eval_interp_from_coeffs_n_fq_poly( n_fq_poly_t v, const n_fq_poly_t a, nmod_eval_interp_t E, const fq_nmod_ctx_t ctx); FLINT_FORCE_INLINE void nmod_evals_zero(n_poly_t a) { a->length = 0; } void nmod_evals_add_inplace(n_poly_t a, n_poly_t b, slong len, nmod_t ctx); void nmod_evals_mul(n_poly_t a, n_poly_t b, n_poly_t c, slong len, nmod_t ctx); void nmod_evals_addmul(n_poly_t a, n_poly_t b, n_poly_t c, slong len, nmod_t ctx); void nmod_evals_fmma(n_poly_t a, n_poly_t b, n_poly_t c, n_poly_t d, n_poly_t e, slong len, nmod_t ctx); FLINT_FORCE_INLINE void n_fq_evals_zero(n_fq_poly_t a) { a->length = 0; } void n_fq_evals_add_inplace(n_fq_poly_t a, n_fq_poly_t b, slong len, const fq_nmod_ctx_t ctx); void n_fq_evals_mul(n_fq_poly_t a, n_fq_poly_t b, n_fq_poly_t c, slong len, const fq_nmod_ctx_t ctx); void n_fq_evals_addmul(n_fq_poly_t a, n_fq_poly_t b, n_fq_poly_t c, slong len, const fq_nmod_ctx_t ctx); void n_fq_evals_fmma(n_fq_poly_t a, n_fq_poly_t b, n_fq_poly_t c, n_fq_poly_t f, n_fq_poly_t e, slong len, const fq_nmod_ctx_t ctx); /*****************************************************************************/ FLINT_FORCE_INLINE void n_polyun_init(n_polyun_t A) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->alloc = 0; } int n_polyun_is_canonical(const n_polyun_t A); void n_polyun_clear(n_polyun_t A); void n_polyun_realloc(n_polyun_t A, slong len); FLINT_FORCE_INLINE void n_polyun_fit_length(n_polyun_t A, slong len) { if (len > A->alloc) n_polyun_realloc(A, len); } int n_polyun_mod_is_canonical(const n_polyun_t A, nmod_t mod); FLINT_FORCE_INLINE void n_polyun_swap(n_polyun_t A, n_polyun_t B) { n_polyun_struct t = *B; *B = *A; *A = t; } void n_polyun_set(n_polyun_t A, const n_polyun_t B); void n_polyu1n_print_pretty(const n_polyun_t A, const char * var0, const char * varlast); void n_polyu2n_print_pretty(const n_polyun_t A, const char * gen0, const char * gen1, const char * varlast); void n_polyu3n_print_pretty(const n_polyun_t A, const char * gen0, const char * gen1, const char * var2, const char * varlast); void n_fq_polyun_set(n_fq_polyun_t A, const n_fq_polyun_t B, const fq_nmod_ctx_t ctx); int n_polyun_equal(const n_polyun_t A, const n_polyun_t B); FLINT_FORCE_INLINE void n_polyun_one(n_polyun_t A) { n_polyun_fit_length(A, 1); A->length = 1; A->exps[0] = 0; n_poly_one(A->coeffs + 0); } FLINT_FORCE_INLINE ulong n_polyu1n_bidegree(n_polyun_t A) { ulong x = A->exps[0]; ulong y = A->coeffs[0].length - 1; return (x << (FLINT_BITS/2)) + y; } /*****************************************************************************/ void n_fq_poly_product_roots_n_fq(n_poly_t M, const mp_limb_t * H, slong length, const fq_nmod_ctx_t ctx, n_poly_stack_t St); slong n_polyun_product_roots(n_polyun_t M, const n_polyun_t H, nmod_t ctx); slong n_fq_polyun_product_roots(n_fq_polyun_t M, const n_fq_polyun_t H, const fq_nmod_ctx_t ctx, n_poly_stack_t St); mp_limb_t _nmod_zip_eval_step(mp_limb_t * cur, const mp_limb_t * inc, const mp_limb_t * coeffs, slong length, nmod_t ctx); void _n_fq_zip_eval_step(mp_limb_t * res, mp_limb_t * cur, const mp_limb_t * inc, const mp_limb_t * coeffs, slong length, const fq_nmod_ctx_t ctx); void _n_fqp_zip_eval_step(mp_limb_t * res, mp_limb_t * cur, const mp_limb_t * inc, const mp_limb_t * coeffs, slong length, slong d, nmod_t mod); int _nmod_zip_vand_solve(mp_limb_t * coeffs, const mp_limb_t * monomials, slong mlength, const mp_limb_t * evals, slong elength, const mp_limb_t * master, mp_limb_t * scratch, nmod_t ctx); int _n_fq_zip_vand_solve(mp_limb_t * coeffs, const mp_limb_t * monomials, slong mlength, const mp_limb_t * evals, slong elength, const mp_limb_t * master, mp_limb_t * scratch, const fq_nmod_ctx_t ctx); int _n_fqp_zip_vand_solve(mp_limb_t * coeffs, const mp_limb_t * monomials, slong mlength, const mp_limb_t * evals, slong elength, const mp_limb_t * master, mp_limb_t * scratch, const fq_nmod_ctx_t ctx); /*****************************************************************************/ void n_poly_stack_init(n_poly_stack_t S); void n_poly_stack_clear(n_poly_stack_t S); n_poly_struct ** n_poly_stack_fit_request(n_poly_stack_t S, slong k); FLINT_FORCE_INLINE mp_limb_t * n_poly_stack_vec_init(n_poly_stack_t S, slong len) { n_poly_struct * poly_top; poly_top = n_poly_stack_fit_request(S, 1)[0]; S->top += 1; n_poly_fit_length(poly_top, len); return poly_top->coeffs; } FLINT_FORCE_INLINE void n_poly_stack_vec_clear(n_poly_stack_t S) { FLINT_ASSERT(S->top >= 1); S->top -= 1; } FLINT_FORCE_INLINE n_poly_struct ** n_poly_stack_request(n_poly_stack_t S, slong k) { n_poly_struct ** poly_top; poly_top = n_poly_stack_fit_request(S, k); S->top += k; return poly_top; } FLINT_FORCE_INLINE n_poly_struct * n_poly_stack_take_top(n_poly_stack_t S) { /* assume the request for 1 has already been fitted */ n_poly_struct ** poly_top; FLINT_ASSERT(S->top + 1 <= S->alloc); poly_top = S->array + S->top; S->top += 1; return poly_top[0]; } FLINT_FORCE_INLINE void n_poly_stack_give_back(n_poly_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } FLINT_FORCE_INLINE slong n_poly_stack_size(const n_poly_stack_t S) { return S->top; } /*****************************************************************************/ void n_bpoly_stack_init(n_bpoly_stack_t S); void n_bpoly_stack_clear(n_bpoly_stack_t S); n_bpoly_struct ** n_bpoly_stack_fit_request(n_bpoly_stack_t S, slong k); FLINT_FORCE_INLINE n_bpoly_struct ** n_bpoly_stack_request(n_bpoly_stack_t S, slong k) { n_bpoly_struct ** bpoly_top; bpoly_top = n_bpoly_stack_fit_request(S, k); S->top += k; return bpoly_top; } FLINT_FORCE_INLINE n_bpoly_struct * n_bpoly_stack_take_top(n_bpoly_stack_t S) { /* assume the request for 1 has already been fitted */ n_bpoly_struct ** bpoly_top; FLINT_ASSERT(S->top + 1 <= S->alloc); bpoly_top = S->array + S->top; S->top += 1; return bpoly_top[0]; } FLINT_FORCE_INLINE void n_bpoly_stack_give_back(n_bpoly_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } FLINT_FORCE_INLINE slong n_bpoly_stack_size(const n_bpoly_stack_t S) { return S->top; } /*****************************************************************************/ void n_polyun_stack_init(n_polyun_stack_t S); void n_polyun_stack_clear(n_polyun_stack_t S); n_polyun_struct ** n_polyun_stack_fit_request(n_polyun_stack_t S, slong k); FLINT_FORCE_INLINE n_polyun_struct ** n_polyun_stack_request(n_polyun_stack_t S, slong k) { n_polyun_struct ** polyun_top; polyun_top = n_polyun_stack_fit_request(S, k); S->top += k; return polyun_top; } FLINT_FORCE_INLINE n_polyun_struct * n_polyun_stack_take_top(n_polyun_stack_t S) { /* assume the request for 1 has already been fitted */ n_polyun_struct ** polyun_top; FLINT_ASSERT(S->top + 1 <= S->alloc); polyun_top = S->array + S->top; S->top += 1; return polyun_top[0]; } FLINT_FORCE_INLINE void n_polyun_stack_give_back(n_polyun_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } FLINT_FORCE_INLINE slong n_polyun_stack_size(const n_polyun_stack_t S) { return S->top; } #if !defined(FQ_NMOD_H) # undef fq_nmod_ctx_degree #endif #ifdef __cplusplus } #endif #endif flint-3.1.3/src/n_poly/000077500000000000000000000000001461254215100147225ustar00rootroot00000000000000flint-3.1.3/src/n_poly/io.c000066400000000000000000000130141461254215100154740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" void n_polyu3_print_pretty( const n_polyu_t A, const char * var0, const char * var1, const char * var2) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; flint_printf("%wu*%s^%wu*%s^%wu*%s^%wu", A->coeffs[i], var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } void n_fq_bpoly_print_pretty( const n_fq_bpoly_t A, const char * xvar, const char * yvar, const fq_nmod_ctx_t ctx) { slong i; int first; first = 1; for (i = A->length - 1; i >= 0; i--) { if (i + 1 != A->length && n_fq_poly_is_zero(A->coeffs + i)) continue; if (!first) flint_printf(" + "); first = 0; flint_printf("("); n_fq_poly_print_pretty(A->coeffs + i, yvar, ctx); flint_printf(")*%s^%wd", xvar, i); } if (first) flint_printf("0"); } void n_bpoly_print_pretty( const n_bpoly_t A, const char * xvar, const char * yvar) { slong i; int first; first = 1; for (i = A->length - 1; i >= 0; i--) { if (i < A->length - 1 && n_poly_is_zero(A->coeffs + i)) continue; if (!first) flint_printf(" + "); first = 0; flint_printf("("); n_poly_print_pretty(A->coeffs + i, yvar); flint_printf(")*%s^%wd", xvar, i); } if (first) flint_printf("0"); } char * n_fq_get_str_pretty( const mp_limb_t * a, const fq_nmod_ctx_t ctx) { char * s; fq_nmod_t A; fq_nmod_init(A, ctx); n_fq_get_fq_nmod(A, a, ctx); s = fq_nmod_get_str_pretty(A, ctx); fq_nmod_clear(A, ctx); return s; } int n_fq_fprint_pretty( FILE * file, const mp_limb_t * a, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; int first; first = 1; for (i = d - 1; i >= 0; i--) { if (a[i] == 0) continue; if (!first) flint_fprintf(file, "+"); first = 0; flint_fprintf(file, "%wu", a[i]); if (i > 0) { flint_fprintf(file, "*%s", ctx->var); if (i > 1) flint_fprintf(file, "^%wd", i); } } if (first) flint_fprintf(file, "0"); return 1; } void n_fq_print_pretty(const mp_limb_t * a, const fq_nmod_ctx_t ctx) { n_fq_fprint_pretty(stdout, a, ctx); } void n_poly_print_pretty(const n_poly_t A, const char * x) { slong i; int first = 1; for (i = A->length - 1; i >= 0; i--) { if (i < A->length - 1 && A->coeffs[i] == 0) continue; if (!first) flint_printf(" + "); first = 0; flint_printf("%wu*%s^%wd", A->coeffs[i], x, i); } if (first) flint_printf("0"); } void n_fq_poly_print_pretty( const n_fq_poly_t A, const char * x, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; int first; first = 1; for (i = A->length - 1; i >= 0; i--) { if (i + 1 != A->length && _n_fq_is_zero(A->coeffs + d*i, d)) continue; if (!first) flint_printf(" + "); first = 0; flint_printf("("); n_fq_print_pretty(A->coeffs + d*i, ctx); flint_printf(")*%s^%wd", x, i); } if (first) flint_printf("0"); } void n_polyu1n_print_pretty( const n_polyun_t A, const char * var0, const char * varlast) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); n_poly_print_pretty(A->coeffs + i, varlast); flint_printf(")*%s^%wu", var0, A->exps[i]); } if (first) flint_printf("0"); } void n_polyu2n_print_pretty( const n_polyun_t A, const char * var0, const char * var1, const char * varlast) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); n_poly_print_pretty(A->coeffs + i, varlast); flint_printf(")*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 1, 2), var1, extract_exp(A->exps[i], 0, 2)); } if (first) flint_printf("0"); } void n_polyu3n_print_pretty( const n_polyun_t A, const char * var0, const char * var1, const char * var2, const char * varlast) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) flint_printf(" + "); first = 0; flint_printf("("); n_poly_print_pretty(A->coeffs + i, varlast); flint_printf(")*%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } flint-3.1.3/src/n_poly/n_bpoly.c000066400000000000000000000065451461254215100165420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" void n_bpoly_clear(n_bpoly_t A) { slong i; if (A->alloc > 0) { FLINT_ASSERT(A->coeffs != NULL); for (i = 0; i < A->alloc; i++) n_poly_clear(A->coeffs + i); flint_free(A->coeffs); } else { FLINT_ASSERT(A->coeffs == NULL); } } void n_bpoly_realloc(n_bpoly_t A, slong len) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; if (A->alloc > 0) { A->coeffs = (n_poly_struct *) flint_realloc(A->coeffs, new_alloc * sizeof(n_poly_struct)); } else { FLINT_ASSERT(A->coeffs == NULL); A->coeffs = (n_poly_struct *) flint_malloc( new_alloc * sizeof(n_poly_struct)); } for (i = old_alloc; i < new_alloc; i++) n_poly_init(A->coeffs + i); A->alloc = len; } slong n_bpoly_degree1(const n_bpoly_t A) { slong i, len = 0; for (i = 0; i < A->length; i++) len = FLINT_MAX(len, A->coeffs[i].length); return len - 1; } int n_bpoly_equal(const n_bpoly_t A, const n_bpoly_t B) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (!n_poly_equal(A->coeffs + i, B->coeffs + i)) return 0; } return 1; } void _n_bpoly_set(n_bpoly_t A, const n_bpoly_t B) { slong i; n_bpoly_fit_length(A, B->length); A->length = B->length; for (i = 0; i < B->length; i++) n_poly_set(A->coeffs + i, B->coeffs + i); } void n_bpoly_set_coeff_nonzero(n_bpoly_t A, slong xi, slong yi, mp_limb_t c) { slong i; FLINT_ASSERT(c != 0); if (xi >= A->length) { n_bpoly_fit_length(A, xi + 1); for (i = A->length; i <= xi; i++) n_poly_zero(A->coeffs + i); A->length = xi + 1; } n_poly_set_coeff_nonzero(A->coeffs + xi, yi, c); FLINT_ASSERT(!n_poly_is_zero(A->coeffs + A->length - 1)); } void n_bpoly_set_coeff(n_bpoly_t A, slong xi, slong yi, mp_limb_t c) { slong i; if (xi >= A->length) { n_bpoly_fit_length(A, xi + 1); for (i = A->length; i <= xi; i++) n_poly_zero(A->coeffs + i); A->length = xi + 1; } n_poly_set_coeff(A->coeffs + xi, yi, c); while (A->length > 0 && n_poly_is_zero(A->coeffs + A->length - 1)) A->length--; } void n_bpoly_set_poly_gen1(n_bpoly_t A, const n_poly_t B) { n_bpoly_fit_length(A, 1); n_poly_set(A->coeffs + 0, B); A->length = !n_poly_is_zero(A->coeffs + 0); } void n_bpoly_set_poly_gen0(n_bpoly_t A, const n_poly_t B) { slong i; n_bpoly_fit_length(A, B->length); for (i = 0; i < B->length; i++) n_poly_set_ui(A->coeffs + i, B->coeffs[i]); A->length = B->length; } void n_bpoly_one(n_bpoly_t A) { n_bpoly_fit_length(A, 1); A->length = 1; n_poly_one(A->coeffs + 0); } flint-3.1.3/src/n_poly/n_bpoly_mod.c000066400000000000000000000052641461254215100173760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" int n_bpoly_mod_is_canonical(const n_bpoly_t A, nmod_t mod) { slong i; if (A->length < 1) return A->length == 0; for (i = 0; i < A->length; i++) { if (!n_poly_mod_is_canonical(A->coeffs + i, mod)) return 0; if (i + 1 == A->length && n_poly_is_zero(A->coeffs + i)) return 0; } return 1; } void n_bpoly_scalar_mul_nmod(n_bpoly_t A, mp_limb_t c, nmod_t ctx) { slong i; if (c <= 1) { if (c == 0) A->length = 0; return; } for (i = 0; i < A->length; i++) _n_poly_mod_scalar_mul_nmod_inplace(A->coeffs + i, c, ctx); } void n_bpoly_mod_content_last(n_poly_t g, const n_bpoly_t A, nmod_t ctx) { slong i; n_poly_zero(g); for (i = 0; i < A->length; i++) { n_poly_mod_gcd(g, g, A->coeffs + i, ctx); if (n_poly_degree(g) == 0) break; } } void n_bpoly_mod_divexact_last(n_bpoly_t A, const n_poly_t b, nmod_t ctx) { slong i; n_poly_struct * t; if (b->length == 1) { if (b->coeffs[0] != 1) n_bpoly_scalar_mul_nmod(A, nmod_inv(b->coeffs[0], ctx), ctx); return; } n_bpoly_fit_length(A, A->length + 1); t = A->coeffs + A->length; for (i = 0; i < A->length; i++) { if (A->coeffs[i].length < 1) continue; n_poly_mod_divexact(t, A->coeffs + i, b, ctx); n_poly_swap(A->coeffs + i, t); } } void n_bpoly_mod_mul_last(n_bpoly_t A, const n_poly_t b, nmod_t ctx) { slong i; n_poly_struct * t; if (n_poly_is_one(b)) return; n_bpoly_fit_length(A, A->length + 1); t = A->coeffs + A->length; for (i = 0; i < A->length; i++) { if (n_poly_is_zero(A->coeffs + i)) continue; n_poly_mod_mul(t, A->coeffs + i, b, ctx); n_poly_swap(A->coeffs + i, t); } } void n_bpoly_mod_derivative_gen0( n_bpoly_t A, const n_bpoly_t B, nmod_t ctx) { slong i; FLINT_ASSERT(A != B); if (B->length < 2) { n_bpoly_zero(A); return; } n_bpoly_fit_length(A, B->length - 1); for (i = 1; i < B->length; i++) n_poly_mod_scalar_mul_ui(A->coeffs + i - 1, B->coeffs + i, i, ctx); A->length = B->length - 1; n_bpoly_normalise(A); } flint-3.1.3/src/n_poly/n_bpoly_mod_gcd.c000066400000000000000000000326661461254215100202210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" void n_bpoly_mod_interp_reduce_2sm_poly( n_poly_t Ap, n_poly_t Am, const n_bpoly_t A, n_poly_t alphapow, nmod_t mod) { slong i, Alen = A->length; const n_poly_struct * Ac = A->coeffs; mp_limb_t * Apc, * Amc; n_poly_fit_length(Ap, Alen); n_poly_fit_length(Am, Alen); Apc = Ap->coeffs; Amc = Am->coeffs; for (i = 0; i < Alen; i++) n_poly_mod_eval2_pow(Apc + i, Amc + i, Ac + i, alphapow, mod); Ap->length = Alen; _n_poly_normalise(Ap); Am->length = Alen; _n_poly_normalise(Am); } void n_bpoly_mod_interp_lift_2sm_poly( slong * deg1, n_bpoly_t T, const n_poly_t A, const n_poly_t B, mp_limb_t alpha, nmod_t mod) { slong i; slong lastlength = 0; const mp_limb_t * Acoeffs = A->coeffs; const mp_limb_t * Bcoeffs = B->coeffs; n_poly_struct * Tcoeffs; slong Alen = A->length; slong Blen = B->length; slong Tlen = FLINT_MAX(Alen, Blen); mp_limb_t d0 = (1 + mod.n)/2; mp_limb_t d1 = nmod_inv(nmod_add(alpha, alpha, mod), mod); mp_limb_t Avalue, Bvalue, u, v; n_bpoly_fit_length(T, Tlen); Tcoeffs = T->coeffs; for (i = 0; i < Tlen; i++) { Avalue = (i < Alen) ? Acoeffs[i] : 0; Bvalue = (i < Blen) ? Bcoeffs[i] : 0; u = nmod_sub(Avalue, Bvalue, mod); v = nmod_add(Avalue, Bvalue, mod); u = nmod_mul(u, d1, mod); v = nmod_mul(v, d0, mod); if ((u | v) == 0) { n_poly_zero(Tcoeffs + i); } else { n_poly_fit_length(Tcoeffs + i, 2); Tcoeffs[i].coeffs[0] = v; Tcoeffs[i].coeffs[1] = u; Tcoeffs[i].length = 1 + (u != 0); lastlength = FLINT_MAX(lastlength, Tcoeffs[i].length); } } *deg1 = lastlength - 1; FLINT_ASSERT(Tlen <= 0 || !n_poly_is_zero(Tcoeffs + Tlen - 1)); T->length = Tlen; } int n_bpoly_mod_interp_crt_2sm_poly( slong * deg1, n_bpoly_t F, n_bpoly_t T, n_poly_t A, n_poly_t B, const n_poly_t modulus, n_poly_t alphapow, nmod_t mod) { int changed = 0; slong i, lastlength = 0; slong Alen = A->length; slong Blen = B->length; slong Flen = F->length; slong Tlen = FLINT_MAX(FLINT_MAX(Alen, Blen), Flen); n_poly_struct * Tcoeffs, * Fcoeffs; mp_limb_t * Acoeffs, * Bcoeffs; n_poly_t zero; mp_limb_t Avalue, Bvalue, FvalueA, FvalueB, u, v; n_poly_struct * Fvalue; mp_limb_t alpha = alphapow->coeffs[1]; zero->alloc = 0; zero->length = 0; zero->coeffs = NULL; n_bpoly_fit_length(T, Tlen); Tcoeffs = T->coeffs; Acoeffs = A->coeffs; Bcoeffs = B->coeffs; Fcoeffs = F->coeffs; for (i = 0; i < Tlen; i++) { Fvalue = (i < Flen) ? Fcoeffs + i : zero; n_poly_mod_eval2_pow(&FvalueA, &FvalueB, Fvalue, alphapow, mod); Avalue = (i < Alen) ? Acoeffs[i] : 0; Bvalue = (i < Blen) ? Bcoeffs[i] : 0; FvalueA = nmod_sub(FvalueA, Avalue, mod); FvalueB = nmod_sub(FvalueB, Bvalue, mod); u = nmod_sub(FvalueB, FvalueA, mod); v = nmod_mul(mod.n - alpha, nmod_add(FvalueB, FvalueA, mod), mod); if ((u | v) != 0) { changed = 1; n_poly_mod_addmul_linear(Tcoeffs + i, Fvalue, modulus, u, v, mod); } else { n_poly_set(Tcoeffs + i, Fvalue); } lastlength = FLINT_MAX(lastlength, Tcoeffs[i].length); } FLINT_ASSERT(Tlen <= 0 || !n_poly_is_zero(Tcoeffs + Tlen - 1)); T->length = Tlen; if (changed) n_bpoly_swap(T, F); FLINT_ASSERT(n_bpoly_mod_is_canonical(F, mod)); *deg1 = lastlength - 1; return changed; } int n_bpoly_mod_gcd_brown_smprime( n_bpoly_t G, n_bpoly_t Abar, n_bpoly_t Bbar, n_bpoly_t A, n_bpoly_t B, nmod_t ctx, n_poly_bpoly_stack_t Sp) { int success; slong bound; mp_limb_t alpha, temp, gammaevalp, gammaevalm; n_poly_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp; n_poly_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm; n_bpoly_struct * T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma; n_poly_struct * modulus, * alphapow, * r; int gstab, astab, bstab, use_stab; #if FLINT_WANT_ASSERT n_poly_t leadA, leadB; const slong Sp_size_poly = n_poly_stack_size(Sp->poly_stack); const slong Sp_size_bpoly = n_bpoly_stack_size(Sp->bpoly_stack); #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); #if FLINT_WANT_ASSERT n_poly_init(leadA); n_poly_init(leadB); n_poly_set(leadA, A->coeffs + A->length - 1); n_poly_set(leadB, B->coeffs + B->length - 1); #endif n_poly_stack_fit_request(Sp->poly_stack, 19); cA = n_poly_stack_take_top(Sp->poly_stack); cB = n_poly_stack_take_top(Sp->poly_stack); cG = n_poly_stack_take_top(Sp->poly_stack); cAbar = n_poly_stack_take_top(Sp->poly_stack); cBbar = n_poly_stack_take_top(Sp->poly_stack); gamma = n_poly_stack_take_top(Sp->poly_stack); Aevalp = n_poly_stack_take_top(Sp->poly_stack); Bevalp = n_poly_stack_take_top(Sp->poly_stack); Gevalp = n_poly_stack_take_top(Sp->poly_stack); Abarevalp = n_poly_stack_take_top(Sp->poly_stack); Bbarevalp = n_poly_stack_take_top(Sp->poly_stack); Aevalm = n_poly_stack_take_top(Sp->poly_stack); Bevalm = n_poly_stack_take_top(Sp->poly_stack); Gevalm = n_poly_stack_take_top(Sp->poly_stack); Abarevalm = n_poly_stack_take_top(Sp->poly_stack); Bbarevalm = n_poly_stack_take_top(Sp->poly_stack); r = n_poly_stack_take_top(Sp->poly_stack); alphapow = n_poly_stack_take_top(Sp->poly_stack); modulus = n_poly_stack_take_top(Sp->poly_stack); n_bpoly_stack_fit_request(Sp->bpoly_stack, 1); T = n_bpoly_stack_take_top(Sp->bpoly_stack); n_bpoly_mod_content_last(cA, A, ctx); n_bpoly_mod_content_last(cB, B, ctx); n_bpoly_mod_divexact_last(A, cA, ctx); n_bpoly_mod_divexact_last(B, cB, ctx); n_poly_mod_gcd(cG, cA, cB, ctx); n_poly_mod_divexact(cAbar, cA, cG, ctx); n_poly_mod_divexact(cBbar, cB, cG, ctx); n_poly_mod_gcd(gamma, A->coeffs + A->length - 1, B->coeffs + B->length - 1, ctx); ldegA = n_bpoly_degree1(A); ldegB = n_bpoly_degree1(B); deggamma = n_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1)); n_poly_one(modulus); use_stab = 1; gstab = bstab = astab = 0; if ((ctx.n & UWORD(1)) == UWORD(0)) { success = 0; goto cleanup; } alpha = (ctx.n - UWORD(1))/UWORD(2); choose_prime: /* primes are v - alpha, v + alpha */ if (alpha < 2) { success = 0; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= ctx.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; n_poly_mod_eval2_pow(&gammaevalp, &gammaevalm, gamma, alphapow, ctx); if (gammaevalp == 0 || gammaevalm == 0) goto choose_prime; n_bpoly_mod_interp_reduce_2sm_poly(Aevalp, Aevalm, A, alphapow, ctx); n_bpoly_mod_interp_reduce_2sm_poly(Bevalp, Bevalm, B, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); if (use_stab && gstab) { slong Gdeg; n_bpoly_mod_interp_reduce_2sm_poly(Gevalp, Gevalm, G, alphapow, ctx); Gdeg = n_bpoly_degree0(G); success = 1; success = success && n_poly_degree(Gevalp) == Gdeg; success = success && n_poly_degree(Gevalm) == Gdeg; success = success && Gevalp->coeffs[Gdeg] == gammaevalp; success = success && Gevalm->coeffs[Gdeg] == gammaevalm; n_poly_mod_divrem(Abarevalp, r, Aevalp, Gevalp, ctx); success = success && (r->length == 0); n_poly_mod_divrem(Abarevalm, r, Aevalm, Gevalm, ctx); success = success && (r->length == 0); n_poly_mod_divrem(Bbarevalp, r, Bevalp, Gevalp, ctx); success = success && (r->length == 0); n_poly_mod_divrem(Bbarevalm, r, Bevalm, Gevalm, ctx); success = success && (r->length == 0); if (!success) { use_stab = 0; n_poly_one(modulus); alpha = (ctx.n - UWORD(1))/UWORD(2); goto choose_prime; } _n_poly_mod_scalar_mul_nmod_inplace(Abarevalp, gammaevalp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Abarevalm, gammaevalm, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Bbarevalp, gammaevalp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Bbarevalm, gammaevalm, ctx); } else { n_poly_mod_gcd(Gevalp, Aevalp, Bevalp, ctx); n_poly_mod_divexact(Abarevalp, Aevalp, Gevalp, ctx); n_poly_mod_divexact(Bbarevalp, Bevalp, Gevalp, ctx); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx); n_poly_mod_divexact(Abarevalm, Aevalm, Gevalm, ctx); n_poly_mod_divexact(Bbarevalm, Bevalm, Gevalm, ctx); gstab = astab = bstab = 0; } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); if (n_poly_degree(Gevalp) == 0 || n_poly_degree(Gevalm) == 0) { n_bpoly_one(G); n_bpoly_swap(Abar, A); n_bpoly_swap(Bbar, B); goto successful_put_content; } if (n_poly_degree(Gevalp) != n_poly_degree(Gevalm)) { goto choose_prime; } if (n_poly_degree(modulus) > 0) { FLINT_ASSERT(G->length > 0); if (n_poly_degree(Gevalp) > n_bpoly_degree0(G)) { goto choose_prime; } else if (n_poly_degree(Gevalp) < n_bpoly_degree0(G)) { n_poly_one(modulus); } } _n_poly_mod_scalar_mul_nmod_inplace(Gevalp, gammaevalp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Gevalm, gammaevalm, ctx); if (n_poly_degree(modulus) > 0) { temp = n_poly_mod_evaluate_nmod(modulus, alpha, ctx); FLINT_ASSERT(temp == n_poly_mod_evaluate_nmod(modulus, ctx.n - alpha, ctx)); temp = nmod_mul(temp, alpha, ctx); temp = nmod_add(temp, temp, ctx); temp = nmod_inv(temp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, ctx); if (!gstab) { gstab = !n_bpoly_mod_interp_crt_2sm_poly(&ldegG, G, T, Gevalp, Gevalm, modulus, alphapow, ctx); } n_bpoly_mod_interp_crt_2sm_poly(&ldegAbar, Abar, T, Abarevalp, Abarevalm, modulus, alphapow, ctx); n_bpoly_mod_interp_crt_2sm_poly(&ldegBbar, Bbar, T, Bbarevalp, Bbarevalm, modulus, alphapow, ctx); } else { n_bpoly_mod_interp_lift_2sm_poly(&ldegG, G, Gevalp, Gevalm, alpha, ctx); n_bpoly_mod_interp_lift_2sm_poly(&ldegAbar, Abar, Abarevalp, Abarevalm, alpha, ctx); n_bpoly_mod_interp_lift_2sm_poly(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, alpha, ctx); gstab = astab = bstab = 0; } temp = ctx.n - nmod_mul(alpha, alpha, ctx); n_poly_mod_shift_left_scalar_addmul(modulus, 2, temp, ctx); if (n_poly_degree(modulus) < bound) goto choose_prime; FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } n_poly_one(modulus); goto choose_prime; successful: n_bpoly_mod_content_last(modulus, G, ctx); n_bpoly_mod_divexact_last(G, modulus, ctx); n_bpoly_mod_divexact_last(Abar, G->coeffs + G->length - 1, ctx); n_bpoly_mod_divexact_last(Bbar, G->coeffs + G->length - 1, ctx); successful_put_content: n_bpoly_mod_mul_last(G, cG, ctx); n_bpoly_mod_mul_last(Abar, cAbar, ctx); n_bpoly_mod_mul_last(Bbar, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { n_poly_struct * Glead = G->coeffs + G->length - 1; FLINT_ASSERT(1 == Glead->coeffs[Glead->length - 1]); n_poly_mod_mul(modulus, G->coeffs + G->length - 1, Abar->coeffs + Abar->length - 1, ctx); FLINT_ASSERT(n_poly_equal(modulus, leadA)); n_poly_mod_mul(modulus, G->coeffs + G->length - 1, Bbar->coeffs + Bbar->length - 1, ctx); FLINT_ASSERT(n_poly_equal(modulus, leadB)); } n_poly_clear(leadA); n_poly_clear(leadB); #endif n_poly_stack_give_back(Sp->poly_stack, 19); n_bpoly_stack_give_back(Sp->bpoly_stack, 1); FLINT_ASSERT(Sp_size_poly == n_poly_stack_size(Sp->poly_stack)); FLINT_ASSERT(Sp_size_bpoly == n_bpoly_stack_size(Sp->bpoly_stack)); return success; } flint-3.1.3/src/n_poly/n_bpoly_stack.c000066400000000000000000000032221461254215100177140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" void n_bpoly_stack_init(n_bpoly_stack_t S) { S->alloc = 0; S->array = NULL; S->top = 0; } void n_bpoly_stack_clear(n_bpoly_stack_t S) { slong i; FLINT_ASSERT(S->top == 0); for (i = 0; i < S->alloc; i++) { n_bpoly_clear(S->array[i]); flint_free(S->array[i]); } if (S->array) flint_free(S->array); } /* insure that k slots are available after top and return pointer to top */ n_bpoly_struct ** n_bpoly_stack_fit_request(n_bpoly_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->alloc >= S->top); if (S->top + k > S->alloc) { newalloc = FLINT_MAX(WORD(1), S->top + k); if (S->array) { S->array = (n_bpoly_struct **) flint_realloc(S->array, newalloc*sizeof(n_bpoly_struct*)); } else { S->array = (n_bpoly_struct **) flint_malloc( newalloc*sizeof(n_bpoly_struct*)); } for (i = S->alloc; i < newalloc; i++) { S->array[i] = (n_bpoly_struct *) flint_malloc(sizeof(n_bpoly_struct)); n_bpoly_init(S->array[i]); } S->alloc = newalloc; } return S->array + S->top; } flint-3.1.3/src/n_poly/n_fq.c000066400000000000000000000514401461254215100160150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "n_poly.h" #define MAC(h, m, l, a, b) \ { \ mp_limb_t p1, p0; \ umul_ppmm(p1, p0, a, b); \ add_sssaaaaaa(h, m, l, h, m, l, 0, p1, p0); \ } #define MAC3(h, m, l, a, b) \ { \ mp_limb_t p1, p0; \ umul_ppmm(p1, p0, a, b); \ add_sssaaaaaa(h, m, l, h, m, l, 0, p1, p0); \ } #define MAC2(h, l, a, b) \ { \ mp_limb_t p1, p0; \ umul_ppmm(p1, p0, a, b); \ add_ssaaaa(h, l, h, l, p1, p0); \ } void n_fq_randtest_not_zero( mp_limb_t * a, flint_rand_t state, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; for (i = 0; i < d; i++) a[i] = n_randint(state, fq_nmod_ctx_mod(ctx).n); if (_n_fq_is_zero(a, d)) _n_fq_one(a, d); } void n_fq_get_fq_nmod( fq_nmod_t a, const mp_limb_t * b, const fq_nmod_ctx_t ctx) { slong i; slong d = fq_nmod_ctx_degree(ctx); nmod_poly_fit_length(a, d); for (i = 0; i < d; i++) a->coeffs[i] = b[i]; a->length = d; _nmod_poly_normalise(a); } void n_fq_set_fq_nmod( mp_limb_t * a, const fq_nmod_t b, const fq_nmod_ctx_t ctx) { slong i, d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(b->length <= d); for (i = 0; i < d; i++) a[i] = i < b->length ? b->coeffs[i] : 0; } void n_fq_get_n_poly( n_poly_t a, const mp_limb_t * b, const fq_nmod_ctx_t ctx) { slong i; slong d = fq_nmod_ctx_degree(ctx); n_poly_fit_length(a, d); for (i = 0; i < d; i++) a->coeffs[i] = b[i]; a->length = d; _n_poly_normalise(a); } void _n_fq_set_n_poly( mp_limb_t * a, const mp_limb_t * bcoeffs, slong blen, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (blen > d) { _nmod_poly_rem(a, bcoeffs, blen, ctx->modulus->coeffs, d + 1, ctx->mod); } else { slong i; for (i = 0; i < blen; i++) a[i] = bcoeffs[i]; for (; i < d; i++) a[i] = 0; } } void n_fq_gen( mp_limb_t * a, const fq_nmod_ctx_t ctx) { slong i, d = fq_nmod_ctx_degree(ctx); if (d == 1) { a[0] = nmod_neg(nmod_div(ctx->modulus->coeffs[0], ctx->modulus->coeffs[1], ctx->mod), ctx->mod); } else { a[0] = 0; a[1] = 1; for (i = 2; i < d; i++) a[i] = 0; } } void n_fq_add_si( mp_limb_t * a, const mp_limb_t * b, slong c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (a != b) _nmod_vec_set(a, b, d); if (c < 0) { ulong cc = -c; if (cc >= ctx->mod.n) NMOD_RED(cc, cc, ctx->mod); a[0] = nmod_sub(a[0], cc, ctx->mod); } else { ulong cc = c; if (cc >= ctx->mod.n) NMOD_RED(cc, cc, ctx->mod); a[0] = nmod_add(a[0], cc, ctx->mod); } } int n_fq_equal_fq_nmod( const mp_limb_t * a, const fq_nmod_t b, const fq_nmod_ctx_t ctx) { slong i, d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(b->length <= d); for (i = 0; i < d; i++) { mp_limb_t c = (i >= b->length) ? 0 : b->coeffs[i]; if (a[i] != c) return 0; } return 1; } void n_fq_add_fq_nmod( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_t c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; FLINT_ASSERT(c->length <= d); for (i = 0; i < d; i++) { if (i < c->length) a[i] = nmod_add(b[i], c->coeffs[i], ctx->mod); else a[i] = b[i]; } } void n_fq_sub_fq_nmod( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_t c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; FLINT_ASSERT(c->length <= d); for (i = 0; i < d; i++) { if (i < c->length) a[i] = nmod_sub(b[i], c->coeffs[i], ctx->mod); else a[i] = b[i]; } } void _n_fq_reduce( mp_limb_t * a, mp_limb_t * b, slong blen, const fq_nmod_ctx_t ctx, mp_limb_t * t) /* length 2d */ { slong i, j, k, deg = ctx->modulus->length - 1; slong d = ctx->j[ctx->len - 1]; FLINT_ASSERT(a != b); FLINT_ASSERT(0 <= blen && blen <= 2*d - 1); FLINT_ASSERT(blen == 0 || b[blen - 1] != 0); if (blen <= deg) { for (i = 0; i < blen; i++) a[i] = b[i]; for (i = blen; i < deg; i++) a[i] = 0; } else if (ctx->sparse_modulus) { nmod_t mod = ctx->mod; for (k = ctx->len - 2; k >= 0; k--) t[k] = mod.n - ctx->a[k]; for (i = blen - 1; i >= d; i--) { for (k = ctx->len - 2; k >= 0; k--) NMOD_ADDMUL(b[ctx->j[k] + i - d], b[i], t[k], mod); b[i] = 0; } for (i = 0; i < deg; i++) a[i] = b[i]; } else { /* _nmod_poly_divrem_newton_n_preinv(t, a, b, blen, ctx->modulus->coeffs, ctx->modulus->length, ctx->inv->coeffs, ctx->inv->length, ctx->mod); */ mp_limb_t * Q = t; mp_limb_t * R = a; const mp_limb_t * A = b; slong lenA = blen; const mp_limb_t * B = ctx->modulus->coeffs; slong lenB = deg + 1; const mp_limb_t * Binv = ctx->inv->coeffs; slong lenBinv = ctx->inv->length; const slong lenQ = lenA - lenB + 1; FLINT_ASSERT(lenBinv > 0); FLINT_ASSERT(lenQ > 0); if (lenQ <= 2) { _nmod_poly_divrem_basecase_preinv1(Q, R, A, lenA, B, lenB, Binv[0], ctx->mod); return; } if (deg < 20) { for (i = 0; i < lenQ; i++) { mp_limb_t t2 = 0, t1 = 0, t0 = 0; j = FLINT_MAX(0, i - lenBinv + 1); umul_ppmm(t1, t0, A[lenA - 1 - j], Binv[i - j]); for (j++; j <= i; j++) MAC(t2, t1, t0, A[lenA - 1 - j], Binv[i - j]); NMOD_RED3(Q[lenQ - 1 - i], t2, t1, t0, ctx->mod); } for (i = 0; i < deg; i++) { mp_limb_t t2 = 0, t1 = 0, t0 = 0; for (j = FLINT_MAX(0, i - lenQ + 1); j <= i; j++) MAC(t2, t1, t0, B[j], Q[i - j]); NMOD_RED3(t0, t2, t1, t0, ctx->mod); R[i] = nmod_sub(A[i], t0, ctx->mod); } } else { mp_ptr Arev = t + d; _nmod_poly_reverse(Arev, A + (lenA - lenQ), lenQ, lenQ); _nmod_poly_mullow(Q, Arev, lenQ, Binv, FLINT_MIN(lenQ, lenBinv), lenQ, ctx->mod); _nmod_poly_reverse(Q, Q, lenQ, lenQ); FLINT_ASSERT(lenB > 1); FLINT_ASSERT(lenQ < lenB - 1); _nmod_poly_mullow(R, B, lenB - 1, Q, lenQ, lenB - 1, ctx->mod); _nmod_vec_sub(R, A, R, lenB - 1, ctx->mod); } } } void _n_fq_madd2( mp_limb_t * a, /* length 2d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const fq_nmod_ctx_t ctx, mp_limb_t * t) /* length 2d */ { slong d = ctx->modulus->length - 1; FLINT_ASSERT(d > 0); if (d < 30) { slong i, j; for (i = 0; i + 1 < d; i++) { mp_limb_t t2 = 0, t1 = 0, t0 = 0; mp_limb_t s2 = 0, s1 = 0, s0 = 0; umul_ppmm(t1, t0, b[i], c[0]); umul_ppmm(s1, s0, b[d - 1], c[d - 1 - i]); add_ssaaaa(t1, t0, t1, t0, 0, a[i]); add_ssaaaa(s1, s0, s1, s0, 0, a[2*d - 2 - i]); for (j = 1; j <= i; j++) { MAC(t2, t1, t0, b[i - j], c[0 + j]); MAC(s2, s1, s0, b[d - 1 - j], c[d - 1 - i + j]); } NMOD_RED3(a[i], t2, t1, t0, ctx->mod); NMOD_RED3(a[2*d - 2 - i], s2, s1, s0, ctx->mod); } { mp_limb_t t2 = 0, t1 = 0, t0 = 0; umul_ppmm(t1, t0, b[d - 1], c[0]); add_ssaaaa(t1, t0, t1, t0, 0, a[d - 1]); for (j = 1; j < d; j++) { MAC(t2, t1, t0, b[d - 1 - j], c[0 + j]); } NMOD_RED3(a[d - 1], t2, t1, t0, ctx->mod); } } else { _nmod_poly_mul(t, b, d, c, d, ctx->mod); _nmod_vec_add(a, a, t, 2*d - 1, ctx->mod); } } void _n_fq_mul_ui( mp_limb_t * a, /* length d */ const mp_limb_t * b, /* length d */ mp_limb_t c, slong d, nmod_t mod) { if (c >= mod.n) NMOD_RED(c, c, mod); _nmod_vec_scalar_mul_nmod(a, b, d, c, mod); } void _n_fq_mul2( mp_limb_t * a, /* length 2d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(d > 0); if (d < 30) { slong i, j; for (i = 0; i + 1 < d; i++) { mp_limb_t t2 = 0, t1 = 0, t0 = 0; mp_limb_t s2 = 0, s1 = 0, s0 = 0; umul_ppmm(t1, t0, b[i], c[0]); umul_ppmm(s1, s0, b[d - 1], c[d - 1 - i]); for (j = 1; j <= i; j++) { MAC(t2, t1, t0, b[i - j], c[0 + j]); MAC(s2, s1, s0, b[d - 1 - j], c[d - 1 - i + j]); } NMOD_RED3(a[i], t2, t1, t0, ctx->mod); NMOD_RED3(a[2*d - 2 - i], s2, s1, s0, ctx->mod); } { mp_limb_t t2 = 0, t1 = 0, t0 = 0; umul_ppmm(t1, t0, b[d - 1], c[0]); for (j = 1; j < d; j++) { MAC(t2, t1, t0, b[d - 1 - j], c[0 + j]); } NMOD_RED3(a[d - 1], t2, t1, t0, ctx->mod); } } else { _nmod_poly_mul(a, b, d, c, d, ctx->mod); } } /**************************** lazy *******************************************/ int _n_fq_dot_lazy_size( slong len, const fq_nmod_ctx_t ctx) { ulong t[4]; slong d = fq_nmod_ctx_degree(ctx); mp_limb_t p = ctx->mod.n; if (d > 30 || p < 2 || len < 0) return 0; umul_ppmm(t[1], t[0], p - 1, p - 1); t[2] = mpn_mul_1(t, t, 2, d); t[3] = mpn_mul_1(t, t, 3, len); if (t[3] != 0) return 0; if (t[2] != 0) return 3; if (t[1] != 0) return 2; return 1; } void _n_fq_reduce2_lazy1( mp_limb_t * a, /* length 6d, 2d used */ slong d, nmod_t ctx) { slong i; for (i = 0; i < 2*d - 1; i++) NMOD_RED(a[i], a[i], ctx); } void _n_fq_madd2_lazy1( mp_limb_t * a, /* length 6d, 2d used */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d) { slong i, j; for (i = 0; i + 1 < d; i++) { mp_limb_t t0 = 0; mp_limb_t s0 = 0; t0 = a[i + 0]; s0 = a[(2*d - 2 - i) + 0]; t0 += b[i]*c[0]; s0 += b[d - 1]*c[d - 1 - i]; for (j = 1; j <= i; j++) { t0 += b[i - j]*c[0 + j]; s0 += b[d - 1 - j]*c[d - 1 - i + j]; } a[i + 0] = t0; a[(2*d - 2 - i) + 0] = s0; } { mp_limb_t t0 = 0; t0 = a[(d - 1) + 0]; t0 += b[d - 1]*c[0]; for (j = 1; j < d; j++) { t0 += b[d - 1 - j]*c[0 + j]; } a[(d - 1) + 0] = t0; } } void _n_fq_mul2_lazy1( mp_limb_t * a, /* length 6d, 2d used */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d) { slong i,j; for (i = 0; i + 1 < d; i++) { mp_limb_t t0 = 0; mp_limb_t s0 = 0; t0 = b[i]*c[0]; s0 = b[d - 1]*c[d - 1 - i]; for (j = 1; j <= i; j++) { t0 += b[i - j]*c[0 + j]; s0 += b[d - 1 - j]*c[d - 1 - i + j]; } a[i + 0] = t0; a[(2*d - 2 - i) + 0] = s0; } { mp_limb_t t0 = 0; t0 = b[d - 1]*c[0]; for (j = 1; j < d; j++) { t0 += b[d - 1 - j]*c[0 + j]; } a[(d - 1) + 0] = t0; } } void _n_fq_reduce2_lazy2( mp_limb_t * a, /* length 6d, 4d used */ slong d, nmod_t ctx) { slong i; for (i = 0; i < 2*d - 1; i++) NMOD2_RED2(a[i], a[2*i + 1], a[2*i + 0], ctx); } void _n_fq_madd2_lazy2( mp_limb_t * a, /* length 6d, 4d used */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d) { slong i,j; for (i = 0; i + 1 < d; i++) { mp_limb_t t1 = 0, t0 = 0; mp_limb_t s1 = 0, s0 = 0; t0 = a[2*i + 0]; t1 = a[2*i + 1]; s0 = a[2*(2*d - 2 - i) + 0]; s1 = a[2*(2*d - 2 - i) + 1]; MAC2(t1, t0, b[i], c[0]); MAC2(s1, s0, b[d - 1], c[d - 1 - i]); for (j = 1; j <= i; j++) { MAC2(t1, t0, b[i - j], c[0 + j]); MAC2(s1, s0, b[d - 1 - j], c[d - 1 - i + j]); } a[2*i + 0] = t0; a[2*i + 1] = t1; a[2*(2*d - 2 - i) + 0] = s0; a[2*(2*d - 2 - i) + 1] = s1; } { mp_limb_t t1 = 0, t0 = 0; t0 = a[2*(d - 1) + 0]; t1 = a[2*(d - 1) + 1]; MAC2(t1, t0, b[d - 1], c[0]); for (j = 1; j < d; j++) { MAC2(t1, t0, b[d - 1 - j], c[0 + j]); } a[2*(d - 1) + 0] = t0; a[2*(d - 1) + 1] = t1; } } void _n_fq_mul2_lazy2( mp_limb_t * a, /* length 6d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d) { slong i,j; for (i = 0; i + 1 < d; i++) { mp_limb_t t1 = 0, t0 = 0; mp_limb_t s1 = 0, s0 = 0; umul_ppmm(t1, t0, b[i], c[0]); umul_ppmm(s1, s0, b[d - 1], c[d - 1 - i]); for (j = 1; j <= i; j++) { MAC2(t1, t0, b[i - j], c[0 + j]); MAC2(s1, s0, b[d - 1 - j], c[d - 1 - i + j]); } a[2*i + 0] = t0; a[2*i + 1] = t1; a[2*(2*d - 2 - i) + 0] = s0; a[2*(2*d - 2 - i) + 1] = s1; } { mp_limb_t t1 = 0, t0 = 0; umul_ppmm(t1, t0, b[d - 1], c[0]); for (j = 1; j < d; j++) { MAC2(t1, t0, b[d - 1 - j], c[0 + j]); } a[2*(d - 1) + 0] = t0; a[2*(d - 1) + 1] = t1; } } void _n_fq_reduce2_lazy3( mp_limb_t * a, /* length 6d */ slong d, nmod_t ctx) { slong i; for (i = 0; i < 2*d - 1; i++) NMOD_RED3(a[i], a[3*i + 2], a[3*i + 1], a[3*i + 0], ctx); } void _n_fq_madd2_lazy3( mp_limb_t * a, /* length 6d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d) { slong i,j; for (i = 0; i + 1 < d; i++) { mp_limb_t t2 = 0, t1 = 0, t0 = 0; mp_limb_t s2 = 0, s1 = 0, s0 = 0; t0 = a[3*i + 0]; t1 = a[3*i + 1]; t2 = a[3*i + 2]; s0 = a[3*(2*d - 2 - i) + 0]; s1 = a[3*(2*d - 2 - i) + 1]; s2 = a[3*(2*d - 2 - i) + 2]; MAC3(t2, t1, t0, b[i], c[0]); MAC3(s2, s1, s0, b[d - 1], c[d - 1 - i]); for (j = 1; j <= i; j++) { MAC3(t2, t1, t0, b[i - j], c[0 + j]); MAC3(s2, s1, s0, b[d - 1 - j], c[d - 1 - i + j]); } a[3*i + 0] = t0; a[3*i + 1] = t1; a[3*i + 2] = t2; a[3*(2*d - 2 - i) + 0] = s0; a[3*(2*d - 2 - i) + 1] = s1; a[3*(2*d - 2 - i) + 2] = s2; } { mp_limb_t t2 = 0, t1 = 0, t0 = 0; t0 = a[3*(d - 1) + 0]; t1 = a[3*(d - 1) + 1]; t2 = a[3*(d - 1) + 2]; MAC3(t2, t1, t0, b[d - 1], c[0]); for (j = 1; j < d; j++) { MAC3(t2, t1, t0, b[d - 1 - j], c[0 + j]); } a[3*(d - 1) + 0] = t0; a[3*(d - 1) + 1] = t1; a[3*(d - 1) + 2] = t2; } } void _n_fq_mul2_lazy3( mp_limb_t * a, /* length 6d */ const mp_limb_t * b, /* length d */ const mp_limb_t * c, /* length d */ slong d) { slong i,j; for (i = 0; i + 1 < d; i++) { mp_limb_t t2 = 0, t1 = 0, t0 = 0; mp_limb_t s2 = 0, s1 = 0, s0 = 0; umul_ppmm(t1, t0, b[i], c[0]); umul_ppmm(s1, s0, b[d - 1], c[d - 1 - i]); for (j = 1; j <= i; j++) { MAC3(t2, t1, t0, b[i - j], c[0 + j]); MAC3(s2, s1, s0, b[d - 1 - j], c[d - 1 - i + j]); } a[3*i + 0] = t0; a[3*i + 1] = t1; a[3*i + 2] = t2; a[3*(2*d - 2 - i) + 0] = s0; a[3*(2*d - 2 - i) + 1] = s1; a[3*(2*d - 2 - i) + 2] = s2; } { mp_limb_t t2 = 0, t1 = 0, t0 = 0; umul_ppmm(t1, t0, b[d - 1], c[0]); for (j = 1; j < d; j++) { MAC3(t2, t1, t0, b[d - 1 - j], c[0 + j]); } a[3*(d - 1) + 0] = t0; a[3*(d - 1) + 1] = t1; a[3*(d - 1) + 2] = t2; } } /***************************************************************************/ void _n_fq_inv( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_ctx_t ctx, mp_limb_t * t) /* length d */ { slong d = ctx->modulus->length - 1; slong blen = d; FLINT_ASSERT(d > 0); while (blen > 0 && b[blen - 1] == 0) blen--; if (blen < 1) { flint_throw(FLINT_ERROR, "impossible inverse in _fq_nmod_inv"); } else if (blen == 1) { a[0] = n_invmod(b[0], ctx->mod.n); _nmod_vec_zero(a + 1, d - 1); } else { if (1 != _nmod_poly_gcdinv(t, a, b, blen, ctx->modulus->coeffs, d + 1, ctx->mod)) { flint_throw(FLINT_ERROR, "impossible inverse in _fq_nmod_inv"); } if (t[0] != 1) { _nmod_vec_scalar_mul_nmod(a, a, d, n_invmod(t[0], ctx->mod.n), ctx->mod); } } } void n_fq_mul( mp_limb_t * a, const mp_limb_t * b, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { fq_nmod_t A, B, C; fq_nmod_init(A, ctx); fq_nmod_init(B, ctx); fq_nmod_init(C, ctx); n_fq_get_fq_nmod(B, b, ctx); n_fq_get_fq_nmod(C, c, ctx); fq_nmod_mul(A, B, C, ctx); n_fq_set_fq_nmod(a, A, ctx); fq_nmod_clear(A, ctx); fq_nmod_clear(B, ctx); fq_nmod_clear(C, ctx); } void n_fq_addmul( mp_limb_t * a, const mp_limb_t * b, const mp_limb_t * c, const mp_limb_t * d, const fq_nmod_ctx_t ctx) { mp_limb_t * t = FLINT_ARRAY_ALLOC(fq_nmod_ctx_degree(ctx), mp_limb_t); n_fq_mul(t, c, d, ctx); n_fq_add(a, b, t, ctx); flint_free(t); } void n_fq_mul_fq_nmod( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_t C, const fq_nmod_ctx_t ctx) { fq_nmod_t A, B; fq_nmod_init(A, ctx); fq_nmod_init(B, ctx); n_fq_get_fq_nmod(B, b, ctx); fq_nmod_mul(A, B, C, ctx); n_fq_set_fq_nmod(a, A, ctx); fq_nmod_clear(A, ctx); fq_nmod_clear(B, ctx); } void n_fq_inv( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_ctx_t ctx) { fq_nmod_t A, B; fq_nmod_init(A, ctx); fq_nmod_init(B, ctx); n_fq_get_fq_nmod(B, b, ctx); fq_nmod_inv(A, B, ctx); n_fq_set_fq_nmod(a, A, ctx); fq_nmod_clear(A, ctx); fq_nmod_clear(B, ctx); } void _n_fq_pow_ui( mp_limb_t * a, const mp_limb_t * b, ulong e, const fq_nmod_ctx_t ctx) { fq_nmod_t A, B; fq_nmod_init(A, ctx); fq_nmod_init(B, ctx); n_fq_get_fq_nmod(B, b, ctx); fq_nmod_pow_ui(A, B, e, ctx); n_fq_set_fq_nmod(a, A, ctx); fq_nmod_clear(A, ctx); fq_nmod_clear(B, ctx); } void n_fq_pow_fmpz( mp_limb_t * a, const mp_limb_t * b, const fmpz_t e, const fq_nmod_ctx_t ctx) { fq_nmod_t A, B; fq_nmod_init(A, ctx); fq_nmod_init(B, ctx); n_fq_get_fq_nmod(B, b, ctx); fq_nmod_pow(A, B, e, ctx); n_fq_set_fq_nmod(a, A, ctx); fq_nmod_clear(A, ctx); fq_nmod_clear(B, ctx); } void n_fq_pow_ui( mp_limb_t * a, const mp_limb_t * b, ulong e, const fq_nmod_ctx_t ctx) { fq_nmod_t A, B; fq_nmod_init(A, ctx); fq_nmod_init(B, ctx); n_fq_get_fq_nmod(B, b, ctx); fq_nmod_pow_ui(A, B, e, ctx); n_fq_set_fq_nmod(a, A, ctx); fq_nmod_clear(A, ctx); fq_nmod_clear(B, ctx); } int n_fq_is_canonical( const mp_limb_t * a, const fq_nmod_ctx_t ctx) { slong i, d = fq_nmod_ctx_degree(ctx); for (i = 0; i < d; i++) { if (a[i] >= ctx->mod.n) return 0; } return 1; } flint-3.1.3/src/n_poly/n_fq_bpoly.c000066400000000000000000000105031461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" int n_fq_bpoly_is_canonical(const n_fq_bpoly_t A, const fq_nmod_ctx_t ctx) { slong i; if (A->length < 0) return 0; if (A->length > A->alloc) return 0; for (i = 0; i < A->length; i++) { if (!n_fq_poly_is_canonical(A->coeffs + i, ctx)) return 0; if (i + 1 == A->length && n_fq_poly_is_zero(A->coeffs + i)) return 0; } return 1; } void n_fq_bpoly_one(n_fq_bpoly_t A, const fq_nmod_ctx_t ctx) { n_fq_bpoly_fit_length(A, 1); A->length = 1; n_fq_poly_one(A->coeffs + 0, ctx); } void n_fq_bpoly_set( n_fq_bpoly_t A, const n_fq_bpoly_t B, const fq_nmod_ctx_t ctx) { slong i; if (A == B) return; n_fq_bpoly_fit_length(A, B->length); A->length = B->length; for (i = 0; i < B->length; i++) n_fq_poly_set(A->coeffs + i, B->coeffs + i, ctx); } int n_fq_bpoly_equal( const n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (!n_fq_poly_equal(A->coeffs + i, B->coeffs + i, ctx)) return 0; } return 1; } void n_fq_bpoly_get_coeff_n_fq( mp_limb_t * c, const n_bpoly_t A, slong e0, slong e1, const fq_nmod_ctx_t ctx) { if (e0 >= A->length) _n_fq_zero(c, fq_nmod_ctx_degree(ctx)); else n_fq_poly_get_coeff_n_fq(c, A->coeffs + e0, e1, ctx); } void n_fq_bpoly_set_coeff_n_fq( n_bpoly_t A, slong e0, slong e1, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong i; if (e0 >= A->length) { n_fq_bpoly_fit_length(A, e0 + 1); for (i = A->length; i <= e0; i++) n_fq_poly_zero(A->coeffs + i); A->length = e0 + 1; } n_fq_poly_set_coeff_n_fq(A->coeffs + e0, e1, c, ctx); n_fq_bpoly_normalise(A); FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); } void n_fq_bpoly_get_coeff_fq_nmod( fq_nmod_t c, const n_bpoly_t A, slong e0, slong e1, const fq_nmod_ctx_t ctx) { if (e0 >= A->length) fq_nmod_zero(c, ctx); else n_fq_poly_get_coeff_fq_nmod(c, A->coeffs + e0, e1, ctx); } void n_fq_bpoly_set_fq_nmod_poly_gen0( n_fq_bpoly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) { slong i; n_bpoly_fit_length(A, B->length); A->length = 0; for (i = 0; i < B->length; i++) n_fq_poly_set_fq_nmod(A->coeffs + i, B->coeffs + i, ctx); A->length = B->length; n_bpoly_normalise(A); } void n_fq_bpoly_set_n_fq_poly_gen0( n_fq_bpoly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; n_bpoly_fit_length(A, B->length); for (i = 0; i < B->length; i++) n_fq_poly_set_n_fq(A->coeffs + i, B->coeffs + d*i, ctx); A->length = B->length; n_bpoly_normalise(A); } void n_fq_bpoly_set_n_fq_poly_gen1( n_fq_bpoly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx) { n_bpoly_fit_length(A, 1); n_fq_poly_set(A->coeffs + 0, B, ctx); A->length = !n_poly_is_zero(A->coeffs + 0); } void n_fq_bpoly_derivative_gen0( n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx) { slong i; slong Blen = B->length; if (Blen < 2) { n_bpoly_zero(A); return; } n_bpoly_fit_length(A, Blen - 1); for (i = 1; i < Blen; i++) n_fq_poly_scalar_mul_ui(A->coeffs + i - 1, B->coeffs + i, i, ctx); A->length = Blen - 1; n_bpoly_normalise(A); } void n_fq_bpoly_scalar_mul_n_fq( n_fq_bpoly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; if (_n_fq_is_zero(c, d)) { A->length = 0; return; } if (_n_fq_is_one(c, d)) { return; } for (i = 0; i < A->length; i++) n_fq_poly_scalar_mul_n_fq(A->coeffs + i, A->coeffs + i, c, ctx); } flint-3.1.3/src/n_poly/n_fq_bpoly_gcd.c000066400000000000000000000742321461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "n_poly.h" #include "fq_nmod_mpoly_factor.h" /* g is in Fq[gen(1)] */ static void n_fq_bpoly_content_var0( n_fq_poly_t g, const n_fq_bpoly_t A, const fq_nmod_ctx_t ctx) { slong i; n_fq_poly_zero(g); for (i = 0; i < A->length; i++) { n_fq_poly_gcd(g, g, A->coeffs + i, ctx); if (n_fq_poly_degree(g) == 0) break; } } static void n_fq_bpoly_divexact_poly_var1( n_fq_bpoly_t A, const n_fq_poly_t b, /* in Fq[gen(1)] */ const fq_nmod_ctx_t ctx) { slong i; n_fq_poly_t t, r; n_fq_poly_init(t); n_fq_poly_init(r); for (i = 0; i < A->length; i++) { if (n_fq_poly_is_zero(A->coeffs + i)) continue; n_fq_poly_divrem(t, r, A->coeffs + i, b, ctx); n_fq_poly_swap(A->coeffs + i, t); } n_fq_poly_clear(t); n_fq_poly_clear(r); } void n_fq_bpoly_mul_last(n_bpoly_t A, const n_poly_t b, const fq_nmod_ctx_t ctx) { slong i; n_fq_poly_t t; n_fq_poly_init(t); for (i = 0; i < A->length; i++) { if (n_fq_poly_is_zero(A->coeffs + i)) continue; n_fq_poly_mul(t, A->coeffs + i, b, ctx); n_fq_poly_set(A->coeffs + i, t, ctx); } n_fq_poly_clear(t); } /*****************************************************************************/ void n_fq_poly_eval2p_pow( mp_limb_t * vp, mp_limb_t * vm, const n_fq_poly_t P, n_poly_t alphapow, slong d, nmod_t ctx) { const mp_limb_t * Pcoeffs = P->coeffs; slong Plen = P->length; mp_limb_t * alpha_powers = alphapow->coeffs; mp_limb_t p1, p0, a0, a1, a2, q1, q0, b0, b1, b2; slong i, k; FLINT_ASSERT(P->alloc >= d*Plen); if (Plen > alphapow->length) { slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); n_poly_fit_length(alphapow, Plen); for (k = oldlength; k < Plen; k++) { alphapow->coeffs[k] = nmod_mul(alphapow->coeffs[k - 1], alphapow->coeffs[1], ctx); } alphapow->length = Plen; alpha_powers = alphapow->coeffs; } for (i = 0; i < d; i++) { a0 = a1 = a2 = 0; b0 = b1 = b2 = 0; for (k = 0; k + 2 <= Plen; k += 2) { umul_ppmm(p1, p0, Pcoeffs[d*(k + 0) + i], alpha_powers[k + 0]); umul_ppmm(q1, q0, Pcoeffs[d*(k + 1) + i], alpha_powers[k + 1]); add_sssaaaaaa(a2, a1, a0, a2, a1, a0, 0, p1, p0); add_sssaaaaaa(b2, b1, b0, b2, b1, b0, 0, q1, q0); } if (k < Plen) { umul_ppmm(p1, p0, Pcoeffs[d*(k + 0) + i], alpha_powers[k + 0]); add_sssaaaaaa(a2, a1, a0, a2, a1, a0, 0, p1, p0); k++; } FLINT_ASSERT(k == Plen); NMOD_RED3(p0, a2, a1, a0, ctx); NMOD_RED3(q0, b2, b1, b0, ctx); vp[i] = nmod_add(p0, q0, ctx); vm[i] = nmod_sub(p0, q0, ctx); } } void n_fq_bpoly_interp_reduce_2psm_poly( n_fq_poly_t Ap, n_fq_poly_t Am, const n_fq_bpoly_t A, n_poly_t alphapow, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, Alen = A->length; const n_poly_struct * Ac = A->coeffs; mp_limb_t * Apc, * Amc; n_poly_fit_length(Ap, d*Alen); n_poly_fit_length(Am, d*Alen); Apc = Ap->coeffs; Amc = Am->coeffs; for (i = 0; i < Alen; i++) n_fq_poly_eval2p_pow(Apc + d*i, Amc + d*i, Ac + i, alphapow, d, fq_nmod_ctx_mod(ctx)); Ap->length = Alen; _n_fq_poly_normalise(Ap, d); Am->length = Alen; _n_fq_poly_normalise(Am, d); } void n_fq_bpoly_interp_lift_2psm_poly( slong * deg1, n_fq_bpoly_t T, const n_fq_poly_t A, const n_fq_poly_t B, mp_limb_t alpha, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); slong i, j; slong lastlength = 0; const mp_limb_t * Acoeffs = A->coeffs; const mp_limb_t * Bcoeffs = B->coeffs; n_fq_poly_struct * Tcoeffs; slong Alen = A->length; slong Blen = B->length; slong Tlen = FLINT_MAX(Alen, Blen); mp_limb_t d0 = (1 + mod.n)/2; mp_limb_t d1 = nmod_inv(nmod_add(alpha, alpha, mod), mod); mp_limb_t * u, u1nonzero, u0nonzero; u = FLINT_ARRAY_ALLOC(2*d, mp_limb_t); n_bpoly_fit_length(T, Tlen); Tcoeffs = T->coeffs; for (i = 0; i < Tlen; i++) { _nmod_vec_zero(u, 2*d); if (i < Alen && i < Blen) { u0nonzero = u1nonzero = 0; for (j = 0; j < d; j++) { ulong t0 = nmod_add(Acoeffs[d*i + j], Bcoeffs[d*i + j], mod); ulong t1 = nmod_sub(Acoeffs[d*i + j], Bcoeffs[d*i + j], mod); u[d*0 + j] = t0; u[d*1 + j] = t1; u1nonzero |= t1; u0nonzero |= t0; } } else if (i < Alen) { u0nonzero = 0; for (j = 0; j < d; j++) { ulong t0 = Acoeffs[d*i + j]; u0nonzero |= t0; u[d*0 + j] = t0; u[d*1 + j] = t0; } u1nonzero = u0nonzero; } else { u0nonzero = 0; for (j = 0; j < d; j++) { ulong t0 = Bcoeffs[d*i + j]; u0nonzero |= t0; u[d*0 + j] = t0; u[d*1 + j] = nmod_neg(t0, mod); } u1nonzero = u0nonzero; } if (u1nonzero | u0nonzero) { n_poly_fit_length(Tcoeffs + i, d*2); _nmod_vec_scalar_mul_nmod(Tcoeffs[i].coeffs + d*0, u + d*0, d, d0, mod); if (u1nonzero) { _nmod_vec_scalar_mul_nmod(Tcoeffs[i].coeffs + d*1, u + d*1, d, d1, mod); Tcoeffs[i].length = 2; } else { Tcoeffs[i].length = 1; } lastlength = FLINT_MAX(lastlength, Tcoeffs[i].length); } else { Tcoeffs[i].length = 0; } } *deg1 = lastlength - 1; flint_free(u); FLINT_ASSERT(Tlen < 1 || !n_fq_poly_is_zero(Tcoeffs + Tlen - 1)); T->length = Tlen; FLINT_ASSERT(n_fq_bpoly_is_canonical(T, ctx)); } void _n_fq_poly_addmul_plinear( n_fq_poly_t A, mp_limb_t * Bcoeffs, slong Blen, const n_poly_t C, mp_limb_t * s, slong d, nmod_t mod) { slong i, j; mp_limb_t * Acoeffs; mp_limb_t * Ccoeffs = C->coeffs; slong Clen = C->length; slong Alen = FLINT_MAX(Blen, Clen + 1); n_poly_fit_length(A, d*Alen); Acoeffs = A->coeffs; for (i = 0; i < Alen; i++) { for (j = 0; j < d; j++) { ulong p1, p0, t0 = 0, t1 = 0, t2 = 0; if (i < Blen) { t0 = Bcoeffs[d*i + j]; } if (i < Clen) { umul_ppmm(p1, p0, Ccoeffs[i], s[0*d + j]); add_ssaaaa(t1, t0, t1, t0, p1, p0); } if (0 < i && i - 1 < Clen) { umul_ppmm(p1, p0, Ccoeffs[i - 1], s[1*d + j]); add_sssaaaaaa(t2, t1, t0, t2, t1, t0, 0, p1, p0); } NMOD_RED3(Acoeffs[i*d + j], t2, t1, t0, mod); } } A->length = Alen; _n_fq_poly_normalise(A, d); } int n_fq_bpoly_interp_crt_2psm_poly( slong * deg1, n_fq_bpoly_t F, n_fq_bpoly_t T, n_fq_poly_t A, n_fq_poly_t B, const n_poly_t modulus, n_poly_t alphapow, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); int changed = 0; slong i, j, lastlength = 0; slong Alen = A->length; slong Blen = B->length; slong Flen = F->length; slong Tlen = FLINT_MAX(FLINT_MAX(Alen, Blen), Flen); n_fq_poly_struct * Tcoeffs, * Fcoeffs; mp_limb_t * Acoeffs, * Bcoeffs; mp_limb_t * u, unonzero; mp_limb_t malpha = mod.n - alphapow->coeffs[1]; n_bpoly_fit_length(T, Tlen); Tcoeffs = T->coeffs; Acoeffs = A->coeffs; Bcoeffs = B->coeffs; Fcoeffs = F->coeffs; u = FLINT_ARRAY_ALLOC(2*d, mp_limb_t); for (i = 0; i < Tlen; i++) { if (i < Flen) n_fq_poly_eval2p_pow(u + d*0, u + d*1, Fcoeffs + i, alphapow, d, mod); else _nmod_vec_zero(u, 2*d); if (i < Alen) _nmod_vec_sub(u + d*0, u + d*0, Acoeffs + d*i, d, mod); if (i < Blen) _nmod_vec_sub(u + d*1, u + d*1, Bcoeffs + d*i, d, mod); unonzero = 0; for (j = 0; j < d; j++) { mp_limb_t t1 = nmod_sub(u[d*1 + j], u[d*0 + j], mod); mp_limb_t t0 = nmod_add(u[d*1 + j], u[d*0 + j], mod); u[d*1 + j] = t1; unonzero |= u[d*1 + j]; u[d*0 + j] = nmod_mul(malpha, t0, mod); unonzero |= u[d*0 + j]; } if (unonzero) { mp_limb_t * Ficoeffs = i < Flen ? Fcoeffs[i].coeffs : NULL; slong Filen = i < Flen ? Fcoeffs[i].length : 0; _n_fq_poly_addmul_plinear(Tcoeffs + i, Ficoeffs, Filen, modulus, u, d, mod); changed = 1; } else { if (i < Flen) n_fq_poly_set(Tcoeffs + i, Fcoeffs + i, ctx); else n_fq_poly_zero(Tcoeffs + i); } lastlength = FLINT_MAX(lastlength, Tcoeffs[i].length); } FLINT_ASSERT(i < 1 || !n_fq_poly_is_zero(Tcoeffs + i - 1)); T->length = i; if (changed) n_bpoly_swap(T, F); FLINT_ASSERT(n_fq_bpoly_is_canonical(F, ctx)); *deg1 = lastlength - 1; flint_free(u); FLINT_ASSERT(n_fq_bpoly_is_canonical(T, ctx)); return changed; } int n_fq_bpoly_gcd_brown_smprime2p( n_fq_bpoly_t G, n_fq_bpoly_t Abar, n_fq_bpoly_t Bbar, const n_fq_bpoly_t A, const n_fq_bpoly_t B, const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t Sp, n_fq_poly_t cA, n_fq_poly_t cB, n_fq_poly_t cG, n_fq_poly_t cAbar, n_fq_poly_t cBbar, n_fq_poly_t gamma, n_fq_poly_t r) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); int success; slong bound; mp_limb_t alpha, temp, * gammaevalp, * gammaevalm; n_fq_poly_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp; n_fq_poly_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm; n_bpoly_struct * T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_struct * modulus, * alphapow; int gstab, astab, bstab, use_stab; ldegA = n_fq_bpoly_degree1(A); ldegB = n_fq_bpoly_degree1(B); deggamma = n_fq_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); if (bound >= mod.n/2) return 0; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); gammaevalp = FLINT_ARRAY_ALLOC(d, mp_limb_t); gammaevalm = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_poly_stack_fit_request(Sp->poly_stack, 12); Aevalp = n_poly_stack_take_top(Sp->poly_stack); Bevalp = n_poly_stack_take_top(Sp->poly_stack); Gevalp = n_poly_stack_take_top(Sp->poly_stack); Abarevalp = n_poly_stack_take_top(Sp->poly_stack); Bbarevalp = n_poly_stack_take_top(Sp->poly_stack); Aevalm = n_poly_stack_take_top(Sp->poly_stack); Bevalm = n_poly_stack_take_top(Sp->poly_stack); Gevalm = n_poly_stack_take_top(Sp->poly_stack); Abarevalm = n_poly_stack_take_top(Sp->poly_stack); Bbarevalm = n_poly_stack_take_top(Sp->poly_stack); alphapow = n_poly_stack_take_top(Sp->poly_stack); modulus = n_poly_stack_take_top(Sp->poly_stack); n_bpoly_stack_fit_request(Sp->bpoly_stack, 1); T = n_bpoly_stack_take_top(Sp->bpoly_stack); n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1)); n_poly_one(modulus); use_stab = 1; gstab = bstab = astab = 0; if ((mod.n & UWORD(1)) == UWORD(0)) { success = 0; goto cleanup; } alpha = (mod.n - UWORD(1))/UWORD(2); choose_prime: if (alpha < 2) { success = 0; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= mod.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; n_fq_poly_eval2p_pow(gammaevalp, gammaevalm, gamma, alphapow, d, mod); if (_n_fq_is_zero(gammaevalp, d) || _n_fq_is_zero(gammaevalm, d)) goto choose_prime; n_fq_bpoly_interp_reduce_2psm_poly(Aevalp, Aevalm, A, alphapow, ctx); n_fq_bpoly_interp_reduce_2psm_poly(Bevalp, Bevalm, B, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); if (use_stab && gstab) { slong Gdeg; n_fq_bpoly_interp_reduce_2psm_poly(Gevalp, Gevalm, G, alphapow, ctx); Gdeg = n_fq_bpoly_degree0(G); success = 1; success = success && n_fq_poly_degree(Gevalp) == Gdeg; success = success && n_fq_poly_degree(Gevalm) == Gdeg; success = success && _n_fq_equal(Gevalp->coeffs + d*Gdeg, gammaevalp, d); success = success && _n_fq_equal(Gevalm->coeffs + d*Gdeg, gammaevalm, d); n_fq_poly_divrem_(Abarevalp, r, Aevalp, Gevalp, ctx, Sp->poly_stack); success = success && (r->length == 0); n_fq_poly_divrem_(Abarevalm, r, Aevalm, Gevalm, ctx, Sp->poly_stack); success = success && (r->length == 0); n_fq_poly_divrem_(Bbarevalp, r, Bevalp, Gevalp, ctx, Sp->poly_stack); success = success && (r->length == 0); n_fq_poly_divrem_(Bbarevalm, r, Bevalm, Gevalm, ctx, Sp->poly_stack); success = success && (r->length == 0); if (!success) { use_stab = 0; n_poly_one(modulus); alpha = (fq_nmod_ctx_mod(ctx).n - UWORD(1))/UWORD(2); goto choose_prime; } n_fq_poly_scalar_mul_n_fq(Abarevalp, Abarevalp, gammaevalp, ctx); n_fq_poly_scalar_mul_n_fq(Abarevalm, Abarevalm, gammaevalm, ctx); n_fq_poly_scalar_mul_n_fq(Bbarevalp, Bbarevalp, gammaevalp, ctx); n_fq_poly_scalar_mul_n_fq(Bbarevalm, Bbarevalm, gammaevalm, ctx); } else { n_fq_poly_gcd_(Gevalp, Aevalp, Bevalp, ctx, Sp->poly_stack); n_fq_poly_divrem_(Abarevalp, r, Aevalp, Gevalp, ctx, Sp->poly_stack); n_fq_poly_divrem_(Bbarevalp, r, Bevalp, Gevalp, ctx, Sp->poly_stack); n_fq_poly_gcd_(Gevalm, Aevalm, Bevalm, ctx, Sp->poly_stack); n_fq_poly_divrem_(Abarevalm, r, Aevalm, Gevalm, ctx, Sp->poly_stack); n_fq_poly_divrem_(Bbarevalm, r, Bevalm, Gevalm, ctx, Sp->poly_stack); gstab = astab = bstab = 0; } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); if (n_fq_poly_degree(Gevalp) == 0 || n_fq_poly_degree(Gevalm) == 0) { n_fq_bpoly_one(G, ctx); n_fq_bpoly_set(Abar, A, ctx); n_fq_bpoly_set(Bbar, B, ctx); goto successful_put_content; } if (n_fq_poly_degree(Gevalp) != n_fq_poly_degree(Gevalm)) { goto choose_prime; } if (n_poly_degree(modulus) > 0) { FLINT_ASSERT(G->length > 0); if (n_fq_poly_degree(Gevalp) > n_fq_bpoly_degree0(G)) { goto choose_prime; } else if (n_fq_poly_degree(Gevalp) < n_fq_bpoly_degree0(G)) { n_poly_one(modulus); } } n_fq_poly_scalar_mul_n_fq(Gevalp, Gevalp, gammaevalp, ctx); n_fq_poly_scalar_mul_n_fq(Gevalm, Gevalm, gammaevalm, ctx); if (n_poly_degree(modulus) > 0) { temp = n_poly_mod_evaluate_nmod(modulus, alpha, mod); FLINT_ASSERT(temp == n_poly_mod_evaluate_nmod(modulus, mod.n - alpha, mod)); temp = nmod_mul(temp, alpha, mod); temp = nmod_add(temp, temp, mod); temp = nmod_inv(temp, mod); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, mod); gstab = gstab || !n_fq_bpoly_interp_crt_2psm_poly(&ldegG, G, T, Gevalp, Gevalm, modulus, alphapow, ctx); n_fq_bpoly_interp_crt_2psm_poly(&ldegAbar, Abar, T, Abarevalp, Abarevalm, modulus, alphapow, ctx); n_fq_bpoly_interp_crt_2psm_poly(&ldegBbar, Bbar, T, Bbarevalp, Bbarevalm, modulus, alphapow, ctx); } else { n_fq_bpoly_interp_lift_2psm_poly(&ldegG, G, Gevalp, Gevalm, alpha, ctx); n_fq_bpoly_interp_lift_2psm_poly(&ldegAbar, Abar, Abarevalp, Abarevalm, alpha, ctx); n_fq_bpoly_interp_lift_2psm_poly(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, alpha, ctx); gstab = astab = bstab = 0; } temp = mod.n - nmod_mul(alpha, alpha, mod); n_poly_mod_shift_left_scalar_addmul(modulus, 2, temp, mod); if (n_poly_degree(modulus) < bound) goto choose_prime; FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if (deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar) { goto successful; } n_poly_one(modulus); goto choose_prime; successful: n_fq_bpoly_content_var0(r, G, ctx); n_fq_bpoly_divexact_poly_var1(G, r, ctx); n_fq_bpoly_divexact_poly_var1(Abar, G->coeffs + G->length - 1, ctx); n_fq_bpoly_divexact_poly_var1(Bbar, G->coeffs + G->length - 1, ctx); successful_put_content: n_fq_bpoly_mul_last(G, cG, ctx); n_fq_bpoly_mul_last(Abar, cAbar, ctx); n_fq_bpoly_mul_last(Bbar, cBbar, ctx); success = 1; cleanup: FLINT_ASSERT(n_fq_bpoly_is_canonical(G, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(Abar, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(Bbar, ctx)); flint_free(gammaevalp); flint_free(gammaevalm); n_poly_stack_give_back(Sp->poly_stack, 12); n_bpoly_stack_give_back(Sp->bpoly_stack, 1); return success; } /*****************************************************************************/ void n_fq_bpoly_interp_reduce_sm_poly( n_fq_poly_t E, const n_fq_bpoly_t A, n_fq_poly_t alphapow, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, Alen = A->length; const n_fq_poly_struct * Ac = A->coeffs; mp_limb_t * Ec; n_poly_fit_length(E, d*Alen); Ec = E->coeffs; for (i = 0; i < Alen; i++) n_fq_poly_eval_pow(Ec + d*i, Ac + i, alphapow, ctx); E->length = Alen; _n_fq_poly_normalise(E, d); } void n_fq_bpoly_interp_lift_sm_poly( n_fq_bpoly_t T, const n_fq_poly_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; const mp_limb_t * Acoeffs = A->coeffs; n_poly_struct * Tcoeffs; slong Alen = A->length; n_fq_bpoly_fit_length(T, Alen); Tcoeffs = T->coeffs; for (i = 0; i < Alen; i++) { n_fq_poly_set_n_fq(Tcoeffs + i, Acoeffs + d*i, ctx); } FLINT_ASSERT(i < 1 || !n_fq_poly_is_zero(Tcoeffs + i - 1)); T->length = i; } int n_fq_bpoly_interp_crt_sm_poly( slong * deg1, n_fq_bpoly_t F, n_fq_bpoly_t T, n_fq_poly_t A, const n_fq_poly_t modulus, n_fq_poly_t alphapow, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); int changed = 0; slong i, lastlength = 0; slong Alen = A->length; slong Flen = F->length; n_fq_poly_struct * Tcoeffs, * Fcoeffs; mp_limb_t * Acoeffs; mp_limb_t * u, * v; FLINT_ASSERT(n_fq_bpoly_is_canonical(F, ctx)); FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); u = FLINT_ARRAY_ALLOC(d, mp_limb_t); v = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_fq_bpoly_fit_length(T, FLINT_MAX(Alen, Flen)); Tcoeffs = T->coeffs; Acoeffs = A->coeffs; Fcoeffs = F->coeffs; for (i = 0; i < Flen; i++) { /* F term ok, A term ok/missing */ n_fq_poly_eval_pow(u, Fcoeffs + i, alphapow, ctx); if (i < Alen) n_fq_sub(v, Acoeffs + d*i, u, ctx); else _n_fq_neg(v, u, d, ctx->mod); if (!_n_fq_is_zero(v, d)) { changed = 1; n_fq_poly_scalar_addmul_n_fq(Tcoeffs + i, Fcoeffs + i, modulus, v, ctx); } else { n_fq_poly_set(Tcoeffs + i, Fcoeffs + i, ctx); } lastlength = FLINT_MAX(lastlength, Tcoeffs[i].length); } for ( ; i < Alen; i++) { /* F term missing, A term ok */ if (!_n_fq_is_zero(Acoeffs + d*i, d)) { changed = 1; n_fq_poly_scalar_mul_n_fq(Tcoeffs + i, modulus, Acoeffs + d*i, ctx); } else { n_fq_poly_zero(Tcoeffs + i); } lastlength = FLINT_MAX(lastlength, Tcoeffs[i].length); } flint_free(u); flint_free(v); FLINT_ASSERT(i < 1 || !n_fq_poly_is_zero(Tcoeffs + i - 1)); T->length = i; if (changed) n_bpoly_swap(T, F); FLINT_ASSERT(n_fq_bpoly_is_canonical(F, ctx)); *deg1 = lastlength - 1; return changed; } int n_fq_bpoly_gcd_brown_smprime( n_fq_bpoly_t G, n_fq_bpoly_t Abar, n_fq_bpoly_t Bbar, n_fq_bpoly_t A, n_fq_bpoly_t B, const fq_nmod_ctx_t ctx, n_poly_bpoly_stack_t Sp) { slong d = fq_nmod_ctx_degree(ctx); int success; slong bound; fq_nmod_t alpha; mp_limb_t * temp, * gammaeval; n_poly_struct * Aeval, * Beval, * Geval, * Abareval, * Bbareval; n_bpoly_struct * T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma; n_poly_struct * modulus, * alphapow, * r; int gstab, astab, bstab, use_stab; #if FLINT_WANT_ASSERT n_fq_bpoly_t Asave, Bsave; const slong Sp_size_poly = n_poly_stack_size(Sp->poly_stack); const slong Sp_size_bpoly = n_bpoly_stack_size(Sp->bpoly_stack); n_fq_bpoly_init(Asave); n_fq_bpoly_init(Bsave); n_fq_bpoly_set(Asave, A, ctx); n_fq_bpoly_set(Bsave, B, ctx); #endif FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx)); FLINT_ASSERT(n_fq_bpoly_is_canonical(B, ctx)); n_poly_stack_fit_request(Sp->poly_stack, 7); cA = n_poly_stack_take_top(Sp->poly_stack); cB = n_poly_stack_take_top(Sp->poly_stack); cG = n_poly_stack_take_top(Sp->poly_stack); cAbar = n_poly_stack_take_top(Sp->poly_stack); cBbar = n_poly_stack_take_top(Sp->poly_stack); gamma = n_poly_stack_take_top(Sp->poly_stack); r = n_poly_stack_take_top(Sp->poly_stack); n_fq_bpoly_content_var0(cA, A, ctx); n_fq_bpoly_content_var0(cB, B, ctx); n_fq_bpoly_divexact_poly_var1(A, cA, ctx); n_fq_bpoly_divexact_poly_var1(B, cB, ctx); n_fq_poly_gcd(cG, cA, cB, ctx); n_fq_poly_divrem(cAbar, r, cA, cG, ctx); n_fq_poly_divrem(cBbar, r, cB, cG, ctx); n_fq_poly_gcd(gamma, A->coeffs + A->length - 1, B->coeffs + B->length - 1, ctx); if (n_fq_bpoly_gcd_brown_smprime2p(G, Abar, Bbar, A, B, ctx, Sp, cA, cB, cG, cAbar, cBbar, gamma, r)) { #if FLINT_WANT_ASSERT { n_fq_poly_struct * Glead = G->coeffs + G->length - 1; n_fq_bpoly_t P; FLINT_ASSERT(_n_fq_is_one(Glead->coeffs + d*(Glead->length - 1), d)); n_fq_bpoly_init(P); n_fq_bpoly_mul(P, G, Abar, ctx); FLINT_ASSERT(n_fq_bpoly_equal(P, Asave, ctx)); n_fq_bpoly_mul(P, G, Bbar, ctx); FLINT_ASSERT(n_fq_bpoly_equal(P, Bsave, ctx)); n_fq_bpoly_clear(P); } n_fq_bpoly_clear(Asave); n_fq_bpoly_clear(Bsave); #endif n_poly_stack_give_back(Sp->poly_stack, 7); FLINT_ASSERT(Sp_size_poly == n_poly_stack_size(Sp->poly_stack)); FLINT_ASSERT(Sp_size_bpoly == n_bpoly_stack_size(Sp->bpoly_stack)); return 1; } FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); fq_nmod_init(alpha, ctx); temp = FLINT_ARRAY_ALLOC(d, mp_limb_t); gammaeval = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_poly_stack_fit_request(Sp->poly_stack, 7); Aeval = n_poly_stack_take_top(Sp->poly_stack); Beval = n_poly_stack_take_top(Sp->poly_stack); Geval = n_poly_stack_take_top(Sp->poly_stack); Abareval = n_poly_stack_take_top(Sp->poly_stack); Bbareval = n_poly_stack_take_top(Sp->poly_stack); alphapow = n_poly_stack_take_top(Sp->poly_stack); modulus = n_poly_stack_take_top(Sp->poly_stack); n_bpoly_stack_fit_request(Sp->bpoly_stack, 1); T = n_bpoly_stack_take_top(Sp->bpoly_stack); ldegA = n_fq_bpoly_degree1(A); ldegB = n_fq_bpoly_degree1(B); deggamma = n_fq_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); n_poly_fit_length(alphapow, d*FLINT_MAX(WORD(3), bound + 1)); n_fq_poly_one(modulus, ctx); use_stab = 1; gstab = bstab = astab = 0; fq_nmod_zero(alpha, ctx); choose_prime: if (fq_nmod_next(alpha, ctx) == 0) { success = 0; goto cleanup; } alphapow->length = 2; _n_fq_one(alphapow->coeffs + d*0, d); n_fq_set_fq_nmod(alphapow->coeffs + d*1, alpha, ctx); n_fq_poly_eval_pow(gammaeval, gamma, alphapow, ctx); if (_n_fq_is_zero(gammaeval, d)) goto choose_prime; n_fq_bpoly_interp_reduce_sm_poly(Aeval, A, alphapow, ctx); n_fq_bpoly_interp_reduce_sm_poly(Beval, B, alphapow, ctx); FLINT_ASSERT(Aeval->length > 0); FLINT_ASSERT(Beval->length > 0); if (use_stab && gstab) { slong Gdeg; n_fq_bpoly_interp_reduce_sm_poly(Geval, G, alphapow, ctx); Gdeg = n_fq_bpoly_degree0(G); success = 1; success = success && n_fq_poly_degree(Geval) == Gdeg; success = success && _n_fq_equal(Geval->coeffs + d*Gdeg, gammaeval, d); n_fq_poly_divrem(Abareval, r, Aeval, Geval, ctx); success = success && n_fq_poly_is_zero(r); n_fq_poly_divrem(Bbareval, r, Beval, Geval, ctx); success = success && n_fq_poly_is_zero(r); if (!success) { use_stab = 0; n_fq_poly_one(modulus, ctx); fq_nmod_zero(alpha, ctx); goto choose_prime; } n_fq_poly_scalar_mul_n_fq(Abareval, Abareval, gammaeval, ctx); n_fq_poly_scalar_mul_n_fq(Bbareval, Bbareval, gammaeval, ctx); } else { n_fq_poly_gcd(Geval, Aeval, Beval, ctx); n_fq_poly_divrem(Abareval, r, Aeval, Geval, ctx); n_fq_poly_divrem(Bbareval, r, Beval, Geval, ctx); gstab = astab = bstab = 0; } FLINT_ASSERT(Geval->length > 0); FLINT_ASSERT(Abareval->length > 0); FLINT_ASSERT(Bbareval->length > 0); if (n_fq_poly_degree(Geval) == 0) { n_fq_bpoly_one(G, ctx); n_fq_bpoly_set(Abar, A, ctx); n_fq_bpoly_set(Bbar, B, ctx); goto successful_put_content; } if (n_fq_poly_degree(modulus) > 0) { FLINT_ASSERT(G->length > 0); if (n_fq_poly_degree(Geval) > n_fq_bpoly_degree0(G)) goto choose_prime; if (n_fq_poly_degree(Geval) < n_fq_bpoly_degree0(G)) n_fq_poly_one(modulus, ctx); } n_fq_poly_scalar_mul_n_fq(Geval, Geval, gammaeval, ctx); if (n_fq_poly_degree(modulus) > 0) { n_fq_poly_eval_pow(temp, modulus, alphapow, ctx); n_fq_inv(temp, temp, ctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, temp, ctx); gstab = gstab || !n_fq_bpoly_interp_crt_sm_poly(&ldegG, G, T, Geval, modulus, alphapow, ctx); n_fq_bpoly_interp_crt_sm_poly(&ldegAbar, Abar, T, Abareval, modulus, alphapow, ctx); n_fq_bpoly_interp_crt_sm_poly(&ldegBbar, Bbar, T, Bbareval, modulus, alphapow, ctx); } else { n_fq_bpoly_interp_lift_sm_poly(G, Geval, ctx); n_fq_bpoly_interp_lift_sm_poly(Abar, Abareval, ctx); n_fq_bpoly_interp_lift_sm_poly(Bbar, Bbareval, ctx); ldegG = ldegAbar = ldegBbar = 0; gstab = astab = bstab = 0; } n_fq_set_fq_nmod(temp, alpha, ctx); n_fq_poly_shift_left_scalar_submul(modulus, 1, temp, ctx); if (n_fq_poly_degree(modulus) < bound) goto choose_prime; FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if (deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar) { goto successful; } n_fq_poly_one(modulus, ctx); goto choose_prime; successful: n_fq_bpoly_content_var0(modulus, G, ctx); n_fq_bpoly_divexact_poly_var1(G, modulus, ctx); n_fq_bpoly_divexact_poly_var1(Abar, G->coeffs + G->length - 1, ctx); n_fq_bpoly_divexact_poly_var1(Bbar, G->coeffs + G->length - 1, ctx); successful_put_content: n_fq_bpoly_mul_last(G, cG, ctx); n_fq_bpoly_mul_last(Abar, cAbar, ctx); n_fq_bpoly_mul_last(Bbar, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { n_fq_poly_struct * Glead = G->coeffs + G->length - 1; n_fq_bpoly_t P; FLINT_ASSERT(_n_fq_is_one(Glead->coeffs + d*(Glead->length - 1), d)); n_fq_bpoly_init(P); n_fq_bpoly_mul(P, G, Abar, ctx); FLINT_ASSERT(n_fq_bpoly_equal(P, Asave, ctx)); n_fq_bpoly_mul(P, G, Bbar, ctx); FLINT_ASSERT(n_fq_bpoly_equal(P, Bsave, ctx)); n_fq_bpoly_clear(P); } n_fq_bpoly_clear(Asave); n_fq_bpoly_clear(Bsave); #endif fq_nmod_clear(alpha, ctx); flint_free(temp); flint_free(gammaeval); n_poly_stack_give_back(Sp->poly_stack, 14); n_bpoly_stack_give_back(Sp->bpoly_stack, 1); FLINT_ASSERT(Sp_size_poly == n_poly_stack_size(Sp->poly_stack)); FLINT_ASSERT(Sp_size_bpoly == n_bpoly_stack_size(Sp->bpoly_stack)); return success; } flint-3.1.3/src/n_poly/n_fq_bpoly_taylor_shift.c000066400000000000000000000065231461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" static void _n_fq_poly_taylor_shift_horner_n_fq( mp_limb_t * poly, const mp_limb_t * c, slong n, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j; mp_limb_t * p = FLINT_ARRAY_ALLOC(d, mp_limb_t); for (i = n - 2; i >= 0; i--) { for (j = i; j < n - 1; j++) { n_fq_mul(p, poly + d*(j + 1), c, ctx); n_fq_add(poly + d*j, poly + d*j, p, ctx); } } flint_free(p); } void n_fq_bpoly_taylor_shift_gen1_fq_nmod( n_bpoly_t A, const n_bpoly_t B, const fq_nmod_t c_, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; mp_limb_t * c = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_fq_set_fq_nmod(c, c_, ctx); n_fq_bpoly_set(A, B, ctx); for (i = A->length - 1; i >= 0; i--) _n_fq_poly_taylor_shift_horner_n_fq(A->coeffs[i].coeffs, c, A->coeffs[i].length, ctx); flint_free(c); } void n_fq_bpoly_taylor_shift_gen0_fq_nmod( n_bpoly_t A, const fq_nmod_t alpha, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong n, i, j; mp_limb_t * c; n_poly_t t; if (fq_nmod_is_zero(alpha, ctx)) return; c = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_fq_set_fq_nmod(c, alpha, ctx); n_poly_init(t); n = A->length; for (i = n - 2; i >= 0; i--) { for (j = i; j < n - 1; j++) { n_fq_poly_scalar_mul_n_fq(t, A->coeffs + j + 1, c, ctx); n_fq_poly_add(A->coeffs + j, A->coeffs + j, t, ctx); } } n_poly_clear(t); flint_free(c); } void n_fq_bpoly_taylor_shift_gen0_n_fq( n_fq_bpoly_t A, const mp_limb_t * alpha, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i, j, n = A->length; mp_limb_t * tmp, * c, * alphainv; TMP_INIT; if (_n_fq_is_zero(alpha, d)) return; TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*N_FQ_MUL_INV_ITCH*sizeof(mp_limb_t)); c = TMP_ALLOC(d*sizeof(mp_limb_t)); alphainv = TMP_ALLOC(d*sizeof(mp_limb_t)); _n_fq_one(c, d); for (i = 1; i < n; i++) { _n_fq_mul(c, c, alpha, ctx, tmp); if (!_n_fq_is_one(c, d)) { mp_limb_t * Aic = A->coeffs[i].coeffs; for (j = 0; j < A->coeffs[i].length; j++) _n_fq_mul(Aic + d*j, Aic + d*j, c, ctx, tmp); } } for (i = n - 2; i >= 0; i--) { for (j = i; j < n - 1; j++) { n_fq_poly_add(A->coeffs + j, A->coeffs + j, A->coeffs + j + 1, ctx); } } _n_fq_inv(alphainv, alpha, ctx, tmp); _n_fq_one(c, d); for (i = 1; i < n; i++) { _n_fq_mul(c, c, alphainv, ctx, tmp); if (!_n_fq_is_one(c, d)) { mp_limb_t * Aic = A->coeffs[i].coeffs; for (j = 0; j < A->coeffs[i].length; j++) _n_fq_mul(Aic + d*j, Aic + d*j, c, ctx, tmp); } } TMP_END; return; } flint-3.1.3/src/n_poly/n_fq_poly.c000066400000000000000000000324231461254215100170600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" int n_fq_poly_is_canonical(const n_poly_t A, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; if (A->length < 0) return 0; if (d*A->length > A->alloc) return 0; for (i = 0; i < A->length; i++) { if (!n_fq_is_canonical(A->coeffs + d*i, ctx)) return 0; if (i + 1 == A->length && _n_fq_is_zero(A->coeffs + d*i, d)) return 0; } return 1; } void n_fq_poly_init2( n_fq_poly_t A, slong alloc, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (alloc > 0) { A->alloc = d*alloc; A->coeffs = flint_malloc(A->alloc*sizeof(mp_limb_t)); } else { A->alloc = 0; A->coeffs = NULL; } A->length = 0; } void n_fq_poly_randtest( n_poly_t A, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; if (len < 1) { A->length = 0; return; } n_poly_fit_length(A, d*len); for (i = 0; i < d*len; i++) A->coeffs[i] = n_randint(state, ctx->mod.n); A->length = len; _n_fq_poly_normalise(A, d); } void _n_fq_poly_one(n_poly_t A, slong d) { n_poly_fit_length(A, d); A->length = 1; _n_fq_one(A->coeffs + d*0, d); } int n_fq_poly_is_one(n_poly_t A, const fq_nmod_ctx_t ctx) { return A->length == 1 && _n_fq_is_one(A->coeffs, fq_nmod_ctx_degree(ctx)); } void n_fq_poly_get_coeff_n_fq( mp_limb_t * c, const n_fq_poly_t A, slong e, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (e >= A->length) _n_fq_zero(c, d); else _n_fq_set(c, A->coeffs + d*e, d); } void n_fq_poly_get_coeff_fq_nmod( fq_nmod_t c, const n_fq_poly_t A, slong e, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (e >= A->length) fq_nmod_zero(c, ctx); else n_fq_get_fq_nmod(c, A->coeffs + d*e, ctx); } void n_fq_poly_set_coeff_n_fq( n_fq_poly_t A, slong j, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(n_fq_is_canonical(c, ctx)); FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); n_poly_fit_length(A, d*(j + 1)); if (j + 1 <= A->length) { _n_fq_set(A->coeffs + d*j, c, d); if (j + 1 == A->length) _n_fq_poly_normalise(A, d); } else if (!_n_fq_is_zero(c, d)) /* extend polynomial */ { flint_mpn_zero(A->coeffs + d*A->length, d*(j - A->length)); _n_fq_set(A->coeffs + d*j, c, d); A->length = j + 1; } FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); } void n_fq_poly_set_coeff_fq_nmod( n_poly_t A, slong j, const fq_nmod_t c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); n_poly_fit_length(A, d*(j + 1)); if (j + 1 <= A->length) { n_fq_set_fq_nmod(A->coeffs + d*j, c, ctx); if (j + 1 == A->length) _n_fq_poly_normalise(A, d); } else if (!fq_nmod_is_zero(c, ctx)) { flint_mpn_zero(A->coeffs + d*A->length, d*(j - A->length)); n_fq_set_fq_nmod(A->coeffs + d*j, c, ctx); A->length = j + 1; } FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); } void n_fq_poly_scalar_mul_ui( n_poly_t A, const n_poly_t B, ulong c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (c >= ctx->mod.n) { NMOD_RED(c, c, ctx->mod); } if (B->length < 1 || c == 0) { n_poly_zero(A); return; } n_poly_fit_length(A, d*B->length); _nmod_vec_scalar_mul_nmod(A->coeffs, B->coeffs, d*B->length, c, ctx->mod); A->length = B->length; _n_fq_poly_normalise(A, d); } int n_fq_poly_equal( const n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; if (A->length != B->length) return 0; for (i = 0; i < d*B->length; i++) if (A->coeffs[i] != B->coeffs[i]) return 0; return 1; } void n_fq_poly_set( n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (A == B) return; n_poly_fit_length(A, d*B->length); _nmod_vec_set(A->coeffs, B->coeffs, d*B->length); A->length = B->length; } void n_fq_poly_set_n_fq( n_poly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); n_poly_fit_length(A, d); _nmod_vec_set(A->coeffs, c, d); A->length = 1; _n_fq_poly_normalise(A, d); } void n_fq_poly_set_fq_nmod( n_poly_t A, const fq_nmod_t c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); n_poly_fit_length(A, d); n_fq_set_fq_nmod(A->coeffs, c, ctx); A->length = 1; _n_fq_poly_normalise(A, d); } void n_fq_poly_shift_right( n_poly_t A, const n_poly_t B, slong n, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (n < 1) { n_fq_poly_set(A, B, ctx); return; } else if (B->length <= n) { n_poly_zero(A); return; } else { n_poly_fit_length(A, d*(B->length - n)); flint_mpn_copyi(A->coeffs, B->coeffs + d*n, d*(B->length - n)); A->length = B->length - n; } } void n_fq_poly_shift_left( n_poly_t A, const n_poly_t B, slong n, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (n < 1) { n_fq_poly_set(A, B, ctx); } else if (n_fq_poly_is_zero(B)) { n_fq_poly_zero(A); } else { n_poly_fit_length(A, d*(B->length + n)); flint_mpn_copyd(A->coeffs + d*n, B->coeffs, d*B->length); flint_mpn_zero(A->coeffs, d*n); A->length = B->length + n; } } void n_fq_poly_truncate(n_poly_t A, slong len, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (A->length > len) { A->length = len; _n_fq_poly_normalise(A, d); } } void n_fq_poly_evaluate_fq_nmod( fq_nmod_t e, const n_poly_t A, const fq_nmod_t c, const fq_nmod_ctx_t ctx) { fq_nmod_poly_t AA; fq_nmod_poly_init(AA, ctx); n_fq_poly_get_fq_nmod_poly(AA, A, ctx); fq_nmod_poly_evaluate_fq_nmod(e, AA, c, ctx); fq_nmod_poly_clear(AA, ctx); } void n_fq_poly_evaluate_n_fq( mp_limb_t * e, const n_poly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; mp_limb_t * u = FLINT_ARRAY_ALLOC(d, mp_limb_t); mp_limb_t * t = FLINT_ARRAY_ALLOC(d, mp_limb_t); _n_fq_zero(t, d); for (i = 0; i < A->length; i++) { n_fq_pow_ui(u, c, i, ctx); n_fq_mul(u, u, A->coeffs + d*i, ctx); n_fq_add(t, t, u, ctx); } _n_fq_set(e, t, d); flint_free(u); flint_free(t); } void n_fq_poly_eval_pow( mp_limb_t * ev, const n_fq_poly_t P, n_fq_poly_t alphapow, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); const mp_limb_t * Pcoeffs = P->coeffs; slong i, Plen = P->length; mp_limb_t * alpha_powers = alphapow->coeffs; mp_limb_t * t; slong k; TMP_INIT; TMP_START; t = TMP_ALLOC(d*FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_LAZY_ITCH)*sizeof(mp_limb_t)); if (Plen > alphapow->length) { slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); n_poly_fit_length(alphapow, d*Plen); alphapow->length = Plen; alpha_powers = alphapow->coeffs; for (k = oldlength; k < Plen; k++) { _n_fq_mul(alpha_powers + d*k, alpha_powers + d*(k - 1), alpha_powers + d*1, ctx, t); } } _nmod_vec_zero(t, 6*d); switch (_n_fq_dot_lazy_size(Plen, ctx)) { #define lazycase(n) \ case n: \ for (i = 0; i < Plen; i++) \ _n_fq_madd2_lazy##n(t, Pcoeffs + d*i, alpha_powers + d*i, d); \ _n_fq_reduce2_lazy##n(t, d, ctx->mod); \ break; lazycase(1) lazycase(2) lazycase(3) default: for (i = 0; i < Plen; i++) _n_fq_madd2(t, Pcoeffs + d*i, alpha_powers + d*i, ctx, t + 2*d); break; } _n_fq_reduce2(ev, t, ctx, t + 2*d); TMP_END; } void n_fq_poly_set_fq_nmod_poly( n_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx) { slong i; slong d = fq_nmod_ctx_degree(ctx); n_poly_fit_length(A, d*B->length); for (i = 0; i < B->length; i++) n_fq_set_fq_nmod(A->coeffs + d*i, B->coeffs + i, ctx); A->length = B->length; } void n_fq_poly_get_fq_nmod_poly( fq_nmod_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; FLINT_ASSERT(B->alloc >= d*B->length); fq_nmod_poly_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) n_fq_get_fq_nmod(A->coeffs + i, B->coeffs + d*i, ctx); A->length = B->length; } void n_fq_poly_scalar_mul_n_fq( n_poly_t A, const n_poly_t B, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong i, d = fq_nmod_ctx_degree(ctx); n_poly_fit_length(A, d*B->length); for (i = 0; i < B->length; i++) n_fq_mul(A->coeffs + d*i, B->coeffs + d*i, c, ctx); A->length = B->length; _n_fq_poly_normalise(A, d); } void n_fq_poly_make_monic( n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong itch = FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_INV_ITCH); mp_limb_t * tmp, * inv; slong i, Blen = B->length; if (Blen < 1) { n_poly_zero(A); return; } n_poly_fit_length(A, d*Blen); tmp = FLINT_ARRAY_ALLOC(d*(itch + 1), mp_limb_t); inv = tmp + d*itch; _n_fq_inv(inv, B->coeffs + d*(Blen - 1), ctx, tmp); for (i = 0; i < Blen - 1; i++) _n_fq_mul(A->coeffs + d*i, B->coeffs + d*i, inv, ctx, tmp); _n_fq_one(A->coeffs + d*(Blen - 1), d); A->length = Blen; flint_free(tmp); } void n_fq_poly_scalar_addmul_n_fq( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, const mp_limb_t * s, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; mp_limb_t * Acoeffs; mp_limb_t * Bcoeffs; mp_limb_t * Ccoeffs; slong Blen = B->length; slong Clen = C->length; mp_limb_t * t; TMP_INIT; n_poly_fit_length(A, d*FLINT_MAX(Blen, Clen)); Bcoeffs = B->coeffs; Ccoeffs = C->coeffs; TMP_START; t = TMP_ALLOC(d*N_FQ_MUL_ITCH*sizeof(mp_limb_t)); if (Blen > Clen) { n_poly_fit_length(A, d*Blen); Acoeffs = A->coeffs; for (i = 0; i < Clen; i++) _n_fq_addmul(Acoeffs + d*i, Bcoeffs + d*i, Ccoeffs + d*i, s, ctx, t); if (A != B) _nmod_vec_set(Acoeffs + d*Clen, Bcoeffs + d*Clen, d*(Blen - Clen)); A->length = Blen; } else if (Blen < Clen) { n_poly_fit_length(A, d*Clen); Acoeffs = A->coeffs; for (i = 0; i < Blen; i++) _n_fq_addmul(Acoeffs + d*i, Bcoeffs + d*i, Ccoeffs + d*i, s, ctx, t); for ( ; i < Clen; i++) _n_fq_mul(Acoeffs + d*i, Ccoeffs + d*i, s, ctx, t); A->length = Clen; } else { n_poly_fit_length(A, d*Blen); Acoeffs = A->coeffs; for (i = 0; i < Blen; i++) _n_fq_addmul(Acoeffs + d*i, Bcoeffs + d*i, Ccoeffs + d*i, s, ctx, t); A->length = Blen; _n_fq_poly_normalise(A, d); } TMP_END; } /* multiply A by (x^k - c) */ void n_fq_poly_shift_left_scalar_submul( n_poly_t A, slong k, const mp_limb_t * c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); mp_limb_t * Acoeffs; slong i; slong Alen = A->length; mp_limb_t * u = FLINT_ARRAY_ALLOC(d, mp_limb_t); n_poly_fit_length(A, d*(Alen + k)); Acoeffs = A->coeffs; flint_mpn_copyd(Acoeffs + d*k, Acoeffs, d*Alen); flint_mpn_zero(Acoeffs, d*k); for (i = 0; i < A->length; i++) { n_fq_mul(u, c, Acoeffs + d*(i + k), ctx); _n_fq_sub(Acoeffs + d*i, Acoeffs + d*i, u, d, fq_nmod_ctx_mod(ctx)); } A->length = Alen + k; flint_free(u); } ulong n_fq_poly_remove( n_poly_t f, const n_poly_t g, const fq_nmod_ctx_t ctx) { n_poly_t q, r; ulong i = 0; n_poly_init(q); n_poly_init(r); while (1) { if (f->length < g->length) break; n_fq_poly_divrem(q, r, f, g, ctx); if (r->length == 0) n_poly_swap(q, f); else break; i++; } n_poly_clear(q); n_poly_clear(r); return i; } flint-3.1.3/src/n_poly/n_fq_poly_add.c000066400000000000000000000026411461254215100176670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" void n_fq_poly_add( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong Blen = B->length; slong Clen = C->length; if (Blen > Clen) { n_poly_fit_length(A, d*Blen); _nmod_vec_add(A->coeffs, B->coeffs, C->coeffs, d*Clen, ctx->mod); if (A != B) _nmod_vec_set(A->coeffs + d*Clen, B->coeffs + d*Clen, d*(Blen - Clen)); A->length = Blen; } else if (Blen < Clen) { n_poly_fit_length(A, d*Clen); _nmod_vec_add(A->coeffs, B->coeffs, C->coeffs, d*Blen, ctx->mod); if (A != C) _nmod_vec_set(A->coeffs + d*Blen, C->coeffs + d*Blen, d*(Clen - Blen)); A->length = Clen; } else { n_poly_fit_length(A, d*Blen); _nmod_vec_add(A->coeffs, B->coeffs, C->coeffs, d*Clen, ctx->mod); A->length = Clen; _n_fq_poly_normalise(A, d); } FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); } flint-3.1.3/src/n_poly/n_fq_poly_add_si.c000066400000000000000000000014521461254215100203610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" void n_fq_poly_add_si( n_fq_poly_t A, const n_fq_poly_t B, slong c, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (A != B) n_fq_poly_set(A, B, ctx); if (A->length < 1) { n_poly_fit_length(A, d); A->length = 1; } n_fq_add_si(A->coeffs + d*0, A->coeffs + d*0, c, ctx); _n_fq_poly_normalise(A, d); } flint-3.1.3/src/n_poly/n_fq_poly_divrem.c000066400000000000000000000261601461254215100204270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #if FLINT_WANT_ASSERT # include "fq_nmod_poly.h" #endif #define N_FQ_POLY_DIVREM_BASECASE_ITCH \ FLINT_MAX(FLINT_MAX(4, N_FQ_MUL_ITCH), 2 + (N_FQ_REDUCE_ITCH)) void _n_fq_poly_rem_basecase_( mp_limb_t * Q, mp_limb_t * A, const mp_limb_t * AA, slong Alen, const mp_limb_t * B, slong Blen, const mp_limb_t * invB, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong i; slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); mp_limb_t * tmp = n_poly_stack_vec_init(St, d*(3 + N_FQ_POLY_DIVREM_BASECASE_ITCH)); mp_limb_t * u = tmp + d*N_FQ_POLY_DIVREM_BASECASE_ITCH; mp_limb_t * q0 = u + d; mp_limb_t * q1 = q0 + d; if (A != AA) _nmod_vec_set(A, AA, d*Alen); while (Alen - Blen > 3 && Blen > 1) { _n_fq_mul(q1, A + d*(Alen - 1), invB, ctx, tmp); _n_fq_mul(q0, q1, B + d*(Blen - 2), ctx, tmp); _n_fq_sub(q0, q0, A + d*(Alen - 2), d, mod); _n_fq_mul(q0, q0, invB, ctx, tmp); _nmod_vec_neg(q1, q1, d, ctx->mod); i = -1; _n_fq_mul(u, q0, B + d*(i + 1), ctx, tmp); _n_fq_add(A + d*(i + Alen - Blen), A + d*(i + Alen - Blen), u, d, mod); for (i = 0; i + 2 < Blen; i++) { _n_fq_mul2(tmp, q1, B + d*i, ctx); _n_fq_madd2(tmp, q0, B + d*(i + 1), ctx, tmp + 2*d); _n_fq_reduce2(u, tmp, ctx, tmp + 2*d); _n_fq_add(A + d*(i + Alen - Blen), A + d*(i + Alen - Blen), u, d, mod); } Alen -= 2; _nmod_vec_zero(A + d*Alen, 2*d); } while (Alen - Blen >= 0) { _n_fq_mul(q0, A + d*(Alen - 1), invB, ctx, tmp); for (i = 0; i + 1 < Blen; i++) { _n_fq_mul(u, q0, B + d*i, ctx, tmp); _n_fq_sub(A + d*(i + Alen - Blen), A + d*(i + Alen - Blen), u, d, mod); } Alen -= 1; _nmod_vec_zero(A + d*Alen, 1*d); } n_poly_stack_vec_clear(St); } void _n_fq_poly_divrem_basecase_( mp_limb_t * Q, mp_limb_t * A, const mp_limb_t * AA, slong Alen, const mp_limb_t * B, slong Blen, const mp_limb_t * invB, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong i; slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); mp_limb_t * tmp = n_poly_stack_vec_init(St, d*(1 + N_FQ_POLY_DIVREM_BASECASE_ITCH)); mp_limb_t * u = tmp + d*N_FQ_POLY_DIVREM_BASECASE_ITCH; if (A != AA) _nmod_vec_set(A, AA, d*Alen); while (Alen - Blen > 3 && Blen > 1) { mp_limb_t * q1 = Q + d*(Alen - Blen); mp_limb_t * q0 = Q + d*(Alen - Blen - 1); _n_fq_mul(q1, A + d*(Alen - 1), invB, ctx, tmp); _n_fq_mul(q0, q1, B + d*(Blen - 2), ctx, tmp); _n_fq_sub(q0, q0, A + d*(Alen - 2), d, mod); _n_fq_mul(q0, q0, invB, ctx, tmp); _nmod_vec_neg(q1, q1, d, ctx->mod); i = -1; _n_fq_mul(u, q0, B + d*(i + 1), ctx, tmp); _n_fq_add(A + d*(i + Alen - Blen), A + d*(i + Alen - Blen), u, d, mod); for (i = 0; i + 2 < Blen; i++) { _n_fq_mul2(tmp, q1, B + d*i, ctx); _n_fq_madd2(tmp, q0, B + d*(i + 1), ctx, tmp + 2*d); _n_fq_reduce2(u, tmp, ctx, tmp + 2*d); _n_fq_add(A + d*(i + Alen - Blen), A + d*(i + Alen - Blen), u, d, mod); } _nmod_vec_neg(q0, q0, 2*d, mod); /* q0 and q1 */ Alen -= 2; _nmod_vec_zero(A + d*Alen, 2*d); } while (Alen - Blen >= 0) { mp_limb_t * q0 = Q + d*(Alen - Blen); _n_fq_mul(q0, A + d*(Alen - 1), invB, ctx, tmp); for (i = 0; i + 1 < Blen; i++) { _n_fq_mul(u, q0, B + d*i, ctx, tmp); _n_fq_sub(A + d*(i + Alen - Blen), A + d*(i + Alen - Blen), u, d, mod); } Alen -= 1; _nmod_vec_zero(A + d*Alen, 1*d); } n_poly_stack_vec_clear(St); } void _n_fq_poly_divrem_divconquer_recursive_( mp_limb_t * Q, mp_limb_t * BQ, mp_limb_t * W, const mp_limb_t * A, const mp_limb_t * B, slong lenB, const mp_limb_t * invB, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); if (lenB <= N_FQ_POLY_DIVREM_DIVCONQUER_CUTOFF) { _nmod_vec_zero(BQ, d*(lenB - 1)); _nmod_vec_set(BQ + d*(lenB - 1), A + d*(lenB - 1), d*lenB); _n_fq_poly_divrem_basecase_(Q, BQ, BQ, 2*lenB - 1, B, lenB, invB, ctx, St); _nmod_vec_neg(BQ, BQ, d*(lenB - 1), ctx->mod); _nmod_vec_set(BQ + d*(lenB - 1), A + d*(lenB - 1), d*lenB); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; mp_limb_t * W1 = W; mp_limb_t * W2 = W + d*lenB; const mp_limb_t * p1 = A + d*2*n2; const mp_limb_t * p2; const mp_limb_t * d1 = B + d*n2; const mp_limb_t * d2 = B; const mp_limb_t * d3 = B + d*n1; const mp_limb_t * d4 = B; mp_limb_t * q1 = Q + d*n2; mp_limb_t * q2 = Q; mp_limb_t * dq1 = BQ + d*n2; mp_limb_t * d1q1 = BQ + d*2*n2; mp_limb_t * d2q1, * d3q2, * d4q2, * t; _n_fq_poly_divrem_divconquer_recursive_(q1, d1q1, W1, p1, d1, n1, invB, ctx, St); d2q1 = W1; _n_fq_poly_mul_(d2q1, q1, n1, d2, n2, ctx, St); _nmod_vec_swap(dq1, d2q1, d*n2); _nmod_vec_add(dq1 + d*n2, dq1 + d*n2, d2q1 + d*n2, d*(n1 - 1), ctx->mod); t = BQ; _nmod_vec_sub(t, A + d*n2 + d*(n1 - 1), dq1 + d*(n1 - 1), d*n2, ctx->mod); p2 = t - d*(n2 - 1); d3q2 = W1; _n_fq_poly_divrem_divconquer_recursive_(q2, d3q2, W2, p2, d3, n2, invB, ctx, St); d4q2 = W2; _n_fq_poly_mul_(d4q2, d4, n1, q2, n2, ctx, St); _nmod_vec_swap(BQ, d4q2, d*n2); _nmod_vec_add(BQ + d*n2, BQ + d*n2, d4q2 + d*n2, d*(n1 - 1), ctx->mod); _nmod_vec_add(BQ + d*n1, BQ + d*n1, d3q2, d*(2*n2 - 1), ctx->mod); } } static void __n_fq_poly_divrem_divconquer_( mp_limb_t * Q, mp_limb_t * R, mp_limb_t * A, slong lenA, mp_limb_t * B, slong lenB, mp_limb_t * invB, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); FLINT_ASSERT(Q != A && Q != B); FLINT_ASSERT(R != A && R != B); FLINT_ASSERT(lenB > 0); FLINT_ASSERT(lenA <= 2*lenB - 1); if (lenA < 2*lenB - 1) { const slong n1 = lenA - lenB + 1; const slong n2 = lenB - n1; const mp_limb_t * p1 = A + d*n2; const mp_limb_t * d1 = B + d*n2; const mp_limb_t * d2 = B; mp_limb_t * W = n_poly_stack_vec_init(St, d*((2*n1 - 1) + lenB - 1)); mp_limb_t * d1q1 = R + d*n2; mp_limb_t * d2q1 = W + d*(2*n1 - 1); _n_fq_poly_divrem_divconquer_recursive_(Q, d1q1, W, p1, d1, n1, invB, ctx, St); _n_fq_poly_mul_(d2q1, Q, n1, d2, n2, ctx, St); _nmod_vec_swap(R, d2q1, d*n2); _nmod_vec_add(R + d*n2, R + d*n2, d2q1 + d*n2, d*(n1 - 1), ctx->mod); _nmod_vec_sub(R, A, R, d*lenA, ctx->mod); n_poly_stack_vec_clear(St); } else { mp_limb_t * W = n_poly_stack_vec_init(St, d*lenA); _n_fq_poly_divrem_divconquer_recursive_(Q, R, W, A, B, lenB, invB, ctx, St); _nmod_vec_sub(R, A, R, d*(lenB - 1), ctx->mod); n_poly_stack_vec_clear(St); } } void _n_fq_poly_divrem_divconquer_( mp_limb_t * Q, mp_limb_t * R, mp_limb_t * A, slong lenA, mp_limb_t * B, slong lenB, mp_limb_t * invB, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); if (lenA <= 2*lenB - 1) { __n_fq_poly_divrem_divconquer_(Q, R, A, lenA, B, lenB, invB, ctx, St); } else { slong shift, n = 2*lenB - 1; mp_limb_t * QB, * W; _nmod_vec_set(R, A, d*lenA); W = n_poly_stack_vec_init(St, d*2*n); QB = W + d*n; while (lenA >= n) { shift = lenA - n; _n_fq_poly_divrem_divconquer_recursive_(Q + d*shift, QB, W, R + d*shift, B, lenB, invB, ctx, St); _nmod_vec_sub(R + d*shift, R + d*shift, QB, d*n, ctx->mod); lenA -= lenB; } if (lenA >= lenB) { __n_fq_poly_divrem_divconquer_(Q, W, R, lenA, B, lenB, invB, ctx, St); _nmod_vec_swap(W, R, d*lenA); } n_poly_stack_vec_clear(St); } } void n_fq_poly_divrem_divconquer_( n_fq_poly_t Q, n_fq_poly_t R, const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); const slong lenA = A->length; const slong lenB = B->length; const slong lenQ = lenA - lenB + 1; mp_limb_t * tmp, * invB; n_poly_t Qt, Rt; mp_limb_t * q, * r; #if FLINT_WANT_ASSERT fq_nmod_poly_t QQ, RR, AA, BB; #endif if (lenQ < 1) { n_fq_poly_set(R, A, ctx); n_poly_zero(Q); return; } #if FLINT_WANT_ASSERT fq_nmod_poly_init(QQ, ctx); fq_nmod_poly_init(RR, ctx); fq_nmod_poly_init(AA, ctx); fq_nmod_poly_init(BB, ctx); n_fq_poly_get_fq_nmod_poly(AA, A, ctx); n_fq_poly_get_fq_nmod_poly(BB, B, ctx); fq_nmod_poly_divrem(QQ, RR, AA, BB, ctx); #endif tmp = n_poly_stack_vec_init(St, d*N_FQ_INV_ITCH + d); invB = tmp + d*N_FQ_INV_ITCH; _n_fq_inv(invB, B->coeffs + d*(lenB - 1), ctx, tmp); if (Q == A || Q == B) { n_fq_poly_init(Qt); n_poly_fit_length(Qt, d*lenQ); q = Qt->coeffs; } else { n_poly_fit_length(Q, d*lenQ); q = Q->coeffs; } /* TODO why lenA here and not lenB ? */ if (R == A || R == B) { n_fq_poly_init(Rt); n_poly_fit_length(Rt, d*lenA); r = Rt->coeffs; } else { n_poly_fit_length(R, d*lenA); r = R->coeffs; } _n_fq_poly_divrem_divconquer_(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, ctx, St); if (Q == A || Q == B) { n_fq_poly_swap(Q, Qt); n_fq_poly_clear(Qt); } Q->length = lenQ; if (R == A || R == B) { n_fq_poly_swap(R, Rt); n_fq_poly_clear(Rt); } R->length = lenB - 1; _n_fq_poly_normalise(R, d); n_poly_stack_vec_clear(St); #if FLINT_WANT_ASSERT n_fq_poly_get_fq_nmod_poly(AA, Q, ctx); n_fq_poly_get_fq_nmod_poly(BB, R, ctx); FLINT_ASSERT(fq_nmod_poly_equal(AA, QQ, ctx)); FLINT_ASSERT(fq_nmod_poly_equal(BB, RR, ctx)); fq_nmod_poly_clear(QQ, ctx); fq_nmod_poly_clear(RR, ctx); fq_nmod_poly_clear(AA, ctx); fq_nmod_poly_clear(BB, ctx); #endif } void n_fq_poly_divrem( n_fq_poly_t Q, n_fq_poly_t R, const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx) { n_poly_stack_t St; n_poly_stack_init(St); n_fq_poly_divrem_divconquer_(Q, R, A, B, ctx, St); n_poly_stack_clear(St); } flint-3.1.3/src/n_poly/n_fq_poly_gcd.c000066400000000000000000000137441461254215100177020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" slong _n_fq_poly_gcd_euclidean_inplace_( mp_limb_t * A, slong Alen, mp_limb_t * B, slong Blen, const fq_nmod_ctx_t ctx, mp_limb_t * tmp) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); slong i; mp_limb_t * u = tmp; mp_limb_t * q0 = u + d; mp_limb_t * q1 = q0 + d; mp_limb_t * t = q1 + d; again: if (Alen < 2 || Blen < 2) { if (Alen < 1) { if (Blen < 1) return 0; _n_fq_inv(u, B + d*(Blen - 1), ctx, t); for (i = 0; i + 1 < Blen; i++) _n_fq_mul(B + d*i, B + d*i, u, ctx, t); _n_fq_one(B + d*(Blen - 1), d); return -Blen - 1; } if (Blen < 1) { _n_fq_inv(u, A + d*(Alen - 1), ctx, t); for (i = 0; i + 1 < Alen; i++) _n_fq_mul(A + d*i, A + d*i, u, ctx, t); _n_fq_one(A + d*(Alen - 1), d); return Alen; } if (Blen < 2) { _n_fq_one(B + d*0, d); return -1 - 1; } FLINT_ASSERT(Alen < 2); _n_fq_one(A + d*0, d); return 1; } if (Alen > Blen) { /* Q = A[Alen-1]/B[Blen-1] x + */ _n_fq_inv(u, B + d*(Blen - 1), ctx, t); _n_fq_mul(q1, A + d*(Alen - 1), u, ctx, t); _n_fq_mul(q0, q1, B + d*(Blen - 2), ctx, t); _n_fq_sub(q0, q0, A + d*(Alen - 2), d, mod); _n_fq_mul(q0, q0, u, ctx, t); _nmod_vec_neg(q1, q1, d, mod); _n_fq_mul(u, q0, B + d*0, ctx, t); _n_fq_add(A + d*(-1 + Alen - Blen), A + d*(-1 + Alen - Blen), u, d, mod); for (i = 0; i < Blen - 1; i++) { _n_fq_mul2(t, q1, B + d*i, ctx); _n_fq_madd2(t, q0, B + d*(i + 1), ctx, t + 2*d); _n_fq_reduce2(u, t, ctx, t + 2*d); _n_fq_add(A + d*(i + Alen - Blen), A + d*(i + Alen - Blen), u, d, mod); } Alen -= 2; while (Alen > 0 && _n_fq_is_zero(A + d*(Alen - 1), d)) Alen--; goto again; } else if (Blen > Alen) { _n_fq_inv(u, A + d*(Alen - 1), ctx, t); _n_fq_mul(q1, B + d*(Blen - 1), u, ctx, t); _n_fq_mul(q0, q1, A + d*(Alen - 2), ctx, t); _n_fq_sub(q0, q0, B + d*(Blen - 2), d, mod); _n_fq_mul(q0, q0, u, ctx, t); _nmod_vec_neg(q1, q1, d, mod); i = -1; _n_fq_mul(u, q0, A + d*(i + 1), ctx, t); _n_fq_add(B + d*(i + Blen - Alen), B + d*(i + Blen - Alen), u, d, mod); for (i = 0; i < Alen - 2; i++) { _n_fq_mul2(t, q1, A + d*i, ctx); _n_fq_madd2(t, q0, A + d*(i + 1), ctx, t + 2*d); _n_fq_reduce2(u, t, ctx, t + 2*d); _n_fq_add(B + d*(i + Blen - Alen), B + d*(i + Blen - Alen), u, d, mod); } Blen -= 2; while (Blen > 0 && _n_fq_is_zero(B + d*(Blen - 1), d)) Blen--; goto again; } else { _n_fq_inv(u, B + d*(Blen - 1), ctx, t); _n_fq_mul(q0, A + d*(Alen - 1), u, ctx, t); for (i = 0; i < Blen - 1; i++) { _n_fq_mul(u, q0, B + d*i, ctx, t); _n_fq_sub(A + d*i, A + d*i, u, d, mod); } Alen -= 1; while (Alen > 0 && _n_fq_is_zero(A + d*(Alen - 1), d)) Alen--; goto again; } } void n_fq_poly_gcd_( n_fq_poly_t G, const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); slong n; mp_limb_t * a, * b, * t; #if FLINT_WANT_ASSERT fq_nmod_poly_t GG, AA, BB; fq_nmod_poly_init(GG, ctx); fq_nmod_poly_init(AA, ctx); fq_nmod_poly_init(BB, ctx); FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); FLINT_ASSERT(n_fq_poly_is_canonical(B, ctx)); n_fq_poly_get_fq_nmod_poly(AA, A, ctx); n_fq_poly_get_fq_nmod_poly(BB, B, ctx); fq_nmod_poly_gcd(GG, AA, BB, ctx); #endif n_poly_stack_fit_request(St, 3); t = n_poly_stack_vec_init(St, 8*d); a = n_poly_stack_vec_init(St, d*A->length + 1); b = n_poly_stack_vec_init(St, d*B->length + 1); _nmod_vec_set(a, A->coeffs, d*A->length); _nmod_vec_set(b, B->coeffs, d*B->length); n = _n_fq_poly_gcd_euclidean_inplace_(a, A->length, b, B->length, ctx, t); if (n < 0) { n = -n - 1; n_poly_fit_length(G, d*n); _nmod_vec_set(G->coeffs, b, d*n); G->length = n; } else { n_poly_fit_length(G, d*n); _nmod_vec_set(G->coeffs, a, d*n); G->length = n; } n_poly_stack_vec_clear(St); n_poly_stack_vec_clear(St); n_poly_stack_vec_clear(St); #if FLINT_WANT_ASSERT FLINT_ASSERT(n_fq_poly_is_canonical(G, ctx)); n_fq_poly_get_fq_nmod_poly(AA, G, ctx); FLINT_ASSERT(fq_nmod_poly_equal(AA, GG, ctx)); fq_nmod_poly_clear(GG, ctx); fq_nmod_poly_clear(AA, ctx); fq_nmod_poly_clear(BB, ctx); #endif } void n_fq_poly_gcd( n_fq_poly_t G, const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx) { #if 0 n_poly_stack_t St; n_poly_stack_init(St); n_fq_poly_gcd_(G, A, B, ctx, St); n_poly_stack_clear(St); #else fq_nmod_poly_t g, a, b; fq_nmod_poly_init(g, ctx); fq_nmod_poly_init(a, ctx); fq_nmod_poly_init(b, ctx); n_fq_poly_get_fq_nmod_poly(a, A, ctx); n_fq_poly_get_fq_nmod_poly(b, B, ctx); fq_nmod_poly_gcd(g, a, b, ctx); n_fq_poly_set_fq_nmod_poly(G, g, ctx); fq_nmod_poly_clear(g, ctx); fq_nmod_poly_clear(a, ctx); fq_nmod_poly_clear(b, ctx); #endif } flint-3.1.3/src/n_poly/n_fq_poly_inv_series.c000066400000000000000000000015541461254215100213070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #include "n_poly.h" void n_fq_poly_inv_series( n_fq_poly_t A, const n_fq_poly_t B, slong order, const fq_nmod_ctx_t ctx) { fq_nmod_poly_t a, b; fq_nmod_poly_init(a, ctx); fq_nmod_poly_init(b, ctx); n_fq_poly_get_fq_nmod_poly(a, A, ctx); n_fq_poly_get_fq_nmod_poly(b, B, ctx); fq_nmod_poly_inv_series(a, b, order, ctx); n_fq_poly_set_fq_nmod_poly(A, a, ctx); fq_nmod_poly_clear(a, ctx); fq_nmod_poly_clear(b, ctx); } flint-3.1.3/src/n_poly/n_fq_poly_mul.c000066400000000000000000000120071461254215100177310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #if FLINT_WANT_ASSERT # include "fq_nmod_poly.h" #endif void _n_fq_poly_mul_( mp_limb_t * A, /* length d*(Blen + Clen - 1) */ const mp_limb_t * B, slong Blen, const mp_limb_t * C, slong Clen, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); slong Alen = Blen + Clen - 1; mp_limb_t * tmp, * u; slong i, j; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_poly_stack_fit_request(St, 4); tmp = n_poly_stack_vec_init(St, 16*d); u = tmp + 6*d; if (Blen < 4 || Clen < 4) { for (i = 0; i < Alen; i++) { slong j_start = FLINT_MAX(0, i - Clen + 1); slong j_stop = FLINT_MIN(i, Blen - 1); j = j_start; if (j_stop <= j_start) { FLINT_ASSERT(j_stop == j_start); _n_fq_mul(A + d*i, B + d*j, C + d*(i - j), ctx, tmp); } else { _n_fq_mul2(u, B + d*j, C + d*(i - j), ctx); for (j++; j <= j_stop; j++) _n_fq_madd2(u, B + d*j, C + d*(i - j), ctx, u + 2*d); _n_fq_reduce2(A + d*i, u, ctx, tmp); } } } else { mp_limb_t * xA, * xB, * xC; slong xAlen, xBlen, xClen, start; xBlen = (2*d-1)*Blen; xB = n_poly_stack_vec_init(St, xBlen); for (i = 0; i < Blen; i++) { _nmod_vec_set(xB + (2*d-1)*i, B + d*i, d); _nmod_vec_zero(xB + (2*d-1)*i + d, d-1); } while (xBlen > 0 && xB[xBlen - 1] == 0) xBlen -= 1; xClen = (2*d-1)*Clen; xC = n_poly_stack_vec_init(St, xClen); for (i = 0; i < Clen; i++) { _nmod_vec_set(xC + (2*d-1)*i, C + d*i, d); _nmod_vec_zero(xC + (2*d-1)*i + d, d-1); } while (xClen > 0 && xC[xClen - 1] == 0) xClen -= 1; if (xClen < 1 || xBlen < 1) { xAlen = 0; xA = n_poly_stack_vec_init(St, d); /* dummy */ } else { xAlen = xClen + xBlen - 1; xA = n_poly_stack_vec_init(St, xAlen); if (xBlen >= xClen) _nmod_poly_mul(xA, xB, xBlen, xC, xClen, ctx->mod); else _nmod_poly_mul(xA, xC, xClen, xB, xBlen, ctx->mod); } start = 0; for (i = 0; i < Alen; i++, start += 2*d - 1) { if (xAlen >= start + (2*d - 1)) _n_fq_reduce2(A + d*i, xA + start, ctx, tmp); else if (start < xAlen) _n_fq_reduce(A + d*i, xA + start, xAlen - start, ctx, tmp); else _n_fq_zero(A + d*i, d); } n_poly_stack_vec_clear(St); n_poly_stack_vec_clear(St); n_poly_stack_vec_clear(St); } n_poly_stack_vec_clear(St); } void n_fq_poly_mul_( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); slong Blen = B->length; slong Clen = C->length; #if FLINT_WANT_ASSERT fq_nmod_poly_t AA, BB, CC; #endif FLINT_ASSERT(n_fq_poly_is_canonical(B, ctx)); FLINT_ASSERT(n_fq_poly_is_canonical(C, ctx)); if (Blen < 1 || Clen < 1) { A->length = 0; return; } if (A == B || A == C) { n_fq_poly_t T; n_fq_poly_init(T); n_fq_poly_mul_(T, B, C, ctx, St); n_fq_poly_swap(A, T); n_fq_poly_clear(T); return; } #if FLINT_WANT_ASSERT fq_nmod_poly_init(AA, ctx); fq_nmod_poly_init(BB, ctx); fq_nmod_poly_init(CC, ctx); n_fq_poly_get_fq_nmod_poly(BB, B, ctx); n_fq_poly_get_fq_nmod_poly(CC, C, ctx); fq_nmod_poly_mul(AA, BB, CC, ctx); #endif n_poly_fit_length(A, d*(Blen + Clen - 1)); _n_fq_poly_mul_(A->coeffs, B->coeffs, Blen, C->coeffs, Clen, ctx, St); A->length = Blen + Clen - 1; _n_fq_poly_normalise(A, d); #if FLINT_WANT_ASSERT n_fq_poly_get_fq_nmod_poly(BB, A, ctx); FLINT_ASSERT(fq_nmod_poly_equal(BB, AA, ctx)); fq_nmod_poly_clear(AA, ctx); fq_nmod_poly_clear(BB, ctx); fq_nmod_poly_clear(CC, ctx); #endif FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); } void n_fq_poly_mul( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, const fq_nmod_ctx_t ctx) { n_poly_stack_t St; n_poly_stack_init(St); FLINT_ASSERT(n_fq_poly_is_canonical(B, ctx)); FLINT_ASSERT(n_fq_poly_is_canonical(C, ctx)); n_fq_poly_mul_(A, B, C, ctx, St); n_poly_stack_clear(St); } flint-3.1.3/src/n_poly/n_fq_poly_mullow.c000066400000000000000000000077041461254215100204630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #if FLINT_WANT_ASSERT # include "fq_nmod_poly.h" #endif void _n_fq_poly_mullow_( mp_limb_t * rop, const mp_limb_t * op1, slong len1, const mp_limb_t * op2, slong len2, slong n, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); const slong fqlen = ctx->modulus->length - 1; const slong pfqlen = 2*fqlen - 1; const nmod_t mod = ctx->mod; const slong rlen = len1 + len2 - 1; const slong m = FLINT_MIN(n, rlen); const slong cmlen = pfqlen*m; const slong clen1 = pfqlen*len1; const slong clen2 = pfqlen*len2; slong i; mp_limb_t * tmp; mp_ptr cop1, cop2, crop; if (len1 < 1 || len2 < 1) { _nmod_vec_zero(rop, d*n); return; } n_poly_stack_fit_request(St, 4); tmp = n_poly_stack_vec_init(St, N_FQ_REDUCE_ITCH*d); cop1 = n_poly_stack_vec_init(St, clen1); for (i = 0; i < len1; i++) { flint_mpn_copyi(cop1 + pfqlen*i, op1 + d*i, d); flint_mpn_zero(cop1 + pfqlen*i + d, pfqlen - d); } cop2 = n_poly_stack_vec_init(St, clen2); for (i = 0; i < len2; i++) { flint_mpn_copyi(cop2 + pfqlen*i, op2 + d*i, d); flint_mpn_zero(cop2 + pfqlen*i + d, pfqlen - d); } crop = n_poly_stack_vec_init(St, cmlen); if (clen1 >= clen2) _nmod_poly_mullow(crop, cop1, clen1, cop2, clen2, cmlen, mod); else _nmod_poly_mullow(crop, cop2, clen2, cop1, clen1, cmlen, mod); for (i = 0; i < m; i++) _n_fq_reduce2(rop + d*i, crop + pfqlen*i, ctx, tmp); for ( ; i < n; i++) _n_fq_zero(rop + d*i, d); n_poly_stack_vec_clear(St); n_poly_stack_vec_clear(St); n_poly_stack_vec_clear(St); n_poly_stack_vec_clear(St); } void n_fq_poly_mullow_( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, slong order, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); slong Blen = B->length; slong Clen = C->length; const slong m = FLINT_MIN(order, Blen + Clen - 1); #if FLINT_WANT_ASSERT fq_nmod_poly_t AA, BB, CC; #endif FLINT_ASSERT(n_fq_poly_is_canonical(B, ctx)); FLINT_ASSERT(n_fq_poly_is_canonical(C, ctx)); if (Blen < 1 || Clen < 1 || order < 1) { A->length = 0; return; } if (A == B || A == C) { n_fq_poly_t T; n_fq_poly_init(T); n_fq_poly_mullow_(T, B, C, order, ctx, St); n_fq_poly_swap(A, T); n_fq_poly_clear(T); return; } #if FLINT_WANT_ASSERT fq_nmod_poly_init(AA, ctx); fq_nmod_poly_init(BB, ctx); fq_nmod_poly_init(CC, ctx); n_fq_poly_get_fq_nmod_poly(BB, B, ctx); n_fq_poly_get_fq_nmod_poly(CC, C, ctx); fq_nmod_poly_mullow(AA, BB, CC, order, ctx); #endif n_poly_fit_length(A, d*m); _n_fq_poly_mullow_(A->coeffs, B->coeffs, Blen, C->coeffs, Clen, m, ctx, St); A->length = m; _n_fq_poly_normalise(A, d); #if FLINT_WANT_ASSERT n_fq_poly_get_fq_nmod_poly(BB, A, ctx); FLINT_ASSERT(fq_nmod_poly_equal(BB, AA, ctx)); fq_nmod_poly_clear(AA, ctx); fq_nmod_poly_clear(BB, ctx); fq_nmod_poly_clear(CC, ctx); #endif FLINT_ASSERT(n_fq_poly_is_canonical(A, ctx)); } void n_fq_poly_mullow( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, slong order, const fq_nmod_ctx_t ctx) { n_poly_stack_t St; n_poly_stack_init(St); FLINT_ASSERT(n_fq_poly_is_canonical(B, ctx)); FLINT_ASSERT(n_fq_poly_is_canonical(C, ctx)); n_fq_poly_mullow_(A, B, C, order, ctx, St); n_poly_stack_clear(St); } flint-3.1.3/src/n_poly/n_fq_poly_mulmod.c000066400000000000000000000021351461254215100204320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #include "n_poly.h" void n_fq_poly_mulmod( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, const n_fq_poly_t M, const fq_nmod_ctx_t ctx) { fq_nmod_poly_t a, b, c, m; fq_nmod_poly_init(a, ctx); fq_nmod_poly_init(b, ctx); fq_nmod_poly_init(c, ctx); fq_nmod_poly_init(m, ctx); n_fq_poly_get_fq_nmod_poly(a, A, ctx); n_fq_poly_get_fq_nmod_poly(b, B, ctx); n_fq_poly_get_fq_nmod_poly(c, C, ctx); n_fq_poly_get_fq_nmod_poly(m, M, ctx); fq_nmod_poly_mulmod(a, b, c, m, ctx); n_fq_poly_set_fq_nmod_poly(A, a, ctx); fq_nmod_poly_clear(a, ctx); fq_nmod_poly_clear(b, ctx); fq_nmod_poly_clear(c, ctx); fq_nmod_poly_clear(m, ctx); } flint-3.1.3/src/n_poly/n_fq_poly_neg.c000066400000000000000000000013301461254215100177020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" void n_fq_poly_neg( n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong Blen = B->length; n_poly_fit_length(A, d*Blen); _nmod_vec_neg(A->coeffs, B->coeffs, d*Blen, ctx->mod); A->length = Blen; _n_fq_poly_normalise(A, d); } flint-3.1.3/src/n_poly/n_fq_poly_pow.c000066400000000000000000000015251461254215100177440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #include "n_poly.h" void n_fq_poly_pow( n_fq_poly_t A, const n_fq_poly_t B, ulong e, const fq_nmod_ctx_t ctx) { fq_nmod_poly_t a, b; fq_nmod_poly_init(a, ctx); fq_nmod_poly_init(b, ctx); n_fq_poly_get_fq_nmod_poly(a, A, ctx); n_fq_poly_get_fq_nmod_poly(b, B, ctx); fq_nmod_poly_pow(a, b, e, ctx); n_fq_poly_set_fq_nmod_poly(A, a, ctx); fq_nmod_poly_clear(a, ctx); fq_nmod_poly_clear(b, ctx); } flint-3.1.3/src/n_poly/n_fq_poly_rem.c000066400000000000000000000017161461254215100177240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #include "n_poly.h" void n_fq_poly_rem( n_fq_poly_t R, const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx) { fq_nmod_poly_t r, a, b; fq_nmod_poly_init(r, ctx); fq_nmod_poly_init(a, ctx); fq_nmod_poly_init(b, ctx); n_fq_poly_get_fq_nmod_poly(r, R, ctx); n_fq_poly_get_fq_nmod_poly(a, A, ctx); n_fq_poly_get_fq_nmod_poly(b, B, ctx); fq_nmod_poly_rem(r, a, b, ctx); n_fq_poly_set_fq_nmod_poly(R, r, ctx); fq_nmod_poly_clear(r, ctx); fq_nmod_poly_clear(a, ctx); fq_nmod_poly_clear(b, ctx); } flint-3.1.3/src/n_poly/n_fq_poly_sub.c000066400000000000000000000026231461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "n_poly.h" void n_fq_poly_sub( n_fq_poly_t A, const n_fq_poly_t B, const n_fq_poly_t C, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; slong Blen = B->length; slong Clen = C->length; if (Blen > Clen) { n_poly_fit_length(A, d*Blen); _nmod_vec_sub(A->coeffs, B->coeffs, C->coeffs, d*Clen, ctx->mod); if (A != B) for (i = d*Clen; i < d*Blen; i++) A->coeffs[i] = B->coeffs[i]; A->length = Blen; } else if (Blen < Clen) { n_poly_fit_length(A, d*Clen); _nmod_vec_sub(A->coeffs, B->coeffs, C->coeffs, d*Blen, ctx->mod); for (i = d*Blen; i < d*Clen; i++) A->coeffs[i] = nmod_neg(C->coeffs[i], ctx->mod); A->length = Clen; } else { n_poly_fit_length(A, d*Blen); _nmod_vec_sub(A->coeffs, B->coeffs, C->coeffs, d*Clen, ctx->mod); A->length = Clen; _n_fq_poly_normalise(A, d); } } flint-3.1.3/src/n_poly/n_fq_poly_xgcd.c000066400000000000000000000023041461254215100200600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #include "n_poly.h" void n_fq_poly_xgcd( n_fq_poly_t G, n_fq_poly_t S, n_fq_poly_t T, const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx) { fq_nmod_poly_t GG, SS, TT, AA, BB; fq_nmod_poly_init(GG, ctx); fq_nmod_poly_init(SS, ctx); fq_nmod_poly_init(TT, ctx); fq_nmod_poly_init(AA, ctx); fq_nmod_poly_init(BB, ctx); n_fq_poly_get_fq_nmod_poly(AA, A, ctx); n_fq_poly_get_fq_nmod_poly(BB, B, ctx); fq_nmod_poly_xgcd(GG, SS, TT, AA, BB, ctx); n_fq_poly_set_fq_nmod_poly(G, GG, ctx); n_fq_poly_set_fq_nmod_poly(S, SS, ctx); n_fq_poly_set_fq_nmod_poly(T, TT, ctx); fq_nmod_poly_clear(GG, ctx); fq_nmod_poly_clear(SS, ctx); fq_nmod_poly_clear(TT, ctx); fq_nmod_poly_clear(AA, ctx); fq_nmod_poly_clear(BB, ctx); } flint-3.1.3/src/n_poly/n_fq_polyun.c000066400000000000000000000013051461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" void n_fq_polyun_set(n_fq_polyun_t A, const n_fq_polyun_t B, const fq_nmod_ctx_t ctx) { slong i; n_polyun_fit_length(A, B->length); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; n_fq_poly_set(A->coeffs + i, B->coeffs + i, ctx); } A->length = B->length; } flint-3.1.3/src/n_poly/n_fq_pow_cache.c000066400000000000000000000162541461254215100200310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" /* hold positive and negative powers of b */ void n_fq_pow_cache_start_n_fq( const mp_limb_t * b, n_poly_t pos, /* b^0, b^1, b^2, ..., b^50 */ n_poly_t bin, /* b^1, b^2, b^3, b^4, b^8, b^12, ... */ n_poly_t neg, /* b^-0, b^-1, b^-2, ..., b^-50 */ const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); n_poly_fit_length(pos, d*2); pos->length = 2; _n_fq_one(pos->coeffs + d*0, d); _n_fq_set(pos->coeffs + d*1, b, d); bin->length = 0; neg->length = 0; } void n_fq_pow_cache_start_fq_nmod( const fq_nmod_t b, n_poly_t pos, n_poly_t bin, n_poly_t neg, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); n_poly_fit_length(pos, d*2); pos->length = 2; _n_fq_one(pos->coeffs + d*0, d); n_fq_set_fq_nmod(pos->coeffs + d*1, b, ctx); bin->length = 0; neg->length = 0; } /* r = a*b^e */ static void n_fq_pow_cache_mulpow_ui_array_bin( mp_limb_t * r, const mp_limb_t * a, mp_limb_t * elimbs, slong elen, n_poly_t bin, const mp_limb_t * b, const fq_nmod_ctx_t ctx, mp_limb_t * tmp) /* size d*N_FQ_MUL_ITCH */ { slong d = fq_nmod_ctx_degree(ctx); const mp_limb_t * s = a; /* source */ slong ei = 0, i = 0; mp_limb_t e = (ei < elen) ? elimbs[ei] : 0; int bits_left = FLINT_BITS; /* complicated code needed if an odd number of bits per limb */ FLINT_ASSERT((FLINT_BITS % 2) == 0); if (bin->length < 3) { n_poly_fit_length(bin, 3*d); bin->length = 3; _n_fq_set(bin->coeffs + d*0, b, d); _n_fq_mul(bin->coeffs + d*1, bin->coeffs + d*0, bin->coeffs + d*0, ctx, tmp); _n_fq_mul(bin->coeffs + d*2, bin->coeffs + d*1, bin->coeffs + d*0, ctx, tmp); } while (ei < elen) { FLINT_ASSERT(i <= bin->length); if (i + 3 > bin->length) { FLINT_ASSERT(i >= 3); n_poly_fit_length(bin, d*(bin->length + 3)); bin->length += 3; _n_fq_mul(bin->coeffs + d*(i + 0), bin->coeffs + d*(i - 2), bin->coeffs + d*(i - 2), ctx, tmp); _n_fq_mul(bin->coeffs + d*(i + 1), bin->coeffs + d*(i + 0), bin->coeffs + d*(i + 0), ctx, tmp); _n_fq_mul(bin->coeffs + d*(i + 2), bin->coeffs + d*(i + 1), bin->coeffs + d*(i + 0), ctx, tmp); } if ((e%4) != 0) { _n_fq_mul(r, s, bin->coeffs + d*(i + (e%4) - 1), ctx, tmp); s = r; } i += 3; e = e/4; if (ei + 1 < elen) { bits_left -= 2; if (bits_left <= 0) { ei++; e = elimbs[ei]; bits_left = FLINT_BITS; } } else { if (e == 0) break; } } if (s != r) _n_fq_set(r, s, d); } /* r = a*b^e */ void n_fq_pow_cache_mulpow_ui( mp_limb_t * r, const mp_limb_t * a, ulong e, n_poly_t pos, n_poly_t bin, n_poly_t neg, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i = pos->length; int a_in_fp = _n_fq_is_ui(a, d); FLINT_ASSERT(i >= 2); if (a[0] == 0 && a_in_fp) { _n_fq_zero(r, d); return; } if (e < 50) { n_poly_fit_length(pos, d*(FLINT_MAX(e + 1, i) + N_FQ_MUL_ITCH)); while (i <= e) { FLINT_ASSERT(d*(i + 1 + N_FQ_MUL_ITCH) <= pos->alloc); _n_fq_mul(pos->coeffs + d*i, pos->coeffs + d*1, pos->coeffs + d*(i - 1), ctx, pos->coeffs + d*(i + 1)); i++; pos->length = i; } if (a_in_fp) _nmod_vec_scalar_mul_nmod(r, pos->coeffs + d*e, d, a[0], ctx->mod); else _n_fq_mul(r, a, pos->coeffs + d*e, ctx, pos->coeffs + d*i); return; } if (_n_fq_is_zero(pos->coeffs + d*1, d)) { _n_fq_zero(r, d); return; } n_poly_fit_length(pos, d*(i + N_FQ_MUL_ITCH)); n_fq_pow_cache_mulpow_ui_array_bin(r, a, &e, 1, bin, pos->coeffs + d*1, ctx, pos->coeffs + d*i); } /* r = a*b^-e */ void n_fq_pow_cache_mulpow_neg_ui( mp_limb_t * r, const mp_limb_t * a, ulong e, n_poly_t pos, n_poly_t bin, n_poly_t neg, const fq_nmod_ctx_t ctx) { slong i, d = fq_nmod_ctx_degree(ctx); mp_limb_t * tmp; fmpz_t f; FLINT_ASSERT(pos->length >= 2); if (_n_fq_is_zero(pos->coeffs + d*1, d)) { if (e > 0) _n_fq_zero(r, d); else _n_fq_set(r, a, d); return; } if (e < 50) { n_poly_fit_length(pos, d*(pos->length + FLINT_MAX(N_FQ_MUL_ITCH, N_FQ_INV_ITCH))); tmp = pos->coeffs + d*pos->length; if (neg->length < 2) { n_poly_fit_length(neg, 2*d); neg->length = 2; _n_fq_one(neg->coeffs + d*0, d); _n_fq_inv(neg->coeffs + d*1, pos->coeffs + d*1, ctx, tmp); } i = neg->length; n_poly_fit_length(neg, d*(e + 1)); while (i <= e) { _n_fq_mul(neg->coeffs + d*i, neg->coeffs + d*1, neg->coeffs + d*(i - 1), ctx, tmp); i++; neg->length = i; } _n_fq_mul(r, a, neg->coeffs + d*e, ctx, tmp); return; } fmpz_init(f); fmpz_neg_ui(f, e); n_fq_pow_cache_mulpow_fmpz(r, a, f, pos, bin, neg, ctx); fmpz_clear(f); } /* r = a*b^-e */ void n_fq_pow_cache_mulpow_fmpz( mp_limb_t * r, const mp_limb_t * a, const fmpz_t e, n_poly_t pos, n_poly_t bin, n_poly_t neg, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); fmpz_t t; FLINT_ASSERT(pos->length >= 2); if (!COEFF_IS_MPZ(*e) && *e >= 0) { n_fq_pow_cache_mulpow_ui(r, a, *e, pos, bin, neg, ctx); return; } if (_n_fq_is_zero(pos->coeffs + d*1, d)) { if (!fmpz_is_zero(e)) _n_fq_zero(r, d); else _n_fq_set(r, a, d); return; } fmpz_init(t); fq_nmod_ctx_order(t, ctx); fmpz_sub_ui(t, t, 1); fmpz_mod(t, e, t); n_poly_fit_length(pos, d*(pos->length + N_FQ_MUL_ITCH)); if (COEFF_IS_MPZ(*t)) n_fq_pow_cache_mulpow_ui_array_bin(r, a, COEFF_TO_PTR(*t)->_mp_d, COEFF_TO_PTR(*t)->_mp_size, bin, pos->coeffs + d*1, ctx, pos->coeffs + d*pos->length); else n_fq_pow_cache_mulpow_ui(r, a, *t, pos, bin, neg, ctx); fmpz_clear(t); } flint-3.1.3/src/n_poly/n_poly.c000066400000000000000000000034161461254215100163720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpn_extras.h" #include "nmod_vec.h" int n_poly_is_canonical(const n_poly_t A) { if (A->length < 0) return 0; return A->length < 1 || A->coeffs[A->length - 1] != 0; } void n_poly_realloc(n_poly_t A, slong len) { slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; if (old_alloc > 0) { FLINT_ASSERT(A->coeffs != NULL); A->coeffs = (mp_limb_t *) flint_realloc(A->coeffs, new_alloc*sizeof(mp_limb_t)); } else { FLINT_ASSERT(A->coeffs == NULL); A->coeffs = (mp_limb_t *) flint_malloc(new_alloc*sizeof(mp_limb_t)); } A->alloc = new_alloc; } void n_poly_set_coeff(n_poly_t poly, slong j, ulong c) { n_poly_fit_length(poly, j + 1); if (j + 1 < poly->length) /* interior */ { poly->coeffs[j] = c; } else if (j + 1 == poly->length) /* leading coeff */ { if (c != 0) { poly->coeffs[j] = c; } else { poly->length--; _n_poly_normalise(poly); } } else if (c != 0) /* extend polynomial */ { flint_mpn_zero(poly->coeffs + poly->length, j - poly->length); poly->coeffs[j] = c; poly->length = j + 1; } } flint-3.1.3/src/n_poly/n_poly_mod.c000066400000000000000000000625421461254215100172360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod.h" #include "n_poly.h" int n_poly_mod_is_canonical(const n_poly_t A, nmod_t mod) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (A->coeffs[i] >= mod.n) return 0; if (A->coeffs[i] == 0 && i + 1 == A->length) return 0; } return 1; } void n_poly_mod_set_coeff_ui( n_poly_t poly, slong j, ulong c, nmod_t ctx) { if (c >= ctx.n) NMOD_RED(c, c, ctx); n_poly_set_coeff(poly, j, c); } void n_poly_mod_add_ui(n_poly_t res, const n_poly_t poly, ulong c, nmod_t ctx) { if (c >= ctx.n) NMOD_RED(c, c, ctx); if (poly->length < 1) { n_poly_set_ui(res, c); } else { n_poly_set(res, poly); res->coeffs[0] = nmod_add(res->coeffs[0], c, ctx); _n_poly_normalise(res); } } mp_limb_t n_poly_mod_div_root(n_poly_t Q, const n_poly_t A, mp_limb_t c, nmod_t ctx) { mp_limb_t rem; slong len = A->length; if (len < 2) { if (len == 1) { rem = A->coeffs[0]; n_poly_zero(Q); return rem; } n_poly_zero(Q); return 0; } n_poly_fit_length(Q, len - 1); rem = _nmod_poly_div_root(Q->coeffs, A->coeffs, len, c, ctx); Q->length = len - 1; return rem; } void n_poly_mod_pow(n_poly_t res, const n_poly_t poly, ulong e, nmod_t ctx) { const slong len = poly->length; slong rlen; if ((len < 2) | (e < UWORD(3))) { if (len == 0) { if (e == 0) n_poly_one(res); else n_poly_zero(res); } else if (len == 1) { n_poly_set_ui(res, n_powmod2_ui_preinv(poly->coeffs[0], e, ctx.n, ctx.ninv)); } else if (e == 0) { n_poly_one(res); } else if (e == 1) n_poly_set(res, poly); else /* e == UWORD(2) */ n_poly_mod_mul(res, poly, poly, ctx); return; } rlen = (slong) e * (len - 1) + 1; if (res != poly) { n_poly_fit_length(res, rlen); _nmod_poly_pow(res->coeffs, poly->coeffs, len, e, ctx); } else { n_poly_t t; n_poly_init2(t, rlen); _nmod_poly_pow(t->coeffs, poly->coeffs, len, e, ctx); n_poly_swap(res, t); n_poly_clear(t); } res->length = rlen; _n_poly_normalise(res); } void n_poly_mod_mul(n_poly_t res, const n_poly_t poly1, const n_poly_t poly2, nmod_t ctx) { slong len1, len2, len_out; len1 = poly1->length; len2 = poly2->length; if (len1 == 0 || len2 == 0) { n_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { n_poly_t temp; n_poly_init2(temp, len_out); if (len1 >= len2) _nmod_poly_mul(temp->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); else _nmod_poly_mul(temp->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, ctx); n_poly_swap(temp, res); n_poly_clear(temp); } else { n_poly_fit_length(res, len_out); if (len1 >= len2) _nmod_poly_mul(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, ctx); else _nmod_poly_mul(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, ctx); } res->length = len_out; _n_poly_normalise(res); } void n_poly_mod_mullow( n_poly_t res, const n_poly_t poly1, const n_poly_t poly2, slong trunc, nmod_t ctx) { slong len1, len2, len_out; len1 = poly1->length; len2 = poly2->length; len_out = poly1->length + poly2->length - 1; if (trunc > len_out) trunc = len_out; if (len1 <= 0 || len2 <= 0 || trunc <= 0) { n_poly_zero(res); return; } if (res == poly1 || res == poly2) { n_poly_t temp; n_poly_init2(temp, trunc); if (len1 >= len2) _nmod_poly_mullow(temp->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, trunc, ctx); else _nmod_poly_mullow(temp->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, trunc, ctx); n_poly_swap(temp, res); n_poly_clear(temp); } else { n_poly_fit_length(res, trunc); if (len1 >= len2) _nmod_poly_mullow(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, trunc, ctx); else _nmod_poly_mullow(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, trunc, ctx); } res->length = trunc; _n_poly_normalise(res); } void n_poly_mod_mulmod(n_poly_t res, const n_poly_t poly1, const n_poly_t poly2, const n_poly_t f, nmod_t ctx) { slong len1, len2, lenf; mp_ptr fcoeffs; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_mulmod). Divide by zero.\n"); } if (lenf == 1 || len1 == 0 || len2 == 0) { n_poly_zero(res); return; } if (len1 + len2 - lenf > 0) { if (f == res) { fcoeffs = flint_malloc(sizeof(mp_limb_t) * lenf); _nmod_vec_set(fcoeffs, f->coeffs, lenf); } else fcoeffs = f->coeffs; n_poly_fit_length(res, lenf - 1); _nmod_poly_mulmod(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fcoeffs, lenf, ctx); if (f == res) flint_free(fcoeffs); res->length = lenf - 1; _n_poly_normalise(res); } else { n_poly_mod_mul(res, poly1, poly2, ctx); } } void n_poly_mod_div(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t ctx) { n_poly_t tQ; mp_ptr q; slong A_len, B_len; B_len = B->length; if (B_len == 0) { if (ctx.n == 1) { n_poly_set(Q, A); return; } else { flint_throw(FLINT_ERROR, "Exception (n_poly_mod_div). Division by zero.\n"); } } A_len = A->length; if (A_len < B_len) { n_poly_zero(Q); return; } if (Q == A || Q == B) { n_poly_init2(tQ, A_len - B_len + 1); q = tQ->coeffs; } else { n_poly_fit_length(Q, A_len - B_len + 1); q = Q->coeffs; } _nmod_poly_div(q, A->coeffs, A_len, B->coeffs, B_len, ctx); if (Q == A || Q == B) { n_poly_swap(tQ, Q); n_poly_clear(tQ); } Q->length = A_len - B_len + 1; } void n_poly_mod_divexact(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t ctx) { n_poly_t tQ; mp_ptr q; slong A_len, B_len; B_len = B->length; if (B_len == 0) { if (ctx.n == 1) { n_poly_set(Q, A); return; } else { flint_throw(FLINT_ERROR, "Exception (n_poly_mod_divexact). Division by zero.\n"); } } A_len = A->length; if (A_len < B_len) { n_poly_zero(Q); return; } if (Q == A || Q == B) { n_poly_init2(tQ, A_len - B_len + 1); q = tQ->coeffs; } else { n_poly_fit_length(Q, A_len - B_len + 1); q = Q->coeffs; } _nmod_poly_divexact(q, A->coeffs, A_len, B->coeffs, B_len, ctx); if (Q == A || Q == B) { n_poly_swap(tQ, Q); n_poly_clear(tQ); } Q->length = A_len - B_len + 1; } void n_poly_mod_rem(n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t ctx) { const slong lenA = A->length, lenB = B->length; n_poly_t tR; mp_ptr r; if (lenB == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_rem). Division by zero.\n"); } if (lenA < lenB) { n_poly_set(R, A); return; } if (R == A || R == B) { n_poly_init2(tR, lenB - 1); r = tR->coeffs; } else { n_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_rem(r, A->coeffs, lenA, B->coeffs, lenB, ctx); if (R == A || R == B) { n_poly_swap(R, tR); n_poly_clear(tR); } R->length = lenB - 1; _n_poly_normalise(R); } void n_poly_mod_divrem(n_poly_t Q, n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t ctx) { const slong lenA = A->length, lenB = B->length; n_poly_t tQ, tR; mp_ptr q, r; if (lenB == 0) { if (ctx.n == 1) { n_poly_set(Q, A); n_poly_zero(R); return; } else { flint_throw(FLINT_ERROR, "Exception (n_poly_mod_divrem). Division by zero."); } } if (lenA < lenB) { n_poly_set(R, A); n_poly_zero(Q); return; } if (Q == A || Q == B) { n_poly_init2(tQ, lenA - lenB + 1); q = tQ->coeffs; } else { n_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } if (R == A || R == B) { n_poly_fit_length(tR, lenB - 1); r = tR->coeffs; } else { n_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, ctx); if (Q == A || Q == B) { n_poly_swap(Q, tQ); n_poly_clear(tQ); } if (R == A || R == B) { n_poly_swap(R, tR); n_poly_clear(tR); } Q->length = lenA - lenB + 1; R->length = lenB - 1; _n_poly_normalise(R); } int n_poly_mod_invmod(n_poly_t A, const n_poly_t B, const n_poly_t P, nmod_t ctx) { const slong lenB = B->length, lenP = P->length; mp_limb_t * a; n_poly_t tA; int ans; if (lenP < 2) flint_throw(FLINT_ERROR, "lenP < 2 in %s\n", __func__); if (lenB == 0) { n_poly_zero(A); return 0; } if (lenB >= lenP) { n_poly_t T; n_poly_init(T); n_poly_mod_rem(T, B, P, ctx); ans = n_poly_mod_invmod(A, T, P, ctx); n_poly_clear(T); return ans; } if (A != B && A != P) { n_poly_fit_length(A, lenP - 1); a = A->coeffs; } else { n_poly_init2(tA, lenP - 1); a = tA->coeffs; } ans = _nmod_poly_invmod(a, B->coeffs, lenB, P->coeffs, lenP, ctx); if (A == B || A == P) { n_poly_swap(A, tA); n_poly_clear(tA); } A->length = lenP - 1; _n_poly_normalise(A); return ans; } void n_poly_mod_gcd(n_poly_t G, const n_poly_t A, const n_poly_t B, nmod_t ctx) { if (A->length < B->length) { n_poly_mod_gcd(G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; n_poly_t tG; mp_ptr g; if (lenA == 0) /* lenA = lenB = 0 */ { n_poly_zero(G); } else if (lenB == 0) /* lenA > lenB = 0 */ { n_poly_mod_make_monic(G, A, ctx); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { n_poly_init2(tG, FLINT_MIN(lenA, lenB)); g = tG->coeffs; } else { n_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } lenG = _nmod_poly_gcd(g, A->coeffs, lenA, B->coeffs, lenB, ctx); if (G == A || G == B) { n_poly_swap(tG, G); n_poly_clear(tG); } G->length = lenG; if (G->length == 1) G->coeffs[0] = 1; else n_poly_mod_make_monic(G, G, ctx); } } } void n_poly_mod_xgcd( n_poly_t G, n_poly_t S, n_poly_t T, const n_poly_t A, const n_poly_t B, nmod_t ctx) { if (A->length < B->length) { n_poly_mod_xgcd(G, T, S, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; mp_limb_t inv; if (lenA == 0) /* lenA = lenB = 0 */ { n_poly_zero(G); n_poly_zero(S); n_poly_zero(T); } else if (lenB == 0) /* lenA > lenB = 0 */ { inv = n_invmod(A->coeffs[lenA - 1], ctx.n); _n_poly_mod_scalar_mul_nmod(G, A, inv, ctx); n_poly_zero(T); n_poly_set_coeff(S, 0, inv); S->length = 1; } else if (lenB == 1) /* lenA >= lenB = 1 */ { n_poly_fit_length(T, 1); T->length = 1; T->coeffs[0] = n_invmod(B->coeffs[0], ctx.n); n_poly_one(G); n_poly_zero(S); } else /* lenA >= lenB >= 2 */ { mp_ptr g, s, t; slong lenG; if (G == A || G == B) { g = _nmod_vec_init(FLINT_MIN(lenA, lenB)); } else { n_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } if (S == A || S == B) { s = _nmod_vec_init(lenB - 1); } else { n_poly_fit_length(S, lenB - 1); s = S->coeffs; } if (T == A || T == B) { t = _nmod_vec_init(lenA - 1); } else { n_poly_fit_length(T, lenA - 1); t = T->coeffs; } if (lenA >= lenB) lenG = _nmod_poly_xgcd(g, s, t, A->coeffs, lenA, B->coeffs, lenB, ctx); else lenG = _nmod_poly_xgcd(g, t, s, B->coeffs, lenB, A->coeffs, lenA, ctx); if (G == A || G == B) { flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { flint_free(S->coeffs); S->coeffs = s; S->alloc = lenB - 1; } if (T == A || T == B) { flint_free(T->coeffs); T->coeffs = t; T->alloc = lenA - 1; } G->length = lenG; S->length = FLINT_MAX(lenB - lenG, 1); T->length = FLINT_MAX(lenA - lenG, 1); MPN_NORM(S->coeffs, S->length); MPN_NORM(T->coeffs, T->length); if (G->coeffs[lenG - 1] != 1) { inv = nmod_inv(G->coeffs[lenG - 1], ctx); _n_poly_mod_scalar_mul_nmod(G, G, inv, ctx); _n_poly_mod_scalar_mul_nmod(S, S, inv, ctx); _n_poly_mod_scalar_mul_nmod(T, T, inv, ctx); } } } } void n_poly_reverse(n_poly_t output, const n_poly_t input, slong m) { n_poly_fit_length(output, m); _nmod_poly_reverse(output->coeffs, input->coeffs, input->length, m); output->length = m; _n_poly_normalise(output); } void n_poly_mod_mulmod_preinv( n_poly_t res, const n_poly_t poly1, const n_poly_t poly2, const n_poly_t f, const n_poly_t finv, nmod_t ctx) { slong len1, len2, lenf; mp_ptr fcoeffs; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf <= len1 || lenf <= len2) { flint_throw(FLINT_ERROR, "n_poly_mod_mulmod_preinv: Input is larger than modulus."); } if (lenf == 1 || len1 == 0 || len2 == 0) { n_poly_zero(res); return; } if (len1 + len2 > lenf) { if (f == res) { fcoeffs = flint_malloc(sizeof(mp_limb_t) * lenf); _nmod_vec_set(fcoeffs, f->coeffs, lenf); } else { fcoeffs = f->coeffs; } n_poly_fit_length(res, lenf - 1); _nmod_poly_mulmod_preinv(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fcoeffs, lenf, finv->coeffs, finv->length, ctx); if (f == res) flint_free(fcoeffs); res->length = lenf - 1; _n_poly_normalise(res); } else { n_poly_mod_mul(res, poly1, poly2, ctx); } } void n_poly_mod_inv_series(n_poly_t Qinv, const n_poly_t Q, slong n, nmod_t ctx) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_throw(FLINT_ERROR, "n_poly_mod_inv_series_newton: Division by zero."); } if (Qinv != Q) { n_poly_fit_length(Qinv, n); _nmod_poly_inv_series_newton(Qinv->coeffs, Q->coeffs, Qlen, n, ctx); } else { n_poly_t t; n_poly_init2(t, n); _nmod_poly_inv_series_newton(t->coeffs, Q->coeffs, Qlen, n, ctx); n_poly_swap(Qinv, t); n_poly_clear(t); } Qinv->length = n; _n_poly_normalise(Qinv); } void n_poly_mod_div_series(n_poly_t Q, const n_poly_t A, const n_poly_t B, slong order, nmod_t ctx) { slong Blen = B->length; slong Alen = A->length; if (order < 1 || Blen == 0 || B->coeffs[0] == 0) { flint_throw(FLINT_ERROR, "Exception (n_poly_div_series). Division by zero.\n"); } if (Alen == 0) { n_poly_zero(Q); return; } if (Q != A && Q != B) { n_poly_fit_length(Q, order); _nmod_poly_div_series(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, order, ctx); } else { n_poly_t t; n_poly_init(t); _nmod_poly_div_series(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, order, ctx); n_poly_swap(Q, t); n_poly_clear(t); } Q->length = order; _n_poly_normalise(Q); } void n_poly_mod_scalar_mul_ui(n_poly_t A, const n_poly_t B, mp_limb_t c, nmod_t ctx) { if (c >= ctx.n) { NMOD_RED(c, c, ctx); } if (c == 0 || B->length < 1) { n_poly_zero(A); return; } _n_poly_mod_scalar_mul_nmod(A, B, c, ctx); _n_poly_normalise(A); } /* multiply A by (x^k + c) */ void n_poly_mod_shift_left_scalar_addmul(n_poly_t A, slong k, mp_limb_t c, nmod_t ctx) { mp_limb_t * Acoeffs; slong i; slong Alen = A->length; n_poly_fit_length(A, Alen + k); Acoeffs = A->coeffs; flint_mpn_copyd(Acoeffs + k, Acoeffs, Alen); flint_mpn_zero(Acoeffs, k); for (i = 0; i < A->length; i++) Acoeffs[i] = nmod_addmul(Acoeffs[i], c, Acoeffs[i + k], ctx); A->length = Alen + k; } /* A = B + C*(d1*x+d0) */ void n_poly_mod_addmul_linear( n_poly_t A, const n_poly_t B, const n_poly_t C, mp_limb_t d1, mp_limb_t d0, nmod_t ctx) { slong i; mp_limb_t * Acoeffs, * Bcoeffs, * Ccoeffs; slong Blen = B->length; slong Clen = C->length; slong Alen = FLINT_MAX(B->length, C->length + 1); FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_poly_fit_length(A, Alen); Acoeffs = A->coeffs; Bcoeffs = B->coeffs; Ccoeffs = C->coeffs; for (i = 0; i < Alen; i++) { ulong p1, p0, t0 = 0, t1 = 0, t2 = 0; if (i < Blen) { t0 = Bcoeffs[i]; } if (i < Clen) { umul_ppmm(p1, p0, Ccoeffs[i], d0); add_ssaaaa(t1, t0, t1, t0, p1, p0); } if (0 < i && i - 1 < Clen) { umul_ppmm(p1, p0, Ccoeffs[i - 1], d1); add_sssaaaaaa(t2, t1, t0, t2, t1, t0, 0, p1, p0); } NMOD_RED3(Acoeffs[i], t2, t1, t0, ctx); } A->length = Alen; _n_poly_normalise(A); } /* A = B + C*d0 */ void n_poly_mod_scalar_addmul_nmod( n_poly_t A, const n_poly_t B, const n_poly_t C, mp_limb_t d0, nmod_t ctx) { slong i; mp_limb_t t0, t1; mp_limb_t * Acoeffs, * Bcoeffs, * Ccoeffs; slong Blen = B->length; slong Clen = C->length; slong Alen = FLINT_MAX(B->length, C->length); n_poly_fit_length(A, Alen); Acoeffs = A->coeffs; Bcoeffs = B->coeffs; Ccoeffs = C->coeffs; if (ctx.norm >= (FLINT_BITS + 1)/2) { for (i = 0; i + 2 <= FLINT_MIN(Blen, Clen); i += 2) { NMOD_RED2(t0, 0, Bcoeffs[i + 0] + d0*Ccoeffs[i + 0], ctx); NMOD_RED2(t1, 0, Bcoeffs[i + 1] + d0*Ccoeffs[i + 1], ctx); Acoeffs[i + 0] = t0; Acoeffs[i + 1] = t1; } for ( ; i < FLINT_MIN(Blen, Clen); i++) { NMOD_RED2(Acoeffs[i], 0, Bcoeffs[i] + d0*Ccoeffs[i], ctx); } for ( ; i + 2 <= Clen; i += 2) { NMOD_RED2(t0, 0, d0*Ccoeffs[i + 0], ctx); NMOD_RED2(t1, 0, d0*Ccoeffs[i + 1], ctx); Acoeffs[i + 0] = t0; Acoeffs[i + 1] = t1; } for ( ; i < Clen; i++) { NMOD_RED2(Acoeffs[i], 0, d0*Ccoeffs[i], ctx); } } else { for (i = 0; i < FLINT_MIN(Blen, Clen); i++) { t0 = Bcoeffs[i]; NMOD_ADDMUL(t0, d0, Ccoeffs[i], ctx); Acoeffs[i] = t0; } while (i < Clen) { Acoeffs[i] = nmod_mul(d0, Ccoeffs[i], ctx); i++; } } while (i < Blen) { Acoeffs[i] = Bcoeffs[i]; i++; } A->length = Alen; _n_poly_normalise(A); } ulong n_poly_mod_remove(n_poly_t f, const n_poly_t p, nmod_t ctx) { n_poly_t q, r; ulong i = 0; n_poly_init(q); n_poly_init(r); while (1) { if (f->length < p->length) break; n_poly_mod_divrem(q, r, f, p, ctx); if (r->length == 0) n_poly_swap(q, f); else break; i++; } n_poly_clear(q); n_poly_clear(r); return i; } mp_limb_t _n_poly_eval_pow(n_poly_t P, n_poly_t alphapow, int nlimbs, nmod_t ctx) { mp_limb_t * Pcoeffs = P->coeffs; slong Plen = P->length; mp_limb_t * alpha_powers = alphapow->coeffs; mp_limb_t res; slong k; if (Plen > alphapow->length) { slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); n_poly_fit_length(alphapow, Plen); alphapow->length = Plen; alpha_powers = alphapow->coeffs; for (k = oldlength; k < Plen; k++) alpha_powers[k] = nmod_mul(alpha_powers[k - 1], alpha_powers[1], ctx); } NMOD_VEC_DOT(res, k, Plen, Pcoeffs[k], alpha_powers[k], ctx, nlimbs); return res; } mp_limb_t n_poly_mod_eval_pow(n_poly_t P, n_poly_t alphapow, nmod_t ctx) { int nlimbs = _nmod_vec_dot_bound_limbs(P->length, ctx); return _n_poly_eval_pow(P, alphapow, nlimbs, ctx); } void n_poly_mod_eval2_pow( mp_limb_t * vp, mp_limb_t * vm, const n_poly_t P, n_poly_t alphapow, nmod_t ctx) { const mp_limb_t * Pcoeffs = P->coeffs; slong Plen = P->length; mp_limb_t * alpha_powers = alphapow->coeffs; mp_limb_t p1, p0, a0, a1, a2, q1, q0, b0, b1, b2; slong k; a0 = a1 = a2 = 0; b0 = b1 = b2 = 0; if (Plen > alphapow->length) { slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); n_poly_fit_length(alphapow, Plen); for (k = oldlength; k < Plen; k++) { alphapow->coeffs[k] = nmod_mul(alphapow->coeffs[k - 1], alphapow->coeffs[1], ctx); } alphapow->length = Plen; alpha_powers = alphapow->coeffs; } for (k = 0; k + 2 <= Plen; k += 2) { umul_ppmm(p1, p0, Pcoeffs[k + 0], alpha_powers[k + 0]); umul_ppmm(q1, q0, Pcoeffs[k + 1], alpha_powers[k + 1]); add_sssaaaaaa(a2, a1, a0, a2, a1, a0, 0, p1, p0); add_sssaaaaaa(b2, b1, b0, b2, b1, b0, 0, q1, q0); } if (k < Plen) { umul_ppmm(p1, p0, Pcoeffs[k + 0], alpha_powers[k + 0]); add_sssaaaaaa(a2, a1, a0, a2, a1, a0, 0, p1, p0); k++; } FLINT_ASSERT(k == Plen); NMOD_RED3(p0, a2, a1, a0, ctx); NMOD_RED3(q0, b2, b1, b0, ctx); *vp = nmod_add(p0, q0, ctx); *vm = nmod_sub(p0, q0, ctx); } mp_limb_t n_poly_mod_eval_step2( n_poly_t Acur, const n_poly_t Ainc, nmod_t mod) { slong i, Alen = Acur->length; mp_limb_t * cur = Acur->coeffs; const mp_limb_t * inc = Ainc->coeffs; ulong t0, t1, t2, p0, p1; FLINT_ASSERT(2*Alen == Ainc->length); t2 = t1 = t0 = 0; for (i = 0; i < Alen; i++) { umul_ppmm(p1, p0, cur[i], inc[2*i + 0]); add_sssaaaaaa(t2, t1, t0, t2, t1, t0, 0, p1, p0); cur[i] = nmod_mul(cur[i], inc[2*i + 1], mod); } NMOD_RED3(t0, t2, t1, t0, mod); return t0; } flint-3.1.3/src/n_poly/n_poly_stack.c000066400000000000000000000032051461254215100175530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" void n_poly_stack_init(n_poly_stack_t S) { S->alloc = 0; S->array = NULL; S->top = 0; } void n_poly_stack_clear(n_poly_stack_t S) { slong i; FLINT_ASSERT(S->top == 0); for (i = 0; i < S->alloc; i++) { n_poly_clear(S->array[i]); flint_free(S->array[i]); } if (S->array) flint_free(S->array); } /* insure that k slots are available after top and return pointer to top */ n_poly_struct ** n_poly_stack_fit_request(n_poly_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->alloc >= S->top); if (S->top + k > S->alloc) { newalloc = FLINT_MAX(WORD(1), S->top + k); if (S->array) { S->array = (n_poly_struct **) flint_realloc(S->array, newalloc*sizeof(n_poly_struct*)); } else { S->array = (n_poly_struct **) flint_malloc( newalloc*sizeof(n_poly_struct*)); } for (i = S->alloc; i < newalloc; i++) { S->array[i] = (n_poly_struct *) flint_malloc(sizeof(n_poly_struct)); n_poly_init(S->array[i]); } S->alloc = newalloc; } return S->array + S->top; } flint-3.1.3/src/n_poly/n_polyu.c000066400000000000000000000035521461254215100165600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpn_extras.h" #include "nmod_vec.h" #include "mpoly.h" void n_polyu_clear(n_polyu_t A) { if (A->alloc > 0) { flint_free(A->exps); flint_free(A->coeffs); } else { FLINT_ASSERT(A->exps == NULL); FLINT_ASSERT(A->coeffs == NULL); } } void n_polyu_realloc(n_polyu_t A, slong len) { slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; if (old_alloc > 0) { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (mp_limb_t *) flint_realloc(A->coeffs, new_alloc*sizeof(mp_limb_t)); } else { FLINT_ASSERT(A->exps == NULL); FLINT_ASSERT(A->coeffs == NULL); A->exps = (ulong *) flint_malloc(new_alloc*sizeof(ulong)); A->coeffs = (mp_limb_t *) flint_malloc(new_alloc*sizeof(mp_limb_t)); } A->alloc = new_alloc; } void n_polyu3_degrees( slong * deg0, slong * deg1, slong * deg2, const n_polyu_t A) { slong i; ulong m; ulong mask = mpoly_overflow_mask_sp(FLINT_BITS/3); if (A->length <= 0) { *deg0 = *deg1 = *deg2 = -1; return; } m = A->exps[0]; for (i = 1; i < A->length; i++) m = mpoly_monomial_max1(m, A->exps[i], FLINT_BITS/3, mask); *deg0 = extract_exp(m, 2, 3); *deg1 = extract_exp(m, 1, 3); *deg2 = extract_exp(m, 0, 3); } flint-3.1.3/src/n_poly/n_polyu1n_gcd.c000066400000000000000000000351521461254215100176350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" static void n_polyu1n_mod_interp_reduce_2sm_poly( n_poly_t E, n_poly_t F, const n_polyun_t A, n_poly_t alphapow, nmod_t ctx) { slong i; mp_limb_t u, v; n_poly_zero(E); n_poly_zero(F); for (i = 0; i < A->length; i++) { n_poly_mod_eval2_pow(&u, &v, A->coeffs + i, alphapow, ctx); n_poly_set_coeff(E, A->exps[i], u); n_poly_set_coeff(F, A->exps[i], v); } } static void n_polyu1n_mod_interp_lift_2sm_poly( slong * lastdeg, n_polyun_t F, const n_poly_t A, const n_poly_t B, mp_limb_t alpha, nmod_t ctx) { slong lastlen = 0; slong Fi, Aexp, Bexp; const mp_limb_t * Acoeffs = A->coeffs; const mp_limb_t * Bcoeffs = B->coeffs; slong e; mp_limb_t d0 = (1 + ctx.n)/2; mp_limb_t d1 = nmod_inv(nmod_add(alpha, alpha, ctx), ctx); mp_limb_t Avalue, Bvalue, u, v; Aexp = n_poly_degree(A); Bexp = n_poly_degree(B); n_polyun_fit_length(F, FLINT_MAX(Aexp, Bexp) + 1); Fi = 0; while (Aexp >= 0 || Bexp >= 0) { e = Aexp; Avalue = 0; Bvalue = 0; if (Aexp == Bexp) { Avalue = Acoeffs[Aexp]; Bvalue = Bcoeffs[Bexp]; } else if (Aexp > Bexp) { Avalue = Acoeffs[Aexp]; } else { FLINT_ASSERT(Bexp > Aexp); e = Bexp; Bvalue = Bcoeffs[Bexp]; } FLINT_ASSERT(Avalue != 0 || Bvalue != 0); u = nmod_add(Avalue, Bvalue, ctx); v = nmod_sub(Avalue, Bvalue, ctx); u = nmod_mul(u, d0, ctx); v = nmod_mul(v, d1, ctx); FLINT_ASSERT(Fi < F->alloc); F->exps[Fi] = e; FLINT_ASSERT(u != 0 || v != 0); n_poly_fit_length(F->coeffs + Fi, 2); F->coeffs[Fi].coeffs[0] = u; F->coeffs[Fi].coeffs[1] = v; F->coeffs[Fi].length = 1 + (v != 0); lastlen = FLINT_MAX(lastlen, F->coeffs[Fi].length); Fi++; if (e == Aexp) { do { Aexp--; } while (Aexp >= 0 && Acoeffs[Aexp] == 0); } if (e == Bexp) { do { Bexp--; } while (Bexp >= 0 && Bcoeffs[Bexp] == 0); } } F->length = Fi; *lastdeg = lastlen - 1; return; } static int n_polyu1n_mod_interp_crt_2sm_poly( slong * lastdeg, n_polyun_t F, n_polyun_t T, const n_poly_t A, const n_poly_t B, const n_poly_t modulus, n_poly_t alphapow, nmod_t ctx) { int changed = 0, Finc; slong lastlen = 0; n_poly_struct * Fvalue; mp_limb_t u, v, FvalueA, FvalueB; slong Fi, Ti, Aexp, Bexp, e, fexp; const mp_limb_t * Acoeff = A->coeffs; const mp_limb_t * Bcoeff = B->coeffs; slong Flen = F->length; n_poly_t zero; zero->alloc = 0; zero->length = 0; zero->coeffs = NULL; Fi = 0; Aexp = n_poly_degree(A); Bexp = n_poly_degree(B); n_polyun_fit_length(T, Flen + FLINT_MAX(Aexp, Bexp) + 1); Ti = 0; #if FLINT_WANT_ASSERT u = n_poly_mod_evaluate_nmod(modulus, alphapow->coeffs[1], ctx); u = nmod_mul(u, alphapow->coeffs[1], ctx); u = nmod_add(u, u, ctx); FLINT_ASSERT(u == 1); v = nmod_neg(alphapow->coeffs[1], ctx); u = n_poly_mod_evaluate_nmod(modulus, v, ctx); u = nmod_mul(u, alphapow->coeffs[1], ctx); u = nmod_add(u, u, ctx); FLINT_ASSERT(u == 1); #endif while (Fi < Flen || Aexp >= 0 || Bexp >= 0) { FLINT_ASSERT(Ti < T->alloc); fexp = e = -WORD(1); if (Fi < Flen) { fexp = e = F->exps[Fi]; FLINT_ASSERT(!n_poly_is_zero(F->coeffs + Fi)); FLINT_ASSERT(n_poly_degree(F->coeffs + Fi) < n_poly_degree(modulus)); } if (Aexp >= 0) { e = FLINT_MAX(e, Aexp); FLINT_ASSERT(Acoeff[Aexp] != 0); } if (Bexp >= 0) { e = FLINT_MAX(e, Bexp); FLINT_ASSERT(Bcoeff[Bexp] != 0); } FLINT_ASSERT(e >= 0); T->exps[Ti] = e; Fvalue = zero; FvalueA = 0; FvalueB = 0; Finc = 0; if (Fi < Flen && e == fexp) { Finc = 1; Fvalue = F->coeffs + Fi; n_poly_mod_eval2_pow(&FvalueA, &FvalueB, Fvalue, alphapow, ctx); } if (e == Aexp) { FvalueA = nmod_sub(FvalueA, Acoeff[Aexp], ctx); } if (e == Bexp) { FvalueB = nmod_sub(FvalueB, Bcoeff[Bexp], ctx); } u = nmod_sub(FvalueB, FvalueA, ctx); v = nmod_add(FvalueB, FvalueA, ctx); v = nmod_mul(v, alphapow->coeffs[1], ctx); v = nmod_neg(v, ctx); changed |= u != 0 || v != 0; n_poly_mod_addmul_linear(T->coeffs + Ti, Fvalue, modulus, u, v, ctx); FLINT_ASSERT(T->coeffs[Ti].length > 0); lastlen = FLINT_MAX(lastlen, T->coeffs[Ti].length); Ti++; Fi += Finc; if (e == Aexp) { do { Aexp--; } while (Aexp >= 0 && Acoeff[Aexp] == 0); } if (e == Bexp) { do { Bexp--; } while (Bexp >= 0 && Bcoeff[Bexp] == 0); } } T->length = Ti; *lastdeg = lastlen - 1; if (changed) n_polyun_swap(T, F); return changed; } int n_polyu1n_mod_gcd_brown_smprime( n_polyun_t G, n_polyun_t Abar, n_polyun_t Bbar, n_polyun_t A, n_polyun_t B, nmod_t ctx, n_poly_polyun_stack_t St) { int success; slong bound; mp_limb_t alpha, temp, gammaevalp, gammaevalm; n_poly_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp; n_poly_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm; n_polyun_struct * T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma; n_poly_struct * modulus, * alphapow, * r; int gstab, astab, bstab, use_stab; #if FLINT_WANT_ASSERT n_poly_t leadA, leadB; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); n_poly_init(leadA); n_poly_init(leadB); n_poly_set(leadA, A->coeffs + 0); n_poly_set(leadB, B->coeffs + 0); #endif n_poly_stack_fit_request(St->poly_stack, 19); cA = n_poly_stack_take_top(St->poly_stack); cB = n_poly_stack_take_top(St->poly_stack); cG = n_poly_stack_take_top(St->poly_stack); cAbar = n_poly_stack_take_top(St->poly_stack); cBbar = n_poly_stack_take_top(St->poly_stack); gamma = n_poly_stack_take_top(St->poly_stack); Aevalp = n_poly_stack_take_top(St->poly_stack); Bevalp = n_poly_stack_take_top(St->poly_stack); Gevalp = n_poly_stack_take_top(St->poly_stack); Abarevalp = n_poly_stack_take_top(St->poly_stack); Bbarevalp = n_poly_stack_take_top(St->poly_stack); Aevalm = n_poly_stack_take_top(St->poly_stack); Bevalm = n_poly_stack_take_top(St->poly_stack); Gevalm = n_poly_stack_take_top(St->poly_stack); Abarevalm = n_poly_stack_take_top(St->poly_stack); Bbarevalm = n_poly_stack_take_top(St->poly_stack); r = n_poly_stack_take_top(St->poly_stack); alphapow = n_poly_stack_take_top(St->poly_stack); modulus = n_poly_stack_take_top(St->poly_stack); n_polyun_stack_fit_request(St->polyun_stack, 1); T = n_polyun_stack_take_top(St->polyun_stack); _n_poly_vec_mod_remove_content(cA, A->coeffs, A->length, ctx); _n_poly_vec_mod_remove_content(cB, B->coeffs, B->length, ctx); n_poly_mod_gcd(cG, cA, cB, ctx); n_poly_mod_divexact(cAbar, cA, cG, ctx); n_poly_mod_divexact(cBbar, cB, cG, ctx); n_poly_mod_gcd(gamma, A->coeffs + 0, B->coeffs + 0, ctx); ldegA = _n_poly_vec_max_degree(A->coeffs, A->length); ldegB = _n_poly_vec_max_degree(B->coeffs, B->length); deggamma = n_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1)); n_poly_one(modulus); use_stab = 1; gstab = bstab = astab = 0; alpha = (ctx.n - 1)/2; choose_prime: /* primes are v - alpha, v + alpha */ if (alpha < 2) { success = 0; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha < ctx.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; n_poly_mod_eval2_pow(&gammaevalp, &gammaevalm, gamma, alphapow, ctx); if (gammaevalp == 0 || gammaevalm == 0) goto choose_prime; /* evaluation point should kill neither A nor B */ n_polyu1n_mod_interp_reduce_2sm_poly(Aevalp, Aevalm, A, alphapow, ctx); n_polyu1n_mod_interp_reduce_2sm_poly(Bevalp, Bevalm, B, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); if (use_stab && gstab) { slong Gdeg; n_polyu1n_mod_interp_reduce_2sm_poly(Gevalp, Gevalm, G, alphapow, ctx); Gdeg = G->exps[0]; success = 1; success = success && n_poly_degree(Gevalp) == Gdeg; success = success && n_poly_degree(Gevalm) == Gdeg; success = success && Gevalp->coeffs[Gdeg] == gammaevalp; success = success && Gevalm->coeffs[Gdeg] == gammaevalm; success = success && (n_poly_mod_divrem(Abarevalp, r, Aevalp, Gevalp, ctx), r->length == 0); success = success && (n_poly_mod_divrem(Abarevalm, r, Aevalm, Gevalm, ctx), r->length == 0); success = success && (n_poly_mod_divrem(Bbarevalp, r, Bevalp, Gevalp, ctx), r->length == 0); success = success && (n_poly_mod_divrem(Bbarevalm, r, Bevalm, Gevalm, ctx), r->length == 0); if (!success) { use_stab = 0; n_poly_one(modulus); goto choose_prime; } _n_poly_mod_scalar_mul_nmod_inplace(Abarevalp, gammaevalp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Abarevalm, gammaevalm, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Bbarevalp, gammaevalp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Bbarevalm, gammaevalm, ctx); } else { n_poly_mod_gcd(Gevalp, Aevalp, Bevalp, ctx); n_poly_mod_divexact(Abarevalp, Aevalp, Gevalp, ctx); n_poly_mod_divexact(Bbarevalp, Bevalp, Gevalp, ctx); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx); n_poly_mod_divexact(Abarevalm, Aevalm, Gevalm, ctx); n_poly_mod_divexact(Bbarevalm, Bevalm, Gevalm, ctx); gstab = astab = bstab = 0; } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); if (n_poly_degree(Gevalp) == 0 || n_poly_degree(Gevalm) == 0) { n_polyun_one(G); n_polyun_swap(Abar, A); n_polyun_swap(Bbar, B); goto successful_put_content; } if (n_poly_degree(Gevalp) != n_poly_degree(Gevalm)) { goto choose_prime; } /* the Geval have matching degrees */ if (n_poly_degree(modulus) > 0) { FLINT_ASSERT(G->length > 0); if (n_poly_degree(Gevalp) > G->exps[0]) { goto choose_prime; } else if (n_poly_degree(Gevalp) < G->exps[0]) { n_poly_one(modulus); } } /* update interpolants */ _n_poly_mod_scalar_mul_nmod_inplace(Gevalp, gammaevalp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(Gevalm, gammaevalm, ctx); if (n_poly_degree(modulus) > 0) { temp = n_poly_mod_evaluate_nmod(modulus, alpha, ctx); FLINT_ASSERT(temp == n_poly_mod_evaluate_nmod(modulus, ctx.n - alpha, ctx)); temp = nmod_mul(temp, alpha, ctx); temp = nmod_add(temp, temp, ctx); temp = nmod_inv(temp, ctx); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, ctx); gstab = gstab || !n_polyu1n_mod_interp_crt_2sm_poly(&ldegG, G, T, Gevalp, Gevalm, modulus, alphapow, ctx); n_polyu1n_mod_interp_crt_2sm_poly(&ldegAbar, Abar, T, Abarevalp, Abarevalm, modulus, alphapow, ctx); n_polyu1n_mod_interp_crt_2sm_poly(&ldegBbar, Bbar, T, Bbarevalp, Bbarevalm, modulus, alphapow, ctx); } else { n_polyu1n_mod_interp_lift_2sm_poly(&ldegG, G, Gevalp, Gevalm, alpha, ctx); n_polyu1n_mod_interp_lift_2sm_poly(&ldegAbar, Abar, Abarevalp, Abarevalm, alpha, ctx); n_polyu1n_mod_interp_lift_2sm_poly(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, alpha, ctx); gstab = astab = bstab = 0; } temp = ctx.n - nmod_mul(alpha, alpha, ctx); n_poly_mod_shift_left_scalar_addmul(modulus, 2, temp, ctx); if (n_poly_degree(modulus) < bound) goto choose_prime; FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if (deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar) { goto successful; } n_poly_one(modulus); goto choose_prime; successful: _n_poly_vec_mod_remove_content(modulus, G->coeffs, G->length, ctx); _n_poly_vec_mod_divexact_poly(Abar->coeffs, Abar->length, G->coeffs + 0, ctx); _n_poly_vec_mod_divexact_poly(Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx); successful_put_content: _n_poly_vec_mod_mul_poly(G->coeffs, G->length, cG, ctx); _n_poly_vec_mod_mul_poly(Abar->coeffs, Abar->length, cAbar, ctx); _n_poly_vec_mod_mul_poly(Bbar->coeffs, Bbar->length, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { FLINT_ASSERT(1 == n_poly_lead(G->coeffs + 0)); n_poly_mod_mul(modulus, G->coeffs + 0, Abar->coeffs + 0, ctx); FLINT_ASSERT(n_poly_equal(modulus, leadA)); n_poly_mod_mul(modulus, G->coeffs + 0, Bbar->coeffs + 0, ctx); FLINT_ASSERT(n_poly_equal(modulus, leadB)); } n_poly_clear(leadA); n_poly_clear(leadB); #endif n_poly_stack_give_back(St->poly_stack, 19); n_polyun_stack_give_back(St->polyun_stack, 1); return success; } flint-3.1.3/src/n_poly/n_polyun.c000066400000000000000000000040261461254215100167330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" int n_polyun_mod_is_canonical(const n_polyun_t A, nmod_t mod) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (!n_poly_mod_is_canonical(A->coeffs + i, mod) || n_poly_is_zero(A->coeffs + i)) { return 0; } if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } void n_polyun_clear(n_polyun_t A) { slong i; for (i = 0; i < A->alloc; i++) n_poly_clear(A->coeffs + i); flint_free(A->coeffs); flint_free(A->exps); } void n_polyun_realloc(n_polyun_t A, slong len) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2); FLINT_ASSERT(A->alloc >= 0); if (len <= A->alloc) return; A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, ulong); A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, n_poly_struct); for (i = old_alloc; i < new_alloc; i++) n_poly_init(A->coeffs + i); A->alloc = new_alloc; } void n_polyun_set(n_polyun_t A, const n_polyun_t B) { slong i; n_polyun_fit_length(A, B->length); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; n_poly_set(A->coeffs + i, B->coeffs + i); } A->length = B->length; } int n_polyun_equal( const n_polyun_t A, const n_polyun_t B) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (A->exps[i] != B->exps[i]) return 0; if (!n_poly_equal(A->coeffs + i, B->coeffs + i)) return 0; } return 1; } flint-3.1.3/src/n_poly/n_polyun_stack.c000066400000000000000000000024161461254215100201210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" void n_polyun_stack_init(n_polyun_stack_t S) { S->alloc = 0; S->array = NULL; S->top = 0; } void n_polyun_stack_clear(n_polyun_stack_t S) { slong i; FLINT_ASSERT(S->top == 0); for (i = 0; i < S->alloc; i++) { n_polyun_clear(S->array[i]); flint_free(S->array[i]); } flint_free(S->array); } n_polyun_struct ** n_polyun_stack_fit_request(n_polyun_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->alloc >= S->top); if (S->top + k > S->alloc) { newalloc = FLINT_MAX(WORD(1), S->top + k); S->array = FLINT_ARRAY_REALLOC(S->array, newalloc, n_polyun_struct *); for (i = S->alloc; i < newalloc; i++) { S->array[i] = FLINT_ARRAY_ALLOC(1, n_polyun_struct); n_polyun_init(S->array[i]); } S->alloc = newalloc; } return S->array + S->top; } flint-3.1.3/src/n_poly/n_tpoly.c000066400000000000000000000022221461254215100165500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" void n_tpoly_fit_length(n_tpoly_t A, slong len) { slong i; if (len <= A->alloc) return; if (len < 2 * A->alloc) len = 2 * A->alloc; if (A->alloc > 0) A->coeffs = (n_bpoly_struct *) flint_realloc(A->coeffs, len * sizeof(n_bpoly_struct)); else A->coeffs = (n_bpoly_struct *) flint_malloc( len * sizeof(n_bpoly_struct)); for (i = A->alloc; i < len; i++) n_bpoly_init(A->coeffs + i); A->alloc = len; } void n_tpoly_clear(n_tpoly_t A) { if (A->alloc > 0) { slong i; for (i = 0; i < A->alloc; i++) n_bpoly_clear(A->coeffs + i); flint_free(A->coeffs); } } flint-3.1.3/src/n_poly/nmod_n_fq_interp.c000066400000000000000000000630141461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "n_poly.h" /* -O3 seems to result in worse code here. Check results for nmod_mpoly_factor/profile/p-factor */ #pragma GCC optimize ("-O2,-funroll-loops") /* conversion between polynomials in coefficient form and point-value form and arithmetic in point-value form */ #define MAC(h, m, l, a, b) \ { \ mp_limb_t p1, p0; \ umul_ppmm(p1, p0, a, b); \ add_sssaaaaaa(h, m, l, h, m, l, 0, p1, p0); \ } /**************** conversion ************************************************/ /* p = 1 mod 4 */ static slong _find_eval_points4( mp_limb_t * list, slong d, nmod_t ctx) { slong i, len; mp_limb_t p = ctx.n; mp_limb_t n; FLINT_ASSERT(d > 0); FLINT_ASSERT((p & UWORD(3)) == 1); list[0] = 1; len = 1; for (n = 2; len < d && n <= (p - 1)/2; n++) { int ok = 1; mp_limb_t mn2 = p - nmod_mul(n, n, ctx); for (i = 0; ok && i < len; i++) ok = (nmod_mul(list[i], list[i], ctx) != mn2); if (ok) list[len++] = n; } return len; } static int _fill_matrices4( mp_limb_t * M, /* length d by 4d */ mp_limb_t * Q, /* length d by 4d+1 */ slong d, nmod_t ctx) { slong i, j; n_poly_t g, h; mp_limb_t * list; mp_limb_t g0i, c; list = FLINT_ARRAY_ALLOC(d, mp_limb_t); if (d != _find_eval_points4(list, d, ctx)) { flint_free(list); return 0; } n_poly_init2(g, 4*d + 4); n_poly_init2(h, 4*d + 4); n_poly_one(g); for (i = 0; i < d; i++) { n_poly_mod_shift_left_scalar_addmul(g, 4, nmod_neg(nmod_pow_ui(list[i], 4, ctx), ctx), ctx); } g0i = nmod_inv(g->coeffs[0], ctx); for (i = 0; i < d; i++) { FLINT_ASSERT(4*i+4 < g->length); Q[i*(4*d+1) + 0] = nmod_mul(g0i, g->coeffs[4*i+4], ctx); n_poly_mod_div_root(h, g, list[i], ctx); c = n_poly_mod_evaluate_nmod(h, list[i], ctx); c = nmod_mul(list[i], c, ctx); c = nmod_inv(c, ctx); for (j = 0; j < 4*d; j++) { M[i*(4*d) + j] = nmod_pow_ui(list[i], 1+j, ctx); Q[(j/4)*(4*d+1) + 4*i + (j%4) + 1] = nmod_mul(h->coeffs[j], c, ctx); } } n_poly_clear(g); n_poly_clear(h); flint_free(list); return 1; } static void _from_coeffs4( mp_limb_t * v, /* length 4d+1 */ const mp_limb_t * a, slong alen, const mp_limb_t * M, /* length d by 4d */ slong d, mp_limb_t w, nmod_t ctx) { slong i, j; FLINT_ASSERT(0 <= alen); FLINT_ASSERT(alen <= 1 + 4*d); if (alen <= 1) { mp_limb_t t = (alen == 1) ? a[0] : 0; for (i = 0; i < 4*d+1; i++) v[i] = t; return; } v[0] = a[0]; for (i = 0; i < d; i++) { mp_limb_t t1, t2, t3, t4; mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; mp_limb_t c3h, c3m, c3; mp_limb_t c4h, c4m, c4; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; c3h = c3m = c3 = 0; c4h = c4m = c4 = 0; for (j = 0; j + 4 < alen; j += 4) { FLINT_ASSERT(j + 3 < 4*d); MAC(c1h, c1m, c1, a[j + 1], M[j + 0]); MAC(c2h, c2m, c2, a[j + 2], M[j + 1]); MAC(c3h, c3m, c3, a[j + 3], M[j + 2]); MAC(c4h, c4m, c4, a[j + 4], M[j + 3]); } MAC(c1h, c1m, c1, j + 1 < alen ? a[j + 1] : 0, M[j + 0]); MAC(c2h, c2m, c2, j + 2 < alen ? a[j + 2] : 0, M[j + 1]); MAC(c3h, c3m, c3, j + 3 < alen ? a[j + 3] : 0, M[j + 2]); FLINT_ASSERT(j + 4 >= alen); NMOD_RED3(c4, c4h, c4m, c4, ctx); NMOD_RED3(c1, c1h, c1m, c1, ctx); NMOD_RED3(c2, c2h, c2m, c2, ctx); NMOD_RED3(c3, c3h, c3m, c3, ctx); M += 4*d; c4 = nmod_add(c4, a[0], ctx); t1 = nmod_add(c4, c2, ctx); t2 = nmod_sub(c4, c2, ctx); t3 = nmod_add(c1, c3, ctx); t4 = nmod_mul(nmod_sub(c1, c3, ctx), w, ctx); v[4*i + 1] = nmod_add(t1, t3, ctx); v[4*i + 2] = nmod_add(t2, t4, ctx); v[4*i + 3] = nmod_sub(t1, t3, ctx); v[4*i + 4] = nmod_sub(t2, t4, ctx); } } static void _from_coeffs4_n_fq( mp_limb_t * v, /* length 4d+1 */ const mp_limb_t * a, slong alen, const mp_limb_t * M_, /* length d by 4d */ slong D, mp_limb_t w, slong d, nmod_t ctx) { slong i, j, k; const mp_limb_t * Mrow; FLINT_ASSERT(0 <= alen); FLINT_ASSERT(alen <= 1 + 4*D); if (alen <= 1) { if (alen == 1) { for (i = 0; i < 4*D + 1; i++) _n_fq_set(v + d*i, a + d*0, d); } else { _nmod_vec_zero(v, d*(4*D+1)); } return; } _n_fq_set(v + d*0, a + d*0, d); for (k = 0; k < d; k++) { Mrow = M_; for (i = 0; i < D; i++) { mp_limb_t t1, t2, t3, t4; mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; mp_limb_t c3h, c3m, c3; mp_limb_t c4h, c4m, c4; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; c3h = c3m = c3 = 0; c4h = c4m = c4 = 0; for (j = 0; j + 4 < alen; j += 4) { FLINT_ASSERT(j + 3 < 4*D); MAC(c1h, c1m, c1, a[d*(j+1)+k], Mrow[j+0]); MAC(c2h, c2m, c2, a[d*(j+2)+k], Mrow[j+1]); MAC(c3h, c3m, c3, a[d*(j+3)+k], Mrow[j+2]); MAC(c4h, c4m, c4, a[d*(j+4)+k], Mrow[j+3]); } MAC(c1h, c1m, c1, j + 1 < alen ? a[d*(j+1)+k] : 0, Mrow[j+0]); MAC(c2h, c2m, c2, j + 2 < alen ? a[d*(j+2)+k] : 0, Mrow[j+1]); MAC(c3h, c3m, c3, j + 3 < alen ? a[d*(j+3)+k] : 0, Mrow[j+2]); FLINT_ASSERT(j + 4 >= alen); NMOD_RED3(c4, c4h, c4m, c4, ctx); NMOD_RED3(c1, c1h, c1m, c1, ctx); NMOD_RED3(c2, c2h, c2m, c2, ctx); NMOD_RED3(c3, c3h, c3m, c3, ctx); Mrow += 4*D; c4 = nmod_add(c4, a[d*0+k], ctx); t1 = nmod_add(c4, c2, ctx); t2 = nmod_sub(c4, c2, ctx); t3 = nmod_add(c1, c3, ctx); t4 = nmod_mul(nmod_sub(c1, c3, ctx), w, ctx); v[d*(4*i+1)+k] = nmod_add(t1, t3, ctx); v[d*(4*i+2)+k] = nmod_add(t2, t4, ctx); v[d*(4*i+3)+k] = nmod_sub(t1, t3, ctx); v[d*(4*i+4)+k] = nmod_sub(t2, t4, ctx); } } } static void _to_coeffs4( mp_limb_t * a, /* length 4d+1 */ const mp_limb_t * v, /* length 4d+1 */ mp_limb_t * t, /* length 4d */ const mp_limb_t * Q, /* length d by 4d+1 */ slong d, mp_limb_t w, nmod_t ctx) { slong i, j; a[0] = v[0]; for (i = 0; i < d; i++) { mp_limb_t t2 = nmod_add(v[1+4*i+0], v[1+4*i+2], ctx); mp_limb_t t1 = nmod_sub(v[1+4*i+0], v[1+4*i+2], ctx); mp_limb_t t3 = nmod_add(v[1+4*i+1], v[1+4*i+3], ctx); mp_limb_t t4 = nmod_mul(nmod_sub(v[1+4*i+1], v[1+4*i+3], ctx), w, ctx); t[4*i+0] = nmod_sub(t1, t4, ctx); t[4*i+1] = nmod_sub(t2, t3, ctx); t[4*i+2] = nmod_add(t1, t4, ctx); t[4*i+3] = nmod_add(t2, t3, ctx); } for (i = 0; i < d; i++) { mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; mp_limb_t c3h, c3m, c3; mp_limb_t c4h, c4m, c4; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; c3h = c3m = c3 = 0; c4h = c4m = c4 = 0; umul_ppmm(c4m, c4, Q[0], v[0]); for (j = 0; j < d; j++) { MAC(c1h, c1m, c1, t[4*j + 0], Q[4*j + 1]); MAC(c2h, c2m, c2, t[4*j + 1], Q[4*j + 2]); MAC(c3h, c3m, c3, t[4*j + 2], Q[4*j + 3]); MAC(c4h, c4m, c4, t[4*j + 3], Q[4*j + 4]); } Q += 4*d + 1; NMOD_RED3(a[4*i + 1], c1h, c1m, c1, ctx); NMOD_RED3(a[4*i + 2], c2h, c2m, c2, ctx); NMOD_RED3(a[4*i + 3], c3h, c3m, c3, ctx); NMOD_RED3(a[4*i + 4], c4h, c4m, c4, ctx); } } static void _to_coeffs4_n_fq( mp_limb_t * a, /* length 4D+1 */ const mp_limb_t * v, /* length 4D+1 */ mp_limb_t * t, /* length 4D */ const mp_limb_t * Q_, /* length D by 4D+1 */ slong D, mp_limb_t w, slong d, nmod_t ctx) { slong i, j, k; const mp_limb_t * Qrow; _n_fq_set(a + d*0, v + d*0, d); for (k = 0; k < d; k++) { for (i = 0; i < D; i++) { mp_limb_t t2 = nmod_add(v[d*(1+4*i+0)+k], v[d*(1+4*i+2)+k], ctx); mp_limb_t t1 = nmod_sub(v[d*(1+4*i+0)+k], v[d*(1+4*i+2)+k], ctx); mp_limb_t t3 = nmod_add(v[d*(1+4*i+1)+k], v[d*(1+4*i+3)+k], ctx); mp_limb_t t4 = nmod_mul(nmod_sub(v[d*(1+4*i+1)+k], v[d*(1+4*i+3)+k], ctx), w, ctx); t[4*i+0] = nmod_sub(t1, t4, ctx); t[4*i+1] = nmod_sub(t2, t3, ctx); t[4*i+2] = nmod_add(t1, t4, ctx); t[4*i+3] = nmod_add(t2, t3, ctx); } Qrow = Q_; for (i = 0; i < D; i++) { mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; mp_limb_t c3h, c3m, c3; mp_limb_t c4h, c4m, c4; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; c3h = c3m = c3 = 0; c4h = c4m = c4 = 0; umul_ppmm(c4m, c4, Qrow[0], v[d*0+k]); for (j = 0; j < D; j++) { MAC(c1h, c1m, c1, t[4*j+0], Qrow[4*j+1]); MAC(c2h, c2m, c2, t[4*j+1], Qrow[4*j+2]); MAC(c3h, c3m, c3, t[4*j+2], Qrow[4*j+3]); MAC(c4h, c4m, c4, t[4*j+3], Qrow[4*j+4]); } Qrow += 4*D + 1; NMOD_RED3(a[d*(4*i+1)+k], c1h, c1m, c1, ctx); NMOD_RED3(a[d*(4*i+2)+k], c2h, c2m, c2, ctx); NMOD_RED3(a[d*(4*i+3)+k], c3h, c3m, c3, ctx); NMOD_RED3(a[d*(4*i+4)+k], c4h, c4m, c4, ctx); } } } static int _fill_matrices2( mp_limb_t * M, /* length d by 2d */ mp_limb_t * Q, /* length d by 2d+1 */ slong d, nmod_t ctx) { slong i, j; n_poly_t g, h; mp_limb_t g0i, c; if (2*d >= ctx.n) return 0; n_poly_init2(g, 2*d + 2); n_poly_init2(h, 2*d + 2); n_poly_one(g); for (i = 0; i < d; i++) { n_poly_mod_shift_left_scalar_addmul(g, 2, nmod_neg(nmod_pow_ui(i + 1, 2, ctx), ctx), ctx); } g0i = nmod_inv(g->coeffs[0], ctx); for (i = 0; i < d; i++) { FLINT_ASSERT(2*(i+1) < g->length); Q[i*(2*d+1) + 0] = nmod_mul(g0i, g->coeffs[2*(i+1)], ctx); n_poly_mod_div_root(h, g, i + 1, ctx); c = n_poly_mod_evaluate_nmod(h, i + 1, ctx); c = nmod_mul(i + 1, c, ctx); c = nmod_inv(c, ctx); for (j = 0; j < 2*d; j++) { M[i*(2*d) + j] = nmod_pow_ui(i + 1, 1+j, ctx); Q[(j/2)*(2*d+1) + 2*i + (j%2) + 1] = nmod_mul(h->coeffs[j], c, ctx); } } n_poly_clear(g); n_poly_clear(h); return 1; } static void _from_coeffs2( mp_limb_t * v, /* length 2d+1 */ const mp_limb_t * a, /* length alen <= 2d+1 */ slong alen, const mp_limb_t * M, /* length d by 2d */ slong d, nmod_t ctx) { slong i, j; FLINT_ASSERT(0 <= alen); FLINT_ASSERT(alen <= 1 + 2*d); if (alen <= 1) { mp_limb_t t = (alen == 1) ? a[0] : 0; for (i = 0; i < 2*d+1; i++) v[i] = t; return; } v[0] = a[0]; for (i = 0; i < d; i++) { mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; for (j = 0; j + 2 < alen; j += 2) { FLINT_ASSERT(j + 1 < 4*d); MAC(c1h, c1m, c1, a[j + 1], M[j + 0]); MAC(c2h, c2m, c2, a[j + 2], M[j + 1]); } MAC(c1h, c1m, c1, j + 1 < alen ? a[j + 1] : 0, M[j + 0]); FLINT_ASSERT(j + 2 >= alen); NMOD_RED3(c2, c2h, c2m, c2, ctx); NMOD_RED3(c1, c1h, c1m, c1, ctx); M += 2*d; c2 = nmod_add(c2, a[0], ctx); v[2*i + 1] = nmod_add(c2, c1, ctx); v[2*i + 2] = nmod_sub(c2, c1, ctx); } } static void _from_coeffs2_n_fq( mp_limb_t * v, /* length 4D+1 */ const mp_limb_t * a, /* length alen <= 2D+1 */ slong alen, const mp_limb_t * M_, /* length D by 4D */ slong D, slong d, nmod_t ctx) { slong i, j, k; const mp_limb_t * Mrow; FLINT_ASSERT(0 <= alen); FLINT_ASSERT(alen <= 1 + 2*D); if (alen <= 1) { if (alen == 1) { for (i = 0; i < 2*D+1; i++) _n_fq_set(v + d*i, a + d*0, d); } else { _nmod_vec_zero(v, d*(2*D+1)); } return; } _n_fq_set(v + d*0, a + d*0, d); for (k = 0; k < d; k++) { Mrow = M_; for (i = 0; i < D; i++) { mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; for (j = 0; j + 2 < alen; j += 2) { FLINT_ASSERT(j + 1 < 4*D); MAC(c1h, c1m, c1, a[d*(j+1)+k], Mrow[j+0]); MAC(c2h, c2m, c2, a[d*(j+2)+k], Mrow[j+1]); } MAC(c1h, c1m, c1, j + 1 < alen ? a[d*(j+1)+k] : 0, Mrow[j+0]); FLINT_ASSERT(j + 2 >= alen); NMOD_RED3(c2, c2h, c2m, c2, ctx); NMOD_RED3(c1, c1h, c1m, c1, ctx); Mrow += 2*D; c2 = nmod_add(c2, a[d*0+k], ctx); v[d*(2*i+1)+k] = nmod_add(c2, c1, ctx); v[d*(2*i+2)+k] = nmod_sub(c2, c1, ctx); } } } static void _to_coeffs2( mp_limb_t * a, /* length 2d+1 */ const mp_limb_t * v, /* length 2d+1 */ mp_limb_t * t, /* length 2d */ const mp_limb_t * Q, /* length d by 2d+1 */ slong d, nmod_t ctx) { slong i, j; a[0] = v[0]; for (i = 0; i < d; i++) { t[2*i+0] = nmod_sub(v[1+2*i+0], v[1+2*i+1], ctx); t[2*i+1] = nmod_add(v[1+2*i+0], v[1+2*i+1], ctx); } for (i = 0; i < d; i++) { mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; umul_ppmm(c2m, c2, Q[0], v[0]); for (j = 0; j < d; j++) { MAC(c1h, c1m, c1, t[2*j + 0], Q[2*j + 1]); MAC(c2h, c2m, c2, t[2*j + 1], Q[2*j + 2]); } Q += 2*d + 1; NMOD_RED3(a[2*i + 1], c1h, c1m, c1, ctx); NMOD_RED3(a[2*i + 2], c2h, c2m, c2, ctx); } } static void _to_coeffs2_n_fq( mp_limb_t * a, /* length 2d+1 */ const mp_limb_t * v, /* length 2d+1 */ mp_limb_t * t, /* length 2d */ const mp_limb_t * Q_, /* length d by 2d+1 */ slong D, slong d, nmod_t ctx) { slong i, j, k; const mp_limb_t * Qrow; _n_fq_set(a + d*0, v + d*0, d); for (k = 0; k < d; k++) { for (i = 0; i < D; i++) { t[2*i+0] = nmod_sub(v[d*(1+2*i+0)+k], v[d*(1+2*i+1)+k], ctx); t[2*i+1] = nmod_add(v[d*(1+2*i+0)+k], v[d*(1+2*i+1)+k], ctx); } Qrow = Q_; for (i = 0; i < D; i++) { mp_limb_t c1h, c1m, c1; mp_limb_t c2h, c2m, c2; c1h = c1m = c1 = 0; c2h = c2m = c2 = 0; umul_ppmm(c2m, c2, Qrow[0], v[d*0+k]); for (j = 0; j < D; j++) { MAC(c1h, c1m, c1, t[2*j+0], Qrow[2*j+1]); MAC(c2h, c2m, c2, t[2*j+1], Qrow[2*j+2]); } Qrow += 2*D + 1; NMOD_RED3(a[d*(2*i+1)+k], c1h, c1m, c1, ctx); NMOD_RED3(a[d*(2*i+2)+k], c2h, c2m, c2, ctx); } } } void nmod_eval_interp_init(nmod_eval_interp_t E) { E->M = NULL; E->T = NULL; E->Q = NULL; E->array = NULL; E->alloc = 0; E->d = 0; E->radix = 0; E->w = 0; } void nmod_eval_interp_clear(nmod_eval_interp_t E) { if (E->alloc > 0) flint_free(E->array); } int nmod_eval_interp_set_degree_modulus( nmod_eval_interp_t E, slong deg, nmod_t ctx) { slong d, new_alloc; mp_limb_t p = ctx.n; FLINT_ASSERT(deg >= 0); if (p < 3 || (p % 2) == 0 || deg >= p) return 0; if ((p % 4) == 1) { d = (deg + 3)/4; d = FLINT_MAX(d, 1); new_alloc = d*(4*d) + 4*d + d*(4*d + 1); if (E->alloc > 0) E->array = flint_realloc(E->array, new_alloc*sizeof(mp_limb_t)); else E->array = flint_malloc(new_alloc*sizeof(mp_limb_t)); E->radix = 4; E->alloc = new_alloc; E->d = d; E->M = E->array; E->T = E->M + d*(4*d); E->Q = E->T + 4*d; E->w = n_sqrtmod(p - 1, p); return _fill_matrices4(E->M, E->Q, d, ctx); } else { d = (deg + 1)/2; d = FLINT_MAX(d, 1); new_alloc = d*(2*d) + 2*d + d*(2*d + 1); if (E->alloc > 0) E->array = flint_realloc(E->array, new_alloc*sizeof(mp_limb_t)); else E->array = flint_malloc(new_alloc*sizeof(mp_limb_t)); E->radix = 2; E->alloc = new_alloc; E->d = d; E->M = E->array; E->T = E->M + d*(2*d); E->Q = E->T + 2*d; E->w = -UWORD(1); return _fill_matrices2(E->M, E->Q, d, ctx); } } static void nmod_eval_interp_to_coeffs( mp_limb_t * a, const mp_limb_t * v, nmod_eval_interp_t E, nmod_t ctx) { if (E->radix == 4) _to_coeffs4(a, v, E->T, E->Q, E->d, E->w, ctx); else _to_coeffs2(a, v, E->T, E->Q, E->d, ctx); } static void nmod_eval_interp_from_coeffs( mp_limb_t * v, const mp_limb_t * a, slong alen, nmod_eval_interp_t E, nmod_t ctx) { if (E->radix == 4) _from_coeffs4(v, a, alen, E->M, E->d, E->w, ctx); else _from_coeffs2(v, a, alen, E->M, E->d, ctx); } static void nmod_eval_interp_to_coeffs_n_fq( mp_limb_t * a, const mp_limb_t * v, nmod_eval_interp_t E, slong d, nmod_t ctx) { if (E->radix == 4) _to_coeffs4_n_fq(a, v, E->T, E->Q, E->d, E->w, d, ctx); else _to_coeffs2_n_fq(a, v, E->T, E->Q, E->d, d, ctx); } static void nmod_eval_interp_from_coeffs_n_fq( mp_limb_t * v, const mp_limb_t * a, slong alen, nmod_eval_interp_t E, slong d, nmod_t ctx) { if (E->radix == 4) _from_coeffs4_n_fq(v, a, alen, E->M, E->d, E->w, d, ctx); else _from_coeffs2_n_fq(v, a, alen, E->M, E->d, d, ctx); } /********** conversion over Fp **********/ void nmod_eval_interp_to_coeffs_poly( n_poly_t a, const n_poly_t v, nmod_eval_interp_t E, nmod_t ctx) { slong l = nmod_eval_interp_eval_length(E); if (v->length == 0) { a->length = 0; return; } FLINT_ASSERT(v->length == l); n_poly_fit_length(a, l); nmod_eval_interp_to_coeffs(a->coeffs, v->coeffs, E, ctx); a->length = l; _n_poly_normalise(a); } void nmod_eval_interp_from_coeffs_poly( n_poly_t v, const n_poly_t a, nmod_eval_interp_t E, nmod_t ctx) { slong l = nmod_eval_interp_eval_length(E); if (a->length == 0) { v->length = 0; return; } n_poly_fit_length(v, l); v->length = l; nmod_eval_interp_from_coeffs(v->coeffs, a->coeffs, a->length, E, ctx); } /********** conversion over Fq **********/ void nmod_eval_interp_to_coeffs_n_fq_poly( n_fq_poly_t a, const n_fq_poly_t v, nmod_eval_interp_t E, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong l = nmod_eval_interp_eval_length(E); if (v->length == 0) { a->length = 0; return; } FLINT_ASSERT(v->length == l); n_poly_fit_length(a, d*l); nmod_eval_interp_to_coeffs_n_fq(a->coeffs, v->coeffs, E, d, ctx->mod); a->length = l; _n_fq_poly_normalise(a, d); } void nmod_eval_interp_from_coeffs_n_fq_poly( n_fq_poly_t v, const n_fq_poly_t a, nmod_eval_interp_t E, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong l = nmod_eval_interp_eval_length(E); if (a->length == 0) { v->length = 0; return; } n_poly_fit_length(v, d*l); v->length = l; nmod_eval_interp_from_coeffs_n_fq(v->coeffs, a->coeffs, a->length, E, d, ctx->mod); } /*********** arithmetic *****************************************************/ /* a += b */ void nmod_evals_add_inplace( n_poly_t a, n_poly_t b, slong len, nmod_t ctx) { slong i; if (b->length == 0) return; n_poly_fit_length(a, len); if (a->length == 0) { _nmod_vec_set(a->coeffs, b->coeffs, len); a->length = len; return; } for (i = 0; i < len; i++) a->coeffs[i] = nmod_add(a->coeffs[i], b->coeffs[i], ctx); a->length = _nmod_vec_is_zero(a->coeffs, len) ? 0 : len; } /* a = b*c */ void nmod_evals_mul( n_poly_t a, n_poly_t b, n_poly_t c, slong len, nmod_t ctx) { slong i; if (b->length == 0 || c->length == 0) { a->length = 0; return; } n_poly_fit_length(a, len); for (i = 0; i < len; i++) a->coeffs[i] = nmod_mul(b->coeffs[i], c->coeffs[i], ctx); a->length = _nmod_vec_is_zero(a->coeffs, len) ? 0 : len; } /* a += b*c */ void nmod_evals_addmul( n_poly_t a, n_poly_t b, n_poly_t c, slong len, nmod_t ctx) { slong i; if (b->length == 0 || c->length == 0) return; if (a->length == 0) { nmod_evals_mul(a, b, c, len, ctx); return; } for (i = 0; i < len; i++) NMOD_ADDMUL(a->coeffs[i], b->coeffs[i], c->coeffs[i], ctx); a->length = _nmod_vec_is_zero(a->coeffs, len) ? 0 : len; } void nmod_evals_fmma( n_poly_t a, n_poly_t b, n_poly_t c, n_poly_t d, n_poly_t e, slong len, nmod_t ctx) { slong i; if (b->length == 0 || c->length == 0) { nmod_evals_mul(a, d, e, len, ctx); return; } if (d->length == 0 || e->length == 0) { nmod_evals_mul(a, b, c, len, ctx); return; } n_poly_fit_length(a, len); for (i = 0; i < len; i++) { mp_limb_t t = nmod_mul(b->coeffs[i], c->coeffs[i], ctx); NMOD_ADDMUL(t, d->coeffs[i], e->coeffs[i], ctx); a->coeffs[i] = t; } a->length = _nmod_vec_is_zero(a->coeffs, len) ? 0 : len; } /* a += b */ void n_fq_evals_add_inplace( n_fq_poly_t a, n_fq_poly_t b, slong len, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); if (b->length == 0) return; n_poly_fit_length(a, d*len); if (a->length == 0) { _nmod_vec_set(a->coeffs, b->coeffs, d*len); a->length = len; return; } _nmod_vec_add(a->coeffs, a->coeffs, b->coeffs, d*len, ctx->mod); a->length = _nmod_vec_is_zero(a->coeffs, d*len) ? 0 : len; } /* a = b*c */ void n_fq_evals_mul( n_fq_poly_t a, n_fq_poly_t b, n_fq_poly_t c, slong len, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; mp_limb_t * tmp; TMP_INIT; if (b->length == 0 || c->length == 0) { a->length = 0; return; } n_poly_fit_length(a, d*len); TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*N_FQ_MUL_ITCH*sizeof(mp_limb_t)); for (i = 0; i < len; i++) _n_fq_mul(a->coeffs + d*i, b->coeffs + d*i, c->coeffs + d*i, ctx, tmp); a->length = _nmod_vec_is_zero(a->coeffs, d*len) ? 0 : len; TMP_END; } /* a += b*c */ void n_fq_evals_addmul( n_fq_poly_t a, n_fq_poly_t b, n_fq_poly_t c, slong len, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; mp_limb_t * tmp; TMP_INIT; if (b->length == 0 || c->length == 0) return; if (a->length == 0) { n_fq_evals_mul(a, b, c, len, ctx); return; } TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*N_FQ_MUL_ITCH*sizeof(mp_limb_t)); for (i = 0; i < len; i++) _n_fq_addmul(a->coeffs + d*i, a->coeffs + d*i, b->coeffs + d*i, c->coeffs + d*i, ctx, tmp); a->length = _nmod_vec_is_zero(a->coeffs, d*len) ? 0 : len; TMP_END; } void n_fq_evals_fmma( n_fq_poly_t a, n_fq_poly_t b, n_fq_poly_t c, n_fq_poly_t f, n_fq_poly_t e, slong len, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; mp_limb_t * tmp, * t; TMP_INIT; if (b->length == 0 || c->length == 0) { n_fq_evals_mul(a, f, e, len, ctx); return; } if (f->length == 0 || e->length == 0) { n_fq_evals_mul(a, b, c, len, ctx); return; } n_poly_fit_length(a, d*len); TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(d*(1 + N_FQ_MUL_ITCH)*sizeof(mp_limb_t)); t = tmp + d*N_FQ_MUL_ITCH; for (i = 0; i < len; i++) { _n_fq_mul(t, b->coeffs + d*i, c->coeffs + d*i, ctx, tmp); _n_fq_addmul(a->coeffs + d*i, t, f->coeffs + d*i, e->coeffs + d*i, ctx, tmp); } a->length = _nmod_vec_is_zero(a->coeffs, d*len) ? 0 : len; TMP_END; } flint-3.1.3/src/n_poly/nmod_pow_cache.c000066400000000000000000000116271461254215100200420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "n_poly.h" /* hold positive and negative powers of b */ void nmod_pow_cache_start( mp_limb_t b, n_poly_t pos, /* b^0, b^1, b^2, ..., b^50 */ n_poly_t bin, /* b^1, b^2, b^3, b^4, b^8, b^12, ... */ n_poly_t neg) /* b^-0, b^-1, b^-2, ..., b^-50 */ { n_poly_fit_length(pos, 2); pos->length = 2; pos->coeffs[0] = 1; pos->coeffs[1] = b; bin->length = 0; neg->length = 0; } /* return a*b^e */ static mp_limb_t nmod_pow_cache_mulpow_ui_array_bin( mp_limb_t a, mp_limb_t * elimbs, slong elen, n_poly_t bin, mp_limb_t b, nmod_t ctx) { slong ei = 0, i = 0; mp_limb_t e = (ei < elen) ? elimbs[ei] : 0; int bits_left = FLINT_BITS; /* complicated code needed if an odd number of bits per limb */ FLINT_ASSERT((FLINT_BITS % 2) == 0); if (bin->length < 3) { n_poly_fit_length(bin, 3); bin->length = 3; bin->coeffs[0] = b; bin->coeffs[1] = nmod_mul(b, b, ctx); bin->coeffs[2] = nmod_mul(bin->coeffs[1], b, ctx); } while (ei < elen) { FLINT_ASSERT(i <= bin->length); if (i + 3 > bin->length) { FLINT_ASSERT(i >= 3); n_poly_fit_length(bin, bin->length + 3); bin->length += 3; b = nmod_mul(bin->coeffs[i - 2], bin->coeffs[i - 2], ctx); bin->coeffs[i + 0] = b; bin->coeffs[i + 1] = nmod_mul(b, b, ctx); bin->coeffs[i + 2] = nmod_mul(bin->coeffs[i + 1], b, ctx); } if ((e%4) != 0) a = nmod_mul(a, bin->coeffs[i + (e%4) - 1], ctx); i += 3; e = e/4; if (ei + 1 < elen) { bits_left -= 2; if (bits_left <= 0) { ei++; e = elimbs[ei]; bits_left = FLINT_BITS; } } else { if (e == 0) break; } } return a; } /* return a*b^e */ mp_limb_t nmod_pow_cache_mulpow_ui( mp_limb_t a, ulong e, n_poly_t pos, n_poly_t bin, n_poly_t neg, nmod_t ctx) { slong i; mp_limb_t b; FLINT_ASSERT(pos->length >= 2); b = pos->coeffs[1]; if (b <= 1) return (b == 1 || e == 0) ? a : 0; if (e < 50) { n_poly_fit_length(pos, e + 1); i = pos->length; while (i <= e) { pos->coeffs[i] = nmod_mul(b, pos->coeffs[i - 1], ctx); pos->length = ++i; } return nmod_mul(a, pos->coeffs[e], ctx); } return nmod_pow_cache_mulpow_ui_array_bin(a, &e, 1, bin, b, ctx); } /* return a*b^-e, assume ctx.n is prime */ mp_limb_t nmod_pow_cache_mulpow_neg_ui( mp_limb_t a, ulong e, n_poly_t pos, n_poly_t bin, n_poly_t neg, nmod_t ctx) { slong i; mp_limb_t b; FLINT_ASSERT(pos->length >= 2); b = pos->coeffs[1]; if (b <= 1) return (b == 1 || e == 0) ? a : 0; if (e < 50) { if (neg->length < 2) { n_poly_fit_length(neg, 2); neg->length = 2; neg->coeffs[0] = 1; neg->coeffs[1] = nmod_inv(b, ctx); } n_poly_fit_length(neg, e + 1); i = neg->length; while (i <= e) { neg->coeffs[i] = nmod_mul(neg->coeffs[1], neg->coeffs[i - 1], ctx); neg->length = ++i; } return nmod_mul(a, neg->coeffs[e], ctx); } if (e >= ctx.n) e = e % (ctx.n - 1); e = ctx.n - 1 - e; return nmod_pow_cache_mulpow_ui(a, e, pos, bin, neg, ctx); } /* return a*b^-e */ mp_limb_t nmod_pow_cache_mulpow_fmpz( mp_limb_t a, const fmpz_t e, n_poly_t pos, n_poly_t bin, n_poly_t neg, nmod_t ctx) { mp_limb_t b = pos->coeffs[1]; FLINT_ASSERT(pos->length >= 2); if (b <= 1) return (b == 1 || fmpz_is_zero(e)) ? a : 0; if (!COEFF_IS_MPZ(*e)) { if (*e >= 0) return nmod_pow_cache_mulpow_ui(a, *e, pos, bin, neg, ctx); else return nmod_pow_cache_mulpow_neg_ui(a, -*e, pos, bin, neg, ctx); } else { if (COEFF_TO_PTR(*e)->_mp_size >= 0) return nmod_pow_cache_mulpow_ui_array_bin(a, COEFF_TO_PTR(*e)->_mp_d, COEFF_TO_PTR(*e)->_mp_size, bin, b, ctx); else return nmod_pow_cache_mulpow_ui(a, fmpz_fdiv_ui(e, ctx.n - 1), pos, bin, neg, ctx); } } flint-3.1.3/src/n_poly/test/000077500000000000000000000000001461254215100157015ustar00rootroot00000000000000flint-3.1.3/src/n_poly/test/main.c000066400000000000000000000020071461254215100167700ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-n_fq_poly_add.c" #include "t-n_fq_poly_divrem.c" #include "t-n_fq_poly_gcd.c" #include "t-n_fq_poly_mul.c" #include "t-n_fq_poly_sub.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(n_fq_poly_add), TEST_FUNCTION(n_fq_poly_divrem), TEST_FUNCTION(n_fq_poly_gcd), TEST_FUNCTION(n_fq_poly_mul), TEST_FUNCTION(n_fq_poly_sub), }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/n_poly/test/t-n_fq_poly_add.c000066400000000000000000000043211461254215100211040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" TEST_FUNCTION_START(n_fq_poly_add, state) { slong i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_ctx_t ctx; n_poly_t a, b, c, d, e; fq_nmod_poly_t A, B, C; fq_nmod_ctx_init_randtest(ctx, state, 3); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(d); n_poly_init(e); fq_nmod_poly_init(A, ctx); fq_nmod_poly_init(B, ctx); fq_nmod_poly_init(C, ctx); for (j = 0; j < 10; j++) { n_fq_poly_randtest(a, state, n_randint(state, 20), ctx); n_fq_poly_randtest(b, state, n_randint(state, 20), ctx); n_fq_poly_randtest(c, state, n_randint(state, 20), ctx); n_fq_poly_randtest(d, state, n_randint(state, 20), ctx); n_fq_poly_get_fq_nmod_poly(B, b, ctx); n_fq_poly_get_fq_nmod_poly(C, c, ctx); fq_nmod_poly_add(A, B, C, ctx); n_fq_poly_set_fq_nmod_poly(a, A, ctx); n_fq_poly_add(d, b, c, ctx); n_fq_poly_set(e, b, ctx); n_fq_poly_add(b, b, c, ctx); n_fq_poly_add(c, e, c, ctx); if (!n_fq_poly_equal(a, d, ctx) || !n_fq_poly_equal(a, b, ctx) || !n_fq_poly_equal(a, c, ctx)) { flint_printf("FAIL\n i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(d); n_poly_clear(e); fq_nmod_poly_clear(A, ctx); fq_nmod_poly_clear(B, ctx); fq_nmod_poly_clear(C, ctx); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/n_poly/test/t-n_fq_poly_divrem.c000066400000000000000000000050771461254215100216530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_poly.h" #include "n_poly.h" TEST_FUNCTION_START(n_fq_poly_divrem, state) { slong i, j; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fq_nmod_ctx_t ctx; n_poly_t a, b, c, d, e, f, q, r; fq_nmod_poly_t A, B, Q, R; fq_nmod_ctx_init_randtest(ctx, state, 3); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(d); n_poly_init(e); n_poly_init(f); n_poly_init(q); n_poly_init(r); fq_nmod_poly_init(A, ctx); fq_nmod_poly_init(B, ctx); fq_nmod_poly_init(Q, ctx); fq_nmod_poly_init(R, ctx); for (j = 0; j < 10; j++) { n_fq_poly_randtest(a, state, n_randint(state, 20), ctx); n_fq_poly_randtest(b, state, n_randint(state, 15), ctx); n_fq_poly_randtest(c, state, n_randint(state, 20), ctx); n_fq_poly_randtest(d, state, n_randint(state, 20), ctx); n_fq_poly_randtest(e, state, n_randint(state, 20), ctx); n_fq_poly_randtest(f, state, n_randint(state, 20), ctx); if (n_poly_is_zero(b)) n_fq_poly_one(b, ctx); n_fq_poly_get_fq_nmod_poly(A, a, ctx); n_fq_poly_get_fq_nmod_poly(B, b, ctx); fq_nmod_poly_divrem(Q, R, A, B, ctx); n_fq_poly_set_fq_nmod_poly(q, Q, ctx); n_fq_poly_set_fq_nmod_poly(r, R, ctx); n_fq_poly_divrem(c, d, a, b, ctx); n_fq_poly_divrem(c, d, a, b, ctx); if (!n_fq_poly_equal(c, q, ctx) || !n_fq_poly_equal(d, r, ctx)) { flint_printf("FAIL\n i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(d); n_poly_clear(e); n_poly_clear(f); n_poly_clear(q); n_poly_clear(r); fq_nmod_poly_clear(A, ctx); fq_nmod_poly_clear(B, ctx); fq_nmod_poly_clear(Q, ctx); fq_nmod_poly_clear(R, ctx); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/n_poly/test/t-n_fq_poly_gcd.c000066400000000000000000000045201461254215100211120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_poly.h" #include "n_poly.h" TEST_FUNCTION_START(n_fq_poly_gcd, state) { slong i, j; for (i = 0; i < 200 * flint_test_multiplier(); i++) { fq_nmod_ctx_t ctx; n_poly_t a, b, c, d, e; fq_nmod_poly_t A, B, C; fq_nmod_ctx_init_randtest(ctx, state, 3); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(d); n_poly_init(e); fq_nmod_poly_init(A, ctx); fq_nmod_poly_init(B, ctx); fq_nmod_poly_init(C, ctx); for (j = 0; j < 5; j++) { n_fq_poly_randtest(a, state, n_randint(state, 15), ctx); n_fq_poly_randtest(b, state, n_randint(state, 15), ctx); n_fq_poly_randtest(c, state, n_randint(state, 15), ctx); n_fq_poly_randtest(d, state, n_randint(state, 15), ctx); n_fq_poly_randtest(e, state, n_randint(state, 15), ctx); n_fq_poly_mul(b, b, e, ctx); n_fq_poly_mul(c, c, e, ctx); n_fq_poly_get_fq_nmod_poly(B, b, ctx); n_fq_poly_get_fq_nmod_poly(C, c, ctx); fq_nmod_poly_gcd(A, B, C, ctx); n_fq_poly_set_fq_nmod_poly(a, A, ctx); n_fq_poly_gcd(d, b, c, ctx); n_fq_poly_set(e, b, ctx); n_fq_poly_gcd(b, b, c, ctx); n_fq_poly_gcd(c, e, c, ctx); if (!n_fq_poly_equal(a, d, ctx) || !n_fq_poly_equal(a, b, ctx) || !n_fq_poly_equal(a, c, ctx)) { flint_printf("FAIL\n i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(d); n_poly_clear(e); fq_nmod_poly_clear(A, ctx); fq_nmod_poly_clear(B, ctx); fq_nmod_poly_clear(C, ctx); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/n_poly/test/t-n_fq_poly_mul.c000066400000000000000000000042731461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_poly.h" #include "n_poly.h" TEST_FUNCTION_START(n_fq_poly_mul, state) { slong i, j; for (i = 0; i < 300 * flint_test_multiplier(); i++) { fq_nmod_ctx_t ctx; n_poly_t a, b, c, d, e; fq_nmod_poly_t A, B, C; fq_nmod_ctx_init_randtest(ctx, state, 3); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(d); n_poly_init(e); fq_nmod_poly_init(A, ctx); fq_nmod_poly_init(B, ctx); fq_nmod_poly_init(C, ctx); for (j = 0; j < 10; j++) { n_fq_poly_randtest(a, state, n_randint(state, 20), ctx); n_fq_poly_randtest(b, state, n_randint(state, 20), ctx); n_fq_poly_randtest(c, state, n_randint(state, 20), ctx); n_fq_poly_randtest(d, state, n_randint(state, 20), ctx); n_fq_poly_get_fq_nmod_poly(B, b, ctx); n_fq_poly_get_fq_nmod_poly(C, c, ctx); fq_nmod_poly_mul(A, B, C, ctx); n_fq_poly_set_fq_nmod_poly(a, A, ctx); n_fq_poly_mul(d, b, c, ctx); n_fq_poly_set(e, b, ctx); n_fq_poly_mul(b, b, c, ctx); n_fq_poly_mul(c, e, c, ctx); if (!n_fq_poly_equal(a, d, ctx) || !n_fq_poly_equal(a, b, ctx) || !n_fq_poly_equal(a, c, ctx)) { flint_printf("FAIL\n i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(d); n_poly_clear(e); fq_nmod_poly_clear(A, ctx); fq_nmod_poly_clear(B, ctx); fq_nmod_poly_clear(C, ctx); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/n_poly/test/t-n_fq_poly_sub.c000066400000000000000000000042741461254215100211540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fq_nmod_poly.h" #include "n_poly.h" TEST_FUNCTION_START(n_fq_poly_sub, state) { slong i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_ctx_t ctx; n_poly_t a, b, c, d, e; fq_nmod_poly_t A, B, C; fq_nmod_ctx_init_randtest(ctx, state, 3); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(d); n_poly_init(e); fq_nmod_poly_init(A, ctx); fq_nmod_poly_init(B, ctx); fq_nmod_poly_init(C, ctx); for (j = 0; j < 10; j++) { n_fq_poly_randtest(a, state, n_randint(state, 20), ctx); n_fq_poly_randtest(b, state, n_randint(state, 20), ctx); n_fq_poly_randtest(c, state, n_randint(state, 20), ctx); n_fq_poly_randtest(d, state, n_randint(state, 20), ctx); n_fq_poly_get_fq_nmod_poly(B, b, ctx); n_fq_poly_get_fq_nmod_poly(C, c, ctx); fq_nmod_poly_sub(A, B, C, ctx); n_fq_poly_set_fq_nmod_poly(a, A, ctx); n_fq_poly_sub(d, b, c, ctx); n_fq_poly_set(e, b, ctx); n_fq_poly_sub(b, b, c, ctx); n_fq_poly_sub(c, e, c, ctx); if (!n_fq_poly_equal(a, d, ctx) || !n_fq_poly_equal(a, b, ctx) || !n_fq_poly_equal(a, c, ctx)) { flint_printf("FAIL\n i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(d); n_poly_clear(e); fq_nmod_poly_clear(A, ctx); fq_nmod_poly_clear(B, ctx); fq_nmod_poly_clear(C, ctx); fq_nmod_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/n_poly/zippel_helpers.c000066400000000000000000000315521461254215100201210ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" /**************** product of roots *******************************************/ void fq_nmod_poly_product_roots( fq_nmod_poly_t master, const fq_nmod_struct * monomials, slong mlength, const fq_nmod_ctx_t ctx); void n_fq_poly_product_roots_n_fq( n_poly_t master, const mp_limb_t * monomials, slong mlength, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong d = fq_nmod_ctx_degree(ctx); slong i; fq_nmod_poly_t p; fq_nmod_struct * m = FLINT_ARRAY_ALLOC(mlength, fq_nmod_struct); fq_nmod_poly_init(p, ctx); for (i = 0; i < mlength; i++) { fq_nmod_init(m + i, ctx); n_fq_get_fq_nmod(m + i, monomials + d*i, ctx); } fq_nmod_poly_product_roots(p, m, mlength, ctx); n_fq_poly_set_fq_nmod_poly(master, p, ctx); fq_nmod_poly_clear(p, ctx); for (i = 0; i < mlength; i++) fq_nmod_clear(m + i, ctx); flint_free(m); } /* return the largest degree */ slong n_polyun_product_roots( n_polyun_t M, const n_polyun_t H, nmod_t ctx) { slong i, max_length = 0; n_polyun_fit_length(M, H->length); M->length = H->length; for (i = 0; i < H->length; i++) { slong len = H->coeffs[i].length; M->exps[i] = H->exps[i]; max_length = FLINT_MAX(max_length, len); n_poly_mod_product_roots_nmod_vec(M->coeffs + i, H->coeffs[i].coeffs, len, ctx); } return max_length; } slong n_fq_polyun_product_roots( n_fq_polyun_t M, const n_fq_polyun_t H, const fq_nmod_ctx_t ctx, n_poly_stack_t St) { slong i, max_length = 0; n_polyun_fit_length(M, H->length); M->length = H->length; for (i = 0; i < H->length; i++) { slong len = H->coeffs[i].length; M->exps[i] = H->exps[i]; max_length = FLINT_MAX(max_length, len); n_fq_poly_product_roots_n_fq(M->coeffs + i, H->coeffs[i].coeffs, len, ctx, St); } return max_length; } /******************** evaluation *********************************************/ /* return dot(cur, coeffs) and multiply cur pointwise by inc */ mp_limb_t _nmod_zip_eval_step( mp_limb_t * cur, /* in Fp */ const mp_limb_t * inc, /* in Fp */ const mp_limb_t * coeffs, /* in Fp */ slong length, nmod_t ctx) { slong i; ulong t0, t1, t2, p0, p1; t2 = t1 = t0 = 0; for (i = 0; i < length; i++) { umul_ppmm(p1, p0, cur[i], coeffs[i]); add_sssaaaaaa(t2, t1, t0, t2, t1, t0, 0, p1, p0); cur[i] = nmod_mul(cur[i], inc[i], ctx); } NMOD_RED3(t0, t2, t1, t0, ctx); return t0; } void _n_fq_zip_eval_step( mp_limb_t * res, /* in Fq: size d */ mp_limb_t * cur, /* in Fq: size d*length */ const mp_limb_t * inc, /* in Fq: size d*length */ const mp_limb_t * coeffs, /* in Fq: size d*length */ slong length, const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); slong i; mp_limb_t * tmp, * sum; TMP_INIT; if (length < 1) { _n_fq_zero(res, d); return; } TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(8*d*sizeof(mp_limb_t)); sum = tmp + 4*d; i = 0; _n_fq_mul2(sum, cur + d*i, coeffs + d*i, ctx); _n_fq_mul(cur + d*i, cur + d*i, inc + d*i, ctx, tmp); for (i = 1; i < length; i++) { _n_fq_madd2(sum, cur + d*i, coeffs + d*i, ctx, tmp); _n_fq_mul(cur + d*i, cur + d*i, inc + d*i, ctx, tmp); } _n_fq_reduce2(res, sum, ctx, tmp); TMP_END; } void _n_fqp_zip_eval_step( mp_limb_t * res, /* in Fq: size d */ mp_limb_t * cur, /* in Fp: size length */ const mp_limb_t * inc, /* in Fp: size length */ const mp_limb_t * coeffs, /* in Fq: size d*length */ slong length, slong d, nmod_t mod) { slong i, j; mp_limb_t p0, p1; mp_limb_t * tmp; TMP_INIT; if (length < 1) { _n_fq_zero(res, d); return; } TMP_START; tmp = (mp_limb_t *) TMP_ALLOC(3*d*sizeof(mp_limb_t)); i = 0; for (j = 0; j < d; j++) { umul_ppmm(tmp[3*j+1], tmp[3*j+0], cur[i], (coeffs + d*i)[j]); tmp[3*j+2] = 0; } cur[i] = nmod_mul(cur[i], inc[i], mod); for (i = 1; i < length; i++) { for (j = 0; j < d; j++) { umul_ppmm(p1, p0, cur[i], (coeffs + d*i)[j]); add_sssaaaaaa(tmp[3*j+2], tmp[3*j+1], tmp[3*j+0], tmp[3*j+2], tmp[3*j+1], tmp[3*j+0], 0, p1, p0); } cur[i] = nmod_mul(cur[i], inc[i], mod); } for (j = 0; j < d; j++) NMOD_RED3(res[j], tmp[3*j+2], tmp[3*j+1], tmp[3*j+0], mod); TMP_END; } /************** vandermonde solving ******************************************/ /* return -1: singular 0: inconsistent 1: success */ int _nmod_zip_vand_solve( mp_limb_t * coeffs, /* in Fp: size mlength */ const mp_limb_t * monomials, /* in Fp: size mlength */ slong mlength, const mp_limb_t * evals, /* in Fp: size elength */ slong elength, const mp_limb_t * master, /* in Fp: size mlength + 1 */ mp_limb_t * scratch, /* in Fp: size mlength */ nmod_t ctx) { slong i, j; mp_limb_t V, V0, V1, V2, T, S, r, p0, p1; FLINT_ASSERT(elength >= mlength); for (i = 0; i < mlength; i++) { /* coeffs[i] is (coeffs(P).values)/P(roots[i]) =: V/S where P(x) = master(x)/(x-roots[i]) */ V0 = V1 = V2 = T = S = 0; r = monomials[i]; for (j = mlength; j > 0; j--) { T = nmod_add(nmod_mul(r, T, ctx), master[j], ctx); S = nmod_add(nmod_mul(r, S, ctx), T, ctx); umul_ppmm(p1, p0, evals[j - 1], T); add_sssaaaaaa(V2, V1, V0, V2, V1, V0, 0, p1, p0); } /* roots[i] should be a root of master */ FLINT_ASSERT(nmod_add(nmod_mul(r, T, ctx), master[0], ctx) == 0); NMOD_RED3(V, V2, V1, V0, ctx); S = nmod_mul(S, r, ctx); /* shift is one */ if (S == 0) return -1; coeffs[i] = nmod_mul(V, nmod_inv(S, ctx), ctx); } /* check that the remaining points match */ for (j = 0; j < mlength; j++) scratch[j] = nmod_pow_ui(monomials[j], mlength, ctx); for (i = mlength; i < elength; i++) { V0 = V1 = V2 = S = 0; for (j = 0; j < mlength; j++) { scratch[j] = nmod_mul(scratch[j], monomials[j], ctx); umul_ppmm(p1, p0, coeffs[j], scratch[j]); add_sssaaaaaa(V2, V1, V0, V2, V1, V0, 0, p1, p0); } NMOD_RED3(V, V2, V1, V0, ctx); if (V != evals[i]) return 0; } return 1; } int _n_fq_zip_vand_solve( mp_limb_t * coeffs, /* in Fq: size d*mlength */ const mp_limb_t * monomials, /* in Fq: size d*mlength */ slong mlength, const mp_limb_t * evals, /* in Fq: size d*elength */ slong elength, const mp_limb_t * master, /* in Fq: size d*(mlength + 1) */ mp_limb_t * scratch, /* in Fq: size d*mlength */ const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); int success; slong i, j; mp_limb_t * tmp = FLINT_ARRAY_ALLOC(12*d, mp_limb_t); mp_limb_t * V = tmp + 6*d; mp_limb_t * V0 = V + d; mp_limb_t * T = V0 + d; mp_limb_t * S = T + d; mp_limb_t * r = S + d; mp_limb_t * p0 = r + d; FLINT_ASSERT(elength >= mlength); for (i = 0; i < mlength; i++) { /* coeffs[i] is (coeffs(P).values)/P(roots[i]) =: V/S where P(x) = master(x)/(x-roots[i]) */ _n_fq_zero(V0, d); _n_fq_zero(T, d); _n_fq_zero(S, d); _n_fq_set(r, monomials + d*i, d); for (j = mlength; j > 0; j--) { _n_fq_mul(T, r, T, ctx, tmp); _n_fq_add(T, T, master + d*j, d, mod); _n_fq_mul(S, r, S, ctx, tmp); _n_fq_add(S, S, T, d, mod); _n_fq_mul(p0, evals + d*(j - 1), T, ctx, tmp); _n_fq_add(V0, V0, p0, d, mod); } /* roots[i] should be a root of master */ #if FLINT_WANT_ASSERT _n_fq_mul(p0, r, T, ctx, tmp); _n_fq_add(p0, p0, master + d*0, d, mod); FLINT_ASSERT(_n_fq_is_zero(p0, d)); #endif _n_fq_set(V, V0, d); _n_fq_mul(S, S, r, ctx, tmp); if (_n_fq_is_zero(S, d)) { success = -1; goto cleanup; } _n_fq_inv(p0, S, ctx, tmp); _n_fq_mul(p0, V, p0, ctx, tmp); _n_fq_set(coeffs + d*i, p0, d); } /* check that the remaining points match */ for (j = 0; j < mlength; j++) { _n_fq_set(p0, monomials + d*j, d); _n_fq_pow_ui(scratch + d*j, p0, mlength, ctx); } for (i = mlength; i < elength; i++) { _n_fq_zero(V0, d); _n_fq_zero(S, d); for (j = 0; j < mlength; j++) { _n_fq_set(p0, monomials + d*j, d); _n_fq_mul(scratch + d*j, scratch + d*j, p0, ctx, tmp); _n_fq_set(p0, coeffs + d*j, d); _n_fq_mul(p0, p0, scratch + d*j, ctx, tmp); _n_fq_add(V0, V0, p0, d, mod); } _n_fq_set(V, V0, d); if (!_n_fq_equal(V, evals + d*i, d)) { success = 0; goto cleanup; } } success = 1; cleanup: flint_free(tmp); return success; } int _n_fqp_zip_vand_solve( mp_limb_t * coeffs, /* in Fq: size d*mlength */ const mp_limb_t * monomials, /* in Fp: size mlength */ slong mlength, const mp_limb_t * evals, /* in Fq: size d*elength */ slong elength, const mp_limb_t * master, /* in Fp: size (mlength + 1) */ mp_limb_t * scratch, /* in Fp: size mlength */ const fq_nmod_ctx_t ctx) { slong d = fq_nmod_ctx_degree(ctx); nmod_t mod = fq_nmod_ctx_mod(ctx); int success; slong i, j, k; mp_limb_t * tmp = FLINT_ARRAY_ALLOC(d*20, mp_limb_t); mp_limb_t * V = tmp + 6*d; mp_limb_t * V0 = V + d; mp_limb_t * T = V0 + d; mp_limb_t * S = T + d; mp_limb_t * r = S + d; mp_limb_t * p0 = r + d; mp_limb_t * V_p = p0 + d; mp_limb_t r_p, T_p, S_p; FLINT_ASSERT(elength >= mlength); for (i = 0; i < mlength; i++) { /* coeffs[i] is (coeffs(P).values)/P(roots[i]) =: V/S where P(x) = master(x)/(x-roots[i]) */ _n_fq_zero(V0, d); _n_fq_zero(T, d); _n_fq_zero(S, d); _nmod_vec_zero(V_p, 3*d); T_p = S_p = 0; r_p = monomials[i]; for (j = mlength; j > 0; j--) { T_p = nmod_add(nmod_mul(r_p, T_p, mod), master[j], mod); S_p = nmod_add(nmod_mul(r_p, S_p, mod), T_p, mod); for (k = 0; k < d; k++) { mp_limb_t hi, lo; umul_ppmm(hi, lo, T_p, (evals + d*(j - 1))[k]); add_sssaaaaaa(V_p[3*k+2], V_p[3*k+1], V_p[3*k+0], V_p[3*k+2], V_p[3*k+1], V_p[3*k+0], 0, hi, lo); } } /* roots[i] should be a root of master */ FLINT_ASSERT(nmod_add(nmod_mul(r_p, T_p, mod), master[0], mod) == 0); S_p = nmod_mul(S_p, r_p, mod); /* shift is one */ if (S == 0) return -1; S_p = nmod_inv(S_p, mod); for (k = 0; k < d; k++) { mp_limb_t vk; NMOD_RED3(vk, V_p[3*k+2], V_p[3*k+1], V_p[3*k+0], mod); (coeffs + d*i)[k] = nmod_mul(vk, S_p, mod); } } /* check that the remaining points match */ for (j = 0; j < mlength; j++) scratch[j] = nmod_pow_ui(monomials[j], mlength, mod); for (i = mlength; i < elength; i++) { _nmod_vec_zero(V_p, 3*d); S_p = 0; for (j = 0; j < mlength; j++) { scratch[j] = nmod_mul(scratch[j], monomials[j], mod); for (k = 0; k < d; k++) { mp_limb_t hi, lo; umul_ppmm(hi, lo, scratch[j], (coeffs + d*j)[k]); add_sssaaaaaa(V_p[3*k+2], V_p[3*k+1], V_p[3*k+0], V_p[3*k+2], V_p[3*k+1], V_p[3*k+0], 0, hi, lo); } } for (k = 0; k < d; k++) { mp_limb_t vk; NMOD_RED3(vk, V_p[3*k+2], V_p[3*k+1], V_p[3*k+0], mod); if (vk != (evals + d*i)[k]) { success = 0; goto cleanup; } } } success = 1; cleanup: flint_free(tmp); return success; } flint-3.1.3/src/n_poly_types.h000066400000000000000000000051541461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef N_POLY_TYPES_H #define N_POLY_TYPES_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* arrays of ulong */ typedef struct { mp_limb_t * coeffs; slong alloc; slong length; } n_poly_struct; typedef n_poly_struct n_poly_t[1]; typedef n_poly_struct n_fq_poly_struct; typedef n_poly_t n_fq_poly_t; /* arrays of arrays of ulong */ typedef struct { n_poly_struct * coeffs; slong alloc; slong length; } n_bpoly_struct; typedef n_bpoly_struct n_bpoly_t[1]; typedef n_bpoly_struct n_fq_bpoly_struct; typedef n_bpoly_t n_fq_bpoly_t; /* arrays of arrays of arrays of ulong */ typedef struct { n_bpoly_struct * coeffs; slong alloc; slong length; } n_tpoly_struct; typedef n_tpoly_struct n_tpoly_t[1]; typedef n_tpoly_struct n_fq_tpoly_struct; typedef n_tpoly_t n_fq_tpoly_t; /* sparse arrays of ulong */ typedef struct { ulong * exps; mp_limb_t * coeffs; slong length; slong alloc; } n_polyu_struct; typedef n_polyu_struct n_polyu_t[1]; typedef n_polyu_struct n_fq_polyu_struct; typedef n_polyu_t n_fq_polyu_t; /* sparse arrays of arrays of ulong n_polyu1n => one exponent is in the exps[i] n_polyu2n => two exponents are packed into the exps[i] ... */ typedef struct { n_poly_struct * coeffs; ulong * exps; slong length; slong alloc; } n_polyun_struct; typedef n_polyun_struct n_polyun_t[1]; typedef n_polyun_struct n_fq_polyun_struct; typedef n_polyun_t n_fq_polyun_t; /* n_poly stack */ typedef struct { n_poly_struct ** array; slong alloc; slong top; } n_poly_stack_struct; typedef n_poly_stack_struct n_poly_stack_t[1]; /* n_bpoly stack */ typedef struct { n_bpoly_struct ** array; slong alloc; slong top; } n_bpoly_stack_struct; typedef n_bpoly_stack_struct n_bpoly_stack_t[1]; typedef struct { n_poly_stack_t poly_stack; n_bpoly_stack_t bpoly_stack; } n_poly_bpoly_stack_struct; typedef n_poly_bpoly_stack_struct n_poly_bpoly_stack_t[1]; typedef struct { mp_limb_t * M; mp_limb_t * T; mp_limb_t * Q; mp_limb_t * array; slong alloc; slong d; slong radix; mp_limb_t w; } nmod_eval_interp_struct; typedef nmod_eval_interp_struct nmod_eval_interp_t[1]; #ifdef __cplusplus } #endif #endif /* N_POLY_TYPES_H */ flint-3.1.3/src/nf.h000066400000000000000000000032241461254215100141770ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NF_H #define NF_H #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpq_poly_t pol; /* defining polynomial */ union { /* insert any precomputed inverse for zz case here */ fmpz_preinvn_t qq; /* precomputed inverse for leading coeff of num(pol), QQ case */ } pinv; union { /* powers of the generator mod pol */ fmpq_poly_powers_precomp_t qq; fmpz_poly_powers_precomp_t zz; } powers; fmpq_poly_t traces; /* S_k = sum_i \theta_i^k for k = 0, 1, 2, ..., (n-1) */ ulong flag; /* 1 = pol monic over ZZ, 2, = linear, 4 = quadratic field */ } nf_struct; typedef nf_struct nf_t[1]; #define NF_POWERS_CUTOFF 30 /* maximum length of pol where we precompute powers */ #define NF_GENERIC 0 #define NF_MONIC 1 #define NF_LINEAR 2 #define NF_QUADRATIC 4 #define NF_GAUSSIAN 8 /****************************************************************************** Initialisation ******************************************************************************/ void nf_init(nf_t nf, const fmpq_poly_t pol); void nf_init_randtest(nf_t nf, flint_rand_t state, slong len, mp_bitcnt_t bits_in); void nf_clear(nf_t nf); void nf_print(const nf_t nf); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nf/000077500000000000000000000000001461254215100140255ustar00rootroot00000000000000flint-3.1.3/src/nf/clear.c000066400000000000000000000016031461254215100152570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nf.h" void nf_clear(nf_t nf) { fmpq_poly_clear(nf->pol); if (!(nf->flag & NF_MONIC)) fmpz_preinvn_clear(nf->pinv.qq); if (nf->pol->length <= NF_POWERS_CUTOFF && nf->pol->length > 3) { if (nf->flag & NF_MONIC) _fmpz_poly_powers_clear(nf->powers.zz->powers, nf->powers.zz->len); else _fmpq_poly_powers_clear(nf->powers.qq->powers, nf->powers.qq->len); } fmpq_poly_clear(nf->traces); } flint-3.1.3/src/nf/init.c000066400000000000000000000060511461254215100151360ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nf.h" void nf_init(nf_t nf, const fmpq_poly_t pol) { slong i, j; slong len = pol->length, deg = len - 1; fmpz * pow, * lead = fmpq_poly_numref(pol) + len - 1; fmpq_poly_init(nf->pol); fmpq_poly_set(nf->pol, pol); /**** Set up precomputed inverse of leading coeff of f(x) ****/ if (fmpz_is_one(fmpq_poly_denref(pol)) /* denominator is one and numerator is monic */ && fmpz_is_one(lead)) nf->flag = NF_MONIC; else { fmpz_preinvn_init(nf->pinv.qq, lead); nf->flag = NF_GENERIC; } /**** Set up precomputed powers x^i mod f(x) ****/ if (len < 2) { flint_throw(FLINT_ERROR, "Exception (nf_init). Degree must be at least 1.\n"); } else if (len == 2) /* linear case */ nf->flag |= NF_LINEAR; else if (len == 3) /* quadratic case */ { nf->flag |= NF_QUADRATIC; if (fmpz_is_one(pol->coeffs + 0) && fmpz_is_zero(pol->coeffs + 1) && fmpz_is_one(pol->coeffs + 2) && fmpz_is_one(pol->den)) nf->flag |= NF_GAUSSIAN; } else if (len <= NF_POWERS_CUTOFF) /* compute powers of generator mod pol */ { if (nf->flag & NF_MONIC) { nf->powers.zz->powers = _fmpz_poly_powers_precompute(fmpq_poly_numref(pol), len); nf->powers.zz->len = len; } else { nf->powers.qq->powers = _fmpq_poly_powers_precompute(fmpq_poly_numref(pol), fmpq_poly_denref(pol), len); nf->powers.qq->len = len; } } /**** Set up precomputed traces S_k = \sum _i theta_i^k for roots theta_i of f(x) ****/ /* Uses the recursive formula from pp. 163 of "A Course in Computational Algebraic Number Theory" by Henri Cohen */ fmpq_poly_init2(nf->traces, deg); pow = fmpq_poly_denref(nf->traces); for (i = 1; i < deg; i++) { fmpz_mul_si(fmpq_poly_numref(nf->traces) + i, fmpq_poly_numref(pol) + deg - i, i); for (j = i - 1; j >= 1; j--) { fmpz_mul(fmpq_poly_numref(nf->traces) + i, fmpq_poly_numref(nf->traces) + i, lead); fmpz_addmul(fmpq_poly_numref(nf->traces) + i, fmpq_poly_numref(pol) + deg - j, fmpq_poly_numref(nf->traces) + i - j); } fmpz_neg(fmpq_poly_numref(nf->traces) + i, fmpq_poly_numref(nf->traces) + i); } for (i = 1; i < deg; i++) { fmpz_mul(fmpq_poly_numref(nf->traces) + deg - i, fmpq_poly_numref(nf->traces) + deg - i, pow); fmpz_mul(pow, pow, lead); } fmpz_mul_si(fmpq_poly_numref(nf->traces), pow, deg); } flint-3.1.3/src/nf/init_randtest.c000066400000000000000000000032171461254215100170430ustar00rootroot00000000000000/* Copyright (C) 2019 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nf.h" void nf_init_randtest(nf_t nf, flint_rand_t state, slong len, mp_bitcnt_t bits_in) { fmpq_poly_t pol; fmpz_poly_t q; if (len < 2 || bits_in < 1) flint_throw(FLINT_ERROR, "len must be >= 2 and bits_in >= 1 in %s\n", __func__); if (len <= 2 || n_randint(state, 10) == 0) len = 2; /* linear */ else if (len <= 3 || n_randint(state, 8) == 0) len = 3; /* quadratic */ else len = 3 + n_randint(state, len-2); fmpz_poly_init(q); fmpq_poly_init(pol); if (len == 3 && (n_randint(state, 8) == 0)) { fmpq_poly_set_coeff_si(pol, 0, 1); fmpq_poly_set_coeff_si(pol, 2, 1); } else { do { fmpz_poly_randtest(q, state, len, 1 + n_randint(state, bits_in)); } while (fmpz_poly_degree(q) < 1 || fmpz_is_zero(q->coeffs)); fmpq_poly_set_fmpz_poly(pol, q); if (n_randint(state, 5) == 0) fmpz_one(pol->coeffs + pol->length - 1); /* monic */ else fmpz_randtest_not_zero(fmpq_poly_denref(pol), state, bits_in); fmpq_poly_canonicalise(pol); } nf_init(nf, pol); fmpq_poly_clear(pol); fmpz_poly_clear(q); } flint-3.1.3/src/nf/print.c000066400000000000000000000010271461254215100153250ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf.h" void nf_print(const nf_t nf) { flint_printf("Number field with defining polynomial "); fmpq_poly_print_pretty(nf->pol, "x"); } flint-3.1.3/src/nf/test/000077500000000000000000000000001461254215100150045ustar00rootroot00000000000000flint-3.1.3/src/nf/test/main.c000066400000000000000000000014011461254215100160700ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-init_clear.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nf_init_clear) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nf/test/t-init_clear.c000066400000000000000000000037551461254215100175340ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2019 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf.h" TEST_FUNCTION_START(nf_init_clear, state) { int i; /* not necessarily monic */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nf_t nf; fmpq_poly_t pol; fmpq_poly_init(pol); do { fmpq_poly_randtest_not_zero(pol, state, 2 + n_randint(state, 40), 10 + n_randint(state, 200)); } while (fmpq_poly_degree(pol) < 1); nf_init(nf, pol); nf_clear(nf); nf_init(nf, pol); fmpq_poly_clear(pol); nf_clear(nf); } /* monic */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { fmpq_poly_t pol; nf_t nf; fmpq_poly_init(pol); do { fmpq_poly_randtest_not_zero(pol, state, 2 + n_randint(state, 40), 10 + n_randint(state, 200)); } while (fmpq_poly_degree(pol) < 1); fmpz_one(fmpq_poly_denref(pol)); fmpz_one(pol->coeffs + fmpq_poly_degree(pol)); nf_init(nf, pol); nf_clear(nf); nf_init(nf, pol); fmpq_poly_clear(pol); nf_clear(nf); } /* random */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nf_t nf; nf_init_randtest(nf, state, 2 + n_randint(state, 50), 1 + n_randint(state, 200)); nf_clear(nf); nf_init_randtest(nf, state, 2 + n_randint(state, 50), 1 + n_randint(state, 200)); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem.h000066400000000000000000000347401461254215100152100ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NF_ELEM_H #define NF_ELEM_H #ifdef NF_ELEM_INLINES_C #define NF_ELEM_INLINE #else #define NF_ELEM_INLINE static inline #endif #include "fmpq.h" #include "fmpq_types.h" #include "fmpz_mod_types.h" #include "nf.h" #ifdef __cplusplus extern "C" { #endif typedef struct /* element of a linear number field */ { fmpz_t num; fmpz_t den; } lnf_elem_struct; typedef lnf_elem_struct lnf_elem_t[1]; typedef struct /* element of a quadratic number field */ { fmpz num[3]; /* extra coeff for delayed reduction */ fmpz_t den; } qnf_elem_struct; typedef qnf_elem_struct qnf_elem_t[1]; typedef union /* element in a number field (specified by an nf_t) */ { fmpq_poly_t elem; /* general case */ lnf_elem_t lelem; /* linear number field */ qnf_elem_t qelem; /* quadratic number field */ } nf_elem_struct; typedef nf_elem_struct nf_elem_t[1]; #define NF_ELEM_NUMREF(xxx) fmpq_poly_numref((xxx)->elem) #define NF_ELEM_DENREF(xxx) fmpq_poly_denref((xxx)->elem) #define LNF_ELEM_NUMREF(xxx) ((xxx)->lelem->num) #define LNF_ELEM_DENREF(xxx) ((xxx)->lelem->den) #define QNF_ELEM_NUMREF(xxx) ((xxx)->qelem->num) #define QNF_ELEM_DENREF(xxx) ((xxx)->qelem->den) #define NF_ELEM(xxx) (xxx)->elem #define LNF_ELEM(xxx) (xxx)->lelem #define QNF_ELEM(xxx) (xxx)->qelem /****************************************************************************** Initialisation ******************************************************************************/ void nf_elem_init(nf_elem_t a, const nf_t nf); void nf_elem_clear(nf_elem_t a, const nf_t nf); void nf_elem_swap(nf_elem_t a, nf_elem_t b, const nf_t nf); void nf_elem_randtest(nf_elem_t a, flint_rand_t state, mp_bitcnt_t bits, const nf_t nf); void nf_elem_randtest_not_zero(nf_elem_t a, flint_rand_t state, mp_bitcnt_t bits, const nf_t nf); NF_ELEM_INLINE void nf_elem_canonicalise(nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) _fmpq_canonicalise(LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a)); else if (nf->flag & NF_QUADRATIC) _fmpq_poly_canonicalise(QNF_ELEM_NUMREF(a), QNF_ELEM_DENREF(a), 3); else fmpq_poly_canonicalise(NF_ELEM(a)); } void _nf_elem_reduce(nf_elem_t a, const nf_t nf); void nf_elem_reduce(nf_elem_t a, const nf_t nf); int _nf_elem_invertible_check(nf_elem_t a, const nf_t nf); /****************************************************************************** Comparison ******************************************************************************/ int _nf_elem_equal(const nf_elem_t a, const nf_elem_t b, const nf_t nf); int nf_elem_equal(const nf_elem_t a, const nf_elem_t b, const nf_t nf); NF_ELEM_INLINE int nf_elem_is_zero(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_is_zero(LNF_ELEM_NUMREF(a)); else if (nf->flag & NF_QUADRATIC) return fmpz_is_zero(QNF_ELEM_NUMREF(a)) && fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1); else return fmpq_poly_is_zero(a->elem); } NF_ELEM_INLINE int nf_elem_is_one(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_is_one(LNF_ELEM_NUMREF(a)) && fmpz_is_one(LNF_ELEM_DENREF(a)); else if (nf->flag & NF_QUADRATIC) return fmpz_is_one(QNF_ELEM_NUMREF(a)) && fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1) && fmpz_is_one(QNF_ELEM_DENREF(a)); else return fmpq_poly_is_one(a->elem); } int nf_elem_is_gen(const nf_elem_t a, const nf_t nf); NF_ELEM_INLINE int nf_elem_is_integer(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_is_one(LNF_ELEM_DENREF(a)); else if (nf->flag & NF_QUADRATIC) return fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1) && fmpz_is_one(QNF_ELEM_DENREF(a)); else return NF_ELEM(a)->length <= 1 && fmpz_is_one(NF_ELEM_DENREF(a)); } NF_ELEM_INLINE int nf_elem_is_rational(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) return 1; else if (nf->flag & NF_QUADRATIC) return fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1); else return NF_ELEM(a)->length <= 1; } int nf_elem_equal_si(const nf_elem_t a, const slong b, const nf_t nf); int nf_elem_equal_ui(const nf_elem_t a, const ulong b, const nf_t nf); int nf_elem_equal_fmpz(const nf_elem_t a, const fmpz_t b, const nf_t nf); int nf_elem_equal_fmpq(const nf_elem_t a, const fmpq_t b, const nf_t nf); /****************************************************************************** I/O ******************************************************************************/ void nf_elem_print_pretty(const nf_elem_t a, const nf_t nf, const char * var); char * nf_elem_get_str_pretty(const nf_elem_t a, const char * var, const nf_t nf); /****************************************************************************** Element creation ******************************************************************************/ void nf_elem_zero(nf_elem_t a, const nf_t nf); void nf_elem_one(nf_elem_t a, const nf_t nf); void nf_elem_gen(nf_elem_t a, const nf_t nf); void nf_elem_set(nf_elem_t a, const nf_elem_t b, const nf_t nf); void nf_elem_set_si(nf_elem_t a, slong c, const nf_t nf); void nf_elem_set_ui(nf_elem_t a, ulong c, const nf_t nf); void nf_elem_set_fmpz(nf_elem_t a, const fmpz_t c, const nf_t nf); void nf_elem_set_fmpq(nf_elem_t a, const fmpq_t c, const nf_t nf); void nf_elem_set_fmpq_poly(nf_elem_t a, const fmpq_poly_t pol, const nf_t nf); /****************************************************************************** Conversion ******************************************************************************/ void nf_elem_set_fmpz_mat_row(nf_elem_t b, const fmpz_mat_t M, const slong i, fmpz_t den, const nf_t nf); void nf_elem_get_fmpz_mat_row(fmpz_mat_t M, const slong i, fmpz_t den, const nf_elem_t b, const nf_t nf); void nf_elem_get_fmpq_poly(fmpq_poly_t pol, const nf_elem_t a, const nf_t nf); void _nf_elem_get_nmod_poly(nmod_poly_t pol, const nf_elem_t a, const nf_t nf); void nf_elem_get_nmod_poly_den(nmod_poly_t pol, const nf_elem_t a, const nf_t nf, int den); void nf_elem_get_nmod_poly(nmod_poly_t pol, const nf_elem_t a, const nf_t nf); void _nf_elem_get_fmpz_mod_poly(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, const fmpz_mod_ctx_t ctx); void nf_elem_get_fmpz_mod_poly_den(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, int den, const fmpz_mod_ctx_t ctx); void nf_elem_get_fmpz_mod_poly(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, const fmpz_mod_ctx_t ctx); /****************************************************************************** Basic manipulation ******************************************************************************/ NF_ELEM_INLINE void nf_elem_get_den(fmpz_t d, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) fmpz_set(d, LNF_ELEM_DENREF(b)); else if (nf->flag & NF_QUADRATIC) fmpz_set(d, QNF_ELEM_DENREF(b)); else fmpz_set(d, NF_ELEM_DENREF(b)); } NF_ELEM_INLINE void nf_elem_set_den(nf_elem_t b, fmpz_t d, const nf_t nf) { if (nf->flag & NF_LINEAR) fmpz_set(LNF_ELEM_DENREF(b), d); else if (nf->flag & NF_QUADRATIC) fmpz_set(QNF_ELEM_DENREF(b), d); else fmpz_set(NF_ELEM_DENREF(b), d); } void nf_elem_get_coeff_fmpq(fmpq_t a, const nf_elem_t b, slong i, const nf_t nf); void nf_elem_get_coeff_fmpz(fmpz_t a, const nf_elem_t b, slong i, const nf_t nf); NF_ELEM_INLINE int nf_elem_den_is_one(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_is_one(LNF_ELEM_DENREF(a)); else if (nf->flag & NF_QUADRATIC) return fmpz_is_one(QNF_ELEM_DENREF(a)); else return fmpz_is_one(NF_ELEM_DENREF(a)); } void _nf_elem_set_coeff_num_fmpz(nf_elem_t a, slong i, const fmpz_t b, const nf_t nf); /****************************************************************************** Arithmetic ******************************************************************************/ void nf_elem_neg(nf_elem_t a, const nf_elem_t b, const nf_t nf); void nf_elem_add_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf); void nf_elem_add_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf); void nf_elem_add_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf); void nf_elem_sub_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf); void nf_elem_sub_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf); void nf_elem_sub_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf); void nf_elem_si_sub(nf_elem_t a, slong c, const nf_elem_t b, const nf_t nf); void nf_elem_fmpz_sub(nf_elem_t a, const fmpz_t c, const nf_elem_t b, const nf_t nf); void nf_elem_fmpq_sub(nf_elem_t a, const fmpq_t c, const nf_elem_t b, const nf_t nf); void nf_elem_scalar_mul_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf); void nf_elem_scalar_mul_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf); void nf_elem_scalar_mul_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf); void nf_elem_scalar_div_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf); void nf_elem_scalar_div_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf); void nf_elem_scalar_div_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf); void _nf_elem_add_lf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can); void _nf_elem_sub_lf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can); void _nf_elem_add_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can); void _nf_elem_sub_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can); void nf_elem_add_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void nf_elem_sub_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void _nf_elem_add(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void nf_elem_add(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void _nf_elem_sub(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void nf_elem_sub(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void nf_elem_mul_gen(nf_elem_t a, const nf_elem_t b, const nf_t nf); void _nf_elem_mul(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void nf_elem_mul(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void _nf_elem_mul_red(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int red); void nf_elem_mul_red(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int red); void _nf_elem_inv(nf_elem_t a, const nf_elem_t b, const nf_t nf); void nf_elem_inv(nf_elem_t a, const nf_elem_t b, const nf_t nf); void _nf_elem_div(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void nf_elem_div(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf); void _nf_elem_pow(nf_elem_t res, const nf_elem_t b, ulong e, const nf_t nf); void nf_elem_pow(nf_elem_t res, const nf_elem_t a, ulong e, const nf_t nf); void _nf_elem_norm(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf); void nf_elem_norm(fmpq_t res, const nf_elem_t a, const nf_t nf); void _nf_elem_norm_div(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf, const fmpz_t divisor, slong nbits); void nf_elem_norm_div(fmpq_t res, const nf_elem_t a, const nf_t nf, const fmpz_t divisor, slong nbits); void _nf_elem_trace(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf); void nf_elem_trace(fmpq_t res, const nf_elem_t a, const nf_t nf); void nf_elem_rep_mat(fmpq_mat_t res, const nf_elem_t a, const nf_t nf); void nf_elem_rep_mat_fmpz_mat_den(fmpz_mat_t res, fmpz_t den, const nf_elem_t a, const nf_t nf); /****************************************************************************** Modular reduction ******************************************************************************/ void _nf_elem_mod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int sign); void nf_elem_mod_fmpz_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int den); void nf_elem_smod_fmpz_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int den); void nf_elem_mod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf); void nf_elem_smod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf); void nf_elem_coprime_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf); void nf_elem_coprime_den_signed(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf); #ifdef __cplusplus } #endif /****************************************************************************** Helpers originally for compatibility with FLINT 2.6 ******************************************************************************/ #define FMPZ_MOD_POLY_FIT_LENGTH(POL, N, CTX) fmpz_mod_poly_fit_length(POL, N, CTX) #define FMPZ_MOD(F, G, CTX, P) fmpz_mod(F, G, (CTX)->n) #define FMPZ_MOD_POLY_ZERO(POL, CTX) fmpz_mod_poly_zero(POL, CTX) #define FMPZ_MOD_POLY_SCALAR_DIV_FMPZ(RES, POL, X, CTX) fmpz_mod_poly_scalar_div_fmpz(RES, POL, X, CTX) #endif flint-3.1.3/src/nf_elem/000077500000000000000000000000001461254215100150275ustar00rootroot00000000000000flint-3.1.3/src/nf_elem/add.c000066400000000000000000000225471461254215100157350ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void _nf_elem_add_lf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can) { const fmpz *const p = LNF_ELEM_NUMREF(b); const fmpz *const q = LNF_ELEM_DENREF(b); const fmpz *const r = LNF_ELEM_NUMREF(c); const fmpz *const s = LNF_ELEM_DENREF(c); fmpz *const rnum = LNF_ELEM_NUMREF(a); fmpz *const rden = LNF_ELEM_DENREF(a); fmpz_t t; if (can) _fmpq_add(rnum, rden, p, q, r, s); else { /* Same denominator */ if (fmpz_equal(q, s)) { fmpz_add(rnum, p, r); fmpz_set(rden, q); return; } /* p/q is an integer */ if (fmpz_is_one(q)) { fmpz_init(t); fmpz_mul(t, p, s); fmpz_add(rnum, t, r); fmpz_set(rden, s); fmpz_clear(t); return; } /* r/s is an integer */ if (fmpz_is_one(s)) { fmpz_init(t); fmpz_mul(t, r, q); fmpz_add(rnum, t, p); fmpz_set(rden, q); fmpz_clear(t); return; } /* We want to compute p/q + r/s which is (p*s + q*r, q*s). */ fmpz_init(t); fmpz_mul(t, p, s); fmpz_mul(rnum, q, r); fmpz_add(rnum, rnum, t); fmpz_mul(rden, q, s); fmpz_clear(t); } } void _nf_elem_add_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can) { fmpz_t d; const fmpz *const bnum = QNF_ELEM_NUMREF(b); const fmpz *const bden = QNF_ELEM_DENREF(b); const fmpz *const cnum = QNF_ELEM_NUMREF(c); const fmpz *const cden = QNF_ELEM_DENREF(c); fmpz *const anum = QNF_ELEM_NUMREF(a); fmpz *const aden = QNF_ELEM_DENREF(a); fmpz_init(d); fmpz_one(d); if (fmpz_equal(bden, cden)) { fmpz_add(anum, bnum, cnum); fmpz_add(anum + 1, bnum + 1, cnum + 1); fmpz_add(anum + 2, bnum + 2, cnum + 2); fmpz_set(aden, bden); if (can && !fmpz_is_one(aden)) { fmpz_gcd3(d, anum + 0, anum + 1, anum + 2); if (!fmpz_is_one(d)) { fmpz_gcd(d, d, aden); if (!fmpz_is_one(d)) { fmpz_divexact(anum, anum, d); fmpz_divexact(anum + 1, anum + 1, d); fmpz_divexact(anum + 2, anum + 2, d); fmpz_divexact(aden, aden, d); } } } fmpz_clear(d); return; } if (!fmpz_is_one(bden) && !fmpz_is_one(cden)) fmpz_gcd(d, bden, cden); if (fmpz_is_one(d)) { fmpz_mul(anum, bnum, cden); fmpz_mul(anum + 1, bnum + 1, cden); fmpz_mul(anum + 2, bnum + 2, cden); fmpz_addmul(anum, cnum, bden); fmpz_addmul(anum + 1, cnum + 1, bden); fmpz_addmul(anum + 2, cnum + 2, bden); fmpz_mul(aden, bden, cden); } else { fmpz_t bden1; fmpz_t cden1; fmpz_init(bden1); fmpz_init(cden1); fmpz_divexact(bden1, bden, d); fmpz_divexact(cden1, cden, d); fmpz_mul(anum, bnum, cden1); fmpz_mul(anum + 1, bnum + 1, cden1); fmpz_mul(anum + 2, bnum + 2, cden1); fmpz_addmul(anum, cnum, bden1); fmpz_addmul(anum + 1, cnum + 1, bden1); fmpz_addmul(anum + 2, cnum + 2, bden1); if (fmpz_is_zero(anum) && fmpz_is_zero(anum + 1) && fmpz_is_zero(anum + 2)) fmpz_one(aden); else { if (can) { fmpz_t e; fmpz_init(e); fmpz_gcd3(e, anum + 0, anum + 1, anum + 2); if (!fmpz_is_one(e)) fmpz_gcd(e, e, d); if (fmpz_is_one(e)) fmpz_mul(aden, bden, cden1); else { fmpz_divexact(anum, anum, e); fmpz_divexact(anum + 1, anum + 1, e); fmpz_divexact(anum + 2, anum + 2, e); fmpz_divexact(bden1, bden, e); fmpz_mul(aden, bden1, cden1); } fmpz_clear(e); } else fmpz_mul(aden, bden, cden1); } fmpz_clear(bden1); fmpz_clear(cden1); } fmpz_clear(d); } void nf_elem_add_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { if (a == c) { nf_elem_t t; nf_elem_init(t, nf); _nf_elem_add_qf(t, b, c, nf, 1); nf_elem_swap(t, a, nf); nf_elem_clear(t, nf); } else _nf_elem_add_qf(a, b, c, nf, 1); } void _nf_elem_add(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) _nf_elem_add_lf(a, b, c, nf, 0); else if (nf->flag & NF_QUADRATIC) _nf_elem_add_qf(a, b, c, nf, 0); else fmpq_poly_add_can(NF_ELEM(a), NF_ELEM(b), NF_ELEM(c), 0); } void nf_elem_add(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) _nf_elem_add_lf(a, b, c, nf, 1); else if (nf->flag & NF_QUADRATIC) nf_elem_add_qf(a, b, c, nf); else fmpq_poly_add_can(NF_ELEM(a), NF_ELEM(b), NF_ELEM(c), 1); } void nf_elem_add_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_add(num, den, num2, den2, fmpq_numref(c), fmpq_denref(c)); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); slong len = 2; nf_elem_set(a, b, nf); while (len != 0 && fmpz_is_zero(num2 + len - 1)) len--; if (len == 0) { fmpz_set(num, fmpq_numref(c)); fmpz_set(den, fmpq_denref(c)); } else if (len == 1) _fmpq_add(num, den, num2, den2, fmpq_numref(c), fmpq_denref(c)); else { /* fast path */ if (fmpz_equal(fmpq_denref(c), den)) { fmpz_add(num, num2, fmpq_numref(c)); fmpz_set(den, den2); } else /* slow path */ { fmpz_t d1, d2, g; fmpz_init(d1); fmpz_init(d2); fmpz_init(g); fmpz_gcd(g, fmpq_denref(c), den); fmpz_divexact(d1, fmpq_denref(c), g); fmpz_divexact(d2, den, g); fmpz_mul(num + 1, num + 1, d1); fmpz_mul(num, num, d1); fmpz_mul(den, den, d1); fmpz_addmul(num, d2, fmpq_numref(c)); fmpz_clear(g); fmpz_clear(d1); fmpz_clear(d2); } _fmpq_poly_canonicalise(num, den, 2); } } else { fmpq_poly_add_fmpq(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_add_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_add_fmpz(num, den, num2, den2, c); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); slong len = 2; nf_elem_set(a, b, nf); while (len != 0 && fmpz_is_zero(num + len - 1)) len--; fmpz_addmul(num, den, c); _fmpq_poly_canonicalise(num, den, len); } else { fmpq_poly_add_fmpz(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_add_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); nf_elem_set(a, b, nf); if (c >= 0) fmpz_addmul_ui(num, den, c); else fmpz_submul_ui(num, den, -c); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); slong len = 2; nf_elem_set(a, b, nf); while (len != 0 && fmpz_is_zero(num + len - 1)) len--; if (c >= 0) fmpz_addmul_ui(num, den, c); else fmpz_submul_ui(num, den, -c); _fmpq_poly_canonicalise(num, den, len); } else { fmpq_poly_add_si(NF_ELEM(a), NF_ELEM(b), c); } } flint-3.1.3/src/nf_elem/clear.c000066400000000000000000000016371461254215100162700ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_clear(nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_clear(LNF_ELEM_NUMREF(a)); fmpz_clear(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz * const aden = QNF_ELEM_DENREF(a); fmpz_clear(anum); fmpz_clear(anum + 1); fmpz_clear(anum + 2); fmpz_clear(aden); } else { fmpq_poly_clear(NF_ELEM(a)); } } flint-3.1.3/src/nf_elem/div.c000066400000000000000000000016721461254215100157630ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void _nf_elem_div(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { nf_elem_t cinv; nf_elem_init(cinv, nf); _nf_elem_inv(cinv, c, nf); _nf_elem_mul(a, b, cinv, nf); nf_elem_clear(cinv, nf); } void nf_elem_div(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { nf_elem_t t; if (a == b) { nf_elem_init(t, nf); _nf_elem_div(t, b, c, nf); nf_elem_swap(t, a, nf); nf_elem_clear(t, nf); } else _nf_elem_div(a, b, c, nf); nf_elem_canonicalise(a, nf); } flint-3.1.3/src/nf_elem/equal.c000066400000000000000000000200521461254215100163010ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" int _nf_elem_equal(const nf_elem_t a, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { slong d, bits1, bits2; int res = 1; const fmpz *const anum = LNF_ELEM_NUMREF(a); const fmpz *const bnum = LNF_ELEM_NUMREF(b); const fmpz *const aden = LNF_ELEM_DENREF(a); const fmpz *const bden = LNF_ELEM_DENREF(b); fmpz_t t1, t2; if (fmpz_equal(aden, bden)) return fmpz_equal(anum, bnum); d = fmpz_bits(aden) - fmpz_bits(bden) + 1; bits1 = fmpz_bits(anum); bits2 = fmpz_bits(bnum); if (!(bits1 == 0 && bits2 == 0) && (ulong) (bits1 - bits2 + d) > 2) return 0; fmpz_init(t1); fmpz_init(t2); fmpz_mul(t1, anum, bden); fmpz_mul(t2, bnum, aden); if (!fmpz_equal(t1, t2)) res = 0; fmpz_clear(t1); fmpz_clear(t2); return res; } else if (nf->flag & NF_QUADRATIC) { slong d, bits1, bits2; int res = 1; const fmpz *const anum = QNF_ELEM_NUMREF(a); const fmpz *const bnum = QNF_ELEM_NUMREF(b); const fmpz *const aden = QNF_ELEM_DENREF(a); const fmpz *const bden = QNF_ELEM_DENREF(b); fmpz_t t1, t2; if (fmpz_equal(aden, bden)) return fmpz_equal(anum, bnum) && fmpz_equal(anum + 1, bnum + 1); d = fmpz_bits(aden) - fmpz_bits(bden) + 1; bits1 = fmpz_bits(anum + 1); bits2 = fmpz_bits(bnum + 1); if (!(bits1 == 0 && bits2 == 0) && (ulong) (bits1 - bits2 + d) > 2) return 0; bits1 = fmpz_bits(anum); bits2 = fmpz_bits(bnum); if (!(bits1 == 0 && bits2 == 0) && (ulong) (bits1 - bits2 + d) > 2) return 0; fmpz_init(t1); fmpz_init(t2); fmpz_mul(t1, anum, bden); fmpz_mul(t2, bnum, aden); if (!fmpz_equal(t1, t2)) { res = 0; goto cleanup; } fmpz_mul(t1, anum + 1, bden); fmpz_mul(t2, bnum + 1, aden); if (!fmpz_equal(t1, t2)) { res = 0; goto cleanup; } cleanup: fmpz_clear(t1); fmpz_clear(t2); return res; } else { const slong len1 = NF_ELEM(a)->length; const slong len2 = NF_ELEM(b)->length; if (len1 != len2) return 0; if (fmpz_equal (fmpq_poly_denref(NF_ELEM(a)), fmpq_poly_denref(NF_ELEM(b)))) return _fmpz_vec_equal(NF_ELEM_NUMREF(a), NF_ELEM_NUMREF(b), len1); else { slong i; slong d = fmpz_bits(fmpq_poly_denref(NF_ELEM(b))) - fmpz_bits(fmpq_poly_denref(NF_ELEM(a))) + 1; fmpz *p1 = NF_ELEM_NUMREF(a); fmpz *p2 = NF_ELEM_NUMREF(b); fmpz_t gcd, den1, den2; fmpz *t1, *t2; int equal; for (i = 0; i < len1; i++) { slong b1 = fmpz_bits(p1 + i); slong b2 = fmpz_bits(p2 + i); if (!(b1 == 0 && b2 == 0) && (ulong) (b1 - b2 + d) > 2) return 0; } fmpz_init(gcd); fmpz_init(den1); fmpz_init(den2); /* TODO: possibly only compute GCD if it will save time */ fmpz_gcd(gcd, fmpq_poly_denref(NF_ELEM(a)), fmpq_poly_denref(NF_ELEM(b))); fmpz_divexact(den1, fmpq_poly_denref(NF_ELEM(a)), gcd); fmpz_divexact(den2, fmpq_poly_denref(NF_ELEM(b)), gcd); t1 = _fmpz_vec_init(len1); t2 = _fmpz_vec_init(len1); _fmpz_vec_scalar_mul_fmpz(t1, p1, len1, den2); _fmpz_vec_scalar_mul_fmpz(t2, p2, len2, den1); equal = _fmpz_vec_equal(t1, t2, len1); fmpz_clear(gcd); fmpz_clear(den1); fmpz_clear(den2); _fmpz_vec_clear(t1, len1); _fmpz_vec_clear(t2, len1); return equal; } } } int nf_elem_equal(const nf_elem_t a, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { if (!fmpz_equal(LNF_ELEM_DENREF(a), LNF_ELEM_DENREF(b))) return 0; if (!fmpz_equal(LNF_ELEM_NUMREF(a), LNF_ELEM_NUMREF(b))) return 0; return 1; } else if (nf->flag & NF_QUADRATIC) { if (!fmpz_equal(QNF_ELEM_DENREF(a), QNF_ELEM_DENREF(b))) return 0; if (!fmpz_equal(QNF_ELEM_NUMREF(a), QNF_ELEM_NUMREF(b))) return 0; if (!fmpz_equal(QNF_ELEM_NUMREF(a) + 1, QNF_ELEM_NUMREF(b) + 1)) return 0; return 1; } else { const slong len1 = NF_ELEM(a)->length; const slong len2 = NF_ELEM(b)->length; if (len1 != len2) return 0; if (fmpz_equal (fmpq_poly_denref(NF_ELEM(a)), fmpq_poly_denref(NF_ELEM(b)))) return _fmpz_vec_equal(NF_ELEM_NUMREF(a), NF_ELEM_NUMREF(b), len1); else return 0; } } int nf_elem_equal_si(const nf_elem_t a, const slong b, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_is_one(LNF_ELEM_DENREF(a)) && fmpz_equal_si(LNF_ELEM_NUMREF(a), b); else if (nf->flag & NF_QUADRATIC) return fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1) && fmpz_is_one(QNF_ELEM_DENREF(a)) && fmpz_equal_si(QNF_ELEM_NUMREF(a), b); else { if (b == 0) return fmpq_poly_is_zero(NF_ELEM(a)); else return NF_ELEM(a)->length == 1 && fmpz_is_one(NF_ELEM_DENREF(a)) && fmpz_equal_si(NF_ELEM_NUMREF(a), b); } } int nf_elem_equal_ui(const nf_elem_t a, const ulong b, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_is_one(LNF_ELEM_DENREF(a)) && fmpz_equal_ui(LNF_ELEM_NUMREF(a), b); else if (nf->flag & NF_QUADRATIC) return fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1) && fmpz_is_one(QNF_ELEM_DENREF(a)) && fmpz_equal_ui(QNF_ELEM_NUMREF(a), b); else { if (b == 0) return fmpq_poly_is_zero(NF_ELEM(a)); else return NF_ELEM(a)->length == 1 && fmpz_is_one(NF_ELEM_DENREF(a)) && fmpz_equal_ui(NF_ELEM_NUMREF(a), b); } } int nf_elem_equal_fmpz(const nf_elem_t a, const fmpz_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_is_one(LNF_ELEM_DENREF(a)) && fmpz_equal(LNF_ELEM_NUMREF(a), b); else if (nf->flag & NF_QUADRATIC) return fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1) && fmpz_is_one(QNF_ELEM_DENREF(a)) && fmpz_equal(QNF_ELEM_NUMREF(a), b); else { if (NF_ELEM(a)->length == 0) return fmpz_is_zero(b); else if (NF_ELEM(a)->length == 1) return fmpz_is_one(NF_ELEM_DENREF(a)) && fmpz_equal(NF_ELEM_NUMREF(a), b); else return 0; } } int nf_elem_equal_fmpq(const nf_elem_t a, const fmpq_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) return fmpz_equal(LNF_ELEM_NUMREF(a), fmpq_numref(b)) && fmpz_equal(LNF_ELEM_DENREF(a), fmpq_denref(b)); else if (nf->flag & NF_QUADRATIC) return fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1) && fmpz_equal(QNF_ELEM_NUMREF(a), fmpq_numref(b)) && fmpz_equal(QNF_ELEM_DENREF(a), fmpq_denref(b)); else { if (NF_ELEM(a)->length == 0) return fmpq_is_zero(b); else if (NF_ELEM(a)->length == 1) return fmpz_equal(NF_ELEM_NUMREF(a), fmpq_numref(b)) && fmpz_equal(NF_ELEM_DENREF(a), fmpq_denref(b)); else return 0; } } flint-3.1.3/src/nf_elem/gen.c000066400000000000000000000017111461254215100157440ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_gen(nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_neg(LNF_ELEM_NUMREF(a), nf->pol->coeffs); fmpz_set(LNF_ELEM_DENREF(a), nf->pol->coeffs + 1); _fmpq_canonicalise(LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz_one(anum + 1); fmpz_zero(anum); fmpz_one(QNF_ELEM_DENREF(a)); } else { fmpq_poly_zero(NF_ELEM(a)); fmpq_poly_set_coeff_ui(NF_ELEM(a), 1, 1); } } flint-3.1.3/src/nf_elem/get_coeff_fmpq.c000066400000000000000000000021601461254215100201360ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_get_coeff_fmpq(fmpq_t a, const nf_elem_t b, slong i, const nf_t nf) { if (nf->flag & NF_LINEAR) { if (i > 0) fmpq_zero(a); else { fmpz_set(fmpq_numref(a), LNF_ELEM_NUMREF(b)); fmpz_set(fmpq_denref(a), LNF_ELEM_DENREF(b)); } } else if (nf->flag & NF_QUADRATIC) { const fmpz * const bnum = QNF_ELEM_NUMREF(b); if (i > 2) /* element may be unreduced */ fmpq_zero(a); else { fmpz_set(fmpq_numref(a), bnum + i); fmpz_set(fmpq_denref(a), QNF_ELEM_DENREF(b)); } fmpq_canonicalise(a); } else fmpq_poly_get_coeff_fmpq(a, NF_ELEM(b), i); } flint-3.1.3/src/nf_elem/get_coeff_fmpz.c000066400000000000000000000016531461254215100201550ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_get_coeff_fmpz(fmpz_t a, const nf_elem_t b, slong i, const nf_t nf) { if (nf->flag & NF_LINEAR) { if (i > 0) fmpz_zero(a); else fmpz_set(a, LNF_ELEM_NUMREF(b)); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const bnum = QNF_ELEM_NUMREF(b); if (i > 2) /* element may be unreduced */ fmpz_zero(a); else fmpz_set(a, bnum + i); } else fmpq_poly_get_coeff_fmpz(a, NF_ELEM(b), i); } flint-3.1.3/src/nf_elem/get_fmpq_poly.c000066400000000000000000000017771461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void nf_elem_get_fmpq_poly(fmpq_poly_t pol, const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpq_poly_set_fmpz(pol, LNF_ELEM_NUMREF(a)); fmpz_set(fmpq_poly_denref(pol), LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); fmpq_poly_fit_length(pol, 2); _fmpq_poly_set_length(pol, 2); _fmpz_vec_set(pol->coeffs, anum, 2); _fmpq_poly_normalise(pol); fmpz_set(pol->den, QNF_ELEM_DENREF(a)); } else { fmpq_poly_set(pol, NF_ELEM(a)); } } flint-3.1.3/src/nf_elem/get_fmpz_mat_row.c000066400000000000000000000025411461254215100205400ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart Copyright (C) 2015 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "nf_elem.h" void nf_elem_get_fmpz_mat_row(fmpz_mat_t M, const slong i, fmpz_t den, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(fmpz_mat_entry(M, i, 0), LNF_ELEM_NUMREF(b)); fmpz_set(den, LNF_ELEM_DENREF(b)); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const bnum = QNF_ELEM_NUMREF(b); fmpz_set(fmpz_mat_entry(M, i, 0), bnum); fmpz_set(fmpz_mat_entry(M, i, 1), bnum + 1); fmpz_set(den, QNF_ELEM_DENREF(b)); } else { slong j; for (j = 0; j < NF_ELEM(b)->length; j++) { fmpz_set(fmpz_mat_entry(M, i, j), NF_ELEM_NUMREF(b) + j); } for ( ; j < nf->pol->length - 1; j++) { fmpz_zero(fmpz_mat_entry(M, i, j)); } fmpz_set(den, NF_ELEM_DENREF(b)); } } flint-3.1.3/src/nf_elem/get_fmpz_mod_poly.c000066400000000000000000000046231461254215100207150ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "nf_elem.h" void _nf_elem_get_fmpz_mod_poly(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, const fmpz_mod_ctx_t ctx) { if (nf_elem_is_zero(a, nf)) { FMPZ_MOD_POLY_ZERO(pol, ctx); return; } if (nf->flag & NF_LINEAR) { { FMPZ_MOD_POLY_FIT_LENGTH(pol, 1, ctx); FMPZ_MOD(pol->coeffs + 0, LNF_ELEM_NUMREF(a), ctx, &(pol->p)); _fmpz_mod_poly_set_length(pol, 1); _fmpz_mod_poly_normalise(pol); } } else if (nf->flag & NF_QUADRATIC) { FMPZ_MOD_POLY_FIT_LENGTH(pol, 3, ctx); FMPZ_MOD(pol->coeffs + 0, QNF_ELEM_NUMREF(a), ctx, &(pol->p)); FMPZ_MOD(pol->coeffs + 1, QNF_ELEM_NUMREF(a) + 1, ctx, &(pol->p)); FMPZ_MOD(pol->coeffs + 2, QNF_ELEM_NUMREF(a) + 2, ctx, &(pol->p)); _fmpz_mod_poly_set_length(pol, 3); _fmpz_mod_poly_normalise(pol); } else { slong len = NF_ELEM(a)->length; slong i; FMPZ_MOD_POLY_FIT_LENGTH(pol, len, ctx); for (i = 0; i < len; i++) FMPZ_MOD(pol->coeffs + i, NF_ELEM_NUMREF(a) + i, ctx, &(pol->p)); _fmpz_mod_poly_set_length(pol, len); _fmpz_mod_poly_normalise(pol); } } void nf_elem_get_fmpz_mod_poly_den(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, int den, const fmpz_mod_ctx_t ctx) { _nf_elem_get_fmpz_mod_poly(pol, a, nf, ctx); if (den) { if (nf->flag & NF_LINEAR) FMPZ_MOD_POLY_SCALAR_DIV_FMPZ(pol, pol, LNF_ELEM_DENREF(a), ctx); else if (nf->flag & NF_QUADRATIC) FMPZ_MOD_POLY_SCALAR_DIV_FMPZ(pol, pol, QNF_ELEM_DENREF(a), ctx); else FMPZ_MOD_POLY_SCALAR_DIV_FMPZ(pol, pol, NF_ELEM_DENREF(a), ctx); } } void nf_elem_get_fmpz_mod_poly(fmpz_mod_poly_t pol, const nf_elem_t a, const nf_t nf, const fmpz_mod_ctx_t ctx) { nf_elem_get_fmpz_mod_poly_den(pol, a, nf, 1, ctx); } flint-3.1.3/src/nf_elem/get_nmod_poly.c000066400000000000000000000043571461254215100200430ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "nf_elem.h" void _nf_elem_get_nmod_poly(nmod_poly_t pol, const nf_elem_t a, const nf_t nf) { if (nf_elem_is_zero(a, nf)) { nmod_poly_zero(pol); return; } if (nf->flag & NF_LINEAR) { { nmod_poly_fit_length(pol, 1); pol->coeffs[0] = fmpz_get_nmod(LNF_ELEM_NUMREF(a), pol->mod); _nmod_poly_set_length(pol, 1); _nmod_poly_normalise(pol); } } else if (nf->flag & NF_QUADRATIC) { nmod_poly_fit_length(pol, 3); pol->coeffs[0] = fmpz_get_nmod(QNF_ELEM_NUMREF(a), pol->mod); pol->coeffs[1] = fmpz_get_nmod(QNF_ELEM_NUMREF(a) + 1, pol->mod); pol->coeffs[2] = fmpz_get_nmod(QNF_ELEM_NUMREF(a) + 2, pol->mod); _nmod_poly_set_length(pol, 3); _nmod_poly_normalise(pol); } else { slong len = NF_ELEM(a)->length; slong i; nmod_poly_fit_length(pol, len); for (i = 0; i < len; i++) pol->coeffs[i] = fmpz_get_nmod(NF_ELEM(a)->coeffs + i, pol->mod); _nmod_poly_set_length(pol, len); _nmod_poly_normalise(pol); } } void nf_elem_get_nmod_poly_den(nmod_poly_t pol, const nf_elem_t a, const nf_t nf, int den) { _nf_elem_get_nmod_poly(pol, a, nf); if (den) { if (nf->flag & NF_LINEAR) nmod_poly_scalar_mul_nmod(pol, pol, n_invmod(fmpz_get_nmod(LNF_ELEM_DENREF(a), pol->mod), pol->mod.n)); else if (nf->flag & NF_QUADRATIC) nmod_poly_scalar_mul_nmod(pol, pol, n_invmod(fmpz_get_nmod(QNF_ELEM_DENREF(a), pol->mod), pol->mod.n)); else nmod_poly_scalar_mul_nmod(pol, pol, n_invmod(fmpz_get_nmod(NF_ELEM_DENREF(a), pol->mod), pol->mod.n)); } } void nf_elem_get_nmod_poly(nmod_poly_t pol, const nf_elem_t a, const nf_t nf) { nf_elem_get_nmod_poly_den(pol, a, nf, 1); } flint-3.1.3/src/nf_elem/get_str_pretty.c000066400000000000000000000021541461254215100202530ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" char * nf_elem_get_str_pretty(const nf_elem_t a, const char * var, const nf_t nf) { if (nf->flag & NF_LINEAR) { const fmpz * const den = LNF_ELEM_DENREF(a); const fmpz * const num = LNF_ELEM_NUMREF(a); slong len = 1 - fmpz_is_zero(num); return _fmpq_poly_get_str_pretty(num, den, len, var); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const den = QNF_ELEM_DENREF(a); const fmpz * const num = QNF_ELEM_NUMREF(a); slong len = 3; while (len != 0 && fmpz_is_zero(num + len - 1)) len--; return _fmpq_poly_get_str_pretty(num, den, len, var); } else { return fmpq_poly_get_str_pretty(NF_ELEM(a), var); } } flint-3.1.3/src/nf_elem/init.c000066400000000000000000000020011461254215100161270ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_init(nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_init(LNF_ELEM_NUMREF(a)); fmpz_init(LNF_ELEM_DENREF(a)); fmpz_one(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz * const aden = QNF_ELEM_DENREF(a); fmpz_init(anum); fmpz_init(anum + 1); fmpz_init(anum + 2); fmpz_init(aden); fmpz_one(aden); } else { fmpq_poly_init2(NF_ELEM(a), FLINT_MAX(2*nf->pol->length - 3, 0)); } } flint-3.1.3/src/nf_elem/inlines.c000066400000000000000000000006521461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NF_ELEM_INLINES_C #include "nf_elem.h" flint-3.1.3/src/nf_elem/inv.c000066400000000000000000000034531461254215100157740ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void _nf_elem_inv(nf_elem_t a, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { if (a == b) fmpz_swap(LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a)); else { fmpz_set(LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(b)); fmpz_set(LNF_ELEM_DENREF(a), LNF_ELEM_NUMREF(b)); } _fmpq_canonicalise(LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz * const aden = QNF_ELEM_DENREF(a); const fmpz * const bnum = QNF_ELEM_NUMREF(b); const fmpz * const bden = QNF_ELEM_DENREF(b); fmpz * t = _fmpz_vec_init(6); slong len = 2; while (len > 0 && fmpz_is_zero(bnum + len - 1)) len--; _fmpq_poly_xgcd(t + 3, t + 5, t, t + 2, anum, aden, fmpq_poly_numref(nf->pol), fmpq_poly_denref(nf->pol), 3, bnum, bden, len); _fmpz_vec_clear(t, 6); } else { fmpq_poly_t g, t; fmpq_poly_init(g); fmpq_poly_init(t); fmpq_poly_xgcd(g, NF_ELEM(a), t, NF_ELEM(b), nf->pol); fmpq_poly_clear(t); fmpq_poly_clear(g); } } void nf_elem_inv(nf_elem_t a, const nf_elem_t b, const nf_t nf) { nf_elem_t t; if (a == b) { nf_elem_init(t, nf); _nf_elem_inv(t, b, nf); nf_elem_swap(t, a, nf); nf_elem_clear(t, nf); } else _nf_elem_inv(a, b, nf); } flint-3.1.3/src/nf_elem/invertible_check.c000066400000000000000000000027151461254215100205000ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" int _nf_elem_invertible_check(nf_elem_t a, const nf_t nf) { int res; if (nf->flag & NF_LINEAR) { const fmpz * const anum = QNF_ELEM_NUMREF(a); if (fmpz_is_zero(anum)) res = 0; else { fmpz * t = _fmpz_vec_init(2); _fmpq_poly_gcd(t, t + 1, fmpq_poly_numref(nf->pol), 2, anum, 1); res = fmpz_is_one(t); _fmpz_vec_clear(t, 2); } } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz * t = _fmpz_vec_init(3); slong len = 2; while (len > 0 && fmpz_is_zero(anum + len - 1)) len--; _fmpq_poly_gcd(t, t + 2, fmpq_poly_numref(nf->pol), 3, anum, len); while (len > 0 && fmpz_is_zero(t + len - 1)) len--; res = len == 1 && fmpz_is_one(t); _fmpz_vec_clear(t, 3); } else { fmpq_poly_t g; fmpq_poly_init(g); fmpq_poly_gcd(g, NF_ELEM(a), nf->pol); res = fmpq_poly_is_one(g); fmpq_poly_clear(g); } return res; } flint-3.1.3/src/nf_elem/io.c000066400000000000000000000026001461254215100156000ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nf_elem.h" void nf_elem_print_pretty(const nf_elem_t a, const nf_t nf, const char * var) { if (nf->flag & NF_LINEAR) { const fmpz * const den = LNF_ELEM_DENREF(a); fmpz_print(LNF_ELEM_NUMREF(a)); if (!fmpz_is_one(den)) { flint_printf("/"); fmpz_print(LNF_ELEM_DENREF(a)); } } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); const fmpz * const aden = QNF_ELEM_DENREF(a); int den1 = fmpz_is_one(aden); int lead0 = fmpz_is_zero(anum + 1); if (!den1 && !lead0) flint_printf("("); if (!lead0) { fmpz_print(anum + 1); flint_printf("*%s", var); if (fmpz_sgn(anum) >= 0) printf("+"); } fmpz_print(anum); if (!den1 && !lead0) flint_printf(")"); if (!den1) { flint_printf("/"); fmpz_print(aden); } } else { fmpq_poly_print_pretty(NF_ELEM(a), var); } } flint-3.1.3/src/nf_elem/is_gen.c000066400000000000000000000025321461254215100164410ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" int nf_elem_is_gen(const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_t t1, t2; int is_gen; /* fast path */ if (fmpz_equal(LNF_ELEM_DENREF(a), nf->pol->coeffs + 1)) return fmpz_cmpabs(LNF_ELEM_DENREF(a), nf->pol->coeffs) == 0 && fmpz_sgn(LNF_ELEM_DENREF(a)) == -fmpz_sgn(nf->pol->coeffs); /* slow path */ fmpz_init(t1); fmpz_init(t2); fmpz_mul(t1, LNF_ELEM_NUMREF(a), nf->pol->coeffs + 1); fmpz_mul(t2, LNF_ELEM_DENREF(a), nf->pol->coeffs); fmpz_neg(t1, t1); is_gen = fmpz_equal(t1, t2); fmpz_clear(t1); fmpz_clear(t2); return is_gen; } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); return fmpz_equal(anum + 1, QNF_ELEM_DENREF(a)) && fmpz_is_zero(anum); } else return fmpq_poly_length(NF_ELEM(a)) == 2 && fmpz_equal(NF_ELEM(a)->coeffs + 1, NF_ELEM(a)->den) && fmpz_is_zero(NF_ELEM(a)->coeffs); } flint-3.1.3/src/nf_elem/mod_fmpz.c000066400000000000000000000144151461254215100170130ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void _nf_elem_mod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int sign) { if (nf_elem_is_zero(a, nf)) { nf_elem_zero(res, nf); return; } if (nf->flag & NF_LINEAR) { if (sign == 0) fmpz_mod(LNF_ELEM_NUMREF(res), LNF_ELEM_NUMREF(a), mod); else fmpz_smod(LNF_ELEM_NUMREF(res), LNF_ELEM_NUMREF(a), mod); fmpz_one(LNF_ELEM_DENREF(res)); } else if (nf->flag & NF_QUADRATIC) { if (sign == 0) _fmpz_vec_scalar_mod_fmpz(QNF_ELEM_NUMREF(res), QNF_ELEM_NUMREF(a), 3, mod); else _fmpz_vec_scalar_smod_fmpz(QNF_ELEM_NUMREF(res), QNF_ELEM_NUMREF(a), 3, mod); fmpz_one(QNF_ELEM_DENREF(res)); } else { fmpq_poly_fit_length(NF_ELEM(res), fmpq_poly_length(NF_ELEM(a))); _fmpq_poly_set_length(NF_ELEM(res), fmpq_poly_length(NF_ELEM(a))); if (sign == 0) _fmpz_vec_scalar_mod_fmpz(NF_ELEM(res)->coeffs, NF_ELEM(a)->coeffs, fmpq_poly_length(NF_ELEM(a)), mod); else _fmpz_vec_scalar_smod_fmpz(NF_ELEM(res)->coeffs, NF_ELEM(a)->coeffs, fmpq_poly_length(NF_ELEM(a)), mod); fmpz_one(NF_ELEM_DENREF(res)); } nf_elem_canonicalise(res, nf); } void _nf_elem_mod_fmpz_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int den, int sign) { if (!den || nf_elem_den_is_one(a, nf)) { _nf_elem_mod_fmpz(res, a, mod, nf, sign); } else { fmpz_t t; fmpz_init(t); nf_elem_get_den(t, a, nf); fmpz_mul(t, t, mod); _nf_elem_mod_fmpz(res, a, t, nf, sign); if (nf->flag & NF_LINEAR) { nf_elem_scalar_div_fmpz(res, res, LNF_ELEM_DENREF(a), nf); } else if (nf->flag & NF_QUADRATIC) { nf_elem_scalar_div_fmpz(res, res, QNF_ELEM_DENREF(a), nf); } else { nf_elem_scalar_div_fmpz(res, res, NF_ELEM_DENREF(a), nf); } fmpz_clear(t); } } void nf_elem_mod_fmpz_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int den) { _nf_elem_mod_fmpz_den(res, a, mod, nf, den, 0); } void nf_elem_smod_fmpz_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int den) { _nf_elem_mod_fmpz_den(res, a, mod, nf, den, 1); } void nf_elem_mod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) { nf_elem_mod_fmpz_den(res, a, mod, nf, 1); } void nf_elem_smod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) { nf_elem_smod_fmpz_den(res, a, mod, nf, 1); } static void _fmpz_ppio(fmpz_t ppi, fmpz_t ppo, const fmpz_t a, const fmpz_t b) { fmpz_t c, n, g; fmpz_init(c); fmpz_init(n); fmpz_init(g); fmpz_gcd(c, a, b); fmpz_divexact(n, a, c); fmpz_gcd(g, c, n); while (!fmpz_is_one(g)) { fmpz_mul(c, c, g); fmpz_divexact(n, n, g); fmpz_gcd(g, c, n); } fmpz_set(ppi, c); fmpz_set(ppo, n); fmpz_clear(c); fmpz_clear(n); fmpz_clear(g); } void _nf_elem_coprime_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf, int sign) { if (nf_elem_is_zero(a, nf)) { nf_elem_zero(res, nf); return; } if (nf_elem_den_is_one(a, nf)) { _nf_elem_mod_fmpz_den(res, a, mod, nf, 0, sign); return ; } if (nf->flag & NF_LINEAR) { fmpz_t c, nc; fmpz_init(c); fmpz_init(nc); _fmpz_ppio(c, nc, LNF_ELEM_DENREF(a), mod); fmpz_mul(LNF_ELEM_DENREF(res), mod, c); fmpz_invmod(nc, nc, LNF_ELEM_DENREF(res)); fmpz_mul(LNF_ELEM_NUMREF(res), LNF_ELEM_NUMREF(a), nc); if (sign == 0) fmpz_mod(LNF_ELEM_NUMREF(res), LNF_ELEM_NUMREF(res), LNF_ELEM_DENREF(res)); else fmpz_smod(LNF_ELEM_NUMREF(res), LNF_ELEM_NUMREF(res), LNF_ELEM_DENREF(res)); fmpz_set(LNF_ELEM_DENREF(res), c); fmpz_clear(c); fmpz_clear(nc); } else if (nf->flag & NF_QUADRATIC) { fmpz_t c, nc; fmpz_init(c); fmpz_init(nc); _fmpz_ppio(c, nc, QNF_ELEM_DENREF(a), mod); fmpz_mul(QNF_ELEM_DENREF(res), mod, c); fmpz_invmod(nc, nc, QNF_ELEM_DENREF(res)); _fmpz_vec_scalar_mul_fmpz(QNF_ELEM_NUMREF(res), QNF_ELEM_NUMREF(a), 3, nc); if (sign == 0) _fmpz_vec_scalar_mod_fmpz(QNF_ELEM_NUMREF(res), QNF_ELEM_NUMREF(res), 3, QNF_ELEM_DENREF(res)); else _fmpz_vec_scalar_smod_fmpz(QNF_ELEM_NUMREF(res), QNF_ELEM_NUMREF(res), 3, QNF_ELEM_DENREF(res)); fmpz_set(QNF_ELEM_DENREF(res), c); fmpz_clear(c); fmpz_clear(nc); } else { fmpz_t c, nc; fmpz_init(c); fmpz_init(nc); fmpq_poly_fit_length(NF_ELEM(res), fmpq_poly_length(NF_ELEM(a))); _fmpz_ppio(c, nc, NF_ELEM_DENREF(a), mod); fmpz_mul(NF_ELEM_DENREF(res), mod, c); fmpz_invmod(nc, nc, NF_ELEM_DENREF(res)); _fmpz_vec_scalar_mul_fmpz(NF_ELEM(res)->coeffs, NF_ELEM(a)->coeffs, fmpq_poly_length(NF_ELEM(a)), nc); if (sign == 0) _fmpz_vec_scalar_mod_fmpz(NF_ELEM(res)->coeffs, NF_ELEM(res)->coeffs, fmpq_poly_length(NF_ELEM(a)), NF_ELEM_DENREF(res)); else _fmpz_vec_scalar_smod_fmpz(NF_ELEM(res)->coeffs, NF_ELEM(res)->coeffs, fmpq_poly_length(NF_ELEM(a)), NF_ELEM_DENREF(res)); fmpz_set(NF_ELEM_DENREF(res), c); _fmpq_poly_set_length(NF_ELEM(res), fmpq_poly_length(NF_ELEM(a))); fmpz_clear(c); fmpz_clear(nc); } nf_elem_canonicalise(res, nf); } void nf_elem_coprime_den_signed(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) { _nf_elem_coprime_den(res, a, mod, nf, 1); } void nf_elem_coprime_den(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf) { _nf_elem_coprime_den(res, a, mod, nf, 0); } flint-3.1.3/src/nf_elem/mul.c000066400000000000000000000165341461254215100160010ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void _nf_elem_mul_gaussian(fmpz * anum, fmpz * aden, const fmpz * bnum, const fmpz * bden, const fmpz * cnum, const fmpz * cden) { fmpz_t t; fmpz_init(t); if (anum == bnum || anum == cnum) /* aliasing */ { if (bnum == cnum && bden == cden) /* squaring */ { fmpz_fmms(t, bnum + 0, bnum + 0, bnum + 1, bnum + 1); fmpz_mul(anum + 1, bnum + 0, bnum + 1); fmpz_mul_2exp(anum + 1, anum + 1, 1); } else { fmpz_fmms(t, bnum + 0, cnum + 0, bnum + 1, cnum + 1); fmpz_fmma(anum + 1, bnum + 0, cnum + 1, bnum + 1, cnum + 0); } fmpz_swap(anum + 0, t); } else { if (bnum == cnum && bden == cden) /* squaring */ { fmpz_fmms(anum + 0, bnum + 0, bnum + 0, bnum + 1, bnum + 1); fmpz_mul(anum + 1, bnum + 0, bnum + 1); fmpz_mul_2exp(anum + 1, anum + 1, 1); } else { fmpz_fmms(anum + 0, bnum + 0, cnum + 0, bnum + 1, cnum + 1); fmpz_fmma(anum + 1, bnum + 0, cnum + 1, bnum + 1, cnum + 0); } } fmpz_zero(anum + 2); fmpz_mul(aden, bden, cden); if (!fmpz_is_one(aden)) { fmpz_gcd3(t, anum + 0, anum + 1, aden); if (!fmpz_is_one(t)) { fmpz_divexact(anum + 0, anum + 0, t); fmpz_divexact(anum + 1, anum + 1, t); fmpz_divexact(aden, aden, t); } } fmpz_clear(t); } void _nf_elem_mul_red(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int red) { if (nf->flag & NF_LINEAR) { const fmpz * const bnum = LNF_ELEM_NUMREF(b); const fmpz * const bden = LNF_ELEM_DENREF(b); const fmpz * const cnum = LNF_ELEM_NUMREF(c); const fmpz * const cden = LNF_ELEM_DENREF(c); fmpz * const anum = LNF_ELEM_NUMREF(a); fmpz * const aden = LNF_ELEM_DENREF(a); fmpz_mul(anum, bnum, cnum); fmpz_mul(aden, bden, cden); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const bnum = QNF_ELEM_NUMREF(b); const fmpz * const bden = QNF_ELEM_DENREF(b); const fmpz * const cnum = QNF_ELEM_NUMREF(c); const fmpz * const cden = QNF_ELEM_DENREF(c); fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz * const aden = QNF_ELEM_DENREF(a); fmpz_mul(anum, bnum, cnum); fmpz_fmma(anum + 1, bnum, cnum + 1, bnum + 1, cnum); fmpz_mul(anum + 2, bnum + 1, cnum + 1); fmpz_mul(aden, bden, cden); if (red && !fmpz_is_zero(anum + 2)) { fmpz * pnum = fmpq_poly_numref(nf->pol); if (nf->flag & NF_MONIC) { fmpz_submul(anum + 1, anum + 2, pnum + 1); fmpz_submul(anum, anum + 2, pnum); } else { fmpz * prod = _fmpz_vec_init(3); _fmpq_poly_scalar_mul_fmpq(prod, prod + 2, pnum, pnum + 2, 2, anum + 2, aden); _fmpq_poly_sub_can(anum, aden, anum, aden, 2, prod, prod + 2, 2, 0); _fmpz_vec_clear(prod, 3); } fmpz_zero(anum + 2); } } else /* generic nf_elem */ { const slong len1 = NF_ELEM(b)->length; const slong len2 = NF_ELEM(c)->length; const slong len = nf->pol->length; slong plen = len1 + len2 - 1; if (len1 == 0 || len2 == 0) { nf_elem_zero(a, nf); return; } fmpq_poly_fit_length(NF_ELEM(a), plen); if (len1 >= len2) { _fmpz_poly_mul(NF_ELEM_NUMREF(a), NF_ELEM_NUMREF(b), len1, NF_ELEM_NUMREF(c), len2); } else { _fmpz_poly_mul(NF_ELEM_NUMREF(a), NF_ELEM_NUMREF(c), len2, NF_ELEM_NUMREF(b), len1); } fmpz_mul(fmpq_poly_denref(NF_ELEM(a)), fmpq_poly_denref(NF_ELEM(b)), fmpq_poly_denref(NF_ELEM(c))); _fmpq_poly_set_length(NF_ELEM(a), plen); if (red && plen >= len) { if (nf->flag & NF_MONIC) { if (len <= NF_POWERS_CUTOFF) { _fmpz_poly_rem_powers_precomp(NF_ELEM_NUMREF(a), plen, fmpq_poly_numref(nf->pol), len, nf->powers.zz->powers); _fmpq_poly_set_length(NF_ELEM(a), len - 1); _fmpq_poly_normalise(NF_ELEM(a)); } else { fmpz * q = _fmpz_vec_init(plen - len + 1); fmpz * r = _fmpz_vec_init(plen); slong i; _fmpz_vec_set(r, NF_ELEM_NUMREF(a), plen); _fmpz_poly_divrem(q, NF_ELEM_NUMREF(a), r, plen, fmpq_poly_numref(nf->pol), len, 0); _fmpz_vec_clear(r, plen); _fmpz_vec_clear(q, plen - len + 1); for (i = len - 2; i >= 0 && fmpz_is_zero(NF_ELEM_NUMREF(a) + i); i--); NF_ELEM(a)->length = i + 1; } } else { fmpq_poly_t t; if (len <= NF_POWERS_CUTOFF) { _fmpq_poly_rem_powers_precomp(NF_ELEM_NUMREF(a), fmpq_poly_denref(NF_ELEM(a)), plen, fmpq_poly_numref(nf->pol), fmpq_poly_denref(nf->pol), len, nf->powers.qq->powers); _fmpq_poly_set_length(NF_ELEM(a), len - 1); _fmpq_poly_normalise(NF_ELEM(a)); } else { fmpq_poly_init2(t, 2*len - 3); _fmpq_poly_rem(t->coeffs, t->den, NF_ELEM(a)->coeffs, NF_ELEM(a)->den, plen, nf->pol->coeffs, nf->pol->den, len, nf->pinv.qq); _fmpq_poly_set_length(t, len - 1); _fmpq_poly_normalise(t); fmpq_poly_swap(t, NF_ELEM(a)); fmpq_poly_clear(t); } } } } } void _nf_elem_mul(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { _nf_elem_mul_red(a, b, c, nf, 1); } void nf_elem_mul_red(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int red) { nf_elem_t t; if (nf->flag & NF_LINEAR) { _fmpq_mul(LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a), LNF_ELEM_NUMREF(b), LNF_ELEM_DENREF(b), LNF_ELEM_NUMREF(c), LNF_ELEM_DENREF(c)); } else if ((nf->flag & NF_GAUSSIAN) && fmpz_is_zero(QNF_ELEM_NUMREF(b) + 2) && fmpz_is_zero(QNF_ELEM_NUMREF(c) + 2)) { _nf_elem_mul_gaussian(QNF_ELEM_NUMREF(a), QNF_ELEM_DENREF(a), QNF_ELEM_NUMREF(b), QNF_ELEM_DENREF(b), QNF_ELEM_NUMREF(c), QNF_ELEM_DENREF(c)); } else { if (a == b || a == c) { nf_elem_init(t, nf); _nf_elem_mul_red(t, b, c, nf, red); nf_elem_swap(t, a, nf); nf_elem_clear(t, nf); } else _nf_elem_mul_red(a, b, c, nf, red); nf_elem_canonicalise(a, nf); } } void nf_elem_mul(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { nf_elem_mul_red(a, b, c, nf, 1); } flint-3.1.3/src/nf_elem/mul_gen.c000066400000000000000000000031411461254215100166200ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_mul_gen(nf_elem_t a, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz * den = LNF_ELEM_DENREF(a); fmpz * num = LNF_ELEM_NUMREF(a); /* _fmpq_mul assumes a positive denominator */ if (fmpz_sgn(fmpq_poly_numref(nf->pol) + 1) < 0) { fmpz_t t; fmpz_init(t); fmpz_neg(t, fmpq_poly_numref(nf->pol) + 1); _fmpq_mul(num, den, LNF_ELEM_NUMREF(b), LNF_ELEM_DENREF(b), fmpq_poly_numref(nf->pol), t); fmpz_clear(t); } else { _fmpq_mul(num, den, LNF_ELEM_NUMREF(b), LNF_ELEM_DENREF(b), fmpq_poly_numref(nf->pol), fmpq_poly_numref(nf->pol) + 1); fmpz_neg(num, num); } _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz * anum = QNF_ELEM_NUMREF(a); fmpz const * bnum = QNF_ELEM_NUMREF(b); fmpz_set(anum + 2, bnum + 1); fmpz_set(anum + 1, bnum); fmpz_zero(anum); fmpz_set(QNF_ELEM_DENREF(a), QNF_ELEM_DENREF(b)); nf_elem_reduce(a, nf); nf_elem_canonicalise(a, nf); } else { fmpq_poly_shift_left(NF_ELEM(a), NF_ELEM(b), 1); nf_elem_reduce(a, nf); nf_elem_canonicalise(a, nf); } } flint-3.1.3/src/nf_elem/neg.c000066400000000000000000000016771461254215100157570ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_neg(nf_elem_t a, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_neg(LNF_ELEM_NUMREF(a), LNF_ELEM_NUMREF(b)); fmpz_set(LNF_ELEM_DENREF(a), LNF_ELEM_DENREF(b)); } else if (nf->flag & NF_QUADRATIC) { fmpz *const anum = QNF_ELEM_NUMREF(a); const fmpz *const bnum = QNF_ELEM_NUMREF(b); fmpz_neg(anum, bnum); fmpz_neg(anum + 1, bnum + 1); fmpz_set(QNF_ELEM_DENREF(a), QNF_ELEM_DENREF(b)); } else fmpq_poly_neg(NF_ELEM(a), NF_ELEM(b)); } flint-3.1.3/src/nf_elem/norm.c000066400000000000000000000054171461254215100161550ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "nf_elem.h" void _nf_elem_norm(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { const fmpz * const anum = LNF_ELEM_NUMREF(a); const fmpz * const aden = LNF_ELEM_DENREF(a); fmpz_set(rnum, anum); fmpz_set(rden, aden); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); const fmpz * const aden = QNF_ELEM_DENREF(a); fmpz_t pow, one; slong alen = 2; while (alen > 0 && fmpz_is_zero(anum + alen - 1)) alen--; if (alen == 0) { fmpz_zero(rnum); fmpz_one(rden); return; } fmpz_init_set_ui(one, 1); fmpz_init(pow); _fmpq_poly_resultant(rnum, rden, nf->pol->coeffs, one, 3, anum, aden, alen); if (!fmpz_is_one(nf->pol->coeffs + 2) && alen > 1) { fmpz_pow_ui(pow, nf->pol->coeffs + 2, alen - 1); if (fmpz_sgn(pow) < 0) { fmpz_neg(one, one); fmpz_neg(pow, pow); } _fmpq_mul(rnum, rden, rnum, rden, one, pow); if (fmpz_sgn(rden) < 0) { fmpz_neg(rnum, rnum); fmpz_neg(rden, rden); } } fmpz_clear(one); fmpz_clear(pow); } else /* generic nf_elem */ { const fmpz * const anum = NF_ELEM_NUMREF(a); const fmpz * const aden = NF_ELEM_DENREF(a); fmpz_t pow, one; slong alen = NF_ELEM(a)->length; slong len = nf->pol->length; fmpz * coeffs = nf->pol->coeffs; if (alen == 0) { fmpz_zero(rnum); fmpz_one(rden); return; } fmpz_init_set_ui(one, 1); fmpz_init(pow); _fmpq_poly_resultant(rnum, rden, nf->pol->coeffs, one, len, anum, aden, alen); if (!fmpz_is_one(coeffs + len - 1) && alen > 1) { fmpz_pow_ui(pow, coeffs + len - 1, alen - 1); if (fmpz_sgn(pow) < 0) { fmpz_neg(one, one); fmpz_neg(pow, pow); } _fmpq_mul(rnum, rden, rnum, rden, one, pow); if (fmpz_sgn(rden) < 0) { fmpz_neg(rnum, rnum); fmpz_neg(rden, rden); } } fmpz_clear(one); fmpz_clear(pow); } } void nf_elem_norm(fmpq_t res, const nf_elem_t a, const nf_t nf) { _nf_elem_norm(fmpq_numref(res), fmpq_denref(res), a, nf); } flint-3.1.3/src/nf_elem/norm_div.c000066400000000000000000000062651461254215100170210ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart Copyright (C) 2015 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "nf_elem.h" void _nf_elem_norm_div(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf, const fmpz_t divisor, slong nbits) { if (fmpz_is_zero(divisor)) { fmpz_zero(rnum); fmpz_one(rden); return; } if (nf->flag & NF_LINEAR) { const fmpz * const anum = LNF_ELEM_NUMREF(a); const fmpz * const aden = LNF_ELEM_DENREF(a); fmpz_gcd(rden, anum, divisor); fmpz_divexact(rnum, anum, rden); fmpz_divexact(rden, divisor, rden); fmpz_mul(rden, rden, aden); if (fmpz_sgn(rden) == -1) { fmpz_neg(rden, rden); fmpz_neg(rnum, rnum); } } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); const fmpz * const aden = QNF_ELEM_DENREF(a); fmpz_t pow, one; slong alen = 2; while (alen > 0 && fmpz_is_zero(anum + alen - 1)) alen--; if (alen == 0) { fmpz_zero(rnum); fmpz_one(rden); return; } fmpz_init_set_ui(one, 1); fmpz_init(pow); _fmpq_poly_resultant_div(rnum, rden, nf->pol->coeffs, one, 3, anum, aden, alen, divisor, nbits); if (!fmpz_is_one(nf->pol->coeffs + 2) && alen > 1) { fmpz_pow_ui(pow, nf->pol->coeffs + 2, alen - 1); _fmpq_mul(rnum, rden, rnum, rden, one, pow); if (fmpz_sgn(rden) < 0) { fmpz_neg(rnum, rnum); fmpz_neg(rden, rden); } } fmpz_clear(one); fmpz_clear(pow); } else /* generic nf_elem */ { const fmpz * const anum = NF_ELEM_NUMREF(a); const fmpz * const aden = NF_ELEM_DENREF(a); fmpz_t pow, one; slong alen = NF_ELEM(a)->length; slong len = nf->pol->length; fmpz * coeffs = nf->pol->coeffs; if (alen == 0) { fmpz_zero(rnum); fmpz_one(rden); return; } fmpz_init_set_ui(one, 1); fmpz_init(pow); _fmpq_poly_resultant_div(rnum, rden, nf->pol->coeffs, one, len, anum, aden, alen, divisor, nbits); if (!fmpz_is_one(coeffs + len - 1) && alen > 1) { fmpz_pow_ui(pow, coeffs + len - 1, alen - 1); _fmpq_mul(rnum, rden, rnum, rden, one, pow); if (fmpz_sgn(rden) < 0) { fmpz_neg(rnum, rnum); fmpz_neg(rden, rden); } } fmpz_clear(one); fmpz_clear(pow); } } void nf_elem_norm_div(fmpq_t res, const nf_elem_t a, const nf_t nf, const fmpz_t divisor, slong nbits) { _nf_elem_norm_div(fmpq_numref(res), fmpq_denref(res), a, nf, divisor, nbits); } flint-3.1.3/src/nf_elem/one.c000066400000000000000000000014401461254215100157530ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_one(nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_one(LNF_ELEM_NUMREF(a)); fmpz_one(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz_one(anum); fmpz_zero(anum + 1); fmpz_one(QNF_ELEM_DENREF(a)); } else fmpq_poly_one(NF_ELEM(a)); } flint-3.1.3/src/nf_elem/pow.c000066400000000000000000000053601461254215100160040ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void _nf_elem_pow(nf_elem_t res, const nf_elem_t a, ulong e, const nf_t nf) { ulong bit = ~((~UWORD(0)) >> 1); nf_elem_t v; nf_elem_struct * R, * S, * T; nf_elem_init(v, nf); /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, len} */ nf_elem_mul(R, a, a, nf); if ((bit & e)) { nf_elem_mul(S, R, a, nf); T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { nf_elem_mul(S, R, R, nf); nf_elem_mul(R, S, a, nf); } else { nf_elem_mul(S, R, R, nf); T = R; R = S; S = T; } } nf_elem_clear(v, nf); } void nf_elem_pow(nf_elem_t res, const nf_elem_t a, ulong e, const nf_t nf) { nf_elem_t t; if (e == UWORD(0)) { nf_elem_one(res, nf); return; } if (nf_elem_is_zero(a, nf)) { nf_elem_zero(res, nf); return; } if (nf->flag & NF_LINEAR) _fmpq_pow_si(LNF_ELEM_NUMREF(res), LNF_ELEM_DENREF(res), LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a), e); else { if (e < UWORD(3)) { if (e == UWORD(1)) nf_elem_set(res, a, nf); else /* e == UWORD(2) */ nf_elem_mul(res, a, a, nf); return; } if (res == a) { nf_elem_init(t, nf); _nf_elem_pow(t, a, e, nf); nf_elem_swap(t, res, nf); nf_elem_clear(t, nf); } else _nf_elem_pow(res, a, e, nf); } } flint-3.1.3/src/nf_elem/profile/000077500000000000000000000000001461254215100164675ustar00rootroot00000000000000flint-3.1.3/src/nf_elem/profile/nf_elem_mul.m000066400000000000000000000152241461254215100211330ustar00rootroot00000000000000/*============================================================================ This file is part of Antic. Antic is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . ===============================================================================*/ /* Profiling MAGMA polynomial multiplication in Z[x]. Usage: run magma with the -b flag to prevent the start up banner, i.e. magma -b magma-profile.m > output.prof (C) 2007 David Harvey + Bill Hart, GPL */ target_name := "NFElemMul"; target_description := "MAGMA number field element multiplication over various degree"; BITS := 10; // bits per coefficient ratio := 1.1; // ratio between consecutive lengths monic := false; // monic integral case or generic rational case R:=PolynomialRing(Rationals()); S:=PolynomialRing(Integers()); // Timing runs need to last at least this many microseconds to be counted: DURATION_THRESHOLD := 200000; // Microseconds per timing run that the prof2d_sample function aims for: DURATION_TARGET := 300000; forward prof2d_sample; /* This function should run count iterations at position (x, y), and return the total time in seconds, using the Cputime() function. */ function sampler(length, bits, count) // first time random element generation + multiplication countmod := 100; if length ge 50 then countmod := 10; end if; if length ge 500 then countmod := 4; end if; time1 := Cputime(); for i := 1 to count do if (i-1) mod countmod eq 0 then p:=Polynomial([(-1)^Random(1)*RandomBits(bits): x in [1..length-1]]); if monic then p1:=S!p + x^(length-1); else den:=RandomBits(bits); if den eq 0 then den:=1; end if; p1:=((R!p)+(-1)^Random(1)*RandomBits(bits)*x^(length-1))/den; end if; if Degree(p1) eq 0 then if monic then p1:=x+1; else p1:=y+1; end if; end if; K:=NumberField(p1:Check:=false); a:=Random(K,2^bits); b:=Random(K,2^bits); if monic then a:=Numerator(a); b:=Numerator(a); end if; end if; c:=Numerator(a*b); end for; time2 := Cputime(); // now time just the random element generation for i := 1 to count do if (i-1) mod countmod eq 0 then p:=Polynomial([(-1)^Random(1)*RandomBits(bits): x in [1..length-1]]); if monic then p1:=S!p + x^(length-1); else den:=RandomBits(bits); if den eq 0 then den:=1; end if; p1:=((R!p)+(-1)^Random(1)*RandomBits(bits)*x^(length-1))/den; end if; if Degree(p1) eq 0 then if monic then p1:=x+1; else p1:=y+1; end if; end if; K:=NumberField(p1:Check:=false); a:=Random(K,2^bits); b:=Random(K,2^bits); if monic then a:=Numerator(a); b:=Numerator(a); end if; end if; c:=a; end for; time3 := Cputime(); return (time2 - time1) - (time3 - time2); end function; /* This function should loop over appropriate combinations of (x, y), and call prof2d_sample(x, y) for each one. */ procedure driver() length:=2; while length lt 10000 do monic:=0; prof2d_sample(length, BITS); monic:=1; prof2d_sample(length, BITS); length := Ceiling(length*ratio); end while; end procedure; /************************************************************************ This last section is the generic profiling code. Just leave this stuff alone. ************************************************************************/ /* Formats in scientific notation with 3 decimal places */ function format_sci(x) L := Floor(Log(10, x)); x := x / 10^L; s := Sprintf("%.3oe", x); if L lt 0 then s := s cat "-"; else s := s cat "+"; end if; s := s cat Sprintf("%o", Floor(Abs(L / 10))); s := s cat Sprintf("%o", (Abs(L) mod 10)); return s; end function; procedure prof2d_sample(x, y) // number of timings that were at least DURATION_THRESHOLD microseconds: good_count := 0; // first try just a few loops num_trials := 4; last_time := sampler(x, y, num_trials) * 1000000.0; max_time := 0; min_time := 0; // loop until we have enough good times while true do per_trial := last_time / num_trials; // if the last recorded time was long enough, record it if last_time gt DURATION_THRESHOLD then if good_count gt 0 then max_time := Max(max_time, per_trial); min_time := Min(min_time, per_trial); else max_time := per_trial; min_time := per_trial; end if; good_count := good_count + 1; if good_count eq 5 then // we've got enough data // print it out and return print Sprintf("%o\t%o\t%o\t%o", x, y, format_sci(min_time), format_sci(max_time)); return; end if; end if; // adjust num_trials so that the elapsed time gravitates towards // DURATION_TARGET; num_trials can be changed by a factor of // at most 25%, and must be at least 1 if last_time lt 0.0001 then last_time := 0.0001; end if; adjust_ratio := 1.0 * DURATION_TARGET / last_time; if adjust_ratio gt 1.25 then adjust_ratio := 1.25; end if; if adjust_ratio lt 0.75 then adjust_ratio := 0.75; end if; num_trials := Ceiling(adjust_ratio * num_trials); // just to be safe: if num_trials eq 0 then num_trials := 1; end if; // run another trial last_time := sampler(x, y, num_trials) * 1000000.0; end while; end procedure; procedure print_header() print "FLINT profile output"; print ""; print "TIMESTAMP: (todo: write code to generate timestamp)"; print "MACHINE: (todo: write code to get machine from environment var)"; print ""; print "MODULE: magma"; print "TARGET:", target_name; print ""; print "DESCRIPTION:"; print target_description; print ""; print "============================================== begin data"; end procedure; print_header(); driver(); quit; // ------------- end of file ------------------------------------ flint-3.1.3/src/nf_elem/profile/nf_elem_norm.m000066400000000000000000000150061461254215100213070ustar00rootroot00000000000000/*============================================================================ This file is part of Antic. Antic is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . ===============================================================================*/ /* Profiling MAGMA polynomial multiplication in Z[x]. Usage: run magma with the -b flag to prevent the start up banner, i.e. magma -b magma-profile.m > output.prof (C) 2007 David Harvey + Bill Hart, GPL */ target_name := "NFElemNorm"; target_description := "MAGMA number field norm over various degree"; BITS := 10; // bits per coefficient ratio := 1.1; // ratio between consecutive lengths monic := false; // monic integral case or generic rational case R:=PolynomialRing(Rationals()); S:=PolynomialRing(Integers()); // Timing runs need to last at least this many microseconds to be counted: DURATION_THRESHOLD := 200000; // Microseconds per timing run that the prof2d_sample function aims for: DURATION_TARGET := 300000; forward prof2d_sample; /* This function should run count iterations at position (x, y), and return the total time in seconds, using the Cputime() function. */ function sampler(length, bits, count) // first time random element generation + multiplication countmod := 100; if length ge 50 then countmod := 10; end if; if length ge 500 then countmod := 4; end if; time1 := Cputime(); for i := 1 to count do if (i-1) mod countmod eq 0 then p:=Polynomial([(-1)^Random(1)*RandomBits(bits): x in [1..length-1]]); if monic then p1:=S!p + x^(length-1); else den:=RandomBits(bits); if den eq 0 then den:=1; end if; p1:=((R!p)+(-1)^Random(1)*RandomBits(bits)*x^(length-1))/den; end if; if Degree(p1) eq 0 then if monic then p1:=x+1; else p1:=y+1; end if; end if; K:=NumberField(p1:Check:=false); a:=Random(K,2^bits); if monic then a:=Numerator(a); end if; end if; c:=Norm(a); end for; time2 := Cputime(); // now time just the random element generation for i := 1 to count do if (i-1) mod countmod eq 0 then p:=Polynomial([(-1)^Random(1)*RandomBits(bits): x in [1..length-1]]); if monic then p1:=S!p + x^(length-1); else den:=RandomBits(bits); if den eq 0 then den:=1; end if; p1:=((R!p)+(-1)^Random(1)*RandomBits(bits)*x^(length-1))/den; end if; if Degree(p1) eq 0 then if monic then p1:=x+1; else p1:=y+1; end if; end if; K:=NumberField(p1:Check:=false); a:=Random(K,2^bits); if monic then a:=Numerator(a); end if; end if; c:=a; end for; time3 := Cputime(); return (time2 - time1) - (time3 - time2); end function; /* This function should loop over appropriate combinations of (x, y), and call prof2d_sample(x, y) for each one. */ procedure driver() length:=2; while length lt 10000 do monic:=0; prof2d_sample(length, BITS); monic:=1; prof2d_sample(length, BITS); length := Ceiling(length*ratio); end while; end procedure; /************************************************************************ This last section is the generic profiling code. Just leave this stuff alone. ************************************************************************/ /* Formats in scientific notation with 3 decimal places */ function format_sci(x) L := Floor(Log(10, x)); x := x / 10^L; s := Sprintf("%.3oe", x); if L lt 0 then s := s cat "-"; else s := s cat "+"; end if; s := s cat Sprintf("%o", Floor(Abs(L / 10))); s := s cat Sprintf("%o", (Abs(L) mod 10)); return s; end function; procedure prof2d_sample(x, y) // number of timings that were at least DURATION_THRESHOLD microseconds: good_count := 0; // first try just a few loops num_trials := 4; last_time := sampler(x, y, num_trials) * 1000000.0; max_time := 0; min_time := 0; // loop until we have enough good times while true do per_trial := last_time / num_trials; // if the last recorded time was long enough, record it if last_time gt DURATION_THRESHOLD then if good_count gt 0 then max_time := Max(max_time, per_trial); min_time := Min(min_time, per_trial); else max_time := per_trial; min_time := per_trial; end if; good_count := good_count + 1; if good_count eq 5 then // we've got enough data // print it out and return print Sprintf("%o\t%o\t%o\t%o", x, y, format_sci(min_time), format_sci(max_time)); return; end if; end if; // adjust num_trials so that the elapsed time gravitates towards // DURATION_TARGET; num_trials can be changed by a factor of // at most 25%, and must be at least 1 if last_time lt 0.0001 then last_time := 0.0001; end if; adjust_ratio := 1.0 * DURATION_TARGET / last_time; if adjust_ratio gt 1.25 then adjust_ratio := 1.25; end if; if adjust_ratio lt 0.75 then adjust_ratio := 0.75; end if; num_trials := Ceiling(adjust_ratio * num_trials); // just to be safe: if num_trials eq 0 then num_trials := 1; end if; // run another trial last_time := sampler(x, y, num_trials) * 1000000.0; end while; end procedure; procedure print_header() print "FLINT profile output"; print ""; print "TIMESTAMP: (todo: write code to generate timestamp)"; print "MACHINE: (todo: write code to get machine from environment var)"; print ""; print "MODULE: magma"; print "TARGET:", target_name; print ""; print "DESCRIPTION:"; print target_description; print ""; print "============================================== begin data"; end procedure; print_header(); driver(); quit; // ------------- end of file ------------------------------------ flint-3.1.3/src/nf_elem/profile/nf_elem_trace.m000066400000000000000000000150111461254215100214260ustar00rootroot00000000000000/*============================================================================ This file is part of Antic. Antic is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . ===============================================================================*/ /* Profiling MAGMA polynomial multiplication in Z[x]. Usage: run magma with the -b flag to prevent the start up banner, i.e. magma -b magma-profile.m > output.prof (C) 2007 David Harvey + Bill Hart, GPL */ target_name := "NFElemTrace"; target_description := "MAGMA number field trace over various degree"; BITS := 10; // bits per coefficient ratio := 1.1; // ratio between consecutive lengths monic := false; // monic integral case or generic rational case R:=PolynomialRing(Rationals()); S:=PolynomialRing(Integers()); // Timing runs need to last at least this many microseconds to be counted: DURATION_THRESHOLD := 200000; // Microseconds per timing run that the prof2d_sample function aims for: DURATION_TARGET := 300000; forward prof2d_sample; /* This function should run count iterations at position (x, y), and return the total time in seconds, using the Cputime() function. */ function sampler(length, bits, count) // first time random element generation + multiplication countmod := 100; if length ge 50 then countmod := 10; end if; if length ge 500 then countmod := 4; end if; time1 := Cputime(); for i := 1 to count do if (i-1) mod countmod eq 0 then p:=Polynomial([(-1)^Random(1)*RandomBits(bits): x in [1..length-1]]); if monic then p1:=S!p + x^(length-1); else den:=RandomBits(bits); if den eq 0 then den:=1; end if; p1:=((R!p)+(-1)^Random(1)*RandomBits(bits)*x^(length-1))/den; end if; if Degree(p1) eq 0 then if monic then p1:=x+1; else p1:=y+1; end if; end if; K:=NumberField(p1:Check:=false); a:=Random(K,2^bits); if monic then a:=Numerator(a); end if; end if; c:=Trace(a); end for; time2 := Cputime(); // now time just the random element generation for i := 1 to count do if (i-1) mod countmod eq 0 then p:=Polynomial([(-1)^Random(1)*RandomBits(bits): x in [1..length-1]]); if monic then p1:=S!p + x^(length-1); else den:=RandomBits(bits); if den eq 0 then den:=1; end if; p1:=((R!p)+(-1)^Random(1)*RandomBits(bits)*x^(length-1))/den; end if; if Degree(p1) eq 0 then if monic then p1:=x+1; else p1:=y+1; end if; end if; K:=NumberField(p1:Check:=false); a:=Random(K,2^bits); if monic then a:=Numerator(a); end if; end if; c:=a; end for; time3 := Cputime(); return (time2 - time1) - (time3 - time2); end function; /* This function should loop over appropriate combinations of (x, y), and call prof2d_sample(x, y) for each one. */ procedure driver() length:=2; while length lt 10000 do monic:=0; prof2d_sample(length, BITS); monic:=1; prof2d_sample(length, BITS); length := Ceiling(length*ratio); end while; end procedure; /************************************************************************ This last section is the generic profiling code. Just leave this stuff alone. ************************************************************************/ /* Formats in scientific notation with 3 decimal places */ function format_sci(x) L := Floor(Log(10, x)); x := x / 10^L; s := Sprintf("%.3oe", x); if L lt 0 then s := s cat "-"; else s := s cat "+"; end if; s := s cat Sprintf("%o", Floor(Abs(L / 10))); s := s cat Sprintf("%o", (Abs(L) mod 10)); return s; end function; procedure prof2d_sample(x, y) // number of timings that were at least DURATION_THRESHOLD microseconds: good_count := 0; // first try just a few loops num_trials := 4; last_time := sampler(x, y, num_trials) * 1000000.0; max_time := 0; min_time := 0; // loop until we have enough good times while true do per_trial := last_time / num_trials; // if the last recorded time was long enough, record it if last_time gt DURATION_THRESHOLD then if good_count gt 0 then max_time := Max(max_time, per_trial); min_time := Min(min_time, per_trial); else max_time := per_trial; min_time := per_trial; end if; good_count := good_count + 1; if good_count eq 5 then // we've got enough data // print it out and return print Sprintf("%o\t%o\t%o\t%o", x, y, format_sci(min_time), format_sci(max_time)); return; end if; end if; // adjust num_trials so that the elapsed time gravitates towards // DURATION_TARGET; num_trials can be changed by a factor of // at most 25%, and must be at least 1 if last_time lt 0.0001 then last_time := 0.0001; end if; adjust_ratio := 1.0 * DURATION_TARGET / last_time; if adjust_ratio gt 1.25 then adjust_ratio := 1.25; end if; if adjust_ratio lt 0.75 then adjust_ratio := 0.75; end if; num_trials := Ceiling(adjust_ratio * num_trials); // just to be safe: if num_trials eq 0 then num_trials := 1; end if; // run another trial last_time := sampler(x, y, num_trials) * 1000000.0; end while; end procedure; procedure print_header() print "FLINT profile output"; print ""; print "TIMESTAMP: (todo: write code to generate timestamp)"; print "MACHINE: (todo: write code to get machine from environment var)"; print ""; print "MODULE: magma"; print "TARGET:", target_name; print ""; print "DESCRIPTION:"; print target_description; print ""; print "============================================== begin data"; end procedure; print_header(); driver(); quit; // ------------- end of file ------------------------------------ flint-3.1.3/src/nf_elem/profile/p-mul.c000066400000000000000000000061011461254215100176630ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "nf.h" #include "nf_elem.h" #define BITS 10 typedef struct { slong length; int monic; } info_t; void random_fmpq_poly(fmpq_poly_t pol, flint_rand_t state, slong length) { fmpz * arr; slong i; fmpq_poly_fit_length(pol, length); arr = fmpq_poly_numref(pol); for (i = 0; i < length; i++) fmpz_randbits(arr + i, state, BITS); fmpz_randbits(fmpq_poly_denref(pol), state, BITS); _fmpq_poly_set_length(pol, length); _fmpq_poly_normalise(pol); fmpq_poly_canonicalise(pol); } void random_nf_elem(nf_elem_t a, flint_rand_t state, nf_t nf) { slong len = nf->pol->length - 1; random_fmpq_poly(NF_ELEM(a), state, len); } void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong length = info->length, i, j; int monic = info->monic; int scale; flint_rand_t state; fmpq_poly_t pol; nf_t nf; nf_elem_t a, b, c; flint_randinit(state); scale = 100; if (length >= 50) scale = 10; if (length >= 500) scale = 4; fmpq_poly_init(pol); for (i = 0; i < count; i++) { random_fmpq_poly(pol, state, length); if (monic) { fmpz_one(fmpq_poly_denref(pol)); fmpq_poly_set_coeff_ui(pol, length - 1, 1); } nf_init(nf, pol); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); random_nf_elem(a, state, nf); random_nf_elem(b, state, nf); if (monic) { fmpz_one(fmpq_poly_denref(NF_ELEM(a))); fmpz_one(fmpq_poly_denref(NF_ELEM(b))); } prof_start(); for (j = 0; j < scale; j++) { nf_elem_mul(c, a, b, nf); } prof_stop(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); fmpq_poly_clear(pol); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("Number field element multiplication\n"); flint_printf("bits = %ld\n", BITS); for (k = 4; k <= 1000; k = (slong) ceil(1.1*k)) { info.length = k; info.monic = 0; scale = 100; if (k >= 50) scale = 10; if (k >= 500) scale = 4; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("length %wd, min %.3e us, max %.3e us\n", info.length, (min/scale), (max/scale) ); info.monic = 1; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("length %wd, min %.3e us, max %.3e us\n", info.length, (min/scale), (max/scale) ); } return 0; } flint-3.1.3/src/nf_elem/profile/p-norm.c000066400000000000000000000056631461254215100200550ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "nf.h" #include "nf_elem.h" #define BITS 10 typedef struct { slong length; int monic; } info_t; void random_fmpq_poly(fmpq_poly_t pol, flint_rand_t state, slong length) { fmpz * arr; slong i; fmpq_poly_fit_length(pol, length); arr = fmpq_poly_numref(pol); for (i = 0; i < length; i++) fmpz_randbits(arr + i, state, BITS); fmpz_randbits(fmpq_poly_denref(pol), state, BITS); _fmpq_poly_set_length(pol, length); _fmpq_poly_normalise(pol); fmpq_poly_canonicalise(pol); } void random_nf_elem(nf_elem_t a, flint_rand_t state, nf_t nf) { slong len = nf->pol->length - 1; random_fmpq_poly(NF_ELEM(a), state, len); } void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong length = info->length, i, j; int monic = info->monic; int scale; flint_rand_t state; fmpq_poly_t pol; nf_t nf; nf_elem_t a; fmpq_t norm; flint_randinit(state); scale = 100; if (length >= 50) scale = 10; if (length >= 500) scale = 4; fmpq_poly_init(pol); fmpq_init(norm); for (i = 0; i < count; i++) { random_fmpq_poly(pol, state, length); if (monic) { fmpz_one(fmpq_poly_denref(pol)); fmpq_poly_set_coeff_ui(pol, length - 1, 1); } nf_init(nf, pol); nf_elem_init(a, nf); random_nf_elem(a, state, nf); if (monic) fmpz_one(fmpq_poly_denref(NF_ELEM(a))); prof_start(); for (j = 0; j < scale; j++) { nf_elem_norm(norm, a, nf); } prof_stop(); } fmpq_clear(norm); nf_elem_clear(a, nf); nf_clear(nf); fmpq_poly_clear(pol); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("Number field element norm\n"); flint_printf("bits = %ld\n", BITS); for (k = 4; k <= 1000; k = (slong) ceil(1.1*k)) { info.length = k; info.monic = 0; scale = 100; if (k >= 50) scale = 10; if (k >= 500) scale = 4; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("generic: length %wd, min %.3e us, max %.3e us\n", info.length, (min/scale), (max/scale) ); info.monic = 1; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("monic : length %wd, min %.3e us, max %.3e us\n", info.length, (min/scale), (max/scale) ); } return 0; } flint-3.1.3/src/nf_elem/profile/p-trace.c000066400000000000000000000056751461254215100202030ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "nf.h" #include "nf_elem.h" #define BITS 10 typedef struct { slong length; int monic; } info_t; void random_fmpq_poly(fmpq_poly_t pol, flint_rand_t state, slong length) { fmpz * arr; slong i; fmpq_poly_fit_length(pol, length); arr = fmpq_poly_numref(pol); for (i = 0; i < length; i++) fmpz_randbits(arr + i, state, BITS); fmpz_randbits(fmpq_poly_denref(pol), state, BITS); _fmpq_poly_set_length(pol, length); _fmpq_poly_normalise(pol); fmpq_poly_canonicalise(pol); } void random_nf_elem(nf_elem_t a, flint_rand_t state, nf_t nf) { slong len = nf->pol->length - 1; random_fmpq_poly(NF_ELEM(a), state, len); } void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong length = info->length, i, j; int monic = info->monic; int scale; flint_rand_t state; fmpq_poly_t pol; nf_t nf; nf_elem_t a; fmpq_t norm; flint_randinit(state); scale = 1000; if (length >= 50) scale = 100; if (length >= 500) scale = 40; fmpq_poly_init(pol); fmpq_init(norm); for (i = 0; i < count; i++) { random_fmpq_poly(pol, state, length); if (monic) { fmpz_one(fmpq_poly_denref(pol)); fmpq_poly_set_coeff_ui(pol, length - 1, 1); } nf_init(nf, pol); nf_elem_init(a, nf); random_nf_elem(a, state, nf); if (monic) fmpz_one(fmpq_poly_denref(NF_ELEM(a))); prof_start(); for (j = 0; j < scale; j++) { nf_elem_trace(norm, a, nf); } prof_stop(); } fmpq_clear(norm); nf_elem_clear(a, nf); nf_clear(nf); fmpq_poly_clear(pol); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; printf("Number field element trace\n"); flint_printf("bits = %ld\n", BITS); for (k = 4; k <= 1000; k = (slong) ceil(1.1*k)) { info.length = k; info.monic = 0; scale = 1000; if (k >= 50) scale = 100; if (k >= 500) scale = 40; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("generic: length %wd, min %.3e us, max %.3e us\n", info.length, (min/scale), (max/scale) ); info.monic = 1; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("monic : length %wd, min %.3e us, max %.3e us\n", info.length, (min/scale), (max/scale) ); } return 0; } flint-3.1.3/src/nf_elem/randtest.c000066400000000000000000000050461461254215100170240ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson Copyright (C) 2013, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void nf_elem_randtest(nf_elem_t a, flint_rand_t state, mp_bitcnt_t bits, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_randtest(LNF_ELEM_NUMREF(a), state, bits); if (n_randint(state, 2)) { fmpz_randtest_not_zero(LNF_ELEM_DENREF(a), state, bits); fmpz_abs(LNF_ELEM_DENREF(a), LNF_ELEM_DENREF(a)); _fmpq_canonicalise(LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a)); } else fmpz_one(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz_randtest(QNF_ELEM_NUMREF(a), state, bits); fmpz_randtest(QNF_ELEM_NUMREF(a) + 1, state, bits); if (n_randint(state, 2)) { fmpz_t d; fmpz_randtest_not_zero(QNF_ELEM_DENREF(a), state, bits); fmpz_abs(QNF_ELEM_DENREF(a), QNF_ELEM_DENREF(a)); fmpz_init(d); fmpz_gcd(d, QNF_ELEM_NUMREF(a), QNF_ELEM_NUMREF(a) + 1); if (!fmpz_is_one(d)) { fmpz_gcd(d, d, QNF_ELEM_DENREF(a)); if (!fmpz_is_one(d)) { _fmpz_vec_scalar_divexact_fmpz(QNF_ELEM_NUMREF(a), QNF_ELEM_NUMREF(a), 2, d); fmpz_divexact(QNF_ELEM_DENREF(a), QNF_ELEM_DENREF(a), d); } } fmpz_clear(d); } else fmpz_one(QNF_ELEM_DENREF(a)); } else { fmpq_poly_randtest(NF_ELEM(a), state, nf->pol->length - 1, bits); } } void nf_elem_randtest_not_zero(nf_elem_t a, flint_rand_t state, mp_bitcnt_t bits, const nf_t nf) { if (nf->flag & NF_LINEAR) { do { nf_elem_randtest(a, state, bits, nf); } while (fmpz_is_zero(QNF_ELEM_NUMREF(a))); } else if (nf->flag & NF_QUADRATIC) { do { nf_elem_randtest(a, state, bits, nf); } while (fmpz_is_zero(QNF_ELEM_NUMREF(a)) && fmpz_is_zero(QNF_ELEM_NUMREF(a) + 1)); } else { do { nf_elem_randtest(a, state, bits, nf); } while (fmpq_poly_is_zero(NF_ELEM(a))); } } flint-3.1.3/src/nf_elem/reduce.c000066400000000000000000000065711461254215100164530ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void _nf_elem_reduce(nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { /* nothing to be done */ } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz * const aden = QNF_ELEM_DENREF(a); if (!fmpz_is_zero(anum + 2)) { fmpz * pnum = fmpq_poly_numref(nf->pol); if (nf->flag & NF_MONIC) { fmpz_submul(anum + 1, anum + 2, pnum + 1); fmpz_submul(anum, anum + 2, pnum); } else { fmpz * prod = _fmpz_vec_init(3); _fmpq_poly_scalar_mul_fmpq(prod, prod + 2, pnum, pnum + 2, 2, anum + 2, aden); _fmpq_poly_sub_can(anum, aden, anum, aden, 2, prod, prod + 2, 2, 0); _fmpz_vec_clear(prod, 3); } fmpz_zero(anum + 2); } } else /* generic nf_elem */ { const slong len = nf->pol->length; slong plen = NF_ELEM(a)->length; if (plen >= len) { if (nf->flag & NF_MONIC) { if (len <= NF_POWERS_CUTOFF) { _fmpz_poly_rem_powers_precomp(NF_ELEM_NUMREF(a), plen, fmpq_poly_numref(nf->pol), len, nf->powers.zz->powers); _fmpq_poly_set_length(NF_ELEM(a), len - 1); _fmpq_poly_normalise(NF_ELEM(a)); } else { fmpz * q = _fmpz_vec_init(plen - len + 1); fmpz * r = _fmpz_vec_init(plen); slong i; _fmpz_vec_set(r, NF_ELEM_NUMREF(a), plen); _fmpz_poly_divrem(q, NF_ELEM_NUMREF(a), r, plen, fmpq_poly_numref(nf->pol), len, 0); _fmpz_vec_clear(r, plen); _fmpz_vec_clear(q, plen - len + 1); for (i = len - 2; i >= 0 && fmpz_is_zero(NF_ELEM_NUMREF(a) + i); i--); NF_ELEM(a)->length = i + 1; } } else { fmpq_poly_t t; if (len <= NF_POWERS_CUTOFF) { _fmpq_poly_rem_powers_precomp(NF_ELEM_NUMREF(a), fmpq_poly_denref(NF_ELEM(a)), plen, fmpq_poly_numref(nf->pol), fmpq_poly_denref(nf->pol), len, nf->powers.qq->powers); _fmpq_poly_set_length(NF_ELEM(a), len - 1); _fmpq_poly_normalise(NF_ELEM(a)); } else { fmpq_poly_init2(t, 2*len - 3); _fmpq_poly_rem(t->coeffs, t->den, NF_ELEM(a)->coeffs, NF_ELEM(a)->den, plen, nf->pol->coeffs, nf->pol->den, len, nf->pinv.qq); _fmpq_poly_set_length(t, len - 1); _fmpq_poly_normalise(t); fmpq_poly_swap(t, NF_ELEM(a)); fmpq_poly_clear(t); } } } } } void nf_elem_reduce(nf_elem_t a, const nf_t nf) { if (!(nf->flag & NF_LINEAR)) _nf_elem_reduce(a, nf); nf_elem_canonicalise(a, nf); } flint-3.1.3/src/nf_elem/rep_mat.c000066400000000000000000000067061461254215100166330ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" #include "nf_elem.h" void nf_elem_rep_mat(fmpq_mat_t res, const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(fmpq_mat_entry_num(res, 0, 0), LNF_ELEM_NUMREF(a)); fmpz_set(fmpq_mat_entry_den(res, 0, 0), LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { nf_elem_t t; const fmpz * const anum = QNF_ELEM_NUMREF(a); const fmpz * const aden = QNF_ELEM_DENREF(a); fmpz * const tnum = QNF_ELEM_NUMREF(t); fmpz * const tden = QNF_ELEM_DENREF(t); nf_elem_init(t, nf); fmpz_set(fmpq_mat_entry_num(res, 0, 0), anum); fmpz_set(fmpq_mat_entry_den(res, 0, 0), aden); fmpq_canonicalise(fmpq_mat_entry(res, 0, 0)); fmpz_set(fmpq_mat_entry_num(res, 0, 1), anum + 1); fmpz_set(fmpq_mat_entry_den(res, 0, 1), aden); fmpq_canonicalise(fmpq_mat_entry(res, 0, 1)); nf_elem_mul_gen(t, a, nf); fmpz_set(fmpq_mat_entry_num(res, 1, 0), tnum); fmpz_set(fmpq_mat_entry_den(res, 1, 0), tden); fmpq_canonicalise(fmpq_mat_entry(res, 1, 0)); fmpz_set(fmpq_mat_entry_num(res, 1, 1), tnum + 1); fmpz_set(fmpq_mat_entry_den(res, 1, 1), tden); fmpq_canonicalise(fmpq_mat_entry(res, 1, 1)); nf_elem_clear(t, nf); } else { nf_elem_t t; slong i, j; slong d = fmpq_poly_degree(nf->pol); nf_elem_init(t, nf); nf_elem_set(t, a, nf); if (NF_ELEM(a)->length == 0) { fmpq_mat_zero(res); return; } for (i = 0; i <= NF_ELEM(a)->length - 1; i ++) { fmpz_set(fmpq_mat_entry_num(res, 0, i), fmpq_poly_numref(NF_ELEM(a)) + i); fmpz_set(fmpq_mat_entry_den(res, 0, i), fmpq_poly_denref(NF_ELEM(a))); fmpq_canonicalise(fmpq_mat_entry(res, 0, i)); } for (i = NF_ELEM(a)->length; i <= d - 1; i++) fmpq_zero(fmpq_mat_entry(res, 0, i)); for (j = 1; j <= d - NF_ELEM(a)->length; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i < j; i++) fmpq_zero(fmpq_mat_entry(res, j, i)); for (i = 0; i <= NF_ELEM(a)->length - 1; i++) { fmpz_set(fmpq_mat_entry_num(res, j, j + i), fmpq_poly_numref(NF_ELEM(a)) + i); fmpz_set(fmpq_mat_entry_den(res, j, j + i), fmpq_poly_denref(NF_ELEM(a))); fmpq_canonicalise(fmpq_mat_entry(res, j, j + i)); } for (i = j + NF_ELEM(a)->length; i <= d - 1; i++) fmpq_zero(fmpq_mat_entry(res, j, i)); } for (j = d - NF_ELEM(a)->length + 1; j <= d - 1; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i <= d - 1; i++) { fmpz_set(fmpq_mat_entry_num(res, j, i), fmpq_poly_numref(NF_ELEM(t)) + i); fmpz_set(fmpq_mat_entry_den(res, j, i), fmpq_poly_denref(NF_ELEM(t))); fmpq_canonicalise(fmpq_mat_entry(res, j, i)); } } nf_elem_clear(t, nf); } } flint-3.1.3/src/nf_elem/rep_mat_fmpz_mat_den.c000066400000000000000000000160431461254215100213510ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "nf_elem.h" void nf_elem_rep_mat_fmpz_mat_den(fmpz_mat_t res, fmpz_t den, const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(fmpz_mat_entry(res, 0, 0), LNF_ELEM_NUMREF(a)); fmpz_set(den, LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { nf_elem_t t; const fmpz * const anum = QNF_ELEM_NUMREF(a); const fmpz * const aden = QNF_ELEM_DENREF(a); fmpz * const tnum = QNF_ELEM_NUMREF(t); fmpz * const tden = QNF_ELEM_DENREF(t); nf_elem_init(t, nf); nf_elem_mul_gen(t, a, nf); if (fmpz_equal(tden, aden)) { fmpz_set(fmpz_mat_entry(res, 0, 0), anum); fmpz_set(fmpz_mat_entry(res, 0, 1), anum + 1); fmpz_set(fmpz_mat_entry(res, 1, 0), tnum); fmpz_set(fmpz_mat_entry(res, 1, 1), tnum + 1); fmpz_set(den, tden); } else { fmpz_lcm(den, tden, aden); fmpz_divexact(fmpz_mat_entry(res, 0, 0), den, aden); fmpz_mul(fmpz_mat_entry(res, 0, 1), anum + 1, fmpz_mat_entry(res, 0, 0)); fmpz_mul(fmpz_mat_entry(res, 0, 0), anum, fmpz_mat_entry(res, 0, 0)); fmpz_divexact(fmpz_mat_entry(res, 1, 0), den, tden); fmpz_mul(fmpz_mat_entry(res, 1, 1), tnum + 1, fmpz_mat_entry(res, 1, 0)); fmpz_mul(fmpz_mat_entry(res, 1, 0), tnum, fmpz_mat_entry(res, 1, 0)); } nf_elem_clear(t, nf); } else { slong i, j; nf_elem_t t; slong d = fmpq_poly_degree(nf->pol); nf_elem_init(t, nf); nf_elem_set(t, a, nf); if (NF_ELEM(a)->length == 0) { fmpz_mat_zero(res); fmpz_one(den); } else if (NF_ELEM(a)->length == 1) { fmpz_mat_zero(res); for (i = 0; i <= d - 1; i++) { fmpz_set(fmpz_mat_entry(res, i, i), fmpq_poly_numref(NF_ELEM(a))); } fmpz_set(den, fmpq_poly_denref(NF_ELEM(a))); } else { /* Special case if defining polynomial is monic and integral and the element also has trivial denominator */ if (nf->flag & NF_MONIC && fmpz_is_one(fmpq_poly_denref(nf->pol)) && fmpz_is_one(fmpq_poly_denref(NF_ELEM(a)))) { fmpz_one(den); for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, 0, i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, 0, i)); for (j = 1; j <= d - NF_ELEM(a)->length; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i < j; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, j, j + i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = j + NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); } for (j = d - NF_ELEM(a)->length + 1; j <= d - 1; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i <= d - 1; i++) fmpz_set(fmpz_mat_entry(res, j, i), fmpq_poly_numref(NF_ELEM(t)) + i); } } else { /* Now the general case. For 0 <= j < d - 2 we store the * denominator for row j at res[d - 1, j]. At the end we * divide the lcm of all of them by the corresponding * denominator of the row to get the correct multiplier for * row. */ for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, 0, i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, 0, i)); fmpz_set(fmpz_mat_entry(res, d - 1, 0), fmpq_poly_denref(NF_ELEM(a))); for (j = 1; j <= d - NF_ELEM(a)->length; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i < j; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, j, j + i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = j + NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); fmpz_set(fmpz_mat_entry(res, d - 1, j), fmpq_poly_denref(NF_ELEM(a))); } for (j = d - NF_ELEM(a)->length + 1; j <= d - 2; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i <= d - 1; i++) fmpz_set(fmpz_mat_entry(res, j, i), fmpq_poly_numref(NF_ELEM(t)) + i); fmpz_set(fmpz_mat_entry(res, d - 1, j), fmpq_poly_denref(NF_ELEM(t))); } nf_elem_mul_gen(t, t, nf); /* Now compute the correct denominator */ fmpz_set(fmpz_mat_entry(res, d - 1, d - 1), fmpq_poly_denref(NF_ELEM(t))); fmpz_set(den, fmpq_poly_denref(NF_ELEM(t))); for (j = 0; j <= d - 2; j++) fmpz_lcm(den, den, fmpz_mat_entry(res, d - 1, j)); for (j = 0; j <= d - 2; j++) { if (!fmpz_equal(den, fmpz_mat_entry(res, d - 1, j))) { fmpz_divexact(fmpz_mat_entry(res, d - 1, j), den, fmpz_mat_entry(res, d - 1, j)); for (i = 0; i <= d - 1; i++) fmpz_mul(fmpz_mat_entry(res, j, i), fmpz_mat_entry(res, j, i), fmpz_mat_entry(res, d - 1, j)); } } if (fmpz_equal(den, fmpz_mat_entry(res, d - 1, d - 1))) { for (i = 0; i < d; i++) fmpz_set(fmpz_mat_entry(res, d - 1, i), fmpq_poly_numref(NF_ELEM(t)) + i); } else { fmpz_divexact(fmpz_mat_entry(res, d - 1, d - 1), den, fmpq_poly_denref(NF_ELEM(t))); for (i = 0; i < d; i++) fmpz_mul(fmpz_mat_entry(res, d - 1, i), fmpq_poly_numref(NF_ELEM(t)) + i, fmpz_mat_entry(res, d - 1, d - 1)); } } } nf_elem_clear(t, nf); } } flint-3.1.3/src/nf_elem/scalar_div.c000066400000000000000000000057721461254215100173150ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void nf_elem_scalar_div_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_div(num, den, num2, den2, fmpq_numref(c), fmpq_denref(c)); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); _fmpq_poly_scalar_div_fmpq(num, den, num2, den2, 2, fmpq_numref(c), fmpq_denref(c)); } else { fmpq_poly_scalar_div_fmpq(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_scalar_div_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); fmpz_mul(den, den2, c); fmpz_set(num, num2); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); fmpz_mul(den, den2, c); _fmpz_vec_set(num, num2, 2); _fmpq_poly_canonicalise(num, den, 2); } else { fmpq_poly_scalar_div_fmpz(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_scalar_div_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); fmpz_mul_si(den, den2, c); fmpz_set(num, num2); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); fmpz_mul_si(den, den2, c); _fmpz_vec_set(num, num2, 2); _fmpq_poly_canonicalise(num, den, 2); } else { fmpq_poly_scalar_div_si(NF_ELEM(a), NF_ELEM(b), c); } } flint-3.1.3/src/nf_elem/scalar_mul.c000066400000000000000000000060151461254215100173170ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "nf_elem.h" void nf_elem_scalar_mul_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_mul(num, den, num2, den2, fmpq_numref(c), fmpq_denref(c)); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); _fmpq_poly_scalar_mul_fmpq(num, den, num2, den2, 2, fmpq_numref(c), fmpq_denref(c)); } else { fmpq_poly_scalar_mul_fmpq(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_scalar_mul_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); fmpz_mul(num, num2, c); fmpz_set(den, den2); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); _fmpz_vec_scalar_mul_fmpz(num, num2, 2, c); fmpz_set(den, den2); _fmpq_poly_canonicalise(num, den, 2); } else { fmpq_poly_scalar_mul_fmpz(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_scalar_mul_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); fmpz_mul_si(num, num2, c); fmpz_set(den, den2); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); _fmpz_vec_scalar_mul_si(num, num2, 2, c); fmpz_set(den, den2); _fmpq_poly_canonicalise(num, den, 2); } else { fmpq_poly_scalar_mul_si(NF_ELEM(a), NF_ELEM(b), c); } } flint-3.1.3/src/nf_elem/set.c000066400000000000000000000052771461254215100160010ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_set(nf_elem_t a, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(LNF_ELEM_NUMREF(a), LNF_ELEM_NUMREF(b)); fmpz_set(LNF_ELEM_DENREF(a), LNF_ELEM_DENREF(b)); } else if (nf->flag & NF_QUADRATIC) { fmpz *const anum = QNF_ELEM_NUMREF(a); const fmpz *const bnum = QNF_ELEM_NUMREF(b); fmpz_set(anum, bnum); fmpz_set(anum + 1, bnum + 1); fmpz_set(QNF_ELEM_DENREF(a), QNF_ELEM_DENREF(b)); } else fmpq_poly_set(NF_ELEM(a), NF_ELEM(b)); } void nf_elem_set_si(nf_elem_t a, slong c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set_si(LNF_ELEM_NUMREF(a), c); fmpz_one(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz *const anum = QNF_ELEM_NUMREF(a); fmpz_set_si(anum, c); fmpz_zero(anum + 1); fmpz_one(QNF_ELEM_DENREF(a)); } else fmpq_poly_set_si(NF_ELEM(a), c); } void nf_elem_set_ui(nf_elem_t a, ulong c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set_ui(LNF_ELEM_NUMREF(a), c); fmpz_one(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz *const anum = QNF_ELEM_NUMREF(a); fmpz_set_ui(anum, c); fmpz_zero(anum + 1); fmpz_one(QNF_ELEM_DENREF(a)); } else fmpq_poly_set_ui(NF_ELEM(a), c); } void nf_elem_set_fmpz(nf_elem_t a, const fmpz_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(LNF_ELEM_NUMREF(a), c); fmpz_one(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz *const anum = QNF_ELEM_NUMREF(a); fmpz_set(anum, c); fmpz_zero(anum + 1); fmpz_one(QNF_ELEM_DENREF(a)); } else fmpq_poly_set_fmpz(NF_ELEM(a), c); } void nf_elem_set_fmpq(nf_elem_t a, const fmpq_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(LNF_ELEM_NUMREF(a), fmpq_numref(c)); fmpz_set(LNF_ELEM_DENREF(a), fmpq_denref(c)); } else if (nf->flag & NF_QUADRATIC) { fmpz *const anum = QNF_ELEM_NUMREF(a); fmpz_set(anum, fmpq_numref(c)); fmpz_zero(anum + 1); fmpz_set(QNF_ELEM_DENREF(a), fmpq_denref(c)); } else fmpq_poly_set_fmpq(NF_ELEM(a), c); } flint-3.1.3/src/nf_elem/set_coeff_num_fmpz.c000066400000000000000000000031601461254215100210430ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void _nf_elem_set_coeff_num_fmpz(nf_elem_t a, slong i, const fmpz_t b, const nf_t nf) { if (i > 2*(fmpq_poly_degree(nf->pol) - 1)) { flint_throw(FLINT_ERROR, "(%s): Degree out of range\n", __func__); } if (nf->flag & NF_LINEAR) { fmpz_set(LNF_ELEM_NUMREF(a), b); nf_elem_canonicalise(a, nf); } else if (nf->flag & NF_QUADRATIC) { fmpz_set(QNF_ELEM_NUMREF(a) + i, b); nf_elem_canonicalise(a, nf); } else { slong len = NF_ELEM(a)->length; const int replace = (i < len && !fmpz_is_zero(NF_ELEM(a)->coeffs + i)); if (!replace && fmpz_is_zero(b)) return; if (i + 1 > len) { fmpq_poly_fit_length(NF_ELEM(a), i + 1); _fmpq_poly_set_length(NF_ELEM(a), i + 1); flint_mpn_zero((mp_ptr) NF_ELEM(a)->coeffs + len, (i + 1) - len); } if (*NF_ELEM(a)->den == WORD(1)) { fmpz_set(NF_ELEM(a)->coeffs + i, b); if (replace) _fmpq_poly_normalise(NF_ELEM(a)); } else { fmpz_set(NF_ELEM(a)->coeffs + i, b); if (replace) fmpq_poly_canonicalise(NF_ELEM(a)); } } } flint-3.1.3/src/nf_elem/set_fmpq_poly.c000066400000000000000000000031141461254215100200530ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_set_fmpq_poly(nf_elem_t a, const fmpq_poly_t pol, const nf_t nf) { if (fmpq_poly_length(pol) >= fmpq_poly_length(nf->pol)) { fmpq_poly_t r; fmpq_poly_init(r); fmpq_poly_rem(r, pol, nf->pol); nf_elem_set_fmpq_poly(a, r, nf); fmpq_poly_clear(r); return; } if (nf->flag & NF_LINEAR) { if (pol->length == 0) { fmpz_zero(LNF_ELEM_NUMREF(a)); fmpz_one(LNF_ELEM_DENREF(a)); } else if (pol->length == 1) { fmpz_set(LNF_ELEM_NUMREF(a), fmpq_poly_numref(pol)); fmpz_set(LNF_ELEM_DENREF(a), fmpq_poly_denref(pol)); } } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); if (pol->length == 0) { fmpz_zero(anum); fmpz_zero(anum + 1); fmpz_one(QNF_ELEM_DENREF(a)); } else if (pol->length == 1) { fmpz_zero(anum + 1); fmpz_set(anum, fmpq_poly_numref(pol)); fmpz_set(QNF_ELEM_DENREF(a), fmpq_poly_denref(pol)); } else { fmpz_set(anum, fmpq_poly_numref(pol)); fmpz_set(anum + 1, fmpq_poly_numref(pol) + 1); fmpz_set(QNF_ELEM_DENREF(a), fmpq_poly_denref(pol)); } } else fmpq_poly_set(NF_ELEM(a), pol); } flint-3.1.3/src/nf_elem/set_fmpz_mat_row.c000066400000000000000000000036221461254215100205550ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart Copyright (C) 2015 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "nf_elem.h" #include "fmpq_poly.h" void nf_elem_set_fmpz_mat_row(nf_elem_t b, const fmpz_mat_t M, const slong i, fmpz_t den, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(LNF_ELEM_NUMREF(b), fmpz_mat_entry(M, i, 0)); fmpz_set(LNF_ELEM_DENREF(b), den); _fmpq_canonicalise(LNF_ELEM_NUMREF(b), LNF_ELEM_DENREF(b)); } else if (nf->flag & NF_QUADRATIC) { fmpz_t d; fmpz * const bnum = QNF_ELEM_NUMREF(b); fmpz_init(d); fmpz_set(bnum, fmpz_mat_entry(M, i, 0)); fmpz_set(bnum + 1, fmpz_mat_entry(M, i, 1)); fmpz_set(QNF_ELEM_DENREF(b), den); fmpz_gcd(d, bnum, bnum + 1); if (!fmpz_is_one(d)) { fmpz_gcd(d, d, QNF_ELEM_DENREF(b)); if (!fmpz_is_one(d)) { fmpz_divexact(bnum, bnum, d); fmpz_divexact(bnum + 1, bnum + 1, d); fmpz_divexact(QNF_ELEM_DENREF(b), QNF_ELEM_DENREF(b), d); } } fmpz_clear(d); } else { slong j; for (j = nf->pol->length - 2; j >= 0; j--) if (!fmpz_is_zero(fmpz_mat_entry(M, i, j))) break; _fmpq_poly_set_length(NF_ELEM(b), j + 1); for (; j >= 0; j--) fmpq_poly_set_coeff_fmpz(NF_ELEM(b), j, fmpz_mat_entry(M, i, j)); fmpz_set(NF_ELEM_DENREF(b), den); fmpq_poly_canonicalise(NF_ELEM(b)); } } flint-3.1.3/src/nf_elem/sub.c000066400000000000000000000316101461254215100157650ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void _nf_elem_sub_lf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can) { const fmpz *const p = LNF_ELEM_NUMREF(b); const fmpz *const q = LNF_ELEM_DENREF(b); const fmpz *const r = LNF_ELEM_NUMREF(c); const fmpz *const s = LNF_ELEM_DENREF(c); fmpz *const rnum = LNF_ELEM_NUMREF(a); fmpz *const rden = LNF_ELEM_DENREF(a); fmpz_t t; if (can) _fmpq_sub(rnum, rden, p, q, r, s); else { /* Same denominator */ if (fmpz_equal(q, s)) { fmpz_sub(rnum, p, r); fmpz_set(rden, q); return; } /* p/q is an integer */ if (fmpz_is_one(q)) { fmpz_init(t); fmpz_mul(t, p, s); fmpz_sub(rnum, t, r); fmpz_set(rden, s); fmpz_clear(t); return; } /* r/s is an integer */ if (fmpz_is_one(s)) { fmpz_init(t); fmpz_mul(t, r, q); fmpz_sub(rnum, t, p); fmpz_set(rden, q); fmpz_clear(t); return; } /* We want to compute p/q - r/s which is (p*s - q*r, q*s). */ fmpz_init(t); fmpz_mul(t, q, r); fmpz_mul(rnum, p, s); fmpz_sub(rnum, rnum, t); fmpz_mul(rden, q, s); fmpz_clear(t); } } void _nf_elem_sub_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can) { fmpz_t d; const fmpz *const bnum = QNF_ELEM_NUMREF(b); const fmpz *const bden = QNF_ELEM_DENREF(b); const fmpz *const cnum = QNF_ELEM_NUMREF(c); const fmpz *const cden = QNF_ELEM_DENREF(c); fmpz *const anum = QNF_ELEM_NUMREF(a); fmpz *const aden = QNF_ELEM_DENREF(a); fmpz_init(d); fmpz_one(d); if (fmpz_equal(bden, cden)) { fmpz_sub(anum, bnum, cnum); fmpz_sub(anum + 1, bnum + 1, cnum + 1); fmpz_sub(anum + 2, bnum + 2, cnum + 2); fmpz_set(aden, bden); if (can && !fmpz_is_one(aden)) { fmpz_gcd3(d, anum + 0, anum + 1, anum + 2); if (!fmpz_is_one(d)) { fmpz_gcd(d, d, aden); if (!fmpz_is_one(d)) { fmpz_divexact(anum, anum, d); fmpz_divexact(anum + 1, anum + 1, d); fmpz_divexact(anum + 2, anum + 2, d); fmpz_divexact(aden, aden, d); } } } fmpz_clear(d); return; } if (!fmpz_is_one(bden) && !fmpz_is_one(cden)) fmpz_gcd(d, bden, cden); if (fmpz_is_one(d)) { fmpz_mul(anum, bnum, cden); fmpz_mul(anum + 1, bnum + 1, cden); fmpz_mul(anum + 2, bnum + 2, cden); fmpz_submul(anum, cnum, bden); fmpz_submul(anum + 1, cnum + 1, bden); fmpz_submul(anum + 2, cnum + 2, bden); fmpz_mul(aden, bden, cden); } else { fmpz_t bden1; fmpz_t cden1; fmpz_init(bden1); fmpz_init(cden1); fmpz_divexact(bden1, bden, d); fmpz_divexact(cden1, cden, d); fmpz_mul(anum, bnum, cden1); fmpz_mul(anum + 1, bnum + 1, cden1); fmpz_mul(anum + 2, bnum + 2, cden1); fmpz_submul(anum, cnum, bden1); fmpz_submul(anum + 1, cnum + 1, bden1); fmpz_submul(anum + 2, cnum + 2, bden1); if (fmpz_is_zero(anum) && fmpz_is_zero(anum + 1) && fmpz_is_zero(anum + 2)) fmpz_one(aden); else { if (can) { fmpz_t e; fmpz_init(e); fmpz_gcd3(e, anum + 0, anum + 1, anum + 2); if (!fmpz_is_one(e)) fmpz_gcd(e, e, d); if (fmpz_is_one(e)) fmpz_mul(aden, bden, cden1); else { fmpz_divexact(anum, anum, e); fmpz_divexact(anum + 1, anum + 1, e); fmpz_divexact(anum + 2, anum + 2, e); fmpz_divexact(bden1, bden, e); fmpz_mul(aden, bden1, cden1); } fmpz_clear(e); } else fmpz_mul(aden, bden, cden1); } fmpz_clear(bden1); fmpz_clear(cden1); } fmpz_clear(d); } void nf_elem_sub_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { if (a == c) { nf_elem_t t; nf_elem_init(t, nf); _nf_elem_sub_qf(t, b, c, nf, 1); nf_elem_swap(t, a, nf); nf_elem_clear(t, nf); } else _nf_elem_sub_qf(a, b, c, nf, 1); } void _nf_elem_sub(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) _nf_elem_sub_lf(a, b, c, nf, 0); else if (nf->flag & NF_QUADRATIC) _nf_elem_sub_qf(a, b, c, nf, 0); else fmpq_poly_sub_can(NF_ELEM(a), NF_ELEM(b), NF_ELEM(c), 0); } void nf_elem_sub(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) _nf_elem_sub_lf(a, b, c, nf, 1); else if (nf->flag & NF_QUADRATIC) nf_elem_sub_qf(a, b, c, nf); else fmpq_poly_sub_can(NF_ELEM(a), NF_ELEM(b), NF_ELEM(c), 1); } void nf_elem_fmpq_sub(nf_elem_t a, const fmpq_t c, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_sub(num, den, fmpq_numref(c), fmpq_denref(c), num2, den2); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); slong len = 2; while (len != 0 && fmpz_is_zero(num2 + len - 1)) len--; if (len == 0) { fmpz_set(num, fmpq_numref(c)); fmpz_set(den, fmpq_denref(c)); } else if (len == 1) _fmpq_sub(num, den, fmpq_numref(c), fmpq_denref(c), num2, den2); else { /* fast path */ if (fmpz_equal(fmpq_denref(c), den2)) { fmpz_sub(num, fmpq_numref(c), num2); fmpz_neg(num + 1, num2 + 1); fmpz_set(den, den2); } else /* slow path */ { fmpz_t d1, d2, g; fmpz_init(d1); fmpz_init(d2); fmpz_init(g); nf_elem_set(a, b, nf); fmpz_gcd(g, fmpq_denref(c), den); fmpz_divexact(d1, fmpq_denref(c), g); fmpz_divexact(d2, den, g); fmpz_mul(num + 1, num + 1, d1); fmpz_mul(num, num, d1); fmpz_mul(den, den, d1); fmpz_submul(num, d2, fmpq_numref(c)); fmpz_neg(num, num); fmpz_neg(num + 1, num + 1); fmpz_clear(g); fmpz_clear(d1); fmpz_clear(d2); } _fmpq_poly_canonicalise(num, den, 2); } } else { fmpq_poly_fmpq_sub(NF_ELEM(a), c, NF_ELEM(b)); } } void nf_elem_sub_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_sub(num, den, num2, den2, fmpq_numref(c), fmpq_denref(c)); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); const fmpz *const den2 = QNF_ELEM_DENREF(b); const fmpz *const num2 = QNF_ELEM_NUMREF(b); slong len = 2; nf_elem_set(a, b, nf); while (len != 0 && fmpz_is_zero(num2 + len - 1)) len--; if (len == 0) { fmpz_neg(num, fmpq_numref(c)); fmpz_set(den, fmpq_denref(c)); } else if (len == 1) _fmpq_sub(num, den, num2, den2, fmpq_numref(c), fmpq_denref(c)); else { /* fast path */ if (fmpz_equal(fmpq_denref(c), den2)) { fmpz_sub(num, num2, fmpq_numref(c)); fmpz_set(den, den2); } else /* slow path */ { fmpz_t d1, d2, g; fmpz_init(d1); fmpz_init(d2); fmpz_init(g); fmpz_gcd(g, fmpq_denref(c), den); fmpz_divexact(d1, fmpq_denref(c), g); fmpz_divexact(d2, den, g); fmpz_mul(num + 1, num + 1, d1); fmpz_mul(num, num, d1); fmpz_mul(den, den, d1); fmpz_submul(num, d2, fmpq_numref(c)); fmpz_clear(g); fmpz_clear(d1); fmpz_clear(d2); } _fmpq_poly_canonicalise(num, den, 2); } } else { fmpq_poly_sub_fmpq(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_fmpz_sub(nf_elem_t a, const fmpz_t c, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_sub_fmpz(num, den, num2, den2, c); fmpz_neg(num, num); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); nf_elem_neg(a, b, nf); fmpz_addmul(num, den, c); _fmpq_poly_canonicalise(num, den, 2); } else { fmpq_poly_fmpz_sub(NF_ELEM(a), c, NF_ELEM(b)); } } void nf_elem_sub_fmpz(nf_elem_t a, const nf_elem_t b, const fmpz_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); const fmpz *const den2 = LNF_ELEM_DENREF(b); const fmpz *const num2 = LNF_ELEM_NUMREF(b); _fmpq_sub_fmpz(num, den, num2, den2, c); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); slong len = 2; nf_elem_set(a, b, nf); while (len != 0 && fmpz_is_zero(num + len - 1)) len--; fmpz_submul(num, den, c); _fmpq_poly_canonicalise(num, den, len); } else { fmpq_poly_sub_fmpz(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_sub_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); nf_elem_set(a, b, nf); if (c >= 0) fmpz_submul_ui(num, den, c); else fmpz_addmul_ui(num, den, -c); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); slong len = 2; nf_elem_set(a, b, nf); while (len != 0 && fmpz_is_zero(num + len - 1)) len--; if (c >= 0) fmpz_submul_ui(num, den, c); else fmpz_addmul_ui(num, den, -c); _fmpq_poly_canonicalise(num, den, len); } else { fmpq_poly_sub_si(NF_ELEM(a), NF_ELEM(b), c); } } void nf_elem_si_sub(nf_elem_t a, slong c, const nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz *den = LNF_ELEM_DENREF(a); fmpz *num = LNF_ELEM_NUMREF(a); nf_elem_neg(a, b, nf); if (c >= 0) fmpz_addmul_ui(num, den, c); else fmpz_submul_ui(num, den, -c); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz *den = QNF_ELEM_DENREF(a); fmpz *num = QNF_ELEM_NUMREF(a); nf_elem_neg(a, b, nf); if (c >= 0) fmpz_addmul_ui(num, den, c); else fmpz_submul_ui(num, den, -c); _fmpq_poly_canonicalise(num, den, 2); } else { fmpq_poly_si_sub(NF_ELEM(a), c, NF_ELEM(b)); } } flint-3.1.3/src/nf_elem/swap.c000066400000000000000000000017411461254215100161500ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_swap(nf_elem_t a, nf_elem_t b, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_swap(LNF_ELEM_NUMREF(a), LNF_ELEM_NUMREF(b)); fmpz_swap(LNF_ELEM_DENREF(a), LNF_ELEM_DENREF(b)); } else if (nf->flag & NF_QUADRATIC) { fmpz *const anum = QNF_ELEM_NUMREF(a); fmpz *const bnum = QNF_ELEM_NUMREF(b); fmpz_swap(anum, bnum); fmpz_swap(anum + 1, bnum + 1); fmpz_swap(anum + 2, bnum + 2); fmpz_swap(QNF_ELEM_DENREF(a), QNF_ELEM_DENREF(b)); } else fmpq_poly_swap(NF_ELEM(a), NF_ELEM(b)); } flint-3.1.3/src/nf_elem/test/000077500000000000000000000000001461254215100160065ustar00rootroot00000000000000flint-3.1.3/src/nf_elem/test/main.c000066400000000000000000000043711461254215100171030ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-div.c" #include "t-equal_fmpz_fmpq.c" #include "t-get_fmpz_mod_poly.c" #include "t-get_nmod_poly.c" #include "t-get_set_den.c" #include "t-get_set_fmpq_poly.c" #include "t-get_set_fmpz_mat_row.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-is_rational_integer.c" #include "t-mod_fmpz.c" #include "t-mul.c" #include "t-mul_div_fmpq.c" #include "t-mul_gen.c" #include "t-norm.c" #include "t-norm_div.c" #include "t-pow.c" #include "t-rep_mat.c" #include "t-rep_mat_fmpz_mat_den.c" #include "t-set_coeff_num_fmpz.c" #include "t-set_equal.c" #include "t-set_equal_si_ui.c" #include "t-trace.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nf_elem_add_sub), TEST_FUNCTION(nf_elem_div), TEST_FUNCTION(nf_elem_equal_fmpz_fmpq), TEST_FUNCTION(nf_elem_get_fmpz_mod_poly), TEST_FUNCTION(nf_elem_get_nmod_poly), TEST_FUNCTION(nf_elem_get_set_den), TEST_FUNCTION(nf_elem_get_set_fmpq_poly), TEST_FUNCTION(nf_elem_get_set_fmpz_mat_row), TEST_FUNCTION(nf_elem_init_clear), TEST_FUNCTION(nf_elem_inv), TEST_FUNCTION(nf_elem_is_rational_integer), TEST_FUNCTION(nf_elem_mod_fmpz), TEST_FUNCTION(nf_elem_mul), TEST_FUNCTION(nf_elem_mul_div_fmpq), TEST_FUNCTION(nf_elem_mul_gen), TEST_FUNCTION(nf_elem_norm), TEST_FUNCTION(nf_elem_norm_div), TEST_FUNCTION(nf_elem_pow), TEST_FUNCTION(nf_elem_rep_mat), TEST_FUNCTION(nf_elem_rep_mat_fmpz_mat_den), TEST_FUNCTION(nf_elem_set_coeff_num_fmpz), TEST_FUNCTION(nf_elem_set_equal), TEST_FUNCTION(nf_elem_set_equal_si_ui), TEST_FUNCTION(nf_elem_trace) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nf_elem/test/t-add_sub.c000066400000000000000000000107401461254215100200160ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_add_sub, state) { int i, result; /* test b + c - c = b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c, t; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_init(t, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); nf_elem_add(t, b, c, nf); nf_elem_sub(a, t, c, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_elem_clear(t, nf); nf_clear(nf); } /* test b + c - c = b : exercise common denominator path */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c, t; nf_init_randtest(nf, state, 3, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_init(t, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); if (nf->flag & NF_QUADRATIC && n_randint(state, 2)) fmpz_set(QNF_ELEM(c)->den, QNF_ELEM(b)->den); nf_elem_add(t, b, c, nf); nf_elem_sub(a, t, c, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_elem_clear(t, nf); nf_clear(nf); } /* test aliasing a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); nf_elem_set(a, b, nf); nf_elem_add(b, b, c, nf); nf_elem_sub(b, b, c, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } /* test aliasing a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); nf_elem_set(a, c, nf); nf_elem_add(c, b, c, nf); nf_elem_sub(a, c, a, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-div.c000066400000000000000000000072171461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_div, state) { int i, result; /* test a*^-1 = 1 */ for (i = 0; i < 10*flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; nf_init_randtest(nf, state, 25, 100); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); do { nf_elem_randtest_not_zero(a, state, 100, nf); } while (!_nf_elem_invertible_check(a, nf)); nf_elem_randtest(b, state, 100, nf); nf_elem_div(c, b, a, nf); nf_elem_mul(c, c, a, nf); result = (nf_elem_equal(b, c, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } /* test aliasing a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; nf_init_randtest(nf, state, 25, 100); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(b, state, 100, nf); do { nf_elem_randtest_not_zero(c, state, 100, nf); } while (!_nf_elem_invertible_check(c, nf)); nf_elem_div(a, b, c, nf); nf_elem_div(b, b, c, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } /* test aliasing a and c */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t pol; nf_t nf; nf_elem_t a, b, c; fmpq_poly_init(pol); do { fmpq_poly_randtest_not_zero(pol, state, 25, 100); } while (fmpq_poly_degree(pol) < 1); nf_init(nf, pol); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(b, state, 100, nf); do { nf_elem_randtest_not_zero(c, state, 100, nf); } while (!_nf_elem_invertible_check(c, nf)); nf_elem_div(a, b, c, nf); nf_elem_div(c, b, c, nf); result = (nf_elem_equal(a, c, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("d = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); fmpq_poly_clear(pol); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-equal_fmpz_fmpq.c000066400000000000000000000062761461254215100216140ustar00rootroot00000000000000/* Copyright (C) 2018 Vincent Delecroix 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_equal_fmpz_fmpq, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t z; fmpq_t q; fmpq_poly_t f; nf_t nf; nf_elem_t a; fmpq_init(q); fmpz_init(z); nf_init_randtest(nf, state, 20, 200); nf_elem_init(a, nf); fmpq_poly_init(f); fmpq_poly_randtest(f, state, fmpq_poly_degree(nf->pol) - 1, 200); nf_elem_set_fmpq_poly(a, f, nf); fmpq_poly_get_coeff_fmpq(q, f, 0); if (nf_elem_equal_fmpq(a, q, nf) != (fmpq_poly_length(f) <= 1)) { flint_printf("nf_elem_equal_fmpq wrong\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); flint_printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_printf("q = "); fmpq_print(q); flint_printf("\n"); flint_abort(); } fmpz_set(z, fmpq_numref(q)); if (nf_elem_equal_fmpz(a, z, nf) != (fmpq_poly_length(f) <= 1 && fmpz_is_one(fmpq_denref(q)))) { flint_printf("nf_elem_equal_fmpz wrong\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); flint_printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_printf("z = "); fmpz_print(z); flint_printf("\n"); flint_abort(); } fmpq_add_si(q, q, 1); if (nf_elem_equal_fmpq(a, q, nf)) { flint_printf("nf_elem_equal_fmpq wrong\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); flint_printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_printf("q = "); fmpq_print(q); flint_printf("\n"); flint_abort(); } fmpz_add_ui(z, z, 1); if (nf_elem_equal_fmpz(a, z, nf)) { flint_printf("nf_elem_equal_fmpz wrong\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); flint_printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_printf("z = "); fmpz_print(z); flint_printf("\n"); flint_abort(); } fmpq_poly_clear(f); nf_elem_clear(a, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-get_fmpz_mod_poly.c000066400000000000000000000101661461254215100221340ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann 2020 Julian Rüth ******************************************************************************/ #include "test_helpers.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_get_fmpz_mod_poly, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong j; nf_t nf; nf_elem_t a; fmpz_mod_poly_t reduced_elem; fmpz_t coeff, mod, reduced_coeff; fmpz_mod_ctx_t ctx; fmpz_init(mod); fmpz_randtest_unsigned(mod, state, 2 * FLINT_BITS); fmpz_add_ui(mod, mod, 2); fmpz_init(coeff); fmpz_init(reduced_coeff); fmpz_mod_ctx_init(ctx, mod); fmpz_mod_poly_init(reduced_elem, ctx); nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_randtest(a, state, 200, nf); nf_elem_get_fmpz_mod_poly_den(reduced_elem, a, nf, 0, ctx); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, a, j, nf); fmpz_mod(coeff, coeff, mod); fmpz_mod_poly_get_coeff_fmpz(reduced_coeff, reduced_elem, j, ctx); result = fmpz_equal(reduced_coeff, coeff); if (!result) { printf("FAIL: Reducing without denominator\n"); printf("f = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("n = "); fmpz_print(mod); printf("\n"); printf("a mod n = "); fmpz_mod_poly_print_pretty(reduced_elem, "x", ctx); printf("\n"); flint_abort(); } } nf_elem_clear(a, nf); fmpz_mod_poly_clear(reduced_elem, ctx); fmpz_mod_ctx_clear(ctx); fmpz_clear(coeff); fmpz_clear(mod); nf_clear(nf); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong j; nf_t nf; nf_elem_t a; fmpz_mod_poly_t reduced_elem; fmpz_t coeff, reduced_coeff, den, mod, d_mod, d_modinv; fmpz_mod_ctx_t ctx; fmpz_init(coeff); fmpz_init(den); fmpz_init(mod); fmpz_init(d_mod); fmpz_init(d_modinv); fmpz_init(reduced_coeff); fmpz_init(mod); fmpz_randtest_unsigned(mod, state, 2 * FLINT_BITS); fmpz_add_ui(mod, mod, 2); fmpz_mod_ctx_init(ctx, mod); fmpz_mod_poly_init(reduced_elem, ctx); nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); do { nf_elem_randtest(a, state, 200, nf); nf_elem_get_den(den, a, nf); fmpz_mod(d_mod, den, mod); fmpz_gcd(d_mod, d_mod, mod); } while (!fmpz_is_one(d_mod)); nf_elem_get_fmpz_mod_poly(reduced_elem, a, nf, ctx); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, a, j, nf); nf_elem_get_den(den, a, nf); fmpz_invmod(d_modinv, den, mod); fmpz_mul(coeff, coeff, d_modinv); fmpz_mod(coeff, coeff, mod); fmpz_mod_poly_get_coeff_fmpz(reduced_coeff, reduced_elem, j, ctx); result = (fmpz_equal(coeff, reduced_coeff)); if (!result) { printf("FAIL: Reducing element with denominator\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("n = "); fmpz_print(mod); flint_printf("\n"); printf("a mod n = "); fmpz_mod_poly_print_pretty(reduced_elem, "x", ctx); printf("\n"); flint_abort(); } } fmpz_clear(den); fmpz_clear(mod); fmpz_clear(coeff); fmpz_clear(reduced_coeff); fmpz_clear(d_mod); fmpz_clear(d_modinv); nf_elem_clear(a, nf); fmpz_mod_poly_clear(reduced_elem, ctx); fmpz_mod_ctx_clear(ctx); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-get_nmod_poly.c000066400000000000000000000065261461254215100212630ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_poly.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_get_nmod_poly, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong j; nf_t nf; nf_elem_t a; nmod_poly_t reduced_elem; ulong mod; fmpz_t coeff; mod = n_randtest_not_zero(state); fmpz_init(coeff); nmod_poly_init(reduced_elem, mod); nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_randtest(a, state, 200, nf); nf_elem_get_nmod_poly_den(reduced_elem, a, nf, 0); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, a, j, nf); result = (nmod_poly_get_coeff_ui(reduced_elem, j) == fmpz_fdiv_ui(coeff, mod)); if (!result) { printf("FAIL: Reducing without denominator\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("n = "); flint_printf("%u\n", mod); printf("a mod n = "); nmod_poly_print_pretty(reduced_elem, "x"); printf("\n"); flint_abort(); } } nf_elem_clear(a, nf); nmod_poly_clear(reduced_elem); fmpz_clear(coeff); nf_clear(nf); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong j; nf_t nf; nf_elem_t a; nmod_poly_t reduced_elem; fmpz_t coeff, den; ulong mod, d_mod, d_modinv; do { mod = n_randtest_not_zero(state); } while (mod == 1); fmpz_init(coeff); fmpz_init(den); nmod_poly_init(reduced_elem, mod); nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); do { nf_elem_randtest(a, state, 200, nf); nf_elem_get_den(den, a, nf); d_mod = fmpz_fdiv_ui(den, mod); } while (n_gcd(d_mod, mod) != 1); nf_elem_get_nmod_poly(reduced_elem, a, nf); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, a, j, nf); d_modinv = n_invmod(d_mod, mod); result = (nmod_poly_get_coeff_ui(reduced_elem, j) == nmod_mul(fmpz_fdiv_ui(coeff, mod), d_modinv, reduced_elem->mod)); if (!result) { printf("FAIL: Reducing element with denominator\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("n = "); flint_printf("%u\n", mod); printf("a mod n = "); nmod_poly_print_pretty(reduced_elem, "x"); printf("\n"); flint_abort(); } } fmpz_clear(den); fmpz_clear(coeff); nf_elem_clear(a, nf); nmod_poly_clear(reduced_elem); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-get_set_den.c000066400000000000000000000026151461254215100206770ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_get_set_den, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a; fmpz_t d, d2; nf_init_randtest(nf, state, 40, 200); fmpz_init(d); fmpz_init(d2); nf_elem_init(a, nf); nf_elem_randtest(a, state, 200, nf); fmpz_randtest_not_zero(d, state, 200); nf_elem_set_den(a, d, nf); nf_elem_get_den(d2, a, nf); result = fmpz_equal(d, d2); if (!result) { flint_printf("FAIL:\n"); flint_printf("d = "); fmpz_print(d); printf("\n"); flint_printf("d2 = "); fmpz_print(d2); printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_abort(); } nf_elem_clear(a, nf); nf_clear(nf); fmpz_clear(d); fmpz_clear(d2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-get_set_fmpq_poly.c000066400000000000000000000051461461254215100221410ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_get_set_fmpq_poly, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t f; fmpq_poly_t g; nf_t nf; nf_elem_t a; fmpq_poly_init(f); fmpq_poly_init(g); nf_init_randtest(nf, state, 40, 200); fmpq_poly_randtest(f, state, fmpq_poly_degree(nf->pol) - 1, 200); nf_elem_init(a, nf); nf_elem_set_fmpq_poly(a, f, nf); nf_elem_get_fmpq_poly(g, a, nf); result = fmpq_poly_equal(f, g); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "a"); printf("\n"); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); printf("\n"); flint_printf("g = "); fmpq_poly_print_pretty(f, "x"); flint_abort(); } nf_elem_clear(a, nf); nf_clear(nf); fmpq_poly_clear(f); fmpq_poly_clear(g); } /* try unreduced polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t f, g, r; nf_t nf; nf_elem_t a; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(r); nf_init_randtest(nf, state, 20, 200); fmpq_poly_randtest(f, state, n_randint(state, 30), 200); nf_elem_init(a, nf); nf_elem_set_fmpq_poly(a, f, nf); nf_elem_get_fmpq_poly(g, a, nf); fmpq_poly_rem(r, f, nf->pol); result = fmpq_poly_equal(r, g); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "a"); printf("\n"); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); printf("\n"); flint_printf("g = "); fmpq_poly_print_pretty(f, "x"); printf("\n"); flint_printf("r = "); fmpq_poly_print_pretty(r, "x"); flint_abort(); } nf_elem_clear(a, nf); nf_clear(nf); fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-get_set_fmpz_mat_row.c000066400000000000000000000034041461254215100226320ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_get_set_fmpz_mat_row, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b; fmpz_mat_t mat; slong rows, j; fmpz_t d; nf_init_randtest(nf, state, 40, 200); rows = n_randint(state, 100) + 1; j = n_randint(state, rows); fmpz_mat_init(mat, rows, fmpq_poly_degree(nf->pol)); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_randtest(a, state, 200, nf); fmpz_init(d); nf_elem_get_fmpz_mat_row(mat, j, d, a, nf); nf_elem_set_fmpz_mat_row(b, mat, j, d, nf); result = nf_elem_equal(a, b, nf); if (!result) { flint_printf("FAIL:\n"); flint_printf("rows = %wd, cols = %wd, j = %wd\n", rows, fmpq_poly_degree(nf->pol), j); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); flint_printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); flint_printf("d = "); fmpz_print(d); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); fmpz_mat_clear(mat); fmpz_clear(d); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-init_clear.c000066400000000000000000000016771461254215100205370ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_init_clear, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); if (!nf_elem_is_zero(a, nf)) { flint_printf("FAIL\n"); flint_abort(); } nf_elem_randtest(a, state, 200, nf); nf_elem_clear(a, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-inv.c000066400000000000000000000044351461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_inv, state) { int i, result; /* test a*^-1 = 1 */ for (i = 0; i < 10*flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, ainv, p1; nf_init_randtest(nf, state, 25, 100); nf_elem_init(a, nf); nf_elem_init(ainv, nf); nf_elem_init(p1, nf); do { nf_elem_randtest_not_zero(a, state, 100, nf); } while (!_nf_elem_invertible_check(a, nf)); nf_elem_inv(ainv, a, nf); nf_elem_mul(p1, ainv, a, nf); result = (nf_elem_is_one(p1, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("ainv = "); nf_elem_print_pretty(ainv, nf, "x"); printf("\n"); printf("p1 = "); nf_elem_print_pretty(p1, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(ainv, nf); nf_elem_clear(p1, nf); nf_clear(nf); } /* test aliasing a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b; nf_init_randtest(nf, state, 25, 100); nf_elem_init(a, nf); nf_elem_init(b, nf); do { nf_elem_randtest_not_zero(b, state, 100, nf); } while (!_nf_elem_invertible_check(b, nf)); nf_elem_inv(a, b, nf); nf_elem_inv(b, b, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-is_rational_integer.c000066400000000000000000000032031461254215100224320ustar00rootroot00000000000000/* Copyright (C) 2018 Vincent Delecroix 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_is_rational_integer, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int is_int; int is_rat; fmpq_poly_t f; nf_t nf; nf_elem_t a; nf_init_randtest(nf, state, 20, 200); nf_elem_init(a, nf); fmpq_poly_init(f); fmpq_poly_randtest(f, state, fmpq_poly_degree(nf->pol) - 1, 200); nf_elem_set_fmpq_poly(a, f, nf); is_rat = fmpq_poly_length(f) <= 1; is_int = is_rat && fmpz_is_one(fmpq_poly_denref(f)); if (nf_elem_is_rational(a, nf) != is_rat || nf_elem_is_integer(a, nf) != is_int) { flint_printf("nf_elem_is_rational/nf_elem_is_integer wrong\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); flint_printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_abort(); } nf_elem_clear(a, nf); fmpq_poly_clear(f); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-mod_fmpz.c000066400000000000000000000142231461254215100202300ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann 2020 Julian Rüth ******************************************************************************/ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_mod_fmpz, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong j; nf_t nf; nf_elem_t a, b; fmpz_t coeff, mod, reduced_coeff; fmpz_init(mod); fmpz_randtest_unsigned(mod, state, 2 * FLINT_BITS); fmpz_add_ui(mod, mod, 2); fmpz_init(coeff); fmpz_init(reduced_coeff); nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_randtest(a, state, 200, nf); nf_elem_mod_fmpz_den(b, a, mod, nf, 0); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, a, j, nf); fmpz_mod(coeff, coeff, mod); nf_elem_get_coeff_fmpz(reduced_coeff, b, j, nf); result = fmpz_equal(reduced_coeff, coeff); if (!result) { printf("FAIL: Reducing without denominator\n"); printf("f = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("n = "); fmpz_print(mod); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); flint_abort(); } } nf_elem_smod_fmpz_den(b, a, mod, nf, 0); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, a, j, nf); fmpz_smod(coeff, coeff, mod); nf_elem_get_coeff_fmpz(reduced_coeff, b, j, nf); result = fmpz_equal(reduced_coeff, coeff); if (!result) { printf("FAIL: Reducing without denominator\n"); printf("f = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("n = "); fmpz_print(mod); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); flint_abort(); } } nf_elem_clear(a, nf); nf_elem_clear(b, nf); fmpz_clear(coeff); fmpz_clear(reduced_coeff); fmpz_clear(mod); nf_clear(nf); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong j; nf_t nf; nf_elem_t a, b, c; fmpz_t coeff, mod, den; fmpz_init(mod); fmpz_randtest_unsigned(mod, state, 2 * FLINT_BITS); fmpz_add_ui(mod, mod, 2); fmpz_init(coeff); fmpz_init(den); nf_init_randtest(nf, state, 4, 2); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(a, state, 2, nf); nf_elem_mod_fmpz(b, a, mod, nf); nf_elem_sub(c, b, a, nf); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, c, j, nf); fmpz_mod(coeff, coeff, mod); result = fmpz_is_zero(coeff); if (!result || !nf_elem_den_is_one(c, nf)) { printf("FAIL: Reducing without denominator\n"); printf("f = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); printf("n = "); fmpz_print(mod); printf("\n"); flint_abort(); } } nf_elem_smod_fmpz(b, a, mod, nf); nf_elem_sub(c, b, a, nf); for (j = 0; j < fmpq_poly_degree(nf->pol); j++) { nf_elem_get_coeff_fmpz(coeff, c, j, nf); fmpz_smod(coeff, coeff, mod); result = fmpz_is_zero(coeff); if (!result || !nf_elem_den_is_one(c, nf)) { printf("FAIL: Reducing without denominator\n"); printf("f = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); printf("n = "); fmpz_print(mod); printf("\n"); flint_abort(); } } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); fmpz_clear(coeff); fmpz_clear(mod); fmpz_clear(den); nf_clear(nf); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; fmpz_t mod, den, gcd; fmpz_init(mod); fmpz_randtest_unsigned(mod, state, 2 * FLINT_BITS); fmpz_add_ui(mod, mod, 2); fmpz_init(den); fmpz_init(gcd); nf_init_randtest(nf, state, 4, 2); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(a, state, 2, nf); nf_elem_coprime_den(b, a, mod, nf); nf_elem_sub(c, b, a, nf); nf_elem_get_den(den, c, nf); fmpz_gcd(gcd, den, mod); if (!fmpz_is_one(gcd)) { printf("FAIL: Coprime denominators\n"); printf("f = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); printf("n = "); fmpz_print(mod); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); fmpz_clear(mod); fmpz_clear(den); fmpz_clear(gcd); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-mul.c000066400000000000000000000077021461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_mul, state) { int i, result; /* test a*(b + c) = a*b + a*c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c, s, p, p1, p2; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_init(s, nf); nf_elem_init(p, nf); nf_elem_init(p1, nf); nf_elem_init(p2, nf); nf_elem_randtest(a, state, 200, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); nf_elem_add(s, b, c, nf); nf_elem_mul(p1, a, b, nf); nf_elem_mul(p2, a, c, nf); nf_elem_mul(p, a, s, nf); nf_elem_add(s, p1, p2, nf); result = (nf_elem_equal(p, s, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); printf("s = "); nf_elem_print_pretty(s, nf, "x"); printf("\n"); printf("p = "); nf_elem_print_pretty(p, nf, "x"); printf("\n"); printf("p1 = "); nf_elem_print_pretty(p1, nf, "x"); printf("\n"); printf("p2 = "); nf_elem_print_pretty(p2, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_elem_clear(s, nf); nf_elem_clear(p, nf); nf_elem_clear(p1, nf); nf_elem_clear(p2, nf); nf_clear(nf); } /* test aliasing a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); nf_elem_mul(a, b, c, nf); nf_elem_mul(b, b, c, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } /* test aliasing a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); nf_elem_mul(a, b, c, nf); nf_elem_mul(c, b, c, nf); result = (nf_elem_equal(a, c, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-mul_div_fmpq.c000066400000000000000000000050221461254215100210740ustar00rootroot00000000000000/* Copyright (C) 2020 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_mul_div_fmpq, state) { int i, result; /* test b + c - c = b */ for (i = 0; i < 100; i++) { nf_t nf; nf_elem_t a, b, t; fmpq_t c; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(t, nf); fmpq_init(c); nf_elem_randtest(b, state, 200, nf); fmpq_randtest_not_zero(c, state, 200); nf_elem_scalar_mul_fmpq(t, b, c, nf); nf_elem_scalar_div_fmpq(a, t, c, nf); result = nf_elem_equal(a, b, nf); if (!result) { printf("FAIL:\n"); printf("nf = "); nf_print(nf); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); fmpq_print(c); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(t, nf); fmpq_clear(c); nf_clear(nf); } /* test aliasing a and b */ for (i = 0; i < 100; i++) { nf_t nf; nf_elem_t a, b; fmpq_t c; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); fmpq_init(c); nf_elem_randtest(b, state, 200, nf); fmpq_randtest_not_zero(c, state, 200); nf_elem_set(a, b, nf); nf_elem_scalar_mul_fmpq(b, b, c, nf); nf_elem_scalar_div_fmpq(b, b, c, nf); result = nf_elem_equal(a, b, nf); if (!result) { printf("FAIL:\n"); printf("(with aliasing)\n"); printf("nf = "); nf_print(nf); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); fmpq_print(c); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); fmpq_clear(c); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-mul_gen.c000066400000000000000000000046311461254215100200450ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_mul_gen, state) { int i, result; /* test mul_gen(b) = a * b, where a is the generator */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, p1, p2; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(p1, nf); nf_elem_init(p2, nf); nf_elem_gen(a, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_mul_gen(p1, b, nf); nf_elem_mul(p2, b, a, nf); result = (nf_elem_equal(p1, p2, nf)); if (!result) { printf("FAIL:\n"); printf("K = "); nf_print(nf); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("p1 = "); nf_elem_print_pretty(p1, nf, "x"); printf("\n"); printf("p2 = "); nf_elem_print_pretty(p2, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(p1, nf); nf_elem_clear(p2, nf); nf_clear(nf); } /* test aliasing b and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t b, c; nf_init_randtest(nf, state, 40, 200); nf_elem_init(b, nf); nf_elem_init(c, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_randtest(c, state, 200, nf); nf_elem_mul_gen(b, c, nf); nf_elem_mul_gen(c, c, nf); result = (nf_elem_equal(b, c, nf)); if (!result) { printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-norm.c000066400000000000000000000042601461254215100173700ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_norm, state) { int i, result; /* test norm(a*b) = norm(a)*norm(b) */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; fmpq_t anorm, bnorm, cnorm, cnorm2; nf_init_randtest(nf, state, 25, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); fmpq_init(anorm); fmpq_init(bnorm); fmpq_init(cnorm); fmpq_init(cnorm2); nf_elem_randtest(a, state, 200, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_mul(c, a, b, nf); nf_elem_norm(anorm, a, nf); nf_elem_norm(bnorm, b, nf); nf_elem_norm(cnorm, c, nf); fmpq_mul(cnorm2, anorm, bnorm); result = (fmpq_equal(cnorm, cnorm2)); if (!result) { printf("FAIL:\n"); printf("nf->pol = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); printf("norm(a) = "); fmpq_print(anorm); printf("\n"); printf("norm(b) = "); fmpq_print(bnorm); printf("\n"); printf("norm(a*b) = "); fmpq_print(cnorm); printf("\n"); printf("norm(a)*norm(b) = "); fmpq_print(cnorm2); printf("\n"); flint_abort(); } fmpq_clear(anorm); fmpq_clear(bnorm); fmpq_clear(cnorm); fmpq_clear(cnorm2); nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-norm_div.c000066400000000000000000000060611461254215100202330ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_norm_div, state) { int i, result; for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpq_poly_t pol; fmpz_poly_t pol2; nf_t nf; nf_elem_t a, b, c; fmpq_t anorm, bnorm, cnorm, cnorm2; fmpz_t d; slong nbits; fmpq_poly_init(pol); fmpz_poly_init(pol2); fmpz_init(d); do { fmpz_poly_randtest_not_zero(pol2, state, 25, 200); fmpz_one(fmpz_poly_lead(pol2)); } while (fmpz_poly_degree(pol2) < 1); fmpq_poly_set_fmpz_poly(pol, pol2); nf_init(nf, pol); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); fmpq_init(anorm); fmpq_init(bnorm); fmpq_init(cnorm); fmpq_init(cnorm2); do { nf_elem_randtest(a, state, 200, nf); nf_elem_get_den(d, a, nf); nf_elem_scalar_mul_fmpz(a, a, d, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_get_den(d, b, nf); nf_elem_scalar_mul_fmpz(b, b, d, nf); nf_elem_mul(c, a, b, nf); nf_elem_norm(anorm, a, nf); nf_elem_norm(bnorm, b, nf); nf_elem_norm(cnorm2, c, nf); } while (fmpq_is_zero(cnorm2)); nbits = (slong)fmpz_bits(fmpq_numref(anorm)) + 1; nf_elem_norm_div(cnorm, c, nf, fmpq_numref(bnorm), nbits); result = (fmpq_equal(cnorm, anorm)); if (!result) { printf("FAIL:\n"); printf("nf->pol = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("norm(c) = "); fmpq_print(cnorm2); printf("\n"); printf("norm(c) = "); fmpq_print(anorm); printf(" * "); fmpq_print(bnorm); printf("\n"); printf("supplied divisor = "); fmpq_print(bnorm); printf("\n"); printf("divisor found = "); fmpq_print(cnorm); printf("\n"); printf("correct result = "); fmpq_print(anorm); printf("\n"); flint_printf("bits bound: %wd\n", nbits); flint_abort(); } fmpq_clear(anorm); fmpq_clear(bnorm); fmpq_clear(cnorm); fmpq_clear(cnorm2); fmpz_clear(d); nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); fmpq_poly_clear(pol); fmpz_poly_clear(pol2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-pow.c000066400000000000000000000051511461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_pow, state) { int i, j, result; /* test pow(a, e) = e*e*...*e */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, p1, p2; slong exp; nf_init_randtest(nf, state, 40, 20); nf_elem_init(a, nf); nf_elem_init(p1, nf); nf_elem_init(p2, nf); nf_elem_randtest(a, state, 20, nf); exp = n_randint(state, 10); nf_elem_pow(p1, a, exp, nf); nf_elem_one(p2, nf); for (j = 0; j < exp; j++) nf_elem_mul(p2, p2, a, nf); result = (nf_elem_equal(p1, p2, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("p1 = "); nf_elem_print_pretty(p1, nf, "x"); printf("\n"); printf("p2 = "); nf_elem_print_pretty(p2, nf, "x"); printf("\n"); flint_printf("exp = %w\n", exp); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(p1, nf); nf_elem_clear(p2, nf); nf_clear(nf); } /* test aliasing a and res */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, p1, p2; slong exp; nf_init_randtest(nf, state, 40, 20); nf_elem_init(a, nf); nf_elem_init(p1, nf); nf_elem_init(p2, nf); nf_elem_randtest(a, state, 20, nf); exp = n_randint(state, 10); nf_elem_pow(p1, a, exp, nf); nf_elem_set(p2, a, nf); nf_elem_pow(p2, p2, exp, nf); result = (nf_elem_equal(p1, p2, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("p1 = "); nf_elem_print_pretty(p1, nf, "x"); printf("\n"); printf("p2 = "); nf_elem_print_pretty(p2, nf, "x"); printf("\n"); flint_printf("exp = %w\n", exp); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(p1, nf); nf_elem_clear(p2, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-rep_mat.c000066400000000000000000000043371461254215100200510ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_mat.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_rep_mat, state) { int i; /* test mul_gen(b) = a * b, where a is the generator */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, p1, p2, t; slong d; slong j, k; fmpq_mat_t R; nf_init_randtest(nf, state, 20, 100); d = fmpq_poly_degree(nf->pol); fmpq_mat_init(R, d, d); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(p1, nf); nf_elem_init(p2, nf); nf_elem_init(t, nf); nf_elem_randtest(b, state, 100, nf); nf_elem_rep_mat(R, b, nf); for (j = 0; j < d; j++) { nf_elem_gen(a, nf); nf_elem_pow(a, a, j, nf); nf_elem_mul(p1, b, a, nf); nf_elem_zero(p2, nf); for (k = 0; k < d; k++) { nf_elem_gen(t, nf); nf_elem_pow(t, t, k, nf); nf_elem_scalar_mul_fmpq(t, t, fmpq_mat_entry(R, j, k), nf); nf_elem_add(p2, p2, t, nf); } if (!nf_elem_equal(p1, p2, nf)) { printf("FAIL:\n"); printf("K = "); nf_print(nf); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("p1 = "); nf_elem_print_pretty(p1, nf, "x"); printf("\n"); printf("p2 = "); nf_elem_print_pretty(p2, nf, "x"); printf("\n"); flint_abort(); } } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(p1, nf); nf_elem_clear(p2, nf); nf_elem_clear(t, nf); fmpq_mat_clear(R); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-rep_mat_fmpz_mat_den.c000066400000000000000000000050531461254215100225700ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mat.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_rep_mat_fmpz_mat_den, state) { int i; /* test mul_gen(b) = a * b, where a is the generator */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, p1, p2, t; slong d; slong j, k; fmpz_mat_t R; fmpz_t den; nf_init_randtest(nf, state, 20, 100); d = fmpq_poly_degree(nf->pol); fmpz_mat_init(R, d, d); fmpz_init(den); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(p1, nf); nf_elem_init(p2, nf); nf_elem_init(t, nf); nf_elem_randtest(b, state, 100, nf); nf_elem_rep_mat_fmpz_mat_den(R, den, b, nf); /* fmpz_mat_print_pretty(R); */ for (j = 0; j < d; j++) { nf_elem_gen(a, nf); nf_elem_pow(a, a, j, nf); nf_elem_mul(p1, b, a, nf); nf_elem_zero(p2, nf); for (k = 0; k < d; k++) { nf_elem_gen(t, nf); nf_elem_pow(t, t, k, nf); nf_elem_scalar_mul_fmpz(t, t, fmpz_mat_entry(R, j, k), nf); nf_elem_add(p2, p2, t, nf); } nf_elem_scalar_div_fmpz(p2, p2, den, nf); if (!nf_elem_equal(p1, p2, nf)) { printf("FAIL:\n"); printf("R = "); fmpz_mat_print_pretty(R); printf("\n"); printf("d = "); fmpz_print(den); printf("\n"); printf("K = "); nf_print(nf); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("p1 = "); nf_elem_print_pretty(p1, nf, "x"); printf("\n"); printf("p2 = "); nf_elem_print_pretty(p2, nf, "x"); printf("\n"); flint_abort(); } } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(p1, nf); nf_elem_clear(p2, nf); nf_elem_clear(t, nf); fmpz_mat_clear(R); fmpz_clear(den); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-set_coeff_num_fmpz.c000066400000000000000000000042411461254215100222640ustar00rootroot00000000000000/* Copyright (C) 2018 Tommy Hofmann 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_set_coeff_num_fmpz, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b; fmpz_t d, d2; slong coeff; fmpq_t newcoeff, tempcoeff; nf_init_randtest(nf, state, 40, 200); fmpz_init(d); fmpz_init(d2); fmpq_init(tempcoeff); fmpq_init(newcoeff); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_randtest(a, state, 200, nf); nf_elem_set(b, a, nf); coeff = (slong) n_randint(state, fmpq_poly_degree(nf->pol)); fmpz_randtest(d, state, 200); nf_elem_get_den(fmpq_denref(tempcoeff), a, nf); fmpz_set(fmpq_numref(tempcoeff), d); fmpq_canonicalise(tempcoeff); _nf_elem_set_coeff_num_fmpz(a, coeff, d, nf); nf_elem_get_coeff_fmpq(newcoeff, a, coeff, nf); result = fmpq_equal(newcoeff, tempcoeff); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); flint_printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); flint_printf("coeff = %u\n", coeff); flint_printf("d = "); fmpz_print(d); printf("\n"); flint_printf("newcoeff = "); fmpq_print(newcoeff); printf("\n"); flint_printf("pol = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_clear(nf); fmpz_clear(d); fmpz_clear(d2); fmpq_clear(tempcoeff); fmpq_clear(newcoeff); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-set_equal.c000066400000000000000000000034471461254215100204050ustar00rootroot00000000000000/* Copyright (C) 2013 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_set_equal, state) { int i, result; /* set a = b, check a == b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_set(a, b, nf); result = (nf_elem_equal(a, b, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_clear(nf); } /* test aliasing a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a; nf_init_randtest(nf, state, 40, 200); nf_elem_init(a, nf); nf_elem_randtest(a, state, 200, nf); nf_elem_set(a, a, nf); result = (nf_elem_equal(a, a, nf)); if (!result) { printf("FAIL:\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); flint_abort(); } nf_elem_clear(a, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-set_equal_si_ui.c000066400000000000000000000100471461254215100215670ustar00rootroot00000000000000/* Copyright (C) 2018 Vincent Delecroix 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_set_equal_si_ui, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t f; ulong m, n; slong sm, sn; int f_is_m; nf_t nf; nf_elem_t a; nf_elem_t b; nf_init_randtest(nf, state, 20, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); fmpq_poly_init(f); /* unsigned words */ m = n_randtest(state); n = n_randtest(state); nf_elem_set_ui(a, m, nf); nf_elem_set_ui(b, n, nf); if (!nf_elem_equal_ui(a, m, nf) || !nf_elem_equal_ui(b, n, nf) || nf_elem_equal_ui(a, n, nf) != (m == n) || nf_elem_equal_ui(b, m, nf) != (m == n)) { flint_printf("set_ui/equal_ui wrong with\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("m = %wu\n", m); flint_printf("n = %wu\n", n); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); flint_printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); flint_abort(); } fmpq_poly_randtest(f, state, fmpq_poly_degree(nf->pol) - 1, 200); nf_elem_set_fmpq_poly(a, f, nf); if (fmpq_poly_length(f) == 0) f_is_m = m == 0; else f_is_m = fmpq_poly_length(f) == 1 && fmpz_equal_ui(fmpq_poly_numref(f), m) && fmpz_is_one(fmpq_poly_denref(f)); if (nf_elem_equal_ui(a, m, nf) != f_is_m) { flint_printf("equal_ui wrong with\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("m = %wu\n", m); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); flint_printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_abort(); } /* with signed words */ sm = (slong) m; sn = (slong) n; nf_elem_set_si(a, sm, nf); nf_elem_set_si(b, sn, nf); if (!nf_elem_equal_si(a, sm, nf) || !nf_elem_equal_si(b, sn, nf) || nf_elem_equal_si(a, sn, nf) != (m == n) || nf_elem_equal_si(b, sm, nf) != (m == n)) { flint_printf("set_si/equal_si wrong with\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("sm = %wd\n", sm); flint_printf("sn = %wd\n", sn); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_printf("b = "); nf_elem_print_pretty(b, nf, "x"); flint_printf("\n"); flint_abort(); } nf_elem_set_fmpq_poly(a, f, nf); if (sm == 0) f_is_m = fmpq_poly_length(f) == 0; else f_is_m = fmpq_poly_length(f) == 1 && fmpz_equal_si(fmpq_poly_numref(f), sm) && fmpz_is_one(fmpq_poly_denref(f)); if (nf_elem_equal_si(a, sm, nf) != f_is_m) { flint_printf("equal_si wrong with\n"); flint_printf("nf = "); nf_print(nf); flint_printf("\n"); flint_printf("sm = %wd\n", sm); flint_printf("f = "); fmpq_poly_print_pretty(f, "x"); flint_printf("\n"); flint_printf("a = "); nf_elem_print_pretty(a, nf, "x"); flint_printf("\n"); flint_abort(); } /* cleaning */ fmpq_poly_clear(f); nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/test/t-trace.c000066400000000000000000000043351461254215100175160ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart 2020 Julian Rüth This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nf_elem.h" TEST_FUNCTION_START(nf_elem_trace, state) { int i, result; /* test trace(a + b) = trace(a) + trace(b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nf_t nf; nf_elem_t a, b, c; fmpq_t atrace, btrace, ctrace, ctrace2; nf_init_randtest(nf, state, 25, 200); nf_elem_init(a, nf); nf_elem_init(b, nf); nf_elem_init(c, nf); fmpq_init(atrace); fmpq_init(btrace); fmpq_init(ctrace); fmpq_init(ctrace2); nf_elem_randtest(a, state, 200, nf); nf_elem_randtest(b, state, 200, nf); nf_elem_add(c, a, b, nf); nf_elem_trace(atrace, a, nf); nf_elem_trace(btrace, b, nf); nf_elem_trace(ctrace, c, nf); fmpq_add(ctrace2, atrace, btrace); result = (fmpq_equal(ctrace, ctrace2)); if (!result) { printf("FAIL:\n"); printf("nf->pol = "); fmpq_poly_print_pretty(nf->pol, "x"); printf("\n"); printf("a = "); nf_elem_print_pretty(a, nf, "x"); printf("\n"); printf("b = "); nf_elem_print_pretty(b, nf, "x"); printf("\n"); printf("c = "); nf_elem_print_pretty(c, nf, "x"); printf("\n"); printf("trace(a) = "); fmpq_print(atrace); printf("\n"); printf("trace(b) = "); fmpq_print(btrace); printf("\n"); printf("trace(a + b) = "); fmpq_print(ctrace); printf("\n"); printf("trace(a) + trace(b) = "); fmpq_print(ctrace2); printf("\n"); flint_abort(); } fmpq_clear(atrace); fmpq_clear(btrace); fmpq_clear(ctrace); fmpq_clear(ctrace2); nf_elem_clear(a, nf); nf_elem_clear(b, nf); nf_elem_clear(c, nf); nf_clear(nf); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nf_elem/trace.c000066400000000000000000000041301461254215100162670ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "nf_elem.h" void _nf_elem_trace(fmpz_t rnum, fmpz_t rden, const nf_elem_t a, const nf_t nf) { slong i; if (nf->flag & NF_LINEAR) { const fmpz * const anum = LNF_ELEM_NUMREF(a); const fmpz * const aden = LNF_ELEM_DENREF(a); fmpz_set(rnum, anum); fmpz_set(rden, aden); } else if (nf->flag & NF_QUADRATIC) { const fmpz * const anum = QNF_ELEM_NUMREF(a); const fmpz * const aden = QNF_ELEM_DENREF(a); const fmpz * const tnum = fmpq_poly_numref(nf->traces); const fmpz * const tden = fmpq_poly_denref(nf->traces); slong alen = 2; while (alen > 0 && fmpz_is_zero(anum + alen - 1)) alen--; if (alen == 0) { fmpz_zero(rnum); fmpz_one(rden); } else { fmpz_mul(rnum, anum, tnum); if (alen == 2) fmpz_addmul(rnum, anum + 1, tnum + 1); fmpz_mul(rden, aden, tden); _fmpq_canonicalise(rnum, rden); } } else /* generic nf_elem */ { const fmpz * const anum = NF_ELEM_NUMREF(a); const fmpz * const aden = NF_ELEM_DENREF(a); const fmpz * const tnum = fmpq_poly_numref(nf->traces); const fmpz * const tden = fmpq_poly_denref(nf->traces); slong alen = NF_ELEM(a)->length; if (alen == 0) { fmpz_zero(rnum); fmpz_one(rden); } else { fmpz_mul(rnum, anum, tnum); for (i = 1; i < alen; i++) fmpz_addmul(rnum, anum + i, tnum + i); fmpz_mul(rden, aden, tden); _fmpq_canonicalise(rnum, rden); } } } void nf_elem_trace(fmpq_t res, const nf_elem_t a, const nf_t nf) { _nf_elem_trace(fmpq_numref(res), fmpq_denref(res), a, nf); } flint-3.1.3/src/nf_elem/zero.c000066400000000000000000000014441461254215100161550ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nf_elem.h" void nf_elem_zero(nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_zero(LNF_ELEM_NUMREF(a)); fmpz_one(LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz_zero(anum); fmpz_zero(anum + 1); fmpz_one(QNF_ELEM_DENREF(a)); } else fmpq_poly_zero(NF_ELEM(a)); } flint-3.1.3/src/nmod.h000066400000000000000000000153761461254215100145440ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_H #define NMOD_H #ifdef NMOD_INLINES_C #define NMOD_INLINE #else #define NMOD_INLINE static inline #endif #include "ulong_extras.h" #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif #define NMOD_RED2(r, a_hi, a_lo, mod) \ do { \ mp_limb_t q0xx, q1xx, r1xx; \ const mp_limb_t u1xx = ((a_hi)<<(mod).norm) + r_shift((a_lo), FLINT_BITS - (mod).norm); \ const mp_limb_t u0xx = ((a_lo)<<(mod).norm); \ const mp_limb_t nxx = ((mod).n<<(mod).norm); \ umul_ppmm(q1xx, q0xx, (mod).ninv, u1xx); \ add_ssaaaa(q1xx, q0xx, q1xx, q0xx, u1xx, u0xx); \ r1xx = (u0xx - (q1xx + 1)*nxx); \ if (r1xx > q0xx) r1xx += nxx; \ if (r1xx < nxx) r = (r1xx>>(mod).norm); \ else r = ((r1xx - nxx)>>(mod).norm); \ } while (0) #define NMOD_RED(r, a, mod) \ do { \ NMOD_RED2(r, 0, a, mod); \ } while (0) #define NMOD2_RED2(r, a_hi, a_lo, mod) \ do { \ mp_limb_t v_hi; \ NMOD_RED(v_hi, a_hi, mod); \ NMOD_RED2(r, v_hi, a_lo, mod); \ } while (0) #define NMOD_RED3(r, a_hi, a_me, a_lo, mod) \ do { \ mp_limb_t v_hi; \ NMOD_RED2(v_hi, a_hi, a_me, mod); \ NMOD_RED2(r, v_hi, a_lo, mod); \ } while (0) #define NMOD_BITS(mod) (FLINT_BITS - ((mod).norm)) #define NMOD_CAN_USE_SHOUP(mod) ((mod).norm > 0) #define NMOD_MUL_PRENORM(res, a, b, mod) \ do { \ mp_limb_t q0xx, q1xx, rxx, p_hixx, p_loxx; \ mp_limb_t nxx, ninvxx; \ unsigned int normxx; \ ninvxx = (mod).ninv; \ normxx = (mod).norm; \ nxx = (mod).n << normxx; \ umul_ppmm(p_hixx, p_loxx, (a), (b)); \ umul_ppmm(q1xx, q0xx, ninvxx, p_hixx); \ add_ssaaaa(q1xx, q0xx, q1xx, q0xx, p_hixx, p_loxx); \ rxx = (p_loxx - (q1xx + 1) * nxx); \ if (rxx > q0xx) \ rxx += nxx; \ rxx = (rxx < nxx ? rxx : rxx - nxx) >> normxx; \ (res) = rxx; \ } while (0) #define NMOD_MUL_FULLWORD(res, a, b, mod) \ do { \ mp_limb_t q0xx, q1xx, rxx, p_hixx, p_loxx; \ mp_limb_t nxx, ninvxx; \ ninvxx = (mod).ninv; \ nxx = (mod).n; \ umul_ppmm(p_hixx, p_loxx, (a), (b)); \ umul_ppmm(q1xx, q0xx, ninvxx, p_hixx); \ add_ssaaaa(q1xx, q0xx, q1xx, q0xx, p_hixx, p_loxx); \ rxx = (p_loxx - (q1xx + 1) * nxx); \ if (rxx > q0xx) \ rxx += nxx; \ rxx = (rxx < nxx ? rxx : rxx - nxx); \ (res) = rxx; \ } while (0) NMOD_INLINE mp_limb_t nmod_set_ui(ulong x, nmod_t mod) { if (x < mod.n) return x; NMOD_RED(x, x, mod); return x; } NMOD_INLINE mp_limb_t nmod_set_si(slong x, nmod_t mod) { ulong res = FLINT_ABS(x); NMOD_RED(res, res, mod); return (res == 0 || x > 0) ? res : mod.n - res; } NMOD_INLINE mp_limb_t _nmod_add(mp_limb_t a, mp_limb_t b, nmod_t mod) { const mp_limb_t sum = a + b; return sum - mod.n + ((((mp_limb_signed_t)(sum - mod.n))>>(FLINT_BITS - 1)) & mod.n); } NMOD_INLINE mp_limb_t _nmod_sub(mp_limb_t a, mp_limb_t b, nmod_t mod) { const mp_limb_t diff = a - b; return ((((mp_limb_signed_t)diff)>>(FLINT_BITS - 1)) & mod.n) + diff; } NMOD_INLINE mp_limb_t nmod_add(mp_limb_t a, mp_limb_t b, nmod_t mod) { const mp_limb_t neg = mod.n - a; if (neg > b) return a + b; else return b - neg; } NMOD_INLINE mp_limb_t nmod_sub(mp_limb_t a, mp_limb_t b, nmod_t mod) { const mp_limb_t diff = a - b; if (a < b) return mod.n + diff; else return diff; } NMOD_INLINE mp_limb_t nmod_neg(mp_limb_t a, nmod_t mod) { if (a) return mod.n - a; else return 0; } NMOD_INLINE mp_limb_t nmod_mul(mp_limb_t a, mp_limb_t b, nmod_t mod) { mp_limb_t res; NMOD_MUL_PRENORM(res, a, b << mod.norm, mod); return res; } NMOD_INLINE mp_limb_t _nmod_mul_fullword(mp_limb_t a, mp_limb_t b, nmod_t mod) { mp_limb_t res; NMOD_MUL_FULLWORD(res, a, b, mod); return res; } NMOD_INLINE mp_limb_t nmod_addmul(mp_limb_t a, mp_limb_t b, mp_limb_t c, nmod_t mod) { return nmod_add(a, nmod_mul(b, c, mod), mod); } #define NMOD_ADDMUL(r, a, b, mod) \ do { \ (r) = nmod_addmul((r), (a), (b), (mod)); \ } while (0) NMOD_INLINE mp_limb_t nmod_inv(mp_limb_t a, nmod_t mod) { return n_invmod(a, mod.n); } NMOD_INLINE mp_limb_t nmod_div(mp_limb_t a, mp_limb_t b, nmod_t mod) { return nmod_mul(a, n_invmod(b, mod.n), mod); } int nmod_divides(mp_limb_t * a, mp_limb_t b, mp_limb_t c, nmod_t mod); NMOD_INLINE mp_limb_t nmod_pow_ui(mp_limb_t a, ulong exp, nmod_t mod) { return n_powmod2_ui_preinv(a, exp, mod.n, mod.ninv); } NMOD_INLINE mp_limb_t nmod_pow_fmpz(mp_limb_t a, const fmpz_t exp, nmod_t mod) { return n_powmod2_fmpz_preinv(a, exp, mod.n, mod.ninv); } NMOD_INLINE void nmod_init(nmod_t * mod, mp_limb_t n) { mod->n = n; mod->ninv = n_preinvert_limb(n); mod->norm = flint_clz(n); } /* discrete logs a la Pohlig - Hellman ***************************************/ typedef struct { mp_limb_t gammapow; ulong cm; } nmod_discrete_log_pohlig_hellman_table_entry_struct; typedef struct { slong exp; ulong prime; mp_limb_t gamma; mp_limb_t gammainv; mp_limb_t startingbeta; ulong co; ulong startinge; ulong idem; ulong cbound; ulong dbound; nmod_discrete_log_pohlig_hellman_table_entry_struct * table; /* length cbound */ } nmod_discrete_log_pohlig_hellman_entry_struct; typedef struct { nmod_t mod; /* p is mod.n */ mp_limb_t alpha; /* p.r. of p */ mp_limb_t alphainv; slong num_factors; /* factors of p - 1*/ nmod_discrete_log_pohlig_hellman_entry_struct * entries; } nmod_discrete_log_pohlig_hellman_struct; typedef nmod_discrete_log_pohlig_hellman_struct nmod_discrete_log_pohlig_hellman_t[1]; void nmod_discrete_log_pohlig_hellman_init( nmod_discrete_log_pohlig_hellman_t L); void nmod_discrete_log_pohlig_hellman_clear( nmod_discrete_log_pohlig_hellman_t L); double nmod_discrete_log_pohlig_hellman_precompute_prime( nmod_discrete_log_pohlig_hellman_t L, mp_limb_t p); ulong nmod_discrete_log_pohlig_hellman_run( const nmod_discrete_log_pohlig_hellman_t L, mp_limb_t y); NMOD_INLINE mp_limb_t nmod_discrete_log_pohlig_hellman_primitive_root( const nmod_discrete_log_pohlig_hellman_t L) { return L->alpha; } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod/000077500000000000000000000000001461254215100143575ustar00rootroot00000000000000flint-3.1.3/src/nmod/divides.c000066400000000000000000000020521461254215100161510ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "ulong_extras.h" int nmod_divides(mp_limb_t * a, mp_limb_t b, mp_limb_t c, nmod_t mod) { int success; ulong g, x, y, q; if (c == 0) { if (b == 0) { *a = 0; return 1; } else { *a = 0; return 0; } } else if (b == 0) { *a = 0; return 1; } /* solve g = c*(-x) + n*y where g = gcd(c, n) */ g = n_xgcd(&y, &x, mod.n, c); success = (b % g == 0); if (success) { q = b / g; *a = nmod_mul(q, nmod_neg(x, mod), mod); } return success; } flint-3.1.3/src/nmod/inlines.c000066400000000000000000000006671461254215100161750ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_INLINES_C #include "flint.h" #include "nmod.h" flint-3.1.3/src/nmod/test/000077500000000000000000000000001461254215100153365ustar00rootroot00000000000000flint-3.1.3/src/nmod/test/main.c000066400000000000000000000013761461254215100164350ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-divides.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_divides), }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod/test/t-divides.c000066400000000000000000000026501461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" TEST_FUNCTION_START(nmod_divides, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t n, x, y, xy, z; int div; n = n_randtest_not_zero(state); nmod_init(&mod, n); x = n_randtest(state) % n; y = n_randtest(state) % n; xy = nmod_mul(x, y, mod); div = nmod_divides(&z, xy, x, mod); /* Claimed divisible, so check this. */ if (!div || nmod_mul(z, x, mod) != xy) TEST_FUNCTION_FAIL("n = %wu, div = %d, x = %wu, y = %wu, z = %wu\n", n, div, x, y, z); div = nmod_divides(&z, x, y, mod); /* If claimed not divisible, verify by brute force. */ if (!div && n <= 50) { for (z = 0; z < n; z++) { if (nmod_mul(z, y, mod) == x) TEST_FUNCTION_FAIL("n = %wu, div = %d, x = %wu, y = %wu, z = %wu\n", n, div, x, y, z); } } } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat.h000066400000000000000000000254001461254215100153720ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_MAT_H #define NMOD_MAT_H #ifdef NMOD_MAT_INLINES_C #define NMOD_MAT_INLINE #else #define NMOD_MAT_INLINE static inline #endif #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif #define nmod_mat_entry(mat,i,j) ((mat)->rows[(i)][(j)]) NMOD_MAT_INLINE mp_limb_t nmod_mat_get_entry(const nmod_mat_t mat, slong i, slong j) { return mat->rows[i][j]; } NMOD_MAT_INLINE mp_limb_t * nmod_mat_entry_ptr(const nmod_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } /* See inlines.c */ NMOD_MAT_INLINE slong nmod_mat_nrows(const nmod_mat_t mat) { return mat->r; } NMOD_MAT_INLINE slong nmod_mat_ncols(const nmod_mat_t mat) { return mat->c; } /* TODO: Document */ void nmod_mat_set_mod(nmod_mat_t mat, mp_limb_t n); /* Memory management */ void nmod_mat_init(nmod_mat_t mat, slong rows, slong cols, mp_limb_t n); void nmod_mat_init_set(nmod_mat_t mat, const nmod_mat_t src); void nmod_mat_clear(nmod_mat_t mat); void nmod_mat_one(nmod_mat_t mat); void nmod_mat_swap(nmod_mat_t mat1, nmod_mat_t mat2); NMOD_MAT_INLINE void nmod_mat_swap_entrywise(nmod_mat_t mat1, nmod_mat_t mat2) { slong i, j; for (i = 0; i < nmod_mat_nrows(mat1); i++) { mp_limb_t * row1 = mat1->rows[i]; mp_limb_t * row2 = mat2->rows[i]; for (j = 0; j < nmod_mat_ncols(mat1); j++) FLINT_SWAP(mp_limb_t, row1[j], row2[j]); } } /* Windows and concatenation */ void nmod_mat_window_init(nmod_mat_t window, const nmod_mat_t mat, slong r1, slong c1, slong r2, slong c2); void nmod_mat_window_clear(nmod_mat_t window); void nmod_mat_concat_horizontal(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2); void nmod_mat_concat_vertical(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2); /* Random matrix generation */ void nmod_mat_randtest(nmod_mat_t mat, flint_rand_t state); void nmod_mat_randfull(nmod_mat_t mat, flint_rand_t state); int nmod_mat_randpermdiag(nmod_mat_t mat, flint_rand_t state, mp_srcptr diag, slong n); void nmod_mat_randrank(nmod_mat_t, flint_rand_t state, slong rank); void nmod_mat_randops(nmod_mat_t mat, flint_rand_t state, slong count); void nmod_mat_randtril(nmod_mat_t mat, flint_rand_t state, int unit); void nmod_mat_randtriu(nmod_mat_t mat, flint_rand_t state, int unit); #ifdef FLINT_HAVE_FILE int nmod_mat_fprint_pretty(FILE* file, const nmod_mat_t mat); int nmod_mat_fprint(FILE* f, const nmod_mat_t mat); #endif void nmod_mat_print_pretty(const nmod_mat_t mat); int nmod_mat_print(const nmod_mat_t mat); int nmod_mat_equal(const nmod_mat_t mat1, const nmod_mat_t mat2); void nmod_mat_zero(nmod_mat_t mat); int nmod_mat_is_zero(const nmod_mat_t mat); int nmod_mat_is_one(const nmod_mat_t mat); int nmod_mat_is_zero_row(const nmod_mat_t mat, slong i); NMOD_MAT_INLINE int nmod_mat_is_empty(const nmod_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } NMOD_MAT_INLINE int nmod_mat_is_square(const nmod_mat_t mat) { return (mat->r == mat->c); } void nmod_mat_set(nmod_mat_t B, const nmod_mat_t A); void nmod_mat_transpose(nmod_mat_t B, const nmod_mat_t A); /* Addition and subtraction */ void nmod_mat_add(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void nmod_mat_sub(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void nmod_mat_neg(nmod_mat_t B, const nmod_mat_t A); /* Matrix-scalar arithmetic */ void nmod_mat_scalar_mul(nmod_mat_t B, const nmod_mat_t A, mp_limb_t c); void nmod_mat_scalar_addmul_ui(nmod_mat_t dest, const nmod_mat_t X, const nmod_mat_t Y, const mp_limb_t b); void nmod_mat_scalar_mul_fmpz(nmod_mat_t res, const nmod_mat_t M, const fmpz_t c); /* Matrix multiplication */ void nmod_mat_mul(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); int nmod_mat_mul_blas(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void nmod_mat_mul_classical(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void _nmod_mat_mul_classical_threaded_pool_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op, thread_pool_handle * threads, slong num_threads); void nmod_mat_mul_classical_threaded(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void nmod_mat_mul_strassen(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void _nmod_mat_mul_classical_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op); void nmod_mat_addmul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void nmod_mat_submul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); void nmod_mat_mul_nmod_vec(mp_limb_t * c, const nmod_mat_t A, const mp_limb_t * b, slong blen); void nmod_mat_mul_nmod_vec_ptr(mp_limb_t * const * c, const nmod_mat_t A, const mp_limb_t * const * b, slong blen); void nmod_mat_nmod_vec_mul(mp_limb_t * c, const mp_limb_t * a, slong alen, const nmod_mat_t B); void nmod_mat_nmod_vec_mul_ptr(mp_limb_t * const * c, const mp_limb_t * const * a, slong alen, const nmod_mat_t B); /* Exponent */ void _nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow); void nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow); /* Trace */ mp_limb_t nmod_mat_trace(const nmod_mat_t mat); /* Determinant */ mp_limb_t _nmod_mat_det(nmod_mat_t A); mp_limb_t nmod_mat_det(const nmod_mat_t A); mp_limb_t _nmod_mat_det_howell(nmod_mat_t A); mp_limb_t nmod_mat_det_howell(const nmod_mat_t A); /* Rank */ slong nmod_mat_rank(const nmod_mat_t A); /* Inverse */ int nmod_mat_inv(nmod_mat_t B, const nmod_mat_t A); /* Permutations */ NMOD_MAT_INLINE void nmod_mat_swap_rows(nmod_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !nmod_mat_is_empty(mat)) { if (perm) FLINT_SWAP(slong, perm[r], perm[s]); FLINT_SWAP(mp_ptr, mat->rows[r], mat->rows[s]); } } NMOD_MAT_INLINE void nmod_mat_invert_rows(nmod_mat_t mat, slong * perm) { slong i; for (i = 0; i < mat->r/2; i++) nmod_mat_swap_rows(mat, perm, i, mat->r - i - 1); } NMOD_MAT_INLINE void nmod_mat_swap_cols(nmod_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !nmod_mat_is_empty(mat)) { slong i; if (perm != NULL) FLINT_SWAP(slong, perm[r], perm[s]); for (i = 0; i < mat->r; i++) FLINT_SWAP(mp_limb_t, mat->rows[i][r], mat->rows[i][s]); } } NMOD_MAT_INLINE void nmod_mat_invert_cols(nmod_mat_t mat, slong * perm) { if (!nmod_mat_is_empty(mat)) { slong t, i; slong c = mat->c; slong k = mat->c/2; if (perm != NULL) for (i = 0; i < k; i++) FLINT_SWAP(slong, perm[i], perm[c - i - 1]); for (t = 0; t < mat->r; t++) for (i = 0; i < k; i++) FLINT_SWAP(mp_limb_t, mat->rows[t][i], mat->rows[t][c - i - 1]); } } void nmod_mat_permute_rows(nmod_mat_t mat, const slong * perm_act, slong * perm_store); /* Triangular solving */ void nmod_mat_solve_tril(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit); void nmod_mat_solve_tril_recursive(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit); void nmod_mat_solve_tril_classical(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit); void nmod_mat_solve_triu(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit); void nmod_mat_solve_triu_recursive(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit); void nmod_mat_solve_triu_classical(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit); /* LU decomposition */ slong nmod_mat_lu(slong * P, nmod_mat_t A, int rank_check); slong nmod_mat_lu_classical(slong * P, nmod_mat_t A, int rank_check); slong nmod_mat_lu_classical_delayed(slong * P, nmod_mat_t A, int rank_check); slong nmod_mat_lu_recursive(slong * P, nmod_mat_t A, int rank_check); /* Nonsingular solving */ int nmod_mat_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B); int nmod_mat_solve_vec(mp_ptr x, const nmod_mat_t A, mp_srcptr b); /* Solving */ int nmod_mat_can_solve_inner(slong * rank, slong * prm, slong * piv, nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B); int nmod_mat_can_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B); /* Reduced row echelon form */ slong nmod_mat_rref(nmod_mat_t A); slong _nmod_mat_rref(nmod_mat_t A, slong * pivots_nonpivots, slong * P); slong nmod_mat_rref_classical(nmod_mat_t A); slong _nmod_mat_rref_classical(nmod_mat_t A, slong * pivots_nonpivots); slong nmod_mat_rref_storjohann(nmod_mat_t A); slong _nmod_mat_rref_storjohann(nmod_mat_t A, slong * pivots_nonpivots); slong nmod_mat_reduce_row(nmod_mat_t M, slong * P, slong * L, slong m); /* Nullspace */ slong nmod_mat_nullspace(nmod_mat_t X, const nmod_mat_t A); /* Howell form */ void nmod_mat_strong_echelon_form(nmod_mat_t A); slong nmod_mat_howell_form(nmod_mat_t A); /* Transforms */ void nmod_mat_similarity(nmod_mat_t M, slong r, ulong d); /* Characteristic polynomial and minimal polynomial */ /* The following prototype actually lives in nmod_poly.h * * void nmod_mat_charpoly_danilevsky(nmod_poly_t p, const nmod_mat_t M); * * void nmod_mat_minpoly(nmod_poly_t p, const nmod_mat_t M); */ /* Tuning parameters *********************************************************/ /* Size at which pre-transposing becomes faster in classical multiplication */ #define NMOD_MAT_MUL_TRANSPOSE_CUTOFF 20 /* Cutoff between classical and recursive triangular solving */ #define NMOD_MAT_SOLVE_TRI_ROWS_CUTOFF 64 #define NMOD_MAT_SOLVE_TRI_COLS_CUTOFF 64 /* Suggested initial modulus size for multimodular algorithms. This should be chosen so that we get the most number of bits per cycle in matrix multiplication. On x86-64 it appears to be optimal to use moduli giving nlimbs = 2. This should hold both in the classical range and in Strassen blocks. */ #define NMOD_MAT_OPTIMAL_MODULUS_BITS (FLINT_BITS-5) /* Inlines *******************************************************************/ void nmod_mat_set_entry(nmod_mat_t mat, slong i, slong j, mp_limb_t x); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod_mat/000077500000000000000000000000001461254215100152205ustar00rootroot00000000000000flint-3.1.3/src/nmod_mat/add.c000066400000000000000000000012361461254215100161160ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_add(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong i; if (C->c == 0) return; for (i = 0; i < C->r; i++) { _nmod_vec_add(C->rows[i], A->rows[i], B->rows[i], C->c, C->mod); } } flint-3.1.3/src/nmod_mat/addmul.c000066400000000000000000000020141461254215100166270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_addmul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong m, k, n, cutoff; m = A->r; k = A->c; n = B->c; if (FLINT_BITS == 64 && C->mod.n < 2048) cutoff = 400; else cutoff = 200; if (flint_get_num_threads() == 1 && (m < cutoff || n < cutoff || k < cutoff)) { _nmod_mat_mul_classical_op(D, C, A, B, 1); } else { nmod_mat_t tmp; nmod_mat_init(tmp, m, n, A->mod.n); nmod_mat_mul(tmp, A, B); nmod_mat_add(D, C, tmp); nmod_mat_clear(tmp); } } flint-3.1.3/src/nmod_mat/can_solve.c000066400000000000000000000063471461254215100173470ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" int nmod_mat_can_solve_inner(slong * rank, slong * prm, slong * piv, nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B) { slong i, j, k, col, * pivots, * perm, rnk; nmod_mat_t LU, LU2, PB; int result = 1; if (rank == NULL) rank = & rnk; if (A->r != B->r || A->c != X->r || X->c != B->c) { *rank = 0; return 0; } if (A->r == 0 || B->c == 0) { nmod_mat_zero(X); *rank = 0; return 1; } if (A->c == 0) { nmod_mat_zero(X); *rank = 0; return nmod_mat_is_zero(B); } nmod_mat_init_set(LU, A); if (prm == NULL) { perm = flint_malloc(sizeof(slong)*A->r); for (i = 0; i < A->r; i++) perm[i] = i; } else perm = prm; *rank = nmod_mat_lu(perm, LU, 0); nmod_mat_window_init(PB, B, 0, 0, B->r, B->c); for (i = 0; i < B->r; i++) PB->rows[i] = B->rows[perm[i]]; nmod_mat_init(LU2, *rank, *rank, A->mod.n); if (piv == NULL) pivots = flint_malloc(sizeof(slong)*(*rank)); else pivots = piv; col = 0; for (i = 0; i < *rank; i++) { while (nmod_mat_entry(LU, i, col) == 0) col++; pivots[i] = col; for (j = 0; j < *rank; j++) nmod_mat_set_entry(LU2, j, i, nmod_mat_entry(LU, j, col)); col++; } X->r = *rank; PB->r = *rank; LU->r = *rank; nmod_mat_solve_tril(X, LU, PB, 1); LU->r = A->r; if (A->r > *rank) { nmod_mat_t P; LU->rows += *rank; LU->r = A->r - *rank; X->r = LU->c; nmod_mat_init(P, LU->r, B->c, A->mod.n); nmod_mat_mul(P, LU, X); PB->r = LU->r; PB->rows += *rank; result = nmod_mat_equal(P, PB); PB->rows -= *rank; nmod_mat_clear(P); LU->rows -= *rank; if (!result) { X->r = A->c; nmod_mat_zero(X); goto cleanup; } } nmod_mat_solve_triu(X, LU2, X, 0); X->r = A->c; k = (*rank) - 1; for (i = A->c - 1; i >= 0; i--) { if (k < 0 || i != pivots[k]) { for (j = 0; j < B->c; j++) nmod_mat_set_entry(X, i, j, 0); } else { for (j = 0; j < B->c; j++) nmod_mat_set_entry(X, i, j, nmod_mat_entry(X, k, j)); k--; } } cleanup: nmod_mat_clear(LU2); PB->r = B->r; nmod_mat_window_clear(PB); LU->r = A->r; nmod_mat_clear(LU); if (prm == NULL) flint_free(perm); if (piv == NULL) flint_free(pivots); return result; } int nmod_mat_can_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B) { return nmod_mat_can_solve_inner(NULL, NULL, NULL, X, A, B); } flint-3.1.3/src/nmod_mat/charpoly.c000066400000000000000000000154471461254215100172200ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" void _nmod_mat_charpoly_berkowitz(mp_ptr cp, const nmod_mat_t mat, nmod_t mod) { const slong n = mat->r; if (mod.n == 1) { _nmod_vec_zero(cp, n + 1); } else if (n == 0) { cp[0] = 1; } else if (n == 1) { cp[0] = nmod_neg(nmod_mat_entry(mat, 0, 0), mod); cp[1] = 1; } else if (n == 2) { cp[0] = nmod_sub(nmod_mul(nmod_mat_entry(mat, 0, 0), nmod_mat_entry(mat, 1, 1), mod), nmod_mul(nmod_mat_entry(mat, 0, 1), nmod_mat_entry(mat, 1, 0), mod), mod); cp[1] = nmod_add(nmod_mat_entry(mat, 0, 0), nmod_mat_entry(mat, 1, 1), mod); cp[1] = nmod_neg(cp[1], mod); cp[2] = 1; } else { slong i, k, t; mp_ptr a, A, s; int nlimbs; TMP_INIT; TMP_START; a = TMP_ALLOC(sizeof(mp_limb_t) * (n * n)); A = a + (n - 1) * n; nlimbs = _nmod_vec_dot_bound_limbs(n, mod); _nmod_vec_zero(cp, n + 1); cp[0] = nmod_neg(nmod_mat_entry(mat, 0, 0), mod); for (t = 1; t < n; t++) { for (i = 0; i <= t; i++) { a[0 * n + i] = nmod_mat_entry(mat, i, t); } A[0] = nmod_mat_entry(mat, t, t); for (k = 1; k < t; k++) { for (i = 0; i <= t; i++) { s = a + k * n + i; s[0] = _nmod_vec_dot(mat->rows[i], a + (k - 1) * n, t + 1, mod, nlimbs); } A[k] = a[k * n + t]; } A[t] = _nmod_vec_dot(mat->rows[t], a + (t - 1) * n, t + 1, mod, nlimbs); for (k = 0; k <= t; k++) { cp[k] = nmod_sub(cp[k], _nmod_vec_dot_rev(A, cp, k, mod, nlimbs), mod); cp[k] = nmod_sub(cp[k], A[k], mod); } } /* Shift all coefficients up by one */ for (i = n; i > 0; i--) cp[i] = cp[i - 1]; cp[0] = 1; _nmod_poly_reverse(cp, cp, n + 1, n + 1); TMP_END; } } void nmod_mat_charpoly_berkowitz(nmod_poly_t cp, const nmod_mat_t mat) { if (mat->r != mat->c) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_charpoly_berkowitz). Non-square matrix.\n"); } nmod_poly_fit_length(cp, mat->r + 1); _nmod_poly_set_length(cp, mat->r + 1); _nmod_mat_charpoly_berkowitz(cp->coeffs, mat, mat->mod); } void nmod_mat_charpoly_danilevsky(nmod_poly_t p, const nmod_mat_t M) { slong n = M->r, i, j, k; ulong ** A; ulong * V, * W, * T; ulong h; nmod_poly_t b; nmod_mat_t M2; int num_limbs; TMP_INIT; if (M->r != M->c) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_charpoly_danilevsky). Non-square matrix.\n"); } if (n == 0) { nmod_poly_one(p); return; } if (n == 1) { nmod_poly_set_coeff_ui(p, 1, 1); nmod_poly_set_coeff_ui(p, 0, n_negmod(M->rows[0][0], p->mod.n)); _nmod_poly_set_length(p, 2); return; } TMP_START; i = 1; num_limbs = _nmod_vec_dot_bound_limbs(n, p->mod); nmod_poly_one(p); nmod_poly_init(b, p->mod.n); nmod_mat_init_set(M2, M); V = (ulong *) TMP_ALLOC(n*sizeof(ulong)); W = (ulong *) TMP_ALLOC(n*sizeof(ulong)); T = (ulong *) TMP_ALLOC(n*sizeof(ulong)); A = M2->rows; while (i < n) { h = A[n - i][n - i - 1]; while (h == 0) { k = 1; while (k < n - i && A[n - i][n - i - k - 1] == 0) k++; if (k == n - i) { nmod_poly_fit_length(b, i + 1); nmod_poly_set_coeff_ui(b, i, 1); for (k = 1; k <= i; k++) nmod_poly_set_coeff_ui(b, k - 1, n_negmod(A[n - i][n - k], p->mod.n)); _nmod_poly_set_length(b, i + 1); nmod_poly_mul(p, p, b); n -= i; i = 1; if (n == 1) { nmod_poly_set_coeff_ui(b, 1, 1); nmod_poly_set_coeff_ui(b, 0, n_negmod(A[0][0], p->mod.n)); _nmod_poly_set_length(b, 2); nmod_poly_mul(p, p, b); goto cleanup; } } else { ulong * ptr; ulong t; ptr = A[n - i - k - 1]; A[n - i - k - 1] = A[n - i - 1]; A[n - i - 1] = ptr; for (j = 1; j <= n - i + 1; j++) { t = A[j - 1][n - i - k - 1]; A[j - 1][n - i - k - 1] = A[j - 1][n - i - 1]; A[j - 1][n - i - 1] = t; } } h = A[n - i][n - i - 1]; } h = n_invmod(n_negmod(h, p->mod.n), p->mod.n); for (j = 1; j <= n; j++) { V[j - 1] = n_mulmod2_preinv(A[n - i][j - 1], h, p->mod.n, p->mod.ninv); W[j - 1] = A[n - i][j - 1]; } h = n_negmod(h, p->mod.n); for (j = 1; j <= n - i; j++) { for (k = 1; k <= n - i - 1; k++) NMOD_ADDMUL(A[j - 1][k - 1], A[j - 1][n - i - 1], V[k - 1], p->mod); for (k = n - i + 1; k <= n; k++) NMOD_ADDMUL(A[j - 1][k - 1], A[j - 1][n - i - 1], V[k - 1], p->mod); A[j - 1][n - i - 1] = n_mulmod2_preinv(A[j - 1][n - i - 1], h, p->mod.n, p->mod.ninv); } for (j = 1; j <= n - i - 1; j++) { for (k = 1; k <= n - i; k++) T[k - 1] = A[k - 1][j - 1]; A[n - i - 1][j - 1] = _nmod_vec_dot(T, W, n - i, p->mod, num_limbs); } for (j = n - i; j <= n - 1; j++) { for (k = 1; k <= n - i; k++) T[k - 1] = A[k - 1][j - 1]; A[n - i - 1][j - 1] = n_addmod(_nmod_vec_dot(T, W, n - i, p->mod, num_limbs), W[j], p->mod.n); } for (k = 1; k <= n - i; k++) T[k - 1] = A[k - 1][j - 1]; A[n - i - 1][n - 1] = _nmod_vec_dot(T, W, n - i, p->mod, num_limbs); i++; } nmod_poly_fit_length(b, n + 1); nmod_poly_set_coeff_ui(b, n, 1); for (i = 1; i <= n; i++) nmod_poly_set_coeff_ui(b, i - 1, n_negmod(A[0][n - i], p->mod.n)); _nmod_poly_set_length(b, n + 1); nmod_poly_mul(p, p, b); cleanup: nmod_mat_clear(M2); nmod_poly_clear(b); TMP_END; } void nmod_mat_charpoly(nmod_poly_t cp, const nmod_mat_t mat) { if (mat->r <= 8 || !n_is_prime(mat->mod.n)) nmod_mat_charpoly_berkowitz(cp, mat); else nmod_mat_charpoly_danilevsky(cp, mat); } flint-3.1.3/src/nmod_mat/clear.c000066400000000000000000000011721461254215100164530ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_clear(nmod_mat_t mat) { if (mat->entries) { flint_free(mat->entries); flint_free(mat->rows); } else if (mat->r != 0) flint_free(mat->rows); } flint-3.1.3/src/nmod_mat/concat.c000066400000000000000000000021151461254215100166320ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_concat_horizontal(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2) { slong i; slong r = mat1->r; slong c1 = mat1->c; slong c2 = mat2->c; for (i = 0; i < r; i++) { flint_mpn_copyi(res->rows[i], mat1->rows[i], c1); flint_mpn_copyi(res->rows[i] + c1, mat2->rows[i], c2); } } void nmod_mat_concat_vertical(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2) { slong i; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; for (i = 0; i < r1; i++) flint_mpn_copyi(res->rows[i], mat1->rows[i], c1); for (i = 0; i < r2; i++) flint_mpn_copyi(res->rows[i + r1], mat2->rows[i], c1); } flint-3.1.3/src/nmod_mat/det.c000066400000000000000000000076071461254215100161520ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "perm.h" static mp_limb_t _nmod_mat_det_2x2(mp_limb_t a, mp_limb_t b, mp_limb_t c, mp_limb_t d, nmod_t mod) { b = nmod_neg(b, mod); return nmod_addmul(nmod_mul(a, d, mod), b, c, mod); } static mp_limb_t _nmod_mat_det_3x3(mp_limb_t a, mp_limb_t b, mp_limb_t c, mp_limb_t d, mp_limb_t e, mp_limb_t f, mp_limb_t g, mp_limb_t h, mp_limb_t i, nmod_t mod) { mp_limb_t s, t, u; s = _nmod_mat_det_2x2(e, f, h, i, mod); t = _nmod_mat_det_2x2(g, i, d, f, mod); u = _nmod_mat_det_2x2(d, e, g, h, mod); s = nmod_mul(a, s, mod); s = nmod_addmul(s, b, t, mod); s = nmod_addmul(s, c, u, mod); return s; } static mp_limb_t _nmod_mat_det_4x4(mp_limb_t ** const mat, nmod_t mod) { mp_limb_t s, t, u, v; s = _nmod_mat_det_3x3(mat[1][1], mat[1][2], mat[1][3], mat[2][1], mat[2][2], mat[2][3], mat[3][1], mat[3][2], mat[3][3], mod); t = _nmod_mat_det_3x3(mat[1][0], mat[1][2], mat[1][3], mat[2][0], mat[2][2], mat[2][3], mat[3][0], mat[3][2], mat[3][3], mod); u = _nmod_mat_det_3x3(mat[1][0], mat[1][1], mat[1][3], mat[2][0], mat[2][1], mat[2][3], mat[3][0], mat[3][1], mat[3][3], mod); v = _nmod_mat_det_3x3(mat[1][0], mat[1][1], mat[1][2], mat[2][0], mat[2][1], mat[2][2], mat[3][0], mat[3][1], mat[3][2], mod); t = nmod_neg(t, mod); v = nmod_neg(v, mod); s = nmod_mul(mat[0][0], s, mod); s = nmod_addmul(s, mat[0][1], t, mod); s = nmod_addmul(s, mat[0][2], u, mod); s = nmod_addmul(s, mat[0][3], v, mod); return s; } mp_limb_t _nmod_mat_det(nmod_mat_t A) { mp_limb_t det; slong * P; slong m = A->r; slong rank; slong i; P = flint_malloc(sizeof(slong) * m); rank = nmod_mat_lu(P, A, 1); det = UWORD(0); if (rank == m) { det = UWORD(1); for (i = 0; i < m; i++) det = n_mulmod2_preinv(det, nmod_mat_entry(A, i, i), A->mod.n, A->mod.ninv); } if (_perm_parity(P, m) == 1) det = nmod_neg(det, A->mod); flint_free(P); return det; } mp_limb_t nmod_mat_det(const nmod_mat_t A) { nmod_mat_t tmp; mp_limb_t det; slong dim = A->r; if (dim != A->c) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_det). Non-square matrix.\n"); } if (dim == 0) return A->mod.n != 1; if (dim == 1) return nmod_mat_entry(A, 0, 0); if (dim == 2) return _nmod_mat_det_2x2( nmod_mat_entry(A, 0, 0), nmod_mat_entry(A, 0, 1), nmod_mat_entry(A, 1, 0), nmod_mat_entry(A, 1, 1), A->mod); if (dim == 3) return _nmod_mat_det_3x3( nmod_mat_entry(A, 0, 0), nmod_mat_entry(A, 0, 1), nmod_mat_entry(A, 0, 2), nmod_mat_entry(A, 1, 0), nmod_mat_entry(A, 1, 1), nmod_mat_entry(A, 1, 2), nmod_mat_entry(A, 2, 0), nmod_mat_entry(A, 2, 1), nmod_mat_entry(A, 2, 2), A->mod); if (dim == 4) return _nmod_mat_det_4x4(A->rows, A->mod); if (dim <= 8) { mp_limb_t cp[9]; _nmod_mat_charpoly_berkowitz(cp, A, A->mod); if (dim % 2) return nmod_neg(cp[0], A->mod); else return cp[0]; } nmod_mat_init_set(tmp, A); if (n_is_prime(A->mod.n)) det = _nmod_mat_det(tmp); else det = _nmod_mat_det_howell(tmp); nmod_mat_clear(tmp); return det; } flint-3.1.3/src/nmod_mat/det_howell.c000066400000000000000000000101251461254215100175110ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" /* We do no quite need the full Howell form. We just need to reduce to upper triangular form using row swaps and Euclidean row operations (i.e. that use the Euclidean xgcd to replace the pivot with its gcd with the entry in the row in question (mod n). Of course we need a special version of the Euclidean xgcd whose first cofactor is a unit mod n. */ /* Find s, t such that g = s*a - t*b is the gcd of a and b mod n and where s is a unit mod n. Assumes a and b are reduced mod n and no aliasing. */ static inline mp_limb_t _nmod_xgcd_unit(mp_limb_t * s, mp_limb_t * t, mp_limb_t a, mp_limb_t b, nmod_t mod) { mp_limb_t g, ag, bg; if (a >= b) g = n_xgcd(s, t, a, b); else /* b > a */ { g = n_xgcd(t, s, b, a); *s = nmod_neg(*s, mod); *t = nmod_neg(*t, mod); } ag = a/g; bg = b/g; while (n_gcd(*s, mod.n) != 1) { *s = nmod_add(*s, bg, mod); *t = nmod_add(*t, ag, mod); } return g; } static inline int _nmod_mat_pivot(nmod_mat_t A, slong start_row, slong col) { slong j; mp_ptr u; if (nmod_mat_entry(A, start_row, col) != 0) return 1; for (j = start_row + 1; j < A->r; j++) { if (nmod_mat_entry(A, j, col) != 0) { u = A->rows[j]; A->rows[j] = A->rows[start_row]; A->rows[start_row] = u; return -1; } } return 0; } /* test whether q*a = b mod N has a solution */ static int _n_is_divisible(mp_ptr q, mp_limb_t b, mp_limb_t a, nmod_t N) { mp_limb_t e, g; g = n_gcdinv(&e, a, N.n); if (( b % g ) == 0) { *q = nmod_mul(e, b/g, N); return 1; } return 0; } mp_limb_t _nmod_mat_det_howell(nmod_mat_t A) { mp_limb_t s, t, t1, det = 1, unit = 1; slong m, n, row, col, i, k; nmod_t mod = A->mod; if (nmod_mat_is_empty(A)) return mod.n != 1; n = A->r; m = A->c; row = col = 0; while (row < n && col < m) { int pivswap = _nmod_mat_pivot(A, row, col); if (pivswap == 0) return 0; if (pivswap == -1) det = nmod_neg(det, mod); for (i = row + 1; i < n; i++) { if (nmod_mat_entry(A, i, col) == 0) continue; if (_n_is_divisible(&s, nmod_mat_entry(A, i, col), nmod_mat_entry(A, row, col), mod)) { for (k = col; k < m; k++) { t = nmod_sub(nmod_mat_entry(A, i, k), nmod_mul(s, nmod_mat_entry(A, row, k), mod), mod); nmod_mat_entry(A, i, k) = t; } } else { _nmod_xgcd_unit(&s, &t, nmod_mat_entry(A, row, col), nmod_mat_entry(A, i, col), mod); /* now g = s*x - t*y mod n */ unit = nmod_mul(unit, s, mod); for (k = col; k < m; k++) { t1 = nmod_sub(nmod_mul(s, nmod_mat_entry(A, row, k), mod), nmod_mul(t, nmod_mat_entry(A, i, k), mod), mod); nmod_mat_entry(A, row, k) = t1; } /* now it's divisible, restart this row */ i--; continue; } } det = nmod_mul(det, nmod_mat_entry(A, row, col), mod); row++; col++; } unit = nmod_inv(unit, mod); return nmod_mul(det, unit, mod); } mp_limb_t nmod_mat_det_howell(const nmod_mat_t A) { nmod_mat_t tmp; mp_limb_t det; slong dim = A->r; if (dim != A->c) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_det_howell). Non-square matrix.\n"); } nmod_mat_init_set(tmp, A); det = _nmod_mat_det_howell(tmp); nmod_mat_clear(tmp); return det; } flint-3.1.3/src/nmod_mat/equal.c000066400000000000000000000016431461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" int nmod_mat_equal(const nmod_mat_t mat1, const nmod_mat_t mat2) { slong i, j; if (mat1->r != mat2->r || mat1->c != mat2->c) return 0; if (mat1->r == 0 || mat1->c == 0) return 1; for (i = 0; i < mat1->r; i++) { for (j = 0; j < mat1->c; j++) { if (mat1->rows[i][j] != mat2->rows[i][j]) return 0; } /* if (!_nmod_vec_equal(mat1->rows[i], mat2->rows[i], mat1->c)) return 0; */ } return 1; } flint-3.1.3/src/nmod_mat/howell_form.c000066400000000000000000000017301461254215100177020ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" slong nmod_mat_howell_form(nmod_mat_t A) { slong i, j, n; slong k; n = A->r; k = n; if (nmod_mat_is_empty(A)) return 0; nmod_mat_strong_echelon_form(A); for (i = 0; i < n; i++) { if (nmod_mat_is_zero_row(A, i)) { k--; for (j = i + 1; j < n; j++) { if (!nmod_mat_is_zero_row(A, j)) { nmod_mat_swap_rows(A, NULL, i, j); j = n; k++; } } } } return k; } flint-3.1.3/src/nmod_mat/init.c000066400000000000000000000035471461254215100163400ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010, 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_init(nmod_mat_t mat, slong rows, slong cols, mp_limb_t n) { slong i; if (rows != 0) mat->rows = (mp_limb_t **) flint_malloc(rows * sizeof(mp_limb_t *)); else mat->rows = NULL; if (rows != 0 && cols != 0) { mat->entries = (mp_limb_t *) flint_calloc(flint_mul_sizes(rows, cols), sizeof(mp_limb_t)); for (i = 0; i < rows; i++) mat->rows[i] = mat->entries + i * cols; } else { mat->entries = NULL; if (rows != 0) { for (i = 0; i < rows; i++) mat->rows[i] = NULL; } } mat->r = rows; mat->c = cols; nmod_mat_set_mod(mat, n); } void nmod_mat_init_set(nmod_mat_t mat, const nmod_mat_t src) { slong rows = src->r; slong cols = src->c; slong i; if (rows != 0) mat->rows = flint_malloc(rows * sizeof(mp_limb_t *)); else mat->rows = NULL; if ((rows) && (cols)) { mat->entries = flint_malloc(flint_mul_sizes(rows, cols) * sizeof(mp_limb_t)); for (i = 0; i < rows; i++) { mat->rows[i] = mat->entries + i * cols; flint_mpn_copyi(mat->rows[i], src->rows[i], cols); } } else { mat->entries = NULL; if (rows != 0) { for (i = 0; i < rows; i++) mat->rows[i] = NULL; } } mat->r = rows; mat->c = cols; mat->mod = src->mod; } flint-3.1.3/src/nmod_mat/inlines.c000066400000000000000000000010761461254215100170310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_MAT_INLINES_C #include "nmod_mat.h" void nmod_mat_set_entry(nmod_mat_t mat, slong i, slong j, mp_limb_t x) { nmod_mat_entry(mat, i, j) = x; } flint-3.1.3/src/nmod_mat/inv.c000066400000000000000000000023111461254215100161550ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" int nmod_mat_inv(nmod_mat_t B, const nmod_mat_t A) { nmod_mat_t I; slong i, dim; int result; dim = A->r; switch (dim) { case 0: result = 1; break; case 1: if (nmod_mat_entry(A, 0, 0) == UWORD(0)) { result = 0; } else { nmod_mat_entry(B, 0, 0) = n_invmod(nmod_mat_entry(A, 0, 0), B->mod.n); result = 1; } break; default: nmod_mat_init(I, dim, dim, B->mod.n); for (i = 0; i < dim; i++) nmod_mat_entry(I, i, i) = UWORD(1); result = nmod_mat_solve(B, A, I); nmod_mat_clear(I); } return result; } flint-3.1.3/src/nmod_mat/io.c000066400000000000000000000033571461254215100160030ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_mat.h" int nmod_mat_fprint_pretty(FILE * file, const nmod_mat_t mat) { slong i, j; int z, width; char fmt[FLINT_BITS + 5]; z = flint_fprintf(file, "<%wd x %wd integer matrix mod %wu>\n", mat->r, mat->c, mat->mod.n); if (z <= 0) return z; if (!(mat->c) || !(mat->r)) return z; width = n_sizeinbase(mat->mod.n, 10); z = flint_sprintf(fmt, "%%%dwu", width); if (z <= 0) return z; for (i = 0; i < mat->r; i++) { z = flint_printf("["); if (z <= 0) return z; for (j = 0; j < mat->c; j++) { z = flint_printf(fmt, mat->rows[i][j]); if (z <= 0) return z; if (j + 1 < mat->c) { z = flint_printf(" "); if (z <= 0) return z; } } flint_printf("]\n"); if (z <= 0) return z; } return z; } void nmod_mat_print_pretty(const nmod_mat_t mat) { nmod_mat_fprint_pretty(stdout, mat); } int nmod_mat_print(const nmod_mat_t mat) { return nmod_mat_fprint_pretty(stdout, mat); } int nmod_mat_fprint(FILE * f, const nmod_mat_t mat) { return nmod_mat_fprint_pretty(f, mat); } flint-3.1.3/src/nmod_mat/is_one.c000066400000000000000000000016201461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" int nmod_mat_is_one(const nmod_mat_t mat) { slong i; if (mat->mod.n == 0 || mat->r == 0 || mat->c == 0) return 1; for (i = 0; i < mat->r; i++) { if (!_nmod_vec_is_zero(mat->rows[i], FLINT_MIN(mat->c, i))) return 0; if (i + 1 > mat->c) continue; if (mat->rows[i][i] != 1) return 0; if (!_nmod_vec_is_zero(mat->rows[i] + i + 1, mat->c - (i + 1))) return 0; } return 1; } flint-3.1.3/src/nmod_mat/is_zero.c000066400000000000000000000012501461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" int nmod_mat_is_zero(const nmod_mat_t mat) { slong j; if (mat->r == 0 || mat->c == 0) return 1; for (j = 0; j < mat->r; j++) { if (!_nmod_vec_is_zero(mat->rows[j], mat->c)) return 0; } return 1; } flint-3.1.3/src/nmod_mat/is_zero_row.c000066400000000000000000000010311461254215100177200ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" int nmod_mat_is_zero_row(const nmod_mat_t mat, slong i) { return _nmod_vec_is_zero(mat->rows[i], mat->c); } flint-3.1.3/src/nmod_mat/lu.c000066400000000000000000000027011461254215100160040ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" slong nmod_mat_lu(slong * P, nmod_mat_t A, int rank_check) { slong nrows, ncols, n, cutoff; int nlimbs, bits; nrows = A->r; ncols = A->c; n = FLINT_MIN(nrows, ncols); if (n <= 3) { return nmod_mat_lu_classical(P, A, rank_check); } else { if (n >= 20) { bits = NMOD_BITS(A->mod); if (bits >= FLINT_BITS - 1) cutoff = 80; else if (bits >= FLINT_BITS / 2 - 2) cutoff = 60; else if (bits >= FLINT_BITS / 4 - 1) cutoff = 180; else cutoff = 60; if (n >= cutoff) return nmod_mat_lu_recursive(P, A, rank_check); } nlimbs = _nmod_vec_dot_bound_limbs(n, A->mod); if (nlimbs <= 1 || (nlimbs == 2 && n >= 12) || (nlimbs == 3 && n >= 20)) return nmod_mat_lu_classical_delayed(P, A, rank_check); else return nmod_mat_lu_classical(P, A, rank_check); } } flint-3.1.3/src/nmod_mat/lu_classical.c000066400000000000000000000036561461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" static inline int nmod_mat_pivot(nmod_mat_t A, slong * P, slong start_row, slong col) { slong j, t; mp_ptr u; if (nmod_mat_entry(A, start_row, col) != 0) return 1; for (j = start_row + 1; j < A->r; j++) { if (nmod_mat_entry(A, j, col) != 0) { u = A->rows[j]; A->rows[j] = A->rows[start_row]; A->rows[start_row] = u; t = P[j]; P[j] = P[start_row]; P[start_row] = t; return -1; } } return 0; } slong nmod_mat_lu_classical(slong * P, nmod_mat_t A, int rank_check) { mp_limb_t d, e, **a; nmod_t mod; slong i, m, n, rank, length, row, col; m = A->r; n = A->c; a = A->rows; mod = A->mod; rank = row = col = 0; for (i = 0; i < m; i++) P[i] = i; while (row < m && col < n) { if (nmod_mat_pivot(A, P, row, col) == 0) { if (rank_check) return 0; col++; continue; } rank++; d = a[row][col]; d = nmod_inv(d, mod); length = n - col - 1; for (i = row + 1; i < m; i++) { e = nmod_mul(a[i][col], d, mod); if (length != 0) _nmod_vec_scalar_addmul_nmod(a[i] + col + 1, a[row] + col + 1, length, nmod_neg(e, mod), mod); a[i][col] = 0; a[i][rank - 1] = e; } row++; col++; } return rank; } flint-3.1.3/src/nmod_mat/lu_classical_delayed.c000066400000000000000000000305371461254215100215210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" static mp_limb_t nmod_set_uiuiui(ulong s2, ulong s1, ulong s0, nmod_t mod) { NMOD_RED(s2, s2, mod); NMOD_RED3(s0, s2, s1, s0, mod); return s0; } slong nmod_mat_lu_classical_delayed_1(slong * P, nmod_mat_t A, int rank_check) { mp_limb_t d, e, f, **a; nmod_t mod; slong i, j, nrows, ncols, rank, row, col, pivot_row, tmp_index; mp_ptr tmp_ptr; nrows = A->r; ncols = A->c; a = A->rows; mod = A->mod; rank = row = col = 0; for (i = 0; i < nrows; i++) P[i] = i; while (row < nrows && col < ncols) { /* reduce current column */ /* can be skipped on the first iteration */ if (col != 0) for (j = row; j < nrows; j++) NMOD_RED(a[j][col], a[j][col], mod); pivot_row = -1; for (i = row; i < nrows; i++) { if (a[i][col] != 0) { pivot_row = i; break; } } if (pivot_row == -1) { if (rank_check) { rank = 0; break; } col++; continue; } /* swap rows */ if (pivot_row != row) { tmp_ptr = a[pivot_row]; a[pivot_row] = a[row]; a[row] = tmp_ptr; tmp_index = P[pivot_row]; P[pivot_row] = P[row]; P[row] = tmp_index; } /* reduce current pivot row */ if (col != 0) for (j = col + 1; j < ncols; j++) NMOD_RED(a[row][j], a[row][j], mod); rank++; /* eliminate remaining submatrix */ d = nmod_inv(a[row][col], mod); for (i = row + 1; i < nrows; i++) { e = nmod_mul(a[i][col], d, mod); f = nmod_neg(e, mod); for (j = col + 1; j + 4 < ncols; j += 4) { mp_limb_t x0, x1, x2, x3; x0 = a[row][j + 0]; x1 = a[row][j + 1]; x2 = a[row][j + 2]; x3 = a[row][j + 3]; a[i][j + 0] += x0 * f; a[i][j + 1] += x1 * f; a[i][j + 2] += x2 * f; a[i][j + 3] += x3 * f; } for ( ; j < ncols; j++) a[i][j] += a[row][j] * f; a[i][col] = 0; a[i][rank - 1] = e; } row++; col++; } return rank; } slong nmod_mat_lu_classical_delayed_2(slong * P, nmod_mat_t A, int rank_check) { mp_limb_t d, e, f, **a; nmod_t mod; slong i, j, nrows, ncols, rank, row, col, pivot_row, tmp_index; mp_ptr tmp_ptr; mp_ptr b; TMP_INIT; nrows = A->r; ncols = A->c; a = A->rows; mod = A->mod; rank = row = col = 0; for (i = 0; i < nrows; i++) P[i] = i; TMP_START; b = TMP_ALLOC(2 * sizeof(mp_limb_t) * nrows * ncols); #define UNREDUCED_LO(ii, jj) b[2 * ((ii) * ncols + jj)] #define UNREDUCED_HI(ii, jj) b[2 * ((ii) * ncols + jj) + 1] for (i = 0; i < nrows; i++) { for (j = 0; j < ncols; j++) { UNREDUCED_LO(i, j) = a[i][j]; UNREDUCED_HI(i, j) = 0; } } while (row < nrows && col < ncols) { /* reduce current column */ /* can be skipped on the first iteration */ if (col != 0) for (j = row; j < nrows; j++) NMOD2_RED2(a[j][col], UNREDUCED_HI(j, col), UNREDUCED_LO(j, col), mod); pivot_row = -1; for (i = row; i < nrows; i++) { if (a[i][col] != 0) { pivot_row = i; break; } } if (pivot_row == -1) { if (rank_check) { rank = 0; break; } col++; continue; } /* swap rows */ if (pivot_row != row) { tmp_ptr = a[pivot_row]; a[pivot_row] = a[row]; a[row] = tmp_ptr; tmp_index = P[pivot_row]; P[pivot_row] = P[row]; P[row] = tmp_index; /* swap rows in unreduced submatrix, and reduce new pivot row */ for (j = col + 1; j < ncols; j++) { mp_limb_t hi, lo; lo = UNREDUCED_LO(row, j); hi = UNREDUCED_HI(row, j); NMOD2_RED2(a[row][j], UNREDUCED_HI(pivot_row, j), UNREDUCED_LO(pivot_row, j), mod); UNREDUCED_LO(pivot_row, j) = lo; UNREDUCED_HI(pivot_row, j) = hi; } } else if (row != 0) { /* reduce current pivot row */ for (j = col + 1; j < ncols; j++) NMOD2_RED2(a[row][j], UNREDUCED_HI(row, j), UNREDUCED_LO(row, j), mod); } rank++; /* eliminate remaining submatrix */ d = nmod_inv(a[row][col], mod); for (i = row + 1; i < nrows; i++) { e = nmod_mul(a[i][col], d, mod); f = nmod_neg(e, mod); if (mod.n <= UWORD(1) << (FLINT_BITS / 2)) { for (j = col + 1; j + 4 < ncols; j += 4) { mp_limb_t x0, x1, x2, x3; x0 = a[row][j + 0] * f; x1 = a[row][j + 1] * f; x2 = a[row][j + 2] * f; x3 = a[row][j + 3] * f; add_ssaaaa(UNREDUCED_HI(i, j + 0), UNREDUCED_LO(i, j + 0), UNREDUCED_HI(i, j + 0), UNREDUCED_LO(i, j + 0), 0, x0); add_ssaaaa(UNREDUCED_HI(i, j + 1), UNREDUCED_LO(i, j + 1), UNREDUCED_HI(i, j + 1), UNREDUCED_LO(i, j + 1), 0, x1); add_ssaaaa(UNREDUCED_HI(i, j + 2), UNREDUCED_LO(i, j + 2), UNREDUCED_HI(i, j + 2), UNREDUCED_LO(i, j + 2), 0, x2); add_ssaaaa(UNREDUCED_HI(i, j + 3), UNREDUCED_LO(i, j + 3), UNREDUCED_HI(i, j + 3), UNREDUCED_LO(i, j + 3), 0, x3); } for ( ; j < ncols; j++) { mp_limb_t hi, lo; hi = 0; lo = a[row][j] * f; add_ssaaaa(UNREDUCED_HI(i, j), UNREDUCED_LO(i, j), UNREDUCED_HI(i, j), UNREDUCED_LO(i, j), hi, lo); } } else { for (j = col + 1; j + 4 < ncols; j += 4) { mp_limb_t x0, x1, x2, x3, h0, h1, h2, h3; umul_ppmm(h0, x0, a[row][j + 0], f); umul_ppmm(h1, x1, a[row][j + 1], f); umul_ppmm(h2, x2, a[row][j + 2], f); umul_ppmm(h3, x3, a[row][j + 3], f); add_ssaaaa(UNREDUCED_HI(i, j + 0), UNREDUCED_LO(i, j + 0), UNREDUCED_HI(i, j + 0), UNREDUCED_LO(i, j + 0), h0, x0); add_ssaaaa(UNREDUCED_HI(i, j + 1), UNREDUCED_LO(i, j + 1), UNREDUCED_HI(i, j + 1), UNREDUCED_LO(i, j + 1), h1, x1); add_ssaaaa(UNREDUCED_HI(i, j + 2), UNREDUCED_LO(i, j + 2), UNREDUCED_HI(i, j + 2), UNREDUCED_LO(i, j + 2), h2, x2); add_ssaaaa(UNREDUCED_HI(i, j + 3), UNREDUCED_LO(i, j + 3), UNREDUCED_HI(i, j + 3), UNREDUCED_LO(i, j + 3), h3, x3); } for ( ; j < ncols; j++) { mp_limb_t hi, lo; umul_ppmm(hi, lo, a[row][j], f); add_ssaaaa(UNREDUCED_HI(i, j), UNREDUCED_LO(i, j), UNREDUCED_HI(i, j), UNREDUCED_LO(i, j), hi, lo); } } a[i][col] = 0; a[i][rank - 1] = e; } row++; col++; } TMP_END; return rank; } slong nmod_mat_lu_classical_delayed_3(slong * P, nmod_mat_t A, int rank_check) { mp_limb_t d, e, f, **a; nmod_t mod; slong i, j, nrows, ncols, rank, row, col, pivot_row, tmp_index; mp_ptr tmp_ptr; mp_ptr b; TMP_INIT; nrows = A->r; ncols = A->c; a = A->rows; mod = A->mod; rank = row = col = 0; for (i = 0; i < nrows; i++) P[i] = i; TMP_START; b = TMP_ALLOC(3 * sizeof(mp_limb_t) * nrows * ncols); #define UNREDUCED3_L0(ii, jj) b[3 * ((ii) * ncols + jj)] #define UNREDUCED3_L1(ii, jj) b[3 * ((ii) * ncols + jj) + 1] #define UNREDUCED3_L2(ii, jj) b[3 * ((ii) * ncols + jj) + 2] for (i = 0; i < nrows; i++) { for (j = 0; j < ncols; j++) { UNREDUCED3_L0(i, j) = a[i][j]; UNREDUCED3_L1(i, j) = 0; UNREDUCED3_L2(i, j) = 0; } } while (row < nrows && col < ncols) { /* reduce current column */ /* can be skipped on the first iteration */ if (col != 0) for (j = row; j < nrows; j++) a[j][col] = nmod_set_uiuiui(UNREDUCED3_L2(j, col), UNREDUCED3_L1(j, col), UNREDUCED3_L0(j, col), mod); pivot_row = -1; for (i = row; i < nrows; i++) { if (a[i][col] != 0) { pivot_row = i; break; } } if (pivot_row == -1) { if (rank_check) { rank = 0; break; } col++; continue; } /* swap rows */ if (pivot_row != row) { tmp_ptr = a[pivot_row]; a[pivot_row] = a[row]; a[row] = tmp_ptr; tmp_index = P[pivot_row]; P[pivot_row] = P[row]; P[row] = tmp_index; /* swap rows in unreduced submatrix, and reduce new pivot row */ for (j = col + 1; j < ncols; j++) { mp_limb_t t2, t1, t0; t0 = UNREDUCED3_L0(row, j); t1 = UNREDUCED3_L1(row, j); t2 = UNREDUCED3_L2(row, j); a[row][j] = nmod_set_uiuiui(UNREDUCED3_L2(pivot_row, j), UNREDUCED3_L1(pivot_row, j), UNREDUCED3_L0(pivot_row, j), mod); UNREDUCED3_L0(pivot_row, j) = t0; UNREDUCED3_L1(pivot_row, j) = t1; UNREDUCED3_L2(pivot_row, j) = t2; } } else if (row != 0) { /* reduce current pivot row */ for (j = col + 1; j < ncols; j++) a[row][j] = nmod_set_uiuiui(UNREDUCED3_L2(row, j), UNREDUCED3_L1(row, j), UNREDUCED3_L0(row, j), mod); } rank++; /* eliminate remaining submatrix */ d = nmod_inv(a[row][col], mod); for (i = row + 1; i < nrows; i++) { e = nmod_mul(a[i][col], d, mod); f = nmod_neg(e, mod); for (j = col + 1; j < ncols; j++) { mp_limb_t hi, lo; umul_ppmm(hi, lo, a[row][j], f); add_sssaaaaaa(UNREDUCED3_L2(i, j), UNREDUCED3_L1(i, j), UNREDUCED3_L0(i, j), UNREDUCED3_L2(i, j), UNREDUCED3_L1(i, j), UNREDUCED3_L0(i, j), 0, hi, lo); } a[i][col] = 0; a[i][rank - 1] = e; } row++; col++; } TMP_END; return rank; } slong nmod_mat_lu_classical_delayed(slong * P, nmod_mat_t A, int rank_check) { slong nrows, ncols; int nlimbs; nrows = A->r; ncols = A->c; nlimbs = _nmod_vec_dot_bound_limbs(FLINT_MIN(nrows, ncols), A->mod); if (nlimbs <= 1) return nmod_mat_lu_classical_delayed_1(P, A, rank_check); else if (nlimbs <= 2) return nmod_mat_lu_classical_delayed_2(P, A, rank_check); else return nmod_mat_lu_classical_delayed_3(P, A, rank_check); } flint-3.1.3/src/nmod_mat/lu_recursive.c000066400000000000000000000054001461254215100200720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" static void _apply_permutation(slong * AP, nmod_mat_t A, slong * P, slong n, slong offset) { if (n != 0) { mp_ptr * Atmp; slong * APtmp; slong i; Atmp = flint_malloc(sizeof(mp_ptr) * n); APtmp = flint_malloc(sizeof(slong) * n); for (i = 0; i < n; i++) Atmp[i] = A->rows[P[i] + offset]; for (i = 0; i < n; i++) A->rows[i + offset] = Atmp[i]; for (i = 0; i < n; i++) APtmp[i] = AP[P[i] + offset]; for (i = 0; i < n; i++) AP[i + offset] = APtmp[i]; flint_free(Atmp); flint_free(APtmp); } } slong nmod_mat_lu_recursive(slong * P, nmod_mat_t A, int rank_check) { slong i, j, m, n, r1, r2, n1; nmod_mat_t A0, A00, A01, A10, A11; slong * P1; m = A->r; n = A->c; /* main cutoffs are in nmod_mat_lu */ if (m <= 1 || n <= 1) { r1 = nmod_mat_lu_classical(P, A, rank_check); return r1; } n1 = n / 2; for (i = 0; i < m; i++) P[i] = i; P1 = flint_malloc(sizeof(slong) * m); nmod_mat_window_init(A0, A, 0, 0, m, n1); r1 = nmod_mat_lu(P1, A0, rank_check); if (rank_check && (r1 != n1)) { flint_free(P1); nmod_mat_window_clear(A0); return 0; } if (r1 != 0) { _apply_permutation(P, A, P1, m, 0); } nmod_mat_window_init(A00, A, 0, 0, r1, r1); nmod_mat_window_init(A10, A, r1, 0, m, r1); nmod_mat_window_init(A01, A, 0, n1, r1, n); nmod_mat_window_init(A11, A, r1, n1, m, n); if (r1 != 0) { nmod_mat_solve_tril(A01, A00, A01, 1); nmod_mat_submul(A11, A11, A10, A01); } r2 = nmod_mat_lu(P1, A11, rank_check); if (rank_check && (r1 + r2 < FLINT_MIN(m, n))) { r1 = r2 = 0; } else { _apply_permutation(P, A, P1, m - r1, r1); /* Compress L */ if (r1 != n1) { for (i = 0; i < m - r1; i++) { mp_ptr row = A->rows[r1 + i]; for (j = 0; j < FLINT_MIN(i, r2); j++) { row[r1 + j] = row[n1 + j]; row[n1 + j] = 0; } } } } flint_free(P1); nmod_mat_window_clear(A00); nmod_mat_window_clear(A01); nmod_mat_window_clear(A10); nmod_mat_window_clear(A11); nmod_mat_window_clear(A0); return r1 + r2; } flint-3.1.3/src/nmod_mat/minpoly.c000066400000000000000000000077531461254215100170670ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" void nmod_mat_minpoly_with_gens(nmod_poly_t p, const nmod_mat_t X, ulong * P) { slong n = X->r, i, j, c, c1, c2, r1, r2; ulong ** A, ** B, ** v, t, h; slong * P1, * P2, * L1, * L2; nmod_mat_t matA, matB, matv; int first_poly = 1, indep = 1; nmod_poly_t b, g; TMP_INIT; if (X->r != X->c) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_charpoly). Non-square matrix.\n"); } if (n == 0) { nmod_poly_one(p); return; } if (n == 1) { nmod_poly_set_coeff_ui(p, 1, 1); nmod_poly_set_coeff_ui(p, 0, n_negmod(X->rows[0][0], p->mod.n)); _nmod_poly_set_length(p, 2); if (P != NULL) P[0] = 1; return; } TMP_START; nmod_poly_init(b, p->mod.n); nmod_poly_init(g, p->mod.n); nmod_poly_one(p); nmod_mat_init(matA, n + 1, 2*n + 1, p->mod.n); nmod_mat_init(matB, n, n, p->mod.n); nmod_mat_init(matv, n, 1, p->mod.n); A = matA->rows; B = matB->rows; v = matv->rows; L1 = (slong *) TMP_ALLOC((n + 1)*sizeof(slong)); L2 = (slong *) TMP_ALLOC(n*sizeof(slong)); P1 = (slong *) TMP_ALLOC((2*n + 1)*sizeof(slong)); P2 = (slong *) TMP_ALLOC(n*sizeof(slong)); for (i = 1; i <= n + 1; i++) L1[i - 1] = n + i; for (i = 1; i <= n; i++) L2[i - 1] = n; for (i = 1; i < n; i++) P2[i] = -WORD(1); P2[0] = 0; r2 = c2 = 0; first_poly = 1; while (r2 < n) { for (i = 0; i < 2*n + 1; i++) P1[i] = -WORD(1); for (i = 0; i < n; i++) { v[i][0] = 0; B[r2][i] = 0; A[0][i] = 0; } P1[c2] = 0; P2[c2] = r2; v[c2][0] = 1; B[r2][c2] = 1; A[0][c2] = 1; A[0][n] = 1; if (P != NULL) P[c2] = 1; indep = 1; r1 = 0; c1 = -WORD(1); while (c1 < n && r1 < n) { r1++; r2 = indep ? r2 + 1 : r2; nmod_mat_mul(matv, X, matv); v = matv->rows; for (i = 0; i < n; i++) A[r1][i] = v[i][0]; for (i = n; i < n + r1; i++) A[r1][i] = 0; A[r1][n + r1] = 1; c1 = nmod_mat_reduce_row(matA, P1, L1, r1); if (indep && r2 < n && !first_poly) { for (i = 0; i < n; i++) B[r2][i] = v[i][0]; c = nmod_mat_reduce_row(matB, P2, L2, r2); indep = c != -WORD(1); } } if (first_poly) { for (i = 0; i < n; i++) P2[i] = P1[i]; r2 = r1; } c = -WORD(1); for (i = c2 + 1; i < n; i++) { if (P2[i] == -WORD(1)) { c = i; break; } } c2 = c; nmod_poly_fit_length(b, r1 + 1); h = n_invmod(A[r1][n + r1], p->mod.n); for (i = 0; i < r1 + 1; i++) { t = n_mulmod2_preinv(A[r1][n + i], h, p->mod.n, p->mod.ninv); nmod_poly_set_coeff_ui(b, i, t); } _nmod_poly_set_length(b, r1 + 1); nmod_poly_gcd(g, p, b); /* todo: compute as (p * b) / g or (p / g) * b or p * (g / b) ? */ nmod_poly_mul(p, p, b); nmod_poly_divexact(p, p, g); if (first_poly && r2 < n) { for (i = 0; i < r1; i++) { for (j = 0; j < n; j++) B[i][j] = A[i][j]; } } first_poly = 0; } nmod_mat_clear(matA); nmod_mat_clear(matB); nmod_mat_clear(matv); nmod_poly_clear(b); nmod_poly_clear(g); TMP_END; } void nmod_mat_minpoly(nmod_poly_t p, const nmod_mat_t X) { nmod_mat_minpoly_with_gens(p, X, NULL); } flint-3.1.3/src/nmod_mat/mul.c000066400000000000000000000051151461254215100161630ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 William Hart Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "thread_support.h" #if FLINT_USES_BLAS # include "cblas.h" #endif void nmod_mat_mul(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong m = A->r; slong k = A->c; slong n = B->c; slong min_dim = FLINT_MIN(FLINT_MIN(m, k), n); slong cutoff; slong flint_num_threads = flint_get_num_threads(); FLINT_ASSERT(C->r == A->r); FLINT_ASSERT(C->c == B->c); FLINT_ASSERT(A->c == B->r); #if FLINT_USES_BLAS /* tuning is based on several assumptions: (1) blas_num_threads >= flint_num_threads. (2) nmod_mat_mul_blas (with crt) only beats nmod_mat_mul_classical on square multiplications of large enough dimension (3) if nmod_mat_mul_blas beats nmod_mat_mul_classical on square multiplications of size d, then it beats it on rectangular muliplications as long as all dimensions are >= d */ if (FLINT_BITS == 64 && min_dim > 100) { flint_bitcnt_t bits = FLINT_BIT_COUNT(A->mod.n); if (FLINT_BIT_COUNT(k) + 2*bits < 53 + 5) { /* mul_blas definitely avoids the slow crt */ cutoff = 100; } else if (flint_num_threads > 1) { /* mul_blas with crt is competing against mul_classical_threaded */ bits = FLINT_MAX(bits, 32); cutoff = 100 + 5*flint_num_threads*bits/2; } else { /* mul_blas with crt is competing against mul_strassen */ cutoff = 450; } if (min_dim > cutoff && nmod_mat_mul_blas(C, A, B)) return; } #endif if (C == A || C == B) { nmod_mat_t T; nmod_mat_init(T, m, n, A->mod.n); nmod_mat_mul(T, A, B); nmod_mat_swap_entrywise(C, T); nmod_mat_clear(T); return; } if (FLINT_BITS == 64 && C->mod.n < 2048) cutoff = 400; else cutoff = 200; if (flint_num_threads > 1) nmod_mat_mul_classical_threaded(C, A, B); else if (min_dim < cutoff) nmod_mat_mul_classical(C, A, B); else nmod_mat_mul_strassen(C, A, B); } flint-3.1.3/src/nmod_mat/mul_blas.c000066400000000000000000000504621461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #if FLINT_USES_BLAS && FLINT_BITS == 64 #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "fmpz.h" #include "cblas.h" /* This code is on the edge of disaster. Blas is used for dot products sum_{i=1}^k a_i*b_i, |a_i|, |b_i| <= n and we **assume** that if k*n^2 < MAX_BLAS_{DP|SP}_INT, then blas will calculate this dot product exactly. Test code fails easily with MAX_BLAS_DP_INT = 2^54 and also fails with MAX_BLAS_SP_INT = 2^25. */ /* for dgemm */ #define MAX_BLAS_DP_INT (UWORD(1) << 53) /* for sgemm */ #define MAX_BLAS_SP_INT (UWORD(1) << 24) /* helper for distributing the input conversion work */ static void _distribute_rows( slong * Astartrow, slong * Astoprow, /* limits for A */ slong * Bstartrow, slong * Bstoprow, /* limits for B */ slong m, /* number of rows of A */ slong start, slong stop) { FLINT_ASSERT(stop <= stop); if (start >= m) { *Astartrow = 0; *Astoprow = 0; *Bstartrow = start - m; *Bstoprow = stop - m; } else if (stop <= m) { *Astartrow = start; *Astoprow = stop; *Bstartrow = 0; *Bstoprow = 0; } else { *Astartrow = start; *Astoprow = m; *Bstartrow = 0; *Bstoprow = stop - m; } } /************ small enough that a single sgemm suffices **********************/ static void _lift_vec_sp(float * a, ulong * b, slong len, ulong n) { slong i; for (i = 0; i < len; i++) a[i] = (int)(b[i] - (n & FLINT_SIGN_EXT(n/2 - b[i]))); } typedef struct { slong m; slong n; slong k; slong Astartrow; slong Astoprow; slong Bstartrow; slong Bstoprow; mp_limb_t ctxn; float * dA; float * dB; mp_limb_t ** Arows; mp_limb_t ** Brows; } _lift_sp_worker_arg_struct; void _lift_sp_worker(void * arg_ptr) { _lift_sp_worker_arg_struct * arg = (_lift_sp_worker_arg_struct *) arg_ptr; slong n = arg->n; slong k = arg->k; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong Bstartrow = arg->Bstartrow; slong Bstoprow = arg->Bstoprow; mp_limb_t ctxn = arg->ctxn; float * dA = arg->dA; float * dB = arg->dB; mp_limb_t ** Arows = arg->Arows; mp_limb_t ** Brows = arg->Brows; slong i; for (i = Astartrow; i < Astoprow; i++) _lift_vec_sp(dA + i*k, Arows[i], k, ctxn); for (i = Bstartrow; i < Bstoprow; i++) _lift_vec_sp(dB + i*n, Brows[i], n, ctxn); } typedef struct { slong n; slong Cstartrow; slong Cstoprow; nmod_t * ctx; mp_limb_t shift; float * dC; mp_limb_t ** Crows; } _reduce_sp_worker_arg_struct; void _reduce_sp_worker(void * arg_ptr) { _reduce_sp_worker_arg_struct * arg = (_reduce_sp_worker_arg_struct *) arg_ptr; slong n = arg->n; slong Cstartrow = arg->Cstartrow; slong Cstoprow = arg->Cstoprow; nmod_t ctx = *arg->ctx; mp_limb_t shift = arg->shift; float * dC = arg->dC; mp_limb_t ** Crows = arg->Crows; slong i, j; for (i = Cstartrow; i < Cstoprow; i++) { for (j = 0; j < n; j++) { slong a = (slong) dC[i*n + j]; mp_limb_t b = (a < 0) ? a + shift : a; NMOD_RED(Crows[i][j], b, ctx); } } } static int _nmod_mat_mul_blas_sp(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong i; slong m = A->r; slong k = A->c; slong n = B->c; float * dC, * dA, * dB; ulong shift; nmod_t ctx = C->mod; slong num_workers; thread_pool_handle * handles; void * tmp; dA = flint_malloc(m*k*sizeof(float)); dB = flint_malloc(k*n*sizeof(float)); dC = flint_calloc(m*n, sizeof(float)); num_workers = flint_request_threads(&handles, INT_MAX); tmp = flint_malloc((num_workers + 1)*FLINT_MAX( sizeof(_lift_sp_worker_arg_struct), sizeof(_reduce_sp_worker_arg_struct))); /* convert inputs */ { _lift_sp_worker_arg_struct * args = (_lift_sp_worker_arg_struct *) tmp; for (i = 0; i <= num_workers; i++) { args[i].m = m; args[i].n = n; args[i].k = k; args[i].ctxn = ctx.n; args[i].dA = dA; args[i].dB = dB; args[i].Arows = A->rows; args[i].Brows = B->rows; _distribute_rows(&args[i].Astartrow, &args[i].Astoprow, &args[i].Bstartrow, &args[i].Bstoprow, m, ((m + k)*(i + 0))/(num_workers + 1), ((m + k)*(i + 1))/(num_workers + 1)); } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _lift_sp_worker, &args[i]); _lift_sp_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); } cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, 1.0, dA, k, dB, n, 0.0, dC, n); /* convert output */ /* the shift for negative outputs must satisfy ctx.n divides shift, and 2^24 <= shift <= 2^64 */ shift = ((2*MAX_BLAS_SP_INT)/ctx.n)*ctx.n; FLINT_ASSERT(MAX_BLAS_SP_INT <= shift); { _reduce_sp_worker_arg_struct * args = (_reduce_sp_worker_arg_struct *) tmp; for (i = 0; i <= num_workers; i++) { args[i].n = n; args[i].Cstartrow = ((i + 0)*m)/(num_workers + 1); args[i].Cstoprow = ((i + 1)*m)/(num_workers + 1); args[i].ctx = &ctx; args[i].shift = shift; args[i].dC = dC; args[i].Crows = C->rows; } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _reduce_sp_worker, &args[i]); _reduce_sp_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); } flint_free(tmp); flint_give_back_threads(handles, num_workers); flint_free(dA); flint_free(dB); flint_free(dC); return 1; } /******** handle larger larger moduli via several dgemm's and crt ************/ #define MAX_CRT_NUM 12 static void _lift_vec_crt(double * a, ulong * b, slong len, nmod_t ctx) { slong i; for (i = 0; i < len; i++) { mp_limb_t bn; NMOD_RED(bn, b[i], ctx); a[i] = (int)(bn - (ctx.n & FLINT_SIGN_EXT(ctx.n/2 - bn))); } } typedef struct { slong m; slong n; slong k; slong Astartrow; slong Astoprow; slong Bstartrow; slong Bstoprow; nmod_t crtmod; double * dA; double * dB; mp_limb_t ** Arows; mp_limb_t ** Brows; } _lift_crt_worker_arg_struct; void _lift_crt_worker(void * arg_ptr) { _lift_crt_worker_arg_struct * arg = (_lift_crt_worker_arg_struct *) arg_ptr; slong n = arg->n; slong k = arg->k; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong Bstartrow = arg->Bstartrow; slong Bstoprow = arg->Bstoprow; nmod_t crtmod = arg->crtmod; double * dA = arg->dA; double * dB = arg->dB; mp_limb_t ** Arows = arg->Arows; mp_limb_t ** Brows = arg->Brows; slong i; for (i = Astartrow; i < Astoprow; i++) _lift_vec_crt(dA + i*k, Arows[i], k, crtmod); for (i = Bstartrow; i < Bstoprow; i++) _lift_vec_crt(dB + i*n, Brows[i], n, crtmod); } typedef struct { slong m; slong n; slong Cstartrow; slong Cstoprow; slong crtnum; nmod_t * crtmod; nmod_t * ctx; double * dC; mp_limb_t ** Crows; } _reduce_crt_worker_arg_struct; void _reduce_crt_worker(void * arg_ptr) { _reduce_crt_worker_arg_struct * arg = (_reduce_crt_worker_arg_struct *) arg_ptr; slong Cstartrow = arg->Cstartrow; slong Cstoprow = arg->Cstoprow; slong i, j, pi, pj; slong m = arg->m; slong n = arg->n; double * dC = arg->dC; nmod_t ctx = *arg->ctx; ulong s, t, hi, lo, reshi, reslo; slong crtnum = arg->crtnum; mp_limb_t ** Crows = arg->Crows; nmod_t crtmod[MAX_CRT_NUM]; mp_limb_t q[MAX_CRT_NUM], v[MAX_CRT_NUM], u[MAX_CRT_NUM]; mp_limb_t shifts[MAX_CRT_NUM], pmodinv[MAX_CRT_NUM*MAX_CRT_NUM]; for (i = 0; i < crtnum; i++) crtmod[i] = arg->crtmod[i]; /* set p_i = crtmod[i].n for finding u given its image u[i] mod p_i, first solve for the v[i]: u = v[0] + v[1]*p_0 + v[2]*p_0*p_1 + ... + v[crtnum-1]*p_0*...*p_{crtnum-1} then evaluate this dot product modulo ctx.n to find u mod ctx.n. The lower triangular matrix pmodinv is used for calculating the v[i]. */ for (pi = 0; pi < crtnum; pi++) { t = 1; s = 1; for (pj = pi - 1; pj >= 0; pj--) { t = nmod_mul(t, crtmod[pj].n, crtmod[pi]); FLINT_ASSERT(crtmod[pj].n < ctx.n); s = nmod_mul(s, crtmod[pj].n, ctx); pmodinv[MAX_CRT_NUM*pi + pj] = nmod_neg( nmod_inv(t, crtmod[pi]), crtmod[pi]); } q[pi] = s; /* q[i] = p_0 * ... * p[i-1] mod ctx.n */ /* for double -> nmod conversion */ shifts[pi] = ((2*MAX_BLAS_DP_INT)/crtmod[pi].n)*crtmod[pi].n; } for (i = Cstartrow; i < Cstoprow; i++) { for (j = 0; j < n; j++) { for (pi = 0; pi < crtnum; pi++) { slong a = (slong) dC[i*n + j + pi*m*n]; mp_limb_t b = (a < 0) ? a + shifts[pi] : a; NMOD_RED(u[pi], b, crtmod[pi]); } reslo = u[0]; reshi = 0; for (pi = 1; pi < crtnum; pi++) { FLINT_ASSERT(u[pi] < crtmod[pi].n); FLINT_ASSERT(u[0] < crtmod[pi].n); t = pmodinv[MAX_CRT_NUM*pi + 0]*nmod_sub(u[0], u[pi], crtmod[pi]); for (pj = 1; pj < pi; pj++) t += pmodinv[MAX_CRT_NUM*pi + pj]*v[pj]; NMOD_RED(v[pi], t, crtmod[pi]); umul_ppmm(hi, lo, v[pi], q[pi]); add_ssaaaa(reshi, reslo, reshi, reslo, hi, lo); } if (reshi < ctx.n) NMOD_RED2(Crows[i][j], reshi, reslo, ctx); else NMOD2_RED2(Crows[i][j], reshi, reslo, ctx); } } } static int _nmod_mat_mul_blas_crt(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong i, pi, crtnum; slong m = A->r; slong k = A->c; slong n = B->c; double * dC, * dA, * dB; nmod_t ctx = C->mod; ulong t; nmod_t crtmod[MAX_CRT_NUM]; /* not nec prime */ fmpz_t prodmod, maxentry; void * tmp; slong num_workers; thread_pool_handle * handles; fmpz_init_set_ui(maxentry, k); fmpz_mul_ui(maxentry, maxentry, ctx.n - 1); fmpz_mul_ui(maxentry, maxentry, ctx.n - 1); t = n_sqrt((4*MAX_BLAS_DP_INT)/k - 1); fmpz_init_set_ui(prodmod, t); nmod_init(crtmod + 0, t); crtnum = 1; do { t = crtmod[crtnum - 1].n; do { if (crtnum >= MAX_CRT_NUM || t < 100) { fmpz_clear(maxentry); fmpz_clear(prodmod); return 0; } t--; } while (n_gcd(fmpz_fdiv_ui(prodmod, t), t) != 1); fmpz_mul_ui(prodmod, prodmod, t); nmod_init(crtmod + crtnum, t); crtnum++; } while (fmpz_cmp(prodmod, maxentry) <= 0); /* note that if k is sufficiently big, i.e. k >= 4, then crtnum >= 3 */ /* arange the crt moduli in increasing order */ for (pi = 0; pi < crtnum/2; pi++) { nmod_t tmp = crtmod[pi]; crtmod[pi] = crtmod[crtnum - 1 - pi]; crtmod[crtnum - 1 - pi] = tmp; } dA = flint_malloc(m*k*sizeof(double)); dB = flint_malloc(k*n*sizeof(double)); dC = flint_calloc(crtnum*m*n, sizeof(double)); num_workers = flint_request_threads(&handles, INT_MAX); tmp = flint_malloc((num_workers + 1)*FLINT_MAX( sizeof(_lift_crt_worker_arg_struct), sizeof(_reduce_crt_worker_arg_struct))); for (pi = 0; pi < crtnum; pi++) { _lift_crt_worker_arg_struct * args = (_lift_crt_worker_arg_struct *) tmp; for (i = 0; i <= num_workers; i++) { args[i].m = m; args[i].n = n; args[i].k = k; args[i].crtmod = crtmod[pi]; args[i].dA = dA; args[i].dB = dB; args[i].Arows = A->rows; args[i].Brows = B->rows; _distribute_rows(&args[i].Astartrow, &args[i].Astoprow, &args[i].Bstartrow, &args[i].Bstoprow, m, ((m + k)*(i + 0))/(num_workers + 1), ((m + k)*(i + 1))/(num_workers + 1)); } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _lift_crt_worker, &args[i]); _lift_crt_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, 1.0, dA, k, dB, n, 0.0, dC + pi*m*n, n); } { _reduce_crt_worker_arg_struct * args = (_reduce_crt_worker_arg_struct *) tmp; for (i = 0; i <= num_workers; i++) { args[i].m = m; args[i].n = n; args[i].Cstartrow = ((i + 0)*m)/(num_workers + 1); args[i].Cstoprow = ((i + 1)*m)/(num_workers + 1); args[i].crtnum = crtnum; args[i].crtmod = crtmod; args[i].ctx = &ctx; args[i].dC = dC; args[i].Crows = C->rows; } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _reduce_crt_worker, &args[i]); _reduce_crt_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); } flint_free(tmp); flint_give_back_threads(handles, num_workers); flint_free(dA); flint_free(dB); flint_free(dC); fmpz_clear(maxentry); fmpz_clear(prodmod); return 1; } /********** try with a single dgemm if possible ******************************/ static void _lift_vec_dp(double * a, ulong * b, slong len, ulong n) { slong i; for (i = 0; i < len; i++) a[i] = (int)(b[i] - (n & FLINT_SIGN_EXT(n/2 - b[i]))); } typedef struct { slong m; slong n; slong k; slong Astartrow; slong Astoprow; slong Bstartrow; slong Bstoprow; mp_limb_t ctxn; double * dA; double * dB; mp_limb_t ** Arows; mp_limb_t ** Brows; } _lift_dp_worker_arg_struct; void _lift_dp_worker(void * arg_ptr) { _lift_dp_worker_arg_struct * arg = (_lift_dp_worker_arg_struct *) arg_ptr; slong n = arg->n; slong k = arg->k; slong Astartrow = arg->Astartrow; slong Astoprow = arg->Astoprow; slong Bstartrow = arg->Bstartrow; slong Bstoprow = arg->Bstoprow; mp_limb_t ctxn = arg->ctxn; double * dA = arg->dA; double * dB = arg->dB; mp_limb_t ** Arows = arg->Arows; mp_limb_t ** Brows = arg->Brows; slong i; for (i = Astartrow; i < Astoprow; i++) _lift_vec_dp(dA + i*k, Arows[i], k, ctxn); for (i = Bstartrow; i < Bstoprow; i++) _lift_vec_dp(dB + i*n, Brows[i], n, ctxn); } typedef struct { slong n; slong Cstartrow; slong Cstoprow; nmod_t * ctx; mp_limb_t shift; double * dC; mp_limb_t ** Crows; } _reduce_dp_worker_arg_struct; void _reduce_dp_worker(void * arg_ptr) { _reduce_dp_worker_arg_struct * arg = (_reduce_dp_worker_arg_struct *) arg_ptr; slong n = arg->n; slong Cstartrow = arg->Cstartrow; slong Cstoprow = arg->Cstoprow; nmod_t ctx = *arg->ctx; mp_limb_t shift = arg->shift; double * dC = arg->dC; mp_limb_t ** Crows = arg->Crows; slong i, j; for (i = Cstartrow; i < Cstoprow; i++) { for (j = 0; j < n; j++) { slong a = (slong) dC[i*n + j]; mp_limb_t b = (a < 0) ? a + shift : a; NMOD_RED(Crows[i][j], b, ctx); } } } int nmod_mat_mul_blas(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong i; slong m = A->r; slong k = A->c; slong n = B->c; double * dC, * dA, * dB; ulong hi, lo, shift; nmod_t ctx = C->mod; slong num_workers; thread_pool_handle * handles; void * tmp; if (m < 1 || k < 1 || n < 1 || m > INT_MAX || k > INT_MAX || n > INT_MAX) return 0; /* Each nmod has |_lift()| <= floor(mod.n/2) in the signed representation. Want k*floor(mod.n/2)^2 < MAX_BLAS_DP_INT. */ umul_ppmm(hi, lo, ctx.n/2, ctx.n/2); if (hi != 0) return _nmod_mat_mul_blas_crt(C, A, B); umul_ppmm(hi, lo, lo, k); if (hi != 0 || lo >= MAX_BLAS_DP_INT) return _nmod_mat_mul_blas_crt(C, A, B); if (lo < MAX_BLAS_SP_INT) return _nmod_mat_mul_blas_sp(C, A, B); dA = flint_malloc(m*k*sizeof(double)); dB = flint_malloc(k*n*sizeof(double)); dC = flint_calloc(m*n, sizeof(double)); num_workers = flint_request_threads(&handles, INT_MAX); tmp = flint_malloc((num_workers + 1)*FLINT_MAX( sizeof(_lift_dp_worker_arg_struct), sizeof(_reduce_dp_worker_arg_struct))); /* convert inputs */ { _lift_dp_worker_arg_struct * args = (_lift_dp_worker_arg_struct *) tmp; for (i = 0; i <= num_workers; i++) { args[i].m = m; args[i].n = n; args[i].k = k; args[i].ctxn = ctx.n; args[i].dA = dA; args[i].dB = dB; args[i].Arows = A->rows; args[i].Brows = B->rows; _distribute_rows(&args[i].Astartrow, &args[i].Astoprow, &args[i].Bstartrow, &args[i].Bstoprow, m, ((m + k)*(i + 0))/(num_workers + 1), ((m + k)*(i + 1))/(num_workers + 1)); } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _lift_dp_worker, &args[i]); _lift_dp_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); } cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, 1.0, dA, k, dB, n, 0.0, dC, n); /* convert output */ /* the shift for negative outputs must satisfy ctx.n divides shift, and 2^53 <= shift <= 2^64 */ shift = ((2*MAX_BLAS_DP_INT)/ctx.n)*ctx.n; FLINT_ASSERT(MAX_BLAS_DP_INT <= shift); { _reduce_dp_worker_arg_struct * args = (_reduce_dp_worker_arg_struct *) tmp; for (i = 0; i <= num_workers; i++) { args[i].n = n; args[i].Cstartrow = ((i + 0)*m)/(num_workers + 1); args[i].Cstoprow = ((i + 1)*m)/(num_workers + 1); args[i].ctx = &ctx; args[i].shift = shift; args[i].dC = dC; args[i].Crows = C->rows; } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _reduce_dp_worker, &args[i]); _reduce_dp_worker(&args[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); } flint_free(tmp); flint_give_back_threads(handles, num_workers); flint_free(dA); flint_free(dB); flint_free(dC); return 1; } #else int nmod_mat_mul_blas(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { return 0; } #endif flint-3.1.3/src/nmod_mat/mul_classical.c000066400000000000000000000122331461254215100202000ustar00rootroot00000000000000/* Copyright (C) 2010,2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" /* gcc11 on x86_64 generates significantly worse code with -O3 */ #pragma GCC optimize("-O2") /* with op = 0, computes D = A*B with op = 1, computes D = C + A*B with op = -1, computes D = C - A*B */ static inline void _nmod_mat_addmul_basic_op(mp_ptr * D, mp_ptr * const C, mp_ptr * const A, mp_ptr * const B, slong m, slong k, slong n, int op, nmod_t mod, int nlimbs) { slong i, j; mp_limb_t c; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { c = _nmod_vec_dot_ptr(A[i], B, j, k, mod, nlimbs); if (op == 1) c = nmod_add(C[i][j], c, mod); else if (op == -1) c = nmod_sub(C[i][j], c, mod); D[i][j] = c; } } } static inline void _nmod_mat_addmul_transpose_op(mp_ptr * D, const mp_ptr * C, const mp_ptr * A, const mp_ptr * B, slong m, slong k, slong n, int op, nmod_t mod, int nlimbs) { mp_ptr tmp; mp_limb_t c; slong i, j; tmp = flint_malloc(sizeof(mp_limb_t) * k * n); for (i = 0; i < k; i++) for (j = 0; j < n; j++) tmp[j*k + i] = B[i][j]; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { c = _nmod_vec_dot(A[i], tmp + j*k, k, mod, nlimbs); if (op == 1) c = nmod_add(C[i][j], c, mod); else if (op == -1) c = nmod_sub(C[i][j], c, mod); D[i][j] = c; } } flint_free(tmp); } /* requires nlimbs = 1 */ void _nmod_mat_addmul_packed_op(mp_ptr * D, const mp_ptr * C, const mp_ptr * A, const mp_ptr * B, slong M, slong N, slong K, int op, nmod_t mod, int nlimbs) { slong i, j, k; slong Kpack; int pack, pack_bits; mp_limb_t c, d, mask; mp_ptr tmp; mp_ptr Aptr, Tptr; /* bound unreduced entry */ c = N * (mod.n-1) * (mod.n-1); pack_bits = FLINT_BIT_COUNT(c); pack = FLINT_BITS / pack_bits; Kpack = (K + pack - 1) / pack; if (pack_bits == FLINT_BITS) mask = UWORD(-1); else mask = (UWORD(1) << pack_bits) - 1; tmp = _nmod_vec_init(Kpack * N); /* pack and transpose B */ for (i = 0; i < Kpack; i++) { for (k = 0; k < N; k++) { c = B[k][i * pack]; for (j = 1; j < pack && i * pack + j < K; j++) c |= B[k][i * pack + j] << (pack_bits * j); tmp[i * N + k] = c; } } /* multiply */ for (i = 0; i < M; i++) { for (j = 0; j < Kpack; j++) { Aptr = A[i]; Tptr = tmp + j * N; c = 0; /* unroll by 4 */ for (k = 0; k + 4 <= N; k += 4) { c += Aptr[k + 0] * Tptr[k + 0]; c += Aptr[k + 1] * Tptr[k + 1]; c += Aptr[k + 2] * Tptr[k + 2]; c += Aptr[k + 3] * Tptr[k + 3]; } for ( ; k < N; k++) c += Aptr[k] * Tptr[k]; /* unpack and reduce */ for (k = 0; k < pack && j * pack + k < K; k++) { d = (c >> (k * pack_bits)) & mask; NMOD_RED(d, d, mod); if (op == 1) d = nmod_add(C[i][j * pack + k], d, mod); else if (op == -1) d = nmod_sub(C[i][j * pack + k], d, mod); D[i][j * pack + k] = d; } } } _nmod_vec_clear(tmp); } void _nmod_mat_mul_classical_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op) { slong m, k, n; int nlimbs; nmod_t mod; mod = A->mod; m = A->r; k = A->c; n = B->c; if (k == 0) { if (op == 0) nmod_mat_zero(D); else nmod_mat_set(D, C); return; } nlimbs = _nmod_vec_dot_bound_limbs(k, mod); if (nlimbs == 1 && m > 10 && k > 10 && n > 10) { _nmod_mat_addmul_packed_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, m, k, n, op, D->mod, nlimbs); } else if (m < NMOD_MAT_MUL_TRANSPOSE_CUTOFF || n < NMOD_MAT_MUL_TRANSPOSE_CUTOFF || k < NMOD_MAT_MUL_TRANSPOSE_CUTOFF) { if ((mod.n & (mod.n - 1)) == 0) nlimbs = 1; _nmod_mat_addmul_basic_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, m, k, n, op, D->mod, nlimbs); } else { if ((mod.n & (mod.n - 1)) == 0) nlimbs = 1; _nmod_mat_addmul_transpose_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, m, k, n, op, D->mod, nlimbs); } } void nmod_mat_mul_classical(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { _nmod_mat_mul_classical_op(C, NULL, A, B, 0); } flint-3.1.3/src/nmod_mat/mul_classical_threaded.c000066400000000000000000000276211461254215100220470ustar00rootroot00000000000000/* Copyright (C) 2010, 2012 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" #define FLINT_MUL_CLASSICAL_CACHE_SIZE 32768 /* size of L1 cache in words */ /* with op = 0, computes D = A*B with op = 1, computes D = C + A*B with op = -1, computes D = C - A*B */ static inline void _nmod_mat_addmul_basic_op(mp_ptr * D, mp_ptr * const C, mp_ptr * const A, mp_ptr * const B, slong m, slong k, slong n, int op, nmod_t mod, int nlimbs) { slong i, j; mp_limb_t c; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { c = _nmod_vec_dot_ptr(A[i], B, j, k, mod, nlimbs); if (op == 1) c = nmod_add(C[i][j], c, mod); else if (op == -1) c = nmod_sub(C[i][j], c, mod); D[i][j] = c; } } } typedef struct { slong block; volatile slong * i; volatile slong * j; slong k; slong m; slong n; slong nlimbs; const mp_ptr * A; const mp_ptr * C; mp_ptr * D; mp_ptr tmp; nmod_t mod; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif int op; } nmod_mat_transpose_arg_t; void _nmod_mat_addmul_transpose_worker(void * arg_ptr) { nmod_mat_transpose_arg_t arg = *((nmod_mat_transpose_arg_t *) arg_ptr); slong i, j, iend, jend, jstart; slong block = arg.block; slong k = arg.k; slong m = arg.m; slong n = arg.n; slong nlimbs = arg.nlimbs; const mp_ptr * A = arg.A; const mp_ptr * C = arg.C; mp_ptr * D = arg.D; mp_ptr tmp = arg.tmp; nmod_t mod = arg.mod; int op = arg.op; mp_limb_t c; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; j = *arg.j; if (j >= n) { i += block; *arg.i = i; j = 0; } *arg.j = j + block; #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= m) return; iend = FLINT_MIN(i + block, m); jend = FLINT_MIN(j + block, n); jstart = j; for ( ; i < iend; i++) { for (j = jstart ; j < jend; j++) { c = _nmod_vec_dot(A[i], tmp + j*k, k, mod, nlimbs); if (op == 1) c = nmod_add(C[i][j], c, mod); else if (op == -1) c = nmod_sub(C[i][j], c, mod); D[i][j] = c; } } } } static inline void _nmod_mat_addmul_transpose_threaded_pool_op(mp_ptr * D, const mp_ptr * C, const mp_ptr * A, const mp_ptr * B, slong m, slong k, slong n, int op, nmod_t mod, int nlimbs, thread_pool_handle * threads, slong num_threads) { mp_ptr tmp; slong i, j, block; slong shared_i = 0, shared_j = 0; nmod_mat_transpose_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif tmp = flint_malloc(sizeof(mp_limb_t) * k * n); /* transpose B */ for (i = 0; i < k; i++) for (j = 0; j < n; j++) tmp[j*k + i] = B[i][j]; /* compute optimal block width */ block = FLINT_MAX(FLINT_MIN(m/(num_threads + 1), n/(num_threads + 1)), 1); while (2*block*k > FLINT_MUL_CLASSICAL_CACHE_SIZE && block > 1) block >>= 1; args = flint_malloc(sizeof(nmod_mat_transpose_arg_t) * (num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].block = block; args[i].i = &shared_i; args[i].j = &shared_j; args[i].k = k; args[i].m = m; args[i].n = n; args[i].nlimbs = nlimbs; args[i].A = A; args[i].C = C; args[i].D = D; args[i].tmp = tmp; args[i].mod = mod; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif args[i].op = op; } #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif for (i = 0; i < num_threads; i++) { thread_pool_wake(global_thread_pool, threads[i], 0, _nmod_mat_addmul_transpose_worker, &args[i]); } _nmod_mat_addmul_transpose_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) { thread_pool_wait(global_thread_pool, threads[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif flint_free(args); flint_free(tmp); } typedef struct { slong block; volatile slong * i; volatile slong * j; slong M; slong K; slong N; slong Kpack; const mp_ptr * A; const mp_ptr * C; mp_ptr * D; mp_ptr tmp; nmod_t mod; mp_limb_t mask; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif int pack; int pack_bits; int op; } nmod_mat_packed_arg_t; void _nmod_mat_addmul_packed_worker(void * arg_ptr) { nmod_mat_packed_arg_t arg = *((nmod_mat_packed_arg_t *) arg_ptr); slong i, j, k, iend, jend, jstart; slong block = arg.block; slong M = arg.M; slong K = arg.K; slong N = arg.N; slong Kpack = arg.Kpack; const mp_ptr * A = arg.A; const mp_ptr * C = arg.C; mp_ptr * D = arg.D; mp_ptr tmp = arg.tmp; nmod_t mod = arg.mod; mp_limb_t mask = arg.mask; int pack = arg.pack; int pack_bits = arg.pack_bits; int op = arg.op; mp_limb_t c, d; mp_ptr Aptr, Tptr; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif i = *arg.i; j = *arg.j; if (j >= Kpack) { i += block; *arg.i = i; j = 0; } *arg.j = j + block; #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (i >= M) return; iend = FLINT_MIN(i + block, M); jend = FLINT_MIN(j + block, Kpack); jstart = j; /* multiply */ for ( ; i < iend; i++) { for (j = jstart; j < jend; j++) { Aptr = A[i]; Tptr = tmp + j * N; c = 0; /* unroll by 4 */ for (k = 0; k + 4 <= N; k += 4) { c += Aptr[k + 0] * Tptr[k + 0]; c += Aptr[k + 1] * Tptr[k + 1]; c += Aptr[k + 2] * Tptr[k + 2]; c += Aptr[k + 3] * Tptr[k + 3]; } for ( ; k < N; k++) c += Aptr[k] * Tptr[k]; /* unpack and reduce */ for (k = 0; k < pack && j * pack + k < K; k++) { d = (c >> (k * pack_bits)) & mask; NMOD_RED(d, d, mod); if (op == 1) d = nmod_add(C[i][j * pack + k], d, mod); else if (op == -1) d = nmod_sub(C[i][j * pack + k], d, mod); D[i][j * pack + k] = d; } } } } } /* requires nlimbs = 1 */ void _nmod_mat_addmul_packed_threaded_pool_op(mp_ptr * D, const mp_ptr * C, const mp_ptr * A, const mp_ptr * B, slong M, slong N, slong K, int op, nmod_t mod, int nlimbs, thread_pool_handle * threads, slong num_threads) { slong i, j, k; slong Kpack, block; int pack, pack_bits; mp_limb_t c, mask; mp_ptr tmp; slong shared_i = 0, shared_j = 0; nmod_mat_packed_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif /* bound unreduced entry */ c = N * (mod.n-1) * (mod.n-1); pack_bits = FLINT_BIT_COUNT(c); pack = FLINT_BITS / pack_bits; Kpack = (K + pack - 1) / pack; if (pack_bits == FLINT_BITS) mask = UWORD(-1); else mask = (UWORD(1) << pack_bits) - 1; tmp = _nmod_vec_init(Kpack * N); /* pack and transpose B */ for (i = 0; i < Kpack; i++) { for (k = 0; k < N; k++) { c = B[k][i * pack]; for (j = 1; j < pack && i * pack + j < K; j++) c |= B[k][i * pack + j] << (pack_bits * j); tmp[i * N + k] = c; } } /* compute optimal block width */ block = FLINT_MAX(FLINT_MIN(M/(num_threads + 1), Kpack/(num_threads + 1)), 1); while (2*block*N > FLINT_MUL_CLASSICAL_CACHE_SIZE && block > 1) block >>= 1; args = flint_malloc(sizeof(nmod_mat_packed_arg_t) * (num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].block = block; args[i].i = &shared_i; args[i].j = &shared_j; args[i].M = M; args[i].K = K; args[i].N = N; args[i].Kpack = Kpack; args[i].A = A; args[i].C = C; args[i].D = D; args[i].tmp = tmp; args[i].mod = mod; args[i].mask = mask; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif args[i].pack = pack; args[i].pack_bits = pack_bits; args[i].op = op; } #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif for (i = 0; i < num_threads; i++) { thread_pool_wake(global_thread_pool, threads[i], 0, _nmod_mat_addmul_packed_worker, &args[i]); } _nmod_mat_addmul_packed_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) { thread_pool_wait(global_thread_pool, threads[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif flint_free(args); _nmod_vec_clear(tmp); } void _nmod_mat_mul_classical_threaded_pool_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op, thread_pool_handle * threads, slong num_threads) { slong m, k, n; int nlimbs; nmod_t mod; mod = A->mod; m = A->r; k = A->c; n = B->c; nlimbs = _nmod_vec_dot_bound_limbs(k, mod); if (nlimbs == 1 && m > 10 && k > 10 && n > 10) { _nmod_mat_addmul_packed_threaded_pool_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, m, k, n, op, D->mod, nlimbs, threads, num_threads); } else { if ((mod.n & (mod.n - 1)) == 0) nlimbs = 1; _nmod_mat_addmul_transpose_threaded_pool_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, m, k, n, op, D->mod, nlimbs, threads, num_threads); } } void _nmod_mat_mul_classical_threaded_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op) { thread_pool_handle * threads; slong num_threads; if (A->c == 0) { if (op == 0) nmod_mat_zero(D); else nmod_mat_set(D, C); return; } if (A->r < NMOD_MAT_MUL_TRANSPOSE_CUTOFF || A->c < NMOD_MAT_MUL_TRANSPOSE_CUTOFF || B->c < NMOD_MAT_MUL_TRANSPOSE_CUTOFF) { slong nlimbs = _nmod_vec_dot_bound_limbs(A->c, D->mod); _nmod_mat_addmul_basic_op(D->rows, (op == 0) ? NULL : C->rows, A->rows, B->rows, A->r, A->c, B->c, op, D->mod, nlimbs); return; } num_threads = flint_request_threads(&threads, flint_get_num_threads()); _nmod_mat_mul_classical_threaded_pool_op(D, C, A, B, op, threads, num_threads); flint_give_back_threads(threads, num_threads); } void nmod_mat_mul_classical_threaded(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { _nmod_mat_mul_classical_threaded_op(C, NULL, A, B, 0); } flint-3.1.3/src/nmod_mat/mul_nmod_vec.c000066400000000000000000000025271461254215100200410ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_mul_nmod_vec( mp_limb_t * c, const nmod_mat_t A, const mp_limb_t * b, slong blen) { nmod_t mod = A->mod; slong i, j; slong len = FLINT_MIN(A->c, blen); int nlimbs = _nmod_vec_dot_bound_limbs(len, mod); for (i = A->r - 1; i >= 0; i--) { const mp_limb_t * Ai = A->rows[i]; NMOD_VEC_DOT(c[i], j, len, Ai[j], b[j], mod, nlimbs); } } void nmod_mat_mul_nmod_vec_ptr( mp_limb_t * const * c, const nmod_mat_t A, const mp_limb_t * const * b, slong blen) { slong i; slong len = FLINT_MIN(A->c, blen); slong nrows = A->r; mp_limb_t * bb, * cc; TMP_INIT; TMP_START; bb = TMP_ARRAY_ALLOC(len, mp_limb_t); cc = TMP_ARRAY_ALLOC(nrows, mp_limb_t); for (i = 0; i < len; i++) bb[i] = b[i][0]; nmod_mat_mul_nmod_vec(cc, A, bb, len); for (i = 0; i < nrows; i++) c[i][0] = cc[i]; TMP_END; } flint-3.1.3/src/nmod_mat/mul_strassen.c000066400000000000000000000105341461254215100201060ustar00rootroot00000000000000/* Copyright (C) 2008, Martin Albrecht Copyright (C) 2008, 2009 William Hart. Copyright (C) 2010, Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" /* The implemented sequence is not Strassen's nor Winograd's, but the sequence proposed by Bodrato, which is equivalent to Winograd's, and can be easily adapted to compute the square of a matrix. */ void nmod_mat_mul_strassen(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong a, b, c; slong anr, anc, bnr, bnc; nmod_mat_t A11, A12, A21, A22; nmod_mat_t B11, B12, B21, B22; nmod_mat_t C11, C12, C21, C22; nmod_mat_t X1, X2; a = A->r; b = A->c; c = B->c; if (a <= 4 || b <= 4 || c <= 4) { nmod_mat_mul(C, A, B); return; } anr = a / 2; anc = b / 2; bnr = anc; bnc = c / 2; nmod_mat_window_init(A11, A, 0, 0, anr, anc); nmod_mat_window_init(A12, A, 0, anc, anr, 2*anc); nmod_mat_window_init(A21, A, anr, 0, 2*anr, anc); nmod_mat_window_init(A22, A, anr, anc, 2*anr, 2*anc); nmod_mat_window_init(B11, B, 0, 0, bnr, bnc); nmod_mat_window_init(B12, B, 0, bnc, bnr, 2*bnc); nmod_mat_window_init(B21, B, bnr, 0, 2*bnr, bnc); nmod_mat_window_init(B22, B, bnr, bnc, 2*bnr, 2*bnc); nmod_mat_window_init(C11, C, 0, 0, anr, bnc); nmod_mat_window_init(C12, C, 0, bnc, anr, 2*bnc); nmod_mat_window_init(C21, C, anr, 0, 2*anr, bnc); nmod_mat_window_init(C22, C, anr, bnc, 2*anr, 2*bnc); nmod_mat_init(X1, anr, FLINT_MAX(bnc, anc), A->mod.n); nmod_mat_init(X2, anc, bnc, A->mod.n); X1->c = anc; /* See Jean-Guillaume Dumas, Clement Pernet, Wei Zhou; "Memory efficient scheduling of Strassen-Winograd's matrix multiplication algorithm"; https://arxiv.org/pdf/0707.2347v3 for reference on the used operation scheduling. */ nmod_mat_add(X1, A22, A12); nmod_mat_add(X2, B22, B12); nmod_mat_mul(C21, X1, X2); nmod_mat_sub(X1, A22, A21); nmod_mat_sub(X2, B22, B21); nmod_mat_mul(C22, X1, X2); nmod_mat_add(X1, X1, A12); nmod_mat_add(X2, X2, B12); nmod_mat_mul(C11, X1, X2); nmod_mat_sub(X1, X1, A11); nmod_mat_mul(C12, X1, B12); X1->c = bnc; nmod_mat_mul(X1, A12, B21); nmod_mat_add(C11, C11, X1); nmod_mat_add(C12, C12, C22); nmod_mat_sub(C12, C11, C12); nmod_mat_sub(C11, C21, C11); nmod_mat_sub(X2, X2, B11); nmod_mat_mul(C21, A21, X2); nmod_mat_clear(X2); nmod_mat_sub(C21, C11, C21); nmod_mat_add(C22, C22, C11); nmod_mat_mul(C11, A11, B11); nmod_mat_add(C11, X1, C11); X1->c = FLINT_MAX(bnc, anc); nmod_mat_clear(X1); nmod_mat_window_clear(A11); nmod_mat_window_clear(A12); nmod_mat_window_clear(A21); nmod_mat_window_clear(A22); nmod_mat_window_clear(B11); nmod_mat_window_clear(B12); nmod_mat_window_clear(B21); nmod_mat_window_clear(B22); nmod_mat_window_clear(C11); nmod_mat_window_clear(C12); nmod_mat_window_clear(C21); nmod_mat_window_clear(C22); if (c > 2*bnc) /* A by last col of B -> last col of C */ { nmod_mat_t Bc, Cc; nmod_mat_window_init(Bc, B, 0, 2*bnc, b, c); nmod_mat_window_init(Cc, C, 0, 2*bnc, a, c); nmod_mat_mul(Cc, A, Bc); nmod_mat_window_clear(Bc); nmod_mat_window_clear(Cc); } if (a > 2*anr) /* last row of A by B -> last row of C */ { nmod_mat_t Ar, Cr; nmod_mat_window_init(Ar, A, 2*anr, 0, a, b); nmod_mat_window_init(Cr, C, 2*anr, 0, a, c); nmod_mat_mul(Cr, Ar, B); nmod_mat_window_clear(Ar); nmod_mat_window_clear(Cr); } if (b > 2*anc) /* last col of A by last row of B -> C */ { nmod_mat_t Ac, Br, Cb; nmod_mat_window_init(Ac, A, 0, 2*anc, 2*anr, b); nmod_mat_window_init(Br, B, 2*bnr, 0, b, 2*bnc); nmod_mat_window_init(Cb, C, 0, 0, 2*anr, 2*bnc); nmod_mat_addmul(Cb, Cb, Ac, Br); nmod_mat_window_clear(Ac); nmod_mat_window_clear(Br); nmod_mat_window_clear(Cb); } } flint-3.1.3/src/nmod_mat/neg.c000066400000000000000000000011621461254215100161350ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_neg(nmod_mat_t B, const nmod_mat_t A) { slong i; if (A->c == 0) return; for (i = 0; i < A->r; i++) _nmod_vec_neg(B->rows[i], A->rows[i], A->c, A->mod); } flint-3.1.3/src/nmod_mat/nmod_vec_mul.c000066400000000000000000000027211461254215100200350ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" /* TODO try delaying the reductions */ void nmod_mat_nmod_vec_mul( mp_limb_t * c, const mp_limb_t * a, slong alen, const nmod_mat_t B) { slong i; slong len = FLINT_MIN(B->r, alen); slong ncols = B->c; /* scalar_addmul wants non-empty */ if (ncols < 1) return; if (len > 0) _nmod_vec_scalar_mul_nmod(c, B->rows[0], ncols, a[0], B->mod); else _nmod_vec_zero(c, ncols); for (i = 1; i < len; i++) _nmod_vec_scalar_addmul_nmod(c, B->rows[i], ncols, a[i], B->mod); } void nmod_mat_nmod_vec_mul_ptr( mp_limb_t * const * c, const mp_limb_t * const * a, slong alen, const nmod_mat_t B) { slong i; slong len = FLINT_MIN(B->r, alen); slong ncols = B->c; mp_limb_t * aa, * cc; TMP_INIT; TMP_START; aa = TMP_ARRAY_ALLOC(len, mp_limb_t); cc = TMP_ARRAY_ALLOC(ncols, mp_limb_t); for (i = 0; i < len; i++) aa[i] = a[i][0]; nmod_mat_nmod_vec_mul(cc, aa, len, B); for (i = 0; i < ncols; i++) c[i][0] = cc[i]; TMP_END; } flint-3.1.3/src/nmod_mat/nullspace.c000066400000000000000000000034461461254215100173610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" slong nmod_mat_nullspace(nmod_mat_t X, const nmod_mat_t A) { slong i, j, k, m, n, rank, nullity; slong * p; slong * pivots; slong * nonpivots; nmod_mat_t tmp; m = A->r; n = A->c; p = flint_malloc(sizeof(slong) * FLINT_MAX(m, n)); nmod_mat_init_set(tmp, A); rank = nmod_mat_rref(tmp); nullity = n - rank; nmod_mat_zero(X); if (rank == 0) { for (i = 0; i < nullity; i++) nmod_mat_entry(X, i, i) = UWORD(1); } else if (nullity) { pivots = p; /* length = rank */ nonpivots = p + rank; /* length = nullity */ for (i = j = k = 0; i < rank; i++) { while (nmod_mat_entry(tmp, i, j) == UWORD(0)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) { mp_limb_t c = nmod_mat_entry(tmp, j, nonpivots[i]); nmod_mat_entry(X, pivots[j], i) = nmod_neg(c, A->mod); } nmod_mat_entry(X, nonpivots[i], i) = UWORD(1); } } flint_free(p); nmod_mat_clear(tmp); return nullity; } flint-3.1.3/src/nmod_mat/one.c000066400000000000000000000013311461254215100161430ustar00rootroot00000000000000/* Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" /*Function to convert a square matrix to an identity matrix The matrix is assumed to be a square one*/ void nmod_mat_one(nmod_mat_t mat) { slong i,j; for(i = 0; i < mat->r; i++) for(j = 0; j < mat->c; j++) if(i==j) nmod_mat_entry(mat, i, j) = 1; else nmod_mat_entry(mat, i, j) = 0; } flint-3.1.3/src/nmod_mat/permute_rows.c000066400000000000000000000023011461254215100201130ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "nmod_mat.h" /** Permute rows of a matrix `mat` according to `perm_act`, and propagate the * action on `perm_store`. * That is, performs for each appropriate index `i`, the operations * `perm_store[i] <- perm_store[perm_act[i]]` * `rows[i] <- rows[perm_act[i]]` */ void nmod_mat_permute_rows(nmod_mat_t mat, const slong * perm_act, slong * perm_store) { slong i; mp_limb_t ** mat_tmp = (mp_limb_t **) flint_malloc(mat->r * sizeof(mp_limb_t *)); /* perm_store[i] <- perm_store[perm_act[i]] */ if (perm_store) _perm_compose(perm_store, perm_store, perm_act, mat->r); /* rows[i] <- rows[perm_act[i]] */ for (i = 0; i < mat->r; i++) mat_tmp[i] = mat->rows[perm_act[i]]; for (i = 0; i < mat->r; i++) mat->rows[i] = mat_tmp[i]; flint_free(mat_tmp); } flint-3.1.3/src/nmod_mat/pow.c000066400000000000000000000033071461254215100161740ustar00rootroot00000000000000/* Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void _nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow) { nmod_mat_t temp1, temp2; if (mat->r == 0) { return; } if (pow == 0) { nmod_mat_one(dest); return; } if (pow == 1) { nmod_mat_set(dest, mat); return; } if (pow == 2) { nmod_mat_mul(dest, mat, mat); return; } nmod_mat_init(temp1, mat->r, mat->c, mat->mod.n); if(pow == 3) { nmod_mat_mul(temp1, mat, mat); nmod_mat_mul(dest, temp1, mat); nmod_mat_clear(temp1); return; } nmod_mat_one(dest); nmod_mat_init_set(temp2, mat); while(pow > 0) { if(pow%2 == 1) { nmod_mat_mul(temp1, dest, temp2); nmod_mat_swap_entrywise(temp1, dest); } if (pow > 1) { nmod_mat_mul(temp1, temp2, temp2); nmod_mat_swap_entrywise(temp1, temp2); } pow /= 2; } nmod_mat_clear(temp1); nmod_mat_clear(temp2); } void nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow) { nmod_mat_t temp; if (mat == dest) { nmod_mat_init_set(temp, mat); _nmod_mat_pow(dest, temp, pow); nmod_mat_clear(temp); } else { _nmod_mat_pow(dest, mat, pow); } } flint-3.1.3/src/nmod_mat/profile/000077500000000000000000000000001461254215100166605ustar00rootroot00000000000000flint-3.1.3/src/nmod_mat/profile/p-lu.c000066400000000000000000000057551461254215100177150ustar00rootroot00000000000000/* Copyright 2009 William Hart Copyright 2010, 2021 Fredrik Johansson Copyright 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "thread_support.h" #include "perm.h" typedef struct { slong n; mp_limb_t modulus; int algorithm; } mat_lu_t; void sample(void * arg, ulong count) { mat_lu_t * params = (mat_lu_t *) arg; int algorithm = params->algorithm; slong * P; nmod_mat_t A, LU; ulong i; flint_rand_t state; flint_randinit(state); nmod_mat_init(A, params->n, params->n, params->modulus); nmod_mat_init(LU, params->n, params->n, params->modulus); nmod_mat_randfull(A, state); P = _perm_init(params->n); prof_start(); if (algorithm == 0) for (i = 0; i < count; i++) { nmod_mat_set(LU, A); nmod_mat_lu(P, LU, 0); } else if (algorithm == 1) for (i = 0; i < count; i++) { nmod_mat_set(LU, A); nmod_mat_lu_classical(P, LU, 0); } else if (algorithm == 2) for (i = 0; i < count; i++) { nmod_mat_set(LU, A); nmod_mat_lu_classical_delayed(P, LU, 0); } else for (i = 0; i < count; i++) { nmod_mat_set(LU, A); nmod_mat_lu_recursive(P, LU, 0); } prof_stop(); nmod_mat_clear(A); nmod_mat_clear(LU); _perm_clear(P); flint_randclear(state); } slong bits_tab[] = { 5, 14, 15, 25, 30, 31, 32, 33, 60, 61, 62, 63, 64, 0 }; int main(void) { double max; mat_lu_t params; slong i, bits, n; flint_printf("nmod_mat_lu:\n"); flint_set_num_threads(1); flint_printf("threads = %wd\n", flint_get_num_threads()); for (i = 0; (bits = bits_tab[i]) != 0; i++) { for (n = 4; n <= 1000; n += n/4 + 1) { double min_default = 0, min_classical = 0, min_delayed = 0, min_recursive = 0; params.n = n; params.modulus = n_nextprime(UWORD(1) << (bits - 1), 0); params.algorithm = 0; prof_repeat(&min_default, &max, sample, ¶ms); params.algorithm = 1; prof_repeat(&min_classical, &max, sample, ¶ms); params.algorithm = 2; prof_repeat(&min_delayed, &max, sample, ¶ms); params.algorithm = 3; prof_repeat(&min_recursive, &max, sample, ¶ms); flint_printf("b = %wd n = %wd default %.2f us classical %.2f us delayed %.2f us recursive %.2f us\n", bits, n, min_default, min_classical, min_delayed, min_recursive); } } return 0; } flint-3.1.3/src/nmod_mat/profile/p-mul.c000066400000000000000000000077661461254215100200760ustar00rootroot00000000000000/* Copyright 2009 William Hart Copyright 2010 Fredrik Johansson Copyright 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "thread_support.h" #if FLINT_HAVE_BLAS #include "cblas.h" #endif typedef struct { slong dim_m; slong dim_n; slong dim_k; mp_limb_t modulus; int algorithm; } mat_mul_t; void sample(void * arg, ulong count) { mat_mul_t * params = (mat_mul_t *) arg; int algorithm = params->algorithm; nmod_mat_t A, B, C; ulong i; flint_rand_t state; flint_randinit(state); nmod_mat_init(A, params->dim_m, params->dim_k, params->modulus); nmod_mat_init(B, params->dim_k, params->dim_n, params->modulus); nmod_mat_init(C, params->dim_m, params->dim_n, params->modulus); nmod_mat_randfull(A, state); nmod_mat_randfull(B, state); nmod_mat_randfull(C, state); prof_start(); if (algorithm == 0) for (i = 0; i < count; i++) nmod_mat_mul(C, A, B); else if (algorithm == 1) for (i = 0; i < count; i++) nmod_mat_mul_classical(C, A, B); else if (algorithm == 2) for (i = 0; i < count; i++) nmod_mat_mul_classical_threaded(C, A, B); else if (algorithm == 3) for (i = 0; i < count; i++) nmod_mat_mul_blas(C, A, B); else for (i = 0; i < count; i++) nmod_mat_mul_strassen(C, A, B); prof_stop(); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); flint_randclear(state); } int main(void) { double max; mat_mul_t params; slong dim, i, flint_num, blas_num; flint_printf("nmod_mat_mul:\n"); for (dim = 2; dim <= 100; dim += dim/4 + 1) { double min_classical, min_strassen; params.dim_m = dim; params.dim_n = dim; params.dim_k = dim; params.modulus = 40000; params.algorithm = 1; prof_repeat(&min_classical, &max, sample, ¶ms); params.algorithm = 4; prof_repeat(&min_strassen, &max, sample, ¶ms); flint_printf("dim = %wd, classical %.2f us strassen %.2f us\n", dim, min_classical, min_strassen); } /* output floating point ratios time(mul_blas)/time(mul_blas) */ for (dim = 200; dim <= 1200; dim += 200) { flint_printf("dimension %wd\n", dim); for (flint_num = 2; flint_num <= 8; flint_num += 1) { flint_set_num_threads(flint_num); for (blas_num = flint_num; blas_num <= flint_num; blas_num *= 2) { double min_old, min_new, min_ratio = 100; #if FLINT_HAVE_BLAS openblas_set_num_threads(blas_num); #endif flint_printf("[flint %wd, blas %wd]: (", flint_num, blas_num); for (i = 7; i < FLINT_BITS; i += 8) { params.dim_m = dim; params.dim_n = dim; params.dim_k = dim; params.modulus = 2*(UWORD(1) << i) - 1; params.algorithm = 2; prof_repeat(&min_old, &max, sample, ¶ms); params.algorithm = 0; prof_repeat(&min_new, &max, sample, ¶ms); min_ratio = FLINT_MIN(min_ratio, min_old/min_new); flint_printf(" %.2f ", min_old/min_new); fflush(stdout); } flint_printf(") min %0.2f\n", min_ratio); /* assume that blas gets faster with more threads */ if (min_ratio > 1) break; } } } return 0; } flint-3.1.3/src/nmod_mat/randfull.c000066400000000000000000000011371461254215100171750ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_randfull(nmod_mat_t mat, flint_rand_t state) { slong i; for (i = 0; i < mat->r * mat->c; i++) { mat->entries[i] = FLINT_MAX(1, n_randint(state, mat->mod.n)); } } flint-3.1.3/src/nmod_mat/randops.c000066400000000000000000000032161461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" void nmod_mat_randops(nmod_mat_t mat, flint_rand_t state, slong count) { slong c, i, j, k; slong m = mat->r; slong n = mat->c; if (mat->r == 0 || mat->c == 0) return; for (c = 0; c < count; c++) { if (n_randint(state, 2)) { if ((i = n_randint(state, m)) == (j = n_randint(state, m))) continue; if (n_randint(state, 2)) for (k = 0; k < n; k++) mat->rows[j][k] = nmod_add(mat->rows[j][k], mat->rows[i][k], mat->mod); else for (k = 0; k < n; k++) mat->rows[j][k] = nmod_sub(mat->rows[j][k], mat->rows[i][k], mat->mod); } else { if ((i = n_randint(state, n)) == (j = n_randint(state, n))) continue; if (n_randint(state, 2)) for (k = 0; k < m; k++) mat->rows[k][j] = nmod_add(mat->rows[k][j], mat->rows[k][i], mat->mod); else for (k = 0; k < m; k++) mat->rows[k][j] = nmod_sub(mat->rows[k][j], mat->rows[k][i], mat->mod); } } } flint-3.1.3/src/nmod_mat/randpermdiag.c000066400000000000000000000016731461254215100200300ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "nmod_mat.h" int nmod_mat_randpermdiag(nmod_mat_t mat, flint_rand_t state, mp_srcptr diag, slong n) { int parity; slong i; slong * rows; slong * cols; rows = _perm_init(mat->r); cols = _perm_init(mat->c); parity = _perm_randtest(rows, mat->r, state); parity ^= _perm_randtest(cols, mat->c, state); nmod_mat_zero(mat); for (i = 0; i < n; i++) nmod_mat_entry(mat, rows[i], cols[i]) = diag[i]; _perm_clear(rows); _perm_clear(cols); return parity; } flint-3.1.3/src/nmod_mat/randrank.c000066400000000000000000000017661461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "nmod_vec.h" void nmod_mat_randrank(nmod_mat_t mat, flint_rand_t state, slong rank) { slong i; mp_limb_t * diag; if (rank < 0 || rank > mat->r || rank > mat->c) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_randrank). Impossible rank.\n"); } diag = _nmod_vec_init(rank); if (mat->mod.n != 1) { for (i = 0; i < rank; i++) diag[i] = 1 + n_randint(state, mat->mod.n - 1); } else { for (i = 0; i < rank; i++) diag[i] = 0; } nmod_mat_randpermdiag(mat, state, diag, rank); _nmod_vec_clear(diag); } flint-3.1.3/src/nmod_mat/randtest.c000066400000000000000000000010631461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_randtest(nmod_mat_t mat, flint_rand_t state) { _nmod_vec_randtest(mat->entries, state, mat->r * mat->c, mat->mod); } flint-3.1.3/src/nmod_mat/randtril.c000066400000000000000000000021301461254215100171770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" void nmod_mat_randtril(nmod_mat_t mat, flint_rand_t state, int unit) { slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (j < i) { nmod_mat_entry(mat, i, j) = n_randlimb(state) % (mat->mod.n); } else if (i == j) { nmod_mat_entry(mat, i, j) = n_randlimb(state) % (mat->mod.n); if (unit || nmod_mat_entry(mat, i, j) == UWORD(0)) nmod_mat_entry(mat, i, j) = UWORD(1); } else { nmod_mat_entry(mat, i, j) = UWORD(0); } } } } flint-3.1.3/src/nmod_mat/randtriu.c000066400000000000000000000021301461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" void nmod_mat_randtriu(nmod_mat_t mat, flint_rand_t state, int unit) { slong i, j; for (i = 0; i < mat->r; i++) { for (j = 0; j < mat->c; j++) { if (j > i) { nmod_mat_entry(mat, i, j) = n_randlimb(state) % (mat->mod.n); } else if (i == j) { nmod_mat_entry(mat, i, j) = n_randlimb(state) % (mat->mod.n); if (unit || nmod_mat_entry(mat, i, j) == UWORD(0)) nmod_mat_entry(mat, i, j) = UWORD(1); } else { nmod_mat_entry(mat, i, j) = UWORD(0); } } } } flint-3.1.3/src/nmod_mat/rank.c000066400000000000000000000013741461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" slong nmod_mat_rank(const nmod_mat_t A) { slong m, n, rank; slong * perm; nmod_mat_t tmp; m = A->r; n = A->c; if (m == 0 || n == 0) return 0; nmod_mat_init_set(tmp, A); perm = flint_malloc(sizeof(slong) * m); rank = nmod_mat_lu(perm, tmp, 0); flint_free(perm); nmod_mat_clear(tmp); return rank; } flint-3.1.3/src/nmod_mat/reduce_row.c000066400000000000000000000070241461254215100175250ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" slong nmod_mat_reduce_row(nmod_mat_t M, slong * P, slong * L, slong m) { slong n = M->c, i, j, r, bits, limbs; ulong ** A = M->rows; ulong h, hi, lo; ulong * rowm; slong res = -WORD(1); TMP_INIT; bits = FLINT_BIT_COUNT(M->mod.n)*2 + FLINT_BIT_COUNT(m + 1); limbs = (bits + FLINT_BITS - 1)/FLINT_BITS; TMP_START; rowm = (ulong *) TMP_ALLOC(n*sizeof(ulong)*limbs); flint_mpn_zero(rowm, n*limbs); for (i = 0, j = 0; i < n; i++, j += limbs) rowm[j] = A[m][i]; for (i = 0; i < n; i++) { if (i != 0) { switch (limbs) { case 1: NMOD_RED(A[m][i], rowm[i], M->mod); break; case 2: NMOD2_RED2(A[m][i], rowm[2*i + 1], rowm[2*i], M->mod); break; case 3: NMOD_RED(rowm[3*i + 2], rowm[3*i + 2], M->mod); \ NMOD_RED3(A[m][i], rowm[3*i + 2], rowm[3*i + 1], rowm[3*i], M->mod); break; } } if (A[m][i] != 0) { r = P[i]; if (r != -WORD(1)) { h = n_negmod(A[m][i], M->mod.n); A[m][i] = 0; switch (limbs) { case 1: for (j = i + 1; j < L[r]; j++) rowm[j] += A[r][j]*h; break; case 2: for (j = i + 1; j < L[r]; j++) { umul_ppmm(hi, lo, A[r][j], h); add_ssaaaa(rowm[2*j + 1], rowm[2*j], rowm[2*j + 1], rowm[2*j], hi, lo); } break; case 3: for (j = i + 1; j < L[r]; j++) { umul_ppmm(hi, lo, A[r][j], h); add_sssaaaaaa(rowm[3*j + 2], rowm[3*j + 1], rowm[3*j], rowm[3*j + 2], rowm[3*j + 1], rowm[3*j], 0, hi, lo); } break; } } else { h = n_invmod(A[m][i], M->mod.n); A[m][i] = 1; switch (limbs) { case 1: for (j = i + 1; j < L[m]; j++) { NMOD_RED(A[m][j], rowm[j], M->mod); A[m][j] = n_mulmod2_preinv(A[m][j], h, M->mod.n, M->mod.ninv); } break; case 2: for (j = i + 1; j < L[m]; j++) { NMOD2_RED2(A[m][j], rowm[2*j + 1], rowm[2*j], M->mod); A[m][j] = n_mulmod2_preinv(A[m][j], h, M->mod.n, M->mod.ninv); } break; case 3: for (j = i + 1; j < L[m]; j++) { NMOD_RED(rowm[3*j + 2], rowm[3*j + 2], M->mod); \ NMOD_RED3(A[m][j], rowm[3*j + 2], rowm[3*j + 1], rowm[3*j], M->mod); A[m][j] = n_mulmod2_preinv(A[m][j], h, M->mod.n, M->mod.ninv); } break; } P[i] = m; res = i; break; } } } TMP_END; return res; } flint-3.1.3/src/nmod_mat/rref.c000066400000000000000000000066241461254215100163320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "nmod.h" #include "nmod_mat.h" slong _nmod_mat_rref(nmod_mat_t A, slong * pivots_nonpivots, slong * P) { slong i, j, k, n, rank; slong * pivots; slong * nonpivots; nmod_mat_t U, V; n = A->c; rank = nmod_mat_lu(P, A, 0); if (rank == 0) { for (i = 0; i < n; i++) pivots_nonpivots[i] = i; return rank; } /* Clear L */ for (i = 0; i < A->r; i++) for (j = 0; j < FLINT_MIN(i, rank); j++) nmod_mat_entry(A, i, j) = UWORD(0); /* We now reorder U to proper upper triangular form U | V with U full-rank triangular, set V = U^(-1) V, and then put the column back in the original order. An improvement for some matrices would be to compress V by discarding columns containing nothing but zeros. */ nmod_mat_init(U, rank, rank, A->mod.n); nmod_mat_init(V, rank, n - rank, A->mod.n); pivots = pivots_nonpivots; nonpivots = pivots_nonpivots + rank; for (i = j = k = 0; i < rank; i++) { while (nmod_mat_entry(A, i, j) == UWORD(0)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (i = 0; i < rank; i++) { for (j = 0; j <= i; j++) nmod_mat_entry(U, j, i) = nmod_mat_entry(A, j, pivots[i]); } for (i = 0; i < n - rank; i++) { for (j = 0; j < rank; j++) nmod_mat_entry(V, j, i) = nmod_mat_entry(A, j, nonpivots[i]); } nmod_mat_solve_triu(V, U, V, 0); /* Clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j <= i; j++) nmod_mat_entry(A, j, pivots[i]) = (i == j); } /* Write back the actual content */ for (i = 0; i < n - rank; i++) { for (j = 0; j < rank; j++) nmod_mat_entry(A, j, nonpivots[i]) = nmod_mat_entry(V, j, i); } nmod_mat_clear(U); nmod_mat_clear(V); return rank; } slong nmod_mat_rref(nmod_mat_t A) { slong rank, * pivots_nonpivots, * P; if (nmod_mat_is_empty(A)) return 0; if (A->r == 1) { mp_limb_t c, cinv; slong i, j; slong r = 0; for (i = 0; i < A->c; i++) { c = nmod_mat_entry(A, 0, i); if (c != 0) { r = 1; if (c == 1) break; cinv = nmod_inv(c, A->mod); nmod_mat_set_entry(A, 0, i, 1); for (j = i + 1;j < A->c; j++) { nmod_mat_set_entry(A, 0, j, nmod_mul(nmod_mat_get_entry(A, 0, j), cinv, A->mod)); } break; } } return r; } pivots_nonpivots = flint_malloc(sizeof(slong) * A->c); P = _perm_init(nmod_mat_nrows(A)); rank = _nmod_mat_rref(A, pivots_nonpivots, P); flint_free(pivots_nonpivots); _perm_clear(P); return rank; } flint-3.1.3/src/nmod_mat/scalar.c000066400000000000000000000042521461254215100166340ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2014 Ashish Kedia Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "fmpz.h" void nmod_mat_scalar_addmul_ui(nmod_mat_t dest, const nmod_mat_t X, const nmod_mat_t Y, const mp_limb_t b) { slong i, j; if (b == UWORD(0)) { if (dest != X) nmod_mat_set(dest, X); return; } for (i = 0; i < X->r; i++) { for (j = 0; j < X->c; j++) { nmod_mat_entry(dest, i, j) = n_addmod(nmod_mat_entry(X, i, j), n_mulmod2_preinv(nmod_mat_entry(Y, i, j), b, Y->mod.n, Y->mod.ninv), X->mod.n); } } } #define UWORD_HALF (UWORD_MAX / 2 + 1) void nmod_mat_scalar_mul(nmod_mat_t B, const nmod_mat_t A, mp_limb_t c) { if (c == UWORD(0)) { nmod_mat_zero(B); } else if (c == UWORD(1)) { nmod_mat_set(B, A); } else if (c == A->mod.n - UWORD(1)) { nmod_mat_neg(B, A); } else if (A->r * A->c > 10 && A->mod.n < UWORD_HALF) { slong i, j; mp_limb_t w_pr = n_mulmod_precomp_shoup(c, A->mod.n); for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_mat_entry(B, i, j) = n_mulmod_shoup( c, nmod_mat_entry(A, i, j), w_pr, A->mod.n); } else { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_mat_entry(B, i, j) = n_mulmod2_preinv( nmod_mat_entry(A, i, j), c, A->mod.n, A->mod.ninv); } } void nmod_mat_scalar_mul_fmpz(nmod_mat_t res, const nmod_mat_t M, const fmpz_t c) { nmod_mat_scalar_mul(res, M, fmpz_get_nmod(c, res->mod)); } flint-3.1.3/src/nmod_mat/set.c000066400000000000000000000011641461254215100161610ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_set(nmod_mat_t B, const nmod_mat_t A) { slong i; if (B == A || A->c == 0) return; for (i = 0; i < A->r; i++) _nmod_vec_set(B->rows[i], A->rows[i], A->c); } flint-3.1.3/src/nmod_mat/set_mod.c000066400000000000000000000011341461254215100170150ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" void nmod_mat_set_mod(nmod_mat_t mat, mp_limb_t n) { mat->mod.n = n; mat->mod.norm = flint_clz(n); mat->mod.ninv = n_preinvert_limb_prenorm(n << mat->mod.norm); } flint-3.1.3/src/nmod_mat/similarity.c000066400000000000000000000017231461254215100175550ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" void nmod_mat_similarity(nmod_mat_t M, slong r, ulong d) { slong n = M->r, i, j; ulong ** A = M->rows; for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) NMOD_ADDMUL(A[i][j], A[i][r], d, M->mod); for (j = r + 1; j < n; j++) NMOD_ADDMUL(A[i][j], A[i][r], d, M->mod); } d = n_negmod(d, M->mod.n); for (i = 0; i < n; i++) { for (j = 0; j < r - 1; j++) NMOD_ADDMUL(A[r][i], A[j][i], d, M->mod); for (j = r + 1; j < n; j++) NMOD_ADDMUL(A[r][i], A[j][i], d, M->mod); } } flint-3.1.3/src/nmod_mat/solve.c000066400000000000000000000022721461254215100165170ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" int nmod_mat_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B) { slong i, rank, *perm; nmod_mat_t LU; int result; if (A->r == 0 || B->c == 0) return 1; nmod_mat_init_set(LU, A); perm = flint_malloc(sizeof(slong) * A->r); for (i = 0; i < A->r; i++) perm[i] = i; rank = nmod_mat_lu(perm, LU, 1); if (rank == A->r) { nmod_mat_t PB; nmod_mat_window_init(PB, B, 0, 0, B->r, B->c); for (i = 0; i < A->r; i++) PB->rows[i] = B->rows[perm[i]]; nmod_mat_solve_tril(X, LU, PB, 1); nmod_mat_solve_triu(X, LU, X, 0); nmod_mat_window_clear(PB); result = 1; } else { result = 0; } nmod_mat_clear(LU); flint_free(perm); return result; } flint-3.1.3/src/nmod_mat/solve_tril.c000066400000000000000000000055671461254215100175630ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_solve_tril_classical(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit) { int nlimbs; slong i, j, n, m; nmod_t mod; mp_ptr inv, tmp; n = L->r; m = B->c; mod = L->mod; if (!unit) { inv = _nmod_vec_init(n); for (i = 0; i < n; i++) inv[i] = n_invmod(nmod_mat_entry(L, i, i), mod.n); } else inv = NULL; nlimbs = _nmod_vec_dot_bound_limbs(n, mod); tmp = _nmod_vec_init(n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = nmod_mat_entry(X, j, i); for (j = 0; j < n; j++) { mp_limb_t s; s = _nmod_vec_dot(L->rows[j], tmp, j, mod, nlimbs); s = nmod_sub(nmod_mat_entry(B, j, i), s, mod); if (!unit) s = n_mulmod2_preinv(s, inv[j], mod.n, mod.ninv); tmp[j] = s; } for (j = 0; j < n; j++) nmod_mat_entry(X, j, i) = tmp[j]; } _nmod_vec_clear(tmp); if (!unit) _nmod_vec_clear(inv); } void nmod_mat_solve_tril_recursive(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit) { nmod_mat_t LA, LC, LD, XX, XY, BX, BY; slong r, n, m; n = L->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A 0]^ [X] == [A^ 0 ] [X] == [A^ X] [C D] [Y] == [-D^ C A^ D^] [Y] == [D^ (Y - C A^ X)] */ nmod_mat_window_init(LA, L, 0, 0, r, r); nmod_mat_window_init(LC, L, r, 0, n, r); nmod_mat_window_init(LD, L, r, r, n, n); nmod_mat_window_init(BX, B, 0, 0, r, m); nmod_mat_window_init(BY, B, r, 0, n, m); nmod_mat_window_init(XX, X, 0, 0, r, m); nmod_mat_window_init(XY, X, r, 0, n, m); nmod_mat_solve_tril(XX, LA, BX, unit); nmod_mat_submul(XY, BY, LC, XX); nmod_mat_solve_tril(XY, LD, XY, unit); nmod_mat_window_clear(LA); nmod_mat_window_clear(LC); nmod_mat_window_clear(LD); nmod_mat_window_clear(BX); nmod_mat_window_clear(BY); nmod_mat_window_clear(XX); nmod_mat_window_clear(XY); } void nmod_mat_solve_tril(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit) { if (B->r < NMOD_MAT_SOLVE_TRI_ROWS_CUTOFF || B->c < NMOD_MAT_SOLVE_TRI_COLS_CUTOFF) { nmod_mat_solve_tril_classical(X, L, B, unit); } else { nmod_mat_solve_tril_recursive(X, L, B, unit); } } flint-3.1.3/src/nmod_mat/solve_triu.c000066400000000000000000000056111461254215100175620ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_solve_triu_classical(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit) { int nlimbs; slong i, j, n, m; nmod_t mod; mp_ptr inv, tmp; n = U->r; m = B->c; mod = U->mod; if (!unit) { inv = _nmod_vec_init(n); for (i = 0; i < n; i++) inv[i] = n_invmod(nmod_mat_entry(U, i, i), mod.n); } else inv = NULL; nlimbs = _nmod_vec_dot_bound_limbs(n, mod); tmp = _nmod_vec_init(n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = nmod_mat_entry(X, j, i); for (j = n - 1; j >= 0; j--) { mp_limb_t s; s = _nmod_vec_dot(U->rows[j] + j + 1, tmp + j + 1, n - j - 1, mod, nlimbs); s = nmod_sub(nmod_mat_entry(B, j, i), s, mod); if (!unit) s = n_mulmod2_preinv(s, inv[j], mod.n, mod.ninv); tmp[j] = s; } for (j = 0; j < n; j++) nmod_mat_entry(X, j, i) = tmp[j]; } _nmod_vec_clear(tmp); if (!unit) _nmod_vec_clear(inv); } void nmod_mat_solve_triu_recursive(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit) { nmod_mat_t UA, UB, UD, XX, XY, BX, BY; slong r, n, m; n = U->r; m = B->c; r = n / 2; if (n == 0 || m == 0) return; /* Denoting inv(M) by M^, we have: [A B]^ [X] == [A^ (X - B D^ Y)] [0 D] [Y] == [ D^ Y ] */ nmod_mat_window_init(UA, U, 0, 0, r, r); nmod_mat_window_init(UB, U, 0, r, r, n); nmod_mat_window_init(UD, U, r, r, n, n); nmod_mat_window_init(BX, B, 0, 0, r, m); nmod_mat_window_init(BY, B, r, 0, n, m); nmod_mat_window_init(XX, X, 0, 0, r, m); nmod_mat_window_init(XY, X, r, 0, n, m); nmod_mat_solve_triu(XY, UD, BY, unit); nmod_mat_submul(XX, BX, UB, XY); nmod_mat_solve_triu(XX, UA, XX, unit); nmod_mat_window_clear(UA); nmod_mat_window_clear(UB); nmod_mat_window_clear(UD); nmod_mat_window_clear(BX); nmod_mat_window_clear(BY); nmod_mat_window_clear(XX); nmod_mat_window_clear(XY); } void nmod_mat_solve_triu(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit) { if (B->r < NMOD_MAT_SOLVE_TRI_ROWS_CUTOFF || B->c < NMOD_MAT_SOLVE_TRI_COLS_CUTOFF) { nmod_mat_solve_triu_classical(X, U, B, unit); } else { nmod_mat_solve_triu_recursive(X, U, B, unit); } } flint-3.1.3/src/nmod_mat/solve_vec.c000066400000000000000000000017531461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" int nmod_mat_solve_vec(mp_ptr x, const nmod_mat_t A, mp_srcptr b) { nmod_mat_t X, B; int result; slong i, m; m = A->r; if (m == 0) return 1; /* This is a bit of a hack. There should be a function to create a window into a vector */ nmod_mat_window_init(X, A, 0, 0, m, 1); nmod_mat_window_init(B, A, 0, 0, m, 1); for (i = 0; i < m; i++) X->rows[i] = x + i; for (i = 0; i < m; i++) B->rows[i] = (mp_ptr) (b + i); result = nmod_mat_solve(X, A, B); nmod_mat_window_clear(X); nmod_mat_window_clear(B); return result; } flint-3.1.3/src/nmod_mat/strong_echelon_form.c000066400000000000000000000141261461254215100214240ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" static inline int _nmod_mat_pivot(nmod_mat_t A, slong start_row, slong col) { slong j; mp_ptr u; if (nmod_mat_entry(A, start_row, col) != 0) return 1; for (j = start_row + 1; j < A->r; j++) { if (nmod_mat_entry(A, j, col) != 0) { u = A->rows[j]; A->rows[j] = A->rows[start_row]; A->rows[start_row] = u; return -1; } } return 0; } static void _n_ppio(mp_ptr ppi, mp_ptr ppo, mp_limb_t a, mp_limb_t b) { mp_limb_t c, n, g; c = n_gcd(a, b); n = a/c; g = n_gcd(c, n); while( g != 1 ) { c = c * g; n = n/g; g = n_gcd(c, n); } *ppi = c; *ppo = n; } static mp_limb_t _n_stab(mp_limb_t a, mp_limb_t b, nmod_t N) { mp_limb_t g, s, t; g = n_gcd(a, b); b = n_gcd(g, N.n); _n_ppio(&s, &t, N.n/b, a/b); return t; } static mp_limb_t _n_unit(mp_limb_t a, nmod_t N) { mp_limb_t g, s, l, d; g = n_gcdinv(&s, a, N.n); if (g == 1) { return s; } else { l = N.n/g; d = _n_stab(s, l, N); return nmod_add(s, nmod_mul(d, l, N), N); } } /* test whether q*a = b mod N has a solution */ static int _n_is_divisible(mp_ptr q, mp_limb_t b, mp_limb_t a, nmod_t N) { mp_limb_t e, g; g = n_gcdinv(&e, a, N.n); if (( b % g ) == 0) { *q = nmod_mul(e, b/g, N); return 1; } return 0; } void nmod_mat_strong_echelon_form(nmod_mat_t A) { mp_limb_t s, t, u, v, q, t1, t2, g; slong m, n, row, col, i, k, l; mp_limb_t **r; nmod_t mod; mp_ptr extra_row; if (nmod_mat_is_empty(A)) return; n = A->r; m = A->c; r = A->rows; mod = A->mod; extra_row = _nmod_vec_init(m); row = col = 0; while (row < n && col < m) { if (_nmod_mat_pivot(A, row, col) == 0) { col++; continue; } for (i = row + 1; i < n; i++) { if (nmod_mat_entry(A, i, col) == 0) { continue; } if (_n_is_divisible(&s, nmod_mat_entry(A, i, col), nmod_mat_entry(A, row, col), mod)) { for (k = col; k < m; k++) { t1 = nmod_sub(nmod_mat_entry(A, i, k), nmod_mul(s, nmod_mat_entry(A, row, k), mod), mod); nmod_mat_entry(A, i, k) = t1; } } else { if (nmod_mat_entry(A, row, col) >= nmod_mat_entry(A, i, col)) { g = n_xgcd(&s, &t, nmod_mat_entry(A, row, col), nmod_mat_entry(A, i, col)); } else { g = n_xgcd(&t, &s, nmod_mat_entry(A, i, col), nmod_mat_entry(A, row, col)); } /* now g = a*x - b*y a,b < x < mod.n */ t = nmod_neg(t, mod); u = (nmod_mat_entry(A, i, col))/g; u = nmod_neg(u, mod); v = (nmod_mat_entry(A, row, col))/g; /* now g = a*x + b*y and 0 = sv - tu = 1 modulo mod.n */ for (k = col; k < m; k++) { t1 = nmod_add(nmod_mul(s, nmod_mat_entry(A, row, k), mod), nmod_mul(t, nmod_mat_entry(A, i, k), mod), mod); t2 = nmod_add(nmod_mul(u, nmod_mat_entry(A, row, k), mod), nmod_mul(v, nmod_mat_entry(A, i, k), mod), mod); nmod_mat_entry(A, row, k) = t1; nmod_mat_entry(A, i, k) = t2; } } } row++; col++; } for (col = 0; col < m; col++) { if (nmod_mat_entry(A, col, col) != 0) { u = _n_unit(nmod_mat_entry(A, col, col), mod); for (k = col; k < m; k++) { nmod_mat_entry(A, col, k) = nmod_mul(u, nmod_mat_entry(A, col, k), mod); } for (row = 0; row < col ; row++) { q = nmod_mat_entry(A, row, col)/nmod_mat_entry(A, col, col); for (l = row; l< m; l++) { s = nmod_sub(nmod_mat_entry(A, row, l), nmod_mul(q, nmod_mat_entry(A, col, l), mod), mod); nmod_mat_entry(A, row, l) = s; } } g = n_gcd(mod.n, nmod_mat_entry(A, col, col)); if (g == 1) { continue; } g = mod.n/g; _nmod_vec_scalar_mul_nmod(extra_row, r[col], m, g, mod); } else { _nmod_vec_set(extra_row, r[col], m); } for (row = col + 1; row < m; row++) { if(nmod_mat_entry(A, row, row) >= extra_row[row]) { g = n_xgcd(&s, &t, nmod_mat_entry(A, row, row), extra_row[row]); } else { g = n_xgcd(&t, &s, extra_row[row], nmod_mat_entry(A, row, row)); } if (g == 0) { continue; } t = nmod_neg(t, mod); u = extra_row[row]/g; u = nmod_neg(u, mod); v = (nmod_mat_entry(A, row, row))/g; /* now g = a*x + b*y and 0 = sv - tu = 1 modulo mod.n */ for (k = row; k < m; k++) { t1 = nmod_add(nmod_mul(s, nmod_mat_entry(A, row, k), mod), nmod_mul(t, extra_row[k], mod), mod); t2 = nmod_add(nmod_mul(u, nmod_mat_entry(A, row, k), mod), nmod_mul(v, extra_row[k], mod), mod); nmod_mat_entry(A, row, k) = t1; extra_row[k] = t2; } } } _nmod_vec_clear(extra_row); } flint-3.1.3/src/nmod_mat/sub.c000066400000000000000000000012361461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_sub(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong i; if (C->c == 0) return; for (i = 0; i < C->r; i++) { _nmod_vec_sub(C->rows[i], A->rows[i], B->rows[i], C->c, C->mod); } } flint-3.1.3/src/nmod_mat/submul.c000066400000000000000000000020431461254215100166720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_submul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong m, k, n, cutoff; m = A->r; k = A->c; n = B->c; if (FLINT_BITS == 64 && C->mod.n < 2048) cutoff = 400; else cutoff = 200; if (flint_get_num_threads() == 1 && (m < cutoff || n < cutoff || k < cutoff)) { _nmod_mat_mul_classical_op(D, C, A, B, -1); } else { nmod_mat_t tmp; nmod_mat_init(tmp, m, n, A->mod.n); nmod_mat_mul(tmp, A, B); nmod_mat_sub(D, C, tmp); nmod_mat_clear(tmp); } } flint-3.1.3/src/nmod_mat/swap.c000066400000000000000000000007711461254215100163430ustar00rootroot00000000000000/* Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_swap(nmod_mat_t mat1, nmod_mat_t mat2) { FLINT_SWAP(nmod_mat_struct, *mat1, *mat2); } flint-3.1.3/src/nmod_mat/test/000077500000000000000000000000001461254215100161775ustar00rootroot00000000000000flint-3.1.3/src/nmod_mat/test/main.c000066400000000000000000000071551461254215100172770ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-addmul.c" #include "t-can_solve.c" #include "t-charpoly_berkowitz.c" #include "t-charpoly.c" #include "t-charpoly_danilevsky.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-det.c" #include "t-det_howell.c" #include "t-howell_form.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-invert_rows_cols.c" #include "t-lu_classical.c" #include "t-lu_classical_delayed.c" #include "t-lu_recursive.c" #include "t-minpoly.c" #include "t-mul_blas.c" #include "t-mul.c" #include "t-mul_classical_threaded.c" #include "t-mul_nmod_vec.c" #include "t-mul_strassen.c" #include "t-neg.c" #include "t-nmod_vec_mul.c" #include "t-nullspace.c" #include "t-permute_rows.c" #include "t-pow.c" #include "t-rank.c" #include "t-rref.c" #include "t-scalar_addmul_ui.c" #include "t-scalar_mul.c" #include "t-solve.c" #include "t-solve_tril.c" #include "t-solve_tril_classical.c" #include "t-solve_tril_recursive.c" #include "t-solve_triu.c" #include "t-solve_triu_classical.c" #include "t-solve_triu_recursive.c" #include "t-solve_vec.c" #include "t-submul.c" #include "t-trace.c" #include "t-transpose.c" #include "t-window_init_clear.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_mat_add), TEST_FUNCTION(nmod_mat_addmul), TEST_FUNCTION(nmod_mat_can_solve), TEST_FUNCTION(nmod_mat_charpoly_berkowitz), TEST_FUNCTION(nmod_mat_charpoly), TEST_FUNCTION(nmod_mat_charpoly_danilevsky), TEST_FUNCTION(nmod_mat_concat_horizontal), TEST_FUNCTION(nmod_mat_concat_vertical), TEST_FUNCTION(nmod_mat_det), TEST_FUNCTION(nmod_mat_det_howell), TEST_FUNCTION(nmod_mat_howell_form), TEST_FUNCTION(nmod_mat_init_clear), TEST_FUNCTION(nmod_mat_inv), TEST_FUNCTION(nmod_mat_invert_rows_cols), TEST_FUNCTION(nmod_mat_lu_classical), TEST_FUNCTION(nmod_mat_lu_classical_delayed), TEST_FUNCTION(nmod_mat_lu_recursive), TEST_FUNCTION(nmod_mat_minpoly), TEST_FUNCTION(nmod_mat_mul_blas), TEST_FUNCTION(nmod_mat_mul), TEST_FUNCTION(nmod_mat_mul_classical_threaded), TEST_FUNCTION(nmod_mat_mul_nmod_vec), TEST_FUNCTION(nmod_mat_mul_strassen), TEST_FUNCTION(nmod_mat_neg), TEST_FUNCTION(nmod_mat_nmod_vec_mul), TEST_FUNCTION(nmod_mat_nullspace), TEST_FUNCTION(nmod_mat_permute_rows), TEST_FUNCTION(nmod_mat_pow), TEST_FUNCTION(nmod_mat_rank), TEST_FUNCTION(nmod_mat_rref), TEST_FUNCTION(nmod_mat_scalar_addmul_ui), TEST_FUNCTION(nmod_mat_scalar_mul), TEST_FUNCTION(nmod_mat_solve), TEST_FUNCTION(nmod_mat_solve_tril), TEST_FUNCTION(nmod_mat_solve_tril_classical), TEST_FUNCTION(nmod_mat_solve_tril_recursive), TEST_FUNCTION(nmod_mat_solve_triu), TEST_FUNCTION(nmod_mat_solve_triu_classical), TEST_FUNCTION(nmod_mat_solve_triu_recursive), TEST_FUNCTION(nmod_mat_solve_vec), TEST_FUNCTION(nmod_mat_submul), TEST_FUNCTION(nmod_mat_trace), TEST_FUNCTION(nmod_mat_transpose), TEST_FUNCTION(nmod_mat_window_init_clear) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod_mat/test/t-add.c000066400000000000000000000023041461254215100173330ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_add, state) { slong m, n, mod, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C, D; m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(C, m, n, mod); nmod_mat_init(D, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_add(C, A, B); nmod_mat_sub(C, C, B); if (!nmod_mat_equal(C, A)) TEST_FUNCTION_FAIL(""); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-addmul.c000066400000000000000000000044221461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_addmul, state) { slong i; for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D, T, E; mp_limb_t mod = n_randtest_not_zero(state); slong m, k, n; m = n_randint(state, 100); k = n_randint(state, 100); n = n_randint(state, 100); /* Force Strassen test */ if (i < 5) { m += 300; k += 300; n += 300; } nmod_mat_init(A, m, k, mod); nmod_mat_init(B, k, n, mod); nmod_mat_init(C, m, n, mod); nmod_mat_init(D, m, n, mod); nmod_mat_init(T, m, n, mod); nmod_mat_init(E, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_randtest(C, state); nmod_mat_addmul(D, C, A, B); nmod_mat_mul(T, A, B); nmod_mat_add(E, C, T); if (!nmod_mat_equal(D, E)) TEST_FUNCTION_FAIL( "Results not equal\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n" "E = %{nmod_mat}\n", A, B, C, D, E); /* Check aliasing */ nmod_mat_addmul(C, C, A, B); if (!nmod_mat_equal(C, E)) TEST_FUNCTION_FAIL( "Results not equal (aliasing)\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n" "E = %{nmod_mat}\n", A, B, C, D, E); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); nmod_mat_clear(E); nmod_mat_clear(T); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-can_solve.c000066400000000000000000000055321461254215100205620ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_can_solve, state) { nmod_mat_t A, X, X2, B, AX; slong i, k, m, n; mp_limb_t mod; int solved; /* test random systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); mod = n_randtest_prime(state, 0); nmod_mat_init(A, m, k, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(X, k, n, mod); nmod_mat_init(AX, m, n, mod); nmod_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1)); nmod_mat_randtest(B, state); /* Dense */ if (n_randint(state, 2)) nmod_mat_randops(A, state, 1+n_randint(state, 1+m*m)); solved = nmod_mat_can_solve(X, A, B); nmod_mat_mul(AX, A, X); if (solved && !nmod_mat_equal(AX, B)) TEST_FUNCTION_FAIL( "AX != B\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "X = %{nmod_mat}\n" "AX = %{nmod_mat}\n", A, B, X, AX); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(AX); } /* test random solvable systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); mod = n_randtest_prime(state, 0); nmod_mat_init(A, m, k, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(X, k, n, mod); nmod_mat_init(X2, k, n, mod); nmod_mat_init(AX, m, n, mod); nmod_mat_randrank(A, state, n_randint(state, FLINT_MIN(m, k) + 1)); nmod_mat_randtest(X2, state); nmod_mat_mul(B, A, X2); solved = nmod_mat_can_solve(X, A, B); nmod_mat_mul(AX, A, X); if (!solved || !nmod_mat_equal(B, AX)) TEST_FUNCTION_FAIL( "AX != B\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "X = %{nmod_mat}\n" "AX = %{nmod_mat}\n", A, B, X, AX); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(X2); nmod_mat_clear(AX); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-charpoly.c000066400000000000000000000051571461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_mat_charpoly, state) { slong m, n, rep, i; ulong mod; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C, D; nmod_poly_t f, g; m = n_randint(state, 10); n = m; mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(C, m, m, mod); nmod_mat_init(D, n, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_mul(C, A, B); nmod_mat_mul(D, B, A); nmod_mat_charpoly(f, C); nmod_mat_charpoly(g, D); if (!nmod_poly_equal(f, g)) TEST_FUNCTION_FAIL( "charpoly(AB) != charpoly(BA)\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "cp(AB) = %{nmod_poly}\n" "cp(BA) = %{nmod_poly}\n", A, B, f, g); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); nmod_poly_clear(f); nmod_poly_clear(g); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A; nmod_poly_t f, g; m = n_randint(state, 10); n = m; mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_mat_randtest(A, state); nmod_mat_charpoly(f, A); for (i = 0; i < 10; i++) nmod_mat_similarity(A, n_randint(state, m), n_randint(state, mod)); nmod_mat_charpoly(g, A); if (!nmod_poly_equal(f, g)) TEST_FUNCTION_FAIL( "charpoly(P^{-1}AP) != charpoly(A)\n" "A = %{nmod_mat}\n" "cp(A) = %{nmod_poly}\n" "cp(P^{-1}AP) = %{nmod_poly}\n", A, f, g); nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-charpoly_berkowitz.c000066400000000000000000000052271461254215100225330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_charpoly_berkowitz, state) { slong m, n, rep, i; ulong mod; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C, D; nmod_poly_t f, g; m = n_randint(state, 10); n = m; mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(C, m, m, mod); nmod_mat_init(D, n, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_mul(C, A, B); nmod_mat_mul(D, B, A); nmod_mat_charpoly_berkowitz(f, C); nmod_mat_charpoly_berkowitz(g, D); if (!nmod_poly_equal(f, g)) TEST_FUNCTION_FAIL( "charpoly(AB) != charpoly(BA)\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "cp(AB) = %{nmod_poly}\n" "cp(BA) = %{nmod_poly}\n", A, B, f, g); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); nmod_poly_clear(f); nmod_poly_clear(g); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A; nmod_poly_t f, g; m = n_randint(state, 10); n = m; mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_mat_randtest(A, state); nmod_mat_charpoly_berkowitz(f, A); for (i = 0; i < 10; i++) nmod_mat_similarity(A, n_randint(state, m), n_randint(state, mod)); nmod_mat_charpoly(g, A); if (!nmod_poly_equal(f, g)) TEST_FUNCTION_FAIL( "charpoly(P^{-1}AP) != charpoly(A)\n" "A = %{nmod_mat}\n" "cp(A) = %{nmod_poly}\n" "cp(P^{-1}AP) = %{nmod_poly}\n", A, f, g); nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-charpoly_danilevsky.c000066400000000000000000000052611461254215100226620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_mat_charpoly_danilevsky, state) { slong m, n, rep, i; ulong mod; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C, D; nmod_poly_t f, g; m = n_randint(state, 10); n = m; mod = n_randprime(state, 6, 0); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(C, m, m, mod); nmod_mat_init(D, n, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_mul(C, A, B); nmod_mat_mul(D, B, A); nmod_mat_charpoly_danilevsky(f, C); nmod_mat_charpoly_danilevsky(g, D); if (!nmod_poly_equal(f, g)) TEST_FUNCTION_FAIL( "charpoly(AB) != charpoly(BA)\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "cp(AB) = %{nmod_poly}\n" "cp(BA) = %{nmod_poly}\n", A, B, f, g); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); nmod_poly_clear(f); nmod_poly_clear(g); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A; nmod_poly_t f, g; m = n_randint(state, 10); n = m; mod = n_randprime(state, 6, 0); nmod_mat_init(A, m, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_mat_randtest(A, state); nmod_mat_charpoly(f, A); for (i = 0; i < 10; i++) nmod_mat_similarity(A, n_randint(state, m), n_randint(state, mod)); nmod_mat_charpoly_danilevsky(g, A); if (!nmod_poly_equal(f, g)) TEST_FUNCTION_FAIL( "charpoly(P^{-1}AP) != charpoly(A)\n" "A = %{nmod_mat}\n" "cp(A) = %{nmod_poly}\n" "cp(P^{-1}AP) = %{nmod_poly}\n", A, f, g); nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-concat_horizontal.c000066400000000000000000000032051461254215100223240ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_concat_horizontal, state) { nmod_mat_t A, B, C; nmod_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong c1, c2, r1, n; c1 = n_randint(state, 50); c2 = n_randint(state, 50); r1 = n_randint(state, 50); n = n_randint(state, 50) + 1; nmod_mat_init(A, r1, c1, n); nmod_mat_init(B, r1, c2, n); nmod_mat_init(C, r1, c1 + c2, n); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_randtest(C, state); nmod_mat_concat_horizontal(C, A, B); nmod_mat_window_init(window1, C, 0, 0, r1, c1); nmod_mat_window_init(window2, C, 0, c1, r1, c1 + c2); if (!(nmod_mat_equal(window1, A) && nmod_mat_equal(window2, B))) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "A concat_horizontal B = %{nmod_mat}\n", A, B, C); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_window_clear(window1); nmod_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-concat_vertical.c000066400000000000000000000031771461254215100217540ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_concat_vertical, state) { nmod_mat_t A, B, C; nmod_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong r1, r2, c1, n; r1 = n_randint(state, 50); r2 = n_randint(state, 50); c1 = n_randint(state, 50); n = n_randint(state, 50) + 1; nmod_mat_init(A, r1, c1, n); nmod_mat_init(B, r2, c1, n); nmod_mat_init(C, (r1+r2), c1, n); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_randtest(C, state); nmod_mat_concat_vertical(C, A, B); nmod_mat_window_init(window1, C, 0, 0, r1, c1); nmod_mat_window_init(window2, C, r1, 0, (r1+r2), c1); if (!(nmod_mat_equal(window1, A) && nmod_mat_equal(window2, B))) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "A concat_vertical B = %{nmod_mat}\n", A, B, C); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_window_clear(window1); nmod_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-det.c000066400000000000000000000034301461254215100173600ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(nmod_mat_det, state) { slong m, mod, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A; fmpz_mat_t B; mp_limb_t Adet; fmpz_t Bdet; ulong t; m = n_randint(state, 30); mod = n_randtest(state); mod += mod == 0; nmod_mat_init(A, m, m, mod); fmpz_mat_init(B, m, m); switch (rep % 3) { case 0: nmod_mat_randrank(A, state, m); nmod_mat_randops(A, state, n_randint(state, 2*m + 1)); break; case 1: t = n_randint(state, m); t = FLINT_MIN(t, m); nmod_mat_randrank(A, state, t); nmod_mat_randops(A, state, n_randint(state, 2*m + 1)); break; default: nmod_mat_randtest(A, state); } fmpz_mat_set_nmod_mat_unsigned(B, A); Adet = nmod_mat_det(A); fmpz_init(Bdet); fmpz_mat_det_bareiss(Bdet, B); fmpz_mod_ui(Bdet, Bdet, mod); if (Adet != fmpz_get_ui(Bdet)) TEST_FUNCTION_FAIL("Adet = %wu, Bdet = %wu\n", Adet, fmpz_get_ui(Bdet)); nmod_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(Bdet); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-det_howell.c000066400000000000000000000034511461254215100207350ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" #include "fmpz.h" #include "fmpz_mat.h" TEST_FUNCTION_START(nmod_mat_det_howell, state) { slong m, mod, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A; fmpz_mat_t B; mp_limb_t Adet; fmpz_t Bdet; ulong t; m = n_randint(state, 30); mod = n_randtest(state); mod += mod == 0; nmod_mat_init(A, m, m, mod); fmpz_mat_init(B, m, m); switch (rep % 3) { case 0: nmod_mat_randrank(A, state, m); nmod_mat_randops(A, state, n_randint(state, 2*m + 1)); break; case 1: t = n_randint(state, m); t = FLINT_MIN(t, m); nmod_mat_randrank(A, state, t); nmod_mat_randops(A, state, n_randint(state, 2*m + 1)); break; default: nmod_mat_randtest(A, state); } fmpz_mat_set_nmod_mat_unsigned(B, A); Adet = nmod_mat_det_howell(A); fmpz_init(Bdet); fmpz_mat_det_bareiss(Bdet, B); fmpz_mod_ui(Bdet, Bdet, mod); if (Adet != fmpz_get_ui(Bdet)) TEST_FUNCTION_FAIL("Adet = %wu, Bdet = %wu\n", Adet, fmpz_get_ui(Bdet)); nmod_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(Bdet); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-howell_form.c000066400000000000000000000137371461254215100211340ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" int nmod_mat_is_in_howell_form(const nmod_mat_t A) { slong *pivots; slong i, j, r; int numberpivots = 0; int prevrowzero = 0; mp_ptr extra_row; mp_limb_t g; if (nmod_mat_is_zero(A)) return 1; pivots = flint_malloc(A->r * sizeof(slong)); if (!nmod_mat_is_zero_row(A, 0)) { for (j = 0; j < A->c; j++) { if (nmod_mat_entry(A, 0, j)) { if ((A->mod).n % nmod_mat_entry(A, 0, j)) { flint_free(pivots); return 0; } pivots[numberpivots] = j; numberpivots++; break; } } } else { prevrowzero = 1; } for (i = 1; i < A->r; i++) { if (!nmod_mat_is_zero_row(A, i)) { if (prevrowzero) { flint_free(pivots); return 0; } for (j = 0; j < A->c; j++) { if (nmod_mat_entry(A, i, j)) { if (j <= pivots[numberpivots - 1]) { flint_free(pivots); return 0; } if ((A->mod).n % nmod_mat_entry(A, i, j)) { flint_free(pivots); return 0; } pivots[numberpivots] = j; numberpivots++; j = A->c; } } } else { prevrowzero = 1; } } for (i = 1; i < numberpivots; i++) { for (j = 0; j < i; j++) { if (nmod_mat_entry(A, j, pivots[i]) >= nmod_mat_entry(A, i, pivots[i])) { flint_free(pivots); return 0; } } } extra_row = _nmod_vec_init(A->c); for (i = 0; i < numberpivots; i++) { g = n_gcd(A->mod.n, nmod_mat_entry(A, i, pivots[i])); if (g == 1) { continue; } g = A->mod.n/g; _nmod_vec_scalar_mul_nmod(extra_row, A->rows[i], A->c, g, A->mod); for ( j = pivots[i] + 1; j < A->c; j++) { if (extra_row[j]) { for ( r = i; r < numberpivots; r++) { if (pivots[r] == j) { if(!(extra_row[j] % nmod_mat_entry(A, r, pivots[r]))) { g = extra_row[j]/nmod_mat_entry(A, r, pivots[r]); _nmod_vec_scalar_addmul_nmod(extra_row, A->rows[r], A->c, nmod_neg(g, A->mod), A->mod); } } } } } if (!_nmod_vec_is_zero(extra_row, A->c)) { _nmod_vec_clear(extra_row); flint_free(pivots); return 0; } } _nmod_vec_clear(extra_row); flint_free(pivots); return 1; } TEST_FUNCTION_START(nmod_mat_howell_form, state) { slong i; for (i = 0; i < 10000*flint_test_multiplier(); i++) { nmod_mat_t A, B, D; mp_limb_t mod; slong j, k, m, n, r1, r2; slong *perm; int equal; mp_limb_t c; mod = n_randtest_not_zero(state); m = n_randint(state, 20); do { n = n_randint(state, 20); } while (n > m); perm = _perm_init(2*m); nmod_mat_init(A, m, n, mod); nmod_mat_init(D, 2*m, n, mod); nmod_mat_randtest(A, state); nmod_mat_init_set(B, A); r1 = nmod_mat_howell_form(B); if (!nmod_mat_is_in_howell_form(B)) TEST_FUNCTION_FAIL( "Malformed Howell form\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); _perm_randtest(perm, 2 * m, state); /* Concatenate the original matrix with the Howell form, scramble the rows, and check that the Howell form is the same */ for (j = 0; j < m; j++) { do { c = n_randint(state, mod); } while ( n_gcd(c, mod) != 1); for (k = 0; k < n; k++) nmod_mat_entry(D, perm[j], k) = nmod_mul(nmod_mat_entry(A, j, k), c, A->mod); } for (j = 0; j < m; j++) { do { c = n_randint(state, mod); } while ( n_gcd(c, mod) != 1); for (k = 0; k < n; k++) nmod_mat_entry(D, perm[m + j], k) = nmod_mul(nmod_mat_entry(B, j, k), c, A->mod); } r2 = nmod_mat_howell_form(D); equal = (r1 == r2); if (equal) { for (j = 0; j < r1; j++) for (k = 0; k < n; k++) equal = equal && (nmod_mat_entry(B, j, k) == nmod_mat_entry(D, j, k)); for (j = r1; j < 2*m; j++) for (k = 0; k < n; k++) equal = equal && (nmod_mat_entry(D, j, k) == 0); } if (!equal) TEST_FUNCTION_FAIL( "r1 = %wd, r2 = %wd\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "D = %{nmod_mat}\n", r1, r2, A, B, D); _perm_clear(perm); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-init_clear.c000066400000000000000000000020661461254215100207210ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_init_clear, state) { slong m, n, mod, i, j, rep; for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { nmod_mat_t A; m = n_randint(state, 50); n = n_randint(state, 50); mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); for (i = 0; i < m; i++) for (j = 0; j < n; j++) if (A->rows[i][j] != UWORD(0)) TEST_FUNCTION_FAIL("entries not zero\n"); if (A->mod.n != mod) TEST_FUNCTION_FAIL("bad modulus\n"); nmod_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-inv.c000066400000000000000000000053101461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_inv, state) { nmod_mat_t A, B, C, I; slong i, j, m, r; mp_limb_t mod; int result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); mod = n_randtest_prime(state, 0); nmod_mat_init(A, m, m, mod); nmod_mat_init(B, m, m, mod); nmod_mat_init(C, m, m, mod); nmod_mat_init(I, m, m, mod); for (j = 0; j < m; j++) I->rows[j][j] = UWORD(1); /* Verify that A * A^-1 = I for random matrices */ nmod_mat_randrank(A, state, m); /* Dense or sparse? */ if (n_randint(state, 2)) nmod_mat_randops(A, state, 1+n_randint(state, 1+m*m)); result = nmod_mat_inv(B, A); nmod_mat_mul(C, A, B); if (!nmod_mat_equal(C, I) || !result) TEST_FUNCTION_FAIL( "A * A^-1 != I\n" "A = %{nmod_mat}\n" "A^-1 = %{nmod_mat}\n" "A * A^-1 = %{nmod_mat}\n", A, B, C); /* Test aliasing */ nmod_mat_set(C, A); nmod_mat_inv(A, A); nmod_mat_mul(B, A, C); if (!nmod_mat_equal(B, I)) TEST_FUNCTION_FAIL( "Aliasing failed\n" "A = %{nmod_mat}\n", C); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(I); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 20); mod = n_randtest_prime(state, 0); r = n_randint(state, m); nmod_mat_init(A, m, m, mod); nmod_mat_init(B, m, m, mod); nmod_mat_randrank(A, state, r); /* Dense */ if (n_randint(state, 2)) nmod_mat_randops(A, state, 1+n_randint(state, 1+m*m)); result = nmod_mat_inv(B, A); if (result) TEST_FUNCTION_FAIL("singular matrix reported as invertible\n"); /* Aliasing */ result = nmod_mat_inv(A, A); if (result) TEST_FUNCTION_FAIL("singular matrix reported as invertible\n"); nmod_mat_clear(A); nmod_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-invert_rows_cols.c000066400000000000000000000027441461254215100222140ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_invert_rows_cols, state) { slong m, n, mod, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B; slong i, j; m = n_randint(state, 10); n = n_randint(state, 10); mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_set(B, A); nmod_mat_invert_rows(A, NULL); nmod_mat_invert_cols(A, NULL); for (i = 0; i < A->r; i++) { for (j =0; j < A->c; j++) { if (nmod_mat_entry(B, i, j) != nmod_mat_entry(A, A->r - i - 1, A->c - j - 1)) TEST_FUNCTION_FAIL( "B != A\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); } } nmod_mat_clear(A); nmod_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-lu_classical.c000066400000000000000000000067161461254215100212540ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" /* Defined in t-lu_classical.c, t-lu_classical_delayed.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(nmod_mat_t A, slong * P) { slong i; mp_ptr * tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(mp_ptr) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu_classical.c, t-lu_classical_delayed.c and t-lu_recursive.c */ #ifndef check #define check check int check(slong * P, nmod_mat_t LU, const nmod_mat_t A, slong rank) { nmod_mat_t B, L, U; slong m, n, i, j; m = A->r; n = A->c; nmod_mat_init(B, m, n, A->mod.n); nmod_mat_init(L, m, m, A->mod.n); nmod_mat_init(U, m, n, A->mod.n); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) for (j = i; j < n; j++) if (nmod_mat_entry(LU, i, j) != 0) return 1; for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) nmod_mat_entry(L, i, j) = nmod_mat_entry(LU, i, j); if (i < rank) nmod_mat_entry(L, i, i) = UWORD(1); for (j = i; j < n; j++) nmod_mat_entry(U, i, j) = nmod_mat_entry(LU, i, j); } nmod_mat_mul(B, L, U); perm(B, P); if (!nmod_mat_equal(A, B)) return 2; nmod_mat_clear(B); nmod_mat_clear(L); nmod_mat_clear(U); return 0; } #endif TEST_FUNCTION_START(nmod_mat_lu_classical, state) { slong i; int result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, LU; mp_limb_t mod; slong m, n, r, d, rank; slong * P; m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_prime(state, 0); for (r = 0; r <= FLINT_MIN(m, n); r++) { nmod_mat_init(A, m, n, mod); nmod_mat_randrank(A, state, r); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); nmod_mat_randops(A, state, d); } nmod_mat_init_set(LU, A); P = flint_malloc(sizeof(slong) * m); rank = nmod_mat_lu_classical(P, LU, 0); result = (r == rank); if (!result) TEST_FUNCTION_FAIL( "Wrong rank\n" "A = %{nmod_mat}\n" "LU = %{nmod_mat}\n", A, LU); result = check(P, LU, A, rank); if (result != 0) { if (result == 1) TEST_FUNCTION_FAIL("Wrong shape\n"); else if (result == 2) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "LU = %{nmod_mat}\n", A, LU); } nmod_mat_clear(A); nmod_mat_clear(LU); flint_free(P); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-lu_classical_delayed.c000066400000000000000000000110221461254215100227250ustar00rootroot00000000000000/* Copyright (C) 2010, 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "perm.h" #include "nmod_mat.h" /* Defined in t-lu_classical.c, t-lu_classical_delayed.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(nmod_mat_t A, slong * P) { slong i; mp_ptr * tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(mp_ptr) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu_classical.c, t-lu_classical_delayed.c and t-lu_recursive.c */ #ifndef check #define check check int check(slong * P, nmod_mat_t LU, const nmod_mat_t A, slong rank) { nmod_mat_t B, L, U; slong m, n, i, j; m = A->r; n = A->c; nmod_mat_init(B, m, n, A->mod.n); nmod_mat_init(L, m, m, A->mod.n); nmod_mat_init(U, m, n, A->mod.n); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) for (j = i; j < n; j++) if (nmod_mat_entry(LU, i, j) != 0) return 1; for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) nmod_mat_entry(L, i, j) = nmod_mat_entry(LU, i, j); if (i < rank) nmod_mat_entry(L, i, i) = UWORD(1); for (j = i; j < n; j++) nmod_mat_entry(U, i, j) = nmod_mat_entry(LU, i, j); } nmod_mat_mul(B, L, U); perm(B, P); if (!nmod_mat_equal(A, B)) return 2; nmod_mat_clear(B); nmod_mat_clear(L); nmod_mat_clear(U); return 0; } #endif TEST_FUNCTION_START(nmod_mat_lu_classical_delayed, state) { slong i; int result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, LU, LU2; mp_limb_t mod; slong m, n, r, d, rank, rank2; slong *P, *P2; m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_prime(state, 0); for (r = 0; r <= FLINT_MIN(m, n); r++) { nmod_mat_init(A, m, n, mod); nmod_mat_randrank(A, state, r); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); nmod_mat_randops(A, state, d); } nmod_mat_init_set(LU, A); P = flint_malloc(sizeof(slong) * m); rank = nmod_mat_lu_classical_delayed(P, LU, 0); if (r != rank) TEST_FUNCTION_FAIL( "Wrong rank\n" "A = %{nmod_mat}\n" "LU = %{nmod_mat}\n", A, LU); result = check(P, LU, A, rank); if (result != 0) { if (result == 1) TEST_FUNCTION_FAIL("Wrong shape\n"); else if (result == 2) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "LU = %{nmod_mat}\n", A, LU); } nmod_mat_init_set(LU2, A); P2 = flint_malloc(sizeof(slong) * m); rank2 = nmod_mat_lu_classical(P2, LU2, 0); if (r != rank || !nmod_mat_equal(LU, LU2) || !_perm_equal(P, P2, m)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "LU = %{nmod_mat}\n" "LU2 = %{nmod_mat}\n", A, LU, LU2); nmod_mat_set(LU, A); rank = nmod_mat_lu_classical_delayed(P, LU, 1); nmod_mat_set(LU2, A); rank2 = nmod_mat_lu_classical(P2, LU2, 1); if (rank != rank2 || (rank == r && (!nmod_mat_equal(LU, LU2) || !_perm_equal(P, P2, m)))) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "r = %wd, rank = %wd, rank2 = %wd\n" "LU = %{nmod_mat}\n" "LU2 = %{nmod_mat}\n", A, r, rank, rank2, LU, LU2); nmod_mat_clear(A); nmod_mat_clear(LU); flint_free(P); nmod_mat_clear(LU2); flint_free(P2); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-lu_recursive.c000066400000000000000000000066541461254215100213260ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" /* Defined in t-lu_classical.c, t-lu_classical_delayed.c and t-lu_recursive.c */ #ifndef perm #define perm perm void perm(nmod_mat_t A, slong * P) { slong i; mp_ptr * tmp; if (A->c == 0 || A->r == 0) return; tmp = flint_malloc(sizeof(mp_ptr) * A->r); for (i = 0; i < A->r; i++) tmp[P[i]] = A->rows[i]; for (i = 0; i < A->r; i++) A->rows[i] = tmp[i]; flint_free(tmp); } #endif /* Defined in t-lu_classical.c, t-lu_classical_delayed.c and t-lu_recursive.c */ #ifndef check #define check check int check(slong * P, nmod_mat_t LU, const nmod_mat_t A, slong rank) { nmod_mat_t B, L, U; slong m, n, i, j; m = A->r; n = A->c; nmod_mat_init(B, m, n, A->mod.n); nmod_mat_init(L, m, m, A->mod.n); nmod_mat_init(U, m, n, A->mod.n); rank = FLINT_ABS(rank); for (i = rank; i < FLINT_MIN(m, n); i++) for (j = i; j < n; j++) if (nmod_mat_entry(LU, i, j) != 0) return 1; for (i = 0; i < m; i++) { for (j = 0; j < FLINT_MIN(i, n); j++) nmod_mat_entry(L, i, j) = nmod_mat_entry(LU, i, j); if (i < rank) nmod_mat_entry(L, i, i) = UWORD(1); for (j = i; j < n; j++) nmod_mat_entry(U, i, j) = nmod_mat_entry(LU, i, j); } nmod_mat_mul(B, L, U); perm(B, P); if (!nmod_mat_equal(A, B)) return 2; nmod_mat_clear(B); nmod_mat_clear(L); nmod_mat_clear(U); return 0; } #endif TEST_FUNCTION_START(nmod_mat_lu_recursive, state) { slong i; int result; for (i = 0; i < 2000 * flint_test_multiplier(); i++) { nmod_mat_t A, LU; mp_limb_t mod; slong m, n, r, d, rank; slong * P; m = n_randint(state, 30); n = n_randint(state, 30); mod = n_randtest_prime(state, 0); for (r = 0; r <= FLINT_MIN(m, n); r++) { nmod_mat_init(A, m, n, mod); nmod_mat_randrank(A, state, r); if (n_randint(state, 2)) { d = n_randint(state, 2*m*n + 1); nmod_mat_randops(A, state, d); } nmod_mat_init_set(LU, A); P = flint_malloc(sizeof(slong) * m); rank = nmod_mat_lu_recursive(P, LU, 0); if (r != rank) TEST_FUNCTION_FAIL( "Wrong rank\n" "A = %{nmod_mat}\n" "LU = %{nmod_mat}\n", A, LU); result = check(P, LU, A, rank); if (result != 0) { if (result == 1) TEST_FUNCTION_FAIL("Wrong shape\n"); else if (result == 2) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "LU = %{nmod_mat}\n", A, LU); } nmod_mat_clear(A); nmod_mat_clear(LU); flint_free(P); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-minpoly.c000066400000000000000000000053701461254215100203000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_mat_minpoly, state) { slong m, n, rep, i, j; ulong mod; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A; nmod_poly_t f, g, q, r; m = n_randint(state, 10); n = m; mod = n_randprime(state, 6, 0); nmod_mat_init(A, m, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_init(q, mod); nmod_poly_init(r, mod); nmod_mat_randtest(A, state); nmod_mat_minpoly(f, A); nmod_mat_charpoly(g, A); nmod_poly_divrem(q, r, g, f); if (!nmod_poly_is_zero(r)) TEST_FUNCTION_FAIL( "minpoly(A) does not divide charpoly(BA)\n" "A = %{nmod_mat}\n" "mp(A) = %{nmod_poly}\n" "cp(A) = %{nmod_poly}\n", A, f, g); nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(q); nmod_poly_clear(r); } for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A; nmod_poly_t f, g; m = n_randint(state, 10); n = m; mod = n_randprime(state, 6, 0); nmod_mat_init(A, m, n, mod); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_mat_randtest(A, state); for (i = 0; i < n/2; i++) { for (j = 0; j < n/2; j++) { A->rows[i + n/2][j] = 0; A->rows[i][j + n/2] = 0; A->rows[i + n/2][j + n/2] = A->rows[i][j]; } } nmod_mat_minpoly(f, A); for (i = 0; i < 10; i++) nmod_mat_similarity(A, n_randint(state, m), n_randint(state, mod)); nmod_mat_minpoly(g, A); if (!nmod_poly_equal(f, g)) TEST_FUNCTION_FAIL( "minpoly(P^{-1}AP) != minpoly(A)\n" "A = %{nmod_mat}\n" "mp(A) = %{nmod_poly}\n" "mp(P^{-1}AP) = %{nmod_poly}\n", A, f, g); nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-mul.c000066400000000000000000000075421461254215100174110ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_mat.h" /* Defined in t-mul.c and t-mul_classical_threaded.c */ #ifndef nmod_mat_mul_check #define nmod_mat_mul_check nmod_mat_mul_check void nmod_mat_mul_check(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong i, j, k; mp_limb_t s0, s1, s2; mp_limb_t t0, t1; for (i = 0; i < A->r; i++) { for (j = 0; j < B->c; j++) { s0 = s1 = s2 = UWORD(0); for (k = 0; k < A->c; k++) { umul_ppmm(t1, t0, A->rows[i][k], B->rows[k][j]); add_sssaaaaaa(s2, s1, s0, s2, s1, s0, 0, t1, t0); } NMOD_RED(s2, s2, C->mod); NMOD_RED3(s0, s2, s1, s0, C->mod); C->rows[i][j] = s0; } } } #endif TEST_FUNCTION_START(nmod_mat_mul, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D; mp_limb_t mod; slong m, k, n; m = n_randint(state, 75); k = n_randint(state, 75); n = n_randint(state, 75); /* We want to generate matrices with many entries close to half or full limbs with high probability, to stress overflow handling */ switch (n_randint(state, 3)) { case 0: mod = n_randtest_not_zero(state); break; case 1: mod = UWORD_MAX/2 + 1 - n_randbits(state, 4); break; case 2: default: mod = UWORD_MAX - n_randbits(state, 4); break; } nmod_mat_init(A, m, n, mod); nmod_mat_init(B, n, k, mod); nmod_mat_init(C, m, k, mod); nmod_mat_init(D, m, k, mod); if (n_randint(state, 2)) nmod_mat_randtest(A, state); else nmod_mat_randfull(A, state); if (n_randint(state, 2)) nmod_mat_randtest(B, state); else nmod_mat_randfull(B, state); nmod_mat_randtest(C, state); /* make sure noise in the output is ok */ nmod_mat_mul(C, A, B); nmod_mat_mul_check(D, A, B); if (!nmod_mat_equal(C, D)) TEST_FUNCTION_FAIL( "Results not equal\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n", A, B, C, D); if (n == k) { nmod_mat_mul(A, A, B); if (!nmod_mat_equal(A, C)) TEST_FUNCTION_FAIL("Aliasing failed\n"); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } /* Test aliasing with windows */ { nmod_mat_t A, B, A_window; nmod_mat_init(A, 2, 2, 3); nmod_mat_init(B, 2, 2, 3); nmod_mat_window_init(A_window, A, 0, 0, 2, 2); nmod_mat_one(A); nmod_mat_one(B); nmod_mat_entry(B, 0, 1) = 1; nmod_mat_entry(B, 1, 0) = 1; nmod_mat_mul(A_window, B, A_window); if (!nmod_mat_equal(A, B)) TEST_FUNCTION_FAIL( "Window aliasing failed\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); nmod_mat_window_clear(A_window); nmod_mat_clear(A); nmod_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-mul_blas.c000066400000000000000000000052631461254215100204100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" /* generate a worst case matrix for blas */ void nmod_mat_randfull_half(nmod_mat_t mat, flint_rand_t state) { slong i, j; slong r = mat->r; slong c = mat->c; for (i = 0; i < r; i++) for (j = 0; j < c; j++) { mat->rows[i][j] = mat->mod.n/2; if (mat->mod.n > 2 && (mat->mod.n % 2)) mat->rows[i][j] += n_randint(state, 2); } } TEST_FUNCTION_START(nmod_mat_mul_blas, state) { slong i, max_threads = 5; for (i = 0; i < 1 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D; mp_limb_t modulus; slong m, k, n; m = n_randint(state, 150) + 2; k = n_randint(state, 150) + 2; n = n_randint(state, 150) + 2; /* We want to generate matrices with many entries close to half or full limbs with high probability, to stress overflow handling */ switch (n_randint(state, 3)) { case 0: modulus = n_randtest_not_zero(state); break; case 1: modulus = UWORD_MAX/2 + 1 - n_randbits(state, 4); break; default: modulus = UWORD_MAX - n_randbits(state, 4); break; } nmod_mat_init(A, m, n, modulus); nmod_mat_init(B, n, k, modulus); nmod_mat_init(C, m, k, modulus); nmod_mat_init(D, m, k, modulus); if (n_randint(state, 2)) nmod_mat_randfull_half(A, state); else nmod_mat_randfull(A, state); if (n_randint(state, 2)) nmod_mat_randfull_half(B, state); else nmod_mat_randfull(B, state); nmod_mat_randtest(C, state); flint_set_num_threads(n_randint(state, max_threads) + 1); if (nmod_mat_mul_blas(C, A, B)) { nmod_mat_mul_classical(D, A, B); if (!nmod_mat_equal(C, D)) TEST_FUNCTION_FAIL("m: %wd, k: %wd, n: %wd, mod: %wu\n", m, k, n, modulus); } #if FLINT_USES_BLAS && FLINT_BITS == 64 else TEST_FUNCTION_FAIL("BLAS should have worked\n"); #endif nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-mul_classical_threaded.c000066400000000000000000000065051461254215100232650ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_mat.h" #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) # include "thread_support.h" #endif /* Defined in t-mul.c and t-mul_classical_threaded.c */ #ifndef nmod_mat_mul_check #define nmod_mat_mul_check nmod_mat_mul_check void nmod_mat_mul_check(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B) { slong i, j, k; mp_limb_t s0, s1, s2; mp_limb_t t0, t1; for (i = 0; i < A->r; i++) { for (j = 0; j < B->c; j++) { s0 = s1 = s2 = UWORD(0); for (k = 0; k < A->c; k++) { umul_ppmm(t1, t0, A->rows[i][k], B->rows[k][j]); add_sssaaaaaa(s2, s1, s0, s2, s1, s0, 0, t1, t0); } NMOD_RED(s2, s2, C->mod); NMOD_RED3(s0, s2, s1, s0, C->mod); C->rows[i][j] = s0; } } } #endif TEST_FUNCTION_START(nmod_mat_mul_classical_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) slong i, max_threads = 5; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D; mp_limb_t mod; slong m, k, n; flint_set_num_threads(n_randint(state, max_threads) + 1); m = n_randint(state, 50); k = n_randint(state, 50); n = n_randint(state, 50); /* We want to generate matrices with many entries close to half or full limbs with high probability, to stress overflow handling */ switch (n_randint(state, 3)) { case 0: mod = n_randtest_not_zero(state); break; case 1: mod = UWORD_MAX/2 + 1 - n_randbits(state, 4); break; case 2: default: mod = UWORD_MAX - n_randbits(state, 4); break; } nmod_mat_init(A, m, n, mod); nmod_mat_init(B, n, k, mod); nmod_mat_init(C, m, k, mod); nmod_mat_init(D, m, k, mod); if (n_randint(state, 2)) nmod_mat_randtest(A, state); else nmod_mat_randfull(A, state); if (n_randint(state, 2)) nmod_mat_randtest(B, state); else nmod_mat_randfull(B, state); nmod_mat_randtest(C, state); /* make sure noise in the output is ok */ nmod_mat_mul_classical_threaded(C, A, B); nmod_mat_mul_check(D, A, B); if (!nmod_mat_equal(C, D)) TEST_FUNCTION_FAIL( "Results not equal\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n", A, B, C, D); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/nmod_mat/test/t-mul_nmod_vec.c000066400000000000000000000045621461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_vec.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_mul_nmod_vec, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t p; nmod_mat_t A, B, C; mp_limb_t * b, * c; mp_limb_t ** bb, ** cc; slong j, m, n, blen; p = n_randtest_not_zero(state); m = n_randint(state, 50); n = n_randint(state, 50); blen = n_randint(state, 50); nmod_mat_init(C, m, 1, p); nmod_mat_init(A, m, n, p); nmod_mat_init(B, n, 1, p); c = _nmod_vec_init(m); b = _nmod_vec_init(blen); nmod_mat_randtest(A, state); _nmod_vec_randtest(c, state, m, A->mod); _nmod_vec_randtest(b, state, blen, A->mod); cc = FLINT_ARRAY_ALLOC(m, mp_limb_t*); for (j = 0; j < m; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, mp_limb_t); cc[j][0] = c[j]; } bb = FLINT_ARRAY_ALLOC(blen, mp_limb_t*); for (j = 0; j < blen; j++) { bb[j] = FLINT_ARRAY_ALLOC(1, mp_limb_t); bb[j][0] = b[j]; } nmod_mat_mul_nmod_vec(c, A, b, blen); nmod_mat_mul_nmod_vec_ptr(cc, A, (const mp_limb_t * const *)bb, blen); /* supposed to match mul of the chopped or zero-extended b */ for (j = 0; j < n && j < blen; j++) nmod_mat_entry(B, j, 0) = b[j]; nmod_mat_mul(C, A, B); for (j = 0; j < m; j++) if (nmod_mat_entry(C, j, 0) != c[j] || nmod_mat_entry(C, j, 0) != cc[j][0]) TEST_FUNCTION_FAIL(""); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); _nmod_vec_clear(c); _nmod_vec_clear(b); for (j = 0; j < m; j++) { flint_free(cc[j]); } flint_free(cc); for (j = 0; j < blen; j++) { flint_free(bb[j]); } flint_free(bb); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-mul_strassen.c000066400000000000000000000027721461254215100213330ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_mul_strassen, state) { slong i; for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D; mp_limb_t mod = n_randtest_not_zero(state); slong m, k, n; m = n_randint(state, 400); k = n_randint(state, 400); n = n_randint(state, 400); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, n, k, mod); nmod_mat_init(C, m, k, mod); nmod_mat_init(D, m, k, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_mul_classical(C, A, B); nmod_mat_mul_strassen(D, A, B); if (!nmod_mat_equal(C, D)) TEST_FUNCTION_FAIL( "Results not equal\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n", A, B, C, D); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-neg.c000066400000000000000000000025421461254215100173600ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_neg, state) { slong m, n, mod, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C, D; m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(C, m, n, mod); nmod_mat_init(D, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_sub(C, A, B); nmod_mat_neg(B, B); nmod_mat_add(D, A, B); if (!nmod_mat_equal(C, D)) TEST_FUNCTION_FAIL(""); nmod_mat_neg(C, B); nmod_mat_neg(B, B); if (!nmod_mat_equal(C, B)) TEST_FUNCTION_FAIL(""); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-nmod_vec_mul.c000066400000000000000000000045621461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_vec.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_nmod_vec_mul, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t p; nmod_mat_t A, B, C; mp_limb_t * a, * c; mp_limb_t ** aa, ** cc; slong j, m, n, alen; p = n_randtest_not_zero(state); m = n_randint(state, 50); n = n_randint(state, 50); alen = n_randint(state, 50); nmod_mat_init(C, 1, n, p); nmod_mat_init(A, 1, m, p); nmod_mat_init(B, m, n, p); c = _nmod_vec_init(n); a = _nmod_vec_init(alen); nmod_mat_randtest(B, state); _nmod_vec_randtest(c, state, n, B->mod); _nmod_vec_randtest(a, state, alen, B->mod); cc = FLINT_ARRAY_ALLOC(n, mp_limb_t*); for (j = 0; j < n; j++) { cc[j] = FLINT_ARRAY_ALLOC(1, mp_limb_t); cc[j][0] = c[j]; } aa = FLINT_ARRAY_ALLOC(alen, mp_limb_t*); for (j = 0; j < alen; j++) { aa[j] = FLINT_ARRAY_ALLOC(1, mp_limb_t); aa[j][0] = a[j]; } nmod_mat_nmod_vec_mul(c, a, alen, B); nmod_mat_nmod_vec_mul_ptr(cc, (const mp_limb_t * const *)aa, alen, B); /* supposed to match mul of the chopped or zero-extended a */ for (j = 0; j < m && j < alen; j++) nmod_mat_entry(A, 0, j) = a[j]; nmod_mat_mul(C, A, B); for (j = 0; j < n; j++) if (nmod_mat_entry(C, 0, j) != c[j] || nmod_mat_entry(C, 0, j) != cc[j][0]) TEST_FUNCTION_FAIL(""); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); _nmod_vec_clear(c); _nmod_vec_clear(a); for (j = 0; j < n; j++) { flint_free(cc[j]); } flint_free(cc); for (j = 0; j < alen; j++) { flint_free(aa[j]); } flint_free(aa); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-nullspace.c000066400000000000000000000037621461254215100206020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_nullspace, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, B, ker; mp_limb_t mod; slong m, n, d, r, nullity, nulrank; m = n_randint(state, 30); n = n_randint(state, 30); for (r = 0; r <= FLINT_MIN(m,n); r++) { mod = n_randtest_prime(state, 0); d = n_randint(state, 2*m*n + 1); nmod_mat_init(A, m, n, mod); nmod_mat_init(ker, n, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_randrank(A, state, r); /* Densify */ if (n_randlimb(state) % 2) nmod_mat_randops(A, state, d); nullity = nmod_mat_nullspace(ker, A); nulrank = nmod_mat_rank(ker); if (nullity != nulrank) TEST_FUNCTION_FAIL( "rank(ker) != nullity\n" "A = %{nmod_mat}\n", A); if (nullity + r != n) TEST_FUNCTION_FAIL( "nullity + rank != n\n" "A = %{nmod_mat}\n", A); nmod_mat_mul(B, A, ker); if (nmod_mat_rank(B) != 0) TEST_FUNCTION_FAIL( "A * ker != 0\n" "A = %{nmod_mat}\n", A); nmod_mat_clear(A); nmod_mat_clear(ker); nmod_mat_clear(B); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-permute_rows.c000066400000000000000000000046171461254215100213470ustar00rootroot00000000000000/* Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_permute_rows, state) { slong m, n, mod, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t mat, matt; slong * perm_act; slong * perm_store; slong * perm; slong i, j; m = n_randint(state, 10); n = n_randint(state, 10); mod = n_randtest_not_zero(state); nmod_mat_init(mat, m, n, mod); nmod_mat_randtest(mat, state); perm_act = _perm_init(m); _perm_randtest(perm_act, m, state); perm_store = _perm_init(m); _perm_randtest(perm_store, m, state); /* perm = copy of perm_store for testing purpose */ perm = _perm_init(m); for (i = 0; i < m; i++) perm[i] = perm_store[i]; nmod_mat_init_set(matt, mat); nmod_mat_permute_rows(matt, perm_act, perm_store); for (i = 0; i < m; i++) { if (perm_store && perm_store[i] != perm[perm_act[i]]) TEST_FUNCTION_FAIL( "auxiliary permutation not correctly permuted by perm_act\n" "m = %wd\n" "input permutation: %{slong*}\n" "acting permutation: %{slong*}\n" "resulting permutation: %{slong*}\n", m, perm, m, perm_act, m, perm_store, m); for (j = 0; j < n; j++) { if (nmod_mat_entry(matt, i, j) != nmod_mat_entry(mat, perm_act[i], j)) TEST_FUNCTION_FAIL( "matrix not correctly row-permuted by perm_act\n" "first matrix = %{nmod_mat}\n" "second matrix = %{nmod_mat}\n", mat, matt); } } nmod_mat_clear(mat); nmod_mat_clear(matt); _perm_clear(perm_act); _perm_clear(perm); _perm_clear(perm_store); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-pow.c000066400000000000000000000030641461254215100174140ustar00rootroot00000000000000/* Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_pow, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D; mp_limb_t mod; slong m, j; ulong exp; mod = n_randtest_not_zero(state); m = n_randint(state, 20); exp = n_randint(state, 50); nmod_mat_init(A, m, m, mod); nmod_mat_init(B, m, m, mod); nmod_mat_init(C, m, m, mod); nmod_mat_init(D, m, m, mod); nmod_mat_randtest(A, state); nmod_mat_pow(B, A, exp); nmod_mat_one(C); for(j = 1; j <= exp; j++) { nmod_mat_mul(D, C, A); nmod_mat_swap(D, C); } nmod_mat_pow(A, A, exp); if (!(nmod_mat_equal(C, B) && nmod_mat_equal(C, A))) TEST_FUNCTION_FAIL( "Results not equal\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n", A, B, C); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-rank.c000066400000000000000000000035011461254215100175360ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_rank, state) { nmod_mat_t A; slong i, m, n, d, r; mp_limb_t mod; /* Maximally sparse matrices of given rank */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_prime(state, 0); for (r = 0; r <= FLINT_MIN(m,n); r++) { nmod_mat_init(A, m, n, mod); nmod_mat_randrank(A, state, r); /* flint_printf("SPARSE %wd\n", r); nmod_mat_print_pretty(A); */ if (r != nmod_mat_rank(A)) TEST_FUNCTION_FAIL("Wrong rank\n"); nmod_mat_clear(A); } } /* Dense */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_prime(state, 0); for (r = 0; r <= FLINT_MIN(m,n); r++) { d = n_randint(state, 2*m*n + 1); nmod_mat_init(A, m, n, mod); nmod_mat_randrank(A, state, r); nmod_mat_randops(A, state, d); /* flint_printf("DENSE %wd %wd\n", r, d); nmod_mat_print_pretty(A); */ if (r != nmod_mat_rank(A)) TEST_FUNCTION_FAIL("Wrong rank\n"); nmod_mat_clear(A); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-rref.c000066400000000000000000000073661461254215100175560ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" #include "nmod.h" #include "nmod_mat.h" int check_rref_form(slong * perm, nmod_mat_t A, slong rank) { slong i, j, k, prev_pivot; /* bottom should be zero */ for (i = rank; i < A->r; i++) for (j = 0; j < A->c; j++) if (nmod_mat_entry(A, i, j) != 0) return 0; prev_pivot = -1; for (i = 0; i < rank; i++) { for (j = 0; j < A->c; j++) { if (nmod_mat_entry(A, i, j) != 0) { /* pivot should have a higher column index than previous */ if (j <= prev_pivot) return 0; /* column should be 0 ... 0 1 0 ... 0 */ for (k = 0; k < rank; k++) if (nmod_mat_entry(A, k, j) != (i == k)) return 0; prev_pivot = j; break; } } } return 1; } TEST_FUNCTION_START(nmod_mat_rref, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D; mp_limb_t mod; slong j, k, m, n, rank1, rank2; slong *perm; int equal; mp_limb_t c; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); perm = _perm_init(2*m); nmod_mat_init(A, m, n, mod); nmod_mat_init(D, 2*m, n, mod); nmod_mat_randtest(A, state); nmod_mat_init_set(B, A); nmod_mat_init_set(C, A); rank1 = nmod_mat_rref(B); if (!check_rref_form(perm, B, rank1)) TEST_FUNCTION_FAIL( "Malformed rref\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { do { c = n_randint(state, mod); } while (c == 0); for (k = 0; k < n; k++) nmod_mat_entry(D, perm[j], k) = nmod_mul(nmod_mat_entry(A, j, k), c, A->mod); } for (j = 0; j < m; j++) { do { c = n_randint(state, mod); } while (c == 0); for (k = 0; k < n; k++) nmod_mat_entry(D, perm[m + j], k) = nmod_mul(nmod_mat_entry(B, j, k), c, A->mod); } rank2 = nmod_mat_rref(D); equal = (rank1 == rank2); if (equal) { for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) equal = equal && (nmod_mat_entry(B, j, k) == nmod_mat_entry(D, j, k)); for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) equal = equal && (nmod_mat_entry(D, j, k) == 0); } if (!equal) TEST_FUNCTION_FAIL( "rank1 = %wd, rank2 = %wd\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "D = %{nmod_mat}\n", rank1, rank2, A, B, D); _perm_clear(perm); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-scalar_addmul_ui.c000066400000000000000000000027711461254215100221030ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_scalar_addmul_ui, state) { slong m, n, mod, rep; mp_limb_t x; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C, D; m = n_randint(state, 40); n = n_randint(state, 40); mod = n_randtest_not_zero(state); x = n_randint(state, mod); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(C, m, n, mod); nmod_mat_init(D, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_scalar_mul(C, A, x); nmod_mat_add(C, B, C); nmod_mat_scalar_addmul_ui(D, B, A, x); if (!nmod_mat_equal(C, D)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n", A, B, C, D); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-scalar_mul.c000066400000000000000000000030551461254215100207310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_scalar_mul, state) { slong m, n, mod, rep; for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C, D; mp_limb_t c; m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_not_zero(state); c = n_randint(state, mod); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(C, m, n, mod); nmod_mat_init(D, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_scalar_mul(C, A, c); nmod_mat_scalar_mul(D, A, nmod_sub(c, UWORD(1), A->mod)); /* c*A - (c-1)*A == A */ nmod_mat_sub(D, C, D); if (!nmod_mat_equal(A, D)) TEST_FUNCTION_FAIL(""); /* Aliasing */ nmod_mat_scalar_mul(C, A, c); nmod_mat_scalar_mul(A, A, c); if (!nmod_mat_equal(A, C)) TEST_FUNCTION_FAIL(""); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve.c000066400000000000000000000051401461254215100177340ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve, state) { nmod_mat_t A, X, B, AX; slong i, m, n, r; mp_limb_t mod; int solved; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_prime(state, 0); nmod_mat_init(A, m, m, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(X, m, n, mod); nmod_mat_init(AX, m, n, mod); nmod_mat_randrank(A, state, m); nmod_mat_randtest(B, state); /* Dense */ if (n_randint(state, 2)) nmod_mat_randops(A, state, 1+n_randint(state, 1+m*m)); solved = nmod_mat_solve(X, A, B); nmod_mat_mul(AX, A, X); if (!nmod_mat_equal(AX, B) || !solved) TEST_FUNCTION_FAIL( "AX != B\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "X = %{nmod_mat}\n" "AX = %{nmod_mat}\n", A, B, X, AX); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(AX); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 20); n = 1 + n_randint(state, 20); r = n_randint(state, m); mod = n_randtest_prime(state, 0); nmod_mat_init(A, m, m, mod); nmod_mat_init(B, m, n, mod); nmod_mat_init(X, m, n, mod); nmod_mat_init(AX, m, n, mod); nmod_mat_randrank(A, state, r); nmod_mat_randtest(B, state); /* Dense */ if (n_randint(state, 2)) nmod_mat_randops(A, state, 1+n_randint(state, 1+m*m)); solved = nmod_mat_solve(X, A, B); if (solved) TEST_FUNCTION_FAIL( "singular system was 'solved'\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "X = %{nmod_mat}\n", A, B, X); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(AX); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve_tril.c000066400000000000000000000035631461254215100207750ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve_tril, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mat_t A, X, B, Y; mp_limb_t m; slong rows, cols; int unit; m = n_randtest_prime(state, 0); rows = n_randint(state, 200); cols = n_randint(state, 200); unit = n_randint(state, 2); nmod_mat_init(A, rows, rows, m); nmod_mat_init(B, rows, cols, m); nmod_mat_init(X, rows, cols, m); nmod_mat_init(Y, rows, cols, m); nmod_mat_randtril(A, state, unit); nmod_mat_randtest(X, state); nmod_mat_mul(B, A, X); /* Check Y = A^(-1) * (A * X) = X */ nmod_mat_solve_tril(Y, A, B, unit); if (!nmod_mat_equal(Y, X)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "X = %{nmod_mat}\n" "B = %{nmod_mat}\n" "Y = %{nmod_mat}\n", A, X, B, Y); /* Check aliasing */ nmod_mat_solve_tril(B, A, B, unit); if (!nmod_mat_equal(B, X)) TEST_FUNCTION_FAIL( "Aliasing test failed\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve_tril_classical.c000066400000000000000000000036221461254215100230070ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve_tril_classical, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mat_t A, X, B, Y; mp_limb_t m; slong rows, cols; int unit; m = n_randtest_prime(state, 0); rows = n_randint(state, 100); cols = n_randint(state, 100); unit = n_randint(state, 2); nmod_mat_init(A, rows, rows, m); nmod_mat_init(B, rows, cols, m); nmod_mat_init(X, rows, cols, m); nmod_mat_init(Y, rows, cols, m); nmod_mat_randtril(A, state, unit); nmod_mat_randtest(X, state); nmod_mat_mul(B, A, X); /* Check Y = A^(-1) * (A * X) = X */ nmod_mat_solve_tril_classical(Y, A, B, unit); if (!nmod_mat_equal(Y, X)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "X = %{nmod_mat}\n" "B = %{nmod_mat}\n" "Y = %{nmod_mat}\n", A, X, B, Y); /* Check aliasing */ nmod_mat_solve_tril_classical(B, A, B, unit); if (!nmod_mat_equal(B, X)) TEST_FUNCTION_FAIL( "Aliasing test failed\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve_tril_recursive.c000066400000000000000000000036221461254215100230600ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve_tril_recursive, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mat_t A, X, B, Y; mp_limb_t m; slong rows, cols; int unit; m = n_randtest_prime(state, 0); rows = n_randint(state, 100); cols = n_randint(state, 100); unit = n_randint(state, 2); nmod_mat_init(A, rows, rows, m); nmod_mat_init(B, rows, cols, m); nmod_mat_init(X, rows, cols, m); nmod_mat_init(Y, rows, cols, m); nmod_mat_randtril(A, state, unit); nmod_mat_randtest(X, state); nmod_mat_mul(B, A, X); /* Check Y = A^(-1) * (A * X) = X */ nmod_mat_solve_tril_recursive(Y, A, B, unit); if (!nmod_mat_equal(Y, X)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "X = %{nmod_mat}\n" "B = %{nmod_mat}\n" "Y = %{nmod_mat}\n", A, X, B, Y); /* Check aliasing */ nmod_mat_solve_tril_recursive(B, A, B, unit); if (!nmod_mat_equal(B, X)) TEST_FUNCTION_FAIL( "Aliasing test failed\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve_triu.c000066400000000000000000000035631461254215100210060ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve_triu, state) { slong i; for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mat_t A, X, B, Y; mp_limb_t m; slong rows, cols; int unit; m = n_randtest_prime(state, 0); rows = n_randint(state, 200); cols = n_randint(state, 200); unit = n_randint(state, 2); nmod_mat_init(A, rows, rows, m); nmod_mat_init(B, rows, cols, m); nmod_mat_init(X, rows, cols, m); nmod_mat_init(Y, rows, cols, m); nmod_mat_randtriu(A, state, unit); nmod_mat_randtest(X, state); nmod_mat_mul(B, A, X); /* Check Y = A^(-1) * (A * X) = X */ nmod_mat_solve_triu(Y, A, B, unit); if (!nmod_mat_equal(Y, X)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "X = %{nmod_mat}\n" "B = %{nmod_mat}\n" "Y = %{nmod_mat}\n", A, X, B, Y); /* Check aliasing */ nmod_mat_solve_triu(B, A, B, unit); if (!nmod_mat_equal(B, X)) TEST_FUNCTION_FAIL( "Aliasing test failed\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve_triu_classical.c000066400000000000000000000036221461254215100230200ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve_triu_classical, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mat_t A, X, B, Y; mp_limb_t m; slong rows, cols; int unit; m = n_randtest_prime(state, 0); rows = n_randint(state, 100); cols = n_randint(state, 100); unit = n_randint(state, 2); nmod_mat_init(A, rows, rows, m); nmod_mat_init(B, rows, cols, m); nmod_mat_init(X, rows, cols, m); nmod_mat_init(Y, rows, cols, m); nmod_mat_randtriu(A, state, unit); nmod_mat_randtest(X, state); nmod_mat_mul(B, A, X); /* Check Y = A^(-1) * (A * X) = X */ nmod_mat_solve_triu_classical(Y, A, B, unit); if (!nmod_mat_equal(Y, X)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "X = %{nmod_mat}\n" "B = %{nmod_mat}\n" "Y = %{nmod_mat}\n", A, X, B, Y); /* Check aliasing */ nmod_mat_solve_triu_classical(B, A, B, unit); if (!nmod_mat_equal(B, X)) TEST_FUNCTION_FAIL( "Aliasing test failed\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve_triu_recursive.c000066400000000000000000000036221461254215100230710ustar00rootroot00000000000000/* Copyright (C) 2010,2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve_triu_recursive, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mat_t A, X, B, Y; mp_limb_t m; slong rows, cols; int unit; m = n_randtest_prime(state, 0); rows = n_randint(state, 100); cols = n_randint(state, 100); unit = n_randint(state, 2); nmod_mat_init(A, rows, rows, m); nmod_mat_init(B, rows, cols, m); nmod_mat_init(X, rows, cols, m); nmod_mat_init(Y, rows, cols, m); nmod_mat_randtriu(A, state, unit); nmod_mat_randtest(X, state); nmod_mat_mul(B, A, X); /* Check Y = A^(-1) * (A * X) = X */ nmod_mat_solve_triu_recursive(Y, A, B, unit); if (!nmod_mat_equal(Y, X)) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "X = %{nmod_mat}\n" "B = %{nmod_mat}\n" "Y = %{nmod_mat}\n", A, X, B, Y); /* Check aliasing */ nmod_mat_solve_triu_recursive(B, A, B, unit); if (!nmod_mat_equal(B, X)) TEST_FUNCTION_FAIL( "Aliasing test failed\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n", A, B); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-solve_vec.c000066400000000000000000000046321461254215100205760ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_solve_vec, state) { nmod_mat_t A, x, b, Ax; slong i, m, r; int solved; mp_limb_t mod; for (i = 0; i < 2000 * flint_test_multiplier(); i++) { m = n_randint(state, 20); mod = n_randtest_prime(state, 0); nmod_mat_init(A, m, m, mod); nmod_mat_init(b, m, 1, mod); nmod_mat_init(x, m, 1, mod); nmod_mat_init(Ax, m, 1, mod); nmod_mat_randrank(A, state, m); nmod_mat_randtest(b, state); /* Dense */ if (n_randint(state, 2)) nmod_mat_randops(A, state, 1+n_randint(state, 1+m*m)); solved = nmod_mat_solve_vec(x->entries, A, b->entries); nmod_mat_mul(Ax, A, x); if (!nmod_mat_equal(Ax, b) || !solved) TEST_FUNCTION_FAIL( "Ax != b\n" "A = %{nmod_mat}\n" "b = %{nmod_mat}\n" "x = %{nmod_mat}\n" "Ax = %{nmod_mat}\n", A, b, x, Ax); nmod_mat_clear(A); nmod_mat_clear(b); nmod_mat_clear(x); nmod_mat_clear(Ax); } /* Test singular systems */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { m = 1 + n_randint(state, 20); r = n_randint(state, m); mod = n_randtest_prime(state, 0); nmod_mat_init(A, m, m, mod); nmod_mat_init(b, m, 1, mod); nmod_mat_init(x, m, 1, mod); nmod_mat_init(Ax, m, 1, mod); nmod_mat_randrank(A, state, r); nmod_mat_randtest(b, state); /* Dense */ if (n_randint(state, 2)) nmod_mat_randops(A, state, 1+n_randint(state, 1+m*m)); solved = nmod_mat_solve_vec(x->entries, A, b->entries); if (solved) TEST_FUNCTION_FAIL("singular system was 'solved'\n"); nmod_mat_clear(A); nmod_mat_clear(b); nmod_mat_clear(x); nmod_mat_clear(Ax); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-submul.c000066400000000000000000000044221461254215100201150ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_submul, state) { slong i; for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D, T, E; mp_limb_t mod = n_randtest_not_zero(state); slong m, k, n; m = n_randint(state, 100); k = n_randint(state, 100); n = n_randint(state, 100); /* Force Strassen test */ if (i < 5) { m += 300; k += 300; n += 300; } nmod_mat_init(A, m, k, mod); nmod_mat_init(B, k, n, mod); nmod_mat_init(C, m, n, mod); nmod_mat_init(D, m, n, mod); nmod_mat_init(T, m, n, mod); nmod_mat_init(E, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_randtest(C, state); nmod_mat_submul(D, C, A, B); nmod_mat_mul(T, A, B); nmod_mat_sub(E, C, T); if (!nmod_mat_equal(D, E)) TEST_FUNCTION_FAIL( "Results not equal\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n" "E = %{nmod_mat}\n", A, B, C, D, E); /* Check aliasing */ nmod_mat_submul(C, C, A, B); if (!nmod_mat_equal(C, E)) TEST_FUNCTION_FAIL( "Results not equal (aliasing)\n" "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "C = %{nmod_mat}\n" "D = %{nmod_mat}\n" "E = %{nmod_mat}\n", A, B, C, D, E); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); nmod_mat_clear(E); nmod_mat_clear(T); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-trace.c000066400000000000000000000032061461254215100177030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_trace, state) { slong i; /* Test trace(AB) = trace(BA) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mat_t A, B, AB, BA; mp_limb_t mod, trab, trba; slong m, n; mod = n_randtest_prime(state, 0); m = n_randint(state, 10); n = n_randint(state, 10); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, n, m, mod); nmod_mat_init(AB, m, m, mod); nmod_mat_init(BA, n, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_mul(AB, A, B); nmod_mat_mul(BA, B, A); trab = nmod_mat_trace(AB); trba = nmod_mat_trace(BA); if (trab != trba) TEST_FUNCTION_FAIL( "A = %{nmod_mat}\n" "B = %{nmod_mat}\n" "AB = %{nmod_mat}\n" "BA = %{nmod_mat}\n" "tr(AB) = %wu\n" "tr(BA) = %wu\n", A, B, AB, BA, trab, trba); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(AB); nmod_mat_clear(BA); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-transpose.c000066400000000000000000000051661461254215100206320ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_transpose, state) { slong m, n, mod, mod2, rep; /* Rectangular transpose, same modulus */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { nmod_mat_t A, B, C; m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_mat_init(B, n, m, mod); nmod_mat_init(C, m, n, mod); nmod_mat_randtest(A, state); nmod_mat_randtest(B, state); nmod_mat_transpose(B, A); nmod_mat_transpose(C, B); if (!nmod_mat_equal(C, A)) TEST_FUNCTION_FAIL("C != A\n"); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } /* Rectangular transpose, different modulus */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { nmod_mat_t A, AT, B, BT, AT2; m = n_randint(state, 20); n = n_randint(state, 20); mod = n_randtest_not_zero(state); mod2 = n_randtest_not_zero(state); nmod_mat_init(A, m, n, mod); nmod_mat_init(AT, n, m, mod); nmod_mat_init(B, m, n, mod2); nmod_mat_init(BT, n, m, mod2); nmod_mat_init(AT2, n, m, mod2); nmod_mat_randtest(A, state); nmod_mat_set(B, A); nmod_mat_transpose(AT, A); nmod_mat_transpose(BT, B); nmod_mat_set(AT2, AT); if (!nmod_mat_equal(BT, AT2)) TEST_FUNCTION_FAIL("AT != BT\n"); nmod_mat_clear(A); nmod_mat_clear(AT); nmod_mat_clear(AT2); nmod_mat_clear(B); nmod_mat_clear(BT); } /* Self-transpose */ for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { nmod_mat_t A, B; m = n_randint(state, 20); mod = n_randtest_not_zero(state); nmod_mat_init(A, m, m, mod); nmod_mat_init(B, m, m, mod); nmod_mat_randtest(A, state); nmod_mat_set(B, A); nmod_mat_transpose(B, B); nmod_mat_transpose(B, B); if (!nmod_mat_equal(B, A)) TEST_FUNCTION_FAIL("B != A\n"); nmod_mat_clear(A); nmod_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/test/t-window_init_clear.c000066400000000000000000000024711461254215100223100ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid Copyright (C) 2015 Sergeicheva Elena This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mat.h" TEST_FUNCTION_START(nmod_mat_window_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t a, w; slong r1, r2, c1, c2, n; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); n = n_randint(state, 50) + 1; nmod_mat_init(a, rows, cols, n); nmod_mat_randtest(a, state); r2 = n_randint(state, rows + 1); c2 = n_randint(state, cols + 1); if (r2) r1 = n_randint(state, r2); else r1 = 0; if (c2) c1 = n_randint(state, c2); else c1 = 0; nmod_mat_window_init(w, a, r1, c1, r2, c2); nmod_mat_one(w); nmod_mat_window_clear(w); nmod_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mat/trace.c000066400000000000000000000013031461254215100164570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" mp_limb_t nmod_mat_trace(const nmod_mat_t mat) { mp_limb_t t; slong i, n = nmod_mat_nrows(mat); if (n == 0) return 0; t = nmod_mat_entry(mat, 0, 0); for (i = 1; i < n; i++) t = nmod_add(t, nmod_mat_entry(mat, i, i), mat->mod); return t; } flint-3.1.3/src/nmod_mat/transpose.c000066400000000000000000000021451461254215100174040ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_transpose(nmod_mat_t B, const nmod_mat_t A) { mp_limb_t tmp; slong i, j; if (B->r != A->c || B->c != A->r) { flint_throw(FLINT_ERROR, "Exception (nmod_mat_transpose). Incompatible dimensions.\n"); } if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < A->r - 1; i++) for (j = i + 1; j < A->c; j++) { tmp = A->rows[i][j]; A->rows[i][j] = A->rows[j][i]; A->rows[j][i] = tmp; } } else /* Not aliased; general case */ { for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) B->rows[i][j] = A->rows[j][i]; } } flint-3.1.3/src/nmod_mat/window.c000066400000000000000000000023151461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2008 2009 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2008 Martin Albrecht Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" void nmod_mat_window_init(nmod_mat_t window, const nmod_mat_t mat, slong r1, slong c1, slong r2, slong c2) { slong i; window->entries = NULL; if (r2 > r1) window->rows = (mp_limb_t **) flint_malloc((r2 - r1) * sizeof(mp_limb_t *)); else window->rows = NULL; if (mat->c > 0) { for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; } else { for (i = 0; i < r2 - r1; i++) window->rows[i] = NULL; } window->r = r2 - r1; window->c = c2 - c1; window->mod = mat->mod; } void nmod_mat_window_clear(nmod_mat_t window) { if (window->r > 0) flint_free(window->rows); } flint-3.1.3/src/nmod_mat/zero.c000066400000000000000000000011561461254215100163460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_mat.h" void nmod_mat_zero(nmod_mat_t mat) { slong i, m, n; m = mat->r; n = mat->c; if (n == 0) return; for (i = 0; i < m; i++) _nmod_vec_zero(mat->rows[i], n); } flint-3.1.3/src/nmod_mpoly.h000066400000000000000000002033171461254215100157560ustar00rootroot00000000000000/* Copyright (C) 2017 - 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_MPOLY_H #define NMOD_MPOLY_H #ifdef NMOD_MPOLY_INLINES_C #define NMOD_MPOLY_INLINE #else #define NMOD_MPOLY_INLINE static inline #endif #include "nmod_types.h" #include "mpoly_types.h" #if FLINT_WANT_ASSERT # include "n_poly.h" # include "mpoly.h" #endif #ifdef __cplusplus extern "C" { #endif FLINT_FORCE_INLINE mp_limb_t * nmod_mpoly_term_coeff_ref(nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < A->length); return A->coeffs + i; } /* Internal type definitions *************************************************/ FLINT_FORCE_INLINE n_poly_struct * evil_cast_nmod_poly_to_n_poly(nmod_poly_struct * a) { return (n_poly_struct *) a; } FLINT_FORCE_INLINE const n_poly_struct * evil_const_cast_nmod_poly_to_n_poly(const nmod_poly_struct * a) { return (const n_poly_struct *) a; } /* nmod_mpoly_univar_t sparse univariates with multivariate coefficients */ typedef struct { nmod_mpoly_struct * coeffs; /* multivariate coefficients */ fmpz * exps; slong alloc; slong length; } nmod_mpoly_univar_struct; typedef nmod_mpoly_univar_struct nmod_mpoly_univar_t[1]; /* nmod_mpolyu_t sparse univariates with nmod_mpoly_t coefficients with uniform bits and LEX ordering */ typedef struct { nmod_mpoly_struct * coeffs; ulong * exps; slong alloc; slong length; flint_bitcnt_t bits; /* default bits to construct coeffs */ } nmod_mpolyu_struct; typedef nmod_mpolyu_struct nmod_mpolyu_t[1]; /* nmod_mpolyd_t A dense mpoly is stored as a flat array of coefficients. Suppose deg_bounds = {r0, r1, r2}. The coefficient of the monomial with exponents {e0, e1, e2} is stored at the coefficient of index e2 + r2*(e1 + r1*(e0 + r0*0)) */ typedef struct { slong nvars; slong degb_alloc; slong * deg_bounds; slong coeff_alloc; mp_limb_t * coeffs; } nmod_mpolyd_struct; typedef nmod_mpolyd_struct nmod_mpolyd_t[1]; /* stack type used in gcd which are generally useful as well *****************/ typedef struct { n_poly_struct ** poly_array; slong poly_alloc; slong poly_top; nmod_mpolyun_struct ** mpolyun_array; slong mpolyun_alloc; slong mpolyun_top; nmod_mpolyn_struct ** mpolyn_array; slong mpolyn_alloc; slong mpolyn_top; const nmod_mpoly_ctx_struct * ctx; flint_bitcnt_t bits; } nmod_poly_stack_struct; typedef nmod_poly_stack_struct nmod_poly_stack_t[1]; void nmod_poly_stack_init(nmod_poly_stack_t S, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); void nmod_poly_stack_clear(nmod_poly_stack_t S); void nmod_poly_stack_set_ctx(nmod_poly_stack_t S, const nmod_mpoly_ctx_t ctx); n_poly_struct ** nmod_poly_stack_fit_request_poly( nmod_poly_stack_t S, slong k); nmod_mpolyun_struct ** nmod_poly_stack_fit_request_mpolyun( nmod_poly_stack_t S, slong k); nmod_mpolyn_struct ** nmod_poly_stack_fit_request_mpolyn( nmod_poly_stack_t S, slong k); FLINT_FORCE_INLINE n_poly_struct ** nmod_poly_stack_request_poly(nmod_poly_stack_t S, slong k) { n_poly_struct ** poly_top; poly_top = nmod_poly_stack_fit_request_poly(S, k); S->poly_top += k; return poly_top; } FLINT_FORCE_INLINE n_poly_struct * nmod_poly_stack_take_top_poly(nmod_poly_stack_t S) { /* assume the request for 1 has already been fitted */ n_poly_struct ** poly_top; FLINT_ASSERT(S->poly_top + 1 <= S->poly_alloc); poly_top = S->poly_array + S->poly_top; S->poly_top += 1; return poly_top[0]; } FLINT_FORCE_INLINE void nmod_poly_stack_give_back_poly(nmod_poly_stack_t S, slong k) { FLINT_ASSERT(S->poly_top >= k); S->poly_top -= k; } FLINT_FORCE_INLINE slong nmod_poly_stack_size_poly(const nmod_poly_stack_t S) { return S->poly_top; } FLINT_FORCE_INLINE nmod_mpolyun_struct ** nmod_poly_stack_request_mpolyun(nmod_poly_stack_t S, slong k) { nmod_mpolyun_struct ** mpolyun_top; mpolyun_top = nmod_poly_stack_fit_request_mpolyun(S, k); S->mpolyun_top += k; return mpolyun_top; } FLINT_FORCE_INLINE nmod_mpolyun_struct * nmod_poly_stack_take_top_mpolyun(nmod_poly_stack_t S) { /* assume the request for 1 has already been fitted */ nmod_mpolyun_struct ** mpolyun_top; FLINT_ASSERT(S->mpolyun_top + 1 <= S->mpolyun_alloc); mpolyun_top = S->mpolyun_array + S->mpolyun_top; S->mpolyun_top += 1; return mpolyun_top[0]; } FLINT_FORCE_INLINE void nmod_poly_stack_give_back_mpolyun(nmod_poly_stack_t S, slong k) { FLINT_ASSERT(S->mpolyun_top >= k); S->mpolyun_top -= k; } FLINT_FORCE_INLINE slong nmod_poly_stack_size_mpolyun(const nmod_poly_stack_t S) { return S->mpolyun_top; } FLINT_FORCE_INLINE nmod_mpolyn_struct ** nmod_poly_stack_request_mpolyn(nmod_poly_stack_t S, slong k) { nmod_mpolyn_struct ** mpolyn_top; mpolyn_top = nmod_poly_stack_fit_request_mpolyn(S, k); S->mpolyn_top += k; return mpolyn_top; } FLINT_FORCE_INLINE nmod_mpolyn_struct * nmod_poly_stack_take_top_mpolyn(nmod_poly_stack_t S) { /* assume the request for 1 has already been fitted */ nmod_mpolyn_struct ** mpolyn_top; FLINT_ASSERT(S->mpolyn_top + 1 <= S->mpolyn_alloc); mpolyn_top = S->mpolyn_array + S->mpolyn_top; S->mpolyn_top += 1; return mpolyn_top[0]; } FLINT_FORCE_INLINE void nmod_poly_stack_give_back_mpolyn(nmod_poly_stack_t S, slong k) { FLINT_ASSERT(S->mpolyn_top >= k); S->mpolyn_top -= k; } FLINT_FORCE_INLINE slong nmod_poly_stack_size_mpolyn(const nmod_poly_stack_t S) { return S->mpolyn_top; } /* Context object ************************************************************/ void nmod_mpoly_ctx_init(nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t modulus); void nmod_mpoly_ctx_init_rand(nmod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, mp_limb_t modulus); void nmod_mpoly_ctx_clear(nmod_mpoly_ctx_t ctx); void nmod_mpoly_ctx_set_modulus(nmod_mpoly_ctx_t ctx, mp_limb_t modulus); NMOD_MPOLY_INLINE slong nmod_mpoly_ctx_nvars(const nmod_mpoly_ctx_t ctx) { return ctx->minfo->nvars; } NMOD_MPOLY_INLINE ordering_t nmod_mpoly_ctx_ord(const nmod_mpoly_ctx_t ctx) { return ctx->minfo->ord; } NMOD_MPOLY_INLINE mp_limb_t nmod_mpoly_ctx_modulus(const nmod_mpoly_ctx_t ctx) { return ctx->mod.n; } /* Memory management ********************************************************/ NMOD_MPOLY_INLINE void nmod_mpoly_init(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->bits = MPOLY_MIN_BITS; A->coeffs_alloc = 0; A->exps_alloc = 0; } NMOD_MPOLY_INLINE void nmod_mpoly_clear(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { if (A->coeffs_alloc > 0) flint_free(A->coeffs); if (A->exps_alloc > 0) flint_free(A->exps); } void nmod_mpoly_init2(nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_init3(nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_realloc(nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_fit_length(nmod_mpoly_t A, slong length, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_fit_length_fit_bits(nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_fit_length_reset_bits(nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void _nmod_mpoly_fit_length( mp_limb_t ** coeffs, slong * coeffs_alloc, ulong ** exps, slong * exps_alloc, slong N, slong length) { if (length > *coeffs_alloc) { *coeffs_alloc = FLINT_MAX(length, *coeffs_alloc*2); *coeffs = (mp_limb_t *) flint_realloc(*coeffs, *coeffs_alloc*sizeof(mp_limb_t)); } if (N*length > *exps_alloc) { *exps_alloc = FLINT_MAX(N*length, *exps_alloc*2); *exps = (mp_limb_t *) flint_realloc(*exps, *exps_alloc*sizeof(ulong)); } } NMOD_MPOLY_INLINE void _nmod_mpoly_set_length(nmod_mpoly_t A, slong newlen, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(newlen <= A->coeffs_alloc); FLINT_ASSERT(mpoly_words_per_exp(A->bits, ctx->minfo)*newlen <= A->exps_alloc); A->length = newlen; } NMOD_MPOLY_INLINE void nmod_mpoly_truncate(nmod_mpoly_t A, slong newlen, const nmod_mpoly_ctx_t ctx) { if (A->length > newlen) { A->length = newlen; } } /* Input/output **************************************************************/ int nmod_mpoly_set_str_pretty(nmod_mpoly_t A, const char * str, const char ** x, const nmod_mpoly_ctx_t ctx); char * nmod_mpoly_get_str_pretty(const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx); #ifdef FLINT_HAVE_FILE int nmod_mpoly_fprint_pretty(FILE * file, const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx); #endif int nmod_mpoly_print_pretty(const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx); /* Basic manipulation *******************************************************/ void nmod_mpoly_gen(nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_is_gen(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_equal(const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void nmod_mpoly_swap(nmod_mpoly_t A, nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { FLINT_SWAP(nmod_mpoly_struct, *A, *B); } /* Constants *****************************************************************/ int nmod_mpoly_is_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_ui(nmod_mpoly_t A, ulong c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_fmpz(nmod_mpoly_t A, const fmpz_t c, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void nmod_mpoly_zero(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { _nmod_mpoly_set_length(A, 0, ctx); } NMOD_MPOLY_INLINE void nmod_mpoly_one(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { nmod_mpoly_set_ui(A, UWORD(1), ctx); } int nmod_mpoly_equal_ui(const nmod_mpoly_t A, ulong c, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE int nmod_mpoly_is_zero(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return A->length == 0; } NMOD_MPOLY_INLINE int nmod_mpoly_is_one(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_equal_ui(A, 1, ctx); } /* Degrees *******************************************************************/ int nmod_mpoly_degrees_fit_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_degrees_fmpz(fmpz ** degs, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_degrees_si(slong * degs, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_degree_fmpz(fmpz_t deg, const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_degree_si(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_total_degree_fits_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_total_degree_fmpz(fmpz_t td, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_total_degree_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_used_vars(int * used, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); /* Coefficients **************************************************************/ ulong nmod_mpoly_get_coeff_ui_monomial(const nmod_mpoly_t A, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_coeff_ui_monomial(nmod_mpoly_t A, ulong c, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_coeff_ui_fmpz(const nmod_mpoly_t A, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_coeff_ui_ui(const nmod_mpoly_t A, const ulong * exp, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_set_coeff_ui_fmpz(nmod_mpoly_t A, ulong c, const fmpz * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_coeff_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_coeff_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_get_coeff_vars_ui(nmod_mpoly_t C, const nmod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE mp_limb_t nmod_mpoly_leadcoeff( nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return A->coeffs[0]; } /* conversion ****************************************************************/ int nmod_mpoly_is_nmod_poly(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_get_n_poly(n_poly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_get_nmod_poly(nmod_poly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_set_nmod_poly(nmod_mpoly_t A, flint_bitcnt_t Abits, const mp_limb_t * Bcoeffs, slong Blen, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_n_poly_mod(nmod_mpoly_t A, const n_poly_t B, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_nmod_poly(nmod_mpoly_t A, const nmod_poly_t B, slong var, const nmod_mpoly_ctx_t ctx); /* comparison ****************************************************************/ int nmod_mpoly_cmp(const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); /* container operations ******************************************************/ int nmod_mpoly_is_canonical(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE slong nmod_mpoly_length(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return A->length; } void nmod_mpoly_resize(nmod_mpoly_t A, slong new_length, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_term_coeff_ui(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_term_coeff_ui(nmod_mpoly_t A, slong i, ulong c, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_term_exp_fits_ui(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_term_exp_fits_si(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_get_term_exp_fmpz(fmpz ** exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_get_term_exp_ui(ulong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_get_term_exp_si(slong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_term_var_exp_ui(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_get_term_var_exp_si(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_term_exp_fmpz(nmod_mpoly_t A, slong i, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_term_exp_ui(nmod_mpoly_t A, slong i, const ulong * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_get_term(nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_get_term_monomial(nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_push_term_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_push_term_ui_ffmpz(nmod_mpoly_t A, ulong c, const fmpz * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_push_term_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_sort_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_combine_like_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_reverse(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_assert_canonical(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_radix_sort1(nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); void _nmod_mpoly_radix_sort(nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); void _nmod_mpoly_push_exp_ffmpz(nmod_mpoly_t A, const fmpz * exp, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_push_exp_pfmpz(nmod_mpoly_t A, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_push_exp_ui(nmod_mpoly_t A, const ulong * exp, const nmod_mpoly_ctx_t ctx); /* Random generation *********************************************************/ void nmod_mpoly_randtest_bounds(nmod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_randtest_bound(nmod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_randtest_bits(nmod_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const nmod_mpoly_ctx_t ctx); ulong _nmod_mpoly_get_term_ui_fmpz(const nmod_mpoly_t poly, const fmpz * exp, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_term_ui_fmpz(const nmod_mpoly_t poly, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_term_ui_ui(const nmod_mpoly_t poly, const ulong * exp, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_max_degrees(ulong * max_degs, const ulong * exps, slong len, slong bits, slong n, int deg, int rev, slong N); void nmod_mpoly_max_degrees(ulong * max_degs, const nmod_mpoly_t poly, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_nmod(nmod_mpoly_t poly, const nmod_t c, const nmod_mpoly_ctx_t ctx); ulong nmod_mpoly_get_coeff_ui(nmod_t x, const nmod_mpoly_t poly, slong n, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_coeff_ui(nmod_mpoly_t poly, slong n, ulong x, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_get_monomial(ulong * exps, const nmod_mpoly_t poly, slong n, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_monomial(nmod_mpoly_t poly, slong n, const ulong * exps, const nmod_mpoly_ctx_t ctx); /* Addition/Subtraction ******************************************************/ void nmod_mpoly_add_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_sub_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_add(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_sub(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); slong _nmod_mpoly_add(mp_limb_t * coeff1, ulong * exp1, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, slong N, const ulong * cmpmask, nmod_t fctx); slong _nmod_mpoly_sub(ulong * coeff1, ulong * exp1, const ulong * coeff2, const ulong * exp2, slong len2, const ulong * coeff3, const ulong * exp3, slong len3, slong N, const ulong * cmpmask, nmod_t fctx); /* Scalar operations *********************************************************/ void nmod_mpoly_neg(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_scalar_mul_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_make_monic(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_scalar_mul_nmod_invertible(nmod_mpoly_t A, const nmod_mpoly_t B, mp_limb_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_scalar_addmul_ui(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, ulong d, const nmod_mpoly_ctx_t ctx); /* Differention **************************************************************/ void nmod_mpoly_derivative(nmod_mpoly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ int _ff_poly_pow_fmpz_is_not_feasible(slong length, const fmpz_t e); int _ff_poly_pow_ui_is_not_feasible(slong length, ulong e); mp_limb_t _nmod_mpoly_eval_all_ui(const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mp_limb_t * alphas, const mpoly_ctx_t mctx, nmod_t mod); ulong nmod_mpoly_evaluate_all_ui(const nmod_mpoly_t A, const ulong * vals, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_evaluate_one_ui(nmod_mpoly_t A, const nmod_mpoly_t B, slong var, ulong val, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_compose_nmod_poly(nmod_poly_t A, const nmod_mpoly_t B, nmod_poly_struct * const * C, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_compose_mat(nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz_mat_t M, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC); int nmod_mpoly_compose_nmod_mpoly_geobucket(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC); int nmod_mpoly_compose_nmod_mpoly_horner(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC); int nmod_mpoly_compose_nmod_mpoly(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC); void nmod_mpoly_compose_nmod_mpoly_gen(nmod_mpoly_t A, const nmod_mpoly_t B, const slong * c, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC); /* Multiplication ************************************************************/ void nmod_mpoly_mul(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_mul_johnson(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_mul_heap_threaded(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_mul_array(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_mul_array_threaded(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_mul_dense(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); slong _nmod_mpoly_mul_johnson(nmod_mpoly_t A, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, nmod_t fctx); void _nmod_mpoly_mul_johnson_maxfields(nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_mul_heap_threaded_pool_maxfields(nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); int _nmod_mpoly_mul_array_DEG(nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx); int _nmod_mpoly_mul_array_LEX(nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx); int _nmod_mpoly_mul_array_threaded_pool_DEG(nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); int _nmod_mpoly_mul_array_threaded_pool_LEX(nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); int _nmod_mpoly_mul_dense(nmod_mpoly_t P, const nmod_mpoly_t A, fmpz * maxAfields, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_ctx_t ctx); /* Powering ******************************************************************/ void _nmod_mpoly_pow_rmul(nmod_mpoly_t A, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, ulong k, slong N, const ulong * cmpmask, nmod_t mod, nmod_mpoly_t T); void nmod_mpoly_pow_rmul(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_pow_fmpz(nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz_t k, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_pow_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx); /* Division ******************************************************************/ int nmod_mpoly_divides(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int _nmod_mpoly_divides_threaded_pool(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); int nmod_mpoly_divides_monagan_pearce(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); #if FLINT_KNOW_STRONG_ORDER #define nmod_mpoly_divides_heap_threaded nmod_mpoly_divides_heap_threaded int nmod_mpoly_divides_heap_threaded(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); #define _nmod_mpoly_divides_heap_threaded_pool _nmod_mpoly_divides_heap_threaded_pool int _nmod_mpoly_divides_heap_threaded_pool(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); #endif int nmod_mpoly_divides_dense(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_div(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_divrem(nmod_mpoly_t Q, nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_divrem_ideal(nmod_mpoly_struct ** Q, nmod_mpoly_t R, const nmod_mpoly_t A, nmod_mpoly_struct * const * B, slong len, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void nmod_mpoly_divexact(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_divides(Q, A, B, ctx)) return; flint_throw(FLINT_ERROR, "nmod_mpoly_divexact: nonexact division"); } int _nmod_mpoly_divides_monagan_pearce(nmod_mpoly_t Q, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, nmod_t fctx); void nmod_mpoly_div_monagan_pearce(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_divrem_monagan_pearce(nmod_mpoly_t q, nmod_mpoly_t r, const nmod_mpoly_t poly2, const nmod_mpoly_t poly3, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_divrem_ideal_monagan_pearce(nmod_mpoly_struct ** Q, nmod_mpoly_t R, const nmod_mpoly_t A, nmod_mpoly_struct * const * B, slong len, const nmod_mpoly_ctx_t ctx); /* Square root ***************************************************************/ int nmod_mpoly_sqrt_heap(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE int nmod_mpoly_sqrt(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_sqrt_heap(Q, A, ctx); } NMOD_MPOLY_INLINE int nmod_mpoly_is_square(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { int res; nmod_mpoly_t Q; nmod_mpoly_init(Q, ctx); res = nmod_mpoly_sqrt_heap(Q, A, ctx); nmod_mpoly_clear(Q, ctx); return res; } int nmod_mpoly_quadratic_root(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); /* GCD ***********************************************************************/ void nmod_mpoly_term_content(nmod_mpoly_t M, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_content_vars(nmod_mpoly_t g, const nmod_mpoly_t A, slong * vars, slong vars_length, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_gcd(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int _nmod_mpoly_gcd_algo_small( nmod_mpoly_t G, nmod_mpoly_t Abar, /* could be NULL */ nmod_mpoly_t Bbar, /* could be NULL */ const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, unsigned int algo); int _nmod_mpoly_gcd_algo(nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, unsigned int algo); int nmod_mpoly_gcd_cofactors(nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_gcd_brown(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_gcd_hensel(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_gcd_zippel(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_gcd_zippel2(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_deflation(fmpz * shift, fmpz * stride, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_deflate(nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_inflate(nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const nmod_mpoly_ctx_t ctx); /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ void mpoly_void_ring_init_nmod_mpoly_ctx(mpoly_void_ring_t R, const nmod_mpoly_ctx_t ctx); void nmod_mpolyl_lead_coeff(nmod_mpoly_t c, const nmod_mpoly_t A, slong num_vars, const nmod_mpoly_ctx_t ctx); int nmod_mpolyl_content(nmod_mpoly_t g, const nmod_mpoly_t A, slong num_vars, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_to_nmod_poly_deflate(nmod_poly_t A, const nmod_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_from_nmod_poly_inflate(nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_repack_bits(nmod_mpoly_t A, const nmod_mpoly_t B, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_repack_bits_inplace(nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx); typedef struct { slong nvars; slong * perm; } nmod_mpolyd_ctx_struct; typedef nmod_mpolyd_ctx_struct nmod_mpolyd_ctx_t[1]; /* data is passed to the threaded mul/div functions via a stripe struct */ typedef struct _nmod_mpoly_stripe_struct { char * big_mem; slong big_mem_alloc; const nmod_mpoly_ctx_struct * ctx; slong N; flint_bitcnt_t bits; nmod_t mod; mp_limb_t lc_minus_inv; const ulong * cmpmask; slong * startidx; slong * endidx; ulong * emin; ulong * emax; int upperclosed; } nmod_mpoly_stripe_struct; typedef nmod_mpoly_stripe_struct nmod_mpoly_stripe_t[1]; /* Univariates ***************************************************************/ void nmod_mpoly_univar_init(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_univar_clear(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_univar_fit_length(nmod_mpoly_univar_t A, slong length, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_univar_print_pretty(const nmod_mpoly_univar_t A, const char ** x, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_univar_assert_canonical(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void nmod_mpoly_univar_zero(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) { A->length = 0; } void nmod_mpoly_univar_set_coeff_ui(nmod_mpoly_univar_t A, ulong e, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_to_univar(nmod_mpoly_univar_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_from_univar(nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_univar_t B, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_from_univar(nmod_mpoly_t A, const nmod_mpoly_univar_t B, slong var, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void nmod_mpoly_univar_swap(nmod_mpoly_univar_t A, nmod_mpoly_univar_t B, const nmod_mpoly_ctx_t ctx) { FLINT_SWAP(nmod_mpoly_univar_struct, *A, *B); } int nmod_mpoly_univar_degree_fits_si(const nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE slong nmod_mpoly_univar_length(const nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) { return A->length; } slong nmod_mpoly_univar_get_term_exp_si(nmod_mpoly_univar_t A, slong i, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void nmod_mpoly_univar_get_term_coeff(nmod_mpoly_t c, const nmod_mpoly_univar_t A, slong i, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); nmod_mpoly_set(c, A->coeffs + i, ctx); } NMOD_MPOLY_INLINE void nmod_mpoly_univar_swap_term_coeff(nmod_mpoly_t c, nmod_mpoly_univar_t A, slong i, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); nmod_mpoly_swap(c, A->coeffs + i, ctx); } int nmod_mpoly_univar_pseudo_gcd(nmod_mpoly_univar_t Gx, const nmod_mpoly_univar_t Ax, const nmod_mpoly_univar_t Bx, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_univar_resultant(nmod_mpoly_t R, const nmod_mpoly_univar_t Ax, const nmod_mpoly_univar_t Bx, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_univar_discriminant(nmod_mpoly_t D, const nmod_mpoly_univar_t Fx, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_resultant(nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_discriminant(nmod_mpoly_t R, const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); /* Helpers for array methods *************************************************/ void _nmod_mpoly_mul_array_chunked_LEX(nmod_mpoly_t P, const nmod_mpoly_t A, const nmod_mpoly_t B, const ulong * mults, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_mul_array_chunked_DEG(nmod_mpoly_t P, const nmod_mpoly_t A, const nmod_mpoly_t B, ulong degb, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_addmul_array1_ulong1(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3); void _nmod_mpoly_addmul_array1_ulong2(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3); void _nmod_mpoly_addmul_array1_ulong3(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3); slong nmod_mpoly_append_array_sm1_LEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, const ulong * mults, slong num, slong array_size, slong top, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm2_LEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, const ulong * mults, slong num, slong array_size, slong top, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm3_LEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, const ulong * mults, slong num, slong array_size, slong top, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm1_DEGLEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm2_DEGLEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm3_DEGLEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm1_DEGREVLEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm2_DEGREVLEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb, const nmod_mpoly_ctx_t ctx); slong nmod_mpoly_append_array_sm3_DEGREVLEX(nmod_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb, const nmod_mpoly_ctx_t ctx); /* mpolyd ********************************************************************/ void nmod_mpolyd_ctx_init(nmod_mpolyd_ctx_t dctx, slong nvars); void nmod_mpolyd_ctx_clear(nmod_mpolyd_ctx_t dctx); FLINT_FORCE_INLINE void nmod_mpolyd_swap(nmod_mpolyd_t poly1, nmod_mpolyd_t poly2) { FLINT_SWAP(nmod_mpolyd_struct, *poly1, *poly2); } int nmod_mpolyd_set_degbounds(nmod_mpolyd_t A, slong * bounds); int nmod_mpolyd_set_degbounds_perm(nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, slong * bounds); void nmod_mpoly_convert_to_nmod_mpolyd( nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_convert_to_nmod_mpolyd_degbound( nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_convert_from_nmod_mpolyd( nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, const nmod_mpolyd_t B, const nmod_mpolyd_ctx_t dctx); void nmod_mpolyd_init(nmod_mpolyd_t poly, slong nvars); void nmod_mpolyd_fit_length(nmod_mpolyd_t poly, slong len); void nmod_mpolyd_zero(nmod_mpolyd_t poly); void nmod_mpolyd_set_nvars(nmod_mpolyd_t poly, slong nvars); void nmod_mpolyd_set(nmod_mpolyd_t A, const nmod_mpolyd_t B); void nmod_mpolyd_clear(nmod_mpolyd_t poly); void nmod_mpolyd_print(nmod_mpolyd_t poly); slong nmod_mpolyd_length(const nmod_mpolyd_t A); /* mpolyu ********************************************************************/ void nmod_mpolyu_init(nmod_mpolyu_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_clear(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx); FLINT_FORCE_INLINE void nmod_mpolyu_swap(nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx) { FLINT_SWAP(nmod_mpolyu_struct, *A, *B); } FLINT_FORCE_INLINE void nmod_mpolyu_zero(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx) { A->length = 0; } int nmod_mpolyu_is_one(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx); void nmod_mpolyu_print_pretty(const nmod_mpolyu_t poly, const char ** x, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_fit_length(nmod_mpolyu_t A, slong length, const nmod_mpoly_ctx_t uctx); void nmod_mpolyu_one(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx); void nmod_mpolyu_degrees_si( slong * degs, const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_repack_bits_inplace( nmod_mpolyu_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); nmod_mpoly_struct * _nmod_mpolyu_get_coeff(nmod_mpolyu_t A, ulong pow, const nmod_mpoly_ctx_t uctx); void nmod_mpolyu_shift_right(nmod_mpolyu_t A, ulong s); void nmod_mpolyu_shift_left(nmod_mpolyu_t A, ulong s); int nmod_mpolyu_content_mpoly(nmod_mpoly_t g, const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_scalar_mul_nmod(nmod_mpolyu_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_set(nmod_mpolyu_t A, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx); void nmod_mpolyu_cvtto_poly(nmod_poly_t a, nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_cvtfrom_poly(nmod_mpolyu_t A, nmod_poly_t a, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_cvtfrom_poly_notmain(nmod_mpolyu_t A, nmod_poly_t a, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_to_mpolyu_perm_deflate_threaded_pool( nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const thread_pool_handle * handles, slong num_handles); void nmod_mpoly_from_mpolyu_perm_inflate( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride); int nmod_mpolyuu_divides(nmod_mpolyu_t Q, const nmod_mpolyu_t A, const nmod_mpolyu_t B, slong nmainvars, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_divexact_mpoly_inplace(nmod_mpolyu_t A, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_mul_mpoly(nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_mul_mpoly_inplace(nmod_mpolyu_t A, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_setform(nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpolyu_gcdm_zippel(nmod_mpolyu_t G, nmod_mpolyu_t Abar, nmod_mpolyu_t Bbar, nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpoly_ctx_t ctx, flint_rand_t randstate); NMOD_MPOLY_INLINE mp_limb_t nmod_mpolyu_leadcoeff( nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return nmod_mpoly_leadcoeff(A->coeffs + 0, ctx); } /* mpolyn ********************************************************************/ void nmod_mpolyn_init(nmod_mpolyn_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_clear(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_swap(nmod_mpolyn_t A, nmod_mpolyn_t B); void nmod_mpolyn_zero(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_is_zero(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_print_pretty(const nmod_mpolyn_t A, const char ** x_in, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_fit_length(nmod_mpolyn_t A, slong length, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_set_length(nmod_mpolyn_t A, slong newlen, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_fit_bits(nmod_mpolyn_t A, slong bits, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_is_canonical(const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_set(nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_set_mpoly(nmod_mpolyn_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_cvtfrom_mpolyn(nmod_mpoly_t A, const nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_mul_poly(nmod_mpolyn_t A, const nmod_mpolyn_t B, const n_poly_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_cvtto_mpolyn(nmod_mpolyn_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE mp_limb_t nmod_mpolyn_leadcoeff(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { n_poly_struct * leadpoly; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(n_poly_degree(A->coeffs + 0) >= 0); leadpoly = A->coeffs + 0; return leadpoly->coeffs[leadpoly->length - 1]; } NMOD_MPOLY_INLINE n_poly_struct * nmod_mpolyn_leadcoeff_poly( nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return A->coeffs + 0; } /* mpolyun *******************************************************************/ void nmod_mpolyun_init(nmod_mpolyun_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_clear(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_FORCE_INLINE void nmod_mpolyun_swap(nmod_mpolyun_t A, nmod_mpolyun_t B) { FLINT_SWAP(nmod_mpolyun_struct, *A, *B); } void nmod_mpolyun_zero(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_print_pretty(const nmod_mpolyun_t poly, const char ** x, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_fit_length(nmod_mpolyun_t A, slong length, const nmod_mpoly_ctx_t ctx); int nmod_mpolyun_is_canonical(const nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_shift_right(nmod_mpolyun_t A, ulong s); void nmod_mpolyun_shift_left(nmod_mpolyun_t A, ulong s); slong nmod_mpolyn_lastdeg(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); slong nmod_mpolyun_lastdeg(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_set(nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_one(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_one(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); mp_limb_t nmod_mpolyun_leadcoeff_last(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_set_mod(nmod_mpolyn_t A, const nmod_t mod); void nmod_mpolyun_set_mod(nmod_mpolyun_t A, const nmod_t mod); int nmod_mpolyn_is_nonzero_nmod(const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpolyun_is_nonzero_nmod(const nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_scalar_mul_nmod( nmod_mpolyn_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_scalar_mul_nmod(nmod_mpolyun_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_mul_last(nmod_mpolyn_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_mul_last(nmod_mpolyun_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_equal( const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpolyun_equal(const nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_cvtto_mpolyun(nmod_mpolyun_t A, const nmod_mpolyu_t B, slong k, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu_cvtfrom_mpolyun(nmod_mpolyu_t A, const nmod_mpolyun_t B, slong var, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_mul_poly(nmod_mpolyun_t A, const nmod_mpolyun_t B, const n_poly_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_content_last(n_poly_t a, nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_content_last(n_poly_t a, nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_divexact_last(nmod_mpolyn_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_divexact_last(nmod_mpolyun_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_divides(nmod_mpolyn_t Q, const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); #if FLINT_KNOW_STRONG_ORDER #define nmod_mpolyn_divides_threaded_pool nmod_mpolyn_divides_threaded_pool int nmod_mpolyn_divides_threaded_pool(nmod_mpolyn_t Q, const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles); #endif int nmod_mpolyun_divides(nmod_mpolyun_t Q, const nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_to_mpolyun_perm_deflate_threaded_pool( nmod_mpolyun_t A, const nmod_mpoly_ctx_t uctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const thread_pool_handle * handles, slong num_handles); void nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(nmod_mpolyn_t A, const nmod_mpoly_ctx_t nctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const thread_pool_handle * handles, slong num_handles); void nmod_mpoly_from_mpolyun_perm_inflate(nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride); void nmod_mpoly_from_mpolyn_perm_inflate(nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t nctx, const slong * perm, const ulong * shift, const ulong * stride); NMOD_MPOLY_INLINE mp_limb_t nmod_mpolyun_leadcoeff( nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return nmod_mpolyn_leadcoeff(A->coeffs + 0, ctx); } NMOD_MPOLY_INLINE n_poly_struct * nmod_mpolyun_leadcoeff_poly( nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return nmod_mpolyn_leadcoeff_poly(A->coeffs + 0, ctx); } /* GCD ***********************************************************************/ int mpoly_gcd_get_use_first(slong rGdeg, slong Adeg, slong Bdeg, slong gammadeg); int nmod_mpoly_gcd_get_use_new(slong rGdeg, slong Adeg, slong Bdeg, slong gammadeg, slong degxAB, slong degyAB, slong numABgamma, const n_polyun_t G, const n_polyun_t Abar, const n_polyun_t Bbar); void nmod_mpolyu_setform_mpolyun(nmod_mpolyu_t A, nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_gcd_brown_smprime_bivar( nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx, nmod_poly_stack_t Sp); int nmod_mpolyn_gcd_brown_smprime(nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, nmod_poly_stack_t Sp); int nmod_mpolyn_gcd_brown_smprime_threaded_pool(nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, const thread_pool_handle * handles, slong num_workers); int nmod_mpolyn_gcd_brown_lgprime(nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx); nmod_gcds_ret_t nmod_mpolyu_gcds_zippel(nmod_mpolyu_t G, nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpolyu_t f, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t randstate, slong * degbound); int nmod_mpolyu_gcdp_zippel(nmod_mpolyu_t G, nmod_mpolyu_t Abar, nmod_mpolyu_t Bbar, nmod_mpolyu_t A, nmod_mpolyu_t B, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t randstate); void nmod_mpoly_to_mpolyl_perm_deflate( nmod_mpoly_t A, const nmod_mpoly_ctx_t lctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride); void nmod_mpoly_from_mpolyl_perm_inflate( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride); int nmod_mpolyl_gcd_zippel_smprime( nmod_mpoly_t rG, const slong * rGdegs, /* guess at rG degrees, could be NULL */ nmod_mpoly_t rAbar, nmod_mpoly_t rBbar, const nmod_mpoly_t A, const slong * Adegs, const nmod_mpoly_t B, const slong * Bdegs, const nmod_mpoly_t gamma, const slong * gammadegs, const nmod_mpoly_ctx_t ctx); int nmod_mpolyl_gcd_zippel_lgprime( nmod_mpoly_t rG, const slong * rGdegs, /* guess at rG degrees, could be NULL */ nmod_mpoly_t rAbar, nmod_mpoly_t rBbar, const nmod_mpoly_t A, const slong * Adegs, const nmod_mpoly_t B, const slong * Bdegs, const nmod_mpoly_t gamma, const slong * gammadegs, const nmod_mpoly_ctx_t ctx); int nmod_mpolyl_gcd_hensel_smprime( nmod_mpoly_t G, slong Gdeg, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpolyl_gcd_hensel_medprime( nmod_mpoly_t G, slong Gdeg, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t smA, const nmod_mpoly_t smB, const nmod_mpoly_ctx_t smctx); void _nmod_mpoly_monomial_evals_cache(n_poly_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mp_limb_t * betas, slong start, slong stop, const mpoly_ctx_t mctx, nmod_t mod); void _nmod_mpoly_monomial_evals2_cache(n_polyun_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mp_limb_t * betas, slong m, const mpoly_ctx_t ctx, nmod_t mod); /* interp ********************************************************************/ void _nmod_poly_eval2_pow(mp_limb_t * vp, mp_limb_t * vm, n_poly_t P, n_poly_t alphapow, nmod_t fctx); void nmod_mpolyn_interp_reduce_2sm_poly(n_poly_t E, n_poly_t F, const nmod_mpolyn_t A, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_lift_2sm_poly(slong * lastdeg_, nmod_mpolyn_t F, const n_poly_t A, const n_poly_t B, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_interp_crt_2sm_poly(slong * lastdeg_, nmod_mpolyn_t F, nmod_mpolyn_t T, const n_poly_t A, const n_poly_t B, const n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_lift_sm_bpoly(nmod_mpolyn_t F, n_bpoly_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_interp_crt_sm_bpoly(slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, n_bpoly_t A, n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_reduce_2sm_mpolyn(nmod_mpolyn_t E, nmod_mpolyn_t F, nmod_mpolyn_t A, slong var, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_lift_2sm_mpolyn(slong * lastdeg, nmod_mpolyn_t T, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_interp_crt_2sm_mpolyn(slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_interp_reduce_sm_mpolyu(nmod_mpolyu_t B, nmod_mpolyun_t A, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx); void nmod_mpolyn_interp_lift_sm_mpoly(nmod_mpolyn_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpolyun_interp_lift_sm_mpolyu(nmod_mpolyun_t A, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_interp_crt_sm_mpoly(slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, nmod_mpoly_t A, n_poly_t modulus, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx); int nmod_mpolyun_interp_crt_sm_mpolyu(slong * lastdeg, nmod_mpolyun_t F, nmod_mpolyun_t T, nmod_mpolyu_t A, n_poly_t modulus, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx); int nmod_mpolyn_interp_mcrt_sm_mpoly(slong * lastdeg_, nmod_mpolyn_t F, const nmod_mpoly_t A, const n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx); /* geobuckets ****************************************************************/ typedef struct nmod_mpoly_geobucket { nmod_mpoly_struct polys[FLINT_BITS/2]; nmod_mpoly_struct temps[FLINT_BITS/2]; slong length; } nmod_mpoly_geobucket_struct; typedef nmod_mpoly_geobucket_struct nmod_mpoly_geobucket_t[1]; void nmod_mpoly_geobucket_init(nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_geobucket_clear(nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_geobucket_empty(nmod_mpoly_t p, nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_geobucket_fit_length(nmod_mpoly_geobucket_t B, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_geobucket_set(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_geobucket_add(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_geobucket_sub(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx); /****************************************************************************** Internal consistency checks ******************************************************************************/ void nmod_mpoly_remainder_strongtest(const nmod_mpoly_t r, const nmod_mpoly_t g, const nmod_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod_mpoly/000077500000000000000000000000001461254215100155775ustar00rootroot00000000000000flint-3.1.3/src/nmod_mpoly/add.c000066400000000000000000000120611461254215100164730ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" slong _nmod_mpoly_add1( mp_limb_t * Acoeffs, ulong * Aexps, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, ulong maskhi, nmod_t fctx) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { if ((Bexps[i]^maskhi) > (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; Acoeffs[k] = Bcoeffs[i]; i++; } else if ((Bexps[i]^maskhi) == (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; Acoeffs[k] = nmod_add(Bcoeffs[i], Ccoeffs[j], fctx); k -= (Acoeffs[k] == 0); i++; j++; } else { Acoeffs[k] = Ccoeffs[j]; Aexps[k] = Cexps[j]; j++; } k++; } while (i < Blen) { Aexps[k] = Bexps[i]; Acoeffs[k] = Bcoeffs[i]; i++; k++; } while (j < Clen) { Aexps[k] = Cexps[j]; Acoeffs[k] = Ccoeffs[j]; j++; k++; } return k; } slong _nmod_mpoly_add(mp_limb_t * Acoeffs, ulong * Aexps, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, slong N, const ulong * cmpmask, nmod_t fctx) { slong i = 0, j = 0, k = 0; if (N == 1) return _nmod_mpoly_add1(Acoeffs, Aexps, Bcoeffs, Bexps, Blen, Ccoeffs, Cexps, Clen, cmpmask[0], fctx); while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); Acoeffs[k] = Bcoeffs[i]; i++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); Acoeffs[k] = nmod_add(Bcoeffs[i], Ccoeffs[j], fctx); k -= (Acoeffs[k] == 0); i++; j++; } else { Acoeffs[k] = Ccoeffs[j]; mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); j++; } k++; } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); Acoeffs[k] = Bcoeffs[i]; i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); Acoeffs[k] = Ccoeffs[j]; j++; k++; } return k; } void nmod_mpoly_add(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) { slong Abits, N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (B->length == 0) { nmod_mpoly_set(A, C, ctx); return; } else if (C->length == 0) { nmod_mpoly_set(A, B, ctx); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { nmod_mpoly_t T; nmod_mpoly_init3(T, B->length + C->length, Abits, ctx); T->length = _nmod_mpoly_add(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->mod); nmod_mpoly_swap(A, T, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _nmod_mpoly_add(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, N, cmpmask, ctx->mod); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } flint-3.1.3/src/nmod_mpoly/add_ui.c000066400000000000000000000035701461254215100171750ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_add_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong Blen = B->length; if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); if (c == 0) { nmod_mpoly_set(A, B, ctx); return; } if (Blen < 1) { nmod_mpoly_set_ui(A, c, ctx); return; } if (mpoly_monomial_is_zero(B->exps + (Blen - 1)*N, N)) { if (A != B) { nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, Blen - 1); mpoly_copy_monomials(A->exps, B->exps, Blen, N); _nmod_mpoly_set_length(A, B->length, ctx); } A->coeffs[Blen - 1] = nmod_add(B->coeffs[Blen - 1], c, ctx->mod); if (A->coeffs[Blen - 1] == 0) _nmod_mpoly_set_length(A, Blen - 1, ctx); } else { if (A != B) { nmod_mpoly_fit_length_reset_bits(A, Blen + 1, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, Blen); mpoly_copy_monomials(A->exps, B->exps, Blen, N); } else { nmod_mpoly_fit_length(A, Blen + 1, ctx); } mpoly_monomial_zero(A->exps + N*Blen, N); A->coeffs[Blen] = c; _nmod_mpoly_set_length(A, Blen + 1, ctx); } } flint-3.1.3/src/nmod_mpoly/cmp.c000066400000000000000000000022061461254215100165220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_cmp(const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { int cmp; slong i; slong length = A->length; mp_limb_t * Acoeffs = A->coeffs; mp_limb_t * Bcoeffs = B->coeffs; if (A->length != B->length) return A->length < B->length ? -1 : 1; if (length <= 0) return 0; cmp = mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, length, ctx->minfo); if (cmp != 0) return cmp; for (i = 0; i < length; i++) { if (Acoeffs[i] != Bcoeffs[i]) return Acoeffs[i] < Bcoeffs[i] ? -1 : 1; } return 0; } flint-3.1.3/src/nmod_mpoly/combine_like_terms.c000066400000000000000000000026661461254215100216070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" /* assuming that the exponents are valid and sorted, put the polynomial in canonical form i.e. 2*x^e + 3*x^e -> 5x^e 2*x^e - 2*x^e -> 0 */ void nmod_mpoly_combine_like_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong in, out, N = mpoly_words_per_exp(A->bits, ctx->minfo); out = -WORD(1); for (in = WORD(0); in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= WORD(0) && mpoly_monomial_equal(A->exps + N*out, A->exps + N*in, N)) { A->coeffs[out] = nmod_add(A->coeffs[out], A->coeffs[in], ctx->mod); } else { if (out < WORD(0) || A->coeffs[out] != UWORD(0)) out++; if (out != in) { mpoly_monomial_set(A->exps + N*out, A->exps + N*in, N); A->coeffs[out] = A->coeffs[in]; } } } if (out < WORD(0) || A->coeffs[out] != UWORD(0)) out++; A->length = out; } flint-3.1.3/src/nmod_mpoly/compose_mat.c000066400000000000000000000042221461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "mpoly.h" #include "nmod_mpoly.h" /* essentially exps(A) = M*exps(B) */ void _nmod_mpoly_compose_mat( nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz_mat_t M, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) { slong i; fmpz * u, * v; flint_bitcnt_t vbits; slong Blen = B->length; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); const ulong * Bexp = B->exps; const mp_limb_t * Bcoeffs = B->coeffs; slong AN; FLINT_ASSERT(A != B); FLINT_ASSERT(fmpz_mat_nrows(M) == ctxAC->minfo->nfields + 1); FLINT_ASSERT(fmpz_mat_ncols(M) == ctxB->minfo->nfields); u = _fmpz_vec_init(ctxB->minfo->nfields); v = _fmpz_vec_init(ctxAC->minfo->nfields + 1); nmod_mpoly_fit_length_reset_bits(A, Blen, MPOLY_MIN_BITS, ctxAC); A->length = 0; for (i = 0; i < Blen; i++) { mpoly_unpack_vec_fmpz(u, Bexp + BN*i, Bbits, ctxB->minfo->nfields, 1); fmpz_mat_mul_fmpz_vec(v, M, u, fmpz_mat_ncols(M)); if (!fmpz_is_zero(v + ctxAC->minfo->nfields)) continue; vbits = _fmpz_vec_max_bits(v, ctxAC->minfo->nfields); FLINT_ASSERT(vbits >= 0); vbits = mpoly_fix_bits(vbits + 1, ctxAC->minfo); nmod_mpoly_fit_length_fit_bits(A, A->length + 1, vbits, ctxAC); A->coeffs[A->length] = Bcoeffs[i]; AN = mpoly_words_per_exp(A->bits, ctxAC->minfo); mpoly_pack_vec_fmpz(A->exps + AN*A->length, v, A->bits, ctxAC->minfo->nfields, 1); A->length++; } _fmpz_vec_clear(u, ctxB->minfo->nfields); _fmpz_vec_clear(v, ctxAC->minfo->nfields + 1); nmod_mpoly_sort_terms(A, ctxAC); nmod_mpoly_combine_like_terms(A, ctxAC); return; } flint-3.1.3/src/nmod_mpoly/compose_nmod_mpoly.c000066400000000000000000000035501461254215100216500ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "mpoly.h" #include "nmod_mpoly.h" /* evaluate B(xbar) at xbar = C */ int nmod_mpoly_compose_nmod_mpoly(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) { slong i; fmpz_mat_t M; FLINT_ASSERT(A != B); if (B->length == 0) { nmod_mpoly_zero(A, ctxAC); return 1; } fmpz_mat_init(M, ctxAC->minfo->nfields + 1, ctxB->minfo->nfields); fmpz_mat_zero(M); for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) goto matrix_no_good; if (C[i]->length == 0) { mpoly_compose_mat_fill_column(M, NULL, 0, i, ctxB->minfo, ctxAC->minfo); } else { if (C[i]->coeffs[0] != 1) goto matrix_no_good; mpoly_compose_mat_fill_column(M, C[i]->exps, C[i]->bits, i, ctxB->minfo, ctxAC->minfo); } } _nmod_mpoly_compose_mat(A, B, M, ctxB, ctxAC); fmpz_mat_clear(M); return 1; matrix_no_good: fmpz_mat_clear(M); for (i = 0; i < ctxB->minfo->nvars; i++) { if (C[i]->length > 1) { return nmod_mpoly_compose_nmod_mpoly_horner(A, B, C, ctxB, ctxAC); } } return nmod_mpoly_compose_nmod_mpoly_geobucket(A, B, C, ctxB, ctxAC); } flint-3.1.3/src/nmod_mpoly/compose_nmod_mpoly_gen.c000066400000000000000000000024121461254215100224750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "mpoly.h" #include "nmod_mpoly.h" /* evaluate B(x_1,...,x_n) at x_i = y_c[i], y_j are vars of ctxAC */ void nmod_mpoly_compose_nmod_mpoly_gen(nmod_mpoly_t A, const nmod_mpoly_t B, const slong * c, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) { fmpz_mat_t M; if (B->length == 0) { nmod_mpoly_zero(A, ctxAC); return; } fmpz_mat_init(M, ctxAC->minfo->nfields + 1, ctxB->minfo->nfields); mpoly_compose_mat_gen(M, c, ctxB->minfo, ctxAC->minfo); if (A == B) { nmod_mpoly_t T; nmod_mpoly_init(T, ctxAC); _nmod_mpoly_compose_mat(T, B, M, ctxB, ctxAC); nmod_mpoly_swap(A, T, ctxAC); nmod_mpoly_clear(T, ctxAC); } else { _nmod_mpoly_compose_mat(A, B, M, ctxB, ctxAC); } fmpz_mat_clear(M); return; } flint-3.1.3/src/nmod_mpoly/compose_nmod_mpoly_geobucket.c000066400000000000000000000035551461254215100237050ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" /* evaluate B(xbar) at xbar = C */ int nmod_mpoly_compose_nmod_mpoly_geobucket(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) { int success = 1; slong i, j; slong Blen = B->length; const mp_limb_t * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); nmod_mpoly_t U, V, W; nmod_mpoly_geobucket_t T; fmpz * e; nmod_mpoly_init(U, ctxAC); nmod_mpoly_init(V, ctxAC); nmod_mpoly_init(W, ctxAC); nmod_mpoly_geobucket_init(T, ctxAC); e = _fmpz_vec_init(ctxB->minfo->nvars); for (i = 0; success && i < Blen; i++) { nmod_mpoly_set_ui(U, Bcoeff[i], ctxAC); mpoly_get_monomial_ffmpz(e, Bexp + BN*i, Bbits, ctxB->minfo); for (j = 0; j < ctxB->minfo->nvars; j++) { success = success && nmod_mpoly_pow_fmpz(V, C[j], e + j, ctxAC); nmod_mpoly_mul(W, U, V, ctxAC); nmod_mpoly_swap(U, W, ctxAC); } nmod_mpoly_geobucket_add(T, U, ctxAC); } if (success) nmod_mpoly_geobucket_empty(A, T, ctxAC); nmod_mpoly_clear(U, ctxAC); nmod_mpoly_clear(V, ctxAC); nmod_mpoly_clear(W, ctxAC); nmod_mpoly_geobucket_clear(T, ctxAC); _fmpz_vec_clear(e, ctxB->minfo->nvars); return success; } flint-3.1.3/src/nmod_mpoly/compose_nmod_mpoly_horner.c000066400000000000000000000252211461254215100232240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" typedef struct { slong f; slong r; slong v_var; fmpz_t v_exp; /* will be managed as stack grows / shrinks */ int ret; } stack_entry_struct; typedef stack_entry_struct stack_entry_t[1]; /* A = A * X^pow */ static int _nmod_mpoly_pmul(nmod_mpoly_t A, const nmod_mpoly_t X, const fmpz_t pow, nmod_mpoly_t T, const nmod_mpoly_ctx_t ctx) { ulong p; FLINT_ASSERT(fmpz_sgn(pow) > 0); if (!fmpz_fits_si(pow)) { if (!nmod_mpoly_pow_fmpz(T, X, pow, ctx)) { nmod_mpoly_zero(A, ctx); return 0; } nmod_mpoly_mul(A, A, T, ctx); return 1; } p = fmpz_get_ui(pow); if (X->length <= WORD(2) || A->length/p < X->length) { if (!nmod_mpoly_pow_ui(T, X, p, ctx)) { nmod_mpoly_zero(A, ctx); return 0; } nmod_mpoly_mul(A, A, T, ctx); } else { while (p >= 1) { nmod_mpoly_mul(T, A, X, ctx); nmod_mpoly_swap(A, T, ctx); p--; } } return 1; } /* evaluate B(xbar) at xbar = C, */ int nmod_mpoly_compose_nmod_mpoly_horner(nmod_mpoly_t A, const nmod_mpoly_t B, nmod_mpoly_struct * const * C, const nmod_mpoly_ctx_t ctxB, const nmod_mpoly_ctx_t ctxAC) { int success = 1; int ret; slong nvars = ctxB->minfo->nvars; slong i, j, k, cur, next, f, r, f_prev, r_prev, v; slong sp, rp; stack_entry_struct * stack; nmod_mpoly_struct * regs; nmod_mpoly_t temp; slong * rtypes; ulong totalcounts, maxcounts; ulong * counts; slong Blen = B->length; slong * Blist; const mp_limb_t * Bcoeff = B->coeffs; ulong * Bexp = B->exps; flint_bitcnt_t Bbits = B->bits; slong BN = mpoly_words_per_exp(Bbits, ctxB->minfo); fmpz * Buexp; fmpz * mdegs; fmpz_t score, tz; TMP_INIT; if (Blen < 1) { nmod_mpoly_zero(A, ctxAC); return 1; } if (nvars < 1) { FLINT_ASSERT(Blen == 1); nmod_mpoly_set_ui(A, B->coeffs[0], ctxAC); return 1; } FLINT_ASSERT(A != B); FLINT_ASSERT(Blen > 0); TMP_START; fmpz_init(score); fmpz_init(tz); /* unpack B exponents */ Buexp = _fmpz_vec_init(nvars*Blen); for (i = 0; i < Blen; i++) mpoly_get_monomial_ffmpz(Buexp + nvars*i, Bexp + BN*i, Bbits, ctxB->minfo); counts = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); mdegs = _fmpz_vec_init(nvars); /* stack */ sp = -WORD(1); /* start with empty stack */ stack = (stack_entry_struct *) TMP_ALLOC(nvars*(Blen + 1)*sizeof(stack_entry_struct)); Blist = (slong *) TMP_ALLOC(Blen*sizeof(slong)); /* registers of polynomials */ rp = 0; rtypes = (slong *) TMP_ALLOC((nvars + 1)*sizeof(slong)); regs = (nmod_mpoly_struct *) TMP_ALLOC(nvars*sizeof(nmod_mpoly_struct)); for (i = 0; i < nvars; i++) nmod_mpoly_init(regs + i, ctxAC); nmod_mpoly_init(temp, ctxAC); /* polynomials will be stored as link lists */ for (i = 0; i + 1 < Blen; i++) Blist[i] = i + 1; Blist[i] = -WORD(1); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 0; (stack + sp)->f = 0; HornerForm: f = (stack + sp)->f; FLINT_ASSERT(f != -WORD(1)); /* f is not supposed to be zero */ /* obtain a count of the number of terms containing each variable */ for (i = 0; i < nvars; i++) { counts[i] = 0; fmpz_set_si(mdegs + i, -WORD(1)); } for (j = f; j != -WORD(1); j = Blist[j]) { for (i = 0; i < nvars; i++) { if (!fmpz_is_zero(Buexp + nvars*j + i )) { counts[i]++; if (fmpz_sgn(mdegs + i) < 0 || fmpz_cmp(mdegs + i, Buexp + nvars*j + i) > 0) { fmpz_set(mdegs + i, Buexp + nvars*j + i); } } } } totalcounts = 0; maxcounts = 0; v = -WORD(1); for (i = 0; i < nvars; i++) { maxcounts = FLINT_MAX(maxcounts, counts[i]); totalcounts += counts[i]; if (counts[i] != 0) v = i; } /* handle simple cases */ if (totalcounts == 0) { FLINT_ASSERT(Blist[f] == -WORD(1)); /* f should have had only one term */ rtypes[rp] = f; goto HornerFormReturn; } else if (totalcounts == 1) { FLINT_ASSERT(!fmpz_is_zero(Buexp + nvars*f + v)); /* this term should not be a scalar */ if (!nmod_mpoly_pow_fmpz(regs + rp, C[v], Buexp + nvars*f + v, ctxAC)) { success = 0; } nmod_mpoly_scalar_mul_ui(regs + rp, regs + rp, Bcoeff[f], ctxAC); if (Blist[f] != -WORD(1)) /* if f has a second term */ { /* this term should be a scalar */ FLINT_ASSERT(fmpz_is_zero(Buexp + nvars*Blist[f] + v)); nmod_mpoly_add_ui(regs + rp, regs + rp, Bcoeff[Blist[f]], ctxAC); } rtypes[rp] = -WORD(1); goto HornerFormReturn; } /* pick best power to pull out */ k = 0; if (maxcounts == 1) { fmpz_set_si(score, -WORD(1)); for (i = 0; i < nvars; i++) { if (counts[i] == 1 && (fmpz_sgn(score) < 0 || fmpz_cmp(mdegs + i, score) < 0)) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_set(score, mdegs + i); k = i; } } } else { fmpz_zero(score); for (i = 0; i < nvars; i++) { if (counts[i] > 1) { FLINT_ASSERT(fmpz_sgn(mdegs + i) > 0); fmpz_mul_ui(tz, mdegs + i, counts[i] - 1); if (fmpz_cmp(tz, score) > 0) { fmpz_swap(score, tz); k = i; } } } } /* set variable power v */ (stack + sp)->v_var = k; fmpz_set((stack + sp)->v_exp, mdegs + k); /* scan f and split into q and v with f = q*v + r then set f = q */ r = -WORD(1); cur = f; f_prev = -WORD(1); r_prev = -WORD(1); while (cur != -WORD(1)) { next = Blist[cur]; if (fmpz_is_zero(Buexp + nvars*cur + k)) { if (f_prev == -WORD(1)) f = Blist[cur]; else Blist[f_prev] = Blist[cur]; if (r_prev == -WORD(1)) r = cur; else Blist[r_prev] = cur; Blist[cur] = -WORD(1); r_prev = cur; } else { /* mdegs[k] should be minimum non zero exponent */ fmpz_sub(Buexp + nvars*cur + k, Buexp + nvars*cur + k, mdegs + k); FLINT_ASSERT(fmpz_sgn(Buexp + nvars*cur + k) >= 0); f_prev = cur; } cur = next; } (stack + sp)->r = r; /* convert the quotient */ sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 1; (stack + sp)->f = f; goto HornerForm; HornerForm1: /* convert the remainder */ r = (stack + sp)->r; if (r != -WORD(1)) { /* remainder is non zero */ rp++; FLINT_ASSERT(0 <= rp && rp <= nvars); sp++; fmpz_init((stack + sp)->v_exp); (stack + sp)->ret = 2; (stack + sp)->f = r; goto HornerForm; HornerForm2: if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] == -WORD(1)) { /* both quotient and remainder are polynomials */ if (!_nmod_mpoly_pmul(regs + rp - 1, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } nmod_mpoly_add(temp, regs + rp - 1, regs + rp, ctxAC); nmod_mpoly_swap(temp, regs + rp - 1, ctxAC); } else if (rtypes[rp - 1] == -WORD(1) && rtypes[rp] != -WORD(1)) { /* quotient is a polynomial, remainder is a scalar */ if (!_nmod_mpoly_pmul(regs + rp - 1, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } nmod_mpoly_add_ui(regs + rp - 1, regs + rp - 1, Bcoeff[rtypes[rp]], ctxAC); } else if (rtypes[rp - 1] != -WORD(1) && rtypes[rp] == -WORD(1)) { /* quotient is a scalar, remainder is a polynomial */ if (!nmod_mpoly_pow_fmpz(temp, C[(stack + sp)->v_var], (stack + sp)->v_exp, ctxAC)) { success = 0; } nmod_mpoly_scalar_mul_ui(temp, temp, Bcoeff[rtypes[rp - 1]], ctxAC); nmod_mpoly_add(regs + rp - 1, temp, regs + rp, ctxAC); } else { /* quotient is a scalar, remainder is a scalar */ FLINT_ASSERT(0); /* this should have been handled by simple case */ } rp--; FLINT_ASSERT(0 <= rp && rp <= nvars); } else { /* remainder is zero */ FLINT_ASSERT(rtypes[rp] == -WORD(1)); /* quotient is a scalar */ /* quotient is a polynomial */ if (!_nmod_mpoly_pmul(regs + rp, C[(stack + sp)->v_var], (stack + sp)->v_exp, temp, ctxAC)) { success = 0; } } rtypes[rp] = -WORD(1); HornerFormReturn: if (!success) { while (sp >= 0) { fmpz_clear((stack + sp)->v_exp); sp--; } goto cleanup; } ret = (stack + sp)->ret; fmpz_clear((stack + sp)->v_exp); sp--; if (ret == 1) goto HornerForm1; if (ret == 2) goto HornerForm2; FLINT_ASSERT(rp == 0); FLINT_ASSERT(sp == -WORD(1)); if (rtypes[rp] == -WORD(1)) { nmod_mpoly_swap(A, regs + rp, ctxAC); } else { nmod_mpoly_set_ui(A, Bcoeff[rtypes[rp]], ctxAC); } cleanup: for (i = 0; i < nvars; i++) nmod_mpoly_clear(regs + i, ctxAC); nmod_mpoly_clear(temp, ctxAC); fmpz_clear(score); fmpz_clear(tz); _fmpz_vec_clear(mdegs, nvars); _fmpz_vec_clear(Buexp, nvars*Blen); TMP_END; return success; } flint-3.1.3/src/nmod_mpoly/compose_nmod_poly.c000066400000000000000000000151611461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" int _ff_poly_pow_fmpz_is_not_feasible(slong length, const fmpz_t e) { if (length < 2) { return 0; } else { ulong limit = (ulong)(WORD_MAX)/(ulong)(2*sizeof(fmpz)); return fmpz_cmp_ui(e, limit/(ulong)(length)) >= 0; } } int _ff_poly_pow_ui_is_not_feasible(slong length, ulong e) { if (length < 2) { return 0; } else { ulong limit = (ulong)(WORD_MAX)/(ulong)(2*sizeof(fmpz)); return e >= limit/(ulong)(length); } } int _nmod_mpoly_compose_nmod_poly_sp(nmod_poly_t A, const nmod_mpoly_t B, nmod_poly_struct * const * C, const nmod_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t bits = B->bits; slong i, j, k, N, nvars = ctx->minfo->nvars; slong shift, off; slong entries, k_len; slong Blen = B->length; const mp_limb_t * Bcoeff = B->coeffs; ulong * Bexp = B->exps; slong * degrees; slong * offs; ulong * masks; nmod_poly_struct * powers; nmod_poly_t t, t2; TMP_INIT; FLINT_ASSERT(Blen != 0); TMP_START; degrees = (slong *) TMP_ALLOC(nvars*sizeof(slong)); mpoly_degrees_si(degrees, Bexp, Blen, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_ff_poly_pow_ui_is_not_feasible(C[i]->length, degrees[i])) { success = 0; goto cleanup_degrees; } entries += FLINT_BIT_COUNT(degrees[i]); } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, nmod_poly_struct); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the non-main variables */ k = 0; for (i = 0; i < nvars; i++) { flint_bitcnt_t varibits = FLINT_BIT_COUNT(degrees[i]); mpoly_gen_offset_shift_sp(&off, &shift, i, bits, ctx->minfo); for (j = 0; j < varibits; j++) { offs[k] = off; masks[k] = UWORD(1) << (shift + j); nmod_poly_init_mod(powers + k, ctx->mod); if (j == 0) nmod_poly_set(powers + k, C[i]); else nmod_poly_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ nmod_poly_zero(A); nmod_poly_init_mod(t, ctx->mod); nmod_poly_init_mod(t2, ctx->mod); for (i = 0; i < Blen; i++) { nmod_poly_zero(t); nmod_poly_set_coeff_ui(t, 0, Bcoeff[i]); for (k = 0; k < k_len; k++) { if ((Bexp[N*i + offs[k]] & masks[k]) != WORD(0)) { nmod_poly_mul(t2, t, powers + k); nmod_poly_swap(t, t2); } } nmod_poly_add(A, A, t); } nmod_poly_clear(t); nmod_poly_clear(t2); for (k = 0; k < k_len; k++) nmod_poly_clear(powers + k); cleanup_degrees: TMP_END; return success; } int _nmod_mpoly_compose_nmod_poly_mp(nmod_poly_t A, const nmod_mpoly_t B, nmod_poly_struct * const * C, const nmod_mpoly_ctx_t ctx) { int success = 1; flint_bitcnt_t bits = B->bits; ulong l; slong i, k, N, nvars = ctx->minfo->nvars; slong off, entries, k_len; slong Blen = B->length; const mp_limb_t * Bcoeff = B->coeffs; ulong * Bexp = B->exps; fmpz * degrees; slong * offs; ulong * masks; flint_bitcnt_t * bitcounts; nmod_poly_struct * powers; nmod_poly_t t, t2; TMP_INIT; FLINT_ASSERT(Blen != 0); TMP_START; bitcounts = TMP_ARRAY_ALLOC(nvars, flint_bitcnt_t); degrees = TMP_ARRAY_ALLOC(nvars, fmpz); for (i = 0; i < nvars; i++) fmpz_init(degrees + i); mpoly_degrees_ffmpz(degrees, Bexp, Blen, bits, ctx->minfo); /* compute how many masks are needed */ entries = 0; for (i = 0; i < nvars; i++) { if (_ff_poly_pow_fmpz_is_not_feasible(C[i]->length, degrees + i)) { success = 0; goto cleanup_degrees; } bitcounts[i] = fmpz_bits(degrees + i); entries += bitcounts[i]; } offs = TMP_ARRAY_ALLOC(entries, slong); masks = TMP_ARRAY_ALLOC(entries, ulong); powers = TMP_ARRAY_ALLOC(entries, nmod_poly_struct); N = mpoly_words_per_exp(bits, ctx->minfo); /* store bit masks for each power of two of the variables */ k = 0; for (i = 0; i < nvars; i++) { off = mpoly_gen_offset_mp(i, bits, ctx->minfo); for (l = 0; l < bitcounts[i]; l++) { offs[k] = off + (l/FLINT_BITS); masks[k] = UWORD(1) << (l%FLINT_BITS); nmod_poly_init_mod(powers + k, ctx->mod); if (l == 0) nmod_poly_set(powers + k, C[i]); else nmod_poly_mul(powers + k, powers + k - 1, powers + k - 1); k++; } } k_len = k; FLINT_ASSERT(k_len == entries); /* accumulate answer */ nmod_poly_zero(A); nmod_poly_init_mod(t, ctx->mod); nmod_poly_init_mod(t2, ctx->mod); for (i = 0; i < Blen; i++) { nmod_poly_zero(t); nmod_poly_set_coeff_ui(t, 0, Bcoeff[i]); for (k = 0; k < k_len; k++) { if ((Bexp[N*i + offs[k]] & masks[k]) != WORD(0)) { nmod_poly_mul(t2, t, powers + k); nmod_poly_swap(t, t2); } } nmod_poly_add(A, A, t); } nmod_poly_clear(t); nmod_poly_clear(t2); for (k = 0; k < k_len; k++) nmod_poly_clear(powers + k); cleanup_degrees: for (i = 0; i < nvars; i++) fmpz_clear(degrees + i); TMP_END; return success; } int nmod_mpoly_compose_nmod_poly(nmod_poly_t A, const nmod_mpoly_t B, nmod_poly_struct * const * C, const nmod_mpoly_ctx_t ctx) { if (B->length == 0) { nmod_poly_zero(A); return 1; } if (B->bits <= FLINT_BITS) { return _nmod_mpoly_compose_nmod_poly_sp(A, B, C, ctx); } else { return _nmod_mpoly_compose_nmod_poly_mp(A, B, C, ctx); } } flint-3.1.3/src/nmod_mpoly/content_vars.c000066400000000000000000000127211461254215100204530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" #include "nmod_mpoly_factor.h" /* content wrt gen(0), ..., gen(num_vars-1) successful answer will be returned with g->bits == A->bits */ int nmod_mpolyl_content( nmod_mpoly_t g, const nmod_mpoly_t A, slong num_vars, const nmod_mpoly_ctx_t ctx) { int success; slong i, j, off, shift; ulong old_shift, new_shift; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; slong Alen = A->length; nmod_mpoly_struct * v; slong vlen, valloc; FLINT_ASSERT(g != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); i = 0; old_shift = (Aexps + N*i)[off] >> shift; valloc = 4; v = (nmod_mpoly_struct *) flint_malloc(valloc*sizeof(nmod_mpoly_struct)); vlen = 0; v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + i; v[vlen].exps = Aexps + N*i; v[vlen].coeffs_alloc = 0; v[vlen].exps_alloc = 0; v[vlen].length = i; v[vlen].coeffs_alloc = v[vlen].length; v[vlen].exps_alloc = N*v[vlen].length; vlen++; for (i = 1; i < Alen; old_shift = new_shift, i++) { new_shift = (Aexps + N*i)[off] >> shift; if (new_shift != old_shift) goto new_one; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto new_one; continue; new_one: v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].coeffs_alloc = v[vlen - 1].length; v[vlen - 1].exps_alloc = N*v[vlen - 1].length; if (vlen + 1 > valloc) { valloc += 2 + valloc/2; v = (nmod_mpoly_struct *) flint_realloc(v, valloc* sizeof(nmod_mpoly_struct)); } v[vlen].bits = A->bits; v[vlen].coeffs = A->coeffs + i; v[vlen].exps = Aexps + N*i; v[vlen].coeffs_alloc = 0; v[vlen].exps_alloc = 0; v[vlen].length = i; vlen++; } v[vlen - 1].length = i - v[vlen - 1].length; FLINT_ASSERT(v[vlen - 1].length > 0); v[vlen - 1].coeffs_alloc = v[vlen - 1].length; v[vlen - 1].exps_alloc = N*v[vlen - 1].length; success = _nmod_mpoly_vec_content_mpoly(g, v, vlen, ctx); if (success) { /* remove gen(0) ... gen(num_vars-1) from the answer */ ulong * gexps; ulong mask; nmod_mpoly_repack_bits_inplace(g, A->bits, ctx); gexps = g->exps; mask = (shift > 0) ? ((-UWORD(1)) >> (FLINT_BITS - shift)) : 0; for (i = 0; i < g->length; i++) { (gexps + N*i)[off] &= mask; for (j = off + 1; j < N; j++) (gexps + N*i)[j] = 0; } } flint_free(v); return success; } int nmod_mpoly_content_vars( nmod_mpoly_t g, const nmod_mpoly_t A, slong * vars, slong num_vars, const nmod_mpoly_ctx_t ctx) { int success; slong i, j, k; nmod_mpolyv_t v, w; nmod_mpoly_univar_t u; if (num_vars < 1) { nmod_mpoly_set(g, A, ctx); return 1; } for (i = 0; i < num_vars; i++) { if (vars[i] >= (ulong) ctx->minfo->nvars) flint_throw(FLINT_ERROR, "nmod_mpoly_content_vars: variable out of range"); } if (nmod_mpoly_is_zero(A, ctx)) { nmod_mpoly_zero(g, ctx); return 1; } if (A->bits <= FLINT_BITS && ctx->minfo->ord == ORD_LEX && num_vars < ctx->minfo->nvars) { for (i = 0; i < num_vars; i++) if (vars[i] != i) goto do_general; if (g == A) { nmod_mpoly_t t; nmod_mpoly_init(t, ctx); success = nmod_mpolyl_content(t, A, num_vars, ctx); nmod_mpoly_swap(g, t, ctx); nmod_mpoly_clear(t, ctx); return success; } return nmod_mpolyl_content(g, A, num_vars, ctx); } do_general: nmod_mpolyv_init(v, ctx); nmod_mpolyv_init(w, ctx); nmod_mpoly_univar_init(u, ctx); i = 0; nmod_mpoly_to_univar(u, A, vars[i], ctx); nmod_mpolyv_fit_length(v, u->length, ctx); v->length = u->length; for (j = 0; j < u->length; j++) nmod_mpoly_swap(v->coeffs + j, u->coeffs + j, ctx); for (i = 1; i < num_vars; i++) { w->length = 0; for (k = 0; k < v->length; k++) { nmod_mpoly_to_univar(u, v->coeffs + k, vars[i], ctx); nmod_mpolyv_fit_length(w, w->length + u->length, ctx); for (j = 0; j < u->length; j++) { nmod_mpoly_swap(w->coeffs + w->length, u->coeffs + j, ctx); w->length++; } } nmod_mpolyv_swap(v, w, ctx); } nmod_mpoly_univar_clear(u, ctx); nmod_mpolyv_clear(w, ctx); success = _nmod_mpoly_vec_content_mpoly(g, v->coeffs, v->length, ctx); nmod_mpolyv_clear(v, ctx); return success; } flint-3.1.3/src/nmod_mpoly/ctx.c000066400000000000000000000021271461254215100165430ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_ctx_init(nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t modulus) { mpoly_ctx_init(ctx->minfo, nvars, ord); nmod_init(&ctx->mod, modulus); } void nmod_mpoly_ctx_init_rand(nmod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, mp_limb_t modulus) { mpoly_ctx_init_rand(ctx->minfo, state, max_nvars); nmod_init(&ctx->mod, modulus); } void nmod_mpoly_ctx_set_modulus(nmod_mpoly_ctx_t ctx, mp_limb_t modulus) { nmod_init(&ctx->mod, modulus); } void nmod_mpoly_ctx_clear(nmod_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); } flint-3.1.3/src/nmod_mpoly/deflate.c000066400000000000000000000031061461254215100173470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_deflate( nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const nmod_mpoly_ctx_t ctx) { slong bits = B->bits; slong NA = mpoly_words_per_exp(bits, ctx->minfo); if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_zero(A, ctx); return; } if (A == B) { slong new_alloc = NA*A->length; ulong * texps = flint_malloc(new_alloc*sizeof(ulong)); mpoly_monomials_deflate(texps, bits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = bits; A->exps_alloc = new_alloc; } else { nmod_mpoly_fit_length_reset_bits(A, B->length, bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, B->length); mpoly_monomials_deflate(A->exps, bits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _nmod_mpoly_set_length(A, B->length, ctx); } if (ctx->minfo->ord != ORD_LEX) nmod_mpoly_sort_terms(A, ctx); } flint-3.1.3/src/nmod_mpoly/deflation.c000066400000000000000000000013151461254215100177100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_deflation(fmpz * shift, fmpz * stride, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { mpoly_monomials_deflation(shift, stride, A->exps, A->bits, A->length, ctx->minfo); } flint-3.1.3/src/nmod_mpoly/degrees.c000066400000000000000000000047501461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2017 - 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_degrees_fit_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_degrees_fit_si(A->exps, A->length, A->bits, ctx->minfo); } void nmod_mpoly_degrees_fmpz(fmpz ** degs, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { mpoly_degrees_pfmpz(degs, A->exps, A->length, A->bits, ctx->minfo); } void nmod_mpoly_degrees_si(slong * degs, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { mpoly_degrees_si(degs, A->exps, A->length, A->bits, ctx->minfo); } void nmod_mpoly_degree_fmpz(fmpz_t deg, const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } slong nmod_mpoly_degree_si(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } int nmod_mpoly_total_degree_fits_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return mpoly_total_degree_fits_si(A->exps, A->length, A->bits, ctx->minfo); } void nmod_mpoly_total_degree_fmpz(fmpz_t td, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { mpoly_total_degree_fmpz(td, A->exps, A->length, A->bits, ctx->minfo); } slong nmod_mpoly_total_degree_si(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return mpoly_total_degree_si(A->exps, A->length, A->bits, ctx->minfo); } void nmod_mpoly_used_vars(int * used, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < ctx->minfo->nvars; i++) used[i] = 0; mpoly_used_vars_or(used, A->exps, A->length, A->bits, ctx->minfo); } flint-3.1.3/src/nmod_mpoly/derivative.c000066400000000000000000000062451461254215100201140ustar00rootroot00000000000000/* Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" static slong _nmod_mpoly_derivative( mp_limb_t * coeff1, ulong * exp1, const mp_limb_t * coeff2, const ulong * exp2, slong len2, flint_bitcnt_t bits, slong N, slong offset, slong shift, ulong * oneexp, nmod_t fctx) { slong i, len1; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); /* x^c -> c*x^(c-1) */ len1 = 0; for (i = 0; i < len2; i++) { mp_limb_t cr; ulong c = (exp2[N*i + offset] >> shift) & mask; if (c == 0) continue; NMOD_RED(cr, c, fctx); coeff1[len1] = nmod_mul(coeff2[i], cr, fctx); if (coeff1[len1] == 0) continue; mpoly_monomial_sub(exp1 + N*len1, exp2 + N*i, oneexp, N); len1++; } return len1; } static slong _nmod_mpoly_derivative_mp( mp_limb_t * coeff1, ulong * exp1, const mp_limb_t * coeff2, const ulong * exp2, slong len2, flint_bitcnt_t bits, slong N, slong offset, ulong * oneexp, nmod_t fctx) { slong i, len1; slong esize = bits/FLINT_BITS; mp_limb_t * t; TMP_INIT; TMP_START; t = (mp_limb_t *) TMP_ALLOC(esize*sizeof(mp_limb_t)); /* x^c -> c*x^(c-1) */ len1 = 0; for (i = 0; i < len2; i++) { mp_limb_t cr = mpn_divrem_1(t, 0, exp2 + N*i + offset, esize, fctx.n); coeff1[len1] = nmod_mul(coeff2[i], cr, fctx); if (coeff1[len1] == 0) continue; mpoly_monomial_sub_mp(exp1 + N*len1, exp2 + N*i, oneexp, N); len1++; } TMP_END; return len1; } void nmod_mpoly_derivative( nmod_mpoly_t poly1, const nmod_mpoly_t poly2, slong var, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = poly2->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong offset, shift; ulong * oneexp; slong len1; TMP_INIT; TMP_START; nmod_mpoly_fit_length_reset_bits(poly1, poly2->length, bits, ctx); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (bits <= FLINT_BITS) { mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, bits, ctx->minfo); len1 = _nmod_mpoly_derivative(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, shift, oneexp, ctx->mod); } else { offset = mpoly_gen_monomial_offset_mp(oneexp, var, bits, ctx->minfo); len1 = _nmod_mpoly_derivative_mp(poly1->coeffs, poly1->exps, poly2->coeffs, poly2->exps, poly2->length, bits, N, offset, oneexp, ctx->mod); } _nmod_mpoly_set_length(poly1, len1, ctx); TMP_END; } flint-3.1.3/src/nmod_mpoly/discriminant.c000066400000000000000000000014351461254215100204320ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" int nmod_mpoly_discriminant(nmod_mpoly_t R, const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { int success; nmod_mpoly_univar_t Ax; nmod_mpoly_univar_init(Ax, ctx); nmod_mpoly_to_univar(Ax, A, var, ctx); success = nmod_mpoly_univar_discriminant(R, Ax, ctx); nmod_mpoly_univar_clear(Ax, ctx); return success; } flint-3.1.3/src/nmod_mpoly/div.c000066400000000000000000000011471461254215100165300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" void nmod_mpoly_div(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { /* TODO !!! */ nmod_mpoly_div_monagan_pearce(Q, A, B, ctx); } flint-3.1.3/src/nmod_mpoly/div_monagan_pearce.c000066400000000000000000000434341461254215100215540ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" static int _nmod_mpoly_div_monagan_pearce1( nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, ulong maskhi, nmod_t fctx) { slong i, j, q_len, s; slong next_loc, heap_len = 2; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; slong * hind; ulong mask, exp; int lt_divides; mp_limb_t lc_minus_inv, acc0, acc1, acc2, pp1, pp0; TMP_INIT; TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); q_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexps[0], x); /* precompute leading coefficient info */ lc_minus_inv = fctx.n - nmod_inv(Bcoeffs[0], fctx); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, q_len + 1); lt_divides = mpoly_monomial_divides1(Qexps + q_len, exp, Bexps[0], mask); acc0 = acc1 = acc2 = 0; if (!lt_divides) { /* optimization: coeff arithmetic not needed */ if (mpoly_monomial_gt1(Bexps[0], exp, maskhi)) { /* optimization: no more quotient terms possible */ goto cleanup; } do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); } else { do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), WORD(0), fctx.n - Acoeffs[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, Bcoeffs[x->i], Qcoeffs[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(acc0, acc2, acc1, acc0, fctx); } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexps[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } } } /* try to divide accumulated term by leading term */ if (!lt_divides) continue; if (acc0 == 0) continue; Qcoeffs[q_len] = nmod_mul(acc0, lc_minus_inv, fctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; q_len++; } cleanup: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = q_len; TMP_END; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; TMP_END; return 0; } static int _nmod_mpoly_div_monagan_pearce( nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, nmod_t fctx) { slong i, j, q_len, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; int lt_divides; mp_limb_t lc_minus_inv, acc0, acc1, acc2, pp1, pp0; TMP_INIT; if (N == 1) { return _nmod_mpoly_div_monagan_pearce1(Q, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, Blen, bits, cmpmask[0], fctx); } TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; q_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coefficient info */ lc_minus_inv = fctx.n - nmod_inv(Bcoeffs[0], fctx); while (heap_len > 1) { _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, q_len + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; lt_divides = mpoly_monomial_divides(Qexps + q_len*N, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; lt_divides = mpoly_monomial_divides_mp(Qexps + q_len*N, exp, Bexps, N, bits); } acc0 = acc1 = acc2 = 0; if (!lt_divides) { /* optimization: coeff arithmetic not needed */ if (mpoly_monomial_gt(Bexps + 0, exp, N, cmpmask)) { /* optimization: no more quotient terms possible */ goto cleanup; } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } else { do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), WORD(0), fctx.n - Acoeffs[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, Bcoeffs[x->i], Qcoeffs[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); } NMOD_RED3(acc0, acc2, acc1, acc0, fctx); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term */ if (acc0 == 0) continue; if (!lt_divides) continue; Qcoeffs[q_len] = nmod_mul(acc0, lc_minus_inv, fctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; q_len++; } cleanup: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = q_len; TMP_END; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; TMP_END; return 0; } void nmod_mpoly_div_monagan_pearce( nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t Qbits; ulong * Aexps = A->exps, * Bexps = B->exps; ulong * cmpmask; int freeAexps = 0, freeBexps = 0; nmod_mpoly_t TQ; nmod_mpoly_struct * q; if (nmod_mpoly_is_zero(B, ctx)) { flint_throw(FLINT_DIVZERO, "nmod_mpoly_div_monagan_pearce: divide by zero"); } if (nmod_mpoly_is_zero(A, ctx)) { nmod_mpoly_zero(Q, ctx); return; } nmod_mpoly_init(TQ, ctx); Qbits = FLINT_MAX(A->bits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (Qbits > A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(Aexps, Bexps, N, cmpmask)) { nmod_mpoly_zero(Q, ctx); goto cleanup; } /* take care of aliasing */ if (Q == A || Q == B) q = TQ; else q = Q; /* do division with remainder */ while (1) { nmod_mpoly_fit_length_reset_bits(q, A->length/B->length + 1, Qbits, ctx); if (_nmod_mpoly_div_monagan_pearce(q, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, Qbits, N, cmpmask, ctx->mod)) { break; } Qbits = mpoly_fix_bits(Qbits + 1, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; if (freeBexps) flint_free(Bexps); Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); freeBexps = 1; } /* deal with aliasing */ if (Q == A || Q == B) nmod_mpoly_swap(Q, TQ, ctx); cleanup: nmod_mpoly_clear(TQ, ctx); if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); flint_free(cmpmask); } flint-3.1.3/src/nmod_mpoly/divides.c000066400000000000000000000122471461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" static int _nmod_mpoly_divides_try_dense( slong * Adegs, slong * Bdegs, slong nvars, slong Alen, slong Blen) { slong i, total_dense_size; ulong hi; FLINT_ASSERT(Alen > WORD(0)); FLINT_ASSERT(Blen > WORD(0)); total_dense_size = WORD(1); for (i = 0; i < nvars; i++) { umul_ppmm(hi, total_dense_size, total_dense_size, Adegs[i] + 1); if (hi != WORD(0) || total_dense_size <= WORD(0)) return 0; } return total_dense_size < WORD(5000000) && total_dense_size/Alen < WORD(10); } typedef struct { slong * degs; ulong * exps; slong length; flint_bitcnt_t bits; const mpoly_ctx_struct * mctx; const thread_pool_handle * handles; slong num_handles; } _degrees_arg_struct; typedef _degrees_arg_struct _degrees_arg_t[1]; static void _worker_degrees(void * varg) { _degrees_arg_struct * arg = (_degrees_arg_struct *) varg; mpoly_degrees_si_threaded(arg->degs, arg->exps, arg->length, arg->bits, arg->mctx, arg->handles, arg->num_handles); } int _nmod_mpoly_divides_threaded_pool( nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong i, * Adegs, * Bdegs; int divides; TMP_INIT; TMP_START; divides = -1; if (A->bits <= FLINT_BITS && B->bits <= FLINT_BITS && A->length > 50) { Adegs = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Bdegs = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); if (num_handles > 0) { slong m = mpoly_divide_threads(num_handles, A->length, B->length); _degrees_arg_t arg; FLINT_ASSERT(m >= 0); FLINT_ASSERT(m < num_handles); arg->degs = Bdegs; arg->exps = B->exps; arg->length = B->length; arg->bits = B->bits; arg->mctx = ctx->minfo; arg->handles = handles + (m + 1); arg->num_handles = num_handles - (m + 1); thread_pool_wake(global_thread_pool, handles[m], 0, _worker_degrees, arg); mpoly_degrees_si_threaded(Adegs, A->exps, A->length, A->bits, ctx->minfo, handles + 0, m); thread_pool_wait(global_thread_pool, handles[m]); } else { mpoly_degrees_si(Adegs, A->exps, A->length, A->bits, ctx->minfo); mpoly_degrees_si(Bdegs, B->exps, B->length, B->bits, ctx->minfo); } /* quick degree check */ for (i = 0; i < ctx->minfo->nvars; i++) { if (Adegs[i] < Bdegs[i]) { nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } } if (_nmod_mpoly_divides_try_dense(Adegs, Bdegs, ctx->minfo->nvars, A->length, B->length)) { divides = nmod_mpoly_divides_dense(Q, A, B, ctx); } } if (divides == 0 || divides == 1) { /* have answer */ goto cleanup; } #ifdef _nmod_mpoly_divides_heap_threaded_pool if (num_handles > 0) { divides = _nmod_mpoly_divides_heap_threaded_pool(Q, A, B, ctx, handles, num_handles); } else { divides = nmod_mpoly_divides_monagan_pearce(Q, A, B, ctx); } #else divides = nmod_mpoly_divides_monagan_pearce(Q, A, B, ctx); #endif cleanup: TMP_END; return divides; } int nmod_mpoly_divides( nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { thread_pool_handle * handles; slong num_handles; slong thread_limit; int divides; if (B->length == 0) { if (A->length == 0 || nmod_mpoly_ctx_modulus(ctx) == 1) { nmod_mpoly_set(Q, A, ctx); return 1; } else { flint_throw(FLINT_DIVZERO, "nmod_mpoly_divides: divide by zero."); } } if (1 != n_gcd(B->coeffs[0], ctx->mod.n)) { flint_throw(FLINT_IMPINV, "nmod_mpoly_divides: leading coefficient is not invertible."); } thread_limit = A->length/1024; if (A->length <= 50) { return nmod_mpoly_divides_monagan_pearce(Q, A, B, ctx); } num_handles = flint_request_threads(&handles, thread_limit); divides = _nmod_mpoly_divides_threaded_pool(Q, A, B, ctx, handles, num_handles); flint_give_back_threads(handles, num_handles); return divides; } flint-3.1.3/src/nmod_mpoly/divides_dense.c000066400000000000000000000226101461254215100205510ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" /* Convert B to A if the degrees of A are <= expected_deg If not, return 0 and set A to 0. */ int nmod_mpoly_convert_from_nmod_mpolyd_degbound( nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, const nmod_mpolyd_t B, const nmod_mpolyd_ctx_t dctx, slong * expect_deg) { int ret; slong off, j, k, N; slong bits, nvars = ctx->minfo->nvars; slong Alen; slong * rexpect_deg, * perm = dctx->perm; slong perm_nontrivial; ulong topmask, outrange; ulong * exps, * pcurexp, * pexps, * rangemask; TMP_INIT; FLINT_ASSERT(nvars == B->nvars); FLINT_ASSERT(nvars <= FLINT_BITS); TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); rexpect_deg = (slong *) TMP_ALLOC(nvars*sizeof(slong)); /* find bits needed for the result */ off = 1; perm_nontrivial = 0; for (j = 0; j < nvars; j++) { rexpect_deg[j] = expect_deg[perm[j]]; FLINT_ASSERT(rexpect_deg[j] >= 0); off *= B->deg_bounds[j]; exps[perm[j]] = rexpect_deg[j]; perm_nontrivial |= j ^ perm[j]; } FLINT_ASSERT(off <= B->coeff_alloc); bits = mpoly_exp_bits_required_ui(exps, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); N = mpoly_words_per_exp(bits, ctx->minfo); /* we are going to push back terms manually */ nmod_mpoly_fit_length_reset_bits(A, 0, bits, ctx); Alen = 0; /* find exponent vector for all variables */ pexps = (ulong *) TMP_ALLOC(N*nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) { for (j = 0; j < nvars; j++) exps[perm[j]] = (j == k); mpoly_set_monomial_ui(pexps + k*N, exps, bits, ctx->minfo); } /* get most significant exponent in exps and its vector in ptempexp */ off--; pcurexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); rangemask = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); outrange = 0; mpoly_monomial_zero(pcurexp, N); k = off; for (j = nvars - 1; j >= 0; j--) { exps[j] = k % B->deg_bounds[j]; rangemask[j] = UWORD(1) << j; outrange ^= (outrange ^ FLINT_SIGN_EXT(rexpect_deg[j] - exps[j])) & rangemask[j]; k = k / B->deg_bounds[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } /* scan down through the exponents */ topmask = 0; for (; off >= 0; off--) { if (B->coeffs[off] != UWORD(0)) { if (outrange) goto failed_out_range; _nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, Alen + 1); A->coeffs[Alen] = B->coeffs[off]; mpoly_monomial_set(A->exps + N*Alen, pcurexp, N); topmask |= (A->exps + N*Alen)[N - 1]; Alen++; } j = nvars - 1; do { --exps[j]; outrange ^= (outrange ^ FLINT_SIGN_EXT(rexpect_deg[j] - exps[j])) & rangemask[j]; if ((slong)(exps[j]) < WORD(0)) { FLINT_ASSERT(off == 0 || j > 0); FLINT_ASSERT(exps[j] == -UWORD(1)); exps[j] = B->deg_bounds[j] - 1; outrange ^= (outrange ^ FLINT_SIGN_EXT(rexpect_deg[j] - exps[j])) & rangemask[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } else { mpoly_monomial_sub_mp(pcurexp, pcurexp, pexps + N*j, N); break; } } while (--j >= 0); } _nmod_mpoly_set_length(A, Alen, ctx); /* sort the exponents if needed */ if (ctx->minfo->ord != ORD_LEX || perm_nontrivial != WORD(0)) { slong msb; mpoly_get_cmpmask(pcurexp, N, bits, ctx->minfo); if (topmask != UWORD(0)) { msb = flint_clz(topmask); msb = (FLINT_BITS - 1)^msb; } else { msb = -WORD(1); } if (N == 1) { if (msb >= WORD(0)) { _nmod_mpoly_radix_sort1(A, 0, A->length, msb, pcurexp[0], topmask); } } else { _nmod_mpoly_radix_sort(A, 0, A->length, (N - 1)*FLINT_BITS + msb, N, pcurexp); } } ret = 1; done: TMP_END; return ret; failed_out_range: ret = 0; _nmod_mpoly_set_length(A, WORD(0), ctx); goto done; } /* return -1 : function failed 0 : B does not divide A 1 : B divides A and quotient is in Q */ int nmod_mpoly_divides_dense(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { int ret, success; slong i; slong nvars = ctx->minfo->nvars; nmod_mpolyd_ctx_t dctx; nmod_mpolyd_t Ad, Bd, Qd; nmod_poly_t Au, Bu, Qu, Ru; slong * Abounds, * Bbounds, * Qbounds, * Edegs; TMP_INIT; if (B->length == 0) { if (A->length == 0 || nmod_mpoly_ctx_modulus(ctx) == 1) { nmod_mpoly_set(Q, A, ctx); return 1; } else { flint_throw(FLINT_DIVZERO, "nmod_mpoly_divides_dense: divide by zero"); } } if (A->length == 0) { nmod_mpoly_zero(Q, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS || ctx->minfo->nvars > FLINT_BITS || ctx->minfo->nvars < 1) { return -1; } TMP_START; /* set the ordering of variables for the dense representation */ nmod_mpolyd_ctx_init(dctx, nvars); /* for each variable v we need to pack to degree deg_v(A) except for the outermost variable */ Abounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Bbounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Qbounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Edegs = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); mpoly_degrees_si(Abounds, A->exps, A->length, A->bits, ctx->minfo); mpoly_degrees_si(Bbounds, B->exps, B->length, B->bits, ctx->minfo); for (i = 0; i < ctx->minfo->nvars; i++) { /* if divides, expected degrees */ Edegs[i] = Abounds[i] - Bbounds[i]; if (Abounds[i] < Bbounds[i]) { ret = 0; nmod_mpoly_zero(Q, ctx); goto cleanup_stage1; } if (i != dctx->perm[0]) { /* variable of index i is not the outermost */ Qbounds[i] = Abounds[i] + 1; Bbounds[i] = Abounds[i] + 1; } else { /* variable of index i is the outermost */ Qbounds[i] = Abounds[i] - Bbounds[i] + 1; Bbounds[i] = Bbounds[i] + 1; } Abounds[i] = Abounds[i] + 1; if (Abounds[i] < WORD(0)) { ret = -1; nmod_mpoly_zero(Q, ctx); goto cleanup_stage1; } } nmod_mpolyd_init(Ad, nvars); nmod_mpolyd_init(Bd, nvars); nmod_mpolyd_init(Qd, nvars); success = 1; success = success && nmod_mpolyd_set_degbounds_perm(Ad, dctx, Abounds); success = success && nmod_mpolyd_set_degbounds_perm(Bd, dctx, Bbounds); success = success && nmod_mpolyd_set_degbounds_perm(Qd, dctx, Qbounds); if (!success) { ret = -1; goto cleanup_stage2; } nmod_mpoly_convert_to_nmod_mpolyd_degbound(Ad, dctx, A, ctx); nmod_mpoly_convert_to_nmod_mpolyd_degbound(Bd, dctx, B, ctx); /* let Au and Bu borrow Ad and Bd */ Au->alloc = Ad->coeff_alloc; Au->coeffs = Ad->coeffs; Au->length = nmod_mpolyd_length(Ad); Au->mod = ctx->mod; Bu->alloc = Bd->coeff_alloc; Bu->coeffs = Bd->coeffs; Bu->length = nmod_mpolyd_length(Bd); Bu->mod = ctx->mod; /* manually move Qd to Qu */ Qu->alloc = Qd->coeff_alloc; Qu->coeffs = Qd->coeffs; Qu->length = 0; Qu->mod = ctx->mod; nmod_poly_init_mod(Ru, ctx->mod); nmod_poly_divrem(Qu, Ru, Au, Bu); if (!nmod_poly_is_zero(Ru)) { ret = 0; goto cleanup_stage3; } nmod_poly_clear(Ru); /* manually move Qu to Qd */ Qd->coeff_alloc = Qu->alloc; Qd->coeffs = Qu->coeffs; for (i = Qu->length; i < Qd->coeff_alloc; i++) Qd->coeffs[i] = UWORD(0); nmod_mpolyd_clear(Bd); nmod_mpolyd_clear(Ad); ret = nmod_mpoly_convert_from_nmod_mpolyd_degbound(Q, ctx, Qd, dctx, Edegs); nmod_mpolyd_clear(Qd); nmod_mpolyd_ctx_clear(dctx); done: TMP_END; return ret; cleanup_stage3: nmod_poly_clear(Ru); cleanup_stage2: nmod_mpolyd_clear(Ad); nmod_mpolyd_clear(Bd); nmod_mpolyd_clear(Qd); cleanup_stage1: nmod_mpolyd_ctx_clear(dctx); goto done; } flint-3.1.3/src/nmod_mpoly/divides_heap_threaded.c000066400000000000000000001517571461254215100222470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" #if FLINT_KNOW_STRONG_ORDER #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "mpoly.h" #include "fmpz_mpoly.h" #define PROFILE_THIS 0 #if PROFILE_THIS #include "profiler.h" typedef struct _vec_slong_struct { slong * array; slong alloc; slong length; } vec_slong_struct; typedef vec_slong_struct vec_slong_t[1]; static void vec_slong_init(vec_slong_t v) { v->length = 0; v->alloc = 16; v->array = (slong *) flint_malloc(v->alloc*sizeof(slong)); } static void vec_slong_clear(vec_slong_t v) { flint_free(v->array); } static void vec_slong_push_back(vec_slong_t v, slong a) { v->length++; if (v->length > v->alloc) { v->alloc = FLINT_MAX(v->length, 2*v->alloc); v->array = (slong *) flint_realloc(v->array, v->alloc*sizeof(slong)); } v->array[v->length - 1] = a; } static void vec_slong_print(const vec_slong_t v) { slong i; flint_printf("["); for (i = 0; i < v->length; i++) { flint_printf("%wd",v->array[i]); if (i + 1 < v->length) { flint_printf(",",v->array[i]); } } flint_printf("]"); } #endif /* a thread safe mpoly supports three mutating operations - init from an array of terms - append an array of terms - clear out contents to a normal mpoly */ typedef struct _nmod_mpoly_ts_struct { mp_limb_t * volatile coeffs; /* this is coeff_array[idx] */ ulong * volatile exps; /* this is exp_array[idx] */ volatile slong length; slong alloc; flint_bitcnt_t bits; flint_bitcnt_t idx; mp_limb_t * exp_array[FLINT_BITS]; ulong * coeff_array[FLINT_BITS]; } nmod_mpoly_ts_struct; typedef nmod_mpoly_ts_struct nmod_mpoly_ts_t[1]; static void nmod_mpoly_ts_init(nmod_mpoly_ts_t A, mp_limb_t * Bcoeff, ulong * Bexp, slong Blen, flint_bitcnt_t bits, slong N) { slong i; flint_bitcnt_t idx = FLINT_BIT_COUNT(Blen); idx = (idx <= 8) ? 0 : idx - 8; for (i = 0; i < FLINT_BITS; i++) { A->exp_array[i] = NULL; A->coeff_array[i] = NULL; } A->bits = bits; A->idx = idx; A->alloc = WORD(256) << idx; A->exps = A->exp_array[idx] = (ulong *) flint_malloc(N*A->alloc*sizeof(ulong)); A->coeffs = A->coeff_array[idx] = (mp_limb_t *) flint_malloc(A->alloc*sizeof(mp_limb_t)); A->length = Blen; for (i = 0; i < Blen; i++) { A->coeffs[i] = Bcoeff[i]; mpoly_monomial_set(A->exps + N*i, Bexp + N*i, N); } } static void nmod_mpoly_ts_clear(nmod_mpoly_ts_t A) { slong i; for (i = 0; i < FLINT_BITS; i++) { if (A->exp_array[i] != NULL) { FLINT_ASSERT(A->coeff_array[i] != NULL); flint_free(A->coeff_array[i]); flint_free(A->exp_array[i]); } } } /* put B on the end of A */ static void nmod_mpoly_ts_append(nmod_mpoly_ts_t A, mp_limb_t * Bcoeff, ulong * Bexps, slong Blen, slong N) { /* TODO: this needs barriers on non-x86 */ slong i; ulong * oldexps = A->exps; ulong * oldcoeffs = A->coeffs; slong oldlength = A->length; slong newlength = A->length + Blen; if (newlength <= A->alloc) { /* write new terms first */ for (i = 0; i < Blen; i++) { oldcoeffs[oldlength + i] = Bcoeff[i]; mpoly_monomial_set(oldexps + N*(oldlength + i), Bexps + N*i, N); } } else { slong newalloc; ulong * newexps; mp_limb_t * newcoeffs; flint_bitcnt_t newidx; newidx = FLINT_BIT_COUNT(newlength - 1); newidx = (newidx > 8) ? newidx - 8 : 0; FLINT_ASSERT(newidx > A->idx); newalloc = UWORD(256) << newidx; FLINT_ASSERT(newlength <= newalloc); newexps = A->exp_array[newidx] = (ulong *) flint_malloc(N*newalloc*sizeof(ulong)); newcoeffs = A->coeff_array[newidx] = (mp_limb_t *) flint_malloc(newalloc*sizeof(mp_limb_t)); for (i = 0; i < oldlength; i++) { newcoeffs[i] = oldcoeffs[i]; mpoly_monomial_set(newexps + N*i, oldexps + N*i, N); } for (i = 0; i < Blen; i++) { newcoeffs[oldlength + i] = Bcoeff[i]; mpoly_monomial_set(newexps + N*(oldlength + i), Bexps + N*i, N); } A->alloc = newalloc; A->exps = newexps; A->coeffs = newcoeffs; A->idx = newidx; /* do not free oldcoeff/exps as other threads may be using them */ } /* update length at the very end */ A->length = newlength; } /* a chunk holds an exponent range on the dividend */ typedef struct _divides_heap_chunk_struct { nmod_mpoly_t polyC; struct _divides_heap_chunk_struct * next; ulong * emin; ulong * emax; slong startidx; slong endidx; int upperclosed; volatile int lock; volatile int producer; volatile slong ma; volatile slong mq; int Cinited; #if PROFILE_THIS slong idx; #endif } divides_heap_chunk_struct; typedef divides_heap_chunk_struct divides_heap_chunk_t[1]; /* the base struct includes a linked list of chunks */ typedef struct { #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif divides_heap_chunk_struct * head; divides_heap_chunk_struct * tail; divides_heap_chunk_struct * volatile cur; nmod_mpoly_t polyA; nmod_mpoly_t polyB; nmod_mpoly_ts_t polyQ; const nmod_mpoly_ctx_struct * ctx; slong length; slong N; flint_bitcnt_t bits; mp_limb_t lc_inv; ulong * cmpmask; int failed; #if PROFILE_THIS timeit_t timer; #endif } divides_heap_base_struct; typedef divides_heap_base_struct divides_heap_base_t[1]; /* the worker struct has a big chunk of memory in the stripe_t and two polys for work space */ typedef struct _worker_arg_struct { divides_heap_base_struct * H; nmod_mpoly_stripe_t S; nmod_mpoly_t polyT1; nmod_mpoly_t polyT2; #if PROFILE_THIS vec_slong_t time_data; #endif } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void divides_heap_base_init(divides_heap_base_t H) { H->head = NULL; H->tail = NULL; H->cur = NULL; H->ctx = NULL; H->length = 0; H->N = 0; H->bits = 0; H->cmpmask = NULL; } static void divides_heap_chunk_clear(divides_heap_chunk_t L, divides_heap_base_t H) { if (L->Cinited) { nmod_mpoly_clear(L->polyC, H->ctx); } } static int divides_heap_base_clear(nmod_mpoly_t Q, divides_heap_base_t H) { divides_heap_chunk_struct * L = H->head; while (L != NULL) { divides_heap_chunk_struct * nextL = L->next; divides_heap_chunk_clear(L, H); flint_free(L); L = nextL; } H->head = NULL; H->tail = NULL; H->cur = NULL; H->length = 0; H->N = 0; H->bits = 0; H->cmpmask = NULL; if (H->failed) { nmod_mpoly_zero(Q, H->ctx); nmod_mpoly_ts_clear(H->polyQ); return 0; } else { nmod_mpoly_ts_struct * A = H->polyQ; slong N = mpoly_words_per_exp(A->bits, H->ctx->minfo); if (Q->exps) flint_free(Q->exps); if (Q->coeffs) flint_free(Q->coeffs); Q->exps = A->exps; Q->coeffs = A->coeffs; Q->bits = A->bits; Q->length = A->length; Q->coeffs_alloc = A->alloc; Q->exps_alloc = N*A->alloc; A->coeff_array[A->idx] = NULL; A->exp_array[A->idx] = NULL; nmod_mpoly_ts_clear(A); return 1; } } static void divides_heap_base_add_chunk(divides_heap_base_t H, divides_heap_chunk_t L) { L->next = NULL; if (H->tail == NULL) { FLINT_ASSERT(H->head == NULL); H->tail = L; H->head = L; } else { divides_heap_chunk_struct * tail = H->tail; FLINT_ASSERT(tail->next == NULL); tail->next = L; H->tail = L; } H->length++; } /* A = D - (a stripe of B * C) S->startidx and S->endidx are assumed to be correct that is, we expect and successive calls to keep B decreasing C the same */ static void _nmod_mpoly_mulsub_stripe1( nmod_mpoly_t A, const mp_limb_t * Dcoeff, const ulong * Dexp, slong Dlen, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeff, const ulong * Cexp, slong Clen, const nmod_mpoly_stripe_t S) { int upperclosed; slong startidx, endidx; ulong prev_startidx; ulong maskhi = S->cmpmask[0]; ulong emax = S->emax[0]; ulong emin = S->emin[0]; slong i, j; slong next_loc = Blen + 4; /* something bigger than heap can ever be */ slong heap_len = 1; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; mp_limb_t * Acoeff = A->coeffs; ulong * Aexp = A->exps; ulong acc0, acc1, acc2, pp0, pp1; ulong exp; slong * ends; ulong texp; slong * hind; FLINT_ASSERT(S->N == 1); i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); ends = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); startidx = *S->startidx; endidx = *S->endidx; upperclosed = S->upperclosed; emax = S->emax[0]; emin = S->emin[0]; /* put all the starting nodes on the heap */ prev_startidx = -UWORD(1); for (i = 0; i < Blen; i++) { if (startidx < Clen) { texp = Bexp[i] + Cexp[startidx]; FLINT_ASSERT(mpoly_monomial_cmp1(emax, texp, maskhi) > -upperclosed); } while (startidx > 0) { texp = Bexp[i] + Cexp[startidx - 1]; if (mpoly_monomial_cmp1(emax, texp, maskhi) <= -upperclosed) { break; } startidx--; } if (endidx < Clen) { texp = Bexp[i] + Cexp[endidx]; FLINT_ASSERT(mpoly_monomial_cmp1(emin, texp, maskhi) > 0); } while (endidx > 0) { texp = Bexp[i] + Cexp[endidx - 1]; if (mpoly_monomial_cmp1(emin, texp, maskhi) <= 0) { break; } endidx--; } ends[i] = endidx; hind[i] = 2*startidx + 1; if ( (startidx < endidx) && (((ulong)startidx) < prev_startidx) ) { x = chain + i; x->i = i; x->j = startidx; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } prev_startidx = startidx; } /* set the indices for the next time mul is called */ *S->startidx = startidx; *S->endidx = endidx; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt1(Dexp[Di], exp, maskhi)) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, 1, Alen + 1); Acoeff[Alen] = Dcoeff[Di]; Aexp[Alen] = Dexp[Di]; Alen++; Di++; } _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, 1, Alen + 1); Aexp[Alen] = exp; acc0 = acc1 = acc2 = 0; if (Di < Dlen && Dexp[Di] == exp) { acc0 = S->mod.n - Dcoeff[Di]; Di++; } do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(Acoeff[Alen], acc2, acc1, acc0, S->mod); if (Acoeff[Alen] != 0) { Acoeff[Alen] = S->mod.n - Acoeff[Alen]; Alen++; } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < ends[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if ( (j + 1 < ends[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } } } FLINT_ASSERT(Di <= Dlen); if (Di < Dlen) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, 1, Alen + Dlen - Di); flint_mpn_copyi(Acoeff + Alen, Dcoeff + Di, Dlen - Di); mpoly_copy_monomials(Aexp + 1*Alen, Dexp + 1*Di, Dlen - Di, 1); Alen += Dlen - Di; } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; } static void _nmod_mpoly_mulsub_stripe( nmod_mpoly_t A, const mp_limb_t * Dcoeff, const ulong * Dexp, slong Dlen, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeff, const ulong * Cexp, slong Clen, const nmod_mpoly_stripe_t S) { int upperclosed; slong startidx, endidx; ulong prev_startidx; ulong * emax = S->emax; ulong * emin = S->emin; slong N = S->N; slong i, j; slong next_loc = Blen + 4; /* something bigger than heap can ever be */ slong heap_len = 1; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; mp_limb_t * Acoeff = A->coeffs; ulong * Aexp = A->exps; ulong acc0, acc1, acc2, pp0, pp1; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * ends; ulong * texp; slong * hind; i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); ends = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); exps = (ulong *)(S->big_mem + i); i += Blen*N*sizeof(ulong); exp_list = (ulong **)(S->big_mem + i); i += Blen*sizeof(ulong *); texp = (ulong *)(S->big_mem + i); i += N*sizeof(ulong); FLINT_ASSERT(i <= S->big_mem_alloc); exp_next = 0; startidx = *S->startidx; endidx = *S->endidx; upperclosed = S->upperclosed; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* put all the starting nodes on the heap */ prev_startidx = -UWORD(1); for (i = 0; i < Blen; i++) { if (startidx < Clen) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*startidx, N); FLINT_ASSERT(mpoly_monomial_cmp(emax, texp, N, S->cmpmask) > -upperclosed); } while (startidx > 0) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*(startidx - 1), N); if (mpoly_monomial_cmp(emax, texp, N, S->cmpmask) <= -upperclosed) { break; } startidx--; } if (endidx < Clen) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*endidx, N); FLINT_ASSERT(mpoly_monomial_cmp(emin, texp, N, S->cmpmask) > 0); } while (endidx > 0) { mpoly_monomial_add_mp(texp, Bexp + N*i, Cexp + N*(endidx - 1), N); if (mpoly_monomial_cmp(emin, texp, N, S->cmpmask) <= 0) { break; } endidx--; } ends[i] = endidx; hind[i] = 2*startidx + 1; if ( (startidx < endidx) && (((ulong)startidx) < prev_startidx) ) { x = chain + i; x->i = i; x->j = startidx; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, S->cmpmask)) exp_next--; } prev_startidx = startidx; } *S->startidx = startidx; *S->endidx = endidx; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt(Dexp + N*Di, exp, N, S->cmpmask)) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexp + N*Alen, Dexp + N*Di, N); Acoeff[Alen] = Dcoeff[Di]; Alen++; Di++; } _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexp + N*Alen, exp, N); acc0 = acc1 = acc2 = 0; if (Di < Dlen && mpoly_monomial_equal(Dexp + N*Di, exp, N)) { acc0 = S->mod.n - Dcoeff[Di]; Di++; } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(Acoeff[Alen], acc2, acc1, acc0, S->mod); if (Acoeff[Alen] != 0) { Acoeff[Alen] = S->mod.n - Acoeff[Alen]; Alen++; } /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < ends[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, S->cmpmask)) exp_next--; } /* should we go up? */ if ( (j + 1 < ends[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, S->cmpmask)) exp_next--; } } } FLINT_ASSERT(Di <= Dlen); if (Di < Dlen) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + Dlen - Di); flint_mpn_copyi(Acoeff + Alen, Dcoeff + Di, Dlen - Di); mpoly_copy_monomials(Aexp + N*Alen, Dexp + N*Di, Dlen - Di, N); Alen += Dlen - Di; } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; } /* Q = stripe of A/B (assume A != 0) return Qlen = 0 if exact division is impossible */ static int _nmod_mpoly_divides_stripe1( nmod_mpoly_t Q, const mp_limb_t * Acoeff, const ulong * Aexp, slong Alen, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const nmod_mpoly_stripe_t S) { flint_bitcnt_t bits = S->bits; ulong emin = S->emin[0]; ulong cmpmask = S->cmpmask[0]; ulong texp; int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Qlen; mp_limb_t * Qcoeff = Q->coeffs; ulong * Qexp = Q->exps; ulong exp; mp_limb_t acc0, acc1, acc2, pp1, pp0; ulong mask; slong * hind; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(S->N == 1); next_loc = Blen + 4; /* something bigger than heap can ever be */ i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); Qlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; HEAP_ASSIGN(heap[1], Aexp[0], x); FLINT_ASSERT(mpoly_monomial_cmp1(Aexp[0], emin, cmpmask) >= 0); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_exact_division; FLINT_ASSERT(mpoly_monomial_cmp1(exp, emin, cmpmask) >= 0); _nmod_mpoly_fit_length(&Qcoeff, &Q->coeffs_alloc, &Qexp, &Q->exps_alloc, 1, Alen + 1); lt_divides = mpoly_monomial_divides1(Qexp + Qlen, exp, Bexp[0], mask); acc0 = acc1 = acc2 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), WORD(0), S->mod.n - Acoeff[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, Bcoeff[x->i], Qcoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(Qcoeff[Qlen], acc2, acc1, acc0, S->mod); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; FLINT_ASSERT(mpoly_monomial_cmp1(Aexp[x->j], emin, cmpmask) >= 0); _mpoly_heap_insert1(heap, Aexp[x->j], x, &next_loc, &heap_len, cmpmask); } } else { /* should we go up */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } } } Qcoeff[Qlen] = nmod_mul(Qcoeff[Qlen], S->lc_minus_inv, S->mod); if (Qcoeff[Qlen] == 0) { continue; } if (!lt_divides) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } s = 1; Qlen++; } Q->coeffs = Qcoeff; Q->exps = Qexp; Q->length = Qlen; return 1; not_exact_division: Q->coeffs = Qcoeff; Q->exps = Qexp; Q->length = 0; return 0; } static int _nmod_mpoly_divides_stripe( nmod_mpoly_t Q, const mp_limb_t * Acoeff, const ulong * Aexp, slong Alen, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const nmod_mpoly_stripe_t S) { flint_bitcnt_t bits = S->bits; slong N = S->N; int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Qlen; mp_limb_t * Qcoeff = Q->coeffs; ulong * Qexp = Q->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; mp_limb_t acc0, acc1, acc2, pp1, pp0; ulong mask; slong * hind; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); next_loc = Blen + 4; /* something bigger than heap can ever be */ i = 0; hind = (slong *) (S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); exps = (ulong *)(S->big_mem + i); i += Blen*N*sizeof(ulong); exp_list = (ulong **)(S->big_mem + i); i += Blen*sizeof(ulong *); exp = (ulong *)(S->big_mem + i); i += N*sizeof(ulong); FLINT_ASSERT(i <= S->big_mem_alloc); exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; Qlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; FLINT_ASSERT(mpoly_monomial_cmp(Aexp + N*0, S->emin, N, S->cmpmask) >= 0); mpoly_monomial_set(heap[1].exp, Aexp + N*0, N); while (heap_len > 1) { _nmod_mpoly_fit_length(&Qcoeff, &Q->coeffs_alloc, &Qexp, &Q->exps_alloc, N, Qlen + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; lt_divides = mpoly_monomial_divides(Qexp + N*Qlen, exp, Bexp + N*0, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto not_exact_division; lt_divides = mpoly_monomial_divides_mp(Qexp + N*Qlen, exp, Bexp + N*0, N, bits); } FLINT_ASSERT(mpoly_monomial_cmp(exp, S->emin, N, S->cmpmask) >= 0); acc0 = acc1 = acc2 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), WORD(0), S->mod.n - Acoeff[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, Bcoeff[x->i], Qcoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(Qcoeff[Qlen], acc2, acc1, acc0, S->mod); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexp + x->j*N, N); FLINT_ASSERT(mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } } else { /* should we go up */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } } } Qcoeff[Qlen] = nmod_mul(Qcoeff[Qlen], S->lc_minus_inv, S->mod); if (Qcoeff[Qlen] == 0) { continue; } if (!lt_divides) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } s = 1; Qlen++; } Q->coeffs = Qcoeff; Q->exps = Qexp; Q->length = Qlen; return 1; not_exact_division: Q->coeffs = Qcoeff; Q->exps = Qexp; Q->length = 0; return 0; } static slong chunk_find_exp(ulong * exp, slong a, const divides_heap_base_t H) { slong N = H->N; slong b = H->polyA->length; const ulong * Aexp = H->polyA->exps; try_again: FLINT_ASSERT(b >= a); FLINT_ASSERT(a > 0); FLINT_ASSERT(mpoly_monomial_cmp(Aexp + N*(a - 1), exp, N, H->cmpmask) >= 0); FLINT_ASSERT(b >= H->polyA->length || mpoly_monomial_cmp(Aexp + N*b, exp, N, H->cmpmask) < 0); if (b - a < 5) { slong i = a; while (i < b && mpoly_monomial_cmp(Aexp + N*i, exp, N, H->cmpmask) >= 0) { i++; } return i; } else { slong c = a + (b - a)/2; if (mpoly_monomial_cmp(Aexp + N*c, exp, N, H->cmpmask) < 0) { b = c; } else { a = c; } goto try_again; } } static void stripe_fit_length(nmod_mpoly_stripe_struct * S, slong new_len) { slong N = S->N; slong new_alloc; new_alloc = 0; if (N == 1) { new_alloc += new_len*sizeof(slong); new_alloc += new_len*sizeof(slong); new_alloc += 2*new_len*sizeof(slong); new_alloc += (new_len + 1)*sizeof(mpoly_heap1_s); new_alloc += new_len*sizeof(mpoly_heap_t); } else { new_alloc += new_len*sizeof(slong); new_alloc += new_len*sizeof(slong); new_alloc += 2*new_len*sizeof(slong); new_alloc += (new_len + 1)*sizeof(mpoly_heap_s); new_alloc += new_len*sizeof(mpoly_heap_t); new_alloc += new_len*N*sizeof(ulong); new_alloc += new_len*sizeof(ulong *); new_alloc += N*sizeof(ulong); } if (S->big_mem_alloc >= new_alloc) { return; } new_alloc = FLINT_MAX(new_alloc, S->big_mem_alloc + S->big_mem_alloc/4); S->big_mem_alloc = new_alloc; if (S->big_mem != NULL) { S->big_mem = (char *) flint_realloc(S->big_mem, new_alloc); } else { S->big_mem = (char *) flint_malloc(new_alloc); } } static void chunk_mulsub(worker_arg_t W, divides_heap_chunk_t L, slong q_prev_length) { divides_heap_base_struct * H = W->H; slong N = H->N; nmod_mpoly_struct * C = L->polyC; const nmod_mpoly_struct * B = H->polyB; const nmod_mpoly_struct * A = H->polyA; nmod_mpoly_ts_struct * Q = H->polyQ; nmod_mpoly_struct * T1 = W->polyT1; nmod_mpoly_stripe_struct * S = W->S; S->startidx = &L->startidx; S->endidx = &L->endidx; S->emin = L->emin; S->emax = L->emax; S->upperclosed = L->upperclosed; FLINT_ASSERT(S->N == N); stripe_fit_length(S, q_prev_length - L->mq); if (L->Cinited) { if (N == 1) { _nmod_mpoly_mulsub_stripe1(T1, C->coeffs, C->exps, C->length, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } else { _nmod_mpoly_mulsub_stripe(T1, C->coeffs, C->exps, C->length, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } nmod_mpoly_swap(C, T1, H->ctx); } else { slong startidx, stopidx; if (L->upperclosed) { startidx = 0; stopidx = chunk_find_exp(L->emin, 1, H); } else { startidx = chunk_find_exp(L->emax, 1, H); stopidx = chunk_find_exp(L->emin, startidx, H); } L->Cinited = 1; nmod_mpoly_init3(C, 16 + stopidx - startidx, H->bits, H->ctx); /*any is OK*/ if (N == 1) { _nmod_mpoly_mulsub_stripe1(C, A->coeffs + startidx, A->exps + N*startidx, stopidx - startidx, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } else { _nmod_mpoly_mulsub_stripe(C, A->coeffs + startidx, A->exps + N*startidx, stopidx - startidx, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } } L->mq = q_prev_length; } static void trychunk(worker_arg_t W, divides_heap_chunk_t L) { divides_heap_base_struct * H = W->H; slong i; slong N = H->N; nmod_mpoly_struct * C = L->polyC; slong q_prev_length; ulong mask; const nmod_mpoly_struct * B = H->polyB; const nmod_mpoly_struct * A = H->polyA; nmod_mpoly_ts_struct * Q = H->polyQ; nmod_mpoly_struct * T2 = W->polyT2; mask = 0; for (i = 0; i < FLINT_BITS/H->bits; i++) mask = (mask << H->bits) + (UWORD(1) << (H->bits - 1)); /* return if this section has already finished processing */ if (L->mq < 0) { return; } /* process more quotient terms if available */ q_prev_length = Q->length; if (q_prev_length > L->mq) { if (L->producer == 0 && q_prev_length - L->mq < 20) return; #if PROFILE_THIS vec_slong_push_back(W->time_data, 4*L->idx + 0); vec_slong_push_back(W->time_data, timeit_query_wall(H->timer)); #endif chunk_mulsub(W, L, q_prev_length); #if PROFILE_THIS vec_slong_push_back(W->time_data, 4*L->idx + 1); vec_slong_push_back(W->time_data, timeit_query_wall(H->timer)); #endif } if (L->producer == 1) { divides_heap_chunk_struct * next; mp_limb_t * Rcoeff; ulong * Rexp; slong Rlen; #if PROFILE_THIS vec_slong_push_back(W->time_data, 4*L->idx + 2); vec_slong_push_back(W->time_data, timeit_query_wall(H->timer)); #endif /* process the remaining quotient terms */ q_prev_length = Q->length; if (q_prev_length > L->mq) { chunk_mulsub(W, L, q_prev_length); } /* find location of remaining terms */ if (L->Cinited) { Rlen = C->length; Rexp = C->exps; Rcoeff = C->coeffs; } else { slong startidx, stopidx; if (L->upperclosed) { startidx = 0; stopidx = chunk_find_exp(L->emin, 1, H); } else { startidx = chunk_find_exp(L->emax, 1, H); stopidx = chunk_find_exp(L->emin, startidx, H); } Rlen = stopidx - startidx; Rcoeff = A->coeffs + startidx; Rexp = A->exps + N*startidx; } /* if we have remaining terms, add to quotient */ if (Rlen > 0) { int divides; nmod_mpoly_stripe_struct * S = W->S; S->startidx = &L->startidx; S->endidx = &L->endidx; S->emin = L->emin; S->emax = L->emax; S->upperclosed = L->upperclosed; if (N == 1) { divides = _nmod_mpoly_divides_stripe1(T2, Rcoeff, Rexp, Rlen, B->coeffs, B->exps, B->length, S); } else { divides = _nmod_mpoly_divides_stripe(T2, Rcoeff, Rexp, Rlen, B->coeffs, B->exps, B->length, S); } if (!divides) { #if PROFILE_THIS vec_slong_push_back(W->time_data, 4*L->idx + 3); vec_slong_push_back(W->time_data, timeit_query_wall(H->timer)); #endif H->failed = 1; return; } else { nmod_mpoly_ts_append(H->polyQ, T2->coeffs, T2->exps, T2->length, N); } } #if PROFILE_THIS vec_slong_push_back(W->time_data, 4*L->idx + 3); vec_slong_push_back(W->time_data, timeit_query_wall(H->timer)); #endif next = L->next; H->length--; H->cur = next; if (next != NULL) { next->producer = 1; } L->producer = 0; L->mq = -1; } return; } static void worker_loop(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; divides_heap_base_struct * H = W->H; nmod_mpoly_stripe_struct * S = W->S; const nmod_mpoly_struct * B = H->polyB; nmod_mpoly_struct * T1 = W->polyT1; nmod_mpoly_struct * T2 = W->polyT2; slong N = H->N; slong Blen = B->length; /* initialize stripe working memory */ S->N = N; S->bits = H->bits; S->ctx = H->ctx; S->cmpmask = H->cmpmask; S->big_mem_alloc = 0; S->big_mem = NULL; S->mod = H->ctx->mod; S->lc_minus_inv = S->mod.n - H->lc_inv; stripe_fit_length(S, Blen); nmod_mpoly_init3(T1, 16, H->bits, H->ctx); nmod_mpoly_init3(T2, 16, H->bits, H->ctx); while (!H->failed) { divides_heap_chunk_struct * L; L = H->cur; if (L == NULL) { break; } while (L != NULL) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&H->mutex); #endif if (L->lock != -1) { L->lock = -1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif trychunk(W, L); #if FLINT_USES_PTHREAD pthread_mutex_lock(&H->mutex); #endif L->lock = 0; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif break; } else { #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif } L = L->next; } } nmod_mpoly_clear(T1, H->ctx); nmod_mpoly_clear(T2, H->ctx); flint_free(S->big_mem); return; } /* return 1 if quotient is exact. The leading coefficient of B should be invertible. */ int _nmod_mpoly_divides_heap_threaded_pool( nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { ulong mask; int divides; fmpz_mpoly_ctx_t zctx; fmpz_mpoly_t S; slong i, k, N; flint_bitcnt_t exp_bits; ulong * cmpmask; ulong * Aexp, * Bexp; int freeAexp, freeBexp; worker_arg_struct * worker_args; mp_limb_t qcoeff; ulong * texps, * qexps; divides_heap_base_t H; #if PROFILE_THIS slong idx = 0; #endif TMP_INIT; if (B->length < 2 || A->length < 2) { return nmod_mpoly_divides_monagan_pearce(Q, A, B, ctx); } TMP_START; exp_bits = MPOLY_MIN_BITS; exp_bits = FLINT_MAX(exp_bits, A->bits); exp_bits = FLINT_MAX(exp_bits, B->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ Aexp = A->exps; freeAexp = 0; if (exp_bits > A->bits) { freeAexp = 1; Aexp = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexp, exp_bits, A->exps, A->bits, A->length, ctx->minfo); } Bexp = B->exps; freeBexp = 0; if (exp_bits > B->bits) { freeBexp = 1; Bexp = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexp, exp_bits, B->exps, B->bits, B->length, ctx->minfo); } fmpz_mpoly_ctx_init(zctx, ctx->minfo->nvars, ctx->minfo->ord); fmpz_mpoly_init(S, zctx); if (mpoly_divides_select_exps(S, zctx, num_handles, Aexp, A->length, Bexp, B->length, exp_bits)) { divides = 0; nmod_mpoly_zero(Q, ctx); goto cleanup1; } /* At this point A and B both have at least two terms and the exponent selection did not give an easy exit. Since we are possibly holding threads, we should try to not throw, so the leading coefficient should already have been checked for invertibility. */ divides_heap_base_init(H); qcoeff = n_gcdinv(&H->lc_inv, B->coeffs[0], ctx->mod.n); FLINT_ASSERT(qcoeff == 1); /* gcd should be one */ H->polyA->coeffs = A->coeffs; H->polyA->exps = Aexp; H->polyA->bits = exp_bits; H->polyA->length = A->length; H->polyA->coeffs_alloc = A->coeffs_alloc; H->polyA->exps_alloc = A->exps_alloc; H->polyB->coeffs = B->coeffs; H->polyB->exps = Bexp; H->polyB->bits = exp_bits; H->polyB->length = B->length; H->polyB->coeffs_alloc = B->coeffs_alloc; H->polyB->exps_alloc = B->coeffs_alloc; H->ctx = ctx; H->bits = exp_bits; H->N = N; H->cmpmask = cmpmask; H->failed = 0; for (i = 0; i + 1 < S->length; i++) { divides_heap_chunk_struct * L; L = (divides_heap_chunk_struct *) flint_malloc( sizeof(divides_heap_chunk_struct)); L->ma = 0; L->mq = 0; L->emax = S->exps + N*i; L->emin = S->exps + N*(i + 1); L->upperclosed = 0; L->startidx = B->length; L->endidx = B->length; L->producer = 0; L->Cinited = 0; L->lock = -2; #if PROFILE_THIS L->idx = idx++; #endif divides_heap_base_add_chunk(H, L); } H->head->upperclosed = 1; H->head->producer = 1; H->cur = H->head; /* generate at least the first quotient terms */ texps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); qexps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_sub_mp(qexps + N*0, Aexp + N*0, Bexp + N*0, N); qcoeff = nmod_mul(H->lc_inv, A->coeffs[0], ctx->mod); nmod_mpoly_ts_init(H->polyQ, &qcoeff, qexps, 1, H->bits, H->N); mpoly_monomial_add_mp(texps, qexps + N*0, Bexp + N*1, N); mask = 0; for (i = 0; i < FLINT_BITS/exp_bits; i++) mask = (mask << exp_bits) + (UWORD(1) << (exp_bits - 1)); k = 1; while (k < A->length && mpoly_monomial_gt(Aexp + N*k, texps, N, cmpmask)) { int lt_divides; if (exp_bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(qexps, Aexp + N*k, Bexp + N*0, N, mask); else lt_divides = mpoly_monomial_divides_mp(qexps, Aexp + N*k, Bexp + N*0, N, exp_bits); if (!lt_divides) { H->failed = 1; break; } qcoeff = nmod_mul(H->lc_inv, A->coeffs[k], ctx->mod); nmod_mpoly_ts_append(H->polyQ, &qcoeff, qexps, 1, H->N); k++; } /* start the workers */ #if FLINT_USES_PTHREAD pthread_mutex_init(&H->mutex, NULL); #endif worker_args = (worker_arg_struct *) flint_malloc((num_handles + 1) *sizeof(worker_arg_t)); #if PROFILE_THIS for (i = 0; i < num_handles + 1; i++) { vec_slong_init((worker_args + i)->time_data); } timeit_start(H->timer); #endif for (i = 0; i < num_handles; i++) { (worker_args + i)->H = H; thread_pool_wake(global_thread_pool, handles[i], 0, worker_loop, worker_args + i); } (worker_args + num_handles)->H = H; worker_loop(worker_args + num_handles); for (i = 0; i < num_handles; i++) thread_pool_wait(global_thread_pool, handles[i]); #if PROFILE_THIS timeit_stop(H->timer); flint_printf("data = ["); for (i = 0; i < num_handles + 1; i++) { flint_printf("[%wd,", i); vec_slong_print((worker_args + i)->time_data); flint_printf("],\n"); vec_slong_clear((worker_args + i)->time_data); } flint_printf("%wd]\n", H->timer->wall); #endif flint_free(worker_args); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&H->mutex); #endif divides = divides_heap_base_clear(Q, H); cleanup1: fmpz_mpoly_clear(S, zctx); fmpz_mpoly_ctx_clear(zctx); if (freeAexp) flint_free(Aexp); if (freeBexp) flint_free(Bexp); TMP_END; return divides; } int nmod_mpoly_divides_heap_threaded( nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { thread_pool_handle * handles; slong num_handles; int divides; slong thread_limit = A->length/32; if (B->length == 0) { if (A->length == 0 || nmod_mpoly_ctx_modulus(ctx) == 1) { nmod_mpoly_set(Q, A, ctx); return 1; } else { flint_throw(FLINT_DIVZERO, "nmod_mpoly_divides_heap_threaded: divide by zero"); } } if (B->length < 2 || A->length < 2) { if (A->length == 0) { nmod_mpoly_zero(Q, ctx); return 1; } return nmod_mpoly_divides_monagan_pearce(Q, A, B, ctx); } if (1 != n_gcd(B->coeffs[0], ctx->mod.n)) { flint_throw(FLINT_IMPINV, "nmod_mpoly_divides_heap_threaded: Cannot invert leading coefficient"); } num_handles = flint_request_threads(&handles, thread_limit); divides = _nmod_mpoly_divides_heap_threaded_pool(Q, A, B, ctx, handles, num_handles); flint_give_back_threads(handles, num_handles); return divides; } #else typedef int this_file_is_empty; #endif flint-3.1.3/src/nmod_mpoly/divides_monagan_pearce.c000066400000000000000000000443761461254215100224270ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" static int _nmod_mpoly_divides_monagan_pearce1( nmod_mpoly_t Q, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, slong bits, ulong maskhi, nmod_t fctx) { int lt_divides; slong i, j, q_len, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * q_coeff = Q->coeffs; ulong * q_exp = Q->exps; slong * hind; ulong mask, exp, maxexp = exp2[len2 - 1]; mp_limb_t lc_minus_inv, acc0, acc1, acc2, pp1, pp0; TMP_INIT; TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); q_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0], x); /* precompute leading coefficient info */ lc_minus_inv = fctx.n - nmod_inv(coeff3[0], fctx); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_exact_division; _nmod_mpoly_fit_length(&q_coeff, &Q->coeffs_alloc, &q_exp, &Q->exps_alloc, 1, q_len + 1); lt_divides = mpoly_monomial_divides1(q_exp + q_len, exp, exp3[0], mask); acc0 = acc1 = acc2 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), WORD(0), fctx.n - coeff2[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, coeff3[x->i], q_coeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(q_coeff[q_len], acc2, acc1, acc0, fctx); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, exp2[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } } } q_coeff[q_len] = nmod_mul(q_coeff[q_len], lc_minus_inv, fctx); if (q_coeff[q_len] == 0) { continue; } if (!lt_divides || (exp^maskhi) < (maxexp^maskhi)) goto not_exact_division; /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp3[x->i] + q_exp[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; q_len++; } Q->coeffs = q_coeff; Q->exps = q_exp; Q->length = q_len; TMP_END; return 1; not_exact_division: Q->coeffs = q_coeff; Q->exps = q_exp; Q->length = 0; TMP_END; return 0; } int _nmod_mpoly_divides_monagan_pearce( nmod_mpoly_t Q, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, nmod_t fctx) { int lt_divides; slong i, j, q_len, s; slong next_loc, heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * q_coeff = Q->coeffs; ulong * q_exp = Q->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; mp_limb_t lc_minus_inv, acc0, acc1, acc2, pp1, pp0; ulong mask; slong * hind; TMP_INIT; if (N == 1) return _nmod_mpoly_divides_monagan_pearce1(Q, coeff2, exp2, len2, coeff3, exp3, len3, bits, cmpmask[0], fctx); TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len3*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*len3*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(len3*sizeof(slong)); for (i = 0; i < len3; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; q_len = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = len3; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, exp2, N); /* precompute leading coefficient info */ lc_minus_inv = fctx.n - nmod_inv(coeff3[0], fctx); while (heap_len > 1) { _nmod_mpoly_fit_length(&q_coeff, &Q->coeffs_alloc, &q_exp, &Q->exps_alloc, N, q_len + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; lt_divides = mpoly_monomial_divides(q_exp + q_len*N, exp, exp3, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto not_exact_division; lt_divides = mpoly_monomial_divides_mp(q_exp + q_len*N, exp, exp3, N, bits); } acc0 = acc1 = acc2 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), WORD(0), fctx.n - coeff2[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, coeff3[x->i], q_coeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(q_coeff[q_len], acc2, acc1, acc0, fctx); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < len2) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], exp2 + x->j*N, N); if (!_mpoly_heap_insert(heap, exp_list[exp_next++], x, &next_loc, &heap_len, N, cmpmask)) exp_next--; } } else { /* should we go up */ if ( (i + 1 < len3) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } q_coeff[q_len] = nmod_mul(q_coeff[q_len], lc_minus_inv, fctx); if (q_coeff[q_len] == 0) { continue; } if (!lt_divides || mpoly_monomial_gt(exp2 + N*(len2 - 1), exp, N, cmpmask)) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = q_len; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp3 + x->i*N, q_exp + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; q_len++; } Q->coeffs = q_coeff; Q->exps = q_exp; Q->length = q_len; TMP_END; return 1; not_exact_division: Q->coeffs = q_coeff; Q->exps = q_exp; Q->length = 0; TMP_END; return 0; } /* return 1 if quotient is exact */ int nmod_mpoly_divides_monagan_pearce( nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t Qbits; fmpz * Amaxfields, * Bmaxfields; ulong * cmpmask; ulong * exp2 = A->exps, * exp3 = B->exps, * expq; int divides, easy_exit, free2 = 0, free3 = 0; ulong mask = 0; TMP_INIT; if (B->length == 0) { if (A->length == 0 || nmod_mpoly_ctx_modulus(ctx) == 1) { nmod_mpoly_set(Q, A, ctx); return 1; } else { flint_throw(FLINT_DIVZERO, "nmod_mpoly_divides_monagan_pearce: divide by zero"); } } if (A->length == 0) { nmod_mpoly_zero(Q, ctx); return 1; } TMP_START; Amaxfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); Bmaxfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(Amaxfields + i); fmpz_init(Bmaxfields + i); } mpoly_max_fields_fmpz(Amaxfields, A->exps, A->length, A->bits, ctx->minfo); mpoly_max_fields_fmpz(Bmaxfields, B->exps, B->length, B->bits, ctx->minfo); easy_exit = 0; for (i = 0; i < ctx->minfo->nfields; i++) { /* cannot be exact division if any max field from A is less than corresponding max field from B */ if (fmpz_cmp(Amaxfields + i, Bmaxfields + i) < 0) easy_exit = 1; } Qbits = 1 + _fmpz_vec_max_bits(Amaxfields, ctx->minfo->nfields); Qbits = FLINT_MAX(Qbits, A->bits); Qbits = FLINT_MAX(Qbits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(Amaxfields + i); fmpz_clear(Bmaxfields + i); } if (easy_exit) { nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* temporary space to check leading monomials divide */ expq = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* quick check for easy case of inexact division of leading monomials */ if (Qbits == A->bits && Qbits == B->bits && A->exps[N - 1] < B->exps[N - 1]) { nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } /* ensure input exponents packed to same size as output exponents */ if (Qbits > A->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(exp2, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits > B->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(exp3, Qbits, B->exps, B->bits, B->length, ctx->minfo); } /* check leading monomial divides exactly */ if (Qbits <= FLINT_BITS) { /* mask with high bit of each exponent vector field set */ for (i = 0; i < FLINT_BITS/Qbits; i++) mask = (mask << Qbits) + (UWORD(1) << (Qbits - 1)); if (!mpoly_monomial_divides(expq, exp2, exp3, N, mask)) { nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } } else { if (!mpoly_monomial_divides_mp(expq, exp2, exp3, N, Qbits)) { nmod_mpoly_zero(Q, ctx); divides = 0; goto cleanup; } } /* deal with aliasing and divide polynomials */ if (Q == A || Q == B) { nmod_mpoly_t temp; nmod_mpoly_init3(temp, A->length/B->length + 1, Qbits, ctx); divides = _nmod_mpoly_divides_monagan_pearce(temp, A->coeffs, exp2, A->length, B->coeffs, exp3, B->length, Qbits, N, cmpmask, ctx->mod); nmod_mpoly_swap(temp, Q, ctx); nmod_mpoly_clear(temp, ctx); } else { nmod_mpoly_fit_length_reset_bits(Q, A->length/B->length + 1, Qbits, ctx); divides = _nmod_mpoly_divides_monagan_pearce(Q, A->coeffs, exp2, A->length, B->coeffs, exp3, B->length, Qbits, N, cmpmask, ctx->mod); } cleanup: if (free2) flint_free(exp2); if (free3) flint_free(exp3); TMP_END; return divides; } flint-3.1.3/src/nmod_mpoly/divrem.c000066400000000000000000000012001461254215100172220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" void nmod_mpoly_divrem(nmod_mpoly_t Q, nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { /* TODO !!! */ nmod_mpoly_divrem_monagan_pearce(Q, R, A, B, ctx); } flint-3.1.3/src/nmod_mpoly/divrem_ideal.c000066400000000000000000000013221461254215100203650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" void nmod_mpoly_divrem_ideal(nmod_mpoly_struct ** Q, nmod_mpoly_t R, const nmod_mpoly_t A, nmod_mpoly_struct * const * B, slong len, const nmod_mpoly_ctx_t ctx) { /* TODO !!! */ nmod_mpoly_divrem_ideal_monagan_pearce(Q, R, A, B, len, ctx); } flint-3.1.3/src/nmod_mpoly/divrem_ideal_monagan_pearce.c000066400000000000000000000474511461254215100234210ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" /* As for divrem_monagan_pearce1 except that an array of divisor polynomials is passed and an array of quotient polynomials is returned. These are not in low level format. */ int _nmod_mpoly_divrem_ideal_monagan_pearce1( nmod_mpoly_struct ** Q, nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, nmod_mpoly_struct * const * Bs, ulong * const * Bexps, slong Blen, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx, ulong maskhi) { slong i, j, p, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_nheap_t ** chains, * chains_ptr; slong ** hinds, * hinds_ptr; mpoly_nheap_t * x; mp_limb_t * r_coeff = R->coeffs; ulong * r_exp = R->exps; slong r_len; ulong exp, texp; ulong mask; slong * q_len, * s; mp_limb_t * lc_minus_inv, acc0, acc1, acc2, pp1, pp0; TMP_INIT; TMP_START; chains = TMP_ARRAY_ALLOC(Blen, mpoly_nheap_t *); hinds = TMP_ARRAY_ALLOC(Blen, slong *); /* chains[w], hinds[w] will be arrays of length Bs[w]->length; combine the allocations*/ len3 = 0; for (w = 0; w < Blen; w++) len3 += Bs[w]->length; chains_ptr = TMP_ARRAY_ALLOC(len3, mpoly_nheap_t); hinds_ptr = TMP_ARRAY_ALLOC(len3, slong); len3 = 0; for (w = 0; w < Blen; w++) { chains[w] = chains_ptr + len3; hinds[w] = hinds_ptr + len3; len3 += Bs[w]->length; for (i = 0; i < Bs[w]->length; i++) hinds[w][i] = 1; } next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap1_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong *)); q_len = (slong *) TMP_ALLOC(Blen*sizeof(slong)); s = (slong *) TMP_ALLOC(Blen*sizeof(slong)); mask = mpoly_overflow_mask_sp(bits); for (w = 0; w < Blen; w++) { q_len[w] = WORD(0); s[w] = Bs[w]->length; } r_len = WORD(0); x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; HEAP_ASSIGN(heap[1], Aexps[0], x); /* precompute leading coeff info */ lc_minus_inv = (mp_limb_t *) TMP_ALLOC(Blen*sizeof(mp_limb_t)); for (w = 0; w < Blen; w++) lc_minus_inv[w] = ctx->mod.n - nmod_inv(Bs[w]->coeffs[0], ctx->mod); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; acc0 = acc1 = acc2 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i != -WORD(1)) hinds[x->p][x->i] |= WORD(1); if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), WORD(0), ctx->mod.n - Acoeffs[x->j]); } else { umul_ppmm(pp1, pp0, Bs[x->p]->coeffs[x->i], Q[x->p]->coeffs[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(acc0, acc2, acc1, acc0, ctx->mod); while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < Alen) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; _mpoly_heap_insert1(heap, Aexps[x->j], x, &next_loc, &heap_len, maskhi); } } else { if ( (i + 1 < Bs[p]->length) && (hinds[p][i + 1] == 2*j + 1) ) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->p][x->i] + Q[x->p]->exps[x->j], x, &next_loc, &heap_len, maskhi); } if (j + 1 == q_len[p]) { s[p]++; } else if ( ((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1)) ) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->p][x->i] + Q[x->p]->exps[x->j], x, &next_loc, &heap_len, maskhi); } } } if (acc0 == 0) continue; for (w = 0; w < Blen; w++) { if (mpoly_monomial_divides1(&texp, exp, Bexps[w][0], mask)) { nmod_mpoly_fit_length(Q[w], q_len[w] + 1, ctx); Q[w]->coeffs[q_len[w]] = nmod_mul(acc0, lc_minus_inv[w], ctx->mod); Q[w]->exps[q_len[w]] = texp; if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = q_len[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[w][x->i] + Q[w]->exps[x->j], x, &next_loc, &heap_len, maskhi); } s[w] = 1; q_len[w]++; goto break_continue; /* break out of w for loop and continue in heap loop */ } } /* if get here, no leading terms divided */ _nmod_mpoly_fit_length(&r_coeff, &R->coeffs_alloc, &r_exp, &R->exps_alloc, 1, r_len + 1); r_coeff[r_len] = ctx->mod.n - acc0; r_exp[r_len] = exp; r_len++; break_continue:; } R->coeffs = r_coeff; R->exps = r_exp; R->length = r_len; for (i = 0; i < Blen; i++) Q[i]->length = q_len[i]; TMP_END; return 1; exp_overflow: R->coeffs = r_coeff; R->exps = r_exp; R->length = 0; for (i = 0; i < Blen; i++) Q[i]->length = 0; TMP_END; return 0; } /* As for divrem_monagan_pearce except that an array of divisor polynomials is passed and an array of quotient polynomials is returned. These are not in low level format. */ int _nmod_mpoly_divrem_ideal_monagan_pearce( nmod_mpoly_struct ** Q, nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, nmod_mpoly_struct * const * Bs, ulong * const * Bexps, slong Blen, slong N, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx, const ulong * cmpmask) { slong i, j, p, w; slong next_loc; slong * store, * store_base; slong len3; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_nheap_t ** chains; slong ** hinds; mpoly_nheap_t * x; mp_limb_t * r_coeff = R->coeffs; ulong * r_exp = R->exps; slong r_len; ulong * exp, * exps, * texp; ulong ** exp_list; slong exp_next; ulong mask; slong * q_len, * s; mp_limb_t * lc_minus_inv, acc0, acc1, acc2, pp1, pp0; TMP_INIT; if (N == 1) { return _nmod_mpoly_divrem_ideal_monagan_pearce1(Q, R, Acoeffs, Aexps, Alen, Bs, Bexps, Blen, bits, ctx, cmpmask[0]); } TMP_START; chains = (mpoly_nheap_t **) TMP_ALLOC(Blen*sizeof(mpoly_nheap_t *)); hinds = (slong **) TMP_ALLOC(Blen*sizeof(mpoly_heap_t *)); len3 = 0; for (w = 0; w < Blen; w++) { chains[w] = (mpoly_nheap_t *) TMP_ALLOC((Bs[w]->length)*sizeof(mpoly_nheap_t)); hinds[w] = (slong *) TMP_ALLOC((Bs[w]->length)*sizeof(slong)); len3 += Bs[w]->length; for (i = 0; i < Bs[w]->length; i++) hinds[w][i] = 1; } next_loc = len3 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len3 + 1)*sizeof(mpoly_heap_s)); store = store_base = (slong *) TMP_ALLOC(3*len3*sizeof(slong *)); exps = (ulong *) TMP_ALLOC(len3*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len3*sizeof(ulong *)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); q_len = (slong *) TMP_ALLOC(Blen*sizeof(slong)); s = (slong *) TMP_ALLOC(Blen*sizeof(slong)); exp_next = 0; for (i = 0; i < len3; i++) exp_list[i] = exps + i*N; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; for (w = 0; w < Blen; w++) { q_len[w] = WORD(0); s[w] = Bs[w]->length; } r_len = WORD(0); x = chains[0] + 0; x->i = -WORD(1); x->j = 0; x->p = -WORD(1); x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coeff info */ lc_minus_inv = (mp_limb_t *) TMP_ALLOC(Blen*sizeof(mp_limb_t)); for (w = 0; w < Blen; w++) lc_minus_inv[w] = ctx->mod.n - nmod_inv(Bs[w]->coeffs[0], ctx->mod); while (heap_len > 1) { mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow; } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow; } acc0 = acc1 = acc2 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; *store++ = x->p; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), UWORD(0), ctx->mod.n - Acoeffs[x->j]); } else { hinds[x->p][x->i] |= WORD(1); umul_ppmm(pp1, pp0, Bs[x->p]->coeffs[x->i], Q[x->p]->coeffs[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(acc0, acc2, acc1, acc0, ctx->mod); while (store > store_base) { p = *--store; j = *--store; i = *--store; if (i == -WORD(1)) { if (j + 1 < Alen) { x = chains[0] + 0; x->i = -WORD(1); x->j = j + 1; x->p = p; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Bs[p]->length) && (hinds[p][i + 1] == 2*j + 1) ) { x = chains[p] + i + 1; x->i = i + 1; x->j = j; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps[x->p] + x->i*N, Q[x->p]->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == q_len[p]) { s[p]++; } else if ( ((hinds[p][i] & 1) == 1) && ((i == 1) || (hinds[p][i - 1] >= 2*(j + 2) + 1)) ) { x = chains[p] + i; x->i = i; x->j = j + 1; x->p = p; x->next = NULL; hinds[p][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps[x->p] + x->i*N, Q[x->p]->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (acc0 == 0) continue; for (w = 0; w < Blen; w++) { int divides; if (bits <= FLINT_BITS) { divides = mpoly_monomial_divides(texp, exp, Bexps[w] + N*0, N, mask); } else { divides = mpoly_monomial_divides_mp(texp, exp, Bexps[w] + N*0, N, bits); } if (divides) { nmod_mpoly_fit_length(Q[w], q_len[w] + 1, ctx); Q[w]->coeffs[q_len[w]] = nmod_mul(acc0, lc_minus_inv[w], ctx->mod); mpoly_monomial_set(Q[w]->exps + N*q_len[w], texp, N); if (s[w] > 1) { i = 1; x = chains[w] + i; x->i = i; x->j = q_len[w]; x->p = w; x->next = NULL; hinds[w][x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps[w] + N*x->i, Q[w]->exps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s[w] = 1; q_len[w]++; goto break_continue; /* break out of w for loop and continue in heap loop */ } } /* if get here, no leading terms divided */ _nmod_mpoly_fit_length(&r_coeff, &R->coeffs_alloc, &r_exp, &R->exps_alloc, N, r_len + 1); r_coeff[r_len] = ctx->mod.n - acc0; mpoly_monomial_set(r_exp + r_len*N, exp, N); r_len++; break_continue:; } R->coeffs = r_coeff; R->exps = r_exp; R->length = r_len; for (i = 0; i < Blen; i++) Q[i]->length = q_len[i]; TMP_END; return 1; exp_overflow: R->coeffs = r_coeff; R->exps = r_exp; R->length = 0; for (i = 0; i < Blen; i++) Q[i]->length = 0; TMP_END; return 0; } /* Assumes divisor polys don't alias any output polys */ void nmod_mpoly_divrem_ideal_monagan_pearce( nmod_mpoly_struct ** Q, nmod_mpoly_t R, const nmod_mpoly_t A, nmod_mpoly_struct * const * B, slong Blen, const nmod_mpoly_ctx_t ctx) { slong i, N; flint_bitcnt_t QRbits; slong len3 = 0; ulong * cmpmask; ulong * Aexps; ulong ** Bexps; int freeAexps, * freeBexps; nmod_mpoly_t TR; nmod_mpoly_struct * r; TMP_INIT; for (i = 0; i < Blen; i++) { len3 = FLINT_MAX(len3, B[i]->length); if (nmod_mpoly_is_zero(B[i], ctx)) { flint_throw(FLINT_DIVZERO, "nmod_mpoly_divrem_ideal_monagan_pearce: divide by zero"); } } /* dividend is zero, write out quotients and remainder */ if (nmod_mpoly_is_zero(A, ctx)) { nmod_mpoly_zero(R, ctx); for (i = 0; i < Blen; i++) nmod_mpoly_zero(Q[i], ctx); return; } TMP_START; nmod_mpoly_init(TR, ctx); freeBexps = (int *) TMP_ALLOC(Blen*sizeof(int)); Bexps = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); /* compute maximum degrees that can occur in any input or output polys */ QRbits = A->bits; for (i = 0; i < Blen; i++) QRbits = FLINT_MAX(QRbits, B[i]->bits); QRbits = mpoly_fix_bits(QRbits, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ Aexps = A->exps; freeAexps = 0; if (QRbits > A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); } for (i = 0; i < Blen; i++) { Bexps[i] = B[i]->exps; freeBexps[i] = 0; if (QRbits > B[i]->bits) { freeBexps[i] = 1; Bexps[i] = (ulong *) flint_malloc(N*B[i]->length*sizeof(ulong)); mpoly_repack_monomials(Bexps[i], QRbits, B[i]->exps, B[i]->bits, B[i]->length, ctx->minfo); } } /* check leading mon. of at least one divisor is at most that of dividend */ for (i = 0; i < Blen; i++) { if (!mpoly_monomial_lt(Aexps + N*0, Bexps[i] + N*0, N, cmpmask)) break; } if (i == Blen) { nmod_mpoly_set(R, A, ctx); for (i = 0; i < Blen; i++) nmod_mpoly_zero(Q[i], ctx); goto cleanup; } /* take care of aliasing */ if (R == A) r = TR; else r = R; /* do division with remainder */ while (1) { nmod_mpoly_fit_length_reset_bits(r, len3, QRbits, ctx); for (i = 0; i < Blen; i++) nmod_mpoly_fit_length_reset_bits(Q[i], 1, QRbits, ctx); if (_nmod_mpoly_divrem_ideal_monagan_pearce(Q, r, A->coeffs, Aexps, A->length, B, Bexps, Blen, N, QRbits, ctx, cmpmask)) { break; } QRbits = mpoly_fix_bits(QRbits + 1, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; for (i = 0; i < Blen; i++) { if (freeBexps[i]) flint_free(Bexps[i]); Bexps[i] = (ulong *) flint_malloc(N*B[i]->length*sizeof(ulong)); mpoly_repack_monomials(Bexps[i], QRbits, B[i]->exps, B[i]->bits, B[i]->length, ctx->minfo); freeBexps[i] = 1; } } /* take care of aliasing */ if (R == A) nmod_mpoly_swap(R, TR, ctx); cleanup: nmod_mpoly_clear(TR, ctx); if (freeAexps) flint_free(Aexps); for (i = 0; i < Blen; i++) { if (freeBexps[i]) flint_free(Bexps[i]); } flint_free(cmpmask); TMP_END; } flint-3.1.3/src/nmod_mpoly/divrem_monagan_pearce.c000066400000000000000000000510411461254215100222510ustar00rootroot00000000000000/* Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" static int _nmod_mpoly_divrem_monagan_pearce1_binomial( nmod_mpoly_t Q, nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, flint_bitcnt_t bits, ulong maskhi, nmod_t mod) { mp_limb_t * Qcoeffs = Q->coeffs; mp_limb_t * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; ulong lexp, mask = mpoly_overflow_mask_sp(bits); mp_limb_t lcoeff; mp_limb_t lc_inv = nmod_inv(Bcoeffs[0], mod); mp_limb_t mBcoeff1 = mod.n - Bcoeffs[1]; slong Qlen = 0; slong Rlen = 0; slong Aidx = 0; slong Qidx = 0; while (1) { FLINT_ASSERT(0 <= Aidx && Aidx <= Alen); FLINT_ASSERT(0 <= Qidx && Qidx <= Qlen); if (Aidx < Alen) { lexp = Aexps[Aidx]; if (Qidx < Qlen) { ulong thisexp = Bexps[1] + Qexps[Qidx]; int cmp = mpoly_monomial_cmp1(lexp, thisexp, maskhi); if (cmp < 0) { lexp = thisexp; lcoeff = nmod_mul(mBcoeff1, Qcoeffs[Qidx], mod); Qidx++; } else if (cmp == 0) { lcoeff = Acoeffs[Aidx]; NMOD_ADDMUL(lcoeff, mBcoeff1, Qcoeffs[Qidx], mod); Aidx++; Qidx++; } else { lcoeff = Acoeffs[Aidx]; Aidx++; } } else { lcoeff = Acoeffs[Aidx]; Aidx++; } } else if (Qidx < Qlen) { lexp = Bexps[1] + Qexps[Qidx]; lcoeff = nmod_mul(mBcoeff1, Qcoeffs[Qidx], mod); Qidx++; } else { break; } if (mpoly_monomial_overflows1(lexp, mask)) goto exp_overflow; if (lcoeff == 0) continue; _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); if (!mpoly_monomial_divides1(Qexps + Qlen, lexp, Bexps[0], mask)) { _nmod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, &Rexps, &R->exps_alloc, 1, Rlen + 1); Rcoeffs[Rlen] = lcoeff; Rexps[Rlen] = lexp; Rlen++; continue; } if (lc_inv == 1) Qcoeffs[Qlen] = lcoeff; else Qcoeffs[Qlen] = nmod_mul(lcoeff, lc_inv, mod); Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; return 0; } static int _nmod_mpoly_divrem_monagan_pearce1( nmod_mpoly_t Q, nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, flint_bitcnt_t bits, ulong maskhi, nmod_t fctx) { slong i, j, Qlen, Rlen, s; slong next_loc, heap_len = 2; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; mp_limb_t * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; slong * hind; ulong mask, exp; int lt_divides; mp_limb_t lc_minus_inv, acc0, acc1, acc2, pp1, pp0; TMP_INIT; TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* quotient and remainder poly indices start at -1 */ Qlen = WORD(0); Rlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexps[0], x); /* precompute leading coefficient info */ lc_minus_inv = fctx.n - nmod_inv(Bcoeffs[0], fctx); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto exp_overflow; _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Bexps[0], mask); acc0 = acc1 = acc2 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), UWORD(0), fctx.n - Acoeffs[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, Bcoeffs[x->i], Qcoeffs[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(acc0, acc2, acc1, acc0, fctx); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexps[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } } } /* try to divide accumulated term by leading term */ if (acc0 == 0) { continue; } if (!lt_divides) { _nmod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, &Rexps, &R->exps_alloc, 1, Rlen + 1); Rcoeffs[Rlen] = fctx.n - acc0; Rexps[Rlen] = exp; Rlen++; continue; } Qcoeffs[Qlen] = nmod_mul(acc0, lc_minus_inv, fctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; TMP_END; return 1; exp_overflow: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; TMP_END; return 0; } static int _nmod_mpoly_divrem_monagan_pearce( nmod_mpoly_t Q, nmod_mpoly_t R, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, slong bits, slong N, const ulong * cmpmask, nmod_t fctx) { slong i, j, Qlen, Rlen, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; mp_limb_t * Rcoeffs = R->coeffs; ulong * Qexps = Q->exps; ulong * Rexps = R->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; int lt_divides; mp_limb_t lc_minus_inv, acc0, acc1, acc2, pp1, pp0; TMP_INIT; if (N == 1) { if (Blen == 2) return _nmod_mpoly_divrem_monagan_pearce1_binomial(Q, R, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, bits, cmpmask[0], fctx); else return _nmod_mpoly_divrem_monagan_pearce1(Q, R, Acoeffs, Aexps, Alen, Bcoeffs, Bexps, Blen, bits, cmpmask[0], fctx); } TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0; Qlen = WORD(0); Rlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, Aexps[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Aexps, N); /* precompute leading coefficient info */ lc_minus_inv = fctx.n - nmod_inv(Bcoeffs[0], fctx); while (heap_len > 1) { _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, Qlen + 1); mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS) { if (mpoly_monomial_overflows(exp, N, mask)) goto exp_overflow2; lt_divides = mpoly_monomial_divides(Qexps + Qlen*N, exp, Bexps, N, mask); } else { if (mpoly_monomial_overflows_mp(exp, N, bits)) goto exp_overflow2; lt_divides = mpoly_monomial_divides_mp(Qexps + Qlen*N, exp, Bexps, N, bits); } acc0 = acc1 = acc2 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i == -WORD(1)) { add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), UWORD(0), fctx.n - Acoeffs[x->j]); } else { hind[x->i] |= WORD(1); umul_ppmm(pp1, pp0, Bcoeffs[x->i], Qcoeffs[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), pp1, pp0); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(acc0, acc2, acc1, acc0, fctx); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } /* try to divide accumulated term by leading term */ if (acc0 == 0) continue; if (!lt_divides) { _nmod_mpoly_fit_length(&Rcoeffs, &R->coeffs_alloc, &Rexps, &R->exps_alloc, N, Rlen + 1); Rcoeffs[Rlen] = fctx.n - acc0; mpoly_monomial_set(Rexps + Rlen*N, exp, N); Rlen++; continue; } Qcoeffs[Qlen] = nmod_mul(acc0, lc_minus_inv, fctx); /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add_mp(exp_list[exp_next], Bexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = Rlen; TMP_END; return 1; exp_overflow2: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; R->coeffs = Rcoeffs; R->exps = Rexps; R->length = 0; TMP_END; return 0; } void nmod_mpoly_divrem_monagan_pearce( nmod_mpoly_t Q, nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t QRbits; ulong * Aexps = A->exps, * Bexps = B->exps; ulong * cmpmask; int freeAexps = 0, freeBexps = 0; nmod_mpoly_t TQ, TR; nmod_mpoly_struct * q, * r; if (nmod_mpoly_is_zero(B, ctx)) { if (nmod_mpoly_ctx_modulus(ctx) == 1) { nmod_mpoly_zero(Q, ctx); nmod_mpoly_zero(R, ctx); return; } else { flint_throw(FLINT_DIVZERO, "nmod_mpoly_divrem_monagan_pearce: divide by zero"); } } if (nmod_mpoly_is_zero(A, ctx)) { nmod_mpoly_zero(Q, ctx); nmod_mpoly_zero(R, ctx); return; } nmod_mpoly_init(TQ, ctx); nmod_mpoly_init(TR, ctx); QRbits = FLINT_MAX(A->bits, B->bits); QRbits = mpoly_fix_bits(QRbits, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (QRbits != A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); } if (QRbits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, QRbits, B->exps, B->bits, B->length, ctx->minfo); } /* check divisor leading monomial is at most that of the dividend */ if (mpoly_monomial_lt(Aexps, Bexps, N, cmpmask)) { nmod_mpoly_set(R, A, ctx); nmod_mpoly_zero(Q, ctx); goto cleanup; } /* take care of aliasing */ if (Q == A || Q == B) q = TQ; else q = Q; if (R == A || R == B) r = TR; else r = R; /* do division with remainder */ while (1) { nmod_mpoly_fit_length_reset_bits(q, A->length/B->length + 1, QRbits, ctx); nmod_mpoly_fit_length_reset_bits(r, B->length, QRbits, ctx); if (_nmod_mpoly_divrem_monagan_pearce(q, r, A->coeffs, Aexps, A->length, B->coeffs, Bexps, B->length, QRbits, N, cmpmask, ctx->mod)) { break; } QRbits = mpoly_fix_bits(QRbits + 1, ctx->minfo); N = mpoly_words_per_exp(QRbits, ctx->minfo); cmpmask = (ulong *) flint_realloc(cmpmask, N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, QRbits, ctx->minfo); if (freeAexps) flint_free(Aexps); Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, QRbits, A->exps, A->bits, A->length, ctx->minfo); freeAexps = 1; if (freeBexps) flint_free(Bexps); Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, QRbits, B->exps, B->bits, B->length, ctx->minfo); freeBexps = 1; } /* deal with aliasing */ if (Q == A || Q == B) nmod_mpoly_swap(Q, TQ, ctx); if (R == A || R == B) nmod_mpoly_swap(R, TR, ctx); cleanup: nmod_mpoly_clear(TQ, ctx); nmod_mpoly_clear(TR, ctx); if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); flint_free(cmpmask); } flint-3.1.3/src/nmod_mpoly/equal.c000066400000000000000000000052361461254215100170600ustar00rootroot00000000000000/* Copyright (C) 2017, 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" int _nmod_mpoly_equal(const mp_limb_t * coeff1, const ulong * exp1, const mp_limb_t * coeff2, const ulong * exp2, slong len, slong N) { slong i; if (coeff1 != coeff2) { for (i = 0; i < len; i++) if (coeff1[i] != coeff2[i]) return 0; } if (exp1 != exp2) { for (i = 0; i < len; i++) if (!mpoly_monomial_equal(exp1 + N*i, exp2 + N*i, N)) return 0; } return 1; } int nmod_mpoly_equal(const nmod_mpoly_t poly1, const nmod_mpoly_t poly2, const nmod_mpoly_ctx_t ctx) { ulong * ptr1 = poly1->exps, * ptr2 = poly2->exps; slong max_bits, N; int r, free1 = 0, free2 = 0; if (poly1 == poly2) return 1; if (poly1->length != poly2->length) return 0; max_bits = FLINT_MAX(poly1->bits, poly2->bits); N = mpoly_words_per_exp(max_bits, ctx->minfo); if (max_bits > poly1->bits) { free1 = 1; ptr1 = (ulong *) flint_malloc(N*poly1->length*sizeof(ulong)); mpoly_repack_monomials(ptr1, max_bits, poly1->exps, poly1->bits, poly1->length, ctx->minfo); } if (max_bits > poly2->bits) { free2 = 1; ptr2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(ptr2, max_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } r = _nmod_mpoly_equal(poly1->coeffs, ptr1, poly2->coeffs, ptr2, poly2->length, N); if (free1) flint_free(ptr1); if (free2) flint_free(ptr2); return r; } int nmod_mpoly_equal_ui(const nmod_mpoly_t A, ulong c, const nmod_mpoly_ctx_t ctx) { slong N; if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); if (c == 0) return A->length == 0; if (A->length != 1) return 0; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) return 0; return A->coeffs[0] == c; } flint-3.1.3/src/nmod_mpoly/evaluate_all.c000066400000000000000000000060311461254215100204010ustar00rootroot00000000000000/* Copyright (C) 2018,2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" mp_limb_t _nmod_mpoly_eval_all_ui( const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mp_limb_t * alphas, const mpoly_ctx_t mctx, nmod_t mod) { slong i, j; slong nvars = mctx->nvars; ulong mask = (Abits <= FLINT_BITS) ? (-UWORD(1)) >> (FLINT_BITS - Abits) : 0; slong N = mpoly_words_per_exp(Abits, mctx); ulong varexp_sp; fmpz_t varexp_mp; slong * offsets, * shifts; n_poly_struct * caches; mp_limb_t eval, t; TMP_INIT; TMP_START; fmpz_init(varexp_mp); caches = (n_poly_struct *) TMP_ALLOC(3*nvars*sizeof(n_poly_struct)); offsets = (slong *) TMP_ALLOC(2*nvars*sizeof(slong)); shifts = offsets + nvars; for (j = 0; j < nvars; j++) { if (Abits <= FLINT_BITS) mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, Abits, mctx); else offsets[j] = mpoly_gen_offset_mp(j, Abits, mctx); n_poly_init(caches + 3*j + 0); n_poly_init(caches + 3*j + 1); n_poly_init(caches + 3*j + 2); t = alphas[j]; if (t >= mod.n) NMOD_RED(t, t, mod); nmod_pow_cache_start(t, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2); } eval = 0; for (i = 0; i < Alen; i++) { t = Acoeffs[i]; if (Abits <= FLINT_BITS) { for (j = 0; j < nvars; j++) { varexp_sp = ((Aexps + N*i)[offsets[j]]>>shifts[j])&mask; t = nmod_pow_cache_mulpow_ui(t, varexp_sp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, mod); } } else { for (j = 0; j < nvars; j++) { fmpz_set_ui_array(varexp_mp, Aexps + N*i + offsets[j], Abits/FLINT_BITS); t = nmod_pow_cache_mulpow_fmpz(t, varexp_mp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, mod); } } eval = nmod_add(eval, t, mod); } fmpz_clear(varexp_mp); for (j = 0; j < 3*nvars; j++) n_poly_clear(caches + j); TMP_END; return eval; } ulong nmod_mpoly_evaluate_all_ui(const nmod_mpoly_t A, const ulong * vals, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_zero(A, ctx)) return 0; return _nmod_mpoly_eval_all_ui(A->coeffs, A->exps, A->length, A->bits, vals, ctx->minfo, ctx->mod); } flint-3.1.3/src/nmod_mpoly/evaluate_one.c000066400000000000000000000131641461254215100204170ustar00rootroot00000000000000/* Copyright (C) 2018-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" /* exponents of B are not multiprecision */ void _nmod_mpoly_evaluate_one_ui_sp( nmod_mpoly_t A, const nmod_mpoly_t B, slong var, ulong val, const nmod_mpoly_ctx_t ctx, n_poly_stack_t St) { slong i, N, off, shift; ulong * cmpmask, * one; slong Blen = B->length; const mp_limb_t * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; mp_limb_t * Acoeffs; ulong * Aexps; ulong mask, k; int need_sort = 0, cmp; n_poly_struct * cache[3]; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; n_poly_stack_fit_request(St, 3); cache[0] = n_poly_stack_take_top(St); cache[1] = n_poly_stack_take_top(St); cache[2] = n_poly_stack_take_top(St); nmod_pow_cache_start(val, cache[0], cache[1], cache[2]); nmod_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; mask = (-UWORD(1)) >> (FLINT_BITS - bits); N = mpoly_words_per_exp_sp(bits, ctx->minfo); one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; Acoeffs[Alen] = nmod_pow_cache_mulpow_ui(Bcoeffs[i], k, cache[0], cache[1], cache[2], ctx->mod); if (Acoeffs[Alen] == 0) continue; mpoly_monomial_msub(Aexps + N*Alen, Bexps + N*i, k, one, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } Acoeffs[Alen - 1] = nmod_add(Acoeffs[Alen - 1], Acoeffs[Alen], ctx->mod); Alen -= (Acoeffs[Alen - 1] == 0); } A->length = Alen; n_poly_stack_give_back(St, 3); TMP_END; if (need_sort) { nmod_mpoly_sort_terms(A, ctx); nmod_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(nmod_mpoly_is_canonical(A, ctx)); } /* exponents of B are multiprecision */ static void _nmod_mpoly_evaluate_one_ui_mp( nmod_mpoly_t A, const nmod_mpoly_t B, slong var, ulong val, const nmod_mpoly_ctx_t ctx, n_poly_stack_t St) { slong i, N, off; ulong * cmpmask, * one, * tmp; slong Blen = B->length; const mp_limb_t * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t bits = B->bits; slong Alen; mp_limb_t * Acoeffs; ulong * Aexps; fmpz_t k; int need_sort = 0, cmp; n_poly_struct * cache[3]; TMP_INIT; FLINT_ASSERT((B->bits % FLINT_BITS) == 0); TMP_START; fmpz_init(k); n_poly_stack_fit_request(St, 3); cache[0] = n_poly_stack_take_top(St); cache[1] = n_poly_stack_take_top(St); cache[2] = n_poly_stack_take_top(St); nmod_pow_cache_start(val, cache[0], cache[1], cache[2]); nmod_mpoly_fit_length_reset_bits(A, Blen, bits, ctx); Acoeffs = A->coeffs; Aexps = A->exps; N = mpoly_words_per_exp(bits, ctx->minfo); one = (ulong *) TMP_ALLOC(3*N*sizeof(ulong)); cmpmask = one + N; tmp = cmpmask + N; off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); Alen = 0; for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexps + N*i + off, bits/FLINT_BITS); Acoeffs[Alen] = nmod_pow_cache_mulpow_fmpz(Bcoeffs[i], k, cache[0], cache[1], cache[2], ctx->mod); if (Acoeffs[Alen] == 0) continue; mpoly_monomial_mul_fmpz(tmp, one, N, k); mpoly_monomial_sub_mp(Aexps + N*Alen, Bexps + N*i, tmp, N); if (Alen < 1) { Alen = 1; continue; } cmp = mpoly_monomial_cmp(Aexps + N*(Alen - 1), Aexps + N*Alen, N, cmpmask); if (cmp != 0) { need_sort |= (cmp < 0); Alen++; continue; } Acoeffs[Alen - 1] = nmod_add(Acoeffs[Alen - 1], Acoeffs[Alen], ctx->mod); Alen -= (Acoeffs[Alen - 1] == 0); } A->length = Alen; n_poly_stack_give_back(St, 3); fmpz_clear(k); TMP_END; if (need_sort) { nmod_mpoly_sort_terms(A, ctx); nmod_mpoly_combine_like_terms(A, ctx); } FLINT_ASSERT(nmod_mpoly_is_canonical(A, ctx)); } void nmod_mpoly_evaluate_one_ui(nmod_mpoly_t A, const nmod_mpoly_t B, slong var, ulong val, const nmod_mpoly_ctx_t ctx) { n_poly_stack_t St; if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_zero(A, ctx); return; } if (val >= ctx->mod.n) NMOD_RED(val, val, ctx->mod); n_poly_stack_init(St); if (B->bits <= FLINT_BITS) _nmod_mpoly_evaluate_one_ui_sp(A, B, var, val, ctx, St); else _nmod_mpoly_evaluate_one_ui_mp(A, B, var, val, ctx, St); n_poly_stack_clear(St); } flint-3.1.3/src/nmod_mpoly/fit_length.c000066400000000000000000000042331461254215100200700ustar00rootroot00000000000000/* Copyright (C) 2018, 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_fit_length( nmod_mpoly_t A, slong len, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); _nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, len); } void nmod_mpoly_fit_length_fit_bits( nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (len > A->coeffs_alloc) { A->coeffs_alloc = FLINT_MAX(len, 2*A->coeffs_alloc); A->coeffs = flint_realloc(A->coeffs, A->coeffs_alloc*sizeof(mp_limb_t)); } if (bits > A->bits) { slong newN = mpoly_words_per_exp(bits, ctx->minfo); slong new_exps_alloc = newN*len; ulong * t; if (len < 1) { A->bits = bits; return; } t = (ulong *) flint_malloc(new_exps_alloc*sizeof(ulong)); if (A->length > 0) mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, ctx->minfo); if (A->exps_alloc > 0) flint_free(A->exps); A->exps = t; A->exps_alloc = new_exps_alloc; A->bits = bits; } else { if (N*len > A->exps_alloc) { A->exps_alloc = FLINT_MAX(N*len, 2*A->exps_alloc); A->exps = flint_realloc(A->exps, A->exps_alloc*sizeof(ulong)); } } } void nmod_mpoly_fit_length_reset_bits( nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(bits, ctx->minfo); _nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, len); A->bits = bits; } flint-3.1.3/src/nmod_mpoly/gcd.c000066400000000000000000002030031461254215100164760ustar00rootroot00000000000000/* Copyright (C) 2018 - 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fq_nmod.h" #include "mpoly.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "n_poly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" #include "nmod_mpoly_factor.h" /* For each j, set out[j] to the evaluation of A at x_i = alpha[i] (i != j) i.e. if nvars = 3 out[0] = A(x, alpha[1], alpha[2]) out[1] = A(alpha[0], x, alpha[2]) out[2] = A(alpha[0], alpha[1], x) If ignore[j] is nonzero, then out[j] need not be calculated, probably because we shouldn't calculate it in dense form. */ static void nmod_mpoly_evals( slong * Atdeg, /* total degree of deflated A, or -1 for overflow */ n_poly_struct * out, const int * ignore, const nmod_mpoly_t A, ulong * Amin_exp, ulong * Amax_exp, ulong * Astride, mp_limb_t * alpha, const nmod_mpoly_ctx_t ctx) { slong i, j; slong nvars = ctx->minfo->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * offsets, * shifts; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * varexps; ulong varexp; slong total_degree, lo, hi; mp_limb_t meval, t; n_poly_struct * caches; offsets = FLINT_ARRAY_ALLOC(2*nvars, slong); shifts = offsets + nvars; varexps = FLINT_ARRAY_ALLOC(nvars, ulong); caches = FLINT_ARRAY_ALLOC(3*nvars, n_poly_struct); for (j = 0; j < nvars; j++) { n_poly_zero(out + j); mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, ctx->minfo); n_poly_init(caches + 3*j + 0); n_poly_init(caches + 3*j + 1); n_poly_init(caches + 3*j + 2); nmod_pow_cache_start(alpha[j], caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2); } total_degree = 0; for (i = 0; i < A->length; i++) { meval = A->coeffs[i]; hi = lo = 0; for (j = 0; j < nvars; j++) { varexp = ((A->exps + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexps[j] = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; add_ssaaaa(hi, lo, hi, lo, 0, varexps[j]); t = nmod_pow_cache_mulpow_ui(meval, varexps[j], caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, ctx->mod); FLINT_ASSERT(t == nmod_mul(meval, nmod_pow_ui(alpha[j], varexps[j], ctx->mod), ctx->mod)); meval = t; } if (hi == 0 && FLINT_SIGN_EXT(lo) == 0 && total_degree >= 0) total_degree = FLINT_MAX(total_degree, lo); else total_degree = -1; for (j = 0; j < nvars; j++) { varexp = varexps[j]; if (ignore[j]) continue; n_poly_fit_length(out + j, varexp + 1); while (out[j].length <= varexp) { out[j].coeffs[out[j].length] = 0; out[j].length++; } t = nmod_pow_cache_mulpow_neg_ui(meval, varexp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, ctx->mod); FLINT_ASSERT(t == nmod_mul(meval, nmod_pow_ui(nmod_inv(alpha[j], ctx->mod), varexp, ctx->mod), ctx->mod)); out[j].coeffs[varexp] = nmod_add(out[j].coeffs[varexp], t, ctx->mod); } } *Atdeg = total_degree; for (j = 0; j < nvars; j++) _n_poly_normalise(out + j); for (j = 0; j < 3*nvars; j++) n_poly_clear(caches + j); flint_free(offsets); flint_free(varexps); flint_free(caches); } static void nmod_mpoly_evals_medprime( slong * Atdeg, /* total degree of deflated A, or -1 for overflow */ fq_zech_poly_struct * out, const int * ignore, const nmod_mpoly_t A, ulong * Amin_exp, ulong * Amax_exp, ulong * Astride, const nmod_mpoly_ctx_t smctx, const fq_zech_struct * alphas, const fq_zech_ctx_t medctx) { slong i, j; slong nvars = smctx->minfo->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * offsets, * shifts; slong N = mpoly_words_per_exp_sp(A->bits, smctx->minfo); ulong * varexps; ulong varexp, lo, hi; slong total_degree; fq_zech_t t1, meval; fq_zech_init(t1, medctx); fq_zech_init(meval, medctx); offsets = FLINT_ARRAY_ALLOC(2*nvars, slong); shifts = offsets + nvars; varexps = FLINT_ARRAY_ALLOC(nvars, ulong); for (j = 0; j < nvars; j++) { fq_zech_poly_zero(out + j, medctx); mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, smctx->minfo); } total_degree = 0; for (i = 0; i < A->length; i++) { fq_zech_set_ui(meval, A->coeffs[i], medctx); lo = hi = 0; for (j = 0; j < nvars; j++) { varexp = ((A->exps + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexps[j] = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; add_ssaaaa(hi, lo, hi, lo, 0, varexps[j]); fq_zech_pow_ui(t1, alphas + j, varexps[j], medctx); fq_zech_mul(meval, meval, t1, medctx); } if (hi == 0 && FLINT_SIGN_EXT(lo) == 0 && total_degree >= 0) total_degree = FLINT_MAX(total_degree, lo); else total_degree = -1; for (j = 0; j < nvars; j++) { varexp = varexps[j]; if (ignore[j]) continue; fq_zech_poly_fit_length(out + j, varexp + 1, medctx); while (out[j].length <= varexp) { fq_zech_zero(out[j].coeffs + out[j].length, medctx); out[j].length++; } fq_zech_inv(t1, alphas + j, medctx); fq_zech_pow_ui(t1, t1, varexp, medctx); fq_zech_mul(t1, meval, t1, medctx); fq_zech_add(out[j].coeffs + varexp, out[j].coeffs + varexp, t1, medctx); } } *Atdeg = total_degree; for (j = 0; j < nvars; j++) _fq_zech_poly_normalise(out + j, medctx); flint_free(offsets); flint_free(varexps); fq_zech_clear(t1, medctx); fq_zech_clear(meval, medctx); } static void nmod_mpoly_evals_lgprime( slong * Atdeg, /* total degree of deflated A, or -1 for overflow */ n_fq_poly_struct * out, const int * ignore, const nmod_mpoly_t A, ulong * Amin_exp, ulong * Amax_exp, ulong * Astride, const nmod_mpoly_ctx_t smctx, const fq_nmod_struct * alpha, const fq_nmod_ctx_t lgctx) { slong d = fq_nmod_ctx_degree(lgctx); slong i, j; slong nvars = smctx->minfo->nvars; ulong mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * offsets, * shifts; slong N = mpoly_words_per_exp_sp(A->bits, smctx->minfo); ulong * varexps; ulong varexp, lo, hi; slong total_degree; n_poly_struct * caches; mp_limb_t * t = FLINT_ARRAY_ALLOC(2*d, mp_limb_t); mp_limb_t * meval = t + d; offsets = FLINT_ARRAY_ALLOC(2*nvars, slong); shifts = offsets + nvars; varexps = FLINT_ARRAY_ALLOC(nvars, ulong); caches = FLINT_ARRAY_ALLOC(3*nvars, n_poly_struct); for (j = 0; j < nvars; j++) { n_fq_poly_zero(out + j); mpoly_gen_offset_shift_sp(offsets + j, shifts + j, j, A->bits, smctx->minfo); n_poly_init(caches + 3*j + 0); n_poly_init(caches + 3*j + 1); n_poly_init(caches + 3*j + 2); n_fq_pow_cache_start_fq_nmod(alpha + j, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, lgctx); } total_degree = 0; for (i = 0; i < A->length; i++) { _n_fq_set_nmod(meval, A->coeffs[i], d); hi = lo = 0; for (j = 0; j < nvars; j++) { varexp = ((A->exps + N*i)[offsets[j]]>>shifts[j])&mask; FLINT_ASSERT((Astride[j] == 0 && varexp == Amin_exp[j]) || (varexp - Amin_exp[j]) % Astride[j] == 0); varexps[j] = Astride[j] < 2 ? varexp - Amin_exp[j] : (varexp - Amin_exp[j])/Astride[j]; add_ssaaaa(hi, lo, hi, lo, 0, varexps[j]); n_fq_pow_cache_mulpow_ui(meval, meval, varexps[j], caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, lgctx); } if (hi == 0 && FLINT_SIGN_EXT(lo) == 0 && total_degree >= 0) total_degree = FLINT_MAX(total_degree, lo); else total_degree = -1; for (j = 0; j < nvars; j++) { varexp = varexps[j]; if (ignore[j]) continue; n_poly_fit_length(out + j, d*(varexp + 1)); while (out[j].length <= varexp) { _n_fq_zero(out[j].coeffs + d*out[j].length, d); out[j].length++; } n_fq_pow_cache_mulpow_neg_ui(t, meval, varexp, caches + 3*j + 0, caches + 3*j + 1, caches + 3*j + 2, lgctx); n_fq_add(out[j].coeffs + d*varexp, out[j].coeffs + d*varexp, t, lgctx); } } *Atdeg = total_degree; for (j = 0; j < nvars; j++) _n_fq_poly_normalise(out + j, d); for (j = 0; j < 3*nvars; j++) n_poly_clear(caches + j); flint_free(offsets); flint_free(varexps); flint_free(caches); flint_free(t); } static void _set_estimates( mpoly_gcd_info_t I, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { int try_count = 0; slong nvars = ctx->minfo->nvars; slong i, j; n_poly_t Geval; n_poly_struct * Aevals, * Bevals; mp_limb_t * alpha; flint_rand_t state; slong ignore_limit; int * ignore; flint_randinit(state); ignore = FLINT_ARRAY_ALLOC(nvars, int); alpha = FLINT_ARRAY_ALLOC(nvars, mp_limb_t); Aevals = FLINT_ARRAY_ALLOC(nvars, n_poly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars, n_poly_struct); n_poly_init(Geval); for (j = 0; j < nvars; j++) { n_poly_init(Aevals + j); n_poly_init(Bevals + j); } ignore_limit = (A->length + B->length)/4096; ignore_limit = FLINT_MAX(WORD(9999), ignore_limit); I->Gdeflate_deg_bounds_are_nice = 1; for (j = 0; j < nvars; j++) { if (I->Adeflate_deg[j] > ignore_limit || I->Bdeflate_deg[j] > ignore_limit) { ignore[j] = 1; I->Gdeflate_deg_bounds_are_nice = 0; } else { ignore[j] = 0; } } try_again: if (++try_count > 10) { I->Gdeflate_deg_bounds_are_nice = 0; for (j = 0; j < nvars; j++) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } goto cleanup; } for (j = 0; j < nvars; j++) alpha[j] = n_urandint(state, ctx->mod.n - 1) + 1; nmod_mpoly_evals(&I->Adeflate_tdeg, Aevals, ignore, A, I->Amin_exp, I->Amax_exp, I->Gstride, alpha, ctx); nmod_mpoly_evals(&I->Bdeflate_tdeg, Bevals, ignore, B, I->Bmin_exp, I->Bmax_exp, I->Gstride, alpha, ctx); for (j = 0; j < nvars; j++) { if (ignore[j]) { I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Adeflate_deg[j], I->Bdeflate_deg[j]); I->Gterm_count_est[j] = 1 + I->Gdeflate_deg_bound[j]/2; } else { if (I->Adeflate_deg[j] != n_poly_degree(Aevals + j) || I->Bdeflate_deg[j] != n_poly_degree(Bevals + j)) { goto try_again; } n_poly_mod_gcd(Geval, Aevals + j, Bevals + j, ctx->mod); I->Gterm_count_est[j] = 0; I->Gdeflate_deg_bound[j] = n_poly_degree(Geval); for (i = I->Gdeflate_deg_bound[j]; i >= 0; i--) I->Gterm_count_est[j] += (Geval->coeffs[i] != 0); } } cleanup: n_poly_clear(Geval); for (j = 0; j < nvars; j++) { n_poly_clear(Aevals + j); n_poly_clear(Bevals + j); } flint_free(ignore); flint_free(alpha); flint_free(Aevals); flint_free(Bevals); flint_randclear(state); return; } /* call to improve on the (valid) results of smprime */ static void _set_estimates_medprime( mpoly_gcd_info_t I, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t smctx) { slong nvars = smctx->minfo->nvars; int tries_left = 10; slong i, j; fq_zech_poly_t Geval; fq_zech_poly_struct * Aevals, * Bevals; fq_zech_struct * alpha; flint_rand_t state; slong ignore_limit; int * ignore; fq_zech_ctx_t medctx; slong d, max_degree = n_flog(1000000, smctx->mod.n); if (max_degree < 2) return; flint_randinit(state); fq_zech_ctx_init_ui(medctx, smctx->mod.n, 1, "#"); d = n_clog(500, smctx->mod.n); d = FLINT_MAX(d, 1); ignore = FLINT_ARRAY_ALLOC(nvars, int); alpha = FLINT_ARRAY_ALLOC(nvars, fq_zech_struct); Aevals = FLINT_ARRAY_ALLOC(nvars, fq_zech_poly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars, fq_zech_poly_struct); for (j = 0; j < nvars; j++) { fq_zech_poly_init(Aevals + j, medctx); fq_zech_poly_init(Bevals + j, medctx); fq_zech_init(alpha + j, medctx); } fq_zech_poly_init(Geval, medctx); ignore_limit = (A->length + B->length)/4096; ignore_limit = FLINT_MAX(WORD(9999), ignore_limit); I->Gdeflate_deg_bounds_are_nice = 1; for (j = 0; j < nvars; j++) { FLINT_ASSERT(I->Gdeflate_deg_bound[j] <= I->Adeflate_deg[j]); FLINT_ASSERT(I->Gdeflate_deg_bound[j] <= I->Bdeflate_deg[j]); if (I->Adeflate_deg[j] > ignore_limit || I->Bdeflate_deg[j] > ignore_limit) { ignore[j] = 1; I->Gdeflate_deg_bounds_are_nice = 0; } else { ignore[j] = 0; } } try_again: tries_left--; d = FLINT_MIN(d + (tries_left % 2), max_degree); if (tries_left < 0) { I->Gdeflate_deg_bounds_are_nice = 0; goto cleanup; } fq_zech_ctx_init_ui(medctx, smctx->mod.n, d, "#"); for (j = 0; j < nvars; j++) fq_zech_rand_not_zero(alpha + j, state, medctx); nmod_mpoly_evals_medprime(&I->Adeflate_tdeg, Aevals, ignore, A, I->Amin_exp, I->Amax_exp, I->Gstride, smctx, alpha, medctx); nmod_mpoly_evals_medprime(&I->Bdeflate_tdeg, Bevals, ignore, B, I->Bmin_exp, I->Bmax_exp, I->Gstride, smctx, alpha, medctx); for (j = 0; j < nvars; j++) { if (!ignore[j]) { if (I->Adeflate_deg[j] != fq_zech_poly_degree(Aevals + j, medctx) || I->Bdeflate_deg[j] != fq_zech_poly_degree(Bevals + j, medctx)) { goto try_again; } fq_zech_poly_gcd(Geval, Aevals + j, Bevals + j, medctx); I->Gterm_count_est[j] = 0; I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Gdeflate_deg_bound[j], fq_zech_poly_degree(Geval, medctx)); for (i = I->Gdeflate_deg_bound[j]; i >= 0; i--) I->Gterm_count_est[j] += !fq_zech_is_zero(Geval->coeffs + i, medctx); } } cleanup: fq_zech_poly_clear(Geval, medctx); for (j = 0; j < nvars; j++) { fq_zech_poly_clear(Aevals + j, medctx); fq_zech_poly_clear(Bevals + j, medctx); fq_zech_clear(alpha + j, medctx); } flint_free(alpha); flint_free(Aevals); flint_free(Bevals); flint_free(ignore); fq_zech_ctx_clear(medctx); flint_randclear(state); return; } /* call to improve on the (valid) results of smprime/medprime */ static void _set_estimates_lgprime( mpoly_gcd_info_t I, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t smctx) { slong nvars = smctx->minfo->nvars; int try_count = 0; slong i, j; n_fq_poly_t Geval; n_fq_poly_struct * Aevals, * Bevals; fq_nmod_struct * alpha; flint_rand_t state; slong ignore_limit; int * ignore; fq_nmod_mpoly_ctx_t lgctx; slong d; flint_randinit(state); d = WORD(20)/(FLINT_BIT_COUNT(smctx->mod.n)); d = FLINT_MAX(WORD(2), d); fq_nmod_mpoly_ctx_init_deg(lgctx, nvars, ORD_LEX, smctx->mod.n, d); ignore = FLINT_ARRAY_ALLOC(nvars, int); alpha = FLINT_ARRAY_ALLOC(nvars, fq_nmod_struct); Aevals = FLINT_ARRAY_ALLOC(nvars, n_fq_poly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars, n_fq_poly_struct); for (j = 0; j < nvars; j++) { n_fq_poly_init(Aevals + j); n_fq_poly_init(Bevals + j); fq_nmod_init(alpha + j, lgctx->fqctx); } n_fq_poly_init(Geval); ignore_limit = (A->length + B->length)/4096; ignore_limit = FLINT_MAX(WORD(9999), ignore_limit); I->Gdeflate_deg_bounds_are_nice = 1; for (j = 0; j < nvars; j++) { FLINT_ASSERT(I->Gdeflate_deg_bound[j] <= I->Adeflate_deg[j]); FLINT_ASSERT(I->Gdeflate_deg_bound[j] <= I->Bdeflate_deg[j]); if (I->Adeflate_deg[j] > ignore_limit || I->Bdeflate_deg[j] > ignore_limit) { ignore[j] = 1; I->Gdeflate_deg_bounds_are_nice = 0; } else { ignore[j] = 0; } } try_again: if (++try_count > 10) { I->Gdeflate_deg_bounds_are_nice = 0; goto cleanup; } for (j = 0; j < nvars; j++) fq_nmod_rand_not_zero(alpha + j, state, lgctx->fqctx); nmod_mpoly_evals_lgprime(&I->Adeflate_tdeg, Aevals, ignore, A, I->Amin_exp, I->Amax_exp, I->Gstride, smctx, alpha, lgctx->fqctx); nmod_mpoly_evals_lgprime(&I->Bdeflate_tdeg, Bevals, ignore, B, I->Bmin_exp, I->Bmax_exp, I->Gstride, smctx, alpha, lgctx->fqctx); for (j = 0; j < nvars; j++) { if (!ignore[j]) { if (I->Adeflate_deg[j] != n_fq_poly_degree(Aevals + j) || I->Bdeflate_deg[j] != n_fq_poly_degree(Bevals + j)) { d++; fq_nmod_mpoly_ctx_change_modulus(lgctx, d); goto try_again; } n_fq_poly_gcd(Geval, Aevals + j, Bevals + j, lgctx->fqctx); I->Gterm_count_est[j] = 0; I->Gdeflate_deg_bound[j] = FLINT_MIN(I->Gdeflate_deg_bound[j], n_fq_poly_degree(Geval)); for (i = I->Gdeflate_deg_bound[j]; i >= 0; i--) I->Gterm_count_est[j] += !_n_fq_is_zero(Geval->coeffs + d*i, d); } } cleanup: n_fq_poly_clear(Geval); for (j = 0; j < nvars; j++) { n_fq_poly_clear(Aevals + j); n_fq_poly_clear(Bevals + j); fq_nmod_clear(alpha + j, lgctx->fqctx); } flint_free(alpha); flint_free(Aevals); flint_free(Bevals); flint_free(ignore); fq_nmod_mpoly_ctx_clear(lgctx); flint_randclear(state); return; } /* (Abar, Bbar) = (A, B) */ static void _parallel_set( nmod_mpoly_t Abar, /* could be NULL */ nmod_mpoly_t Bbar, /* could be NULL */ const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (Abar == B && Bbar == A) { FLINT_ASSERT(Abar != NULL && Bbar != NULL); nmod_mpoly_set(Abar, B, ctx); nmod_mpoly_set(Bbar, A, ctx); nmod_mpoly_swap(Abar, Bbar, ctx); } else if (Abar == B && Bbar != A) { FLINT_ASSERT(Abar != NULL); if (Bbar != NULL) nmod_mpoly_set(Bbar, B, ctx); nmod_mpoly_set(Abar, A, ctx); } else { if (Abar != NULL) nmod_mpoly_set(Abar, A, ctx); if (Bbar != NULL) nmod_mpoly_set(Bbar, B, ctx); } } /* The variables in ess(A) and ess(B) are disjoint. gcd is trivial to compute */ static int _do_trivial( nmod_mpoly_t G, nmod_mpoly_t Abar, /* could be NULL */ nmod_mpoly_t Bbar, /* could be NULL */ const nmod_mpoly_t A, const nmod_mpoly_t B, const mpoly_gcd_info_t I, const nmod_mpoly_ctx_t ctx) { _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) mpoly_monomials_shift_right_ui(Abar->exps, Abar->bits, Abar->length, I->Gmin_exp, ctx->minfo); if (Bbar != NULL) mpoly_monomials_shift_right_ui(Bbar->exps, Bbar->bits, Bbar->length, I->Gmin_exp, ctx->minfo); nmod_mpoly_fit_length_reset_bits(G, 1, I->Gbits, ctx); mpoly_set_monomial_ui(G->exps, I->Gmin_exp, I->Gbits, ctx->minfo); G->coeffs[0] = UWORD(1); G->length = 1; return 1; } /*********************** Easy when B is a monomial ***************************/ static int _do_monomial_gcd( nmod_mpoly_t G, nmod_mpoly_t Abar, /* could be NULL */ nmod_mpoly_t Bbar, /* could be NULL */ const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); fmpz * minAfields, * minAdegs, * minBdegs; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length == 1); TMP_START; /* get the field-wise minimum of A */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, A->bits, ctx->minfo); /* unpack to get the min degrees of each variable in A */ minAdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minAdegs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(minAdegs, minAfields, ctx->minfo); /* get the degree of each variable in B */ minBdegs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(minBdegs + i); mpoly_get_monomial_ffmpz(minBdegs, B->exps, B->bits, ctx->minfo); /* compute the degree of each variable in G */ _fmpz_vec_min_inplace(minBdegs, minAdegs, ctx->minfo->nvars); _parallel_set(Abar, Bbar, A, B, ctx); if (Abar != NULL) mpoly_monomials_shift_right_ffmpz(Abar->exps, Abar->bits, Abar->length, minBdegs, ctx->minfo); if (Bbar != NULL) mpoly_monomials_shift_right_ffmpz(Bbar->exps, Bbar->bits, Bbar->length, minBdegs, ctx->minfo); nmod_mpoly_fit_length_reset_bits(G, 1, Gbits, ctx); mpoly_set_monomial_ffmpz(G->exps, minBdegs, Gbits, ctx->minfo); G->coeffs[0] = 1; G->length = 1; for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(minAfields + i); } for (i = 0; i < ctx->minfo->nvars; i++) { fmpz_clear(minAdegs + i); fmpz_clear(minBdegs + i); } TMP_END; return 1; } /********************** See if cofactors are monomials ***********************/ static int _try_monomial_cofactors( nmod_mpoly_t G, nmod_mpoly_t Abar, /* could be NULL */ nmod_mpoly_t Bbar, /* could be NULL */ const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { int success; slong i, j; slong NA, NG; slong nvars = ctx->minfo->nvars; fmpz * Abarexps, * Bbarexps, * Texps; mp_limb_t a0, b0, a0inv; nmod_mpoly_t T; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); flint_bitcnt_t Abarbits = A->bits; flint_bitcnt_t Bbarbits = B->bits; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (A->length != B->length) return 0; a0 = A->coeffs[0]; b0 = B->coeffs[0]; for (i = A->length - 1; i > 0; i--) { success = (nmod_mul(a0, B->coeffs[i], ctx->mod) == nmod_mul(b0, A->coeffs[i], ctx->mod)); if (!success) goto cleanup; } TMP_START; Abarexps = (fmpz *) TMP_ALLOC(3*nvars*sizeof(fmpz)); Bbarexps = Abarexps + 1*nvars; Texps = Abarexps + 2*nvars; for (j = 0; j < nvars; j++) { fmpz_init(Abarexps + j); fmpz_init(Bbarexps + j); fmpz_init(Texps + j); } success = mpoly_monomial_cofactors(Abarexps, Bbarexps, A->exps, A->bits, B->exps, B->bits, A->length, ctx->minfo); if (!success) goto cleanup_tmp; nmod_mpoly_init3(T, A->length, Gbits, ctx); NG = mpoly_words_per_exp(Gbits, ctx->minfo); NA = mpoly_words_per_exp(A->bits, ctx->minfo); a0inv = nmod_inv(a0, ctx->mod); T->length = A->length; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ffmpz(Texps, A->exps + NA*i, A->bits, ctx->minfo); _fmpz_vec_sub(Texps, Texps, Abarexps, nvars); mpoly_set_monomial_ffmpz(T->exps + NG*i, Texps, Gbits, ctx->minfo); T->coeffs[i] = nmod_mul(A->coeffs[i], a0inv, ctx->mod); } nmod_mpoly_swap(G, T, ctx); nmod_mpoly_clear(T, ctx); if (Abar != NULL) { nmod_mpoly_fit_length_reset_bits(Abar, 1, Abarbits, ctx); mpoly_set_monomial_ffmpz(Abar->exps, Abarexps, Abarbits, ctx->minfo); Abar->coeffs[0] = a0; _nmod_mpoly_set_length(Abar, 1, ctx); } if (Bbar != NULL) { nmod_mpoly_fit_length_reset_bits(Bbar, 1, Bbarbits, ctx); mpoly_set_monomial_ffmpz(Bbar->exps, Bbarexps, Bbarbits, ctx->minfo); Bbar->coeffs[0] = b0; _nmod_mpoly_set_length(Bbar, 1, ctx); } success = 1; cleanup_tmp: for (j = 0; j < nvars; j++) { fmpz_clear(Abarexps + j); fmpz_clear(Bbarexps + j); fmpz_clear(Texps + j); } TMP_END; cleanup: return success; } /*** ess(A) and ess(B) depend on only one variable v_in_both ****************/ int _do_univar( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, slong v_in_both, const mpoly_gcd_info_t I, const nmod_mpoly_ctx_t ctx) { nmod_poly_t a, b, g, t; nmod_poly_init_mod(a, ctx->mod); nmod_poly_init_mod(b, ctx->mod); nmod_poly_init_mod(g, ctx->mod); nmod_poly_init_mod(t, ctx->mod); _nmod_mpoly_to_nmod_poly_deflate(a, A, v_in_both, I->Amin_exp, I->Gstride, ctx); _nmod_mpoly_to_nmod_poly_deflate(b, B, v_in_both, I->Bmin_exp, I->Gstride, ctx); nmod_poly_gcd(g, a, b); _nmod_mpoly_from_nmod_poly_inflate(G, I->Gbits, g, v_in_both, I->Gmin_exp, I->Gstride, ctx); if (Abar != NULL) { nmod_poly_divexact(t, a, g); _nmod_mpoly_from_nmod_poly_inflate(Abar, I->Abarbits, t, v_in_both, I->Abarmin_exp, I->Gstride, ctx); } if (Bbar != NULL) { nmod_poly_divexact(t, b, g); _nmod_mpoly_from_nmod_poly_inflate(Bbar, I->Bbarbits, t, v_in_both, I->Bbarmin_exp, I->Gstride, ctx); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(t); return 1; } /********* Assume B has length one when converted to univar format ***********/ static int _try_missing_var( nmod_mpoly_t G, flint_bitcnt_t Gbits, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, slong var, const nmod_mpoly_t A, ulong Ashift, const nmod_mpoly_t B, ulong Bshift, const nmod_mpoly_ctx_t ctx) { int success; nmod_mpoly_univar_t Au; nmod_mpoly_univar_init(Au, ctx); #if FLINT_WANT_ASSERT nmod_mpoly_to_univar(Au, B, var, ctx); FLINT_ASSERT(Au->length == 1); #endif nmod_mpoly_to_univar(Au, A, var, ctx); nmod_mpoly_univar_fit_length(Au, Au->length + 1, ctx); nmod_mpoly_set(Au->coeffs + Au->length, B, ctx); Au->length++; if (Abar == NULL && Bbar == NULL) { success = _nmod_mpoly_vec_content_mpoly(G, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; nmod_mpoly_repack_bits_inplace(G, Gbits, ctx); _mpoly_gen_shift_left(G->exps, G->bits, G->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); } else { nmod_mpoly_t tG, tAbar, tBbar; nmod_mpoly_init(tG, ctx); nmod_mpoly_init(tAbar, ctx); nmod_mpoly_init(tBbar, ctx); success = _nmod_mpoly_vec_content_mpoly(tG, Au->coeffs, Au->length, ctx); if (!success) goto cleanup; nmod_mpoly_repack_bits_inplace(tG, Gbits, ctx); _mpoly_gen_shift_left(tG->exps, tG->bits, tG->length, var, FLINT_MIN(Ashift, Bshift), ctx->minfo); if (Abar != NULL) { success = nmod_mpoly_divides(tAbar, A, tG, ctx); FLINT_ASSERT(success); } if (Bbar != NULL) { success = nmod_mpoly_divides(tBbar, B, tG, ctx); FLINT_ASSERT(success); } nmod_mpoly_swap(G, tG, ctx); if (Abar != NULL) nmod_mpoly_swap(Abar, tAbar, ctx); if (Bbar != NULL) nmod_mpoly_swap(Bbar, tBbar, ctx); nmod_mpoly_clear(tG, ctx); nmod_mpoly_clear(tAbar, ctx); nmod_mpoly_clear(tBbar, ctx); } success = 1; cleanup: nmod_mpoly_univar_clear(Au, ctx); return success; } /************************ See if B divides A ********************************/ static int _try_divides( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t BB, const nmod_mpoly_ctx_t ctx) { int success = 0; nmod_mpoly_t Q, B, M; nmod_mpoly_init(Q, ctx); nmod_mpoly_init(B, ctx); nmod_mpoly_init(M, ctx); /* BB = M*B */ nmod_mpoly_term_content(M, BB, ctx); nmod_mpoly_divides(B, BB, M, ctx); if (nmod_mpoly_divides(Q, A, B, ctx)) { /* gcd(Q*B, M*B) */ _do_monomial_gcd(G, Abar, Bbar, Q, M, ctx); nmod_mpoly_mul(G, G, B, ctx); success = 1; } nmod_mpoly_clear(Q, ctx); nmod_mpoly_clear(B, ctx); nmod_mpoly_clear(M, ctx); return success; } /********************** Hit A and B with zippel ******************************/ static int _try_zippel( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const mpoly_gcd_info_t I, const nmod_mpoly_ctx_t ctx) { slong m = I->mvars; int success; flint_bitcnt_t wbits; flint_rand_t randstate; nmod_mpoly_ctx_t uctx; nmod_mpolyu_t Au, Bu, Gu, Abaru, Bbaru; nmod_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL)) return 0; FLINT_ASSERT(m >= WORD(2)); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); flint_randinit(randstate); /* uctx is context for Z[y_1,...,y_{m-1}]*/ nmod_mpoly_ctx_init(uctx, m - 1, ORD_LEX, ctx->mod.n); wbits = FLINT_MAX(A->bits, B->bits); nmod_mpolyu_init(Au, wbits, uctx); nmod_mpolyu_init(Bu, wbits, uctx); nmod_mpolyu_init(Gu, wbits, uctx); nmod_mpolyu_init(Abaru, wbits, uctx); nmod_mpolyu_init(Bbaru, wbits, uctx); nmod_mpoly_init3(Ac, 0, wbits, uctx); nmod_mpoly_init3(Bc, 0, wbits, uctx); nmod_mpoly_init3(Gc, 0, wbits, uctx); nmod_mpoly_init3(Abarc, 0, wbits, uctx); nmod_mpoly_init3(Bbarc, 0, wbits, uctx); nmod_mpoly_to_mpolyu_perm_deflate_threaded_pool(Au, uctx, A, ctx, I->zippel_perm, I->Amin_exp, I->Gstride, NULL, 0); nmod_mpoly_to_mpolyu_perm_deflate_threaded_pool(Bu, uctx, B, ctx, I->zippel_perm, I->Bmin_exp, I->Gstride, NULL, 0); success = nmod_mpolyu_content_mpoly(Ac, Au, uctx) && nmod_mpolyu_content_mpoly(Bc, Bu, uctx); if (!success) goto cleanup; nmod_mpolyu_divexact_mpoly_inplace(Au, Ac, uctx); nmod_mpolyu_divexact_mpoly_inplace(Bu, Bc, uctx); success = nmod_mpolyu_gcdm_zippel(Gu, Abaru, Bbaru, Au, Bu, uctx, randstate); if (!success) goto cleanup; if (Abar == NULL && Bbar == NULL) { success = nmod_mpoly_gcd(Gc, Ac, Bc, uctx); if (!success) goto cleanup; nmod_mpoly_repack_bits_inplace(Gc, wbits, uctx); nmod_mpolyu_mul_mpoly_inplace(Gu, Gc, uctx); nmod_mpoly_from_mpolyu_perm_inflate(G, I->Gbits, ctx, Gu, uctx, I->zippel_perm, I->Gmin_exp, I->Gstride); } else { success = nmod_mpoly_gcd_cofactors(Gc, Abarc, Bbarc, Ac, Bc, uctx); if (!success) goto cleanup; nmod_mpoly_repack_bits_inplace(Gc, wbits, uctx); nmod_mpoly_repack_bits_inplace(Abarc, wbits, uctx); nmod_mpoly_repack_bits_inplace(Bbarc, wbits, uctx); nmod_mpolyu_mul_mpoly_inplace(Gu, Gc, uctx); nmod_mpolyu_mul_mpoly_inplace(Abaru, Abarc, uctx); nmod_mpolyu_mul_mpoly_inplace(Bbaru, Bbarc, uctx); nmod_mpoly_from_mpolyu_perm_inflate(G, I->Gbits, ctx, Gu, uctx, I->zippel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) nmod_mpoly_from_mpolyu_perm_inflate(Abar, I->Abarbits, ctx, Abaru, uctx, I->zippel_perm, I->Abarmin_exp, I->Gstride); if (Bbar != NULL) nmod_mpoly_from_mpolyu_perm_inflate(Bbar, I->Bbarbits, ctx, Bbaru, uctx, I->zippel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: nmod_mpolyu_clear(Au, uctx); nmod_mpolyu_clear(Bu, uctx); nmod_mpolyu_clear(Gu, uctx); nmod_mpolyu_clear(Abaru, uctx); nmod_mpolyu_clear(Bbaru, uctx); nmod_mpoly_clear(Ac, uctx); nmod_mpoly_clear(Bc, uctx); nmod_mpoly_clear(Gc, uctx); nmod_mpoly_clear(Abarc, uctx); nmod_mpoly_clear(Bbarc, uctx); nmod_mpoly_ctx_clear(uctx); flint_randclear(randstate); return success; } static int _try_zippel2( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const mpoly_gcd_info_t I, const nmod_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; nmod_mpoly_ctx_t lctx; nmod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; nmod_mpoly_t Al_lc, Bl_lc, Ac, Bc, Gc, Abarc, Bbarc, Gamma; slong * tmp, * Gl_degs, * Al_degs, * Bl_degs, * Gamma_degs, * Gguess; slong max_degree; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_ZIPPEL2)) return 0; FLINT_ASSERT(m >= 3); tmp = FLINT_ARRAY_ALLOC(5*m, slong); Al_degs = tmp + 1*m; Bl_degs = tmp + 2*m; Gl_degs = tmp + 3*m; Gamma_degs = tmp + 4*m; nmod_mpoly_ctx_init(lctx, m, ORD_LEX, ctx->mod.n); max_degree = 0; for (i = 0; i < m; i++) { k = I->zippel2_perm[i]; Gl_degs[i] = I->Gdeflate_deg_bound[k]; Al_degs[i] = I->Adeflate_deg[k]; max_degree = FLINT_MAX(max_degree, Al_degs[i]); Bl_degs[i] = I->Bdeflate_deg[k]; max_degree = FLINT_MAX(max_degree, Bl_degs[i]); } wbits = 1 + FLINT_BIT_COUNT(max_degree); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); nmod_mpoly_init3(Al, 0, wbits, lctx); nmod_mpoly_init3(Bl, 0, wbits, lctx); nmod_mpoly_init3(Gl, 0, wbits, lctx); nmod_mpoly_init3(Abarl, 0, wbits, lctx); nmod_mpoly_init3(Bbarl, 0, wbits, lctx); nmod_mpoly_init3(Ac, 0, wbits, lctx); nmod_mpoly_init3(Bc, 0, wbits, lctx); nmod_mpoly_init3(Gc, 0, wbits, lctx); nmod_mpoly_init3(Abarc, 0, wbits, lctx); nmod_mpoly_init3(Bbarc, 0, wbits, lctx); nmod_mpoly_init3(Gamma, 0, wbits, lctx); nmod_mpoly_init3(Al_lc, 0, wbits, lctx); nmod_mpoly_init3(Bl_lc, 0, wbits, lctx); nmod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->zippel2_perm, I->Amin_exp, I->Gstride); nmod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->zippel2_perm, I->Bmin_exp, I->Gstride); success = nmod_mpolyl_content(Ac, Al, 2, lctx) && nmod_mpolyl_content(Bc, Bl, 2, lctx); if (!success) goto cleanup; if (Abar == NULL && Bbar == NULL) success = nmod_mpoly_gcd(Gc, Ac, Bc, lctx); else success = nmod_mpoly_gcd_cofactors(Gc, Abarc, Bbarc, Ac, Bc, lctx); if (!success) goto cleanup; nmod_mpoly_degrees_si(tmp, Ac, lctx); for (i = 0; i < m; i++) Al_degs[i] -= tmp[i]; success = nmod_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); nmod_mpoly_degrees_si(tmp, Bc, lctx); for (i = 0; i < m; i++) Bl_degs[i] -= tmp[i]; success = nmod_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); nmod_mpoly_degrees_si(tmp, Gc, lctx); for (i = 0; i < m; i++) Gl_degs[i] -= tmp[i]; nmod_mpoly_repack_bits_inplace(Al, wbits, lctx); nmod_mpoly_repack_bits_inplace(Bl, wbits, lctx); nmod_mpolyl_lead_coeff(Al_lc, Al, 2, lctx); nmod_mpolyl_lead_coeff(Bl_lc, Bl, 2, lctx); success = nmod_mpoly_gcd(Gamma, Al_lc, Bl_lc, lctx); if (!success) goto cleanup; nmod_mpoly_repack_bits_inplace(Gamma, wbits, lctx); nmod_mpoly_degrees_si(Gamma_degs, Gamma, lctx); Gguess = I->Gdeflate_deg_bounds_are_nice ? Gl_degs : NULL; success = nmod_mpolyl_gcd_zippel_smprime(Gl, Gguess, Abarl, Bbarl, Al, Al_degs, Bl, Bl_degs, Gamma, Gamma_degs, lctx); if (!success) { success = nmod_mpolyl_gcd_zippel_lgprime(Gl, Gguess, Abarl, Bbarl, Al, Al_degs, Bl, Bl_degs, Gamma, Gamma_degs, lctx); if (!success) goto cleanup; } nmod_mpoly_mul(Gl, Gl, Gc, lctx); nmod_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->zippel2_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { nmod_mpoly_mul(Abarl, Abarl, Abarc, lctx); nmod_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->zippel2_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { nmod_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); nmod_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->zippel2_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: nmod_mpoly_clear(Al, lctx); nmod_mpoly_clear(Bl, lctx); nmod_mpoly_clear(Gl, lctx); nmod_mpoly_clear(Abarl, lctx); nmod_mpoly_clear(Bbarl, lctx); nmod_mpoly_clear(Ac, lctx); nmod_mpoly_clear(Bc, lctx); nmod_mpoly_clear(Gc, lctx); nmod_mpoly_clear(Abarc, lctx); nmod_mpoly_clear(Bbarc, lctx); nmod_mpoly_clear(Gamma, lctx); nmod_mpoly_clear(Al_lc, lctx); nmod_mpoly_clear(Bl_lc, lctx); nmod_mpoly_ctx_clear(lctx); flint_free(tmp); return success; } /******************** Hit A and B with hensel lifting ************************/ static int _try_hensel( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const mpoly_gcd_info_t I, const nmod_mpoly_ctx_t ctx) { slong i, k; slong m = I->mvars; int success; flint_bitcnt_t wbits; nmod_mpoly_ctx_t lctx; nmod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; nmod_mpoly_t Ac, Bc, Gc, Abarc, Bbarc; slong max_deg; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (!(I->can_use & MPOLY_GCD_USE_HENSEL)) return 0; FLINT_ASSERT(m >= WORD(2)); nmod_mpoly_ctx_init(lctx, m, ORD_LEX, ctx->mod.n); max_deg = 0; for (i = 0; i < m; i++) { k = I->hensel_perm[i]; max_deg = FLINT_MAX(max_deg, I->Adeflate_deg[k]); max_deg = FLINT_MAX(max_deg, I->Bdeflate_deg[k]); } wbits = 1 + FLINT_BIT_COUNT(max_deg); wbits = mpoly_fix_bits(wbits, lctx->minfo); FLINT_ASSERT(wbits <= FLINT_BITS); nmod_mpoly_init3(Al, 0, wbits, lctx); nmod_mpoly_init3(Bl, 0, wbits, lctx); nmod_mpoly_init3(Gl, 0, wbits, lctx); nmod_mpoly_init3(Abarl, 0, wbits, lctx); nmod_mpoly_init3(Bbarl, 0, wbits, lctx); nmod_mpoly_init3(Ac, 0, wbits, lctx); nmod_mpoly_init3(Bc, 0, wbits, lctx); nmod_mpoly_init3(Gc, 0, wbits, lctx); nmod_mpoly_init3(Abarc, 0, wbits, lctx); nmod_mpoly_init3(Bbarc, 0, wbits, lctx); nmod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, I->hensel_perm, I->Amin_exp, I->Gstride); nmod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, I->hensel_perm, I->Bmin_exp, I->Gstride); success = nmod_mpolyl_content(Ac, Al, 1, lctx) && nmod_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; if (Abar == NULL && Bbar == NULL) success = nmod_mpoly_gcd(Gc, Ac, Bc, lctx); else success = nmod_mpoly_gcd_cofactors(Gc, Abarc, Bbarc, Ac, Bc, lctx); if (!success) goto cleanup; success = nmod_mpoly_divides(Al, Al, Ac, lctx); FLINT_ASSERT(success); success = nmod_mpoly_divides(Bl, Bl, Bc, lctx); FLINT_ASSERT(success); nmod_mpoly_repack_bits_inplace(Al, wbits, lctx); nmod_mpoly_repack_bits_inplace(Bl, wbits, lctx); max_deg = I->Gdeflate_deg_bound[I->hensel_perm[0]]; success = nmod_mpolyl_gcd_hensel_smprime(Gl, max_deg, Abarl, Bbarl, Al, Bl, lctx); if (!success) { success = nmod_mpolyl_gcd_hensel_medprime(Gl, max_deg, Abarl, Bbarl, Al, Bl, lctx); if (!success) goto cleanup; } nmod_mpoly_mul(Gl, Gl, Gc, lctx); nmod_mpoly_from_mpolyl_perm_inflate(G, I->Gbits, ctx, Gl, lctx, I->hensel_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) { nmod_mpoly_mul(Abarl, Abarl, Abarc, lctx); nmod_mpoly_from_mpolyl_perm_inflate(Abar, I->Abarbits, ctx, Abarl, lctx, I->hensel_perm, I->Abarmin_exp, I->Gstride); } if (Bbar != NULL) { nmod_mpoly_mul(Bbarl, Bbarl, Bbarc, lctx); nmod_mpoly_from_mpolyl_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarl, lctx, I->hensel_perm, I->Bbarmin_exp, I->Gstride); } success = 1; cleanup: nmod_mpoly_clear(Al, lctx); nmod_mpoly_clear(Bl, lctx); nmod_mpoly_clear(Gl, lctx); nmod_mpoly_clear(Abarl, lctx); nmod_mpoly_clear(Bbarl, lctx); nmod_mpoly_clear(Ac, lctx); nmod_mpoly_clear(Bc, lctx); nmod_mpoly_clear(Gc, lctx); nmod_mpoly_clear(Abarc, lctx); nmod_mpoly_clear(Bbarc, lctx); nmod_mpoly_ctx_clear(lctx); return success; } /*********************** Hit A and B with brown ******************************/ typedef struct { nmod_mpolyn_struct * Pn; const nmod_mpoly_ctx_struct * nctx; const nmod_mpoly_struct * P; const nmod_mpoly_ctx_struct * ctx; const slong * perm; const ulong * shift, * stride; const thread_pool_handle * handles; slong num_handles; } _convertn_arg_struct; typedef _convertn_arg_struct _convertn_arg_t[1]; static void _worker_convertn(void * varg) { _convertn_arg_struct * arg = (_convertn_arg_struct *) varg; nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(arg->Pn, arg->nctx, arg->P, arg->ctx, arg->perm, arg->shift, arg->stride, arg->handles, arg->num_handles); } static int _try_brown( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, mpoly_gcd_info_t I, const nmod_mpoly_ctx_t ctx) { int success; slong k, m = I->mvars; flint_bitcnt_t wbits; nmod_mpoly_ctx_t nctx; nmod_mpolyn_t An, Bn, Gn, Abarn, Bbarn; nmod_poly_stack_t Sp; slong thread_limit; thread_pool_handle * handles; slong num_handles; if (!(I->can_use & MPOLY_GCD_USE_BROWN)) return 0; FLINT_ASSERT(m >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); wbits = FLINT_MAX(A->bits, B->bits); nmod_mpoly_ctx_init(nctx, m, ORD_LEX, ctx->mod.n); nmod_poly_stack_init(Sp, wbits, nctx); nmod_mpolyn_init(An, wbits, nctx); nmod_mpolyn_init(Bn, wbits, nctx); nmod_mpolyn_init(Gn, wbits, nctx); nmod_mpolyn_init(Abarn, wbits, nctx); nmod_mpolyn_init(Bbarn, wbits, nctx); /* parallelism only on the outer variable */ k = I->brown_perm[m - 1]; thread_limit = FLINT_MIN(I->Adeflate_deg[k], I->Bdeflate_deg[k])/8; thread_limit = FLINT_MIN(thread_limit, (A->length + B->length)/1024); num_handles = flint_request_threads(&handles, thread_limit); if (num_handles > 0) { slong s = mpoly_divide_threads(num_handles, A->length, B->length); _convertn_arg_t arg; FLINT_ASSERT(s >= 0); FLINT_ASSERT(s < num_handles); arg->Pn = Bn; arg->nctx = nctx; arg->P = B; arg->ctx = ctx; arg->perm = I->brown_perm; arg->shift = I->Bmin_exp; arg->stride = I->Gstride; arg->handles = handles + (s + 1); arg->num_handles = num_handles - (s + 1); thread_pool_wake(global_thread_pool, handles[s], 0, _worker_convertn, arg); nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(An, nctx, A, ctx, I->brown_perm, I->Amin_exp, I->Gstride, handles + 0, s); thread_pool_wait(global_thread_pool, handles[s]); } else { nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(An, nctx, A, ctx, I->brown_perm, I->Amin_exp, I->Gstride, NULL, 0); nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(Bn, nctx, B, ctx, I->brown_perm, I->Bmin_exp, I->Gstride, NULL, 0); } FLINT_ASSERT(An->bits == wbits); FLINT_ASSERT(Bn->bits == wbits); FLINT_ASSERT(An->length > 1); FLINT_ASSERT(Bn->length > 1); success = (num_handles > 0) ? nmod_mpolyn_gcd_brown_smprime_threaded_pool(Gn, Abarn, Bbarn, An, Bn, m - 1, nctx, I, handles, num_handles) : nmod_mpolyn_gcd_brown_smprime(Gn, Abarn, Bbarn, An, Bn, m - 1, nctx, I, Sp); if (!success) { nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(An, nctx, A, ctx, I->brown_perm, I->Amin_exp, I->Gstride, NULL, 0); nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(Bn, nctx, B, ctx, I->brown_perm, I->Bmin_exp, I->Gstride, NULL, 0); success = nmod_mpolyn_gcd_brown_lgprime(Gn, Abarn, Bbarn, An, Bn, m - 1, nctx); } if (!success) goto cleanup; nmod_mpoly_from_mpolyn_perm_inflate(G, I->Gbits, ctx, Gn, nctx, I->brown_perm, I->Gmin_exp, I->Gstride); if (Abar != NULL) nmod_mpoly_from_mpolyn_perm_inflate(Abar, I->Abarbits, ctx, Abarn, nctx, I->brown_perm, I->Abarmin_exp, I->Gstride); if (Bbar != NULL) nmod_mpoly_from_mpolyn_perm_inflate(Bbar, I->Bbarbits, ctx, Bbarn, nctx, I->brown_perm, I->Bbarmin_exp, I->Gstride); success = 1; cleanup: flint_give_back_threads(handles, num_handles); nmod_mpolyn_clear(An, nctx); nmod_mpolyn_clear(Bn, nctx); nmod_mpolyn_clear(Gn, nctx); nmod_mpolyn_clear(Abarn, nctx); nmod_mpolyn_clear(Bbarn, nctx); nmod_poly_stack_clear(Sp); nmod_mpoly_ctx_clear(nctx); return success; } /* Both A and B have to be packed into bits <= FLINT_BITS return is 1 for success, 0 for failure. */ int _nmod_mpoly_gcd_algo_small( nmod_mpoly_t G, nmod_mpoly_t Abar, /* could be NULL */ nmod_mpoly_t Bbar, /* could be NULL */ const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; flint_bitcnt_t Gbits = FLINT_MIN(A->bits, B->bits); flint_bitcnt_t Abarbits = A->bits; flint_bitcnt_t Bbarbits = B->bits; slong v_in_both; slong v_in_either; slong v_in_A_only; slong v_in_B_only; slong j; slong nvars = ctx->minfo->nvars; mpoly_gcd_info_t I; #if FLINT_WANT_ASSERT nmod_mpoly_t T, Asave, Bsave; #endif if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); else if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); #if FLINT_WANT_ASSERT nmod_mpoly_init(T, ctx); nmod_mpoly_init(Asave, ctx); nmod_mpoly_init(Bsave, ctx); nmod_mpoly_set(Asave, A, ctx); nmod_mpoly_set(Bsave, B, ctx); #endif mpoly_gcd_info_init(I, nvars); /* entries of I are all now invalid */ I->Gbits = Gbits; I->Abarbits = Abarbits; I->Bbarbits = Bbarbits; mpoly_gcd_info_limits(I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, A->exps, A->bits, A->length, ctx->minfo); mpoly_gcd_info_limits(I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, B->exps, B->bits, B->length, ctx->minfo); /* set ess(p) := p/term_content(p) */ /* check if the cofactors could be monomials, i.e. ess(A) == ess(B) */ for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] - I->Amin_exp[j] != I->Bmax_exp[j] - I->Bmin_exp[j]) goto skip_monomial_cofactors; } if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) { goto successful; } skip_monomial_cofactors: mpoly_gcd_info_stride(I->Gstride, A->exps, A->bits, A->length, I->Amax_exp, I->Amin_exp, B->exps, B->bits, B->length, I->Bmax_exp, I->Bmin_exp, ctx->minfo); for (j = 0; j < nvars; j++) { ulong t = I->Gstride[j]; if (t == 0) { FLINT_ASSERT(I->Amax_exp[j] == I->Amin_exp[j] || I->Bmax_exp[j] == I->Bmin_exp[j]); } else { FLINT_ASSERT((I->Amax_exp[j] - I->Amin_exp[j]) % t == 0); FLINT_ASSERT((I->Bmax_exp[j] - I->Bmin_exp[j]) % t == 0); } I->Adeflate_deg[j] = t == 0 ? 0 : (I->Amax_exp[j] - I->Amin_exp[j])/t; I->Bdeflate_deg[j] = t == 0 ? 0 : (I->Bmax_exp[j] - I->Bmin_exp[j])/t; t = FLINT_MIN(I->Amin_exp[j], I->Bmin_exp[j]); I->Gmin_exp[j] = t; I->Abarmin_exp[j] = I->Amin_exp[j] - t; I->Bbarmin_exp[j] = I->Bmin_exp[j] - t; } /* The following are now valid: I->Amax_exp, I->Amin_exp, I->Alead_count, I->Atail_count, I->Bmax_exp, I->Bmin_exp, I->Blead_count, I->Btail_count, I->Gstride I->Adeflate_deg I->Bdeflate_deg I->Gmin_exp */ /* check if ess(A) and ess(B) have a variable v_in_both in common */ v_in_both = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_both = j; break; } } if (v_in_both == -WORD(1)) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } /* check if ess(A) and ess(B) depend on another variable v_in_either */ FLINT_ASSERT(0 <= v_in_both && v_in_both < nvars); v_in_either = -WORD(1); for (j = 0; j < nvars; j++) { if (j == v_in_both) continue; if (I->Amax_exp[j] > I->Amin_exp[j] || I->Bmax_exp[j] > I->Bmin_exp[j]) { v_in_either = j; break; } } if (v_in_either == -WORD(1)) { _do_univar(G, Abar, Bbar, A, B, v_in_both, I, ctx); goto successful; } /* check if there is a variable in ess(A) that is not in ess(B) */ v_in_A_only = -WORD(1); v_in_B_only = -WORD(1); for (j = 0; j < nvars; j++) { if (I->Amax_exp[j] > I->Amin_exp[j] && I->Bmax_exp[j] == I->Bmin_exp[j]) { v_in_A_only = j; break; } if (I->Bmax_exp[j] > I->Bmin_exp[j] && I->Amax_exp[j] == I->Amin_exp[j]) { v_in_B_only = j; break; } } if (v_in_A_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Abar, Bbar, v_in_A_only, A, I->Amin_exp[v_in_A_only], B, I->Bmin_exp[v_in_A_only], ctx); goto cleanup; } if (v_in_B_only != -WORD(1)) { success = _try_missing_var(G, I->Gbits, Bbar, Abar, v_in_B_only, B, I->Bmin_exp[v_in_B_only], A, I->Amin_exp[v_in_B_only], ctx); goto cleanup; } /* all variable are now either missing from both ess(A) and ess(B), or present in both ess(A) and ess(B) and there are at least two in the latter case */ mpoly_gcd_info_set_perm(I, A->length, B->length, ctx->minfo); /* _set_estimates will probably calculate the correct total degrees */ I->Adeflate_tdeg = I->Bdeflate_tdeg = -1; _set_estimates(I, A, B, ctx); j = FLINT_MAX(0, 8 - I->mvars); if (!I->Gdeflate_deg_bounds_are_nice || ctx->mod.n < j) _set_estimates_medprime(I, A, B, ctx); if (!I->Gdeflate_deg_bounds_are_nice) _set_estimates_lgprime(I, A, B, ctx); /* everything in I is valid now */ /* check divisibility A/B and B/A */ { int gcd_is_trivial = 1; int try_a = I->Gdeflate_deg_bounds_are_nice; int try_b = I->Gdeflate_deg_bounds_are_nice; for (j = 0; j < nvars; j++) { if (I->Gdeflate_deg_bound[j] != 0) gcd_is_trivial = 0; if (I->Adeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_a = 0; if (I->Bdeflate_deg[j] != I->Gdeflate_deg_bound[j]) try_b = 0; } if (gcd_is_trivial) { _do_trivial(G, Abar, Bbar, A, B, I, ctx); goto successful; } if (try_a && _try_divides(G, Bbar, Abar, B, A, ctx)) goto successful; if (try_b && _try_divides(G, Abar, Bbar, A, B, ctx)) goto successful; } if (I->mvars < 3) { mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); algo &= (MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); if (algo == MPOLY_GCD_USE_BROWN) { success = _try_brown(G, Abar, Bbar, A, B, I, ctx); } else if (algo == MPOLY_GCD_USE_HENSEL) { success = _try_hensel(G, Abar, Bbar, A, B, I, ctx); } else { slong k = I->brown_perm[1]; slong d = FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); int deg_is_small = d < ctx->mod.n/2; if (I->Adensity + I->Bdensity > (deg_is_small ? 0.05 : 0.2)) { success = _try_brown(G, Abar, Bbar, A, B, I, ctx) || _try_hensel(G, Abar, Bbar, A, B, I, ctx); } else { success = _try_hensel(G, Abar, Bbar, A, B, I, ctx) || _try_brown(G, Abar, Bbar, A, B, I, ctx); } } goto cleanup; } else if (algo == MPOLY_GCD_USE_HENSEL) { mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); success = _try_hensel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_BROWN) { mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); success = _try_brown(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL) { mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); success = _try_zippel(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else if (algo == MPOLY_GCD_USE_ZIPPEL2) { mpoly_gcd_info_measure_zippel2(I, A->length, B->length, ctx->minfo); success = _try_zippel2(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } else { slong k, d; int deg_is_small = 1; double density = I->Adensity + I->Bdensity; /* mpoly gcd case. Only rule is that measure_X must be called before try_X is called or I->X_perm is accessed. */ mpoly_gcd_info_measure_hensel(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_brown(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_zippel(I, A->length, B->length, ctx->minfo); mpoly_gcd_info_measure_zippel2(I, A->length, B->length, ctx->minfo); for (j = 1; j < I->mvars; j++) { k = I->brown_perm[j]; d = FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); if (d > ctx->mod.n/2) deg_is_small = 0; } if (density > 0.08) { if (!deg_is_small && _try_hensel(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_brown(G, Abar, Bbar, A, B, I, ctx)) goto successful; } if (I->Adeflate_tdeg > 0 && I->Bdeflate_tdeg > 0) { fmpz_t x; double tdensity; fmpz_init(x); fmpz_bin_uiui(x, (ulong)I->Adeflate_tdeg + I->mvars, I->mvars); tdensity = A->length/fmpz_get_d(x); fmpz_bin_uiui(x, (ulong)I->Bdeflate_tdeg + I->mvars, I->mvars); tdensity += B->length/fmpz_get_d(x); density = FLINT_MAX(density, tdensity); fmpz_clear(x); } if (density > (deg_is_small ? 0.05 : 0.001)) { if (_try_hensel(G, Abar, Bbar, A, B, I, ctx)) goto successful; } k = I->zippel2_perm[1]; k = FLINT_MAX(I->Adeflate_deg[k], I->Bdeflate_deg[k]); if ((A->length + B->length)/64 < k) { if (_try_zippel(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_zippel2(G, Abar, Bbar, A, B, I, ctx)) goto successful; } else { if (_try_zippel2(G, Abar, Bbar, A, B, I, ctx)) goto successful; if (_try_zippel(G, Abar, Bbar, A, B, I, ctx)) goto successful; } success = _try_hensel(G, Abar, Bbar, A, B, I, ctx) || _try_brown(G, Abar, Bbar, A, B, I, ctx); goto cleanup; } success = 0; goto cleanup; successful: success = 1; cleanup: mpoly_gcd_info_clear(I); if (success) { FLINT_ASSERT(G->length > 0); if (G->coeffs[0] != 1) { if (Abar != NULL) _nmod_vec_scalar_mul_nmod(Abar->coeffs, Abar->coeffs, Abar->length, G->coeffs[0], ctx->mod); if (Bbar != NULL) _nmod_vec_scalar_mul_nmod(Bbar->coeffs, Bbar->coeffs, Bbar->length, G->coeffs[0], ctx->mod); _nmod_vec_scalar_mul_nmod(G->coeffs, G->coeffs, G->length, nmod_inv(G->coeffs[0], ctx->mod), ctx->mod); } FLINT_ASSERT(nmod_mpoly_divides(T, Asave, G, ctx)); FLINT_ASSERT(Abar == NULL || nmod_mpoly_equal(T, Abar, ctx)); FLINT_ASSERT(nmod_mpoly_divides(T, Bsave, G, ctx)); FLINT_ASSERT(Bbar == NULL || nmod_mpoly_equal(T, Bbar, ctx)); } #if FLINT_WANT_ASSERT nmod_mpoly_clear(T, ctx); nmod_mpoly_clear(Asave, ctx); nmod_mpoly_clear(Bsave, ctx); #endif return success; } /* The gcd calculation is unusual. First see if both inputs fit into FLINT_BITS. Then, try deflation as a last resort. */ static int _nmod_mpoly_gcd_algo_large( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong k; fmpz * Ashift, * Astride; fmpz * Bshift, * Bstride; fmpz * Gshift, * Gstride; nmod_mpoly_t Anew, Bnew; const nmod_mpoly_struct * Ause, * Buse; if (A->length == 1) return _do_monomial_gcd(G, Bbar, Abar, B, A, ctx); if (B->length == 1) return _do_monomial_gcd(G, Abar, Bbar, A, B, ctx); if (_try_monomial_cofactors(G, Abar, Bbar, A, B, ctx)) return 1; nmod_mpoly_init(Anew, ctx); nmod_mpoly_init(Bnew, ctx); Ause = A; if (A->bits > FLINT_BITS) { if (!nmod_mpoly_repack_bits(Anew, A, FLINT_BITS, ctx)) goto could_not_repack; Ause = Anew; } Buse = B; if (B->bits > FLINT_BITS) { if (!nmod_mpoly_repack_bits(Bnew, B, FLINT_BITS, ctx)) goto could_not_repack; Buse = Bnew; } success = _nmod_mpoly_gcd_algo(G, Abar, Bbar, Ause, Buse, ctx, algo); goto cleanup; could_not_repack: /* One of A or B could not be repacked into FLINT_BITS. See if they both fit into FLINT_BITS after deflation. */ Ashift = _fmpz_vec_init(ctx->minfo->nvars); Astride = _fmpz_vec_init(ctx->minfo->nvars); Bshift = _fmpz_vec_init(ctx->minfo->nvars); Bstride = _fmpz_vec_init(ctx->minfo->nvars); Gshift = _fmpz_vec_init(ctx->minfo->nvars); Gstride = _fmpz_vec_init(ctx->minfo->nvars); nmod_mpoly_deflation(Ashift, Astride, A, ctx); nmod_mpoly_deflation(Bshift, Bstride, B, ctx); _fmpz_vec_min(Gshift, Ashift, Bshift, ctx->minfo->nvars); for (k = 0; k < ctx->minfo->nvars; k++) fmpz_gcd(Gstride + k, Astride + k, Bstride + k); nmod_mpoly_deflate(Anew, A, Ashift, Gstride, ctx); if (Anew->bits > FLINT_BITS) { success = nmod_mpoly_repack_bits(Anew, Anew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } nmod_mpoly_deflate(Bnew, B, Bshift, Gstride, ctx); if (Bnew->bits > FLINT_BITS) { success = nmod_mpoly_repack_bits(Bnew, Bnew, FLINT_BITS, ctx); if (!success) goto deflate_cleanup; } success = _nmod_mpoly_gcd_algo(G, Abar, Bbar, Anew, Bnew, ctx, algo); if (!success) goto deflate_cleanup; for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_sub(Ashift + k, Ashift + k, Gshift + k); fmpz_sub(Bshift + k, Bshift + k, Gshift + k); FLINT_ASSERT(fmpz_sgn(Ashift + k) >= 0); FLINT_ASSERT(fmpz_sgn(Bshift + k) >= 0); } nmod_mpoly_inflate(G, G, Gshift, Gstride, ctx); if (Abar != NULL) nmod_mpoly_inflate(Abar, Abar, Ashift, Gstride, ctx); if (Bbar != NULL) nmod_mpoly_inflate(Bbar, Bbar, Bshift, Gstride, ctx); FLINT_ASSERT(G->length > 0); if (G->coeffs[0] != 1) { if (Abar != NULL) _nmod_vec_scalar_mul_nmod(Abar->coeffs, Abar->coeffs, Abar->length, G->coeffs[0], ctx->mod); if (Bbar != NULL) _nmod_vec_scalar_mul_nmod(Bbar->coeffs, Bbar->coeffs, Bbar->length, G->coeffs[0], ctx->mod); _nmod_vec_scalar_mul_nmod(G->coeffs, G->coeffs, G->length, nmod_inv(G->coeffs[0], ctx->mod), ctx->mod); } deflate_cleanup: _fmpz_vec_clear(Ashift, ctx->minfo->nvars); _fmpz_vec_clear(Astride, ctx->minfo->nvars); _fmpz_vec_clear(Bshift, ctx->minfo->nvars); _fmpz_vec_clear(Bstride, ctx->minfo->nvars); _fmpz_vec_clear(Gshift, ctx->minfo->nvars); _fmpz_vec_clear(Gstride, ctx->minfo->nvars); cleanup: nmod_mpoly_clear(Anew, ctx); nmod_mpoly_clear(Bnew, ctx); return success; } int _nmod_mpoly_gcd_algo( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, unsigned int algo) { FLINT_ASSERT(!nmod_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!nmod_mpoly_is_zero(B, ctx)); if (A->bits <= FLINT_BITS && B->bits <= FLINT_BITS) return _nmod_mpoly_gcd_algo_small(G, Abar, Bbar, A, B, ctx, algo); else return _nmod_mpoly_gcd_algo_large(G, Abar, Bbar, A, B, ctx, algo); } int nmod_mpoly_gcd( nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_zero(A, ctx)) { if (nmod_mpoly_is_zero(B, ctx)) nmod_mpoly_zero(G, ctx); else nmod_mpoly_make_monic(G, B, ctx); return 1; } if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_make_monic(G, A, ctx); return 1; } return _nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/nmod_mpoly/gcd_brown.c000066400000000000000000001210461461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" typedef struct { volatile int gcd_is_one; n_poly_struct * gamma; const nmod_mpoly_ctx_struct * ctx; nmod_mpolyn_struct * A, * B; ulong num_threads; slong var; slong bound; const mpoly_gcd_info_struct * I; } _splitbase_struct; typedef _splitbase_struct _splitbase_t[1]; typedef struct { slong idx; _splitbase_struct * base; nmod_mpolyn_t G, Abar, Bbar; n_poly_t modulus; mp_limb_t alpha; slong required_images; } _splitworker_arg_struct; static void _splitworker_bivar(void * varg) { _splitworker_arg_struct * arg = (_splitworker_arg_struct *) varg; _splitbase_struct * base = arg->base; const nmod_mpoly_ctx_struct * ctx = base->ctx; n_poly_t modulus2, alphapow, r; n_poly_t Aevalp, Bevalp, Gevalp, Abarevalp, Bbarevalp; n_poly_t Aevalm, Bevalm, Gevalm, Abarevalm, Bbarevalm; nmod_mpolyn_t T; mp_limb_t gammaevalp, alpha, temp; mp_limb_t gammaevalm; int gstab, astab, bstab, use_stab; slong ldeg; slong N, off, shift; N = mpoly_words_per_exp_sp(base->A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, base->A->bits, ctx->minfo); FLINT_ASSERT(base->var == 1); n_poly_init(r); n_poly_init(modulus2); n_poly_init(alphapow); n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), base->bound + 1)); n_poly_init(Aevalp); n_poly_init(Bevalp); n_poly_init(Gevalp); n_poly_init(Abarevalp); n_poly_init(Bbarevalp); n_poly_init(Aevalm); n_poly_init(Bevalm); n_poly_init(Gevalm); n_poly_init(Abarevalm); n_poly_init(Bbarevalm); nmod_mpolyn_init(T, base->A->bits, ctx); alpha = arg->alpha; use_stab = 1; gstab = bstab = astab = 0; n_poly_one(arg->modulus); while (n_poly_degree(arg->modulus) < arg->required_images) { /* get evaluation point */ if (alpha <= base->num_threads) { break; } alpha -= base->num_threads; FLINT_ASSERT(0 < alpha && alpha <= ctx->mod.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; /* make sure evaluation point does not kill both lc(A) and lc(B) */ _nmod_poly_eval2_pow(&gammaevalp, &gammaevalm, base->gamma, alphapow, ctx->mod); if (gammaevalp == 0 || gammaevalm == 0) { continue; } /* evaluation point should kill neither A nor B */ nmod_mpolyn_interp_reduce_2sm_poly(Aevalp, Aevalm, base->A, alphapow, ctx); nmod_mpolyn_interp_reduce_2sm_poly(Bevalp, Bevalm, base->B, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); if (use_stab && gstab) { int success; slong Gdeg; nmod_mpolyn_interp_reduce_2sm_poly(Gevalp, Gevalm, arg->G, alphapow, ctx); Gdeg = ((arg->G->exps + N*0)[off]>>shift); success = 1; success = success && n_poly_degree(Gevalp) == Gdeg; success = success && n_poly_degree(Gevalm) == Gdeg; success = success && Gevalp->coeffs[Gdeg] == gammaevalp; success = success && Gevalm->coeffs[Gdeg] == gammaevalm; n_poly_mod_divrem(Abarevalp, r, Aevalp, Gevalp, ctx->mod); success = success && (r->length == 0); n_poly_mod_divrem(Abarevalm, r, Aevalm, Gevalm, ctx->mod); success = success && (r->length == 0); n_poly_mod_divrem(Bbarevalp, r, Bevalp, Gevalp, ctx->mod); success = success && (r->length == 0); n_poly_mod_divrem(Bbarevalm, r, Bevalm, Gevalm, ctx->mod); success = success && (r->length == 0); if (!success) { use_stab = 0; n_poly_one(arg->modulus); alpha = arg->alpha; continue; } _n_poly_mod_scalar_mul_nmod(Abarevalp, Abarevalp, gammaevalp, ctx->mod); _n_poly_mod_scalar_mul_nmod(Abarevalm, Abarevalm, gammaevalm, ctx->mod); _n_poly_mod_scalar_mul_nmod(Bbarevalp, Bbarevalp, gammaevalp, ctx->mod); _n_poly_mod_scalar_mul_nmod(Bbarevalm, Bbarevalm, gammaevalm, ctx->mod); } else { n_poly_mod_gcd(Gevalp, Aevalp, Bevalp, ctx->mod); n_poly_mod_divexact(Abarevalp, Aevalp, Gevalp, ctx->mod); n_poly_mod_divexact(Bbarevalp, Bevalp, Gevalp, ctx->mod); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx->mod); n_poly_mod_divexact(Abarevalm, Aevalm, Gevalm, ctx->mod); n_poly_mod_divexact(Bbarevalm, Bevalm, Gevalm, ctx->mod); } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); /* check up */ if (base->gcd_is_one) { break; } if (n_poly_degree(Gevalp) == 0 || n_poly_degree(Gevalm) == 0) { base->gcd_is_one = 1; break; } if (n_poly_degree(Gevalp) != n_poly_degree(Gevalm)) { continue; } /* the Geval have matching degrees */ if (n_poly_degree(arg->modulus) > 0) { FLINT_ASSERT(arg->G->length > 0); if (n_poly_degree(Gevalp) > ((arg->G->exps + N*0)[off]>>shift)) { continue; } else if (n_poly_degree(Gevalp) < ((arg->G->exps + N*0)[off]>>shift)) { n_poly_one(arg->modulus); } } /* update interpolants */ _n_poly_mod_scalar_mul_nmod(Gevalp, Gevalp, gammaevalp, ctx->mod); _n_poly_mod_scalar_mul_nmod(Gevalm, Gevalm, gammaevalm, ctx->mod); if (n_poly_degree(arg->modulus) > 0) { temp = n_poly_mod_evaluate_nmod(arg->modulus, alpha, ctx->mod); FLINT_ASSERT(temp == n_poly_mod_evaluate_nmod(arg->modulus, ctx->mod.n - alpha, ctx->mod)); temp = nmod_mul(temp, alpha, ctx->mod); temp = nmod_add(temp, temp, ctx->mod); temp = n_invmod(temp, ctx->mod.n); _n_poly_mod_scalar_mul_nmod(arg->modulus, arg->modulus, temp, ctx->mod); if (!gstab) { gstab = !nmod_mpolyn_interp_crt_2sm_poly(&ldeg, arg->G, T, Gevalp, Gevalm, arg->modulus, alphapow, ctx); } nmod_mpolyn_interp_crt_2sm_poly(&ldeg, arg->Abar, T, Abarevalp, Abarevalm, arg->modulus, alphapow, ctx); nmod_mpolyn_interp_crt_2sm_poly(&ldeg, arg->Bbar, T, Bbarevalp, Bbarevalm, arg->modulus, alphapow, ctx); } else { nmod_mpolyn_interp_lift_2sm_poly(&ldeg, arg->G, Gevalp, Gevalm, alpha, ctx); nmod_mpolyn_interp_lift_2sm_poly(&ldeg, arg->Abar, Abarevalp, Abarevalm, alpha, ctx); nmod_mpolyn_interp_lift_2sm_poly(&ldeg, arg->Bbar, Bbarevalp, Bbarevalm, alpha, ctx); gstab = astab = bstab = 0; } temp = nmod_mul(alpha, alpha, ctx->mod); _n_poly_mod_scalar_mul_nmod(modulus2, arg->modulus, temp, ctx->mod); n_poly_shift_left(arg->modulus, arg->modulus, 2); n_poly_mod_sub(arg->modulus, arg->modulus, modulus2, ctx->mod); } n_poly_clear(r); n_poly_clear(modulus2); n_poly_clear(alphapow); n_poly_clear(Aevalp); n_poly_clear(Bevalp); n_poly_clear(Gevalp); n_poly_clear(Abarevalp); n_poly_clear(Bbarevalp); n_poly_clear(Aevalm); n_poly_clear(Bevalm); n_poly_clear(Gevalm); n_poly_clear(Abarevalm); n_poly_clear(Bbarevalm); nmod_mpolyn_clear(T, ctx); } static void _splitworker(void * varg) { _splitworker_arg_struct * arg = (_splitworker_arg_struct *) varg; _splitbase_struct * base = arg->base; const nmod_mpoly_ctx_struct * ctx = base->ctx; flint_bitcnt_t bits = base->A->bits; slong var = base->var; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong offset, shift; n_poly_t modulus2, alphapow; nmod_mpolyn_t Aevalp, Bevalp, Gevalp, Abarevalp, Bbarevalp; nmod_mpolyn_t Aevalm, Bevalm, Gevalm, Abarevalm, Bbarevalm; nmod_mpolyn_t T; mp_limb_t gammaevalp, alpha, temp; mp_limb_t gammaevalm; slong ldeg; int success; nmod_poly_stack_t Sp; nmod_poly_stack_init(Sp, bits, ctx); FLINT_ASSERT(var > 0); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, bits, ctx->minfo); n_poly_init(modulus2); n_poly_init(alphapow); n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), base->bound + 1)); nmod_mpolyn_init(Aevalp, bits, ctx); nmod_mpolyn_init(Bevalp, bits, ctx); nmod_mpolyn_init(Gevalp, bits, ctx); nmod_mpolyn_init(Abarevalp, bits, ctx); nmod_mpolyn_init(Bbarevalp, bits, ctx); nmod_mpolyn_init(Aevalm, bits, ctx); nmod_mpolyn_init(Bevalm, bits, ctx); nmod_mpolyn_init(Gevalm, bits, ctx); nmod_mpolyn_init(Abarevalm, bits, ctx); nmod_mpolyn_init(Bbarevalm, bits, ctx); nmod_mpolyn_init(T, bits, ctx); alpha = arg->alpha; n_poly_one(arg->modulus); while (n_poly_degree(arg->modulus) < arg->required_images) { /* get evaluation point */ if (alpha <= base->num_threads) { break; } alpha -= base->num_threads; FLINT_ASSERT(0 < alpha && alpha <= ctx->mod.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; /* make sure evaluation point does not kill both lc(A) and lc(B) */ _nmod_poly_eval2_pow(&gammaevalp, &gammaevalm, base->gamma, alphapow, ctx->mod); if (gammaevalp == 0 || gammaevalm == 0) { continue; } /* evaluation should kill neither A nor B */ nmod_mpolyn_interp_reduce_2sm_mpolyn(Aevalp, Aevalm, base->A, var, alphapow, ctx); nmod_mpolyn_interp_reduce_2sm_mpolyn(Bevalp, Bevalm, base->B, var, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); success = nmod_mpolyn_gcd_brown_smprime( Gevalp, Abarevalp, Bbarevalp, Aevalp, Bevalp, var - 1, ctx, base->I, Sp); success = success && nmod_mpolyn_gcd_brown_smprime( Gevalm, Abarevalm, Bbarevalm, Aevalm, Bevalm, var - 1, ctx, base->I, Sp); if (success == 0) { continue; } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); /* check up */ if (base->gcd_is_one) { break; } if ( nmod_mpolyn_is_nonzero_nmod(Gevalp, ctx) || nmod_mpolyn_is_nonzero_nmod(Gevalm, ctx)) { base->gcd_is_one = 1; break; } if (n_poly_degree(Gevalp->coeffs + 0) != n_poly_degree(Gevalm->coeffs + 0)) { continue; } if (!mpoly_monomial_equal(Gevalp->exps + N*0, Gevalm->exps + N*0, N)) { continue; } /* the Geval have matching degrees */ if (n_poly_degree(arg->modulus) > 0) { int cmp; slong k; FLINT_ASSERT(arg->G->length > 0); k = n_poly_degree(Gevalp->coeffs + 0); cmp = mpoly_monomial_cmp_nomask_extra(arg->G->exps + N*0, Gevalp->exps + N*0, N, offset, k << shift); if (cmp < 0) { continue; } else if (cmp > 0) { n_poly_one(arg->modulus); } } /* update interpolants */ temp = nmod_mpolyn_leadcoeff(Gevalp, ctx); temp = n_invmod(temp, ctx->mod.n); temp = nmod_mul(gammaevalp, temp, ctx->mod); nmod_mpolyn_scalar_mul_nmod(Gevalp, temp, ctx); temp = nmod_mpolyn_leadcoeff(Gevalm, ctx); temp = n_invmod(temp, ctx->mod.n); temp = nmod_mul(gammaevalm, temp, ctx->mod); nmod_mpolyn_scalar_mul_nmod(Gevalm, temp, ctx); if (n_poly_degree(arg->modulus) > 0) { temp = n_poly_mod_evaluate_nmod(arg->modulus, alpha, ctx->mod); FLINT_ASSERT(temp == n_poly_mod_evaluate_nmod(arg->modulus, ctx->mod.n - alpha, ctx->mod)); temp = nmod_mul(temp, alpha, ctx->mod); temp = nmod_add(temp, temp, ctx->mod); temp = n_invmod(temp, ctx->mod.n); _n_poly_mod_scalar_mul_nmod(arg->modulus, arg->modulus, temp, ctx->mod); nmod_mpolyn_interp_crt_2sm_mpolyn(&ldeg, arg->G, T, Gevalp, Gevalm, var, arg->modulus, alphapow, ctx); nmod_mpolyn_interp_crt_2sm_mpolyn(&ldeg, arg->Abar, T, Abarevalp, Abarevalm, var, arg->modulus, alphapow, ctx); nmod_mpolyn_interp_crt_2sm_mpolyn(&ldeg, arg->Bbar, T, Bbarevalp, Bbarevalm, var, arg->modulus, alphapow, ctx); } else { nmod_mpolyn_interp_lift_2sm_mpolyn(&ldeg, arg->G, Gevalp, Gevalm, var, alpha, ctx); nmod_mpolyn_interp_lift_2sm_mpolyn(&ldeg, arg->Abar, Abarevalp, Abarevalm, var, alpha, ctx); nmod_mpolyn_interp_lift_2sm_mpolyn(&ldeg, arg->Bbar, Bbarevalp, Bbarevalm, var, alpha, ctx); } temp = nmod_mul(alpha, alpha, ctx->mod); _n_poly_mod_scalar_mul_nmod(modulus2, arg->modulus, temp, ctx->mod); n_poly_shift_left(arg->modulus, arg->modulus, 2); n_poly_mod_sub(arg->modulus, arg->modulus, modulus2, ctx->mod); } n_poly_clear(modulus2); n_poly_clear(alphapow); nmod_mpolyn_clear(Aevalp, ctx); nmod_mpolyn_clear(Bevalp, ctx); nmod_mpolyn_clear(Gevalp, ctx); nmod_mpolyn_clear(Abarevalp, ctx); nmod_mpolyn_clear(Bbarevalp, ctx); nmod_mpolyn_clear(Aevalm, ctx); nmod_mpolyn_clear(Bevalm, ctx); nmod_mpolyn_clear(Gevalm, ctx); nmod_mpolyn_clear(Abarevalm, ctx); nmod_mpolyn_clear(Bbarevalm, ctx); nmod_mpolyn_clear(T, ctx); nmod_poly_stack_clear(Sp); } typedef struct { slong hint_start, hint_stop; ulong * left_exp, * right_exp; nmod_mpolyn_t poly; slong lastdeg; slong thread_idx; slong final_idx; int GAB; /* 0 -> G, 1 -> A, 2 -> B */ } _joinworker_arg_struct; /* A = crt(B[0], ...., B[count-1]) wrt to P This function takes some preallocated temp space. */ static void _find_edge( slong * start, slong count, const ulong * exp_left, nmod_mpolyn_struct * const * B, slong N) { slong k; for (k = 0; k < count; k++) { slong Blength = B[k]->length; const ulong * Bexps = B[k]->exps; if (start[k] < Blength && mpoly_monomial_gt_nomask(Bexps + N*start[k], exp_left, N)) { /* go right */ do { start[k]++; } while (start[k] < Blength && mpoly_monomial_gt_nomask(Bexps + N*start[k], exp_left, N)); } else { /* go left */ while (start[k] > 0 && !mpoly_monomial_gt_nomask(Bexps + N*(start[k] - 1), exp_left, N)) { start[k]--; } } } } static slong _nmod_mpolyn_crt( const nmod_poly_multi_crt_t P, _joinworker_arg_struct * S, nmod_mpolyn_struct * const * B, slong count, nmod_poly_struct * output, nmod_poly_struct * input, const nmod_mpoly_ctx_t ctx) { int cmp; slong N = mpoly_words_per_exp_sp(S->poly->bits, ctx->minfo); slong lastdegree; slong Ai; slong j, k; slong * start, * stop; nmod_mpolyn_t A; n_poly_t zero; const ulong * exp_left = S->left_exp; const ulong * exp_right = S->right_exp; TMP_INIT; *A = *S->poly; TMP_START; n_poly_init(zero); n_poly_zero(zero); start = (slong *) TMP_ALLOC(2*count*sizeof(slong)); stop = start + count; for (k = 0; k < count; k++) { start[k] = exp_left ? FLINT_MIN(S->hint_start, B[k]->length) : 0; stop[k] = exp_right ? FLINT_MIN(S->hint_stop, B[k]->length) : B[k]->length; } if (exp_left) _find_edge(start, count, exp_left, B, N); if (exp_right) _find_edge(stop, count, exp_right, B, N); #if FLINT_WANT_ASSERT for (k = 0; k < count; k++) { FLINT_ASSERT(0 <= start[k]); FLINT_ASSERT(0 <= stop[k]); FLINT_ASSERT(start[k] <= B[k]->length); FLINT_ASSERT(stop[k] <= B[k]->length); FLINT_ASSERT(start[k] <= stop[k]); /* check start */ if (!exp_left) { FLINT_ASSERT(start[k] == 0); } else { FLINT_ASSERT(start[k] == B[k]->length || !mpoly_monomial_gt_nomask(B[k]->exps + N*start[k], exp_left, N)); FLINT_ASSERT(start[k] == 0 || mpoly_monomial_gt_nomask(B[k]->exps + N*(start[k] - 1), exp_left, N)); } /* check stop */ if (!exp_right) { FLINT_ASSERT(stop[k] == B[k]->length); } else { FLINT_ASSERT(stop[k] == B[k]->length || !mpoly_monomial_gt_nomask(B[k]->exps + N*stop[k], exp_right, N)); FLINT_ASSERT(stop[k] == 0 || mpoly_monomial_gt_nomask(B[k]->exps + N*(stop[k] - 1), exp_right, N)); } } #endif Ai = 0; lastdegree = -WORD(1); while (1) { nmod_mpolyn_fit_length(A, Ai + 1, ctx); k = 0; do { nmod_poly_mock(&input[k], zero, ctx->mod); if (start[k] < stop[k]) goto found_max; } while (++k < count); break; /* all B[k] have been scanned completely */ found_max: nmod_poly_mock(&input[k], B[k]->coeffs + start[k], ctx->mod); mpoly_monomial_set(A->exps + N*Ai, B[k]->exps + N*start[k], N); start[k]++; for (k++; k < count; k++) { nmod_poly_mock(&input[k], zero, ctx->mod); if (start[k] >= stop[k]) { continue; } cmp = mpoly_monomial_cmp_nomask(B[k]->exps + N*start[k], A->exps + N*Ai, N); if (cmp == 0) { nmod_poly_mock(&input[k], B[k]->coeffs + start[k], ctx->mod); FLINT_ASSERT(input[k].length > 0); start[k]++; } else if (cmp > 0) { /* undo previous max's */ for (j = 0; j < k; j++) { start[j] -= (input[j].length > 0); nmod_poly_mock(&input[j], zero, ctx->mod); } goto found_max; } } _nmod_poly_multi_crt_run(output, P, input); n_poly_set_nmod_poly(A->coeffs + Ai, output + 0); lastdegree = FLINT_MAX(lastdegree, n_poly_degree(A->coeffs + Ai)); Ai += !n_poly_is_zero(A->coeffs + Ai); } A->length = Ai; n_poly_clear(zero); TMP_END; *S->poly = *A; return lastdegree; } typedef struct { volatile int idx; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif const nmod_mpoly_ctx_struct * ctx; nmod_poly_multi_crt_t CRT; nmod_mpolyn_struct ** gptrs, ** abarptrs, ** bbarptrs; nmod_mpolyn_struct * G, * Abar, * Bbar; _joinworker_arg_struct * chunks; slong chunks_length; ulong num_threads; } _joinbase_struct; typedef _joinbase_struct _joinbase_t[1]; typedef struct { _joinbase_struct * base; slong thread_idx; } _njoinworker_arg_struct; /* Join the images of G, Abar, and Bbar in each of the split threads */ static void _joinworker(void * varg) { _njoinworker_arg_struct * arg = (_njoinworker_arg_struct *) varg; _joinbase_struct * base = arg->base; nmod_poly_struct * input; nmod_poly_struct * output; slong i, ls = _nmod_poly_multi_crt_local_size(base->CRT); TMP_INIT; TMP_START; input = (nmod_poly_struct *) TMP_ALLOC( base->num_threads * sizeof(nmod_poly_struct)); output = (nmod_poly_struct *) TMP_ALLOC(ls*sizeof(nmod_poly_struct)); for (i = 0; i < ls; i++) nmod_poly_init_mod(output + i, base->ctx->mod); while (1) { /* get exponent of either G, Abar, or Bbar to start working on */ #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif i = base->idx; base->idx = i + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif if (i >= base->chunks_length) { goto cleanup; } base->chunks[i].thread_idx = arg->thread_idx; if (base->chunks[i].GAB == 0) { base->chunks[i].lastdeg = _nmod_mpolyn_crt(base->CRT, base->chunks + i, base->gptrs, base->num_threads, output, input, base->ctx); } else if (base->chunks[i].GAB == 1) { base->chunks[i].lastdeg = _nmod_mpolyn_crt(base->CRT, base->chunks + i, base->abarptrs, base->num_threads, output, input, base->ctx); } else { FLINT_ASSERT(base->chunks[i].GAB == 2); base->chunks[i].lastdeg = _nmod_mpolyn_crt(base->CRT, base->chunks + i, base->bbarptrs, base->num_threads, output, input, base->ctx); } } cleanup: for (i = 0; i < ls; i++) nmod_poly_clear(output + i); TMP_END; return; } static void _finaljoinworker(void * varg) { _njoinworker_arg_struct * arg = (_njoinworker_arg_struct *) varg; _joinbase_struct * base = arg->base; const nmod_mpoly_ctx_struct * ctx = base->ctx; flint_bitcnt_t bits = base->G->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong i, j; slong source_len; ulong * source_exps; n_poly_struct * source_coeffs; slong Ti; ulong * Texps; n_poly_struct * Tcoeffs; for (i = base->chunks_length - 1; i >= 0; i--) { int type = base->chunks[i].GAB; FLINT_ASSERT(base->chunks[i].thread_idx >= 0); if (base->chunks[i].thread_idx != arg->thread_idx) continue; if (type == 0) { Texps = base->G->exps; Tcoeffs = base->G->coeffs; } else if (type == 1) { Texps = base->Abar->exps; Tcoeffs = base->Abar->coeffs; } else { FLINT_ASSERT(type == 2); Texps = base->Bbar->exps; Tcoeffs = base->Bbar->coeffs; } source_len = base->chunks[i].poly->length; source_exps = base->chunks[i].poly->exps + N*0; source_coeffs = base->chunks[i].poly->coeffs + 0; Ti = base->chunks[i].final_idx; mpoly_copy_monomials(Texps + N*Ti, source_exps, source_len, N); for (j = 0; j < source_len; j++) n_poly_swap(Tcoeffs + Ti + j, source_coeffs + j); } } /* Do same as nmod_mpolyun_gcd_brown_smprime but use the threads in handles[0], ..., handles[num_handles - 1] num_handles is allowed to be zero. */ int nmod_mpolyn_gcd_brown_smprime_threaded_pool( nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, const thread_pool_handle * handles, slong num_handles) { int divisibility_test = 0; /* 1: by G, 2: by Abar, 3: by Bbar */ slong i, j; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong offset, shift; ulong num_threads; int success; ulong bound, best_est; slong g_stab_est, abar_stab_est, bbar_stab_est, upper_limit; mp_limb_t alpha; slong deggamma, ldegA, ldegB; slong ldegGs_Abars_Bbars[3]; n_poly_t cA, cB, cG, cAbar, cBbar, gamma; nmod_poly_struct * mptrs; nmod_mpolyn_struct ** gptrs, ** abarptrs, ** bbarptrs; _splitworker_arg_struct * splitargs; _splitbase_t splitbase; _njoinworker_arg_struct * joinargs; _joinbase_t joinbase; n_poly_t t1; nmod_mpolyn_t T1, T2; #if FLINT_WANT_ASSERT nmod_mpolyn_t Aorg, Borg; #endif FLINT_ASSERT(var > 0); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == G->bits); FLINT_ASSERT(bits == Abar->bits); FLINT_ASSERT(bits == Bbar->bits); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); #if FLINT_WANT_ASSERT nmod_mpolyn_init(Aorg, A->bits, ctx); nmod_mpolyn_init(Borg, B->bits, ctx); nmod_mpolyn_set(Aorg, A, ctx); nmod_mpolyn_set(Borg, B, ctx); #endif mpoly_gen_offset_shift_sp(&offset, &shift, 0, G->bits, ctx->minfo); n_poly_init(t1); nmod_mpolyn_init(T1, bits, ctx); nmod_mpolyn_init(T2, bits, ctx); n_poly_init(cA); n_poly_init(cB); nmod_mpolyn_content_last(cA, A, ctx); nmod_mpolyn_content_last(cB, B, ctx); nmod_mpolyn_divexact_last(A, cA, ctx); nmod_mpolyn_divexact_last(B, cB, ctx); n_poly_init(cG); n_poly_mod_gcd(cG, cA, cB, ctx->mod); n_poly_init(cAbar); n_poly_init(cBbar); n_poly_mod_divexact(cAbar, cA, cG, ctx->mod); n_poly_mod_divexact(cBbar, cB, cG, ctx->mod); n_poly_init(gamma); n_poly_mod_gcd(gamma, nmod_mpolyn_leadcoeff_poly(A, ctx), nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->mod); ldegA = nmod_mpolyn_lastdeg(A, ctx); ldegB = nmod_mpolyn_lastdeg(B, ctx); deggamma = n_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); best_est = bound; upper_limit = mpoly_gcd_info_get_brown_upper_limit(I, var, bound); if (I != NULL && I->Gdeflate_deg_bounds_are_nice) { slong k = I->brown_perm[var]; FLINT_ASSERT(var < I->mvars); g_stab_est = 2 + deggamma + I->Gdeflate_deg_bound[k]; abar_stab_est = 2 + deggamma + I->Adeflate_deg[k] - I->Gdeflate_deg_bound[k]; bbar_stab_est = 2 + deggamma + I->Bdeflate_deg[k] - I->Gdeflate_deg_bound[k]; if (g_stab_est < upper_limit) { best_est = g_stab_est; divisibility_test = 1; } if (abar_stab_est < upper_limit && (divisibility_test == 0 || abar_stab_est < best_est)) { best_est = abar_stab_est; divisibility_test = 2; } if (bbar_stab_est < upper_limit && (divisibility_test == 0 || bbar_stab_est < best_est)) { best_est = bbar_stab_est; divisibility_test = 3; } } alpha = (ctx->mod.n - UWORD(1))/UWORD(2); if ((ctx->mod.n & UWORD(1)) == UWORD(0)) { success = 0; goto cleanup; } num_threads = num_handles + 1; gptrs = (nmod_mpolyn_struct **) flint_malloc( num_threads*sizeof(nmod_mpolyn_struct *)); abarptrs = (nmod_mpolyn_struct **) flint_malloc( num_threads*sizeof(nmod_mpolyn_struct *)); bbarptrs = (nmod_mpolyn_struct **) flint_malloc( num_threads*sizeof(nmod_mpolyn_struct *)); mptrs = (nmod_poly_struct *) flint_malloc( num_threads*sizeof(nmod_poly_struct)); splitargs = (_splitworker_arg_struct *) flint_malloc( num_threads*sizeof(_splitworker_arg_struct)); for (i = 0; i < num_threads; i++) { nmod_mpolyn_init(splitargs[i].G, bits, ctx); nmod_mpolyn_init(splitargs[i].Abar, bits, ctx); nmod_mpolyn_init(splitargs[i].Bbar, bits, ctx); n_poly_init(splitargs[i].modulus); } splitbase->num_threads = num_threads; splitbase->A = A; splitbase->B = B; splitbase->ctx = ctx; splitbase->gamma = gamma; splitbase->var = var; splitbase->I = I; compute_split: splitbase->bound = best_est; if (alpha <= num_threads) { success = 0; goto cleanup_split; } alpha -= num_threads; splitbase->gcd_is_one = 0; for (i = 0; i < num_threads; i++) { slong ri = best_est / num_threads + (i < (best_est % num_threads)); splitargs[i].idx = i; splitargs[i].base = splitbase; splitargs[i].alpha = alpha + i; splitargs[i].required_images = FLINT_MAX(ri, WORD(2)); } for (i = 0; i + 1 < num_threads; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, var == 1 ? _splitworker_bivar : _splitworker, &splitargs[i]); } (var == 1 ? _splitworker_bivar : _splitworker)(&splitargs[num_threads - 1]); for (i = 0; i + 1 < num_threads; i++) { thread_pool_wait(global_thread_pool, handles[i]); } if (splitbase->gcd_is_one) { nmod_mpolyn_one(G, ctx); nmod_mpolyn_swap(Abar, A); nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } for (i = 0; i < num_threads; i++) { gptrs[i] = splitargs[i].G; abarptrs[i] = splitargs[i].Abar; bbarptrs[i] = splitargs[i].Bbar; nmod_poly_mock(&mptrs[i], splitargs[i].modulus, ctx->mod); if (n_poly_degree(splitargs[i].modulus) < splitargs[i].required_images) { /* not enough evaluation points - must fail */ success = 0; goto cleanup_split; } FLINT_ASSERT(gptrs[i]->length > 0); FLINT_ASSERT(abarptrs[i]->length > 0); FLINT_ASSERT(bbarptrs[i]->length > 0); } /* Check for consistency in the leading monomial. All args have at least one image, so G, Abar, Bbar are defined and nonzero for each. */ for (i = 1; i < num_threads; i++) { if (!mpoly_monomial_equal(gptrs[i]->exps + N*0, gptrs[0]->exps + N*0, N)) { /* very unlucky - could try again or just fail */ goto compute_split; } } nmod_poly_multi_crt_init(joinbase->CRT); success = nmod_poly_multi_crt_precompute(joinbase->CRT, mptrs, num_threads); FLINT_ASSERT(success); joinbase->num_threads = num_threads; joinbase->gptrs = gptrs; joinbase->abarptrs = abarptrs; joinbase->bbarptrs = bbarptrs; joinbase->G = G; joinbase->Abar = Abar; joinbase->Bbar = Bbar; joinbase->ctx = ctx; #if FLINT_USES_PTHREAD pthread_mutex_init(&joinbase->mutex, NULL); #endif joinargs = (_njoinworker_arg_struct *) flint_malloc( num_threads*sizeof(_njoinworker_arg_struct)); for (i = 0; i < num_threads; i++) { joinargs[i].base = joinbase; joinargs[i].thread_idx = i; } joinbase->chunks_length = 3*num_threads; joinbase->chunks = (_joinworker_arg_struct *) flint_malloc( joinbase->chunks_length*sizeof(_joinworker_arg_struct)); FLINT_ASSERT(joinbase->chunks_length >= 3); for (i = 0; i < 3; i++) { nmod_mpolyn_struct * poly = (i == 0) ? gptrs[0] : (i == 1) ? abarptrs[0] : bbarptrs[0]; for (j = 0; j < num_threads; j++) { _joinworker_arg_struct * d = joinbase->chunks + i*num_threads + j; nmod_mpolyn_init(d->poly, bits, ctx); d->GAB = i; d->lastdeg = -WORD(1); d->thread_idx = -WORD(1); d->final_idx = -WORD(1); d->hint_start = poly->length * (j + 0) / num_threads; d->hint_stop = poly->length * (j + 1) / num_threads; d->left_exp = NULL; d->right_exp = NULL; FLINT_ASSERT(0 <= d->hint_start); FLINT_ASSERT(d->hint_start <= d->hint_stop); FLINT_ASSERT(d->hint_stop <= poly->length); FLINT_ASSERT(d->hint_start < poly->length); if (j > 0) { FLINT_ASSERT(d->hint_start < poly->length); d->left_exp = poly->exps + N*d->hint_start; } if (j + 1 < num_threads) { FLINT_ASSERT(d->hint_stop < poly->length); d->right_exp = poly->exps + N*d->hint_stop; } } } joinbase->idx = 0; for (i = 0; i + 1 < num_threads; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, _joinworker, joinargs + i); } _joinworker(joinargs + num_threads - 1); for (i = 0; i + 1 < num_threads; i++) { thread_pool_wait(global_thread_pool, handles[i]); } /* final trivial join */ ldegGs_Abars_Bbars[0] = -WORD(1); ldegGs_Abars_Bbars[1] = -WORD(1); ldegGs_Abars_Bbars[2] = -WORD(1); { slong idxs[3] = {0, 0, 0}; for (i = 0; i < joinbase->chunks_length; i++) { int type = joinbase->chunks[i].GAB; FLINT_ASSERT(0 <= type && type < 3); joinbase->chunks[i].final_idx = idxs[type]; idxs[type] += joinbase->chunks[i].poly->length; ldegGs_Abars_Bbars[type] = FLINT_MAX(ldegGs_Abars_Bbars[type], joinbase->chunks[i].lastdeg); } nmod_mpolyn_fit_length(G, idxs[0], ctx); nmod_mpolyn_fit_length(Abar, idxs[1], ctx); nmod_mpolyn_fit_length(Bbar, idxs[2], ctx); G->length = idxs[0]; Abar->length = idxs[1]; Bbar->length = idxs[2]; } joinbase->idx = 0; for (i = 0; i + 1 < num_threads; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, _finaljoinworker, joinargs + i); } _finaljoinworker(joinargs + num_threads - 1); for (i = 0; i + 1 < num_threads; i++) { thread_pool_wait(global_thread_pool, handles[i]); } FLINT_ASSERT(nmod_mpolyn_is_canonical(G, ctx)); FLINT_ASSERT(nmod_mpolyn_is_canonical(Abar, ctx)); FLINT_ASSERT(nmod_mpolyn_is_canonical(Bbar, ctx)); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&joinbase->mutex); #endif /* free join data */ nmod_poly_multi_crt_clear(joinbase->CRT); for (i = 0; i < joinbase->chunks_length; i++) { nmod_mpolyn_clear(joinbase->chunks[i].poly, ctx); } flint_free(joinbase->chunks); flint_free(joinargs); if (divisibility_test == 1) { nmod_mpolyn_content_last(t1, G, ctx); nmod_mpolyn_divexact_last(G, t1, ctx); #ifdef nmod_mpolyn_divides_threaded_pool success = nmod_mpolyn_divides_threaded_pool(T1, A, G, ctx, handles, num_handles); success = success && nmod_mpolyn_divides_threaded_pool(T2, B, G, ctx, handles, num_handles); #else success = nmod_mpolyn_divides(T1, A, G, ctx); success = success && nmod_mpolyn_divides(T2, B, G, ctx); #endif if (success) { ulong temp; nmod_mpolyn_swap(T1, Abar); nmod_mpolyn_swap(T2, Bbar); successful_fix_lc: temp = nmod_mpolyn_leadcoeff(G, ctx); nmod_mpolyn_scalar_mul_nmod(Abar, temp, ctx); nmod_mpolyn_scalar_mul_nmod(Bbar, temp, ctx); temp = n_invmod(temp, ctx->mod.n); nmod_mpolyn_scalar_mul_nmod(G, temp, ctx); goto successful_put_content; } } else if (divisibility_test == 2) { nmod_mpolyn_content_last(t1, Abar, ctx); nmod_mpolyn_divexact_last(Abar, t1, ctx); #ifdef nmod_mpolyn_divides_threaded_pool success = nmod_mpolyn_divides_threaded_pool(T1, A, Abar, ctx, handles, num_handles); success = success && nmod_mpolyn_divides_threaded_pool(T2, B, T1, ctx, handles, num_handles); #else success = nmod_mpolyn_divides(T1, A, Abar, ctx); success = success && nmod_mpolyn_divides(T2, B, T1, ctx); #endif if (success) { nmod_mpolyn_swap(T1, G); nmod_mpolyn_swap(T2, Bbar); goto successful_fix_lc; } } else if (divisibility_test == 3) { nmod_mpolyn_content_last(t1, Bbar, ctx); nmod_mpolyn_divexact_last(Bbar, t1, ctx); #ifdef nmod_mpolyn_divides_threaded_pool success = nmod_mpolyn_divides_threaded_pool(T1, B, Bbar, ctx, handles, num_handles); success = success && nmod_mpolyn_divides_threaded_pool(T2, A, T1, ctx, handles, num_handles); #else success = nmod_mpolyn_divides(T1, B, Bbar, ctx); success = success && nmod_mpolyn_divides(T2, A, T1, ctx); #endif if (success) { nmod_mpolyn_swap(T1, G); nmod_mpolyn_swap(T2, Abar); goto successful_fix_lc; } } else /* divisibility test == 0 */ { if ( deggamma + ldegA == ldegGs_Abars_Bbars[0] + ldegGs_Abars_Bbars[1] && deggamma + ldegB == ldegGs_Abars_Bbars[0] + ldegGs_Abars_Bbars[2]) { goto successful; } } /* divisibility test failed - try again */ best_est = bound; divisibility_test = 0; goto compute_split; successful: nmod_mpolyn_content_last(t1, G, ctx); nmod_mpolyn_divexact_last(G, t1, ctx); nmod_mpolyn_divexact_last(Abar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); nmod_mpolyn_divexact_last(Bbar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); successful_put_content: nmod_mpolyn_mul_last(G, cG, ctx); nmod_mpolyn_mul_last(Abar, cAbar, ctx); nmod_mpolyn_mul_last(Bbar, cBbar, ctx); success = 1; cleanup_split: for (i = 0; i < num_threads; i++) { nmod_mpolyn_clear(splitargs[i].G, ctx); nmod_mpolyn_clear(splitargs[i].Abar, ctx); nmod_mpolyn_clear(splitargs[i].Bbar, ctx); n_poly_clear(splitargs[i].modulus); } flint_free(gptrs); flint_free(abarptrs); flint_free(bbarptrs); flint_free(mptrs); flint_free(splitargs); cleanup: #if FLINT_WANT_ASSERT if (success) { success = nmod_mpolyn_divides(T1, Aorg, G, ctx) && nmod_mpolyn_divides(T2, Borg, G, ctx); FLINT_ASSERT(success); FLINT_ASSERT(nmod_mpolyn_equal(T1, Abar, ctx)); FLINT_ASSERT(nmod_mpolyn_equal(T2, Bbar, ctx)); success = 1; } nmod_mpolyn_clear(Aorg, ctx); nmod_mpolyn_clear(Borg, ctx); #endif n_poly_clear(cA); n_poly_clear(cB); n_poly_clear(cG); n_poly_clear(cAbar); n_poly_clear(cBbar); n_poly_clear(gamma); n_poly_clear(t1); nmod_mpolyn_clear(T1, ctx); nmod_mpolyn_clear(T2, ctx); return success; } /* should find its way back here in interesting cases */ int nmod_mpoly_gcd_brown( nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_zero(A, ctx) || nmod_mpoly_is_zero(B, ctx)) return nmod_mpoly_gcd(G, A, B, ctx); return _nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_BROWN); } flint-3.1.3/src/nmod_mpoly/gcd_cofactors.c000066400000000000000000000036641461254215100205540ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_gcd_cofactors( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_zero(A, ctx)) { if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_zero(G, ctx); nmod_mpoly_zero(Abar, ctx); nmod_mpoly_zero(Bbar, ctx); return 1; } nmod_mpoly_set(G, B, ctx); nmod_mpoly_zero(Abar, ctx); nmod_mpoly_one(Bbar, ctx); if (G->coeffs[0] != 1) { _nmod_vec_scalar_mul_nmod(Bbar->coeffs, Bbar->coeffs, Bbar->length, G->coeffs[0], ctx->mod); _nmod_vec_scalar_mul_nmod(G->coeffs, G->coeffs, G->length, nmod_inv(G->coeffs[0], ctx->mod), ctx->mod); } return 1; } if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_set(G, A, ctx); nmod_mpoly_zero(Bbar, ctx); nmod_mpoly_one(Abar, ctx); if (G->coeffs[0] != 1) { _nmod_vec_scalar_mul_nmod(Abar->coeffs, Abar->coeffs, Abar->length, G->coeffs[0], ctx->mod); _nmod_vec_scalar_mul_nmod(G->coeffs, G->coeffs, G->length, nmod_inv(G->coeffs[0], ctx->mod), ctx->mod); } return 1; } return _nmod_mpoly_gcd_algo(G, Abar, Bbar, A, B, ctx, MPOLY_GCD_USE_ALL); } flint-3.1.3/src/nmod_mpoly/gcd_hensel.c000066400000000000000000000632631461254215100200500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod.h" #include "fq_zech.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_zech_mpoly.h" #include "nmod_mpoly_factor.h" #include "fq_zech_mpoly_factor.h" /* in F[x_1, ..., x_n][X]: cont_X(A) = cont_X(B) = 1 compute gamma = gcd(lc_X(A), lc_X(B)) try to find evaluation point x_i -> alpha_i a = A(x_i = alpha_i) in F[X] b = B(x_i = alpha_i) in F[X] compute univariate a = g*abar, b = g*bbar try to find mu1, mu2 in F with gcd(g, mu1*abar + mu2*bbar) = 1 set H = mu1*A + mu2*B lift the univariate factorization g * (mu1*abar + mu2*bbar) against gamma*H imposing (gamma, lc_X H) as the leading coefficients remove content from the lift of g to get G and divide to get Abar and Bbar */ int nmod_mpolyl_gcd_hensel_smprime( nmod_mpoly_t G, slong Gdeg, /* upperbound on deg_X(G) */ nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { int success, alphas_tries_remaining, gamma_is_one; const slong n = ctx->minfo->nvars - 1; slong i, k; flint_bitcnt_t bits = A->bits; mp_limb_t * alphas, * prev_alphas; mp_limb_t q, mu1, mu2; nmod_mpoly_struct * Aevals, * Bevals, * Hevals; nmod_mpoly_struct * H; /* points to A, B, or Hevals + n */ nmod_mpoly_struct * Glcs, * Hlcs; nmod_mpoly_struct Hfac[2], Htfac[2]; slong * Hdegs; slong Adegx, Bdegx, gdegx; nmod_mpoly_t t1, t2, g, abar, bbar, hbar; flint_rand_t state; FLINT_ASSERT(n > 0); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); flint_randinit(state); Hdegs = FLINT_ARRAY_ALLOC(n + 1, slong); Glcs = FLINT_ARRAY_ALLOC(3*(n + 1), nmod_mpoly_struct); Hlcs = Glcs + (n + 1); Hevals = Hlcs + (n + 1); for (i = 0; i < n + 1; i++) { nmod_mpoly_init(Glcs + i, ctx); nmod_mpoly_init(Hlcs + i, ctx); nmod_mpoly_init(Hevals + i, ctx); } alphas = FLINT_ARRAY_ALLOC(2*n, mp_limb_t); prev_alphas = alphas + n; Aevals = FLINT_ARRAY_ALLOC(2*(n + 1), nmod_mpoly_struct); Bevals = Aevals + (n + 1); for (i = 0; i < n; i++) { nmod_mpoly_init(Aevals + i, ctx); nmod_mpoly_init(Bevals + i, ctx); } nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(hbar, ctx); nmod_mpoly_init(Hfac + 0, ctx); nmod_mpoly_init(Hfac + 1, ctx); nmod_mpoly_init(Htfac + 0, ctx); nmod_mpoly_init(Htfac + 1, ctx); /* init done */ alphas_tries_remaining = 10; /* try all zeros first */ for (i = 0; i < n; i++) { prev_alphas[i] = ctx->mod.n; /* no previous at this point */ alphas[i] = 0; } goto got_alpha; next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) { do { alphas[i] = n_urandint(state, ctx->mod.n); } while (alphas[i] == prev_alphas[i]); } got_alpha: /* ensure deg_X do not drop under evaluation */ Adegx = nmod_mpoly_degree_si(A, 0, ctx); Bdegx = nmod_mpoly_degree_si(B, 0, ctx); for (i = n - 1; i >= 0; i--) { nmod_mpoly_evaluate_one_ui(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alphas[i], ctx); nmod_mpoly_evaluate_one_ui(Bevals + i, i == n - 1 ? B : Bevals + i + 1, i + 1, alphas[i], ctx); if (Adegx != nmod_mpoly_degree_si(Aevals + i, 0, ctx) || Bdegx != nmod_mpoly_degree_si(Bevals + i, 0, ctx)) { goto next_alpha; } } /* univariate gcd */ success = nmod_mpoly_gcd_cofactors(g, abar, bbar, Aevals + 0, Bevals + 0, ctx) && nmod_mpoly_gcd(t1, g, abar, ctx) && nmod_mpoly_gcd(t2, g, bbar, ctx); if (!success) goto cleanup; gdegx = nmod_mpoly_degree_si(g, 0, ctx); if (gdegx == 0) { /* G is trivial */ nmod_mpoly_set(Abar, A, ctx); nmod_mpoly_set(Bbar, B, ctx); nmod_mpoly_one(G, ctx); success = 1; goto cleanup; } else if (gdegx > Gdeg) { goto next_alpha; } else if (gdegx < Gdeg) { Gdeg = gdegx; for (i = 0; i < n; i++) prev_alphas[i] = alphas[i]; goto next_alpha; } /* the degbound gdegx (== Gdeg) has at least two witnesses now */ if (gdegx == Adegx) { if (nmod_mpoly_divides(Bbar, B, A, ctx)) { nmod_mpoly_set(G, A, ctx); nmod_mpoly_one(Abar, ctx); success = 1; goto cleanup; } goto next_alpha; } else if (gdegx == Bdegx) { if (nmod_mpoly_divides(Abar, A, B, ctx)) { nmod_mpoly_set(G, B, ctx); nmod_mpoly_one(Bbar, ctx); success = 1; goto cleanup; } goto next_alpha; } FLINT_ASSERT(0 < gdegx && gdegx < FLINT_MIN(Adegx, Bdegx)); /* set Hlcs[n], Glcs[n] (gamma), H, and Hevals */ if (nmod_mpoly_is_one(t1, ctx)) { mu1 = 1; mu2 = 0; nmod_mpoly_swap(hbar, abar, ctx); nmod_mpolyl_lead_coeff(Hlcs + n, A, 1, ctx); nmod_mpolyl_lead_coeff(t2, B, 1, ctx); success = nmod_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (nmod_mpoly_struct *) A; gamma_is_one = nmod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) nmod_mpoly_swap(Hevals + i, Aevals + i, ctx); } else if (nmod_mpoly_is_one(t2, ctx)) { mu1 = 0; mu2 = 1; nmod_mpoly_swap(hbar, bbar, ctx); nmod_mpolyl_lead_coeff(Hlcs + n, B, 1, ctx); nmod_mpolyl_lead_coeff(t2, A, 1, ctx); success = nmod_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (nmod_mpoly_struct *) B; gamma_is_one = nmod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) nmod_mpoly_swap(Hevals + i, Bevals + i, ctx); } else { int mu_tries_remaining = 10; next_mu: if (--mu_tries_remaining < 0) { success = 0; goto cleanup; } mu1 = 1; mu2 = n_urandint(state, ctx->mod.n - 1) + 1; nmod_mpoly_scalar_addmul_ui(hbar, abar, bbar, mu2, ctx); /* make sure the linear combo did not drop degree */ if (nmod_mpoly_degree_si(hbar, 0, ctx) != FLINT_MAX(Adegx, Bdegx) - gdegx) goto next_mu; /* make sure the linear combo is prime to g */ success = nmod_mpoly_gcd(t1, hbar, g, ctx); if (!success) goto cleanup; if (!nmod_mpoly_is_one(t1, ctx)) goto next_mu; nmod_mpolyl_lead_coeff(t1, A, 1, ctx); nmod_mpolyl_lead_coeff(t2, B, 1, ctx); success = nmod_mpoly_gcd(Glcs + n, t1, t2, ctx); if (!success) goto cleanup; H = Hevals + n; nmod_mpoly_scalar_addmul_ui(H, A, B, mu2, ctx); nmod_mpolyl_lead_coeff(Hlcs + n, H, 1, ctx); gamma_is_one = nmod_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) nmod_mpoly_scalar_addmul_ui(Hevals + i, Aevals + i, Bevals + i, mu2, ctx); } if (!gamma_is_one) { nmod_mpoly_mul(Hevals + n, H, Glcs + n, ctx); H = Hevals + n; for (i = n - 1; i >= 0; i--) nmod_mpoly_evaluate_one_ui(Hevals + i, Hevals + i + 1, i + 1, alphas[i], ctx); } success = H->bits <= FLINT_BITS || nmod_mpoly_repack_bits_inplace(H, FLINT_BITS, ctx); if (!success) goto cleanup; /* the evals should all fit in H->bits */ for (i = 0; i < n; i++) nmod_mpoly_repack_bits_inplace(Hevals + i, H->bits, ctx); nmod_mpoly_degrees_si(Hdegs, H, ctx); /* computed evaluated leading coeffs */ for (i = n - 1; i >= 0; i--) { nmod_mpoly_evaluate_one_ui(Glcs + i, Glcs + i + 1, i + 1, alphas[i], ctx); nmod_mpoly_evaluate_one_ui(Hlcs + i, Hlcs + i + 1, i + 1, alphas[i], ctx); /* evaluation could have killed gamma */ if (nmod_mpoly_is_zero(Glcs + i, ctx) || nmod_mpoly_is_zero(Hlcs + i, ctx)) { goto next_alpha; } } /* make the leading coefficients match Glcs[0], Hlcs[0] */ FLINT_ASSERT(nmod_mpoly_is_ui(Glcs + 0, ctx) && Glcs[0].length == 1); FLINT_ASSERT(nmod_mpoly_is_ui(Hlcs + 0, ctx) && Hlcs[0].length == 1); q = nmod_inv(g->coeffs[0], ctx->mod); q = nmod_mul(q, Glcs[0].coeffs[0], ctx->mod); nmod_mpoly_scalar_mul_nmod_invertible(Hfac + 0, g, q, ctx); q = nmod_inv(hbar->coeffs[0], ctx->mod); q = nmod_mul(q, Hlcs[0].coeffs[0], ctx->mod); nmod_mpoly_scalar_mul_nmod_invertible(Hfac + 1, hbar, q, ctx); for (k = 1; k <= n; k++) { _nmod_mpoly_set_lead0(Htfac + 0, Hfac + 0, Glcs + k, ctx); _nmod_mpoly_set_lead0(Htfac + 1, Hfac + 1, Hlcs + k, ctx); success = nmod_mpoly_hlift(k, Htfac, 2, alphas, k < n ? Hevals + k : H, Hdegs, ctx); if (!success) goto next_alpha; nmod_mpoly_swap(Hfac + 0, Htfac + 0, ctx); nmod_mpoly_swap(Hfac + 1, Htfac + 1, ctx); } success = nmod_mpolyl_content(t1, Hfac + 0, 1, ctx); if (!success) goto cleanup; success = nmod_mpoly_divides(G, Hfac + 0, t1, ctx); FLINT_ASSERT(success); if (mu2 == 0) { FLINT_ASSERT(mu1 == 1); /* the division by t1 should succeed, but let's be careful */ nmod_mpolyl_lead_coeff(t1, G, 1, ctx); success = nmod_mpoly_divides(Abar, Hfac + 1, t1, ctx) && nmod_mpoly_divides(Bbar, B, G, ctx); } else if (mu1 == 0) { FLINT_ASSERT(mu2 == 1); /* ditto */ nmod_mpolyl_lead_coeff(t1, G, 1, ctx); success = nmod_mpoly_divides(Bbar, Hfac + 1, t1, ctx) && nmod_mpoly_divides(Abar, A, G, ctx); } else { FLINT_ASSERT(mu1 == 1); success = nmod_mpoly_divides(Abar, A, G, ctx) && nmod_mpoly_divides(Bbar, B, G, ctx); } if (!success) goto next_alpha; success = 1; cleanup: flint_randclear(state); flint_free(Hdegs); for (i = 0; i < n + 1; i++) { nmod_mpoly_clear(Glcs + i, ctx); nmod_mpoly_clear(Hlcs + i, ctx); nmod_mpoly_clear(Hevals + i, ctx); } flint_free(Glcs); for (i = 0; i < n; i++) { nmod_mpoly_clear(Aevals + i, ctx); nmod_mpoly_clear(Bevals + i, ctx); } flint_free(alphas); flint_free(Aevals); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(hbar, ctx); nmod_mpoly_clear(Hfac + 0, ctx); nmod_mpoly_clear(Hfac + 1, ctx); nmod_mpoly_clear(Htfac + 0, ctx); nmod_mpoly_clear(Htfac + 1, ctx); if (success) { nmod_mpoly_repack_bits_inplace(G, bits, ctx); nmod_mpoly_repack_bits_inplace(Abar, bits, ctx); nmod_mpoly_repack_bits_inplace(Bbar, bits, ctx); FLINT_ASSERT(G->length > 0); FLINT_ASSERT(Abar->length > 0); FLINT_ASSERT(Bbar->length > 0); } return success; } int nmod_mpolyl_gcd_hensel_medprime( nmod_mpoly_t G, slong Gdeg, /* upperbound on deg_X(G) */ nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t smA, const nmod_mpoly_t smB, const nmod_mpoly_ctx_t smctx) { int success, alphas_tries_remaining, gamma_is_one; const slong n = smctx->minfo->nvars - 1; slong i, k; flint_bitcnt_t bits = smA->bits; fq_zech_struct * alphas; fq_zech_t q, mu1, mu2; fq_zech_mpoly_t A, B; fq_zech_mpoly_struct * Aevals, * Bevals, * Hevals; fq_zech_mpoly_struct * H; /* points to A, B, or Hevals + n */ fq_zech_mpoly_struct * Glcs, * Hlcs; fq_zech_mpoly_struct Hfac[2], Htfac[2]; nmod_mpoly_struct smHfac[2]; slong * Hdegs; slong Adegx, Bdegx, gdegx; fq_zech_mpoly_t t1, t2, g, abar, bbar, hbar; nmod_mpoly_t t; flint_rand_t state; fq_zech_mpoly_ctx_t ctx; slong edeg, max_degree = n_flog(1000000, smctx->mod.n); if (max_degree < 2) return 0; FLINT_ASSERT(n > 0); FLINT_ASSERT(smA->length > 0); FLINT_ASSERT(smB->length > 0); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(smA->bits == bits); FLINT_ASSERT(smB->bits == bits); FLINT_ASSERT(smctx->minfo->ord == ORD_LEX); edeg = 1 + n_clog(500, smctx->mod.n); edeg = FLINT_MAX(2, edeg); edeg = FLINT_MIN(edeg, max_degree); fq_zech_mpoly_ctx_init_deg(ctx, smctx->minfo->nvars, ORD_LEX, smctx->mod.n, edeg); fq_zech_init(q, ctx->fqctx); fq_zech_init(mu1, ctx->fqctx); fq_zech_init(mu2, ctx->fqctx); fq_zech_mpoly_init(A, ctx); fq_zech_mpoly_init(B, ctx); flint_randinit(state); Hdegs = FLINT_ARRAY_ALLOC(n + 1, slong); Glcs = FLINT_ARRAY_ALLOC(3*(n + 1), fq_zech_mpoly_struct); Hlcs = Glcs + (n + 1); Hevals = Hlcs + (n + 1); for (i = 0; i < n + 1; i++) { fq_zech_mpoly_init(Glcs + i, ctx); fq_zech_mpoly_init(Hlcs + i, ctx); fq_zech_mpoly_init(Hevals + i, ctx); } alphas = FLINT_ARRAY_ALLOC(n, fq_zech_struct); Aevals = FLINT_ARRAY_ALLOC(2*(n + 1), fq_zech_mpoly_struct); Bevals = Aevals + (n + 1); for (i = 0; i < n; i++) { fq_zech_init(alphas + i, ctx->fqctx); fq_zech_mpoly_init(Aevals + i, ctx); fq_zech_mpoly_init(Bevals + i, ctx); } fq_zech_mpoly_init(t1, ctx); fq_zech_mpoly_init(t2, ctx); fq_zech_mpoly_init(g, ctx); fq_zech_mpoly_init(abar, ctx); fq_zech_mpoly_init(bbar, ctx); fq_zech_mpoly_init(hbar, ctx); fq_zech_mpoly_init(Hfac + 0, ctx); fq_zech_mpoly_init(Hfac + 1, ctx); fq_zech_mpoly_init(Htfac + 0, ctx); fq_zech_mpoly_init(Htfac + 1, ctx); nmod_mpoly_init(t, smctx); nmod_mpoly_init(smHfac + 0, smctx); nmod_mpoly_init(smHfac + 1, smctx); /* init done */ _fq_zech_mpoly_set_nmod_mpoly(A, ctx, smA, smctx); _fq_zech_mpoly_set_nmod_mpoly(B, ctx, smB, smctx); alphas_tries_remaining = 20; increase_degree: edeg++; if (edeg > max_degree) { success = 0; goto cleanup; } fq_zech_mpoly_ctx_change_modulus(ctx, edeg); _fq_zech_mpoly_set_nmod_mpoly(A, ctx, smA, smctx); _fq_zech_mpoly_set_nmod_mpoly(B, ctx, smB, smctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) fq_zech_rand(alphas + i, state, ctx->fqctx); /* ensure deg_X do not drop under evaluation */ Adegx = fq_zech_mpoly_degree_si(A, 0, ctx); Bdegx = fq_zech_mpoly_degree_si(B, 0, ctx); for (i = n - 1; i >= 0; i--) { fq_zech_mpoly_evaluate_one_fq_zech(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alphas + i, ctx); fq_zech_mpoly_evaluate_one_fq_zech(Bevals + i, i == n - 1 ? B : Bevals + i + 1, i + 1, alphas + i, ctx); if (Adegx != fq_zech_mpoly_degree_si(Aevals + i, 0, ctx) || Bdegx != fq_zech_mpoly_degree_si(Bevals + i, 0, ctx)) { goto increase_degree; } } /* univariate gcd */ success = fq_zech_mpoly_gcd_cofactors(g, abar, bbar, Aevals + 0, Bevals + 0, ctx) && fq_zech_mpoly_gcd(t1, g, abar, ctx) && fq_zech_mpoly_gcd(t2, g, bbar, ctx); if (!success) goto cleanup; gdegx = fq_zech_mpoly_degree_si(g, 0, ctx); if (gdegx == 0) { /* G is trivial */ nmod_mpoly_set(Abar, smA, smctx); nmod_mpoly_set(Bbar, smB, smctx); nmod_mpoly_one(G, smctx); success = 1; goto cleanup; } else if (gdegx > Gdeg) { goto next_alpha; } else if (gdegx < Gdeg) { Gdeg = gdegx; goto next_alpha; } /* the degbound gdegx (== Gdeg) has at least two witnesses now */ if (gdegx == Adegx) { if (nmod_mpoly_divides(Bbar, smB, smA, smctx)) { nmod_mpoly_set(G, smA, smctx); nmod_mpoly_one(Abar, smctx); success = 1; goto cleanup; } goto next_alpha; } else if (gdegx == Bdegx) { if (nmod_mpoly_divides(Abar, smA, smB, smctx)) { nmod_mpoly_set(G, smB, smctx); nmod_mpoly_one(Bbar, smctx); success = 1; goto cleanup; } goto next_alpha; } FLINT_ASSERT(0 < gdegx && gdegx < FLINT_MIN(Adegx, Bdegx)); /* set Hlcs[n], Glcs[n] (gamma), H, and Hevals */ if (fq_zech_mpoly_is_one(t1, ctx)) { fq_zech_one(mu1, ctx->fqctx); fq_zech_zero(mu2, ctx->fqctx); fq_zech_mpoly_swap(hbar, abar, ctx); fq_zech_mpolyl_lead_coeff(Hlcs + n, A, 1, ctx); fq_zech_mpolyl_lead_coeff(t2, B, 1, ctx); success = fq_zech_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fq_zech_mpoly_struct *) A; gamma_is_one = fq_zech_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fq_zech_mpoly_swap(Hevals + i, Aevals + i, ctx); } else if (fq_zech_mpoly_is_one(t2, ctx)) { fq_zech_zero(mu1, ctx->fqctx); fq_zech_one(mu2, ctx->fqctx); fq_zech_mpoly_swap(hbar, bbar, ctx); fq_zech_mpolyl_lead_coeff(Hlcs + n, B, 1, ctx); fq_zech_mpolyl_lead_coeff(t2, A, 1, ctx); success = fq_zech_mpoly_gcd(Glcs + n, Hlcs + n, t2, ctx); if (!success) goto cleanup; H = (fq_zech_mpoly_struct *) B; gamma_is_one = fq_zech_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fq_zech_mpoly_swap(Hevals + i, Bevals + i, ctx); } else { int mu_tries_remaining = 10; next_mu: if (--mu_tries_remaining < 0) { success = 0; goto cleanup; } fq_zech_one(mu1, ctx->fqctx); fq_zech_rand_not_zero(mu2, state, ctx->fqctx); fq_zech_mpoly_scalar_addmul_fq_zech(hbar, abar, bbar, mu2, ctx); /* make sure the linear combo did not drop degree */ if (fq_zech_mpoly_degree_si(hbar, 0, ctx) != FLINT_MAX(Adegx, Bdegx) - gdegx) goto next_mu; /* make sure the linear combo is prime to g */ success = fq_zech_mpoly_gcd(t1, hbar, g, ctx); if (!success) goto cleanup; if (!fq_zech_mpoly_is_one(t1, ctx)) goto next_mu; fq_zech_mpolyl_lead_coeff(t1, A, 1, ctx); fq_zech_mpolyl_lead_coeff(t2, B, 1, ctx); success = fq_zech_mpoly_gcd(Glcs + n, t1, t2, ctx); if (!success) goto cleanup; H = Hevals + n; fq_zech_mpoly_scalar_addmul_fq_zech(H, A, B, mu2, ctx); fq_zech_mpolyl_lead_coeff(Hlcs + n, H, 1, ctx); gamma_is_one = fq_zech_mpoly_is_one(Glcs + n, ctx); if (gamma_is_one) for (i = 0; i < n; i++) fq_zech_mpoly_scalar_addmul_fq_zech(Hevals + i, Aevals + i, Bevals + i, mu2, ctx); } if (!gamma_is_one) { fq_zech_mpoly_mul(Hevals + n, H, Glcs + n, ctx); H = Hevals + n; for (i = n - 1; i >= 0; i--) fq_zech_mpoly_evaluate_one_fq_zech(Hevals + i, Hevals + i + 1, i + 1, alphas + i, ctx); } success = H->bits <= FLINT_BITS || fq_zech_mpoly_repack_bits_inplace(H, FLINT_BITS, ctx); if (!success) goto cleanup; /* the evals should all fit in H->bits */ for (i = 0; i < n; i++) fq_zech_mpoly_repack_bits_inplace(Hevals + i, H->bits, ctx); fq_zech_mpoly_degrees_si(Hdegs, H, ctx); /* computed evaluated leading coeffs */ for (i = n - 1; i >= 0; i--) { fq_zech_mpoly_evaluate_one_fq_zech(Glcs + i, Glcs + i + 1, i + 1, alphas + i, ctx); fq_zech_mpoly_evaluate_one_fq_zech(Hlcs + i, Hlcs + i + 1, i + 1, alphas + i, ctx); /* evaluation could have killed gamma */ if (fq_zech_mpoly_is_zero(Glcs + i, ctx) || fq_zech_mpoly_is_zero(Hlcs + i, ctx)) { goto increase_degree; } } /* make the leading coefficients match Glcs[0], Hlcs[0] */ FLINT_ASSERT(fq_zech_mpoly_is_fq_zech(Glcs + 0, ctx) && Glcs[0].length == 1); FLINT_ASSERT(fq_zech_mpoly_is_fq_zech(Hlcs + 0, ctx) && Hlcs[0].length == 1); fq_zech_inv(q, g->coeffs + 0, ctx->fqctx); fq_zech_mul(q, q, Glcs[0].coeffs + 0, ctx->fqctx); fq_zech_mpoly_scalar_mul_fq_zech(Hfac + 0, g, q, ctx); fq_zech_inv(q, hbar->coeffs + 0, ctx->fqctx); fq_zech_mul(q, q, Hlcs[0].coeffs + 0, ctx->fqctx); fq_zech_mpoly_scalar_mul_fq_zech(Hfac + 1, hbar, q, ctx); for (k = 1; k <= n; k++) { _fq_zech_mpoly_set_lead0(Htfac + 0, Hfac + 0, Glcs + k, ctx); _fq_zech_mpoly_set_lead0(Htfac + 1, Hfac + 1, Hlcs + k, ctx); success = fq_zech_mpoly_hlift(k, Htfac, 2, alphas, k < n ? Hevals + k : H, Hdegs, ctx); if (!success) goto next_alpha; fq_zech_mpoly_swap(Hfac + 0, Htfac + 0, ctx); fq_zech_mpoly_swap(Hfac + 1, Htfac + 1, ctx); } fq_zech_mpoly_scalar_mul_fq_zech(Hfac + 1, Hfac + 1, Hfac[0].coeffs + 0, ctx); fq_zech_mpoly_make_monic(Hfac + 0, Hfac + 0, ctx); if (!_fq_zech_mpoly_get_nmod_mpoly(smHfac + 0, smctx, Hfac + 0, ctx)) { /* the lifted gcd is not in Fp. possible? */ goto next_alpha; } success = nmod_mpolyl_content(t, smHfac + 0, 1, smctx); if (!success) goto cleanup; success = nmod_mpoly_divides(G, smHfac + 0, t, smctx); FLINT_ASSERT(success); if (fq_zech_is_zero(mu2, ctx->fqctx)) { FLINT_ASSERT(fq_zech_is_one(mu1, ctx->fqctx)); if (!_fq_zech_mpoly_get_nmod_mpoly(smHfac + 1, smctx, Hfac + 1, ctx)) goto next_alpha; /* the division by t1 should succeed, but let's be careful */ nmod_mpolyl_lead_coeff(t, G, 1, smctx); success = nmod_mpoly_divides(Abar, smHfac + 1, t, smctx) && nmod_mpoly_divides(Bbar, smB, G, smctx); } else if (fq_zech_is_zero(mu1, ctx->fqctx)) { FLINT_ASSERT(fq_zech_is_one(mu2, ctx->fqctx)); if (!_fq_zech_mpoly_get_nmod_mpoly(smHfac + 1, smctx, Hfac + 1, ctx)) goto next_alpha; /* ditto */ nmod_mpolyl_lead_coeff(t, G, 1, smctx); success = nmod_mpoly_divides(Bbar, smHfac + 1, t, smctx) && nmod_mpoly_divides(Abar, smA, G, smctx); } else { FLINT_ASSERT(fq_zech_is_one(mu1, ctx->fqctx)); success = nmod_mpoly_divides(Abar, smA, G, smctx) && nmod_mpoly_divides(Bbar, smB, G, smctx); } if (!success) goto next_alpha; success = 1; cleanup: fq_zech_clear(q, ctx->fqctx); fq_zech_clear(mu1, ctx->fqctx); fq_zech_clear(mu2, ctx->fqctx); fq_zech_mpoly_clear(A, ctx); fq_zech_mpoly_clear(B, ctx); flint_randclear(state); flint_free(Hdegs); for (i = 0; i < n + 1; i++) { fq_zech_mpoly_clear(Glcs + i, ctx); fq_zech_mpoly_clear(Hlcs + i, ctx); fq_zech_mpoly_clear(Hevals + i, ctx); } flint_free(Glcs); for (i = 0; i < n; i++) { fq_zech_clear(alphas + i, ctx->fqctx); fq_zech_mpoly_clear(Aevals + i, ctx); fq_zech_mpoly_clear(Bevals + i, ctx); } flint_free(alphas); flint_free(Aevals); fq_zech_mpoly_clear(t1, ctx); fq_zech_mpoly_clear(t2, ctx); fq_zech_mpoly_clear(g, ctx); fq_zech_mpoly_clear(abar, ctx); fq_zech_mpoly_clear(bbar, ctx); fq_zech_mpoly_clear(hbar, ctx); fq_zech_mpoly_clear(Hfac + 0, ctx); fq_zech_mpoly_clear(Hfac + 1, ctx); fq_zech_mpoly_clear(Htfac + 0, ctx); fq_zech_mpoly_clear(Htfac + 1, ctx); nmod_mpoly_clear(t, smctx); nmod_mpoly_clear(smHfac + 0, smctx); nmod_mpoly_clear(smHfac + 1, smctx); fq_zech_mpoly_ctx_clear(ctx); if (success) { nmod_mpoly_repack_bits_inplace(G, bits, smctx); nmod_mpoly_repack_bits_inplace(Abar, bits, smctx); nmod_mpoly_repack_bits_inplace(Bbar, bits, smctx); FLINT_ASSERT(G->length > 0); FLINT_ASSERT(Abar->length > 0); FLINT_ASSERT(Bbar->length > 0); } return success; } /* should find its way back here in interesting cases */ int nmod_mpoly_gcd_hensel( nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_zero(A, ctx) || nmod_mpoly_is_zero(B, ctx)) return nmod_mpoly_gcd(G, A, B, ctx); return _nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_HENSEL); } flint-3.1.3/src/nmod_mpoly/gcd_zippel.c000066400000000000000000000375301461254215100200730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" int nmod_mpolyu_gcdm_zippel_bivar( nmod_mpolyu_t G, nmod_mpolyu_t Abar, nmod_mpolyu_t Bbar, nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { slong var = 0; slong Alastdeg, Blastdeg; slong bound; slong lastdeg; int success = 0, changed, have_enough; nmod_mpolyun_t An, Bn, H, Ht; slong deg; fq_nmod_mpoly_ctx_t ffctx; fq_nmod_mpolyu_t Aeval, Beval, Geval; n_poly_t modulus, gamma, hc; fq_nmod_t t, geval; FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(Abar->bits == A->bits); FLINT_ASSERT(Bbar->bits == A->bits); FLINT_ASSERT(B->bits == A->bits); nmod_mpolyun_init(An, A->bits, ctx); nmod_mpolyun_init(Bn, A->bits, ctx); nmod_mpolyu_cvtto_mpolyun(An, A, var, ctx); nmod_mpolyu_cvtto_mpolyun(Bn, B, var, ctx); FLINT_ASSERT(An->bits == B->bits); FLINT_ASSERT(An->bits == G->bits); FLINT_ASSERT(An->length > 0); FLINT_ASSERT(Bn->length > 0); FLINT_ASSERT(An->exps[A->length - 1] == 0); FLINT_ASSERT(Bn->exps[B->length - 1] == 0); n_poly_init(gamma); n_poly_mod_gcd(gamma, nmod_mpolyun_leadcoeff_poly(An, ctx), nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->mod); /* bound on the number of images */ Alastdeg = nmod_mpolyun_lastdeg(An, ctx); Blastdeg = nmod_mpolyun_lastdeg(Bn, ctx); bound = 1 + n_poly_degree(gamma) + FLINT_MIN(Alastdeg, Blastdeg); n_poly_init(hc); n_poly_init(modulus); n_poly_one(modulus); nmod_mpolyun_init(H, A->bits, ctx); nmod_mpolyun_init(Ht, A->bits, ctx); deg = WORD(20)/(FLINT_BIT_COUNT(ctx->mod.n)); deg = FLINT_MAX(WORD(2), deg); fq_nmod_mpoly_ctx_init_deg(ffctx, ctx->minfo->nvars, ORD_LEX, ctx->mod.n, deg); fq_nmod_mpolyu_init(Aeval, A->bits, ffctx); fq_nmod_mpolyu_init(Beval, A->bits, ffctx); fq_nmod_mpolyu_init(Geval, A->bits, ffctx); fq_nmod_init(geval, ffctx->fqctx); fq_nmod_init(t, ffctx->fqctx); while (1) { /* TODO: instead of simply increasing the degree every time, try to find more irreducibles of the same degree */ deg++; if (deg > 10000) { /* ran out of primes */ success = 0; goto finished; } fq_nmod_mpolyu_clear(Aeval, ffctx); fq_nmod_mpolyu_clear(Beval, ffctx); fq_nmod_mpolyu_clear(Geval, ffctx); fq_nmod_clear(geval, ffctx->fqctx); fq_nmod_clear(t, ffctx->fqctx); fq_nmod_mpoly_ctx_change_modulus(ffctx, deg); fq_nmod_mpolyu_init(Aeval, A->bits, ffctx); fq_nmod_mpolyu_init(Beval, A->bits, ffctx); fq_nmod_mpolyu_init(Geval, A->bits, ffctx); fq_nmod_init(geval, ffctx->fqctx); fq_nmod_init(t, ffctx->fqctx); /* make sure reduction does not kill both lc(A) and lc(B) */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(geval), gamma, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); if (fq_nmod_is_zero(geval, ffctx->fqctx)) goto outer_continue; /* make sure reduction does not kill either A or B */ nmod_mpolyun_interp_reduce_lg_mpolyu(Aeval, An, ffctx, ctx); nmod_mpolyun_interp_reduce_lg_mpolyu(Beval, Bn, ffctx, ctx); if (Aeval->length == 0 || Beval->length == 0) goto outer_continue; FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Aeval, ffctx)); FLINT_ASSERT(fq_nmod_mpolyu_is_canonical(Beval, ffctx)); fq_nmod_mpolyu_gcdp_zippel_univar_no_cofactors(Geval, Aeval, Beval, ffctx); if (fq_nmod_mpolyu_is_one(Geval, ffctx)) { nmod_mpolyu_one(G, ctx); nmod_mpolyu_swap(Abar, A, ctx); nmod_mpolyu_swap(Bbar, B, ctx); success = 1; goto finished; } FLINT_ASSERT(Geval->length > 0); if (n_poly_degree(modulus) > 0) { if (Geval->exps[0] > H->exps[0]) { goto outer_continue; } else if (Geval->exps[0] < H->exps[0]) { n_poly_one(modulus); } } n_fq_get_fq_nmod(t, fq_nmod_mpolyu_leadcoeff(Geval, ffctx), ffctx->fqctx); fq_nmod_inv(t, t, ffctx->fqctx); fq_nmod_mul(t, t, geval, ffctx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Geval, t, ffctx); if (n_poly_degree(modulus) > 0) { changed = nmod_mpolyun_interp_crt_lg_mpolyu(&lastdeg, H, Ht, modulus, ctx, Geval, ffctx); n_poly_mod_mul(modulus, modulus, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); have_enough = n_poly_degree(modulus) >= bound; if (changed && !have_enough) { goto outer_continue; } if (!changed || have_enough) { nmod_mpolyun_content_last(hc, H, ctx); nmod_mpolyun_set(Ht, H, ctx); nmod_mpolyun_divexact_last(Ht, hc, ctx); nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { n_poly_one(modulus); goto outer_continue; } } else { nmod_mpolyun_interp_lift_lg_mpolyu(H, ctx, Geval, ffctx); n_poly_set_nmod_poly(modulus, ffctx->fqctx->modulus); } outer_continue:; } finished: n_poly_clear(gamma); n_poly_clear(hc); n_poly_clear(modulus); nmod_mpolyun_clear(An, ctx); nmod_mpolyun_clear(Bn, ctx); nmod_mpolyun_clear(H, ctx); nmod_mpolyun_clear(Ht, ctx); fq_nmod_clear(geval, ffctx->fqctx); fq_nmod_clear(t, ffctx->fqctx); fq_nmod_mpolyu_clear(Aeval, ffctx); fq_nmod_mpolyu_clear(Beval, ffctx); fq_nmod_mpolyu_clear(Geval, ffctx); fq_nmod_mpoly_ctx_clear(ffctx); return success; } int nmod_mpolyu_gcdm_zippel( nmod_mpolyu_t G, nmod_mpolyu_t Abar, nmod_mpolyu_t Bbar, nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { slong degbound; slong bound; slong Alastdeg, Blastdeg; slong lastdeg; int success, changed, have_enough; nmod_mpolyun_t An, Bn, Hn, Ht; slong deg; fq_nmod_mpoly_ctx_t ffctx; fq_nmod_mpolyu_t Aff, Bff, Gff, Abarff, Bbarff, Gform; n_poly_t modulus, gamma, hc; fq_nmod_t t, gammaff; FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(Abar->bits == A->bits); FLINT_ASSERT(Bbar->bits == A->bits); FLINT_ASSERT(B->bits == A->bits); success = nmod_mpolyu_gcdp_zippel(G, Abar, Bbar, A, B, ctx->minfo->nvars - 1, ctx, randstate); if (success) { return 1; } /* bivariate more comfortable separated */ if (ctx->minfo->nvars == 1) { return nmod_mpolyu_gcdm_zippel_bivar(G, Abar, Bbar, A, B, ctx, randstate); } FLINT_ASSERT(ctx->minfo->nvars > 1); n_poly_init(hc); n_poly_init(modulus); nmod_mpolyun_init(An, A->bits, ctx); nmod_mpolyun_init(Bn, A->bits, ctx); nmod_mpolyu_cvtto_mpolyun(An, A, ctx->minfo->nvars - 1, ctx); nmod_mpolyu_cvtto_mpolyun(Bn, B, ctx->minfo->nvars - 1, ctx); FLINT_ASSERT(An->bits == B->bits); FLINT_ASSERT(An->bits == G->bits); FLINT_ASSERT(An->length > 0); FLINT_ASSERT(Bn->length > 0); FLINT_ASSERT(An->exps[A->length - 1] == 0); FLINT_ASSERT(Bn->exps[B->length - 1] == 0); n_poly_init(gamma); n_poly_mod_gcd(gamma, nmod_mpolyun_leadcoeff_poly(An, ctx), nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->mod); /* bound on the number of images */ Alastdeg = nmod_mpolyun_lastdeg(An, ctx); Blastdeg = nmod_mpolyun_lastdeg(Bn, ctx); bound = 1 + n_poly_degree(gamma) + FLINT_MIN(Alastdeg, Blastdeg); /* degree bound on the gcd */ degbound = FLINT_MIN(A->exps[0], B->exps[0]); n_poly_one(modulus); nmod_mpolyun_init(Hn, A->bits, ctx); nmod_mpolyun_init(Ht, A->bits, ctx); deg = WORD(20)/(FLINT_BIT_COUNT(ctx->mod.n)); deg = FLINT_MAX(WORD(2), deg); fq_nmod_mpoly_ctx_init_deg(ffctx, ctx->minfo->nvars, ORD_LEX, ctx->mod.n, deg); fq_nmod_mpolyu_init(Aff, A->bits, ffctx); fq_nmod_mpolyu_init(Bff, A->bits, ffctx); fq_nmod_mpolyu_init(Gff, A->bits, ffctx); fq_nmod_mpolyu_init(Abarff, A->bits, ffctx); fq_nmod_mpolyu_init(Bbarff, A->bits, ffctx); fq_nmod_mpolyu_init(Gform, A->bits, ffctx); fq_nmod_init(gammaff, ffctx->fqctx); fq_nmod_init(t, ffctx->fqctx); choose_prime_outer: /* same TODO */ deg++; if (deg > 10000) { /* ran out of primes */ success = 0; goto finished; } fq_nmod_mpolyu_clear(Aff, ffctx); fq_nmod_mpolyu_clear(Bff, ffctx); fq_nmod_mpolyu_clear(Gff, ffctx); fq_nmod_mpolyu_clear(Abarff, ffctx); fq_nmod_mpolyu_clear(Bbarff, ffctx); fq_nmod_mpolyu_clear(Gform, ffctx); fq_nmod_clear(gammaff, ffctx->fqctx); fq_nmod_clear(t, ffctx->fqctx); fq_nmod_mpoly_ctx_change_modulus(ffctx, deg); fq_nmod_mpolyu_init(Aff, A->bits, ffctx); fq_nmod_mpolyu_init(Bff, A->bits, ffctx); fq_nmod_mpolyu_init(Gff, A->bits, ffctx); fq_nmod_mpolyu_init(Abarff, A->bits, ffctx); fq_nmod_mpolyu_init(Bbarff, A->bits, ffctx); fq_nmod_mpolyu_init(Gform, A->bits, ffctx); fq_nmod_init(gammaff, ffctx->fqctx); fq_nmod_init(t, ffctx->fqctx); /* make sure reduction does not kill both lc(A) and lc(B) */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(gammaff), gamma, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); if (fq_nmod_is_zero(gammaff, ffctx->fqctx)) goto choose_prime_outer; /* make sure reduction does not kill either A or B */ nmod_mpolyun_interp_reduce_lg_mpolyu(Aff, An, ffctx, ctx); nmod_mpolyun_interp_reduce_lg_mpolyu(Bff, Bn, ffctx, ctx); if (Aff->length == 0 || Bff->length == 0) goto choose_prime_outer; success = fq_nmod_mpolyu_gcdp_zippel(Gff, Abarff, Bbarff, Aff, Bff, ctx->minfo->nvars - 2, ffctx, randstate); if (!success || Gff->exps[0] > degbound) goto choose_prime_outer; degbound = Gff->exps[0]; if (Gff->length == 1 && Gff->exps[0] == 0) { FLINT_ASSERT(fq_nmod_mpoly_is_one(Gff->coeffs + 0, ffctx)); FLINT_ASSERT(!fq_nmod_mpoly_is_zero(Gff->coeffs + 0, ffctx)); nmod_mpolyu_one(G, ctx); nmod_mpolyu_swap(Abar, A, ctx); nmod_mpolyu_swap(Bbar, B, ctx); success = 1; goto finished; } n_fq_get_fq_nmod(t, fq_nmod_mpolyu_leadcoeff(Gff, ffctx), ffctx->fqctx); fq_nmod_inv(t, t, ffctx->fqctx); fq_nmod_mul(t, t, gammaff, ffctx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Gff, t, ffctx); fq_nmod_mpolyu_setform(Gform, Gff, ffctx); nmod_mpolyun_interp_lift_lg_mpolyu(Hn, ctx, Gff, ffctx); n_poly_set_nmod_poly(modulus, ffctx->fqctx->modulus); choose_prime_inner: deg++; if (deg > 1000) { /* ran out of primes */ success = 0; goto finished; } /* Gform need not be reinited because only its exponents are used */ fq_nmod_mpolyu_clear(Aff, ffctx); fq_nmod_mpolyu_clear(Bff, ffctx); fq_nmod_mpolyu_clear(Gff, ffctx); fq_nmod_mpolyu_clear(Abarff, ffctx); fq_nmod_mpolyu_clear(Bbarff, ffctx); fq_nmod_clear(gammaff, ffctx->fqctx); fq_nmod_clear(t, ffctx->fqctx); fq_nmod_mpoly_ctx_change_modulus(ffctx, deg); fq_nmod_mpolyu_init(Aff, A->bits, ffctx); fq_nmod_mpolyu_init(Bff, A->bits, ffctx); fq_nmod_mpolyu_init(Gff, A->bits, ffctx); fq_nmod_mpolyu_init(Abarff, A->bits, ffctx); fq_nmod_mpolyu_init(Bbarff, A->bits, ffctx); fq_nmod_init(gammaff, ffctx->fqctx); fq_nmod_init(t, ffctx->fqctx); /* make sure reduction does not kill both lc(A) and lc(B) */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(gammaff), gamma, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); if (fq_nmod_is_zero(gammaff, ffctx->fqctx)) goto choose_prime_inner; /* make sure reduction does not kill either A or B */ nmod_mpolyun_interp_reduce_lg_mpolyu(Aff, An, ffctx, ctx); nmod_mpolyun_interp_reduce_lg_mpolyu(Bff, Bn, ffctx, ctx); if (Aff->length == 0 || Bff->length == 0) goto choose_prime_inner; switch (fq_nmod_mpolyu_gcds_zippel(Gff, Aff, Bff, Gform, ctx->minfo->nvars - 1, ffctx, randstate, °bound)) { default: FLINT_ASSERT(0); case nmod_gcds_form_main_degree_too_high: case nmod_gcds_form_wrong: case nmod_gcds_no_solution: goto choose_prime_outer; case nmod_gcds_scales_not_found: case nmod_gcds_eval_point_not_found: case nmod_gcds_eval_gcd_deg_too_high: goto choose_prime_inner; case nmod_gcds_success: break; } n_fq_get_fq_nmod(t, fq_nmod_mpolyu_leadcoeff(Gff, ffctx), ffctx->fqctx); if (fq_nmod_is_zero(t, ffctx->fqctx)) goto choose_prime_inner; fq_nmod_inv(t, t, ffctx->fqctx); fq_nmod_mul(t, t, gammaff, ffctx->fqctx); fq_nmod_mpolyu_scalar_mul_fq_nmod(Gff, t, ffctx); changed = nmod_mpolyun_interp_mcrt_lg_mpolyu(&lastdeg, Hn, ctx, modulus, Gff, ffctx); n_poly_mod_mul(modulus, modulus, evil_const_cast_nmod_poly_to_n_poly(ffctx->fqctx->modulus), ctx->mod); have_enough = n_poly_degree(modulus) >= bound; if (changed && !have_enough) { goto choose_prime_inner; } if (!changed || have_enough) { nmod_mpolyun_content_last(hc, Hn, ctx); nmod_mpolyun_set(Ht, Hn, ctx); nmod_mpolyun_divexact_last(Ht, hc, ctx); nmod_mpolyu_cvtfrom_mpolyun(G, Ht, ctx->minfo->nvars - 1, ctx); if ( nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { n_poly_one(modulus); goto choose_prime_outer; } goto choose_prime_inner; finished: n_poly_clear(gamma); n_poly_clear(hc); n_poly_clear(modulus); nmod_mpolyun_clear(An, ctx); nmod_mpolyun_clear(Bn, ctx); nmod_mpolyun_clear(Hn, ctx); nmod_mpolyun_clear(Ht, ctx); fq_nmod_mpolyu_clear(Aff, ffctx); fq_nmod_mpolyu_clear(Bff, ffctx); fq_nmod_mpolyu_clear(Gff, ffctx); fq_nmod_mpolyu_clear(Abarff, ffctx); fq_nmod_mpolyu_clear(Bbarff, ffctx); fq_nmod_mpolyu_clear(Gform, ffctx); fq_nmod_clear(gammaff, ffctx->fqctx); fq_nmod_clear(t, ffctx->fqctx); fq_nmod_mpoly_ctx_clear(ffctx); return success; } /* should find its way back here in interesting cases */ int nmod_mpoly_gcd_zippel( nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_zero(A, ctx) || nmod_mpoly_is_zero(B, ctx)) return nmod_mpoly_gcd(G, A, B, ctx); return _nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL); } flint-3.1.3/src/nmod_mpoly/gcd_zippel2.c000066400000000000000000002366001461254215100201540ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "nmod_mpoly_factor.h" #include "fq_nmod_mpoly_factor.h" /* evaluation at gen(start) -> betas[0] gen(start+1) -> betas[1] ... gen(stop-1) -> betas[stop-start-1] the other gen are assumed to not appear in A */ void _nmod_mpoly_monomial_evals_cache( n_poly_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mp_limb_t * betas, slong start, slong stop, const mpoly_ctx_t mctx, nmod_t mod) { slong i, Ai; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; n_poly_struct * caches; mp_limb_t * c; slong num = stop - start; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(num > 0); caches = FLINT_ARRAY_ALLOC(3*num, n_poly_struct); off = FLINT_ARRAY_ALLOC(2*num, slong); shift = off + num; for (i = 0; i < num; i++) { mpoly_gen_offset_shift_sp(&off[i], &shift[i], i + start, Abits, mctx); n_poly_init(caches + 3*i + 0); n_poly_init(caches + 3*i + 1); n_poly_init(caches + 3*i + 2); nmod_pow_cache_start(betas[i], caches + 3*i + 0, caches + 3*i + 1, caches + 3*i + 2); } n_poly_fit_length(E, Alen); E->length = Alen; for (Ai = 0; Ai < Alen; Ai++) { c = E->coeffs + Ai; *c = 1; for (i = 0; i < num; i++) { ulong ei = (Aexps[N*Ai + off[i]] >> shift[i]) & mask; *c = nmod_pow_cache_mulpow_ui(*c, ei, caches + 3*i + 0, caches + 3*i + 1, caches + 3*i + 2, mod); } } for (i = 0; i < num; i++) { n_poly_clear(caches + 3*i + 0); n_poly_clear(caches + 3*i + 1); n_poly_clear(caches + 3*i + 2); } flint_free(caches); flint_free(off); } /* evaluation at gen(0) -> x gen(1) -> y gen(2) -> betas[0] gen(3) -> betas[1] ... gen(m-1) -> betas[m-3] */ void _nmod_mpoly_monomial_evals2_cache( n_polyun_t E, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mp_limb_t * betas, slong m, const mpoly_ctx_t mctx, nmod_t mod) { slong i, Ai, Ei; ulong e0, e1, e01; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; n_poly_struct * caches; mp_limb_t * c; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(m > 2); caches = FLINT_ARRAY_ALLOC(3*(m - 2), n_poly_struct); off = FLINT_ARRAY_ALLOC(2*m, slong); shift = off + m; for (i = 0; i < m; i++) { mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, Abits, mctx); if (i >= 2) { n_poly_init(caches + 3*(i - 2) + 0); n_poly_init(caches + 3*(i - 2) + 1); n_poly_init(caches + 3*(i - 2) + 2); nmod_pow_cache_start(betas[i - 2], caches + 3*(i - 2) + 0, caches + 3*(i - 2) + 1, caches + 3*(i - 2) + 2); } } Ai = 0; Ei = 0; e0 = (Aexps[N*Ai + off[0]] >> shift[0]) & mask; e1 = (Aexps[N*Ai + off[1]] >> shift[1]) & mask; e01 = pack_exp2(e0, e1); n_polyun_fit_length(E, Ei + 1); E->exps[Ei] = e01; n_poly_fit_length(E->coeffs + Ei, 1); c = E->coeffs[Ei].coeffs + 0; E->coeffs[Ei].length = 1; Ei++; *c = 1; for (i = 2; i < m; i++) { ulong ei = (Aexps[N*Ai + off[i]] >> shift[i]) & mask; *c = nmod_pow_cache_mulpow_ui(*c, ei, caches + 3*(i - 2) + 0, caches + 3*(i - 2) + 1, caches + 3*(i - 2) + 2, mod); } for (Ai++; Ai < Alen; Ai++) { e0 = (Aexps[N*Ai + off[0]] >> shift[0]) & mask; e1 = (Aexps[N*Ai + off[1]] >> shift[1]) & mask; e01 = pack_exp2(e0, e1); if (e01 == E->exps[Ei - 1]) { slong len = E->coeffs[Ei - 1].length; n_poly_fit_length(E->coeffs + Ei - 1, len + 1); c = E->coeffs[Ei - 1].coeffs + len; E->coeffs[Ei - 1].length = len + 1; } else { n_polyun_fit_length(E, Ei + 1); E->exps[Ei] = e01; n_poly_fit_length(E->coeffs + Ei, 1); c = E->coeffs[Ei].coeffs + 0; E->coeffs[Ei].length = 1; Ei++; } *c = 1; for (i = 2; i < m; i++) { ulong ei = (Aexps[N*Ai + off[i]] >> shift[i]) & mask; *c = nmod_pow_cache_mulpow_ui(*c, ei, caches + 3*(i - 2) + 0, caches + 3*(i - 2) + 1, caches + 3*(i - 2) + 2, mod); } } E->length = Ei; for (i = 0; i < m - 2; i++) { n_poly_clear(caches + 3*i + 0); n_poly_clear(caches + 3*i + 1); n_poly_clear(caches + 3*i + 2); } flint_free(caches); flint_free(off); #if FLINT_WANT_ASSERT Ai = 0; for (i = 0; i < E->length; i++) Ai += E->coeffs[i].length; FLINT_ASSERT(Ai == Alen); #endif } static ulong _nmod_mpoly_bidegree( const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return _mpoly_bidegree(A->exps, A->bits, ctx->minfo); } static ulong _fq_nmod_mpoly_bidegree( const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length > 0); return _mpoly_bidegree(A->exps, A->bits, ctx->minfo); } #define USE_G 1 #define USE_ABAR 2 #define USE_BBAR 4 /* The cost of interpolating gen(m) into G mod (gen(m) - alpha) = sum_i x^e_i*y^f_i c_i(gen(0), ..., gen(m-1)) is (# = length, deg = deg_(gen(m))): (deg G)*(#A + #B + #gamma) eval setup + (deg G)*(max_i #c_i)*(#A + #B + #gamma) zip eval + (deg G)*(max_i #c_i)*(deg_x AB)^2 (deg_y AB)^2 base gcd + (deg G)*(max_i #c_i)*(sum_i # c_i) zip solve + (deg(G))^2*(sum_i #c_i) final interp */ static double interp_cost( double degG, double numABgamma, double maxnumci, double totnumci, double degxAB, double degyAB) { return degG*(degG*totnumci + numABgamma + 0.01*maxnumci*( numABgamma + totnumci + (degxAB*degyAB)*(degxAB*degyAB))); } int mpoly_gcd_get_use_first( slong rGdeg, slong Adeg, slong Bdeg, slong gammadeg) { int use = 0; slong lower = FLINT_MAX(gammadeg, rGdeg); slong upper = gammadeg + FLINT_MIN(FLINT_MIN(Adeg, Bdeg), rGdeg); if (lower <= upper) { slong Gdeg = ((ulong)upper + (ulong)lower)/2; slong Abardeg = gammadeg + Adeg - Gdeg; slong Bbardeg = gammadeg + Bdeg - Gdeg; if (Gdeg <= Abardeg && Gdeg <= Bbardeg) use |= USE_G; if (Abardeg <= Gdeg && Abardeg <= Bbardeg) use |= USE_ABAR; if (Bbardeg <= Gdeg && Bbardeg <= Abardeg) use |= USE_BBAR; } if (use == 0) use = USE_G | USE_ABAR | USE_BBAR; return use; } int nmod_mpoly_gcd_get_use_new( slong rGdeg, slong Adeg, slong Bdeg, slong gammadeg, slong degxAB, slong degyAB, slong numABgamma, const n_polyun_t G, const n_polyun_t Abar, const n_polyun_t Bbar) { int use = 0; slong i, lower = FLINT_MAX(gammadeg, rGdeg); slong upper = gammadeg + FLINT_MIN(FLINT_MIN(Adeg, Bdeg), rGdeg); if (lower <= upper) { slong Gdeg = ((ulong)upper + (ulong)lower)/2; slong maxnumci, totnumci; double Gcost, Abarcost, Bbarcost; maxnumci = totnumci = 0; for (i = 0; i < G->length; i++) { maxnumci = FLINT_MAX(maxnumci, G->coeffs[i].length); totnumci += G->coeffs[i].length; } FLINT_ASSERT(Gdeg >= 0); Gcost = interp_cost(Gdeg, numABgamma, maxnumci, totnumci, degxAB, degyAB); maxnumci = totnumci = 0; for (i = 0; i < Abar->length; i++) { maxnumci = FLINT_MAX(maxnumci, Abar->coeffs[i].length); totnumci += Abar->coeffs[i].length; } FLINT_ASSERT(gammadeg + Adeg - Gdeg >= 0); Abarcost = interp_cost(gammadeg + Adeg - Gdeg, numABgamma, maxnumci, totnumci, degxAB, degyAB); maxnumci = totnumci = 0; for (i = 0; i < Bbar->length; i++) { maxnumci = FLINT_MAX(maxnumci, Bbar->coeffs[i].length); totnumci += Bbar->coeffs[i].length; } FLINT_ASSERT(gammadeg + Bdeg - Gdeg >= 0); Bbarcost = interp_cost(gammadeg + Bdeg - Gdeg, numABgamma, maxnumci, totnumci, degxAB, degyAB); if (Gcost <= FLINT_MIN(Abarcost, Bbarcost)*1.125) use |= USE_G; if (Abarcost <= FLINT_MIN(Gcost, Bbarcost)*1.125) use |= USE_ABAR; if (Bbarcost <= FLINT_MIN(Gcost, Abarcost)*1.125) use |= USE_BBAR; } if (use == 0) use = USE_G | USE_ABAR | USE_BBAR; return use; } mp_limb_t n_poly_mod_eval_step_sep( n_poly_t cur, const n_poly_t inc, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(A->length == cur->length); FLINT_ASSERT(A->length == inc->length); return _nmod_zip_eval_step(cur->coeffs, inc->coeffs, A->coeffs, A->length, ctx->mod); } static void n_fq_poly_eval_step_sep( mp_limb_t * res, n_fq_poly_t cur, const n_fq_poly_t inc, const fq_nmod_mpoly_t A, const fq_nmod_ctx_t ctx) { FLINT_ASSERT(A->length == cur->length); FLINT_ASSERT(A->length == inc->length); _n_fq_zip_eval_step(res, cur->coeffs, inc->coeffs, A->coeffs, A->length, ctx); } void static n_bpoly_mod_eval_step_sep( n_bpoly_t E, n_polyun_t cur, const n_polyun_t inc, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong i, Ai; slong e0, e1; mp_limb_t c; n_bpoly_zero(E); Ai = 0; for (i = 0; i < cur->length; i++) { slong this_len = cur->coeffs[i].length; c = _nmod_zip_eval_step(cur->coeffs[i].coeffs, inc->coeffs[i].coeffs, A->coeffs + Ai, this_len, ctx->mod); Ai += this_len; e0 = extract_exp(cur->exps[i], 1, 2); e1 = extract_exp(cur->exps[i], 0, 2); if (c == 0) continue; n_bpoly_set_coeff_nonzero(E, e0, e1, c); } FLINT_ASSERT(Ai == A->length); } static void nmod_mpoly_monomial_evals( n_poly_t E, const nmod_mpoly_t A, const mp_limb_t * betas, slong start, slong stop, const nmod_mpoly_ctx_t ctx) { _nmod_mpoly_monomial_evals_cache(E, A->exps, A->bits, A->length, betas, start, stop, ctx->minfo, ctx->mod); } static void fq_nmod_mpoly_monomial_evals( n_fq_poly_t E, const fq_nmod_mpoly_t A, const fq_nmod_struct * betas, slong start, slong stop, const fq_nmod_mpoly_ctx_t ctx) { _fq_nmod_mpoly_monomial_evals_cache(E, A->exps, A->bits, A->length, betas, start, stop, ctx); } static void nmod_mpoly_monomial_evals2( n_polyun_t E, const nmod_mpoly_t A, const mp_limb_t * betas, slong m, const nmod_mpoly_ctx_t ctx) { _nmod_mpoly_monomial_evals2_cache(E, A->exps, A->bits, A->length, betas, m, ctx->minfo, ctx->mod); } static void fq_nmod_mpoly_monomial_evals2( n_fq_polyun_t E, const fq_nmod_mpoly_t A, const fq_nmod_struct * betas, slong m, const fq_nmod_mpoly_ctx_t ctx) { _fq_nmod_mpoly_monomial_evals2_cache(E, A->exps, A->bits, A->length, betas, m, ctx); } /* gamma = gcd(lc(A), lc(B)) fake answers G, Abar, Bbar with G*Abar = gamma*A G*Bbar = gamma*B lc(G) = gamma lc(Abar) = lc(A) lc(Bbar) = lc(B) real answers rG = pp(G) rAbar = Abar/lc(rG) rBbar = Bbar/lc(rG) The degrees of A, B, and gamma wrt the minor vars must be passed in. A guess of the degrees of rG wrt the minor vars can be passed in. deg(G) = deg(gamma) - deg(lc(rG)) + deg(rG) deg(G) <= deg(gamma) + deg(rG) deg(G) <= deg(gamma) + deg(A) deg(G) <= deg(gamma) + deg(B) deg(G) >= deg(gamma) deg(G) >= deg(rG) deg(A) = deg(gamma) + deg(A) - deg(G) deg(B) = deg(gamma) + deg(B) - deg(G) */ int nmod_mpolyl_gcd_zippel_smprime( nmod_mpoly_t rG, const slong * rGdegs, /* guess at rG degrees, could be NULL */ nmod_mpoly_t rAbar, nmod_mpoly_t rBbar, const nmod_mpoly_t A, const slong * Adegs, const nmod_mpoly_t B, const slong * Bdegs, const nmod_mpoly_t gamma, const slong * gammadegs, const nmod_mpoly_ctx_t ctx) { int success, use, alpha_tries_left; slong i, m; slong nvars = ctx->minfo->nvars; flint_bitcnt_t bits = A->bits; mp_limb_t * alphas, * betas; flint_rand_t state; nmod_mpoly_t cont; nmod_mpoly_t T, G, Abar, Bbar; n_polyun_t HG, HAbar, HBbar, MG, MAbar, MBbar, ZG, ZAbar, ZBbar; n_bpoly_t Aev, Bev, Gev, Abarev, Bbarev; mp_limb_t gammaev; nmod_mpolyn_t Tn, Gn, Abarn, Bbarn; slong lastdeg; slong cur_zip_image, req_zip_images, this_length; n_polyun_t Aeh_cur, Aeh_inc, Beh_cur, Beh_inc; n_poly_t gammaeh_cur, gammaeh_inc; n_poly_t modulus, alphapow; nmod_mpoly_struct * Aevals, * Bevals; nmod_mpoly_struct * gammaevals; n_poly_bpoly_stack_t St; mp_limb_t c, start_alpha; ulong GdegboundXY, newdegXY, Abideg, Bbideg; slong degxAB, degyAB; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == gamma->bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(gamma->length > 0); nmod_mpoly_fit_length_reset_bits(rG, 1, bits, ctx); nmod_mpoly_fit_length_reset_bits(rAbar, 1, bits, ctx); nmod_mpoly_fit_length_reset_bits(rBbar, 1, bits, ctx); #if FLINT_WANT_ASSERT { slong * tmp_degs = FLINT_ARRAY_ALLOC(nvars, slong); nmod_mpoly_degrees_si(tmp_degs, A, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Adegs[i]); nmod_mpoly_degrees_si(tmp_degs, B, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Bdegs[i]); nmod_mpoly_degrees_si(tmp_degs, gamma, ctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == gammadegs[i]); flint_free(tmp_degs); } #endif FLINT_ASSERT(gammadegs[0] == 0); FLINT_ASSERT(gammadegs[1] == 0); if (ctx->mod.n < 7) return 0; n_polyun_init(HG); n_polyun_init(HAbar); n_polyun_init(HBbar); n_polyun_init(MG); n_polyun_init(MAbar); n_polyun_init(MBbar); n_polyun_init(ZG); n_polyun_init(ZAbar); n_polyun_init(ZBbar); n_bpoly_init(Aev); n_bpoly_init(Bev); n_bpoly_init(Gev); n_bpoly_init(Abarev); n_bpoly_init(Bbarev); n_poly_init2(alphapow, 4); nmod_mpoly_init3(cont, 1, bits, ctx); nmod_mpoly_init3(T, 1, bits, ctx); nmod_mpoly_init3(G, 1, bits, ctx); nmod_mpoly_init3(Abar, 1, bits, ctx); nmod_mpoly_init3(Bbar, 1, bits, ctx); nmod_mpolyn_init(Tn, bits, ctx); nmod_mpolyn_init(Gn, bits, ctx); nmod_mpolyn_init(Abarn, bits, ctx); nmod_mpolyn_init(Bbarn, bits, ctx); n_polyun_init(Aeh_cur); n_polyun_init(Aeh_inc); n_polyun_init(Beh_cur); n_polyun_init(Beh_inc); n_poly_init(gammaeh_cur); n_poly_init(gammaeh_inc); n_poly_init(modulus); n_poly_stack_init(St->poly_stack); n_bpoly_stack_init(St->bpoly_stack); betas = FLINT_ARRAY_ALLOC(nvars, mp_limb_t); alphas = FLINT_ARRAY_ALLOC(nvars, mp_limb_t); flint_randinit(state); Aevals = FLINT_ARRAY_ALLOC(nvars + 1, nmod_mpoly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars + 1, nmod_mpoly_struct); gammaevals = FLINT_ARRAY_ALLOC(nvars + 1, nmod_mpoly_struct); for (i = 0; i < nvars; i++) { nmod_mpoly_init3(Aevals + i, 0, bits, ctx); nmod_mpoly_init3(Bevals + i, 0, bits, ctx); nmod_mpoly_init3(gammaevals + i, 0, bits, ctx); } Aevals[nvars] = *A; Bevals[nvars] = *B; gammaevals[nvars] = *gamma; Abideg = _nmod_mpoly_bidegree(A, ctx); Bbideg = _nmod_mpoly_bidegree(B, ctx); degxAB = FLINT_MAX(Adegs[0], Bdegs[0]); degyAB = FLINT_MAX(Adegs[1], Bdegs[1]); GdegboundXY = pack_exp2(FLINT_MIN(Adegs[0], Bdegs[0]), FLINT_MIN(Adegs[1], Bdegs[1])); if (GdegboundXY == 0) goto gcd_is_trivial; alpha_tries_left = 20; choose_alphas: if (--alpha_tries_left < 0) { success = 0; goto cleanup; } for (i = 2; i < nvars; i++) alphas[i] = n_urandint(state, ctx->mod.n - 2) + 1; for (i = nvars - 1; i >= 2; i--) { nmod_mpoly_evaluate_one_ui(Aevals + i, Aevals + i + 1, i, alphas[i], ctx); nmod_mpoly_repack_bits_inplace(Aevals + i, bits, ctx); nmod_mpoly_evaluate_one_ui(Bevals + i, Bevals + i + 1, i, alphas[i], ctx); nmod_mpoly_repack_bits_inplace(Bevals + i, bits, ctx); nmod_mpoly_evaluate_one_ui(gammaevals + i, gammaevals + i + 1, i, alphas[i], ctx); nmod_mpoly_repack_bits_inplace(gammaevals + i, bits, ctx); if (nmod_mpoly_is_zero(gammaevals + i, ctx)) goto choose_alphas; if (Aevals[i].length < 1 || _nmod_mpoly_bidegree(Aevals + i, ctx) != Abideg) goto choose_alphas; if (Bevals[i].length < 1 || _nmod_mpoly_bidegree(Bevals + i, ctx) != Bbideg) goto choose_alphas; } m = 2; if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = mpoly_gcd_get_use_first(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m]); nmod_mpoly_get_bpoly(Aev, Aevals + m, 0, 1, ctx); nmod_mpoly_get_bpoly(Bev, Bevals + m, 0, 1, ctx); success = n_bpoly_mod_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->mod, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alphas; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; } gammaev = nmod_mpoly_get_ui(gammaevals + m, ctx); n_bpoly_scalar_mul_nmod(Gev, gammaev, ctx->mod); nmod_mpolyn_interp_lift_sm_bpoly(Gn, Gev, ctx); nmod_mpolyn_interp_lift_sm_bpoly(Abarn, Abarev, ctx); nmod_mpolyn_interp_lift_sm_bpoly(Bbarn, Bbarev, ctx); n_poly_one(modulus); c = nmod_neg(alphas[m], ctx->mod); n_poly_mod_shift_left_scalar_addmul(modulus, 1, c, ctx->mod); start_alpha = alphas[m]; while (1) { choose_alpha_2: alphas[m] = (alphas[m] < 2) ? ctx->mod.n - 1 : alphas[m] - 1; if (alphas[m] == start_alpha) goto choose_alphas; FLINT_ASSERT(alphapow->alloc >= 2); alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alphas[m]; alphapow->length = 2; nmod_mpoly_evaluate_one_ui(Aevals + m, Aevals + m + 1, m, alphas[m], ctx); nmod_mpoly_repack_bits_inplace(Aevals + m, bits, ctx); nmod_mpoly_evaluate_one_ui(Bevals + m, Bevals + m + 1, m, alphas[m], ctx); nmod_mpoly_repack_bits_inplace(Bevals + m, bits, ctx); nmod_mpoly_evaluate_one_ui(gammaevals + m, gammaevals + m + 1, m, alphas[m], ctx); nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, ctx); if (nmod_mpoly_is_zero(gammaevals + m, ctx)) goto choose_alpha_2; if (Aevals[m].length < 1 || _nmod_mpoly_bidegree(Aevals + m, ctx) != Abideg) goto choose_alpha_2; if (Bevals[m].length < 1 || _nmod_mpoly_bidegree(Bevals + m, ctx) != Bbideg) goto choose_alpha_2; nmod_mpoly_get_bpoly(Aev, Aevals + m, 0, 1, ctx); nmod_mpoly_get_bpoly(Bev, Bevals + m, 0, 1, ctx); success = n_bpoly_mod_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->mod, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alpha_2; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } gammaev = nmod_mpoly_get_ui(gammaevals + m, ctx); n_bpoly_scalar_mul_nmod(Gev, gammaev, ctx->mod); c = n_poly_mod_eval_pow(modulus, alphapow, ctx->mod); c = nmod_inv(c, ctx->mod); _n_poly_mod_scalar_mul_nmod(modulus, modulus, c, ctx->mod); if ((use & USE_G) && !nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Gn, Tn, Gev, modulus, alphapow, ctx)) { if (m == nvars - 1) { nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx); success = nmod_mpolyl_content(cont, rG, 2, ctx); if (!success) goto cleanup; nmod_mpoly_divides(rG, rG, cont, ctx); nmod_mpoly_repack_bits_inplace(rG, bits, ctx); if (nmod_mpoly_divides(rAbar, A, rG, ctx) && nmod_mpoly_divides(rBbar, B, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { nmod_mpoly_cvtfrom_mpolyn(G, Gn, m, ctx); nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(Abar, T, G, ctx)) { nmod_mpoly_repack_bits_inplace(Abar, bits, ctx); nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(Bbar, T, G, ctx)) { nmod_mpoly_repack_bits_inplace(Bbar, bits, ctx); break; } } } } if ((use & USE_ABAR) && !nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Abarn, Tn, Abarev, modulus, alphapow, ctx)) { if (m == nvars - 1) { nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx); success = nmod_mpolyl_content(cont, rAbar, 2, ctx); if (!success) goto cleanup; nmod_mpoly_divides(rAbar, rAbar, cont, ctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); if (nmod_mpoly_divides(rG, A, rAbar, ctx) && nmod_mpoly_divides(rBbar, B, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { nmod_mpoly_cvtfrom_mpolyn(Abar, Abarn, m, ctx); nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(G, T, Abar, ctx)) { nmod_mpoly_repack_bits_inplace(G, bits, ctx); nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(Bbar, T, G, ctx)) { nmod_mpoly_repack_bits_inplace(Bbar, bits, ctx); break; } } } } if ((use & USE_BBAR) && !nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, Bbarn, Tn, Bbarev, modulus, alphapow, ctx)) { if (m == nvars - 1) { nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx); success = nmod_mpolyl_content(cont, rBbar, 2, ctx); if (!success) goto cleanup; nmod_mpoly_divides(rBbar, rBbar, cont, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); if (nmod_mpoly_divides(rG, B, rBbar, ctx) && nmod_mpoly_divides(rAbar, A, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, ctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); break; } } else { nmod_mpoly_cvtfrom_mpolyn(Bbar, Bbarn, m, ctx); nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(G, T, Bbar, ctx)) { nmod_mpoly_repack_bits_inplace(G, bits, ctx); nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(Abar, T, G, ctx)) { nmod_mpoly_repack_bits_inplace(Abar, bits, ctx); break; } } } } if (n_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } c = nmod_neg(alphas[m], ctx->mod); n_poly_mod_shift_left_scalar_addmul(modulus, 1, c, ctx->mod); } for (m = 3; m < nvars; m++) { /* G, Abar, Bbar are in Fp[gen(0), ..., gen(m - 1)] */ nmod_mpolyn_interp_lift_sm_mpoly(Gn, G, ctx); nmod_mpolyn_interp_lift_sm_mpoly(Abarn, Abar, ctx); nmod_mpolyn_interp_lift_sm_mpoly(Bbarn, Bbar, ctx); if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = 0; n_poly_one(modulus); c = nmod_neg(alphas[m], ctx->mod); n_poly_mod_shift_left_scalar_addmul(modulus, 1, c, ctx->mod); start_alpha = alphas[m]; choose_betas: /* only beta[2], beta[1], ..., beta[m - 1] will be used */ for (i = 2; i < ctx->minfo->nvars; i++) betas[i] = n_urandint(state, ctx->mod.n - 3) + 2; nmod_mpoly_monomial_evals2(HG, G, betas + 2, m, ctx); nmod_mpoly_monomial_evals2(HAbar, Abar, betas + 2, m, ctx); nmod_mpoly_monomial_evals2(HBbar, Bbar, betas + 2, m, ctx); if (use == 0) { this_length = gammaevals[m + 1].length + Aevals[m + 1].length + Bevals[m + 1].length; use = nmod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar); } req_zip_images = 1; if (use & USE_G) { this_length = n_polyun_product_roots(MG, HG, ctx->mod); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_ABAR) { this_length = n_polyun_product_roots(MAbar, HAbar, ctx->mod); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_BBAR) { this_length = n_polyun_product_roots(MBbar, HBbar, ctx->mod); req_zip_images = FLINT_MAX(req_zip_images, this_length); } while (1) { choose_alpha_m: alphas[m] = (alphas[m] < 2) ? ctx->mod.n - 1 : alphas[m] - 1; if (alphas[m] == start_alpha) goto choose_alphas; FLINT_ASSERT(alphapow->alloc >= 2); alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alphas[m]; alphapow->length = 2; nmod_mpoly_evaluate_one_ui(Aevals + m, Aevals + m + 1, m, alphas[m], ctx); nmod_mpoly_repack_bits_inplace(Aevals + m, bits, ctx); nmod_mpoly_evaluate_one_ui(Bevals + m, Bevals + m + 1, m, alphas[m], ctx); nmod_mpoly_repack_bits_inplace(Bevals + m, bits, ctx); nmod_mpoly_evaluate_one_ui(gammaevals + m, gammaevals + m + 1, m, alphas[m], ctx); nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, ctx); if (nmod_mpoly_is_zero(gammaevals + m, ctx)) goto choose_alpha_m; if (Aevals[m].length < 1 || _nmod_mpoly_bidegree(Aevals + m, ctx) != Abideg) goto choose_alpha_m; if (Bevals[m].length < 1 || _nmod_mpoly_bidegree(Bevals + m, ctx) != Bbideg) goto choose_alpha_m; nmod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, betas + 2, m, ctx); nmod_mpoly_monomial_evals2(Beh_inc, Bevals + m, betas + 2, m, ctx); nmod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, betas + 2, 2, m, ctx); n_polyun_set(Aeh_cur, Aeh_inc); n_polyun_set(Beh_cur, Beh_inc); n_poly_set(gammaeh_cur, gammaeh_inc); n_polyun_zip_start(ZG, HG, req_zip_images); n_polyun_zip_start(ZAbar, HAbar, req_zip_images); n_polyun_zip_start(ZBbar, HBbar, req_zip_images); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { n_bpoly_mod_eval_step_sep(Aev, Aeh_cur, Aeh_inc, Aevals + m, ctx); n_bpoly_mod_eval_step_sep(Bev, Beh_cur, Beh_inc, Bevals + m, ctx); gammaev = n_poly_mod_eval_step_sep(gammaeh_cur, gammaeh_inc, gammaevals + m, ctx); if (gammaev == 0) goto choose_betas; if (Aev->length < 1 || n_bpoly_bidegree(Aev) != Abideg) goto choose_betas; if (Bev->length < 1 || n_bpoly_bidegree(Bev) != Bbideg) goto choose_betas; success = n_bpoly_mod_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->mod, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_betas; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } n_bpoly_scalar_mul_nmod(Gev, gammaev, ctx->mod); if ((use & USE_G) && !n_polyu2n_add_zip_must_match(ZG, Gev, cur_zip_image)) goto choose_alphas; if ((use & USE_ABAR) && !n_polyu2n_add_zip_must_match(ZAbar, Abarev, cur_zip_image)) goto choose_alphas; if ((use & USE_BBAR) && !n_polyu2n_add_zip_must_match(ZBbar, Bbarev, cur_zip_image)) goto choose_alphas; } if ((use & USE_G) && n_polyun_zip_solve(G, ZG, HG, MG, ctx) < 1) goto choose_alphas; if ((use & USE_ABAR) && n_polyun_zip_solve(Abar, ZAbar, HAbar, MAbar, ctx) < 1) goto choose_alphas; if ((use & USE_BBAR) && n_polyun_zip_solve(Bbar, ZBbar, HBbar, MBbar, ctx) < 1) goto choose_alphas; FLINT_ASSERT(n_poly_degree(modulus) > 0); c = n_poly_mod_eval_pow(modulus, alphapow, ctx->mod); c = nmod_inv(c, ctx->mod); _n_poly_mod_scalar_mul_nmod(modulus, modulus, c, ctx->mod); if ((use & USE_G) && !nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Gn, G, modulus, alphapow, ctx)) { nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx); if (m == nvars - 1) { success = nmod_mpolyl_content(cont, rG, 2, ctx); if (!success) goto cleanup; nmod_mpoly_divides(rG, rG, cont, ctx); nmod_mpoly_repack_bits_inplace(rG, bits, ctx); if (nmod_mpoly_divides(rAbar, A, rG, ctx) && nmod_mpoly_divides(rBbar, B, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(rAbar, T, rG, ctx)) { nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(rBbar, T, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); nmod_mpoly_swap(G, rG, ctx); nmod_mpoly_swap(Abar, rAbar, ctx); nmod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if ((use & USE_ABAR) && !nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Abarn, Abar, modulus, alphapow, ctx)) { nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx); if (m == nvars - 1) { success = nmod_mpolyl_content(cont, rAbar, 2, ctx); if (!success) goto cleanup; nmod_mpoly_divides(rAbar, rAbar, cont, ctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); if (nmod_mpoly_divides(rG, A, rAbar, ctx) && nmod_mpoly_divides(rBbar, B, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); break; } } else { nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(rG, T, rAbar, ctx)) { nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(rBbar, T, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); nmod_mpoly_swap(G, rG, ctx); nmod_mpoly_swap(Abar, rAbar, ctx); nmod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if ((use & USE_BBAR) && !nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, Bbarn, Bbar, modulus, alphapow, ctx)) { nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx); if (m == nvars - 1) { success = nmod_mpolyl_content(cont, rBbar, 2, ctx); if (!success) goto cleanup; nmod_mpoly_divides(rBbar, rBbar, cont, ctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, ctx); if (nmod_mpoly_divides(rG, B, rBbar, ctx) && nmod_mpoly_divides(rAbar, A, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, ctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); break; } } else { nmod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(rG, T, rBbar, ctx)) { nmod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx); if (nmod_mpoly_divides(rAbar, T, rG, ctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, ctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, ctx); nmod_mpoly_swap(G, rG, ctx); nmod_mpoly_swap(Abar, rAbar, ctx); nmod_mpoly_swap(Bbar, rBbar, ctx); break; } } } } if (n_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } c = nmod_neg(alphas[m], ctx->mod); n_poly_mod_shift_left_scalar_addmul(modulus, 1, c, ctx->mod); } } success = 1; cleanup: n_polyun_clear(HG); n_polyun_clear(HAbar); n_polyun_clear(HBbar); n_polyun_clear(MG); n_polyun_clear(MAbar); n_polyun_clear(MBbar); n_polyun_clear(ZG); n_polyun_clear(ZAbar); n_polyun_clear(ZBbar); n_bpoly_clear(Aev); n_bpoly_clear(Bev); n_bpoly_clear(Gev); n_bpoly_clear(Abarev); n_bpoly_clear(Bbarev); n_poly_clear(alphapow); nmod_mpoly_clear(cont, ctx); nmod_mpoly_clear(T, ctx); nmod_mpoly_clear(G, ctx); nmod_mpoly_clear(Abar, ctx); nmod_mpoly_clear(Bbar, ctx); nmod_mpolyn_clear(Tn, ctx); nmod_mpolyn_clear(Gn, ctx); nmod_mpolyn_clear(Abarn, ctx); nmod_mpolyn_clear(Bbarn, ctx); n_polyun_clear(Aeh_cur); n_polyun_clear(Aeh_inc); n_polyun_clear(Beh_cur); n_polyun_clear(Beh_inc); n_poly_clear(gammaeh_cur); n_poly_clear(gammaeh_inc); n_poly_clear(modulus); n_poly_stack_clear(St->poly_stack); n_bpoly_stack_clear(St->bpoly_stack); flint_free(betas); flint_free(alphas); flint_randclear(state); for (i = 0; i < nvars; i++) { nmod_mpoly_clear(Aevals + i, ctx); nmod_mpoly_clear(Bevals + i, ctx); nmod_mpoly_clear(gammaevals + i, ctx); } flint_free(Aevals); flint_free(Bevals); flint_free(gammaevals); FLINT_ASSERT(!success || rG->bits == bits); FLINT_ASSERT(!success || rAbar->bits == bits); FLINT_ASSERT(!success || rBbar->bits == bits); return success; gcd_is_trivial: nmod_mpoly_one(rG, ctx); nmod_mpoly_set(rAbar, A, ctx); nmod_mpoly_set(rBbar, B, ctx); success = 1; goto cleanup; } int nmod_mpolyl_gcd_zippel_lgprime( nmod_mpoly_t rG, const slong * rGdegs, /* guess at rG degrees, could be NULL */ nmod_mpoly_t rAbar, nmod_mpoly_t rBbar, const nmod_mpoly_t A, const slong * Adegs, const nmod_mpoly_t B, const slong * Bdegs, const nmod_mpoly_t gamma, const slong * gammadegs, const nmod_mpoly_ctx_t smctx) { slong lgd; int success, use; slong i, m; slong nvars = smctx->minfo->nvars; flint_bitcnt_t bits = A->bits; fq_nmod_struct * alphas, * betas; flint_rand_t state; nmod_mpoly_t cont; nmod_mpoly_t T, G, Abar, Bbar; nmod_mpolyn_t Tn, Gn, Abarn, Bbarn; fq_nmod_mpoly_t qT, qG, qAbar, qBbar; fq_nmod_mpoly_t qrG, qrAbar, qrBbar; fq_nmod_mpolyn_t qTn, qGn, qAbarn, qBbarn; n_fq_polyun_t HG, HAbar, HBbar, MG, MAbar, MBbar, ZG, ZAbar, ZBbar; n_fq_bpoly_t Aev, Bev, Gev, Abarev, Bbarev; const mp_limb_t * gammaev; slong lastdeg; slong cur_zip_image, req_zip_images, this_length; n_polyun_t Aeh_cur, Aeh_inc, Beh_cur, Beh_inc; n_fq_poly_t gammaeh_cur, gammaeh_inc; n_fq_poly_t alphapow; fq_nmod_mpoly_struct * Aevals, * Bevals; fq_nmod_mpoly_struct * gammaevals; n_poly_t modulus; n_poly_bpoly_stack_t St; n_poly_t tmp; /* tmp arithmetic space */ fq_nmod_t start_alpha; ulong GdegboundXY, newdegXY, Abideg, Bbideg; slong degxAB, degyAB; fq_nmod_mpoly_ctx_t lgctx; nmod_mpolyn_t gamman; nmod_mpolyn_t An, Bn; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == gamma->bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(gamma->length > 0); nmod_mpoly_fit_length_reset_bits(rG, 1, bits, smctx); nmod_mpoly_fit_length_reset_bits(rAbar, 1, bits, smctx); nmod_mpoly_fit_length_reset_bits(rBbar, 1, bits, smctx); #if FLINT_WANT_ASSERT { slong * tmp_degs = FLINT_ARRAY_ALLOC(nvars, slong); nmod_mpoly_degrees_si(tmp_degs, A, smctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Adegs[i]); nmod_mpoly_degrees_si(tmp_degs, B, smctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == Bdegs[i]); nmod_mpoly_degrees_si(tmp_degs, gamma, smctx); for (i = 0; i < nvars; i++) FLINT_ASSERT(tmp_degs[i] == gammadegs[i]); flint_free(tmp_degs); } #endif FLINT_ASSERT(gammadegs[0] == 0); FLINT_ASSERT(gammadegs[1] == 0); flint_randinit(state); lgd = WORD(20)/(FLINT_BIT_COUNT(smctx->mod.n)); lgd = FLINT_MAX(WORD(2), lgd); fq_nmod_mpoly_ctx_init_deg(lgctx, nvars, ORD_LEX, smctx->mod.n, lgd); n_poly_init2(tmp, lgd); n_poly_init2(alphapow, 2*lgd); fq_nmod_init(start_alpha, lgctx->fqctx); n_fq_polyun_init(HG); n_fq_polyun_init(HAbar); n_fq_polyun_init(HBbar); n_fq_polyun_init(MG); n_fq_polyun_init(MAbar); n_fq_polyun_init(MBbar); n_fq_polyun_init(ZG); n_fq_polyun_init(ZAbar); n_fq_polyun_init(ZBbar); n_fq_bpoly_init(Aev); n_fq_bpoly_init(Bev); n_fq_bpoly_init(Gev); n_fq_bpoly_init(Abarev); n_fq_bpoly_init(Bbarev); nmod_mpoly_init3(cont, 1, bits, smctx); nmod_mpoly_init3(T, 1, bits, smctx); nmod_mpoly_init3(G, 1, bits, smctx); nmod_mpoly_init3(Abar, 1, bits, smctx); nmod_mpoly_init3(Bbar, 1, bits, smctx); nmod_mpolyn_init(Tn, bits, smctx); nmod_mpolyn_init(Gn, bits, smctx); nmod_mpolyn_init(Abarn, bits, smctx); nmod_mpolyn_init(Bbarn, bits, smctx); fq_nmod_mpoly_init3(qT, 1, bits, lgctx); fq_nmod_mpoly_init3(qG, 1, bits, lgctx); fq_nmod_mpoly_init3(qAbar, 1, bits, lgctx); fq_nmod_mpoly_init3(qBbar, 1, bits, lgctx); fq_nmod_mpoly_init3(qrG, 1, bits, lgctx); fq_nmod_mpoly_init3(qrAbar, 1, bits, lgctx); fq_nmod_mpoly_init3(qrBbar, 1, bits, lgctx); fq_nmod_mpolyn_init(qTn, bits, lgctx); fq_nmod_mpolyn_init(qGn, bits, lgctx); fq_nmod_mpolyn_init(qAbarn, bits, lgctx); fq_nmod_mpolyn_init(qBbarn, bits, lgctx); n_fq_polyun_init(Aeh_cur); n_fq_polyun_init(Aeh_inc); n_fq_polyun_init(Beh_cur); n_fq_polyun_init(Beh_inc); n_fq_poly_init(gammaeh_cur); n_fq_poly_init(gammaeh_inc); n_poly_init(modulus); n_poly_stack_init(St->poly_stack); n_bpoly_stack_init(St->bpoly_stack); nmod_mpolyn_init(An, bits, smctx); nmod_mpolyn_init(Bn, bits, smctx); nmod_mpolyn_init(gamman, bits, smctx); /* alphas[nvars - 1] not used - it is replaced lgctx->fqctx->modulus */ alphas = FLINT_ARRAY_ALLOC(2*nvars, fq_nmod_struct); betas = alphas + nvars; for (i = 0; i < nvars; i++) { fq_nmod_init(betas + i, lgctx->fqctx); fq_nmod_init(alphas + i, lgctx->fqctx); } /* Aevals[nvars] does not exist - it is replaced by An */ Aevals = FLINT_ARRAY_ALLOC(nvars, fq_nmod_mpoly_struct); Bevals = FLINT_ARRAY_ALLOC(nvars, fq_nmod_mpoly_struct); gammaevals = FLINT_ARRAY_ALLOC(nvars, fq_nmod_mpoly_struct); for (i = 0; i < nvars; i++) { fq_nmod_mpoly_init3(Aevals + i, 0, bits, lgctx); fq_nmod_mpoly_init3(Bevals + i, 0, bits, lgctx); fq_nmod_mpoly_init3(gammaevals + i, 0, bits, lgctx); } nmod_mpoly_cvtto_mpolyn(An, A, nvars - 1, smctx); nmod_mpoly_cvtto_mpolyn(Bn, B, nvars - 1, smctx); nmod_mpoly_cvtto_mpolyn(gamman, gamma, nvars - 1, smctx); Abideg = _nmod_mpoly_bidegree(A, smctx); Bbideg = _nmod_mpoly_bidegree(B, smctx); degxAB = FLINT_MAX(Adegs[0], Bdegs[0]); degyAB = FLINT_MAX(Adegs[1], Bdegs[1]); GdegboundXY = pack_exp2(FLINT_MIN(Adegs[0], Bdegs[0]), FLINT_MIN(Adegs[1], Bdegs[1])); if (GdegboundXY == 0) goto gcd_is_trivial; goto got_alpha_last; increase_degree: choose_alphas: /* TODO: don't necessarily increase degree here */ lgd++; if (lgd > 10000) { /* ran out of primes */ success = 0; goto cleanup; } fq_nmod_mpoly_ctx_change_modulus(lgctx, lgd); n_poly_fit_length(tmp, lgd); n_poly_fit_length(alphapow, 2*lgd); got_alpha_last: for (i = 2; i < nvars - 1; i++) fq_nmod_rand_not_zero(alphas + i, state, lgctx->fqctx); i = nvars - 1; nmod_mpolyn_interp_reduce_lg_mpoly(Aevals + i, An, lgctx, smctx); nmod_mpolyn_interp_reduce_lg_mpoly(Bevals + i, Bn, lgctx, smctx); nmod_mpolyn_interp_reduce_lg_mpoly(gammaevals + i, gamman, lgctx, smctx); if (fq_nmod_mpoly_is_zero(gammaevals + i, lgctx)) goto choose_alphas; if (Aevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + i, lgctx) != Abideg) goto choose_alphas; if (Bevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + i, lgctx) != Bbideg) goto choose_alphas; for (i--; i >= 2; i--) { fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + i, Aevals + i + 1, i, alphas + i, lgctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + i, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + i, Bevals + i + 1, i, alphas + i, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + i, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + i, gammaevals + i + 1, i, alphas + i, lgctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + i, bits, lgctx); if (fq_nmod_mpoly_is_zero(gammaevals + i, lgctx)) goto choose_alphas; if (Aevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + i, lgctx) != Abideg) goto choose_alphas; if (Bevals[i].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + i, lgctx) != Bbideg) goto choose_alphas; } m = 2; if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = mpoly_gcd_get_use_first(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m]); fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, lgctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, lgctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alphas; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, lgctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, lgctx->fqctx); if (nvars == 3) { nmod_mpolyn_interp_lift_lg_bpoly(&lastdeg, Gn, smctx, Gev, lgctx); nmod_mpolyn_interp_lift_lg_bpoly(&lastdeg, Abarn, smctx, Abarev, lgctx); nmod_mpolyn_interp_lift_lg_bpoly(&lastdeg, Bbarn, smctx, Bbarev, lgctx); n_poly_set_nmod_poly(modulus, lgctx->fqctx->modulus); while (1) { choose_alpha_2_last: lgd++; if (lgd > 10000) { /* ran out of primes */ success = 0; goto cleanup; } fq_nmod_mpoly_ctx_change_modulus(lgctx, lgd); n_poly_fit_length(tmp, lgd); n_poly_fit_length(alphapow, 2*lgd); nmod_mpolyn_interp_reduce_lg_mpoly(Aevals + m, An, lgctx, smctx); nmod_mpolyn_interp_reduce_lg_mpoly(Bevals + m, Bn, lgctx, smctx); nmod_mpolyn_interp_reduce_lg_mpoly(gammaevals + m, gamman, lgctx, smctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_2_last; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_2_last; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_2_last; fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, lgctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, lgctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alpha_2_last; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, lgctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, lgctx->fqctx); if ((use & USE_G) && !nmod_mpolyn_interp_crt_lg_bpoly( &lastdeg, Gn, Tn, modulus, smctx, Gev, lgctx)) { nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, smctx); success = nmod_mpolyl_content(cont, rG, 2, smctx); if (!success) goto cleanup; nmod_mpoly_divides(rG, rG, cont, smctx); nmod_mpoly_repack_bits_inplace(rG, bits, smctx); if (nmod_mpoly_divides(rAbar, A, rG, smctx) && nmod_mpoly_divides(rBbar, B, rG, smctx)) { nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_ABAR) && !nmod_mpolyn_interp_crt_lg_bpoly( &lastdeg, Abarn, Tn, modulus, smctx, Abarev, lgctx)) { nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, smctx); success = nmod_mpolyl_content(cont, rAbar, 2, smctx); if (!success) goto cleanup; nmod_mpoly_divides(rAbar, rAbar, cont, smctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); if (nmod_mpoly_divides(rG, A, rAbar, smctx) && nmod_mpoly_divides(rBbar, B, rG, smctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, smctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_BBAR) && !nmod_mpolyn_interp_crt_lg_bpoly( &lastdeg, Bbarn, Tn, modulus, smctx, Bbarev, lgctx)) { nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, smctx); success = nmod_mpolyl_content(cont, rBbar, 2, smctx); if (!success) goto cleanup; nmod_mpoly_divides(rBbar, rBbar, cont, smctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); if (nmod_mpoly_divides(rG, B, rBbar, smctx) && nmod_mpoly_divides(rAbar, A, rG, smctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, smctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); break; } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } { n_poly_t h_mock; n_poly_mock(h_mock, lgctx->fqctx->modulus); n_poly_mod_mul(modulus, modulus, h_mock, smctx->mod); } } success = 1; goto cleanup; } fq_nmod_mpolyn_interp_lift_sm_bpoly(qGn, Gev, lgctx); fq_nmod_mpolyn_interp_lift_sm_bpoly(qAbarn, Abarev, lgctx); fq_nmod_mpolyn_interp_lift_sm_bpoly(qBbarn, Bbarev, lgctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_one(modulus, lgctx->fqctx); n_fq_set_fq_nmod(tmp->coeffs, alphas + m, lgctx->fqctx); n_fq_poly_shift_left_scalar_submul(modulus, 1, tmp->coeffs, lgctx->fqctx); fq_nmod_set(start_alpha, alphas + m, lgctx->fqctx); while (1) { choose_alpha_2: fq_nmod_next_not_zero(alphas + m, lgctx->fqctx); if (fq_nmod_equal(alphas + m, start_alpha, lgctx->fqctx)) goto increase_degree; FLINT_ASSERT(alphapow->alloc >= lgd*2); alphapow->length = 2; _n_fq_one(alphapow->coeffs + lgd*0, lgd); n_fq_set_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + m, Aevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + m, Bevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + m, gammaevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, lgctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_2; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_2; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_2; fq_nmod_mpoly_get_n_fq_bpoly(Aev, Aevals + m, 0, 1, lgctx); fq_nmod_mpoly_get_n_fq_bpoly(Bev, Bevals + m, 0, 1, lgctx); success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_alpha_2; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } gammaev = fq_nmod_mpoly_get_nonzero_n_fq(gammaevals + m, lgctx); n_fq_bpoly_scalar_mul_n_fq(Gev, gammaev, lgctx->fqctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_pow(tmp->coeffs, modulus, alphapow, lgctx->fqctx); n_fq_inv(tmp->coeffs, tmp->coeffs, lgctx->fqctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, qGn, qTn, Gev, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(qG, qGn, m, lgctx); fq_nmod_mpoly_mul(qT, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qAbar, qT, qG, lgctx)) { fq_nmod_mpoly_mul(qT, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qBbar, qT, qG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(qAbar, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(qBbar, bits, lgctx); break; } } } if ((use & USE_ABAR) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, qAbarn, qTn, Abarev, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(qAbar, qAbarn, m, lgctx); fq_nmod_mpoly_mul(qT, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qG, qT, qAbar, lgctx)) { fq_nmod_mpoly_mul(qT, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qBbar, qT, qG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(qG, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(qBbar, bits, lgctx); break; } } } if ((use & USE_BBAR) && !fq_nmod_mpolyn_interp_crt_sm_bpoly( &lastdeg, qBbarn, qTn, Bbarev, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(qBbar, qBbarn, m, lgctx); fq_nmod_mpoly_mul(qT, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qG, qT, qBbar, lgctx)) { fq_nmod_mpoly_mul(qT, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qAbar, qT, qG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(qG, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(qAbar, bits, lgctx); break; } } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } FLINT_ASSERT(n_fq_equal_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx)); n_fq_poly_shift_left_scalar_submul(modulus, 1, alphapow->coeffs + lgd*1, lgctx->fqctx); } for (m = 3; m < nvars - 1; m++) { /* qG, qAbar, qBbar are in Fq[gen(0), ..., gen(m - 1)] */ fq_nmod_mpolyn_interp_lift_sm_mpoly(qGn, qG, lgctx); fq_nmod_mpolyn_interp_lift_sm_mpoly(qAbarn, qAbar, lgctx); fq_nmod_mpolyn_interp_lift_sm_mpoly(qBbarn, qBbar, lgctx); if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = 0; FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_one(modulus, lgctx->fqctx); n_fq_set_fq_nmod(tmp->coeffs, alphas + m, lgctx->fqctx); n_fq_poly_shift_left_scalar_submul(modulus, 1, tmp->coeffs, lgctx->fqctx); fq_nmod_set(start_alpha, alphas + m, lgctx->fqctx); choose_betas_m: /* only beta[2], beta[1], ..., beta[m - 1] will be used */ for (i = 2; i < nvars; i++) fq_nmod_rand_not_zero(betas + i, state, lgctx->fqctx); FLINT_ASSERT(qG->bits == bits); FLINT_ASSERT(qAbar->bits == bits); FLINT_ASSERT(qBbar->bits == bits); fq_nmod_mpoly_monomial_evals2(HG, qG, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HAbar, qAbar, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HBbar, qBbar, betas + 2, m, lgctx); if (use == 0) { this_length = gammaevals[m + 1].length + Aevals[m + 1].length + Bevals[m + 1].length; use = nmod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar); } req_zip_images = 1; if (use & USE_G) { this_length = n_fq_polyun_product_roots(MG, HG, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_ABAR) { this_length = n_fq_polyun_product_roots(MAbar, HAbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_BBAR) { this_length = n_fq_polyun_product_roots(MBbar, HBbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } while (1) { choose_alpha_m: fq_nmod_next_not_zero(alphas + m, lgctx->fqctx); if (fq_nmod_equal(alphas + m, start_alpha, lgctx->fqctx)) goto increase_degree; FLINT_ASSERT(alphapow->alloc >= lgd*2); alphapow->length = 2; _n_fq_one(alphapow->coeffs + lgd*0, lgd); n_fq_set_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Aevals + m, Aevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Aevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(Bevals + m, Bevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(Bevals + m, bits, lgctx); fq_nmod_mpoly_evaluate_one_fq_nmod(gammaevals + m, gammaevals + m + 1, m, alphas + m, lgctx); fq_nmod_mpoly_repack_bits_inplace(gammaevals + m, bits, lgctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_m; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_m; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_m; fq_nmod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(Beh_inc, Bevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, betas + 2, 2, m, lgctx); n_fq_polyun_set(Aeh_cur, Aeh_inc, lgctx->fqctx); n_fq_polyun_set(Beh_cur, Beh_inc, lgctx->fqctx); n_fq_poly_set(gammaeh_cur, gammaeh_inc, lgctx->fqctx); n_fq_polyun_zip_start(ZG, HG, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZAbar, HAbar, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZBbar, HBbar, req_zip_images, lgctx->fqctx); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { n_fq_bpoly_eval_step_sep(Aev, Aeh_cur, Aeh_inc, Aevals + m, lgctx->fqctx); n_fq_bpoly_eval_step_sep(Bev, Beh_cur, Beh_inc, Bevals + m, lgctx->fqctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_step_sep(tmp->coeffs, gammaeh_cur, gammaeh_inc, gammaevals + m, lgctx->fqctx); if (_n_fq_is_zero(tmp->coeffs, lgd)) goto choose_betas_m; if (Aev->length < 1 || n_bpoly_bidegree(Aev) != Abideg) goto choose_betas_m; if (Bev->length < 1 || n_bpoly_bidegree(Bev) != Bbideg) goto choose_betas_m; success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto increase_degree; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_betas_m; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } n_fq_bpoly_scalar_mul_n_fq(Gev, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !n_fq_polyu2n_add_zip_must_match(ZG, Gev, cur_zip_image, lgctx->fqctx)) goto choose_alphas; if ((use & USE_ABAR) && !n_fq_polyu2n_add_zip_must_match(ZAbar, Abarev, cur_zip_image, lgctx->fqctx)) goto choose_alphas; if ((use & USE_BBAR) && !n_fq_polyu2n_add_zip_must_match(ZBbar, Bbarev, cur_zip_image, lgctx->fqctx)) goto choose_alphas; } if ((use & USE_G) && n_fq_polyun_zip_solve(qG, ZG, HG, MG, lgctx) < 1) goto choose_alphas; if ((use & USE_ABAR) && n_fq_polyun_zip_solve(qAbar, ZAbar, HAbar, MAbar, lgctx) < 1) goto choose_alphas; if ((use & USE_BBAR) && n_fq_polyun_zip_solve(qBbar, ZBbar, HBbar, MBbar, lgctx) < 1) goto choose_alphas; FLINT_ASSERT(n_fq_poly_degree(modulus) > 0); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_pow(tmp->coeffs, modulus, alphapow, lgctx->fqctx); n_fq_inv(tmp->coeffs, tmp->coeffs, lgctx->fqctx); n_fq_poly_scalar_mul_n_fq(modulus, modulus, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, qGn, qG, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(qrG, qGn, m, lgctx); fq_nmod_mpoly_mul(qT, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qrAbar, qT, qrG, lgctx)) { fq_nmod_mpoly_mul(qT, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qrBbar, qT, qrG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(qrAbar, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(qrBbar, bits, lgctx); fq_nmod_mpoly_swap(qG, qrG, lgctx); fq_nmod_mpoly_swap(qAbar, qrAbar, lgctx); fq_nmod_mpoly_swap(qBbar, qrBbar, lgctx); break; } } } if ((use & USE_ABAR) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, qAbarn, qAbar, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(qrAbar, qAbarn, m, lgctx); fq_nmod_mpoly_mul(qT, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qrG, qT, qrAbar, lgctx)) { fq_nmod_mpoly_mul(qT, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qrBbar, qT, qrG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(qrG, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(qrBbar, bits, lgctx); fq_nmod_mpoly_swap(qG, qrG, lgctx); fq_nmod_mpoly_swap(qAbar, qrAbar, lgctx); fq_nmod_mpoly_swap(qBbar, qrBbar, lgctx); break; } } } if ((use & USE_BBAR) && !fq_nmod_mpolyn_interp_mcrt_sm_mpoly( &lastdeg, qBbarn, qBbar, modulus, alphapow, lgctx)) { fq_nmod_mpoly_cvtfrom_mpolyn(qrBbar, qBbarn, m, lgctx); fq_nmod_mpoly_mul(qT, Bevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qrG, qT, qrBbar, lgctx)) { fq_nmod_mpoly_mul(qT, Aevals + m + 1, gammaevals + m + 1, lgctx); if (fq_nmod_mpoly_divides(qrAbar, qT, qrG, lgctx)) { fq_nmod_mpoly_repack_bits_inplace(qrG, bits, lgctx); fq_nmod_mpoly_repack_bits_inplace(qrAbar, bits, lgctx); fq_nmod_mpoly_swap(qG, qrG, lgctx); fq_nmod_mpoly_swap(qAbar, qrAbar, lgctx); fq_nmod_mpoly_swap(qBbar, qrBbar, lgctx); break; } } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } FLINT_ASSERT(n_fq_equal_fq_nmod(alphapow->coeffs + lgd*1, alphas + m, lgctx->fqctx)); n_fq_poly_shift_left_scalar_submul(modulus, 1, alphapow->coeffs + lgd*1, lgctx->fqctx); } } m = nvars - 1; { /* G, Abar, Bbar are in Fq/alpha(gen(m-1))[gen(0), ..., gen(m - 1)] */ nmod_mpolyn_interp_lift_lg_mpoly(Gn, smctx, qG, lgctx); nmod_mpolyn_interp_lift_lg_mpoly(Abarn, smctx, qAbar, lgctx); nmod_mpolyn_interp_lift_lg_mpoly(Bbarn, smctx, qBbar, lgctx); if (rGdegs == NULL) use = USE_G | USE_ABAR | USE_BBAR; else use = 0; n_poly_set_nmod_poly(modulus, lgctx->fqctx->modulus); while (1) { choose_alpha_last: lgd++; if (lgd > 10000) { /* ran out of primes */ success = 0; goto cleanup; } fq_nmod_mpoly_ctx_change_modulus(lgctx, lgd); n_poly_fit_length(tmp, lgd); n_poly_fit_length(alphapow, 2*lgd); nmod_mpolyn_interp_reduce_lg_mpoly(Aevals + m, An, lgctx, smctx); nmod_mpolyn_interp_reduce_lg_mpoly(Bevals + m, Bn, lgctx, smctx); nmod_mpolyn_interp_reduce_lg_mpoly(gammaevals + m, gamman, lgctx, smctx); if (fq_nmod_mpoly_is_zero(gammaevals + m, lgctx)) goto choose_alpha_last; if (Aevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Aevals + m, lgctx) != Abideg) goto choose_alpha_last; if (Bevals[m].length < 1 || _fq_nmod_mpoly_bidegree(Bevals + m, lgctx) != Bbideg) goto choose_alpha_last; choose_betas_last: /* only beta[2], ..., beta[m - 1] will be used */ for (i = 2; i < nvars; i++) fq_nmod_rand_not_zero(betas + i, state, lgctx->fqctx); fq_nmod_mpoly_monomial_evals2(HG, qG, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HAbar, qAbar, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(HBbar, qBbar, betas + 2, m, lgctx); if (use == 0) { this_length = gamma->length + A->length + B->length; use = nmod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar); } req_zip_images = 1; if (use & USE_G) { this_length = n_fq_polyun_product_roots(MG, HG, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_ABAR) { this_length = n_fq_polyun_product_roots(MAbar, HAbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } if (use & USE_BBAR) { this_length = n_fq_polyun_product_roots(MBbar, HBbar, lgctx->fqctx, St->poly_stack); req_zip_images = FLINT_MAX(req_zip_images, this_length); } fq_nmod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals2(Beh_inc, Bevals + m, betas + 2, m, lgctx); fq_nmod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, betas + 2, 2, m, lgctx); n_fq_polyun_set(Aeh_cur, Aeh_inc, lgctx->fqctx); n_fq_polyun_set(Beh_cur, Beh_inc, lgctx->fqctx); n_fq_poly_set(gammaeh_cur, gammaeh_inc, lgctx->fqctx); n_fq_polyun_zip_start(ZG, HG, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZAbar, HAbar, req_zip_images, lgctx->fqctx); n_fq_polyun_zip_start(ZBbar, HBbar, req_zip_images, lgctx->fqctx); for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++) { n_fq_bpoly_eval_step_sep(Aev, Aeh_cur, Aeh_inc, Aevals + m, lgctx->fqctx); n_fq_bpoly_eval_step_sep(Bev, Beh_cur, Beh_inc, Bevals + m, lgctx->fqctx); FLINT_ASSERT(tmp->alloc >= lgd); n_fq_poly_eval_step_sep(tmp->coeffs, gammaeh_cur, gammaeh_inc, gammaevals + m, lgctx->fqctx); if (_n_fq_is_zero(tmp->coeffs, lgd)) goto choose_betas_last; if (Aev->length < 1 || n_bpoly_bidegree(Aev) != Abideg) goto choose_betas_last; if (Bev->length < 1 || n_bpoly_bidegree(Bev) != Bbideg) goto choose_betas_last; success = n_fq_bpoly_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, lgctx->fqctx, St); if (!success) goto cleanup; newdegXY = n_bpoly_bidegree(Gev); if (newdegXY > GdegboundXY) goto choose_betas_last; if (newdegXY < GdegboundXY) { GdegboundXY = newdegXY; if (GdegboundXY == 0) goto gcd_is_trivial; goto choose_alphas; } n_fq_bpoly_scalar_mul_n_fq(Gev, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !n_fq_polyu2n_add_zip_must_match(ZG, Gev, cur_zip_image, lgctx->fqctx)) goto choose_alphas; if ((use & USE_ABAR) && !n_fq_polyu2n_add_zip_must_match(ZAbar, Abarev, cur_zip_image, lgctx->fqctx)) goto choose_alphas; if ((use & USE_BBAR) && !n_fq_polyu2n_add_zip_must_match(ZBbar, Bbarev, cur_zip_image, lgctx->fqctx)) goto choose_alphas; } if ((use & USE_G) && n_fq_polyun_zip_solve(qG, ZG, HG, MG, lgctx) < 1) goto choose_alphas; if ((use & USE_ABAR) && n_fq_polyun_zip_solve(qAbar, ZAbar, HAbar, MAbar, lgctx) < 1) goto choose_alphas; if ((use & USE_BBAR) && n_fq_polyun_zip_solve(qBbar, ZBbar, HBbar, MBbar, lgctx) < 1) goto choose_alphas; FLINT_ASSERT(n_fq_poly_degree(modulus) > 0); n_poly_fit_length(tmp, lgd); _n_fq_set_n_poly(tmp->coeffs, modulus->coeffs, modulus->length, lgctx->fqctx); n_fq_inv(tmp->coeffs, tmp->coeffs, lgctx->fqctx); if ((use & USE_G) && !nmod_mpolyn_interp_mcrt_lg_mpoly( &lastdeg, Gn, smctx, modulus, tmp->coeffs, qG, lgctx)) { nmod_mpoly_cvtfrom_mpolyn(rG, Gn, m, smctx); success = nmod_mpolyl_content(cont, rG, 2, smctx); if (!success) goto cleanup; nmod_mpoly_divides(rG, rG, cont, smctx); nmod_mpoly_repack_bits_inplace(rG, bits, smctx); if (nmod_mpoly_divides(rAbar, A, rG, smctx) && nmod_mpoly_divides(rBbar, B, rG, smctx)) { nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_ABAR) && !nmod_mpolyn_interp_mcrt_lg_mpoly( &lastdeg, Abarn, smctx, modulus, tmp->coeffs, qAbar, lgctx)) { nmod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, smctx); success = nmod_mpolyl_content(cont, rAbar, 2, smctx); if (!success) goto cleanup; nmod_mpoly_divides(rAbar, rAbar, cont, smctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); if (nmod_mpoly_divides(rG, A, rAbar, smctx) && nmod_mpoly_divides(rBbar, B, rG, smctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, smctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); break; } } if ((use & USE_BBAR) && !nmod_mpolyn_interp_mcrt_lg_mpoly( &lastdeg, Bbarn, smctx, modulus, tmp->coeffs, qBbar, lgctx)) { nmod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, smctx); success = nmod_mpolyl_content(cont, rBbar, 2, smctx); if (!success) goto cleanup; nmod_mpoly_divides(rBbar, rBbar, cont, smctx); nmod_mpoly_repack_bits_inplace(rBbar, bits, smctx); if (nmod_mpoly_divides(rG, B, rBbar, smctx) && nmod_mpoly_divides(rAbar, A, rG, smctx)) { nmod_mpoly_repack_bits_inplace(rG, bits, smctx); nmod_mpoly_repack_bits_inplace(rAbar, bits, smctx); break; } } if (n_fq_poly_degree(modulus) > gammadegs[m] + Adegs[m] && n_fq_poly_degree(modulus) > gammadegs[m] + Bdegs[m]) { goto choose_alphas; } { n_poly_t h_mock; n_poly_mock(h_mock, lgctx->fqctx->modulus); n_poly_mod_mul(modulus, modulus, h_mock, smctx->mod); } } } success = 1; cleanup: nmod_mpolyn_clear(An, smctx); nmod_mpolyn_clear(Bn, smctx); nmod_mpolyn_clear(gamman, smctx); n_fq_polyun_clear(HG); n_fq_polyun_clear(HAbar); n_fq_polyun_clear(HBbar); n_fq_polyun_clear(MG); n_fq_polyun_clear(MAbar); n_fq_polyun_clear(MBbar); n_fq_polyun_clear(ZG); n_fq_polyun_clear(ZAbar); n_fq_polyun_clear(ZBbar); n_fq_bpoly_clear(Aev); n_fq_bpoly_clear(Bev); n_fq_bpoly_clear(Gev); n_fq_bpoly_clear(Abarev); n_fq_bpoly_clear(Bbarev); n_fq_poly_clear(alphapow); nmod_mpoly_clear(cont, smctx); nmod_mpoly_clear(T, smctx); nmod_mpoly_clear(G, smctx); nmod_mpoly_clear(Abar, smctx); nmod_mpoly_clear(Bbar, smctx); nmod_mpolyn_clear(Tn, smctx); nmod_mpolyn_clear(Gn, smctx); nmod_mpolyn_clear(Abarn, smctx); nmod_mpolyn_clear(Bbarn, smctx); fq_nmod_mpoly_clear(qT, lgctx); fq_nmod_mpoly_clear(qG, lgctx); fq_nmod_mpoly_clear(qAbar, lgctx); fq_nmod_mpoly_clear(qBbar, lgctx); fq_nmod_mpoly_clear(qrG, lgctx); fq_nmod_mpoly_clear(qrAbar, lgctx); fq_nmod_mpoly_clear(qrBbar, lgctx); fq_nmod_mpolyn_clear(qTn, lgctx); fq_nmod_mpolyn_clear(qGn, lgctx); fq_nmod_mpolyn_clear(qAbarn, lgctx); fq_nmod_mpolyn_clear(qBbarn, lgctx); n_fq_polyun_clear(Aeh_cur); n_fq_polyun_clear(Aeh_inc); n_fq_polyun_clear(Beh_cur); n_fq_polyun_clear(Beh_inc); n_fq_poly_clear(gammaeh_cur); n_fq_poly_clear(gammaeh_inc); n_poly_clear(modulus); n_poly_stack_clear(St->poly_stack); n_bpoly_stack_clear(St->bpoly_stack); fq_nmod_clear(start_alpha, lgctx->fqctx); n_poly_clear(tmp); for (i = 0; i < nvars; i++) { fq_nmod_clear(alphas + i, lgctx->fqctx); fq_nmod_clear(betas + i, lgctx->fqctx); } flint_free(alphas); flint_randclear(state); for (i = 0; i < nvars; i++) { fq_nmod_mpoly_clear(Aevals + i, lgctx); fq_nmod_mpoly_clear(Bevals + i, lgctx); fq_nmod_mpoly_clear(gammaevals + i, lgctx); } flint_free(Aevals); flint_free(Bevals); flint_free(gammaevals); fq_nmod_mpoly_ctx_clear(lgctx); FLINT_ASSERT(!success || rG->bits == bits); FLINT_ASSERT(!success || rAbar->bits == bits); FLINT_ASSERT(!success || rBbar->bits == bits); return success; gcd_is_trivial: nmod_mpoly_one(rG, smctx); nmod_mpoly_set(rAbar, A, smctx); nmod_mpoly_set(rBbar, B, smctx); success = 1; goto cleanup; } /* should find its way back here in interesting cases */ int nmod_mpoly_gcd_zippel2( nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_zero(A, ctx) || nmod_mpoly_is_zero(B, ctx)) return nmod_mpoly_gcd(G, A, B, ctx); return _nmod_mpoly_gcd_algo(G, NULL, NULL, A, B, ctx, MPOLY_GCD_USE_ZIPPEL2); } flint-3.1.3/src/nmod_mpoly/gen.c000066400000000000000000000016231461254215100165160ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_gen(nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits; bits = mpoly_gen_bits_required(var, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(A, 1, bits, ctx); A->coeffs[0] = 1; if (bits <= FLINT_BITS) mpoly_gen_monomial_sp(A->exps, var, bits, ctx->minfo); else mpoly_gen_monomial_offset_mp(A->exps, var, bits, ctx->minfo); _nmod_mpoly_set_length(A, 1, ctx); } flint-3.1.3/src/nmod_mpoly/geobuckets.c000066400000000000000000000101251461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2017-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_geobucket_init(nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { nmod_mpoly_init(B->polys + i, ctx); nmod_mpoly_init(B->temps + i, ctx); } B->length = 0; } void nmod_mpoly_geobucket_clear(nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < FLINT_BITS/2; i++) { nmod_mpoly_clear(B->polys + i, ctx); nmod_mpoly_clear(B->temps + i, ctx); } } /* empty out bucket B into polynomial p */ void nmod_mpoly_geobucket_empty(nmod_mpoly_t p, nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx) { slong i; if (B->length < 2) { if (B->length < 1) nmod_mpoly_zero(p, ctx); else nmod_mpoly_set(p, B->polys + 0, ctx); } else if (B->length == 2) { nmod_mpoly_add(p, B->polys + 1, B->polys + 0, ctx); } else { nmod_mpoly_add(B->temps + 1, B->polys + 1, B->polys + 0, ctx); for (i = 2; i < B->length - 1; i++) nmod_mpoly_add(B->temps + i, B->polys + i, B->temps + i - 1, ctx); nmod_mpoly_add(p, B->polys + i, B->temps + i - 1, ctx); } B->length = 0; } void nmod_mpoly_geobucket_fit_length(nmod_mpoly_geobucket_t B, slong len, const nmod_mpoly_ctx_t ctx) { slong j; for (j = B->length; j < len; j++) nmod_mpoly_zero(B->polys + j, ctx); B->length = j; } /* set bucket B to polynomial p */ void nmod_mpoly_geobucket_set(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx) { slong i = mpoly_geobucket_clog4(p->length); B->length = 0; nmod_mpoly_geobucket_fit_length(B, i + 1, ctx); nmod_mpoly_swap(B->polys + i, p, ctx); B->length = i + 1; } /* internal function for fixing overflows */ void _nmod_mpoly_geobucket_fix(nmod_mpoly_geobucket_t B, slong i, const nmod_mpoly_ctx_t ctx) { while (mpoly_geobucket_clog4((B->polys + i)->length) > i) { FLINT_ASSERT(i + 1 <= B->length); if (i + 1 == B->length) { B->length = i + 2; nmod_mpoly_set(B->polys + i + 1, B->polys + i, ctx); } else { nmod_mpoly_add(B->temps + i + 1, B->polys + i + 1, B->polys + i, ctx); nmod_mpoly_swap(B->polys + i + 1, B->temps + i + 1, ctx); } nmod_mpoly_zero(B->polys + i, ctx); i++; } } /* add polynomial p to bucket B */ void nmod_mpoly_geobucket_add(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx) { slong i; if (nmod_mpoly_is_zero(p, ctx)) return; i = mpoly_geobucket_clog4(p->length); nmod_mpoly_geobucket_fit_length(B, i + 1, ctx); nmod_mpoly_add(B->temps + i, B->polys + i, p, ctx); nmod_mpoly_swap(B->polys + i, B->temps + i, ctx); _nmod_mpoly_geobucket_fix(B, i, ctx); } /* sub polynomial p to buckect B */ void nmod_mpoly_geobucket_sub(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx) { slong i; if (nmod_mpoly_is_zero(p, ctx)) return; i = mpoly_geobucket_clog4(p->length); nmod_mpoly_geobucket_fit_length(B, i + 1, ctx); nmod_mpoly_sub(B->temps + i, B->polys + i, p, ctx); nmod_mpoly_swap(B->polys + i, B->temps + i, ctx); _nmod_mpoly_geobucket_fix(B, i, ctx); } flint-3.1.3/src/nmod_mpoly/get_coeff.c000066400000000000000000000131001461254215100176570ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" ulong nmod_mpoly_get_coeff_ui_fmpz(const nmod_mpoly_t A, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_pfmpz(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { return 0; } else { FLINT_ASSERT(index < A->length); return A->coeffs[index]; } } ulong nmod_mpoly_get_coeff_ui_monomial(const nmod_mpoly_t A, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx) { slong index; if (M->length != WORD(1)) { flint_throw(FLINT_ERROR, "M not monomial in nmod_mpoly_get_coeff_ui_monomial"); } index = mpoly_monomial_index_monomial(A->exps, A->bits, A->length, M->exps, M->bits, ctx->minfo); if (index < 0) { return 0; } else { FLINT_ASSERT(index < A->length); return A->coeffs[index]; } } ulong nmod_mpoly_get_coeff_ui_ui(const nmod_mpoly_t A, const ulong * exp, const nmod_mpoly_ctx_t ctx) { slong index; index = mpoly_monomial_index_ui(A->exps, A->bits, A->length, exp, ctx->minfo); if (index < 0) { return 0; } else { FLINT_ASSERT(index < A->length); return A->coeffs[index]; } } void nmod_mpoly_get_coeff_vars_ui(nmod_mpoly_t C, const nmod_mpoly_t A, const slong * vars, const ulong * exps, slong length, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong i, j; slong offset, shift; slong maxoffset, minoffset; ulong * uexp; ulong * tmask, * texp; slong nvars = ctx->minfo->nvars; mp_limb_t * Ccoeff; ulong * Cexp; slong Clen; TMP_INIT; if (C == A) { nmod_mpoly_t T; nmod_mpoly_init(T, ctx); nmod_mpoly_get_coeff_vars_ui(T, A, vars, exps,length, ctx); nmod_mpoly_swap(T, C, ctx); nmod_mpoly_clear(T, ctx); return; } TMP_START; uexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); for (i = 0; i < nvars; i++) uexp[i] = 0; for (i = 0; i < length; i++) uexp[vars[i]] = exps[i]; if (bits < mpoly_exp_bits_required_ui(uexp, ctx->minfo)) { nmod_mpoly_zero(C, ctx); goto cleanup; } nmod_mpoly_fit_length_reset_bits(C, 4, bits, ctx); tmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); texp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(tmask, N); mpoly_set_monomial_ui(texp, uexp, bits, ctx->minfo); if (bits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { mpoly_gen_offset_shift_sp(&offset, &shift, vars[i], bits, ctx->minfo); tmask[offset] |= mask << shift; maxoffset = FLINT_MAX(maxoffset, offset); minoffset = FLINT_MIN(minoffset, offset); } FLINT_ASSERT(minoffset < N); Ccoeff = C->coeffs; Cexp = C->exps; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_sp; } _nmod_mpoly_fit_length(&Ccoeff, &C->coeffs_alloc, &Cexp, &C->exps_alloc, N, Clen + 1); mpoly_monomial_sub(Cexp + N*Clen, A->exps + N*i, texp, N); Ccoeff[Clen] = A->coeffs[i]; Clen++; continue_outer_sp:; } C->coeffs = Ccoeff; C->exps = Cexp; _nmod_mpoly_set_length(C, Clen, ctx); } else { ulong wpf = A->bits/FLINT_BITS; maxoffset = 0; minoffset = N; for (i = 0; i < length; i++) { offset = mpoly_gen_offset_mp(vars[i], A->bits, ctx->minfo); minoffset = FLINT_MIN(minoffset, offset); maxoffset = FLINT_MAX(maxoffset, offset + wpf - 1); for (j = 0; j < wpf; j++) tmask[offset + j] = -UWORD(1); } FLINT_ASSERT(minoffset < N); Ccoeff = C->coeffs; Cexp = C->exps; Clen = 0; for (i = 0; i < A->length; i++) { for (j = minoffset; j <= maxoffset; j++) { if ((((A->exps + N*i)[j] ^ texp[j]) & tmask[j]) != UWORD(0)) goto continue_outer_mp; } _nmod_mpoly_fit_length(&Ccoeff, &C->coeffs_alloc, &Cexp, &C->exps_alloc, N, Clen + 1); mpoly_monomial_sub_mp(Cexp + N*Clen, A->exps + N*i, texp, N); Ccoeff[Clen] = A->coeffs[i]; Clen++; continue_outer_mp:; } C->coeffs = Ccoeff; C->exps = Cexp; _nmod_mpoly_set_length(C, Clen, ctx); } cleanup: TMP_END; return; } flint-3.1.3/src/nmod_mpoly/get_set_is_nmod_poly.c000066400000000000000000000074011461254215100221520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_is_nmod_poly( const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { return mpoly_is_poly(A->exps, A->length, A->bits, var, ctx->minfo); } int nmod_mpoly_get_nmod_poly( nmod_poly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) { A->mod = ctx->mod; return nmod_mpoly_get_n_poly(evil_cast_nmod_poly_to_n_poly(A), B, var, ctx); } int nmod_mpoly_get_n_poly( n_poly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong Blen = B->length; const mp_limb_t * Bcoeffs = B->coeffs; const ulong * Bexps = B->exps; flint_bitcnt_t Bbits = B->bits; slong i, N = mpoly_words_per_exp(Bbits, ctx->minfo); ulong k; n_poly_zero(A); if (B->length < 1) return 1; if (Bbits <= FLINT_BITS) { ulong mask = (-UWORD(1)) >> (FLINT_BITS - Bbits); slong off, shift; mpoly_gen_offset_shift_sp(&off, &shift, var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = (Bexps[N*i + off] >> shift) & mask; n_poly_set_coeff(A, k, Bcoeffs[i]); } return 1; } else { slong j, off; ulong check, wpf = Bbits/FLINT_BITS; off = mpoly_gen_offset_mp(var, Bbits, ctx->minfo); for (i = 0; i < Blen; i++) { k = Bexps[N*i + off + 0]; check = 0; for (j = 1; j < wpf; j++) check |= Bexps[N*i + off + j]; if (check != 0 || (slong) k < 0) return 0; n_poly_set_coeff(A, k, Bcoeffs[i]); } return 1; } } void _nmod_mpoly_set_nmod_poly( nmod_mpoly_t A, flint_bitcnt_t Abits, const mp_limb_t * Bcoeffs, slong Blen, slong var, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; ulong * genexp; TMP_INIT; TMP_START; genexp = TMP_ARRAY_ALLOC(N, ulong); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += (Bcoeffs[i] != 0); nmod_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { if (Bcoeffs[i] == 0) continue; FLINT_ASSERT(Alen < A->coeffs_alloc); A->coeffs[Alen] = Bcoeffs[i]; if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } void nmod_mpoly_set_n_poly_mod( nmod_mpoly_t A, const n_poly_t B, slong var, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits; if (B->length < 1) { nmod_mpoly_zero(A, ctx); return; } bits = mpoly_gen_pow_exp_bits_required(var, B->length - 1, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); _nmod_mpoly_set_nmod_poly(A, bits, B->coeffs, B->length, var, ctx); } void nmod_mpoly_set_nmod_poly( nmod_mpoly_t A, const nmod_poly_t B, slong var, const nmod_mpoly_ctx_t ctx) { nmod_mpoly_set_n_poly_mod(A, evil_const_cast_nmod_poly_to_n_poly(B), var, ctx); } flint-3.1.3/src/nmod_mpoly/get_str_pretty.c000066400000000000000000000063221461254215100210240ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" #define ALLOC_PER_VAR ((FLINT_BITS+4)/3) static char * _nmod_mpoly_get_str_pretty(const mp_limb_t * coeff, const ulong * exp, slong len, const char ** x_in, slong bits, const mpoly_ctx_t mctx, nmod_t fctx) { char * str, ** x = (char **) x_in, *xtmp; slong i, j, N, bound, off; fmpz * exponents; int first; TMP_INIT; if (len == 0) { str = flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } N = mpoly_words_per_exp(bits, mctx); TMP_START; if (x == NULL) { xtmp = (char *) TMP_ALLOC(mctx->nvars * ALLOC_PER_VAR * sizeof(char)); x = (char **) TMP_ALLOC(mctx->nvars*sizeof(char *)); for (i = 0; i < mctx->nvars; i++) { x[i] = xtmp + i * ALLOC_PER_VAR; flint_sprintf(x[i], "x%wd", i + 1); } } bound = 1 + len * ((FLINT_BIT_COUNT(fctx.n) + 3)/3); exponents = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(ulong)); for (i = 0; i < mctx->nvars; i++) fmpz_init(exponents + i); mpoly_degrees_ffmpz((fmpz *) exponents, exp, len, bits, mctx); for (i = 0; i < mctx->nvars; i++) bound += (fmpz_sizeinbase(exponents + i, 10) + strlen(x[i]) + 3)*len; str = flint_malloc(bound); off = 0; for (i = 0; i < len; i++) { if (i > 0) { str[off++] = '+'; } first = (coeff[i] == 1); if (!first) { off += flint_sprintf(str + off, "%wu", coeff[i]); } mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, mctx); for (j = 0; j < mctx->nvars; j++) { if (fmpz_is_zero(exponents + j)) continue; if (!first) { str[off++] = '*'; } if (fmpz_cmp_ui(exponents + j, UWORD(1)) > 0) { off += flint_sprintf(str + off, "%s^", x[j]); if (!COEFF_IS_MPZ(exponents[j])) off += flint_sprintf(str + off, "%wd", exponents[j]); else off += gmp_sprintf(str + off, "%Zd", COEFF_TO_PTR(exponents[j])); } else { off += flint_sprintf(str + off, "%s", x[j]); } first = 0; } if (first) { off += flint_sprintf(str + off, "1"); } } for (i = 0; i < mctx->nvars; i++) fmpz_clear(exponents + i); TMP_END; return str; } char * nmod_mpoly_get_str_pretty(const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx) { return _nmod_mpoly_get_str_pretty(A->coeffs, A->exps, A->length, x, A->bits, ctx->minfo, ctx->mod); } flint-3.1.3/src/nmod_mpoly/get_term.c000066400000000000000000000016551461254215100175600ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_get_term( nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "nmod_mpoly_get_term: index out of range"); } nmod_mpoly_fit_length_reset_bits(M, 1, bits, ctx); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); M->coeffs[0] = A->coeffs[i]; _nmod_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/nmod_mpoly/get_term_coeff_ui.c000066400000000000000000000013211461254215100214050ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" ulong nmod_mpoly_get_term_coeff_ui(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "index out of range in nmod_mpoly_get_term_coeff_ui"); } return A->coeffs[i]; } flint-3.1.3/src/nmod_mpoly/get_term_exp.c000066400000000000000000000033621461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_get_term_exp_fmpz(fmpz ** exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in nmod_mpoly_get_term_exp_fmpz"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_pfmpz(exp, A->exps + N*i, A->bits, ctx->minfo); } void nmod_mpoly_get_term_exp_si(slong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in nmod_mpoly_get_term_exp_si"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_si(exp, A->exps + N*i, A->bits, ctx->minfo); } void nmod_mpoly_get_term_exp_ui(ulong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in nmod_mpoly_get_term_exp_ui"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_get_monomial_ui(exp, A->exps + N*i, A->bits, ctx->minfo); } flint-3.1.3/src/nmod_mpoly/get_term_monomial.c000066400000000000000000000017161461254215100214510ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_get_term_monomial(nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "nmod_mpoly_get_term_monomial: index out of range"); } nmod_mpoly_fit_length_reset_bits(M, 1, bits, ctx); mpoly_monomial_set(M->exps + N*0, A->exps + N*i, N); M->coeffs[0] = 1; _nmod_mpoly_set_length(M, 1, ctx); } flint-3.1.3/src/nmod_mpoly/get_term_ui_fmpz.c000066400000000000000000000036601461254215100213070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" ulong _nmod_mpoly_get_term_ui_fmpz(const nmod_mpoly_t poly, const fmpz * exp, const nmod_mpoly_ctx_t ctx) { slong N, index, exp_bits; ulong * cmpmask, * packed_exp; int exists; TMP_INIT; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); if (exp_bits > poly->bits) /* exponent too large to be poly exponent */ { return UWORD(0); } TMP_START; N = mpoly_words_per_exp(poly->bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, poly->bits, ctx->minfo); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, poly->bits, ctx->minfo); exists = mpoly_monomial_exists(&index, poly->exps, packed_exp, poly->length, N, cmpmask); TMP_END; if (!exists) return UWORD(0); else return poly->coeffs[index]; } ulong nmod_mpoly_get_term_ui_fmpz(const nmod_mpoly_t poly, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) { ulong ret; slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_init(newexp + i); fmpz_set(newexp + i, exp[i]); } ret = _nmod_mpoly_get_term_ui_fmpz(poly, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; return ret; } flint-3.1.3/src/nmod_mpoly/get_term_ui_ui.c000066400000000000000000000016731461254215100207520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly.h" ulong nmod_mpoly_get_term_ui_ui(const nmod_mpoly_t poly, const ulong * exp, const nmod_mpoly_ctx_t ctx) { ulong ret; slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); ret = _nmod_mpoly_get_term_ui_fmpz(poly, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; return ret; } flint-3.1.3/src/nmod_mpoly/get_term_var_exp.c000066400000000000000000000024351461254215100213010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" slong nmod_mpoly_get_term_var_exp_si(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in nmod_mpoly_get_term_var_exp_si"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_get_monomial_var_exp_si(A->exps + N*i, var, A->bits, ctx->minfo); } ulong nmod_mpoly_get_term_var_exp_ui(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx) { slong N; if ((ulong) i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "Index out of range in nmod_mpoly_get_term_var_exp_ui"); } N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_get_monomial_var_exp_ui(A->exps + N*i, var, A->bits, ctx->minfo); } flint-3.1.3/src/nmod_mpoly/get_ui.c000066400000000000000000000016051461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" ulong nmod_mpoly_get_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong N; if (A->length > WORD(1)) flint_throw(FLINT_ERROR, "Nonconstant polynomial in nmod_mpoly_get_ui"); if (A->length == WORD(0)) { return UWORD(0); } N = mpoly_words_per_exp(A->bits, ctx->minfo); if (!mpoly_monomial_is_zero(A->exps + N*0, N)) flint_throw(FLINT_ERROR, "Nonconstant monomial in nmod_mpoly_get_ui"); return A->coeffs[0]; } flint-3.1.3/src/nmod_mpoly/inflate.c000066400000000000000000000047251461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_inflate( nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz * shift, const fmpz * stride, const nmod_mpoly_ctx_t ctx) { int have_zero_stride; slong j; slong Abits; slong nvars = ctx->minfo->nvars; fmpz * exps; TMP_INIT; if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_zero(A, ctx); return; } TMP_START; exps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exps + j); /* quick and safe bound on bits required */ mpoly_degrees_ffmpz(exps, B->exps, B->length, B->bits, ctx->minfo); have_zero_stride = 0; for (j = 0; j < nvars; j++) { have_zero_stride |= fmpz_is_zero(stride + j); fmpz_mul(exps + j, exps + j, stride + j); fmpz_add(exps + j, exps + j, shift + j); } Abits = mpoly_exp_bits_required_ffmpz(exps, ctx->minfo); Abits = mpoly_fix_bits(Abits, ctx->minfo); for (j = 0; j < nvars; j++) fmpz_clear(exps + j); if (A == B) { slong NA = mpoly_words_per_exp(Abits, ctx->minfo); slong exps_alloc = NA*B->length; ulong * texps = flint_malloc(exps_alloc*sizeof(ulong)); mpoly_monomials_inflate(texps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); flint_free(A->exps); A->exps = texps; A->bits = Abits; A->exps_alloc = exps_alloc; } else { nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, B->length); mpoly_monomials_inflate(A->exps, Abits, B->exps, B->bits, B->length, shift, stride, ctx->minfo); _nmod_mpoly_set_length(A, B->length, ctx); } TMP_END; if (have_zero_stride || ctx->minfo->ord != ORD_LEX) { nmod_mpoly_sort_terms(A, ctx); if (have_zero_stride) nmod_mpoly_combine_like_terms(A, ctx); } return; } flint-3.1.3/src/nmod_mpoly/init.c000066400000000000000000000022411461254215100167050ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_init3( nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(bits, ctx->minfo); if (alloc > 0) { A->coeffs_alloc = alloc; A->coeffs = FLINT_ARRAY_ALLOC(A->coeffs_alloc, mp_limb_t); A->exps_alloc = N*alloc; A->exps = FLINT_ARRAY_ALLOC(A->exps_alloc, ulong); } else { A->coeffs = NULL; A->exps = NULL; A->coeffs_alloc = 0; A->exps_alloc = 0; } A->length = 0; A->bits = bits; } void nmod_mpoly_init2(nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = mpoly_fix_bits(MPOLY_MIN_BITS, ctx->minfo); nmod_mpoly_init3(A, alloc, bits, ctx); } flint-3.1.3/src/nmod_mpoly/inlines.c000066400000000000000000000006621461254215100174100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_MPOLY_INLINES_C #include "nmod_mpoly.h" flint-3.1.3/src/nmod_mpoly/interp.c000066400000000000000000001257611461254215100172600ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" /* interp_reduce: map from Fp[x] to Fp[x]/poly(x) interp_lift: map from Fp[x]/poly(x) to Fp[x] interp_crt: update element of Fp[x] with a new image in Fp[x]/poly(x) interp_mcrt: same as interp_crt, but monomial match, thus easier */ void _nmod_poly_eval2_pow( mp_limb_t * vp, mp_limb_t * vm, n_poly_t P, n_poly_t alphapow, nmod_t fctx) { mp_limb_t * Pcoeffs = P->coeffs; slong Plen = P->length; mp_limb_t * alpha_powers = alphapow->coeffs; mp_limb_t p1, p0, a0, a1, a2, q1, q0, b0, b1, b2; slong k; a0 = a1 = a2 = UWORD(0); b0 = b1 = b2 = UWORD(0); if (Plen > alphapow->length) { slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); n_poly_fit_length(alphapow, Plen); for (k = oldlength; k < Plen; k++) { alphapow->coeffs[k] = nmod_mul(alphapow->coeffs[k - 1], alphapow->coeffs[1], fctx); } alphapow->length = Plen; alpha_powers = alphapow->coeffs; } for (k = 0; k + 2 <= Plen; k += 2) { umul_ppmm(p1, p0, Pcoeffs[k + 0], alpha_powers[k + 0]); umul_ppmm(q1, q0, Pcoeffs[k + 1], alpha_powers[k + 1]); add_sssaaaaaa(a2, a1, a0, a2, a1, a0, WORD(0), p1, p0); add_sssaaaaaa(b2, b1, b0, b2, b1, b0, WORD(0), q1, q0); } if (k < Plen) { umul_ppmm(p1, p0, Pcoeffs[k + 0], alpha_powers[k + 0]); add_sssaaaaaa(a2, a1, a0, a2, a1, a0, WORD(0), p1, p0); k++; } FLINT_ASSERT(k == Plen); NMOD_RED3(p0, a2, a1, a0, fctx); NMOD_RED3(q0, b2, b1, b0, fctx); *vp = nmod_add(p0, q0, fctx); *vm = nmod_sub(p0, q0, fctx); } /*****************************************************************************/ void nmod_mpolyn_interp_reduce_2sm_poly( n_poly_t E, n_poly_t F, const nmod_mpolyn_t A, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx) { mp_limb_t u, v; slong Ai, Alen, k; n_poly_struct * Acoeff; ulong * Aexp; slong N, off, shift; N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); Acoeff = A->coeffs; Aexp = A->exps; Alen = A->length; Ai = 0; n_poly_zero(E); n_poly_zero(F); for (Ai = 0; Ai < Alen; Ai++) { _nmod_poly_eval2_pow(&u, &v, Acoeff + Ai, alphapow, ctx->mod); k = (Aexp + N*Ai)[off] >> shift; n_poly_set_coeff(E, k, u); n_poly_set_coeff(F, k, v); } } void nmod_mpolyn_interp_lift_2sm_poly( slong * lastdeg_, nmod_mpolyn_t F, const n_poly_t A, const n_poly_t B, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { slong lastdeg = -WORD(1); mp_limb_t u, v, d0, d1, Avalue, Bvalue; slong Fi, Aexp, Bexp; mp_limb_t * Acoeff = A->coeffs; mp_limb_t * Bcoeff = B->coeffs; n_poly_struct * Fcoeff; ulong * Fexp; slong e; slong N, off, shift; N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, F->bits, ctx->minfo); Aexp = n_poly_degree(A); Bexp = n_poly_degree(B); nmod_mpolyn_fit_length(F, FLINT_MAX(Aexp, Bexp) + 1, ctx); Fcoeff = F->coeffs; Fexp = F->exps; d0 = n_invmod(UWORD(2), ctx->mod.n); d1 = n_invmod(nmod_add(alpha, alpha, ctx->mod), ctx->mod.n); Fi = 0; while (Aexp >= 0 || Bexp >= 0) { e = Aexp; Avalue = 0; Bvalue = 0; if (Aexp == Bexp) { Avalue = Acoeff[Aexp]; Bvalue = Bcoeff[Bexp]; } else if (Aexp > Bexp) { Avalue = Acoeff[Aexp]; } else { FLINT_ASSERT(Bexp > Aexp); e = Bexp; Bvalue = Bcoeff[Bexp]; } FLINT_ASSERT(Avalue != 0 || Bvalue != 0); u = nmod_add(Avalue, Bvalue, ctx->mod); v = nmod_sub(Avalue, Bvalue, ctx->mod); u = nmod_mul(u, d0, ctx->mod); v = nmod_mul(v, d1, ctx->mod); FLINT_ASSERT(Fi < F->alloc); mpoly_monomial_zero(Fexp + N*Fi, N); (Fexp + N*Fi)[off] = e << shift; FLINT_ASSERT(u != 0 || v != 0); n_poly_fit_length(Fcoeff + Fi, 2); (Fcoeff + Fi)->coeffs[0] = u; (Fcoeff + Fi)->coeffs[1] = v; (Fcoeff + Fi)->length = 1 + (v != 0); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Fcoeff + Fi)); Fi++; if (e == Aexp) { do { Aexp--; } while (Aexp >= 0 && Acoeff[Aexp] == 0); } if (e == Bexp) { do { Bexp--; } while (Bexp >= 0 && Bcoeff[Bexp] == 0); } } F->length = Fi; *lastdeg_ = lastdeg; return; } int nmod_mpolyn_interp_crt_2sm_poly( slong * lastdeg_, nmod_mpolyn_t F, nmod_mpolyn_t T, const n_poly_t A, const n_poly_t B, const n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx) { int changed = 0, Finc; mp_limb_t alpha = n_poly_get_coeff(alphapow, 1); slong lastdeg = -WORD(1); mp_limb_t u, v, FvalueA, FvalueB; slong Fi, Toff, Aexp, Bexp, e, fexp; mp_limb_t * Acoeff = A->coeffs; mp_limb_t * Bcoeff = B->coeffs; slong Flen = F->length; n_poly_struct * Fcoeff = F->coeffs; ulong * Fexp = F->exps; n_poly_struct * Tcoeff; ulong * Texp; slong N, off, shift; FLINT_ASSERT(T->bits == F->bits); N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, F->bits, ctx->minfo); Fi = 0; Aexp = n_poly_degree(A); Bexp = n_poly_degree(B); nmod_mpolyn_fit_length(T, Flen + FLINT_MAX(Aexp, Bexp) + 1, ctx); Tcoeff = T->coeffs; Texp = T->exps; Toff = 0; #if FLINT_WANT_ASSERT u = n_poly_mod_evaluate_nmod(modulus, alpha, ctx->mod); u = nmod_mul(u, alpha, ctx->mod); u = nmod_mul(u, 2, ctx->mod); FLINT_ASSERT(u == 1); u = n_poly_mod_evaluate_nmod(modulus, ctx->mod.n - alpha, ctx->mod); u = nmod_mul(u, alpha, ctx->mod); u = nmod_mul(u, 2, ctx->mod); FLINT_ASSERT(u == 1); #endif while (Fi < Flen || Aexp >= 0 || Bexp >= 0) { FLINT_ASSERT(Toff < T->alloc); fexp = e = -WORD(1); if (Fi < Flen) { fexp = e = (Fexp + N*Fi)[off]>>shift; FLINT_ASSERT(!n_poly_is_zero(Fcoeff + Fi)); FLINT_ASSERT(n_poly_degree(Fcoeff + Fi) < n_poly_degree(modulus)); } if (Aexp >= 0) { e = FLINT_MAX(e, Aexp); FLINT_ASSERT(Acoeff[Aexp] != UWORD(0)); } if (Bexp >= 0) { e = FLINT_MAX(e, Bexp); FLINT_ASSERT(Bcoeff[Bexp] != UWORD(0)); } FLINT_ASSERT(e >= 0); mpoly_monomial_zero(Texp + N*Toff, N); (Texp + N*Toff)[off] = e << shift; FvalueA = FvalueB = 0; Finc = 0; if (Fi < Flen && e == fexp) { Finc = 1; _nmod_poly_eval2_pow(&FvalueA, &FvalueB, Fcoeff + Fi, alphapow, ctx->mod); } if (e == Aexp) { FvalueA = nmod_sub(FvalueA, Acoeff[Aexp], ctx->mod); } if (e == Bexp) { FvalueB = nmod_sub(FvalueB, Bcoeff[Bexp], ctx->mod); } u = nmod_sub(FvalueB, FvalueA, ctx->mod); v = nmod_mul(ctx->mod.n - alpha, nmod_add(FvalueB, FvalueA, ctx->mod), ctx->mod); if (u != 0 || v != 0) { changed = 1; if (u != 0) { _n_poly_mod_scalar_mul_nmod(Tcoeff + Toff, modulus, u, ctx->mod); n_poly_shift_left(Tcoeff + Toff, Tcoeff + Toff, 1); _nmod_vec_scalar_addmul_nmod((Tcoeff + Toff)->coeffs, modulus->coeffs, modulus->length, v, ctx->mod); } else { _n_poly_mod_scalar_mul_nmod(Tcoeff + Toff, modulus, v, ctx->mod); } if (Finc) { n_poly_mod_add(Tcoeff + Toff, Tcoeff + Toff, Fcoeff + Fi, ctx->mod); } } else { FLINT_ASSERT(Finc == 1); n_poly_set(Tcoeff + Toff, Fcoeff + Fi); } FLINT_ASSERT(!n_poly_is_zero(Tcoeff + Toff)); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Tcoeff + Toff)); Toff++; Fi += Finc; if (e == Aexp) { do { Aexp--; } while (Aexp >= 0 && Acoeff[Aexp] == 0); } if (e == Bexp) { do { Bexp--; } while (Bexp >= 0 && Bcoeff[Bexp] == 0); } } T->length = Toff; if (changed) { nmod_mpolyn_swap(T, F); } *lastdeg_ = lastdeg; return changed; } void nmod_mpolyn_interp_lift_sm_bpoly( nmod_mpolyn_t F, n_bpoly_t A, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp_sp(F->bits, ctx->minfo); slong i, j, Fi; slong off0, shift0, off1, shift1; mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo); Fi = 0; for (i = A->length - 1; i >= 0; i--) { n_poly_struct * Ai = A->coeffs + i; for (j = Ai->length - 1; j >= 0; j--) { if (Ai->coeffs[j] == 0) continue; nmod_mpolyn_fit_length(F, Fi + 1, ctx); mpoly_monomial_zero(F->exps + N*Fi, N); (F->exps + N*Fi)[off0] += (i << shift0); (F->exps + N*Fi)[off1] += (j << shift1); n_poly_set_ui(F->coeffs + Fi, Ai->coeffs[j]); Fi++; } } F->length = Fi; } int nmod_mpolyn_interp_crt_sm_bpoly( slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, n_bpoly_t A, n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx) { int changed = 0; int nlimbs = _nmod_vec_dot_bound_limbs(modulus->length, ctx->mod); slong N = mpoly_words_per_exp(F->bits, ctx->minfo); slong off0, shift0, off1, shift1; n_poly_struct * Acoeffs = A->coeffs; slong Fi, Ti, Ai, ai; slong Flen = F->length; ulong * Fexps = F->exps; n_poly_struct * Fcoeffs = F->coeffs; ulong * Texps = T->exps; n_poly_struct * Tcoeffs = T->coeffs; mp_limb_t v; ulong Fexpi, mask; mask = (-UWORD(1)) >> (FLINT_BITS - F->bits); mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo); FLINT_ASSERT(T->bits == F->bits); *lastdeg = -1; Ti = Fi = 0; Ai = A->length - 1; ai = (Ai < 0) ? 0 : n_poly_degree(Acoeffs + Ai); while (Fi < Flen || Ai >= 0) { if (Ti >= T->alloc) { slong extra = Flen - Fi; extra = FLINT_MAX(extra, Ai); nmod_mpolyn_fit_length(T, Ti + extra + 1, ctx); Tcoeffs = T->coeffs; Texps = T->exps; } if (Fi < Flen) Fexpi = pack_exp2(((Fexps + N*Fi)[off0]>>shift0)&mask, ((Fexps + N*Fi)[off1]>>shift1)&mask); else Fexpi = 0; if (Fi < Flen && Ai >= 0 && Fexpi == pack_exp2(Ai, ai)) { /* F term ok, A term ok */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); v = _n_poly_eval_pow(Fcoeffs + Fi, alphapow, nlimbs, ctx->mod); v = nmod_sub(Acoeffs[Ai].coeffs[ai], v, ctx->mod); if (v != 0) { changed = 1; n_poly_mod_scalar_addmul_nmod(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx->mod); } else { n_poly_set(Tcoeffs + Ti, Fcoeffs + Fi); } Fi++; do { ai--; } while (ai >= 0 && Acoeffs[Ai].coeffs[ai] == 0); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_poly_degree(Acoeffs + Ai); } } else if (Ai >= 0 && (Fi >= Flen || Fexpi < pack_exp2(Ai, ai))) { /* F term missing, A term ok */ mpoly_monomial_zero(Texps + N*Ti, N); (Texps + N*Ti)[off0] += (Ai << shift0); (Texps + N*Ti)[off1] += (ai << shift1); changed = 1; _n_poly_mod_scalar_mul_nmod(Tcoeffs + Ti, modulus, Acoeffs[Ai].coeffs[ai], ctx->mod); do { ai--; } while (ai >= 0 && Acoeffs[Ai].coeffs[ai] == 0); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_poly_degree(Acoeffs + Ai); } } else { FLINT_ASSERT(Fi < Flen && (Ai < 0 || Fexpi > pack_exp2(Ai, ai))); /* F term ok, Aterm missing */ mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N); v = _n_poly_eval_pow(Fcoeffs + Fi, alphapow, nlimbs, ctx->mod); if (v != 0) { changed = 1; v = nmod_neg(v, ctx->mod); n_poly_mod_scalar_addmul_nmod(Tcoeffs + Ti, Fcoeffs + Fi, modulus, v, ctx->mod); } else { n_poly_set(Tcoeffs + Ti, Fcoeffs + Fi); } Fi++; } FLINT_ASSERT(!n_poly_is_zero(Tcoeffs + Ti)); *lastdeg = FLINT_MAX(*lastdeg, n_poly_degree(Tcoeffs + Ti)); Ti++; } T->length = Ti; if (changed) nmod_mpolyn_swap(T, F); return changed; } /*****************************************************************************/ /* The following functions are currently undocumented, unused. */ #if 0 /* E = A(x_var = alpha) A is in Fp[x_0, ..., x_(var-2), x_(var-1)][x_var] E is in Fp[x_0, ..., x_(var-2)][x_(var-1)] */ void nmod_mpolyn_interp_reduce_sm_mpolyn( nmod_mpolyn_t E, nmod_mpolyn_t A, slong var, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong offset, shift, k; ulong mask; mp_limb_t v; n_poly_struct * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong Alen = A->length; slong Ai; n_poly_struct * Ecoeff; ulong * Eexp; slong Ei; FLINT_ASSERT(var > 0); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); Ecoeff = E->coeffs; Eexp = E->exps; Ei = 0; for (Ai = 0; Ai < Alen; Ai++) { v = n_poly_mod_evaluate_nmod(Acoeff + Ai, alpha, ctx->mod); k = ((Aexp + N*Ai)[offset] >> shift) & mask; if (v == 0) { continue; } if (Ei > 0 && mpoly_monomial_equal_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ n_poly_set_coeff(Ecoeff + Ei - 1, k, v); } else { FLINT_ASSERT(Ei == 0 || mpoly_monomial_gt_nomask_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Ei >= E->alloc) { nmod_mpolyn_fit_length(E, Ei + 1, ctx); Ecoeff = E->coeffs; Eexp = E->exps; } mpoly_monomial_set_extra(Eexp + N*Ei, Aexp + N*Ai, N, offset, -(k << shift)); n_poly_zero(Ecoeff + Ei); n_poly_set_coeff(Ecoeff + Ei, k, v); Ei++; } } E->length = Ei; } /* A = B A is in Fp[x_0, ..., x_(var-1), x_(var-1)][x_var] B is in Fp[x_0, ..., x_(var-2)][x_(var-1)] */ void nmod_mpolyn_interp_lift_sm_mpolyn( nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); slong offset, shift; slong vi; n_poly_struct * Bcoeff = B->coeffs; ulong * Bexp = B->exps; slong Blen = B->length; slong Bi; n_poly_struct * Acoeff; ulong * Aexp; slong Ai; nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Aexp = A->exps; mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Ai = 0; for (Bi = 0; Bi < Blen; Bi++) { if (Ai + (Bcoeff + Bi)->length >= A->alloc) { nmod_mpolyn_fit_length(A, Ai + (Bcoeff + Bi)->length, ctx); Acoeff = A->coeffs; Aexp = A->exps; } for (vi = (Bcoeff + Bi)->length - 1; vi >= 0; vi--) { if ((Bcoeff + Bi)->coeffs[vi] != 0) { mpoly_monomial_set_extra(Aexp + N*Ai, Bexp + N*Bi, N, offset, vi << shift); n_poly_zero(Acoeff + Ai); n_poly_set_coeff(Acoeff + Ai, 0, (Bcoeff + Bi)->coeffs[vi]); Ai++; } } } A->length = Ai; } /* T = F + modulus*(A - F(x_var = alpha)) no assumptions about matching monomials F is in Fp[x_0, ..., x_(var-1), x_(var-1)][x_var] A is in Fp[x_0, ..., x_(var-2)][x_(var-1)] in order to fxn correctly, modulus(alpha) should be 1 */ int nmod_mpolyn_interp_crt_sm_mpolyn( slong * lastdeg_, nmod_mpolyn_t T, nmod_mpolyn_t F, nmod_mpolyn_t A, slong var, n_poly_t modulus, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { int changed = 0; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong lastdeg = -WORD(1); slong offset, shift; slong vi; mp_limb_t v; n_poly_t tp; n_poly_struct * Tcoeff; ulong * Texp; slong Ti; n_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai; n_poly_struct * Fcoeff = F->coeffs; slong Flen = F->length; ulong * Fexp = F->exps; slong Fi; n_poly_init(tp); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); FLINT_ASSERT(F->bits == A->bits); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Flen = F->length; nmod_mpolyn_fit_length(T, FLINT_MAX(Flen, Alen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = 0; Fi = Ai = vi = 0; if (Ai < Alen) { vi = n_poly_degree(Acoeff + Ai); } while (Fi < Flen || Ai < Alen) { if (Ti >= T->alloc) { nmod_mpolyn_fit_length(T, Ti + FLINT_MAX(Flen - Fi, Alen - Ai), ctx); Tcoeff = T->coeffs; Texp = T->exps; } if (Fi < Flen && Ai < Alen && mpoly_monomial_equal_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift)) { /* F term ok, A term ok */ v = n_poly_mod_evaluate_nmod(Fcoeff + Fi, alpha, ctx->mod); v = nmod_sub((Acoeff + Ai)->coeffs[vi], v, ctx->mod); if (v != UWORD(0)) { changed = 1; _n_poly_mod_scalar_mul_nmod(tp, modulus, v, ctx->mod); n_poly_mod_add(Tcoeff + Ti, Fcoeff + Fi, tp, ctx->mod); } else { n_poly_set(Tcoeff + Ti, Fcoeff + Fi); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; do { vi--; } while (vi >= 0 && (Acoeff + Ai)->coeffs[vi] == 0); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_poly_degree(Acoeff + Ai); } } } else if (Fi < Flen && (Ai >= Alen || mpoly_monomial_gt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))) { /* F term ok, A term missing */ v = n_poly_mod_evaluate_nmod(Fcoeff + Fi, alpha, ctx->mod); if (v != UWORD(0)) { changed = 1; _n_poly_mod_scalar_mul_nmod(tp, modulus, v, ctx->mod); n_poly_mod_sub(Tcoeff + Ti, Fcoeff + Fi, tp, ctx->mod); } else { n_poly_set(Tcoeff + Ti, Fcoeff + Fi); } mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); Fi++; } else { FLINT_ASSERT(Ai < Alen && (Fi >= Flen || mpoly_monomial_lt_nomask_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, vi << shift))); /* F term missing, A term ok */ changed = 1; _n_poly_mod_scalar_mul_nmod(Tcoeff + Ti, modulus, (Acoeff + Ai)->coeffs[vi], ctx->mod); mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, vi << shift); do { vi--; } while (vi >= 0 && (Acoeff + Ai)->coeffs[vi] == 0); if (vi < 0) { Ai++; if (Ai < Alen) { vi = n_poly_degree(Acoeff + Ai); } } } FLINT_ASSERT(!n_poly_is_zero(Tcoeff + Ti)); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Tcoeff + Ti)); Ti++; } T->length = Ti; n_poly_clear(tp); *lastdeg_ = FLINT_MAX(*lastdeg_, lastdeg); return changed; } #endif /****************************************************************************/ void nmod_mpolyn_interp_reduce_2sm_mpolyn( nmod_mpolyn_t E, nmod_mpolyn_t F, nmod_mpolyn_t A, slong var, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong offset, shift, k; ulong mask; mp_limb_t e, f; n_poly_struct * Acoeff = A->coeffs; ulong * Aexp = A->exps; slong Alen = A->length; slong Ai; n_poly_struct * Ecoeff; ulong * Eexp; slong Ei; n_poly_struct * Fcoeff; ulong * Fexp; slong Fi; FLINT_ASSERT(var > 0); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); Ecoeff = E->coeffs; Eexp = E->exps; Ei = 0; Fcoeff = F->coeffs; Fexp = F->exps; Fi = 0; for (Ai = 0; Ai < Alen; Ai++) { _nmod_poly_eval2_pow(&e, &f, Acoeff + Ai, alphapow, ctx->mod); k = ((Aexp + N*Ai)[offset] >> shift) & mask; if (e != 0) { if (Ei > 0 && mpoly_monomial_equal_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ n_poly_set_coeff(Ecoeff + Ei - 1, k, e); } else { FLINT_ASSERT(Ei == 0 || mpoly_monomial_gt_nomask_extra(Eexp + N*(Ei - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Ei >= E->alloc) { nmod_mpolyn_fit_length(E, Ei + 1, ctx); Ecoeff = E->coeffs; Eexp = E->exps; } mpoly_monomial_set_extra(Eexp + N*Ei, Aexp + N*Ai, N, offset, -(k << shift)); n_poly_zero(Ecoeff + Ei); n_poly_set_coeff(Ecoeff + Ei, k, e); Ei++; } } if (f != 0) { if (Fi > 0 && mpoly_monomial_equal_extra(Fexp + N*(Fi - 1), Aexp + N*Ai, N, offset, -(k << shift))) { /* append to previous */ n_poly_set_coeff(Fcoeff + Fi - 1, k, f); } else { FLINT_ASSERT(Fi == 0 || mpoly_monomial_gt_nomask_extra(Fexp + N*(Fi - 1), Aexp + N*Ai, N, offset, -(k << shift))); /* create new */ if (Fi >= F->alloc) { nmod_mpolyn_fit_length(F, Fi + 1, ctx); Fcoeff = F->coeffs; Fexp = F->exps; } mpoly_monomial_set_extra(Fexp + N*Fi, Aexp + N*Ai, N, offset, -(k << shift)); n_poly_zero(Fcoeff + Fi); n_poly_set_coeff(Fcoeff + Fi, k, f); Fi++; } } } E->length = Ei; F->length = Fi; } void nmod_mpolyn_interp_lift_2sm_mpolyn( slong * lastdeg_, nmod_mpolyn_t T, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong lastdeg = -WORD(1); slong offset, shift; n_poly_t tp; n_poly_t zero; n_poly_struct * Tcoeff; ulong * Texp; slong Ti; n_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai, ai; n_poly_struct * Bcoeff = B->coeffs; slong Blen = B->length; ulong * Bexp = B->exps; slong Bi, bi; mp_limb_t u, v, Avalue, Bvalue, FvalueA, FvalueB; int cmp; mp_limb_t d0 = n_invmod(alpha + alpha, ctx->mod.n); n_poly_init(tp); n_poly_init(zero); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); nmod_mpolyn_fit_length(T, FLINT_MAX(Alen, Blen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = Ai = Bi = 0; ai = (Ai >= Alen) ? 0 : n_poly_degree(Acoeff + Ai); bi = (Bi >= Blen) ? 0 : n_poly_degree(Bcoeff + Bi); while (Ai < Alen || Bi < Blen) { if (Ti >= T->alloc) { slong extra = FLINT_MAX(Alen - Ai, Blen - Bi); nmod_mpolyn_fit_length(T, Ti + extra, ctx); Tcoeff = T->coeffs; Texp = T->exps; } FLINT_ASSERT(Ai >= Alen || (Acoeff + Ai)->coeffs[ai] != 0); FLINT_ASSERT(Bi >= Blen || (Bcoeff + Bi)->coeffs[bi] != 0); Avalue = 0; if (Ai < Alen) { Avalue = (Acoeff + Ai)->coeffs[ai]; mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, ai << shift); } Bvalue = 0; if (Bi < Blen) { cmp = (Avalue == 0) ? -1 : mpoly_monomial_cmp_nomask_extra( Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); if (cmp <= 0) { Bvalue = (Bcoeff + Bi)->coeffs[bi]; } if (cmp < 0) { Avalue = 0; mpoly_monomial_set_extra(Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); } } FvalueA = nmod_neg(Avalue, ctx->mod); FvalueB = nmod_neg(Bvalue, ctx->mod); u = nmod_sub(FvalueB, FvalueA, ctx->mod); v = nmod_mul(ctx->mod.n - alpha, nmod_add(FvalueB, FvalueA, ctx->mod), ctx->mod); FLINT_ASSERT(u != 0 || v != 0); n_poly_zero(Tcoeff + Ti); u = nmod_mul(u, d0, ctx->mod); v = nmod_mul(v, d0, ctx->mod); n_poly_set_coeff(Tcoeff + Ti, 0, v); n_poly_set_coeff(Tcoeff + Ti, 1, u); if (Avalue != 0) { do { ai--; } while (ai >= 0 && (Acoeff + Ai)->coeffs[ai] == 0); if (ai < 0) { Ai++; if (Ai < Alen) { ai = n_poly_degree(Acoeff + Ai); } } } if (Bvalue != 0) { do { bi--; } while (bi >= 0 && (Bcoeff + Bi)->coeffs[bi] == 0); if (bi < 0) { Bi++; if (Bi < Blen) { bi = n_poly_degree(Bcoeff + Bi); } } } FLINT_ASSERT(!n_poly_is_zero(Tcoeff + Ti)); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Tcoeff + Ti)); Ti++; } T->length = Ti; FLINT_ASSERT(nmod_mpolyn_is_canonical(T, ctx)); *lastdeg_ = lastdeg; return; } int nmod_mpolyn_interp_crt_2sm_mpolyn( slong * lastdeg_, nmod_mpolyn_t F, nmod_mpolyn_t T, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx) { int changed = 0; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong lastdeg = -WORD(1); slong offset, shift; n_poly_t tp; n_poly_t zero; n_poly_struct * Tcoeff; ulong * Texp; slong Ti; n_poly_struct * Fcoeff = F->coeffs; slong Flen = F->length; ulong * Fexp = F->exps; slong Fi; n_poly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong Ai, ai; n_poly_struct * Bcoeff = B->coeffs; slong Blen = B->length; ulong * Bexp = B->exps; slong Bi, bi; n_poly_struct * Fvalue; mp_limb_t u, v, Avalue, Bvalue, FvalueA, FvalueB; int texp_set, cmp; mp_limb_t alpha = n_poly_get_coeff(alphapow, 1); #if FLINT_WANT_ASSERT u = n_poly_mod_evaluate_nmod(modulus, alpha, ctx->mod); u = nmod_mul(u, alpha, ctx->mod); u = nmod_mul(u, 2, ctx->mod); FLINT_ASSERT(u == 1); u = n_poly_mod_evaluate_nmod(modulus, ctx->mod.n - alpha, ctx->mod); u = nmod_mul(u, alpha, ctx->mod); u = nmod_mul(u, 2, ctx->mod); FLINT_ASSERT(u == 1); #endif FLINT_ASSERT(nmod_mpolyn_is_canonical(A, ctx)); FLINT_ASSERT(nmod_mpolyn_is_canonical(B, ctx)); FLINT_ASSERT(nmod_mpolyn_is_canonical(F, ctx)); n_poly_init(tp); n_poly_init(zero); FLINT_ASSERT(var > 0); FLINT_ASSERT(T->bits == A->bits); FLINT_ASSERT(F->bits == A->bits); FLINT_ASSERT(A->bits <= FLINT_BITS); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, A->bits, ctx->minfo); Flen = F->length; nmod_mpolyn_fit_length(T, FLINT_MAX(Flen, Alen), ctx); Tcoeff = T->coeffs; Texp = T->exps; Ti = Fi = Ai = Bi = 0; ai = (Ai >= Alen) ? 0 : n_poly_degree(Acoeff + Ai); bi = (Bi >= Blen) ? 0 : n_poly_degree(Bcoeff + Bi); while (Fi < Flen || Ai < Alen || Bi < Blen) { if (Ti >= T->alloc) { slong extra = Flen - Fi; extra = FLINT_MAX(extra, Alen - Ai); extra = FLINT_MAX(extra, Blen - Bi); nmod_mpolyn_fit_length(T, Ti + extra, ctx); Tcoeff = T->coeffs; Texp = T->exps; } FLINT_ASSERT(Fi >= Flen || (Fcoeff + Fi)->length != 0); FLINT_ASSERT(Ai >= Alen || (Acoeff + Ai)->coeffs[ai] != 0); FLINT_ASSERT(Bi >= Blen || (Bcoeff + Bi)->coeffs[bi] != 0); Fvalue = zero; texp_set = 0; if (Fi < Flen) { Fvalue = Fcoeff + Fi; texp_set = 1; mpoly_monomial_set(Texp + N*Ti, Fexp + N*Fi, N); } Avalue = 0; if (Ai < Alen) { cmp = (!texp_set) ? -1 : mpoly_monomial_cmp_nomask_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, ai << shift); if (cmp <= 0) { Avalue = (Acoeff + Ai)->coeffs[ai]; } if (cmp < 0) { Fvalue = zero; texp_set = 1; mpoly_monomial_set_extra(Texp + N*Ti, Aexp + N*Ai, N, offset, ai << shift); } } Bvalue = 0; if (Bi < Blen) { cmp = (!texp_set) ? -1 : mpoly_monomial_cmp_nomask_extra( Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); if (cmp <= 0) { Bvalue = (Bcoeff + Bi)->coeffs[bi]; } if (cmp < 0) { Fvalue = zero; Avalue = 0; texp_set = 1; mpoly_monomial_set_extra(Texp + N*Ti, Bexp + N*Bi, N, offset, bi << shift); } } FLINT_ASSERT(texp_set); _nmod_poly_eval2_pow(&FvalueA, &FvalueB, Fvalue, alphapow, ctx->mod); FvalueA = nmod_sub(FvalueA, Avalue, ctx->mod); FvalueB = nmod_sub(FvalueB, Bvalue, ctx->mod); u = nmod_sub(FvalueB, FvalueA, ctx->mod); v = nmod_mul(ctx->mod.n - alpha, nmod_add(FvalueB, FvalueA, ctx->mod), ctx->mod); if (u != 0 || v != 0) { changed = 1; n_poly_set_coeff(tp, 0, v); n_poly_set_coeff(tp, 1, u); n_poly_mod_mul(Tcoeff + Ti, modulus, tp, ctx->mod); n_poly_mod_add(Tcoeff + Ti, Tcoeff + Ti, Fvalue, ctx->mod); } else { FLINT_ASSERT(!n_poly_is_zero(Fvalue)); n_poly_set(Tcoeff + Ti, Fvalue); } Fi += (Fvalue != zero); if (Avalue != 0) { do { ai--; } while (ai >= 0 && (Acoeff + Ai)->coeffs[ai] == 0); if (ai < 0) { Ai++; if (Ai < Alen) { ai = n_poly_degree(Acoeff + Ai); } } } if (Bvalue != 0) { do { bi--; } while (bi >= 0 && (Bcoeff + Bi)->coeffs[bi] == 0); if (bi < 0) { Bi++; if (Bi < Blen) { bi = n_poly_degree(Bcoeff + Bi); } } } FLINT_ASSERT(!n_poly_is_zero(Tcoeff + Ti)); lastdeg = FLINT_MAX(lastdeg, n_poly_degree(Tcoeff + Ti)); Ti++; } T->length = Ti; if (changed) { nmod_mpolyn_swap(T, F); } n_poly_clear(tp); n_poly_clear(zero); FLINT_ASSERT(nmod_mpolyn_is_canonical(F, ctx)); *lastdeg_ = lastdeg; return changed; } /*****************************************************************************/ /* evaluate A at lastvar = alpha */ void nmod_mpolyn_interp_reduce_sm_mpoly( nmod_mpoly_t B, nmod_mpolyn_t A, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { slong i, N, k; FLINT_ASSERT(B->bits == A->bits); nmod_mpoly_fit_length(B, A->length, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); k = 0; for (i = 0; i < A->length; i++) { mpoly_monomial_set(B->exps + N*k, A->exps + N*i, N); B->coeffs[k] = n_poly_mod_evaluate_nmod(A->coeffs + i, alpha, ctx->mod); if (B->coeffs[k] != UWORD(0)) { k++; } } B->length = k; } void nmod_mpolyun_interp_reduce_sm_mpolyu( nmod_mpolyu_t B, nmod_mpolyun_t A, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { slong i, k; FLINT_ASSERT(B->bits == A->bits); nmod_mpolyu_fit_length(B, A->length, ctx); k = 0; for (i = 0; i < A->length; i++) { B->exps[k] = A->exps[i]; nmod_mpolyn_interp_reduce_sm_mpoly(B->coeffs + k, A->coeffs + i, alpha, ctx); k += !nmod_mpoly_is_zero(B->coeffs + k, ctx); } B->length = k; } void nmod_mpolyn_interp_lift_sm_mpoly( nmod_mpolyn_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong i, N; n_poly_struct * Acoeff; mp_limb_t * Bcoeff; ulong * Aexp, * Bexp; slong Blen; FLINT_ASSERT(A->bits == B->bits); Blen = B->length; nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < Blen; i++) { n_poly_zero(Acoeff + i); n_poly_set_coeff(Acoeff + i, 0, Bcoeff[i]); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } A->length = Blen; } void nmod_mpolyun_interp_lift_sm_mpolyu( nmod_mpolyun_t A, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx) { slong i; FLINT_ASSERT(A->bits == B->bits); nmod_mpolyun_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; nmod_mpolyn_interp_lift_sm_mpoly(A->coeffs + i, B->coeffs + i, ctx); FLINT_ASSERT((A->coeffs + i)->bits == B->bits); } A->length = B->length; } /* F = F + modulus*(A - F(alpha)) no assumptions about matching monomials */ int nmod_mpolyn_interp_crt_sm_mpoly( slong * lastdeg, nmod_mpolyn_t F, nmod_mpolyn_t T, nmod_mpoly_t A, n_poly_t modulus, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { int changed = 0; slong i, j, k; slong N; mp_limb_t v; flint_bitcnt_t bits = A->bits; slong Flen = F->length, Alen = A->length; ulong * Fexp = F->exps, * Aexp = A->exps; ulong * Texp; mp_limb_t * Acoeff = A->coeffs; n_poly_struct * Fcoeff = F->coeffs; n_poly_struct * Tcoeff; n_poly_t tp; FLINT_ASSERT(F->bits == bits); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); n_poly_init(tp); nmod_mpolyn_fit_length(T, Flen + Alen, ctx); Texp = T->exps; Tcoeff = T->coeffs; N = mpoly_words_per_exp(bits, ctx->minfo); i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || mpoly_monomial_gt_nomask(Fexp + N*i, Aexp + N*j, N))) { FLINT_ASSERT(!n_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_poly_degree(Fcoeff + i) < n_poly_degree(modulus)); /* F term ok, A term missing */ v = n_poly_mod_evaluate_nmod(Fcoeff + i, alpha, ctx->mod); if (v != UWORD(0)) { changed = 1; _n_poly_mod_scalar_mul_nmod(tp, modulus, v, ctx->mod); n_poly_mod_sub(Tcoeff + k, Fcoeff + i, tp, ctx->mod); } else { n_poly_set(Tcoeff + k, Fcoeff + i); } lastdeg[0] = FLINT_MAX(lastdeg[0], n_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Fexp + N*i, N); FLINT_ASSERT(!n_poly_is_zero(Tcoeff + k)); k++; i++; } else if (j < Alen && (i >= Flen || mpoly_monomial_lt_nomask(Fexp + N*i, Aexp + N*j, N))) { /* F term missing, A term ok */ if (Acoeff[j] != UWORD(0)) { changed = 1; n_poly_zero(Tcoeff + k); _n_poly_mod_scalar_mul_nmod(Tcoeff + k, modulus, Acoeff[j], ctx->mod); lastdeg[0] = FLINT_MAX(lastdeg[0], n_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); k++; } j++; } else if (i < Flen && j < Alen && mpoly_monomial_equal(Fexp + N*i, Aexp + N*j, N)) { FLINT_ASSERT(!n_poly_is_zero(Fcoeff + i)); FLINT_ASSERT(n_poly_degree(Fcoeff + i) < n_poly_degree(modulus)); /* F term ok, A term ok */ v = n_poly_mod_evaluate_nmod(Fcoeff + i, alpha, ctx->mod); v = nmod_sub(Acoeff[j], v, ctx->mod); if (v != UWORD(0)) { changed = 1; _n_poly_mod_scalar_mul_nmod(tp, modulus, v, ctx->mod); n_poly_mod_add(Tcoeff + k, Fcoeff + i, tp, ctx->mod); } else { n_poly_set(Tcoeff + k, Fcoeff + i); } lastdeg[0] = FLINT_MAX(lastdeg[0], n_poly_degree(Tcoeff + k)); mpoly_monomial_set(Texp + N*k, Aexp + N*j, N); FLINT_ASSERT(!n_poly_is_zero(Tcoeff + k)); k++; i++; j++; } else { FLINT_ASSERT(0); } } nmod_mpolyn_set_length(T, k, ctx); if (changed) { nmod_mpolyn_swap(T, F); } n_poly_clear(tp); return changed; } int nmod_mpolyun_interp_crt_sm_mpolyu( slong * lastdeg, nmod_mpolyun_t F, nmod_mpolyun_t T, nmod_mpolyu_t A, n_poly_t modulus, mp_limb_t alpha, const nmod_mpoly_ctx_t ctx) { int changed = 0; slong i, j, k; ulong * Texp; ulong * Fexp; ulong * Aexp; slong Flen; slong Alen; nmod_mpolyn_t S; nmod_mpolyn_struct * Tcoeff; nmod_mpolyn_struct * Fcoeff; nmod_mpoly_struct * Acoeff; nmod_mpoly_t zero; lastdeg[0] = -WORD(1); FLINT_ASSERT(F->bits == T->bits); FLINT_ASSERT(T->bits == A->bits); nmod_mpolyn_init(S, F->bits, ctx); Flen = F->length; Alen = A->length; nmod_mpolyun_fit_length(T, Flen + Alen, ctx); Tcoeff = T->coeffs; Fcoeff = F->coeffs; Acoeff = A->coeffs; Texp = T->exps; Fexp = F->exps; Aexp = A->exps; nmod_mpoly_init3(zero, 0, A->bits, ctx); i = j = k = 0; while (i < Flen || j < Alen) { if (i < Flen && (j >= Alen || Fexp[i] > Aexp[j])) { /* F term ok, A term missing */ nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= nmod_mpolyn_interp_crt_sm_mpoly(lastdeg, Tcoeff + k, S, zero, modulus, alpha, ctx); Texp[k] = Fexp[i]; k++; i++; } else if (j < Alen && (i >= Flen || Aexp[j] > Fexp[i])) { /* F term missing, A term ok */ nmod_mpolyn_zero(Tcoeff + k, ctx); changed |= nmod_mpolyn_interp_crt_sm_mpoly(lastdeg, Tcoeff + k, S, Acoeff + j, modulus, alpha, ctx); Texp[k] = Aexp[j]; k++; j++; } else if (i < Flen && j < Alen && (Fexp[i] == Aexp[j])) { /* F term ok, A term ok */ nmod_mpolyn_set(Tcoeff + k, Fcoeff + i, ctx); changed |= nmod_mpolyn_interp_crt_sm_mpoly(lastdeg, Tcoeff + k, S, Acoeff + j, modulus, alpha, ctx); Texp[k] = Aexp[j]; FLINT_ASSERT(!nmod_mpolyn_is_zero(Tcoeff + k, ctx)); k++; i++; j++; } else { FLINT_ASSERT(0); } } T->length = k; if (changed) { nmod_mpolyun_swap(T, F); } nmod_mpolyn_clear(S, ctx); nmod_mpoly_clear(zero, ctx); return changed; } /* F = F + modulus*(A - F(alpha)) monomials assumed to match */ int nmod_mpolyn_interp_mcrt_sm_mpoly( slong * lastdeg_, nmod_mpolyn_t F, const nmod_mpoly_t A, const n_poly_t modulus, n_poly_t alphapow, const nmod_mpoly_ctx_t ctx) { slong lastdeg = -1; int changed = 0; slong i; mp_limb_t v; mp_limb_t * Acoeff = A->coeffs; slong Flen = F->length; FLINT_ASSERT(Flen == A->length); for (i = 0; i < Flen; i++) { /* F term ok, A term ok */ v = n_poly_mod_eval_pow(F->coeffs + i, alphapow, ctx->mod); v = nmod_sub(Acoeff[i], v, ctx->mod); if (v != 0) { changed = 1; n_poly_mod_scalar_addmul_nmod(F->coeffs + i, F->coeffs + i, modulus, v, ctx->mod); } lastdeg = FLINT_MAX(lastdeg, n_poly_degree(F->coeffs + i)); } *lastdeg_ = lastdeg; return changed; } flint-3.1.3/src/nmod_mpoly/io.c000066400000000000000000000161131461254215100163540ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" /* printing *******************************************************************/ static int _nmod_mpoly_fprint_pretty(FILE * file, const mp_limb_t * coeff, const ulong * exp, slong len, const char ** x_in, slong bits, const mpoly_ctx_t mctx) { slong i, j, N; fmpz * exponents; int r = 0, first; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { r = fputc('0', file); r = (r != EOF) ? 1 : EOF; return r; } N = mpoly_words_per_exp(bits, mctx); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(mctx->nvars*sizeof(char *)); for (i = 0; i < mctx->nvars; i++) { x[i] = (char *) TMP_ALLOC(((FLINT_BITS+4)/3)*sizeof(char)); flint_sprintf(x[i], "x%wd", i + 1); } } exponents = (fmpz *) TMP_ALLOC(mctx->nvars*sizeof(fmpz)); for (i = 0; i < mctx->nvars; i++) fmpz_init(exponents + i); for (i = 0; i < len; i++) { if (i > 0) { r = fputc('+', file); r = (r != EOF) ? 1 : EOF; if (r <= 0) goto done; } first = (coeff[i] == 1); if (!first) { r = flint_fprintf(file, "%wu", coeff[i]); if (r <= 0) goto done; } mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, mctx); for (j = 0; j < mctx->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, WORD(1)); if (cmp < 0) continue; if (!first) { r = fputc('*', file); r = (r != EOF) ? 1 : EOF; if (r <= 0) goto done; } r = flint_fprintf(file, "%s", x[j]); if (r <= 0) goto done; if (cmp > 0) { r = fputc('^', file); if (r <= 0) goto done; r = fmpz_fprint(file, exponents + j); if (r <= 0) goto done; } first = 0; } if (first) { r = flint_fprintf(file, "1"); if (r <= 0) goto done; } } done: for (i = 0; i < mctx->nvars; i++) fmpz_clear(exponents + i); TMP_END; return r; } int nmod_mpoly_fprint_pretty(FILE * file, const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx) { return _nmod_mpoly_fprint_pretty(file, A->coeffs, A->exps, A->length, x, A->bits, ctx->minfo); } int nmod_mpoly_print_pretty(const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_fprint_pretty(stdout, A, x, ctx); } /* debugging ******************************************************************/ /* test that r is a valid remainder upon division by g this means that no monomial of r is divisible by lm(g) */ void nmod_mpoly_remainder_strongtest(const nmod_mpoly_t r, const nmod_mpoly_t g, const nmod_mpoly_ctx_t ctx) { slong i, N, bits; ulong mask = 0; ulong * rexp, * gexp; bits = FLINT_MAX(r->bits, g->bits); N = mpoly_words_per_exp(bits, ctx->minfo); if (g->length == 0 ) flint_throw(FLINT_ERROR, "Zero denominator in remainder test"); if (r->length == 0 ) return; rexp = (ulong *) flint_malloc(N*r->length*sizeof(ulong)); gexp = (ulong *) flint_malloc(N*1 *sizeof(ulong)); mpoly_repack_monomials(rexp, bits, r->exps, r->bits, r->length, ctx->minfo); mpoly_repack_monomials(gexp, bits, g->exps, g->bits, 1, ctx->minfo); if (bits <= FLINT_BITS) mask = mpoly_overflow_mask_sp(bits); else mask = 0; for (i = 0; i < r->length; i++) { int divides; if (bits <= FLINT_BITS) divides = mpoly_monomial_divides_test(rexp + i*N, gexp + 0*N, N, mask); else divides = mpoly_monomial_divides_mp_test(rexp + i*N, gexp + 0*N, N, bits); if (divides) { flint_throw(FLINT_ERROR, "nmod_mpoly_remainder_strongtest FAILED i = %wd\n" "rem %s\n\n" "den %s\n\n", i, nmod_mpoly_get_str_pretty(r, NULL, ctx), nmod_mpoly_get_str_pretty(g, NULL, ctx)); } } flint_free(rexp); flint_free(gexp); } void nmod_mpolyd_print(nmod_mpolyd_t poly) { int first = 0; slong i, j; slong degb_prod; degb_prod = WORD(1); for (j = 0; j < poly->nvars; j++) { degb_prod *= poly->deg_bounds[j]; } first = 1; for (i = 0; i < degb_prod; i++) { ulong k = i; if (poly->coeffs[i] == 0) continue; if (!first) printf(" + "); flint_printf("%wu", poly->coeffs[i]); for (j = poly->nvars - 1; j >= 0; j--) { ulong m = poly->deg_bounds[j]; ulong e = k % m; k = k / m; flint_printf("*x%wd^%wu", j, e); } FLINT_ASSERT(k == 0); first = 0; } if (first) flint_printf("0"); } void nmod_mpolyn_print_pretty(const nmod_mpolyn_t A, const char ** x_in, const nmod_mpoly_ctx_t ctx) { n_poly_struct * coeff = A->coeffs; slong len = A->length; ulong * exp = A->exps; slong bits = A->bits; slong i, j, N; fmpz * exponents; char ** x = (char **) x_in; TMP_INIT; if (len == 0) { flint_printf("0"); return; } N = mpoly_words_per_exp(bits, ctx->minfo); TMP_START; if (x == NULL) { x = (char **) TMP_ALLOC(ctx->minfo->nvars*sizeof(char *)); for (i = 0; i < ctx->minfo->nvars; i++) { x[i] = (char *) TMP_ALLOC(((FLINT_BITS+4)/3)*sizeof(char)); flint_sprintf(x[i], "x%wd", i+1); } } exponents = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(exponents + i); for (i = 0; i < len; i++) { if (i > 0) { printf(" + "); } printf("("); n_poly_print_pretty(coeff + i, "v"); printf(")"); mpoly_get_monomial_ffmpz(exponents, exp + N*i, bits, ctx->minfo); for (j = 0; j < ctx->minfo->nvars; j++) { int cmp = fmpz_cmp_ui(exponents + j, WORD(1)); if (cmp > 0) { printf("*%s^", x[j]); fmpz_print(exponents + j); } else if (cmp == 0) { printf("*%s", x[j]); } } } for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(exponents + i); TMP_END; } flint-3.1.3/src/nmod_mpoly/is_canonical.c000066400000000000000000000034461461254215100203740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_is_canonical(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { if (A->coeffs[i] == UWORD(0)) return 0; if (A->coeffs[i] >= ctx->mod.n) return 0; } return 1; } void nmod_mpoly_assert_canonical(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents out of order"); for (i = 0; i < A->length; i++) { if (A->coeffs[i] == UWORD(0)) flint_throw(FLINT_ERROR, "Polynomial has a zero coefficient"); if (A->coeffs[i] >= ctx->mod.n) flint_throw(FLINT_ERROR, "Polynomial coefficient is out of range"); } } flint-3.1.3/src/nmod_mpoly/is_gen.c000066400000000000000000000013121461254215100172040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_is_gen(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { if (A->length != WORD(1)) return 0; if (A->coeffs[0] != UWORD(1)) return 0; return mpoly_is_gen(A->exps, var, A->bits, ctx->minfo); } flint-3.1.3/src/nmod_mpoly/is_ui.c000066400000000000000000000013111461254215100170470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_is_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong N; if (A->length > WORD(1)) return 0; if (A->length == WORD(0)) return 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } flint-3.1.3/src/nmod_mpoly/lead_coeff_vars.c000066400000000000000000000036101461254215100210450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" /* leading coefficient wrt gen(0), ..., gen(num_vars-1) c will be returned with c->bits == A->bits */ void nmod_mpolyl_lead_coeff( nmod_mpoly_t c, const nmod_mpoly_t A, slong num_vars, const nmod_mpoly_ctx_t ctx) { slong i, j, off, shift; ulong mask, first_mask; slong N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); ulong * Aexps = A->exps; ulong * cexps; slong Alen = A->length; FLINT_ASSERT(c != A); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 < num_vars && num_vars < ctx->minfo->nvars); mpoly_gen_offset_shift_sp(&off, &shift, num_vars - 1, A->bits, ctx->minfo); mask = (-UWORD(1)) << shift; i = 0; first_mask = (Aexps + N*i)[off] & mask; for (i = 1; i < Alen; i++) { if (((Aexps + N*i)[off] & mask) != first_mask) goto break_outer; for (j = off + 1; j < N; j++) if ((Aexps + N*(i - 1))[j] != (Aexps + N*i)[j]) goto break_outer; } break_outer: nmod_mpoly_fit_length_reset_bits(c, i, A->bits, ctx); c->length = i; cexps = c->exps; _nmod_vec_set(c->coeffs, A->coeffs, c->length); mask = ~mask; for (i = 0; i < c->length; i++) { for (j = 0; j < off; j++) (cexps + N*i)[j] = (Aexps + N*i)[j]; (cexps + N*i)[off] = mask & (Aexps + N*i)[off]; for (j = off + 1; j < N; j++) (cexps + N*i)[j] = 0; } } flint-3.1.3/src/nmod_mpoly/make_monic.c000066400000000000000000000014671461254215100200550ustar00rootroot00000000000000/* Copyright (C) 2017, 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mpoly.h" void nmod_mpoly_make_monic(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (B->length == 0) { flint_throw(FLINT_ERROR, "nmod_mpoly_make_monic: polynomial is zero."); } nmod_mpoly_scalar_mul_nmod_invertible(A, B, nmod_inv(B->coeffs[0], ctx->mod), ctx); } flint-3.1.3/src/nmod_mpoly/mpolyd.c000066400000000000000000000224661461254215100172610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" void nmod_mpolyd_ctx_init(nmod_mpolyd_ctx_t dctx, slong nvars) { slong i; dctx->nvars = nvars; dctx->perm = (slong *) flint_malloc(nvars*sizeof(slong)); for (i = 0; i < nvars; i++) { dctx->perm[i] = i; } } void nmod_mpolyd_ctx_clear(nmod_mpolyd_ctx_t dctx) { flint_free(dctx->perm); } void nmod_mpolyd_init(nmod_mpolyd_t poly, slong nvars) { slong i; poly->nvars = nvars; poly->degb_alloc = nvars; poly->deg_bounds = (slong *) flint_malloc(poly->degb_alloc*sizeof(slong)); for (i = 0; i < nvars; i++) { poly->deg_bounds[i] = WORD(1); } poly->coeff_alloc = WORD(16); poly->coeffs = (mp_limb_t *) flint_malloc(poly->coeff_alloc*sizeof(mp_limb_t)); for (i = 0; i < poly->coeff_alloc; i++) { poly->coeffs[i] = UWORD(0); } } void nmod_mpolyd_fit_length(nmod_mpolyd_t poly, slong len) { if (poly->coeff_alloc < len) { /*flint_printf("realloc %wd -> %wd\n",poly->coeff_alloc, len);*/ poly->coeffs = (mp_limb_t *) flint_realloc(poly->coeffs, len*sizeof(mp_limb_t)); poly->coeff_alloc = len; } } void nmod_mpolyd_set_nvars(nmod_mpolyd_t poly, slong nvars) { poly->nvars = nvars; if (poly->degb_alloc < nvars) { poly->deg_bounds = (slong *) flint_realloc(poly->deg_bounds, nvars*sizeof(slong)); poly->degb_alloc = nvars; } } void nmod_mpolyd_zero(nmod_mpolyd_t poly) { slong i; for (i = 0; i < poly->nvars; i++) { poly->deg_bounds[i] = WORD(1); } poly->coeffs[0] = UWORD(0); } void nmod_mpolyd_clear(nmod_mpolyd_t poly) { flint_free(poly->deg_bounds); flint_free(poly->coeffs); poly->deg_bounds = NULL; poly->coeffs = NULL; } int nmod_mpolyd_set_degbounds(nmod_mpolyd_t A, slong * bounds) { slong i; int success = 0; slong degb_prod; degb_prod = 1; for (i = 0; i < A->nvars; i++) { ulong hi; A->deg_bounds[i] = bounds[i]; umul_ppmm(hi, degb_prod, degb_prod, A->deg_bounds[i]); if (hi != WORD(0) || degb_prod < 0) { goto done; } } success = 1; nmod_mpolyd_fit_length(A, degb_prod); done: return success; } int nmod_mpolyd_set_degbounds_perm(nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, slong * bounds) { slong i; int success = 0; const slong * perm = dctx->perm; slong degb_prod; degb_prod = 1; for (i = 0; i < A->nvars; i++) { ulong hi; A->deg_bounds[i] = bounds[perm[i]]; umul_ppmm(hi, degb_prod, degb_prod, A->deg_bounds[i]); if (hi != WORD(0) || degb_prod < 0) { goto done; } } success = 1; nmod_mpolyd_fit_length(A, degb_prod); done: return success; } /* convert B to A assuming degree bounds have been set in A */ void nmod_mpoly_convert_to_nmod_mpolyd_degbound(nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong degb_prod; slong i, j, N; ulong * exps; const slong * perm = dctx->perm; slong nvars = ctx->minfo->nvars; TMP_INIT; FLINT_ASSERT(A->nvars == nvars); FLINT_ASSERT(B->bits <= FLINT_BITS); degb_prod = WORD(1); for (i = 0; i < nvars; i++) { degb_prod *= A->deg_bounds[i]; } for (i = 0; i < degb_prod; i++) { A->coeffs[i] = UWORD(0); } TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < B->length; i++) { slong off; mpoly_get_monomial_ui(exps, B->exps + N*i, B->bits, ctx->minfo); off = 0; for (j = 0; j < nvars; j++) { off = exps[perm[j]] + A->deg_bounds[j]*off; } A->coeffs[off] = B->coeffs[i]; } TMP_END; } /* convert B to A - sets degree bounds in A */ void nmod_mpoly_convert_to_nmod_mpolyd( nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong degb_prod; slong i, j, N; slong * exps; const slong * perm = dctx->perm; slong nvars = ctx->minfo->nvars; TMP_INIT; nmod_mpolyd_set_nvars(A, ctx->minfo->nvars); FLINT_ASSERT(B->bits <= FLINT_BITS); if (B->length == 0) { nmod_mpolyd_zero(A); return; } TMP_START; exps = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); nmod_mpoly_degrees_si(exps, B, ctx); degb_prod = WORD(1); for (i = 0; i < nvars; i++) { A->deg_bounds[i] = exps[perm[i]] + 1; degb_prod *= A->deg_bounds[i]; } nmod_mpolyd_fit_length(A, degb_prod); for (i = 0; i < degb_prod; i++) { A->coeffs[i] = UWORD(0); } N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < B->length; i++) { slong off = 0; mpoly_get_monomial_ui((ulong *)exps, B->exps + N*i, B->bits, ctx->minfo); for (j = 0; j < nvars; j++) { off = exps[perm[j]] + A->deg_bounds[j]*off; } A->coeffs[off] = B->coeffs[i]; } TMP_END; } /* Convert B to A */ void nmod_mpoly_convert_from_nmod_mpolyd( nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, const nmod_mpolyd_t B, const nmod_mpolyd_ctx_t dctx) { slong off, j, k, N; slong bits, nvars = ctx->minfo->nvars; slong Alen; slong * perm = dctx->perm; slong perm_nontrivial = 0; ulong topmask; ulong * exps, * pcurexp, * pexps; TMP_INIT; FLINT_ASSERT(nvars == B->nvars); TMP_START; exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); /* find bits needed for the result */ off = 1; for (j = 0; j < nvars; j++) { off *= B->deg_bounds[j]; exps[perm[j]] = B->deg_bounds[j] - 1; perm_nontrivial |= j ^ perm[j]; } FLINT_ASSERT(off <= B->coeff_alloc); bits = mpoly_exp_bits_required_ui(exps, ctx->minfo); bits = mpoly_fix_bits(bits, ctx->minfo); N = mpoly_words_per_exp(bits, ctx->minfo); /* we are going to push back terms manually */ nmod_mpoly_fit_length_reset_bits(A, 0, bits, ctx); Alen = 0; /* find exponent vector for all variables */ pexps = (ulong *) TMP_ALLOC(N*nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) { for (j = 0; j < nvars; j++) exps[perm[j]] = (j == k); mpoly_set_monomial_ui(pexps + k*N, exps, bits, ctx->minfo); } /* get most significant exponent in exps and its vector in ptempexp */ off--; pcurexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(pcurexp, N); k = off; for (j = nvars - 1; j >= 0; j--) { exps[j] = k % B->deg_bounds[j]; k = k / B->deg_bounds[j]; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } /* scan down through the exponents */ topmask = 0; for (; off >= 0; off--) { if (B->coeffs[off] != UWORD(0)) { _nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, Alen + 1); A->coeffs[Alen] = B->coeffs[off]; mpoly_monomial_set(A->exps + N*Alen, pcurexp, N); topmask |= (A->exps + N*Alen)[N - 1]; Alen++; } j = nvars - 1; do { --exps[j]; if ((slong)(exps[j]) < WORD(0)) { FLINT_ASSERT(off == 0 || j > 0); FLINT_ASSERT(exps[j] == -UWORD(1)); exps[j] = B->deg_bounds[j] - 1; mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N); } else { mpoly_monomial_sub_mp(pcurexp, pcurexp, pexps + N*j, N); break; } } while (--j >= 0); } _nmod_mpoly_set_length(A, Alen, ctx); /* sort the exponents if needed */ if (ctx->minfo->ord != ORD_LEX || perm_nontrivial != WORD(0)) { slong msb; mpoly_get_cmpmask(pcurexp, N, bits, ctx->minfo); if (topmask != WORD(0)) { msb = flint_clz(topmask); msb = (FLINT_BITS - 1)^msb; } else { msb = -WORD(1); } if (N == 1) { if (msb >= WORD(0)) { _nmod_mpoly_radix_sort1(A, 0, A->length, msb, pcurexp[0], topmask); } } else { _nmod_mpoly_radix_sort(A, 0, A->length, (N - 1)*FLINT_BITS + msb, N, pcurexp); } } TMP_END; } slong nmod_mpolyd_length(const nmod_mpolyd_t A) { slong i, j, degb_prod; degb_prod = WORD(1); for (j = 0; j < A->nvars; j++) degb_prod *= A->deg_bounds[j]; for (i = degb_prod; i > 0; i--) { if (A->coeffs[i - 1] != UWORD(0)) break; } return i; } flint-3.1.3/src/nmod_mpoly/mpolyn.c000066400000000000000000000122101461254215100172550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpolyn_init(nmod_mpolyn_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void nmod_mpolyn_clear(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) n_poly_clear(A->coeffs + i); flint_free(A->coeffs); flint_free(A->exps); } void nmod_mpolyn_swap(nmod_mpolyn_t A, nmod_mpolyn_t B) { nmod_mpolyn_struct t = *A; *A = *B; *B = t; } void nmod_mpolyn_zero(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) { n_poly_clear(A->coeffs + i); n_poly_init(A->coeffs + i); } A->length = 0; } int nmod_mpolyn_is_zero(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { return A->length == 0; } void nmod_mpolyn_fit_length(nmod_mpolyn_t A, slong length, const nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (old_alloc == 0) { A->exps = (ulong *) flint_malloc(new_alloc*N*sizeof(ulong)); A->coeffs = (n_poly_struct *) flint_malloc(new_alloc*sizeof(n_poly_struct)); } else { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*N*sizeof(ulong)); A->coeffs = (n_poly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(n_poly_struct)); } for (i = old_alloc; i < new_alloc; i++) { n_poly_init(A->coeffs + i); } A->alloc = new_alloc; } } void nmod_mpolyn_set_length(nmod_mpolyn_t A, slong newlen, const nmod_mpoly_ctx_t ctx) { if (A->length > newlen) { slong i; for (i = newlen; i < A->length; i++) { n_poly_clear(A->coeffs + i); n_poly_init(A->coeffs + i); } } A->length = newlen; } void nmod_mpolyn_fit_bits(nmod_mpolyn_t A, slong bits, const nmod_mpoly_ctx_t ctx) { slong N; ulong * t; if (A->bits < bits) { if (A->alloc != 0) { N = mpoly_words_per_exp(bits, ctx->minfo); t = flint_malloc(N*A->alloc*sizeof(ulong)); mpoly_repack_monomials(t, bits, A->exps, A->bits, A->length, ctx->minfo); flint_free(A->exps); A->exps = t; } A->bits = bits; } } int nmod_mpolyn_is_canonical(const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { slong i; if (!mpoly_monomials_valid_test(A->exps, A->length, A->bits, ctx->minfo)) { return 0; } if (mpoly_monomials_overflow_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; if (!mpoly_monomials_inorder_test(A->exps, A->length, A->bits, ctx->minfo)) return 0; for (i = 0; i < A->length; i++) { slong l = (A->coeffs + i)->length; if (l == 0) { return 0; } if ((A->coeffs + i)->coeffs[l - 1] == 0) { return 0; } } return 1; } void nmod_mpolyn_set(nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx) { slong i; n_poly_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; slong Blen; slong N; nmod_mpolyn_fit_bits(A, B->bits, ctx); A->bits = B->bits; Blen = B->length; nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < Blen; i++) { n_poly_set(Acoeff + i, Bcoeff + i); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } /* demote remaining coefficients */ for (i = Blen; i < A->length; i++) { n_poly_clear(Acoeff + i); n_poly_init(Acoeff + i); } A->length = Blen; } void nmod_mpolyn_mul_poly( nmod_mpolyn_t A, const nmod_mpolyn_t B, const n_poly_t c, const nmod_mpoly_ctx_t ctx) { slong i; n_poly_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; slong Blen; slong N; nmod_mpolyn_fit_bits(A, B->bits, ctx); A->bits = B->bits; Blen = B->length; nmod_mpolyn_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; N = mpoly_words_per_exp(B->bits, ctx->minfo); FLINT_ASSERT(!n_poly_is_zero(c)); for (i = 0; i < Blen; i++) { n_poly_mod_mul(Acoeff + i, Bcoeff + i, c, ctx->mod); mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N); } /* demote remaining coefficients */ for (i = Blen; i < A->length; i++) { n_poly_clear(Acoeff + i); n_poly_init(Acoeff + i); } A->length = Blen; } flint-3.1.3/src/nmod_mpoly/mpolyn_divides_threaded.c000066400000000000000000001454621461254215100226440ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" #if FLINT_KNOW_STRONG_ORDER #include "thread_pool.h" #include "n_poly.h" #include "mpoly.h" #include "fmpz_mpoly.h" typedef struct _nmod_mpolyn_stripe_struct { char * big_mem; slong big_mem_alloc; slong N; flint_bitcnt_t bits; const ulong * cmpmask; slong * startidx; slong * endidx; ulong * emin; ulong * emax; int upperclosed; const nmod_mpoly_ctx_struct * ctx; } nmod_mpolyn_stripe_struct; typedef nmod_mpolyn_stripe_struct nmod_mpolyn_stripe_t[1]; static void stripe_fit_length(nmod_mpolyn_stripe_struct * S, slong new_len) { slong N = S->N; slong new_alloc; new_alloc = 0; if (N == 1) { new_alloc += new_len*sizeof(slong); new_alloc += new_len*sizeof(slong); new_alloc += 2*new_len*sizeof(slong); new_alloc += (new_len + 1)*sizeof(mpoly_heap1_s); new_alloc += new_len*sizeof(mpoly_heap_t); } else { new_alloc += new_len*sizeof(slong); new_alloc += new_len*sizeof(slong); new_alloc += 2*new_len*sizeof(slong); new_alloc += (new_len + 1)*sizeof(mpoly_heap_s); new_alloc += new_len*sizeof(mpoly_heap_t); new_alloc += new_len*N*sizeof(ulong); new_alloc += new_len*sizeof(ulong *); new_alloc += N*sizeof(ulong); } if (S->big_mem_alloc >= new_alloc) { return; } new_alloc = FLINT_MAX(new_alloc, S->big_mem_alloc + S->big_mem_alloc/4); S->big_mem_alloc = new_alloc; if (S->big_mem != NULL) { S->big_mem = (char *) flint_realloc(S->big_mem, new_alloc); } else { S->big_mem = (char *) flint_malloc(new_alloc); } } /* a thread safe mpolyn supports three mutating operations - init from an array of terms - append an array of terms - clear out contents to a normal mpoly */ typedef struct _nmod_mpolyn_ts_struct { n_poly_struct * volatile coeffs; /* this is coeff_array[idx] */ ulong * volatile exps; /* this is exp_array[idx] */ volatile slong length; slong alloc; flint_bitcnt_t bits; flint_bitcnt_t idx; ulong * exp_array[FLINT_BITS]; n_poly_struct * coeff_array[FLINT_BITS]; } nmod_mpolyn_ts_struct; typedef nmod_mpolyn_ts_struct nmod_mpolyn_ts_t[1]; /* Bcoeff is changed */ static void nmod_mpolyn_ts_init(nmod_mpolyn_ts_t A, n_poly_struct * Bcoeff, ulong * Bexp, slong Blen, flint_bitcnt_t bits, slong N, const nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t idx = FLINT_BIT_COUNT(Blen); idx = (idx <= 8) ? 0 : idx - 8; for (i = 0; i < FLINT_BITS; i++) { A->exp_array[i] = NULL; A->coeff_array[i] = NULL; } A->bits = bits; A->idx = idx; A->alloc = WORD(256) << idx; A->exps = A->exp_array[idx] = (ulong *) flint_malloc(N*A->alloc*sizeof(ulong)); A->coeffs = A->coeff_array[idx] = (n_poly_struct *) flint_malloc(A->alloc*sizeof(n_poly_struct)); for (i = 0; i < A->alloc; i++) { n_poly_init(A->coeffs + i); } A->length = Blen; for (i = 0; i < Blen; i++) { n_poly_swap(A->coeffs + i, Bcoeff + i); mpoly_monomial_set(A->exps + N*i, Bexp + N*i, N); } } static void nmod_mpolyn_ts_clear(nmod_mpolyn_ts_t A) { slong i; for (i = 0; i < A->length; i++) { n_poly_clear(A->coeffs + i); } for (i = 0; i < FLINT_BITS; i++) { if (A->exp_array[i] != NULL) { FLINT_ASSERT(A->coeff_array[i] != NULL); flint_free(A->coeff_array[i]); flint_free(A->exp_array[i]); } } } static void nmod_mpolyn_ts_clear_poly(nmod_mpolyn_t Q, nmod_mpolyn_ts_t A) { if (Q->alloc != 0) { slong i; FLINT_ASSERT(Q->exps != NULL); FLINT_ASSERT(Q->coeffs != NULL); for (i = 0; i < Q->alloc; i++) { n_poly_clear(Q->coeffs + i); } flint_free(Q->exps); flint_free(Q->coeffs); } Q->exps = A->exps; Q->coeffs = A->coeffs; Q->bits = A->bits; Q->alloc = A->alloc; Q->length = A->length; A->length = 0; A->coeff_array[A->idx] = NULL; A->exp_array[A->idx] = NULL; nmod_mpolyn_ts_clear(A); } /* put B on the end of A - Bcoeff is changed*/ static void nmod_mpolyn_ts_append(nmod_mpolyn_ts_t A, n_poly_struct * Bcoeff, ulong * Bexps, slong Blen, slong N, const nmod_mpoly_ctx_t ctx) { /* TODO: this needs barriers on non-x86 */ slong i; ulong * oldexps = A->exps; n_poly_struct * oldcoeffs = A->coeffs; slong oldlength = A->length; slong newlength = A->length + Blen; if (newlength <= A->alloc) { /* write new terms first */ for (i = 0; i < Blen; i++) { n_poly_swap(oldcoeffs + oldlength + i, Bcoeff + i); mpoly_monomial_set(oldexps + N*(oldlength + i), Bexps + N*i, N); } } else { slong newalloc; ulong * newexps; n_poly_struct * newcoeffs; flint_bitcnt_t newidx; newidx = FLINT_BIT_COUNT(newlength - 1); newidx = (newidx > 8) ? newidx - 8 : 0; FLINT_ASSERT(newidx > A->idx); newalloc = UWORD(256) << newidx; FLINT_ASSERT(newlength <= newalloc); newexps = A->exp_array[newidx] = (ulong *) flint_malloc(N*newalloc*sizeof(ulong)); newcoeffs = A->coeff_array[newidx] = (n_poly_struct *) flint_malloc(newalloc*sizeof(n_poly_struct)); for (i = 0; i < newalloc; i++) { n_poly_init(newcoeffs + i); } for (i = 0; i < oldlength; i++) { newcoeffs[i] = oldcoeffs[i]; /* just copy the bits */ mpoly_monomial_set(newexps + N*i, oldexps + N*i, N); } for (i = 0; i < Blen; i++) { n_poly_swap(newcoeffs + oldlength + i, Bcoeff + i); mpoly_monomial_set(newexps + N*(oldlength + i), Bexps + N*i, N); } A->alloc = newalloc; A->exps = newexps; A->coeffs = newcoeffs; A->idx = newidx; /* do not free oldcoeff/exps as other threads may be using them */ } /* update length at the very end */ A->length = newlength; } /* a chunk holds an exponent range on the dividend */ typedef struct _divides_heap_chunk_struct { nmod_mpolyn_t polyC; struct _divides_heap_chunk_struct * next; ulong * emin; ulong * emax; slong startidx; slong endidx; int upperclosed; volatile int lock; volatile int producer; volatile slong ma; volatile slong mq; int Cinited; } divides_heap_chunk_struct; typedef divides_heap_chunk_struct divides_heap_chunk_t[1]; /* the base struct includes a linked list of chunks */ typedef struct { #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif divides_heap_chunk_struct * head; divides_heap_chunk_struct * tail; divides_heap_chunk_struct * volatile cur; nmod_mpolyn_t polyA; nmod_mpolyn_t polyB; nmod_mpolyn_ts_t polyQ; const nmod_mpoly_ctx_struct * ctx; slong length; slong N; flint_bitcnt_t bits; ulong * cmpmask; int failed; } divides_heap_base_struct; typedef divides_heap_base_struct divides_heap_base_t[1]; /* the worker struct has a big chunk of memory in the stripe_t and two polys for work space */ typedef struct _worker_arg_struct { divides_heap_base_struct * H; nmod_mpolyn_stripe_t S; nmod_mpolyn_t polyT1; nmod_mpolyn_t polyT2; } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void divides_heap_base_init(divides_heap_base_t H) { H->head = NULL; H->tail = NULL; H->cur = NULL; H->ctx = NULL; H->length = 0; H->N = 0; H->bits = 0; H->cmpmask = NULL; } static void divides_heap_chunk_clear(divides_heap_chunk_t L, divides_heap_base_t H) { if (L->Cinited) { nmod_mpolyn_clear(L->polyC, H->ctx); } } static int divides_heap_base_clear(nmod_mpolyn_t Q, divides_heap_base_t H) { divides_heap_chunk_struct * L = H->head; while (L != NULL) { divides_heap_chunk_struct * nextL = L->next; divides_heap_chunk_clear(L, H); flint_free(L); L = nextL; } H->head = NULL; H->tail = NULL; H->cur = NULL; H->ctx = NULL; H->length = 0; H->N = 0; H->bits = 0; H->cmpmask = NULL; if (H->failed) { nmod_mpolyn_zero(Q, H->ctx); nmod_mpolyn_ts_clear(H->polyQ); return 0; } else { nmod_mpolyn_ts_clear_poly(Q, H->polyQ); return 1; } } static void divides_heap_base_add_chunk(divides_heap_base_t H, divides_heap_chunk_t L) { L->next = NULL; if (H->tail == NULL) { FLINT_ASSERT(H->head == NULL); H->tail = L; H->head = L; } else { divides_heap_chunk_struct * tail = H->tail; FLINT_ASSERT(tail->next == NULL); tail->next = L; H->tail = L; } H->length++; } static void _nmod_mpolyn_fit_length(n_poly_struct ** coeffs, ulong ** exps, slong * alloc, slong length, slong N, const nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = *alloc; slong new_alloc = FLINT_MAX(length, 2*old_alloc); if (length > old_alloc) { if (old_alloc == 0) { *exps = (ulong *) flint_malloc(new_alloc*N*sizeof(ulong)); *coeffs = (n_poly_struct *) flint_malloc(new_alloc*sizeof(n_poly_struct)); } else { *exps = (ulong *) flint_realloc(*exps, new_alloc*N*sizeof(ulong)); *coeffs = (n_poly_struct *) flint_realloc(*coeffs, new_alloc*sizeof(n_poly_struct)); } for (i = old_alloc; i < new_alloc; i++) { n_poly_init(*coeffs + i); } *alloc = new_alloc; } } static slong _nmod_mpolyn_mulsub_stripe1( n_poly_struct ** A_coeff, ulong ** A_exp, slong * A_alloc, const n_poly_struct * Dcoeff, const ulong * Dexp, slong Dlen, int saveD, const n_poly_struct * Bcoeff, const ulong * Bexp, slong Blen, const n_poly_struct * Ccoeff, const ulong * Cexp, slong Clen, const nmod_mpolyn_stripe_t S) { int upperclosed; slong startidx, endidx; ulong prev_startidx; ulong maskhi = S->cmpmask[0]; ulong emax = S->emax[0]; ulong emin = S->emin[0]; slong i, j; slong next_loc = Blen + 4; /* something bigger than heap can ever be */ slong heap_len = 1; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; slong Aalloc = *A_alloc; n_poly_struct * Acoeff = *A_coeff; ulong * Aexp = *A_exp; ulong exp; slong * ends; ulong texp; slong * hind; n_poly_t pp; FLINT_ASSERT(S->N == 1); FLINT_ASSERT(S->bits <= FLINT_BITS); n_poly_init(pp); i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); ends = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); startidx = *S->startidx; endidx = *S->endidx; upperclosed = S->upperclosed; emax = S->emax[0]; emin = S->emin[0]; /* put all the starting nodes on the heap */ prev_startidx = -UWORD(1); for (i = 0; i < Blen; i++) { if (startidx < Clen) { texp = Bexp[i] + Cexp[startidx]; FLINT_ASSERT(mpoly_monomial_cmp1(emax, texp, maskhi) > -upperclosed); } while (startidx > 0) { texp = Bexp[i] + Cexp[startidx - 1]; if (mpoly_monomial_cmp1(emax, texp, maskhi) <= -upperclosed) { break; } startidx--; } if (endidx < Clen) { texp = Bexp[i] + Cexp[endidx]; FLINT_ASSERT(mpoly_monomial_cmp1(emin, texp, maskhi) > 0); } while (endidx > 0) { texp = Bexp[i] + Cexp[endidx - 1]; if (mpoly_monomial_cmp1(emin, texp, maskhi) <= 0) { break; } endidx--; } ends[i] = endidx; hind[i] = 2*startidx + 1; if ( (startidx < endidx) && (((ulong)startidx) < prev_startidx) ) { x = chain + i; x->i = i; x->j = startidx; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } prev_startidx = startidx; } /* set the indices for the next time mul is called */ *S->startidx = startidx; *S->endidx = endidx; FLINT_ASSERT(ends[0] >= startidx); Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt1(Dexp[Di], exp, maskhi)) { _nmod_mpolyn_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, 1, S->ctx); Aexp[Alen] = Dexp[Di]; if (saveD) n_poly_set(Acoeff + Alen, Dcoeff + Di); else n_poly_swap(Acoeff + Alen, (n_poly_struct *)(Dcoeff + Di)); Alen++; Di++; } _nmod_mpolyn_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, 1, S->ctx); Aexp[Alen] = exp; if (Di < Dlen && Dexp[Di] == exp) { n_poly_set(Acoeff + Alen, Dcoeff + Di); Di++; } else { n_poly_zero(Acoeff + Alen); } do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; n_poly_mod_mul(pp, Bcoeff + x->i, Ccoeff + x->j, S->ctx->mod); n_poly_mod_sub(Acoeff + Alen, Acoeff + Alen, pp, S->ctx->mod); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); Alen += !n_poly_is_zero(Acoeff + Alen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < ends[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if ( (j + 1 < ends[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } } } FLINT_ASSERT(Di <= Dlen); _nmod_mpolyn_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + Dlen - Di, 1, S->ctx); if (saveD) { for (i = 0; i < Dlen - Di; i++) n_poly_set(Acoeff + Alen + i, Dcoeff + Di + i); } else { for (i = 0; i < Dlen - Di; i++) n_poly_swap(Acoeff + Alen + i, (n_poly_struct *)(Dcoeff + Di + i)); } mpoly_copy_monomials(Aexp + 1*Alen, Dexp + 1*Di, Dlen - Di, 1); Alen += Dlen - Di; *A_coeff = Acoeff; *A_exp = Aexp; *A_alloc = Aalloc; n_poly_clear(pp); return Alen; } static slong _nmod_mpolyn_mulsub_stripe( n_poly_struct ** A_coeff, ulong ** A_exp, slong * A_alloc, const n_poly_struct * Dcoeff, const ulong * Dexp, slong Dlen, int saveD, const n_poly_struct * Bcoeff, const ulong * Bexp, slong Blen, const n_poly_struct * Ccoeff, const ulong * Cexp, slong Clen, const nmod_mpolyn_stripe_t S) { int upperclosed; slong startidx, endidx; ulong prev_startidx; ulong * emax = S->emax; ulong * emin = S->emin; slong N = S->N; slong i, j; slong next_loc = Blen + 4; /* something bigger than heap can ever be */ slong heap_len = 1; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; slong Aalloc = *A_alloc; n_poly_struct * Acoeff = *A_coeff; ulong * Aexp = *A_exp; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * ends; ulong * texp; slong * hind; n_poly_t pp; FLINT_ASSERT(S->bits <= FLINT_BITS); n_poly_init(pp); i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); ends = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); exps = (ulong *)(S->big_mem + i); i += Blen*N*sizeof(ulong); exp_list = (ulong **)(S->big_mem + i); i += Blen*sizeof(ulong *); texp = (ulong *)(S->big_mem + i); i += N*sizeof(ulong); FLINT_ASSERT(i <= S->big_mem_alloc); exp_next = 0; startidx = *S->startidx; endidx = *S->endidx; upperclosed = S->upperclosed; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* put all the starting nodes on the heap */ prev_startidx = -UWORD(1); for (i = 0; i < Blen; i++) { if (startidx < Clen) { mpoly_monomial_add(texp, Bexp + N*i, Cexp + N*startidx, N); FLINT_ASSERT(mpoly_monomial_cmp(emax, texp, N, S->cmpmask) > -upperclosed); } while (startidx > 0) { mpoly_monomial_add(texp, Bexp + N*i, Cexp + N*(startidx - 1), N); if (mpoly_monomial_cmp(emax, texp, N, S->cmpmask) <= -upperclosed) { break; } startidx--; } if (endidx < Clen) { mpoly_monomial_add(texp, Bexp + N*i, Cexp + N*endidx, N); FLINT_ASSERT(mpoly_monomial_cmp(emin, texp, N, S->cmpmask) > 0); } while (endidx > 0) { mpoly_monomial_add(texp, Bexp + N*i, Cexp + N*(endidx - 1), N); if (mpoly_monomial_cmp(emin, texp, N, S->cmpmask) <= 0) { break; } endidx--; } ends[i] = endidx; hind[i] = 2*startidx + 1; if ( (startidx < endidx) && (((ulong)startidx) < prev_startidx) ) { x = chain + i; x->i = i; x->j = startidx; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } prev_startidx = startidx; } *S->startidx = startidx; *S->endidx = endidx; FLINT_ASSERT(ends[0] >= startidx); Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt(Dexp + N*Di, exp, N, S->cmpmask)) { _nmod_mpolyn_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N, S->ctx); mpoly_monomial_set(Aexp + N*Alen, Dexp + N*Di, N); if (saveD) n_poly_set(Acoeff + Alen, Dcoeff + Di); else n_poly_swap(Acoeff + Alen, (n_poly_struct *)(Dcoeff + Di)); Alen++; Di++; } _nmod_mpolyn_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N, S->ctx); mpoly_monomial_set(Aexp + N*Alen, exp, N); if (Di < Dlen && mpoly_monomial_equal(Dexp + N*Di, exp, N)) { n_poly_set(Acoeff + Alen, Dcoeff + Di); Di++; } else { n_poly_zero(Acoeff + Alen); } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; FLINT_ASSERT(startidx <= x->j); FLINT_ASSERT(x->j < ends[0]); n_poly_mod_mul(pp, Bcoeff + x->i, Ccoeff + x->j, S->ctx->mod); n_poly_mod_sub(Acoeff + Alen, Acoeff + Alen, pp, S->ctx->mod); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); Alen += !n_poly_is_zero(Acoeff + Alen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < ends[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } /* should we go up? */ if ( (j + 1 < ends[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } } } FLINT_ASSERT(Di <= Dlen); _nmod_mpolyn_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + Dlen - Di, N, S->ctx); if (saveD) { for (i = 0; i < Dlen - Di; i++) n_poly_set(Acoeff + Alen + i, Dcoeff + Di + i); } else { for (i = 0; i < Dlen - Di; i++) n_poly_swap(Acoeff + Alen + i, (n_poly_struct *)(Dcoeff + Di + i)); } mpoly_copy_monomials(Aexp + N*Alen, Dexp + N*Di, Dlen - Di, N); Alen += Dlen - Di; *A_coeff = Acoeff; *A_exp = Aexp; *A_alloc = Aalloc; n_poly_clear(pp); return Alen; } /* Q = stripe of A/B (assume A != 0) return Qlen = 0 if exact division is impossible */ static slong _nmod_mpolyn_divides_stripe1( n_poly_struct ** Q_coeff, ulong ** Q_exp, slong * Q_alloc, const n_poly_struct * Acoeff, const ulong * Aexp, slong Alen, const n_poly_struct * Bcoeff, const ulong * Bexp, slong Blen, const nmod_mpolyn_stripe_t S) { flint_bitcnt_t bits = S->bits; ulong emin = S->emin[0]; ulong cmpmask = 0; ulong texp; int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Qlen; slong Qalloc = * Q_alloc; n_poly_struct * Qcoeff = * Q_coeff; ulong * Qexp = * Q_exp; ulong exp; ulong mask; slong * hind; n_poly_t acc_lg, pp; FLINT_ASSERT(S->cmpmask[0] == 0); FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(S->N == 1); FLINT_ASSERT(S->bits <= FLINT_BITS); next_loc = Blen + 4; /* something bigger than heap can ever be */ i = 0; hind = (slong *)(S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); n_poly_init(acc_lg); n_poly_init(pp); for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); Qlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; HEAP_ASSIGN(heap[1], Aexp[0], x); FLINT_ASSERT(mpoly_monomial_cmp1(Aexp[0], emin, cmpmask) >= 0); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_exact_division; FLINT_ASSERT(mpoly_monomial_cmp1(exp, emin, cmpmask) >= 0); _nmod_mpolyn_fit_length(&Qcoeff, &Qexp, &Qalloc, Qlen + 1, 1, S->ctx); lt_divides = mpoly_monomial_divides1(Qexp + Qlen, exp, Bexp[0], mask); n_poly_zero(acc_lg); do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { n_poly_mod_add(acc_lg, acc_lg, Acoeff + x->j, S->ctx->mod); } else { n_poly_mod_mul(pp, Bcoeff + x->i, Qcoeff + x->j, S->ctx->mod); n_poly_mod_sub(acc_lg, acc_lg, pp, S->ctx->mod); } } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; FLINT_ASSERT(mpoly_monomial_cmp1(Aexp[x->j], emin, cmpmask) >= 0); _mpoly_heap_insert1(heap, Aexp[x->j], x, &next_loc, &heap_len, cmpmask); } } else { /* should we go up */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } } } if (n_poly_is_zero(acc_lg)) { continue; } n_poly_mod_divrem(Qcoeff + Qlen, pp, acc_lg, Bcoeff + 0, S->ctx->mod); if (!n_poly_is_zero(pp)) { goto not_exact_division; } if (!lt_divides) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; texp = Bexp[x->i] + Qexp[x->j]; if (mpoly_monomial_cmp1(texp, emin, cmpmask) >= 0) { _mpoly_heap_insert1(heap, texp, x, &next_loc, &heap_len, cmpmask); } else { hind[x->i] |= 1; } } s = 1; Qlen++; } cleanup: n_poly_clear(acc_lg); n_poly_clear(pp); *Q_alloc = Qalloc; *Q_coeff = Qcoeff; *Q_exp = Qexp; return Qlen; not_exact_division: Qlen = 0; goto cleanup; } static slong _nmod_mpolyn_divides_stripe( n_poly_struct ** Q_coeff, ulong ** Q_exp, slong * Q_alloc, const n_poly_struct * Acoeff, const ulong * Aexp, slong Alen, const n_poly_struct * Bcoeff, const ulong * Bexp, slong Blen, const nmod_mpolyn_stripe_t S) { flint_bitcnt_t bits = S->bits; slong N = S->N; int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Qlen; slong Qalloc = * Q_alloc; n_poly_struct * Qcoeff = * Q_coeff; ulong * Qexp = * Q_exp; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; n_poly_t acc_lg, pp; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(S->bits <= FLINT_BITS); next_loc = Blen + 4; /* something bigger than heap can ever be */ i = 0; hind = (slong *) (S->big_mem + i); i += Blen*sizeof(slong); store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); exps = (ulong *)(S->big_mem + i); i += Blen*N*sizeof(ulong); exp_list = (ulong **)(S->big_mem + i); i += Blen*sizeof(ulong *); FLINT_ASSERT(i <= S->big_mem_alloc); n_poly_init(acc_lg); n_poly_init(pp); exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; for (i = 0; i < Blen; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); Qlen = WORD(0); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; FLINT_ASSERT(mpoly_monomial_cmp(Aexp + N*0, S->emin, N, S->cmpmask) >= 0); mpoly_monomial_set(heap[1].exp, Aexp + N*0, N); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows(exp, N, mask)) { goto not_exact_division; } FLINT_ASSERT(mpoly_monomial_cmp(exp, S->emin, N, S->cmpmask) >= 0); _nmod_mpolyn_fit_length(&Qcoeff, &Qexp, &Qalloc, Qlen + 1, N, S->ctx); lt_divides = mpoly_monomial_divides(Qexp + N*Qlen, exp, Bexp + N*0, N, mask); n_poly_zero(acc_lg); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, S->cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { n_poly_mod_add(acc_lg, acc_lg, Acoeff + x->j, S->ctx->mod); } else { n_poly_mod_mul(pp, Bcoeff + x->i, Qcoeff + x->j, S->ctx->mod); n_poly_mod_sub(acc_lg, acc_lg, pp, S->ctx->mod); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Aexp + x->j*N, N); FLINT_ASSERT(mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } } else { /* should we go up */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } } } if (n_poly_is_zero(acc_lg)) { continue; } n_poly_mod_divrem(Qcoeff + Qlen, pp, acc_lg, Bcoeff + 0, S->ctx->mod); if (!n_poly_is_zero(pp)) { goto not_exact_division; } if (!lt_divides) { goto not_exact_division; } if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Qexp + N*x->j, N); if (mpoly_monomial_cmp(exp_list[exp_next], S->emin, N, S->cmpmask) >= 0) { exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, S->cmpmask); } else { hind[x->i] |= 1; } } s = 1; Qlen++; } cleanup: n_poly_clear(acc_lg); n_poly_clear(pp); *Q_alloc = Qalloc; *Q_coeff = Qcoeff; *Q_exp = Qexp; return Qlen; not_exact_division: Qlen = 0; goto cleanup; } static slong _chunk_find_exp(ulong * exp, slong a, const divides_heap_base_t H) { slong N = H->N; slong b = H->polyA->length; const ulong * Aexp = H->polyA->exps; try_again: FLINT_ASSERT(b >= a); FLINT_ASSERT(a > 0); FLINT_ASSERT(mpoly_monomial_cmp(Aexp + N*(a - 1), exp, N, H->cmpmask) >= 0); FLINT_ASSERT(b >= H->polyA->length || mpoly_monomial_cmp(Aexp + N*b, exp, N, H->cmpmask) < 0); if (b - a < 5) { slong i = a; while (i < b && mpoly_monomial_cmp(Aexp + N*i, exp, N, H->cmpmask) >= 0) { i++; } return i; } else { slong c = a + (b - a)/2; if (mpoly_monomial_cmp(Aexp + N*c, exp, N, H->cmpmask) < 0) { b = c; } else { a = c; } goto try_again; } } static void chunk_mulsub(worker_arg_t W, divides_heap_chunk_t L, slong q_prev_length) { divides_heap_base_struct * H = W->H; slong N = H->N; nmod_mpolyn_struct * C = L->polyC; const nmod_mpolyn_struct * B = H->polyB; const nmod_mpolyn_struct * A = H->polyA; nmod_mpolyn_ts_struct * Q = H->polyQ; nmod_mpolyn_struct * T1 = W->polyT1; nmod_mpolyn_stripe_struct * S = W->S; S->startidx = &L->startidx; S->endidx = &L->endidx; S->emin = L->emin; S->emax = L->emax; S->upperclosed = L->upperclosed; FLINT_ASSERT(S->N == N); stripe_fit_length(S, q_prev_length - L->mq); if (L->Cinited) { if (N == 1) { T1->length = _nmod_mpolyn_mulsub_stripe1( &T1->coeffs, &T1->exps, &T1->alloc, C->coeffs, C->exps, C->length, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } else { T1->length = _nmod_mpolyn_mulsub_stripe( &T1->coeffs, &T1->exps, &T1->alloc, C->coeffs, C->exps, C->length, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } nmod_mpolyn_swap(C, T1); } else { slong startidx, stopidx; if (L->upperclosed) { startidx = 0; stopidx = _chunk_find_exp(L->emin, 1, H); } else { startidx = _chunk_find_exp(L->emax, 1, H); stopidx = _chunk_find_exp(L->emin, startidx, H); } L->Cinited = 1; nmod_mpolyn_init(C, H->bits, H->ctx); nmod_mpolyn_fit_length(C, 16 + stopidx - startidx, H->ctx); if (N == 1) { C->length = _nmod_mpolyn_mulsub_stripe1( &C->coeffs, &C->exps, &C->alloc, A->coeffs + startidx, A->exps + N*startidx, stopidx - startidx, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } else { C->length = _nmod_mpolyn_mulsub_stripe( &C->coeffs, &C->exps, &C->alloc, A->coeffs + startidx, A->exps + N*startidx, stopidx - startidx, 1, Q->coeffs + L->mq, Q->exps + N*L->mq, q_prev_length - L->mq, B->coeffs, B->exps, B->length, S); } } L->mq = q_prev_length; } static void trychunk(worker_arg_t W, divides_heap_chunk_t L) { divides_heap_base_struct * H = W->H; slong N = H->N; nmod_mpolyn_struct * C = L->polyC; slong q_prev_length; const nmod_mpolyn_struct * B = H->polyB; const nmod_mpolyn_struct * A = H->polyA; nmod_mpolyn_ts_struct * Q = H->polyQ; nmod_mpolyn_struct * T2 = W->polyT2; /* return if this section has already finished processing */ if (L->mq < 0) { return; } /* process more quotient terms if available */ q_prev_length = Q->length; if (q_prev_length > L->mq) { if (L->producer == 0 && q_prev_length - L->mq < 20) return; chunk_mulsub(W, L, q_prev_length); } if (L->producer == 1) { divides_heap_chunk_struct * next; n_poly_struct * Rcoeff; ulong * Rexp; slong Rlen; /* process the remaining quotient terms */ q_prev_length = Q->length; if (q_prev_length > L->mq) { chunk_mulsub(W, L, q_prev_length); } /* find location of remaining terms */ if (L->Cinited) { Rlen = C->length; Rexp = C->exps; Rcoeff = C->coeffs; } else { slong startidx, stopidx; if (L->upperclosed) { startidx = 0; stopidx = _chunk_find_exp(L->emin, 1, H); } else { startidx = _chunk_find_exp(L->emax, 1, H); stopidx = _chunk_find_exp(L->emin, startidx, H); } Rlen = stopidx - startidx; Rcoeff = A->coeffs + startidx; Rexp = A->exps + N*startidx; } /* if we have remaining terms, add to quotient */ if (Rlen > 0) { nmod_mpolyn_stripe_struct * S = W->S; S->startidx = &L->startidx; S->endidx = &L->endidx; S->emin = L->emin; S->emax = L->emax; S->upperclosed = L->upperclosed; if (N == 1) { T2->length = _nmod_mpolyn_divides_stripe1( &T2->coeffs, &T2->exps, &T2->alloc, Rcoeff, Rexp, Rlen, B->coeffs, B->exps, B->length, S); } else { T2->length = _nmod_mpolyn_divides_stripe( &T2->coeffs, &T2->exps, &T2->alloc, Rcoeff, Rexp, Rlen, B->coeffs, B->exps, B->length, S); } if (T2->length == 0) { H->failed = 1; return; } else { nmod_mpolyn_ts_append(H->polyQ, T2->coeffs, T2->exps, T2->length, N, H->ctx); } } next = L->next; H->length--; H->cur = next; if (next != NULL) { next->producer = 1; } L->producer = 0; L->mq = -1; } return; } static void worker_loop(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; divides_heap_base_struct * H = W->H; nmod_mpolyn_stripe_struct * S = W->S; const nmod_mpolyn_struct * B = H->polyB; nmod_mpolyn_struct * T1 = W->polyT1; nmod_mpolyn_struct * T2 = W->polyT2; slong N = H->N; slong Blen = B->length; /* initialize stripe working memory */ S->ctx = H->ctx; S->N = N; S->bits = H->bits; S->cmpmask = H->cmpmask; S->big_mem_alloc = 0; S->big_mem = NULL; stripe_fit_length(S, Blen); nmod_mpolyn_init(T1, H->bits, H->ctx); nmod_mpolyn_fit_length(T1, 16, H->ctx); nmod_mpolyn_init(T2, H->bits, H->ctx); nmod_mpolyn_fit_length(T2, 16, H->ctx); while (!H->failed) { divides_heap_chunk_struct * L; L = H->cur; if (L == NULL) { break; } while (L != NULL) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&H->mutex); #endif if (L->lock != -1) { L->lock = -1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif trychunk(W, L); #if FLINT_USES_PTHREAD pthread_mutex_lock(&H->mutex); #endif L->lock = 0; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif break; } else { #if FLINT_USES_PTHREAD pthread_mutex_unlock(&H->mutex); #endif } L = L->next; } } nmod_mpolyn_clear(T1, H->ctx); nmod_mpolyn_clear(T2, H->ctx); flint_free(S->big_mem); return; } /* return 1 if quotient is exact */ int nmod_mpolyn_divides_threaded_pool( nmod_mpolyn_t Q, const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { ulong mask; int divides; fmpz_mpoly_ctx_t zctx; fmpz_mpoly_t S; slong i, k, N; flint_bitcnt_t bits = A->bits; ulong * cmpmask; worker_arg_struct * worker_args; n_poly_t qcoeff, r; ulong * texps, * qexps; divides_heap_base_t H; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(Q->bits == bits); if (B->length < 2 || A->length < 2) { return nmod_mpolyn_divides(Q, A, B, ctx); } TMP_START; n_poly_init(qcoeff); n_poly_init(r); N = mpoly_words_per_exp_sp(bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); fmpz_mpoly_ctx_init(zctx, ctx->minfo->nvars, ctx->minfo->ord); fmpz_mpoly_init(S, zctx); n_poly_mod_rem(r, A->coeffs + 0, B->coeffs + 0, ctx->mod); if (!n_poly_is_zero(r)) { divides = 0; nmod_mpolyn_zero(Q, ctx); goto cleanup1; } if (mpoly_divides_select_exps(S, zctx, num_handles, A->exps, A->length, B->exps, B->length, bits)) { divides = 0; nmod_mpolyn_zero(Q, ctx); goto cleanup1; } /* At this point A and B both have at least two terms and the leading coefficients and monomials divide and the exponent selection did not give an easy exit */ divides_heap_base_init(H); *H->polyA = *A; *H->polyB = *B; H->ctx = ctx; H->bits = bits; H->N = N; H->cmpmask = cmpmask; H->failed = 0; for (i = 0; i + 1 < S->length; i++) { divides_heap_chunk_struct * L; L = (divides_heap_chunk_struct *) flint_malloc( sizeof(divides_heap_chunk_struct)); L->ma = 0; L->mq = 0; L->emax = S->exps + N*i; L->emin = S->exps + N*(i + 1); L->upperclosed = 0; L->startidx = B->length; L->endidx = B->length; L->producer = 0; L->Cinited = 0; L->lock = -2; divides_heap_base_add_chunk(H, L); } H->head->upperclosed = 1; H->head->producer = 1; H->cur = H->head; /* generate at least the first quotient term */ texps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); qexps = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_sub(qexps + N*0, A->exps + N*0, B->exps + N*0, N); n_poly_mod_divexact(qcoeff, A->coeffs + 0, B->coeffs + 0, ctx->mod); /* already checked */ nmod_mpolyn_ts_init(H->polyQ, qcoeff, qexps, 1, H->bits, H->N, ctx); mpoly_monomial_add(texps, qexps + N*0, B->exps + N*1, N); mask = mpoly_overflow_mask_sp(bits); k = 1; while (k < A->length && mpoly_monomial_gt(A->exps + N*k, texps, N, cmpmask)) { if (!mpoly_monomial_divides(qexps, A->exps + N*k, B->exps + N*0, N, mask)) { H->failed = 1; break; } n_poly_mod_divrem(qcoeff, r, A->coeffs + k, B->coeffs + 0, ctx->mod); if (!n_poly_is_zero(r)) { H->failed = 1; break; } nmod_mpolyn_ts_append(H->polyQ, qcoeff, qexps, 1, H->N, ctx); k++; } /* start the workers */ #if FLINT_USES_PTHREAD pthread_mutex_init(&H->mutex, NULL); #endif worker_args = (worker_arg_struct *) flint_malloc((num_handles + 1) *sizeof(worker_arg_t)); for (i = 0; i < num_handles; i++) { (worker_args + i)->H = H; thread_pool_wake(global_thread_pool, handles[i], 0, worker_loop, worker_args + i); } (worker_args + num_handles)->H = H; worker_loop(worker_args + num_handles); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } flint_free(worker_args); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&H->mutex); #endif divides = divides_heap_base_clear(Q, H); cleanup1: fmpz_mpoly_clear(S, zctx); fmpz_mpoly_ctx_clear(zctx); n_poly_clear(qcoeff); n_poly_clear(r); TMP_END; return divides; } #else typedef int this_file_is_empty; #endif flint-3.1.3/src/nmod_mpoly/mpolyn_gcd_brown.c000066400000000000000000001137171461254215100213170ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" int nmod_mpolyn_gcd_brown_smprime_bivar( nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx, nmod_poly_stack_t Sp) { int success; slong bound; mp_limb_t alpha, temp, gammaevalp, gammaevalm; n_poly_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp; n_poly_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm; nmod_mpolyn_struct * T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma; n_poly_struct * modulus, * modulus2, * alphapow, * r; int gstab, astab, bstab, use_stab; slong N, off, shift; flint_bitcnt_t bits = A->bits; #if FLINT_WANT_ASSERT n_poly_t leadA, leadB; const slong Sp_size_poly = nmod_poly_stack_size_poly(Sp); const slong Sp_size_mpolyn = nmod_poly_stack_size_mpolyn(Sp); #endif FLINT_ASSERT(Sp->ctx->mod.n == ctx->mod.n); FLINT_ASSERT(Sp->ctx->minfo->nvars == ctx->minfo->nvars); FLINT_ASSERT(Sp->bits == bits); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(Abar->bits == bits); FLINT_ASSERT(Bbar->bits == bits); #if FLINT_WANT_ASSERT n_poly_init(leadA); n_poly_init(leadB); n_poly_set(leadA, nmod_mpolyn_leadcoeff_poly(A, ctx)); n_poly_set(leadB, nmod_mpolyn_leadcoeff_poly(B, ctx)); #endif N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo); nmod_poly_stack_fit_request_poly(Sp, 20); cA = nmod_poly_stack_take_top_poly(Sp); cB = nmod_poly_stack_take_top_poly(Sp); cG = nmod_poly_stack_take_top_poly(Sp); cAbar = nmod_poly_stack_take_top_poly(Sp); cBbar = nmod_poly_stack_take_top_poly(Sp); gamma = nmod_poly_stack_take_top_poly(Sp); Aevalp = nmod_poly_stack_take_top_poly(Sp); Bevalp = nmod_poly_stack_take_top_poly(Sp); Gevalp = nmod_poly_stack_take_top_poly(Sp); Abarevalp = nmod_poly_stack_take_top_poly(Sp); Bbarevalp = nmod_poly_stack_take_top_poly(Sp); Aevalm = nmod_poly_stack_take_top_poly(Sp); Bevalm = nmod_poly_stack_take_top_poly(Sp); Gevalm = nmod_poly_stack_take_top_poly(Sp); Abarevalm = nmod_poly_stack_take_top_poly(Sp); Bbarevalm = nmod_poly_stack_take_top_poly(Sp); r = nmod_poly_stack_take_top_poly(Sp); alphapow = nmod_poly_stack_take_top_poly(Sp); modulus = nmod_poly_stack_take_top_poly(Sp); modulus2 = nmod_poly_stack_take_top_poly(Sp); nmod_poly_stack_fit_request_mpolyn(Sp, 1); T = nmod_poly_stack_take_top_mpolyn(Sp); nmod_mpolyn_content_last(cA, A, ctx); nmod_mpolyn_content_last(cB, B, ctx); nmod_mpolyn_divexact_last(A, cA, ctx); nmod_mpolyn_divexact_last(B, cB, ctx); n_poly_mod_gcd(cG, cA, cB, ctx->mod); n_poly_mod_divexact(cAbar, cA, cG, ctx->mod); n_poly_mod_divexact(cBbar, cB, cG, ctx->mod); n_poly_mod_gcd(gamma, nmod_mpolyn_leadcoeff_poly(A, ctx), nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->mod); ldegA = nmod_mpolyn_lastdeg(A, ctx); ldegB = nmod_mpolyn_lastdeg(B, ctx); deggamma = n_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1)); n_poly_one(modulus); if ((ctx->mod.n & UWORD(1)) == UWORD(0)) { success = 0; goto cleanup; } use_stab = 1; gstab = bstab = astab = 0; alpha = (ctx->mod.n - UWORD(1))/UWORD(2); choose_prime: /* primes are v - alpha, v + alpha */ if (alpha < 2) { success = 0; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= ctx->mod.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; /* make sure evaluation point does not kill both lc(A) and lc(B) */ _nmod_poly_eval2_pow(&gammaevalp, &gammaevalm, gamma, alphapow, ctx->mod); if (gammaevalp == 0 || gammaevalm == 0) { goto choose_prime; } /* evaluation point should kill neither A nor B */ nmod_mpolyn_interp_reduce_2sm_poly(Aevalp, Aevalm, A, alphapow, ctx); nmod_mpolyn_interp_reduce_2sm_poly(Bevalp, Bevalm, B, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); if (use_stab && gstab) { slong Gdeg; nmod_mpolyn_interp_reduce_2sm_poly(Gevalp, Gevalm, G, alphapow, ctx); Gdeg = ((G->exps + N*0)[off]>>shift); success = 1; success = success && n_poly_degree(Gevalp) == Gdeg; success = success && n_poly_degree(Gevalm) == Gdeg; success = success && Gevalp->coeffs[Gdeg] == gammaevalp; success = success && Gevalm->coeffs[Gdeg] == gammaevalm; n_poly_mod_divrem(Abarevalp, r, Aevalp, Gevalp, ctx->mod); success = success && (r->length == 0); n_poly_mod_divrem(Abarevalm, r, Aevalm, Gevalm, ctx->mod); success = success && (r->length == 0); n_poly_mod_divrem(Bbarevalp, r, Bevalp, Gevalp, ctx->mod); success = success && (r->length == 0); n_poly_mod_divrem(Bbarevalm, r, Bevalm, Gevalm, ctx->mod); success = success && (r->length == 0); if (!success) { use_stab = 0; n_poly_one(modulus); alpha = (ctx->mod.n - UWORD(1))/UWORD(2); goto choose_prime; } _n_poly_mod_scalar_mul_nmod(Abarevalp, Abarevalp, gammaevalp, ctx->mod); _n_poly_mod_scalar_mul_nmod(Abarevalm, Abarevalm, gammaevalm, ctx->mod); _n_poly_mod_scalar_mul_nmod(Bbarevalp, Bbarevalp, gammaevalp, ctx->mod); _n_poly_mod_scalar_mul_nmod(Bbarevalm, Bbarevalm, gammaevalm, ctx->mod); } else { n_poly_mod_gcd(Gevalp, Aevalp, Bevalp, ctx->mod); n_poly_mod_divexact(Abarevalp, Aevalp, Gevalp, ctx->mod); n_poly_mod_divexact(Bbarevalp, Bevalp, Gevalp, ctx->mod); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx->mod); n_poly_mod_divexact(Abarevalm, Aevalm, Gevalm, ctx->mod); n_poly_mod_divexact(Bbarevalm, Bevalm, Gevalm, ctx->mod); gstab = astab = bstab = 0; } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); if (n_poly_degree(Gevalp) == 0 || n_poly_degree(Gevalm) == 0) { nmod_mpolyn_one(G, ctx); nmod_mpolyn_swap(Abar, A); nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (n_poly_degree(Gevalp) != n_poly_degree(Gevalm)) { goto choose_prime; } /* the Geval have matching degrees */ if (n_poly_degree(modulus) > 0) { FLINT_ASSERT(G->length > 0); if (n_poly_degree(Gevalp) > ((G->exps + N*0)[off]>>shift)) { goto choose_prime; } else if (n_poly_degree(Gevalp) < ((G->exps + N*0)[off]>>shift)) { n_poly_one(modulus); } } /* update interpolants */ _n_poly_mod_scalar_mul_nmod(Gevalp, Gevalp, gammaevalp, ctx->mod); _n_poly_mod_scalar_mul_nmod(Gevalm, Gevalm, gammaevalm, ctx->mod); if (n_poly_degree(modulus) > 0) { temp = n_poly_mod_evaluate_nmod(modulus, alpha, ctx->mod); FLINT_ASSERT(temp == n_poly_mod_evaluate_nmod(modulus, ctx->mod.n - alpha, ctx->mod)); temp = nmod_mul(temp, alpha, ctx->mod); temp = nmod_add(temp, temp, ctx->mod); temp = n_invmod(temp, ctx->mod.n); _n_poly_mod_scalar_mul_nmod(modulus, modulus, temp, ctx->mod); if (!gstab) { gstab = !nmod_mpolyn_interp_crt_2sm_poly(&ldegG, G, T, Gevalp, Gevalm, modulus, alphapow, ctx); } nmod_mpolyn_interp_crt_2sm_poly(&ldegAbar, Abar, T, Abarevalp, Abarevalm, modulus, alphapow, ctx); nmod_mpolyn_interp_crt_2sm_poly(&ldegBbar, Bbar, T, Bbarevalp, Bbarevalm, modulus, alphapow, ctx); } else { nmod_mpolyn_interp_lift_2sm_poly(&ldegG, G, Gevalp, Gevalm, alpha, ctx); nmod_mpolyn_interp_lift_2sm_poly(&ldegAbar, Abar, Abarevalp, Abarevalm, alpha, ctx); nmod_mpolyn_interp_lift_2sm_poly(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, alpha, ctx); gstab = astab = bstab = 0; } temp = nmod_mul(alpha, alpha, ctx->mod); _n_poly_mod_scalar_mul_nmod(modulus2, modulus, temp, ctx->mod); n_poly_shift_left(modulus, modulus, 2); n_poly_mod_sub(modulus, modulus, modulus2, ctx->mod); if (n_poly_degree(modulus) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } n_poly_one(modulus); goto choose_prime; successful: nmod_mpolyn_content_last(modulus, G, ctx); nmod_mpolyn_divexact_last(G, modulus, ctx); nmod_mpolyn_divexact_last(Abar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); nmod_mpolyn_divexact_last(Bbar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); successful_put_content: nmod_mpolyn_mul_last(G, cG, ctx); nmod_mpolyn_mul_last(Abar, cAbar, ctx); nmod_mpolyn_mul_last(Bbar, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { FLINT_ASSERT(1 == nmod_mpolyn_leadcoeff(G, ctx)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadA)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadB)); } n_poly_clear(leadA); n_poly_clear(leadB); #endif nmod_poly_stack_give_back_poly(Sp, 20); nmod_poly_stack_give_back_mpolyn(Sp, 1); FLINT_ASSERT(Sp_size_poly == nmod_poly_stack_size_poly(Sp)); FLINT_ASSERT(Sp_size_mpolyn == nmod_poly_stack_size_mpolyn(Sp)); return success; } int nmod_mpolyn_gcd_brown_smprime( nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx, const mpoly_gcd_info_t I, nmod_poly_stack_t Sp) { int success; int changed; slong bound; slong upper_limit; slong offset, shift; mp_limb_t alpha, temp, gammaevalp, gammaevalm; nmod_mpolyn_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp; nmod_mpolyn_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm; nmod_mpolyn_struct * T1, * T2; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma; n_poly_struct * modulus, * modulus2, * alphapow; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); #if FLINT_WANT_ASSERT nmod_mpolyn_t Aorg, Borg; n_poly_t leadA, leadB; slong Sp_size_poly = nmod_poly_stack_size_poly(Sp); slong Sp_size_mpolyn = nmod_poly_stack_size_mpolyn(Sp); #endif FLINT_ASSERT(Sp->ctx->mod.n == ctx->mod.n); FLINT_ASSERT(Sp->ctx->minfo->nvars == ctx->minfo->nvars); FLINT_ASSERT(Sp->bits == A->bits); FLINT_ASSERT(Sp->bits == B->bits); FLINT_ASSERT(Sp->bits == G->bits); FLINT_ASSERT(Sp->bits == Abar->bits); FLINT_ASSERT(Sp->bits == Bbar->bits); FLINT_ASSERT(var > 0); if (var == 1) return nmod_mpolyn_gcd_brown_smprime_bivar(G, Abar, Bbar, A, B, ctx, Sp); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, G->bits, ctx->minfo); #if FLINT_WANT_ASSERT n_poly_init(leadA); n_poly_init(leadB); n_poly_set(leadA, nmod_mpolyn_leadcoeff_poly(A, ctx)); n_poly_set(leadB, nmod_mpolyn_leadcoeff_poly(B, ctx)); nmod_mpolyn_init(Aorg, A->bits, ctx); nmod_mpolyn_init(Borg, B->bits, ctx); nmod_mpolyn_set(Aorg, A, ctx); nmod_mpolyn_set(Borg, B, ctx); #endif nmod_poly_stack_fit_request_poly(Sp, 9); cA = nmod_poly_stack_take_top_poly(Sp); cB = nmod_poly_stack_take_top_poly(Sp); cG = nmod_poly_stack_take_top_poly(Sp); cAbar = nmod_poly_stack_take_top_poly(Sp); cBbar = nmod_poly_stack_take_top_poly(Sp); gamma = nmod_poly_stack_take_top_poly(Sp); alphapow = nmod_poly_stack_take_top_poly(Sp); modulus = nmod_poly_stack_take_top_poly(Sp); modulus2 = nmod_poly_stack_take_top_poly(Sp); nmod_poly_stack_fit_request_mpolyn(Sp, 12); Aevalp = nmod_poly_stack_take_top_mpolyn(Sp); Bevalp = nmod_poly_stack_take_top_mpolyn(Sp); Gevalp = nmod_poly_stack_take_top_mpolyn(Sp); Abarevalp = nmod_poly_stack_take_top_mpolyn(Sp); Bbarevalp = nmod_poly_stack_take_top_mpolyn(Sp); Aevalm = nmod_poly_stack_take_top_mpolyn(Sp); Bevalm = nmod_poly_stack_take_top_mpolyn(Sp); Gevalm = nmod_poly_stack_take_top_mpolyn(Sp); Abarevalm = nmod_poly_stack_take_top_mpolyn(Sp); Bbarevalm = nmod_poly_stack_take_top_mpolyn(Sp); T1 = nmod_poly_stack_take_top_mpolyn(Sp); T2 = nmod_poly_stack_take_top_mpolyn(Sp); nmod_mpolyn_content_last(cA, A, ctx); nmod_mpolyn_content_last(cB, B, ctx); nmod_mpolyn_divexact_last(A, cA, ctx); nmod_mpolyn_divexact_last(B, cB, ctx); n_poly_mod_gcd(cG, cA, cB, ctx->mod); n_poly_mod_divexact(cAbar, cA, cG, ctx->mod); n_poly_mod_divexact(cBbar, cB, cG, ctx->mod); n_poly_mod_gcd(gamma, nmod_mpolyn_leadcoeff_poly(A, ctx), nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->mod); ldegA = nmod_mpolyn_lastdeg(A, ctx); ldegB = nmod_mpolyn_lastdeg(B, ctx); deggamma = n_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); upper_limit = mpoly_gcd_info_get_brown_upper_limit(I, var, bound); n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1)); n_poly_one(modulus); if ((ctx->mod.n & UWORD(1)) == UWORD(0)) { success = 0; goto cleanup; } alpha = (ctx->mod.n - UWORD(1))/UWORD(2); choose_prime: if (alpha < 2) { success = 0; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= ctx->mod.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; /* make sure evaluation point does not kill both lc(A) and lc(B) */ _nmod_poly_eval2_pow(&gammaevalp, &gammaevalm, gamma, alphapow, ctx->mod); if (gammaevalp == 0 || gammaevalm == 0) { goto choose_prime; } /* evaluation point should kill neither A nor B */ nmod_mpolyn_interp_reduce_2sm_mpolyn(Aevalp, Aevalm, A, var, alphapow, ctx); nmod_mpolyn_interp_reduce_2sm_mpolyn(Bevalp, Bevalm, B, var, alphapow, ctx); FLINT_ASSERT(Aevalp->length > 0); FLINT_ASSERT(Aevalm->length > 0); FLINT_ASSERT(Bevalp->length > 0); FLINT_ASSERT(Bevalm->length > 0); success = nmod_mpolyn_gcd_brown_smprime(Gevalp, Abarevalp, Bbarevalp, Aevalp, Bevalp, var - 1, ctx, I, Sp); success = success && nmod_mpolyn_gcd_brown_smprime(Gevalm, Abarevalm, Bbarevalm, Aevalm, Bevalm, var - 1, ctx, I, Sp); if (success == 0) { goto choose_prime; } FLINT_ASSERT(Gevalp->length > 0); FLINT_ASSERT(Abarevalp->length > 0); FLINT_ASSERT(Bbarevalp->length > 0); FLINT_ASSERT(Gevalm->length > 0); FLINT_ASSERT(Abarevalm->length > 0); FLINT_ASSERT(Bbarevalm->length > 0); if ( nmod_mpolyn_is_nonzero_nmod(Gevalp, ctx) || nmod_mpolyn_is_nonzero_nmod(Gevalm, ctx)) { nmod_mpolyn_one(G, ctx); nmod_mpolyn_swap(Abar, A); nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (n_poly_degree(Gevalp->coeffs + 0) != n_poly_degree(Gevalm->coeffs + 0)) { goto choose_prime; } if (!mpoly_monomial_equal(Gevalp->exps + N*0, Gevalm->exps + N*0, N)) { goto choose_prime; } /* the Geval have matching degrees */ if (n_poly_degree(modulus) > 0) { int cmp; slong k; FLINT_ASSERT(G->length > 0); k = n_poly_degree(Gevalp->coeffs + 0); cmp = mpoly_monomial_cmp_nomask_extra(G->exps + N*0, Gevalp->exps + N*0, N, offset, k << shift); if (cmp < 0) { goto choose_prime; } else if (cmp > 0) { n_poly_one(modulus); } } /* update interpolants */ temp = nmod_mpolyn_leadcoeff(Gevalp, ctx); temp = n_invmod(temp, ctx->mod.n); temp = nmod_mul(gammaevalp, temp, ctx->mod); nmod_mpolyn_scalar_mul_nmod(Gevalp, temp, ctx); temp = nmod_mpolyn_leadcoeff(Gevalm, ctx); temp = n_invmod(temp, ctx->mod.n); temp = nmod_mul(gammaevalm, temp, ctx->mod); nmod_mpolyn_scalar_mul_nmod(Gevalm, temp, ctx); if (n_poly_degree(modulus) > 0) { temp = n_poly_mod_evaluate_nmod(modulus, alpha, ctx->mod); FLINT_ASSERT(temp == n_poly_mod_evaluate_nmod(modulus, ctx->mod.n - alpha, ctx->mod)); temp = nmod_mul(temp, alpha, ctx->mod); temp = nmod_add(temp, temp, ctx->mod); temp = n_invmod(temp, ctx->mod.n); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, ctx->mod); changed = nmod_mpolyn_interp_crt_2sm_mpolyn(&ldegG, G, T1, Gevalp, Gevalm, var, modulus, alphapow, ctx); if (!changed && n_poly_degree(modulus) < upper_limit) { nmod_mpolyn_content_last(modulus2, G, ctx); nmod_mpolyn_divexact_last(G, modulus2, ctx); success = nmod_mpolyn_divides(T1, A, G, ctx); success = success && nmod_mpolyn_divides(T2, B, G, ctx); if (success) { nmod_mpolyn_swap(T1, Abar); nmod_mpolyn_swap(T2, Bbar); successful_fix_lc: temp = nmod_mpolyn_leadcoeff(G, ctx); nmod_mpolyn_scalar_mul_nmod(Abar, temp, ctx); nmod_mpolyn_scalar_mul_nmod(Bbar, temp, ctx); temp = n_invmod(temp, ctx->mod.n); nmod_mpolyn_scalar_mul_nmod(G, temp, ctx); goto successful_put_content; } else { nmod_mpolyn_mul_last(G, modulus2, ctx); /* restore G */ } } changed = nmod_mpolyn_interp_crt_2sm_mpolyn(&ldegAbar, Abar, T1, Abarevalp, Abarevalm, var, modulus, alphapow, ctx); if (!changed && n_poly_degree(modulus) < upper_limit) { nmod_mpolyn_content_last(modulus2, Abar, ctx); nmod_mpolyn_divexact_last(Abar, modulus2, ctx); success = nmod_mpolyn_divides(T1, A, Abar, ctx); success = success && nmod_mpolyn_divides(T2, B, T1, ctx); if (success) { nmod_mpolyn_swap(T1, G); nmod_mpolyn_swap(T2, Bbar); goto successful_fix_lc; } else { nmod_mpolyn_mul_last(Abar, modulus2, ctx); /* restore Abar */ } } changed = nmod_mpolyn_interp_crt_2sm_mpolyn(&ldegBbar, Bbar, T1, Bbarevalp, Bbarevalm, var, modulus, alphapow, ctx); if (!changed && n_poly_degree(modulus) < upper_limit) { nmod_mpolyn_content_last(modulus2, Bbar, ctx); nmod_mpolyn_divexact_last(Bbar, modulus2, ctx); success = nmod_mpolyn_divides(T1, B, Bbar, ctx); success = success && nmod_mpolyn_divides(T2, A, T1, ctx); if (success) { nmod_mpolyn_swap(T1, G); nmod_mpolyn_swap(T2, Abar); goto successful_fix_lc; } else { nmod_mpolyn_mul_last(Bbar, modulus2, ctx); /* restore Bbar */ } } } else { nmod_mpolyn_interp_lift_2sm_mpolyn(&ldegG, G, Gevalp, Gevalm, var, alpha, ctx); nmod_mpolyn_interp_lift_2sm_mpolyn(&ldegAbar, Abar, Abarevalp, Abarevalm, var, alpha, ctx); nmod_mpolyn_interp_lift_2sm_mpolyn(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, var, alpha, ctx); } temp = nmod_mul(alpha, alpha, ctx->mod); _n_poly_mod_scalar_mul_nmod(modulus2, modulus, temp, ctx->mod); n_poly_shift_left(modulus, modulus, 2); n_poly_mod_sub(modulus, modulus, modulus2, ctx->mod); if (n_poly_degree(modulus) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } n_poly_one(modulus); goto choose_prime; successful: nmod_mpolyn_content_last(modulus2, G, ctx); nmod_mpolyn_divexact_last(G, modulus2, ctx); nmod_mpolyn_divexact_last(Abar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); nmod_mpolyn_divexact_last(Bbar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); successful_put_content: nmod_mpolyn_mul_last(G, cG, ctx); nmod_mpolyn_mul_last(Abar, cAbar, ctx); nmod_mpolyn_mul_last(Bbar, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { FLINT_ASSERT(1 == nmod_mpolyn_leadcoeff(G, ctx)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadA)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadB)); success = nmod_mpolyn_divides(T1, Aorg, G, ctx); success = success && nmod_mpolyn_divides(T2, Borg, G, ctx); FLINT_ASSERT(success); FLINT_ASSERT(nmod_mpolyn_equal(T1, Abar, ctx)); FLINT_ASSERT(nmod_mpolyn_equal(T2, Bbar, ctx)); success = 1; } n_poly_clear(leadA); n_poly_clear(leadB); nmod_mpolyn_clear(Aorg, ctx); nmod_mpolyn_clear(Borg, ctx); #endif nmod_poly_stack_give_back_poly(Sp, 9); nmod_poly_stack_give_back_mpolyn(Sp, 12); FLINT_ASSERT(Sp_size_poly == nmod_poly_stack_size_poly(Sp)); FLINT_ASSERT(Sp_size_mpolyn == nmod_poly_stack_size_mpolyn(Sp)); return success; } int nmod_mpolyn_gcd_brown_lgprime_bivar( nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx) { int success; slong bound; fq_nmod_t temp, gammaeval; fq_nmod_poly_t Aeval, Beval, Geval, Abareval, Bbareval; nmod_mpolyn_t T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_t cA, cB, cG, cAbar, cBbar, gamma; n_poly_t modulus; slong deg; fq_nmod_mpoly_ctx_t ectx; slong N, off, shift; #if FLINT_WANT_ASSERT n_poly_t leadA, leadB; #endif #if FLINT_WANT_ASSERT n_poly_init(leadA); n_poly_init(leadB); n_poly_set(leadA, nmod_mpolyn_leadcoeff_poly(A, ctx)); n_poly_set(leadB, nmod_mpolyn_leadcoeff_poly(B, ctx)); #endif N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, 0, A->bits, ctx->minfo); n_poly_init(cA); n_poly_init(cB); nmod_mpolyn_content_last(cA, A, ctx); nmod_mpolyn_content_last(cB, B, ctx); nmod_mpolyn_divexact_last(A, cA, ctx); nmod_mpolyn_divexact_last(B, cB, ctx); n_poly_init(cG); n_poly_mod_gcd(cG, cA, cB, ctx->mod); n_poly_init(cAbar); n_poly_init(cBbar); n_poly_mod_divexact(cAbar, cA, cG, ctx->mod); n_poly_mod_divexact(cBbar, cB, cG, ctx->mod); n_poly_init(gamma); n_poly_mod_gcd(gamma, nmod_mpolyn_leadcoeff_poly(A, ctx), nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->mod); ldegA = nmod_mpolyn_lastdeg(A, ctx); ldegB = nmod_mpolyn_lastdeg(B, ctx); deggamma = n_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); nmod_mpolyn_init(T, A->bits, ctx); n_poly_init(modulus); n_poly_one(modulus); deg = WORD(20)/(FLINT_BIT_COUNT(ctx->mod.n)); deg = FLINT_MAX(WORD(2), deg); fq_nmod_mpoly_ctx_init_deg(ectx, ctx->minfo->nvars, ORD_LEX, ctx->mod.n, deg); fq_nmod_poly_init(Aeval, ectx->fqctx); fq_nmod_poly_init(Beval, ectx->fqctx); fq_nmod_poly_init(Geval, ectx->fqctx); fq_nmod_poly_init(Abareval, ectx->fqctx); fq_nmod_poly_init(Bbareval, ectx->fqctx); fq_nmod_init(gammaeval, ectx->fqctx); fq_nmod_init(temp, ectx->fqctx); /* initialization already picked a prime */ goto have_prime; choose_prime: /* prime will be irreducible element of Fp[v] */ /* same TODO */ deg++; if (deg > 10000) { /* ran out of primes */ success = 0; goto cleanup; } fq_nmod_mpoly_ctx_change_modulus(ectx, deg); have_prime: /* make sure reduction does not kill both lc(A) and lc(B) */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(gammaeval), gamma, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); if (fq_nmod_is_zero(gammaeval, ectx->fqctx)) { goto choose_prime; } /* reduction should kill neither A nor B */ nmod_mpolyn_interp_reduce_lg_poly(Aeval, ectx->fqctx, A, ctx); nmod_mpolyn_interp_reduce_lg_poly(Beval, ectx->fqctx, B, ctx); FLINT_ASSERT(Aeval->length > 0); FLINT_ASSERT(Beval->length > 0); fq_nmod_poly_gcd(Geval, Aeval, Beval, ectx->fqctx); success = fq_nmod_poly_divides(Abareval, Aeval, Geval, ectx->fqctx); FLINT_ASSERT(success); success = fq_nmod_poly_divides(Bbareval, Beval, Geval, ectx->fqctx); FLINT_ASSERT(success); FLINT_ASSERT(Geval->length > 0); FLINT_ASSERT(Abareval->length > 0); FLINT_ASSERT(Bbareval->length > 0); if (fq_nmod_poly_degree(Geval, ectx->fqctx) == 0) { nmod_mpolyn_one(G, ctx); nmod_mpolyn_swap(Abar, A); nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (n_poly_degree(modulus) > 0) { slong Gdeg; FLINT_ASSERT(G->length > 0); Gdeg = (G->exps + N*0)[off]>>shift; if (fq_nmod_poly_degree(Geval, ectx->fqctx) > Gdeg) { goto choose_prime; } else if (fq_nmod_poly_degree(Geval, ectx->fqctx) < Gdeg) { n_poly_one(modulus); } } FLINT_ASSERT(fq_nmod_is_one(Geval->coeffs + Geval->length - 1, ectx->fqctx)); fq_nmod_poly_scalar_mul_fq_nmod(Geval, Geval, gammaeval, ectx->fqctx); if (n_poly_degree(modulus) > 0) { nmod_mpolyn_interp_crt_lg_poly(&ldegG, G, T, modulus, ctx, Geval, ectx->fqctx); nmod_mpolyn_interp_crt_lg_poly(&ldegAbar, Abar, T, modulus, ctx, Abareval, ectx->fqctx); nmod_mpolyn_interp_crt_lg_poly(&ldegBbar, Bbar, T, modulus, ctx, Bbareval, ectx->fqctx); } else { nmod_mpolyn_interp_lift_lg_poly(&ldegG, G, ctx, Geval, ectx->fqctx); nmod_mpolyn_interp_lift_lg_poly(&ldegAbar, Abar, ctx, Abareval, ectx->fqctx); nmod_mpolyn_interp_lift_lg_poly(&ldegBbar, Bbar, ctx, Bbareval, ectx->fqctx); } n_poly_mod_mul(modulus, modulus, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); if (n_poly_degree(modulus) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } n_poly_one(modulus); goto choose_prime; successful: nmod_mpolyn_content_last(modulus, G, ctx); nmod_mpolyn_divexact_last(G, modulus, ctx); nmod_mpolyn_divexact_last(Abar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); nmod_mpolyn_divexact_last(Bbar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); successful_put_content: nmod_mpolyn_mul_last(G, cG, ctx); nmod_mpolyn_mul_last(Abar, cAbar, ctx); nmod_mpolyn_mul_last(Bbar, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { FLINT_ASSERT(1 == nmod_mpolyn_leadcoeff(G, ctx)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadA)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadB)); } n_poly_clear(leadA); n_poly_clear(leadB); #endif n_poly_clear(cA); n_poly_clear(cB); n_poly_clear(cG); n_poly_clear(cAbar); n_poly_clear(cBbar); n_poly_clear(gamma); n_poly_clear(modulus); nmod_mpolyn_clear(T, ctx); fq_nmod_poly_clear(Aeval, ectx->fqctx); fq_nmod_poly_clear(Beval, ectx->fqctx); fq_nmod_poly_clear(Geval, ectx->fqctx); fq_nmod_poly_clear(Abareval, ectx->fqctx); fq_nmod_poly_clear(Bbareval, ectx->fqctx); fq_nmod_clear(gammaeval, ectx->fqctx); fq_nmod_clear(temp, ectx->fqctx); fq_nmod_mpoly_ctx_clear(ectx); return success; } int nmod_mpolyn_gcd_brown_lgprime( nmod_mpolyn_t G, nmod_mpolyn_t Abar, nmod_mpolyn_t Bbar, nmod_mpolyn_t A, nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx) { int success; slong bound; slong offset, shift; fq_nmod_t temp, gammaeval; fq_nmod_mpolyn_t Aeval, Beval, Geval, Abareval, Bbareval; nmod_mpolyn_t T; slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB; n_poly_t cA, cB, cG, cAbar, cBbar, gamma; n_poly_t modulus; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong deg; fq_nmod_mpoly_ctx_t ectx; #if FLINT_WANT_ASSERT n_poly_t leadA, leadB; #endif FLINT_ASSERT(var > 0); if (var == 1) return nmod_mpolyn_gcd_brown_lgprime_bivar(G, Abar, Bbar, A, B, ctx); mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, G->bits, ctx->minfo); #if FLINT_WANT_ASSERT n_poly_init(leadA); n_poly_init(leadB); n_poly_set(leadA, nmod_mpolyn_leadcoeff_poly(A, ctx)); n_poly_set(leadB, nmod_mpolyn_leadcoeff_poly(B, ctx)); #endif n_poly_init(cA); n_poly_init(cB); nmod_mpolyn_content_last(cA, A, ctx); nmod_mpolyn_content_last(cB, B, ctx); nmod_mpolyn_divexact_last(A, cA, ctx); nmod_mpolyn_divexact_last(B, cB, ctx); n_poly_init(cG); n_poly_mod_gcd(cG, cA, cB, ctx->mod); n_poly_init(cAbar); n_poly_init(cBbar); n_poly_mod_divexact(cAbar, cA, cG, ctx->mod); n_poly_mod_divexact(cBbar, cB, cG, ctx->mod); n_poly_init(gamma); n_poly_mod_gcd(gamma, nmod_mpolyn_leadcoeff_poly(A, ctx), nmod_mpolyn_leadcoeff_poly(B, ctx), ctx->mod); ldegA = nmod_mpolyn_lastdeg(A, ctx); ldegB = nmod_mpolyn_lastdeg(B, ctx); deggamma = n_poly_degree(gamma); bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB); nmod_mpolyn_init(T, bits, ctx); n_poly_init(modulus); n_poly_one(modulus); deg = WORD(20)/(FLINT_BIT_COUNT(ctx->mod.n)); deg = FLINT_MAX(WORD(2), deg); fq_nmod_mpoly_ctx_init_deg(ectx, ctx->minfo->nvars, ORD_LEX, ctx->mod.n, deg); fq_nmod_mpolyn_init(Aeval, bits, ectx); fq_nmod_mpolyn_init(Beval, bits, ectx); fq_nmod_mpolyn_init(Geval, bits, ectx); fq_nmod_mpolyn_init(Abareval, bits, ectx); fq_nmod_mpolyn_init(Bbareval, bits, ectx); fq_nmod_init(gammaeval, ectx->fqctx); fq_nmod_init(temp, ectx->fqctx); /* initialization already picked a prime */ goto have_prime; choose_prime: /* prime will be irreducible element of Fp[v] */ /* same TODO */ deg++; if (deg > 10000) { /* ran out of primes */ success = 0; goto cleanup; } fq_nmod_mpoly_ctx_change_modulus(ectx, deg); have_prime: /* make sure reduction does not kill both lc(A) and lc(B) */ n_poly_mod_rem(evil_cast_nmod_poly_to_n_poly(gammaeval), gamma, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); if (fq_nmod_is_zero(gammaeval, ectx->fqctx)) { goto choose_prime; } /* make sure reduction does not kill either A or B */ nmod_mpolyn_interp_reduce_lg_mpolyn(Aeval, ectx, A, var, ctx); nmod_mpolyn_interp_reduce_lg_mpolyn(Beval, ectx, B, var, ctx); FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(Aeval, ectx)); FLINT_ASSERT(fq_nmod_mpolyn_is_canonical(Beval, ectx)); if (Aeval->length == 0 || Beval->length == 0) { goto choose_prime; } success = fq_nmod_mpolyn_gcd_brown_smprime(Geval, Abareval, Bbareval, Aeval, Beval, var - 1, ectx); if (success == 0) { goto choose_prime; } if (fq_nmod_mpolyn_is_nonzero_fq_nmod(Geval, ectx)) { nmod_mpolyn_one(G, ctx); nmod_mpolyn_swap(Abar, A); nmod_mpolyn_swap(Bbar, B); goto successful_put_content; } if (n_poly_degree(modulus) > 0) { /* compare leading monomials of Geval and G */ int cmp = 0; slong k; FLINT_ASSERT(G->length > 0); k = n_poly_degree(Geval->coeffs + 0); cmp = mpoly_monomial_cmp_nomask_extra(G->exps + N*0, Geval->exps + N*0, N, offset, k << shift); if (cmp < 0) { goto choose_prime; } else if (cmp > 0) { n_poly_one(modulus); } } n_fq_get_fq_nmod(temp, fq_nmod_mpolyn_leadcoeff(Geval, ectx), ectx->fqctx); fq_nmod_inv(temp, temp, ectx->fqctx); fq_nmod_mul(temp, temp, gammaeval, ectx->fqctx); fq_nmod_mpolyn_scalar_mul_fq_nmod(Geval, temp, ectx); if (n_poly_degree(modulus) > 0) { nmod_mpolyn_interp_crt_lg_mpolyn(&ldegG, G, T, modulus, var, ctx, Geval, ectx); nmod_mpolyn_interp_crt_lg_mpolyn(&ldegAbar, Abar, T, modulus, var, ctx, Abareval, ectx); nmod_mpolyn_interp_crt_lg_mpolyn(&ldegBbar, Bbar, T, modulus, var, ctx, Bbareval, ectx); } else { nmod_mpolyn_interp_lift_lg_mpolyn(&ldegG, G, var, ctx, Geval, ectx); nmod_mpolyn_interp_lift_lg_mpolyn(&ldegAbar, Abar, var, ctx, Abareval, ectx); nmod_mpolyn_interp_lift_lg_mpolyn(&ldegBbar, Bbar, var, ctx, Bbareval, ectx); } n_poly_mod_mul(modulus, modulus, evil_const_cast_nmod_poly_to_n_poly(ectx->fqctx->modulus), ctx->mod); if (n_poly_degree(modulus) < bound) { goto choose_prime; } FLINT_ASSERT(ldegG >= 0); FLINT_ASSERT(ldegAbar >= 0); FLINT_ASSERT(ldegBbar >= 0); if ( deggamma + ldegA == ldegG + ldegAbar && deggamma + ldegB == ldegG + ldegBbar ) { goto successful; } n_poly_one(modulus); goto choose_prime; successful: nmod_mpolyn_content_last(modulus, G, ctx); nmod_mpolyn_divexact_last(G, modulus, ctx); nmod_mpolyn_divexact_last(Abar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); nmod_mpolyn_divexact_last(Bbar, nmod_mpolyn_leadcoeff_poly(G, ctx), ctx); successful_put_content: nmod_mpolyn_mul_last(G, cG, ctx); nmod_mpolyn_mul_last(Abar, cAbar, ctx); nmod_mpolyn_mul_last(Bbar, cBbar, ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success) { FLINT_ASSERT(1 == nmod_mpolyn_leadcoeff(G, ctx)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Abar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadA)); n_poly_mod_mul(modulus, nmod_mpolyn_leadcoeff_poly(G, ctx), nmod_mpolyn_leadcoeff_poly(Bbar, ctx), ctx->mod); FLINT_ASSERT(n_poly_equal(modulus, leadB)); } n_poly_clear(leadA); n_poly_clear(leadB); #endif n_poly_clear(cA); n_poly_clear(cB); n_poly_clear(cG); n_poly_clear(cAbar); n_poly_clear(cBbar); n_poly_clear(gamma); n_poly_clear(modulus); nmod_mpolyn_clear(T, ctx); fq_nmod_mpolyn_clear(Aeval, ectx); fq_nmod_mpolyn_clear(Beval, ectx); fq_nmod_mpolyn_clear(Geval, ectx); fq_nmod_mpolyn_clear(Abareval, ectx); fq_nmod_mpolyn_clear(Bbareval, ectx); fq_nmod_clear(gammaeval, ectx->fqctx); fq_nmod_clear(temp, ectx->fqctx); fq_nmod_mpoly_ctx_clear(ectx); return success; } flint-3.1.3/src/nmod_mpoly/mpolyu.c000066400000000000000000000700741461254215100173000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "nmod_mpoly_factor.h" void nmod_mpolyu_init(nmod_mpolyu_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void nmod_mpolyu_clear(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx) { slong i; for (i = 0; i < A->alloc; i++) nmod_mpoly_clear(A->coeffs + i, uctx); flint_free(A->coeffs); flint_free(A->exps); } int nmod_mpolyu_is_one(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx) { if (A->length != 1 || A->exps[0] != UWORD(0)) return 0; return nmod_mpoly_is_one(A->coeffs + 0, uctx); } void nmod_mpolyu_print_pretty(const nmod_mpolyu_t poly, const char ** x, const nmod_mpoly_ctx_t ctx) { slong i; if (poly->length == 0) flint_printf("0"); for (i = 0; i < poly->length; i++) { if (i != 0) flint_printf(" + "); flint_printf("("); nmod_mpoly_print_pretty(poly->coeffs + i,x,ctx); flint_printf(")*X^%wd",poly->exps[i]); } } void nmod_mpolyu_fit_length(nmod_mpolyu_t A, slong length, const nmod_mpoly_ctx_t uctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (nmod_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(nmod_mpoly_struct)); for (i = old_alloc; i < new_alloc; i++) nmod_mpoly_init3(A->coeffs + i, 0, A->bits, uctx); A->alloc = new_alloc; } } void nmod_mpolyu_one(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx) { nmod_mpolyu_fit_length(A, WORD(1), uctx); A->exps[0] = UWORD(0); nmod_mpoly_one(A->coeffs + 0, uctx); A->length = WORD(1); } void nmod_mpolyu_degrees_si( slong * degs, const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx) { slong i, j; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong * pmax, mask; TMP_INIT; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (A->length < 1) { for (j = 0; j < ctx->minfo->nvars; j++) degs[j] = -1; } TMP_START; mask = mpoly_overflow_mask_sp(bits); pmax = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_monomial_zero(pmax, N); for (i = 0; i < A->length; i++) { ulong * Aiexps = A->coeffs[i].exps; FLINT_ASSERT(A->coeffs[i].bits == bits); for (j = 0; j < A->coeffs[i].length; j++) mpoly_monomial_max(pmax, pmax, Aiexps + N*j, bits, N, mask); } mpoly_unpack_vec_ui((ulong *) degs, pmax, bits, ctx->minfo->nvars, 1); for (i = 0; i < ctx->minfo->nvars/2; i++) FLINT_SWAP(slong, degs[i], degs[ctx->minfo->nvars - i - 1]); TMP_END; } void nmod_mpolyu_repack_bits_inplace( nmod_mpolyu_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { slong i; if (bits == A->bits) return; A->bits = bits; for (i = 0; i < A->alloc; i++) nmod_mpoly_repack_bits_inplace(A->coeffs + i, bits, ctx); } /* if the coefficient doesn't exist, a new one is created (and set to zero) */ nmod_mpoly_struct * _nmod_mpolyu_get_coeff(nmod_mpolyu_t A, ulong pow, const nmod_mpoly_ctx_t uctx) { slong i, j; nmod_mpoly_struct * xk; for (i = 0; i < A->length && A->exps[i] >= pow; i++) { if (A->exps[i] == pow) { return A->coeffs + i; } } nmod_mpolyu_fit_length(A, A->length + 1, uctx); for (j = A->length; j > i; j--) { A->exps[j] = A->exps[j - 1]; nmod_mpoly_swap(A->coeffs + j, A->coeffs + j - 1, uctx); } A->length++; A->exps[i] = pow; xk = A->coeffs + i; xk->length = 0; FLINT_ASSERT(xk->bits == A->bits); return xk; } typedef struct { volatile slong index; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong length; nmod_mpoly_struct * coeffs; const nmod_mpoly_ctx_struct * ctx; } _sort_arg_struct; typedef _sort_arg_struct _sort_arg_t[1]; static void _worker_sort(void * varg) { _sort_arg_struct * arg = (_sort_arg_struct *) varg; slong i; get_next_index: #if FLINT_USES_PTHREAD pthread_mutex_lock(&arg->mutex); #endif i = arg->index; arg->index++; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&arg->mutex); #endif if (i >= arg->length) goto cleanup; nmod_mpoly_sort_terms(arg->coeffs + i, arg->ctx); goto get_next_index; cleanup: return; } /** 1 variables *************************************/ /* Convert B to A using the variable permutation perm. The uctx (m vars) should be the context of the coefficients of A. The ctx (n vars) should be the context of B. operation on each term: for 0 <= k < m + 1 l = perm[k] Aexp[k] = (Bexp[l] - shift[l])/stride[l] the most significant main variable uses k = 0 the coefficients of A use variables k = 1 ... m */ void nmod_mpoly_to_mpolyu_perm_deflate_threaded_pool( nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const thread_pool_handle * handles, slong num_handles) { slong i, j, k, l; slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong NA, NB; ulong * uexps; ulong * Bexps; nmod_mpoly_struct * Ac; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 1 <= n); TMP_START; uexps = (ulong *) TMP_ALLOC((m + 1)*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); nmod_mpolyu_zero(A, uctx); NA = mpoly_words_per_exp(A->bits, uctx->minfo); NB = mpoly_words_per_exp(B->bits, ctx->minfo); for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); for (k = 0; k < m + 1; k++) { l = perm[k]; FLINT_ASSERT(stride[l] != UWORD(0)); FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == UWORD(0)); uexps[k] = (Bexps[l] - shift[l]) / stride[l]; } Ac = _nmod_mpolyu_get_coeff(A, uexps[0], uctx); FLINT_ASSERT(Ac->bits == A->bits); nmod_mpoly_fit_length(Ac, Ac->length + 1, uctx); Ac->coeffs[Ac->length] = B->coeffs[j]; mpoly_set_monomial_ui(Ac->exps + NA*Ac->length, uexps + 1, A->bits, uctx->minfo); Ac->length++; } if (num_handles > 0) { _sort_arg_t arg; #if FLINT_USES_PTHREAD pthread_mutex_init(&arg->mutex, NULL); #endif arg->index = 0; arg->coeffs = A->coeffs; arg->length = A->length; arg->ctx = uctx; for (i = 0; i < num_handles; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, _worker_sort, arg); } _worker_sort(arg); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&arg->mutex); #endif } else { for (i = 0; i < A->length; i++) { nmod_mpoly_sort_terms(A->coeffs + i, uctx); } } TMP_END; } /* Convert B to A using the variable permutation vector perm. This function inverts nmod_mpoly_to_mpolyu_perm_deflate. A will be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k < m + 1 l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void nmod_mpoly_from_mpolyu_perm_inflate( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride) { slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong i, j, k, l; slong NA, NB; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * uexps; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 1 <= n); TMP_START; uexps = (ulong *) TMP_ALLOC((m + 1)*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, uctx->minfo); nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { nmod_mpoly_struct * Bc = B->coeffs + i; FLINT_ASSERT(Bc->bits == B->bits); _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, NA, Alen + Bc->length); for (j = 0; j < Bc->length; j++) { Acoeff[Alen + j] = Bc->coeffs[j]; mpoly_get_monomial_ui(uexps + 1, Bc->exps + NB*j, Bc->bits, uctx->minfo); uexps[0] = B->exps[i]; for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m + 1; k++) { l = perm[k]; Aexps[l] += stride[l]*uexps[k]; } mpoly_set_monomial_ui(Aexp + NA*(Alen + j), Aexps, Abits, ctx->minfo); } Alen += Bc->length; } A->coeffs = Acoeff; A->exps = Aexp; _nmod_mpoly_set_length(A, Alen, ctx); TMP_END; nmod_mpoly_sort_terms(A, ctx); } /** 0 variables *************************************/ void nmod_mpoly_to_mpolyl_perm_deflate( nmod_mpoly_t A, const nmod_mpoly_ctx_t lctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride) { slong j, k, l; slong m = lctx->minfo->nvars; slong n = ctx->minfo->nvars; slong NA, NB; ulong * lexps; ulong * Bexps; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; nmod_mpoly_fit_length(A, B->length, ctx); A->length = B->length; lexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(A->bits, lctx->minfo); NB = mpoly_words_per_exp(B->bits, ctx->minfo); for (j = 0; j < B->length; j++) { A->coeffs[j] = B->coeffs[j]; mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); for (k = 0; k < m; k++) { l = perm[k]; if (stride[l] == 1) { lexps[k] = (Bexps[l] - shift[l]); } else { FLINT_ASSERT(stride[l] != 0); FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == 0); lexps[k] = (Bexps[l] - shift[l]) / stride[l]; } } mpoly_set_monomial_ui(A->exps + NA*j, lexps, A->bits, lctx->minfo); } TMP_END; nmod_mpoly_sort_terms(A, lctx); FLINT_ASSERT(nmod_mpoly_is_canonical(A, lctx)); } /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k < m + 2 l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void nmod_mpoly_from_mpolyl_perm_inflate( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t lctx, const slong * perm, const ulong * shift, const ulong * stride) { slong n = ctx->minfo->nvars; slong m = lctx->minfo->nvars; slong i, k, l; slong NA, NB; ulong * Bexps; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, lctx->minfo); nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); A->length = B->length; for (i = 0; i < B->length; i++) { A->coeffs[i] = B->coeffs[i]; mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, lctx->minfo); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m; k++) { l = perm[k]; Aexps[l] += stride[l]*Bexps[k]; } mpoly_set_monomial_ui(A->exps + NA*i, Aexps, Abits, ctx->minfo); } TMP_END; nmod_mpoly_sort_terms(A, ctx); FLINT_ASSERT(nmod_mpoly_is_canonical(A, ctx)); } /** 2 variables *************************************/ /* Convert B to A using the variable permutation perm. The uctx should be the context of the coefficients of A. The ctx should be the context of B. operation on each term: for 0 <= k < m + 2 l = perm[k] Aexp[k] = (Bexp[l] - shift[l])/stride[l] the most significant main variable uses Aexp[0] the least significant main variable uses Aexp[1] the coefficients of A use variables Aexp[2], ..., Aexp[m + 1] maxexps if it exists is supposed to be a degree bound on B */ void nmod_mpoly_to_mpolyuu_perm_deflate_threaded_pool( nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const ulong * maxexps, /* nullptr is ok */ const thread_pool_handle * handles, slong num_handles) { slong i, j, k, l; slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong NA, NB; ulong * uexps; ulong * Bexps; nmod_mpoly_struct * Ac; TMP_INIT; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 2 <= n); nmod_mpolyu_zero(A, uctx); { TMP_START; uexps = (ulong *) TMP_ALLOC((m + 2)*sizeof(ulong)); Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(A->bits, uctx->minfo); NB = mpoly_words_per_exp(B->bits, ctx->minfo); for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); for (k = 0; k < m + 2; k++) { l = perm[k]; if (stride[l] == 1) { uexps[k] = (Bexps[l] - shift[l]); } else { FLINT_ASSERT(stride[l] != 0); FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == 0); uexps[k] = (Bexps[l] - shift[l]) / stride[l]; } } FLINT_ASSERT(FLINT_BIT_COUNT(uexps[0]) < FLINT_BITS/2); FLINT_ASSERT(FLINT_BIT_COUNT(uexps[1]) < FLINT_BITS/2); Ac = _nmod_mpolyu_get_coeff(A, (uexps[0] << (FLINT_BITS/2)) + uexps[1], uctx); FLINT_ASSERT(Ac->bits == A->bits); nmod_mpoly_fit_length(Ac, Ac->length + 1, uctx); Ac->coeffs[Ac->length] = B->coeffs[j]; mpoly_set_monomial_ui(Ac->exps + NA*Ac->length, uexps + 2, A->bits, uctx->minfo); Ac->length++; } for (i = 0; i < A->length; i++) { nmod_mpoly_sort_terms(A->coeffs + i, uctx); } TMP_END; } } /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k < m + 2 l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void nmod_mpoly_from_mpolyuu_perm_inflate( /* only for 2 main vars */ nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride) { slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong i, j, k, l; slong NA, NB; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * uexps; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 2 <= n); TMP_START; uexps = (ulong *) TMP_ALLOC((m + 2)*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, uctx->minfo); nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { nmod_mpoly_struct * Bc = B->coeffs + i; FLINT_ASSERT(Bc->bits == B->bits); _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, NA, Alen + Bc->length); for (j = 0; j < Bc->length; j++) { Acoeff[Alen + j] = Bc->coeffs[j]; mpoly_get_monomial_ui(uexps + 2, Bc->exps + NB*j, Bc->bits, uctx->minfo); uexps[0] = B->exps[i] >> (FLINT_BITS/2); uexps[1] = B->exps[i] & ((-UWORD(1)) >> (FLINT_BITS - FLINT_BITS/2)); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m + 2; k++) { l = perm[k]; Aexps[l] += stride[l]*uexps[k]; } mpoly_set_monomial_ui(Aexp + NA*(Alen + j), Aexps, Abits, ctx->minfo); } Alen += Bc->length; } A->coeffs = Acoeff; A->exps = Aexp; _nmod_mpoly_set_length(A, Alen, ctx); nmod_mpoly_sort_terms(A, ctx); TMP_END; } void nmod_mpolyu_shift_right(nmod_mpolyu_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { FLINT_ASSERT(A->exps[i] >= s); A->exps[i] -= s; } } void nmod_mpolyu_shift_left(nmod_mpolyu_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { A->exps[i] += s; } } void nmod_mpolyu_scalar_mul_nmod(nmod_mpolyu_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx) { slong i, j; for (i = 0; i < A->length; i++) { for (j = 0; j < (A->coeffs + i)->length; j++) { A->coeffs[i].coeffs[j] = nmod_mul(A->coeffs[i].coeffs[j], c, ctx->mod); } } } void nmod_mpolyu_set(nmod_mpolyu_t A, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx) { slong i; nmod_mpoly_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; slong Alen, Blen; Alen = 0; Blen = B->length; nmod_mpolyu_fit_length(A, Blen, uctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; for (i = 0; i < Blen; i++) { nmod_mpoly_set(Acoeff + Alen, Bcoeff + i, uctx); Aexp[Alen++] = Bexp[i]; } Alen = Blen; /* demote remaining coefficients */ for (i = Alen; i < A->length; i++) { nmod_mpoly_clear(Acoeff + i, uctx); nmod_mpoly_init(Acoeff + i, uctx); } A->length = Alen; } void nmod_mpoly_cvtfrom_poly_notmain(nmod_mpoly_t A, nmod_poly_t a, slong var, const nmod_mpoly_ctx_t ctx) { slong i; slong k; ulong * oneexp; slong N; TMP_INIT; TMP_START; FLINT_ASSERT(A->bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); oneexp = (ulong *)TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_sp(oneexp, var, A->bits, ctx->minfo); nmod_mpoly_fit_length(A, nmod_poly_length(a), ctx); k = 0; for (i = nmod_poly_length(a) - 1; i >= 0; i--) { mp_limb_t c = nmod_poly_get_coeff_ui(a, i); if (c != UWORD(0)) { A->coeffs[k] = c; mpoly_monomial_mul_ui(A->exps + N*k, oneexp, N, i); k++; } } A->length = k; TMP_END; } /* Set "A" to "a" where "a" is a polynomial in a non-main variable "var" */ void nmod_mpolyu_cvtfrom_poly_notmain(nmod_mpolyu_t A, nmod_poly_t a, slong var, const nmod_mpoly_ctx_t ctx) { nmod_mpolyu_fit_length(A, 1, ctx); A->exps[0] = 0; nmod_mpoly_cvtfrom_poly_notmain(A->coeffs + 0, a, var, ctx); A->length = !nmod_mpoly_is_zero(A->coeffs + 0, ctx); } /* Assuming that "A" depends only on the main variable, convert it to a poly "a". */ void nmod_mpolyu_cvtto_poly(nmod_poly_t a, nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx) { slong i; nmod_poly_zero(a); for (i = 0; i < A->length; i++) { FLINT_ASSERT((A->coeffs + i)->length == 1); FLINT_ASSERT(mpoly_monomial_is_zero((A->coeffs + i)->exps, mpoly_words_per_exp((A->coeffs + i)->bits, ctx->minfo))); nmod_poly_set_coeff_ui(a, A->exps[i], (A->coeffs + i)->coeffs[0]); } } /* Convert a poly "a" to "A" in the main variable, */ void nmod_mpolyu_cvtfrom_poly(nmod_mpolyu_t A, nmod_poly_t a, const nmod_mpoly_ctx_t ctx) { slong i; slong k; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); nmod_mpolyu_zero(A, ctx); k = 0; for (i = nmod_poly_length(a) - 1; i >= 0; i--) { mp_limb_t c = nmod_poly_get_coeff_ui(a, i); if (c != UWORD(0)) { nmod_mpolyu_fit_length(A, k + 1, ctx); A->exps[k] = i; nmod_mpoly_fit_length_reset_bits(A->coeffs + k, 1, A->bits, ctx); A->coeffs[k].coeffs[0] = c; A->coeffs[k].length = 1; mpoly_monomial_zero(A->coeffs[k].exps + N*0, N); k++; } } A->length = k; } void nmod_mpolyu_msub(nmod_mpolyu_t R, nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpoly_t c, slong e, const nmod_mpoly_ctx_t ctx) { slong i, j, k; nmod_mpoly_t T; nmod_mpolyu_fit_length(R, A->length + B->length, ctx); nmod_mpoly_init(T, ctx); i = j = k = 0; while (i < A->length || j < B->length) { if (i < A->length && (j >= B->length || A->exps[i] > B->exps[j] + e)) { /* only A ok */ nmod_mpoly_set(R->coeffs + k, A->coeffs + i, ctx); R->exps[k] = A->exps[i]; k++; i++; } else if (j < B->length && (i >= A->length || B->exps[j] + e > A->exps[i])) { /* only B ok */ nmod_mpoly_mul(R->coeffs + k, B->coeffs + j, c, ctx); nmod_mpoly_neg(R->coeffs + k, R->coeffs + k, ctx); R->exps[k] = B->exps[j] + e; k++; j++; } else if (i < A->length && j < B->length && (A->exps[i] == B->exps[j] + e)) { nmod_mpoly_mul(T, B->coeffs + j, c, ctx); nmod_mpoly_sub(R->coeffs + k, A->coeffs + i, T, ctx); R->exps[k] = A->exps[i]; k += !nmod_mpoly_is_zero(R->coeffs + k, ctx); i++; j++; } else { FLINT_ASSERT(0); } } nmod_mpoly_clear(T, ctx); R->length = k; } void nmod_mpolyu_divexact_mpoly_inplace(nmod_mpolyu_t A, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong * cmpmask; nmod_mpoly_t t; TMP_INIT; FLINT_ASSERT(bits == c->bits); FLINT_ASSERT(c->length > 0); if (nmod_mpoly_is_ui(c, ctx)) { if (c->coeffs[0] == 1) return; for (i = 0; i < A->length; i++) { nmod_mpoly_struct * Ai = A->coeffs + i; _nmod_vec_scalar_mul_nmod(Ai->coeffs, Ai->coeffs, Ai->length, nmod_inv(c->coeffs[0], ctx->mod), ctx->mod); } return; } nmod_mpoly_init3(t, 0, bits, ctx); TMP_START; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); for (i = A->length - 1; i >= 0; i--) { FLINT_ASSERT(A->coeffs[i].bits == bits); _nmod_mpoly_divides_monagan_pearce(t, A->coeffs[i].coeffs, A->coeffs[i].exps, A->coeffs[i].length, c->coeffs, c->exps, c->length, bits, N, cmpmask, ctx->mod); nmod_mpoly_swap(A->coeffs + i, t, ctx); FLINT_ASSERT(A->coeffs[i].length > 0); } TMP_END; nmod_mpoly_clear(t, ctx); } /* A = B * c and preserve the bit packing */ void nmod_mpolyu_mul_mpoly( nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong * cmpmask; TMP_INIT; TMP_START; bits = B->bits; FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(A->bits == c->bits); FLINT_ASSERT(A != B); nmod_mpolyu_fit_length(A, B->length, ctx); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); for (i = 0; i < B->length; i++) { nmod_mpoly_fit_length(A->coeffs + i, B->coeffs[i].length + c->length + 1, ctx); _nmod_mpoly_mul_johnson(A->coeffs + i, B->coeffs[i].coeffs, B->coeffs[i].exps, B->coeffs[i].length, c->coeffs, c->exps, c->length, bits, N, cmpmask, ctx->mod); FLINT_ASSERT(A->coeffs[i].length > 0); A->exps[i] = B->exps[i]; } A->length = B->length; TMP_END; } void nmod_mpolyu_mul_mpoly_inplace(nmod_mpolyu_t A, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong * cmpmask; nmod_mpoly_t t; TMP_INIT; FLINT_ASSERT(bits == c->bits); FLINT_ASSERT(c->length > 0); if (nmod_mpoly_is_ui(c, ctx)) { if (c->coeffs[0] == 1) return; for (i = 0; i < A->length; i++) { nmod_mpoly_struct * Ai = A->coeffs + i; _nmod_vec_scalar_mul_nmod(Ai->coeffs, Ai->coeffs, Ai->length, c->coeffs[0], ctx->mod); } return; } nmod_mpoly_init3(t, 0, bits, ctx); N = mpoly_words_per_exp(bits, ctx->minfo); TMP_START; cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); for (i = A->length - 1; i >= 0; i--) { FLINT_ASSERT(A->coeffs[i].bits == bits); _nmod_mpoly_mul_johnson(t, A->coeffs[i].coeffs, A->coeffs[i].exps, A->coeffs[i].length, c->coeffs, c->exps, c->length, bits, N, cmpmask, ctx->mod); nmod_mpoly_swap(A->coeffs + i, t, ctx); FLINT_ASSERT(A->coeffs[i].length > 0); } TMP_END; nmod_mpoly_clear(t, ctx); } int nmod_mpolyu_content_mpoly( nmod_mpoly_t g, const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx) { int success; success = _nmod_mpoly_vec_content_mpoly(g, A->coeffs, A->length, ctx); if (!success) nmod_mpoly_zero(g, ctx); nmod_mpoly_repack_bits_inplace(g, A->bits, ctx); return success; } flint-3.1.3/src/nmod_mpoly/mpolyu_divides.c000066400000000000000000000442161461254215100210060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" /* A = D - B*C */ slong _nmod_mpoly_mulsub1(nmod_mpoly_t A, const mp_limb_t * Dcoeff, const ulong * Dexp, slong Dlen, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeff, const ulong * Cexp, slong Clen, ulong maskhi, nmod_t fctx) { slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; mp_limb_t * Acoeff = A->coeffs; ulong * Aexp = A->exps; ulong exp; slong * hind; mp_limb_t acc0, acc1, acc2, pp1, pp0; TMP_INIT; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); TMP_START; next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; /* put (0, 0, Bexp[0] + Cexp[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Bexp[0] + Cexp[0], x); hind[0] = 2*1 + 0; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt1(Dexp[Di], exp, maskhi)) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, 1, Alen + 1); Aexp[Alen] = Dexp[Di]; Acoeff[Alen] = Dcoeff[Di]; Alen++; Di++; } _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, 1, Alen + 1); Aexp[Alen] = exp; acc0 = acc1 = acc2 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, 0, pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, 0, pp1, pp0); } } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(pp0, acc2, acc1, acc0, fctx); pp1 = 0; if (Di < Dlen && Dexp[Di] == exp) { pp1 = Dcoeff[Di]; Di++; } Acoeff[Alen] = nmod_sub(pp1, pp0, fctx); Alen += Acoeff[Alen] != 0; /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if ( (j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, maskhi); } } } FLINT_ASSERT(Di <= Dlen); if (Di < Dlen) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, 1, Alen + Dlen - Di); _nmod_vec_set(Acoeff + Alen, Dcoeff + Di, Dlen - Di); mpoly_copy_monomials(Aexp + 1*Alen, Dexp + 1*Di, Dlen - Di, 1); Alen += Dlen - Di; } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; TMP_END; return Alen; } /* A = D - B*C */ void _nmod_mpoly_mulsub(nmod_mpoly_t A, const mp_limb_t * Dcoeff, const ulong * Dexp, slong Dlen, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeff, const ulong * Cexp, slong Clen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, nmod_t fctx) { slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; mp_limb_t * Acoeff = A->coeffs; ulong * Aexp = A->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; mp_limb_t acc0, acc1, acc2, pp1, pp0; TMP_INIT; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); if (N == 1) { _nmod_mpoly_mulsub1(A, Dcoeff, Dexp, Dlen, Bcoeff, Bexp, Blen, Ccoeff, Cexp, Clen, cmpmask[0], fctx); return; } TMP_START; next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); exps = (ulong *) TMP_ALLOC(Blen*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(Blen*sizeof(ulong *)); for (i = 0; i < Blen; i++) exp_list[i] = exps + i*N; /* space for heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, Bexp[0] + Cexp[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; if (bits <= FLINT_BITS) mpoly_monomial_add(heap[1].exp, Bexp + N*0, Cexp + N*0, N); else mpoly_monomial_add_mp(heap[1].exp, Bexp + N*0, Cexp + N*0, N); hind[0] = 2*1 + 0; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt(Dexp + N*Di, exp, N, cmpmask)) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexp + N*Alen, Dexp + N*Di, N); Acoeff[Alen] = Dcoeff[Di]; Alen++; Di++; } _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexp + N*Alen, exp, N); acc0 = acc1 = acc2 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, 0, pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, 0, pp1, pp0); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(pp0, acc2, acc1, acc0, fctx); pp1 = 0; if (Di < Dlen && mpoly_monomial_equal(Dexp + N*Di, exp, N)) { pp1 = Dcoeff[Di]; Di++; } Acoeff[Alen] = nmod_sub(pp1, pp0, fctx); Alen += Acoeff[Alen] != 0; /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ( (j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } FLINT_ASSERT(Di <= Dlen); if (Di < Dlen) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + Dlen - Di); _nmod_vec_set(Acoeff + Alen, Dcoeff + Di, Dlen - Di); mpoly_copy_monomials(Aexp + N*Alen, Dexp + N*Di, Dlen - Di, N); Alen += Dlen - Di; } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; TMP_END; } /* Q = A/B return 1 if division was exact. nmainvars is the number of main vars. */ int nmod_mpolyuu_divides( nmod_mpolyu_t Q, const nmod_mpolyu_t A, const nmod_mpolyu_t B, slong nmainvars, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; nmod_mpoly_struct * Bcoeff = B->coeffs; slong Blen = B->length; ulong * Bexp = B->exps; nmod_mpoly_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; nmod_mpoly_struct * a, * b, * q; slong N; ulong * cmpmask; /* cmp mask for lesser variables */ nmod_mpoly_t T, S; int success; ulong maskhi = 0; /* main variables are in lex */ int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; ulong mask, exp, maxexp = Aexp[Alen - 1]; TMP_INIT; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == Q->bits); TMP_START; N = mpoly_words_per_exp(bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*Blen*sizeof(slong)); /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < B->length; i++) hind[i] = 1; /* mask with high bit set in each field of main exponent vector */ mask = 0; for (i = 0; i < nmainvars; i++) mask = (mask << (FLINT_BITS/nmainvars)) + (UWORD(1) << (FLINT_BITS/nmainvars - 1)); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexp[0], x); Q->length = 0; nmod_mpoly_init3(T, 16, bits, ctx); nmod_mpoly_init3(S, 16, bits, ctx); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) { goto not_exact_division; } nmod_mpolyu_fit_length(Q, Q->length + 1, ctx); lt_divides = mpoly_monomial_divides1(Q->exps + Q->length, exp, Bexp[0], mask); T->length = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { a = Acoeff + x->j; nmod_mpoly_fit_length(S, T->length + a->length, ctx); S->length = _nmod_mpoly_add( S->coeffs, S->exps, T->coeffs, T->exps, T->length, a->coeffs, a->exps, a->length, N, cmpmask, ctx->mod); } else { b = Bcoeff + x->i; q = Q->coeffs + x->j; _nmod_mpoly_mulsub(S, T->coeffs, T->exps, T->length, b->coeffs, b->exps, b->length, q->coeffs, q->exps, q->length, bits, N, cmpmask, ctx->mod); } nmod_mpoly_swap(S, T, ctx); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexp[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == Q->length) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } } } if (T->length == 0) { continue; } if (mpoly_monomials_overflow_test(T->exps, T->length, bits, ctx->minfo)) { goto not_exact_division; } q = Q->coeffs + Q->length; FLINT_ASSERT(q->bits == bits); b = Bcoeff + 0; if (!_nmod_mpoly_divides_monagan_pearce(q, T->coeffs, T->exps, T->length, b->coeffs, b->exps, b->length, bits, N, cmpmask, ctx->mod)) { goto not_exact_division; } if (!lt_divides || (exp^maskhi) < (maxexp^maskhi)) { goto not_exact_division; } /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Q->length; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; Q->length++; } success = 1; cleanup: nmod_mpoly_clear(T, ctx); nmod_mpoly_clear(S, ctx); TMP_END; return success; not_exact_division: success = 0; Q->length = 0; goto cleanup; } flint-3.1.3/src/nmod_mpoly/mpolyu_gcdp_zippel.c000066400000000000000000001065361461254215100216630ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" /* store in each coefficient the evaluation of the corresponding monomial */ void nmod_mpoly_evalsk(nmod_mpoly_t A, nmod_mpoly_t B, slong entries, slong * offs, ulong * masks, mp_limb_t * powers, const nmod_mpoly_ctx_t ctx) { slong i, j; slong N; FLINT_ASSERT(A->bits == B->bits); nmod_mpoly_fit_length(A, B->length, ctx); N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < B->length; i++) { mp_limb_t prod = UWORD(1); for (j = 0; j < entries; j++) { if ((B->exps + N*i)[offs[j]] & masks[j]) { prod = nmod_mul(prod, powers[j], ctx->mod); } } A->coeffs[i] = prod; mpoly_monomial_set(A->exps + N*i, B->exps + N*i, N); } A->length = B->length; } void nmod_mpolyu_evalsk(nmod_mpolyu_t A, nmod_mpolyu_t B, slong entries, slong * offs, ulong * masks, mp_limb_t * powers, const nmod_mpoly_ctx_t ctx) { slong i; nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { A->exps[i] = B->exps[i]; nmod_mpoly_evalsk(A->coeffs + i, B->coeffs + i, entries, offs, masks, powers, ctx); } A->length = B->length; } /* multiply the coefficients of A pointwise by those of B */ void nmod_mpolyu_mulsk(nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx) { slong i, j; FLINT_ASSERT(A->length == B->length); for (i = 0; i < A->length; i++) { FLINT_ASSERT(A->exps[i] == B->exps[i]); FLINT_ASSERT((A->coeffs + i)->length == (B->coeffs + i)->length); for (j = 0; j < (A->coeffs + i)->length; j++) { (A->coeffs + i)->coeffs[j] = nmod_mul((A->coeffs + i)->coeffs[j], (B->coeffs + i)->coeffs[j], ctx->mod); } } } /* return 0 if the leading coeff of A vanishes else return 1 */ int nmod_mpolyu_evalfromsk(nmod_poly_t e, nmod_mpolyu_t A, nmod_mpolyu_t SK, const nmod_mpoly_ctx_t ctx) { slong i, j; int ret = 0; FLINT_ASSERT(A->length == SK->length); nmod_poly_zero(e); for (i = 0; i < A->length; i++) { mp_limb_t v, pp0, pp1, ac0 = 0, ac1 = 0, ac2 = 0; FLINT_ASSERT((A->coeffs + i)->length == (SK->coeffs + i)->length); for (j = 0; j < (A->coeffs + i)->length; j++) { umul_ppmm(pp1, pp0, (A->coeffs + i)->coeffs[j], (SK->coeffs + i)->coeffs[j]); add_sssaaaaaa(ac2, ac1, ac0, ac2, ac1, ac0, WORD(0), pp1, pp0); } NMOD_RED3(v, ac2, ac1, ac0, ctx->mod); nmod_poly_set_coeff_ui(e, A->exps[i], v); ret |= (i == 0 && v != 0); } return ret; } /* solve [ a[0] a[1] ... a[n-1] ] [ x[0] ] [ b[0] ] [ a[0]^2 a[1]^2 ... a[n-1]^2 ] [ x[1] ] [ b[1] ] [ ... ... ] . [ ... ] = [ ... ] [ a[0]^n a[1]^n ... a[n-1]^n ] [ x[n-1] ] [ b[n-1] ] for x */ int nmod_vandsolve(mp_limb_t * x, mp_limb_t * a, mp_limb_t * b, slong n, nmod_t mod) { int success = 0; slong i, j; mp_limb_t t; mp_limb_t Dinv; nmod_poly_t Q, P, R, u; for (i = 0; i < n; i++) x[i] = 0; nmod_poly_init(Q, mod.n); nmod_poly_init(P, mod.n); nmod_poly_init(R, mod.n); nmod_poly_init(u, mod.n); nmod_poly_set_coeff_ui(u, 1, 1); nmod_poly_product_roots_nmod_vec(P, a, n); for (i = 0; i < n; i++) { if (a[i] == UWORD(0)) goto cleanup; nmod_poly_set_coeff_ui(u, 0, mod.n - a[i]); nmod_poly_divrem(Q, R, P, u); t = nmod_mul(a[i], nmod_poly_evaluate_nmod(Q, a[i]), mod); if (t == UWORD(0)) goto cleanup; Dinv = nmod_inv(t, mod); for (j = 0; j < n; j++) { t = nmod_mul(b[j], Dinv, mod); t = nmod_mul(t, nmod_poly_get_coeff_ui(Q, j), mod); x[i] = nmod_add(x[i], t, mod); } } success = 1; cleanup: nmod_poly_clear(Q); nmod_poly_clear(P); nmod_poly_clear(R); nmod_poly_clear(u); return success; } /* Try to set G to the gcd of A and B given the form f of G. return codes as enumerated in nmod_mpoly.h: nmod_gcds_success, nmod_gcds_form_wrong, nmod_gcds_no_solution, nmod_gcds_scales_not_found, nmod_gcds_eval_point_not_found, nmod_gcds_eval_gcd_deg_too_high */ nmod_gcds_ret_t nmod_mpolyu_gcds_zippel(nmod_mpolyu_t G, nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpolyu_t f, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t randstate, slong * degbound) { int eval_points_tried; nmod_gcds_ret_t success; nmod_mpolyu_t Aevalsk1, Bevalsk1, fevalsk1, Aevalski, Bevalski, fevalski; nmod_poly_t Aeval, Beval, Geval; mp_limb_t * alpha, * b; nmod_mat_struct * M, * ML; nmod_mat_t MF, Msol; int lc_ok; int underdeterminedcount = 0; int exceededcount = 0; int * ML_is_initialized; slong i, j, k, s, S, nullity; slong * d; slong l; mp_limb_t * W; slong entries; slong * offs; ulong * masks; mp_limb_t * powers; TMP_INIT; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(f->length > 0); FLINT_ASSERT(A->bits == B->bits); FLINT_ASSERT(A->bits == G->bits); FLINT_ASSERT(A->bits == f->bits); FLINT_ASSERT(var >= 0); FLINT_ASSERT(*degbound == f->exps[0]); FLINT_ASSERT(var > 0); if (f->length == 1) { if ((f->coeffs + 0)->length > 1) { /* impossible to find scale factors in this case */ return nmod_gcds_scales_not_found; } else { /* otherwise set the coeff of the monomial to one */ nmod_gcds_ret_t ret; FLINT_ASSERT((f->coeffs + 0)->length == 1); nmod_mpolyu_set(G, f, ctx); (G->coeffs + 0)->coeffs[0] = UWORD(1); nmod_mpolyu_init(Aevalsk1, f->bits, ctx); ret = nmod_gcds_form_wrong; if ( nmod_mpolyuu_divides(Aevalsk1, A, G, 1, ctx) && nmod_mpolyuu_divides(Aevalsk1, B, G, 1, ctx)) { ret = nmod_gcds_success; } nmod_mpolyu_clear(Aevalsk1, ctx); return ret; } } TMP_START; nmod_mpolyu_init(Aevalsk1, f->bits, ctx); nmod_mpolyu_init(Bevalsk1, f->bits, ctx); nmod_mpolyu_init(fevalsk1, f->bits, ctx); nmod_mpolyu_init(Aevalski, f->bits, ctx); nmod_mpolyu_init(Bevalski, f->bits, ctx); nmod_mpolyu_init(fevalski, f->bits, ctx); nmod_poly_init(Aeval, ctx->mod.n); nmod_poly_init(Beval, ctx->mod.n); nmod_poly_init(Geval, ctx->mod.n); d = (slong *) TMP_ALLOC(f->length*sizeof(slong)); for (i = 0; i < f->length; i++) { d[i] = i; } /* make d sort the coeffs so that (f->coeffs + d[j-1])->length <= (f->coeffs + d[j-0])->length for all j */ for (i = 1; ilength; i++) { for (j=i; j > 0 && (f->coeffs + d[j-1])->length > (f->coeffs + d[j-0])->length; j--) { slong temp = d[j-1]; d[j-1] = d[j-0]; d[j-0] = temp; } } /* l is the number of images we will try to construct */ l = f->length - 3; for (i = 0; i < f->length; i++) { l += (f->coeffs + i)->length; } l = l / (f->length - 1); l = FLINT_MAX(l, (f->coeffs + d[f->length - 1])->length); /* one extra test image */ l += 1; alpha = (mp_limb_t *) TMP_ALLOC(var*sizeof(mp_limb_t)); ML = (nmod_mat_struct *) TMP_ALLOC(f->length*sizeof(nmod_mat_struct)); b = (mp_limb_t *) TMP_ALLOC((f->coeffs + d[f->length - 1])->length *sizeof(mp_limb_t)); nmod_mat_init(MF, 0, l, ctx->mod.n); M = (nmod_mat_struct *) TMP_ALLOC(f->length*sizeof(nmod_mat_struct)); ML_is_initialized = (int *) TMP_ALLOC(f->length*sizeof(int)); for (i = 0; i < f->length; i++) { nmod_mat_init(M + i, l, (f->coeffs + i)->length, ctx->mod.n); ML_is_initialized[i] = 0; } W = (mp_limb_t *) flint_malloc(l*f->length*sizeof(mp_limb_t)); nmod_mat_init(Msol, l, 1, ctx->mod.n); /* compute how many masks are needed */ entries = f->bits * var; offs = (slong *) TMP_ALLOC(entries*sizeof(slong)); masks = (ulong *) TMP_ALLOC(entries*sizeof(slong)); powers = (mp_limb_t *) TMP_ALLOC(entries*sizeof(mp_limb_t)); /***** evaluation loop head *******/ eval_points_tried = 0; pick_evaluation_point: if (++eval_points_tried > 10) { success = nmod_gcds_eval_point_not_found; goto finished; } /* avoid 0, 1 and -1 for the evaluation points */ FLINT_ASSERT(ctx->mod.n > UWORD(3)); for (i = 0; i < var; i++) alpha[i] = UWORD(2) + n_randint(randstate, ctx->mod.n - UWORD(3)); /* store bit masks for each power of two of the non-main variables */ for (i = 0; i < var; i++) { slong shift, off; mpoly_gen_offset_shift_sp(&off, &shift, i, f->bits, ctx->minfo); for (j = 0; j < f->bits; j++) { offs[f->bits*i + j] = off; masks[f->bits*i + j] = UWORD(1) << (j + shift); if (j == 0) powers[f->bits*i + j] = alpha[i]; else powers[f->bits*i + j] = nmod_mul(powers[f->bits*i + j-1], powers[f->bits*i + j-1], ctx->mod); } } nmod_mpolyu_evalsk(Aevalsk1, A, entries, offs, masks, powers, ctx); nmod_mpolyu_evalsk(Bevalsk1, B, entries, offs, masks, powers, ctx); nmod_mpolyu_evalsk(fevalsk1, f, entries, offs, masks, powers, ctx); for (i = 0; i < l*f->length; i++) { W[i] = 0; } for (i = 0; i < l; i++) { if (i == 0) { nmod_mpolyu_set(Aevalski, Aevalsk1, ctx); nmod_mpolyu_set(Bevalski, Bevalsk1, ctx); nmod_mpolyu_set(fevalski, fevalsk1, ctx); } else { nmod_mpolyu_mulsk(Aevalski, Aevalsk1, ctx); nmod_mpolyu_mulsk(Bevalski, Bevalsk1, ctx); nmod_mpolyu_mulsk(fevalski, fevalsk1, ctx); } for (j = 0; j < f->length; j++) { for (k = 0; k < (f->coeffs + j)->length; k++) { (M + j)->rows[i][k] = (fevalski->coeffs + j)->coeffs[k]; } } lc_ok = 1; lc_ok = lc_ok && nmod_mpolyu_evalfromsk(Aeval, A, Aevalski, ctx); lc_ok = lc_ok && nmod_mpolyu_evalfromsk(Beval, B, Bevalski, ctx); if (!lc_ok) { /* lc of A or B vanished */ goto pick_evaluation_point; } nmod_poly_gcd(Geval, Aeval, Beval); if (f->exps[0] < nmod_poly_degree(Geval)) { ++exceededcount; if (exceededcount < 2) goto pick_evaluation_point; success = nmod_gcds_eval_gcd_deg_too_high; goto finished; } if (f->exps[0] > nmod_poly_degree(Geval)) { success = nmod_gcds_form_main_degree_too_high; *degbound = nmod_poly_degree(Geval); goto finished; } k = nmod_poly_length(Geval); j = WORD(0); while ((--k) >= 0) { mp_limb_t ck = nmod_poly_get_coeff_ui(Geval, k); if (ck != UWORD(0)) { while (j < f->length && f->exps[j] > k) { j++; } if (j >= f->length || f->exps[j] != k) { success = nmod_gcds_form_wrong; goto finished; } W[l*j + i] = ck; } } } nullity = -1; nmod_mat_clear(MF); nmod_mat_init(MF, 0, l, ctx->mod.n); for (S = 0; S < f->length; S++) { s = d[S]; if (!ML_is_initialized[s]) { nmod_mat_init(ML + s, l, (f->coeffs + s)->length + l, ctx->mod.n); ML_is_initialized[s] = 1; for (i = 0; i < l; i++) { for (j = 0; j < (f->coeffs + s)->length; j++) { (ML + s)->rows[i][j] = (M + s)->rows[i][j]; } (ML + s)->rows[i][(f->coeffs + s)->length + i] = W[l*s + i]; } } else { for (i = 0; i < l; i++) { for (j = 0; j < (f->coeffs + s)->length; j++) { (ML + s)->rows[i][j] = (M + s)->rows[i][j]; } for (j = 0; j < l; j++) { (ML + s)->rows[i][(f->coeffs + s)->length + j] = (j==i ? W[l*s + i] : UWORD(0)); } } } nmod_mat_rref(ML + s); for (i = 0; i < (f->coeffs + s)->length; i++) { if ((ML + s)->rows[i][i] != UWORD(1)) { /* evaluation points produced a singular vandermonde matrix */ goto pick_evaluation_point; } } { /* appends rows to MF */ nmod_mat_t MFtemp; nmod_mat_t Mwindow; nmod_mat_window_init(Mwindow, ML + s, (f->coeffs + s)->length, (f->coeffs + s)->length, l, (f->coeffs + s)->length + l); nmod_mat_init(MFtemp, nmod_mat_nrows(MF) + l - (f->coeffs + s)->length, l, ctx->mod.n); nmod_mat_concat_vertical(MFtemp, MF, Mwindow); nmod_mat_swap(MFtemp, MF); nmod_mat_clear(MFtemp); nmod_mat_window_clear(Mwindow); } nullity = l - nmod_mat_rref(MF); if (nullity == 0) { /* There is no solution for scale factors. Form f must be wrong */ success = nmod_gcds_form_wrong; goto finished; } if (nullity == 1) { /* There is one solution for scale factors based on equations considered thus far. Accept this as a solution and perform checks of the remaining equations at the end. */ break; } } if (nullity != 1) { ++underdeterminedcount; if (underdeterminedcount < 2) goto pick_evaluation_point; success = nmod_gcds_scales_not_found; goto finished; } nullity = nmod_mat_nullspace(Msol, MF); FLINT_ASSERT(nullity == 1); nmod_mpolyu_setform(G, f, ctx); for (i = 0; i < f->length; i++) { for (j = 0; j < (f->coeffs + i)->length; j++) { FLINT_ASSERT((f->coeffs + i)->length <= l); b[j] = nmod_mul(W[l*i + j], nmod_mat_get_entry(Msol, j, 0), ctx->mod); } success = nmod_vandsolve((G->coeffs + i)->coeffs, (fevalsk1->coeffs + i)->coeffs, b, (f->coeffs + i)->length, ctx->mod); if (!success) { /* evaluation points produced a singular vandermonde matrix */ goto pick_evaluation_point; } } /* check solution */ for (s = 0; s < f->length; s++) { mp_limb_t pp0, pp1, ac0, ac1, ac2, u, v; for (i = 0; i < l; i++) { ac0 = ac1 = ac2 = 0; for (j = 0; j < (f->coeffs + s)->length; j++) { umul_ppmm(pp1, pp0, (M + s)->rows[i][j], (G->coeffs + s)->coeffs[j]); add_sssaaaaaa(ac2, ac1, ac0, ac2, ac1, ac0, WORD(0), pp1, pp0); } NMOD_RED3(v, ac2, ac1, ac0, ctx->mod); u = nmod_mul(W[l*s + i], nmod_mat_get_entry(Msol, i, 0), ctx->mod); if (v != u) { success = nmod_gcds_no_solution; goto finished; } } } success = nmod_gcds_success; finished: flint_free(W); nmod_mat_clear(MF); nmod_mat_clear(Msol); for (i = 0; i < f->length; i++) { nmod_mat_clear(M + i); if (ML_is_initialized[i]) { nmod_mat_clear(ML + i); } } nmod_mpolyu_clear(Aevalsk1, ctx); nmod_mpolyu_clear(Bevalsk1, ctx); nmod_mpolyu_clear(fevalsk1, ctx); nmod_mpolyu_clear(Aevalski, ctx); nmod_mpolyu_clear(Bevalski, ctx); nmod_mpolyu_clear(fevalski, ctx); nmod_poly_clear(Aeval); nmod_poly_clear(Beval); nmod_poly_clear(Geval); TMP_END; return success; } static int nmod_mpolyu_gcdp_zippel_univar( nmod_mpolyu_t G, nmod_mpolyu_t Abar, nmod_mpolyu_t Bbar, nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx) { nmod_poly_t a, b, g, t; FLINT_ASSERT(A->bits == B->bits); nmod_poly_init_mod(a, ctx->mod); nmod_poly_init_mod(b, ctx->mod); nmod_poly_init_mod(g, ctx->mod); nmod_poly_init_mod(t, ctx->mod); nmod_mpolyu_cvtto_poly(a, A, ctx); nmod_mpolyu_cvtto_poly(b, B, ctx); nmod_poly_gcd(g, a, b); nmod_mpolyu_cvtfrom_poly(G, g, ctx); nmod_poly_divexact(t, a, g); nmod_mpolyu_cvtfrom_poly(Abar, t, ctx); nmod_poly_divexact(t, b, g); nmod_mpolyu_cvtfrom_poly(Bbar, t, ctx); nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(t); return 1; } static int nmod_mpolyu_gcdp_zippel_univar_no_cofactors( nmod_mpolyu_t G, nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx) { nmod_poly_t a, b, g; FLINT_ASSERT(A->bits == B->bits); nmod_poly_init_mod(a, ctx->mod); nmod_poly_init_mod(b, ctx->mod); nmod_poly_init_mod(g, ctx->mod); nmod_poly_init_mod(g, ctx->mod); nmod_mpolyu_cvtto_poly(a, A, ctx); nmod_mpolyu_cvtto_poly(b, B, ctx); nmod_poly_gcd(g, a, b); nmod_mpolyu_cvtfrom_poly(G, g, ctx); nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); return 1; } int nmod_mpolyu_gcdp_zippel_bivar( nmod_mpolyu_t G, nmod_mpolyu_t Abar, nmod_mpolyu_t Bbar, nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx) { slong var = 0; slong Alastdeg; slong Blastdeg; ulong Ashift, Bshift, Gshift; slong lastdeg; slong bound; int success = 0, changed, have_enough; n_poly_t a, b, c, g, modulus, tempmod; nmod_mpolyu_t Aeval, Beval, Geval; nmod_mpolyun_t An, Bn, H, Ht; mp_limb_t geval, temp, alpha; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(var >= -WORD(1)); FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(G->bits == B->bits); nmod_mpolyun_init(An, A->bits, ctx); nmod_mpolyun_init(Bn, A->bits, ctx); nmod_mpolyu_cvtto_mpolyun(An, A, var, ctx); nmod_mpolyu_cvtto_mpolyun(Bn, B, var, ctx); FLINT_ASSERT(An->length > 0); FLINT_ASSERT(Bn->length > 0); Ashift = A->exps[A->length - 1]; Bshift = B->exps[B->length - 1]; Gshift = FLINT_MIN(Ashift, Bshift); nmod_mpolyun_shift_right(An, Ashift); nmod_mpolyun_shift_right(Bn, Bshift); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(g); /* if the gcd has content wrt last variable, we are going to fail */ nmod_mpolyun_content_last(a, An, ctx); nmod_mpolyun_content_last(b, Bn, ctx); nmod_mpolyun_divexact_last(An, a, ctx); nmod_mpolyun_divexact_last(Bn, b, ctx); n_poly_mod_gcd(c, a, b, ctx->mod); n_poly_mod_gcd(g, nmod_mpolyun_leadcoeff_poly(An, ctx), nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->mod); Alastdeg = nmod_mpolyun_lastdeg(An, ctx); Blastdeg = nmod_mpolyun_lastdeg(Bn, ctx); /* bound of the number of images required */ bound = 1 + FLINT_MIN(Alastdeg, Blastdeg) + n_poly_degree(g); n_poly_init(modulus); n_poly_init(tempmod); n_poly_set_coeff(tempmod, 1, UWORD(1)); nmod_mpolyu_init(Aeval, A->bits, ctx); nmod_mpolyu_init(Beval, A->bits, ctx); nmod_mpolyu_init(Geval, A->bits, ctx); nmod_mpolyun_init(H, A->bits, ctx); nmod_mpolyun_init(Ht, A->bits, ctx); /* fail if the gcd has content wrt last variable */ if (n_poly_degree(c) > 0) { success = 0; goto finished; } n_poly_one(modulus); nmod_mpolyun_zero(H, ctx); alpha = ctx->mod.n; while (1) { if (alpha == 0) { success = 0; goto finished; } alpha--; /* make sure evaluation point does not kill both lc(A) and lc(B) */ geval = n_poly_mod_evaluate_nmod(g, alpha, ctx->mod); if (geval == WORD(0)) goto outer_continue; /* make sure evaluation point does not kill either A or B */ nmod_mpolyun_interp_reduce_sm_mpolyu(Aeval, An, alpha, ctx); nmod_mpolyun_interp_reduce_sm_mpolyu(Beval, Bn, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) goto outer_continue; nmod_mpolyu_gcdp_zippel_univar_no_cofactors(Geval, Aeval, Beval, ctx); if (nmod_mpolyu_is_one(Geval, ctx)) { nmod_mpolyu_one(G, ctx); nmod_mpolyu_swap(Abar, A, ctx); nmod_mpolyu_swap(Bbar, B, ctx); nmod_mpolyu_shift_left(G, Gshift); nmod_mpolyu_shift_left(Abar, Ashift - Gshift); nmod_mpolyu_shift_left(Bbar, Bshift - Gshift); success = 1; goto finished; } FLINT_ASSERT(Geval->length > 0); if (n_poly_degree(modulus) > 0) { if (Geval->exps[0] > H->exps[0]) { goto outer_continue; } else if (Geval->exps[0] < H->exps[0]) { n_poly_one(modulus); } } temp = n_invmod(nmod_mpolyu_leadcoeff(Geval, ctx), ctx->mod.n); temp = nmod_mul(geval, temp, ctx->mod); nmod_mpolyu_scalar_mul_nmod(Geval, temp, ctx); /* update interpolant H */ if (n_poly_degree(modulus) > 0) { mp_limb_t t = n_poly_mod_evaluate_nmod(modulus, alpha, ctx->mod); t = nmod_inv(t, ctx->mod); _n_poly_mod_scalar_mul_nmod_inplace(modulus, t, ctx->mod); changed = nmod_mpolyun_interp_crt_sm_mpolyu(&lastdeg, H, Ht, Geval, modulus, alpha, ctx); n_poly_set_coeff(tempmod, 0, ctx->mod.n - alpha); n_poly_mod_mul(modulus, modulus, tempmod, ctx->mod); have_enough = n_poly_degree(modulus) >= bound; if (changed && !have_enough) { goto outer_continue; } if (!changed || have_enough) { nmod_mpolyun_content_last(a, H, ctx); nmod_mpolyun_mul_poly(Ht, H, c, ctx); nmod_mpolyun_divexact_last(Ht, a, ctx); nmod_mpolyun_shift_left(Ht, Gshift); nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { n_poly_one(modulus); goto outer_continue; } } else { nmod_mpolyun_interp_lift_sm_mpolyu(H, Geval, ctx); n_poly_set_coeff(tempmod, 0, ctx->mod.n - alpha); n_poly_mod_mul(modulus, modulus, tempmod, ctx->mod); } outer_continue:; } finished: n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(g); n_poly_clear(modulus); n_poly_clear(tempmod); nmod_mpolyu_clear(Aeval, ctx); nmod_mpolyu_clear(Beval, ctx); nmod_mpolyu_clear(Geval, ctx); nmod_mpolyun_clear(An, ctx); nmod_mpolyun_clear(Bn, ctx); nmod_mpolyun_clear(H, ctx); nmod_mpolyun_clear(Ht, ctx); return success; } int nmod_mpolyu_gcdp_zippel( nmod_mpolyu_t G, nmod_mpolyu_t Abar, nmod_mpolyu_t Bbar, nmod_mpolyu_t A, nmod_mpolyu_t B, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t randstate) { slong lastdeg; slong Alastdeg; slong Blastdeg; ulong Ashift, Bshift, Gshift; slong degbound; slong bound; int success = 0, changed, have_enough; nmod_mpolyun_t An, Bn; n_poly_t a, b, c, g; n_poly_t modulus, tempmod; nmod_mpolyu_t Aeval, Beval, Geval, Abareval, Bbareval, Gform; nmod_mpolyun_t H, Ht; mp_limb_t geval, temp; mp_limb_t alpha, start_alpha; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(var >= -WORD(1)); FLINT_ASSERT(G->bits == A->bits); FLINT_ASSERT(G->bits == B->bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (var == -WORD(1)) { /* no more variables left to interpolate */ return nmod_mpolyu_gcdp_zippel_univar(G, Abar, Bbar, A, B, ctx); } if (var == WORD(0)) { /* bivariate is more comfortable separated */ return nmod_mpolyu_gcdp_zippel_bivar(G, Abar, Bbar, A, B, ctx); } nmod_mpolyun_init(An, A->bits, ctx); nmod_mpolyun_init(Bn, A->bits, ctx); nmod_mpolyu_cvtto_mpolyun(An, A, var, ctx); nmod_mpolyu_cvtto_mpolyun(Bn, B, var, ctx); Ashift = A->exps[A->length - 1]; Bshift = B->exps[B->length - 1]; Gshift = FLINT_MIN(Ashift, Bshift); nmod_mpolyun_shift_right(An, Ashift); nmod_mpolyun_shift_right(Bn, Bshift); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(g); /* if the gcd has content wrt last variable, we are going to fail */ nmod_mpolyun_content_last(a, An, ctx); nmod_mpolyun_content_last(b, Bn, ctx); nmod_mpolyun_divexact_last(An, a, ctx); nmod_mpolyun_divexact_last(Bn, b, ctx); n_poly_mod_gcd(c, a, b, ctx->mod); n_poly_mod_gcd(g, nmod_mpolyun_leadcoeff_poly(An, ctx), nmod_mpolyun_leadcoeff_poly(Bn, ctx), ctx->mod); Alastdeg = nmod_mpolyun_lastdeg(An, ctx); Blastdeg = nmod_mpolyun_lastdeg(Bn, ctx); /* bound of the number of images required */ bound = 1 + FLINT_MIN(Alastdeg, Blastdeg) + n_poly_degree(g); /* degree bound on the gcd */ degbound = FLINT_MIN(A->exps[0], B->exps[0]); n_poly_init(modulus); n_poly_init(tempmod); n_poly_set_coeff(tempmod, 1, UWORD(1)); nmod_mpolyu_init(Aeval, A->bits, ctx); nmod_mpolyu_init(Beval, A->bits, ctx); nmod_mpolyu_init(Geval, A->bits, ctx); nmod_mpolyu_init(Abareval, A->bits, ctx); nmod_mpolyu_init(Bbareval, A->bits, ctx); nmod_mpolyu_init(Gform, A->bits, ctx); nmod_mpolyun_init(H, A->bits, ctx); nmod_mpolyun_init(Ht, A->bits, ctx); /* fail if the gcd has content wrt last variable */ if (n_poly_degree(c) > 0) { success = 0; goto finished; } if (ctx->mod.n <= UWORD(3)) { success = 0; goto finished; } n_poly_one(modulus); nmod_mpolyun_zero(H, ctx); start_alpha = UWORD(1) + n_randint(randstate, ctx->mod.n - UWORD(1)); alpha = start_alpha; while (1) { /* get new evaluation point */ --alpha; if (alpha == 0) { alpha = ctx->mod.n - UWORD(1); } if (alpha == start_alpha) { success = 0; goto finished; } /* make sure evaluation point does not kill both lc(A) and lc(B) */ geval = n_poly_mod_evaluate_nmod(g, alpha, ctx->mod); if (geval == 0) { goto outer_continue; } /* make sure evaluation point does not kill either A or B */ nmod_mpolyun_interp_reduce_sm_mpolyu(Aeval, An, alpha, ctx); nmod_mpolyun_interp_reduce_sm_mpolyu(Beval, Bn, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) { goto outer_continue; } success = nmod_mpolyu_gcdp_zippel(Geval, Abareval, Bbareval, Aeval, Beval, var - 1, ctx, randstate); if (!success || Geval->exps[0] > degbound) { success = 0; goto finished; } degbound = Geval->exps[0]; if (nmod_mpolyu_is_one(Geval, ctx)) { nmod_mpolyu_one(G, ctx); nmod_mpolyu_swap(Abar, A, ctx); nmod_mpolyu_swap(Bbar, B, ctx); nmod_mpolyu_shift_left(G, Gshift); nmod_mpolyu_shift_left(Abar, Ashift - Gshift); nmod_mpolyu_shift_left(Bbar, Bshift - Gshift); success = 1; goto finished; } if (n_poly_degree(modulus) > 0) { if (Geval->exps[0] > H->exps[0]) { goto outer_continue; } else if (Geval->exps[0] < H->exps[0]) { n_poly_one(modulus); } } /* update interpolant H */ temp = nmod_inv(nmod_mpolyu_leadcoeff(Geval, ctx), ctx->mod); temp = nmod_mul(geval, temp, ctx->mod); nmod_mpolyu_scalar_mul_nmod(Geval, temp, ctx); if (n_poly_degree(modulus) > 0) { temp = n_poly_mod_evaluate_nmod(modulus, alpha, ctx->mod); temp = n_invmod(temp, ctx->mod.n); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, ctx->mod); changed = nmod_mpolyun_interp_crt_sm_mpolyu(&lastdeg, H, Ht, Geval, modulus, alpha, ctx); if (!changed) { nmod_mpolyun_content_last(a, H, ctx); nmod_mpolyun_mul_poly(Ht, H, c, ctx); nmod_mpolyun_divexact_last(Ht, a, ctx); nmod_mpolyun_shift_left(Ht, Gshift); nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( !nmod_mpolyuu_divides(Abar, A, G, 1, ctx) || !nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { goto outer_continue; } success = 1; goto finished; } } else { nmod_mpolyun_interp_lift_sm_mpolyu(H, Geval, ctx); } n_poly_set_coeff(tempmod, 0, ctx->mod.n - alpha); n_poly_mod_mul(modulus, modulus, tempmod, ctx->mod); nmod_mpolyu_setform_mpolyun(Gform, H, ctx); while (1) { /* get new evaluation point */ --alpha; if (alpha == 0) { alpha = ctx->mod.n - UWORD(1); } if (alpha == start_alpha) { success = 0; goto finished; } /* make sure evaluation does not kill both lc(A) and lc(B) */ geval = n_poly_mod_evaluate_nmod(g, alpha, ctx->mod); if (geval == WORD(0)) { goto inner_continue; } /* make sure evaluation does not kill either A or B */ nmod_mpolyun_interp_reduce_sm_mpolyu(Aeval, An, alpha, ctx); nmod_mpolyun_interp_reduce_sm_mpolyu(Beval, Bn, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) { goto inner_continue; } switch (nmod_mpolyu_gcds_zippel(Geval, Aeval, Beval, Gform, var, ctx, randstate, °bound)) { default: FLINT_ASSERT(0); case nmod_gcds_form_main_degree_too_high: /* nmod_mpolyu_gcds_zippel has updated degbound */ n_poly_one(modulus); goto outer_continue; case nmod_gcds_form_wrong: case nmod_gcds_no_solution: success = 0; goto finished; case nmod_gcds_scales_not_found: case nmod_gcds_eval_point_not_found: case nmod_gcds_eval_gcd_deg_too_high: goto inner_continue; case nmod_gcds_success: (void)(NULL); } if (nmod_mpolyu_leadcoeff(Geval, ctx) == UWORD(0)) { goto inner_continue; } /* update interpolant H */ temp = nmod_inv(nmod_mpolyu_leadcoeff(Geval, ctx), ctx->mod); nmod_mpolyu_scalar_mul_nmod(Geval, nmod_mul(geval, temp, ctx->mod), ctx); FLINT_ASSERT(n_poly_degree(modulus) > 0); temp = n_poly_mod_evaluate_nmod(modulus, alpha, ctx->mod); temp = nmod_inv(temp, ctx->mod); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, ctx->mod); changed = nmod_mpolyun_interp_crt_sm_mpolyu(&lastdeg, H, Ht, Geval, modulus, alpha, ctx); n_poly_set_coeff(tempmod, 0, ctx->mod.n - alpha); n_poly_mod_mul(modulus, modulus, tempmod, ctx->mod); have_enough = n_poly_degree(modulus) >= bound; if (changed && !have_enough) { goto inner_continue; } if (!changed || have_enough) { nmod_mpolyun_content_last(a, H, ctx); nmod_mpolyun_mul_poly(Ht, H, c, ctx); nmod_mpolyun_divexact_last(Ht, a, ctx); nmod_mpolyun_shift_left(Ht, Gshift); nmod_mpolyu_cvtfrom_mpolyun(G, Ht, var, ctx); if ( nmod_mpolyuu_divides(Abar, A, G, 1, ctx) && nmod_mpolyuu_divides(Bbar, B, G, 1, ctx)) { success = 1; goto finished; } } if (have_enough) { n_poly_one(modulus); goto outer_continue; } inner_continue:; } FLINT_ASSERT(0 && "not reachable"); outer_continue:; } FLINT_ASSERT(0 && "not reachable"); finished: n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(g); n_poly_clear(modulus); n_poly_clear(tempmod); nmod_mpolyu_clear(Aeval, ctx); nmod_mpolyu_clear(Beval, ctx); nmod_mpolyu_clear(Geval, ctx); nmod_mpolyu_clear(Abareval, ctx); nmod_mpolyu_clear(Bbareval, ctx); nmod_mpolyu_clear(Gform, ctx); nmod_mpolyun_clear(An, ctx); nmod_mpolyun_clear(Bn, ctx); nmod_mpolyun_clear(H, ctx); nmod_mpolyun_clear(Ht, ctx); return success; } flint-3.1.3/src/nmod_mpoly/mpolyun.c000066400000000000000000000673561461254215100174670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" void nmod_mpolyun_init( nmod_mpolyun_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; A->bits = bits; } void nmod_mpolyun_clear( nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) nmod_mpolyn_clear(A->coeffs + i, ctx); flint_free(A->coeffs); flint_free(A->exps); } int nmod_mpolyun_is_canonical( const nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { slong i; if (A->length > A->alloc) { return 0; } for (i = 0; i < A->length; i++) { if (!nmod_mpolyn_is_canonical(A->coeffs + i, ctx)) { return 0; } if (i > 0 && A->exps[i - 1] <= A->exps[i]) { return 0; } } return 1; } void nmod_mpolyun_print_pretty( const nmod_mpolyun_t poly, const char ** x, const nmod_mpoly_ctx_t ctx) { slong i; if (poly->length == 0) flint_printf("0"); for (i = 0; i < poly->length; i++) { if (i != 0) flint_printf(" + "); flint_printf("("); nmod_mpolyn_print_pretty(poly->coeffs + i,x,ctx); flint_printf(")*X^%wd",poly->exps[i]); } } void nmod_mpolyun_zero(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) { nmod_mpolyn_clear(A->coeffs + i, ctx); nmod_mpolyn_init(A->coeffs + i, A->bits, ctx); } A->length = 0; } void nmod_mpolyun_fit_length(nmod_mpolyun_t A, slong length, const nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { if (old_alloc == 0) { A->exps = (ulong *) flint_malloc(new_alloc*sizeof(ulong)); A->coeffs = (nmod_mpolyn_struct *) flint_malloc( new_alloc*sizeof(nmod_mpolyn_struct)); } else { A->exps = (ulong *) flint_realloc(A->exps, new_alloc*sizeof(ulong)); A->coeffs = (nmod_mpolyn_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(nmod_mpolyn_struct)); } for (i = old_alloc; i < new_alloc; i++) { nmod_mpolyn_init(A->coeffs + i, A->bits, ctx); } A->alloc = new_alloc; } } int nmod_mpolyn_is_nonzero_nmod(const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { slong N; if (A->length != WORD(1)) { return 0; } if (n_poly_degree(A->coeffs + 0) != 0) { return 0; } N = mpoly_words_per_exp(A->bits, ctx->minfo); return mpoly_monomial_is_zero(A->exps + N*0, N); } int nmod_mpolyun_is_nonzero_nmod(const nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { if (A->length != 1 || A->exps[0] != UWORD(0)) { return 0; } return nmod_mpolyn_is_nonzero_nmod(A->coeffs + 0, ctx); } void nmod_mpolyun_shift_right(nmod_mpolyun_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { FLINT_ASSERT(A->exps[i] >= s); A->exps[i] -= s; } } void nmod_mpolyun_shift_left(nmod_mpolyun_t A, ulong s) { slong i; for (i = 0; i < A->length; i++) { A->exps[i] += s; } } slong nmod_mpolyun_lastdeg(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { slong i, j; slong deg = -WORD(1); for (i = 0; i < A->length; i++) { for (j = 0; j < (A->coeffs + i)->length; j++) { deg = FLINT_MAX(deg, n_poly_degree((A->coeffs + i)->coeffs + j)); } } FLINT_ASSERT(deg >= 0); return deg; } slong nmod_mpolyn_lastdeg(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { slong i; slong deg = -WORD(1); for (i = 0; i < A->length; i++) { deg = FLINT_MAX(deg, n_poly_degree(A->coeffs + i)); } return deg; } void nmod_mpolyun_set(nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx) { slong i, Blen; nmod_mpolyn_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; Blen = B->length; nmod_mpolyun_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; for (i = 0; i < Blen; i++) { nmod_mpolyn_set(Acoeff + i, Bcoeff + i, ctx); Aexp[i] = Bexp[i]; } /* demote remaining coefficients */ for (i = Blen; i < A->length; i++) { nmod_mpolyn_clear(Acoeff + i, ctx); nmod_mpolyn_init(Acoeff + i, A->bits, ctx); } A->length = Blen; } void nmod_mpolyn_one(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx) { n_poly_struct * Acoeff; ulong * Aexp; slong N; nmod_mpolyn_fit_length(A, 1, ctx); Acoeff = A->coeffs; Aexp = A->exps; N = mpoly_words_per_exp(A->bits, ctx->minfo); n_poly_one(Acoeff + 0); mpoly_monomial_zero(Aexp + N*0, N); A->length = 1; } void nmod_mpolyun_one(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(ctx->mod.n > 1); nmod_mpolyun_fit_length(A, 1, ctx); nmod_mpolyn_one(A->coeffs + 0, ctx); A->exps[0] = 0; A->length = 1; } void nmod_mpolyn_set_mod(nmod_mpolyn_t A, const nmod_t mod) { } void nmod_mpolyun_set_mod(nmod_mpolyun_t A, const nmod_t mod) { } void nmod_mpolyn_scalar_mul_nmod( nmod_mpolyn_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx) { slong i; if (c == 1) return; for (i = 0; i < A->length; i++) _n_poly_mod_scalar_mul_nmod_inplace(A->coeffs + i, c, ctx->mod); } void nmod_mpolyun_scalar_mul_nmod( nmod_mpolyun_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx) { slong i; FLINT_ASSERT(c != 0); for (i = 0; i < A->length; i++) { nmod_mpolyn_scalar_mul_nmod(A->coeffs + i, c, ctx); } } void nmod_mpolyn_mul_last( nmod_mpolyn_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx) { slong i; n_poly_t t; FLINT_ASSERT(!n_poly_is_zero(b)); if (n_poly_is_one(b)) return; n_poly_init(t); for (i = 0; i < A->length; i++) { n_poly_mod_mul(t, A->coeffs + i, b, ctx->mod); n_poly_swap(t, A->coeffs + i); } n_poly_clear(t); } /* A *= b A is in R[X][x_0,..., x_(v-1)][x_v] b is in R[x_v] */ void nmod_mpolyun_mul_last( nmod_mpolyun_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx) { slong i, j; n_poly_t t; FLINT_ASSERT(!n_poly_is_zero(b)); if (n_poly_is_one(b)) return; n_poly_init(t); for (i = 0; i < A->length; i++) { for (j = 0; j < (A->coeffs + i)->length; j++) { n_poly_mod_mul(t, (A->coeffs + i)->coeffs + j, b, ctx->mod); n_poly_swap(t, (A->coeffs + i)->coeffs + j); } } n_poly_clear(t); } int nmod_mpolyn_equal( const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); slong i; FLINT_ASSERT(A->bits == B->bits); if (A->length != B->length) { return 0; } for (i = 0; i < A->length; i++) { if (!mpoly_monomial_equal(A->exps + N*i, B->exps + N*i, N)) { return 0; } if (!n_poly_equal(A->coeffs + i, B->coeffs + i)) { return 0; } } return 1; } int nmod_mpolyun_equal( const nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx) { slong i; FLINT_ASSERT(A->bits == B->bits); if (A->length != B->length) { return 0; } for (i = 0; i < A->length; i++) { if (A->exps[i] != B->exps[i]) { return 0; } if (!nmod_mpolyn_equal(A->coeffs + i, B->coeffs + i, ctx)) { return 0; } } return 1; } /* if the coefficient doesn't exist, a new one is created (and set to zero) */ n_poly_struct * _nmod_mpolyn_get_coeff(nmod_mpolyn_t A, ulong * pow, const nmod_mpoly_ctx_t uctx) { slong i, j, a, b; n_poly_struct * xk; slong N = mpoly_words_per_exp_sp(A->bits, uctx->minfo); int cmp; a = 0; b = A->length; if (b == 0 || mpoly_monomial_gt_nomask(pow, A->exps + N*0, N)) { i = 0; goto create_new; } if (mpoly_monomial_equal(pow , A->exps + N*(b - 1), N)) { return A->coeffs + b - 1; } try_again: if (b - a < 4) { for (i = a; i < b && (cmp = mpoly_monomial_cmp_nomask(A->exps + N*i, pow, N)) >= 0; i++) { if (cmp == 0) { return A->coeffs + i; } } goto create_new; } else { i = a + (b - a)/2; cmp = mpoly_monomial_cmp_nomask(A->exps + N*i, pow, N); if (cmp == 0) { return A->coeffs + i; } else if (cmp > 0) { a = i; } else { b = i; } goto try_again; } create_new: nmod_mpolyn_fit_length(A, A->length + 1, uctx); for (j = A->length; j > i; j--) { mpoly_monomial_set(A->exps + N*j, A->exps + N*(j - 1), N); n_poly_swap(A->coeffs + j, A->coeffs + j - 1); } mpoly_monomial_set(A->exps + N*i, pow, N); A->length++; xk = A->coeffs + i; xk->length = 0; return xk; } /* if the coefficient doesn't exist, a new one is created (and set to zero) */ nmod_mpolyn_struct * _nmod_mpolyun_get_coeff(nmod_mpolyun_t A, ulong pow, const nmod_mpoly_ctx_t uctx) { slong i, j, a, b; nmod_mpolyn_struct * xk; a = 0; b = A->length; if (b == 0 || pow > A->exps[0]) { i = 0; goto create_new; } if (pow == A->exps[b - 1]) { return A->coeffs + b - 1; } try_again: if (b - a < 8) { for (i = a; i < b && A->exps[i] >= pow; i++) { if (A->exps[i] == pow) { return A->coeffs + i; } } goto create_new; } else { i = a + (b - a)/2; if (A->exps[i] == pow) { return A->coeffs + i; } else if (A->exps[i] > pow) { a = i; } else { b = i; } goto try_again; } create_new: nmod_mpolyun_fit_length(A, A->length + 1, uctx); for (j = A->length; j > i; j--) { A->exps[j] = A->exps[j - 1]; nmod_mpolyn_swap(A->coeffs + j, A->coeffs + j - 1); } A->length++; A->exps[i] = pow; xk = A->coeffs + i; xk->length = 0; FLINT_ASSERT(xk->bits == A->bits); return xk; } void nmod_mpoly_to_mpolyun_perm_deflate_bivar( nmod_mpolyun_t A, const nmod_mpoly_t B, const slong * perm, const ulong * shift, const ulong * stride, const nmod_mpoly_ctx_t uctx, const nmod_mpoly_ctx_t ctx) { slong j; slong NB, NA; slong p0 = perm[0], p1 = perm[1]; ulong shift0 = shift[p0], shift1 = shift[p1]; ulong stride0 = stride[p0], stride1 = stride[p1]; ulong Bexp0, Bexp1; slong Boff0, Bshift0, Boff1, Bshift1; ulong mask; nmod_mpolyn_struct * Ac; FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(1 == uctx->minfo->nvars); NA = mpoly_words_per_exp_sp(A->bits, uctx->minfo); NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boff0, &Bshift0, p0, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boff1, &Bshift1, p1, B->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); for (j = 0; j < B->length; j++) { Bexp0 = ((B->exps + NB*j)[Boff0] >> Bshift0) & mask; Bexp1 = ((B->exps + NB*j)[Boff1] >> Bshift1) & mask; Ac = _nmod_mpolyun_get_coeff(A, stride0 == 1 ? (Bexp0 - shift0) : (Bexp0 - shift0) / stride0, uctx); FLINT_ASSERT(Ac->bits == A->bits); if (Ac->length == 0) { nmod_mpolyn_fit_length(Ac, 1, uctx); n_poly_zero(Ac->coeffs + 0); } Ac->length = 1; n_poly_set_coeff(Ac->coeffs + 0, stride1 == 1 ? (Bexp1 - shift1) : (Bexp1 - shift1) / stride1, B->coeffs[j]); mpoly_monomial_zero(Ac->exps + NA*0, NA); } } /* Convert B to A using the variable permutation perm. The uctx should be the context of the coefficients of A. The ctx should be the context of B. operation on each term: for 0 <= k < m + 1 l = perm[k] Aexp[k] = (Bexp[l] - shift[l])/stride[l] the most significant main variable uses k = 0 the coefficients of A use variables k = 1 ... m the variable corresponding to k = m is moved to dense storage. */ void nmod_mpoly_to_mpolyun_perm_deflate( nmod_mpolyun_t A, const nmod_mpoly_ctx_t uctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const thread_pool_handle * handles, slong num_handles) { slong j, k, l; slong NA = mpoly_words_per_exp_sp(A->bits, uctx->minfo); slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; ulong * Bexps; ulong * texp; slong * offs, * shifts; nmod_mpolyn_struct * Ac; n_poly_struct * Acc; TMP_INIT; A->length = 0; if (m == 1) { nmod_mpoly_to_mpolyun_perm_deflate_bivar(A, B, perm, shift, stride, uctx, ctx); return; } if (m > 2) { nmod_mpolyu_t Au; nmod_mpolyu_init(Au, A->bits, uctx); nmod_mpoly_to_mpolyu_perm_deflate_threaded_pool(Au, uctx, B, ctx, perm, shift, stride, handles, num_handles); nmod_mpolyu_cvtto_mpolyun(A, Au, m - 1, uctx); nmod_mpolyu_clear(Au, uctx); return; } TMP_START; Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); texp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); offs = (slong *) TMP_ALLOC(m*sizeof(slong)); shifts = (slong *) TMP_ALLOC(m*sizeof(slong)); for (k = 0; k < m; k++) { mpoly_gen_offset_shift_sp(offs + k, shifts + k, k, A->bits, uctx->minfo); } for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); l = perm[0]; Ac = _nmod_mpolyun_get_coeff(A, stride[l] == 1 ? (Bexps[l] - shift[l]) : (Bexps[l] - shift[l]) / stride[l], uctx); FLINT_ASSERT(Ac->bits == A->bits); mpoly_monomial_zero(texp, NA); for (k = 1; k < m; k++) { l = perm[k]; texp[offs[k - 1]] += (stride[l] == 1 ? (Bexps[l] - shift[l]) : (Bexps[l] - shift[l]) / stride[l]) << shifts[k - 1]; } Acc = _nmod_mpolyn_get_coeff(Ac, texp, uctx); l = perm[m]; n_poly_set_coeff(Acc, stride[l] == 1 ? (Bexps[l] - shift[l]) : (Bexps[l] - shift[l]) / stride[l], B->coeffs[j]); } TMP_END; } void nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool( nmod_mpolyn_t A, const nmod_mpoly_ctx_t nctx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, const slong * perm, const ulong * shift, const ulong * stride, const thread_pool_handle * handles, slong num_handles) { slong j, k, l; slong NA = mpoly_words_per_exp_sp(A->bits, nctx->minfo); slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); slong n = ctx->minfo->nvars; slong m = nctx->minfo->nvars; ulong * Bexps; slong * offs, * shifts; nmod_mpoly_t T; TMP_INIT; FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); offs = (slong *) TMP_ALLOC(m*sizeof(slong)); shifts = (slong *) TMP_ALLOC(m*sizeof(slong)); for (k = 0; k < m; k++) { mpoly_gen_offset_shift_sp(offs + k, shifts + k, k, A->bits, nctx->minfo); } nmod_mpoly_init3(T, B->length, A->bits, nctx); T->length = B->length; for (j = 0; j < B->length; j++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo); T->coeffs[j] = B->coeffs[j]; mpoly_monomial_zero(T->exps + NA*j, NA); for (k = 0; k < m; k++) { l = perm[k]; (T->exps + NA*j)[offs[k]] += ((Bexps[l] - shift[l]) / stride[l]) << shifts[k]; } } nmod_mpoly_sort_terms(T, nctx); nmod_mpoly_cvtto_mpolyn(A, T, nctx->minfo->nvars - 1, nctx); nmod_mpoly_clear(T, nctx); TMP_END; } /* Convert B to A using the variable permutation vector perm. A must be constructed with bits = Abits. operation on each term: for 0 <= l < n Aexp[l] = shift[l] for 0 <= k <= m l = perm[k] Aexp[l] += scale[l]*Bexp[k] */ void nmod_mpoly_from_mpolyun_perm_inflate( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t uctx, const slong * perm, const ulong * shift, const ulong * stride) { slong n = ctx->minfo->nvars; slong m = uctx->minfo->nvars; slong i, j, h, k, l; slong NA, NB; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * uexps; ulong * Aexps, * tAexp, * tAgexp; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m + 1 <= n); TMP_START; uexps = (ulong *) TMP_ALLOC((m + 1)*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, uctx->minfo); tAexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); tAgexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); mpoly_gen_monomial_sp(tAgexp, perm[m], Abits, ctx->minfo); for (i = 0; i < NA; i++) { tAgexp[i] *= stride[perm[m]]; } nmod_mpoly_fit_length_reset_bits(A, 0, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { nmod_mpolyn_struct * Bc = B->coeffs + i; FLINT_ASSERT(Bc->bits == B->bits); for (j = 0; j < Bc->length; j++) { mpoly_get_monomial_ui(uexps + 1, Bc->exps + NB*j, Bc->bits, uctx->minfo); uexps[0] = B->exps[i]; FLINT_ASSERT(uexps[m] == 0); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m + 1; k++) { l = perm[k]; Aexps[l] += stride[l]*uexps[k]; } mpoly_set_monomial_ui(tAexp, Aexps, Abits, ctx->minfo); l = perm[m]; h = (Bc->coeffs + j)->length; _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, NA, Alen + h); for (h--; h >= 0; h--) { mp_limb_t c = (Bc->coeffs + j)->coeffs[h]; if (c == 0) continue; mpoly_monomial_madd(Aexp + NA*Alen, tAexp, h, tAgexp, NA); Acoeff[Alen] = c; Alen++; } } } A->coeffs = Acoeff; A->exps = Aexp; _nmod_mpoly_set_length(A, Alen, ctx); nmod_mpoly_sort_terms(A, ctx); TMP_END; } void nmod_mpoly_from_mpolyn_perm_inflate( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t nctx, const slong * perm, const ulong * shift, const ulong * stride) { slong n = ctx->minfo->nvars; slong m = nctx->minfo->nvars; slong i, h, k, l; slong NA, NB; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * Bexps; ulong * Aexps, * tAexp, * tAgexp; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(m <= n); TMP_START; Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong)); Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); NA = mpoly_words_per_exp(Abits, ctx->minfo); NB = mpoly_words_per_exp(B->bits, nctx->minfo); tAexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); tAgexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong)); mpoly_gen_monomial_sp(tAgexp, perm[m - 1], Abits, ctx->minfo); for (i = 0; i < NA; i++) tAgexp[i] *= stride[perm[m - 1]]; nmod_mpoly_fit_length_reset_bits(A, 0, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, nctx->minfo); FLINT_ASSERT(Bexps[m - 1] == 0); for (l = 0; l < n; l++) { Aexps[l] = shift[l]; } for (k = 0; k < m; k++) { l = perm[k]; Aexps[l] += stride[l]*Bexps[k]; } mpoly_set_monomial_ui(tAexp, Aexps, Abits, ctx->minfo); h = (B->coeffs + i)->length; _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, NA, Alen + h); for (h--; h >= 0; h--) { mp_limb_t c = (B->coeffs + i)->coeffs[h]; if (c == 0) continue; mpoly_monomial_madd(Aexp + NA*Alen, tAexp, h, tAgexp, NA); Acoeff[Alen] = c; Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; _nmod_mpoly_set_length(A, Alen, ctx); nmod_mpoly_sort_terms(A, ctx); TMP_END; } /* take the last variable of B out */ void nmod_mpoly_cvtto_mpolyn(nmod_mpolyn_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong i; slong k; ulong * oneexp; slong offset; slong shift; ulong mask; slong N; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); TMP_START; N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); oneexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var, B->bits, ctx->minfo); nmod_mpolyn_fit_bits(A, B->bits, ctx); A->bits = B->bits; k = 0; nmod_mpolyn_fit_length(A, k + 1, ctx); for (i = 0; i < B->length; i++) { ulong c = (B->exps[N*i + offset] >> shift) & mask; mpoly_monomial_msub(A->exps + N*k, B->exps + N*i, c, oneexp, N); if (k > 0 && mpoly_monomial_equal(A->exps + N*k, A->exps + N*(k - 1), N)) { n_poly_set_coeff(A->coeffs + k - 1, c, B->coeffs[i]); } else { n_poly_zero(A->coeffs + k); n_poly_set_coeff(A->coeffs + k, c, B->coeffs[i]); k++; nmod_mpolyn_fit_length(A, k + 1, ctx); } } nmod_mpolyn_set_length(A, k, ctx); TMP_END; } void nmod_mpolyu_cvtto_mpolyun(nmod_mpolyun_t A, const nmod_mpolyu_t B, slong k, const nmod_mpoly_ctx_t ctx) { slong i, Blen; nmod_mpolyn_struct * Acoeff; nmod_mpoly_struct * Bcoeff; ulong * Aexp, * Bexp; Blen = B->length; nmod_mpolyun_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; for (i = 0; i < Blen; i++) { nmod_mpoly_cvtto_mpolyn(Acoeff + i, Bcoeff + i, k, ctx); Aexp[i] = Bexp[i]; } A->length = Blen; } /* put the last variable of B back into A */ void nmod_mpoly_cvtfrom_mpolyn( nmod_mpoly_t A, const nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong i, j, k; slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); ulong * genexp; TMP_INIT; FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_gen_monomial_sp(genexp, var, B->bits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); k = 0; for (i = 0; i < B->length; i++) { for (j = B->coeffs[i].length - 1; j >= 0; j--) { mp_limb_t c = B->coeffs[i].coeffs[j]; if (c == 0) continue; _nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, k + 1); A->coeffs[k] = c; mpoly_monomial_madd(A->exps + N*k, B->exps + N*i, j, genexp, N); k++; } } A->length = k; TMP_END; } void nmod_mpolyu_cvtfrom_mpolyun(nmod_mpolyu_t A, const nmod_mpolyun_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong i; nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { nmod_mpoly_cvtfrom_mpolyn(A->coeffs + i, B->coeffs + i, var, ctx); A->exps[i] = B->exps[i]; } A->length = B->length; } void nmod_mpolyun_mul_poly(nmod_mpolyun_t A, const nmod_mpolyun_t B, const n_poly_t c, const nmod_mpoly_ctx_t ctx) { slong i, Blen; nmod_mpolyn_struct * Acoeff, * Bcoeff; ulong * Aexp, * Bexp; Blen = B->length; nmod_mpolyun_fit_length(A, Blen, ctx); Acoeff = A->coeffs; Bcoeff = B->coeffs; Aexp = A->exps; Bexp = B->exps; for (i = 0; i < Blen; i++) { nmod_mpolyn_mul_poly(Acoeff + i, Bcoeff + i, c, ctx); Aexp[i] = Bexp[i]; } /* demote remaining coefficients */ for (i = Blen; i < A->length; i++) { nmod_mpolyn_clear(Acoeff + i, ctx); nmod_mpolyn_init(Acoeff + i, A->bits, ctx); } A->length = Blen; } void nmod_mpolyun_content_last( n_poly_t a, nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx) { slong i, j; n_poly_zero(a); for (i = 0; i < B->length; i++) { for (j = 0; j < (B->coeffs + i)->length; j++) { n_poly_mod_gcd(a, a, (B->coeffs + i)->coeffs + j, ctx->mod); if (n_poly_degree(a) == 0) break; } } } void nmod_mpolyn_content_last( n_poly_t a, nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx) { slong i; n_poly_zero(a); for (i = 0; i < B->length; i++) { n_poly_mod_gcd(a, a, B->coeffs + i, ctx->mod); if (n_poly_degree(a) == 0) break; } } void nmod_mpolyun_divexact_last( nmod_mpolyun_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx) { slong i, j; n_poly_t r; if (n_poly_is_one(b)) return; n_poly_init(r); for (i = 0; i < A->length; i++) { for (j = 0; j < (A->coeffs + i)->length; j++) { n_poly_mod_divrem((A->coeffs + i)->coeffs + j, r, (A->coeffs + i)->coeffs + j, b, ctx->mod); FLINT_ASSERT(n_poly_is_zero(r)); } } n_poly_clear(r); } void nmod_mpolyn_divexact_last( nmod_mpolyn_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx) { slong i; n_poly_t r; if (n_poly_is_one(b)) return; n_poly_init(r); for (i = 0; i < A->length; i++) { n_poly_mod_divrem(A->coeffs + i, r, A->coeffs + i, b, ctx->mod); FLINT_ASSERT(n_poly_is_zero(r)); } n_poly_clear(r); } flint-3.1.3/src/nmod_mpoly/mpolyun_divides.c000066400000000000000000000524131461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" int _nmod_mpolyn_divides( nmod_mpolyn_t Q, const nmod_mpolyn_t A, const nmod_mpolyn_t B, slong N, const ulong * cmpmask, const nmod_mpoly_ctx_t ctx) { int success; int lt_divides; flint_bitcnt_t bits = Q->bits; slong i, j, Qlen, s; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; slong * hind; n_poly_t r, acc; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == Q->bits); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); TMP_START; n_poly_init(r); n_poly_init(acc); /* alloc array of heap nodes which can be chained together */ next_loc = B->length + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*B->length*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC(B->length*sizeof(ulong *)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < B->length; i++) exp_list[i] = exps + i*N; /* space for flagged heap indices */ hind = (slong *) TMP_ALLOC(B->length*sizeof(slong)); for (i = 0; i < B->length; i++) hind[i] = 1; mask = mpoly_overflow_mask_sp(bits); /* s is the number of terms * (latest quotient) we should put into heap */ s = B->length; /* insert (-1, 0, exp2[0]) into heap */ x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, A->exps + N*0, N); Qlen = 0; while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows(exp, N, mask)) goto not_exact_division; nmod_mpolyn_fit_length(Q, Qlen + 1, ctx); lt_divides = mpoly_monomial_divides(Q->exps + Qlen*N, exp, B->exps + N*0, N, mask); n_poly_zero(acc); do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { n_poly_mod_add(acc, acc, A->coeffs + x->j, ctx->mod); } else { n_poly_mod_mul(r, B->coeffs + x->i, Q->coeffs + x->j, ctx->mod); n_poly_mod_sub(acc, acc, r, ctx->mod); } } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < A->length) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], A->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } else { /* should we go right? */ if ( (i + 1 < B->length) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], B->exps + x->i*N, Q->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if (j + 1 == Qlen) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], B->exps + x->i*N, Q->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } if (n_poly_is_zero(acc)) continue; n_poly_mod_divrem(Q->coeffs + Qlen, r, acc, B->coeffs + 0, ctx->mod); if (!n_poly_is_zero(r)) goto not_exact_division; if (!lt_divides) goto not_exact_division; if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; mpoly_monomial_add(exp_list[exp_next], B->exps + x->i*N, Q->exps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } s = 1; Qlen++; } success = 1; cleanup: n_poly_clear(r); n_poly_clear(acc); Q->length = Qlen; TMP_END; return success; not_exact_division: success = 0; goto cleanup; } int nmod_mpolyn_divides( nmod_mpolyn_t Q, const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx) { slong N; ulong * cmpmask; flint_bitcnt_t bits = Q->bits; int success; TMP_INIT; TMP_START; N = mpoly_words_per_exp_sp(bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); success = _nmod_mpolyn_divides(Q, A, B, N, cmpmask, ctx); TMP_END; return success; } /* The following functions are currently untested and unused. */ void _nmod_mpolyn_add( nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpolyn_t C, slong N, const nmod_mpoly_ctx_t ctx) { slong i = 0, j = 0, Alen = 0; FLINT_ASSERT(N == mpoly_words_per_exp(A->bits, ctx->minfo)); FLINT_ASSERT(N == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(N == mpoly_words_per_exp(C->bits, ctx->minfo)); nmod_mpolyn_fit_length(A, B->length + C->length, ctx); while (i < B->length && j < C->length) { int cmp = mpoly_monomial_cmp_nomask(B->exps + i*N, C->exps + j*N, N); if (cmp > 0) { n_poly_set(A->coeffs + Alen, B->coeffs + i); mpoly_monomial_set(A->exps + Alen*N, B->exps + i*N, N); i++; Alen++; } else if (cmp == 0) { n_poly_mod_add(A->coeffs + Alen, B->coeffs + i, C->coeffs + j, ctx->mod); mpoly_monomial_set(A->exps + Alen*N, B->exps + i*N, N); i++; j++; Alen += !n_poly_is_zero(A->coeffs + Alen); } else { n_poly_set(A->coeffs + Alen, C->coeffs + j); mpoly_monomial_set(A->exps + Alen*N, C->exps + j*N, N); j++; Alen++; } } while (i < B->length) { n_poly_set(A->coeffs + Alen, B->coeffs + i); mpoly_monomial_set(A->exps + Alen*N, B->exps + i*N, N); i++; Alen++; } while (j < C->length) { n_poly_set(A->coeffs + Alen, C->coeffs + j); mpoly_monomial_set(A->exps + Alen*N, C->exps + j*N, N); j++; Alen++; } A->length = Alen; } /* A = D - B*C, D may be modified if saveD == 0 */ void _nmod_mpolyn_mulsub( nmod_mpolyn_t A, const nmod_mpolyn_t D, int saveD, const nmod_mpolyn_t B, const nmod_mpolyn_t C, slong N, const ulong * cmpmask, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = A->bits; slong i, j; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong Di; slong Alen; slong Dlen = D->length; slong Blen = B->length; slong Clen = C->length; ulong * Dexp = D->exps; ulong * Bexp = B->exps; ulong * Cexp = C->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; n_poly_t t; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == D->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == C->bits); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(C->length > 0); TMP_START; n_poly_init(t); next_loc = B->length + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*B->length*sizeof(slong)); exps = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(B->length*sizeof(ulong *)); for (i = 0; i < B->length; i++) exp_list[i] = exps + i*N; /* space for heap indices */ hind = (slong *) TMP_ALLOC(B->length*sizeof(slong)); for (i = 0; i < B->length; i++) hind[i] = 1; /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, Bexp[0] + Cexp[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_add(heap[1].exp, B->exps + N*0, C->exps + N*0, N); hind[0] = 2*1 + 0; Alen = 0; Di = 0; while (heap_len > 1) { exp = heap[1].exp; while (Di < Dlen && mpoly_monomial_gt(Dexp + N*Di, exp, N, cmpmask)) { nmod_mpolyn_fit_length(A, Alen + 1, ctx); mpoly_monomial_set(A->exps + N*Alen, D->exps + N*Di, N); if (saveD) n_poly_set(A->coeffs + Alen, D->coeffs + Di); else n_poly_swap(A->coeffs + Alen, D->coeffs + Di); Alen++; Di++; } nmod_mpolyn_fit_length(A, Alen + 1, ctx); mpoly_monomial_set(A->exps + N*Alen, exp, N); if (Di < Dlen && mpoly_monomial_equal(Dexp + N*Di, exp, N)) { if (saveD) n_poly_set(A->coeffs + Alen, D->coeffs + Di); else n_poly_swap(A->coeffs + Alen, D->coeffs + Di); Di++; } else { n_poly_zero(A->coeffs + Alen); } do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; n_poly_mod_mul(t, B->coeffs + x->i, C->coeffs + x->j, ctx->mod); n_poly_mod_sub(A->coeffs + Alen, A->coeffs + Alen, t, ctx->mod); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); Alen += !n_poly_is_zero(A->coeffs + Alen); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ( (j + 1 < Clen) && ((hind[i] & 1) == 1) && ((i == 0) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } FLINT_ASSERT(Di <= Dlen); nmod_mpolyn_fit_length(A, Alen + Dlen - Di, ctx); for (i = 0; i < Dlen - Di; i++) if (saveD) n_poly_set(A->coeffs + Alen + i, D->coeffs + Di + i); else n_poly_swap(A->coeffs + Alen + i, D->coeffs + Di + i); mpoly_copy_monomials(A->exps + N*Alen, Dexp + N*Di, Dlen - Di, N); Alen += Dlen - Di; A->length = Alen; n_poly_clear(t); TMP_END; } /* Q = A/B return 1 if division was exact. nmainvars is the number of main vars. */ int nmod_mpolyun_divides( nmod_mpolyun_t Q, const nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx) { slong nmainvars = 1; flint_bitcnt_t bits = A->bits; nmod_mpolyn_struct * Bcoeff = B->coeffs; slong Blen = B->length; ulong * Bexp = B->exps; nmod_mpolyn_struct * Acoeff = A->coeffs; slong Alen = A->length; ulong * Aexp = A->exps; slong N; ulong * cmpmask; /* cmp mask for lesser variables */ nmod_mpolyn_t T, S; int success; ulong maskhi = 0; /* main variables are in lex */ int lt_divides; slong i, j, s; slong next_loc, heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; slong * hind; ulong mask, exp, maxexp = Aexp[Alen - 1]; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); FLINT_ASSERT(bits == A->bits); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == Q->bits); N = mpoly_words_per_exp(bits, ctx->minfo); cmpmask = (ulong *) flint_malloc(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); /* alloc array of heap nodes which can be chained together */ next_loc = Blen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) flint_malloc((Blen + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) flint_malloc(Blen*sizeof(mpoly_heap_t)); store = store_base = (slong *) flint_malloc(2*Blen*sizeof(mpoly_heap_t *)); /* space for flagged heap indices */ hind = (slong *) flint_malloc(Blen*sizeof(slong)); for (i = 0; i < B->length; i++) hind[i] = 1; /* mask with high bit set in each field of main exponent vector */ mask = 0; for (i = 0; i < nmainvars; i++) mask = (mask << (FLINT_BITS/nmainvars)) + (UWORD(1) << (FLINT_BITS/nmainvars - 1)); /* s is the number of terms * (latest quotient) we should put into heap */ s = Blen; /* insert (-1, 0, exp2[0]) into heap */ heap_len = 2; x = chain + 0; x->i = -WORD(1); x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], Aexp[0], x); Q->length = 0; nmod_mpolyn_init(T, bits, ctx); nmod_mpolyn_init(S, bits, ctx); while (heap_len > 1) { exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) { goto not_exact_division; } nmod_mpolyun_fit_length(Q, Q->length + 1, ctx); lt_divides = mpoly_monomial_divides1(Q->exps + Q->length, exp, Bexp[0], mask); T->length = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; if (x->i != -WORD(1)) hind[x->i] |= WORD(1); if (x->i == -WORD(1)) { _nmod_mpolyn_add(S, T, Acoeff + x->j, N, ctx); } else { _nmod_mpolyn_mulsub(S, T, 0, Bcoeff + x->i, Q->coeffs + x->j, N, cmpmask, ctx); } nmod_mpolyn_swap(S, T); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; if (i == -WORD(1)) { /* take next dividend term */ if (j + 1 < Alen) { x = chain + 0; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Aexp[x->j], x, &next_loc, &heap_len, maskhi); } } else { /* should we go right? */ if ( (i + 1 < Blen) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if (j + 1 == Q->length) { s++; } else if ( ((hind[i] & 1) == 1) && ((i == 1) || (hind[i - 1] >= 2*(j + 2) + 1)) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } } } if (T->length == 0) { continue; } if (mpoly_monomials_overflow_test(T->exps, T->length, bits, ctx->minfo)) { goto not_exact_division; } if (!_nmod_mpolyn_divides(Q->coeffs + Q->length, T, Bcoeff + 0, N, cmpmask, ctx)) { goto not_exact_division; } if (!lt_divides || (exp^maskhi) < (maxexp^maskhi)) { goto not_exact_division; } /* put newly generated quotient term back into the heap if necessary */ if (s > 1) { i = 1; x = chain + i; x->i = i; x->j = Q->length; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Q->exps[x->j], x, &next_loc, &heap_len, maskhi); } s = 1; Q->length++; } success = 1; cleanup: nmod_mpolyn_clear(T, ctx); nmod_mpolyn_clear(S, ctx); flint_free(cmpmask); flint_free(heap); flint_free(chain); flint_free(store); flint_free(hind); return success; not_exact_division: success = 0; Q->length = 0; goto cleanup; } flint-3.1.3/src/nmod_mpoly/mul.c000066400000000000000000000170721461254215100165470ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" static int _try_dense(int try_array, slong * Bdegs, slong * Cdegs, slong Blen, slong Clen, slong nvars) { const int max_bit_size = FLINT_MIN(FLINT_BITS/3 + 16, FLINT_BITS - 3); slong i, product_count, dense_size; ulong hi; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); dense_size = WORD(1); for (i = 0; i < nvars; i++) { umul_ppmm(hi, dense_size, dense_size, Bdegs[i] + Cdegs[i] + 1); if (hi != 0 || dense_size <= 0) return 0; } if (dense_size >= WORD(1) << max_bit_size) return 0; umul_ppmm(hi, product_count, Blen, Clen); if (hi != 0 || product_count < 0) return 1; /* Assume that the running time of the dense method is linear in "dense_size" and that the running time of the array|heap method is linear in "product_count". Assume further that the array method is 4x faster than heap. */ if (try_array) return dense_size < product_count/128; else return dense_size < product_count/32; } static int _try_array_LEX(slong * Bdegs, slong * Cdegs, slong Blen, slong Clen, slong nvars) { slong i, dense_size; ulong hi; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); /* accept array method if the array is probably at least 10% full */ dense_size = WORD(1); for (i = 0; i < nvars; i++) { umul_ppmm(hi, dense_size, dense_size, Bdegs[i] + Cdegs[i] + 1); if (hi != 0 || dense_size <= 0) return 0; } return dense_size <= WORD(50000000) && dense_size/Blen/Clen < WORD(10); } static int _try_array_DEG(slong Btotaldeg, slong Ctotaldeg, slong Blen, slong Clen, slong nvars) { slong i, dense_size, total_degree; ulong hi; FLINT_ASSERT(Blen > 0); FLINT_ASSERT(Clen > 0); total_degree = Btotaldeg + Btotaldeg; if (total_degree <= 0) return 0; /* the relevant portion of the array has approx size d^nvars/nvars!*/ dense_size = WORD(1); for (i = 0; i < nvars; i++) { umul_ppmm(hi, dense_size, dense_size, total_degree); if (hi != WORD(0) || dense_size < 0) return 0; } for (i = 0; i < nvars; i++) { dense_size /= i + 1; } return dense_size <= WORD(5000000) && dense_size/Blen/Clen < WORD(10); } void nmod_mpoly_mul( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) { slong i; slong nvars = ctx->minfo->nvars; int success, try_array; slong * Bdegs, * Cdegs; fmpz * maxBfields, * maxCfields; thread_pool_handle * handles; slong num_handles; slong min_length, max_length; slong thread_limit; TMP_INIT; if (B->length == 0 || C->length == 0) { nmod_mpoly_zero(A, ctx); return; } TMP_START; /* All methods require a linear scan of the exponents. Do it here once and for all. */ maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); min_length = FLINT_MIN(B->length, C->length); max_length = FLINT_MAX(B->length, C->length); thread_limit = min_length/512; /* If one polynomial is tiny or if both polynomials are small, heap method with operational complexity O(B->length*C->length) is fine. */ if (nvars < 1 || min_length < 20 || max_length < 50) { _nmod_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); goto cleanup; } /* If either polynomial has multi-word fields, only heap will do. */ if (B->bits > FLINT_BITS || C->bits > FLINT_BITS) { num_handles = flint_request_threads(&handles, thread_limit); goto do_heap; } /* The multiplication is not trivial and each packed field fits into one word. In particular, the degrees must fit an slong. */ Bdegs = (slong *) TMP_ALLOC(nvars*sizeof(slong)); Cdegs = (slong *) TMP_ALLOC(nvars*sizeof(slong)); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Bdegs, maxBfields, ctx->minfo); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Cdegs, maxCfields, ctx->minfo); /* See if array method is applicable. If so, it should be about 4x faster than heap. */ try_array = 0; if (nvars > WORD(1) && nvars < WORD(8) && 1 == mpoly_words_per_exp(B->bits, ctx->minfo) && 1 == mpoly_words_per_exp(C->bits, ctx->minfo)) { if (ctx->minfo->ord == ORD_LEX) { try_array = _try_array_LEX(Bdegs, Cdegs, B->length, C->length, nvars); } else if (ctx->minfo->ord == ORD_DEGLEX || ctx->minfo->ord == ORD_DEGREVLEX) { slong Btdeg = fmpz_get_si(maxBfields + nvars); slong Ctdeg = fmpz_get_si(maxCfields + nvars); try_array = _try_array_DEG(Btdeg, Ctdeg, B->length, C->length, nvars); } } success = 0; if (_try_dense(try_array, Bdegs, Cdegs, B->length, C->length, nvars)) { success = _nmod_mpoly_mul_dense(A, B, maxBfields, C, maxCfields, ctx); if (success) { goto cleanup; } } num_handles = flint_request_threads(&handles, thread_limit); if (!try_array) { goto do_heap; } if (ctx->minfo->ord == ORD_LEX) { success = (num_handles > 0) ? _nmod_mpoly_mul_array_threaded_pool_LEX( A, B, maxBfields, C, maxCfields, ctx, handles, num_handles) : _nmod_mpoly_mul_array_LEX( A, B, maxBfields, C, maxCfields, ctx); } else if (ctx->minfo->ord == ORD_DEGLEX || ctx->minfo->ord == ORD_DEGREVLEX) { success = (num_handles > 0) ? _nmod_mpoly_mul_array_threaded_pool_DEG( A, B, maxBfields, C, maxCfields, ctx, handles, num_handles) : _nmod_mpoly_mul_array_DEG( A, B, maxBfields, C, maxCfields, ctx); } if (success) { goto cleanup_threads; } do_heap: if (num_handles > 0) { _nmod_mpoly_mul_heap_threaded_pool_maxfields(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); } else { _nmod_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); } cleanup_threads: flint_give_back_threads(handles, num_handles); cleanup: for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; } flint-3.1.3/src/nmod_mpoly/mul_array.c000066400000000000000000001150071461254215100177420ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" /* Currently we do not -funroll-loops by default in the nmod_mpoly module, but it is worthwhile for the functions in this file. */ #pragma GCC optimize("-funroll-loops") /* improve locality */ #define BLOCK 128 #define MAX_ARRAY_SIZE (WORD(300000)) #define MAX_LEX_SIZE (WORD(300)) void _nmod_mpoly_addmul_array1_ulong1(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong * c2; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + (slong) exp2[i]; if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c2[(slong) exp3[j]] += poly2[i]*poly3[j]; } } } } } } void _nmod_mpoly_addmul_array1_ulong2(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong p[2]; ulong * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { /* Hack: both the (slong) cast and writing as a shift by 1 instead of a multiply by 2 are needed to get GCC to generate good code on Zen3. Check build/nmod_mpoly/profile/p-mul 1 dense 30 20 before changing this. */ c2 = poly1 + (((slong) exp2[i]) << 1); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { /* Hack. */ c = c2 + (((slong) exp3[j]) << 1); umul_ppmm(p[1], p[0], poly2[i], poly3[j]); add_ssaaaa(c[1], c[0], c[1], c[0], p[1], p[0]); } } } } } } void _nmod_mpoly_addmul_array1_ulong3(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3) { slong ii, i, jj, j; ulong p[2]; ulong * c2, * c; for (ii = 0; ii < len2 + BLOCK; ii += BLOCK) { for (jj = 0; jj < len3 + BLOCK; jj += BLOCK) { for (i = ii; i < FLINT_MIN(ii + BLOCK, len2); i++) { c2 = poly1 + 3*((slong) exp2[i]); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + 3*((slong) exp3[j]); umul_ppmm(p[1], p[0], poly2[i], poly3[j]); add_sssaaaaaa(c[2], c[1], c[0], c[2], c[1], c[0], 0, p[1], p[0]); } } } } } } /**************************************************** LEX ****************************************************/ #define LEX_UNPACK_MACRO(fxn_name, coeff_decl, nonzero_test, reduce_coeff) \ slong fxn_name(nmod_mpoly_t P, slong Plen, coeff_decl, \ const ulong * mults, slong num, slong array_size, slong top, \ const nmod_mpoly_ctx_t ctx) \ { \ slong off, j; \ slong topmult = num == 0 ? 1 : mults[num - 1]; \ slong lastd = topmult - 1; \ slong reset = array_size/topmult; \ slong counter = reset; \ ulong startexp = (top << (P->bits*num)) + (lastd << (P->bits*(num-1))); \ ulong coeff; \ for (off = array_size - 1; off >= 0; off--) \ { \ if (nonzero_test) \ { \ reduce_coeff \ if (coeff != UWORD(0)) \ { \ slong d = off; \ ulong exp = startexp; \ for (j = 0; j + 1 < num; j++) { \ exp += (d % mults[j]) << (P->bits*j); \ d = d / mults[j]; \ } \ _nmod_mpoly_fit_length(&P->coeffs, &P->coeffs_alloc, \ &P->exps, &P->exps_alloc, 1, Plen + 1); \ P->exps[Plen] = exp; \ P->coeffs[Plen] = coeff; \ Plen++; \ } \ } \ counter--; \ if (counter <= 0) { \ counter = reset; \ lastd--; \ startexp -= UWORD(1) << (P->bits*(num-1)); \ } \ } \ return Plen; \ } /* These four functions will replace _fmpz_mpoly_from_ulong_array, ..., _fmpz_mpoly_from_fmpz_array defined above. */ LEX_UNPACK_MACRO( nmod_mpoly_append_array_sm1_LEX, ulong * coeff_array , coeff_array[off] != UWORD(0) , NMOD_RED(coeff, coeff_array[off], ctx->mod); coeff_array[off] = 0; ) LEX_UNPACK_MACRO( nmod_mpoly_append_array_sm2_LEX, ulong * coeff_array , (coeff_array[2*off + 0] || coeff_array[2*off + 1]) != UWORD(0) , NMOD2_RED2(coeff, coeff_array[2*off + 1], coeff_array[2*off + 0], ctx->mod); coeff_array[2*off + 0] = coeff_array[2*off + 1] = 0; ) LEX_UNPACK_MACRO( nmod_mpoly_append_array_sm3_LEX, ulong * coeff_array , (coeff_array[3*off + 0] || coeff_array[3*off + 1] || coeff_array[3*off + 2]) != UWORD(0) , NMOD_RED3(coeff, coeff_array[3*off + 2], coeff_array[3*off + 1], coeff_array[3*off + 0], ctx->mod); coeff_array[3*off + 0] = coeff_array[3*off + 1] = coeff_array[3*off + 2] = UWORD(0); ) void _nmod_mpoly_mul_array_chunked_LEX( nmod_mpoly_t P, const nmod_mpoly_t A, const nmod_mpoly_t B, const ulong * mults, const nmod_mpoly_ctx_t ctx) { slong num = ctx->minfo->nfields - 1; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; TMP_INIT; array_size = 1; for (i = 0; i < num; i++) { array_size *= mults[i]; } /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*num)); Bl = 1 + (slong) (B->exps[0] >> (B->bits*num)); TMP_START; /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC((Al + 1)*sizeof(slong)); Bmain = (slong *) TMP_ALLOC((Bl + 1)*sizeof(slong)); Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_LEX(Amain, Apexp, A->exps, Al, A->length, mults, num, A->bits); mpoly_main_variable_split_LEX(Bmain, Bpexp, B->exps, Bl, B->length, mults, num, B->bits); Pl = Al + Bl - 1; Plen = 0; { ulong * coeff_array = (ulong *) TMP_ALLOC(3*array_size*sizeof(ulong)); for (j = 0; j < 3*array_size; j++) coeff_array[j] = 0; /* for each output chunk */ for (Pi = 0; Pi < Pl; Pi++) { /* compute bound on coeffs of output chunk */ slong len = 0; mp_limb_t t2, t1, t0, u1, u0; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { len += FLINT_MIN(Amain[i + 1] - Amain[i], Bmain[j + 1] - Bmain[j]); } } umul_ppmm(t1, t0, ctx->mod.n - 1, ctx->mod.n - 1); umul_ppmm(t2, t1, t1, len); umul_ppmm(u1, u0, t0, len); add_sssaaaaaa(t2, t1, t0, t2, t1, UWORD(0), UWORD(0), u1, u0); if (t2 != UWORD(0)) { /* need three words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _nmod_mpoly_addmul_array1_ulong3(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = nmod_mpoly_append_array_sm3_LEX(P, Plen, coeff_array, mults, num, array_size, Pl - Pi - 1, ctx); } else if (t1 != UWORD(0)) { /* fits into two words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _nmod_mpoly_addmul_array1_ulong2(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = nmod_mpoly_append_array_sm2_LEX(P, Plen, coeff_array, mults, num, array_size, Pl - Pi - 1, ctx); } else { /* fits into one word */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _nmod_mpoly_addmul_array1_ulong1(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = nmod_mpoly_append_array_sm1_LEX(P, Plen, coeff_array, mults, num, array_size, Pl - Pi - 1, ctx); } } } _nmod_mpoly_set_length(P, Plen, ctx); flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _nmod_mpoly_mul_array_LEX( nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx) { slong i, exp_bits, array_size; ulong max, * mults; int success; TMP_INIT; FLINT_ASSERT(ctx->minfo->nvars > 0); FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); TMP_START; /* compute maximum exponents for each variable */ mults = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); /* the field of index n-1 is the one that will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max = mults[i]; if (((slong) mults[i]) <= 0 || mults[i] > MAX_LEX_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...0, contribute to the array size */ array_size = WORD(1); for (i--; i >= 0; i--) { ulong hi; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max |= mults[i]; umul_ppmm(hi, array_size, array_size, mults[i]); if (hi != 0 || (slong) mults[i] <= 0 || array_size <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(max) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fit into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { nmod_mpoly_t T; nmod_mpoly_init3(T, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_LEX(T, C, B, mults, ctx); nmod_mpoly_swap(T, A, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(A, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_LEX(A, C, B, mults, ctx); } success = 1; cleanup: TMP_END; return success; } /**************************************************** DEGLEX and DEGREVLEX ****************************************************/ #define DEGLEX_UNPACK_MACRO(fxn_name, coeff_decl, nonzero_test, reduce_coeff) \ slong fxn_name(nmod_mpoly_t P, slong Plen, coeff_decl, \ slong top, slong nvars, slong degb, \ const nmod_mpoly_ctx_t ctx) \ { \ slong i; \ ulong exp, lomask = (UWORD(1) << (P->bits - 1)) - 1; \ slong off, array_size; \ slong * curexp, * degpow; \ ulong * oneexp; \ ulong coeff; \ int carry; \ TMP_INIT; \ \ TMP_START; \ curexp = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ degpow = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ oneexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); \ array_size = 1; \ curexp[0] = 0; \ oneexp[0] = 0; \ degpow[0] = 1; \ for (i = 0; i < nvars-1; i++) \ { \ curexp[i] = 0; \ degpow[i] = array_size; \ oneexp[i] = (UWORD(1) << (P->bits*(i+1))) - UWORD(1); \ array_size *= degb; \ } \ off = 0; \ if (nvars > 1) \ { \ curexp[nvars - 2] = top; \ off = top * degpow[nvars - 2]; \ } \ exp = (top << (P->bits*nvars)) + (top << (P->bits*(nvars-1))); \ \ carry = 1; \ do { \ if (nonzero_test) \ { \ reduce_coeff \ if (coeff != UWORD(0)) \ { \ _nmod_mpoly_fit_length(&P->coeffs, &P->coeffs_alloc, \ &P->exps, &P->exps_alloc, 1, Plen + 1); \ P->exps[Plen] = exp; \ P->coeffs[Plen] = coeff; \ Plen++; \ } \ } \ \ exp -= oneexp[0]; \ off -= 1; \ curexp[0] -= 1; \ if (curexp[0] >= 0) \ { \ carry = 0; \ } else \ { \ exp -= curexp[0]*oneexp[0]; \ off -= curexp[0]; \ curexp[0] = 0; \ carry = 1; \ \ for (i = 1; i < nvars - 1; i++) \ { \ exp -= oneexp[i]; \ off -= degpow[i]; \ curexp[i] -= 1; \ if (curexp[i] < 0) \ { \ exp -= curexp[i]*oneexp[i]; \ off -= curexp[i]*degpow[i]; \ curexp[i] = 0; \ carry = 1; \ } else \ { \ ulong t = exp & lomask; \ off += t*degpow[i - 1]; \ curexp[i - 1] = t; \ exp += t*oneexp[i - 1]; \ carry = 0; \ break; \ } \ } \ } \ } while (!carry); \ \ TMP_END; \ \ return Plen; \ } DEGLEX_UNPACK_MACRO( nmod_mpoly_append_array_sm1_DEGLEX, ulong * coeff_array , coeff_array[off] != UWORD(0) , NMOD_RED(coeff, coeff_array[off], ctx->mod); coeff_array[off] = 0; ) DEGLEX_UNPACK_MACRO( nmod_mpoly_append_array_sm2_DEGLEX, ulong * coeff_array , (coeff_array[2*off + 0] || coeff_array[2*off + 1]) != UWORD(0) , NMOD2_RED2(coeff, coeff_array[2*off + 1], coeff_array[2*off + 0], ctx->mod); coeff_array[2*off + 0] = coeff_array[2*off + 1] = 0; ) DEGLEX_UNPACK_MACRO( nmod_mpoly_append_array_sm3_DEGLEX, ulong * coeff_array , (coeff_array[3*off + 0] || coeff_array[3*off + 1] || coeff_array[3*off + 2]) != UWORD(0) , NMOD_RED3(coeff, coeff_array[3*off + 2], coeff_array[3*off + 1], coeff_array[3*off + 0], ctx->mod); coeff_array[3*off + 0] = coeff_array[3*off + 1] = coeff_array[3*off + 2] = 0; ) #define DEGREVLEX_UNPACK_MACRO(fxn_name, coeff_decl, nonzero_test, reduce_coeff) \ slong fxn_name(nmod_mpoly_t P, slong Plen, coeff_decl, \ slong top, slong nvars, slong degb, \ const nmod_mpoly_ctx_t ctx) \ { \ slong i; \ ulong exp, mask = UWORD(1) << (P->bits - 1); \ slong off, array_size; \ slong * curexp, * degpow; \ ulong * oneexp; \ ulong coeff; \ int carry; \ TMP_INIT; \ \ TMP_START; \ curexp = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ degpow = (slong *) TMP_ALLOC(nvars*sizeof(slong)); \ oneexp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); \ array_size = 1; \ oneexp[0] = 0; \ for (i = 0; i < nvars-1; i++) { \ curexp[i] = 0; \ degpow[i] = array_size; \ oneexp[i] = (UWORD(1) << (P->bits*(i+1))) - UWORD(1); \ array_size *= degb; \ } \ \ off = 0; \ exp = (top << (P->bits*nvars)) + top; \ \ do { \ if (nonzero_test) \ { \ reduce_coeff \ if (coeff != UWORD(0)) \ { \ _nmod_mpoly_fit_length(&P->coeffs, &P->coeffs_alloc, \ &P->exps, &P->exps_alloc, 1, Plen + 1); \ P->exps[Plen] = exp; \ P->coeffs[Plen] = coeff; \ Plen++; \ } \ } \ \ exp += oneexp[0]; \ off += 1; \ curexp[0] += 1; \ if ((exp & mask) == 0) \ { \ carry = (nvars - 1 == 0); \ } else \ { \ carry = 1; \ exp -= curexp[0]*oneexp[0]; \ off -= curexp[0]; \ curexp[0] = 0; \ for (i = 1; i < nvars - 1; i++) \ { \ exp += oneexp[i]; \ off += degpow[i]; \ curexp[i] += 1; \ if ((exp & mask) == 0) \ { \ carry = 0; \ break; \ } else { \ carry = 1; \ exp -= curexp[i]*oneexp[i]; \ off -= curexp[i]*degpow[i]; \ curexp[i] = 0; \ } \ } \ } \ } while (!carry); \ \ TMP_END; \ \ return Plen; \ } DEGREVLEX_UNPACK_MACRO( nmod_mpoly_append_array_sm1_DEGREVLEX, ulong * coeff_array , coeff_array[off] != WORD(0) , NMOD_RED(coeff, coeff_array[off], ctx->mod); coeff_array[off] = 0; ) DEGREVLEX_UNPACK_MACRO( nmod_mpoly_append_array_sm2_DEGREVLEX, ulong * coeff_array , (coeff_array[2*off + 0] || coeff_array[2*off + 1]) != WORD(0) , NMOD2_RED2(coeff, coeff_array[2*off + 1], coeff_array[2*off + 0], ctx->mod); coeff_array[2*off + 0] = coeff_array[2*off + 1] = 0; ) DEGREVLEX_UNPACK_MACRO( nmod_mpoly_append_array_sm3_DEGREVLEX, ulong * coeff_array , (coeff_array[3*off + 0] || coeff_array[3*off + 1] || coeff_array[3*off + 2]) != WORD(0) , NMOD_RED3(coeff, coeff_array[3*off + 2], coeff_array[3*off + 1], coeff_array[3*off + 0], ctx->mod); coeff_array[3*off + 0] = coeff_array[3*off + 1] = coeff_array[3*off + 2] = 0; ) void _nmod_mpoly_mul_array_chunked_DEG( nmod_mpoly_t P, const nmod_mpoly_t A, const nmod_mpoly_t B, ulong degb, const nmod_mpoly_ctx_t ctx) { slong nvars = ctx->minfo->nvars; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; slong (* upack_sm1)(nmod_mpoly_t, slong, ulong *, slong, slong, slong, const nmod_mpoly_ctx_t); slong (* upack_sm2)(nmod_mpoly_t, slong, ulong *, slong, slong, slong, const nmod_mpoly_ctx_t); slong (* upack_sm3)(nmod_mpoly_t, slong, ulong *, slong, slong, slong, const nmod_mpoly_ctx_t); TMP_INIT; TMP_START; /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*nvars)); Bl = 1 + (slong) (B->exps[0] >> (B->bits*nvars)); array_size = 1; for (i = 0; i < nvars-1; i++) { array_size *= degb; } upack_sm1 = &nmod_mpoly_append_array_sm1_DEGLEX; upack_sm2 = &nmod_mpoly_append_array_sm2_DEGLEX; upack_sm3 = &nmod_mpoly_append_array_sm3_DEGLEX; if (ctx->minfo->ord == ORD_DEGREVLEX) { upack_sm1 = &nmod_mpoly_append_array_sm1_DEGREVLEX; upack_sm2 = &nmod_mpoly_append_array_sm2_DEGREVLEX; upack_sm3 = &nmod_mpoly_append_array_sm3_DEGREVLEX; } /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC((Al + 1)*sizeof(slong)); Bmain = (slong *) TMP_ALLOC((Bl + 1)*sizeof(slong)); Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_DEG(Amain, Apexp, A->exps, Al, A->length, degb, nvars, A->bits); mpoly_main_variable_split_DEG(Bmain, Bpexp, B->exps, Bl, B->length, degb, nvars, B->bits); Pl = Al + Bl - 1; FLINT_ASSERT(Pl == degb); Plen = 0; { ulong * coeff_array = (ulong *) TMP_ALLOC(3*array_size*sizeof(ulong)); for (j = 0; j < 3*array_size; j++) coeff_array[j] = 0; /* for each output chunk */ for (Pi = 0; Pi < Pl; Pi++) { /* compute bound on coeffs of output chunk */ slong len = 0; mp_limb_t t2, t1, t0, u1, u0; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { len += FLINT_MIN(Amain[i + 1] - Amain[i], Bmain[j + 1] - Bmain[j]); } } umul_ppmm(t1, t0, ctx->mod.n - 1, ctx->mod.n - 1); umul_ppmm(t2, t1, t1, len); umul_ppmm(u1, u0, t0, len); add_sssaaaaaa(t2, t1, t0, t2, t1, UWORD(0), UWORD(0), u1, u0); if (t2 != UWORD(0)) { /* need three words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _nmod_mpoly_addmul_array1_ulong3(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = upack_sm3(P, Plen, coeff_array, Pl - Pi - 1, nvars, degb, ctx); } else if (t1 != UWORD(0)) { /* fits into two words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _nmod_mpoly_addmul_array1_ulong2(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = upack_sm2(P, Plen, coeff_array, Pl - Pi - 1, nvars, degb, ctx); } else if (t0 != UWORD(0)) { /* fits into one word */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { _nmod_mpoly_addmul_array1_ulong1(coeff_array, A->coeffs + Amain[i], Apexp + Amain[i], Amain[i + 1] - Amain[i], B->coeffs + Bmain[j], Bpexp + Bmain[j], Bmain[j + 1] - Bmain[j]); } } Plen = upack_sm1(P, Plen, coeff_array, Pl - Pi - 1, nvars, degb, ctx); } } } _nmod_mpoly_set_length(P, Plen, ctx); flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _nmod_mpoly_mul_array_DEG( nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx) { slong i, exp_bits, array_size; ulong deg; int success; FLINT_ASSERT(ctx->minfo->nvars > 0); FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT( ctx->minfo->ord == ORD_DEGREVLEX || ctx->minfo->ord == ORD_DEGLEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); /* the field of index n-1 is the one that will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); deg = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); if (((slong) deg) <= 0 || deg > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...1, contribute to the array size */ array_size = WORD(1); for (i--; i >= 1; i--) { ulong hi; umul_ppmm(hi, array_size, array_size, deg); if (hi != WORD(0) || array_size <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(deg) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fit into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { nmod_mpoly_t T; nmod_mpoly_init3(T, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_DEG(T, C, B, deg, ctx); nmod_mpoly_swap(T, A, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(A, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_DEG(A, C, B, deg, ctx); } success = 1; cleanup: return success; } int nmod_mpoly_mul_array(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) { slong i; int success; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length == 0 || C->length == 0) { nmod_mpoly_zero(A, ctx); return 1; } if (ctx->minfo->nvars < 1 || 1 != mpoly_words_per_exp(B->bits, ctx->minfo) || 1 != mpoly_words_per_exp(C->bits, ctx->minfo)) { return 0; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); switch (ctx->minfo->ord) { case ORD_LEX: { success = _nmod_mpoly_mul_array_LEX(A, B, maxBfields, C, maxCfields, ctx); break; } case ORD_DEGLEX: case ORD_DEGREVLEX: { success = _nmod_mpoly_mul_array_DEG(A, B, maxBfields, C, maxCfields, ctx); break; } default: { success = 0; break; } } for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; return success; } flint-3.1.3/src/nmod_mpoly/mul_array_threaded.c000066400000000000000000000632031461254215100216020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" /* improve locality */ #define BLOCK 128 #define MAX_ARRAY_SIZE (WORD(300000)) #define MAX_LEX_SIZE (WORD(300)) typedef struct { slong idx; slong work; slong len; nmod_mpoly_t poly; } _chunk_struct; typedef struct { #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif volatile int idx; slong nthreads; slong Al, Bl, Pl; mp_limb_t * Acoeffs, * Bcoeffs; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; slong * perm; slong nvars; const ulong * mults; slong array_size; slong degb; const nmod_mpoly_ctx_struct * ctx; _chunk_struct * Pchunks; int rev; } _base_struct; typedef _base_struct _base_t[1]; typedef struct { slong idx; slong time; _base_struct * base; ulong * exp; } _worker_arg_struct; /****************** LEX ******************/ static void _nmod_mpoly_mul_array_threaded_worker_LEX(void * varg) { slong i, j, Pi; _worker_arg_struct * arg = (_worker_arg_struct *) varg; _base_struct * base = arg->base; slong Al = base->Al; slong Bl = base->Bl; slong Pl = base->Pl; slong * Amain = base->Amain; slong * Bmain = base->Bmain; ulong * coeff_array; TMP_INIT; TMP_START; coeff_array = (ulong *) TMP_ALLOC(3*base->array_size*sizeof(ulong)); for (j = 0; j < 3*base->array_size; j++) coeff_array[j] = 0; #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif while (Pi < Pl) { slong len; mp_limb_t t2, t1, t0, u1, u0; Pi = base->perm[Pi]; /* work out bit counts for this chunk */ len = 0; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { len += FLINT_MIN(Amain[i + 1] - Amain[i], Bmain[j + 1] - Bmain[j]); } } umul_ppmm(t1, t0, base->ctx->mod.n - 1, base->ctx->mod.n - 1); umul_ppmm(t2, t1, t1, len); umul_ppmm(u1, u0, t0, len); add_sssaaaaaa(t2, t1, t0, t2, t1, UWORD(0), UWORD(0), u1, u0); (base->Pchunks + Pi)->len = 0; if (t2 != 0) { /* need three words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j >= Bl) continue; _nmod_mpoly_addmul_array1_ulong3(coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } (base->Pchunks + Pi)->len = nmod_mpoly_append_array_sm3_LEX( (base->Pchunks + Pi)->poly, 0, coeff_array, base->mults, base->nvars - 1, base->array_size, Pl - Pi - 1, base->ctx); } else if (t1 != 0) { /* fits into two words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j >= Bl) continue; _nmod_mpoly_addmul_array1_ulong2(coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } (base->Pchunks + Pi)->len = nmod_mpoly_append_array_sm2_LEX( (base->Pchunks + Pi)->poly, 0, coeff_array, base->mults, base->nvars - 1, base->array_size, Pl - Pi - 1, base->ctx); } else if (t0 != 0) { /* fits into one word */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j >= Bl) continue; _nmod_mpoly_addmul_array1_ulong1(coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } (base->Pchunks + Pi)->len = nmod_mpoly_append_array_sm1_LEX( (base->Pchunks + Pi)->poly, 0, coeff_array, base->mults, base->nvars - 1, base->array_size, Pl - Pi - 1, base->ctx); } #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } TMP_END; } void _nmod_mpoly_mul_array_chunked_threaded_LEX( nmod_mpoly_t P, const nmod_mpoly_t A, const nmod_mpoly_t B, const ulong * mults, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong nvars = ctx->minfo->nvars; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; _base_t base; _worker_arg_struct * args; _chunk_struct * Pchunks; slong * perm; TMP_INIT; array_size = 1; for (i = 0; i < nvars - 1; i++) { array_size *= mults[i]; } /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*(nvars - 1))); Bl = 1 + (slong) (B->exps[0] >> (B->bits*(nvars - 1))); TMP_START; /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC((Al + 1)*sizeof(slong)); Bmain = (slong *) TMP_ALLOC((Bl + 1)*sizeof(slong)); Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_LEX(Amain, Apexp, A->exps, Al, A->length, mults, nvars - 1, A->bits); mpoly_main_variable_split_LEX(Bmain, Bpexp, B->exps, Bl, B->length, mults, nvars - 1, B->bits); Pl = Al + Bl - 1; /* work out data for each chunk of the output */ Pchunks = (_chunk_struct *) TMP_ALLOC(Pl*sizeof(_chunk_struct)); perm = (slong *) TMP_ALLOC(Pl*sizeof(slong)); for (Pi = 0; Pi < Pl; Pi++) { nmod_mpoly_init3((Pchunks + Pi)->poly, 8, P->bits, ctx); (Pchunks + Pi)->work = 0; perm[Pi] = Pi; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j >= Bl) continue; (Pchunks + Pi)->work += (Amain[i + 1] - Amain[i]) *(Bmain[j + 1] - Bmain[j]); } } for (i = 0; i < Pl; i++) { for (j = i; j > 0 && (Pchunks + perm[j - 1])->work < (Pchunks + perm[j])->work; j--) { slong t = perm[j - 1]; perm[j - 1] = perm[j]; perm[j] = t; } } base->nthreads = num_handles + 1; base->Al = Al; base->Bl = Bl; base->Pl = Pl; base->Acoeffs = A->coeffs; base->Amain = Amain; base->Apexp = Apexp; base->Bcoeffs = B->coeffs; base->Bmain = Bmain; base->Bpexp = Bpexp; base->idx = 0; base->perm = perm; base->nvars = nvars; base->ctx = ctx; base->Pchunks = Pchunks; base->array_size = array_size; base->mults = mults; args = (_worker_arg_struct *) TMP_ALLOC(base->nthreads *sizeof(_worker_arg_struct)); #if FLINT_USES_PTHREAD pthread_mutex_init(&base->mutex, NULL); #endif for (i = 0; i < num_handles; i++) { args[i].idx = i; args[i].base = base; thread_pool_wake(global_thread_pool, handles[i], 0, _nmod_mpoly_mul_array_threaded_worker_LEX, &args[i]); } i = num_handles; args[i].idx = i; args[i].base = base; _nmod_mpoly_mul_array_threaded_worker_LEX(&args[i]); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&base->mutex); #endif /* join answers */ Plen = 0; for (Pi = 0; Pi < Pl; Pi++) { _nmod_mpoly_fit_length(&P->coeffs, &P->coeffs_alloc, &P->exps, &P->exps_alloc, 1, Plen + (Pchunks + Pi)->len); FLINT_ASSERT((Pchunks + Pi)->poly->coeffs != NULL); FLINT_ASSERT((Pchunks + Pi)->poly->exps != NULL); memcpy(P->exps + Plen, (Pchunks + Pi)->poly->exps, (Pchunks + Pi)->len*sizeof(ulong)); memcpy(P->coeffs + Plen, (Pchunks + Pi)->poly->coeffs, (Pchunks + Pi)->len*sizeof(mp_limb_t)); Plen += (Pchunks + Pi)->len; flint_free((Pchunks + Pi)->poly->coeffs); flint_free((Pchunks + Pi)->poly->exps); } P->length = Plen; flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _nmod_mpoly_mul_array_threaded_pool_LEX( nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong i, exp_bits, array_size; ulong max, * mults; int success; TMP_INIT; FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); TMP_START; /* compute maximum exponents for each variable */ mults = (ulong *) TMP_ALLOC(ctx->minfo->nfields*sizeof(ulong)); /* the field of index n-1 is the one that will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max = mults[i]; if (((slong) mults[i]) <= 0 || mults[i] > MAX_LEX_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...0, contribute to the array size */ array_size = WORD(1); for (i--; i >= 0; i--) { ulong hi; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); mults[i] = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); max |= mults[i]; umul_ppmm(hi, array_size, array_size, mults[i]); if (hi != 0 || (slong) mults[i] <= 0 || array_size <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(max) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fits into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { nmod_mpoly_t T; nmod_mpoly_init3(T, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_threaded_LEX(T, C, B, mults, ctx, handles, num_handles); nmod_mpoly_swap(T, A, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(A, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_threaded_LEX(A, C, B, mults, ctx, handles, num_handles); } success = 1; cleanup: TMP_END; return success; } /***************************** DEGLEX and DEGREVLEX *****************************/ static void _nmod_mpoly_mul_array_threaded_worker_DEG(void * varg) { slong i, j, Pi; _worker_arg_struct * arg = (_worker_arg_struct *) varg; _base_struct * base = arg->base; slong Al = base->Al; slong Bl = base->Bl; slong Pl = base->Pl; slong * Amain = base->Amain; slong * Bmain = base->Bmain; ulong * coeff_array; slong (* upack_sm1)(nmod_mpoly_t, slong, ulong *, slong, slong, slong, const nmod_mpoly_ctx_t); slong (* upack_sm2)(nmod_mpoly_t, slong, ulong *, slong, slong, slong, const nmod_mpoly_ctx_t); slong (* upack_sm3)(nmod_mpoly_t, slong, ulong *, slong, slong, slong, const nmod_mpoly_ctx_t); TMP_INIT; upack_sm1 = &nmod_mpoly_append_array_sm1_DEGLEX; upack_sm2 = &nmod_mpoly_append_array_sm2_DEGLEX; upack_sm3 = &nmod_mpoly_append_array_sm3_DEGLEX; if (base->rev) { upack_sm1 = &nmod_mpoly_append_array_sm1_DEGREVLEX; upack_sm2 = &nmod_mpoly_append_array_sm2_DEGREVLEX; upack_sm3 = &nmod_mpoly_append_array_sm3_DEGREVLEX; } TMP_START; coeff_array = (ulong *) TMP_ALLOC(3*base->array_size*sizeof(ulong)); for (j = 0; j < 3*base->array_size; j++) coeff_array[j] = 0; #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif while (Pi < Pl) { slong len; mp_limb_t t2, t1, t0, u1, u0; Pi = base->perm[Pi]; /* work out bit counts for this chunk */ len = 0; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { len += FLINT_MIN(Amain[i + 1] - Amain[i], Bmain[j + 1] - Bmain[j]); } } umul_ppmm(t1, t0, base->ctx->mod.n - 1, base->ctx->mod.n - 1); umul_ppmm(t2, t1, t1, len); umul_ppmm(u1, u0, t0, len); add_sssaaaaaa(t2, t1, t0, t2, t1, UWORD(0), UWORD(0), u1, u0); (base->Pchunks + Pi)->len = 0; if (t2 != 0) { /* need three words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j >= Bl) continue; _nmod_mpoly_addmul_array1_ulong3(coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } (base->Pchunks + Pi)->len = upack_sm3((base->Pchunks + Pi)->poly, 0, coeff_array, Pl - Pi - 1, base->nvars, base->degb, base->ctx); } else if (t1 != 0) { /* fits into two words */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j >= Bl) continue; _nmod_mpoly_addmul_array1_ulong2(coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } (base->Pchunks + Pi)->len = upack_sm2((base->Pchunks + Pi)->poly, 0, coeff_array, Pl - Pi - 1, base->nvars, base->degb, base->ctx); } else if (t0 != 0) { /* fits into one word */ for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j >= Bl) continue; _nmod_mpoly_addmul_array1_ulong1(coeff_array, base->Acoeffs + base->Amain[i], base->Apexp + base->Amain[i], base->Amain[i + 1] - base->Amain[i], base->Bcoeffs + base->Bmain[j], base->Bpexp + base->Bmain[j], base->Bmain[j + 1] - base->Bmain[j]); } (base->Pchunks + Pi)->len = upack_sm1((base->Pchunks + Pi)->poly, 0, coeff_array, Pl - Pi - 1, base->nvars, base->degb, base->ctx); } #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif Pi = base->idx; base->idx = Pi + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } TMP_END; } void _nmod_mpoly_mul_array_chunked_threaded_DEG( nmod_mpoly_t P, const nmod_mpoly_t A, const nmod_mpoly_t B, ulong degb, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong nvars = ctx->minfo->nvars; slong Pi, i, j, Plen, Pl, Al, Bl, array_size; slong * Amain, * Bmain; ulong * Apexp, * Bpexp; _base_t base; _worker_arg_struct * args; _chunk_struct * Pchunks; slong * perm; TMP_INIT; /* compute lengths of poly2 and poly3 in chunks */ Al = 1 + (slong) (A->exps[0] >> (A->bits*nvars)); Bl = 1 + (slong) (B->exps[0] >> (B->bits*nvars)); array_size = 1; for (i = 0; i < nvars-1; i++) { array_size *= degb; } TMP_START; /* compute indices and lengths of coefficients of polys in main variable */ Amain = (slong *) TMP_ALLOC((Al + 1)*sizeof(slong)); Bmain = (slong *) TMP_ALLOC((Bl + 1)*sizeof(slong)); Apexp = (ulong *) flint_malloc(A->length*sizeof(ulong)); Bpexp = (ulong *) flint_malloc(B->length*sizeof(ulong)); mpoly_main_variable_split_DEG(Amain, Apexp, A->exps, Al, A->length, degb, nvars, A->bits); mpoly_main_variable_split_DEG(Bmain, Bpexp, B->exps, Bl, B->length, degb, nvars, B->bits); Pl = Al + Bl - 1; FLINT_ASSERT(Pl == degb); /* work out data for each chunk of the output */ Pchunks = (_chunk_struct *) TMP_ALLOC(Pl*sizeof(_chunk_struct)); perm = (slong *) TMP_ALLOC(Pl*sizeof(slong)); for (Pi = 0; Pi < Pl; Pi++) { nmod_mpoly_init3((Pchunks + Pi)->poly, 8, P->bits, ctx); (Pchunks + Pi)->work = 0; perm[Pi] = Pi; for (i = 0, j = Pi; i < Al && j >= 0; i++, j--) { if (j < Bl) { (Pchunks + Pi)->work += (Amain[i + 1] - Amain[i]) *(Bmain[j + 1] - Bmain[j]); } } } for (i = 0; i < Pl; i++) { for (j = i; j > 0 && (Pchunks + perm[j-1])->work < (Pchunks + perm[j])->work; j--) { slong t = perm[j - 1]; perm[j - 1] = perm[j]; perm[j] = t; } } base->nthreads = num_handles + 1; base->Al = Al; base->Bl = Bl; base->Pl = Pl; base->Acoeffs = A->coeffs; base->Amain = Amain; base->Apexp = Apexp; base->Bcoeffs = B->coeffs; base->Bmain = Bmain; base->Bpexp = Bpexp; base->idx = 0; base->perm = perm; base->nvars = nvars; base->Pchunks = Pchunks; base->ctx = ctx; base->array_size = array_size; base->degb = degb; base->rev = (ctx->minfo->ord == ORD_DEGREVLEX); args = (_worker_arg_struct *) TMP_ALLOC(base->nthreads *sizeof(_worker_arg_struct)); #if FLINT_USES_PTHREAD pthread_mutex_init(&base->mutex, NULL); #endif for (i = 0; i < num_handles; i++) { args[i].idx = i; args[i].base = base; thread_pool_wake(global_thread_pool, handles[i], 0, _nmod_mpoly_mul_array_threaded_worker_DEG, &args[i]); } i = num_handles; args[i].idx = i; args[i].base = base; _nmod_mpoly_mul_array_threaded_worker_DEG(&args[i]); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&base->mutex); #endif /* join answers */ Plen = 0; for (Pi = 0; Pi < Pl; Pi++) { _nmod_mpoly_fit_length(&P->coeffs, &P->coeffs_alloc, &P->exps, &P->exps_alloc, 1, Plen + (Pchunks + Pi)->len); FLINT_ASSERT((Pchunks + Pi)->poly->coeffs != NULL); FLINT_ASSERT((Pchunks + Pi)->poly->exps != NULL); memcpy(P->exps + Plen, (Pchunks + Pi)->poly->exps, (Pchunks + Pi)->len*sizeof(ulong)); memcpy(P->coeffs + Plen, (Pchunks + Pi)->poly->coeffs, (Pchunks + Pi)->len*sizeof(mp_limb_t)); Plen += (Pchunks + Pi)->len; flint_free((Pchunks + Pi)->poly->coeffs); flint_free((Pchunks + Pi)->poly->exps); } P->length = Plen; flint_free(Apexp); flint_free(Bpexp); TMP_END; } int _nmod_mpoly_mul_array_threaded_pool_DEG( nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong i, exp_bits, array_size; ulong deg; int success; FLINT_ASSERT(B->length != 0); FLINT_ASSERT(C->length != 0); FLINT_ASSERT( ctx->minfo->ord == ORD_DEGREVLEX || ctx->minfo->ord == ORD_DEGLEX); FLINT_ASSERT(1 == mpoly_words_per_exp(B->bits, ctx->minfo)); FLINT_ASSERT(1 == mpoly_words_per_exp(C->bits, ctx->minfo)); /* the field of index n-1 is the one that will be pulled out */ i = ctx->minfo->nfields - 1; FLINT_ASSERT(fmpz_fits_si(maxBfields + i)); FLINT_ASSERT(fmpz_fits_si(maxCfields + i)); deg = 1 + fmpz_get_ui(maxBfields + i) + fmpz_get_ui(maxCfields + i); if (((slong) deg) <= 0 || deg > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } /* the fields of index n-2...1, contribute to the array size */ array_size = WORD(1); for (i--; i >= 1; i--) { ulong hi; umul_ppmm(hi, array_size, array_size, deg); if (hi != WORD(0) || array_size <= 0 || array_size > MAX_ARRAY_SIZE) { success = 0; goto cleanup; } } exp_bits = FLINT_MAX(MPOLY_MIN_BITS, FLINT_BIT_COUNT(deg) + 1); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); /* array multiplication assumes result fit into 1 word */ if (1 != mpoly_words_per_exp(exp_bits, ctx->minfo)) { success = 0; goto cleanup; } /* handle aliasing and do array multiplication */ if (A == B || A == C) { nmod_mpoly_t T; nmod_mpoly_init3(T, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_threaded_DEG(T, C, B, deg, ctx, handles, num_handles); nmod_mpoly_swap(T, A, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(A, B->length + C->length - 1, exp_bits, ctx); _nmod_mpoly_mul_array_chunked_threaded_DEG(A, C, B, deg, ctx, handles, num_handles); } success = 1; cleanup: return success; } int nmod_mpoly_mul_array_threaded( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) { slong i; int success; fmpz * maxBfields, * maxCfields; thread_pool_handle * handles; slong num_handles; slong thread_limit = FLINT_MIN(B->length, C->length)/16; TMP_INIT; if (B->length == 0 || C->length == 0) { nmod_mpoly_zero(A, ctx); return 1; } if (ctx->minfo->nvars < 1 || 1 != mpoly_words_per_exp(B->bits, ctx->minfo) || 1 != mpoly_words_per_exp(C->bits, ctx->minfo)) { return 0; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); num_handles = flint_request_threads(&handles, thread_limit); switch (ctx->minfo->ord) { case ORD_LEX: { success = _nmod_mpoly_mul_array_threaded_pool_LEX(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); break; } case ORD_DEGREVLEX: case ORD_DEGLEX: { success = _nmod_mpoly_mul_array_threaded_pool_DEG(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); break; } default: { success = 0; break; } } flint_give_back_threads(handles, num_handles); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; return success; } flint-3.1.3/src/nmod_mpoly/mul_dense.c000066400000000000000000000115621461254215100177230ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" int _nmod_mpoly_mul_dense(nmod_mpoly_t P, const nmod_mpoly_t A, fmpz * maxAfields, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_ctx_t ctx) { int success = 1; slong i; slong nvars = ctx->minfo->nvars; nmod_mpolyd_ctx_t dctx; nmod_mpolyd_t Ad, Bd, Pd; nmod_poly_t Au, Bu, Pu; slong * Abounds, * Bbounds, * Pbounds; TMP_INIT; FLINT_ASSERT(A->length != 0); FLINT_ASSERT(B->length != 0); FLINT_ASSERT(nvars > 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); TMP_START; /* set the ordering of variables for the dense representation */ nmod_mpolyd_ctx_init(dctx, nvars); /* for each variable v except for the outermost variable, we need to pack to degree deg_v(A) + deg_v(B) */ Abounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Bbounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); Pbounds = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong)); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Abounds, maxAfields, ctx->minfo); mpoly_get_monomial_ui_unpacked_ffmpz((ulong *)Bbounds, maxBfields, ctx->minfo); for (i = 0; i < ctx->minfo->nvars; i++) { Abounds[i] = Abounds[i] + 1; Bbounds[i] = Bbounds[i] + 1; Pbounds[i] = Abounds[i] + Bbounds[i] - 1; if ((Abounds[i] | Bbounds[i] | Pbounds[i]) < WORD(0)) { goto failed_stage1; } if (i != dctx->perm[0]) { /* variable of index i is not the outermost */ Abounds[i] = Pbounds[i]; Bbounds[i] = Pbounds[i]; } } nmod_mpolyd_init(Ad, nvars); nmod_mpolyd_init(Bd, nvars); nmod_mpolyd_init(Pd, nvars); success = 1; success = success && nmod_mpolyd_set_degbounds_perm(Ad, dctx, Abounds); success = success && nmod_mpolyd_set_degbounds_perm(Bd, dctx, Bbounds); success = success && nmod_mpolyd_set_degbounds_perm(Pd, dctx, Pbounds); if (!success) { goto failed_stage2; } nmod_mpoly_convert_to_nmod_mpolyd_degbound(Ad, dctx, A, ctx); nmod_mpoly_convert_to_nmod_mpolyd_degbound(Bd, dctx, B, ctx); /* let Au and Bu borrow Ad and Bd */ Au->alloc = Ad->coeff_alloc; Au->coeffs = Ad->coeffs; Au->length = nmod_mpolyd_length(Ad); Au->mod = ctx->mod; Bu->alloc = Bd->coeff_alloc; Bu->coeffs = Bd->coeffs; Bu->length = nmod_mpolyd_length(Bd); Bu->mod = ctx->mod; /* manually move P to Pu */ Pu->alloc = Pd->coeff_alloc; Pu->coeffs = Pd->coeffs; Pu->length = 0; Pu->mod = ctx->mod; nmod_poly_mul(Pu, Au, Bu); /* manually move Pu to P */ Pd->coeff_alloc = Pu->alloc; Pd->coeffs = Pu->coeffs; for (i = Pu->length; i < Pd->coeff_alloc; i++) Pd->coeffs[i] = UWORD(0); nmod_mpolyd_clear(Bd); nmod_mpolyd_clear(Ad); nmod_mpoly_convert_from_nmod_mpolyd(P, ctx, Pd, dctx); nmod_mpolyd_clear(Pd); nmod_mpolyd_ctx_clear(dctx); done: TMP_END; return success; failed_stage2: nmod_mpolyd_clear(Ad); nmod_mpolyd_clear(Bd); nmod_mpolyd_clear(Pd); failed_stage1: nmod_mpolyd_ctx_clear(dctx); success = 0; goto done; } int nmod_mpoly_mul_dense(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) { slong i; int success; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length == 0 || C->length == 0) { nmod_mpoly_zero(A, ctx); return 1; } if (B->bits > FLINT_BITS || C->bits > FLINT_BITS || ctx->minfo->nvars < 1) { return 0; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); success = _nmod_mpoly_mul_dense(A, B, maxBfields, C, maxCfields, ctx); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; return success; } flint-3.1.3/src/nmod_mpoly/mul_heap_threaded.c000066400000000000000000000575711461254215100214140ustar00rootroot00000000000000/* Copyright (C) 2017-2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "long_extras.h" #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" /* set A = the part of B*C with exps in [start, end) this functions reallocates A and returns the length of A version for N == 1 */ void _nmod_mpoly_mul_heap_part1( nmod_mpoly_t A, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeff, const ulong * Cexp, slong Clen, slong * start, slong * end, slong * hind, const nmod_mpoly_stripe_t S) { const ulong cmpmask = S->cmpmask[0]; slong i, j; ulong exp; mpoly_heap_t * x; slong next_loc; slong heap_len; mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * store, * store_base; slong Alen; ulong * Aexp = A->exps; mp_limb_t * Acoeff = A->coeffs; mp_limb_t acc0, acc1, acc2, pp0, pp1; FLINT_ASSERT(S->N == 1); /* tmp allocs from S->big_mem */ i = 0; store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); heap = (mpoly_heap1_s *)(S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap1_s); chain = (mpoly_heap_t *)(S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); /* put all the starting nodes on the heap */ heap_len = 1; /* heap zero index unused */ next_loc = Blen + 4; /* something bigger than heap can ever be */ for (i = 0; i < Blen; i++) { hind[i] = 2*start[i] + 1; } for (i = 0; i < Blen; i++) { if ( (start[i] < end[i]) && ( (i == 0) || (start[i] < start[i - 1]) ) ) { x = chain + i; x->i = i; x->j = start[i]; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, cmpmask); } } Alen = 0; while (heap_len > 1) { exp = heap[1].exp; _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, 1, Alen + 1); Aexp[Alen] = exp; acc0 = acc1 = acc2 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(Acoeff[Alen], acc2, acc1, acc0, S->mod); Alen += (Acoeff[Alen] != UWORD(0)); /* for each node temporarily stored */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < end[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, cmpmask); } /* should we go up? */ if ( (j + 1 < end[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; _mpoly_heap_insert1(heap, Bexp[x->i] + Cexp[x->j], x, &next_loc, &heap_len, cmpmask); } } } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; } void _nmod_mpoly_mul_heap_part( nmod_mpoly_t A, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeff, const ulong * Cexp, slong Clen, slong * start, slong * end, slong * hind, const nmod_mpoly_stripe_t S) { flint_bitcnt_t bits = S->bits; slong N = S->N; const ulong * cmpmask = S->cmpmask; slong i, j; slong next_loc; slong heap_len; ulong * exp, * exps; ulong ** exp_list; slong exp_next; mpoly_heap_t * x; mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; slong Alen; ulong * Aexp = A->exps; mp_limb_t * Acoeff = A->coeffs; ulong acc0, acc1, acc2, pp0, pp1; /* tmp allocs from S->big_mem */ i = 0; store = store_base = (slong *) (S->big_mem + i); i += 2*Blen*sizeof(slong); exp_list = (ulong **) (S->big_mem + i); i += Blen*sizeof(ulong *); exps = (ulong *) (S->big_mem + i); i += Blen*N*sizeof(ulong); heap = (mpoly_heap_s *) (S->big_mem + i); i += (Blen + 1)*sizeof(mpoly_heap_s); chain = (mpoly_heap_t *) (S->big_mem + i); i += Blen*sizeof(mpoly_heap_t); FLINT_ASSERT(i <= S->big_mem_alloc); /* put all the starting nodes on the heap */ heap_len = 1; /* heap zero index unused */ next_loc = Blen + 4; /* something bigger than heap can ever be */ exp_next = 0; for (i = 0; i < Blen; i++) exp_list[i] = exps + N*i; for (i = 0; i < Blen; i++) hind[i] = 2*start[i] + 1; for (i = 0; i < Blen; i++) { if ( (start[i] < end[i]) && ( (i == 0) || (start[i] < start[i - 1]) ) ) { x = chain + i; x->i = i; x->j = start[i]; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } Alen = 0; while (heap_len > 1) { exp = heap[1].exp; _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + 1); mpoly_monomial_set(Aexp + N*Alen, exp, N); acc0 = acc1 = acc2 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Bcoeff[x->i], Ccoeff[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(Acoeff[Alen], acc2, acc1, acc0, S->mod); Alen += (Acoeff[Alen] != UWORD(0)); /* for each node temporarily stored */ while (store > store_base) { j = *--store; i = *--store; /* should we go right? */ if ( (i + 1 < Blen) && (j + 0 < end[i + 1]) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ( (j + 1 < end[i + 0]) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Bexp + N*x->i, Cexp + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; } /* The workers calculate product terms from 4*n divisions, where n is the number of threads. */ typedef struct { volatile int idx; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif slong nthreads; slong ndivs; const nmod_mpoly_ctx_struct * ctx; mp_limb_t * Acoeff; ulong * Aexp; const mp_limb_t * Bcoeff; const ulong * Bexp; slong Blen; const mp_limb_t * Ccoeff; const ulong * Cexp; slong Clen; slong N; flint_bitcnt_t bits; const ulong * cmpmask; } _base_struct; typedef _base_struct _base_t[1]; typedef struct { slong lower; slong upper; slong thread_idx; slong Aoffset; nmod_mpoly_t A; } _div_struct; typedef struct { nmod_mpoly_stripe_t S; slong idx; slong time; _base_struct * base; _div_struct * divs; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; pthread_cond_t cond; #endif slong * t1, * t2, * t3, * t4; ulong * exp; } _worker_arg_struct; /* The workers simply take the next available division and calculate all product terms in this division. */ #define SWAP_PTRS(xx, yy) \ do { \ tt = xx; \ xx = yy; \ yy = tt; \ } while (0) static void _nmod_mpoly_mul_heap_threaded_worker(void * arg_ptr) { _worker_arg_struct * arg = (_worker_arg_struct *) arg_ptr; nmod_mpoly_stripe_struct * S = arg->S; _div_struct * divs = arg->divs; _base_struct * base = arg->base; slong Blen = base->Blen; slong N = base->N; slong i, j; ulong * exp; slong score; slong * start, * end, * t1, * t2, * t3, * t4, * tt; exp = (ulong *) flint_malloc(N*sizeof(ulong)); t1 = (slong *) flint_malloc(Blen*sizeof(slong)); t2 = (slong *) flint_malloc(Blen*sizeof(slong)); t3 = (slong *) flint_malloc(Blen*sizeof(slong)); t4 = (slong *) flint_malloc(Blen*sizeof(slong)); S->N = N; S->bits = base->bits; S->cmpmask = base->cmpmask; S->ctx = base->ctx; S->mod = base->ctx->mod; S->big_mem_alloc = 0; if (N == 1) { S->big_mem_alloc += 2*Blen*sizeof(slong); S->big_mem_alloc += (Blen + 1)*sizeof(mpoly_heap1_s); S->big_mem_alloc += Blen*sizeof(mpoly_heap_t); } else { S->big_mem_alloc += 2*Blen*sizeof(slong); S->big_mem_alloc += (Blen + 1)*sizeof(mpoly_heap_s); S->big_mem_alloc += Blen*sizeof(mpoly_heap_t); S->big_mem_alloc += Blen*S->N*sizeof(ulong); S->big_mem_alloc += Blen*sizeof(ulong *); } S->big_mem = (char *) flint_malloc(S->big_mem_alloc); /* get index to start working on */ if (arg->idx + 1 < base->nthreads) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif i = base->idx - 1; base->idx = i; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } else { i = base->ndivs - 1; } while (i >= 0) { FLINT_ASSERT(divs[i].thread_idx == -WORD(1)); divs[i].thread_idx = arg->idx; /* calculate start */ if (i + 1 < base-> ndivs) { mpoly_search_monomials( &start, exp, &score, t1, t2, t3, divs[i].lower, divs[i].lower, base->Bexp, base->Blen, base->Cexp, base->Clen, base->N, base->cmpmask); if (start == t2) { SWAP_PTRS(t1, t2); } else if (start == t3) { SWAP_PTRS(t1, t3); } } else { start = t1; for (j = 0; j < base->Blen; j++) start[j] = 0; } /* calculate end */ if (i > 0) { mpoly_search_monomials( &end, exp, &score, t2, t3, t4, divs[i - 1].lower, divs[i - 1].lower, base->Bexp, base->Blen, base->Cexp, base->Clen, base->N, base->cmpmask); if (end == t3) { SWAP_PTRS(t2, t3); } else if (end == t4) { SWAP_PTRS(t2, t4); } } else { end = t2; for (j = 0; j < base->Blen; j++) end[j] = base->Clen; } /* t3 and t4 are free for workspace at this point */ /* calculate products in [start, end) */ _nmod_mpoly_fit_length(&divs[i].A->coeffs, &divs[i].A->coeffs_alloc, &divs[i].A->exps, &divs[i].A->exps_alloc, N, 256); if (N == 1) { _nmod_mpoly_mul_heap_part1(divs[i].A, base->Bcoeff, base->Bexp, base->Blen, base->Ccoeff, base->Cexp, base->Clen, start, end, t3, S); } else { _nmod_mpoly_mul_heap_part(divs[i].A, base->Bcoeff, base->Bexp, base->Blen, base->Ccoeff, base->Cexp, base->Clen, start, end, t3, S); } /* get next index to work on */ #if FLINT_USES_PTHREAD pthread_mutex_lock(&base->mutex); #endif i = base->idx - 1; base->idx = i; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&base->mutex); #endif } /* clean up */ flint_free(S->big_mem); flint_free(t4); flint_free(t3); flint_free(t2); flint_free(t1); flint_free(exp); } static void _join_worker(void * varg) { _worker_arg_struct * arg = (_worker_arg_struct *) varg; _div_struct * divs = arg->divs; _base_struct * base = arg->base; slong N = base->N; slong i; for (i = base->ndivs - 2; i >= 0; i--) { FLINT_ASSERT(divs[i].thread_idx != -WORD(1)); if (divs[i].thread_idx != arg->idx) continue; FLINT_ASSERT(divs[i].A->coeffs != NULL); FLINT_ASSERT(divs[i].A->exps != NULL); memcpy(base->Acoeff + divs[i].Aoffset, divs[i].A->coeffs, divs[i].A->length*sizeof(mp_limb_t)); memcpy(base->Aexp + N*divs[i].Aoffset, divs[i].A->exps, N*divs[i].A->length*sizeof(ulong)); flint_free(divs[i].A->coeffs); flint_free(divs[i].A->exps); } } void _nmod_mpoly_mul_heap_threaded( nmod_mpoly_t A, const mp_limb_t * Bcoeff, const ulong * Bexp, slong Blen, const mp_limb_t * Ccoeff, const ulong * Cexp, slong Clen, flint_bitcnt_t bits, slong N, const ulong * cmpmask, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong i; _base_t base; _div_struct * divs; _worker_arg_struct * args; slong BClen, Alen; /* bail if product of lengths overflows a word */ if (z_mul_checked(&BClen, Blen, Clen)) { _nmod_mpoly_mul_johnson(A, Bcoeff, Bexp, Blen, Ccoeff, Cexp, Clen, bits, N, cmpmask, ctx->mod); return; } base->nthreads = num_handles + 1; base->ndivs = base->nthreads*4; /* number of divisions */ base->Bcoeff = Bcoeff; base->Bexp = Bexp; base->Blen = Blen; base->Ccoeff = Ccoeff; base->Cexp = Cexp; base->Clen = Clen; base->bits = bits; base->N = N; base->cmpmask = cmpmask; base->idx = base->ndivs - 1; /* decremented by worker threads */ base->ctx = ctx; divs = (_div_struct *) flint_malloc(base->ndivs*sizeof(_div_struct)); args = (_worker_arg_struct *) flint_malloc(base->nthreads *sizeof(_worker_arg_struct)); /* allocate space and set the boundary for each division */ FLINT_ASSERT(BClen/Blen == Clen); for (i = base->ndivs - 1; i >= 0; i--) { double d = (double)(i + 1) / (double)(base->ndivs); /* divisions decrease in size so that no worker finishes too early */ divs[i].lower = (d * d) * BClen; divs[i].lower = FLINT_MIN(divs[i].lower, BClen); divs[i].lower = FLINT_MAX(divs[i].lower, WORD(0)); divs[i].upper = divs[i].lower; divs[i].Aoffset = -WORD(1); divs[i].thread_idx = -WORD(1); if (i == base->ndivs - 1) { /* highest division writes to original poly */ *divs[i].A = *A; } else { /* lower divisions write to a new worker poly */ divs[i].A->exps = NULL; divs[i].A->coeffs = NULL; divs[i].A->bits = A->bits; divs[i].A->coeffs_alloc = 0; divs[i].A->exps_alloc = 0; } divs[i].A->length = 0; } /* compute each chunk in parallel */ #if FLINT_USES_PTHREAD pthread_mutex_init(&base->mutex, NULL); #endif for (i = 0; i < num_handles; i++) { args[i].idx = i; args[i].base = base; args[i].divs = divs; thread_pool_wake(global_thread_pool, handles[i], 0, _nmod_mpoly_mul_heap_threaded_worker, &args[i]); } i = num_handles; args[i].idx = i; args[i].base = base; args[i].divs = divs; _nmod_mpoly_mul_heap_threaded_worker(&args[i]); for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); } /* calculate and allocate space for final answer */ i = base->ndivs - 1; *A = *divs[i].A; Alen = A->length; for (i = base->ndivs - 2; i >= 0; i--) { divs[i].Aoffset = Alen; Alen += divs[i].A->length; } nmod_mpoly_fit_length(A, Alen, ctx); base->Acoeff = A->coeffs; base->Aexp = A->exps; /* join answers */ for (i = 0; i < num_handles; i++) thread_pool_wake(global_thread_pool, handles[i], 0, _join_worker, &args[i]); _join_worker(&args[num_handles]); for (i = 0; i < num_handles; i++) thread_pool_wait(global_thread_pool, handles[i]); A->length = Alen; #if FLINT_USES_PTHREAD pthread_mutex_destroy(&base->mutex); #endif flint_free(args); flint_free(divs); } /* maxBfields gets clobbered */ void _nmod_mpoly_mul_heap_threaded_pool_maxfields( nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx, const thread_pool_handle * handles, slong num_handles) { slong N; flint_bitcnt_t Abits; ulong * cmpmask; ulong * Bexp, * Cexp; int freeBexp, freeCexp; nmod_mpoly_struct * a, T[1]; TMP_INIT; TMP_START; _fmpz_vec_add(maxBfields, maxBfields, maxCfields, ctx->minfo->nfields); Abits = 1 + _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); Abits = FLINT_MAX(Abits, B->bits); Abits = FLINT_MAX(Abits, C->bits); Abits = mpoly_fix_bits(Abits, ctx->minfo); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); /* ensure input exponents are packed into same sized fields as output */ freeBexp = 0; Bexp = B->exps; if (Abits > B->bits) { freeBexp = 1; Bexp = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexp, Abits, B->exps, B->bits, B->length, ctx->minfo); } freeCexp = 0; Cexp = C->exps; if (Abits > C->bits) { freeCexp = 1; Cexp = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexp, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { nmod_mpoly_init(T, ctx); a = T; } else { a = A; } nmod_mpoly_fit_length_reset_bits(a, B->length + C->length, Abits, ctx); if (B->length > C->length) { _nmod_mpoly_mul_heap_threaded(a, C->coeffs, Cexp, C->length, B->coeffs, Bexp, B->length, Abits, N, cmpmask, ctx, handles, num_handles); } else { _nmod_mpoly_mul_heap_threaded(a, B->coeffs, Bexp, B->length, C->coeffs, Cexp, C->length, Abits, N, cmpmask, ctx, handles, num_handles); } if (A == B || A == C) { nmod_mpoly_swap(A, T, ctx); nmod_mpoly_clear(T, ctx); } if (freeBexp) flint_free(Bexp); if (freeCexp) flint_free(Cexp); TMP_END; } void nmod_mpoly_mul_heap_threaded( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields, * maxCfields; thread_pool_handle * handles; slong num_handles; slong thread_limit = FLINT_MIN(B->length, C->length)/16; TMP_INIT; if (B->length == 0 || C->length == 0) { nmod_mpoly_zero(A, ctx); return; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); num_handles = flint_request_threads(&handles, thread_limit); _nmod_mpoly_mul_heap_threaded_pool_maxfields(A, B, maxBfields, C, maxCfields, ctx, handles, num_handles); flint_give_back_threads(handles, num_handles); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; } flint-3.1.3/src/nmod_mpoly/mul_johnson.c000066400000000000000000000271671461254215100203130ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" slong _nmod_mpoly_mul_johnson1( nmod_mpoly_t A, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, ulong maskhi, nmod_t fctx) { slong i, j; slong next_loc; slong Q_len = 0, heap_len = 2; /* heap zero index unused */ mpoly_heap1_s * heap; mpoly_heap_t * chain; slong * Q; mpoly_heap_t * x; slong len1; mp_limb_t * p1 = A->coeffs; ulong * e1 = A->exps; slong * hind; ulong exp; ulong acc0, acc1, acc2, pp0, pp1; TMP_INIT; TMP_START; next_loc = len2 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap1_s *) TMP_ALLOC((len2 + 1)*sizeof(mpoly_heap1_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len2*sizeof(mpoly_heap_t)); Q = (slong *) TMP_ALLOC(2*len2*sizeof(slong)); /* space for heap indices */ hind = (slong *) TMP_ALLOC(len2*sizeof(slong)); for (i = 0; i < len2; i++) hind[i] = 1; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; HEAP_ASSIGN(heap[1], exp2[0] + exp3[0], x); hind[0] = 2*1 + 0; len1 = 0; while (heap_len > 1) { exp = heap[1].exp; _nmod_mpoly_fit_length(&p1, &A->coeffs_alloc, &e1, &A->exps_alloc, 1, len1 + 1); e1[len1] = exp; acc0 = acc1 = acc2 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; umul_ppmm(pp1, pp0, coeff2[x->i], coeff3[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; umul_ppmm(pp1, pp0, coeff2[x->i], coeff3[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while (heap_len > 1 && heap[1].exp == exp); NMOD_RED3(p1[len1], acc2, acc1, acc0, fctx); len1 += (p1[len1] != 0); while (Q_len > 0) { j = Q[--Q_len]; i = Q[--Q_len]; /* should we go right? */ if ( (i + 1 < len2) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp2[x->i] + exp3[x->j], x, &next_loc, &heap_len, maskhi); } /* should we go up? */ if ( (j + 1 < len3) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j + 1) + 0; _mpoly_heap_insert1(heap, exp2[x->i] + exp3[x->j], x, &next_loc, &heap_len, maskhi); } } } A->coeffs = p1; A->exps = e1; A->length = len1; TMP_END; return len1; } slong _nmod_mpoly_mul_johnson( nmod_mpoly_t A, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, flint_bitcnt_t bits, slong N, const ulong * cmpmask, nmod_t fctx) { slong i, j; slong next_loc; slong Q_len = 0, heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * Q; mpoly_heap_t * x; slong len1; mp_limb_t * p1 = A->coeffs; ulong * e1 = A->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; slong * hind; ulong acc0, acc1, acc2, pp0, pp1; TMP_INIT; FLINT_ASSERT(len2 > 0); FLINT_ASSERT(len3 > 0); if (N == 1) return _nmod_mpoly_mul_johnson1(A, coeff2, exp2, len2, coeff3, exp3, len3, cmpmask[0], fctx); TMP_START; next_loc = len2 + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((len2 + 1)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC(len2*sizeof(mpoly_heap_t)); Q = (slong *) TMP_ALLOC(2*len2*sizeof(slong)); exps = (ulong *) TMP_ALLOC(len2*N*sizeof(ulong)); exp_list = (ulong **) TMP_ALLOC(len2*sizeof(ulong *)); for (i = 0; i < len2; i++) exp_list[i] = exps + i*N; hind = (slong *) TMP_ALLOC(len2*sizeof(slong)); for (i = 0; i < len2; i++) hind[i] = 1; /* start with no heap nodes and no exponent vectors in use */ exp_next = 0; /* put (0, 0, exp2[0] + exp3[0]) on heap */ x = chain + 0; x->i = 0; x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; if (bits <= FLINT_BITS) mpoly_monomial_add(heap[1].exp, exp2, exp3, N); else mpoly_monomial_add_mp(heap[1].exp, exp2, exp3, N); hind[0] = 2*1 + 0; len1 = 0; while (heap_len > 1) { exp = heap[1].exp; _nmod_mpoly_fit_length(&p1, &A->coeffs_alloc, &e1, &A->exps_alloc, N, len1 + 1); mpoly_monomial_set(e1 + len1*N, exp, N); acc0 = acc1 = acc2 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; umul_ppmm(pp1, pp0, coeff2[x->i], coeff3[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); while ((x = x->next) != NULL) { hind[x->i] |= WORD(1); Q[Q_len++] = x->i; Q[Q_len++] = x->j; umul_ppmm(pp1, pp0, coeff2[x->i], coeff3[x->j]); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, WORD(0), pp1, pp0); } } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); NMOD_RED3(p1[len1], acc2, acc1, acc0, fctx); len1 += (p1[len1] != 0); while (Q_len > 0) { /* take node from store */ j = Q[--Q_len]; i = Q[--Q_len]; /* should we go right? */ if ( (i + 1 < len2) && (hind[i + 1] == 2*j + 1) ) { x = chain + i + 1; x->i = i + 1; x->j = j; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } /* should we go up? */ if ( (j + 1 < len3) && ((hind[i] & 1) == 1) && ( (i == 0) || (hind[i - 1] >= 2*(j + 2) + 1) ) ) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; hind[x->i] = 2*(x->j+1) + 0; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], exp2 + x->i*N, exp3 + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } } A->coeffs = p1; A->exps = e1; A->length = len1; TMP_END; return len1; } /* maxBfields gets clobbered */ void _nmod_mpoly_mul_johnson_maxfields( nmod_mpoly_t A, const nmod_mpoly_t B, fmpz * maxBfields, const nmod_mpoly_t C, fmpz * maxCfields, const nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t Abits; ulong * cmpmask; ulong * Bexps = B->exps, * Cexps = C->exps; int freeBexps = 0, freeCexps = 0; nmod_mpoly_struct * a, T[1]; TMP_INIT; TMP_START; _fmpz_vec_add(maxBfields, maxBfields, maxCfields, ctx->minfo->nfields); Abits = 1 + _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); Abits = FLINT_MAX(Abits, B->bits); Abits = FLINT_MAX(Abits, C->bits); Abits = mpoly_fix_bits(Abits, ctx->minfo); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); /* ensure input exponents are packed into same sized fields as output */ if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { nmod_mpoly_init(T, ctx); a = T; } else { a = A; } nmod_mpoly_fit_length_reset_bits(a, B->length + C->length, Abits, ctx); if (B->length > C->length) { _nmod_mpoly_mul_johnson(a, C->coeffs, Cexps, C->length, B->coeffs, Bexps, B->length, Abits, N, cmpmask, ctx->mod); } else { _nmod_mpoly_mul_johnson(a, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, Abits, N, cmpmask, ctx->mod); } if (A == B || A == C) { nmod_mpoly_swap(A, T, ctx); nmod_mpoly_clear(T, ctx); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } void nmod_mpoly_mul_johnson( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields, * maxCfields; TMP_INIT; if (B->length == 0 || C->length == 0) { nmod_mpoly_zero(A, ctx); return; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); maxCfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(maxBfields + i); fmpz_init(maxCfields + i); } mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); mpoly_max_fields_fmpz(maxCfields, C->exps, C->length, C->bits, ctx->minfo); _nmod_mpoly_mul_johnson_maxfields(A, B, maxBfields, C, maxCfields, ctx); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(maxBfields + i); fmpz_clear(maxCfields + i); } TMP_END; } flint-3.1.3/src/nmod_mpoly/neg.c000066400000000000000000000016321461254215100165160ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_neg(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { if (A != B) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); _nmod_mpoly_set_length(A, B->length, ctx); } _nmod_vec_neg(A->coeffs, B->coeffs, B->length, ctx->mod); } flint-3.1.3/src/nmod_mpoly/pow_fmpz.c000066400000000000000000000037161461254215100176130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_pow_fmpz(nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz_t k, const nmod_mpoly_ctx_t ctx) { slong i; fmpz * maxBfields; flint_bitcnt_t exp_bits; TMP_INIT; if (fmpz_sgn(k) < 0) flint_throw(FLINT_ERROR, "nmod_mpoly_pow_fmpz: power is negative"); if (fmpz_fits_si(k)) return nmod_mpoly_pow_ui(A, B, fmpz_get_ui(k), ctx); /* we are raising a polynomial to an unreasonable exponent It must either be zero or a monomial with unit coefficient */ if (B->length == 0) { nmod_mpoly_zero(A, ctx); return 1; } if (B->length != 1) return 0; TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_fmpz(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = 1 + _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(A, 1, exp_bits, ctx); A->coeffs[0] = nmod_pow_fmpz(B->coeffs[0], k, ctx->mod); mpoly_pack_vec_fmpz(A->exps + 0, maxBfields, exp_bits, ctx->minfo->nfields, 1); _nmod_mpoly_set_length(A, A->coeffs[0] != 0, ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/nmod_mpoly/pow_rmul.c000066400000000000000000000043331461254215100176120ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void _nmod_mpoly_pow_rmul( nmod_mpoly_t A, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, ulong k, slong N, const ulong * cmpmask, nmod_t mod, nmod_mpoly_t T) { flint_bitcnt_t bits = A->bits; FLINT_ASSERT(bits == T->bits); FLINT_ASSERT(Blen > 0); _nmod_mpoly_fit_length(&A->coeffs, &A->coeffs_alloc, &A->exps, &A->exps_alloc, N, Blen + 2); if (k >= 2) { _nmod_mpoly_mul_johnson(A, Bcoeffs, Bexps, Blen, Bcoeffs, Bexps, Blen, bits, N, cmpmask, mod); k -= 2; while (k >= 1 && A->length > 0) { _nmod_mpoly_mul_johnson(T, A->coeffs, A->exps, A->length, Bcoeffs, Bexps, Blen, bits, N, cmpmask, mod); nmod_mpoly_swap(A, T, NULL); k -= 1; } } else if (k == 1) { FLINT_ASSERT(A->coeffs_alloc >= Blen); _nmod_vec_set(A->coeffs, Bcoeffs, Blen); mpoly_copy_monomials(A->exps, Bexps, Blen, N); A->length = Blen; } else { mpoly_monomial_zero(A->exps, N); A->coeffs[0] = 1; A->length = 1; } } void nmod_mpoly_pow_rmul(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx) { nmod_mpoly_t T; nmod_mpoly_init(T, ctx); if (A == B) { nmod_mpoly_pow_rmul(T, A, k, ctx); nmod_mpoly_swap(T, A, ctx); } else { nmod_mpoly_one(A, ctx); while (k > 0) { nmod_mpoly_mul_johnson(T, A, B, ctx); nmod_mpoly_swap(A, T, ctx); k -= 1; } } nmod_mpoly_clear(T, ctx); } flint-3.1.3/src/nmod_mpoly/pow_ui.c000066400000000000000000000110521461254215100172440ustar00rootroot00000000000000/* Copyright (C) 2018,2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_pow_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx) { slong i, exp_bits, N; fmpz * maxBfields; ulong * cmpmask; ulong * Bexps; int freeBexps; nmod_mpoly_t T, Atemp; nmod_mpoly_struct * R; TMP_INIT; if (k == 0) { nmod_mpoly_set_ui(A, ctx->mod.n > 1, ctx); return 1; } if (B->length == 0) { nmod_mpoly_zero(A, ctx); return 1; } if (k == 1) { nmod_mpoly_set(A, B, ctx); return 1; } if (k == 2) { nmod_mpoly_mul(A, B, B, ctx); return 1; } TMP_START; maxBfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(maxBfields + i); mpoly_max_fields_fmpz(maxBfields, B->exps, B->length, B->bits, ctx->minfo); _fmpz_vec_scalar_mul_ui(maxBfields, maxBfields, ctx->minfo->nfields, k); exp_bits = _fmpz_vec_max_bits(maxBfields, ctx->minfo->nfields); exp_bits = FLINT_MAX(MPOLY_MIN_BITS, exp_bits + 1); exp_bits = FLINT_MAX(exp_bits, B->bits); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); N = mpoly_words_per_exp(exp_bits, ctx->minfo); if (B->length == 1) { /* powering a monomial */ nmod_mpoly_fit_length_reset_bits(A, 1, exp_bits, ctx); if (B->bits == exp_bits && B != A) mpoly_monomial_mul_ui_mp(A->exps, B->exps, N, k); else mpoly_pack_vec_fmpz(A->exps, maxBfields, exp_bits, ctx->minfo->nfields, 1); A->coeffs[0] = nmod_pow_ui(B->coeffs[0], k, ctx->mod); _nmod_mpoly_set_length(A, A->coeffs[0] != 0, ctx); goto cleanup; } freeBexps = 0; Bexps = B->exps; if (exp_bits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, exp_bits, B->exps, B->bits, B->length, ctx->minfo); } if (A == B) { nmod_mpoly_init3(Atemp, B->length, exp_bits, ctx); R = Atemp; } else { nmod_mpoly_fit_length_reset_bits(A, B->length, exp_bits, ctx); R = A; } nmod_mpoly_init3(T, B->length, exp_bits, ctx); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, exp_bits, ctx->minfo); if (ctx->mod.n > 99999 || !n_is_prime(ctx->mod.n)) { _nmod_mpoly_pow_rmul(R, B->coeffs, Bexps, B->length, k, N, cmpmask, ctx->mod, T); } else { ulong ne, kmodn; nmod_mpoly_t S; nmod_mpoly_init3(S, B->length, exp_bits, ctx); mpoly_monomial_zero(R->exps, N); R->coeffs[0] = 1; R->length = 1; for (ne = 1; k > 0; k = k/ctx->mod.n, ne = ne * ctx->mod.n) { NMOD_RED(kmodn, k, ctx->mod); /* R *= B^(n^e*(k%n)) */ if (kmodn == 0) continue; _nmod_mpoly_pow_rmul(S, B->coeffs, Bexps, B->length, kmodn, N, cmpmask, ctx->mod, T); mpoly_monomial_mul_ui_mp(S->exps, S->exps, N*S->length, ne); if (nmod_mpoly_is_one(R, ctx)) { nmod_mpoly_swap(R, S, ctx); } else { _nmod_mpoly_mul_johnson(T, R->coeffs, R->exps, R->length, S->coeffs, S->exps, S->length, exp_bits, N, cmpmask, ctx->mod); nmod_mpoly_swap(R, T, ctx); } } nmod_mpoly_clear(S, ctx); } nmod_mpoly_clear(T, ctx); if (A == B) { nmod_mpoly_swap(A, Atemp, ctx); nmod_mpoly_clear(Atemp, ctx); } if (freeBexps) flint_free(Bexps); cleanup: for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(maxBfields + i); TMP_END; return 1; } flint-3.1.3/src/nmod_mpoly/profile/000077500000000000000000000000001461254215100172375ustar00rootroot00000000000000flint-3.1.3/src/nmod_mpoly/profile/p-divides.c000066400000000000000000000172171461254215100212770ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* usage: likwid-setFrequencies -g performance make profile MOD=nmod_mpoly && ./build/nmod_mpoly/profile/p-divides 4 sparse 12 12 p-divides nthreads sparse m n: run the sparse benchmark on nthreads with powers (m, n) divides((1+x+y+2*z^2+3*t^3+5*u^5)^m*(1+u+t+2*z^2+3*y^3+5*x^5)^n, (1+u+t+2*z^2+3*y^3+5*x^5)^n) */ #include #include #include "profiler.h" #include "nmod_mpoly.h" #define CALCULATE_MACHINE_EFFICIENCY 0 int * cpu_affinities; #if CALCULATE_MACHINE_EFFICIENCY typedef struct _worker_arg_struct { nmod_mpoly_t Q; const nmod_mpoly_struct * A, * B; const nmod_mpoly_ctx_struct * ctx; } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void worker_divides(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; nmod_mpoly_divides_threaded(W->Q, W->A, W->B, W->ctx, 1); } #endif void profile_divides( const nmod_mpoly_t realQ, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, slong max_threads) { nmod_mpoly_t Q; timeit_t timer; slong num_threads; slong serial_time; flint_set_num_threads(1); flint_set_thread_affinity(cpu_affinities, 1); nmod_mpoly_init(Q, ctx); timeit_start(timer); nmod_mpoly_divides(Q, A, B, ctx); timeit_stop(timer); serial_time = FLINT_MAX(WORD(1), timer->wall); flint_printf("serial time: %wd\n", serial_time); if (!nmod_mpoly_equal(Q, realQ, ctx)) { printf("quotient wrong!!!\n"); flint_abort(); } for (num_threads = 2; num_threads <= max_threads; num_threads++) { slong parallel_time; double parallel_efficiency; #if CALCULATE_MACHINE_EFFICIENCY thread_pool_handle * handles; worker_arg_struct * worker_args; slong i; double machine_efficiency; slong num_workers; #endif flint_set_num_threads(num_threads); flint_set_thread_affinity(cpu_affinities, num_threads); #if CALCULATE_MACHINE_EFFICIENCY handles = (thread_pool_handle *) flint_malloc((num_threads - 1)*sizeof(thread_pool_handle)); num_workers = thread_pool_request(global_thread_pool, handles, num_threads - 1); worker_args = (worker_arg_struct *) flint_malloc((num_workers + 1)*sizeof(worker_arg_t)); timeit_start(timer); for (i = 0; i <= num_workers; i++) { nmod_mpoly_init((worker_args + i)->Q, ctx); (worker_args + i)->A = A; (worker_args + i)->B = B; (worker_args + i)->ctx = ctx; if (i < num_workers) { thread_pool_wake(global_thread_pool, handles[i], 0, worker_divides, worker_args + i); } else { worker_divides(worker_args + i); } } for (i = 0; i < num_workers; i++) { thread_pool_wait(global_thread_pool, handles[i]); } timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); for (i = 0; i <= num_workers; i++) { if (!nmod_mpoly_equal((worker_args + i)->Q, realQ, ctx)) { printf("quotient wrong\n"); flint_abort(); } nmod_mpoly_clear((worker_args + i)->Q, ctx); if (i < num_workers) { thread_pool_give_back(global_thread_pool, handles[i]); } } flint_free(worker_args); flint_free(handles); machine_efficiency = (double)(serial_time)/(double)(parallel_time); #endif nmod_mpoly_clear(Q, ctx); nmod_mpoly_init(Q, ctx); timeit_start(timer); nmod_mpoly_divides(Q, A, B, ctx); timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); if (!nmod_mpoly_equal(Q, realQ, ctx)) { printf("quotient wrong!!!\n"); flint_abort(); } parallel_efficiency = (double)(serial_time)/(double)(parallel_time)/(double)(num_threads); #if CALCULATE_MACHINE_EFFICIENCY flint_printf("parallel %wd time: %wd, efficiency %f (machine %f)\n", num_threads, parallel_time, parallel_efficiency, machine_efficiency); #else flint_printf("parallel %wd time: %wd, efficiency %f\n", num_threads, parallel_time, parallel_efficiency); #endif } nmod_mpoly_clear(Q, ctx); } int main(int argc, char *argv[]) { slong i, m, n, max_threads; const slong thread_limit = 64; const char * name; cpu_affinities = flint_malloc(thread_limit*sizeof(int)); for (i = 0; i < thread_limit; i++) cpu_affinities[i] = i; if (argc == 5) { max_threads = atoi(argv[1]); max_threads = FLINT_MIN(max_threads, thread_limit); max_threads = FLINT_MAX(max_threads, WORD(1)); name = argv[2]; m = atoi(argv[3]); n = atoi(argv[4]); } else { printf(" usage: p-divides nthreads {dense|sparse} m n\n"); printf("running: p-divides 4 sparse 12 12\n"); max_threads = 4; name = "sparse"; m = 12; n = 12; } m = FLINT_MIN(m, WORD(30)); m = FLINT_MAX(m, WORD(5)); n = FLINT_MIN(n, WORD(30)); n = FLINT_MAX(n, WORD(5)); flint_printf("setting up nmod_mpoly %s divides ... ", name, m, n); if (strcmp(name, "dense") == 0) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, A, B, Q; const char * vars[] = {"x", "y", "z", "t"}; nmod_mpoly_ctx_init(ctx, 4, ORD_DEGLEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(A, ctx); nmod_mpoly_init(B, ctx); nmod_mpoly_init(Q, ctx); nmod_mpoly_set_str_pretty(a, "1 + x + y + z + t", vars, ctx); nmod_mpoly_set_str_pretty(b, "1 + x + y + z + t", vars, ctx); nmod_mpoly_pow_ui(Q, a, m, ctx); nmod_mpoly_pow_ui(B, b, n, ctx); nmod_mpoly_mul(A, Q, B, ctx); flint_printf("starting dense divides (%wu, %wd):\n", m, n); profile_divides(Q, A, B, ctx, max_threads); nmod_mpoly_clear(Q, ctx); nmod_mpoly_clear(B, ctx); nmod_mpoly_clear(A, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } else /* sparse */ { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, A, B, Q; const char * vars[] = {"x", "y", "z", "t", "u"}; nmod_mpoly_ctx_init(ctx, 5, ORD_LEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(A, ctx); nmod_mpoly_init(B, ctx); nmod_mpoly_init(Q, ctx); nmod_mpoly_set_str_pretty(a, "1 + x + y + 2*z^2 + 3*t^3 + 5*u^5", vars, ctx); nmod_mpoly_set_str_pretty(b, "1 + u + t + 2*z^2 + 3*y^3 + 5*x^5", vars, ctx); nmod_mpoly_pow_ui(Q, a, m, ctx); nmod_mpoly_pow_ui(B, b, n, ctx); nmod_mpoly_mul(A, Q, B, ctx); flint_printf("starting sparse divides (%wu, %wd):\n", m, n); profile_divides(Q, A, B, ctx, max_threads); nmod_mpoly_clear(Q, ctx); nmod_mpoly_clear(B, ctx); nmod_mpoly_clear(A, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } flint_free(cpu_affinities); flint_cleanup_master(); return 0; } flint-3.1.3/src/nmod_mpoly/profile/p-gcd.c000066400000000000000000000261761461254215100204110ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" #include "profiler.h" slong count = 0; slong total_super = 0; void profile_gcd( const nmod_mpoly_t realG, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, unsigned int algo) { nmod_mpoly_t G; timeit_t timer; slong hensel = -1, brown = -1, zippel = -1, zippel2 = -1, super = -1; nmod_mpoly_init(G, ctx); if (algo & MPOLY_GCD_USE_BROWN) { nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); nmod_mpoly_gcd_brown(G, A, B, ctx); timeit_stop(timer); brown = timer->wall; if (!nmod_mpoly_equal(G, realG, ctx)) { flint_printf("brown is wrong\n"); flint_abort(); } } flint_printf("%10wd ", brown); fflush(stdout); if (algo & MPOLY_GCD_USE_HENSEL) { nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); nmod_mpoly_gcd_hensel(G, A, B, ctx); timeit_stop(timer); hensel = timer->wall; if (!nmod_mpoly_equal(G, realG, ctx)) { flint_printf("hensel is wrong\n"); flint_abort(); } } flint_printf("%10wd ", hensel); fflush(stdout); if (algo & MPOLY_GCD_USE_ZIPPEL2) { nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); nmod_mpoly_gcd_zippel2(G, A, B, ctx); timeit_stop(timer); zippel2 = timer->wall; if (!nmod_mpoly_equal(G, realG, ctx)) { flint_printf("zippel2 is wrong\n"); flint_abort(); } } flint_printf("%10wd ", zippel2); fflush(stdout); if (algo & MPOLY_GCD_USE_ZIPPEL) { nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); nmod_mpoly_gcd_zippel(G, A, B, ctx); timeit_stop(timer); zippel = timer->wall; if (!nmod_mpoly_equal(G, realG, ctx)) { flint_printf("zippel is wrong\n"); flint_abort(); } } flint_printf("%10wd ", zippel); fflush(stdout); { nmod_mpoly_add(G, A, B, ctx); timeit_start(timer); nmod_mpoly_gcd(G, A, B, ctx); timeit_stop(timer); super = timer->wall; if (!nmod_mpoly_equal(G, realG, ctx)) { flint_printf("super is wrong\n"); flint_abort(); } } count++; flint_printf("%10wd #%wd\n", super, count); fflush(stdout); total_super += super; nmod_mpoly_clear(G, ctx); } void print_banner(void) { flint_printf("| brown | hensel | zippel2 | zippel | super |\n"); flint_printf("+----------+----------+----------+----------+----------+\n"); } int main(int argc, char *argv[]) { slong i, j, k; const char * vars[] = {"x", "y", "z", "t" ,"u", "v", "w", "s", "p"}; for (k = 0; k < 2; k++) { print_banner(); for (i = 3; i <= 11; i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b, t; nmod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, k == 0 ? 43051 : 3); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_one(g, ctx); nmod_mpoly_one(a, ctx); nmod_mpoly_one(b, ctx); for (j = 0; j < i; j++) { nmod_mpoly_gen(t, j, ctx); nmod_mpoly_add_ui(t, t, 1, ctx); nmod_mpoly_mul(g, g, t, ctx); nmod_mpoly_gen(t, j, ctx); nmod_mpoly_sub_ui(t, t, 2, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_gen(t, j, ctx); nmod_mpoly_add_ui(t, t, 2, ctx); nmod_mpoly_mul(b, b, t, ctx); } nmod_mpoly_sub_ui(g, g, 2, ctx); nmod_mpoly_add_ui(a, a, 2, ctx); nmod_mpoly_sub_ui(b, b, 2, ctx); nmod_mpoly_mul(a, a, g, ctx); nmod_mpoly_mul(b, b, g, ctx); nmod_mpoly_make_monic(g, g, ctx); profile_gcd(g, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } } print_banner(); for (i = 50; i < 100; i += 4) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, t, m; nmod_mpoly_ctx_init(ctx, 2, ORD_LEX, 1073741827); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(m, ctx); nmod_mpoly_set_str_pretty(a, "1+x+y", vars, ctx); nmod_mpoly_pow_ui(a, a, i, ctx); nmod_mpoly_set_str_pretty(m, "x", vars, ctx); nmod_mpoly_add(a, a, m, ctx); nmod_mpoly_set_str_pretty(b, "1-2*x-y", vars, ctx); nmod_mpoly_pow_ui(b, b, i, ctx); nmod_mpoly_set_str_pretty(m, "y", vars, ctx); nmod_mpoly_add(b, b, m, ctx); nmod_mpoly_set_str_pretty(t, "2-x+y", vars, ctx); nmod_mpoly_pow_ui(t, t, i, ctx); nmod_mpoly_set_str_pretty(m, "x-y", vars, ctx); nmod_mpoly_add(t, t, m, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 5; i < 15; i += 1) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, t, m; nmod_mpoly_ctx_init(ctx, 2, ORD_LEX, 1073741827); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(m, ctx); nmod_mpoly_set_str_pretty(a, "1+x^31+y^51", vars, ctx); nmod_mpoly_pow_ui(a, a, i, ctx); nmod_mpoly_set_str_pretty(m, "x^7", vars, ctx); nmod_mpoly_add(a, a, m, ctx); nmod_mpoly_set_str_pretty(b, "1-2*x^23-y^47", vars, ctx); nmod_mpoly_pow_ui(b, b, i, ctx); nmod_mpoly_set_str_pretty(m, "y^9", vars, ctx); nmod_mpoly_add(b, b, m, ctx); nmod_mpoly_set_str_pretty(t, "2-x^39+y^24", vars, ctx); nmod_mpoly_pow_ui(t, t, i, ctx); nmod_mpoly_set_str_pretty(m, "x^6*y^7", vars, ctx); nmod_mpoly_add(t, t, m, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_BROWN | MPOLY_GCD_USE_HENSEL); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 15; i < 30; i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, t, m; nmod_mpoly_ctx_init(ctx, 3, ORD_LEX, 1073741827); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(m, ctx); nmod_mpoly_set_str_pretty(a, "1+x+y+z", vars, ctx); nmod_mpoly_pow_ui(a, a, i, ctx); nmod_mpoly_set_str_pretty(m, "x", vars, ctx); nmod_mpoly_add(a, a, m, ctx); nmod_mpoly_set_str_pretty(b, "1-2*x-y+z", vars, ctx); nmod_mpoly_pow_ui(b, b, i, ctx); nmod_mpoly_set_str_pretty(m, "y", vars, ctx); nmod_mpoly_add(b, b, m, ctx); nmod_mpoly_set_str_pretty(t, "3+x+y-2*z", vars, ctx); nmod_mpoly_pow_ui(t, t, i, ctx); nmod_mpoly_set_str_pretty(m, "z", vars, ctx); nmod_mpoly_add(t, t, m, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_ALL); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 1; i < 10; i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, t, m; nmod_mpoly_ctx_init(ctx, 7, ORD_LEX, 1073741827); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(m, ctx); nmod_mpoly_set_str_pretty(a, "1+x+y+z+t+u+2*v+w", vars, ctx); nmod_mpoly_pow_ui(a, a, i, ctx); nmod_mpoly_set_str_pretty(m, "x", vars, ctx); nmod_mpoly_add(a, a, m, ctx); nmod_mpoly_set_str_pretty(b, "1-2*x-y+z+t+u+v+w", vars, ctx); nmod_mpoly_pow_ui(b, b, i, ctx); nmod_mpoly_set_str_pretty(m, "y", vars, ctx); nmod_mpoly_add(b, b, m, ctx); nmod_mpoly_set_str_pretty(t, "1+x+y+z-t-u+v+3*w", vars, ctx); nmod_mpoly_pow_ui(t, t, i, ctx); nmod_mpoly_set_str_pretty(m, "z", vars, ctx); nmod_mpoly_add(t, t, m, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_HENSEL | MPOLY_GCD_USE_ZIPPEL2); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); } print_banner(); for (i = 1; i < 8; i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, t, m; nmod_mpoly_ctx_init(ctx, 9, ORD_LEX, 1073741827); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(m, ctx); nmod_mpoly_set_str_pretty(a, "1+x+y+z+t+u+2*v+w+s-p", vars, ctx); nmod_mpoly_pow_ui(a, a, i, ctx); nmod_mpoly_set_str_pretty(m, "x", vars, ctx); nmod_mpoly_add(a, a, m, ctx); nmod_mpoly_set_str_pretty(b, "1-2*x-y+z+t+u+v+w-2*s+p", vars, ctx); nmod_mpoly_pow_ui(b, b, i, ctx); nmod_mpoly_set_str_pretty(m, "y", vars, ctx); nmod_mpoly_add(b, b, m, ctx); nmod_mpoly_set_str_pretty(t, "1+x+y+z-t-u+v+3*w+2*s-3*p", vars, ctx); nmod_mpoly_pow_ui(t, t, i, ctx); nmod_mpoly_set_str_pretty(m, "z", vars, ctx); nmod_mpoly_add(t, t, m, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_make_monic(t, t, ctx); profile_gcd(t, a, b, ctx, MPOLY_GCD_USE_HENSEL | MPOLY_GCD_USE_ZIPPEL2); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); } flint_printf("--------------------\n"); flint_printf("total time: %wd\n", total_super); flint_printf(" record: 19050\n"); flint_cleanup_master(); return 0; } flint-3.1.3/src/nmod_mpoly/profile/p-mul.c000066400000000000000000000160421461254215100204400ustar00rootroot00000000000000/* Copyright 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* usage: likwid-setFrequencies -g performance make profile MOD=nmod_mpoly && ./build/nmod_mpoly/profile/p-mul 4 sparse 12 12 p-mul nthreads sparse m n: run the sparse benchmark on nthreads with powers (m, n) mul((1+x+y+2*z^2+3*t^3+5*u^5)^m, (1+u+t+2*z^2+3*y^3+5*x^5)^n) p-mul nthreads dense m n: run the dense benchmark on nthreads with powers (m, n) mul((1+x+y+z+t)^m, (1+x+y+z+t)^n) */ #include #include #include "nmod_mpoly.h" #include "profiler.h" #define CALCULATE_MACHINE_EFFICIENCY 0 int * cpu_affinities; #if CALCULATE_MACHINE_EFFICIENCY typedef struct _worker_arg_struct { nmod_mpoly_t P; const nmod_mpoly_struct * A, * B; const nmod_mpoly_ctx_struct * ctx; } worker_arg_struct; typedef worker_arg_struct worker_arg_t[1]; static void worker_mul(void * varg) { worker_arg_struct * W = (worker_arg_struct *) varg; nmod_mpoly_mul_threaded(W->P, W->A, W->B, W->ctx, 1); } #endif void profile_mul( const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, slong max_threads) { nmod_mpoly_t P; timeit_t timer; slong num_threads; slong serial_time; flint_set_num_threads(1); flint_set_thread_affinity(cpu_affinities, 1); nmod_mpoly_init(P, ctx); timeit_start(timer); nmod_mpoly_mul(P, A, B, ctx); timeit_stop(timer); serial_time = FLINT_MAX(WORD(1), timer->wall); flint_printf(" serial time: %wd\n", serial_time); for (num_threads = 2; num_threads <= max_threads; num_threads++) { slong parallel_time; double parallel_efficiency; #if CALCULATE_MACHINE_EFFICIENCY thread_pool_handle * handles; worker_arg_struct * worker_args; slong i; double machine_efficiency; slong num_workers; #endif flint_set_num_threads(num_threads); flint_set_thread_affinity(cpu_affinities, num_threads); #if CALCULATE_MACHINE_EFFICIENCY handles = (thread_pool_handle *) flint_malloc((num_threads - 1)*sizeof(thread_pool_handle)); num_workers = thread_pool_request(global_thread_pool, handles, num_threads - 1); worker_args = (worker_arg_struct *) flint_malloc((num_workers + 1)*sizeof(worker_arg_t)); timeit_start(timer); for (i = 0; i <= num_workers; i++) { nmod_mpoly_init((worker_args + i)->P, ctx); (worker_args + i)->A = A; (worker_args + i)->B = B; (worker_args + i)->ctx = ctx; if (i < num_workers) { thread_pool_wake(global_thread_pool, handles[i], 0, worker_mul, worker_args + i); } else { worker_mul(worker_args + i); } } for (i = 0; i < num_workers; i++) { thread_pool_wait(global_thread_pool, handles[i]); } timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); for (i = 0; i <= num_workers; i++) { nmod_mpoly_clear((worker_args + i)->P, ctx); if (i < num_workers) { thread_pool_give_back(global_thread_pool, handles[i]); } } flint_free(worker_args); flint_free(handles); machine_efficiency = (double)(serial_time)/(double)(parallel_time); #endif /* find parallel efficiency */ nmod_mpoly_clear(P, ctx); nmod_mpoly_init(P, ctx); timeit_start(timer); nmod_mpoly_mul(P, A, B, ctx); timeit_stop(timer); parallel_time = FLINT_MAX(WORD(1), timer->wall); parallel_efficiency = (double)(serial_time)/(double)(parallel_time)/(double)(num_threads); #if CALCULATE_MACHINE_EFFICIENCY flint_printf("parallel %wd time: %wd, efficiency %f (machine %f)\n", num_threads, parallel_time, parallel_efficiency, machine_efficiency); #else flint_printf("parallel %wd time: %wd, efficiency %f\n", num_threads, parallel_time, parallel_efficiency); #endif } nmod_mpoly_clear(P, ctx); } int main(int argc, char *argv[]) { slong i, m, n, max_threads; const slong thread_limit = 64; const char * name; cpu_affinities = flint_malloc(thread_limit*sizeof(int)); for (i = 0; i < thread_limit; i++) cpu_affinities[i] = i; if (argc == 5) { max_threads = atoi(argv[1]); max_threads = FLINT_MIN(max_threads, thread_limit); max_threads = FLINT_MAX(max_threads, WORD(1)); name = argv[2]; m = atoi(argv[3]); n = atoi(argv[4]); } else { printf(" usage: p-mul nthreads {dense|sparse} m n\n"); printf("running: p-mul 4 sparse 12 12\n"); max_threads = 4; name = "sparse"; m = 12; n = 12; } m = FLINT_MIN(m, WORD(30)); m = FLINT_MAX(m, WORD(5)); n = FLINT_MIN(n, WORD(30)); n = FLINT_MAX(n, WORD(5)); flint_printf("setting up nmod_mpoly %s mul ... ", name, m, n); if (strcmp(name, "dense") == 0) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, A, B; const char * vars[] = {"x", "y", "z", "t"}; nmod_mpoly_ctx_init(ctx, 4, ORD_DEGLEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(A, ctx); nmod_mpoly_init(B, ctx); nmod_mpoly_set_str_pretty(a, "1 + x + y + z + t", vars, ctx); nmod_mpoly_set_str_pretty(b, "1 + x + y + z + t", vars, ctx); nmod_mpoly_pow_ui(A, a, m, ctx); nmod_mpoly_pow_ui(B, b, n, ctx); flint_printf("starting dense mul (%wu, %wd):\n", m, n); profile_mul(A, B, ctx, max_threads); nmod_mpoly_clear(B, ctx); nmod_mpoly_clear(A, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } else /* sparse */ { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, A, B; const char * vars[] = {"x", "y", "z", "t", "u"}; nmod_mpoly_ctx_init(ctx, 5, ORD_LEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(A, ctx); nmod_mpoly_init(B, ctx); nmod_mpoly_set_str_pretty(a, "1 + x + y + 2*z^2 + 3*t^3 + 5*u^5", vars, ctx); nmod_mpoly_set_str_pretty(b, "1 + u + t + 2*z^2 + 3*y^3 + 5*x^5", vars, ctx); nmod_mpoly_pow_ui(A, a, m, ctx); nmod_mpoly_pow_ui(B, b, n, ctx); flint_printf("starting sparse mul (%wu, %wd):\n", m, n); profile_mul(A, B, ctx, max_threads); nmod_mpoly_clear(B, ctx); nmod_mpoly_clear(A, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } flint_free(cpu_affinities); flint_cleanup_master(); return 0; } flint-3.1.3/src/nmod_mpoly/profile/p-sqrt.c000066400000000000000000000046731461254215100206430ustar00rootroot00000000000000/* Copyright 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mpoly.h" #include "profiler.h" int iter_list[21] = {0, 300000, 50000, 5000, 1000, 300, 100, 40, 10, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1}; int main(void) { nmod_mpoly_t f, g, h, k; timeit_t timer; slong iters, j, n; nmod_mpoly_ctx_t ctx; mp_limb_t p = n_nextprime(UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX), 1); const char * vars[] = {"x", "y", "z", "t", "u"}; nmod_mpoly_ctx_init(ctx, 5, ORD_LEX, p); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)", vars, ctx); printf("Timing sqrt(p^2) where p = (1+x+y+2z^2+3t^3+5u^5)^n\n\n"); printf("LEX ordering\n\n"); for (n = 1; n <= 20; n++) { nmod_mpoly_pow_ui(g, f, 2*n, ctx); iters = iter_list[n]; timeit_start(timer); for (j = 0; j < iters; j++) nmod_mpoly_sqrt(h, g, ctx); timeit_stop(timer); flint_printf("n = %wd: %.10lf s\n", n, (((double)timer->wall)/iters)/1000); } nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); nmod_mpoly_ctx_init(ctx, 5, ORD_DEGREVLEX, p); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)", vars, ctx); printf("Timing sqrt(p^2) where p = (1+x+y+2z^2+3t^3+5u^5)^n\n\n"); printf("DEGREVLEX ordering:\n\n"); for (n = 1; n <= 20; n++) { nmod_mpoly_pow_ui(g, f, 2*n, ctx); iters = iter_list[n]; timeit_start(timer); for (j = 0; j < iters; j++) nmod_mpoly_sqrt(h, g, ctx); timeit_stop(timer); flint_printf("n = %wd: %.10lf s\n", n, (((double)timer->wall)/iters)/1000); } nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); return 0; } flint-3.1.3/src/nmod_mpoly/push_term.c000066400000000000000000000054431461254215100177570ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" void _nmod_mpoly_push_exp_ffmpz( nmod_mpoly_t A, const fmpz * exp, const nmod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); nmod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ffmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void _nmod_mpoly_push_exp_pfmpz( nmod_mpoly_t A, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); nmod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_pfmpz(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void nmod_mpoly_push_term_ui_fmpz( nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) { _nmod_mpoly_push_exp_pfmpz(A, exp, ctx); if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); A->coeffs[A->length - 1] = c; } void nmod_mpoly_push_term_ui_ffmpz( nmod_mpoly_t A, ulong c, const fmpz * exp, const nmod_mpoly_ctx_t ctx) { _nmod_mpoly_push_exp_ffmpz(A, exp, ctx); if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); A->coeffs[A->length - 1] = c; } void _nmod_mpoly_push_exp_ui( nmod_mpoly_t A, const ulong * exp, const nmod_mpoly_ctx_t ctx) { slong N; slong old_length = A->length; flint_bitcnt_t exp_bits; exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); nmod_mpoly_fit_length_fit_bits(A, old_length + 1, exp_bits, ctx); A->length = old_length + 1; N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ui(A->exps + N*old_length, exp, A->bits, ctx->minfo); } void nmod_mpoly_push_term_ui_ui( nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx) { _nmod_mpoly_push_exp_ui(A, exp, ctx); if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); A->coeffs[A->length - 1] = c; } flint-3.1.3/src/nmod_mpoly/quadratic_root.c000066400000000000000000000276051461254215100207750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" /* solve x^2+A*x=B if x = Q + x' for the candidate solution terms Q, x'^2+Ax'=B-Q^2-A*Q B has heap idx (-1, j) Q^2 has heap idx (-2, j) A*Q has heap idx (i, j) for i > 0 */ static int _nmod_mpoly_quadratic_root_heap( nmod_mpoly_t Q, const ulong * Aexps, slong Alen, const ulong * Bexps, slong Blen, slong bits, slong N, const ulong * cmpmask) { slong i, j, Qlen, Qs, As; slong next_loc; slong heap_len = 2; /* heap zero index unused */ mpoly_heap_s * heap; mpoly_heap_t * chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exps; ulong ** exp_list; slong exp_next; ulong mask; ulong acc; int mcmp; TMP_INIT; FLINT_ASSERT(Alen > 0); FLINT_ASSERT(Blen > 0); TMP_START; /* alloc array of heap nodes which can be chained together */ next_loc = Alen + 4; /* something bigger than heap can ever be */ heap = (mpoly_heap_s *) TMP_ALLOC((Alen + 3)*sizeof(mpoly_heap_s)); chain = (mpoly_heap_t *) TMP_ALLOC((Alen + 2)*sizeof(mpoly_heap_t)); store = store_base = (slong *) TMP_ALLOC(2*(Alen + 2)*sizeof(slong)); /* array of exponent vectors, each of "N" words */ exps = (ulong *) TMP_ALLOC((Alen + 2)*N*sizeof(ulong)); /* list of pointers to available exponent vectors */ exp_list = (ulong **) TMP_ALLOC((Alen + 2)*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < Alen + 2; i++) exp_list[i] = exps + i*N; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; Qs = 1; As = Alen; mcmp = 1; Qlen = 0; /* insert (-1, 0, Bexps[0]) into heap */ x = chain + Alen + 0; x->i = -UWORD(1); x->j = 0; x->next = NULL; heap[1].next = x; heap[1].exp = exp_list[exp_next++]; mpoly_monomial_set(heap[1].exp, Bexps + N*0, N); while (heap_len > 1) { FLINT_ASSERT(heap_len - 1 <= Alen + 2); _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, Qlen + 1); /* exp can overflow, but divisibility & halving check their answers */ mpoly_monomial_set(exp, heap[1].exp, N); acc = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; acc++; } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); while (store > store_base) { j = *--store; i = *--store; if (i == -UWORD(1)) { if (j + 1 < Blen) { x = chain + Alen; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_set(exp_list[exp_next], Bexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); } } else if (i == -UWORD(2)) { if (j + 1 < Qlen) { x = chain + Alen + 1; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Qexps + N*x->j, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } else { FLINT_ASSERT(j + 1 == Qlen); FLINT_ASSERT(Qs == 0); Qs = 1; } } else { FLINT_ASSERT(0 <= i && i < Alen); if (j + 1 < Qlen) { x = chain + i; x->i = i; x->j = j + 1; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Aexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } else { FLINT_ASSERT(j + 1 == Qlen); As++; FLINT_ASSERT(As <= Alen); } } } if ((acc % 2) == 0) continue; /* mcmp > 0: The last written Qexp is > lm(A) mcmp = 0: = lm(A) mcmp < 0: < lm(A) must find an m such that m^2 + lt(A)*m = acc*exp */ if (mcmp <= 0) goto try_less; if (bits <= FLINT_BITS ? !mpoly_monomial_halves(Qexps + N*Qlen, exp, N, mask) : !mpoly_monomial_halves_mp(Qexps + N*Qlen, exp, N, bits)) { goto try_less; } if (mpoly_monomial_gt(Qexps + N*Qlen, Aexps + N*0, N, cmpmask)) { Qcoeffs[Qlen] = 1; goto mfound; } /* z^2+z=1 insoluble over F2 */ try_less: mcmp = -1; if (bits <= FLINT_BITS ? !mpoly_monomial_divides(Qexps + Qlen*N, exp, Aexps + N*0, N, mask) : !mpoly_monomial_divides_mp(Qexps + Qlen*N, exp, Aexps + N*0, N, bits)) { goto no_solution; } if (!mpoly_monomial_lt(Qexps + N*Qlen, Aexps + N*0, N, cmpmask)) goto no_solution; Qcoeffs[Qlen] = 1; mfound: /* verify heap consistency (i >= 0, j) should be in the heap iff i >= As (-2, j) should be in the heap iff Qs = 0 */ FLINT_ASSERT(Qs == 0 || Qs == 1); FLINT_ASSERT(As <= Alen); #if FLINT_WANT_ASSERT { slong Asleft = Alen, Qsleft = 1; for (i = 1; i < heap_len; i++) { mpoly_heap_t * x = (mpoly_heap_t *) heap[i].next; do { if (x->i == -UWORD(1)) { continue; } else if (x->i == -UWORD(2)) { Qsleft--; } else { FLINT_ASSERT(x->i >= As); Asleft--; } } while ((x = x->next) != NULL); } FLINT_ASSERT(Asleft == As); FLINT_ASSERT(Qsleft == Qs); } #endif FLINT_ASSERT(mcmp < 0 || Qs == 1); if ((mcmp >= 0) < Qs) { /* the new Q^2 term did not not cancel exp */ x = chain + Alen + 1; x->i = -UWORD(2); x->j = Qlen; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Qexps + N*x->j, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } Qs = FLINT_MIN(Qs, (mcmp >= 0)); for (i = (mcmp <= 0); i < As; i++) { /* the new Q*A[i] term did not not cancel exp */ x = chain + i; x->i = i; x->j = Qlen; x->next = NULL; mpoly_monomial_add_mp(exp_list[exp_next], Aexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); FLINT_ASSERT(exp_next <= Alen + 2); FLINT_ASSERT(heap_len - 1 <= Alen + 2); } As = FLINT_MIN(As, (mcmp <= 0)); Qlen++; } Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; TMP_END; return 1; no_solution: Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = 0; TMP_END; return 0; } int nmod_mpoly_quadratic_root( nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t Qbits; ulong * cmpmask; ulong * Aexps = A->exps, * Bexps = B->exps; int success, freeAexps = 0, freeBexps = 0; TMP_INIT; if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_zero(Q, ctx); return 1; } if (nmod_mpoly_is_zero(A, ctx)) { return nmod_mpoly_sqrt(Q, B, ctx); } if (ctx->mod.n != 2) { mp_limb_t c = (ctx->mod.n - 1)/2; nmod_mpoly_t t1, t2; nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); nmod_mpoly_mul(t1, A, A, ctx); nmod_mpoly_scalar_addmul_ui(t2, B, t1, nmod_mul(c, c, ctx->mod), ctx); success = nmod_mpoly_sqrt(t1, t2, ctx); if (success) nmod_mpoly_scalar_addmul_ui(Q, t1, A, c, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); return success; } TMP_START; Qbits = FLINT_MAX(A->bits, B->bits); Qbits = mpoly_fix_bits(Qbits, ctx->minfo); N = mpoly_words_per_exp(Qbits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Qbits, ctx->minfo); /* ensure input exponents packed to same size as output exponents */ if (Qbits > A->bits) { freeAexps = 1; Aexps = (ulong *) flint_malloc(N*A->length*sizeof(ulong)); mpoly_repack_monomials(Aexps, Qbits, A->exps, A->bits, A->length, ctx->minfo); } if (Qbits > B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Qbits, B->exps, B->bits, B->length, ctx->minfo); } if (Q == A || Q == B) { nmod_mpoly_t T; nmod_mpoly_init3(T, B->length/A->length + 1, Qbits, ctx); success = _nmod_mpoly_quadratic_root_heap(T, Aexps, A->length, Bexps, B->length, Qbits, N, cmpmask); nmod_mpoly_swap(T, Q, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(Q, B->length/A->length + 1, Qbits, ctx); success = _nmod_mpoly_quadratic_root_heap(Q, Aexps, A->length, Bexps, B->length, Qbits, N, cmpmask); } if (freeAexps) flint_free(Aexps); if (freeBexps) flint_free(Bexps); TMP_END; return success; } flint-3.1.3/src/nmod_mpoly/randtest.c000066400000000000000000000051441461254215100175730ustar00rootroot00000000000000/* Copyright (C) 2017, 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_randtest_bits(nmod_mpoly_t A, flint_rand_t state, slong length, flint_bitcnt_t exp_bits, const nmod_mpoly_ctx_t ctx) { mp_limb_t p = ctx->mod.n; slong i, j, nvars = ctx->minfo->nvars; fmpz * exp; TMP_INIT; TMP_START; exp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) fmpz_init(exp + j); nmod_mpoly_zero(A, ctx); for (i = 0; i < length; i++) { mpoly_monomial_randbits_fmpz(exp, state, exp_bits, ctx->minfo); _nmod_mpoly_push_exp_ffmpz(A, exp, ctx); A->coeffs[A->length - 1] = p > 1 ? 1 + n_randint(state, p - 1) : 0; } nmod_mpoly_sort_terms(A, ctx); nmod_mpoly_combine_like_terms(A, ctx); for (j = 0; j < nvars; j++) fmpz_clear(exp + j); TMP_END; } void nmod_mpoly_randtest_bound(nmod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const nmod_mpoly_ctx_t ctx) { mp_limb_t p = ctx->mod.n; slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); nmod_mpoly_zero(A, ctx); for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bound); _nmod_mpoly_push_exp_ui(A, exp, ctx); A->coeffs[A->length - 1] = p > 1 ? 1 + n_randint(state, p - 1) : 0; } nmod_mpoly_sort_terms(A, ctx); nmod_mpoly_combine_like_terms(A, ctx); TMP_END; } void nmod_mpoly_randtest_bounds(nmod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const nmod_mpoly_ctx_t ctx) { mp_limb_t p = ctx->mod.n; slong i, j, nvars = ctx->minfo->nvars; ulong * exp; TMP_INIT; TMP_START; exp = (ulong *) TMP_ALLOC(nvars*sizeof(ulong)); nmod_mpoly_zero(A, ctx); for (i = 0; i < length; i++) { for (j = 0; j < nvars; j++) exp[j] = n_randint(state, exp_bounds[j]); _nmod_mpoly_push_exp_ui(A, exp, ctx); A->coeffs[A->length - 1] = p > 1 ? 1 + n_randint(state, p - 1) : 0; } nmod_mpoly_sort_terms(A, ctx); nmod_mpoly_combine_like_terms(A, ctx); TMP_END; } flint-3.1.3/src/nmod_mpoly/realloc.c000066400000000000000000000016771461254215100173770ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_realloc( nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(A->bits, ctx->minfo); if (alloc == 0) /* Clear up, reinitialise */ { nmod_mpoly_clear(A, ctx); nmod_mpoly_init(A, ctx); return; } A->exps_alloc = N*alloc; A->exps = (ulong *) flint_realloc(A->exps, A->exps_alloc*sizeof(ulong)); A->coeffs_alloc = alloc; A->coeffs = (mp_limb_t *) flint_realloc(A->coeffs, A->coeffs_alloc*sizeof(ulong)); } flint-3.1.3/src/nmod_mpoly/repack_bits.c000066400000000000000000000040431461254215100202320ustar00rootroot00000000000000/* Copyright (C) 2018, 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_repack_bits( nmod_mpoly_t A, const nmod_mpoly_t B, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx) { int success; Abits = mpoly_fix_bits(Abits, ctx->minfo); if (B->bits == Abits || B->length == 0) { nmod_mpoly_set(A, B, ctx); return 1; } if (A == B) return nmod_mpoly_repack_bits_inplace(A, Abits, ctx); nmod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx); success = mpoly_repack_monomials(A->exps, Abits, B->exps, B->bits, B->length, ctx->minfo); if (success) { _nmod_vec_set(A->coeffs, B->coeffs, B->length); A->length = B->length; } else { A->length = 0; } return success; } int nmod_mpoly_repack_bits_inplace( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx) { int success; ulong * texps; slong talloc; slong N = mpoly_words_per_exp(Abits, ctx->minfo); if (A->bits == Abits) { return 1; } if (A->length < 1) { A->bits = Abits; return 1; } N = mpoly_words_per_exp(Abits, ctx->minfo); talloc = N*A->length; texps = FLINT_ARRAY_ALLOC(talloc, ulong); success = mpoly_repack_monomials(texps, Abits, A->exps, A->bits, A->length, ctx->minfo); A->bits = Abits; if (success) { flint_free(A->exps); A->exps = texps; A->exps_alloc = talloc; } else { flint_free(texps); A->length = 0; } return success; } flint-3.1.3/src/nmod_mpoly/resize.c000066400000000000000000000021041461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_resize( nmod_mpoly_t A, slong new_length, const nmod_mpoly_ctx_t ctx) { slong old_length = A->length; slong N; new_length = FLINT_MAX(WORD(0), new_length); N = mpoly_words_per_exp(A->bits, ctx->minfo); if (new_length > old_length) { nmod_mpoly_fit_length(A, new_length, ctx); /* must zero out the new coeffs/exps past the old end */ N = mpoly_words_per_exp(A->bits, ctx->minfo); flint_mpn_zero(A->exps + N*old_length, N*(new_length - old_length)); _nmod_vec_zero(A->coeffs + old_length, new_length - old_length); } A->length = new_length; } flint-3.1.3/src/nmod_mpoly/resultant.c000066400000000000000000000016211461254215100177640ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" int nmod_mpoly_resultant(nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) { int success; nmod_mpoly_univar_t Ax, Bx; nmod_mpoly_univar_init(Ax, ctx); nmod_mpoly_univar_init(Bx, ctx); nmod_mpoly_to_univar(Ax, A, var, ctx); nmod_mpoly_to_univar(Bx, B, var, ctx); success = nmod_mpoly_univar_resultant(R, Ax, Bx, ctx); nmod_mpoly_univar_clear(Ax, ctx); nmod_mpoly_univar_clear(Bx, ctx); return success; } flint-3.1.3/src/nmod_mpoly/reverse.c000066400000000000000000000020071461254215100174150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_reverse(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong i; slong Blen = B->length; slong N = mpoly_words_per_exp(B->bits, ctx->minfo); if (A != B) { nmod_mpoly_fit_length_reset_bits(A, Blen, B->bits, ctx); A->length = Blen; for (i = 0; i < Blen; i++) A->coeffs[i] = B->coeffs[Blen - i - 1]; } else { for (i = 0; i < Blen/2; i++) FLINT_SWAP(mp_limb_t, A->coeffs[i], A->coeffs[Blen - i - 1]); } mpoly_reverse(A->exps, B->exps, Blen, N); } flint-3.1.3/src/nmod_mpoly/scalar.c000066400000000000000000000171061461254215100172150ustar00rootroot00000000000000/* Copyright (C) 2018, 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" slong _nmod_mpoly_scalar_addmul_ui1( mp_limb_t * Acoeffs, ulong * Aexps, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, mp_limb_t d, ulong maskhi, nmod_t fctx) { slong i = 0, j = 0, k = 0; while (i < Blen && j < Clen) { if ((Bexps[i]^maskhi) > (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; Acoeffs[k] = Bcoeffs[i]; i++; k++; } else if ((Bexps[i]^maskhi) == (Cexps[j]^maskhi)) { Aexps[k] = Bexps[i]; Acoeffs[k] = nmod_addmul(Bcoeffs[i], Ccoeffs[j], d, fctx); k += (Acoeffs[k] != 0); i++; j++; } else { Aexps[k] = Cexps[j]; Acoeffs[k] = nmod_mul(Ccoeffs[j], d, fctx); k += (Acoeffs[k] != 0); j++; } } while (i < Blen) { Aexps[k] = Bexps[i]; Acoeffs[k] = Bcoeffs[i]; i++; k++; } while (j < Clen) { Aexps[k] = Cexps[j]; Acoeffs[k] = nmod_mul(Ccoeffs[j], d, fctx); k += (Acoeffs[k] != 0); j++; } return k; } static slong _nmod_mpoly_scalar_addmul_ui( mp_limb_t * Acoeffs, ulong * Aexps, const mp_limb_t * Bcoeffs, const ulong * Bexps, slong Blen, const mp_limb_t * Ccoeffs, const ulong * Cexps, slong Clen, mp_limb_t d, slong N, const ulong * cmpmask, nmod_t fctx) { slong i = 0, j = 0, k = 0; if (N == 1) { return _nmod_mpoly_scalar_addmul_ui1(Acoeffs, Aexps, Bcoeffs, Bexps, Blen, Ccoeffs, Cexps, Clen, d, cmpmask[0], fctx); } while (i < Blen && j < Clen) { int cmp = mpoly_monomial_cmp(Bexps + i*N, Cexps + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); Acoeffs[k] = Bcoeffs[i]; i++; k++; } else if (cmp == 0) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); Acoeffs[k] = nmod_addmul(Bcoeffs[i], Ccoeffs[j], d, fctx); k += (Acoeffs[k] != 0); i++; j++; } else { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); Acoeffs[k] = nmod_mul(Ccoeffs[j], d, fctx); k += (Acoeffs[k] != 0); j++; } } while (i < Blen) { mpoly_monomial_set(Aexps + k*N, Bexps + i*N, N); Acoeffs[k] = Bcoeffs[i]; i++; k++; } while (j < Clen) { mpoly_monomial_set(Aexps + k*N, Cexps + j*N, N); Acoeffs[k] = nmod_mul(Ccoeffs[j], d, fctx); k += (Acoeffs[k] != 0); j++; } return k; } void nmod_mpoly_scalar_addmul_ui( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, mp_limb_t d, const nmod_mpoly_ctx_t ctx) { slong Abits, N; ulong * Bexps = B->exps, * Cexps = C->exps; ulong * cmpmask; int freeBexps = 0, freeCexps = 0; TMP_INIT; if (d >= ctx->mod.n) NMOD_RED(d, d, ctx->mod); if (B->length == 0) { nmod_mpoly_scalar_mul_ui(A, C, d, ctx); return; } else if (C->length == 0 || d == 0) { nmod_mpoly_set(A, B, ctx); return; } TMP_START; Abits = FLINT_MAX(B->bits, C->bits); N = mpoly_words_per_exp(Abits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); if (Abits != B->bits) { freeBexps = 1; Bexps = (ulong *) flint_malloc(N*B->length*sizeof(ulong)); mpoly_repack_monomials(Bexps, Abits, B->exps, B->bits, B->length, ctx->minfo); } if (Abits != C->bits) { freeCexps = 1; Cexps = (ulong *) flint_malloc(N*C->length*sizeof(ulong)); mpoly_repack_monomials(Cexps, Abits, C->exps, C->bits, C->length, ctx->minfo); } if (A == B || A == C) { nmod_mpoly_t T; nmod_mpoly_init3(T, B->length + C->length, Abits, ctx); T->length = _nmod_mpoly_scalar_addmul_ui(T->coeffs, T->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, d, N, cmpmask, ctx->mod); nmod_mpoly_swap(A, T, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(A, B->length + C->length, Abits, ctx); A->length = _nmod_mpoly_scalar_addmul_ui(A->coeffs, A->exps, B->coeffs, Bexps, B->length, C->coeffs, Cexps, C->length, d, N, cmpmask, ctx->mod); } if (freeBexps) flint_free(Bexps); if (freeCexps) flint_free(Cexps); TMP_END; } /* c is assumed to be invertible and reduced mod n */ void nmod_mpoly_scalar_mul_nmod_invertible( nmod_mpoly_t A, const nmod_mpoly_t B, mp_limb_t c, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(c != 0); FLINT_ASSERT(c < ctx->mod.n); FLINT_ASSERT(n_gcd(c, ctx->mod.n) == 1); if (A == B) { if (c == 1) return; } else { slong N; nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); A->length = B->length; N = mpoly_words_per_exp(B->bits, ctx->minfo); flint_mpn_copyi(A->exps, B->exps, N*B->length); if (c == UWORD(1)) { flint_mpn_copyi(A->coeffs, B->coeffs, B->length); return; } } _nmod_vec_scalar_mul_nmod(A->coeffs, B->coeffs, B->length, c, ctx->mod); } /* c is assumed to be reduced mod n */ void nmod_mpoly_scalar_mul_nmod_general( nmod_mpoly_t A, const nmod_mpoly_t B, mp_limb_t c, const nmod_mpoly_ctx_t ctx) { slong i, N; slong Alen, Blen; ulong * Aexp, * Bexp; mp_limb_t * Acoeff, * Bcoeff; FLINT_ASSERT(c < ctx->mod.n); N = mpoly_words_per_exp(B->bits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); Aexp = A->exps; Bexp = B->exps; Acoeff = A->coeffs; Bcoeff = B->coeffs; Blen = B->length; Alen = 0; for (i = 0; i < Blen; i++) { mpoly_monomial_set(Aexp + N*Alen, Bexp + N*i, N); Acoeff[Alen] = nmod_mul(Bcoeff[i], c, ctx->mod); Alen += (Acoeff[Alen] != UWORD(0)); } A->length = Alen; } void nmod_mpoly_scalar_mul_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx) { if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); if (c == 0 || nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_zero(A, ctx); return; } if (n_gcd(c, ctx->mod.n) == 1) nmod_mpoly_scalar_mul_nmod_invertible(A, B, c, ctx); else nmod_mpoly_scalar_mul_nmod_general(A, B, c, ctx); return; } flint-3.1.3/src/nmod_mpoly/set.c000066400000000000000000000015371461254215100165440ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_set( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(B->bits, ctx->minfo); if (A == B) return; nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, ctx); _nmod_vec_set(A->coeffs, B->coeffs, B->length); mpoly_copy_monomials(A->exps, B->exps, B->length, N); _nmod_mpoly_set_length(A, B->length, ctx); } flint-3.1.3/src/nmod_mpoly/set_coeff.c000066400000000000000000000076311461254215100177070ustar00rootroot00000000000000/* Copyright (C) 2017, 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" void _nmod_mpoly_set_coeff_ui_fmpz( nmod_mpoly_t A, ulong c, const fmpz * exp, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t exp_bits; slong i, N, index; ulong * cmpmask; ulong * packed_exp; int exists; TMP_INIT; TMP_START; if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); exp_bits = mpoly_exp_bits_required_ffmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); nmod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, A->bits, ctx->minfo); packed_exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ffmpz(packed_exp, exp, A->bits, ctx->minfo); exists = mpoly_monomial_exists(&index, A->exps, packed_exp, A->length, N, cmpmask); if (!exists) { if (c != UWORD(0)) /* make new term only if coeff is nonzero*/ { nmod_mpoly_fit_length(A, A->length + 1, ctx); for (i = A->length; i >= index + 1; i--) { A->coeffs[i] = A->coeffs[i - 1]; mpoly_monomial_set(A->exps + N*i, A->exps + N*(i - 1), N); } A->coeffs[index] = c; mpoly_monomial_set(A->exps + N*index, packed_exp, N); A->length++; } } else if (c == UWORD(0)) /* zero coeff, remove term */ { for (i = index; i < A->length - 1; i++) { A->coeffs[i] = A->coeffs[i + 1]; mpoly_monomial_set(A->exps + N*i, A->exps + N*(i + 1), N); } A->length--; } else /* term with that monomial exists, coeff is nonzero */ { A->coeffs[index] = c; } TMP_END; } void nmod_mpoly_set_coeff_ui_fmpz( nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) { fmpz_init(newexp + i); fmpz_set(newexp + i, exp[i]); } _nmod_mpoly_set_coeff_ui_fmpz(A, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } void nmod_mpoly_set_coeff_ui_monomial(nmod_mpoly_t A, ulong c, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * texps; TMP_INIT; if (M->length != WORD(1)) { flint_throw(FLINT_ERROR, "M not monomial in nmod_mpoly_set_coeff_ui_monomial"); } TMP_START; texps = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init(texps + i); mpoly_get_monomial_ffmpz(texps, M->exps + 0, M->bits, ctx->minfo); _nmod_mpoly_set_coeff_ui_fmpz(A, c, texps, ctx); for (i = 0; i < nvars; i++) fmpz_clear(texps + i); TMP_END; return; } void nmod_mpoly_set_coeff_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx) { slong i, nvars = ctx->minfo->nvars; fmpz * newexp; TMP_INIT; TMP_START; newexp = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) fmpz_init_set_ui(newexp + i, exp[i]); _nmod_mpoly_set_coeff_ui_fmpz(A, c, newexp, ctx); for (i = 0; i < nvars; i++) fmpz_clear(newexp + i); TMP_END; } flint-3.1.3/src/nmod_mpoly/set_fmpz.c000066400000000000000000000020501461254215100175670ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_set_ui( nmod_mpoly_t A, ulong c, const nmod_mpoly_ctx_t ctx) { slong N; N = mpoly_words_per_exp(A->bits, ctx->minfo); if (c >= ctx->mod.n) NMOD_RED(c, c, ctx->mod); if (c == 0) { _nmod_mpoly_set_length(A, 0, ctx); return; } nmod_mpoly_fit_length(A, 1, ctx); A->coeffs[0] = c; mpoly_monomial_zero(A->exps, N); _nmod_mpoly_set_length(A, 1, ctx); } void nmod_mpoly_set_fmpz( nmod_mpoly_t A, const fmpz_t c, const nmod_mpoly_ctx_t ctx) { nmod_mpoly_set_ui(A, fmpz_get_nmod(c, ctx->mod), ctx); } flint-3.1.3/src/nmod_mpoly/set_str_pretty.c000066400000000000000000000023711461254215100210400ustar00rootroot00000000000000/* Copyright (C) 2019-2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_set_str_pretty(nmod_mpoly_t poly, const char * str, const char** x, const nmod_mpoly_ctx_t ctx) { int ret; slong i; nmod_mpoly_t val; mpoly_parse_t E; char dummy[FLINT_BITS/2]; mpoly_void_ring_init_nmod_mpoly_ctx(E->R, ctx); mpoly_parse_init(E); nmod_mpoly_init(val, ctx); for (i = 0; i < ctx->minfo->nvars; i++) { nmod_mpoly_gen(val, i, ctx); if (x == NULL) { flint_sprintf(dummy, "x%wd", i + 1); mpoly_parse_add_terminal(E, dummy, (const void *)val); } else { mpoly_parse_add_terminal(E, x[i], (const void *)val); } } nmod_mpoly_clear(val, ctx); ret = mpoly_parse_parse(E, poly, str, strlen(str)); mpoly_parse_clear(E); return ret; } flint-3.1.3/src/nmod_mpoly/set_term_coeff_ui.c000066400000000000000000000014411461254215100214240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mpoly.h" void nmod_mpoly_set_term_coeff_ui(nmod_mpoly_t A, slong i, ulong c, const nmod_mpoly_ctx_t ctx) { if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "nmod_mpoly_set_term_coeff_ui: index out of range."); } if (c >= ctx->mod.n) { NMOD_RED(c, c, ctx->mod); } A->coeffs[i] = c; } flint-3.1.3/src/nmod_mpoly/set_term_exp.c000066400000000000000000000031721461254215100204440ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_set_term_exp_fmpz(nmod_mpoly_t A, slong i, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "nmod_mpoly_set_term_exp_fmpz: index out of range"); } exp_bits = mpoly_exp_bits_required_pfmpz(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); nmod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_pfmpz(A->exps + N*i, exp, A->bits, ctx->minfo); } void nmod_mpoly_set_term_exp_ui(nmod_mpoly_t A, slong i, const ulong * exp, const nmod_mpoly_ctx_t ctx) { slong N; flint_bitcnt_t exp_bits; if (i >= (ulong) A->length) { flint_throw(FLINT_ERROR, "nmod_mpoly_set_term_exp_ui: index is out of range"); } exp_bits = mpoly_exp_bits_required_ui(exp, ctx->minfo); exp_bits = mpoly_fix_bits(exp_bits, ctx->minfo); nmod_mpoly_fit_length_fit_bits(A, A->length, exp_bits, ctx); N = mpoly_words_per_exp(A->bits, ctx->minfo); mpoly_set_monomial_ui(A->exps + N*i, exp, A->bits, ctx->minfo); } flint-3.1.3/src/nmod_mpoly/setform.c000066400000000000000000000042671461254215100174330ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" /* setform copies the exponents and zeros the coefficients */ void nmod_mpoly_setform(nmod_mpoly_t A, nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(A, B->length, bits, ctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); _nmod_vec_zero(A->coeffs, B->length); A->length = B->length; } void nmod_mpolyu_setform(nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx) { slong i; nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { nmod_mpoly_setform(A->coeffs + i, B->coeffs + i, ctx); A->exps[i] = B->exps[i]; } A->length = B->length; } void nmod_mpoly_setform_mpolyn(nmod_mpoly_t A, nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx) { slong i; slong N; FLINT_ASSERT(A->bits == B->bits); nmod_mpoly_fit_length(A, B->length, ctx); N = mpoly_words_per_exp(B->bits, ctx->minfo); for (i = 0; i < B->length; i++) { A->coeffs[i] = UWORD(0); mpoly_monomial_set(A->exps + N*i, B->exps + N*i, N); } A->length = B->length; } void nmod_mpolyu_setform_mpolyun(nmod_mpolyu_t A, nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx) { slong i; nmod_mpolyu_fit_length(A, B->length, ctx); for (i = 0; i < B->length; i++) { FLINT_ASSERT((B->coeffs + i)->bits == B->bits); nmod_mpoly_setform_mpolyn(A->coeffs + i, B->coeffs + i, ctx); A->exps[i] = B->exps[i]; } A->length = B->length; } flint-3.1.3/src/nmod_mpoly/sort_terms.c000066400000000000000000000112431461254215100201450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" /* sort terms in [left, right) by exponent assuming that bits in position > pos are already sorted and assuming exponent vectors fit into one word and assuming that all bit positions that need to be sorted are in totalmask */ void _nmod_mpoly_radix_sort1(nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask) { ulong mask = UWORD(1) << pos; ulong cmp = cmpmask & mask; slong mid, cur; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < FLINT_BITS); /* do nothing on lists of 0 or 1 elements */ if (left + 1 >= right) { return; } /* return if there is no information to sort on this bit */ if ((totalmask & mask) == WORD(0)) { --pos; if ((slong)(pos) >= 0) { _nmod_mpoly_radix_sort1(A, left, right, pos, cmpmask, totalmask); } return; } /* find first 'zero' */ mid = left; while (mid < right && ((A->exps + 1*mid)[0] & mask) != cmp) { mid++; } /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ cur = mid; while (++cur < right) { if (((A->exps + 1*cur)[0] & mask) != cmp) { { mp_limb_t t; t = A->coeffs[mid]; A->coeffs[mid] = A->coeffs[cur]; A->coeffs[cur] = t; } mpoly_monomial_swap(A->exps + 1*cur, A->exps + 1*mid, 1); mid++; } } --pos; if ((slong)(pos) >= 0) { _nmod_mpoly_radix_sort1(A, left, mid, pos, cmpmask, totalmask); _nmod_mpoly_radix_sort1(A, mid, right, pos, cmpmask, totalmask); } } /* sort terms in [left, right) by exponent assuming that bits in position > pos are already sorted TODO: Stack depth is proportional to N*FLINT_BITS Might turn into iterative version Low priority */ void _nmod_mpoly_radix_sort(nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask) { ulong off = pos/FLINT_BITS; ulong bit = pos%FLINT_BITS; ulong mask = UWORD(1) << bit; ulong cmp = cmpmask[off] & mask; slong mid, check; FLINT_ASSERT(left <= right); FLINT_ASSERT(pos < N*FLINT_BITS); /* do nothing on lists of 0 or 1 elements */ if (left + 1 >= right) return; /* find first 'zero' */ mid = left; while (mid < right && ((A->exps+N*mid)[off] & mask) != cmp) { mid++; } /* make sure [left,mid) doesn't match cmpmask in position pos 'one' [mid,right) does match cmpmask in position pos 'zero' */ check = mid; while (++check < right) { if (((A->exps + N*check)[off] & mask) != cmp) { { mp_limb_t t; t = A->coeffs[mid]; A->coeffs[mid] = A->coeffs[check]; A->coeffs[check] = t; } mpoly_monomial_swap(A->exps + N*check, A->exps + N*mid, N); mid++; } } --pos; if ((slong)(pos) >= 0) { _nmod_mpoly_radix_sort(A, left, mid, pos, N, cmpmask); _nmod_mpoly_radix_sort(A, mid, right, pos, N, cmpmask); } } /* sort the terms in A by exponent assuming that the exponents are valid (other than being in order) */ void nmod_mpoly_sort_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong i, msb, N; ulong himask, * ptempexp; TMP_INIT; TMP_START; N = mpoly_words_per_exp(A->bits, ctx->minfo); ptempexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(ptempexp, N, A->bits, ctx->minfo); himask = 0; for (i = 0; i < A->length; i++) { himask |= (A->exps + N*i)[N - 1]; } if (himask != 0) { msb = flint_clz(himask); msb = (FLINT_BITS - 1)^msb; } else { msb = -WORD(1); } if (N == 1) { if (msb >= 0) { _nmod_mpoly_radix_sort1(A, 0, A->length, msb, ptempexp[0], himask); } } else { _nmod_mpoly_radix_sort(A, 0, A->length, (N - 1)*FLINT_BITS + msb, N, ptempexp); } TMP_END; } flint-3.1.3/src/nmod_mpoly/sqrt_heap.c000066400000000000000000000522211461254215100177330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif #include "nmod.h" #include "fq_zech.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fq_zech_mpoly.h" static int _is_proved_not_square_medprime( int count, flint_rand_t state, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx, nmod_t mod) { int success = 0; slong i; fq_zech_struct eval[1], * t, * alphas, ** alpha_ptrs; fq_zech_ctx_t fqctx; slong edeg, max_degree = n_flog(1000000, mod.n); TMP_INIT; FLINT_ASSERT(Alen > 0); edeg = (max_degree + count - 2)/2; edeg = FLINT_MAX(2, edeg); if (edeg > max_degree) return 0; fq_zech_ctx_init_ui(fqctx, mod.n, edeg, "#"); fq_zech_init(eval, fqctx); TMP_START; alphas = (fq_zech_struct *) TMP_ALLOC(mctx->nvars*sizeof(fq_zech_struct)); alpha_ptrs = (fq_zech_struct **) TMP_ALLOC(mctx->nvars*sizeof(fq_zech_struct *)); for (i = 0; i < mctx->nvars; i++) { alpha_ptrs[i] = alphas + i; fq_zech_init(alphas + i, fqctx); } t = (fq_zech_struct *) TMP_ALLOC(Alen*sizeof(fq_zech_struct)); for (i = 0; i < Alen; i++) { fq_zech_init(t + i, fqctx); fq_zech_set_ui(t + i, Acoeffs[i], fqctx); } /* try at most 3*count evaluations */ count *= 3; next_p: for (i = 0; i < mctx->nvars; i++) fq_zech_rand(alphas + i, state, fqctx); _fq_zech_mpoly_eval_all_fq_zech(eval, t, Aexps, Alen, Abits, alpha_ptrs, mctx, fqctx); success = !fq_zech_is_square(eval, fqctx); if (!success && --count >= 0) goto next_p; fq_zech_clear(eval, fqctx); fq_zech_ctx_clear(fqctx); TMP_END; return success; } /* try to prove that A is not a square */ static int _is_proved_not_square( int count, flint_rand_t state, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx, nmod_t mod) { int tries_left, success = 0; slong i, N = mpoly_words_per_exp(Abits, mctx); mp_limb_t eval, * alphas; ulong * t; TMP_INIT; FLINT_ASSERT(Alen > 0); TMP_START; t = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (count == 1) { success = mpoly_is_proved_not_square(Aexps, Alen, Abits, N, t); if (success) goto cleanup; } tries_left = 3*count; alphas = (mp_limb_t *) TMP_ALLOC(mctx->nvars*sizeof(mp_limb_t)); next_p: for (i = 0; i < mctx->nvars; i++) alphas[i] = n_urandint(state, mod.n); eval = _nmod_mpoly_eval_all_ui(Acoeffs, Aexps, Alen, Abits, alphas, mctx, mod); success = n_jacobi_unsigned(eval, mod.n) < 0; if (!success && --tries_left >= 0) goto next_p; cleanup: TMP_END; if (!success) success = _is_proved_not_square_medprime(count, state, Acoeffs, Aexps, Alen, Abits, mctx, mod); return success; } static int _nmod_mpoly_sqrt_heap1( nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t bits, const mpoly_ctx_t mctx, nmod_t mod) { slong i, j, Qlen, Ai; slong next_loc, heap_len = 1, heap_alloc; mpoly_heap1_s * heap; mpoly_heap_t * chain_nodes[64]; mpoly_heap_t ** chain; slong exp_alloc; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong mask, exp, exp3 = 0; ulong maskhi; ulong pp1, pp0, acc2, acc1, acc0, tmp2, tmp1, tmp0, lc_minus_inv; int lt_divides; flint_rand_t heuristic_state; int heuristic_count = 0; FLINT_ASSERT(mpoly_words_per_exp(bits, mctx) == 1); mpoly_get_cmpmask(&maskhi, 1, bits, mctx); flint_randinit(heuristic_state); /* alloc array of heap nodes which can be chained together */ next_loc = 2*n_sqrt(Alen) + 4; /* something bigger than heap can ever be */ heap_alloc = next_loc - 3; heap = (mpoly_heap1_s *) flint_malloc((heap_alloc + 1)*sizeof(mpoly_heap1_s)); chain_nodes[0] = (mpoly_heap_t *) flint_malloc(heap_alloc*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_malloc(heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_malloc(2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc; i++) chain[i] = chain_nodes[0] + i; exp_alloc = 1; mask = mpoly_overflow_mask_sp(bits); /* "insert" (-1, 1, Aexps[1]) into "heap" */ Ai = 1; /* compute first term */ Qlen = 0; _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); Qcoeffs[0] = n_sqrtmod(Acoeffs[0], mod.n); if (Qcoeffs[0] == 0) goto not_sqrt; Qlen = 1; /* precompute leading coefficient info */ lc_minus_inv = mod.n - nmod_inv(nmod_add(Qcoeffs[0], Qcoeffs[0], mod), mod); if (!mpoly_monomial_halves1(Qexps + 0, Aexps[0], mask)) goto not_sqrt; /* exponent is not square */ /* optimisation, compute final exponent */ { if (0 == n_sqrtmod(Acoeffs[Alen - 1], mod.n)) goto not_sqrt; if (!mpoly_monomial_halves1(&exp3, Aexps[Alen - 1], mask)) goto not_sqrt; /* exponent is not square */ exp3 += Qexps[0]; /* overflow not possible */ } while (heap_len > 1 || Ai < Alen) { _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, 1, Qlen + 1); acc2 = acc1 = acc0 = 0; if (heap_len > 1 && Ai < Alen && Aexps[Ai] == heap[1].exp) { /* take from both A and heap */ exp = Aexps[Ai]; acc0 = mod.n - Acoeffs[Ai]; Ai++; } else if (heap_len > 1 && (Ai >= Alen || mpoly_monomial_gt1(heap[1].exp, Aexps[Ai], maskhi))) { /* take only from heap */ exp = heap[1].exp; if (mpoly_monomial_overflows1(exp, mask)) goto not_sqrt; } else { FLINT_ASSERT(Ai < Alen); /* take only from A */ exp = Aexps[Ai]; acc0 = mod.n - Acoeffs[Ai]; Ai++; goto skip_heap; } /* total is always acc + 2*tmp */ tmp2 = tmp1 = tmp0 = 0; do { x = _mpoly_heap_pop1(heap, &heap_len, maskhi); do { *store++ = x->i; *store++ = x->j; umul_ppmm(pp1, pp0, Qcoeffs[x->i], Qcoeffs[x->j]); if (x->i != x->j) add_sssaaaaaa(tmp2, tmp1, tmp0, tmp2, tmp1, tmp0, UWORD(0), pp1, pp0); else add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), pp1, pp0); } while ((x = x->next) != NULL); } while (heap_len > 1 && heap[1].exp == exp); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, tmp2, tmp1, tmp0); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, tmp2, tmp1, tmp0); NMOD_RED3(acc0, acc2, acc1, acc0, mod); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right */ if (j < i) { x = chain[i]; x->i = i; x->j = j + 1; x->next = NULL; _mpoly_heap_insert1(heap, Qexps[x->i] + Qexps[x->j], x, &next_loc, &heap_len, maskhi); } } if (acc0 == 0) continue; skip_heap: lt_divides = mpoly_monomial_divides1(Qexps + Qlen, exp, Qexps[0], mask); if (!lt_divides) goto not_sqrt; Qcoeffs[Qlen] = nmod_mul(acc0, lc_minus_inv, mod); if (Qlen >= heap_alloc) { /* run some tests if the square root is getting long */ if (Qlen > Alen && _is_proved_not_square( ++heuristic_count, heuristic_state, Acoeffs, Aexps, Alen, bits, mctx, mod)) { goto not_sqrt; } heap_alloc *= 2; heap = (mpoly_heap1_s *) flint_realloc(heap, (heap_alloc + 1)*sizeof(mpoly_heap1_s)); chain_nodes[exp_alloc] = (mpoly_heap_t *) flint_malloc((heap_alloc/2)*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_realloc(chain, heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_realloc(store_base, 2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc/2; i++) chain[i + heap_alloc/2] = chain_nodes[exp_alloc] + i; exp_alloc++; } /* put (Qlen, 1) in heap */ i = Qlen; x = chain[i]; x->i = i; x->j = 1; x->next = NULL; _mpoly_heap_insert1(heap, Qexps[i] + Qexps[1], x, &next_loc, &heap_len, maskhi); Qlen++; } cleanup: flint_randclear(heuristic_state); Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; flint_free(heap); flint_free(chain); flint_free(store_base); for (i = 0; i < exp_alloc; i++) flint_free(chain_nodes[i]); return Qlen > 0; not_sqrt: Qlen = 0; goto cleanup; } static int _nmod_mpoly_sqrt_heap( nmod_mpoly_t Q, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, flint_bitcnt_t bits, const mpoly_ctx_t mctx, nmod_t mod) { slong N = mpoly_words_per_exp(bits, mctx); ulong * cmpmask; slong i, j, Qlen, Ai; slong next_loc; slong heap_len = 1, heap_alloc; int exp_alloc; mpoly_heap_s * heap; mpoly_heap_t * chain_nodes[64]; mpoly_heap_t ** chain; slong * store, * store_base; mpoly_heap_t * x; mp_limb_t * Qcoeffs = Q->coeffs; ulong * Qexps = Q->exps; ulong * exp, * exp3; ulong * exps[64]; ulong ** exp_list; slong exp_next; ulong mask; ulong pp1, pp0, acc2, acc1, acc0, tmp2, tmp1, tmp0, lc_minus_inv; int lt_divides, halves; flint_rand_t heuristic_state; int heuristic_count = 0; TMP_INIT; if (N == 1) return _nmod_mpoly_sqrt_heap1(Q, Acoeffs, Aexps, Alen, bits, mctx, mod); TMP_START; cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, mctx); flint_randinit(heuristic_state); /* alloc array of heap nodes which can be chained together */ next_loc = 2*sqrt(Alen) + 4; /* something bigger than heap can ever be */ heap_alloc = next_loc - 3; heap = (mpoly_heap_s *) flint_malloc((heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[0] = (mpoly_heap_t *) flint_malloc(heap_alloc*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_malloc(heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_malloc(2*heap_alloc*sizeof(mpoly_heap_t *)); for (i = 0; i < heap_alloc; i++) chain[i] = chain_nodes[0] + i; /* array of exponent vectors, each of "N" words */ exps[0] = (ulong *) flint_malloc(heap_alloc*N*sizeof(ulong)); exp_alloc = 1; /* list of pointers to available exponent vectors */ exp_list = (ulong **) flint_malloc(heap_alloc*sizeof(ulong *)); /* space to save copy of current exponent vector */ exp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* final exponent */ exp3 = (ulong *) TMP_ALLOC(N*sizeof(ulong)); /* set up list of available exponent vectors */ exp_next = 0; for (i = 0; i < heap_alloc; i++) exp_list[i] = exps[0] + i*N; mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; /* "insert" (-1, 1, Aexps[0]) into "heap" */ Ai = 1; /* compute first term */ Qlen = 0; _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, Qlen + 1); Qcoeffs[0] = n_sqrtmod(Acoeffs[0], mod.n); if (Qcoeffs[0] == 0) goto not_sqrt; Qlen = 1; /* precompute leading coefficient info */ lc_minus_inv = mod.n - nmod_inv(nmod_add(Qcoeffs[0], Qcoeffs[0], mod), mod); if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(Qexps + 0, Aexps + 0, N, mask); else halves = mpoly_monomial_halves_mp(Qexps + 0, Aexps + 0, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ /* optimisation, compute final term */ { if (0 == n_sqrtmod(Acoeffs[Alen - 1], mod.n)) goto not_sqrt; if (bits <= FLINT_BITS) halves = mpoly_monomial_halves(exp3, Aexps + (Alen - 1)*N, N, mask); else halves = mpoly_monomial_halves_mp(exp3, Aexps + (Alen - 1)*N, N, bits); if (!halves) goto not_sqrt; /* exponent is not square */ if (bits <= FLINT_BITS) mpoly_monomial_add(exp3, exp3, Qexps + 0, N); else mpoly_monomial_add_mp(exp3, exp3, Qexps + 0, N); } while (heap_len > 1 || Ai < Alen) { _nmod_mpoly_fit_length(&Qcoeffs, &Q->coeffs_alloc, &Qexps, &Q->exps_alloc, N, Qlen + 1); acc2 = acc1 = acc0 = 0; if (heap_len > 1 && Ai < Alen && mpoly_monomial_equal(Aexps + N*Ai, heap[1].exp, N)) { /* take from both A and heap */ mpoly_monomial_set(exp, Aexps + N*Ai, N); acc0 = mod.n - Acoeffs[Ai]; Ai++; } else if (heap_len > 1 && (Ai >= Alen || mpoly_monomial_lt( Aexps + N*Ai, heap[1].exp, N, cmpmask))) { /* take only from heap */ mpoly_monomial_set(exp, heap[1].exp, N); if (bits <= FLINT_BITS ? mpoly_monomial_overflows(exp, N, mask) : mpoly_monomial_overflows_mp(exp, N, bits)) goto not_sqrt; } else { FLINT_ASSERT(Ai < Alen); /* take only from A */ mpoly_monomial_set(exp, Aexps + N*Ai, N); acc0 = mod.n - Acoeffs[Ai]; Ai++; goto skip_heap; } /* total is always -acc - 2*tmp */ tmp2 = tmp1 = tmp0 = 0; do { exp_list[--exp_next] = heap[1].exp; x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); do { *store++ = x->i; *store++ = x->j; FLINT_ASSERT(x->i > 0 && x->j > 0); umul_ppmm(pp1, pp0, Qcoeffs[x->i], Qcoeffs[x->j]); if (x->i != x->j) add_sssaaaaaa(tmp2, tmp1, tmp0, tmp2, tmp1, tmp0, UWORD(0), pp1, pp0); else add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, UWORD(0), pp1, pp0); } while ((x = x->next) != NULL); } while (heap_len > 1 && mpoly_monomial_equal(heap[1].exp, exp, N)); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, tmp2, tmp1, tmp0); add_sssaaaaaa(acc2, acc1, acc0, acc2, acc1, acc0, tmp2, tmp1, tmp0); NMOD_RED3(acc0, acc2, acc1, acc0, mod); /* process nodes taken from the heap */ while (store > store_base) { j = *--store; i = *--store; /* should we go right */ if (j < i) { x = chain[i]; x->i = i; x->j = j + 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + N*x->i, Qexps + N*x->j, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + N*x->i, Qexps + N*x->j, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); } } if (acc0 == 0) continue; skip_heap: if (bits <= FLINT_BITS) lt_divides = mpoly_monomial_divides(Qexps + N*Qlen, exp, Qexps + N*0, N, mask); else lt_divides = mpoly_monomial_divides_mp(Qexps + N*Qlen, exp, Qexps + N*0, N, bits); if (!lt_divides) goto not_sqrt; Qcoeffs[Qlen] = nmod_mul(acc0, lc_minus_inv, mod); if (Qlen >= heap_alloc) { /* run some tests if the square root is getting long */ if (Qlen > Alen && _is_proved_not_square( ++heuristic_count, heuristic_state, Acoeffs, Aexps, Alen, bits, mctx, mod)) { goto not_sqrt; } heap_alloc *= 2; heap = (mpoly_heap_s *) flint_realloc(heap, (heap_alloc + 1)*sizeof(mpoly_heap_s)); chain_nodes[exp_alloc] = (mpoly_heap_t *) flint_malloc((heap_alloc/2)*sizeof(mpoly_heap_t)); chain = (mpoly_heap_t **) flint_realloc(chain, heap_alloc*sizeof(mpoly_heap_t*)); store = store_base = (slong *) flint_realloc(store_base, 2*heap_alloc*sizeof(mpoly_heap_t *)); exps[exp_alloc] = (ulong *) flint_malloc((heap_alloc/2)*N*sizeof(ulong)); exp_list = (ulong **) flint_realloc(exp_list, heap_alloc*sizeof(ulong *)); for (i = 0; i < heap_alloc/2; i++) { chain[i + heap_alloc/2] = chain_nodes[exp_alloc] + i; exp_list[i + heap_alloc/2] = exps[exp_alloc] + i*N; } exp_alloc++; } /* put (Qlen, 1) in heap */ i = Qlen; x = chain[i]; x->i = i; x->j = 1; x->next = NULL; if (bits <= FLINT_BITS) mpoly_monomial_add(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); else mpoly_monomial_add_mp(exp_list[exp_next], Qexps + x->i*N, Qexps + x->j*N, N); exp_next += _mpoly_heap_insert(heap, exp_list[exp_next], x, &next_loc, &heap_len, N, cmpmask); Qlen++; } cleanup: flint_randclear(heuristic_state); Q->coeffs = Qcoeffs; Q->exps = Qexps; Q->length = Qlen; flint_free(heap); flint_free(chain); flint_free(store_base); flint_free(exp_list); for (i = 0; i < exp_alloc; i++) { flint_free(exps[i]); flint_free(chain_nodes[i]); } TMP_END; return Qlen > 0; not_sqrt: Qlen = 0; goto cleanup; } int nmod_mpoly_sqrt_heap(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { int success; slong lenq_est; if ((ctx->mod.n % 2) == 0) { flint_bitcnt_t bits = A->bits; mp_limb_t * Aexps = A->exps; slong Alen = A->length; slong i, N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 0; if (ctx->mod.n != 2) flint_throw(FLINT_IMPINV, "nmod_mpoly_sqrt_heap: " "cannot compute sqrt modulo %wd*%wd", 2, ctx->mod.n/2); if (Q != A) { nmod_mpoly_fit_length_reset_bits(Q, Alen, bits, ctx); for (i = 0; i < Alen; i++) Q->coeffs[i] = 1; } for (i = 0; i < Alen; i++) { if (bits <= FLINT_BITS ? !mpoly_monomial_halves(Q->exps + N*i, Aexps + N*i, N, mask) : !mpoly_monomial_halves_mp(Q->exps + N*i, Aexps + N*i, N, bits)) { Q->length = 0; return 0; } } Q->length = Alen; return 1; } if (nmod_mpoly_is_zero(A, ctx)) { nmod_mpoly_zero(Q, ctx); return 1; } lenq_est = n_sqrt(A->length); if (Q == A) { nmod_mpoly_t T; nmod_mpoly_init3(T, lenq_est, A->bits, ctx); success = _nmod_mpoly_sqrt_heap(T, A->coeffs, A->exps, A->length, A->bits, ctx->minfo, ctx->mod); nmod_mpoly_swap(Q, T, ctx); nmod_mpoly_clear(T, ctx); } else { nmod_mpoly_fit_length_reset_bits(Q, lenq_est, A->bits, ctx); success = _nmod_mpoly_sqrt_heap(Q, A->coeffs, A->exps, A->length, A->bits, ctx->minfo, ctx->mod); } return success; } flint-3.1.3/src/nmod_mpoly/stack.c000066400000000000000000000120451461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "n_poly.h" #include "nmod_mpoly.h" void nmod_poly_stack_init(nmod_poly_stack_t S, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx) { S->bits = bits; S->ctx = ctx; S->poly_alloc = 0; S->poly_array = NULL; S->poly_top = 0; S->mpolyun_alloc = 0; S->mpolyun_array = NULL; S->mpolyun_top = 0; S->mpolyn_alloc = 0; S->mpolyn_array = NULL; S->mpolyn_top = 0; } void nmod_poly_stack_clear(nmod_poly_stack_t S) { slong i; FLINT_ASSERT(S->poly_top == 0); for (i = 0; i < S->poly_alloc; i++) { n_poly_clear(S->poly_array[i]); flint_free(S->poly_array[i]); } if (S->poly_array) flint_free(S->poly_array); for (i = 0; i < S->mpolyun_alloc; i++) { nmod_mpolyun_clear(S->mpolyun_array[i], S->ctx); flint_free(S->mpolyun_array[i]); } if (S->mpolyun_array) flint_free(S->mpolyun_array); for (i = 0; i < S->mpolyn_alloc; i++) { nmod_mpolyn_clear(S->mpolyn_array[i], S->ctx); flint_free(S->mpolyn_array[i]); } if (S->mpolyn_array) flint_free(S->mpolyn_array); S->ctx = NULL; } void nmod_poly_stack_set_ctx(nmod_poly_stack_t S, const nmod_mpoly_ctx_t ctx) { slong i; FLINT_ASSERT(S->ctx->minfo->nvars == ctx->minfo->nvars); S->ctx = ctx; for (i = 0; i < S->mpolyun_alloc; i++) { nmod_mpolyun_set_mod(S->mpolyun_array[i], S->ctx->mod); } for (i = 0; i < S->mpolyn_alloc; i++) { nmod_mpolyn_set_mod(S->mpolyn_array[i], S->ctx->mod); } } /* insure that k slots are available after top and return pointer to top */ n_poly_struct ** nmod_poly_stack_fit_request_poly(nmod_poly_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->poly_alloc >= S->poly_top); if (S->poly_top + k > S->poly_alloc) { newalloc = FLINT_MAX(WORD(1), S->poly_top + k); if (S->poly_array) { S->poly_array = (n_poly_struct **) flint_realloc(S->poly_array, newalloc*sizeof(n_poly_struct*)); } else { S->poly_array = (n_poly_struct **) flint_malloc( newalloc*sizeof(n_poly_struct*)); } for (i = S->poly_alloc; i < newalloc; i++) { S->poly_array[i] = (n_poly_struct *) flint_malloc( sizeof(n_poly_struct)); n_poly_init(S->poly_array[i]); } S->poly_alloc = newalloc; } return S->poly_array + S->poly_top; } nmod_mpolyun_struct ** nmod_poly_stack_fit_request_mpolyun(nmod_poly_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->mpolyun_alloc >= S->mpolyun_top); if (S->mpolyun_top + k > S->mpolyun_alloc) { newalloc = FLINT_MAX(WORD(1), S->mpolyun_top + k); if (S->mpolyun_array) { S->mpolyun_array = (nmod_mpolyun_struct **) flint_realloc(S->mpolyun_array, newalloc*sizeof(nmod_mpolyun_struct*)); } else { S->mpolyun_array = (nmod_mpolyun_struct **) flint_malloc( newalloc*sizeof(nmod_mpolyun_struct*)); } for (i = S->mpolyun_alloc; i < newalloc; i++) { S->mpolyun_array[i] = (nmod_mpolyun_struct *) flint_malloc( sizeof(nmod_mpolyun_struct)); nmod_mpolyun_init(S->mpolyun_array[i], S->bits, S->ctx); } S->mpolyun_alloc = newalloc; } return S->mpolyun_array + S->mpolyun_top; } nmod_mpolyn_struct ** nmod_poly_stack_fit_request_mpolyn(nmod_poly_stack_t S, slong k) { slong newalloc, i; FLINT_ASSERT(S->mpolyn_alloc >= S->mpolyn_top); if (S->mpolyn_top + k > S->mpolyn_alloc) { newalloc = FLINT_MAX(WORD(1), S->mpolyn_top + k); if (S->mpolyn_array) { S->mpolyn_array = (nmod_mpolyn_struct **) flint_realloc(S->mpolyn_array, newalloc*sizeof(nmod_mpolyn_struct*)); } else { S->mpolyn_array = (nmod_mpolyn_struct **) flint_malloc( newalloc*sizeof(nmod_mpolyn_struct*)); } for (i = S->mpolyn_alloc; i < newalloc; i++) { S->mpolyn_array[i] = (nmod_mpolyn_struct *) flint_malloc( sizeof(nmod_mpolyn_struct)); nmod_mpolyn_init(S->mpolyn_array[i], S->bits, S->ctx); } S->mpolyn_alloc = newalloc; } return S->mpolyn_array + S->mpolyn_top; } flint-3.1.3/src/nmod_mpoly/sub.c000066400000000000000000000124351461254215100165410ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "mpoly.h" #include "nmod_mpoly.h" slong _nmod_mpoly_sub1(mp_limb_t * coeff1, ulong * exp1, const mp_limb_t * coeff2, const ulong * exp2, slong len2, const mp_limb_t * coeff3, const ulong * exp3, slong len3, ulong maskhi, nmod_t fctx) { slong i = 0, j = 0, k = 0; while (i < len2 && j < len3) { if ((exp2[i]^maskhi) > (exp3[j]^maskhi)) { exp1[k] = exp2[i]; coeff1[k] = coeff2[i]; i++; } else if ((exp2[i]^maskhi) == (exp3[j]^maskhi)) { exp1[k] = exp2[i]; coeff1[k] = nmod_sub(coeff2[i], coeff3[j], fctx); k -= (coeff1[k] == 0); i++; j++; } else { exp1[k] = exp3[j]; coeff1[k] = nmod_neg(coeff3[j], fctx); j++; } k++; } while (i < len2) { exp1[k] = exp2[i]; coeff1[k] = coeff2[i]; i++; k++; } while (j < len3) { exp1[k] = exp3[j]; coeff1[k] = nmod_neg(coeff3[j], fctx); j++; k++; } return k; } slong _nmod_mpoly_sub(ulong * coeff1, ulong * exp1, const ulong * coeff2, const ulong * exp2, slong len2, const ulong * coeff3, const ulong * exp3, slong len3, slong N, const ulong * cmpmask, nmod_t fctx) { slong i = 0, j = 0, k = 0; if (N == 1) return _nmod_mpoly_sub1(coeff1, exp1, coeff2, exp2, len2, coeff3, exp3, len3, cmpmask[0], fctx); while (i < len2 && j < len3) { int cmp = mpoly_monomial_cmp(exp2 + i*N, exp3 + j*N, N, cmpmask); if (cmp > 0) { mpoly_monomial_set(exp1 + k*N, exp2 + i*N, N); coeff1[k] = coeff2[i]; i++; } else if (cmp == 0) { mpoly_monomial_set(exp1 + k*N, exp2 + i*N, N); coeff1[k] = nmod_sub(coeff2[i], coeff3[j], fctx); k -= (coeff1[k] == 0); i++; j++; } else { mpoly_monomial_set(exp1 + k*N, exp3 + j*N, N); coeff1[k] = nmod_neg(coeff3[j], fctx); j++; } k++; } while (i < len2) { mpoly_monomial_set(exp1 + k*N, exp2 + i*N, N); coeff1[k] = coeff2[i]; i++; k++; } while (j < len3) { mpoly_monomial_set(exp1 + k*N, exp3 + j*N, N); coeff1[k] = nmod_neg(coeff3[j], fctx); j++; k++; } return k; } void nmod_mpoly_sub(nmod_mpoly_t poly1, const nmod_mpoly_t poly2, const nmod_mpoly_t poly3, const nmod_mpoly_ctx_t ctx) { slong len1 = 0, max_bits, N; ulong * exp2 = poly2->exps, * exp3 = poly3->exps; ulong * cmpmask; int free2 = 0, free3 = 0; TMP_INIT; max_bits = FLINT_MAX(poly2->bits, poly3->bits); N = mpoly_words_per_exp(max_bits, ctx->minfo); if (poly2->length == 0) { nmod_mpoly_neg(poly1, poly3, ctx); return; } else if (poly3->length == 0) { nmod_mpoly_set(poly1, poly2, ctx); return; } TMP_START; cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, max_bits, ctx->minfo); if (max_bits > poly2->bits) { free2 = 1; exp2 = (ulong *) flint_malloc(N*poly2->length*sizeof(ulong)); mpoly_repack_monomials(exp2, max_bits, poly2->exps, poly2->bits, poly2->length, ctx->minfo); } if (max_bits > poly3->bits) { free3 = 1; exp3 = (ulong *) flint_malloc(N*poly3->length*sizeof(ulong)); mpoly_repack_monomials(exp3, max_bits, poly3->exps, poly3->bits, poly3->length, ctx->minfo); } if (poly1 == poly2 || poly1 == poly3) { nmod_mpoly_t temp; nmod_mpoly_init3(temp, poly2->length + poly3->length, max_bits, ctx); len1 = _nmod_mpoly_sub(temp->coeffs, temp->exps, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, N, cmpmask, ctx->mod); nmod_mpoly_swap(temp, poly1, ctx); nmod_mpoly_clear(temp, ctx); } else { nmod_mpoly_fit_length_reset_bits(poly1, poly2->length + poly3->length, max_bits, ctx); len1 = _nmod_mpoly_sub(poly1->coeffs, poly1->exps, poly2->coeffs, exp2, poly2->length, poly3->coeffs, exp3, poly3->length, N, cmpmask, ctx->mod); } _nmod_mpoly_set_length(poly1, len1, ctx); if (free2) flint_free(exp2); if (free3) flint_free(exp3); TMP_END; } flint-3.1.3/src/nmod_mpoly/sub_ui.c000066400000000000000000000012701461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mpoly.h" void nmod_mpoly_sub_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx) { if (c >= ctx->mod.n) { NMOD_RED(c, c, ctx->mod); } nmod_mpoly_add_ui(A, B, nmod_neg(c, ctx->mod), ctx); } flint-3.1.3/src/nmod_mpoly/term_content.c000066400000000000000000000032651461254215100204520ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_term_content(nmod_mpoly_t M, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t Abits; fmpz * minAfields, * min_degs; TMP_INIT; if (A->length == 0) { nmod_mpoly_zero(M, ctx); return; } TMP_START; Abits = A->bits; /* get the field-wise minimum */ minAfields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_init(minAfields + i); mpoly_min_fields_fmpz(minAfields, A->exps, A->length, Abits, ctx->minfo); /* unpack to get the min exponents of each variable */ min_degs = (fmpz *) TMP_ALLOC(ctx->minfo->nvars*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_init(min_degs + i); mpoly_get_monomial_ffmpz_unpacked_ffmpz(min_degs, minAfields, ctx->minfo); nmod_mpoly_fit_length_reset_bits(M, 1, Abits, ctx); mpoly_set_monomial_ffmpz(M->exps, min_degs, Abits, ctx->minfo); M->coeffs[0] = 1; _nmod_mpoly_set_length(M, 1, ctx); for (i = 0; i < ctx->minfo->nfields; i++) fmpz_clear(minAfields + i); for (i = 0; i < ctx->minfo->nvars; i++) fmpz_clear(min_degs + i); TMP_END; } flint-3.1.3/src/nmod_mpoly/term_exp_fits.c000066400000000000000000000015301461254215100206120ustar00rootroot00000000000000/* Copyright (C) 2017 - 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly.h" int nmod_mpoly_term_exp_fits_ui(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_ui(A->exps, A->bits, i, ctx->minfo); } int nmod_mpoly_term_exp_fits_si(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx) { return A->bits <= FLINT_BITS ? 1 : mpoly_term_exp_fits_si(A->exps, A->bits, i, ctx->minfo); } flint-3.1.3/src/nmod_mpoly/test/000077500000000000000000000000001461254215100165565ustar00rootroot00000000000000flint-3.1.3/src/nmod_mpoly/test/main.c000066400000000000000000000115331461254215100176510ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub.c" #include "t-add_sub_ui.c" #include "t-cmp.c" #include "t-compose_nmod_mpoly.c" #include "t-compose_nmod_poly.c" #include "t-content_vars.c" #include "t-degree.c" #include "t-derivative.c" #include "t-div.c" #include "t-divides.c" #include "t-divides_dense.c" #include "t-divides_heap_threaded.c" #include "t-divides_monagan_pearce.c" #include "t-div_monagan_pearce.c" #include "t-divrem.c" #include "t-divrem_ideal.c" #include "t-divrem_ideal_monagan_pearce.c" #include "t-divrem_monagan_pearce.c" #include "t-evaluate.c" #include "t-gcd_brown.c" #include "t-gcd.c" #include "t-gcd_cofactors.c" #include "t-gcd_hensel.c" #include "t-gcd_zippel2.c" #include "t-gcd_zippel.c" #include "t-gen.c" #include "t-get_coeff_vars_ui.c" #include "t-get_set_string_pretty.c" #include "t-get_set_term_coeff_ui.c" #include "t-get_set_term_exp_si.c" #include "t-get_set_term_exp_ui.c" #include "t-get_term.c" #include "t-get_term_monomial.c" #include "t-inflate_deflate.c" #include "t-mpolyn_divides_threaded_pool.c" #include "t-mpolyuu_divides.c" #include "t-mul_array.c" #include "t-mul_array_threaded.c" #include "t-mul.c" #include "t-mul_dense.c" #include "t-mul_heap_threaded.c" #include "t-mul_johnson.c" #include "t-pow_rmul.c" #include "t-pow_ui.c" #include "t-push_term_ui_fmpz.c" #include "t-push_term_ui_ui.c" #include "t-quadratic_root.c" #include "t-repack_bits.c" #include "t-resize.c" #include "t-resultant_discriminant.c" #include "t-scalar_addmul_ui.c" #include "t-scalar_mul_ui.c" #include "t-sqrt.c" #include "t-term_content.c" #include "t-total_degree.c" #include "t-univar.c" #include "t-univar_resultant.c" #include "t-used_vars.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_mpoly_add_sub), TEST_FUNCTION(nmod_mpoly_add_sub_ui), TEST_FUNCTION(nmod_mpoly_cmp), TEST_FUNCTION(nmod_mpoly_compose_nmod_mpoly), TEST_FUNCTION(nmod_mpoly_compose_nmod_poly), TEST_FUNCTION(nmod_mpoly_content_vars), TEST_FUNCTION(nmod_mpoly_degree), TEST_FUNCTION(nmod_mpoly_derivative), TEST_FUNCTION(nmod_mpoly_div), TEST_FUNCTION(nmod_mpoly_divides), TEST_FUNCTION(nmod_mpoly_divides_dense), TEST_FUNCTION(nmod_mpoly_divides_heap_threaded), TEST_FUNCTION(nmod_mpoly_divides_monagan_pearce), TEST_FUNCTION(nmod_mpoly_div_monagan_pearce), TEST_FUNCTION(nmod_mpoly_divrem), TEST_FUNCTION(nmod_mpoly_divrem_ideal), TEST_FUNCTION(nmod_mpoly_divrem_ideal_monagan_pearce), TEST_FUNCTION(nmod_mpoly_divrem_monagan_pearce), TEST_FUNCTION(nmod_mpoly_evaluate), TEST_FUNCTION(nmod_mpoly_gcd_brown), TEST_FUNCTION(nmod_mpoly_gcd), TEST_FUNCTION(nmod_mpoly_gcd_cofactors), TEST_FUNCTION(nmod_mpoly_gcd_hensel), TEST_FUNCTION(nmod_mpoly_gcd_zippel2), TEST_FUNCTION(nmod_mpoly_gcd_zippel), TEST_FUNCTION(nmod_mpoly_gen), TEST_FUNCTION(nmod_mpoly_get_coeff_vars_ui), TEST_FUNCTION(nmod_mpoly_get_set_string_pretty), TEST_FUNCTION(nmod_mpoly_get_set_term_coeff_ui), TEST_FUNCTION(nmod_mpoly_get_set_term_exp_si), TEST_FUNCTION(nmod_mpoly_get_set_term_exp_ui), TEST_FUNCTION(nmod_mpoly_get_term), TEST_FUNCTION(nmod_mpoly_get_term_monomial), TEST_FUNCTION(nmod_mpoly_inflate_deflate), TEST_FUNCTION(nmod_mpolyn_divides_threaded_pool), TEST_FUNCTION(nmod_mpoly_mpolyuu_divides), TEST_FUNCTION(nmod_mpoly_mul_array), TEST_FUNCTION(nmod_mpoly_mul_array_threaded), TEST_FUNCTION(nmod_mpoly_mul), TEST_FUNCTION(nmod_mpoly_mul_dense), TEST_FUNCTION(nmod_mpoly_mul_heap_threaded), TEST_FUNCTION(nmod_mpoly_mul_johnson), TEST_FUNCTION(nmod_mpoly_pow_rmul), TEST_FUNCTION(nmod_mpoly_pow_ui), TEST_FUNCTION(nmod_mpoly_push_term_ui_fmpz), TEST_FUNCTION(nmod_mpoly_push_term_ui_ui), TEST_FUNCTION(nmod_mpoly_quadratic_root), TEST_FUNCTION(nmod_mpoly_repack_bits), TEST_FUNCTION(nmod_mpoly_resize), TEST_FUNCTION(nmod_mpoly_resultant_discriminant), TEST_FUNCTION(nmod_mpoly_scalar_addmul_ui), TEST_FUNCTION(nmod_mpoly_scalar_mul_ui), TEST_FUNCTION(nmod_mpoly_sqrt), TEST_FUNCTION(nmod_mpoly_term_content), TEST_FUNCTION(nmod_mpoly_total_degree), TEST_FUNCTION(nmod_mpoly_univar), TEST_FUNCTION(nmod_mpoly_univar_resultant), TEST_FUNCTION(nmod_mpoly_used_vars) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod_mpoly/test/t-add_sub.c000066400000000000000000000322641461254215100205730ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_add_sub, state) { int i, j, result; /* Check (f + g) - g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_add(h, g, f, ctx); nmod_mpoly_sub(k, h, g, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + g) - g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f + g = g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_add(h, f, g, ctx); nmod_mpoly_add(k, g, f, ctx); result = nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + g = g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f - g = -g + f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_sub(h, f, g, ctx); nmod_mpoly_neg(k, g, ctx); nmod_mpoly_add(k, k, f, ctx); result = nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f - g = -g + f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f + (g + h) = (f + g) + h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k1, k2; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); nmod_mpoly_add(k1, f, g, ctx); nmod_mpoly_add(k1, k1, h, ctx); nmod_mpoly_add(k2, g, h, ctx); nmod_mpoly_add(k2, k2, f, ctx); result = nmod_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f + (g + h) = (f + g) + h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f - (g + h) = (f - g) - h */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k1, k2; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); nmod_mpoly_add(k1, g, h, ctx); nmod_mpoly_sub(k1, f, k1, ctx); nmod_mpoly_sub(k2, f, g, ctx); nmod_mpoly_sub(k2, k2, h, ctx); result = nmod_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f - (g + h) = (f - g) - h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first arg */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_set(h, f, ctx); nmod_mpoly_add(f, f, g, ctx); nmod_mpoly_assert_canonical(f, ctx); nmod_mpoly_sub(f, f, g, ctx); nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second arg */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); if ((j % 2) == 0) { nmod_mpoly_add(h, g, f, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_add(f, g, f, ctx); nmod_mpoly_assert_canonical(f, ctx); } else { nmod_mpoly_sub(h, g, f, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_sub(f, g, f, ctx); nmod_mpoly_assert_canonical(f, ctx); } result = nmod_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-add_sub_ui.c000066400000000000000000000073561461254215100212740ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_add_sub_ui, state) { int i, j, result; /* Check (f + c) - c = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; mp_limb_t modulus; ulong c; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); c = n_randtest(state); nmod_mpoly_add_ui(g, f, c, ctx); nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_sub_ui(h, g, c, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f + c) - c = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g; mp_limb_t modulus; ulong c; slong len1, len2; slong exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_set(g, f, ctx); c = n_randtest(state); nmod_mpoly_add_ui(f, f, c, ctx); nmod_mpoly_assert_canonical(f, ctx); nmod_mpoly_sub_ui(f, f, c, ctx); nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-cmp.c000066400000000000000000000134331461254215100177460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpoly.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_cmp, state) { int result; slong i, j1, j2; /* check polynomial terms are in order */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, mf, mg; slong len; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = UWORD(1) + n_randint(state, -UWORD(1)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(mf, ctx); nmod_mpoly_init(mg, ctx); len = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits = n_randint(state, exp_bits) + 2; nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); nmod_mpoly_repack_bits(g, f, f->bits + n_randint(state, FLINT_BITS), ctx); nmod_mpoly_assert_canonical(f, ctx); nmod_mpoly_assert_canonical(g, ctx); for (j1 = 0; j1 < f->length; j1++) for (j2 = 0; j2 < g->length; j2++) { nmod_mpoly_get_term_monomial(mf, f, j1, ctx); nmod_mpoly_get_term_monomial(mg, g, j2, ctx); result = nmod_mpoly_cmp(mf, mg, ctx); result = (result == 0 && j1 == j2) || (result == +1 && j1 < j2) || (result == -1 && j1 > j2); if (!result) { flint_printf("FAIL\n" "check polynomial terms are in order\n" "i = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(mf, ctx); nmod_mpoly_clear(mg, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, c, aa, bb, cc; int a_a, a_b, a_c, a_aa, a_bb, a_cc; int b_a, b_b, b_c, b_aa, b_bb, b_cc; int c_a, c_b, c_c, c_aa, c_bb, c_cc; flint_bitcnt_t newbits; mp_limb_t modulus; modulus = UWORD(1) + n_randint(state, -UWORD(1)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(c, ctx); nmod_mpoly_init(aa, ctx); nmod_mpoly_init(bb, ctx); nmod_mpoly_init(cc, ctx); nmod_mpoly_randtest_bits(a, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); nmod_mpoly_randtest_bits(b, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); nmod_mpoly_randtest_bits(c, state, n_randint(state, 100) + 1, n_randint(state, 200) + 2, ctx); newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(aa, a, newbits, ctx); newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(bb, b, newbits, ctx); newbits = c->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(cc, c, newbits, ctx); a_a = nmod_mpoly_cmp(a, a, ctx); a_b = nmod_mpoly_cmp(a, b, ctx); a_c = nmod_mpoly_cmp(a, c, ctx); a_aa = nmod_mpoly_cmp(a, aa, ctx); a_bb = nmod_mpoly_cmp(a, bb, ctx); a_cc = nmod_mpoly_cmp(a, cc, ctx); b_a = nmod_mpoly_cmp(b, a, ctx); b_b = nmod_mpoly_cmp(b, b, ctx); b_c = nmod_mpoly_cmp(b, c, ctx); b_aa = nmod_mpoly_cmp(b, aa, ctx); b_bb = nmod_mpoly_cmp(b, bb, ctx); b_cc = nmod_mpoly_cmp(b, cc, ctx); c_a = nmod_mpoly_cmp(c, a, ctx); c_b = nmod_mpoly_cmp(c, b, ctx); c_c = nmod_mpoly_cmp(c, c, ctx); c_aa = nmod_mpoly_cmp(c, aa, ctx); c_bb = nmod_mpoly_cmp(c, bb, ctx); c_cc = nmod_mpoly_cmp(c, cc, ctx); if (a_a != 0 || a_aa != 0 || b_b != 0 || b_bb != 0 || c_c != 0 || c_cc != 0) { flint_printf("FAIL\n" "check polynomial compares equal to itself\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if (a_b != a_bb || a_c != a_cc || b_a != b_aa || b_c != b_cc || c_a != c_aa || c_b != c_bb) { flint_printf("FAIL\n" "check polynomial comparison with differing bits\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } if ((a_b*b_c == 0 && a_c != a_b + b_c) || (a_b*b_c > 0 && a_c != a_b)) { flint_printf("FAIL\n" "check transitivity\n" "i = %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(c, ctx); nmod_mpoly_clear(aa, ctx); nmod_mpoly_clear(bb, ctx); nmod_mpoly_clear(cc, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-compose_nmod_mpoly.c000066400000000000000000000352341461254215100230740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_compose_nmod_mpoly, state) { slong i, j, v; { nmod_mpoly_t A, A1, A2, B; nmod_mpoly_struct * Cp[3]; nmod_mpoly_struct C[3]; nmod_mpoly_ctx_t ctxAC, ctxB; nmod_mpoly_ctx_init(ctxB, 3, ORD_LEX, 13); nmod_mpoly_ctx_init(ctxAC, 2, ORD_LEX, 13); nmod_mpoly_init(B, ctxB); nmod_mpoly_init(A, ctxAC); nmod_mpoly_init(A1, ctxAC); nmod_mpoly_init(A2, ctxAC); for (i = 0; i < 3; i++) { Cp[i] = C + i; nmod_mpoly_init(C + i, ctxAC); } nmod_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB); nmod_mpoly_set_str_pretty(C + 0, "x1 + x2", NULL, ctxAC); nmod_mpoly_set_str_pretty(C + 1, "x1 - x2", NULL, ctxAC); nmod_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (nmod_mpoly_compose_nmod_mpoly(A, B, Cp, ctxB, ctxAC) || nmod_mpoly_compose_nmod_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || nmod_mpoly_compose_nmod_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_set_str_pretty(C + 0, "x1", NULL, ctxAC); nmod_mpoly_set_str_pretty(C + 1, "2*x2", NULL, ctxAC); nmod_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (!nmod_mpoly_compose_nmod_mpoly(A, B, Cp, ctxB, ctxAC) || !nmod_mpoly_compose_nmod_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || !nmod_mpoly_compose_nmod_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check non-example 2\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_set_str_pretty(C + 0, "2*x1", NULL, ctxAC); nmod_mpoly_set_str_pretty(C + 1, "x2", NULL, ctxAC); nmod_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC); if (!nmod_mpoly_compose_nmod_mpoly(A, B, Cp, ctxB, ctxAC) || !nmod_mpoly_compose_nmod_mpoly_horner(A1, B, Cp, ctxB, ctxAC) || !nmod_mpoly_compose_nmod_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check example 3\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(B, ctxB); nmod_mpoly_clear(A, ctxAC); nmod_mpoly_clear(A1, ctxAC); nmod_mpoly_clear(A2, ctxAC); for (i = 0; i < 3; i++) nmod_mpoly_clear(C + i, ctxAC); nmod_mpoly_ctx_clear(ctxB); nmod_mpoly_ctx_clear(ctxAC); } /* check composition with generators */ for (i = 0; i < 10*flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctxB, ctxAC; nmod_mpoly_t B, A, A1, A2, A3; nmod_mpoly_struct ** C; slong * c; slong nvarsB, nvarsAC; slong len; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctxB, state, 20, modulus); nmod_mpoly_ctx_init_rand(ctxAC, state, 20, modulus); nvarsB = ctxB->minfo->nvars; nvarsAC = ctxAC->minfo->nvars; nmod_mpoly_init(B, ctxB); nmod_mpoly_init(A, ctxAC); nmod_mpoly_init(A1, ctxAC); nmod_mpoly_init(A2, ctxAC); nmod_mpoly_init(A3, ctxAC); c = (slong *) flint_malloc(nvarsB*sizeof(slong)); C = (nmod_mpoly_struct **) flint_malloc(nvarsB * sizeof(nmod_mpoly_struct *)); for (v = 0; v < nvarsB; v++) { C[v] = (nmod_mpoly_struct *) flint_malloc(sizeof(nmod_mpoly_struct)); nmod_mpoly_init(C[v], ctxAC); } for (j = 0; j < 4; j++) { len = n_randint(state, 200); exp_bits = n_randint(state, 100) + 1; for (v = 0; v < nvarsB; v++) { c[v] = n_randint(state, nvarsAC + 2) - 2; if (c[v] >= 0) nmod_mpoly_gen(C[v], c[v], ctxAC); else nmod_mpoly_zero(C[v], ctxAC); } nmod_mpoly_randtest_bits(B, state, len, exp_bits, ctxB); nmod_mpoly_compose_nmod_mpoly_gen(A, B, c, ctxB, ctxAC); if (!nmod_mpoly_compose_nmod_mpoly(A1, B, C, ctxB, ctxAC) || !nmod_mpoly_compose_nmod_mpoly_horner(A2, B, C, ctxB, ctxAC) || !nmod_mpoly_compose_nmod_mpoly_geobucket(A3, B, C, ctxB, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition success with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } if (!nmod_mpoly_equal(A, A1, ctxAC) || !nmod_mpoly_equal(A, A2, ctxAC) || !nmod_mpoly_equal(A, A3, ctxAC)) { printf("FAIL\n"); flint_printf("Check composition with generators\n" "i: %wd, j: %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(A, ctxAC); nmod_mpoly_assert_canonical(A1, ctxAC); nmod_mpoly_assert_canonical(A2, ctxAC); nmod_mpoly_assert_canonical(A3, ctxAC); } for (v = 0; v < nvarsB; v++) { nmod_mpoly_clear(C[v], ctxAC); flint_free(C[v]); } flint_free(C); flint_free(c); nmod_mpoly_clear(B, ctxB); nmod_mpoly_clear(A, ctxAC); nmod_mpoly_clear(A1, ctxAC); nmod_mpoly_clear(A2, ctxAC); nmod_mpoly_clear(A3, ctxAC); nmod_mpoly_ctx_clear(ctxB); nmod_mpoly_ctx_clear(ctxAC); } /* Check composition with identity */ for (i = 0; i < 10*flint_test_multiplier(); i++) { slong nvars, len, exp_bits; nmod_mpoly_struct ** vals1; nmod_mpoly_t f, g, g1, g2; nmod_mpoly_ctx_t ctx; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; vals1 = (nmod_mpoly_struct **) flint_malloc(nvars*sizeof(nmod_mpoly_struct *)); for (v = 0; v < nvars; v++) { vals1[v] = (nmod_mpoly_struct *) flint_malloc(sizeof(nmod_mpoly_struct)); nmod_mpoly_init(vals1[v], ctx); nmod_mpoly_gen(vals1[v], v, ctx); } nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(g1, ctx); nmod_mpoly_init(g2, ctx); len = n_randint(state, 200); exp_bits = n_randint(state, 300) + 1; nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (!nmod_mpoly_compose_nmod_mpoly(g, f, vals1, ctx, ctx) || !nmod_mpoly_compose_nmod_mpoly_horner(g1, f, vals1, ctx, ctx) || !nmod_mpoly_compose_nmod_mpoly_geobucket(g2, f, vals1, ctx, ctx) || !nmod_mpoly_equal(g, g1, ctx) || !nmod_mpoly_equal(g, g2, ctx)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_assert_canonical(g1, ctx); nmod_mpoly_assert_canonical(g2, ctx); if (!nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check composition with identity\ni: %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(g1, ctx); nmod_mpoly_clear(g2, ctx); for (v = 0; v < nvars; v++) { nmod_mpoly_clear(vals1[v], ctx); flint_free(vals1[v]); } flint_free(vals1); nmod_mpoly_ctx_clear(ctx); } /* Check composition and evalall commute */ for (i = 0; i < 40*flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx1, ctx2; nmod_mpoly_t f, g, g1, g2; nmod_mpoly_struct ** vals1; mp_limb_t fe, ge; mp_limb_t * vals2, * vals3; slong nvars1, nvars2; slong len1, len2; slong exp_bound1; flint_bitcnt_t exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx1, state, 4, modulus); nmod_mpoly_ctx_init_rand(ctx2, state, 8, modulus); nvars1 = ctx1->minfo->nvars; nvars2 = ctx2->minfo->nvars; nmod_mpoly_init(f, ctx1); nmod_mpoly_init(g, ctx2); nmod_mpoly_init(g1, ctx2); nmod_mpoly_init(g2, ctx2); len1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars1) + 1); len2 = n_randint(state, 10/FLINT_MAX(WORD(1), nvars2) + 2); exp_bound1 = n_randint(state, 12/FLINT_MAX(WORD(1), nvars1) + 1) + 2; exp_bits2 = n_randint(state, 200) + 1; nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx1); vals1 = (nmod_mpoly_struct **) flint_malloc(nvars1 * sizeof(nmod_mpoly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (nmod_mpoly_struct *) flint_malloc( sizeof(nmod_mpoly_struct)); nmod_mpoly_init(vals1[v], ctx2); nmod_mpoly_randtest_bound(vals1[v], state, len2, exp_bits2, ctx2); } vals2 = (mp_limb_t *) flint_malloc(nvars2*sizeof(mp_limb_t)); for (v = 0; v < nvars2; v++) { vals2[v] = n_randlimb(state); } vals3 = (mp_limb_t *) flint_malloc(nvars1*sizeof(mp_limb_t)); for (v = 0; v < nvars1; v++) { vals3[v] = nmod_mpoly_evaluate_all_ui(vals1[v], vals2, ctx2); } if (!nmod_mpoly_compose_nmod_mpoly(g, f, vals1, ctx1, ctx2) || !nmod_mpoly_compose_nmod_mpoly_horner(g1, f, vals1, ctx1, ctx2) || !nmod_mpoly_compose_nmod_mpoly_geobucket(g2, f, vals1, ctx1, ctx2) || !nmod_mpoly_equal(g, g1, ctx2) || !nmod_mpoly_equal(g, g2, ctx2)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx2); nmod_mpoly_assert_canonical(g1, ctx2); nmod_mpoly_assert_canonical(g2, ctx2); fe = nmod_mpoly_evaluate_all_ui(f, vals3, ctx1); ge = nmod_mpoly_evaluate_all_ui(g, vals2, ctx2); if (fe != ge) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } for (v = 0; v < nvars1; v++) { nmod_mpoly_clear(vals1[v], ctx2); flint_free(vals1[v]); } flint_free(vals1); flint_free(vals2); flint_free(vals3); nmod_mpoly_clear(f, ctx1); nmod_mpoly_clear(g, ctx2); nmod_mpoly_clear(g1, ctx2); nmod_mpoly_clear(g2, ctx2); nmod_mpoly_ctx_clear(ctx1); nmod_mpoly_ctx_clear(ctx2); } /* Check composition with constants matches evalall */ for (i = 0; i < 10*flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx1, ctx2; nmod_mpoly_t f, g, g1, g2; nmod_mpoly_struct ** vals1; mp_limb_t * vals2; slong nvars1; slong len1; flint_bitcnt_t exp_bits1; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx1, state, 20, modulus); nmod_mpoly_ctx_init_rand(ctx2, state, 10, modulus); nvars1 = ctx1->minfo->nvars; nmod_mpoly_init(f, ctx1); nmod_mpoly_init(g, ctx2); nmod_mpoly_init(g1, ctx2); nmod_mpoly_init(g2, ctx2); len1 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 1; nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx1); vals1 = (nmod_mpoly_struct **) flint_malloc(nvars1 * sizeof(nmod_mpoly_struct *)); vals2 = (mp_limb_t *) flint_malloc(nvars1*sizeof(mp_limb_t)); for (v = 0; v < nvars1; v++) { vals1[v] = (nmod_mpoly_struct *) flint_malloc( sizeof(nmod_mpoly_struct)); nmod_mpoly_init(vals1[v], ctx2); vals2[v] = n_randlimb(state); nmod_mpoly_set_ui(vals1[v], vals2[v], ctx2); } if (!nmod_mpoly_compose_nmod_mpoly(g, f, vals1, ctx1, ctx2) || !nmod_mpoly_compose_nmod_mpoly_geobucket(g1, f, vals1, ctx1, ctx2) || !nmod_mpoly_compose_nmod_mpoly_horner(g2, f, vals1, ctx1, ctx2)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx2); nmod_mpoly_assert_canonical(g1, ctx2); nmod_mpoly_assert_canonical(g2, ctx2); if (!nmod_mpoly_is_ui(g, ctx2) || nmod_mpoly_get_ui(g, ctx2) != nmod_mpoly_evaluate_all_ui(f, vals2, ctx1)) { printf("FAIL\n"); flint_printf("Check composition with constants matches evalall\ni: %wd\n", i); fflush(stdout); flint_abort(); } for (v = 0; v < nvars1; v++) { nmod_mpoly_clear(vals1[v], ctx2); flint_free(vals1[v]); } flint_free(vals1); flint_free(vals2); nmod_mpoly_clear(f, ctx1); nmod_mpoly_clear(g, ctx2); nmod_mpoly_clear(g1, ctx2); nmod_mpoly_clear(g2, ctx2); nmod_mpoly_ctx_clear(ctx1); nmod_mpoly_ctx_clear(ctx2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-compose_nmod_poly.c000066400000000000000000000115131461254215100227110ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_compose_nmod_poly, state) { slong i, v; { nmod_poly_t A; nmod_mpoly_t B; nmod_poly_struct * Cp[3]; nmod_poly_struct C[3]; nmod_mpoly_ctx_t ctxB; nmod_mpoly_ctx_init(ctxB, 3, ORD_LEX, 13); nmod_mpoly_init(B, ctxB); nmod_poly_init_mod(A, ctxB->mod); for (i = 0; i < 3; i++) { Cp[i] = C + i; nmod_poly_init_mod(C + i, ctxB->mod); } nmod_mpoly_set_str_pretty(B, "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB); nmod_poly_zero(C + 0); nmod_poly_zero(C + 1); nmod_poly_zero(C + 2); nmod_poly_set_coeff_ui(C + 0, 1, 1); nmod_poly_set_coeff_ui(C + 1, 2, 2); nmod_poly_set_coeff_ui(C + 2, 3, 3); if (nmod_mpoly_compose_nmod_poly(A, B, Cp, ctxB)) { printf("FAIL\n"); flint_printf("Check non-example 1\n", i); fflush(stdout); flint_abort(); } nmod_poly_zero(C + 0); nmod_poly_zero(C + 1); nmod_poly_zero(C + 2); nmod_poly_set_coeff_ui(C + 0, 0, 1); nmod_poly_set_coeff_ui(C + 1, 0, 2); nmod_poly_set_coeff_ui(C + 2, 0, 3); if (!nmod_mpoly_compose_nmod_poly(A, B, Cp, ctxB)) { printf("FAIL\n"); flint_printf("Check example 2\n", i); fflush(stdout); flint_abort(); } if (!nmod_poly_is_zero(A)) { printf("FAIL\n"); flint_printf("Check example 2 equality\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(B, ctxB); nmod_poly_clear(A); for (i = 0; i < 3; i++) nmod_poly_clear(C + i); nmod_mpoly_ctx_clear(ctxB); } /* Check composition and evalall commute */ for (i = 0; i < 50*flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx1; nmod_mpoly_t f; nmod_poly_t g; nmod_poly_struct ** vals1; mp_limb_t fe, ge; mp_limb_t vals2, * vals3; slong nvars1; slong len1, len2; slong exp_bound1; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx1, state, 3, modulus); nvars1 = ctx1->minfo->nvars; nmod_mpoly_init(f, ctx1); nmod_poly_init(g, modulus); len1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars1) + 1); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 200/FLINT_MAX(WORD(1), nvars1) + 2) + 1; nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx1); vals1 = (nmod_poly_struct **) flint_malloc(nvars1 * sizeof(nmod_poly_struct *)); for (v = 0; v < nvars1; v++) { vals1[v] = (nmod_poly_struct *) flint_malloc( sizeof(nmod_poly_struct)); nmod_poly_init(vals1[v], modulus); nmod_poly_randtest(vals1[v], state, len2); } vals2 = n_randint(state, modulus); vals3 = (mp_limb_t *) flint_malloc(nvars1*sizeof(mp_limb_t)); for (v = 0; v < nvars1; v++) { vals3[v] = nmod_poly_evaluate_nmod(vals1[v], vals2); } if (nmod_mpoly_total_degree_si(f, ctx1) < 100) { if (!nmod_mpoly_compose_nmod_poly(g, f, vals1, ctx1)) { printf("FAIL\n"); flint_printf("Check composition success\ni: %wd\n", i); fflush(stdout); flint_abort(); } fe = nmod_mpoly_evaluate_all_ui(f, vals3, ctx1); ge = nmod_poly_evaluate_nmod(g, vals2); if (fe != ge) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); fflush(stdout); flint_abort(); } } for (v = 0; v < nvars1; v++) { nmod_poly_clear(vals1[v]); flint_free(vals1[v]); } flint_free(vals1); flint_free(vals3); nmod_mpoly_clear(f, ctx1); nmod_poly_clear(g); nmod_mpoly_ctx_clear(ctx1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-content_vars.c000066400000000000000000000116241461254215100216740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_content_vars, state) { slong i, j; /* check simple example */ { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g; slong varl[2] = {0, 1}; const char * vars[4] = {"x", "y", "z", "w"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, 11); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(f, "x*y*(z+w)*(x*z+y*w+1+z*w)", vars, ctx); nmod_mpoly_set_str_pretty(g, "z+w", vars, ctx); nmod_mpoly_content_vars(f, f, varl, 2, ctx); if (!nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check simple example\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, t; slong nvars, num_vars, len; ulong * exp_bounds; slong * vars; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nvars = ctx->minfo->nvars; if (nvars < 1) { nmod_mpoly_ctx_clear(ctx); continue; } nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(t, ctx); exp_bounds = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (j = 0; j < nvars; j++) exp_bounds[j] = 1 + n_randint(state, 5); len = n_randint(state, 20); nmod_mpoly_randtest_bounds(f, state, len, exp_bounds, ctx); vars = (slong *) flint_malloc(nvars*sizeof(slong)); for (j = 0; j < nvars; j++) vars[j] = j; for (j = 0; j < 2*nvars; j++) { slong k1 = n_randint(state, nvars); slong k2 = n_randint(state, nvars); FLINT_SWAP(slong, vars[k1], vars[k2]); } num_vars = 1 + n_randint(state, nvars); for (j = 0; j < num_vars; j++) exp_bounds[vars[j]] = 1; len = n_randint(state, 10); nmod_mpoly_randtest_bounds(t, state, len, exp_bounds, ctx); nmod_mpoly_mul(f, f, t, ctx); nmod_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); if (!nmod_mpoly_content_vars(g, f, vars, num_vars, ctx)) { flint_printf("FAIL: check content could be computed\n"); fflush(stdout); flint_abort(); } if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(f, ctx)) { flint_printf("FAIL: check zero content\n"); fflush(stdout); flint_abort(); } } else { for (j = 0; j < num_vars; j++) { if (nmod_mpoly_degree_si(g, vars[j], ctx) != 0) { flint_printf("FAIL: content depends on a bad variable\n"); fflush(stdout); flint_abort(); } } if (!nmod_mpoly_divides(t, f, g, ctx)) { flint_printf("FAIL: check content divides\n"); fflush(stdout); flint_abort(); } if (!nmod_mpoly_content_vars(t, t, vars, num_vars, ctx)) { flint_printf("FAIL: check cofactor content could be computed\n"); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_one(t, ctx)) { flint_printf("FAIL: check cofactor content is one\n"); fflush(stdout); flint_abort(); } } if (!nmod_mpoly_content_vars(f, f, vars, num_vars, ctx)) { flint_printf("FAIL: check aliased content could be computed\n"); fflush(stdout); flint_abort(); } if (!nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check aliasing\n"); fflush(stdout); flint_abort(); } flint_free(exp_bounds); flint_free(vars); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-degree.c000066400000000000000000000110741461254215100204210ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_degree, state) { int i, j; /* Check degree does not go up under addition */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randbits(state, n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < ctx->minfo->nvars; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_add(h, f, g, ctx); nmod_mpoly_degree_fmpz(hdeg, h, j, ctx); nmod_mpoly_degree_fmpz(fdeg, f, j, ctx); nmod_mpoly_degree_fmpz(gdeg, g, j, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check degree adds under multiplication */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { int ok; nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randbits(state, n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < ctx->minfo->nvars; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_degree_fmpz(hdeg, h, j, ctx); nmod_mpoly_degree_fmpz(fdeg, f, j, ctx); nmod_mpoly_degree_fmpz(gdeg, g, j, ctx); if (nmod_mpoly_is_zero(f, ctx) || nmod_mpoly_is_zero(g, ctx)) { ok = fmpz_equal_si(hdeg, -WORD(1)) && (fmpz_equal_si(fdeg, -WORD(1)) || fmpz_equal_si(gdeg, -WORD(1))); } else { fmpz_add(gdeg, gdeg, fdeg); if (n_is_prime(nmod_mpoly_ctx_modulus(ctx))) { ok = fmpz_equal(hdeg, gdeg); } else { ok = fmpz_cmp(hdeg, gdeg) <= 0; } } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-derivative.c000066400000000000000000000145251461254215100213340ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_derivative, state) { int i, j, result; slong tmul = 5; /* Check d(f*g) = df*g + f*dg */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, fp, gp, hp, t1, t2; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; slong idx; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); if (ctx->minfo->nvars < 1) { nmod_mpoly_ctx_clear(ctx); continue; } nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(fp, ctx); nmod_mpoly_init(gp, ctx); nmod_mpoly_init(hp, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; nmod_mpoly_randtest_bits(hp, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(fp, state, len, exp_bits1, ctx); nmod_mpoly_randtest_bits(gp, state, len, exp_bits2, ctx); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); idx = n_randint(state, ctx->minfo->nvars); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_derivative(hp, h, idx, ctx); nmod_mpoly_assert_canonical(hp, ctx); nmod_mpoly_derivative(fp, f, idx, ctx); nmod_mpoly_assert_canonical(fp, ctx); nmod_mpoly_derivative(gp, g, idx, ctx); nmod_mpoly_assert_canonical(gp, ctx); nmod_mpoly_mul_johnson(t1, f, gp, ctx); nmod_mpoly_assert_canonical(t1, ctx); nmod_mpoly_mul_johnson(t2, g, fp, ctx); nmod_mpoly_assert_canonical(t2, ctx); nmod_mpoly_add(t1, t1, t2, ctx); nmod_mpoly_assert_canonical(t1, ctx); result = nmod_mpoly_equal(hp, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(fp, ctx); nmod_mpoly_clear(gp, ctx); nmod_mpoly_clear(hp, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check d(f*g) = df*g + f*dg with aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, fp, gp, t1, t2; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; slong idx; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); if (ctx->minfo->nvars < 1) { nmod_mpoly_ctx_clear(ctx); continue; } nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(fp, ctx); nmod_mpoly_init(gp, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(fp, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(gp, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); idx = n_randint(state, ctx->minfo->nvars); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_derivative(h, h, idx, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_set(fp, f, ctx); nmod_mpoly_derivative(fp, fp, idx, ctx); nmod_mpoly_assert_canonical(fp, ctx); nmod_mpoly_set(gp, g, ctx); nmod_mpoly_derivative(gp, gp, idx, ctx); nmod_mpoly_assert_canonical(gp, ctx); nmod_mpoly_mul_johnson(t1, f, gp, ctx); nmod_mpoly_assert_canonical(t1, ctx); nmod_mpoly_mul_johnson(t2, g, fp, ctx); nmod_mpoly_assert_canonical(t2, ctx); nmod_mpoly_add(t1, t1, t2, ctx); nmod_mpoly_assert_canonical(t1, ctx); result = nmod_mpoly_equal(h, t1, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check d(f*g) = df*g + f*dg with aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(fp, ctx); nmod_mpoly_clear(gp, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-div.c000066400000000000000000000220041461254215100177430ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_div, state) { slong i, j, tmul = 10; { nmod_mpoly_t f, g, p, q; nmod_mpoly_ctx_t ctx; const char * vars[] = {"x", "y", "z", "t", "u"}; nmod_mpoly_ctx_init(ctx, 5, ORD_LEX, 1000003); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(p, ctx); nmod_mpoly_init(q, ctx); nmod_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)^6", vars, ctx); nmod_mpoly_set_str_pretty(g, "(1+u+t+2*z^2+3*y^3+5*x^5)^6", vars, ctx); nmod_mpoly_mul(p, f, g, ctx); nmod_mpoly_assert_canonical(p, ctx); nmod_mpoly_div(q, p, f, ctx); nmod_mpoly_assert_canonical(q, ctx); if (!nmod_mpoly_equal(q, g, ctx)) { printf("FAIL\n"); flint_printf("Check example\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_clear(q, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f */ for (i = 0; i < 10 * tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, l; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(l, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(l, state, len, exp_bits, ctx); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_div(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); if (!nmod_mpoly_equal(k, f, ctx)) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_set(l, h, ctx); nmod_mpoly_div(l, l, g, ctx); nmod_mpoly_assert_canonical(l, ctx); if (!nmod_mpoly_equal(l, f, ctx)) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing dividend\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_div(g, h, g, ctx); nmod_mpoly_assert_canonical(g, ctx); if (!nmod_mpoly_equal(g, f, ctx)) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing divisor\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(l, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check div matches divrem for random polys */ for (i = 0; i < 5 * tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, q, r, k; mp_limb_t modulus; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; fmpz * shifts, * strides; slong n, nvars; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(q, ctx); nmod_mpoly_init(r, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), nvars); max_bound = 1 + 400/n/n; exp_bound = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); for (j = 0; j < nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(q, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(r, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); nmod_mpoly_inflate(f, f, shifts, strides, ctx); nmod_mpoly_inflate(g, g, shifts, strides, ctx); nmod_mpoly_divrem(q, r, f, g, ctx); nmod_mpoly_assert_canonical(q, ctx); nmod_mpoly_assert_canonical(r, ctx); nmod_mpoly_remainder_strongtest(r, g, ctx); nmod_mpoly_mul(k, q, g, ctx); nmod_mpoly_add(k, k, r, ctx); nmod_mpoly_assert_canonical(k, ctx); if (!nmod_mpoly_equal(f, k, ctx)) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_div(k, f, g, ctx); nmod_mpoly_assert_canonical(k, ctx); if (!nmod_mpoly_equal(k, q, ctx)) { printf("FAIL\n"); flint_printf("Check div matches divrem\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_set(k, f, ctx); nmod_mpoly_div(k, k, g, ctx); nmod_mpoly_assert_canonical(k, ctx); if (!nmod_mpoly_equal(k, q, ctx)) { printf("FAIL\n"); flint_printf("Check div matches divrem aliasing dividend\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_div(g, f, g, ctx); nmod_mpoly_assert_canonical(g, ctx); if (!nmod_mpoly_equal(g, q, ctx)) { printf("FAIL\n"); flint_printf("Check div matches divrem aliasing divisor\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(q, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000153751461254215100227770ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_div_monagan_pearce, state) { int i, j, result; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, l; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(l, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(l, state, len, exp_bits, ctx); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_div_monagan_pearce(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_set(l, h, ctx); nmod_mpoly_div_monagan_pearce(l, l, g, ctx); nmod_mpoly_assert_canonical(l, ctx); result = nmod_mpoly_equal(l, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing dividend\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_div_monagan_pearce(g, h, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(g, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing divisor\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(l, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check div matches divrem for random polys */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, q, r, k; mp_limb_t modulus; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(q, ctx); nmod_mpoly_init(r, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = n_randint(state, 50/n) + 1; exp_bound1 = n_randint(state, 50/n) + 1; exp_bound2 = n_randint(state, 50/n) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(q, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_divrem_monagan_pearce(q, r, f, g, ctx); nmod_mpoly_assert_canonical(q, ctx); nmod_mpoly_assert_canonical(r, ctx); nmod_mpoly_remainder_strongtest(r, g, ctx); nmod_mpoly_mul_johnson(k, q, g, ctx); nmod_mpoly_add(k, k, r, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_div_monagan_pearce(k, f, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(k, q, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check div matches divrem\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_set(k, f, ctx); nmod_mpoly_div_monagan_pearce(k, k, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(k, q, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check div matches divrem aliasing dividend\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_div_monagan_pearce(g, f, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(g, q, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check div matches divrem aliasing divisor\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(q, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-divides.c000066400000000000000000000351621461254215100206210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_divides, state) { int i, j, result, ret, max_threads = 5, tmul = 25; /* Check f*g/g = f sparse */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, hsave, gsave; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(hsave, ctx); nmod_mpoly_init(gsave, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2 + 1, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_set(hsave, h, ctx); nmod_mpoly_set(gsave, g, ctx); ret = nmod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); nmod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f sparse\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } if ( !nmod_mpoly_equal(h, hsave, ctx) || !nmod_mpoly_equal(g, gsave, ctx)) { printf("FAIL\n"); flint_printf("Check f*g/g = f sparse input modification\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(hsave, ctx); nmod_mpoly_clear(gsave, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f dense */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 150/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ret = nmod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); nmod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f dense\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check divisibility of random polys */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; fmpz * shifts, * strides; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); max_bound = 1 + 20/FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); nmod_mpoly_inflate(f, f, shifts, strides, ctx); nmod_mpoly_inflate(g, g, shifts, strides, ctx); ret = nmod_mpoly_divides(h, f, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); if (ret == 0) continue; nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check divisibility of random polys\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_set(h, f, ctx); nmod_mpoly_mul(h, h, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ret = nmod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); nmod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing first\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); nmod_mpoly_set(h, g, ctx); nmod_mpoly_mul(h, f, h, ctx); nmod_mpoly_assert_canonical(h, ctx); ret = nmod_mpoly_divides(k, h, g, ctx); FLINT_ASSERT(ret == 0 || ret == 1); nmod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing second\n" "i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-divides_dense.c000066400000000000000000000255671461254215100220070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_divides_dense, state) { int i, j, result, ret; /* Check f*g/g = f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ret = nmod_mpoly_divides_dense(k, h, g, ctx); if (ret == -1) continue; nmod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check divisibility of random polys */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 20/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); ret = nmod_mpoly_divides_dense(h, f, g, ctx); if (ret == -1 || ret == 0) continue; nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check divisibility of random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing first argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); nmod_mpoly_set(h, f, ctx); nmod_mpoly_mul(h, h, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ret = nmod_mpoly_divides_dense(k, h, g, ctx); if (ret == -1) continue; nmod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f aliasing second argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; mp_limb_t max_bound, * exp_bound, * exp_bound1, * exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, (i % 4 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound1 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); exp_bound2 = (mp_limb_t *) flint_malloc(ctx->minfo->nvars*sizeof(mp_limb_t)); for (j = 0; j < ctx->minfo->nvars; j++) { exp_bound[j] = UWORD(1) << (FLINT_BITS - 1); exp_bound1[j] = n_randint(state, max_bound) + 1; exp_bound2[j] = n_randint(state, max_bound) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bounds(g, state, len2 + 1, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bounds(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bounds(k, state, len, exp_bound, ctx); nmod_mpoly_set(h, g, ctx); nmod_mpoly_mul(h, f, h, ctx); nmod_mpoly_assert_canonical(h, ctx); ret = nmod_mpoly_divides_dense(k, h, g, ctx); if (ret == -1) continue; nmod_mpoly_assert_canonical(k, ctx); result = (ret == 1) && nmod_mpoly_equal(k, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f aliasing second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } flint_free(exp_bound); flint_free(exp_bound1); flint_free(exp_bound2); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-divides_heap_threaded.c000066400000000000000000000343721461254215100234600ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" #if defined(nmod_mpoly_divides_heap_threaded) TEST_FUNCTION_START(nmod_mpoly_divides_heap_threaded, state) { int i, j, result, result2, max_threads = 5, tmul = 30; #ifdef _WIN32 tmul = 1; #endif { nmod_mpoly_ctx_t ctx; nmod_mpoly_t p, f, g, h, h2; const char * vars[] = {"x","y","z","t","u"}; int aff[] = {0, 1}; nmod_mpoly_ctx_init(ctx, 5, ORD_DEGLEX, 179424691); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(p, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(h2, ctx); nmod_mpoly_set_str_pretty(g, "(1+x+y+2*z^2+3*t^3+5*u^5)^6", vars, ctx); nmod_mpoly_set_str_pretty(f, "(1+u+t+2*z^2+3*y^3+5*x^5)^6", vars, ctx); nmod_mpoly_mul(p, f, g, ctx); result = nmod_mpoly_divides_monagan_pearce(h, p, f, ctx); nmod_mpoly_assert_canonical(h, ctx); flint_set_num_threads(2); flint_set_thread_affinity(aff, 2); result2 = nmod_mpoly_divides_heap_threaded(h2, p, f, ctx); nmod_mpoly_assert_canonical(h2, ctx); flint_restore_thread_affinity(); if (!result || !result2 || !nmod_mpoly_equal(h, g, ctx) || !nmod_mpoly_equal(h2, g, ctx)) { printf("FAIL\n"); flint_printf("Check simple example\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(h2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_divides_heap_threaded(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = result && nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f with divisor aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_divides_heap_threaded(g, h, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = result && nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f with divisor aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*g/g = f with dividend aliasing */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_divides_heap_threaded(h, h, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = result && nmod_mpoly_equal(f, h, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f with dividend aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check random polys don't divide */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, p, h1, h2; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bound3; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(p, ctx); nmod_mpoly_init(h1, ctx); nmod_mpoly_init(h2, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; len3 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bound3 = n_randint(state, 20) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(p, state, len3, exp_bound3, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul(f, f, g, ctx); nmod_mpoly_add(f, f, p, ctx); result = nmod_mpoly_divides_monagan_pearce(h1, f, g, ctx); nmod_mpoly_assert_canonical(h1, ctx); result2 = nmod_mpoly_divides_heap_threaded(h2, f, g, ctx); nmod_mpoly_assert_canonical(h2, ctx); if (result != result2 || !nmod_mpoly_equal(h1, h2, ctx)) { flint_printf("Check random polys don't divide\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_clear(h1, ctx); nmod_mpoly_clear(h2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check random polys don't divide alias dividend */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, p, h1; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bound3; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(p, ctx); nmod_mpoly_init(h1, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; len3 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bound3 = n_randint(state, 20) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(p, state, len3, exp_bound3, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul(f, f, g, ctx); nmod_mpoly_add(f, f, p, ctx); result = nmod_mpoly_divides_monagan_pearce(h1, f, g, ctx); nmod_mpoly_assert_canonical(h1, ctx); result2 = nmod_mpoly_divides_heap_threaded(f, f, g, ctx); nmod_mpoly_assert_canonical(f, ctx); if (result != result2 || !nmod_mpoly_equal(h1, f, ctx)) { flint_printf("Check random polys don't divide alias dividend\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_clear(h1, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check random polys don't divide alias divisor */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, p, h1; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bound3; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(p, ctx); nmod_mpoly_init(h1, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; len3 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bound3 = n_randint(state, 20) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(p, state, len3, exp_bound3, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul(f, f, g, ctx); nmod_mpoly_add(f, f, p, ctx); result = nmod_mpoly_divides_monagan_pearce(h1, f, g, ctx); nmod_mpoly_assert_canonical(h1, ctx); result2 = nmod_mpoly_divides_heap_threaded(g, f, g, ctx); nmod_mpoly_assert_canonical(g, ctx); if (result != result2 || !nmod_mpoly_equal(h1, g, ctx)) { flint_printf("Check random polys don't divide alias divisor\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_clear(h1, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(nmod_mpoly_divides_heap_threaded, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/nmod_mpoly/test/t-divides_monagan_pearce.c000066400000000000000000000312661461254215100236410ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_divides_monagan_pearce, state) { int i, j, result, ok1, ok2; /* Check f*g/g = f */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ok1 = nmod_mpoly_divides_monagan_pearce(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = (ok1 && nmod_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check random polys don't divide */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), nvars); exp_bound = n_randint(state, 200/n + 1) + 1; exp_bound1 = n_randint(state, 200/n + 1) + 1; exp_bound2 = n_randint(state, 200/n + 1) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); ok1 = nmod_mpoly_divides_monagan_pearce(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); if (ok1) { nmod_mpoly_mul_johnson(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); } result = (ok1 == 0 || nmod_mpoly_equal(f, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check random polys don't divide\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument, exact division */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ok1 = nmod_mpoly_divides_monagan_pearce(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); ok2 = nmod_mpoly_divides_monagan_pearce(h, h, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = (ok1 == 1 && ok2 == 1 && nmod_mpoly_equal(h, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument, exact division\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing, first argument, random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; n = FLINT_MAX(WORD(1), nvars); exp_bound = n_randint(state, 200/n + 1) + 1; exp_bound1 = n_randint(state, 200/n + 1) + 1; exp_bound2 = n_randint(state, 200/n + 1) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); ok1 = nmod_mpoly_divides_monagan_pearce(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ok2 = nmod_mpoly_divides_monagan_pearce(f, f, g, ctx); nmod_mpoly_assert_canonical(f, ctx); result = ((ok1 == ok2) && (ok1 == 0 || nmod_mpoly_equal(f, h, ctx))); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing, first argument, random polys\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument, exact division */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ok1 = nmod_mpoly_divides_monagan_pearce(k, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); ok2 = nmod_mpoly_divides_monagan_pearce(g, h, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = (ok1 == 1 && ok2 == 1 && nmod_mpoly_equal(g, k, ctx)); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument, exact division\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing, second argument, random polys */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; n = FLINT_MAX(WORD(1), nvars); exp_bound = n_randint(state, 200/n + 1) + 1; exp_bound1 = n_randint(state, 200/n + 1) + 1; exp_bound2 = n_randint(state, 200/n + 1) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); ok1 = nmod_mpoly_divides_monagan_pearce(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); ok2 = nmod_mpoly_divides_monagan_pearce(g, f, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = ((ok1 == ok2) && (ok1 == 0 || nmod_mpoly_equal(g, h, ctx))); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing, second argument, random polys\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-divrem.c000066400000000000000000000350031461254215100204520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_divrem, state) { int i, j, result; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1; exp_bits1 = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1; exp_bits2 = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(r, state, len, exp_bits, ctx); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_divrem(k, r, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); nmod_mpoly_assert_canonical(r, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f = g*q + r for random polys */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_divrem(h, r, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r, ctx); nmod_mpoly_remainder_strongtest(r, g, ctx); nmod_mpoly_mul(k, h, g, ctx); nmod_mpoly_add(k, k, r, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, r1, r2; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(r1, ctx); nmod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); nmod_mpoly_divrem(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem(f, r2, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r2, ctx); nmod_mpoly_remainder_strongtest(r2, g, ctx); result = nmod_mpoly_equal(h, f, ctx) && nmod_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_clear(r2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, r1, r2; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(r1, ctx); nmod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); nmod_mpoly_divrem(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem(g, r2, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r2, ctx); result = nmod_mpoly_equal(h, g, ctx) && nmod_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_clear(r2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r1; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_divrem(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem(k, f, f, g, ctx); nmod_mpoly_assert_canonical(k, ctx); nmod_mpoly_assert_canonical(f, ctx); nmod_mpoly_remainder_strongtest(f, g, ctx); result = nmod_mpoly_equal(h, k, ctx) && nmod_mpoly_equal(r1, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r1; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_divrem(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem(k, g, f, g, ctx); nmod_mpoly_assert_canonical(k, ctx); nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(h, k, ctx) && nmod_mpoly_equal(r1, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-divrem_ideal.c000066400000000000000000000240111461254215100216050ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_divrem_ideal, state) { int result; slong i, j, w; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; nmod_mpoly_struct * qarr[1], * darr[1]; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bits2 + 1, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bits, ctx); nmod_mpoly_randtest_bound(r, state, len, exp_bits, ctx); nmod_mpoly_mul(h, f, g, ctx); qarr[0] = k; darr[0] = g; nmod_mpoly_divrem_ideal(qarr, r, h, darr, 1, ctx); nmod_mpoly_assert_canonical(qarr[0], ctx); nmod_mpoly_assert_canonical(r, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f = g1*q1 + ... + gn*qn + r for random polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, r, k1, k2; nmod_mpoly_struct * g, * q; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; nmod_mpoly_struct * qarr[5], * darr[5]; fmpz * shifts, * strides; num = n_randint(state, 5) + 1; g = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); q = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; for (w = 0; w < num; w++) { nmod_mpoly_init(g + w, ctx); darr[w] = g + w; nmod_mpoly_init(q + w, ctx); qarr[w] = q + w; } nmod_mpoly_init(f, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 10/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound1 = n_randint(state, 25/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound2 = n_randint(state, 20/FLINT_MAX(WORD(1), nvars) + 1) + 1; shifts = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = (fmpz *) flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_init(shifts + j); fmpz_init(strides + j); fmpz_randtest_unsigned(shifts + j, state, 100); fmpz_randtest_unsigned(strides + j, state, 100); fmpz_add_ui(strides + j, strides + j, 1); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_inflate(f, f, shifts, strides, ctx); for (w = 0; w < num; w++) { nmod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (nmod_mpoly_is_zero(darr[w], ctx)) nmod_mpoly_one(darr[w], ctx); nmod_mpoly_inflate(darr[w], darr[w], shifts, strides, ctx); nmod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } nmod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); nmod_mpoly_divrem_ideal(qarr, r, f, darr, num, ctx); nmod_mpoly_assert_canonical(r, ctx); for (w = 0; w < num; w++) { nmod_mpoly_assert_canonical(qarr[w], ctx); nmod_mpoly_remainder_strongtest(r, darr[w], ctx); } nmod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { nmod_mpoly_mul(k1, qarr[w], darr[w], ctx); nmod_mpoly_add(k2, k2, k1, ctx); } nmod_mpoly_add(k2, k2, r, ctx); result = nmod_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g1*q1 + ... + gn*qn + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (j = 0; j < ctx->minfo->nvars; j++) { fmpz_clear(shifts + j); fmpz_clear(strides + j); } flint_free(shifts); flint_free(strides); for (w = 0; w < num; w++) nmod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) nmod_mpoly_clear(darr[w], ctx); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, r, k1, k2; nmod_mpoly_struct * g, * q; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; nmod_mpoly_struct * qarr[5], * darr[5]; num = n_randint(state, 5) + 1; g = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); q = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; for (w = 0; w < num; w++) { nmod_mpoly_init(g + w, ctx); darr[w] = g + w; nmod_mpoly_init(q + w, ctx); qarr[w] = q + w; } nmod_mpoly_init(f, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 10/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound1 = n_randint(state, 25/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound2 = n_randint(state, 20/FLINT_MAX(WORD(1), nvars) + 1) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); for (w = 0; w < num; w++) { nmod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (nmod_mpoly_is_zero(darr[w], ctx)) nmod_mpoly_one(darr[w], ctx); nmod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } nmod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); nmod_mpoly_set(r, f, ctx); nmod_mpoly_divrem_ideal(qarr, f, f, darr, num, ctx); nmod_mpoly_assert_canonical(f, ctx); for (w = 0; w < num; w++) { nmod_mpoly_assert_canonical(qarr[w], ctx); nmod_mpoly_remainder_strongtest(f, darr[w], ctx); } nmod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { nmod_mpoly_mul(k1, qarr[w], darr[w], ctx); nmod_mpoly_add(k2, k2, k1, ctx); } nmod_mpoly_add(k2, k2, f, ctx); result = nmod_mpoly_equal(r, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) nmod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) nmod_mpoly_clear(darr[w], ctx); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000233211461254215100246270ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_divrem_ideal_monagan_pearce, state) { int result; slong i, j, w; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r; ordering_t ord; mp_limb_t modulus; slong maxbits; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong exp_bits, exp_bits1, exp_bits2; nmod_mpoly_struct * qarr[1], * darr[1]; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init(ctx, nvars, ord, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; maxbits = FLINT_BITS - mpoly_ordering_isdeg(ctx->minfo)*FLINT_BIT_COUNT(nvars); exp_bits = n_randint(state, maxbits - 1) + 1; exp_bits1 = n_randint(state, maxbits - 2) + 1; exp_bits2 = n_randint(state, maxbits - 2) + 1; exp_bound = n_randbits(state, exp_bits); exp_bound1 = n_randbits(state, exp_bits1); exp_bound2 = n_randbits(state, exp_bits2); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2 + 1, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); qarr[0] = k; darr[0] = g; nmod_mpoly_divrem_ideal_monagan_pearce(qarr, r, h, darr, 1, ctx); nmod_mpoly_assert_canonical(qarr[0], ctx); nmod_mpoly_assert_canonical(r, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f = g1*q1 + ... + gn*qn + r for random polys */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, r, k1, k2; nmod_mpoly_struct * g, * q; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; nmod_mpoly_struct * qarr[5], * darr[5]; num = n_randint(state, 5) + 1; g = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); q = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; for (w = 0; w < num; w++) { nmod_mpoly_init(g + w, ctx); darr[w] = g + w; nmod_mpoly_init(q + w, ctx); qarr[w] = q + w; } nmod_mpoly_init(f, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 10/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound1 = n_randint(state, 25/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound2 = n_randint(state, 20/FLINT_MAX(WORD(1), nvars) + 1) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); for (w = 0; w < num; w++) { nmod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (nmod_mpoly_is_zero(darr[w], ctx)) nmod_mpoly_one(darr[w], ctx); nmod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } nmod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); nmod_mpoly_divrem_ideal_monagan_pearce(qarr, r, f, darr, num, ctx); nmod_mpoly_assert_canonical(r, ctx); for (w = 0; w < num; w++) { nmod_mpoly_assert_canonical(qarr[w], ctx); nmod_mpoly_remainder_strongtest(r, darr[w], ctx); } nmod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { nmod_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); nmod_mpoly_add(k2, k2, k1, ctx); } nmod_mpoly_add(k2, k2, r, ctx); result = nmod_mpoly_equal(f, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g1*q1 + ... + gn*qn + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) nmod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) nmod_mpoly_clear(darr[w], ctx); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, r, k1, k2; nmod_mpoly_struct * g, * q; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; nmod_mpoly_struct * qarr[5], * darr[5]; num = n_randint(state, 5) + 1; g = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); q = (nmod_mpoly_struct *) flint_malloc(num*sizeof(nmod_mpoly_struct)); modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; for (w = 0; w < num; w++) { nmod_mpoly_init(g + w, ctx); darr[w] = g + w; nmod_mpoly_init(q + w, ctx); qarr[w] = q + w; } nmod_mpoly_init(f, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 10/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound1 = n_randint(state, 25/FLINT_MAX(WORD(1), nvars) + 1) + 2; exp_bound2 = n_randint(state, 20/FLINT_MAX(WORD(1), nvars) + 1) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); for (w = 0; w < num; w++) { nmod_mpoly_randtest_bound(darr[w], state, len2, exp_bound2 + 1, ctx); if (nmod_mpoly_is_zero(darr[w], ctx)) nmod_mpoly_one(darr[w], ctx); nmod_mpoly_randtest_bound(qarr[w], state, len, exp_bound, ctx); } nmod_mpoly_randtest_bound(k1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k2, state, len, exp_bound, ctx); nmod_mpoly_set(r, f, ctx); nmod_mpoly_divrem_ideal_monagan_pearce(qarr, f, f, darr, num, ctx); nmod_mpoly_assert_canonical(f, ctx); for (w = 0; w < num; w++) { nmod_mpoly_assert_canonical(qarr[w], ctx); nmod_mpoly_remainder_strongtest(f, darr[w], ctx); } nmod_mpoly_zero(k2, ctx); for (w = 0; w < num; w++) { nmod_mpoly_mul_johnson(k1, qarr[w], darr[w], ctx); nmod_mpoly_add(k2, k2, k1, ctx); } nmod_mpoly_add(k2, k2, f, ctx); result = nmod_mpoly_equal(r, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } for (w = 0; w < num; w++) nmod_mpoly_clear(qarr[w], ctx); for (w = 0; w < num; w++) nmod_mpoly_clear(darr[w], ctx); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_clear(r, ctx); flint_free(g); flint_free(q); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-divrem_monagan_pearce.c000066400000000000000000000352161461254215100234770ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_divrem_monagan_pearce, state) { int i, j, result; /* Check f*g/g = f */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bits2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(r, state, len, exp_bits, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_divrem_monagan_pearce(k, r, h, g, ctx); nmod_mpoly_assert_canonical(k, ctx); nmod_mpoly_assert_canonical(r, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*g/g = f\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f = g*q + r for random polys */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r, ctx); len = n_randint(state, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_divrem_monagan_pearce(h, r, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r, ctx); nmod_mpoly_remainder_strongtest(r, g, ctx); nmod_mpoly_mul_johnson(k, h, g, ctx); nmod_mpoly_add(k, k, r, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(f, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f = g*q + r for random polys\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, r1, r2; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(r1, ctx); nmod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem_monagan_pearce(f, r2, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r2, ctx); nmod_mpoly_remainder_strongtest(r2, g, ctx); result = nmod_mpoly_equal(h, f, ctx) && nmod_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_clear(r2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of quotient with second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, r1, r2; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(r1, ctx); nmod_mpoly_init(r2, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r2, state, len, exp_bound, ctx); nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem_monagan_pearce(g, r2, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r2, ctx); result = nmod_mpoly_equal(h, g, ctx) && nmod_mpoly_equal(r1, r2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of quotient with second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_clear(r2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r1; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem_monagan_pearce(k, f, f, g, ctx); nmod_mpoly_assert_canonical(k, ctx); nmod_mpoly_assert_canonical(f, ctx); nmod_mpoly_remainder_strongtest(f, g, ctx); result = nmod_mpoly_equal(h, k, ctx) && nmod_mpoly_equal(r1, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of remainder with second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k, r1; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); nmod_mpoly_init(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound1 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; exp_bound2 = n_randint(state, 50/FLINT_MAX(WORD(1), nvars)) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); if (nmod_mpoly_is_zero(g, ctx)) nmod_mpoly_one(g, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(r1, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_divrem_monagan_pearce(h, r1, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_assert_canonical(r1, ctx); nmod_mpoly_remainder_strongtest(r1, g, ctx); nmod_mpoly_divrem_monagan_pearce(k, g, f, g, ctx); nmod_mpoly_assert_canonical(k, ctx); nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(h, k, ctx) && nmod_mpoly_equal(r1, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing of remainder with second argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_clear(r1, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-evaluate.c000066400000000000000000000147141461254215100210000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_evaluate, state) { slong i, j, v; int tmul = 20; /* Check repeated evalone matches evalall */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g; mp_limb_t fe; mp_limb_t * vals; slong * perm; slong nvars, len; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); len = n_randint(state, 50); exp_bits = n_randint(state, 200) + 1; perm = (slong *) flint_malloc(nvars*sizeof(slong)); vals = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); for (v = 0; v < nvars; v++) { vals[v] = n_randlimb(state); perm[v] = v; } for (j = 0; j < 2*nvars; j++) { slong a, b, c; a = n_randint(state, nvars); b = n_randint(state, nvars); c = perm[a]; perm[a] = perm[b]; perm[b] = c; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); fe = nmod_mpoly_evaluate_all_ui(f, vals, ctx); for (v = 0; v < nvars; v++) { nmod_mpoly_evaluate_one_ui(g, f, perm[v], vals[perm[v]], ctx); nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_evaluate_one_ui(f, f, perm[v], vals[perm[v]], ctx); nmod_mpoly_assert_canonical(f, ctx); if (!nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check evalone aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } if (!nmod_mpoly_equal_ui(f, fe, ctx)) { printf("FAIL\n"); flint_printf("Check repeated evalone matches evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } flint_free(vals); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); flint_free(perm); } /* Check add commutes with evalall */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, fg; mp_limb_t fe, ge, fge; mp_limb_t * vals; slong nvars, len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(fg, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; vals = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); for (v = 0; v < nvars; v++) { vals[v] = n_randlimb(state); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_add(fg, f, g, ctx); fe = nmod_mpoly_evaluate_all_ui(f, vals, ctx); ge = nmod_mpoly_evaluate_all_ui(g, vals, ctx); fge = nmod_mpoly_evaluate_all_ui(fg, vals, ctx); if (fge != nmod_add(fe, ge, ctx->mod)) { printf("FAIL\n"); flint_printf("Check add commutes with evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } flint_free(vals); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(fg, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check mul commutes with evalall */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, fg; mp_limb_t fe, ge, fge; mp_limb_t * vals; slong nvars, len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(fg, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); exp_bits1 = n_randint(state, 200) + 1; exp_bits2 = n_randint(state, 200) + 1; vals = (mp_limb_t *) flint_malloc(nvars*sizeof(mp_limb_t)); for (v = 0; v < nvars; v++) { vals[v] = n_randlimb(state); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_add(fg, f, g, ctx); fe = nmod_mpoly_evaluate_all_ui(f, vals, ctx); ge = nmod_mpoly_evaluate_all_ui(g, vals, ctx); fge = nmod_mpoly_evaluate_all_ui(fg, vals, ctx); if (fge != nmod_add(fe, ge, ctx->mod)) { printf("FAIL\n"); flint_printf("Check mul commutes with evalall\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } flint_free(vals); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(fg, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-gcd.c000066400000000000000000000672171461254215100177350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd void gcd_check( nmod_mpoly_t g, nmod_mpoly_t a, nmod_mpoly_t b, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { nmod_mpoly_t ca, cb, cg; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); if (!nmod_mpoly_gcd(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx); if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != UWORD(1)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (((i + j) % 7) == 0) { nmod_mpoly_set(cg, b, ctx); nmod_mpoly_gcd(cg, cg, a, ctx); if (!nmod_mpoly_equal(cg, g, ctx)) { flint_printf("FAIL: check aliasing 1\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (((i + j) % 9) == 0) { nmod_mpoly_set(cg, b, ctx); nmod_mpoly_gcd(cg, a, cg, ctx); if (!nmod_mpoly_equal(cg, g, ctx)) { flint_printf("FAIL: check aliasing 2\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (!nmod_mpoly_divides(ca, a, g, ctx) || !nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_gcd(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(cg, ctx); if (!nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check cofactor gcd is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(nmod_mpoly_gcd, state) { const slong max_threads = 5; slong i, j, k, tmul = 5; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b; const char * vars[] = {"t" ,"x", "y", "z"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(g, "x + y + z + t", vars, ctx); nmod_mpoly_set_str_pretty(a, "x^2 + y^2 + z^2 + t^2", vars, ctx); nmod_mpoly_set_str_pretty(b, "x^3 + y^3 + z^3 + t^3", vars, ctx); nmod_mpoly_mul(a, a, g, ctx); nmod_mpoly_mul(b, b, g, ctx); gcd_check(g, a, b, ctx, 0, 0, "sparse example"); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b; const char * vars[] = {"t" ,"x", "y", "z"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(g, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); nmod_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); nmod_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); nmod_mpoly_mul(a, a, g, ctx); nmod_mpoly_mul(b, b, g, ctx); gcd_check(g, a, b, ctx, 0, 0, "sparse example"); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b; const char * vars[] = {"x", "y"}; nmod_mpoly_ctx_init(ctx, 2, ORD_LEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(g, "(1+x+y)^100", vars, ctx); nmod_mpoly_set_str_pretty(a, "(2+x+y)^100", vars, ctx); nmod_mpoly_set_str_pretty(b, "(3+x+y)^100", vars, ctx); nmod_mpoly_mul(a, a, g, ctx); nmod_mpoly_mul(b, b, g, ctx); gcd_check(g, a, b, ctx, 0, 0, "big example"); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 3; i <= 8; i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b, t; nmod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, 43051); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_one(g, ctx); nmod_mpoly_one(a, ctx); nmod_mpoly_one(b, ctx); for (j = 0; j < i; j++) { nmod_mpoly_gen(t, j, ctx); nmod_mpoly_add_ui(t, t, 1, ctx); nmod_mpoly_mul(g, g, t, ctx); nmod_mpoly_gen(t, j, ctx); nmod_mpoly_sub_ui(t, t, 2, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_gen(t, j, ctx); nmod_mpoly_add_ui(t, t, 2, ctx); nmod_mpoly_mul(b, b, t, ctx); } nmod_mpoly_sub_ui(g, g, 2, ctx); nmod_mpoly_add_ui(a, a, 2, ctx); nmod_mpoly_sub_ui(b, b, 2, ctx); nmod_mpoly_mul(a, a, g, ctx); nmod_mpoly_mul(b, b, g, ctx); gcd_check(g, a, b, ctx, i, 0, "dense examples"); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b; const char * vars[] = {"x1", "x2", "x3", "x4"}; nmod_mpoly_ctx_init(ctx, 2, ORD_DEGREVLEX, 2); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(a, "x1*x2^5+x1*x2^3+x2^4+x2^2", vars, ctx); nmod_mpoly_set_str_pretty(b, "x1*x2^7+x1*x2^6+x1*x2^5+x2^6+x2^5+x2^4+x1*x2^2+x2", vars, ctx); nmod_mpoly_set_str_pretty(g, "1", vars, ctx); nmod_mpoly_mul(a, a, g,ctx); nmod_mpoly_mul(b, b, g,ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, 0, 0, "example"); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(t, state, 1, exp_bits, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(b, state, len2, exp_bits2, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "monomial"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t1, t2; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(t1, state, 1, exp_bits1, ctx); nmod_mpoly_randtest_bits(t2, state, 1, exp_bits2, ctx); if (t1->length != 1 || t2->length != 1) { flint_printf("FAIL:\ncheck random monomial generation\n"); fflush(stdout); flint_abort(); } nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); nmod_mpoly_mul(b, a, t1, ctx); nmod_mpoly_mul(a, a, t2, ctx); nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "monomial cofactors"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { mp_limb_t c; nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t1, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(t2, state, len2, exp_bound2, ctx); nmod_mpoly_mul(b, t1, t2, ctx); c = n_randint(state, ctx->mod.n); nmod_mpoly_scalar_mul_ui(a, t2, c, ctx); c = n_randint(state, ctx->mod.n); nmod_mpoly_scalar_mul_ui(b, b, c, ctx); nmod_mpoly_randtest_bound(g, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); if ((j%2) == 0) nmod_mpoly_swap(a, b, ctx); gcd_check(g, a, b, ctx, i, j, "one input divides the other"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 7, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 40/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "sparse inputs"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len, len1, len2; slong degbound; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 7, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 40/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(b, b, newbits, ctx); } nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "sparse input with repacking"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 7, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 30); len2 = n_randint(state, 30); degbound = 40/(2*ctx->minfo->nvars - 1); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } nmod_mpoly_inflate(a, a, shifts1, strides, ctx); nmod_mpoly_inflate(b, b, shifts2, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 16/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 16/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 16/ctx->minfo->nvars); } bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "dense input"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 16/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 16/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 16/ctx->minfo->nvars); } bits4 = n_randint(state, 200); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(b, b, newbits, ctx); } nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "dense input with repacking"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len1 = n_randint(state, 300) + 1; len2 = n_randint(state, 300); len3 = n_randint(state, 300); len4 = n_randint(state, 300); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 2 + n_randint(state, 15/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 15/ctx->minfo->nvars); } bits4 = n_randint(state, 200); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } nmod_mpoly_inflate(a, a, shifts1, strides, ctx); nmod_mpoly_inflate(b, b, shifts2, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, a, b, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/nmod_mpoly/test/t-gcd_brown.c000066400000000000000000000153031461254215100211310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_brown void gcd_check( nmod_mpoly_t g, nmod_mpoly_t a, nmod_mpoly_t b, nmod_mpoly_t t, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { nmod_mpoly_t ca, cb, cg; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); if (!nmod_mpoly_gcd_brown(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx); if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != UWORD(1)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_zero(t, ctx) && !nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_divides(ca, a, g, ctx) || !nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_gcd_brown(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(cg, ctx); if (!nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(nmod_mpoly_gcd_brown, state) { slong i, j; slong tmul = 10; slong max_threads = 6; #ifdef _WIN32 tmul = 1; #endif { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b, t; const char * vars[] = {"x", "y", "z", "w"}; nmod_mpoly_ctx_init(ctx, 3, ORD_DEGREVLEX, 1009); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_set_str_pretty(a, "x^3+y^3+z^3", vars, ctx); nmod_mpoly_set_str_pretty(b, "x^5+y^5+z^5", vars, ctx); nmod_mpoly_set_str_pretty(t, "x^7+y^7+z^7", vars, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, 0, 0, "example"); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; mp_limb_t p; p = n_randint(state, FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, p < 3000 ? 3 : 4, p); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 40) + 1; len1 = n_randint(state, 80); len2 = n_randint(state, 80); degbound = 1 + 20/FLINT_MAX(WORD(1), ctx->minfo->nvars); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random small"); } flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; slong len, len1, len2; slong n, degbound; mp_limb_t p; p = n_randint(state, FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, p < 3000 ? 3 : 4, p); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 100) + 1; len1 = n_randint(state, 150); len2 = n_randint(state, 150); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); degbound = 1 + 60/n/n; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense"); } flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/nmod_mpoly/test/t-gcd_cofactors.c000066400000000000000000001037411461254215100217710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_cofactors void gcd_check( nmod_mpoly_t g, nmod_mpoly_t abar, nmod_mpoly_t bbar, nmod_mpoly_t a, nmod_mpoly_t b, const nmod_mpoly_t gdiv, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; nmod_mpoly_t ca, cb, cg, u, v, w; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); nmod_mpoly_init(u, ctx); nmod_mpoly_init(v, ctx); nmod_mpoly_init(w, ctx); res = nmod_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_assert_canonical(abar, ctx); nmod_mpoly_assert_canonical(bbar, ctx); if (!res) { flint_printf("Check gcd can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_zero(gdiv, ctx)) { if (!nmod_mpoly_divides(ca, g, gdiv, ctx)) { printf("FAIL\n"); flint_printf("Check divisor of gcd\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } nmod_mpoly_mul(ca, g, abar, ctx); nmod_mpoly_mul(cb, g, bbar, ctx); if (!nmod_mpoly_equal(ca, a, ctx) || !nmod_mpoly_equal(cb, b, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { printf("FAIL\n"); flint_printf("Check zero gcd only results from zero inputs\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != 1) { printf("FAIL\n"); flint_printf("Check gcd is monic\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(u, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, a, u, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(v, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, a, v, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(w, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, a, w, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (a, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(u, a, ctx); nmod_mpoly_gcd_cofactors(u, v, w, u, b, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(v, a, ctx); nmod_mpoly_gcd_cofactors(u, v, w, v, b, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(w, a, ctx); nmod_mpoly_gcd_cofactors(u, v, w, w, b, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, b): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(u, a, ctx); nmod_mpoly_set(v, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, u, v, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(v, a, ctx); nmod_mpoly_set(u, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, v, u, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(u, a, ctx); nmod_mpoly_set(w, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, u, w, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (u, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(w, a, ctx); nmod_mpoly_set(u, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, w, u, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, u): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(v, a, ctx); nmod_mpoly_set(w, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, v, w, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (v, w): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_set(w, a, ctx); nmod_mpoly_set(v, b, ctx); nmod_mpoly_gcd_cofactors(u, v, w, w, v, ctx); if (!nmod_mpoly_equal(g, u, ctx) || !nmod_mpoly_equal(abar, v, ctx) || !nmod_mpoly_equal(bbar, w, ctx)) { flint_printf("FAIL (u, v, w), (w, v): i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = nmod_mpoly_gcd_cofactors(cg, ca, cb, abar, bbar, ctx); nmod_mpoly_assert_canonical(cg, ctx); if (!res) { printf("FAIL\n"); flint_printf("Check gcd of cofactors can be computed\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_one(cg, ctx)) { printf("FAIL\n"); flint_printf("Check gcd of cofactors is one\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_equal(ca, abar, ctx) || !nmod_mpoly_equal(cb, bbar, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors of cofactors\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = nmod_mpoly_gcd_cofactors(cg, abar, bbar, abar, bbar, ctx); nmod_mpoly_assert_canonical(cg, ctx); if (!nmod_mpoly_equal(ca, abar, ctx) || !nmod_mpoly_equal(cb, bbar, ctx)) { printf("FAIL\n"); flint_printf("Check cofactors of cofactors with aliasing\n" "i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); nmod_mpoly_clear(u, ctx); nmod_mpoly_clear(v, ctx); nmod_mpoly_clear(w, ctx); } TEST_FUNCTION_START(nmod_mpoly_gcd_cofactors, state) { const slong max_threads = 5; slong i, j, k, tmul = 3; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, abar, bbar, a, b, t; const char * vars[] = {"t" ,"x", "y", "z"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, 536870909); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); nmod_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); nmod_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, 0, 0, "example"); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 3; i <= 7; i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, abar, bbar, a, b, t; nmod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, 43051); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_one(g, ctx); nmod_mpoly_one(a, ctx); nmod_mpoly_one(b, ctx); for (j = 0; j < i; j++) { nmod_mpoly_gen(t, j, ctx); nmod_mpoly_add_ui(t, t, 1, ctx); nmod_mpoly_mul(g, g, t, ctx); nmod_mpoly_gen(t, j, ctx); nmod_mpoly_sub_ui(t, t, 2, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_gen(t, j, ctx); nmod_mpoly_add_ui(t, t, 2, ctx); nmod_mpoly_mul(b, b, t, ctx); } nmod_mpoly_sub_ui(g, g, 2, ctx); nmod_mpoly_add_ui(a, a, 2, ctx); nmod_mpoly_sub_ui(b, b, 2, ctx); nmod_mpoly_mul(a, a, g, ctx); nmod_mpoly_mul(b, b, g, ctx); nmod_mpoly_set(t, g, ctx); gcd_check(g, abar, bbar, a, b, t, ctx, i, 0, "dense examples"); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } { int success; nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, abar, bbar, a, b; const char * vars[] = {"x" ,"y", "z", "t"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, 101); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_set_str_pretty(a, "x^3 + 1", vars, ctx); nmod_mpoly_set_str_pretty(b, "x^9999999999999999999999 + x^3333333333333333333333 + x", vars, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); success = nmod_mpoly_gcd_cofactors(g, abar, bbar, a, b, ctx); if (success) { printf("FAIL\n"); flint_printf("Check non-example\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_ctx_clear(ctx); } /* The gcd should always work when one input is a monomial */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 25); len1 = n_randint(state, 50); len2 = n_randint(state, 50); if (n_randlimb(state) & UWORD(1)) len1 = FLINT_MIN(len1, WORD(1)); else len2 = FLINT_MIN(len2, WORD(1)); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(t, state, 1, exp_bits, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(b, state, len2, exp_bits2, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "monomial"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* The gcd should always work when both cofactors are monomials */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 25); len1 = n_randint(state, 25); exp_bits = n_randint(state, 70) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(t1, state, 1, exp_bits1, ctx); nmod_mpoly_randtest_bits(t2, state, 1, exp_bits2, ctx); if (t1->length != 1 || t2->length != 1) { flint_printf("FAIL:\ncheck random monomial generation\n"); fflush(stdout); flint_abort(); } nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); nmod_mpoly_mul(b, a, t1, ctx); nmod_mpoly_mul(t2, a, t2, ctx); nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, t2, b, a, ctx, i, j, "monomial cofactors"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } /* one input divides the other */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { mp_limb_t c; nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t1, t2; slong len, len1, len2; mp_limb_t exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 5); len1 = n_randint(state, 5); len2 = n_randint(state, 5); exp_bound = n_randint(state, 100) + 2; exp_bound1 = n_randint(state, 100) + 2; exp_bound2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t1, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(t2, state, len2, exp_bound2, ctx); nmod_mpoly_mul(b, t1, t2, ctx); c = n_randint(state, ctx->mod.n); nmod_mpoly_scalar_mul_ui(a, t2, c, ctx); c = n_randint(state, ctx->mod.n); nmod_mpoly_scalar_mul_ui(b, b, c, ctx); nmod_mpoly_randtest_bound(g, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); if ((j%2) == 0) nmod_mpoly_swap(a, b, ctx); gcd_check(g, abar, bbar, a, b, t2, ctx, i, j, "one input divides the other"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } /* sparse inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t; slong len, len1, len2; slong degbound; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 10) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse inputs"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random repackings */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len, len1, len2; slong degbound; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 10) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(b, b, newbits, ctx); } nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with repacking"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* sparse inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len, len1, len2; slong degbound; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 10) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 25/(2*ctx->minfo->nvars - 1); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } nmod_mpoly_inflate(a, a, shifts1, strides, ctx); nmod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } nmod_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "sparse input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* dense inputs */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* dense inputs with repacking */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t; mp_limb_t rlimb; flint_bitcnt_t newbits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); rlimb = n_randlimb(state); if (rlimb & UWORD(3)) { newbits = a->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(a, a, newbits, ctx); } if (rlimb & UWORD(12)) { newbits = b->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(b, b, newbits, ctx); } nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with repacking"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } /* dense inputs with random inflations */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, abar, bbar, t; fmpz * shifts1, * shifts2, * strides; flint_bitcnt_t stride_bits, shift_bits; slong len1, len2, len3, len4; ulong degbounds1[4]; ulong degbounds2[4]; ulong degbounds3[4]; flint_bitcnt_t bits4; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(abar, ctx); nmod_mpoly_init(bbar, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len1 = n_randint(state, 150) + 1; len2 = n_randint(state, 150); len3 = n_randint(state, 150); len4 = n_randint(state, 150); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds1[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds2[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); degbounds3[j] = 1 + n_randint(state, 12/ctx->minfo->nvars); } bits4 = n_randint(state, 100); stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; shifts1 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts2 = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(shifts1 + k); fmpz_init(shifts2 + k); fmpz_init(strides + k); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(t, state, len1, degbounds1, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len2, degbounds2, ctx); nmod_mpoly_randtest_bounds(b, state, len3, degbounds3, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len4, bits4, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts1 + k, state, shift_bits); fmpz_randtest_unsigned(shifts2 + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } nmod_mpoly_inflate(a, a, shifts1, strides, ctx); nmod_mpoly_inflate(b, b, shifts2, strides, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (fmpz_cmp(shifts1 + k, shifts2 + k) > 0) fmpz_set(shifts1 + k, shifts2 + k); } nmod_mpoly_inflate(t, t, shifts1, strides, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); gcd_check(g, abar, bbar, a, b, t, ctx, i, j, "dense input with inflation"); } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(shifts1 + k); fmpz_clear(shifts2 + k); fmpz_clear(strides + k); } flint_free(shifts1); flint_free(shifts2); flint_free(strides); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(abar, ctx); nmod_mpoly_clear(bbar, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/nmod_mpoly/test/t-gcd_hensel.c000066400000000000000000000126461461254215100212670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_hensel void gcd_check( nmod_mpoly_t g, nmod_mpoly_t a, nmod_mpoly_t b, nmod_mpoly_t t, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { nmod_mpoly_t ca, cb, cg; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); if (!nmod_mpoly_gcd_hensel(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx); if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != UWORD(1)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_zero(t, ctx) && !nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_divides(ca, a, g, ctx) || !nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_gcd_hensel(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(cg, ctx); if (!nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(nmod_mpoly_gcd_hensel, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t1, t2, t3; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); nmod_mpoly_init(t3, ctx); len = n_randint(state, 20) + 1; len1 = n_randint(state, 20); len2 = n_randint(state, 20); degbound = 50/(2*ctx->minfo->nvars - 1); degbounds = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 6; j++) { nmod_mpoly_randtest_bounds(t1, state, len, degbounds, ctx); nmod_mpoly_randtest_bounds(t2, state, len1, degbounds1, ctx); nmod_mpoly_randtest_bounds(t3, state, len2, degbounds2, ctx); switch (n_randint(state, 4)) { case 3: nmod_mpoly_mul(t3, t1, t2, ctx); break; case 2: nmod_mpoly_mul(t3, t3, t1, ctx); break; case 1: nmod_mpoly_mul(t3, t3, t2, ctx); break; default: break; } nmod_mpoly_mul(a, t1, t3, ctx); nmod_mpoly_mul(b, t2, t3, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t3, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_clear(t3, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/nmod_mpoly/test/t-gcd_zippel.c000066400000000000000000000122151461254215100213040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_zippel void gcd_check( nmod_mpoly_t g, nmod_mpoly_t a, nmod_mpoly_t b, nmod_mpoly_t t, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { nmod_mpoly_t ca, cb, cg; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); if (!nmod_mpoly_gcd_zippel(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx); if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != UWORD(1)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_zero(t, ctx) && !nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_divides(ca, a, g, ctx) || !nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_gcd_zippel(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(cg, ctx); if (!nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(nmod_mpoly_gcd_zippel, state) { slong i, j; for (i = 0; i < 30 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, ca, cb, cg, t; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, WORD(10), modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 16) + 1; len1 = n_randint(state, 16); len2 = n_randint(state, 16); degbound = 100/(2*ctx->minfo->nvars - 1); degbounds = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + 1) + 1; degbounds1[j] = n_randint(state, degbound + 1) + 1; degbounds2[j] = n_randint(state, degbound + 1) + 1; } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bounds(t, state, len, degbounds, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len1, degbounds1, ctx); nmod_mpoly_randtest_bounds(b, state, len2, degbounds2, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/nmod_mpoly/test/t-gcd_zippel2.c000066400000000000000000000122701461254215100213670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" /* Defined in t-gcd.c, t-gcd_brown.c, t-gcd_cofactors.c, t-gcd_hensel.c, * t-gcd_zippel2.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_zippel2 void gcd_check( nmod_mpoly_t g, nmod_mpoly_t a, nmod_mpoly_t b, nmod_mpoly_t t, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { nmod_mpoly_t ca, cb, cg; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); if (!nmod_mpoly_gcd_zippel2(g, a, b, ctx)) { flint_printf("FAIL: check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx); if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != UWORD(1)) { flint_printf("FAIL: check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_zero(t, ctx) && !nmod_mpoly_divides(cg, g, t, ctx)) { flint_printf("FAIL: check gcd divisor\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_divides(ca, a, g, ctx) || !nmod_mpoly_divides(cb, b, g, ctx)) { flint_printf("FAIL: check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_gcd_zippel2(cg, ca, cb, ctx)) { flint_printf("FAIL: check cofactor gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(cg, ctx); if (!nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(nmod_mpoly_gcd_zippel2, state) { slong i, j; for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, ca, cb, cg, t; slong len, len1, len2; ulong degbound; ulong * degbounds, * degbounds1, * degbounds2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 16) + 1; len1 = n_randint(state, 16); len2 = n_randint(state, 16); degbound = 120/(2*ctx->minfo->nvars - 1); degbounds = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds1 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); degbounds2 = (ulong * ) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); for (j = 0; j < ctx->minfo->nvars; j++) { degbounds[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); degbounds1[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); degbounds2[j] = n_randint(state, degbound + UWORD(1)) + UWORD(1); } for (j = 0; j < 5; j++) { nmod_mpoly_randtest_bounds(t, state, len, degbounds, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bounds(a, state, len1, degbounds1, ctx); nmod_mpoly_randtest_bounds(b, state, len2, degbounds2, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random"); } flint_free(degbounds); flint_free(degbounds1); flint_free(degbounds2); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef gcd_check flint-3.1.3/src/nmod_mpoly/test/t-gen.c000066400000000000000000000047401461254215100177410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_gen, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f1, f2; slong len, exp_bits, k1, k2; mp_limb_t modulus; modulus = UWORD(2) + n_randint(state, -UWORD(2)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); if (ctx->minfo->nvars < 1) { nmod_mpoly_ctx_clear(ctx); continue; } nmod_mpoly_init(f1, ctx); nmod_mpoly_init(f2, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; nmod_mpoly_randtest_bits(f1, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(f2, state, len, exp_bits, ctx); k1 = n_randint(state, ctx->minfo->nvars); k2 = n_randint(state, ctx->minfo->nvars); nmod_mpoly_gen(f1, k1, ctx); nmod_mpoly_assert_canonical(f1, ctx); nmod_mpoly_gen(f2, k2, ctx); nmod_mpoly_assert_canonical(f2, ctx); result = 1; result = result && nmod_mpoly_is_gen(f1, k1, ctx); result = result && nmod_mpoly_is_gen(f1, -WORD(1), ctx); result = result && nmod_mpoly_is_gen(f2, k2, ctx); result = result && nmod_mpoly_is_gen(f2, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check one generator\ni = %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_mul_johnson(f1, f1, f2, ctx); result = 1; result = result && !nmod_mpoly_is_gen(f1, k1, ctx); result = result && !nmod_mpoly_is_gen(f1, k2, ctx); result = result && !nmod_mpoly_is_gen(f1, -WORD(1), ctx); if (!result) { printf("FAIL\n"); flint_printf("Check product of two generators\ni = %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f1, ctx); nmod_mpoly_clear(f2, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000134611461254215100226410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(nmod_mpoly_get_coeff_vars_ui, state) { slong i, j1, j2; /* check simple example */ { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g; /* get the coefficient of y^1*x^2*/ slong varl[2] = {1, 0}; ulong expl[2] = {1, 2}; const char * vars[] = {"x", "y", "z", "w"}; nmod_mpoly_ctx_init(ctx, 4, ORD_DEGREVLEX, 11); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(f, "x^2*y*(z+w)+x+y+x*y^2+z^2+w^2", vars, ctx); nmod_mpoly_set_str_pretty(g, "z+w", vars, ctx); nmod_mpoly_get_coeff_vars_ui(f, f, varl, expl, 2, ctx); if (!nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\nCheck simple example\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } /* check 1 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, m; slong nvars, len; ulong exp_bound; slong vars[1]; ulong exps[1]; slong var1; mp_limb_t modulus; modulus = UWORD(2) + n_randint(state, -UWORD(2)); nvars = 1 + n_randint(state, 20); nmod_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state), modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 20) + 1; nmod_mpoly_randtest_bound(f, state, len, exp_bound, ctx); nmod_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars); nmod_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { vars[0] = var1; exps[0] = j1; nmod_mpoly_get_coeff_vars_ui(g, f, vars, exps, 1, ctx); nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_gen(m, var1, ctx); if (!nmod_mpoly_pow_ui(m, m, j1, ctx)) { printf("FAIL\n"); flint_printf("Check pow_ui success\ni = %wd, j1 = %wd\n", i, j1); fflush(stdout); flint_abort(); } nmod_mpoly_mul(g, g, m, ctx); nmod_mpoly_add(h, h, g, ctx); } if (!nmod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n"); flint_printf("Check 1 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); } /* check 2 variable sum of coefficients */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, m; slong nvars, len; ulong exp_bound; slong vars[2]; ulong exps[2]; slong var1, var2; mp_limb_t modulus; modulus = UWORD(2) + n_randint(state, -UWORD(2)); nvars = 2 + n_randint(state, 20); nmod_mpoly_ctx_init(ctx, nvars, mpoly_ordering_randtest(state), modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(m, ctx); len = n_randint(state, 200); exp_bound = n_randint(state, 12) + 1; nmod_mpoly_randtest_bound(f, state, len, exp_bound, ctx); nmod_mpoly_repack_bits(f, f, f->bits + n_randint(state, FLINT_BITS), ctx); var1 = n_randint(state, nvars - 1); var2 = 1 + var1 + n_randint(state, nvars - 1 - var1); nmod_mpoly_zero(h, ctx); for (j1 = 0; j1 < exp_bound; j1++) { for (j2 = 0; j2 < exp_bound; j2++) { vars[0] = var1; exps[0] = j1; vars[1] = var2; exps[1] = j2; nmod_mpoly_get_coeff_vars_ui(g, f, vars, exps, 2, ctx); nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_gen(m, var1, ctx); if (!nmod_mpoly_pow_ui(m, m, j1, ctx)) { printf("FAIL\n"); flint_printf("Check pow_ui success\ni = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } nmod_mpoly_mul(g, g, m, ctx); nmod_mpoly_gen(m, var2, ctx); if (!nmod_mpoly_pow_ui(m, m, j2, ctx)) { printf("FAIL\n"); flint_printf("Check pow_ui success\ni = %wd, j1 = %wd, j2 = %wd\n", i, j1, j2); fflush(stdout); flint_abort(); } nmod_mpoly_mul(g, g, m, ctx); nmod_mpoly_add(h, h, g, ctx); } } if (!nmod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\n"); flint_printf("Check 2 variable sum of coefficients\ni = %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-get_set_string_pretty.c000066400000000000000000000034251461254215100236160ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_get_set_string_pretty, state) { slong i; { slong len1; flint_bitcnt_t exp_bits1; mp_limb_t modulus; nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, f1; char * str; const char * vars[] = {"x","y","z","w","u","v"}; for (i = 0; i < flint_test_multiplier(); i++) { modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(f1, ctx); for (len1 = 3; len1 < 1000; len1 += len1/2) { exp_bits1 = 200; nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); str = nmod_mpoly_get_str_pretty(f, vars, ctx); nmod_mpoly_set_str_pretty(f1, str, vars, ctx); flint_free(str); if (!nmod_mpoly_equal(f, f1, ctx)) { flint_printf("FAIL\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(f1, ctx); nmod_mpoly_ctx_clear(ctx); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-get_set_term_coeff_ui.c000066400000000000000000000042071461254215100235060ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_get_set_term_coeff_ui, state) { slong i, j; /* Set coeff and get coeff and compare */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f; slong len, index; flint_bitcnt_t exp_bits; mp_limb_t c, d; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); len = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (f->length > 0) { for (j = 0; j < 10; j++) { c = n_randint(state, modulus); index = n_randint(state, f->length); nmod_mpoly_set_term_coeff_ui(f, index, c, ctx); d = nmod_mpoly_get_term_coeff_ui(f, index, ctx); if (c != d) { printf("FAIL\n"); flint_printf("check get and set match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } if (*nmod_mpoly_term_coeff_ref(f, index, ctx) != d) { printf("FAIL\n"); flint_printf("check reference match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } } nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000052571461254215100232240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(nmod_mpoly_get_set_term_exp_si, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = UWORD(2) + n_randint(state, -UWORD(2)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nvars = nmod_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (nmod_mpoly_is_zero(f, ctx)) nmod_mpoly_one(f, ctx); for (j = 0; j < 10; j++) { slong * exp1 = (slong *) flint_malloc(nvars*sizeof(slong)); slong * exp2 = (slong *) flint_malloc(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS - 1) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); nmod_mpoly_set_term_exp_ui(f, index, (ulong *) exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); nmod_mpoly_get_term_exp_si(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == nmod_mpoly_get_term_var_exp_si(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000052421461254215100232200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" #include "ulong_extras.h" TEST_FUNCTION_START(nmod_mpoly_get_set_term_exp_ui, state) { slong i, j, k; int result; /* check set and get match */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f; slong nvars, len, index; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = UWORD(2) + n_randint(state, -UWORD(2)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nvars = nmod_mpoly_ctx_nvars(ctx); len = n_randint(state, 50) + 1; exp_bits = n_randint(state, 100) + 2; nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); if (nmod_mpoly_is_zero(f, ctx)) nmod_mpoly_one(f, ctx); for (j = 0; j < 10; j++) { ulong * exp1 = (ulong *) flint_malloc(nvars*sizeof(ulong)); ulong * exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); for (k = 0; k < nvars; k++) { slong bits = n_randint(state, FLINT_BITS) + 1; exp1[k] = n_randbits(state, bits); } index = n_randint(state, f->length); nmod_mpoly_set_term_exp_ui(f, index, exp1, ctx); if (!mpoly_monomials_valid_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents invalid"); if (mpoly_monomials_overflow_test(f->exps, f->length, f->bits, ctx->minfo)) flint_throw(FLINT_ERROR, "Polynomial exponents overflow"); nmod_mpoly_get_term_exp_ui(exp2, f, index, ctx); result = 1; for (k = 0; k < nvars; k++) { result = result && exp1[k] == exp2[k] && exp1[k] == nmod_mpoly_get_term_var_exp_ui(f, index, k, ctx); } if (!result) { flint_printf("FAIL\ncheck set and get match\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } flint_free(exp1); flint_free(exp2); } nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-get_term.c000066400000000000000000000040021461254215100207650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_get_term, state) { int i, j; /* Check a polynomial is the sum of its terms */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; mp_limb_t modulus; modulus = UWORD(2) + n_randint(state, -UWORD(2)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); nmod_mpoly_zero(h, ctx); for (j = nmod_mpoly_length(f, ctx) - 1; j >= 0; j--) { nmod_mpoly_get_term(g, f, j, ctx); nmod_mpoly_add(h, h, g, ctx); } if (!nmod_mpoly_equal(f, h, ctx)) { flint_printf("FAIL\nCheck a polynomial is the sum of its terms\ni = %wd\n", i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-get_term_monomial.c000066400000000000000000000044761461254215100226770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_get_term_monomial, state) { int i, j; /* Check getting a coeff by its monomial */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { mp_limb_t c, d; nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; slong len1, len2, len3; mp_limb_t modulus; modulus = UWORD(2) + n_randint(state, -UWORD(2)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); nmod_mpoly_repack_bits(h, f, f->bits + n_randint(state, 2*FLINT_BITS), ctx); for (j = nmod_mpoly_length(f, ctx) - 1; j >= 0; j--) { nmod_mpoly_get_term_monomial(g, f, j, ctx); nmod_mpoly_repack_bits(g, g, g->bits + n_randint(state, FLINT_BITS), ctx); d = nmod_mpoly_get_term_coeff_ui(f, j, ctx); c = nmod_mpoly_get_coeff_ui_monomial(h, g, ctx); if (c != d) { flint_printf("FAIL\nCheck getting a coeff by its monomial\ni = %wd\n", i); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-inflate_deflate.c000066400000000000000000000154331461254215100222770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_inflate_deflate, state) { int i, j, success; /* Check deflate undoes inflate */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { slong k; nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; fmpz * strides, * shifts; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; flint_bitcnt_t stride_bits, shift_bits; mp_limb_t modulus; modulus = FLINT_MAX(UWORD(2), n_randlimb(state)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); len3 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bits3 = n_randint(state, 100) + 2; stride_bits = n_randint(state, 100) + 2; shift_bits = n_randint(state, 100) + 2; strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(strides + k); fmpz_init(shifts + k); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts + k, state, shift_bits); fmpz_randtest_not_zero(strides + k, state, stride_bits); fmpz_abs(strides + k, strides + k); } nmod_mpoly_inflate(h, f, shifts, strides, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_deflate(g, h, shifts, strides, ctx); nmod_mpoly_assert_canonical(g, ctx); if (!nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check deflate undoes inflate\n" "i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_set(h, f, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_inflate(h, h, shifts, strides, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_deflate(h, h, shifts, strides, ctx); nmod_mpoly_assert_canonical(h, ctx); if (!nmod_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check deflate undoes inflate with aliasing\n" "i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(strides + k); fmpz_clear(shifts + k); } flint_free(strides); flint_free(shifts); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check deflating by deflation leaves trivial deflation */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { slong k; nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; fmpz * strides, * shifts; slong len1, len2, len3; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3; flint_bitcnt_t stride_bits, shift_bits; mp_limb_t modulus; modulus = FLINT_MAX(UWORD(2), n_randlimb(state)); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); len3 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; exp_bits3 = n_randint(state, 100) + 2; stride_bits = n_randint(state, 10) + 2; shift_bits = n_randint(state, 10) + 2; strides = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); shifts = flint_malloc(ctx->minfo->nvars*sizeof(fmpz)); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_init(strides + k); fmpz_init(shifts + k); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_randtest_unsigned(shifts + k, state, shift_bits); fmpz_randtest_unsigned(strides + k, state, stride_bits); } nmod_mpoly_inflate(h, f, shifts, strides, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_deflation(shifts, strides, h, ctx); nmod_mpoly_deflate(g, h, shifts, strides, ctx); nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_deflation(shifts, strides, g, ctx); nmod_mpoly_deflate(f, g, shifts, strides, ctx); nmod_mpoly_assert_canonical(f, ctx); success = nmod_mpoly_equal(f, g, ctx); for (k = 0; k < ctx->minfo->nvars; k++) { if (!fmpz_is_zero(shifts + k)) success = 0; if (fmpz_cmp_ui(strides + k, UWORD(1)) > 0) success = 0; } if (!success) { printf("FAIL\n"); flint_printf("Check deflating by deflation leaves trivial deflation\n" "i: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < ctx->minfo->nvars; k++) { fmpz_clear(strides + k); fmpz_clear(shifts + k); } flint_free(strides); flint_free(shifts); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-mpolyn_divides_threaded_pool.c000066400000000000000000000144141461254215100251050ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_support.h" #include "nmod_mpoly.h" #if defined(nmod_mpolyn_divides_threaded_pool) void _divides_check( const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, slong ii, slong jj, const char * name, flint_rand_t randstate) { int divides, ndivides; nmod_mpoly_ctx_t nctx; nmod_mpolyn_t An, Bn, Qn; nmod_mpoly_t Q, Qcheck; flint_bitcnt_t ABbits; ulong * shift, * stride; slong * perm; slong i, j, k; thread_pool_handle * handles; slong num_workers; if ( A->bits > FLINT_BITS || B->bits > FLINT_BITS || A->length == 0 || B->length == 0 || ctx->minfo->nvars <= 2) { return; } perm = (slong *) flint_malloc((ctx->minfo->nvars)*sizeof(slong)); shift = (ulong *) flint_malloc((ctx->minfo->nvars)*sizeof(ulong)); stride = (ulong *) flint_malloc((ctx->minfo->nvars)*sizeof(ulong)); nmod_mpoly_init(Q, ctx); nmod_mpoly_init(Qcheck, ctx); nmod_mpoly_ctx_init(nctx, ctx->minfo->nvars, ORD_LEX, ctx->mod.n); ABbits = FLINT_MAX(A->bits, B->bits); nmod_mpolyn_init(An, ABbits, nctx); nmod_mpolyn_init(Bn, ABbits, nctx); nmod_mpolyn_init(Qn, ABbits, nctx); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } /* randomize perm */ for (k = 0; k < ctx->minfo->nvars; k++) { slong t1, t2; i = n_randint(randstate, ctx->minfo->nvars - 1); j = i + n_randint(randstate, ctx->minfo->nvars - i); t1 = perm[i]; t2 = perm[j]; perm[i] = t2; perm[j] = t1; } nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(An, nctx, A, ctx, perm, shift, stride, NULL, 0); nmod_mpoly_to_mpolyn_perm_deflate_threaded_pool(Bn, nctx, B, ctx, perm, shift, stride, NULL, 0); num_workers = flint_request_threads(&handles, 9999); ndivides = nmod_mpolyn_divides_threaded_pool(Qn, An, Bn, nctx, handles, num_workers); flint_give_back_threads(handles, num_workers); divides = nmod_mpoly_divides(Q, A, B, ctx); if (divides != ndivides) { flint_printf("check divisibility i = %wd, j = %wd, %s\n", ii, jj, name); fflush(stdout); flint_abort(); } if (!divides) { goto cleanup; } nmod_mpoly_from_mpolyn_perm_inflate(Qcheck, ABbits, ctx, Qn, nctx, perm, shift, stride); if (!nmod_mpoly_equal(Q, Qcheck, ctx)) { flint_printf("check quotient i = %wd, j = %wd, %s\n", ii, jj, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpolyn_clear(An, nctx); nmod_mpolyn_clear(Bn, nctx); nmod_mpolyn_clear(Qn, nctx); nmod_mpoly_ctx_clear(nctx); nmod_mpoly_clear(Q, ctx); nmod_mpoly_clear(Qcheck, ctx); flint_free(perm); flint_free(shift); flint_free(stride); } TEST_FUNCTION_START(nmod_mpolyn_divides_threaded_pool, state) { slong i, j, max_threads = 5, tmul = 50; #ifdef _WIN32 tmul = 2; #endif /* Check (a*b)/b = a */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b; slong len1, len2; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); exp_bits = n_randint(state, 8) + 3; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); nmod_mpoly_randtest_bits(b, state, len2, exp_bits, ctx); nmod_mpoly_mul(a, a, b, ctx); _divides_check(a, b, ctx, i, j, "check (a*b)/b = a", state); } flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check (a*b + c)/b */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, c; slong len1, len2, len3; ulong exp_bound, exp_bound2; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); if (ctx->minfo->nvars < 1) { nmod_mpoly_ctx_clear(ctx); continue; } nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(c, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); len3 = n_randint(state, 30); exp_bound = 1 + 200/ctx->minfo->nvars; exp_bound2 = 1 + 100/ctx->minfo->nvars; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(a, state, len1, exp_bound, ctx); nmod_mpoly_randtest_bound(b, state, len2, exp_bound, ctx); nmod_mpoly_randtest_bound(c, state, len3, exp_bound2, ctx); nmod_mpoly_mul(a, a, b, ctx); nmod_mpoly_add(a, a, c, ctx); _divides_check(a, b, ctx, i, j, "check (a*b + c)/b", state); } flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(c, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(nmod_mpolyn_divides_threaded_pool, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif flint-3.1.3/src/nmod_mpoly/test/t-mpolyuu_divides.c000066400000000000000000000132571461254215100224140ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" void univar_divides_check( const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx, slong ii, slong jj, const char * name, flint_rand_t randstate) { int divides, udivides; nmod_mpoly_ctx_t uctx; nmod_mpolyu_t Au, Bu, Qu; nmod_mpoly_t Q, Qcheck; flint_bitcnt_t ABbits; ulong * shift, * stride; slong * perm; slong i, j, k; if ( A->bits > FLINT_BITS || B->bits > FLINT_BITS || A->length == 0 || B->length == 0 || ctx->minfo->nvars < 2) { return; } perm = (slong *) flint_malloc((ctx->minfo->nvars)*sizeof(slong)); shift = (ulong *) flint_malloc((ctx->minfo->nvars)*sizeof(ulong)); stride = (ulong *) flint_malloc((ctx->minfo->nvars)*sizeof(ulong)); nmod_mpoly_init(Q, ctx); nmod_mpoly_init(Qcheck, ctx); nmod_mpoly_ctx_init(uctx, ctx->minfo->nvars - 1, ORD_LEX, ctx->mod.n); ABbits = FLINT_MAX(A->bits, B->bits); nmod_mpolyu_init(Au, ABbits, uctx); nmod_mpolyu_init(Bu, ABbits, uctx); nmod_mpolyu_init(Qu, ABbits, uctx); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } /* randomize perm */ for (k = 0; k < ctx->minfo->nvars; k++) { slong t1, t2; i = n_randint(randstate, ctx->minfo->nvars - 1); j = i + n_randint(randstate, ctx->minfo->nvars - i); t1 = perm[i]; t2 = perm[j]; perm[i] = t2; perm[j] = t1; } nmod_mpoly_to_mpolyu_perm_deflate_threaded_pool(Au, uctx, A, ctx, perm, shift, stride, NULL, 0); nmod_mpoly_to_mpolyu_perm_deflate_threaded_pool(Bu, uctx, B, ctx, perm, shift, stride, NULL, 0); udivides = nmod_mpolyuu_divides(Qu, Au, Bu, 1, uctx); divides = nmod_mpoly_divides(Q, A, B, ctx); if (divides != udivides) { flint_printf("check univariate divisibility\n" "i = %wd, j = %wd, %s\n", ii, jj, name); fflush(stdout); flint_abort(); } if (!divides) { goto cleanup; } nmod_mpoly_from_mpolyu_perm_inflate(Qcheck, ABbits, ctx, Qu, uctx, perm, shift, stride); if (!nmod_mpoly_equal(Q, Qcheck, ctx)) { flint_printf("check univariate quotient\n" "i = %wd, j = %wd, %s\n", ii, jj, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpolyu_clear(Au, uctx); nmod_mpolyu_clear(Bu, uctx); nmod_mpolyu_clear(Qu, uctx); nmod_mpoly_ctx_clear(uctx); nmod_mpoly_clear(Q, ctx); nmod_mpoly_clear(Qcheck, ctx); flint_free(perm); flint_free(shift); flint_free(stride); } TEST_FUNCTION_START(nmod_mpoly_mpolyuu_divides, state) { slong i, j, tmul = 50; /* Check (a*b)/b = a */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b; slong len1, len2; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); exp_bits = n_randint(state, FLINT_BITS/2 - 2) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); nmod_mpoly_randtest_bits(b, state, len2, exp_bits, ctx); nmod_mpoly_mul(a, a, b, ctx); univar_divides_check(a, b, ctx, i, j, "univar Check (a*b)/b = a", state); } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check (a*b + c)/b */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, c; slong len1, len2, len3; flint_bitcnt_t exp_bits; mp_limb_t modulus; modulus = n_randint(state, (i % 10 == 0) ? 4: FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 15, modulus); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(c, ctx); len1 = n_randint(state, 20); len2 = n_randint(state, 20); len3 = n_randint(state, 30); exp_bits = n_randint(state, 8) + 3; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(a, state, len1, exp_bits, ctx); nmod_mpoly_randtest_bits(b, state, len2, exp_bits, ctx); nmod_mpoly_randtest_bits(c, state, len3, exp_bits, ctx); nmod_mpoly_mul(a, a, b, ctx); nmod_mpoly_add(a, a, c, ctx); univar_divides_check(a, b, ctx, i, j, "univar Check (a*b + c)/b", state); } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(c, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-mul.c000066400000000000000000000162271461254215100177700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_mul, state) { int i, j, result, max_threads = 5; int tmul = 10; #ifdef _WIN32 tmul = 1; #endif /* Check f*(g + h) = f*g + f*h with bit bound */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 100) + 2; exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; nmod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len2, exp_bits, ctx); nmod_mpoly_add(t1, g, h, ctx); nmod_mpoly_assert_canonical(t1, ctx); nmod_mpoly_mul(k1, f, t1, ctx); nmod_mpoly_assert_canonical(k1, ctx); nmod_mpoly_mul(t1, f, g, ctx); nmod_mpoly_assert_canonical(t1, ctx); nmod_mpoly_mul(t2, f, h, ctx); nmod_mpoly_assert_canonical(t2, ctx); nmod_mpoly_add(k2, t1, t2, ctx); nmod_mpoly_assert_canonical(k2, ctx); result = nmod_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*(g + h) = f*g + f*h with bit bound\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = 3 + n_randint(state, 1 + 100/n/n); exp_bound1 = 3 + n_randint(state, 1 + 100/n/n); exp_bound2 = 3 + n_randint(state, 1 + 100/n/n); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, n) + 2; j >= 0; j--) { len *= exp_bound + 1; len1 *= exp_bound1 + 1; len2 *= exp_bound2 + 1; len = FLINT_MIN(len, WORD(1000)); len1 = FLINT_MIN(len, WORD(1000)); len2 = FLINT_MIN(len, WORD(1000)); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul(f, f, g, ctx); nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); exp_bound = 3 + n_randint(state, 1 + 100/n/n); exp_bound1 = 3 + n_randint(state, 1 + 100/n/n); exp_bound2 = 3 + n_randint(state, 1 + 100/n/n); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, n) + 2; j >= 0; j--) { len *= exp_bound + 1; len1 *= exp_bound1 + 1; len2 *= exp_bound2 + 1; len = FLINT_MIN(len, WORD(1000)); len1 = FLINT_MIN(len, WORD(1000)); len2 = FLINT_MIN(len, WORD(1000)); } for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul(g, f, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-mul_array.c000066400000000000000000000141221461254215100211560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_mul_array, state) { int i, j, result; /* Check mul_array matches mul_johnson */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n, max_bound; mp_limb_t modulus; modulus = n_randint(state, -UWORD(2)) + UWORD(2); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); max_bound = ctx->minfo->ord == ORD_LEX ? 200 : 100; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = max_bound/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_mul_array(k, f, g, ctx); if (!result) { continue; } nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_array matches mul_johnson\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n, max_bound; mp_limb_t modulus; modulus = n_randint(state, -UWORD(2)) + UWORD(2); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_mul_array(f, f, g, ctx); if (!result) continue; nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n, max_bound; mp_limb_t modulus; modulus = n_randint(state, -UWORD(2)) + UWORD(2); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_mul_array(f, g, f, ctx); if (!result) continue; nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-mul_array_threaded.c000066400000000000000000000151101461254215100230140ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_mul_array_threaded, state) { int i, j, result, max_threads = 5; int tmul = 50; #ifdef _WIN32 tmul = 1; #endif /* Check mul_array_threaded matches mul_johnson */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n, max_bound; mp_limb_t modulus; modulus = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 5, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); max_bound = ctx->minfo->ord == ORD_LEX ? 200 : 100; n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = max_bound/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_mul_array_threaded(k, f, g, ctx); if (!result) { continue; } nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_array_threaded matches mul_johnson\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n, max_bound; mp_limb_t modulus; modulus = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_mul_array_threaded(f, f, g, ctx); if (!result) continue; nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong n, max_bound; mp_limb_t modulus; modulus = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 200/n/n; exp_bound = n_randint(state, max_bound) + 1; exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); result = nmod_mpoly_mul_array_threaded(g, f, g, ctx); if (!result) continue; nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second argument\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-mul_dense.c000066400000000000000000000144701461254215100211440ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_mul_dense, state) { int i, j, result, success; /* Check mul_dense matches mul_johnson */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; slong len, len1, len2; slong max_bound, exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_randtest_bound(k, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); success = nmod_mpoly_mul_dense(k, f, g, ctx); if (!success) continue; nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_dense matches mul_johnson\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; slong max_bound, exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); success = nmod_mpoly_mul_dense(f, f, g, ctx); if (!success) continue; nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; slong max_bound, exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; slong n; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 200); len1 = n_randint(state, 200); len2 = n_randint(state, 200); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); max_bound = 1 + 100/n/n; exp_bound = UWORD(1) << (FLINT_BITS - 1); exp_bound1 = n_randint(state, max_bound) + 1; exp_bound2 = n_randint(state, max_bound) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(f, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(g, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(h, state, len, exp_bound, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); success = nmod_mpoly_mul_dense(f, g, f, ctx); if (!success) continue; nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-mul_heap_threaded.c000066400000000000000000000160171461254215100226220ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_mul_heap_threaded, state) { slong i, j, result, max_threads = 5; slong tmul = 10; #ifdef _WIN32 tmul = 2; #endif { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h1, h2; const char * vars[] = {"x","y","z","t","u"}; nmod_mpoly_ctx_init(ctx, 5, ORD_LEX, -UWORD(1)); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h1, ctx); nmod_mpoly_init(h2, ctx); nmod_mpoly_set_str_pretty(f, "(1+x+y+2*z^2+3*t^3+5*u^5)^6", vars, ctx); nmod_mpoly_set_str_pretty(g, "(1+u+t+2*z^2+3*y^3+5*x^5)^6", vars, ctx); nmod_mpoly_mul(h1, f, g, ctx); flint_set_num_threads(2); nmod_mpoly_mul_heap_threaded(h2, f, g, ctx); if (!nmod_mpoly_equal(h1, h2, ctx)) { printf("FAIL\n"); flint_printf("Check simple example\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h1, ctx); nmod_mpoly_clear(h2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check mul_heap_threaded matches mul_johnson */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul_heap_threaded(k, f, g, ctx); nmod_mpoly_assert_canonical(k, ctx); result = nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check mul_heap_threaded matches mul_johnson\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul_heap_threaded(f, f, g, ctx); nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul_heap_threaded(g, f, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing first argument\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-mul_johnson.c000066400000000000000000000145011461254215100215170ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_mul_johnson, state) { slong tmul = 8; int i, j, result; /* Check f*(g + h) = f*g + f*h */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k1, k2, t1, t2; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k1, ctx); nmod_mpoly_init(k2, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; nmod_mpoly_randtest_bits(k1, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k2, state, len, exp_bits, ctx); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len2, exp_bits2, ctx); nmod_mpoly_add(t1, g, h, ctx); nmod_mpoly_assert_canonical(t1, ctx); nmod_mpoly_mul_johnson(k1, f, t1, ctx); nmod_mpoly_assert_canonical(k1, ctx); nmod_mpoly_mul_johnson(t1, f, g, ctx); nmod_mpoly_assert_canonical(t1, ctx); nmod_mpoly_mul_johnson(t2, f, h, ctx); nmod_mpoly_assert_canonical(t2, ctx); nmod_mpoly_add(k2, t1, t2, ctx); nmod_mpoly_assert_canonical(k2, ctx); result = nmod_mpoly_equal(k1, k2, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*(g + h) = f*g + f*h\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k1, ctx); nmod_mpoly_clear(k2, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing first argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul_johnson(f, f, g, ctx); nmod_mpoly_assert_canonical(f, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing second argument */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_assert_canonical(h, ctx); nmod_mpoly_mul_johnson(g, f, g, ctx); nmod_mpoly_assert_canonical(g, ctx); result = nmod_mpoly_equal(h, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing second arg\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-pow_rmul.c000066400000000000000000000101151461254215100210250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" /* Defined in t-pow_ui.c and t-pow_rmul.c */ #ifndef nmod_mpoly_pow_naive #define nmod_mpoly_pow_naive nmod_mpoly_pow_naive void nmod_mpoly_pow_naive(nmod_mpoly_t res, nmod_mpoly_t f, slong n, nmod_mpoly_ctx_t ctx) { if (n == 0) nmod_mpoly_set_ui(res, 1, ctx); else if (f->length == 0) nmod_mpoly_zero(res, ctx); else if (n == 1) nmod_mpoly_set(res, f, ctx); else { slong i; nmod_mpoly_t pow; nmod_mpoly_init(pow, ctx); nmod_mpoly_set(pow, f, ctx); for (i = 1; i < n - 1; i++) nmod_mpoly_mul_johnson(pow, pow, f, ctx); nmod_mpoly_mul_johnson(res, pow, f, ctx); nmod_mpoly_clear(pow, ctx); } } #endif TEST_FUNCTION_START(nmod_mpoly_pow_rmul, state) { slong i, j; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b; nmod_mpoly_ctx_init(ctx, 20, ORD_LEX, 4); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_set_str_pretty(a, "1", NULL, ctx); nmod_mpoly_set_str_pretty(b, "2 + 2*x1 + 2*x2 + 2*x3", NULL, ctx); nmod_mpoly_pow_rmul(a, b, 3, ctx); if (nmod_mpoly_is_zero(b, ctx) || !nmod_mpoly_is_zero(a, ctx)) { flint_printf("FAIL: Check simple example\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; ulong pow_bound; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randbits(state, n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits = n_randint(state, 20) + 2; exp_bits1 = n_randint(state, 20) + 2; exp_bits2 = n_randint(state, 20) + 2; pow_bound = 250/(len1+1); pow_bound = pow_bound/FLINT_MAX(WORD(1), ctx->minfo->nvars); pow_bound = FLINT_MAX(pow_bound, UWORD(5)); for (j = 0; j < 10; j++) { slong pow; pow = n_randint(state, pow_bound); nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_pow_rmul(g, f, pow, ctx); nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_pow_naive(h, f, pow, ctx); nmod_mpoly_assert_canonical(h, ctx); if (!nmod_mpoly_equal(g, h, ctx)) { flint_printf("FAIL: Check pow_ui against pow_naive\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_pow_rmul(f, f, pow, ctx); nmod_mpoly_assert_canonical(f, ctx); if (!nmod_mpoly_equal(g, f, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-pow_ui.c000066400000000000000000000077771461254215100205070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" /* Defined in t-pow_ui.c and t-pow_rmul.c */ #ifndef nmod_mpoly_pow_naive #define nmod_mpoly_pow_naive nmod_mpoly_pow_naive void nmod_mpoly_pow_naive(nmod_mpoly_t res, nmod_mpoly_t f, slong n, nmod_mpoly_ctx_t ctx) { if (n == 0) nmod_mpoly_set_ui(res, 1, ctx); else if (f->length == 0) nmod_mpoly_zero(res, ctx); else if (n == 1) nmod_mpoly_set(res, f, ctx); else { slong i; nmod_mpoly_t pow; nmod_mpoly_init(pow, ctx); nmod_mpoly_set(pow, f, ctx); for (i = 1; i < n - 1; i++) nmod_mpoly_mul_johnson(pow, pow, f, ctx); nmod_mpoly_mul_johnson(res, pow, f, ctx); nmod_mpoly_clear(pow, ctx); } } #endif TEST_FUNCTION_START(nmod_mpoly_pow_ui, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; ulong pow_bound; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randbits(state, n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits = n_randint(state, 20) + 2; exp_bits1 = n_randint(state, 20) + 2; exp_bits2 = n_randint(state, 20) + 2; if (n_is_prime(nmod_mpoly_ctx_modulus(ctx))) pow_bound = 5000/(FLINT_BIT_COUNT(modulus)+1); else pow_bound = 200; pow_bound = pow_bound/(len1+1); pow_bound = pow_bound/FLINT_MAX(WORD(1), ctx->minfo->nvars); pow_bound = FLINT_MAX(pow_bound, UWORD(5)); for (j = 0; j < 10; j++) { slong pow; pow = n_randint(state, pow_bound); nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); if (!nmod_mpoly_pow_ui(g, f, pow, ctx)) { flint_printf("FAIL\n"); flint_printf("Check pow_ui success\ni = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(g, ctx); nmod_mpoly_pow_naive(h, f, pow, ctx); nmod_mpoly_assert_canonical(h, ctx); if (!nmod_mpoly_equal(g, h, ctx)) { flint_printf("FAIL: Check pow_ui against pow_naive\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } if (!nmod_mpoly_pow_ui(f, f, pow, ctx)) { flint_printf("FAIL: Check pow_ui success\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_assert_canonical(f, ctx); if (!nmod_mpoly_equal(g, f, ctx)) { flint_printf("FAIL: Check aliasing\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-push_term_ui_fmpz.c000066400000000000000000000074521461254215100227320ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_push_term_ui_fmpz, state) { slong i, j, k; /* Check pushback matches add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f1, f2, f3, m; flint_bitcnt_t exp_bits; fmpz **exp, **exp2, *exp3; slong len, nvars; mp_limb_t c, c2; mp_limb_t modulus; modulus = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f1, ctx); nmod_mpoly_init(f2, ctx); nmod_mpoly_init(f3, ctx); nmod_mpoly_init(m, ctx); nvars = nmod_mpoly_ctx_nvars(ctx); exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *)flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *)flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); fmpz_init(exp3 + k); } len = n_randint(state, 20); exp_bits = n_randint(state, 200); nmod_mpoly_zero(f1, ctx); nmod_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ c = n_randlimb(state); for (k = 0; k < nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits); fmpz_set(exp3 + k, exp[k]); } /* add it to f1 */ nmod_mpoly_zero(m, ctx); nmod_mpoly_set_coeff_ui_fmpz(m, c, exp, ctx); nmod_mpoly_add(f1, f1, m, ctx); nmod_mpoly_assert_canonical(f1, ctx); /* push it back on f2 and f3*/ nmod_mpoly_push_term_ui_fmpz(f2, c, exp, ctx); nmod_mpoly_push_term_ui_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ c2 = nmod_mpoly_get_term_coeff_ui(f2, nmod_mpoly_length(f2, ctx) - 1, ctx); nmod_mpoly_get_term_exp_fmpz(exp2, f2, nmod_mpoly_length(f2, ctx) - 1, ctx); if ((c % modulus) != c2) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (!fmpz_equal(exp[k], exp2[k])) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } } } nmod_mpoly_sort_terms(f2, ctx); nmod_mpoly_combine_like_terms(f2, ctx); nmod_mpoly_assert_canonical(f2, ctx); nmod_mpoly_sort_terms(f3, ctx); nmod_mpoly_combine_like_terms(f3, ctx); nmod_mpoly_assert_canonical(f3, ctx); if (!nmod_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushed polynomial matches add\ni=%wd\n", i, j); fflush(stdout); flint_abort(); } if (!nmod_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check pushed ffmpz polynomial matches add\ni=%wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f1, ctx); nmod_mpoly_clear(f2, ctx); nmod_mpoly_clear(f3, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); fmpz_clear(exp3 + k); } flint_free(exp3); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-push_term_ui_ui.c000066400000000000000000000062471461254215100223740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_push_term_ui_ui, state) { slong i, j, k; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f1, f2, m; flint_bitcnt_t exp_bits; ulong * exp, * exp2; slong len, nvars; mp_limb_t c, c2; mp_limb_t modulus; modulus = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f1, ctx); nmod_mpoly_init(f2, ctx); nmod_mpoly_init(m, ctx); nvars = nmod_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 20); exp_bits = n_randint(state, FLINT_BITS) + 1; nmod_mpoly_zero(f1, ctx); nmod_mpoly_zero(f2, ctx); for (j = 0; j < len; j++) { /* get random term */ c = n_randlimb(state); for (k = 0; k < nvars; k++) exp[k] = n_randtest_bits(state, n_randint(state, exp_bits) + 1); /* add it to f1 */ nmod_mpoly_zero(m, ctx); nmod_mpoly_set_coeff_ui_ui(m, c, exp, ctx); nmod_mpoly_add(f1, f1, m, ctx); /* push it back on f2 */ nmod_mpoly_push_term_ui_ui(f2, c, exp, ctx); /* make sure last term matches */ c2 = nmod_mpoly_get_term_coeff_ui(f2, nmod_mpoly_length(f2, ctx) - 1, ctx); nmod_mpoly_get_term_exp_ui(exp2, f2, nmod_mpoly_length(f2, ctx) - 1, ctx); if ((c % modulus) != c2) { printf("FAIL\n"); flint_printf("Check pushed coefficient matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } for (k = 0; k < nvars; k++) { if (exp[k] != exp2[k]) { printf("FAIL\n"); flint_printf("Check pushed exponent matches\ni=%wd, j=%wd\n", i, j); fflush(stdout); flint_abort(); } } } nmod_mpoly_sort_terms(f2, ctx); nmod_mpoly_combine_like_terms(f2, ctx); nmod_mpoly_assert_canonical(f2, ctx); if (!nmod_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushback matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f1, ctx); nmod_mpoly_clear(f2, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-quadratic_root.c000066400000000000000000000070331461254215100222060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" void _test_root( nmod_mpoly_t x, const nmod_mpoly_t a, const nmod_mpoly_t b, const nmod_mpoly_ctx_t ctx, int sol_exists) { int success, success2; nmod_mpoly_t s, t; nmod_mpoly_init(s, ctx); nmod_mpoly_init(t, ctx); success = nmod_mpoly_quadratic_root(x, a, b, ctx); if (sol_exists && !success) { flint_printf("FAIL: solution exists but root failed\n"); fflush(stdout); flint_abort(); } if (success) { nmod_mpoly_add(t, x, a, ctx); nmod_mpoly_mul(s, t, x, ctx); if (!nmod_mpoly_equal(s, b, ctx)) { flint_printf("FAIL: reported solution is not a solution\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_set(t, a, ctx); success2 = nmod_mpoly_quadratic_root(t, t, b, ctx); if (success != success2 || (success && !nmod_mpoly_equal(x, t, ctx))) { flint_printf("FAIL: Check aliasing first argument\n"); fflush(stdout); flint_abort(); } nmod_mpoly_set(t, b, ctx); success2 = nmod_mpoly_quadratic_root(t, a, t, ctx); if (success != success2 || (success && !nmod_mpoly_equal(x, t, ctx))) { flint_printf("FAIL: Check aliasing second argument\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(s, ctx); nmod_mpoly_clear(t, ctx); } TEST_FUNCTION_START(nmod_mpoly_quadratic_root, state) { slong i, j, tmul = 20; /* Check sqrt(f^2) = +-f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, a, b, x; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); if (i % 2) modulus = 2; nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(x, ctx); for (j = 0; j < 5; j++) { len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 100) + 1; exp_bits1 = n_randint(state, 100) + 1; nmod_mpoly_randtest_bits(a, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); nmod_mpoly_add(b, f, a, ctx); nmod_mpoly_mul(b, b, f, ctx); _test_root(x, a, b, ctx, 1); len = n_randint(state, 50); len1 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 20) + 1; exp_bits1 = n_randint(state, 20) + 1; nmod_mpoly_randtest_bits(a, state, len1, 10, ctx); nmod_mpoly_randtest_bits(b, state, len, 10, ctx); _test_root(x, a, b, ctx, 0); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(x, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-repack_bits.c000066400000000000000000000150251461254215100214540ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_repack_bits, state) { slong i, j; int success; /* Check packing up */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2, newbits; nmod_mpoly_ctx_init_rand(ctx, state, 20, n_randint(state, 10000) + 2); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = nmod_mpoly_repack_bits(f, g, newbits, ctx); nmod_mpoly_assert_canonical(f, ctx); if (!success || !nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing up\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = nmod_mpoly_repack_bits(g, g, newbits, ctx); nmod_mpoly_assert_canonical(g, ctx); if (!success || !nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing up with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check repacking down up */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2, newbits; nmod_mpoly_ctx_init_rand(ctx, state, 20, n_randint(state, 10000) + 2); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len2, exp_bits2, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); nmod_mpoly_repack_bits(f, g, newbits, ctx); nmod_mpoly_assert_canonical(f, ctx); newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = nmod_mpoly_repack_bits(h, f, newbits, ctx); nmod_mpoly_assert_canonical(h, ctx); if (!success || !nmod_mpoly_equal(h, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check repacking down\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } newbits = g->bits + n_randint(state, 2*FLINT_BITS); newbits = mpoly_fix_bits(newbits, ctx->minfo); success = nmod_mpoly_repack_bits(f, f, newbits, ctx); nmod_mpoly_assert_canonical(f, ctx); if (!success || !nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check repacking down with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check packing down */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2, newbits; nmod_mpoly_ctx_init_rand(ctx, state, 20, n_randint(state, 10000) + 2); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); if (g->bits <= MPOLY_MIN_BITS) continue; newbits = n_randint(state, g->bits - MPOLY_MIN_BITS) + MPOLY_MIN_BITS; newbits = mpoly_fix_bits(newbits, ctx->minfo); success = nmod_mpoly_repack_bits(f, g, newbits, ctx); nmod_mpoly_assert_canonical(f, ctx); if (success && !nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing down\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_set(f, g, ctx); newbits = n_randint(state, g->bits - MPOLY_MIN_BITS) + MPOLY_MIN_BITS; newbits = mpoly_fix_bits(newbits, ctx->minfo); success = nmod_mpoly_repack_bits(g, g, newbits, ctx); nmod_mpoly_assert_canonical(g, ctx); if (success && !nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL\n"); flint_printf("Check packing down with aliasing\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-resize.c000066400000000000000000000060401461254215100204640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_resize, state) { slong i, j, k; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f1, f2, f3, m; flint_bitcnt_t exp_bits; ulong * exp, * exp2; slong len, nvars; mp_limb_t c; mp_limb_t modulus; modulus = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f1, ctx); nmod_mpoly_init(f2, ctx); nmod_mpoly_init(f3, ctx); nmod_mpoly_init(m, ctx); nvars = nmod_mpoly_ctx_nvars(ctx); exp = (ulong *) flint_malloc(nvars*sizeof(ulong)); exp2 = (ulong *) flint_malloc(nvars*sizeof(ulong)); len = n_randint(state, 200); exp_bits = n_randint(state, FLINT_BITS) + 1; nmod_mpoly_zero(f1, ctx); nmod_mpoly_zero(f2, ctx); nmod_mpoly_zero(f3, ctx); for (j = 0; j < len; j++) { /* get random term */ c = n_randlimb(state); for (k = 0; k < nvars; k++) exp[k] = n_randtest_bits(state, n_randint(state, exp_bits) + 1); /* add it to f1 */ nmod_mpoly_zero(m, ctx); nmod_mpoly_set_coeff_ui_ui(m, c, exp, ctx); nmod_mpoly_add(f1, f1, m, ctx); /* push it back on f2 */ nmod_mpoly_push_term_ui_ui(f2, c, exp, ctx); /* manually push it on f3 */ nmod_mpoly_resize(f3, j + 1 + n_randint(state, 10), ctx); nmod_mpoly_set_term_coeff_ui(f3, j, c, ctx); nmod_mpoly_set_term_exp_ui(f3, j, exp, ctx); } nmod_mpoly_sort_terms(f2, ctx); nmod_mpoly_combine_like_terms(f2, ctx); nmod_mpoly_assert_canonical(f2, ctx); nmod_mpoly_sort_terms(f3, ctx); nmod_mpoly_combine_like_terms(f3, ctx); nmod_mpoly_assert_canonical(f3, ctx); if (!nmod_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); flint_printf("Check pushback matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } if (!nmod_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check resize+setterm matches add\ni=%wd\n",i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f1, ctx); nmod_mpoly_clear(f2, ctx); nmod_mpoly_clear(f3, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_ctx_clear(ctx); flint_free(exp2); flint_free(exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-resultant_discriminant.c000066400000000000000000000206411461254215100237530ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_resultant_discriminant, state) { slong i, j; /* Check quadratic polynomial */ { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, d, d1; const char * vars[] = {"x","a","b","c"}; nmod_mpoly_ctx_init(ctx, 4, ORD_DEGLEX, 100003); nmod_mpoly_init(f, ctx); nmod_mpoly_init(d, ctx); nmod_mpoly_init(d1, ctx); nmod_mpoly_set_str_pretty(f, "a^10*x^2 + b^100*x + c^100000000000000000000", vars, ctx); nmod_mpoly_set_str_pretty(d1, "b^200 - 4*a^10*c^100000000000000000000", vars, ctx); if (!nmod_mpoly_discriminant(d, f, 0, ctx)) { flint_printf("FAIL: could not compute quadratic discriminant\n"); fflush(stdout); flint_abort(); } if (!nmod_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(d, ctx); nmod_mpoly_clear(d1, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check univariate resultant */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, r; nmod_poly_t au, bu; mp_limb_t ru; slong len1, len2, exp_bound1, exp_bound2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init(ctx, 1, mpoly_ordering_randtest(state), modulus); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(r, ctx); nmod_poly_init(au, nmod_mpoly_ctx_modulus(ctx)); nmod_poly_init(bu, nmod_mpoly_ctx_modulus(ctx)); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 50) + 1; exp_bound2 = n_randint(state, 50) + 1; nmod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); nmod_mpoly_get_nmod_poly(au, a, 0, ctx); nmod_mpoly_get_nmod_poly(bu, b, 0, ctx); ru = nmod_poly_resultant(au, bu); if (!nmod_mpoly_resultant(r, a, b, 0, ctx) || !nmod_mpoly_equal_ui(r, ru, ctx)) { flint_printf("FAIL: Check univariate resultant \n"); flint_printf("i: %wd\n",i); fflush(stdout); flint_abort(); } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(r, ctx); nmod_poly_clear(au); nmod_poly_clear(bu); nmod_mpoly_ctx_clear(ctx); } /* Check res(a*b,c) = res(a,c)*res(b,c) */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, c, ab, ra, rb, rab, p; slong len1, len2, len3, exp_bound1, exp_bound2, exp_bound3; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 3, modulus); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(c, ctx); nmod_mpoly_init(ab, ctx); nmod_mpoly_init(ra, ctx); nmod_mpoly_init(rb, ctx); nmod_mpoly_init(rab, ctx); nmod_mpoly_init(p, ctx); len1 = n_randint(state, 15); len2 = n_randint(state, 15); len3 = n_randint(state, 15); exp_bound1 = n_randint(state, 5) + 1; exp_bound2 = n_randint(state, 5) + 1; exp_bound3 = n_randint(state, 5) + 1; nmod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); nmod_mpoly_randtest_bound(c, state, len3, exp_bound3, ctx); for (j = 0; j < nmod_mpoly_ctx_nvars(ctx); j++) { nmod_mpoly_mul(ab, a, b, ctx); if (!nmod_mpoly_resultant(ra, a, c, j, ctx)) continue; nmod_mpoly_assert_canonical(ra, ctx); if (!nmod_mpoly_resultant(rb, b, c, j, ctx)) continue; nmod_mpoly_assert_canonical(rb, ctx); if (!nmod_mpoly_resultant(rab, ab, c, j, ctx)) continue; nmod_mpoly_assert_canonical(rab, ctx); nmod_mpoly_mul(p, ra, rb, ctx); if (!nmod_mpoly_equal(p,rab,ctx)) { flint_printf("FAIL: Check res(a*b,c) = res(a,c)*res(b,c)\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(c, ctx); nmod_mpoly_clear(ab, ctx); nmod_mpoly_clear(ra, ctx); nmod_mpoly_clear(rb, ctx); nmod_mpoly_clear(rab, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2 */ for (i = 0; i < 30 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, ab, r, da, db, dab, p; slong len1, len2, exp_bound1, exp_bound2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 3, modulus); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(ab, ctx); nmod_mpoly_init(da, ctx); nmod_mpoly_init(db, ctx); nmod_mpoly_init(dab, ctx); nmod_mpoly_init(r, ctx); nmod_mpoly_init(p, ctx); len1 = n_randint(state, 15); len2 = n_randint(state, 15); exp_bound1 = n_randint(state, 4) + 1; exp_bound2 = n_randint(state, 5) + 1; nmod_mpoly_randtest_bound(a, state, len1, exp_bound1, ctx); nmod_mpoly_randtest_bound(b, state, len2, exp_bound2, ctx); for (j = 0; j < nmod_mpoly_ctx_nvars(ctx); j++) { if (nmod_mpoly_degree_si(a, j, ctx) < 1) continue; if (nmod_mpoly_degree_si(b, j, ctx) < 1) continue; nmod_mpoly_mul(ab, a, b, ctx); if (!nmod_mpoly_resultant(r, a, b, j, ctx)) continue; if (!nmod_mpoly_discriminant(da, a, j, ctx)) continue; if (!nmod_mpoly_discriminant(db, b, j, ctx)) continue; if (!nmod_mpoly_discriminant(dab, ab, j, ctx)) continue; nmod_mpoly_mul(p, da, db, ctx); nmod_mpoly_mul(p, p, r, ctx); nmod_mpoly_mul(p, p, r, ctx); if (!nmod_mpoly_equal(dab, p, ctx)) { flint_printf("FAIL: Check disc(a*b) = disc(a)*disc(b)*res(a,b)^2\n"); flint_printf("a: "); nmod_mpoly_print_pretty(a, NULL, ctx); flint_printf("\n"); flint_printf("b: "); nmod_mpoly_print_pretty(b, NULL, ctx); flint_printf("\n"); flint_printf("disc(a*b): "); nmod_mpoly_print_pretty(dab, NULL, ctx); flint_printf("\n"); flint_printf("disc(a): "); nmod_mpoly_print_pretty(da, NULL, ctx); flint_printf("\n"); flint_printf("disc(b): "); nmod_mpoly_print_pretty(db, NULL, ctx); flint_printf("\n"); flint_printf("res(a, b): "); nmod_mpoly_print_pretty(r, NULL, ctx); flint_printf("\n"); flint_printf("i: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(ab, ctx); nmod_mpoly_clear(da, ctx); nmod_mpoly_clear(db, ctx); nmod_mpoly_clear(dab, ctx); nmod_mpoly_clear(r, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-scalar_addmul_ui.c000066400000000000000000000057521461254215100224640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_scalar_addmul_ui, state) { slong i, j; for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; mp_limb_t modulus; slong len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = FLINT_MAX(2, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { mp_limb_t c = n_randlimb(state); nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); nmod_mpoly_scalar_addmul_ui(f, g, h, c, ctx); nmod_mpoly_scalar_mul_ui(k, h, c, ctx); nmod_mpoly_add(k, k, g, ctx); if (!nmod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: check definition\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_set(k, g, ctx); nmod_mpoly_scalar_addmul_ui(k, k, h, c, ctx); if (!nmod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: check aliasing first argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_set(k, h, ctx); nmod_mpoly_scalar_addmul_ui(k, g, k, c, ctx); if (!nmod_mpoly_equal(f, k, ctx)) { flint_printf("FAIL: check aliasing second argument\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-scalar_mul_ui.c000066400000000000000000000136731461254215100220140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_scalar_mul_ui, state) { int i, j, result; /* Check (f*a)*b = f*(a*b) */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; ulong a, b, c; slong len1, len2, len3, len4; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3, exp_bits4; mp_limb_t modulus; modulus = n_randbits(state, 1 + n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 2, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); len4 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; exp_bits4 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); nmod_mpoly_randtest_bits(k, state, len4, exp_bits4, ctx); a = n_randtest(state); b = n_randtest(state); nmod_mpoly_scalar_mul_ui(g, f, a, ctx); nmod_mpoly_scalar_mul_ui(h, g, b, ctx); NMOD_RED(a, a, ctx->mod); NMOD_RED(b, b, ctx->mod); c = nmod_mul(a, b, ctx->mod); nmod_mpoly_scalar_mul_ui(k, f, c, ctx); result = nmod_mpoly_equal(h, k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b)\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_scalar_mul_ui(g, f, a, ctx); nmod_mpoly_scalar_mul_ui(g, g, b, ctx); nmod_mpoly_scalar_mul_ui(f, f, c, ctx); result = nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check (f*a)*b = f*(a*b) with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check f*a*inv(a) = f */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h, k; ulong a, b; slong len1, len2, len3, len4; flint_bitcnt_t exp_bits1, exp_bits2, exp_bits3, exp_bits4; mp_limb_t modulus; modulus = n_randbits(state, 1 + n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 2, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_init(k, ctx); len1 = n_randint(state, 100); len2 = n_randint(state, 100); len3 = n_randint(state, 100); len4 = n_randint(state, 100); exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; exp_bits3 = n_randint(state, 200) + 2; exp_bits4 = n_randint(state, 200) + 2; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_randtest_bits(h, state, len3, exp_bits3, ctx); nmod_mpoly_randtest_bits(k, state, len4, exp_bits4, ctx); a = n_randtest(state); nmod_mpoly_scalar_mul_ui(g, f, a, ctx); NMOD_RED(a, a, ctx->mod); if (n_gcd(a, ctx->mod.n) != UWORD(1)) continue; b = nmod_inv(a, ctx->mod); nmod_mpoly_scalar_mul_ui(h, g, b, ctx); result = nmod_mpoly_equal(h, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*a*inv(a) = f\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_scalar_mul_ui(g, f, a, ctx); nmod_mpoly_scalar_mul_ui(g, g, b, ctx); result = nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check f*a*inv(a) = f with aliasing\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-sqrt.c000066400000000000000000000134401461254215100201560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_sqrt, state) { slong i, j, tmul = 10; /* Check sqrt(f^2) = +-f */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr; mp_limb_t modulus; modulus = n_randint(state, (i % 4 == 0) ? 4 : FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 5) + 1; exp_bits1 = n_randint(state, 5) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_mul(g, f, f, ctx); nmod_mpoly_assert_canonical(g, ctx); sqr = nmod_mpoly_sqrt(h, g, ctx); nmod_mpoly_assert_canonical(h, ctx); if (!sqr) { flint_printf("FAIL: Check sqrt(f^2) returns 1\n"); fflush(stdout); flint_abort(); } if (!nmod_mpoly_equal(h, f, ctx) && !(nmod_mpoly_neg(h, h, ctx), nmod_mpoly_equal(h, f, ctx))) { flint_printf("FAIL: Check sqrt(f^2) = +-f\n"); flint_printf("i = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check sqrt(random) */ for (i = 0; i < 2*tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr; mp_limb_t modulus; modulus = n_randint(state, (i % 4 == 0) ? 4 : FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100) + 1; exp_bits = n_randint(state, 200) + 1; /* low bits: sqrt(random) is less reliable in positive char */ exp_bits1 = n_randint(state, 100) + 1; for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); sqr = nmod_mpoly_sqrt(g, f, ctx); nmod_mpoly_assert_canonical(g, ctx); if (sqr) { nmod_mpoly_mul(g, g, g, ctx); if (!nmod_mpoly_equal(g, f, ctx)) { flint_printf("FAIL: Check sqrt(random)\n"); flint_printf("i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } else if (!nmod_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check aliasing of square root with input */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; slong len, len1; flint_bitcnt_t exp_bits, exp_bits1; int sqr1, sqr2; mp_limb_t modulus; modulus = n_randint(state, (i % 4 == 0) ? 4 : FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); len = n_randint(state, 100); len1 = n_randint(state, 100); exp_bits = n_randint(state, 200) + 1; exp_bits1 = n_randint(state, 200) + 1; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len, exp_bits, ctx); nmod_mpoly_randtest_bits(h, state, len, exp_bits, ctx); nmod_mpoly_mul(g, f, f, ctx); nmod_mpoly_assert_canonical(g, ctx); sqr1 = nmod_mpoly_sqrt(h, g, ctx); nmod_mpoly_assert_canonical(h, ctx); sqr2 = nmod_mpoly_sqrt(g, g, ctx); nmod_mpoly_assert_canonical(g, ctx); if (sqr1 != sqr2 || !nmod_mpoly_equal(g, h, ctx)) { printf("FAIL: Check aliasing\n"); flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-term_content.c000066400000000000000000000072541461254215100216740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_term_content, state) { int i, j, result; /* Check division by content leaves trivial content */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, k; slong len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; nmod_mpoly_ctx_init_rand(ctx, state, 20, 2 + n_randint(state, -UWORD(2))); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(k, ctx); len = n_randint(state, 50); len1 = n_randint(state, 50); len2 = n_randint(state, 50) + 1; exp_bits = n_randint(state, 200) + 2; exp_bits1 = n_randint(state, 200) + 2; exp_bits2 = n_randint(state, 200) + 2; nmod_mpoly_randtest_bits(k, state, len, exp_bits, ctx); for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_term_content(f, g, ctx); if (nmod_mpoly_is_zero(g, ctx)) { result = nmod_mpoly_is_zero(f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check zero\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } else { result = nmod_mpoly_length(f, ctx) == 1; if (!result) { printf("FAIL\n"); flint_printf("Check content is monomial\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } result = f->coeffs[0] == 1; if (!result) { printf("FAIL\n"); flint_printf("Check content is monic\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } result = nmod_mpoly_divides(k, g, f, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check content divides\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } nmod_mpoly_term_content(k, k, ctx); result = nmod_mpoly_is_one(k, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check quotient is primitive\ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_term_content(g, g, ctx); result = nmod_mpoly_equal(f, g, ctx); if (!result) { printf("FAIL\n"); flint_printf("Check aliasing \ni = %wd, j = %wd\n", i ,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-total_degree.c000066400000000000000000000123741461254215100216300ustar00rootroot00000000000000/* Copyright (C) 2017 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" /* foolproof way to check totdeg_check is correct */ void _check_total_degree(const fmpz_t totdeg_check, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { fmpz_t totdeg; fmpz_init(totdeg); mpoly_total_degree_fmpz_ref(totdeg, A->exps, A->length, A->bits, ctx->minfo); if (!fmpz_equal(totdeg_check, totdeg)) flint_throw(FLINT_ERROR, "Total degree is wrong"); fmpz_clear(totdeg); } TEST_FUNCTION_START(nmod_mpoly_total_degree, state) { int i, j; /* Check total_degree does not go up under addition */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randbits(state, n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_add(h, f, g, ctx); nmod_mpoly_total_degree_fmpz(hdeg, h, ctx); nmod_mpoly_total_degree_fmpz(fdeg, f, ctx); nmod_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if ((fmpz_cmp(hdeg, fdeg) > 0) && (fmpz_cmp(hdeg, gdeg) > 0)) { printf("FAIL\n"); flint_printf("Check degree does not go up under addition\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } /* Check total_degree adds under multiplication */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { int ok; nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; fmpz_t fdeg, gdeg, hdeg; slong len1, len2; flint_bitcnt_t exp_bits1, exp_bits2; mp_limb_t modulus; modulus = n_randbits(state, n_randint(state, FLINT_BITS)); modulus = FLINT_MAX(UWORD(2), modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); fmpz_init(fdeg); fmpz_init(gdeg); fmpz_init(hdeg); len1 = n_randint(state, 10); len2 = n_randint(state, 10); exp_bits1 = n_randint(state, 100) + 2; exp_bits2 = n_randint(state, 100) + 2; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_mul_johnson(h, f, g, ctx); nmod_mpoly_total_degree_fmpz(hdeg, h, ctx); nmod_mpoly_total_degree_fmpz(fdeg, f, ctx); nmod_mpoly_total_degree_fmpz(gdeg, g, ctx); _check_total_degree(hdeg, h, ctx); _check_total_degree(fdeg, f, ctx); _check_total_degree(gdeg, g, ctx); if (nmod_mpoly_is_zero(f, ctx) || nmod_mpoly_is_zero(g, ctx)) { ok = fmpz_equal_si(hdeg, -WORD(1)) && (fmpz_equal_si(fdeg, -WORD(1)) || fmpz_equal_si(gdeg, -WORD(1))); } else { fmpz_add(gdeg, gdeg, fdeg); if (n_is_prime(nmod_mpoly_ctx_modulus(ctx))) { ok = fmpz_equal(hdeg, gdeg); } else { ok = fmpz_cmp(hdeg, gdeg) <= 0; } } if (!ok) { printf("FAIL\n"); flint_printf("Check degree adds under multiplication\ni: %wd j: %wd\n", i, j); fflush(stdout); flint_abort(); } } fmpz_clear(fdeg); fmpz_clear(gdeg); fmpz_clear(hdeg); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-univar.c000066400000000000000000000067121461254215100204750ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_univar, state) { slong i, j, k; /* Check mpoly -> mpoly_univar -> mpoly */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, h; nmod_mpoly_univar_t fx, gx; slong len1, len2, n; flint_bitcnt_t exp_bits1, exp_bits2, bits; mp_limb_t modulus; modulus = n_randint(state, SMALL_FMPZ_BITCOUNT_MAX) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 20, modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); nmod_mpoly_univar_init(fx, ctx); nmod_mpoly_univar_init(gx, ctx); len1 = n_randint(state, 50); len2 = n_randint(state, 50); exp_bits1 = n_randint(state, 3*FLINT_BITS) + 1; exp_bits2 = n_randint(state, 3*FLINT_BITS) + 1; for (j = 0; j < ctx->minfo->nvars; j++) { nmod_mpoly_randtest_bits(f, state, len1, exp_bits1, ctx); nmod_mpoly_randtest_bits(g, state, len2, exp_bits2, ctx); nmod_mpoly_to_univar(fx, f, j, ctx); nmod_mpoly_univar_assert_canonical(fx, ctx); nmod_mpoly_from_univar(g, fx, j, ctx); nmod_mpoly_assert_canonical(g, ctx); if (!nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check mpoly -> mpoly_univar -> mpoly\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } bits = mpoly_fix_bits(f->bits + n_randint(state, FLINT_BITS), ctx->minfo); _nmod_mpoly_from_univar(h, bits, fx, j, ctx); nmod_mpoly_assert_canonical(h, ctx); if (h->bits != bits || !nmod_mpoly_equal(f, h, ctx)) { printf("FAIL\n"); flint_printf("Check mpoly -> mpoly_univar -> mpoly with bits\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } if (!nmod_mpoly_univar_degree_fits_si(fx, ctx)) continue; n = nmod_mpoly_univar_length(fx, ctx); nmod_mpoly_univar_fit_length(gx, n, ctx); gx->length = n; for (k = 0; k < n; k++) { nmod_mpoly_univar_swap_term_coeff(gx->coeffs + k, fx, k, ctx); fmpz_set_si(gx->exps + k, nmod_mpoly_univar_get_term_exp_si(fx, k, ctx)); } nmod_mpoly_from_univar(g, gx, j, ctx); if (!nmod_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check construction\ni: %wd j: %wd\n",i,j); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_univar_clear(gx, ctx); nmod_mpoly_univar_clear(fx, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-univar_resultant.c000066400000000000000000000131151461254215100225710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" void test_resultant( const nmod_mpoly_t fx, const nmod_mpoly_t gx, const nmod_mpoly_ctx_t ctx) { nmod_mpoly_univar_t F, G; nmod_poly_t f, g; nmod_mpoly_t R; mp_limb_t r; nmod_mpoly_univar_init(F, ctx); nmod_mpoly_univar_init(G, ctx); nmod_poly_init(f, nmod_mpoly_ctx_modulus(ctx)); nmod_poly_init(g, nmod_mpoly_ctx_modulus(ctx)); nmod_mpoly_init(R, ctx); nmod_mpoly_get_nmod_poly(f, fx, 0, ctx); nmod_mpoly_get_nmod_poly(g, gx, 0, ctx); r = nmod_poly_resultant(f, g); nmod_mpoly_to_univar(F, fx, 0, ctx); nmod_mpoly_to_univar(G, gx, 0, ctx); nmod_mpoly_univar_resultant(R, F, G, ctx); if (!nmod_mpoly_equal_ui(R, r, ctx)) { flint_printf("FAIL: Check resultant against univariate\n"); flint_printf("fx: "); nmod_mpoly_print_pretty(fx, NULL, ctx); flint_printf("\n"); flint_printf("gx: "); nmod_mpoly_print_pretty(gx, NULL, ctx); flint_printf("\n"); flint_printf("R: "); nmod_mpoly_print_pretty(R, NULL, ctx); flint_printf("\n"); flint_printf("r: %wu\n", r); fflush(stdout); flint_abort(); } nmod_mpoly_univar_clear(F, ctx); nmod_mpoly_univar_clear(G, ctx); nmod_poly_clear(f); nmod_poly_clear(g); nmod_mpoly_clear(R, ctx); } TEST_FUNCTION_START(nmod_mpoly_univar_resultant, state) { slong i, j; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t t, s; nmod_mpoly_univar_t f; const char * vars[] = {"a", "b", "c", "d"}; nmod_mpoly_ctx_init(ctx, 4, ORD_DEGLEX, 3); nmod_mpoly_init(t, ctx); nmod_mpoly_init(s, ctx); nmod_mpoly_univar_init(f, ctx); nmod_mpoly_univar_zero(f, ctx); nmod_mpoly_set_str_pretty(t, "a", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); nmod_mpoly_set_str_pretty(t, "b", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); nmod_mpoly_set_str_pretty(t, "1", vars, ctx); nmod_mpoly_univar_discriminant(s, f, ctx); if (!nmod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check linear discriminant\n"); fflush(stdout); flint_abort(); } nmod_mpoly_univar_zero(f, ctx); nmod_mpoly_set_str_pretty(t, "a", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 2, t, ctx); nmod_mpoly_set_str_pretty(t, "b", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); nmod_mpoly_set_str_pretty(t, "c", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); nmod_mpoly_set_str_pretty(t, "b^2-4*a*c", vars, ctx); nmod_mpoly_univar_discriminant(s, f, ctx); if (!nmod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check quadratic discriminant\n"); fflush(stdout); flint_abort(); } nmod_mpoly_univar_zero(f, ctx); nmod_mpoly_set_str_pretty(t, "a", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 3, t, ctx); nmod_mpoly_set_str_pretty(t, "b", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 2, t, ctx); nmod_mpoly_set_str_pretty(t, "c", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 1, t, ctx); nmod_mpoly_set_str_pretty(t, "d", vars, ctx); nmod_mpoly_univar_set_coeff_ui(f, 0, t, ctx); nmod_mpoly_set_str_pretty(t, "b^2*c^2-4*a*c^3-4*b^3*d-27*a^2*d^2+18*a*b*c*d", vars, ctx); nmod_mpoly_univar_discriminant(s, f, ctx); if (!nmod_mpoly_equal(s, t, ctx)) { flint_printf("FAIL: check cubic discriminant\n"); fflush(stdout); flint_abort(); } nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(s, ctx); nmod_mpoly_univar_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f, g, t; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init(ctx, 1, mpoly_ordering_randtest(state), modulus); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(t, ctx); for (j = 0; j < 10; j++) { nmod_mpoly_randtest_bound(f, state, 3, 3, ctx); if (nmod_mpoly_is_zero(f, ctx)) nmod_mpoly_one(f, ctx); nmod_mpoly_zero(g, ctx); while (nmod_mpoly_degree_si(f, 0, ctx) < 100) { nmod_mpoly_randtest_bound(t, state, 5, 10, ctx); nmod_mpoly_mul(t, t, f, ctx); nmod_mpoly_add(g, g, t, ctx); nmod_mpoly_swap(f, g, ctx); } nmod_mpoly_randtest_bound(f, state, 20, 50, ctx); nmod_mpoly_randtest_bound(g, state, 20, 50, ctx); test_resultant(f, g, ctx); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/test/t-used_vars.c000066400000000000000000000040461461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_mpoly_used_vars, state) { slong i, j, k; for (i = 0; i < 30 * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t f; fmpz_t fdeg; slong len, var; flint_bitcnt_t exp_bits; int * used; nmod_mpoly_ctx_init_rand(ctx, state, 10, n_randint(state, 100) + 1); nmod_mpoly_init(f, ctx); fmpz_init(fdeg); used = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, int); for (j = 0; j < ctx->minfo->nvars; j++) { len = n_randint(state, 500); exp_bits = n_randint(state, 20) + 2; nmod_mpoly_randtest_bits(f, state, len, exp_bits, ctx); for (k = n_randint(state, ctx->minfo->nvars); k > 0; k--) { var = n_randint(state, ctx->minfo->nvars); nmod_mpoly_evaluate_one_ui(f, f, var, 1, ctx); } nmod_mpoly_used_vars(used, f, ctx); for (var = 0; var < ctx->minfo->nvars; var++) { nmod_mpoly_degree_fmpz(fdeg, f, var, ctx); if ((fmpz_sgn(fdeg) <= 0) != !used[var]) { flint_printf("FAIL: checked used matches degree\n"); flint_printf("var = %wd\n", var); flint_printf("deg: "); fmpz_print(fdeg); flint_printf("\n"); fflush(stdout); flint_abort(); } } } flint_free(used); fmpz_clear(fdeg); nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly/to_from_nmod_poly.c000066400000000000000000000070341461254215100214740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" /* set A(x_var^Bstride[var]) to B/xbar^Bshifts it is asserted that the conversion is correct */ void _nmod_mpoly_to_nmod_poly_deflate( nmod_poly_t A, const nmod_mpoly_t B, slong var, const ulong * Bshift, const ulong * Bstride, const nmod_mpoly_ctx_t ctx) { ulong mask; slong i, shift, off, N; slong len = B->length; mp_limb_t * coeff = B->coeffs; ulong * exp = B->exps; ulong var_shift, var_stride; flint_bitcnt_t bits = B->bits; FLINT_ASSERT(len > 0); FLINT_ASSERT(bits <= FLINT_BITS); N = mpoly_words_per_exp_sp(bits, ctx->minfo); mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo); nmod_poly_zero(A); mask = (-UWORD(1)) >> (FLINT_BITS - bits); var_shift = Bshift[var]; var_stride = Bstride[var]; for (i = 0; i < len; i++) { ulong k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT(k >= var_shift); k -= var_shift; if (k != 0) { k /= var_stride; } nmod_poly_set_coeff_ui(A, k, coeff[i]); } #if FLINT_WANT_ASSERT for (i = 0; i < len; i++) { slong v; for (v = 0; v < ctx->minfo->nvars; v++) { ulong k; mpoly_gen_offset_shift_sp(&off, &shift, v, bits, ctx->minfo); k = (exp[N*i + off] >> shift) & mask; FLINT_ASSERT( (v == var && k >= Bshift[v]) || (v != var && k == Bshift[v])); } } #endif } /* set A to B(x_var^Astride[var])*xbar^Ashift A must be packed into bits = Abits */ void _nmod_mpoly_from_nmod_poly_inflate( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_poly_t B, slong var, const ulong * Ashift, const ulong * Astride, const nmod_mpoly_ctx_t ctx) { slong N; slong k; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * shiftexp; ulong * strideexp; slong Bdeg = nmod_poly_degree(B); TMP_INIT; TMP_START; FLINT_ASSERT(Abits <= FLINT_BITS); FLINT_ASSERT(!nmod_poly_is_zero(B)); /* must have at least space for the highest exponent of var */ FLINT_ASSERT(1 + FLINT_BIT_COUNT(Ashift[var] + Bdeg*Astride[var]) <= Abits); N = mpoly_words_per_exp_sp(Abits, ctx->minfo); strideexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); shiftexp = (ulong*) TMP_ALLOC(N*sizeof(ulong)); mpoly_set_monomial_ui(shiftexp, Ashift, Abits, ctx->minfo); mpoly_gen_monomial_sp(strideexp, var, Abits, ctx->minfo); mpoly_monomial_mul_ui(strideexp, strideexp, N, Astride[var]); nmod_mpoly_fit_length_reset_bits(A, 0, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (k = Bdeg; k >= 0; k--) { _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, N, Alen + 1); Acoeff[Alen] = nmod_poly_get_coeff_ui(B, k); if (Acoeff[Alen] == 0) continue; mpoly_monomial_madd(Aexp + N*Alen, shiftexp, k, strideexp, N); Alen++; } A->coeffs = Acoeff; A->exps = Aexp; _nmod_mpoly_set_length(A, Alen, ctx); TMP_END; } flint-3.1.3/src/nmod_mpoly/univar.c000066400000000000000000000443451461254215100172610ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" void nmod_mpoly_univar_init(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->exps = NULL; A->alloc = 0; A->length = 0; } void nmod_mpoly_univar_clear(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) { nmod_mpoly_clear(A->coeffs + i, ctx); fmpz_clear(A->exps + i); } if (A->coeffs) flint_free(A->coeffs); if (A->exps) flint_free(A->exps); } void nmod_mpoly_univar_fit_length(nmod_mpoly_univar_t A, slong length, const nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length > old_alloc) { if (old_alloc == 0) { A->exps = (fmpz *) flint_malloc(new_alloc*sizeof(fmpz)); A->coeffs = (nmod_mpoly_struct *) flint_malloc( new_alloc*sizeof(nmod_mpoly_struct)); } else { A->exps = (fmpz *) flint_realloc(A->exps, new_alloc*sizeof(fmpz)); A->coeffs = (nmod_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(nmod_mpoly_struct)); } for (i = old_alloc; i < new_alloc; i++) { fmpz_init(A->exps + i); nmod_mpoly_init(A->coeffs + i, ctx); } A->alloc = new_alloc; } } void nmod_mpoly_univar_set_coeff_ui( nmod_mpoly_univar_t A, ulong e, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx) { slong i, j; for (i = A->length; i >= 0; i--) { int cmp = i > 0 ? fmpz_cmp_ui(A->exps + i - 1, e) : 1; if (cmp > 0) { if (nmod_mpoly_is_zero(c, ctx)) return; nmod_mpoly_univar_fit_length(A, A->length + 1, ctx); for (j = A->length; j > i; j--) { nmod_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } A->length++; fmpz_set_ui(A->exps + i, e); nmod_mpoly_set(A->coeffs + i, c, ctx); return; } else if (cmp == 0) { nmod_mpoly_set(A->coeffs + i, c, ctx); if (!nmod_mpoly_is_zero(A->coeffs + i, ctx)) return; A->length--; for (j = i; j < A->length; j++) { nmod_mpoly_swap(A->coeffs + j, A->coeffs + j + 1, ctx); fmpz_swap(A->exps + j, A->exps + j + 1); } } } FLINT_ASSERT(0 && "unreachable"); return; } int nmod_mpoly_univar_degree_fits_si(const nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) { return A->length == 0 || fmpz_fits_si(A->exps + 0); } slong nmod_mpoly_univar_get_term_exp_si(nmod_mpoly_univar_t A, slong i, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT((ulong)i < (ulong)A->length); return fmpz_get_si(A->exps + i); } void nmod_mpoly_univar_assert_canonical(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i + 1 < A->length; i++) { if (fmpz_cmp(A->exps + i, A->exps + i + 1) <= 0 || fmpz_sgn(A->exps + i) < 0 || fmpz_sgn(A->exps + i + 1) < 0) { flint_throw(FLINT_ERROR, "Univariate polynomial exponents out of order"); } } for (i = 0; i < A->length; i++) nmod_mpoly_assert_canonical(A->coeffs + i, ctx); } void nmod_mpoly_univar_print_pretty(const nmod_mpoly_univar_t A, const char ** x, const nmod_mpoly_ctx_t ctx) { slong i; if (A->length == 0) flint_printf("0"); for (i = 0; i < A->length; i++) { if (i != 0) flint_printf("+"); flint_printf("("); nmod_mpoly_print_pretty(A->coeffs + i,x,ctx); flint_printf(")*X^"); fmpz_print(A->exps + i); } } static void _tree_data_clear_sp( nmod_mpoly_univar_t A, mpoly_rbtree_ui_t tree, slong idx, const nmod_mpoly_ctx_t ctx) { mpoly_rbnode_ui_struct * nodes = tree->nodes + 2; nmod_mpoly_struct * data = (nmod_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_sp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set_ui(A->exps + A->length, nodes[idx].key); nmod_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; nmod_mpoly_clear(data + idx, ctx); _tree_data_clear_sp(A, tree, nodes[idx].left, ctx); } static void _tree_data_clear_mp( nmod_mpoly_univar_t A, mpoly_rbtree_fmpz_t tree, slong idx, const nmod_mpoly_ctx_t ctx) { mpoly_rbnode_fmpz_struct * nodes = tree->nodes + 2; nmod_mpoly_struct * data = (nmod_mpoly_struct *) tree->data; if (idx < 0) return; _tree_data_clear_mp(A, tree, nodes[idx].right, ctx); FLINT_ASSERT(A->length < A->alloc); fmpz_set(A->exps + A->length, nodes[idx].key); nmod_mpoly_swap(A->coeffs + A->length, data + idx, ctx); A->length++; nmod_mpoly_clear(data + idx, ctx); _tree_data_clear_mp(A, tree, nodes[idx].left, ctx); } /* the coefficients of A should be constructed with the same bits as B */ void nmod_mpoly_to_univar(nmod_mpoly_univar_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) { flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctx->minfo); slong shift, off; slong Blen = B->length; const mp_limb_t * Bcoeff = B->coeffs; const ulong * Bexp = B->exps; slong i; int its_new; ulong * one; #define LUT_limit (48) nmod_mpoly_struct LUT[LUT_limit]; if (B->length == 0) { A->length = 0; return; } one = FLINT_ARRAY_ALLOC(N, ulong); if (bits <= FLINT_BITS) { slong Alen; mpoly_rbtree_ui_t tree; nmod_mpoly_struct * d; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); mpoly_rbtree_ui_init(tree, sizeof(nmod_mpoly_struct)); mpoly_gen_monomial_offset_shift_sp(one, &off, &shift, var, bits, ctx->minfo); for (i = 0; i < LUT_limit; i++) nmod_mpoly_init3(LUT + i, 4, bits, ctx); /* fill in tree/LUT from B */ for (i = 0; i < Blen; i++) { ulong k = (Bexp[N*i + off] >> shift) & mask; if (k < LUT_limit) { d = LUT + k; } else { d = mpoly_rbtree_ui_lookup(tree, &its_new, k); if (its_new) nmod_mpoly_init3(d, 4, bits, ctx); } nmod_mpoly_fit_length(d, d->length + 1, ctx); d->coeffs[d->length] = Bcoeff[i]; mpoly_monomial_msub(d->exps + N*d->length, Bexp + N*i, k, one, N); d->length++; } /* clear out tree to A */ Alen = tree->length; for (i = LUT_limit - 1; i >= 0; i--) Alen += (LUT[i].length > 0); nmod_mpoly_univar_fit_length(A, Alen, ctx); A->length = 0; _tree_data_clear_sp(A, tree, mpoly_rbtree_ui_head(tree), ctx); for (i = LUT_limit - 1; i >= 0; i--) { d = LUT + i; if (d->length > 0) { FLINT_ASSERT(A->length < A->alloc); fmpz_set_si(A->exps + A->length, i); nmod_mpoly_swap(A->coeffs + A->length, d, ctx); A->length++; } nmod_mpoly_clear(d, ctx); } mpoly_rbtree_ui_clear(tree); } else { mpoly_rbtree_fmpz_t tree; nmod_mpoly_struct * d; fmpz_t k; fmpz_init(k); mpoly_rbtree_fmpz_init(tree, sizeof(nmod_mpoly_struct)); off = mpoly_gen_monomial_offset_mp(one, var, bits, ctx->minfo); /* fill in tree from B */ for (i = 0; i < Blen; i++) { fmpz_set_ui_array(k, Bexp + N*i + off, bits/FLINT_BITS); d = mpoly_rbtree_fmpz_lookup(tree, &its_new, k); if (its_new) nmod_mpoly_init3(d, 4, bits, ctx); nmod_mpoly_fit_length(d, d->length + 1, ctx); d->coeffs[d->length] = Bcoeff[i]; mpoly_monomial_msub_ui_array(d->exps + N*d->length, Bexp + N*i, Bexp + N*i + off, bits/FLINT_BITS, one, N); d->length++; } /* clear out tree to A */ nmod_mpoly_univar_fit_length(A, tree->length, ctx); A->length = 0; _tree_data_clear_mp(A, tree, mpoly_rbtree_fmpz_head(tree), ctx); fmpz_clear(k); mpoly_rbtree_fmpz_clear(tree); } flint_free(one); } /* Currently this function does not work if the coefficients depend on "var". The assertion x->next == NULL would need to be replaced by a loop. Other asserts would need to be removed as well. */ void _nmod_mpoly_from_univar( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_univar_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i; slong next_loc, heap_len = 1; ulong * cmpmask; slong total_len; mpoly_heap_s * heap; slong Alen; ulong ** Btexp; ulong * exp; ulong * one; mpoly_heap_t * chain, * x; TMP_INIT; if (B->length == 0) { nmod_mpoly_fit_length_reset_bits(A, 0, Abits, ctx); A->length = 0; return; } TMP_START; /* pack everything into Abits */ one = (ulong*) TMP_ALLOC(N*sizeof(ulong)); cmpmask = (ulong*) TMP_ALLOC(N*sizeof(ulong)); Btexp = (ulong **) TMP_ALLOC(B->length*sizeof(ulong*)); total_len = 0; for (i = 0; i < B->length; i++) { nmod_mpoly_struct * Bi = B->coeffs + i; total_len += Bi->length; Btexp[i] = Bi->exps; if (Abits != Bi->bits) { Btexp[i] = (ulong *) flint_malloc(N*Bi->length*sizeof(ulong)); if (!mpoly_repack_monomials(Btexp[i], Abits, Bi->exps, Bi->bits, Bi->length, ctx->minfo)) { FLINT_ASSERT(0 && "repack does not fit"); } } } nmod_mpoly_fit_length_reset_bits(A, total_len, Abits, ctx); next_loc = B->length + 2; heap = (mpoly_heap_s *) TMP_ALLOC((B->length + 1)*sizeof(mpoly_heap_s)); exp = (ulong *) TMP_ALLOC(B->length*N*sizeof(ulong)); chain = (mpoly_heap_t *) TMP_ALLOC(B->length*sizeof(mpoly_heap_t)); mpoly_get_cmpmask(cmpmask, N, Abits, ctx->minfo); Alen = 0; if (Abits <= FLINT_BITS) { mpoly_gen_monomial_sp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { FLINT_ASSERT(fmpz_fits_si(B->exps + i)); x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + i), one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->coeffs_alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); A->coeffs[Alen] = (B->coeffs + x->i)->coeffs[x->j]; Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { FLINT_ASSERT(fmpz_fits_si(B->exps + x->i)); x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd(exp + N*x->i, Btexp[x->i] + N*x->j, fmpz_get_si(B->exps + x->i), one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } else { mpoly_gen_monomial_offset_mp(one, var, Abits, ctx->minfo); for (i = 0; i < B->length; i++) { x = chain + i; x->i = i; x->j = 0; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + i, one, N); _mpoly_heap_insert(heap, exp + N*i, x, &next_loc, &heap_len, N, cmpmask); } while (heap_len > 1) { FLINT_ASSERT(Alen < A->coeffs_alloc); mpoly_monomial_set(A->exps + N*Alen, heap[1].exp, N); x = _mpoly_heap_pop(heap, &heap_len, N, cmpmask); A->coeffs[Alen] = (B->coeffs + x->i)->coeffs[x->j]; Alen++; FLINT_ASSERT(x->next == NULL); if (x->j + 1 < (B->coeffs + x->i)->length) { x->j = x->j + 1; x->next = NULL; mpoly_monomial_madd_fmpz(exp + N*x->i, Btexp[x->i] + N*x->j, B->exps + x->i, one, N); _mpoly_heap_insert(heap, exp + N*x->i, x, &next_loc, &heap_len, N, cmpmask); } } } A->length = Alen; for (i = 0; i < B->length; i++) { if (Btexp[i] != (B->coeffs + i)->exps) flint_free(Btexp[i]); } TMP_END; } void nmod_mpoly_from_univar(nmod_mpoly_t A, const nmod_mpoly_univar_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong n = ctx->minfo->nfields; flint_bitcnt_t bits; slong i; fmpz * gen_fields, * tmp_fields, * max_fields; TMP_INIT; if (B->length == 0) { nmod_mpoly_zero(A, ctx); return; } TMP_START; /* find bits required to represent result */ gen_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); tmp_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); max_fields = (fmpz *) TMP_ALLOC(ctx->minfo->nfields*sizeof(fmpz)); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_init(gen_fields + i); fmpz_init(tmp_fields + i); fmpz_init(max_fields + i); } mpoly_gen_fields_fmpz(gen_fields, var, ctx->minfo); for (i = 0; i < B->length; i++) { nmod_mpoly_struct * Bi = B->coeffs + i; mpoly_max_fields_fmpz(tmp_fields, Bi->exps, Bi->length, Bi->bits, ctx->minfo); _fmpz_vec_scalar_addmul_fmpz(tmp_fields, gen_fields, n, B->exps + i); _fmpz_vec_max_inplace(max_fields, tmp_fields, n); } bits = _fmpz_vec_max_bits(max_fields, n); bits = FLINT_MAX(MPOLY_MIN_BITS, bits + 1); bits = mpoly_fix_bits(bits, ctx->minfo); for (i = 0; i < ctx->minfo->nfields; i++) { fmpz_clear(gen_fields + i); fmpz_clear(tmp_fields + i); fmpz_clear(max_fields + i); } TMP_END; _nmod_mpoly_from_univar(A, bits, B, var, ctx); } #define COEFF(A, i) ((void*)(A->coeffs + (i)*R->elem_size)) static void mpoly_univar_set_nmod_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, const nmod_mpoly_univar_t B, const nmod_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); A->length = B->length; for (i = B->length - 1; i >= 0; i--) { fmpz_set(A->exps + i, B->exps + i); nmod_mpoly_set(COEFF(A, i), B->coeffs + i, ctx); } } static void mpoly_univar_swap_nmod_mpoly_univar( mpoly_univar_t A, mpoly_void_ring_t R, nmod_mpoly_univar_t B, const nmod_mpoly_ctx_t ctx) { slong i; mpoly_univar_fit_length(A, B->length, R); nmod_mpoly_univar_fit_length(B, A->length, ctx); for (i = FLINT_MAX(A->length, B->length) - 1; i >= 0; i--) { fmpz_swap(A->exps + i, B->exps + i); nmod_mpoly_swap(COEFF(A, i), B->coeffs + i, ctx); } FLINT_SWAP(slong, A->length, B->length); } int nmod_mpoly_univar_pseudo_gcd( nmod_mpoly_univar_t gx, const nmod_mpoly_univar_t ax, const nmod_mpoly_univar_t bx, const nmod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx, Gx; mpoly_void_ring_init_nmod_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_init(Gx, R); mpoly_univar_set_nmod_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_nmod_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_pseudo_gcd_ducos(Gx, Ax, Bx, R); if (success) mpoly_univar_swap_nmod_mpoly_univar(Gx, R, gx, ctx); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); mpoly_univar_clear(Gx, R); return success; } int nmod_mpoly_univar_resultant( nmod_mpoly_t d, const nmod_mpoly_univar_t ax, const nmod_mpoly_univar_t bx, const nmod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Ax, Bx; mpoly_void_ring_init_nmod_mpoly_ctx(R, ctx); mpoly_univar_init(Ax, R); mpoly_univar_init(Bx, R); mpoly_univar_set_nmod_mpoly_univar(Ax, R, ax, ctx); mpoly_univar_set_nmod_mpoly_univar(Bx, R, bx, ctx); success = mpoly_univar_resultant(d, Ax, Bx, R); mpoly_univar_clear(Ax, R); mpoly_univar_clear(Bx, R); return success; } int nmod_mpoly_univar_discriminant( nmod_mpoly_t d, const nmod_mpoly_univar_t fx, const nmod_mpoly_ctx_t ctx) { int success; mpoly_void_ring_t R; mpoly_univar_t Fx; mpoly_void_ring_init_nmod_mpoly_ctx(R, ctx); mpoly_univar_init(Fx, R); mpoly_univar_set_nmod_mpoly_univar(Fx, R, fx, ctx); success = mpoly_univar_discriminant(d, Fx, R); mpoly_univar_clear(Fx, R); return success; } flint-3.1.3/src/nmod_mpoly/void_ring.c000066400000000000000000000073371461254215100177350ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly.h" static void nmod_mpoly_void_init(void * a, const void * ctx) { nmod_mpoly_init(a, ctx); } static void nmod_mpoly_void_clear(void * a, const void * ctx) { nmod_mpoly_clear(a, ctx); } static int nmod_mpoly_void_is_zero(const void * a, const void * ctx) { return nmod_mpoly_is_zero(a, ctx); } static void nmod_mpoly_void_zero(void * a, const void * ctx) { nmod_mpoly_zero(a, ctx); } static void nmod_mpoly_void_one(void * a, const void * ctx) { nmod_mpoly_one(a, ctx); } static void nmod_mpoly_void_set(void * a, const void * b, const void * ctx) { nmod_mpoly_set(a, b, ctx); } static void nmod_mpoly_void_set_fmpz(void * a, const fmpz_t b, const void * ctx) { nmod_mpoly_set_fmpz(a, b, ctx); } static void nmod_mpoly_void_swap(void * a, void * b, const void * ctx) { nmod_mpoly_swap(a, b, ctx); } static void nmod_mpoly_void_neg(void * a, const void * b, const void * ctx) { nmod_mpoly_neg(a, b, ctx); } static void nmod_mpoly_void_add(void * a, const void * b, const void * c, const void * ctx) { nmod_mpoly_add(a, b, c, ctx); } static void nmod_mpoly_void_sub(void * a, const void * b, const void * c, const void * ctx) { nmod_mpoly_sub(a, b, c, ctx); } static void nmod_mpoly_void_mul(void * a, const void * b, const void * c, const void * ctx) { nmod_mpoly_mul(a, b, c, ctx); } static void nmod_mpoly_void_mul_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx_) { const nmod_mpoly_ctx_struct * ctx = ctx_; nmod_mpoly_scalar_mul_ui(a, b, fmpz_get_nmod(c, ctx->mod), ctx); } static void nmod_mpoly_void_divexact(void * a, const void * b, const void * c, const void * ctx) { if (!nmod_mpoly_divides(a, b, c, ctx)) flint_throw(FLINT_ERROR, "nmod_mpoly_void_divexact: nonexact"); } static int nmod_mpoly_void_divides(void * a, const void * b, const void * c, const void * ctx) { return nmod_mpoly_divides(a, b, c, ctx); } static int nmod_mpoly_void_pow_fmpz(void * a, const void * b, const fmpz_t c, const void * ctx) { return nmod_mpoly_pow_fmpz(a, b, c, ctx); } static slong nmod_mpoly_void_length(const void * a, const void * ctx) { return nmod_mpoly_length(a, ctx); } void mpoly_void_ring_init_nmod_mpoly_ctx( mpoly_void_ring_t R, const nmod_mpoly_ctx_t ctx) { R->elem_size = sizeof(nmod_mpoly_struct); R->ctx = ctx; R->init = nmod_mpoly_void_init; R->clear = nmod_mpoly_void_clear; R->is_zero = nmod_mpoly_void_is_zero; R->zero = nmod_mpoly_void_zero; R->one = nmod_mpoly_void_one; R->set = nmod_mpoly_void_set; R->set_fmpz = nmod_mpoly_void_set_fmpz; R->swap = nmod_mpoly_void_swap; R->neg = nmod_mpoly_void_neg; R->add = nmod_mpoly_void_add; R->sub = nmod_mpoly_void_sub; R->mul = nmod_mpoly_void_mul; R->mul_fmpz = nmod_mpoly_void_mul_fmpz; R->divexact = nmod_mpoly_void_divexact; R->divides = nmod_mpoly_void_divides; R->pow_fmpz = nmod_mpoly_void_pow_fmpz; R->length = nmod_mpoly_void_length; } flint-3.1.3/src/nmod_mpoly_factor.h000066400000000000000000000433521461254215100173150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_MPOLY_FACTOR_H #define NMOD_MPOLY_FACTOR_H #ifdef NMOD_MPOLY_FACTOR_INLINES_C #define NMOD_MPOLY_FACTOR_INLINE #else #define NMOD_MPOLY_FACTOR_INLINE static inline #endif #include "nmod_mpoly.h" #ifdef __cplusplus extern "C" { #endif void nmod_mpoly_get_bpoly(n_bpoly_t A, const nmod_mpoly_t B, slong var0, slong var1, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_bpoly(nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong var0, slong var1, const nmod_mpoly_ctx_t ctx); int n_bpoly_mod_factor_smprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, int allow_shift, nmod_t ctx); void n_bpoly_mod_factor_lgprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, nmod_t ctx); /*****************************************************************************/ int nmod_mat_is_reduced(const nmod_mat_t N); void nmod_mat_init_nullspace_tr(nmod_mat_t X, nmod_mat_t tmp); /*****************************************************************************/ NMOD_MPOLY_FACTOR_INLINE void nmod_mpoly_factor_init(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { f->constant = 1; f->poly = NULL; f->exp = NULL; f->num = 0; f->alloc = 0; } void nmod_mpoly_factor_init2(nmod_mpoly_factor_t f, slong alloc, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_realloc(nmod_mpoly_factor_t f, slong alloc, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_fit_length(nmod_mpoly_factor_t f, slong len, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_clear(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_FACTOR_INLINE slong nmod_mpoly_factor_length(const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { return f->num; } NMOD_MPOLY_FACTOR_INLINE ulong nmod_mpoly_factor_get_constant_ui(const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { return f->constant; } NMOD_MPOLY_FACTOR_INLINE void nmod_mpoly_factor_get_base(nmod_mpoly_t p, const nmod_mpoly_factor_t f, slong i, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); nmod_mpoly_set(p, f->poly + i, ctx); } NMOD_MPOLY_FACTOR_INLINE void nmod_mpoly_factor_swap_base(nmod_mpoly_t p, nmod_mpoly_factor_t f, slong i, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); nmod_mpoly_swap(p, f->poly + i, ctx); } slong nmod_mpoly_factor_get_exp_si(nmod_mpoly_factor_t f, slong i, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_append_ui(nmod_mpoly_factor_t f, const nmod_mpoly_t A, ulong e, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_append_fmpz(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const fmpz_t e, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_set(nmod_mpoly_factor_t f, const nmod_mpoly_factor_t g, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_print_pretty(const nmod_mpoly_factor_t f, const char ** vars, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_content(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_squarefree(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_separable(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, int sep); int nmod_mpoly_factor(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_factor_sort(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_cmp( const nmod_mpoly_factor_t A, const nmod_mpoly_factor_t B, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_expand(nmod_mpoly_t A, const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_FACTOR_INLINE int nmod_mpoly_factor_matches(const nmod_mpoly_t a, const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { int matches; nmod_mpoly_t t; nmod_mpoly_init(t, ctx); nmod_mpoly_factor_expand(t, f, ctx); matches = nmod_mpoly_equal(t, a, ctx); nmod_mpoly_clear(t, ctx); return matches; } int nmod_mpoly_factor_fix_units(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_FACTOR_INLINE void nmod_mpoly_factor_swap(nmod_mpoly_factor_t f, nmod_mpoly_factor_t g, const nmod_mpoly_ctx_t ctx) { nmod_mpoly_factor_struct t = *f; *f = *g; *g = t; } NMOD_MPOLY_FACTOR_INLINE void nmod_mpoly_factor_one(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { f->constant = 1; f->num = 0; } void _nmod_mpoly_get_lead0( nmod_mpoly_t c, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_set_lead0( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); /* n_poly_vec ****************************************************************/ slong _n_poly_vec_max_degree(const n_poly_struct * A, slong Alen); void _n_poly_vec_mul_nmod_intertible(n_poly_struct * A, slong Alen, mp_limb_t c, nmod_t ctx); void _n_poly_vec_mod_mul_poly(n_poly_struct * A, slong Alen, const n_poly_t g, const nmod_t ctx); void _n_poly_vec_mod_divexact_poly(n_poly_struct * A, slong Alen, const n_poly_t g, nmod_t ctx); void _n_poly_vec_mod_content(n_poly_t g, const n_poly_struct * A, slong Alen, nmod_t ctx); void _n_poly_vec_mod_remove_content(n_poly_t g, n_poly_struct * A, slong Alen, nmod_t ctx); /* polyun ********************************************************************/ void nmod_mpoly_get_polyu1n(n_polyun_t A, const nmod_mpoly_t B, slong varx, slong vary, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_set_polyu1n(nmod_mpoly_t B, const n_polyun_t A, slong varx, slong vary, const nmod_mpoly_ctx_t ctx); /*****************************************************************************/ typedef struct { nmod_mpoly_struct * coeffs; slong alloc; slong length; } nmod_mpolyv_struct; typedef nmod_mpolyv_struct nmod_mpolyv_t[1]; NMOD_MPOLY_FACTOR_INLINE void nmod_mpolyv_init(nmod_mpolyv_t A, const nmod_mpoly_ctx_t ctx) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } NMOD_MPOLY_FACTOR_INLINE void nmod_mpolyv_swap(nmod_mpolyv_t A, nmod_mpolyv_t B, const nmod_mpoly_ctx_t ctx) { nmod_mpolyv_struct t = *A; *A = *B; *B = t; } void nmod_mpolyv_clear(nmod_mpolyv_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyv_print_pretty(const nmod_mpolyv_t poly, const char ** x, const nmod_mpoly_ctx_t ctx); void nmod_mpolyv_fit_length(nmod_mpolyv_t A, slong length, const nmod_mpoly_ctx_t ctx); void nmod_mpolyv_set_coeff(nmod_mpolyv_t A, slong i, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_to_mpolyv(nmod_mpolyv_t A, const nmod_mpoly_t B, const nmod_mpoly_t xalpha, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_from_mpolyv(nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpolyv_t B, const nmod_mpoly_t xalpha, const nmod_mpoly_ctx_t ctx); int _nmod_mpoly_vec_content_mpoly(nmod_mpoly_t g, const nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_vec_divexact_mpoly(nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_vec_mul_mpoly(nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); /*****************************************************************************/ int _nmod_mpoly_factor_separable(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, int sep); int nmod_mpoly_factor_lcc_wang(nmod_mpoly_struct * lc_divs, const nmod_mpoly_factor_t lcAfac, const n_poly_t Auc, const n_bpoly_struct * Auf, slong r, const n_poly_struct * alpha, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_irred_smprime_zassenhaus(nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_medprime_zassenhaus(nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_lgprime_zassenhaus(nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_smprime_wang(nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_medprime_wang(nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_lgprime_wang(nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_smprime_zippel(nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_medprime_zippel(nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_irred_lgprime_zippel(nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state); /*****************************************************************************/ void nmod_mpoly_compression_do(nmod_mpoly_t L, const nmod_mpoly_ctx_t Lctx, mp_limb_t * Acoeffs, slong Alen, mpoly_compression_t M); void nmod_mpoly_compression_undo(nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t Actx, nmod_mpoly_t L, const nmod_mpoly_ctx_t Lctx, mpoly_compression_t M); /*****************************************************************************/ int nmod_mpolyu_is_canonical(const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); void nmod_mpolyu3_print_pretty(const nmod_mpolyu_t A, const char * var0, const char * var1, const char * var2, const char ** vars, const nmod_mpoly_ctx_t ctx); /*****************************************************************************/ typedef struct { flint_bitcnt_t bits; slong w; slong r; n_poly_struct * inv_prod_dbetas; nmod_mpoly_struct * inv_prod_dbetas_mvar; n_poly_struct * dbetas; nmod_mpoly_struct * dbetas_mvar; nmod_mpoly_struct * prod_mbetas; nmod_mpolyv_struct * prod_mbetas_coeffs; nmod_mpoly_struct * mbetas; nmod_mpoly_struct * deltas; nmod_mpoly_struct * xalpha; nmod_mpoly_struct * q; nmod_mpoly_geobucket_struct * G; nmod_mpoly_struct * qt; nmod_mpoly_struct * newt; nmod_mpolyv_struct * delta_coeffs; nmod_mpoly_t T; nmod_mpoly_t Q; nmod_mpoly_t R; } nmod_mpoly_pfrac_struct; typedef nmod_mpoly_pfrac_struct nmod_mpoly_pfrac_t[1]; int nmod_mpoly_pfrac_init(nmod_mpoly_pfrac_t I, flint_bitcnt_t bits, slong l, slong r, const nmod_mpoly_struct * betas, const mp_limb_t * alpha, const nmod_mpoly_ctx_t ctx); void nmod_mpoly_pfrac_clear(nmod_mpoly_pfrac_t I, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_pfrac(slong r, nmod_mpoly_t t, const slong * deg, nmod_mpoly_pfrac_t I, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_hlift(slong m, nmod_mpoly_struct * f, slong r, const mp_limb_t * alpha, const nmod_mpoly_t A, const slong * degs, const nmod_mpoly_ctx_t ctx); int n_bpoly_mod_pfrac(slong r, n_bpoly_struct * C, slong * C_deg1_bound, n_bpoly_t A, n_bpoly_struct * B, nmod_t mod); int n_bpoly_mod_hlift2(n_bpoly_t A, n_bpoly_t B0, n_bpoly_t B1, mp_limb_t alpha, slong degree_inner, nmod_t mod, n_poly_bpoly_stack_t St); int n_bpoly_mod_hlift2_cubic(n_bpoly_t A, n_bpoly_t B0, n_bpoly_t B1, mp_limb_t alpha, slong degree_inner, nmod_t ctx, nmod_eval_interp_t E, n_poly_bpoly_stack_t St); int n_bpoly_mod_hlift(slong r, n_bpoly_t A, n_bpoly_struct * B, mp_limb_t alpha, slong degree_inner, nmod_t mod, n_poly_bpoly_stack_t St); int n_bpoly_mod_hlift_cubic(slong r, n_bpoly_t A, n_bpoly_struct * B, mp_limb_t alpha, slong degree_inner, nmod_t mod, nmod_eval_interp_t E, n_poly_bpoly_stack_t St); int n_polyu3_mod_hlift(slong r, n_polyun_struct * BB, n_polyu_t A, n_polyu_struct * B, mp_limb_t beta, slong degree_inner, nmod_t ctx); int nmod_mpoly_hlift_zippel(slong m, nmod_mpoly_struct * B, slong r, const mp_limb_t * alpha, const nmod_mpoly_t A, const slong * degs, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpoly_factor_algo(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, unsigned int algo); int nmod_mpoly_factor_zassenhaus(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_wang(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); int nmod_mpoly_factor_zippel(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); int _nmod_mpoly_evaluate_rest_n_poly(n_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, slong var, const n_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, nmod_t ctx); void _nmod_mpoly_eval_rest_to_n_bpoly(n_bpoly_t E, const nmod_mpoly_t A, const n_poly_struct * alphabetas, const nmod_mpoly_ctx_t ctx); void _nmod_mpoly_set_n_bpoly_var1_zero(nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); /* gcd ***********************************************************************/ int nmod_mpolyl_gcdp_zippel_smprime(nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, nmod_mpoly_t A, nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t state); int nmod_mpolyl_gcds_zippel(nmod_mpoly_t G, const ulong * Gmarks, slong Gmarkslen, nmod_mpoly_t A, nmod_mpoly_t B, slong *perm, slong l, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t state, slong * Gdegbound, n_poly_t Amarks, n_poly_t Bmarks); /* zip helpers ***************************************************************/ void mpoly_monomial_evals_nmod(n_poly_t EH, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, n_poly_struct * alpha_caches, slong start, slong stop, const mpoly_ctx_t mctx, const nmod_t fpctx); void mpoly1_monomial_evals_nmod(n_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Amarks, slong Amarkslen, n_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const nmod_t fpctx); void mpoly2_monomial_evals_nmod(n_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, ulong * Amarks, slong Amarkslen, n_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const nmod_t fpctx); void n_polyun_zip_start(n_polyun_t Z, n_polyun_t H, slong req_images); int n_polyu2n_add_zip_must_match(n_polyun_t Z, const n_bpoly_t A, slong cur_length); int n_polyun_zip_solve(nmod_mpoly_t A, n_polyun_t Z, n_polyun_t H, n_polyun_t M, const nmod_mpoly_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod_mpoly_factor/000077500000000000000000000000001461254215100171355ustar00rootroot00000000000000flint-3.1.3/src/nmod_mpoly_factor/append.c000066400000000000000000000020151461254215100205460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly_factor.h" void nmod_mpoly_factor_append_ui( nmod_mpoly_factor_t f, const nmod_mpoly_t A, ulong e, const nmod_mpoly_ctx_t ctx) { slong i = f->num; nmod_mpoly_factor_fit_length(f, i + 1, ctx); nmod_mpoly_set(f->poly + i, A, ctx); fmpz_set_ui(f->exp + i, e); f->num = i + 1; } void nmod_mpoly_factor_append_fmpz( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const fmpz_t e, const nmod_mpoly_ctx_t ctx) { slong i = f->num; nmod_mpoly_factor_fit_length(f, i + 1, ctx); nmod_mpoly_set(f->poly + i, A, ctx); fmpz_set(f->exp + i, e); f->num = i + 1; } flint-3.1.3/src/nmod_mpoly_factor/clear.c000066400000000000000000000014041461254215100203660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly_factor.h" void nmod_mpoly_factor_clear(nmod_mpoly_factor_t fac, const nmod_mpoly_ctx_t ctx) { if (fac->alloc > 0) { slong i; for (i = 0; i < fac->alloc; i++) { nmod_mpoly_clear(fac->poly + i, ctx); fmpz_clear(fac->exp + i); } flint_free(fac->poly); flint_free(fac->exp); } } flint-3.1.3/src/nmod_mpoly_factor/cmp.c000066400000000000000000000017541461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly_factor.h" int nmod_mpoly_factor_cmp( const nmod_mpoly_factor_t A, const nmod_mpoly_factor_t B, const nmod_mpoly_ctx_t ctx) { int cmp; slong i; if (A->constant != B->constant) return A->constant > B->constant ? 1 : -1; if (A->num != B->num) return A->num > B->num ? 1 : -1; for (i = 0; i < A->num; i++) { cmp = fmpz_cmp(A->exp + i, B->exp + i); if (cmp != 0) return cmp; cmp = nmod_mpoly_cmp(A->poly + i, B->poly + i, ctx); if (cmp != 0) return cmp; } return 0; } flint-3.1.3/src/nmod_mpoly_factor/compression.c000066400000000000000000000061051461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "nmod_mpoly_factor.h" void nmod_mpoly_compression_do( nmod_mpoly_t L, const nmod_mpoly_ctx_t Lctx, mp_limb_t * Acoeffs, slong Alen, mpoly_compression_t M) { slong i, max_deg; flint_bitcnt_t Lbits; slong mvars = Lctx->minfo->nvars; slong nvars = M->nvars; slong LN; FLINT_ASSERT(mvars == M->mvars); max_deg = M->degs[0]; for (i = 1; i < mvars; i++) max_deg = FLINT_MAX(max_deg, M->degs[i]); Lbits = mpoly_fix_bits(1 + FLINT_BIT_COUNT(max_deg), Lctx->minfo); nmod_mpoly_fit_length_reset_bits(L, Alen, Lbits, Lctx); LN = mpoly_words_per_exp_sp(Lbits, Lctx->minfo); L->length = Alen; for (i = 0; i < Alen; i++) { L->coeffs[i] = Acoeffs[i]; mpoly_set_monomial_ui(L->exps + LN*i, (ulong *)M->exps + nvars*i, Lbits, Lctx->minfo); } nmod_mpoly_sort_terms(L, Lctx); nmod_mpoly_make_monic(L, L, Lctx); } void nmod_mpoly_compression_undo( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t Actx, nmod_mpoly_t L, const nmod_mpoly_ctx_t Lctx, mpoly_compression_t M) { slong i, k, l; slong nvars = Actx->minfo->nvars; slong NA = mpoly_words_per_exp(Abits, Actx->minfo); slong mvars = Lctx->minfo->nvars; flint_bitcnt_t Lbits = L->bits; slong NL = mpoly_words_per_exp(Lbits, Lctx->minfo); slong * mins, * texps; TMP_INIT; FLINT_ASSERT(mvars == M->mvars); FLINT_ASSERT(nmod_mpoly_degrees_fit_si(L, Lctx)); TMP_START; texps = (slong *) TMP_ALLOC(nvars*sizeof(slong)); mins = (slong *) TMP_ALLOC(nvars*sizeof(slong)); for (k = 0; k < nvars; k++) mins[k] = WORD_MAX; _slong_array_fit_length(&M->exps, &M->exps_alloc, L->length*nvars); nmod_mpoly_fit_length_reset_bits(A, L->length, Abits, Actx); _nmod_mpoly_set_length(A, L->length, Actx); for (i = 0; i < L->length; i++) { A->coeffs[i] = L->coeffs[i]; mpoly_get_monomial_ui((ulong *)texps, L->exps + NL*i, Lbits, Lctx->minfo); for (k = 0; k < nvars; k++) { slong tot = M->deltas[k]; for (l = 0; l < mvars; l++) tot += M->umat[k*nvars + l]*texps[l]; M->exps[i*nvars + k] = tot; mins[k] = FLINT_MIN(mins[k], tot); } } for (i = 0; i < L->length; i++) { for (k = 0; k < nvars; k++) M->exps[i*nvars + k] -= mins[k]; mpoly_set_monomial_ui(A->exps + NA*i, (ulong *)M->exps + i*nvars, Abits, Actx->minfo); } TMP_END; nmod_mpoly_sort_terms(A, Actx); nmod_mpoly_make_monic(A, A, Actx); } flint-3.1.3/src/nmod_mpoly_factor/eval.c000066400000000000000000000136051461254215100202350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" /* only E and alphas are shifted by "var" so output is in E[0] */ int _nmod_mpoly_evaluate_rest_n_poly( n_poly_struct * E, slong * starts, slong * ends, slong * stops, ulong * es, const mp_limb_t * Acoeffs, const ulong * Aexps, slong Alen, slong var, const n_poly_struct * alphas, const slong * offsets, const slong * shifts, slong N, ulong mask, slong nvars, nmod_t ctx) { slong v, stop; ulong next_e; FLINT_ASSERT(var < nvars); E -= var; alphas -= var; v = var; starts[v] = 0; ends[v] = Alen; n_poly_zero(E + v); if (Alen < 1) return 1; calculate: /* input: v starts[v] ends[v] */ FLINT_ASSERT(ends[v] > starts[v]); es[v] = mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]); n_poly_zero(E + v); next: FLINT_ASSERT(es[v] == (mask & (Aexps[N*starts[v] + offsets[v]] >> shifts[v]))); stop = starts[v] + 1; while (stop < ends[v] && (mask & (Aexps[N*stop + offsets[v]] >> shifts[v])) == es[v]) { stop++; } stops[v] = stop; if (v + 1 < nvars) { starts[v + 1] = starts[v]; ends[v + 1] = stops[v]; v++; goto calculate; calculate_return: n_poly_mod_add(E + v, E + v, E + v + 1, ctx); } else { n_poly_mod_add_ui(E + v, E + v, Acoeffs[starts[v]], ctx); } if (stops[v] < ends[v]) { next_e = mask & (Aexps[N*stops[v] + offsets[v]] >> shifts[v]); FLINT_ASSERT(next_e < es[v]); n_poly_mod_pow(E + v + 1, alphas + v, es[v] - next_e, ctx); n_poly_mod_mul(E + v, E + v, E + v + 1, ctx); es[v] = next_e; starts[v] = stops[v]; goto next; } else { n_poly_mod_pow(E + v + 1, alphas + v, es[v], ctx); n_poly_mod_mul(E + v, E + v, E + v + 1, ctx); } if (v > var) { v--; goto calculate_return; } return 1; } void _nmod_mpoly_eval_rest_to_n_bpoly( n_bpoly_t E, const nmod_mpoly_t A, const n_poly_struct * alphabetas, const nmod_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, N = mpoly_words_per_exp_sp(A->bits, ctx->minfo); slong * offsets, * shifts; slong offset, shift; slong start, stop; ulong e, mask = (-UWORD(1)) >> (FLINT_BITS - A->bits); slong * starts, * ends, * stops; ulong * es; n_poly_struct * realE; E->length = 0; if (A->length < 1) return; starts = FLINT_ARRAY_ALLOC(n, slong); ends = FLINT_ARRAY_ALLOC(n, slong); stops = FLINT_ARRAY_ALLOC(n, slong); es = FLINT_ARRAY_ALLOC(n, ulong); realE = FLINT_ARRAY_ALLOC(n + 1, n_poly_struct); for (i = 0; i < n + 1; i++) n_poly_init(realE + i); offsets = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); shifts = (slong *) flint_malloc(ctx->minfo->nvars*sizeof(slong)); for (i = 0; i < ctx->minfo->nvars; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, A->bits, ctx->minfo); offset = offsets[0]; shift = shifts[0]; start = 0; e = mask & (A->exps[N*start + offset] >> shift); next: FLINT_ASSERT(start < A->length); FLINT_ASSERT(e == (mask & (A->exps[N*start + offset] >> shift))); stop = start + 1; while (stop < A->length && (mask & (A->exps[N*stop + offset] >> shift)) == e) stop++; n_bpoly_fit_length(E, e + 1); while (E->length <= e) { n_poly_zero(E->coeffs + E->length); E->length++; } _nmod_mpoly_evaluate_rest_n_poly(realE, starts, ends, stops, es, A->coeffs + start, A->exps + N*start, stop - start, 1, alphabetas, offsets, shifts, N, mask, ctx->minfo->nvars, ctx->mod); n_poly_set(E->coeffs + e, realE + 0); if (stop < A->length) { FLINT_ASSERT(e > (mask & (A->exps[N*stop + offset] >> shift))); e = (mask & (A->exps[N*stop + offset] >> shift)); start = stop; goto next; } n_bpoly_normalise(E); for (i = 0; i < n + 1; i++) n_poly_clear(realE + i); flint_free(realE); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); } /* A = B(gen(var), 0) */ void _nmod_mpoly_set_n_bpoly_var1_zero( nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong var, const nmod_mpoly_ctx_t ctx) { slong N = mpoly_words_per_exp(Abits, ctx->minfo); slong i, Alen; slong Blen = B->length; ulong * genexp; TMP_INIT; TMP_START; genexp = (ulong *) TMP_ALLOC(N*sizeof(ulong)); if (Abits <= FLINT_BITS) mpoly_gen_monomial_sp(genexp, var, Abits, ctx->minfo); else mpoly_gen_monomial_offset_mp(genexp, var, Abits, ctx->minfo); Alen = 2; for (i = 0; i < Blen; i++) Alen += (B->coeffs[i].length > 0); nmod_mpoly_fit_length_reset_bits(A, Alen, Abits, ctx); Alen = 0; for (i = Blen - 1; i >= 0; i--) { mp_limb_t c = n_poly_get_coeff(B->coeffs + i, 0); if (c == 0) continue; FLINT_ASSERT(Alen < A->coeffs_alloc); A->coeffs[Alen] = c; if (Abits <= FLINT_BITS) mpoly_monomial_mul_ui(A->exps + N*Alen, genexp, N, i); else mpoly_monomial_mul_ui_mp(A->exps + N*Alen, genexp, N, i); Alen++; } A->length = Alen; TMP_END; } flint-3.1.3/src/nmod_mpoly_factor/expand.c000066400000000000000000000021261461254215100205610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly_factor.h" int nmod_mpoly_factor_expand( nmod_mpoly_t A, const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { int success = 1; slong i; nmod_mpoly_t t1, t2; nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); nmod_mpoly_set_ui(A, f->constant, ctx); for (i = 0; i < f->num; i++) { if (fmpz_sgn(f->exp + i) < 0 || !nmod_mpoly_pow_fmpz(t1, f->poly + i, f->exp + i, ctx)) { success = 0; goto cleanup; } nmod_mpoly_mul(t2, A, t1, ctx); nmod_mpoly_swap(A, t2, ctx); } cleanup: nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); return success; } flint-3.1.3/src/nmod_mpoly_factor/factor.c000066400000000000000000000700761461254215100205710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "fmpz.h" #include "n_poly.h" #include "nmod_poly_factor.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" static slong _deflate( nmod_mpoly_t A, slong tot_deg, const ulong * strides, const slong * perm, const nmod_mpoly_ctx_t ctx) { slong i, j; slong nvars = ctx->minfo->nvars; flint_bitcnt_t bits = A->bits; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong * texps, * sexps; TMP_INIT; for (j = 0; j < nvars; j++) { if (strides[j] != 1 || perm[j] != j) goto do_it; } return tot_deg; do_it: TMP_START; texps = (ulong *) TMP_ALLOC(2*nvars*sizeof(ulong)); sexps = texps + nvars; tot_deg = 1; for (i = 0; i < A->length; i++) { slong this_deg = 0; mpoly_get_monomial_ui(texps, A->exps + N*i, bits, ctx->minfo); for (j = 0; j < nvars; j++) { FLINT_ASSERT(0 == texps[j] % strides[j]); texps[j] = texps[j]/strides[j]; } for (j = 0; j < nvars; j++) { sexps[j] = texps[perm[j]]; this_deg += sexps[j]; } tot_deg = FLINT_MAX(tot_deg, this_deg); mpoly_set_monomial_ui(A->exps + N*i, sexps, bits, ctx->minfo); } TMP_END; nmod_mpoly_sort_terms(A, ctx); nmod_mpoly_make_monic(A, A, ctx); return tot_deg; } static void _inflate( nmod_mpoly_t A, flint_bitcnt_t bits, const ulong * strides, const slong * perm, const nmod_mpoly_ctx_t ctx) { slong i, j; slong nvars = ctx->minfo->nvars; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong * texps, * sexps; TMP_INIT; for (j = 0; j < nvars; j++) { if (strides[j] != 1 || perm[j] != j) goto do_it; } return; do_it: nmod_mpoly_repack_bits_inplace(A, bits, ctx); TMP_START; texps = (ulong *) TMP_ALLOC(2*nvars*sizeof(ulong)); sexps = texps + nvars; for (i = 0; i < A->length; i++) { mpoly_get_monomial_ui(sexps, A->exps + N*i, bits, ctx->minfo); for (j = 0; j < nvars; j++) texps[perm[j]] = sexps[j]; for (j = 0; j < nvars; j++) texps[j] = texps[j]*strides[j]; mpoly_set_monomial_ui(A->exps + N*i, texps, bits, ctx->minfo); } TMP_END; nmod_mpoly_sort_terms(A, ctx); nmod_mpoly_make_monic(A, A, ctx); return; } /* A has degree 2 wrt gen(0) */ static int _apply_quadratic( nmod_mpolyv_t Af, nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { int success; slong i, shift, off, N; flint_bitcnt_t bits = A->bits; ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); nmod_mpoly_t a_mock, b_mock, c_mock; nmod_mpoly_t t0, t1, t2, t3; FLINT_ASSERT(A->length > 1 || A->coeffs[0] != 0); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); nmod_mpoly_init(t0, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); nmod_mpoly_init(t3, ctx); mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo); N = mpoly_words_per_exp_sp(bits, ctx->minfo); i = 0; a_mock->exps = A->exps + N*i; a_mock->coeffs = A->coeffs + i; a_mock->bits = bits; while (i < A->length && (mask & (A->exps[N*i + off] >> shift)) == 2) i++; a_mock->length = i; a_mock->coeffs_alloc = a_mock->length; a_mock->exps_alloc = N*a_mock->length; b_mock->exps = A->exps + N*i; b_mock->coeffs = A->coeffs + i; b_mock->bits = bits; while (i < A->length && (mask & (A->exps[N*i + off] >> shift)) == 1) i++; b_mock->length = i - a_mock->length; b_mock->coeffs_alloc = b_mock->length; b_mock->exps_alloc = N*b_mock->length; c_mock->exps = A->exps + N*i; c_mock->coeffs = A->coeffs + i; c_mock->bits = bits; c_mock->length = A->length - i; c_mock->coeffs_alloc = c_mock->length; c_mock->exps_alloc = N*c_mock->length; FLINT_ASSERT(a_mock->length > 0); FLINT_ASSERT(c_mock->length > 0); nmod_mpoly_mul(t1, a_mock, c_mock, ctx); nmod_mpoly_neg(t1, t1, ctx); if (!nmod_mpoly_quadratic_root(t2, b_mock, t1, ctx)) { nmod_mpolyv_fit_length(Af, 1, ctx); Af->length = 1; nmod_mpoly_swap(Af->coeffs + 0, A, ctx); success = 1; goto cleanup; } nmod_mpoly_neg(t2, t2, ctx); success = nmod_mpoly_gcd_cofactors(t0, t1, t2, a_mock, t2, ctx); if (!success) goto cleanup; nmod_mpoly_divides(t3, c_mock, t2, ctx); nmod_mpolyv_fit_length(Af, 2, ctx); Af->length = 2; nmod_mpoly_add(Af->coeffs + 0, t1, t2, ctx); nmod_mpoly_add(Af->coeffs + 1, t0, t3, ctx); success = 1; cleanup: nmod_mpoly_clear(t0, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_clear(t3, ctx); return success; } /* The property "sep" used here is that of the returned factors of _nmod_mpoly_factor_separable with sep = 1, namely: (1) monic (2) primitive wrt each variable (3) for all i, derivative(A, gen(i)) = 0, or gcd(A, derivative(A, gen(i))) = 1 (4) there is at least one i for which derivative(A, gen(i)) != 0 Input A is sep and compressed. return 1 for success, 0 for failure */ static int _factor_irred_compressed( nmod_mpolyv_t Af, nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j, tot_deg; slong nvars = ctx->minfo->nvars; slong * perm; ulong * strides, * texps; flint_bitcnt_t Abits; flint_rand_t state; #if FLINT_WANT_ASSERT nmod_mpoly_t Aorg; nmod_mpoly_init(Aorg, ctx); nmod_mpoly_set(Aorg, A, ctx); #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (A->length < 2) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(!nmod_mpoly_is_ui(A, ctx)); nmod_mpolyv_fit_length(Af, 1, ctx); nmod_mpoly_swap(Af->coeffs + 0, A, ctx); Af->length = 1; return 1; } if (A->bits > FLINT_BITS && !nmod_mpoly_repack_bits_inplace(A, FLINT_BITS, ctx)) { return 0; } Abits = A->bits; flint_randinit(state); strides = FLINT_ARRAY_ALLOC(2*nvars, ulong); texps = strides + nvars; perm = FLINT_ARRAY_ALLOC(nvars, slong); /* fill perm with id, and fill in strides */ { ulong ppowt, ppow = ctx->mod.n; slong N = mpoly_words_per_exp_sp(Abits, ctx->minfo); while (!n_mul_checked(&ppowt, ppow, ctx->mod.n)) ppow = ppowt; for (j = 0; j < nvars; j++) { strides[j] = ppow; perm[j] = j; } tot_deg = 1; for (i = 0; i < A->length; i++) { slong this_deg = 0; mpoly_get_monomial_ui(texps, A->exps + N*i, Abits, ctx->minfo); for (j = 0; j < nvars; j++) { if (z_add_checked(&this_deg, this_deg, texps[j])) { success = 0; goto cleanup; } strides[j] = n_gcd(strides[j], texps[j]); } tot_deg = FLINT_MAX(tot_deg, this_deg); } } /* find permutation with gcd(A, derivative(A, gen(perm[0]))) = 1 */ for (i = 0; i < nvars; i++) { if (strides[i] == 1) { FLINT_SWAP(slong, perm[0], perm[i]); break; } } if (nvars < 2) { nmod_poly_t Au; nmod_poly_factor_t Auf; FLINT_ASSERT(nvars == 1); nmod_poly_init_mod(Au, ctx->mod); nmod_poly_factor_init(Auf); FLINT_ASSERT(nmod_mpoly_is_nmod_poly(A, perm[0], ctx)); success = nmod_mpoly_get_nmod_poly(Au, A, perm[0], ctx); FLINT_ASSERT(success); nmod_poly_factor(Auf, Au); nmod_mpolyv_fit_length(Af, Auf->num, ctx); Af->length = Auf->num; for (i = 0; i < Auf->num; i++) { FLINT_ASSERT(Auf->exp[i] == 1); _nmod_mpoly_set_nmod_poly(Af->coeffs + i, Abits, Auf->p[i].coeffs, Auf->p[i].length, perm[0], ctx); } nmod_poly_clear(Au); nmod_poly_factor_clear(Auf); success = 1; } else if (nvars == 2) { n_poly_t c; n_bpoly_t Ab; n_tpoly_t Abf; n_poly_init(c); n_bpoly_init(Ab); n_tpoly_init(Abf); nmod_mpoly_get_bpoly(Ab, A, perm[0], perm[1], ctx); success = n_bpoly_mod_factor_smprime(c, Abf, Ab, 1, ctx->mod); if (!success) { nmod_mpoly_get_bpoly(Ab, A, perm[0], perm[1], ctx); n_bpoly_mod_factor_lgprime(c, Abf, Ab, ctx->mod); } FLINT_ASSERT(n_poly_degree(c) == 0); nmod_mpolyv_fit_length(Af, Abf->length, ctx); Af->length = Abf->length; for (i = 0; i < Abf->length; i++) { nmod_mpoly_set_bpoly(Af->coeffs + i, Abits, Abf->coeffs + i, perm[0], perm[1], ctx); nmod_mpoly_make_monic(Af->coeffs + i, Af->coeffs + i, ctx); } n_poly_clear(c); n_bpoly_clear(Ab); n_tpoly_clear(Abf); success = 1; } else { slong Adeg0; nmod_mpoly_t lcA; nmod_mpoly_factor_t lcAf; nmod_mpoly_init(lcA, ctx); nmod_mpoly_factor_init(lcAf, ctx); tot_deg = _deflate(A, tot_deg, strides, perm, ctx); #if FLINT_WANT_ASSERT { nmod_mpoly_t g; nmod_mpoly_init(g, ctx); nmod_mpoly_derivative(g, A, 0, ctx); FLINT_ASSERT(nmod_mpoly_gcd(g, g, A, ctx)); FLINT_ASSERT(nmod_mpoly_is_one(g, ctx)); nmod_mpoly_clear(g, ctx); } #endif Adeg0 = nmod_mpoly_degree_si(A, 0, ctx); if (Adeg0 == 1) { nmod_mpolyv_fit_length(Af, 1, ctx); Af->length = 1; nmod_mpoly_swap(Af->coeffs + 0, A, ctx); success = 1; goto cleanup_inflate; } else if (Adeg0 == 2) { success = _apply_quadratic(Af, A, ctx); goto cleanup_inflate; } success = 0; if (!(algo & (MPOLY_FACTOR_USE_WANG | MPOLY_FACTOR_USE_ZIP))) goto try_zassenhaus; /* TODO lcc_kaltofen */ _nmod_mpoly_get_lead0(lcA, A, ctx); if (!nmod_mpoly_factor(lcAf, lcA, ctx)) goto try_zassenhaus; if (!(algo & MPOLY_FACTOR_USE_ZIP)) { if (success == 0) success = nmod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_medprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_lgprime_wang( Af, A, lcAf, lcA, ctx, state); } else if (!(algo & MPOLY_FACTOR_USE_WANG)) { if (success == 0) success = nmod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_medprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_lgprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { double tdensity; fmpz_t x; fmpz_init(x); fmpz_bin_uiui(x, (ulong)tot_deg + nvars, nvars); tdensity = A->length/fmpz_get_d(x); fmpz_clear(x); if (tdensity > 0.005) { if (success == 0) success = nmod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_medprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_medprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { if (success == 0) success = nmod_mpoly_factor_irred_smprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_medprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_smprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_medprime_wang( Af, A, lcAf, lcA, ctx, state); } if (tdensity > 0.001) { if (success == 0) success = nmod_mpoly_factor_irred_lgprime_wang( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_lgprime_zippel( Af, A, lcAf, lcA, ctx, state); } else { if (success == 0) success = nmod_mpoly_factor_irred_lgprime_zippel( Af, A, lcAf, lcA, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_lgprime_wang( Af, A, lcAf, lcA, ctx, state); } } try_zassenhaus: if (algo & MPOLY_FACTOR_USE_ZAS) { if (success == 0) success = nmod_mpoly_factor_irred_smprime_zassenhaus( Af, A, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_medprime_zassenhaus( Af, A, ctx, state); if (success == 0) success = nmod_mpoly_factor_irred_lgprime_zassenhaus( Af, A, ctx, state); } cleanup_inflate: success = (success > 0); if (success) { for (i = 0; i < Af->length; i++) _inflate(Af->coeffs + i, Abits, strides, perm, ctx); } nmod_mpoly_clear(lcA, ctx); nmod_mpoly_factor_clear(lcAf, ctx); } cleanup: flint_randclear(state); flint_free(strides); flint_free(perm); #if FLINT_WANT_ASSERT if (success) { nmod_mpoly_t prod; nmod_mpoly_init(prod, ctx); nmod_mpoly_one(prod, ctx); for (i = 0; i < Af->length; i++) nmod_mpoly_mul(prod, prod, Af->coeffs + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(prod, Aorg, ctx)); nmod_mpoly_clear(prod, ctx); nmod_mpoly_clear(Aorg, ctx); } #endif FLINT_ASSERT(success == 0 || success == 1); return success; } /* f is already squarefree make the factors in f have the sep property */ static int _refine_sep( nmod_mpolyv_t f, const nmod_mpoly_ctx_t ctx, nmod_mpolyv_t g) /* temp */ { int success; slong v, i; nmod_mpoly_struct * t; nmod_mpoly_univar_t u; nmod_mpoly_univar_init(u, ctx); /* first make primitive */ for (v = 0; v < ctx->minfo->nvars; v++) { g->length = 0; for (i = 0; i < f->length; i++) { nmod_mpoly_to_univar(u, f->coeffs + i, v, ctx); FLINT_ASSERT(u->length > 0); FLINT_ASSERT(fmpz_is_zero(u->exps + u->length - 1)); nmod_mpolyv_fit_length(g, g->length + 2, ctx); success = _nmod_mpoly_vec_content_mpoly(g->coeffs + g->length, u->coeffs, u->length, ctx); if (!success) goto cleanup; if (nmod_mpoly_is_ui(g->coeffs + g->length, ctx)) { nmod_mpoly_swap(g->coeffs + g->length, f->coeffs + i, ctx); g->length++; } else { success = nmod_mpoly_divides(g->coeffs + g->length + 1, f->coeffs + i, g->coeffs + g->length, ctx); FLINT_ASSERT(success); if (nmod_mpoly_is_ui(g->coeffs + g->length + 1, ctx)) g->length += 1; else g->length += 2; } } nmod_mpolyv_swap(f, g, ctx); } /* now make separable/derivative zero wrt each variable */ nmod_mpolyv_fit_length(g, 1, ctx); t = g->coeffs + 0; for (v = 0; v < ctx->minfo->nvars; v++) { i = 0; while (i < f->length) { nmod_mpoly_derivative(t, f->coeffs + i, v, ctx); if (nmod_mpoly_is_zero(t, ctx)) { /* f[i] has zero derivative */ i++; continue; } nmod_mpolyv_fit_length(f, f->length + 1, ctx); success = nmod_mpoly_gcd_cofactors(f->coeffs + f->length, f->coeffs + i, t, f->coeffs + i, t, ctx); if (!success) goto cleanup; if (nmod_mpoly_is_ui(f->coeffs + f->length, ctx)) { /* f[i] is comprime with its derivative */ i++; } else { /* f[i] and f[end] at least got smaller */ f->length++; } } } success = 1; cleanup: nmod_mpoly_univar_clear(u, ctx); return 1; } /* A is sep. return 1 for success, 0 for failure */ static int _factor_irred( nmod_mpolyv_t Af, nmod_mpoly_t A, const nmod_mpoly_ctx_t Actx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t Abits; mpoly_compression_t M; #if FLINT_WANT_ASSERT nmod_mpoly_t Aorg; nmod_mpoly_init(Aorg, Actx); nmod_mpoly_set(Aorg, A, Actx); #endif FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); if (A->length < 2) { FLINT_ASSERT(A->length == 1); FLINT_ASSERT(!nmod_mpoly_is_ui(A, Actx)); nmod_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; nmod_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; goto cleanup_less; } if (A->bits > FLINT_BITS && !nmod_mpoly_repack_bits_inplace(A, FLINT_BITS, Actx)) { success = 0; goto cleanup_less; } Abits = A->bits; mpoly_compression_init(M); mpoly_compression_set(M, A->exps, A->bits, A->length, Actx->minfo); if (M->is_irred) { nmod_mpolyv_fit_length(Af, 1, Actx); Af->length = 1; nmod_mpoly_swap(Af->coeffs + 0, A, Actx); success = 1; } else if (M->is_trivial) { success = _factor_irred_compressed(Af, A, Actx, algo); } else { nmod_mpoly_ctx_t Lctx; nmod_mpolyv_t Lf, Lft, Lfs; nmod_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX, Actx->mod.n); nmod_mpolyv_init(Lf, Lctx); nmod_mpolyv_init(Lft, Lctx); nmod_mpolyv_init(Lfs, Lctx); nmod_mpolyv_fit_length(Lft, 1, Lctx); Lft->length = 1; nmod_mpoly_compression_do(Lft->coeffs + 0, Lctx, A->coeffs, A->length, M); _refine_sep(Lft, Lctx, Lf); if (Lft->length == 1) { success = _factor_irred_compressed(Lf, Lft->coeffs + 0, Lctx, algo); } else { success = 1; Lf->length = 0; for (i = 0; i < Lft->length; i++) { success = _factor_irred(Lfs, Lft->coeffs + i, Lctx, algo); if (!success) break; nmod_mpolyv_fit_length(Lf, Lf->length + Lfs->length, Lctx); for (j = 0; j < Lfs->length; j++) { nmod_mpoly_swap(Lf->coeffs + Lf->length, Lfs->coeffs + j, Lctx); Lf->length++; } } } if (success) { nmod_mpolyv_fit_length(Af, Lf->length, Actx); Af->length = Lf->length; for (i = 0; i < Lf->length; i++) { nmod_mpoly_compression_undo(Af->coeffs + i, Abits, Actx, Lf->coeffs + i, Lctx, M); } } nmod_mpolyv_clear(Lf, Lctx); nmod_mpolyv_clear(Lft, Lctx); nmod_mpolyv_clear(Lfs, Lctx); nmod_mpoly_ctx_clear(Lctx); } mpoly_compression_clear(M); cleanup_less: #if FLINT_WANT_ASSERT if (success) { nmod_mpoly_t prod; nmod_mpoly_init(prod, Actx); nmod_mpoly_one(prod, Actx); for (i = 0; i < Af->length; i++) nmod_mpoly_mul(prod, prod, Af->coeffs + i, Actx); FLINT_ASSERT(nmod_mpoly_equal(prod, Aorg, Actx)); nmod_mpoly_clear(prod, Actx); nmod_mpoly_clear(Aorg, Actx); } #endif FLINT_ASSERT(success == 0 || success == 1); return success; } /* Assume each factor in f is sep. Replace f by an irreducible factorization. */ int nmod_mpoly_factor_irred( nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; nmod_mpolyv_t t; nmod_mpoly_factor_t g; nmod_mpolyv_init(t, ctx); nmod_mpoly_factor_init(g, ctx); g->constant = f->constant; g->num = 0; for (j = 0; j < f->num; j++) { success = _factor_irred(t, f->poly + j, ctx, algo); if (!success) goto cleanup; nmod_mpoly_factor_fit_length(g, g->num + t->length, ctx); for (i = 0; i < t->length; i++) { fmpz_set(g->exp + g->num, f->exp + j); nmod_mpoly_swap(g->poly + g->num, t->coeffs + i, ctx); g->num++; } } nmod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: nmod_mpolyv_clear(t, ctx); nmod_mpoly_factor_clear(g, ctx); return success; } /* append factor(f)^e to g assuming f is compressed and content free */ static int _compressed_content_to_irred( nmod_mpoly_factor_t g, nmod_mpoly_t f, const fmpz_t e, const nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong j, k; nmod_mpoly_factor_t h; nmod_mpolyv_t v; nmod_mpoly_factor_init(h, ctx); nmod_mpolyv_init(v, ctx); success = _nmod_mpoly_factor_separable(h, f, ctx, 1); if (!success) goto cleanup; for (j = 0; j < h->num; j++) { success = h->num > 1 ? _factor_irred(v, h->poly + j, ctx, algo) : _factor_irred_compressed(v, h->poly + j, ctx, algo); if (!success) goto cleanup; nmod_mpoly_factor_fit_length(g, g->num + v->length, ctx); for (k = 0; k < v->length; k++) { fmpz_mul(g->exp + g->num, h->exp + j, e); nmod_mpoly_swap(g->poly + g->num, v->coeffs + k, ctx); g->num++; } } cleanup: nmod_mpoly_factor_clear(h, ctx); nmod_mpolyv_clear(v, ctx); return success; } int nmod_mpoly_factor_algo( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, unsigned int algo) { int success; slong i, j; flint_bitcnt_t bits; nmod_mpoly_factor_t g; mpoly_compression_t M; if (!nmod_mpoly_factor_content(f, A, ctx)) return 0; nmod_mpoly_factor_init(g, ctx); mpoly_compression_init(M); /* write into g */ g->constant = f->constant; g->num = 0; for (i = 0; i < f->num; i++) { if (f->poly[i].length < 2) { nmod_mpoly_factor_fit_length(g, g->num + 1, ctx); nmod_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; continue; } if (f->poly[i].bits > FLINT_BITS && !nmod_mpoly_repack_bits_inplace(f->poly + i, FLINT_BITS, ctx)) { success = 0; goto cleanup; } bits = f->poly[i].bits; mpoly_compression_set(M, f->poly[i].exps, bits, f->poly[i].length, ctx->minfo); if (M->is_irred) { nmod_mpoly_factor_fit_length(g, g->num + 1, ctx); nmod_mpoly_swap(g->poly + g->num, f->poly + i, ctx); fmpz_swap(g->exp + g->num, f->exp + i); g->num++; } else if (M->is_trivial) { success = _compressed_content_to_irred(g, f->poly + i, f->exp + i, ctx, algo); if (!success) goto cleanup; } else { nmod_mpoly_ctx_t Lctx; nmod_mpoly_t L; nmod_mpoly_factor_t h; /* compression may have messed up the content factorization */ nmod_mpoly_ctx_init(Lctx, M->mvars, ORD_LEX, ctx->mod.n); nmod_mpoly_init(L, Lctx); nmod_mpoly_factor_init(h, Lctx); nmod_mpoly_compression_do(L, Lctx, f->poly[i].coeffs, f->poly[i].length, M); if (M->is_perm) { success = _compressed_content_to_irred(h, L, f->exp + i, Lctx, algo); fmpz_one(f->exp + i); } else { success = nmod_mpoly_factor_separable(h, L, Lctx, 1) && nmod_mpoly_factor_irred(h, Lctx, algo); } if (success) { FLINT_ASSERT(h->constant == 1); nmod_mpoly_factor_fit_length(g, g->num + h->num, ctx); for (j = 0; j < h->num; j++) { fmpz_mul(g->exp + g->num, f->exp + i, h->exp + j); nmod_mpoly_compression_undo(g->poly + g->num, bits, ctx, h->poly + j, Lctx, M); g->num++; } } nmod_mpoly_factor_clear(h, Lctx); nmod_mpoly_clear(L, Lctx); nmod_mpoly_ctx_clear(Lctx); if (!success) goto cleanup; } } nmod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: nmod_mpoly_factor_clear(g, ctx); mpoly_compression_clear(M); FLINT_ASSERT(!success || nmod_mpoly_factor_matches(A, f, ctx)); return success; } int nmod_mpoly_factor( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ALL); } int nmod_mpoly_factor_zassenhaus( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZAS); } int nmod_mpoly_factor_wang( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_WANG); } int nmod_mpoly_factor_zippel( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_factor_algo(f, A, ctx, MPOLY_FACTOR_USE_ZIP); } flint-3.1.3/src/nmod_mpoly_factor/factor_content.c000066400000000000000000000116251461254215100223160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" /* either give a non-trivial split a = f*g or establish that a is primitive wrt all variables return: 1: split a = f*g 0: a is primitive wrt all variables (f & g undefined) -1: failed */ static int _split( nmod_mpoly_t f, nmod_mpoly_t g, nmod_mpoly_t a, fmpz_t a_vars_left, const nmod_mpoly_ctx_t ctx, nmod_mpoly_univar_struct * u, /* temp */ slong * vars) { slong i, j, v; slong nvars = ctx->minfo->nvars; slong mvars = 0; for (v = 0; v < nvars; v++) { if (!fmpz_tstbit(a_vars_left, v)) continue; nmod_mpoly_to_univar(u + v, a, v, ctx); vars[mvars] = v; mvars++; } if (mvars < 1) return 0; /* sort vars by decreasing length */ for (i = 1; i < mvars; i++) for (j = i; j > 0 && u[vars[j]].length > u[vars[j - 1]].length; j--) FLINT_SWAP(slong, vars[j], vars[j - 1]); for (i = 0; i < mvars; i++) { v = vars[i]; FLINT_ASSERT(fmpz_tstbit(a_vars_left, v)); fmpz_clrbit(a_vars_left, v); if (u[v].length < 2) { FLINT_ASSERT(u[v].length == 1); FLINT_ASSERT(fmpz_is_zero(u[v].exps + 0)); continue; } if (!_nmod_mpoly_vec_content_mpoly(g, u[v].coeffs, u[v].length, ctx)) return -1; if (g->length < 2) { FLINT_ASSERT(nmod_mpoly_is_one(g, ctx)); continue; } nmod_mpoly_divides(f, a, g, ctx); FLINT_ASSERT(f->length > 1); return 1; } return 0; } /* return factors that are primitive wrt each variable */ int nmod_mpoly_factor_content( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { int success; slong nvars = ctx->minfo->nvars; slong v; nmod_mpoly_univar_struct * u; nmod_mpoly_factor_t g; /* exponents are bitsets */ slong * vars; f->num = 0; if (nmod_mpoly_is_ui(A, ctx)) { f->constant = nmod_mpoly_get_ui(A, ctx); return 1; } vars = FLINT_ARRAY_ALLOC(nvars, slong); nmod_mpoly_factor_init(g, ctx); u = FLINT_ARRAY_ALLOC(nvars, nmod_mpoly_univar_struct); for (v = 0; v < nvars; v++) nmod_mpoly_univar_init(u + v, ctx); /* remove leading coefficient */ FLINT_ASSERT(A->length > 0); f->constant = A->coeffs[0]; nmod_mpoly_factor_fit_length(g, nvars, ctx); nmod_mpoly_make_monic(g->poly + 0, A, ctx); /* remove monomial divisors */ mpoly_remove_var_powers(g->exp, g->poly[0].exps, g->poly[0].bits, g->poly[0].length, ctx->minfo); for (v = 0; v < nvars; v++) { if (fmpz_is_zero(g->exp + v)) continue; nmod_mpoly_factor_fit_length(f, f->num + 1, ctx); nmod_mpoly_gen(f->poly + f->num, v, ctx); fmpz_swap(f->exp + f->num, g->exp + v); f->num++; } /* done if g->poly[0] is constant */ if (g->poly[0].length == 1) { success = 1; goto cleanup; } /* g has length one and no variable has been checked yet */ fmpz_one(g->exp + 0); fmpz_mul_2exp(g->exp + 0, g->exp + 0, nvars); fmpz_sub_ui(g->exp + 0, g->exp + 0, 1); g->num = 1; while (g->num > 0) { slong t = g->num - 1; nmod_mpoly_factor_fit_length(g, t + 3, ctx); success = _split(g->poly + t + 2, g->poly + t + 1, g->poly + t, g->exp + t, ctx, u, vars); if (success < 0) { success = 0; goto cleanup; } else if (success == 0) { FLINT_ASSERT(!nmod_mpoly_is_ui(g->poly + t, ctx)); nmod_mpoly_factor_fit_length(f, f->num + 1, ctx); nmod_mpoly_swap(f->poly + f->num, g->poly + t, ctx); fmpz_one(f->exp + f->num); f->num++; g->num = t; } else { FLINT_ASSERT(!nmod_mpoly_is_ui(g->poly + t + 1, ctx)); FLINT_ASSERT(!nmod_mpoly_is_ui(g->poly + t + 2, ctx)); nmod_mpoly_swap(g->poly + t, g->poly + t + 2, ctx); fmpz_set(g->exp + t + 1, g->exp + t); g->num = t + 2; } } success = 1; cleanup: nmod_mpoly_factor_clear(g, ctx); for (v = 0; v < nvars; v++) nmod_mpoly_univar_clear(u + v, ctx); flint_free(u); flint_free(vars); FLINT_ASSERT(!success || nmod_mpoly_factor_matches(A, f, ctx)); return success; } flint-3.1.3/src/nmod_mpoly_factor/factor_squarefree.c000066400000000000000000000264421461254215100230110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "fmpz.h" #include "fmpz_vec.h" #include "nmod_mpoly_factor.h" static void nmod_mpoly_factor_mul_mpoly_fmpz( nmod_mpoly_factor_t fac, const nmod_mpoly_t a, const fmpz_t e, const nmod_mpoly_ctx_t ctx) { if (nmod_mpoly_is_ui(a, ctx)) { ulong t = nmod_mpoly_get_ui(a, ctx); t = nmod_pow_fmpz(t, e, ctx->mod); fac->constant = nmod_mul(fac->constant, t, ctx->mod); return; } else { nmod_mpoly_factor_append_fmpz(fac, a, e, ctx); } } #if FLINT_WANT_ASSERT /* return: 0 no 1 yes -1 don't know */ static int nmod_mpoly_factor_is_pairwise_prime( const nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { int result; slong i, j; nmod_mpoly_t g; nmod_mpoly_init(g, ctx); for (i = 0; i + 1 < f->num; i++) for (j = i + 1; j < f->num; j++) { /* make sure factors are monic */ if (f->poly[i].length < 1 || f->poly[j].length < 1 || f->poly[i].coeffs[0] != 1 || f->poly[j].coeffs[0] != 1) { result = 0; goto cleanup; } if (nmod_mpoly_gcd(g, f->poly + i, f->poly + j, ctx)) { if (!nmod_mpoly_is_one(g, ctx)) { result = 0; goto cleanup; } } else { result = -1; goto cleanup; } } result = 1; cleanup: nmod_mpoly_clear(g, ctx); return result; } #endif /* b and c are pairwise prime produce a=b*c pairwise prime and return 1 else return 0 with a undefined */ static int nmod_mpoly_factor_mul_pairwise_prime( nmod_mpoly_factor_t a, const nmod_mpoly_factor_t b, const nmod_mpoly_factor_t c, const nmod_mpoly_ctx_t ctx) { int success; slong i, j; nmod_mpoly_t T1, T2; nmod_mpoly_struct * g; fmpz_t t; if (a == b || a == c) { nmod_mpoly_factor_t ta; nmod_mpoly_factor_init(ta, ctx); success = nmod_mpoly_factor_mul_pairwise_prime(ta, b, c, ctx); nmod_mpoly_factor_swap(a, ta, ctx); nmod_mpoly_factor_clear(ta, ctx); return success; } fmpz_init(t); nmod_mpoly_init(T1, ctx); nmod_mpoly_init(T2, ctx); FLINT_ASSERT(nmod_mpoly_factor_is_pairwise_prime(b, ctx) == 1); FLINT_ASSERT(nmod_mpoly_factor_is_pairwise_prime(c, ctx) == 1); g = (nmod_mpoly_struct *) flint_malloc(b->num*c->num*sizeof(nmod_mpoly_struct)); /* g[i,j] = gcd(b[i], c[j]) */ for (i = 0; i < b->num; i++) for (j = 0; j < c->num; j++) nmod_mpoly_init(g + i*c->num + j, ctx); a->constant = nmod_mul(b->constant, c->constant, ctx->mod); a->num = 0; for (i = 0; i < b->num; i++) for (j = 0; j < c->num; j++) { if (!nmod_mpoly_gcd(g + i*c->num + j, b->poly + i, c->poly + j, ctx)) { success = 0; goto cleanup; } fmpz_add(t, b->exp + i, c->exp + j); nmod_mpoly_factor_mul_mpoly_fmpz(a, g + i*c->num + j, t, ctx); } for (i = 0; i < b->num; i++) { nmod_mpoly_set(T1, b->poly + i, ctx); for (j = 0; j < c->num; j++) { success = nmod_mpoly_divides(T1, T1, g + i*c->num + j, ctx); FLINT_ASSERT(success); } nmod_mpoly_factor_mul_mpoly_fmpz(a, T1, b->exp + i, ctx); } for (j = 0; j < c->num; j++) { nmod_mpoly_set(T1, c->poly + j, ctx); for (i = 0; i < b->num; i++) { success = nmod_mpoly_divides(T1, T1, g + i*c->num + j, ctx); FLINT_ASSERT(success); } nmod_mpoly_factor_mul_mpoly_fmpz(a, T1, c->exp + j, ctx); } success = 1; cleanup: for (i = 0; i < b->num; i++) for (j = 0; j < c->num; j++) nmod_mpoly_clear(g + i*c->num + j, ctx); flint_free(g); nmod_mpoly_clear(T1, ctx); nmod_mpoly_clear(T2, ctx); fmpz_clear(t); if (success) { nmod_mpoly_t ae, be, ce; nmod_mpoly_init(ae, ctx); nmod_mpoly_init(be, ctx); nmod_mpoly_init(ce, ctx); FLINT_ASSERT(nmod_mpoly_factor_is_pairwise_prime(a, ctx) == 1); nmod_mpoly_factor_expand(be, b, ctx); nmod_mpoly_factor_expand(ce, c, ctx); nmod_mpoly_mul(ae, be, ce, ctx); FLINT_ASSERT(nmod_mpoly_factor_matches(ae, a, ctx)); nmod_mpoly_clear(ae, ctx); nmod_mpoly_clear(be, ctx); nmod_mpoly_clear(ce, ctx); } return success; } /* a has zero derivative wrt gen(i) for all i for which vars_left[i] = 0 gcd(a, derivative(a, gen(var))) = 1 sep = false: just tack on a sep = true: make sure either 1. derivative(a, gen(var)) = 0, or 2. gcd(a, derivative(a, gen(i))) = 1 holds for the other factors for all i for which vars_left[i] != 0 */ static int _append_factor_sep( nmod_mpoly_factor_t f, nmod_mpoly_t a, ulong k, int * vars_left, const nmod_mpoly_ctx_t ctx, int sep, nmod_mpoly_t t) /* temp */ { slong v, org = f->num; if (nmod_mpoly_is_ui(a, ctx)) { FLINT_ASSERT(nmod_mpoly_is_one(a, ctx)); return 1; } nmod_mpoly_factor_fit_length(f, org + 1, ctx); nmod_mpoly_swap(f->poly + org, a, ctx); fmpz_set_ui(f->exp + org, k); f->num = org + 1; if (!sep) return 1; for (v = 0; v < ctx->minfo->nvars; v++) { slong i = org; if (!vars_left[v]) continue; while (i < f->num) { nmod_mpoly_derivative(t, f->poly + i, v, ctx); if (nmod_mpoly_is_zero(t, ctx)) { /* f[i] has zero derivative */ i++; continue; } nmod_mpoly_factor_fit_length(f, f->num + 1, ctx); fmpz_set_ui(f->exp + f->num, k); if (!nmod_mpoly_gcd_cofactors(f->poly + f->num, f->poly + i, t, f->poly + i, t, ctx)) { return 0; } if (nmod_mpoly_is_ui(f->poly + f->num, ctx)) { /* f[i] is comprime with its derivative */ i++; } else { /* f[i] and f[end] at least got smaller */ f->num++; } } } return 1; } int _nmod_mpoly_factor_separable( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, int sep) { int success; slong v, var, j; ulong k; int * vars_left; fmpz * shift, * stride; nmod_mpoly_factor_t Tf; fmpz_t g, gr, p, pk; nmod_mpoly_t B, C, U, V, W, G; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); nmod_mpoly_init(B, ctx); nmod_mpoly_init(C, ctx); nmod_mpoly_init(U, ctx); nmod_mpoly_init(V, ctx); nmod_mpoly_init(W, ctx); nmod_mpoly_init(G, ctx); fmpz_init_set_ui(p, ctx->mod.n); fmpz_init(pk); fmpz_init(g); fmpz_init(gr); nmod_mpoly_factor_init(Tf, ctx); shift = _fmpz_vec_init(ctx->minfo->nvars); stride = _fmpz_vec_init(ctx->minfo->nvars); vars_left = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, int); for (v = 0; v < ctx->minfo->nvars; v++) vars_left[v] = 1; nmod_mpoly_factor_one(f, ctx); nmod_mpoly_set(C, A, ctx); for (j = 0; j < ctx->minfo->nvars; j++) { /* take the next variable with shortest derivative */ var = -1; for (v = 0; v < ctx->minfo->nvars; v++) { if (!vars_left[v]) continue; nmod_mpoly_derivative(U, C, v, ctx); if (var < 0 || U->length < G->length) { var = v; nmod_mpoly_swap(G, U, ctx); } } FLINT_ASSERT(var >= 0); FLINT_ASSERT(vars_left[var] == 1); vars_left[var] = 0; success = nmod_mpoly_gcd_cofactors(C, W, V, C, G, ctx); if (!success) goto cleanup; for (k = 1; k + 1 < ctx->mod.n && !(nmod_mpoly_derivative(G, W, var, ctx), nmod_mpoly_sub(U, V, G, ctx), nmod_mpoly_is_zero(U, ctx)); k++) { success = nmod_mpoly_gcd_cofactors(G, W, V, W, U, ctx); if (!success) goto cleanup; success = _append_factor_sep(f, G, k, vars_left, ctx, sep, U); if (!success) goto cleanup; if (!nmod_mpoly_is_one(W, ctx)) { success = nmod_mpoly_divides(U, C, W, ctx); FLINT_ASSERT(success); nmod_mpoly_swap(C, U, ctx); } } success = _append_factor_sep(f, W, k, vars_left, ctx, sep, U); if (!success) goto cleanup; } if (nmod_mpoly_is_ui(C, ctx)) { FLINT_ASSERT(nmod_mpoly_is_one(C, ctx)); } else { nmod_mpoly_deflation(shift, stride, C, ctx); fmpz_zero(g); for (var = 0; var < ctx->minfo->nvars; var++) { fmpz_gcd(g, g, stride + var); fmpz_gcd(g, g, shift + var); } fmpz_pow_ui(pk, p, fmpz_remove(gr, g, p)); FLINT_ASSERT(fmpz_cmp_ui(pk, 1) > 0); for (var = 0; var < ctx->minfo->nvars; var++) { fmpz_set(stride + var, pk); fmpz_zero(shift + var); } nmod_mpoly_deflate(C, C, shift, stride, ctx); success = _nmod_mpoly_factor_separable(Tf, C, ctx, sep); if (!success) goto cleanup; /* f *= Tf^pk */ FLINT_ASSERT(Tf->constant == 1); _fmpz_vec_scalar_mul_fmpz(Tf->exp, Tf->exp, Tf->num, pk); nmod_mpoly_factor_mul_pairwise_prime(f, f, Tf, ctx); } success = 1; cleanup: nmod_mpoly_clear(C, ctx); nmod_mpoly_clear(U, ctx); nmod_mpoly_clear(V, ctx); nmod_mpoly_clear(W, ctx); nmod_mpoly_clear(G, ctx); fmpz_clear(p); fmpz_clear(pk); fmpz_clear(g); fmpz_clear(gr); nmod_mpoly_factor_clear(Tf, ctx); _fmpz_vec_clear(shift, ctx->minfo->nvars); _fmpz_vec_clear(stride, ctx->minfo->nvars); flint_free(vars_left); return success; } /* if sep = true, each returned factor should satisfy: (1) monic (2) primitive wrt each variable (3) for all i, derivative(a, gen(i)) = 0, or gcd(a, derivative(a, gen(i))) = 1 (4) there is at least i for which derivative(a, gen(i)) != 0 otherwise, the factors are just squarefree */ int nmod_mpoly_factor_separable( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, int sep) { int success; slong i, j; nmod_mpoly_factor_t g, t; if (!nmod_mpoly_factor_content(f, A, ctx)) return 0; nmod_mpoly_factor_init(g, ctx); nmod_mpoly_factor_init(t, ctx); g->constant = f->constant; g->num = 0; for (j = 0; j < f->num; j++) { success = _nmod_mpoly_factor_separable(t, f->poly + j, ctx, sep); if (!success) goto cleanup; FLINT_ASSERT(1 == t->constant); nmod_mpoly_factor_fit_length(g, g->num + t->num, ctx); for (i = 0; i < t->num; i++) { fmpz_mul(g->exp + g->num, t->exp + i, f->exp + j); nmod_mpoly_swap(g->poly + g->num, t->poly + i, ctx); g->num++; } } nmod_mpoly_factor_swap(f, g, ctx); success = 1; cleanup: nmod_mpoly_factor_clear(t, ctx); nmod_mpoly_factor_clear(g, ctx); FLINT_ASSERT(!success || nmod_mpoly_factor_matches(A, f, ctx)); return success; } int nmod_mpoly_factor_squarefree( nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { return nmod_mpoly_factor_separable(f, A, ctx, 0); } flint-3.1.3/src/nmod_mpoly_factor/fit_length.c000066400000000000000000000014131461254215100214230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" void nmod_mpoly_factor_fit_length(nmod_mpoly_factor_t fac, slong len, const nmod_mpoly_ctx_t ctx) { if (len > fac->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * fac->alloc) len = 2 * fac->alloc; nmod_mpoly_factor_realloc(fac, len, ctx); } } flint-3.1.3/src/nmod_mpoly_factor/gcd_zippel.c000066400000000000000000000631471461254215100214340ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" /* set up mock to point to the coefficients of A, which are not owned by mock */ static void nmod_mpoly_mock_eval_coeff( n_polyun_t mock, const nmod_mpoly_t A, const n_polyun_t Aeh_inc, const nmod_mpoly_ctx_t ctx) { slong i, k; if (mock->alloc < Aeh_inc->length) { mock->alloc = FLINT_MAX(Aeh_inc->length, mock->alloc + mock->alloc/2); mock->coeffs = FLINT_ARRAY_REALLOC(mock->coeffs, mock->alloc, n_poly_struct); } mock->length = Aeh_inc->length; k = 0; for (i = 0; i < Aeh_inc->length; i++) { slong l = Aeh_inc->coeffs[i].length; mock->coeffs[i].coeffs = A->coeffs + k; mock->coeffs[i].alloc = l; mock->coeffs[i].length = l; k += l; } FLINT_ASSERT(k == A->length); } static void nmod_mpoly_monomial_evals1( n_polyun_t E, const nmod_mpoly_t A, const ulong * Amarks, slong Amarkslen, n_poly_struct * betas, slong m, const nmod_mpoly_ctx_t ctx) { mpoly1_monomial_evals_nmod(E, A->exps, A->bits, Amarks, Amarkslen, betas, m, ctx->minfo, ctx->mod); } static void n_polyu1n_mod_zip_eval_cur_inc_coeff( n_poly_t E, n_polyun_t Acur, const n_polyun_t Ainc, const n_polyun_t Acoeff, const nmod_t ctx) { slong i; mp_limb_t c; FLINT_ASSERT(Acur->length > 0); FLINT_ASSERT(Acur->length == Ainc->length); FLINT_ASSERT(Acur->length == Acoeff->length); n_poly_zero(E); for (i = 0; i < Acur->length; i++) { slong this_len = Acur->coeffs[i].length; FLINT_ASSERT(this_len == Ainc->coeffs[i].length); FLINT_ASSERT(this_len == Acoeff->coeffs[i].length); c = _nmod_zip_eval_step(Acur->coeffs[i].coeffs, Ainc->coeffs[i].coeffs, Acoeff->coeffs[i].coeffs, this_len, ctx); n_poly_set_coeff(E, Acur->exps[i], c); } } static int n_poly_add_zip_must_match( n_polyun_t Z, n_poly_t A, slong cur_length) { slong i, ai; slong Alen = A->length; ulong * Zexps = Z->exps; n_poly_struct * Zcoeffs = Z->coeffs; mp_limb_t * Acoeffs = A->coeffs; ai = Alen - 1; for (i = 0; i < Z->length; i++) { if (ai >= 0 && Zexps[i] == ai) { /* Z present, A present */ Zcoeffs[i].coeffs[cur_length] = Acoeffs[ai]; Zcoeffs[i].length = cur_length + 1; do { ai--; } while (ai >= 0 && Acoeffs[ai] == 0); } else if (ai < 0 || Zexps[i] > ai) { /* Z present, A missing */ Zcoeffs[i].coeffs[cur_length] = 0; Zcoeffs[i].length = cur_length + 1; } else { /* Z missing, A present */ return 0; } } return ai < 0; } static mp_limb_t * nmod_mat_row_ref(nmod_mat_t M, slong i) { return M->rows[i]; } static void _nmod_vec_mul(mp_limb_t * a, mp_limb_t * b, mp_limb_t * c, slong n, nmod_t ctx) { for (n--; n >= 0; n--) a[n] = nmod_mul(b[n], c[n], ctx); } /* Try to set G to the gcd of A and B given the form f of G. f = sum_i X^i sum_j c_ij x^e_j images are formed from evaluation at x = alpha^(k+1), 0 <= k < l Assume all image gcds have the same degree and are sum_i X^i g_ik, 0 <= k < l Then, for each 0 <= k < l there is a scalar factor s_k such that sum_j c_ij alpha^((k+1)e_j) = s_k g_ik for 0 <= i <= degree(gcd) */ int nmod_mpolyl_gcds_zippel( nmod_mpoly_t G, const ulong * Gmarks, slong Gmarkslen, nmod_mpoly_t A, nmod_mpoly_t B, slong *perm, slong l, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t state, slong * Gdegbound, n_poly_t Amarks, /* temps */ n_poly_t Bmarks) { int success; int betas_tries_left, underdetermined_left, exceeded_left; slong i, s, S, n, cur_zip_image; slong Adeg, Bdeg, Gdeg; flint_bitcnt_t bits = A->bits; n_poly_t Aev, Bev, Gev; n_polyun_t Aeh_inc, Aeh_cur, Aeh_coeff_mock; n_polyun_t Beh_inc, Beh_cur, Beh_coeff_mock; n_polyun_t HG, MG, ZG; mp_limb_t * betas; n_poly_struct * beta_caches; nmod_mat_struct * ML; nmod_mat_t MF, Msol, MFtemp, Mwindow; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(1 < var && var <= ctx->minfo->nvars); FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(G->length > 0); FLINT_ASSERT(Gmarkslen > 0); FLINT_ASSERT(*Gdegbound == mpoly_degree_si(G->exps, G->length, bits, 0, ctx->minfo)); if (Gmarkslen < 2) { G->coeffs[0] = 1; return Gmarks[1] - Gmarks[0] == 1; } betas = FLINT_ARRAY_ALLOC(var, mp_limb_t); beta_caches = FLINT_ARRAY_ALLOC(3*var, n_poly_struct); for (i = 0; i < var; i++) { n_poly_init(beta_caches + 3*i + 0); n_poly_init(beta_caches + 3*i + 1); n_poly_init(beta_caches + 3*i + 2); } ML = FLINT_ARRAY_ALLOC(Gmarkslen, nmod_mat_struct); for (i = 0; i < Gmarkslen; i++) nmod_mat_init(ML + i, 0, 0, nmod_mpoly_ctx_modulus(ctx)); nmod_mat_init(MF, 0, l, nmod_mpoly_ctx_modulus(ctx)); nmod_mat_init(Msol, l, 1, nmod_mpoly_ctx_modulus(ctx)); n_poly_init(Aev); n_poly_init(Bev); n_poly_init(Gev); n_polyun_init(Aeh_inc); n_polyun_init(Aeh_cur); n_polyun_init(Beh_inc); n_polyun_init(Beh_cur); Aeh_coeff_mock->exps = NULL; Aeh_coeff_mock->coeffs = NULL; Aeh_coeff_mock->length = 0; Aeh_coeff_mock->alloc = 0; Beh_coeff_mock->exps = NULL; Beh_coeff_mock->coeffs = NULL; Beh_coeff_mock->length = 0; Beh_coeff_mock->alloc = 0; n_polyun_init(HG); n_polyun_init(MG); n_polyun_init(ZG); Adeg = nmod_mpoly_degree_si(A, 0, ctx); Bdeg = nmod_mpoly_degree_si(B, 0, ctx); mpoly1_fill_marks(&Amarks->coeffs, &Amarks->length, &Amarks->alloc, A->exps, A->length, bits, ctx->minfo); mpoly1_fill_marks(&Bmarks->coeffs, &Bmarks->length, &Bmarks->alloc, B->exps, B->length, bits, ctx->minfo); betas_tries_left = 10; underdetermined_left = 3; exceeded_left = 3; next_betas: if (--betas_tries_left < 0) { success = -1; goto cleanup; } for (i = 1; i < var; i++) { betas[i] = 1 + n_randint(state, nmod_mpoly_ctx_modulus(ctx) - 1); nmod_pow_cache_start(betas[i], beta_caches + 3*i + 0, beta_caches + 3*i + 1, beta_caches + 3*i + 2); } nmod_mpoly_monomial_evals1(Aeh_inc, A, Amarks->coeffs, Amarks->length, beta_caches + 3*1, var, ctx); nmod_mpoly_monomial_evals1(Beh_inc, B, Bmarks->coeffs, Bmarks->length, beta_caches + 3*1, var, ctx); n_polyun_set(Aeh_cur, Aeh_inc); n_polyun_set(Beh_cur, Beh_inc); nmod_mpoly_mock_eval_coeff(Aeh_coeff_mock, A, Aeh_inc, ctx); nmod_mpoly_mock_eval_coeff(Beh_coeff_mock, B, Beh_inc, ctx); nmod_mpoly_monomial_evals1(HG, G, Gmarks, Gmarkslen, beta_caches + 3*1, var, ctx); n_polyun_zip_start(ZG, HG, l); n = n_polyun_product_roots(MG, HG, ctx->mod); FLINT_ASSERT(n <= l); for (cur_zip_image = 0; cur_zip_image < l; cur_zip_image++) { n_polyu1n_mod_zip_eval_cur_inc_coeff(Aev, Aeh_cur, Aeh_inc, Aeh_coeff_mock, ctx->mod); n_polyu1n_mod_zip_eval_cur_inc_coeff(Bev, Beh_cur, Beh_inc, Beh_coeff_mock, ctx->mod); if (n_poly_degree(Aev) != Adeg) goto next_betas; if (n_poly_degree(Bev) != Bdeg) goto next_betas; n_poly_mod_gcd(Gev, Aev, Bev, ctx->mod); Gdeg = n_poly_degree(Gev); if (Gdeg > *Gdegbound) { if (--exceeded_left >= 0) goto next_betas; success = -1; goto cleanup; } if (Gdeg < *Gdegbound) { *Gdegbound = Gdeg; success = 0; goto cleanup; } if (!n_poly_add_zip_must_match(ZG, Gev, cur_zip_image)) goto next_betas; } nmod_mat_clear(Msol); nmod_mat_init(Msol, 1, l, nmod_mpoly_ctx_modulus(ctx)); s = perm[0]; if (Gmarks[s + 1] - Gmarks[s] == 1) { /* monic case */ mp_limb_t temp = 1; for (i = 0; i < l; i++) { temp = nmod_mul(temp, HG->coeffs[s].coeffs[0], ctx->mod); if (ZG->coeffs[s].coeffs[i] == 0) goto general_case; nmod_mat_entry(Msol, 0, i) = nmod_div(temp, ZG->coeffs[s].coeffs[i], ctx->mod); } goto try_it; } general_case: nmod_mat_clear(Msol); nmod_mat_init(Msol, 0, l, nmod_mpoly_ctx_modulus(ctx)); nmod_mat_clear(MF); nmod_mat_init(MF, 0, l, nmod_mpoly_ctx_modulus(ctx)); for (S = 0; S < Gmarkslen; S++) { s = perm[S]; n = Gmarks[s + 1] - Gmarks[s]; FLINT_ASSERT(n <= l); if (nmod_mat_nrows(ML + s) != l || nmod_mat_ncols(ML + s) != l + n) { nmod_mat_clear(ML + s); nmod_mat_init(ML + s, l, l + n, nmod_mpoly_ctx_modulus(ctx)); } _nmod_vec_set(nmod_mat_row_ref(ML + s, 0), HG->coeffs[s].coeffs, n); for (i = 1; i < l; i++) { _nmod_vec_mul(nmod_mat_row_ref(ML + s, i), nmod_mat_row_ref(ML + s, i - 1), HG->coeffs[s].coeffs, n, ctx->mod); } for (i = 0; i < l; i++) { _nmod_vec_zero(nmod_mat_row_ref(ML + s, i) + n, l); nmod_mat_entry(ML + s, i, n + i) = ZG->coeffs[s].coeffs[i]; } /* l x (n + l) matrix ML[s] n l | monomial evals 1 | image coeffs 0 | l | ... | on the | | monomial evals l | 0 diagonal | */ nmod_mat_rref(ML + s); for (i = 0; i < n; i++) if (nmod_mat_entry(ML + s, i, i) != 1) goto next_betas; /* delete zero rows from MF, matrix interface makes this fun */ i = nmod_mat_nrows(MF); while (i > 1 && _nmod_vec_is_zero(nmod_mat_row_ref(MF, i - 1), l)) i--; if (i < nmod_mat_nrows(MF)) { nmod_mat_window_init(Mwindow, MF, 0, 0, i, l); nmod_mat_init(MFtemp, i, l, nmod_mpoly_ctx_modulus(ctx)); nmod_mat_set(MFtemp, Mwindow); nmod_mat_swap(MF, MFtemp); nmod_mat_clear(MFtemp); nmod_mat_window_clear(Mwindow); } /* appends rows to MF */ nmod_mat_window_init(Mwindow, ML + s, n, n, l, n + l); nmod_mat_init(MFtemp, i + l - n, l, nmod_mpoly_ctx_modulus(ctx)); nmod_mat_concat_vertical(MFtemp, MF, Mwindow); nmod_mat_swap(MF, MFtemp); nmod_mat_clear(MFtemp); nmod_mat_window_clear(Mwindow); nmod_mat_clear(Msol); nmod_mat_init_nullspace_tr(Msol, MF); if (nmod_mat_nrows(Msol) < 1) { success = 0; goto cleanup; } if (nmod_mat_nrows(Msol) == 1) break; } if (nmod_mat_nrows(Msol) != 1) { if (--underdetermined_left >= 0) goto next_betas; success = -1; goto cleanup; } try_it: /* the first row of Msol has the scales */ for (s = 0; s < Gmarkslen; s++) { _nmod_vec_mul(ZG->coeffs[s].coeffs, ZG->coeffs[s].coeffs, nmod_mat_row_ref(Msol, 0), l, ctx->mod); } success = n_polyun_zip_solve(G, ZG, HG, MG, ctx); if (success < 0) goto next_betas; cleanup: n_poly_clear(Aev); n_poly_clear(Bev); n_poly_clear(Gev); for (i = 0; i < var; i++) { n_poly_clear(beta_caches + 3*i + 0); n_poly_clear(beta_caches + 3*i + 1); n_poly_clear(beta_caches + 3*i + 2); } flint_free(beta_caches); flint_free(betas); for (i = 0; i < Gmarkslen; i++) nmod_mat_clear(ML + i); flint_free(ML); nmod_mat_clear(MF); nmod_mat_clear(Msol); n_polyun_clear(Aeh_inc); n_polyun_clear(Aeh_cur); n_polyun_clear(Beh_inc); n_polyun_clear(Beh_cur); flint_free(Aeh_coeff_mock->coeffs); flint_free(Beh_coeff_mock->coeffs); n_polyun_clear(HG); n_polyun_clear(MG); n_polyun_clear(ZG); return success; } static int _do_bivar_or_univar( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, nmod_mpoly_t A, nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { if (var == 1) { int success; n_poly_t c; n_polyun_t Aev, Bev, Gev, Abarev, Bbarev; n_poly_polyun_stack_t St; n_poly_stack_init(St->poly_stack); n_polyun_stack_init(St->polyun_stack); n_polyun_init(Aev); n_polyun_init(Bev); n_polyun_init(Gev); n_polyun_init(Abarev); n_polyun_init(Bbarev); n_poly_init(c); nmod_mpoly_get_polyu1n(Aev, A, 0, 1, ctx); nmod_mpoly_get_polyu1n(Bev, B, 0, 1, ctx); success = n_polyu1n_mod_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev, ctx->mod, St); if (success) { _n_poly_vec_mod_content(c, Gev->coeffs, Gev->length, ctx->mod); success = n_poly_is_one(c); nmod_mpoly_set_polyu1n(G, Gev, 0, 1, ctx); } n_poly_clear(c); n_polyun_clear(Aev); n_polyun_clear(Bev); n_polyun_clear(Gev); n_polyun_clear(Abarev); n_polyun_clear(Bbarev); n_poly_stack_clear(St->poly_stack); n_polyun_stack_clear(St->polyun_stack); return success; } else { n_poly_t a, b, c; n_poly_init(a); n_poly_init(b); n_poly_init(c); nmod_mpoly_get_n_poly(a, A, 0, ctx); nmod_mpoly_get_n_poly(b, B, 0, ctx); n_poly_mod_gcd(c, a, b, ctx->mod); _nmod_mpoly_set_nmod_poly(G, G->bits, c->coeffs, c->length, 0, ctx); n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); return 1; } } /* A and B depend only on x_0, ..., x_var. Assume content_x0(G) = 1, and fail otherwise when var = 1, this is checked explicitly. when var = 2, The possibility of f(x2) | G(x0,x1,x2) for nonconstant f(x2) is ruled out by the explicit check. suppose f(x1,x2) | G(x0,x1,x2) where f is not in Fp[x2] the evaluation point x2 = a2 is chosen so that lc_{x0,x1}(G(x0,x1,x2)) does not vanish at x2 = a2. This means that lc_x1(f(x1, x2)) does not vanish at x2 = a2, and so f(x1, a2) is a nontrivial divisor of G(x0,x1,a2) which would be caught by the recursive call. ... */ int nmod_mpolyl_gcdp_zippel_smprime( nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, nmod_mpoly_t A, nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { flint_bitcnt_t bits = A->bits; slong i, j, N = mpoly_words_per_exp_sp(bits, ctx->minfo); slong Adeg, Bdeg, Alastdeg, Blastdeg, Gdeg; slong bound, Gdegbound, lastdeg, req_zip_images; int success, changed, have_enough; mp_limb_t alpha, start_alpha, gammaeval, temp; n_poly_t a, b, c, gamma, modulus, alphapow; nmod_mpoly_t Ac, Bc, Aeval, Beval, Geval, Abareval, Bbareval; nmod_mpolyn_t H, T; n_poly_t Amarks, Bmarks, Gmarks; slong * perm = NULL; FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); FLINT_ASSERT(0 <= var && var < ctx->minfo->nvars); FLINT_ASSERT(A->bits == bits); FLINT_ASSERT(B->bits == bits); FLINT_ASSERT(G->bits == bits); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(B->length > 0); if (var < 2) return _do_bivar_or_univar(G, Abar, Bbar, A, B, var, ctx, state); nmod_mpoly_init3(Ac, 0, bits, ctx); nmod_mpoly_init3(Bc, 0, bits, ctx); nmod_mpoly_init3(Aeval, 0, bits, ctx); nmod_mpoly_init3(Beval, 0, bits, ctx); nmod_mpoly_init3(Geval, 0, bits, ctx); nmod_mpoly_init3(Abareval, 0, bits, ctx); nmod_mpoly_init3(Bbareval, 0, bits, ctx); n_poly_init(a); n_poly_init(b); n_poly_init(c); n_poly_init(gamma); n_poly_init(modulus); n_poly_init2(alphapow, 3); nmod_mpolyn_init(H, bits, ctx); nmod_mpolyn_init(T, bits, ctx); n_poly_init(Amarks); n_poly_init(Bmarks); n_poly_init(Gmarks); nmod_mpolyl_content(Ac, A, var, ctx); if (!nmod_mpoly_is_one(Ac, ctx)) { success = nmod_mpoly_divides(A, A, Ac, ctx); FLINT_ASSERT(success); } nmod_mpolyl_content(Bc, B, var, ctx); if (!nmod_mpoly_is_one(Bc, ctx)) { success = nmod_mpoly_divides(B, B, Bc, ctx); FLINT_ASSERT(success); } nmod_mpoly_get_n_poly(a, Ac, var, ctx); nmod_mpoly_get_n_poly(b, Bc, var, ctx); n_poly_mod_gcd(c, a, b, ctx->mod); success = n_poly_is_one(c); if (!success) goto cleanup; nmod_mpolyl_lead_coeff(Ac, A, var, ctx); nmod_mpolyl_lead_coeff(Bc, B, var, ctx); nmod_mpoly_get_n_poly(a, Ac, var, ctx); nmod_mpoly_get_n_poly(b, Bc, var, ctx); n_poly_mod_gcd(gamma, a, b, ctx->mod); /* degree bound on the gcd */ Adeg = nmod_mpoly_degree_si(A, 0, ctx); Bdeg = nmod_mpoly_degree_si(B, 0, ctx); Gdegbound = FLINT_MIN(Adeg, Bdeg); /* bound of the number of images required */ Alastdeg = nmod_mpoly_degree_si(A, var, ctx); Blastdeg = nmod_mpoly_degree_si(B, var, ctx); bound = 1 + FLINT_MIN(Alastdeg, Blastdeg) + n_poly_degree(gamma); n_poly_one(modulus); start_alpha = 1 + n_randint(state, ctx->mod.n - 1); alpha = start_alpha; outer_loop: /* get new evaluation point */ if (alpha < 2) alpha = ctx->mod.n; alpha -= 1; success = (alpha != start_alpha); if (!success) goto cleanup; FLINT_ASSERT(alphapow->alloc >= 2); alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; alphapow->length = 2; /* make sure evaluation point does not kill both lc(A) and lc(B) */ gammaeval = n_poly_mod_eval_pow(gamma, alphapow, ctx->mod); if (gammaeval == 0) goto outer_loop; /* make sure evaluation point does not kill either A or B */ nmod_mpoly_evaluate_one_ui(Aeval, A, var, alpha, ctx); nmod_mpoly_evaluate_one_ui(Beval, B, var, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) goto outer_loop; nmod_mpoly_repack_bits_inplace(Aeval, bits, ctx); nmod_mpoly_repack_bits_inplace(Beval, bits, ctx); success = nmod_mpolyl_gcdp_zippel_smprime(Geval, Abareval, Bbareval, Aeval, Beval, var - 1, ctx, state); if (!success) goto cleanup; FLINT_ASSERT(Geval->length > 0); FLINT_ASSERT(Geval->coeffs[0] == 1); if (nmod_mpoly_is_one(Geval, ctx)) { nmod_mpoly_one(G, ctx); nmod_mpoly_set(Abar, A, ctx); nmod_mpoly_set(Bbar, B, ctx); success = 1; goto cleanup; } Gdeg = nmod_mpoly_degree_si(Geval, 0, ctx); if (Gdeg > Gdegbound) goto outer_loop; if (Gdeg < Gdegbound) n_poly_one(modulus); Gdegbound = Gdeg; /* update interpolant H */ nmod_mpoly_scalar_mul_nmod_invertible(Geval, Geval, gammaeval, ctx); if (n_poly_degree(modulus) > 0) { temp = n_poly_mod_eval_pow(modulus, alphapow, ctx->mod); temp = nmod_inv(temp, ctx->mod); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, ctx->mod); changed = nmod_mpolyn_interp_crt_sm_mpoly(&lastdeg, H, T, Geval, modulus, alphapow->coeffs[1], ctx); if (!changed) { _n_poly_vec_mod_remove_content(c, H->coeffs, H->length, ctx->mod); nmod_mpoly_cvtfrom_mpolyn(G, H, var, ctx); nmod_mpoly_make_monic(G, G, ctx); success = nmod_mpoly_divides(Abar, A, G, ctx) && nmod_mpoly_divides(Bbar, B, G, ctx); if (success) goto cleanup; /* restore H */ _n_poly_vec_mod_mul_poly(H->coeffs, H->length, c, ctx->mod); goto outer_loop; } } else { nmod_mpolyn_interp_lift_sm_mpoly(H, Geval, ctx); } temp = nmod_neg(alpha, ctx->mod); n_poly_mod_shift_left_scalar_addmul(modulus, 1, temp, ctx->mod); nmod_mpoly_fit_length(G, H->length, ctx); mpoly_copy_monomials(G->exps, H->exps, H->length, N); G->length = H->length; mpoly1_fill_marks(&Gmarks->coeffs, &Gmarks->length, &Gmarks->alloc, G->exps, G->length, bits, ctx->minfo); perm = FLINT_ARRAY_REALLOC(perm, Gmarks->length, slong); for (i = 0; i < Gmarks->length; i++) perm[i] = i; #define length(k) Gmarks->coeffs[(k)+1] - Gmarks->coeffs[k] for (i = 1; i < Gmarks->length; i++) for (j = i; j > 0 && length(perm[j-1]) > length(perm[j]); j--) FLINT_SWAP(slong, perm[j-1], perm[j]); req_zip_images = Gmarks->length - 2; j = 0; for (i = 0; i < Gmarks->length; i++) { req_zip_images += length(i); j = FLINT_MAX(j, length(i)); } if (Gmarks->length > 1) req_zip_images = req_zip_images / (Gmarks->length - 1); req_zip_images = FLINT_MAX(req_zip_images, j); req_zip_images += 1; inner_loop: /* get new evaluation point */ if (alpha < 2) alpha = ctx->mod.n; alpha -= 1; success = (alpha != start_alpha); if (!success) goto cleanup; FLINT_ASSERT(alphapow->alloc >= 2); alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; alphapow->length = 2; /* make sure evaluation does not kill both lc(A) and lc(B) */ gammaeval = n_poly_mod_eval_pow(gamma, alphapow, ctx->mod); if (gammaeval == 0) goto inner_loop; /* make sure evaluation does not kill either A or B */ nmod_mpoly_evaluate_one_ui(Aeval, A, var, alpha, ctx); nmod_mpoly_evaluate_one_ui(Beval, B, var, alpha, ctx); if (Aeval->length == 0 || Beval->length == 0) goto outer_loop; nmod_mpoly_repack_bits_inplace(Aeval, bits, ctx); nmod_mpoly_repack_bits_inplace(Beval, bits, ctx); success = nmod_mpolyl_gcds_zippel(Geval, Gmarks->coeffs, Gmarks->length, Aeval, Beval, perm, req_zip_images, var, ctx, state, &Gdegbound, Amarks, Bmarks); if (success == 0) { n_poly_one(modulus); goto outer_loop; } if (success < 0 || Geval->coeffs[0] == 0) goto inner_loop; /* update interpolant H */ temp = nmod_div(gammaeval, Geval->coeffs[0], ctx->mod); nmod_mpoly_scalar_mul_nmod_invertible(Geval, Geval, temp, ctx); FLINT_ASSERT(n_poly_degree(modulus) > 0); temp = n_poly_mod_eval_pow(modulus, alphapow, ctx->mod); temp = nmod_inv(temp, ctx->mod); _n_poly_mod_scalar_mul_nmod_inplace(modulus, temp, ctx->mod); changed = nmod_mpolyn_interp_mcrt_sm_mpoly(&lastdeg, H, Geval, modulus, alphapow, ctx); temp = nmod_neg(alpha, ctx->mod); n_poly_mod_shift_left_scalar_addmul(modulus, 1, temp, ctx->mod); have_enough = n_poly_degree(modulus) >= bound; if (changed && !have_enough) goto inner_loop; if (!changed || have_enough) { /* since H started from a correct modular image and was scaled wrt to the univariate gamma, if H is the correct gcd modulo content, the only content is univariate in the last variable */ _n_poly_vec_mod_remove_content(c, H->coeffs, H->length, ctx->mod); nmod_mpoly_cvtfrom_mpolyn(G, H, var, ctx); nmod_mpoly_make_monic(G, G, ctx); success = nmod_mpoly_divides(Abar, A, G, ctx) && nmod_mpoly_divides(Bbar, B, G, ctx); if (success) goto cleanup; /* restore H */ _n_poly_vec_mod_mul_poly(H->coeffs, H->length, c, ctx->mod); } if (have_enough) { n_poly_one(modulus); goto outer_loop; } goto inner_loop; cleanup: flint_free(perm); nmod_mpoly_clear(Ac, ctx); nmod_mpoly_clear(Bc, ctx); nmod_mpoly_clear(Aeval, ctx); nmod_mpoly_clear(Beval, ctx); nmod_mpoly_clear(Geval, ctx); nmod_mpoly_clear(Abareval, ctx); nmod_mpoly_clear(Bbareval, ctx); n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); n_poly_clear(gamma); n_poly_clear(modulus); n_poly_clear(alphapow); nmod_mpolyn_clear(H, ctx); nmod_mpolyn_clear(T, ctx); n_poly_clear(Amarks); n_poly_clear(Bmarks); n_poly_clear(Gmarks); if (success) { FLINT_ASSERT(G->bits == bits); } return success; } flint-3.1.3/src/nmod_mpoly_factor/get_set.c000066400000000000000000000034461461254215100207420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly_factor.h" slong nmod_mpoly_factor_get_exp_si(nmod_mpoly_factor_t f, slong i, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(i < (ulong) f->num); return fmpz_get_si(f->exp + i); } void nmod_mpoly_factor_set(nmod_mpoly_factor_t res, const nmod_mpoly_factor_t fac, const nmod_mpoly_ctx_t ctx) { slong i; if (res == fac) return; nmod_mpoly_factor_fit_length(res, fac->num, ctx); res->constant = fac->constant; for (i = 0; i < fac->num; i++) { nmod_mpoly_set(res->poly + i, fac->poly + i, ctx); fmpz_set(res->exp + i, fac->exp + i); } res->num = fac->num; } void _nmod_mpoly_get_lead0( nmod_mpoly_t c, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { nmod_mpolyl_lead_coeff(c, A, 1, ctx); } void _nmod_mpoly_set_lead0( nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx) { slong deg; nmod_mpoly_t t, g; nmod_mpoly_init(t, ctx); nmod_mpoly_init(g, ctx); deg = nmod_mpoly_degree_si(B, 0, ctx); FLINT_ASSERT(deg >= 0); nmod_mpoly_gen(g, 0, ctx); nmod_mpoly_pow_ui(g, g, deg, ctx); _nmod_mpoly_get_lead0(t, B, ctx); nmod_mpoly_sub(t, c, t, ctx); nmod_mpoly_mul(t, t, g, ctx); nmod_mpoly_add(A, B, t, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(g, ctx); } flint-3.1.3/src/nmod_mpoly_factor/init.c000066400000000000000000000021341461254215100202440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly_factor.h" void nmod_mpoly_factor_init2(nmod_mpoly_factor_t f, slong alloc, const nmod_mpoly_ctx_t ctx) { f->constant = 1; if (alloc > 0) { slong i; f->exp = (fmpz *) flint_malloc(alloc * sizeof(fmpz)); f->poly = (nmod_mpoly_struct *) flint_malloc(alloc * sizeof(nmod_mpoly_struct)); for (i = 0; i < alloc; i++) { nmod_mpoly_init(f->poly + i, ctx); fmpz_init(f->exp + i); } f->alloc = alloc; } else { f->poly = NULL; f->exp = NULL; f->alloc = 0; } f->num = 0; } flint-3.1.3/src/nmod_mpoly_factor/inlines.c000066400000000000000000000007001461254215100207370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_MPOLY_FACTOR_INLINES_C #include "nmod_mpoly_factor.h" flint-3.1.3/src/nmod_mpoly_factor/io.c000066400000000000000000000034451461254215100177160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" void nmod_mpoly_factor_print_pretty(const nmod_mpoly_factor_t f, const char ** vars, const nmod_mpoly_ctx_t ctx) { slong i; flint_printf("%wu", f->constant); for (i = 0; i < f->num; i++) { flint_printf("\n*(", i); nmod_mpoly_print_pretty(f->poly + i, vars, ctx); flint_printf(")^"); fmpz_print(f->exp + i); } } void nmod_mpolyu3_print_pretty( const nmod_mpolyu_t A, const char * var0, const char * var1, const char * var2, const char ** vars, const nmod_mpoly_ctx_t ctx) { slong i; int first = 1; for (i = 0; i < A->length; i++) { if (!first) printf(" + "); first = 0; flint_printf("("); nmod_mpoly_print_pretty(A->coeffs + i, vars, ctx); flint_printf(")*%s^%wu*%s^%wu*%s^%wu", var0, extract_exp(A->exps[i], 2, 3), var1, extract_exp(A->exps[i], 1, 3), var2, extract_exp(A->exps[i], 0, 3)); } if (first) flint_printf("0"); } void nmod_mpolyv_print_pretty( const nmod_mpolyv_t poly, const char ** x, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < poly->length; i++) { flint_printf("coeff[%wd]: ", i); nmod_mpoly_print_pretty(poly->coeffs + i, x, ctx); flint_printf("\n"); } } flint-3.1.3/src/nmod_mpoly_factor/irred_lgprime.c000066400000000000000000000223631461254215100221330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "fq_nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #include "fq_nmod_mpoly_factor.h" static void _fq_nmod_mpoly_set_nmod_mpoly( fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t Actx, const nmod_mpoly_t B, const nmod_mpoly_ctx_t Bctx) { slong d = fq_nmod_ctx_degree(Actx->fqctx); slong N = mpoly_words_per_exp(B->bits, Bctx->minfo); slong i; FLINT_ASSERT(Actx->minfo->ord == Bctx->minfo->ord); FLINT_ASSERT(Actx->minfo->nvars == Bctx->minfo->nvars); fq_nmod_mpoly_fit_length_reset_bits(A, B->length, B->bits, Actx); A->length = B->length; mpoly_copy_monomials(A->exps, B->exps, B->length, N); for (i = 0; i < B->length; i++) _n_fq_set_nmod(A->coeffs + d*i, B->coeffs[i], d); } static void _frob_combine( nmod_mpolyv_t Af, fq_nmod_mpolyv_t eAf, const nmod_mpoly_ctx_t ctx, const fq_nmod_mpoly_ctx_t ectx) { slong d = fq_nmod_ctx_degree(ectx->fqctx); slong i, j, N; fq_nmod_mpolyv_t tfac; fq_nmod_mpoly_t t; nmod_mpoly_struct * s; FLINT_ASSERT(d > 1); fq_nmod_mpoly_init(t, ectx); fq_nmod_mpolyv_init(tfac, ectx); Af->length = 0; while (eAf->length > 0) { eAf->length--; fq_nmod_mpoly_swap(t, eAf->coeffs + eAf->length, ectx); fq_nmod_mpolyv_fit_length(tfac, 1, ectx); fq_nmod_mpoly_set(tfac->coeffs + 0, t, ectx); tfac->length = 1; for (i = 1; i < d; i++) { for (j = 0; j < t->length; j++) { n_fq_pow_ui(t->coeffs + d*j, t->coeffs + d*j, ectx->fqctx->modulus->mod.n, ectx->fqctx); } for (j = 0; j < eAf->length; j++) { if (fq_nmod_mpoly_equal(t, eAf->coeffs + j, ectx)) break; } if (j >= eAf->length) continue; /* t should already be in tfac */ fq_nmod_mpolyv_fit_length(tfac, tfac->length + 1, ectx); fq_nmod_mpoly_swap(tfac->coeffs + tfac->length, eAf->coeffs + j, ectx); tfac->length++; eAf->length--; fq_nmod_mpoly_swap(eAf->coeffs + j, eAf->coeffs + eAf->length, ectx); } fq_nmod_mpoly_swap(t, tfac->coeffs + 0, ectx); for (i = 1; i < tfac->length; i++) fq_nmod_mpoly_mul(t, t, tfac->coeffs + i, ectx); nmod_mpolyv_fit_length(Af, Af->length + 1, ctx); s = Af->coeffs + Af->length; Af->length++; nmod_mpoly_fit_length_reset_bits(s, t->length, t->bits, ctx); s->length = t->length; N = mpoly_words_per_exp(t->bits, ectx->minfo); mpoly_copy_monomials(s->exps, t->exps, t->length, N); for (i = 0; i < t->length; i++) { for (j = 1; j < d; j++) { if ((t->coeffs + d*i)[j] != 0) { flint_throw(FLINT_ERROR, "fatal error in _frob_combine"); } } s->coeffs[i] = (t->coeffs + d*i)[0]; } } fq_nmod_mpolyv_clear(tfac, ectx); fq_nmod_mpoly_clear(t, ectx); } /* return: 1: success 0: failed, ran out of primes, don't try again -1: failed, don't try again */ int nmod_mpoly_factor_irred_lgprime_zassenhaus( nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; fq_nmod_mpolyv_t eAf; fq_nmod_mpoly_t eA; fq_nmod_mpoly_ctx_t ectx; slong edeg; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); edeg = 2; fq_nmod_mpoly_ctx_init_deg(ectx, ctx->minfo->nvars, ORD_LEX, ctx->mod.n, edeg); fq_nmod_mpoly_init(eA, ectx); fq_nmod_mpolyv_init(eAf, ectx); goto have_prime; choose_prime: edeg++; fq_nmod_mpoly_ctx_change_modulus(ectx, edeg); have_prime: _fq_nmod_mpoly_set_nmod_mpoly(eA, ectx, A, ctx); success = fq_nmod_mpoly_factor_irred_smprime_zassenhaus(eAf, eA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx); success = 1; cleanup: fq_nmod_mpoly_clear(eA, ectx); fq_nmod_mpolyv_clear(eAf, ectx); fq_nmod_mpoly_ctx_clear(ectx); return success; } /* the methods in the extended context want an irreducible factorization */ static int _map_fac( fq_nmod_mpoly_factor_t eAfac, const fq_nmod_mpoly_ctx_t ectx, const nmod_mpoly_factor_t Afac, const nmod_mpoly_ctx_t ctx) { int success; slong i, j; fq_nmod_mpoly_t t; fq_nmod_mpoly_factor_t tfac; fq_nmod_mpoly_init(t, ectx); fq_nmod_mpoly_factor_init(tfac, ectx); fq_nmod_set_ui(eAfac->constant, Afac->constant, ectx->fqctx); eAfac->num = 0; for (i = 0; i < Afac->num; i++) { _fq_nmod_mpoly_set_nmod_mpoly(t, ectx, Afac->poly + i, ctx); success = fq_nmod_mpoly_factor(tfac, t, ectx); if (!success) goto cleanup; FLINT_ASSERT(fq_nmod_is_one(tfac->constant, ectx->fqctx)); fq_nmod_mpoly_factor_fit_length(eAfac, eAfac->num + tfac->num, ectx); for (j = 0; j < tfac->num; j++) { fq_nmod_mpoly_swap(eAfac->poly + eAfac->num, tfac->poly + j, ectx); fmpz_mul(eAfac->exp + eAfac->num, tfac->exp + j, Afac->exp + i); eAfac->num++; } } success = 1; cleanup: fq_nmod_mpoly_clear(t, ectx); fq_nmod_mpoly_factor_clear(tfac, ectx); return success; } int nmod_mpoly_factor_irred_lgprime_wang( nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; fq_nmod_mpoly_factor_t elcAfac; fq_nmod_mpolyv_t eAf; fq_nmod_mpoly_t eA, elcA; fq_nmod_mpoly_ctx_t ectx; slong edeg; const slong n = ctx->minfo->nvars - 1; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); edeg = 1 + n_clog(A->length + 1, ctx->mod.n)/2; edeg = FLINT_MAX(2, edeg); fq_nmod_mpoly_ctx_init_deg(ectx, n + 1, ORD_LEX, ctx->mod.n, edeg); fq_nmod_mpoly_init(eA, ectx); fq_nmod_mpolyv_init(eAf, ectx); fq_nmod_mpoly_init(elcA, ectx); fq_nmod_mpoly_factor_init(elcAfac, ectx); fq_nmod_mpoly_factor_fit_length(elcAfac, lcAfac->num, ectx); elcAfac->num = lcAfac->num; goto have_prime; choose_prime: edeg++; fq_nmod_mpoly_ctx_change_modulus(ectx, edeg); have_prime: _fq_nmod_mpoly_set_nmod_mpoly(eA, ectx, A, ctx); _fq_nmod_mpoly_set_nmod_mpoly(elcA, ectx, lcA, ctx); _map_fac(elcAfac, ectx, lcAfac, ctx); success = fq_nmod_mpoly_factor_irred_smprime_wang(eAf, eA, elcAfac, elcA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx); success = 1; cleanup: fq_nmod_mpoly_clear(eA, ectx); fq_nmod_mpolyv_clear(eAf, ectx); fq_nmod_mpoly_clear(elcA, ectx); fq_nmod_mpoly_factor_clear(elcAfac, ectx); fq_nmod_mpoly_ctx_clear(ectx); return success; } int nmod_mpoly_factor_irred_lgprime_zippel( nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; fq_nmod_mpoly_factor_t elcAfac; fq_nmod_mpolyv_t eAf; fq_nmod_mpoly_t eA, elcA; fq_nmod_mpoly_ctx_t ectx; slong edeg; const slong n = ctx->minfo->nvars - 1; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); edeg = 1 + n_clog(A->length + 1, ctx->mod.n); edeg = FLINT_MAX(2, edeg); fq_nmod_mpoly_ctx_init_deg(ectx, n + 1, ORD_LEX, ctx->mod.n, edeg); fq_nmod_mpoly_init(eA, ectx); fq_nmod_mpolyv_init(eAf, ectx); fq_nmod_mpoly_init(elcA, ectx); fq_nmod_mpoly_factor_init(elcAfac, ectx); fq_nmod_mpoly_factor_fit_length(elcAfac, lcAfac->num, ectx); elcAfac->num = lcAfac->num; goto have_prime; choose_prime: edeg++; fq_nmod_mpoly_ctx_change_modulus(ectx, edeg); have_prime: _fq_nmod_mpoly_set_nmod_mpoly(eA, ectx, A, ctx); _fq_nmod_mpoly_set_nmod_mpoly(elcA, ectx, lcA, ctx); fq_nmod_set_ui(elcAfac->constant, lcAfac->constant, ectx->fqctx); _map_fac(elcAfac, ectx, lcAfac, ctx); success = fq_nmod_mpoly_factor_irred_smprime_zippel(eAf, eA, elcAfac, elcA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx); success = 1; cleanup: fq_nmod_mpoly_clear(eA, ectx); fq_nmod_mpolyv_clear(eAf, ectx); fq_nmod_mpoly_clear(elcA, ectx); fq_nmod_mpoly_factor_clear(elcAfac, ectx); fq_nmod_mpoly_ctx_clear(ectx); return success; } flint-3.1.3/src/nmod_mpoly_factor/irred_medprime.c000066400000000000000000000222721461254215100222750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" #include "fq_zech.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #include "fq_zech_mpoly_factor.h" static void _frob_combine( nmod_mpolyv_t Af, fq_zech_mpolyv_t eAf, const nmod_mpoly_ctx_t ctx, const fq_zech_mpoly_ctx_t ectx) { slong i, j, N; fq_zech_mpolyv_t tfac; fq_zech_mpoly_t t; nmod_mpoly_struct * s; slong k = fq_zech_ctx_degree(ectx->fqctx); FLINT_ASSERT(k > 1); fq_zech_mpoly_init(t, ectx); fq_zech_mpolyv_init(tfac, ectx); Af->length = 0; while (eAf->length > 0) { eAf->length--; fq_zech_mpoly_swap(t, eAf->coeffs + eAf->length, ectx); fq_zech_mpolyv_fit_length(tfac, 1, ectx); fq_zech_mpoly_set(tfac->coeffs + 0, t, ectx); tfac->length = 1; for (i = 1; i < k; i++) { for (j = 0; j < t->length; j++) { fq_zech_pow_ui(t->coeffs + j, t->coeffs + j, ctx->mod.n, ectx->fqctx); } for (j = 0; j < eAf->length; j++) { if (fq_zech_mpoly_equal(t, eAf->coeffs + j, ectx)) break; } if (j >= eAf->length) continue; /* t should already be in tfac */ fq_zech_mpolyv_fit_length(tfac, tfac->length + 1, ectx); fq_zech_mpoly_swap(tfac->coeffs + tfac->length, eAf->coeffs + j, ectx); tfac->length++; eAf->length--; fq_zech_mpoly_swap(eAf->coeffs + j, eAf->coeffs + eAf->length, ectx); } fq_zech_mpoly_swap(t, tfac->coeffs + 0, ectx); for (i = 1; i < tfac->length; i++) fq_zech_mpoly_mul(t, t, tfac->coeffs + i, ectx); nmod_mpolyv_fit_length(Af, Af->length + 1, ctx); s = Af->coeffs + Af->length; Af->length++; nmod_mpoly_fit_length_reset_bits(s, t->length, t->bits, ctx); s->length = t->length; N = mpoly_words_per_exp(t->bits, ectx->minfo); mpoly_copy_monomials(s->exps, t->exps, t->length, N); for (i = 0; i < t->length; i++) { nmod_poly_t asdf; nmod_poly_init_mod(asdf, ctx->mod); fq_zech_get_nmod_poly(asdf, t->coeffs + i, ectx->fqctx); if (asdf->length != 1) { flint_throw(FLINT_ERROR, "fatal error in _frob_combine"); } s->coeffs[i] = asdf->coeffs[0]; nmod_poly_clear(asdf); } } fq_zech_mpolyv_clear(tfac, ectx); fq_zech_mpoly_clear(t, ectx); } /* return: 1: success 0: failed, ran out of primes, don't try again -1: failed, don't try again */ int nmod_mpoly_factor_irred_medprime_zassenhaus( nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; fq_zech_mpolyv_t eAf; fq_zech_mpoly_t eA; fq_zech_mpoly_ctx_t ectx; slong edeg, max_degree = n_flog(1000000, ctx->mod.n); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); edeg = 1 + n_clog(A->length + 1, ctx->mod.n)/2; edeg = FLINT_MAX(2, edeg); if (edeg > max_degree) return 0; fq_zech_mpoly_ctx_init_deg(ectx, ctx->minfo->nvars, ORD_LEX, ctx->mod.n, edeg); fq_zech_mpoly_init(eA, ectx); fq_zech_mpolyv_init(eAf, ectx); goto have_prime; choose_prime: edeg++; if (edeg > max_degree) { success = 0; goto cleanup; } fq_zech_mpoly_ctx_change_modulus(ectx, edeg); have_prime: _fq_zech_mpoly_set_nmod_mpoly(eA, ectx, A, ctx); success = fq_zech_mpoly_factor_irred_smprime_zassenhaus(eAf, eA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx); success = 1; cleanup: fq_zech_mpoly_clear(eA, ectx); fq_zech_mpolyv_clear(eAf, ectx); fq_zech_mpoly_ctx_clear(ectx); return success; } /* the methods in the extended context want an irreducible factorization */ static int _map_fac( fq_zech_mpoly_factor_t eAfac, const fq_zech_mpoly_ctx_t ectx, const nmod_mpoly_factor_t Afac, const nmod_mpoly_ctx_t ctx) { int success; slong i, j; fq_zech_mpoly_t t; fq_zech_mpoly_factor_t tfac; fq_zech_mpoly_init(t, ectx); fq_zech_mpoly_factor_init(tfac, ectx); fq_zech_set_ui(eAfac->constant, Afac->constant, ectx->fqctx); eAfac->num = 0; for (i = 0; i < Afac->num; i++) { _fq_zech_mpoly_set_nmod_mpoly(t, ectx, Afac->poly + i, ctx); success = fq_zech_mpoly_factor(tfac, t, ectx); if (!success) goto cleanup; FLINT_ASSERT(fq_zech_is_one(tfac->constant, ectx->fqctx)); fq_zech_mpoly_factor_fit_length(eAfac, eAfac->num + tfac->num, ectx); for (j = 0; j < tfac->num; j++) { fq_zech_mpoly_swap(eAfac->poly + eAfac->num, tfac->poly + j, ectx); fmpz_mul(eAfac->exp + eAfac->num, tfac->exp + j, Afac->exp + i); eAfac->num++; } } success = 1; cleanup: fq_zech_mpoly_clear(t, ectx); fq_zech_mpoly_factor_clear(tfac, ectx); return success; } int nmod_mpoly_factor_irred_medprime_wang( nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; const slong n = ctx->minfo->nvars - 1; fq_zech_mpoly_factor_t elcAfac; fq_zech_mpolyv_t eAf; fq_zech_mpoly_t eA, elcA; fq_zech_mpoly_ctx_t ectx; slong edeg, max_degree = n_flog(1000000, ctx->mod.n); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); edeg = 1 + n_clog(A->length + 1, ctx->mod.n)/2; edeg = FLINT_MAX(2, edeg); if (edeg > max_degree) return 0; fq_zech_mpoly_ctx_init_deg(ectx, n + 1, ORD_LEX, ctx->mod.n, edeg); fq_zech_mpoly_init(eA, ectx); fq_zech_mpolyv_init(eAf, ectx); fq_zech_mpoly_init(elcA, ectx); fq_zech_mpoly_factor_init(elcAfac, ectx); fq_zech_mpoly_factor_fit_length(elcAfac, lcAfac->num, ectx); elcAfac->num = lcAfac->num; goto have_prime; choose_prime: edeg++; if (edeg > max_degree) { success = 0; goto cleanup; } fq_zech_mpoly_ctx_change_modulus(ectx, edeg); have_prime: _fq_zech_mpoly_set_nmod_mpoly(eA, ectx, A, ctx); _fq_zech_mpoly_set_nmod_mpoly(elcA, ectx, lcA, ctx); _map_fac(elcAfac, ectx, lcAfac, ctx); success = fq_zech_mpoly_factor_irred_smprime_wang(eAf, eA, elcAfac, elcA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx); success = 1; cleanup: fq_zech_mpoly_clear(eA, ectx); fq_zech_mpolyv_clear(eAf, ectx); fq_zech_mpoly_clear(elcA, ectx); fq_zech_mpoly_factor_clear(elcAfac, ectx); fq_zech_mpoly_ctx_clear(ectx); return success; } int nmod_mpoly_factor_irred_medprime_zippel( nmod_mpolyv_t Af, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; const slong n = ctx->minfo->nvars - 1; fq_zech_mpoly_factor_t elcAfac; fq_zech_mpolyv_t eAf; fq_zech_mpoly_t eA, elcA; fq_zech_mpoly_ctx_t ectx; slong edeg, max_degree = n_flog(1000000, ctx->mod.n); FLINT_ASSERT(A->length > 0); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); edeg = 1 + n_clog(A->length + 1, ctx->mod.n); edeg = FLINT_MAX(2, edeg); if (edeg > max_degree) return 0; fq_zech_mpoly_ctx_init_deg(ectx, n + 1, ORD_LEX, ctx->mod.n, edeg); fq_zech_mpoly_init(eA, ectx); fq_zech_mpolyv_init(eAf, ectx); fq_zech_mpoly_init(elcA, ectx); fq_zech_mpoly_factor_init(elcAfac, ectx); fq_zech_mpoly_factor_fit_length(elcAfac, lcAfac->num, ectx); elcAfac->num = lcAfac->num; goto have_prime; choose_prime: edeg++; if (edeg > max_degree) { success = 0; goto cleanup; } fq_zech_mpoly_ctx_change_modulus(ectx, edeg); have_prime: _fq_zech_mpoly_set_nmod_mpoly(eA, ectx, A, ctx); _fq_zech_mpoly_set_nmod_mpoly(elcA, ectx, lcA, ctx); _map_fac(elcAfac, ectx, lcAfac, ctx); success = fq_zech_mpoly_factor_irred_smprime_zippel(eAf, eA, elcAfac, elcA, ectx, state); if (success == 0) goto choose_prime; if (success < 0) goto cleanup; _frob_combine(Af, eAf, ctx, ectx); success = 1; cleanup: fq_zech_mpoly_clear(eA, ectx); fq_zech_mpolyv_clear(eAf, ectx); fq_zech_mpoly_clear(elcA, ectx); fq_zech_mpoly_factor_clear(elcAfac, ectx); fq_zech_mpoly_ctx_clear(ectx); return success; } flint-3.1.3/src/nmod_mpoly_factor/irred_smprime_wang.c000066400000000000000000000213031461254215100231550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" /* return 1: success 0: failed -1: exception (large exps) */ int nmod_mpoly_factor_irred_smprime_wang( nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; mp_limb_t * alpha; n_poly_struct * alphabetas; nmod_mpoly_struct * Aevals; slong * degs, * degeval; nmod_mpolyv_t tfac; nmod_mpoly_t t, Acopy; nmod_mpoly_struct * newA; n_poly_t Abfc; n_bpoly_t Ab; n_tpoly_t Abfp; nmod_mpoly_t m, mpow; nmod_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(A->bits <= FLINT_BITS); nmod_mpoly_init(Acopy, ctx); nmod_mpoly_init(m, ctx); nmod_mpoly_init(mpow, ctx); nmod_mpolyv_init(new_lcs, ctx); nmod_mpolyv_init(lc_divs, ctx); n_poly_init(Abfc); n_tpoly_init(Abfp); n_bpoly_init(Ab); degs = (slong *) flint_malloc((n + 1)*sizeof(slong)); degeval = (slong *) flint_malloc((n + 1)*sizeof(slong)); alpha = (mp_limb_t *) flint_malloc(n*sizeof(mp_limb_t)); alphabetas = (n_poly_struct *) flint_malloc(n*sizeof(n_poly_struct)); Aevals = (nmod_mpoly_struct *) flint_malloc(n*sizeof(nmod_mpoly_struct)); for (i = 0; i < n; i++) { n_poly_init(alphabetas + i); nmod_mpoly_init(Aevals + i, ctx); } nmod_mpolyv_init(tfac, ctx); nmod_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; nmod_mpoly_degrees_si(degs, A, ctx); next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) alpha[i] = n_urandint(state, ctx->mod.n - 1) + 1; /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { nmod_mpoly_evaluate_one_ui(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha[i], ctx); nmod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } /* make sure univar is squarefree */ nmod_mpoly_derivative(t, Aevals + 0, 0, ctx); if (!nmod_mpoly_gcd(t, t, Aevals + 0, ctx)) { success = -1; goto cleanup; } if (!nmod_mpoly_is_one(t, ctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 10) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { n_poly_fit_length(alphabetas + i, alphabetas_length); alphabetas[i].coeffs[0] = alpha[i]; for (j = 1; j < alphabetas_length; j++) alphabetas[i].coeffs[j] = n_urandint(state, ctx->mod.n); alphabetas[i].length = alphabetas_length; _n_poly_normalise(alphabetas + i); } _nmod_mpoly_eval_rest_to_n_bpoly(Ab, A, alphabetas, ctx); success = n_bpoly_mod_factor_smprime(Abfc, Abfp, Ab, 0, ctx->mod); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } nmod_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = nmod_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) nmod_mpoly_one(lc_divs->coeffs + i, ctx); } success = nmod_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = nmod_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } nmod_mpoly_pow_ui(mpow, m, r - 1, ctx); if (nmod_mpoly_is_one(mpow, ctx)) { newA = (nmod_mpoly_struct *) A; } else { newA = Acopy; nmod_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } nmod_mpoly_degrees_si(degs, newA, ctx); nmod_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { nmod_mpoly_evaluate_one_ui(t, mpow, i + 1, alpha[i], ctx); nmod_mpoly_swap(t, mpow, ctx); nmod_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); nmod_mpoly_repack_bits_inplace(Aevals + i, newA->bits, ctx); } nmod_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { nmod_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { nmod_mpoly_evaluate_one_ui(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha[i], ctx); } } nmod_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { mp_limb_t q; FLINT_ASSERT(nmod_mpoly_is_ui(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(nmod_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _nmod_mpoly_set_n_bpoly_var1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); q = nmod_inv(fac->coeffs[i].coeffs[0], ctx->mod); q = nmod_mul(q, new_lcs->coeffs[0*r + i].coeffs[0], ctx->mod); nmod_mpoly_scalar_mul_nmod_invertible(fac->coeffs + i, fac->coeffs + i, q, ctx); } nmod_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _nmod_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } success = nmod_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); if (!success) goto next_alphabetas; nmod_mpolyv_swap(tfac, fac, ctx); } if (!nmod_mpoly_is_ui(m, ctx)) { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!nmod_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = nmod_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } } for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); nmod_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); } success = 1; cleanup: nmod_mpolyv_clear(new_lcs, ctx); nmod_mpolyv_clear(lc_divs, ctx); n_poly_clear(Abfc); n_tpoly_clear(Abfp); n_bpoly_clear(Ab); for (i = 0; i < n; i++) { nmod_mpoly_clear(Aevals + i, ctx); n_poly_clear(alphabetas + i); } flint_free(alphabetas); flint_free(alpha); flint_free(Aevals); flint_free(degs); flint_free(degeval); nmod_mpolyv_clear(tfac, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(Acopy, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { nmod_mpoly_t prod; nmod_mpoly_init(prod, ctx); nmod_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) nmod_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(prod, A, ctx)); nmod_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/nmod_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000256271461254215100244220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_poly_factor.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" /* return: 1: success 0: lift is impossible -1: failed, don't try again */ static int _try_lift( nmod_mpolyv_t qfac, const nmod_mpoly_t q, const nmod_mpolyv_t pfac, const nmod_mpoly_t p, slong m, mp_limb_t * alpha, slong n, const nmod_mpoly_ctx_t ctx) { int success; slong i; slong * newdeg; nmod_mpoly_t lcq, lcp, t, newq; FLINT_ASSERT(pfac->length > 1); newdeg = (slong *) flint_malloc((n + 1)*sizeof(slong)); nmod_mpoly_init(lcq, ctx); nmod_mpoly_init(lcp, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(newq, ctx); #if FLINT_WANT_ASSERT nmod_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) nmod_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(t, p, ctx)); #endif _nmod_mpoly_get_lead0(lcq, q, ctx); nmod_mpoly_evaluate_one_ui(lcp, lcq, m, alpha[m - 1], ctx); FLINT_ASSERT(lcp->length > 0); nmod_mpoly_pow_ui(t, lcq, pfac->length - 1, ctx); nmod_mpoly_mul(newq, q, t, ctx); if (newq->bits > FLINT_BITS) { success = -1; goto cleanup; } nmod_mpoly_degrees_si(newdeg, newq, ctx); nmod_mpolyv_fit_length(qfac, pfac->length, ctx); qfac->length = pfac->length; for (i = 0; i < pfac->length; i++) { _nmod_mpoly_get_lead0(t, pfac->coeffs + i, ctx); success = nmod_mpoly_divides(t, lcp, t, ctx); FLINT_ASSERT(success); nmod_mpoly_mul(qfac->coeffs + i, pfac->coeffs + i, t, ctx); _nmod_mpoly_set_lead0(qfac->coeffs + i, qfac->coeffs + i, lcq, ctx); } success = nmod_mpoly_hlift(m, qfac->coeffs, qfac->length, alpha, newq, newdeg, ctx); if (!success) goto cleanup; for (i = 0; i < qfac->length; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(qfac->coeffs[i].bits <= FLINT_BITS); if (!nmod_mpolyl_content(t, qfac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = nmod_mpoly_divides(qfac->coeffs + i, qfac->coeffs + i, t, ctx); FLINT_ASSERT(success); nmod_mpoly_make_monic(qfac->coeffs + i, qfac->coeffs + i, ctx); } success = 1; cleanup: flint_free(newdeg); nmod_mpoly_clear(lcq, ctx); nmod_mpoly_clear(lcp, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(newq, ctx); #if FLINT_WANT_ASSERT if (success > 0) { nmod_mpoly_init(t, ctx); nmod_mpoly_one(t, ctx); for (i = 0; i < qfac->length; i++) nmod_mpoly_mul(t, t, qfac->coeffs + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(t, q, ctx)); nmod_mpoly_clear(t, ctx); } #endif return success; } int nmod_mpoly_factor_irred_smprime_zassenhaus( nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; int tries_remaining = 10; const slong n = ctx->minfo->nvars - 1; slong i, j, k, m, len; slong * subset; mp_limb_t * alpha; nmod_mpoly_struct * Aevals; slong * deg, * degeval; nmod_mpolyv_t qfac, pfac, tfac, dfac; nmod_mpoly_t t, p, q; n_poly_t c; n_bpoly_t B; n_tpoly_t F; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(A->bits <= FLINT_BITS); subset = (slong*) flint_malloc(4*sizeof(slong)); alpha = (mp_limb_t *) flint_malloc(n*sizeof(mp_limb_t)); Aevals = (nmod_mpoly_struct *) flint_malloc(n*sizeof(nmod_mpoly_struct)); deg = (slong *) flint_malloc((n + 1)*sizeof(slong)); degeval = (slong *) flint_malloc((n + 1)*sizeof(slong)); for (i = 0; i < n; i++) nmod_mpoly_init(Aevals + i, ctx); nmod_mpolyv_init(pfac, ctx); nmod_mpolyv_init(qfac, ctx); nmod_mpolyv_init(tfac, ctx); nmod_mpolyv_init(dfac, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(p, ctx); nmod_mpoly_init(q, ctx); n_poly_init(c); n_bpoly_init(B); n_tpoly_init(F); nmod_mpoly_degrees_si(deg, A, ctx); next_alpha: if (--tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) alpha[i] = n_urandint(state, ctx->mod.n - 1) + 1; /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { nmod_mpoly_evaluate_one_ui(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha[i], ctx); nmod_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); nmod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != deg[j]) goto next_alpha; } /* make sure univar is squarefree */ nmod_mpoly_derivative(t, Aevals + 0, 0, ctx); success = nmod_mpoly_gcd(t, t, Aevals + 0, ctx); if (!success) goto cleanup; if (!nmod_mpoly_is_one(t, ctx)) goto next_alpha; /* make evaluations primitive */ for (i = n - 1; i > 0; i--) { success = nmod_mpolyl_content(t, Aevals + i, 1, ctx); if (!success) goto cleanup; success = nmod_mpoly_divides(Aevals + i, Aevals + i, t, ctx); FLINT_ASSERT(success); nmod_mpoly_make_monic(Aevals + i, Aevals + i, ctx); nmod_mpoly_repack_bits_inplace(Aevals + i, A->bits, ctx); } nmod_mpoly_get_bpoly(B, Aevals + 1, 0, 1, ctx); success = n_bpoly_mod_factor_smprime(c, F, B, 1, ctx->mod); if (!success) goto next_alpha; FLINT_ASSERT(n_poly_degree(c) == 0); nmod_mpolyv_fit_length(pfac, F->length, ctx); pfac->length = F->length; for (i = 0; i < F->length; i++) { nmod_mpoly_set_bpoly(pfac->coeffs + i, A->bits, F->coeffs + i, 0, 1, ctx); nmod_mpoly_make_monic(pfac->coeffs + i, pfac->coeffs + i, ctx); } /* number of of local factors can only decrease from here on */ subset = flint_realloc(subset, pfac->length*sizeof(slong)); for (m = 2; m <= n; m++) { nmod_mpoly_set(q, m < n ? Aevals + m : A, ctx); nmod_mpoly_set(p, Aevals + m - 1, ctx); #if FLINT_WANT_ASSERT nmod_mpoly_one(t, ctx); for (i = 0; i < pfac->length; i++) nmod_mpoly_mul(t, t, pfac->coeffs + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(t, p, ctx)); #endif /* if one local factor, A must be irreducible */ if (pfac->length < 2) { nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } success = _try_lift(qfac, q, pfac, p, m, alpha, n, ctx); if (success > 0) { nmod_mpolyv_swap(qfac, pfac, ctx); continue; } else if (success < 0) { success = 0; goto cleanup; } /* if we couldn't lift two local, A must be irreducible */ if (pfac->length == 2) { nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } qfac->length = 0; len = pfac->length; for (k = 0; k < len; k++) subset[k] = k; for (k = 1; k <= len/2; k++) { zassenhaus_subset_first(subset, len, k); #if FLINT_WANT_ASSERT nmod_mpoly_one(t, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; nmod_mpoly_mul(t, t, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } FLINT_ASSERT(nmod_mpoly_equal(t, p, ctx)); #endif while (1) { nmod_mpolyv_fit_length(dfac, 2, ctx); dfac->length = 2; nmod_mpoly_one(dfac->coeffs + 0, ctx); nmod_mpoly_one(dfac->coeffs + 1, ctx); for (i = 0; i < len; i++) { int in = subset[i] >= 0; nmod_mpoly_mul(dfac->coeffs + in, dfac->coeffs + in, pfac->coeffs + (in ? subset[i] : -1 - subset[i]), ctx); } success = _try_lift(tfac, q, dfac, p, m, alpha, n, ctx); if (success > 0) { nmod_mpolyv_fit_length(qfac, qfac->length + 1, ctx); nmod_mpoly_swap(qfac->coeffs + qfac->length, tfac->coeffs + 1, ctx); qfac->length++; nmod_mpoly_swap(q, tfac->coeffs + 0, ctx); nmod_mpoly_swap(p, dfac->coeffs + 0, ctx); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else if (success < 0) { success = 0; goto cleanup; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } /* remnants are irreducible */ if (!nmod_mpoly_is_ui(q, ctx)) { nmod_mpolyv_fit_length(qfac, qfac->length + 1, ctx); nmod_mpoly_swap(qfac->coeffs + qfac->length, q, ctx); qfac->length++; } else { FLINT_ASSERT(nmod_mpoly_is_one(q, ctx)); } nmod_mpolyv_swap(qfac, pfac, ctx); } success = 1; nmod_mpolyv_swap(fac, pfac, ctx); cleanup: flint_free(subset); flint_free(alpha); for (i = 0; i < n; i++) nmod_mpoly_clear(Aevals + i, ctx); flint_free(Aevals); flint_free(deg); flint_free(degeval); nmod_mpolyv_clear(pfac, ctx); nmod_mpolyv_clear(qfac, ctx); nmod_mpolyv_clear(tfac, ctx); nmod_mpolyv_clear(dfac, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(p, ctx); nmod_mpoly_clear(q, ctx); n_poly_clear(c); n_bpoly_clear(B); n_tpoly_clear(F); #if FLINT_WANT_ASSERT if (success) { nmod_mpoly_init(t, ctx); nmod_mpoly_one(t, ctx); for (i = 0; i < fac->length; i++) nmod_mpoly_mul(t, t, fac->coeffs + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(t, A, ctx)); nmod_mpoly_clear(t, ctx); } #endif return success; } flint-3.1.3/src/nmod_mpoly_factor/irred_smprime_zippel.c000066400000000000000000000221611461254215100235270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" /* return 1: success 0: failed -1: exception (large exps) */ int nmod_mpoly_factor_irred_smprime_zippel( nmod_mpolyv_t fac, const nmod_mpoly_t A, const nmod_mpoly_factor_t lcAfac, const nmod_mpoly_t lcA, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { int success; int alphas_tries_remaining, alphabetas_tries_remaining, alphabetas_length; const slong n = ctx->minfo->nvars - 1; slong i, j, k, r; mp_limb_t * alpha; n_poly_struct * alphabetas; nmod_mpoly_struct * Aevals; slong * degs, * degeval; nmod_mpolyv_t tfac; nmod_mpoly_t t, Acopy; nmod_mpoly_struct * newA; n_poly_t Abfc; n_bpoly_t Ab; n_tpoly_t Abfp; nmod_mpoly_t m, mpow; nmod_mpolyv_t new_lcs, lc_divs; FLINT_ASSERT(n > 1); FLINT_ASSERT(A->length > 1); FLINT_ASSERT(A->coeffs[0] == 1); FLINT_ASSERT(A->bits <= FLINT_BITS); if (ctx->mod.n < 7) return 0; nmod_mpoly_init(Acopy, ctx); nmod_mpoly_init(m, ctx); nmod_mpoly_init(mpow, ctx); nmod_mpolyv_init(new_lcs, ctx); nmod_mpolyv_init(lc_divs, ctx); n_poly_init(Abfc); n_tpoly_init(Abfp); n_bpoly_init(Ab); degs = (slong *) flint_malloc((n + 1)*sizeof(slong)); degeval = (slong *) flint_malloc((n + 1)*sizeof(slong)); alpha = (mp_limb_t *) flint_malloc(n*sizeof(mp_limb_t)); alphabetas = (n_poly_struct *) flint_malloc(n*sizeof(n_poly_struct)); Aevals = (nmod_mpoly_struct *) flint_malloc(n*sizeof(nmod_mpoly_struct)); for (i = 0; i < n; i++) { n_poly_init(alphabetas + i); nmod_mpoly_init(Aevals + i, ctx); } nmod_mpolyv_init(tfac, ctx); nmod_mpoly_init(t, ctx); /* init done */ alphabetas_length = 2; alphas_tries_remaining = 10; nmod_mpoly_degrees_si(degs, A, ctx); k = 0; for (i = 0; i <= n; i++) { k += degs[i]; if (ctx->mod.n < (ulong) k) { success = 0; goto cleanup; } } next_alpha: if (--alphas_tries_remaining < 0) { success = 0; goto cleanup; } for (i = 0; i < n; i++) alpha[i] = n_urandint(state, ctx->mod.n - 1) + 1; /* ensure degrees do not drop under evaluation */ for (i = n - 1; i >= 0; i--) { nmod_mpoly_evaluate_one_ui(Aevals + i, i == n - 1 ? A : Aevals + i + 1, i + 1, alpha[i], ctx); nmod_mpoly_degrees_si(degeval, Aevals + i, ctx); for (j = 0; j <= i; j++) if (degeval[j] != degs[j]) goto next_alpha; } /* make sure univar is squarefree */ nmod_mpoly_derivative(t, Aevals + 0, 0, ctx); if (!nmod_mpoly_gcd(t, t, Aevals + 0, ctx)) { success = -1; goto cleanup; } if (!nmod_mpoly_is_one(t, ctx)) goto next_alpha; alphabetas_tries_remaining = 2 + alphabetas_length; next_alphabetas: if (--alphabetas_tries_remaining < 0) { if (++alphabetas_length > 10) { success = 0; goto cleanup; } goto next_alpha; } for (i = 0; i < n; i++) { n_poly_fit_length(alphabetas + i, alphabetas_length); alphabetas[i].coeffs[0] = alpha[i]; for (j = 1; j < alphabetas_length; j++) alphabetas[i].coeffs[j] = n_urandint(state, ctx->mod.n); alphabetas[i].length = alphabetas_length; _n_poly_normalise(alphabetas + i); } _nmod_mpoly_eval_rest_to_n_bpoly(Ab, A, alphabetas, ctx); success = n_bpoly_mod_factor_smprime(Abfc, Abfp, Ab, 0, ctx->mod); if (!success) { FLINT_ASSERT(0 && "this should not happen"); goto next_alpha; } r = Abfp->length; if (r < 2) { nmod_mpolyv_fit_length(fac, 1, ctx); fac->length = 1; nmod_mpoly_set(fac->coeffs + 0, A, ctx); success = 1; goto cleanup; } nmod_mpolyv_fit_length(lc_divs, r, ctx); lc_divs->length = r; if (lcAfac->num > 0) { success = nmod_mpoly_factor_lcc_wang(lc_divs->coeffs, lcAfac, Abfc, Abfp->coeffs, r, alphabetas, ctx); if (!success) goto next_alphabetas; } else { for (i = 0; i < r; i++) nmod_mpoly_one(lc_divs->coeffs + i, ctx); } success = nmod_mpoly_divides(m, lcA, lc_divs->coeffs + 0, ctx); FLINT_ASSERT(success); for (i = 1; i < r; i++) { success = nmod_mpoly_divides(m, m, lc_divs->coeffs + i, ctx); FLINT_ASSERT(success); } nmod_mpoly_pow_ui(mpow, m, r - 1, ctx); if (nmod_mpoly_is_one(mpow, ctx)) { newA = (nmod_mpoly_struct *) A; } else { newA = Acopy; nmod_mpoly_mul(newA, A, mpow, ctx); } if (newA->bits > FLINT_BITS) { success = 0; goto cleanup; } nmod_mpoly_degrees_si(degs, newA, ctx); for (i = 0; i < n + 1; i++) { if (FLINT_BIT_COUNT(degs[i]) >= FLINT_BITS/3) { success = -1; goto cleanup; } } nmod_mpoly_set(t, mpow, ctx); for (i = n - 1; i >= 0; i--) { nmod_mpoly_evaluate_one_ui(t, mpow, i + 1, alpha[i], ctx); nmod_mpoly_swap(t, mpow, ctx); nmod_mpoly_mul(Aevals + i, Aevals + i, mpow, ctx); } nmod_mpolyv_fit_length(new_lcs, (n + 1)*r, ctx); i = n; for (j = 0; j < r; j++) { nmod_mpoly_mul(new_lcs->coeffs + i*r + j, lc_divs->coeffs + j, m, ctx); } for (i = n - 1; i >= 0; i--) { for (j = 0; j < r; j++) { nmod_mpoly_evaluate_one_ui(new_lcs->coeffs + i*r + j, new_lcs->coeffs + (i + 1)*r + j, i + 1, alpha[i], ctx); } } nmod_mpolyv_fit_length(fac, r, ctx); fac->length = r; for (i = 0; i < r; i++) { mp_limb_t q; FLINT_ASSERT(nmod_mpoly_is_ui(new_lcs->coeffs + 0*r + i, ctx)); FLINT_ASSERT(nmod_mpoly_length(new_lcs->coeffs + 0*r + i, ctx) == 1); _nmod_mpoly_set_n_bpoly_var1_zero(fac->coeffs + i, newA->bits, Abfp->coeffs + i, 0, ctx); FLINT_ASSERT(fac->coeffs[i].length > 0); q = nmod_inv(fac->coeffs[i].coeffs[0], ctx->mod); q = nmod_mul(q, new_lcs->coeffs[0*r + i].coeffs[0], ctx->mod); nmod_mpoly_scalar_mul_nmod_invertible(fac->coeffs + i, fac->coeffs + i, q, ctx); } nmod_mpolyv_fit_length(tfac, r, ctx); tfac->length = r; for (k = 1; k <= n; k++) { for (i = 0; i < r; i++) { _nmod_mpoly_set_lead0(tfac->coeffs + i, fac->coeffs + i, new_lcs->coeffs + k*r + i, ctx); } if (k > 2) { success = nmod_mpoly_hlift_zippel(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx, state); } else { success = nmod_mpoly_hlift(k, tfac->coeffs, r, alpha, k < n ? Aevals + k : newA, degs, ctx); } if (!success) goto next_alphabetas; nmod_mpolyv_swap(tfac, fac, ctx); } if (!nmod_mpoly_is_ui(m, ctx)) { for (i = 0; i < r; i++) { /* hlift should not have returned any large bits */ FLINT_ASSERT(fac->coeffs[i].bits <= FLINT_BITS); if (!nmod_mpolyl_content(t, fac->coeffs + i, 1, ctx)) { success = -1; goto cleanup; } success = nmod_mpoly_divides(fac->coeffs + i, fac->coeffs + i, t, ctx); FLINT_ASSERT(success); } } for (i = 0; i < r; i++) nmod_mpoly_make_monic(fac->coeffs + i, fac->coeffs + i, ctx); success = 1; cleanup: nmod_mpolyv_clear(new_lcs, ctx); nmod_mpolyv_clear(lc_divs, ctx); n_poly_clear(Abfc); n_tpoly_clear(Abfp); n_bpoly_clear(Ab); for (i = 0; i < n; i++) { nmod_mpoly_clear(Aevals + i, ctx); n_poly_clear(alphabetas + i); } flint_free(alphabetas); flint_free(alpha); flint_free(Aevals); flint_free(degs); flint_free(degeval); nmod_mpolyv_clear(tfac, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(Acopy, ctx); nmod_mpoly_clear(m, ctx); nmod_mpoly_clear(mpow, ctx); #if FLINT_WANT_ASSERT if (success) { nmod_mpoly_t prod; nmod_mpoly_init(prod, ctx); nmod_mpoly_one(prod, ctx); for (i = 0; i < fac->length; i++) nmod_mpoly_mul(prod, prod, fac->coeffs + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(prod, A, ctx)); nmod_mpoly_clear(prod, ctx); } #endif return success; } flint-3.1.3/src/nmod_mpoly_factor/lcc_wang.c000066400000000000000000000077441461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" int nmod_mpoly_factor_lcc_wang( nmod_mpoly_struct * lc_divs, const nmod_mpoly_factor_t lcAfac, const n_poly_t Auc, const n_bpoly_struct * Auf, slong r, const n_poly_struct * alpha, const nmod_mpoly_ctx_t ctx) { int success; slong i, j, k; const slong n = ctx->minfo->nvars - 1; n_poly_struct * lcAfaceval; n_poly_struct * d; n_poly_t Q, R; nmod_mpoly_t t; slong N, * offsets, * shifts, * starts, * ends, * stops; ulong mask, * es; n_poly_struct * T; n_poly_init(Q); n_poly_init(R); nmod_mpoly_init(t, ctx); lcAfaceval = FLINT_ARRAY_ALLOC(lcAfac->num, n_poly_struct); for (i = 0; i < lcAfac->num; i++) n_poly_init(lcAfaceval + i); d = FLINT_ARRAY_ALLOC(lcAfac->num + 1, n_poly_struct); for (i = 0; i < lcAfac->num + 1; i++) n_poly_init(d + i); starts = FLINT_ARRAY_ALLOC(n + 1, slong); ends = FLINT_ARRAY_ALLOC(n + 1, slong); stops = FLINT_ARRAY_ALLOC(n + 1, slong); es = FLINT_ARRAY_ALLOC(n + 1, ulong); T = FLINT_ARRAY_ALLOC(n + 2, n_poly_struct); for (i = 0; i < n + 2; i++) n_poly_init(T + i); offsets = FLINT_ARRAY_ALLOC(n + 1, slong); shifts = FLINT_ARRAY_ALLOC(n + 1, slong); for (j = 0; j < lcAfac->num; j++) { nmod_mpoly_struct * P = lcAfac->poly + j; for (i = 0; i < n + 1; i++) mpoly_gen_offset_shift_sp(offsets + i, shifts + i, i, P->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - P->bits); N = mpoly_words_per_exp_sp(P->bits, ctx->minfo); _nmod_mpoly_evaluate_rest_n_poly(T, starts, ends, stops, es, P->coeffs, P->exps, P->length, 1, alpha, offsets, shifts, N, mask, n + 1, ctx->mod); n_poly_set(lcAfaceval + j, T + 0); } n_poly_set(d + 0, Auc); for (i = 0; i < lcAfac->num; i++) { n_poly_mod_make_monic(Q, lcAfaceval + i, ctx->mod); if (n_poly_degree(Q) < 1) { success = 0; goto cleanup; } for (j = i; j >= 0; j--) { n_poly_set(R, d + j); while (n_poly_degree(R) > 0) { n_poly_mod_gcd(R, R, Q, ctx->mod); n_poly_mod_divexact(Q, Q, R, ctx->mod); if (n_poly_degree(Q) < 1) { success = 0; goto cleanup; } } } n_poly_set(d + i + 1, Q); } for (j = 0; j < r; j++) { nmod_mpoly_one(lc_divs + j, ctx); n_poly_mod_mul(R, Auf[j].coeffs + Auf[j].length - 1, Auc, ctx->mod); for (i = lcAfac->num - 1; i >= 0; i--) { n_poly_mod_make_monic(Q, lcAfaceval + i, ctx->mod); if (n_poly_degree(Q) < 1) continue; k = n_poly_mod_remove(R, Q, ctx->mod); nmod_mpoly_pow_ui(t, lcAfac->poly + i, k, ctx); nmod_mpoly_mul(lc_divs + j, lc_divs + j, t, ctx); } } success = 1; cleanup: n_poly_clear(Q); n_poly_clear(R); nmod_mpoly_clear(t, ctx); for (i = 0; i < lcAfac->num; i++) n_poly_clear(lcAfaceval + i); flint_free(lcAfaceval); for (i = 0; i < lcAfac->num + 1; i++) n_poly_clear(d + i); flint_free(d); for (i = 0; i < n + 2; i++) n_poly_clear(T + i); flint_free(T); flint_free(starts); flint_free(ends); flint_free(stops); flint_free(es); flint_free(offsets); flint_free(shifts); return success; } flint-3.1.3/src/nmod_mpoly_factor/mpoly_hlift.c000066400000000000000000000272141461254215100216350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" static int _hlift_quartic2( slong m, nmod_mpoly_struct * f, slong r, const mp_limb_t * alpha, const nmod_mpoly_t A, const slong * degs, const nmod_mpoly_ctx_t ctx) { int success; slong i, j; nmod_mpoly_t Aq, t, t2, t3, xalpha; nmod_mpoly_geobucket_t G; nmod_mpoly_struct betas[2], * deltas; nmod_mpoly_pfrac_t I; nmod_mpolyv_struct B[2]; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r == 2); r = 2; nmod_mpoly_init(t, ctx); nmod_mpoly_init(t2, ctx); nmod_mpoly_init(t3, ctx); nmod_mpoly_init(xalpha, ctx); nmod_mpoly_init(Aq, ctx); nmod_mpoly_geobucket_init(G, ctx); nmod_mpoly_gen(xalpha, m, ctx); nmod_mpoly_sub_ui(xalpha, xalpha, alpha[m - 1], ctx); nmod_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (i = 0; i < r; i++) { nmod_mpolyv_init(B + i, ctx); nmod_mpoly_repack_bits_inplace(f + i, bits, ctx); nmod_mpoly_to_mpolyv(B + i, f + i, xalpha, ctx); nmod_mpolyv_fit_length(B + i, degs[m] + 1, ctx); for (j = B[i].length; j <= degs[m]; j++) nmod_mpoly_zero(B[i].coeffs + j, ctx); } for (i = 0; i < r; i++) betas[i] = B[i].coeffs[0]; success = nmod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; nmod_mpoly_divrem(Aq, t, A, xalpha, ctx); #if FLINT_WANT_ASSERT nmod_mpoly_one(t2, ctx); for (i = 0; i < r; i++) nmod_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { nmod_mpoly_divrem(t2, t, Aq, xalpha, ctx); nmod_mpoly_swap(Aq, t2, ctx); nmod_mpoly_geobucket_set(G, t, ctx); for (i = 0; i <= j; i++) { nmod_mpoly_mul(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx); nmod_mpoly_geobucket_sub(G, t, ctx); } nmod_mpoly_geobucket_empty(t, G, ctx); if (nmod_mpoly_is_zero(t, ctx)) continue; success = nmod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { nmod_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); nmod_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!nmod_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } } success = 1; cleanup: nmod_mpoly_pfrac_clear(I, ctx); for (i = 0; i < r; i++) { if (success) nmod_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); nmod_mpolyv_clear(B + i, ctx); } nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_clear(t3, ctx); nmod_mpoly_clear(xalpha, ctx); nmod_mpoly_clear(Aq, ctx); nmod_mpoly_geobucket_clear(G, ctx); return success; } static int _hlift_quartic( slong m, nmod_mpoly_struct * f, slong r, const mp_limb_t * alpha, const nmod_mpoly_t A, const slong * degs, const nmod_mpoly_ctx_t ctx) { int success; slong i, j, k; nmod_mpoly_t Aq, t, t1, t2, t3, xalpha; nmod_mpoly_geobucket_t G; nmod_mpoly_struct * betas, * deltas; nmod_mpoly_pfrac_t I; nmod_mpolyv_struct * B, * U; slong tdeg; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 2); B = FLINT_ARRAY_ALLOC(2*r, nmod_mpolyv_struct); U = B + r; nmod_mpoly_init(t, ctx); nmod_mpoly_init(t1, ctx); nmod_mpoly_init(t2, ctx); nmod_mpoly_init(t3, ctx); nmod_mpoly_init(xalpha, ctx); nmod_mpoly_init(Aq, ctx); nmod_mpoly_geobucket_init(G, ctx); nmod_mpoly_gen(xalpha, m, ctx); nmod_mpoly_sub_ui(xalpha, xalpha, alpha[m - 1], ctx); nmod_mpoly_repack_bits_inplace(xalpha, bits, ctx); for (k = 0; k < r; k++) { nmod_mpolyv_init(U + k, ctx); nmod_mpolyv_fit_length(U + k, degs[m] + 1, ctx); for (j = 0; j <= degs[m]; j++) nmod_mpoly_zero(U[k].coeffs + j, ctx); nmod_mpolyv_init(B + k, ctx); nmod_mpoly_repack_bits_inplace(f + k, bits, ctx); nmod_mpoly_to_mpolyv(B + k, f + k, xalpha, ctx); nmod_mpolyv_fit_length(B + k, degs[m] + 1, ctx); for (j = B[k].length; j <= degs[m]; j++) nmod_mpoly_zero(B[k].coeffs + j, ctx); } betas = FLINT_ARRAY_ALLOC(r, nmod_mpoly_struct); for (i = 0; i < r; i++) betas[i] = B[i].coeffs[0]; success = nmod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); FLINT_ASSERT(success == 1); deltas = I->deltas + (m - 1)*I->r; k = r - 2; nmod_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k >= 1; k--) nmod_mpoly_mul(U[k].coeffs + 0, B[k].coeffs + 0, U[k + 1].coeffs + 0, ctx); nmod_mpoly_divrem(t2, t, A, xalpha, ctx); nmod_mpoly_swap(Aq, t2, ctx); #if FLINT_WANT_ASSERT nmod_mpoly_one(t2, ctx); for (i = 0; i < r; i++) nmod_mpoly_mul(t2, t2, betas + i, ctx); FLINT_ASSERT(nmod_mpoly_equal(t, t2, ctx)); #endif for (j = 1; j <= degs[m]; j++) { k = r - 2; G->length = 0; for (i = 0; i <= j; i++) { nmod_mpoly_mul(t1, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); nmod_mpoly_geobucket_add(G, t1, ctx); } nmod_mpoly_geobucket_empty(U[k].coeffs + j, G, ctx); for (k--; k >= 1; k--) { G->length = 0; for (i = 0; i <= j; i++) { nmod_mpoly_mul(t1, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); nmod_mpoly_geobucket_add(G, t1, ctx); } nmod_mpoly_geobucket_empty(U[k].coeffs + j, G, ctx); } nmod_mpoly_divrem(t2, t, Aq, xalpha, ctx); nmod_mpoly_swap(Aq, t2, ctx); nmod_mpoly_geobucket_set(G, t, ctx); for (i = 0; i <= j; i++) { nmod_mpoly_mul(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx); nmod_mpoly_geobucket_sub(G, t, ctx); } nmod_mpoly_geobucket_empty(t, G, ctx); if (nmod_mpoly_is_zero(t, ctx)) continue; success = nmod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } tdeg = 0; for (i = 0; i < r; i++) { nmod_mpoly_add(t3, B[i].coeffs + j, deltas + i, ctx); nmod_mpoly_swap(B[i].coeffs + j, t3, ctx); if (!nmod_mpoly_is_zero(B[i].coeffs + j, ctx)) B[i].length = FLINT_MAX(B[i].length, j + 1); FLINT_ASSERT(B[i].length > 0); tdeg += B[i].length - 1; } if (tdeg > degs[m]) { success = 0; goto cleanup; } k = r - 2; nmod_mpoly_mul(t, B[k].coeffs + 0, deltas + k + 1, ctx); nmod_mpoly_mul(t1, deltas + k, B[k + 1].coeffs + 0, ctx); nmod_mpoly_add(t, t, t1, ctx); nmod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); for (k--; k >= 1; k--) { nmod_mpoly_mul(t1, B[k].coeffs + 0, t, ctx); nmod_mpoly_swap(t, t1, ctx); nmod_mpoly_mul(t1, deltas + k, U[k + 1].coeffs + 0, ctx); nmod_mpoly_add(t, t, t1, ctx); nmod_mpoly_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } success = 1; cleanup: nmod_mpoly_pfrac_clear(I, ctx); flint_free(betas); for (i = 0; i < r; i++) { if (success) nmod_mpoly_from_mpolyv(f + i, bits, B + i, xalpha, ctx); nmod_mpolyv_clear(B + i, ctx); nmod_mpolyv_clear(U + i, ctx); } flint_free(B); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(t1, ctx); nmod_mpoly_clear(t2, ctx); nmod_mpoly_clear(t3, ctx); nmod_mpoly_clear(xalpha, ctx); nmod_mpoly_clear(Aq, ctx); nmod_mpoly_geobucket_clear(G, ctx); return success; } static int _hlift_quintic( slong m, nmod_mpoly_struct * f, slong r, const mp_limb_t * alpha, const nmod_mpoly_t A, const slong * degs, const nmod_mpoly_ctx_t ctx) { int success; slong i, j; nmod_mpoly_t e, t, pow, xalpha, q; nmod_mpoly_struct * betas, * deltas; nmod_mpoly_pfrac_t I; flint_bitcnt_t bits = A->bits; FLINT_ASSERT(r > 1); nmod_mpoly_init(e, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_init(pow, ctx); nmod_mpoly_init(xalpha, ctx); nmod_mpoly_init(q, ctx); betas = FLINT_ARRAY_ALLOC(r, nmod_mpoly_struct); for (i = 0; i < r; i++) { nmod_mpoly_init(betas + i, ctx); nmod_mpoly_repack_bits_inplace(f + i, bits, ctx); nmod_mpoly_evaluate_one_ui(betas + i, f + i, m, alpha[m - 1], ctx); } nmod_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) nmod_mpoly_mul(t, t, f + i, ctx); nmod_mpoly_sub(e, A, t, ctx); nmod_mpoly_one(pow, ctx); nmod_mpoly_repack_bits_inplace(pow, bits, ctx); nmod_mpoly_gen(xalpha, m, ctx); nmod_mpoly_sub_ui(xalpha, xalpha, alpha[m - 1], ctx); nmod_mpoly_repack_bits_inplace(xalpha, bits, ctx); nmod_mpoly_pfrac_init(I, bits, r, m - 1, betas, alpha, ctx); deltas = I->deltas + (m - 1)*I->r; for (j = 1; j <= degs[m]; j++) { if (nmod_mpoly_is_zero(e, ctx)) { success = 1; goto cleanup; } nmod_mpoly_mul(pow, pow, xalpha, ctx); success = nmod_mpoly_divides(q, e, pow, ctx); FLINT_ASSERT(success); nmod_mpoly_evaluate_one_ui(t, q, m, alpha[m - 1], ctx); success = nmod_mpoly_pfrac(m - 1, t, degs, I, ctx); if (success < 1) { success = 0; goto cleanup; } for (i = 0; i < r; i++) { nmod_mpoly_mul(t, deltas + i, pow, ctx); nmod_mpoly_add(f + i, f + i, t, ctx); } nmod_mpoly_mul(t, f + 0, f + 1, ctx); for (i = 2; i < r; i++) nmod_mpoly_mul(t, t, f + i, ctx); nmod_mpoly_sub(e, A, t, ctx); } success = nmod_mpoly_is_zero(e, ctx); cleanup: nmod_mpoly_pfrac_clear(I, ctx); nmod_mpoly_clear(e, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(pow, ctx); nmod_mpoly_clear(xalpha, ctx); nmod_mpoly_clear(q, ctx); for (i = 0; i < r; i++) { if (success) nmod_mpoly_repack_bits_inplace(f + i, bits, ctx); nmod_mpoly_clear(betas + i, ctx); } flint_free(betas); return success; } /* should have A = prod_i f[i] mod (gen(m) - alpha[m-1]) */ int nmod_mpoly_hlift( slong m, nmod_mpoly_struct * f, /* length r */ slong r, const mp_limb_t * alpha, const nmod_mpoly_t A, const slong * degs, const nmod_mpoly_ctx_t ctx) { FLINT_ASSERT(r >= 2); FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(ctx->minfo->ord == ORD_LEX); if (r == 2) return _hlift_quartic2(m, f, r, alpha, A, degs, ctx); else if (r < 20) return _hlift_quartic(m, f, r, alpha, A, degs, ctx); else return _hlift_quintic(m, f, r, alpha, A, degs, ctx); } flint-3.1.3/src/nmod_mpoly_factor/mpoly_hlift_zippel.c000066400000000000000000000524021461254215100232150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" static void _delete_duplicates( nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx) { slong i, j; slong N = mpoly_words_per_exp(A->bits, ctx->minfo); j = -1; for (i = 0; i < A->length; i++) { if (j >= 0 && mpoly_monomial_equal(A->exps + N*j, A->exps + N*i, N)) { FLINT_ASSERT(A->coeffs[j] == A->coeffs[i]); continue; } j++; A->coeffs[j] = A->coeffs[i]; mpoly_monomial_set(A->exps + N*j, A->exps + N*i, N); } j++; A->length = j; } static int nmod_mpoly_from_zip( nmod_mpoly_t B, const n_polyun_t Z, nmod_mpolyu_t H, ulong deg, slong yvar, /* Y = gen(yvar) */ const nmod_mpoly_ctx_t ctx, n_polyun_t M) /* temp */ { int success; slong Hi, Zi, Bi, i, j; slong xvar = 0; slong zvar = 1; ulong x, y, z; flint_bitcnt_t bits = B->bits; mp_limb_t * Bcoeffs; ulong * Bexps; slong N = mpoly_words_per_exp_sp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); slong xoff, xshift, yoff, yshift, zoff, zshift; nmod_mpoly_struct * Hc; slong Hlen = H->length; FLINT_ASSERT(bits == H->bits); n_polyun_fit_length(M, Hlen + 1); for (i = 0; i <= Hlen; i++) M->coeffs[i].length = 0; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); /* x is most significant in ctx, so keeping the lc_x in B is easy */ FLINT_ASSERT(xvar == 0); for (Bi = 0; Bi < B->length; Bi++) { x = (((B->exps + N*Bi)[xoff] >> xshift) & mask); FLINT_ASSERT(x <= deg); if (x != deg) break; } for (Zi = 0; Zi < Z->length; Zi++) { y = extract_exp(Z->exps[Zi], 2, 3); x = extract_exp(Z->exps[Zi], 1, 3); z = extract_exp(Z->exps[Zi], 0, 3); FLINT_ASSERT(x < deg); Hi = mpoly_monomial_index1_nomask(H->exps, H->length, pack_exp3(0, x, z)); if (Hi < 0) return 0; FLINT_ASSERT(Hi < Hlen); FLINT_ASSERT(H->exps[Hi] == pack_exp3(0, x, z)); Hc = H->coeffs + Hi; FLINT_ASSERT(bits == Hc->bits); FLINT_ASSERT(Hc->length > 0); nmod_mpoly_fit_length(B, Bi + Hc->length, ctx); Bcoeffs = B->coeffs; /* fill in root product if it is missing */ if (M->coeffs[Hi].length < 1) n_poly_mod_product_roots_nmod_vec(M->coeffs + Hi, Hc->coeffs, Hc->length, ctx->mod); n_poly_fit_length(M->coeffs + Hlen, Hc->length); success = _nmod_zip_vand_solve(Bcoeffs + Bi, Hc->coeffs, Hc->length, Z->coeffs[Zi].coeffs, Z->coeffs[Zi].length, M->coeffs[Hi].coeffs, M->coeffs[Hlen].coeffs, ctx->mod); if (success < 1) return success; Bexps = B->exps; for (j = Bi, i = 0; i < Hc->length; j++, i++) { if (Bcoeffs[j] == 0) continue; FLINT_ASSERT(Bi < B->coeffs_alloc); FLINT_ASSERT(N*Bi < B->exps_alloc); Bcoeffs[Bi] = Bcoeffs[j]; mpoly_monomial_set(Bexps + N*Bi, Hc->exps + N*i, N); (Bexps + N*Bi)[yoff] += y << yshift; Bi++; } } B->length = Bi; nmod_mpoly_sort_terms(B, ctx); FLINT_ASSERT(nmod_mpoly_is_canonical(B, ctx)); return 1; } static void _clearit( n_polyun_t W, mpoly_rbtree_ui_t T, slong idx) { mpoly_rbnode_ui_struct * nodes = T->nodes + 2; FLINT_ASSERT(0 <= idx && idx < T->length); if (nodes[idx].right >= 0) _clearit(W, T, nodes[idx].right); FLINT_ASSERT(W->length < W->alloc); W->exps[W->length] = nodes[idx].key; W->coeffs[W->length] = ((n_poly_struct *) T->data)[idx]; W->length++; if (nodes[idx].left >= 0) _clearit(W, T, nodes[idx].left); } static void nmod_mpoly_set_eval_helper3( n_polyun_t EH, const nmod_mpoly_t A, slong yvar, n_poly_struct * caches, const nmod_mpoly_ctx_t ctx) { slong xvar = 0; slong zvar = 1; slong i, j, k, n; ulong y, x, z; slong yoff, xoff, zoff, * off; slong yshift, xshift, zshift, * shift; mp_limb_t * p; flint_bitcnt_t bits = A->bits; slong Alen = A->length; const ulong * Aexps = A->exps; const mp_limb_t * Acoeffs = A->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; mpoly_rbtree_ui_t W; TMP_INIT; TMP_START; n_polyun_init(T); mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Alen; i++) { n_poly_struct * Wc; int its_new; y = (Aexps[N*i + yoff] >> yshift) & mask; x = (Aexps[N*i + xoff] >> xshift) & mask; z = (Aexps[N*i + zoff] >> zshift) & mask; Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); n_polyun_fit_length(EH, T->length); EH->length = T->length; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; n = T->coeffs[i].length; n_poly_fit_length(EH->coeffs + i, 3*n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Ai = ind[j]; mp_limb_t meval = 1; for (k = 2; k < yvar; k++) { ulong ei = (Aexps[N*Ai + off[k]] >> shift[k]) & mask; meval = nmod_pow_cache_mulpow_ui(meval, ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->mod); } /* set cur = monomial eval */ p[j] = meval; /* copy cur to inc */ p[j + n] = meval; /* copy coeff */ p[j + 2*n] = Acoeffs[Ai]; } } n_polyun_clear(T); TMP_END; } /* for each term Y^y*X^x*Z^z * pol(x1,...) in B with j < deg set Y^0*X^x*Z^z in H as the monomials with the monomial evals as coeffs merge monomial sets coming from different y's (shouldn't happen) */ static slong nmod_mpoly_set_eval_helper_and_zip_form3( ulong * deg_, /* deg_X(B), output */ n_polyun_t EH, nmod_mpolyu_t H, const nmod_mpoly_t B, n_poly_struct * caches, slong yvar, /* Y = gen(yvar) (X = gen(0), Z = gen(1))*/ const nmod_mpoly_ctx_t ctx) { slong xvar = 0; slong zvar = 1; slong i, j, k, n; slong * off, * shift; ulong y, x, z; mp_limb_t * p; nmod_mpoly_struct * Hc; slong old_len, zip_length = 0; flint_bitcnt_t bits = B->bits; slong Blen = B->length; const ulong * Bexps = B->exps; const mp_limb_t * Bcoeffs = B->coeffs; slong N = mpoly_words_per_exp(bits, ctx->minfo); ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits); ulong * ind; n_polyun_t T; ulong deg; TMP_INIT; FLINT_ASSERT(bits <= FLINT_BITS); FLINT_ASSERT(bits == B->bits); FLINT_ASSERT(bits == H->bits); FLINT_ASSERT(Blen > 0); TMP_START; off = (slong *) TMP_ALLOC(2*yvar*sizeof(slong)); shift = off + yvar; for (i = 2; i < yvar; i++) mpoly_gen_offset_shift_sp(&off[i], &shift[i], i, bits, ctx->minfo); /* init T */ { mpoly_rbtree_ui_t W; n_poly_struct * Wc; slong yoff, xoff, zoff; slong yshift, xshift, zshift; int its_new; mpoly_gen_offset_shift_sp(&yoff, &yshift, yvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&xoff, &xshift, xvar, bits, ctx->minfo); mpoly_gen_offset_shift_sp(&zoff, &zshift, zvar, bits, ctx->minfo); deg = (Bexps[N*0 + xoff] >> xshift) & mask; mpoly_rbtree_ui_init(W, sizeof(n_poly_struct)); for (i = 0; i < Blen; i++) { y = (Bexps[N*i + yoff] >> yshift) & mask; x = (Bexps[N*i + xoff] >> xshift) & mask; z = (Bexps[N*i + zoff] >> zshift) & mask; FLINT_ASSERT(x <= deg); Wc = mpoly_rbtree_ui_lookup(W, &its_new, pack_exp3(y, x, z)); if (its_new) { n_poly_init2(Wc, 4); Wc->coeffs[0] = i; Wc->length = 1; } else { n_poly_fit_length(Wc, Wc->length + 1); Wc->coeffs[Wc->length] = i; Wc->length++; } } FLINT_ASSERT(W->length > 0); T->exps = FLINT_ARRAY_ALLOC(W->length, ulong); T->coeffs = FLINT_ARRAY_ALLOC(W->length, n_poly_struct); T->alloc = W->length; T->length = 0; _clearit(T, W, W->nodes[2 - 1].left); mpoly_rbtree_ui_clear(W); } n_polyun_fit_length(EH, T->length); EH->length = T->length; H->length = 0; for (i = 0; i < T->length; i++) { EH->exps[i] = T->exps[i]; y = extract_exp(EH->exps[i], 2, 3); x = extract_exp(EH->exps[i], 1, 3); z = extract_exp(EH->exps[i], 0, 3); n = T->coeffs[i].length; n_poly_fit_length(EH->coeffs + i, 3*n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; ind = T->coeffs[i].coeffs; for (j = 0; j < n; j++) { slong Bi = ind[j]; mp_limb_t meval = 1; for (k = 2; k < yvar; k++) { ulong ei = (Bexps[N*Bi + off[k]] >> shift[k]) & mask; meval = nmod_pow_cache_mulpow_ui(meval, ei, caches + 3*k + 0, caches + 3*k + 1, caches + 3*k + 2, ctx->mod); } /* set cur = monomial eval */ p[j] = meval; /* copy cur to inc */ p[j + n] = meval; /* copy coeff */ p[j + 2*n] = Bcoeffs[Bi]; } if (x < deg) { FLINT_ASSERT(y == 0 && "strange but ok"); Hc = _nmod_mpolyu_get_coeff(H, pack_exp3(0, x, z), ctx); nmod_mpoly_fit_length(Hc, n, ctx); old_len = Hc->length; flint_mpn_copyi(Hc->coeffs + old_len, p, n); for (j = 0; j < n; j++) mpoly_monomial_set(Hc->exps + N*(old_len + j), Bexps + N*ind[j], N); Hc->length += n; zip_length = FLINT_MAX(zip_length, Hc->length); if (old_len > 0) { FLINT_ASSERT(0 && "strange but ok"); nmod_mpoly_sort_terms(Hc, ctx); _delete_duplicates(Hc, ctx); } } } n_polyun_clear(T); TMP_END; *deg_ = deg; return zip_length; } static void n_polyu_mod_eval_step(n_polyu_t E, n_polyun_t A, nmod_t ctx) { slong Ai, Ei, n; mp_limb_t * p; n_polyu_fit_length(E, A->length); Ei = 0; for (Ai = 0; Ai < A->length; Ai++) { FLINT_ASSERT(Ei < E->alloc); E->exps[Ei] = A->exps[Ai]; n = A->coeffs[Ai].length; p = A->coeffs[Ai].coeffs; FLINT_ASSERT(A->coeffs[Ai].alloc >= 3*n); E->coeffs[Ei] = _nmod_zip_eval_step(p + 0*n, p + 1*n, p + 2*n, n, ctx); Ei += (E->coeffs[Ei] != 0); } E->length = Ei; } static void n_polyu3_add_zip_limit1( n_polyun_t Z, const n_polyun_t A, const ulong deg1, slong cur_length, slong fit_length) { const n_poly_struct * Acoeffs = A->coeffs; ulong * Aexps = A->exps; n_poly_struct * Zcoeffs = Z->coeffs; ulong * Zexps = Z->exps; slong Ai, ai, Zi, j; Ai = -1; ai = -1; do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = n_poly_degree(Acoeffs + Ai); Zi = 0; while (Ai < A->length && Zi < Z->length) { if (Aexps[Ai] + ai > Zexps[Zi]) { /* missing from Z */ n_polyun_fit_length(Z, Z->length + 1); Zcoeffs = Z->coeffs; Zexps = Z->exps; for (j = Z->length; j > Zi; j--) { n_poly_swap(Zcoeffs + j, Zcoeffs + j - 1); FLINT_SWAP(ulong, Zexps[j], Zexps[j - 1]); } Z->length++; Zexps[Zi] = Aexps[Ai] + ai; n_poly_fit_length(Zcoeffs + Zi, fit_length); Zcoeffs[Zi].length = cur_length; flint_mpn_zero(Zcoeffs[Zi].coeffs, cur_length); goto in_both; } else if (Aexps[Ai] + ai < Zexps[Zi]) { /* missing from A */ FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); Zcoeffs[Zi].coeffs[cur_length] = 0; Zcoeffs[Zi].length = cur_length + 1; Zi++; } else { in_both: FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); Zcoeffs[Zi].coeffs[cur_length] = Acoeffs[Ai].coeffs[ai]; Zcoeffs[Zi].length = cur_length + 1; Zi++; do { ai--; } while (ai >= 0 && Acoeffs[Ai].coeffs[ai] == 0); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = n_poly_degree(Acoeffs + Ai); } } } /* everything in A must be put on the end of Z */ while (Ai < A->length) { Zi = Z->length; n_polyun_fit_length(Z, Zi + A->length - Ai); Zcoeffs = Z->coeffs; Zexps = Z->exps; Zexps[Zi] = Aexps[Ai] + ai; n_poly_fit_length(Zcoeffs + Zi, fit_length); Zcoeffs[Zi].length = cur_length; flint_mpn_zero(Zcoeffs[Zi].coeffs, cur_length); FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); Zcoeffs[Zi].coeffs[cur_length] = Acoeffs[Ai].coeffs[ai]; Zcoeffs[Zi].length = cur_length + 1; Z->length = ++Zi; do { ai--; } while (ai >= 0 && Acoeffs[Ai].coeffs[ai] == 0); if (ai < 0) { do { Ai++; } while (Ai < A->length && extract_exp(Aexps[Ai], 1, 3) >= deg1); if (Ai < A->length) ai = n_poly_degree(Acoeffs + Ai); } } /* everything in Z must have a zero appended */ while (Zi < Z->length) { FLINT_ASSERT(cur_length == Zcoeffs[Zi].length); FLINT_ASSERT(cur_length + 1 <= Zcoeffs[Zi].alloc); Zcoeffs[Zi].coeffs[cur_length] = 0; Zcoeffs[Zi].length = cur_length + 1; Zi++; } for (Zi = 0; Zi < Z->length; Zi++) { FLINT_ASSERT(Z->coeffs[Zi].length == cur_length + 1); } } int nmod_mpoly_hlift_zippel( slong m, nmod_mpoly_struct * B, slong r, const mp_limb_t * alpha, const nmod_mpoly_t A, const slong * degs, const nmod_mpoly_ctx_t ctx, flint_rand_t state) { flint_bitcnt_t bits = A->bits; int success; slong i, zip_fails_remaining, req_zip_images, cur_zip_image; nmod_mpolyu_struct * H; n_polyun_struct M[1], Aeh[1], * Beh, * BBeval, * Z; n_polyu_struct Aeval[1], * Beval; mp_limb_t * beta; n_poly_struct * caches; nmod_mpoly_t T1, T2; ulong * Bdegs; const slong degs0 = degs[0]; FLINT_ASSERT(m > 2); FLINT_ASSERT(r > 1); FLINT_ASSERT(bits <= FLINT_BITS); #if FLINT_WANT_ASSERT { nmod_mpoly_t T; slong j, * check_degs = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); nmod_mpoly_init(T, ctx); nmod_mpoly_degrees_si(check_degs, A, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); nmod_mpoly_one(T, ctx); for (i = 0; i < r; i++) { nmod_mpoly_degrees_si(check_degs, B + i, ctx); for (j = 0; j < ctx->minfo->nvars; j++) FLINT_ASSERT(FLINT_BIT_COUNT(check_degs[j]) < FLINT_BITS/3); nmod_mpoly_mul(T, T, B + i, ctx); } nmod_mpoly_sub(T, A, T, ctx); nmod_mpoly_evaluate_one_ui(T, T, m, alpha[m - 1], ctx); FLINT_ASSERT(nmod_mpoly_is_zero(T, ctx)); nmod_mpoly_clear(T, ctx); flint_free(check_degs); } #endif beta = FLINT_ARRAY_ALLOC(ctx->minfo->nvars,mp_limb_t); /* caches for powers of the betas */ caches = FLINT_ARRAY_ALLOC(3*ctx->minfo->nvars, n_poly_struct); for (i = 0; i < 3*ctx->minfo->nvars; i++) n_poly_init(caches + i); Bdegs = FLINT_ARRAY_ALLOC(r, ulong); H = FLINT_ARRAY_ALLOC(r, nmod_mpolyu_struct); Beh = FLINT_ARRAY_ALLOC(r, n_polyun_struct); Beval = FLINT_ARRAY_ALLOC(r, n_polyu_struct); BBeval = FLINT_ARRAY_ALLOC(r, n_polyun_struct); Z = FLINT_ARRAY_ALLOC(r, n_polyun_struct); n_polyun_init(Aeh); n_polyu_init(Aeval); n_polyun_init(M); for (i = 0; i < r; i++) { nmod_mpolyu_init(H + i, bits, ctx); n_polyun_init(Beh + i); n_polyu_init(Beval + i); n_polyun_init(BBeval + i); n_polyun_init(Z + i); } /* init done */ for (i = 0; i < r; i++) { success = nmod_mpoly_repack_bits_inplace(B + i, bits, ctx); if (!success) goto cleanup; } zip_fails_remaining = 3; choose_betas: /* only beta[2], beta[3], ..., beta[m - 1] will be used */ FLINT_ASSERT(ctx->mod.n > 3); for (i = 0; i < ctx->minfo->nvars; i++) { beta[i] = n_urandint(state, ctx->mod.n - 3) + 2; nmod_pow_cache_start(beta[i], caches + 3*i + 0, caches + 3*i + 1, caches + 3*i + 2); } nmod_mpoly_set_eval_helper3(Aeh, A, m, caches, ctx); req_zip_images = 1; for (i = 0; i < r; i++) { slong this_images; this_images = nmod_mpoly_set_eval_helper_and_zip_form3(Bdegs + i, Beh + i, H + i, B + i, caches, m, ctx); req_zip_images = FLINT_MAX(req_zip_images, this_images); FLINT_ASSERT(Bdegs[i] > 0); Z[i].length = 0; } cur_zip_image = 0; next_zip_image: n_polyu_mod_eval_step(Aeval, Aeh, ctx->mod); for (i = 0; i < r; i++) n_polyu_mod_eval_step(Beval + i, Beh + i, ctx->mod); success = n_polyu3_mod_hlift(r, BBeval, Aeval, Beval, alpha[m - 1], degs0, ctx->mod); if (success < 1) { if (--zip_fails_remaining >= 0) goto choose_betas; success = 0; goto cleanup; } for (i = 0; i < r; i++) { n_polyu3_add_zip_limit1(Z + i, BBeval + i, Bdegs[i], cur_zip_image, req_zip_images); } cur_zip_image++; if (cur_zip_image < req_zip_images) goto next_zip_image; for (i = 0; i < r; i++) { success = nmod_mpoly_from_zip(B + i, Z + i, H + i, Bdegs[i], m, ctx, M); if (success < 1) { success = 0; goto cleanup; } } nmod_mpoly_init3(T1, A->length, bits, ctx); nmod_mpoly_init3(T2, A->length, bits, ctx); nmod_mpoly_mul(T1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { nmod_mpoly_mul(T2, T1, B + i, ctx); nmod_mpoly_swap(T1, T2, ctx); } success = nmod_mpoly_equal(T1, A, ctx); nmod_mpoly_clear(T1, ctx); nmod_mpoly_clear(T2, ctx); cleanup: n_polyun_clear(Aeh); n_polyu_clear(Aeval); n_polyun_clear(M); for (i = 0; i < r; i++) { nmod_mpolyu_clear(H + i, ctx); n_polyun_clear(Beh + i); n_polyu_clear(Beval + i); n_polyun_clear(BBeval + i); n_polyun_clear(Z + i); } flint_free(beta); for (i = 0; i < 3*ctx->minfo->nvars; i++) n_poly_clear(caches + i); flint_free(caches); flint_free(Bdegs); flint_free(H); flint_free(Beh); flint_free(Beval); flint_free(BBeval); flint_free(Z); return success; } flint-3.1.3/src/nmod_mpoly_factor/mpoly_pfrac.c000066400000000000000000000220701461254215100216150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "nmod_mpoly_factor.h" int nmod_mpoly_pfrac_init( nmod_mpoly_pfrac_t I, flint_bitcnt_t bits, slong r, slong w, const nmod_mpoly_struct * betas, const mp_limb_t * alpha, const nmod_mpoly_ctx_t ctx) { int success = 1; slong i, j, k; n_poly_t p; n_poly_t G, S, pq; FLINT_ASSERT(bits <= FLINT_BITS); I->bits = bits; I->r = r; I->w = w; I->dbetas = FLINT_ARRAY_ALLOC(r, n_poly_struct); I->inv_prod_dbetas = FLINT_ARRAY_ALLOC(r, n_poly_struct); I->prod_mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, nmod_mpoly_struct); I->prod_mbetas_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, nmod_mpolyv_struct); I->mbetas = FLINT_ARRAY_ALLOC((w + 1)*r, nmod_mpoly_struct); I->deltas = FLINT_ARRAY_ALLOC((w + 1)*r, nmod_mpoly_struct); I->xalpha = FLINT_ARRAY_ALLOC(w + 1, nmod_mpoly_struct); I->q = FLINT_ARRAY_ALLOC(w + 1, nmod_mpoly_struct); I->G = FLINT_ARRAY_ALLOC(w + 1, nmod_mpoly_geobucket_struct); I->qt = FLINT_ARRAY_ALLOC(w + 1, nmod_mpoly_struct); I->newt = FLINT_ARRAY_ALLOC(w + 1, nmod_mpoly_struct); I->delta_coeffs = FLINT_ARRAY_ALLOC((w + 1)*r, nmod_mpolyv_struct); for (i = 0; i <= w; i++) { nmod_mpoly_init(I->xalpha + i, ctx); nmod_mpoly_init(I->q + i, ctx); nmod_mpoly_geobucket_init(I->G + i, ctx); nmod_mpoly_init(I->qt + i, ctx); nmod_mpoly_init(I->newt + i, ctx); for (j = 0; j < r; j++) { nmod_mpoly_init(I->deltas + i*r + j, ctx); nmod_mpolyv_init(I->delta_coeffs + i*r + j, ctx); } if (i < 1) continue; nmod_mpoly_gen(I->xalpha + i, i, ctx); nmod_mpoly_sub_ui(I->xalpha + i, I->xalpha + i, alpha[i - 1], ctx); nmod_mpoly_repack_bits_inplace(I->xalpha + i, I->bits, ctx); } n_poly_init(p); n_poly_init(G); n_poly_init(S); n_poly_init(pq); /* set betas */ i = w; for (j = 0; j < r; j++) { nmod_mpoly_init(I->mbetas + i*r + j, ctx); nmod_mpoly_set(I->mbetas + i*r + j, betas + j, ctx); } for (i--; i >= 0; i--) { for (j = 0; j < r; j++) { nmod_mpoly_init(I->mbetas + i*r + j, ctx); nmod_mpoly_evaluate_one_ui(I->mbetas + i*r + j, I->mbetas + (i + 1)*r + j, i + 1, alpha[i], ctx); } } for (j = 0; j < r; j++) { n_poly_init(I->dbetas + j); if (!nmod_mpoly_get_n_poly(I->dbetas + j, I->mbetas + 0*r + j, 0, ctx)) { success = 0; } } /* set product of betas */ for (i = w; i >= 0; i--) { for (j = 0; j < r; j++) { nmod_mpoly_init(I->prod_mbetas + i*r + j, ctx); nmod_mpoly_one(I->prod_mbetas + i*r + j, ctx); for (k = 0; k < r; k++) { if (k == j) continue; nmod_mpoly_mul(I->prod_mbetas + i*r + j, I->prod_mbetas + i*r + j, I->mbetas + i*r + k, ctx); } nmod_mpolyv_init(I->prod_mbetas_coeffs + i*r + j, ctx); if (i > 0) { nmod_mpoly_to_mpolyv(I->prod_mbetas_coeffs + i*r + j, I->prod_mbetas + i*r + j, I->xalpha + i, ctx); } } } for (j = 0; j < r; j++) n_poly_init(I->inv_prod_dbetas + j); for (j = 0; success && j < r; j++) { if (n_poly_degree(I->dbetas + j) != nmod_mpoly_degree_si(betas + j, 0, ctx)) { success = 0; } } for (j = 0; success && j < r; j++) { n_poly_one(pq); for (k = 0; k < r; k++) { if (k == j) continue; n_poly_mod_mul(pq, pq, I->dbetas + k, ctx->mod); } n_poly_mod_xgcd(G, S, I->inv_prod_dbetas + j, I->dbetas + j, pq, ctx->mod); if (!n_poly_is_one(G)) { success = 0; } } n_poly_clear(p); n_poly_clear(G); n_poly_clear(S); n_poly_clear(pq); I->dbetas_mvar = FLINT_ARRAY_ALLOC(r, nmod_mpoly_struct); I->inv_prod_dbetas_mvar = FLINT_ARRAY_ALLOC(r, nmod_mpoly_struct); for (j = 0; j < r; j++) { nmod_mpoly_init(I->dbetas_mvar + j, ctx); nmod_mpoly_init(I->inv_prod_dbetas_mvar + j, ctx); _nmod_mpoly_set_nmod_poly(I->dbetas_mvar + j, I->bits, I->dbetas[j].coeffs, I->dbetas[j].length, 0, ctx); _nmod_mpoly_set_nmod_poly(I->inv_prod_dbetas_mvar + j, I->bits, I->inv_prod_dbetas[j].coeffs, I->inv_prod_dbetas[j].length, 0, ctx); } nmod_mpoly_init(I->T, ctx); nmod_mpoly_init(I->Q, ctx); nmod_mpoly_init(I->R, ctx); FLINT_ASSERT(success == 1); return success; } void nmod_mpoly_pfrac_clear( nmod_mpoly_pfrac_t I, const nmod_mpoly_ctx_t ctx) { slong i, j; for (i = 0; i <= I->w; i++) { nmod_mpoly_clear(I->xalpha + i, ctx); nmod_mpoly_clear(I->q + i, ctx); nmod_mpoly_geobucket_clear(I->G + i, ctx); nmod_mpoly_clear(I->qt + i, ctx); nmod_mpoly_clear(I->newt + i, ctx); for (j = 0; j < I->r; j++) nmod_mpolyv_clear(I->delta_coeffs + i*I->r + j, ctx); } flint_free(I->xalpha); flint_free(I->q); flint_free(I->G); flint_free(I->qt); flint_free(I->newt); flint_free(I->delta_coeffs); for (j = 0; j < I->r; j++) { n_poly_clear(I->inv_prod_dbetas + j); n_poly_clear(I->dbetas + j); for (i = 0; i <= I->w; i++) { nmod_mpolyv_clear(I->prod_mbetas_coeffs + i*I->r + j, ctx); nmod_mpoly_clear(I->prod_mbetas + i*I->r + j, ctx); nmod_mpoly_clear(I->mbetas + i*I->r + j, ctx); nmod_mpoly_clear(I->deltas + i*I->r + j, ctx); } } flint_free(I->inv_prod_dbetas); flint_free(I->dbetas); flint_free(I->prod_mbetas); flint_free(I->prod_mbetas_coeffs); flint_free(I->mbetas); flint_free(I->deltas); for (j = 0; j < I->r; j++) { nmod_mpoly_clear(I->dbetas_mvar + j, ctx); nmod_mpoly_clear(I->inv_prod_dbetas_mvar + j, ctx); } flint_free(I->dbetas_mvar); flint_free(I->inv_prod_dbetas_mvar); nmod_mpoly_clear(I->T, ctx); nmod_mpoly_clear(I->Q, ctx); nmod_mpoly_clear(I->R, ctx); } int nmod_mpoly_pfrac( slong l, nmod_mpoly_t t, const slong * degs, nmod_mpoly_pfrac_t I, const nmod_mpoly_ctx_t ctx) { int success; slong i, j, k; nmod_mpoly_struct * deltas = I->deltas + l*I->r; nmod_mpoly_struct * newdeltas = I->deltas + (l - 1)*I->r; nmod_mpoly_struct * q = I->q + l; nmod_mpoly_struct * qt = I->qt + l; nmod_mpoly_struct * newt = I->newt + l; nmod_mpolyv_struct * delta_coeffs = I->delta_coeffs + l*I->r; nmod_mpoly_geobucket_struct * G = I->G + l; FLINT_ASSERT(l >= 0); if (!nmod_mpoly_repack_bits_inplace(t, I->bits, ctx)) return -1; if (l < 1) { for (i = 0; i < I->r; i++) { nmod_mpoly_divrem(I->Q, I->R, t, I->dbetas_mvar + i, ctx); nmod_mpoly_mul(I->T, I->R, I->inv_prod_dbetas_mvar + i, ctx); nmod_mpoly_divrem(I->Q, deltas + i, I->T, I->dbetas_mvar + i, ctx); } return 1; } for (i = 0; i < I->r; i++) delta_coeffs[i].length = 0; for (k = 0; k <= degs[l]; k++) { nmod_mpoly_divrem(q, newt, t, I->xalpha + l, ctx); nmod_mpoly_swap(t, q, ctx); nmod_mpoly_geobucket_set(G, newt, ctx); for (j = 0; j < k; j++) for (i = 0; i < I->r; i++) { if (j >= delta_coeffs[i].length) continue; if (k - j >= I->prod_mbetas_coeffs[l*I->r + i].length) continue; nmod_mpoly_mul(qt, delta_coeffs[i].coeffs + j, I->prod_mbetas_coeffs[l*I->r + i].coeffs + k - j, ctx); nmod_mpoly_geobucket_sub(G, qt, ctx); } nmod_mpoly_geobucket_empty(newt, G, ctx); if (nmod_mpoly_is_zero(newt, ctx)) continue; success = nmod_mpoly_pfrac(l - 1, newt, degs, I, ctx); if (success < 1) return success; for (i = 0; i < I->r; i++) { if (nmod_mpoly_is_zero(newdeltas + i, ctx)) continue; if (k + I->prod_mbetas_coeffs[l*I->r + i].length - 1 > degs[l]) return 0; nmod_mpolyv_set_coeff(delta_coeffs + i, k, newdeltas + i, ctx); } } for (i = 0; i < I->r; i++) nmod_mpoly_from_mpolyv(deltas + i, I->bits, delta_coeffs + i, I->xalpha + l, ctx); return 1; } flint-3.1.3/src/nmod_mpoly_factor/mpolyu.c000066400000000000000000000014471461254215100206340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" int nmod_mpolyu_is_canonical( const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->length; i++) { if (!nmod_mpoly_is_canonical(A->coeffs + i, ctx)) return 0; if (nmod_mpoly_is_zero(A->coeffs + i, ctx)) return 0; if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } flint-3.1.3/src/nmod_mpoly_factor/mpolyv.c000066400000000000000000000076701461254215100206410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" void nmod_mpolyv_clear(nmod_mpolyv_t A, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < A->alloc; i++) nmod_mpoly_clear(A->coeffs + i, ctx); flint_free(A->coeffs); } void nmod_mpolyv_fit_length( nmod_mpolyv_t A, slong length, const nmod_mpoly_ctx_t ctx) { slong i; slong old_alloc = A->alloc; slong new_alloc = FLINT_MAX(length, 2*A->alloc); if (length <= old_alloc) return; A->coeffs = (nmod_mpoly_struct *) flint_realloc(A->coeffs, new_alloc*sizeof(nmod_mpoly_struct)); for (i = old_alloc; i < new_alloc; i++) nmod_mpoly_init(A->coeffs + i, ctx); A->alloc = new_alloc; } void nmod_mpolyv_set_coeff( nmod_mpolyv_t A, slong i, nmod_mpoly_t c, /* clobbered */ const nmod_mpoly_ctx_t ctx) { slong j; FLINT_ASSERT(!nmod_mpoly_is_zero(c, ctx)); nmod_mpolyv_fit_length(A, i + 1, ctx); for (j = A->length; j < i; j++) nmod_mpoly_zero(A->coeffs + j, ctx); nmod_mpoly_swap(A->coeffs + i, c, ctx); A->length = FLINT_MAX(A->length, i + 1); } void nmod_mpoly_to_mpolyv( nmod_mpolyv_t A, const nmod_mpoly_t B, const nmod_mpoly_t xalpha, const nmod_mpoly_ctx_t ctx) { nmod_mpoly_t Q, T; nmod_mpoly_init(Q, ctx); nmod_mpoly_init(T, ctx); nmod_mpolyv_fit_length(A, 8, ctx); nmod_mpoly_divrem(Q, A->coeffs + 0, B, xalpha, ctx); A->length = 1; while (!nmod_mpoly_is_zero(Q, ctx)) { nmod_mpolyv_fit_length(A, A->length + 1, ctx); nmod_mpoly_divrem(T, A->coeffs + A->length, Q, xalpha, ctx); nmod_mpoly_swap(Q, T, ctx); A->length++; } while (A->length > 0 && nmod_mpoly_is_zero(A->coeffs + A->length - 1, ctx)) A->length--; nmod_mpoly_clear(Q, ctx); nmod_mpoly_clear(T, ctx); } void nmod_mpoly_from_mpolyv( nmod_mpoly_t A, flint_bitcnt_t Abits, const nmod_mpolyv_t B, const nmod_mpoly_t xalpha, const nmod_mpoly_ctx_t ctx) { slong i; nmod_mpoly_t T; nmod_mpoly_init(T, ctx); nmod_mpoly_zero(A, ctx); for (i = B->length - 1; i >= 0; i--) { nmod_mpoly_mul(T, A, xalpha, ctx); nmod_mpoly_add(A, T, B->coeffs + i, ctx); } nmod_mpoly_clear(T, ctx); nmod_mpoly_repack_bits_inplace(A, Abits, ctx); } int _nmod_mpoly_vec_content_mpoly( nmod_mpoly_t g, const nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_ctx_t ctx) { slong i, j1, j2; if (Alen <= 1) { if (Alen == 1) nmod_mpoly_make_monic(g, A + 0, ctx); else nmod_mpoly_zero(g, ctx); return 1; } j1 = 0; j2 = 1; for (i = 2; i < Alen; i++) { if (A[i].length < A[j1].length) j1 = i; else if (A[i].length < A[j2].length) j2 = i; } FLINT_ASSERT(j1 != j2); if (!nmod_mpoly_gcd(g, A + j1, A + j2, ctx)) return 0; for (i = 0; i < Alen; i++) { if (i == j1 || i == j2) continue; if (!nmod_mpoly_gcd(g, g, A + i, ctx)) return 0; } return 1; } void _nmod_mpoly_vec_divexact_mpoly( nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) nmod_mpoly_divexact(A + i, A + i, c, ctx); } void _nmod_mpoly_vec_mul_mpoly( nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx) { slong i; for (i = 0; i < Alen; i++) nmod_mpoly_mul(A + i, A + i, c, ctx); } flint-3.1.3/src/nmod_mpoly_factor/n_bpoly_mod.c000066400000000000000000000357041461254215100216130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" void nmod_mpoly_get_bpoly( n_bpoly_t A, const nmod_mpoly_t B, slong varx, slong vary, const nmod_mpoly_ctx_t ctx) { slong j; slong NB; ulong Bexpx, Bexpy; slong Boffx, Bshiftx, Boffy, Bshifty; ulong mask; FLINT_ASSERT(B->bits <= FLINT_BITS); NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); n_bpoly_zero(A); for (j = 0; j < B->length; j++) { Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask; Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask; n_bpoly_set_coeff(A, Bexpx, Bexpy, B->coeffs[j]); } } void nmod_mpoly_set_bpoly( nmod_mpoly_t A, flint_bitcnt_t Abits, const n_bpoly_t B, slong varx, slong vary, const nmod_mpoly_ctx_t ctx) { slong n = ctx->minfo->nvars; slong i, j; slong NA; slong Alen; mp_limb_t * Acoeff; ulong * Aexp; ulong * Aexps; TMP_INIT; FLINT_ASSERT(B->length > 0); FLINT_ASSERT(Abits <= FLINT_BITS); TMP_START; Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong)); for (i = 0; i < n; i++) Aexps[i] = 0; NA = mpoly_words_per_exp(Abits, ctx->minfo); nmod_mpoly_fit_length_reset_bits(A, 4, Abits, ctx); Acoeff = A->coeffs; Aexp = A->exps; Alen = 0; for (i = 0; i < B->length; i++) { n_poly_struct * Bc = B->coeffs + i; _nmod_mpoly_fit_length(&Acoeff, &A->coeffs_alloc, &Aexp, &A->exps_alloc, NA, Alen + Bc->length); for (j = 0; j < Bc->length; j++) { if (0 == Bc->coeffs[j]) continue; Aexps[varx] = i; Aexps[vary] = j; Acoeff[Alen] = Bc->coeffs[j]; mpoly_set_monomial_ui(Aexp + NA*Alen, Aexps, Abits, ctx->minfo); Alen++; } } A->coeffs = Acoeff; A->exps = Aexp; A->length = Alen; TMP_END; nmod_mpoly_sort_terms(A, ctx); } void n_bpoly_mod_taylor_shift_gen1(n_bpoly_t A, const n_bpoly_t B, mp_limb_t c, nmod_t ctx) { slong i; n_bpoly_set(A, B); for (i = A->length - 1; i >= 0; i--) n_poly_mod_taylor_shift(A->coeffs + i, c, ctx); } void n_bpoly_mod_sub( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t mod) { slong i; slong Alen = FLINT_MAX(B->length, C->length); FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_bpoly_fit_length(A, Alen); A->length = 0; for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) { n_poly_mod_sub(A->coeffs + i, B->coeffs + i, C->coeffs + i, mod); } else { n_poly_set(A->coeffs + i, B->coeffs + i); } } else { FLINT_ASSERT(i < C->length); n_poly_mod_neg(A->coeffs + i, C->coeffs + i, mod); } if (!n_poly_is_zero(A->coeffs + i)) A->length = i + 1; } } void n_bpoly_mod_add( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t mod) { slong i; slong Alen = FLINT_MAX(B->length, C->length); FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_bpoly_fit_length(A, Alen); A->length = 0; for (i = 0; i < Alen; i++) { if (i < B->length) { if (i < C->length) { n_poly_mod_add(A->coeffs + i, B->coeffs + i, C->coeffs + i, mod); } else { n_poly_set(A->coeffs + i, B->coeffs + i); } } else { FLINT_ASSERT(i < C->length); n_poly_set(A->coeffs + i, C->coeffs + i); } if (!n_poly_is_zero(A->coeffs + i)) A->length = i + 1; } } void n_bpoly_mod_make_primitive(n_poly_t g, n_bpoly_t A, nmod_t ctx) { mp_limb_t c = 1; slong Alen = A->length; slong i; n_poly_t q, r; n_poly_init(q); n_poly_init(r); n_poly_zero(g); for (i = 0; i < Alen; i++) { n_poly_mod_gcd(q, g, A->coeffs + i, ctx); n_poly_swap(g, q); } for (i = 0; i < Alen; i++) { n_poly_mod_divrem(q, r, A->coeffs + i, g, ctx); FLINT_ASSERT(n_poly_is_zero(r)); n_poly_swap(A->coeffs + i, q); } /* make lc_xy(A) one */ if (Alen > 0) { c = A->coeffs[Alen - 1].coeffs[A->coeffs[Alen - 1].length - 1]; if (c != 1) { _n_poly_mod_scalar_mul_nmod(g, g, c, ctx); c = nmod_inv(c, ctx); for (i = 0; i < Alen; i++) _n_poly_mod_scalar_mul_nmod(A->coeffs + i, A->coeffs + i, c, ctx); } } n_poly_clear(q); n_poly_clear(r); } /* multiplication in F[y][x] */ void n_bpoly_mod_mul( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t ctx) { slong i, j; n_poly_struct * t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); if (B->length < 1 || C->length < 1) { A->length = 0; return; } if (B->length > 2 && C->length > 2) { n_poly_t a, b, c; slong order = n_bpoly_degree1(B) + n_bpoly_degree1(C) + 1; n_poly_init(a); n_poly_init(b); n_poly_init(c); for (i = B->length - 1; i >= 0; i--) { n_poly_struct * Bi = B->coeffs + i; for (j = Bi->length - 1; j >= 0; j--) n_poly_set_coeff(b, order*i + j, Bi->coeffs[j]); } for (i = C->length - 1; i >= 0; i--) { n_poly_struct * Ci = C->coeffs + i; for (j = Ci->length - 1; j >= 0; j--) n_poly_set_coeff(c, order*i + j, Ci->coeffs[j]); } n_poly_mod_mul(a, b, c, ctx); A->length = 0; for (i = B->length + C->length - 1; i >= 0; i--) { for (j = order - 1; j >= 0; j--) n_bpoly_set_coeff(A, i, j, n_poly_get_coeff(a, order*i + j)); } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); return; } n_bpoly_fit_length(A, B->length + C->length); for (i = 0; i < B->length + C->length - 1; i++) n_poly_zero(A->coeffs + i); t = A->coeffs + B->length + C->length - 1; for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { _n_poly_mod_mul(t, B->coeffs + i, C->coeffs + j, ctx); n_poly_mod_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } A->length = B->length + C->length - 1; n_bpoly_normalise(A); } /* multiplication in (F[y]/y^order)[x] B, C need not be reduced mod y^order A should come out reduced mod y^order */ void n_bpoly_mod_mul_series( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, slong order, nmod_t ctx) { slong i, j; n_poly_t t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); if (B->length < 1 || C->length < 1) { A->length = 0; return; } if (B->length > 2 && C->length > 2) { n_poly_t a, b, c; n_poly_init(a); n_poly_init(b); n_poly_init(c); for (i = B->length - 1; i >= 0; i--) { n_poly_struct * Bi = B->coeffs + i; for (j = FLINT_MIN(order, Bi->length) - 1; j >= 0; j--) n_poly_set_coeff(b, 2*order*i + j, Bi->coeffs[j]); } for (i = C->length - 1; i >= 0; i--) { n_poly_struct * Ci = C->coeffs + i; for (j = FLINT_MIN(order, Ci->length) - 1; j >= 0; j--) n_poly_set_coeff(c, 2*order*i + j, Ci->coeffs[j]); } n_poly_mod_mul(a, b, c, ctx); A->length = 0; for (i = B->length + C->length - 1; i >= 0; i--) { for (j = order - 1; j >= 0; j--) n_bpoly_set_coeff(A, i, j, n_poly_get_coeff(a, 2*order*i + j)); } n_poly_clear(a); n_poly_clear(b); n_poly_clear(c); return; } n_poly_init(t); n_bpoly_fit_length(A, B->length + C->length - 1); for (i = 0; i < B->length + C->length - 1; i++) n_poly_zero(A->coeffs + i); for (i = 0; i < B->length; i++) { for (j = 0; j < C->length; j++) { n_poly_mod_mullow(t, B->coeffs + i, C->coeffs + j, order, ctx); n_poly_mod_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); } } A->length = B->length + C->length - 1; n_bpoly_normalise(A); n_poly_clear(t); } /* division in (F[y]/y^order)[x] A, B need not be reduced mod y^order Q, R should come out reduced mod y^order TODO: make this faster */ void n_bpoly_mod_divrem_series( n_bpoly_t Q, n_bpoly_t R, const n_bpoly_t A, const n_bpoly_t B, slong order, nmod_t ctx) { slong i, qoff; n_poly_t q, t; FLINT_ASSERT(R != A); FLINT_ASSERT(R != B); FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); n_poly_init(q); n_poly_init(t); n_bpoly_set(R, A); for (i = 0; i < R->length; i++) n_poly_truncate(R->coeffs + i, order); n_bpoly_normalise(R); Q->length = 0; while (R->length >= B->length) { n_poly_mod_div_series(q, R->coeffs + R->length - 1, B->coeffs + B->length - 1, order, ctx); for (i = 0; i < B->length; i++) { n_poly_mod_mullow(t, B->coeffs + i, q, order, ctx); n_poly_mod_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { n_bpoly_fit_length(Q, qoff + 1); for (i = Q->length; i <= qoff; i++) n_poly_zero(Q->coeffs + i); Q->length = qoff + 1; } n_poly_set(Q->coeffs + qoff, q); FLINT_ASSERT(n_poly_is_zero(R->coeffs + R->length - 1)); n_bpoly_normalise(R); } n_poly_clear(q); n_poly_clear(t); } /* divisibility in F[y][x] */ int n_bpoly_mod_divides( n_bpoly_t Q, const n_bpoly_t A, const n_bpoly_t B, nmod_t ctx) { slong i, qoff; int divides; n_poly_t q, t; n_bpoly_t R; FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); /* ksub not faster :( */ if (0 && A->length > B->length && B->length > 2) { n_poly_t a, b, q, r; slong j; slong Adeg = n_bpoly_degree1(A); slong Bdeg = n_bpoly_degree1(B); slong Qdeg = Adeg - Bdeg; slong order = Adeg + 1; if (Qdeg < 0) return 0; n_poly_init(a); n_poly_init(b); n_poly_init(q); n_poly_init(r); for (i = B->length - 1; i >= 0; i--) { n_poly_struct * Bi = B->coeffs + i; for (j = Bi->length - 1; j >= 0; j--) n_poly_set_coeff(b, order*i + j, Bi->coeffs[j]); } for (i = A->length - 1; i >= 0; i--) { n_poly_struct * Ai = A->coeffs + i; for (j = Ai->length - 1; j >= 0; j--) n_poly_set_coeff(a, order*i + j, Ai->coeffs[j]); } n_poly_mod_divrem(q, r, a, b, ctx); if (r->length > 0 || q->length - 1 < order*(A->length - B->length) || q->length - 1 > Qdeg + order*(A->length - B->length)) { divides = 0; goto cleanup_inner; } for (i = A->length - B->length; i >= 0; i--) { for (j = order - 1; j >= 0; j--) { mp_limb_t qc = n_poly_get_coeff(q, order*i + j); if (qc == 0) continue; if (j > Qdeg) { divides = 0; goto cleanup_inner; } n_bpoly_set_coeff(Q, i, j, qc); } } divides = 1; cleanup_inner: n_poly_clear(a); n_poly_clear(b); n_poly_clear(q); n_poly_clear(r); return divides; } n_poly_init(q); n_poly_init(t); n_bpoly_init(R); n_bpoly_set(R, A); Q->length = 0; while (R->length >= B->length) { _n_poly_mod_divrem(q, t, R->coeffs + R->length - 1, B->coeffs + B->length - 1, ctx); if (!n_poly_is_zero(t)) { divides = 0; goto cleanup; } for (i = 0; i < B->length; i++) { _n_poly_mod_mul(t, B->coeffs + i, q, ctx); n_poly_mod_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { n_bpoly_fit_length(Q, qoff + 1); for (i = Q->length; i <= qoff; i++) n_poly_zero(Q->coeffs + i); Q->length = qoff + 1; } n_poly_set(Q->coeffs + qoff, q); while (R->length > 0 && n_poly_is_zero(R->coeffs + R->length - 1)) R->length--; } divides = (R->length == 0); cleanup: n_poly_clear(q); n_poly_clear(t); n_bpoly_clear(R); return divides; } void n_bpoly_mod_taylor_shift_gen0(n_bpoly_t A, mp_limb_t alpha, nmod_t ctx) { slong i, j; slong n = A->length; n_poly_struct * Acoeffs = A->coeffs; mp_limb_t c; FLINT_ASSERT(alpha < ctx.n); if (alpha == 0) return; c = 1; for (i = 1; i < n; i++) { c = nmod_mul(c, alpha, ctx); if (c != 1) { _nmod_vec_scalar_mul_nmod(Acoeffs[i].coeffs, Acoeffs[i].coeffs, Acoeffs[i].length, c, ctx); } } for (i = n - 2; i >= 0; i--) { for (j = i; j < n - 1; j++) { n_poly_mod_add(Acoeffs + j, Acoeffs + j, Acoeffs + j + 1, ctx); } } alpha = nmod_inv(alpha, ctx); c = 1; for (i = 1; i < n; i++) { c = nmod_mul(c, alpha, ctx); if (c != 1) { _nmod_vec_scalar_mul_nmod(Acoeffs[i].coeffs, Acoeffs[i].coeffs, Acoeffs[i].length, c, ctx); } } } flint-3.1.3/src/nmod_mpoly_factor/n_bpoly_mod_factor_lgprime.c000066400000000000000000000570731461254215100246730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "fmpz_poly_factor.h" #include "fq_nmod.h" #include "fq_nmod_poly.h" #include "fq_nmod_poly_factor.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" static void n_bpoly_eval_fq_nmod_poly( fq_nmod_poly_t A, const fq_nmod_ctx_t ectx, const n_bpoly_t B) { slong i; n_poly_t t; n_poly_t mock; nmod_poly_t mock2; n_poly_init(t); fq_nmod_poly_zero(A, ectx); for (i = B->length - 1; i >= 0; i--) { n_poly_mock(mock, ectx->modulus); n_poly_mod_rem(t, B->coeffs + i, mock, ectx->modulus->mod); nmod_poly_mock(mock2, t, ectx->modulus->mod); fq_nmod_poly_set_coeff(A, i, mock2, ectx); } n_poly_clear(t); } static void n_bpoly_mod_make_monic_mod(n_bpoly_t A, n_poly_t mk, nmod_t mod) { slong i; n_poly_t t, lcinv; FLINT_ASSERT(A->length > 0); FLINT_ASSERT(n_bpoly_mod_is_canonical(A, mod)); n_poly_init(t); n_poly_init(lcinv); if (!n_poly_mod_invmod(lcinv, A->coeffs + A->length - 1, mk, mod)) { FLINT_ASSERT(0); } for (i = 0; i < A->length; i++) { n_poly_mod_mulmod(t, A->coeffs + i, lcinv, mk, mod); n_poly_swap(A->coeffs + i, t); } n_poly_clear(t); n_poly_clear(lcinv); } static void n_bpoly_set_fq_nmod_poly_gen0( n_bpoly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ectx) { slong i; n_bpoly_fit_length(A, B->length); A->length = B->length; for (i = 0; i < B->length; i++) n_poly_set_nmod_poly(A->coeffs + i, B->coeffs + i); } static void n_bpoly_mod_mul_mod_poly( n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, const n_poly_t m, nmod_t ctx) { slong i, j; n_poly_t t; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_poly_init(t); n_bpoly_fit_length(A, B->length + C->length - 1); for (i = 0; i < B->length + C->length - 1; i++) n_poly_zero(A->coeffs + i); for (i = 0; i < B->length; i++) for (j = 0; j < C->length; j++) { n_poly_mod_mul(t, B->coeffs + i, C->coeffs + j, ctx); n_poly_mod_add(A->coeffs + i + j, A->coeffs + i + j, t, ctx); n_poly_mod_rem(A->coeffs + i + j, A->coeffs + i + j, m, ctx); } A->length = B->length + C->length - 1; n_bpoly_normalise(A); n_poly_clear(t); } /* division in ((Z/nZ)[y]/m(y))[x] */ static void n_bpoly_mod_divrem_mod_poly( n_bpoly_t Q, n_bpoly_t R, const n_bpoly_t A, const n_bpoly_t B, const n_poly_t m, nmod_t ctx) { slong i, qoff; n_poly_t q, t, Binv; FLINT_ASSERT(R != A); FLINT_ASSERT(R != B); FLINT_ASSERT(Q != A); FLINT_ASSERT(Q != B); FLINT_ASSERT(B->length > 0); n_poly_init(q); n_poly_init(t); n_poly_init(Binv); n_bpoly_set(R, A); Q->length = 0; if (!n_poly_mod_invmod(Binv, B->coeffs + B->length - 1, m, ctx)) { FLINT_ASSERT(0); } while (R->length >= B->length) { n_poly_mod_mulmod(q, R->coeffs + R->length - 1, Binv, m, ctx); for (i = 0; i < B->length; i++) { n_poly_mod_mulmod(t, B->coeffs + i, q, m, ctx); n_poly_mod_sub(R->coeffs + i + R->length - B->length, R->coeffs + i + R->length - B->length, t, ctx); } qoff = R->length - B->length; FLINT_ASSERT(qoff >= 0); if (qoff >= Q->length) { n_bpoly_fit_length(Q, qoff + 1); for (i = Q->length; i <= qoff; i++) n_poly_zero(Q->coeffs + i); Q->length = qoff + 1; } n_poly_set(Q->coeffs + qoff, q); FLINT_ASSERT(n_poly_is_zero(R->coeffs + R->length - 1)); n_bpoly_normalise(R); } n_poly_clear(q); n_poly_clear(t); n_poly_clear(Binv); } static int _zassenhaus( const zassenhaus_prune_t zas, slong limit, n_tpoly_t F, const n_poly_t finalmpow, const nmod_mat_t N, n_bpoly_struct * const * loc_fac_org, slong r, const n_bpoly_t B, nmod_t ctx) { int success; slong total_deg; n_bpoly_t Q, R, t1, t2; n_poly_t leadf, g; slong i, j, k, len, d = nmod_mat_nrows(N); slong * subset; n_bpoly_struct * loc_fac; n_bpoly_struct * f; n_bpoly_t B_copy; FLINT_ASSERT(nmod_mat_ncols(N) == r); loc_fac = (n_bpoly_struct *) flint_malloc(d*sizeof(n_bpoly_struct)); for (i = 0; i < d; i++) n_bpoly_init(loc_fac + i); n_poly_init(g); n_bpoly_init(Q); n_bpoly_init(R); n_bpoly_init(t1); n_bpoly_init(t2); n_poly_init(leadf); n_bpoly_init(B_copy); for (i = 0; i < d; i++) { n_bpoly_one(loc_fac + i); for (j = 0; j < r; j++) { if (nmod_mat_entry(N, i, j) == 0) continue; FLINT_ASSERT(nmod_mat_entry(N, i, j) == 1); n_bpoly_mod_mul_mod_poly(t1, loc_fac + i, loc_fac_org[j], finalmpow, ctx); n_bpoly_swap(t1, loc_fac + i); } } f = (n_bpoly_struct *) B; FLINT_ASSERT(f->length > 0); n_poly_set(leadf, f->coeffs + f->length - 1); subset = (slong *) flint_malloc(d * sizeof(slong)); for (k = 0; k < d; k++) subset[k] = k; len = d; for (k = 1; k <= len/2; k++) { if (k > limit) { success = 0; goto cleanup; } zassenhaus_subset_first(subset, len, k); while (1) { total_deg = 0; for (i = 0; i < len; i++) { if (subset[i] >= 0) total_deg += loc_fac[subset[i]].length - 1; } if (!zassenhaus_prune_degree_is_possible(zas, total_deg)) { if (!zassenhaus_subset_next(subset, len)) break; continue; } n_bpoly_set_poly_gen1(t1, leadf); for (i = 0; i < len; i++) { if (subset[i] >= 0) { n_bpoly_mod_mul_mod_poly(t2, t1, loc_fac + subset[i], finalmpow, ctx); n_bpoly_swap(t1, t2); } } n_bpoly_mod_make_primitive(g, t1, ctx); if (n_bpoly_mod_divides(Q, f, t1, ctx)) { n_tpoly_fit_length(F, F->length + 1); n_bpoly_swap(F->coeffs + F->length, t1); F->length++; f = B_copy; n_bpoly_swap(f, Q); FLINT_ASSERT(f->length > 0); n_poly_set(leadf, f->coeffs + f->length - 1); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (f->length > 1) { n_tpoly_fit_length(F, F->length + 1); n_bpoly_set(F->coeffs + F->length, f); F->length++; } else { FLINT_ASSERT(f->length == 1); FLINT_ASSERT(n_poly_is_one(f->coeffs + 0)); } success = 1; cleanup: flint_free(subset); n_poly_clear(g); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(t1); n_bpoly_clear(t2); n_poly_clear(leadf); n_bpoly_clear(B_copy); for (i = 0; i < d; i++) n_bpoly_clear(loc_fac + i); flint_free(loc_fac); return success; } static void _hensel_build_tree( slong * link, n_bpoly_struct * v, n_bpoly_struct * w, const fq_nmod_poly_struct * local_facs, slong r, fq_nmod_ctx_t ctx) { slong i, j; fq_nmod_poly_t d; fq_nmod_poly_struct * V; fq_nmod_poly_struct * W; V = (fq_nmod_poly_struct *) flint_malloc((2*r - 2)*sizeof(fq_nmod_poly_struct)); W = (fq_nmod_poly_struct *) flint_malloc((2*r - 2)*sizeof(fq_nmod_poly_struct)); fq_nmod_poly_init(d, ctx); for (i = 0; i < 2*r - 2; i++) { fq_nmod_poly_init(V + i, ctx); fq_nmod_poly_init(W + i, ctx); } for (i = 0; i < r; i++) { fq_nmod_poly_set(V + i, local_facs + i, ctx); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp, mind; minp = j; mind = fq_nmod_poly_degree(V + j, ctx); for (s = j + 1; s < i; s++) { if (fq_nmod_poly_degree(V + s, ctx) < mind) { minp = s; mind = fq_nmod_poly_degree(V + s, ctx); } } fq_nmod_poly_swap(V + j, V + minp, ctx); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = fq_nmod_poly_degree(V + j + 1, ctx); for (s = j + 2; s < i; s++) { if (fq_nmod_poly_degree(V + s, ctx) < mind) { minp = s; mind = fq_nmod_poly_degree(V + s, ctx); } } fq_nmod_poly_swap(V + j + 1, V + minp, ctx); FLINT_SWAP(slong, link[j + 1], link[minp]); fq_nmod_poly_mul(V + i, V + j, V + j + 1, ctx); link[i] = j; } for (j = 0; j < 2*r - 2; j += 2) { fq_nmod_poly_xgcd(d, W + j, W + j + 1, V + j, V + j + 1, ctx); FLINT_ASSERT(fq_nmod_poly_is_one(d, ctx)); } for (j = 0; j < 2*r - 2; j++) { n_bpoly_set_fq_nmod_poly_gen0(v + j, V + j, ctx); n_bpoly_set_fq_nmod_poly_gen0(w + j, W + j, ctx); } fq_nmod_poly_clear(d, ctx); for (i = 0; i < 2*r - 2; i++) { fq_nmod_poly_clear(V + i, ctx); fq_nmod_poly_clear(W + i, ctx); } flint_free(V); flint_free(W); } static void _hensel_lift_fac( n_bpoly_t G, n_bpoly_t H, const n_bpoly_t f, n_bpoly_t g, n_bpoly_t h, const n_bpoly_t a, const n_bpoly_t b, const n_poly_t p0, const n_poly_t p1, nmod_t ctx) { slong i; n_bpoly_t c, t1, t2, q, r; n_poly_t tq, tr; n_bpoly_init(c); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(q); n_bpoly_init(r); n_poly_init(tq); n_poly_init(tr); #if FLINT_WANT_ASSERT n_bpoly_mod_mul(t1, g, a, ctx); n_bpoly_mod_mul(t2, h, b, ctx); n_bpoly_mod_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_poly_mod_neg(c->coeffs + i, c->coeffs + i, ctx); n_poly_mod_add_ui(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { n_poly_mod_divrem(tq, tr, c->coeffs + i, p0, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); } #endif n_bpoly_mod_mul(t1, g, h, ctx); n_bpoly_mod_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { n_poly_mod_divrem(tq, tr, c->coeffs + i, p0, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); n_poly_mod_divrem(tr, c->coeffs + i, tq, p1, ctx); } n_bpoly_mod_mul_mod_poly(t1, c, b, p1, ctx); n_bpoly_mod_divrem_mod_poly(q, r, t1, g, p1, ctx); for (i = 0; i < r->length; i++) n_poly_mod_mul(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < g->length; i++) n_poly_mod_divrem(tq, g->coeffs + i, g->coeffs + i, p0, ctx); n_bpoly_mod_add(t1, r, g, ctx); n_bpoly_mod_mul_mod_poly(t2, c, a, p1, ctx); n_bpoly_mod_divrem_mod_poly(q, r, t2, h, p1, ctx); for (i = 0; i < r->length; i++) n_poly_mod_mul(r->coeffs + i, r->coeffs + i, p0, ctx); for (i = 0; i < h->length; i++) n_poly_mod_divrem(tq, h->coeffs + i, h->coeffs + i, p0, ctx); n_bpoly_mod_add(t2, r, h, ctx); n_bpoly_swap(G, t1); n_bpoly_swap(H, t2); #if FLINT_WANT_ASSERT { n_poly_t p01; n_poly_init(p01); n_poly_mod_mul(p01, p0, p1, ctx); n_bpoly_mod_mul(t1, G, H, ctx); n_bpoly_mod_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { n_poly_mod_divrem(tq, tr, c->coeffs + i, p01, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); } n_poly_clear(p01); } #endif n_bpoly_clear(c); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(q); n_bpoly_clear(r); n_poly_clear(tq); n_poly_clear(tr); } static void _hensel_lift_inv( n_bpoly_t A, n_bpoly_t B, const n_bpoly_t G, const n_bpoly_t H, n_bpoly_t a, n_bpoly_t b, const n_poly_t p0, const n_poly_t p1, nmod_t ctx) { slong i; n_bpoly_t c, t1, t2, q, r; n_poly_t tq, tr; n_bpoly_init(c); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(q); n_bpoly_init(r); n_poly_init(tq); n_poly_init(tr); for (i = 0; i < b->length; i++) n_poly_mod_divrem(tq, b->coeffs + i, b->coeffs + i, p0, ctx); for (i = 0; i < a->length; i++) n_poly_mod_divrem(tq, a->coeffs + i, a->coeffs + i, p0, ctx); n_bpoly_mod_mul(t1, G, a, ctx); n_bpoly_mod_mul(t2, H, b, ctx); n_bpoly_mod_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_poly_mod_neg(c->coeffs + i, c->coeffs + i, ctx); n_poly_mod_add_ui(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { n_poly_mod_divrem(tq, tr, c->coeffs + i, p0, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); n_poly_mod_divrem(tr, c->coeffs + i, tq, p1, ctx); } n_bpoly_mod_mul_mod_poly(t1, c, b, p1, ctx); n_bpoly_mod_divrem_mod_poly(q, r, t1, G, p1, ctx); for (i = 0; i < r->length; i++) n_poly_mod_mul(r->coeffs + i, r->coeffs + i, p0, ctx); n_bpoly_mod_add(t1, r, b, ctx); n_bpoly_mod_mul_mod_poly(t2, c, a, p1, ctx); n_bpoly_mod_divrem_mod_poly(q, r, t2, H, p1, ctx); for (i = 0; i < r->length; i++) n_poly_mod_mul(r->coeffs + i, r->coeffs + i, p0, ctx); n_bpoly_mod_add(t2, r, a, ctx); n_bpoly_swap(t1, B); n_bpoly_swap(t2, A); #if FLINT_WANT_ASSERT { n_poly_t p01; n_poly_init(p01); n_poly_mod_mul(p01, p0, p1, ctx); n_bpoly_mod_mul(t1, G, A, ctx); n_bpoly_mod_mul(t2, H, B, ctx); n_bpoly_mod_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_poly_mod_neg(c->coeffs + i, c->coeffs + i, ctx); n_poly_mod_add_ui(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { n_poly_mod_divrem(tq, tr, c->coeffs + i, p01, ctx); FLINT_ASSERT(n_poly_is_zero(tr)); } n_poly_clear(p01); } #endif n_bpoly_clear(c); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(q); n_bpoly_clear(r); n_poly_clear(tq); n_poly_clear(tr); } static void _hensel_lift_tree( int opt, slong * link, n_bpoly_struct * v, n_bpoly_struct * w, const n_bpoly_t f, slong j, const n_poly_t p0, const n_poly_t p1, nmod_t ctx) { FLINT_ASSERT(p1->length <= p0->length); if (j < 0) return; if (opt >= 0) _hensel_lift_fac(v + j, v + j + 1, f, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); if (opt <= 0) _hensel_lift_inv(w + j, w + j + 1, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j, link[j], p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j + 1, link[j + 1], p0, p1, ctx); } static void _lattice( nmod_mat_t N, n_bpoly_struct * const * g, slong r, const n_poly_t lift_alpha_pow, slong * starts, const n_bpoly_t f, nmod_t ctx) { slong i, j, k; n_bpoly_t Q, R, dg; n_bpoly_struct * ld; nmod_mat_t M, T1, T2; int nlimbs; mp_limb_t * trow; slong lift_order = lift_alpha_pow->length - 1; nlimbs = _nmod_vec_dot_bound_limbs(r, ctx); trow = (mp_limb_t *) flint_malloc(r*sizeof(mp_limb_t)); n_bpoly_init(Q); n_bpoly_init(R); n_bpoly_init(dg); ld = (n_bpoly_struct *) flint_malloc(r*sizeof(n_bpoly_struct)); for (i = 0; i < r; i++) n_bpoly_init(ld + i); /* init done */ for (i = 0; i < r; i++) { n_bpoly_mod_divrem_mod_poly(Q, R, f, g[i], lift_alpha_pow, ctx); FLINT_ASSERT(R->length == 0); n_bpoly_mod_derivative_gen0(R, g[i], ctx); n_bpoly_mod_mul_mod_poly(ld + i, Q, R, lift_alpha_pow, ctx); } for (k = 0; k + 1 < f->length; k++) { slong d = nmod_mat_nrows(N); if (d < 2) break; if (lift_order <= starts[k]) continue; nmod_mat_init(M, lift_order - starts[k], d, ctx.n); for (j = starts[k]; j < lift_order; j++) { for (i = 0; i < r; i++) trow[i] = n_bpoly_get_coeff(ld + i, k, j); for (i = 0; i < d; i++) nmod_mat_entry(M, j - starts[k], i) = _nmod_vec_dot(trow, N->rows[i], r, ctx, nlimbs); } nmod_mat_init_nullspace_tr(T1, M); nmod_mat_init(T2, nmod_mat_nrows(T1), nmod_mat_ncols(N), ctx.n); nmod_mat_mul(T2, T1, N); nmod_mat_swap(T2, N); nmod_mat_rref(N); nmod_mat_clear(M); nmod_mat_clear(T1); nmod_mat_clear(T2); if (nmod_mat_is_reduced(N)) break; } flint_free(trow); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(dg); for (i = 0; i < r; i++) n_bpoly_clear(ld + i); flint_free(ld); } void n_bpoly_mod_factor_lgprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, nmod_t ctx) { int success; slong i, r, deg; slong Blenx = B->length; slong Bleny; slong final_pow, curr_lift_pow, prev_lift_pow, next_lift_pow; slong * starts; fq_nmod_poly_t Beval; fq_nmod_poly_factor_t local_fac; fq_nmod_t Blc; n_bpoly_t monicB; nmod_mat_t N; slong * link; n_bpoly_struct * v, * w, ** lift_fac; n_tpoly_t tmp; slong e[FLINT_BITS]; slong old_nrows; slong zas_limit; n_poly_t final_alpha_pow, curr_alpha_pow, prev_alpha_pow, next_alpha_pow; n_poly_t alpha, p1; fq_nmod_ctx_t ectx; zassenhaus_prune_t zas; FLINT_ASSERT(Blenx > 1); deg = 2; fq_nmod_ctx_init_ui(ectx, ctx.n, deg, "y"); n_poly_init(final_alpha_pow); n_poly_init(curr_alpha_pow); n_poly_init(prev_alpha_pow); n_poly_init(next_alpha_pow); fq_nmod_poly_init(Beval, ectx); fq_nmod_poly_factor_init(local_fac, ectx); fq_nmod_init(Blc, ectx); n_bpoly_init(monicB); n_tpoly_init(tmp); nmod_mat_init(N, 0, 0, ctx.n); starts = (slong *) flint_malloc(Blenx*sizeof(slong)); link = (slong *) flint_malloc(sizeof(slong)); lift_fac = (n_bpoly_struct **) flint_malloc(sizeof(n_bpoly_struct *)); n_poly_init(p1); zassenhaus_prune_init(zas); /* init done */ n_poly_mock(alpha, ectx->modulus); n_bpoly_mod_make_primitive(c, B, ctx); Bleny = 0; for (i = 0; i < B->length; i++) Bleny = FLINT_MAX(Bleny, (B->coeffs + i)->length); /* CLD bounds */ for (i = 0; i < Blenx; i++) starts[i] = Bleny; zassenhaus_prune_set_degree(zas, Blenx - 1); goto got_alpha; next_alpha: deg++; fq_nmod_ctx_clear(ectx); fq_nmod_ctx_init_ui(ectx, ctx.n, deg, "y"); n_poly_mock(alpha, ectx->modulus); got_alpha: n_bpoly_eval_fq_nmod_poly(Beval, ectx, B); /* if killed leading/trailing coeff, get new alpha */ if (Beval->length != Blenx || fq_nmod_is_zero(Beval->coeffs + 0, ectx)) goto next_alpha; local_fac->num = 0; fq_nmod_poly_factor(local_fac, Blc, Beval, ectx); r = local_fac->num; zassenhaus_prune_start_add_factors(zas); for (i = 0; i < r; i++) zassenhaus_prune_add_factor(zas, fq_nmod_poly_degree(local_fac->poly + i, ectx), local_fac->exp[i]); zassenhaus_prune_end_add_factors(zas); if ((r < 2 && local_fac->exp[0] == 1) || zassenhaus_prune_must_be_irreducible(zas)) { n_tpoly_fit_length(F, 1); F->length = 1; n_bpoly_swap(F->coeffs + 0, B); goto cleanup; } /* if multiple factors, get new alpha */ for (i = 0; i < r; i++) { if (local_fac->exp[i] != 1) goto next_alpha; } for (i = 0; i < r; i++) { FLINT_ASSERT(local_fac->poly[i].length > 1); FLINT_ASSERT(fq_nmod_is_one(local_fac->poly[i].coeffs + local_fac->poly[i].length - 1, ectx)); } /* precision for constructing true factors */ final_pow = (Bleny - 1 + deg)/deg; n_poly_mod_pow(final_alpha_pow, alpha, final_pow, ctx); nmod_mat_clear(N); nmod_mat_init(N, r, r, ctx.n); for (i = 0; i < r; i++) nmod_mat_entry(N, i, i) = 1; link = (slong *) flint_realloc(link, (2*r - 2)*sizeof(slong)); lift_fac = (n_bpoly_struct **) flint_realloc(lift_fac, r*sizeof(n_bpoly_struct *)); n_tpoly_fit_length(tmp, 2*(2*r - 2)); v = tmp->coeffs + 0; w = tmp->coeffs + (2*r - 2); curr_lift_pow = final_pow + r; n_poly_mod_pow(curr_alpha_pow, alpha, curr_lift_pow, ctx); n_bpoly_set(monicB, B); n_bpoly_mod_make_monic_mod(monicB, curr_alpha_pow, ctx); _hensel_build_tree(link, v, w, local_fac->poly, r, ectx); for (i = 0; i < 2*r - 2; i++) if (-link[i] - 1 >= 0) lift_fac[-link[i] - 1] = v + i; FLINT_ASSERT(curr_lift_pow > 1); for (i = 0, e[i] = curr_lift_pow; e[i] > 1; i++) e[i+1] = (e[i] + 1) / 2; for (i--; i > 0; i--) { n_poly_mod_pow(prev_alpha_pow, alpha, e[i+1], ctx); n_poly_mod_pow(p1, alpha, e[i]-e[i+1], ctx); _hensel_lift_tree(0, link, v, w, monicB, 2*r-4, prev_alpha_pow, p1, ctx); } prev_lift_pow = e[1]; n_poly_mod_pow(prev_alpha_pow, alpha, prev_lift_pow, ctx); n_poly_mod_pow(p1, alpha, curr_lift_pow - prev_lift_pow, ctx); _hensel_lift_tree(1, link, v, w, monicB, 2*r-4, prev_alpha_pow, p1, ctx); zas_limit = 2; try_zas: F->length = 0; success = _zassenhaus(zas, zas_limit, F, final_alpha_pow, N, lift_fac, r, B, ctx); if (success) goto cleanup; zas_limit = 3; more: old_nrows = nmod_mat_nrows(N); _lattice(N, lift_fac, r, curr_alpha_pow, starts, B, ctx); if (nmod_mat_nrows(N) < old_nrows && nmod_mat_is_reduced(N)) goto try_zas; next_lift_pow = curr_lift_pow + r; next_lift_pow = FLINT_MIN(next_lift_pow, 2*curr_lift_pow); n_poly_mod_pow(p1, alpha, curr_lift_pow - prev_lift_pow, ctx); _hensel_lift_tree(-1, link, v, w, monicB, 2*r-4, prev_alpha_pow, p1, ctx); n_poly_mod_pow(p1, alpha, next_lift_pow - curr_lift_pow, ctx); n_poly_mod_mul(next_alpha_pow, next_alpha_pow, p1, ctx); n_bpoly_set(monicB, B); n_bpoly_mod_make_monic_mod(monicB, next_alpha_pow, ctx); _hensel_lift_tree(0, link, v, w, monicB, 2*r-4, curr_alpha_pow, p1, ctx); prev_lift_pow = curr_lift_pow; curr_lift_pow = next_lift_pow; n_poly_swap(prev_alpha_pow, curr_alpha_pow); n_poly_swap(curr_alpha_pow, next_alpha_pow); goto more; cleanup: n_poly_clear(final_alpha_pow); n_poly_clear(curr_alpha_pow); n_poly_clear(prev_alpha_pow); n_poly_clear(next_alpha_pow); fq_nmod_poly_clear(Beval, ectx); fq_nmod_poly_factor_clear(local_fac, ectx); fq_nmod_clear(Blc, ectx); n_bpoly_clear(monicB); n_tpoly_clear(tmp); nmod_mat_clear(N); flint_free(starts); flint_free(link); flint_free(lift_fac); n_poly_clear(p1); fq_nmod_ctx_clear(ectx); zassenhaus_prune_clear(zas); return; } flint-3.1.3/src/nmod_mpoly_factor/n_bpoly_mod_factor_smprime.c000066400000000000000000001267421461254215100247100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "nmod_poly_factor.h" #include "fmpz_poly_factor.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" static void n_bpoly_reverse_gens(n_bpoly_t a, const n_bpoly_t b) { slong i, j; n_bpoly_zero(a); for (i = 0; i < b->length; i++) { const n_fq_poly_struct * bi = b->coeffs + i; for (j = 0; j < bi->length; j++) { n_bpoly_set_coeff(a, j, i, bi->coeffs[j]); } } } static void n_bpoly_mod_make_monic_series( n_bpoly_t A, const n_bpoly_t B, slong order, nmod_t ctx) { slong i; n_poly_t lcinv; FLINT_ASSERT(A != B); FLINT_ASSERT(B->length > 0); FLINT_ASSERT(n_bpoly_mod_is_canonical(B, ctx)); n_poly_init(lcinv); n_poly_mod_inv_series(lcinv, B->coeffs + B->length - 1, order, ctx); n_bpoly_fit_length(A, B->length); for (i = 0; i < B->length; i++) n_poly_mod_mullow(A->coeffs + i, B->coeffs + i, lcinv, order, ctx); A->length = B->length; n_bpoly_normalise(A); n_poly_clear(lcinv); } static void _n_bpoly_set_poly_gen0( n_bpoly_t A, const mp_limb_t * Bcoeffs, slong Blength) { slong i; n_bpoly_fit_length(A, Blength); A->length = Blength; for (i = 0; i < Blength; i++) n_poly_set_ui(A->coeffs + i, Bcoeffs[i]); } static void n_bpoly_mod_eval( nmod_poly_t E, const n_bpoly_t A, mp_limb_t alpha, nmod_t ctx) { slong i; n_poly_t alphapow; nmod_poly_zero(E); if (alpha == 0) { for (i = A->length - 1; i >= 0; i--) nmod_poly_set_coeff_ui(E, i, n_poly_get_coeff(A->coeffs + i, 0)); return; } n_poly_init2(alphapow, 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; for (i = A->length - 1; i >= 0; i--) nmod_poly_set_coeff_ui(E, i, n_poly_mod_eval_pow(A->coeffs + i, alphapow, ctx)); n_poly_clear(alphapow); } /****************** lifting **************************************************/ static void _hensel_lift_fac( n_bpoly_t G, n_bpoly_t H, const n_bpoly_t f, n_bpoly_t g, n_bpoly_t h, const n_bpoly_t a, const n_bpoly_t b, slong p0, slong p1, nmod_t ctx) { slong i, j; n_bpoly_t c, t1, t2, q, r; n_bpoly_init(c); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(q); n_bpoly_init(r); n_bpoly_mod_mul(t1, g, h, ctx); n_bpoly_mod_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) { for (j = 0; j < p0; j++) FLINT_ASSERT(n_poly_get_coeff(c->coeffs + i, j) == 0); n_poly_shift_right(c->coeffs + i, c->coeffs + i, p0); n_poly_truncate(c->coeffs + i, p1); } n_bpoly_mod_mul_series(t1, c, b, p1, ctx); n_bpoly_mod_divrem_series(q, r, t1, g, p1, ctx); for (i = 0; i < r->length; i++) n_poly_shift_left(r->coeffs + i, r->coeffs + i, p0); for (i = 0; i < g->length; i++) n_poly_truncate(g->coeffs + i, p0); n_bpoly_mod_add(t1, r, g, ctx); n_bpoly_mod_mul_series(t2, c, a, p1, ctx); n_bpoly_mod_divrem_series(q, r, t2, h, p1, ctx); for (i = 0; i < r->length; i++) n_poly_shift_left(r->coeffs + i, r->coeffs + i, p0); for (i = 0; i < h->length; i++) n_poly_truncate(h->coeffs + i, p0); n_bpoly_mod_add(t2, r, h, ctx); n_bpoly_swap(G, t1); n_bpoly_swap(H, t2); #if FLINT_WANT_ASSERT n_bpoly_mod_mul(t1, G, H, ctx); n_bpoly_mod_sub(c, f, t1, ctx); for (i = 0; i < c->length; i++) for (j = 0; j < p0 + p1; j++) FLINT_ASSERT(n_poly_get_coeff(c->coeffs + i, j) == 0); #endif n_bpoly_clear(c); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(q); n_bpoly_clear(r); } static void _hensel_lift_inv( n_bpoly_t A, n_bpoly_t B, const n_bpoly_t G, const n_bpoly_t H, n_bpoly_t a, n_bpoly_t b, slong p0, slong p1, nmod_t ctx) { slong i, j; n_bpoly_t c, t1, t2, q, r; n_bpoly_init(c); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(q); n_bpoly_init(r); for (i = 0; i < a->length; i++) n_poly_truncate(a->coeffs + i, p0); for (i = 0; i < b->length; i++) n_poly_truncate(b->coeffs + i, p0); n_bpoly_mod_mul(t1, G, a, ctx); n_bpoly_mod_mul(t2, H, b, ctx); n_bpoly_mod_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_poly_mod_neg(c->coeffs + i, c->coeffs + i, ctx); n_poly_mod_add_ui(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) { for (j = 0; j < p0; j++) FLINT_ASSERT(n_poly_get_coeff(c->coeffs + i, j) == 0); n_poly_shift_right(c->coeffs + i, c->coeffs + i, p0); n_poly_truncate(c->coeffs + i, p1); } n_bpoly_mod_mul_series(t1, c, b, p1, ctx); n_bpoly_mod_divrem_series(q, r, t1, G, p1, ctx); for (i = 0; i < r->length; i++) n_poly_shift_left(r->coeffs + i, r->coeffs + i, p0); n_bpoly_mod_add(t1, r, b, ctx); n_bpoly_mod_mul_series(t2, c, a, p1, ctx); n_bpoly_mod_divrem_series(q, r, t2, H, p1, ctx); for (i = 0; i < r->length; i++) n_poly_shift_left(r->coeffs + i, r->coeffs + i, p0); n_bpoly_mod_add(t2, r, a, ctx); n_bpoly_swap(t1, B); n_bpoly_swap(t2, A); #if FLINT_WANT_ASSERT n_bpoly_mod_mul(t1, G, A, ctx); n_bpoly_mod_mul(t2, H, B, ctx); n_bpoly_mod_add(c, t1, t2, ctx); FLINT_ASSERT(c->length > 0); for (i = 0; i < c->length; i++) n_poly_mod_neg(c->coeffs + i, c->coeffs + i, ctx); n_poly_mod_add_ui(c->coeffs + 0, c->coeffs + 0, 1, ctx); n_bpoly_normalise(c); for (i = 0; i < c->length; i++) for (j = 0; j < p0 + p1; j++) FLINT_ASSERT(n_poly_get_coeff(c->coeffs + i, j) == 0); #endif n_bpoly_clear(c); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(q); n_bpoly_clear(r); } static void _hensel_lift_tree( int opt, slong * link, n_bpoly_struct * v, n_bpoly_struct * w, const n_bpoly_t f, slong j, slong p0, slong p1, nmod_t ctx) { FLINT_ASSERT(p1 <= p0); if (j < 0) return; if (opt >= 0) _hensel_lift_fac(v + j, v + j + 1, f, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); if (opt <= 0) _hensel_lift_inv(w + j, w + j + 1, v + j, v + j + 1, w + j, w + j + 1, p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j, link[j], p0, p1, ctx); _hensel_lift_tree(opt, link, v, w, v + j + 1, link[j + 1], p0, p1, ctx); } typedef struct { slong * link; n_bpoly_struct ** lifted_fac; n_tpoly_t tmp; n_bpoly_t bmp; slong r; slong fac_lift_order; slong inv_lift_order; nmod_eval_interp_t E; int Eok; int use_linear; } n_bpoly_mod_lift_struct; typedef n_bpoly_mod_lift_struct n_bpoly_mod_lift_t[1]; static void n_bpoly_mod_lift_init(n_bpoly_mod_lift_t L) { L->link = NULL; L->lifted_fac = NULL; n_tpoly_init(L->tmp); n_bpoly_init(L->bmp); L->r = 0; L->fac_lift_order = 0; L->inv_lift_order = 0; nmod_eval_interp_init(L->E); } static void n_bpoly_mod_lift_clear(n_bpoly_mod_lift_t L) { flint_free(L->link); flint_free(L->lifted_fac); n_tpoly_clear(L->tmp); n_bpoly_clear(L->bmp); nmod_eval_interp_clear(L->E); } static void _n_bpoly_mod_lift_build_tree( n_bpoly_mod_lift_t L, n_bpoly_struct * local_facs, slong r, const n_bpoly_t monicA, nmod_t ctx) { slong i, j; n_bpoly_struct * v, * w; slong e[FLINT_BITS+1]; slong * link; nmod_poly_t d, g, h, a, b; nmod_poly_init_mod(d, ctx); nmod_poly_init_mod(g, ctx); nmod_poly_init_mod(h, ctx); nmod_poly_init_mod(a, ctx); nmod_poly_init_mod(b, ctx); FLINT_ASSERT(r > 1); L->link = (slong *) flint_realloc(L->link, (2*r - 2)*sizeof(slong)); link = L->link; n_tpoly_clear(L->tmp); n_tpoly_init(L->tmp); n_tpoly_fit_length(L->tmp, 2*(2*r - 2)); v = L->tmp->coeffs + 0; w = L->tmp->coeffs + (2*r - 2); for (i = 0; i < r; i++) { n_bpoly_swap(v + i, local_facs + i); link[i] = -i - 1; } for (i = r, j = 0; j < 2*r - 4; i++, j += 2) { slong s, minp, mind; minp = j; mind = n_bpoly_degree0(v + j); for (s = j + 1; s < i; s++) { if (n_bpoly_degree0(v + s) < mind) { minp = s; mind = n_bpoly_degree0(v + s); } } n_bpoly_swap(v + j, v + minp); FLINT_SWAP(slong, link[j], link[minp]); minp = j + 1; mind = n_bpoly_degree0(v + j + 1); for (s = j + 2; s < i; s++) { if (n_bpoly_degree0(v + s) < mind) { minp = s; mind = n_bpoly_degree0(v + s); } } n_bpoly_swap(v + j + 1, v + minp); FLINT_SWAP(slong, link[j + 1], link[minp]); n_bpoly_mod_mul_series(v + i, v + j, v + j + 1, L->fac_lift_order, ctx); link[i] = j; } for (j = 0; j < 2*r - 2; j += 2) { n_bpoly_mod_eval(g, v + j, 0, ctx); n_bpoly_mod_eval(h, v + j + 1, 0, ctx); nmod_poly_xgcd(d, a, b, g, h); if (!nmod_poly_is_one(d)) flint_throw(FLINT_IMPINV, "n_bpoly_mod_lift: bad inverse"); _n_bpoly_set_poly_gen0(w + j, a->coeffs, a->length); _n_bpoly_set_poly_gen0(w + j + 1, b->coeffs, b->length); } nmod_poly_clear(d); nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(a); nmod_poly_clear(b); for (i = 0; i < 2*r - 2; i++) if (-L->link[i] - 1 >= 0) L->lifted_fac[-L->link[i] - 1] = v + i; for (i = 0, e[i] = L->inv_lift_order; e[i] > 1; i++) e[i+1] = (e[i] + 1)/2; e[i] = 1; for (i--; i >= 0; i--) _hensel_lift_tree(-1, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); } static void _n_bpoly_mod_lift_build_steps(n_bpoly_mod_lift_t L, nmod_t ctx) { slong i, j, k; slong r = L->r; slong order = L->fac_lift_order; n_bpoly_struct * A, * Bfinal, * U, * Ue, * Be, * B; n_poly_struct * s, * Binv; n_poly_struct * c, * t; FLINT_ASSERT(L->tmp->alloc >= 4*r + 1); A = L->tmp->coeffs; Bfinal = A + 1; U = Ue = Bfinal + r; B = U + r; Be = B + r; FLINT_ASSERT(L->bmp->alloc >= 2*r + 5); s = L->bmp->coeffs; Binv = s + r; c = Binv + r; t = c + 1; for (k = 0; k < r; k++) { /* s[k] = (prod_{i!=k} B[i].coeffs[0])^-1 (mod B[k].coeffs[0]) */ n_poly_mod_divexact(t, A->coeffs + 0, B[k].coeffs + 0, ctx); if (!n_poly_mod_invmod(s + k, t, B[k].coeffs + 0, ctx)) flint_throw(FLINT_IMPINV, "n_bpoly_mod_lift: bad inverse"); /* set up mul (mod B[k].coeffs[0]) */ n_poly_reverse(t, B[k].coeffs + 0, B[k].coeffs[0].length); n_poly_mod_inv_series(Binv + k, t, B[k].coeffs[0].length, ctx); if (L->Eok) { n_bpoly_fit_length(Be + k, order); for (i = 0; i < order; i++) nmod_eval_interp_from_coeffs_poly(Be[k].coeffs + i, B[k].coeffs + i, L->E, ctx); } } /* U[0], U[r-1] are not used, zero out both U and Ue */ for (k = 1; k < r - 1; k++) { n_bpoly_fit_length(U + k, order); for (i = U[k].length; i < order; i++) U[k].coeffs[i].length = 0; U[k].length = order; } if (r > 2 && L->Eok) { slong len = nmod_eval_interp_eval_length(L->E); for (j = 0; j < order; j++) { k = r - 2; nmod_evals_zero(Ue[k].coeffs + j); for (i = 0; i <= j; i++) nmod_evals_addmul(Ue[k].coeffs + j, Be[k].coeffs + i, Be[k + 1].coeffs + j - i, len, ctx); for (k--; k > 0; k--) { nmod_evals_zero(Ue[k].coeffs + j); for (i = 0; i <= j; i++) nmod_evals_addmul(Ue[k].coeffs + j, Be[k].coeffs + i, Ue[k + 1].coeffs + j - i, len, ctx); } } } else if (r > 2) { for (j = 0; j < order; j++) { k = r - 2; n_poly_zero(U[k].coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { n_poly_mod_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); n_poly_mod_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (k--; k > 0; k--) { n_poly_zero(U[k].coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length) { n_poly_mod_mul(t, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); n_poly_mod_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } } } } } /* linear lifting has large memory requirements wrt r */ static int _use_linear_cutoff(slong r, slong degx) { return r < 30 + 5*FLINT_BIT_COUNT(degx); } /* evaluation has even large memory requirements wrt r */ static int _try_eval_cutoff(slong r, slong degx) { return r < 20 + 2*FLINT_BIT_COUNT(degx); } static void n_bpoly_mod_lift_start( n_bpoly_mod_lift_t L, nmod_poly_struct * local_facs, slong r, const n_bpoly_t monicA, nmod_t ctx) { slong i, k; slong degx = n_bpoly_degree0(monicA); n_bpoly_struct * A, * Bfinal, * U, * Ue, * B; FLINT_ASSERT(r > 1); L->r = r; L->lifted_fac = (n_bpoly_struct **) flint_realloc(L->lifted_fac, r*sizeof(n_bpoly_struct *)); L->fac_lift_order = 1; L->inv_lift_order = 1; L->use_linear = _use_linear_cutoff(r, degx); if (!L->use_linear) { n_bpoly_struct * new_facs = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); for (i = 0; i < r; i++) { n_bpoly_init(new_facs + i); _n_bpoly_set_poly_gen0(new_facs + i, local_facs[i].coeffs, local_facs[i].length); } _n_bpoly_mod_lift_build_tree(L, new_facs, r, monicA, ctx); for (i = 0; i < r; i++) n_bpoly_clear(new_facs + i); flint_free(new_facs); } else { n_tpoly_fit_length(L->tmp, 4*r + 1); A = L->tmp->coeffs; Bfinal = A + 1; U = Ue = Bfinal + r; B = U + r; n_bpoly_fit_length(L->bmp, 2*r + 5); n_bpoly_fit_length(A, 1); A->length = 1; n_poly_one(A->coeffs + 0); for (k = 0; k < r; k++) { n_bpoly_fit_length(B + k, 1); B[k].length = 1; n_poly_set_nmod_poly(B[k].coeffs + 0, local_facs + k); n_poly_mod_mul(A->coeffs + 0, A->coeffs + 0, B[k].coeffs + 0, ctx); L->lifted_fac[k] = Bfinal + k; n_bpoly_reverse_gens(L->lifted_fac[k], B + k); U[k].length = 0; } L->Eok = _try_eval_cutoff(r, degx) && nmod_eval_interp_set_degree_modulus(L->E, degx, ctx); _n_bpoly_mod_lift_build_steps(L, ctx); } } /* assuming N is reduced combine the factors in L according to the rows of N and then replace N by an identity matrix */ void n_bpoly_mod_lift_combine( n_bpoly_mod_lift_t L, nmod_mat_t N, const n_bpoly_t monicA, nmod_t ctx) { slong i, j, k, r, degx; n_bpoly_struct * A, * Bfinal, * U, * Ue, * B; slong oldr = L->r; slong newr = nmod_mat_nrows(N); slong order = L->fac_lift_order; n_bpoly_struct * new_facs; n_bpoly_t T; FLINT_ASSERT(newr > 1); FLINT_ASSERT(newr < oldr); FLINT_ASSERT(oldr == nmod_mat_ncols(N)); FLINT_ASSERT(nmod_mat_is_reduced(N)); /* on input we should have a factorization of monicA mod y^order */ #if FLINT_WANT_ASSERT { n_bpoly_t t1, t2; n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_set(t1, L->lifted_fac[0]); for (k = 1; k < L->r; k++) { n_bpoly_mod_mul_series(t2, t1, L->lifted_fac[k], order, ctx); n_bpoly_swap(t1, t2); } n_bpoly_mod_sub(t2, monicA, t1, ctx); for (i = 0; i < t2->length; i++) for (j = 0; j < order; j++) FLINT_ASSERT(0 == n_poly_get_coeff(t2->coeffs + i, j)); n_bpoly_clear(t1); n_bpoly_clear(t2); } #endif n_bpoly_init(T); new_facs = FLINT_ARRAY_ALLOC(newr, n_bpoly_struct); for (i = 0; i < newr; i++) { n_bpoly_init(new_facs + i); n_bpoly_one(new_facs + i); for (j = 0; j < oldr; j++) { if (nmod_mat_entry(N, i, j) == 0) continue; FLINT_ASSERT(nmod_mat_entry(N, i, j) == 1); n_bpoly_mod_mul_series(T, new_facs + i, L->lifted_fac[j], order, ctx); n_bpoly_swap(new_facs + i, T); } } L->r = r = newr; degx = n_bpoly_degree0(monicA); /* do not use quadratic lifting if we were not already */ L->use_linear = L->use_linear || _use_linear_cutoff(r, degx); if (!L->use_linear) { _n_bpoly_mod_lift_build_tree(L, new_facs, newr, monicA, ctx); for (i = 0; i < newr; i++) n_bpoly_clear(new_facs + i); flint_free(new_facs); n_bpoly_clear(T); } else { if (!L->Eok && r < 20 + 2*FLINT_BIT_COUNT(degx)) L->Eok = nmod_eval_interp_set_degree_modulus(L->E, degx, ctx); A = L->tmp->coeffs; Bfinal = A + 1; n_bpoly_swap(T, A); n_tpoly_clear(L->tmp); n_tpoly_init(L->tmp); n_tpoly_fit_length(L->tmp, 4*r + 1); A = L->tmp->coeffs; n_bpoly_swap(A, T); n_bpoly_clear(T); Bfinal = A + 1; U = Ue = Bfinal + r; B = U + r; n_bpoly_clear(L->bmp); n_bpoly_init(L->bmp); n_bpoly_fit_length(L->bmp, 2*r + 5); for (i = 0; i < newr; i++) { L->lifted_fac[i] = Bfinal + i; n_bpoly_swap(Bfinal + i, new_facs + i); n_bpoly_clear(new_facs + i); } flint_free(new_facs); for (k = 0; k < r; k++) { n_bpoly_reverse_gens(B + k, L->lifted_fac[k]); FLINT_ASSERT(B[k].length <= order); n_bpoly_fit_length(B + k, order); for (i = B[k].length; i < order; i++) n_poly_zero(B[k].coeffs + i); } _n_bpoly_mod_lift_build_steps(L, ctx); } nmod_mat_clear(N); nmod_mat_init(N, L->r, L->r, ctx.n); for (i = 0; i < L->r; i++) nmod_mat_entry(N, i, i) = 1; /* on output we should have a factorization of monicA mod y^order */ #if FLINT_WANT_ASSERT { n_bpoly_t t1, t2; n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_set(t1, L->lifted_fac[0]); for (k = 1; k < L->r; k++) { n_bpoly_mod_mul_series(t2, t1, L->lifted_fac[k], order, ctx); n_bpoly_swap(t1, t2); } n_bpoly_mod_sub(t2, monicA, t1, ctx); for (i = 0; i < t2->length; i++) for (j = 0; j < FLINT_MIN(order, t2->coeffs[i].length); j++) FLINT_ASSERT(0 == t2->coeffs[i].coeffs[j]); n_bpoly_clear(t1); n_bpoly_clear(t2); } #endif } static void n_bpoly_mod_lift_continue( n_bpoly_mod_lift_t L, const n_bpoly_t monicA, slong order, nmod_t ctx) { slong i, j, k; slong r = L->r; n_bpoly_struct * A, * Bfinal, * U, * Ue, * Be, * B; n_poly_struct * s, * Binv; n_poly_struct * c, * t, * ce, * vk, * vek; if (order <= L->fac_lift_order) return; if (!L->use_linear) { n_bpoly_struct * v = L->tmp->coeffs + 0; n_bpoly_struct * w = L->tmp->coeffs + (2*r - 2); slong e[FLINT_BITS+1]; FLINT_ASSERT(1 <= L->inv_lift_order); FLINT_ASSERT(L->fac_lift_order <= 2*L->inv_lift_order); for (i = 0, e[i] = order; e[i] > L->fac_lift_order; i++) e[i+1] = (e[i] + 1)/2; e[i] = L->fac_lift_order; e[i+1] = L->inv_lift_order; if (e[i+1] < e[i]) _hensel_lift_tree(-1, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); for (i--; i > 0; i--) _hensel_lift_tree(0, L->link, v, w, monicA, 2*r-4, e[i+1], e[i]-e[i+1], ctx); _hensel_lift_tree(1, L->link, v, w, monicA, 2*r-4, e[1], e[0]-e[1], ctx); L->fac_lift_order = e[0]; L->inv_lift_order = e[1]; return; } A = L->tmp->coeffs; Bfinal = A + 1; U = Ue = Bfinal + r; B = U + r; Be = B + r; s = L->bmp->coeffs; Binv = s + r; c = Binv + r; t = c + 1; ce = t + 1; vk = ce + 1; vek = vk + 1; /* tack on reversal of monicA */ for (i = 0; i < monicA->length; i++) { n_poly_struct * Bi = monicA->coeffs + i; j = FLINT_MIN(Bi->length, order); for (j--; j >= L->fac_lift_order; j--) n_bpoly_set_coeff(A, j, i, Bi->coeffs[j]); } /* tack on zeros to the B[k] */ for (k = 0; k < r; k++) { n_bpoly_fit_length(B + k, order); if (L->Eok) n_bpoly_fit_length(Be + k, order); for (i = B[k].length; i < order; i++) { n_poly_zero(B[k].coeffs + i); if (L->Eok) nmod_evals_zero(Be[k].coeffs + i); } /* U[0] is not used, zero out both U and Ue */ if (k > 0) { n_bpoly_fit_length(U + k, order); for (i = U[k].length; i < order; i++) U[k].coeffs[i].length = 0; U[k].length = order; } } if (L->Eok && r > 2) { slong len = nmod_eval_interp_eval_length(L->E); for (j = L->fac_lift_order; j < order; j++) { k = r - 2; nmod_evals_zero(Ue[k].coeffs + j); for (i = 0; i <= j; i++) nmod_evals_addmul(Ue[k].coeffs + j, Be[k].coeffs + i, Be[k + 1].coeffs + j - i, len, ctx); for (k--; k > 0; k--) { nmod_evals_zero(Ue[k].coeffs + j); for (i = 0; i <= j; i++) nmod_evals_addmul(Ue[k].coeffs + j, Be[k].coeffs + i, Ue[k + 1].coeffs + j - i, len, ctx); } nmod_evals_zero(ce); for (i = 0; i <= j; i++) nmod_evals_addmul(ce, Be[0].coeffs + i, Ue[1].coeffs + j - i, len, ctx); nmod_eval_interp_to_coeffs_poly(c, ce, L->E, ctx); if (j < A->length) n_poly_mod_sub(c, A->coeffs + j, c, ctx); else n_poly_mod_neg(c, c, ctx); if (n_poly_is_zero(c)) continue; for (k = r - 1; k >= 0; k--) { n_poly_mod_rem(t, c, B[k].coeffs + 0, ctx); n_poly_mod_mulmod_preinv(vk, s + k, t, B[k].coeffs + 0, Binv + k, ctx); nmod_eval_interp_from_coeffs_poly(vek, vk, L->E, ctx); if (!n_poly_is_zero(vk)) { nmod_evals_add_inplace(Be[k].coeffs + j, vek, len, ctx); n_poly_mod_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } /* correct the U's */ if (k > r - 2) { n_poly_swap(ce, vek); } else if (k > 0) { n_poly_struct * p; p = (k == r - 2) ? Be[k + 1].coeffs : Ue[k + 1].coeffs; nmod_evals_fmma(ce, Be[k].coeffs + 0, ce, p, vek, len, ctx); nmod_evals_add_inplace(Ue[k].coeffs + j, ce, len, ctx); } } } } else if (L->Eok) { slong len = nmod_eval_interp_eval_length(L->E); FLINT_ASSERT(r == 2); for (j = L->fac_lift_order; j < order; j++) { nmod_evals_zero(ce); for (i = 0; i <= j; i++) nmod_evals_addmul(ce, Be[0].coeffs + i, Be[1].coeffs + j - i, len, ctx); nmod_eval_interp_to_coeffs_poly(c, ce, L->E, ctx); if (j < A->length) n_poly_mod_sub(c, A->coeffs + j, c, ctx); else n_poly_mod_neg(c, c, ctx); if (n_poly_is_zero(c)) continue; for (k = 0; k < r; k++) { n_poly_mod_rem(t, c, B[k].coeffs + 0, ctx); n_poly_mod_mulmod_preinv(vk, s + k, t, B[k].coeffs + 0, Binv + k, ctx); nmod_eval_interp_from_coeffs_poly(vek, vk, L->E, ctx); if (!n_poly_is_zero(vk)) { nmod_evals_add_inplace(Be[k].coeffs + j, vek, len, ctx); n_poly_mod_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } } } } else if (r > 2) { for (j = L->fac_lift_order; j < order; j++) { k = r - 2; n_poly_zero(U[k].coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { n_poly_mod_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); n_poly_mod_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } for (k--; k > 0; k--) { n_poly_zero(U[k].coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length) { n_poly_mod_mul(t, B[k].coeffs + i, U[k + 1].coeffs + j - i, ctx); n_poly_mod_add(U[k].coeffs + j, U[k].coeffs + j, t, ctx); } } } if (j < A->length) n_poly_set(c, A->coeffs + j); else n_poly_zero(c); for (i = 0; i <= j; i++) { if (i < B[0].length) { n_poly_mod_mul(t, B[0].coeffs + i, U[1].coeffs + j - i, ctx); n_poly_mod_sub(c, c, t, ctx); } } if (n_poly_is_zero(c)) continue; for (k = r - 1; k >= 0; k--) { n_poly_mod_rem(t, c, B[k].coeffs + 0, ctx); n_poly_mod_mulmod_preinv(vk, s + k, t, B[k].coeffs + 0, Binv + k, ctx); if (!n_poly_is_zero(vk)) { n_poly_mod_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } /* correct the U's */ if (k > r - 2) { n_poly_swap(ce, vk); } else if (k > 0) { n_poly_struct * p; n_poly_mod_mul(t, B[k].coeffs + 0, ce, ctx); p = (k == r - 2) ? B[k + 1].coeffs : U[k + 1].coeffs; n_poly_mod_mul(ce, p, vk, ctx); n_poly_mod_add(ce, ce, t, ctx); n_poly_mod_add(U[k].coeffs + j, U[k].coeffs + j, ce, ctx); } } } } else { FLINT_ASSERT(r == 2); for (j = L->fac_lift_order; j < order; j++) { if (j < A->length) n_poly_set(c, A->coeffs + j); else n_poly_zero(c); for (i = FLINT_MIN(j, B[0].length - 1); i >= 0; i--) { n_poly_mod_mul(t, B[0].coeffs + i, B[1].coeffs + j - i, ctx); n_poly_mod_sub(c, c, t, ctx); } if (n_poly_is_zero(c)) continue; for (k = 0; k < r; k++) { n_poly_mod_rem(t, c, B[k].coeffs + 0, ctx); n_poly_mod_mulmod_preinv(vk, s + k, t, B[k].coeffs + 0, Binv + k, ctx); if (!n_poly_is_zero(vk)) { n_poly_mod_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } } } } L->fac_lift_order = order; for (k = 0; k < r; k++) n_bpoly_reverse_gens(Bfinal + k, B + k); #if FLINT_WANT_ASSERT { n_bpoly_t t1, t2; n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_set(t1, Bfinal + 0); for (k = 1; k < r; k++) { n_bpoly_mod_mul_series(t2, t1, Bfinal + k, order, ctx); n_bpoly_swap(t1, t2); } n_bpoly_mod_sub(t2, monicA, t1, ctx); for (i = 0; i < t2->length; i++) { for (j = 0; j < FLINT_MIN(order, t2->coeffs[i].length); j++) { FLINT_ASSERT(0 == t2->coeffs[i].coeffs[j]); } } n_bpoly_clear(t1); n_bpoly_clear(t2); } #endif } /************* lattice reduction ********************************************/ /* The rows of N, if they are 0-1, correspond to combinations of the g that give factors of A. Compute {A/g[i]*g[i]'}_i and use the CLD bounds to try to make N smaller. */ static void _lattice( nmod_mat_t N, n_bpoly_struct * const * g, slong r, slong lift_order, slong * CLD, slong * lattice_order, const n_bpoly_t A, nmod_t ctx) { slong i, j, k; n_bpoly_t Q, R, dg; n_bpoly_struct * ld; nmod_mat_t M, T1, T2; int nlimbs; mp_limb_t * trow; nlimbs = _nmod_vec_dot_bound_limbs(r, ctx); trow = FLINT_ARRAY_ALLOC(r, mp_limb_t); n_bpoly_init(Q); n_bpoly_init(R); n_bpoly_init(dg); ld = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); for (i = 0; i < r; i++) { n_bpoly_init(ld + i); n_bpoly_mod_divrem_series(Q, R, A, g[i], lift_order, ctx); FLINT_ASSERT(R->length == 0); n_bpoly_mod_derivative_gen0(R, g[i], ctx); n_bpoly_mod_mul_series(ld + i, Q, R, lift_order, ctx); } for (k = 0; k + 1 < A->length; k++) { slong nrows = nmod_mat_nrows(N); slong lower = FLINT_MAX(CLD[k], *lattice_order); FLINT_ASSERT(nrows > 0); /* consider powers y^j for which j >= lattice_order (j < lattice_order has already been added) j >= CLD[k] j < lift_order */ if (lift_order <= lower) continue; nmod_mat_init(M, lift_order - lower, nrows, ctx.n); for (j = lower; j < lift_order; j++) { for (i = 0; i < r; i++) trow[i] = n_bpoly_get_coeff(ld + i, k, j); for (i = 0; i < nrows; i++) nmod_mat_entry(M, j - lower, i) = _nmod_vec_dot(trow, N->rows[i], r, ctx, nlimbs); } nmod_mat_init_nullspace_tr(T1, M); nmod_mat_init(T2, nmod_mat_nrows(T1), nmod_mat_ncols(N), ctx.n); nmod_mat_mul(T2, T1, N); nmod_mat_swap(T2, N); nmod_mat_rref(N); nmod_mat_clear(M); nmod_mat_clear(T1); nmod_mat_clear(T2); } flint_free(trow); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(dg); for (i = 0; i < r; i++) n_bpoly_clear(ld + i); flint_free(ld); *lattice_order = lift_order; } /**************** recombination **********************************************/ /* First multiply the g[i] into the gprod[i] according the the rows of N. Then, run zassenhaus on the gprod[i] as factors of A. */ static int _zassenhaus( const zassenhaus_prune_t zas, slong limit, n_tpoly_t F, mp_limb_t malpha, const nmod_mat_t N, n_bpoly_struct * const * g, slong r, slong order, const n_bpoly_t A, nmod_t ctx) { slong total_deg; int success; n_bpoly_t Q, R, t1, t2; n_poly_t cont; slong i, j, k, len, nrows = nmod_mat_nrows(N); slong * subset; n_bpoly_struct * gprod; n_bpoly_struct * f; n_bpoly_t A_copy; int is_simple_check = (limit == 1 && r == nmod_mat_nrows(N)); FLINT_ASSERT(nmod_mat_ncols(N) == r); n_poly_init(cont); n_bpoly_init(Q); n_bpoly_init(R); n_bpoly_init(t1); n_bpoly_init(t2); n_bpoly_init(A_copy); gprod = FLINT_ARRAY_ALLOC(nrows, n_bpoly_struct); subset = FLINT_ARRAY_ALLOC(nrows, slong); for (i = 0; i < nrows; i++) { subset[i] = i; n_bpoly_init(gprod + i); n_bpoly_one(gprod + i); for (j = 0; j < r; j++) { if (nmod_mat_entry(N, i, j) == 0) continue; FLINT_ASSERT(nmod_mat_entry(N, i, j) == 1); n_bpoly_mod_mul_series(t1, gprod + i, g[j], order, ctx); n_bpoly_swap(gprod + i, t1); } } f = (n_bpoly_struct *) A; len = nrows; for (k = 1; k <= len/2; k++) { if (k > limit) { success = 0; goto cleanup; } zassenhaus_subset_first(subset, len, k); while (1) { total_deg = 0; for (i = 0; i < len; i++) { if (subset[i] >= 0) total_deg += gprod[subset[i]].length - 1; } if (!zassenhaus_prune_degree_is_possible(zas, total_deg)) { if (!zassenhaus_subset_next(subset, len)) break; continue; } FLINT_ASSERT(f->length > 0); n_bpoly_set_poly_gen1(t1, f->coeffs + f->length - 1); for (i = 0; i < len; i++) { if (subset[i] >= 0) { n_bpoly_mod_mul_series(t2, t1, gprod + subset[i], order, ctx); n_bpoly_swap(t1, t2); } } n_bpoly_mod_make_primitive(cont, t1, ctx); if (n_bpoly_mod_divides(Q, f, t1, ctx)) { n_bpoly_mod_taylor_shift_gen1(t1, t1, malpha, ctx); n_tpoly_fit_length(F, F->length + 1); n_bpoly_swap(F->coeffs + F->length, t1); F->length++; f = A_copy; n_bpoly_swap(f, Q); len -= k; if (!zassenhaus_subset_next_disjoint(subset, len + k)) break; } else if (is_simple_check) { success = 0; goto cleanup; } else { if (!zassenhaus_subset_next(subset, len)) break; } } } if (f->length > 1) { n_tpoly_fit_length(F, F->length + 1); n_bpoly_mod_taylor_shift_gen1(F->coeffs + F->length, f, malpha, ctx); F->length++; } else { FLINT_ASSERT(f->length == 1); FLINT_ASSERT(n_poly_is_one(f->coeffs + 0)); } success = 1; cleanup: for (i = 0; i < nrows; i++) n_bpoly_clear(gprod + i); flint_free(gprod); flint_free(subset); n_poly_clear(cont); n_bpoly_clear(Q); n_bpoly_clear(R); n_bpoly_clear(t1); n_bpoly_clear(t2); n_bpoly_clear(A_copy); return success; } /*****************************************************************************/ /* x = gen(0), y = gen(1). A is supposed to be separable wrt x. Put the content of A wrt x in c, and the factors in F. Return 1 for success, i.e. a good small prime (y - alpha) was found. If allow_shift is false, only (y - 0) is tried. TODO: copy this precision strategy to the other bpoly factorers The helpers n_bpoly_mod_lift_{start|continue|combine} are used: start: start the lift mod y^0 continue: lift up to mod y^n combine: when the lattice work has proven several factors to be grouped together, combine these and start over with fewer local factors. ex: if N = [1 1 0 1 0], [0 0 1 0 1] then combine the five factors f1,...,f5 into two f1*f2*f4, f3*f5 */ int n_bpoly_mod_factor_smprime( n_poly_t c, /* poly in y */ n_tpoly_t F, n_bpoly_t A, /* clobbered */ int allow_shift, nmod_t ctx) { int success; slong i, r; slong Alenx, Aleny; slong final_order, lift_order, lattice_order; slong * CLD; nmod_poly_t Aeval; mp_limb_t alpha_best, alpha_tmp; nmod_poly_factor_t local_fac_best, local_fac_tmp; int local_fac_tries = 0; n_bpoly_t monicA; nmod_mat_t N; slong zas_limit; zassenhaus_prune_t zas; n_bpoly_mod_lift_t L; n_bpoly_mod_make_primitive(c, A, ctx); Alenx = A->length; FLINT_ASSERT(Alenx > 1); nmod_poly_init_mod(Aeval, ctx); nmod_poly_factor_init(local_fac_best); nmod_poly_factor_init(local_fac_tmp); n_bpoly_init(monicA); nmod_mat_init(N, 0, 0, ctx.n); CLD = FLINT_ARRAY_ALLOC(Alenx, slong); zassenhaus_prune_init(zas); n_bpoly_mod_lift_init(L); Aleny = 0; for (i = 0; i < Alenx; i++) { Aleny = FLINT_MAX(Aleny, A->coeffs[i].length); CLD[i] = A->coeffs[i].length; } mpoly_bivar_cld_bounds(CLD, Alenx); zassenhaus_prune_set_degree(zas, Alenx - 1); alpha_tmp = 0; alpha_best = 0; goto got_alpha; next_alpha: if (!allow_shift || alpha_tmp + 1 >= ctx.n) { if (local_fac_best->num > 0) goto doit; success = 0; goto cleanup; } alpha_tmp++; got_alpha: n_bpoly_mod_eval(Aeval, A, alpha_tmp, ctx); /* if killed leading coeff, get new alpha */ if (Aeval->length != Alenx) goto next_alpha; /* note the constant term of Aeval can be zero */ nmod_poly_factor(local_fac_tmp, Aeval); r = local_fac_tmp->num; zassenhaus_prune_start_add_factors(zas); for (i = 0; i < r; i++) zassenhaus_prune_add_factor(zas, local_fac_tmp->p[i].length - 1, local_fac_tmp->exp[i]); zassenhaus_prune_end_add_factors(zas); if (r < 2 && local_fac_tmp->exp[0] == 1) goto irreducible; if (zassenhaus_prune_must_be_irreducible(zas)) goto irreducible; /* if multiple factors, get new alpha */ for (i = 0; i < r; i++) { FLINT_ASSERT(local_fac_tmp->p[i].length > 1); FLINT_ASSERT(local_fac_tmp->p[i].coeffs[local_fac_tmp->p[i].length - 1] == 1); if (local_fac_tmp->exp[i] != 1) goto next_alpha; } /* done if A is constant in y */ if (Aleny < 2) { n_poly_t mock; n_tpoly_fit_length(F, r); F->length = r; for (i = 0; i < r; i++) { n_poly_mock(mock, local_fac_tmp->p + i); n_bpoly_set_poly_gen0(F->coeffs + i, mock); } success = 1; goto cleanup; } /* alpha_tmp & local_fac_tmp are good; update best */ if (local_fac_best->num < 1 || local_fac_best->num > local_fac_tmp->num) { alpha_best = alpha_tmp; nmod_poly_factor_swap(local_fac_best, local_fac_tmp); } if (++local_fac_tries < 2) goto next_alpha; doit: n_bpoly_mod_taylor_shift_gen1(A, A, alpha_best, ctx); /* local_fac_best is a factorization mod (y - alpha_best) */ r = local_fac_best->num; /* precision for constructing true factors */ final_order = Aleny; /* precision for lifted local factors */ lift_order = Aleny; for (i = 0; i < Alenx - 1; i++) if (CLD[i] > 0 && lift_order > CLD[i]) lift_order = CLD[i]; lift_order = lift_order + 4; /* lift up to y^lift_order */ n_bpoly_mod_make_monic_series(monicA, A, lift_order, ctx); n_bpoly_mod_lift_start(L, local_fac_best->p, r, monicA, ctx); n_bpoly_mod_lift_continue(L, monicA, lift_order, ctx); /* the rows of N give the combinations of local factors */ nmod_mat_clear(N); nmod_mat_init(N, r, r, ctx.n); for (i = 0; i < r; i++) nmod_mat_entry(N, i, i) = 1; /* size limit on subsets in zassenhaus combination */ zas_limit = 1; lattice_order = 0; _lattice(N, L->lifted_fac, L->r, lift_order, CLD, &lattice_order, A, ctx); if (nmod_mat_nrows(N) < 2) goto irreducible_shift; if (!nmod_mat_is_reduced(N)) goto increase; if (nmod_mat_nrows(N) < nmod_mat_ncols(N)/4*3) n_bpoly_mod_lift_combine(L, N, monicA, ctx); try_zas: /* zassenhaus only make sense if N is a nice 0-1 mat */ FLINT_ASSERT(nmod_mat_is_reduced(N)); while (nmod_mat_nrows(N) > 2 && 2*L->fac_lift_order < final_order) { lift_order = 2*L->fac_lift_order; n_bpoly_mod_make_monic_series(monicA, A, lift_order, ctx); n_bpoly_mod_lift_continue(L, monicA, lift_order, ctx); _lattice(N, L->lifted_fac, L->r, lift_order, CLD, &lattice_order, A, ctx); if (nmod_mat_nrows(N) < 2) goto irreducible_shift; if (!nmod_mat_is_reduced(N)) goto increase; if (nmod_mat_nrows(N) < nmod_mat_ncols(N)/4*3) n_bpoly_mod_lift_combine(L, N, monicA, ctx); } if (L->fac_lift_order < final_order) { lift_order = final_order; n_bpoly_mod_make_monic_series(monicA, A, lift_order, ctx); n_bpoly_mod_lift_continue(L, monicA, lift_order, ctx); } /* combine local factors according the rows of N, then by subsets */ F->length = 0; success = _zassenhaus(zas, zas_limit, F, nmod_neg(alpha_best, ctx), N, L->lifted_fac, L->r, final_order, A, ctx); if (success) goto cleanup; /* first attempt failed, try subsets of size 1 or 2 from now on */ zas_limit = 2; more: /* increase precision until N is a nice 0-1 mat */ _lattice(N, L->lifted_fac, L->r, lift_order, CLD, &lattice_order, A, ctx); if (nmod_mat_nrows(N) < 2) goto irreducible_shift; if (!nmod_mat_is_reduced(N)) goto increase; if (nmod_mat_nrows(N) < nmod_mat_ncols(N)/4*3) n_bpoly_mod_lift_combine(L, N, monicA, ctx); goto try_zas; increase: if (lift_order < final_order) lift_order += 4 + lift_order/2; else lift_order += 1 + lift_order/8; n_bpoly_mod_make_monic_series(monicA, A, lift_order, ctx); n_bpoly_mod_lift_continue(L, monicA, lift_order, ctx); goto more; cleanup: n_bpoly_mod_lift_clear(L); flint_free(CLD); nmod_mat_clear(N); nmod_poly_clear(Aeval); nmod_poly_factor_clear(local_fac_best); nmod_poly_factor_clear(local_fac_tmp); n_bpoly_clear(monicA); zassenhaus_prune_clear(zas); return success; irreducible_shift: n_bpoly_mod_taylor_shift_gen1(A, A, nmod_neg(alpha_best, ctx), ctx); irreducible: n_tpoly_fit_length(F, 1); F->length = 1; n_bpoly_swap(F->coeffs + 0, A); success = 1; goto cleanup; } flint-3.1.3/src/nmod_mpoly_factor/n_bpoly_mod_hlift.c000066400000000000000000000543301461254215100227750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" int n_bpoly_mod_hlift2_cubic( n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_t B0, n_bpoly_t B1, mp_limb_t alpha, slong degree_inner, /* required degree in x */ nmod_t ctx, nmod_eval_interp_t E, n_poly_bpoly_stack_t St) { int success; slong len = nmod_eval_interp_eval_length(E); slong i, j; n_poly_struct * c, * s, * t, * u, * v, * ce; n_bpoly_struct * B0e, * B1e; FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx)); FLINT_ASSERT(n_bpoly_mod_is_canonical(B0, ctx)); FLINT_ASSERT(n_bpoly_mod_is_canonical(B1, ctx)); if (A->length < 1 || B0->length < 1 || B1->length < 1) return -1; n_poly_stack_fit_request(St->poly_stack, 6); c = n_poly_stack_take_top(St->poly_stack); s = n_poly_stack_take_top(St->poly_stack); t = n_poly_stack_take_top(St->poly_stack); u = n_poly_stack_take_top(St->poly_stack); v = n_poly_stack_take_top(St->poly_stack); ce = n_poly_stack_take_top(St->poly_stack); n_bpoly_stack_fit_request(St->bpoly_stack, 2); B0e = n_bpoly_stack_take_top(St->bpoly_stack); B1e = n_bpoly_stack_take_top(St->bpoly_stack); n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx); n_bpoly_mod_taylor_shift_gen0(B0, alpha, ctx); n_bpoly_mod_taylor_shift_gen0(B1, alpha, ctx); /* check that A(alpha,x) = B0(alpha,x) * B1(alpha,x) */ #if FLINT_WANT_ASSERT { n_poly_t T; n_poly_init(T); n_poly_mod_mul(T, B0->coeffs + 0, B1->coeffs + 0, ctx); FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T)); n_poly_clear(T); } #endif if (n_poly_degree(A->coeffs + 0) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0)); if (!n_poly_mod_invmod(s, B1->coeffs + 0, B0->coeffs + 0, ctx)) { success = -2; goto cleanup; } n_bpoly_fit_length(B0, A->length); n_bpoly_fit_length(B0e, A->length); for (i = 0; i < B0->length; i++) nmod_eval_interp_from_coeffs_poly(B0e->coeffs + i, B0->coeffs + i, E, ctx); for (i = B0->length; i < A->length; i++) { n_poly_zero(B0->coeffs + i); nmod_evals_zero(B0e->coeffs + i); } n_bpoly_fit_length(B1, A->length); n_bpoly_fit_length(B1e, A->length); for (i = 0; i < B1->length; i++) nmod_eval_interp_from_coeffs_poly(B1e->coeffs + i, B1->coeffs + i, E, ctx); for (i = B1->length; i < A->length; i++) { n_poly_zero(B1->coeffs + i); nmod_evals_zero(B1e->coeffs + i); } for (j = 1; j < A->length; j++) { nmod_evals_zero(ce); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { nmod_evals_addmul(ce, B0e->coeffs + i, B1e->coeffs + j - i, len, ctx); } } nmod_eval_interp_to_coeffs_poly(c, ce, E, ctx); n_poly_mod_sub(c, A->coeffs + j, c, ctx); #if FLINT_WANT_ASSERT { n_poly_t c_check; n_poly_init(c_check); n_poly_set(c_check, A->coeffs + j); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { n_poly_mod_mul(t, B0->coeffs + i, B1->coeffs + j - i, ctx); n_poly_mod_sub(c_check, c_check, t, ctx); } } FLINT_ASSERT(n_poly_equal(c, c_check)); n_poly_clear(c_check); } #endif if (n_poly_is_zero(c)) continue; n_poly_mod_mul(t, s, c, ctx); n_poly_mod_rem(u, t, B0->coeffs + 0, ctx); n_poly_mod_mul(t, u, B1->coeffs + 0, ctx); n_poly_mod_sub(c, c, t, ctx); n_poly_mod_divexact(v, c, B0->coeffs + 0, ctx); if (!n_poly_is_zero(u)) { n_poly_mod_add(B0->coeffs + j, B0->coeffs + j, u, ctx); nmod_eval_interp_from_coeffs_poly(B0e->coeffs + j, B0->coeffs + j, E, ctx); } if (!n_poly_is_zero(v)) { n_poly_mod_add(B1->coeffs + j, B1->coeffs + j, v, ctx); nmod_eval_interp_from_coeffs_poly(B1e->coeffs + j, B1->coeffs + j, E, ctx); } if (!n_poly_is_zero(B0->coeffs + j)) B0->length = FLINT_MAX(B0->length, j + 1); if (!n_poly_is_zero(B1->coeffs + j)) B1->length = FLINT_MAX(B1->length, j + 1); if (B0->length - 1 + B1->length - 1 > A->length - 1) { success = 0; goto cleanup; } } n_bpoly_mod_taylor_shift_gen0(B0, nmod_neg(alpha, ctx), ctx); n_bpoly_mod_taylor_shift_gen0(B1, nmod_neg(alpha, ctx), ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { n_bpoly_t tp1, tp2; n_bpoly_init(tp1); n_bpoly_init(tp2); n_bpoly_mod_taylor_shift_gen0(A, nmod_neg(alpha, ctx), ctx); n_bpoly_mod_mul(tp1, B0, B1, ctx); FLINT_ASSERT(n_bpoly_equal(tp1, A)); n_bpoly_clear(tp1); n_bpoly_clear(tp2); } #endif n_poly_stack_give_back(St->poly_stack, 6); n_bpoly_stack_give_back(St->bpoly_stack, 2); return success; } int n_bpoly_mod_hlift2( n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_t B0, n_bpoly_t B1, mp_limb_t alpha, slong degree_inner, /* required degree in x */ nmod_t ctx, n_poly_bpoly_stack_t St) { int success; slong i, j; n_poly_struct * c, * s, * t, * u, * v; FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx)); FLINT_ASSERT(n_bpoly_mod_is_canonical(B0, ctx)); FLINT_ASSERT(n_bpoly_mod_is_canonical(B1, ctx)); if (A->length < 1 || B0->length < 1 || B1->length < 1) return -1; n_poly_stack_fit_request(St->poly_stack, 5); c = n_poly_stack_take_top(St->poly_stack); s = n_poly_stack_take_top(St->poly_stack); t = n_poly_stack_take_top(St->poly_stack); u = n_poly_stack_take_top(St->poly_stack); v = n_poly_stack_take_top(St->poly_stack); n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx); n_bpoly_mod_taylor_shift_gen0(B0, alpha, ctx); n_bpoly_mod_taylor_shift_gen0(B1, alpha, ctx); /* check that A(alpha,x) = B0(alpha,x) * B1(alpha,x) */ #if FLINT_WANT_ASSERT { n_poly_t T; n_poly_init(T); n_poly_mod_mul(T, B0->coeffs + 0, B1->coeffs + 0, ctx); FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T)); n_poly_clear(T); } #endif if (n_poly_degree(A->coeffs + 0) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0)); if (!n_poly_mod_invmod(s, B1->coeffs + 0, B0->coeffs + 0, ctx)) { success = -2; goto cleanup; } n_bpoly_fit_length(B0, A->length); n_bpoly_fit_length(B1, A->length); for (j = 1; j < A->length; j++) { n_poly_set(c, A->coeffs + j); for (i = 0; i <= j; i++) { if (i < B0->length && j - i < B1->length) { n_poly_mod_mul(t, B0->coeffs + i, B1->coeffs + j - i, ctx); n_poly_mod_sub(c, c, t, ctx); } } if (n_poly_is_zero(c)) continue; n_poly_mod_mul(t, s, c, ctx); n_poly_mod_rem(u, t, B0->coeffs + 0, ctx); n_poly_mod_mul(t, u, B1->coeffs + 0, ctx); n_poly_mod_sub(c, c, t, ctx); n_poly_mod_divexact(v, c, B0->coeffs + 0, ctx); if (j < B0->length) n_poly_mod_add(B0->coeffs + j, B0->coeffs + j, u, ctx); else n_poly_set(B0->coeffs + j, u); if (j < B1->length) n_poly_mod_add(B1->coeffs + j, B1->coeffs + j, v, ctx); else n_poly_set(B1->coeffs + j, v); if (!n_poly_is_zero(B0->coeffs + j)) B0->length = FLINT_MAX(B0->length, j + 1); if (!n_poly_is_zero(B1->coeffs + j)) B1->length = FLINT_MAX(B1->length, j + 1); if (B0->length - 1 + B1->length - 1 > A->length - 1) { success = 0; goto cleanup; } } n_bpoly_mod_taylor_shift_gen0(B0, nmod_neg(alpha, ctx), ctx); n_bpoly_mod_taylor_shift_gen0(B1, nmod_neg(alpha, ctx), ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { n_bpoly_t tp1, tp2; n_bpoly_init(tp1); n_bpoly_init(tp2); n_bpoly_mod_taylor_shift_gen0(A, nmod_neg(alpha, ctx), ctx); n_bpoly_mod_mul(tp1, B0, B1, ctx); FLINT_ASSERT(n_bpoly_equal(tp1, A)); n_bpoly_clear(tp1); n_bpoly_clear(tp2); } #endif n_poly_stack_give_back(St->poly_stack, 5); return success; } int n_bpoly_mod_hlift_cubic( slong r, n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_struct * B, mp_limb_t alpha, slong degree_inner, /* required degree in x */ nmod_t ctx, nmod_eval_interp_t E, n_poly_bpoly_stack_t St) { int success; slong len = nmod_eval_interp_eval_length(E); slong i, j, k, tdeg; n_poly_struct * p, * c, * t, * ce; n_poly_struct ** s, * vk, ** Binv, * vek; n_bpoly_struct ** Ue, ** Be; #if FLINT_WANT_ASSERT n_bpoly_t Acopy; n_bpoly_struct * Bcqt; int successcqt; #endif TMP_INIT; FLINT_ASSERT(r > 2); FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx)); if (A->length < 1) return -1; for (i = 0; i < r; i++) { FLINT_ASSERT(n_bpoly_mod_is_canonical(B + i, ctx)); if (B[i].length < 1) return -1; } TMP_START; #if FLINT_WANT_ASSERT n_bpoly_init(Acopy); n_bpoly_set(Acopy, A); Bcqt = FLINT_ARRAY_ALLOC(r, n_bpoly_struct); for (i = 0; i < r; i++) { n_bpoly_init(Bcqt + i); n_bpoly_set(Bcqt + i, B + i); } successcqt = n_bpoly_mod_hlift(r, Acopy, Bcqt, alpha, degree_inner, ctx, St); #endif n_bpoly_stack_fit_request(St->bpoly_stack, 2*r); Ue = TMP_ARRAY_ALLOC(2*r, n_bpoly_struct *); Be = Ue + r; for (i = 0; i < r; i++) { Ue[i] = n_bpoly_stack_take_top(St->bpoly_stack); Be[i] = n_bpoly_stack_take_top(St->bpoly_stack); } n_poly_stack_fit_request(St->poly_stack, 2*r + 5); s = TMP_ARRAY_ALLOC(2*r, n_poly_struct *); Binv = s + r; for (i = 0; i < r; i++) { s[i] = n_poly_stack_take_top(St->poly_stack); Binv[i] = n_poly_stack_take_top(St->poly_stack); } vk = n_poly_stack_take_top(St->poly_stack); vek = n_poly_stack_take_top(St->poly_stack); c = n_poly_stack_take_top(St->poly_stack); t = n_poly_stack_take_top(St->poly_stack); ce = n_poly_stack_take_top(St->poly_stack); n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx); for (i = 0; i < r; i++) n_bpoly_mod_taylor_shift_gen0(B + i, alpha, ctx); /* check that A(alpha,x) = B0(alpha,x) * B1(alpha,x) * ... */ #if FLINT_WANT_ASSERT { n_poly_t T; n_poly_init(T); n_poly_mod_mul(T, B[0].coeffs + 0, B[1].coeffs + 0, ctx); for (i = 2; i < r; i++) n_poly_mod_mul(T, T, B[i].coeffs + 0, ctx); FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T)); n_poly_clear(T); } #endif /* the required degree in x is supposed to be deg_x(A) */ if (n_poly_degree(A->coeffs + 0) != degree_inner) { success = -1; goto cleanup; } FLINT_ASSERT(n_bpoly_degree1(A) == degree_inner); for (k = 0; k < r; k++) { /* s[k] = (prod_{i!=k} B[i].coeffs[0])^-1 (mod B[k].coeffs[0]) */ n_poly_mod_divexact(t, A->coeffs + 0, B[k].coeffs + 0, ctx); if (!n_poly_mod_invmod(s[k], t, B[k].coeffs + 0, ctx)) { success = -1; goto cleanup; } /* set up mul (mod B[k].coeffs[0]) */ n_poly_reverse(t, B[k].coeffs + 0, B[k].coeffs[0].length); n_poly_mod_inv_series(Binv[k], t, B[k].coeffs[0].length, ctx); /* set up the evaluation of B[k] */ n_bpoly_fit_length(B + k, A->length); n_bpoly_fit_length(Be[k], A->length); for (i = 0; i < B[k].length; i++) nmod_eval_interp_from_coeffs_poly(Be[k]->coeffs + i, B[k].coeffs + i, E, ctx); for (i = B[k].length; i < A->length; i++) { n_poly_zero(B[k].coeffs + i); nmod_evals_zero(Be[k]->coeffs + i); } /* Ue[0] is not used */ if (k > 0) { n_bpoly_fit_length(Ue[k], A->length); Ue[k]->length = A->length; for (i = 0; i < A->length; i++) nmod_evals_zero(Ue[k]->coeffs + i); } } k = r - 2; nmod_evals_mul(Ue[k]->coeffs + 0, Be[k]->coeffs + 0, Be[k + 1]->coeffs + 0, len, ctx); for (k--; k > 0; k--) nmod_evals_mul(Ue[k]->coeffs + 0, Be[k]->coeffs + 0, Ue[k + 1]->coeffs + 0, len, ctx); for (j = 1; j < A->length; j++) { k = r - 2; nmod_evals_zero(Ue[k]->coeffs + j); for (i = 0; i <= j; i++) nmod_evals_addmul(Ue[k]->coeffs + j, Be[k]->coeffs + i, Be[k + 1]->coeffs + j - i, len, ctx); for (k--; k > 0; k--) { nmod_evals_zero(Ue[k]->coeffs + j); for (i = 0; i <= j; i++) nmod_evals_addmul(Ue[k]->coeffs + j, Be[k]->coeffs + i, Ue[k + 1]->coeffs + j - i, len, ctx); } nmod_evals_zero(ce); for (i = 0; i <= j; i++) nmod_evals_addmul(ce, Be[0]->coeffs + i, Ue[1]->coeffs + j - i, len, ctx); nmod_eval_interp_to_coeffs_poly(c, ce, E, ctx); n_poly_mod_sub(c, A->coeffs + j, c, ctx); if (n_poly_is_zero(c)) continue; tdeg = 0; for (k = r - 1; k >= 0; k--) { n_poly_mod_rem(t, c, B[k].coeffs + 0, ctx); n_poly_mod_mulmod_preinv(vk, s[k], t, B[k].coeffs + 0, Binv[k], ctx); nmod_eval_interp_from_coeffs_poly(vek, vk, E, ctx); if (!n_poly_is_zero(vk)) { nmod_evals_add_inplace(Be[k]->coeffs + j, vek, len, ctx); n_poly_mod_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx); if (!n_poly_is_zero(B[k].coeffs + j)) B[k].length = FLINT_MAX(B[k].length, j + 1); } tdeg += B[k].length - 1; /* correct the U's */ if (k > r - 2) { n_poly_swap(ce, vek); } else if (k > 0) { p = (k == r - 2) ? Be[k + 1]->coeffs : Ue[k + 1]->coeffs; nmod_evals_fmma(ce, Be[k]->coeffs + 0, ce, p, vek, len, ctx); nmod_evals_add_inplace(Ue[k]->coeffs + j, ce, len, ctx); } } if (tdeg >= A->length) { success = 0; goto cleanup; } } for (k = 0; k < r; k++) n_bpoly_mod_taylor_shift_gen0(B + k, nmod_neg(alpha, ctx), ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT FLINT_ASSERT(success == successcqt); if (success > 0) { for (i = 0; i < r; i++) FLINT_ASSERT(n_bpoly_equal(Bcqt + i, B + i)); } n_bpoly_clear(Acopy); for (i = 0; i < r; i++) n_bpoly_clear(Bcqt + i); flint_free(Bcqt); #endif n_bpoly_stack_give_back(St->bpoly_stack, 2*r); n_poly_stack_give_back(St->poly_stack, 2*r + 5); TMP_END; return success; } /* y = gen(0), x = gen(1) input A, Bi with A(y,x) = prod_i Bi(y,x) ctx (y-alpha) return -1: the Bi(alpha,x) are not pairwise prime, or A(alpha,x) has wrong degree w.r.t x 0: lift of the Bi to true factors is impossible 1: successfully lifted the Bi to true factors without changing lc_x */ int n_bpoly_mod_hlift( slong r, n_bpoly_t A, /* clobbered (shifted by alpha) */ n_bpoly_struct * B, mp_limb_t alpha, slong degree_inner, /* required degree in x */ nmod_t ctx, n_poly_bpoly_stack_t St) { int success; slong i, j, k, tdeg; n_poly_struct * c, * t, * u; n_poly_struct ** s, ** v, ** Binv; n_bpoly_struct ** U; TMP_INIT; FLINT_ASSERT(r > 2); FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx)); if (A->length < 1) return -1; for (i = 0; i < r; i++) { FLINT_ASSERT(n_bpoly_mod_is_canonical(B + i, ctx)); if (B[i].length < 1) return -1; } TMP_START; n_bpoly_stack_fit_request(St->bpoly_stack, r); U = TMP_ARRAY_ALLOC(r, n_bpoly_struct *); for (i = 0; i < r; i++) { U[i] = n_bpoly_stack_take_top(St->bpoly_stack); n_bpoly_fit_length(U[i], A->length); for (j = 0; j < A->length; j++) n_poly_zero(U[i]->coeffs + j); U[i]->length = A->length; n_bpoly_fit_length(B + i, A->length); } n_poly_stack_fit_request(St->poly_stack, 3*r + 3); s = TMP_ARRAY_ALLOC(3*r, n_poly_struct *); v = s + r; Binv = v + r; for (i = 0; i < r; i++) { s[i] = n_poly_stack_take_top(St->poly_stack); v[i] = n_poly_stack_take_top(St->poly_stack); Binv[i] = n_poly_stack_take_top(St->poly_stack); } c = n_poly_stack_take_top(St->poly_stack); t = n_poly_stack_take_top(St->poly_stack); u = n_poly_stack_take_top(St->poly_stack); n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx); for (i = 0; i < r; i++) n_bpoly_mod_taylor_shift_gen0(B + i, alpha, ctx); /* check that A(alpha,x) = B0(alpha,x) * B1(alpha,x) * ... */ #if FLINT_WANT_ASSERT { n_poly_t T; n_poly_init(T); n_poly_mod_mul(T, B[0].coeffs + 0, B[1].coeffs + 0, ctx); for (i = 2; i < r; i++) n_poly_mod_mul(T, T, B[i].coeffs + 0, ctx); FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T)); n_poly_clear(T); } #endif if (n_poly_degree(A->coeffs + 0) != degree_inner) { success = -1; goto cleanup; } /* the required degree in x is supposed to be deg_x(A) */ FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0)); for (i = 0; i < r; i++) { n_poly_one(t); for (j = 0; j < r; j++) { if (j != i) n_poly_mod_mul(t, t, B[j].coeffs + 0, ctx); } if (!n_poly_mod_invmod(s[i], t, B[i].coeffs + 0, ctx)) { success = -1; goto cleanup; } n_poly_reverse(t, B[i].coeffs + 0, B[i].coeffs[0].length); n_poly_mod_inv_series(Binv[i], t, B[i].coeffs[0].length, ctx); } k = r - 2; n_poly_mod_mul(U[k]->coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx); for (k--; k > 0; k--) n_poly_mod_mul(U[k]->coeffs + 0, B[k].coeffs + 0, U[k + 1]->coeffs + 0, ctx); for (j = 1; j < A->length; j++) { for (k = 0; k < r; k++) n_poly_zero(U[k]->coeffs + j); k = r - 2; n_poly_zero(U[k]->coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length && j - i < B[k + 1].length) { n_poly_mod_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx); n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); } } for (k--; k > 0; k--) { n_poly_zero(U[k]->coeffs + j); for (i = 0; i <= j; i++) { if (i < B[k].length) { n_poly_mod_mul(t, B[k].coeffs + i, U[k + 1]->coeffs + j - i, ctx); n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); } } } n_poly_set(c, A->coeffs + j); for (i = 0; i <= j; i++) { if (i < B[0].length) { n_poly_mod_mul(t, B[0].coeffs + i, U[1]->coeffs + j - i, ctx); n_poly_mod_sub(c, c, t, ctx); } } if (n_poly_is_zero(c)) continue; tdeg = 0; for (i = 0; i < r; i++) { n_poly_mod_rem(t, c, B[i].coeffs + 0, ctx); n_poly_mod_mulmod_preinv(v[i], s[i], t, B[i].coeffs + 0, Binv[i], ctx); while (j >= B[i].length) { n_poly_zero(B[i].coeffs + B[i].length); B[i].length++; } n_poly_mod_add(B[i].coeffs + j, B[i].coeffs + j, v[i], ctx); n_bpoly_normalise(B + i); tdeg += B[i].length - 1; } if (tdeg >= A->length) { success = 0; goto cleanup; } k = r - 2; n_poly_mod_mul(t, B[k].coeffs + 0, v[k + 1], ctx); n_poly_mod_mul(u, B[k + 1].coeffs + 0, v[k], ctx); n_poly_mod_add(t, t, u, ctx); n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); for (k--; k > 0; k--) { n_poly_mod_mul(u, B[k].coeffs + 0, t, ctx); n_poly_mod_mul(t, U[k + 1]->coeffs + 0, v[k], ctx); n_poly_mod_add(t, t, u, ctx); n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx); } } for (i = 0; i < r; i++) n_bpoly_mod_taylor_shift_gen0(B + i, nmod_neg(alpha, ctx), ctx); success = 1; cleanup: #if FLINT_WANT_ASSERT if (success > 0) { n_bpoly_t tp1, tp2; n_bpoly_init(tp1); n_bpoly_init(tp2); n_bpoly_mod_taylor_shift_gen0(A, nmod_neg(alpha, ctx), ctx); n_bpoly_mod_mul(tp1, B + 0, B + 1, ctx); for (i = 2; i < r; i++) { n_bpoly_mod_mul(tp2, tp1, B + i, ctx); n_bpoly_swap(tp1, tp2); } FLINT_ASSERT(n_bpoly_equal(tp1, A)); n_bpoly_clear(tp1); n_bpoly_clear(tp2); } #endif n_bpoly_stack_give_back(St->bpoly_stack, r); n_poly_stack_give_back(St->poly_stack, 3*r + 3); TMP_END; return success; } flint-3.1.3/src/nmod_mpoly_factor/n_bpoly_mod_pfrac.c000066400000000000000000000265641461254215100227720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" int n_bpoly_mod_pfrac2( n_bpoly_t C1, n_bpoly_t C2, slong C1_deg1_bound, slong C2_deg1_bound, n_bpoly_t A, n_bpoly_t B1, n_bpoly_t B2, nmod_t mod) { int success; slong A_deg1, B1_deg1, B2_deg1, C1_deg1, C2_deg1; slong bad_prime_count, bound; mp_limb_t alpha, c; n_poly_t Aevalp, B1evalp, B2evalp, C1evalp, C2evalp; n_poly_t Aevalm, B1evalm, B2evalm, C1evalm, C2evalm; n_poly_t modulus, alphapow, t1, t2; n_bpoly_t T; n_poly_init(Aevalp); n_poly_init(B1evalp); n_poly_init(B2evalp); n_poly_init(C1evalp); n_poly_init(C2evalp); n_poly_init(Aevalm); n_poly_init(B1evalm); n_poly_init(B2evalm); n_poly_init(C1evalm); n_poly_init(C2evalm); n_poly_init(modulus); n_poly_init(alphapow); n_poly_init(t1); n_poly_init(t2); n_bpoly_init(T); A_deg1 = n_bpoly_degree1(A); B1_deg1 = n_bpoly_degree1(B1); B2_deg1 = n_bpoly_degree1(B2); bound = A_deg1; bound = FLINT_MAX(bound, C1_deg1_bound + B2_deg1); bound = FLINT_MAX(bound, B1_deg1 + C2_deg1_bound); bound += 1; bad_prime_count = 0; n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1)); n_poly_one(modulus); if ((mod.n & UWORD(1)) == UWORD(0)) { success = -1; goto cleanup; } alpha = (mod.n - UWORD(1))/UWORD(2); goto choose_prime; bad_prime: if (bad_prime_count > bound) { success = n_poly_degree(modulus) > 0 ? -1 : -2; goto cleanup; } bad_prime_count++; choose_prime: if (alpha < 2) { success = -1; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= mod.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; n_bpoly_mod_interp_reduce_2sm_poly(Aevalp, Aevalm, A, alphapow, mod); n_bpoly_mod_interp_reduce_2sm_poly(B1evalp, B1evalm, B1, alphapow, mod); n_bpoly_mod_interp_reduce_2sm_poly(B2evalp, B2evalm, B2, alphapow, mod); /* make sure evaluation point did not drop the degree of a Bi */ if (n_poly_degree(B1evalp) < n_bpoly_degree0(B1) || n_poly_degree(B1evalm) < n_bpoly_degree0(B1) || n_poly_degree(B2evalp) < n_bpoly_degree0(B2) || n_poly_degree(B2evalm) < n_bpoly_degree0(B2)) { goto choose_prime; } /* image pfrac's */ if (!n_poly_mod_invmod(t1, B2evalp, B1evalp, mod)) goto bad_prime; _n_poly_mod_mul(t2, Aevalp, t1, mod); _n_poly_mod_rem(C1evalp, t2, B1evalp, mod); _n_poly_mod_mul(t2, B2evalp, C1evalp, mod); n_poly_mod_sub(Aevalp, Aevalp, t2, mod); _n_poly_mod_divexact(C2evalp, Aevalp, B1evalp, mod); if (!n_poly_mod_invmod(t1, B2evalm, B1evalm, mod)) goto bad_prime; _n_poly_mod_mul(t2, Aevalm, t1, mod); _n_poly_mod_rem(C1evalm, t2, B1evalm, mod); _n_poly_mod_mul(t2, B2evalm, C1evalm, mod); n_poly_mod_sub(Aevalm, Aevalm, t2, mod); _n_poly_mod_divexact(C2evalm, Aevalm, B1evalm, mod); /* update interpolants */ if (n_poly_degree(modulus) > 0) { c = n_poly_mod_evaluate_nmod(modulus, alpha, mod); FLINT_ASSERT(c == n_poly_mod_evaluate_nmod(modulus, mod.n - alpha, mod)); c = nmod_mul(c, alpha, mod); c = nmod_add(c, c, mod); c = nmod_inv(c, mod); _n_poly_mod_scalar_mul_nmod(modulus, modulus, c, mod); n_bpoly_mod_interp_crt_2sm_poly(&C1_deg1, C1, T, C1evalp, C1evalm, modulus, alphapow, mod); n_bpoly_mod_interp_crt_2sm_poly(&C2_deg1, C2, T, C2evalp, C2evalm, modulus, alphapow, mod); } else { n_bpoly_mod_interp_lift_2sm_poly(&C1_deg1, C1, C1evalp, C1evalm, alpha, mod); n_bpoly_mod_interp_lift_2sm_poly(&C2_deg1, C2, C2evalp, C2evalm, alpha, mod); } c = mod.n - nmod_mul(alpha, alpha, mod); n_poly_mod_shift_left_scalar_addmul(modulus, 2, c, mod); if (C1_deg1 > C1_deg1_bound || C2_deg1 > C2_deg1_bound) { success = 0; goto cleanup; } if (n_poly_degree(modulus) < bound) { goto choose_prime; } success = 1; cleanup: #if FLINT_WANT_ASSERT if (success == 1) { n_bpoly_t T1, T2, T3; n_bpoly_init(T1); n_bpoly_init(T2); n_bpoly_init(T3); n_bpoly_set(T1, A); n_bpoly_mod_mul(T2, C1, B2, mod); n_bpoly_mod_sub(T3, T1, T2, mod); n_bpoly_swap(T1, T3); n_bpoly_mod_mul(T2, C2, B1, mod); n_bpoly_mod_sub(T3, T1, T2, mod); n_bpoly_swap(T1, T3); FLINT_ASSERT(n_bpoly_is_zero(T1)); n_bpoly_clear(T1); n_bpoly_clear(T2); n_bpoly_clear(T3); } #endif n_poly_clear(Aevalp); n_poly_clear(B1evalp); n_poly_clear(B2evalp); n_poly_clear(C1evalp); n_poly_clear(C2evalp); n_poly_clear(Aevalm); n_poly_clear(B1evalm); n_poly_clear(B2evalm); n_poly_clear(C1evalm); n_poly_clear(C2evalm); n_poly_clear(modulus); n_poly_clear(alphapow); n_poly_clear(t1); n_poly_clear(t2); n_bpoly_clear(T); return success; } /* Try to solve A/(B[0]*...*B[r-1]) = C[0]/B[0] + ... + C[r-1]/B[r-1] for the C[i] in Fp[y][x]. return: 1: solution found with deg_y(Ci) <= ldegCibound 0: no solution exists with deg_y(Ci) <= ldegCibound -1: could not find enough evaluation points where the Bi are pariwise prime -2: found no evaluation points where the Bi are pariwise prime */ int n_bpoly_mod_pfrac( slong r, n_bpoly_struct * C, slong * C_deg1_bound, n_bpoly_t A, n_bpoly_struct * B, nmod_t mod) { int success; slong i, j, bad_prime_count, bound; mp_limb_t alpha, c; n_poly_struct Aevalp[1], * Bevalp, * Cevalp; n_poly_struct Aevalm[1], * Bevalm, * Cevalm; n_poly_t modulus, alphapow, t1, t2; n_bpoly_t T; slong * B_deg1, * C_deg1, B_deg1_total, A_deg1; TMP_INIT; if (r < 3) { return n_bpoly_mod_pfrac2(C + 0, C + 1, C_deg1_bound[0], C_deg1_bound[1], A, B + 0, B + 1, mod); } TMP_START; B_deg1 = (slong *) TMP_ALLOC(2*r*sizeof(slong)); C_deg1 = B_deg1 + r; Bevalp = (n_poly_struct *) TMP_ALLOC(4*r*sizeof(n_poly_struct)); Bevalm = Bevalp + r; Cevalp = Bevalm + r; Cevalm = Cevalp + r; n_poly_init(Aevalp); n_poly_init(Aevalm); n_poly_init(modulus); n_poly_init(alphapow); n_poly_init(t1); n_poly_init(t2); for (i = 0; i < r; i++) { n_poly_init(Bevalp + i); n_poly_init(Bevalm + i); n_poly_init(Cevalp + i); n_poly_init(Cevalm + i); } n_bpoly_init(T); A_deg1 = n_bpoly_degree1(A); B_deg1_total = 0; for (i = 0; i < r; i++) { B_deg1[i] = n_bpoly_degree1(B + i); B_deg1_total += B_deg1[i]; } bound = A_deg1; for (i = 0; i < r; i++) bound = FLINT_MAX(bound, C_deg1_bound[i] + B_deg1_total - B_deg1[i]); bound += 1; bad_prime_count = 0; n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1)); n_poly_one(modulus); if ((mod.n & UWORD(1)) == UWORD(0)) { success = -1; goto cleanup; } alpha = (mod.n - UWORD(1))/UWORD(2); goto choose_prime; bad_prime: if (bad_prime_count > 2*bound) { success = n_poly_degree(modulus) > 0 ? -1 : -2; goto cleanup; } bad_prime_count++; choose_prime: if (alpha < 2) { success = -1; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= mod.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; n_bpoly_mod_interp_reduce_2sm_poly(Aevalp, Aevalm, A, alphapow, mod); for (i = 0; i < r; i++) { n_bpoly_mod_interp_reduce_2sm_poly(Bevalp + i, Bevalm + i, B + i, alphapow, mod); if (n_poly_degree(Bevalp + i) < n_bpoly_degree0(B + i) || n_poly_degree(Bevalm + i) < n_bpoly_degree0(B + i)) { goto choose_prime; } } for (i = 0; i < r; i++) { n_poly_one(t2); for (j = 0; j < r; j++) { if (j == i) continue; _n_poly_mod_mul(t1, t2, Bevalp + j, mod); n_poly_swap(t1, t2); } if (!n_poly_mod_invmod(t1, t2, Bevalp + i, mod)) goto bad_prime; _n_poly_mod_mul(t2, Aevalp, t1, mod); _n_poly_mod_rem(Cevalp + i, t2, Bevalp + i, mod); n_poly_one(t2); for (j = 0; j < r; j++) { if (j == i) continue; _n_poly_mod_mul(t1, t2, Bevalm + j, mod); n_poly_swap(t1, t2); } if (!n_poly_mod_invmod(t1, t2, Bevalm + i, mod)) goto bad_prime; _n_poly_mod_mul(t2, Aevalm, t1, mod); _n_poly_mod_rem(Cevalm + i, t2, Bevalm + i, mod); } if (n_poly_degree(modulus) > 0) { c = n_poly_mod_evaluate_nmod(modulus, alpha, mod); FLINT_ASSERT(c == n_poly_mod_evaluate_nmod(modulus, mod.n - alpha, mod)); c = nmod_mul(c, alpha, mod); c = nmod_add(c, c, mod); c = nmod_inv(c, mod); _n_poly_mod_scalar_mul_nmod(modulus, modulus, c, mod); for (i = 0; i < r; i++) { n_bpoly_mod_interp_crt_2sm_poly(C_deg1 + i, C + i, T, Cevalp + i, Cevalm + i, modulus, alphapow, mod); } } else { for (i = 0; i < r; i++) { n_bpoly_mod_interp_lift_2sm_poly(C_deg1 + i, C + i, Cevalp + i, Cevalm + i, alpha, mod); } } c = mod.n - nmod_mul(alpha, alpha, mod); n_poly_mod_shift_left_scalar_addmul(modulus, 2, c, mod); for (i = 0; i < r; i++) { if (C_deg1[i] > C_deg1_bound[i]) { success = 0; goto cleanup; } } if (n_poly_degree(modulus) < bound) { goto choose_prime; } success = 1; cleanup: #if FLINT_WANT_ASSERT if (success == 1) { n_bpoly_t T1, T2, T3; n_bpoly_init(T1); n_bpoly_init(T2); n_bpoly_init(T3); n_bpoly_set(T1, A); for (i = 0; i < j; i++) { n_bpoly_one(T2); for (j = 0; j < r; j++) { n_bpoly_mod_mul(T3, T2, j == i ? C + j : B + j, mod); n_bpoly_swap(T2, T3); } n_bpoly_mod_sub(T3, T1, T2, mod); n_bpoly_swap(T1, T3); } FLINT_ASSERT(n_bpoly_is_zero(T1)); n_bpoly_clear(T1); n_bpoly_clear(T2); n_bpoly_clear(T3); } #endif n_poly_clear(Aevalp); n_poly_clear(Aevalm); n_poly_clear(modulus); n_poly_clear(alphapow); n_poly_clear(t1); n_poly_clear(t2); for (i = 0; i < r; i++) { n_poly_clear(Bevalp + i); n_poly_clear(Bevalm + i); n_poly_clear(Cevalp + i); n_poly_clear(Cevalm + i); } n_bpoly_clear(T); TMP_END; return success; } flint-3.1.3/src/nmod_mpoly_factor/n_poly_vec.c000066400000000000000000000040471461254215100214430ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "nmod_mpoly_factor.h" #if FLINT_WANT_ASSERT # include "ulong_extras.h" #endif slong _n_poly_vec_max_degree(const n_poly_struct * A, slong Alen) { slong i, len = 0; for (i = 0; i < Alen; i++) len = FLINT_MAX(len, A[i].length); return len - 1; } void _n_poly_vec_mul_nmod_intertible( n_poly_struct * A, slong Alen, mp_limb_t c, nmod_t ctx) { slong i; FLINT_ASSERT(n_gcd(c, ctx.n) == 1); if (c == 1) return; for (i = 0; i < Alen; i++) _n_poly_mod_scalar_mul_nmod_inplace(A + i, c, ctx); } void _n_poly_vec_mod_mul_poly( n_poly_struct * A, slong Alen, const n_poly_t g, const nmod_t ctx) { slong i; if (n_poly_is_one(g)) return; for (i = 0; i < Alen; i++) n_poly_mod_mul(A + i, A + i, g, ctx); } void _n_poly_vec_mod_content( n_poly_t g, const n_poly_struct * A, slong Alen, nmod_t ctx) { slong i; n_poly_zero(g); for (i = 0; i < Alen; i++) { n_poly_mod_gcd(g, g, A + i, ctx); if (n_poly_is_one(g)) break; } } void _n_poly_vec_mod_divexact_poly( n_poly_struct * A, slong Alen, const n_poly_t g, nmod_t ctx) { slong i; n_poly_t r; if (n_poly_is_one(g)) return; n_poly_init(r); for (i = 0; i < Alen; i++) { n_poly_mod_divrem(A + i, r, A + i, g, ctx); FLINT_ASSERT(n_poly_is_zero(r)); } n_poly_clear(r); } void _n_poly_vec_mod_remove_content( n_poly_t g, n_poly_struct * A, slong Alen, nmod_t ctx) { _n_poly_vec_mod_content(g, A, Alen, ctx); _n_poly_vec_mod_divexact_poly(A, Alen, g, ctx); } flint-3.1.3/src/nmod_mpoly_factor/nmod_mat_extras.c000066400000000000000000000042211461254215100224640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_mat.h" #include "nmod_mpoly_factor.h" int nmod_mat_is_reduced(const nmod_mat_t N) { slong i, j, k = 0; slong r = nmod_mat_ncols(N); slong d = nmod_mat_nrows(N); for (i = 0; i < d; i++) for (j = 0; j < r; j++) { if (nmod_mat_entry(N, i, j) != 0) { if (nmod_mat_entry(N, i, j) == 1) k++; else return 0; } } return k == r; } void nmod_mat_init_nullspace_tr(nmod_mat_t X, nmod_mat_t tmp) { slong i, j, k, m, n, rank, nullity; slong * p; slong * pivots; slong * nonpivots; m = tmp->r; n = tmp->c; p = flint_malloc(sizeof(slong) * FLINT_MAX(m, n)); rank = nmod_mat_rref(tmp); nullity = n - rank; nmod_mat_init(X, nullity, n, tmp->mod.n); if (rank == 0) { for (i = 0; i < nullity; i++) nmod_mat_entry(X, i, i) = UWORD(1); } else if (nullity) { pivots = p; /* length = rank */ nonpivots = p + rank; /* length = nullity */ for (i = j = k = 0; i < rank; i++) { while (nmod_mat_entry(tmp, i, j) == UWORD(0)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) { mp_limb_t c = nmod_mat_entry(tmp, j, nonpivots[i]); nmod_mat_entry(X, i, pivots[j]) = nmod_neg(c, tmp->mod); } nmod_mat_entry(X, i, nonpivots[i]) = UWORD(1); } } flint_free(p); } flint-3.1.3/src/nmod_mpoly_factor/polyu3_mod_hlift.c000066400000000000000000000600071461254215100225640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" #if FLINT_WANT_ASSERT /* take last variable out of dense storage */ static void n_polyu_set_n_polyun(n_polyu_t A, const n_polyun_t B) { slong i, j; A->length = 0; for (i = 0; i < B->length; i++) { for (j = B->coeffs[i].length - 1; j >= 0; j--) { if (B->coeffs[i].coeffs[j] == 0) continue; n_polyu_fit_length(A, A->length + 1); A->coeffs[A->length] = B->coeffs[i].coeffs[j]; A->exps[A->length] = B->exps[i] + j; A->length++; } } } static void n_polyu_sort_terms(n_polyu_t A) { slong i, j; for (i = 1; i < A->length; i++) for (j = i; j > 0 && A->exps[j - 1] < A->exps[j]; j--) { FLINT_SWAP(mp_limb_t, A->coeffs[j - 1], A->coeffs[j]); FLINT_SWAP(ulong, A->exps[j - 1], A->exps[j]); } return; } int n_polyu_mod_is_canonical(const n_polyu_t A, nmod_t mod) { slong i; if (A->length < 0) return 0; for (i = 0; i < A->length; i++) { if (A->coeffs[i] >= mod.n || A->coeffs[i] <= 0) return 0; if (i > 0 && A->exps[i] >= A->exps[i - 1]) return 0; } return 1; } static void n_polyu_mod_combine_like_terms(n_polyu_t A, nmod_t ctx) { slong in, out; out = -1; for (in = 0; in < A->length; in++) { FLINT_ASSERT(in > out); if (out >= 0 && A->exps[out] == A->exps[in]) { A->coeffs[out] = nmod_add(A->coeffs[out], A->coeffs[in], ctx); } else { if (out < 0 || A->coeffs[out] != 0) out++; if (out != in) { A->exps[out] = A->exps[in]; A->coeffs[out] = A->coeffs[in]; } } } if (out < 0 || A->coeffs[out] != 0) out++; A->length = out; } static int n_polyu_equal(n_polyu_t A, n_polyu_t B) { slong i; if (A->length != B->length) return 0; for (i = 0; i < A->length; i++) { if (A->coeffs[i] != B->coeffs[i]) return 0; if (A->exps[i] != B->exps[i]) return 0; } return 1; } static void n_polyu_mod_mul( n_polyu_t A, const n_polyu_t B, const n_polyu_t C, nmod_t ctx) { slong Ai, Bi, Ci; FLINT_ASSERT(A != B); FLINT_ASSERT(A != C); n_polyu_fit_length(A, B->length*C->length); Ai = 0; for (Bi = 0; Bi < B->length; Bi++) for (Ci = 0; Ci < C->length; Ci++) { A->exps[Ai] = B->exps[Bi] + C->exps[Ci]; A->coeffs[Ai] = nmod_mul(B->coeffs[Bi], C->coeffs[Ci], ctx); Ai++; } A->length = Ai; n_polyu_sort_terms(A); n_polyu_mod_combine_like_terms(A, ctx); } #endif void n_poly_fill_powers( n_poly_t alphapow, slong target, nmod_t mod) { if (target + 1 > alphapow->length) { slong k; slong oldlength = alphapow->length; FLINT_ASSERT(2 <= oldlength); n_poly_fit_length(alphapow, target + 1); for (k = oldlength; k <= target; k++) { alphapow->coeffs[k] = nmod_mul(alphapow->coeffs[k - 1], alphapow->coeffs[1], mod); } alphapow->length = target + 1; } } void n_polyu3_mod_interp_reduce_2sm_bpoly( n_bpoly_t Ap, n_bpoly_t Am, const n_polyu_t A, n_poly_t alpha, nmod_t mod) { slong i; slong cur0, cur1, e0, e1, e2; ulong tp0, tp1, tp2, tm0, tm1, tm2, p1, p0; const mp_limb_t * Acoeffs = A->coeffs; const ulong * Aexps = A->exps; n_bpoly_zero(Ap); n_bpoly_zero(Am); FLINT_ASSERT(A->length > 0); i = 0; cur0 = extract_exp(Aexps[i], 2, 3); cur1 = extract_exp(Aexps[i], 1, 3); e2 = extract_exp(Aexps[i], 0, 3); n_poly_fill_powers(alpha, e2, mod); tp2 = tp1 = tp0 = tm2 = tm1 = tm0 = 0; if (e2 & 1) umul_ppmm(tm1, tm0, alpha->coeffs[e2], Acoeffs[i]); else umul_ppmm(tp1, tp0, alpha->coeffs[e2], Acoeffs[i]); for (i = 1; i < A->length; i++) { e0 = extract_exp(Aexps[i], 2, 3); e1 = extract_exp(Aexps[i], 1, 3); e2 = extract_exp(Aexps[i], 0, 3); FLINT_ASSERT(e0 <= cur0); if (e0 < cur0 || e1 < cur1) { NMOD_RED3(tp0, tp2, tp1, tp0, mod); NMOD_RED3(tm0, tm2, tm1, tm0, mod); n_bpoly_set_coeff(Ap, cur0, cur1, nmod_add(tp0, tm0, mod)); n_bpoly_set_coeff(Am, cur0, cur1, nmod_sub(tp0, tm0, mod)); tp2 = tp1 = tp0 = tm2 = tm1 = tm0 = 0; } else { FLINT_ASSERT(e0 == cur0); FLINT_ASSERT(e1 == cur1); } cur0 = e0; cur1 = e1; n_poly_fill_powers(alpha, e2, mod); FLINT_ASSERT(alpha->coeffs[e2] == nmod_pow_ui(alpha->coeffs[1], e2, mod)); umul_ppmm(p1, p0, alpha->coeffs[e2], Acoeffs[i]); if (e2 & 1) add_sssaaaaaa(tm2, tm1, tm0, tm2, tm1, tm0, 0, p1, p0); else add_sssaaaaaa(tp2, tp1, tp0, tp2, tp1, tp0, 0, p1, p0); } NMOD_RED3(tp0, tp2, tp1, tp0, mod); NMOD_RED3(tm0, tm2, tm1, tm0, mod); n_bpoly_set_coeff(Ap, cur0, cur1, nmod_add(tp0, tm0, mod)); n_bpoly_set_coeff(Am, cur0, cur1, nmod_sub(tp0, tm0, mod)); } /* T(x0, x1, x2) is in F[x2][x0, x1] A(x0, x1) are B(x0, x1) are in F[x0, x1] set T so that T(x0, x1, x2) == A(x0, x1) mod (x2 - alpha) T(x0, x1, x2) == B(x0, x1) mod (x2 + alpha) */ void n_polyu3n_mod_interp_lift_2sm_bpoly( slong * lastdeg, n_polyun_t T, const n_bpoly_t A, const n_bpoly_t B, mp_limb_t alpha, nmod_t mod) { slong lastlength = 0; n_poly_struct * Tcoeffs; ulong * Texps; slong Ti; n_poly_struct * Acoeffs = A->coeffs; slong Ai, ai; n_poly_struct * Bcoeffs = B->coeffs; slong Bi, bi; mp_limb_t u, v, Avalue, Bvalue; mp_limb_t d0, d1; FLINT_ASSERT(2*alpha < mod.n); d0 = (1 + mod.n)/2; d1 = nmod_inv(nmod_add(alpha, alpha, mod), mod); n_polyun_fit_length(T, FLINT_MAX(A->length, B->length)); Tcoeffs = T->coeffs; Texps = T->exps; Ti = 0; Ai = A->length - 1; Bi = B->length - 1; ai = (Ai < 0) ? 0 : n_poly_degree(A->coeffs + Ai); bi = (Bi < 0) ? 0 : n_poly_degree(B->coeffs + Bi); while (Ai >= 0 || Bi >= 0) { if (Ti >= T->alloc) { n_polyun_fit_length(T, Ti + FLINT_MAX(Ai, Bi) + 1); Tcoeffs = T->coeffs; Texps = T->exps; } FLINT_ASSERT(Ai < 0 || Acoeffs[Ai].coeffs[ai] != 0); FLINT_ASSERT(Bi < 0 || Bcoeffs[Bi].coeffs[bi] != 0); Avalue = 0; if (Ai >= 0) { Avalue = Acoeffs[Ai].coeffs[ai]; Texps[Ti] = pack_exp3(Ai, ai, 0); } Bvalue = 0; if (Bi >= 0) { ulong Bexp = pack_exp3(Bi, bi, 0); if (Avalue == 0) { Bvalue = Bcoeffs[Bi].coeffs[bi]; Texps[Ti] = Bexp; } else { if (Texps[Ti] <= Bexp) { Bvalue = Bcoeffs[Bi].coeffs[bi]; } if (Texps[Ti] < Bexp) { Avalue = 0; Texps[Ti] = Bexp; } } } u = nmod_sub(Avalue, Bvalue, mod); v = nmod_add(Avalue, Bvalue, mod); u = nmod_mul(u, d1, mod); v = nmod_mul(v, d0, mod); FLINT_ASSERT(u != 0 || v != 0); n_poly_fit_length(Tcoeffs + Ti, 2); Tcoeffs[Ti].coeffs[0] = v; Tcoeffs[Ti].coeffs[1] = u; Tcoeffs[Ti].length = 1 + (u != 0); lastlength = FLINT_MAX(lastlength, Tcoeffs[Ti].length); Ti++; if (Avalue != 0) { do { ai--; } while (ai >= 0 && Acoeffs[Ai].coeffs[ai] == 0); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_poly_degree(Acoeffs + Ai); } } if (Bvalue != 0) { do { bi--; } while (bi >= 0 && Bcoeffs[Bi].coeffs[bi] == 0); if (bi < 0) { do { Bi--; } while (Bi >= 0 && Bcoeffs[Bi].length == 0); if (Bi >= 0) bi = n_poly_degree(Bcoeffs + Bi); } } } T->length = Ti; FLINT_ASSERT(n_polyun_mod_is_canonical(T, mod)); *lastdeg = lastlength - 1; return; } int n_polyu3n_mod_interp_crt_2sm_bpoly( slong * lastdeg, n_polyun_t F, n_polyun_t T, n_bpoly_t A, n_bpoly_t B, const n_poly_t modulus, n_poly_t alphapow, nmod_t mod) { int changed = 0; slong lastlength = 0; n_poly_t zero; n_poly_struct * Tcoeffs; ulong * Texps; slong Ti; n_poly_struct * Fcoeffs = F->coeffs; ulong * Fexps = F->exps; slong Flen = F->length; slong Fi; n_poly_struct * Acoeffs = A->coeffs; slong Ai, ai; n_poly_struct * Bcoeffs = B->coeffs; slong Bi, bi; n_poly_struct * Fvalue; mp_limb_t u, v, Avalue, Bvalue, FvalueA, FvalueB; int texp_set, cmp; mp_limb_t alpha = alphapow->coeffs[1]; #if FLINT_WANT_ASSERT u = n_poly_mod_evaluate_nmod(modulus, alpha, mod); u = nmod_mul(u, alpha, mod); u = nmod_mul(u, 2, mod); FLINT_ASSERT(u == 1); u = n_poly_mod_evaluate_nmod(modulus, mod.n - alpha, mod); u = nmod_mul(u, alpha, mod); u = nmod_mul(u, 2, mod); FLINT_ASSERT(u == 1); #endif FLINT_ASSERT(n_bpoly_mod_is_canonical(A, mod)); FLINT_ASSERT(n_bpoly_mod_is_canonical(B, mod)); FLINT_ASSERT(n_polyun_mod_is_canonical(F, mod)); n_polyun_fit_length(T, FLINT_MAX(Flen, A->length)); Tcoeffs = T->coeffs; Texps = T->exps; zero->alloc = 0; zero->length = 0; zero->coeffs = NULL; Ti = Fi = 0; Ai = A->length - 1; Bi = B->length - 1; ai = (Ai < 0) ? 0 : n_poly_degree(A->coeffs + Ai); bi = (Bi < 0) ? 0 : n_poly_degree(B->coeffs + Bi); while (Fi < Flen || Ai >= 0 || Bi >= 0) { if (Ti >= T->alloc) { slong extra = Flen - Fi; extra = FLINT_MAX(extra, Ai); extra = FLINT_MAX(extra, Bi); n_polyun_fit_length(T, Ti + extra + 1); Tcoeffs = T->coeffs; Texps = T->exps; } FLINT_ASSERT(Fi >= Flen || Fcoeffs[Fi].length > 0); FLINT_ASSERT(Ai < 0 || Acoeffs[Ai].coeffs[ai] != 0); FLINT_ASSERT(Bi < 0 || Bcoeffs[Bi].coeffs[bi] != 0); Fvalue = zero; texp_set = 0; if (Fi < Flen) { Fvalue = Fcoeffs + Fi; texp_set = 1; Texps[Ti] = Fexps[Fi]; } Avalue = 0; if (Ai >= 0) { ulong Aexp = pack_exp3(Ai, ai, 0); cmp = (!texp_set) ? -1 : Texps[Ti] < Aexp ? -1 : Texps[Ti] > Aexp ? 1 : 0; if (cmp <= 0) { Avalue = Acoeffs[Ai].coeffs[ai]; } if (cmp < 0) { Fvalue = zero; texp_set = 1; Texps[Ti] = Aexp; } } Bvalue = 0; if (Bi >= 0) { ulong Bexp = pack_exp3(Bi, bi, 0); cmp = (!texp_set) ? -1 : Texps[Ti] < Bexp ? -1 : Texps[Ti] > Bexp ? 1 : 0; if (cmp <= 0) { Bvalue = Bcoeffs[Bi].coeffs[bi]; } if (cmp < 0) { Fvalue = zero; Avalue = 0; texp_set = 1; Texps[Ti] = Bexp; } } FLINT_ASSERT(texp_set); n_poly_mod_eval2_pow(&FvalueA, &FvalueB, Fvalue, alphapow, mod); FvalueA = nmod_sub(FvalueA, Avalue, mod); FvalueB = nmod_sub(FvalueB, Bvalue, mod); u = nmod_sub(FvalueB, FvalueA, mod); v = nmod_mul(mod.n - alpha, nmod_add(FvalueB, FvalueA, mod), mod); if (u != 0 || v != 0) { changed = 1; n_poly_mod_addmul_linear(Tcoeffs + Ti, Fvalue, modulus, u, v, mod); } else { FLINT_ASSERT(!n_poly_is_zero(Fvalue)); n_poly_set(Tcoeffs + Ti, Fvalue); } FLINT_ASSERT(Tcoeffs[Ti].length >= Fvalue->length); Fi += (Fvalue != zero); if (Avalue != 0) { do { ai--; } while (ai >= 0 && Acoeffs[Ai].coeffs[ai] == 0); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_poly_degree(Acoeffs + Ai); } } if (Bvalue != 0) { do { bi--; } while (bi >= 0 && Bcoeffs[Bi].coeffs[bi] == 0); if (bi < 0) { do { Bi--; } while (Bi >= 0 && Bcoeffs[Bi].length == 0); if (Bi >= 0) bi = n_poly_degree(Bcoeffs + Bi); } } FLINT_ASSERT(!n_poly_is_zero(Tcoeffs + Ti)); lastlength = FLINT_MAX(lastlength, Tcoeffs[Ti].length); Ti++; } T->length = Ti; if (changed) n_polyun_swap(T, F); FLINT_ASSERT(n_polyun_mod_is_canonical(F, mod)); *lastdeg = lastlength - 1; return changed; } /* Input A, B0, B1, with A(y,x,z) = B0(y,x,z)*B1(y,x,z) mod (y-beta) return -1: suspect that B0(beta,x,z) & B1(beta,x,z) are not pairwise prime, i.e. could not find an eval point for z making them pairwise prime, or A(y,x,z) has wrong degree in x, or could not find enough eval points for z with the required degree in x 0: lift of B0*B1 to true factors is impossible 1: successfully lifted B0*B1 to true factors BB0*BB1 without changing lc_x */ int n_polyu3_mod_hlift2( n_polyun_t BB0, n_polyun_t BB1, n_polyu_t A, n_polyu_t B0, n_polyu_t B1, mp_limb_t beta, slong degree_inner, /* required degree in x */ nmod_t ctx) { int success, Eok; n_polyun_t T; n_bpoly_t Ap, Am, B0p, B0m, B1p, B1m; n_poly_t modulus, alphapow, t1, t2; mp_limb_t alpha, c; slong ldegBB0, ldegBB1; slong Adegy, Adegz, Adegx; slong bad_primes_left; n_poly_bpoly_stack_t St; nmod_eval_interp_t E; FLINT_ASSERT(n_polyu_mod_is_canonical(A, ctx)); FLINT_ASSERT(n_polyu_mod_is_canonical(B0, ctx)); FLINT_ASSERT(n_polyu_mod_is_canonical(B1, ctx)); n_polyun_init(T); n_bpoly_init(Ap); n_bpoly_init(Am); n_bpoly_init(B0p); n_bpoly_init(B0m); n_bpoly_init(B1p); n_bpoly_init(B1m); n_poly_init(modulus); n_poly_init(alphapow); n_poly_init(t1); n_poly_init(t2); n_poly_stack_init(St->poly_stack); n_bpoly_stack_init(St->bpoly_stack); nmod_eval_interp_init(E); Eok = nmod_eval_interp_set_degree_modulus(E, degree_inner, ctx); n_polyu3_degrees(&Adegy, &Adegx, &Adegz, A); if (Adegx != degree_inner) { success = -1; goto cleanup; } n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), Adegz + 2)); n_poly_one(modulus); FLINT_ASSERT((ctx.n & UWORD(1)) == UWORD(1)); alpha = (ctx.n - UWORD(1))/UWORD(2); bad_primes_left = FLINT_MAX(5, Adegz); goto choose_prime; choose_prime: if (alpha < 2) { success = -1; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= ctx.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; n_polyu3_mod_interp_reduce_2sm_bpoly(Ap, Am, A, alphapow, ctx); n_polyu3_mod_interp_reduce_2sm_bpoly(B0p, B0m, B0, alphapow, ctx); n_polyu3_mod_interp_reduce_2sm_bpoly(B1p, B1m, B1, alphapow, ctx); success = Eok ? n_bpoly_mod_hlift2_cubic(Ap, B0p, B1p, beta, degree_inner, ctx, E, St) : n_bpoly_mod_hlift2(Ap, B0p, B1p, beta, degree_inner, ctx, St); if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } success = Eok ? n_bpoly_mod_hlift2_cubic(Am, B0m, B1m, beta, degree_inner, ctx, E, St) : n_bpoly_mod_hlift2(Am, B0m, B1m, beta, degree_inner, ctx, St); if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } if (n_poly_degree(modulus) > 0) { c = n_poly_mod_evaluate_nmod(modulus, alpha, ctx); FLINT_ASSERT(c == n_poly_mod_evaluate_nmod(modulus, ctx.n - alpha, ctx)); c = nmod_mul(c, alpha, ctx); c = nmod_add(c, c, ctx); c = n_invmod(c, ctx.n); _n_poly_mod_scalar_mul_nmod(modulus, modulus, c, ctx); n_polyu3n_mod_interp_crt_2sm_bpoly(&ldegBB0, BB0, T, B0p, B0m, modulus, alphapow, ctx); n_polyu3n_mod_interp_crt_2sm_bpoly(&ldegBB1, BB1, T, B1p, B1m, modulus, alphapow, ctx); } else { n_polyu3n_mod_interp_lift_2sm_bpoly(&ldegBB0, BB0, B0p, B0m, alpha, ctx); n_polyu3n_mod_interp_lift_2sm_bpoly(&ldegBB1, BB1, B1p, B1m, alpha, ctx); } c = ctx.n - nmod_mul(alpha, alpha, ctx); n_poly_mod_shift_left_scalar_addmul(modulus, 2, c, ctx); if (ldegBB0 + ldegBB1 > Adegz) { success = 0; goto cleanup; } if (n_poly_degree(modulus) <= Adegz) { goto choose_prime; } success = 1; cleanup: #if FLINT_WANT_ASSERT if (success == 1) { n_polyu_t T1, T2, T3; n_polyu_init(T1); n_polyu_init(T2); n_polyu_init(T3); n_polyu_set_n_polyun(T2, BB0); n_polyu_set_n_polyun(T3, BB1); n_polyu_mod_mul(T1, T2, T3, ctx); FLINT_ASSERT(n_polyu_equal(A, T1)); n_polyu_clear(T1); n_polyu_clear(T2); n_polyu_clear(T3); } #endif n_polyun_clear(T); n_bpoly_clear(Ap); n_bpoly_clear(Am); n_bpoly_clear(B0p); n_bpoly_clear(B0m); n_bpoly_clear(B1p); n_bpoly_clear(B1m); n_poly_clear(modulus); n_poly_clear(alphapow); n_poly_clear(t1); n_poly_clear(t2); n_poly_stack_clear(St->poly_stack); n_bpoly_stack_clear(St->bpoly_stack); nmod_eval_interp_clear(E); return success; } /* r factor version */ int n_polyu3_mod_hlift( slong r, n_polyun_struct * BB, n_polyu_t A, n_polyu_struct * B, mp_limb_t beta, slong degree_inner, /* required degree in x */ nmod_t ctx) { int success, Eok; slong i, j; n_polyun_t T; n_bpoly_struct * Bp, * Bm; n_bpoly_t Ap, Am; n_poly_t modulus, alphapow, t1, t2; mp_limb_t alpha, c; slong * BBdegZ; slong AdegY, AdegX, AdegZ; slong bad_primes_left; n_poly_bpoly_stack_t St; nmod_eval_interp_t E; if (r < 3) return n_polyu3_mod_hlift2(BB + 0, BB + 1, A, B + 0, B + 1, beta, degree_inner, ctx); FLINT_ASSERT(n_polyu_mod_is_canonical(A, ctx)); for (i = 0; i < r; i++) FLINT_ASSERT(n_polyu_mod_is_canonical(B + i, ctx)); BBdegZ = (slong *) flint_malloc(r*sizeof(slong)); Bp = (n_bpoly_struct *) flint_malloc(r*sizeof(n_bpoly_struct)); Bm = (n_bpoly_struct *) flint_malloc(r*sizeof(n_bpoly_struct)); for (i = 0; i < r; i++) { n_bpoly_init(Bp + i); n_bpoly_init(Bm + i); } n_polyun_init(T); n_bpoly_init(Ap); n_bpoly_init(Am); n_poly_init(modulus); n_poly_init(alphapow); n_poly_init(t1); n_poly_init(t2); n_poly_stack_init(St->poly_stack); n_bpoly_stack_init(St->bpoly_stack); nmod_eval_interp_init(E); Eok = nmod_eval_interp_set_degree_modulus(E, degree_inner, ctx); n_polyu3_degrees(&AdegY, &AdegX, &AdegZ, A); if (AdegX != degree_inner) { success = -1; goto cleanup; } n_poly_fit_length(alphapow, FLINT_MAX(WORD(3), AdegZ + 2)); n_poly_one(modulus); FLINT_ASSERT((ctx.n & UWORD(1)) == UWORD(1)); alpha = (ctx.n - UWORD(1))/UWORD(2); bad_primes_left = FLINT_MAX(5, AdegZ); goto choose_prime; choose_prime: if (alpha < 2) { success = -1; goto cleanup; } alpha--; FLINT_ASSERT(0 < alpha && alpha <= ctx.n/2); FLINT_ASSERT(alphapow->alloc >= 2); alphapow->length = 2; alphapow->coeffs[0] = 1; alphapow->coeffs[1] = alpha; n_polyu3_mod_interp_reduce_2sm_bpoly(Ap, Am, A, alphapow, ctx); for (i = 0; i < r; i++) { n_polyu3_mod_interp_reduce_2sm_bpoly(Bp + i, Bm + i, B + i, alphapow, ctx); } success = Eok ? n_bpoly_mod_hlift_cubic(r, Ap, Bp, beta, degree_inner, ctx, E, St) : n_bpoly_mod_hlift(r, Ap, Bp, beta, degree_inner, ctx, St); if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } success = Eok ? n_bpoly_mod_hlift_cubic(r, Am, Bm, beta, degree_inner, ctx, E, St) : n_bpoly_mod_hlift(r, Am, Bm, beta, degree_inner, ctx, St); if (success < 1) { if (success == 0 || --bad_primes_left < 0) goto cleanup; goto choose_prime; } if (n_poly_degree(modulus) > 0) { c = n_poly_mod_evaluate_nmod(modulus, alpha, ctx); FLINT_ASSERT(c == n_poly_mod_evaluate_nmod(modulus, ctx.n - alpha, ctx)); c = nmod_mul(c, alpha, ctx); c = nmod_add(c, c, ctx); c = nmod_inv(c, ctx); _n_poly_mod_scalar_mul_nmod(modulus, modulus, c, ctx); for (i = 0; i < r; i++) { n_polyu3n_mod_interp_crt_2sm_bpoly(BBdegZ + i, BB + i, T, Bp + i, Bm + i, modulus, alphapow, ctx); } } else { for (i = 0; i < r; i++) { n_polyu3n_mod_interp_lift_2sm_bpoly(BBdegZ + i, BB + i, Bp + i, Bm + i, alpha, ctx); } } c = ctx.n - nmod_mul(alpha, alpha, ctx); n_poly_mod_shift_left_scalar_addmul(modulus, 2, c, ctx); j = BBdegZ[0]; for (i = 1; i < r; i++) j += BBdegZ[i]; if (j > AdegZ) { success = 0; goto cleanup; } if (n_poly_degree(modulus) <= AdegZ) { goto choose_prime; } success = 1; cleanup: #if FLINT_WANT_ASSERT if (success == 1) { n_polyu_t T1, T2, T3; n_polyu_init(T1); n_polyu_init(T2); n_polyu_init(T3); n_polyu_set_n_polyun(T2, BB + 0); n_polyu_set_n_polyun(T3, BB + 1); n_polyu_mod_mul(T1, T2, T3, ctx); for (i = 2; i < r; i++) { n_polyu_set_n_polyun(T3, BB + i); n_polyu_mod_mul(T2, T1, T3, ctx); n_polyu_swap(T2, T1); } FLINT_ASSERT(n_polyu_equal(A, T1)); n_polyu_clear(T1); n_polyu_clear(T2); n_polyu_clear(T3); } #endif n_polyun_clear(T); n_bpoly_clear(Ap); n_bpoly_clear(Am); for (i = 0; i < r; i++) { n_bpoly_clear(Bp + i); n_bpoly_clear(Bm + i); } flint_free(BBdegZ); flint_free(Bp); flint_free(Bm); n_poly_clear(modulus); n_poly_clear(alphapow); n_poly_clear(t1); n_poly_clear(t2); n_poly_stack_clear(St->poly_stack); n_bpoly_stack_clear(St->bpoly_stack); nmod_eval_interp_clear(E); return success; } flint-3.1.3/src/nmod_mpoly_factor/polyun.c000066400000000000000000000050751461254215100206360ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" /* assuming B is bivariate in x and y, put x on the outside, y inside */ void nmod_mpoly_get_polyu1n( n_polyun_t A, const nmod_mpoly_t B, slong varx, slong vary, const nmod_mpoly_ctx_t ctx) { slong j, Ai; ulong Bexpx, Bexpy; slong Boffx, Bshiftx, Boffy, Bshifty; ulong mask = (-UWORD(1)) >> (FLINT_BITS - B->bits); slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); Ai = -1; for (j = 0; j < B->length; j++) { Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask; Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask; if (Ai < 0 || A->exps[Ai] != Bexpx) { Ai++; n_polyun_fit_length(A, Ai + 1); A->exps[Ai] = Bexpx; n_poly_zero(A->coeffs + Ai); } n_poly_set_coeff(A->coeffs + Ai, Bexpy, B->coeffs[j]); if (n_poly_is_zero(A->coeffs + Ai)) Ai--; } A->length = Ai + 1; FLINT_ASSERT(n_polyun_mod_is_canonical(A, ctx->mod)); } void nmod_mpoly_set_polyu1n( nmod_mpoly_t B, const n_polyun_t A, slong varx, slong vary, const nmod_mpoly_ctx_t ctx) { slong i, j; slong Boffx, Bshiftx, Boffy, Bshifty; slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo); mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo); B->length = 0; for (i = 0; i < A->length; i++) { for (j = A->coeffs[i].length - 1; j >= 0; j--) { if (A->coeffs[i].coeffs[j] == 0) continue; nmod_mpoly_fit_length(B, B->length + 1, ctx); mpoly_monomial_zero(B->exps + N*B->length, N); (B->exps + N*B->length)[Boffx] += A->exps[i] << Bshiftx; (B->exps + N*B->length)[Boffy] += j << Bshifty; B->coeffs[B->length] = A->coeffs[i].coeffs[j]; B->length++; } } FLINT_ASSERT(nmod_mpoly_is_canonical(B, ctx)); } flint-3.1.3/src/nmod_mpoly_factor/profile/000077500000000000000000000000001461254215100205755ustar00rootroot00000000000000flint-3.1.3/src/nmod_mpoly_factor/profile/p-factor.c000066400000000000000000007163111461254215100224650ustar00rootroot00000000000000/* Copyright 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "fmpz.h" #include "nmod_mpoly_factor.h" #if defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Woverlength-strings" #endif slong check_omega(slong om, const nmod_mpoly_t p, const char ** vars, const nmod_mpoly_ctx_t ctx) { slong i; nmod_mpoly_factor_t g; nmod_mpoly_t q; fmpz_t omega; timeit_t timer; fmpz_init(omega); nmod_mpoly_factor_init(g, ctx); nmod_mpoly_init(q, ctx); timeit_start(timer); nmod_mpoly_factor(g, p, ctx); timeit_stop(timer); fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, om) < 0) { flint_printf("factorization has wrong number of factors\n"); flint_abort(); } if (!nmod_mpoly_factor_expand(q, g, ctx) || !nmod_mpoly_equal(q, p, ctx)) { flint_printf("factorization does not match\n"); flint_abort(); } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); fmpz_clear(omega); return timer->wall; } int main(int argc, char *argv[]) { slong i, k, time, total_time; flint_printf("\n------ bivariate powers ------\n"); total_time = 0; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, c; const char * vars[] = {"x", "y", "z", "t"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, UWORD(4611686018427388073)); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(c, ctx); for (i = 1; i <= 100; i++) { nmod_mpoly_set_str_pretty(a, "x+1", vars, ctx); nmod_mpoly_set_str_pretty(b, "y+2", vars, ctx); nmod_mpoly_set_str_pretty(c, "1+x+y+z*0+t*0", vars, ctx); nmod_mpoly_pow_ui(c, c, i, ctx); nmod_mpoly_add(a, a, c, ctx); nmod_mpoly_add(b, b, c, ctx); nmod_mpoly_mul(a, a, b, ctx); time = check_omega(2, a, vars, ctx); flint_printf("power %wd: %wd\n", i, time); total_time += time; } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(c, ctx); nmod_mpoly_ctx_clear(ctx); } flint_printf("total_time: %wd\n", total_time); flint_printf("\n------ characteristic 43051 ------\n"); total_time = 0; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a; const char * vars[] = {"x","y","z","u","v","w","s","t"}; nmod_mpoly_ctx_init(ctx, 8, ORD_LEX, 43051); nmod_mpoly_init(a, ctx); flint_printf(" #1: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(13269*y^128+9940*x^2*y^126+38886*y^126+22127*x^4*y^124+7922*x^2*y^124+25434*y^124+26172*x^6*y^122+20019*x^4*y^122+710*x^2*y^122+39701*y^122+30041*x^8*y^120+14420*x^6*y^120+18592*x^4*y^120" "+28677*x^2*y^120+1803*y^120+38458*x^10*y^118+20323*x^8*y^118+8330*x^6*y^118+30874*x^4*y^118+29200*x^2*y^118+29220*y^118+33741*x^12*y^116+35378*x^10*y^116+13296*x^8*y^116+33509*x^6*y^116+15132*x^4*y^116" "+16915*x^2*y^116+36779*y^116+12066*x^14*y^114+35681*x^12*y^114+38852*x^10*y^114+32818*x^8*y^114+34141*x^6*y^114+29281*x^4*y^114+17106*x^2*y^114+3974*y^114+7189*x^16*y^112+38835*x^14*y^112+2669*x^12*y^112" "+13844*x^10*y^112+27827*x^8*y^112+4543*x^6*y^112+22980*x^4*y^112+14802*x^2*y^112+7911*y^112+8742*x^18*y^110+17449*x^16*y^110+17848*x^14*y^110+11408*x^12*y^110+15204*x^10*y^110+38475*x^8*y^110+22477*x^6*y^110" "+10864*x^4*y^110+7567*x^2*y^110+2699*y^110+15389*x^20*y^108+28996*x^18*y^108+33417*x^16*y^108+9037*x^14*y^108+37403*x^12*y^108+14179*x^10*y^108+22500*x^8*y^108+30910*x^6*y^108+6007*x^4*y^108+3533*x^2*y^108" "+13784*y^108+3379*x^22*y^106+9097*x^20*y^106+8875*x^18*y^106+23815*x^16*y^106+26019*x^14*y^106+12197*x^12*y^106+33524*x^10*y^106+26645*x^8*y^106+12525*x^6*y^106+4936*x^4*y^106+16621*x^2*y^106+6518*y^106" "+34806*x^24*y^104+27532*x^22*y^104+15481*x^20*y^104+42694*x^18*y^104+9716*x^16*y^104+1534*x^14*y^104+3364*x^12*y^104+26521*x^10*y^104+8018*x^8*y^104+21019*x^6*y^104+23939*x^4*y^104+37877*x^2*y^104+1982*y^104" "+39670*x^26*y^102+7080*x^24*y^102+38717*x^22*y^102+22559*x^20*y^102+17582*x^18*y^102+10978*x^16*y^102+17609*x^14*y^102+23514*x^12*y^102+7142*x^10*y^102+18372*x^8*y^102+24156*x^6*y^102+31836*x^4*y^102" "+7956*x^2*y^102+5676*y^102+20087*x^28*y^100+42143*x^26*y^100+35489*x^24*y^100+3622*x^22*y^100+12450*x^20*y^100+11884*x^18*y^100+3686*x^16*y^100+8795*x^14*y^100+16044*x^12*y^100+18886*x^10*y^100" "+22394*x^8*y^100+29781*x^6*y^100+12108*x^4*y^100+16344*x^2*y^100+40582*y^100+41751*x^30*y^98+13657*x^28*y^98+38882*x^26*y^98+11472*x^24*y^98+15202*x^22*y^98+22179*x^20*y^98+26651*x^18*y^98+18181*x^16*y^98" "+37427*x^14*y^98+39266*x^12*y^98+41153*x^10*y^98+589*x^8*y^98+41441*x^6*y^98+11572*x^4*y^98+36978*x^2*y^98+34026*y^98+28554*x^32*y^96+3506*x^30*y^96+14744*x^28*y^96+12003*x^26*y^96+5792*x^24*y^96" "+5472*x^22*y^96+9862*x^20*y^96+16472*x^18*y^96+23916*x^16*y^96+37473*x^14*y^96+1570*x^12*y^96+31816*x^10*y^96+1632*x^8*y^96+18727*x^6*y^96+42747*x^4*y^96+39545*x^2*y^96+20847*y^96+23258*x^34*y^94" "+14891*x^32*y^94+22624*x^30*y^94+19054*x^28*y^94+24085*x^26*y^94+1173*x^24*y^94+1725*x^22*y^94+38084*x^20*y^94+9415*x^18*y^94+27090*x^16*y^94+20682*x^14*y^94+35221*x^12*y^94+27233*x^10*y^94+21631*x^8*y^94" "+36526*x^6*y^94+30049*x^4*y^94+37434*x^2*y^94+9317*y^94+4301*x^36*y^92+24353*x^34*y^92+38244*x^32*y^92+40102*x^30*y^92+10779*x^28*y^92+2406*x^26*y^92+29521*x^24*y^92+35520*x^22*y^92+24174*x^20*y^92" "+31341*x^18*y^92+31252*x^16*y^92+36897*x^14*y^92+38817*x^12*y^92+11280*x^10*y^92+11765*x^8*y^92+11426*x^6*y^92+17193*x^4*y^92+5249*x^2*y^92+3786*y^92+2062*x^38*y^90+16466*x^36*y^90+33854*x^34*y^90" "+18164*x^32*y^90+41008*x^30*y^90+8560*x^28*y^90+6013*x^26*y^90+28230*x^24*y^90+30742*x^22*y^90+766*x^20*y^90+4589*x^18*y^90+4721*x^16*y^90+23669*x^14*y^90+42632*x^12*y^90+38975*x^10*y^90+4290*x^8*y^90" "+39169*x^6*y^90+42415*x^4*y^90+39842*x^2*y^90+6303*y^90+28643*x^40*y^88+26752*x^38*y^88+27117*x^36*y^88+19904*x^34*y^88+31532*x^32*y^88+36366*x^30*y^88+17029*x^28*y^88+12013*x^26*y^88+392*x^24*y^88" "+28586*x^22*y^88+10892*x^20*y^88+27171*x^18*y^88+751*x^16*y^88+23150*x^14*y^88+8943*x^12*y^88+16890*x^10*y^88+13828*x^8*y^88+13590*x^6*y^88+30307*x^4*y^88+23580*x^2*y^88+35840*y^88+13720*x^42*y^86" "+4201*x^40*y^86+29883*x^38*y^86+39011*x^36*y^86+16134*x^34*y^86+2827*x^32*y^86+34105*x^30*y^86+18083*x^28*y^86+1128*x^26*y^86+42071*x^24*y^86+8728*x^22*y^86+32551*x^20*y^86+6477*x^18*y^86+35594*x^16*y^86" "+3430*x^14*y^86+34152*x^12*y^86+34763*x^10*y^86+23526*x^8*y^86+36433*x^6*y^86+40790*x^4*y^86+40902*x^2*y^86+1260*y^86+28351*x^44*y^84+35086*x^42*y^84+21750*x^40*y^84+29763*x^38*y^84+23105*x^36*y^84" "+5133*x^34*y^84+25378*x^32*y^84+7204*x^30*y^84+599*x^28*y^84+10893*x^26*y^84+20630*x^24*y^84+38664*x^22*y^84+3311*x^20*y^84+39756*x^18*y^84+29977*x^16*y^84+12988*x^14*y^84+32133*x^12*y^84+7480*x^10*y^84" "+38030*x^8*y^84+24896*x^6*y^84+23322*x^4*y^84+527*x^2*y^84+7194*y^84+14689*x^46*y^82+27358*x^44*y^82+39746*x^42*y^82+41624*x^40*y^82+9843*x^38*y^82+37032*x^36*y^82+34955*x^34*y^82+41680*x^32*y^82" "+38649*x^30*y^82+873*x^28*y^82+19101*x^26*y^82+5510*x^24*y^82+42854*x^22*y^82+29836*x^20*y^82+5166*x^18*y^82+35976*x^16*y^82+41226*x^14*y^82+15451*x^12*y^82+25699*x^10*y^82+36727*x^8*y^82+41747*x^6*y^82" "+15122*x^4*y^82+33256*x^2*y^82+11865*y^82+1261*x^48*y^80+41191*x^46*y^80+23857*x^44*y^80+24554*x^42*y^80+249*x^40*y^80+9784*x^38*y^80+30001*x^36*y^80+5892*x^34*y^80+3102*x^32*y^80+21979*x^30*y^80" "+12432*x^28*y^80+5754*x^26*y^80+35541*x^24*y^80+6519*x^22*y^80+27304*x^20*y^80+15388*x^18*y^80+18735*x^16*y^80+9247*x^14*y^80+38058*x^12*y^80+30223*x^10*y^80+23680*x^8*y^80+10792*x^6*y^80+2037*x^4*y^80" "+31430*x^2*y^80+37487*y^80+40821*x^50*y^78+29556*x^48*y^78+21181*x^46*y^78+433*x^44*y^78+13497*x^42*y^78+16557*x^40*y^78+3344*x^38*y^78+31070*x^36*y^78+7191*x^34*y^78+34074*x^32*y^78+11389*x^30*y^78" "+34808*x^28*y^78+40597*x^26*y^78+18785*x^24*y^78+29152*x^22*y^78+13545*x^20*y^78+15043*x^18*y^78+35323*x^16*y^78+6749*x^14*y^78+10723*x^12*y^78+6215*x^10*y^78+13219*x^8*y^78+2403*x^6*y^78+27159*x^4*y^78" "+6739*x^2*y^78+39482*y^78+24936*x^52*y^76+39579*x^50*y^76+18109*x^48*y^76+9200*x^46*y^76+21917*x^44*y^76+21512*x^42*y^76+3494*x^40*y^76+30316*x^38*y^76+27578*x^36*y^76+16055*x^34*y^76+17444*x^32*y^76" "+30974*x^30*y^76+29826*x^28*y^76+20885*x^26*y^76+6088*x^24*y^76+39051*x^22*y^76+42106*x^20*y^76+633*x^18*y^76+40532*x^16*y^76+9605*x^14*y^76+12151*x^12*y^76+19166*x^10*y^76+32793*x^8*y^76+26505*x^6*y^76" "+17150*x^4*y^76+42179*x^2*y^76+3463*y^76+35354*x^54*y^74+1784*x^52*y^74+39386*x^50*y^74+24457*x^48*y^74+7039*x^46*y^74+5638*x^44*y^74+28496*x^42*y^74+11840*x^40*y^74+8367*x^38*y^74+14337*x^36*y^74" "+41239*x^34*y^74+31896*x^32*y^74+16415*x^30*y^74+4437*x^28*y^74+37810*x^26*y^74+21840*x^24*y^74+30056*x^22*y^74+20859*x^20*y^74+15006*x^18*y^74+12615*x^16*y^74+7097*x^14*y^74+39697*x^12*y^74+15179*x^10*y^74" "+9091*x^8*y^74+24597*x^6*y^74+33813*x^4*y^74+16431*x^2*y^74+39442*y^74+21994*x^56*y^72+23221*x^54*y^72+4777*x^52*y^72+21109*x^50*y^72+29308*x^48*y^72+37585*x^46*y^72+35642*x^44*y^72+33195*x^42*y^72" "+16961*x^40*y^72+5696*x^38*y^72+10891*x^36*y^72+23260*x^34*y^72+21439*x^32*y^72+15920*x^30*y^72+11650*x^28*y^72+17637*x^26*y^72+14778*x^24*y^72+22650*x^22*y^72+40164*x^20*y^72+13178*x^18*y^72+31708*x^16*y^72" "+8834*x^14*y^72+2983*x^12*y^72+39918*x^10*y^72+34849*x^8*y^72+23260*x^6*y^72+40205*x^4*y^72+6976*x^2*y^72+2094*y^72+1146*x^58*y^70+24413*x^56*y^70+12873*x^54*y^70+25581*x^52*y^70+20753*x^50*y^70" "+24596*x^48*y^70+38206*x^46*y^70+35617*x^44*y^70+24374*x^42*y^70+15768*x^40*y^70+1180*x^38*y^70+18543*x^36*y^70+31526*x^34*y^70+18439*x^32*y^70+5449*x^30*y^70+31649*x^28*y^70+6921*x^26*y^70+40896*x^24*y^70" "+17814*x^22*y^70+38174*x^20*y^70+4280*x^18*y^70+10545*x^16*y^70+14409*x^14*y^70+9825*x^12*y^70+11439*x^10*y^70+696*x^8*y^70+9148*x^6*y^70+9556*x^4*y^70+37894*x^2*y^70+28384*y^70+11524*x^60*y^68" "+31287*x^58*y^68+36708*x^56*y^68+8833*x^54*y^68+32388*x^52*y^68+34835*x^50*y^68+24759*x^48*y^68+19158*x^46*y^68+37727*x^44*y^68+17225*x^42*y^68+22448*x^40*y^68+29257*x^38*y^68+3050*x^36*y^68+26991*x^34*y^68" "+42260*x^32*y^68+28008*x^30*y^68+19951*x^28*y^68+10241*x^26*y^68+4701*x^24*y^68+42846*x^22*y^68+32709*x^20*y^68+24142*x^18*y^68+17844*x^16*y^68+33978*x^14*y^68+24093*x^12*y^68+7345*x^10*y^68+24056*x^8*y^68" "+1137*x^6*y^68+24621*x^4*y^68+20000*x^2*y^68+8368*y^68+19698*x^62*y^66+17428*x^60*y^66+18656*x^58*y^66+12098*x^56*y^66+33898*x^54*y^66+36282*x^52*y^66+3982*x^50*y^66+34954*x^48*y^66+25276*x^46*y^66" "+7124*x^44*y^66+2548*x^42*y^66+34243*x^40*y^66+33396*x^38*y^66+1802*x^36*y^66+20924*x^34*y^66+22330*x^32*y^66+37722*x^30*y^66+27253*x^28*y^66+20318*x^26*y^66+6915*x^24*y^66+29259*x^22*y^66+40765*x^20*y^66" "+40850*x^18*y^66+6350*x^16*y^66+14602*x^14*y^66+16563*x^12*y^66+28333*x^10*y^66+37615*x^8*y^66+34203*x^6*y^66+15083*x^4*y^66+29973*x^2*y^66+11182*y^66+16668*x^64*y^64+17076*x^62*y^64+23108*x^60*y^64" "+16076*x^58*y^64+21715*x^56*y^64+42365*x^54*y^64+14679*x^52*y^64+2435*x^50*y^64+4323*x^48*y^64+24661*x^46*y^64+5920*x^44*y^64+30586*x^42*y^64+29527*x^40*y^64+9929*x^38*y^64+40914*x^36*y^64+10823*x^34*y^64" "+28152*x^32*y^64+33222*x^30*y^64+33030*x^28*y^64+21067*x^26*y^64+29242*x^24*y^64+24720*x^22*y^64+33707*x^20*y^64+21129*x^18*y^64+6904*x^16*y^64+25010*x^14*y^64+18601*x^12*y^64+15843*x^10*y^64+4486*x^8*y^64" "+30374*x^6*y^64+22083*x^4*y^64+31695*x^2*y^64+22493*y^64+12276*x^66*y^62+24005*x^64*y^62+1458*x^62*y^62+32140*x^60*y^62+30310*x^58*y^62+6565*x^56*y^62+42796*x^54*y^62+30875*x^52*y^62+9859*x^50*y^62" "+5671*x^48*y^62+41619*x^46*y^62+16726*x^44*y^62+14558*x^42*y^62+38081*x^40*y^62+39519*x^38*y^62+23184*x^36*y^62+7717*x^34*y^62+36359*x^32*y^62+13753*x^30*y^62+15058*x^28*y^62+17577*x^26*y^62+7552*x^24*y^62" "+40018*x^22*y^62+18031*x^20*y^62+1277*x^18*y^62+19526*x^16*y^62+14797*x^14*y^62+17118*x^12*y^62+22507*x^10*y^62+32407*x^8*y^62+4565*x^6*y^62+3746*x^4*y^62+41973*x^2*y^62+38408*y^62+41341*x^68*y^60" "+15439*x^66*y^60+38824*x^64*y^60+29213*x^62*y^60+22553*x^60*y^60+35030*x^58*y^60+5673*x^56*y^60+3965*x^54*y^60+23647*x^52*y^60+15672*x^50*y^60+23949*x^48*y^60+37541*x^46*y^60+34126*x^44*y^60+35653*x^42*y^60" "+30103*x^40*y^60+3398*x^38*y^60+21058*x^36*y^60+4178*x^34*y^60+36146*x^32*y^60+7207*x^30*y^60+12375*x^28*y^60+2010*x^26*y^60+1614*x^24*y^60+6990*x^22*y^60+39480*x^20*y^60+5586*x^18*y^60+24150*x^16*y^60" "+20509*x^14*y^60+23325*x^12*y^60+37591*x^10*y^60+18376*x^8*y^60+135*x^6*y^60+38976*x^4*y^60+2479*x^2*y^60+5132*y^60+35081*x^70*y^58+10055*x^68*y^58+31883*x^66*y^58+23638*x^64*y^58+111*x^62*y^58" "+36014*x^60*y^58+14815*x^58*y^58+32603*x^56*y^58+14793*x^54*y^58+15900*x^52*y^58+8066*x^50*y^58+9231*x^48*y^58+1433*x^46*y^58+8801*x^44*y^58+34927*x^42*y^58+12648*x^40*y^58+17794*x^38*y^58+4717*x^36*y^58" "+22750*x^34*y^58+39069*x^32*y^58+32550*x^30*y^58+12566*x^28*y^58+28916*x^26*y^58+3222*x^24*y^58+18972*x^22*y^58+16638*x^20*y^58+10451*x^18*y^58+33459*x^16*y^58+20790*x^14*y^58+25238*x^12*y^58+21942*x^10*y^58" "+25742*x^8*y^58+38731*x^6*y^58+6279*x^4*y^58+33448*x^2*y^58+40665*y^58+1992*x^72*y^56+22602*x^70*y^56+43019*x^68*y^56+38997*x^66*y^56+11795*x^64*y^56+6799*x^62*y^56+21300*x^60*y^56+4250*x^58*y^56" "+1391*x^56*y^56+35236*x^54*y^56+13580*x^52*y^56+32097*x^50*y^56+9259*x^48*y^56+5648*x^46*y^56+25912*x^44*y^56+26802*x^42*y^56+3076*x^40*y^56+1568*x^38*y^56+14097*x^36*y^56+6182*x^34*y^56+42121*x^32*y^56" "+33024*x^30*y^56+31955*x^28*y^56+6931*x^26*y^56+7828*x^24*y^56+15697*x^22*y^56+40832*x^20*y^56+18829*x^18*y^56+22533*x^16*y^56+40039*x^14*y^56+20856*x^12*y^56+7369*x^10*y^56+38738*x^8*y^56+16962*x^6*y^56" "+6555*x^4*y^56+6155*x^2*y^56+17337*y^56+25063*x^74*y^54+7849*x^72*y^54+3993*x^70*y^54+33525*x^68*y^54+35796*x^66*y^54+27258*x^64*y^54+32803*x^62*y^54+21301*x^60*y^54+16149*x^58*y^54+14072*x^56*y^54" "+32225*x^54*y^54+42102*x^52*y^54+21056*x^50*y^54+21135*x^48*y^54+21510*x^46*y^54+21638*x^44*y^54+1767*x^42*y^54+40617*x^40*y^54+12037*x^38*y^54+7724*x^36*y^54+13452*x^34*y^54+17124*x^32*y^54+10586*x^30*y^54" "+12990*x^28*y^54+14528*x^26*y^54+40503*x^24*y^54+17442*x^22*y^54+30693*x^20*y^54+29523*x^18*y^54+5902*x^16*y^54+41843*x^14*y^54+27627*x^12*y^54+16147*x^10*y^54+13582*x^8*y^54+27791*x^6*y^54+27196*x^4*y^54" "+24489*x^2*y^54+16314*y^54+38813*x^76*y^52+37642*x^74*y^52+997*x^72*y^52+8437*x^70*y^52+28275*x^68*y^52+37920*x^66*y^52+39022*x^64*y^52+21600*x^62*y^52+28446*x^60*y^52+12594*x^58*y^52+30021*x^56*y^52" "+963*x^54*y^52+27416*x^52*y^52+22971*x^50*y^52+461*x^48*y^52+11039*x^46*y^52+17409*x^44*y^52+6722*x^42*y^52+12652*x^40*y^52+24340*x^38*y^52+26213*x^36*y^52+18368*x^34*y^52+15457*x^32*y^52+42555*x^30*y^52" "+13509*x^28*y^52+5437*x^26*y^52+432*x^24*y^52+25772*x^22*y^52+26984*x^20*y^52+26485*x^18*y^52+12322*x^16*y^52+16373*x^14*y^52+27311*x^12*y^52+1147*x^10*y^52+7118*x^8*y^52+24230*x^6*y^52+29138*x^4*y^52" "+7764*x^2*y^52+12887*y^52+36780*x^78*y^50+32809*x^76*y^50+35028*x^74*y^50+34763*x^72*y^50+2179*x^70*y^50+21534*x^68*y^50+8824*x^66*y^50+15959*x^64*y^50+40301*x^62*y^50+13376*x^60*y^50+30565*x^58*y^50" "+31475*x^56*y^50+30495*x^54*y^50+16418*x^52*y^50+5053*x^50*y^50+26234*x^48*y^50+12901*x^46*y^50+29730*x^44*y^50+40763*x^42*y^50+42343*x^40*y^50+42509*x^38*y^50+35211*x^36*y^50+41383*x^34*y^50+4838*x^32*y^50" "+17793*x^30*y^50+16851*x^28*y^50+2502*x^26*y^50+27544*x^24*y^50+25660*x^22*y^50+30680*x^20*y^50+2403*x^18*y^50+2899*x^16*y^50+3400*x^14*y^50+11532*x^12*y^50+22755*x^10*y^50+9158*x^8*y^50+34876*x^6*y^50" "+18182*x^4*y^50+6935*x^2*y^50+30723*y^50+41480*x^80*y^48+18665*x^78*y^48+22404*x^76*y^48+39684*x^74*y^48+42481*x^72*y^48+40986*x^70*y^48+9440*x^68*y^48+5311*x^66*y^48+38442*x^64*y^48+26692*x^62*y^48" "+7739*x^60*y^48+36291*x^58*y^48+11040*x^56*y^48+15778*x^54*y^48+3419*x^52*y^48+7692*x^50*y^48+22548*x^48*y^48+3458*x^46*y^48+22218*x^44*y^48+8138*x^42*y^48+29129*x^40*y^48+37396*x^38*y^48+41999*x^36*y^48" "+22450*x^34*y^48+35776*x^32*y^48+16663*x^30*y^48+30596*x^28*y^48+5572*x^26*y^48+11292*x^24*y^48+22640*x^22*y^48+3895*x^20*y^48+23764*x^18*y^48+5658*x^16*y^48+1770*x^14*y^48+14594*x^12*y^48+35696*x^10*y^48" "+28740*x^8*y^48+39807*x^6*y^48+21201*x^4*y^48+32788*x^2*y^48+467*y^48+28277*x^82*y^46+21388*x^80*y^46+29022*x^78*y^46+10823*x^76*y^46+16670*x^74*y^46+18291*x^72*y^46+30573*x^70*y^46+27194*x^68*y^46" "+36056*x^66*y^46+8701*x^64*y^46+21702*x^62*y^46+1608*x^60*y^46+1153*x^58*y^46+32066*x^56*y^46+5275*x^54*y^46+26654*x^52*y^46+40862*x^50*y^46+11931*x^48*y^46+40390*x^46*y^46+39493*x^44*y^46+13443*x^42*y^46" "+40146*x^40*y^46+33850*x^38*y^46+11769*x^36*y^46+16720*x^34*y^46+38288*x^32*y^46+31694*x^30*y^46+6762*x^28*y^46+20344*x^26*y^46+39827*x^24*y^46+7122*x^22*y^46+24426*x^20*y^46+22137*x^18*y^46+20010*x^16*y^46" "+6158*x^14*y^46+42761*x^12*y^46+34882*x^10*y^46+21773*x^8*y^46+4728*x^6*y^46+23276*x^4*y^46+13858*x^2*y^46+19550*y^46+18042*x^84*y^44+18424*x^82*y^44+30517*x^80*y^44+27229*x^78*y^44+10937*x^76*y^44" "+18269*x^74*y^44+12745*x^72*y^44+23122*x^70*y^44+15015*x^68*y^44+22397*x^66*y^44+33999*x^64*y^44+38038*x^62*y^44+28303*x^60*y^44+10625*x^58*y^44+18795*x^56*y^44+39147*x^54*y^44+14803*x^52*y^44+34315*x^50*y^44" "+27419*x^48*y^44+15314*x^46*y^44+36436*x^44*y^44+3411*x^42*y^44+28836*x^40*y^44+12758*x^38*y^44+31308*x^36*y^44+34208*x^34*y^44+12621*x^32*y^44+1299*x^30*y^44+39496*x^28*y^44+35319*x^26*y^44+16066*x^24*y^44" "+1968*x^22*y^44+17711*x^20*y^44+24536*x^18*y^44+24805*x^16*y^44+563*x^14*y^44+22542*x^12*y^44+6718*x^10*y^44+16265*x^8*y^44+2024*x^6*y^44+24659*x^4*y^44+19696*x^2*y^44+4535*y^44+10504*x^86*y^42" "+37860*x^84*y^42+32406*x^82*y^42+14292*x^80*y^42+12380*x^78*y^42+15078*x^76*y^42+9167*x^74*y^42+38278*x^72*y^42+3597*x^70*y^42+38756*x^68*y^42+36343*x^66*y^42+24110*x^64*y^42+19712*x^62*y^42+17022*x^60*y^42" "+18779*x^58*y^42+18561*x^56*y^42+32615*x^54*y^42+14108*x^52*y^42+31567*x^50*y^42+9235*x^48*y^42+8428*x^46*y^42+17151*x^44*y^42+14630*x^42*y^42+31408*x^40*y^42+15386*x^38*y^42+26901*x^36*y^42+19188*x^34*y^42" "+35660*x^32*y^42+18112*x^30*y^42+9989*x^28*y^42+42510*x^26*y^42+4515*x^24*y^42+16339*x^22*y^42+24628*x^20*y^42+41504*x^18*y^42+42523*x^16*y^42+18954*x^14*y^42+18903*x^12*y^42+36965*x^10*y^42+9151*x^8*y^42" "+38003*x^6*y^42+40263*x^4*y^42+24391*x^2*y^42+14740*y^42+31188*x^88*y^40+21316*x^86*y^40+27934*x^84*y^40+31960*x^82*y^40+778*x^80*y^40+21473*x^78*y^40+20012*x^76*y^40+28203*x^74*y^40+31068*x^72*y^40" "+19311*x^70*y^40+33559*x^68*y^40+19931*x^66*y^40+16403*x^64*y^40+3283*x^62*y^40+11978*x^60*y^40+35948*x^58*y^40+17011*x^56*y^40+16383*x^54*y^40+27811*x^52*y^40+2656*x^50*y^40+31268*x^48*y^40+33075*x^46*y^40" "+24069*x^44*y^40+24003*x^42*y^40+9713*x^40*y^40+17333*x^38*y^40+19700*x^36*y^40+24090*x^34*y^40+37365*x^32*y^40+2711*x^30*y^40+29136*x^28*y^40+16831*x^26*y^40+10347*x^24*y^40+22176*x^22*y^40+29371*x^20*y^40" "+36081*x^18*y^40+5113*x^16*y^40+32126*x^14*y^40+2028*x^12*y^40+30741*x^10*y^40+33024*x^8*y^40+10398*x^6*y^40+27455*x^4*y^40+34902*x^2*y^40+30512*y^40+29849*x^90*y^38+41133*x^88*y^38+27716*x^86*y^38" "+138*x^84*y^38+32679*x^82*y^38+2747*x^80*y^38+33487*x^78*y^38+13823*x^76*y^38+39475*x^74*y^38+3497*x^72*y^38+41243*x^70*y^38+39880*x^68*y^38+12411*x^66*y^38+34154*x^64*y^38+5074*x^62*y^38+22161*x^60*y^38" "+39319*x^58*y^38+25549*x^56*y^38+15968*x^54*y^38+8305*x^52*y^38+41426*x^50*y^38+35134*x^48*y^38+36521*x^46*y^38+14182*x^44*y^38+30536*x^42*y^38+8423*x^40*y^38+5474*x^38*y^38+31565*x^36*y^38+4711*x^34*y^38" "+43038*x^32*y^38+38258*x^30*y^38+42573*x^28*y^38+8200*x^26*y^38+11618*x^24*y^38+18823*x^22*y^38+10215*x^20*y^38+36187*x^18*y^38+42142*x^16*y^38+37681*x^14*y^38+42931*x^12*y^38+38124*x^10*y^38+17536*x^8*y^38" "+35925*x^6*y^38+8998*x^4*y^38+27564*x^2*y^38+16004*y^38+12442*x^92*y^36+29872*x^90*y^36+38715*x^88*y^36+5344*x^86*y^36+40687*x^84*y^36+15441*x^82*y^36+942*x^80*y^36+34058*x^78*y^36+12928*x^76*y^36" "+9450*x^74*y^36+10515*x^72*y^36+9330*x^70*y^36+15511*x^68*y^36+31114*x^66*y^36+42745*x^64*y^36+14424*x^62*y^36+7069*x^60*y^36+1769*x^58*y^36+13742*x^56*y^36+303*x^54*y^36+24852*x^52*y^36+38114*x^50*y^36" "+42462*x^48*y^36+16431*x^46*y^36+22962*x^44*y^36+14290*x^42*y^36+12347*x^40*y^36+17425*x^38*y^36+11366*x^36*y^36+27289*x^34*y^36+5298*x^32*y^36+28347*x^30*y^36+23967*x^28*y^36+20786*x^26*y^36+1208*x^24*y^36" "+19388*x^22*y^36+1056*x^20*y^36+21187*x^18*y^36+10954*x^16*y^36+5538*x^14*y^36+28512*x^12*y^36+13434*x^10*y^36+31202*x^8*y^36+36133*x^6*y^36+10807*x^4*y^36+24627*x^2*y^36+18242*y^36+32303*x^94*y^34" "+34804*x^92*y^34+12595*x^90*y^34+466*x^88*y^34+25693*x^86*y^34+30639*x^84*y^34+39699*x^82*y^34+38419*x^80*y^34+6841*x^78*y^34+39044*x^76*y^34+31469*x^74*y^34+14907*x^72*y^34+18833*x^70*y^34+6608*x^68*y^34" "+17902*x^66*y^34+8702*x^64*y^34+15290*x^62*y^34+24784*x^60*y^34+11200*x^58*y^34+4515*x^56*y^34+18866*x^54*y^34+39522*x^52*y^34+11216*x^50*y^34+30197*x^48*y^34+38665*x^46*y^34+24942*x^44*y^34+2599*x^42*y^34" "+28470*x^40*y^34+39133*x^38*y^34+7643*x^36*y^34+41850*x^34*y^34+37617*x^32*y^34+34835*x^30*y^34+36766*x^28*y^34+27850*x^26*y^34+30279*x^24*y^34+38347*x^22*y^34+31850*x^20*y^34+36012*x^18*y^34+1895*x^16*y^34" "+17845*x^14*y^34+23484*x^12*y^34+40104*x^10*y^34+13404*x^8*y^34+40238*x^6*y^34+6260*x^4*y^34+41873*x^2*y^34+21135*y^34+30296*x^96*y^32+1003*x^94*y^32+30294*x^92*y^32+21119*x^90*y^32+1811*x^88*y^32" "+39110*x^86*y^32+1530*x^84*y^32+22334*x^82*y^32+22487*x^80*y^32+33660*x^78*y^32+35557*x^76*y^32+14741*x^74*y^32+13387*x^72*y^32+32164*x^70*y^32+18429*x^68*y^32+36119*x^66*y^32+35287*x^64*y^32+42840*x^62*y^32" "+25360*x^60*y^32+4209*x^58*y^32+36431*x^56*y^32+20892*x^54*y^32+22762*x^52*y^32+37186*x^50*y^32+40139*x^48*y^32+33507*x^46*y^32+39864*x^44*y^32+17099*x^42*y^32+24078*x^40*y^32+13217*x^38*y^32+26178*x^36*y^32" "+27115*x^34*y^32+5264*x^32*y^32+20163*x^30*y^32+21928*x^28*y^32+9182*x^26*y^32+7375*x^24*y^32+36810*x^22*y^32+30855*x^20*y^32+27868*x^18*y^32+17233*x^16*y^32+6041*x^14*y^32+35985*x^12*y^32+23924*x^10*y^32" "+16483*x^8*y^32+6214*x^6*y^32+911*x^4*y^32+39978*x^2*y^32+31930*y^32+13259*x^98*y^30+1649*x^96*y^30+42343*x^94*y^30+40042*x^92*y^30+17446*x^90*y^30+12726*x^88*y^30+37524*x^86*y^30+36817*x^84*y^30" "+24541*x^82*y^30+27597*x^80*y^30+36919*x^78*y^30+9540*x^76*y^30+26864*x^74*y^30+5141*x^72*y^30+38779*x^70*y^30+3244*x^68*y^30+23123*x^66*y^30+40038*x^64*y^30+40294*x^62*y^30+33946*x^60*y^30+22834*x^58*y^30" "+5815*x^56*y^30+14495*x^54*y^30+3736*x^52*y^30+25571*x^50*y^30+30148*x^48*y^30+42213*x^46*y^30+1907*x^44*y^30+7740*x^42*y^30+33694*x^40*y^30+29242*x^38*y^30+37577*x^36*y^30+34653*x^34*y^30+13100*x^32*y^30" "+22401*x^30*y^30+16864*x^28*y^30+17561*x^26*y^30+35158*x^24*y^30+30240*x^22*y^30+1402*x^20*y^30+13055*x^18*y^30+18530*x^16*y^30+1017*x^14*y^30+7572*x^12*y^30+34197*x^10*y^30+12809*x^8*y^30+9511*x^6*y^30" "+11985*x^4*y^30+31220*x^2*y^30+9145*y^30+40351*x^100*y^28+20622*x^98*y^28+22519*x^96*y^28+8261*x^94*y^28+21997*x^92*y^28+30223*x^90*y^28+19856*x^88*y^28+33089*x^86*y^28+11154*x^84*y^28+4030*x^82*y^28" "+38869*x^80*y^28+4924*x^78*y^28+40791*x^76*y^28+40472*x^74*y^28+9788*x^72*y^28+2117*x^70*y^28+7080*x^68*y^28+16187*x^66*y^28+13884*x^64*y^28+15498*x^62*y^28+10730*x^60*y^28+17576*x^58*y^28+28463*x^56*y^28" "+29228*x^54*y^28+13000*x^52*y^28+15277*x^50*y^28+25205*x^48*y^28+1737*x^46*y^28+16335*x^44*y^28+34544*x^42*y^28+26159*x^40*y^28+1170*x^38*y^28+37992*x^36*y^28+23194*x^34*y^28+22400*x^32*y^28+33934*x^30*y^28" "+33699*x^28*y^28+36330*x^26*y^28+38636*x^24*y^28+42919*x^22*y^28+175*x^20*y^28+23148*x^18*y^28+18512*x^16*y^28+5208*x^14*y^28+39725*x^12*y^28+18623*x^10*y^28+5052*x^8*y^28+5972*x^6*y^28+31164*x^4*y^28" "+16078*x^2*y^28+13045*y^28+11763*x^102*y^26+21004*x^100*y^26+35020*x^98*y^26+16898*x^96*y^26+16872*x^94*y^26+20002*x^92*y^26+2124*x^90*y^26+10098*x^88*y^26+8120*x^86*y^26+1522*x^84*y^26+8732*x^82*y^26" "+4742*x^80*y^26+3280*x^78*y^26+13553*x^76*y^26+31868*x^74*y^26+20962*x^72*y^26+10907*x^70*y^26+39769*x^68*y^26+15994*x^66*y^26+5412*x^64*y^26+29519*x^62*y^26+11859*x^60*y^26+40331*x^58*y^26+22206*x^56*y^26" "+8824*x^54*y^26+17297*x^52*y^26+29074*x^50*y^26+18621*x^48*y^26+6710*x^46*y^26+9842*x^44*y^26+34232*x^42*y^26+318*x^40*y^26+7817*x^38*y^26+4536*x^36*y^26+32775*x^34*y^26+13246*x^32*y^26+23924*x^30*y^26" "+7712*x^28*y^26+556*x^26*y^26+16362*x^24*y^26+10096*x^22*y^26+7565*x^20*y^26+4982*x^18*y^26+9802*x^16*y^26+25388*x^14*y^26+25321*x^12*y^26+8307*x^10*y^26+27764*x^8*y^26+24583*x^6*y^26+27578*x^4*y^26" "+21206*x^2*y^26+37859*y^26+28377*x^104*y^24+8962*x^102*y^24+11376*x^100*y^24+14525*x^98*y^24+42979*x^96*y^24+4682*x^94*y^24+9041*x^92*y^24+8583*x^90*y^24+37014*x^88*y^24+29291*x^86*y^24+12310*x^84*y^24" "+31482*x^82*y^24+16114*x^80*y^24+30997*x^78*y^24+20887*x^76*y^24+17150*x^74*y^24+33006*x^72*y^24+20600*x^70*y^24+5047*x^68*y^24+17114*x^66*y^24+609*x^64*y^24+7507*x^62*y^24+25411*x^60*y^24+40113*x^58*y^24" "+29618*x^56*y^24+19746*x^54*y^24+35582*x^52*y^24+4122*x^50*y^24+3359*x^48*y^24+30716*x^46*y^24+24840*x^44*y^24+1799*x^42*y^24+7841*x^40*y^24+3141*x^38*y^24+634*x^36*y^24+25616*x^34*y^24+32660*x^32*y^24" "+41753*x^30*y^24+23043*x^28*y^24+42804*x^26*y^24+34500*x^24*y^24+28351*x^22*y^24+26411*x^20*y^24+14351*x^18*y^24+40745*x^16*y^24+19739*x^14*y^24+28593*x^12*y^24+37098*x^10*y^24+20578*x^8*y^24+31054*x^6*y^24" "+37188*x^4*y^24+4924*x^2*y^24+4891*y^24+22744*x^106*y^22+27515*x^104*y^22+5117*x^102*y^22+32814*x^100*y^22+13114*x^98*y^22+37879*x^96*y^22+16011*x^94*y^22+24858*x^92*y^22+23518*x^90*y^22+26351*x^88*y^22" "+21153*x^86*y^22+36728*x^84*y^22+22112*x^82*y^22+22345*x^80*y^22+6502*x^78*y^22+23010*x^76*y^22+41233*x^74*y^22+10499*x^72*y^22+19707*x^70*y^22+13145*x^68*y^22+38094*x^66*y^22+38179*x^64*y^22+38218*x^62*y^22" "+11010*x^60*y^22+30153*x^58*y^22+10249*x^56*y^22+33039*x^54*y^22+33936*x^52*y^22+9793*x^50*y^22+18374*x^48*y^22+27264*x^46*y^22+9677*x^44*y^22+3607*x^42*y^22+25575*x^40*y^22+18776*x^38*y^22+37784*x^36*y^22" "+6192*x^34*y^22+27424*x^32*y^22+31379*x^30*y^22+42991*x^28*y^22+35781*x^26*y^22+35142*x^24*y^22+27961*x^22*y^22+40257*x^20*y^22+21985*x^18*y^22+42941*x^16*y^22+9119*x^14*y^22+15735*x^12*y^22+24902*x^10*y^22" "+21706*x^8*y^22+25112*x^6*y^22+6725*x^4*y^22+24107*x^2*y^22+15931*y^22+33321*x^108*y^20+10563*x^106*y^20+3363*x^104*y^20+29142*x^102*y^20+10993*x^100*y^20+6844*x^98*y^20+6045*x^96*y^20+16946*x^94*y^20" "+40994*x^92*y^20+18802*x^90*y^20+5729*x^88*y^20+40880*x^86*y^20+4686*x^84*y^20+38678*x^82*y^20+23143*x^80*y^20+4598*x^78*y^20+1292*x^76*y^20+32374*x^74*y^20+1789*x^72*y^20+4012*x^70*y^20+6061*x^68*y^20" "+23981*x^66*y^20+26920*x^64*y^20+12102*x^62*y^20+40871*x^60*y^20+38508*x^58*y^20+8448*x^56*y^20+3318*x^54*y^20+25796*x^52*y^20+3765*x^50*y^20+13953*x^48*y^20+39638*x^46*y^20+7641*x^44*y^20+34281*x^42*y^20" "+25188*x^40*y^20+6245*x^38*y^20+7963*x^36*y^20+10665*x^34*y^20+19712*x^32*y^20+21808*x^30*y^20+36183*x^28*y^20+34582*x^26*y^20+24967*x^24*y^20+262*x^22*y^20+42403*x^20*y^20+28224*x^18*y^20+10950*x^16*y^20" "+29651*x^14*y^20+23728*x^12*y^20+17933*x^10*y^20+3664*x^8*y^20+26875*x^6*y^20+34708*x^4*y^20+2642*x^2*y^20+33896*y^20+27775*x^110*y^18+41310*x^108*y^18+30173*x^106*y^18+21709*x^104*y^18+37047*x^102*y^18" "+36285*x^100*y^18+14457*x^98*y^18+31018*x^96*y^18+40470*x^94*y^18+18310*x^92*y^18+10704*x^90*y^18+13274*x^88*y^18+42113*x^86*y^18+22749*x^84*y^18+14881*x^82*y^18+39762*x^80*y^18+19974*x^78*y^18" "+27029*x^76*y^18+30579*x^74*y^18+41704*x^72*y^18+27726*x^70*y^18+16723*x^68*y^18+38490*x^66*y^18+36600*x^64*y^18+36024*x^62*y^18+38352*x^60*y^18+41432*x^58*y^18+23731*x^56*y^18+17018*x^54*y^18+24536*x^52*y^18" "+32150*x^50*y^18+6730*x^48*y^18+22602*x^46*y^18+5261*x^44*y^18+5536*x^42*y^18+18176*x^40*y^18+12507*x^38*y^18+12327*x^36*y^18+5200*x^34*y^18+3951*x^32*y^18+1139*x^30*y^18+28799*x^28*y^18+42298*x^26*y^18" "+15858*x^24*y^18+18482*x^22*y^18+42595*x^20*y^18+41085*x^18*y^18+36609*x^16*y^18+30801*x^14*y^18+42662*x^12*y^18+33381*x^10*y^18+14186*x^8*y^18+2973*x^6*y^18+14058*x^4*y^18+9942*x^2*y^18+22053*y^18" "+16123*x^112*y^16+9727*x^110*y^16+39670*x^108*y^16+19731*x^106*y^16+37428*x^104*y^16+5815*x^102*y^16+15514*x^100*y^16+25870*x^98*y^16+29954*x^96*y^16+4840*x^94*y^16+33251*x^92*y^16+3840*x^90*y^16" "+21369*x^88*y^16+1379*x^86*y^16+37462*x^84*y^16+40905*x^82*y^16+27393*x^80*y^16+10898*x^78*y^16+546*x^76*y^16+35102*x^74*y^16+24746*x^72*y^16+35841*x^70*y^16+39231*x^68*y^16+38679*x^66*y^16+34683*x^64*y^16" "+12743*x^62*y^16+5524*x^60*y^16+16862*x^58*y^16+33161*x^56*y^16+25286*x^54*y^16+30665*x^52*y^16+37040*x^50*y^16+6538*x^48*y^16+10239*x^46*y^16+15301*x^44*y^16+23289*x^42*y^16+22443*x^40*y^16+35604*x^38*y^16" "+15837*x^36*y^16+5135*x^34*y^16+33046*x^32*y^16+11347*x^30*y^16+16223*x^28*y^16+7607*x^26*y^16+12076*x^24*y^16+15038*x^22*y^16+37709*x^20*y^16+41144*x^18*y^16+9187*x^16*y^16+32064*x^14*y^16+8593*x^12*y^16" "+10499*x^10*y^16+7764*x^8*y^16+36493*x^6*y^16+17176*x^4*y^16+32635*x^2*y^16+19758*y^16+25384*x^114*y^14+42375*x^112*y^14+9096*x^110*y^14+689*x^108*y^14+26996*x^106*y^14+27150*x^104*y^14+12256*x^102*y^14" "+27479*x^100*y^14+28589*x^98*y^14+23303*x^96*y^14+7653*x^94*y^14+32175*x^92*y^14+17866*x^90*y^14+1954*x^88*y^14+38326*x^86*y^14+24090*x^84*y^14+15817*x^82*y^14+1302*x^80*y^14+18067*x^78*y^14+39447*x^76*y^14" "+24658*x^74*y^14+21765*x^72*y^14+41654*x^70*y^14+18524*x^68*y^14+32640*x^66*y^14+28450*x^64*y^14+7676*x^62*y^14+14977*x^60*y^14+7476*x^58*y^14+30438*x^56*y^14+27107*x^54*y^14+23548*x^52*y^14+37117*x^50*y^14" "+19375*x^48*y^14+3066*x^46*y^14+1255*x^44*y^14+12791*x^42*y^14+24241*x^40*y^14+20990*x^38*y^14+21084*x^36*y^14+22010*x^34*y^14+37408*x^32*y^14+32849*x^30*y^14+35358*x^28*y^14+23592*x^26*y^14+15623*x^24*y^14" "+38007*x^22*y^14+11885*x^20*y^14+21078*x^18*y^14+41118*x^16*y^14+19656*x^14*y^14+12726*x^12*y^14+33941*x^10*y^14+42913*x^8*y^14+27271*x^6*y^14+25971*x^4*y^14+18223*x^2*y^14+29918*y^14+1067*x^116*y^12" "+21936*x^114*y^12+4889*x^112*y^12+4369*x^110*y^12+23938*x^108*y^12+27567*x^106*y^12+11840*x^104*y^12+30365*x^102*y^12+30369*x^100*y^12+11970*x^98*y^12+15389*x^96*y^12+37830*x^94*y^12+17303*x^92*y^12" "+19292*x^90*y^12+15776*x^88*y^12+249*x^86*y^12+342*x^84*y^12+3535*x^82*y^12+36936*x^80*y^12+3147*x^78*y^12+20237*x^76*y^12+25742*x^74*y^12+354*x^72*y^12+40560*x^70*y^12+15310*x^68*y^12+35580*x^66*y^12" "+19979*x^64*y^12+27972*x^62*y^12+6767*x^60*y^12+37514*x^58*y^12+8011*x^56*y^12+6231*x^54*y^12+24350*x^52*y^12+25423*x^50*y^12+38459*x^48*y^12+40086*x^46*y^12+15813*x^44*y^12+17851*x^42*y^12+37129*x^40*y^12" "+3496*x^38*y^12+33837*x^36*y^12+5447*x^34*y^12+6383*x^32*y^12+9474*x^30*y^12+24724*x^28*y^12+6481*x^26*y^12+15411*x^24*y^12+13093*x^22*y^12+40731*x^20*y^12+6468*x^18*y^12+40848*x^16*y^12+21875*x^14*y^12" "+1108*x^10*y^12+16118*x^8*y^12+34812*x^6*y^12+9296*x^4*y^12+21946*x^2*y^12+22856*y^12+35518*x^118*y^10+25608*x^116*y^10+14746*x^114*y^10+10454*x^112*y^10+19292*x^110*y^10+11001*x^108*y^10+36431*x^106*y^10" "+36762*x^104*y^10+3397*x^102*y^10+33909*x^100*y^10+28242*x^98*y^10+32528*x^96*y^10+22459*x^94*y^10+23104*x^92*y^10+17464*x^90*y^10+13727*x^88*y^10+13076*x^86*y^10+11231*x^84*y^10+23416*x^82*y^10" "+40218*x^80*y^10+18282*x^78*y^10+42255*x^76*y^10+10871*x^74*y^10+6648*x^72*y^10+20228*x^70*y^10+29206*x^68*y^10+1569*x^66*y^10+19627*x^64*y^10+24770*x^62*y^10+33794*x^60*y^10+30866*x^58*y^10+29169*x^56*y^10" "+28939*x^54*y^10+30376*x^52*y^10+42151*x^50*y^10+19761*x^48*y^10+37827*x^46*y^10+3359*x^44*y^10+9546*x^42*y^10+25614*x^40*y^10+31995*x^38*y^10+21234*x^36*y^10+33334*x^34*y^10+25114*x^32*y^10+38854*x^30*y^10" "+389*x^28*y^10+20600*x^26*y^10+22432*x^24*y^10+15923*x^22*y^10+30038*x^20*y^10+29312*x^18*y^10+14323*x^16*y^10+34932*x^14*y^10+36115*x^12*y^10+5416*x^10*y^10+41426*x^8*y^10+33099*x^6*y^10+12083*x^4*y^10" "+17452*x^2*y^10+42701*y^10+42314*x^120*y^8+21544*x^118*y^8+37500*x^116*y^8+13985*x^114*y^8+730*x^112*y^8+33930*x^110*y^8+27030*x^108*y^8+12788*x^106*y^8+3851*x^104*y^8+8245*x^102*y^8+25684*x^100*y^8" "+16418*x^98*y^8+30443*x^96*y^8+35812*x^94*y^8+39533*x^92*y^8+19972*x^90*y^8+23609*x^88*y^8+8468*x^86*y^8+32765*x^84*y^8+36027*x^82*y^8+29048*x^80*y^8+20962*x^78*y^8+11490*x^76*y^8+11794*x^74*y^8+9219*x^72*y^8" "+6885*x^70*y^8+38853*x^68*y^8+11940*x^66*y^8+11316*x^64*y^8+16865*x^62*y^8+17924*x^60*y^8+32336*x^58*y^8+16885*x^56*y^8+25698*x^54*y^8+1379*x^52*y^8+20310*x^50*y^8+41692*x^48*y^8+38184*x^46*y^8+29771*x^44*y^8" "+34485*x^42*y^8+11760*x^40*y^8+7575*x^38*y^8+35492*x^36*y^8+28155*x^34*y^8+23719*x^32*y^8+18253*x^30*y^8+3509*x^28*y^8+20494*x^26*y^8+23353*x^24*y^8+15905*x^22*y^8+24318*x^20*y^8+20535*x^18*y^8+20057*x^16*y^8" "+15786*x^14*y^8+38197*x^12*y^8+21260*x^10*y^8+41792*x^8*y^8+6679*x^6*y^8+42019*x^4*y^8+22441*x^2*y^8+12577*y^8+13606*x^122*y^6+31259*x^120*y^6+3199*x^118*y^6+21030*x^116*y^6+37581*x^114*y^6+14359*x^112*y^6" "+17525*x^110*y^6+15288*x^108*y^6+22520*x^106*y^6+32196*x^104*y^6+30644*x^102*y^6+33321*x^100*y^6+9241*x^98*y^6+17384*x^96*y^6+16640*x^94*y^6+35673*x^92*y^6+6638*x^90*y^6+20454*x^88*y^6+5794*x^86*y^6" "+22843*x^84*y^6+30716*x^82*y^6+10880*x^80*y^6+37932*x^78*y^6+31310*x^76*y^6+36341*x^74*y^6+731*x^72*y^6+8364*x^70*y^6+28596*x^68*y^6+33290*x^66*y^6+29033*x^64*y^6+28890*x^62*y^6+37977*x^60*y^6+27613*x^58*y^6" "+24192*x^56*y^6+9950*x^54*y^6+29308*x^52*y^6+11359*x^50*y^6+41909*x^48*y^6+203*x^46*y^6+38196*x^44*y^6+7704*x^42*y^6+10320*x^40*y^6+30688*x^38*y^6+35354*x^36*y^6+6957*x^34*y^6+20292*x^32*y^6+38218*x^30*y^6" "+24611*x^28*y^6+20466*x^26*y^6+15209*x^24*y^6+19270*x^22*y^6+27721*x^20*y^6+6845*x^18*y^6+29018*x^16*y^6+23952*x^14*y^6+27870*x^12*y^6+40985*x^10*y^6+2602*x^8*y^6+20584*x^6*y^6+32011*x^4*y^6+38749*x^2*y^6" "+40627*y^6+9994*x^124*y^4+34119*x^122*y^4+9024*x^120*y^4+37204*x^118*y^4+33887*x^116*y^4+9177*x^114*y^4+15179*x^112*y^4+36258*x^110*y^4+30374*x^108*y^4+19268*x^106*y^4+3566*x^104*y^4+33516*x^102*y^4" "+22410*x^100*y^4+1492*x^98*y^4+30548*x^96*y^4+40127*x^94*y^4+10646*x^92*y^4+1666*x^90*y^4+29859*x^88*y^4+26565*x^86*y^4+5696*x^84*y^4+10268*x^82*y^4+20378*x^80*y^4+733*x^78*y^4+18248*x^76*y^4+2908*x^74*y^4" "+41169*x^72*y^4+16635*x^70*y^4+4059*x^68*y^4+39873*x^66*y^4+16195*x^64*y^4+33356*x^62*y^4+8160*x^60*y^4+1093*x^58*y^4+16063*x^56*y^4+37764*x^54*y^4+12619*x^52*y^4+5780*x^50*y^4+16383*x^48*y^4+15494*x^46*y^4" "+26499*x^44*y^4+32670*x^42*y^4+29531*x^40*y^4+11272*x^38*y^4+6931*x^36*y^4+41099*x^34*y^4+1210*x^32*y^4+8810*x^30*y^4+27165*x^28*y^4+37630*x^26*y^4+7329*x^24*y^4+31246*x^22*y^4+17787*x^20*y^4+33572*x^18*y^4" "+16678*x^16*y^4+38212*x^14*y^4+30056*x^12*y^4+35986*x^10*y^4+12193*x^8*y^4+9064*x^6*y^4+24665*x^4*y^4+400*x^2*y^4+21210*y^4+42603*x^126*y^2+36901*x^124*y^2+33142*x^122*y^2+19026*x^120*y^2+26257*x^118*y^2" "+31668*x^116*y^2+21902*x^114*y^2+41439*x^112*y^2+36772*x^110*y^2+16520*x^108*y^2+16801*x^106*y^2+13208*x^104*y^2+22892*x^102*y^2+36494*x^100*y^2+42852*x^98*y^2+35447*x^96*y^2+29449*x^94*y^2+11369*x^92*y^2" "+23905*x^90*y^2+6904*x^88*y^2+23311*x^86*y^2+16416*x^84*y^2+17023*x^82*y^2+6396*x^80*y^2+29010*x^78*y^2+28121*x^76*y^2+4439*x^74*y^2+41866*x^72*y^2+2443*x^70*y^2+1787*x^68*y^2+23637*x^66*y^2+35450*x^64*y^2" "+25101*x^62*y^2+38210*x^60*y^2+25920*x^58*y^2+977*x^56*y^2+37499*x^54*y^2+43019*x^52*y^2+17431*x^50*y^2+42286*x^48*y^2+26977*x^46*y^2+42471*x^44*y^2+42637*x^42*y^2+16109*x^40*y^2+1806*x^38*y^2+21331*x^36*y^2" "+43042*x^34*y^2+21708*x^32*y^2+2999*x^30*y^2+21064*x^28*y^2+32594*x^26*y^2+7587*x^24*y^2+2077*x^22*y^2+27117*x^20*y^2+21429*x^18*y^2+24873*x^16*y^2+40822*x^14*y^2+22856*x^12*y^2+39615*x^10*y^2+32121*x^8*y^2" "+8136*x^6*y^2+40332*x^4*y^2+12301*x^2*y^2+32848*y^2+x^128+41259*x^126+32543*x^124+26938*x^122+25117*x^120+3458*x^118+28947*x^116+19659*x^114+20639*x^112+41369*x^110+6547*x^108+19680*x^106+31688*x^104" "+10952*x^102+1407*x^100+1278*x^98+13056*x^96+32272*x^94+19351*x^92+11254*x^90+18780*x^88+41868*x^86+13034*x^84+38190*x^82+34930*x^80+23678*x^78+7426*x^76+13585*x^74+41317*x^72+40154*x^70+10739*x^68+22876*x^66" "+19733*x^64+3127*x^62+33675*x^60+30109*x^58+20180*x^56+13924*x^54+4045*x^52+37752*x^50+30118*x^48+1615*x^46+4510*x^44+16577*x^42+7536*x^40+34837*x^38+241*x^36+9705*x^34+2196*x^32+33198*x^30+21393*x^28" "+32583*x^26+33148*x^24+12208*x^22+31138*x^20+15252*x^18+5157*x^16+15920*x^14+761*x^12+5651*x^10+42802*x^8+14396*x^6+34190*x^4+31143*x^2+39447)" "*(y^128+42603*x^2*y^126+41259*y^126+9994*x^4*y^124+36901*x^2*y^124+32543*y^124+13606*x^6*y^122+34119*x^4*y^122+33142*x^2*y^122+26938*y^122+42314*x^8*y^120+31259*x^6*y^120+9024*x^4*y^120+19026*x^2*y^120" "+25117*y^120+35518*x^10*y^118+21544*x^8*y^118+3199*x^6*y^118+37204*x^4*y^118+26257*x^2*y^118+3458*y^118+1067*x^12*y^116+25608*x^10*y^116+37500*x^8*y^116+21030*x^6*y^116+33887*x^4*y^116+31668*x^2*y^116" "+28947*y^116+25384*x^14*y^114+21936*x^12*y^114+14746*x^10*y^114+13985*x^8*y^114+37581*x^6*y^114+9177*x^4*y^114+21902*x^2*y^114+19659*y^114+16123*x^16*y^112+42375*x^14*y^112+4889*x^12*y^112+10454*x^10*y^112" "+730*x^8*y^112+14359*x^6*y^112+15179*x^4*y^112+41439*x^2*y^112+20639*y^112+27775*x^18*y^110+9727*x^16*y^110+9096*x^14*y^110+4369*x^12*y^110+19292*x^10*y^110+33930*x^8*y^110+17525*x^6*y^110+36258*x^4*y^110" "+36772*x^2*y^110+41369*y^110+33321*x^20*y^108+41310*x^18*y^108+39670*x^16*y^108+689*x^14*y^108+23938*x^12*y^108+11001*x^10*y^108+27030*x^8*y^108+15288*x^6*y^108+30374*x^4*y^108+16520*x^2*y^108+6547*y^108" "+22744*x^22*y^106+10563*x^20*y^106+30173*x^18*y^106+19731*x^16*y^106+26996*x^14*y^106+27567*x^12*y^106+36431*x^10*y^106+12788*x^8*y^106+22520*x^6*y^106+19268*x^4*y^106+16801*x^2*y^106+19680*y^106" "+28377*x^24*y^104+27515*x^22*y^104+3363*x^20*y^104+21709*x^18*y^104+37428*x^16*y^104+27150*x^14*y^104+11840*x^12*y^104+36762*x^10*y^104+3851*x^8*y^104+32196*x^6*y^104+3566*x^4*y^104+13208*x^2*y^104" "+31688*y^104+11763*x^26*y^102+8962*x^24*y^102+5117*x^22*y^102+29142*x^20*y^102+37047*x^18*y^102+5815*x^16*y^102+12256*x^14*y^102+30365*x^12*y^102+3397*x^10*y^102+8245*x^8*y^102+30644*x^6*y^102+33516*x^4*y^102" "+22892*x^2*y^102+10952*y^102+40351*x^28*y^100+21004*x^26*y^100+11376*x^24*y^100+32814*x^22*y^100+10993*x^20*y^100+36285*x^18*y^100+15514*x^16*y^100+27479*x^14*y^100+30369*x^12*y^100+33909*x^10*y^100" "+25684*x^8*y^100+33321*x^6*y^100+22410*x^4*y^100+36494*x^2*y^100+1407*y^100+13259*x^30*y^98+20622*x^28*y^98+35020*x^26*y^98+14525*x^24*y^98+13114*x^22*y^98+6844*x^20*y^98+14457*x^18*y^98+25870*x^16*y^98" "+28589*x^14*y^98+11970*x^12*y^98+28242*x^10*y^98+16418*x^8*y^98+9241*x^6*y^98+1492*x^4*y^98+42852*x^2*y^98+1278*y^98+30296*x^32*y^96+1649*x^30*y^96+22519*x^28*y^96+16898*x^26*y^96+42979*x^24*y^96" "+37879*x^22*y^96+6045*x^20*y^96+31018*x^18*y^96+29954*x^16*y^96+23303*x^14*y^96+15389*x^12*y^96+32528*x^10*y^96+30443*x^8*y^96+17384*x^6*y^96+30548*x^4*y^96+35447*x^2*y^96+13056*y^96+32303*x^34*y^94" "+1003*x^32*y^94+42343*x^30*y^94+8261*x^28*y^94+16872*x^26*y^94+4682*x^24*y^94+16011*x^22*y^94+16946*x^20*y^94+40470*x^18*y^94+4840*x^16*y^94+7653*x^14*y^94+37830*x^12*y^94+22459*x^10*y^94+35812*x^8*y^94" "+16640*x^6*y^94+40127*x^4*y^94+29449*x^2*y^94+32272*y^94+12442*x^36*y^92+34804*x^34*y^92+30294*x^32*y^92+40042*x^30*y^92+21997*x^28*y^92+20002*x^26*y^92+9041*x^24*y^92+24858*x^22*y^92+40994*x^20*y^92" "+18310*x^18*y^92+33251*x^16*y^92+32175*x^14*y^92+17303*x^12*y^92+23104*x^10*y^92+39533*x^8*y^92+35673*x^6*y^92+10646*x^4*y^92+11369*x^2*y^92+19351*y^92+29849*x^38*y^90+29872*x^36*y^90+12595*x^34*y^90" "+21119*x^32*y^90+17446*x^30*y^90+30223*x^28*y^90+2124*x^26*y^90+8583*x^24*y^90+23518*x^22*y^90+18802*x^20*y^90+10704*x^18*y^90+3840*x^16*y^90+17866*x^14*y^90+19292*x^12*y^90+17464*x^10*y^90+19972*x^8*y^90" "+6638*x^6*y^90+1666*x^4*y^90+23905*x^2*y^90+11254*y^90+31188*x^40*y^88+41133*x^38*y^88+38715*x^36*y^88+466*x^34*y^88+1811*x^32*y^88+12726*x^30*y^88+19856*x^28*y^88+10098*x^26*y^88+37014*x^24*y^88" "+26351*x^22*y^88+5729*x^20*y^88+13274*x^18*y^88+21369*x^16*y^88+1954*x^14*y^88+15776*x^12*y^88+13727*x^10*y^88+23609*x^8*y^88+20454*x^6*y^88+29859*x^4*y^88+6904*x^2*y^88+18780*y^88+10504*x^42*y^86" "+21316*x^40*y^86+27716*x^38*y^86+5344*x^36*y^86+25693*x^34*y^86+39110*x^32*y^86+37524*x^30*y^86+33089*x^28*y^86+8120*x^26*y^86+29291*x^24*y^86+21153*x^22*y^86+40880*x^20*y^86+42113*x^18*y^86+1379*x^16*y^86" "+38326*x^14*y^86+249*x^12*y^86+13076*x^10*y^86+8468*x^8*y^86+5794*x^6*y^86+26565*x^4*y^86+23311*x^2*y^86+41868*y^86+18042*x^44*y^84+37860*x^42*y^84+27934*x^40*y^84+138*x^38*y^84+40687*x^36*y^84" "+30639*x^34*y^84+1530*x^32*y^84+36817*x^30*y^84+11154*x^28*y^84+1522*x^26*y^84+12310*x^24*y^84+36728*x^22*y^84+4686*x^20*y^84+22749*x^18*y^84+37462*x^16*y^84+24090*x^14*y^84+342*x^12*y^84+11231*x^10*y^84" "+32765*x^8*y^84+22843*x^6*y^84+5696*x^4*y^84+16416*x^2*y^84+13034*y^84+28277*x^46*y^82+18424*x^44*y^82+32406*x^42*y^82+31960*x^40*y^82+32679*x^38*y^82+15441*x^36*y^82+39699*x^34*y^82+22334*x^32*y^82" "+24541*x^30*y^82+4030*x^28*y^82+8732*x^26*y^82+31482*x^24*y^82+22112*x^22*y^82+38678*x^20*y^82+14881*x^18*y^82+40905*x^16*y^82+15817*x^14*y^82+3535*x^12*y^82+23416*x^10*y^82+36027*x^8*y^82+30716*x^6*y^82" "+10268*x^4*y^82+17023*x^2*y^82+38190*y^82+41480*x^48*y^80+21388*x^46*y^80+30517*x^44*y^80+14292*x^42*y^80+778*x^40*y^80+2747*x^38*y^80+942*x^36*y^80+38419*x^34*y^80+22487*x^32*y^80+27597*x^30*y^80" "+38869*x^28*y^80+4742*x^26*y^80+16114*x^24*y^80+22345*x^22*y^80+23143*x^20*y^80+39762*x^18*y^80+27393*x^16*y^80+1302*x^14*y^80+36936*x^12*y^80+40218*x^10*y^80+29048*x^8*y^80+10880*x^6*y^80+20378*x^4*y^80" "+6396*x^2*y^80+34930*y^80+36780*x^50*y^78+18665*x^48*y^78+29022*x^46*y^78+27229*x^44*y^78+12380*x^42*y^78+21473*x^40*y^78+33487*x^38*y^78+34058*x^36*y^78+6841*x^34*y^78+33660*x^32*y^78+36919*x^30*y^78" "+4924*x^28*y^78+3280*x^26*y^78+30997*x^24*y^78+6502*x^22*y^78+4598*x^20*y^78+19974*x^18*y^78+10898*x^16*y^78+18067*x^14*y^78+3147*x^12*y^78+18282*x^10*y^78+20962*x^8*y^78+37932*x^6*y^78+733*x^4*y^78" "+29010*x^2*y^78+23678*y^78+38813*x^52*y^76+32809*x^50*y^76+22404*x^48*y^76+10823*x^46*y^76+10937*x^44*y^76+15078*x^42*y^76+20012*x^40*y^76+13823*x^38*y^76+12928*x^36*y^76+39044*x^34*y^76+35557*x^32*y^76" "+9540*x^30*y^76+40791*x^28*y^76+13553*x^26*y^76+20887*x^24*y^76+23010*x^22*y^76+1292*x^20*y^76+27029*x^18*y^76+546*x^16*y^76+39447*x^14*y^76+20237*x^12*y^76+42255*x^10*y^76+11490*x^8*y^76+31310*x^6*y^76" "+18248*x^4*y^76+28121*x^2*y^76+7426*y^76+25063*x^54*y^74+37642*x^52*y^74+35028*x^50*y^74+39684*x^48*y^74+16670*x^46*y^74+18269*x^44*y^74+9167*x^42*y^74+28203*x^40*y^74+39475*x^38*y^74+9450*x^36*y^74" "+31469*x^34*y^74+14741*x^32*y^74+26864*x^30*y^74+40472*x^28*y^74+31868*x^26*y^74+17150*x^24*y^74+41233*x^22*y^74+32374*x^20*y^74+30579*x^18*y^74+35102*x^16*y^74+24658*x^14*y^74+25742*x^12*y^74+10871*x^10*y^74" "+11794*x^8*y^74+36341*x^6*y^74+2908*x^4*y^74+4439*x^2*y^74+13585*y^74+1992*x^56*y^72+7849*x^54*y^72+997*x^52*y^72+34763*x^50*y^72+42481*x^48*y^72+18291*x^46*y^72+12745*x^44*y^72+38278*x^42*y^72" "+31068*x^40*y^72+3497*x^38*y^72+10515*x^36*y^72+14907*x^34*y^72+13387*x^32*y^72+5141*x^30*y^72+9788*x^28*y^72+20962*x^26*y^72+33006*x^24*y^72+10499*x^22*y^72+1789*x^20*y^72+41704*x^18*y^72+24746*x^16*y^72" "+21765*x^14*y^72+354*x^12*y^72+6648*x^10*y^72+9219*x^8*y^72+731*x^6*y^72+41169*x^4*y^72+41866*x^2*y^72+41317*y^72+35081*x^58*y^70+22602*x^56*y^70+3993*x^54*y^70+8437*x^52*y^70+2179*x^50*y^70+40986*x^48*y^70" "+30573*x^46*y^70+23122*x^44*y^70+3597*x^42*y^70+19311*x^40*y^70+41243*x^38*y^70+9330*x^36*y^70+18833*x^34*y^70+32164*x^32*y^70+38779*x^30*y^70+2117*x^28*y^70+10907*x^26*y^70+20600*x^24*y^70+19707*x^22*y^70" "+4012*x^20*y^70+27726*x^18*y^70+35841*x^16*y^70+41654*x^14*y^70+40560*x^12*y^70+20228*x^10*y^70+6885*x^8*y^70+8364*x^6*y^70+16635*x^4*y^70+2443*x^2*y^70+40154*y^70+41341*x^60*y^68+10055*x^58*y^68" "+43019*x^56*y^68+33525*x^54*y^68+28275*x^52*y^68+21534*x^50*y^68+9440*x^48*y^68+27194*x^46*y^68+15015*x^44*y^68+38756*x^42*y^68+33559*x^40*y^68+39880*x^38*y^68+15511*x^36*y^68+6608*x^34*y^68+18429*x^32*y^68" "+3244*x^30*y^68+7080*x^28*y^68+39769*x^26*y^68+5047*x^24*y^68+13145*x^22*y^68+6061*x^20*y^68+16723*x^18*y^68+39231*x^16*y^68+18524*x^14*y^68+15310*x^12*y^68+29206*x^10*y^68+38853*x^8*y^68+28596*x^6*y^68" "+4059*x^4*y^68+1787*x^2*y^68+10739*y^68+12276*x^62*y^66+15439*x^60*y^66+31883*x^58*y^66+38997*x^56*y^66+35796*x^54*y^66+37920*x^52*y^66+8824*x^50*y^66+5311*x^48*y^66+36056*x^46*y^66+22397*x^44*y^66" "+36343*x^42*y^66+19931*x^40*y^66+12411*x^38*y^66+31114*x^36*y^66+17902*x^34*y^66+36119*x^32*y^66+23123*x^30*y^66+16187*x^28*y^66+15994*x^26*y^66+17114*x^24*y^66+38094*x^22*y^66+23981*x^20*y^66+38490*x^18*y^66" "+38679*x^16*y^66+32640*x^14*y^66+35580*x^12*y^66+1569*x^10*y^66+11940*x^8*y^66+33290*x^6*y^66+39873*x^4*y^66+23637*x^2*y^66+22876*y^66+16668*x^64*y^64+24005*x^62*y^64+38824*x^60*y^64+23638*x^58*y^64" "+11795*x^56*y^64+27258*x^54*y^64+39022*x^52*y^64+15959*x^50*y^64+38442*x^48*y^64+8701*x^46*y^64+33999*x^44*y^64+24110*x^42*y^64+16403*x^40*y^64+34154*x^38*y^64+42745*x^36*y^64+8702*x^34*y^64+35287*x^32*y^64" "+40038*x^30*y^64+13884*x^28*y^64+5412*x^26*y^64+609*x^24*y^64+38179*x^22*y^64+26920*x^20*y^64+36600*x^18*y^64+34683*x^16*y^64+28450*x^14*y^64+19979*x^12*y^64+19627*x^10*y^64+11316*x^8*y^64+29033*x^6*y^64" "+16195*x^4*y^64+35450*x^2*y^64+19733*y^64+19698*x^66*y^62+17076*x^64*y^62+1458*x^62*y^62+29213*x^60*y^62+111*x^58*y^62+6799*x^56*y^62+32803*x^54*y^62+21600*x^52*y^62+40301*x^50*y^62+26692*x^48*y^62" "+21702*x^46*y^62+38038*x^44*y^62+19712*x^42*y^62+3283*x^40*y^62+5074*x^38*y^62+14424*x^36*y^62+15290*x^34*y^62+42840*x^32*y^62+40294*x^30*y^62+15498*x^28*y^62+29519*x^26*y^62+7507*x^24*y^62+38218*x^22*y^62" "+12102*x^20*y^62+36024*x^18*y^62+12743*x^16*y^62+7676*x^14*y^62+27972*x^12*y^62+24770*x^10*y^62+16865*x^8*y^62+28890*x^6*y^62+33356*x^4*y^62+25101*x^2*y^62+3127*y^62+11524*x^68*y^60+17428*x^66*y^60" "+23108*x^64*y^60+32140*x^62*y^60+22553*x^60*y^60+36014*x^58*y^60+21300*x^56*y^60+21301*x^54*y^60+28446*x^52*y^60+13376*x^50*y^60+7739*x^48*y^60+1608*x^46*y^60+28303*x^44*y^60+17022*x^42*y^60+11978*x^40*y^60" "+22161*x^38*y^60+7069*x^36*y^60+24784*x^34*y^60+25360*x^32*y^60+33946*x^30*y^60+10730*x^28*y^60+11859*x^26*y^60+25411*x^24*y^60+11010*x^22*y^60+40871*x^20*y^60+38352*x^18*y^60+5524*x^16*y^60+14977*x^14*y^60" "+6767*x^12*y^60+33794*x^10*y^60+17924*x^8*y^60+37977*x^6*y^60+8160*x^4*y^60+38210*x^2*y^60+33675*y^60+1146*x^70*y^58+31287*x^68*y^58+18656*x^66*y^58+16076*x^64*y^58+30310*x^62*y^58+35030*x^60*y^58" "+14815*x^58*y^58+4250*x^56*y^58+16149*x^54*y^58+12594*x^52*y^58+30565*x^50*y^58+36291*x^48*y^58+1153*x^46*y^58+10625*x^44*y^58+18779*x^42*y^58+35948*x^40*y^58+39319*x^38*y^58+1769*x^36*y^58+11200*x^34*y^58" "+4209*x^32*y^58+22834*x^30*y^58+17576*x^28*y^58+40331*x^26*y^58+40113*x^24*y^58+30153*x^22*y^58+38508*x^20*y^58+41432*x^18*y^58+16862*x^16*y^58+7476*x^14*y^58+37514*x^12*y^58+30866*x^10*y^58+32336*x^8*y^58" "+27613*x^6*y^58+1093*x^4*y^58+25920*x^2*y^58+30109*y^58+21994*x^72*y^56+24413*x^70*y^56+36708*x^68*y^56+12098*x^66*y^56+21715*x^64*y^56+6565*x^62*y^56+5673*x^60*y^56+32603*x^58*y^56+1391*x^56*y^56" "+14072*x^54*y^56+30021*x^52*y^56+31475*x^50*y^56+11040*x^48*y^56+32066*x^46*y^56+18795*x^44*y^56+18561*x^42*y^56+17011*x^40*y^56+25549*x^38*y^56+13742*x^36*y^56+4515*x^34*y^56+36431*x^32*y^56+5815*x^30*y^56" "+28463*x^28*y^56+22206*x^26*y^56+29618*x^24*y^56+10249*x^22*y^56+8448*x^20*y^56+23731*x^18*y^56+33161*x^16*y^56+30438*x^14*y^56+8011*x^12*y^56+29169*x^10*y^56+16885*x^8*y^56+24192*x^6*y^56+16063*x^4*y^56" "+977*x^2*y^56+20180*y^56+35354*x^74*y^54+23221*x^72*y^54+12873*x^70*y^54+8833*x^68*y^54+33898*x^66*y^54+42365*x^64*y^54+42796*x^62*y^54+3965*x^60*y^54+14793*x^58*y^54+35236*x^56*y^54+32225*x^54*y^54" "+963*x^52*y^54+30495*x^50*y^54+15778*x^48*y^54+5275*x^46*y^54+39147*x^44*y^54+32615*x^42*y^54+16383*x^40*y^54+15968*x^38*y^54+303*x^36*y^54+18866*x^34*y^54+20892*x^32*y^54+14495*x^30*y^54+29228*x^28*y^54" "+8824*x^26*y^54+19746*x^24*y^54+33039*x^22*y^54+3318*x^20*y^54+17018*x^18*y^54+25286*x^16*y^54+27107*x^14*y^54+6231*x^12*y^54+28939*x^10*y^54+25698*x^8*y^54+9950*x^6*y^54+37764*x^4*y^54+37499*x^2*y^54" "+13924*y^54+24936*x^76*y^52+1784*x^74*y^52+4777*x^72*y^52+25581*x^70*y^52+32388*x^68*y^52+36282*x^66*y^52+14679*x^64*y^52+30875*x^62*y^52+23647*x^60*y^52+15900*x^58*y^52+13580*x^56*y^52+42102*x^54*y^52" "+27416*x^52*y^52+16418*x^50*y^52+3419*x^48*y^52+26654*x^46*y^52+14803*x^44*y^52+14108*x^42*y^52+27811*x^40*y^52+8305*x^38*y^52+24852*x^36*y^52+39522*x^34*y^52+22762*x^32*y^52+3736*x^30*y^52+13000*x^28*y^52" "+17297*x^26*y^52+35582*x^24*y^52+33936*x^22*y^52+25796*x^20*y^52+24536*x^18*y^52+30665*x^16*y^52+23548*x^14*y^52+24350*x^12*y^52+30376*x^10*y^52+1379*x^8*y^52+29308*x^6*y^52+12619*x^4*y^52+43019*x^2*y^52" "+4045*y^52+40821*x^78*y^50+39579*x^76*y^50+39386*x^74*y^50+21109*x^72*y^50+20753*x^70*y^50+34835*x^68*y^50+3982*x^66*y^50+2435*x^64*y^50+9859*x^62*y^50+15672*x^60*y^50+8066*x^58*y^50+32097*x^56*y^50" "+21056*x^54*y^50+22971*x^52*y^50+5053*x^50*y^50+7692*x^48*y^50+40862*x^46*y^50+34315*x^44*y^50+31567*x^42*y^50+2656*x^40*y^50+41426*x^38*y^50+38114*x^36*y^50+11216*x^34*y^50+37186*x^32*y^50+25571*x^30*y^50" "+15277*x^28*y^50+29074*x^26*y^50+4122*x^24*y^50+9793*x^22*y^50+3765*x^20*y^50+32150*x^18*y^50+37040*x^16*y^50+37117*x^14*y^50+25423*x^12*y^50+42151*x^10*y^50+20310*x^8*y^50+11359*x^6*y^50+5780*x^4*y^50" "+17431*x^2*y^50+37752*y^50+1261*x^80*y^48+29556*x^78*y^48+18109*x^76*y^48+24457*x^74*y^48+29308*x^72*y^48+24596*x^70*y^48+24759*x^68*y^48+34954*x^66*y^48+4323*x^64*y^48+5671*x^62*y^48+23949*x^60*y^48" "+9231*x^58*y^48+9259*x^56*y^48+21135*x^54*y^48+461*x^52*y^48+26234*x^50*y^48+22548*x^48*y^48+11931*x^46*y^48+27419*x^44*y^48+9235*x^42*y^48+31268*x^40*y^48+35134*x^38*y^48+42462*x^36*y^48+30197*x^34*y^48" "+40139*x^32*y^48+30148*x^30*y^48+25205*x^28*y^48+18621*x^26*y^48+3359*x^24*y^48+18374*x^22*y^48+13953*x^20*y^48+6730*x^18*y^48+6538*x^16*y^48+19375*x^14*y^48+38459*x^12*y^48+19761*x^10*y^48+41692*x^8*y^48" "+41909*x^6*y^48+16383*x^4*y^48+42286*x^2*y^48+30118*y^48+14689*x^82*y^46+41191*x^80*y^46+21181*x^78*y^46+9200*x^76*y^46+7039*x^74*y^46+37585*x^72*y^46+38206*x^70*y^46+19158*x^68*y^46+25276*x^66*y^46" "+24661*x^64*y^46+41619*x^62*y^46+37541*x^60*y^46+1433*x^58*y^46+5648*x^56*y^46+21510*x^54*y^46+11039*x^52*y^46+12901*x^50*y^46+3458*x^48*y^46+40390*x^46*y^46+15314*x^44*y^46+8428*x^42*y^46+33075*x^40*y^46" "+36521*x^38*y^46+16431*x^36*y^46+38665*x^34*y^46+33507*x^32*y^46+42213*x^30*y^46+1737*x^28*y^46+6710*x^26*y^46+30716*x^24*y^46+27264*x^22*y^46+39638*x^20*y^46+22602*x^18*y^46+10239*x^16*y^46+3066*x^14*y^46" "+40086*x^12*y^46+37827*x^10*y^46+38184*x^8*y^46+203*x^6*y^46+15494*x^4*y^46+26977*x^2*y^46+1615*y^46+28351*x^84*y^44+27358*x^82*y^44+23857*x^80*y^44+433*x^78*y^44+21917*x^76*y^44+5638*x^74*y^44" "+35642*x^72*y^44+35617*x^70*y^44+37727*x^68*y^44+7124*x^66*y^44+5920*x^64*y^44+16726*x^62*y^44+34126*x^60*y^44+8801*x^58*y^44+25912*x^56*y^44+21638*x^54*y^44+17409*x^52*y^44+29730*x^50*y^44+22218*x^48*y^44" "+39493*x^46*y^44+36436*x^44*y^44+17151*x^42*y^44+24069*x^40*y^44+14182*x^38*y^44+22962*x^36*y^44+24942*x^34*y^44+39864*x^32*y^44+1907*x^30*y^44+16335*x^28*y^44+9842*x^26*y^44+24840*x^24*y^44+9677*x^22*y^44" "+7641*x^20*y^44+5261*x^18*y^44+15301*x^16*y^44+1255*x^14*y^44+15813*x^12*y^44+3359*x^10*y^44+29771*x^8*y^44+38196*x^6*y^44+26499*x^4*y^44+42471*x^2*y^44+4510*y^44+13720*x^86*y^42+35086*x^84*y^42" "+39746*x^82*y^42+24554*x^80*y^42+13497*x^78*y^42+21512*x^76*y^42+28496*x^74*y^42+33195*x^72*y^42+24374*x^70*y^42+17225*x^68*y^42+2548*x^66*y^42+30586*x^64*y^42+14558*x^62*y^42+35653*x^60*y^42+34927*x^58*y^42" "+26802*x^56*y^42+1767*x^54*y^42+6722*x^52*y^42+40763*x^50*y^42+8138*x^48*y^42+13443*x^46*y^42+3411*x^44*y^42+14630*x^42*y^42+24003*x^40*y^42+30536*x^38*y^42+14290*x^36*y^42+2599*x^34*y^42+17099*x^32*y^42" "+7740*x^30*y^42+34544*x^28*y^42+34232*x^26*y^42+1799*x^24*y^42+3607*x^22*y^42+34281*x^20*y^42+5536*x^18*y^42+23289*x^16*y^42+12791*x^14*y^42+17851*x^12*y^42+9546*x^10*y^42+34485*x^8*y^42+7704*x^6*y^42" "+32670*x^4*y^42+42637*x^2*y^42+16577*y^42+28643*x^88*y^40+4201*x^86*y^40+21750*x^84*y^40+41624*x^82*y^40+249*x^80*y^40+16557*x^78*y^40+3494*x^76*y^40+11840*x^74*y^40+16961*x^72*y^40+15768*x^70*y^40" "+22448*x^68*y^40+34243*x^66*y^40+29527*x^64*y^40+38081*x^62*y^40+30103*x^60*y^40+12648*x^58*y^40+3076*x^56*y^40+40617*x^54*y^40+12652*x^52*y^40+42343*x^50*y^40+29129*x^48*y^40+40146*x^46*y^40+28836*x^44*y^40" "+31408*x^42*y^40+9713*x^40*y^40+8423*x^38*y^40+12347*x^36*y^40+28470*x^34*y^40+24078*x^32*y^40+33694*x^30*y^40+26159*x^28*y^40+318*x^26*y^40+7841*x^24*y^40+25575*x^22*y^40+25188*x^20*y^40+18176*x^18*y^40" "+22443*x^16*y^40+24241*x^14*y^40+37129*x^12*y^40+25614*x^10*y^40+11760*x^8*y^40+10320*x^6*y^40+29531*x^4*y^40+16109*x^2*y^40+7536*y^40+2062*x^90*y^38+26752*x^88*y^38+29883*x^86*y^38+29763*x^84*y^38" "+9843*x^82*y^38+9784*x^80*y^38+3344*x^78*y^38+30316*x^76*y^38+8367*x^74*y^38+5696*x^72*y^38+1180*x^70*y^38+29257*x^68*y^38+33396*x^66*y^38+9929*x^64*y^38+39519*x^62*y^38+3398*x^60*y^38+17794*x^58*y^38" "+1568*x^56*y^38+12037*x^54*y^38+24340*x^52*y^38+42509*x^50*y^38+37396*x^48*y^38+33850*x^46*y^38+12758*x^44*y^38+15386*x^42*y^38+17333*x^40*y^38+5474*x^38*y^38+17425*x^36*y^38+39133*x^34*y^38+13217*x^32*y^38" "+29242*x^30*y^38+1170*x^28*y^38+7817*x^26*y^38+3141*x^24*y^38+18776*x^22*y^38+6245*x^20*y^38+12507*x^18*y^38+35604*x^16*y^38+20990*x^14*y^38+3496*x^12*y^38+31995*x^10*y^38+7575*x^8*y^38+30688*x^6*y^38" "+11272*x^4*y^38+1806*x^2*y^38+34837*y^38+4301*x^92*y^36+16466*x^90*y^36+27117*x^88*y^36+39011*x^86*y^36+23105*x^84*y^36+37032*x^82*y^36+30001*x^80*y^36+31070*x^78*y^36+27578*x^76*y^36+14337*x^74*y^36" "+10891*x^72*y^36+18543*x^70*y^36+3050*x^68*y^36+1802*x^66*y^36+40914*x^64*y^36+23184*x^62*y^36+21058*x^60*y^36+4717*x^58*y^36+14097*x^56*y^36+7724*x^54*y^36+26213*x^52*y^36+35211*x^50*y^36+41999*x^48*y^36" "+11769*x^46*y^36+31308*x^44*y^36+26901*x^42*y^36+19700*x^40*y^36+31565*x^38*y^36+11366*x^36*y^36+7643*x^34*y^36+26178*x^32*y^36+37577*x^30*y^36+37992*x^28*y^36+4536*x^26*y^36+634*x^24*y^36+37784*x^22*y^36" "+7963*x^20*y^36+12327*x^18*y^36+15837*x^16*y^36+21084*x^14*y^36+33837*x^12*y^36+21234*x^10*y^36+35492*x^8*y^36+35354*x^6*y^36+6931*x^4*y^36+21331*x^2*y^36+241*y^36+23258*x^94*y^34+24353*x^92*y^34" "+33854*x^90*y^34+19904*x^88*y^34+16134*x^86*y^34+5133*x^84*y^34+34955*x^82*y^34+5892*x^80*y^34+7191*x^78*y^34+16055*x^76*y^34+41239*x^74*y^34+23260*x^72*y^34+31526*x^70*y^34+26991*x^68*y^34+20924*x^66*y^34" "+10823*x^64*y^34+7717*x^62*y^34+4178*x^60*y^34+22750*x^58*y^34+6182*x^56*y^34+13452*x^54*y^34+18368*x^52*y^34+41383*x^50*y^34+22450*x^48*y^34+16720*x^46*y^34+34208*x^44*y^34+19188*x^42*y^34+24090*x^40*y^34" "+4711*x^38*y^34+27289*x^36*y^34+41850*x^34*y^34+27115*x^32*y^34+34653*x^30*y^34+23194*x^28*y^34+32775*x^26*y^34+25616*x^24*y^34+6192*x^22*y^34+10665*x^20*y^34+5200*x^18*y^34+5135*x^16*y^34+22010*x^14*y^34" "+5447*x^12*y^34+33334*x^10*y^34+28155*x^8*y^34+6957*x^6*y^34+41099*x^4*y^34+43042*x^2*y^34+9705*y^34+28554*x^96*y^32+14891*x^94*y^32+38244*x^92*y^32+18164*x^90*y^32+31532*x^88*y^32+2827*x^86*y^32" "+25378*x^84*y^32+41680*x^82*y^32+3102*x^80*y^32+34074*x^78*y^32+17444*x^76*y^32+31896*x^74*y^32+21439*x^72*y^32+18439*x^70*y^32+42260*x^68*y^32+22330*x^66*y^32+28152*x^64*y^32+36359*x^62*y^32+36146*x^60*y^32" "+39069*x^58*y^32+42121*x^56*y^32+17124*x^54*y^32+15457*x^52*y^32+4838*x^50*y^32+35776*x^48*y^32+38288*x^46*y^32+12621*x^44*y^32+35660*x^42*y^32+37365*x^40*y^32+43038*x^38*y^32+5298*x^36*y^32+37617*x^34*y^32" "+5264*x^32*y^32+13100*x^30*y^32+22400*x^28*y^32+13246*x^26*y^32+32660*x^24*y^32+27424*x^22*y^32+19712*x^20*y^32+3951*x^18*y^32+33046*x^16*y^32+37408*x^14*y^32+6383*x^12*y^32+25114*x^10*y^32+23719*x^8*y^32" "+20292*x^6*y^32+1210*x^4*y^32+21708*x^2*y^32+2196*y^32+41751*x^98*y^30+3506*x^96*y^30+22624*x^94*y^30+40102*x^92*y^30+41008*x^90*y^30+36366*x^88*y^30+34105*x^86*y^30+7204*x^84*y^30+38649*x^82*y^30" "+21979*x^80*y^30+11389*x^78*y^30+30974*x^76*y^30+16415*x^74*y^30+15920*x^72*y^30+5449*x^70*y^30+28008*x^68*y^30+37722*x^66*y^30+33222*x^64*y^30+13753*x^62*y^30+7207*x^60*y^30+32550*x^58*y^30+33024*x^56*y^30" "+10586*x^54*y^30+42555*x^52*y^30+17793*x^50*y^30+16663*x^48*y^30+31694*x^46*y^30+1299*x^44*y^30+18112*x^42*y^30+2711*x^40*y^30+38258*x^38*y^30+28347*x^36*y^30+34835*x^34*y^30+20163*x^32*y^30+22401*x^30*y^30" "+33934*x^28*y^30+23924*x^26*y^30+41753*x^24*y^30+31379*x^22*y^30+21808*x^20*y^30+1139*x^18*y^30+11347*x^16*y^30+32849*x^14*y^30+9474*x^12*y^30+38854*x^10*y^30+18253*x^8*y^30+38218*x^6*y^30+8810*x^4*y^30" "+2999*x^2*y^30+33198*y^30+20087*x^100*y^28+13657*x^98*y^28+14744*x^96*y^28+19054*x^94*y^28+10779*x^92*y^28+8560*x^90*y^28+17029*x^88*y^28+18083*x^86*y^28+599*x^84*y^28+873*x^82*y^28+12432*x^80*y^28" "+34808*x^78*y^28+29826*x^76*y^28+4437*x^74*y^28+11650*x^72*y^28+31649*x^70*y^28+19951*x^68*y^28+27253*x^66*y^28+33030*x^64*y^28+15058*x^62*y^28+12375*x^60*y^28+12566*x^58*y^28+31955*x^56*y^28+12990*x^54*y^28" "+13509*x^52*y^28+16851*x^50*y^28+30596*x^48*y^28+6762*x^46*y^28+39496*x^44*y^28+9989*x^42*y^28+29136*x^40*y^28+42573*x^38*y^28+23967*x^36*y^28+36766*x^34*y^28+21928*x^32*y^28+16864*x^30*y^28+33699*x^28*y^28" "+7712*x^26*y^28+23043*x^24*y^28+42991*x^22*y^28+36183*x^20*y^28+28799*x^18*y^28+16223*x^16*y^28+35358*x^14*y^28+24724*x^12*y^28+389*x^10*y^28+3509*x^8*y^28+24611*x^6*y^28+27165*x^4*y^28+21064*x^2*y^28" "+21393*y^28+39670*x^102*y^26+42143*x^100*y^26+38882*x^98*y^26+12003*x^96*y^26+24085*x^94*y^26+2406*x^92*y^26+6013*x^90*y^26+12013*x^88*y^26+1128*x^86*y^26+10893*x^84*y^26+19101*x^82*y^26+5754*x^80*y^26" "+40597*x^78*y^26+20885*x^76*y^26+37810*x^74*y^26+17637*x^72*y^26+6921*x^70*y^26+10241*x^68*y^26+20318*x^66*y^26+21067*x^64*y^26+17577*x^62*y^26+2010*x^60*y^26+28916*x^58*y^26+6931*x^56*y^26+14528*x^54*y^26" "+5437*x^52*y^26+2502*x^50*y^26+5572*x^48*y^26+20344*x^46*y^26+35319*x^44*y^26+42510*x^42*y^26+16831*x^40*y^26+8200*x^38*y^26+20786*x^36*y^26+27850*x^34*y^26+9182*x^32*y^26+17561*x^30*y^26+36330*x^28*y^26" "+556*x^26*y^26+42804*x^24*y^26+35781*x^22*y^26+34582*x^20*y^26+42298*x^18*y^26+7607*x^16*y^26+23592*x^14*y^26+6481*x^12*y^26+20600*x^10*y^26+20494*x^8*y^26+20466*x^6*y^26+37630*x^4*y^26+32594*x^2*y^26" "+32583*y^26+34806*x^104*y^24+7080*x^102*y^24+35489*x^100*y^24+11472*x^98*y^24+5792*x^96*y^24+1173*x^94*y^24+29521*x^92*y^24+28230*x^90*y^24+392*x^88*y^24+42071*x^86*y^24+20630*x^84*y^24+5510*x^82*y^24" "+35541*x^80*y^24+18785*x^78*y^24+6088*x^76*y^24+21840*x^74*y^24+14778*x^72*y^24+40896*x^70*y^24+4701*x^68*y^24+6915*x^66*y^24+29242*x^64*y^24+7552*x^62*y^24+1614*x^60*y^24+3222*x^58*y^24+7828*x^56*y^24" "+40503*x^54*y^24+432*x^52*y^24+27544*x^50*y^24+11292*x^48*y^24+39827*x^46*y^24+16066*x^44*y^24+4515*x^42*y^24+10347*x^40*y^24+11618*x^38*y^24+1208*x^36*y^24+30279*x^34*y^24+7375*x^32*y^24+35158*x^30*y^24" "+38636*x^28*y^24+16362*x^26*y^24+34500*x^24*y^24+35142*x^22*y^24+24967*x^20*y^24+15858*x^18*y^24+12076*x^16*y^24+15623*x^14*y^24+15411*x^12*y^24+22432*x^10*y^24+23353*x^8*y^24+15209*x^6*y^24+7329*x^4*y^24" "+7587*x^2*y^24+33148*y^24+3379*x^106*y^22+27532*x^104*y^22+38717*x^102*y^22+3622*x^100*y^22+15202*x^98*y^22+5472*x^96*y^22+1725*x^94*y^22+35520*x^92*y^22+30742*x^90*y^22+28586*x^88*y^22+8728*x^86*y^22" "+38664*x^84*y^22+42854*x^82*y^22+6519*x^80*y^22+29152*x^78*y^22+39051*x^76*y^22+30056*x^74*y^22+22650*x^72*y^22+17814*x^70*y^22+42846*x^68*y^22+29259*x^66*y^22+24720*x^64*y^22+40018*x^62*y^22+6990*x^60*y^22" "+18972*x^58*y^22+15697*x^56*y^22+17442*x^54*y^22+25772*x^52*y^22+25660*x^50*y^22+22640*x^48*y^22+7122*x^46*y^22+1968*x^44*y^22+16339*x^42*y^22+22176*x^40*y^22+18823*x^38*y^22+19388*x^36*y^22+38347*x^34*y^22" "+36810*x^32*y^22+30240*x^30*y^22+42919*x^28*y^22+10096*x^26*y^22+28351*x^24*y^22+27961*x^22*y^22+262*x^20*y^22+18482*x^18*y^22+15038*x^16*y^22+38007*x^14*y^22+13093*x^12*y^22+15923*x^10*y^22+15905*x^8*y^22" "+19270*x^6*y^22+31246*x^4*y^22+2077*x^2*y^22+12208*y^22+15389*x^108*y^20+9097*x^106*y^20+15481*x^104*y^20+22559*x^102*y^20+12450*x^100*y^20+22179*x^98*y^20+9862*x^96*y^20+38084*x^94*y^20+24174*x^92*y^20" "+766*x^90*y^20+10892*x^88*y^20+32551*x^86*y^20+3311*x^84*y^20+29836*x^82*y^20+27304*x^80*y^20+13545*x^78*y^20+42106*x^76*y^20+20859*x^74*y^20+40164*x^72*y^20+38174*x^70*y^20+32709*x^68*y^20+40765*x^66*y^20" "+33707*x^64*y^20+18031*x^62*y^20+39480*x^60*y^20+16638*x^58*y^20+40832*x^56*y^20+30693*x^54*y^20+26984*x^52*y^20+30680*x^50*y^20+3895*x^48*y^20+24426*x^46*y^20+17711*x^44*y^20+24628*x^42*y^20+29371*x^40*y^20" "+10215*x^38*y^20+1056*x^36*y^20+31850*x^34*y^20+30855*x^32*y^20+1402*x^30*y^20+175*x^28*y^20+7565*x^26*y^20+26411*x^24*y^20+40257*x^22*y^20+42403*x^20*y^20+42595*x^18*y^20+37709*x^16*y^20+11885*x^14*y^20" "+40731*x^12*y^20+30038*x^10*y^20+24318*x^8*y^20+27721*x^6*y^20+17787*x^4*y^20+27117*x^2*y^20+31138*y^20+8742*x^110*y^18+28996*x^108*y^18+8875*x^106*y^18+42694*x^104*y^18+17582*x^102*y^18+11884*x^100*y^18" "+26651*x^98*y^18+16472*x^96*y^18+9415*x^94*y^18+31341*x^92*y^18+4589*x^90*y^18+27171*x^88*y^18+6477*x^86*y^18+39756*x^84*y^18+5166*x^82*y^18+15388*x^80*y^18+15043*x^78*y^18+633*x^76*y^18+15006*x^74*y^18" "+13178*x^72*y^18+4280*x^70*y^18+24142*x^68*y^18+40850*x^66*y^18+21129*x^64*y^18+1277*x^62*y^18+5586*x^60*y^18+10451*x^58*y^18+18829*x^56*y^18+29523*x^54*y^18+26485*x^52*y^18+2403*x^50*y^18+23764*x^48*y^18" "+22137*x^46*y^18+24536*x^44*y^18+41504*x^42*y^18+36081*x^40*y^18+36187*x^38*y^18+21187*x^36*y^18+36012*x^34*y^18+27868*x^32*y^18+13055*x^30*y^18+23148*x^28*y^18+4982*x^26*y^18+14351*x^24*y^18+21985*x^22*y^18" "+28224*x^20*y^18+41085*x^18*y^18+41144*x^16*y^18+21078*x^14*y^18+6468*x^12*y^18+29312*x^10*y^18+20535*x^8*y^18+6845*x^6*y^18+33572*x^4*y^18+21429*x^2*y^18+15252*y^18+7189*x^112*y^16+17449*x^110*y^16" "+33417*x^108*y^16+23815*x^106*y^16+9716*x^104*y^16+10978*x^102*y^16+3686*x^100*y^16+18181*x^98*y^16+23916*x^96*y^16+27090*x^94*y^16+31252*x^92*y^16+4721*x^90*y^16+751*x^88*y^16+35594*x^86*y^16+29977*x^84*y^16" "+35976*x^82*y^16+18735*x^80*y^16+35323*x^78*y^16+40532*x^76*y^16+12615*x^74*y^16+31708*x^72*y^16+10545*x^70*y^16+17844*x^68*y^16+6350*x^66*y^16+6904*x^64*y^16+19526*x^62*y^16+24150*x^60*y^16+33459*x^58*y^16" "+22533*x^56*y^16+5902*x^54*y^16+12322*x^52*y^16+2899*x^50*y^16+5658*x^48*y^16+20010*x^46*y^16+24805*x^44*y^16+42523*x^42*y^16+5113*x^40*y^16+42142*x^38*y^16+10954*x^36*y^16+1895*x^34*y^16+17233*x^32*y^16" "+18530*x^30*y^16+18512*x^28*y^16+9802*x^26*y^16+40745*x^24*y^16+42941*x^22*y^16+10950*x^20*y^16+36609*x^18*y^16+9187*x^16*y^16+41118*x^14*y^16+40848*x^12*y^16+14323*x^10*y^16+20057*x^8*y^16+29018*x^6*y^16" "+16678*x^4*y^16+24873*x^2*y^16+5157*y^16+12066*x^114*y^14+38835*x^112*y^14+17848*x^110*y^14+9037*x^108*y^14+26019*x^106*y^14+1534*x^104*y^14+17609*x^102*y^14+8795*x^100*y^14+37427*x^98*y^14+37473*x^96*y^14" "+20682*x^94*y^14+36897*x^92*y^14+23669*x^90*y^14+23150*x^88*y^14+3430*x^86*y^14+12988*x^84*y^14+41226*x^82*y^14+9247*x^80*y^14+6749*x^78*y^14+9605*x^76*y^14+7097*x^74*y^14+8834*x^72*y^14+14409*x^70*y^14" "+33978*x^68*y^14+14602*x^66*y^14+25010*x^64*y^14+14797*x^62*y^14+20509*x^60*y^14+20790*x^58*y^14+40039*x^56*y^14+41843*x^54*y^14+16373*x^52*y^14+3400*x^50*y^14+1770*x^48*y^14+6158*x^46*y^14+563*x^44*y^14" "+18954*x^42*y^14+32126*x^40*y^14+37681*x^38*y^14+5538*x^36*y^14+17845*x^34*y^14+6041*x^32*y^14+1017*x^30*y^14+5208*x^28*y^14+25388*x^26*y^14+19739*x^24*y^14+9119*x^22*y^14+29651*x^20*y^14+30801*x^18*y^14" "+32064*x^16*y^14+19656*x^14*y^14+21875*x^12*y^14+34932*x^10*y^14+15786*x^8*y^14+23952*x^6*y^14+38212*x^4*y^14+40822*x^2*y^14+15920*y^14+33741*x^116*y^12+35681*x^114*y^12+2669*x^112*y^12+11408*x^110*y^12" "+37403*x^108*y^12+12197*x^106*y^12+3364*x^104*y^12+23514*x^102*y^12+16044*x^100*y^12+39266*x^98*y^12+1570*x^96*y^12+35221*x^94*y^12+38817*x^92*y^12+42632*x^90*y^12+8943*x^88*y^12+34152*x^86*y^12" "+32133*x^84*y^12+15451*x^82*y^12+38058*x^80*y^12+10723*x^78*y^12+12151*x^76*y^12+39697*x^74*y^12+2983*x^72*y^12+9825*x^70*y^12+24093*x^68*y^12+16563*x^66*y^12+18601*x^64*y^12+17118*x^62*y^12+23325*x^60*y^12" "+25238*x^58*y^12+20856*x^56*y^12+27627*x^54*y^12+27311*x^52*y^12+11532*x^50*y^12+14594*x^48*y^12+42761*x^46*y^12+22542*x^44*y^12+18903*x^42*y^12+2028*x^40*y^12+42931*x^38*y^12+28512*x^36*y^12+23484*x^34*y^12" "+35985*x^32*y^12+7572*x^30*y^12+39725*x^28*y^12+25321*x^26*y^12+28593*x^24*y^12+15735*x^22*y^12+23728*x^20*y^12+42662*x^18*y^12+8593*x^16*y^12+12726*x^14*y^12+36115*x^10*y^12+38197*x^8*y^12+27870*x^6*y^12" "+30056*x^4*y^12+22856*x^2*y^12+761*y^12+38458*x^118*y^10+35378*x^116*y^10+38852*x^114*y^10+13844*x^112*y^10+15204*x^110*y^10+14179*x^108*y^10+33524*x^106*y^10+26521*x^104*y^10+7142*x^102*y^10+18886*x^100*y^10" "+41153*x^98*y^10+31816*x^96*y^10+27233*x^94*y^10+11280*x^92*y^10+38975*x^90*y^10+16890*x^88*y^10+34763*x^86*y^10+7480*x^84*y^10+25699*x^82*y^10+30223*x^80*y^10+6215*x^78*y^10+19166*x^76*y^10+15179*x^74*y^10" "+39918*x^72*y^10+11439*x^70*y^10+7345*x^68*y^10+28333*x^66*y^10+15843*x^64*y^10+22507*x^62*y^10+37591*x^60*y^10+21942*x^58*y^10+7369*x^56*y^10+16147*x^54*y^10+1147*x^52*y^10+22755*x^50*y^10+35696*x^48*y^10" "+34882*x^46*y^10+6718*x^44*y^10+36965*x^42*y^10+30741*x^40*y^10+38124*x^38*y^10+13434*x^36*y^10+40104*x^34*y^10+23924*x^32*y^10+34197*x^30*y^10+18623*x^28*y^10+8307*x^26*y^10+37098*x^24*y^10+24902*x^22*y^10" "+17933*x^20*y^10+33381*x^18*y^10+10499*x^16*y^10+33941*x^14*y^10+1108*x^12*y^10+5416*x^10*y^10+21260*x^8*y^10+40985*x^6*y^10+35986*x^4*y^10+39615*x^2*y^10+5651*y^10+30041*x^120*y^8+20323*x^118*y^8" "+13296*x^116*y^8+32818*x^114*y^8+27827*x^112*y^8+38475*x^110*y^8+22500*x^108*y^8+26645*x^106*y^8+8018*x^104*y^8+18372*x^102*y^8+22394*x^100*y^8+589*x^98*y^8+1632*x^96*y^8+21631*x^94*y^8+11765*x^92*y^8" "+4290*x^90*y^8+13828*x^88*y^8+23526*x^86*y^8+38030*x^84*y^8+36727*x^82*y^8+23680*x^80*y^8+13219*x^78*y^8+32793*x^76*y^8+9091*x^74*y^8+34849*x^72*y^8+696*x^70*y^8+24056*x^68*y^8+37615*x^66*y^8+4486*x^64*y^8" "+32407*x^62*y^8+18376*x^60*y^8+25742*x^58*y^8+38738*x^56*y^8+13582*x^54*y^8+7118*x^52*y^8+9158*x^50*y^8+28740*x^48*y^8+21773*x^46*y^8+16265*x^44*y^8+9151*x^42*y^8+33024*x^40*y^8+17536*x^38*y^8+31202*x^36*y^8" "+13404*x^34*y^8+16483*x^32*y^8+12809*x^30*y^8+5052*x^28*y^8+27764*x^26*y^8+20578*x^24*y^8+21706*x^22*y^8+3664*x^20*y^8+14186*x^18*y^8+7764*x^16*y^8+42913*x^14*y^8+16118*x^12*y^8+41426*x^10*y^8+41792*x^8*y^8" "+2602*x^6*y^8+12193*x^4*y^8+32121*x^2*y^8+42802*y^8+26172*x^122*y^6+14420*x^120*y^6+8330*x^118*y^6+33509*x^116*y^6+34141*x^114*y^6+4543*x^112*y^6+22477*x^110*y^6+30910*x^108*y^6+12525*x^106*y^6" "+21019*x^104*y^6+24156*x^102*y^6+29781*x^100*y^6+41441*x^98*y^6+18727*x^96*y^6+36526*x^94*y^6+11426*x^92*y^6+39169*x^90*y^6+13590*x^88*y^6+36433*x^86*y^6+24896*x^84*y^6+41747*x^82*y^6+10792*x^80*y^6" "+2403*x^78*y^6+26505*x^76*y^6+24597*x^74*y^6+23260*x^72*y^6+9148*x^70*y^6+1137*x^68*y^6+34203*x^66*y^6+30374*x^64*y^6+4565*x^62*y^6+135*x^60*y^6+38731*x^58*y^6+16962*x^56*y^6+27791*x^54*y^6+24230*x^52*y^6" "+34876*x^50*y^6+39807*x^48*y^6+4728*x^46*y^6+2024*x^44*y^6+38003*x^42*y^6+10398*x^40*y^6+35925*x^38*y^6+36133*x^36*y^6+40238*x^34*y^6+6214*x^32*y^6+9511*x^30*y^6+5972*x^28*y^6+24583*x^26*y^6+31054*x^24*y^6" "+25112*x^22*y^6+26875*x^20*y^6+2973*x^18*y^6+36493*x^16*y^6+27271*x^14*y^6+34812*x^12*y^6+33099*x^10*y^6+6679*x^8*y^6+20584*x^6*y^6+9064*x^4*y^6+8136*x^2*y^6+14396*y^6+22127*x^124*y^4+20019*x^122*y^4" "+18592*x^120*y^4+30874*x^118*y^4+15132*x^116*y^4+29281*x^114*y^4+22980*x^112*y^4+10864*x^110*y^4+6007*x^108*y^4+4936*x^106*y^4+23939*x^104*y^4+31836*x^102*y^4+12108*x^100*y^4+11572*x^98*y^4+42747*x^96*y^4" "+30049*x^94*y^4+17193*x^92*y^4+42415*x^90*y^4+30307*x^88*y^4+40790*x^86*y^4+23322*x^84*y^4+15122*x^82*y^4+2037*x^80*y^4+27159*x^78*y^4+17150*x^76*y^4+33813*x^74*y^4+40205*x^72*y^4+9556*x^70*y^4+24621*x^68*y^4" "+15083*x^66*y^4+22083*x^64*y^4+3746*x^62*y^4+38976*x^60*y^4+6279*x^58*y^4+6555*x^56*y^4+27196*x^54*y^4+29138*x^52*y^4+18182*x^50*y^4+21201*x^48*y^4+23276*x^46*y^4+24659*x^44*y^4+40263*x^42*y^4+27455*x^40*y^4" "+8998*x^38*y^4+10807*x^36*y^4+6260*x^34*y^4+911*x^32*y^4+11985*x^30*y^4+31164*x^28*y^4+27578*x^26*y^4+37188*x^24*y^4+6725*x^22*y^4+34708*x^20*y^4+14058*x^18*y^4+17176*x^16*y^4+25971*x^14*y^4+9296*x^12*y^4" "+12083*x^10*y^4+42019*x^8*y^4+32011*x^6*y^4+24665*x^4*y^4+40332*x^2*y^4+34190*y^4+9940*x^126*y^2+7922*x^124*y^2+710*x^122*y^2+28677*x^120*y^2+29200*x^118*y^2+16915*x^116*y^2+17106*x^114*y^2+14802*x^112*y^2" "+7567*x^110*y^2+3533*x^108*y^2+16621*x^106*y^2+37877*x^104*y^2+7956*x^102*y^2+16344*x^100*y^2+36978*x^98*y^2+39545*x^96*y^2+37434*x^94*y^2+5249*x^92*y^2+39842*x^90*y^2+23580*x^88*y^2+40902*x^86*y^2" "+527*x^84*y^2+33256*x^82*y^2+31430*x^80*y^2+6739*x^78*y^2+42179*x^76*y^2+16431*x^74*y^2+6976*x^72*y^2+37894*x^70*y^2+20000*x^68*y^2+29973*x^66*y^2+31695*x^64*y^2+41973*x^62*y^2+2479*x^60*y^2+33448*x^58*y^2" "+6155*x^56*y^2+24489*x^54*y^2+7764*x^52*y^2+6935*x^50*y^2+32788*x^48*y^2+13858*x^46*y^2+19696*x^44*y^2+24391*x^42*y^2+34902*x^40*y^2+27564*x^38*y^2+24627*x^36*y^2+41873*x^34*y^2+39978*x^32*y^2+31220*x^30*y^2" "+16078*x^28*y^2+21206*x^26*y^2+4924*x^24*y^2+24107*x^22*y^2+2642*x^20*y^2+9942*x^18*y^2+32635*x^16*y^2+18223*x^14*y^2+21946*x^12*y^2+17452*x^10*y^2+22441*x^8*y^2+38749*x^6*y^2+400*x^4*y^2+12301*x^2*y^2" "+31143*y^2+13269*x^128+38886*x^126+25434*x^124+39701*x^122+1803*x^120+29220*x^118+36779*x^116+3974*x^114+7911*x^112+2699*x^110+13784*x^108+6518*x^106+1982*x^104+5676*x^102+40582*x^100+34026*x^98+20847*x^96" "+9317*x^94+3786*x^92+6303*x^90+35840*x^88+1260*x^86+7194*x^84+11865*x^82+37487*x^80+39482*x^78+3463*x^76+39442*x^74+2094*x^72+28384*x^70+8368*x^68+11182*x^66+22493*x^64+38408*x^62+5132*x^60+40665*x^58" "+17337*x^56+16314*x^54+12887*x^52+30723*x^50+467*x^48+19550*x^46+4535*x^44+14740*x^42+30512*x^40+16004*x^38+18242*x^36+21135*x^34+31930*x^32+9145*x^30+13045*x^28+37859*x^26+4891*x^24+15931*x^22+33896*x^20" "+22053*x^18+19758*x^16+29918*x^14+22856*x^12+42701*x^10+12577*x^8+40627*x^6+21210*x^4+32848*x^2+39447)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #2: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(39739*z^9*x^10*y^7*s^9+33115*z^9*x^11*y^6*s^9+33115*z^10*x^10*y^6*s^9+33115*z^9*x^12*y^5*s^9+23179*z^10*x^11*y^5*s^9+33115*z^11*x^10*y^5*s^9+39739*z^9*x^13*y^4*s^9+33115*z^10*x^12*y^4*s^9+33115*z^11*x^11*y^4*s^9+39739*z^12*x^10*y^4*s^9+41743*x*y^13*s^8+39127*x^2*y^12*s^8+39127*z*x*y^12*s^8+39127*x^3*y^11*s^8+35203*z*x^2*y^11*s^8+39127*z^2*x*y^11*s^8+41743*x^4*y^10*s^8+39127*z*x^3*y^10*s^8+39127*z^2*x^2*y^10*s^8+41743*z^3*x*y^10*s^8+21629*z^6*x*y^9*s^7+21836*z^6*x^2*y^8*s^7+21836*z^7*x*y^8*s^7+21836*z^6*x^3*y^7*s^7+621*z^7*x^2*y^7*s^7+21836*z^8*x*y^7*s^7+21629*z^6*x^4*y^6*s^7+21836*z^7*x^3*y^6*s^7+21836*z^8*x^2*y^6*s^7+21629*z^9*x*y^6*s^7+16873*z^8*x^3*y^12*s^6+7568*z^8*x^4*y^11*s^6+7568*z^9*x^3*y^11*s^6+7568*z^8*x^5*y^10*s^6+15136*z^9*x^4*y^10*s^6+7568*z^10*x^3*y^10*s^6+16873*z^8*x^6*y^9*s^6+7568*z^9*x^5*y^9*s^6+7568*z^10*x^4*y^9*s^6+16873*z^11*x^3*y^9*s^6+24116*z^6*x*y^11*s^5+29297*z^6*x^2*y^10*s^5+15295*z^7*x*y^10*s^5+29297*z^6*x^3*y^9*s^5+16588*z^7*x^2*y^9*s^5+30342*z^8*x*y^9*s^5+24116*z^6*x^4*y^8*s^5+30342*z^7*x^3*y^8*s^5+31387*z^8*x^2*y^8*s^5+25161*z^9*x*y^8*s^5+29049*z^7*x^4*y^7*s^5+1045*z^8*x^3*y^7*s^5+1045*z^9*x^2*y^7*s^5+29049*z^10*x*y^7*s^5+13845*z^6*x^2*y^13*s^3+41535*z^6*x^3*y^12*s^3+41535*z^7*x^2*y^12*s^3+41535*z^6*x^4*y^11*s^3+40019*z^7*x^3*y^11*s^3+41535*z^8*x^2*y^11*s^3+13845*z^6*x^5*y^10*s^3+41535*z^7*x^4*y^10*s^3+41535*z^8*x^3*y^10*s^3+13845*z^9*x^2*y^10*s^3+8506*z*x^10*y^9*s+25518*z*x^11*y^8*s+25518*z^2*x^10*y^8*s+25518*z*x^12*y^7*s+7985*z^2*x^11*y^7*s+25518*z^3*x^10*y^7*s+8506*z*x^13*y^6*s+25518*z^2*x^12*y^6*s+25518*z^3*x^11*y^6*s+8506*z^4*x^10*y^6*s+19583*z^8*x*y^6+15698*z^8*x^2*y^5+15698*z^9*x*y^5+15698*z^8*x^3*y^4+31396*z^9*x^2*y^4+15698*z^10*x*y^4+19583*z^8*x^4*y^3+15698*z^9*x^3*y^3+15698*z^10*x^2*y^3+19583*z^11*x*y^3)*(22750*z^4*x^4*y^4*s^4+41200*z^4*x*y^3*s^3+14342*x^4*y^2*s^3+27324*z^4*x^3*y^3*s+42152*z^2*y^3*s+14244*z^3*y^2*s+40575*z*x^2*y*s+4017*z^2*y^4+26755*z^4*x^3)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #3: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(16873*z^2*x^8*y^7*s^8+7568*z^2*x^9*y^6*s^8+7568*z^3*x^8*y^6*s^8+7568*z^2*x^10*y^5*s^8+15136*z^3*x^9*y^5*s^8+7568*z^4*x^8*y^5*s^8+16873*z^2*x^11*y^4*s^8+7568*z^3*x^10*y^4*s^8+7568*z^4*x^9*y^4*s^8+16873*z^5*x^8*y^4*s^8+41743*z^9*x^7*y^8*s^5+39127*z^9*x^8*y^7*s^5+39127*z^10*x^7*y^7*s^5+39127*z^9*x^9*y^6*s^5+35203*z^10*x^8*y^6*s^5+39127*z^11*x^7*y^6*s^5+41743*z^9*x^10*y^5*s^5+39127*z^10*x^9*y^5*s^5+39127*z^11*x^8*y^5*s^5+41743*z^12*x^7*y^5*s^5+19583*z^4*x^6*y^7*s^4+13845*z^6*x^9*y^6*s^4+15698*z^4*x^7*y^6*s^4+15698*z^5*x^6*y^6*s^4+41535*z^6*x^10*y^5*s^4+41535*z^7*x^9*y^5*s^4+15698*z^4*x^8*y^5*s^4+31396*z^5*x^7*y^5*s^4+15698*z^6*x^6*y^5*s^4+41535*z^6*x^11*y^4*s^4+40019*z^7*x^10*y^4*s^4+41535*z^8*x^9*y^4*s^4+19583*z^4*x^9*y^4*s^4+15698*z^5*x^8*y^4*s^4+15698*z^6*x^7*y^4*s^4+19583*z^7*x^6*y^4*s^4+13845*z^6*x^12*y^3*s^4+41535*z^7*x^11*y^3*s^4+41535*z^8*x^10*y^3*s^4+13845*z^9*x^9*y^3*s^4+39739*z^9*x^6*y^13*s^2+33115*z^9*x^7*y^12*s^2+33115*z^10*x^6*y^12*s^2+33115*z^9*x^8*y^11*s^2+23179*z^10*x^7*y^11*s^2+33115*z^11*x^6*y^11*s^2+39739*z^9*x^9*y^10*s^2+33115*z^10*x^8*y^10*s^2+33115*z^11*x^7*y^10*s^2+39739*z^12*x^6*y^10*s^2+8506*z^8*x^6*y^10*s^2+25518*z^8*x^7*y^9*s^2+25518*z^9*x^6*y^9*s^2+25518*z^8*x^8*y^8*s^2+7985*z^9*x^7*y^8*s^2+25518*z^10*x^6*y^8*s^2+21629*z^6*x^6*y^8*s^2+8506*z^8*x^9*y^7*s^2+25518*z^9*x^8*y^7*s^2+25518*z^10*x^7*y^7*s^2+21836*z^6*x^7*y^7*s^2+8506*z^11*x^6*y^7*s^2+21836*z^7*x^6*y^7*s^2+21836*z^6*x^8*y^6*s^2+621*z^7*x^7*y^6*s^2+21836*z^8*x^6*y^6*s^2+21629*z^6*x^9*y^5*s^2+21836*z^7*x^8*y^5*s^2+21836*z^8*x^7*y^5*s^2+21629*z^9*x^6*y^5*s^2+24116*z^6*x^7*y^4*s+29297*z^6*x^8*y^3*s+29297*z^7*x^7*y^3*s+29297*z^6*x^9*y^2*s+15543*z^7*x^8*y^2*s+29297*z^8*x^7*y^2*s+24116*z^6*x^10*y*s+29297*z^7*x^9*y*s+29297*z^8*x^8*y*s+24116*z^9*x^7*y*s+29049*z^7*x^6*y^6+1045*z^7*x^7*y^5+1045*z^8*x^6*y^5+1045*z^7*x^8*y^4+2090*z^8*x^7*y^4+1045*z^9*x^6*y^4+29049*z^7*x^9*y^3+1045*z^8*x^8*y^3+1045*z^9*x^7*y^3+29049*z^10*x^6*y^3)*(41200*x*y^4*s^3+40575*z*x^3*y^3*s^3+14342*x*y^3*s^3+4017*z*x^4*y^4*s^2+22750*z*x^3*y^3*s^2+26425*x^3*y^3*s^2+26755*z*x^2*s^2+14244*z^3*x^4*y*s)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #4: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(41743*z^7*x^5*y^6*s^8+39127*z^7*x^6*y^5*s^8+39127*z^8*x^5*y^5*s^8+39127*z^7*x^7*y^4*s^8+35203*z^8*x^6*y^4*s^8+39127*z^9*x^5*y^4*s^8+41743*z^7*x^8*y^3*s^8+39127*z^8*x^7*y^3*s^8+39127*z^9*x^6*y^3*s^8+41743*z^10*x^5*y^3*s^8+29049*x*y^5*s^7+1045*x^2*y^4*s^7+1045*z*x*y^4*s^7+1045*x^3*y^3*s^7+2090*z*x^2*y^3*s^7+1045*z^2*x*y^3*s^7+29049*x^4*y^2*s^7+1045*z*x^3*y^2*s^7+1045*z^2*x^2*y^2*s^7+29049*z^3*x*y^2*s^7+39739*z^3*x^8*y^11*s^5+33115*z^3*x^9*y^10*s^5+33115*z^4*x^8*y^10*s^5+33115*z^3*x^10*y^9*s^5+23179*z^4*x^9*y^9*s^5+33115*z^5*x^8*y^9*s^5+39739*z^3*x^11*y^8*s^5+33115*z^4*x^10*y^8*s^5+33115*z^5*x^9*y^8*s^5+39739*z^6*x^8*y^8*s^5+13845*x*y^4*s^4+41535*x^2*y^3*s^4+41535*z*x*y^3*s^4+41535*x^3*y^2*s^4+40019*z*x^2*y^2*s^4+41535*z^2*x*y^2*s^4+13845*x^4*y*s^4+41535*z*x^3*y*s^4+41535*z^2*x^2*y*s^4+13845*z^3*x*y*s^4+16873*z^3*x^10*y^11*s+7568*z^3*x^11*y^10*s+7568*z^4*x^10*y^10*s+21629*z^9*x^6*y^10*s+7568*z^3*x^12*y^9*s+15136*z^4*x^11*y^9*s+7568*z^5*x^10*y^9*s+21836*z^9*x^7*y^9*s+21836*z^10*x^6*y^9*s+16873*z^3*x^13*y^8*s+7568*z^4*x^12*y^8*s+7568*z^5*x^11*y^8*s+16873*z^6*x^10*y^8*s+21836*z^9*x^8*y^8*s+621*z^10*x^7*y^8*s+21836*z^11*x^6*y^8*s+21629*z^9*x^9*y^7*s+21836*z^10*x^8*y^7*s+21836*z^11*x^7*y^7*s+21629*z^12*x^6*y^7*s+19583*z^4*x^5*y^4*s+8506*z^4*x^3*y^4*s+15698*z^4*x^6*y^3*s+15698*z^5*x^5*y^3*s+25518*z^4*x^4*y^3*s+25518*z^5*x^3*y^3*s+15698*z^4*x^7*y^2*s+31396*z^5*x^6*y^2*s+15698*z^6*x^5*y^2*s+25518*z^4*x^5*y^2*s+7985*z^5*x^4*y^2*s+25518*z^6*x^3*y^2*s+19583*z^4*x^8*y*s+15698*z^5*x^7*y*s+15698*z^6*x^6*y*s+8506*z^4*x^6*y*s+19583*z^7*x^5*y*s+25518*z^5*x^5*y*s+25518*z^6*x^4*y*s+8506*z^7*x^3*y*s+24116*z^5*x^9*y^7+29297*z^5*x^10*y^6+29297*z^6*x^9*y^6+29297*z^5*x^11*y^5+15543*z^6*x^10*y^5+29297*z^7*x^9*y^5+24116*z^5*x^12*y^4+29297*z^6*x^11*y^4+29297*z^7*x^10*y^4+24116*z^8*x^9*y^4)*(41200*z^4*x^4*y^3*s^4+14244*z^3*x^4*y*s^4+14342*x^3*y*s^4+39676*z*x^2*y^2*s^3+27324*z^3*x*y^2*s^3+22750*z^4*y*s^3+26755*x*y*s^2+4017*x^3*y^3)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #5: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(13845*x^2*y^8*s^9+41535*x^3*y^7*s^9+41535*z*x^2*y^7*s^9+41535*x^4*y^6*s^9+40019*z*x^3*y^6*s^9+41535*z^2*x^2*y^6*s^9+13845*x^5*y^5*s^9+41535*z*x^4*y^5*s^9+41535*z^2*x^3*y^5*s^9+13845*z^3*x^2*y^5*s^9+41743*z^2*x^7*y^11*s^7+16873*x*y^11*s^7+39127*z^2*x^8*y^10*s^7+39127*z^3*x^7*y^10*s^7+7568*x^2*y^10*s^7+7568*z*x*y^10*s^7+39127*z^2*x^9*y^9*s^7+35203*z^3*x^8*y^9*s^7+39127*z^4*x^7*y^9*s^7+7568*x^3*y^9*s^7+15136*z*x^2*y^9*s^7+7568*z^2*x*y^9*s^7+41743*z^2*x^10*y^8*s^7+39127*z^3*x^9*y^8*s^7+39127*z^4*x^8*y^8*s^7+41743*z^5*x^7*y^8*s^7+16873*x^4*y^8*s^7+27151*z*x^3*y^8*s^7+7568*z^2*x^2*y^8*s^7+16873*z^3*x*y^8*s^7+8506*z^7*x^10*y^7*s^7+15698*z*x^4*y^7*s^7+15698*z^2*x^3*y^7*s^7+25518*z^7*x^11*y^6*s^7+25518*z^8*x^10*y^6*s^7+15698*z*x^5*y^6*s^7+31396*z^2*x^4*y^6*s^7+15698*z^3*x^3*y^6*s^7+25518*z^7*x^12*y^5*s^7+7985*z^8*x^11*y^5*s^7+25518*z^9*x^10*y^5*s^7+19583*z*x^6*y^5*s^7+15698*z^2*x^5*y^5*s^7+15698*z^3*x^4*y^5*s^7+19583*z^4*x^3*y^5*s^7+8506*z^7*x^13*y^4*s^7+25518*z^8*x^12*y^4*s^7+25518*z^9*x^11*y^4*s^7+8506*z^10*x^10*y^4*s^7+29049*z^8*x^2*y^13*s^6+1045*z^8*x^3*y^12*s^6+1045*z^9*x^2*y^12*s^6+1045*z^8*x^4*y^11*s^6+2090*z^9*x^3*y^11*s^6+1045*z^10*x^2*y^11*s^6+29049*z^8*x^5*y^10*s^6+1045*z^9*x^4*y^10*s^6+1045*z^10*x^3*y^10*s^6+29049*z^11*x^2*y^10*s^6+39739*z^3*x^5*y^4*s^4+33115*z^3*x^6*y^3*s^4+33115*z^4*x^5*y^3*s^4+33115*z^3*x^7*y^2*s^4+23179*z^4*x^6*y^2*s^4+33115*z^5*x^5*y^2*s^4+39739*z^3*x^8*y*s^4+33115*z^4*x^7*y*s^4+33115*z^5*x^6*y*s^4+39739*z^6*x^5*y*s^4+21629*z^4*x^5*y^9*s^3+21836*z^4*x^6*y^8*s^3+21836*z^5*x^5*y^8*s^3+21836*z^4*x^7*y^7*s^3+621*z^5*x^6*y^7*s^3+21836*z^6*x^5*y^7*s^3+21629*z^4*x^8*y^6*s^3+21836*z^5*x^7*y^6*s^3+21836*z^6*x^6*y^6*s^3+21629*z^7*x^5*y^6*s^3+24116*z^9*x^2*y^5+29297*z^9*x^3*y^4+29297*z^10*x^2*y^4+29297*z^9*x^4*y^3+15543*z^10*x^3*y^3+29297*z^11*x^2*y^3+24116*z^9*x^5*y^2+29297*z^10*x^4*y^2+29297*z^11*x^3*y^2+24116*z^12*x^2*y^2)*(4017*z*x^4*y^2*s^4+27324*z*x^3*s^4+26755*z^4*x^2*y^3*s^3+40575*x*s^3+14244*x*y^4*s^2+41200*z^4*x^2*s+42152*z*x*s+22750*s+14342*x^4*y)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #6: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(39739*z^7*x^10*y^7*s^7+33115*z^7*x^11*y^6*s^7+33115*z^8*x^10*y^6*s^7+33115*z^7*x^12*y^5*s^7+23179*z^8*x^11*y^5*s^7+33115*z^9*x^10*y^5*s^7+39739*z^7*x^13*y^4*s^7+33115*z^8*x^12*y^4*s^7+33115*z^9*x^11*y^4*s^7+39739*z^10*x^10*y^4*s^7+8506*z^3*x^10*y^4*s^7+25518*z^3*x^11*y^3*s^7+25518*z^4*x^10*y^3*s^7+25518*z^3*x^12*y^2*s^7+7985*z^4*x^11*y^2*s^7+25518*z^5*x^10*y^2*s^7+8506*z^3*x^13*y*s^7+25518*z^4*x^12*y*s^7+25518*z^5*x^11*y*s^7+8506*z^6*x^10*y*s^7+41743*x^5*y^13*s^6+39127*x^6*y^12*s^6+39127*z*x^5*y^12*s^6+39127*x^7*y^11*s^6+35203*z*x^6*y^11*s^6+39127*z^2*x^5*y^11*s^6+41743*x^8*y^10*s^6+39127*z*x^7*y^10*s^6+39127*z^2*x^6*y^10*s^6+41743*z^3*x^5*y^10*s^6+16873*z^6*x^4*y^7*s^5+7568*z^6*x^5*y^6*s^5+7568*z^7*x^4*y^6*s^5+7568*z^6*x^6*y^5*s^5+15136*z^7*x^5*y^5*s^5+7568*z^8*x^4*y^5*s^5+16873*z^6*x^7*y^4*s^5+7568*z^7*x^6*y^4*s^5+7568*z^8*x^5*y^4*s^5+16873*z^9*x^4*y^4*s^5+13845*z^7*x^6*y^13*s^4+41535*z^7*x^7*y^12*s^4+41535*z^8*x^6*y^12*s^4+41535*z^7*x^8*y^11*s^4+40019*z^8*x^7*y^11*s^4+41535*z^9*x^6*y^11*s^4+13845*z^7*x^9*y^10*s^4+41535*z^8*x^8*y^10*s^4+41535*z^9*x^7*y^10*s^4+13845*z^10*x^6*y^10*s^4+19583*z^7*x^7*y^6*s^4+15698*z^7*x^8*y^5*s^4+15698*z^8*x^7*y^5*s^4+15698*z^7*x^9*y^4*s^4+31396*z^8*x^8*y^4*s^4+15698*z^9*x^7*y^4*s^4+19583*z^7*x^10*y^3*s^4+15698*z^8*x^9*y^3*s^4+15698*z^9*x^8*y^3*s^4+19583*z^10*x^7*y^3*s^4+21629*z*x^9*y^8*s^2+24116*z^3*x^5*y^8*s^2+21836*z*x^10*y^7*s^2+21836*z^2*x^9*y^7*s^2+29297*z^3*x^6*y^7*s^2+29297*z^4*x^5*y^7*s^2+21836*z*x^11*y^6*s^2+621*z^2*x^10*y^6*s^2+21836*z^3*x^9*y^6*s^2+29297*z^3*x^7*y^6*s^2+15543*z^4*x^6*y^6*s^2+29297*z^5*x^5*y^6*s^2+21629*z*x^12*y^5*s^2+21836*z^2*x^11*y^5*s^2+21836*z^3*x^10*y^5*s^2+21629*z^4*x^9*y^5*s^2+24116*z^3*x^8*y^5*s^2+29297*z^4*x^7*y^5*s^2+29297*z^5*x^6*y^5*s^2+24116*z^6*x^5*y^5*s^2+29049*z^2*x^2*y^10+1045*z^2*x^3*y^9+1045*z^3*x^2*y^9+1045*z^2*x^4*y^8+2090*z^3*x^3*y^8+1045*z^4*x^2*y^8+29049*z^2*x^5*y^7+1045*z^3*x^4*y^7+1045*z^4*x^3*y^7+29049*z^5*x^2*y^7)*(41200*z^4*x^4*y^3*s^3+22750*x^3*s^3+26755*z^2*x^3*y^4*s^2+4017*z^4*y^2*s^2+40575*z^2*x^4*y^2*s+42152*z^2*x*s+27324*x^2*y^2+14244*z^2*x^4*y+14342*y)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #7: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(29049*z^5*x^8*y^11*s^9+22674*z^5*x^9*y^10*s^9+1045*z^6*x^8*y^10*s^9+22881*z^5*x^10*y^9*s^9+23926*z^6*x^9*y^9*s^9+1045*z^7*x^8*y^9*s^9+7834*z^5*x^11*y^8*s^9+1666*z^6*x^10*y^8*s^9+22881*z^7*x^9*y^8*s^9+29049*z^8*x^8*y^8*s^9+21629*z^5*x^12*y^7*s^9+21836*z^6*x^11*y^7*s^9+21836*z^7*x^10*y^7*s^9+21629*z^8*x^9*y^7*s^9+41743*z^6*x^6*y^8*s^7+39127*z^6*x^7*y^7*s^7+39127*z^7*x^6*y^7*s^7+39127*z^6*x^8*y^6*s^7+35203*z^7*x^7*y^6*s^7+39127*z^8*x^6*y^6*s^7+19583*z^4*x*y^6*s^7+41743*z^6*x^9*y^5*s^7+39127*z^7*x^8*y^5*s^7+39127*z^8*x^7*y^5*s^7+41743*z^9*x^6*y^5*s^7+15698*z^4*x^2*y^5*s^7+15698*z^5*x*y^5*s^7+15698*z^4*x^3*y^4*s^7+31396*z^5*x^2*y^4*s^7+15698*z^6*x*y^4*s^7+19583*z^4*x^4*y^3*s^7+15698*z^5*x^3*y^3*s^7+15698*z^6*x^2*y^3*s^7+19583*z^7*x*y^3*s^7+39739*z^3*x^7*y^13*s^5+33115*z^3*x^8*y^12*s^5+33115*z^4*x^7*y^12*s^5+33115*z^3*x^9*y^11*s^5+23179*z^4*x^8*y^11*s^5+33115*z^5*x^7*y^11*s^5+39739*z^3*x^10*y^10*s^5+33115*z^4*x^9*y^10*s^5+33115*z^5*x^8*y^10*s^5+39739*z^6*x^7*y^10*s^5+16873*z^9*x^10*y^5*s^5+7568*z^9*x^11*y^4*s^5+7568*z^10*x^10*y^4*s^5+7568*z^9*x^12*y^3*s^5+15136*z^10*x^11*y^3*s^5+7568*z^11*x^10*y^3*s^5+16873*z^9*x^13*y^2*s^5+7568*z^10*x^12*y^2*s^5+7568*z^11*x^11*y^2*s^5+16873*z^12*x^10*y^2*s^5+24116*z^7*x^7*y^4*s^4+29297*z^7*x^8*y^3*s^4+29297*z^8*x^7*y^3*s^4+29297*z^7*x^9*y^2*s^4+15543*z^8*x^8*y^2*s^4+29297*z^9*x^7*y^2*s^4+24116*z^7*x^10*y*s^4+29297*z^8*x^9*y*s^4+29297*z^9*x^8*y*s^4+24116*z^10*x^7*y*s^4+8506*z^6*x^3*y^5*s^3+25518*z^6*x^4*y^4*s^3+25518*z^7*x^3*y^4*s^3+25518*z^6*x^5*y^3*s^3+7985*z^7*x^4*y^3*s^3+25518*z^8*x^3*y^3*s^3+8506*z^6*x^6*y^2*s^3+25518*z^7*x^5*y^2*s^3+25518*z^8*x^4*y^2*s^3+8506*z^9*x^3*y^2*s^3+13845*z^7*x^10*y^7+41535*z^7*x^11*y^6+41535*z^8*x^10*y^6+41535*z^7*x^12*y^5+40019*z^8*x^11*y^5+41535*z^9*x^10*y^5+13845*z^7*x^13*y^4+41535*z^8*x^12*y^4+41535*z^9*x^11*y^4+13845*z^10*x^10*y^4)*(40575*z^4*x^4*s^4+22750*z^4*x^2*y^2*s^2+26755*z^3*y^2*s^2+27324*z^4*x^4*y*s^2+14342*z^4*x^3*y^2*s+14244*x^2*y*s+41200*x^3*s+4017*z^4*y^2+42152*x)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #8: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(39739*z^9*x^7*y^8*s^7+33115*z^9*x^8*y^7*s^7+33115*z^10*x^7*y^7*s^7+33115*z^9*x^9*y^6*s^7+23179*z^10*x^8*y^6*s^7+33115*z^11*x^7*y^6*s^7+39739*z^9*x^10*y^5*s^7+33115*z^10*x^9*y^5*s^7+33115*z^11*x^8*y^5*s^7+39739*z^12*x^7*y^5*s^7+24116*z^8*x*y^10*s^6+29297*z^8*x^2*y^9*s^6+29297*z^9*x*y^9*s^6+29297*z^8*x^3*y^8*s^6+15543*z^9*x^2*y^8*s^6+29297*z^10*x*y^8*s^6+24116*z^8*x^4*y^7*s^6+29297*z^9*x^3*y^7*s^6+29297*z^10*x^2*y^7*s^6+24116*z^11*x*y^7*s^6+21629*z^6*x^7*y^6*s^5+21836*z^6*x^8*y^5*s^5+21836*z^7*x^7*y^5*s^5+21836*z^6*x^9*y^4*s^5+621*z^7*x^8*y^4*s^5+21836*z^8*x^7*y^4*s^5+21629*z^6*x^10*y^3*s^5+21836*z^7*x^9*y^3*s^5+21836*z^8*x^8*y^3*s^5+21629*z^9*x^7*y^3*s^5+19583*z^6*x^9*y^9*s^3+15698*z^6*x^10*y^8*s^3+15698*z^7*x^9*y^8*s^3+15698*z^6*x^11*y^7*s^3+31396*z^7*x^10*y^7*s^3+15698*z^8*x^9*y^7*s^3+29049*z^7*x^8*y^7*s^3+19583*z^6*x^12*y^6*s^3+15698*z^7*x^11*y^6*s^3+15698*z^8*x^10*y^6*s^3+19583*z^9*x^9*y^6*s^3+1045*z^7*x^9*y^6*s^3+1045*z^8*x^8*y^6*s^3+1045*z^7*x^10*y^5*s^3+2090*z^8*x^9*y^5*s^3+1045*z^9*x^8*y^5*s^3+29049*z^7*x^11*y^4*s^3+1045*z^8*x^10*y^4*s^3+1045*z^9*x^9*y^4*s^3+29049*z^10*x^8*y^4*s^3+41743*z^2*x^3*y^11*s^2+39127*z^2*x^4*y^10*s^2+39127*z^3*x^3*y^10*s^2+39127*z^2*x^5*y^9*s^2+35203*z^3*x^4*y^9*s^2+39127*z^4*x^3*y^9*s^2+41743*z^2*x^6*y^8*s^2+39127*z^3*x^5*y^8*s^2+39127*z^4*x^4*y^8*s^2+41743*z^5*x^3*y^8*s^2+13845*z^7*x^7*y^4*s+41535*z^7*x^8*y^3*s+41535*z^8*x^7*y^3*s+41535*z^7*x^9*y^2*s+40019*z^8*x^8*y^2*s+41535*z^9*x^7*y^2*s+13845*z^7*x^10*y*s+41535*z^8*x^9*y*s+41535*z^9*x^8*y*s+13845*z^10*x^7*y*s+8506*z^2*x^5*y^10+16873*z^8*x^4*y^10+25518*z^2*x^6*y^9+7568*z^8*x^5*y^9+25518*z^3*x^5*y^9+7568*z^9*x^4*y^9+25518*z^2*x^7*y^8+7568*z^8*x^6*y^8+7985*z^3*x^6*y^8+15136*z^9*x^5*y^8+25518*z^4*x^5*y^8+7568*z^10*x^4*y^8+8506*z^2*x^8*y^7+16873*z^8*x^7*y^7+25518*z^3*x^7*y^7+7568*z^9*x^6*y^7+25518*z^4*x^6*y^7+7568*z^10*x^5*y^7+8506*z^5*x^5*y^7+16873*z^11*x^4*y^7)*(26755*z^4*x^4*y*s^3+11768*x^3*s^2+27324*z^2*x^2*y^2*s+4017*z*x^3*y*s+42152*z^2*x*s+41200*z*x^4*y+14342*z^4*x^2*y+22750*z^2*x^2)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #9: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(29049*z^4*x*y^8*s^9+1045*z^4*x^2*y^7*s^9+1045*z^5*x*y^7*s^9+1045*z^4*x^3*y^6*s^9+2090*z^5*x^2*y^6*s^9+1045*z^6*x*y^6*s^9+29049*z^4*x^4*y^5*s^9+1045*z^5*x^3*y^5*s^9+1045*z^6*x^2*y^5*s^9+29049*z^7*x*y^5*s^9+16873*z^2*x^5*y^13*s^8+7568*z^2*x^6*y^12*s^8+7568*z^3*x^5*y^12*s^8+7568*z^2*x^7*y^11*s^8+15136*z^3*x^6*y^11*s^8+7568*z^4*x^5*y^11*s^8+16873*z^2*x^8*y^10*s^8+7568*z^3*x^7*y^10*s^8+7568*z^4*x^6*y^10*s^8+16873*z^5*x^5*y^10*s^8+19583*z^6*x^2*y^13*s^6+15698*z^6*x^3*y^12*s^6+15698*z^7*x^2*y^12*s^6+15698*z^6*x^4*y^11*s^6+31396*z^7*x^3*y^11*s^6+15698*z^8*x^2*y^11*s^6+19583*z^6*x^5*y^10*s^6+15698*z^7*x^4*y^10*s^6+15698*z^8*x^3*y^10*s^6+19583*z^9*x^2*y^10*s^6+41743*z^6*x^3*y^8*s^6+39127*z^6*x^4*y^7*s^6+39127*z^7*x^3*y^7*s^6+39127*z^6*x^5*y^6*s^6+35203*z^7*x^4*y^6*s^6+39127*z^8*x^3*y^6*s^6+41743*z^6*x^6*y^5*s^6+39127*z^7*x^5*y^5*s^6+39127*z^8*x^4*y^5*s^6+41743*z^9*x^3*y^5*s^6+24116*x^3*y^12*s^4+29297*x^4*y^11*s^4+29297*z*x^3*y^11*s^4+29297*x^5*y^10*s^4+15543*z*x^4*y^10*s^4+29297*z^2*x^3*y^10*s^4+24116*x^6*y^9*s^4+29297*z*x^5*y^9*s^4+29297*z^2*x^4*y^9*s^4+24116*z^3*x^3*y^9*s^4+13845*z^8*x^9*y^7*s^3+41535*z^8*x^10*y^6*s^3+41535*z^9*x^9*y^6*s^3+41535*z^8*x^11*y^5*s^3+40019*z^9*x^10*y^5*s^3+41535*z^10*x^9*y^5*s^3+13845*z^8*x^12*y^4*s^3+41535*z^9*x^11*y^4*s^3+41535*z^10*x^10*y^4*s^3+13845*z^11*x^9*y^4*s^3+8506*z^7*x^5*y^4*s^3+25518*z^7*x^6*y^3*s^3+25518*z^8*x^5*y^3*s^3+25518*z^7*x^7*y^2*s^3+7985*z^8*x^6*y^2*s^3+25518*z^9*x^5*y^2*s^3+8506*z^7*x^8*y*s^3+25518*z^8*x^7*y*s^3+25518*z^9*x^6*y*s^3+8506*z^10*x^5*y*s^3+39739*z^4*x^8*y^10*s^2+33115*z^4*x^9*y^9*s^2+33115*z^5*x^8*y^9*s^2+33115*z^4*x^10*y^8*s^2+23179*z^5*x^9*y^8*s^2+33115*z^6*x^8*y^8*s^2+21629*z^5*x^7*y^8*s^2+39739*z^4*x^11*y^7*s^2+33115*z^5*x^10*y^7*s^2+33115*z^6*x^9*y^7*s^2+39739*z^7*x^8*y^7*s^2+21836*z^5*x^8*y^7*s^2+21836*z^6*x^7*y^7*s^2+21836*z^5*x^9*y^6*s^2+621*z^6*x^8*y^6*s^2+21836*z^7*x^7*y^6*s^2+21629*z^5*x^10*y^5*s^2+21836*z^6*x^9*y^5*s^2+21836*z^7*x^8*y^5*s^2+21629*z^8*x^7*y^5*s^2)*(14342*z*x*y^4*s^3+41200*z^2*x^3*y^2*s^3+26755*z*x^3*y^2*s^3+4017*z^4*y*s^3+22750*x^3*y^3*s^2+42152*z^2*x^2*s^2+27324*z*y^2*s+40575*x^4*y*s+14244*z^3*x^2)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#10: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(24116*z^3*x^5*y^4*s^3+29297*z^3*x^6*y^3*s^3+29297*z^4*x^5*y^3*s^3+29297*z^3*x^7*y^2*s^3+15543*z^4*x^6*y^2*s^3+29297*z^5*x^5*y^2*s^3+24116*z^3*x^8*y*s^3+29297*z^4*x^7*y*s^3+29297*z^5*x^6*y*s^3+24116*z^6*x^5*y*s^3+41743*z^2*x^5*y^8*s^2+39127*z^2*x^6*y^7*s^2+39127*z^3*x^5*y^7*s^2+39127*z^2*x^7*y^6*s^2+35203*z^3*x^6*y^6*s^2+39127*z^4*x^5*y^6*s^2+41743*z^2*x^8*y^5*s^2+39127*z^3*x^7*y^5*s^2+39127*z^4*x^6*y^5*s^2+41743*z^5*x^5*y^5*s^2+8506*x^5*y^5*s^2+25518*x^6*y^4*s^2+25518*z*x^5*y^4*s^2+19583*z^4*x^4*y^4*s^2+25518*x^7*y^3*s^2+7985*z*x^6*y^3*s^2+15698*z^4*x^5*y^3*s^2+25518*z^2*x^5*y^3*s^2+15698*z^5*x^4*y^3*s^2+8506*x^8*y^2*s^2+25518*z*x^7*y^2*s^2+15698*z^4*x^6*y^2*s^2+25518*z^2*x^6*y^2*s^2+31396*z^5*x^5*y^2*s^2+8506*z^3*x^5*y^2*s^2+15698*z^6*x^4*y^2*s^2+19583*z^4*x^7*y*s^2+15698*z^5*x^6*y*s^2+15698*z^6*x^5*y*s^2+19583*z^7*x^4*y*s^2)*(22750*x*y+14244*y+18359*z^2)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#11: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(26755*z^6*x^5*y^3*s^7+12889*z^5*x^4*y^4*s^6+40575*y^2*s^6+22750*z^3*s^6+14244*z*x^3*y*s^4+41200*z^7*y^2*s^3+38991*z^7*x^7*y^4*s^2+42152*z^7*y^3*s^2+27324*z^6*y^2*s^2+33099*z^3*x^2*s^2+14342*z^4*x^5*y^3*s+9788*z*x^6*y^2*s+4620*z^6*x^3*y^6+4017*z^2*x^3*y^4)*(6157*z^14*x^5*y^15*s^14+18471*z^14*x^6*y^14*s^14+18471*z^15*x^5*y^14*s^14+18471*z^14*x^7*y^13*s^14+36942*z^15*x^6*y^13*s^14+18471*z^16*x^5*y^13*s^14+6157*z^14*x^8*y^12*s^14+18471*z^15*x^7*y^12*s^14+18471*z^16*x^6*y^12*s^14+6157*z^17*x^5*y^12*s^14+24116*z^3*x^3*y^6*s^13+29297*z^3*x^4*y^5*s^13+29297*z^4*x^3*y^5*s^13+29297*z^3*x^5*y^4*s^13+15543*z^4*x^4*y^4*s^13+29297*z^5*x^3*y^4*s^13+24116*z^3*x^6*y^3*s^13+29297*z^4*x^5*y^3*s^13+29297*z^5*x^4*y^3*s^13+24116*z^6*x^3*y^3*s^13+39739*z^6*x^15*y^8*s^12+33115*z^6*x^16*y^7*s^12+33115*z^7*x^15*y^7*s^12+33115*z^6*x^17*y^6*s^12+23179*z^7*x^16*y^6*s^12+33115*z^8*x^15*y^6*s^12+39739*z^6*x^18*y^5*s^12+33115*z^7*x^17*y^5*s^12+33115*z^8*x^16*y^5*s^12+39739*z^9*x^15*y^5*s^12+29049*z^12*x^8*y^4*s^10+1045*z^12*x^9*y^3*s^10+1045*z^13*x^8*y^3*s^10+1045*z^12*x^10*y^2*s^10+2090*z^13*x^9*y^2*s^10+1045*z^14*x^8*y^2*s^10+29049*z^12*x^11*y*s^10+1045*z^13*x^10*y*s^10+1045*z^14*x^9*y*s^10+29049*z^15*x^8*y*s^10+19583*z^10*x*y^16*s^9+15698*z^10*x^2*y^15*s^9+15698*z^11*x*y^15*s^9+15698*z^10*x^3*y^14*s^9+31396*z^11*x^2*y^14*s^9+15698*z^12*x*y^14*s^9+19583*z^10*x^4*y^13*s^9+15698*z^11*x^3*y^13*s^9+15698*z^12*x^2*y^13*s^9+19583*z^13*x*y^13*s^9+40031*z^6*x^4*y^14*s^8+33991*z^6*x^5*y^13*s^8+33991*z^7*x^4*y^13*s^8+33991*z^6*x^6*y^12*s^8+24931*z^7*x^5*y^12*s^8+33991*z^8*x^4*y^12*s^8+40031*z^6*x^7*y^11*s^8+33991*z^7*x^6*y^11*s^8+33991*z^8*x^5*y^11*s^8+40031*z^9*x^4*y^11*s^8+8506*z^6*x*y^15*s^7+25518*z^6*x^2*y^14*s^7+25518*z^7*x*y^14*s^7+25518*z^6*x^3*y^13*s^7+7985*z^7*x^2*y^13*s^7+25518*z^8*x*y^13*s^7+8506*z^6*x^4*y^12*s^7+25518*z^7*x^3*y^12*s^7+25518*z^8*x^2*y^12*s^7+8506*z^9*x*y^12*s^7+41743*z^12*x^2*y^10*s^7+39127*z^12*x^3*y^9*s^7+39127*z^13*x^2*y^9*s^7+39127*z^12*x^4*y^8*s^7+35203*z^13*x^3*y^8*s^7+39127*z^14*x^2*y^8*s^7+41743*z^12*x^5*y^7*s^7+39127*z^13*x^4*y^7*s^7+39127*z^14*x^3*y^7*s^7+41743*z^15*x^2*y^7*s^7+21629*z^10*x^8*y^8*s^6+9048*z^10*x^5*y^8*s^6+21836*z^10*x^9*y^7*s^6+21836*z^11*x^8*y^7*s^6+27144*z^10*x^6*y^7*s^6+27144*z^11*x^5*y^7*s^6+21836*z^10*x^10*y^6*s^6+621*z^11*x^9*y^6*s^6+21836*z^12*x^8*y^6*s^6+27144*z^10*x^7*y^6*s^6+11237*z^11*x^6*y^6*s^6+27144*z^12*x^5*y^6*s^6+21629*z^10*x^11*y^5*s^6+21836*z^11*x^10*y^5*s^6+21836*z^12*x^9*y^5*s^6+21629*z^13*x^8*y^5*s^6+9048*z^10*x^8*y^5*s^6+27144*z^11*x^7*y^5*s^6+27144*z^12*x^6*y^5*s^6+9048*z^13*x^5*y^5*s^6+16680*z^8*x^5*y^18*s^5+6989*z^8*x^6*y^17*s^5+6989*z^9*x^5*y^17*s^5+6989*z^8*x^7*y^16*s^5+13978*z^9*x^6*y^16*s^5+6989*z^10*x^5*y^16*s^5+16680*z^8*x^8*y^15*s^5+6989*z^9*x^7*y^15*s^5+6989*z^10*x^6*y^15*s^5+16680*z^11*x^5*y^15*s^5+16873*z^10*x^15*y^9*s^4+7568*z^10*x^16*y^8*s^4+7568*z^11*x^15*y^8*s^4+7568*z^10*x^17*y^7*s^4+15136*z^11*x^16*y^7*s^4+7568*z^12*x^15*y^7*s^4+16873*z^10*x^18*y^6*s^4+7568*z^11*x^17*y^6*s^4+7568*z^12*x^16*y^6*s^4+16873*z^13*x^15*y^6*s^4+13845*x^7*y^11*s+41535*x^8*y^10*s+41535*z*x^7*y^10*s+41535*x^9*y^9*s+40019*z*x^8*y^9*s+41535*z^2*x^7*y^9*s+13845*x^10*y^8*s+41535*z*x^9*y^8*s+41535*z^2*x^8*y^8*s+13845*z^3*x^7*y^8*s+37652*x*y^12+26854*x^2*y^11+26854*z*x*y^11+26854*x^3*y^10+10657*z*x^2*y^10+26854*z^2*x*y^10+37652*x^4*y^9+26854*z*x^3*y^9+26854*z^2*x^2*y^9+37652*z^3*x*y^9)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#12: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(27324*x^2*y^4*s^4+26755*z^4*x^2*y*s^3+41200*x^2*s^3+14244*z^2*x^3*y^4*s^2+22750*z^4*y^4*s^2+4017*z^2*x^3*y^2*s^2+40575*z^4*x^2*y^2*s^2+14342*z^3*x^2*y^4*s+42152*z^2*x^3*y^2*s)*(21629*z^3*x^9*y^6*s^11+21836*z^3*x^10*y^5*s^11+21836*z^4*x^9*y^5*s^11+21836*z^3*x^11*y^4*s^11+621*z^4*x^10*y^4*s^11+21836*z^5*x^9*y^4*s^11+21629*z^3*x^12*y^3*s^11+21836*z^4*x^11*y^3*s^11+21836*z^5*x^10*y^3*s^11+21629*z^6*x^9*y^3*s^11+21629*z^2*x^9*y^8*s^10+21629*z^4*x^10*y^7*s^10+21836*z^2*x^10*y^7*s^10+21836*z^3*x^9*y^7*s^10+39739*z^7*x^8*y^7*s^10+21836*z^4*x^11*y^6*s^10+21836*z^2*x^11*y^6*s^10+21836*z^5*x^10*y^6*s^10+621*z^3*x^10*y^6*s^10+33115*z^7*x^9*y^6*s^10+21836*z^4*x^9*y^6*s^10+33115*z^8*x^8*y^6*s^10+21836*z^4*x^12*y^5*s^10+21629*z^2*x^12*y^5*s^10+621*z^5*x^11*y^5*s^10+21836*z^3*x^11*y^5*s^10+33115*z^7*x^10*y^5*s^10+21836*z^6*x^10*y^5*s^10+21836*z^4*x^10*y^5*s^10+23179*z^8*x^9*y^5*s^10+21629*z^5*x^9*y^5*s^10+33115*z^9*x^8*y^5*s^10+21629*z^4*x^13*y^4*s^10+21836*z^5*x^12*y^4*s^10+39739*z^7*x^11*y^4*s^10+21836*z^6*x^11*y^4*s^10+33115*z^8*x^10*y^4*s^10+21629*z^7*x^10*y^4*s^10+33115*z^9*x^9*y^4*s^10+39739*z^10*x^8*y^4*s^10+39739*z^6*x^8*y^9*s^9+39739*z^8*x^9*y^8*s^9+33115*z^6*x^9*y^8*s^9+33115*z^7*x^8*y^8*s^9+21629*z^2*x^11*y^7*s^9+33115*z^8*x^10*y^7*s^9+33115*z^6*x^10*y^7*s^9+33115*z^9*x^9*y^7*s^9+23179*z^7*x^9*y^7*s^9+33115*z^8*x^8*y^7*s^9+21836*z^2*x^12*y^6*s^9+33115*z^8*x^11*y^6*s^9+39739*z^6*x^11*y^6*s^9+21836*z^3*x^11*y^6*s^9+23179*z^9*x^10*y^6*s^9+33115*z^7*x^10*y^6*s^9+21629*z^4*x^10*y^6*s^9+33115*z^10*x^9*y^6*s^9+33115*z^8*x^9*y^6*s^9+21629*z^2*x^9*y^6*s^9+39739*z^9*x^8*y^6*s^9+21836*z^2*x^13*y^5*s^9+39739*z^8*x^12*y^5*s^9+621*z^3*x^12*y^5*s^9+33115*z^9*x^11*y^5*s^9+621*z^4*x^11*y^5*s^9+33115*z^10*x^10*y^5*s^9+21836*z^5*x^10*y^5*s^9+21836*z^2*x^10*y^5*s^9+39739*z^11*x^9*y^5*s^9+21836*z^3*x^9*y^5*s^9+21629*z^2*x^14*y^4*s^9+21836*z^3*x^13*y^4*s^9+621*z^4*x^12*y^4*s^9+22250*z^5*x^11*y^4*s^9+21836*z^2*x^11*y^4*s^9+21836*z^6*x^10*y^4*s^9+621*z^3*x^10*y^4*s^9+21836*z^4*x^9*y^4*s^9+21629*z^4*x^13*y^3*s^9+21836*z^5*x^12*y^3*s^9+21629*z^2*x^12*y^3*s^9+21836*z^6*x^11*y^3*s^9+21836*z^3*x^11*y^3*s^9+21629*z^7*x^10*y^3*s^9+21836*z^4*x^10*y^3*s^9+21629*z^5*x^9*y^3*s^9+29049*z^3*x*y^9*s^8+39739*z^6*x^10*y^8*s^8+1045*z^3*x^2*y^8*s^8+1045*z^4*x*y^8*s^8+33115*z^6*x^11*y^7*s^8+33115*z^7*x^10*y^7*s^8+39739*z^8*x^9*y^7*s^8+39739*z^6*x^8*y^7*s^8+1045*z^3*x^3*y^7*s^8+2090*z^4*x^2*y^7*s^8+1045*z^5*x*y^7*s^8+33115*z^6*x^12*y^6*s^8+23179*z^7*x^11*y^6*s^8+23179*z^8*x^10*y^6*s^8+33115*z^9*x^9*y^6*s^8+33115*z^6*x^9*y^6*s^8+33115*z^7*x^8*y^6*s^8+29049*z^3*x^4*y^6*s^8+1045*z^4*x^3*y^6*s^8+1045*z^5*x^2*y^6*s^8+29049*z^6*x*y^6*s^8+39739*z^6*x^13*y^5*s^8+33115*z^7*x^12*y^5*s^8+23179*z^8*x^11*y^5*s^8+19867*z^9*x^10*y^5*s^8+33115*z^6*x^10*y^5*s^8+33115*z^10*x^9*y^5*s^8+23179*z^7*x^9*y^5*s^8+33115*z^8*x^8*y^5*s^8+39739*z^8*x^12*y^4*s^8+33115*z^9*x^11*y^4*s^8+39739*z^6*x^11*y^4*s^8+33115*z^10*x^10*y^4*s^8+33115*z^7*x^10*y^4*s^8+39739*z^11*x^9*y^4*s^8+33115*z^8*x^9*y^4*s^8+39739*z^9*x^8*y^4*s^8+29049*z^2*x*y^11*s^7+29049*z^4*x^2*y^10*s^7+1045*z^2*x^2*y^10*s^7+1045*z^3*x*y^10*s^7+1045*z^4*x^3*y^9*s^7+1045*z^2*x^3*y^9*s^7+1045*z^5*x^2*y^9*s^7+2090*z^3*x^2*y^9*s^7+1045*z^4*x*y^9*s^7+1045*z^4*x^4*y^8*s^7+29049*z^2*x^4*y^8*s^7+2090*z^5*x^3*y^8*s^7+1045*z^3*x^3*y^8*s^7+1045*z^6*x^2*y^8*s^7+1045*z^4*x^2*y^8*s^7+29049*z^5*x*y^8*s^7+29049*z^4*x^5*y^7*s^7+1045*z^5*x^4*y^7*s^7+1045*z^6*x^3*y^7*s^7+29049*z^7*x^2*y^7*s^7+19583*z^6*x^4*y^4*s^7+15698*z^6*x^5*y^3*s^7+15698*z^7*x^4*y^3*s^7+15698*z^6*x^6*y^2*s^7+31396*z^7*x^5*y^2*s^7+15698*z^8*x^4*y^2*s^7+19583*z^6*x^7*y*s^7+15698*z^7*x^6*y*s^7+15698*z^8*x^5*y*s^7+19583*z^9*x^4*y*s^7+13845*z^5*x^8*y^12*s^6+41535*z^5*x^9*y^11*s^6+41535*z^6*x^8*y^11*s^6+41535*z^5*x^10*y^10*s^6+40019*z^6*x^9*y^10*s^6+41535*z^7*x^8*y^10*s^6+29049*z^2*x^3*y^10*s^6+13845*z^5*x^11*y^9*s^6+41535*z^6*x^10*y^9*s^6+41535*z^7*x^9*y^9*s^6+13845*z^8*x^8*y^9*s^6+1045*z^2*x^4*y^9*s^6+1045*z^3*x^3*y^9*s^6+29049*z^4*x^2*y^9*s^6+29049*z^2*x*y^9*s^6+1045*z^2*x^5*y^8*s^6+2090*z^3*x^4*y^8*s^6+2090*z^4*x^3*y^8*s^6+1045*z^5*x^2*y^8*s^6+1045*z^2*x^2*y^8*s^6+1045*z^3*x*y^8*s^6+29049*z^2*x^6*y^7*s^6+1045*z^3*x^5*y^7*s^6+2090*z^4*x^4*y^7*s^6+31139*z^5*x^3*y^7*s^6+1045*z^2*x^3*y^7*s^6+1045*z^6*x^2*y^7*s^6+2090*z^3*x^2*y^7*s^6+1045*z^4*x*y^7*s^6+29049*z^4*x^5*y^6*s^6+20628*z^5*x^4*y^6*s^6+29049*z^2*x^4*y^6*s^6+1045*z^6*x^3*y^6*s^6+1045*z^3*x^3*y^6*s^6+29049*z^7*x^2*y^6*s^6+1045*z^4*x^2*y^6*s^6+29049*z^5*x*y^6*s^6+19583*z^7*x^5*y^5*s^6+15698*z^5*x^5*y^5*s^6+15698*z^6*x^4*y^5*s^6+15698*z^7*x^6*y^4*s^6+15698*z^5*x^6*y^4*s^6+15698*z^8*x^5*y^4*s^6+31396*z^6*x^5*y^4*s^6+15698*z^7*x^4*y^4*s^6+15698*z^7*x^7*y^3*s^6+19583*z^5*x^7*y^3*s^6+31396*z^8*x^6*y^3*s^6+15698*z^6*x^6*y^3*s^6+15698*z^9*x^5*y^3*s^6+15698*z^7*x^5*y^3*s^6+19583*z^8*x^4*y^3*s^6+19583*z^7*x^8*y^2*s^6+15698*z^8*x^7*y^2*s^6+15698*z^9*x^6*y^2*s^6+19583*z^10*x^5*y^2*s^6+13845*z^4*x^8*y^14*s^5+13845*z^6*x^9*y^13*s^5+41535*z^4*x^9*y^13*s^5+41535*z^5*x^8*y^13*s^5+41535*z^6*x^10*y^12*s^5+41535*z^4*x^10*y^12*s^5+41535*z^7*x^9*y^12*s^5+40019*z^5*x^9*y^12*s^5+41535*z^6*x^8*y^12*s^5+41535*z^6*x^11*y^11*s^5+13845*z^4*x^11*y^11*s^5+40019*z^7*x^10*y^11*s^5+41535*z^5*x^10*y^11*s^5+41535*z^8*x^9*y^11*s^5+41535*z^6*x^9*y^11*s^5+13845*z^7*x^8*y^11*s^5+13845*z^6*x^12*y^10*s^5+41535*z^7*x^11*y^10*s^5+41535*z^8*x^10*y^10*s^5+13845*z^9*x^9*y^10*s^5+19583*z^5*x^6*y^5*s^5+15698*z^5*x^7*y^4*s^5+15698*z^6*x^6*y^4*s^5+19583*z^7*x^5*y^4*s^5+19583*z^5*x^4*y^4*s^5+15698*z^5*x^8*y^3*s^5+31396*z^6*x^7*y^3*s^5+31396*z^7*x^6*y^3*s^5+15698*z^8*x^5*y^3*s^5+15698*z^5*x^5*y^3*s^5+15698*z^6*x^4*y^3*s^5+19583*z^5*x^9*y^2*s^5+15698*z^6*x^8*y^2*s^5+31396*z^7*x^7*y^2*s^5+7928*z^8*x^6*y^2*s^5+15698*z^5*x^6*y^2*s^5+15698*z^9*x^5*y^2*s^5+31396*z^6*x^5*y^2*s^5+15698*z^7*x^4*y^2*s^5+19583*z^7*x^8*y*s^5+15698*z^8*x^7*y*s^5+19583*z^5*x^7*y*s^5+15698*z^9*x^6*y*s^5+15698*z^6*x^6*y*s^5+19583*z^10*x^5*y*s^5+15698*z^7*x^5*y*s^5+19583*z^8*x^4*y*s^5+13845*z^4*x^10*y^13*s^4+41535*z^4*x^11*y^12*s^4+41535*z^5*x^10*y^12*s^4+13845*z^6*x^9*y^12*s^4+13845*z^4*x^8*y^12*s^4+41535*z^4*x^12*y^11*s^4+40019*z^5*x^11*y^11*s^4+40019*z^6*x^10*y^11*s^4+41535*z^7*x^9*y^11*s^4+41535*z^4*x^9*y^11*s^4+41535*z^5*x^8*y^11*s^4+13845*z^4*x^13*y^10*s^4+41535*z^5*x^12*y^10*s^4+40019*z^6*x^11*y^10*s^4+10813*z^7*x^10*y^10*s^4+41535*z^4*x^10*y^10*s^4+41535*z^8*x^9*y^10*s^4+40019*z^5*x^9*y^10*s^4+41535*z^6*x^8*y^10*s^4+13845*z^6*x^12*y^9*s^4+41535*z^7*x^11*y^9*s^4+13845*z^4*x^11*y^9*s^4+41535*z^8*x^10*y^9*s^4+41535*z^5*x^10*y^9*s^4+13845*z^9*x^9*y^9*s^4+41535*z^6*x^9*y^9*s^4+13845*z^7*x^8*y^9*s^4+16873*z^2*x^9*y^7*s^4+7568*z^2*x^10*y^6*s^4+7568*z^3*x^9*y^6*s^4+7568*z^2*x^11*y^5*s^4+15136*z^3*x^10*y^5*s^4+7568*z^4*x^9*y^5*s^4+41743*z^2*x^4*y^5*s^4+16873*z^2*x^12*y^4*s^4+7568*z^3*x^11*y^4*s^4+7568*z^4*x^10*y^4*s^4+16873*z^5*x^9*y^4*s^4+8506*z^5*x^5*y^4*s^4+39127*z^2*x^5*y^4*s^4+39127*z^3*x^4*y^4*s^4+25518*z^5*x^6*y^3*s^4+39127*z^2*x^6*y^3*s^4+25518*z^6*x^5*y^3*s^4+35203*z^3*x^5*y^3*s^4+39127*z^4*x^4*y^3*s^4+25518*z^5*x^7*y^2*s^4+41743*z^2*x^7*y^2*s^4+7985*z^6*x^6*y^2*s^4+39127*z^3*x^6*y^2*s^4+25518*z^7*x^5*y^2*s^4+39127*z^4*x^5*y^2*s^4+41743*z^5*x^4*y^2*s^4+8506*z^5*x^8*y*s^4+25518*z^6*x^7*y*s^4+25518*z^7*x^6*y*s^4+8506*z^8*x^5*y*s^4+16873*z*x^9*y^9*s^3+16873*z^3*x^10*y^8*s^3+7568*z*x^10*y^8*s^3+7568*z^2*x^9*y^8*s^3+7568*z^3*x^11*y^7*s^3+7568*z*x^11*y^7*s^3+7568*z^4*x^10*y^7*s^3+15136*z^2*x^10*y^7*s^3+7568*z^3*x^9*y^7*s^3+41743*z*x^4*y^7*s^3+7568*z^3*x^12*y^6*s^3+16873*z*x^12*y^6*s^3+15136*z^4*x^11*y^6*s^3+7568*z^2*x^11*y^6*s^3+7568*z^5*x^10*y^6*s^3+7568*z^3*x^10*y^6*s^3+16873*z^4*x^9*y^6*s^3+8506*z^4*x^5*y^6*s^3+41743*z^3*x^5*y^6*s^3+39127*z*x^5*y^6*s^3+39127*z^2*x^4*y^6*s^3+16873*z^3*x^13*y^5*s^3+7568*z^4*x^12*y^5*s^3+7568*z^5*x^11*y^5*s^3+16873*z^6*x^10*y^5*s^3+8506*z^6*x^6*y^5*s^3+25518*z^4*x^6*y^5*s^3+39127*z^3*x^6*y^5*s^3+39127*z*x^6*y^5*s^3+25518*z^5*x^5*y^5*s^3+39127*z^4*x^5*y^5*s^3+35203*z^2*x^5*y^5*s^3+39127*z^3*x^4*y^5*s^3+25518*z^6*x^7*y^4*s^3+25518*z^4*x^7*y^4*s^3+39127*z^3*x^7*y^4*s^3+41743*z*x^7*y^4*s^3+25518*z^7*x^6*y^4*s^3+7985*z^5*x^6*y^4*s^3+35203*z^4*x^6*y^4*s^3+39127*z^2*x^6*y^4*s^3+25518*z^6*x^5*y^4*s^3+39127*z^5*x^5*y^4*s^3+39127*z^3*x^5*y^4*s^3+41743*z^4*x^4*y^4*s^3+25518*z^6*x^8*y^3*s^3+8506*z^4*x^8*y^3*s^3+41743*z^3*x^8*y^3*s^3+7985*z^7*x^7*y^3*s^3+25518*z^5*x^7*y^3*s^3+39127*z^4*x^7*y^3*s^3+25518*z^8*x^6*y^3*s^3+25518*z^6*x^6*y^3*s^3+39127*z^5*x^6*y^3*s^3+8506*z^7*x^5*y^3*s^3+41743*z^6*x^5*y^3*s^3+8506*z^6*x^9*y^2*s^3+25518*z^7*x^8*y^2*s^3+25518*z^8*x^7*y^2*s^3+8506*z^9*x^6*y^2*s^3+24116*z^10*x^6*y^11*s^2+29297*z^10*x^7*y^10*s^2+29297*z^11*x^6*y^10*s^2+29297*z^10*x^8*y^9*s^2+15543*z^11*x^7*y^9*s^2+29297*z^12*x^6*y^9*s^2+16873*z*x^11*y^8*s^2+24116*z^10*x^9*y^8*s^2+29297*z^11*x^8*y^8*s^2+29297*z^12*x^7*y^8*s^2+24116*z^13*x^6*y^8*s^2+7568*z*x^12*y^7*s^2+7568*z^2*x^11*y^7*s^2+16873*z^3*x^10*y^7*s^2+16873*z*x^9*y^7*s^2+7568*z*x^13*y^6*s^2+15136*z^2*x^12*y^6*s^2+15136*z^3*x^11*y^6*s^2+7568*z^4*x^10*y^6*s^2+7568*z*x^10*y^6*s^2+7568*z^2*x^9*y^6*s^2+41743*z*x^6*y^6*s^2+16873*z*x^14*y^5*s^2+7568*z^2*x^13*y^5*s^2+15136*z^3*x^12*y^5*s^2+32009*z^4*x^11*y^5*s^2+7568*z*x^11*y^5*s^2+7568*z^5*x^10*y^5*s^2+15136*z^2*x^10*y^5*s^2+7568*z^3*x^9*y^5*s^2+8506*z^4*x^7*y^5*s^2+39127*z*x^7*y^5*s^2+39127*z^2*x^6*y^5*s^2+41743*z^3*x^5*y^5*s^2+41743*z*x^4*y^5*s^2+16873*z^3*x^13*y^4*s^2+7568*z^4*x^12*y^4*s^2+16873*z*x^12*y^4*s^2+7568*z^5*x^11*y^4*s^2+7568*z^2*x^11*y^4*s^2+16873*z^6*x^10*y^4*s^2+7568*z^3*x^10*y^4*s^2+16873*z^4*x^9*y^4*s^2+25518*z^4*x^8*y^4*s^2+39127*z*x^8*y^4*s^2+25518*z^5*x^7*y^4*s^2+35203*z^2*x^7*y^4*s^2+8506*z^6*x^6*y^4*s^2+35203*z^3*x^6*y^4*s^2+4582*z^4*x^5*y^4*s^2+39127*z*x^5*y^4*s^2+39127*z^2*x^4*y^4*s^2+25518*z^4*x^9*y^3*s^2+41743*z*x^9*y^3*s^2+7985*z^5*x^8*y^3*s^2+39127*z^2*x^8*y^3*s^2+7985*z^6*x^7*y^3*s^2+35203*z^3*x^7*y^3*s^2+25518*z^7*x^6*y^3*s^2+16362*z^4*x^6*y^3*s^2+39127*z*x^6*y^3*s^2+21594*z^5*x^5*y^3*s^2+35203*z^2*x^5*y^3*s^2+39127*z^3*x^4*y^3*s^2+8506*z^4*x^10*y^2*s^2+25518*z^5*x^9*y^2*s^2+7985*z^6*x^8*y^2*s^2+41743*z^3*x^8*y^2*s^2+16491*z^7*x^7*y^2*s^2+21594*z^4*x^7*y^2*s^2+41743*z*x^7*y^2*s^2+25518*z^8*x^6*y^2*s^2+4061*z^5*x^6*y^2*s^2+39127*z^2*x^6*y^2*s^2+24210*z^6*x^5*y^2*s^2+39127*z^3*x^5*y^2*s^2+41743*z^4*x^4*y^2*s^2+8506*z^6*x^9*y*s^2+25518*z^7*x^8*y*s^2+8506*z^4*x^8*y*s^2+25518*z^8*x^7*y*s^2+25518*z^5*x^7*y*s^2+8506*z^9*x^6*y*s^2+25518*z^6*x^6*y*s^2+8506*z^7*x^5*y*s^2+24116*z^9*x^6*y^13*s+24116*z^11*x^7*y^12*s+29297*z^9*x^7*y^12*s+29297*z^10*x^6*y^12*s+29297*z^11*x^8*y^11*s+29297*z^9*x^8*y^11*s+29297*z^12*x^7*y^11*s+15543*z^10*x^7*y^11*s+29297*z^11*x^6*y^11*s+29297*z^11*x^9*y^10*s+24116*z^9*x^9*y^10*s+15543*z^12*x^8*y^10*s+29297*z^10*x^8*y^10*s+29297*z^13*x^7*y^10*s+29297*z^11*x^7*y^10*s+24116*z^12*x^6*y^10*s+24116*z^11*x^10*y^9*s+29297*z^12*x^9*y^9*s+29297*z^13*x^8*y^9*s+24116*z^14*x^7*y^9*s+24116*z^9*x^8*y^12+29297*z^9*x^9*y^11+29297*z^10*x^8*y^11+24116*z^11*x^7*y^11+24116*z^9*x^6*y^11+29297*z^9*x^10*y^10+15543*z^10*x^9*y^10+15543*z^11*x^8*y^10+29297*z^12*x^7*y^10+29297*z^9*x^7*y^10+29297*z^10*x^6*y^10+24116*z^9*x^11*y^9+29297*z^10*x^10*y^9+15543*z^11*x^9*y^9+39659*z^12*x^8*y^9+29297*z^9*x^8*y^9+29297*z^13*x^7*y^9+15543*z^10*x^7*y^9+29297*z^11*x^6*y^9+24116*z^11*x^10*y^8+29297*z^12*x^9*y^8+24116*z^9*x^9*y^8+29297*z^13*x^8*y^8+29297*z^10*x^8*y^8+24116*z^14*x^7*y^8+29297*z^11*x^7*y^8+24116*z^12*x^6*y^8)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#13: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(4017*z^3*x^3*y^4*s^4+27324*x^2*y^3*s^4+41200*x^2*y^2*s^2+26755*x*y*s^2+22750*z^2*x^4*y^4*s+42152*z^2*x^3*y^2*s+14244*z^2*x^3*y^2+40575*z^2*x^4*y+14342*z)*(41743*z^2*x^4*y^11*s^11+39127*z^2*x^5*y^10*s^11+39127*z^3*x^4*y^10*s^11+39127*z^2*x^6*y^9*s^11+35203*z^3*x^5*y^9*s^11+39127*z^4*x^4*y^9*s^11+41743*z^2*x^7*y^8*s^11+39127*z^3*x^6*y^8*s^11+39127*z^4*x^5*y^8*s^11+39739*z^10*x^4*y^8*s^11+41743*z^5*x^4*y^8*s^11+33115*z^10*x^5*y^7*s^11+33115*z^11*x^4*y^7*s^11+33115*z^10*x^6*y^6*s^11+23179*z^11*x^5*y^6*s^11+33115*z^12*x^4*y^6*s^11+39739*z^10*x^7*y^5*s^11+33115*z^11*x^6*y^5*s^11+33115*z^12*x^5*y^5*s^11+39739*z^13*x^4*y^5*s^11+19583*z^9*x^5*y^13*s^10+41743*z*x^4*y^13*s^10+15698*z^9*x^6*y^12*s^10+15698*z^10*x^5*y^12*s^10+41743*z^3*x^5*y^12*s^10+39127*z*x^5*y^12*s^10+39127*z^2*x^4*y^12*s^10+15698*z^9*x^7*y^11*s^10+31396*z^10*x^6*y^11*s^10+39127*z^3*x^6*y^11*s^10+39127*z*x^6*y^11*s^10+15698*z^11*x^5*y^11*s^10+39127*z^4*x^5*y^11*s^10+35203*z^2*x^5*y^11*s^10+39127*z^3*x^4*y^11*s^10+19583*z^9*x^8*y^10*s^10+15698*z^10*x^7*y^10*s^10+39127*z^3*x^7*y^10*s^10+41743*z*x^7*y^10*s^10+15698*z^11*x^6*y^10*s^10+35203*z^4*x^6*y^10*s^10+39127*z^2*x^6*y^10*s^10+19583*z^12*x^5*y^10*s^10+39127*z^5*x^5*y^10*s^10+39127*z^3*x^5*y^10*s^10+39739*z^9*x^4*y^10*s^10+41743*z^4*x^4*y^10*s^10+41743*z^3*x^8*y^9*s^10+39127*z^4*x^7*y^9*s^10+39127*z^5*x^6*y^9*s^10+39739*z^11*x^5*y^9*s^10+33115*z^9*x^5*y^9*s^10+41743*z^6*x^5*y^9*s^10+33115*z^10*x^4*y^9*s^10+33115*z^11*x^6*y^8*s^10+33115*z^9*x^6*y^8*s^10+33115*z^12*x^5*y^8*s^10+23179*z^10*x^5*y^8*s^10+33115*z^11*x^4*y^8*s^10+33115*z^11*x^7*y^7*s^10+39739*z^9*x^7*y^7*s^10+23179*z^12*x^6*y^7*s^10+33115*z^10*x^6*y^7*s^10+33115*z^13*x^5*y^7*s^10+33115*z^11*x^5*y^7*s^10+39739*z^12*x^4*y^7*s^10+39739*z^11*x^8*y^6*s^10+33115*z^12*x^7*y^6*s^10+33115*z^13*x^6*y^6*s^10+39739*z^14*x^5*y^6*s^10+19583*z^8*x^5*y^15*s^9+19583*z^10*x^6*y^14*s^9+15698*z^8*x^6*y^14*s^9+15698*z^9*x^5*y^14*s^9+15698*z^10*x^7*y^13*s^9+15698*z^8*x^7*y^13*s^9+15698*z^11*x^6*y^13*s^9+31396*z^9*x^6*y^13*s^9+15698*z^10*x^5*y^13*s^9+15698*z^10*x^8*y^12*s^9+19583*z^8*x^8*y^12*s^9+31396*z^11*x^7*y^12*s^9+15698*z^9*x^7*y^12*s^9+15698*z^12*x^6*y^12*s^9+15698*z^10*x^6*y^12*s^9+41743*z*x^6*y^12*s^9+19583*z^11*x^5*y^12*s^9+19583*z^10*x^9*y^11*s^9+15698*z^11*x^8*y^11*s^9+15698*z^12*x^7*y^11*s^9+39127*z*x^7*y^11*s^9+19583*z^13*x^6*y^11*s^9+39127*z^2*x^6*y^11*s^9+41743*z^3*x^5*y^11*s^9+41743*z*x^4*y^11*s^9+39127*z*x^8*y^10*s^9+35203*z^2*x^7*y^10*s^9+35203*z^3*x^6*y^10*s^9+39127*z^4*x^5*y^10*s^9+39127*z*x^5*y^10*s^9+39127*z^2*x^4*y^10*s^9+41743*z*x^9*y^9*s^9+39127*z^2*x^8*y^9*s^9+35203*z^3*x^7*y^9*s^9+39739*z^9*x^6*y^9*s^9+33895*z^4*x^6*y^9*s^9+39127*z*x^6*y^9*s^9+39127*z^5*x^5*y^9*s^9+35203*z^2*x^5*y^9*s^9+39127*z^3*x^4*y^9*s^9+41743*z^3*x^8*y^8*s^9+33115*z^9*x^7*y^8*s^9+39127*z^4*x^7*y^8*s^9+41743*z*x^7*y^8*s^9+33115*z^10*x^6*y^8*s^9+39127*z^5*x^6*y^8*s^9+39127*z^2*x^6*y^8*s^9+39739*z^11*x^5*y^8*s^9+41743*z^6*x^5*y^8*s^9+39127*z^3*x^5*y^8*s^9+39739*z^9*x^4*y^8*s^9+41743*z^4*x^4*y^8*s^9+33115*z^9*x^8*y^7*s^9+23179*z^10*x^7*y^7*s^9+23179*z^11*x^6*y^7*s^9+33115*z^12*x^5*y^7*s^9+33115*z^9*x^5*y^7*s^9+33115*z^10*x^4*y^7*s^9+39739*z^9*x^9*y^6*s^9+33115*z^10*x^8*y^6*s^9+23179*z^11*x^7*y^6*s^9+19867*z^12*x^6*y^6*s^9+33115*z^9*x^6*y^6*s^9+33115*z^13*x^5*y^6*s^9+23179*z^10*x^5*y^6*s^9+33115*z^11*x^4*y^6*s^9+39739*z^11*x^8*y^5*s^9+33115*z^12*x^7*y^5*s^9+39739*z^9*x^7*y^5*s^9+33115*z^13*x^6*y^5*s^9+33115*z^10*x^6*y^5*s^9+39739*z^14*x^5*y^5*s^9+33115*z^11*x^5*y^5*s^9+39739*z^12*x^4*y^5*s^9+19583*z^8*x^7*y^14*s^8+15698*z^8*x^8*y^13*s^8+15698*z^9*x^7*y^13*s^8+19583*z^10*x^6*y^13*s^8+19583*z^8*x^5*y^13*s^8+15698*z^8*x^9*y^12*s^8+31396*z^9*x^8*y^12*s^8+31396*z^10*x^7*y^12*s^8+15698*z^11*x^6*y^12*s^8+15698*z^8*x^6*y^12*s^8+15698*z^9*x^5*y^12*s^8+19583*z^8*x^10*y^11*s^8+15698*z^9*x^9*y^11*s^8+31396*z^10*x^8*y^11*s^8+7928*z^11*x^7*y^11*s^8+15698*z^8*x^7*y^11*s^8+15698*z^12*x^6*y^11*s^8+31396*z^9*x^6*y^11*s^8+15698*z^10*x^5*y^11*s^8+19583*z^10*x^9*y^10*s^8+15698*z^11*x^8*y^10*s^8+19583*z^8*x^8*y^10*s^8+15698*z^12*x^7*y^10*s^8+15698*z^9*x^7*y^10*s^8+19583*z^13*x^6*y^10*s^8+15698*z^10*x^6*y^10*s^8+19583*z^11*x^5*y^10*s^8+16873*z^3*x^3*y^5*s^8+7568*z^3*x^4*y^4*s^8+7568*z^4*x^3*y^4*s^8+7568*z^3*x^5*y^3*s^8+15136*z^4*x^4*y^3*s^8+7568*z^5*x^3*y^3*s^8+16873*z^3*x^6*y^2*s^8+7568*z^4*x^5*y^2*s^8+7568*z^5*x^4*y^2*s^8+16873*z^6*x^3*y^2*s^8+16873*z^2*x^3*y^7*s^7+16873*z^4*x^4*y^6*s^7+7568*z^2*x^4*y^6*s^7+7568*z^3*x^3*y^6*s^7+7568*z^4*x^5*y^5*s^7+7568*z^2*x^5*y^5*s^7+7568*z^5*x^4*y^5*s^7+15136*z^3*x^4*y^5*s^7+7568*z^4*x^3*y^5*s^7+7568*z^4*x^6*y^4*s^7+16873*z^2*x^6*y^4*s^7+15136*z^5*x^5*y^4*s^7+7568*z^3*x^5*y^4*s^7+7568*z^6*x^4*y^4*s^7+7568*z^4*x^4*y^4*s^7+16873*z^5*x^3*y^4*s^7+16873*z^4*x^7*y^3*s^7+7568*z^5*x^6*y^3*s^7+7568*z^6*x^5*y^3*s^7+16873*z^7*x^4*y^3*s^7+16873*z^2*x^5*y^6*s^6+7568*z^2*x^6*y^5*s^6+7568*z^3*x^5*y^5*s^6+16873*z^4*x^4*y^5*s^6+16873*z^2*x^3*y^5*s^6+7568*z^2*x^7*y^4*s^6+15136*z^3*x^6*y^4*s^6+15136*z^4*x^5*y^4*s^6+7568*z^5*x^4*y^4*s^6+7568*z^2*x^4*y^4*s^6+7568*z^3*x^3*y^4*s^6+16873*z^2*x^8*y^3*s^6+7568*z^3*x^7*y^3*s^6+15136*z^4*x^6*y^3*s^6+32009*z^5*x^5*y^3*s^6+7568*z^2*x^5*y^3*s^6+7568*z^6*x^4*y^3*s^6+15136*z^3*x^4*y^3*s^6+7568*z^4*x^3*y^3*s^6+16873*z^4*x^7*y^2*s^6+7568*z^5*x^6*y^2*s^6+16873*z^2*x^6*y^2*s^6+7568*z^6*x^5*y^2*s^6+7568*z^3*x^5*y^2*s^6+16873*z^7*x^4*y^2*s^6+7568*z^4*x^4*y^2*s^6+16873*z^5*x^3*y^2*s^6+21629*z*x*y^13*s^5+21836*z*x^2*y^12*s^5+21836*z^2*x*y^12*s^5+21836*z*x^3*y^11*s^5+621*z^2*x^2*y^11*s^5+21836*z^3*x*y^11*s^5+21629*z*x^4*y^10*s^5+21836*z^2*x^3*y^10*s^5+21836*z^3*x^2*y^10*s^5+21629*z^4*x*y^10*s^5+24116*z^3*x^5*y^6*s^5+29297*z^3*x^6*y^5*s^5+29297*z^4*x^5*y^5*s^5+13845*z^7*x^4*y^5*s^5+29297*z^3*x^7*y^4*s^5+15543*z^4*x^6*y^4*s^5+41535*z^7*x^5*y^4*s^5+29297*z^5*x^5*y^4*s^5+41535*z^8*x^4*y^4*s^5+24116*z^3*x^8*y^3*s^5+29297*z^4*x^7*y^3*s^5+41535*z^7*x^6*y^3*s^5+29297*z^5*x^6*y^3*s^5+40019*z^8*x^5*y^3*s^5+24116*z^6*x^5*y^3*s^5+41535*z^9*x^4*y^3*s^5+13845*z^7*x^7*y^2*s^5+41535*z^8*x^6*y^2*s^5+41535*z^9*x^5*y^2*s^5+13845*z^10*x^4*y^2*s^5+21629*x*y^15*s^4+21629*z^2*x^2*y^14*s^4+21836*x^2*y^14*s^4+21836*z*x*y^14*s^4+21836*z^2*x^3*y^13*s^4+21836*x^3*y^13*s^4+21836*z^3*x^2*y^13*s^4+621*z*x^2*y^13*s^4+21836*z^2*x*y^13*s^4+8506*z^2*x^8*y^12*s^4+21836*z^2*x^4*y^12*s^4+21629*x^4*y^12*s^4+621*z^3*x^3*y^12*s^4+21836*z*x^3*y^12*s^4+21836*z^4*x^2*y^12*s^4+21836*z^2*x^2*y^12*s^4+21629*z^3*x*y^12*s^4+25518*z^2*x^9*y^11*s^4+25518*z^3*x^8*y^11*s^4+21629*z^2*x^5*y^11*s^4+21836*z^3*x^4*y^11*s^4+21836*z^4*x^3*y^11*s^4+21629*z^5*x^2*y^11*s^4+25518*z^2*x^10*y^10*s^4+7985*z^3*x^9*y^10*s^4+25518*z^4*x^8*y^10*s^4+8506*z^2*x^11*y^9*s^4+25518*z^3*x^10*y^9*s^4+25518*z^4*x^9*y^9*s^4+8506*z^5*x^8*y^9*s^4+24116*z^2*x^5*y^8*s^4+24116*z^4*x^6*y^7*s^4+29297*z^2*x^6*y^7*s^4+29297*z^3*x^5*y^7*s^4+13845*z^6*x^4*y^7*s^4+29297*z^4*x^7*y^6*s^4+29297*z^2*x^7*y^6*s^4+29297*z^5*x^6*y^6*s^4+15543*z^3*x^6*y^6*s^4+13845*z^8*x^5*y^6*s^4+41535*z^6*x^5*y^6*s^4+29297*z^4*x^5*y^6*s^4+41535*z^7*x^4*y^6*s^4+29297*z^4*x^8*y^5*s^4+24116*z^2*x^8*y^5*s^4+15543*z^5*x^7*y^5*s^4+29297*z^3*x^7*y^5*s^4+41535*z^8*x^6*y^5*s^4+27781*z^6*x^6*y^5*s^4+29297*z^4*x^6*y^5*s^4+41535*z^9*x^5*y^5*s^4+40019*z^7*x^5*y^5*s^4+24116*z^5*x^5*y^5*s^4+41535*z^8*x^4*y^5*s^4+24116*z^4*x^9*y^4*s^4+29297*z^5*x^8*y^4*s^4+41535*z^8*x^7*y^4*s^4+91*z^6*x^7*y^4*s^4+40019*z^9*x^6*y^4*s^4+22600*z^7*x^6*y^4*s^4+41535*z^10*x^5*y^4*s^4+41535*z^8*x^5*y^4*s^4+13845*z^9*x^4*y^4*s^4+13845*z^8*x^8*y^3*s^4+41535*z^9*x^7*y^3*s^4+41535*z^10*x^6*y^3*s^4+13845*z^11*x^5*y^3*s^4+8506*z*x^8*y^14*s^3+21629*x^3*y^14*s^3+8506*z^3*x^9*y^13*s^3+25518*z*x^9*y^13*s^3+25518*z^2*x^8*y^13*s^3+21836*x^4*y^13*s^3+21836*z*x^3*y^13*s^3+21629*z^2*x^2*y^13*s^3+21629*x*y^13*s^3+25518*z^3*x^10*y^12*s^3+25518*z*x^10*y^12*s^3+25518*z^4*x^9*y^12*s^3+7985*z^2*x^9*y^12*s^3+25518*z^3*x^8*y^12*s^3+21836*x^5*y^12*s^3+621*z*x^4*y^12*s^3+621*z^2*x^3*y^12*s^3+21836*z^3*x^2*y^12*s^3+21836*x^2*y^12*s^3+21836*z*x*y^12*s^3+25518*z^3*x^11*y^11*s^3+8506*z*x^11*y^11*s^3+7985*z^4*x^10*y^11*s^3+25518*z^2*x^10*y^11*s^3+25518*z^5*x^9*y^11*s^3+25518*z^3*x^9*y^11*s^3+8506*z^4*x^8*y^11*s^3+21629*x^6*y^11*s^3+21836*z*x^5*y^11*s^3+621*z^2*x^4*y^11*s^3+22250*z^3*x^3*y^11*s^3+21836*x^3*y^11*s^3+21836*z^4*x^2*y^11*s^3+621*z*x^2*y^11*s^3+21836*z^2*x*y^11*s^3+8506*z^3*x^12*y^10*s^3+25518*z^4*x^11*y^10*s^3+25518*z^5*x^10*y^10*s^3+8506*z^6*x^9*y^10*s^3+21629*z^2*x^5*y^10*s^3+21836*z^3*x^4*y^10*s^3+21629*x^4*y^10*s^3+21836*z^4*x^3*y^10*s^3+21836*z*x^3*y^10*s^3+21629*z^5*x^2*y^10*s^3+21836*z^2*x^2*y^10*s^3+21629*z^3*x*y^10*s^3+29049*z^7*x^9*y^7*s^3+24116*z^2*x^7*y^7*s^3+1045*z^7*x^10*y^6*s^3+1045*z^8*x^9*y^6*s^3+29297*z^2*x^8*y^6*s^3+29297*z^3*x^7*y^6*s^3+13845*z^6*x^6*y^6*s^3+24116*z^4*x^6*y^6*s^3+24116*z^2*x^5*y^6*s^3+1045*z^7*x^11*y^5*s^3+2090*z^8*x^10*y^5*s^3+1045*z^9*x^9*y^5*s^3+29297*z^2*x^9*y^5*s^3+15543*z^3*x^8*y^5*s^3+41535*z^6*x^7*y^5*s^3+15543*z^4*x^7*y^5*s^3+41535*z^7*x^6*y^5*s^3+29297*z^5*x^6*y^5*s^3+29297*z^2*x^6*y^5*s^3+13845*z^8*x^5*y^5*s^3+29297*z^3*x^5*y^5*s^3+13845*z^6*x^4*y^5*s^3+29049*z^7*x^12*y^4*s^3+1045*z^8*x^11*y^4*s^3+1045*z^9*x^10*y^4*s^3+24116*z^2*x^10*y^4*s^3+29049*z^10*x^9*y^4*s^3+29297*z^3*x^9*y^4*s^3+41535*z^6*x^8*y^4*s^3+15543*z^4*x^8*y^4*s^3+40019*z^7*x^7*y^4*s^3+39659*z^5*x^7*y^4*s^3+29297*z^2*x^7*y^4*s^3+40019*z^8*x^6*y^4*s^3+29297*z^6*x^6*y^4*s^3+15543*z^3*x^6*y^4*s^3+41535*z^9*x^5*y^4*s^3+41535*z^6*x^5*y^4*s^3+29297*z^4*x^5*y^4*s^3+41535*z^7*x^4*y^4*s^3+13845*z^6*x^9*y^3*s^3+24116*z^4*x^9*y^3*s^3+41535*z^7*x^8*y^3*s^3+29297*z^5*x^8*y^3*s^3+24116*z^2*x^8*y^3*s^3+40019*z^8*x^7*y^3*s^3+29297*z^6*x^7*y^3*s^3+29297*z^3*x^7*y^3*s^3+10813*z^9*x^6*y^3*s^3+24116*z^7*x^6*y^3*s^3+41535*z^6*x^6*y^3*s^3+29297*z^4*x^6*y^3*s^3+41535*z^10*x^5*y^3*s^3+40019*z^7*x^5*y^3*s^3+24116*z^5*x^5*y^3*s^3+41535*z^8*x^4*y^3*s^3+13845*z^8*x^8*y^2*s^3+41535*z^9*x^7*y^2*s^3+13845*z^6*x^7*y^2*s^3+41535*z^10*x^6*y^2*s^3+41535*z^7*x^6*y^2*s^3+13845*z^11*x^5*y^2*s^3+41535*z^8*x^5*y^2*s^3+13845*z^9*x^4*y^2*s^3+8506*z*x^10*y^13*s^2+25518*z*x^11*y^12*s^2+25518*z^2*x^10*y^12*s^2+8506*z^3*x^9*y^12*s^2+8506*z*x^8*y^12*s^2+25518*z*x^12*y^11*s^2+7985*z^2*x^11*y^11*s^2+7985*z^3*x^10*y^11*s^2+25518*z^4*x^9*y^11*s^2+25518*z*x^9*y^11*s^2+25518*z^2*x^8*y^11*s^2+8506*z*x^13*y^10*s^2+25518*z^2*x^12*y^10*s^2+7985*z^3*x^11*y^10*s^2+16491*z^4*x^10*y^10*s^2+25518*z*x^10*y^10*s^2+25518*z^5*x^9*y^10*s^2+7985*z^2*x^9*y^10*s^2+25518*z^3*x^8*y^10*s^2+8506*z^3*x^12*y^9*s^2+25518*z^4*x^11*y^9*s^2+8506*z*x^11*y^9*s^2+25518*z^5*x^10*y^9*s^2+25518*z^2*x^10*y^9*s^2+37555*z^6*x^9*y^9*s^2+25518*z^3*x^9*y^9*s^2+8506*z^4*x^8*y^9*s^2+29049*z^8*x^10*y^8*s^2+1045*z^6*x^10*y^8*s^2+1045*z^7*x^9*y^8*s^2+1045*z^8*x^11*y^7*s^2+1045*z^6*x^11*y^7*s^2+1045*z^9*x^10*y^7*s^2+2090*z^7*x^10*y^7*s^2+1045*z^8*x^9*y^7*s^2+1045*z^8*x^12*y^6*s^2+29049*z^6*x^12*y^6*s^2+2090*z^9*x^11*y^6*s^2+1045*z^7*x^11*y^6*s^2+1045*z^10*x^10*y^6*s^2+1045*z^8*x^10*y^6*s^2+29049*z^9*x^9*y^6*s^2+29049*z^8*x^13*y^5*s^2+1045*z^9*x^12*y^5*s^2+1045*z^10*x^11*y^5*s^2+29049*z^11*x^10*y^5*s^2+29049*z^6*x^11*y^8*s+1045*z^6*x^12*y^7*s+1045*z^7*x^11*y^7*s+29049*z^8*x^10*y^7*s+29049*z^6*x^9*y^7*s+1045*z^6*x^13*y^6*s+2090*z^7*x^12*y^6*s+2090*z^8*x^11*y^6*s+1045*z^9*x^10*y^6*s+1045*z^6*x^10*y^6*s+1045*z^7*x^9*y^6*s+29049*z^6*x^14*y^5*s+1045*z^7*x^13*y^5*s+2090*z^8*x^12*y^5*s+31139*z^9*x^11*y^5*s+1045*z^6*x^11*y^5*s+1045*z^10*x^10*y^5*s+2090*z^7*x^10*y^5*s+1045*z^8*x^9*y^5*s+29049*z^8*x^13*y^4*s+1045*z^9*x^12*y^4*s+29049*z^6*x^12*y^4*s+1045*z^10*x^11*y^4*s+1045*z^7*x^11*y^4*s+29049*z^11*x^10*y^4*s+1045*z^8*x^10*y^4*s+29049*z^9*x^9*y^4*s)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#14: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(16873*z^4*x^6*y^7*s^11+7568*z^4*x^7*y^6*s^11+7568*z^5*x^6*y^6*s^11+7568*z^4*x^8*y^5*s^11+15136*z^5*x^7*y^5*s^11+7568*z^6*x^6*y^5*s^11+16873*z^4*x^9*y^4*s^11+7568*z^5*x^8*y^4*s^11+7568*z^6*x^7*y^4*s^11+16873*z^7*x^6*y^4*s^11+16873*z^3*x^6*y^9*s^10+16873*z^5*x^7*y^8*s^10+7568*z^3*x^7*y^8*s^10+7568*z^4*x^6*y^8*s^10+7568*z^5*x^8*y^7*s^10+7568*z^3*x^8*y^7*s^10+7568*z^6*x^7*y^7*s^10+15136*z^4*x^7*y^7*s^10+7568*z^5*x^6*y^7*s^10+7568*z^5*x^9*y^6*s^10+16873*z^3*x^9*y^6*s^10+15136*z^6*x^8*y^6*s^10+7568*z^4*x^8*y^6*s^10+7568*z^7*x^7*y^6*s^10+7568*z^5*x^7*y^6*s^10+16873*z^6*x^6*y^6*s^10+16873*z^5*x^10*y^5*s^10+7568*z^6*x^9*y^5*s^10+7568*z^7*x^8*y^5*s^10+16873*z^8*x^7*y^5*s^10+41743*z^8*x^8*y^13*s^9+39127*z^8*x^9*y^12*s^9+39127*z^9*x^8*y^12*s^9+39127*z^8*x^10*y^11*s^9+35203*z^9*x^9*y^11*s^9+19583*z^3*x^9*y^11*s^9+39127*z^10*x^8*y^11*s^9+41743*z^8*x^11*y^10*s^9+39127*z^9*x^10*y^10*s^9+15698*z^3*x^10*y^10*s^9+39127*z^10*x^9*y^10*s^9+15698*z^4*x^9*y^10*s^9+41743*z^11*x^8*y^10*s^9+15698*z^3*x^11*y^9*s^9+31396*z^4*x^10*y^9*s^9+15698*z^5*x^9*y^9*s^9+19583*z^3*x^12*y^8*s^9+15698*z^4*x^11*y^8*s^9+15698*z^5*x^10*y^8*s^9+19583*z^6*x^9*y^8*s^9+16873*z^3*x^8*y^8*s^9+7568*z^3*x^9*y^7*s^9+7568*z^4*x^8*y^7*s^9+16873*z^5*x^7*y^7*s^9+16873*z^3*x^6*y^7*s^9+7568*z^3*x^10*y^6*s^9+15136*z^4*x^9*y^6*s^9+15136*z^5*x^8*y^6*s^9+7568*z^6*x^7*y^6*s^9+7568*z^3*x^7*y^6*s^9+7568*z^4*x^6*y^6*s^9+16873*z^3*x^11*y^5*s^9+7568*z^4*x^10*y^5*s^9+15136*z^5*x^9*y^5*s^9+32009*z^6*x^8*y^5*s^9+7568*z^3*x^8*y^5*s^9+7568*z^7*x^7*y^5*s^9+15136*z^4*x^7*y^5*s^9+7568*z^5*x^6*y^5*s^9+16873*z^5*x^10*y^4*s^9+7568*z^6*x^9*y^4*s^9+16873*z^3*x^9*y^4*s^9+7568*z^7*x^8*y^4*s^9+7568*z^4*x^8*y^4*s^9+16873*z^8*x^7*y^4*s^9+7568*z^5*x^7*y^4*s^9+16873*z^6*x^6*y^4*s^9+41743*z^7*x^8*y^15*s^8+41743*z^9*x^9*y^14*s^8+39127*z^7*x^9*y^14*s^8+39127*z^8*x^8*y^14*s^8+39127*z^9*x^10*y^13*s^8+39127*z^7*x^10*y^13*s^8+39127*z^10*x^9*y^13*s^8+35203*z^8*x^9*y^13*s^8+19583*z^2*x^9*y^13*s^8+39127*z^9*x^8*y^13*s^8+39127*z^9*x^11*y^12*s^8+41743*z^7*x^11*y^12*s^8+35203*z^10*x^10*y^12*s^8+39127*z^8*x^10*y^12*s^8+19583*z^4*x^10*y^12*s^8+15698*z^2*x^10*y^12*s^8+39127*z^11*x^9*y^12*s^8+39127*z^9*x^9*y^12*s^8+15698*z^3*x^9*y^12*s^8+41743*z^10*x^8*y^12*s^8+41743*z^9*x^12*y^11*s^8+39127*z^10*x^11*y^11*s^8+15698*z^4*x^11*y^11*s^8+15698*z^2*x^11*y^11*s^8+39127*z^11*x^10*y^11*s^8+15698*z^5*x^10*y^11*s^8+31396*z^3*x^10*y^11*s^8+41743*z^12*x^9*y^11*s^8+15698*z^4*x^9*y^11*s^8+15698*z^4*x^12*y^10*s^8+19583*z^2*x^12*y^10*s^8+31396*z^5*x^11*y^10*s^8+15698*z^3*x^11*y^10*s^8+15698*z^6*x^10*y^10*s^8+15698*z^4*x^10*y^10*s^8+19583*z^5*x^9*y^10*s^8+21629*z^8*x*y^10*s^8+19583*z^4*x^13*y^9*s^8+15698*z^5*x^12*y^9*s^8+15698*z^6*x^11*y^9*s^8+19583*z^7*x^10*y^9*s^8+21836*z^8*x^2*y^9*s^8+21836*z^9*x*y^9*s^8+21836*z^8*x^3*y^8*s^8+621*z^9*x^2*y^8*s^8+21836*z^10*x*y^8*s^8+21629*z^8*x^4*y^7*s^8+21836*z^9*x^3*y^7*s^8+21836*z^10*x^2*y^7*s^8+21629*z^11*x*y^7*s^8+41743*z^7*x^10*y^14*s^7+39127*z^7*x^11*y^13*s^7+39127*z^8*x^10*y^13*s^7+41743*z^9*x^9*y^13*s^7+41743*z^7*x^8*y^13*s^7+29049*z^10*x^7*y^13*s^7+39127*z^7*x^12*y^12*s^7+35203*z^8*x^11*y^12*s^7+19583*z^2*x^11*y^12*s^7+35203*z^9*x^10*y^12*s^7+39127*z^10*x^9*y^12*s^7+39127*z^7*x^9*y^12*s^7+1045*z^10*x^8*y^12*s^7+39127*z^8*x^8*y^12*s^7+1045*z^11*x^7*y^12*s^7+21629*z^7*x*y^12*s^7+41743*z^7*x^13*y^11*s^7+39127*z^8*x^12*y^11*s^7+15698*z^2*x^12*y^11*s^7+35203*z^9*x^11*y^11*s^7+15698*z^3*x^11*y^11*s^7+33895*z^10*x^10*y^11*s^7+39127*z^7*x^10*y^11*s^7+19583*z^4*x^10*y^11*s^7+39127*z^11*x^9*y^11*s^7+1045*z^10*x^9*y^11*s^7+35203*z^8*x^9*y^11*s^7+19583*z^2*x^9*y^11*s^7+2090*z^11*x^8*y^11*s^7+39127*z^9*x^8*y^11*s^7+1045*z^12*x^7*y^11*s^7+21629*z^9*x^2*y^11*s^7+21836*z^7*x^2*y^11*s^7+21836*z^8*x*y^11*s^7+15698*z^2*x^13*y^10*s^7+41743*z^9*x^12*y^10*s^7+31396*z^3*x^12*y^10*s^7+39127*z^10*x^11*y^10*s^7+41743*z^7*x^11*y^10*s^7+31396*z^4*x^11*y^10*s^7+39127*z^11*x^10*y^10*s^7+29049*z^10*x^10*y^10*s^7+39127*z^8*x^10*y^10*s^7+15698*z^5*x^10*y^10*s^7+15698*z^2*x^10*y^10*s^7+41743*z^12*x^9*y^10*s^7+1045*z^11*x^9*y^10*s^7+39127*z^9*x^9*y^10*s^7+15698*z^3*x^9*y^10*s^7+1045*z^12*x^8*y^10*s^7+41743*z^10*x^8*y^10*s^7+29049*z^13*x^7*y^10*s^7+21836*z^9*x^3*y^10*s^7+21836*z^7*x^3*y^10*s^7+21836*z^10*x^2*y^10*s^7+621*z^8*x^2*y^10*s^7+21836*z^9*x*y^10*s^7+19583*z^2*x^14*y^9*s^7+15698*z^3*x^13*y^9*s^7+31396*z^4*x^12*y^9*s^7+7928*z^5*x^11*y^9*s^7+15698*z^2*x^11*y^9*s^7+15698*z^6*x^10*y^9*s^7+31396*z^3*x^10*y^9*s^7+15698*z^4*x^9*y^9*s^7+21836*z^9*x^4*y^9*s^7+21629*z^7*x^4*y^9*s^7+621*z^10*x^3*y^9*s^7+21836*z^8*x^3*y^9*s^7+21836*z^11*x^2*y^9*s^7+21836*z^9*x^2*y^9*s^7+21629*z^10*x*y^9*s^7+19583*z^4*x^13*y^8*s^7+15698*z^5*x^12*y^8*s^7+19583*z^2*x^12*y^8*s^7+15698*z^6*x^11*y^8*s^7+15698*z^3*x^11*y^8*s^7+19583*z^7*x^10*y^8*s^7+15698*z^4*x^10*y^8*s^7+39739*z^6*x^9*y^8*s^7+19583*z^5*x^9*y^8*s^7+21629*z^9*x^5*y^8*s^7+21836*z^10*x^4*y^8*s^7+21836*z^11*x^3*y^8*s^7+21629*z^12*x^2*y^8*s^7+33115*z^6*x^10*y^7*s^7+33115*z^7*x^9*y^7*s^7+33115*z^6*x^11*y^6*s^7+23179*z^7*x^10*y^6*s^7+33115*z^8*x^9*y^6*s^7+39739*z^6*x^12*y^5*s^7+33115*z^7*x^11*y^5*s^7+33115*z^8*x^10*y^5*s^7+39739*z^9*x^9*y^5*s^7+29049*z^9*x^7*y^15*s^6+29049*z^11*x^8*y^14*s^6+1045*z^9*x^8*y^14*s^6+1045*z^10*x^7*y^14*s^6+1045*z^11*x^9*y^13*s^6+1045*z^9*x^9*y^13*s^6+1045*z^12*x^8*y^13*s^6+2090*z^10*x^8*y^13*s^6+1045*z^11*x^7*y^13*s^6+8506*z^7*x^6*y^13*s^6+1045*z^11*x^10*y^12*s^6+29049*z^9*x^10*y^12*s^6+2090*z^12*x^9*y^12*s^6+1045*z^10*x^9*y^12*s^6+1045*z^13*x^8*y^12*s^6+1045*z^11*x^8*y^12*s^6+29049*z^12*x^7*y^12*s^6+25518*z^7*x^7*y^12*s^6+25518*z^8*x^6*y^12*s^6+29049*z^11*x^11*y^11*s^6+1045*z^12*x^10*y^11*s^6+1045*z^13*x^9*y^11*s^6+29049*z^14*x^8*y^11*s^6+25518*z^7*x^8*y^11*s^6+7985*z^8*x^7*y^11*s^6+25518*z^9*x^6*y^11*s^6+21629*z^7*x^3*y^11*s^6+8506*z^7*x^9*y^10*s^6+39739*z^5*x^9*y^10*s^6+25518*z^8*x^8*y^10*s^6+25518*z^9*x^7*y^10*s^6+8506*z^10*x^6*y^10*s^6+21836*z^7*x^4*y^10*s^6+21836*z^8*x^3*y^10*s^6+21629*z^9*x^2*y^10*s^6+21629*z^7*x*y^10*s^6+39739*z^7*x^10*y^9*s^6+33115*z^5*x^10*y^9*s^6+33115*z^6*x^9*y^9*s^6+21836*z^7*x^5*y^9*s^6+621*z^8*x^4*y^9*s^6+621*z^9*x^3*y^9*s^6+21836*z^10*x^2*y^9*s^6+21836*z^7*x^2*y^9*s^6+21836*z^8*x*y^9*s^6+33115*z^7*x^11*y^8*s^6+33115*z^5*x^11*y^8*s^6+33115*z^8*x^10*y^8*s^6+23179*z^6*x^10*y^8*s^6+33115*z^7*x^9*y^8*s^6+21629*z^7*x^6*y^8*s^6+21836*z^8*x^5*y^8*s^6+621*z^9*x^4*y^8*s^6+22250*z^10*x^3*y^8*s^6+21836*z^7*x^3*y^8*s^6+21836*z^11*x^2*y^8*s^6+621*z^8*x^2*y^8*s^6+21836*z^9*x*y^8*s^6+33115*z^7*x^12*y^7*s^6+39739*z^5*x^12*y^7*s^6+23179*z^8*x^11*y^7*s^6+33115*z^6*x^11*y^7*s^6+33115*z^9*x^10*y^7*s^6+33115*z^7*x^10*y^7*s^6+39739*z^8*x^9*y^7*s^6+21629*z^9*x^5*y^7*s^6+21836*z^10*x^4*y^7*s^6+21629*z^7*x^4*y^7*s^6+21836*z^11*x^3*y^7*s^6+21836*z^8*x^3*y^7*s^6+21629*z^12*x^2*y^7*s^6+21836*z^9*x^2*y^7*s^6+21629*z^10*x*y^7*s^6+39739*z^7*x^13*y^6*s^6+33115*z^8*x^12*y^6*s^6+33115*z^9*x^11*y^6*s^6+39739*z^10*x^10*y^6*s^6+8506*z^6*x^6*y^15*s^5+29049*z^9*x^9*y^14*s^5+8506*z^8*x^7*y^14*s^5+25518*z^6*x^7*y^14*s^5+25518*z^7*x^6*y^14*s^5+1045*z^9*x^10*y^13*s^5+1045*z^10*x^9*y^13*s^5+29049*z^11*x^8*y^13*s^5+25518*z^8*x^8*y^13*s^5+25518*z^6*x^8*y^13*s^5+11516*z^9*x^7*y^13*s^5+7985*z^7*x^7*y^13*s^5+25518*z^8*x^6*y^13*s^5+1045*z^9*x^11*y^12*s^5+2090*z^10*x^10*y^12*s^5+2090*z^11*x^9*y^12*s^5+25518*z^8*x^9*y^12*s^5+8506*z^6*x^9*y^12*s^5+1045*z^12*x^8*y^12*s^5+9030*z^9*x^8*y^12*s^5+25518*z^7*x^8*y^12*s^5+26563*z^10*x^7*y^12*s^5+25518*z^8*x^7*y^12*s^5+8506*z^9*x^6*y^12*s^5+29049*z^9*x^12*y^11*s^5+1045*z^10*x^11*y^11*s^5+2090*z^11*x^10*y^11*s^5+8506*z^8*x^10*y^11*s^5+31139*z^12*x^9*y^11*s^5+26563*z^9*x^9*y^11*s^5+1045*z^13*x^8*y^11*s^5+27608*z^10*x^8*y^11*s^5+9551*z^11*x^7*y^11*s^5+29049*z^11*x^11*y^10*s^5+1045*z^12*x^10*y^10*s^5+29049*z^9*x^10*y^10*s^5+1045*z^13*x^9*y^10*s^5+1045*z^10*x^9*y^10*s^5+29049*z^14*x^8*y^10*s^5+1045*z^11*x^8*y^10*s^5+29049*z^12*x^7*y^10*s^5+39739*z^5*x^11*y^9*s^5+33115*z^5*x^12*y^8*s^5+33115*z^6*x^11*y^8*s^5+39739*z^7*x^10*y^8*s^5+39739*z^5*x^9*y^8*s^5+33115*z^5*x^13*y^7*s^5+23179*z^6*x^12*y^7*s^5+23179*z^7*x^11*y^7*s^5+33115*z^8*x^10*y^7*s^5+33115*z^5*x^10*y^7*s^5+33115*z^6*x^9*y^7*s^5+39739*z^5*x^14*y^6*s^5+33115*z^6*x^13*y^6*s^5+23179*z^7*x^12*y^6*s^5+19867*z^8*x^11*y^6*s^5+33115*z^5*x^11*y^6*s^5+33115*z^9*x^10*y^6*s^5+23179*z^6*x^10*y^6*s^5+33115*z^7*x^9*y^6*s^5+39739*z^7*x^13*y^5*s^5+33115*z^8*x^12*y^5*s^5+39739*z^5*x^12*y^5*s^5+33115*z^9*x^11*y^5*s^5+33115*z^6*x^11*y^5*s^5+39739*z^10*x^10*y^5*s^5+33115*z^7*x^10*y^5*s^5+39739*z^8*x^9*y^5*s^5+13845*z^4*x^4*y^5*s^5+41535*z^4*x^5*y^4*s^5+41535*z^5*x^4*y^4*s^5+41535*z^4*x^6*y^3*s^5+40019*z^5*x^5*y^3*s^5+41535*z^6*x^4*y^3*s^5+13845*z^4*x^7*y^2*s^5+41535*z^5*x^6*y^2*s^5+41535*z^6*x^5*y^2*s^5+13845*z^7*x^4*y^2*s^5+8506*z^6*x^8*y^14*s^4+25518*z^6*x^9*y^13*s^4+25518*z^7*x^8*y^13*s^4+8506*z^8*x^7*y^13*s^4+8506*z^6*x^6*y^13*s^4+25518*z^6*x^10*y^12*s^4+7985*z^7*x^9*y^12*s^4+7985*z^8*x^8*y^12*s^4+25518*z^9*x^7*y^12*s^4+25518*z^6*x^7*y^12*s^4+25518*z^7*x^6*y^12*s^4+8506*z^6*x^11*y^11*s^4+25518*z^7*x^10*y^11*s^4+7985*z^8*x^9*y^11*s^4+16491*z^9*x^8*y^11*s^4+25518*z^6*x^8*y^11*s^4+25518*z^10*x^7*y^11*s^4+7985*z^7*x^7*y^11*s^4+25518*z^8*x^6*y^11*s^4+8506*z^8*x^10*y^10*s^4+25518*z^9*x^9*y^10*s^4+8506*z^6*x^9*y^10*s^4+25518*z^10*x^8*y^10*s^4+25518*z^7*x^8*y^10*s^4+8506*z^11*x^7*y^10*s^4+25518*z^8*x^7*y^10*s^4+8506*z^9*x^6*y^10*s^4+24116*z^5*x^10*y^9*s^4+29297*z^5*x^11*y^8*s^4+29297*z^6*x^10*y^8*s^4+29297*z^5*x^12*y^7*s^4+15543*z^6*x^11*y^7*s^4+29297*z^7*x^10*y^7*s^4+13845*z^3*x^4*y^7*s^4+24116*z^5*x^13*y^6*s^4+29297*z^6*x^12*y^6*s^4+29297*z^7*x^11*y^6*s^4+24116*z^8*x^10*y^6*s^4+13845*z^5*x^5*y^6*s^4+41535*z^3*x^5*y^6*s^4+41535*z^4*x^4*y^6*s^4+41535*z^5*x^6*y^5*s^4+41535*z^3*x^6*y^5*s^4+41535*z^6*x^5*y^5*s^4+40019*z^4*x^5*y^5*s^4+41535*z^5*x^4*y^5*s^4+41535*z^5*x^7*y^4*s^4+13845*z^3*x^7*y^4*s^4+40019*z^6*x^6*y^4*s^4+41535*z^4*x^6*y^4*s^4+41535*z^7*x^5*y^4*s^4+41535*z^5*x^5*y^4*s^4+13845*z^6*x^4*y^4*s^4+13845*z^5*x^8*y^3*s^4+41535*z^6*x^7*y^3*s^4+41535*z^7*x^6*y^3*s^4+13845*z^8*x^5*y^3*s^4+24116*z^4*x^10*y^11*s^3+24116*z^6*x^11*y^10*s^3+29297*z^4*x^11*y^10*s^3+29297*z^5*x^10*y^10*s^3+29297*z^6*x^12*y^9*s^3+29297*z^4*x^12*y^9*s^3+29297*z^7*x^11*y^9*s^3+15543*z^5*x^11*y^9*s^3+29297*z^6*x^10*y^9*s^3+29297*z^6*x^13*y^8*s^3+24116*z^4*x^13*y^8*s^3+15543*z^7*x^12*y^8*s^3+29297*z^5*x^12*y^8*s^3+29297*z^8*x^11*y^8*s^3+29297*z^6*x^11*y^8*s^3+24116*z^7*x^10*y^8*s^3+24116*z^6*x^14*y^7*s^3+29297*z^7*x^13*y^7*s^3+29297*z^8*x^12*y^7*s^3+24116*z^9*x^11*y^7*s^3+13845*z^3*x^6*y^6*s^3+41535*z^3*x^7*y^5*s^3+41535*z^4*x^6*y^5*s^3+13845*z^5*x^5*y^5*s^3+13845*z^3*x^4*y^5*s^3+41535*z^3*x^8*y^4*s^3+40019*z^4*x^7*y^4*s^3+40019*z^5*x^6*y^4*s^3+41535*z^6*x^5*y^4*s^3+41535*z^3*x^5*y^4*s^3+41535*z^4*x^4*y^4*s^3+13845*z^3*x^9*y^3*s^3+41535*z^4*x^8*y^3*s^3+40019*z^5*x^7*y^3*s^3+10813*z^6*x^6*y^3*s^3+41535*z^3*x^6*y^3*s^3+41535*z^7*x^5*y^3*s^3+40019*z^4*x^5*y^3*s^3+41535*z^5*x^4*y^3*s^3+13845*z^5*x^8*y^2*s^3+41535*z^6*x^7*y^2*s^3+13845*z^3*x^7*y^2*s^3+41535*z^7*x^6*y^2*s^3+41535*z^4*x^6*y^2*s^3+13845*z^8*x^5*y^2*s^3+41535*z^5*x^5*y^2*s^3+13845*z^6*x^4*y^2*s^3+24116*z^4*x^12*y^10*s^2+29297*z^4*x^13*y^9*s^2+29297*z^5*x^12*y^9*s^2+24116*z^6*x^11*y^9*s^2+24116*z^4*x^10*y^9*s^2+29297*z^4*x^14*y^8*s^2+15543*z^5*x^13*y^8*s^2+15543*z^6*x^12*y^8*s^2+29297*z^7*x^11*y^8*s^2+29297*z^4*x^11*y^8*s^2+29297*z^5*x^10*y^8*s^2+24116*z^4*x^15*y^7*s^2+29297*z^5*x^14*y^7*s^2+15543*z^6*x^13*y^7*s^2+39659*z^7*x^12*y^7*s^2+29297*z^4*x^12*y^7*s^2+29297*z^8*x^11*y^7*s^2+15543*z^5*x^11*y^7*s^2+29297*z^6*x^10*y^7*s^2+24116*z^6*x^14*y^6*s^2+29297*z^7*x^13*y^6*s^2+24116*z^4*x^13*y^6*s^2+29297*z^8*x^12*y^6*s^2+29297*z^5*x^12*y^6*s^2+24116*z^9*x^11*y^6*s^2+29297*z^6*x^11*y^6*s^2+24116*z^7*x^10*y^6*s^2)*(22750*x^4*y^4*s^3+41200*z^2*x*y^3*s^3+4017*x*y^3*s^3+26755*z*x^4*y*s^3+42152*s+27324*x^4*y^3+40575*x^2*y^3+14244*z^3*x^2*y^2+14342*z*x^2*y)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#15: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(22750*x^2*y^4*s^4+14244*z^3*y^4*s^4+27324*z^2*x^3*y^4*s^3+4017*y^4*s^2+14342*z^3*x*s^2+40575*x^3*y^4*s+26755*z^2*x*y^4*s+41200*z^3*y*s+42152*z^2*x^4*y^3)*(29049*z^6*x*y^11*s^11+1045*z^6*x^2*y^10*s^11+1045*z^7*x*y^10*s^11+1045*z^6*x^3*y^9*s^11+21629*z^4*x^3*y^9*s^11+2090*z^7*x^2*y^9*s^11+1045*z^8*x*y^9*s^11+29049*z^6*x^4*y^8*s^11+21836*z^4*x^4*y^8*s^11+1045*z^7*x^3*y^8*s^11+21836*z^5*x^3*y^8*s^11+1045*z^8*x^2*y^8*s^11+29049*z^9*x*y^8*s^11+21836*z^4*x^5*y^7*s^11+621*z^5*x^4*y^7*s^11+21836*z^6*x^3*y^7*s^11+21629*z^4*x^6*y^6*s^11+21836*z^5*x^5*y^6*s^11+21836*z^6*x^4*y^6*s^11+21629*z^7*x^3*y^6*s^11+29049*z^5*x*y^13*s^10+29049*z^7*x^2*y^12*s^10+1045*z^5*x^2*y^12*s^10+1045*z^6*x*y^12*s^10+1045*z^7*x^3*y^11*s^10+1045*z^5*x^3*y^11*s^10+21629*z^3*x^3*y^11*s^10+1045*z^8*x^2*y^11*s^10+2090*z^6*x^2*y^11*s^10+1045*z^7*x*y^11*s^10+1045*z^7*x^4*y^10*s^10+7627*z^5*x^4*y^10*s^10+21836*z^3*x^4*y^10*s^10+2090*z^8*x^3*y^10*s^10+1045*z^6*x^3*y^10*s^10+21836*z^4*x^3*y^10*s^10+1045*z^9*x^2*y^10*s^10+1045*z^7*x^2*y^10*s^10+29049*z^8*x*y^10*s^10+29049*z^7*x^5*y^9*s^10+21836*z^5*x^5*y^9*s^10+21836*z^3*x^5*y^9*s^10+1045*z^8*x^4*y^9*s^10+21836*z^6*x^4*y^9*s^10+621*z^4*x^4*y^9*s^10+1045*z^9*x^3*y^9*s^10+21836*z^5*x^3*y^9*s^10+29049*z^10*x^2*y^9*s^10+21836*z^5*x^6*y^8*s^10+21629*z^3*x^6*y^8*s^10+621*z^6*x^5*y^8*s^10+21836*z^4*x^5*y^8*s^10+21836*z^7*x^4*y^8*s^10+21836*z^5*x^4*y^8*s^10+21629*z^6*x^3*y^8*s^10+21629*z^5*x^7*y^7*s^10+21836*z^6*x^6*y^7*s^10+21836*z^7*x^5*y^7*s^10+21629*z^8*x^4*y^7*s^10+16873*z^8*x^8*y^6*s^10+7568*z^8*x^9*y^5*s^10+7568*z^9*x^8*y^5*s^10+7568*z^8*x^10*y^4*s^10+15136*z^9*x^9*y^4*s^10+7568*z^10*x^8*y^4*s^10+16873*z^8*x^11*y^3*s^10+7568*z^9*x^10*y^3*s^10+7568*z^10*x^9*y^3*s^10+16873*z^11*x^8*y^3*s^10+29049*z^5*x^3*y^12*s^9+1045*z^5*x^4*y^11*s^9+1045*z^6*x^3*y^11*s^9+29049*z^7*x^2*y^11*s^9+29049*z^5*x*y^11*s^9+1045*z^5*x^5*y^10*s^9+21629*z^3*x^5*y^10*s^9+2090*z^6*x^4*y^10*s^9+2090*z^7*x^3*y^10*s^9+1045*z^8*x^2*y^10*s^9+1045*z^5*x^2*y^10*s^9+1045*z^6*x*y^10*s^9+29049*z^5*x^6*y^9*s^9+21836*z^3*x^6*y^9*s^9+1045*z^6*x^5*y^9*s^9+21836*z^4*x^5*y^9*s^9+2090*z^7*x^4*y^9*s^9+21629*z^5*x^4*y^9*s^9+31139*z^8*x^3*y^9*s^9+1045*z^5*x^3*y^9*s^9+21629*z^3*x^3*y^9*s^9+1045*z^9*x^2*y^9*s^9+2090*z^6*x^2*y^9*s^9+1045*z^7*x*y^9*s^9+16873*z^7*x^8*y^8*s^9+21836*z^3*x^7*y^8*s^9+621*z^4*x^6*y^8*s^9+29049*z^7*x^5*y^8*s^9+621*z^5*x^5*y^8*s^9+1045*z^8*x^4*y^8*s^9+21836*z^6*x^4*y^8*s^9+29049*z^5*x^4*y^8*s^9+21836*z^3*x^4*y^8*s^9+1045*z^9*x^3*y^8*s^9+1045*z^6*x^3*y^8*s^9+21836*z^4*x^3*y^8*s^9+29049*z^10*x^2*y^8*s^9+1045*z^7*x^2*y^8*s^9+29049*z^8*x*y^8*s^9+16873*z^9*x^9*y^7*s^9+7568*z^7*x^9*y^7*s^9+7568*z^8*x^8*y^7*s^9+21629*z^3*x^8*y^7*s^9+21836*z^4*x^7*y^7*s^9+621*z^5*x^6*y^7*s^9+22250*z^6*x^5*y^7*s^9+21836*z^3*x^5*y^7*s^9+21836*z^7*x^4*y^7*s^9+621*z^4*x^4*y^7*s^9+21836*z^5*x^3*y^7*s^9+7568*z^9*x^10*y^6*s^9+7568*z^7*x^10*y^6*s^9+7568*z^10*x^9*y^6*s^9+15136*z^8*x^9*y^6*s^9+7568*z^9*x^8*y^6*s^9+21629*z^5*x^7*y^6*s^9+21836*z^6*x^6*y^6*s^9+21629*z^3*x^6*y^6*s^9+21836*z^7*x^5*y^6*s^9+21836*z^4*x^5*y^6*s^9+21629*z^8*x^4*y^6*s^9+21836*z^5*x^4*y^6*s^9+21629*z^6*x^3*y^6*s^9+7568*z^9*x^11*y^5*s^9+16873*z^7*x^11*y^5*s^9+15136*z^10*x^10*y^5*s^9+7568*z^8*x^10*y^5*s^9+7568*z^11*x^9*y^5*s^9+7568*z^9*x^9*y^5*s^9+16873*z^10*x^8*y^5*s^9+16873*z^9*x^12*y^4*s^9+7568*z^10*x^11*y^4*s^9+7568*z^11*x^10*y^4*s^9+16873*z^12*x^9*y^4*s^9+41743*z^5*x^2*y^10*s^8+39127*z^5*x^3*y^9*s^8+39127*z^6*x^2*y^9*s^8+39127*z^5*x^4*y^8*s^8+35203*z^6*x^3*y^8*s^8+39127*z^7*x^2*y^8*s^8+16873*z^7*x^10*y^7*s^8+8506*z^5*x^10*y^7*s^8+41743*z^5*x^5*y^7*s^8+39127*z^6*x^4*y^7*s^8+39127*z^7*x^3*y^7*s^8+41743*z^8*x^2*y^7*s^8+7568*z^7*x^11*y^6*s^8+25518*z^5*x^11*y^6*s^8+7568*z^8*x^10*y^6*s^8+25518*z^6*x^10*y^6*s^8+16873*z^9*x^9*y^6*s^8+16873*z^7*x^8*y^6*s^8+7568*z^7*x^12*y^5*s^8+25518*z^5*x^12*y^5*s^8+15136*z^8*x^11*y^5*s^8+7985*z^6*x^11*y^5*s^8+15136*z^9*x^10*y^5*s^8+25518*z^7*x^10*y^5*s^8+7568*z^10*x^9*y^5*s^8+7568*z^7*x^9*y^5*s^8+7568*z^8*x^8*y^5*s^8+16873*z^7*x^13*y^4*s^8+8506*z^5*x^13*y^4*s^8+7568*z^8*x^12*y^4*s^8+25518*z^6*x^12*y^4*s^8+15136*z^9*x^11*y^4*s^8+25518*z^7*x^11*y^4*s^8+32009*z^10*x^10*y^4*s^8+8506*z^8*x^10*y^4*s^8+7568*z^7*x^10*y^4*s^8+7568*z^11*x^9*y^4*s^8+15136*z^8*x^9*y^4*s^8+7568*z^9*x^8*y^4*s^8+16873*z^9*x^12*y^3*s^8+7568*z^10*x^11*y^3*s^8+16873*z^7*x^11*y^3*s^8+7568*z^11*x^10*y^3*s^8+7568*z^8*x^10*y^3*s^8+16873*z^12*x^9*y^3*s^8+7568*z^9*x^9*y^3*s^8+16873*z^10*x^8*y^3*s^8+41743*z^4*x^2*y^12*s^7+41743*z^6*x^3*y^11*s^7+39127*z^4*x^3*y^11*s^7+39127*z^5*x^2*y^11*s^7+39127*z^6*x^4*y^10*s^7+39127*z^4*x^4*y^10*s^7+39127*z^7*x^3*y^10*s^7+35203*z^5*x^3*y^10*s^7+39127*z^6*x^2*y^10*s^7+8506*z^4*x^10*y^9*s^7+39127*z^6*x^5*y^9*s^7+41743*z^4*x^5*y^9*s^7+35203*z^7*x^4*y^9*s^7+39127*z^5*x^4*y^9*s^7+39127*z^8*x^3*y^9*s^7+39127*z^6*x^3*y^9*s^7+13845*z^3*x^3*y^9*s^7+41743*z^7*x^2*y^9*s^7+8506*z^6*x^11*y^8*s^7+25518*z^4*x^11*y^8*s^7+25518*z^5*x^10*y^8*s^7+41743*z^6*x^6*y^8*s^7+39127*z^7*x^5*y^8*s^7+39127*z^8*x^4*y^8*s^7+41535*z^3*x^4*y^8*s^7+41743*z^9*x^3*y^8*s^7+41535*z^4*x^3*y^8*s^7+25518*z^6*x^12*y^7*s^7+25518*z^4*x^12*y^7*s^7+25518*z^7*x^11*y^7*s^7+7985*z^5*x^11*y^7*s^7+25518*z^6*x^10*y^7*s^7+41535*z^3*x^5*y^7*s^7+40019*z^4*x^4*y^7*s^7+41535*z^5*x^3*y^7*s^7+25518*z^6*x^13*y^6*s^7+8506*z^4*x^13*y^6*s^7+7985*z^7*x^12*y^6*s^7+25518*z^5*x^12*y^6*s^7+25518*z^8*x^11*y^6*s^7+25518*z^6*x^11*y^6*s^7+8506*z^7*x^10*y^6*s^7+13845*z^3*x^6*y^6*s^7+41535*z^4*x^5*y^6*s^7+41535*z^5*x^4*y^6*s^7+13845*z^6*x^3*y^6*s^7+8506*z^6*x^14*y^5*s^7+25518*z^7*x^13*y^5*s^7+25518*z^8*x^12*y^5*s^7+8506*z^9*x^11*y^5*s^7+24116*z^10*x^10*y^13*s^6+29297*z^10*x^11*y^12*s^6+29297*z^11*x^10*y^12*s^6+39739*z^3*x^2*y^12*s^6+29297*z^10*x^12*y^11*s^6+15543*z^11*x^11*y^11*s^6+29297*z^12*x^10*y^11*s^6+41743*z^4*x^4*y^11*s^6+33115*z^3*x^3*y^11*s^6+13845*z^2*x^3*y^11*s^6+33115*z^4*x^2*y^11*s^6+24116*z^10*x^13*y^10*s^6+29297*z^11*x^12*y^10*s^6+29297*z^12*x^11*y^10*s^6+24116*z^13*x^10*y^10*s^6+39127*z^4*x^5*y^10*s^6+39127*z^5*x^4*y^10*s^6+13845*z^4*x^4*y^10*s^6+33115*z^3*x^4*y^10*s^6+41535*z^2*x^4*y^10*s^6+41743*z^6*x^3*y^10*s^6+23179*z^4*x^3*y^10*s^6+41535*z^3*x^3*y^10*s^6+33115*z^5*x^2*y^10*s^6+41743*z^4*x^2*y^10*s^6+39127*z^4*x^6*y^9*s^6+35203*z^5*x^5*y^9*s^6+41535*z^4*x^5*y^9*s^6+39739*z^3*x^5*y^9*s^6+41535*z^2*x^5*y^9*s^6+35203*z^6*x^4*y^9*s^6+41535*z^5*x^4*y^9*s^6+33115*z^4*x^4*y^9*s^6+40019*z^3*x^4*y^9*s^6+39127*z^7*x^3*y^9*s^6+33115*z^5*x^3*y^9*s^6+37611*z^4*x^3*y^9*s^6+39739*z^6*x^2*y^9*s^6+39127*z^5*x^2*y^9*s^6+8506*z^4*x^12*y^8*s^6+41743*z^4*x^7*y^8*s^6+39127*z^5*x^6*y^8*s^6+41535*z^4*x^6*y^8*s^6+13845*z^2*x^6*y^8*s^6+35203*z^6*x^5*y^8*s^6+40019*z^5*x^5*y^8*s^6+41535*z^3*x^5*y^8*s^6+33895*z^7*x^4*y^8*s^6+41535*z^6*x^4*y^8*s^6+37611*z^4*x^4*y^8*s^6+39127*z^8*x^3*y^8*s^6+5997*z^5*x^3*y^8*s^6+39127*z^6*x^2*y^8*s^6+25518*z^4*x^13*y^7*s^6+25518*z^5*x^12*y^7*s^6+8506*z^6*x^11*y^7*s^6+8506*z^4*x^10*y^7*s^6+13845*z^4*x^7*y^7*s^6+41743*z^6*x^6*y^7*s^6+41535*z^5*x^6*y^7*s^6+39127*z^7*x^5*y^7*s^6+41535*z^6*x^5*y^7*s^6+41743*z^4*x^5*y^7*s^6+39127*z^8*x^4*y^7*s^6+13845*z^7*x^4*y^7*s^6+39127*z^5*x^4*y^7*s^6+41743*z^9*x^3*y^7*s^6+39127*z^6*x^3*y^7*s^6+41743*z^7*x^2*y^7*s^6+25518*z^4*x^14*y^6*s^6+7985*z^5*x^13*y^6*s^6+7985*z^6*x^12*y^6*s^6+25518*z^7*x^11*y^6*s^6+25518*z^4*x^11*y^6*s^6+25518*z^5*x^10*y^6*s^6+8506*z^4*x^15*y^5*s^6+25518*z^5*x^14*y^5*s^6+7985*z^6*x^13*y^5*s^6+16491*z^7*x^12*y^5*s^6+25518*z^4*x^12*y^5*s^6+25518*z^8*x^11*y^5*s^6+7985*z^5*x^11*y^5*s^6+25518*z^6*x^10*y^5*s^6+8506*z^6*x^14*y^4*s^6+25518*z^7*x^13*y^4*s^6+8506*z^4*x^13*y^4*s^6+25518*z^8*x^12*y^4*s^6+25518*z^5*x^12*y^4*s^6+8506*z^9*x^11*y^4*s^6+25518*z^6*x^11*y^4*s^6+8506*z^7*x^10*y^4*s^6+24116*z^9*x^10*y^15*s^5+24116*z^11*x^11*y^14*s^5+29297*z^9*x^11*y^14*s^5+29297*z^10*x^10*y^14*s^5+39739*z^2*x^2*y^14*s^5+29297*z^11*x^12*y^13*s^5+29297*z^9*x^12*y^13*s^5+29297*z^12*x^11*y^13*s^5+15543*z^10*x^11*y^13*s^5+29297*z^11*x^10*y^13*s^5+39739*z^4*x^3*y^13*s^5+33115*z^2*x^3*y^13*s^5+33115*z^3*x^2*y^13*s^5+29297*z^11*x^13*y^12*s^5+24116*z^9*x^13*y^12*s^5+15543*z^12*x^12*y^12*s^5+29297*z^10*x^12*y^12*s^5+29297*z^13*x^11*y^12*s^5+29297*z^11*x^11*y^12*s^5+24116*z^12*x^10*y^12*s^5+33115*z^4*x^4*y^12*s^5+33115*z^2*x^4*y^12*s^5+33115*z^5*x^3*y^12*s^5+23179*z^3*x^3*y^12*s^5+33115*z^4*x^2*y^12*s^5+24116*z^11*x^14*y^11*s^5+29297*z^12*x^13*y^11*s^5+29297*z^13*x^12*y^11*s^5+24116*z^14*x^11*y^11*s^5+33115*z^4*x^5*y^11*s^5+39739*z^2*x^5*y^11*s^5+23179*z^5*x^4*y^11*s^5+33115*z^3*x^4*y^11*s^5+33115*z^6*x^3*y^11*s^5+33115*z^4*x^3*y^11*s^5+39739*z^5*x^2*y^11*s^5+39739*z^4*x^6*y^10*s^5+33115*z^5*x^5*y^10*s^5+13845*z^2*x^5*y^10*s^5+33115*z^6*x^4*y^10*s^5+39739*z^7*x^3*y^10*s^5+41535*z^2*x^6*y^9*s^5+41535*z^3*x^5*y^9*s^5+13845*z^4*x^4*y^9*s^5+13845*z^2*x^3*y^9*s^5+41535*z^2*x^7*y^8*s^5+40019*z^3*x^6*y^8*s^5+40019*z^4*x^5*y^8*s^5+41535*z^5*x^4*y^8*s^5+41535*z^2*x^4*y^8*s^5+41535*z^3*x^3*y^8*s^5+13845*z^2*x^8*y^7*s^5+41535*z^3*x^7*y^7*s^5+40019*z^4*x^6*y^7*s^5+10813*z^5*x^5*y^7*s^5+41535*z^2*x^5*y^7*s^5+41535*z^6*x^4*y^7*s^5+40019*z^3*x^4*y^7*s^5+41535*z^4*x^3*y^7*s^5+13845*z^4*x^7*y^6*s^5+41535*z^5*x^6*y^6*s^5+13845*z^2*x^6*y^6*s^5+41535*z^6*x^5*y^6*s^5+41535*z^3*x^5*y^6*s^5+13845*z^7*x^4*y^6*s^5+41535*z^4*x^4*y^6*s^5+13845*z^5*x^3*y^6*s^5+24116*z^9*x^12*y^14*s^4+29297*z^9*x^13*y^13*s^4+29297*z^10*x^12*y^13*s^4+24116*z^11*x^11*y^13*s^4+24116*z^9*x^10*y^13*s^4+39739*z^2*x^4*y^13*s^4+29297*z^9*x^14*y^12*s^4+15543*z^10*x^13*y^12*s^4+15543*z^11*x^12*y^12*s^4+29297*z^12*x^11*y^12*s^4+29297*z^9*x^11*y^12*s^4+29297*z^10*x^10*y^12*s^4+33115*z^2*x^5*y^12*s^4+33115*z^3*x^4*y^12*s^4+39739*z^4*x^3*y^12*s^4+39739*z^2*x^2*y^12*s^4+24116*z^9*x^15*y^11*s^4+29297*z^10*x^14*y^11*s^4+15543*z^11*x^13*y^11*s^4+39659*z^12*x^12*y^11*s^4+29297*z^9*x^12*y^11*s^4+29297*z^13*x^11*y^11*s^4+15543*z^10*x^11*y^11*s^4+29297*z^11*x^10*y^11*s^4+33115*z^2*x^6*y^11*s^4+23179*z^3*x^5*y^11*s^4+23179*z^4*x^4*y^11*s^4+33115*z^5*x^3*y^11*s^4+33115*z^2*x^3*y^11*s^4+33115*z^3*x^2*y^11*s^4+24116*z^11*x^14*y^10*s^4+29297*z^12*x^13*y^10*s^4+24116*z^9*x^13*y^10*s^4+29297*z^13*x^12*y^10*s^4+29297*z^10*x^12*y^10*s^4+24116*z^14*x^11*y^10*s^4+29297*z^11*x^11*y^10*s^4+24116*z^12*x^10*y^10*s^4+39739*z^2*x^7*y^10*s^4+33115*z^3*x^6*y^10*s^4+23179*z^4*x^5*y^10*s^4+19867*z^5*x^4*y^10*s^4+33115*z^2*x^4*y^10*s^4+33115*z^6*x^3*y^10*s^4+23179*z^3*x^3*y^10*s^4+33115*z^4*x^2*y^10*s^4+39739*z^4*x^6*y^9*s^4+33115*z^5*x^5*y^9*s^4+39739*z^2*x^5*y^9*s^4+33115*z^6*x^4*y^9*s^4+33115*z^3*x^4*y^9*s^4+39739*z^7*x^3*y^9*s^4+33115*z^4*x^3*y^9*s^4+39739*z^5*x^2*y^9*s^4+19583*z^6*x^2*y^13*s^3+15698*z^6*x^3*y^12*s^3+15698*z^7*x^2*y^12*s^3+15698*z^6*x^4*y^11*s^3+31396*z^7*x^3*y^11*s^3+15698*z^8*x^2*y^11*s^3+19583*z^6*x^5*y^10*s^3+15698*z^7*x^4*y^10*s^3+15698*z^8*x^3*y^10*s^3+19583*z^9*x^2*y^10*s^3+19583*z^5*x^2*y^15*s^2+19583*z^7*x^3*y^14*s^2+15698*z^5*x^3*y^14*s^2+15698*z^6*x^2*y^14*s^2+15698*z^7*x^4*y^13*s^2+15698*z^5*x^4*y^13*s^2+15698*z^8*x^3*y^13*s^2+31396*z^6*x^3*y^13*s^2+15698*z^7*x^2*y^13*s^2+15698*z^7*x^5*y^12*s^2+19583*z^5*x^5*y^12*s^2+31396*z^8*x^4*y^12*s^2+15698*z^6*x^4*y^12*s^2+15698*z^9*x^3*y^12*s^2+15698*z^7*x^3*y^12*s^2+19583*z^8*x^2*y^12*s^2+19583*z^7*x^6*y^11*s^2+15698*z^8*x^5*y^11*s^2+15698*z^9*x^4*y^11*s^2+19583*z^10*x^3*y^11*s^2+19583*z^5*x^4*y^14*s+15698*z^5*x^5*y^13*s+15698*z^6*x^4*y^13*s+19583*z^7*x^3*y^13*s+19583*z^5*x^2*y^13*s+15698*z^5*x^6*y^12*s+31396*z^6*x^5*y^12*s+31396*z^7*x^4*y^12*s+15698*z^8*x^3*y^12*s+15698*z^5*x^3*y^12*s+15698*z^6*x^2*y^12*s+19583*z^5*x^7*y^11*s+15698*z^6*x^6*y^11*s+31396*z^7*x^5*y^11*s+7928*z^8*x^4*y^11*s+15698*z^5*x^4*y^11*s+15698*z^9*x^3*y^11*s+31396*z^6*x^3*y^11*s+15698*z^7*x^2*y^11*s+19583*z^7*x^6*y^10*s+15698*z^8*x^5*y^10*s+19583*z^5*x^5*y^10*s+15698*z^9*x^4*y^10*s+15698*z^6*x^4*y^10*s+19583*z^10*x^3*y^10*s+15698*z^7*x^3*y^10*s+19583*z^8*x^2*y^10*s)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#16: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(8506*z^12*x^11*y^10*t^12+25518*z^12*x^12*y^9*t^12+25518*z^13*x^11*y^9*t^12+25518*z^12*x^13*y^8*t^12+7985*z^13*x^12*y^8*t^12+25518*z^14*x^11*y^8*t^12+8506*z^12*x^14*y^7*t^12+25518*z^13*x^13*y^7*t^12+25518*z^14*x^12*y^7*t^12+8506*z^15*x^11*y^7*t^12+6157*z^4*x^6*y^10*s^9*t^10+18471*z^4*x^7*y^9*s^9*t^10+18471*z^5*x^6*y^9*s^9*t^10+18471*z^4*x^8*y^8*s^9*t^10+36942*z^5*x^7*y^8*s^9*t^10+18471*z^6*x^6*y^8*s^9*t^10+6157*z^4*x^9*y^7*s^9*t^10+18471*z^5*x^8*y^7*s^9*t^10+18471*z^6*x^7*y^7*s^9*t^10+6157*z^7*x^6*y^7*s^9*t^10+16680*z^12*x^4*y^16*s^6*t^10+6989*z^12*x^5*y^15*s^6*t^10+6989*z^13*x^4*y^15*s^6*t^10+6989*z^12*x^6*y^14*s^6*t^10+13978*z^13*x^5*y^14*s^6*t^10+6989*z^14*x^4*y^14*s^6*t^10+16680*z^12*x^7*y^13*s^6*t^10+6989*z^13*x^6*y^13*s^6*t^10+6989*z^14*x^5*y^13*s^6*t^10+16680*z^15*x^4*y^13*s^6*t^10+41743*z*x^6*y^10*s^6*t^10+39127*z*x^7*y^9*s^6*t^10+39127*z^2*x^6*y^9*s^6*t^10+39127*z*x^8*y^8*s^6*t^10+35203*z^2*x^7*y^8*s^6*t^10+39127*z^3*x^6*y^8*s^6*t^10+41743*z*x^9*y^7*s^6*t^10+39127*z^2*x^8*y^7*s^6*t^10+39127*z^3*x^7*y^7*s^6*t^10+41743*z^4*x^6*y^7*s^6*t^10+16873*z^11*x^3*y^5*s^10*t^6+7568*z^11*x^4*y^4*s^10*t^6+7568*z^12*x^3*y^4*s^10*t^6+7568*z^11*x^5*y^3*s^10*t^6+15136*z^12*x^4*y^3*s^10*t^6+7568*z^13*x^3*y^3*s^10*t^6+16873*z^11*x^6*y^2*s^10*t^6+7568*z^12*x^5*y^2*s^10*t^6+7568*z^13*x^4*y^2*s^10*t^6+16873*z^14*x^3*y^2*s^10*t^6+21629*z^10*x^7*y^8*t^5+21836*z^10*x^8*y^7*t^5+21836*z^11*x^7*y^7*t^5+21836*z^10*x^9*y^6*t^5+621*z^11*x^8*y^6*t^5+21836*z^12*x^7*y^6*t^5+21629*z^10*x^10*y^5*t^5+21836*z^11*x^9*y^5*t^5+21836*z^12*x^8*y^5*t^5+21629*z^13*x^7*y^5*t^5+13845*z^10*x*y^13*s^4*t^4+41535*z^10*x^2*y^12*s^4*t^4+41535*z^11*x*y^12*s^4*t^4+41535*z^10*x^3*y^11*s^4*t^4+40019*z^11*x^2*y^11*s^4*t^4+41535*z^12*x*y^11*s^4*t^4+13845*z^10*x^4*y^10*s^4*t^4+41535*z^11*x^3*y^10*s^4*t^4+41535*z^12*x^2*y^10*s^4*t^4+13845*z^13*x*y^10*s^4*t^4+19583*z^8*x*y^12*s^11*t^3+15698*z^8*x^2*y^11*s^11*t^3+15698*z^9*x*y^11*s^11*t^3+15698*z^8*x^3*y^10*s^11*t^3+31396*z^9*x^2*y^10*s^11*t^3+15698*z^10*x*y^10*s^11*t^3+19583*z^8*x^4*y^9*s^11*t^3+15698*z^9*x^3*y^9*s^11*t^3+15698*z^10*x^2*y^9*s^11*t^3+19583*z^11*x*y^9*s^11*t^3+37652*z*x^12*y^16*s^7*t+26854*z*x^13*y^15*s^7*t+26854*z^2*x^12*y^15*s^7*t+26854*z*x^14*y^14*s^7*t+10657*z^2*x^13*y^14*s^7*t+26854*z^3*x^12*y^14*s^7*t+37652*z*x^15*y^13*s^7*t+26854*z^2*x^14*y^13*s^7*t+26854*z^3*x^13*y^13*s^7*t+37652*z^4*x^12*y^13*s^7*t+24116*z^3*x*y^4*s^9+29297*z^3*x^2*y^3*s^9+29297*z^4*x*y^3*s^9+29297*z^3*x^3*y^2*s^9+15543*z^4*x^2*y^2*s^9+29297*z^5*x*y^2*s^9+24116*z^3*x^4*y*s^9+29297*z^4*x^3*y*s^9+29297*z^5*x^2*y*s^9+24116*z^6*x*y*s^9+29049*z^4*x^12*y^10*s^6+1045*z^4*x^13*y^9*s^6+1045*z^5*x^12*y^9*s^6+1045*z^4*x^14*y^8*s^6+2090*z^5*x^13*y^8*s^6+1045*z^6*x^12*y^8*s^6+29049*z^4*x^15*y^7*s^6+1045*z^5*x^14*y^7*s^6+1045*z^6*x^13*y^7*s^6+29049*z^7*x^12*y^7*s^6+39739*z^3*x^7*y^9*s+33115*z^3*x^8*y^8*s+33115*z^4*x^7*y^8*s+33115*z^3*x^9*y^7*s+23179*z^4*x^8*y^7*s+33115*z^5*x^7*y^7*s+39739*z^3*x^10*y^6*s+33115*z^4*x^9*y^6*s+33115*z^5*x^8*y^6*s+39739*z^6*x^7*y^6*s)*(4017*x^3*y^2*s^6*u^5+42152*z*x^2*y*s^6*u^5+26755*z^5*x^5*y*s^5*u^5+41200*z^5*x^4*y^5*s^2*u^5+14342*z*x^3*s^2*u^5+14244*z^4*x*y^3*u^5+12889*z^4*x^4*y^6*u^3+27324*x*y^6*s^6*u^2+40575*z^3*x^2*y^5*s^2*u+33099*x*s*u+22750*z^5*x^4*y^2*s+38991*z^2*x^3)*(31261*z*x*y^3+26706*z^2*x*y^2+2238*z*x*y^2+6828*z*y^2+20135*z^2*x^2*y+41530*z*x^2*y+7431*z^2*x*y+27*z^2*y+14865*x^2+12602*z^3*x+10797*z*x)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#17: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(19583*z^5*x^14*y^22*s^5*t^17+15698*z^5*x^15*y^21*s^5*t^17+15698*z^6*x^14*y^21*s^5*t^17+15698*z^5*x^16*y^20*s^5*t^17+31396*z^6*x^15*y^20*s^5*t^17+15698*z^7*x^14*y^20*s^5*t^17+19583*z^5*x^17*y^19*s^5*t^17+15698*z^6*x^16*y^19*s^5*t^17+15698*z^7*x^15*y^19*s^5*t^17+19583*z^8*x^14*y^19*s^5*t^17+13845*x^9*y^10*s^2*t^17+41535*x^10*y^9*s^2*t^17+41535*z*x^9*y^9*s^2*t^17+41535*x^11*y^8*s^2*t^17+40019*z*x^10*y^8*s^2*t^17+41535*z^2*x^9*y^8*s^2*t^17+13845*x^12*y^7*s^2*t^17+41535*z*x^11*y^7*s^2*t^17+41535*z^2*x^10*y^7*s^2*t^17+13845*z^3*x^9*y^7*s^2*t^17+16873*z*x^17*y^5*s^16*t^16+7568*z*x^18*y^4*s^16*t^16+7568*z^2*x^17*y^4*s^16*t^16+7568*z*x^19*y^3*s^16*t^16+15136*z^2*x^18*y^3*s^16*t^16+7568*z^3*x^17*y^3*s^16*t^16+16873*z*x^20*y^2*s^16*t^16+7568*z^2*x^19*y^2*s^16*t^16+7568*z^3*x^18*y^2*s^16*t^16+16873*z^4*x^17*y^2*s^16*t^16+16680*x^14*y^6*s^9*t^16+6989*x^15*y^5*s^9*t^16+6989*z*x^14*y^5*s^9*t^16+6989*x^16*y^4*s^9*t^16+13978*z*x^15*y^4*s^9*t^16+6989*z^2*x^14*y^4*s^9*t^16+16680*x^17*y^3*s^9*t^16+6989*z*x^16*y^3*s^9*t^16+6989*z^2*x^15*y^3*s^9*t^16+16680*z^3*x^14*y^3*s^9*t^16+15656*z^9*x^12*y^9*s^12*t^15+3917*z^9*x^13*y^8*s^12*t^15+3917*z^10*x^12*y^8*s^12*t^15+3917*z^9*x^14*y^7*s^12*t^15+7834*z^10*x^13*y^7*s^12*t^15+3917*z^11*x^12*y^7*s^12*t^15+15656*z^9*x^15*y^6*s^12*t^15+3917*z^10*x^14*y^6*s^12*t^15+3917*z^11*x^13*y^6*s^12*t^15+15656*z^12*x^12*y^6*s^12*t^15+41743*z*x^17*y^9*s^13*t^13+39127*z*x^18*y^8*s^13*t^13+39127*z^2*x^17*y^8*s^13*t^13+39127*z*x^19*y^7*s^13*t^13+35203*z^2*x^18*y^7*s^13*t^13+39127*z^3*x^17*y^7*s^13*t^13+41743*z*x^20*y^6*s^13*t^13+39127*z^2*x^19*y^6*s^13*t^13+39127*z^3*x^18*y^6*s^13*t^13+41743*z^4*x^17*y^6*s^13*t^13+40031*x^16*y^4*t^10+33991*x^17*y^3*t^10+33991*z*x^16*y^3*t^10+33991*x^18*y^2*t^10+24931*z*x^17*y^2*t^10+33991*z^2*x^16*y^2*t^10+40031*x^19*y*t^10+33991*z*x^18*y*t^10+33991*z^2*x^17*y*t^10+40031*z^3*x^16*y*t^10+24116*z*x^12*y^22*s^16*t^9+29297*z*x^13*y^21*s^16*t^9+29297*z^2*x^12*y^21*s^16*t^9+29297*z*x^14*y^20*s^16*t^9+15543*z^2*x^13*y^20*s^16*t^9+29297*z^3*x^12*y^20*s^16*t^9+24116*z*x^15*y^19*s^16*t^9+29297*z^2*x^14*y^19*s^16*t^9+29297*z^3*x^13*y^19*s^16*t^9+24116*z^4*x^12*y^19*s^16*t^9+37652*z^12*x^7*y^14*s^4*t^9+26854*z^12*x^8*y^13*s^4*t^9+26854*z^13*x^7*y^13*s^4*t^9+26854*z^12*x^9*y^12*s^4*t^9+10657*z^13*x^8*y^12*s^4*t^9+26854*z^14*x^7*y^12*s^4*t^9+37652*z^12*x^10*y^11*s^4*t^9+26854*z^13*x^9*y^11*s^4*t^9+26854*z^14*x^8*y^11*s^4*t^9+37652*z^15*x^7*y^11*s^4*t^9+39739*z^3*x*y^12*s^12*t^7+33115*z^3*x^2*y^11*s^12*t^7+33115*z^4*x*y^11*s^12*t^7+33115*z^3*x^3*y^10*s^12*t^7+23179*z^4*x^2*y^10*s^12*t^7+33115*z^5*x*y^10*s^12*t^7+39739*z^3*x^4*y^9*s^12*t^7+33115*z^4*x^3*y^9*s^12*t^7+33115*z^5*x^2*y^9*s^12*t^7+39739*z^6*x*y^9*s^12*t^7+29049*z^9*x^10*y^16*s^9*t^7+1045*z^9*x^11*y^15*s^9*t^7+1045*z^10*x^10*y^15*s^9*t^7+1045*z^9*x^12*y^14*s^9*t^7+2090*z^10*x^11*y^14*s^9*t^7+1045*z^11*x^10*y^14*s^9*t^7+29049*z^9*x^13*y^13*s^9*t^7+1045*z^10*x^12*y^13*s^9*t^7+1045*z^11*x^11*y^13*s^9*t^7+29049*z^12*x^10*y^13*s^9*t^7+9048*z^17*x*y^22*s^2*t^7+27144*z^17*x^2*y^21*s^2*t^7+27144*z^18*x*y^21*s^2*t^7+27144*z^17*x^3*y^20*s^2*t^7+11237*z^18*x^2*y^20*s^2*t^7+27144*z^19*x*y^20*s^2*t^7+9048*z^17*x^4*y^19*s^2*t^7+27144*z^18*x^3*y^19*s^2*t^7+27144*z^19*x^2*y^19*s^2*t^7+9048*z^20*x*y^19*s^2*t^7+27198*z^18*x^9*y^12*s^8*t^6+38543*z^18*x^10*y^11*s^8*t^6+38543*z^19*x^9*y^11*s^8*t^6+38543*z^18*x^11*y^10*s^8*t^6+34035*z^19*x^10*y^10*s^8*t^6+38543*z^20*x^9*y^10*s^8*t^6+27198*z^18*x^12*y^9*s^8*t^6+38543*z^19*x^11*y^9*s^8*t^6+38543*z^20*x^10*y^9*s^8*t^6+27198*z^21*x^9*y^9*s^8*t^6+40487*z^14*x^19*y^4*s^6*t^6+35359*z^14*x^20*y^3*s^6*t^6+35359*z^15*x^19*y^3*s^6*t^6+35359*z^14*x^21*y^2*s^6*t^6+27667*z^15*x^20*y^2*s^6*t^6+35359*z^16*x^19*y^2*s^6*t^6+40487*z^14*x^22*y*s^6*t^6+35359*z^15*x^21*y*s^6*t^6+35359*z^16*x^20*y*s^6*t^6+40487*z^17*x^19*y*s^6*t^6+6157*z^8*x^14*y^10*s^17*t^4+18471*z^8*x^15*y^9*s^17*t^4+18471*z^9*x^14*y^9*s^17*t^4+18471*z^8*x^16*y^8*s^17*t^4+36942*z^9*x^15*y^8*s^17*t^4+18471*z^10*x^14*y^8*s^17*t^4+6157*z^8*x^17*y^7*s^17*t^4+18471*z^9*x^16*y^7*s^17*t^4+18471*z^10*x^15*y^7*s^17*t^4+6157*z^11*x^14*y^7*s^17*t^4+8506*z^14*x^5*y^14*s^2*t^4+25518*z^14*x^6*y^13*s^2*t^4+25518*z^15*x^5*y^13*s^2*t^4+25518*z^14*x^7*y^12*s^2*t^4+7985*z^15*x^6*y^12*s^2*t^4+25518*z^16*x^5*y^12*s^2*t^4+8506*z^14*x^8*y^11*s^2*t^4+25518*z^15*x^7*y^11*s^2*t^4+25518*z^16*x^6*y^11*s^2*t^4+8506*z^17*x^5*y^11*s^2*t^4+12608*z^5*x^11*y^5*s^2*t^4+37824*z^5*x^12*y^4*s^2*t^4+37824*z^6*x^11*y^4*s^2*t^4+37824*z^5*x^13*y^3*s^2*t^4+32597*z^6*x^12*y^3*s^2*t^4+37824*z^7*x^11*y^3*s^2*t^4+12608*z^5*x^14*y^2*s^2*t^4+37824*z^6*x^13*y^2*s^2*t^4+37824*z^7*x^12*y^2*s^2*t^4+12608*z^8*x^11*y^2*s^2*t^4+21629*z^17*x^4*y^18*s^13*t^3+21836*z^17*x^5*y^17*s^13*t^3+21836*z^18*x^4*y^17*s^13*t^3+21836*z^17*x^6*y^16*s^13*t^3+621*z^18*x^5*y^16*s^13*t^3+21836*z^19*x^4*y^16*s^13*t^3+21629*z^17*x^7*y^15*s^13*t^3+21836*z^18*x^6*y^15*s^13*t^3+21836*z^19*x^5*y^15*s^13*t^3+21629*z^20*x^4*y^15*s^13*t^3)*(14244*z^3*x^6*s^7*u^8+33099*z^6*x^6*s^2*u^8+40832*z^3*x*y^6*s^2*u^7+27324*z*x^8*y^7*s*u^7+12889*z^2*x^2*y^3*s*u^7+26775*z^7*x^3*y^7*s^8*u^6+14342*z^5*x^2*y^5*s^7*u^6+24361*z^3*y^4*s^2*u^4+38991*z^6*x^3*y^4*s^8*u^3+41200*z^3*x^3*y^2*s^4*u^3+9788*z^4*x^4*y^7*s*u^3+26755*z^6*x^5*y^7*u^3+4017*z*x^9*y^5*u^3+31443*z^7*x^6*y*u^3+4620*x^4*y^4*s^8*u^2+42152*z^4*x^6*y^6*s^7*u^2+40575*z^6*x^6*y^6*s^3*u^2+22750*z^3*x^8*y^5*s^5*u)*(23880*z^4*x^3*y^4+15611*z^2*x^2*y^4+24361*z*x^2*y^4+12602*z^4*y^3+20135*z^2*y^3+12135*z^2*x^4*y^2+31261*z^4*x^3*y^2+2238*z^2*x^3*y^2+26706*z^3*x^3*y+7431*z^3*x^2*y+10797*z^3*x*y+41530*z*x*y+14865*x*y+5596*z*y+27*y+31987*z^2*x^3+6828*z^3)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#18: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(13845*z^10*x^11*y^13*s^11+41535*z^10*x^12*y^12*s^11+41535*z^11*x^11*y^12*s^11+41535*z^10*x^13*y^11*s^11+40019*z^11*x^12*y^11*s^11+41535*z^12*x^11*y^11*s^11+13845*z^10*x^14*y^10*s^11+41535*z^11*x^13*y^10*s^11+41535*z^12*x^12*y^10*s^11+13845*z^13*x^11*y^10*s^11+41743*z^8*x^8*y^11*s^9+39127*z^8*x^9*y^10*s^9+39127*z^9*x^8*y^10*s^9+39127*z^8*x^10*y^9*s^9+35203*z^9*x^9*y^9*s^9+39127*z^10*x^8*y^9*s^9+41743*z^8*x^11*y^8*s^9+39127*z^9*x^10*y^8*s^9+39127*z^10*x^9*y^8*s^9+41743*z^11*x^8*y^8*s^9+16873*z^4*x^7*y^5*s^9+7568*z^4*x^8*y^4*s^9+7568*z^5*x^7*y^4*s^9+7568*z^4*x^9*y^3*s^9+15136*z^5*x^8*y^3*s^9+7568*z^6*x^7*y^3*s^9+16873*z^4*x^10*y^2*s^9+7568*z^5*x^9*y^2*s^9+7568*z^6*x^8*y^2*s^9+16873*z^7*x^7*y^2*s^9+29049*z^5*x*y^9*s^8+1045*z^5*x^2*y^8*s^8+1045*z^6*x*y^8*s^8+19583*z*x*y^8*s^8+1045*z^5*x^3*y^7*s^8+2090*z^6*x^2*y^7*s^8+15698*z*x^2*y^7*s^8+1045*z^7*x*y^7*s^8+15698*z^2*x*y^7*s^8+29049*z^5*x^4*y^6*s^8+1045*z^6*x^3*y^6*s^8+15698*z*x^3*y^6*s^8+1045*z^7*x^2*y^6*s^8+31396*z^2*x^2*y^6*s^8+29049*z^8*x*y^6*s^8+15698*z^3*x*y^6*s^8+19583*z*x^4*y^5*s^8+15698*z^2*x^3*y^5*s^8+15698*z^3*x^2*y^5*s^8+19583*z^4*x*y^5*s^8+16680*z^5*x^2*y^10*s^2+24116*z^4*x^9*y^9*s^2+6989*z^5*x^3*y^9*s^2+6989*z^6*x^2*y^9*s^2+8506*x^2*y^9*s^2+29297*z^4*x^10*y^8*s^2+29297*z^5*x^9*y^8*s^2+6989*z^5*x^4*y^8*s^2+13978*z^6*x^3*y^8*s^2+25518*x^3*y^8*s^2+6989*z^7*x^2*y^8*s^2+25518*z*x^2*y^8*s^2+29297*z^4*x^11*y^7*s^2+15543*z^5*x^10*y^7*s^2+29297*z^6*x^9*y^7*s^2+16680*z^5*x^5*y^7*s^2+6989*z^6*x^4*y^7*s^2+25518*x^4*y^7*s^2+6989*z^7*x^3*y^7*s^2+7985*z*x^3*y^7*s^2+16680*z^8*x^2*y^7*s^2+25518*z^2*x^2*y^7*s^2+24116*z^4*x^12*y^6*s^2+29297*z^5*x^11*y^6*s^2+29297*z^6*x^10*y^6*s^2+24116*z^7*x^9*y^6*s^2+8506*x^5*y^6*s^2+25518*z*x^4*y^6*s^2+25518*z^2*x^3*y^6*s^2+8506*z^3*x^2*y^6*s^2+39739*z^8*x^5*y^5*s^2+33115*z^8*x^6*y^4*s^2+33115*z^9*x^5*y^4*s^2+33115*z^8*x^7*y^3*s^2+23179*z^9*x^6*y^3*s^2+33115*z^10*x^5*y^3*s^2+39739*z^8*x^8*y^2*s^2+33115*z^9*x^7*y^2*s^2+33115*z^10*x^6*y^2*s^2+39739*z^11*x^5*y^2*s^2+37652*z*x^4*y^10*s+26854*z*x^5*y^9*s+26854*z^2*x^4*y^9*s+26854*z*x^6*y^8*s+10657*z^2*x^5*y^8*s+26854*z^3*x^4*y^8*s+37652*z*x^7*y^7*s+26854*z^2*x^6*y^7*s+26854*z^3*x^5*y^7*s+37652*z^4*x^4*y^7*s+21629*z^7*x^7*y^5+21836*z^7*x^8*y^4+21836*z^8*x^7*y^4+21836*z^7*x^9*y^3+621*z^8*x^8*y^3+21836*z^9*x^7*y^3+21629*z^7*x^10*y^2+21836*z^8*x^9*y^2+21836*z^9*x^8*y^2+21629*z^10*x^7*y^2)*(40575*z*y^4*s^5+14244*z^2*x^2*y^2*s^5+26755*z*x^5*y^4*s^4+41200*z^3*x^5*y*s^4+42152*x*y^4*s^3+22750*z^5*x^5*y^4*s^2+14342*z^4*y^4*s+33099*z^2*x^2*y^5+27324*z^5*x^2*y^4+12889*x^4*y^3+4017*z^2*x^5)*(30008*z^2*x^2*y^2+13070*x^2*y^2+41530*z*x*y^2+12602*x*y^2+31261*z^2*y^2+5951*z^2*x*y+2238*z*y+10797*z*x^2+6828*z^2)", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#19: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "2036*(x)^2*(y)^2*(y^55+x^27)*(" "x^26*y^27+22502*x^25*y^27+26129*x^24*y^27+29216*x^23*y^27+34834*x^22*y^27+16100*" "x^21*y^27+31667*x^20*y^27+1906*x^19*y^27+22185*x^18*y^27+16677*x^17*y^27+41095*x" "^16*y^27+15123*x^15*y^27+14491*x^14*y^27+5571*x^13*y^27+11913*x^12*y^27+21343*x^" "11*y^27+32816*x^10*y^27+29154*x^9*y^27+22111*x^8*y^27+30147*x^7*y^27+1673*x^6*y^" "27+30810*x^5*y^27+16497*x^4*y^27+39798*x^3*y^27+4394*x^2*y^27+31502*x*y^27+17487" "*y^27+3083*x^26*y^26+7510*x^25*y^26+3246*x^24*y^26+11984*x^23*y^26+25636*x^22*y^" "26+15923*x^21*y^26+542*x^20*y^26+29538*x^19*y^26+26552*x^18*y^26+24474*x^17*y^26" "+4843*x^16*y^26+6664*x^15*y^26+30375*x^14*y^26+25269*x^13*y^26+21676*x^12*y^26+" "33967*x^11*y^26+16441*x^10*y^26+16777*x^9*y^26+32168*x^8*y^26+31612*x^7*y^26+" "30808*x^6*y^26+11273*x^5*y^26+19942*x^4*y^26+6182*x^3*y^26+40996*x^2*y^26+31624*" "x*y^26+63*y^26+20355*x^25*y^25+31973*x^24*y^25+22971*x^23*y^25+27166*x^22*y^25+" "36472*x^21*y^25+35782*x^20*y^25+24678*x^19*y^25+30016*x^18*y^25+4607*x^17*y^25+" "41947*x^16*y^25+31198*x^15*y^25+16004*x^14*y^25+10632*x^13*y^25+18864*x^12*y^25+" "17038*x^11*y^25+25214*x^10*y^25+38756*x^9*y^25+7046*x^8*y^25+19978*x^7*y^25+1376" "*x^6*y^25+41415*x^5*y^25+10386*x^4*y^25+19065*x^3*y^25+17113*x^2*y^25+16281*x*y^" "25+13858*y^25+5491*x^24*y^24+38472*x^23*y^24+35769*x^22*y^24+15694*x^21*y^24+" "33392*x^20*y^24+1146*x^19*y^24+18050*x^18*y^24+12125*x^17*y^24+29102*x^16*y^24+" "38748*x^15*y^24+42753*x^14*y^24+6698*x^13*y^24+28160*x^12*y^24+21070*x^11*y^24+" "41637*x^10*y^24+19616*x^9*y^24+14406*x^8*y^24+23476*x^7*y^24+21817*x^6*y^24+" "25840*x^5*y^24+25086*x^4*y^24+23775*x^3*y^24+21227*x^2*y^24+27888*x*y^24+23515*y" "^24+19459*x^23*y^23+36602*x^22*y^23+208*x^21*y^23+12857*x^20*y^23+12486*x^19*y^" "23+22368*x^18*y^23+2551*x^17*y^23+34235*x^16*y^23+14390*x^15*y^23+5882*x^14*y^23" "+33538*x^13*y^23+42285*x^12*y^23+8690*x^11*y^23+30406*x^10*y^23+27320*x^9*y^23+" "16879*x^8*y^23+3731*x^7*y^23+38196*x^6*y^23+42159*x^5*y^23+8240*x^4*y^23+31121*x" "^3*y^23+35093*x^2*y^23+14738*x*y^23+30083*y^23+7123*x^22*y^22+6572*x^21*y^22+" "8982*x^20*y^22+39575*x^19*y^22+28765*x^18*y^22+20952*x^17*y^22+8540*x^16*y^22+" "2594*x^15*y^22+30737*x^14*y^22+18260*x^13*y^22+19933*x^12*y^22+8099*x^11*y^22+" "29843*x^10*y^22+37536*x^9*y^22+13943*x^8*y^22+1823*x^7*y^22+4331*x^6*y^22+11682*" "x^5*y^22+28595*x^4*y^22+26253*x^3*y^22+21766*x^2*y^22+33032*x*y^22+18506*y^22+" "19732*x^21*y^21+29287*x^20*y^21+33671*x^19*y^21+20636*x^18*y^21+9129*x^17*y^21+" "668*x^16*y^21+12392*x^15*y^21+18209*x^14*y^21+42027*x^13*y^21+10723*x^12*y^21+" "40606*x^11*y^21+21152*x^10*y^21+28922*x^9*y^21+42902*x^8*y^21+23603*x^7*y^21+" "10788*x^6*y^21+40011*x^5*y^21+25015*x^4*y^21+16784*x^3*y^21+7690*x^2*y^21+14090*" "x*y^21+29510*y^21+36673*x^20*y^20+18226*x^19*y^20+9351*x^18*y^20+38118*x^17*y^20" "+17449*x^16*y^20+30651*x^15*y^20+6652*x^14*y^20+4443*x^13*y^20+28114*x^12*y^20+" "27713*x^11*y^20+14382*x^10*y^20+35435*x^9*y^20+15403*x^8*y^20+27528*x^7*y^20+" "35417*x^6*y^20+21835*x^5*y^20+25685*x^4*y^20+3166*x^3*y^20+2542*x^2*y^20+30766*x" "*y^20+31657*y^20+26361*x^19*y^19+1812*x^18*y^19+3983*x^17*y^19+36023*x^16*y^19+" "22928*x^15*y^19+6855*x^14*y^19+27546*x^13*y^19+24902*x^12*y^19+36654*x^11*y^19+" "5191*x^10*y^19+28174*x^9*y^19+10932*x^8*y^19+33381*x^7*y^19+18283*x^6*y^19+10138" "*x^5*y^19+3525*x^4*y^19+31818*x^3*y^19+26751*x^2*y^19+8791*x*y^19+35017*y^19+" "8068*x^18*y^18+11779*x^17*y^18+6526*x^16*y^18+37302*x^15*y^18+11164*x^14*y^18+" "13769*x^13*y^18+39382*x^12*y^18+40572*x^11*y^18+13765*x^10*y^18+24417*x^9*y^18+" "30189*x^8*y^18+21349*x^7*y^18+39167*x^6*y^18+20606*x^5*y^18+14305*x^4*y^18+29683" "*x^3*y^18+1266*x^2*y^18+24840*x*y^18+21656*y^18+16312*x^17*y^17+5217*x^16*y^17+" "41816*x^15*y^17+8280*x^14*y^17+9410*x^13*y^17+9008*x^12*y^17+30427*x^11*y^17+" "2633*x^10*y^17+14363*x^9*y^17+967*x^8*y^17+1177*x^7*y^17+1020*x^6*y^17+29630*x^5" "*y^17+15743*x^4*y^17+20952*x^3*y^17+31064*x^2*y^17+3319*x*y^17+8408*y^17+12350*x" "^16*y^16+14714*x^15*y^16+38478*x^14*y^16+18118*x^13*y^16+38544*x^12*y^16+17870*x" "^11*y^16+39355*x^10*y^16+5319*x^9*y^16+27260*x^8*y^16+30534*x^7*y^16+14619*x^6*y" "^16+29338*x^5*y^16+18577*x^4*y^16+5699*x^3*y^16+25077*x^2*y^16+24985*x*y^16+" "41762*y^16+14161*x^15*y^15+24818*x^14*y^15+2538*x^13*y^15+5694*x^12*y^15+36797*x" "^11*y^15+11305*x^10*y^15+266*x^9*y^15+34388*x^8*y^15+36472*x^7*y^15+35287*x^6*y^" "15+36112*x^5*y^15+39364*x^4*y^15+31042*x^3*y^15+24571*x^2*y^15+22543*x*y^15+" "33036*y^15+3046*x^14*y^14+42428*x^13*y^14+14398*x^12*y^14+8792*x^11*y^14+16394*x" "^10*y^14+24593*x^9*y^14+29104*x^8*y^14+29172*x^7*y^14+4617*x^6*y^14+16803*x^5*y^" "14+38129*x^4*y^14+25100*x^3*y^14+14495*x^2*y^14+16736*x*y^14+5132*y^14+23113*x^" "13*y^13+40441*x^12*y^13+38512*x^11*y^13+8600*x^10*y^13+24449*x^9*y^13+11553*x^8*" "y^13+20503*x^7*y^13+22462*x^6*y^13+28782*x^5*y^13+32654*x^4*y^13+8182*x^3*y^13+" "18208*x^2*y^13+31145*x*y^13+9877*y^13+33439*x^12*y^12+37259*x^11*y^12+3230*x^10*" "y^12+7924*x^9*y^12+21484*x^8*y^12+5249*x^7*y^12+28816*x^6*y^12+36832*x^5*y^12+" "31614*x^4*y^12+30336*x^3*y^12+28977*x^2*y^12+33842*x*y^12+27712*y^12+11480*x^11*" "y^11+42024*x^10*y^11+40159*x^9*y^11+4656*x^8*y^11+13905*x^7*y^11+32675*x^6*y^11+" "15182*x^5*y^11+33276*x^4*y^11+40271*x^3*y^11+33097*x^2*y^11+5450*x*y^11+16545*y^" "11+4444*x^10*y^10+29813*x^9*y^10+30598*x^8*y^10+19265*x^7*y^10+27733*x^6*y^10+" "12332*x^5*y^10+4041*x^4*y^10+17994*x^3*y^10+37626*x^2*y^10+18017*x*y^10+41985*y^" "10+18161*x^9*y^9+37064*x^8*y^9+38753*x^7*y^9+30823*x^6*y^9+12976*x^5*y^9+27156*x" "^4*y^9+22754*x^3*y^9+5457*x^2*y^9+37393*x*y^9+18558*y^9+5969*x^8*y^8+8372*x^7*y^" "8+5034*x^6*y^8+39726*x^5*y^8+23781*x^4*y^8+18050*x^3*y^8+38810*x^2*y^8+22187*x*y" "^8+33578*y^8+6247*x^7*y^7+31686*x^6*y^7+17254*x^5*y^7+13842*x^4*y^7+5880*x^3*y^7" "+7517*x^2*y^7+29126*x*y^7+25434*y^7+42719*x^6*y^6+37537*x^5*y^6+7149*x^4*y^6+" "6926*x^3*y^6+30890*x^2*y^6+33056*x*y^6+35681*y^6+3125*x^5*y^5+33376*x^4*y^5+" "24387*x^3*y^5+23868*x^2*y^5+35142*x*y^5+5143*y^5+40391*x^4*y^4+657*x^3*y^4+30346" "*x^2*y^4+30607*x*y^4+9432*y^4+31094*x^3*y^3+25871*x^2*y^3+29619*x*y^3+40511*y^3+" "747*x^2*y^2+23254*x*y^2+39636*y^2+17316*x*y+3609*y+8994)*(" "x^53*y^53+18147*x^52*y^53+43022*x^51*y^53+40085*x^50*y^53+28237*x^49*y^53+30609*" "x^48*y^53+24338*x^47*y^53+34438*x^46*y^53+17995*x^45*y^53+11285*x^44*y^53+23365*" "x^43*y^53+34068*x^42*y^53+36580*x^41*y^53+18333*x^40*y^53+28343*x^39*y^53+10219*" "x^38*y^53+41928*x^37*y^53+14530*x^36*y^53+8169*x^35*y^53+10664*x^34*y^53+28456*x" "^33*y^53+40045*x^32*y^53+36063*x^31*y^53+40317*x^30*y^53+3892*x^29*y^53+18610*x^" "28*y^53+42334*x^27*y^53+11181*x^26*y^53+14187*x^25*y^53+19731*x^24*y^53+15756*x^" "23*y^53+9842*x^22*y^53+12573*x^21*y^53+3119*x^20*y^53+21843*x^19*y^53+2270*x^18*" "y^53+25305*x^17*y^53+38419*x^16*y^53+23222*x^15*y^53+29693*x^14*y^53+37556*x^13*" "y^53+16413*x^12*y^53+4411*x^11*y^53+27575*x^10*y^53+15150*x^9*y^53+6260*x^8*y^53" "+27551*x^7*y^53+25107*x^6*y^53+32932*x^5*y^53+38353*x^4*y^53+9*x^3*y^53+5495*x^2" "*y^53+10261*x*y^53+31369*y^53+5547*x^52*y^52+30032*x^51*y^52+284*x^50*y^52+14830" "*x^49*y^52+22659*x^48*y^52+10626*x^47*y^52+22237*x^46*y^52+38950*x^45*y^52+40954" "*x^44*y^52+9413*x^43*y^52+21276*x^42*y^52+31506*x^41*y^52+9404*x^40*y^52+10655*x" "^39*y^52+10743*x^38*y^52+4401*x^37*y^52+32372*x^36*y^52+15524*x^35*y^52+28427*x^" "34*y^52+26855*x^33*y^52+530*x^32*y^52+28907*x^31*y^52+4066*x^30*y^52+20491*x^29*" "y^52+2863*x^28*y^52+12779*x^27*y^52+40264*x^26*y^52+27587*x^25*y^52+2553*x^24*y^" "52+6016*x^23*y^52+2097*x^22*y^52+39570*x^21*y^52+34283*x^20*y^52+17879*x^19*y^52" "+17020*x^18*y^52+40538*x^17*y^52+25557*x^16*y^52+39049*x^15*y^52+12516*x^14*y^52" "+20550*x^13*y^52+37236*x^12*y^52+27582*x^11*y^52+40355*x^10*y^52+9244*x^9*y^52+" "12348*x^8*y^52+3487*x^7*y^52+34984*x^6*y^52+6073*x^5*y^52+39538*x^4*y^52+28840*x" "^3*y^52+6672*x^2*y^52+35673*x*y^52+21090*y^52+26879*x^51*y^51+19080*x^50*y^51+" "20236*x^49*y^51+40752*x^48*y^51+4404*x^47*y^51+28484*x^46*y^51+19369*x^45*y^51+" "21123*x^44*y^51+42333*x^43*y^51+3104*x^42*y^51+41974*x^41*y^51+1561*x^40*y^51+" "11103*x^39*y^51+10769*x^38*y^51+27387*x^37*y^51+21812*x^36*y^51+1578*x^35*y^51+" "39358*x^34*y^51+22262*x^33*y^51+28872*x^32*y^51+29393*x^31*y^51+37195*x^30*y^51+" "9259*x^29*y^51+12198*x^28*y^51+33283*x^27*y^51+6171*x^26*y^51+1678*x^25*y^51+" "19116*x^24*y^51+34014*x^23*y^51+42437*x^22*y^51+17526*x^21*y^51+30549*x^20*y^51+" "29170*x^19*y^51+16093*x^18*y^51+4549*x^17*y^51+42768*x^16*y^51+40904*x^15*y^51+" "3467*x^14*y^51+36407*x^13*y^51+18943*x^12*y^51+22205*x^11*y^51+7868*x^10*y^51+" "15795*x^9*y^51+36617*x^8*y^51+17510*x^7*y^51+15678*x^6*y^51+16520*x^5*y^51+40409" "*x^4*y^51+27740*x^3*y^51+35836*x^2*y^51+30552*x*y^51+20808*y^51+42970*x^50*y^50+" "5860*x^49*y^50+23145*x^48*y^50+9906*x^47*y^50+34850*x^46*y^50+38599*x^45*y^50+" "40329*x^44*y^50+15967*x^43*y^50+7261*x^42*y^50+41272*x^41*y^50+4284*x^40*y^50+" "37022*x^39*y^50+27603*x^38*y^50+8694*x^37*y^50+42972*x^36*y^50+26061*x^35*y^50+" "18941*x^34*y^50+4252*x^33*y^50+34789*x^32*y^50+34843*x^31*y^50+13722*x^30*y^50+" "20217*x^29*y^50+16944*x^28*y^50+7910*x^27*y^50+30072*x^26*y^50+9131*x^25*y^50+" "17095*x^24*y^50+38859*x^23*y^50+11391*x^22*y^50+8284*x^21*y^50+40113*x^20*y^50+" "16017*x^19*y^50+30360*x^18*y^50+28241*x^17*y^50+42497*x^16*y^50+12082*x^15*y^50+" "1284*x^14*y^50+16288*x^13*y^50+24860*x^12*y^50+13411*x^11*y^50+10975*x^10*y^50+" "33044*x^9*y^50+8235*x^8*y^50+22317*x^7*y^50+31218*x^6*y^50+20511*x^5*y^50+24255*" "x^4*y^50+26118*x^3*y^50+31607*x^2*y^50+12349*x*y^50+39022*y^50+13425*x^49*y^49+" "39757*x^48*y^49+27451*x^47*y^49+194*x^46*y^49+24526*x^45*y^49+9875*x^44*y^49+" "31606*x^43*y^49+38444*x^42*y^49+18652*x^41*y^49+29818*x^40*y^49+15631*x^39*y^49+" "21247*x^38*y^49+10326*x^37*y^49+30737*x^36*y^49+28353*x^35*y^49+32283*x^34*y^49+" "40894*x^33*y^49+19141*x^32*y^49+11212*x^31*y^49+4674*x^30*y^49+28404*x^29*y^49+" "33933*x^28*y^49+6387*x^27*y^49+32050*x^26*y^49+14228*x^25*y^49+29664*x^24*y^49+" "35576*x^23*y^49+40915*x^22*y^49+40400*x^21*y^49+1818*x^20*y^49+31280*x^19*y^49+" "6559*x^18*y^49+33932*x^17*y^49+37524*x^16*y^49+27603*x^15*y^49+10707*x^14*y^49+" "32695*x^13*y^49+26450*x^12*y^49+25719*x^11*y^49+38755*x^10*y^49+6656*x^9*y^49+" "21403*x^8*y^49+5632*x^7*y^49+888*x^6*y^49+42735*x^5*y^49+13602*x^4*y^49+24940*x^" "3*y^49+38405*x^2*y^49+8054*x*y^49+20049*y^49+27372*x^48*y^48+30233*x^47*y^48+657" "*x^46*y^48+29614*x^45*y^48+20701*x^44*y^48+23794*x^43*y^48+3737*x^42*y^48+6648*x" "^41*y^48+20102*x^40*y^48+22356*x^39*y^48+32369*x^38*y^48+12432*x^37*y^48+26613*x" "^36*y^48+21249*x^35*y^48+5150*x^34*y^48+2672*x^33*y^48+15097*x^32*y^48+37938*x^" "31*y^48+14805*x^30*y^48+22802*x^29*y^48+39201*x^28*y^48+30407*x^27*y^48+20653*x^" "26*y^48+33705*x^25*y^48+23079*x^24*y^48+2198*x^23*y^48+38433*x^22*y^48+7227*x^21" "*y^48+23891*x^20*y^48+3967*x^19*y^48+37476*x^18*y^48+36934*x^17*y^48+12206*x^16*" "y^48+22197*x^15*y^48+10245*x^14*y^48+22127*x^13*y^48+41418*x^12*y^48+814*x^11*y^" "48+31931*x^10*y^48+38041*x^9*y^48+6354*x^8*y^48+22194*x^7*y^48+22787*x^6*y^48+" "30170*x^5*y^48+5917*x^4*y^48+36122*x^3*y^48+19222*x^2*y^48+32886*x*y^48+22622*y^" "48+3812*x^47*y^47+25985*x^46*y^47+36819*x^45*y^47+13268*x^44*y^47+35718*x^43*y^" "47+24087*x^42*y^47+33429*x^41*y^47+38428*x^40*y^47+42427*x^39*y^47+18508*x^38*y^" "47+807*x^37*y^47+28580*x^36*y^47+12219*x^35*y^47+38548*x^34*y^47+41213*x^33*y^47" "+13374*x^32*y^47+240*x^31*y^47+18855*x^30*y^47+3163*x^29*y^47+39802*x^28*y^47+" "4065*x^27*y^47+21549*x^26*y^47+35680*x^25*y^47+30407*x^24*y^47+9345*x^23*y^47+" "37516*x^22*y^47+31854*x^21*y^47+10318*x^20*y^47+2740*x^19*y^47+11306*x^18*y^47+" "5988*x^17*y^47+16224*x^16*y^47+22259*x^15*y^47+19555*x^14*y^47+20347*x^13*y^47+" "6069*x^12*y^47+20053*x^11*y^47+9241*x^10*y^47+29531*x^9*y^47+12594*x^8*y^47+" "25231*x^7*y^47+2145*x^6*y^47+36468*x^5*y^47+24431*x^4*y^47+38896*x^3*y^47+13456*" "x^2*y^47+40531*x*y^47+9268*y^47+33917*x^46*y^46+7802*x^45*y^46+43037*x^44*y^46+" "20656*x^43*y^46+37129*x^42*y^46+11642*x^41*y^46+19623*x^40*y^46+796*x^39*y^46+" "16361*x^38*y^46+41230*x^37*y^46+29857*x^36*y^46+24087*x^35*y^46+5566*x^34*y^46+" "6421*x^33*y^46+40958*x^32*y^46+37371*x^31*y^46+18049*x^30*y^46+19808*x^29*y^46+" "5885*x^28*y^46+38032*x^27*y^46+5553*x^26*y^46+42145*x^25*y^46+34158*x^24*y^46+" "38717*x^23*y^46+5514*x^22*y^46+39714*x^21*y^46+17252*x^20*y^46+13415*x^19*y^46+" "9576*x^18*y^46+35622*x^17*y^46+34212*x^16*y^46+28019*x^15*y^46+42386*x^14*y^46+" "27403*x^13*y^46+38945*x^12*y^46+12139*x^11*y^46+29342*x^10*y^46+13347*x^9*y^46+" "37592*x^8*y^46+13920*x^7*y^46+30889*x^6*y^46+13930*x^5*y^46+21793*x^4*y^46+9482*" "x^3*y^46+42650*x^2*y^46+2703*x*y^46+19032*y^46+40355*x^45*y^45+34673*x^44*y^45+" "16318*x^43*y^45+38013*x^42*y^45+30018*x^41*y^45+7755*x^40*y^45+16854*x^39*y^45+" "25824*x^38*y^45+30004*x^37*y^45+22057*x^36*y^45+30486*x^35*y^45+18166*x^34*y^45+" "30268*x^33*y^45+42335*x^32*y^45+9703*x^31*y^45+8876*x^30*y^45+31479*x^29*y^45+" "4458*x^28*y^45+1013*x^27*y^45+26568*x^26*y^45+26890*x^25*y^45+37461*x^24*y^45+" "16554*x^23*y^45+7323*x^22*y^45+8189*x^21*y^45+6451*x^20*y^45+33300*x^19*y^45+" "26185*x^18*y^45+24508*x^17*y^45+23070*x^16*y^45+5113*x^15*y^45+29902*x^14*y^45+" "23508*x^13*y^45+29179*x^12*y^45+24325*x^11*y^45+691*x^10*y^45+9957*x^9*y^45+" "23116*x^8*y^45+31858*x^7*y^45+40746*x^6*y^45+23740*x^5*y^45+16587*x^4*y^45+18456" "*x^3*y^45+22891*x^2*y^45+24232*x*y^45+24901*y^45+1581*x^44*y^44+8067*x^43*y^44+" "40636*x^42*y^44+590*x^41*y^44+28238*x^40*y^44+18484*x^39*y^44+13782*x^38*y^44+" "26591*x^37*y^44+38088*x^36*y^44+7380*x^35*y^44+35239*x^34*y^44+1000*x^33*y^44+" "20981*x^32*y^44+4647*x^31*y^44+37942*x^30*y^44+8411*x^29*y^44+1844*x^28*y^44+" "42980*x^27*y^44+1636*x^26*y^44+19108*x^25*y^44+10146*x^24*y^44+20133*x^23*y^44+" "31891*x^22*y^44+36956*x^21*y^44+4778*x^20*y^44+28052*x^19*y^44+7656*x^18*y^44+" "23804*x^17*y^44+25604*x^16*y^44+34159*x^15*y^44+39731*x^14*y^44+40121*x^13*y^44+" "33040*x^12*y^44+19546*x^11*y^44+4051*x^10*y^44+22053*x^9*y^44+8357*x^8*y^44+" "13907*x^7*y^44+25422*x^6*y^44+16353*x^5*y^44+17091*x^4*y^44+10820*x^3*y^44+10885" "*x^2*y^44+26791*x*y^44+26814*y^44+30035*x^43*y^43+19261*x^42*y^43+5960*x^41*y^43" "+25009*x^40*y^43+31459*x^39*y^43+5593*x^38*y^43+11908*x^37*y^43+40759*x^36*y^43+" "25678*x^35*y^43+317*x^34*y^43+2911*x^33*y^43+21930*x^32*y^43+10338*x^31*y^43+" "18544*x^30*y^43+21395*x^29*y^43+32184*x^28*y^43+2508*x^27*y^43+30020*x^26*y^43+" "36827*x^25*y^43+32729*x^24*y^43+37356*x^23*y^43+37941*x^22*y^43+38560*x^21*y^43+" "25442*x^20*y^43+15046*x^19*y^43+25010*x^18*y^43+29960*x^17*y^43+317*x^16*y^43+" "19367*x^15*y^43+12431*x^14*y^43+22477*x^13*y^43+7299*x^12*y^43+29600*x^11*y^43+" "18368*x^10*y^43+30660*x^9*y^43+31625*x^8*y^43+34063*x^7*y^43+39332*x^6*y^43+" "42283*x^5*y^43+24888*x^4*y^43+19738*x^3*y^43+2405*x^2*y^43+5956*x*y^43+4332*y^43" "+39260*x^42*y^42+19385*x^41*y^42+31659*x^40*y^42+34965*x^39*y^42+34569*x^38*y^42" "+20394*x^37*y^42+29989*x^36*y^42+4513*x^35*y^42+8431*x^34*y^42+40216*x^33*y^42+" "42045*x^32*y^42+17569*x^31*y^42+17859*x^30*y^42+7805*x^29*y^42+39762*x^28*y^42+" "7624*x^27*y^42+12453*x^26*y^42+13594*x^25*y^42+42421*x^24*y^42+36751*x^23*y^42+" "21549*x^22*y^42+1117*x^21*y^42+27687*x^20*y^42+17486*x^19*y^42+37758*x^18*y^42+" "41570*x^17*y^42+4711*x^16*y^42+21777*x^15*y^42+9007*x^14*y^42+14510*x^13*y^42+" "495*x^12*y^42+27546*x^11*y^42+15369*x^10*y^42+28778*x^9*y^42+1890*x^8*y^42+38622" "*x^7*y^42+14667*x^6*y^42+24823*x^5*y^42+26179*x^4*y^42+37676*x^3*y^42+19558*x^2*" "y^42+20984*x*y^42+33240*y^42+36690*x^41*y^41+17023*x^40*y^41+17026*x^39*y^41+" "6811*x^38*y^41+16785*x^37*y^41+12085*x^36*y^41+29521*x^35*y^41+34282*x^34*y^41+" "8706*x^33*y^41+37090*x^32*y^41+30501*x^31*y^41+18192*x^30*y^41+35111*x^29*y^41+" "39271*x^28*y^41+5042*x^27*y^41+25069*x^26*y^41+34380*x^25*y^41+13858*x^24*y^41+" "9698*x^23*y^41+12876*x^22*y^41+18196*x^21*y^41+31276*x^20*y^41+38122*x^19*y^41+" "12008*x^18*y^41+24932*x^17*y^41+33107*x^16*y^41+20016*x^15*y^41+11013*x^14*y^41+" "39534*x^13*y^41+28790*x^12*y^41+9663*x^11*y^41+34756*x^10*y^41+41666*x^9*y^41+" "33575*x^8*y^41+31797*x^7*y^41+17028*x^6*y^41+35080*x^5*y^41+23794*x^4*y^41+31927" "*x^3*y^41+42101*x^2*y^41+3694*x*y^41+17898*y^41+5030*x^40*y^40+20705*x^39*y^40+" "40138*x^38*y^40+20010*x^37*y^40+41623*x^36*y^40+3326*x^35*y^40+21134*x^34*y^40+" "36214*x^33*y^40+42448*x^32*y^40+9904*x^31*y^40+3791*x^30*y^40+38996*x^29*y^40+" "7031*x^28*y^40+21395*x^27*y^40+16931*x^26*y^40+23563*x^25*y^40+5604*x^24*y^40+" "18577*x^23*y^40+17832*x^22*y^40+38462*x^21*y^40+17939*x^20*y^40+13578*x^19*y^40+" "5091*x^18*y^40+11389*x^17*y^40+41259*x^16*y^40+6438*x^15*y^40+35827*x^14*y^40+" "38132*x^13*y^40+14738*x^12*y^40+35596*x^11*y^40+22288*x^10*y^40+38612*x^9*y^40+" "30582*x^8*y^40+9216*x^7*y^40+22498*x^6*y^40+41447*x^5*y^40+21423*x^4*y^40+18859*" "x^3*y^40+2943*x^2*y^40+42*x*y^40+26122*y^40+21917*x^39*y^39+16248*x^38*y^39+" "12815*x^37*y^39+1065*x^36*y^39+23742*x^35*y^39+3529*x^34*y^39+6933*x^33*y^39+" "6197*x^32*y^39+18254*x^31*y^39+5200*x^30*y^39+14892*x^29*y^39+32191*x^28*y^39+" "27194*x^27*y^39+12220*x^26*y^39+15416*x^25*y^39+8038*x^24*y^39+23518*x^23*y^39+" "21732*x^22*y^39+40262*x^21*y^39+3864*x^20*y^39+18543*x^19*y^39+32141*x^18*y^39+" "6335*x^17*y^39+16625*x^16*y^39+22604*x^15*y^39+25647*x^14*y^39+14043*x^13*y^39+" "37489*x^12*y^39+32245*x^11*y^39+24467*x^10*y^39+124*x^9*y^39+27492*x^8*y^39+72*x" "^7*y^39+7216*x^6*y^39+8002*x^5*y^39+18089*x^4*y^39+11437*x^3*y^39+35176*x^2*y^39" "+18285*x*y^39+28670*y^39+4532*x^38*y^38+37470*x^37*y^38+19891*x^36*y^38+41542*x^" "35*y^38+9718*x^34*y^38+42839*x^33*y^38+8238*x^32*y^38+22952*x^31*y^38+39648*x^30" "*y^38+28131*x^29*y^38+22317*x^28*y^38+25299*x^27*y^38+23511*x^26*y^38+9894*x^25*" "y^38+13716*x^24*y^38+35578*x^23*y^38+31881*x^22*y^38+13171*x^21*y^38+31957*x^20*" "y^38+7557*x^19*y^38+9080*x^18*y^38+33605*x^17*y^38+28061*x^16*y^38+26224*x^15*y^" "38+38115*x^14*y^38+12579*x^13*y^38+9476*x^12*y^38+18826*x^11*y^38+24558*x^10*y^" "38+32988*x^9*y^38+4475*x^8*y^38+1586*x^7*y^38+37795*x^6*y^38+21563*x^5*y^38+" "41768*x^4*y^38+25716*x^3*y^38+5730*x^2*y^38+6989*x*y^38+2665*y^38+18474*x^37*y^" "37+17873*x^36*y^37+37340*x^35*y^37+39770*x^34*y^37+23012*x^33*y^37+12488*x^32*y^" "37+35457*x^31*y^37+24228*x^30*y^37+38299*x^29*y^37+31351*x^28*y^37+41876*x^27*y^" "37+15132*x^26*y^37+29672*x^25*y^37+19441*x^24*y^37+27592*x^23*y^37+1004*x^22*y^" "37+23100*x^21*y^37+24305*x^20*y^37+35140*x^19*y^37+29466*x^18*y^37+34872*x^17*y^" "37+31689*x^16*y^37+41226*x^15*y^37+6209*x^14*y^37+18431*x^13*y^37+15545*x^12*y^" "37+4217*x^11*y^37+12267*x^10*y^37+23055*x^9*y^37+27958*x^8*y^37+24946*x^7*y^37+" "18221*x^6*y^37+3834*x^5*y^37+35345*x^4*y^37+25813*x^3*y^37+20611*x^2*y^37+16263*" "x*y^37+20199*y^37+14465*x^36*y^36+3944*x^35*y^36+10818*x^34*y^36+33496*x^33*y^36" "+40148*x^32*y^36+40913*x^31*y^36+32228*x^30*y^36+25515*x^29*y^36+27597*x^28*y^36" "+40498*x^27*y^36+14302*x^26*y^36+14742*x^25*y^36+18012*x^24*y^36+20790*x^23*y^36" "+1636*x^22*y^36+40195*x^21*y^36+40702*x^20*y^36+22371*x^19*y^36+734*x^18*y^36+" "23769*x^17*y^36+38645*x^16*y^36+9831*x^15*y^36+5784*x^14*y^36+14661*x^13*y^36+" "33984*x^12*y^36+24153*x^11*y^36+2695*x^10*y^36+34150*x^9*y^36+1475*x^8*y^36+" "38333*x^7*y^36+860*x^6*y^36+15027*x^5*y^36+19228*x^4*y^36+41952*x^3*y^36+8466*x^" "2*y^36+13330*x*y^36+31877*y^36+22137*x^35*y^35+26911*x^34*y^35+3921*x^33*y^35+" "30649*x^32*y^35+36112*x^31*y^35+26462*x^30*y^35+18707*x^29*y^35+24132*x^28*y^35+" "21788*x^27*y^35+5384*x^26*y^35+31009*x^25*y^35+7078*x^24*y^35+32871*x^23*y^35+" "40177*x^22*y^35+34384*x^21*y^35+34362*x^20*y^35+14431*x^19*y^35+17033*x^18*y^35+" "37687*x^17*y^35+15153*x^16*y^35+4993*x^15*y^35+7366*x^14*y^35+32202*x^13*y^35+" "4531*x^12*y^35+21959*x^11*y^35+10107*x^10*y^35+6830*x^9*y^35+37430*x^8*y^35+" "26724*x^7*y^35+29060*x^6*y^35+3962*x^5*y^35+27723*x^4*y^35+42152*x^3*y^35+39841*" "x^2*y^35+2484*x*y^35+13587*y^35+466*x^34*y^34+31954*x^33*y^34+30801*x^32*y^34+" "8936*x^31*y^34+5640*x^30*y^34+2119*x^29*y^34+38507*x^28*y^34+2916*x^27*y^34+" "34260*x^26*y^34+9889*x^25*y^34+17037*x^24*y^34+41972*x^23*y^34+24788*x^22*y^34+" "42342*x^21*y^34+12153*x^20*y^34+31900*x^19*y^34+32150*x^18*y^34+353*x^17*y^34+" "13211*x^16*y^34+26356*x^15*y^34+22476*x^14*y^34+37191*x^13*y^34+7778*x^12*y^34+" "22556*x^11*y^34+5996*x^10*y^34+29641*x^9*y^34+41363*x^8*y^34+30009*x^7*y^34+" "22934*x^6*y^34+17759*x^5*y^34+25741*x^4*y^34+6401*x^3*y^34+36544*x^2*y^34+171*x*" "y^34+37979*y^34+15313*x^33*y^33+31019*x^32*y^33+17942*x^31*y^33+38375*x^30*y^33+" "41049*x^29*y^33+35567*x^28*y^33+17522*x^27*y^33+11884*x^26*y^33+38114*x^25*y^33+" "40939*x^24*y^33+37389*x^23*y^33+24852*x^22*y^33+18117*x^21*y^33+10444*x^20*y^33+" "4656*x^19*y^33+12501*x^18*y^33+14323*x^17*y^33+12415*x^16*y^33+27799*x^15*y^33+" "18562*x^14*y^33+2589*x^13*y^33+27567*x^12*y^33+16865*x^11*y^33+13922*x^10*y^33+" "33463*x^9*y^33+17112*x^8*y^33+11243*x^7*y^33+2891*x^6*y^33+32742*x^5*y^33+42456*" "x^4*y^33+2235*x^3*y^33+4800*x^2*y^33+40847*x*y^33+5399*y^33+14186*x^32*y^32+" "14885*x^31*y^32+41339*x^30*y^32+40829*x^29*y^32+3576*x^28*y^32+38477*x^27*y^32+" "8225*x^26*y^32+35327*x^25*y^32+27970*x^24*y^32+14944*x^23*y^32+15098*x^22*y^32+" "41185*x^21*y^32+38742*x^20*y^32+22816*x^19*y^32+18799*x^18*y^32+3939*x^17*y^32+" "5267*x^16*y^32+3223*x^15*y^32+18224*x^14*y^32+24474*x^13*y^32+12038*x^12*y^32+" "21401*x^11*y^32+7939*x^10*y^32+5051*x^9*y^32+25616*x^8*y^32+32954*x^7*y^32+11947" "*x^6*y^32+31059*x^5*y^32+9947*x^4*y^32+16462*x^3*y^32+5660*x^2*y^32+4926*x*y^32+" "31371*y^32+24980*x^31*y^31+10429*x^30*y^31+29583*x^29*y^31+25670*x^28*y^31+30325" "*x^27*y^31+32707*x^26*y^31+4554*x^25*y^31+4824*x^24*y^31+14157*x^23*y^31+2480*x^" "22*y^31+26739*x^21*y^31+33788*x^20*y^31+33490*x^19*y^31+13645*x^18*y^31+31574*x^" "17*y^31+24871*x^16*y^31+23525*x^15*y^31+25346*x^14*y^31+11150*x^13*y^31+5930*x^" "12*y^31+17831*x^11*y^31+25316*x^10*y^31+11055*x^9*y^31+40769*x^8*y^31+39049*x^7*" "y^31+6889*x^6*y^31+29402*x^5*y^31+17396*x^4*y^31+26425*x^3*y^31+29573*x^2*y^31+" "3048*x*y^31+2061*y^31+25688*x^30*y^30+10729*x^29*y^30+10281*x^28*y^30+2873*x^27*" "y^30+7957*x^26*y^30+6862*x^25*y^30+12421*x^24*y^30+22267*x^23*y^30+18530*x^22*y^" "30+31964*x^21*y^30+2708*x^20*y^30+29289*x^19*y^30+22534*x^18*y^30+16556*x^17*y^" "30+16343*x^16*y^30+24490*x^15*y^30+51*x^14*y^30+13138*x^13*y^30+37878*x^12*y^30+" "32475*x^11*y^30+9118*x^10*y^30+23428*x^9*y^30+36826*x^8*y^30+17404*x^7*y^30+6387" "*x^6*y^30+39313*x^5*y^30+11115*x^4*y^30+11112*x^3*y^30+39059*x^2*y^30+36567*x*y^" "30+3244*y^30+10546*x^29*y^29+40279*x^28*y^29+8192*x^27*y^29+31945*x^26*y^29+8036" "*x^25*y^29+7530*x^24*y^29+15828*x^23*y^29+39078*x^22*y^29+22083*x^21*y^29+546*x^" "20*y^29+32237*x^19*y^29+15428*x^18*y^29+26710*x^17*y^29+36279*x^16*y^29+493*x^15" "*y^29+41644*x^14*y^29+17588*x^13*y^29+37437*x^12*y^29+8873*x^11*y^29+15706*x^10*" "y^29+12130*x^9*y^29+10474*x^8*y^29+8157*x^7*y^29+21743*x^6*y^29+5867*x^5*y^29+" "36624*x^4*y^29+29051*x^3*y^29+39496*x^2*y^29+11651*x*y^29+21746*y^29+30819*x^28*" "y^28+38218*x^27*y^28+33643*x^26*y^28+19933*x^25*y^28+870*x^24*y^28+36669*x^23*y^" "28+7497*x^22*y^28+25876*x^21*y^28+1074*x^20*y^28+4707*x^19*y^28+41663*x^18*y^28+" "14372*x^17*y^28+31723*x^16*y^28+26094*x^15*y^28+31950*x^14*y^28+7385*x^13*y^28+" "34842*x^12*y^28+39265*x^11*y^28+32953*x^10*y^28+3198*x^9*y^28+37808*x^8*y^28+" "31909*x^7*y^28+21768*x^6*y^28+15479*x^5*y^28+1803*x^4*y^28+26958*x^3*y^28+21801*" "x^2*y^28+24033*x*y^28+22473*y^28+7589*x^27*y^27+4367*x^26*y^27+20572*x^25*y^27+" "39710*x^24*y^27+8092*x^23*y^27+25234*x^22*y^27+13211*x^21*y^27+11362*x^20*y^27+" "18325*x^19*y^27+12979*x^18*y^27+41351*x^17*y^27+37022*x^16*y^27+34113*x^15*y^27+" "10288*x^14*y^27+36321*x^13*y^27+14218*x^12*y^27+37248*x^11*y^27+40101*x^10*y^27+" "28540*x^9*y^27+34804*x^8*y^27+9105*x^7*y^27+6660*x^6*y^27+11207*x^5*y^27+22855*x" "^4*y^27+40243*x^3*y^27+41892*x^2*y^27+24857*x*y^27+28411*y^27+14847*x^26*y^26+" "32215*x^25*y^26+5485*x^24*y^26+4576*x^23*y^26+39245*x^22*y^26+24182*x^21*y^26+" "35561*x^20*y^26+5451*x^19*y^26+7418*x^18*y^26+20800*x^17*y^26+17607*x^16*y^26+" "12464*x^15*y^26+31957*x^14*y^26+40498*x^13*y^26+13706*x^12*y^26+14134*x^11*y^26+" "11623*x^10*y^26+31906*x^9*y^26+9172*x^8*y^26+9678*x^7*y^26+42073*x^6*y^26+21816*" "x^5*y^26+9905*x^4*y^26+21512*x^3*y^26+9958*x^2*y^26+37130*x*y^26+18774*y^26+" "17837*x^25*y^25+10493*x^24*y^25+27604*x^23*y^25+24967*x^22*y^25+26075*x^21*y^25+" "2779*x^20*y^25+14140*x^19*y^25+23181*x^18*y^25+38206*x^17*y^25+12289*x^16*y^25+" "17597*x^15*y^25+21453*x^14*y^25+2796*x^13*y^25+10492*x^12*y^25+35608*x^11*y^25+" "11080*x^10*y^25+39047*x^9*y^25+11198*x^8*y^25+40664*x^7*y^25+8717*x^6*y^25+2104*" "x^5*y^25+6462*x^4*y^25+945*x^3*y^25+4611*x^2*y^25+39716*x*y^25+20421*y^25+25068*" "x^24*y^24+37094*x^23*y^24+35791*x^22*y^24+28613*x^21*y^24+16768*x^20*y^24+17224*" "x^19*y^24+27360*x^18*y^24+40916*x^17*y^24+2844*x^16*y^24+35191*x^15*y^24+34962*x" "^14*y^24+10333*x^13*y^24+34628*x^12*y^24+28608*x^11*y^24+10876*x^10*y^24+23038*x" "^9*y^24+33994*x^8*y^24+30860*x^7*y^24+34744*x^6*y^24+14153*x^5*y^24+41239*x^4*y^" "24+25076*x^3*y^24+777*x^2*y^24+13338*x*y^24+32637*y^24+38843*x^23*y^23+26338*x^" "22*y^23+27918*x^21*y^23+24043*x^20*y^23+1599*x^19*y^23+19731*x^18*y^23+20154*x^" "17*y^23+6166*x^16*y^23+20721*x^15*y^23+21112*x^14*y^23+8898*x^13*y^23+38361*x^12" "*y^23+37265*x^11*y^23+10091*x^10*y^23+12686*x^9*y^23+13789*x^8*y^23+28215*x^7*y^" "23+27651*x^6*y^23+40100*x^5*y^23+28948*x^4*y^23+5650*x^3*y^23+39475*x^2*y^23+" "17889*x*y^23+12555*y^23+13632*x^22*y^22+5483*x^21*y^22+10809*x^20*y^22+5154*x^19" "*y^22+41705*x^18*y^22+36857*x^17*y^22+23493*x^16*y^22+9585*x^15*y^22+13620*x^14*" "y^22+39469*x^13*y^22+37948*x^12*y^22+27976*x^11*y^22+32606*x^10*y^22+10965*x^9*y" "^22+36314*x^8*y^22+11877*x^7*y^22+32677*x^6*y^22+30277*x^5*y^22+36275*x^4*y^22+" "20185*x^3*y^22+40116*x^2*y^22+7415*x*y^22+30632*y^22+24620*x^21*y^21+21412*x^20*" "y^21+830*x^19*y^21+10356*x^18*y^21+872*x^17*y^21+20256*x^16*y^21+15659*x^15*y^21" "+19693*x^14*y^21+15424*x^13*y^21+19893*x^12*y^21+5829*x^11*y^21+7319*x^10*y^21+" "24476*x^9*y^21+20773*x^8*y^21+289*x^7*y^21+33710*x^6*y^21+574*x^5*y^21+38775*x^4" "*y^21+9839*x^3*y^21+15268*x^2*y^21+27786*x*y^21+28450*y^21+20398*x^20*y^20+9431*" "x^19*y^20+1699*x^18*y^20+33355*x^17*y^20+2995*x^16*y^20+31114*x^15*y^20+9506*x^" "14*y^20+9026*x^13*y^20+30973*x^12*y^20+4232*x^11*y^20+16928*x^10*y^20+10179*x^9*" "y^20+4292*x^8*y^20+10780*x^7*y^20+40092*x^6*y^20+5546*x^5*y^20+32176*x^4*y^20+" "14031*x^3*y^20+13990*x^2*y^20+26324*x*y^20+40218*y^20+11114*x^19*y^19+30557*x^18" "*y^19+9052*x^17*y^19+25115*x^16*y^19+35097*x^15*y^19+8092*x^14*y^19+15130*x^13*y" "^19+8004*x^12*y^19+1495*x^11*y^19+27644*x^10*y^19+24610*x^9*y^19+38821*x^8*y^19+" "19648*x^7*y^19+26314*x^6*y^19+23318*x^5*y^19+38165*x^4*y^19+33175*x^3*y^19+3381*" "x^2*y^19+28440*x*y^19+207*y^19+21053*x^18*y^18+35057*x^17*y^18+8238*x^16*y^18+" "33300*x^15*y^18+12824*x^14*y^18+37945*x^13*y^18+33900*x^12*y^18+13601*x^11*y^18+" "29959*x^10*y^18+12862*x^9*y^18+21879*x^8*y^18+31948*x^7*y^18+3099*x^6*y^18+15507" "*x^5*y^18+5575*x^4*y^18+26045*x^3*y^18+29592*x^2*y^18+10936*x*y^18+15772*y^18+" "713*x^17*y^17+32307*x^16*y^17+41726*x^15*y^17+20941*x^14*y^17+28478*x^13*y^17+" "18581*x^12*y^17+22577*x^11*y^17+30966*x^10*y^17+8170*x^9*y^17+17869*x^8*y^17+" "6744*x^7*y^17+27888*x^6*y^17+32051*x^5*y^17+30810*x^4*y^17+14707*x^3*y^17+38126*" "x^2*y^17+33384*x*y^17+23882*y^17+6803*x^16*y^16+30672*x^15*y^16+26280*x^14*y^16+" "14477*x^13*y^16+24391*x^12*y^16+11327*x^11*y^16+2705*x^10*y^16+36645*x^9*y^16+" "11888*x^8*y^16+32246*x^7*y^16+13623*x^6*y^16+37322*x^5*y^16+38519*x^4*y^16+31179" "*x^3*y^16+34600*x^2*y^16+29376*x*y^16+2154*y^16+26152*x^15*y^15+13168*x^14*y^15+" "13683*x^13*y^15+4036*x^12*y^15+20263*x^11*y^15+31133*x^10*y^15+26193*x^9*y^15+" "6801*x^8*y^15+11653*x^7*y^15+9040*x^6*y^15+36600*x^5*y^15+946*x^4*y^15+4003*x^3*" "y^15+9589*x^2*y^15+412*x*y^15+2699*y^15+5480*x^14*y^14+11828*x^13*y^14+10150*x^" "12*y^14+26355*x^11*y^14+10819*x^10*y^14+35113*x^9*y^14+15186*x^8*y^14+20558*x^7*" "y^14+19722*x^6*y^14+40367*x^5*y^14+5224*x^4*y^14+1701*x^3*y^14+38742*x^2*y^14+" "13350*x*y^14+265*y^14+34787*x^13*y^13+23544*x^12*y^13+31722*x^11*y^13+14630*x^10" "*y^13+30193*x^9*y^13+34518*x^8*y^13+37652*x^7*y^13+8454*x^6*y^13+23095*x^5*y^13+" "40459*x^4*y^13+19841*x^3*y^13+20398*x^2*y^13+33334*x*y^13+41152*y^13+29967*x^12*" "y^12+9540*x^11*y^12+36229*x^10*y^12+1670*x^9*y^12+21738*x^8*y^12+744*x^7*y^12+" "40820*x^6*y^12+6388*x^5*y^12+14649*x^4*y^12+27675*x^3*y^12+23094*x^2*y^12+15691*" "x*y^12+4379*y^12+6842*x^11*y^11+42560*x^10*y^11+31197*x^9*y^11+34010*x^8*y^11+" "25953*x^7*y^11+32134*x^6*y^11+33154*x^5*y^11+27110*x^4*y^11+17143*x^3*y^11+20511" "*x^2*y^11+38503*x*y^11+17850*y^11+4599*x^10*y^10+22849*x^9*y^10+25896*x^8*y^10+" "25981*x^7*y^10+13940*x^6*y^10+34610*x^5*y^10+20111*x^4*y^10+37706*x^3*y^10+39941" "*x^2*y^10+22020*x*y^10+30878*y^10+42108*x^9*y^9+39357*x^8*y^9+5802*x^7*y^9+11442" "*x^6*y^9+22956*x^5*y^9+13392*x^4*y^9+10615*x^3*y^9+9505*x^2*y^9+2863*x*y^9+33798" "*y^9+5939*x^8*y^8+36618*x^7*y^8+13200*x^6*y^8+8689*x^5*y^8+518*x^4*y^8+4026*x^3*" "y^8+16640*x^2*y^8+39860*x*y^8+32154*y^8+11496*x^7*y^7+3970*x^6*y^7+16147*x^5*y^7" "+42885*x^4*y^7+22064*x^3*y^7+32153*x^2*y^7+39290*x*y^7+37882*y^7+20742*x^6*y^6+" "16687*x^5*y^6+1890*x^4*y^6+38545*x^3*y^6+35135*x^2*y^6+16921*x*y^6+42898*y^6+" "40861*x^5*y^5+16687*x^4*y^5+22548*x^3*y^5+9752*x^2*y^5+9003*x*y^5+14580*y^5+" "18136*x^4*y^4+21446*x^3*y^4+12391*x^2*y^4+29220*x*y^4+13920*y^4+4960*x^3*y^3+" "2851*x^2*y^3+1789*x*y^3+33655*y^3+28567*x^2*y^2+24794*x*y^2+19511*y^2+25676*x*y+" "8828*y+18760)*(y^55+x*y+x^55)*(y+11888*x)*(y+31162*x)*(y^2+11695*x*y+43050*x^2)*" "(y^2+x^2)*(y^2+31356*x*y+43050*x^2)*(y^27+x^55)*(y+x)^2", vars, ctx); time = check_omega(16, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } flint_printf("total_time: %wd\n", total_time); flint_printf("\n------ characteristic 2 ------\n"); total_time = 0; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a; const char * vars[] = {"x","y","z","u","v","w","s","t"}; nmod_mpoly_ctx_init(ctx, 8, ORD_LEX, 2); nmod_mpoly_init(a, ctx); flint_printf(" #1: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^2*x^2*y^12*s^8+z^2*x^3*y^11*s^8+z^3*x^2*y^11*s^8+z^2*x^4*y^10*s^8+z^4*x^2*y^10*s^8+z^2*x^5*y^9*s^8+z^3*x^4*y^9*s^8+z^4*x^3*y^9*s^8+z^5*x^2*y^9*s^8+z^8*x^11*y^7*s^2+z^8*x^8*y^7*s^2+z^8*x^12*y^6*s^2+z^9*x^11*y^6*s^2+z^8*x^9*y^6*s^2+z^9*x^8*y^6*s^2+z^8*x^13*y^5*s^2+z^10*x^11*y^5*s^2+z^8*x^10*y^5*s^2+z^10*x^8*y^5*s^2+z^8*x^14*y^4*s^2+z^9*x^13*y^4*s^2+z^10*x^12*y^4*s^2+z^11*x^11*y^4*s^2+z^8*x^11*y^4*s^2+z^9*x^10*y^4*s^2+z^10*x^9*y^4*s^2+z^11*x^8*y^4*s^2+z^8*x^3*y^6+z^8*x^4*y^5+z^9*x^3*y^5+z^8*x^5*y^4+z^10*x^3*y^4+z^8*x^6*y^3+z^9*x^5*y^3+z^10*x^4*y^3+z^11*x^3*y^3)*(z^3*x^3*y^4*s^5+z^3*x*y^3*s^5+z^5*x^2*y^3*s^4+z^3*x^4*s^2+z^2*x^3*y^4*s+y)", vars, ctx); time = check_omega(12, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #2: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^9*x^7*y^14*s^11+z^9*x^8*y^13*s^11+z^10*x^7*y^13*s^11+z^9*x^9*y^12*s^11+z^11*x^7*y^12*s^11+z^9*x^10*y^11*s^11+z^10*x^9*y^11*s^11+z^11*x^8*y^11*s^11+z^12*x^7*y^11*s^11+z^3*x^10*y^4*s^11+z^3*x^11*y^3*s^11+z^4*x^10*y^3*s^11+z^3*x^12*y^2*s^11+z^5*x^10*y^2*s^11+z^3*x^13*y*s^11+z^4*x^12*y*s^11+z^5*x^11*y*s^11+z^6*x^10*y*s^11+z^6*x^5*y^7*s^9+z^6*x^6*y^6*s^9+z^7*x^5*y^6*s^9+z^6*x^7*y^5*s^9+z^8*x^5*y^5*s^9+z^6*x^8*y^4*s^9+z^7*x^7*y^4*s^9+z^8*x^6*y^4*s^9+z^9*x^5*y^4*s^9+z^11*x^13*y^4*s^3+z^11*x^14*y^3*s^3+z^12*x^13*y^3*s^3+z^11*x^15*y^2*s^3+z^13*x^13*y^2*s^3+z^11*x^16*y*s^3+z^12*x^15*y*s^3+z^13*x^14*y*s^3+z^14*x^13*y*s^3+z^5*x^6*y^15*s^2+z^5*x^7*y^14*s^2+z^6*x^6*y^14*s^2+z^5*x^8*y^13*s^2+z^7*x^6*y^13*s^2+z^5*x^9*y^12*s^2+z^6*x^8*y^12*s^2+z^7*x^7*y^12*s^2+z^8*x^6*y^12*s^2)*(z^3*y^5*s^6+z*x^5*y*s^5+z^3*y^6*s^4+z^2*x*y*s^4+z^5*x^2*s^3+z*y^5*s^2+z^3*x^3*y^2*s^2)", vars, ctx); time = check_omega(19, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #3: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z*x^3*y^5*s^5+z^4*x^4*y^5*s^4+y*s^4+z*x^4*y^3*s^3+z^3*x*y^3*s+z^3*y*s)*(z^3*x^4*y^12*s^11+z^3*x^5*y^11*s^11+z^4*x^4*y^11*s^11+z^3*x^6*y^10*s^11+z^5*x^4*y^10*s^11+z^3*x^7*y^9*s^11+z^4*x^6*y^9*s^11+z^5*x^5*y^9*s^11+z^6*x^4*y^9*s^11+z^7*x^5*y^13*s^9+z^7*x^6*y^12*s^9+z^8*x^5*y^12*s^9+z^7*x^7*y^11*s^9+z^9*x^5*y^11*s^9+z^7*x^8*y^10*s^9+z^8*x^7*y^10*s^9+z^9*x^6*y^10*s^9+z^10*x^5*y^10*s^9+z^4*x^9*y^12+z^2*x^8*y^12+z^4*x^10*y^11+z^5*x^9*y^11+z^2*x^9*y^11+z^3*x^8*y^11+z^4*x^11*y^10+z^2*x^10*y^10+z^6*x^9*y^10+z^4*x^8*y^10+z^4*x^12*y^9+z^5*x^11*y^9+z^2*x^11*y^9+z^6*x^10*y^9+z^3*x^10*y^9+z^7*x^9*y^9+z^4*x^9*y^9+z^5*x^8*y^9)", vars, ctx); time = check_omega(22, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #4: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^9*x^9*y^17*s^16+z^9*x^10*y^16*s^16+z^10*x^9*y^16*s^16+z^9*x^11*y^15*s^16+z^11*x^9*y^15*s^16+z^9*x^12*y^14*s^16+z^10*x^11*y^14*s^16+z^11*x^10*y^14*s^16+z^12*x^9*y^14*s^16+z^15*x^16*y^7*s^15+z^15*x^17*y^6*s^15+z^16*x^16*y^6*s^15+z^15*x^18*y^5*s^15+z^17*x^16*y^5*s^15+z^15*x^19*y^4*s^15+z^16*x^18*y^4*s^15+z^17*x^17*y^4*s^15+z^18*x^16*y^4*s^15+z^14*x^12*y^12*s^12+z^14*x^13*y^11*s^12+z^15*x^12*y^11*s^12+z^14*x^14*y^10*s^12+z^16*x^12*y^10*s^12+z^14*x^15*y^9*s^12+z^15*x^14*y^9*s^12+z^16*x^13*y^9*s^12+z^17*x^12*y^9*s^12+z^16*x^12*y^20*s^11+z^16*x^13*y^19*s^11+z^17*x^12*y^19*s^11+z^16*x^14*y^18*s^11+z^18*x^12*y^18*s^11+z^16*x^15*y^17*s^11+z^17*x^14*y^17*s^11+z^18*x^13*y^17*s^11+z^19*x^12*y^17*s^11+z^7*x^7*y^18*s^6+z^7*x^8*y^17*s^6+z^8*x^7*y^17*s^6+z^7*x^9*y^16*s^6+z^9*x^7*y^16*s^6+z^7*x^10*y^15*s^6+z^8*x^9*y^15*s^6+z^9*x^8*y^15*s^6+z^10*x^7*y^15*s^6+x^8*y^18*s^2+x^9*y^17*s^2+z*x^8*y^17*s^2+x^10*y^16*s^2+z^2*x^8*y^16*s^2+x^11*y^15*s^2+z*x^10*y^15*s^2+z^2*x^9*y^15*s^2+z^3*x^8*y^15*s^2)*(z^4*x^8*y^5*s^7+z^7*x^5*s^7+z^4*x^3*y^4*s^4+z^6*x*y^5*s^3+z^7*y^8*s+x^5*y^5*s+z^7*x^6*y^2*s)", vars, ctx); time = check_omega(19, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #5: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z*x^4*y*s^4+z^3*x^3*y*s^3+z*x^3*y*s^2+z*y*s+z^3*y^3)*(z^9*x^9*y^10*s^7+z^9*x^10*y^9*s^7+z^10*x^9*y^9*s^7+z^9*x^11*y^8*s^7+z^11*x^9*y^8*s^7+z^9*x^12*y^7*s^7+z^10*x^11*y^7*s^7+z^11*x^10*y^7*s^7+z^12*x^9*y^7*s^7+z*x^6*y^4*s^6+z*x^7*y^3*s^6+z^2*x^6*y^3*s^6+z*x^8*y^2*s^6+z^3*x^6*y^2*s^6+z*x^9*y*s^6+z^2*x^8*y*s^6+z^3*x^7*y*s^6+z^4*x^6*y*s^6+z^5*x^9*y^9*s^5+z^5*x^10*y^8*s^5+z^6*x^9*y^8*s^5+z^5*x^11*y^7*s^5+z^7*x^9*y^7*s^5+z^5*x^12*y^6*s^5+z^6*x^11*y^6*s^5+z^7*x^10*y^6*s^5+z^8*x^9*y^6*s^5)", vars, ctx); time = check_omega(20, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #6: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "z^3*x^6*y^7*s^5+z^3*x^7*y^6*s^5+z^4*x^6*y^6*s^5+z^3*x^8*y^5*s^5+z^5*x^6*y^5*s^5+z^5*x^5*y^5*s^5+z^3*x^9*y^4*s^5+z^4*x^8*y^4*s^5+z^5*x^7*y^4*s^5+z^6*x^6*y^4*s^5+z^5*x^6*y^4*s^5+z^6*x^5*y^4*s^5+z^5*x^7*y^3*s^5+z^7*x^5*y^3*s^5+z^5*x^8*y^2*s^5+z^6*x^7*y^2*s^5+z^7*x^6*y^2*s^5+z^8*x^5*y^2*s^5+x^4*y^9*s^4+x^5*y^8*s^4+z*x^4*y^8*s^4+x^6*y^7*s^4+z^5*x^4*y^7*s^4+z^2*x^4*y^7*s^4+z^2*x^3*y^7*s^4+x^7*y^6*s^4+z*x^6*y^6*s^4+z^5*x^5*y^6*s^4+z^2*x^5*y^6*s^4+z^6*x^4*y^6*s^4+z^3*x^4*y^6*s^4+z^2*x^4*y^6*s^4+z^3*x^3*y^6*s^4+z^5*x^6*y^5*s^4+z^2*x^5*y^5*s^4+z^7*x^4*y^5*s^4+z^4*x^3*y^5*s^4+z^5*x^7*y^4*s^4+z^6*x^6*y^4*s^4+z^2*x^6*y^4*s^4+z^7*x^5*y^4*s^4+z^3*x^5*y^4*s^4+z^8*x^4*y^4*s^4+z^4*x^4*y^4*s^4+z^5*x^3*y^4*s^4+z^2*x^2*y^9*s^3+z^2*x^3*y^8*s^3+z^3*x^2*y^8*s^3+z^2*x^4*y^7*s^3+z^4*x^2*y^7*s^3+z^2*x^5*y^6*s^3+z^3*x^4*y^6*s^3+z^4*x^3*y^6*s^3+z^5*x^2*y^6*s^3", vars, ctx); time = check_omega(12, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #7: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^5*x^3*y^6*s^8+z^4*y^8*s^6+z^3*x^8*y^5*s^6+z^5*x^4*y^7*s^4+z^2*x^4*y^8*s^3+z^3*x^3*y^6*s^3+z^7*y^7*s)*(z^10*x^7*y^9*s^16+z^10*x^8*y^8*s^16+z^11*x^7*y^8*s^16+z^10*x^9*y^7*s^16+z^12*x^7*y^7*s^16+z^10*x^10*y^6*s^16+z^11*x^9*y^6*s^16+z^12*x^8*y^6*s^16+z^13*x^7*y^6*s^16+z*x^15*y^6*s^11+z*x^16*y^5*s^11+z^2*x^15*y^5*s^11+z*x^17*y^4*s^11+z^3*x^15*y^4*s^11+z*x^18*y^3*s^11+z^2*x^17*y^3*s^11+z^3*x^16*y^3*s^11+z^4*x^15*y^3*s^11+z^5*x^2*y^11*s^9+z^5*x^3*y^10*s^9+z^6*x^2*y^10*s^9+z^5*x^4*y^9*s^9+z^7*x^2*y^9*s^9+z^5*x^5*y^8*s^9+z^6*x^4*y^8*s^9+z^7*x^3*y^8*s^9+z^8*x^2*y^8*s^9+z^4*x^15*y^15*s^8+z^15*x^6*y^15*s^8+z^4*x^16*y^14*s^8+z^5*x^15*y^14*s^8+z^15*x^7*y^14*s^8+z^16*x^6*y^14*s^8+z^4*x^17*y^13*s^8+z^6*x^15*y^13*s^8+z^15*x^8*y^13*s^8+z^17*x^6*y^13*s^8+z^4*x^18*y^12*s^8+z^5*x^17*y^12*s^8+z^6*x^16*y^12*s^8+z^7*x^15*y^12*s^8+z^15*x^9*y^12*s^8+z^16*x^8*y^12*s^8+z^17*x^7*y^12*s^8+z^18*x^6*y^12*s^8+z^9*x^17*y^5*s^7+z^9*x^18*y^4*s^7+z^10*x^17*y^4*s^7+z^11*x^14*y^4*s^7+z^9*x^19*y^3*s^7+z^11*x^17*y^3*s^7+z^11*x^15*y^3*s^7+z^12*x^14*y^3*s^7+z^9*x^20*y^2*s^7+z^10*x^19*y^2*s^7+z^11*x^18*y^2*s^7+z^12*x^17*y^2*s^7+z^11*x^16*y^2*s^7+z^13*x^14*y^2*s^7+z^11*x^17*y*s^7+z^12*x^16*y*s^7+z^13*x^15*y*s^7+z^14*x^14*y*s^7)", vars, ctx); time = check_omega(24, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #8: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "z^5*x*y^8*s^5+z^5*x^2*y^7*s^5+z^6*x*y^7*s^5+z^5*x^3*y^6*s^5+z^7*x*y^6*s^5+z^5*x^4*y^5*s^5+z^6*x^3*y^5*s^5+z^7*x^2*y^5*s^5+z^8*x*y^5*s^5+z^4*x^2*y^6*s^4+z^4*x^3*y^5*s^4+z^5*x^2*y^5*s^4+z^4*x^4*y^4*s^4+z^6*x^2*y^4*s^4+z^4*x^5*y^3*s^4+z^5*x^4*y^3*s^4+z^6*x^3*y^3*s^4+z^7*x^2*y^3*s^4+z^4*x^3*y^6*s^3+z^4*x^4*y^5*s^3+z^5*x^3*y^5*s^3+z^4*x^5*y^4*s^3+z^6*x^3*y^4*s^3+z^4*x^6*y^3*s^3+z^5*x^5*y^3*s^3+z^6*x^4*y^3*s^3+z^7*x^3*y^3*s^3+z^2*x^4*y^9*s^2+z^2*x^5*y^8*s^2+z^3*x^4*y^8*s^2+z^2*x^6*y^7*s^2+z^4*x^4*y^7*s^2+z^2*x^7*y^6*s^2+z^3*x^6*y^6*s^2+z^4*x^5*y^6*s^2+z^5*x^4*y^6*s^2+z*x^5*y^7*s+z*x^6*y^6*s+z^2*x^5*y^6*s+z*x^7*y^5*s+z^3*x^5*y^5*s+z*x^8*y^4*s+z^2*x^7*y^4*s+z^3*x^6*y^4*s+z^4*x^5*y^4*s+z*x^6*y^7+z*x^7*y^6+z^2*x^6*y^6+z*x^8*y^5+z^3*x^6*y^5+z*x^9*y^4+z^2*x^8*y^4+z^3*x^7*y^4+z^4*x^6*y^4", vars, ctx); time = check_omega(10, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf(" #9: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^5*x*y^10*s^9+z^5*x^2*y^9*s^9+z^6*x*y^9*s^9+z^5*x^3*y^8*s^9+z^7*x*y^8*s^9+z^5*x^4*y^7*s^9+z^6*x^3*y^7*s^9+z^7*x^2*y^7*s^9+z^8*x*y^7*s^9+z^9*x^8*y^15*s^7+z^9*x^9*y^14*s^7+z^10*x^8*y^14*s^7+z^9*x^10*y^13*s^7+z^11*x^8*y^13*s^7+z^9*x^11*y^12*s^7+z^10*x^10*y^12*s^7+z^11*x^9*y^12*s^7+z^12*x^8*y^12*s^7+x^6*y^6*s^3+x^7*y^5*s^3+z*x^6*y^5*s^3+x^8*y^4*s^3+z^2*x^6*y^4*s^3+x^9*y^3*s^3+z*x^8*y^3*s^3+z^2*x^7*y^3*s^3+z^3*x^6*y^3*s^3+z^4*x^10*y^14+z^4*x^11*y^13+z^5*x^10*y^13+z^4*x^12*y^12+z^6*x^10*y^12+z^4*x^13*y^11+z^5*x^12*y^11+z^6*x^11*y^11+z^7*x^10*y^11)*(z^3*x^3*y^4*s^5+z^5*x^4*y*s^4+z^4*x^2*y*s^4+z^5*x^5*y^2*s+z^4*x^3*s+x*y^2)", vars, ctx); time = check_omega(10, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#10: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "z^7*x^2*y^10*s^6+z^7*x^3*y^9*s^6+z^8*x^2*y^9*s^6+z^7*x^4*y^8*s^6+z^9*x^2*y^8*s^6+z^7*x^5*y^7*s^6+z^8*x^4*y^7*s^6+z^9*x^3*y^7*s^6+z^10*x^2*y^7*s^6+z^5*x^3*y^10*s^4+z^7*x^2*y^10*s^4+z^5*x^4*y^9*s^4+z^7*x^3*y^9*s^4+z^6*x^3*y^9*s^4+z^8*x^2*y^9*s^4+z^5*x^5*y^8*s^4+z^7*x^4*y^8*s^4+z^7*x^3*y^8*s^4+z^9*x^2*y^8*s^4+z^5*x^6*y^7*s^4+z^7*x^5*y^7*s^4+z^6*x^5*y^7*s^4+z^8*x^4*y^7*s^4+z^7*x^4*y^7*s^4+z^9*x^3*y^7*s^4+z^8*x^3*y^7*s^4+z^10*x^2*y^7*s^4+z^3*x^5*y^10*s^2+z^3*x^6*y^9*s^2+z^4*x^5*y^9*s^2+z^3*x^7*y^8*s^2+z^5*x^5*y^8*s^2+z^3*x^8*y^7*s^2+z^4*x^7*y^7*s^2+z^5*x^6*y^7*s^2+z^6*x^5*y^7*s^2+z*x^6*y^10+z^3*x^5*y^10+z*x^7*y^9+z^3*x^6*y^9+z^2*x^6*y^9+z^4*x^5*y^9+z*x^8*y^8+z^3*x^7*y^8+z^3*x^6*y^8+z^5*x^5*y^8+z*x^9*y^7+z^3*x^8*y^7+z^2*x^8*y^7+z^4*x^7*y^7+z^3*x^7*y^7+z^5*x^6*y^7+z^4*x^6*y^7+z^6*x^5*y^7", vars, ctx); time = check_omega(15, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#11: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^2*x^4*y^13*s^10+z^2*x^5*y^12*s^10+z^3*x^4*y^12*s^10+z^2*x^6*y^11*s^10+z^4*x^4*y^11*s^10+z^2*x^7*y^10*s^10+z^3*x^6*y^10*s^10+z^4*x^5*y^10*s^10+z^5*x^4*y^10*s^10+z^2*x^7*y^6*s^10+z^2*x^8*y^5*s^10+z^3*x^7*y^5*s^10+z^3*x^10*y^4*s^10+z^2*x^9*y^4*s^10+z^4*x^7*y^4*s^10+z^3*x^11*y^3*s^10+z^4*x^10*y^3*s^10+z^2*x^10*y^3*s^10+z^3*x^9*y^3*s^10+z^4*x^8*y^3*s^10+z^5*x^7*y^3*s^10+z^3*x^12*y^2*s^10+z^5*x^10*y^2*s^10+z^3*x^13*y*s^10+z^4*x^12*y*s^10+z^5*x^11*y*s^10+z^6*x^10*y*s^10)*(z^5*y^2*s^4+x^5*y^3*s^3+x^2*s^2+z^4*x*y^3+z^5*x^5*y^2)", vars, ctx); time = check_omega(22, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#12: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "z^5*x*y^5*s^3+z^5*x^2*y^4*s^3+z^6*x*y^4*s^3+z^5*x^3*y^3*s^3+z^7*x*y^3*s^3+z^5*x^4*y^2*s^3+z^6*x^3*y^2*s^3+z^7*x^2*y^2*s^3+z^8*x*y^2*s^3+z^7*x^4*y^10*s^2+z^7*x^5*y^9*s^2+z^8*x^4*y^9*s^2+z^7*x^6*y^8*s^2+z^9*x^4*y^8*s^2+z^7*x^7*y^7*s^2+z^8*x^6*y^7*s^2+z^9*x^5*y^7*s^2+z^10*x^4*y^7*s^2+z^3*x^3*y^6*s^2+z^4*x^2*y^6*s^2+z^3*x^4*y^5*s^2+z^5*x^2*y^5*s^2+z^3*x^5*y^4*s^2+z^4*x^4*y^4*s^2+z^5*x^3*y^4*s^2+z^6*x^2*y^4*s^2+z^3*x^6*y^3*s^2+z^7*x^2*y^3*s^2+z^5*x^6*y^11*s+z^6*x^5*y^11*s+z^5*x^7*y^10*s+z^7*x^5*y^10*s+z^5*x^8*y^9*s+z^6*x^7*y^9*s+z^7*x^6*y^9*s+z^8*x^5*y^9*s+z^5*x^9*y^8*s+z^9*x^5*y^8*s", vars, ctx); time = check_omega(12, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#13: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "z^5*x^7*y^7*s^5+z^5*x^8*y^6*s^5+z^6*x^7*y^6*s^5+z^5*x^9*y^5*s^5+z^7*x^7*y^5*s^5+z^4*x^6*y^5*s^5+z^5*x^10*y^4*s^5+z^6*x^9*y^4*s^5+z^7*x^8*y^4*s^5+z^8*x^7*y^4*s^5+z^4*x^7*y^4*s^5+z^5*x^6*y^4*s^5+z^4*x^8*y^3*s^5+z^6*x^6*y^3*s^5+z^4*x^9*y^2*s^5+z^5*x^8*y^2*s^5+z^6*x^7*y^2*s^5+z^7*x^6*y^2*s^5+z^4*x^7*y^7*s^3+z^4*x^8*y^6*s^3+z^5*x^7*y^6*s^3+z^4*x^9*y^5*s^3+z^6*x^7*y^5*s^3+z^4*x^10*y^4*s^3+z^5*x^9*y^4*s^3+z^6*x^8*y^4*s^3+z^7*x^7*y^4*s^3+z^3*x^3*y^11*s^2+z^3*x^4*y^10*s^2+z^4*x^3*y^10*s^2+z^3*x^5*y^9*s^2+z^5*x^3*y^9*s^2+z^2*x^2*y^9*s^2+z^3*x^6*y^8*s^2+z^4*x^5*y^8*s^2+z^5*x^4*y^8*s^2+z^6*x^3*y^8*s^2+z^2*x^3*y^8*s^2+z^3*x^2*y^8*s^2+z^2*x^4*y^7*s^2+z^4*x^2*y^7*s^2+z^2*x^5*y^6*s^2+z^3*x^4*y^6*s^2+z^4*x^3*y^6*s^2+z^5*x^2*y^6*s^2+z^2*x^3*y^11+z^2*x^4*y^10+z^3*x^3*y^10+z^2*x^5*y^9+z^4*x^3*y^9+z^2*x^6*y^8+z^3*x^5*y^8+z^4*x^4*y^8+z^5*x^3*y^8", vars, ctx); time = check_omega(11, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#14: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(x^9*y^4*s^8+z^9*x^6*y^4*s^8+x^10*y^3*s^8+z*x^9*y^3*s^8+z^9*x^7*y^3*s^8+z^10*x^6*y^3*s^8+x^11*y^2*s^8+z^2*x^9*y^2*s^8+z^9*x^8*y^2*s^8+z^11*x^6*y^2*s^8+x^12*y*s^8+z*x^11*y*s^8+z^2*x^10*y*s^8+z^9*x^9*y*s^8+z^3*x^9*y*s^8+z^10*x^8*y*s^8+z^11*x^7*y*s^8+z^12*x^6*y*s^8+z*x^2*y^13*s+z*x^3*y^12*s+z^2*x^2*y^12*s+z*x^4*y^11*s+z^6*x^3*y^11*s+z^3*x^2*y^11*s+z*x^5*y^10*s+z^6*x^4*y^10*s+z^2*x^4*y^10*s+z^7*x^3*y^10*s+z^3*x^3*y^10*s+z^4*x^2*y^10*s+z^6*x^5*y^9*s+z^8*x^3*y^9*s+z^6*x^6*y^8*s+z^7*x^5*y^8*s+z^8*x^4*y^8*s+z^9*x^3*y^8*s)*(z^4*x^5*y*s^5+z^2*y*s^5+z^5*x^4*s^5+y^2*s^3+x^2*y^4*s^2+z^4*x^5*y^5)", vars, ctx); time = check_omega(9, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#15: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "z^7*x^8*y^7*s^3+z^7*x^9*y^6*s^3+z^8*x^8*y^6*s^3+z^9*x^7*y^6*s^3+z^7*x^10*y^5*s^3+z^10*x^7*y^5*s^3+z^7*x^11*y^4*s^3+z^8*x^10*y^4*s^3+z^10*x^8*y^4*s^3+z^11*x^7*y^4*s^3+z^9*x^10*y^3*s^3+z^10*x^9*y^3*s^3+z^11*x^8*y^3*s^3+z^12*x^7*y^3*s^3+z^8*x^8*y^8*s+z^8*x^9*y^7*s+z^9*x^8*y^7*s+z^10*x^7*y^7*s+z^6*x^11*y^6*s+z^8*x^10*y^6*s+z^11*x^7*y^6*s+z^6*x^12*y^5*s+z^8*x^11*y^5*s+z^7*x^11*y^5*s+z^9*x^10*y^5*s+z^8*x^10*y^5*s+z^11*x^8*y^5*s+z^12*x^7*y^5*s+z^6*x^13*y^4*s+z^10*x^10*y^4*s+z^9*x^10*y^4*s+z^11*x^9*y^4*s+z^12*x^8*y^4*s+z^13*x^7*y^4*s+z^6*x^14*y^3*s+z^7*x^13*y^3*s+z^9*x^11*y^3*s+z^10*x^10*y^3*s+z^8*x^13*y^2*s+z^9*x^12*y^2*s+z^10*x^11*y^2*s+z^11*x^10*y^2*s", vars, ctx); time = check_omega(21, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#16: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^5*x^2*y^6*s^6+z^4*x^2*y*s^5+z^6*x^3*y^6*s^4+z*y^5*s^4+z*x^5*y^4*s^3+x^4*y*s^2+z^6*x^3*y^6*s)*(z^13*x^5*y^14*s^9+z^13*x^6*y^13*s^9+z^14*x^5*y^13*s^9+z^13*x^7*y^12*s^9+z^15*x^5*y^12*s^9+z^13*x^8*y^11*s^9+z^14*x^7*y^11*s^9+z^15*x^6*y^11*s^9+z^16*x^5*y^11*s^9+z^9*x^10*y^7*s^7+z^9*x^11*y^6*s^7+z^10*x^10*y^6*s^7+z^9*x^12*y^5*s^7+z^11*x^10*y^5*s^7+z^9*x^13*y^4*s^7+z^10*x^12*y^4*s^7+z^11*x^11*y^4*s^7+z^12*x^10*y^4*s^7+x^5*y^8*s^6+x^6*y^7*s^6+z*x^5*y^7*s^6+x^7*y^6*s^6+z^2*x^5*y^6*s^6+x^8*y^5*s^6+z*x^7*y^5*s^6+z^2*x^6*y^5*s^6+z^3*x^5*y^5*s^6+z^7*x^13*y^16*s^2+z^7*x^14*y^15*s^2+z^8*x^13*y^15*s^2+z^7*x^15*y^14*s^2+z^9*x^13*y^14*s^2+z^7*x^16*y^13*s^2+z^8*x^15*y^13*s^2+z^9*x^14*y^13*s^2+z^10*x^13*y^13*s^2+z^6*x^13*y^10+z^6*x^14*y^9+z^7*x^13*y^9+z^6*x^15*y^8+z^8*x^13*y^8+z^6*x^16*y^7+z^7*x^15*y^7+z^8*x^14*y^7+z^9*x^13*y^7)", vars, ctx); time = check_omega(16, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#17: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^14*x^5*y^18*s^13+z^14*x^6*y^17*s^13+z^15*x^5*y^17*s^13+z^14*x^7*y^16*s^13+z^16*x^5*y^16*s^13+z^14*x^8*y^15*s^13+z^15*x^7*y^15*s^13+z^16*x^6*y^15*s^13+z^17*x^5*y^15*s^13+x*y^18*s^12+x^2*y^17*s^12+z*x*y^17*s^12+x^3*y^16*s^12+z^2*x*y^16*s^12+x^4*y^15*s^12+z*x^3*y^15*s^12+z^2*x^2*y^15*s^12+z^3*x*y^15*s^12+z*x^10*y^14*s^12+z*x^11*y^13*s^12+z^2*x^10*y^13*s^12+z*x^12*y^12*s^12+z^3*x^10*y^12*s^12+z*x^13*y^11*s^12+z^2*x^12*y^11*s^12+z^3*x^11*y^11*s^12+z^4*x^10*y^11*s^12+z^10*x^4*y^13*s^11+z^10*x^5*y^12*s^11+z^11*x^4*y^12*s^11+z^10*x^6*y^11*s^11+z^12*x^4*y^11*s^11+z^10*x^7*y^10*s^11+z^11*x^6*y^10*s^11+z^12*x^5*y^10*s^11+z^13*x^4*y^10*s^11+z^7*x^2*y^4*s^11+z^7*x^3*y^3*s^11+z^8*x^2*y^3*s^11+z^7*x^4*y^2*s^11+z^9*x^2*y^2*s^11+z^7*x^5*y*s^11+z^8*x^4*y*s^11+z^9*x^3*y*s^11+z^10*x^2*y*s^11+z^4*x^2*y^7*s^6+z^4*x^3*y^6*s^6+z^5*x^2*y^6*s^6+z^4*x^4*y^5*s^6+z^6*x^2*y^5*s^6+z^4*x^5*y^4*s^6+z^5*x^4*y^4*s^6+z^6*x^3*y^4*s^6+z^7*x^2*y^4*s^6)*(z^4*x^2*y^6*s^7+z^5*x^5*y^5*s^7+z^6*x^4*y^3*s^5+z^5*x^6*y^5*s^4+z^7*x^4*s^3+z^4*x*y^2*s+z^2*x^4)", vars, ctx); time = check_omega(16, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#18: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^4*x^2*y^10*s^9+z^4*x^3*y^9*s^9+1*x^3*y^9*s^9+z^5*x^2*y^9*s^9+z^4*x^4*y^8*s^9+1*x^4*y^8*s^9+z*x^3*y^8*s^9+z^6*x^2*y^8*s^9+z^4*x^5*y^7*s^9+1*x^5*y^7*s^9+z^5*x^4*y^7*s^9+z^6*x^3*y^7*s^9+z^2*x^3*y^7*s^9+z^7*x^2*y^7*s^9+x^6*y^6*s^9+z*x^5*y^6*s^9+z^2*x^4*y^6*s^9+z^3*x^3*y^6*s^9+z^8*x^7*y^5*s^8+z^8*x^8*y^4*s^8+z^9*x^7*y^4*s^8+z^8*x^9*y^3*s^8+z^10*x^7*y^3*s^8+z^8*x^10*y^2*s^8+z^9*x^9*y^2*s^8+z^10*x^8*y^2*s^8+z^11*x^7*y^2*s^8+z^7*x^3*y^7*s^3+z^7*x^4*y^6*s^3+z^8*x^3*y^6*s^3+z^7*x^5*y^5*s^3+z^9*x^3*y^5*s^3+z^7*x^6*y^4*s^3+z^8*x^5*y^4*s^3+z^9*x^4*y^4*s^3+z^10*x^3*y^4*s^3)*(x^5*y^5*s^4+z*y^4*s^4+x*y^2*s^4+z^2*x^4*s^4+z^3*x^2*y^2*s+z^5*y)", vars, ctx); time = check_omega(12, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#19: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^7*x^13*y^17*s^16+z^7*x^14*y^16*s^16+z^8*x^13*y^16*s^16+z^7*x^15*y^15*s^16+z^9*x^13*y^15*s^16+z^7*x^16*y^14*s^16+z^8*x^15*y^14*s^16+z^9*x^14*y^14*s^16+z^10*x^13*y^14*s^16+z^3*x^4*y^17*s^14+z^3*x^5*y^16*s^14+z^4*x^4*y^16*s^14+z^3*x^6*y^15*s^14+z^5*x^4*y^15*s^14+z^3*x^7*y^14*s^14+z^4*x^6*y^14*s^14+z^5*x^5*y^14*s^14+z^6*x^4*y^14*s^14+z^8*x^5*y^6*s^13+z^8*x^6*y^5*s^13+z^9*x^5*y^5*s^13+z^8*x^7*y^4*s^13+z^10*x^5*y^4*s^13+z^8*x^8*y^3*s^13+z^9*x^7*y^3*s^13+z^10*x^6*y^3*s^13+z^11*x^5*y^3*s^13+z^6*x^2*y^12*s^8+z^6*x^3*y^11*s^8+z^7*x^2*y^11*s^8+z^6*x^4*y^10*s^8+z^8*x^2*y^10*s^8+z^6*x^5*y^9*s^8+z^7*x^4*y^9*s^8+z^8*x^3*y^9*s^8+z^9*x^2*y^9*s^8+z^5*x*y^5*s^5+z^5*x^2*y^4*s^5+z^6*x*y^4*s^5+z^5*x^3*y^3*s^5+z^7*x*y^3*s^5+z^5*x^4*y^2*s^5+z^6*x^3*y^2*s^5+z^7*x^2*y^2*s^5+z^8*x*y^2*s^5+z^15*x^5*y^8*s+z^15*x^6*y^7*s+z^16*x^5*y^7*s+z^15*x^7*y^6*s+z^17*x^5*y^6*s+z^15*x^8*y^5*s+z^16*x^7*y^5*s+z^17*x^6*y^5*s+z^18*x^5*y^5*s)*(z^3*x^2*y^3*s^7+z^6*x*y^2*s^6+z^7*x^3*y*s^5+z^6*x^5*s^3+z^5*x^3*s^3+z^2*x^4*y^7*s^2+z^3*y^3*s^2)*(z^3*x^3*y^3+z^2*x^3*y^3+z^4*x^2*y^3+z*y^3+z^3*x*y^2+z*x*y^2+z^4*y+x)", vars, ctx); time = check_omega(17, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#20: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^7*x^11*y^17*s^12+z^7*x^12*y^16*s^12+z^8*x^11*y^16*s^12+z^7*x^13*y^15*s^12+z^9*x^11*y^15*s^12+z^7*x^14*y^14*s^12+z^8*x^13*y^14*s^12+z^9*x^12*y^14*s^12+z^10*x^11*y^14*s^12+z^6*x^6*y^17*s^6+z^6*x^7*y^16*s^6+z^7*x^6*y^16*s^6+z^6*x^8*y^15*s^6+z^8*x^6*y^15*s^6+z^6*x^9*y^14*s^6+z^7*x^8*y^14*s^6+z^8*x^7*y^14*s^6+z^9*x^6*y^14*s^6+z^9*x^10*y^10*s^6+z^9*x^11*y^9*s^6+z^10*x^10*y^9*s^6+z^9*x^12*y^8*s^6+z^11*x^10*y^8*s^6+z^9*x^13*y^7*s^6+z^10*x^12*y^7*s^6+z^11*x^11*y^7*s^6+z^12*x^10*y^7*s^6+z^4*x*y^8*s^2+z^4*x^2*y^7*s^2+z^5*x*y^7*s^2+z^4*x^3*y^6*s^2+z^6*x*y^6*s^2+z^4*x^4*y^5*s^2+z^5*x^3*y^5*s^2+z^6*x^2*y^5*s^2+z^7*x*y^5*s^2+z^4*x^9*y^5*s+z^4*x^10*y^4*s+z^5*x^9*y^4*s+z^4*x^11*y^3*s+z^6*x^9*y^3*s+z^4*x^12*y^2*s+z^5*x^11*y^2*s+z^6*x^10*y^2*s+z^7*x^9*y^2*s)*(y^2*s^5+x^3*y^6*s^4+z^6*x^6*y^2*s^4+z^6*x^6*y^6*s^3+z^5*x^2*s^3+z^3*x^6*y^3*s^2+z^6*x^6*y^6*s)*(z^2*x*y^3+z^2*x^3*y+x*y+z^2*y+z^3*x^3+z*x)", vars, ctx); time = check_omega(15, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#21: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^4*x*y^13*s^4*t^9+z^4*x^2*y^12*s^4*t^9+z^5*x*y^12*s^4*t^9+z^4*x^3*y^11*s^4*t^9+z^6*x*y^11*s^4*t^9+z^4*x^4*y^10*s^4*t^9+z^5*x^3*y^10*s^4*t^9+z^6*x^2*y^10*s^4*t^9+z^7*x*y^10*s^4*t^9+x^6*y^13*s^2*t^8+x^7*y^12*s^2*t^8+z*x^6*y^12*s^2*t^8+x^8*y^11*s^2*t^8+z^2*x^6*y^11*s^2*t^8+x^9*y^10*s^2*t^8+z*x^8*y^10*s^2*t^8+z^2*x^7*y^10*s^2*t^8+z^3*x^6*y^10*s^2*t^8+z^2*x^6*y^6*s^2*t^2+z^2*x^7*y^5*s^2*t^2+z^3*x^6*y^5*s^2*t^2+z^2*x^8*y^4*s^2*t^2+z^4*x^6*y^4*s^2*t^2+z^2*x^9*y^3*s^2*t^2+z^3*x^8*y^3*s^2*t^2+z^4*x^7*y^3*s^2*t^2+z^5*x^6*y^3*s^2*t^2)*(x^3*y^2*s^3*u^4+z^4*x*y*s^2*u^4+z*x^4*y*u^2+z*y*u^2+z^4*x^3*y*s^3)*(z^2*x*y^2+y+x+z^2+1)", vars, ctx); time = check_omega(15, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#22: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^2*x^13*y^18*s^10*t^11+z^2*x^14*y^17*s^10*t^11+z^3*x^13*y^17*s^10*t^11+z^2*x^15*y^16*s^10*t^11+z^4*x^13*y^16*s^10*t^11+z^2*x^16*y^15*s^10*t^11+z^3*x^15*y^15*s^10*t^11+z^4*x^14*y^15*s^10*t^11+z^5*x^13*y^15*s^10*t^11+z*x^17*y^5*s^7*t^9+z*x^18*y^4*s^7*t^9+z^2*x^17*y^4*s^7*t^9+z*x^19*y^3*s^7*t^9+z^3*x^17*y^3*s^7*t^9+z*x^20*y^2*s^7*t^9+z^2*x^19*y^2*s^7*t^9+z^3*x^18*y^2*s^7*t^9+z^4*x^17*y^2*s^7*t^9+z^11*x^2*y^16*s^2*t^8+z^11*x^3*y^15*s^2*t^8+z^12*x^2*y^15*s^2*t^8+z^11*x^4*y^14*s^2*t^8+z^13*x^2*y^14*s^2*t^8+z^11*x^5*y^13*s^2*t^8+z^12*x^4*y^13*s^2*t^8+z^13*x^3*y^13*s^2*t^8+z^14*x^2*y^13*s^2*t^8+z^6*x^8*y^15*s^10*t^6+z^6*x^9*y^14*s^10*t^6+z^7*x^8*y^14*s^10*t^6+z^6*x^10*y^13*s^10*t^6+z^8*x^8*y^13*s^10*t^6+z^6*x^11*y^12*s^10*t^6+z^7*x^10*y^12*s^10*t^6+z^8*x^9*y^12*s^10*t^6+z^9*x^8*y^12*s^10*t^6+z^10*x^7*y^14*s*t^4+z^10*x^8*y^13*s*t^4+z^11*x^7*y^13*s*t^4+z^10*x^9*y^12*s*t^4+z^12*x^7*y^12*s*t^4+z^10*x^10*y^11*s*t^4+z^11*x^9*y^11*s*t^4+z^12*x^8*y^11*s*t^4+z^13*x^7*y^11*s*t^4+z^6*x^7*y^4*t+z^6*x^8*y^3*t+z^7*x^7*y^3*t+z^6*x^9*y^2*t+z^8*x^7*y^2*t+z^6*x^10*y*t+z^7*x^9*y*t+z^8*x^8*y*t+z^9*x^7*y*t)*(x^5*y^3*s^7*u^5+z^5*x^2*y*s*u^4+x^4*y^4*s^8*u^3+x*s^6*u+x^6*y^6*s^2*u+z^4*x^3*y^6*s^2*u+z*x*y^7*u)*(z^3*x^3*y^2+z^2*x^2*y^2+z*y^2+z^3*x^3*y+z*y+z^2*x^4+z^3*x^2+1)", vars, ctx); time = check_omega(13, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#23: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^8*x^9*y^17*s^14*t^14+z^8*x^10*y^16*s^14*t^14+z^9*x^9*y^16*s^14*t^14+z^8*x^11*y^15*s^14*t^14+z^10*x^9*y^15*s^14*t^14+z^8*x^12*y^14*s^14*t^14+z^9*x^11*y^14*s^14*t^14+z^10*x^10*y^14*s^14*t^14+z^11*x^9*y^14*s^14*t^14+x^3*y^10*t^10+x^4*y^9*t^10+z*x^3*y^9*t^10+x^5*y^8*t^10+z^2*x^3*y^8*t^10+x^6*y^7*t^10+z*x^5*y^7*t^10+z^2*x^4*y^7*t^10+z^3*x^3*y^7*t^10+z^7*x^10*y^4*s^4*t^9+z^7*x^11*y^3*s^4*t^9+z^8*x^10*y^3*s^4*t^9+z^7*x^12*y^2*s^4*t^9+z^9*x^10*y^2*s^4*t^9+z^7*x^13*y*s^4*t^9+z^8*x^12*y*s^4*t^9+z^9*x^11*y*s^4*t^9+z^10*x^10*y*s^4*t^9+z^14*x^14*y^12*s^11*t^8+z^14*x^15*y^11*s^11*t^8+z^15*x^14*y^11*s^11*t^8+z^14*x^16*y^10*s^11*t^8+z^16*x^14*y^10*s^11*t^8+z^14*x^17*y^9*s^11*t^8+z^15*x^16*y^9*s^11*t^8+z^16*x^15*y^9*s^11*t^8+z^17*x^14*y^9*s^11*t^8+z^6*x^13*y^13*s^13*t^7+z^6*x^14*y^12*s^13*t^7+z^7*x^13*y^12*s^13*t^7+z^6*x^15*y^11*s^13*t^7+z^8*x^13*y^11*s^13*t^7+z^6*x^16*y^10*s^13*t^7+z^7*x^15*y^10*s^13*t^7+z^8*x^14*y^10*s^13*t^7+z^9*x^13*y^10*s^13*t^7+z^15*x^9*y^4*s^3+z^15*x^10*y^3*s^3+z^16*x^9*y^3*s^3+z^15*x^11*y^2*s^3+z^17*x^9*y^2*s^3+z^15*x^12*y*s^3+z^16*x^11*y*s^3+z^17*x^10*y*s^3+z^18*x^9*y*s^3)*(z^6*y^5*s^4*u^7+z^7*x^7*y^3*s^3*u^3+z^7*x^7*y^3*s^7*u^2+z^4*x^3*y^6*s^3*u+z^2*x^4*y^3*s^2*u+z^3*x^7*y*s*u+z^5*x*y^4*u)*(z*x^3*y^2+z^2*y^2+z^2*x*y+z*x*y+1*y+z*x^2+z^2)", vars, ctx); time = check_omega(14, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#24: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^7*x^5*y^14*s^4*t^9+z^7*x^6*y^13*s^4*t^9+z^8*x^5*y^13*s^4*t^9+z^7*x^7*y^12*s^4*t^9+z^9*x^5*y^12*s^4*t^9+z^7*x^8*y^11*s^4*t^9+z^8*x^7*y^11*s^4*t^9+z^9*x^6*y^11*s^4*t^9+z^10*x^5*y^11*s^4*t^9+z^7*x^4*y^14*s^4*t^7+z^7*x^5*y^13*s^4*t^7+z^8*x^4*y^13*s^4*t^7+z^7*x^6*y^12*s^4*t^7+z^9*x^4*y^12*s^4*t^7+z^7*x^7*y^11*s^4*t^7+z^8*x^6*y^11*s^4*t^7+z^9*x^5*y^11*s^4*t^7+z^10*x^4*y^11*s^4*t^7+z^10*x^13*y^10*s^3*t^7+z^10*x^14*y^9*s^3*t^7+z^11*x^13*y^9*s^3*t^7+z^10*x^15*y^8*s^3*t^7+z^12*x^13*y^8*s^3*t^7+z^10*x^16*y^7*s^3*t^7+z^11*x^15*y^7*s^3*t^7+z^12*x^14*y^7*s^3*t^7+z^13*x^13*y^7*s^3*t^7+z^12*x^5*y^13*s^4*t^4+z^12*x^6*y^12*s^4*t^4+z^13*x^5*y^12*s^4*t^4+z^12*x^7*y^11*s^4*t^4+z^14*x^5*y^11*s^4*t^4+z^12*x^8*y^10*s^4*t^4+z^13*x^7*y^10*s^4*t^4+z^14*x^6*y^10*s^4*t^4+z^15*x^5*y^10*s^4*t^4+z^6*x^13*y^12*s^3*t^2+z^6*x^14*y^11*s^3*t^2+z^7*x^13*y^11*s^3*t^2+z^6*x^15*y^10*s^3*t^2+z^8*x^13*y^10*s^3*t^2+z^6*x^16*y^9*s^3*t^2+z^7*x^15*y^9*s^3*t^2+z^8*x^14*y^9*s^3*t^2+z^9*x^13*y^9*s^3*t^2)*(x*y^3*s^5*u^6+z^3*x^2*y^3*s^3*u^4+z^4*x^6*s^5*u^3+z^2*x^6*s^3*u^3+z^6*x^2*y^4*s^6*u^2+z^2*y^5*s^4*u^2+z*y^5*s^6)*(z^2*x^2*y^3+z^3*y^3+x^2*y^2+z^3*x*y^2+z^3*x^2*y+z^3)", vars, ctx); time = check_omega(31, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#25: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^11*x^7*y^9*s^7*t^11+z^11*x^8*y^8*s^7*t^11+z^12*x^7*y^8*s^7*t^11+z^11*x^9*y^7*s^7*t^11+z^13*x^7*y^7*s^7*t^11+z^11*x^10*y^6*s^7*t^11+z^12*x^9*y^6*s^7*t^11+z^13*x^8*y^6*s^7*t^11+z^14*x^7*y^6*s^7*t^11+z^10*x^8*y^12*s^8*t^9+z^10*x^9*y^11*s^8*t^9+z^11*x^8*y^11*s^8*t^9+z^10*x^10*y^10*s^8*t^9+z^12*x^8*y^10*s^8*t^9+z^10*x^11*y^9*s^8*t^9+z^11*x^10*y^9*s^8*t^9+z^12*x^9*y^9*s^8*t^9+z^13*x^8*y^9*s^8*t^9+z^5*x^2*y^7*s^3*t^7+z^5*x^3*y^6*s^3*t^7+z^6*x^2*y^6*s^3*t^7+z^5*x^4*y^5*s^3*t^7+z^7*x^2*y^5*s^3*t^7+z^5*x^5*y^4*s^3*t^7+z^6*x^4*y^4*s^3*t^7+z^7*x^3*y^4*s^3*t^7+z^8*x^2*y^4*s^3*t^7+x^3*y^12*t^5+x^4*y^11*t^5+z*x^3*y^11*t^5+x^5*y^10*t^5+z^2*x^3*y^10*t^5+x^6*y^9*t^5+z*x^5*y^9*t^5+z^2*x^4*y^9*t^5+z^3*x^3*y^9*t^5+z^10*x^4*y^7*s^8*t^4+z^10*x^5*y^6*s^8*t^4+z^11*x^4*y^6*s^8*t^4+z^10*x^6*y^5*s^8*t^4+z^12*x^4*y^5*s^8*t^4+z^10*x^7*y^4*s^8*t^4+z^11*x^6*y^4*s^8*t^4+z^12*x^5*y^4*s^8*t^4+z^13*x^4*y^4*s^8*t^4)*(z^3*y^5*s^3*u^6+z^4*x^2*y^2*s^4*u^5+z^2*x*s^4*u^5+z*y^3*s^2*u^3+z^6*y^5*u^2+x^2*s^3+x^2*y*s^2)*(z^2*y^2+z*x^2*y+z^2*x+1)", vars, ctx); time = check_omega(16, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#26: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^8*x^4*y^6*s^7*t^10+z^8*x^5*y^5*s^7*t^10+z^9*x^4*y^5*s^7*t^10+z^8*x^6*y^4*s^7*t^10+z^10*x^4*y^4*s^7*t^10+z^8*x^7*y^3*s^7*t^10+z^9*x^6*y^3*s^7*t^10+z^10*x^5*y^3*s^7*t^10+z^11*x^4*y^3*s^7*t^10+z^2*x^8*y^14*s^5*t^10+z^2*x^9*y^13*s^5*t^10+z^3*x^8*y^13*s^5*t^10+z^2*x^10*y^12*s^5*t^10+z^4*x^8*y^12*s^5*t^10+z^2*x^11*y^11*s^5*t^10+z^3*x^10*y^11*s^5*t^10+z^4*x^9*y^11*s^5*t^10+z^5*x^8*y^11*s^5*t^10+z^8*x^2*y^13*s^6*t^6+z^8*x^3*y^12*s^6*t^6+z^9*x^2*y^12*s^6*t^6+z^8*x^4*y^11*s^6*t^6+z^10*x^2*y^11*s^6*t^6+z^8*x^5*y^10*s^6*t^6+z^9*x^4*y^10*s^6*t^6+z^10*x^3*y^10*s^6*t^6+z^11*x^2*y^10*s^6*t^6+z^8*x^6*y^15*s^6+z^8*x^7*y^14*s^6+z^9*x^6*y^14*s^6+z^8*x^8*y^13*s^6+z^10*x^6*y^13*s^6+z^8*x^9*y^12*s^6+z^9*x^8*y^12*s^6+z^10*x^7*y^12*s^6+z^11*x^6*y^12*s^6)*(z*x^2*y^3*s^4*u^4+x^3*y^2*s^4*u^4+z^2*x^2*s^4*u^2+z^4*x^3*u^2+z^5*x^2*y^2*s^5*u+z^2*x^5*y^2)*(x^2*y^2+z^2*y^2+z*x*y+1*x*y)", vars, ctx); time = check_omega(21, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#27: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^2*x^2*y^10*s^8*t^3+z^2*x^3*y^9*s^8*t^3+z^3*x^2*y^9*s^8*t^3+z^2*x^4*y^8*s^8*t^3+z^4*x^2*y^8*s^8*t^3+z^2*x^5*y^7*s^8*t^3+z^3*x^4*y^7*s^8*t^3+z^4*x^3*y^7*s^8*t^3+z^5*x^2*y^7*s^8*t^3+z*x^11*y^9*t^3+z*x^12*y^8*t^3+z^2*x^11*y^8*t^3+z*x^13*y^7*t^3+z^3*x^11*y^7*t^3+z*x^14*y^6*t^3+z^2*x^13*y^6*t^3+z^3*x^12*y^6*t^3+z^4*x^11*y^6*t^3+x^11*y^9*s^2*t+x^12*y^8*s^2*t+z*x^11*y^8*s^2*t+x^13*y^7*s^2*t+z^2*x^11*y^7*s^2*t+x^14*y^6*s^2*t+z*x^13*y^6*s^2*t+z^2*x^12*y^6*s^2*t+z^3*x^11*y^6*s^2*t)*(z^4*x^2*y^2*s^3*u^3+z^2*x^3*y^2*s^3*u^2+z^3*x^3*y^2*s^2*u+z*x^3*y^4*s*u+z^4*x^4*u)*(z^2*y^2+x^2*y+z*x*y+z^2*y+1*y+x)", vars, ctx); time = check_omega(19, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#28: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^7*x^7*y^8*s^3*t^7+z^7*x^8*y^7*s^3*t^7+z^8*x^7*y^7*s^3*t^7+z^7*x^9*y^6*s^3*t^7+z^9*x^7*y^6*s^3*t^7+z^7*x^10*y^5*s^3*t^7+z^8*x^9*y^5*s^3*t^7+z^9*x^8*y^5*s^3*t^7+z^10*x^7*y^5*s^3*t^7+z^9*x^8*y^10*s^5*t^3+z^9*x^9*y^9*s^5*t^3+z^10*x^8*y^9*s^5*t^3+z^9*x^10*y^8*s^5*t^3+z^11*x^8*y^8*s^5*t^3+z^9*x^11*y^7*s^5*t^3+z^10*x^10*y^7*s^5*t^3+z^11*x^9*y^7*s^5*t^3+z^12*x^8*y^7*s^5*t^3+z^6*x^8*y^13*s^4+z^6*x^9*y^12*s^4+z^7*x^8*y^12*s^4+z^6*x^10*y^11*s^4+z^8*x^8*y^11*s^4+z^6*x^11*y^10*s^4+z^7*x^10*y^10*s^4+z^8*x^9*y^10*s^4+z^9*x^8*y^10*s^4)*(z^4*x^2*s^3*u^4+z*x^2*y^3*s^3*u^3+z^2*x^4*y^2*s*u^2+z^4*x^3*y^4*s^3*u+z^3*x^2*y^3*s^4)*(y+z*x^2+x+z+1)", vars, ctx); time = check_omega(31, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#29: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(x^10*y^13*s^3*t^13+x^11*y^12*s^3*t^13+z*x^10*y^12*s^3*t^13+x^12*y^11*s^3*t^13+z^2*x^10*y^11*s^3*t^13+x^13*y^10*s^3*t^13+z*x^12*y^10*s^3*t^13+z^2*x^11*y^10*s^3*t^13+z^3*x^10*y^10*s^3*t^13+z^13*x^7*y^17*s^2*t^5+z^13*x^8*y^16*s^2*t^5+z^14*x^7*y^16*s^2*t^5+z^13*x^9*y^15*s^2*t^5+z^15*x^7*y^15*s^2*t^5+z^13*x^10*y^14*s^2*t^5+z^14*x^9*y^14*s^2*t^5+z^15*x^8*y^14*s^2*t^5+z^16*x^7*y^14*s^2*t^5+z^2*x^14*y^4*s^12*t^3+z^2*x^15*y^3*s^12*t^3+z^3*x^14*y^3*s^12*t^3+z^2*x^16*y^2*s^12*t^3+z^4*x^14*y^2*s^12*t^3+z^2*x^17*y*s^12*t^3+z^3*x^16*y*s^12*t^3+z^4*x^15*y*s^12*t^3+z^5*x^14*y*s^12*t^3+z^4*x^14*y^15*s^3*t^2+z^4*x^15*y^14*s^3*t^2+z^5*x^14*y^14*s^3*t^2+z^4*x^16*y^13*s^3*t^2+z^6*x^14*y^13*s^3*t^2+z^4*x^17*y^12*s^3*t^2+z^5*x^16*y^12*s^3*t^2+z^6*x^15*y^12*s^3*t^2+z^7*x^14*y^12*s^3*t^2+z^5*x^11*y^15*s^3+z^5*x^12*y^14*s^3+z^6*x^11*y^14*s^3+z^5*x^13*y^13*s^3+z^7*x^11*y^13*s^3+z^5*x^14*y^12*s^3+z^6*x^13*y^12*s^3+z^7*x^12*y^12*s^3+z^8*x^11*y^12*s^3)*(z*x^4*y^3*u^6+z^3*x^5*y^4*s^5*u^4+z*x^5*y^4*s^5*u^4+z^4*x^6*y^4*s*u^4+z*x*y^5*s^4*u^2+z^5*y^6*s^2*u^2+z^5*x^4*y^5)*(z*x^2*y^3+1*y^3+z^2*x^2*y^2+z^2*x*y^2+z*y^2+z^2*x*y)", vars, ctx); time = check_omega(21, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#30: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^2*x^4*y^6+z^2*x^5*y^5+z^3*x^4*y^5+z^2*x^6*y^4+z^4*x^4*y^4+z^2*x^7*y^3+z^3*x^6*y^3+z^4*x^5*y^3+z^5*x^4*y^3)*(z*x*y*s*u+y*s)", vars, ctx); time = check_omega(15, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#31: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^7*x^14*y^14*s^13*t^11+z^7*x^15*y^13*s^13*t^11+z^8*x^14*y^13*s^13*t^11+z^7*x^16*y^12*s^13*t^11+z^9*x^14*y^12*s^13*t^11+z^7*x^17*y^11*s^13*t^11+z^8*x^16*y^11*s^13*t^11+z^9*x^15*y^11*s^13*t^11+z^10*x^14*y^11*s^13*t^11+z^12*x^13*y^16*s^15*t^9+z^12*x^14*y^15*s^15*t^9+z^13*x^13*y^15*s^15*t^9+z^12*x^15*y^14*s^15*t^9+z^14*x^13*y^14*s^15*t^9+z^12*x^16*y^13*s^15*t^9+z^13*x^15*y^13*s^15*t^9+z^14*x^14*y^13*s^15*t^9+z^15*x^13*y^13*s^15*t^9+z^14*x^15*y^9*s^4*t^8+z^14*x^16*y^8*s^4*t^8+z^15*x^15*y^8*s^4*t^8+z^14*x^17*y^7*s^4*t^8+z^16*x^15*y^7*s^4*t^8+z^14*x^18*y^6*s^4*t^8+z^15*x^17*y^6*s^4*t^8+z^16*x^16*y^6*s^4*t^8+z^17*x^15*y^6*s^4*t^8+z^8*x^16*y^18*s^14*t^7+z^8*x^17*y^17*s^14*t^7+z^9*x^16*y^17*s^14*t^7+z^8*x^18*y^16*s^14*t^7+z^10*x^16*y^16*s^14*t^7+z^8*x^19*y^15*s^14*t^7+z^9*x^18*y^15*s^14*t^7+z^10*x^17*y^15*s^14*t^7+z^11*x^16*y^15*s^14*t^7+z^3*x^10*y^4*s*t^5+z^3*x^11*y^3*s*t^5+z^4*x^10*y^3*s*t^5+z^3*x^12*y^2*s*t^5+z^5*x^10*y^2*s*t^5+z^3*x^13*y*s*t^5+z^4*x^12*y*s*t^5+z^5*x^11*y*s*t^5+z^6*x^10*y*s*t^5+z^2*x^6*y^15*s^15*t^3+z^2*x^7*y^14*s^15*t^3+z^3*x^6*y^14*s^15*t^3+z^2*x^8*y^13*s^15*t^3+z^4*x^6*y^13*s^15*t^3+z^2*x^9*y^12*s^15*t^3+z^3*x^8*y^12*s^15*t^3+z^4*x^7*y^12*s^15*t^3+z^5*x^6*y^12*s^15*t^3)*(z^6*x^7*y^2*s^5*u^6+x^2*s^8*u^5+z^7*x^5*y^6*s^2*u^5+z^2*x^7*u^5+z^5*x^7*y^6*s*u^4+z^7*x^8*y^6*s^2*u+z^6*x^4*y^7)*(z*x^3*y^3+x^2*y^3+z^2*x*y^3+x^3*y^2+z^3*x*y^2+x^2*y+z^3*x^2+z^2*x)", vars, ctx); time = check_omega(22, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#32: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^8*x^3*y^5*s^3*t^14+z^8*x^4*y^4*s^3*t^14+z^9*x^3*y^4*s^3*t^14+z^8*x^5*y^3*s^3*t^14+z^10*x^3*y^3*s^3*t^14+z^8*x^6*y^2*s^3*t^14+z^9*x^5*y^2*s^3*t^14+z^10*x^4*y^2*s^3*t^14+z^11*x^3*y^2*s^3*t^14+z^4*x^11*y^17*s^12*t^12+z^4*x^12*y^16*s^12*t^12+z^5*x^11*y^16*s^12*t^12+z^4*x^13*y^15*s^12*t^12+z^6*x^11*y^15*s^12*t^12+z^4*x^14*y^14*s^12*t^12+z^5*x^13*y^14*s^12*t^12+z^6*x^12*y^14*s^12*t^12+z^7*x^11*y^14*s^12*t^12+z^3*x*y^10*s^14*t^4+z^3*x^2*y^9*s^14*t^4+z^4*x*y^9*s^14*t^4+z^3*x^3*y^8*s^14*t^4+z^5*x*y^8*s^14*t^4+z^3*x^4*y^7*s^14*t^4+z^4*x^3*y^7*s^14*t^4+z^5*x^2*y^7*s^14*t^4+z^6*x*y^7*s^14*t^4+z^7*x^4*y^14*s^9*t^3+z^7*x^5*y^13*s^9*t^3+z^8*x^4*y^13*s^9*t^3+z^7*x^6*y^12*s^9*t^3+z^9*x^4*y^12*s^9*t^3+z^7*x^7*y^11*s^9*t^3+z^8*x^6*y^11*s^9*t^3+z^9*x^5*y^11*s^9*t^3+z^10*x^4*y^11*s^9*t^3+x^11*y^16*s^10*t^2+x^12*y^15*s^10*t^2+z*x^11*y^15*s^10*t^2+x^13*y^14*s^10*t^2+z^2*x^11*y^14*s^10*t^2+x^14*y^13*s^10*t^2+z*x^13*y^13*s^10*t^2+z^2*x^12*y^13*s^10*t^2+z^3*x^11*y^13*s^10*t^2+z^11*x^5*y^11*s^2+z^11*x^6*y^10*s^2+z^12*x^5*y^10*s^2+z^11*x^7*y^9*s^2+z^13*x^5*y^9*s^2+z^11*x^8*y^8*s^2+z^12*x^7*y^8*s^2+z^13*x^6*y^8*s^2+z^14*x^5*y^8*s^2)*(z^3*x^5*y^5*s^5*u^7+z^2*x^4*y^3*s^3*u^5+z^3*y^2*s^2*u^5+x^6*y^3*s^4*u^4+z*x*y^3*u^3+z^3*x^5*y^3*s^5*u^2+z*x^7*y^7*s^5*u)*(y^2+z*y+1*y+x^2+z^3*x)", vars, ctx); time = check_omega(14, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#33: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^6*x^6*y^4*s^8*t^12+z^6*x^7*y^3*s^8*t^12+z^7*x^6*y^3*s^8*t^12+z^6*x^8*y^2*s^8*t^12+z^8*x^6*y^2*s^8*t^12+z^6*x^9*y*s^8*t^12+z^7*x^8*y*s^8*t^12+z^8*x^7*y*s^8*t^12+z^9*x^6*y*s^8*t^12+x*y^7*s^7*t^8+x^2*y^6*s^7*t^8+z*x*y^6*s^7*t^8+x^3*y^5*s^7*t^8+z^2*x*y^5*s^7*t^8+x^4*y^4*s^7*t^8+z*x^3*y^4*s^7*t^8+z^2*x^2*y^4*s^7*t^8+z^3*x*y^4*s^7*t^8+x^2*y^9*s^8*t^7+x^3*y^8*s^8*t^7+z*x^2*y^8*s^8*t^7+x^4*y^7*s^8*t^7+z^2*x^2*y^7*s^8*t^7+x^5*y^6*s^8*t^7+z*x^4*y^6*s^8*t^7+z^2*x^3*y^6*s^8*t^7+z^3*x^2*y^6*s^8*t^7+z^4*x^8*y^5*s^5*t^7+z^4*x^9*y^4*s^5*t^7+z^5*x^8*y^4*s^5*t^7+z^4*x^10*y^3*s^5*t^7+z^6*x^8*y^3*s^5*t^7+z^4*x^11*y^2*s^5*t^7+z^5*x^10*y^2*s^5*t^7+z^6*x^9*y^2*s^5*t^7+z^7*x^8*y^2*s^5*t^7+z^9*x^10*y^6*s^9*t+z^9*x^11*y^5*s^9*t+z^10*x^10*y^5*s^9*t+z^9*x^12*y^4*s^9*t+z^11*x^10*y^4*s^9*t+z^9*x^13*y^3*s^9*t+z^10*x^12*y^3*s^9*t+z^11*x^11*y^3*s^9*t+z^12*x^10*y^3*s^9*t)*(z^3*x^3*y^5*s^5*u^5+z^3*x^3*y^3*s^6*u^2+z^2*x^2*y^2*s^4*u+z^4*x^3*y^4*s^2*u+z^3*x^2*y^5*s^2+z^3*x^3*y^2*s^2+z^4*x^5*y^4*s)*(z^2*x*y^2+z*x*y^2+z^2*y+1)", vars, ctx); time = check_omega(21, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#34: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z*x^9*y^6*s^2*t^5+z*x^10*y^5*s^2*t^5+z^2*x^9*y^5*s^2*t^5+z*x^11*y^4*s^2*t^5+z^3*x^9*y^4*s^2*t^5+z*x^12*y^3*s^2*t^5+z^2*x^11*y^3*s^2*t^5+z^3*x^10*y^3*s^2*t^5+z^4*x^9*y^3*s^2*t^5+z^4*x^7*y^6*s^4+z^4*x^8*y^5*s^4+z^5*x^7*y^5*s^4+z^4*x^9*y^4*s^4+z^6*x^7*y^4*s^4+z^4*x^10*y^3*s^4+z^5*x^9*y^3*s^4+z^6*x^8*y^3*s^4+z^7*x^7*y^3*s^4)*(z*x^4*s^3*u^3+z*x^3*y*u^3+z*x^4*s^4+x^2*y^2)*(z*x*y)", vars, ctx); time = check_omega(23, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#35: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^3*x*y^20*s^5*t^17+z^3*x^2*y^19*s^5*t^17+z^4*x*y^19*s^5*t^17+z^3*x^3*y^18*s^5*t^17+z^5*x*y^18*s^5*t^17+z^3*x^4*y^17*s^5*t^17+z^4*x^3*y^17*s^5*t^17+z^5*x^2*y^17*s^5*t^17+z^6*x*y^17*s^5*t^17+z^17*x^15*y^16*s^16*t^16+z^17*x^16*y^15*s^16*t^16+z^18*x^15*y^15*s^16*t^16+z^17*x^17*y^14*s^16*t^16+z^19*x^15*y^14*s^16*t^16+z^17*x^18*y^13*s^16*t^16+z^18*x^17*y^13*s^16*t^16+z^19*x^16*y^13*s^16*t^16+z^20*x^15*y^13*s^16*t^16+z^2*x^16*y^4*s^13*t^13+z^2*x^17*y^3*s^13*t^13+z^3*x^16*y^3*s^13*t^13+z^2*x^18*y^2*s^13*t^13+z^4*x^16*y^2*s^13*t^13+z^2*x^19*y*s^13*t^13+z^3*x^18*y*s^13*t^13+z^4*x^17*y*s^13*t^13+z^5*x^16*y*s^13*t^13+z^11*x^2*y^4*s^8*t^11+z^11*x^3*y^3*s^8*t^11+z^12*x^2*y^3*s^8*t^11+z^11*x^4*y^2*s^8*t^11+z^13*x^2*y^2*s^8*t^11+z^11*x^5*y*s^8*t^11+z^12*x^4*y*s^8*t^11+z^13*x^3*y*s^8*t^11+z^14*x^2*y*s^8*t^11+z^8*x^12*y^14*s*t^11+z^8*x^13*y^13*s*t^11+z^9*x^12*y^13*s*t^11+z^8*x^14*y^12*s*t^11+z^10*x^12*y^12*s*t^11+z^8*x^15*y^11*s*t^11+z^9*x^14*y^11*s*t^11+z^10*x^13*y^11*s*t^11+z^11*x^12*y^11*s*t^11+z^14*x^11*y^12*s^14*t^5+z^14*x^12*y^11*s^14*t^5+z^15*x^11*y^11*s^14*t^5+z^14*x^13*y^10*s^14*t^5+z^16*x^11*y^10*s^14*t^5+z^14*x^14*y^9*s^14*t^5+z^15*x^13*y^9*s^14*t^5+z^16*x^12*y^9*s^14*t^5+z^17*x^11*y^9*s^14*t^5+z^7*x^12*y^15*s^10+z^7*x^13*y^14*s^10+z^8*x^12*y^14*s^10+z^7*x^14*y^13*s^10+z^9*x^12*y^13*s^10+z^7*x^15*y^12*s^10+z^8*x^14*y^12*s^10+z^9*x^13*y^12*s^10+z^10*x^12*y^12*s^10)*(z^6*x^7*y^5*s^6*u^8+z^4*x^6*y^5*s^2*u^8+z^4*x^4*y*s^7*u^7+z^7*x^8*y^7*s^4*u^7+z^4*x^4*y^6*s^3*u^5+z^4*y^5*s^2*u^4+z^8*s^4)*(z*x^3*y^4+x^3*y^3+z^2*x^2*y^3+z*y^3+z*x^3*y^2+z^3*x^3*y+z^2*x^3*y+z*x*y+z^2*x^3)", vars, ctx); time = check_omega(17, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#36: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^13*x^11*y^16*s^13*t^13+z^13*x^12*y^15*s^13*t^13+z^14*x^11*y^15*s^13*t^13+z^13*x^13*y^14*s^13*t^13+z^15*x^11*y^14*s^13*t^13+z^13*x^14*y^13*s^13*t^13+z^14*x^13*y^13*s^13*t^13+z^15*x^12*y^13*s^13*t^13+z^16*x^11*y^13*s^13*t^13+x^8*y^13*s^2*t^12+x^9*y^12*s^2*t^12+z*x^8*y^12*s^2*t^12+x^10*y^11*s^2*t^12+z^2*x^8*y^11*s^2*t^12+x^11*y^10*s^2*t^12+z*x^10*y^10*s^2*t^12+z^2*x^9*y^10*s^2*t^12+z^3*x^8*y^10*s^2*t^12+z^11*x^6*y^16*s^6*t^8+z^11*x^7*y^15*s^6*t^8+z^12*x^6*y^15*s^6*t^8+z^11*x^8*y^14*s^6*t^8+z^13*x^6*y^14*s^6*t^8+z^11*x^9*y^13*s^6*t^8+z^12*x^8*y^13*s^6*t^8+z^13*x^7*y^13*s^6*t^8+z^14*x^6*y^13*s^6*t^8+z^5*x^2*y^9*s^11*t^6+z^5*x^3*y^8*s^11*t^6+z^6*x^2*y^8*s^11*t^6+z^5*x^4*y^7*s^11*t^6+z^7*x^2*y^7*s^11*t^6+z^5*x^5*y^6*s^11*t^6+z^6*x^4*y^6*s^11*t^6+z^7*x^3*y^6*s^11*t^6+z^8*x^2*y^6*s^11*t^6+z^14*x^5*y^9*s^14*t+z^14*x^6*y^8*s^14*t+z^15*x^5*y^8*s^14*t+z^14*x^7*y^7*s^14*t+z^16*x^5*y^7*s^14*t+z^14*x^8*y^6*s^14*t+z^15*x^7*y^6*s^14*t+z^16*x^6*y^6*s^14*t+z^17*x^5*y^6*s^14*t+z^12*x^9*y^17*s^14+z^12*x^10*y^16*s^14+z^13*x^9*y^16*s^14+z^12*x^11*y^15*s^14+z^14*x^9*y^15*s^14+z^12*x^12*y^14*s^14+z^13*x^11*y^14*s^14+z^14*x^10*y^14*s^14+z^15*x^9*y^14*s^14)*(z^6*x^4*s^4*u^7+z^3*y*u^6+z^4*x^4*y*s^5*u^5+z^4*x^4*y^3*s^4*u^5+z^3*x^5*y^3*s^7*u^4+z^7*y*s^5*u^3+z^4*y^7*s^5)*(z^3*y^3+z*x^2*y^2+z^3*x^3*y+z*x^3*y+z^3*x*y+x^2+z^3)", vars, ctx); time = check_omega(19, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#37: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^5*x^13*y^15*s^8*t^13+z^5*x^14*y^14*s^8*t^13+z^6*x^13*y^14*s^8*t^13+z^5*x^15*y^13*s^8*t^13+z^7*x^13*y^13*s^8*t^13+z^5*x^16*y^12*s^8*t^13+z^6*x^15*y^12*s^8*t^13+z^7*x^14*y^12*s^8*t^13+z^8*x^13*y^12*s^8*t^13+z^3*x*y^6*t^11+z^3*x^2*y^5*t^11+z^4*x*y^5*t^11+z^3*x^3*y^4*t^11+z^5*x*y^4*t^11+z^3*x^4*y^3*t^11+z^4*x^3*y^3*t^11+z^5*x^2*y^3*t^11+z^6*x*y^3*t^11+z^5*x^6*y^16*s^5*t^9+z^5*x^7*y^15*s^5*t^9+z^6*x^6*y^15*s^5*t^9+z^5*x^8*y^14*s^5*t^9+z^7*x^6*y^14*s^5*t^9+z^5*x^9*y^13*s^5*t^9+z^6*x^8*y^13*s^5*t^9+z^7*x^7*y^13*s^5*t^9+z^8*x^6*y^13*s^5*t^9+z^6*x^11*y^6*s^11*t^7+z^6*x^12*y^5*s^11*t^7+z^7*x^11*y^5*s^11*t^7+z^6*x^13*y^4*s^11*t^7+z^8*x^11*y^4*s^11*t^7+z^6*x^14*y^3*s^11*t^7+z^7*x^13*y^3*s^11*t^7+z^8*x^12*y^3*s^11*t^7+z^9*x^11*y^3*s^11*t^7+z^3*x^14*y^16*s^2*t^3+z^3*x^15*y^15*s^2*t^3+z^4*x^14*y^15*s^2*t^3+z^3*x^16*y^14*s^2*t^3+z^5*x^14*y^14*s^2*t^3+z^3*x^17*y^13*s^2*t^3+z^4*x^16*y^13*s^2*t^3+z^5*x^15*y^13*s^2*t^3+z^6*x^14*y^13*s^2*t^3)*(x^4*y*s^6*u^3+x*y^2*s^4*u^3+x^3*y*s^4*u+x*y^4*u+x^5*y^4*s^4+z^6*y^4*s^3+x*y^6)*(z*y^2+z*x^3*y+z^3*y+1*y+z*x+z^2)", vars, ctx); time = check_omega(17, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#38: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^5*x^14*y^17*s^6*t^12+z^5*x^15*y^16*s^6*t^12+z^6*x^14*y^16*s^6*t^12+z^5*x^16*y^15*s^6*t^12+z^7*x^14*y^15*s^6*t^12+z^5*x^17*y^14*s^6*t^12+z^6*x^16*y^14*s^6*t^12+z^7*x^15*y^14*s^6*t^12+z^8*x^14*y^14*s^6*t^12+z^12*x^4*y^17*s^6*t^10+z^12*x^5*y^16*s^6*t^10+z^13*x^4*y^16*s^6*t^10+z^12*x^6*y^15*s^6*t^10+z^14*x^4*y^15*s^6*t^10+z^12*x^7*y^14*s^6*t^10+z^13*x^6*y^14*s^6*t^10+z^14*x^5*y^14*s^6*t^10+z^15*x^4*y^14*s^6*t^10+z^6*x^5*y^6*s^9*t^9+z^6*x^6*y^5*s^9*t^9+z^7*x^5*y^5*s^9*t^9+z^6*x^7*y^4*s^9*t^9+z^8*x^5*y^4*s^9*t^9+z^6*x^8*y^3*s^9*t^9+z^7*x^7*y^3*s^9*t^9+z^8*x^6*y^3*s^9*t^9+z^9*x^5*y^3*s^9*t^9+z^12*x^12*y^14*s^2*t^6+z^12*x^13*y^13*s^2*t^6+z^13*x^12*y^13*s^2*t^6+z^12*x^14*y^12*s^2*t^6+z^14*x^12*y^12*s^2*t^6+z^12*x^15*y^11*s^2*t^6+z^13*x^14*y^11*s^2*t^6+z^14*x^13*y^11*s^2*t^6+z^15*x^12*y^11*s^2*t^6+z^3*x^12*y^18*s*t^6+z^3*x^13*y^17*s*t^6+z^4*x^12*y^17*s*t^6+z^3*x^14*y^16*s*t^6+z^5*x^12*y^16*s*t^6+z^3*x^15*y^15*s*t^6+z^4*x^14*y^15*s*t^6+z^5*x^13*y^15*s*t^6+z^6*x^12*y^15*s*t^6+z^6*x^14*y^13*s^2*t+z^6*x^15*y^12*s^2*t+z^7*x^14*y^12*s^2*t+z^6*x^16*y^11*s^2*t+z^8*x^14*y^11*s^2*t+z^6*x^17*y^10*s^2*t+z^7*x^16*y^10*s^2*t+z^8*x^15*y^10*s^2*t+z^9*x^14*y^10*s^2*t)*(z^4*x^6*y^7*s*u^7+z^6*x^4*y^2*u^6+z*x*s^3*u^5+z^3*x*y*s^7*u^2+z^2*y^2*s^5*u^2+z^3*x*y^4*s^7*u+z^5*x*y*s*u)*(x^3*y^3+z*x^2*y^3+z^2*x*y^3+z^2*x^2*y^2+z*x^2*y^2)", vars, ctx); time = check_omega(23, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#39: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^5*x^10*y^13*s^5*t^11+z^5*x^11*y^12*s^5*t^11+z^6*x^10*y^12*s^5*t^11+z^5*x^12*y^11*s^5*t^11+z^7*x^10*y^11*s^5*t^11+z^5*x^13*y^10*s^5*t^11+z^6*x^12*y^10*s^5*t^11+z^7*x^11*y^10*s^5*t^11+z^8*x^10*y^10*s^5*t^11+z^8*x^2*y^15*s^3*t^11+z^8*x^3*y^14*s^3*t^11+z^9*x^2*y^14*s^3*t^11+z^8*x^4*y^13*s^3*t^11+z^10*x^2*y^13*s^3*t^11+z^8*x^5*y^12*s^3*t^11+z^9*x^4*y^12*s^3*t^11+z^10*x^3*y^12*s^3*t^11+z^11*x^2*y^12*s^3*t^11+z^14*x^14*y^5*s^14*t^10+z^14*x^15*y^4*s^14*t^10+z^15*x^14*y^4*s^14*t^10+z^14*x^16*y^3*s^14*t^10+z^16*x^14*y^3*s^14*t^10+z^14*x^17*y^2*s^14*t^10+z^15*x^16*y^2*s^14*t^10+z^16*x^15*y^2*s^14*t^10+z^17*x^14*y^2*s^14*t^10+z*x^12*y^11*s*t^7+z*x^13*y^10*s*t^7+z^2*x^12*y^10*s*t^7+z*x^14*y^9*s*t^7+z^3*x^12*y^9*s*t^7+z*x^15*y^8*s*t^7+z^2*x^14*y^8*s*t^7+z^3*x^13*y^8*s*t^7+z^4*x^12*y^8*s*t^7+z^11*x^16*y^13*s^10*t^3+z^11*x^17*y^12*s^10*t^3+z^12*x^16*y^12*s^10*t^3+z^11*x^18*y^11*s^10*t^3+z^13*x^16*y^11*s^10*t^3+z^11*x^19*y^10*s^10*t^3+z^12*x^18*y^10*s^10*t^3+z^13*x^17*y^10*s^10*t^3+z^14*x^16*y^10*s^10*t^3+z^5*x^4*y^6*s^2*t^3+z^5*x^5*y^5*s^2*t^3+z^6*x^4*y^5*s^2*t^3+z^5*x^6*y^4*s^2*t^3+z^7*x^4*y^4*s^2*t^3+z^5*x^7*y^3*s^2*t^3+z^6*x^6*y^3*s^2*t^3+z^7*x^5*y^3*s^2*t^3+z^8*x^4*y^3*s^2*t^3)*(z^4*x^2*y^3*s^5*u^7+z^3*x^6*y^2*s^7*u^6+z^2*x*y*s*u^4+y*s^4*u^3+z^3*x^4*y^3*s^4*u^2+z^7*x*s^6*u+z^5*x^6*y^7*s)*(z*x^2*y^3+z^3*x*y^3+y^2+z*x*y+z^2*y)", vars, ctx); time = check_omega(17, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#40: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^8*x^14+z^8*x^12+1*x^12+z^8*x^10+z^6*x^10+z^6*x^8+1*x^8+z^8*x^6+z^8*x^4+1*x^4+z^8*x^2+z^6*x^2+z*x^2+z^10+z^6+z+1)", vars, ctx); time = check_omega(1, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#41: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "(z^6*x^10*y^13*s^9*t^12+z^6*x^11*y^12*s^9*t^12+z^7*x^10*y^12*s^9*t^12+z^6*x^12*y^11*s^9*t^12+z^8*x^10*y^11*s^9*t^12+z^6*x^13*y^10*s^9*t^12+z^7*x^12*y^10*s^9*t^12+z^8*x^11*y^10*s^9*t^12+z^9*x^10*y^10*s^9*t^12+z^7*x^2*y^11*s*t^9+z^7*x^3*y^10*s*t^9+z^8*x^2*y^10*s*t^9+z^7*x^4*y^9*s*t^9+z^9*x^2*y^9*s*t^9+z^7*x^5*y^8*s*t^9+z^8*x^4*y^8*s*t^9+z^9*x^3*y^8*s*t^9+z^10*x^2*y^8*s*t^9+z^11*x^10*y^9*s^11*t^7+z^11*x^11*y^8*s^11*t^7+z^12*x^10*y^8*s^11*t^7+z^11*x^12*y^7*s^11*t^7+z^13*x^10*y^7*s^11*t^7+z^11*x^13*y^6*s^11*t^7+z^12*x^12*y^6*s^11*t^7+z^13*x^11*y^6*s^11*t^7+z^14*x^10*y^6*s^11*t^7+z^7*x^2*y^6*s*t^7+z^7*x^3*y^5*s*t^7+z^8*x^2*y^5*s*t^7+z^7*x^4*y^4*s*t^7+z^9*x^2*y^4*s*t^7+z^7*x^5*y^3*s*t^7+z^8*x^4*y^3*s*t^7+z^9*x^3*y^3*s*t^7+z^10*x^2*y^3*s*t^7+z^2*x^13*y^11*t^3+z^2*x^14*y^10*t^3+z^3*x^13*y^10*t^3+z^2*x^15*y^9*t^3+z^4*x^13*y^9*t^3+z^2*x^16*y^8*t^3+z^3*x^15*y^8*t^3+z^4*x^14*y^8*t^3+z^5*x^13*y^8*t^3)*(z^4*y^2*s*u^6+x^4*y^5*u^4+z^5*y^4*s^5*u^3+z^6*x^5*y^6*s^4*u^2+z^6*x^5*y*s^6*u+z^6*x^3*y^6*s^4*u+z^4*x^2*y^2*u)*(z*x^3*y^3+z^3*x^2*y^2+z^2*x^2*y^2+z^3*y^2+z*y+z^3*x)", vars, ctx); time = check_omega(19, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; flint_printf("#42: "); fflush(stdout); nmod_mpoly_set_str_pretty(a, "x^4120 + x^4118*y^2 + x^3708*y^400 + x^3706*y^402 + x^2781*y^1300 + x^2779*y^1302 + x^1339*y^2700 + x^927*y^3100 + y^4000 + x^7172*y^4167 + x^8349*y^4432 + x^8347*y^4434 + x^6760*y^4567 + x^5833*y^5467 + x^5568*y^7132 + x^11401*y^8599", vars, ctx); time = check_omega(2, a, vars, ctx); flint_printf("%wd\n", time); total_time += time; nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } flint_printf("total_time: %wd\n", total_time); for (k = 0; k <= 4; k++) { mp_limb_t ps[] = {2, 3, 11, 257, 43051}; flint_printf("\n------ 4 variables, characteristic %wu ------\n", ps[k]); total_time = 0; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, c; const char * vars[] = {"x","y","z","t"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, ps[k]); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(c, ctx); for (i = 1; i <= 20; i++) { nmod_mpoly_set_str_pretty(a, "1+x+y+z+t", vars, ctx); nmod_mpoly_pow_ui(c, a, i, ctx); nmod_mpoly_set_str_pretty(a, "x", vars, ctx); nmod_mpoly_add(a, a, c, ctx); nmod_mpoly_set_str_pretty(b, "y", vars, ctx); nmod_mpoly_add(b, b, c, ctx); nmod_mpoly_mul(c, a, b, ctx); flint_printf("#%wd: ", i); fflush(stdout); time = check_omega(2, c, vars, ctx); flint_printf("%wd\n", time); total_time += time; } nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(c, ctx); nmod_mpoly_ctx_clear(ctx); } flint_printf("total_time: %wd\n", total_time); } flint_cleanup_master(); return 0; } #if defined(__GNUC__) # pragma GCC diagnostic pop #endif flint-3.1.3/src/nmod_mpoly_factor/realloc.c000066400000000000000000000036661461254215100207350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "nmod_mpoly_factor.h" void nmod_mpoly_factor_realloc(nmod_mpoly_factor_t f, slong alloc, const nmod_mpoly_ctx_t ctx) { slong i; if (alloc <= 0) { nmod_mpoly_factor_clear(f, ctx); nmod_mpoly_factor_init(f, ctx); return; } if (f->alloc > 0) { if (f->alloc > alloc) { for (i = alloc; i < f->alloc; i++) { nmod_mpoly_clear(f->poly + i, ctx); fmpz_clear(f->exp + i); } f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (nmod_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(nmod_mpoly_struct)); } else if (f->alloc < alloc) { f->exp = (fmpz *) flint_realloc(f->exp, alloc * sizeof(fmpz)); f->poly = (nmod_mpoly_struct *) flint_realloc(f->poly, alloc * sizeof(nmod_mpoly_struct)); for (i = f->alloc; i < alloc; i++) { nmod_mpoly_init(f->poly + i, ctx); fmpz_init(f->exp + i); } } } else { f->exp = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); f->poly = (nmod_mpoly_struct *) flint_malloc(alloc * sizeof(nmod_mpoly_struct)); for (i = 0; i < alloc; i++) nmod_mpoly_init(f->poly + i, ctx); } f->alloc = alloc; } flint-3.1.3/src/nmod_mpoly_factor/sort.c000066400000000000000000000035041461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "nmod_mpoly_factor.h" typedef struct { slong idx; fmpz exp; const nmod_mpoly_struct * polys; const nmod_mpoly_ctx_struct * ctx; } sort_struct; static int _sort(const void * a_, const void * b_) { int cmp; const sort_struct * a = (const sort_struct *) a_; const sort_struct * b = (const sort_struct *) b_; const nmod_mpoly_struct * apoly = a->polys + a->idx; const nmod_mpoly_struct * bpoly = b->polys + b->idx; cmp = fmpz_cmp(&a->exp, &b->exp); if (cmp != 0) return cmp; return nmod_mpoly_cmp(apoly, bpoly, a->ctx); } void nmod_mpoly_factor_sort( nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx) { slong i; sort_struct * data; nmod_mpoly_struct * fc; if (f->num < 1) return; data = (sort_struct *) flint_malloc(f->num*sizeof(sort_struct)); for (i = 0; i < f->num; i++) { data[i].idx = i; data[i].exp = f->exp[i]; data[i].polys = f->poly; data[i].ctx = ctx; } qsort(data, f->num, sizeof(sort_struct), _sort); /* we will not permute in place */ fc = (nmod_mpoly_struct *) flint_malloc(f->num * sizeof(nmod_mpoly_struct)); memcpy(fc, f->poly, f->num*sizeof(nmod_mpoly_struct)); for (i = 0; i < f->num; i++) { f->exp[i] = data[i].exp; f->poly[i] = fc[data[i].idx]; } flint_free(fc); flint_free(data); return; } flint-3.1.3/src/nmod_mpoly_factor/test/000077500000000000000000000000001461254215100201145ustar00rootroot00000000000000flint-3.1.3/src/nmod_mpoly_factor/test/main.c000066400000000000000000000024431461254215100212070ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor.c" #include "t-factor_content.c" #include "t-factor_squarefree.c" #include "t-factor_wang.c" #include "t-factor_zassenhaus.c" #include "t-factor_zippel.c" #include "t-gcd_subresultant.c" #include "t-gcd_zippel.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_mpoly_factor), TEST_FUNCTION(nmod_mpoly_factor_content), TEST_FUNCTION(nmod_mpoly_factor_squarefree), TEST_FUNCTION(nmod_mpoly_factor_wang), TEST_FUNCTION(nmod_mpoly_factor_zassenhaus), TEST_FUNCTION(nmod_mpoly_factor_zippel), TEST_FUNCTION(nmod_mpoly_factor_gcd_subresultant), TEST_FUNCTION(nmod_mpoly_factor_gcd_zippel) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod_mpoly_factor/test/t-factor.c000066400000000000000000000160001461254215100217740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c and * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx, int (* factor_fun)(nmod_mpoly_factor_t, const nmod_mpoly_t, const nmod_mpoly_ctx_t)) { slong i; nmod_mpoly_t q; nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); nmod_mpoly_factor_init(g, ctx); nmod_mpoly_factor_init(h, ctx); nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { if (!nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } nmod_mpoly_factor_expand(q, g, ctx); if (!nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { nmod_mpoly_factor_sort(g, ctx); nmod_mpoly_factor_sort(h, ctx); if (nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(nmod_mpoly_factor, state) { slong i, j, tmul = 30; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a; const char * vars[] = {"x", "y", "z"}; nmod_mpoly_ctx_init(ctx, 3, ORD_LEX, 2); nmod_mpoly_init(a, ctx); nmod_mpoly_set_str_pretty(a, "x^4120+x^4118*y^2+x^3708*y^400+x^3706*y^402+x^2781*y^1300+" "x^2779*y^1302+x^1339*y^2700+x^927*y^3100+y^4000+x^7172*y^4167+" "x^8349*y^4432+x^8347*y^4434+x^6760*y^4567+x^5833*y^5467+" "x^5568*y^7132+x^11401*y^8599", vars, ctx); check_omega(2, 2, a, ctx, nmod_mpoly_factor); /* irreducibility test */ nmod_mpoly_set_str_pretty(a, "(1+x^2+y+x*y+y^2+z+x*z+y*z+z^2)*" "(1+x+x^2+x^3+y^2+x*y^2+y^3+y*z+x*y*z+z^2+x*z^2+y*z^2+z^3)*" "(1+x+x^4+x^5+y^3+x^2*y^3+y^5+y*z+x*y*z+x^2*y*z+x^3*y*z+y^3*z+" "x*y^3*z+y*z^2+x^2*y*z^2+z^3+x^2*z^3+y^2*z^3+z^5)", vars, ctx); check_omega(3, 3, a, ctx, nmod_mpoly_factor); /* frobenius recombination */ nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul*flint_test_multiplier(); i++) { slong lower; nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong nfacs, len; ulong expbound, powbound, pow, expbounds[2]; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 4 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init(ctx, 2, mpoly_ordering_randtest(state), p); nmod_mpoly_init(a, ctx); nmod_mpoly_init(t, ctx); nfacs = 5 + n_randint(state, 5); powbound = 1 + n_randint(state, 3); expbound = 3 + 70/nfacs/powbound; lower = 0; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10); expbounds[0] = 1 + n_randint(state, expbound); expbounds[1] = 1 + n_randint(state, expbound); nmod_mpoly_randtest_bounds(t, state, len, expbounds, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!nmod_mpoly_is_ui(t, ctx)) lower += pow; nmod_mpoly_pow_ui(t, t, pow, ctx); nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, nmod_mpoly_factor); /* bivariate */ nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 4 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, p); nmod_mpoly_init(a, ctx); nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 100/nfacs/n/powbound; lower = 0; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!nmod_mpoly_is_ui(t, ctx)) lower += pow; nmod_mpoly_pow_ui(t, t, pow, ctx); nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, nmod_mpoly_factor); /* multivariate */ nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly_factor/test/t-factor_content.c000066400000000000000000000077371461254215100235470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "nmod_mpoly_factor.h" void check_content(const nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx) { slong i, v; nmod_mpoly_t q; nmod_mpoly_factor_t g; fmpz_t deg; nmod_mpoly_factor_init(g, ctx); nmod_mpoly_init(q, ctx); fmpz_init(deg); if (!nmod_mpoly_factor_content(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_factor_expand(q, g, ctx); if (!nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { for (v = 0; v < ctx->minfo->nvars; v++) { if (nmod_mpoly_length(g->poly + i, ctx) < 2) { if (!nmod_mpoly_is_gen(g->poly + i, -1, ctx)) { flint_printf("FAIL:\nmonomial is bad\n"); fflush(stdout); flint_abort(); } } else { if (!nmod_mpoly_content_vars(q, g->poly + i, &v, 1, ctx)) { flint_printf("FAIL:\ncheck content could be computed\n"); fflush(stdout); flint_abort(); } nmod_mpoly_degree_fmpz(deg, g->poly + i, v, ctx); if (!nmod_mpoly_is_one(q, ctx) && !fmpz_is_zero(deg)) { flint_printf("FAIL:\ncontent is bad\n"); fflush(stdout); flint_abort(); } } } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); fmpz_clear(deg); } TEST_FUNCTION_START(nmod_mpoly_factor_content, state) { slong i, j, k, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong n, nfacs, len; ulong * expbounds; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 4 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, p); nmod_mpoly_init(a, ctx); nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 5 + (8 + n_randint(state, 8))/n; expbounds = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); for (k = 0; k < ctx->minfo->nvars; k++) expbounds[k] = 3; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 9); if (ctx->minfo->nvars > 0) { k = n_randint(state, ctx->minfo->nvars); expbounds[k] = 1; } nmod_mpoly_randtest_bounds(t, state, len, expbounds, ctx); if (!nmod_mpoly_is_zero(t, ctx)) { nmod_mpoly_mul(t, a, t, ctx); if (t->length < 1500) nmod_mpoly_swap(a, t, ctx); } } check_content(a, ctx); flint_free(expbounds); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000066531461254215100242330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly_factor.h" void check_it(const nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx) { slong i, j; nmod_mpoly_t q; nmod_mpoly_factor_t g, h; nmod_mpoly_factor_init(g, ctx); nmod_mpoly_factor_init(h, ctx); nmod_mpoly_init(q, ctx); if (!nmod_mpoly_factor_squarefree(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_factor_expand(q, g, ctx); if (!nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } for (i = 0; i < g->num; i++) { nmod_mpoly_factor_squarefree(h, g->poly + i, ctx); for (j = 0; j < h->num; j++) { if (!fmpz_is_one(h->exp + j)) { flint_printf("FAIL:\nfactor has a square factor\n"); fflush(stdout); flint_abort(); } } } for (i = 1; i < g->num; i++) for (j = 0; j < i; j++) { if (!nmod_mpoly_gcd(q, g->poly + i, g->poly + j, ctx)) { flint_printf("FAIL:\ncheck gcd could be computed\n"); } if (!nmod_mpoly_is_one(q, ctx)) { flint_printf("FAIL:\nbases have a common factor\n"); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); } TEST_FUNCTION_START(nmod_mpoly_factor_squarefree, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 4 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, 6, p); nmod_mpoly_init(a, ctx); nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); expbound = 3 + 25/nfacs/n/powbound; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 60/powbound/n); nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); nmod_mpoly_pow_ui(t, t, pow, ctx); nmod_mpoly_mul(a, a, t, ctx); } check_it(a, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly_factor/test/t-factor_wang.c000066400000000000000000000107061461254215100230170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c and * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx, int (* factor_fun)(nmod_mpoly_factor_t, const nmod_mpoly_t, const nmod_mpoly_ctx_t)) { slong i; nmod_mpoly_t q; nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); nmod_mpoly_factor_init(g, ctx); nmod_mpoly_factor_init(h, ctx); nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { if (!nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } nmod_mpoly_factor_expand(q, g, ctx); if (!nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { nmod_mpoly_factor_sort(g, ctx); nmod_mpoly_factor_sort(h, ctx); if (nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(nmod_mpoly_factor_wang, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 4 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, 7, p); nmod_mpoly_init(a, ctx); nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 20/nfacs/n/powbound; lower = 0; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!nmod_mpoly_is_ui(t, ctx)) lower += pow; nmod_mpoly_pow_ui(t, t, pow, ctx); nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, nmod_mpoly_factor_wang); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000107221461254215100242450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c and * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx, int (* factor_fun)(nmod_mpoly_factor_t, const nmod_mpoly_t, const nmod_mpoly_ctx_t)) { slong i; nmod_mpoly_t q; nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); nmod_mpoly_factor_init(g, ctx); nmod_mpoly_factor_init(h, ctx); nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { if (!nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } nmod_mpoly_factor_expand(q, g, ctx); if (!nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { nmod_mpoly_factor_sort(g, ctx); nmod_mpoly_factor_sort(h, ctx); if (nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(nmod_mpoly_factor_zassenhaus, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 4 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, 5, p); nmod_mpoly_init(a, ctx); nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 15/nfacs/n/powbound; lower = 0; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!nmod_mpoly_is_ui(t, ctx)) lower += pow; nmod_mpoly_pow_ui(t, t, pow, ctx); nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, nmod_mpoly_factor_zassenhaus); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000107131461254215100233640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly_factor.h" /* Defined in t-factor.c, t-factor_wang.c, t-factor_zassenhaus.c and * t-factor_zippel.c */ #ifndef check_omega #define check_omega check_omega /* check total number of factors with multiplicity is between lower and upper */ void check_omega( slong lower, slong upper, const nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx, int (* factor_fun)(nmod_mpoly_factor_t, const nmod_mpoly_t, const nmod_mpoly_ctx_t)) { slong i; nmod_mpoly_t q; nmod_mpoly_factor_t g, h; fmpz_t omega; fmpz_init(omega); nmod_mpoly_factor_init(g, ctx); nmod_mpoly_factor_init(h, ctx); nmod_mpoly_init(q, ctx); if (!factor_fun(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { if (!nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL:\nfactorization is not unit normal\n"); fflush(stdout); flint_abort(); } } fmpz_zero(omega); for (i = 0; i < g->num; i++) fmpz_add(omega, omega, g->exp + i); if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0) { flint_printf("FAIL:\nfactorization has wrong number of factors\n"); fflush(stdout); flint_abort(); } nmod_mpoly_factor_expand(q, g, ctx); if (!nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL:\nfactorization does not match original polynomial\n"); fflush(stdout); flint_abort(); } if (factor_fun != nmod_mpoly_factor) { nmod_mpoly_factor_sort(g, ctx); nmod_mpoly_factor_sort(h, ctx); if (nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("FAIL:\nfactorizations do not match\n"); fflush(stdout); flint_abort(); } } for (i = 0; i < g->num; i++) { nmod_mpoly_factor(h, g->poly + i, ctx); if (h->num != 1 || !fmpz_is_one(h->exp + 0)) { flint_printf("FAIL:\nfactor is reducible\n"); fflush(stdout); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } #endif TEST_FUNCTION_START(nmod_mpoly_factor_zippel, state) { slong i, j, tmul = 30; for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong n, nfacs, len; ulong expbound, powbound, pow; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 4 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, p); nmod_mpoly_init(a, ctx); nmod_mpoly_init(t, ctx); n = FLINT_MAX(WORD(1), ctx->minfo->nvars); nfacs = 1 + (6 + n_randint(state, 6))/n; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 80/nfacs/n/powbound; lower = 0; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 10/powbound); nmod_mpoly_randtest_bound(t, state, len, expbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); pow = 1 + n_randint(state, powbound); if (!nmod_mpoly_is_ui(t, ctx)) lower += pow; nmod_mpoly_pow_ui(t, t, pow, ctx); nmod_mpoly_mul(a, a, t, ctx); } check_omega(lower, WORD_MAX, a, ctx, nmod_mpoly_factor_zippel); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000163771461254215100241070ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly_factor.h" /* Defined in t-gcd_subresultant.c and t-gcd_zippel.c */ #define compute_gcd compute_gcd_subresultant int compute_gcd( nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { int success; slong var = 0; nmod_mpoly_t Ac, Bc, Gc, s, t; nmod_mpoly_univar_t Ax, Bx, Gx; if (nmod_mpoly_is_zero(A, ctx) || nmod_mpoly_is_zero(B, ctx)) return nmod_mpoly_gcd(G, A, B, ctx); nmod_mpoly_init(Ac, ctx); nmod_mpoly_init(Bc, ctx); nmod_mpoly_init(Gc, ctx); nmod_mpoly_init(s, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_univar_init(Ax, ctx); nmod_mpoly_univar_init(Bx, ctx); nmod_mpoly_univar_init(Gx, ctx); nmod_mpoly_to_univar(Ax, A, var, ctx); nmod_mpoly_to_univar(Bx, B, var, ctx); success = _nmod_mpoly_vec_content_mpoly(Ac, Ax->coeffs, Ax->length, ctx) && _nmod_mpoly_vec_content_mpoly(Bc, Bx->coeffs, Bx->length, ctx) && nmod_mpoly_gcd(Gc, Ac, Bc, ctx); if (!success) goto cleanup; _nmod_mpoly_vec_divexact_mpoly(Ax->coeffs, Ax->length, Ac, ctx); _nmod_mpoly_vec_divexact_mpoly(Bx->coeffs, Bx->length, Bc, ctx); success = fmpz_cmp(Ax->exps + 0, Bx->exps + 0) > 0 ? nmod_mpoly_univar_pseudo_gcd(Gx, Ax, Bx, ctx) : nmod_mpoly_univar_pseudo_gcd(Gx, Bx, Ax, ctx); if (!success) goto cleanup; if (nmod_mpoly_gcd(t, Ax->coeffs + 0, Bx->coeffs + 0, ctx) && t->length == 1) { nmod_mpoly_term_content(s, Gx->coeffs + 0, ctx); nmod_mpoly_divexact(t, Gx->coeffs + 0, s, ctx); _nmod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } else if (nmod_mpoly_gcd(t, Ax->coeffs + Ax->length - 1, Bx->coeffs + Bx->length - 1, ctx) && t->length == 1) { nmod_mpoly_term_content(s, Gx->coeffs + Gx->length - 1, ctx); nmod_mpoly_divexact(t, Gx->coeffs + Gx->length - 1, s, ctx); _nmod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); } success = _nmod_mpoly_vec_content_mpoly(t, Gx->coeffs, Gx->length, ctx); if (!success) goto cleanup; _nmod_mpoly_vec_divexact_mpoly(Gx->coeffs, Gx->length, t, ctx); _nmod_mpoly_vec_mul_mpoly(Gx->coeffs, Gx->length, Gc, ctx); _nmod_mpoly_from_univar(G, FLINT_MIN(A->bits, B->bits), Gx, var, ctx); nmod_mpoly_make_monic(G, G, ctx); success = 1; cleanup: nmod_mpoly_clear(Ac, ctx); nmod_mpoly_clear(Bc, ctx); nmod_mpoly_clear(Gc, ctx); nmod_mpoly_clear(s, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_univar_clear(Ax, ctx); nmod_mpoly_univar_clear(Bx, ctx); nmod_mpoly_univar_clear(Gx, ctx); return success; } /* Defined in t-gcd_subresultant.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_subresultant void gcd_check( nmod_mpoly_t g, nmod_mpoly_t a, nmod_mpoly_t b, const nmod_mpoly_t gdiv, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; nmod_mpoly_t ca, cb, cg; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); res = compute_gcd(g, a, b, ctx); nmod_mpoly_assert_canonical(g, ctx); if (!res) { flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_zero(gdiv, ctx)) { if (!nmod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != 1) { flint_printf("FAIL: Check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = 1; res = res && nmod_mpoly_divides(ca, a, g, ctx); res = res && nmod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd(cg, ca, cb, ctx); nmod_mpoly_assert_canonical(cg, ctx); if (!res) { flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(nmod_mpoly_factor_gcd_subresultant, state) { slong i, j, tmul = 15; for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); if (ctx->minfo->nvars < 1) { nmod_mpoly_ctx_clear(ctx); continue; } nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 12) + 1; len1 = n_randint(state, 12); len2 = n_randint(state, 12); degbound = 1 + 10/ctx->minfo->nvars; for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "random dense"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd #undef gcd_check flint-3.1.3/src/nmod_mpoly_factor/test/t-gcd_zippel.c000066400000000000000000000360711461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly_factor.h" /* Defined in t-gcd_subresultant.c and t-gcd_zippel.c */ #define compute_gcd compute_gcd_zippel int compute_gcd( nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx) { slong i; flint_bitcnt_t wbits; flint_rand_t state; int success = 0; nmod_mpoly_ctx_t lctx; nmod_mpoly_t Al, Bl, Gl, Abarl, Bbarl; nmod_mpoly_t Ac, Bc, Gc; ulong * shift, * stride; slong * perm; if (nmod_mpoly_is_zero(A, ctx)) { if (nmod_mpoly_is_zero(B, ctx)) nmod_mpoly_zero(G, ctx); else nmod_mpoly_make_monic(G, B, ctx); return 1; } if (nmod_mpoly_is_zero(B, ctx)) { nmod_mpoly_make_monic(G, A, ctx); return 1; } if (A->bits > FLINT_BITS || B->bits > FLINT_BITS) { return 0; } if (ctx->minfo->nvars < 2) { return nmod_mpoly_gcd(G, A, B, ctx); } perm = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, slong); shift = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); stride = FLINT_ARRAY_ALLOC(ctx->minfo->nvars, ulong); for (i = 0; i < ctx->minfo->nvars; i++) { perm[i] = i; shift[i] = 0; stride[i] = 1; } FLINT_ASSERT(A->bits <= FLINT_BITS); FLINT_ASSERT(B->bits <= FLINT_BITS); FLINT_ASSERT(!nmod_mpoly_is_zero(A, ctx)); FLINT_ASSERT(!nmod_mpoly_is_zero(B, ctx)); FLINT_ASSERT(ctx->minfo->nvars >= 2); flint_randinit(state); wbits = FLINT_MAX(A->bits, B->bits); nmod_mpoly_ctx_init(lctx, ctx->minfo->nvars, ORD_LEX, nmod_mpoly_ctx_modulus(ctx)); nmod_mpoly_init3(Al, 0, wbits, lctx); nmod_mpoly_init3(Bl, 0, wbits, lctx); nmod_mpoly_init3(Gl, 0, wbits, lctx); nmod_mpoly_init3(Abarl, 0, wbits, lctx); nmod_mpoly_init3(Bbarl, 0, wbits, lctx); nmod_mpoly_init3(Ac, 0, wbits, lctx); nmod_mpoly_init3(Bc, 0, wbits, lctx); nmod_mpoly_init3(Gc, 0, wbits, lctx); nmod_mpoly_to_mpolyl_perm_deflate(Al, lctx, A, ctx, perm, shift, stride); nmod_mpoly_to_mpolyl_perm_deflate(Bl, lctx, B, ctx, perm, shift, stride); success = nmod_mpolyl_content(Ac, Al, 1, lctx) && nmod_mpolyl_content(Bc, Bl, 1, lctx); if (!success) goto cleanup; if (!nmod_mpoly_divides(Al, Al, Ac, lctx) || !nmod_mpoly_divides(Bl, Bl, Bc, lctx)) { flint_printf("FAIL: Check content divides\n"); fflush(stdout); flint_abort(); } nmod_mpoly_repack_bits_inplace(Al, wbits, lctx); nmod_mpoly_repack_bits_inplace(Bl, wbits, lctx); success = nmod_mpolyl_gcdp_zippel_smprime(Gl, Abarl, Bbarl, Al, Bl, ctx->minfo->nvars - 1, lctx, state); if (!success) goto cleanup; success = nmod_mpoly_gcd(Gc, Ac, Bc, lctx); if (!success) goto cleanup; nmod_mpoly_mul(Gl, Gl, Gc, lctx); nmod_mpoly_from_mpolyl_perm_inflate(G, FLINT_MIN(A->bits, B->bits), ctx, Gl, lctx, perm, shift, stride); success = 1; nmod_mpoly_make_monic(G, G, ctx); cleanup: nmod_mpoly_clear(Al, lctx); nmod_mpoly_clear(Bl, lctx); nmod_mpoly_clear(Gl, lctx); nmod_mpoly_clear(Abarl, lctx); nmod_mpoly_clear(Bbarl, lctx); nmod_mpoly_clear(Ac, lctx); nmod_mpoly_clear(Bc, lctx); nmod_mpoly_clear(Gc, lctx); nmod_mpoly_ctx_clear(lctx); flint_randclear(state); flint_free(perm); flint_free(shift); flint_free(stride); return success; } /* Defined in t-gcd_subresultant.c and t-gcd_zippel.c */ #define gcd_check gcd_check_gcd_zippel void gcd_check( nmod_mpoly_t g, nmod_mpoly_t a, nmod_mpoly_t b, const nmod_mpoly_t gdiv, nmod_mpoly_ctx_t ctx, slong i, slong j, const char * name) { int res; nmod_mpoly_t ca, cb, cg; nmod_mpoly_init(ca, ctx); nmod_mpoly_init(cb, ctx); nmod_mpoly_init(cg, ctx); res = compute_gcd(g, a, b, ctx); nmod_mpoly_assert_canonical(g, ctx); if (!res) { if (FLINT_BIT_COUNT(nmod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_zero(gdiv, ctx)) { if (!nmod_mpoly_divides(ca, g, gdiv, ctx)) { flint_printf("FAIL: Check divisor of gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } } if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(a, ctx) || !nmod_mpoly_is_zero(b, ctx)) { flint_printf("FAIL: Check zero gcd\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } goto cleanup; } if (g->coeffs[0] != 1) { flint_printf("FAIL: Check gcd is monic\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = nmod_mpoly_divides(ca, a, g, ctx) && nmod_mpoly_divides(cb, b, g, ctx); if (!res) { flint_printf("FAIL: Check divisibility\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } res = compute_gcd(cg, ca, cb, ctx); nmod_mpoly_assert_canonical(cg, ctx); if (!res) { if (FLINT_BIT_COUNT(nmod_mpoly_ctx_modulus(ctx)) < 10) goto cleanup; flint_printf("FAIL: Check gcd of cofactors can be computed\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } if (!nmod_mpoly_is_one(cg, ctx)) { flint_printf("FAIL: Check gcd of cofactors is one\n"); flint_printf("i = %wd, j = %wd, %s\n", i, j, name); fflush(stdout); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } TEST_FUNCTION_START(nmod_mpoly_factor_gcd_zippel, state) { slong i, j, tmul = 20; { nmod_mpoly_ctx_t ctx; nmod_mpoly_t r, a, b, g; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, 1009); nmod_mpoly_init(r, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(a, "x1+x2+x3+1", NULL, ctx); nmod_mpoly_set_str_pretty(b, "x1+x2+x3+2", NULL, ctx); nmod_mpoly_set_str_pretty(g, "x1^3*(x3+1)*x4 + x1^2*(x3+1)*(x4+1) + x1*(x3+1)*(x3+2)*x2 + (x3^2+x3+2)*x4 + 1", NULL, ctx); nmod_mpoly_mul(a, a, g, ctx); nmod_mpoly_mul(b, b, g, ctx); gcd_check(r, a, b, g, ctx, -2, 0, "example"); nmod_mpoly_clear(r, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } { nmod_mpoly_ctx_t ctx; nmod_mpoly_t g, a, b, t; const char * vars[] = {"t" ,"z", "y", "x"}; nmod_mpoly_ctx_init(ctx, 4, ORD_LEX, 1000003); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(t, ctx); nmod_mpoly_set_str_pretty(t, "39 - t*x + 39*x^100 - t*x^101 + 39*x^3*y - t*x^4*y - 7*x^2*y^3*z^11 - 7*x^102*y^3*z^11 - 7*x^5*y^4*z^11 + 78*t^15*x^78*y^3*z^13 - 2*t^16*x^79*y^3*z^13 + x^1000*y^3*z^20 + x^1100*y^3*z^20 + x^1003*y^4*z^20 - 14*t^15*x^80*y^6*z^24 + 2*t^15*x^1078*y^6*z^33", vars, ctx); nmod_mpoly_set_str_pretty(a, "39 - t*x - 7*x^2*y^3*z^11 + x^1000*y^3*z^20", vars, ctx); nmod_mpoly_set_str_pretty(b, "1 + x^100 + x^3*y + 2*t^15*x^78*y^3*z^13", vars, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); gcd_check(g, a, b, t, ctx, -2, 1, "example"); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } { nmod_mpoly_ctx_t ctx; nmod_mpoly_t r, d, f, g; const char* vars[] = {"x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"}; const char * example[][3] = {{ "x1^2 + x1 + 3", "2*x1^2 + 2*x1 + 1", "x1^2 + 2*x1 + 2" }, { "2*x1^2*x2^2 + x1*x2 + 2*x1", "x2^2 + 2*x1^2*x2 + x1^2 + 1", "x1^2*x2^2 + x1^2*x2 + x1*x2 + x1^2 + x1" }, { "x2^2*x3^2 + x2^2*x3 + 2*x1^2*x2*x3 + x1*x3", "x3^2 + x2^2*x3 + x1^2*x2*x3 + x1*x3 + x1^2*x2^2", "x2*x3 + 2*x1*x3 + x3 + x1" }, { "x1^2*x4^2 + x2^2*x3*x4 + x1^2*x2*x4 + x2*x4 + x1^2*x2*x3", "x1*x2*x3^2*x4^2 + x1*x3^2*x4^2 + x1*x4^2 + x4^2 + x1*x3*x4", "x1*x3^2*x4^2 + x3^2*x4^2 + x4^2 + x1*x2^2*x3*x4 + x1*x2^2" }, { "x1^3*x2^2*x3^2*x4*x5^2 + x1*x2^2*x5^2 + x1^3*x3*x4^2*x5" " + x1^3*x2*x3^2*x4*x5 + x1^2*x2*x3^2*x4^2" , "x1*x2^2*x5^2 + x1*x2*x3^2*x4*x5 + x1*x2*x3^2*x4^2" " + x1*x2^2*x4^2 + 1" , "x1*x3^2*x4*x5^2 + x2*x5^2 + x1*x2*x4*x5 + x2*x5 + x1*x2*x3*x4^2" }, { "x1*x2*x4^2*x5^2*x6^2 + x1*x2^2*x3^2*x4*x5^2*x6^2 + x1^2*x3*x6^2" " + x1^2*x2*x3^2*x4*x5^2*x6 + x1^2*x3*x5*x6" , "x1^2*x2*x4*x5^2*x6^2 + x1*x3*x5^2*x6^2 + x1*x2^2*x6^2" " + x1^2*x2^2*x3^2*x5*x6 + x1*x3^2*x4*x5" , "x2^2*x3^2*x4*x5^2*x6 + x1*x4^2*x5*x6 + x2^2*x3^2*x4*x5*x6" " + x1*x2^2*x3*x4^2*x6 + x1^2*x3*x5^2" }, { "x1*x2^2*x4^2*x6^2*x7^2 + x1^2*x3*x4*x6^2*x7^2 + x3^2*x4^2*x7^2" " + x1^2*x2*x4^2*x6 + x3*x4*x5^2" , "x1^2*x2*x4^2*x5*x6^2*x7^2 + x1*x2*x3*x6*x7 + x3*x4^2*x5^2*x7" " + x1*x4^2*x5^2*x7 + x1^2*x2*x3*x4^2+x5*x6" , "x1*x3*x5*x6^2*x7^2 + x2^2*x3^2*x4^2*x5*x6*x7^2 + x4*x6*x7^2" " + x1^2*x2*x3*x5*x6*x7 + x1^2*x3^2*x4*x5^2" }, { "x2^2*x4*x5*x6*x7*x8^2 + x1^2*x2*x3^2*x4^2*x6^2*x7^2*x8" " + x1^2*x3*x4^2*x6^2*x7^2 + x1^2*x2^2*x3^2*x4*x5^2*x6*x7^2" " + x2^2*x4*x6" , "x1^2*x2^2*x3*x4^2*x5*x6^2*x8^2 + x2*x5*x6^2*x8^2" " + x1^2*x2^2*x3^2*x4^2*x6^2*x7^2*x8 + x1^2*x3^2*x4*x5^2*x7^2*x8" " + x1*x2^2*x3^2*x5^2*x7" , "x1*x4^2*x5*x6*x7*x8^2 + x1*x2^2*x4^2*x5^2*x6^2*x8" " + x1^2*x2*x3*x4^2*x6^2*x8 + x1^2*x2^2*x3^2*x4*x5^2*x8" " + x1*x2*x4^2*x5^2" }, { "x1^2*x3^3*x4*x6*x8*x9^2 + x1*x2*x3*x4^2*x5^2*x8*x9" " + x2*x3*x4*x5^2*x8*x9 + x1*x3^3*x4^2*x5^2*x6^2*x7*x8^2" " + x2*x3*x4*x5^2*x6*x7*x8^2" , "x1^2*x2^2*x3*x7^2*x8*x9 + x2^2*x9 + x1^2*x3*x4^2*x5^2*x6*x7^2" " + x4^2*x5^2*x7^2 + x3*x4^2*x6*x7" , "x1^2*x2*x4*x5*x6*x7^2*x8^2*x9^2 + x1^2*x2*x3*x5*x6^2*x7^2*x8*x9^2" " + x1^2*x3*x4*x6*x7^2*x8*x9 + x1^2*x2^2*x6*x8^2" " + x2^2*x4*x5*x6^2*x7" }, { "x1*x2^2*x4^2*x8*x9^2*x10^2 + x2^2*x4*x5^2*x6*x7*x9*x10^2" " + x1^2*x2*x3*x5^2*x7^2*x9^2 + x1*x3^2*x4^2*x7^2*x9^2" " + x1^2*x3*x4*x7^2*x8^2" , "x1*x2*x3^2*x4*x6*x7*x8*x9^2*x10^2 + x2^2*x3^2*x4^2*x6^2*x9*x10^2" " + x1*x2^2*x3^2*x4*x5*x6*x7*x8^2*x9^2*x10" " + x1^2*x2*x4^2*x5^2*x8^2*x9^2*x10 + x3*x4^2*x5*x6*x7^2*x9*x10" , "x1*x2^2*x3^2*x5^2*x6^2*x7*x8*x9^2*x10^2 + x3*x8*x9^2*x10^2" " + x1*x2^2*x3*x4*x5^2*x6^2*x8^2*x9*x10 + x1*x3*x6*x7*x8*x10" " + x4^2*x5^2*x6^2*x7*x9^2" }}; for (i = 1; i <= 10; i++) { nmod_mpoly_ctx_init(ctx, i, ORD_DEGREVLEX, 1009); nmod_mpoly_init(r, ctx); nmod_mpoly_init(d, ctx); nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_set_str_pretty(d, example[i - 1][0], vars, ctx); nmod_mpoly_set_str_pretty(f, example[i - 1][1], vars, ctx); nmod_mpoly_set_str_pretty(g, example[i - 1][2], vars, ctx); nmod_mpoly_mul(f, f, d, ctx); nmod_mpoly_mul(g, g, d, ctx); nmod_mpoly_randtest_bits(r, state, 10, FLINT_BITS, ctx); gcd_check(r, f, g, d, ctx, -1, i, "example"); nmod_mpoly_clear(r, ctx); nmod_mpoly_clear(d, ctx); nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } } for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, b, g, t; slong len, len1, len2; slong degbound; mp_limb_t p; p = n_randint(state, (i % 2 == 0) ? 10 : FLINT_BITS - 1) + 1; p = n_randbits(state, p); p = n_nextprime(p, 1); nmod_mpoly_ctx_init_rand(ctx, state, 10, p); nmod_mpoly_init(g, ctx); nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx); nmod_mpoly_init(t, ctx); len = n_randint(state, 30) + 1; len1 = n_randint(state, 30) + 1; len2 = n_randint(state, 30) + 1; degbound = 2 + 150/(2*ctx->minfo->nvars - 1); for (j = 0; j < 4; j++) { nmod_mpoly_randtest_bound(a, state, len1, degbound, ctx); nmod_mpoly_randtest_bound(b, state, len2, degbound, ctx); nmod_mpoly_randtest_bound(t, state, len, degbound, ctx); if (nmod_mpoly_is_zero(t, ctx)) nmod_mpoly_one(t, ctx); nmod_mpoly_mul(a, a, t, ctx); nmod_mpoly_mul(b, b, t, ctx); nmod_mpoly_randtest_bits(g, state, len, FLINT_BITS, ctx); gcd_check(g, a, b, t, ctx, i, j, "sparse"); } nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx); nmod_mpoly_clear(t, ctx); nmod_mpoly_ctx_clear(ctx); } TEST_FUNCTION_END(state); } #undef compute_gcd #undef gcd_check flint-3.1.3/src/nmod_mpoly_factor/zip_helpers.c000066400000000000000000000203331461254215100216260ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpoly.h" #include "nmod_mpoly_factor.h" /* evaluation at gen(start) -> alpha[0] gen(start+1) -> alpha[1] ... gen(stop-1) -> alpha[stop-start-1] the other gen are assumed to not appear in A alpha[i] is represented by alpha_caches[3*i], ..., alpha_caches[3*i+2] */ void mpoly_monomial_evals_nmod( n_poly_t EH, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, n_poly_struct * alpha_caches, slong start, slong stop, const mpoly_ctx_t mctx, const nmod_t fpctx) { slong i, k; mp_limb_t * p; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; slong num = stop - start; TMP_INIT; TMP_START; off = TMP_ARRAY_ALLOC(2*num, slong); shift = off + num; for (k = 0; k < num; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k + start, Abits, mctx); n_poly_fit_length(EH, Alen); EH->length = Alen; p = EH->coeffs; for (i = 0; i < Alen; i++) { p[i] = 1; for (k = 0; k < num; k++) { ulong ei = (Aexps[N*i + off[k]] >> shift[k]) & mask; p[i] = nmod_pow_cache_mulpow_ui(p[i], ei, alpha_caches + 3*k + 0, alpha_caches + 3*k + 1, alpha_caches + 3*k + 2, fpctx); } } TMP_END; } /* evaluation at gen(0) -> x gen(1) -> alpha[0] gen(2) -> alpha[1] gen(3) -> alpha[2] ... gen(m-1) -> alpha[m-2] the univariate marks should be filled in by mpoly1_fill_marks alpha[i] is represented by alpha_caches[3*i], ..., alpha_caches[3*i+2] */ void mpoly1_monomial_evals_nmod( n_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, const ulong * Amarks, slong Amarkslen, n_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const nmod_t fpctx) { slong start, stop, i, j, k, n; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; mp_limb_t * p; TMP_INIT; FLINT_ASSERT(1 < m && m <= mctx->nvars); FLINT_ASSERT(Amarkslen > 0); TMP_START; off = TMP_ARRAY_ALLOC(2*m, slong); shift = off + m; for (k = 0; k < m; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k, Abits, mctx); n_polyun_fit_length(EH, Amarkslen); for (i = 0; i < Amarkslen; i++) { start = Amarks[i]; stop = Amarks[i + 1]; FLINT_ASSERT(start < stop); n = stop - start; EH->exps[i] = (Aexps[N*start + off[0]] >> shift[0]) & mask; n_poly_fit_length(EH->coeffs + i, n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; for (j = 0; j < n; j++) { p[j] = 1; for (k = 1; k < m; k++) { ulong ei = (Aexps[N*(start + j) + off[k]] >> shift[k]) & mask; p[j] = nmod_pow_cache_mulpow_ui(p[j], ei, alpha_caches + 3*(k - 1) + 0, alpha_caches + 3*(k - 1) + 1, alpha_caches + 3*(k - 1) + 2, fpctx); } } } EH->length = Amarkslen; TMP_END; } /* evaluation at gen(0) -> x gen(1) -> y gen(2) -> alpha[0] gen(3) -> alpha[1] ... gen(m-1) -> alpha[m-3] the bivariate marks should be filled in by mpoly2_fill_marks alpha[i] is represented by alpha_caches[3*i], ..., alpha_caches[3*i+2] */ void mpoly2_monomial_evals_nmod( n_polyun_t EH, const ulong * Aexps, flint_bitcnt_t Abits, ulong * Amarks, slong Amarkslen, n_poly_struct * alpha_caches, slong m, const mpoly_ctx_t mctx, const nmod_t fpctx) { slong start, stop, i, j, k, n; ulong e0, e1; ulong mask = (-UWORD(1)) >> (FLINT_BITS - Abits); slong N = mpoly_words_per_exp_sp(Abits, mctx); slong * off, * shift; mp_limb_t * p; TMP_INIT; FLINT_ASSERT(2 < m && m <= mctx->nvars); FLINT_ASSERT(Amarkslen > 0); TMP_START; off = TMP_ARRAY_ALLOC(2*m, slong); shift = off + m; for (k = 0; k < m; k++) mpoly_gen_offset_shift_sp(&off[k], &shift[k], k, Abits, mctx); n_polyun_fit_length(EH, Amarkslen); for (i = 0; i < Amarkslen; i++) { start = Amarks[i]; stop = Amarks[i + 1]; FLINT_ASSERT(start < stop); n = stop - start; e0 = (Aexps[N*start + off[0]] >> shift[0]) & mask; e1 = (Aexps[N*start + off[1]] >> shift[1]) & mask; EH->exps[i] = pack_exp2(e0, e1); n_poly_fit_length(EH->coeffs + i, n); EH->coeffs[i].length = n; p = EH->coeffs[i].coeffs; for (j = 0; j < n; j++) { p[j] = 1; for (k = 2; k < m; k++) { ulong ei = (Aexps[N*(start + j) + off[k]] >> shift[k]) & mask; p[j] = nmod_pow_cache_mulpow_ui(p[j], ei, alpha_caches + 3*(k - 2) + 0, alpha_caches + 3*(k - 2) + 1, alpha_caches + 3*(k - 2) + 2, fpctx); } } } EH->length = Amarkslen; TMP_END; } void n_polyun_zip_start(n_polyun_t Z, n_polyun_t H, slong req_images) { slong j; n_polyun_fit_length(Z, H->length); Z->length = H->length; for (j = 0; j < H->length; j++) { Z->exps[j] = H->exps[j]; n_poly_fit_length(Z->coeffs + j, req_images); Z->coeffs[j].length = 0; } } int n_polyu2n_add_zip_must_match( n_polyun_t Z, const n_bpoly_t A, slong cur_length) { slong i, Ai, ai; const n_poly_struct * Acoeffs = A->coeffs; Ai = A->length - 1; ai = (Ai < 0) ? 0 : n_poly_degree(A->coeffs + Ai); for (i = 0; i < Z->length; i++) { if (Ai >= 0 && Z->exps[i] == pack_exp2(Ai, ai)) { /* Z present, A present */ Z->coeffs[i].coeffs[cur_length] = Acoeffs[Ai].coeffs[ai]; Z->coeffs[i].length = cur_length + 1; do { ai--; } while (ai >= 0 && Acoeffs[Ai].coeffs[ai] == 0); if (ai < 0) { do { Ai--; } while (Ai >= 0 && Acoeffs[Ai].length == 0); if (Ai >= 0) ai = n_poly_degree(Acoeffs + Ai); } } else if (Ai < 0 || Z->exps[i] > pack_exp2(Ai, ai)) { /* Z present, A missing */ Z->coeffs[i].coeffs[cur_length] = 0; Z->coeffs[i].length = cur_length + 1; } else { /* Z missing, A present */ return 0; } } return 1; } int n_polyun_zip_solve( nmod_mpoly_t A, n_polyun_t Z, n_polyun_t H, n_polyun_t M, const nmod_mpoly_ctx_t ctx) { int success; slong Ai, i, n; mp_limb_t * Acoeffs = A->coeffs; n_poly_t t; n_poly_init(t); FLINT_ASSERT(Z->length == H->length); FLINT_ASSERT(Z->length == M->length); Ai = 0; for (i = 0; i < H->length; i++) { n = H->coeffs[i].length; FLINT_ASSERT(M->coeffs[i].length == n + 1); FLINT_ASSERT(Z->coeffs[i].length >= n); FLINT_ASSERT(Ai + n <= A->length); n_poly_fit_length(t, n); success = _nmod_zip_vand_solve(Acoeffs + Ai, H->coeffs[i].coeffs, n, Z->coeffs[i].coeffs, Z->coeffs[i].length, M->coeffs[i].coeffs, t->coeffs, ctx->mod); if (success < 1) { n_poly_clear(t); return success; } Ai += n; FLINT_ASSERT(Ai <= A->length); } FLINT_ASSERT(Ai == A->length); n_poly_clear(t); return 1; } flint-3.1.3/src/nmod_poly.h000066400000000000000000001356331461254215100156060ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden Copyright (C) 2010, 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_POLY_H #define NMOD_POLY_H #ifdef NMOD_POLY_INLINES_C #define NMOD_POLY_INLINE #else #define NMOD_POLY_INLINE static inline #endif #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif #define NMOD_POLY_HGCD_CUTOFF 100 /* HGCD: Basecase -> Recursion */ #define NMOD_POLY_GCD_CUTOFF 340 /* GCD: Euclidean -> HGCD */ #define NMOD_POLY_SMALL_GCD_CUTOFF 200 /* GCD (small n): Euclidean -> HGCD */ typedef struct { mp_limb_t res; mp_limb_t lc; slong len0; slong len1; slong off; } nmod_poly_res_struct; typedef nmod_poly_res_struct nmod_poly_res_t[1]; typedef struct { nmod_mat_struct * A; nmod_poly_struct * poly1; nmod_poly_struct * poly2; nmod_poly_struct * poly2inv; } nmod_poly_matrix_precompute_arg_t; typedef struct { nmod_mat_struct * A; nmod_poly_struct * res; nmod_poly_struct * poly1; nmod_poly_struct * poly3; nmod_poly_struct * poly3inv; } nmod_poly_compose_mod_precomp_preinv_arg_t; /* zn_poly helper functions ************************************************ Copyright (C) 2007, 2008 David Harvey */ NMOD_POLY_INLINE int signed_mpn_sub_n(mp_ptr res, mp_srcptr op1, mp_srcptr op2, slong n) { if (mpn_cmp(op1, op2, n) >= 0) { mpn_sub_n(res, op1, op2, n); return 0; } else { mpn_sub_n(res, op2, op1, n); return 1; } } /* Memory management ********************************************************/ void nmod_poly_init(nmod_poly_t poly, mp_limb_t n); void nmod_poly_init_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv); void nmod_poly_init2(nmod_poly_t poly, mp_limb_t n, slong alloc); void nmod_poly_init2_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv, slong alloc); void nmod_poly_realloc(nmod_poly_t poly, slong alloc); void nmod_poly_clear(nmod_poly_t poly); void nmod_poly_fit_length(nmod_poly_t poly, slong alloc); NMOD_POLY_INLINE void nmod_poly_init_mod(nmod_poly_t poly, const nmod_t mod) { poly->coeffs = NULL; poly->alloc = 0; poly->length = 0; poly->mod = mod; } NMOD_POLY_INLINE void nmod_poly_set_mod(nmod_poly_t poly, const nmod_t mod) { poly->mod = mod; } NMOD_POLY_INLINE void _nmod_poly_set_length(nmod_poly_t poly, slong len) { poly->length = len; } NMOD_POLY_INLINE void _nmod_poly_normalise(nmod_poly_t poly) { while (poly->length && (poly->coeffs[poly->length - 1] == WORD(0))) poly->length--; } /* Polynomial parameters ****************************************************/ NMOD_POLY_INLINE slong nmod_poly_length(const nmod_poly_t poly) { return poly->length; } NMOD_POLY_INLINE slong nmod_poly_degree(const nmod_poly_t poly) { return poly->length - 1; } NMOD_POLY_INLINE mp_limb_t nmod_poly_modulus(const nmod_poly_t poly) { return poly->mod.n; } flint_bitcnt_t nmod_poly_max_bits(const nmod_poly_t poly); NMOD_POLY_INLINE mp_ptr nmod_poly_lead(const nmod_poly_t poly) { if (poly->length) return poly->coeffs + (poly->length - 1); else return NULL; } /* Assignment and basic manipulation ****************************************/ NMOD_POLY_INLINE void nmod_poly_set(nmod_poly_t a, const nmod_poly_t b) { if (a != b) { nmod_poly_fit_length(a, b->length); flint_mpn_copyi(a->coeffs, b->coeffs, b->length); a->length = b->length; } } NMOD_POLY_INLINE void nmod_poly_swap(nmod_poly_t poly1, nmod_poly_t poly2) { FLINT_SWAP(nmod_poly_struct, *poly1, *poly2); } NMOD_POLY_INLINE void nmod_poly_zero(nmod_poly_t res) { res->length = 0; } NMOD_POLY_INLINE void nmod_poly_one(nmod_poly_t res) { nmod_poly_fit_length(res, 1); res->length = (res->mod.n != UWORD(1)); res->coeffs[0] = 1; } void nmod_poly_set_trunc(nmod_poly_t res, const nmod_poly_t poly, slong len); NMOD_POLY_INLINE void nmod_poly_truncate(nmod_poly_t poly, slong len) { nmod_poly_set_trunc(poly, poly, len); } void _nmod_poly_reverse(mp_ptr output, mp_srcptr input, slong len, slong m); void nmod_poly_reverse(nmod_poly_t output, const nmod_poly_t input, slong m); /* Comparison ***************************************************************/ int nmod_poly_equal(const nmod_poly_t a, const nmod_poly_t b); int nmod_poly_equal_nmod(const nmod_poly_t poly, ulong cst); int nmod_poly_equal_ui(const nmod_poly_t poly, ulong cst); int nmod_poly_equal_trunc(const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); NMOD_POLY_INLINE int nmod_poly_is_zero(const nmod_poly_t poly) { return (poly->length == 0); } NMOD_POLY_INLINE int nmod_poly_is_one(const nmod_poly_t poly) { return (poly->mod.n == 0) || (poly->length == 1 && poly->coeffs[0] == 1); } /* bogus for non-prime modulus */ NMOD_POLY_INLINE int nmod_poly_is_unit(const nmod_poly_t poly) { return (poly->length == 1) && poly->coeffs[0] != 0; } NMOD_POLY_INLINE int nmod_poly_is_gen(const nmod_poly_t poly) { return (poly->mod.n == 0) || (poly->length == 2 && poly->coeffs[0] == 0 && poly->coeffs[1] == 1); } NMOD_POLY_INLINE int nmod_poly_is_monic(const nmod_poly_t poly) { return (poly->length && poly->coeffs[(poly->length - 1)] == 1); } /* Randomisation ************************************************************/ void nmod_poly_randtest(nmod_poly_t poly, flint_rand_t state, slong len); NMOD_POLY_INLINE void nmod_poly_randtest_not_zero(nmod_poly_t poly, flint_rand_t state, slong len) { do { nmod_poly_randtest(poly, state, len); } while (nmod_poly_is_zero(poly)); } void nmod_poly_randtest_irreducible(nmod_poly_t poly, flint_rand_t state, slong len); void nmod_poly_randtest_monic(nmod_poly_t poly, flint_rand_t state, slong len); void nmod_poly_randtest_monic_irreducible(nmod_poly_t poly, flint_rand_t state, slong len); void nmod_poly_randtest_monic_primitive(nmod_poly_t poly, flint_rand_t state, slong len); void nmod_poly_randtest_trinomial(nmod_poly_t poly, flint_rand_t state, slong len); int nmod_poly_randtest_trinomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts); void nmod_poly_randtest_pentomial(nmod_poly_t poly, flint_rand_t state, slong len); int nmod_poly_randtest_pentomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts); void nmod_poly_randtest_sparse_irreducible(nmod_poly_t poly, flint_rand_t state, slong len); /* Getting and setting coefficients *****************************************/ NMOD_POLY_INLINE ulong nmod_poly_get_coeff_ui(const nmod_poly_t poly, slong j) { return (j >= poly->length) ? 0 : poly->coeffs[j]; } void nmod_poly_set_coeff_ui(nmod_poly_t poly, slong j, ulong c); /* Input and output *********************************************************/ char * nmod_poly_get_str(const nmod_poly_t poly); char * nmod_poly_get_str_pretty(const nmod_poly_t poly, const char * x); int nmod_poly_set_str(nmod_poly_t poly, const char * s); #ifdef FLINT_HAVE_FILE int nmod_poly_fprint(FILE * f, const nmod_poly_t poly); int nmod_poly_fprint_pretty(FILE * f, const nmod_poly_t a, const char * x); int nmod_poly_fread(FILE * f, nmod_poly_t poly); #endif int nmod_poly_print(const nmod_poly_t a); int nmod_poly_print_pretty(const nmod_poly_t a, const char * x); int nmod_poly_read(nmod_poly_t poly); /* Shifting *****************************************************************/ void _nmod_poly_shift_left(mp_ptr res, mp_srcptr poly, slong len, slong k); void nmod_poly_shift_left(nmod_poly_t res, const nmod_poly_t poly, slong k); void _nmod_poly_shift_right(mp_ptr res, mp_srcptr poly, slong len, slong k); void nmod_poly_shift_right(nmod_poly_t res, const nmod_poly_t poly, slong k); /* Addition and subtraction *************************************************/ void _nmod_poly_add(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); void nmod_poly_add(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); void nmod_poly_add_ui(nmod_poly_t res, const nmod_poly_t poly, ulong c); void nmod_poly_add_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); void _nmod_poly_sub(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); void nmod_poly_sub(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); void nmod_poly_sub_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); void nmod_poly_sub_ui(nmod_poly_t res, const nmod_poly_t poly, ulong c); void nmod_poly_neg(nmod_poly_t res, const nmod_poly_t poly1); /* Scalar multiplication and division ***************************************/ void nmod_poly_scalar_mul_nmod(nmod_poly_t res, const nmod_poly_t poly, mp_limb_t c); void nmod_poly_scalar_addmul_nmod(nmod_poly_t res, const nmod_poly_t poly, ulong c); void _nmod_poly_make_monic(mp_ptr output, mp_srcptr input, slong len, nmod_t mod); void nmod_poly_make_monic(nmod_poly_t output, const nmod_poly_t input); /* Bit packing and unpacking aand reduction **********************************/ void _nmod_poly_KS2_pack1(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r); void _nmod_poly_KS2_pack(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r); void _nmod_poly_KS2_unpack1(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); void _nmod_poly_KS2_unpack2(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); void _nmod_poly_KS2_unpack3(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); void _nmod_poly_KS2_unpack(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); void _nmod_poly_KS2_reduce(mp_ptr res, slong s, mp_srcptr op, slong n, ulong w, nmod_t mod); void _nmod_poly_KS2_recover_reduce1(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); void _nmod_poly_KS2_recover_reduce2(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); void _nmod_poly_KS2_recover_reduce2b(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); void _nmod_poly_KS2_recover_reduce3(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); void _nmod_poly_KS2_recover_reduce(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); void _nmod_poly_bit_pack(mp_ptr res, mp_srcptr poly, slong len, flint_bitcnt_t bits); void _nmod_poly_bit_unpack(mp_ptr res, slong len, mp_srcptr mpn, flint_bitcnt_t bits, nmod_t mod); void nmod_poly_bit_pack(fmpz_t f, const nmod_poly_t poly, flint_bitcnt_t bit_size); void nmod_poly_bit_unpack(nmod_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size); /* Multiplication ***********************************************************/ void _nmod_poly_mul_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); void nmod_poly_mul_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); void _nmod_poly_mullow_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong trunc, nmod_t mod); void nmod_poly_mullow_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc); void _nmod_poly_mulhigh_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong start, nmod_t mod); void nmod_poly_mulhigh_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong start); void _nmod_poly_mul_KS(mp_ptr out, mp_srcptr in1, slong len1, mp_srcptr in2, slong len2, flint_bitcnt_t bits, nmod_t mod); void nmod_poly_mul_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, flint_bitcnt_t bits); void _nmod_poly_mul_KS2(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod); void nmod_poly_mul_KS2(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); void _nmod_poly_mul_KS4(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod); void nmod_poly_mul_KS4(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); void _nmod_poly_mullow_KS(mp_ptr out, mp_srcptr in1, slong len1, mp_srcptr in2, slong len2, flint_bitcnt_t bits, slong n, nmod_t mod); void nmod_poly_mullow_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, flint_bitcnt_t bits, slong n); void _nmod_poly_mul(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); void nmod_poly_mul(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); void _nmod_poly_mullow(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong trunc, nmod_t mod); void nmod_poly_mullow(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc); void _nmod_poly_mulhigh(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod); void nmod_poly_mulhigh(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); void _nmod_poly_mulmod(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, mp_srcptr f, slong lenf, nmod_t mod); void nmod_poly_mulmod(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f); void _nmod_poly_mulmod_preinv(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod); void nmod_poly_mulmod_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f, const nmod_poly_t finv); int _nmod_poly_invmod(mp_limb_t *A, const mp_limb_t *B, slong lenB, const mp_limb_t *P, slong lenP, const nmod_t mod); int nmod_poly_invmod(nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t P); /* Powering *****************************************************************/ void _nmod_poly_pow_binexp(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod); void nmod_poly_pow_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e); void _nmod_poly_pow(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod); void nmod_poly_pow(nmod_poly_t res, const nmod_poly_t poly, ulong e); void _nmod_poly_pow_trunc_binexp(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod); void nmod_poly_pow_trunc_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc); void _nmod_poly_pow_trunc(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod); void nmod_poly_pow_trunc(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc); void nmod_poly_powmod_ui_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, const nmod_poly_t f); void _nmod_poly_powmod_ui_binexp(mp_ptr res, mp_srcptr poly, ulong e, mp_srcptr f, slong lenf, nmod_t mod); void nmod_poly_powmod_fmpz_binexp(nmod_poly_t res, const nmod_poly_t poly, fmpz_t e, const nmod_poly_t f); void _nmod_poly_powmod_fmpz_binexp(mp_ptr res, mp_srcptr poly, fmpz_t e, mp_srcptr f, slong lenf, nmod_t mod); void _nmod_poly_powmod_ui_binexp_preinv (mp_ptr res, mp_srcptr poly, ulong e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod); void nmod_poly_powmod_ui_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, ulong e, const nmod_poly_t f, const nmod_poly_t finv); void _nmod_poly_powmod_fmpz_binexp_preinv (mp_ptr res, mp_srcptr poly, fmpz_t e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod); void nmod_poly_powmod_fmpz_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, fmpz_t e, const nmod_poly_t f, const nmod_poly_t finv); void _nmod_poly_powmod_x_ui_preinv (mp_ptr res, ulong e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod); void nmod_poly_powmod_x_ui_preinv(nmod_poly_t res, ulong e, const nmod_poly_t f, const nmod_poly_t finv); void _nmod_poly_powmod_x_fmpz_preinv (mp_ptr res, fmpz_t e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod); void nmod_poly_powmod_x_fmpz_preinv(nmod_poly_t res, fmpz_t e, const nmod_poly_t f, const nmod_poly_t finv); void _nmod_poly_powers_mod_preinv_naive(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod); void nmod_poly_powers_mod_naive(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g); void _nmod_poly_powers_mod_preinv_threaded_pool(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod, thread_pool_handle * threads, slong num_threads); void _nmod_poly_powers_mod_preinv_threaded(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod); void nmod_poly_powers_mod_bsgs(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g); /* Division *****************************************************************/ void _nmod_poly_divrem_basecase_preinv1(mp_ptr Q, mp_ptr R, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, mp_limb_t invB, nmod_t mod); void _nmod_poly_divrem_basecase(mp_ptr Q, mp_ptr R, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod); void nmod_poly_divrem_basecase(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); void _nmod_poly_divrem(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_divrem(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); void _nmod_poly_div(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_div(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); void _nmod_poly_rem(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_rem(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); void _nmod_poly_divexact(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_divexact(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); void _nmod_poly_inv_series_basecase(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod); void nmod_poly_inv_series_basecase(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); void _nmod_poly_inv_series_newton(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod); void nmod_poly_inv_series_newton(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); void _nmod_poly_inv_series(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod); void nmod_poly_inv_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); void _nmod_poly_div_series_basecase(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, slong n, nmod_t mod); void nmod_poly_div_series_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n); void _nmod_poly_div_series(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, slong n, nmod_t mod); void nmod_poly_div_series(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n); void _nmod_poly_div_newton_n_preinv (mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_srcptr Binv, slong lenBinv, nmod_t mod); void nmod_poly_div_newton_n_preinv (nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t Binv); void _nmod_poly_divrem_newton_n_preinv (mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_srcptr Binv, slong lenBinv, nmod_t mod); void nmod_poly_divrem_newton_n_preinv(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t Binv); mp_limb_t _nmod_poly_div_root(mp_ptr Q, mp_srcptr A, slong len, mp_limb_t c, nmod_t mod); mp_limb_t nmod_poly_div_root(nmod_poly_t Q, const nmod_poly_t A, mp_limb_t c); /* Divisibility testing *****************************************************/ int _nmod_poly_divides_classical(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); int nmod_poly_divides_classical(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); int _nmod_poly_divides(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); int nmod_poly_divides(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); ulong nmod_poly_remove(nmod_poly_t f, const nmod_poly_t p); /* Derivative ***************************************************************/ void _nmod_poly_derivative(mp_ptr x_prime, mp_srcptr x, slong len, nmod_t mod); void nmod_poly_derivative(nmod_poly_t x_prime, const nmod_poly_t x); void _nmod_poly_integral(mp_ptr x_int, mp_srcptr x, slong len, nmod_t mod); void nmod_poly_integral(nmod_poly_t x_int, const nmod_poly_t x); /* Evaluation ***************************************************************/ mp_limb_t _nmod_poly_evaluate_nmod(mp_srcptr poly, slong len, mp_limb_t c, nmod_t mod); mp_limb_t nmod_poly_evaluate_nmod(const nmod_poly_t poly, mp_limb_t c); void _nmod_poly_evaluate_nmod_vec(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod); void nmod_poly_evaluate_nmod_vec(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n); void _nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod); void nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n); void _nmod_poly_evaluate_nmod_vec_fast_precomp(mp_ptr vs, mp_srcptr poly, slong plen, const mp_ptr * tree, slong len, nmod_t mod); void _nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod); void nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n); void nmod_mat_one_addmul(nmod_mat_t dest, const nmod_mat_t mat, mp_limb_t c); void nmod_poly_evaluate_mat_horner(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c); void nmod_poly_evaluate_mat_paterson_stockmeyer(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c); NMOD_POLY_INLINE void nmod_poly_evaluate_mat(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c) { if (poly->length < 5 || c->r * poly->length < 425) { nmod_poly_evaluate_mat_horner(dest, poly, c); } else { nmod_poly_evaluate_mat_paterson_stockmeyer(dest, poly, c); } } /* Subproduct tree **********************************************************/ mp_ptr * _nmod_poly_tree_alloc(slong len); void _nmod_poly_tree_free(mp_ptr * tree, slong len); void _nmod_poly_tree_build(mp_ptr * tree, mp_srcptr roots, slong len, nmod_t mod); /* Interpolation ************************************************************/ void _nmod_poly_interpolate_nmod_vec_newton(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod); void nmod_poly_interpolate_nmod_vec_newton(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); void _nmod_poly_interpolate_nmod_vec_barycentric(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod); void nmod_poly_interpolate_nmod_vec_barycentric(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); void _nmod_poly_interpolate_nmod_vec(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod); void nmod_poly_interpolate_nmod_vec(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); void nmod_poly_interpolate_nmod_vec_fast(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); void _nmod_poly_interpolate_nmod_vec_fast(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong len, nmod_t mod); void _nmod_poly_interpolate_nmod_vec_fast_precomp(mp_ptr poly, mp_srcptr ys, const mp_ptr * tree, mp_srcptr weights, slong len, nmod_t mod); void _nmod_poly_interpolation_weights(mp_ptr w, const mp_ptr * tree, slong len, nmod_t mod); /* Composition **************************************************************/ void _nmod_poly_compose_horner(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); void nmod_poly_compose_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); void _nmod_poly_compose(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); void nmod_poly_compose(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); /* obsolete implementation */ #define _nmod_poly_compose_divconquer _nmod_poly_compose #define nmod_poly_compose_divconquer nmod_poly_compose /* Taylor shift *************************************************************/ void _nmod_poly_taylor_shift_horner(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod); void nmod_poly_taylor_shift_horner(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c); void _nmod_poly_taylor_shift_convolution(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod); void nmod_poly_taylor_shift_convolution(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c); void _nmod_poly_taylor_shift(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod); void nmod_poly_taylor_shift(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c); /* Modular composition ******************************************************/ void _nmod_poly_compose_mod_brent_kung(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod); void nmod_poly_compose_mod_brent_kung(nmod_poly_t res, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t h); void _nmod_poly_reduce_matrix_mod_poly(nmod_mat_t A, const nmod_mat_t B, const nmod_poly_t f); void _nmod_poly_precompute_matrix(nmod_mat_t A, mp_srcptr poly1, mp_srcptr poly2, slong len2, mp_srcptr poly2inv, slong len2inv, nmod_t mod); void _nmod_poly_precompute_matrix_worker(void * arg_ptr); void nmod_poly_precompute_matrix(nmod_mat_t A, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly2inv); void _nmod_poly_compose_mod_brent_kung_precomp_preinv(mp_ptr res, mp_srcptr poly1, slong len1, const nmod_mat_t A, mp_srcptr poly3, slong len3, mp_srcptr poly3inv, slong len3inv, nmod_t mod); void _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr); void nmod_poly_compose_mod_brent_kung_precomp_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_mat_t A, const nmod_poly_t poly3, const nmod_poly_t poly3inv); void _nmod_poly_compose_mod_brent_kung_preinv(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, mp_srcptr poly3, slong len3, mp_srcptr poly3inv, slong len3inv, nmod_t mod); void nmod_poly_compose_mod_brent_kung_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3, const nmod_poly_t poly3inv); void _nmod_poly_compose_mod_brent_kung_vec_preinv(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong l, mp_srcptr g, slong glen, mp_srcptr poly, slong len, mp_srcptr polyinv,slong leninv, nmod_t mod); void nmod_poly_compose_mod_brent_kung_vec_preinv(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv); void _nmod_poly_compose_mod_brent_kung_vec_preinv_worker(void * arg_ptr); void nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv, thread_pool_handle * threads, slong num_threads); void _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool( nmod_poly_struct * res, const nmod_poly_struct * polys, slong lenpolys, slong l, mp_srcptr g, slong glen, mp_srcptr poly, slong len, mp_srcptr polyinv, slong leninv, nmod_t mod, thread_pool_handle * threads, slong num_threads); void nmod_poly_compose_mod_brent_kung_vec_preinv_threaded(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv); void _nmod_poly_compose_mod_horner(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod); void nmod_poly_compose_mod_horner(nmod_poly_t res, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t h); void _nmod_poly_compose_mod(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod); void nmod_poly_compose_mod(nmod_poly_t res, const nmod_poly_t f, const nmod_poly_t g, const nmod_poly_t h); /* Power series composition and reversion ************************************/ void _nmod_poly_compose_series(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod); void nmod_poly_compose_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); void _nmod_poly_revert_series(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod); void nmod_poly_revert_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); /* norms *********************************************************************/ NMOD_POLY_INLINE slong _nmod_poly_hamming_weight(mp_srcptr a, slong len) { slong i, sum = 0; for (i = 0; i < len; i++) sum += !(a[i] == 0); return sum; } NMOD_POLY_INLINE slong nmod_poly_hamming_weight(const nmod_poly_t A) { return _nmod_poly_hamming_weight(A->coeffs, A->length); } /* Greatest common divisor **************************************************/ slong _nmod_poly_gcd_euclidean(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_gcd_euclidean(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B); slong _nmod_poly_hgcd_recursive(mp_ptr *M, slong *lenM, mp_ptr A, slong *lenA, mp_ptr B, slong *lenB, mp_srcptr a, slong lena, mp_srcptr b, slong lenb, mp_ptr P, nmod_t mod, int flag, nmod_poly_res_t res); slong _nmod_poly_hgcd(mp_ptr *M, slong *lenM, mp_ptr A, slong *lenA, mp_ptr B, slong *lenB, mp_srcptr a, slong lena, mp_srcptr b, slong lenb, nmod_t mod); slong nmod_poly_hgcd_ref( nmod_poly_t m11, nmod_poly_t m12, nmod_poly_t m21, nmod_poly_t m22, nmod_poly_t A, nmod_poly_t B, const nmod_poly_t a, const nmod_poly_t b); slong nmod_poly_hgcd( nmod_poly_t m11, nmod_poly_t m12, nmod_poly_t m21, nmod_poly_t m22, nmod_poly_t A, nmod_poly_t B, const nmod_poly_t a, const nmod_poly_t b); slong _nmod_poly_gcd_hgcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_gcd_hgcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B); slong _nmod_poly_gcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_gcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B); slong _nmod_poly_xgcd_euclidean(mp_ptr res, mp_ptr s, mp_ptr t, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); void nmod_poly_xgcd_euclidean(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B); slong _nmod_poly_xgcd_hgcd(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_xgcd_hgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B); slong _nmod_poly_xgcd(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); void nmod_poly_xgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B); mp_limb_t _nmod_poly_resultant_euclidean(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); mp_limb_t nmod_poly_resultant_euclidean(const nmod_poly_t f, const nmod_poly_t g); mp_limb_t _nmod_poly_resultant_hgcd(mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); mp_limb_t nmod_poly_resultant_hgcd(const nmod_poly_t A, const nmod_poly_t B); mp_limb_t _nmod_poly_resultant(mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); mp_limb_t nmod_poly_resultant(const nmod_poly_t A, const nmod_poly_t B); slong _nmod_poly_gcdinv(mp_limb_t *G, mp_limb_t *S, const mp_limb_t *A, slong lenA, const mp_limb_t *B, slong lenB, const nmod_t mod); void nmod_poly_gcdinv(nmod_poly_t G, nmod_poly_t S, const nmod_poly_t A, const nmod_poly_t B); /* Discriminant **************************************************************/ mp_limb_t _nmod_poly_discriminant(mp_srcptr poly, slong len, nmod_t mod); mp_limb_t nmod_poly_discriminant(const nmod_poly_t f); /* Square roots **************************************************************/ void _nmod_poly_invsqrt_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_invsqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_sqrt_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_sqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n); int _nmod_poly_sqrt(mp_ptr s, mp_srcptr p, slong len, nmod_t mod); int nmod_poly_sqrt(nmod_poly_t b, const nmod_poly_t a); /* Power sums ****************************************************************/ void _nmod_poly_power_sums_naive(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod); void nmod_poly_power_sums_naive(nmod_poly_t res, const nmod_poly_t poly, slong n); void _nmod_poly_power_sums_schoenhage(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod); void nmod_poly_power_sums_schoenhage(nmod_poly_t res, const nmod_poly_t poly, slong n); void _nmod_poly_power_sums(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod); void nmod_poly_power_sums(nmod_poly_t res, const nmod_poly_t poly, slong n); void _nmod_poly_power_sums_to_poly_naive(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod); void nmod_poly_power_sums_to_poly_naive(nmod_poly_t res, const nmod_poly_t Q); void _nmod_poly_power_sums_to_poly_schoenhage(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod); void nmod_poly_power_sums_to_poly_schoenhage(nmod_poly_t res, const nmod_poly_t Q); void _nmod_poly_power_sums_to_poly(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod); void nmod_poly_power_sums_to_poly(nmod_poly_t res, const nmod_poly_t Q); /* Transcendental functions **************************************************/ void _nmod_poly_atan_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_atan_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_tan_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_tan_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_asin_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_asin_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_sin_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); void nmod_poly_sin_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_cos_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); void nmod_poly_cos_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_asinh_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_asinh_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_atanh_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_atanh_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_sinh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); void nmod_poly_sinh_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_cosh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); void nmod_poly_cosh_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_tanh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); void nmod_poly_tanh_series(nmod_poly_t g, const nmod_poly_t h, slong n); void _nmod_poly_log_series(mp_ptr res, mp_srcptr f, slong flen, slong n, nmod_t mod); void nmod_poly_log_series(nmod_poly_t res, const nmod_poly_t f, slong n); void _nmod_poly_exp_expinv_series(mp_ptr f, mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); void _nmod_poly_exp_series(mp_ptr f, mp_srcptr h, slong hlen, slong n, nmod_t mod); void nmod_poly_exp_series(nmod_poly_t f, const nmod_poly_t h, slong n); /* Special polynomials *******************************************************/ int _nmod_poly_conway(mp_ptr op, ulong prime, slong deg); ulong _nmod_poly_conway_rand(slong * degree, flint_rand_t state, int type); /* Products *****************************************************************/ void nmod_poly_product_roots_nmod_vec(nmod_poly_t poly, mp_srcptr xs, slong n); void _nmod_poly_product_roots_nmod_vec(mp_ptr poly, mp_srcptr xs, slong n, nmod_t mod); void _nmod_poly_split_rabin(nmod_poly_t a, nmod_poly_t b, const nmod_poly_t f, nmod_poly_t t, nmod_poly_t t2, flint_rand_t randstate); int nmod_poly_find_distinct_nonzero_roots(mp_limb_t * roots, const nmod_poly_t P); /* CRT ***********************************************************************/ /* instructions do A = B + I*(C - B) mod M */ typedef struct { slong a_idx; /* index of A */ slong b_idx; /* index of B */ slong c_idx; /* index of C */ nmod_poly_t idem; /* I */ nmod_poly_t modulus; /* M */ } _nmod_poly_multi_crt_prog_instr; typedef struct { _nmod_poly_multi_crt_prog_instr * prog; /* straight line program */ slong length; /* length of prog */ slong alloc; /* alloc of prog */ slong localsize; /* length of outputs required in nmod_poly_multi_crt_run */ slong temp1loc; /* index of temporary used in run */ slong temp2loc; /* index of another temporary used in run */ int good; /* the moduli are good for CRT, essentially relatively prime */ } nmod_poly_multi_crt_struct; typedef nmod_poly_multi_crt_struct nmod_poly_multi_crt_t[1]; void nmod_poly_multi_crt_init(nmod_poly_multi_crt_t CRT); int nmod_poly_multi_crt_precompute(nmod_poly_multi_crt_t CRT, const nmod_poly_struct * moduli, slong len); int nmod_poly_multi_crt_precompute_p(nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * moduli, slong len); void nmod_poly_multi_crt_precomp(nmod_poly_t output, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * values); void nmod_poly_multi_crt_precomp_p(nmod_poly_t output, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * values); int nmod_poly_multi_crt(nmod_poly_t output, const nmod_poly_struct * moduli, const nmod_poly_struct * values, slong len); void nmod_poly_multi_crt_clear(nmod_poly_multi_crt_t CRT); NMOD_POLY_INLINE slong _nmod_poly_multi_crt_local_size(const nmod_poly_multi_crt_t CRT) { return CRT->localsize; } void _nmod_poly_multi_crt_run(nmod_poly_struct * outputs, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * inputs); void _nmod_poly_multi_crt_run_p(nmod_poly_struct * outputs, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * inputs); /* Inflation and deflation ***************************************************/ ulong nmod_poly_deflation(const nmod_poly_t input); void nmod_poly_deflate(nmod_poly_t result, const nmod_poly_t input, ulong deflation); void nmod_poly_inflate(nmod_poly_t result, const nmod_poly_t input, ulong inflation); /* Characteristic polynomial and minimal polynomial */ /* FIXME: These should be moved to nmod_mat.h. */ void _nmod_mat_charpoly_berkowitz(mp_ptr p, const nmod_mat_t M, nmod_t mod); void nmod_mat_charpoly_berkowitz(nmod_poly_t p, const nmod_mat_t M); void nmod_mat_charpoly_danilevsky(nmod_poly_t p, const nmod_mat_t M); void nmod_mat_charpoly(nmod_poly_t p, const nmod_mat_t M); void nmod_mat_minpoly_with_gens(nmod_poly_t p, const nmod_mat_t X, ulong * P); void nmod_mat_minpoly(nmod_poly_t p, const nmod_mat_t M); /* Berlekamp-Massey Algorithm - see nmod_poly/berlekamp_massey.c for more info ************/ typedef struct { slong npoints; nmod_poly_t R0, R1; nmod_poly_t V0, V1; nmod_poly_t qt, rt; nmod_poly_t points; } nmod_berlekamp_massey_struct; typedef nmod_berlekamp_massey_struct nmod_berlekamp_massey_t[1]; void nmod_berlekamp_massey_init( nmod_berlekamp_massey_t B, mp_limb_t p); void nmod_berlekamp_massey_start_over( nmod_berlekamp_massey_t B); void nmod_berlekamp_massey_clear( nmod_berlekamp_massey_t B); void nmod_berlekamp_massey_set_prime( nmod_berlekamp_massey_t B, mp_limb_t p); void nmod_berlekamp_massey_print( const nmod_berlekamp_massey_t B); void nmod_berlekamp_massey_add_points( nmod_berlekamp_massey_t B, const mp_limb_t * a, slong count); void nmod_berlekamp_massey_add_zeros( nmod_berlekamp_massey_t B, slong count); void nmod_berlekamp_massey_add_point( nmod_berlekamp_massey_t B, mp_limb_t a); int nmod_berlekamp_massey_reduce( nmod_berlekamp_massey_t B); NMOD_POLY_INLINE const mp_limb_t * nmod_berlekamp_massey_points( const nmod_berlekamp_massey_t B) { return B->points->coeffs; } NMOD_POLY_INLINE slong nmod_berlekamp_massey_point_count( const nmod_berlekamp_massey_t B) { return B->points->length; } NMOD_POLY_INLINE const nmod_poly_struct * nmod_berlekamp_massey_V_poly( const nmod_berlekamp_massey_t B) { return B->V1; } NMOD_POLY_INLINE const nmod_poly_struct * nmod_berlekamp_massey_R_poly( const nmod_berlekamp_massey_t B) { return B->R1; } #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod_poly/000077500000000000000000000000001461254215100154225ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly/KS2_pack.c000066400000000000000000000063161461254215100171710ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 David Harvey (zn_poly) Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" /* Same as _nmod_poly_KS2_pack(), but requires b <= FLINT_BITS. */ void _nmod_poly_KS2_pack1(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r) { /* where to write the next limb */ mp_ptr dest = res; /* limb currently being filled */ mp_limb_t buf; /* number of bits used in buf; always in [0, FLINT_BITS) */ ulong buf_b, buf_b_old; /* write leading zero-padding */ while (k >= FLINT_BITS) { *dest++ = 0; k -= FLINT_BITS; } buf = 0; buf_b = k; for (; n > 0; n--, op += s) { /* put low bits of current input into buffer */ buf += *op << buf_b; buf_b_old = buf_b; buf_b += b; if (buf_b >= FLINT_BITS) { /* buffer is full; flush it */ *dest++ = buf; buf_b -= FLINT_BITS; /* put remaining bits of current input into buffer */ buf = buf_b_old ? (*op >> (FLINT_BITS - buf_b_old)) : 0; } } /* write last limb if it's non-empty */ if (buf_b) *dest++ = buf; /* zero-pad up to requested length */ if (r) { slong written = dest - res; for (; written < r; written++) *dest++ = 0; } } void _nmod_poly_KS2_pack(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r) { /* where to write the next limb */ mp_ptr dest = res; /* limb currently being filled */ mp_limb_t buf; /* number of bits used in buf; always in [0, FLINT_BITS) */ ulong buf_b, buf_b_old; if (b <= FLINT_BITS) { /* use specialised version if b is small enough */ _nmod_poly_KS2_pack1(res, op, n, s, b, k, r); return; } /* write leading zero-padding */ while (k >= FLINT_BITS) { *dest++ = 0; k -= FLINT_BITS; } buf = 0; buf_b = k; for (; n > 0; n--, op += s) { /* put low bits of current input into buffer */ buf += *op << buf_b; buf_b_old = buf_b; buf_b += b; if (buf_b >= FLINT_BITS) { /* buffer is full; flush it */ *dest++ = buf; buf_b -= FLINT_BITS; /* put remaining bits of current input into buffer */ buf = buf_b_old ? (*op >> (FLINT_BITS - buf_b_old)) : 0; /* write as many extra zeroes as necessary */ if (buf_b >= FLINT_BITS) { *dest++ = buf; buf = 0; buf_b -= FLINT_BITS; if (buf_b >= FLINT_BITS) { *dest++ = 0; buf_b -= FLINT_BITS; } } } } /* write last limb if it's non-empty */ if (buf_b) *dest++ = buf; /* zero-pad up to requested length */ if (r) { slong written = dest - res; for (; written < r; written++) *dest++ = 0; } } flint-3.1.3/src/nmod_poly/KS2_reduce.c000066400000000000000000000124351461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 David Harvey (zn_poly) Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" void _nmod_poly_KS2_reduce(mp_ptr res, slong s, mp_srcptr op, slong n, ulong w, nmod_t mod) { if (w == 1) { for (; n; n--, res += s, op++) NMOD_RED(*res, *op, mod); } else if (w == 2) { for (; n; n--, res += s, op += 2) NMOD2_RED2(*res, op[1], op[0], mod); } else /* w == 3 */ { for (; n; n--, res += s, op += 3) NMOD_RED3(*res, op[2], op[1], op[0], mod); } } /* Same as _nmod_poly_KS2_recover_reduce(), but requires 0 < 2 * b <= FLINT_BITS */ void _nmod_poly_KS2_recover_reduce1(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) { ulong mask = (UWORD(1) << b) - 1; /* (x0, x1) and (y0, y1) are two-digit windows into X and Y. */ ulong x1, x0 = *op1++; ulong y0, y1, borrow; op2 += n; y1 = *op2--; borrow = 0; /* plain reduction version */ for (; n; n--) { y0 = *op2--; x1 = *op1++; if (y0 < x0) y1--; NMOD_RED(*res, x0 + (y1 << b), mod); res += s; y1 += borrow; borrow = (x1 < y1); x1 -= y1; y1 = (y0 - x0) & mask; x0 = x1 & mask; } } /* Same as _nmod_poly_KS2_recover_reduce(), but requires FLINT_BITS < 2 * b < 2*FLINT_BITS */ void _nmod_poly_KS2_recover_reduce2(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) { /* The main loop is the same as in _nmod_poly_KS2_recover_reduce1(), but the modular reduction step needs to handle two input words. */ ulong mask = (UWORD(1) << b) - 1; ulong x1, x0 = *op1++; ulong y0, y1, borrow, b2; op2 += n; y1 = *op2--; borrow = 0; b2 = FLINT_BITS - b; /* plain reduction version */ for (; n; n--) { y0 = *op2--; x1 = *op1++; if (y0 < x0) y1--; NMOD2_RED2(*res, y1 >> b2, x0 + (y1 << b), mod); res += s; y1 += borrow; borrow = (x1 < y1); x1 -= y1; y1 = (y0 - x0) & mask; x0 = x1 & mask; } } /* Same as _nmod_poly_KS2_recover_reduce(), but requires b == FLINT_BITS */ void _nmod_poly_KS2_recover_reduce2b(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) { /* Basically the same code as _nmod_poly_KS2_recover_reduce2(), specialised for b == FLINT_BITS. */ ulong x1, x0 = *op1++; ulong y0, y1, borrow; op2 += n; y1 = *op2--; borrow = 0; /* plain reduction version */ for (; n; n--) { y0 = *op2--; x1 = *op1++; if (y0 < x0) y1--; NMOD2_RED2(*res, y1, x0, mod); res += s; y1 += borrow; borrow = (x1 < y1); x1 -= y1; y1 = y0 - x0; x0 = x1; } } /* Same as _nmod_poly_KS2_recover_reduce(), but requires 2 * FLINT_BITS < 2 * b <= 3 * FLINT_BITS. */ void _nmod_poly_KS2_recover_reduce3(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) { /* The main loop is the same as in zn_array_recover_reduce1(), but needs to operate on double-word quantities everywhere, i.e. we simulate double-word registers. The suffixes L and H stand for low and high words of each. */ ulong maskH = (UWORD(1) << (b - FLINT_BITS)) - 1; ulong x1L, x0L = *op1++; ulong x1H, x0H = *op1++; ulong y0H, y1H, y0L, y1L; ulong borrow, b1, b2; op2 += 2 * n + 1; y1H = *op2--; y1L = *op2--; borrow = 0; b1 = b - FLINT_BITS; b2 = 2 * FLINT_BITS - b; /* plain reduction version */ for (; n; n--) { y0H = *op2--; y0L = *op2--; x1L = *op1++; x1H = *op1++; if ((y0H < x0H) || (y0H == x0H && y0L < x0L)) y1H -= (y1L-- == 0); NMOD_RED3(*res, (y1H << b1) + (y1L >> b2), (y1L << b1) + x0H, x0L, mod); res += s; if (borrow) y1H += (++y1L == 0); borrow = ((x1H < y1H) || (x1H == y1H && x1L < y1L)); sub_ddmmss(x1H, x1L, x1H, x1L, y1H, y1L); sub_ddmmss(y1H, y1L, y0H, y0L, x0H, x0L); y1H &= maskH; x0L = x1L; x0H = x1H & maskH; } } /* Dispatches to one of the above routines depending on b. */ void _nmod_poly_KS2_recover_reduce(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod) { if (2 * b <= FLINT_BITS) _nmod_poly_KS2_recover_reduce1(res, s, op1, op2, n, b, mod); else if (b < FLINT_BITS) _nmod_poly_KS2_recover_reduce2(res, s, op1, op2, n, b, mod); else if (b == FLINT_BITS) _nmod_poly_KS2_recover_reduce2b(res, s, op1, op2, n, b, mod); else _nmod_poly_KS2_recover_reduce3(res, s, op1, op2, n, b, mod); } flint-3.1.3/src/nmod_poly/KS2_unpack.c000066400000000000000000000134431461254215100175330ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 David Harvey (zn_poly) Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" /* Same as _nmod_poly_KS2_unpack(), but requires b <= FLINT_BITS (i.e. writes one word per coefficient) */ void _nmod_poly_KS2_unpack1(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) { /* limb we're currently extracting bits from */ mp_limb_t buf = 0; /* number of bits currently in buf; always in [0, FLINT_BITS) */ ulong buf_b = 0; /* skip over k leading bits */ while (k >= FLINT_BITS) { k -= FLINT_BITS; op++; } if (k) { buf = *op++; buf >>= k; buf_b = FLINT_BITS - k; } if (b == FLINT_BITS) { /* various special cases */ if (buf_b) { for (; n > 0; n--) { /* we need bits from both sides of a limb boundary */ ulong temp = buf; buf = *op++; *res++ = temp + (buf << buf_b); buf >>= (FLINT_BITS - buf_b); } } else { for (; n > 0; n--) *res++ = *op++; } } else { ulong mask = (UWORD(1) << b) - 1; for (; n > 0; n--) { if (b <= buf_b) { /* buf contains all the bits we need */ *res++ = buf & mask; buf >>= b; buf_b -= b; } else { /* we need bits from both sides of a limb boundary */ ulong temp = buf; buf = *op++; *res++ = temp + ((buf << buf_b) & mask); buf >>= (b - buf_b); buf_b = FLINT_BITS - (b - buf_b); } } } } /* Same as _nmod_poly_KS2_unpack(), but requires FLINT_BITS < b <= 2 * FLINT_BITS (i.e. writes two words per coefficient) */ void _nmod_poly_KS2_unpack2(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) { /* limb we're currently extracting bits from */ mp_limb_t buf = 0; /* number of bits currently in buf; always in [0, FLINT_BITS) */ ulong buf_b = 0; /* skip over k leading bits */ while (k >= FLINT_BITS) { k -= FLINT_BITS; op++; } if (k) { buf = *op++; buf >>= k; buf_b = FLINT_BITS - k; } if (b == 2 * FLINT_BITS) { n *= 2; /* various special cases */ if (buf_b) { for (; n > 0; n--) { /* we need bits from both sides of a limb boundary */ ulong temp = buf; buf = *op++; *res++ = temp + (buf << buf_b); buf >>= (FLINT_BITS - buf_b); } } else { for (; n > 0; n--) *res++ = *op++; } } else { ulong mask; b -= FLINT_BITS; mask = (UWORD(1) << b) - 1; for (; n > 0; n--) { /* shunt one whole limb through first */ if (buf_b) { ulong temp = buf; buf = *op++; *res++ = temp + (buf << buf_b); buf >>= (FLINT_BITS - buf_b); } else *res++ = *op++; /* now handle the fractional limb */ if (b <= buf_b) { /* buf contains all the bits we need */ *res++ = buf & mask; buf >>= b; buf_b -= b; } else { /* we need bits from both sides of a limb boundary */ ulong temp = buf; buf = *op++; *res++ = temp + ((buf << buf_b) & mask); buf >>= (b - buf_b); buf_b = FLINT_BITS - (b - buf_b); } } } } /* Same as _nmod_poly_KS2_unpack(), but requires 2 * FLINT_BITS < b < 3 * FLINT_BITS (i.e. writes three words per coefficient) */ void _nmod_poly_KS2_unpack3(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) { /* limb we're currently extracting bits from */ mp_limb_t buf = 0; /* number of bits currently in buf; always in [0, FLINT_BITS) */ ulong buf_b = 0, mask; /* skip over k leading bits */ while (k >= FLINT_BITS) { k -= FLINT_BITS; op++; } if (k) { buf = *op++; buf >>= k; buf_b = FLINT_BITS - k; } b -= 2 * FLINT_BITS; mask = (UWORD(1) << b) - 1; for (; n > 0; n--) { /* shunt two whole limbs through first */ if (buf_b) { ulong temp = buf; buf = *op++; *res++ = temp + (buf << buf_b); buf >>= (FLINT_BITS - buf_b); temp = buf; buf = *op++; *res++ = temp + (buf << buf_b); buf >>= (FLINT_BITS - buf_b); } else { *res++ = *op++; *res++ = *op++; } /* now handle the fractional limb */ if (b <= buf_b) { /* buf contains all the bits we need */ *res++ = buf & mask; buf >>= b; buf_b -= b; } else { /* we need bits from both sides of a limb boundary */ ulong temp = buf; buf = *op++; *res++ = temp + ((buf << buf_b) & mask); buf >>= (b - buf_b); buf_b = FLINT_BITS - (b - buf_b); } } } void _nmod_poly_KS2_unpack(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k) { if (b <= FLINT_BITS) _nmod_poly_KS2_unpack1 (res, op, n, b, k); else if (b <= 2 * FLINT_BITS) _nmod_poly_KS2_unpack2 (res, op, n, b, k); else /* b < 3 * FLINT_BITS */ _nmod_poly_KS2_unpack3 (res, op, n, b, k); } flint-3.1.3/src/nmod_poly/add.c000066400000000000000000000025611461254215100163220ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_add(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { slong i, min = FLINT_MIN(len1, len2); _nmod_vec_add(res, poly1, poly2, min, mod); if (poly1 != res) /* copy any remaining coefficients from poly1 */ for (i = min; i < len1; i++) res[i] = poly1[i]; if (poly2 != res) /* copy any remaining coefficients from poly2 */ for (i = min; i < len2; i++) res[i] = poly2[i]; } void nmod_poly_add(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { slong max = FLINT_MAX(poly1->length, poly2->length); nmod_poly_fit_length(res, max); _nmod_poly_add(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); res->length = max; _nmod_poly_normalise(res); /* there may have been cancellation */ } flint-3.1.3/src/nmod_poly/add_series.c000066400000000000000000000017711461254215100176760ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void nmod_poly_add_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); nmod_poly_fit_length(res, max); _nmod_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); _nmod_poly_set_length(res, max); _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/add_ui.c000066400000000000000000000020101461254215100170040ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" void nmod_poly_add_ui(nmod_poly_t res, const nmod_poly_t poly, ulong c) { if (poly->length == 0) { if (c == 0) nmod_poly_zero(res); else { nmod_poly_fit_length(res, 1); nmod_poly_set_coeff_ui(res, 0, c); _nmod_poly_set_length(res, 1); } } else { if (c >= poly->mod.n) NMOD_RED(c, c, poly->mod); nmod_poly_set(res, poly); nmod_poly_set_coeff_ui(res, 0, nmod_add(res->coeffs[0], c, poly->mod)); _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/asin_series.c000066400000000000000000000021551461254215100200750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_asin_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_asin_series(g, h, hlen, n, ctx)); } void nmod_poly_asin_series(nmod_poly_t g, const nmod_poly_t h, slong n) { slong hlen = h->length; if (hlen > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_asin_series). Constant term != 0.\n"); } if (hlen <= 1 || n <= 1) { nmod_poly_zero(g); return; } nmod_poly_fit_length(g, n); _nmod_poly_asin_series(g->coeffs, h->coeffs, hlen, n, h->mod); _nmod_poly_set_length(g, n); _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/asinh_series.c000066400000000000000000000021621461254215100202430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_asinh_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_asinh_series(g, h, hlen, n, ctx)); } void nmod_poly_asinh_series(nmod_poly_t g, const nmod_poly_t h, slong n) { slong hlen = h->length; if (hlen > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_asinh_series). Constant term != 0.\n"); } if (hlen <= 1 || n <= 1) { nmod_poly_zero(g); return; } nmod_poly_fit_length(g, n); _nmod_poly_asinh_series(g->coeffs, h->coeffs, hlen, n, h->mod); _nmod_poly_set_length(g, n); _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/atan_series.c000066400000000000000000000021551461254215100200660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_atan_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_atan_series(g, h, hlen, n, ctx)); } void nmod_poly_atan_series(nmod_poly_t g, const nmod_poly_t h, slong n) { slong hlen = h->length; if (hlen > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_atan_series). Constant term != 0.\n"); } if (hlen <= 1 || n <= 1) { nmod_poly_zero(g); return; } nmod_poly_fit_length(g, n); _nmod_poly_atan_series(g->coeffs, h->coeffs, hlen, n, h->mod); _nmod_poly_set_length(g, n); _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/atanh_series.c000066400000000000000000000021621461254215100202340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_atanh_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_atanh_series(g, h, hlen, n, ctx)); } void nmod_poly_atanh_series(nmod_poly_t g, const nmod_poly_t h, slong n) { slong hlen = h->length; if (hlen > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_atanh_series). Constant term != 0.\n"); } if (hlen <= 1 || n <= 1) { nmod_poly_zero(g); return; } nmod_poly_fit_length(g, n); _nmod_poly_atanh_series(g->coeffs, h->coeffs, hlen, n, h->mod); _nmod_poly_set_length(g, n); _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/berlekamp_massey.c000066400000000000000000000211161461254215100211120ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod.h" #include "nmod_poly.h" /* typedef struct { slong npoints; nmod_poly_t R0, R1; nmod_poly_t V0, V1; nmod_poly_t qt, rt; temporaries nmod_poly_t points; } nmod_berlekamp_massey_struct; typedef nmod_berlekamp_massey_struct nmod_berlekamp_massey_t[1]; n = B->npoints is the number of points a_1, ..., a_n that have been added to the sequence. The polynomials A and S are then defined as A = x^n S = a_1*x^(n-1) + a_2*x^(n-2) + ... + a_n We maintain polynomials U0, V0, U1, V1 such that U0*A + V0*S = R0 deg(R0) >= n/2 U1*A + V1*S = R1 deg(R1) < n/2 where R0 and R1 are consecutive euclidean remainders and U0, V0, U1, V1 are the corresponding Bezout coefficients. Note that deg(U1) < deg(V1) = deg(A) - deg(R0) <= n/2 The U0 and U1 are not stored explicitly. The points a_1, ..., a_n are stored in B->points, which is used merely as a resizable array. The main usage of this function is the rational reconstruction of a series a1 a2 a3 -U1 --- + --- + --- + ... = ---- maybe x x^2 x^3 V1 It can be seen that a1 a2 an -U1 R1 --- + --- + ... --- = --- + ------- x x^2 x^n V1 V1*x^n Thus the error is O(1/x^(n+1)) iff deg(R1) < deg(V1). */ void nmod_berlekamp_massey_init( nmod_berlekamp_massey_t B, mp_limb_t p) { nmod_t fpctx; nmod_init(&fpctx, p); nmod_poly_init_mod(B->V0, fpctx); nmod_poly_init_mod(B->R0, fpctx); nmod_poly_one(B->R0); nmod_poly_init_mod(B->V1, fpctx); nmod_poly_one(B->V1); nmod_poly_init_mod(B->R1, fpctx); nmod_poly_init_mod(B->rt, fpctx); nmod_poly_init_mod(B->qt, fpctx); nmod_poly_init_mod(B->points, fpctx); B->npoints = 0; B->points->length = 0; } void nmod_berlekamp_massey_start_over( nmod_berlekamp_massey_t B) { B->npoints = 0; B->points->length = 0; nmod_poly_zero(B->V0); nmod_poly_one(B->R0); nmod_poly_one(B->V1); nmod_poly_zero(B->R1); } void nmod_berlekamp_massey_clear( nmod_berlekamp_massey_t B) { nmod_poly_clear(B->R0); nmod_poly_clear(B->R1); nmod_poly_clear(B->V0); nmod_poly_clear(B->V1); nmod_poly_clear(B->rt); nmod_poly_clear(B->qt); nmod_poly_clear(B->points); } /* setting the prime also starts over */ void nmod_berlekamp_massey_set_prime( nmod_berlekamp_massey_t B, mp_limb_t p) { nmod_t fpctx; nmod_init(&fpctx, p); nmod_poly_set_mod(B->V0, fpctx); nmod_poly_set_mod(B->R0, fpctx); nmod_poly_set_mod(B->V1, fpctx); nmod_poly_set_mod(B->R1, fpctx); nmod_poly_set_mod(B->rt, fpctx); nmod_poly_set_mod(B->qt, fpctx); nmod_poly_set_mod(B->points, fpctx); nmod_berlekamp_massey_start_over(B); } void nmod_berlekamp_massey_print( const nmod_berlekamp_massey_t B) { slong i; nmod_poly_print_pretty(B->V1, "#"); flint_printf(","); for (i = 0; i < B->points->length; i++) { flint_printf(" %wu", B->points->coeffs[i]); } } void nmod_berlekamp_massey_add_points( nmod_berlekamp_massey_t B, const mp_limb_t * a, slong count) { slong i; slong old_length = B->points->length; nmod_poly_fit_length(B->points, old_length + count); for (i = 0; i < count; i++) { B->points->coeffs[old_length + i] = a[i]; } B->points->length = old_length + count; } void nmod_berlekamp_massey_add_zeros( nmod_berlekamp_massey_t B, slong count) { slong i; slong old_length = B->points->length; nmod_poly_fit_length(B->points, old_length + count); for (i = 0; i < count; i++) { B->points->coeffs[old_length + i] = 0; } B->points->length = old_length + count; } void nmod_berlekamp_massey_add_point( nmod_berlekamp_massey_t B, mp_limb_t a) { slong old_length = B->points->length; nmod_poly_fit_length(B->points, old_length + 1); B->points->coeffs[old_length] = a; B->points->length = old_length + 1; } /* return 1 if reduction changed the master poly, 0 otherwise */ int nmod_berlekamp_massey_reduce( nmod_berlekamp_massey_t B) { slong i, l, k, queue_len, queue_lo, queue_hi; /* the points in B->points->coeffs[j] for queue_lo <= j < queue_hi need to be added to the internal polynomials. These are first reversed into rt. deg(rt) < queue_len. */ queue_lo = B->npoints; queue_hi = B->points->length; queue_len = queue_hi - queue_lo; FLINT_ASSERT(queue_len >= 0); nmod_poly_zero(B->rt); for (i = 0; i < queue_len; i++) { nmod_poly_set_coeff_ui(B->rt, queue_len - i - 1, B->points->coeffs[queue_lo + i]); } B->npoints = queue_hi; /* Ri = Ri * x^queue_len + Vi*rt */ nmod_poly_mul(B->qt, B->V0, B->rt); nmod_poly_shift_left(B->R0, B->R0, queue_len); nmod_poly_add(B->R0, B->R0, B->qt); nmod_poly_mul(B->qt, B->V1, B->rt); nmod_poly_shift_left(B->R1, B->R1, queue_len); nmod_poly_add(B->R1, B->R1, B->qt); /* now start reducing R0, R1 */ if (2*nmod_poly_degree(B->R1) < B->npoints) { /* already have deg(R1) < B->npoints/2 */ return 0; } /* one iteration of euclid to get deg(R0) >= B->npoints/2 */ nmod_poly_divrem(B->qt, B->rt, B->R0, B->R1); nmod_poly_swap(B->R0, B->R1); nmod_poly_swap(B->R1, B->rt); nmod_poly_mul(B->rt, B->qt, B->V1); nmod_poly_sub(B->qt, B->V0, B->rt); nmod_poly_swap(B->V0, B->V1); nmod_poly_swap(B->V1, B->qt); l = nmod_poly_degree(B->R0); FLINT_ASSERT(B->npoints <= 2*l && l < B->npoints); k = B->npoints - l; FLINT_ASSERT(0 <= k && k <= l); /* (l - k)/2 is the expected number of required euclidean iterations. Either branch is OK anytime. TODO: find cutoff */ if (l - k < 10) { while (B->npoints <= 2*nmod_poly_degree(B->R1)) { nmod_poly_divrem(B->qt, B->rt, B->R0, B->R1); nmod_poly_swap(B->R0, B->R1); nmod_poly_swap(B->R1, B->rt); nmod_poly_mul(B->rt, B->qt, B->V1); nmod_poly_sub(B->qt, B->V0, B->rt); nmod_poly_swap(B->V0, B->V1); nmod_poly_swap(B->V1, B->qt); } } else { slong sgnM; nmod_poly_t m11, m12, m21, m22, r0, r1, t0, t1; nmod_poly_init_mod(m11, B->V1->mod); nmod_poly_init_mod(m12, B->V1->mod); nmod_poly_init_mod(m21, B->V1->mod); nmod_poly_init_mod(m22, B->V1->mod); nmod_poly_init_mod(r0, B->V1->mod); nmod_poly_init_mod(r1, B->V1->mod); nmod_poly_init_mod(t0, B->V1->mod); nmod_poly_init_mod(t1, B->V1->mod); nmod_poly_shift_right(r0, B->R0, k); nmod_poly_shift_right(r1, B->R1, k); sgnM = nmod_poly_hgcd(m11, m12, m21, m22, t0, t1, r0, r1); /* multiply [[V0 R0] [V1 R1]] by M^(-1) on the left */ nmod_poly_mul(B->rt, m22, B->V0); nmod_poly_mul(B->qt, m12, B->V1); sgnM > 0 ? nmod_poly_sub(r0, B->rt, B->qt) : nmod_poly_sub(r0, B->qt, B->rt); nmod_poly_mul(B->rt, m11, B->V1); nmod_poly_mul(B->qt, m21, B->V0); sgnM > 0 ? nmod_poly_sub(r1, B->rt, B->qt) : nmod_poly_sub(r1, B->qt, B->rt); nmod_poly_swap(B->V0, r0); nmod_poly_swap(B->V1, r1); nmod_poly_mul(B->rt, m22, B->R0); nmod_poly_mul(B->qt, m12, B->R1); sgnM > 0 ? nmod_poly_sub(r0, B->rt, B->qt) : nmod_poly_sub(r0, B->qt, B->rt); nmod_poly_mul(B->rt, m11, B->R1); nmod_poly_mul(B->qt, m21, B->R0); sgnM > 0 ? nmod_poly_sub(r1, B->rt, B->qt) : nmod_poly_sub(r1, B->qt, B->rt); nmod_poly_swap(B->R0, r0); nmod_poly_swap(B->R1, r1); nmod_poly_clear(m11); nmod_poly_clear(m12); nmod_poly_clear(m21); nmod_poly_clear(m22); nmod_poly_clear(r0); nmod_poly_clear(r1); nmod_poly_clear(t0); nmod_poly_clear(t1); } FLINT_ASSERT(nmod_poly_degree(B->V1) >= 0); FLINT_ASSERT(2*nmod_poly_degree(B->V1) <= B->npoints); FLINT_ASSERT(2*nmod_poly_degree(B->R0) >= B->npoints); FLINT_ASSERT(2*nmod_poly_degree(B->R1) < B->npoints); return 1; } flint-3.1.3/src/nmod_poly/bit_pack.c000066400000000000000000000101711461254215100173420ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fmpz.h" /* Assumes length > 0, bits > 0. */ void _nmod_poly_bit_pack(mp_ptr res, mp_srcptr poly, slong len, flint_bitcnt_t bits) { slong i; ulong current_bit = 0, current_limb = 0; ulong total_limbs = (len * bits - 1) / FLINT_BITS + 1; mp_limb_t temp_lower, temp_upper; res[0] = WORD(0); if (bits < FLINT_BITS) { ulong boundary_limit_bit = FLINT_BITS - bits; for (i = 0; i < len; i++) { if (current_bit > boundary_limit_bit) { /* the coefficient will be added across a limb boundary */ temp_lower = (poly[i] << current_bit); temp_upper = (poly[i] >> (FLINT_BITS - current_bit)); res[current_limb] |= temp_lower; current_limb++; res[current_limb] = temp_upper; current_bit += bits - FLINT_BITS; } else { /* the coefficient will fit in the current limb */ temp_lower = poly[i] << current_bit; res[current_limb] |= temp_lower; current_bit += bits; if (current_bit == FLINT_BITS) { current_limb++; if (current_limb < total_limbs) res[current_limb] = WORD(0); current_bit = 0; } } } } else if (bits == FLINT_BITS) { for (i = 0; i < len; i++) res[i] = poly[i]; } else if (bits == 2 * FLINT_BITS) { for (i = 0; i < len; i++) { res[current_limb++] = poly[i]; res[current_limb++] = WORD(0); } } else if (bits < 2 * FLINT_BITS) { for (i = 0; i < len; i++) { /* the coefficient will be added across a limb boundary */ temp_lower = poly[i] << current_bit; temp_upper = r_shift(poly[i], FLINT_BITS - current_bit); res[current_limb++] |= temp_lower; res[current_limb] = temp_upper; current_bit += bits - FLINT_BITS; if (current_bit >= FLINT_BITS) { current_bit -= FLINT_BITS; current_limb++; if (current_limb < total_limbs) res[current_limb] = WORD(0); } } } else /* 2*FLINT_BITS < bits < 3*FLINT_BITS */ { for (i = 0; i < len; i++) { temp_lower = poly[i] << current_bit; temp_upper = r_shift(poly[i], FLINT_BITS - current_bit); res[current_limb++] |= temp_lower; res[current_limb++] = temp_upper; if (current_limb < total_limbs) res[current_limb] = WORD(0); current_bit += bits - 2 * FLINT_BITS; if (current_bit >= FLINT_BITS) { current_bit -= FLINT_BITS; current_limb++; if (current_limb < total_limbs) res[current_limb] = WORD(0); } } } } void nmod_poly_bit_pack(fmpz_t f, const nmod_poly_t poly, flint_bitcnt_t bit_size) { slong len, limbs; __mpz_struct * mpz; slong i; len = nmod_poly_length(poly); if (len == 0 || bit_size == 0) { fmpz_zero(f); return; } mpz = _fmpz_promote(f); mpz_realloc2(mpz, len * bit_size); limbs = (len * bit_size - 1) / FLINT_BITS + 1; _nmod_poly_bit_pack(mpz->_mp_d, poly->coeffs, len, bit_size); for (i = limbs - 1; i >= 0; i--) { if (mpz->_mp_d[i] != 0) break; } mpz->_mp_size = i + 1; _fmpz_demote_val(f); } flint-3.1.3/src/nmod_poly/bit_unpack.c000066400000000000000000000156541461254215100177200ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #include "fmpz.h" /* Assumes len > 0, bits > 0. */ void _nmod_poly_bit_unpack(mp_ptr res, slong len, mp_srcptr mpn, flint_bitcnt_t bits, nmod_t mod) { slong i; ulong current_bit = 0, current_limb = 0; mp_limb_t temp_lower, temp_upper, temp_upper2; if (bits < FLINT_BITS) { ulong boundary_limit_bit = FLINT_BITS - bits; mp_limb_t mask = (WORD(1) << bits) - WORD(1); for (i = 0; i < len; i++) { if (current_bit > boundary_limit_bit) { temp_lower = mpn[current_limb++] >> current_bit; temp_upper = mpn[current_limb] << (FLINT_BITS - current_bit); temp_upper |= temp_lower; temp_upper &= mask; NMOD_RED(res[i], temp_upper, mod); current_bit += bits - FLINT_BITS; } else { /* the coeff will fit in the current limb */ temp_upper = (mpn[current_limb] >> current_bit) & mask; NMOD_RED(res[i], temp_upper, mod); current_bit += bits; if (current_bit == FLINT_BITS) { current_bit = 0; current_limb++; } } } } else if (bits == FLINT_BITS) { for (i = 0; i < len; i++) NMOD_RED(res[i], mpn[i], mod); } else if (bits == 2 * FLINT_BITS) { for (i = 0; i < len; i++) { NMOD2_RED2(res[i], mpn[current_limb + 1], mpn[current_limb], mod); current_limb += 2; } } else if (bits < 2 * FLINT_BITS) /* FLINT_BITS < bits < 2*FLINT_BITS */ { ulong double_boundary_limit_bit = 2 * FLINT_BITS - bits; mp_limb_t mask = (WORD(1) << (bits - FLINT_BITS)) - WORD(1); for (i = 0; i < len; i++) { if (current_bit == 0) { temp_lower = mpn[current_limb++]; temp_upper = mpn[current_limb] & mask; NMOD2_RED2(res[i], temp_upper, temp_lower, mod); current_bit = bits - FLINT_BITS; } else if (current_bit > double_boundary_limit_bit) { /* the coeff will be across two limb boundaries */ temp_lower = mpn[current_limb++] >> current_bit; temp_lower |= (mpn[current_limb] << (FLINT_BITS - current_bit)); temp_upper = mpn[current_limb++] >> current_bit; temp_upper |= (mpn[current_limb] << (FLINT_BITS - current_bit)); temp_upper &= mask; NMOD2_RED2(res[i], temp_upper, temp_lower, mod); current_bit += bits - 2 * FLINT_BITS; } else { /* the coeff will be across one limb boundary */ temp_lower = (mpn[current_limb] >> current_bit) | (mpn[current_limb + 1] << (FLINT_BITS - current_bit)); current_limb++; temp_upper = mpn[current_limb] >> current_bit; temp_upper &= mask; NMOD2_RED2(res[i], temp_upper, temp_lower, mod); current_bit += bits - FLINT_BITS; if (current_bit == FLINT_BITS) { current_bit = 0; current_limb++; } } } } else /* 2*FLINT_BITS < bits < 3*FLINT_BITS */ { ulong double_boundary_limit_bit = 3 * FLINT_BITS - bits; mp_limb_t mask = (WORD(1) << (bits - 2 * FLINT_BITS)) - WORD(1); for (i = 0; i < len; i++) { if (current_bit == 0) { temp_lower = mpn[current_limb++]; temp_upper = mpn[current_limb++]; temp_upper2 = mpn[current_limb] & mask; NMOD_RED3(res[i], temp_upper2, temp_upper, temp_lower, mod); current_bit = bits - 2 * FLINT_BITS; } else if (current_bit <= double_boundary_limit_bit) { /* the coeff will be across two limb boundaries */ temp_lower = mpn[current_limb++] >> current_bit; temp_lower |= (mpn[current_limb] << (FLINT_BITS - current_bit)); temp_upper = mpn[current_limb++] >> current_bit; temp_upper |= (mpn[current_limb] << (FLINT_BITS - current_bit)); temp_upper2 = mpn[current_limb] >> current_bit; temp_upper2 &= mask; NMOD_RED3(res[i], temp_upper2, temp_upper, temp_lower, mod); current_bit += bits - 2 * FLINT_BITS; if (current_bit == FLINT_BITS) { current_bit = 0; current_limb++; } } else { /* the coeff will be across three limb boundaries */ temp_lower = mpn[current_limb++] >> current_bit; temp_lower |= (mpn[current_limb] << (FLINT_BITS - current_bit)); temp_upper = mpn[current_limb++] >> current_bit; temp_upper |= (mpn[current_limb] << (FLINT_BITS - current_bit)); temp_upper2 = mpn[current_limb++] >> current_bit; temp_upper2 |= (mpn[current_limb] << (FLINT_BITS - current_bit)); temp_upper2 &= mask; NMOD_RED3(res[i], temp_upper2, temp_upper, temp_lower, mod); current_bit += bits - 3 * FLINT_BITS; } } } } void nmod_poly_bit_unpack(nmod_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size) { slong len; mpz_t tmp; if (fmpz_sgn(f) < 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_bit_unpack). f < 0.\n"); } if (bit_size == 0 || fmpz_is_zero(f)) { nmod_poly_zero(poly); return; } len = (fmpz_bits(f) + bit_size - 1) / bit_size; mpz_init2(tmp, bit_size*len); flint_mpn_zero(tmp->_mp_d, tmp->_mp_alloc); fmpz_get_mpz(tmp, f); nmod_poly_fit_length(poly, len); _nmod_poly_bit_unpack(poly->coeffs, len, tmp->_mp_d, bit_size, poly->mod); poly->length = len; _nmod_poly_normalise(poly); mpz_clear(tmp); } flint-3.1.3/src/nmod_poly/clear.c000066400000000000000000000010331461254215100166510ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void nmod_poly_clear(nmod_poly_t poly) { if (poly->coeffs) flint_free(poly->coeffs); } flint-3.1.3/src/nmod_poly/compose.c000066400000000000000000000044331461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010, 2012 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_compose(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { if (len1 == 1) res[0] = poly1[0]; else if (len2 == 1) res[0] = _nmod_poly_evaluate_nmod(poly1, len1, poly2[0], mod); else if (len1 <= 7) _nmod_poly_compose_horner(res, poly1, len1, poly2, len2, mod); else { /* delegates to Taylor shift, divconquer */ /* todo: also incorporate the nmod_poly Taylor shift in gr_poly */ gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_compose(res, poly1, len1, poly2, len2, ctx)); } } void nmod_poly_compose(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { nmod_poly_zero(res); } else if (len1 == 1 || len2 == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = poly1->coeffs[0]; res->length = (res->coeffs[0] != 0); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { nmod_poly_fit_length(res, lenr); _nmod_poly_compose(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly1->mod.n, lenr); _nmod_poly_compose(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } res->length = lenr; _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/compose_horner.c000066400000000000000000000057551461254215100206240ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_compose_horner(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { if (len1 == 1) { res[0] = poly1[0]; } else if (len2 == 1) { res[0] = _nmod_poly_evaluate_nmod(poly1, len1, poly2[0], mod); } else if (len1 == 2) { _nmod_vec_scalar_mul_nmod(res, poly2, len2, poly1[1], mod); res[0] = n_addmod(res[0], poly1[0], mod.n); } else { const slong alloc = (len1 - 1) * (len2 - 1) + 1; slong i = len1 - 1, lenr = len2; mp_ptr t, t1, t2; TMP_INIT; TMP_START; t = TMP_ALLOC(alloc * sizeof(mp_limb_t)); if (len1 % 2 == 0) { t1 = res; t2 = t; } else { t1 = t; t2 = res; } /* Perform the first two steps as one, "res = a(m) * poly2 + a(m-1)". */ { _nmod_vec_scalar_mul_nmod(t1, poly2, len2, poly1[i], mod); i--; t1[0] = n_addmod(t1[0], poly1[i], mod.n); } while (i--) { _nmod_poly_mul(t2, t1, lenr, poly2, len2, mod); lenr += len2 - 1; FLINT_SWAP(mp_ptr, t1, t2); t1[0] = n_addmod(t1[0], poly1[i], mod.n); } TMP_END; } } void nmod_poly_compose_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; if (len1 == 0) { nmod_poly_zero(res); } else if (len1 == 1 || len2 == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = poly1->coeffs[0]; res->length = (res->coeffs[0] != 0); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { nmod_poly_fit_length(res, lenr); _nmod_poly_compose_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly1->mod.n, lenr); _nmod_poly_compose_horner(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } res->length = lenr; _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/compose_mod.c000066400000000000000000000041361461254215100200760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_compose_mod(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod) { if (lenh < 8 || lenf >= lenh) _nmod_poly_compose_mod_horner(res, f, lenf, g, h, lenh, mod); else _nmod_poly_compose_mod_brent_kung(res, f, lenf, g, h, lenh, mod); } void nmod_poly_compose_mod(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; mp_ptr ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_compose_mod). Division by zero.\n"); } if (len1 == 0 || len3 == 1) { nmod_poly_zero(res); return; } if (len1 == 1) { nmod_poly_set(res, poly1); return; } if (res == poly3 || res == poly1) { nmod_poly_t tmp; nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv); nmod_poly_compose_mod(tmp, poly1, poly2, poly3); nmod_poly_swap(tmp, res); nmod_poly_clear(tmp); return; } ptr2 = _nmod_vec_init(len); if (len2 <= len) { flint_mpn_copyi(ptr2, poly2->coeffs, len2); flint_mpn_zero(ptr2 + len2, len - len2); } else { _nmod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, res->mod); } nmod_poly_fit_length(res, len); _nmod_poly_compose_mod(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, res->mod); res->length = len; _nmod_poly_normalise(res); _nmod_vec_clear(ptr2); } flint-3.1.3/src/nmod_poly/compose_mod_brent_kung.c000066400000000000000000000072221461254215100223130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" void _nmod_poly_compose_mod_brent_kung(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, mp_srcptr poly3, slong len3, nmod_t mod) { nmod_mat_t A, B, C; mp_ptr t, h; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { res[0] = poly1[0]; return; } if (len3 == 2) { res[0] = _nmod_poly_evaluate_nmod(poly1, len1, poly2[0], mod); return; } m = n_sqrt(n) + 1; nmod_mat_init(A, m, n, mod.n); nmod_mat_init(B, m, m, mod.n); nmod_mat_init(C, m, n, mod.n); h = _nmod_vec_init(n); t = _nmod_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _nmod_vec_set(B->rows[i], poly1 + i*m, m); _nmod_vec_set(B->rows[i], poly1 + i*m, len1 % m); /* Set rows of A to powers of poly2 */ A->rows[0][0] = UWORD(1); _nmod_vec_set(A->rows[1], poly2, n); for (i = 2; i < m; i++) _nmod_poly_mulmod(A->rows[i], A->rows[i-1], n, poly2, n, poly3, len3, mod); nmod_mat_mul(C, B, A); /* Evaluate block composition using the Horner scheme */ _nmod_vec_set(res, C->rows[m - 1], n); _nmod_poly_mulmod(h, A->rows[m - 1], n, poly2, n, poly3, len3, mod); for (i = m - 2; i >= 0; i--) { _nmod_poly_mulmod(t, res, n, h, n, poly3, len3, mod); _nmod_poly_add(res, t, n, C->rows[i], n, mod); } _nmod_vec_clear(h); _nmod_vec_clear(t); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } void nmod_poly_compose_mod_brent_kung(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; mp_ptr ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung): Division by zero.\n"); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung): " "The degree of the first polynomial must be smaller than that of the modulus.\n"); } if (len1 == 0 || len3 == 1) { nmod_poly_zero(res); return; } if (len1 == 1) { nmod_poly_set(res, poly1); return; } if (res == poly3 || res == poly1) { nmod_poly_t tmp; nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv); nmod_poly_compose_mod_brent_kung(tmp, poly1, poly2, poly3); nmod_poly_swap(tmp, res); nmod_poly_clear(tmp); return; } ptr2 = _nmod_vec_init(len); if (len2 <= len) { flint_mpn_copyi(ptr2, poly2->coeffs, len2); flint_mpn_zero(ptr2 + len2, len - len2); } else { _nmod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, res->mod); } nmod_poly_fit_length(res, len); _nmod_poly_compose_mod_brent_kung(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, res->mod); res->length = len; _nmod_poly_normalise(res); _nmod_vec_clear(ptr2); } flint-3.1.3/src/nmod_poly/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000130001461254215100254120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" void _nmod_poly_reduce_matrix_mod_poly(nmod_mat_t A, const nmod_mat_t B, const nmod_poly_t f) { mp_ptr tmp1; slong n = f->length - 1; slong i, m = n_sqrt(n) + 1; nmod_mat_init(A, m, n, f->mod.n); tmp1 = _nmod_vec_init(B->c - f->length + 1); A->rows[0][0] = 1; for (i = 1; i < m; i++) _nmod_poly_divrem(tmp1, A->rows[i], B->rows[i], B->c, f->coeffs, f->length, f->mod); _nmod_vec_clear(tmp1); } void _nmod_poly_precompute_matrix(nmod_mat_t A, mp_srcptr poly1, mp_srcptr poly2, slong len2, mp_srcptr poly2inv, slong len2inv, nmod_t mod) { /* Set rows of A to powers of poly1 */ slong n, m; n = len2 - 1; m = n_sqrt(n) + 1; _nmod_poly_powers_mod_preinv_naive(A->rows, poly1, n, m, poly2, len2, poly2inv, len2inv, mod); } void nmod_poly_precompute_matrix(nmod_mat_t A, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly2inv) { slong len1 = poly1->length; slong len2 = poly2->length; slong len = len2 - 1; slong m = n_sqrt(len) + 1; mp_ptr ptr1; if (len2 == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_precompute_matrix). Division by zero.\n"); } if (A->r != m || A->c != len) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_precompute_matrix). Wrong dimensions.\n"); } if (len2 == 1) { nmod_mat_zero(A); return; } ptr1 = _nmod_vec_init(len); if (len1 <= len) { flint_mpn_copyi(ptr1, poly1->coeffs, len1); flint_mpn_zero(ptr1 + len1, len - len1); } else { _nmod_poly_rem(ptr1, poly1->coeffs, len1, poly2->coeffs, len2, A->mod); } _nmod_poly_precompute_matrix(A, ptr1, poly2->coeffs, len2, poly2inv->coeffs, poly2inv->length, A->mod); _nmod_vec_clear(ptr1); } void _nmod_poly_compose_mod_brent_kung_precomp_preinv(mp_ptr res, mp_srcptr poly1, slong len1, const nmod_mat_t A, mp_srcptr poly3, slong len3, mp_srcptr poly3inv, slong len3inv, nmod_t mod) { nmod_mat_t B, C; mp_ptr t, h; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { res[0] = poly1[0]; return; } if (len3 == 2) { res[0] = _nmod_poly_evaluate_nmod(poly1, len1, A->rows[1][0], mod); return; } m = n_sqrt(n) + 1; /* TODO check A*/ nmod_mat_init(B, m, m, mod.n); nmod_mat_init(C, m, n, mod.n); h = _nmod_vec_init(n); t = _nmod_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1/m; i++) _nmod_vec_set(B->rows[i], poly1 + i*m, m); _nmod_vec_set(B->rows[i], poly1 + i*m, len1%m); nmod_mat_mul(C, B, A); /* Evaluate block composition using the Horner scheme */ _nmod_vec_set(res, C->rows[m - 1], n); _nmod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly3, len3, poly3inv, len3inv,mod); for (i = m - 2; i >= 0; i--) { _nmod_poly_mulmod_preinv(t, res, n, h, n, poly3, len3, poly3inv, len3inv, mod); _nmod_poly_add(res, t, n, C->rows[i], n, mod); } _nmod_vec_clear(h); _nmod_vec_clear(t); nmod_mat_clear(B); nmod_mat_clear(C); } void nmod_poly_compose_mod_brent_kung_precomp_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_mat_t A, const nmod_poly_t poly3, const nmod_poly_t poly3inv) { slong len1 = poly1->length; slong len3 = poly3->length; slong len = len3 - 1; if (len3 == 0) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_precomp_preinv): Division by zero.\n"); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_precomp_preinv): " "The degree of the first polynomial must be smaller than that of the modulus.\n"); } if (len1 == 0 || len3 == 1) { nmod_poly_zero(res); return; } if (len1 == 1) { nmod_poly_set(res, poly1); return; } if (res == poly3 || res == poly1 || res == poly3inv) { nmod_poly_t tmp; nmod_poly_init_mod(tmp, res->mod); nmod_poly_compose_mod_brent_kung_precomp_preinv(tmp, poly1, A, poly3, poly3inv); nmod_poly_swap(tmp, res); nmod_poly_clear(tmp); return; } nmod_poly_fit_length(res, len); _nmod_poly_compose_mod_brent_kung_precomp_preinv(res->coeffs, poly1->coeffs, len1, A, poly3->coeffs, len3, poly3inv->coeffs, poly3inv->length, res->mod); res->length = len; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/compose_mod_brent_kung_preinv.c000066400000000000000000000100631461254215100236730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" void _nmod_poly_compose_mod_brent_kung_preinv(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, mp_srcptr poly3, slong len3, mp_srcptr poly3inv, slong len3inv, nmod_t mod) { nmod_mat_t A, B, C; mp_ptr t, h; slong i, n, m; n = len3 - 1; if (len3 == 1) return; if (len1 == 1) { res[0] = poly1[0]; return; } if (len3 == 2) { res[0] = _nmod_poly_evaluate_nmod(poly1, len1, poly2[0], mod); return; } m = n_sqrt(n) + 1; nmod_mat_init(A, m, n, mod.n); nmod_mat_init(B, m, m, mod.n); nmod_mat_init(C, m, n, mod.n); h = _nmod_vec_init(n); t = _nmod_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1/m; i++) _nmod_vec_set(B->rows[i], poly1 + i*m, m); _nmod_vec_set(B->rows[i], poly1 + i*m, len1%m); /* Set rows of A to powers of poly2 */ _nmod_poly_powers_mod_preinv_naive(A->rows, poly2, n, m, poly3, len3, poly3inv, len3inv, mod); nmod_mat_mul(C, B, A); /* Evaluate block composition using the Horner scheme */ _nmod_vec_set(res, C->rows[m - 1], n); _nmod_poly_mulmod_preinv(h, A->rows[m - 1], n, poly2, n, poly3, len3, poly3inv, len3inv,mod); for (i = m - 2; i >= 0; i--) { _nmod_poly_mulmod_preinv(t, res, n, h, n, poly3, len3, poly3inv, len3inv, mod); _nmod_poly_add(res, t, n, C->rows[i], n, mod); } _nmod_vec_clear(h); _nmod_vec_clear(t); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } void nmod_poly_compose_mod_brent_kung_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3, const nmod_poly_t poly3inv) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; mp_ptr ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_preinv): Division by zero.\n"); } if (len1 >= len3) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_preinv): " "The degree of the first polynomial must be smaller than that of the modulus.\n"); } if (len1 == 0 || len3 == 1) { nmod_poly_zero(res); return; } if (len1 == 1) { nmod_poly_set(res, poly1); return; } if (res == poly3 || res == poly1 || res == poly3inv) { nmod_poly_t tmp; nmod_poly_init_mod(tmp, res->mod); nmod_poly_compose_mod_brent_kung_preinv(tmp, poly1, poly2, poly3, poly3inv); nmod_poly_swap(tmp, res); nmod_poly_clear(tmp); return; } ptr2 = _nmod_vec_init(len); if (len2 <= len) { flint_mpn_copyi(ptr2, poly2->coeffs, len2); flint_mpn_zero(ptr2 + len2, len - len2); } else { _nmod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, res->mod); } nmod_poly_fit_length(res, len); _nmod_poly_compose_mod_brent_kung_preinv(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, poly3inv->coeffs, poly3inv->length, res->mod); res->length = len; _nmod_poly_normalise(res); _nmod_vec_clear(ptr2); } flint-3.1.3/src/nmod_poly/compose_mod_brent_kung_vec_preinv.c000066400000000000000000000107211461254215100245310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" void _nmod_poly_compose_mod_brent_kung_vec_preinv(nmod_poly_struct * res, const nmod_poly_struct * polys, slong lenpolys, slong l, mp_srcptr g, slong glen, mp_srcptr poly, slong len, mp_srcptr polyinv, slong leninv, nmod_t mod) { nmod_mat_t A, B, C; mp_ptr t, h; slong i, j, k, n, m, len2 = l, len1; n = len - 1; m = n_sqrt(n*len2) + 1; h = _nmod_vec_init(n); t = _nmod_vec_init(n); k = len/m + 1; nmod_mat_init(A, m, n, mod.n); nmod_mat_init(B, k*len2, m, mod.n); nmod_mat_init(C, k*len2, n, mod.n); /* Set rows of B to the segments of polys */ for (j = 0; j < len2; j++) { len1 = (polys + j)->length; for (i = 0; i < len1/m; i++) _nmod_vec_set(B->rows[i + j*k], (polys + j)->coeffs + i*m, m); _nmod_vec_set(B->rows[i + j*k], (polys + j)->coeffs + i*m, len1%m); } /* Set rows of A to powers of last element of polys */ _nmod_poly_powers_mod_preinv_naive(A->rows, g, glen, m, poly, len, polyinv, leninv, mod); nmod_mat_mul(C, B, A); /* Evaluate block composition using the Horner scheme */ if (n == 1) { h[0] = n_mulmod2_preinv(A->rows[m - 1][0], A->rows[1][0], mod.n, mod.ninv); } else { _nmod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly, len, polyinv, leninv, mod); } for (j = 0; j < len2; j++) { _nmod_vec_set((res + j)->coeffs, C->rows[(j + 1)*k - 1], n); if (n == 1) { for (i = 2; i <= k; i++) { t[0] = n_mulmod2_preinv(res[j].coeffs[0], h[0], mod.n, mod.ninv); res[j].coeffs[0] = n_addmod(t[0], C->rows[(j + 1)*k - i][0], mod.n); } } else { for (i = 2; i <= k; i++) { _nmod_poly_mulmod_preinv(t, res[j].coeffs, n, h, n, poly, len, polyinv, leninv, mod); _nmod_poly_add(res[j].coeffs, t, n, C->rows[(j + 1)*k - i], n, mod); } } } _nmod_vec_clear(h); _nmod_vec_clear(t); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } void nmod_poly_compose_mod_brent_kung_vec_preinv(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv) { slong len2 = poly->length; slong len3, i; for (i = 0; i < len1; i++) { len3 = (polys + i)->length; if (len3 >= len2) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_vec_preinv): " "The degree of the first polynomial must be smaller than that of the modulus\n"); } } if (n > len1) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_vec_preinv): " "n is larger than the length of polys\n"); } if (n == 0) return; if (len2 == 1) { for (i = 0; i < n; i++) nmod_poly_zero(res + i); return; } if (len2 == 2) { for (i = 0; i < n; i++) nmod_poly_set(res + i, polys + i); return; } for (i = 0; i < n; i++) { nmod_poly_fit_length(res + i, len2 - 1); _nmod_poly_set_length(res + i, len2 - 1); } _nmod_poly_compose_mod_brent_kung_vec_preinv(res, polys, len1, n, g->coeffs, g->length, poly->coeffs, len2, polyinv->coeffs, polyinv->length, poly->mod); for (i = 0; i < n; i++) _nmod_poly_normalise(res + i); } flint-3.1.3/src/nmod_poly/compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000231301461254215100263670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" typedef struct { nmod_poly_struct * res; nmod_mat_struct * C; mp_srcptr h; mp_srcptr poly; mp_srcptr polyinv; nmod_t p; mp_ptr t; volatile slong * j; slong k; slong m; slong len; slong leninv; slong len2; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } compose_vec_arg_t; void _nmod_poly_compose_mod_brent_kung_vec_preinv_worker(void * arg_ptr) { compose_vec_arg_t arg = *((compose_vec_arg_t *) arg_ptr); slong i, j, k = arg.k, n = arg.len - 1; slong len = arg.len, leninv = arg.leninv; mp_ptr t = arg.t; mp_srcptr h = arg.h; mp_srcptr poly = arg.poly; mp_srcptr polyinv = arg.polyinv; nmod_poly_struct * res = arg.res; nmod_mat_struct * C = arg.C; nmod_t p = arg.p; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif j = *arg.j; *arg.j = j + 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (j >= arg.len2) return; _nmod_vec_set(res[j].coeffs, C->rows[(j + 1)*k - 1], n); if (n == 1) /* special case, constant polynomials */ { for (i = 2; i <= k; i++) { t[0] = n_mulmod2_preinv(res[j].coeffs[0], h[0], p.n, p.ninv); res[j].coeffs[0] = n_addmod(t[0], C->rows[(j + 1)*k - i][0], p.n); } } else { for (i = 2; i <= k; i++) { _nmod_poly_mulmod_preinv(t, res[j].coeffs, n, h, n, poly, len, polyinv, leninv, p); _nmod_poly_add(res[j].coeffs, t, n, C->rows[(j + 1)*k - i], n, p); } } } } void _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(nmod_poly_struct * res, const nmod_poly_struct * polys, slong lenpolys, slong l, mp_srcptr g, slong glen, mp_srcptr poly, slong len, mp_srcptr polyinv, slong leninv, nmod_t mod, thread_pool_handle * threads, slong num_threads) { nmod_mat_t A, B, C; slong i, j, n, m, k, len2 = l, len1, shared_j = 0; mp_ptr h; compose_vec_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif n = len - 1; m = n_sqrt(n*len2) + 1; h = _nmod_vec_init(n); k = len/m + 1; nmod_mat_init(A, m, n, mod.n); nmod_mat_init(B, k*len2, m, mod.n); nmod_mat_init(C, k*len2, n, mod.n); /* Set rows of B to the segments of polys */ for (j = 0; j < len2; j++) { len1 = polys[j].length; for (i = 0; i < len1 / m; i++) _nmod_vec_set(B->rows[i + j * k], polys[j].coeffs + i * m, m); _nmod_vec_set(B->rows[i + j * k], polys[j].coeffs + i * m, len1 % m); } /* Set rows of A to powers of g */ _nmod_poly_powers_mod_preinv_threaded_pool(A->rows, g, glen, m, poly, len, polyinv, leninv, mod, threads, num_threads); _nmod_mat_mul_classical_threaded_pool_op(C, NULL, B, A, 0, threads, num_threads); /* Evaluate block composition using the Horner scheme */ if (n == 1) { h[0] = n_mulmod2_preinv(A->rows[m - 1][0], A->rows[1][0], mod.n, mod.ninv); } else { _nmod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly, len, polyinv, leninv, mod); } args = (compose_vec_arg_t *) flint_malloc(sizeof(compose_vec_arg_t) * (num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].res = res; args[i].C = C; args[i].h = h; args[i].k = k; args[i].m = m; args[i].j = &shared_j; args[i].poly = poly; args[i].t = _nmod_vec_init(len); args[i].len = len; args[i].polyinv = polyinv; args[i].leninv = leninv; args[i].p = mod; args[i].len2 = len2; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif } #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif for (i = 0; i < num_threads; i++) { thread_pool_wake(global_thread_pool, threads[i], 0, _nmod_poly_compose_mod_brent_kung_vec_preinv_worker, &args[i]); } _nmod_poly_compose_mod_brent_kung_vec_preinv_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) { thread_pool_wait(global_thread_pool, threads[i]); } #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif for (i = 0; i < num_threads + 1; i++) _nmod_vec_clear(args[i].t); flint_free(args); _nmod_vec_clear(h); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } void nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv, thread_pool_handle * threads, slong num_threads) { slong len2 = poly->length; slong i; if (n == 0) return; if (len2 == 1) { for (i = 0; i < n; i++) nmod_poly_zero(res + i); return; } if (len2 == 2) { for (i = 0; i < n; i++) nmod_poly_set(res + i, polys + i); return; } for (i = 0; i < n; i++) { nmod_poly_fit_length(res + i, len2 - 1); _nmod_poly_set_length(res + i, len2 - 1); } _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(res, polys, len1, n, g->coeffs, g->length, poly->coeffs, len2, polyinv->coeffs, polyinv->length, poly->mod, threads, num_threads); for (i = 0; i < n; i++) _nmod_poly_normalise(res + i); } void nmod_poly_compose_mod_brent_kung_vec_preinv_threaded(nmod_poly_struct * res, const nmod_poly_struct * polys, slong len1, slong n, const nmod_poly_t g, const nmod_poly_t poly, const nmod_poly_t polyinv) { slong i, len2 = poly->length; thread_pool_handle * threads; slong num_threads; for (i = 0; i < len1; i++) { if (polys[i].length >= len2) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_vec_preinv_threaded): " "The degree of the first polynomial must be smaller than that of the modulus\n"); } } if (n > len1) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_mod_brent_kung_vec_preinv_threaded): " "n is larger than the length of polys\n"); } if (n == 0) return; if (len2 == 1) { for (i = 0; i < n; i++) nmod_poly_zero(res + i); return; } if (len2 == 2) { for (i = 0; i < n; i++) nmod_poly_set(res + i, polys + i); return; } for (i = 0; i < n; i++) { nmod_poly_fit_length(res + i, len2 - 1); _nmod_poly_set_length(res + i, len2 - 1); } num_threads = flint_request_threads(&threads, flint_get_num_threads()); _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(res, polys, len1, n, g->coeffs, g->length, poly->coeffs, len2, polyinv->coeffs, polyinv->length, poly->mod, threads, num_threads); flint_give_back_threads(threads, num_threads); for (i = 0; i < n; i++) _nmod_poly_normalise(res + i); } flint-3.1.3/src/nmod_poly/compose_mod_horner.c000066400000000000000000000051141461254215100214500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_compose_mod_horner(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod) { slong i, len; mp_ptr t; if (lenh == 1) return; if (lenf == 1) { res[0] = f[0]; return; } if (lenh == 2) { res[0] = _nmod_poly_evaluate_nmod(f, lenf, g[0], mod); return; } len = lenh - 1; i = lenf - 1; t = _nmod_vec_init(len); _nmod_vec_scalar_mul_nmod(res, g, len, f[i], mod); i--; if (i >= 0) res[0] = nmod_add(res[0], f[i], mod); while (i > 0) { i--; _nmod_poly_mulmod(t, res, len, g, len, h, lenh, mod); _nmod_poly_add(res, t, len, f + i, 1, mod); } _nmod_vec_clear(t); } void nmod_poly_compose_mod_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3) { slong len1 = poly1->length; slong len2 = poly2->length; slong len3 = poly3->length; slong len = len3 - 1; mp_ptr ptr2; if (len3 == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_compose_mod_horner). Division by zero.\n"); } if (len1 == 0 || len3 == 1) { nmod_poly_zero(res); return; } if (len1 == 1) { nmod_poly_set(res, poly1); return; } if (res == poly3 || res == poly1) { nmod_poly_t tmp; nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv); nmod_poly_compose_mod_horner(tmp, poly1, poly2, poly3); nmod_poly_swap(tmp, res); nmod_poly_clear(tmp); return; } ptr2 = _nmod_vec_init(len); if (len2 <= len) { flint_mpn_copyi(ptr2, poly2->coeffs, len2); flint_mpn_zero(ptr2 + len2, len - len2); } else { _nmod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, res->mod); } nmod_poly_fit_length(res, len); _nmod_poly_compose_mod_horner(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, res->mod); res->length = len; _nmod_poly_normalise(res); _nmod_vec_clear(ptr2); } flint-3.1.3/src/nmod_poly/compose_series.c000066400000000000000000000043161461254215100206110ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_compose_series(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_compose_series(res, poly1, len1, poly2, len2, n, ctx)); } void nmod_poly_compose_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) { slong len1 = poly1->length; slong len2 = poly2->length; slong lenr; if (len2 != 0 && poly2->coeffs[0] != 0) { flint_throw(FLINT_ERROR, "(nmod_poly_compose_series): " "Inner polynomial must have zero constant term.\n"); } if (len1 == 0 || n == 0) { nmod_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { nmod_poly_fit_length(res, 1); res->coeffs[0] = poly1->coeffs[0]; res->length = 1; _nmod_poly_normalise(res); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { nmod_poly_fit_length(res, lenr); _nmod_poly_compose_series(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, res->mod); res->length = lenr; _nmod_poly_normalise(res); } else { nmod_poly_t t; nmod_poly_init2_preinv(t, res->mod.n, res->mod.ninv, lenr); _nmod_poly_compose_series(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, res->mod); t->length = lenr; _nmod_poly_normalise(t); nmod_poly_swap(res, t); nmod_poly_clear(t); } } flint-3.1.3/src/nmod_poly/conway.c000066400000000000000000000401071461254215100170700ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_poly.h" extern uint8_t __nmod_poly_cp_primes0[]; extern uint16_t __nmod_poly_cp_degrees0[]; extern uint8_t __nmod_poly_numntcoeffs0[]; extern uint8_t __nmod_poly_ntcoeffs0[]; #define primes __nmod_poly_cp_primes0 #define degrees __nmod_poly_cp_degrees0 #define num_nontrivialcoeffs __nmod_poly_numntcoeffs0 #define nontrivialcoeffs __nmod_poly_ntcoeffs0 static int conway_polynomial_lt_260(mp_ptr op, ulong prime, ulong deg) { slong ix, jx, kx; slong numnt, sum; const uint8_t * ntcoeffs; /* primes in __nmod_poly_cp_primes0 are offset by 2 */ prime -= 2; /* Find corresponding index. As we offset the primes by two in order to fit * 257 into a byte, we cannot check if the first "prime" is zero. */ ix = 0; if (primes[ix] == prime) /* Do nothing */; else { do { ix++; if (primes[ix] == prime) break; else if (primes[ix] == 0) return 0; } while (1); } /* Degrees are stored as [{degrees for prime = 2}, {degrees for prime = 3}, ...] in the one-dimensional array __nmod_poly_cp_degrees0. Hence, we first has to get to the correct place in this array where the degrees for `prime' are stored. */ kx = 0; jx = 0; while (jx != ix) { while (degrees[kx] < degrees[kx + 1]) kx++; kx++; jx++; } if (deg == 1) /* Do nothing */; else { do kx++; while (degrees[kx] < deg && degrees[kx] != 1 && degrees[kx] != 0); /* degrees[kx] == 1 means that we've gone to the next prime, and degrees[kx] == 0 means that we've reached the end of the list. */ } if (degrees[kx] != deg) return 0; /* Sum up all numbers of non-trivial coefficients before this one to get the index where our non-trivial coefficients appear. */ sum = 0; for (jx = 0; jx < kx; jx++) sum += num_nontrivialcoeffs[jx]; numnt = num_nontrivialcoeffs[kx]; /* Set trivial coefficients */ for (jx = 1; jx < deg; jx++) op[jx] = 0; op[deg] = 1; ntcoeffs = nontrivialcoeffs + sum; for (jx = 0; jx < numnt; jx++) op[jx] = ntcoeffs[jx]; return 1; } #undef primes #undef degrees #undef num_nontrivialcoeffs #undef nontrivialcoeffs extern uint16_t __nmod_poly_cp_primes1[]; extern uint8_t __nmod_poly_cp_sm_coeffs1[]; extern uint16_t __nmod_poly_cp_md_coeffs1[]; #define primes __nmod_poly_cp_primes1 #define small_coeffs __nmod_poly_cp_sm_coeffs1 #define big_coeffs __nmod_poly_cp_md_coeffs1 static int conway_polynomial_lt_300(mp_ptr op, ulong prime, ulong deg) { slong ix = 0; const uint8_t * ap; const uint16_t * bp; if (deg > 12) return 0; /* Find corresponding index */ do { if (primes[ix] == prime) break; else if (primes[ix] == 0) return 0; ix++; } while (1); ap = small_coeffs + 23 * ix; bp = big_coeffs + 11 * ix; for (ix = 1; ix < deg; ix++) op[ix] = 0; op[deg] = 1; switch (deg) { case 1: op[0] = bp[0]; break; case 2: op[0] = ap[0]; op[1] = bp[1]; break; case 3: op[0] = bp[0]; op[1] = ap[1]; break; case 4: op[0] = ap[0]; op[1] = bp[2]; op[2] = ap[2]; break; case 5: op[0] = bp[0]; op[1] = ap[3]; break; case 6: op[0] = ap[0]; op[1] = bp[3]; op[2] = ap[4]; op[3] = ap[5]; op[4] = ap[6]; break; case 7: op[0] = bp[0]; op[1] = ap[7]; break; case 8: op[0] = ap[0]; op[1] = ap[8]; op[2] = bp[4]; op[3] = ap[9]; op[4] = ap[10]; break; case 9: op[0] = bp[0]; op[1] = bp[5]; op[2] = bp[6]; op[3] = ap[11]; break; case 10: op[0] = ap[0]; op[1] = bp[7]; op[2] = ap[12]; op[3] = bp[8]; op[4] = ap[13]; op[5] = bp[9]; op[6] = ap[14]; break; case 11: op[0] = bp[0]; op[1] = ap[15]; break; case 12: op[0] = ap[0]; op[1] = ap[16]; op[2] = bp[10]; op[3] = ap[17]; op[4] = ap[18]; op[5] = ap[19]; op[6] = ap[20]; op[7] = ap[21]; op[8] = ap[22]; break; default: FLINT_UNREACHABLE; } return 1; } #undef primes #undef small_coeffs #undef big_coeffs extern uint16_t __nmod_poly_cp_primes2[]; extern uint8_t __nmod_poly_cp_sm_coeffs2[]; extern uint16_t __nmod_poly_cp_md_coeffs2[]; #define primes __nmod_poly_cp_primes2 #define small_coeffs __nmod_poly_cp_sm_coeffs2 #define big_coeffs __nmod_poly_cp_md_coeffs2 static int conway_polynomial_lt_1000(mp_ptr op, ulong prime, ulong deg) { slong ix = 0; const uint8_t * ap; const uint16_t * bp; if (deg > 9) return 0; /* Find corresponding index */ do { if (primes[ix] == prime) break; else if (primes[ix] == 0) return 0; ix++; } while (1); ap = small_coeffs + 8 * ix; bp = big_coeffs + 11 * ix; for (ix = 1; ix < deg; ix++) op[ix] = 0; op[deg] = 1; switch (deg) { case 1: op[0] = bp[0]; break; case 2: op[0] = ap[0]; op[1] = bp[1]; break; case 3: op[0] = bp[0]; op[1] = ap[1]; break; case 4: op[0] = ap[0]; op[1] = bp[2]; op[2] = ap[2]; break; case 5: op[0] = bp[0]; op[1] = ap[3]; break; case 6: op[0] = ap[0]; op[1] = bp[3]; op[2] = bp[4]; op[3] = bp[5]; op[4] = ap[4]; break; case 7: op[0] = bp[0]; op[1] = ap[5]; break; case 8: op[0] = ap[0]; op[1] = bp[6]; op[2] = bp[7]; op[3] = bp[8]; op[4] = ap[6]; break; case 9: op[0] = bp[0]; op[1] = bp[9]; op[2] = bp[10]; op[3] = ap[7]; break; default: FLINT_UNREACHABLE; } return 1; } #undef primes #undef small_coeffs #undef big_coeffs extern uint16_t __nmod_poly_cp_primes3[]; extern uint8_t __nmod_poly_cp_sm_coeffs3[]; extern uint16_t __nmod_poly_cp_md_coeffs3[]; #define primes __nmod_poly_cp_primes3 #define small_coeffs __nmod_poly_cp_sm_coeffs3 #define big_coeffs __nmod_poly_cp_md_coeffs3 static int conway_polynomial_lt_3371(mp_ptr op, ulong prime, ulong deg) { slong ix = 0; const uint8_t * ap; const uint16_t * bp; if (deg > 9 || deg == 8) return 0; else if (deg > 6 && (prime == 2689 || prime == 2797 || prime == 2833 || prime == 3019 || prime == 3163 || prime == 3209 || prime == 3331)) return 0; /* Find corresponding index */ do { if (primes[ix] == prime) break; else if (primes[ix] == 0) return 0; ix++; } while (1); ap = small_coeffs + 7 * ix; bp = big_coeffs + 8 * ix; for (ix = 1; ix < deg; ix++) op[ix] = 0; op[deg] = 1; switch (deg) { case 1: op[0] = bp[0]; break; case 2: op[0] = ap[0]; op[1] = bp[1]; break; case 3: op[0] = bp[0]; op[1] = ap[1]; break; case 4: op[0] = ap[0]; op[1] = bp[2]; op[2] = ap[2]; break; case 5: op[0] = bp[0]; op[1] = ap[3]; break; case 6: op[0] = ap[0]; op[1] = bp[3]; op[2] = bp[4]; op[3] = bp[5]; op[4] = ap[4]; break; case 7: op[0] = bp[0]; op[1] = ap[5]; break; case 9: op[0] = bp[0]; op[1] = bp[6]; op[2] = bp[7]; op[3] = ap[6]; break; default: FLINT_UNREACHABLE; } return 1; } #undef primes #undef small_coeffs #undef big_coeffs extern uint16_t __nmod_poly_cp_primes4[]; extern uint8_t __nmod_poly_cp_sm_coeffs4[]; extern uint16_t __nmod_poly_cp_md_coeffs4[]; #define primes __nmod_poly_cp_primes4 #define small_coeffs __nmod_poly_cp_sm_coeffs4 #define big_coeffs __nmod_poly_cp_md_coeffs4 static int conway_polynomial_lt_11000(mp_ptr op, ulong prime, ulong deg) { slong ix = 0; const uint8_t * ap; const uint16_t * bp; if (deg > 6) return 0; /* Find corresponding index */ do { if (primes[ix] == prime) break; else if (primes[ix] == 0) return 0; ix++; } while (1); ap = small_coeffs + 5 * ix; bp = big_coeffs + 6 * ix; for (ix = 1; ix < deg; ix++) op[ix] = 0; op[deg] = 1; switch (deg) { case 1: op[0] = bp[0]; break; case 2: op[0] = ap[0]; op[1] = bp[1]; break; case 3: op[0] = bp[0]; op[1] = ap[1]; break; case 4: op[0] = ap[0]; op[1] = bp[2]; op[2] = ap[2]; break; case 5: op[0] = bp[0]; op[1] = ap[3]; break; case 6: op[0] = ap[0]; op[1] = bp[3]; op[2] = bp[4]; op[3] = bp[5]; op[4] = ap[4]; break; default: FLINT_UNREACHABLE; } return 1; } #undef primes #undef small_coeffs #undef big_coeffs extern uint16_t __nmod_poly_cp_primes5[]; extern uint8_t __nmod_poly_cp_sm_coeffs5[]; extern uint16_t __nmod_poly_cp_md_coeffs5[]; #define primes __nmod_poly_cp_primes5 #define small_coeffs __nmod_poly_cp_sm_coeffs5 #define big_coeffs __nmod_poly_cp_md_coeffs5 static int conway_polynomial_lt_65536(mp_ptr op, ulong prime, ulong deg) { slong ix = 0; const uint8_t * ap; const uint16_t * bp; if (deg > 4) return 0; /* Find corresponding index */ do { if (primes[ix] == prime) break; else if (primes[ix] == 0) return 0; ix++; } while (1); ap = small_coeffs + 3 * ix; bp = big_coeffs + 3 * ix; for (ix = 1; ix < deg; ix++) op[ix] = 0; op[deg] = 1; switch (deg) { case 1: op[0] = bp[0]; break; case 2: op[0] = ap[0]; op[1] = bp[1]; break; case 3: op[0] = bp[0]; op[1] = ap[1]; break; case 4: op[0] = ap[0]; op[1] = bp[2]; op[2] = ap[2]; break; default: FLINT_UNREACHABLE; } return 1; } #undef primes #undef small_coeffs #undef big_coeffs extern uint16_t __nmod_poly_cp_primes6[]; extern uint8_t __nmod_poly_cp_sm_coeffs6[]; extern uint32_t __nmod_poly_cp_lg_coeffs6[]; #define primes __nmod_poly_cp_primes6 #define small_coeffs __nmod_poly_cp_sm_coeffs6 #define big_coeffs __nmod_poly_cp_lg_coeffs6 static int conway_polynomial_lt_109988(mp_ptr op, ulong prime, ulong deg) { slong ix = 0; const uint8_t * ap; const uint32_t * bp; if (deg != 4) return 0; /* primes in __nmod_poly_cp_primes6 are offset by 2^16 */ prime -= 1 << 16; /* Find corresponding index */ do { if (primes[ix] == prime) break; else if (primes[ix] == 0) return 0; ix++; } while (1); ap = small_coeffs + 2 * ix; bp = big_coeffs + 1 * ix; op[0] = ap[0]; op[1] = bp[0]; op[2] = ap[1]; op[3] = 0; op[4] = 1; return 1; } #undef primes #undef small_coeffs #undef big_coeffs int _nmod_poly_conway(mp_ptr op, ulong prime, slong deg) { if (deg <= 0) return 0; else if (prime < 2) return 0; if (prime < 260) return conway_polynomial_lt_260(op, prime, deg); else if (prime % 2 == 0) return 0; else if (prime < 300) return conway_polynomial_lt_300(op, prime, deg); else if (prime < 1000) return conway_polynomial_lt_1000(op, prime, deg); else if (prime < 3371) return conway_polynomial_lt_3371(op, prime, deg); else if (prime < 11000) return conway_polynomial_lt_11000(op, prime, deg); else if (prime < 65536) return conway_polynomial_lt_65536(op, prime, deg); else if (prime < 109988) return conway_polynomial_lt_109988(op, prime, deg); else return 0; } ulong _nmod_poly_conway_rand(slong * degree, flint_rand_t state, int type) { ulong prime; switch (type) { case 0: /* prime whatever, degree whatever */ case 1: /* degree < 15 */ do prime = n_randprime(state, 2 + n_randint(state, 16), 1); while (prime > 109987); break; case 2: /* prime < 2^10 */ case 3: /* prime < 2^10 and degree < 15 */ prime = n_randprime(state, 2 + n_randint(state, 9), 1); break; default: flint_throw(FLINT_ERROR, "wrong type in %s", __func__); } if (prime < 260) { /* Find the position it corresponds to in __nmod_poly_cp_primes0, and * then generate degree based on __nmod_poly_cp_degrees0. */ #define primes __nmod_poly_cp_primes0 #define degrees __nmod_poly_cp_degrees0 slong ix = 0, jx, kx; /* Primes are offset by 2 in table */ prime -= 2; /* Search for prime's index */ while (prime != primes[ix]) ix++; /* Reset prime */ prime += 2; /* Search for starting index of degrees for prime */ kx = 0; jx = 0; while (jx != ix) { while (degrees[kx] < degrees[kx + 1]) kx++; kx++; jx++; } /* Now kx points to the starting degree for prime */ jx = 0; if (type % 2 == 1) { do jx++; while (degrees[kx + jx] < 15); } else { do jx++; while (degrees[kx + jx] != 1 && degrees[kx + jx] != 0); } /* The degrees we will be using are degrees[kx + 0], ..., * degrees[kx + jx - 1]. */ *degree = degrees[kx + n_randint(state, jx)]; #undef primes #undef degrees } else if (prime < 300) { *degree = 1 + n_randint(state, 12); } else if (prime < 1000) { *degree = 1 + n_randint(state, 9); } else if (prime < 3371) { switch (prime) { case 2689: case 2797: case 2833: case 3019: case 3163: case 3209: case 3331: *degree = 1 + n_randint(state, 6); break; default: *degree = 1 + n_randint(state, 8); if (*degree == 8) *degree += 1; } } else if (prime < 11000) *degree = 1 + n_randint(state, 6); else if (prime < 65536) *degree = 1 + n_randint(state, 4); else *degree = 4; return prime; } flint-3.1.3/src/nmod_poly/conway_polynomial_data.c000066400000000000000000011645011461254215100223320ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Data is compressed from: * https://www.math.rwth-aachen.de/~Frank.Luebeck/data/ConwayPol/CPimport.txt */ #include uint8_t __nmod_poly_cp_primes0[] = {0,1,3,5,9,11,15,17,21,27,29,35,39,41,45,51,57,59,65,69,71,77,81,87,95,99,101,105,107,111,125,129,135,137,147,149,155,161,165,171,177,179,189,191,195,197,209,221,225,227,231,237,239,249,255,0}; uint16_t __nmod_poly_cp_degrees0[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,95,96,97,98,100,101,102,103,107,108,109,110,113,114,115,119,120,121,125,126,127,131,132,133,137,139,143,149,150,151,157,163,167,169,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,289,293,307,311,313,317,331,337,347,349,353,359,361,367,373,379,383,389,397,401,409,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,59,60,61,65,66,67,71,72,73,77,79,83,85,89,91,97,101,103,107,109,113,121,127,131,137,139,149,151,157,163,167,169,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,33,35,36,37,39,41,42,43,47,49,53,55,59,61,67,71,73,79,83,89,97,101,103,107,109,113,121,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,35,36,37,41,42,43,47,49,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,223,227,229,241,251,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,27,29,30,31,35,37,41,43,47,49,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,211,223,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,31,37,41,43,47,49,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,173,179,191,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,31,37,41,43,47,49,53,59,61,67,71,73,79,83,89,97,101,103,107,113,127,131,157,163,179,191,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,23,24,25,29,30,31,37,41,43,47,49,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,167,181,199,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,103,107,127,137,151,163,179,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,103,107,109,131,137,139,151,157,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,101,103,107,109,113,137,139,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,49,53,59,61,67,71,73,79,83,97,107,151,157,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,113,149,151,157,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,107,109,131,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,97,101,107,127,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,97,101,107,113,127,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,107,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,89,101,107,109,139,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,89,103,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,97,107,109,131,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,89,101,107,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,109,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,83,89,97,103,113,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,89,101,107,109,113,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,53,59,61,67,71,73,79,97,113,127,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,25,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,1,2,3,4,5,6,7,8,9,10,11,12,13,17,19,23,29,31,37,41,43,47,0}; uint8_t __nmod_poly_numntcoeffs0[] = {1,2,2,2,3,5,2,5,5,7,3,8,5,8,6,6,4,13,6,11,7,13,6,17,9,15,13,14,3,18,4,16,14,17,12,24,6,15,16,24,4,31,7,25,21,24,6,26,11,30,17,29,7,35,12,34,22,32,7,46,6,33,25,34,16,47,6,36,25,45,6,49,5,38,33,39,16,47,5,49,28,38,8,58,23,44,31,48,7,65,18,49,25,64,7,57,58,8,69,8,8,71,6,69,6,78,26,22,87,14,23,90,2,8,92,26,9,8,25,10,112,4,7,8,7,18,9,5,8,8,9,9,8,10,6,7,10,8,6,9,8,8,10,8,9,8,10,9,23,10,9,8,8,8,8,8,8,7,10,9,21,8,9,10,10,8,9,8,8,1,2,2,4,2,5,3,6,4,7,3,7,2,10,9,8,2,11,3,14,11,12,4,15,7,14,8,15,5,21,4,13,13,19,10,22,4,20,13,24,2,30,4,24,21,23,5,32,9,28,19,29,5,36,15,33,22,4,45,4,18,47,3,5,48,2,18,5,6,20,4,18,4,5,4,4,5,4,14,5,6,2,6,7,3,5,6,4,13,5,6,6,6,7,6,5,5,6,6,6,5,6,4,5,7,4,1,2,2,3,2,5,2,5,4,6,2,8,3,9,6,9,3,13,4,13,8,13,3,17,7,16,11,15,4,22,2,13,11,25,3,15,4,30,2,5,9,4,15,4,3,5,5,4,4,4,4,4,5,3,5,3,4,13,5,4,5,4,5,3,3,4,5,4,5,4,4,5,4,2,5,4,4,3,4,5,4,5,1,2,3,3,2,5,2,4,5,7,2,9,3,8,7,9,2,13,3,13,8,13,3,16,7,13,11,15,2,23,3,12,25,2,4,30,3,3,8,2,4,3,3,3,4,4,4,2,4,4,4,3,5,3,3,2,5,4,5,3,4,3,4,4,4,3,3,4,4,3,4,5,5,4,5,1,2,2,3,3,5,2,5,3,6,2,9,2,8,7,9,2,13,3,13,9,13,3,16,7,9,2,22,3,11,3,4,2,3,7,3,3,3,3,3,3,3,3,3,4,3,3,4,3,4,3,4,3,3,4,4,4,2,4,3,3,4,4,4,4,4,4,1,2,2,3,2,4,2,5,5,6,2,9,2,8,8,9,3,12,2,13,10,2,16,5,11,3,23,3,2,3,3,3,7,2,2,3,3,2,4,4,3,3,3,3,3,2,3,4,3,2,3,3,3,3,3,4,4,4,3,1,2,2,3,2,5,2,5,3,6,2,9,2,9,7,9,2,13,2,13,10,3,17,6,10,3,22,2,2,3,3,3,8,3,3,2,3,3,3,2,2,4,3,2,2,3,3,3,4,3,4,3,3,1,2,2,3,2,4,2,5,4,6,2,8,2,8,8,8,2,12,2,12,10,3,16,6,2,23,3,3,3,2,3,8,2,3,3,3,3,3,3,4,3,2,3,3,3,3,3,3,3,3,4,3,3,3,3,3,3,1,2,2,3,2,5,2,5,4,6,3,8,2,9,7,8,2,13,2,2,6,3,2,3,3,3,3,3,3,3,3,2,2,2,3,3,2,3,3,2,3,3,2,3,1,2,2,3,2,5,2,5,4,7,3,9,2,9,7,9,2,12,2,2,6,2,2,3,3,2,2,2,3,3,2,3,2,3,2,3,3,3,3,3,3,3,3,3,3,1,2,2,3,2,4,2,4,4,6,2,8,2,8,7,8,2,13,2,2,7,2,2,2,3,2,2,2,3,3,3,2,3,3,3,2,3,2,3,3,3,3,3,1,2,2,3,2,4,2,5,4,6,2,8,2,9,8,2,13,3,3,5,3,3,2,3,2,2,7,3,2,3,3,3,3,3,2,3,2,3,3,1,2,2,2,3,5,2,5,4,6,2,7,2,8,7,2,12,2,2,7,2,2,2,2,2,2,3,3,3,2,3,3,2,2,3,2,3,2,3,3,1,2,2,3,2,4,3,5,4,7,2,8,2,8,8,2,13,2,2,6,3,2,3,2,2,2,2,2,3,3,2,2,3,2,2,3,2,2,3,1,2,2,3,2,5,2,5,4,7,2,8,2,8,7,2,12,2,3,6,2,3,3,2,2,2,2,3,2,2,2,2,2,2,2,2,2,3,1,2,2,3,2,5,2,5,3,7,2,9,3,9,7,2,12,2,2,6,2,2,2,3,2,2,2,3,2,2,2,2,3,3,2,2,3,2,3,1,2,2,3,2,5,2,5,4,7,2,8,2,9,7,2,13,2,2,6,3,2,2,2,2,2,3,2,2,3,3,2,2,3,3,3,1,2,2,3,2,4,2,4,4,6,2,9,2,9,7,2,13,2,2,6,2,2,2,3,2,3,3,2,2,3,2,3,2,3,2,3,2,1,2,2,3,2,4,2,5,4,7,3,9,2,8,8,2,13,2,2,6,2,2,2,2,2,3,2,3,2,2,2,3,2,3,2,1,2,2,3,2,5,2,4,4,6,2,8,2,7,2,2,2,6,2,2,2,2,2,2,2,3,3,2,2,2,3,3,2,3,3,3,1,2,2,3,2,4,2,5,3,7,2,9,2,6,2,2,2,6,2,2,2,2,3,3,2,2,2,2,2,2,2,3,3,1,2,2,3,2,4,2,4,3,7,2,9,3,2,2,2,6,2,3,2,2,3,2,2,2,3,2,2,2,2,2,3,2,1,2,2,3,2,5,2,5,4,6,2,8,2,2,2,2,6,2,2,2,3,2,2,2,2,2,2,2,2,2,2,3,2,3,1,2,2,3,2,5,2,4,4,7,3,9,2,2,2,2,6,2,2,3,2,2,2,3,2,2,2,2,2,2,2,2,3,2,2,1,2,2,3,2,4,2,4,4,6,2,8,2,2,2,2,6,2,2,2,2,3,3,2,3,2,3,3,3,2,2,2,2,1,2,2,3,2,5,2,5,3,7,2,9,2,2,2,2,6,2,2,2,2,2,2,1,2,2,3,2,4,2,5,3,7,2,9,2,3,2,2,6,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,7,2,8,2,2,2,2,5,2,2,2,2,2,2,1,2,2,3,2,4,2,5,3,7,2,9,2,2,2,2,6,2,2,2,2,2,2,1,2,2,2,2,5,2,5,3,6,2,9,2,2,2,2,6,2,2,2,2,2,2,1,2,2,3,2,4,2,5,4,6,2,8,2,2,2,2,6,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,6,2,8,2,2,2,2,6,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,7,2,9,2,3,2,2,6,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,6,2,8,2,2,2,3,6,2,2,2,2,2,2,1,2,2,3,2,5,2,5,3,6,2,7,2,2,2,2,5,2,2,3,2,2,2,1,2,2,3,2,4,2,5,4,7,2,9,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,6,2,8,3,2,2,2,6,2,2,2,2,2,2,1,2,2,3,2,4,2,5,4,7,2,8,2,2,2,2,5,2,2,2,2,2,2,1,2,2,3,2,5,2,5,3,6,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,5,3,7,2,9,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,4,3,6,2,9,2,2,2,2,6,2,2,2,2,2,2,1,2,2,3,2,4,2,5,4,6,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,5,3,6,2,8,2,2,3,2,2,2,2,2,2,2,1,2,2,3,2,4,2,5,4,6,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,4,4,6,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,4,2,5,4,6,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,4,2,5,4,7,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,7,2,9,2,2,2,2,2,2,3,2,2,2,1,2,2,3,2,5,2,5,4,6,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,4,2,5,4,7,2,8,2,2,3,2,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,7,2,8,2,2,2,2,3,2,2,2,2,2,1,2,2,3,2,5,2,5,4,6,2,9,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,4,2,5,3,7,2,8,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,5,4,7,2,9,2,2,2,2,2,2,2,2,2,2,1,2,2,3,2,5,2,4,4,6,2,9,2,2,2,2,2,2,2,2,2,2}; uint8_t __nmod_poly_ntcoeffs0[] = {1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,0,1,0,1,0,1,1,0,1,0,1,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,1,0,1,0,0,1,1,1,0,0,0,0,1,1,0,1,1,1,1,1,1,0,0,0,0,1,1,0,0,1,0,1,0,1,0,1,1,0,0,1,1,1,1,1,0,1,0,0,0,1,0,1,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,0,0,1,1,1,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,0,1,0,0,0,1,0,1,0,0,1,1,1,0,0,1,1,0,0,1,1,0,0,1,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,1,1,0,0,1,1,1,0,1,0,0,1,0,1,0,0,1,1,1,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0,1,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,0,1,0,1,0,0,1,0,0,0,1,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,1,0,1,0,0,0,1,1,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,1,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,0,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,0,1,1,0,1,0,0,0,1,0,1,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1,0,0,0,0,0,1,0,1,1,1,1,0,0,1,0,0,0,1,0,1,0,1,1,1,1,0,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,1,1,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,0,0,1,0,0,1,0,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,1,0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,1,0,1,1,1,1,1,0,0,1,1,1,0,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,1,1,0,1,0,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1,0,1,1,0,1,0,0,1,1,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,0,0,0,1,0,0,1,1,1,0,0,0,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,1,1,1,0,0,1,0,1,1,1,1,1,1,0,0,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,1,0,0,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0,1,0,1,0,0,1,1,0,1,1,1,1,1,1,0,1,0,0,0,1,1,1,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,1,1,0,1,0,1,0,1,1,1,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,1,1,1,0,1,1,1,1,0,0,1,0,0,0,0,1,0,0,1,1,1,0,0,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,1,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,0,0,1,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,1,1,1,0,1,0,1,1,1,0,1,1,0,1,0,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,1,0,1,1,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,1,0,1,1,0,1,1,1,1,1,1,1,0,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0,1,1,0,1,0,0,0,1,0,0,0,1,1,1,1,1,1,1,0,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,0,1,0,0,1,1,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,1,1,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,1,0,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,0,1,1,0,1,0,0,1,0,0,1,1,0,1,1,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,1,1,0,1,0,1,0,1,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,0,0,1,0,0,0,0,1,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,0,0,0,1,1,0,1,1,1,1,1,0,0,0,1,1,1,0,1,0,0,1,0,1,1,0,0,1,1,1,0,1,1,1,0,0,1,0,0,1,1,0,1,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,1,1,1,0,1,0,0,1,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,1,0,0,1,1,0,1,0,1,1,0,1,0,0,1,1,0,0,1,1,1,1,0,0,0,1,0,1,1,1,1,1,1,0,0,0,1,0,0,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,1,0,0,0,1,1,1,1,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,1,1,0,0,0,0,1,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1,0,0,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,1,1,0,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,0,0,1,0,1,1,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,1,1,1,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,1,1,1,1,0,0,1,0,1,1,1,1,0,0,1,1,1,1,0,1,0,1,0,1,1,1,0,0,1,0,1,1,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,1,0,1,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,1,0,0,1,1,1,1,1,0,0,1,0,1,1,0,0,1,1,1,1,1,0,1,1,1,0,1,0,0,1,1,1,0,0,0,1,1,0,1,0,1,1,0,1,0,1,1,1,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,1,1,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,0,1,0,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,1,0,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,1,1,1,1,0,0,1,1,1,1,1,0,1,0,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,0,0,1,0,0,1,1,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,0,0,0,0,1,0,1,1,0,0,1,1,1,1,0,0,1,0,1,1,0,1,1,1,1,0,0,0,0,1,1,1,1,0,1,0,1,1,0,1,0,1,1,1,0,0,1,1,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,0,1,1,1,1,0,1,1,1,0,0,0,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,0,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,0,1,1,0,1,1,1,0,0,1,0,0,0,0,1,1,1,1,0,0,1,1,0,1,1,1,1,1,0,0,1,1,1,0,1,0,1,1,1,0,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,1,1,0,1,0,1,0,0,0,1,1,0,0,1,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,0,0,1,1,0,1,0,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,1,1,0,1,1,1,0,0,1,0,1,0,1,0,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1,0,0,0,0,1,1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,1,1,1,1,1,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,0,1,0,1,0,1,1,2,2,1,2,2,0,0,2,1,2,2,2,1,0,2,1,0,2,2,2,2,0,1,2,1,1,2,2,2,1,0,0,2,2,2,1,0,2,2,0,1,0,1,1,1,1,2,2,0,1,2,0,1,2,1,1,2,1,1,2,0,0,1,0,0,2,2,1,2,2,2,0,2,2,1,2,2,0,2,0,2,1,2,0,2,0,1,1,0,2,2,1,0,2,2,2,0,0,1,1,1,1,0,2,1,2,0,2,0,1,2,0,2,0,2,2,2,0,1,0,1,1,1,2,2,1,2,1,1,0,1,2,2,0,2,2,0,2,0,2,0,0,2,0,0,1,1,2,1,1,0,2,2,2,1,2,1,0,0,2,2,2,2,2,2,2,1,1,0,0,0,0,0,0,2,2,0,0,1,2,0,2,0,1,1,1,2,1,1,2,1,0,0,0,2,2,2,2,1,2,2,1,2,0,2,2,2,0,2,1,0,2,2,2,0,2,1,1,0,1,2,1,0,1,2,1,2,0,0,0,0,2,2,1,0,2,1,2,2,1,0,0,1,0,1,2,2,0,0,0,2,0,2,1,0,2,0,1,2,0,2,0,2,2,1,1,1,2,0,2,0,0,1,1,1,2,1,1,1,0,2,2,0,2,1,2,2,0,2,2,0,1,1,0,0,2,1,1,2,2,1,2,2,0,1,2,2,2,0,2,2,1,0,2,2,2,2,1,0,2,1,1,0,2,0,1,0,1,2,0,1,2,2,1,2,0,1,2,1,1,2,2,1,0,1,2,0,2,0,1,1,2,0,1,0,0,0,2,1,2,2,2,0,2,0,1,0,0,2,1,0,2,1,1,2,1,2,1,1,1,0,0,2,1,0,2,2,1,0,1,1,1,0,1,2,0,1,1,2,2,1,1,0,0,1,0,1,0,2,2,0,1,1,0,2,1,1,2,1,0,0,1,1,2,0,1,2,2,0,1,2,0,1,1,2,2,2,1,2,2,0,1,2,2,1,0,1,0,2,1,0,0,1,2,2,0,2,0,1,1,1,2,1,2,2,0,2,2,0,1,2,1,0,2,0,2,0,2,2,0,2,1,0,0,1,1,1,1,2,1,0,2,0,2,2,0,1,0,2,1,1,0,0,1,1,0,1,1,2,2,1,0,0,1,0,1,0,1,1,2,2,1,0,2,0,1,1,0,0,1,1,2,0,1,0,2,1,2,2,2,1,0,2,2,2,0,2,0,1,0,0,0,2,1,2,2,0,1,1,1,2,0,1,2,0,0,0,1,0,2,0,2,2,2,1,2,0,2,1,0,0,2,2,1,1,0,2,2,2,2,1,1,1,2,0,1,2,0,1,0,1,1,0,0,0,0,1,1,2,1,0,2,2,2,2,0,2,1,1,1,0,2,2,0,1,1,0,0,1,1,2,1,0,1,0,1,2,0,1,1,2,2,0,0,0,1,0,2,0,0,0,0,2,1,1,0,0,1,2,2,2,2,0,2,2,1,2,2,0,1,0,0,1,1,1,2,2,2,2,1,0,1,1,0,2,1,0,2,2,2,1,0,2,1,1,1,2,2,1,2,0,2,2,2,1,2,0,2,0,1,2,0,0,1,2,2,0,0,0,1,1,2,0,2,0,2,2,2,0,1,0,1,2,1,1,2,0,2,2,1,2,0,0,1,1,2,2,1,1,1,0,2,2,0,0,2,2,1,1,2,2,0,2,2,0,1,2,2,2,1,0,2,0,2,1,2,0,2,0,0,2,0,2,2,1,0,0,0,1,0,1,0,1,2,0,1,1,2,1,0,0,1,2,0,1,2,1,2,0,2,0,0,1,1,0,2,1,2,2,0,1,2,2,0,2,1,1,1,2,1,0,2,1,2,1,0,1,0,2,1,1,0,2,1,2,1,2,0,2,0,1,1,1,2,2,1,0,2,2,1,1,0,0,1,2,0,1,1,2,1,2,1,2,1,1,0,1,2,2,2,0,0,2,2,0,0,1,2,2,1,2,1,0,2,1,2,2,0,0,1,1,0,1,1,0,1,2,1,1,0,0,0,0,1,2,2,2,2,0,2,1,0,1,2,1,1,2,1,2,1,1,0,1,2,2,0,0,2,2,2,1,1,1,2,2,2,1,0,2,2,2,1,1,2,2,1,0,0,2,1,0,1,2,2,1,2,2,1,1,2,1,2,2,1,1,0,2,2,0,1,2,1,1,0,1,1,1,1,0,1,2,1,2,1,2,1,1,2,1,0,1,1,2,2,1,1,0,2,1,0,2,1,2,1,1,1,1,0,1,2,1,1,1,1,2,2,1,2,0,0,2,1,0,0,0,2,0,0,1,1,1,1,2,1,1,2,0,1,2,1,1,1,2,0,2,1,1,0,1,0,1,1,1,2,0,2,1,1,2,1,1,1,2,0,2,1,0,0,2,1,1,2,1,0,2,1,2,2,1,1,2,1,1,0,0,1,1,1,0,2,1,2,1,1,2,2,0,2,1,1,0,0,0,1,1,1,2,2,1,2,0,2,2,1,0,2,1,0,1,2,1,1,2,2,3,2,4,3,3,2,4,4,3,4,2,0,1,4,1,3,3,2,4,3,0,1,3,1,0,2,2,1,4,2,3,3,3,3,2,2,3,4,4,0,1,1,3,3,4,2,1,0,3,2,4,4,0,1,3,4,3,3,0,2,2,1,4,4,2,4,4,4,1,3,2,3,2,0,2,2,0,1,2,0,2,1,1,1,1,3,2,0,1,2,1,0,4,0,0,3,0,2,3,4,0,3,3,2,2,1,2,2,2,4,2,3,3,4,0,2,2,0,3,4,0,3,1,3,0,2,2,1,3,3,2,0,4,2,4,0,3,1,2,4,0,4,2,3,4,2,4,0,1,3,2,3,4,3,1,1,3,3,2,1,4,0,2,2,0,4,3,3,0,4,3,2,0,3,0,0,4,2,4,2,3,0,2,0,2,3,2,4,2,2,2,2,3,1,3,1,2,1,1,0,1,4,3,4,2,2,0,2,3,4,4,0,4,4,0,3,0,4,3,3,3,0,1,3,3,0,3,2,4,1,3,1,2,3,2,0,2,1,3,2,0,0,4,3,2,1,3,1,0,4,0,2,2,0,3,0,4,1,2,3,3,1,0,2,0,1,1,0,1,3,3,4,3,2,1,0,2,3,0,4,0,0,0,0,0,0,3,3,0,0,4,2,1,2,0,2,3,3,0,1,4,2,4,2,4,2,3,3,0,0,3,0,1,0,3,3,4,0,4,0,2,3,3,3,0,4,1,4,3,2,2,4,0,1,0,1,3,3,1,2,2,3,0,4,0,0,2,1,2,2,3,1,3,4,1,4,3,1,2,1,3,4,4,3,1,0,3,4,3,3,3,3,4,3,2,4,3,3,2,0,1,3,1,3,1,3,0,1,1,3,2,4,2,3,4,4,0,4,3,1,1,3,1,3,4,4,3,2,1,3,0,2,2,3,2,2,2,3,1,4,3,2,3,1,3,3,3,1,3,1,4,3,4,0,1,3,2,2,0,4,3,1,2,1,3,4,1,0,4,3,0,4,3,3,4,3,0,1,1,3,3,2,4,1,3,3,0,1,3,2,4,3,3,3,3,1,1,3,4,3,2,3,4,2,4,3,3,4,1,3,3,3,3,0,3,2,3,3,4,2,3,3,1,3,1,3,2,1,3,4,2,1,3,1,4,0,3,3,0,1,1,3,1,4,3,1,4,3,6,4,0,6,3,4,5,4,1,3,6,4,5,1,4,6,3,2,6,4,4,6,0,1,6,3,3,2,1,4,1,1,4,1,3,0,5,0,4,2,3,5,2,4,0,6,3,6,3,0,2,6,0,5,4,2,1,4,6,6,5,3,4,2,6,1,4,3,5,4,4,1,3,2,6,0,0,3,1,5,6,1,6,2,1,4,0,5,3,1,0,3,0,3,1,3,2,5,2,6,1,4,4,0,6,0,0,0,3,3,4,5,5,6,4,3,2,5,3,5,6,1,4,4,4,3,3,4,6,2,2,5,4,3,0,1,2,1,5,5,6,4,2,1,0,5,0,5,3,5,5,0,2,0,1,4,6,1,6,3,1,4,0,5,5,4,2,6,4,5,1,6,3,1,0,5,1,3,6,4,2,2,6,2,6,0,4,4,6,3,2,5,1,0,3,2,4,2,3,3,2,5,6,3,2,1,0,4,1,4,4,1,4,0,5,4,4,0,3,1,3,5,5,6,5,1,1,3,1,1,3,3,6,0,6,3,3,6,2,3,3,0,4,1,6,6,2,2,5,4,3,1,4,6,4,1,4,1,3,5,2,3,0,1,0,3,1,6,0,5,1,0,2,5,2,4,3,2,6,6,2,4,1,5,0,6,1,3,4,2,5,4,3,4,4,1,2,1,5,4,3,6,4,6,4,3,6,1,4,5,6,4,4,6,4,1,6,4,2,6,3,4,2,5,1,4,6,6,1,4,1,4,5,6,1,4,4,1,6,4,1,1,1,4,4,6,4,1,0,0,6,4,5,3,4,0,5,4,5,4,2,3,0,6,4,4,6,2,4,1,6,2,6,4,5,5,4,0,1,3,4,2,5,4,1,5,2,4,2,2,2,4,3,1,4,4,3,3,4,2,5,4,4,6,2,4,4,0,3,4,4,6,4,4,5,2,4,6,5,3,6,4,3,1,4,6,4,3,2,3,4,3,4,0,5,9,2,7,9,2,2,10,8,9,0,10,2,7,6,4,3,9,4,2,7,1,7,7,9,8,9,2,6,6,10,8,7,9,10,2,5,6,5,5,2,4,1,1,9,7,2,10,6,8,4,6,9,2,9,0,0,5,0,7,10,2,9,10,3,5,3,1,10,1,9,4,2,2,8,9,3,0,1,9,3,8,10,8,3,9,2,8,2,5,6,5,5,4,2,7,5,1,9,10,1,9,2,10,7,10,1,7,6,9,2,4,3,6,10,10,8,4,10,4,1,10,1,9,1,8,2,9,6,5,5,1,4,7,2,5,1,9,9,3,0,9,9,4,10,0,4,9,10,9,5,8,3,5,7,8,5,5,9,2,2,3,3,0,8,10,2,1,6,0,6,9,1,10,5,0,7,8,8,2,0,10,9,6,7,9,3,9,8,6,9,3,2,4,4,3,9,4,10,9,6,0,1,9,9,9,7,8,9,0,8,5,7,6,6,9,1,10,9,3,1,9,7,7,9,10,4,9,10,9,9,7,9,9,9,10,9,1,8,9,1,6,9,3,0,1,9,5,10,9,1,8,9,10,6,1,9,4,10,9,5,10,3,9,7,8,9,8,10,2,9,2,9,9,4,6,9,6,0,1,9,10,10,1,9,0,8,1,9,7,9,10,4,1,9,8,5,9,2,8,9,3,9,1,9,0,8,1,9,4,0,2,9,0,10,5,9,5,4,2,9,3,2,2,11,2,12,11,2,2,12,3,11,4,2,11,11,10,11,3,2,3,2,12,8,11,12,12,8,12,2,1,1,8,5,7,11,3,2,4,1,1,3,11,8,5,1,11,12,2,10,10,7,11,6,0,4,11,8,11,10,11,2,12,2,2,6,12,9,12,2,8,12,3,11,6,10,2,9,0,6,5,3,5,9,11,11,4,10,11,9,2,11,8,4,0,4,7,8,7,0,9,12,1,11,7,12,11,0,4,0,2,9,1,11,3,2,1,10,0,3,0,9,1,1,0,9,0,5,0,0,4,11,1,0,5,7,11,8,7,9,6,7,5,3,5,0,12,11,4,11,2,0,2,4,4,4,5,4,12,4,9,5,4,6,7,11,3,11,10,1,0,0,2,11,2,11,11,12,11,5,1,11,8,12,11,6,5,11,7,3,5,3,4,1,11,4,11,6,11,8,10,11,6,6,11,9,11,7,8,1,11,9,10,1,11,0,10,11,7,11,11,4,4,11,5,1,11,3,2,11,9,11,3,8,11,12,10,2,11,7,1,11,7,11,11,12,11,10,7,11,11,12,11,12,7,11,6,3,11,12,8,2,11,2,6,3,11,6,4,2,11,7,6,14,3,16,14,1,3,10,7,14,1,3,3,10,0,2,14,12,3,6,0,12,11,14,8,7,3,12,9,5,6,13,14,5,3,9,14,6,13,14,14,4,1,14,15,3,3,9,13,16,8,1,11,1,14,14,14,6,16,4,4,3,1,12,13,12,2,5,13,1,14,16,3,9,13,13,11,9,0,1,7,16,9,0,1,14,11,3,5,2,13,1,9,14,3,13,14,16,5,1,14,3,6,6,0,16,12,9,10,1,14,16,15,3,14,14,6,6,14,7,15,8,2,3,2,2,6,6,3,1,14,9,6,13,15,4,14,4,6,7,6,10,7,0,1,1,14,11,16,3,14,8,0,6,12,5,12,15,1,8,16,15,14,8,13,13,3,12,0,9,14,14,4,14,16,14,1,15,14,11,13,14,8,16,14,13,14,15,1,7,9,3,14,2,12,14,1,15,14,3,14,11,16,14,15,10,14,14,14,14,3,14,16,14,3,11,1,14,10,15,14,14,14,16,14,8,15,14,15,16,14,9,15,14,9,13,1,14,16,13,14,3,11,1,14,5,16,14,7,2,17,2,18,17,4,2,11,2,17,5,2,6,17,17,17,6,2,3,10,12,1,17,16,14,11,2,4,3,17,13,18,17,8,2,7,16,9,2,18,2,3,17,11,2,7,16,5,1,11,11,11,17,0,14,15,13,11,10,1,2,14,6,9,15,0,13,12,17,2,2,14,3,7,5,16,0,5,17,7,9,10,17,18,2,11,6,3,0,6,8,7,4,0,13,16,17,16,12,7,10,1,12,15,12,1,17,13,18,2,8,17,8,5,12,6,0,9,15,15,6,14,0,4,6,17,12,1,14,8,1,17,8,2,14,14,16,6,16,14,14,13,2,9,5,4,13,0,18,0,16,11,10,15,13,1,17,5,17,17,1,18,17,1,18,17,7,17,6,18,17,11,0,15,7,11,10,8,17,5,17,0,12,17,16,18,17,0,17,17,14,9,17,2,17,17,7,18,17,11,14,1,17,4,18,17,8,17,2,14,17,3,18,17,8,15,17,6,18,17,18,13,17,7,18,17,1,16,17,3,16,17,11,18,1,17,4,17,17,4,10,17,14,9,17,14,16,17,1,15,17,9,1,18,5,21,18,2,5,19,3,18,3,5,1,9,9,1,18,21,5,3,5,20,3,18,9,8,3,5,1,6,15,5,17,18,7,22,5,12,18,12,14,15,21,21,18,9,5,22,1,19,18,1,16,5,1,18,18,7,9,15,8,2,5,17,14,1,13,16,19,19,18,20,5,19,3,11,0,21,16,3,18,1,2,18,1,18,5,18,22,18,4,13,5,11,7,18,5,21,18,13,18,3,22,18,7,22,18,6,22,18,2,15,18,6,22,18,1,19,18,17,22,18,7,22,18,14,18,9,18,5,18,17,22,18,3,22,18,22,18,18,21,18,7,22,18,12,18,10,19,18,3,19,18,3,18,5,13,27,2,24,27,2,2,15,2,27,3,2,13,17,25,1,27,2,2,23,26,24,3,27,22,22,4,2,22,2,17,8,25,1,27,8,28,2,1,1,25,16,9,28,19,3,27,7,2,5,27,18,21,10,14,3,1,27,26,12,1,8,14,13,2,10,27,1,23,18,2,27,6,27,2,2,14,19,16,8,10,2,26,6,1,1,24,27,4,27,10,27,0,21,9,28,9,27,28,27,13,27,21,27,27,5,23,27,15,27,10,27,27,27,6,27,27,23,27,27,9,27,19,27,27,10,27,23,25,27,20,27,28,21,27,20,25,27,21,28,27,14,27,27,24,26,27,5,13,27,24,23,27,22,26,27,13,24,27,4,27,28,3,29,28,1,3,16,3,28,7,3,8,16,19,28,1,3,24,12,25,28,29,20,4,3,13,13,13,26,30,28,20,3,12,25,9,2,28,14,4,28,6,3,6,18,18,1,1,5,10,28,25,23,13,12,29,30,3,27,19,11,28,26,24,28,28,10,3,6,10,25,25,11,12,7,2,24,5,27,1,28,7,28,26,28,15,0,17,18,3,30,28,11,28,30,28,5,28,1,30,28,7,28,10,28,4,28,26,29,28,6,30,28,13,29,28,28,28,26,28,28,15,29,28,11,30,28,26,28,30,30,28,21,28,15,26,28,16,28,28,25,28,28,17,29,28,1,24,35,2,33,35,6,2,24,6,35,10,2,30,4,35,35,7,2,1,27,20,7,35,32,20,6,2,4,11,18,29,8,35,2,2,33,18,23,23,10,31,4,35,6,2,9,1,16,32,1,35,35,4,35,33,34,13,27,28,31,1,35,3,2,20,27,14,32,12,20,22,1,15,19,8,1,35,23,36,35,22,36,35,10,24,33,7,35,13,36,35,33,35,35,36,35,22,36,35,2,35,15,35,25,0,35,23,11,34,35,27,35,35,8,35,29,34,35,16,36,35,2,32,35,7,33,35,23,32,35,4,35,29,34,35,7,35,17,32,35,1,34,35,6,38,35,1,6,23,35,14,40,6,6,39,33,4,35,6,6,6,20,32,5,35,5,31,4,6,30,20,8,31,3,35,20,6,27,21,24,34,13,26,35,13,6,10,39,11,27,4,15,12,35,21,10,35,2,16,29,35,4,6,6,10,29,12,24,38,35,23,20,7,1,35,10,35,10,35,38,21,27,40,0,40,35,13,35,6,35,30,35,40,35,1,35,38,35,21,40,35,12,40,35,11,40,35,35,35,2,39,35,12,40,35,35,35,11,35,4,37,35,8,35,0,39,35,15,35,25,35,35,8,40,40,3,42,40,1,3,42,5,40,8,3,21,28,19,40,7,42,3,24,20,39,1,40,1,39,12,3,24,27,5,36,26,3,40,7,3,38,23,6,17,16,27,34,40,4,3,19,4,18,37,24,22,38,40,37,15,4,42,22,37,2,40,36,3,18,37,34,16,29,24,7,24,41,28,3,1,40,30,40,27,40,2,25,19,13,1,40,8,42,40,4,40,13,42,40,17,40,42,40,29,40,7,40,24,40,40,40,40,27,36,40,34,40,13,40,14,40,40,6,40,41,40,24,40,40,21,40,25,40,18,37,42,5,45,42,3,5,40,8,42,1,5,41,9,35,2,42,12,5,3,19,29,1,42,1,19,1,5,45,45,18,14,42,1,42,6,5,9,14,46,12,35,40,46,42,5,5,32,9,24,17,30,20,36,42,17,13,42,14,31,43,42,16,5,33,45,5,11,22,24,44,26,42,41,6,42,35,42,14,46,42,27,43,12,46,3,42,15,42,10,46,42,34,45,42,3,42,30,42,46,42,17,42,18,46,42,37,42,1,42,40,42,3,42,20,42,30,42,26,42,22,42,16,42,41,46,51,2,49,51,3,2,38,9,51,3,2,45,4,7,1,51,9,2,1,18,29,8,51,5,13,2,29,15,27,1,0,1,51,15,2,41,34,42,10,13,4,34,2,51,28,52,2,23,12,37,0,52,23,45,1,51,4,20,11,15,31,22,51,12,2,11,16,8,6,44,39,0,27,51,31,52,51,11,51,27,51,11,27,21,12,12,51,20,51,33,51,9,51,50,52,51,46,51,15,51,52,51,23,51,51,36,51,28,51,24,51,11,51,26,50,51,38,40,51,15,51,8,51,49,48,51,5,51,25,52,57,2,58,57,5,2,40,2,57,8,2,0,38,18,2,57,10,2,50,2,32,16,57,47,32,1,2,15,39,4,25,28,1,57,6,2,1,8,38,21,51,25,39,57,3,2,26,32,25,13,11,51,33,1,57,58,39,13,23,24,57,57,9,2,32,34,47,16,44,7,14,11,27,38,37,1,57,11,57,35,57,6,45,56,33,2,57,9,58,57,9,57,22,57,23,57,36,57,6,57,14,58,57,58,57,36,57,49,57,57,22,58,57,20,57,22,57,47,57,57,15,58,57,34,57,59,2,60,59,7,2,40,3,59,12,2,29,3,49,59,2,2,56,1,57,59,18,50,9,2,6,16,44,15,28,59,18,2,15,1,14,38,8,33,42,2,59,3,2,48,54,30,8,11,26,48,1,59,51,23,25,44,35,39,59,10,2,52,25,25,42,57,32,4,36,13,36,35,3,59,2,59,13,59,28,25,43,58,37,59,4,59,11,59,5,59,35,60,59,15,59,20,60,59,39,60,59,24,59,60,59,44,60,59,3,59,51,60,59,31,59,31,58,59,17,59,52,60,59,55,65,2,63,65,6,2,54,8,65,2,2,55,49,63,65,7,2,64,17,46,3,65,55,49,25,2,23,7,16,0,21,2,65,9,66,2,27,21,64,55,4,27,57,3,65,22,2,37,1,0,56,5,22,17,65,46,21,20,41,52,1,1,65,5,2,13,59,6,51,29,28,55,33,18,52,63,1,65,18,65,11,65,3,11,51,21,1,65,2,65,24,65,54,65,9,65,17,65,26,66,65,15,65,42,65,65,5,65,66,65,4,65,23,66,65,14,65,47,66,65,23,64,7,69,64,4,7,41,4,64,18,7,29,13,10,1,64,2,7,19,22,53,64,62,43,4,7,40,1,26,17,53,64,48,7,23,58,21,55,29,28,12,64,27,64,49,67,52,18,32,28,64,3,64,4,64,4,64,7,30,65,69,24,64,19,64,21,64,35,64,33,64,26,64,12,64,4,64,50,70,64,24,70,64,2,64,70,64,4,64,33,70,64,26,70,64,7,64,48,65,64,6,68,64,8,67,68,5,70,68,2,5,56,16,68,9,5,48,23,45,68,10,5,18,39,53,3,68,15,72,5,69,32,33,23,15,2,68,5,5,25,29,46,20,26,52,69,1,68,7,68,62,57,57,33,10,68,8,68,25,68,13,68,46,20,21,27,4,68,3,68,10,68,11,68,8,68,22,71,68,1,71,68,53,68,59,68,19,68,17,68,5,68,72,68,63,68,40,67,68,64,72,76,3,78,76,9,3,66,2,76,5,3,68,28,19,76,4,3,48,59,60,76,19,57,3,42,30,1,51,44,4,76,3,3,62,59,40,7,52,45,29,1,76,4,78,76,25,76,25,76,9,76,68,67,7,42,1,76,11,76,52,78,76,44,76,7,76,13,78,76,3,76,66,76,13,76,48,77,76,16,76,18,76,49,76,78,76,60,76,10,76,76,59,81,2,82,81,3,2,42,4,81,9,2,17,32,76,1,81,3,2,42,23,65,1,81,18,24,1,2,53,0,73,0,7,81,17,2,75,55,65,19,31,12,35,81,15,81,7,81,47,81,4,81,74,17,3,11,8,81,9,81,38,81,32,81,18,82,81,44,81,40,81,4,81,17,81,63,81,39,81,66,81,16,81,82,81,64,81,80,82,81,58,81,21,82,86,3,82,86,3,3,72,4,86,1,3,15,80,82,1,86,7,3,79,40,65,86,6,12,5,3,4,52,82,33,16,1,86,26,88,3,52,70,8,51,44,15,85,2,86,17,86,20,86,34,86,9,86,18,44,40,84,1,86,1,86,24,86,7,88,86,3,86,71,86,15,86,14,88,86,8,86,32,86,17,86,6,86,22,86,11,86,88,86,6,86,79,87,86,34,86,4,92,5,96,92,9,5,80,6,92,3,5,88,58,92,92,5,5,32,1,65,92,7,59,12,5,20,34,34,66,22,92,5,5,94,78,86,0,81,59,30,92,3,92,5,92,15,92,35,92,10,73,85,11,9,92,22,92,59,92,28,92,94,92,0,96,92,66,96,92,24,92,14,95,92,11,92,7,96,92,7,96,92,79,96,92,21,92,96,92,93,92,21,99,2,97,99,3,2,78,1,99,2,2,67,20,90,2,99,6,2,24,29,76,4,99,47,64,2,52,100,100,49,67,1,99,31,2,21,84,48,78,39,64,79,1,99,7,99,31,99,24,99,38,99,55,72,95,79,87,99,12,99,63,99,66,99,9,99,3,99,27,98,5,102,98,2,5,88,2,98,11,5,30,9,96,98,5,5,49,71,70,1,98,51,97,5,11,94,101,86,101,1,98,5,5,88,29,81,20,94,23,74,1,98,5,98,8,102,98,2,98,2,98,58,7,39,21,1,98,101,98,16,98,9,98,74,98,16,98,6,105,2,103,105,5,2,79,13,105,8,2,79,22,52,1,105,16,2,95,24,105,2,105,66,3,3,2,95,83,83,61,94,2,105,8,2,57,42,61,0,6,48,37,105,4,105,2,105,24,105,18,105,15,101,8,8,105,45,105,9,105,10,105,12,105,29,105,34,103,6,108,103,1,6,98,11,103,4,6,66,102,107,103,14,6,86,34,102,1,103,87,93,6,69,75,16,55,71,1,103,11,6,28,103,65,8,37,53,50,1,103,1,103,1,103,15,103,23,103,9,94,61,83,6,103,43,103,9,103,66,103,24,103,32,103,52,110,3,101,110,8,3,62,110,7,3,71,30,59,1,110,5,3,28,38,98,3,110,71,87,3,56,83,45,57,108,110,3,3,27,10,56,98,4,62,23,1,110,4,110,4,110,22,110,1,110,73,76,59,53,3,110,52,110,11,110,9,110,11,110,15,110,16,124,3,126,124,3,3,97,2,124,7,3,82,115,84,124,15,3,8,55,104,3,124,126,119,14,3,4,60,95,64,107,124,11,3,8,99,15,97,33,25,119,124,8,124,9,124,30,124,25,124,82,71,50,33,16,124,15,124,13,124,73,124,4,124,54,124,60,129,2,127,129,3,2,109,9,129,19,2,22,4,66,2,129,10,2,104,116,72,3,129,19,6,6,2,44,126,9,97,124,129,6,2,103,28,125,83,40,122,50,129,9,129,6,129,9,129,9,129,109,130,96,129,25,129,15,129,19,129,11,129,90,129,24,129,12,134,3,131,134,6,3,95,1,134,7,3,3,102,116,1,134,1,3,34,21,105,4,134,122,80,1,3,119,93,67,20,0,2,134,1,3,61,135,36,12,40,40,61,1,134,14,134,4,136,134,18,134,12,134,130,29,88,129,1,134,57,134,38,134,21,134,39,134,53,134,11,137,2,138,137,6,2,96,7,137,10,2,118,10,46,4,137,9,2,21,36,103,4,137,87,70,3,2,106,66,130,48,110,137,7,2,10,8,106,77,41,75,120,137,22,137,2,137,23,137,12,138,137,70,100,35,105,9,137,32,137,9,137,12,137,58,137,75,137,3,147,2,145,147,3,2,107,7,147,2,2,55,33,105,1,147,19,2,123,25,140,2,147,20,146,2,51,143,148,42,74,147,33,2,110,104,9,52,91,121,147,4,147,29,147,5,147,65,147,85,5,80,27,147,10,147,43,147,13,148,147,49,147,3,147,54,145,6,149,145,1,6,89,13,145,11,6,15,18,125,145,9,6,43,122,140,9,145,96,126,6,6,142,20,49,104,21,1,145,1,6,147,107,77,6,101,121,109,1,145,12,145,24,145,9,145,11,145,12,145,20,145,2,145,39,145,22,145,4,152,5,152,152,1,5,136,11,152,7,5,144,43,130,3,152,14,5,153,40,97,3,152,52,114,2,5,93,61,124,22,61,152,29,5,57,152,43,137,72,110,77,152,9,156,152,12,152,14,152,9,152,42,56,112,15,5,152,33,152,116,152,25,152,56,152,15,152,145,161,2,159,161,7,2,91,8,161,3,2,156,25,83,161,9,2,6,83,132,1,161,127,162,15,2,0,15,125,120,111,3,161,11,2,69,10,103,38,31,112,39,161,24,161,71,161,8,161,59,161,95,71,120,45,161,6,161,3,161,34,161,15,161,28,161,37,162,5,166,162,7,5,120,3,162,3,5,2,38,75,2,162,10,5,113,56,149,2,162,122,165,5,148,143,109,68,85,162,24,5,57,41,140,131,142,10,142,162,10,162,32,162,14,162,8,162,48,162,85,162,17,162,14,162,9,162,54,171,2,169,171,2,2,102,1,171,6,2,107,134,27,1,171,5,2,27,158,125,2,171,104,56,2,58,106,48,164,156,1,171,12,2,22,159,0,166,46,64,29,1,171,6,171,7,171,6,171,5,171,19,171,3,171,42,171,20,171,4,171,9,177,2,172,177,4,2,109,1,177,2,2,109,55,91,7,177,6,2,73,144,163,177,64,40,2,87,49,150,71,115,177,28,2,1,177,8,76,43,83,103,2,177,18,177,4,177,11,177,42,177,143,85,31,8,6,177,35,177,69,177,12,177,3,177,107,177,45,179,2,177,179,6,2,105,6,179,21,2,169,163,177,179,4,2,149,22,108,2,179,168,107,11,2,88,57,94,104,154,179,24,2,10,12,175,122,45,141,171,179,8,179,9,179,36,179,43,179,2,179,6,179,19,179,15,179,7,179,122,172,19,190,172,4,19,100,7,172,1,19,10,10,110,1,172,14,19,171,139,164,2,172,124,62,19,156,74,173,47,113,172,6,19,151,7,90,49,25,168,79,172,12,172,2,172,2,190,172,48,172,50,172,3,172,20,172,70,172,35,172,96,188,5,192,188,1,5,148,6,188,7,5,172,8,149,188,8,5,154,34,145,10,188,27,168,8,5,89,0,77,51,20,188,1,5,28,46,90,152,135,52,155,188,39,188,9,188,5,188,18,188,8,188,3,188,9,188,80,188,11,188,100,195,2,192,195,3,2,124,16,195,4,2,173,79,124,1,195,6,2,29,96,176,195,8,127,13,2,42,73,8,137,121,195,14,2,163,90,9,141,130,15,168,195,39,195,35,195,6,195,19,195,52,195,13,195,25,195,75,195,8,195,23,196,3,193,196,1,3,162,7,196,3,3,79,58,90,196,3,3,159,23,160,1,196,141,177,8,3,9,54,31,158,171,196,1,3,151,57,69,138,197,192,33,196,10,196,13,196,19,196,19,196,37,196,15,196,1,196,7,196,8,196,23,209,2,207,209,2,2,161,8,209,13,2,133,194,81,209,3,2,29,87,200,2,209,26,139,19,2,125,87,148,61,30,1,209,7,2,27,84,184,126,145,50,8,209,12,209,12,209,17,209,12,209,33,209,8,209,69,209,14,209,7,209,54,220,3,221,220,6,3,163,6,220,1,3,196,24,68,2,220,6,3,138,98,139,2,220,64,164,1,3,62,99,87,177,118,1,220,8,3,213,151,64,105,11,94,64,1,220,23,220,1,220,7,220,25,220,47,220,12,220,22,222,220,27,220,69,220,8,225,2,220,225,2,2,143,1,225,5,2,135,24,174,1,225,18,2,106,176,151,2,225,183,24,3,2,77,93,12,199,22,225,2,2,94,142,127,96,160,99,123,225,2,225,8,225,34,225,12,225,22,225,17,225,10,225,2,225,49,225,142,223,6,228,223,1,6,162,7,223,8,6,186,160,24,223,7,6,205,62,193,8,223,50,117,15,6,98,167,158,135,185,1,223,2,6,145,9,172,6,25,140,131,223,47,223,2,223,15,228,223,8,223,40,223,48,223,37,223,154,223,9,223,103,230,3,232,230,1,3,158,4,230,17,3,32,215,122,3,230,4,3,181,135,202,12,230,146,56,7,3,48,3,102,71,28,3,230,5,3,20,216,19,31,114,21,96,230,14,230,4,230,25,230,13,230,5,232,230,153,230,24,230,18,230,63,230,41,232,7,237,232,11,7,132,11,232,2,7,200,60,237,1,232,17,7,54,202,201,1,232,88,2,3,7,108,127,226,68,57,232,8,7,216,81,101,182,113,14,235,1,232,2,232,9,232,24,232,7,232,63,232,16,232,92,232,15,232,93,232,74,234,7,238,234,1,7,152,14,234,7,7,5,6,83,234,2,7,153,212,173,1,234,125,236,7,55,208,145,27,29,1,234,3,7,17,197,22,168,109,10,42,234,11,234,14,234,11,234,1,234,17,234,106,234,9,234,104,234,20,234,41,245,6,242,245,3,6,200,3,245,3,6,179,151,247,1,245,8,6,173,215,142,7,245,106,187,4,6,149,34,45,110,138,1,245,26,6,232,201,15,20,20,53,192,1,245,15,245,9,245,8,245,13,245,4,245,11,245,79,245,38,245,92,245,67,254,3,251,254,6,3,187,16,254,4,3,138,18,62,3,254,31,3,162,140,179,254,50,201,1,3,20,180,225,12,97,254,40,3,20,148,249,173,215,225,13,2,254,5,254,8,254,10,254,35,254,48,254,22,254,3,254,9,254,104,254,16}; uint16_t __nmod_poly_cp_primes1[] = {263,269,271,277,281,283,293,0}; uint8_t __nmod_poly_cp_sm_coeffs1[] = {5,14,5,13,250,222,1,1,7,227,3,6,145,231,0,2,180,47,252,162,174,172,0,2,9,8,12,101,120,1,6,232,220,4,2,61,243,2,20,150,132,215,63,165,126,0,6,2,3,2,207,207,0,22,69,199,1,10,74,10,1,10,130,237,205,116,210,162,0,5,3,1,1,9,33,1,9,176,187,4,4,241,253,0,5,202,180,40,240,218,183,4,3,1,7,5,13,151,1,19,140,195,4,6,138,145,2,36,191,58,116,103,68,202,0,3,3,5,3,68,199,0,8,232,179,11,0,100,185,3,4,56,49,229,96,8,20,0,2,2,3,2,210,128,1,8,239,175,29,0,184,28,0,3,157,167,212,125,210,159,0}; uint16_t __nmod_poly_cp_md_coeffs1[] = {258,261,171,225,170,29,261,119,198,245,45,267,268,262,206,131,267,214,10,186,264,180,265,269,205,81,114,186,266,126,256,133,256,272,274,222,118,159,110,177,260,237,206,115,278,280,176,27,279,70,148,191,13,258,28,280,282,238,73,32,65,136,219,68,271,14,291,292,166,260,195,190,208,24,46,186,144}; uint16_t __nmod_poly_cp_primes2[] = {307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,0}; uint8_t __nmod_poly_cp_sm_coeffs2[] = {5,7,2,5,0,6,0,1,17,3,3,1,1,10,19,1,10,2,8,7,0,4,8,8,2,7,6,2,2,7,1,0,3,1,3,4,1,5,1,0,10,2,25,2,0,5,0,12,2,9,13,3,3,4,1,2,2,4,3,2,0,10,0,36,3,3,0,1,1,16,1,2,7,3,2,1,4,1,0,0,6,10,3,3,0,13,2,15,2,5,15,2,0,7,0,14,2,5,2,4,0,14,13,11,5,1,7,1,1,6,10,2,2,2,2,4,1,24,0,2,5,2,12,7,0,12,1,6,3,3,2,4,4,5,0,1,21,3,12,5,0,7,3,8,2,11,4,4,2,4,8,0,2,2,10,15,0,21,5,18,7,2,2,7,4,1,5,2,5,1,6,5,0,6,10,27,15,3,0,1,0,1,0,16,2,4,4,4,1,6,2,3,3,1,2,9,2,28,0,6,13,1,8,4,0,14,9,9,2,3,3,14,1,5,15,5,3,10,17,3,0,13,0,3,2,2,14,2,1,7,5,0,13,4,6,2,1,4,7,2,3,4,4,1,0,7,1,10,2,2,7,5,1,5,1,0,7,2,4,17,0,8,1,5,5,2,6,15,1,11,8,3,2,3,4,3,1,6,2,0,3,4,0,3,1,1,6,5,2,5,2,4,0,13,4,19,2,2,6,3,0,2,3,16,2,4,8,2,0,11,10,11,2,3,7,9,1,6,0,1,2,3,20,6,1,5,2,3,3,4,7,4,2,5,1,1,3,8,2,4,0,7,4,34,5,2,12,3,1,8,12,17,2,3,16,2,1,3,5,0,3,6,4,3,2,15,9,8,7,2,3,8,1,2,3,3,7,1,14,13,1,5,0,7,3,5,8,4,0,9,4,1,2,6,12,32,0,6,6,8,3,3,2,4,1,7,0,15,2,6,6,8,0,7,10,0,3,5,6,5,0,5,2,3,3,4,0,1,2,3,3,0,11,1,0,2,0,5,1,3,5,6,3,11,5,1,9,13,2,3,6,5,2,15,0,0,2,2,8,4,6,5,6,2,2,4,7,19,0,2,0,18,5,1,6,15,0,6,6,11,2,2,0,5,1,10,0,0,5,5,5,7,2,30,0,0,3,14,3,4,0,4,7,5,2,2,12,5,1,10,1,1,2,2,6,10,0,4,2,3,11,1,5,1,1,11,5,3,5,7,3,5,0,17,0,6,6,4,12,8,1,3,1,2,3,11,3,9,0,44,2,1,5,3,5,6,1,6,0,3,3,5,3,7,2,7,3,10,2,6,10,13,0,4,12,8,6,12,0,6,2,6,11,4,11,2,32,1,0,8,1,0,2,2,4,8,1,9,0,4,2,2,11,9,0,3,5,5,2,2,1,3,1,11,1,2,3,1,4,3,1,3,1,1,3,1,3,3,0,1,3,10,2,2,15,9,2,10,5,1,3,3,4,3,0,10,0,6,2,5,18,3,9,5,2,0,2,5,9,7,1,5,1,3,11,4,2,2,1,7,16,0,2,4,3,2,0,4,8,11,3,4,0,3,1,7,3,0,2,6,2,12,0,2,0,7,5,5,2,10,1,1,9,1,2,5,6,6,0,3,4,9,3,1,0,8,1,6,21,2,2,6,8,14,0,6,7,5,5,1,3,5,1,8,0,4,2,4,14,2,0,2,4,1,17,1,11,2,1,4,6,0,7,2,3,11,0,9,6,7,3,5,0,3,2,7,5,0,5,3,23,5,0,24,0,28,2,3,3,2,2,4,0,1,2,3,8,15,2,6,1,1,3,7,1,1,1,5,6,1,5,1,3,2,0,9,15,3,6,3,2,14,1,13,0,0,3,1,0,11,2,7,0,0,5,1,5,8,2,3,7,0,6,4,10,3,0,7,15,9,7,2,4,10,0,1,0,39}; uint16_t __nmod_poly_cp_md_coeffs2[] = {302,306,239,61,172,213,131,232,283,70,165,294,310,163,152,167,27,2,118,162,74,287,303,310,239,253,213,196,106,99,306,300,267,315,313,178,4,156,195,31,85,207,296,284,328,326,290,159,205,283,78,308,249,210,194,327,332,224,109,127,216,251,246,331,98,148,345,343,295,56,26,343,117,213,187,252,235,347,348,279,316,177,135,268,328,308,130,290,350,348,199,295,226,215,37,26,182,49,319,352,358,229,327,327,309,271,143,301,165,356,361,366,295,324,321,222,50,282,335,268,213,371,369,304,108,83,126,66,219,203,370,238,377,374,327,246,364,374,173,194,210,369,362,378,382,309,158,8,69,296,332,281,76,137,387,379,266,255,339,218,290,19,351,308,258,392,392,363,287,274,382,203,255,375,252,166,398,396,372,51,81,115,164,113,380,158,199,388,404,407,364,53,372,396,69,256,211,318,417,418,373,257,33,411,151,388,234,386,93,419,417,257,41,342,111,77,32,389,145,394,424,430,323,182,202,161,115,286,243,329,71,428,432,402,360,353,244,39,32,347,45,232,424,436,323,190,324,1,266,296,359,254,342,441,437,383,41,218,298,290,217,437,109,125,446,444,249,69,293,437,124,348,361,9,226,444,454,407,266,389,205,412,296,365,84,354,459,460,393,329,432,439,321,449,388,276,210,460,461,262,110,51,462,396,414,234,227,433,465,463,353,237,62,123,289,413,318,447,397,466,474,386,334,287,243,17,440,247,185,3,484,485,483,185,427,450,137,249,283,447,271,489,487,360,125,402,369,216,372,378,453,149,492,493,495,78,191,407,200,309,288,222,491,498,498,325,255,292,380,316,203,441,337,158,507,508,408,41,232,350,382,473,420,28,314,518,515,509,280,153,315,312,407,462,483,181,521,522,382,371,475,475,380,184,518,145,342,539,537,333,69,320,239,113,108,376,318,340,545,543,334,423,153,334,180,20,368,263,238,555,553,430,253,192,202,113,384,480,434,456,561,559,399,246,303,122,509,176,503,19,15,566,568,381,480,263,50,241,173,527,566,478,568,570,402,33,295,221,371,119,363,179,545,572,572,494,283,25,450,321,545,450,449,576,585,583,444,226,121,204,91,44,492,55,333,590,592,419,478,65,345,495,291,350,523,223,592,598,419,586,274,515,124,37,440,98,114,594,598,347,49,440,128,490,241,550,590,487,604,606,449,478,45,10,449,35,468,129,444,611,609,333,601,595,609,539,57,489,536,513,614,612,503,310,595,318,155,501,519,543,388,617,618,492,347,468,238,225,383,416,310,579,628,629,376,106,541,516,187,516,379,413,296,638,635,629,294,557,105,332,392,356,141,66,632,641,600,293,412,345,569,573,631,475,591,642,645,643,642,385,308,271,259,603,123,561,651,649,596,242,220,45,296,18,385,60,365,657,655,351,223,105,371,90,246,358,46,592,659,660,616,382,456,551,72,285,612,220,389,668,672,416,35,248,524,302,587,669,553,347,675,672,631,50,632,446,152,619,363,404,504,678,682,455,434,109,644,65,184,383,444,85,688,686,632,262,408,579,321,425,356,443,556,699,697,379,285,327,571,593,206,619,373,459,707,705,384,295,514,669,79,233,689,171,257,708,715,602,182,591,533,244,362,714,560,288,722,725,723,672,397,86,368,671,639,502,573,727,732,539,151,549,174,142,610,532,6,337,736,734,678,625,447,422,25,169,401,81,616,738,742,425,88,471,236,588,279,551,676,327,748,749,525,539,633,298,672,243,741,489,703,755,753,537,745,739,753,509,110,494,702,688,755,758,658,155,597,634,540,144,603,571,317,758,765,741,650,326,43,632,574,560,751,623,771,772,444,581,3,91,693,94,484,574,216,785,786,605,606,512,98,715,26,612,573,480,795,793,717,71,396,657,389,747,596,599,240,806,799,644,43,75,562,673,745,593,727,341,808,806,453,307,755,780,525,806,663,200,382,819,816,662,803,130,160,589,556,626,557,650,820,821,819,744,616,822,31,437,451,609,740,825,821,605,691,601,685,32,79,812,372,177,827,828,604,817,476,341,138,241,468,552,621,828,838,609,23,537,370,329,779,553,206,349,851,852,623,512,194,276,118,846,544,821,677,854,850,528,65,824,32,494,552,611,719,308,857,858,530,566,646,419,672,446,522,845,648,858,862,770,300,62,330,849,576,765,1,381,875,873,604,855,400,629,347,319,767,278,770,878,869,447,231,419,218,561,490,635,510,587,881,879,715,871,865,879,768,762,740,557,360,882,885,883,28,341,775,706,381,781,345,727,905,903,478,266,752,626,811,518,584,57,783,894,909,887,19,683,172,168,590,708,116,679,912,910,602,113,817,312,504,202,708,623,410,926,917,787,86,92,805,586,292,699,199,481,932,934,585,934,727,794,53,26,658,483,533,939,940,505,538,694,459,590,675,805,197,708,945,943,894,95,787,880,581,597,845,808,269,950,947,865,730,829,507,108,658,579,316,819,962,965,963,831,948,805,136,502,840,783,512,965,970,527,718,729,970,206,281,725,473,805,974,972,800,753,830,729,77,807,855,740,450,978,981,567,228,296,849,530,276,738,87,858,985,989,794,278,855,637,234,786,941,222,466,990,995,622,260,58,981,241,473,934,616,732}; uint16_t __nmod_poly_cp_primes3[] = {1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,0}; uint8_t __nmod_poly_cp_sm_coeffs3[] = {11,3,14,6,0,1,2,3,7,2,12,2,7,9,2,3,8,3,1,9,0,10,3,3,2,0,1,2,14,4,3,7,4,1,5,5,2,16,9,0,13,11,3,3,7,1,0,1,5,3,1,4,1,3,13,5,7,2,6,8,0,3,13,2,2,6,11,1,5,10,3,3,2,3,0,8,3,6,2,6,2,0,4,4,3,6,10,23,4,1,5,2,3,2,2,2,2,0,5,3,6,7,0,5,39,3,1,4,13,1,1,0,5,6,2,6,1,23,2,2,3,8,2,1,3,3,2,4,6,2,0,9,2,2,2,8,2,0,3,1,11,3,16,8,2,3,14,17,1,4,1,1,4,1,5,3,29,1,0,24,3,5,2,3,9,2,1,2,2,2,8,2,0,4,0,7,1,3,2,2,2,6,2,4,4,5,2,7,4,3,4,11,11,2,15,3,11,2,20,17,0,6,0,2,4,9,6,0,9,5,3,3,9,3,2,1,0,5,2,4,2,2,8,4,2,3,6,7,1,19,0,3,3,3,5,0,1,24,2,4,6,4,0,22,10,7,5,17,1,0,2,0,2,3,6,5,1,5,2,2,2,4,9,2,20,0,3,6,6,4,0,7,0,2,3,8,3,1,2,1,6,6,3,16,1,4,3,2,5,6,5,0,4,4,10,2,8,1,0,2,6,2,7,3,3,1,8,10,6,2,2,2,0,4,0,2,2,4,4,3,6,0,13,1,5,2,1,6,0,13,5,8,1,0,6,7,3,1,2,9,0,4,12,3,13,0,29,1,22,3,5,1,8,2,2,8,3,2,7,11,2,2,9,3,2,4,10,2,1,12,15,13,3,14,28,0,5,8,3,1,2,10,1,40,1,3,7,4,10,2,4,21,2,2,13,21,5,10,1,6,2,6,12,1,2,1,3,19,3,12,1,28,0,7,7,4,2,1,9,0,3,3,5,6,0,1,10,2,9,3,20,6,5,2,2,6,9,4,0,15,6,3,3,7,21,0,10,2,6,1,2,3,0,2,34,3,5,4,17,1,12,4,2,2,14,3,0,11,7,5,2,3,11,1,11,9,14,2,9,2,0,1,7,2,11,3,5,1,3,0,2,2,7,6,1,2,7,11,2,3,5,1,16,7,2,7,0,4,1,28,1,2,6,2,3,3,2,7,5,2,3,15,0,5,7,2,5,0,5,0,3,9,3,1,4,9,2,8,0,19,3,2,1,1,2,3,3,4,4,6,0,18,5,2,3,2,17,1,7,6,3,11,6,8,0,1,0,5,1,3,2,1,7,1,11,5,1,2,0,11,9,3,15,7,5,2,1,5,5,3,11,26,1,2,1,7,4,5,8,0,2,7,3,4,0,14,2,10,5,2,2,8,3,1,6,9,2,4,6,3,0,13,5,3,1,3,5,0,11,0,2,2,1,4,1,7,5,11,1,13,8,2,7,7,3,3,2,4,0,10,19,2,3,8,9,1,3,1,2,4,6,8,0,4,6,2,2,3,3,0,11,10,3,3,17,15,1,3,3,3,3,3,13,0,1,22,3,1,0,5,1,6,3,3,3,2,5,1,11,6,3,1,2,1,2,13,1,2,16,2,9,1,7,1,2,5,9,17,0,25,4,2,5,8,6,1,4,2,7,1,14,1,0,2,25,6,3,4,6,0,16,0,5,2,18,1,0,19,11,10,6,5,8,1,4,17,2,8,7,13,1,7,1,6,1,0,3,0,33,11,11,1,24,1,0,6,9,6,3,11,3,1,12,4,5,1,2,9,1,31,1,3,10,4,1,0,9,1,5,2,5,2,1,2,0,2,4,3,15,1,12,4,2,2,7,5,0,6,3,14,1,10,7,1,12,4,10,4,13,7,0,2,10,2,3,6,6,1,6,3,6,3,3,9,0,9,25,3,6,0,18,1,15,6,2,2,8,4,1,13,1,2,2,2,3,4,2,0,3,4,2,3,1,14,4,2,3,7,9,1,9,4,5,5,6,6,3,14,0,2,9,3,4,1,2,2,3,9,3,10,0,11,4,2,2,4,6,4,3,0,2,3,13,2,1,11,3,2,2,7,2,0,6,2,5,2,18,12,0,5,40,2,3,9,3,1,4,3,3,1,3,1,0,1,7,5,7,13,3,2,6,3,3,3,5,6,0,3,28,5,14,6,35,0,2,9,2,5,0,2,1,3,6,2,5,7,12,0,6,20,7,7,14,4,2,4,0,2,6,10,31,0,6,1,5,1,8,1,1,1,7,2,2,6,8,4,4,0,3,10,7,4,1,10,5,2,4,8,3,0,6,8,5,1,6,3,1,2,1,7,4,2,5,0,1,2,2,3,7,6,2,9,5,7,9,2,1,6,8,0,5,1,18,5,0,10,1,3,1,6,3,3,3,6,2,5,2,17,0,3,5,10,6,6,5,0,15,27,2,3,3,2,1,7,0,3,1,3,3,0,7,6,3,3,2,3,1,8,1,23,2,15,2,1,6,6,7,1,6,3,0,15,3,5,1,7,1,0,5,8,5,3,8,2,1,10,0,2,3,6,5,1,6,2,2,6,6,8,0,2,5,2,4,8,7,1,11,5,3,6,11,8,0,1,31,2,2,1,2,2,5,0,7,1,6,3,0,7,2,2,2,10,9,4,12,1,2,2,10,3,0,4,9,3,3,2,7,1,20,1,7,5,0,3,0,1,10,19,1,6,4,0,4,1,2,5,10,2,0,10,7,5,1,8,2,1,1,0,2,3,1,6,1,14,6,3,3,3,11,3,7,1,2,3,7,9,1,8,0,2,20,0,6,2,17,0,7,3,9,3,0,9,33,3,4,3,3,0,6,5,13,1,6,2,1,1,3,2,2,8,5,1,7,0,2,4,7,2,2,4,23,5,1,6,10,0,2,28,3,7,12,20,1,12,4,5,2,8,1,3,34,11,2,2,10,5,0,3,4,3,4,7,7,2,9,1,11,4,3,3,2,3,5,6,3,4,12,1,1,1,3,1,14,3,1,4,0,5,1,10,6,1,7,5,2,6,6,2,0,14,5,6,1,0,7,1,4,0,5,1,2,3,1,9,4,2,3,7,2,1,4,7,2,6,7,6,0,6,9,5,1,11,10,1,26,4,2,2,3,5,2,9,9,3,14,2,9,0,5,7,17,1,23,6,1,4,12,2,2,8,5,2,3,0,2,5,2,3,0,5,7,5,6,3,3,2,21,0,2,2,12,3,1,2,0,6,2,3,7,0,23,4,2,6,6,4,0,2,6,2,5,1,12,1,4,7,7,1,5,5,1,14,1,7,3,14,12,0,3,11,3,1,0,1,1,6,3,5,5,10,2,0,3,16,2,3,9,10,1,6,1,3,3,9,4,1,3,0,3,4,5,3,0,10,2,3,3,2,8,1,13,1,2,4,2,13,0,28,10,5,12,3,3,1,1,4,7,7,2,1,0,2,16,2,2,6,8,0,14,11,2,13,8,7,0,2,8,5,1,2,7,1,7,3,19,2,24,4,0,0,0,2,2,0,7,1,21,3,2,2,4,8,1,2,5,2,7,2,2,0,13,19,7,1,2,1,1,5,0,5,1,6,1,0,11,3,3,4,3,19,1,8,2,3,4,0,1,1,1,0,3,3,2,10,0,7,1,2,3,12,8,1,5,5,6,1,0,20,0,6,10,3,5,9,4,3,4,4,3,15,5,3,0,1,5,3,1,0,1,4,17,2,2,3,3,4,1,5,3,6,7,3,19,0,9,3,2,6,9,2,0,0,0,3,1,7,3,1,6,2,2,4,16,9,0,4,0,2,3,3,9,2,8,1,5,3,22,1,0,0,0,2,3,18,3,3,5,6,2,3,8,12,1,5,0,2,12,8,3,0,5,9,11,2,21,1,0,2,1,2,3,1,17,1,15,0,7,2,2,1,1,18,0,5,1,9,16,0,9,9,3,3,1,9,3,18,1,5,1,4,11,3,9,1,2,2,1,6,1,5,0,5,2,3,2,1,1,0,5,7,10,3,1,10,5,2,3,13,5,1,20,1,13,5,14,1,1,31,10,2,2,6,6,1,5,4,2,3,8,5,1,17,9,3,3,4,3,1,4,0,10,2,5,5,0,8,15,17,4,12,8,7,3,7,14,2,15,1,2,1,0,2,3,7,4,1,2,1,2,4,8,4,0,0,0,5,2,3,9,1,8,0,2,2,9,5,0,22,4,3,1,8,1,4,6,0,11,3,27,5,0,2,3,6,2,10,12,1,1,0,2,4,8,5,0,2,12,6,1,3,2,0,4,2,2,2,11,5,5,20,6,3,3,1,5,5,22,1,6,4,6,3,0,8,18,7,8,3,1,1,1,1,7,1,0,1,0,5,11,3,4,1,15,1,23,8,3,4,5,6,0,0,0,5,1,4,5,1,13,1,7,1,0,8,0,10,9,7,4,4,1,0,1,4,2,5,8,3,0,7,5,11,6,5,4,2,1,7,2,3,16,18,1,4,1,3,3,2,12,1,0,0,5,1,15,1,0,5,6,10,2,8,4,1,5,5,6,1,0,6,2,2,18,6,1,7,7,2,2,11,2,2,3,3,0,8,3,3,1,0,20,2,22,1,3,6,4,17,0,1,3,3,1,3,1,0,4,11,2,2,0,8,1,7,1,6,2,2,2,0,6,9,2,2,2,9,0,7,2,10,15,6,5,0,5,8,6,3,7,12,0,1,6,2,2,7,3,1,4,0,3,5,7,9,1,7,3,3,1,7,5,0,0,0,5,10,3,15,0,10,16,2,3,7,6,1,3,4,11,2,3,2,1,5,6,22,4,12,5,0,5,5}; uint16_t __nmod_poly_cp_md_coeffs3[] = {998,1008,825,509,515,850,627,634,1010,1006,728,319,230,17,451,396,1017,1015,964,384,359,996,549,971,1011,1020,936,862,66,684,628,395,1017,1029,864,327,378,721,158,823,1028,1030,986,204,680,697,331,447,1036,1033,800,703,447,1025,17,930,1046,1038,929,616,685,338,330,422,1044,1049,994,335,627,680,736,789,1059,1057,649,95,552,875,180,187,1060,1062,628,379,917,483,429,979,1063,1065,1065,497,137,686,452,896,1084,1085,1079,795,168,171,58,941,1089,1090,947,93,72,774,1053,784,1088,1092,988,199,119,720,635,840,1094,1096,987,74,641,91,625,17,1098,1091,819,698,931,796,789,448,1107,1108,1102,86,1031,1004,684,1050,1115,1113,856,12,1014,996,14,815,1121,1122,1116,536,187,918,964,522,1118,1124,916,366,139,1122,885,669,1134,1148,687,490,331,594,789,953,1148,1152,870,656,903,254,473,991,1158,1161,1159,919,503,226,238,281,1169,1167,1112,1049,594,1042,1092,580,1174,1180,706,903,1129,989,628,75,1185,1181,758,324,472,882,699,213,1190,1187,826,148,475,1120,12,1185,1190,1192,1006,985,428,917,575,1090,1211,1209,879,72,125,608,1169,1122,1214,1211,888,1080,782,304,143,1200,1218,1220,715,761,50,1041,675,154,1227,1225,1159,400,1219,1216,953,983,1228,1229,662,1162,399,1152,85,1121,1235,1236,960,346,117,849,46,1163,1242,1246,792,439,679,474,240,1149,1257,1258,1049,1187,1008,1191,864,794,1275,1276,753,500,456,996,1270,428,1276,1277,916,871,896,159,336,1118,1281,1279,672,386,536,842,1259,1145,1283,1280,1105,314,308,1117,179,659,1289,1290,899,183,1164,1044,607,646,1287,1294,807,531,428,797,709,1093,1299,1295,1152,160,635,1068,1293,1108,1297,1302,816,1092,1278,1228,300,865,1305,1306,844,65,788,130,958,743,1306,1316,1015,576,1005,957,408,1211,1308,1320,1223,683,1020,1055,1130,1162,1324,1326,724,665,911,1208,1153,605,1358,1355,1349,124,977,824,164,34,1362,1365,1022,1108,514,507,407,1250,1371,1365,1269,1177,567,874,104,1202,1379,1377,1307,746,1373,168,723,970,1386,1395,964,1222,533,1164,111,696,1406,1404,968,156,1165,624,55,778,1420,1421,1419,169,1041,1357,730,830,1425,1426,1089,770,1252,250,1056,747,1423,1425,1425,1301,716,1226,469,1214,1430,1420,883,74,937,1421,283,456,1432,1438,1430,1336,31,1267,451,1118,1444,1446,909,1246,33,430,750,1300,1449,1446,759,1094,208,615,15,193,1451,1449,1368,1441,1435,1449,23,1381,1456,1458,855,406,1309,629,73,1115,1465,1470,1287,1228,728,969,1362,599,1478,1480,1372,1021,855,1436,968,651,1481,1482,1170,541,996,1168,1452,1464,1482,1485,1483,1289,808,1194,866,1283,1475,1487,1299,1485,269,254,61,1192,1491,1485,1120,102,499,465,701,1377,1497,1495,1270,844,588,698,1196,1357,1500,1509,1433,1032,1278,106,403,142,1521,1518,1123,1226,1518,67,1286,573,1529,1530,948,827,122,1129,314,1400,1538,1541,1539,796,1363,1391,132,1157,1547,1541,1336,1191,987,1422,311,1322,1550,1552,1330,804,1242,904,1399,643,1540,1558,1107,1236,514,1237,1473,514,1564,1565,1563,988,1370,855,278,1384,1569,1570,838,1460,986,1541,113,601,1576,1578,1447,234,358,1245,666,1226,1578,1581,1579,466,898,271,719,1438,1586,1594,1270,567,200,793,611,1205,1598,1600,962,830,956,296,1120,603,1602,1605,1595,1182,923,203,508,1279,1602,1597,1277,490,1348,872,518,1578,1610,1606,1279,812,1085,1532,734,563,1617,1615,1410,20,1190,330,277,281,1619,1617,957,1208,679,1337,3,1605,1624,1622,1176,1257,265,1071,398,1354,1635,1633,864,1387,1455,1448,1263,1123,1646,1655,915,692,904,988,1018,956,1660,1662,1534,1371,1128,1471,559,1500,1665,1663,1267,255,1656,1508,1126,602,1667,1665,880,163,99,1328,852,689,1691,1692,1539,422,793,1299,242,1558,1694,1692,1208,22,42,1228,806,255,1696,1686,1506,99,299,590,855,1498,1706,1696,1199,176,1012,1460,188,658,1718,1716,1662,1363,1406,424,182,1597,1720,1722,1046,79,102,1250,331,1513,1731,1726,1072,1679,69,1638,1640,728,1739,1740,1477,1515,1720,1643,169,868,1745,1743,1426,1284,142,545,1407,1329,1746,1746,951,1199,1699,1534,639,1196,1753,1757,1144,1665,1526,1332,212,1720,1772,1774,1224,74,792,1744,731,1365,1773,1782,1380,1263,639,1202,920,1652,1785,1783,1086,911,1515,794,1703,1616,1783,1781,1599,1091,771,688,212,734,1790,1796,1782,1504,636,1791,787,1424,1805,1809,1396,1516,1210,364,1098,1569,1818,1822,1574,555,751,1442,1245,1010,1828,1829,1827,534,187,1679,1123,818,1842,1845,1150,844,477,1225,846,815,1859,1860,1641,515,862,1352,64,776,1865,1866,1297,323,1719,924,1336,1826,1857,1869,1486,1351,593,903,1116,1627,1863,1870,1796,708,47,487,1667,1056,1875,1873,1329,877,362,1792,1677,1840,1873,1877,1690,1098,870,1781,850,1570,1886,1883,1877,822,364,26,1877,991,1899,1896,1198,467,1830,952,157,1755,1905,1906,1800,1237,383,1019,1122,572,1910,1908,1815,1407,956,1266,1499,1049,1929,1927,1239,786,504,729,939,1464,1928,1932,1144,86,834,950,816,1400,1947,1948,1024,454,100,1846,0,1216,1948,1949,1034,598,1950,1542,1119,702,1971,1972,1505,1421,1641,85,818,1438,1977,1975,1748,315,1590,1945,416,823,1985,1986,1727,478,208,981,1084,1883,1988,1990,1078,1873,75,1750,1102,1671,1995,1993,1836,1168,326,1724,1081,1712,1996,1998,1177,1171,423,1114,651,1798,1998,2002,1333,350,1856,1981,1532,353,2008,2004,1947,1530,1650,1233,1256,1168,2012,2016,1393,943,129,1843,10,1133,2025,2021,1899,1083,1623,2006,1995,87,2027,2028,1663,317,1791,1492,1332,1730,2032,2026,1377,755,1630,1937,1023,1657,2051,2049,1580,2041,2035,2049,1432,837,2058,2058,1625,1137,949,608,1964,829,2067,2065,1413,1268,1157,1365,1924,1763,2078,2080,1796,873,2034,1765,646,1414,2081,2079,1925,830,2053,790,1011,1762,2082,2084,1305,1567,114,517,1970,1931,2082,2080,1985,1492,977,1737,570,2054,2097,2095,1828,1169,1728,1204,747,1559,2104,2110,1916,117,1071,1472,2097,615,2108,2108,1278,456,1649,1853,1636,1520,2126,2120,1672,700,1338,1245,844,115,2129,2130,2051,1622,1717,1000,431,2105,2127,2136,1153,970,84,734,965,2084,2139,2140,1154,1939,860,1732,829,278,2140,2141,1638,802,1443,1616,1518,2089,2150,2145,1925,1732,2007,1833,1865,2027,2138,2160,1561,699,821,1898,439,967,2172,2177,2017,1709,2022,2038,2079,981,2198,2202,1600,731,1727,742,581,2028,2202,2205,1195,2074,865,508,1132,1570,2211,2209,2119,1438,1211,1450,0,2017,2219,2217,1282,2209,2203,2217,1126,2012,2235,2232,1387,1978,160,839,1056,797,2236,2233,2145,1910,490,1124,947,1594,2241,2234,1553,2141,92,1983,957,1339,2244,2249,1840,1081,1578,2067,1455,1129,2265,2266,1889,1447,170,1050,2206,1865,2267,2265,1609,2181,867,2260,172,2153,2270,2268,1913,1673,1140,2220,1769,1846,2274,2274,1462,1814,946,1240,1458,1648,2268,2283,2160,233,630,1812,386,1670,2291,2289,1256,435,1415,1935,2124,1905,2292,2292,1772,607,1036,2147,1213,2134,2307,2305,2173,94,164,1911,1532,1441,2308,2309,2175,1099,1270,424,309,1796,2331,2329,1591,966,990,1899,1892,204,2337,2329,1768,1112,764,2243,900,1724,2334,2339,1919,1291,342,1220,328,2061,2344,2342,1254,889,177,2337,743,2277,2338,2347,1822,773,1036,1247,1452,1725,2355,2352,2140,280,2291,1782,2317,1931,2369,2370,2087,860,370,1269,1314,1457,2372,2376,1684,299,83,975,1827,2178,2378,2379,2283,1568,1764,432,2290,74,2378,2382,2159,767,2110,372,1599,2180,2387,2385,1651,953,405,1962,1273,1724,2390,2392,2047,606,861,1633,678,757,2388,2398,1637,1344,89,1838,1220,30,2405,2410,1681,1092,1304,2016,813,1670,2414,2408,2350,167,2026,893,742,1272,2418,2421,1349,2166,1751,2050,2267,915,2435,2433,1592,2425,2419,2433,444,2275,2435,2438,2078,1678,1880,1270,1272,787,2442,2446,1426,1496,2409,2123,1269,1060,2457,2455,1737,885,1850,2138,114,849,2465,2466,1277,1060,1538,1507,1683,1543,2468,2472,1380,1517,348,2137,1146,1002,2475,2476,1955,80,1343,959,223,1104,2500,2502,2207,2195,972,1282,1979,1152,2504,2520,1993,277,659,1946,822,2454,2529,2527,1375,1051,184,2346,2207,1381,2537,2538,2069,1802,1911,1332,822,2293,2538,2541,2539,860,1428,1634,1813,1024,2547,2545,2242,2264,1711,1391,1819,2,2545,2549,2007,1355,1591,1888,1151,2487,2555,2553,2444,2545,2539,2553,2359,1177,2577,2560,1954,73,471,1709,1770,866,2584,2589,2159,1936,607,1663,2384,310,2586,2586,2226,946,1268,1392,371,1458,2606,2603,2597,1184,2345,1105,1030,2447,2612,2614,2248,644,2355,1514,1014,2367,2619,2620,1919,1136,283,2390,1379,1858,2630,2627,1393,773,318,1332,1843,111,2644,2646,1656,234,1628,1100,561,1736,2654,2652,1910,1392,1071,1723,370,538,2657,2658,1570,35,998,1901,629,1806,2658,2655,2263,2428,772,1799,556,349,2664,2662,2226,2007,1802,2472,338,2358,2675,2676,2358,271,1113,723,1934,1971,2681,2679,1386,170,125,1906,259,997,2682,2686,1568,772,1402,1390,726,2286,2670,2684,1679,1942,2441,2393,0,0,2691,2688,2281,1940,68,2650,205,1843,2697,2693,1520,2046,773,2361,440,1133,2705,2706,1560,1133,2011,2594,466,2339,2704,2710,1442,2519,102,1774,2424,2482,2708,2712,2548,2518,1036,1920,1291,2050,2716,2718,2480,1769,441,689,1481,2154,2726,2723,2717,1424,213,2547,1869,1348,2728,2722,2591,1404,1520,512,2672,1637,2739,2737,2507,1311,1967,1856,2251,1666,2743,2741,1695,465,1636,767,2573,2665,2750,2747,1947,1153,1520,1673,1096,788,2764,2766,2422,1940,1828,1310,2582,2742,2774,2772,1801,1761,1143,1344,2399,2419,2787,2783,2423,2433,781,1923,1610,1475,2785,2789,1653,1742,1391,1876,1355,2415,2795,2793,2145,2785,2779,2793,0,0,2798,2800,1614,964,2436,600,410,1893,2801,2802,2468,917,2197,1394,179,1929,2817,2814,2651,1428,1252,2713,2516,1075,2828,2830,2233,2264,954,685,0,0,2835,2833,2731,1415,2694,2430,2419,2410,2841,2839,2566,2629,920,1618,2363,1669,2849,2847,2674,1398,200,509,656,2167,2846,2856,2703,1166,2012,2854,1833,2188,2859,2857,1958,424,459,2461,396,22,2872,2878,1579,1566,1144,2755,324,2154,2882,2885,1657,2797,2682,1171,1265,1114,2894,2891,1560,964,2504,1785,1011,2818,2898,2902,2291,2600,757,324,2226,558,2907,2900,2786,1025,2659,683,2338,681,2912,2916,1860,2643,1589,2181,914,2767,2922,2925,2446,1521,1142,2191,1741,428,2937,2938,1878,875,2840,2808,514,1940,2940,2952,2109,1904,94,702,1830,2020,2955,2956,2502,2223,2582,2361,1274,2653,2961,2959,1600,2724,1929,1507,2845,2121,2966,2968,2702,212,181,1690,2846,1727,2961,2970,1931,905,1121,2893,1724,2610,2982,2995,2779,2843,164,1108,506,1970,2987,2999,2975,1887,1943,1408,639,1829,3009,3007,2235,452,208,2613,1678,2158,3017,3015,2924,2983,1076,2099,0,0,3018,3021,3019,731,1273,1407,104,971,3035,3036,1881,2415,1532,928,272,2593,3038,3030,2059,1279,1713,2942,2606,1279,3038,3048,2806,453,1501,2406,1727,1617,3055,3057,2404,2164,914,1417,704,1540,3065,3063,2516,2295,2309,2709,304,1495,3073,3078,2775,2589,1176,1907,513,1559,3081,3079,1589,1552,662,2261,124,2,3086,3082,3009,822,2198,2929,1304,2593,3103,3105,3105,174,2325,2041,2388,1654,3112,3118,2052,2363,2315,1459,1849,450,3114,3114,1779,1798,478,2851,2996,1972,3134,3131,2714,3061,2685,3099,610,703,3160,3162,1675,1181,2392,3096,0,0,3162,3164,1750,1333,321,2821,2779,2174,3162,3162,2295,2744,731,3147,2562,1570,3174,3179,1885,937,2559,801,2312,2637,3185,3183,1795,134,564,1147,2880,1947,3180,3189,1986,1308,2065,2741,1632,2601,3201,3199,2883,610,1778,248,2402,1490,3206,3204,2273,911,304,2745,0,0,3212,3212,2588,1673,2408,2630,1567,3004,3211,3211,1741,2289,3027,2712,1296,1226,3223,3221,3001,2758,3091,1986,586,2272,3245,3249,3241,1634,696,2665,1022,2372,3251,3252,2830,1160,736,2923,1654,2858,3254,3252,2302,1992,1026,2176,2081,1711,3256,3248,2888,2050,892,1791,2286,3016,3268,3269,2843,959,2172,3031,1765,3006,3297,3293,1855,1901,1806,965,2403,100,3295,3297,1754,893,732,2883,2830,3284,3305,3306,2555,1264,2264,1625,2128,2558,3303,3312,3105,2527,1900,3133,193,1954,3313,3317,3309,3276,833,1883,2553,2265,3321,3319,2982,1089,591,1836,987,1801,3326,3328,3247,631,1163,1915,982,204,3328,3322,1902,419,756,2615,0,0,3338,3342,3261,1284,436,3081,1109,2343,3345,3343,2846,1196,1277,1699,1310,551,3348,3357,3075,1811,2201,3024,3082,3330,3339,3360,1909,429,102,468,3147,1704}; uint16_t __nmod_poly_cp_primes4[] = {3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733,9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857,9859,9871,9883,9887,9901,9907,9923,9929,9931,9941,9949,9967,9973,10007,10009,10037,10039,10061,10067,10069,10079,10091,10093,10099,10103,10111,10133,10139,10141,10151,10159,10163,10169,10177,10181,10193,10211,10223,10243,10247,10253,10259,10267,10271,10273,10289,10301,10303,10313,10321,10331,10333,10337,10343,10357,10369,10391,10399,10427,10429,10433,10453,10457,10459,10463,10477,10487,10499,10501,10513,10529,10531,10559,10567,10589,10597,10601,10607,10613,10627,10631,10639,10651,10657,10663,10667,10687,10691,10709,10711,10723,10729,10733,10739,10753,10771,10781,10789,10799,10831,10837,10847,10853,10859,10861,10867,10883,10889,10891,10903,10909,10937,10939,10949,10957,10973,10979,10987,10993,0}; uint8_t __nmod_poly_cp_sm_coeffs4[] = {2,2,3,4,3,5,2,20,1,0,3,6,4,4,3,3,7,6,5,0,5,2,5,22,1,2,5,5,9,2,5,5,6,1,0,3,4,7,7,1,7,8,8,8,0,2,3,3,9,1,3,5,4,1,0,2,4,15,2,1,2,6,12,3,0,2,3,2,6,2,2,4,6,6,0,7,1,5,1,0,2,2,3,2,0,5,2,2,2,2,17,1,21,9,0,2,2,3,5,2,2,2,4,8,1,7,1,4,4,0,2,2,8,6,0,2,3,12,4,1,3,1,2,3,0,2,2,8,2,0,2,3,6,14,2,3,11,12,1,0,3,1,2,6,1,5,1,17,10,2,2,5,9,14,0,3,1,0,4,1,5,3,2,12,3,15,1,5,3,0,2,5,12,7,0,2,5,2,3,0,2,4,4,2,2,13,4,6,9,4,5,5,10,2,0,2,3,6,2,2,2,2,11,9,0,5,1,15,1,0,2,3,1,7,2,2,6,3,3,0,7,5,7,9,3,3,3,3,11,0,2,6,6,11,0,7,11,1,1,0,3,4,4,8,3,5,1,5,2,1,7,1,4,2,0,2,14,3,11,1,5,1,10,7,0,2,2,3,5,1,2,3,7,3,1,3,5,14,4,2,3,3,18,3,0,3,7,1,3,1,5,1,17,2,0,2,2,7,2,1,2,2,9,7,0,5,1,7,6,1,2,2,6,4,0,13,18,9,6,2,11,4,12,3,0,2,5,8,2,4,13,2,3,7,3,2,3,6,6,2,3,20,7,1,0,2,2,11,2,2,3,4,7,4,1,2,6,8,5,0,3,5,3,18,0,2,3,8,29,1,6,1,2,4,1,2,10,3,21,2,3,4,7,5,3,2,2,8,28,0,5,9,8,9,1,2,3,9,8,1,2,3,7,7,1,2,5,3,5,0,3,3,2,1,0,3,3,0,12,2,10,2,5,1,0,5,2,6,2,2,3,4,0,8,3,11,2,8,3,1,2,3,8,12,2,2,4,6,2,0,2,2,8,2,0,12,4,5,4,0,5,1,5,3,1,13,1,48,7,0,2,3,3,12,1,2,2,8,5,2,5,1,16,7,0,2,3,3,6,1,3,3,4,1,0,5,3,10,2,0,11,1,12,1,0,6,3,4,11,3,3,1,0,9,1,2,6,8,6,0,2,3,7,3,1,3,4,3,10,0,3,5,0,19,1,2,6,8,5,0,2,3,6,2,5,2,4,0,6,3,2,6,8,4,0,7,3,4,8,2,5,1,10,1,0,2,2,11,2,3,3,4,0,1,1,5,3,6,1,0,3,4,3,1,0,3,3,1,1,1,10,11,8,1,0,2,2,6,8,2,2,2,6,6,0,2,6,8,14,0,2,2,1,7,4,14,1,4,2,1,2,3,6,5,1,3,3,0,11,2,3,6,3,18,2,3,3,0,3,0,21,2,8,5,1,3,1,6,3,0,2,3,16,3,1,3,3,0,1,1,5,1,6,2,2,3,4,1,1,1,2,2,2,6,0,2,2,1,2,1,2,6,1,11,0,7,1,8,2,0,2,11,0,3,2,3,6,4,1,2,5,2,4,11,2,2,4,4,2,2,6,2,2,3,0,11,2,12,9,0,3,1,5,13,3,5,2,11,1,1,11,2,2,6,0,5,1,3,6,0,2,6,8,3,0,2,2,6,7,0,2,9,4,2,1,3,1,3,19,0,5,3,1,11,1,3,1,4,8,2,3,6,6,8,0,15,6,0,24,0,3,3,5,13,0,3,1,0,15,4,11,2,3,2,1,2,2,0,9,1,5,5,4,1,3,6,7,0,2,1,2,2,7,5,2,17,1,22,4,0,5,7,0,10,5,19,4,9,1,1,3,1,7,5,0,6,8,3,11,0,2,2,7,8,2,2,2,15,3,0,3,16,4,1,2,7,8,2,1,1,7,1,31,1,0,2,4,12,4,0,3,1,7,3,1,3,5,2,3,0,11,5,9,4,0,11,7,10,1,2,2,3,6,2,2,3,1,0,7,2,3,4,2,8,0,6,6,7,6,0,13,1,9,6,2,6,3,7,7,1,2,2,6,2,0,3,1,5,7,6,7,2,4,1,1,6,1,4,4,0,2,6,6,3,0,5,3,12,1,3,11,1,14,3,0,2,2,6,11,3,2,2,2,5,0,5,3,6,2,2,3,1,3,26,0,2,2,11,6,1,3,6,0,7,2,2,4,10,3,0,3,1,3,4,1,3,4,2,1,0,11,1,7,2,1,2,2,8,7,2,2,6,1,2,0,2,6,6,3,0,3,1,0,5,3,5,19,2,5,1,2,3,8,4,1,6,2,6,4,0,2,5,13,5,0,19,11,23,5,2,3,3,3,4,0,2,3,7,12,2,5,1,15,9,2,6,2,3,28,0,2,3,4,2,1,2,4,1,7,1,2,2,0,2,2,7,2,10,1,0,17,2,23,1,0,2,2,7,18,0,7,1,2,4,3,10,12,12,13,0,3,1,7,15,5,2,2,12,5,1,3,1,0,3,1,7,3,10,2,1,7,1,26,3,0,3,3,8,1,2,5,8,7,14,3,2,3,6,9,3,5,3,2,2,0,2,2,4,7,1,3,3,5,1,0,11,2,3,3,1,3,1,10,4,2,2,5,0,2,1,3,5,0,9,2,7,2,3,5,1,3,1,5,5,0,5,5,11,5,0,3,4,16,4,2,3,5,3,4,2,3,3,3,1,0,5,1,6,10,0,3,4,0,5,1,2,6,8,13,0,7,3,17,1,0,7,1,2,3,1,2,9,3,5,3,3,4,4,1,0,2,3,7,3,1,2,3,8,9,2,3,3,3,9,1,2,3,2,7,1,13,3,3,8,2,11,1,10,2,0,5,5,10,2,3,10,5,1,13,1,2,4,7,2,0,2,2,2,7,0,13,1,14,3,0,2,3,12,9,1,6,8,23,7,0,11,7,10,2,1,5,1,5,3,0,7,3,9,4,1,14,1,0,14,0,3,7,4,4,0,2,2,0,10,1,5,1,7,1,1,3,3,0,7,1,2,6,2,3,0,3,1,5,6,1,2,4,10,2,0,11,2,10,8,0,2,3,7,2,2,2,6,7,10,0,19,1,2,3,1,2,2,9,3,7,5,2,12,2,0,2,2,2,6,2,10,6,4,14,0,2,4,6,9,0,2,2,8,5,0,7,2,5,7,1,6,10,10,12,0,3,5,0,9,2,5,12,4,2,1,2,5,9,8,1,6,2,2,6,4,2,2,7,3,0,6,2,4,4,0,2,3,7,8,1,3,1,7,9,3,2,6,1,2,0,7,9,14,4,1,3,7,12,8,2,5,2,6,1,1,2,4,3,10,0,11,11,5,5,2,31,5,16,2,0,3,9,8,3,1,5,2,3,2,3,2,5,8,4,0,5,2,3,6,1,2,3,7,2,1,7,2,18,1,0,3,5,3,5,2,2,3,7,16,3,3,3,3,9,0,2,3,7,18,2,2,3,6,11,1,5,3,3,2,1,5,2,6,5,1,5,8,4,3,2,2,2,8,3,1,2,6,7,2,0,10,4,16,2,1,17,6,3,1,0,3,3,7,7,1,7,2,6,1,2,2,3,12,3,1,3,5,4,4,2,7,5,16,1,0,2,5,3,10,1,5,12,3,3,0,5,6,8,5,3,3,1,2,3,0,3,1,10,11,0,2,2,3,16,2,2,3,7,2,1,3,11,4,12,0,2,7,4,16,2,2,2,8,6,0,5,1,18,6,0,3,1,3,5,4,2,6,6,3,0,5,1,10,2,0,3,1,3,5,1,5,1,7,2,4,2,2,12,19,1,11,3,1,3,0,2,2,3,3,0,7,2,5,7,1,2,5,1,5,1,10,6,12,1,0,7,2,2,7,1,2,2,6,2,1,2,8,6,2,1,3,1,2,4,1,10,2,6,6,0,3,1,14,5,1,3,7,7,1,1,13,1,2,17,1,19,5,10,13,0,3,3,3,3,0,2,2,8,3,0,2,4,2,5,3,2,3,8,2,4,2,2,9,2,0,6,9,2,6,1,3,6,3,9,0,3,6,0,7,4,3,3,5,8,0,2,2,12,7,2,3,7,9,1,3,7,1,16,8,0,2,3,7,4,1,6,6,0,6,2,7,1,17,1,0,2,6,8,9,0,17,1,2,11,1,10,3,8,24,0,5,1,6,9,1,3,4,7,16,1,3,4,3,1,0,5,3,6,1,0,14,2,1,3,1,13,2,15,5,2,3,3,2,3,0,2,6,3,3,0,2,6,6,2,0,2,2,6,3,1,2,3,8,7,1,6,1,7,4,1,5,7,14,2,3,7,1,5,10,0,3,3,2,3,4,2,5,2,13,0,2,3,6,2,1,5,3,5,6,1,2,5,3,12,0,11,1,6,5,1,2,2,6,6,0,3,5,12,3,1,3,5,7,9,2,2,6,0,3,0,2,3,7,2,1,2,4,7,4,0,7,2,4,14,2,10,2,8,6,0,2,2,14,5,1,3,8,4,1,0,2,3,7,5,1,2,2,6,2,0,3,1,4,3,2,22,1,18,2,0,3,4,0,1,1,5,3,6,3,1,2,3,12,3,2,3,1,2,1,0,2,6,8,11,0,2,3,7,19,2,2,9,8,6,0,7,3,2,25,1,2,3,9,28,1,2,2,3,15,3,2,4,3,3,0,7,10,13,3,1,13,3,18,1,2,5,12,17,2,0,2,10,2,13,2,3,5,9,17,1,5,9,4,2,4,6,1,3,2,0,5,9,20,10,0,3,3,1,4,1,2,2,3,21,1,2,3,7,3,2,2,4,7,8,0,3,5,3,9,0,2,4,25,4,2,5,2,6,7,0,2,6,6,2,0,7,1,5,8,1,5,3,9,16,3,2,2,1,6,1,3,6,0,1,1,5,8,4,1,3,7,2,16,1,0,7,5,7,3,1,3,3,3,3,0,10,3,15,1,0,2,2,4,6,1,3,1,11,4,1,3,4,5,3,0,2,3,8,8,1,5,2,3,1,0,2,2,8,7,4,2,3,3,11,2,2,6,7,3,0,2,2,10,2,2,5,2,3,2,1,2,3,6,2,1,2,3,2,2,1,5,5,10,5,0,2,2,2,9,1,6,4,10,7,1,7,2,0,1,0,2,2,7,5,1,6,1,19,13,0,2,3,4,2,1,6,3,3,6,0,7,5,0,13,2,5,2,6,13,0,2,6,12,14,0,5,7,10,2,0,3,4,4,4,1,2,4,1,10,1,3,3,12,24,1,2,6,8,10,0,2,5,6,7,0,6,4,0,4,1,5,1,5,7,1,7,9,17,1,0,2,2,0,4,1,2,4,8,2,0,2,2,6,11,1,2,3,4,4,1,3,5,2,1,2,7,7,10,2,0,2,2,6,13,2,2,3,8,2,1,2,6,7,5,0,13,2,4,9,1,13,3,35,7,0,2,4,6,4,0,3,1,0,8,1,5,3,6,15,1,2,3,6,3,2,6,4,3,6,0,2,5,8,8,1,5,1,8,6,1,2,5,9,2,0,7,1,12,1,0,2,8,8,5,1,3,3,8,12,3,2,2,12,2,0,3,5,11,4,1,17,1,14,12,0,6,13,3,10,0,2,3,7,12,2,3,3,2,1,0,5,1,2,6,1,2,4,9,7,0,3,1,3,3,1,5,2,4,3,2,7,9,4,12,0,10,7,14,2,0,2,4,11,4,1,3,11,7,8,0,2,5,6,3,0,3,3,2,3,1,3,6,16,3,2,5,5,3,2,3,2,3,3,8,1,12,1,13,10,1,2,7,3,10,1,3,4,11,1,0,5,6,10,3,0,2,3,6,5,5,3,3,7,1,0,2,3,7,6,1,2,8,3,2,1,2,3,7,15,4,7,3,3,8,4,3,1,2,4,0,2,5,12,5,0,3,1,6,14,2,2,3,18,6,5,6,1,3,10,3,5,1,5,5,1,5,7,6,11,0,3,6,0,5,1,14,1,0,31,0,5,3,11,7,0,11,1,9,1,3,2,4,8,2,0,3,6,2,1,0,2,5,3,2,1,3,3,4,6,2,5,1,4,1,1,17,2,28,14,0,2,3,7,20,2,6,1,7,3,0,11,4,3,1,1,2,10,13,12,1,2,4,4,4,2,2,2,13,8,1,7,1,0,15,0,3,1,6,10,0,2,2,8,17,1,2,4,2,15,0,17,5,3,4,0,7,3,0,12,0,2,9,4,8,1,2,5,7,3,1,11,2,2,2,1,10,3,10,6,0,2,5,4,11,1,2,3,8,4,1,3,11,2,4,0,2,4,6,2,0,3,1,2,3,1,3,1,6,5,0,2,3,7,6,1,2,6,3,2,0,3,6,5,4,1,3,3,3,8,0,6,3,6,3,0,7,8,0,2,0,5,1,6,8,0,2,2,8,4,1,3,1,0,9,1,5,6,10,5,0,2,9,0,8,2,6,2,11,4,0,3,5,3,8,0,5,6,11,8,1,2,2,7,2,2,3,4,3,1,1,2,6,8,7,0,5,6,9,3,1,6,8,7,2,1,2,4,8,2,0,7,1,11,10,3,5,6,6,1,1,13,1,25,1,0,5,1,5,1,2,3,1,1,22,1,2,4,2,2,0,5,1,5,5,2,2,5,8,4,0,2,2,1,3,1,6,6,10,2,1,2,3,6,4,2,3,5,3,8,0,3,7,7,11,2,3,10,5,1,0,2,2,2,7,1,6,8,0,6,2,17,3,26,8,0,3,1,3,6,0,5,3,5,5,2,2,3,1,3,1,2,6,6,5,0,15,3,4,4,2,13,9,29,1,0,2,2,0,5,3,2,3,3,11,1,5,1,3,2,0,5,1,15,1,3,3,1,6,3,0,2,2,8,3,3,5,5,34,5,0,2,3,1,7,1,2,3,8,8,1,3,4,6,4,2,23,10,20,8,1,11,3,2,1,1,5,6,10,23,1,2,6,8,2,0,5,5,10,2,2,2,3,2,5,2,2,2,10,3,0,7,1,4,5,1,2,3,1,7,2,3,1,6,11,0,3,5,0,8,1,2,4,1,2,2,3,1,5,15,0,2,5,13,4,2,3,1,5,3,1,5,6,11,13,0,2,2,12,2,2,11,2,27,1,0,2,3,7,4,1,6,6,11,6,0,13,5,11,1,3,2,2,13,7,1,3,5,0,4,2,2,2,8,6,0,7,9,4,3,5,7,3,16,4,0,3,5,4,6,1,2,2,4,4,1,5,2,7,19,0,2,3,4,4,2,3,3,4,9,1,3,1,12,13,0,7,2,0,4,0,2,2,7,5,2,3,10,3,3,0,3,3,0,1,0,6,6,5,2,0,10,6,5,11,0,3,1,5,4,0,6,3,8,12,0,3,4,4,1,1,3,3,2,6,0,6,3,8,6,0,3,12,0,3,2,2,2,3,5,2,2,6,10,2,0,3,9,2,1,0,3,1,3,4,0,2,2,4,7,1,3,7,4,7,1,2,7,15,9,2,2,3,7,2,1,19,7,7,12,2,13,4,14,4,0,3,1,7,3,2,5,5,11,8,0,3,5,0,1,1,2,6,8,3,0,2,3,6,12,1,7,1,4,4,1,3,4,4,1,0,2,2,8,11,2,5,3,8,17,2,2,3,3,4,2,5,2,10,7,3,2,2,0,3,0,2,4,13,2,1,3,10,3,12,1,3,6,6,7,0,2,6,6,9,0,3,1,11,5,1,3,4,4,5,4,2,9,0,3,1,2,6,7,2,0,7,3,2,5,1,5,9,14,5,0,2,4,1,4,1,22,2,2,3,0,3,12,14,6,1,3,4,4,1,0,2,2,4,2,1,3,1,1,19,2,7,2,8,2,3,2,5,4,6,3,3,3,11,6,1,3,4,3,6,0,3,3,7,3,2,2,2,1,2,5,2,11,8,2,1,2,2,10,6,0,11,7,4,8,1,2,3,8,15,4,13,5,42,15,0,2,5,5,6,0,2,2,8,3,0,5,1,8,18,2,2,2,0,13,1,3,7,6,7,0,2,6,8,4,0,7,2,0,11,0,2,2,6,6,0,2,3,1,21,2,3,7,2,8,0,3,6,0,4,1,10,5,10,24,0,17,1,8,3,3,7,5,22,1,0,2,2,8,2,0,3,8,5,1,0,5,8,6,2,1,2,5,4,6,2,5,2,3,3,3,13,9,14,1,0,6,4,2,6,0,3,4,2,4,0,11,1,2,2,2,2,2,2,3,1,3,1,6,13,0,5,1,6,1,0,10,11,2,3,0,3,6,12,5,1,7,1,2,1,1,2,2,4,7,2,5,5,4,10,2,2,4,1,3,0,3,3,3,3,1,2,2,11,12,0,5,1,6,3,1,2,4,8,2,1,2,4,8,9,0,2,4,0,6,1,3,1,4,3,1,10,4,4,2,2,2,3,7,2,2,2,4,10,5,0,3,3,4,4,0,11,1,2,8,0,5,3,11,3,1,11,1,11,1,1,2,2,1,3,1,3,1,2,3,3,3,4,4,9,2,2,3,14,3,1,2,4,6,4,0,11,2,12,3,5,2,3,8,8,1,2,2,3,2,0,2,6,1,5,0,5,8,4,1,1,12,5,3,4,1,2,3,7,2,1,2,5,8,4,1,2,5,3,5,0,7,1,4,17,1,3,1,3,4,0,2,2,17,5,1,3,1,0,9,5,7,1,8,9,0,2,9,3,7,1,3,7,4,1,1,6,1,2,7,1,5,1,14,12,1,7,2,13,7,0,5,5,6,2,1,2,8,6,11,1,2,5,0,5,1,2,2,1,17,0,7,1,3,1,1,10,5,16,4,1,3,1,0,4,1,2,2,0,7,2,3,4,2,6,9,3,5,4,12,1,7,8,0,9,0,2,3,2,2,1,5,3,11,7,0,3,3,7,10,1,5,5,3,5,2,2,4,9,29,1,13,4,0,14,5,19,1,3,6,2,6,1,4,4,1,2,3,8,4,3,7,8,8,5,0,3,1,2,11,1,5,3,3,11,2,3,3,6,4,2,2,2,8,5,0,5,2,5,9,1,2,2,6,5,0,5,1,5,5,1,2,3,7,12,1,2,2,6,11,0,7,1,21,3,0,3,5,15,5,3,3,3,5,13,1,23,10,4,2,1,6,2,2,6,0,2,3,3,18,1,5,11,3,2,0,3,7,2,3,8,5,5,3,3,1,2,8,8,6,2,5,1,6,2,0,11,1,5,1,2,6,3,5,3,2,7,2,6,8,0,7,3,14,3,0,3,1,0,3,0,2,3,4,16,1,5,7,3,5,4,2,12,0,21,2,2,5,3,4,2,3,9,2,1,0,2,2,8,6,0,7,7,0,5,1,2,3,9,2,2,6,2,5,4,1,11,2,21,1,0,3,4,2,4,0,10,4,11,11,2,2,2,17,12,0,19,2,5,2,10,7,5,2,10,0,2,6,10,7,0,5,5,10,7,2,2,2,8,3,1,2,2,0,5,1,2,2,12,9,0,2,2,8,6,0,2,3,2,2,2,3,1,2,7,2,2,6,2,16,0,3,1,5,5,0,2,6,3,27,0,3,4,1,11,1,3,1,3,8,0,2,3,12,2,1,5,1,7,1,3,2,3,7,4,1,2,4,3,8,1,2,6,8,5,0,7,10,21,1,0}; uint16_t __nmod_poly_cp_md_coeffs4[] = {3369,3366,2291,2408,1283,2758,3368,3372,3354,1701,2205,2230,3386,3387,3385,2246,619,3370,3388,3389,2209,38,1728,3156,3402,3405,2792,1933,3127,1959,3411,3405,2381,1557,3367,2318,3428,3432,1930,2465,1603,1777,3446,3448,2833,1525,1591,526,3450,3454,2376,3136,2416,3421,3459,3460,3161,1077,1453,3380,3460,3461,3459,2512,2050,491,3465,3455,2489,1625,364,3455,3467,3465,2383,3457,3451,3465,3489,3490,1980,681,1056,2910,3497,3498,3149,1570,3394,2404,3504,3508,2456,1811,3091,2649,3515,3516,2895,646,1777,3426,3522,3526,2323,766,3357,2445,3512,3525,1957,559,3222,338,3531,3532,3345,746,1540,1167,3537,3525,3080,294,3273,2694,3534,3535,3537,1620,3281,2886,3545,3546,3540,3029,624,2127,3555,3553,3127,2418,1690,2780,3556,3558,1956,3488,412,1908,3569,3567,2653,1424,2222,3504,3579,3577,2125,1283,1744,316,3580,3582,3572,549,607,2464,3590,3585,3195,3077,1496,2356,3602,3605,2930,3486,3024,913,3611,3609,3295,1181,2771,2217,3614,3605,2714,825,2384,42,3618,3616,1865,3350,1960,2559,3616,3630,3231,2672,2089,3556,3635,3630,1942,3284,865,1745,3641,3642,2103,2646,2013,2118,3657,3658,2273,1806,2084,2998,3658,3667,3010,1907,728,579,3668,3670,2625,54,1117,3020,3675,3673,2118,3242,690,3160,3689,3685,3456,2293,2814,3611,3692,3692,2023,2968,780,3552,3699,3697,2072,2528,2741,2061,3707,3708,2816,2504,2011,181,3712,3716,3402,1864,1919,3182,3724,3725,2722,2653,1052,1194,3731,3729,3404,3721,3715,3729,3732,3736,2830,3724,475,2935,3758,3760,3323,2793,2314,272,3762,3765,2094,2774,504,2920,3762,3751,3487,371,1049,2185,3777,3774,2807,158,3225,191,3788,3788,3571,2860,3155,3660,3795,3796,3340,3487,2754,1721,3801,3799,2826,2899,2520,2493,3818,3819,2640,242,2236,2523,3820,3822,2316,3256,688,2440,3830,3827,2810,2090,3555,3536,3842,3845,2007,2960,2951,3576,3849,3847,2109,538,2883,1595,3851,3852,3714,1061,683,3379,3858,3858,3343,2842,3189,2955,3875,3876,2067,2388,1029,2690,3868,3879,3449,1214,1806,2289,3878,3888,2189,418,1211,2603,3905,3903,2057,2140,3244,3396,3898,3909,3384,509,2434,770,3915,3913,3340,2753,2025,635,3916,3914,3459,3364,1782,1393,3921,3922,3517,2908,1332,444,3926,3928,3318,3588,3864,2235,3929,3927,2867,3919,3913,3927,3940,3941,3258,344,3559,2762,3945,3946,3940,2244,2906,2996,3961,3966,2458,768,313,254,3987,3988,3348,1169,1437,2331,3998,4000,2873,1714,3347,624,4001,4002,3996,139,3070,2275,4002,4005,2773,738,297,3896,4011,4009,2953,312,1603,3671,4017,4015,3470,3869,2830,3408,4019,4020,2365,3492,2818,1504,4024,4020,3765,423,4007,3986,4046,4043,4037,1007,3235,653,4041,4050,2367,1767,3082,701,4052,4056,2914,1797,3212,2395,4070,4061,3117,2900,4001,3356,4068,4076,3922,265,679,1978,4089,4090,4084,155,771,4021,4091,4092,3106,1942,1514,2807,4097,4095,3462,2299,633,3078,4099,4110,3586,1053,973,3920,4122,4125,2630,1872,1197,3436,4116,4120,3348,64,3902,3622,4131,4132,2646,849,3596,3591,4137,4135,3367,3148,2490,3012,4148,4150,2470,1334,1363,1137,4155,4156,3798,1241,1691,2413,4156,4157,4155,524,318,2954,4172,4174,2899,2637,2547,2641,4190,4200,2944,4121,1043,4040,4205,4208,4052,2570,1635,4208,4214,4212,4045,2712,633,2499,4217,4218,4212,2522,1265,3909,4227,4225,2478,1927,83,427,4228,4230,3325,956,953,3565,4238,4235,4229,1001,170,2946,4241,4239,2742,4231,4225,4239,4251,4249,2244,3397,1152,2531,4257,4246,3422,3885,1573,4168,4259,4260,4254,3462,1719,2416,4264,4269,2992,2631,1442,2342,4268,4268,2546,1236,2690,1754,4281,4279,3405,187,3765,1768,4286,4283,4277,295,148,3642,4292,4296,3648,3561,3069,3822,4324,4325,2389,1155,3649,3566,4334,4330,4175,55,176,3754,4329,4337,2523,2434,2335,3625,4347,4345,2432,4221,3320,4068,4355,4356,3793,2229,1623,3187,4361,4359,4144,4351,4345,4359,4371,4367,2568,3528,4263,3992,4377,4388,2791,3177,2954,3175,4395,4393,2377,1409,3598,4101,4406,4403,4397,2342,2421,2996,4418,4420,3830,1494,1122,4112,4420,4417,4411,3440,4067,3428,4420,4440,4142,3103,3247,629,4444,4445,2739,775,3099,2489,4449,4447,3166,256,3346,1419,4454,4452,4268,2943,3671,2423,4458,4460,2602,280,3180,1205,4478,4468,3892,4213,3703,3999,4481,4482,4367,2616,1198,695,4491,4489,4132,3144,2017,1085,4505,4503,2907,4495,4489,4503,4506,4510,2378,3674,235,3867,4515,4512,4284,1108,3536,3489,4516,4517,4515,2478,149,3566,4518,4520,3148,1902,3411,3259,4545,4541,4148,1387,3790,2417,4543,4545,4058,46,4336,886,4550,4560,4381,1145,3578,2777,4564,4566,2779,3246,976,4123,4578,4581,4571,53,4496,4242,4580,4590,2962,957,2109,2806,4592,4596,4179,2664,3847,2401,4601,4599,4153,4591,4585,4599,4619,4617,4013,1100,2174,879,4635,4631,2395,305,4319,808,4636,4637,3896,1317,1809,1606,4638,4634,2546,3845,2560,4022,4646,4648,4013,2396,3040,479,4648,4642,3318,843,1576,4195,4642,4652,3692,2713,2474,4346,4660,4662,3855,4017,2517,4263,4670,4668,2460,865,3238,160,4668,4677,4414,184,2733,3552,4689,4684,4509,4288,4489,3051,4698,4702,3012,3972,487,3929,4715,4718,4464,693,182,858,4721,4722,4408,4018,2920,2673,4712,4718,4536,2614,4300,4551,4728,4721,3462,1,969,4094,4732,4747,3565,4544,1906,704,4756,4753,2513,3147,1700,1939,4777,4782,4466,4214,3223,2342,4785,4783,3115,4307,4559,3742,4787,4784,3684,1158,1476,1036,4790,4792,2583,4483,930,3,4792,4798,4439,4125,600,2053,4794,4798,2998,3631,2238,4495,4811,4809,4308,1051,1931,2681,4814,4816,3744,4496,2100,3364,4828,4830,2775,1713,4453,2779,4850,4859,3500,2959,2621,2014,4860,4870,3209,812,73,4465,4875,4876,4589,3454,4507,1653,4886,4883,4877,1718,2917,4840,4900,4902,2979,1702,1305,1797,4903,4908,3865,2599,3481,4769,4906,4915,4686,2943,4045,3643,4925,4928,3112,1657,4017,1703,4931,4932,4500,129,4255,3313,4934,4926,4763,3800,3340,3079,4936,4940,4276,4160,1268,4619,4945,4949,3348,3464,4044,4102,4955,4953,3521,4945,4939,4953,4962,4966,3184,950,3727,466,4958,4966,4047,639,155,4528,4971,4972,2632,4155,4621,2573,4985,4986,4814,3525,4440,4786,4988,4992,4297,1106,3867,2646,4996,4997,4799,2779,360,4996,5001,4999,4493,4980,1719,2697,5006,5003,4997,2797,3783,4178,5009,5010,4242,4952,3074,3137,5018,5000,3369,536,4470,3582,5020,5022,2666,4661,406,4842,5028,5035,2763,1402,3485,389,5049,5047,3758,2908,2629,3492,5057,5055,3985,5047,5041,5055,5075,5073,3432,5065,5059,5073,5078,5070,3582,1571,2217,3364,5082,5086,3574,1424,3477,3422,5097,5098,5092,4903,38,759,5095,5097,5097,3421,4320,4789,5105,5103,4396,2785,1583,3796,5094,5109,3501,1417,4051,4963,5116,5117,4529,4512,2247,5016,5145,5143,3705,890,4432,3125,5148,5148,3288,4040,3661,3222,5161,5166,2756,2012,4295,4940,5169,5170,4578,2532,605,2542,5177,5175,4114,3903,3978,4616,5187,5179,3521,4015,1142,1147,5190,5195,3172,3064,949,3188,5192,5208,3547,1317,1227,4296,5225,5226,3673,1338,3492,1839,5224,5230,2945,2064,124,829,5223,5232,4917,5172,4218,4161,5234,5235,4976,1244,3085,651,5259,5257,3906,237,2891,1780,5270,5268,3736,2525,568,4238,5272,5275,3255,812,3859,3442,5274,5278,4529,1574,4991,4876,5294,5296,2780,4813,693,1723,5298,5298,4664,2210,3779,1797,5307,5305,3402,1374,1244,3426,5318,5322,4544,4678,449,4833,5331,5332,3011,4173,4880,4665,5344,5340,4300,3872,3767,4767,5340,5349,2904,2813,3018,1365,5378,5379,5373,591,3442,2419,5385,5381,5179,294,2140,4831,5390,5388,2779,3959,3645,1417,5392,5398,4859,2407,4443,3793,5404,5406,2801,5256,3948,4841,5408,5408,3179,648,4784,5019,5414,5411,3351,5229,2844,2225,5416,5414,4003,3470,5375,4215,5428,5430,4493,5406,3798,5206,5432,5436,3703,16,180,4983,5438,5435,5429,2825,1966,2329,5441,5439,3215,5431,5425,5439,5442,5446,5215,3651,1577,918,5464,5470,4654,1611,5284,4877,5475,5476,4592,1630,2737,726,5476,5477,5475,4310,4043,3121,5481,5479,4428,15,761,4423,5499,5500,5494,3141,1376,2152,5500,5501,4553,807,3098,4862,5505,5506,4674,4320,3265,1486,5506,5517,4514,1728,77,3957,5510,5518,5107,1127,3611,4199,5522,5525,3244,1602,4694,291,5521,5523,5284,3780,522,2818,5555,5556,5232,4509,1414,5195,5561,5562,4029,824,2629,3660,5556,5568,5005,2058,4630,3619,5571,5569,4990,458,5276,1540,5575,5580,2877,5084,5293,4711,5580,5589,4672,1604,4049,1141,5618,5622,4471,2026,3434,2370,5632,5632,5533,3109,2719,1858,5627,5627,3065,2049,1341,2687,5644,5645,5643,469,92,4939,5649,5645,5114,4954,2981,3352,5648,5652,5415,2467,4995,4874,5654,5652,4685,2612,4118,5555,5657,5658,3882,2138,5546,3119,5666,5657,2924,2120,1592,657,5681,5682,4164,2285,1361,5120,5678,5686,4145,2179,909,5572,5691,5689,4512,4455,2355,3472,5699,5700,4705,1099,3264,3092,5692,5710,3629,5210,5696,2375,5715,5716,4875,5001,2337,4666,5732,5736,3985,5307,2532,5344,5739,5736,4555,1063,5658,2348,5733,5741,4715,169,4833,5621,5747,5745,3224,3786,1618,3265,5777,5775,4989,520,936,4860,5776,5779,3417,3792,2474,3363,5785,5789,5496,5626,3300,3847,5798,5795,5789,3402,1709,4616,5802,5806,5319,3822,3004,2936,5811,5812,5538,3366,3540,2594,5815,5817,4968,5593,3825,5161,5825,5826,4800,2659,4815,4660,5833,5837,3944,1721,5345,2750,5841,5839,5271,1733,1896,3818,5846,5848,4466,1028,1241,4207,5849,5847,4062,5839,5833,5847,5850,5850,5725,1880,4090,2563,5858,5859,4246,4521,1056,2999,5862,5865,5859,4508,3300,3178,5867,5868,3845,767,5450,4506,5868,5877,5039,5094,4222,4253,5850,5876,5848,4546,2592,4096,5894,5892,4016,1149,1348,716,5898,5901,5899,3098,1573,314,5921,5919,3089,4010,5787,3895,5922,5926,3813,4057,5756,5257,5937,5935,5109,1341,2001,5778,5946,5946,5381,834,2240,4791,5978,5980,3130,5402,5980,3703,5985,5983,5641,3661,3911,205,6004,6005,5427,1729,5799,285,6009,6007,3814,2903,5566,956,6027,6025,4854,3826,933,1263,6032,6036,4169,2142,5518,2213,6038,6041,6035,2565,3936,3603,6042,6044,4284,5019,3051,3663,6051,6052,6046,376,426,4554,6065,6066,5710,876,3284,3354,6063,6072,3299,5420,1253,6051,6062,6077,6071,1413,5393,513,6086,6088,4969,485,1448,2643,6084,6089,4936,2839,484,5594,6099,6097,4125,1347,940,4989,6110,6112,4935,3957,4751,4691,6114,6118,4176,4024,2225,4299,6129,6126,4866,840,3151,3592,6128,6132,4719,187,5292,2412,6138,6141,5375,2112,319,5720,6148,6150,5687,1739,781,4259,6160,6154,4191,3969,1252,6155,6171,6172,5879,1787,5731,2807,6195,6193,4395,4487,2745,5836,6196,6197,6195,5339,3145,1684,6201,6197,4407,3723,3336,317,6209,6207,3831,4401,3423,1452,6212,6214,4005,4686,324,3426,6218,6220,4737,767,4690,2283,6227,6225,5804,6217,6211,6225,6242,6246,4249,5013,3016,863,6254,6248,5301,3820,902,764,6258,6262,3733,2635,2176,743,6267,6265,5915,4080,614,5113,6260,6267,3429,4877,5120,2956,6275,6276,5873,2132,1671,4081,6280,6285,5422,4689,149,2056,6297,6288,5835,5417,5643,2902,6291,6297,3648,1594,3503,229,6304,6310,5361,3661,4292,3292,6315,6316,5652,4441,2796,4421,6321,6311,5598,5335,6243,547,6326,6324,6151,1099,3130,695,6327,6336,5231,6074,4620,4918,6340,6342,3971,5827,5075,5042,6350,6352,5517,1406,6344,1479,6346,6358,6246,852,4721,6094,6342,6358,4383,1181,629,5908,6364,6365,5709,1894,5862,4612,6371,6372,6366,5239,3274,6004,6377,6370,3885,5798,2466,757,6387,6388,6382,1872,576,4136,6395,6396,6218,2137,983,1992,6415,6417,3300,1652,805,3697,6424,6422,5590,1225,4193,4170,6446,6443,6437,3985,2704,1378,6448,6444,5883,4522,5757,4142,6467,6465,4409,5646,1235,1560,6470,6467,3818,524,1141,2150,6474,6478,5873,1488,3948,2363,6489,6487,3747,5503,6117,837,6515,6515,3760,2751,1750,6329,6522,6526,5221,2223,2089,1712,6545,6543,3676,6535,6529,6543,6534,6550,3541,757,3626,3950,6543,6550,6219,1417,2186,6188,6558,6561,6555,2323,4178,4246,6566,6568,6125,1853,3838,6126,6568,6566,4564,410,3112,3877,6572,6576,4769,1408,995,6264,6567,6577,6043,3255,2186,5790,6586,6586,6418,2581,5600,2426,6604,6606,6492,1568,6135,2932,6617,6614,4540,5406,784,1425,6635,6633,4675,6625,6619,6633,6651,6652,3675,6102,1495,3732,6657,6655,5754,4969,5657,6486,6655,6660,3579,198,5037,4210,6668,6670,6662,3662,844,4835,6672,6676,6084,3803,3644,2537,6686,6684,3532,5708,4934,6026,6689,6690,5612,4749,150,6099,6699,6697,6518,278,2145,3624,6698,6702,5107,4801,5837,6622,6707,6708,4545,2390,5583,1108,6708,6716,5879,5545,2901,2787,6731,6732,5096,5670,4209,5611,6734,6731,4969,4305,3010,3041,6758,6760,3691,5874,5625,5122,6761,6758,3708,2068,1859,6719,6777,6775,3633,762,1713,5811,6779,6780,6422,4279,2576,5639,6784,6789,6226,4446,4602,2743,6783,6792,3546,2987,917,4415,6801,6799,5750,612,2018,6190,6820,6821,6819,1630,3578,6433,6825,6823,4068,5263,3597,6226,6827,6825,6384,4259,4000,6425,6830,6832,6428,3213,4297,4331,6819,6840,5338,53,1004,6303,6854,6852,3578,4241,4549,6371,6858,6860,3569,1806,5646,3396,6867,6865,5754,1589,4498,1535,6868,6870,3573,2819,4821,4520,6881,6879,4187,6871,6865,6879,6897,6895,5297,3996,6687,5926,6905,6906,6900,226,1334,5841,6904,6910,6479,3787,3523,646,6915,6913,4673,2784,5776,3952,6945,6942,6296,5933,5914,5586,6947,6948,5165,6814,4446,4030,6952,6957,5088,395,5933,3213,6948,6950,5425,787,5199,2288,6962,6965,3595,6552,1246,6016,6969,6970,5192,6619,3007,3606,6974,6971,6423,3216,6689,1076,6978,6974,6746,704,6370,5285,6985,6990,4491,1313,1793,3115,6992,6992,5900,5945,458,2575,6998,6994,4330,4025,3151,2368,7011,7012,5076,6926,5439,4350,7017,7015,4031,461,5640,2328,7025,7026,4903,421,4131,6876,7036,7038,4087,6693,3074,3617,7041,7037,6012,1762,2987,3991,7052,7056,4013,326,1378,6981,7067,7065,6317,7057,7051,7065,7072,7077,6370,6760,944,5256,7098,7101,6519,6748,5159,5353,7107,7100,5252,4001,1752,258,7118,7115,7109,1471,4940,2839,7122,7126,3637,5469,402,644,7122,7120,3757,1515,6041,2103,7144,7150,3932,1854,1423,1105,7156,7157,6236,1474,193,3635,7167,7172,4338,3113,6174,3830,7185,7186,6410,4440,6639,5701,7190,7187,3771,2785,6600,3366,7204,7206,3716,5204,2384,180,7209,7207,6379,402,5798,1605,7208,7212,4303,5006,6932,3215,7217,7215,4165,1767,795,5732,7227,7228,4625,1002,52,6435,7235,7236,3772,6719,3532,4691,7241,7242,4257,1410,5830,2864,7242,7246,6940,5700,7009,4641,7251,7249,5662,21,6469,7159,7281,7282,6911,2502,1631,6658,7292,7292,4126,5735,2750,4830,7305,7306,5047,585,5601,130,7303,7305,5705,6166,5665,5038,7314,7314,4513,6092,2104,6562,7329,7327,5535,5844,3873,6972,7327,7332,6200,5415,5266,2398,7347,7348,7052,5790,252,6222,7345,7350,4268,5578,1302,7044,7362,7362,4712,2196,3185,6895,7388,7392,4462,259,1460,1063,7409,7410,5186,3431,5822,5540,7412,7412,6268,5540,4355,4108,7430,7432,7147,3233,2366,6076,7449,7444,5087,2909,3645,3008,7454,7456,7446,1190,2527,3235,7457,7455,5760,7447,7441,7455,7475,7473,6608,4847,3501,6488,7475,7478,5095,5246,6853,3117,7482,7485,6913,1146,949,6607,7482,7486,4900,3602,5586,3832,7497,7493,5082,796,3707,5190,7505,7506,7500,7435,2078,5967,7515,7516,4573,5797,5676,6158,7521,7522,7329,6910,7216,6368,7526,7524,6670,2780,3909,6608,7530,7534,4898,895,6822,2291,7539,7537,3927,4749,4047,3247,7545,7543,4129,5032,3183,3233,7547,7548,5562,5305,4439,6900,7546,7557,5754,1411,1583,5606,7548,7552,5370,3226,6576,6950,7571,7572,3966,3595,7410,1807,7574,7572,4887,1333,6254,189,7578,7578,6405,6021,6421,2469,7587,7585,5491,1436,3574,7495,7585,7589,7302,6269,6080,4565,7601,7599,7301,7353,3297,5880,7602,7605,5918,2945,5588,5572,7619,7620,7159,2265,1419,1558,7632,7628,4871,2491,5805,3494,7641,7642,7636,5555,2982,7211,7646,7644,7359,5418,6712,1749,7667,7665,4671,4020,5683,5971,7670,7667,7312,1329,930,6164,7664,7680,7308,7076,4925,6113,7681,7686,5032,4875,2718,4602,7689,7687,7443,6510,1487,1304,7696,7698,6377,1172,5156,5599,7698,7702,6237,826,6494,6471,7715,7716,3957,1202,2249,2931,7720,7708,4643,886,7164,3978,7722,7726,3940,3518,2100,7081,7734,7739,7389,6003,5031,2290,7743,7752,5369,6896,4162,6595,7755,7749,6682,6662,7212,1941,7756,7754,4050,3196,2762,2236,7787,7785,5723,1115,3539,3519,7790,7788,7668,3922,2501,7568,7814,7811,6121,6437,7096,7295,7818,7822,4777,2438,356,4599,7827,7828,4796,7155,5906,401,7829,7840,6793,6877,710,7133,7851,7852,5386,2079,5068,7765,7864,7862,5804,5298,6607,6744,7868,7870,6445,4367,1891,7380,7875,7873,6597,4653,1395,7625,7876,7873,6527,6111,1548,4084,7881,7879,6618,3598,6912,4848,7899,7895,6435,6704,7881,7263,7905,7903,7224,5736,6031,6389,7912,7918,7322,4922,5917,3472,7924,7926,6367,1272,6856,6150,7931,7929,7734,7866,3854,2022,7934,7936,5414,3961,509,6755,7947,7944,7294,6177,7753,243,7945,7949,6758,2016,735,7698,7958,7962,4368,5444,659,6806,7988,7992,4905,2935,2235,7864,8006,8003,7997,3251,5503,6841,7997,8009,7273,6704,4929,7473,8012,8016,5204,3710,7946,7470,8028,8035,7648,7158,7277,2220,8051,8052,8046,898,1783,6375,8056,8058,7932,6629,5055,6373,8067,8068,4135,6072,7997,7974,8078,8080,7439,5498,5491,6981,8082,8086,7414,472,5447,1925,8072,8078,5877,7517,7863,819,8091,8089,6711,7359,2707,7561,8095,8100,5576,4610,3231,3842,8100,8110,4175,3313,5943,1374,8115,8109,4332,1507,1015,7142,8121,8122,5348,3854,5556,3044,8145,8146,7196,5596,5401,7685,8154,8154,7029,2036,1414,7254,8164,8165,6636,2265,7153,7585,8169,8167,4824,3525,6436,5270,8177,8178,6095,6127,4044,2735,8174,8189,8183,5644,5964,7746,8202,8202,4481,62,2959,4046,8217,8213,4992,5939,3375,1851,8219,8220,7152,6791,7026,7234,8220,8230,7131,3070,2212,4203,8223,8228,6061,4744,7612,6108,8235,8225,4806,6543,4317,5886,8241,8239,5696,4507,2514,2990,8260,8262,7377,454,2810,8004,8267,8265,5697,4559,6757,4287,8270,8266,4860,2399,6059,806,8284,8282,4792,1330,3839,5431,8289,8287,6693,1582,4825,2325,8291,8292,8005,6472,7110,7311,8294,8286,7646,6022,1160,4149,8308,8310,5431,7511,2038,1522,8311,8316,7793,2429,2524,6808,8322,8322,6997,7712,2699,2870,8348,8352,7054,6800,8204,4239,8361,8362,8356,3927,7299,6690,8366,8363,8357,5099,1511,5994,8372,8374,6188,2821,1440,6678,8385,8382,4315,1580,511,3244,8383,8388,5414,6479,3184,5219,8416,8414,6238,6064,6754,5573,8418,8421,8411,5929,1937,64,8427,8425,8111,2003,5123,5355,8428,8429,4337,7241,2827,8415,8441,8439,4731,8431,8425,8439,8442,8445,4690,8257,6076,6828,8455,8460,7804,2963,2257,4200,8465,8463,5912,2283,7061,7008,8494,8500,6003,7679,7644,1322,8508,8502,5492,1458,7531,85,8508,8518,5088,3817,5411,7988,8522,8526,8207,1927,2709,2231,8534,8531,7792,5831,2444,2380,8537,8538,7075,6655,6418,7175,8538,8541,5021,2782,5208,1478,8561,8559,5843,8102,7430,8481,8571,8569,6305,7706,6841,3192,8575,8577,7245,5084,7059,1532,8595,8593,7922,6709,5455,4088,8596,8598,7681,4637,4756,4240,8606,8608,6308,4751,1907,1867,8620,8622,8007,2263,4793,8507,8625,8626,6369,6559,3726,6628,8623,8621,8257,8607,8139,6917,8624,8634,8622,811,5137,8132,8644,8645,8461,5759,720,3543,8658,8662,6897,5105,6101,4990,8667,8665,6162,5286,1956,5119,8675,8673,7175,8665,8659,8673,8666,8680,5574,4442,6034,7487,8676,8686,8553,5398,120,8133,8691,8688,5646,8213,3798,8606,8697,8694,6822,3504,7003,4612,8702,8705,8703,3691,3786,6104,8708,8708,8053,5244,6551,7568,8716,8717,7179,8369,6247,8216,8729,8727,6427,6142,4660,815,8732,8732,6826,2847,8068,6560,8739,8737,5400,7582,7150,7172,8745,8743,6301,3019,1296,1216,8750,8744,5995,3660,1441,4276,8738,8758,5114,7319,3611,1537,8768,8778,7274,7050,2306,4786,8778,8781,7117,3955,5862,8316,8801,8799,6724,8791,8785,8799,8802,8805,4665,1200,2306,7401,8817,8818,6655,2915,3630,3811,8819,8817,6971,6300,1857,297,8824,8830,8822,3580,2624,6291,8835,8833,7250,6956,8689,2566,8836,8837,4544,2176,397,8457,8846,8843,8837,365,3317,2590,8859,8852,4774,6360,3414,6144,8860,8862,8306,6194,2869,6513,8865,8866,5451,6602,2630,2828,8884,8886,7808,3843,8137,8361,8888,8888,6168,2650,334,8386,8921,8922,8144,3743,1143,5020,8918,8924,7151,595,4416,6678,8931,8929,5194,4122,4036,7280,8935,8940,6891,1810,8744,7820,8938,8946,5765,8329,7274,6547,8961,8962,4564,4734,1878,3128,8966,8957,8121,7099,1084,5646,8969,8967,8043,4491,1899,493,8992,8997,8544,8803,8232,6050,8994,8998,5064,8167,7414,7543,9004,9005,9003,4954,800,6000,9009,9005,8821,649,2187,8646,9008,9008,5925,8822,5809,6555,9027,9028,5776,7194,1991,4979,9038,9040,8772,6171,2124,889,9040,9038,7495,1849,8353,8638,9042,9042,5725,4624,3105,2186,9057,9055,4811,1482,2453,1579,9064,9062,6260,6562,6836,6692,9088,9080,7453,5472,6337,1877,9097,9100,5578,1096,3322,4647,9099,9106,4902,3208,1962,6330,9124,9126,5302,702,4646,7426,9127,9131,6574,1196,3312,2556,9134,9136,5911,5560,3193,7286,9148,9150,8204,3429,6655,5977,9151,9155,6299,110,1682,5647,9158,9155,9149,6453,200,1330,9171,9172,7906,2784,3937,4880,9179,9177,8076,9169,9163,9177,9184,9186,5702,190,1967,7141,9196,9197,7846,5822,6629,9182,9201,9202,7110,5524,643,8945,9206,9208,7273,6289,1969,4074,9219,9216,7422,910,722,2441,9225,9223,6443,9082,3243,6820,9220,9234,8312,1407,6785,7285,9228,9240,4914,7794,4004,1012,9254,9256,7434,5278,4027,1045,9272,9272,5440,4880,1596,7970,9278,9275,9269,8133,1833,5545,9281,9279,8339,9271,9265,9279,9291,9289,7365,749,6168,4056,9304,9309,6729,4113,1876,1736,9316,9317,9315,6313,8883,8118,9321,9322,9316,6343,5860,726,9332,9336,7142,5575,6468,244,9339,9340,6817,2514,6633,7176,9338,9342,6592,2315,2343,6295,9347,9341,5840,8492,2492,7008,9369,9370,5834,6635,7764,3855,9374,9368,5819,3121,5127,2868,9388,9390,6807,1863,2392,5521,9395,9396,7969,5616,6531,5832,9400,9396,9129,5255,7055,4230,9410,9412,5447,8993,8167,4942,9417,9413,6628,7744,1647,8231,9419,9420,8855,4585,2484,1701,9424,9430,6132,2701,1680,8388,9428,9430,9422,8892,1778,9190,9435,9428,6215,2779,7855,3741,9417,9438,8780,8565,5999,6390,9458,9459,7151,1197,6380,4176,9460,9461,9459,5543,5930,5856,9465,9466,6384,1881,6205,5578,9470,9467,5129,1935,6654,995,9472,9472,6365,7469,8721,3242,9489,9476,5083,270,5031,8755,9494,9491,6593,6345,5362,863,9508,9510,9373,6658,4480,7514,9518,9520,5073,4999,8694,307,9531,9529,5479,2635,4771,6184,9537,9538,9532,4451,8475,9120,9545,9546,4903,9537,5553,3164,9540,9550,8763,4846,6942,2120,9585,9583,7602,3461,1202,8007,9588,9598,6113,8072,4399,5411,9611,9606,6141,3952,1517,6558,9617,9615,7026,373,4736,8835,9618,9621,7793,3984,8996,5702,9627,9621,6790,4940,5754,6591,9628,9629,5229,5073,5882,7033,9641,9639,5310,9631,9625,9639,9642,9642,5002,7129,3802,1048,9659,9657,9105,8970,4756,665,9675,9673,8915,747,3816,3455,9676,9678,7499,90,9445,7366,9686,9683,9677,223,5702,6648,9687,9692,6346,3349,7898,2350,9702,9712,5263,7452,2386,9440,9714,9718,9702,113,1306,5624,9731,9732,9726,8889,7453,2254,9736,9732,8326,9508,7496,2435,9738,9740,5224,6883,8750,5105,9747,9748,5546,7694,5721,3734,9762,9765,9763,2381,5959,3257,9756,9768,6230,6921,632,8704,9775,9777,5001,9149,9684,2229,9784,9786,6629,5127,4555,9505,9780,9790,6086,2437,3419,6324,9801,9802,7808,1791,6435,2148,9808,9810,6930,7526,2384,5050,9812,9816,5210,1895,215,6969,9819,9825,5988,2581,8245,8531,9830,9824,6035,3223,2059,6117,9832,9838,5413,8207,1934,3887,9849,9845,5951,6021,1251,5705,9852,9856,9114,4495,7184,7053,9857,9855,9231,2796,4250,5028,9868,9869,6493,7230,2345,4177,9881,9882,5028,8787,9638,9399,9882,9882,7319,8678,2032,6861,9899,9900,9894,1748,4483,8692,9905,9903,6151,5230,3284,7577,9921,9918,9317,2269,2624,6629,9926,9928,8041,2171,5942,8347,9921,9928,9545,2316,8350,5581,9939,9937,8321,1291,7931,1408,9947,9945,9170,1443,1156,6970,9964,9965,9963,6881,7254,9681,9962,9969,7687,3928,2985,9944,10002,10005,9995,7978,7220,7070,9998,10005,9995,8706,3520,9952,10035,10033,7099,102,8872,6761,10036,10038,6587,4408,9268,8821,10058,10059,10057,8516,7568,6258,10065,10063,7032,9132,2222,7159,10067,10065,8451,2432,8214,5305,10068,10076,5337,9540,4152,9065,10089,10087,6538,7118,9253,3773,10091,10092,5918,6200,562,4293,10097,10095,9440,355,883,6474,10098,10102,6950,8645,8394,7728,10099,10109,8381,91,4329,5293,10131,10129,5713,9574,3849,8838,10137,10138,10132,1353,1688,2822,10139,10140,8225,4279,4575,8246,10144,10149,7169,502,5985,7872,10156,10157,9468,9446,9225,438,10161,10159,8097,2747,2058,9888,10166,10163,10157,9807,1773,6295,10170,10174,10034,8952,8195,10064,10179,10180,6033,3594,8153,7912,10190,10192,8097,3862,8561,9167,10205,10210,8236,7499,8739,8209,10218,10221,9079,7202,5227,9800,10236,10241,9513,5937,6838,8205,10242,10244,5485,5326,8735,6340,10251,10252,8614,2012,2852,5703,10257,10249,8416,1727,5263,7235,10265,10263,8737,3657,3099,4244,10264,10270,6272,9500,1943,3784,10263,10268,9542,2243,6345,3002,10286,10283,10277,8887,8083,9311,10299,10293,9322,1126,316,2802,10300,10302,9982,119,6862,2036,10310,10312,5430,3920,3425,5885,10314,10314,5844,8505,8845,7362,10329,10330,8493,3409,9355,5321,10328,10328,6295,5943,6139,5383,10334,10336,9346,9593,5351,1518,10338,10341,10339,4855,709,8804,10355,10353,9464,7218,4223,6369,10356,10358,5914,9237,7072,9774,10372,10389,8160,8612,5888,4117,10393,10397,10004,3057,5189,6359,10425,10423,6390,2327,2364,2585,10422,10423,6339,702,1521,2882,10430,10428,9291,5541,9400,2175,10448,10452,8607,9188,8836,20,10454,10456,5413,3710,9475,2194,10457,10455,5399,5965,1050,1150,10458,10461,7139,2150,9054,10455,10475,10476,9846,5188,9854,6644,10482,10486,5442,10225,1681,7999,10497,10495,7152,6824,8169,10136,10499,10497,5365,806,246,10118,10506,10506,8031,4862,7613,5528,10526,10520,9453,9960,3590,9477,10528,10524,9291,4037,4785,8414,10536,10558,10135,4513,1327,8562,10561,10566,8731,2127,2150,5867,10587,10588,5746,6284,3375,5122,10592,10596,8893,8342,5064,9389,10598,10596,5797,1548,5573,8384,10602,10599,10428,3761,10137,9577,10611,10608,7629,5300,6621,6918,10622,10625,10619,2103,2607,6675,10620,10629,7438,2265,3246,2360,10633,10635,6229,7741,10588,5732,10644,10649,8034,8343,5328,6888,10650,10650,8173,6442,4670,9286,10660,10657,10651,2853,8493,7534,10665,10666,9077,9831,1922,2875,10682,10685,10683,8608,2242,1554,10689,10685,8483,4913,8402,879,10707,10708,6531,2824,7462,9497,10708,10710,7232,9464,216,6034,10721,10722,10716,8107,9992,10099,10722,10722,8196,9079,3233,3512,10731,10729,5821,9859,3470,7843,10733,10738,6930,10428,8594,10506,10742,10752,9268,8853,456,6717,10768,10770,10157,4964,4159,3365,10771,10780,7606,8080,7494,10445,10787,10782,7877,8124,4627,10087,10780,10797,9456,8481,4614,8994,10824,10822,10215,6435,9453,10520,10835,10833,10360,10825,10819,10833,10842,10845,6619,5616,1870,8460,10851,10852,10846,4861,2671,8870,10857,10853,6366,1506,6878,10660,10859,10857,10395,7967,1894,9957,10865,10866,10860,7094,7525,5213,10881,10882,8117,6775,5586,8864,10886,10884,6640,7550,68,2058,10889,10890,6688,6672,8404,2556,10900,10902,7497,3939,7090,1946,10907,10908,9660,4559,6806,6471,10934,10931,10641,9042,5447,8395,10936,10934,10791,6782,6456,6392,10947,10945,9086,4707,4207,10455,10952,10956,6612,2344,954,10070,10971,10969,7937,1660,7027,5553,10977,10974,10209,1555,2504,2716,10985,10983,8862,10975,10969,10983,10986,10986,9709,4015,6869,8311}; uint16_t __nmod_poly_cp_primes5[] = {11003,11027,11047,11057,11059,11069,11071,11083,11087,11093,11113,11117,11119,11131,11149,11159,11161,11171,11173,11177,11197,11213,11239,11243,11251,11257,11261,11273,11279,11287,11299,11311,11317,11321,11329,11351,11353,11369,11383,11393,11399,11411,11423,11437,11443,11447,11467,11471,11483,11489,11491,11497,11503,11519,11527,11549,11551,11579,11587,11593,11597,11617,11621,11633,11657,11677,11681,11689,11699,11701,11717,11719,11731,11743,11777,11779,11783,11789,11801,11807,11813,11821,11827,11831,11833,11839,11863,11867,11887,11897,11903,11909,11923,11927,11933,11939,11941,11953,11959,11969,11971,11981,11987,12007,12011,12037,12041,12043,12049,12071,12073,12097,12101,12107,12109,12113,12119,12143,12149,12157,12161,12163,12197,12203,12211,12227,12239,12241,12251,12253,12263,12269,12277,12281,12289,12301,12323,12329,12343,12347,12373,12377,12379,12391,12401,12409,12413,12421,12433,12437,12451,12457,12473,12479,12487,12491,12497,12503,12511,12517,12527,12539,12541,12547,12553,12569,12577,12583,12589,12601,12611,12613,12619,12637,12641,12647,12653,12659,12671,12689,12697,12703,12713,12721,12739,12743,12757,12763,12781,12791,12799,12809,12821,12823,12829,12841,12853,12889,12893,12899,12907,12911,12917,12919,12923,12941,12953,12959,12967,12973,12979,12983,13001,13003,13007,13009,13033,13037,13043,13049,13063,13093,13099,13103,13109,13121,13127,13147,13151,13159,13163,13171,13177,13183,13187,13217,13219,13229,13241,13249,13259,13267,13291,13297,13309,13313,13327,13331,13337,13339,13367,13381,13397,13399,13411,13417,13421,13441,13451,13457,13463,13469,13477,13487,13499,13513,13523,13537,13553,13567,13577,13591,13597,13613,13619,13627,13633,13649,13669,13679,13681,13687,13691,13693,13697,13709,13711,13721,13723,13729,13751,13757,13759,13763,13781,13789,13799,13807,13829,13831,13841,13859,13873,13877,13879,13883,13901,13903,13907,13913,13921,13931,13933,13963,13967,13997,13999,14009,14011,14029,14033,14051,14057,14071,14081,14083,14087,14107,14143,14149,14153,14159,14173,14177,14197,14207,14221,14243,14249,14251,14281,14293,14303,14321,14323,14327,14341,14347,14369,14387,14389,14401,14407,14411,14419,14423,14431,14437,14447,14449,14461,14479,14489,14503,14519,14533,14537,14543,14549,14551,14557,14561,14563,14591,14593,14621,14627,14629,14633,14639,14653,14657,14669,14683,14699,14713,14717,14723,14731,14737,14741,14747,14753,14759,14767,14771,14779,14783,14797,14813,14821,14827,14831,14843,14851,14867,14869,14879,14887,14891,14897,14923,14929,14939,14947,14951,14957,14969,14983,15013,15017,15031,15053,15061,15073,15077,15083,15091,15101,15107,15121,15131,15137,15139,15149,15161,15173,15187,15193,15199,15217,15227,15233,15241,15259,15263,15269,15271,15277,15287,15289,15299,15307,15313,15319,15329,15331,15349,15359,15361,15373,15377,15383,15391,15401,15413,15427,15439,15443,15451,15461,15467,15473,15493,15497,15511,15527,15541,15551,15559,15569,15581,15583,15601,15607,15619,15629,15641,15643,15647,15649,15661,15667,15671,15679,15683,15727,15731,15733,15737,15739,15749,15761,15767,15773,15787,15791,15797,15803,15809,15817,15823,15859,15877,15881,15887,15889,15901,15907,15913,15919,15923,15937,15959,15971,15973,15991,16001,16007,16033,16057,16061,16063,16067,16069,16073,16087,16091,16097,16103,16111,16127,16139,16141,16183,16187,16189,16193,16217,16223,16229,16231,16249,16253,16267,16273,16301,16319,16333,16339,16349,16361,16363,16369,16381,16411,16417,16421,16427,16433,16447,16451,16453,16477,16481,16487,16493,16519,16529,16547,16553,16561,16567,16573,16603,16607,16619,16631,16633,16649,16651,16657,16661,16673,16691,16693,16699,16703,16729,16741,16747,16759,16763,16787,16811,16823,16829,16831,16843,16871,16879,16883,16889,16901,16903,16921,16927,16931,16937,16943,16963,16979,16981,16987,16993,17011,17021,17027,17029,17033,17041,17047,17053,17077,17093,17099,17107,17117,17123,17137,17159,17167,17183,17189,17191,17203,17207,17209,17231,17239,17257,17291,17293,17299,17317,17321,17327,17333,17341,17351,17359,17377,17383,17387,17389,17393,17401,17417,17419,17431,17443,17449,17467,17471,17477,17483,17489,17491,17497,17509,17519,17539,17551,17569,17573,17579,17581,17597,17599,17609,17623,17627,17657,17659,17669,17681,17683,17707,17713,17729,17737,17747,17749,17761,17783,17789,17791,17807,17827,17837,17839,17851,17863,17881,17891,17903,17909,17911,17921,17923,17929,17939,17957,17959,17971,17977,17981,17987,17989,18013,18041,18043,18047,18049,18059,18061,18077,18089,18097,18119,18121,18127,18131,18133,18143,18149,18169,18181,18191,18199,18211,18217,18223,18229,18233,18251,18253,18257,18269,18287,18289,18301,18307,18311,18313,18329,18341,18353,18367,18371,18379,18397,18401,18413,18427,18433,18439,18443,18451,18457,18461,18481,18493,18503,18517,18521,18523,18539,18541,18553,18583,18587,18593,18617,18637,18661,18671,18679,18691,18701,18713,18719,18731,18743,18749,18757,18773,18787,18793,18797,18803,18839,18859,18869,18899,18911,18913,18917,18919,18947,18959,18973,18979,19001,19009,19013,19031,19037,19051,19069,19073,19079,19081,19087,19121,19139,19141,19157,19163,19181,19183,19207,19211,19213,19219,19231,19237,19249,19259,19267,19273,19289,19301,19309,19319,19333,19373,19379,19381,19387,19391,19403,19417,19421,19423,19427,19429,19433,19441,19447,19457,19463,19469,19471,19477,19483,19489,19501,19507,19531,19541,19543,19553,19559,19571,19577,19583,19597,19603,19609,19661,19681,19687,19697,19699,19709,19717,19727,19739,19751,19753,19759,19763,19777,19793,19801,19813,19819,19841,19843,19853,19861,19867,19889,19891,19913,19919,19927,19937,19949,19961,19963,19973,19979,19991,19993,19997,20011,20021,20023,20029,20047,20051,20063,20071,20089,20101,20107,20113,20117,20123,20129,20143,20147,20149,20161,20173,20177,20183,20201,20219,20231,20233,20249,20261,20269,20287,20297,20323,20327,20333,20341,20347,20353,20357,20359,20369,20389,20393,20399,20407,20411,20431,20441,20443,20477,20479,20483,20507,20509,20521,20533,20543,20549,20551,20563,20593,20599,20611,20627,20639,20641,20663,20681,20693,20707,20717,20719,20731,20743,20747,20749,20753,20759,20771,20773,20789,20807,20809,20849,20857,20873,20879,20887,20897,20899,20903,20921,20929,20939,20947,20959,20963,20981,20983,21001,21011,21013,21017,21019,21023,21031,21059,21061,21067,21089,21101,21107,21121,21139,21143,21149,21157,21163,21169,21179,21187,21191,21193,21211,21221,21227,21247,21269,21277,21283,21313,21317,21319,21323,21341,21347,21377,21379,21383,21391,21397,21401,21407,21419,21433,21467,21481,21487,21491,21493,21499,21503,21517,21521,21523,21529,21557,21559,21563,21569,21577,21587,21589,21599,21601,21611,21613,21617,21647,21649,21661,21673,21683,21701,21713,21727,21737,21739,21751,21757,21767,21773,21787,21799,21803,21817,21821,21839,21841,21851,21859,21863,21871,21881,21893,21911,21929,21937,21943,21961,21977,21991,21997,22003,22013,22027,22031,22037,22039,22051,22063,22067,22073,22079,22091,22093,22109,22111,22123,22129,22133,22147,22153,22157,22159,22171,22189,22193,22229,22247,22259,22271,22273,22277,22279,22283,22291,22303,22307,22343,22349,22367,22369,22381,22391,22397,22409,22433,22441,22447,22453,22469,22481,22483,22501,22511,22531,22541,22543,22549,22567,22571,22573,22613,22619,22621,22637,22639,22643,22651,22669,22679,22691,22697,22699,22709,22717,22721,22727,22739,22741,22751,22769,22777,22783,22787,22807,22811,22817,22853,22859,22861,22871,22877,22901,22907,22921,22937,22943,22961,22963,22973,22993,23003,23011,23017,23021,23027,23029,23039,23041,23053,23057,23059,23063,23071,23081,23087,23099,23117,23131,23143,23159,23167,23173,23189,23197,23201,23203,23209,23227,23251,23269,23279,23291,23293,23297,23311,23321,23327,23333,23339,23357,23369,23371,23399,23417,23431,23447,23459,23473,23497,23509,23531,23537,23539,23549,23557,23561,23563,23567,23581,23593,23599,23603,23609,23623,23627,23629,23633,23663,23669,23671,23677,23687,23689,23719,23741,23743,23747,23753,23761,23767,23773,23789,23801,23813,23819,23827,23831,23833,23857,23869,23873,23879,23887,23893,23899,23909,23911,23917,23929,23957,23971,23977,23981,23993,24001,24007,24019,24023,24029,24043,24049,24061,24071,24077,24083,24091,24097,24103,24107,24109,24113,24121,24133,24137,24151,24169,24179,24181,24197,24203,24223,24229,24239,24247,24251,24281,24317,24329,24337,24359,24371,24373,24379,24391,24407,24413,24419,24421,24439,24443,24469,24473,24481,24499,24509,24517,24527,24533,24547,24551,24571,24593,24611,24623,24631,24659,24671,24677,24683,24691,24697,24709,24733,24749,24763,24767,24781,24793,24799,24809,24821,24841,24847,24851,24859,24877,24889,24907,24917,24919,24923,24943,24953,24967,24971,24977,24979,24989,25013,25031,25033,25037,25057,25073,25087,25097,25111,25117,25121,25127,25147,25153,25163,25169,25171,25183,25189,25219,25229,25237,25243,25247,25253,25261,25301,25303,25307,25309,25321,25339,25343,25349,25357,25367,25373,25391,25409,25411,25423,25439,25447,25453,25457,25463,25469,25471,25523,25537,25541,25561,25577,25579,25583,25589,25601,25603,25609,25621,25633,25639,25643,25657,25667,25673,25679,25693,25703,25717,25733,25741,25747,25759,25763,25771,25793,25799,25801,25819,25841,25847,25849,25867,25873,25889,25903,25913,25919,25931,25933,25939,25943,25951,25969,25981,25997,25999,26003,26017,26021,26029,26041,26053,26083,26099,26107,26111,26113,26119,26141,26153,26161,26171,26177,26183,26189,26203,26209,26227,26237,26249,26251,26261,26263,26267,26293,26297,26309,26317,26321,26339,26347,26357,26371,26387,26393,26399,26407,26417,26423,26431,26437,26449,26459,26479,26489,26497,26501,26513,26539,26557,26561,26573,26591,26597,26627,26633,26641,26647,26669,26681,26683,26687,26693,26699,26701,26711,26713,26717,26723,26729,26731,26737,26759,26777,26783,26801,26813,26821,26833,26839,26849,26861,26863,26879,26881,26891,26893,26903,26921,26927,26947,26951,26953,26959,26981,26987,26993,27011,27017,27031,27043,27059,27061,27067,27073,27077,27091,27103,27107,27109,27127,27143,27179,27191,27197,27211,27239,27241,27253,27259,27271,27277,27281,27283,27299,27329,27337,27361,27367,27397,27407,27409,27427,27431,27437,27449,27457,27479,27481,27487,27509,27527,27529,27539,27541,27551,27581,27583,27611,27617,27631,27647,27653,27673,27689,27691,27697,27701,27733,27737,27739,27743,27749,27751,27763,27767,27773,27779,27791,27793,27799,27803,27809,27817,27823,27827,27847,27851,27883,27893,27901,27917,27919,27941,27943,27947,27953,27961,27967,27983,27997,28001,28019,28027,28031,28051,28057,28069,28081,28087,28097,28099,28109,28111,28123,28151,28163,28181,28183,28201,28211,28219,28229,28277,28279,28283,28289,28297,28307,28309,28319,28349,28351,28387,28393,28403,28409,28411,28429,28433,28439,28447,28463,28477,28493,28499,28513,28517,28537,28541,28547,28549,28559,28571,28573,28579,28591,28597,28603,28607,28619,28621,28627,28631,28643,28649,28657,28661,28663,28669,28687,28697,28703,28711,28723,28729,28751,28753,28759,28771,28789,28793,28807,28813,28817,28837,28843,28859,28867,28871,28879,28901,28909,28921,28927,28933,28949,28961,28979,29009,29017,29021,29023,29027,29033,29059,29063,29077,29101,29123,29129,29131,29137,29147,29153,29167,29173,29179,29191,29201,29207,29209,29221,29231,29243,29251,29269,29287,29297,29303,29311,29327,29333,29339,29347,29363,29383,29387,29389,29399,29401,29411,29423,29429,29437,29443,29453,29473,29483,29501,29527,29531,29537,29567,29569,29573,29581,29587,29599,29611,29629,29633,29641,29663,29669,29671,29683,29717,29723,29741,29753,29759,29761,29789,29803,29819,29833,29837,29851,29863,29867,29873,29879,29881,29917,29921,29927,29947,29959,29983,29989,30011,30013,30029,30047,30059,30071,30089,30091,30097,30103,30109,30113,30119,30133,30137,30139,30161,30169,30181,30187,30197,30203,30211,30223,30241,30253,30259,30269,30271,30293,30307,30313,30319,30323,30341,30347,30367,30389,30391,30403,30427,30431,30449,30467,30469,30491,30493,30497,30509,30517,30529,30539,30553,30557,30559,30577,30593,30631,30637,30643,30649,30661,30671,30677,30689,30697,30703,30707,30713,30727,30757,30763,30773,30781,30803,30809,30817,30829,30839,30841,30851,30853,30859,30869,30871,30881,30893,30911,30931,30937,30941,30949,30971,30977,30983,31013,31019,31033,31039,31051,31063,31069,31079,31081,31091,31121,31123,31139,31147,31151,31153,31159,31177,31181,31183,31189,31193,31219,31223,31231,31237,31247,31249,31253,31259,31267,31271,31277,31307,31319,31321,31327,31333,31337,31357,31379,31387,31391,31393,31397,31469,31477,31481,31489,31511,31513,31517,31531,31541,31543,31547,31567,31573,31583,31601,31607,31627,31643,31649,31657,31663,31667,31687,31699,31721,31723,31727,31729,31741,31751,31769,31771,31793,31799,31817,31847,31849,31859,31873,31883,31891,31907,31957,31963,31973,31981,31991,32003,32009,32027,32029,32051,32057,32059,32063,32069,32077,32083,32089,32099,32117,32119,32141,32143,32159,32173,32183,32189,32191,32203,32213,32233,32237,32251,32257,32261,32297,32299,32303,32309,32321,32323,32327,32341,32353,32359,32363,32369,32371,32377,32381,32401,32411,32413,32423,32429,32441,32443,32467,32479,32491,32497,32503,32507,32531,32533,32537,32561,32563,32569,32573,32579,32587,32603,32609,32611,32621,32633,32647,32653,32687,32693,32707,32713,32717,32719,32749,32771,32779,32783,32789,32797,32801,32803,32831,32833,32839,32843,32869,32887,32909,32911,32917,32933,32939,32941,32957,32969,32971,32983,32987,32993,32999,33013,33023,33029,33037,33049,33053,33071,33073,33083,33091,33107,33113,33119,33149,33151,33161,33179,33181,33191,33199,33203,33211,33223,33247,33287,33289,33301,33311,33317,33329,33331,33343,33347,33349,33353,33359,33377,33391,33403,33409,33413,33427,33457,33461,33469,33479,33487,33493,33503,33521,33529,33533,33547,33563,33569,33577,33581,33587,33589,33599,33601,33613,33617,33619,33623,33629,33637,33641,33647,33679,33703,33713,33721,33739,33749,33751,33757,33767,33769,33773,33791,33797,33809,33811,33827,33829,33851,33857,33863,33871,33889,33893,33911,33923,33931,33937,33941,33961,33967,33997,34019,34031,34033,34039,34057,34061,34123,34127,34129,34141,34147,34157,34159,34171,34183,34211,34213,34217,34231,34253,34259,34261,34267,34273,34283,34297,34301,34303,34313,34319,34327,34337,34351,34361,34367,34369,34381,34403,34421,34429,34439,34457,34469,34471,34483,34487,34499,34501,34511,34513,34519,34537,34543,34549,34583,34589,34591,34603,34607,34613,34631,34649,34651,34667,34673,34679,34687,34693,34703,34721,34729,34739,34747,34757,34759,34763,34781,34807,34819,34841,34843,34847,34849,34871,34877,34883,34897,34913,34919,34939,34949,34961,34963,34981,35023,35027,35051,35053,35059,35069,35081,35083,35089,35099,35107,35111,35117,35129,35141,35149,35153,35159,35171,35201,35221,35227,35251,35257,35267,35279,35281,35291,35311,35317,35323,35327,35339,35353,35363,35381,35393,35401,35407,35419,35423,35437,35447,35449,35461,35491,35507,35509,35521,35527,35531,35533,35537,35543,35569,35573,35591,35593,35597,35603,35617,35671,35677,35729,35731,35747,35753,35759,35771,35797,35801,35803,35809,35831,35837,35839,35851,35863,35869,35879,35897,35899,35911,35923,35933,35951,35963,35969,35977,35983,35993,35999,36007,36011,36013,36017,36037,36061,36067,36073,36083,36097,36107,36109,36131,36137,36151,36161,36187,36191,36209,36217,36229,36241,36251,36263,36269,36277,36293,36299,36307,36313,36319,36341,36343,36353,36373,36383,36389,36433,36451,36457,36467,36469,36473,36479,36493,36497,36523,36527,36529,36541,36551,36559,36563,36571,36583,36587,36599,36607,36629,36637,36643,36653,36671,36677,36683,36691,36697,36709,36713,36721,36739,36749,36761,36767,36779,36781,36787,36791,36793,36809,36821,36833,36847,36857,36871,36877,36887,36899,36901,36913,36919,36923,36929,36931,36943,36947,36973,36979,36997,37003,37013,37019,37021,37039,37049,37057,37061,37087,37097,37117,37123,37139,37159,37171,37181,37189,37199,37201,37217,37223,37243,37253,37273,37277,37307,37309,37313,37321,37337,37339,37357,37361,37363,37369,37379,37397,37409,37423,37441,37447,37463,37483,37489,37493,37501,37507,37511,37517,37529,37537,37547,37549,37561,37567,37571,37573,37579,37589,37591,37607,37619,37633,37643,37649,37657,37663,37691,37693,37699,37717,37747,37781,37783,37799,37811,37813,37831,37847,37853,37861,37871,37879,37889,37897,37907,37951,37957,37963,37967,37987,37991,37993,37997,38011,38039,38047,38053,38069,38083,38113,38119,38149,38153,38167,38177,38183,38189,38197,38201,38219,38231,38237,38239,38261,38273,38281,38287,38299,38303,38317,38321,38327,38329,38333,38351,38371,38377,38393,38431,38447,38449,38453,38459,38461,38501,38543,38557,38561,38567,38569,38593,38603,38609,38611,38629,38639,38651,38653,38669,38671,38677,38693,38699,38707,38711,38713,38723,38729,38737,38747,38749,38767,38783,38791,38803,38821,38833,38839,38851,38861,38867,38873,38891,38903,38917,38921,38923,38933,38953,38959,38971,38977,38993,39019,39023,39041,39043,39047,39079,39089,39097,39103,39107,39113,39119,39133,39139,39157,39161,39163,39181,39191,39199,39209,39217,39227,39229,39233,39239,39241,39251,39293,39301,39313,39317,39323,39341,39343,39359,39367,39371,39373,39383,39397,39409,39419,39439,39443,39451,39461,39499,39503,39509,39511,39521,39541,39551,39563,39569,39581,39607,39619,39623,39631,39659,39667,39671,39679,39703,39709,39719,39727,39733,39749,39761,39769,39779,39791,39799,39821,39827,39829,39839,39841,39847,39857,39863,39869,39877,39883,39887,39901,39929,39937,39953,39971,39979,39983,39989,40009,40013,40031,40037,40039,40063,40087,40093,40099,40111,40123,40127,40129,40151,40153,40163,40169,40177,40189,40193,40213,40231,40237,40241,40253,40277,40283,40289,40343,40351,40357,40361,40387,40423,40427,40429,40433,40459,40471,40483,40487,40493,40499,40507,40519,40529,40531,40543,40559,40577,40583,40591,40597,40609,40627,40637,40639,40693,40697,40699,40709,40739,40751,40759,40763,40771,40787,40801,40813,40819,40823,40829,40841,40847,40849,40853,40867,40879,40883,40897,40903,40927,40933,40939,40949,40961,40973,40993,41011,41017,41023,41039,41047,41051,41057,41077,41081,41113,41117,41131,41141,41143,41149,41161,41177,41179,41183,41189,41201,41203,41213,41221,41227,41231,41233,41243,41257,41263,41269,41281,41299,41333,41341,41351,41357,41381,41387,41389,41399,41411,41413,41443,41453,41467,41479,41491,41507,41513,41519,41521,41539,41543,41549,41579,41593,41597,41603,41609,41611,41617,41621,41627,41641,41647,41651,41659,41669,41681,41687,41719,41729,41737,41759,41761,41771,41777,41801,41809,41813,41843,41849,41851,41863,41879,41887,41893,41897,41903,41911,41927,41941,41947,41953,41957,41959,41969,41981,41983,41999,42013,42017,42019,42023,42043,42061,42071,42073,42083,42089,42101,42131,42139,42157,42169,42179,42181,42187,42193,42197,42209,42221,42223,42227,42239,42257,42281,42283,42293,42299,42307,42323,42331,42337,42349,42359,42373,42379,42391,42397,42403,42407,42409,42433,42437,42443,42451,42457,42461,42463,42467,42473,42487,42491,42499,42509,42533,42557,42569,42571,42577,42589,42611,42641,42643,42649,42667,42677,42683,42689,42697,42701,42703,42709,42719,42727,42737,42743,42751,42767,42773,42787,42793,42797,42821,42829,42839,42841,42853,42859,42863,42899,42901,42923,42929,42937,42943,42953,42961,42967,42979,42989,43003,43013,43019,43037,43049,43051,43063,43067,43093,43103,43117,43133,43151,43159,43177,43189,43201,43207,43223,43237,43261,43271,43283,43291,43313,43319,43321,43331,43391,43397,43399,43403,43411,43427,43441,43451,43457,43481,43487,43499,43517,43541,43543,43573,43577,43579,43591,43597,43607,43609,43613,43627,43633,43649,43651,43661,43669,43691,43711,43717,43721,43753,43759,43777,43781,43783,43787,43789,43793,43801,43853,43867,43889,43891,43913,43933,43943,43951,43961,43963,43969,43973,43987,43991,43997,44017,44021,44027,44029,44041,44053,44059,44071,44087,44089,44101,44111,44119,44123,44129,44131,44159,44171,44179,44189,44201,44203,44207,44221,44249,44257,44263,44267,44269,44273,44279,44281,44293,44351,44357,44371,44381,44383,44389,44417,44449,44453,44483,44491,44497,44501,44507,44519,44531,44533,44537,44543,44549,44563,44579,44587,44617,44621,44623,44633,44641,44647,44651,44657,44683,44687,44699,44701,44711,44729,44741,44753,44771,44773,44777,44789,44797,44809,44819,44839,44843,44851,44867,44879,44887,44893,44909,44917,44927,44939,44953,44959,44963,44971,44983,44987,45007,45013,45053,45061,45077,45083,45119,45121,45127,45131,45137,45139,45161,45179,45181,45191,45197,45233,45247,45259,45263,45281,45289,45293,45307,45317,45319,45329,45337,45341,45343,45361,45377,45389,45403,45413,45427,45433,45439,45481,45491,45497,45503,45523,45533,45541,45553,45557,45569,45587,45589,45599,45613,45631,45641,45659,45667,45673,45677,45691,45697,45707,45737,45751,45757,45763,45767,45779,45817,45821,45823,45827,45833,45841,45853,45863,45869,45887,45893,45943,45949,45953,45959,45971,45979,45989,46021,46027,46049,46051,46061,46073,46091,46093,46099,46103,46133,46141,46147,46153,46171,46181,46183,46187,46199,46219,46229,46237,46261,46271,46273,46279,46301,46307,46309,46327,46337,46349,46351,46381,46399,46411,46439,46441,46447,46451,46457,46471,46477,46489,46499,46507,46511,46523,46549,46559,46567,46573,46589,46591,46601,46619,46633,46639,46643,46649,46663,46679,46681,46687,46691,46703,46723,46727,46747,46751,46757,46769,46771,46807,46811,46817,46819,46829,46831,46853,46861,46867,46877,46889,46901,46919,46933,46957,46993,46997,47017,47041,47051,47057,47059,47087,47093,47111,47119,47123,47129,47137,47143,47147,47149,47161,47189,47207,47221,47237,47251,47269,47279,47287,47293,47297,47303,47309,47317,47339,47351,47353,47363,47381,47387,47389,47407,47417,47419,47431,47441,47459,47491,47497,47501,47507,47513,47521,47527,47533,47543,47563,47569,47581,47591,47599,47609,47623,47629,47639,47653,47657,47659,47681,47699,47701,47711,47713,47717,47737,47741,47743,47777,47779,47791,47797,47807,47809,47819,47837,47843,47857,47869,47881,47903,47911,47917,47933,47939,47947,47951,47963,47969,47977,47981,48017,48023,48029,48049,48073,48079,48091,48109,48119,48121,48131,48157,48163,48179,48187,48193,48197,48221,48239,48247,48259,48271,48281,48299,48311,48313,48337,48341,48353,48371,48383,48397,48407,48409,48413,48437,48449,48463,48473,48479,48481,48487,48491,48497,48523,48527,48533,48539,48541,48563,48571,48589,48593,48611,48619,48623,48647,48649,48661,48673,48677,48679,48731,48733,48751,48757,48761,48767,48779,48781,48787,48799,48809,48817,48821,48823,48847,48857,48859,48869,48871,48883,48889,48907,48947,48953,48973,48989,48991,49003,49009,49019,49031,49033,49037,49043,49057,49069,49081,49103,49109,49117,49121,49123,49139,49157,49169,49171,49177,49193,49199,49201,49207,49211,49223,49253,49261,49277,49279,49297,49307,49331,49333,49339,49363,49367,49369,49391,49393,49409,49411,49417,49429,49433,49451,49459,49463,49477,49481,49499,49523,49529,49531,49537,49547,49549,49559,49597,49603,49613,49627,49633,49639,49663,49667,49669,49681,49697,49711,49727,49739,49741,49747,49757,49783,49787,49789,49801,49807,49811,49823,49831,49843,49853,49871,49877,49891,49919,49921,49927,49937,49939,49943,49957,49991,49993,49999,50021,50023,50033,50047,50051,50053,50069,50077,50087,50093,50101,50111,50119,50123,50129,50131,50147,50153,50159,50177,50207,50221,50227,50231,50261,50263,50273,50287,50291,50311,50321,50329,50333,50341,50359,50363,50377,50383,50387,50411,50417,50423,50441,50459,50461,50497,50503,50513,50527,50539,50543,50549,50551,50581,50587,50591,50593,50599,50627,50647,50651,50671,50683,50707,50723,50741,50753,50767,50773,50777,50789,50821,50833,50839,50849,50857,50867,50873,50891,50893,50909,50923,50929,50951,50957,50969,50971,50989,50993,51001,51031,51043,51047,51059,51061,51071,51109,51131,51133,51137,51151,51157,51169,51193,51197,51199,51203,51217,51229,51239,51241,51257,51263,51283,51287,51307,51329,51341,51343,51347,51349,51361,51383,51407,51413,51419,51421,51427,51431,51437,51439,51449,51461,51473,51479,51481,51487,51503,51511,51517,51521,51539,51551,51563,51577,51581,51593,51599,51607,51613,51631,51637,51647,51659,51673,51679,51683,51691,51713,51719,51721,51749,51767,51769,51787,51797,51803,51817,51827,51829,51839,51853,51859,51869,51871,51893,51899,51907,51913,51929,51941,51949,51971,51973,51977,51991,52009,52021,52027,52051,52057,52067,52069,52081,52103,52121,52127,52147,52153,52163,52177,52181,52183,52189,52201,52223,52237,52249,52253,52259,52267,52289,52291,52301,52313,52321,52361,52363,52369,52379,52387,52391,52433,52453,52457,52489,52501,52511,52517,52529,52541,52543,52553,52561,52567,52571,52579,52583,52609,52627,52631,52639,52667,52673,52691,52697,52709,52711,52721,52727,52733,52747,52757,52769,52783,52807,52813,52817,52837,52859,52861,52879,52883,52889,52901,52903,52919,52937,52951,52957,52963,52967,52973,52981,52999,53003,53017,53047,53051,53069,53077,53087,53089,53093,53101,53113,53117,53129,53147,53149,53161,53171,53173,53189,53197,53201,53231,53233,53239,53267,53269,53279,53281,53299,53309,53323,53327,53353,53359,53377,53381,53401,53407,53411,53419,53437,53441,53453,53479,53503,53507,53527,53549,53551,53569,53591,53593,53597,53609,53611,53617,53623,53629,53633,53639,53653,53657,53681,53693,53699,53717,53719,53731,53759,53773,53777,53783,53791,53813,53819,53831,53849,53857,53861,53881,53887,53891,53897,53899,53917,53923,53927,53939,53951,53959,53987,53993,54001,54011,54013,54037,54049,54059,54083,54091,54101,54121,54133,54139,54151,54163,54167,54181,54193,54217,54251,54269,54277,54287,54293,54311,54319,54323,54331,54347,54361,54367,54371,54377,54401,54403,54409,54413,54419,54421,54437,54443,54449,54469,54493,54497,54499,54503,54517,54521,54539,54541,54547,54559,54563,54577,54581,54583,54601,54617,54623,54629,54631,54647,54667,54673,54679,54709,54713,54721,54727,54751,54767,54773,54779,54787,54799,54829,54833,54851,54869,54877,54881,54907,54917,54919,54941,54949,54959,54973,54979,54983,55001,55009,55021,55049,55051,55057,55061,55073,55079,55103,55109,55117,55127,55147,55163,55171,55201,55207,55213,55217,55219,55229,55243,55249,55259,55291,55313,55331,55333,55337,55339,55343,55351,55373,55381,55399,55411,55439,55441,55457,55469,55487,55501,55511,55529,55541,55547,55579,55589,55603,55609,55619,55621,55631,55633,55639,55661,55663,55667,55673,55681,55691,55697,55711,55717,55721,55733,55763,55787,55793,55799,55807,55813,55817,55819,55823,55829,55837,55843,55849,55871,55889,55897,55901,55903,55921,55927,55931,55933,55949,55967,55987,55997,56003,56009,56039,56041,56053,56081,56087,56093,56099,56101,56113,56123,56131,56149,56167,56171,56179,56197,56207,56209,56237,56239,56249,56263,56267,56269,56299,56311,56333,56359,56369,56377,56383,56393,56401,56417,56431,56437,56443,56453,56467,56473,56477,56479,56489,56501,56503,56509,56519,56527,56531,56533,56543,56569,56591,56597,56599,56611,56629,56633,56659,56663,56671,56681,56687,56701,56711,56713,56731,56737,56747,56767,56773,56779,56783,56807,56809,56813,56821,56827,56843,56857,56873,56891,56893,56897,56909,56911,56921,56923,56929,56941,56951,56957,56963,56983,56989,56993,56999,57037,57041,57047,57059,57073,57077,57089,57097,57107,57119,57131,57139,57143,57149,57163,57173,57179,57191,57193,57203,57221,57223,57241,57251,57259,57269,57271,57283,57287,57301,57329,57331,57347,57349,57367,57373,57383,57389,57397,57413,57427,57457,57467,57487,57493,57503,57527,57529,57557,57559,57571,57587,57593,57601,57637,57641,57649,57653,57667,57679,57689,57697,57709,57713,57719,57727,57731,57737,57751,57773,57781,57787,57791,57793,57803,57809,57829,57839,57847,57853,57859,57881,57899,57901,57917,57923,57943,57947,57973,57977,57991,58013,58027,58031,58043,58049,58057,58061,58067,58073,58099,58109,58111,58129,58147,58151,58153,58169,58171,58189,58193,58199,58207,58211,58217,58229,58231,58237,58243,58271,58309,58313,58321,58337,58363,58367,58369,58379,58391,58393,58403,58411,58417,58427,58439,58441,58451,58453,58477,58481,58511,58537,58543,58549,58567,58573,58579,58601,58603,58613,58631,58657,58661,58679,58687,58693,58699,58711,58727,58733,58741,58757,58763,58771,58787,58789,58831,58889,58897,58901,58907,58909,58913,58921,58937,58943,58963,58967,58979,58991,58997,59009,59011,59021,59023,59029,59051,59053,59063,59069,59077,59083,59093,59107,59113,59119,59123,59141,59149,59159,59167,59183,59197,59207,59209,59219,59221,59233,59239,59243,59263,59273,59281,59333,59341,59351,59357,59359,59369,59377,59387,59393,59399,59407,59417,59419,59441,59443,59447,59453,59467,59471,59473,59497,59509,59513,59539,59557,59561,59567,59581,59611,59617,59621,59627,59629,59651,59659,59663,59669,59671,59693,59699,59707,59723,59729,59743,59747,59753,59771,59779,59791,59797,59809,59833,59863,59879,59887,59921,59929,59951,59957,59971,59981,59999,60013,60017,60029,60037,60041,60077,60083,60089,60091,60101,60103,60107,60127,60133,60139,60149,60161,60167,60169,60209,60217,60223,60251,60257,60259,60271,60289,60293,60317,60331,60337,60343,60353,60373,60383,60397,60413,60427,60443,60449,60457,60493,60497,60509,60521,60527,60539,60589,60601,60607,60611,60617,60623,60631,60637,60647,60649,60659,60661,60679,60689,60703,60719,60727,60733,60737,60757,60761,60763,60773,60779,60793,60811,60821,60859,60869,60887,60889,60899,60901,60913,60917,60919,60923,60937,60943,60953,60961,61001,61007,61027,61031,61043,61051,61057,61091,61099,61121,61129,61141,61151,61153,61169,61211,61223,61231,61253,61261,61283,61291,61297,61331,61333,61339,61343,61357,61363,61379,61381,61403,61409,61417,61441,61463,61469,61471,61483,61487,61493,61507,61511,61519,61543,61547,61553,61559,61561,61583,61603,61609,61613,61627,61631,61637,61643,61651,61657,61667,61673,61681,61687,61703,61717,61723,61729,61751,61757,61781,61813,61819,61837,61843,61861,61871,61879,61909,61927,61933,61949,61961,61967,61979,61981,61987,61991,62003,62011,62017,62039,62047,62053,62057,62071,62081,62099,62119,62129,62131,62137,62141,62143,62171,62189,62191,62201,62207,62213,62219,62233,62273,62297,62299,62303,62311,62323,62327,62347,62351,62383,62401,62417,62423,62459,62467,62473,62477,62483,62497,62501,62507,62533,62539,62549,62563,62581,62591,62597,62603,62617,62627,62633,62639,62653,62659,62683,62687,62701,62723,62731,62743,62753,62761,62773,62791,62801,62819,62827,62851,62861,62869,62873,62897,62903,62921,62927,62929,62939,62969,62971,62981,62983,62987,62989,63029,63031,63059,63067,63073,63079,63097,63103,63113,63127,63131,63149,63179,63197,63199,63211,63241,63247,63277,63281,63299,63311,63313,63317,63331,63337,63347,63353,63361,63367,63377,63389,63391,63397,63409,63419,63421,63439,63443,63463,63467,63473,63487,63493,63499,63521,63527,63533,63541,63559,63577,63587,63589,63599,63601,63607,63611,63617,63629,63647,63649,63659,63667,63671,63689,63691,63697,63703,63709,63719,63727,63737,63743,63761,63773,63781,63793,63799,63803,63809,63823,63839,63841,63853,63857,63863,63901,63907,63913,63929,63949,63977,63997,64007,64013,64019,64033,64037,64063,64067,64081,64091,64109,64123,64151,64153,64157,64171,64187,64189,64217,64223,64231,64237,64271,64279,64283,64301,64303,64319,64327,64333,64373,64381,64399,64403,64433,64439,64451,64453,64483,64489,64499,64513,64553,64567,64577,64579,64591,64601,64609,64613,64621,64627,64633,64661,64663,64667,64679,64693,64709,64717,64747,64763,64781,64783,64793,64811,64817,64849,64853,64871,64877,64879,64891,64901,64919,64921,64927,64937,64951,64969,64997,65003,65011,65027,65029,65033,65053,65063,65071,65089,65099,65101,65111,65119,65123,65129,65141,65147,65167,65171,65173,65179,65183,65203,65213,65239,65257,65267,65269,65287,65293,65309,65323,65327,65353,65357,65371,65381,65393,65407,65413,65419,65423,65437,65447,65449,65479,65497,65519,65521,0}; uint8_t __nmod_poly_cp_sm_coeffs5[] = {2,4,8,2,3,8,3,4,3,3,1,7,10,8,0,2,12,0,3,6,3,2,6,8,5,5,3,2,2,6,13,4,14,3,1,4,3,1,6,2,4,8,10,2,7,7,11,4,7,1,16,2,3,4,5,1,18,3,4,9,2,6,6,2,2,1,3,1,2,5,7,3,13,2,2,10,4,10,2,3,3,3,3,0,7,7,2,3,1,6,3,1,6,3,1,4,2,2,8,3,5,7,7,3,5,7,11,2,7,3,8,3,3,2,5,2,9,3,3,4,11,1,5,7,4,7,5,2,3,2,2,3,2,2,7,5,1,14,5,2,2,11,1,2,2,2,14,3,5,0,3,3,2,7,7,8,3,4,2,7,3,3,5,5,2,2,3,8,7,4,2,2,2,3,2,6,8,5,2,12,3,4,7,10,4,21,2,3,6,3,4,4,3,6,6,2,4,18,3,1,2,7,2,0,2,4,8,6,2,12,2,7,3,6,2,4,3,6,3,3,3,12,3,1,2,2,5,2,5,7,2,2,2,7,3,4,0,5,2,6,2,5,9,2,6,3,2,4,8,7,1,11,5,3,6,3,3,3,3,4,4,2,3,7,3,1,18,3,1,4,5,2,3,2,5,2,5,1,5,5,3,10,2,2,4,2,9,3,10,3,3,5,3,6,3,4,2,3,10,4,10,2,5,2,2,0,2,2,1,13,5,3,2,3,9,5,1,6,3,6,4,2,2,2,13,4,35,11,4,6,7,2,8,5,3,12,3,4,1,2,4,3,6,8,7,3,4,0,7,1,7,10,10,2,2,5,2,2,2,3,3,3,2,5,2,2,2,11,6,2,3,8,2,5,6,2,2,2,13,3,2,7,5,14,2,2,3,2,2,3,5,1,3,2,5,4,2,2,6,3,1,0,11,1,23,2,5,6,2,3,2,3,6,8,7,3,0,2,2,4,2,4,6,6,3,1,2,5,8,26,1,3,3,6,0,7,4,16,2,8,6,7,5,4,13,3,11,2,3,3,3,1,7,10,2,8,3,3,16,23,3,14,3,10,2,2,3,7,3,4,25,5,2,7,3,5,6,6,1,6,5,5,1,2,3,8,14,2,1,2,2,7,5,5,6,3,3,0,10,4,15,5,1,15,2,4,8,11,3,23,2,2,7,2,6,3,2,5,2,2,4,6,3,3,2,5,1,8,2,3,6,2,3,9,14,6,8,3,1,11,7,11,14,3,4,10,3,5,7,13,5,14,2,6,6,5,3,3,2,2,7,2,4,8,2,4,3,7,13,3,13,7,4,3,8,0,2,7,6,3,5,4,2,6,8,21,1,18,5,1,10,13,1,0,3,1,4,2,3,7,2,2,2,23,3,3,2,3,6,6,3,4,2,5,8,2,3,1,3,3,4,7,1,2,3,8,10,14,1,3,2,2,20,5,8,6,3,1,6,5,9,6,5,2,3,7,2,14,5,5,10,2,2,3,2,4,4,3,6,0,5,1,5,6,2,0,3,1,3,5,2,6,2,4,3,7,1,4,5,6,5,2,5,8,13,2,3,3,1,6,2,2,4,11,3,1,5,1,12,3,3,6,2,2,2,3,6,7,3,1,2,2,3,3,3,3,0,7,2,0,6,2,2,3,4,6,2,4,2,5,1,15,6,9,11,3,5,26,3,1,5,2,3,8,3,6,25,2,4,8,5,7,5,10,4,10,2,2,23,3,9,4,2,6,2,5,7,8,10,6,12,11,2,24,2,3,7,3,5,1,5,2,8,2,2,6,2,6,10,5,9,3,6,1,2,5,1,12,2,3,2,7,7,17,3,4,0,3,17,6,3,9,0,3,4,2,5,2,12,2,2,4,2,7,1,2,6,8,5,10,6,3,5,0,6,2,7,7,1,11,22,5,13,3,5,6,2,4,1,6,3,10,3,3,0,2,3,1,6,3,3,3,1,2,2,2,8,23,7,28,11,1,3,2,3,7,6,2,3,2,4,0,7,1,3,7,3,4,7,1,2,5,7,12,2,4,4,6,3,3,6,4,0,2,3,0,5,5,6,2,3,6,6,1,2,2,3,0,2,3,3,3,5,5,2,2,4,3,1,9,7,2,14,2,3,8,2,2,3,3,1,2,5,1,6,2,3,6,3,5,3,3,6,1,2,4,8,6,1,7,3,3,4,2,2,8,3,1,12,7,2,2,3,1,2,3,1,2,5,5,5,2,6,8,3,1,2,6,1,2,3,4,7,13,2,4,2,2,6,3,1,0,11,1,7,5,3,3,2,2,10,2,2,7,3,5,3,3,1,5,19,4,32,6,1,7,5,1,4,3,1,7,5,1,6,5,1,3,2,4,3,3,7,3,3,1,0,2,3,7,2,2,18,11,2,20,19,1,11,2,4,3,2,4,6,5,1,3,3,3,3,5,3,7,5,6,7,22,1,39,2,4,3,3,1,4,3,3,2,3,15,10,13,1,4,2,4,2,3,5,4,5,2,2,2,4,0,3,1,6,2,4,6,6,2,0,3,1,2,11,2,5,5,7,14,2,7,4,2,3,7,2,5,0,3,1,9,11,1,7,2,7,12,3,3,0,2,2,1,3,5,3,2,3,4,5,5,14,2,2,6,2,3,7,10,3,2,10,7,6,2,3,9,2,2,1,3,3,6,17,5,3,3,8,6,2,2,0,3,8,2,5,5,10,2,6,3,2,3,6,2,4,6,2,6,8,11,1,4,2,3,13,2,5,8,2,2,4,2,2,6,7,2,2,3,1,3,2,2,7,3,1,1,2,5,10,7,1,16,2,3,7,2,6,8,19,1,2,2,2,8,3,3,2,3,6,4,2,2,6,3,4,7,3,3,3,2,8,4,2,5,10,5,3,15,2,3,9,2,2,0,2,6,1,2,7,0,2,8,0,11,3,23,2,3,8,3,1,0,2,4,2,2,2,7,3,7,0,2,3,7,2,4,8,5,8,6,6,6,4,10,2,21,2,3,8,3,5,1,11,2,14,2,5,2,5,6,8,2,5,9,11,5,6,6,1,7,5,1,8,11,1,16,2,3,8,3,1,5,5,3,20,3,11,7,3,1,7,2,2,8,2,6,22,11,1,6,7,2,0,2,5,6,3,8,0,5,2,2,12,6,10,6,11,6,2,2,3,2,5,2,3,8,3,2,3,3,3,4,6,2,3,3,5,5,3,3,1,6,5,1,3,3,11,9,3,10,4,5,3,9,6,1,2,7,5,3,3,6,6,3,1,2,2,3,8,5,7,3,23,2,8,3,1,3,7,3,6,2,3,8,3,3,2,5,2,0,5,12,4,11,3,27,2,2,12,2,6,8,13,3,3,11,3,2,2,3,2,3,5,2,2,2,3,6,3,4,3,3,7,2,6,2,2,7,8,3,1,2,5,6,3,2,4,19,2,6,8,29,1,3,2,2,4,2,3,8,3,5,5,5,1,14,3,1,3,2,2,8,5,1,6,3,3,7,5,2,5,21,3,18,10,2,3,2,2,24,5,2,12,6,1,6,2,2,11,7,1,8,11,1,8,2,2,8,7,4,9,12,6,6,3,3,4,5,5,5,5,1,24,7,4,14,12,5,2,5,1,2,2,4,0,2,2,9,3,3,7,5,11,5,6,3,2,3,8,1,5,2,2,7,1,5,5,5,7,2,2,3,6,4,10,3,1,3,2,2,2,2,6,3,5,2,2,3,3,2,5,1,11,2,3,1,3,4,3,17,6,20,2,5,3,3,6,2,7,1,14,2,3,3,7,3,11,2,6,12,2,5,8,2,3,6,3,7,2,2,4,14,7,4,16,2,4,6,3,1,2,10,4,21,2,8,7,2,3,7,3,11,4,3,5,5,7,3,4,2,2,3,2,2,8,6,7,3,5,1,5,2,3,6,3,6,3,3,10,7,2,2,2,3,1,9,7,1,14,3,4,3,2,7,12,2,6,16,5,1,10,2,2,7,19,1,8,15,4,14,3,6,0,2,4,12,5,13,6,10,7,7,3,1,7,6,1,7,2,6,3,3,10,3,5,8,2,13,2,16,6,1,11,2,2,2,3,4,6,2,2,21,2,3,13,7,2,2,5,3,8,2,2,12,6,3,3,2,6,13,17,2,3,3,4,6,2,15,0,3,7,4,2,3,8,3,3,5,17,3,16,6,1,2,2,3,2,3,1,7,5,7,7,2,5,8,2,2,0,2,6,3,3,1,3,10,5,14,2,2,8,2,8,0,2,2,4,10,6,10,3,5,1,7,1,0,3,1,2,2,4,10,2,6,36,2,2,1,2,3,2,3,5,2,3,4,14,2,3,7,5,1,6,7,1,3,3,11,2,5,1,7,2,4,1,3,4,3,2,5,8,5,3,3,14,5,0,13,3,6,6,3,3,5,1,10,6,1,1,7,3,7,2,6,8,2,2,6,3,6,2,5,2,11,2,3,6,6,4,11,11,2,3,3,3,3,7,2,17,5,6,3,2,4,8,2,6,12,3,5,9,11,2,8,3,5,6,3,3,2,3,1,3,2,6,1,14,4,19,3,12,2,11,2,5,2,3,6,2,5,3,3,4,6,3,4,3,5,2,23,2,2,12,13,2,3,3,5,0,3,3,2,11,3,19,2,3,1,2,4,7,10,13,3,2,2,3,6,1,10,3,1,0,3,1,3,2,4,4,3,5,2,3,1,3,2,3,6,3,1,0,5,7,5,3,9,2,7,1,12,3,14,0,7,4,20,2,3,8,2,2,15,19,1,32,5,5,6,2,3,18,3,4,6,5,1,13,2,2,11,2,3,7,6,3,3,2,2,8,6,1,3,7,1,29,2,3,11,5,13,6,2,3,3,3,3,3,3,8,1,2,2,2,11,3,1,2,5,1,2,5,0,6,14,4,3,7,6,5,16,6,2,12,3,5,2,1,2,6,9,2,6,6,3,4,0,2,4,8,5,6,4,13,3,15,2,10,3,6,1,2,2,5,1,3,3,2,5,3,23,17,2,3,23,3,8,3,6,12,7,2,2,5,6,7,5,5,3,2,3,3,11,3,37,2,6,12,29,6,4,11,3,3,7,1,7,7,3,20,3,4,16,2,4,6,3,1,6,2,2,3,5,17,3,5,2,13,2,3,1,5,1,7,13,3,16,6,1,6,11,7,2,13,2,6,10,3,13,3,4,0,3,3,2,3,6,0,3,1,5,11,4,1,3,1,4,6,2,6,3,3,2,2,3,1,2,6,7,5,5,6,3,5,4,2,2,2,3,3,0,5,2,6,2,7,0,13,4,16,2,4,3,5,5,5,6,4,4,3,6,0,3,6,2,6,4,5,6,2,2,5,7,10,3,4,10,2,3,7,3,12,9,3,6,1,2,2,8,10,2,3,7,1,3,6,3,3,3,3,2,2,2,0,3,10,6,7,2,5,2,3,7,5,1,7,2,5,17,2,6,6,2,3,12,2,2,12,5,13,6,3,1,4,5,2,5,7,1,2,2,2,8,2,2,0,2,3,7,14,7,7,7,1,10,2,2,3,3,3,2,2,2,4,13,3,2,2,4,7,2,2,8,3,3,0,23,1,20,2,5,2,11,2,3,2,3,6,2,2,8,2,2,7,3,3,0,7,5,4,17,3,8,19,1,18,6,4,0,2,3,8,2,4,7,2,3,3,2,3,7,2,3,6,3,1,2,5,3,9,6,3,7,5,1,1,2,5,2,6,2,10,2,4,6,7,1,0,2,3,7,3,1,5,5,5,18,3,5,1,2,2,6,6,4,2,11,4,3,2,4,3,2,4,1,2,3,4,7,2,4,2,4,10,11,4,6,2,2,2,5,1,6,3,4,1,3,1,5,2,3,20,6,9,0,3,1,0,13,2,14,3,9,5,3,1,1,5,9,3,2,2,12,11,8,6,6,3,6,2,4,20,19,2,22,2,6,7,2,2,2,13,2,8,2,3,12,3,1,2,3,8,4,13,2,3,2,3,9,3,4,4,5,1,2,2,6,12,2,2,8,13,4,0,2,5,4,11,4,30,5,2,2,3,3,4,7,2,6,2,2,9,2,2,6,5,1,3,2,3,2,7,5,3,5,9,14,3,3,3,2,4,0,11,4,12,3,1,2,13,5,24,2,2,3,3,1,2,3,1,7,19,2,10,2,7,0,11,4,0,2,4,8,3,13,0,2,2,8,3,1,9,7,4,6,6,7,7,3,4,8,2,3,3,6,1,4,2,4,11,2,3,7,2,2,7,11,5,3,10,2,8,2,2,3,12,4,3,3,5,4,3,3,4,2,4,6,3,3,6,2,4,6,5,1,5,3,3,3,7,2,2,6,2,19,2,2,8,10,5,16,2,3,2,2,3,8,3,3,4,5,1,3,6,2,2,2,6,3,13,7,22,2,5,3,3,14,9,5,2,1,6,2,0,2,3,2,29,6,3,5,1,10,3,1,0,2,4,3,2,2,6,5,3,3,3,4,11,2,4,8,5,2,3,3,11,2,2,6,3,3,4,2,5,2,15,2,4,19,11,2,4,3,4,2,6,2,2,3,1,7,7,7,5,5,3,3,6,1,5,3,13,4,3,4,0,2,2,2,2,3,7,3,3,2,5,6,3,2,3,7,2,4,6,11,6,20,2,9,12,5,1,6,2,3,12,3,1,3,3,1,3,5,1,12,3,1,2,2,4,2,2,3,2,11,8,6,7,2,0,5,2,3,3,3,2,2,3,9,5,3,3,2,3,6,3,3,3,2,2,8,5,5,5,5,3,8,2,4,10,3,3,0,7,8,2,2,3,8,2,4,10,2,3,1,5,7,3,7,2,0,3,11,0,10,5,14,3,4,0,11,1,7,3,1,6,3,4,0,2,2,8,5,1,3,3,4,0,7,3,14,2,10,3,3,1,8,7,3,0,2,2,17,2,2,6,3,4,2,11,2,20,2,2,1,2,2,6,3,5,11,2,6,6,5,3,4,12,1,2,2,3,2,7,1,4,2,5,8,3,6,4,2,3,9,2,10,0,19,7,50,2,7,7,10,3,5,3,6,10,2,4,7,2,4,8,13,1,0,2,2,7,2,2,2,7,2,3,11,4,6,2,6,8,2,3,6,2,3,13,3,7,23,2,3,1,6,1,8,11,1,6,5,2,6,2,5,4,14,2,4,5,3,0,2,3,4,2,3,7,3,1,2,2,2,8,5,2,4,6,7,3,2,2,3,3,1,1,5,9,2,2,3,7,5,6,19,2,2,4,13,1,14,3,4,6,2,2,3,2,2,3,3,3,5,5,2,4,5,3,7,3,3,2,2,2,7,11,3,20,2,11,7,15,4,2,2,2,8,3,5,2,5,3,6,2,3,10,2,2,12,7,8,2,7,11,0,2,3,8,2,5,6,3,1,0,5,6,4,14,2,10,2,6,3,10,6,21,2,3,7,2,3,7,3,4,0,3,3,5,6,3,8,2,2,8,3,8,3,5,3,3,5,3,3,2,2,1,23,4,11,7,4,5,2,2,4,7,11,22,2,2,6,11,5,5,11,6,24,6,3,0,2,6,2,5,2,5,6,6,2,3,1,2,2,4,3,13,10,2,3,3,2,7,8,12,5,2,11,17,15,30,3,3,0,3,7,3,7,2,4,2,6,8,2,2,3,3,6,3,7,4,4,2,3,7,6,1,3,3,3,2,5,3,9,2,2,2,3,5,9,7,2,12,2,3,2,6,2,8,2,3,3,6,2,3,2,6,17,19,1,16,2,8,1,5,3,24,5,1,6,2,8,6,6,6,2,2,2,8,2,4,27,3,3,6,2,5,0,5,5,20,2,3,15,7,9,2,5,5,10,2,2,1,3,1,6,2,4,4,3,1,5,6,1,4,2,12,0,5,8,7,2,3,1,5,3,3,11,3,22,10,3,9,13,1,8,2,3,7,3,5,7,3,1,0,14,2,10,3,3,5,5,2,7,2,3,6,3,1,7,2,2,1,2,4,3,11,1,5,2,4,2,3,1,10,3,1,6,2,2,6,3,3,15,6,2,7,6,7,6,2,2,2,2,2,0,2,2,6,2,5,1,6,2,2,2,2,7,3,1,2,2,5,7,13,1,3,2,2,8,3,6,1,12,1,2,2,2,15,2,6,6,3,5,7,5,7,3,2,4,4,7,2,9,21,2,3,3,3,7,7,2,10,3,1,5,2,3,7,3,4,4,6,2,5,3,8,1,2,2,6,2,7,0,2,7,7,7,4,4,2,3,6,2,2,7,5,3,3,7,4,0,3,3,6,5,2,9,6,1,7,3,4,2,2,3,9,5,3,6,2,11,2,7,5,6,5,3,6,2,3,4,2,3,7,2,6,6,7,5,10,11,1,24,2,4,12,5,1,1,3,4,15,5,1,11,3,1,6,3,1,0,5,1,3,2,7,12,2,3,1,3,3,5,5,2,3,11,1,8,3,1,6,5,1,6,2,3,9,2,2,21,3,4,7,3,4,3,31,1,32,3,1,5,2,5,8,6,6,10,7,2,6,6,1,2,5,10,3,3,5,18,3,5,3,3,7,0,5,3,10,2,3,7,2,3,8,2,2,6,3,1,2,2,6,2,17,2,3,3,1,3,3,5,4,5,3,6,2,2,1,5,1,6,5,1,6,2,4,3,2,2,3,3,3,6,2,6,3,2,3,12,5,2,9,3,3,2,2,6,8,5,2,6,6,9,6,5,2,6,3,5,4,2,2,17,6,4,9,6,7,5,2,3,8,2,2,10,5,3,8,5,1,5,2,5,4,3,8,2,5,3,3,5,1,3,11,3,16,6,1,3,2,3,12,3,6,6,2,2,10,3,3,25,7,1,0,3,3,5,5,1,11,2,10,3,3,1,22,2,2,1,2,5,2,2,2,8,11,1,6,5,1,14,5,2,6,2,6,8,3,4,0,7,1,2,3,4,5,5,1,3,2,6,8,2,2,6,6,2,2,2,6,6,7,5,24,2,2,2,10,2,0,5,1,6,3,4,4,3,3,2,14,4,14,17,4,3,2,2,8,5,2,3,2,3,1,2,2,7,19,3,20,10,3,14,11,2,2,2,7,6,2,2,4,7,3,6,5,1,10,5,3,17,2,2,2,2,6,6,3,3,16,13,6,19,6,3,10,3,1,1,6,3,10,11,3,12,2,3,7,17,1,3,2,5,1,2,3,8,3,1,16,2,6,12,13,5,3,3,1,6,6,7,7,3,7,0,2,2,3,3,3,4,5,1,15,11,2,3,2,4,7,7,2,4,2,5,1,3,4,3,5,1,8,2,3,5,2,3,4,7,2,12,6,2,6,2,7,2,14,2,1,3,12,1,11,4,20,2,5,1,2,3,0,5,6,10,5,1,19,2,3,6,2,5,7,7,3,4,7,1,6,3,1,6,13,2,7,5,2,3,3,3,2,2,12,2,11,2,4,2,3,6,2,4,0,2,4,9,5,7,14,2,6,10,2,6,12,2,3,6,2,6,8,5,1,2,2,2,10,5,1,10,6,1,3,6,2,15,2,3,9,14,1,9,3,5,6,2,2,9,2,2,8,5,1,1,11,3,24,2,4,14,2,3,6,3,1,3,2,2,2,5,2,2,3,7,0,3,7,5,2,3,7,3,10,7,2,4,6,2,3,3,2,3,6,13,6,3,5,3,12,2,2,1,5,1,6,3,6,1,3,1,2,3,3,0,3,1,3,5,10,6,3,3,7,5,1,8,2,2,2,10,5,6,2,3,11,3,8,8,3,3,0,5,21,20,2,4,3,2,6,6,2,2,12,2,4,9,2,4,10,5,2,2,2,3,7,7,4,15,3,4,4,3,1,3,2,4,7,13,1,11,19,2,8,3,17,2,5,1,10,2,4,12,2,2,7,5,5,7,2,3,21,7,1,2,3,3,7,7,1,6,3,11,5,7,9,6,3,13,6,2,4,2,3,1,0,5,5,3,2,3,8,6,3,3,2,4,3,10,2,14,2,3,1,11,3,30,3,3,6,2,6,8,5,6,5,2,5,0,3,8,6,2,5,8,7,1,18,10,7,9,5,5,6,3,3,3,2,3,8,5,1,10,2,2,8,3,3,6,11,7,2,2,2,3,5,7,9,2,2,3,2,8,0,6,1,2,2,5,8,3,1,3,5,2,2,2,8,8,3,7,9,7,3,2,7,2,2,3,1,0,3,1,4,5,3,6,7,1,0,2,6,8,10,6,0,3,4,7,5,5,10,3,1,7,11,1,6,2,3,2,2,2,12,3,3,2,5,1,5,3,1,2,7,2,16,11,3,0,2,2,2,7,3,0,2,2,7,5,1,14,2,2,6,6,9,10,13,10,20,2,2,6,7,1,11,2,3,2,2,4,8,7,3,5,7,4,26,3,1,3,2,4,8,3,5,4,13,1,32,2,3,8,3,1,7,5,1,5,2,2,2,3,1,3,11,3,12,3,4,3,2,3,6,3,1,2,2,6,8,2,5,7,3,1,5,2,2,7,6,2,4,3,3,4,2,7,3,6,6,6,3,1,0,2,8,2,3,3,5,2,8,2,3,1,3,2,5,0,3,5,26,7,1,11,5,2,3,3,5,6,5,1,7,3,1,3,5,8,3,7,1,0,2,7,1,3,7,2,3,1,8,5,5,15,2,3,3,3,1,1,2,6,8,2,4,6,3,1,7,2,3,7,22,1,5,2,3,7,2,2,2,3,5,1,7,1,17,3,1,6,2,4,9,6,2,0,2,2,2,5,8,3,2,4,8,2,2,4,22,1,3,11,11,10,10,2,14,2,2,6,2,3,7,3,4,4,3,5,5,10,4,8,13,6,4,3,1,9,5,7,2,3,8,0,2,2,3,2,2,6,5,2,20,3,5,6,3,4,3,2,2,4,5,1,3,13,2,4,11,3,24,6,3,0,5,2,22,5,2,2,13,6,2,5,3,4,2,6,8,7,2,4,7,1,21,6,3,5,3,7,2,2,3,18,3,6,11,2,5,6,5,3,4,6,6,4,2,6,10,2,3,7,2,6,6,2,2,2,5,3,16,2,3,12,2,2,8,3,6,5,2,2,10,7,4,4,3,4,3,5,5,5,2,3,9,26,2,4,2,4,7,10,4,2,7,2,4,17,4,20,2,6,10,2,2,8,6,3,5,6,2,12,6,1,0,5,2,5,2,7,1,3,1,0,5,13,6,7,5,0,3,12,5,2,6,3,5,1,8,13,1,12,5,12,10,17,3,2,2,10,12,3,3,0,7,2,8,7,7,11,7,7,0,3,14,3,2,16,12,5,1,2,7,4,0,2,3,7,19,1,0,17,10,3,2,2,6,3,3,2,2,3,13,3,4,14,6,1,5,5,1,5,2,3,1,11,4,7,3,12,7,3,3,5,5,1,8,2,2,12,2,2,3,3,4,7,3,3,2,5,1,9,3,3,2,3,10,4,3,8,5,5,2,3,2,5,2,2,3,2,7,1,4,5,1,14,7,17,13,2,11,10,3,1,2,5,3,15,6,1,5,2,9,4,6,1,2,2,3,4,3,5,3,2,2,9,2,6,8,2,3,7,3,1,3,2,2,6,5,2,9,2,3,10,3,1,4,13,4,0,3,3,6,5,2,2,5,5,6,3,4,7,2,3,9,2,2,2,19,2,2,2,2,8,5,2,12,7,1,16,19,3,20,3,4,6,3,5,1,2,2,8,2,2,7,3,1,2,2,4,8,7,2,2,2,3,8,2,3,3,3,1,4,11,3,14,2,2,8,3,1,3,2,3,1,2,7,6,3,3,6,2,3,2,6,1,7,5,3,15,2,2,2,2,2,10,7,4,2,2,11,8,6,7,3,2,6,8,15,2,6,5,1,3,3,1,2,2,4,2,2,2,11,3,3,9,11,5,3,3,1,4,5,2,7,2,6,12,2,2,4,2,2,0,5,2,6,2,2,4,5,1,6,2,2,7,2,4,1,2,6,9,11,4,3,2,5,8,2,6,7,2,5,2,3,3,3,2,4,6,2,6,8,5,13,3,2,3,19,13,5,3,5,1,5,11,1,7,2,2,8,3,1,4,5,2,1,2,7,3,3,10,5,6,1,11,6,1,7,3,6,2,5,12,3,3,1,3,2,5,8,22,4,12,14,6,6,10,2,10,3,7,3,2,2,8,7,1,4,3,4,6,11,6,0,2,6,9,3,5,6,2,4,9,2,2,2,2,3,4,3,4,3,13,3,3,3,11,3,3,8,14,2,6,7,11,3,16,3,4,5,2,5,9,2,2,7,3,1,0,2,4,6,3,3,4,5,2,23,2,5,4,3,1,6,2,2,2,3,8,5,2,2,2,10,3,4,2,6,9,2,2,6,2,2,11,3,4,0,2,2,8,5,1,6,2,2,4,3,3,1,3,1,8,2,4,10,13,4,2,7,1,2,3,10,7,5,7,3,7,1,0,2,5,7,13,2,4,2,3,7,2,5,7,6,2,2,5,2,2,3,1,25,7,7,10,3,15,2,5,2,2,2,2,3,2,2,0,3,4,3,2,2,2,6,12,4,2,3,16,2,5,8,13,4,5,13,1,22,2,2,0,5,1,5,2,2,7,2,6,12,2,5,20,2,7,2,5,1,15,2,2,2,2,5,2,3,3,6,2,11,2,3,6,6,5,5,7,17,3,20,2,2,6,10,2,7,2,2,2,13,1,9,3,4,6,7,1,4,3,7,4,7,1,0,5,2,3,2,7,3,6,3,3,11,2,3,2,10,3,2,3,7,2,9,3,3,5,4,7,1,2,17,1,12,2,2,6,7,2,11,6,1,5,5,2,6,2,2,4,2,5,2,10,4,2,2,3,7,3,10,6,11,6,3,7,3,16,2,6,3,3,1,0,5,10,6,3,1,3,6,1,3,5,9,17,2,2,3,2,9,0,2,5,12,2,3,1,5,2,3,2,3,7,13,7,2,3,9,2,21,2,6,10,5,21,3,6,6,2,5,33,3,3,0,11,4,8,5,1,6,3,4,7,2,6,12,3,4,4,7,2,2,2,2,6,5,1,7,2,3,1,2,5,8,2,6,6,3,5,5,11,3,12,2,2,6,3,5,3,3,1,3,3,4,2,2,3,7,2,4,8,5,8,6,3,3,15,2,2,2,2,9,3,2,3,14,5,6,11,2,2,6,3,3,3,5,7,14,5,2,7,11,11,4,3,6,0,2,3,7,2,5,3,2,3,16,6,2,4,3,6,6,2,5,2,2,5,10,13,1,14,2,3,7,5,2,10,2,3,7,7,7,0,5,6,14,3,6,4,3,3,2,2,2,3,2,10,8,7,1,30,2,5,6,11,1,3,2,3,6,3,1,0,10,2,16,3,7,5,2,3,4,3,3,0,3,5,6,5,2,6,2,4,7,3,1,12,2,4,6,2,2,13,3,4,5,5,1,6,2,2,10,7,13,5,7,12,21,2,3,8,2,6,12,2,6,6,2,3,1,3,3,3,3,5,2,2,3,12,17,2,7,2,5,12,15,1,20,2,2,7,10,2,5,2,4,6,3,3,2,5,3,2,2,2,4,2,2,8,10,2,6,7,1,0,11,2,5,3,4,2,2,6,7,11,6,5,13,2,18,2,7,7,3,4,4,3,6,11,2,3,2,2,6,8,7,9,12,10,2,15,3,1,2,7,2,12,2,3,3,3,6,4,13,3,7,5,5,6,10,2,6,5,3,5,6,3,3,6,7,7,5,1,11,23,9,27,2,3,3,2,2,8,2,4,2,7,1,2,2,4,5,2,2,13,7,10,4,7,2,0,6,8,4,5,2,6,3,5,0,2,9,12,2,5,4,2,4,10,31,1,4,5,2,10,2,3,9,2,7,0,6,1,0,6,1,14,7,1,0,7,4,7,7,9,12,2,3,1,2,5,6,3,1,4,3,1,2,2,2,2,6,1,2,5,2,3,5,1,7,3,8,2,5,2,7,3,4,2,2,2,4,3,1,4,5,2,6,3,4,6,2,2,2,3,1,5,2,4,10,11,2,11,3,3,5,5,7,3,7,1,24,6,2,6,11,1,3,6,1,5,10,5,8,3,3,3,11,2,2,3,9,0,5,1,3,14,2,10,2,9,7,11,4,17,2,2,4,2,6,7,2,9,4,2,4,12,2,4,10,2,3,9,6,4,22,7,1,5,2,2,0,3,6,4,2,3,14,2,4,12,10,2,3,3,1,1,2,6,1,5,2,2,2,3,6,2,6,6,2,4,8,13,5,12,2,3,7,2,3,7,3,1,3,2,11,2,6,2,1,7,4,5,5,1,7,5,6,3,2,3,4,6,1,2,2,2,2,2,3,1,5,1,20,2,4,6,3,14,2,15,1,20,2,3,1,3,6,9,12,5,7,5,5,7,2,4,1,6,7,0,2,6,10,5,3,3,2,4,6,15,3,16,3,1,3,2,8,0,6,2,4,2,6,6,5,3,15,2,3,1,7,5,0,2,2,1,5,1,6,5,2,9,3,3,2,3,3,7,2,4,2,2,5,8,6,2,3,2,2,10,7,4,21,3,5,3,2,2,12,2,3,7,2,6,17,3,5,11,6,1,0,2,2,7,7,1,0,2,14,5,6,3,0,2,4,8,2,4,9,3,3,3,3,6,6,3,7,3,3,5,13,3,3,5,2,2,6,5,2,6,2,2,4,3,8,1,5,1,6,2,2,2,3,11,4,2,5,3,2,2,7,3,6,3,7,2,3,2,2,11,2,6,9,3,3,4,5,2,0,13,4,2,5,3,10,6,2,8,2,2,11,6,9,10,3,1,2,2,2,16,3,1,2,2,6,9,2,2,3,2,2,0,2,5,3,12,4,9,3,8,0,11,1,7,3,4,3,2,2,2,3,1,1,7,4,5,5,2,6,5,2,7,2,3,3,2,4,6,29,3,20,2,2,4,11,4,0,5,3,6,2,7,8,3,1,3,2,9,4,3,3,0,7,1,4,2,3,7,3,3,2,3,9,2,2,3,6,6,1,7,7,2,2,3,3,6,2,4,4,2,6,2,10,4,2,5,3,10,5,2,2,29,1,24,2,6,12,11,11,2,2,10,3,3,18,0,3,1,5,3,6,12,2,3,7,2,4,6,3,1,0,7,3,5,5,3,6,6,1,4,3,8,5,7,11,0,2,4,13,2,6,10,10,5,12,3,7,3,2,2,10,17,1,2,6,1,4,2,5,8,5,8,5,6,4,10,7,1,0,2,3,6,2,4,7,2,3,14,3,8,0,5,1,10,2,7,2,6,1,9,2,6,3,11,4,3,29,1,12,5,5,3,3,1,11,2,5,2,5,3,4,2,3,0,2,6,6,3,1,4,5,5,5,3,1,3,5,3,3,3,1,2,11,3,24,2,6,2,2,2,12,6,1,3,2,2,6,5,5,4,11,3,5,2,2,4,7,2,11,3,6,14,3,12,7,15,3,0,2,12,8,2,8,7,2,3,6,3,1,4,5,7,5,15,1,4,13,5,28,2,2,4,11,13,3,2,5,23,2,6,3,5,2,6,2,3,3,13,15,14,3,1,5,2,2,3,2,4,0,7,1,4,7,3,12,3,4,3,5,7,25,2,3,1,2,4,8,5,7,2,11,3,18,2,4,6,3,1,2,2,3,12,3,4,7,2,6,8,3,1,2,2,16,7,2,6,10,3,1,12,6,3,4,2,20,4,2,2,7,2,6,3,2,5,2,5,3,18,2,9,7,5,2,6,3,17,2,17,1,2,3,3,0,19,1,19,5,3,2,3,1,6,3,1,3,3,3,7,5,3,4,7,2,18,6,2,11,2,2,13,2,2,23,2,4,3,11,11,3,3,3,0,10,7,7,6,1,3,2,6,8,5,1,4,2,3,7,7,4,12,7,1,4,11,2,8,3,4,3,5,11,6,6,1,3,2,2,6,5,1,4,2,7,6,3,5,2,2,4,8,10,6,4,2,2,1,7,3,3,3,7,7,2,2,8,2,2,7,3,3,0,7,4,5,5,11,5,6,1,8,5,6,5,3,1,8,13,6,14,6,1,1,2,2,8,2,13,11,6,2,4,2,3,8,2,3,3,3,10,3,2,2,3,3,4,0,2,4,8,7,2,6,7,7,0,7,3,2,2,2,3,2,4,0,5,7,11,3,1,0,19,1,2,2,2,10,2,3,1,3,1,0,2,2,2,2,6,6,5,2,3,2,3,11,2,3,7,2,6,12,10,2,2,2,3,1,3,4,4,2,2,11,11,11,10,2,2,7,2,5,8,13,2,6,2,2,4,3,4,4,2,2,7,2,2,6,3,10,7,11,2,3,2,4,1,3,5,0,6,4,2,2,2,11,3,6,7,7,5,12,2,3,7,29,7,2,23,1,32,2,2,8,11,3,3,5,1,6,3,8,5,5,1,4,2,3,4,5,5,8,2,2,7,3,3,14,3,1,7,13,7,14,6,2,9,2,4,8,5,3,5,6,1,6,5,1,5,13,5,6,6,1,6,7,4,6,2,2,2,2,4,7,7,1,14,3,5,5,6,1,4,2,4,6,3,7,4,5,3,3,11,4,18,2,2,4,17,1,3,5,2,10,2,3,9,2,3,7,11,12,32,3,6,7,2,2,20,3,3,2,2,4,6,2,5,0,3,8,6,11,2,4,6,6,0,2,2,9,3,1,4,14,12,2,13,1,14,11,1,3,2,3,7,6,1,3,2,2,8,3,3,3,10,2,3,7,8,16,3,1,10,2,4,10,12,4,4,2,5,8,2,3,6,11,2,3,2,5,2,3,1,0,10,10,6,3,1,5,3,11,4,13,1,3,3,3,6,2,3,8,2,6,3,3,1,0,2,5,6,2,2,10,5,1,0,5,1,15,2,2,1,5,1,14,2,7,4,2,6,3,2,2,3,3,4,1,3,8,3,3,3,1,3,7,5,7,3,4,3,8,0,19,4,11,2,5,10,19,1,22,2,3,7,5,11,8,2,2,7,2,4,3,2,3,6,2,2,7,2,4,7,5,1,18,6,1,1,2,2,6,13,3,2,3,3,2,2,6,6,5,1,4,3,6,12,5,1,6,7,19,4,5,2,6,2,3,7,2,6,9,3,1,7,7,8,5,2,6,6,3,4,6,2,6,18,5,5,3,7,4,0,10,3,3,7,1,2,6,2,3,2,3,14,2,5,2,7,1,0,2,2,0,19,3,9,3,3,5,2,3,3,5,6,1,3,1,2,2,3,12,13,1,4,2,4,12,2,2,11,2,6,8,5,2,6,2,2,6,3,12,7,37,8,12,2,5,2,2,3,1,6,1,4,5,2,4,2,2,8,2,6,3,2,4,8,17,1,7,15,2,13,3,3,2,2,5,9,3,5,9,3,4,5,3,5,7,15,5,3,2,4,9,5,1,3,2,9,4,2,2,6,5,21,6,3,3,3,2,2,11,3,11,4,2,4,2,3,3,10,2,8,0,2,2,3,3,7,6,2,4,6,2,5,8,2,10,5,2,4,3,6,4,18,3,1,2,6,1,15,5,3,2,2,7,3,3,1,5,3,7,11,2,2,6,3,4,3,2,2,7,3,1,3,3,1,2,2,4,3,2,6,7,7,1,18,7,12,0,3,1,1,5,7,4,2,4,7,2,3,7,5,5,6,2,5,5,2,4,4,7,1,4,3,1,0,23,5,18,3,6,1,3,1,5,6,1,6,3,5,0,3,1,2,7,1,14,2,3,4,2,2,4,3,3,2,6,4,18,17,2,0,3,5,6,5,1,3,2,5,2,19,4,52,2,4,2,2,2,10,17,2,3,11,4,6,2,3,7,3,3,13,13,1,2,2,3,2,2,2,12,11,3,8,3,3,5,2,2,3,5,10,3,2,6,2,2,9,3,6,2,10,5,1,14,2,2,7,5,1,12,2,3,8,3,4,7,5,2,6,3,6,2,6,2,5,2,2,3,3,3,0,5,1,3,3,1,5,2,2,8,3,4,10,11,5,2,6,2,4,2,5,10,3,3,3,5,1,3,2,4,17,2,6,3,7,5,8,7,3,0,3,3,1,5,1,16,2,8,7,3,3,3,2,5,3,2,6,8,5,1,6,5,1,9,7,4,2,10,5,16,2,3,7,2,2,8,7,2,4,3,1,10,5,2,3,2,4,2,3,4,3,7,2,17,3,1,4,6,4,7,3,3,0,3,3,5,3,5,7,5,3,6,2,3,6,2,8,6,3,3,2,2,3,7,13,3,10,2,2,7,13,3,2,2,3,4,3,12,1,14,1,20,7,2,4,2,2,7,5,10,10,2,2,7,3,1,4,5,1,5,13,1,14,2,4,11,11,1,3,10,3,5,5,2,10,3,6,1,6,2,2,5,5,4,13,3,8,2,4,12,2,2,8,13,1,7,2,2,0,5,6,3,2,4,10,3,7,0,5,6,6,14,1,15,5,3,15,2,2,4,3,6,7,3,3,5,2,4,3,29,5,2,2,9,4,2,2,3,2,2,15,6,2,3,5,3,3,2,7,2,2,3,6,2,6,8,7,1,5,5,5,6,2,3,11,3,3,2,5,3,6,2,10,4,2,2,6,5,1,15,5,1,4,6,10,4,5,1,6,2,7,6,5,2,18,6,1,2,3,1,2,14,2,0,2,2,2,3,10,4,2,4,10,5,1,5,5,8,11,6,2,7,2,6,8,2,3,4,5,1,6,3,6,6,2,6,8,5,2,6,3,3,9,2,2,3,5,1,5,3,1,7,2,4,10,5,5,3,3,3,3,3,4,0,5,1,6,5,2,17,2,3,2,3,1,4,11,1,2,5,1,3,7,10,6,6,1,8,3,1,8,2,2,8,6,2,6,11,1,2,17,7,15,3,4,0,7,4,14,2,2,8,2,5,6,3,1,4,7,1,2,7,2,0,2,3,8,2,3,9,7,1,15,10,3,0,2,2,6,2,5,7,2,2,6,3,13,8,11,2,6,3,9,3,2,4,4,22,3,0,5,1,9,2,5,12,7,1,14,2,3,8,3,3,3,2,2,13,2,6,6,2,2,12,2,6,2,5,1,4,3,1,10,3,5,2,3,1,0,2,4,3,7,5,8,2,3,10,3,1,3,2,3,8,3,3,5,2,6,7,5,5,2,3,6,6,2,3,7,3,5,4,7,5,2,6,2,3,5,1,2,6,2,7,7,1,4,3,3,2,2,6,12,2,3,3,3,8,2,13,3,14,2,3,13,11,6,7,3,1,3,2,4,3,2,3,8,6,1,11,7,1,2,31,8,12,5,1,16,3,5,19,5,2,10,2,2,0,2,2,9,3,3,2,7,3,14,2,4,12,3,3,2,5,1,18,3,4,3,2,2,8,3,3,6,5,6,11,2,3,1,11,3,12,2,3,6,19,5,13,2,12,11,6,1,3,3,1,4,3,4,6,2,5,6,3,6,3,3,1,3,2,2,2,5,7,6,7,1,0,11,4,3,5,2,20,2,7,4,3,4,4,10,5,18,2,6,12,3,5,7,6,3,0,3,3,3,6,3,6,3,3,2,2,2,6,2,3,3,2,3,8,3,3,0,5,1,11,3,4,3,5,2,7,3,1,1,2,6,13,3,1,3,2,4,8,14,5,10,5,1,6,2,5,2,3,6,2,2,4,8,5,1,7,2,3,3,2,2,3,2,5,7,6,3,11,3,3,0,2,2,8,3,1,3,7,3,5,3,4,11,5,3,14,13,6,5,2,5,9,22,5,25,2,4,19,2,7,6,7,1,3,2,7,12,3,1,2,2,2,3,2,2,6,2,11,3,14,5,3,3,1,4,2,9,0,10,2,8,2,2,13,13,1,10,2,2,6,3,3,2,5,5,3,2,7,3,3,7,2,5,3,8,11,2,20,2,3,9,2,6,8,6,3,3,2,2,2,5,1,24,3,1,3,3,1,5,2,10,15,2,4,2,2,3,1,3,3,7,2,3,6,5,10,6,2,6,2,5,11,6,5,7,2,11,1,7,5,2,10,2,3,2,3,4,2,2,4,6,3,14,6,5,2,16,2,2,8,10,5,2,2,2,0,3,1,3,2,6,8,22,6,0,3,3,1,3,5,3,5,17,2,2,7,0,3,12,4,3,6,5,2,12,6,2,4,7,2,6,22,7,1,7,5,3,12,2,3,16,5,7,8,5,1,2,2,6,15,17,4,16,2,4,6,2,3,1,2,6,7,7,1,2,2,3,7,3,5,3,2,2,11,6,4,2,7,1,18,2,3,2,6,2,8,2,6,8,2,2,2,14,4,0,3,9,3,13,1,5,2,3,8,3,1,6,7,2,4,22,3,0,3,1,1,5,2,10,3,4,3,2,12,4,5,9,14,2,2,4,2,4,4,3,6,4,2,6,2,5,1,10,3,3,1,2,3,2,13,1,31,3,1,3,2,4,0,3,11,6,2,3,1,3,7,7,5,3,3,6,4,3,3,5,7,5,3,6,7,2,3,19,2,10,2,3,7,3,3,4,3,4,2,21,3,18,2,3,6,2,3,7,3,3,0,15,5,9,3,5,5,13,6,2,3,5,5,2,2,6,3,1,8,5,1,14,3,3,4,5,5,5,2,2,12,5,3,2,5,6,14,2,2,4,6,3,2,3,5,0,2,3,7,6,2,5,11,4,7,6,1,8,3,4,7,2,5,2,5,8,3,5,5,2,6,2,7,7,9,5,5,2,12,2,3,7,3,3,0,2,4,4,2,4,6,2,4,1,2,2,7,11,3,12,2,2,0,10,4,1,13,1,8,15,3,12,2,3,17,3,1,4,2,4,2,5,5,12,2,2,4,7,3,5,3,3,4,11,13,0,2,2,7,2,2,6,2,3,2,3,4,14,2,7,3,3,3,7,5,6,10,2,6,3,7,1,2,5,1,3,2,2,8,6,3,1,2,2,6,2,4,8,5,1,2,14,4,20,10,2,0,2,2,3,2,3,8,3,4,2,11,5,22,2,3,1,3,8,4,5,1,2,3,1,7,5,7,2,2,3,7,2,2,8,2,9,4,2,3,12,2,3,6,3,3,7,2,6,8,7,2,14,2,2,12,2,3,8,3,4,0,2,2,7,11,3,14,7,2,15,2,2,4,2,3,7,3,20,4,5,3,29,3,7,3,5,1,2,6,2,11,19,9,6,3,5,3,3,9,6,7,7,10,6,1,2,5,3,14,3,4,7,5,1,10,5,1,15,2,2,8,2,2,7,2,5,3,11,7,5,23,1,12,2,2,14,10,2,5,5,1,4,2,3,4,6,8,2,2,2,16,3,5,3,5,1,10,3,3,5,3,6,25,11,2,16,3,1,3,3,1,6,2,8,0,5,1,6,2,2,4,2,3,8,2,3,6,3,18,4,2,2,8,3,12,6,2,2,4,5,1,1,5,1,3,2,6,6,2,3,3,11,4,4,3,4,3,5,1,14,2,6,0,23,1,14,3,4,5,5,9,10,2,2,7,2,2,10,13,1,5,2,3,7,3,1,6,3,8,4,11,1,3,13,1,14,2,3,7,17,1,2,2,3,7,13,1,0,2,2,2,3,3,2,2,2,4,11,1,10,2,3,7,3,3,0,6,8,7,5,5,8,2,2,9,2,8,9,2,3,12,3,1,3,2,2,3,3,8,18,2,6,8,11,2,2,2,6,9,5,7,2,14,5,15,2,2,6,2,2,11,5,2,29,3,3,2,2,5,6,2,3,6,2,4,11,6,2,4,13,1,6,5,2,22,3,1,2,7,3,10,3,4,3,5,2,10,2,3,4,3,1,6,2,4,3,6,2,11,3,1,4,31,10,12,2,2,3,3,1,5,3,4,7,3,1,2,3,1,1,2,6,6,5,9,2,6,1,3,6,2,0,12,5,0,11,1,16,2,2,3,2,2,20,17,2,4,2,5,4,11,8,11,2,3,3,2,8,3,6,1,6,11,1,33,2,6,6,2,2,8,3,6,3,5,6,4,13,5,5,6,9,7,7,5,2,6,2,2,2,4,8,3,6,7,2,5,8,11,1,3,2,3,7,2,2,8,2,3,2,6,2,0,5,1,0,5,1,3,2,2,12,3,1,7,5,7,10,3,1,2,2,8,2,2,5,10,3,1,1,7,1,6,7,5,0,2,6,9,19,3,2,2,2,6,2,4,2,2,2,6,3,4,3,2,2,10,3,4,4,13,1,8,2,2,9,2,2,8,13,5,8,5,8,6,2,2,6,2,3,7,13,9,2,2,2,7,2,2,9,3,1,1,5,13,8,2,2,0,3,3,7,2,3,2,3,7,2,5,6,12,2,3,1,5,6,9,3,5,1,19,1,53,5,3,3,2,10,2,3,3,1,2,6,8,5,5,7,2,3,13,2,4,3,7,3,3,3,12,8,2,2,6,3,1,0,6,3,1,5,7,10,3,1,7,2,3,3,2,4,19,11,3,12,2,8,4,6,2,10,5,2,5,10,6,11,2,3,8,7,1,12,5,3,10,5,2,3,2,2,12,5,12,7,7,11,0,2,4,1,5,1,23,3,4,3,2,3,8,3,9,2,3,3,3,2,2,2,3,3,16,2,6,9,2,3,7,2,2,6,2,7,16,2,2,2,7,1,3,7,4,14,12,1,5,2,2,4,3,4,25,2,5,7,3,11,4,6,10,1,2,4,8,11,1,5,2,5,4,3,7,1,5,1,3,3,11,3,5,6,3,3,3,2,14,4,12,2,2,3,2,6,8,2,2,3,3,1,4,3,5,2,5,1,6,2,2,1,6,6,3,11,1,12,3,3,0,2,2,0,3,1,2,2,5,4,3,6,5,7,1,12,3,4,7,13,1,18,2,3,7,3,1,27,5,1,3,2,4,8,2,4,9,10,3,14,5,3,6,3,3,6,3,1,4,2,10,13,2,5,9,7,4,6,2,6,12,12,3,2,11,1,15,2,5,1,2,2,11,5,5,10,2,3,12,7,5,6,10,6,6,2,5,3,3,5,0,3,4,2,2,6,7,5,6,6,5,2,5,2,4,6,5,7,6,2,3,1,3,1,2,2,3,4,5,5,11,7,3,17,5,1,11,10,2,3,2,4,3,5,9,3,2,3,26,6,6,5,2,2,10,3,9,8,7,3,7,2,2,8,2,5,7,2,3,9,2,6,3,2,6,8,3,5,8,3,1,3,2,2,7,5,6,2,2,3,19,2,2,6,2,4,8,10,4,11,2,9,3,10,11,9,2,5,2,5,7,12,3,4,3,2,3,12,3,8,4,2,8,2,17,7,3,3,1,2,2,2,2,2,4,12,2,5,3,7,3,4,5,5,6,3,3,3,2,3,1,2,9,13,2,4,12,3,8,2,3,1,0,2,5,17,3,6,3,7,2,5,3,4,4,3,4,7,7,1,5,7,2,18,3,5,4,6,2,5,3,1,0,3,1,3,2,5,10,29,3,20,2,3,7,2,2,1,11,2,6,5,6,5,2,5,6,7,9,2,3,1,6,2,9,6,2,2,4,6,2,1,3,5,1,6,3,9,5,3,10,6,3,3,2,4,4,15,1,4,5,1,2,17,3,8,11,2,14,3,1,4,2,3,8,5,1,9,2,2,2,5,2,11,2,6,8,11,1,3,2,3,6,3,1,0,2,2,8,3,1,5,2,2,0,3,1,11,2,6,5,2,3,3,3,4,3,2,7,5,6,7,22,2,5,8,2,2,1,3,3,2,11,4,0,11,1,5,2,2,3,5,1,3,5,6,15,2,2,4,7,3,12,29,2,16,2,2,3,3,4,7,2,6,2,5,6,3,2,3,6,7,2,13,3,1,3,2,2,20,3,1,0,5,1,23,6,1,4,2,3,8,2,2,0,17,2,22,2,2,0,5,2,4,6,7,2,2,3,6,10,5,0,6,2,0,7,2,4,5,1,5,6,2,27,3,1,1,5,1,4,2,5,1,6,4,4,2,4,8,13,1,3,5,1,10,2,3,7,2,5,9,2,3,8,2,5,9,3,3,8,3,1,7,2,6,8,12,6,0,3,1,0,2,15,6,2,5,2,5,1,18,3,4,4,2,2,16,3,3,0,17,3,20,3,3,5,2,2,3,5,1,3,2,2,2,17,6,14,2,2,12,11,8,3,3,4,2,6,4,7,3,1,4,10,2,13,7,8,2,13,3,3,3,1,9,2,6,7,3,11,4,2,2,3,2,6,7,11,2,3,10,4,10,2,2,3,5,2,23,3,1,11,3,1,4,3,3,2,3,3,2,7,3,1,5,2,6,5,5,3,7,4,16,2,2,0,2,2,1,2,2,2,7,2,8,2,6,3,29,2,18,7,2,2,3,1,3,5,2,6,2,3,6,2,3,2,2,5,13,7,5,5,2,2,4,3,5,0,7,1,12,2,3,14,3,3,4,5,5,12,2,11,0,17,1,20,5,3,6,6,3,4,7,1,6,2,6,11,7,3,4,13,8,8,6,3,5,5,2,1,3,8,3,6,3,9,2,6,2,7,1,12,2,3,7,2,9,4,7,2,8,3,1,6,2,2,8,6,2,2,3,12,4,2,3,7,7,1,4,5,1,6,10,3,10,3,3,3,3,3,7,2,7,3,5,7,3,5,2,10,5,1,2,17,1,28,2,3,6,2,7,16,3,3,2,5,5,5,3,7,4,7,9,2,17,2,17,5,1,8,2,3,7,3,3,0,3,4,5,5,3,8,2,7,9,2,2,8,2,5,7,2,5,0,2,6,7,10,10,3,3,4,17,2,7,12,2,4,3,5,3,3,5,6,6,7,2,2,2,7,6,15,2,0,2,3,4,3,4,6,6,1,4,2,6,6,3,1,4,2,5,12,3,4,2,5,3,7,2,11,7,6,1,7,2,5,8,3,6,6,3,3,0,5,1,16,2,5,4,5,2,2,3,4,5,3,5,9,2,4,1,2,7,8,3,6,6,2,4,8,34,2,34,2,2,7,2,2,8,3,4,2,5,8,6,2,3,3,6,3,3,13,2,4,19,6,32,2,3,9,13,2,13,10,5,8,2,3,18,2,3,8,5,1,6,2,4,7,11,2,12,5,9,11,2,5,7,2,6,9,3,3,4,2,4,17,2,3,4,2,7,12,3,1,4,2,4,2,5,1,16,3,12,1,13,2,4,7,3,24,3,5,6,2,3,7,5,3,2,2,3,12,2,2,6,2,3,6,3,3,9,5,1,10,2,3,0,2,2,8,2,6,12,11,1,6,2,2,2,5,6,8,13,1,10,11,1,2,5,2,11,3,1,0,2,4,10,5,1,15,2,4,6,3,1,13,10,5,8,3,5,0,5,3,8,11,1,3,3,1,0,2,3,7,2,2,2,3,5,7,10,5,11,10,2,16,2,3,7,6,4,7,11,7,9,5,2,11,3,1,3,2,3,6,3,4,5,5,5,10,3,13,6,3,1,4,2,3,8,2,2,6,17,2,14,3,4,0,7,1,10,5,1,3,2,3,1,2,5,3,3,4,5,2,3,7,3,13,5,2,2,13,6,8,11,13,1,10,3,4,14,6,1,5,5,1,8,12,1,3,2,6,7,2,2,4,17,1,3,2,7,7,2,2,8,7,1,3,23,2,23,3,1,10,3,1,1,7,3,6,5,7,3,5,2,9,7,11,2,5,1,18,3,5,13,2,5,8,3,3,5,5,3,4,6,4,10,2,2,3,2,2,6,2,3,3,2,6,6,5,5,3,2,3,8,2,4,12,17,4,3,3,1,4,2,4,10,3,1,4,2,2,8,2,10,10,3,11,9,7,1,2,3,4,6,5,1,16,13,3,7,2,6,8,11,2,8,3,7,10,3,1,3,3,3,1,3,3,5,2,3,2,3,3,2,6,2,2,7,7,0,2,3,3,2,2,12,3,1,4,2,2,2,5,1,6,3,1,3,2,4,4,2,4,3,3,5,9,5,2,8,6,2,3,2,3,4,7,1,15,5,2,6,5,2,10,3,3,0,3,1,10,2,5,1,5,5,2,2,8,0,3,4,3,2,4,9,14,6,2,7,1,5,5,5,11,3,3,3,2,2,16,3,5,3,2,3,2,11,1,3,2,2,8,3,1,2,2,5,6,2,7,4,3,1,7,5,10,12,11,1,3,3,5,12,2,2,6,2,4,10,7,7,12,3,3,2,3,7,2,19,7,9,2,2,2,3,5,1,2,9,4,2,2,3,2,3,8,2,2,7,11,2,20,23,1,13,2,3,12,3,1,0,2,2,8,2,5,6,3,3,4,7,3,0,3,4,2,2,2,2,5,18,2,2,3,7,2,5,3,11,4,4,10,3,14,6,3,5,2,2,6,3,3,2,3,3,3,5,3,1,14,1,10,5,2,32,2,8,3,12,3,3,2,2,7,5,11,6,2,6,3,23,1,13,17,1,18,3,3,4,5,1,5,2,5,8,5,1,3,5,6,3,3,1,2,2,3,8,5,3,11,2,3,8,10,6,9,37,1,32,5,2,3,5,2,2,2,4,3,2,2,7,2,4,3,2,2,32,7,2,3,2,4,17,3,6,7,3,3,2,2,3,7,3,3,16,7,1,12,17,6,17,3,8,5,5,1,3,6,3,3,6,3,6,3,1,4,2,3,2,11,1,7,2,3,8,10,5,6,2,3,1,3,4,2,7,7,2,3,3,8,2,6,10,15,7,3,5,7,19,7,1,6,2,10,0,7,1,10,6,3,3,2,3,7,10,5,0,3,12,1,13,3,7,7,3,26,2,3,1,5,3,6,19,1,26,3,5,5,3,1,7,2,3,4,10,4,0,2,3,7,2,2,12,7,1,2,11,8,5,3,1,0,2,8,4,7,2,0,2,18,2,2,3,7,11,1,3,10,3,10,3,1,2,3,1,2,2,5,6,2,13,2,2,2,6,3,4,7,7,8,10,17,12,20,2,5,12,2,6,2,2,5,1,7,3,17,2,3,16,2,6,3,17,3,20,5,2,3,3,1,0,5,2,3,2,4,8,5,6,10,2,2,11,5,3,6,3,6,3,3,1,2,13,5,23,17,7,14,5,5,9,6,3,0,13,5,0,2,4,6,2,2,3,2,4,8,3,8,7,7,9,6,2,2,9,3,1,11,17,1,18,6,2,0,5,1,20,13,5,34,2,4,2,2,2,2,11,4,5,3,4,4,2,5,10,3,3,1,7,8,0,10,3,15,7,1,3,2,9,1,3,17,0,2,3,4,3,9,2,3,1,10,7,3,0,3,1,4,2,3,3,2,6,4,5,2,2,11,2,12,3,1,2,13,5,2,3,8,4,2,2,14,3,1,2,2,2,7,3,5,4,2,3,3,23,6,3,3,3,2,5,14,9,2,3,9,3,6,5,2,2,1,3,3,2,5,1,3,5,1,0,2,2,7,3,11,4,2,6,10,6,1,5,11,1,0,3,1,3,2,2,14,3,1,3,3,5,4,3,4,6,11,2,4,5,3,6,3,4,3,5,2,11,3,3,10,5,1,3,2,3,9,2,4,9,3,1,6,2,3,7,5,1,10,3,1,3,6,3,4,2,3,6,2,2,3,5,1,3,31,3,24,2,2,3,2,5,7,5,1,18,2,3,12,3,3,7,2,3,2,6,7,7,14,2,19,2,3,2,18,1,0,2,3,4,2,4,9,3,4,0,23,1,7,5,8,6,3,1,2,2,3,8,7,4,5,7,1,2,11,1,24,2,4,8,2,2,0,2,6,14,5,2,4,7,1,17,3,5,6,5,2,10,2,8,9,7,2,0,5,2,3,2,2,8,2,6,8,2,6,3,3,1,2,2,3,6,3,5,2,3,4,3,2,2,2,3,7,4,2,4,4,3,1,6,19,5,0,13,4,4,5,10,6,2,3,11,3,6,7,10,8,0,5,2,6,3,4,4,6,9,0,3,1,7,11,4,2,2,2,3,3,6,0,3,6,0,2,3,3,2,9,9,2,2,6,6,2,3,12,1,6,17,2,3,2,2,6,3,1,16,5,9,3,6,3,2,2,8,3,2,7,3,7,4,5,3,8,0,5,3,15,2,5,9,31,1,24,3,8,3,2,4,2,3,4,4,2,5,1,2,2,7,5,5,6,5,1,3,2,2,4,7,3,4,3,4,3,2,2,4,3,4,3,11,4,14,2,5,1,5,1,6,2,4,6,11,2,22,2,3,2,2,3,7,3,8,3,3,1,4,13,9,14,5,5,6,2,6,8,6,3,3,2,6,8,5,2,8,2,2,12,10,2,12,5,1,6,2,3,8,2,4,8,5,2,3,5,5,3,2,5,2,11,2,10,3,4,6,2,2,7,2,2,8,2,2,11,7,1,16,5,10,2,6,10,4,5,9,1,3,1,4,2,2,1,7,7,17,2,10,4,2,2,8,2,6,8,2,2,0,2,3,8,3,3,0,2,2,12,2,6,9,3,1,4,3,1,5,7,10,4,5,6,23,3,4,4,2,7,4,2,2,6,3,1,4,3,1,2,2,2,7,5,1,14,10,8,0,5,2,3,22,2,22,3,4,7,5,1,4,3,7,12,6,2,3,5,3,7,2,6,13,5,2,6,7,1,0,2,2,6,5,3,6,11,1,20,3,1,5,6,3,7,5,1,5,2,2,2,2,2,8,2,6,7,3,3,2,2,4,8,3,11,1,6,3,15,2,3,4,2,4,12,3,9,4,2,2,7,2,8,5,3,4,3,2,5,3,2,4,8,7,1,2,14,5,1,3,1,3,5,2,6,3,4,8,7,11,24,6,2,7,6,2,4,2,6,2,10,5,12,2,4,3,3,3,7,13,1,2,5,1,3,2,4,9,5,10,1,5,1,5,5,2,3,2,3,13,10,2,13,7,1,0,5,1,2,2,5,6,3,1,11,2,4,2,2,4,4,2,2,2,11,2,8,6,2,0,11,1,0,3,4,0,2,7,6,6,2,8,3,1,7,2,2,8,7,1,16,7,13,3,2,2,3,6,2,11,6,2,2,2,4,2,13,2,4,38,1,20,3,10,1,2,2,1,5,2,6,6,1,6,11,6,5,3,3,2,2,9,4,2,9,4,2,6,2,2,3,12,2,6,8,13,1,0,2,2,7,2,4,7,7,1,4,5,5,16,3,6,6,2,5,12,3,3,3,2,2,13,3,1,4,11,5,12,2,3,2,3,1,2,3,5,2,2,6,9,3,13,7,2,7,1,2,8,4,2,5,3,3,1,12,7,19,5,3,5,6,2,4,10,3,1,0,2,2,8,5,3,8,2,2,7,5,14,6,2,6,8,14,1,10,7,4,3,3,1,0,5,1,12,2,3,3,11,4,2,21,4,8,3,4,3,6,1,0,2,2,6,2,3,1,5,1,5,2,6,8,2,3,12,2,2,2,3,3,2,7,3,4,7,5,0,2,6,9,3,6,0,5,1,5,2,3,6,2,2,4,7,4,15,5,8,16,2,3,8,2,6,2,6,4,0,3,4,3,2,4,2,3,1,3,13,2,3,5,1,3,7,3,0,2,3,6,3,3,3,3,3,2,3,1,4,2,3,7,2,6,7,10,6,0,6,3,6,2,13,0,3,3,2,3,4,0,5,1,23,3,1,5,3,4,6,13,6,14,3,1,9,3,13,6,2,2,3,5,3,5,2,2,1,2,4,2,5,2,32,2,3,7,6,8,3,3,10,3,3,6,4,3,4,2,2,4,3,13,2,11,3,3,3,2,3,15,5,1,3,5,1,3,11,1,33,19,15,4,2,5,5,3,3,4,26,1,0,2,6,8,3,1,0,2,6,8,5,1,3,3,3,2,3,4,0,5,3,4,2,2,6,7,1,2,5,6,10,2,6,6,10,10,12,2,3,7,3,3,17,2,4,3,2,2,8,5,5,9,5,2,8,17,1,26,3,6,14,6,4,7,2,4,8,2,2,7,7,1,12,3,3,0,2,2,8,2,8,6,5,6,8,2,4,8,3,1,3,3,13,7,3,3,4,14,1,12,2,6,9,13,1,2,2,2,1,2,4,6,3,8,3,6,2,2,3,6,1,13,1,13,5,1,1,11,12,6,7,1,3,2,2,3,5,3,10,2,3,6,3,1,7,7,1,13,2,3,7,19,5,3,2,7,7,2,6,6,5,9,3,2,4,0,2,6,8,2,4,7,2,4,2,7,4,5,5,2,15,2,2,10,2,4,3,3,7,3,11,3,20,2,7,3,2,4,2,2,2,12,3,7,6,2,6,8,5,1,7,6,2,2,3,1,0,2,4,8,2,2,8,2,6,8,3,6,5,2,5,15,5,15,4,2,3,3,2,6,6,2,4,14,2,4,10,5,13,10,2,3,7,6,8,3,5,5,6,5,2,11,5,1,2,7,1,0,2,2,1,6,3,11,13,2,4,2,2,2,3,1,9,7,5,16,2,2,6,3,10,0,13,2,28,2,3,7,3,3,6,3,1,3,3,5,0,5,2,6,2,2,6,3,1,4,7,10,7,3,4,5,2,2,1,3,5,11,6,2,3,3,11,4,6,1,19,2,6,8,26,2,8,5,2,6,2,3,8,3,3,2,10,7,3,11,4,3,3,6,6,5,1,10,2,6,8,3,4,2,2,11,8,2,2,12,2,2,1,2,3,8,5,3,5,5,6,5,5,6,7,3,5,6,6,3,3,2,3,7,2,6,8,7,2,5,2,2,4,3,1,0,7,7,14,3,1,4,2,3,8,5,3,2,10,3,2,2,3,8,12,3,5,13,2,0,3,4,3,7,1,2,10,5,0,6,4,0,2,2,8,6,1,8,3,1,1,7,2,4,5,3,2,2,3,15,3,1,1,2,3,1,6,1,3,15,3,0,2,2,2,11,2,5,6,4,12,3,1,0,11,2,24,3,3,0,2,5,8,7,2,4,7,1,0,2,7,4,11,11,3,5,2,10,2,3,7,2,4,6,5,6,14,2,3,7,17,2,7,13,1,14,10,3,11,2,2,3,5,1,3,6,2,4,13,13,6,7,3,17,6,2,4,2,2,12,6,1,7,2,6,19,2,5,2,3,6,0,2,2,2,2,4,5,19,1,5,5,2,15,2,2,6,11,14,2,6,2,10,2,2,3,2,5,7,6,1,3,5,3,3,2,3,6,2,6,6,2,2,3,2,3,4,11,1,2,2,3,13,2,5,9,11,1,2,3,5,4,5,6,15,2,9,3,2,4,7,2,2,12,3,5,7,13,15,0,3,1,11,5,2,6,3,6,6,5,3,7,2,3,7,7,8,4,3,5,14,3,1,4,2,4,8,2,2,6,5,6,18,2,5,7,10,5,6,15,4,7,5,2,3,2,3,1,5,1,1,2,5,2,3,1,14,2,2,1,7,1,20,3,1,7,2,4,3,3,4,14,2,5,3,7,2,4,3,3,4,5,1,7,2,2,3,5,2,5,11,1,10,2,3,2,2,2,6,5,1,6,3,5,6,2,3,8,3,3,5,3,1,11,7,10,0,2,4,6,14,7,7,13,1,6,2,3,7,6,3,2,3,1,4,5,1,6,2,2,7,5,1,8,7,2,2,3,4,5,3,9,4,2,6,8,3,3,4,2,2,10,5,1,8,2,3,9,2,6,8,11,1,7,10,7,6,15,3,32,10,2,2,3,1,1,2,4,2,2,4,6,3,1,7,5,1,2,6,6,7,2,4,7,7,7,10,3,16,4,2,3,7,2,4,6,2,2,1,3,1,5,5,13,10,2,3,12,12,5,3,2,12,2,2,16,2,3,13,5,2,7,1,3,1,2,3,5,5,2,7,2,5,1,5,2,7,8,10,2,5,3,1,3,2,6,7,17,2,30,5,1,11,5,3,16,14,1,2,3,7,3,3,10,1,19,7,22,11,4,6,2,4,5,3,4,7,2,8,12,7,3,3,6,7,4,3,4,1,2,2,7,2,2,3,3,6,2,2,3,3,2,4,0,3,1,4,2,4,6,3,3,4,5,9,11,2,2,4,3,5,6,6,1,7,3,4,6,2,3,8,3,1,0,5,5,2,11,5,14,3,13,4,5,3,12,3,1,10,6,1,2,3,3,7,3,3,6,3,3,10,7,1,16,2,4,0,2,2,4,12,1,5,5,5,12,3,9,5,3,5,4,2,5,6,5,1,6,5,5,7,2,3,19,3,9,5,2,2,4,3,4,2,13,6,11,2,6,6,3,5,6,2,2,6,3,4,4,5,2,4,2,3,7,2,2,2,11,4,16,3,1,5,10,2,4,3,7,0,5,8,2,6,6,4,2,2,9,5,3,9,11,1,24,2,2,8,2,5,3,3,1,3,3,1,7,3,6,17,7,1,6,5,3,12,2,4,10,3,4,6,2,6,9,6,1,0,3,4,5,2,2,1,2,3,4,5,1,6,2,4,8,2,3,3,3,8,3,2,2,7,7,2,10,21,6,8,2,3,1,2,2,6,5,2,6,2,2,3,3,1,6,2,10,3,10,5,21,5,1,2,3,5,4,7,3,0,3,3,7,5,1,14,2,6,8,22,4,8,2,3,20,3,9,1,5,5,6,2,2,7,2,5,6,3,9,2,7,2,2,6,8,7,31,1,2,10,3,8,3,4,0,2,4,2,5,1,5,7,1,0,2,3,22,2,2,10,2,3,10,3,1,2,7,2,8,2,2,8,2,2,3,2,4,6,5,3,8,6,2,10,3,3,2,2,3,4,6,1,7,2,5,10,3,1,7,5,6,14,17,2,12,5,9,14,2,10,20,3,7,6,2,6,2,5,11,3,2,7,21,2,2,2,7,1,3,3,1,2,3,3,3,2,2,7,3,1,0,7,3,4,7,2,0,5,1,6,2,6,2,13,3,26,2,2,3,3,6,3,11,6,2,2,8,0,2,3,8,2,5,8,5,1,6,2,3,8,5,2,0,29,3,36,6,2,5,5,2,4,2,6,3,5,5,3,7,2,0,7,8,6,2,2,4,2,4,17,2,4,6,3,5,0,6,2,0,2,6,8,2,6,12,19,3,6,3,5,3,6,7,2,3,4,5,5,1,3,2,9,3,3,14,0,5,5,2,2,2,4,7,3,4,2,4,14,13,1,7,2,3,8,2,5,6,10,5,6,17,1,4,3,1,5,2,5,7,3,4,1,7,1,3,6,6,0,2,3,7,7,10,5,3,1,2,2,6,1,7,4,14,2,3,6,3,9,3,2,2,0,2,2,6,3,1,2,3,11,0,5,3,9,2,15,12,2,3,2,7,3,10,3,10,4,3,4,1,2,6,17,5,1,2,6,1,4,2,6,8,5,2,6,3,3,2,7,3,3,5,6,3,17,1,17,3,6,9,5,5,2,6,2,2,3,7,11,5,1,15,2,10,11,2,3,8,10,2,12,2,5,3,2,3,7,2,4,6,2,2,8,2,3,6,3,4,2,2,4,10,7,7,3,2,2,3,2,9,8,5,3,6,2,2,2,3,1,4,11,4,5,2,2,3,3,1,5,3,7,2,5,1,14,2,6,6,2,2,2,10,6,5,7,1,1,3,1,9,7,2,0,5,8,23,3,3,3,3,3,2,2,2,7,3,8,2,2,6,8,3,3,3,2,4,6,3,1,11,3,6,7,5,1,9,14,2,8,5,10,2,14,2,24,2,2,4,3,14,0,10,4,2,2,2,7,5,3,3,2,3,8,2,6,10,2,3,6,3,7,3,2,11,0,2,6,8,5,1,6,3,3,7,5,2,10,3,1,2,3,1,1,3,1,6,2,3,4,2,3,0,2,2,8,2,10,4,3,5,7,7,1,6,7,4,0,5,1,5,2,6,6,6,4,0,2,3,2,17,1,3,5,1,10,2,7,7,2,2,8,5,5,16,2,3,8,3,11,1,37,7,36,3,1,2,3,1,0,2,2,12,3,1,6,2,5,6,7,7,0,2,3,4,2,5,6,3,1,2,2,3,7,5,10,3,2,2,4,3,1,0,3,7,5,2,2,6,3,4,2,3,7,4,5,1,2,3,3,7,2,6,6,3,4,6,5,1,6,2,3,11,2,6,12,7,2,3,7,2,16,3,1,4,2,5,3,3,3,0,2,3,9,5,1,7,7,3,17,2,2,7,2,6,10,11,5,3,3,3,0,15,1,6,5,1,14,3,3,2,6,1,27,13,1,6,6,1,9,3,3,2,5,7,6,3,5,0,2,2,3,2,4,6,5,1,11,6,3,3,2,3,2,3,4,2,3,10,3,29,6,4,17,1,18,2,2,6,3,4,4,5,5,6,7,3,4,2,4,10,13,4,6,3,3,4,2,5,6,3,15,1,2,2,3,5,1,8,2,2,6,2,3,7,5,2,12,2,3,9,3,3,5,5,5,13,11,2,14,2,3,4,2,4,4,2,2,2,17,10,3,5,2,15,2,3,7,7,4,6,2,3,8,2,6,7,3,1,4,5,3,3,12,1,8,2,6,3,7,4,3,29,1,2,2,3,8,2,3,1,6,10,5,13,1,7,3,3,5,2,5,6,2,7,0,2,2,12,3,3,3,5,1,0,3,3,0,7,2,4,2,2,7,2,6,6,2,2,1,7,1,14,2,2,7,5,1,6,3,3,0,3,1,5,3,1,11,2,2,3,3,1,3,3,6,0,35,1,20,2,3,3,6,1,7,5,5,10,5,5,12,2,2,6,6,2,3,2,3,8,17,5,6,2,6,3,3,6,2,2,4,10,5,1,5,2,3,16,2,4,2,5,1,2,3,6,9,2,12,2,3,4,9,13,4,14,2,3,1,7,7,3,3,7,6,6,3,3,10,5,2,2,3,6,7,9,5,7,1,0,3,4,6,3,1,0,3,4,2,13,1,14,2,3,7,5,3,0,2,5,8,2,4,4,2,6,3,3,1,0,5,9,1,5,6,10,3,6,3,7,2,22,2,3,1,2,2,10,7,1,2,3,4,7,2,3,8,3,1,3,2,3,18,2,5,10,5,3,3,2,3,7,2,5,6,2,2,8,5,2,3,2,2,10,2,3,7,3,7,6,5,2,12,2,2,8,2,6,6,3,3,5,2,6,15,2,3,3,2,4,2,5,1,9,5,1,6,2,3,3,2,4,2,3,6,10,3,13,13,3,1,6,5,5,6,3,5,7,5,2,6,6,1,16,5,7,5,11,1,11,7,3,0,7,11,14,11,2,3,17,1,20}; uint16_t __nmod_poly_cp_md_coeffs5[] = {11001,11002,10996,11025,11023,10607,11044,11045,9701,11054,11056,10481,11049,11049,5760,11067,11061,6982,11068,11069,7980,11081,11079,10536,11082,11086,10473,11091,11092,7869,11100,11112,7710,11114,11116,7991,11116,11117,10561,11129,11127,9391,11139,11148,5896,11152,11157,10793,11154,11158,9994,11169,11170,7302,11168,11170,9051,11174,11171,6647,11195,11193,6642,11211,11209,9249,11236,11238,6673,11238,11238,5897,11238,11250,5766,11247,11252,9783,11259,11260,10474,11270,11268,9079,11272,11278,7469,11284,11285,6223,11296,11298,6832,11308,11309,11307,11315,11316,11310,11318,11320,5880,11322,11317,8324,11344,11350,8130,11346,11350,11202,11366,11354,10844,11378,11382,9168,11390,11392,7035,11388,11397,9253,11404,11405,11226,11418,11421,11419,11435,11436,7118,11441,11442,8699,11442,11445,7158,11462,11466,9143,11460,11470,6789,11481,11476,7121,11486,11483,11477,11488,11481,8779,11490,11494,9646,11500,11502,7225,11512,11518,7599,11522,11526,8088,11547,11544,11363,11544,11542,6094,11577,11566,8159,11585,11583,10873,11588,11592,9337,11594,11587,9996,11607,11616,6340,11619,11617,10543,11630,11632,8552,11654,11656,6727,11675,11673,10358,11678,11673,8444,11682,11682,7401,11697,11695,5943,11695,11700,6465,11715,11716,9431,11713,11717,10615,11728,11726,7601,11740,11742,11732,11774,11768,8084,11777,11778,11591,11778,11782,10624,11787,11785,9784,11798,11795,11789,11802,11802,11346,11811,11809,6237,11819,11820,7766,11825,11823,8917,11824,11829,11523,11828,11832,9164,11836,11837,9176,11860,11861,11859,11865,11863,7791,11884,11886,10400,11894,11896,8766,11898,11901,11899,11907,11893,7289,11918,11922,6692,11922,11919,7777,11931,11932,7489,11937,11934,11206,11931,11940,6541,11948,11952,8562,11956,11958,6303,11966,11962,8176,11961,11970,8429,11979,11973,7574,11985,11980,10954,11994,12006,10837,12009,12007,9302,12032,12036,7802,12038,12040,8855,12041,12042,9243,12036,12040,8499,12060,12068,10269,12066,12070,8681,12092,12096,6345,12098,12090,9744,12105,12102,11759,12103,12108,8914,12110,12106,6426,12112,12118,8857,12133,12142,10228,12147,12144,10662,12155,12156,9056,12158,12153,6434,12158,12162,8225,12195,12196,7573,12201,12199,6197,12209,12210,7980,12225,12226,6696,12226,12238,11522,12234,12234,7895,12249,12246,6778,12251,12252,7895,12258,12262,8857,12267,12268,6657,12275,12276,6367,12278,12264,9966,12278,12288,10637,12299,12297,11309,12321,12322,7335,12326,12324,8762,12336,12340,11091,12345,12346,10924,12371,12369,11774,12371,12366,9835,12377,12378,12372,12365,12390,10137,12398,12395,12389,12402,12406,9146,12411,12409,6331,12414,12419,11329,12420,12432,7663,12435,12436,10551,12448,12450,11286,12447,12454,10267,12470,12467,10319,12456,12466,8509,12484,12486,6883,12489,12487,10160,12494,12491,8631,12498,12498,10642,12508,12509,8133,12511,12516,10850,12522,12519,10348,12537,12535,8483,12527,12538,12187,12545,12546,11040,12548,12552,9804,12566,12563,12557,12567,12576,10786,12578,12581,7861,12587,12588,12582,12590,12600,8297,12609,12607,8240,12611,12612,6509,12617,12618,9097,12635,12633,9579,12638,12636,11325,12642,12645,10998,12651,12649,7719,12657,12655,9226,12657,12666,8174,12686,12663,10300,12690,12690,7201,12700,12701,12695,12710,12712,11614,12708,12720,11757,12737,12738,7197,12738,12742,9400,12755,12756,10778,12761,12759,12176,12779,12780,7134,12784,12790,12538,12786,12796,9776,12806,12803,12797,12819,12817,8064,12820,12821,12819,12827,12828,12822,12820,12837,12285,12848,12848,10364,12876,12876,12850,12890,12891,12889,12897,12895,11522,12905,12906,10806,12888,12909,11184,12915,12913,10722,12913,12917,12237,12921,12919,9816,12939,12937,6943,12950,12952,6783,12952,12958,12476,12964,12965,12959,12959,12972,8938,12977,12975,12782,12978,12978,8709,12998,12992,8473,12998,13001,12995,13002,13005,13003,13002,13006,11645,13028,13028,8087,13035,13036,10273,13041,13037,10220,13046,13043,13037,13058,13062,6753,13087,13091,12260,13096,13094,9131,13098,13100,12631,13107,13108,10967,13114,13120,13112,13122,13125,11607,13145,13143,10388,13138,13149,8034,13156,13157,7702,13161,13162,10042,13160,13155,9001,13172,13176,12852,13180,13181,9259,13185,13186,11476,13214,13216,8353,13216,13218,9064,13227,13228,12376,13238,13235,13229,13242,13242,9771,13253,13258,7318,13264,13262,12885,13289,13290,9534,13292,13292,10985,13303,13308,10048,13310,13307,10149,13324,13326,12644,13329,13330,13324,13334,13331,11563,13337,13335,11379,13362,13365,10774,13371,13377,13369,13395,13387,8569,13396,13397,13395,13409,13410,12560,13412,13416,9896,13411,13412,11263,13430,13436,13422,13449,13447,13123,13454,13451,13055,13458,13461,7855,13467,13465,12001,13475,13473,8310,13482,13485,13483,13493,13498,11673,13508,13508,12909,13521,13522,10269,13530,13530,13336,13550,13548,9255,13564,13565,10098,13574,13572,11270,13588,13590,7954,13592,13592,8962,13611,13612,9342,13617,13612,12678,13625,13626,13620,13628,13632,8948,13646,13643,13637,13663,13668,8034,13672,13677,12320,13659,13679,12837,13684,13685,13219,13689,13684,7555,13687,13691,12123,13694,13692,12739,13707,13705,10841,13705,13709,10891,13718,13716,13459,13721,13722,13716,13706,13724,9923,13740,13750,12072,13755,13753,12979,13753,13758,11518,13761,13758,8176,13774,13780,12092,13782,13787,12012,13792,13798,13200,13802,13806,7160,13827,13822,13104,13825,13829,7411,13835,13835,9725,13857,13849,8838,13868,13872,12572,13875,13873,12699,13873,13878,7827,13881,13878,8704,13899,13900,10722,13900,13902,9020,13905,13906,12303,13910,13907,9536,13914,13918,10679,13929,13927,12622,13931,13932,12695,13960,13956,9166,13962,13964,13388,13995,13993,9119,13996,13998,13497,14006,14002,7563,14009,14007,13601,14023,14028,10970,14030,14032,13187,14049,14047,7128,14054,14051,11112,14064,14062,13232,14078,14076,9476,14080,14076,8351,14082,14085,10003,14105,14103,8711,14140,14142,8452,14143,14145,12231,14150,14152,9492,14146,14142,7929,14171,14172,7332,14174,14172,13112,14186,14196,13990,14202,14206,10123,14219,14217,10322,14241,14239,11177,14246,14240,8020,14248,14244,7517,14262,14268,12888,14287,14292,9296,14298,14302,13408,14318,14320,12410,14318,14321,14315,14322,14319,13083,14339,14340,13520,14344,14342,12043,14366,14363,14357,14385,14383,11871,14387,14384,12161,14390,14400,9977,14388,14405,13007,14409,14406,9697,14417,14418,8774,14418,14422,9831,14428,14430,11655,14432,14432,9262,14442,14442,9069,14427,14443,13340,14459,14460,7365,14476,14477,14475,14486,14484,11364,14500,14501,14495,14506,14516,10077,14531,14526,12880,14534,14536,11076,14538,14542,8060,14547,14536,13678,14548,14549,13724,14555,14553,14122,14555,14558,13475,14560,14562,10162,14580,14588,14295,14588,14590,14582,14619,14615,11075,14625,14623,7514,14627,14623,8495,14630,14627,9488,14628,14633,14397,14651,14649,9191,14654,14652,12260,14667,14657,11437,14680,14678,14412,14697,14698,11988,14708,14710,14702,14715,14713,9721,14721,14719,13815,14721,14730,13058,14727,14736,10198,14739,14740,11603,14745,14740,10091,14750,14752,14315,14742,14757,14751,14764,14765,11676,14769,14765,14427,14776,14778,9676,14778,14774,12067,14795,14796,11646,14811,14809,13288,14819,14817,10680,14825,14823,8938,14820,14830,14142,14841,14839,14210,14849,14847,14640,14865,14866,11809,14867,14865,12464,14872,14878,7908,14884,14885,13556,14889,14887,9122,14894,14891,11419,14921,14922,9081,14922,14926,9447,14937,14935,12854,14945,14943,12696,14932,14950,9679,14955,14956,14950,14966,14964,13196,14980,14981,14979,15011,15012,11191,15014,15016,11978,15028,15029,8554,15051,15047,14277,15059,15057,9468,15068,15068,13101,15075,15076,10509,15081,15075,7810,15089,15087,7652,15099,15093,14609,15105,15101,12520,15110,15120,11091,15129,15127,14639,15134,15132,12044,15137,15138,10952,15147,15145,13568,15158,15155,15149,15171,15169,9189,15185,15183,12918,15188,15192,9152,15193,15197,14595,15207,15216,8075,15225,15223,13122,15230,15227,14724,15230,15240,12892,15257,15258,9510,15258,15261,9395,15267,15262,14071,15260,15269,10687,15271,15276,10990,15282,15285,10761,15278,15284,13890,15297,15295,12536,15304,15306,14957,15308,15312,15294,15316,15313,13897,15326,15328,9817,15329,15327,8141,15347,15348,10522,15348,15357,11082,15354,15354,8585,15371,15369,11244,15374,15372,13302,15378,15382,7799,15379,15390,8544,15395,15398,13736,15411,15412,9182,15425,15426,12801,15436,15438,8299,15441,15438,13921,15448,15450,8718,15459,15460,15132,15462,15462,13985,15470,15472,9553,15488,15492,13989,15494,15491,15145,15508,15509,15507,15522,15524,12618,15535,15537,13485,15544,15550,8500,15556,15557,12175,15566,15564,9214,15579,15580,15574,15578,15582,12039,15578,15600,9357,15604,15605,10488,15612,15617,15119,15627,15624,13192,15638,15636,10034,15638,15641,10262,15642,15646,10656,15638,15644,13785,15659,15657,10274,15665,15663,8825,15658,15669,11603,15668,15678,14897,15681,15682,14689,15724,15726,13197,15729,15726,10581,15727,15731,13802,15734,15736,12626,15737,15738,12090,15747,15744,13579,15758,15756,8021,15762,15765,15763,15771,15765,11997,15785,15783,8715,15762,15789,13692,15795,15796,11364,15801,15799,13330,15806,15793,11417,15812,15814,15806,15820,15821,11784,15857,15855,14606,15872,15876,12548,15878,15880,14374,15882,15885,12622,15868,15885,8661,15891,15900,8178,15905,15906,14352,15908,15912,10875,15913,15915,15915,15921,15922,11080,15930,15934,9049,15948,15957,12406,15969,15967,13906,15966,15971,15535,15979,15990,15501,15998,16000,11518,16002,16005,10910,16028,16030,10823,16050,16054,8370,16049,16057,12651,16058,16062,10575,16065,16061,10096,16067,16062,15200,16070,16072,11304,16082,16086,14210,16085,16090,15496,16094,16091,13585,16098,16102,8601,16104,16100,11905,16122,16126,9406,16137,16134,13098,16135,16137,12611,16180,16181,13542,16185,16186,14687,16187,16188,12027,16188,16186,11495,16214,16209,9176,16218,16221,16211,16227,16225,10412,16228,16230,11282,16232,16246,9288,16251,16252,11667,16264,16254,9631,16266,16266,9328,16299,16300,9533,16312,16318,14283,16331,16329,13777,16337,16335,9888,16347,16345,15888,16358,16353,15626,16361,16359,13047,16362,16366,11519,16379,16377,15657,16408,16410,8375,16407,16416,13893,16419,16411,11652,16425,16423,15023,16430,16423,14284,16444,16446,13423,16444,16445,16447,16451,16452,15443,16475,16476,16470,16475,16471,13531,16482,16486,14263,16491,16489,8748,16516,16517,12886,16526,16528,16347,16545,16546,10767,16550,16547,12969,16554,16558,9382,16564,16565,10444,16571,16569,9569,16601,16602,15788,16602,16605,15925,16617,16615,15056,16612,16630,10223,16618,16632,9934,16646,16643,16637,16649,16650,11256,16652,16656,13959,16651,16656,12016,16670,16672,8824,16685,16689,16681,16691,16692,8491,16696,16694,16410,16698,16702,8813,16716,16726,12734,16735,16740,8876,16745,16746,16430,16756,16754,13520,16761,16759,13241,16785,16783,10145,16804,16810,14794,16818,16821,11944,16827,16825,13058,16825,16829,14569,16841,16839,11857,16854,16869,16863,16876,16877,9540,16881,16875,8556,16886,16882,15970,16899,16900,16894,16900,16902,12591,16904,16918,16162,16921,16926,9845,16929,16930,13481,16934,16936,9810,16938,16942,9020,16961,16959,14815,16977,16973,10100,16979,16980,13100,16984,16976,13805,16983,16992,15879,17009,17007,13795,17019,17013,13081,17025,17026,14040,17019,17025,17017,17030,17027,14449,17034,17034,16291,17044,17046,11227,17051,17049,14289,17075,17073,8890,17091,17089,12893,17097,17098,13487,17104,17106,16922,17114,17115,14382,17121,17119,14197,17132,17136,11563,17152,17158,16866,17164,17166,10995,17178,17178,11186,17187,17177,8834,17188,17189,11345,17201,17199,16333,17202,17205,17203,17195,17202,8751,17218,17227,9900,17233,17237,9995,17252,17252,12127,17285,17288,9115,17286,17291,13974,17297,17295,16555,17315,17316,14695,17318,17316,11113,17322,17324,12024,17331,17329,15647,17335,17340,16573,17340,17350,8850,17356,17357,14524,17370,17370,13357,17378,17381,17379,17385,17380,11427,17387,17385,14053,17390,17387,15367,17390,17400,8849,17414,17408,12851,17416,17418,14679,17428,17430,16720,17441,17439,9848,17435,17444,15512,17464,17466,13632,17460,17468,9740,17475,17476,10983,17481,17478,16596,17486,17480,12697,17488,17486,11158,17492,17494,11505,17507,17505,14794,17506,17517,16641,17536,17531,12655,17548,17550,10092,17558,17564,11572,17571,17569,15339,17577,17575,12349,17571,17580,14731,17595,17596,13272,17593,17597,11910,17606,17603,17597,17620,17621,10124,17625,17621,9640,17654,17648,16553,17656,17643,9493,17667,17665,13132,17678,17675,17669,17678,17682,10266,17704,17706,9502,17706,17706,10800,17726,17723,17717,17730,17730,12831,17745,17743,10694,17747,17740,13430,17742,17748,14869,17778,17778,9981,17787,17784,10357,17788,17789,12096,17802,17802,17454,17825,17826,11229,17835,17833,14362,17833,17837,17396,17849,17847,13825,17857,17862,16183,17874,17878,9480,17889,17887,12191,17898,17898,17549,17907,17903,12859,17908,17909,9990,17918,17914,15904,17921,17922,12671,17918,17915,15684,17937,17932,9366,17955,17952,16029,17953,17957,15994,17968,17970,10615,17972,17976,11843,17979,17980,14248,17982,17984,14070,17987,17988,14690,18011,18009,15982,18038,18035,18029,18041,18039,13772,18042,18044,11073,18036,18048,15234,18057,18054,11939,18055,18057,9650,18075,18071,12604,18086,18084,9195,18092,18094,14769,18102,18117,18111,18098,18120,17654,18124,18126,18116,18124,18127,12288,18128,18128,13395,18138,18135,15942,18147,18148,16538,18158,18154,17818,18179,18177,9768,18162,18190,15236,18188,18197,13365,18204,18205,11326,18210,18214,11839,18220,18222,16672,18227,18225,17959,18230,18232,9739,18249,18246,11575,18248,18252,11906,18252,18249,16485,18267,18265,9937,18282,18282,13947,18276,18280,9706,18295,18297,18297,18296,18306,16831,18298,18307,14877,18303,18310,17080,18326,18323,18317,18338,18336,14231,18350,18341,16535,18364,18366,9844,18360,18368,16148,18376,18368,16019,18391,18396,12477,18398,18396,12715,18411,18409,13627,18425,18426,9861,18428,18432,15443,18436,18437,18435,18441,18442,14970,18448,18440,17314,18452,18456,10609,18459,18453,17838,18468,18478,15261,18491,18492,11729,18498,18501,14477,18511,18515,12181,18518,18515,18509,18520,18522,13398,18533,18537,15012,18535,18537,10978,18548,18550,9961,18580,18581,18575,18585,18583,13034,18590,18587,16589,18614,18610,12761,18635,18636,18630,18651,18660,13839,18664,18670,10586,18673,18677,17207,18688,18690,16159,18699,18693,10844,18710,18712,17106,18712,18717,11067,18729,18727,18494,18738,18738,16527,18747,18742,17743,18755,18753,10613,18771,18768,10974,18785,18786,16032,18788,18792,14561,18794,18795,18793,18798,18802,16948,18832,18838,14835,18857,18855,10191,18867,18861,15316,18897,18895,15825,18897,18905,17681,18906,18910,10361,18915,18916,16591,18916,18918,16302,18945,18946,15044,18946,18958,11516,18971,18972,15546,18977,18975,10202,18998,18995,18989,18986,19006,15317,19011,19008,10213,19020,19029,16760,19035,19033,16206,19049,19047,18812,19067,19064,10991,19070,19068,15571,19072,19077,10494,19064,19080,18602,19068,19085,15189,19115,19118,12575,19137,19135,18536,19139,19140,9820,19155,19156,12944,19161,19159,16983,19179,19177,13168,19180,19182,10706,19202,19205,17416,19205,19208,17571,19208,19210,13122,19217,19210,15652,19225,19229,13006,19235,19233,10465,19242,19242,10637,19257,19255,18438,19264,19266,11639,19268,19268,13201,19286,19276,14941,19299,19297,16927,19303,19305,18808,19308,19318,18667,19331,19332,9822,19371,19358,13948,19377,19378,10801,19374,19379,12050,19385,19383,13594,19380,19389,11000,19401,19402,10684,19412,19416,15493,19418,19412,13945,19420,19422,14877,19425,19423,11849,19423,19421,11211,19430,19428,13274,19428,19440,14039,19444,19446,18565,19454,19450,19115,19458,19455,16645,19467,19465,16973,19460,19469,14971,19471,19476,14529,19481,19479,15277,19470,19484,14131,19499,19500,16335,19505,19506,17426,19518,19527,19519,19539,19537,14530,19540,19542,13152,19550,19552,14809,19546,19557,17030,19569,19567,11687,19574,19576,17994,19578,19582,19041,19595,19593,18971,19601,19602,19596,19596,19596,19570,19659,19660,17605,19670,19680,14428,19682,19686,11861,19694,19696,19300,19692,19697,12581,19707,19702,11056,19715,19716,10550,19722,19725,19723,19737,19738,13586,19744,19750,12836,19748,19750,19742,19756,19757,11645,19761,19757,11361,19766,19775,19757,19790,19788,16165,19788,19790,16129,19811,19812,18848,19816,19818,16578,19838,19840,10211,19824,19840,15188,19851,19848,15733,19850,19859,19546,19865,19863,17475,19886,19883,19877,19889,19887,11654,19910,19907,10168,19912,19918,11212,19921,19924,17010,19934,19932,11705,19947,19948,18260,19955,19960,12333,19961,19962,15034,19971,19969,10367,19977,19975,17346,19980,19990,13741,19983,19990,10617,19995,19996,16717,19999,20009,15522,20018,20019,20017,20020,20021,20019,20027,20025,17747,20044,20045,10742,20049,20050,15376,20058,20062,17486,20068,20070,13551,20082,20080,16179,20095,20100,16896,20105,20106,20100,20103,20112,19737,20115,20112,17193,20121,20122,20116,20126,20128,14233,20138,20142,15741,20141,20138,16405,20147,20148,11354,20148,20158,10924,20171,20172,12648,20174,20171,12724,20178,20175,19020,20195,20195,15004,20217,20218,11006,20202,20230,19120,20228,20228,16403,20246,20243,20237,20259,20260,18378,20267,20265,19095,20282,20286,11622,20294,20296,12438,20321,20319,19228,20322,20325,20323,20330,20326,15379,20339,20340,10330,20344,20346,11117,20348,20348,20106,20355,20349,12291,20348,20356,19263,20366,20364,14324,20383,20385,10912,20390,20392,12277,20392,20395,10542,20402,20405,20403,20405,20410,10887,20428,20429,20427,20438,20435,20429,20441,20442,16404,20475,20473,12367,20476,20478,16508,20478,20481,20479,20505,20503,11073,20507,20505,11765,20510,20512,13028,20531,20529,12737,20538,20532,12630,20547,20545,12215,20548,20549,11603,20560,20548,13174,20588,20586,10926,20596,20598,20396,20609,20610,19726,20625,20626,11219,20628,20636,19354,20634,20634,17957,20658,20655,14980,20678,20676,11466,20691,20689,11356,20702,20705,20703,20715,20713,19390,20716,20718,16971,20729,20727,15429,20738,20742,13294,20742,20746,19111,20747,20745,16542,20750,20748,15131,20752,20758,17518,20769,20767,10858,20771,20769,11356,20787,20785,15511,20802,20805,20803,20802,20802,17529,20846,20843,20837,20847,20856,18094,20870,20868,19344,20868,20877,12172,20884,20885,17620,20894,20892,18719,20897,20895,11108,20898,20901,20899,20918,20915,20909,20922,20926,15261,20937,20928,12137,20944,20940,17590,20952,20948,18067,20961,20962,20712,20979,20977,17538,20980,20982,10920,20990,20992,11284,21009,21004,12497,21011,21012,15841,21014,21011,12444,21017,21018,17038,21018,21020,18234,21019,21030,11608,21057,21058,17715,21054,21059,14335,21065,21063,16954,21086,21079,11010,21099,21100,12337,21105,21102,18689,21102,21109,11023,21137,21138,13810,21133,21139,16832,21146,21147,21141,21155,21156,13289,21161,21159,11414,21156,21156,21130,21177,21175,13268,21185,21186,18507,21184,21190,20985,21182,21192,13689,21209,21207,20728,21219,21217,18148,21225,21226,15984,21244,21246,14636,21267,21265,13497,21271,21275,11311,21272,21281,21030,21308,21312,11188,21315,21310,17994,21305,21317,11947,21318,21321,15462,21339,21340,11664,21345,21343,19528,21374,21369,20407,21377,21375,10816,21378,21382,11578,21385,21389,17645,21395,21396,16917,21398,21394,17194,21402,21406,15684,21417,21415,15943,21428,21428,18101,21465,21466,15783,21468,21480,11187,21484,21485,20081,21489,21486,17541,21491,21492,15459,21496,21492,13890,21498,21502,14072,21512,21512,16883,21518,21516,15845,21521,21522,20994,21518,21528,15558,21555,21553,12548,21544,21554,16632,21561,21562,21556,21566,21564,19927,21572,21576,12406,21585,21586,15908,21587,21585,12637,21592,21598,15458,21594,21594,18308,21609,21607,21023,21611,21609,21319,21614,21612,20609,21642,21644,13870,21635,21646,10990,21659,21660,20652,21663,21672,11562,21681,21679,21428,21699,21697,11188,21710,21706,11351,21724,21726,20947,21731,21735,15587,21737,21735,20761,21748,21749,18831,21752,21756,20260,21762,21766,11790,21771,21769,14021,21764,21786,17555,21792,21788,12115,21801,21802,13905,21810,21810,16726,21819,21817,15700,21828,21835,14928,21830,21836,21822,21845,21849,15992,21857,21858,16731,21858,21861,18880,21865,21870,17088,21878,21876,11106,21891,21885,20466,21898,21910,16837,21926,21924,18844,21930,21930,19558,21938,21941,21931,21944,21960,18877,21974,21972,18370,21988,21990,17520,21990,21995,18589,22001,21999,20223,22011,22012,11274,22024,22022,16824,22024,22030,22022,22035,22033,19625,22033,22038,19033,22048,22050,11985,22058,22061,20190,22065,22066,17808,22070,22067,15707,22072,22075,13498,22089,22090,13125,22087,22091,19829,22107,22103,18368,22105,22109,20781,22121,22122,17751,22110,22124,14125,22131,22127,15963,22142,22146,16305,22148,22152,11345,22155,22153,19121,22153,22158,21602,22169,22167,16048,22187,22185,14003,22190,22192,12354,22227,22221,15382,22242,22245,17628,22257,22255,12627,22264,22270,12906,22268,22268,22062,22275,22273,18990,22276,22277,15116,22281,22277,18879,22288,22284,20233,22297,22300,19217,22305,22302,19485,22338,22342,20747,22347,22340,12245,22362,22365,22363,22358,22358,20057,22371,22378,20073,22378,22390,19015,22395,22393,17655,22406,22408,11808,22430,22428,21207,22427,22438,15277,22444,22446,16286,22448,22452,11570,22467,22465,18906,22478,22480,20688,22481,22479,13033,22499,22500,12237,22500,22510,19183,22529,22530,22271,22538,22539,22533,22540,22541,20698,22547,22545,19242,22564,22565,14944,22565,22569,22561,22567,22572,12988,22611,22608,13162,22617,22612,19196,22619,22617,20510,22635,22631,17813,22633,22638,22076,22641,22639,14386,22648,22650,17235,22667,22668,15799,22666,22677,13290,22689,22687,20225,22694,22691,22175,22687,22698,19604,22707,22704,21768,22715,22713,22380,22718,22720,20033,22722,22719,13027,22737,22738,12192,22734,22739,17229,22730,22749,18369,22766,22768,16921,22770,22774,13091,22780,22782,21890,22785,22783,11840,22804,22805,22803,22805,22809,22226,22814,22811,12875,22851,22849,11699,22857,22852,13165,22859,22860,11777,22864,22870,22862,22875,22873,15815,22899,22897,22473,22902,22902,19319,22914,22914,18100,22934,22936,12673,22938,22940,15087,22955,22960,19430,22960,22962,12220,22971,22972,22634,22988,22992,20272,23001,22993,18086,23004,23009,15883,23012,23016,20398,23019,23020,21707,23025,23023,19504,23027,23025,15045,23032,23038,16180,23030,23036,23022,23051,23049,19444,23052,23050,16889,23056,23042,16809,23058,23060,16943,23068,23069,17794,23078,23075,23069,23082,23086,22201,23097,23098,16685,23115,23113,12190,23128,23124,12649,23138,23141,23139,23148,23153,23155,23164,23165,14687,23168,23172,21666,23187,23188,19547,23195,23196,21941,23198,23200,19539,23200,23198,19660,23178,23208,11886,23224,23226,13128,23249,23247,17091,23263,23265,21069,23272,23278,22708,23285,23290,12883,23288,23292,18037,23294,23296,14862,23308,23310,21212,23318,23315,23309,23322,23325,21599,23331,23329,17585,23337,23335,21157,23355,23356,14555,23366,23364,15507,23369,23370,17462,23382,23397,23391,23414,23408,15219,23428,23429,23427,23442,23444,18884,23457,23450,17342,23468,23472,12620,23492,23496,23280,23507,23508,18922,23529,23526,20955,23534,23536,20947,23537,23534,13023,23547,23545,16278,23552,23554,13162,23558,23556,13414,23561,23559,22059,23562,23562,15639,23575,23577,23577,23588,23592,13402,23596,23597,23595,23601,23602,20737,23603,23606,12496,23617,23620,20619,23625,23623,20095,23627,23625,22694,23628,23628,22258,23658,23661,14091,23667,23662,22391,23668,23670,13774,23672,23676,17965,23682,23685,23683,23678,23684,17232,23713,23717,17194,23739,23737,14491,23740,23738,12127,23745,23746,21173,23750,23747,21853,23754,23754,13633,23764,23766,22423,23768,23770,22420,23787,23788,20966,23798,23791,18160,23811,23809,23057,23817,23811,19293,23825,23826,23820,23820,23827,18265,23828,23830,23822,23852,23856,13498,23867,23863,14180,23870,23868,13312,23872,23878,12533,23884,23886,21324,23888,23892,21391,23897,23895,20028,23907,23905,16857,23905,23910,22897,23915,23916,18746,23922,23926,13359,23955,23950,18108,23961,23969,21167,23972,23976,16580,23978,23979,23977,23990,23985,17629,23987,23998,19905,23990,24005,23999,24017,24015,21463,24018,24021,24019,24027,24025,17813,24041,24042,19923,24030,24046,17444,24051,24060,15322,24060,24070,22963,24075,24073,21575,24081,24082,15842,24084,24089,19002,24092,24094,18233,24098,24101,16916,24105,24106,16265,24107,24105,15418,24110,24107,13869,24108,24109,21986,24127,24131,18645,24134,24131,22964,24145,24149,19583,24158,24168,23491,24177,24175,18883,24164,24180,20864,24195,24191,20105,24201,24199,23092,24220,24221,16011,24227,24225,12395,24226,24237,17548,24244,24242,15502,24245,24249,24241,24278,24269,23583,24315,24316,19371,24326,24328,13839,24332,24332,13634,24348,24357,18118,24369,24367,16480,24366,24371,14265,24377,24375,19135,24388,24389,23642,24402,24405,16779,24411,24405,20485,24417,24418,17258,24414,24419,14717,24433,24435,24435,24441,24442,18400,24455,24466,20631,24470,24467,22810,24470,24472,20309,24497,24495,19662,24507,24501,20791,24512,24512,14823,24522,24510,21810,24531,24532,13522,24545,24546,17155,24544,24550,24542,24564,24569,22890,24590,24592,23409,24598,24607,13355,24618,24622,24401,24628,24630,18822,24657,24658,24387,24660,24670,12472,24675,24673,21473,24681,24677,20298,24689,24687,12606,24692,24694,24686,24707,24705,17368,24731,24729,20705,24747,24745,19862,24761,24759,15839,24762,24766,23274,24779,24777,19579,24788,24790,15414,24793,24798,15233,24803,24806,23226,24819,24820,16665,24827,24839,14749,24844,24845,17856,24849,24846,24434,24857,24855,22967,24872,24874,19054,24878,24884,24870,24905,24903,18748,24915,24913,15180,24916,24917,19134,24921,24922,12901,24938,24942,22421,24950,24948,12957,24964,24966,15797,24969,24967,18660,24974,24976,23990,24977,24978,23765,24987,24988,21711,25011,25009,21530,25018,25029,18502,25028,25032,20483,25035,25033,22014,25052,25056,17482,25070,25067,24625,25084,25086,18369,25094,25092,22684,25108,25109,23263,25112,25116,19643,25118,25120,13068,25122,25125,15511,25145,25146,24323,25143,25152,24581,25161,25159,17257,25166,25158,24153,25168,25160,19305,25178,25182,25164,25187,25188,15569,25217,25210,13660,25227,25225,15951,25235,25233,12796,25241,25239,20249,25242,25246,18166,25251,25249,16484,25254,25259,23105,25298,25299,25297,25300,25301,20395,25305,25303,23849,25296,25300,17876,25302,25302,17706,25336,25338,14839,25338,25341,23928,25347,25345,15950,25355,25356,16390,25362,25366,24452,25371,25372,18348,25384,25390,24563,25406,25408,16382,25404,25409,17404,25420,25422,20629,25432,25435,15607,25444,25445,20273,25451,25443,24739,25454,25445,18293,25458,25462,18607,25467,25468,25462,25465,25470,16657,25521,25518,24349,25527,25536,13603,25539,25537,21841,25550,25560,18210,25574,25576,20220,25577,25575,25025,25578,25581,20849,25587,25581,17836,25598,25583,19529,25601,25599,14069,25602,25598,25333,25611,25618,17653,25628,25632,16896,25636,25637,23467,25641,25639,15275,25652,25652,13832,25665,25666,25660,25670,25672,14189,25668,25678,22310,25691,25692,19927,25698,25701,20340,25715,25716,19736,25731,25728,25455,25735,25737,17719,25745,25743,19241,25756,25758,15974,25758,25762,15195,25769,25767,21110,25790,25787,16061,25792,25798,23379,25794,25788,13642,25816,25809,18669,25838,25840,17379,25842,25844,15693,25842,25842,23130,25865,25863,17712,25863,25863,21826,25886,25888,16880,25898,25901,17698,25910,25912,23988,25908,25918,23765,25929,25930,24429,25931,25932,25231,25936,25926,16606,25938,25942,16536,25948,25950,22211,25962,25966,23150,25970,25979,16071,25995,25990,18736,25992,25987,15883,26001,25999,23173,26012,26014,26006,26019,26017,15677,26023,26025,18412,26028,26038,19185,26051,26052,25471,26076,26081,17280,26097,26098,14663,26105,26103,16461,26104,26109,25336,26106,26102,20499,26116,26117,24356,26139,26136,21261,26150,26152,18937,26148,26152,24227,26169,26170,26164,26174,26176,18571,26178,26181,15893,26187,26179,19369,26200,26198,17154,26198,26208,21110,26224,26222,18650,26235,26233,15275,26246,26244,23205,26249,26247,15154,26259,26257,23709,26260,26262,15154,26265,26263,24302,26287,26291,21461,26294,26296,19083,26307,26308,19641,26311,26316,20554,26318,26315,26309,26337,26338,24248,26344,26346,19895,26355,26350,20207,26368,26366,23788,26385,26382,21859,26390,26387,25460,26392,26390,20930,26402,26405,26403,26414,26408,16448,26418,26422,15901,26428,26429,21524,26432,26436,21196,26442,26442,18096,26457,26452,14846,26476,26478,24093,26486,26478,14238,26492,26492,21704,26499,26500,13544,26510,26507,18750,26537,26535,20981,26555,26556,17024,26558,26560,24291,26571,26569,25826,26569,26589,17105,26595,26593,15264,26625,26626,21132,26630,26627,20767,26634,26638,20536,26644,26645,17281,26667,26668,13629,26675,26678,13523,26681,26682,14202,26682,26685,26683,26691,26688,25003,26697,26693,25065,26679,26700,26068,26700,26709,14485,26703,26712,21848,26715,26716,20892,26721,26719,17493,26726,26719,16586,26728,26724,21780,26727,26734,25022,26746,26757,22112,26774,26771,14760,26778,26782,19230,26798,26795,26789,26811,26812,14508,26819,26817,14326,26828,26828,24987,26836,26837,22643,26846,26840,19139,26859,26854,19313,26858,26861,26859,26866,26878,26387,26870,26876,26862,26885,26889,16896,26888,26892,24300,26898,26902,23332,26908,26916,21832,26922,26924,22601,26945,26943,23175,26944,26949,24429,26946,26946,16703,26953,26955,16795,26978,26976,15016,26985,26983,17425,26990,26992,24801,27009,27003,22922,27012,27016,18792,27025,27029,17674,27041,27039,23086,27057,27055,15396,27059,27057,17843,27065,27066,26664,27068,27070,26840,27075,27073,14297,27089,27087,19090,27100,27102,14162,27105,27106,21945,27102,27103,27105,27124,27125,15454,27138,27141,26211,27177,27175,20628,27165,27189,22000,27195,27192,19228,27201,27210,13925,27232,27238,27230,27224,27238,22918,27251,27249,23503,27257,27255,22941,27265,27267,18035,27271,27276,21297,27275,27278,23165,27278,27282,24149,27297,27292,18406,27326,27323,27317,27332,27336,22681,27354,27354,23316,27364,27366,16245,27395,27396,26553,27402,27405,26272,27396,27408,17344,27422,27426,26705,27414,27430,20902,27435,27433,20670,27446,27443,27437,27450,27454,25825,27472,27478,23201,27474,27474,16721,27484,27485,14442,27507,27504,16018,27522,27526,18273,27522,27522,18740,27537,27535,18112,27522,27539,14327,27534,27549,27543,27579,27577,21932,27580,27582,18630,27609,27607,18864,27614,27616,19393,27625,27627,21856,27642,27645,26495,27651,27649,22982,27662,27671,21682,27686,27688,15654,27688,27684,23649,27692,27696,14230,27699,27697,22935,27731,27732,16728,27734,27736,22452,27736,27738,15220,27738,27738,16117,27746,27744,24376,27748,27749,27747,27760,27762,18860,27762,27766,22807,27771,27768,17311,27777,27778,14110,27784,27789,18896,27788,27790,27782,27792,27796,27175,27801,27802,21069,27806,27804,25850,27812,27812,18284,27817,27820,20444,27825,27821,14407,27841,27846,19020,27849,27850,23955,27880,27878,17518,27891,27892,20167,27899,27895,17018,27915,27913,21672,27916,27917,20139,27939,27937,23222,27938,27942,25944,27945,27946,24727,27950,27952,26759,27948,27948,27922,27964,27965,23857,27978,27982,25214,27992,27996,18866,27998,28000,26370,28017,28015,14907,28025,28022,23430,28012,28030,17916,28049,28047,24860,28052,28056,19702,28062,28063,18824,28062,28078,22235,28084,28085,25323,28094,28091,15760,28097,28095,27228,28107,28105,23032,28108,28110,19480,28121,28119,23818,28144,28150,22238,28161,28159,23095,28179,28180,23797,28180,28181,28179,28190,28198,19509,28209,28207,18436,28216,28206,21787,28227,28220,24350,28275,28273,18350,28276,28277,18556,28281,28282,25284,28283,28288,17328,28292,28292,21396,28305,28306,20261,28307,28305,27538,28312,28318,23506,28347,28344,25323,28345,28350,26373,28385,28383,18465,28378,28392,14936,28398,28401,28399,28406,28400,25949,28409,28410,19551,28427,28424,19769,28430,28427,24023,28428,28437,16708,28444,28445,28443,28458,28458,19734,28475,28473,14427,28491,28492,23102,28497,28493,24255,28508,28512,28274,28515,28516,27932,28532,28536,19203,28539,28537,22580,28545,28540,18577,28547,28548,21317,28548,28557,21583,28569,28567,24687,28571,28572,20213,28577,28578,21361,28588,28590,19908,28595,28593,18952,28601,28599,18823,28602,28605,28603,28617,28615,26797,28608,28620,27089,28622,28626,24350,28620,28625,17656,28641,28642,28636,28646,28638,17102,28652,28649,17774,28659,28660,24490,28660,28662,17708,28663,28668,19840,28681,28684,22832,28694,28692,14538,28698,28689,28659,28708,28709,27443,28721,28719,22265,28707,28728,16634,28737,28750,15346,28743,28748,24524,28756,28757,23891,28769,28767,23259,28782,28787,20285,28790,28792,19115,28796,28804,19354,28811,28809,19508,28814,28816,18171,28835,28833,20125,28841,28842,22865,28857,28858,17533,28864,28862,18464,28858,28869,14843,28876,28877,28064,28898,28899,17058,28907,28908,15741,28910,28916,15579,28924,28926,28027,28931,28929,19493,28947,28945,27456,28958,28955,28949,28977,28971,18470,29006,29008,26200,29012,29014,14998,29019,29015,28640,29020,29021,18196,29025,29026,15411,29030,29022,18828,29057,29054,22311,29053,29061,18950,29075,29076,14846,29099,29097,21252,29121,29119,28287,29126,29123,29117,29129,29127,26509,29132,29136,16303,29145,29146,19304,29150,29147,17373,29164,29166,17782,29171,29169,21434,29166,29178,28727,29184,29182,22099,29198,29200,28265,29202,29205,29203,29202,29196,25391,29219,29220,23703,29218,29229,15869,29241,29239,27114,29249,29250,27108,29263,29265,20234,29282,29286,23381,29294,29291,16396,29296,29301,23680,29308,29310,20443,29322,29326,19955,29331,29332,26625,29337,29333,26845,29344,29342,22197,29361,29362,22209,29377,29380,14840,29385,29383,17320,29387,29388,29382,29386,29396,28356,29388,29398,24677,29409,29404,14933,29418,29421,19236,29427,29425,25294,29435,29433,25134,29441,29439,18291,29451,29446,15788,29468,29468,21461,29481,29482,25211,29499,29496,20034,29524,29525,21906,29529,29530,21925,29534,29536,25213,29562,29566,20491,29552,29566,18151,29571,29572,26920,29571,29580,17406,29585,29586,26406,29586,29595,19983,29608,29610,26191,29622,29627,23634,29630,29632,25224,29634,29634,24805,29658,29661,29659,29667,29668,27999,29665,29669,26942,29672,29681,15914,29715,29709,24974,29721,29719,16626,29739,29740,16425,29750,29746,26197,29752,29758,22835,29744,29760,21538,29787,29785,16795,29796,29801,20953,29813,29818,22081,29828,29832,21582,29835,29836,20232,29849,29850,19580,29853,29862,24650,29865,29863,27059,29870,29872,20724,29868,29877,25142,29874,29878,22162,29915,29916,26532,29918,29915,29909,29922,29924,28232,29944,29942,27189,29953,29957,23001,29978,29981,20417,29987,29980,27546,30009,30005,26951,30011,30009,28053,30027,30025,17215,30042,30046,22017,30057,30055,29484,30058,30070,27810,30086,30084,15442,30070,30090,18186,30087,30096,18998,30100,30101,22137,30107,30102,19414,30110,30108,22214,30108,30117,22758,30128,30132,23507,30134,30136,17463,30137,30133,20974,30158,30160,21019,30162,30160,19551,30179,30177,18980,30182,30186,19640,30195,30193,21691,30201,30202,30196,30209,30203,16242,30220,30222,27943,30230,30240,16745,30251,30252,21456,30256,30254,29870,30266,30268,21776,30268,30270,16756,30291,30289,21473,30305,30303,26118,30308,30312,18238,30316,30313,15805,30321,30322,28026,30339,30335,28783,30345,30343,17617,30362,30365,30355,30387,30385,23109,30388,30389,24019,30398,30402,19714,30422,30426,16271,30420,30416,16803,30446,30443,30437,30465,30463,23496,30467,30468,29917,30489,30487,29458,30487,30491,23342,30494,30485,25756,30507,30504,27775,30515,30513,26108,30516,30528,19269,30537,30535,17947,30548,30550,19373,30555,30553,15679,30552,30548,27067,30572,30574,30566,30590,30592,17254,30628,30630,19988,30635,30636,23467,30641,30639,20662,30642,30638,22659,30659,30657,20324,30660,30670,17644,30675,30676,23980,30686,30683,30677,30687,30692,28684,30700,30702,22014,30705,30706,23927,30710,30708,27578,30724,30725,24780,30752,30756,26454,30761,30762,25015,30770,30772,30762,30779,30777,19287,30801,30799,16549,30806,30787,27459,30812,30816,24603,30827,30825,16743,30832,30837,25900,30834,30834,25905,30849,30847,26815,30851,30849,18765,30857,30858,17937,30867,30865,22574,30868,30869,23037,30878,30876,23515,30891,30889,30107,30894,30909,21641,30929,30930,20931,30922,30934,16156,30939,30937,18994,30939,30946,20186,30969,30963,30666,30974,30972,20520,30978,30982,15644,31011,31012,23752,31017,31015,30714,31023,31032,26446,31032,31036,19176,31040,31050,23777,31060,31062,26380,31067,31068,25009,31068,31077,29978,31068,31080,19769,31089,31085,18968,31118,31111,29125,31120,31116,18218,31137,31138,17165,31145,31143,22415,31144,31149,26366,31143,31152,30170,31156,31158,27759,31170,31170,19612,31179,31180,28389,31180,31181,31179,31176,31188,20344,31188,31192,20145,31209,31217,31207,31218,31221,27619,31225,31230,24588,31231,31235,31227,31242,31244,28170,31226,31245,26334,31251,31252,29539,31257,31255,20506,31265,31266,27397,31264,31270,19977,31275,31270,30358,31305,31303,27165,31312,31308,25793,31314,31314,25513,31321,31324,21898,31328,31332,25417,31334,31332,27679,31355,31353,24570,31377,31378,27418,31385,31386,15928,31360,31389,16662,31388,31390,26054,31395,31393,28910,31467,31459,19610,31471,31475,16850,31475,31478,30304,31482,31482,28488,31504,31510,17581,31506,31506,25338,31515,31511,30053,31529,31530,20456,31538,31539,31537,31540,31542,20872,31545,31546,17600,31561,31566,24886,31568,31572,18777,31578,31578,30502,31598,31596,20344,31602,31602,30966,31624,31626,21695,31641,31642,21228,31646,31648,27565,31652,31656,23384,31660,31661,25142,31665,31666,21477,31684,31686,21500,31697,31698,16753,31710,31716,29853,31720,31716,27099,31722,31725,31723,31722,31726,23340,31735,31737,31737,31740,31749,21928,31763,31757,17097,31761,31769,27394,31790,31780,25278,31788,31798,28237,31814,31812,31345,31842,31845,31843,31835,31846,25058,31857,31855,16084,31862,31871,16816,31881,31882,20059,31889,31890,25349,31905,31901,20919,31955,31953,24976,31961,31959,31017,31971,31969,16771,31975,31980,22591,31984,31988,24528,32001,31995,17396,32006,32008,19461,32025,32023,21014,32027,32025,23167,32041,32046,25281,32054,32050,20274,32057,32055,18541,32058,32062,18079,32067,32065,16860,32075,32076,21600,32081,32079,22551,32076,32088,20637,32097,32095,24817,32115,32113,20811,32116,32118,26845,32139,32136,17811,32137,32139,24658,32152,32157,27961,32168,32168,24843,32178,32181,32179,32187,32188,18279,32185,32190,23688,32201,32202,24230,32211,32209,23787,32228,32228,28092,32235,32233,18370,32248,32250,25215,32242,32256,22507,32259,32257,29740,32294,32291,23537,32287,32298,20907,32298,32302,20531,32307,32300,25180,32315,32309,20416,32321,32319,30321,32322,32326,19526,32339,32337,18167,32338,32351,32325,32356,32358,26081,32361,32356,27433,32363,32359,25327,32369,32370,30989,32372,32372,25952,32379,32377,30655,32394,32394,20058,32409,32399,30480,32408,32412,20094,32418,32421,19579,32426,32424,17357,32438,32440,29800,32441,32442,23922,32465,32463,29034,32473,32477,28790,32489,32487,18735,32490,32490,16766,32500,32501,32026,32505,32506,22167,32529,32527,16799,32531,32529,25409,32534,32536,28952,32555,32555,19428,32561,32562,24619,32562,32562,20514,32571,32566,29250,32573,32577,23356,32585,32583,28439,32601,32598,24530,32606,32603,19295,32608,32610,28696,32618,32620,29276,32630,32627,28234,32644,32646,17491,32651,32652,22423,32682,32684,30309,32691,32692,23175,32704,32692,23204,32708,32712,18247,32715,32703,29481,32716,32717,32715,32747,32748,30851,32769,32767,32259,32776,32774,26012,32776,32782,28998,32787,32781,32277,32795,32793,28616,32798,32800,22863,32798,32801,25866,32818,32830,18423,32828,32828,29968,32833,32835,21220,32841,32839,17834,32863,32865,27500,32884,32886,26361,32907,32904,18890,32908,32910,18623,32915,32916,21131,32931,32932,20665,32937,32929,21184,32939,32940,22761,32945,32956,18115,32966,32963,32957,32960,32970,24648,32980,32981,16927,32985,32986,28023,32990,32987,32244,32992,32997,31501,33008,33012,17239,33018,33018,27157,33027,33028,27592,33035,33033,26224,33020,33048,17775,33051,33052,23062,33060,33060,30672,33068,33072,18093,33081,33073,29809,33088,33086,27901,33105,33101,19761,33110,33108,22628,33112,33118,33110,33147,33145,16778,33148,33150,26104,33158,33156,20542,33177,33178,32385,33175,33180,22519,33184,33190,20472,33196,33197,20640,33201,33197,21507,33209,33210,25145,33213,33222,23554,33242,33245,27069,33282,33286,23269,33260,33282,17665,33299,33297,29088,33300,33310,20962,33315,33309,32351,33326,33323,33317,33328,33324,19187,33340,33342,33332,33345,33343,27382,33347,33345,28951,33350,33348,17232,33352,33356,32248,33372,33376,17018,33385,33389,26084,33400,33402,26826,33402,33402,26059,33411,33405,24533,33425,33423,23368,33447,33456,25484,33458,33460,32603,33467,33465,22958,33462,33478,26329,33481,33484,26490,33491,33492,33486,33498,33501,20309,33515,33518,32624,33522,33522,25410,33531,33532,18904,33545,33546,32059,33561,33559,22030,33566,33563,33557,33572,33572,32243,33579,33576,31633,33581,33573,26388,33587,33588,26734,33588,33583,26711,33572,33600,29589,33608,33612,18310,33614,33611,31668,33617,33618,28186,33618,33622,20626,33627,33621,20008,33635,33633,23036,33638,33630,32587,33642,33645,21492,33676,33678,32838,33698,33701,33699,33710,33706,25095,33710,33716,33702,33737,33738,28573,33747,33745,25591,33745,33750,22979,33755,33756,27295,33762,33764,17486,33758,33753,33247,33771,33772,24868,33784,33789,22107,33794,33795,32757,33806,33808,27277,33796,33809,24502,33825,33826,33820,33827,33828,29111,33849,33850,33049,33854,33856,30037,33858,33861,24686,33856,33869,26736,33876,33880,24533,33891,33892,17992,33900,33910,26841,33921,33911,20091,33929,33925,17987,33932,33936,20229,33939,33940,26503,33948,33960,24460,33964,33966,20622,33995,33996,28864,34017,34009,21975,34024,34030,34022,34026,34026,19209,34036,34037,29357,34052,34052,24647,34059,34057,28075,34121,34122,34116,34122,34126,33807,34118,34128,27504,34139,34137,17568,34144,34138,22260,34155,34153,19275,34156,34154,20405,34169,34167,23285,34180,34182,26315,34209,34207,30318,34211,34209,21739,34214,34211,30499,34225,34229,18282,34251,34241,22385,34257,34242,27770,34259,34260,27220,34265,34262,22256,34268,34270,20465,34281,34277,30976,34292,34296,24969,34298,34289,30648,34286,34302,20822,34310,34308,25339,34300,34301,29846,34322,34326,31086,34334,34336,22979,34348,34349,32470,34358,34360,30241,34362,34366,19563,34362,34358,21857,34375,34380,18518,34401,34402,18263,34419,34417,32218,34427,34428,21285,34428,34437,17799,34454,34452,25198,34459,34460,24838,34465,34470,19446,34481,34479,24949,34482,34486,28325,34497,34495,18492,34494,34499,28465,34504,34509,24801,34502,34512,33682,34516,34517,25289,34532,34536,34274,34537,34542,28376,34547,34545,19235,34578,34582,32137,34587,34585,23410,34588,34590,24433,34601,34599,21587,34597,34605,24077,34611,34609,30117,34624,34630,20505,34646,34648,25174,34649,34647,27131,34665,34663,22401,34670,34668,29380,34672,34675,28528,34682,34686,20425,34687,34691,26188,34698,34701,24420,34718,34716,34194,34716,34726,22002,34733,34736,29717,34745,34746,34740,34755,34749,18057,34753,34757,25196,34761,34759,26536,34779,34775,34012,34804,34805,30898,34817,34814,20983,34838,34835,34829,34841,34839,21035,34840,34845,33401,34842,34842,28928,34864,34870,22279,34875,34876,18970,34881,34877,24993,34892,34896,25694,34910,34908,21047,34900,34918,27648,34937,34935,22028,34947,34945,33588,34958,34949,21770,34961,34962,32993,34979,34977,21190,35018,35021,35019,35025,35023,33020,35049,35047,31484,35051,35049,34378,35049,35058,24233,35067,35065,23519,35078,35080,24328,35081,35082,30282,35078,35086,23856,35097,35095,30378,35105,35103,33400,35098,35106,34316,35115,35116,29689,35126,35128,30888,35139,35137,22688,35147,35145,33603,35150,35152,30948,35148,35158,27315,35169,35164,30035,35198,35195,35189,35215,35217,19694,35225,35226,21352,35248,35250,34574,35250,35250,22970,35265,35263,34156,35250,35278,18049,35258,35278,25185,35289,35287,23112,35300,35310,20984,35312,35316,23743,35320,35322,20708,35322,35324,23922,35337,35338,20494,35348,35352,21644,35361,35359,29573,35378,35379,28683,35390,35392,20372,35388,35400,24079,35401,35406,22403,35417,35418,35412,35418,35421,31626,35431,35436,25467,35442,35445,20162,35436,35432,30833,35455,35457,35457,35484,35489,24761,35505,35506,32405,35507,35508,19205,35514,35518,33397,35524,35526,20682,35525,35530,27235,35531,35529,33119,35534,35536,30152,35538,35542,29884,35558,35568,31907,35571,35566,22925,35574,35589,35583,35588,35590,32282,35595,35593,32596,35601,35599,34191,35606,35615,31025,35668,35665,33223,35675,35676,33207,35726,35724,22054,35729,35730,20912,35745,35739,20052,35750,35741,24804,35748,35758,31616,35765,35769,23040,35795,35793,21997,35798,35800,18410,35789,35802,28409,35796,35808,20668,35820,35829,27470,35835,35833,27920,35833,35837,20789,35849,35847,32401,35860,35861,25693,35859,35868,25437,35872,35865,26393,35894,35881,24352,35897,35898,34062,35899,35909,30858,35921,35922,35916,35931,35929,26455,35940,35949,20372,35961,35956,21073,35966,35962,35285,35967,35976,29866,35980,35982,32077,35990,35986,21439,35986,35997,19538,36004,36005,33167,36009,36010,36004,36011,36012,30730,36014,36012,25143,36035,36033,31822,36059,36057,24535,36062,36065,29480,36068,36068,30882,36081,36074,34713,36092,36094,36086,36105,36101,31026,36107,36108,25606,36129,36126,29519,36134,36131,19639,36148,36149,32430,36158,36153,31503,36184,36186,33102,36184,36189,34588,36206,36195,33794,36198,36213,30943,36227,36225,23421,36222,36238,30081,36249,36247,29127,36258,36258,29741,36267,36265,25760,36275,36276,20036,36291,36292,19996,36297,36295,28690,36305,36306,34759,36308,36310,32125,36313,36315,26609,36339,36337,33197,36330,36342,23388,36350,36348,33590,36371,36369,29979,36378,36380,30951,36386,36387,29737,36428,36432,32929,36444,36445,36447,36452,36456,20331,36465,36463,35613,36467,36468,23910,36470,36472,19617,36472,36476,29389,36491,36489,26318,36494,36496,24594,36521,36519,21049,36522,36525,36523,36522,36522,35431,36531,36540,29944,36544,36550,21398,36553,36557,20681,36561,36559,22728,36569,36570,31515,36576,36580,34883,36585,36582,30336,36580,36595,28767,36604,36606,19013,36627,36628,32104,36632,36634,33971,36640,36642,34748,36651,36649,32200,36658,36670,28165,36675,36673,26307,36681,36679,19255,36689,36687,27601,36692,36696,31757,36707,36705,32935,36710,36712,21973,36684,36716,30482,36737,36738,36407,36747,36745,28643,36755,36751,26036,36762,36766,22326,36777,36775,20821,36779,36780,25314,36785,36783,22006,36774,36787,22588,36778,36790,36460,36806,36804,27220,36819,36814,20832,36830,36827,31974,36844,36846,19359,36854,36856,32096,36856,36870,31644,36875,36873,23194,36882,36886,31122,36897,36893,29442,36899,36897,25191,36908,36912,18803,36916,36917,20454,36921,36919,34345,36926,36919,21647,36929,36930,30324,36940,36941,36935,36945,36940,24391,36971,36972,23162,36976,36978,19090,36995,36993,21881,37001,36999,26101,37011,37005,29720,37017,37014,22512,37015,37020,32663,37036,37038,25707,37043,37046,23618,37052,37048,34294,37059,37060,26907,37084,37086,35869,37094,37091,26078,37115,37116,35600,37120,37118,29214,37137,37135,21300,37156,37157,33865,37168,37170,24119,37179,37166,25911,37187,37188,30260,37192,37187,19932,37194,37194,27563,37214,37211,25495,37218,37222,29669,37241,37242,19542,37251,37249,28291,37268,37272,34429,37275,37269,33278,37305,37301,25085,37302,37307,19242,37310,37301,30263,37298,37320,20097,37334,37331,19067,37336,37332,20666,37351,37356,25712,37358,37355,37349,37360,37362,21155,37362,37366,33527,37377,37378,29464,37395,37396,26940,37406,37404,21337,37417,37420,37408,37424,37430,33605,37444,37445,19779,37458,37461,37459,37481,37482,27131,37470,37474,33346,37491,37486,27205,37499,37497,34278,37490,37505,37499,37500,37508,31881,37515,37513,18975,37526,37519,26883,37524,37528,30190,37545,37546,32251,37547,37545,18991,37550,37560,19631,37564,37566,24636,37569,37560,32823,37568,37572,19136,37577,37578,19454,37587,37588,34854,37585,37589,33174,37602,37605,29548,37617,37615,34006,37628,37632,36406,37641,37639,26690,37646,37648,31939,37652,37656,28634,37660,37662,22013,37685,37689,24698,37691,37692,22114,37696,37687,34574,37712,37716,32095,37744,37746,25645,37779,37776,25477,37780,37781,37775,37788,37798,19068,37805,37810,35535,37811,37809,19352,37828,37830,31814,37842,37846,23220,37851,37848,22552,37859,37860,22027,37864,37864,33945,37872,37876,28903,37886,37881,25113,37892,37894,37195,37905,37903,33823,37948,37949,29265,37955,37956,30796,37961,37959,21601,37962,37964,35382,37982,37985,34893,37984,37990,28727,37983,37992,35024,37995,37993,29297,38009,38007,19512,38032,38037,33167,38044,38045,38039,38048,38052,33474,38067,38064,21442,38080,38078,19791,38106,38110,30887,38116,38117,38115,38143,38148,28909,38150,38148,25251,38164,38166,32206,38174,38176,35652,38178,38180,31711,38187,38185,27557,38195,38196,26216,38198,38196,35721,38217,38215,26073,38218,38230,32649,38235,38233,25637,38226,38238,19289,38259,38260,36648,38270,38267,21659,38267,38278,24768,38280,38284,19895,38297,38293,36650,38298,38301,26437,38315,38316,31189,38318,38320,36923,38322,38325,30440,38316,38328,25055,38331,38325,30289,38340,38349,37128,38361,38370,24488,38372,38372,38100,38390,38387,20238,38425,38430,36645,38442,38446,23340,38436,38448,29532,38451,38449,30005,38457,38455,37440,38448,38460,33488,38499,38493,20275,38538,38541,38539,38555,38553,22303,38558,38555,38549,38562,38562,34251,38555,38567,38543,38588,38588,22172,38601,38602,23298,38606,38608,38331,38608,38604,29249,38627,38628,32309,38610,38638,29599,38649,38645,36685,38651,38652,36591,38667,38664,33671,38665,38669,21972,38672,38676,37582,38691,38683,32166,38697,38698,33472,38705,38703,37302,38704,38708,34674,38708,38712,23934,38721,38719,37759,38726,38724,29906,38732,38736,23632,38745,38736,20734,38747,38745,24273,38762,38765,24075,38778,38780,23214,38785,38789,30215,38798,38801,38795,38819,38817,30471,38828,38828,37701,38833,38838,24569,38848,38850,23661,38847,38838,23356,38865,38866,27407,38870,38872,33001,38889,38890,26445,38898,38902,26815,38912,38914,24190,38915,38920,25186,38921,38922,38916,38931,38932,33245,38948,38952,35439,38956,38954,30864,38969,38967,21563,38972,38976,26193,38990,38987,35395,39017,39013,33763,39018,39021,24508,39038,39040,26546,39041,39039,22536,39042,39046,33621,39076,39077,28472,39086,39083,39077,39092,39096,30051,39098,39101,36150,39105,39106,20557,39110,39112,30930,39108,39118,25086,39128,39132,24278,39132,39137,34512,39151,39156,25232,39158,39156,35010,39161,39162,39156,39175,39177,39177,39180,39190,35745,39182,39195,36081,39206,39203,39197,39210,39210,26512,39225,39226,39220,39227,39225,23379,39230,39232,29629,39232,39238,36389,39234,39234,31295,39249,39247,22058,39291,39289,33034,39294,39299,38586,39303,39308,32642,39315,39316,36258,39321,39319,22160,39339,39337,31163,39340,39342,23892,39348,39356,27324,39364,39365,30496,39369,39370,35643,39351,39371,38401,39378,39382,38278,39395,39393,36507,39402,39406,32961,39417,39415,21067,39436,39429,23903,39441,39442,30777,39449,39450,37321,39459,39457,20975,39497,39498,23602,39498,39502,30046,39506,39507,39501,39508,39510,26516,39518,39515,39509,39539,39540,20129,39544,39548,26926,39561,39562,25866,39566,39559,21015,39579,39580,39574,39604,39606,21811,39617,39618,19982,39618,39622,21113,39628,39629,29962,39657,39655,30533,39664,39658,34504,39664,39670,20353,39673,39677,29071,39698,39702,20563,39703,39708,38547,39712,39717,38397,39724,39726,35383,39731,39729,29299,39747,39748,29632,39758,39756,20842,39756,39768,31398,39777,39775,26299,39780,39789,20451,39796,39797,20740,39819,39815,23010,39825,39823,27913,39823,39825,35544,39832,39838,34688,39810,39840,37627,39842,39845,36920,39854,39850,32268,39858,39861,32102,39867,39861,35127,39875,39876,27572,39880,39882,27660,39880,39885,28653,39899,39897,32944,39926,39921,23450,39932,39934,20329,39950,39944,21336,39969,39967,38660,39976,39970,28841,39978,39981,39971,39987,39985,36619,39998,40008,30730,40011,40009,29898,40012,40030,40001,40035,40029,35214,40033,40038,38943,40060,40061,40059,40084,40085,21667,40091,40089,30961,40096,40094,23464,40108,40109,29259,40121,40122,34321,40122,40124,25313,40122,40122,37548,40140,40149,24171,40148,40148,34765,40161,40157,38283,40166,40159,29838,40167,40176,23176,40187,40185,33230,40190,40192,25310,40207,40211,39490,40228,40229,38577,40231,40236,21847,40238,40236,37334,40251,40249,33918,40275,40276,36883,40281,40282,40276,40286,40283,40277,40338,40341,40331,40348,40349,24291,40352,40352,28961,40358,40345,27273,40385,40383,25780,40420,40421,32670,40425,40423,25846,40415,40425,24419,40428,40430,27145,40457,40458,27701,40468,40470,21751,40481,40479,25023,40482,40482,32754,40491,40492,37633,40497,40494,22620,40505,40506,36181,40513,40509,33044,40526,40523,40517,40529,40527,26103,40540,40537,20538,40552,40556,28279,40574,40571,23305,40578,40581,36766,40578,40590,23143,40595,40593,27420,40587,40606,32138,40625,40623,30140,40635,40626,20898,40632,40630,24068,40691,40689,40242,40694,40692,32615,40697,40693,22810,40707,40705,26989,40737,40734,26215,40737,40750,26491,40756,40757,40755,40761,40758,25783,40761,40769,34197,40785,40783,21438,40788,40798,20627,40811,40812,24806,40816,40810,24908,40818,40821,40819,40827,40828,23012,40838,40836,29237,40842,40842,29258,40838,40848,31508,40851,40849,25624,40865,40863,24590,40873,40877,23940,40881,40882,24907,40892,40894,37119,40900,40901,38313,40924,40926,40256,40931,40929,39591,40937,40938,33285,40947,40937,27494,40958,40960,36045,40971,40969,25152,40988,40992,36660,41009,41010,30297,41012,41016,38780,41018,41022,25426,41028,41034,35768,41042,41045,31745,41049,41050,26951,41054,41050,25119,41075,41073,28407,41078,41072,40794,41108,41110,40826,41115,41112,36922,41121,41127,20741,41139,41133,25057,41140,41141,25489,41147,41148,41142,41139,41150,31429,41174,41171,32635,41176,41174,37566,41178,41182,34579,41187,41179,26633,41198,41200,32563,41200,41202,29148,41211,41209,40807,41219,41220,22592,41225,41221,24158,41224,41229,39520,41228,41228,39339,41241,41239,29410,41252,41256,40905,41258,41262,21896,41267,41264,25657,41264,41278,34193,41297,41298,27828,41331,41329,40337,41339,41340,31592,41344,41350,27913,41355,41353,38481,41378,41380,28687,41385,41386,39457,41383,41385,31412,41392,41397,21094,41409,41410,38845,41407,41411,21880,41441,41442,41436,41451,41448,23622,41453,41465,24950,41476,41477,36172,41478,41490,34900,41505,41503,22418,41510,41512,27579,41512,41517,26294,41499,41510,26353,41536,41528,21498,41538,41541,29025,41546,41548,21142,41577,41578,33637,41588,41590,41582,41595,41596,25029,41601,41597,28645,41606,41608,22146,41609,41610,40112,41612,41612,40597,41618,41613,39277,41625,41626,38959,41628,41632,34077,41644,41645,24249,41649,41645,40974,41656,41658,27113,41667,41665,28432,41678,41680,40406,41682,41685,41683,41713,41718,28988,41726,41728,32489,41732,41736,33331,41752,41758,41302,41742,41758,21110,41769,41767,40857,41774,41776,28975,41798,41796,37527,41788,41805,25666,41811,41809,33303,41841,41839,37269,41846,41843,41837,41836,41848,29500,41860,41862,35189,41866,41878,32276,41884,41886,30353,41891,41892,41155,41894,41892,38726,41898,41901,27030,41908,41909,41907,41922,41926,33194,41939,41937,33233,41942,41946,40004,41948,41950,41942,41955,41956,35105,41953,41958,38417,41966,41963,41957,41979,41977,33173,41977,41980,39620,41988,41997,30341,42007,42012,25317,42014,42016,41727,42017,42018,22334,42018,42021,42019,42038,42042,35790,42055,42060,32864,42064,42067,31233,42068,42068,38165,42081,42079,36671,42086,42083,42077,42099,42100,26708,42129,42130,22755,42137,42135,31828,42155,42156,41262,42158,42168,39075,42177,42161,35470,42171,42178,35274,42174,42186,35833,42178,42192,39181,42195,42192,33616,42206,42208,25189,42219,42216,26446,42218,42218,24675,42225,42226,41308,42232,42235,21824,42254,42256,27944,42270,42270,35421,42281,42282,38525,42291,42292,26526,42297,42298,29826,42304,42302,29452,42321,42318,37569,42328,42322,35501,42332,42332,33700,42347,42348,41579,42352,42358,30711,42368,42372,25617,42377,42375,33587,42385,42387,29306,42395,42396,33251,42401,42399,26121,42402,42406,30921,42395,42406,34944,42423,42428,24349,42435,42436,32230,42441,42439,29817,42448,42450,32143,42446,42455,36096,42459,42457,28461,42460,42461,42459,42462,42466,33449,42470,42472,39182,42482,42486,33118,42489,42487,42134,42497,42495,33589,42507,42503,41205,42531,42529,28048,42555,42553,23138,42566,42568,40558,42569,42567,32911,42570,42570,32664,42587,42585,26561,42609,42607,35865,42638,42635,42629,42641,42642,27387,42638,42646,24225,42660,42665,29827,42675,42676,38324,42681,42679,34075,42686,42678,21718,42692,42694,29768,42698,42700,21824,42698,42702,33987,42703,42708,26009,42700,42718,24773,42724,42725,37668,42734,42736,39247,42736,42741,26987,42745,42750,37845,42762,42765,37821,42770,42771,24335,42782,42786,34696,42788,42788,26894,42795,42796,42790,42819,42817,39582,42827,42828,32006,42828,42837,23627,42818,42840,39641,42851,42852,38687,42849,42858,38482,42858,42862,39068,42897,42898,22968,42895,42897,39485,42921,42911,27243,42926,42919,38061,42932,42932,42644,42940,42942,26521,42950,42947,35469,42950,42956,24271,42964,42965,29612,42976,42978,31641,42987,42981,29404,42998,43001,42995,43011,43012,25052,43017,43015,25405,43035,43033,40246,43046,43048,25533,43049,43047,39322,43060,43058,40513,43065,43066,38385,43088,43090,38709,43098,43101,43099,43115,43113,33081,43131,43127,35076,43140,43150,28114,43156,43158,34751,43172,43174,43166,43187,43183,36760,43178,43200,29702,43204,43206,39155,43218,43221,39112,43235,43236,24655,43259,43257,28419,43258,43269,43259,43281,43279,38919,43288,43290,34735,43310,43312,40552,43308,43317,38802,43308,43320,29474,43329,43327,40546,43374,43390,27050,43395,43393,33130,43386,43396,41165,43401,43402,32462,43408,43402,21982,43425,43426,42961,43430,43438,34169,43449,43447,23733,43454,43452,25956,43475,43480,32217,43482,43485,38995,43497,43495,24344,43515,43516,29167,43539,43537,33814,43540,43541,37975,43571,43572,32563,43574,43576,39567,43577,43575,36760,43580,43590,39505,43595,43593,25494,43602,43606,33614,43595,43607,43583,43611,43612,33869,43625,43626,23387,43628,43630,42940,43646,43644,39029,43649,43650,31013,43659,43657,42390,43667,43665,31089,43685,43688,25082,43698,43707,40875,43712,43712,25396,43718,43716,24256,43746,43750,34502,43756,43757,31341,43772,43774,33589,43779,43780,28286,43780,43781,26033,43785,43782,29567,43783,43788,26852,43790,43792,22460,43770,43800,38713,43851,43852,33682,43864,43866,40905,43886,43888,35759,43888,43882,27605,43910,43906,40419,43931,43929,28743,43938,43942,26709,43945,43950,37226,43955,43958,41983,43951,43961,31920,43958,43964,36514,43971,43972,39500,43985,43986,25031,43974,43989,25746,43995,43985,43240,44006,44016,27001,44019,44020,25060,44025,44022,43513,44023,44025,44025,44030,44030,40183,44051,44049,34020,44057,44055,41061,44068,44069,38223,44082,44084,35704,44076,44077,37163,44095,44100,27234,44104,44110,34808,44113,44118,24852,44121,44119,27622,44126,44128,25052,44129,44130,44124,44148,44157,24048,44169,44167,28055,44177,44175,22840,44187,44184,24361,44195,44198,29090,44198,44201,30833,44202,44206,42981,44219,44217,32008,44246,44248,30476,44252,44252,23929,44260,44262,41855,44265,44266,29079,44267,44265,31561,44270,44267,34723,44272,44278,43581,44274,44274,35321,44291,44289,32613,44332,44350,27884,44355,44356,33875,44369,44370,33187,44379,44377,22426,44380,44381,38428,44387,44385,30976,44414,44416,22776,44436,44448,43275,44451,44452,32208,44481,44482,44476,44478,44487,44479,44492,44496,40423,44499,44497,40698,44505,44503,23167,44506,44518,36891,44529,44527,25071,44531,44532,40441,44534,44526,34804,44538,44541,30983,44547,44541,26924,44560,44562,29486,44577,44578,32744,44584,44580,42198,44612,44610,36621,44619,44617,25247,44618,44621,38712,44630,44627,25261,44622,44626,29082,44642,44645,44643,44649,44639,29349,44654,44650,35664,44681,44679,39812,44682,44686,22753,44697,44695,22700,44699,44700,33644,44704,44710,32919,44726,44718,33328,44739,44737,24989,44750,44748,40201,44765,44768,37426,44768,44768,31254,44774,44776,35882,44787,44788,25164,44795,44793,38114,44798,44808,42414,44817,44818,39060,44833,44837,23972,44838,44842,40321,44841,44849,44833,44865,44863,29181,44872,44872,35745,44882,44885,22724,44888,44892,35048,44907,44905,41382,44912,44912,36869,44920,44920,24924,44937,44932,36433,44948,44950,23277,44956,44958,31149,44961,44959,26831,44968,44958,24561,44980,44981,37289,44985,44986,37946,45004,45006,39082,45011,45012,44248,45051,45049,28099,45059,45057,37766,45075,45072,42647,45081,45082,36140,45112,45118,43617,45114,45118,31700,45115,45123,41102,45129,45125,28913,45134,45124,40344,45137,45138,30734,45158,45160,34176,45173,45171,41353,45179,45180,45174,45180,45187,27300,45195,45196,31103,45230,45227,30727,45242,45246,38021,45256,45254,41101,45258,45261,45259,45278,45276,44980,45275,45284,34625,45291,45292,29347,45305,45306,45300,45315,45316,27826,45316,45317,45315,45326,45315,26229,45332,45336,32816,45339,45329,42292,45337,45342,34743,45350,45360,44156,45374,45372,37182,45387,45379,30421,45400,45402,27129,45411,45406,42709,45424,45426,23344,45426,45426,26654,45436,45433,36560,45468,45480,35722,45489,45487,35717,45494,45491,33499,45498,45501,45499,45521,45519,30815,45531,45532,41057,45531,45540,26200,45548,45552,44878,45554,45556,44882,45566,45568,40897,45585,45586,31949,45587,45588,28142,45592,45595,44995,45611,45609,29096,45619,45630,26884,45630,45632,36166,45657,45650,41259,45665,45663,29332,45668,45668,32101,45675,45673,37666,45684,45689,25859,45687,45696,38298,45705,45702,25083,45734,45730,38513,45748,45750,30312,45755,45756,40134,45758,45761,45755,45762,45766,26371,45777,45767,24414,45812,45816,43698,45819,45817,27262,45820,45822,30323,45825,45826,40257,45828,45825,44852,45834,45838,31158,45848,45848,27311,45853,45862,24212,45867,45868,26797,45882,45886,39288,45891,45889,39520,45937,45940,30371,45947,45945,33945,45950,45952,37935,45952,45958,32873,45969,45967,44216,45977,45978,28690,45987,45988,35560,46019,46020,31211,46025,46023,30373,46046,46038,26786,46048,46046,25364,46059,46057,38464,46068,46068,33248,46089,46087,38291,46091,46092,32682,46097,46095,39615,46093,46101,46085,46131,46132,28930,46131,46138,39758,46145,46146,25219,46148,46152,35048,46168,46166,27178,46179,46177,35131,46180,46181,46179,46185,46177,36061,46182,46197,46191,46216,46218,43375,46227,46224,44536,46235,46233,41915,46259,46260,23371,46264,46269,38257,46268,46272,34133,46276,46278,39624,46299,46297,29134,46305,46303,28139,46307,46305,25582,46324,46326,32791,46334,46332,44575,46347,46342,42092,46348,46350,39860,46374,46378,35780,46396,46397,46395,46408,46410,39497,46432,46437,42373,46434,46434,27654,46444,46445,46443,46445,46449,41734,46454,46452,43174,46468,46470,41420,46475,46473,26312,46460,46486,44904,46497,46495,24692,46505,46503,30550,46500,46507,45147,46518,46521,43829,46547,46545,36157,46552,46558,24905,46564,46565,30664,46571,46569,42450,46587,46582,42838,46585,46587,23581,46598,46594,37174,46613,46617,44101,46628,46628,41892,46633,46637,34453,46641,46637,37192,46634,46648,26508,46658,46662,38255,46662,46677,45842,46670,46680,38568,46684,46685,46683,46689,46687,39580,46698,46700,25022,46721,46722,40260,46722,46725,46715,46745,46743,23732,46740,46749,38211,46755,46753,33210,46766,46763,46757,46769,46767,33203,46804,46806,24365,46809,46805,41529,46814,46811,41548,46817,46812,24486,46827,46828,29540,46828,46829,29341,46851,46845,25849,46855,46860,35569,46865,46863,26956,46875,46873,34515,46886,46884,33650,46890,46899,26924,46908,46917,37138,46931,46932,36682,46952,46956,37504,46988,46988,32806,46995,46996,40850,47010,47010,31573,47012,47038,26628,47049,47046,40653,47054,47056,35069,47057,47058,31564,47082,47085,47083,47091,47089,46659,47104,47107,46497,47116,47117,45329,47121,47119,30269,47126,47117,37567,47132,47134,41132,47137,47140,36780,47145,47143,30463,47147,47141,43332,47144,47156,26737,47187,47181,45094,47202,47204,35549,47215,47217,40587,47235,47233,44006,47241,47249,31356,47263,47261,34884,47272,47277,31867,47282,47286,30338,47287,47292,29331,47294,47291,31326,47298,47302,24970,47307,47300,36347,47311,47315,36456,47337,47338,47332,47338,47349,24355,47348,47348,42696,47361,47359,36657,47379,47380,29852,47385,47383,47010,47387,47388,23938,47404,47406,41033,47414,47416,30547,47417,47415,23898,47419,47428,36693,47438,47435,47429,47457,47458,24336,47489,47490,44244,47492,47494,26516,47498,47499,47497,47505,47503,38252,47510,47508,31881,47504,47520,29097,47524,47526,35241,47531,47532,34111,47538,47535,24194,47561,47562,30316,47552,47568,44979,47579,47577,29004,47580,47590,25303,47596,47598,42246,47603,47608,42600,47620,47621,47619,47619,47626,36643,47632,47638,26912,47640,47642,40519,47654,47651,28471,47657,47658,29906,47678,47680,26764,47697,47694,35869,47699,47700,40941,47700,47709,28539,47703,47708,31546,47715,47716,43442,47732,47734,37040,47738,47733,28355,47740,47741,47739,47774,47769,46327,47776,47778,44214,47784,47778,25128,47792,47796,38175,47802,47806,32752,47802,47800,36600,47817,47813,29004,47835,47831,26959,47841,47842,35977,47850,47854,24323,47867,47868,36099,47852,47876,46952,47896,47902,36964,47908,47910,44831,47912,47916,41117,47931,47929,46754,47937,47938,38673,47945,47943,38585,47944,47949,35366,47961,47962,28626,47966,47963,47957,47970,47970,35515,47979,47974,27256,48014,48016,39230,48018,48006,39800,48027,48021,40222,48032,48046,30905,48068,48072,31604,48073,48077,31403,48084,48089,30351,48107,48105,41128,48112,48117,41509,48108,48120,28355,48125,48129,38135,48152,48154,41490,48160,48158,34731,48173,48177,44807,48185,48186,40059,48186,48186,30606,48195,48193,34515,48219,48215,47059,48232,48232,33840,48244,48245,32980,48257,48255,38080,48265,48270,40466,48278,48280,43232,48297,48295,42653,48304,48310,48302,48308,48312,48002,48327,48332,34674,48338,48340,29790,48350,48352,25766,48369,48366,33067,48378,48381,48379,48392,48394,39035,48402,48406,26131,48392,48398,39919,48411,48409,46445,48435,48433,29367,48446,48444,46270,48458,48462,44000,48470,48472,42834,48472,48478,29312,48464,48478,33727,48482,48486,47077,48489,48487,34981,48494,48492,44812,48520,48522,40596,48522,48525,34075,48531,48529,31450,48537,48535,42777,48539,48540,37897,48561,48557,47832,48569,48570,36188,48579,48588,44652,48590,48587,45796,48609,48610,32878,48617,48613,26111,48618,48615,47859,48642,48642,46056,48642,48640,37237,48659,48657,36619,48658,48668,31069,48675,48676,40064,48676,48677,43172,48725,48730,30965,48731,48729,38665,48748,48749,48747,48755,48753,45082,48758,48756,30253,48762,48766,38128,48777,48775,41865,48775,48780,43730,48785,48783,33906,48796,48797,37818,48806,48803,48797,48812,48814,45035,48819,48820,37862,48818,48822,43255,48844,48846,29183,48854,48851,32875,48857,48855,44505,48867,48864,42699,48868,48869,24728,48881,48879,38356,48855,48872,46792,48905,48906,46136,48945,48946,48940,48950,48948,40344,48968,48972,45963,48987,48988,38762,48985,48989,38716,48990,49000,40738,48990,48996,25010,49017,49015,45449,49018,49022,46127,49023,49030,40636,49035,49033,44789,49041,49039,43188,49052,49056,39309,49067,49068,32044,49070,49080,34628,49098,49098,37207,49107,49105,33641,49115,49116,25424,49118,49120,43733,49121,49119,37322,49137,49138,38377,49155,49152,34802,49166,49168,35300,49169,49170,33733,49172,49174,47757,49190,49186,46513,49186,49196,45713,49194,49198,33068,49204,49205,45887,49209,49207,32254,49218,49222,38606,49251,49249,43835,49259,49257,46480,49275,49273,26712,49276,49272,43012,49292,49294,36111,49305,49293,45416,49329,49327,39900,49331,49329,28444,49328,49330,43354,49361,49362,44925,49362,49365,39079,49356,49366,44953,49380,49390,28511,49388,49392,25335,49406,49403,49397,49409,49410,43356,49412,49412,38659,49427,49425,27773,49430,49427,26127,49441,49450,28037,49456,49451,30359,49458,49461,32467,49466,49476,33940,49478,49475,49469,49497,49495,27389,49521,49522,44113,49526,49528,44829,49521,49529,49513,49527,49536,31783,49545,49543,27116,49543,49548,48251,49548,49557,33849,49592,49592,40614,49600,49598,29825,49611,49609,48353,49624,49626,30852,49628,49628,27663,49636,49637,32045,49660,49661,49659,49665,49663,35014,49667,49665,40306,49664,49680,26405,49694,49692,32921,49704,49702,28138,49722,49725,49723,49737,49732,44053,49739,49740,48212,49744,49740,34505,49755,49753,29424,49780,49782,40233,49785,49783,45577,49783,49788,25766,49788,49798,31480,49804,49806,32124,49805,49809,34569,49818,49818,28121,49819,49830,28689,49841,49842,26448,49851,49852,27228,49854,49869,49863,49875,49873,37283,49889,49887,38705,49912,49918,38692,49898,49917,49883,49924,49925,49919,49934,49931,39765,49932,49937,45043,49938,49941,49939,49952,49954,38964,49984,49990,34536,49988,49988,36062,49996,49993,36978,50019,50020,50014,50020,50022,39725,50028,50026,35784,50041,50046,39163,50049,50046,27862,50051,50052,37338,50067,50068,34473,50075,50076,45399,50082,50086,40006,50091,50088,33148,50099,50097,49294,50094,50109,50103,50116,50117,50115,50121,50122,29841,50126,50128,43702,50129,50127,32113,50145,50146,29812,50150,50147,39996,50152,50158,45366,50174,50176,26300,50202,50205,37343,50208,50220,45023,50225,50223,37029,50220,50228,27812,50258,50259,50253,50260,50261,48726,50270,50267,41061,50284,50286,45318,50289,50290,43956,50308,50310,25819,50315,50312,49819,50322,50322,47892,50331,50332,31976,50339,50337,42673,50356,50357,50355,50361,50362,34649,50372,50376,44870,50380,50381,32021,50385,50381,30105,50409,50406,49861,50414,50411,47117,50418,50421,37270,50435,50431,25866,50457,50458,42533,50454,50459,41484,50492,50496,36424,50498,50501,34429,50510,50508,30427,50524,50525,50519,50537,50535,38391,50538,50542,35497,50547,50541,27326,50548,50550,50233,50579,50580,39499,50573,50586,41596,50584,50589,34087,50588,50592,26449,50596,50598,41000,50625,50623,25979,50644,50645,26551,50649,50650,41952,50660,50669,26891,50681,50682,50676,50704,50706,45182,50721,50718,49068,50739,50740,28510,50750,50752,39774,50762,50766,38749,50762,50772,27150,50774,50771,36989,50787,50785,40054,50819,50817,41439,50826,50826,30908,50836,50838,30653,50846,50844,48200,50838,50853,32990,50865,50866,40928,50870,50866,29597,50889,50885,47150,50891,50892,43160,50907,50908,50902,50921,50922,31950,50918,50920,42833,50928,50947,44911,50955,50953,44272,50966,50963,50957,50969,50967,50580,50987,50985,41764,50990,50992,29297,50994,50994,30917,51028,51030,29818,51041,51042,30270,51042,51046,43008,51057,51055,43363,51059,51060,42845,51060,51070,33195,51099,51108,39597,51125,51129,31172,51131,51132,36778,51134,51129,35927,51148,51149,36445,51152,51154,47246,51155,51166,43076,51188,51190,47089,51195,51187,30959,51187,51189,33515,51201,51199,50563,51212,51216,38869,51227,51228,36253,51216,51233,37381,51224,51240,41348,51254,51256,30626,51258,51261,34676,51281,51279,46692,51282,51285,51283,51302,51305,51303,51326,51324,28338,51339,51340,51334,51338,51341,51331,51345,51343,37882,51339,51346,29555,51324,51358,36924,51378,51381,51379,51402,51406,50690,51411,51412,47171,51417,51415,48935,51419,51420,46584,51425,51426,33403,51424,51430,47569,51435,51432,50502,51436,51433,30174,51446,51444,30638,51459,51457,37625,51470,51467,35766,51472,51477,28324,51464,51478,36296,51484,51486,39036,51498,51502,27446,51505,51510,34580,51511,51516,45268,51518,51520,45198,51537,51538,42061,51540,51549,36288,51561,51559,33015,51567,51576,47092,51579,51577,44285,51590,51586,27603,51592,51598,44072,51604,51606,32990,51611,51609,26327,51616,51629,39763,51632,51636,50571,51640,51645,30770,51657,51649,35307,51666,51670,39291,51673,51678,30497,51681,51679,41425,51681,51689,34612,51710,51706,42691,51706,51717,35614,51714,51718,47016,51747,51745,33772,51762,51762,39984,51750,51766,28683,51784,51786,41309,51794,51795,34746,51801,51802,41067,51807,51812,29040,51825,51823,34212,51827,51825,51320,51832,51838,27888,51842,51850,45646,51856,51851,41790,51867,51857,44581,51864,51859,35005,51891,51886,31509,51897,51895,43375,51896,51905,42771,51903,51908,34965,51926,51921,45104,51938,51936,33200,51947,51945,40496,51969,51970,39077,51971,51972,51151,51974,51976,33537,51984,51982,35432,51992,52006,44665,52019,52017,39143,52025,52026,35108,52049,52047,40756,52050,52050,49013,52065,52063,42954,52067,52068,41826,52064,52078,41781,52098,52101,52099,52118,52115,52109,52122,52126,49124,52145,52143,44306,52148,52150,40698,52161,52162,39023,52172,52176,28122,52178,52180,28647,52180,52182,44586,52176,52180,40268,52184,52200,46708,52218,52221,34293,52231,52235,48847,52236,52236,52210,52251,52252,46552,52257,52245,43253,52265,52266,52260,52286,52288,43330,52284,52289,42016,52299,52294,51696,52310,52307,30146,52304,52320,47622,52355,52358,28483,52358,52362,52344,52356,52358,50272,52377,52378,49810,52385,52386,45789,52380,52388,40163,52430,52432,31887,52451,52449,51995,52454,52451,49747,52482,52482,39696,52491,52500,27307,52504,52510,28612,52515,52511,32464,52526,52523,52517,52539,52540,45653,52540,52542,30071,52550,52548,49860,52554,52554,50303,52564,52565,52563,52569,52566,42415,52577,52572,49320,52578,52582,44395,52598,52608,28702,52624,52620,51978,52618,52630,41479,52636,52637,52635,52665,52663,32868,52670,52666,50520,52689,52687,31262,52694,52696,30819,52707,52708,45603,52688,52709,27839,52718,52716,28804,52722,52722,28078,52731,52729,37759,52744,52746,30461,52755,52753,34759,52766,52761,51298,52778,52781,52779,52802,52804,49469,52811,52812,39817,52814,52816,44518,52835,52833,39891,52853,52858,30636,52850,52859,38349,52876,52878,30897,52881,52879,38001,52886,52880,29129,52898,52899,52897,52900,52901,38242,52908,52918,34050,52932,52936,29372,52948,52950,29695,52952,52952,41398,52960,52954,45941,52962,52965,52963,52971,52969,46099,52979,52980,51763,52996,52994,40493,53001,52999,44042,53012,53014,35010,53044,53045,27313,53045,53048,35622,53067,53065,48916,53075,53076,50322,53082,53085,53083,53058,53088,34721,53091,53092,50859,53099,53100,32404,53108,53112,47333,53115,53113,28531,53126,53128,38670,53145,53146,30289,53143,53148,35954,53147,53156,46763,53169,53170,48565,53155,53171,49287,53187,53188,46605,53195,53193,31752,53198,53195,53189,53208,53230,37258,53228,53232,34161,53236,53238,45917,53265,53263,46483,53262,53266,50668,53272,53278,41917,53270,53270,34812,53297,53295,38727,53307,53301,27768,53321,53319,30154,53322,53324,42727,53346,53346,38054,53356,53357,52435,53372,53372,39744,53379,53380,29714,53394,53394,39557,53402,53405,53403,53409,53407,42544,53417,53415,30159,53435,53436,30309,53438,53436,32629,53451,53449,36781,53476,53478,51225,53500,53501,34581,53505,53506,47738,53524,53525,53523,53547,53548,42415,53548,53549,33763,53550,53550,30483,53578,53589,33693,53588,53592,32222,53595,53593,52044,53606,53608,47985,53601,53609,27407,53612,53616,31561,53620,53621,53619,53623,53621,30991,53630,53632,27294,53628,53638,47011,53651,53652,47442,53654,53652,31526,53678,53675,53669,53691,53692,33623,53697,53695,28092,53715,53716,36983,53713,53718,28206,53719,53729,29169,53742,53757,53751,53771,53772,34710,53774,53771,42831,53778,53782,32552,53785,53790,27401,53811,53805,28837,53817,53814,48668,53824,53827,40011,53846,53843,53837,53852,53852,49534,53859,53860,53342,53850,53880,43513,53884,53885,41551,53889,53883,42377,53894,53896,53127,53897,53895,37119,53915,53916,34912,53918,53921,53915,53922,53925,53923,53937,53933,43058,53944,53950,53942,53956,53957,47291,53985,53986,51795,53990,53984,32327,53990,53998,38898,54009,54004,47801,54008,54012,53278,54035,54033,33218,54038,54044,34837,54057,54058,35508,54081,54079,33127,54088,54086,31288,54098,54099,54097,54108,54120,41494,54128,54132,31507,54137,54135,53333,54145,54149,39340,54161,54159,49878,54162,54165,39230,54179,54177,29314,54183,54188,53577,54212,54216,41596,54249,54247,35571,54267,54264,52348,54272,54276,46093,54282,54285,54283,54291,54288,52801,54300,54310,35318,54316,54317,46010,54321,54319,53550,54329,54327,48975,54345,54343,36691,54354,54358,51839,54362,54366,43976,54365,54370,51692,54372,54370,51708,54398,54400,32412,54401,54399,42818,54402,54406,40433,54411,54406,37262,54417,54415,44995,54419,54420,54414,54435,54432,40155,54441,54439,27730,54446,54442,36474,54467,54465,28084,54491,54492,28709,54494,54483,52734,54496,54492,37260,54496,54501,47550,54512,54512,41098,54518,54514,31723,54537,54533,31098,54539,54537,45092,54544,54538,52356,54556,54558,53941,54561,54559,52815,54572,54574,54566,54571,54578,52377,54578,54582,41655,54579,54598,52577,54614,54616,49252,54618,54620,35656,54626,54627,38672,54625,54629,32685,54642,54642,48318,54665,54663,30127,54668,54672,48898,54672,54667,48374,54707,54705,54186,54708,54712,44310,54710,54712,45297,54724,54726,51959,54745,54749,54741,54762,54765,36070,54771,54766,49710,54777,54775,37806,54785,54786,40532,54796,54798,31708,54827,54828,54822,54830,54827,51648,54845,54849,44707,54867,54868,49807,54875,54873,49718,54878,54880,47900,54905,54906,38476,54915,54909,41903,54916,54918,42837,54939,54940,50581,54947,54948,54942,54952,54958,31117,54959,54970,30370,54976,54974,42920,54978,54978,48837,54998,54996,40914,55002,54998,38608,55015,55020,28224,55043,55048,45962,55049,55050,35693,55047,55056,38627,55059,55060,33619,55070,55072,38454,55066,55078,37766,55098,55102,48476,55107,55098,35765,55112,55114,40725,55122,55125,40534,55142,55145,55143,55161,55162,49605,55161,55169,38724,55194,55194,51398,55202,55206,44099,55211,55209,48748,55214,55216,50697,55217,55218,28415,55227,55223,38844,55241,55242,50554,55238,55248,51344,55253,55249,46182,55280,55288,29304,55310,55308,52824,55329,55330,47533,55327,55331,37793,55334,55336,38163,55337,55335,31052,55336,55339,55331,55344,55342,46608,55371,55372,45800,55375,55380,41076,55393,55398,44143,55409,55410,46072,55426,55437,42340,55403,55440,47380,55454,55451,51566,55467,55460,34598,55482,55482,47865,55495,55497,55497,55500,55509,45652,55526,55524,42741,55539,55535,44080,55545,55541,29580,55577,55578,45669,55587,55585,39396,55601,55599,32874,55596,55596,55570,55617,55615,34176,55619,55620,39788,55624,55629,38577,55628,55630,35265,55636,55637,46470,55659,55657,37283,55660,55661,28880,55665,55663,51291,55670,55672,41377,55670,55680,30307,55689,55690,44290,55694,55692,35089,55708,55710,54042,55715,55713,45647,55718,55720,35341,55731,55727,41119,55761,55757,32202,55785,55782,44917,55790,55787,29668,55792,55797,28837,55804,55805,28470,55811,55809,31826,55814,55805,48937,55817,55815,33154,55818,55821,45481,55827,55825,33851,55832,55836,49246,55841,55839,42336,55835,55846,46684,55864,55870,37071,55886,55883,55877,55892,55896,41446,55899,55900,49020,55892,55902,43803,55900,55920,43101,55924,55925,35633,55925,55929,52723,55931,55932,48082,55947,55945,28239,55962,55966,42501,55985,55983,36179,55995,55993,37684,56001,56002,43720,56006,56001,43639,56032,56038,56030,56034,56034,40523,56051,56049,49665,56078,56069,49974,56082,56085,54608,56091,56089,50569,56097,56093,42982,56094,56099,44663,56108,56110,51606,56121,56119,43350,56129,56130,54390,56143,56141,55201,56164,56165,55693,56169,56170,29334,56176,56174,54503,56184,56196,52594,56202,56205,56203,56202,56202,54847,56235,56236,51506,56236,56237,42826,56246,56244,51793,56260,56261,56259,56265,56263,47807,56267,56268,40885,56289,56297,47088,56305,56310,48710,56331,56328,44573,56356,56358,41399,56366,56363,56357,56372,56374,53649,56380,56382,43205,56390,56392,48024,56388,56400,31874,56414,56411,37285,56428,56429,30540,56435,56436,43979,56438,56442,41908,56451,56447,28655,56465,56466,32208,56468,56470,41277,56475,56473,28783,56473,56478,31461,56486,56480,30320,56498,56499,56497,56500,56502,35604,56507,56508,39742,56506,56510,29316,56524,56525,47508,56529,56527,29045,56528,56532,35775,56538,56541,56539,56558,56558,44961,56572,56590,56576,56595,56590,45525,56596,56597,56595,56585,56609,55822,56627,56628,56622,56630,56628,31538,56657,56655,47043,56658,56661,56659,56668,56670,45827,56678,56675,56669,56682,56686,44288,56699,56697,53689,56704,56710,48465,56708,56710,41674,56729,56730,30326,56727,56736,51769,56745,56743,47524,56764,56766,31734,56771,56772,42713,56777,56775,49583,56778,56781,36408,56802,56802,39806,56792,56802,56790,56810,56811,55747,56815,56820,49900,56825,56823,39738,56841,56839,48461,56850,56850,35829,56870,56868,31446,56889,56887,32887,56891,56889,36782,56892,56892,49662,56907,56908,56902,56908,56910,31894,56918,56920,40471,56920,56914,47329,56915,56924,29755,56939,56940,31538,56938,56950,38438,56955,56953,30493,56961,56951,52095,56980,56981,36515,56983,56985,29829,56990,56987,38637,56986,56995,56981,57032,57034,55996,57030,57038,34827,57040,57046,34431,57057,57054,39457,57068,57068,44036,57075,57076,29715,57086,57088,56751,57090,57094,39494,57105,57103,40016,57100,57117,55685,57129,57127,36157,57137,57138,30322,57138,57135,36287,57147,57141,47915,57161,57159,36804,57171,57169,38644,57177,57178,52261,57184,57189,42241,57188,57192,39799,57201,57202,52152,57219,57215,31351,57220,57221,42759,57230,57240,46815,57249,57246,45427,57257,57258,35735,57267,57265,36576,57268,57269,49860,57281,57279,50812,57282,57286,38078,57295,57297,37913,57326,57323,57317,57329,57327,51427,57345,57346,57340,57347,57343,49578,57364,57366,55950,57371,57369,31513,57378,57382,37502,57387,57388,47299,57395,57393,47519,57411,57407,55753,57425,57426,55666,57452,57452,45768,57465,57463,52560,57481,57486,42883,57488,57492,44338,57498,57501,57491,57522,57526,34433,57522,57518,29315,57555,57553,44691,57553,57550,38120,57558,57568,56016,57585,57586,48928,57590,57587,50111,57594,57598,51952,57635,57633,54068,57638,57629,50846,57636,57640,47197,57651,57649,43843,57664,57650,41653,57676,57678,54439,57686,57683,57677,57692,57696,50189,57707,57705,51030,57710,57712,39774,57712,57717,39353,57724,57726,33496,57729,57724,50693,57734,57731,53953,57745,57750,52885,57770,57771,57769,57775,57780,54988,57785,57783,31258,57765,57784,45332,57788,57792,29330,57801,57799,35996,57806,57804,47249,57819,57828,39378,57828,57837,47367,57844,57845,49112,57848,57848,43173,57857,57855,31091,57878,57876,57343,57897,57895,36940,57899,57897,43209,57915,57911,43655,57921,57922,57916,57938,57942,48885,57942,57935,56021,57968,57968,53894,57974,57976,32248,57985,57989,46233,58011,58009,34641,58025,58023,53939,58024,58029,46714,58041,58042,49155,58046,58043,58037,58050,58050,30538,58058,58054,38376,58065,58063,55226,58068,58068,38829,58089,58098,38520,58107,58104,48748,58099,58110,34656,58116,58116,58090,58144,58142,46811,58144,58150,40891,58143,58148,39832,58163,58163,43378,58169,58167,51474,58183,58188,48887,58190,58186,56340,58192,58197,42928,58202,58206,32800,58209,58207,43921,58214,58211,48348,58227,58225,51018,58225,58229,53033,58222,58235,31925,58241,58242,57340,58260,58267,37635,58303,58305,58301,58310,58308,35319,58310,58316,58302,58334,58332,29604,58361,58359,41459,58360,58365,43398,58362,58362,30188,58377,58378,57542,58380,58389,55344,58388,58388,44634,58401,58399,35770,58409,58410,31595,58412,58414,58406,58425,58423,47674,58422,58435,33992,58428,58440,40655,58441,58449,58433,58451,58452,53853,58472,58476,42959,58475,58480,29511,58498,58506,41376,58530,58530,48187,58537,58540,53814,58547,58545,58008,58561,58564,34218,58571,58569,54611,58577,58578,35266,58598,58595,58589,58601,58602,38029,58611,58606,37260,58612,58627,53136,58652,58652,43645,58659,58657,56239,58668,58678,43631,58681,58686,46188,58691,58692,35548,58697,58693,46234,58705,58710,50134,58722,58725,58723,58731,58732,51995,58739,58737,51466,58755,58756,57521,58761,58762,33436,58760,58770,31439,58785,58783,53034,58787,58788,43414,58820,58830,49291,58886,58888,55753,58892,58892,42970,58899,58900,44936,58905,58901,33592,58907,58905,49635,58910,58912,31211,58908,58908,58882,58934,58936,33022,58938,58938,44689,58960,58958,52617,58962,58966,57572,58977,58975,37095,58984,58990,58982,58994,58995,41475,59006,59002,41755,59009,59007,46242,59019,59017,44130,59018,59021,59007,59027,59028,52110,59041,59049,59039,59038,59051,42434,59058,59061,59059,59067,59065,47659,59072,59074,32079,59081,59082,31074,59090,59091,35731,59105,59103,45262,59106,59106,49406,59116,59114,42179,59121,59118,56145,59138,59139,39886,59147,59148,58239,59152,59158,59150,59164,59165,59163,59178,59178,47171,59195,59196,30666,59202,59206,44946,59198,59206,29877,59217,59207,51679,59219,59217,45722,59228,59232,39196,59236,59234,36481,59241,59239,54074,59260,59262,55226,59270,59267,40628,59274,59274,56883,59331,59329,48426,59327,59340,53520,59338,59347,38445,59355,59353,41315,59353,59358,58297,59366,59368,48940,59372,59376,57603,59385,59383,33537,59388,59388,32290,59392,59398,35888,59404,59406,30026,59414,59416,40071,59417,59418,59412,59438,59440,40468,59441,59442,34764,59442,59445,54195,59451,59449,51754,59465,59463,40603,59460,59469,56163,59463,59472,39154,59482,59494,49261,59499,59505,49122,59510,59507,40979,59537,59534,49508,59555,59553,41602,59558,59560,39592,59562,59566,45015,59575,59580,44209,59609,59610,39105,59610,59614,54965,59618,59614,56091,59625,59623,57389,59627,59625,58314,59649,59642,47557,59656,59652,54020,59658,59661,43156,59667,59665,33597,59659,59669,38104,59691,59688,34867,59697,59698,30989,59704,59706,46798,59721,59716,54408,59726,59724,56858,59740,59742,40344,59745,59737,51354,59748,59742,57333,59769,59770,59764,59769,59778,59132,59788,59790,36138,59795,59796,40340,59792,59808,42116,59828,59832,46665,59858,59862,33091,59865,59878,45363,59884,59885,57869,59918,59914,55013,59910,59926,51620,59940,59948,57454,59955,59950,49111,59968,59970,59088,59979,59976,47505,59992,59998,58199,60007,60011,52216,60014,60006,31524,60027,60025,51903,60035,60036,38532,60038,60036,51746,60075,60076,39408,60081,60078,46956,60086,60088,43037,60089,60090,43323,60098,60099,60097,60098,60101,60091,60105,60106,57860,60124,60125,45764,60127,60132,55618,60136,60138,38015,60147,60148,60142,60158,60155,60149,60162,60166,44146,60158,60168,41275,60206,60208,39868,60212,60212,36215,60220,60221,60215,60245,60250,55705,60254,60256,58724,60256,60250,31861,60268,60270,36772,60282,60286,56173,60291,60288,55589,60315,60316,36105,60319,60330,30701,60332,60336,53239,60340,60342,40662,60350,60352,43662,60371,60372,51163,60378,60378,56436,60392,60396,36324,60411,60412,42023,60424,60420,34137,60441,60442,32304,60446,60435,45079,60444,60456,44255,60491,60492,59943,60494,60496,55621,60507,60505,43962,60518,60520,49677,60522,60526,55656,60537,60535,57889,60587,60579,45582,60590,60596,59044,60604,60606,46733,60601,60608,45565,60614,60612,37458,60618,60622,38247,60625,60629,37775,60635,60636,42535,60642,60642,31472,60638,60648,57391,60657,60655,37394,60659,60660,48780,60676,60677,35802,60686,60688,48859,60700,60701,42426,60712,60715,59617,60722,60726,41599,60731,60729,41358,60734,60736,49217,60755,60753,37347,60755,60758,34826,60760,60762,48750,60771,60769,53959,60777,60778,43256,60788,60792,42116,60809,60807,49132,60819,60820,58097,60856,60854,32881,60867,60865,43138,60880,60885,41522,60868,60888,30890,60897,60890,40968,60899,60897,59505,60908,60912,37275,60915,60916,56743,60916,60917,54223,60921,60918,44157,60927,60936,51187,60938,60942,31353,60950,60952,38273,60954,60954,46153,60998,61000,55315,61002,61005,49699,61025,61023,41014,61009,61028,49802,61041,61042,41886,61048,61040,53312,61052,61056,31428,61089,61087,44076,61097,61098,34487,61118,61116,49149,61122,61120,46243,61135,61140,53310,61120,61150,59965,61143,61150,37800,61166,61163,61157,61209,61203,49876,61218,61221,34750,61224,61228,40021,61251,61249,43674,61259,61257,41485,61281,61282,43068,61288,61290,57988,61290,61294,36957,61329,61327,54672,61331,61332,34465,61337,61338,33990,61338,61341,39504,61351,61355,33171,61360,61356,33832,61377,61378,60825,61375,61380,40379,61401,61402,42392,61406,61408,54546,61412,61408,42540,61424,61440,34907,61458,61461,57285,61467,61464,55713,61468,61469,52115,61481,61478,40254,61482,61485,61483,61491,61492,31024,61505,61506,45654,61504,61510,59211,61516,61518,42703,61540,61541,45606,61545,61543,37014,61550,61548,31054,61552,61557,55248,61554,61554,37994,61578,61578,41969,61601,61602,50916,61596,61606,46793,61611,61597,50836,61624,61622,49372,61620,61630,50465,61635,61632,44458,61641,61639,41731,61649,61647,44616,61652,61656,58391,61665,61663,38136,61668,61670,47605,61652,61674,59222,61681,61684,45338,61698,61702,41755,61715,61716,57170,61718,61721,61719,61722,61722,38315,61744,61750,37416,61755,61756,51635,61779,61774,51262,61811,61812,47977,61816,61812,39500,61831,61835,56096,61841,61842,61836,61859,61857,43169,61852,61870,59775,61876,61877,31536,61903,61905,45367,61924,61926,40760,61928,61932,61581,61947,61943,53327,61958,61955,61949,61962,61966,60581,61977,61973,43937,61974,61979,42871,61985,61983,45800,61978,61989,48932,62001,61999,61007,62009,62010,34612,62007,62016,53517,62022,62037,59403,62044,62046,59196,62051,62052,51561,62054,62050,51886,62064,62062,38517,62075,62078,46374,62097,62095,44457,62112,62116,52234,62126,62124,41537,62129,62127,51020,62130,62130,47863,62139,62137,45909,62140,62141,42592,62169,62165,45467,62187,62185,46417,62188,62190,36223,62198,62195,62189,62202,62205,59062,62211,62209,33853,62217,62218,61608,62226,62230,42282,62270,62272,34964,62294,62291,42663,62297,62298,40082,62298,62302,53972,62305,62309,55233,62321,62319,46418,62322,62322,41669,62344,62346,45311,62344,62350,50862,62378,62381,62379,62384,62398,33894,62414,62411,55883,62418,62422,47543,62453,62458,33256,62464,62462,55812,62468,62468,38917,62475,62469,37627,62481,62479,42208,62487,62496,57867,62499,62500,45749,62505,62503,42044,62531,62529,49614,62537,62535,31486,62547,62545,44535,62560,62562,36586,62579,62577,59696,62584,62590,47670,62595,62596,44147,62601,62599,39073,62612,62616,54329,62625,62626,62014,62630,62632,35689,62628,62636,39672,62651,62652,59122,62656,62652,32070,62680,62676,62123,62682,62685,55913,62699,62697,39258,62721,62722,59565,62721,62730,36959,62736,62732,33771,62750,62747,48144,62754,62754,42142,62768,62770,60647,62788,62789,31727,62798,62796,57059,62817,62815,40689,62824,62826,52046,62849,62850,62844,62858,62860,50905,62867,62865,35329,62870,62867,44762,62894,62896,54782,62898,62902,34079,62907,62916,62089,62922,62920,38104,62915,62926,46660,62937,62933,43142,62966,62963,62957,62961,62967,52750,62979,62977,56568,62978,62981,62979,62985,62983,44134,62987,62985,42878,63027,63025,38322,63028,63029,51837,63057,63049,42683,63065,63063,45304,63068,63072,45905,63076,63073,42838,63092,63092,43546,63100,63102,59006,63110,63107,38456,63124,63125,51151,63129,63130,41900,63147,63141,36683,63177,63175,39541,63195,63188,34917,63196,63194,45062,63204,63209,38146,63234,63234,51494,63242,63246,59655,63275,63273,35827,63275,63278,43459,63297,63298,60566,63294,63310,51397,63308,63310,34930,63315,63313,57640,63329,63327,60540,63332,63336,38091,63345,63343,53866,63350,63347,62641,63324,63344,46878,63364,63366,34185,63374,63372,52720,63387,63385,48122,63388,63389,52937,63395,63396,55543,63402,63402,62501,63417,63418,47019,63419,63417,41070,63436,63438,61658,63441,63439,50612,63458,63462,59293,63465,63466,50599,63470,63468,42553,63484,63486,45109,63491,63492,32266,63496,63498,53027,63518,63520,44157,63522,63526,59118,63530,63531,45853,63539,63537,39262,63556,63557,55017,63572,63576,52829,63585,63583,50506,63587,63585,44259,63592,63598,49293,63594,63598,63244,63604,63605,63603,63609,63606,32024,63614,63612,42887,63627,63628,54409,63642,63642,39696,63642,63646,48666,63657,63655,44961,63665,63663,61260,63660,63669,62157,63686,63683,63677,63676,63690,34653,63692,63694,63686,63700,63702,44331,63703,63708,52134,63706,63715,49694,63721,63726,60312,63734,63729,44762,63738,63738,44314,63758,63755,63749,63771,63772,51531,63779,63777,46335,63788,63792,46437,63793,63798,33492,63801,63802,45662,63806,63804,38517,63820,63821,44743,63810,63836,52266,63824,63840,32205,63851,63852,60444,63854,63856,41700,63858,63860,50800,63894,63899,42432,63905,63903,36755,63900,63912,50745,63926,63928,51391,63947,63945,62108,63974,63966,47618,63995,63996,49095,64002,64005,51492,64011,64012,36728,64017,64015,55357,64028,64032,42155,64035,64033,40137,64060,64062,56576,64062,64066,33568,64070,64078,55613,64089,64090,39373,64107,64108,42240,64121,64122,55300,64134,64150,38195,64148,64148,45494,64155,64153,38351,64164,64169,39100,64185,64183,57561,64187,64188,54808,64214,64216,46207,64218,64221,64219,64219,64230,48608,64235,64236,56727,64264,64270,46350,64250,64278,62098,64281,64279,32361,64299,64297,37355,64297,64300,32487,64306,64315,42640,64324,64326,33104,64331,64329,50093,64371,64368,42537,64379,64377,54656,64396,64397,38922,64398,64401,53529,64430,64428,55938,64432,64437,63003,64449,64447,54312,64451,64449,38959,64481,64479,50586,64482,64486,54347,64497,64495,50377,64508,64512,50578,64550,64548,60008,64564,64566,50465,64574,64571,36260,64577,64573,59371,64588,64590,53938,64598,64595,64589,64574,64596,37869,64611,64612,43964,64615,64620,41431,64622,64626,57281,64628,64632,57835,64659,64657,52413,64657,64662,57699,64665,64663,58548,64662,64674,60594,64691,64692,62227,64706,64704,56549,64715,64713,42839,64742,64746,36222,64761,64759,43934,64779,64776,38678,64778,64782,58349,64790,64787,41440,64809,64810,58749,64814,64811,59280,64836,64848,41497,64851,64849,57996,64864,64870,39297,64874,64876,60577,64873,64878,42037,64881,64890,64217,64899,64897,52960,64912,64917,54303,64914,64914,32920,64924,64925,55506,64934,64932,53518,64948,64950,56365,64956,64968,53294,64995,64993,52445,64998,65001,34388,65009,65007,57311,65025,65021,54894,65027,65028,56829,65030,65028,58622,65048,65050,57093,65058,65061,51223,65068,65070,40238,65082,65086,65070,65097,65090,53861,65099,65097,61904,65104,65110,58892,65116,65114,47853,65121,65119,55674,65126,65120,37272,65139,65136,64516,65145,65146,41370,65162,65165,65163,65169,65167,35802,65171,65172,58034,65177,65175,39472,65178,65181,65179,65201,65202,56555,65211,65209,64642,65236,65234,38859,65252,65252,49206,65265,65266,65260,65267,65265,49182,65284,65286,40493,65291,65289,61269,65307,65308,39470,65321,65322,51095,65322,65320,41871,65348,65352,41358,65355,65356,58240,65369,65370,58383,65378,65379,65373,65390,65386,40335,65404,65405,33781,65408,65412,43090,65416,65418,33267,65418,65420,55880,65431,65435,35512,65442,65445,34701,65438,65445,65435,65472,65467,58767,65490,65490,42170,65508,65518,41499,65504,65518,42121}; uint16_t __nmod_poly_cp_primes6[] = {1,3,7,15,21,27,43,45,51,63,73,81,93,97,111,115,121,141,151,163,165,171,177,181,183,193,195,225,241,253,273,291,295,301,303,307,315,331,345,363,385,391,393,415,421,427,445,447,457,493,501,505,511,531,535,547,553,567,571,573,601,625,633,637,643,655,685,703,735,757,765,801,807,811,823,825,837,841,847,867,877,895,913,921,927,931,955,963,973,987,993,997,1005,1017,1033,1035,1051,1057,1065,1081,1093,1107,1117,1147,1161,1165,1177,1185,1197,1203,1213,1215,1227,1255,1261,1273,1285,1305,1315,1317,1327,1341,1347,1353,1383,1387,1395,1407,1411,1413,1423,1437,1441,1467,1485,1497,1507,1513,1521,1525,1537,1543,1567,1585,1593,1603,1605,1617,1621,1633,1645,1651,1653,1675,1677,1681,1683,1695,1711,1725,1735,1737,1753,1771,1803,1807,1813,1833,1855,1863,1873,1875,1885,1891,1893,1897,1911,1917,1941,1945,1953,1957,1963,1975,1987,1995,2001,2011,2023,2031,2041,2043,2053,2065,2071,2083,2095,2115,2143,2163,2173,2187,2197,2205,2215,2221,2223,2227,2241,2247,2253,2265,2271,2283,2293,2307,2317,2331,2347,2355,2365,2391,2395,2397,2403,2407,2421,2425,2431,2443,2451,2457,2487,2505,2517,2523,2535,2551,2563,2575,2577,2605,2611,2625,2635,2671,2673,2677,2683,2691,2703,2725,2743,2745,2775,2793,2815,2835,2853,2863,2901,2907,2911,2913,2937,2941,2947,2953,2955,2965,2971,2985,2995,3003,3007,3031,3045,3061,3075,3097,3103,3123,3133,3147,3151,3163,3175,3177,3193,3201,3207,3213,3231,3235,3241,3255,3277,3283,3285,3327,3343,3345,3355,3361,3363,3367,3373,3381,3391,3411,3427,3457,3465,3475,3483,3493,3495,3525,3531,3537,3573,3583,3591,3607,3613,3615,3627,3655,3657,3661,3667,3685,3697,3703,3711,3721,3723,3727,3777,3781,3801,3805,3835,3843,3847,3853,3865,3867,3891,3895,3903,3921,3927,3931,3937,3945,3955,3957,3961,3963,4003,4021,4057,4087,4117,4125,4141,4155,4161,4173,4201,4203,4225,4227,4231,4243,4273,4285,4291,4293,4297,4311,4321,4323,4341,4363,4375,4393,4395,4405,4423,4455,4461,4465,4467,4473,4483,4503,4515,4525,4531,4543,4563,4575,4581,4585,4587,4603,4605,4621,4627,4641,4645,4647,4663,4665,4671,4687,4693,4701,4705,4713,4735,4753,4761,4773,4777,4785,4791,4815,4837,4843,4845,4857,4887,4893,4903,4915,4921,4923,4945,4951,4953,4965,4971,4993,5001,5013,5035,5037,5047,5053,5071,5083,5085,5091,5103,5121,5127,5131,5151,5173,5181,5193,5217,5233,5247,5257,5287,5305,5307,5313,5317,5331,5341,5343,5355,5365,5377,5383,5385,5401,5413,5415,5421,5433,5443,5445,5455,5461,5463,5475,5487,5503,5523,5533,5545,5553,5583,5593,5607,5611,5617,5625,5631,5635,5655,5673,5697,5701,5713,5721,5725,5727,5751,5757,5781,5791,5793,5797,5803,5805,5811,5817,5823,5827,5851,5853,5863,5875,5877,5883,5893,5901,5907,5917,5935,5937,5943,5947,5967,5991,6001,6013,6015,6027,6033,6057,6061,6097,6111,6127,6135,6157,6163,6171,6175,6177,6183,6205,6225,6241,6253,6271,6273,6285,6301,6307,6313,6325,6331,6343,6345,6351,6363,6373,6381,6397,6405,6411,6427,6435,6447,6451,6457,6463,6483,6495,6507,6511,6517,6537,6541,6553,6555,6565,6567,6573,6603,6625,6631,6633,6637,6675,6685,6687,6691,6693,6715,6717,6733,6735,6741,6751,6771,6777,6801,6805,6817,6831,6843,6847,6885,6895,6925,6931,6933,6945,6957,6961,6967,6997,7011,7015,7023,7041,7077,7081,7087,7107,7111,7113,7125,7135,7137,7143,7153,7165,7171,7183,7191,7197,7203,7227,7231,7261,7281,7287,7323,7333,7335,7347,7353,7357,7365,7371,7375,7387,7395,7401,7413,7417,7423,7437,7441,7461,7473,7477,7483,7501,7503,7507,7525,7527,7543,7555,7585,7591,7597,7605,7645,7653,7701,7707,7723,7741,7755,7767,7773,7791,7795,7815,7825,7827,7833,7843,7851,7881,7885,7897,7917,7923,7935,7941,7947,7981,7987,7993,8011,8017,8025,8035,8047,8053,8061,8071,8073,8077,8101,8107,8115,8137,8143,8145,8157,8163,8173,8185,8191,8215,8221,8235,8247,8283,8287,8311,8313,8323,8331,8341,8347,8361,8371,8403,8407,8415,8425,8437,8463,8481,8485,8491,8511,8515,8535,8541,8557,8563,8565,8595,8607,8613,8623,8625,8631,8641,8653,8661,8665,8667,8673,8683,8695,8721,8743,8751,8757,8761,8775,8781,8787,8817,8821,8827,8841,8845,8847,8875,8877,8883,8905,8913,8917,8935,8953,8971,8973,8985,8991,8995,9015,9025,9031,9037,9051,9061,9073,9075,9087,9117,9151,9163,9171,9177,9181,9183,9193,9195,9211,9223,9225,9235,9243,9261,9285,9291,9295,9307,9321,9325,9333,9337,9351,9355,9361,9367,9387,9393,9397,9405,9423,9475,9477,9481,9493,9501,9505,9543,9547,9573,9597,9613,9625,9631,9633,9645,9657,9673,9675,9681,9687,9691,9703,9717,9733,9741,9753,9771,9787,9793,9801,9811,9817,9831,9841,9853,9855,9865,9867,9871,9895,9901,9943,9967,9975,9985,9991,9997,10003,10005,10017,10021,10035,10041,10047,10075,10081,10083,10093,10105,10117,10123,10143,10147,10153,10167,10171,10173,10185,10195,10207,10231,10237,10245,10251,10257,10261,10285,10297,10317,10333,10347,10377,10395,10401,10405,10431,10443,10447,10453,10455,10461,10465,10467,10495,10503,10543,10545,10555,10563,10567,10587,10593,10611,10621,10623,10627,10671,10677,10695,10707,10713,10717,10723,10725,10747,10753,10767,10797,10807,10831,10833,10843,10851,10867,10885,10887,10905,10927,10935,10945,10951,10957,10971,10975,10983,11001,11005,11007,11025,11043,11061,11067,11071,11095,11113,11115,11131,11137,11143,11161,11181,11197,11217,11221,11235,11241,11245,11265,11283,11293,11295,11301,11311,11335,11337,11347,11371,11377,11383,11407,11413,11425,11427,11455,11467,11481,11487,11493,11505,11511,11533,11545,11557,11565,11601,11605,11617,11631,11635,11655,11665,11677,11701,11703,11707,11713,11725,11727,11731,11733,11743,11755,11781,11787,11803,11811,11815,11823,11833,11841,11847,11881,11883,11895,11911,11935,11941,11943,11953,11955,11973,11977,11985,11991,12007,12013,12015,12021,12027,12033,12037,12051,12055,12075,12081,12085,12105,12111,12123,12145,12151,12153,12163,12175,12177,12183,12187,12195,12207,12211,12225,12237,12247,12261,12265,12277,12303,12313,12327,12331,12357,12363,12393,12397,12415,12433,12441,12447,12463,12471,12481,12495,12505,12513,12523,12543,12565,12585,12601,12603,12621,12627,12631,12637,12643,12655,12657,12667,12693,12697,12705,12723,12741,12747,12765,12771,12775,12781,12805,12811,12831,12865,12891,12901,12903,12931,12943,12951,12961,12973,12975,12981,13003,13005,13017,13033,13035,13041,13047,13057,13071,13087,13107,13113,13117,13155,13161,13171,13177,13185,13201,13243,13245,13251,13255,13261,13267,13273,13287,13303,13317,13321,13341,13351,13353,13357,13365,13383,13393,13405,13441,13443,13453,13495,13503,13507,13527,13551,13567,13575,13597,13603,13611,13615,13617,13623,13645,13651,13657,13665,13693,13695,13705,13723,13737,13743,13747,13765,13773,13783,13797,13801,13813,13821,13831,13843,13857,13861,13863,13875,13887,13891,13897,13915,13945,13957,13995,14001,14013,14023,14025,14043,14053,14065,14073,14077,14085,14091,14095,14097,14121,14133,14151,14155,14157,14161,14163,14221,14233,14241,14265,14275,14277,14281,14287,14293,14305,14307,14311,14325,14331,14337,14353,14365,14367,14371,14403,14407,14431,14437,14443,14451,14461,14463,14485,14503,14515,14535,14541,14571,14575,14605,14611,14613,14617,14631,14637,14641,14655,14671,14673,14685,14695,14697,14703,14715,14727,14737,14743,14751,14773,14781,14793,14805,14811,14827,14833,14851,14871,14893,14911,14913,14935,14937,14953,14955,14977,14991,15001,15021,15031,15063,15067,15075,15085,15091,15093,15115,15121,15133,15135,15141,15145,15147,15151,15165,15177,15201,15211,15213,15225,15241,15243,15247,15253,15267,15273,15283,15295,15297,15313,15327,15361,15373,15375,15381,15387,15393,15397,15417,15427,15453,15465,15477,15481,15483,15487,15495,15505,15507,15511,15513,15535,15541,15547,15561,15565,15583,15595,15621,15627,15637,15645,15661,15663,15667,15687,15697,15703,15745,15747,15757,15763,15771,15795,15807,15813,15817,15823,15835,15837,15865,15873,15885,15903,15921,15927,15973,15981,15991,15997,16011,16015,16017,16023,16027,16033,16075,16083,16093,16101,16111,16113,16131,16135,16141,16153,16165,16167,16171,16191,16201,16213,16225,16233,16237,16263,16281,16303,16311,16317,16333,16347,16363,16365,16383,16393,16395,16401,16407,16417,16431,16435,16437,16467,16471,16473,16477,16485,16495,16501,16503,16515,16531,16537,16593,16603,16605,16617,16627,16635,16647,16653,16657,16671,16681,16683,16687,16695,16701,16705,16725,16731,16743,16765,16771,16803,16813,16815,16825,16837,16851,16857,16885,16921,16927,16933,16935,16947,16951,16957,16963,16971,16993,16995,17013,17023,17025,17031,17035,17055,17065,17073,17077,17083,17097,17115,17121,17163,17185,17187,17191,17193,17221,17223,17227,17245,17251,17257,17263,17275,17277,17301,17311,17347,17353,17355,17367,17377,17403,17427,17445,17461,17467,17473,17487,17511,17523,17527,17535,17541,17553,17557,17565,17581,17601,17641,17667,17671,17683,17685,17691,17695,17697,17707,17721,17731,17733,17737,17763,17775,17803,17805,17821,17847,17853,17863,17865,17871,17881,17887,17895,17901,17907,17913,17923,17935,17941,17961,18001,18021,18025,18027,18043,18055,18061,18073,18081,18085,18103,18105,18117,18127,18153,18165,18181,18183,18201,18225,18237,18241,18255,18277,18297,18307,18321,18333,18337,18355,18367,18375,18385,18397,18403,18433,18447,18451,18475,18481,18511,18517,18523,18525,18531,18553,18585,18591,18595,18601,18607,18627,18643,18645,18655,18663,18675,18685,18687,18693,18703,18711,18727,18763,18771,18777,18781,18783,18811,18813,18841,18853,18855,18865,18871,18885,18895,18901,18907,18913,18921,18927,18931,18945,18963,18967,18973,18985,18987,18997,19015,19023,19053,19093,19095,19113,19117,19123,19137,19155,19161,19165,19177,19183,19195,19201,19215,19225,19251,19257,19273,19275,19291,19321,19323,19333,19335,19377,19383,19411,19425,19431,19441,19443,19455,19473,19485,19491,19501,19513,19525,19545,19551,19555,19557,19567,19573,19585,19597,19611,19623,19657,19663,19665,19677,19687,19693,19701,19707,19711,19723,19761,19767,19777,19795,19797,19825,19827,19833,19845,19875,19891,19893,19903,19911,19915,19917,19933,19951,19977,19981,19987,19995,20013,20035,20041,20061,20065,20071,20083,20085,20091,20103,20107,20125,20131,20133,20155,20167,20175,20181,20197,20215,20245,20257,20281,20283,20293,20295,20301,20307,20311,20317,20353,20367,20373,20395,20397,20455,20463,20475,20481,20491,20493,20533,20541,20547,20575,20577,20581,20595,20601,20607,20625,20635,20643,20647,20661,20665,20673,20703,20707,20713,20721,20727,20733,20751,20755,20757,20761,20775,20787,20805,20815,20817,20821,20833,20835,20845,20853,20863,20877,20887,20905,20917,20925,20931,20941,20955,20965,20973,20995,20997,21003,21025,21037,21043,21051,21063,21091,21093,21141,21153,21157,21175,21183,21193,21207,21217,21231,21235,21247,21277,21301,21307,21315,21321,21325,21333,21387,21391,21393,21403,21415,21423,21433,21445,21457,21475,21477,21501,21505,21513,21535,21547,21567,21571,21583,21585,21597,21613,21615,21643,21645,21651,21675,21685,21687,21715,21717,21721,21741,21745,21757,21763,21777,21781,21787,21801,21823,21847,21867,21871,21885,21891,21897,21907,21937,21945,21955,21973,21975,21981,21987,22003,22005,22011,22017,22021,22023,22047,22051,22053,22077,22087,22093,22095,22105,22107,22113,22135,22143,22147,22155,22161,22165,22183,22185,22203,22207,22215,22231,22257,22261,22267,22275,22297,22317,22333,22341,22345,22351,22375,22381,22395,22407,22423,22425,22437,22441,22455,22465,22467,22471,22483,22501,22533,22543,22557,22581,22593,22633,22641,22675,22687,22701,22705,22723,22725,22753,22765,22785,22791,22801,22803,22843,22861,22875,22887,22891,22927,22933,22935,22957,22963,22977,22987,23011,23053,23055,23071,23073,23107,23115,23121,23125,23127,23131,23145,23185,23193,23205,23211,23235,23253,23257,23263,23265,23271,23275,23277,23281,23283,23307,23317,23325,23331,23337,23347,23361,23367,23383,23401,23415,23433,23457,23461,23467,23473,23481,23485,23505,23515,23521,23533,23535,23547,23551,23565,23571,23577,23583,23587,23601,23617,23653,23667,23673,23677,23691,23695,23701,23725,23733,23737,23757,23767,23781,23793,23827,23835,23845,23851,23857,23863,23877,23881,23895,23907,23913,23923,23941,23955,23965,23977,23983,23985,23991,23997,24025,24027,24031,24055,24061,24063,24067,24075,24091,24097,24117,24121,24123,24133,24135,24145,24153,24217,24223,24231,24243,24247,24261,24273,24283,24285,24297,24303,24313,24331,24355,24361,24363,24373,24381,24387,24403,24423,24427,24441,24447,24453,24465,24471,24475,24481,24483,24487,24495,24517,24523,24531,24535,24537,24553,24571,24585,24591,24613,24627,24637,24651,24655,24661,24663,24667,24681,24691,24703,24711,24727,24735,24745,24753,24777,24817,24823,24835,24837,24843,24861,24865,24867,24871,24901,24903,24933,24937,24945,24963,24975,24987,24991,24993,24997,25011,25047,25063,25081,25083,25095,25105,25111,25123,25141,25143,25161,25167,25173,25195,25213,25251,25257,25267,25285,25287,25297,25305,25311,25327,25351,25365,25371,25375,25381,25395,25411,25435,25441,25453,25461,25473,25483,25497,25543,25545,25561,25563,25585,25591,25593,25603,25605,25615,25617,25623,25627,25647,25657,25663,25693,25701,25707,25713,25717,25747,25755,25761,25767,25773,25795,25831,25833,25837,25845,25851,25857,25861,25875,25887,25897,25917,25921,25923,25927,25957,25963,25977,25993,26005,26035,26037,26041,26047,26055,26085,26095,26103,26137,26155,26167,26175,26197,26217,26221,26235,26245,26265,26271,26275,26277,26287,26301,26305,26331,26337,26373,26385,26403,26407,26415,26421,26425,26431,26433,26461,26467,26473,26497,26505,26515,26541,26547,26571,26575,26583,26607,26617,26637,26641,26643,26653,26667,26683,26685,26691,26697,26701,26707,26715,26733,26761,26775,26781,26797,26811,26817,26821,26827,26833,26841,26845,26847,26851,26863,26865,26877,26883,26895,26923,26925,26931,26943,26953,26967,26971,27015,27021,27031,27033,27045,27057,27087,27091,27103,27105,27111,27121,27133,27135,27145,27147,27157,27163,27171,27181,27187,27201,27217,27225,27231,27243,27253,27255,27265,27273,27285,27295,27313,27321,27325,27327,27331,27357,27363,27385,27391,27405,27415,27421,27423,27451,27457,27465,27511,27517,27523,27541,27547,27553,27561,27567,27577,27595,27597,27603,27615,27633,27643,27651,27663,27693,27703,27705,27715,27717,27721,27727,27745,27747,27751,27771,27783,27787,27793,27801,27835,27841,27847,27871,27883,27891,27927,27943,27945,27951,27955,27957,27961,27967,27987,27993,28017,28021,28023,28027,28045,28065,28071,28093,28101,28147,28165,28167,28183,28203,28225,28227,28251,28273,28275,28291,28315,28335,28351,28353,28357,28365,28375,28377,28387,28401,28405,28413,28431,28435,28443,28447,28461,28471,28473,28497,28513,28521,28527,28543,28563,28573,28575,28581,28585,28615,28617,28633,28665,28671,28683,28693,28717,28725,28737,28755,28771,28773,28785,28791,28795,28807,28813,28815,28843,28861,28863,28885,28891,28897,28903,28905,28911,28927,28941,28947,28977,28993,28995,29005,29007,29011,29023,29025,29037,29047,29061,29067,29077,29085,29113,29115,29151,29157,29173,29187,29191,29211,29235,29241,29245,29253,29257,29275,29283,29287,29301,29305,29311,29313,29337,29353,29367,29371,29397,29413,29415,29425,29457,29463,29467,29473,29485,29491,29527,29535,29547,29551,29553,29557,29565,29571,29575,29595,29607,29617,29641,29653,29655,29667,29677,29683,29695,29697,29703,29721,29725,29731,29737,29743,29751,29775,29781,29791,29803,29833,29847,29857,29865,29877,29883,29893,29905,29907,29925,29931,29935,29943,29947,29971,29991,29995,30003,30013,30025,30033,30045,30061,30067,30081,30085,30093,30097,30115,30165,30171,30177,30181,30187,30195,30201,30211,30237,30247,30253,30255,30265,30267,30277,30283,30321,30333,30337,30345,30355,30375,30381,30387,30393,30411,30421,30423,30435,30451,30453,30465,30477,30481,30507,30517,30523,30543,30561,30601,30613,30621,30631,30643,30645,30663,30675,30685,30687,30697,30723,30727,30733,30745,30753,30757,30787,30793,30795,30801,30817,30841,30865,30883,30895,30907,30915,30921,30925,30933,30943,30951,30957,30961,30981,30991,31017,31021,31045,31051,31053,31065,31107,31125,31131,31135,31161,31167,31195,31201,31203,31213,31221,31227,31233,31243,31251,31261,31263,31285,31287,31291,31311,31315,31321,31357,31371,31375,31395,31417,31423,31437,31443,31453,31461,31465,31467,31471,31485,31503,31537,31545,31567,31581,31591,31615,31621,31623,31633,31635,31641,31651,31677,31695,31705,31723,31747,31765,31767,31791,31831,31833,31837,31843,31845,31851,31861,31887,31893,31905,31917,31923,31927,31963,31965,31975,31987,32011,32013,32017,32025,32035,32041,32043,32047,32071,32073,32077,32113,32115,32137,32151,32175,32193,32235,32241,32251,32253,32277,32293,32305,32307,32311,32313,32323,32325,32335,32343,32347,32383,32391,32395,32407,32425,32431,32437,32451,32473,32475,32481,32505,32511,32521,32545,32565,32587,32593,32607,32643,32671,32677,32685,32691,32715,32721,32733,32761,32763,32781,32785,32787,32791,32811,32833,32841,32851,32853,32871,32875,32883,32893,32907,32917,32923,32931,32937,32943,32955,32971,32983,32997,33007,33025,33027,33037,33061,33085,33091,33103,33105,33127,33133,33153,33175,33177,33181,33193,33195,33201,33237,33243,33265,33271,33273,33301,33313,33331,33333,33337,33351,33357,33361,33363,33373,33375,33391,33393,33403,33411,33417,33427,33445,33457,33463,33477,33481,33487,33505,33517,33543,33547,33553,33567,33573,33583,33595,33597,33601,33603,33613,33637,33645,33655,33687,33697,33705,33715,33721,33723,33741,33753,33781,33811,33813,33831,33835,33841,33855,33861,33865,33873,33895,33903,33933,33951,33961,33987,33991,33993,34015,34023,34027,34035,34041,34045,34071,34075,34087,34107,34125,34131,34143,34153,34171,34173,34177,34183,34185,34197,34225,34231,34251,34257,34273,34281,34287,34293,34297,34303,34323,34335,34341,34345,34365,34371,34387,34393,34425,34435,34453,34455,34467,34483,34507,34513,34521,34533,34567,34573,34593,34615,34617,34633,34647,34653,34657,34671,34677,34701,34731,34735,34743,34755,34761,34777,34797,34807,34821,34825,34827,34843,34855,34857,34867,34875,34881,34911,34923,34933,34947,34957,34965,34975,34981,34983,34987,35001,35011,35013,35023,35055,35073,35077,35085,35113,35133,35137,35157,35163,35167,35197,35205,35211,35233,35251,35263,35265,35275,35287,35293,35311,35317,35371,35377,35391,35395,35401,35407,35421,35445,35451,35463,35473,35485,35491,35515,35527,35545,35553,35571,35575,35577,35581,35583,35605,35613,35623,35625,35637,35647,35661,35667,35671,35673,35685,35731,35737,35743,35745,35751,35757,35787,35797,35805,35811,35823,35827,35841,35847,35863,35875,35883,35893,35913,35931,35941,35947,35953,35965,35967,35977,35991,35995,35997,36001,36025,36037,36045,36063,36067,36075,36091,36105,36117,36127,36145,36157,36165,36183,36187,36201,36205,36211,36213,36235,36253,36261,36271,36297,36301,36303,36327,36333,36337,36343,36355,36381,36385,36393,36403,36421,36427,36441,36451,36463,36465,36477,36483,36487,36495,36507,36523,36525,36535,36541,36543,36565,36567,36571,36585,36603,36613,36625,36645,36655,36661,36663,36667,36681,36693,36697,36705,36715,36717,36723,36757,36763,36765,36781,36793,36801,36823,36831,36861,36871,36873,36897,36901,36915,36925,36945,36961,36963,36967,36987,36997,37003,37011,37015,37023,37027,37051,37057,37071,37075,37107,37111,37117,37131,37137,37141,37143,37165,37225,37227,37233,37257,37261,37275,37293,37305,37323,37335,37341,37345,37375,37377,37393,37395,37417,37431,37447,37465,37471,37507,37513,37531,37533,37543,37551,37555,37557,37563,37587,37605,37635,37641,37647,37681,37695,37701,37753,37755,37771,37783,37797,37813,37821,37851,37855,37857,37863,37873,37885,37887,37915,37921,37935,37947,37975,37993,38013,38017,38025,38031,38037,38041,38047,38055,38077,38083,38107,38115,38121,38133,38145,38151,38163,38167,38187,38233,38251,38265,38275,38277,38301,38305,38307,38331,38353,38367,38377,38383,38415,38427,38431,38433,38443,38445,38455,38457,38461,38467,38473,38485,38497,38511,38517,38523,38551,38553,38571,38577,38583,38587,38611,38613,38625,38637,38643,38647,38671,38695,38697,38703,38707,38745,38751,38761,38773,38775,38787,38791,38811,38833,38845,38847,38857,38863,38881,38923,38935,38937,38943,38955,38977,38991,39001,39007,39013,39015,39025,39043,39057,39061,39087,39103,39115,39123,39141,39145,39147,39157,39165,39171,39175,39181,39187,39193,39207,39223,39225,39237,39243,39253,39265,39267,39291,39295,39313,39315,39333,39343,39355,39375,39381,39397,39411,39417,39423,39435,39451,39463,39483,39487,39495,39501,39535,39561,39571,39601,39607,39631,39637,39663,39675,39691,39693,39703,39715,39717,39727,39733,39741,39783,39787,39795,39801,39805,39823,39825,39831,39837,39843,39853,39861,39865,39871,39901,39913,39931,39955,39963,39967,39973,39981,39991,39993,39997,40005,40021,40027,40065,40071,40077,40083,40113,40117,40131,40137,40147,40155,40165,40191,40197,40215,40225,40231,40233,40281,40293,40327,40335,40347,40363,40371,40377,40393,40407,40417,40431,40435,40441,40447,40461,40477,40483,40495,40497,40551,40567,40573,40585,40587,40593,40627,40645,40651,40653,40671,40677,40681,40683,40707,40725,40737,40741,40743,40755,40761,40767,40771,40783,40785,40795,40813,40821,40827,40831,40837,40855,40861,40875,40881,40891,40897,40905,40915,40917,40951,40965,40995,41001,41005,41007,41055,41083,41085,41091,41101,41113,41121,41125,41127,41133,41145,41157,41163,41167,41185,41191,41203,41211,41215,41217,41223,41245,41247,41251,41265,41287,41317,41323,41325,41331,41335,41341,41367,41371,41385,41401,41413,41421,41425,41427,41443,41457,41485,41497,41517,41521,41533,41535,41541,41553,41563,41565,41583,41587,41601,41635,41647,41661,41665,41673,41691,41707,41715,41733,41737,41743,41773,41787,41803,41811,41815,41821,41841,41905,41913,41917,41931,41937,41971,41973,42027,42045,42063,42067,42073,42085,42105,42111,42135,42151,42157,42163,42177,42181,42183,42205,42211,42225,42237,42241,42255,42291,42301,42303,42307,42321,42331,42337,42345,42361,42367,42387,42391,42405,42415,42435,42445,42463,42471,42475,42477,42487,42501,42505,42525,42543,42553,42571,42573,42591,42595,42603,42625,42643,42651,42655,42657,42667,42675,42681,42687,42697,42711,42727,42735,42751,42753,42757,42765,42807,42811,42823,42841,42843,42865,42877,42885,42903,42921,42925,42927,42961,42963,42967,42981,42993,42997,43005,43017,43021,43035,43051,43095,43101,43107,43113,43141,43171,43173,43191,43203,43215,43225,43233,43255,43257,43263,43267,43285,43291,43327,43333,43341,43345,43347,43351,43357,43371,43381,43387,43393,43407,43411,43413,43423,43425,43431,43435,43455,43465,43477,43501,43513,43527,43537,43561,43567,43575,43585,43597,43603,43605,43611,43623,43633,43635,43663,43665,43675,43693,43717,43731,43743,43761,43767,43777,43785,43795,43821,43827,43831,43843,43851,43855,43861,43887,43897,43905,43915,43917,43933,43935,43945,43971,43981,43983,44001,44005,44011,44031,44043,44047,44053,44061,44073,44083,44085,44103,44125,44127,44137,44181,44185,44205,44215,44253,44257,44271,44283,44293,44295,44305,44307,44311,44313,44323,44337,44347,44355,44361,44367,44377,44383,44401,44407,44425,44451,0}; uint8_t __nmod_poly_cp_sm_coeffs6[] = {3,7,2,6,5,11,6,6,5,1,3,0,2,7,2,3,2,10,3,3,3,0,13,11,2,2,3,9,3,2,2,2,3,0,2,3,5,5,2,3,6,0,2,2,10,6,2,7,3,4,3,4,10,0,7,16,3,7,2,4,11,23,2,0,31,4,2,18,3,6,2,0,3,3,2,7,11,18,3,3,3,1,5,11,7,14,13,7,2,1,2,7,2,9,3,3,3,1,2,1,2,6,3,2,5,2,3,2,22,7,2,4,3,0,3,3,2,14,2,10,3,0,3,4,14,20,2,4,2,0,11,3,2,6,17,7,3,2,2,1,22,12,5,12,5,2,2,8,13,3,17,35,2,14,3,1,5,10,2,8,2,6,7,9,3,3,5,6,10,2,2,13,2,2,2,6,2,19,2,8,19,26,2,2,6,2,10,6,3,0,7,6,2,2,3,4,7,0,3,0,2,1,2,2,2,1,5,6,5,10,3,3,3,1,13,14,2,10,2,8,3,2,3,7,3,3,7,6,2,6,6,4,2,3,7,24,2,3,2,3,5,2,5,9,2,2,17,20,6,3,2,11,3,2,3,5,2,2,10,12,7,4,2,6,5,6,2,7,7,12,5,16,2,7,3,2,5,20,2,12,3,6,11,2,5,7,6,10,7,17,2,1,2,10,5,10,2,0,3,2,2,6,2,8,6,2,2,8,2,6,3,6,11,1,3,2,5,5,2,3,14,10,7,10,3,7,2,7,3,7,5,3,2,9,19,42,7,3,3,3,3,0,2,8,2,1,2,7,2,3,3,0,3,2,2,21,2,12,3,2,23,27,2,1,2,7,11,3,2,7,10,0,5,16,2,0,7,2,3,6,3,6,7,8,2,0,3,1,5,5,2,2,7,2,11,10,19,9,2,2,2,0,5,0,2,0,6,12,13,5,3,4,6,3,2,10,5,16,3,3,6,2,11,12,3,3,10,0,2,1,14,0,2,6,2,8,2,8,3,2,3,4,3,2,6,7,2,3,3,6,5,3,2,9,3,0,5,3,2,4,2,2,5,14,3,5,22,0,5,3,2,7,6,2,5,12,2,7,7,5,5,19,3,11,2,7,13,35,2,7,5,4,13,24,2,3,2,8,2,7,3,3,2,6,7,7,7,17,6,3,11,12,17,5,7,6,2,3,7,4,2,3,5,6,5,3,7,0,10,14,2,3,2,18,3,2,10,5,3,4,2,4,7,0,6,0,2,3,5,3,5,3,6,2,2,12,2,8,3,1,7,7,2,2,2,3,2,8,5,3,2,0,11,5,5,16,3,0,5,11,3,4,6,0,3,2,10,6,3,0,3,2,2,3,2,8,14,1,3,10,13,16,22,19,2,3,3,9,2,2,5,5,2,7,5,1,5,8,2,35,2,2,3,1,19,32,6,9,2,2,2,2,3,3,2,6,2,8,10,0,2,3,13,4,5,3,5,2,2,2,11,3,2,8,11,5,10,8,2,9,2,15,2,12,3,4,7,3,3,5,3,2,2,8,5,8,10,0,3,4,5,15,3,10,2,8,2,8,5,3,2,4,6,4,14,7,2,8,13,7,3,3,5,6,6,4,2,2,3,0,7,2,2,8,2,6,3,7,3,5,2,7,2,4,3,1,5,6,2,1,6,7,2,4,2,2,5,12,11,11,3,4,2,2,3,4,2,10,5,5,2,7,3,0,7,9,2,24,10,14,5,10,10,3,3,4,10,1,2,6,2,4,7,4,3,2,3,2,2,6,7,5,3,3,2,2,3,4,2,10,19,32,6,5,3,2,7,6,2,3,2,0,7,3,3,2,6,3,2,6,6,7,2,14,2,1,10,12,2,5,2,1,5,6,7,0,3,4,17,8,14,8,5,5,5,3,2,4,2,3,6,4,23,34,11,5,3,4,5,10,6,11,3,11,7,17,11,14,6,2,2,6,6,0,10,1,5,10,5,3,10,2,13,6,6,5,3,4,3,2,3,2,5,14,17,20,2,10,2,2,3,7,5,15,2,3,2,7,2,8,5,3,2,4,5,4,2,2,6,7,7,13,3,3,7,8,3,2,2,3,5,18,2,6,2,6,22,0,5,15,3,4,3,7,3,6,5,2,3,1,2,7,17,35,2,3,3,3,2,2,3,2,3,2,2,3,3,4,7,6,13,14,3,11,2,0,6,3,2,3,11,16,2,2,6,2,7,2,2,9,11,9,15,6,6,3,11,6,7,6,2,9,3,7,11,22,3,8,3,2,6,7,2,4,3,9,11,12,3,2,2,4,3,2,7,0,11,7,2,6,3,4,5,14,3,12,5,2,3,2,5,1,2,12,5,3,7,0,2,11,2,13,6,6,2,7,5,12,6,4,2,10,2,15,11,8,11,2,2,7,2,8,2,7,2,6,2,10,11,5,2,3,7,4,5,6,6,10,2,4,3,6,3,6,3,0,2,4,6,3,2,8,19,32,5,15,2,0,3,4,3,6,5,2,15,3,2,1,2,6,2,1,17,7,5,12,3,3,2,3,44,13,3,9,2,0,5,11,7,17,2,10,2,3,2,8,3,7,7,5,2,2,11,2,7,0,3,2,2,8,2,3,2,6,2,6,2,6,2,8,2,8,2,8,3,5,2,26,3,1,7,7,2,1,3,3,5,8,5,5,2,7,5,10,2,4,3,0,2,2,2,12,6,2,2,6,2,8,6,4,5,3,7,0,2,1,2,2,2,6,3,17,2,2,2,9,7,4,2,6,3,3,3,3,5,1,5,3,3,0,5,6,7,17,2,9,3,0,3,6,2,12,5,4,6,7,13,6,2,6,2,13,6,7,11,8,2,6,5,6,5,2,2,1,2,8,13,9,3,14,5,14,2,6,3,4,5,8,2,17,5,3,7,17,11,3,7,3,5,14,6,3,3,2,2,8,2,7,11,5,7,0,2,6,2,15,2,16,5,4,2,6,5,25,5,5,2,2,2,8,6,2,3,8,7,0,2,6,2,7,2,8,11,6,2,8,10,9,5,6,2,12,3,9,17,17,2,7,3,0,2,9,7,1,2,4,2,3,2,3,3,2,2,7,2,6,3,3,13,4,2,4,3,2,5,3,2,17,7,4,2,7,2,12,6,6,3,2,2,7,3,4,3,11,5,5,2,9,3,4,2,4,3,6,11,4,5,3,11,16,2,1,2,8,10,21,2,3,3,1,2,10,2,8,3,4,6,8,2,8,2,6,2,0,3,0,2,13,3,7,13,16,2,8,5,3,2,14,2,9,5,6,19,14,2,12,2,4,2,14,2,8,3,4,14,6,14,0,2,9,2,1,2,4,6,0,5,11,13,3,2,3,2,6,3,5,3,3,5,2,5,3,7,0,2,3,2,2,2,4,2,0,5,16,2,9,2,1,5,3,3,3,3,0,2,8,6,10,7,10,2,1,2,14,3,5,6,2,14,3,5,3,2,9,2,0,2,8,2,8,5,3,2,7,13,5,7,0,5,2,3,1,2,8,5,6,6,0,2,2,19,0,2,4,11,9,5,32,7,4,3,4,5,6,3,5,12,3,2,6,5,2,5,10,2,1,2,8,5,23,2,1,5,18,2,7,5,7,2,8,3,0,13,14,2,6,11,5,3,7,2,7,2,10,13,10,3,5,2,7,11,2,3,0,5,3,2,6,2,8,2,3,3,2,2,2,3,5,2,3,5,5,2,7,2,7,10,16,2,1,7,0,3,4,2,5,2,7,11,3,19,18,2,4,2,6,5,7,6,6,3,5,7,4,2,7,5,10,2,1,2,37,3,4,3,2,2,9,3,1,5,3,5,3,17,26,2,6,6,8,3,4,6,7,2,10,3,8,2,4,2,10,3,2,3,3,2,7,2,7,2,6,2,0,3,2,5,5,7,0,2,6,7,10,3,0,2,6,5,23,3,3,2,2,13,16,2,3,2,3,2,6,13,40,3,6,2,7,3,0,5,6,2,11,3,9,3,5,3,9,2,3,3,3,3,7,3,2,5,3,19,3,2,3,19,2,5,3,3,2,3,4,5,2,2,3,2,0,2,6,5,10,2,1,2,2,17,17,5,20,2,3,3,2,2,5,2,12,3,2,2,6,2,2,6,4,2,2,3,0,5,9,2,6,2,12,11,20,2,19,5,4,5,7,2,6,6,8,5,2,10,8,2,7,2,0,3,4,5,1,2,0,2,7,5,12,3,3,10,0,2,3,3,4,2,8,5,7,2,0,11,4,2,6,3,2,5,5,7,2,12,3,11,7,7,0,2,8,7,6,5,6,3,3,17,48,2,8,2,6,3,6,2,3,3,5,5,7,6,4,3,5,7,0,2,4,2,7,2,8,2,7,3,4,3,8,5,3,5,0,5,7,11,11,2,0,3,2,2,7,3,6,5,18,11,23,5,5,6,3,3,2,5,2,2,2,2,8,7,11,3,6,5,10,2,8,3,6,17,20,14,2,7,10,2,8,5,7,7,6,6,0,3,5,2,7,3,9,7,4,3,1,2,9,2,3,5,6,2,3,2,8,5,14,2,9,17,20,7,8,2,6,29,2,5,1,5,9,7,2,10,22,2,4,2,7,3,0,13,3,10,4,2,1,3,0,3,7,13,4,2,2,7,10,3,6,2,0,7,0,3,3,2,1,3,0,2,4,7,4,13,4,3,4,3,0,21,12,2,4,6,10,3,2,2,4,2,3,3,2,2,2,3,4,2,19,5,11,2,7,2,9,11,5,2,0,2,19,2,8,2,4,3,2,14,7,3,2,3,7,5,10,3,3,3,9,2,2,3,2,5,4,7,3,2,4,6,5,3,3,3,2,2,7,3,1,7,0,5,10,5,3,2,1,6,3,5,6,2,10,13,0,2,1,2,2,13,6,2,8,10,6,2,8,13,42,3,6,2,8,3,0,5,3,14,8,2,9,14,7,7,12,6,8,2,8,2,2,3,2,2,8,11,16,2,6,5,5,5,10,7,13,2,7,3,6,3,13,5,3,2,2,2,10,14,2,14,9,2,2,11,6,3,2,5,10,3,6,11,7,3,5,3,1,7,0,3,4,7,0,2,3,12,5,2,6,11,16,3,2,3,7,6,8,3,2,5,6,2,0,2,2,11,6,5,6,2,2,2,15,3,2,19,40,2,1,6,7,3,5,6,10,2,11,14,2,2,7,2,8,2,2,5,11,13,0,3,7,2,7,6,10,2,3,7,2,3,5,3,13,3,4,3,3,2,8,2,8,2,10,5,14,3,4,2,1,5,11,3,5,3,12,3,6,5,7,11,2,11,12,3,11,7,6,5,6,2,7,3,8,7,0,3,9,2,7,10,2,2,8,11,3,2,4,2,7,3,0,3,2,13,7,5,6,3,3,2,6,5,10,11,10,2,6,10,5,3,3,3,1,2,0,3,4,3,6,2,0,7,5,6,2,2,4,5,3,3,16,5,5,6,2,2,1,2,8,2,8,13,2,10,25,3,4,2,6,5,1,3,15,13,16,2,3,3,4,3,2,2,13,5,14,3,6,2,4,2,3,2,10,7,2,5,6,3,0,2,6,7,7,5,11,2,2,5,16,2,3,3,6,2,8,3,6,2,4,3,46,6,6,6,0,5,3,2,8,7,20,2,7,7,7,7,0,10,5,2,1,3,2,14,8,2,12,2,9,3,3,13,5,13,6,5,23,10,3,3,6,10,1,5,7,3,4,2,8,2,3,3,0,5,6,23,24,2,8,2,9,3,1,5,8,2,2,3,8,2,8,5,6,2,7,2,8,7,12,3,7,2,3,3,3,2,8,3,6,5,2,5,2,2,6,2,3,2,7,2,6,3,2,2,12,11,3,2,2,3,2,2,6,2,10,11,2,2,3,2,8,6,2,3,6,3,2,6,4,3,2,11,2,5,2,14,12,2,12,7,2,7,13,3,3,2,2,3,2,3,0,11,5,3,3,2,4,2,3,11,12,2,13,2,10,2,8,3,0,2,11,3,5,2,3,5,6,7,16,17,4,5,12,3,2,2,6,3,13,3,2,3,7,2,6,5,10,3,2,2,2,2,6,2,6,2,7,2,3,2,8,3,1,2,17,3,2,2,6,3,7,3,3,5,3,2,7,5,18,7,18,2,7,2,12,11,28,3,1,2,2,5,2,2,6,2,13,19,42,2,7,7,3,5,20,3,0,3,5,3,1,2,4,3,6,6,8,2,7,19,0,2,3,7,8,5,5,2,3,11,14,6,19,3,17,2,2,5,8,6,10,6,5,5,2,5,16,7,22,7,6,2,3,2,14,5,10,2,1,11,3,2,7,6,9,2,2,2,5,6,11,2,6,6,3,2,8,5,11,3,11,7,2,3,7,2,7,2,9,2,3,2,8,12,6,6,3,2,12,3,1,11,2,2,2,2,7,3,2,7,6,11,31,3,2,5,14,5,2,2,0,2,12,5,3,3,5,3,3,7,5,5,14,6,4,2,11,3,2,2,8,3,6,2,6,2,3,5,8,11,0,3,5,7,2,3,4,3,3,2,12,3,5,2,1,3,5,3,7,2,1,12,0,11,0,2,0,3,1,5,6,7,15,3,5,11,1,2,8,3,5,2,1,2,6,3,3,3,8,3,3,5,15,5,5,3,9,5,10,2,8,2,6,2,7,5,2,13,16,11,3,22,6,11,3,2,6,15,2,2,8,2,0,3,0,13,24,6,4,6,2,5,15,2,8,2,2,21,2,10,2,5,8,3,4,3,2,2,3,5,5,7,5,5,10,3,0,6,10,2,1,6,6,2,0,2,8,2,2,3,14,3,4,3,8,2,5,2,8,5,15,2,1,3,0,5,2,2,2,3,6,2,8,5,8,2,6,6,2,2,7,3,2,3,3,2,9,7,2,7,0,3,6,6,4,6,2,3,0,11,22,2,6,2,2,5,6,2,8,10,15,3,3,6,0,2,8,5,2,7,22,2,6,3,2,2,7,2,1,2,11,3,1,13,4,2,7,2,6,2,7,5,8,2,18,3,0,2,8,3,5,3,7,2,2,3,3,2,3,2,3,2,4,3,0,3,8,3,5,2,8,5,2,14,6,14,7,7,0,2,12,2,6,2,6,5,10,3,4,2,8,5,3,2,2,7,13,5,0,7,13,7,8,2,10,5,6,2,4,2,15,3,2,2,0,12,3,2,7,10,3,2,8,3,10,2,7,7,5,7,16,5,3,3,9,5,2,12,6,2,18,2,2,13,26,2,2,11,2,2,6,10,6,3,3,2,7,3,0,2,8,2,11,7,4,2,1,3,3,5,18,2,3,19,8,7,14,5,8,5,9,13,34,6,2,2,9,6,2,5,15,11,10,5,3,3,0,3,6,2,9,5,18,2,0,5,6,6,7,3,9,2,4,5,3,3,6,3,7,2,6,2,7,3,7,5,5,2,3,6,4,3,0,5,4,2,6,2,2,7,4,2,8,3,2,13,14,3,5,2,7,3,3,5,3,2,8,2,7,2,8,7,4,11,5,3,6,2,4,6,2,2,3,11,5,5,10,5,6,2,2,3,11,5,6,2,16,6,10,2,8,2,6,3,0,2,12,3,10,3,2,5,9,2,12,7,3,2,4,2,4,3,4,5,6,5,5,2,11,7,0,2,8,15,5,2,3,3,13,2,2,2,17,19,2,3,3,2,16,2,2,6,2,13,14,2,7,2,0,10,8,2,2,11,12,2,6,3,4,13,6,2,6,3,1,6,2,7,7,2,2,5,21,3,4,3,7,2,3,3,1,2,6,3,2,3,2,5,6,3,3,2,18,11,16,3,6,3,9,2,6,3,6,13,28,7,4,2,10,2,2,3,4,2,6,7,24,3,2,6,4,2,12,5,6,2,1,6,7,2,1,2,7,3,2,3,1,7,4,22,25,6,7,5,2,3,4,2,6,3,3,5,3,2,6,15,6,5,5,3,4,2,8,5,1,3,4,3,3,17,16,6,11,2,8,2,6,6,7,7,4,3,5,2,8,2,6,3,4,5,5,5,6,2,6,2,8,14,2,2,6,2,8,3,7,2,10,3,0,5,4,6,1,10,17,2,8,3,4,2,0,2,7,5,11,2,6,2,8,5,4,6,3,2,10,2,7,14,7,2,4,3,2,3,4,2,7,2,7,3,3,2,8,3,5,5,3,2,6,3,2,3,6,2,0,2,2,5,3,11,7,3,6,7,6,5,14,2,8,2,10,2,0,5,1,2,8,11,5,5,12,2,4,2,2,5,6,3,2,14,22,7,2,2,8,5,3,2,7,3,2,11,14,3,6,2,13,3,0,5,10,3,3,6,2,11,2,2,8,2,10,3,1,3,3,2,7,2,3,13,2,10,24,2,3,3,0,3,2,3,12,2,7,11,10,2,3,5,6,3,0,2,1,2,12,2,2,2,3,2,2,2,7,6,10,2,7,2,7,3,7,3,4,2,12,2,2,3,7,3,2,2,16,2,6,2,9,13,14,2,3,7,3,6,3,3,2,3,2,3,7,3,5,6,5,5,2,2,0,2,7,2,8,2,8,10,22,2,9,2,11,2,8,5,4,14,12,2,4,7,2,3,3,3,3,2,3,3,9,2,7,5,6,2,6,3,2,19,8,17,2,2,2,3,6,2,13,7,0,7,0,6,4,2,1,3,6,2,3,2,3,3,2,13,0,10,8,3,3,2,7,2,7,3,1,5,3,3,7,2,4,2,3,5,12,2,1,2,4,5,6,19,7,5,4,2,8,5,5,6,11,2,8,5,6,2,3,5,10,29,36,2,2,2,2,3,2,2,6,2,8,2,16,18,7,2,10,5,10,3,15,3,6,3,6,2,4,2,3,2,9,5,3,2,4,6,3,3,2,3,2,17,18,11,9,3,3,2,3,7,6,17,11,2,4,7,4,11,20,7,11,5,8,3,4,5,3,5,6,2,3,5,1,2,6,3,26,2,3,2,4,2,6,3,7,5,7,29,4,2,6,10,0,3,6,7,4,14,0,2,10,3,4,6,10,6,0,2,2,5,2,2,3,2,2,2,12,31,6,2,6,5,6,11,8,3,0,5,15,2,7,5,2,2,6,3,2,2,2,2,3,3,1,2,2,34,13,5,5,3,6,3,5,2,16,2,6,2,3,6,2,2,4,5,3,2,3,11,3,2,6,2,3,10,15,2,0,2,15,2,19,15,10,5,11,17,20,2,0,3,2,5,12,2,4,3,10,2,11,7,0,3,7,17,22,2,10,7,11,11,5,2,10,3,2,7,4,7,26,5,3,2,8,5,1,3,1,2,1,2,8,2,2,2,9,2,8,15,8,2,7,11,12,3,3,23,6,3,7,3,4,7,0,5,20,2,11,2,2,3,7,5,6,2,12,29,25,2,7,3,0,2,16,6,2,2,8,5,3,2,7,2,8,7,10,6,3,5,2,5,6,3,1,2,6,2,8,22,0,2,1,3,7,14,2,2,7,2,2,2,8,3,11,5,3,5,2,2,10,13,14,5,0,2,8,2,1,2,7,3,6,7,2,2,7,3,1,11,2,2,10,11,10,2,7,2,9,2,8,2,9,3,22,11,5,14,10,3,3,2,6,3,7,2,7,5,4,13,2,2,6,3,3,2,11,2,8,2,13,3,2,17,3,3,4,10,5,2,3,6,3,3,8,7,0,3,1,13,3,3,5,2,8,5,5,5,3,7,17,2,8,2,6,5,18,7,0,3,2,2,6,7,4,3,0,2,1,2,7,2,22,3,24,2,2,3,3,2,4,5,6,3,3,2,10,13,23,6,5,2,11,3,0,14,2,5,5,3,3,2,3,2,6,2,17,7,2,10,22,3,7,2,15,23,16,3,3,2,1,2,2,2,4,2,2,17,14,2,0,3,4,2,7,22,6,2,1,7,2,5,9,5,7,3,3,3,3,23,8,5,10,3,1,11,10,2,4,5,1,2,8,2,3,6,0,3,3,5,11,2,6,13,2,2,7,3,0,14,8,2,10,3,3,2,7,5,7,7,24,2,9,2,10,5,3,11,3,3,6,3,5,3,3,3,2,5,6,2,11,2,8,3,3,5,6,3,2,6,0,2,8,2,6,3,3,5,10,2,7,3,4,6,8,3,7,17,20,5,2,5,3,5,5,2,7,5,3,7,2,2,7,11,2,2,1,2,4,3,11,2,3,5,20,11,16,2,4,5,14,7,12,17,30,3,0,2,8,6,0,5,3,7,0,2,1,6,7,7,2,7,8,6,2,2,7,3,3,3,2,11,4,2,1,6,6,5,6,17,21,2,12,2,13,2,28,5,6,3,3,10,10,2,3,11,6,7,0,3,20,17,4,2,8,23,47,2,1,2,6,3,2,3,2,6,6,3,0,2,8,5,5,2,9,2,7,10,6,3,0,2,1,2,8,5,3,3,7,5,2,3,4,2,3,7,4,3,3,3,4,2,2,5,3,11,6,2,6,10,8,2,11,2,8,2,12,13,10,3,4,2,7,2,10,5,5,2,6,3,4,2,10,5,6,2,9,13,16,2,3,5,3,3,3,7,4,15,3,5,3,13,16,2,6,2,13,3,2,3,0,7,0,6,2,2,3,2,12,2,8,13,7,3,6,5,5,3,7,2,12,6,8,3,2,2,2,2,11,2,7,6,8,3,3,5,15,2,1,2,4,2,6,10,3,3,6,7,5,6,4,2,3,5,0,5,12,3,14,2,12,3,4,7,10,2,6,3,4,2,8,13,4,34,32,2,3,2,8,6,3,2,7,2,3,2,8,6,3,3,0,5,10,2,8,7,5,2,6,5,4,31,26,6,0,5,14,11,5,2,0,7,7,11,22,3,3,3,0,2,9,3,2,3,7,3,2,2,3,2,2,2,2,2,12,2,3,5,16,3,1,26,29,3,6,2,8,2,6,6,3,3,2,14,8,6,12,7,2,3,8,5,14,2,1,6,5,2,10,5,3,7,0,3,0,5,11,2,10,11,2,2,7,6,5,2,2,3,4,14,8,5,8,2,6,2,7,2,3,2,8,3,0,10,10,5,8,3,11,6,5,6,0,2,8,3,3,11,10,2,8,3,5,7,5,6,7,11,7,13,30,2,8,2,3,3,0,5,1,3,2,2,8,5,3,2,14,3,3,2,7,3,2,5,14,2,11,3,0,5,5,5,4,2,7,2,2,3,5,7,4,35,8,6,2,2,2,2,12,3,0,5,10,2,11,11,24,5,10,2,6,3,3,5,0,3,12,22,12,3,5,2,8,5,7,2,18,2,4,5,2,13,8,3,0,6,0,2,2,7,19,3,0,2,8,2,2,2,8,3,2,5,2,14,10,2,2,2,7,11,2,5,6,2,7,15,14,2,7,2,0,11,2,2,4,3,3,5,5,11,3,5,11,13,0,15,13,3,4,7,14,3,2,13,6,2,2,2,17,3,3,2,10,3,0,7,5,5,6,3,0,11,27,6,2,3,3,2,9,2,4,6,7,5,6,2,8,2,4,6,2,7,0,3,5,2,2,5,5,2,3,3,6,2,2,2,4,3,3,2,3,2,2,5,4,7,2,11,20,5,11,5,7,2,9,2,8,5,10,3,7,10,2,2,3,3,3,2,4,11,2,14,20,2,3,5,3,5,6,5,18,3,6,2,10,3,10,2,8,5,12,5,23,2,7,2,8,5,8,2,8,10,0,10,16,2,6,2,6,3,1,2,2,2,8,5,3,2,6,3,4,5,3,7,6,5,10,3,8,3,5,2,0,2,8,2,4,6,2,3,4,10,6,3,3,2,0,3,0,2,3,2,4,5,3,3,3,2,8,5,6,13,28,2,9,2,3,5,2,11,6,7,6,3,4,3,0,3,12,2,1,13,4,2,7,3,6,2,2,11,5,5,10,7,11,5,6,2,4,2,7,3,12,7,2,3,6,3,6,5,8,5,7,2,4,3,7,3,5,3,11,7,26,2,3,3,7,2,1,3,2,3,5,2,6,5,0,43,4,17,9,2,2,2,10,3,3,2,8,3,3,2,8,3,2,14,12,2,3,2,1,5,4,5,10,3,14,2,10,3,2,2,2,2,10,2,7,5,6,2,2,2,2,2,6,5,6,5,0,7,8,5,3,2,6,3,3,3,4,3,11,2,12,2,4,10,6,6,7,3,0,13,16,2,2,3,2,2,3,3,2,26,0,2,2,2,5,3,3,3,6,2,13,6,8,7,17,2,9,3,1,2,7,2,6,2,4,3,3,5,6,3,7,2,6,5,1,5,5,2,3,6,6,3,7,2,6,2,1,5,3,3,11,2,8,5,9,2,3,3,0,11,14,2,6,2,20,3,4,10,0,5,10,3,12,3,7,3,4,6,0,11,7,2,0,2,2,5,6,2,6,10,2,11,2,3,4,5,7,3,0,2,10,5,11,5,6,2,3,2,12,2,3,6,2,11,20,2,8,7,1,2,8,7,5,7,12,3,5,2,7,3,0,2,6,2,7,5,7,5,2,22,26,2,3,2,2,2,12,6,2,2,8,5,2,2,2,3,6,2,2,3,2,2,6,2,1,11,2,2,8,3,0,7,2,2,6,3,5,2,14,2,3,3,2,7,11,5,5,2,10,3,3,3,13,7,25,5,8,2,7,5,3,13,7,2,5,3,3,3,0,10,8,5,15,2,1,5,1,6,2,3,0,6,1,2,7,2,2,3,2,5,2,5,6,7,14,2,1,2,7,2,6,2,10,2,3,3,5,6,6,37,29,2,6,2,7,5,8,2,4,7,4,7,10,2,8,2,7,2,0,3,12,11,12,2,2,3,6,2,6,5,7,5,3,17,16,2,3,3,7,2,8,3,0,5,3,11,9,13,22,3,3,17,8,2,8,2,3,2,6,2,6,6,6,2,8,5,14,13,4,2,2,2,10,7,2,6,2,2,8,23,4,3,6,2,7,5,4,3,4,5,6,2,4,2,8,3,8,10,0,7,8,13,33,5,3,3,0,6,0,2,9,2,4,3,3,5,2,2,8,5,2,2,9,2,6,3,5,2,7,10,12,2,3,3,1,2,1,6,6,3,0,3,2,5,3,2,10,3,7,5,8,2,8,2,6,6,7,2,6,2,7,2,12,2,8,2,4,2,8,3,5,10,6,3,2,7,6,2,11,7,7,2,18,5,15,3,2,2,2,2,9,2,18,7,4,2,0,7,2,17,20,5,3,2,12,7,14,13,6,5,6,2,6,3,2,2,2,5,6,2,6,2,3,3,4,5,8,17,32,2,12,3,0,2,4,2,6,3,0,3,12,2,9,3,6,2,2,2,3,12,2,5,3,11,8,2,4,3,7,10,0,2,8,3,4,3,0,19,2,6,6,3,6,5,5,6,0,2,6,3,2,2,7,3,8,3,4,6,6,11,6,6,4,2,6,3,26,2,6,2,4,2,6,7,12,11,7,3,4,3,7,11,22,10,2,3,0,2,8,2,9,26,22,2,6,2,2,11,3,3,6,2,3,3,2,6,3,2,10,3,0,11,2,13,3,3,3,2,8,3,3,3,0,5,0,5,6,7,0,7,3,3,6,2,7,2,7,5,15,2,4,3,2,2,0,5,8,3,3,2,6,2,8,6,2,3,12,2,4,10,5,3,11,7,6,11,24,2,6,3,1,5,5,2,2,5,10,3,4,5,11,21,2,2,6,3,4,11,3,2,7,3,2,2,12,6,0,2,12,2,7,2,2,3,1,31,30,2,0,2,0,6,3,2,19,2,11,2,2,6,7,10,24,10,2,5,8,2,12,11,27,7,4,5,10,3,0,3,8,2,8,3,0,3,5,2,9,5,7,5,6,13,7,3,6,3,2,13,4,3,0,2,12,5,9,2,6,3,4,2,8,2,2,7,2,5,16,2,14,2,1,5,6,3,2,2,8,2,3,3,3,2,0,2,6,11,3,2,13,6,3,2,13,7,8,2,2,2,6,7,6,6,4,7,20,2,6,18,9,3,3,6,12,3,1,2,10,2,8,5,5,2,4,6,10,2,10,3,1,2,4,17,4,11,20,2,4,5,6,2,12,5,7,3,12,2,7,3,0,3,5,2,1,3,0,5,7,2,9,7,9,2,2,3,3,3,1,2,6,2,2,2,9,7,4,6,9,31,17,3,5,17,7,5,6,2,7,3,2,3,3,2,11,7,3,13,14,2,6,5,3,2,3,7,16,5,5,7,17,6,12,2,2,3,6,17,4,14,16,3,12,2,6,2,2,2,7,2,10,2,8,3,3,2,2,5,6,3,5,7,4,2,8,2,2,2,8,11,18,2,8,2,3,2,7,3,0,2,2,5,9,3,1,5,10,2,6,5,20,3,7,3,2,2,3,2,6,11,2,2,4,2,6,2,8,13,16,5,6,5,4,6,4,2,2,2,3,3,2,2,10,7,12,2,1,2,1,2,10,2,12,2,6,2,6,5,4,5,12,5,6,15,2,3,6,6,2,3,4,7,5,2,6,5,14,11,4,17,22,2,4,2,7,2,7,5,16,2,7,7,3,31,32,5,6,2,8,5,3,3,3,5,5,2,2,2,6,7,2,2,8,3,3,2,1,5,34,2,2,7,16,3,3,2,4,6,0,6,11,11,6,2,3,11,0,2,0,5,10,2,12,3,7,11,8,2,8,2,9,3,0,2,1,2,3,7,9,2,3,3,2,5,6,11,3,3,3,5,10,5,5,7,14,5,18,2,2,3,2,2,12,13,14,3,7,3,0,5,9,2,8,2,6,2,8,2,8,13,5,3,6,2,10,2,8,3,4,5,10,2,4,7,12,5,3,2,4,3,11,5,14,3,4,3,13,2,12,6,7,2,8,11,23,5,6,2,9,2,8,2,14,13,14,3,1,12,3,2,6,3,3,7,10,5,10,6,0,3,2,3,0,3,12,5,3,7,12,5,10,2,2,3,2,2,2,2,12,7,2,3,11,6,5,2,6,10,0,3,3,6,12,14,7,10,0,3,3,3,9,3,3,5,1,3,0,2,2,2,4,13,6,2,3,3,3,6,8,5,5,7,11,5,6,3,4,3,2,10,8,5,16,2,3,3,12,3,6,2,8,7,2,3,0,2,3,3,7,21,8,7,10,5,1,3,0,5,2,3,3,2,1,2,2,2,8,2,8,5,11,6,2,11,23,3,6,2,8,5,8,3,5,3,0,2,2,14,12,2,7,6,16,5,3,3,0,2,11,2,8,3,2,3,2,3,1,7,4,6,3,2,7,5,4,7,0,2,7,6,7,19,2,5,14,2,6,2,8,3,0,2,16,3,0,5,3,6,0,2,8,5,1,7,0,5,2,5,11,6,2,2,2,2,3,6,7,19,14,2,6,2,2,5,14,5,3,7,6,7,10,6,10,2,2,26,14,5,5,3,7,2,6,6,5,5,5,5,3,11,2,3,2,2,0,5,3,3,11,7,2,6,7,2,7,11,5,5,17,7,0,3,6,3,4,3,3,3,9,5,14,2,1,3,2,6,0,2,2,5,12,2,20,7,5,13,3,6,0,2,8,2,6,6,0,2,11,3,15,2,10,2,8,43,3,2,6,2,2,12,0,3,3,7,2,7,0,2,12,3,5,2,1,13,5,3,5,3,5,22,4,3,7,13,2,2,12,11,5,2,8,6,4,2,12,2,6,5,7,5,18,3,2,2,2,2,7,11,7,2,1,5,5,3,3,5,10,7,7,7,13,2,8,3,7,5,8,5,11,2,3,6,3,2,8,5,5,2,8,14,2,2,2,6,6,5,3,2,9,6,10,3,3,2,8,2,13,10,6,2,4,7,8,17,28,3,3,2,9,2,7,2,6,2,7,3,4,5,9,2,3,6,4,2,4,2,7,2,3,10,8,2,3,2,9,5,8,11,22,2,8,2,6,3,5,2,14,17,20,3,2,2,10,3,7,7,0,2,12,3,2,5,6,2,13,2,2,3,3,6,3,6,0,7,0,3,7,5,3,7,22,5,23,2,8,5,2,17,3,2,8,2,2,5,0,10,6,3,0,3,5,3,0,3,6,2,8,5,4,5,6,5,6,2,3,2,8,19,3,5,11,3,4,5,3,2,1,3,2,2,7,23,22,2,7,2,4,2,14,6,7,6,4,2,6,3,0,7,4,3,3,2,7,5,16,2,3,3,2,2,6,5,15,3,6,2,2,11,6,13,15,7,2,2,1,2,6,2,10,5,6,5,7,23,4,2,9,2,8,7,17,2,2,3,4,7,17,2,7,6,8,5,3,2,8,3,6,5,18,3,3,5,2,3,6,2,7,10,19,2,14,2,1,3,0,5,6,2,6,5,3,19,13,23,21,2,1,3,7,7,3,3,4,10,3,2,1,2,10,13,6,5,12,6,8,2,4,5,12,2,0,11,14,5,3,2,1,2,7,7,4,3,2,7,2,2,1,5,3,2,11,14,10,3,6,2,1,5,20,3,7,3,5,2,6,5,18,7,9,3,9,5,19,3,0,2,1,3,3,2,8,7,0,2,9,6,12,3,6,2,4,10,15,10,2,5,4,2,15,7,7,13,14,20,5,2,13,3,2,6,7,3,1,7,3,2,6,13,2,6,4,2,8,19,5,2,3,10,8,3,0,7,0,2,9,2,2,5,15,2,8,6,6,11,10,2,7,3,3,2,11,3,4,2,15,11,12,5,5,6,10,5,7,2,2,2,8,10,20,2,6,3,2,3,4,2,8,14,0,2,6,3,7,3,3,5,3,2,6,15,5,2,0,5,12,2,18,3,17,23,14,3,2,5,9,2,8,5,3,6,10,7,3,3,6,2,4,13,6,11,2,7,1,6,8,5,7,2,22,6,10,2,10,3,4,6,2,2,12,2,6,6,7,6,0,2,6,3,0,2,8,5,8,13,3,13,6,2,8,3,5,5,12,3,3,3,1,3,2,5,8,3,6,5,9,7,17,2,4,6,7,3,6,2,0,11,7,3,7,2,2,3,4,2,2,17,1,3,6,5,16,2,4,5,3,3,12,14,2,5,2,5,6,23,14,2,3,2,10,5,25,2,6,3,3,2,0,6,3,15,15,5,6,11,22,2,12,2,0,6,8,3,4,2,8,3,3,3,0,7,16,7,2,5,8,6,5,2,8,2,0,2,10,5,3,2,3,2,3,3,2,2,2,5,5,3,7,12,0,2,28,2,7,3,2,3,5,2,2,2,10,11,7,7,14,3,3,2,4,6,2,3,0,2,7,2,1,3,0,6,3,3,1,3,6,5,7,3,6,3,0,2,9,2,8,2,12,3,2,6,4,3,8,2,3,19,5,17,38,6,4,2,1,3,23,2,8,11,3,5,17,3,8,3,6,19,20,2,4,11,3,3,0,5,3,2,5,2,6,7,4,2,17,3,14,3,9,14,8,2,2,2,6,2,3,3,2,3,2,2,2,2,0,3,3,5,14,2,9,2,7,5,2,2,8,5,2,2,0,5,7,14,16,2,7,10,7,3,4,3,4,11,5,3,0,5,10,3,7,2,6,11,6,10,12,3,0,5,3,3,3,2,3,3,3,3,4,2,7,5,14,7,24,2,3,15,0,2,8,2,6,10,12,3,2,3,2,17,3,3,5,5,3,3,0,3,3}; uint32_t __nmod_poly_cp_lg_coeffs6[] = {48035,53504,44768,65547,60449,59509,39899,56596,39688,48691,65597,46802,64483,53051,54892,58463,54810,52138,39057,58874,35742,62355,63124,56730,65715,37642,61963,65398,51201,52108,36642,41666,64129,56209,38189,36484,44421,60917,46761,56823,54248,65915,45196,64135,62325,38212,62459,52265,37433,42133,47483,51490,49893,41503,33376,43702,66077,64179,59363,47832,36824,36306,34612,48656,46239,40036,43440,38430,33897,36555,66277,63257,53293,52402,40724,54358,64893,37215,46399,46989,39202,43779,49019,35848,47564,38103,47685,46693,42163,46700,34453,49134,50298,57958,61968,66124,46349,47462,42297,37334,45627,37302,37184,66675,51165,39641,51248,51624,49817,51010,41570,61431,34439,63890,46537,59124,49306,35751,53354,60261,61991,57414,34328,40264,63458,41480,49609,42749,52267,59718,66950,60937,47327,60348,66503,40294,45952,36231,66160,66482,46520,59667,40335,44101,47157,35718,42216,60531,64015,44657,40205,39121,34897,66762,34141,63758,52068,47479,63238,54686,36213,62964,60185,38062,39869,67339,50278,38219,40053,37548,67397,40791,39383,54909,62571,62067,60311,45967,54738,34031,65362,34037,34518,52043,44628,40415,46327,37219,65191,36628,66797,65404,58765,67233,66360,44755,51169,40363,66816,59915,50938,38763,36882,67733,39889,67753,60346,50484,54147,57395,62008,44970,44975,46696,64028,60029,41571,54474,42483,47030,67897,53290,67921,50804,56500,41694,58354,67949,67963,65282,58210,67982,66480,53027,50643,61367,63651,61008,56605,56197,58986,56253,50319,61180,53531,57650,66709,34705,48877,67030,42806,64746,54053,62806,35999,44735,39570,67918,43445,67493,65782,68435,68443,61208,59060,64640,35912,44684,64941,59518,46230,44205,36372,48277,67315,63503,39927,43600,35758,61618,39801,57459,48273,68676,50345,44701,43127,48329,68717,56637,68739,52637,36909,54749,48049,46092,57442,65671,58139,68855,60045,68855,43114,47010,59615,36021,65803,38485,52010,60274,53458,64207,67000,63999,47422,52075,55096,59670,69060,41305,53659,35190,69123,43087,56221,57951,69156,53053,35071,68453,68459,45363,35325,50195,59921,68051,39845,59152,67033,51122,48687,69333,38806,53834,69379,45620,58645,66102,49466,60664,68321,66848,47263,43474,44504,56254,35320,61830,56279,49301,36956,37857,61280,35040,40852,46057,67391,54995,38932,59497,40589,41714,54923,43287,60380,62123,50037,45311,66053,41766,62115,57258,43449,54267,40066,65475,69902,51163,69231,43594,54329,68518,67197,63569,42929,60077,38012,51654,37283,68098,69150,40728,45248,57088,47614,36468,50832,42365,69186,42002,43249,51571,65289,70179,53238,54788,42032,37478,47017,56553,53215,41688,68323,64290,47250,53424,56400,36964,68433,63404,51044,57535,56129,48327,70419,59245,36995,57297,60784,51996,48650,44704,45627,64881,44678,56755,62941,56638,54714,70566,70579,49075,58381,61619,41805,53445,61082,36137,54656,59153,70671,57901,39997,48128,63030,53835,36793,53597,63787,48633,69291,38090,66950,68822,54683,43553,65467,67460,42051,39710,54135,56041,62905,57780,51988,61783,57757,66178,61011,38359,66744,49875,58735,68825,41189,43626,69416,39634,67357,43019,70219,46222,42472,66960,59112,51451,47696,45847,55561,65919,70494,71246,66274,54562,41172,67279,52171,71323,42666,49522,42483,71337,55724,41313,44808,52079,44921,46466,35931,40070,71406,68999,50209,54737,36676,37951,41094,45163,56282,47456,68586,39248,36582,70584,64114,58689,60317,36565,70889,38013,59824,51461,43839,55090,67291,63239,38247,47165,63829,65142,51693,58795,48870,71795,68346,47183,41955,37674,43545,57037,55662,58652,51859,55991,65761,71061,41181,62443,48283,67395,71956,40745,64115,47287,53608,57398,62742,55350,41388,62811,59135,48859,42757,72077,60530,63163,57940,46459,45029,44064,72163,37026,47862,62661,42079,63494,60882,71628,72242,36427,58151,65518,66880,72283,64560,62407,39917,58293,55199,62623,51422,71622,66249,58708,43369,61622,60664,36542,69682,36734,54638,64635,72540,41107,46343,72566,57646,69042,59960,49227,72643,47012,62100,61218,72662,41235,69268,72694,55870,63204,64380,62105,52065,50862,44380,68786,40745,39509,42403,72862,49897,40725,59320,52422,65487,42627,39056,55043,60579,39982,52415,65046,72933,45763,45322,60557,61290,38041,47919,44880,59389,66445,58871,48207,40351,43963,42292,73123,72158,43993,47002,55841,65241,71712,61316,73273,69472,62926,66589,73323,42910,65865,51499,73359,70828,72262,73380,53155,37199,48227,72911,49334,73467,68628,70827,53158,46328,42582,66601,64744,42718,68944,63211,41254,51616,66527,72074,37537,56357,51879,67415,57691,64280,57935,58210,67161,39653,53276,73715,42278,53235,43300,72176,46285,38688,73843,54332,68126,51175,51052,72698,62054,38461,73468,67134,65283,73949,69985,37849,60515,66942,60175,66570,59760,65525,69539,48470,56842,74094,73228,74139,60624,74147,61232,46898,73054,74182,61162,46682,59268,72874,45079,64699,62236,74270,74283,45178,43437,69621,42707,65969,44387,64986,53504,58041,60053,74367,63354,52255,52003,74429,43654,67106,38724,70962,45482,66467,71684,56896,45219,67291,74549,74563,55217,74114,50072,48007,41939,39560,37632,48383,61778,72057,47033,67732,52460,65169,46647,52370,68112,57690,53812,65169,67484,74817,53210,46151,65225,42453,59239,43349,52027,62207,45677,44783,74899,74919,74910,56989,38035,74955,75001,68366,45462,43015,55138,60728,49811,38728,70881,63032,57023,57173,73433,59133,61827,45746,75197,53922,65957,64366,38702,74289,43719,61218,53931,63503,66690,39729,75317,59122,55916,49497,54296,47702,50980,62947,64247,47857,75403,64329,52905,54717,75499,63924,58652,39797,55610,71048,61862,49539,41269,41127,75551,57532,56351,49824,38524,74529,75252,63291,66607,61237,44590,75677,49498,44851,62812,68593,47760,62967,48472,42560,74581,73821,53297,39226,46250,38658,48073,57594,39825,49747,46134,42999,58727,75963,49107,66619,72681,61459,67184,53826,45793,61858,48240,67672,46107,48161,66436,71301,67204,76086,43774,75162,68242,64513,73692,65965,56446,42989,56790,59618,58288,76254,57665,54581,75307,62666,58212,68296,76355,40673,67788,67684,74011,76407,48662,54082,47297,39574,53589,42860,69273,54082,59686,42941,76534,40615,46886,50427,43441,58855,73867,70497,56278,52165,62005,66368,55592,50870,45082,56050,39385,49527,71492,76766,67454,48804,66753,61574,58581,60173,50138,58549,60065,41684,55765,52470,48489,69382,72266,76949,67494,55398,55719,64348,75692,58146,60137,61257,75574,77069,72956,40000,71265,77137,46439,39536,55211,70075,60243,41850,56993,61017,52825,52093,59385,77251,60416,73786,56247,65473,67074,59021,51352,63248,39544,55517,42002,74267,66656,57001,48070,43837,65461,44438,69614,64095,68695,47151,46053,70285,61075,39718,77539,58006,52072,42053,56342,77530,52860,50630,39037,73968,58808,77614,76166,60310,73063,77669,53507,62425,52513,66066,43614,76382,58596,53946,44481,77740,39193,65208,75933,43634,77783,46881,39991,53594,77859,41264,40695,75848,47811,67619,55967,70513,42830,54514,59423,77217,54087,61180,69721,46692,44202,40845,72401,66847,73578,77255,47619,76509,44736,57237,54881,59080,46298,77518,46801,72963,75215,57170,78267,47118,49151,64618,46637,45633,57293,65609,78355,77775,49267,46740,39762,65667,68429,74525,53802,78505,41910,78510,78532,64106,78542,52115,74274,67410,40331,64531,68027,72708,65412,61309,45000,63442,71814,40959,50674,45214,60761,60950,44740,75674,40272,67871,70667,64605,56477,43368,50889,76077,76365,57880,60182,59423,60797,74576,74478,72076,74142,60274,65252,52820,46887,75219,79059,47249,53185,58142,41941,75121,79140,67901,67468,79155,69094,57992,72932,57322,57924,79227,77951,44765,79262,52356,60361,54740,46121,44979,61604,60327,60161,65224,79355,78891,76492,72098,67608,79404,49546,76844,58499,44750,46790,56334,44457,76539,74949,68022,77151,60920,52849,40116,72499,63052,78990,78996,79619,44968,44055,44344,48111,49652,42715,47978,58007,51791,79757,75249,45329,77043,41146,77684,58590,48036,59475,41769,73592,40440,48936,59499,59347,50778,46371,70669,42155,46832,41208,65729,67881,54593,55896,64502,63575,51580,72344,50443,49161,40428,45203,79392,40809,70486,53569,65523,43355,71491,51587,59881,48958,56865,61268,72373,56406,78779,48238,66155,50740,60988,43863,63865,51392,59368,52202,80356,80357,57221,68664,41322,52770,67212,71746,74835,71800,76331,65304,63782,67798,52088,79065,45384,42304,75776,65341,44131,48667,58369,77638,79013,72929,69647,62240,59236,66673,67080,68049,63594,60140,71585,56384,57078,41715,75803,59014,78391,71007,73319,63312,76540,80837,59199,44553,72495,65970,47894,75107,56800,52283,73436,74575,56470,70314,62924,69703,73095,75713,66505,75738,79030,63890,81030,44123,77672,59721,42547,56209,69730,44016,76125,46963,75089,64088,62182,58312,81196,81211,72077,51287,62754,61273,72331,69876,75198,64308,80036,48042,66025,42040,47683,49604,80763,78971,68224,57820,81446,44020,41409,71606,81523,66135,66662,79472,81542,63371,56504,59997,81604,51777,55990,55131,50077,75177,56420,41578,75110,67242,73754,76131,74069,70729,43365,52507,63911,48137,44810,59239,54243,78131,55689,74376,74007,72549,72373,69257,76496,51057,79907,62686,59549,58809,77324,51046,56121,65809,62385,72624,62069,82009,54552,70086,63270,62947,65454,63700,63046,44113,55716,46076,75805,44300,74480,76121,50705,82203,80903,69126,71062,44407,74473,82229,55032,67823,82275,49980,52422,49544,51170,82347,56310,67086,54542,55968,46757,77652,78808,49032,48843,80432,78103,77844,53676,76333,71002,75326,46110,63452,75309,68679,80871,75332,82589,58894,47546,69694,58355,59623,48337,75912,72837,61102,62324,82710,72493,45072,52949,64996,42141,72993,46750,43150,66458,77577,61464,55847,82877,72806,73894,68256,44621,52130,49573,54972,46629,82997,47178,47635,53800,78249,43185,57821,48300,58833,78175,60873,73266,61245,67888,80501,71402,73515,42363,49723,79225,42837,59600,77915,74469,70147,44145,67642,77318,81383,55141,83375,81043,45528,60294,83403,60180,63381,76750,80169,44134,42049,71233,69008,75305,46830,55121,66055,83549,58344,44355,83582,71004,75159,45680,69792,43072,61860,80330,49846,73739,53413,73333,65689,43562,65650,51690,61569,73069,63896,46024,48028,62309,63809,70093,47157,83899,67617,42888,65209,43773,53813,65906,75739,68532,68671,51858,44102,66685,52237,58797,57127,81912,62032,78301,48372,84139,70983,73594,84174,84182,46401,54952,82432,53831,42439,68558,60526,71886,63350,58693,53362,42483,54492,83844,66228,67026,44813,65740,72744,79795,78870,53302,59837,75808,78305,78551,60009,74475,60446,51269,43248,55675,61147,57944,61937,68949,55918,60868,74132,61193,62937,78406,57484,61794,56204,75971,49463,74698,45992,46079,56766,43010,64891,47901,75166,71505,47337,63494,84033,59239,59778,66439,73940,70169,77330,81274,68727,65886,48347,66190,46408,75704,57937,47435,51697,68635,73852,69501,52263,57947,69098,71033,71135,71810,69923,51289,60997,85190,63597,71391,65949,84816,47471,68405,85243,63812,57173,71357,77832,46636,72738,44557,61217,64954,67497,48210,79618,50139,85430,46532,67788,72121,85465,61207,75894,55533,50514,77821,55721,85564,70921,43941,57286,43057,84127,64858,85620,85635,66957,68797,70694,54576,53620,72072,84740,73875,51237,57604,61366,78800,63942,43548,62106,57416,85830,61435,85843,76113,49293,44603,73309,64320,54460,69614,71115,79304,86006,77272,56318,83006,82618,45544,60598,75500,65408,68761,67832,78747,48931,48630,58736,62841,66956,47936,61514,81264,66854,86237,45060,68526,85210,67760,45154,76062,71712,64381,77742,64182,72249,52875,45402,86357,46150,66569,74249,83534,55786,86006,86429,68996,52347,68868,81636,65433,81054,81483,85699,66465,49584,72627,54557,73124,67004,44640,57171,85044,64843,84972,55253,55000,57420,71675,49384,75157,48986,71195,56575,68698,82049,52412,54827,74284,84997,53726,54590,59244,70834,53450,83694,55630,73143,69207,51121,48638,82915,84714,77323,82393,84135,59950,74077,82394,58638,82060,79783,49705,79521,56367,73538,46572,43996,70413,84598,81055,78421,69139,70778,85436,71729,65226,64889,77751,60246,57913,71352,75760,79194,55107,81011,61148,52544,62593,44636,48219,65234,80161,62448,80313,75300,47703,63377,61089,81453,64239,62832,73976,84795,45093,81843,69085,69345,81868,86979,52502,73497,84308,80235,76787,87178,52724,85003,86693,72924,58923,47423,87747,87763,81599,61351,83146,86300,55388,72141,47212,67457,63538,47133,80044,87254,83876,81473,87950,64659,68687,74554,50810,73068,45385,55334,53516,69629,55880,49692,65214,65820,76899,82590,47824,44598,66757,72822,61281,77291,82703,55821,76602,74290,60040,87076,55904,78778,75084,69314,79157,82450,88459,55759,46755,57070,77171,73337,69774,77053,61714,65659,88595,64549,60879,54690,61668,77749,88655,69703,79580,85597,76589,69371,60687,68103,52808,45894,88790,60014,88803,86213,45904,70968,56474,88836,58554,85821,85769,58644,48911,88877,53184,66274,79818,88947,52073,72906,83220,63678,88587,48720,85906,49844,52231,62232,65186,80263,84206,60314,50989,88590,57056,79322,60119,73978,76538,82558,83761,78469,83322,82947,54243,78562,47531,89262,82440,73019,70612,47251,80083,71387,75314,48063,76759,70160,53441,78153,66268,63805,65879,72948,48498,67764,89484,88832,49461,66672,77349,56588,50430,58735,67302,56806,79892,76712,68467,78467,51932,74306,87516,47869,46656,66021,77196,83849,88834,73283,72351,50779,61326,78492,68963,87272,50080,62438,53125,61199,48463,74019,86502,89882,54108,83993,52838,71569,77197,79281,58162,66614,72067,50744,77048,58023,70111,51361,65711,59043,45731,80184,86329,72422,46751,49992,48964,88445,46823,87998,55920,86484,88312,60563,53565,72994,67144,90195,87602,86753,82857,51383,72406,52953,67902,70020,69885,88188,79362,76295,65545,49256,79573,84894,54060,51970,90395,79758,60092,71719,74211,45930,71957,80865,85970,61759,52506,87647,52710,90579,57709,54153,46200,75393,77187,52402,76125,90670,78993,85335,75915,64890,67657,49247,55921,61253,51188,90817,90149,51966,51367,84626,90859,80344,65844,90903,69833,65494,70813,69616,65157,77733,58819,84198,81745,79315,91022,73240,49467,57390,86394,74214,50315,73326,73038,74979,90724,88955,81521,53788,76981,69107,57553,74540,54395,91235,88547,78562,52796,46882,75899,53758,91297,81982,78831,58816,63406,85807,67182,79072,49266,61380,82479,60385,62412,85056,84182,86817,53089,50634,65693,91517,57756,55807,91145,55670,90626,91587,68885,74108,68529,83024,73690,91699,69581,69673,85710,50197,75038,61413,89177,91803,74995,61823,78435,48907,64452,67015,79986,54536,62926,53264,60751,82295,70115,78886,91963,69462,55417,86036,54896,50748,64681,74667,60404,67601,52323,83816,67374,65197,61292,80029,73491,85229,56701,69284,61932,47606,88520,74044,66244,83218,73491,77657,57158,89997,76088,75472,46963,59252,52873,68580,84567,46885,64984,92379,54274,91487,72727,51430,92412,75729,54438,76655,50389,62711,92477,83399,88006,62292,86841,72826,85427,72794,92582,68484,56687,70281,47585,75648,91796,60388,71451,53959,79305,57116,51708,51068,84707,63648,72599,57683,56897,67277,90004,66713,64287,49917,70472,92813,51923,79914,92846,89454,63894,63074,68537,86070,92909,92915,62327,47140,64421,60236,61611,74567,81131,52220,84425,60438,82908,48340,67299,54524,46816,82056,50691,86194,81769,74064,89770,79311,54248,61765,83093,66356,55403,90259,69769,92449,78965,84093,92225,93283,92778,58537,69739,58619,93326,89104,77700,61397,62820,52904,52093,71770,64398,62766,85764,51730,64208,73856,56264,52065,50187,58144,52052,87503,49564,87932,81215,55991,66153,85296,60736,65243,48177,67929,60347,56073,51543,58891,93797,61705,53937,53104,59140,73264,69762,75439,88746,87317,68389,88020,48278,88961,60276,85776,62226,54012,92921,68986,49707,93970,75335,58138,80469,61800,57861,52964,81390,90076,86182,94109,69112,66094,94157,53642,92735,56115,53294,70338,66238,91249,51158,51537,60382,64258,92510,57050,90761,70590,70560,62113,75264,76959,67118,47481,57405,74611,61560,94435,73343,92533,48946,74549,70277,73810,86720,54415,75384,66411,57069,83257,94579,67430,89653,81968,47865,79805,54714,77788,54942,82155,94716,61647,80561,68212,61064,86227,76763,61930,65216,71968,94819,55689,79982,79653,64470,63762,63113,72731,83172,94926,93796,93929,73412,72892,67981,88963,94997,93750,69054,86191,85185,65786,67780,62743,79129,65026,59108,57452,71012,95139,74243,60159,83204,93882,48274,87737,49786,61498,68408,49752,75830,62802,48970,83479,80857,85970,69780,48647,81502,79802,76681,73155,74291,48825,68600,93540,75302,91825,64280,84420,89914,78567,72918,86754,93236,82183,76672,67779,95542,78911,92540,69439,77240,53811,74245,89689,51163,75190,81910,78245,64406,79947,81045,66923,69479,79467,74356,89150,95779,74195,84161,59716,55773,58590,52328,66217,70183,61085,80960,80263,77739,75116,52044,48312,93508,84588,55515,53167,85476,68967,75790,93294,67724,74901,93405,77432,81412,81898,78031,68855,85623,87206,79292,96177,62765,59834,75652,96219,94954,94201,71103,55930,96269,55587,71802,58808,51241,67123,74628,71768,93121,67648,51814,68311,94119,75576,84928,60988,90351,56985,96483,62411,62856,88676,67420,80776,67702,59621,76978,67855,63429,79925,59902,54005,92488,48909,49867,61297,52379,75132,49212,79768,65086,78211,92856,86895,92267,67656,53675,68098,87707,83225,62054,73630,94442,65057,52910,60283,94602,81272,49922,77350,71391,50855,75690,56471,73660,58337,89245,64947,90865,68961,59869,97123,89716,86477,59421,97157,65438,65272,87090,91750,56787,97229,83125,56145,56394,70350,82939,81613,87306,86367,66311,73755,65200,74074,57360,97425,66484,68677,89451,63961,61863,80183,90201,97516,79551,93801,54418,81708,54336,89843,63825,53026,97603,53535,96625,97207,84145,73017,62987,88700,51717,90080,92452,65537,88523,63890,90608,52449,54813,85087,64418,69466,92362,52802,81139,71286,83099,69330,91641,72877,51177,71612,89220,65742,80745,52900,66882,86782,98043,66944,65154,73751,75528,90198,79362,69135,75019,68474,64436,60233,58585,94292,49485,60788,57555,49805,98309,97436,64582,49445,55675,81792,94623,59966,85397,52914,88714,56713,85043,75524,88983,60098,50191,96260,66517,87406,54357,87373,84185,82017,88061,97685,97828,98612,51821,88232,78207,77646,59692,91235,83300,88728,64223,85831,96422,59469,77188,59519,77245,96652,64705,64513,98837,89513,92236,86974,98876,91158,84197,78657,88337,57552,98923,95329,89466,57547,82272,54403,98977,83315,66741,53070,86521,83330,95398,69467,63619,89229,69977,99099,99105,55145,78401,94358,83228,51038,90254,62125,83135,65978,99219,94614,58571,60280,87776,99252,75149,50603,71690,66879,56004,87376,90073,59447,95466,60075,99389,55067,96774,91222,56284,81536,60273,59386,50890,72102,92660,97156,54616,87056,63318,76108,52843,66058,88069,72041,68473,50357,58807,99678,81678,59397,82670,52361,67218,94954,75746,76539,55326,86930,74403,91887,63356,58958,76290,83927,57571,69176,80944,94555,76750,81363,88689,68784,95999,80658,65733,63566,98003,94727,80144,60696,50599,65117,84148,87453,85213,100142,85065,100157,61963,100182,54015,79012,52584,61791,100259,57533,51225,76569,80672,54952,82356,86579,54408,62889,97259,60895,70589,63844,80213,53510,78734,74631,76639,57663,88247,92806,50822,50675,55941,82185,62593,86031,56101,50629,79981,94786,87081,81955,96659,78430,55740,65991,55534,58357,81421,60875,52359,63140,58892,72686,67707,56231,68525,71888,86843,77189,66999,98156,95347,53940,77774,95053,74933,54986,91700,60984,84306,74909,96296,53688,96739,101054,79352,63437,83486,61375,90770,91989,69572,92023,50930,76253,92503,86538,99691,54187,59682,88094,65889,61316,74117,72475,53259,82421,101276,92263,65516,97244,61994,71845,97886,74202,70545,61665,101390,69358,96674,101422,85031,60770,86313,96436,101477,58912,84290,68932,92918,88370,83362,74293,99936,84763,65628,77791,92932,64823,90570,97121,101202,98655,89200,93804,77077,90529,70235,59738,78441,92827,57004,76676,84943,88983,97809,93760,64541,91279,65805,95574,86526,78537,54719,101906,58319,54509,88833,80402,76000,88974,99534,75721,83535,87162,97457,52974,66420,86820,100399,74291,59223,102070,59246,93738,88550,52675,96083,101687,54873,67310,89499,79839,85632,101416,97058,72290,62288,61249,98918,59922,101538,100725,57489,63103,77648,81415,83518,52333,92323,66798,69176,85977,55943,61943,57934,85850,57706,57206,64317,56652,54038,65832,69310,102532,92126,58879,81057,93025,87605,55795,70761,54237,59656,102643,53146,100718,102662,87685,65776,63466,79754,102756,57972,73589,66448,75581,72698,66555,86290,91554,89490,86668,84244,55630,65058,87941,52055,102956,100007,92108,63251,102487,97745,86256,79836,60715,85764,72821,77752,83855,100945,103133,95700,55642,84641,69497,93689,55872,103277,96681,55036,66378,72051,89966,74250,75077,99077,65275,103395,79050,65431,84181,65555,95339,99962,61867,102146,103517,61041,58725,101657,72790,60321,92578,86987,83774,88297,53087,88180,82461,101984,76248,79708,55186,95277,78562,83164,103757,97037,86695,73655,79788,92499,103829,93165,79812,79879,52905,87325,103910,77651,83403,90166,75541,69800,61321,73271,103982,75815,57229,103997,64314,70317,82234,100959,72611,87326,65453,100195,68904,101251,78232,67667,98807,86605,86281,69168,53198,104203,64988,68462,69062,70322,99646,63999,56603,75154,69756,53402,104323,100898,96656,69007,104379,59113,98018,98691,101660,71148,80426,68011,85947,62342,60643,76572,77726,60922,70500,61988,85884,92312,78156,75045,83282,55441,102978,91683,91337,74335,90701,93197,85720,92145,98245,99515,86801,84761,101184,96846,101520,54828,85032,104789,57748,81090,96444,104391,61997,81114,73074,104884,62542,65257,90338,87971,81890,72421,101949,55614,79633,94135,84131,74231,90097,69564,55342,98222,103361,95356,105155,77550,103097,55049,57345,105222,93426,82405,54633,105259,60321,86590,58606,95205,96671,79802,56459,78705,91628,101826,84771,70643,102396,80564,58077,84794,64232,54933,104342,82262,78421,57033,86419,60399,74025,75095,74680,54907,81753,73255,61332,80280,88206,70070,104477,101280,84802,94445,54090,103302,70314,56762,77423,78035,89313,68554,105750,80975,105822,83676,68994,58528,53380,102525,64189,105917,96487,67076,74907,105964,64467,98453,84705,54278,85099,94445,101451,106083,106099,84568,55610,94890,64933,86777,92499,91731,62156,104422,70417,65895,106215,96651,97618,62225,53503,62704,82469,96101,59249,73928,91359,95182,78048,85621,69834,66299,57873,89495,90435,104671,105281,82086,95480,102699,75881,95914,78899,106483,106494,73172,80739,86225,72749,90293,68024,100239,71429,99105,106637,60799,54836,106659,104118,79142,100556,82384,68234,65440,81877,91828,69594,86007,90199,105192,104271,99744,76629,75438,106819,53792,58647,92657,104933,71803,84310,106899,81631,79667,71137,89521,100199,61054,57105,85298,68696,62999,87292,88582,57579,100051,87186,107070,96108,87849,107093,97885,77610,59087,101625,65923,87303,78916,73503,62810,66189,79808,84140,86004,69237,80777,77205,54304,68776,87143,89342,97492,107429,87184,100577,106664,93041,101260,107505,91516,57281,76989,94082,73896,65807,91733,92136,90840,62234,60379,88066,100860,95667,96804,107737,107740,107027,101928,95854,72374,60617,63755,77835,99620,89097,60541,67841,105401,54316,70956,106785,107923,64633,103981,98229,96717,59088,86064,55179,75473,77798,80139,103451,70777,108075,75930,105736,62811,87299,64592,77447,108149,99577,71686,105936,69944,64580,58404,71451,72368,58932,102791,92442,65980,87705,75051,107723,103015,99766,100204,106815,104358,65781,73509,61123,78239,83691,66705,59975,108459,81126,92342,63561,89622,80774,90567,64993,88115,102067,92412,81296,92907,59747,108635,87737,82009,80616,81347,108723,63931,79316,108749,73877,58472,70431,94170,57904,68836,97718,57378,106422,103058,70048,92194,68489,95872,62872,81187,57198,70698,59113,77901,80916,71732,90013,80825,55462,70144,108989,102916,105116,109037,67465,83169,93654,85353,55735,109109,59368,61426,79949,100589,98795,100843,83228,95952,55710,61645,83105,68506,97367,58405,99462,95106,102362,67002,81855,61625,108266,83980,83806,62657,109382,74657,105318,90967,57513,72099,75295,58496,95240,97234,64343,76379,99769,109526,56063,67604,108285,73494,90581,105548,61160,76940,76843,74602,109635,109657,103620,72803,56797,90989,98434,108128,55492,79253,109803,89809,105285,103096,81116,77866,65590,91741,97735,56143,105350,83307,79199,81212,103200,109911,96530,109939,109949,100525}; flint-3.1.3/src/nmod_poly/cos_series.c000066400000000000000000000034321461254215100177260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_cos_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) { mp_ptr t, u; t = _nmod_vec_init(n); u = _nmod_vec_init(n); /* cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2) */ _nmod_vec_scalar_mul_nmod(u, h, n, n_invmod(UWORD(2), mod.n), mod); _nmod_poly_tan_series(t, u, n, n, mod); _nmod_poly_mullow(u, t, n, t, n, n, mod); _nmod_vec_neg(t, u, n, mod); t[0] = u[0] = UWORD(1); _nmod_poly_div_series(g, t, n, u, n, n, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_cos_series(nmod_poly_t g, const nmod_poly_t h, slong n) { mp_ptr h_coeffs; slong h_len = h->length; if (h_len > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_cos_series). Constant term != 0.\n"); } if (h_len == 1 || n < 2) { nmod_poly_zero(g); if (n > 0) nmod_poly_set_coeff_ui(g, 0, UWORD(1)); return; } nmod_poly_fit_length(g, n); if (h_len < n) { h_coeffs = _nmod_vec_init(n); flint_mpn_copyi(h_coeffs, h->coeffs, h_len); flint_mpn_zero(h_coeffs + h_len, n - h_len); } else h_coeffs = h->coeffs; _nmod_poly_cos_series(g->coeffs, h_coeffs, n, h->mod); if (h_len < n) _nmod_vec_clear(h_coeffs); g->length = n; _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/cosh_series.c000066400000000000000000000035741461254215100201050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_cosh_series(mp_ptr f, mp_srcptr h, slong n, nmod_t mod) { mp_ptr g = _nmod_vec_init(n); _nmod_poly_exp_expinv_series(f, g, h, n, n, mod); _nmod_vec_add(f, f, g, n, mod); _nmod_vec_scalar_mul_nmod(f, f, n, n_invmod(UWORD(2), mod.n), mod); _nmod_vec_clear(g); } void nmod_poly_cosh_series(nmod_poly_t g, const nmod_poly_t h, slong n) { mp_ptr g_coeffs, h_coeffs; nmod_poly_t t1; slong h_len; h_len = h->length; if (h_len > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_cosh_series). Constant term != 0.\n"); } if (h_len == 1 || n < 2) { nmod_poly_zero(g); if (n > 0) nmod_poly_set_coeff_ui(g, 0, UWORD(1)); return; } if (h_len < n) { h_coeffs = _nmod_vec_init(n); flint_mpn_copyi(h_coeffs, h->coeffs, h_len); flint_mpn_zero(h_coeffs + h_len, n - h_len); } else h_coeffs = h->coeffs; if (h == g && h_len >= n) { nmod_poly_init2(t1, h->mod.n, n); g_coeffs = t1->coeffs; } else { nmod_poly_fit_length(g, n); g_coeffs = g->coeffs; } _nmod_poly_cosh_series(g_coeffs, h_coeffs, n, h->mod); if (h == g && h_len >= n) { nmod_poly_swap(g, t1); nmod_poly_clear(t1); } g->length = n; if (h_len < n) _nmod_vec_clear(h_coeffs); _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/deflate.c000066400000000000000000000017771461254215100172060ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void nmod_poly_deflate(nmod_poly_t result, const nmod_poly_t input, ulong deflation) { slong res_length, i; if (deflation == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_deflate). Division by zero.\n"); } if (input->length <= 1 || deflation == 1) { nmod_poly_set(result, input); return; } res_length = (input->length - 1) / deflation + 1; nmod_poly_fit_length(result, res_length); for (i = 0; i < res_length; i++) result->coeffs[i] = input->coeffs[i*deflation]; result->length = res_length; } flint-3.1.3/src/nmod_poly/deflation.c000066400000000000000000000020611461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" ulong nmod_poly_deflation(const nmod_poly_t input) { ulong deflation; slong i, coeff; if (input->length <= 1) return input->length; coeff = 1; while (!input->coeffs[coeff]) coeff++; deflation = n_gcd(input->length - 1, coeff); while ((deflation > 1) && (coeff + deflation < input->length)) { for (i = 0; i < deflation - 1; i++) { coeff++; if (input->coeffs[coeff]) deflation = n_gcd(coeff, deflation); } if (i == deflation - 1) coeff++; } return deflation; } flint-3.1.3/src/nmod_poly/derivative.c000066400000000000000000000021241461254215100177270ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" void _nmod_poly_derivative(mp_ptr x_prime, mp_srcptr x, slong len, nmod_t mod) { slong j; mp_limb_t k = 1; for (j = 1; j < len; j++) { if (k <= 1) x_prime[j - 1] = k == 0 ? WORD(0) : x[j]; else x_prime[j - 1] = n_mulmod2_preinv(x[j], k, mod.n, mod.ninv); if (++k == mod.n) k = WORD(0); } } void nmod_poly_derivative(nmod_poly_t x_prime, const nmod_poly_t x) { if (x->length <= 1) { nmod_poly_zero(x_prime); return; } nmod_poly_fit_length(x_prime, x->length - 1); _nmod_poly_derivative(x_prime->coeffs, x->coeffs, x->length, x->mod); x_prime->length = x->length - 1; _nmod_poly_normalise(x_prime); } flint-3.1.3/src/nmod_poly/discriminant.c000066400000000000000000000024201461254215100202500ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" mp_limb_t _nmod_poly_discriminant(mp_srcptr poly, slong len, nmod_t mod) { mp_ptr der = _nmod_vec_init(len - 1); slong dlen = len - 1; mp_limb_t res, pow; _nmod_poly_derivative(der, poly, len, mod); NMOD_VEC_NORM(der, dlen); if (dlen == 0) { _nmod_vec_clear(der); return 0; } res = _nmod_poly_resultant(poly, len, der, dlen, mod); pow = n_powmod2_preinv(poly[len - 1], len - dlen - 2, mod.n, mod.ninv); res = n_mulmod2_preinv(res, pow, mod.n, mod.ninv); if ((len & 3) == 0 || (len & 3) == 3) /* degree is not 0, 1 mod 4 */ res = nmod_neg(res, mod); _nmod_vec_clear(der); return res; } mp_limb_t nmod_poly_discriminant(const nmod_poly_t f) { const slong len = f->length; if (len <= 1) return 0; else return _nmod_poly_discriminant(f->coeffs, len, f->mod); } flint-3.1.3/src/nmod_poly/div.c000066400000000000000000000041201461254215100163450ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_div(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenA == lenB) { Q[0] = nmod_div(A[lenA - 1], B[lenB - 1], mod); } else if (lenB == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, nmod_inv(B[0], mod), mod); } else { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); if (lenB <= 15 || lenA - lenB <= 15) GR_MUST_SUCCEED(_gr_poly_div_basecase(Q, A, lenA, B, lenB, ctx)); else GR_MUST_SUCCEED(_gr_poly_div_newton(Q, A, lenA, B, lenB, ctx)); } } void nmod_poly_div(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { nmod_poly_t tQ; mp_ptr q; slong A_len, B_len; B_len = B->length; if (B_len == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); return; } else { flint_throw(FLINT_ERROR, "Exception (nmod_poly_divrem). Division by zero.\n"); } } A_len = A->length; if (A_len < B_len) { nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2(tQ, A->mod.n, A_len - B_len + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, A_len - B_len + 1); q = Q->coeffs; } _nmod_poly_div(q, A->coeffs, A_len, B->coeffs, B_len, A->mod); if (Q == A || Q == B) { nmod_poly_swap(tQ, Q); nmod_poly_clear(tQ); } Q->length = A_len - B_len + 1; } flint-3.1.3/src/nmod_poly/div_newton_n_preinv.c000066400000000000000000000043741461254215100216520ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_div_newton_n_preinv(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_srcptr Binv, slong lenBinv, nmod_t mod) { const slong lenQ = lenA - lenB + 1; mp_ptr Arev; Arev = _nmod_vec_init(lenQ); _nmod_poly_reverse(Arev, A + (lenA - lenQ), lenQ, lenQ); _nmod_poly_mullow(Q, Arev, lenQ, Binv, FLINT_MIN(lenQ,lenBinv), lenQ, mod); _nmod_poly_reverse(Q, Q, lenQ, lenQ); _nmod_vec_clear(Arev); } void nmod_poly_div_newton_n_preinv(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t Binv) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1, lenBinv = Binv->length; mp_ptr q; if (lenB == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); return; } else { flint_throw(FLINT_ERROR, "Exception (nmod_poly_div_newton_n_preinv). Division by zero.\n"); } } if (lenA < lenB) { nmod_poly_zero(Q); return; } if (lenA > 2 * lenB - 2) { flint_printf ("Exception (nmod_poly_div_newton_n_preinv).\n"); } if (Q == A || Q == B || Q == Binv) { q = (mp_ptr) flint_malloc(lenQ * sizeof(mp_limb_t)); } else { nmod_poly_fit_length(Q, lenQ); q = Q->coeffs; } _nmod_poly_div_newton_n_preinv(q, A->coeffs, lenA, B->coeffs, lenB, Binv->coeffs, lenBinv, B->mod); if (Q == A || Q == B || Q == Binv) { flint_free(Q->coeffs); Q->coeffs = q; Q->alloc = lenQ; } Q->length = lenQ; } flint-3.1.3/src/nmod_poly/div_root.c000066400000000000000000000026521461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" mp_limb_t _nmod_poly_div_root(mp_ptr Q, mp_srcptr A, slong len, mp_limb_t c, nmod_t mod) { mp_limb_t r, t; slong i; if (len < 2) return UWORD(0); t = A[len - 2]; r = Q[len - 2] = A[len - 1]; for (i = len - 2; i > 0; i--) { r = nmod_add(nmod_mul(r, c, mod), t, mod); t = A[i-1]; Q[i-1] = r; } r = nmod_add(nmod_mul(r, c, mod), t, mod); return r; } mp_limb_t nmod_poly_div_root(nmod_poly_t Q, const nmod_poly_t A, mp_limb_t c) { mp_limb_t rem; slong len = A->length; if (len == 0) { nmod_poly_zero(Q); return UWORD(0); } if (len == 1) { rem = A->coeffs[0]; nmod_poly_zero(Q); return rem; } if (c == 0) { rem = A->coeffs[0]; nmod_poly_shift_right(Q, A, 1); return rem; } nmod_poly_fit_length(Q, len - 1); rem = _nmod_poly_div_root(Q->coeffs, A->coeffs, len, c, Q->mod); Q->length = len - 1; return rem; } flint-3.1.3/src/nmod_poly/div_series.c000066400000000000000000000076471461254215100177400ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_div_series_basecase_preinv1(mp_ptr Qinv, mp_srcptr P, slong Plen, mp_srcptr Q, slong Qlen, slong n, mp_limb_t q, nmod_t mod) { slong i, j, l; int nlimbs; mp_limb_t s; Plen = FLINT_MIN(Plen, n); Qlen = FLINT_MIN(Qlen, n); if (Qlen == 1) { _nmod_vec_scalar_mul_nmod(Qinv, P, Plen, q, mod); _nmod_vec_zero(Qinv + Plen, n - Plen); } else { Qinv[0] = nmod_mul(q, P[0], mod); nlimbs = _nmod_vec_dot_bound_limbs(FLINT_MIN(n, Qlen), mod); for (i = 1; i < n; i++) { l = FLINT_MIN(i, Qlen - 1); NMOD_VEC_DOT(s, j, l, Q[j + 1], Qinv[i - 1 - j], mod, nlimbs); if (i < Plen) s = nmod_sub(P[i], s, mod); else s = nmod_neg(s, mod); if (q != 1) Qinv[i] = nmod_mul(s, q, mod); else Qinv[i] = s; } } } void _nmod_poly_div_series_basecase(mp_ptr Qinv, mp_srcptr P, slong Plen, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { mp_limb_t q; q = Q[0]; if (q != 1) q = n_invmod(q, mod.n); _nmod_poly_div_series_basecase_preinv1(Qinv, P, Plen, Q, Qlen, n, q, mod); } void nmod_poly_div_series_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n) { slong Alen, Blen; Blen = B->length; if (n == 0 || Blen == 0 || B->coeffs[0] == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_div_series_basecase). Division by zero.\n"); } Alen = A->length; if (Alen == 0) { nmod_poly_zero(Q); return; } if (Q != A && Q != B) { nmod_poly_fit_length(Q, n); _nmod_poly_div_series_basecase(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, Q->mod); } else { nmod_poly_t t; nmod_poly_init2(t, Q->mod.n, n); _nmod_poly_div_series_basecase(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, Q->mod); nmod_poly_swap(Q, t); nmod_poly_clear(t); } Q->length = n; _nmod_poly_normalise(Q); } void _nmod_poly_div_series(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, slong n, nmod_t mod) { Blen = FLINT_MIN(Blen, n); if (Blen <= 5) { _nmod_poly_div_series_basecase(Q, A, Alen, B, Blen, n, mod); } else { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_div_series(Q, A, Alen, B, Blen, n, ctx)); } } void nmod_poly_div_series(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n) { slong Alen, Blen; Blen = B->length; if (n == 0 || Blen == 0 || B->coeffs[0] == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_div_series). Division by zero.\n"); } Alen = A->length; if (Alen == 0) { nmod_poly_zero(Q); return; } if (Q != A && Q != B) { nmod_poly_fit_length(Q, n); _nmod_poly_div_series(Q->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, Q->mod); } else { nmod_poly_t t; nmod_poly_init2(t, Q->mod.n, n); _nmod_poly_div_series(t->coeffs, A->coeffs, Alen, B->coeffs, Blen, n, Q->mod); nmod_poly_swap(Q, t); nmod_poly_clear(t); } Q->length = n; _nmod_poly_normalise(Q); } flint-3.1.3/src/nmod_poly/divexact.c000066400000000000000000000037041461254215100174010ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 William Hart Copyright (C) 2023, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_divexact(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenA == lenB) { Q[0] = nmod_div(A[lenA - 1], B[lenB - 1], mod); } else if (lenB == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, nmod_inv(B[0], mod), mod); } else { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_divexact(Q, A, lenA, B, lenB, ctx)); } } void nmod_poly_divexact(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { nmod_poly_t tQ; mp_ptr q; slong A_len, B_len; B_len = B->length; if (B_len == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); return; } else { flint_throw(FLINT_ERROR, "Exception (nmod_poly_divexact). Division by zero.\n"); } } A_len = A->length; if (A_len < B_len) { nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2(tQ, A->mod.n, A_len - B_len + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, A_len - B_len + 1); q = Q->coeffs; } _nmod_poly_divexact(q, A->coeffs, A_len, B->coeffs, B_len, A->mod); if (Q == A || Q == B) { nmod_poly_swap(tQ, Q); nmod_poly_clear(tQ); } Q->length = A_len - B_len + 1; } flint-3.1.3/src/nmod_poly/divides.c000066400000000000000000000124701461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" int _nmod_poly_divides(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { mp_ptr R; slong i, lenQ = lenA - lenB + 1; int res = 1; if (lenA < 40 && lenB < 20) return _nmod_poly_divides_classical(Q, A, lenA, B, lenB, mod); R = _nmod_vec_init(lenB - 1); if (lenA < 2*lenB - 1) { slong offset = 0; mp_ptr P; P = (mp_ptr) _nmod_vec_init(2*lenQ - 1); _nmod_vec_zero(R, lenB - 1); _nmod_poly_div(Q, A, lenA, B, lenB, mod); while (offset < lenB - 1) { if (offset + 2*lenQ - 1 < lenB) { _nmod_poly_mul(P, B + offset, lenQ, Q, lenQ, mod); _nmod_poly_add(R + offset, R + offset, 2*lenQ - 1, P, 2*lenQ - 1, mod); } else { _nmod_poly_mullow(P, Q, lenQ, B + offset, lenQ, lenB - offset - 1, mod); _nmod_poly_add(R + offset, R + offset, lenB - offset - 1, P, lenB - offset - 1, mod); } for (i = 0; i < FLINT_MIN(lenQ, lenB - offset - 1); i++) { if (R[offset + i] != A[offset + i]) { res = 0; break; } } offset += lenQ; } _nmod_vec_clear(P); } else { _nmod_poly_divrem(Q, R, A, lenA, B, lenB, mod); for (i = 0; i < lenB - 1; i++) { if (R[i] != 0) { res = 0; break; } } } _nmod_vec_clear(R); if (res == 0) _nmod_vec_zero(Q, lenQ); return res; } int nmod_poly_divides(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { nmod_poly_t tQ; mp_ptr q; slong lenA, lenB; int res; lenA = A->length; lenB = B->length; if (lenB == 0 || lenA < lenB) { nmod_poly_zero(Q); return lenA == 0; } if (Q == A || Q == B) { nmod_poly_init2(tQ, A->mod.n, lenA - lenB + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } res = _nmod_poly_divides(q, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (Q == A || Q == B) { nmod_poly_swap(tQ, Q); nmod_poly_clear(tQ); } Q->length = lenA - lenB + 1; _nmod_poly_normalise(Q); return res; } /* check if (p, n) = mullow(poly1, len1, poly2, n, n) where len1 > 0, n >= 0 */ static int _nmod_poly_mullow_classical_check(mp_srcptr p, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong n, nmod_t mod) { slong i, j, bits, log_len, nlimbs, n1; mp_limb_t c; len1 = FLINT_MIN(len1, n); if (n == 0) return 1; if (n == 1) return p[0] == nmod_mul(poly1[0], poly2[0], mod); log_len = FLINT_BIT_COUNT(n); bits = FLINT_BITS - (slong) mod.norm; bits = 2 * bits + log_len; if (bits <= FLINT_BITS) { for (i = 0; i < n; i++) { c = 0; for (j = 0; j <= FLINT_MIN(i, len1 - 1); j++) c += poly1[j] * poly2[i - j]; NMOD_RED(c, c, mod); if (p[i] != c) return 0; } } else { if (bits <= 2 * FLINT_BITS) nlimbs = 2; else nlimbs = 3; for (i = 0; i < n; i++) { n1 = FLINT_MIN(len1 - 1, i); c = _nmod_vec_dot_rev(poly1, poly2 + i - n1, n1 + 1, mod, nlimbs); if (p[i] != c) return 0; } } return 1; } int _nmod_poly_divides_classical(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { slong lenQ = lenA - lenB + 1; int res; _nmod_poly_div(Q, A, lenA, B, lenB, mod); /* check coefficients of product one at a time */ res = _nmod_poly_mullow_classical_check(A, Q, lenQ, B, lenB - 1, mod); if (!res) _nmod_vec_zero(Q, lenQ); return res; } int nmod_poly_divides_classical(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { nmod_poly_t tQ; mp_ptr q; slong lenA, lenB; int res; lenA = A->length; lenB = B->length; if (lenB == 0 || lenA < lenB) { nmod_poly_zero(Q); return lenA == 0; } if (Q == A || Q == B) { nmod_poly_init2(tQ, A->mod.n, lenA - lenB + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } res = _nmod_poly_divides_classical(q, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (Q == A || Q == B) { nmod_poly_swap(tQ, Q); nmod_poly_clear(tQ); } Q->length = lenA - lenB + 1; _nmod_poly_normalise(Q); return res; } flint-3.1.3/src/nmod_poly/divrem.c000066400000000000000000000054551461254215100170650ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 William Hart Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_divrem(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { mp_limb_t invB; if (lenA <= 20 || lenB <= 8 || lenA - lenB <= 6 || (NMOD_BITS(mod) <= 61 && lenA <= 40) || (NMOD_BITS(mod) <= 29 && lenA <= 70)) { invB = (B[lenB - 1] == 1) ? 1 : n_invmod(B[lenB - 1], mod.n); _nmod_poly_divrem_basecase_preinv1(Q, R, A, lenA, B, lenB, invB, mod); } else { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); #ifdef FLINT_HAVE_FFT_SMALL GR_MUST_SUCCEED(_gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, ctx)); #else if (NMOD_BITS(mod) >= 16 && lenB >= 1024 && lenA <= 16384) GR_MUST_SUCCEED(_gr_poly_divrem_divconquer(Q, R, A, lenA, B, lenB, 16, ctx)); else GR_MUST_SUCCEED(_gr_poly_divrem_newton(Q, R, A, lenA, B, lenB, ctx)); #endif } } void nmod_poly_divrem(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { const slong lenA = A->length, lenB = B->length; nmod_poly_t tQ, tR; mp_ptr q, r; if (lenB == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); nmod_poly_zero(R); return; } else { flint_throw(FLINT_ERROR, "Exception (nmod_poly_divrem). Division by zero."); } } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2_preinv(tQ, A->mod.n, A->mod.ninv, lenA - lenB + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } if (R == B) { nmod_poly_init2_preinv(tR, B->mod.n, B->mod.ninv, lenB - 1); r = tR->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (Q == A || Q == B) { nmod_poly_swap(Q, tQ); nmod_poly_clear(tQ); } if (R == B) { nmod_poly_swap(R, tR); nmod_poly_clear(tR); } Q->length = lenA - lenB + 1; R->length = lenB - 1; _nmod_poly_normalise(R); } flint-3.1.3/src/nmod_poly/divrem_basecase.c000066400000000000000000000227211461254215100207060ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" static slong NMOD_DIVREM_BC_ITCH(slong lenA, slong lenB, nmod_t mod) { const flint_bitcnt_t bits = 2 * (FLINT_BITS - mod.norm) + FLINT_BIT_COUNT(lenA - lenB + 1); if (bits <= FLINT_BITS) return lenA; else if (bits <= 2 * FLINT_BITS) return 2*(lenA + lenB - 1); else return 3*(lenA + lenB - 1); } void _nmod_poly_divrem_q0_preinv1(mp_ptr Q, mp_ptr R, mp_srcptr A, mp_srcptr B, slong lenA, mp_limb_t invL, nmod_t mod) { if (lenA == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, invL, mod); } else { Q[0] = nmod_mul(A[lenA-1], invL, mod); if (R == A) { _nmod_vec_scalar_addmul_nmod(R, B, lenA - 1, nmod_neg(Q[0], mod), mod); } else { _nmod_vec_scalar_mul_nmod(R, B, lenA - 1, Q[0], mod); _nmod_vec_sub(R, A, R, lenA - 1, mod); } } } void _nmod_poly_divrem_q1_preinv1(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_limb_t invL, nmod_t mod) { if (lenB == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, invL, mod); } else { mp_limb_t q0, q1, t, t0, t1, s0, s1; slong i; q1 = nmod_mul(A[lenA-1], invL, mod); t = nmod_mul(q1, B[lenB-2], mod); t = nmod_sub(t, A[lenA-2], mod); q0 = nmod_mul(t, invL, mod); R[0] = nmod_addmul(A[0], q0, B[0], mod); Q[0] = nmod_neg(q0, mod); Q[1] = q1; q1 = nmod_neg(q1, mod); if (mod.norm >= (FLINT_BITS + 1) / 2 + 1) { for (i = 1; i < lenB - 1; i++) { NMOD_RED2(R[i], 0, A[i] + q1*B[i - 1] + q0*B[i], mod); } } else if (mod.norm != 0) { for (i = 1; i < lenB - 1; i++) { umul_ppmm(t1, t0, q1, B[i - 1]); umul_ppmm(s1, s0, q0, B[i]); add_ssaaaa(t1, t0, t1, t0, 0, A[i]); add_ssaaaa(t1, t0, t1, t0, s1, s0); t1 = FLINT_MIN(t1, t1 - mod.n); FLINT_ASSERT(t1 < mod.n); NMOD_RED2(R[i], t1, t0, mod); } } else { for (i = 1; i < lenB - 1; i++) { t = A[i]; NMOD_ADDMUL(t, q1, B[i - 1], mod); NMOD_ADDMUL(t, q0, B[i], mod); R[i] = t; } } } } void _nmod_poly_divrem_basecase_preinv1_1(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_limb_t invL, nmod_t mod) { slong iR; mp_ptr ptrQ = Q - lenB + 1; mp_ptr R1 = W; flint_mpn_copyi(R1, A, lenA); for (iR = lenA - 1; iR >= lenB - 1; iR--) { if (R1[iR] == 0) { ptrQ[iR] = WORD(0); } else { ptrQ[iR] = n_mulmod2_preinv(R1[iR], invL, mod.n, mod.ninv); if (lenB > 1) { const mp_limb_t c = n_negmod(ptrQ[iR], mod.n); mpn_addmul_1(R1 + iR - lenB + 1, B, lenB - 1, c); } } } if (lenB > 1) _nmod_vec_reduce(R, R1, lenB - 1, mod); } void _nmod_poly_divrem_basecase_preinv1_2(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_limb_t invL, nmod_t mod) { slong iR, i; mp_ptr B2 = W, R2 = W + 2*(lenB - 1), ptrQ = Q - lenB + 1; for (i = 0; i < lenB - 1; i++) { B2[2 * i] = B[i]; B2[2 * i + 1] = 0; } for (i = 0; i < lenA; i++) { R2[2 * i] = A[i]; R2[2 * i + 1] = 0; } for (iR = lenA - 1; iR >= lenB - 1; ) { mp_limb_t r = n_ll_mod_preinv(R2[2 * iR + 1], R2[2 * iR], mod.n, mod.ninv); while ((iR + 1 >= lenB) && (r == WORD(0))) { ptrQ[iR--] = WORD(0); if (iR + 1 >= lenB) r = n_ll_mod_preinv(R2[2 * iR + 1], R2[2 * iR], mod.n, mod.ninv); } if (iR + 1 >= lenB) { ptrQ[iR] = n_mulmod2_preinv(r, invL, mod.n, mod.ninv); if (lenB > 1) { const mp_limb_t c = n_negmod(ptrQ[iR], mod.n); mpn_addmul_1(R2 + 2 * (iR - lenB + 1), B2, 2 * lenB - 2, c); } iR--; } } for (iR = 0; iR < lenB - 1; iR++) R[iR] = n_ll_mod_preinv(R2[2*iR+1], R2[2*iR], mod.n, mod.ninv); } void _nmod_poly_divrem_basecase_preinv1_3(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_limb_t invL, nmod_t mod) { slong iR, i; mp_ptr B3 = W, R3 = W + 3*(lenB - 1), ptrQ = Q - lenB + 1; for (i = 0; i < lenB - 1; i++) { B3[3 * i] = B[i]; B3[3 * i + 1] = 0; B3[3 * i + 2] = 0; } for (i = 0; i < lenA; i++) { R3[3 * i] = A[i]; R3[3 * i + 1] = 0; R3[3 * i + 2] = 0; } for (iR = lenA - 1; iR >= lenB - 1; ) { mp_limb_t r = n_lll_mod_preinv(R3[3 * iR + 2], R3[3 * iR + 1], R3[3 * iR], mod.n, mod.ninv); while ((iR + 1 >= lenB) && (r == WORD(0))) { ptrQ[iR--] = WORD(0); if (iR + 1 >= lenB) r = n_lll_mod_preinv(R3[3 * iR + 2], R3[3 * iR + 1], R3[3 * iR], mod.n, mod.ninv); } if (iR + 1 >= lenB) { ptrQ[iR] = n_mulmod2_preinv(r, invL, mod.n, mod.ninv); if (lenB > 1) { const mp_limb_t c = n_negmod(ptrQ[iR], mod.n); mpn_addmul_1(R3 + 3 * (iR - lenB + 1), B3, 3 * lenB - 3, c); } iR--; } } for (iR = 0; iR < lenB - 1; iR++) R[iR] = n_lll_mod_preinv(R3[3 * iR + 2], R3[3 * iR + 1], R3[3 * iR], mod.n, mod.ninv); } void _nmod_poly_divrem_basecase_preinv1(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_limb_t invB, nmod_t mod) { if (lenA == lenB + 1) { _nmod_poly_divrem_q1_preinv1(Q, R, A, lenA, B, lenB, invB, mod); } else if (lenA == lenB) { _nmod_poly_divrem_q0_preinv1(Q, R, A, B, lenB, invB, mod); } else if (lenB == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, invB, mod); } else { mp_ptr W; TMP_INIT; slong bits = 2 * (FLINT_BITS - mod.norm) + FLINT_BIT_COUNT(lenA - lenB + 1); TMP_START; W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, mod)*sizeof(mp_limb_t)); if (bits <= FLINT_BITS) _nmod_poly_divrem_basecase_preinv1_1(Q, R, W, A, lenA, B, lenB, invB, mod); else if (bits <= 2 * FLINT_BITS) _nmod_poly_divrem_basecase_preinv1_2(Q, R, W, A, lenA, B, lenB, invB, mod); else _nmod_poly_divrem_basecase_preinv1_3(Q, R, W, A, lenA, B, lenB, invB, mod); TMP_END; } } void _nmod_poly_divrem_basecase(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { mp_limb_t invB; invB = (B[lenB - 1] == 1) ? 1 : n_invmod(B[lenB - 1], mod.n); _nmod_poly_divrem_basecase_preinv1(Q, R, A, lenA, B, lenB, invB, mod); } void nmod_poly_divrem_basecase(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { const slong lenA = A->length, lenB = B->length; nmod_poly_t tQ, tR; mp_ptr q, r; if (lenB == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); nmod_poly_zero(R); return; } else { flint_throw(FLINT_ERROR, "Exception (nmod_poly_divrem). Division by zero."); } } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2_preinv(tQ, A->mod.n, A->mod.ninv, lenA - lenB + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } if (R == B) { nmod_poly_init2_preinv(tR, B->mod.n, B->mod.ninv, lenB - 1); r = tR->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_divrem(q, r, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (Q == A || Q == B) { nmod_poly_swap(Q, tQ); nmod_poly_clear(tQ); } if (R == B) { nmod_poly_swap(R, tR); nmod_poly_clear(tR); } Q->length = lenA - lenB + 1; R->length = lenB - 1; _nmod_poly_normalise(R); } flint-3.1.3/src/nmod_poly/divrem_newton_n_preinv.c000066400000000000000000000056271461254215100223600ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_divrem_newton_n_preinv(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, mp_srcptr Binv, slong lenBinv, nmod_t mod) { const slong lenQ = lenA - lenB + 1; if (lenA == lenB + 1) { /* xxx: direction */ _nmod_poly_divrem_basecase_preinv1(Q, R, A, lenA, B, lenB, Binv[0], mod); return; } _nmod_poly_div_newton_n_preinv(Q, A, lenA, B, lenB, Binv, lenBinv, mod); if (lenB > 1) { if (lenQ >= lenB - 1) _nmod_poly_mullow(R, Q, lenQ, B, lenB - 1, lenB - 1, mod); else _nmod_poly_mullow(R, B, lenB - 1, Q, lenQ, lenB - 1, mod); _nmod_vec_sub(R, A, R, lenB - 1, mod); } } void nmod_poly_divrem_newton_n_preinv(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t Binv) { const slong lenA = A->length, lenB = B->length, lenBinv = Binv->length; mp_ptr q, r; if (lenB == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); nmod_poly_zero(R); return; } else { flint_throw(FLINT_ERROR, "Exception (nmod_poly_divrem_newton_n_preinv). Division by zero.\n"); } } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (lenA > 2 * lenB - 1) { flint_printf ("Exception (nmod_poly_divrem_newton_n_preinv).\n"); } if (Q == A || Q == B || Q == Binv) { q = _nmod_vec_init(lenA - lenB + 1); } else { nmod_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } if (R == A || R == B || R == Binv) { r = _nmod_vec_init(lenB - 1); } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_divrem_newton_n_preinv(q, r, A->coeffs, lenA, B->coeffs, lenB, Binv->coeffs, lenBinv, B->mod); if (Q == A || Q == B || Q == Binv) { _nmod_vec_clear(Q->coeffs); Q->coeffs = q; Q->alloc = lenA - lenB + 1; } if (R == A || R == B || R == Binv) { _nmod_vec_clear(R->coeffs); R->coeffs = r; R->alloc = lenB - 1; } Q->length = lenA - lenB + 1; R->length = lenB - 1; _nmod_poly_normalise(R); } flint-3.1.3/src/nmod_poly/equal.c000066400000000000000000000017521461254215100167020ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" int nmod_poly_equal(const nmod_poly_t a, const nmod_poly_t b) { if (a->length != b->length) return 0; if (a != b) if (!_nmod_vec_equal(a->coeffs, b->coeffs, a->length)) return 0; return 1; } int nmod_poly_equal_nmod(const nmod_poly_t poly, ulong cst) { if (cst == 0) return nmod_poly_is_zero(poly); else return (poly->length == 1 && poly->coeffs[0] == cst); } int nmod_poly_equal_ui(const nmod_poly_t poly, ulong cst) { return nmod_poly_equal_nmod(poly, nmod_set_ui(cst, poly->mod)); } flint-3.1.3/src/nmod_poly/equal_trunc.c000066400000000000000000000022371461254215100201140ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" int nmod_poly_equal_trunc(const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) { slong i, len1, len2; if (poly1 == poly2) return 1; /* same polynomial */ if (n < 0) n = 0; len1 = FLINT_MIN(poly1->length, n); len2 = FLINT_MIN(poly2->length, n); if (len1 < len2) { for (i = len1; i < len2; i++) { if (poly2->coeffs[i] != 0) return 0; } } else if (len2 < len1) { for (i = len2; i < len1; i++) { if (poly1->coeffs[i] != 0) return 0; } } for (i = 0; i < FLINT_MIN(len1, len2); i++) /* check if coefficients the same */ if (poly1->coeffs[i] != poly2->coeffs[i]) return 0; return 1; } flint-3.1.3/src/nmod_poly/evaluate_mat.c000066400000000000000000000071421461254215100202410ustar00rootroot00000000000000/* Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_mat.h" void nmod_mat_one_addmul(nmod_mat_t dest, const nmod_mat_t mat, mp_limb_t c) { slong i, j; if (dest == mat) { for (i = 0; i < mat->r; i++) { nmod_mat_entry(dest, i, i) = n_addmod(nmod_mat_entry(mat, i, i), c, mat->mod.n); } return; } for (i = 0; i < mat->r; i++) for (j = 0; j < mat->c; j++) { nmod_mat_entry(dest, i, j) = nmod_mat_entry(mat, i, j); if (i == j) { nmod_mat_entry(dest, i, i) = n_addmod(nmod_mat_entry(dest, i, i), c, mat->mod.n); } } } void _nmod_poly_evaluate_mat_horner(nmod_mat_t dest, mp_srcptr poly, slong len, const nmod_mat_t c) { slong m = len-1; nmod_mat_t temp; nmod_mat_zero(dest); if (len == 0) { return; } if (len == 1 || nmod_mat_is_zero(c)) { nmod_mat_one_addmul(dest, dest, poly[0]); return; } nmod_mat_init_set(temp, c); nmod_mat_one_addmul(dest, dest, poly[m]); for( m-- ; m >= 0 ; m--) { nmod_mat_mul(temp, dest, c); nmod_mat_one_addmul(dest, temp, poly[m]); } nmod_mat_clear(temp); } void nmod_poly_evaluate_mat_horner(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c) { nmod_mat_t temp; if (dest == c) { nmod_mat_init_set(temp, c); _nmod_poly_evaluate_mat_horner(dest, poly->coeffs, poly->length, temp); nmod_mat_clear(temp); } else { _nmod_poly_evaluate_mat_horner(dest, poly->coeffs, poly->length, c); } } void nmod_poly_evaluate_mat_paterson_stockmeyer(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c) { slong lim = n_sqrt(poly->length), i, j, rem, quo, curr; nmod_mat_t tmat, *temp; nmod_mat_zero(dest); if (poly->length == 0) { return; } if (poly->length == 1 || nmod_mat_is_zero(c)) { nmod_mat_one_addmul(dest, dest, poly->coeffs[0]); return; } temp = flint_malloc((lim + 1) * sizeof(nmod_mat_t)); nmod_mat_init(temp[0], c->r, c->c, c->mod.n); nmod_mat_one(temp[0]); nmod_mat_init(temp[1], c->r, c->c, c->mod.n); nmod_mat_set(temp[1], c); nmod_mat_init(tmat, c->r, c->c, c->mod.n); for (i = 2; i <= lim; i++) { nmod_mat_init(temp[i], c->r, c->c, c->mod.n); nmod_mat_mul(temp[i], temp[i - 1], c); } rem = (poly->length % lim); quo = poly->length / lim; curr = poly->length - rem - 1; for (i = 0; i < rem; i++) { nmod_mat_scalar_addmul_ui(dest, dest, temp[i], poly->coeffs[poly->length - rem + i]); } for (i = 0; i < quo; i++) { nmod_mat_mul(tmat, dest, temp[lim]); nmod_mat_scalar_addmul_ui(dest, tmat, temp[lim - 1], poly->coeffs[curr--]); for (j = 1; j < lim; j++) { nmod_mat_scalar_addmul_ui(dest, dest, temp[lim - 1 - j], poly->coeffs[curr--]); } } for (i = 0; i <= lim; i++) { nmod_mat_clear(temp[i]); } nmod_mat_clear(tmat); flint_free(temp); } flint-3.1.3/src/nmod_poly/evaluate_nmod.c000066400000000000000000000017501461254215100204140ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" mp_limb_t _nmod_poly_evaluate_nmod(mp_srcptr poly, slong len, mp_limb_t c, nmod_t mod) { slong m; mp_limb_t val; if (len == 0) return 0; if (len == 1 || c == 0) return poly[0]; m = len - 1; val = poly[m]; m--; for ( ; m >= 0; m--) { val = n_mulmod2_preinv(val, c, mod.n, mod.ninv); val = n_addmod(val, poly[m], mod.n); } return val; } mp_limb_t nmod_poly_evaluate_nmod(const nmod_poly_t poly, mp_limb_t c) { return _nmod_poly_evaluate_nmod(poly->coeffs, poly->length, c, poly->mod); } flint-3.1.3/src/nmod_poly/evaluate_nmod_vec.c000066400000000000000000000104411461254215100212460ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_evaluate_nmod_vec(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod) { if (len < 32) _nmod_poly_evaluate_nmod_vec_iter(ys, coeffs, len, xs, n, mod); else _nmod_poly_evaluate_nmod_vec_fast(ys, coeffs, len, xs, n, mod); } void nmod_poly_evaluate_nmod_vec(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n) { _nmod_poly_evaluate_nmod_vec(ys, poly->coeffs, poly->length, xs, n, poly->mod); } /* This gives some speedup for small lengths. */ static inline void _nmod_poly_rem_2(mp_ptr r, mp_srcptr a, slong al, mp_srcptr b, slong bl, nmod_t mod) { if (al == 2) r[0] = nmod_sub(a[0], nmod_mul(a[1], b[0], mod), mod); else _nmod_poly_rem(r, a, al, b, bl, mod); } void _nmod_poly_evaluate_nmod_vec_fast_precomp(mp_ptr vs, mp_srcptr poly, slong plen, const mp_ptr * tree, slong len, nmod_t mod) { slong height, i, j, pow, left; slong tree_height; slong tlen; mp_ptr t, u, swap, pa, pb, pc; /* avoid worrying about some degenerate cases */ if (len < 2 || plen < 2) { if (len == 1) vs[0] = _nmod_poly_evaluate_nmod(poly, plen, nmod_neg(tree[0][0], mod), mod); else if (len != 0 && plen == 0) _nmod_vec_zero(vs, len); else if (len != 0 && plen == 1) for (i = 0; i < len; i++) vs[i] = poly[0]; return; } t = _nmod_vec_init(len); u = _nmod_vec_init(len); left = len; /* Initial reduction. We allow the polynomial to be larger or smaller than the number of points. */ height = FLINT_BIT_COUNT(plen - 1) - 1; tree_height = FLINT_CLOG2(len); while (height >= tree_height) height--; pow = WORD(1) << height; for (i = j = 0; i < len; i += pow, j += (pow + 1)) { tlen = ((i + pow) <= len) ? pow : len % pow; _nmod_poly_rem(t + i, poly, plen, tree[height] + j, tlen + 1, mod); } for (i = height - 1; i >= 0; i--) { pow = WORD(1) << i; left = len; pa = tree[i]; pb = t; pc = u; while (left >= 2 * pow) { _nmod_poly_rem_2(pc, pb, 2 * pow, pa, pow + 1, mod); _nmod_poly_rem_2(pc + pow, pb, 2 * pow, pa + pow + 1, pow + 1, mod); pa += 2 * pow + 2; pb += 2 * pow; pc += 2 * pow; left -= 2 * pow; } if (left > pow) { _nmod_poly_rem(pc, pb, left, pa, pow + 1, mod); _nmod_poly_rem(pc + pow, pb, left, pa + pow + 1, left - pow + 1, mod); } else if (left > 0) _nmod_vec_set(pc, pb, left); swap = t; t = u; u = swap; } _nmod_vec_set(vs, t, len); _nmod_vec_clear(t); _nmod_vec_clear(u); } void _nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, mp_srcptr poly, slong plen, mp_srcptr xs, slong n, nmod_t mod) { mp_ptr * tree; tree = _nmod_poly_tree_alloc(n); _nmod_poly_tree_build(tree, xs, n, mod); _nmod_poly_evaluate_nmod_vec_fast_precomp(ys, poly, plen, tree, n, mod); _nmod_poly_tree_free(tree, n); } void nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n) { _nmod_poly_evaluate_nmod_vec_fast(ys, poly->coeffs, poly->length, xs, n, poly->mod); } void _nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod) { slong i; for (i = 0; i < n; i++) ys[i] = _nmod_poly_evaluate_nmod(coeffs, len, xs[i], mod); } void nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n) { _nmod_poly_evaluate_nmod_vec_iter(ys, poly->coeffs, poly->length, xs, n, poly->mod); } flint-3.1.3/src/nmod_poly/exp_series.c000066400000000000000000000026351461254215100177420ustar00rootroot00000000000000/* Copyright (C) 2011, 2016, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_exp_series(mp_ptr f, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_exp_series(f, h, hlen, n, ctx)); } /* todo: gr version */ void _nmod_poly_exp_expinv_series(mp_ptr f, mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { _nmod_poly_exp_series(f, h, hlen, n, mod); _nmod_poly_inv_series(g, f, n, n, mod); } void nmod_poly_exp_series(nmod_poly_t f, const nmod_poly_t h, slong n) { slong hlen = h->length; if (hlen > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_exp_series). Constant term != 0.\n"); } if (n <= 1 || hlen <= 1) { if (n == 0) nmod_poly_zero(f); else nmod_poly_one(f); return; } nmod_poly_fit_length(f, n); _nmod_poly_exp_series(f->coeffs, h->coeffs, hlen, n, f->mod); f->length = n; _nmod_poly_normalise(f); } flint-3.1.3/src/nmod_poly/find_distinct_nonzero_roots.c000066400000000000000000000102021461254215100234020ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" /* split f assuming that f has degree(f) distinct nonzero roots in Fp */ void _nmod_poly_split_rabin( nmod_poly_t a, nmod_poly_t b, const nmod_poly_t f, nmod_poly_t t, nmod_poly_t t2, flint_rand_t randstate) { FLINT_ASSERT(nmod_poly_degree(f) > 1); nmod_poly_reverse(t, f, f->length); nmod_poly_inv_series_newton(t2, t, t->length); try_again: nmod_poly_zero(a); nmod_poly_set_coeff_ui(a, 1, 1); nmod_poly_set_coeff_ui(a, 0, n_randint(randstate, f->mod.n)); nmod_poly_powmod_ui_binexp_preinv(t, a, (f->mod.n - 1)/2, f, t2); nmod_poly_sub_ui(t, t, 1); nmod_poly_gcd(a, t, f); FLINT_ASSERT(!nmod_poly_is_zero(a)); if (0 >= nmod_poly_degree(a) || nmod_poly_degree(a) >= nmod_poly_degree(f)) { goto try_again; } nmod_poly_divexact(b, f, a); /* deg a >= deg b */ if (nmod_poly_degree(a) < nmod_poly_degree(b)) nmod_poly_swap(a, b); return; } /* If P has deg(P) distinct nonzero roots of P, fill them in and return 1. Otherwise return 0. Function is undefined for zero P. The modulus of P is assumed to be prime. */ int nmod_poly_find_distinct_nonzero_roots( mp_limb_t * roots, const nmod_poly_t P) { mp_limb_t a0, a1; int success; slong i, roots_idx, sp; nmod_poly_struct * a , * b; nmod_poly_t f, t, t2; nmod_poly_struct stack[FLINT_BITS + 1]; flint_rand_t randstate; slong d = nmod_poly_degree(P); if (d < 2) { if (d == 1) { a0 = nmod_poly_get_coeff_ui(P, 0); a1 = nmod_poly_get_coeff_ui(P, 1); if (a0 == 0) { return 0; } roots[0] = nmod_mul(a0, nmod_inv(P->mod.n - a1, P->mod), P->mod); } return 1; } if (P->mod.n == 2) return 0; if (P->coeffs[0] == 0) return 0; flint_randinit(randstate); nmod_poly_init_mod(t, P->mod); nmod_poly_init_mod(t2, P->mod); nmod_poly_init_mod(f, P->mod); for (i = 0; i <= FLINT_BITS; i++) nmod_poly_init_mod(stack + i, P->mod); roots_idx = 0; nmod_poly_make_monic(f, P); nmod_poly_reverse(t, f, f->length); nmod_poly_inv_series_newton(t2, t, t->length); a = stack + 0; nmod_poly_zero(a); nmod_poly_set_coeff_ui(a, 1, 1); nmod_poly_powmod_ui_binexp_preinv(t, a, (P->mod.n - 1)/2, f, t2); nmod_poly_sub_ui(t, t, 1); nmod_poly_gcd(a, t, f); b = stack + 1; nmod_poly_add_ui(t, t, 2); nmod_poly_gcd(b, t, f); if (nmod_poly_degree(b) + nmod_poly_degree(a) != d) { success = 0; goto cleanup; } /* deg a >= deg b */ if (nmod_poly_degree(a) < nmod_poly_degree(b)) { nmod_poly_swap(a, b); } sp = nmod_poly_degree(b) > 0 ? 2 : 1; while (sp > 0) { FLINT_ASSERT(sp < FLINT_BITS); sp--; nmod_poly_swap(f, stack + sp); FLINT_ASSERT(nmod_poly_degree(f) > 0); if (nmod_poly_degree(f) == 1) { a0 = nmod_poly_get_coeff_ui(f, 0); a1 = nmod_poly_get_coeff_ui(f, 1); FLINT_ASSERT(a0 != 0); FLINT_ASSERT(a1 == 1); roots[roots_idx] = P->mod.n - a0; roots_idx++; } else { _nmod_poly_split_rabin(stack + sp + 0, stack + sp + 1, f, t, t2, randstate); FLINT_ASSERT(FLINT_BIT_COUNT(nmod_poly_degree(stack + sp + 1)) <= FLINT_BITS - sp - 1); sp += 2; } } success = 1; cleanup: flint_randclear(randstate); nmod_poly_clear(t); nmod_poly_clear(t2); nmod_poly_clear(f); for (i = 0; i <= FLINT_BITS; i++) nmod_poly_clear(stack + i); FLINT_ASSERT((!success) || roots_idx == d); return success; } flint-3.1.3/src/nmod_poly/fit_length.c000066400000000000000000000012211461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void nmod_poly_fit_length(nmod_poly_t poly, slong alloc) { if (alloc > poly->alloc) { if (alloc < 2 * poly->alloc) alloc = 2 * poly->alloc; nmod_poly_realloc(poly, alloc); } } flint-3.1.3/src/nmod_poly/gcd.c000066400000000000000000000151261461254215100163300ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" slong _nmod_poly_gcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { slong cutoff = NMOD_BITS(mod) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; if (lenB < cutoff) return _nmod_poly_gcd_euclidean(G, A, lenA, B, lenB, mod); else return _nmod_poly_gcd_hgcd(G, A, lenA, B, lenB, mod); } void nmod_poly_gcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B) { if (A->length < B->length) { nmod_poly_gcd(G, B, A); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; nmod_poly_t tG; mp_ptr g; if (lenA == 0) /* lenA = lenB = 0 */ { nmod_poly_zero(G); } else if (lenB == 0) /* lenA > lenB = 0 */ { nmod_poly_make_monic(G, A); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { nmod_poly_init2(tG, A->mod.n, FLINT_MIN(lenA, lenB)); g = tG->coeffs; } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } lenG = _nmod_poly_gcd(g, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (G == A || G == B) { nmod_poly_swap(tG, G); nmod_poly_clear(tG); } G->length = lenG; if (G->length == 1) G->coeffs[0] = 1; else nmod_poly_make_monic(G, G); } } } slong _nmod_poly_gcd_euclidean(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { slong steps; slong lenR1, lenR2 = 0, lenG = 0; mp_ptr F, R1, R2, R3 = G, T; if (lenB == 1) { G[0] = B[0]; return 1; } F = _nmod_vec_init(2*lenB - 3); R1 = F; R2 = R1 + lenB - 1; _nmod_poly_rem(R1, A, lenA, B, lenB, mod); lenR1 = lenB - 1; MPN_NORM(R1, lenR1); if (lenR1 > 1) { _nmod_poly_rem(R2, B, lenB, R1, lenR1, mod); lenR2 = lenR1 - 1; MPN_NORM(R2, lenR2); } else { if (lenR1 == 0) { flint_mpn_copyi(G, B, lenB); _nmod_vec_clear(F); return lenB; } else { G[0] = R1[0]; _nmod_vec_clear(F); return 1; } } for (steps = 2; lenR2 > 1; steps++) { _nmod_poly_rem(R3, R1, lenR1, R2, lenR2, mod); lenR1 = lenR2--; MPN_NORM(R3, lenR2); T = R1; R1 = R2; R2 = R3; R3 = T; } if (lenR2 == 1) { lenG = 1; if (steps % 3) G[0] = R2[0]; } else { lenG = lenR1; if (steps % 3 != 1) flint_mpn_copyi(G, R1, lenR1); } _nmod_vec_clear(F); return lenG; } void nmod_poly_gcd_euclidean(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B) { if (A->length < B->length) { nmod_poly_gcd_euclidean(G, B, A); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; nmod_poly_t tG; mp_ptr g; if (lenA == 0) /* lenA = lenB = 0 */ { nmod_poly_zero(G); } else if (lenB == 0) /* lenA > lenB = 0 */ { nmod_poly_make_monic(G, A); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { nmod_poly_init2(tG, A->mod.n, FLINT_MIN(lenA, lenB)); g = tG->coeffs; } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } lenG = _nmod_poly_gcd_euclidean(g, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (G == A || G == B) { nmod_poly_swap(tG, G); nmod_poly_clear(tG); } G->length = lenG; if (G->length == 1) G->coeffs[0] = 1; else nmod_poly_make_monic(G, G); } } } slong _nmod_poly_gcd_hgcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { slong cutoff = NMOD_BITS(mod) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; slong lenG = 0; gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_gcd_hgcd(G, &lenG, A, lenA, B, lenB, NMOD_POLY_HGCD_CUTOFF, cutoff, ctx)); return lenG; } void nmod_poly_gcd_hgcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B) { if (A->length < B->length) { nmod_poly_gcd_hgcd(G, B, A); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; nmod_poly_t tG; mp_ptr g; if (lenA == 0) /* lenA = lenB = 0 */ { nmod_poly_zero(G); } else if (lenB == 0) /* lenA > lenB = 0 */ { nmod_poly_make_monic(G, A); } else /* lenA >= lenB >= 1 */ { if (G == A || G == B) { nmod_poly_init2(tG, A->mod.n, FLINT_MIN(lenA, lenB)); g = tG->coeffs; } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } lenG = _nmod_poly_gcd_hgcd(g, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (G == A || G == B) { nmod_poly_swap(tG, G); nmod_poly_clear(tG); } G->length = lenG; if (G->length == 1) G->coeffs[0] = 1; else nmod_poly_make_monic(G, G); } } } flint-3.1.3/src/nmod_poly/gcdinv.c000066400000000000000000000054161461254215100170460ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" slong _nmod_poly_gcdinv(mp_limb_t *G, mp_limb_t *S, const mp_limb_t *A, slong lenA, const mp_limb_t *B, slong lenB, const nmod_t mod) { mp_limb_t *T; slong ans; T = _nmod_vec_init(lenA - 1); ans = _nmod_poly_xgcd(G, T, S, B, lenB, A, lenA, mod); _nmod_vec_clear(T); return ans; } void nmod_poly_gcdinv(nmod_poly_t G, nmod_poly_t S, const nmod_poly_t A, const nmod_poly_t B) { const slong lenA = A->length, lenB = B->length; if (lenB < 2) flint_throw(FLINT_ERROR, "lenB < 2 in %s\n", __func__); if (lenA >= lenB) { nmod_poly_t T; /* TODO: We can probably use init_preinv here */ nmod_poly_init(T, A->mod.n); nmod_poly_rem(T, A, B); nmod_poly_gcdinv(G, S, T, B); nmod_poly_clear(T); return; } if (lenA == 0) { nmod_poly_zero(G); nmod_poly_zero(S); } else { mp_limb_t *g, *s; slong lenG; if (G == A || G == B) { g = _nmod_vec_init(lenA); } else { nmod_poly_fit_length(G, lenA); g = G->coeffs; } if (S == A || S == B) { s = _nmod_vec_init(lenB - 1); } else { nmod_poly_fit_length(S, lenB - 1); s = S->coeffs; } lenG = _nmod_poly_gcdinv(g, s, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (G == A || G == B) { _nmod_vec_clear(G->coeffs); G->coeffs = g; G->alloc = lenA; } if (S == A || S == B) { _nmod_vec_clear(S->coeffs); S->coeffs = s; S->alloc = lenB - 1; } _nmod_poly_set_length(G, lenG); _nmod_poly_set_length(S, lenB - lenG); _nmod_poly_normalise(S); if (nmod_poly_lead(G)[0] != WORD(1)) { mp_limb_t inv; inv = n_invmod(nmod_poly_lead(G)[0], A->mod.n); nmod_poly_scalar_mul_nmod(G, G, inv); nmod_poly_scalar_mul_nmod(S, S, inv); } } } flint-3.1.3/src/nmod_poly/get_str.c000066400000000000000000000066441461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_poly.h" char * nmod_poly_get_str(const nmod_poly_t poly) { slong i; char * buf, * ptr; /* estimate for the length, n and three spaces */ #if FLINT64 slong size = 21*2 + 1; #else slong size = 11*2 + 1; #endif for (i = 0; i < poly->length; i++) { if (poly->coeffs[i]) /* log(2)/log(10) < 0.30103, +1 for space/null */ size += (ulong) ceil(0.30103*FLINT_BIT_COUNT(poly->coeffs[i])) + 1; else size += 2; } buf = (char *) flint_malloc(size); ptr = buf + flint_sprintf(buf, "%wd %wu", poly->length, poly->mod.n); if (poly->length) ptr += flint_sprintf(ptr, " "); for (i = 0; i < poly->length; i++) ptr += flint_sprintf(ptr, " %wu", poly->coeffs[i]); return buf; } char * nmod_poly_get_str_pretty(const nmod_poly_t poly, const char * x) { slong i; char * buf, * ptr; slong size = 0; if (poly->length == 0) { buf = (char *) flint_malloc(2); buf[0] = '0'; buf[1] = '\0'; return buf; } else if (poly->length == 1) { size = (ulong) ceil(0.30103*FLINT_BIT_COUNT(poly->coeffs[0])) + 1; buf = (char *) flint_malloc(size); flint_sprintf(buf, "%wu", poly->coeffs[0]); return buf; } for (i = 0; i < poly->length; i++) { if (poly->coeffs[i]) /* log(2)/log(10) < 0.30103, +3 for +*^ or null*/ size += (ulong) ceil(0.30103*FLINT_BIT_COUNT(poly->coeffs[i])) + (ulong) ceil(0.30103*FLINT_BIT_COUNT(i)) + strlen(x) + 3; } buf = (char *) flint_malloc(size); ptr = buf; --i; if (i == 1) { switch (poly->coeffs[1]) { case UWORD(1): ptr += flint_sprintf(ptr, "%s", x); break; default: ptr += flint_sprintf(ptr, "%wu*%s", poly->coeffs[1], x); } --i; } else { switch (poly->coeffs[i]) { case UWORD(1): ptr += flint_sprintf(ptr, "%s^%wd", x, i); break; default: ptr += flint_sprintf(ptr, "%wu*%s^%wd", poly->coeffs[i], x, i); } --i; } for (; i > 1; --i) { switch (poly->coeffs[i]) { case UWORD(0): break; case UWORD(1): ptr += flint_sprintf(ptr, "+%s^%wd", x, i); break; default: ptr += flint_sprintf(ptr, "+%wu*%s^%wd", poly->coeffs[i], x, i); } } if (i == 1) { switch (poly->coeffs[1]) { case UWORD(0): break; case UWORD(1): ptr += flint_sprintf(ptr, "+%s", x); break; default: ptr += flint_sprintf(ptr, "+%wu*%s", poly->coeffs[1], x); } } { if (poly->coeffs[0] != UWORD(0)) ptr += flint_sprintf(ptr, "+%wu", poly->coeffs[0]); } return buf; } flint-3.1.3/src/nmod_poly/hgcd.c000066400000000000000000000112761461254215100165020ustar00rootroot00000000000000/* Copyright (C) 2011, 2014 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" /* XXX: Currently supports aliasing between {A,a} and {B,b}. */ slong _nmod_poly_hgcd(mp_ptr *M, slong *lenM, mp_ptr A, slong *lenA, mp_ptr B, slong *lenB, mp_srcptr a, slong lena, mp_srcptr b, slong lenb, nmod_t mod) { slong sgnM; gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_hgcd(NULL, &sgnM, (gr_ptr *) M, lenM, A, lenA, B, lenB, a, lena, b, lenb, NMOD_POLY_HGCD_CUTOFF, ctx)); return sgnM; } /* Assuming deg(a) > deg(b) (in particular b could be zero, but a must not be) compute a matrix M = [[m11, m12] [m21 m22]] and A, B so that [ a ] = [ m11 m12 ][ A ] [ b ] [ m21 m22 ][ B ] with (1) A and B are consecutive remainders in the euclidean remainder sequence for a, b satsifying 2*deg(A) >= deg(a) > 2*deg(B) (2) M is a product of [[qi 1][1 0]] where the qi are the quotients obtained in (1) No aliasing. The return is det(M), which is +-1. All of the moduli of the arguments should be the same and prime. Here is a reference implementation in case something is wrong with _nmod_poly_hgcd (there doesn't seem to be). */ slong nmod_poly_hgcd_ref( nmod_poly_t m11, nmod_poly_t m12, nmod_poly_t m21, nmod_poly_t m22, nmod_poly_t A, nmod_poly_t B, const nmod_poly_t a, const nmod_poly_t b) { slong sgnM; slong dega = nmod_poly_degree(a); nmod_poly_t q, r, t; if (nmod_poly_degree(a) <= nmod_poly_degree(b)) { flint_throw(FLINT_ERROR, "Exception in nmod_poly_hgcd_ref:" " Input degrees are invalid.\n"); } nmod_poly_init_mod(q, a->mod); nmod_poly_init_mod(r, a->mod); nmod_poly_init_mod(t, a->mod); nmod_poly_one(m11); nmod_poly_zero(m12); nmod_poly_zero(m21); nmod_poly_one(m22); nmod_poly_set(A, a); nmod_poly_set(B, b); sgnM = 1; while (dega <= 2*nmod_poly_degree(B)) { nmod_poly_divrem(q, r, A, B); nmod_poly_swap(A, B); nmod_poly_swap(B, r); /* multipliy M by [[q 1] [1 0]] on the right */ nmod_poly_mul(t, q, m11); nmod_poly_add(r, m12, t); nmod_poly_swap(m11, m12); nmod_poly_swap(m11, r); nmod_poly_mul(t, q, m21); nmod_poly_add(r, m22, t); nmod_poly_swap(m21, m22); nmod_poly_swap(m21, r); sgnM = -sgnM; } nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(t); return sgnM; } slong nmod_poly_hgcd( nmod_poly_t m11, nmod_poly_t m12, nmod_poly_t m21, nmod_poly_t m22, nmod_poly_t A, nmod_poly_t B, const nmod_poly_t a, const nmod_poly_t b) { mp_limb_t * M[4]; slong lenM[4]; slong sgnM; if (nmod_poly_degree(a) <= nmod_poly_degree(b)) { flint_throw(FLINT_ERROR, "Exception in nmod_poly_hgcd:" " Input degrees are invalid.\n"); } if (nmod_poly_length(b) == 0) { nmod_poly_one(m11); nmod_poly_zero(m12); nmod_poly_zero(m21); nmod_poly_one(m22); nmod_poly_set(A, a); nmod_poly_set(B, b); return 1; } /* now nmod_poly_length(a) > nmod_poly_length(b) > 0 */ nmod_poly_fit_length(m11, nmod_poly_length(a)); nmod_poly_fit_length(m12, nmod_poly_length(a)); nmod_poly_fit_length(m21, nmod_poly_length(a)); nmod_poly_fit_length(m22, nmod_poly_length(a)); nmod_poly_fit_length(A, nmod_poly_length(a)); nmod_poly_fit_length(B, nmod_poly_length(a)); /* Looks like _nmod_poly_hgcd produces an M with det(M) = sgnM = +-1 and [ a ] = [ m11 m12 ] [ A ] [ b ] [ m21 m22 ] [ B ] */ M[0] = m11->coeffs; M[1] = m12->coeffs; M[2] = m21->coeffs; M[3] = m22->coeffs; sgnM = _nmod_poly_hgcd(M, lenM, A->coeffs, &A->length, B->coeffs, &B->length, a->coeffs, a->length, b->coeffs, b->length, A->mod); m11->length = lenM[0]; m12->length = lenM[1]; m21->length = lenM[2]; m22->length = lenM[3]; FLINT_ASSERT(2*nmod_poly_degree(A) >= nmod_poly_degree(a)); FLINT_ASSERT(nmod_poly_degree(a) > 2*nmod_poly_degree(B)); return sgnM; } flint-3.1.3/src/nmod_poly/inflate.c000066400000000000000000000023651461254215100172160ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void nmod_poly_inflate(nmod_poly_t result, const nmod_poly_t input, ulong inflation) { if (input->length <= 1 || inflation == 1) { nmod_poly_set(result, input); } else if (inflation == 0) { mp_limb_t v = nmod_poly_evaluate_nmod(input, 1); nmod_poly_zero(result); nmod_poly_set_coeff_ui(result, 0, v); } else { slong i, j, res_length = (input->length - 1) * inflation + 1; nmod_poly_fit_length(result, res_length); for (i = input->length - 1; i > 0; i--) { result->coeffs[i * inflation] = input->coeffs[i]; for (j = i * inflation - 1; j > (i - 1) * inflation; j--) result->coeffs[j] = 0; } result->coeffs[0] = input->coeffs[0]; result->length = res_length; } } flint-3.1.3/src/nmod_poly/init.c000066400000000000000000000024501461254215100165320ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" void nmod_poly_init_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv) { poly->coeffs = NULL; poly->alloc = 0; poly->length = 0; poly->mod.n = n; poly->mod.ninv = ninv; poly->mod.norm = flint_clz(n); } void nmod_poly_init(nmod_poly_t poly, mp_limb_t n) { nmod_poly_init_preinv(poly, n, n_preinvert_limb(n)); } void nmod_poly_init2_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv, slong alloc) { if (alloc) poly->coeffs = (mp_ptr) flint_malloc(alloc * sizeof(mp_limb_t)); else poly->coeffs = NULL; poly->mod.n = n; poly->mod.ninv = ninv; poly->mod.norm = flint_clz(n); poly->alloc = alloc; poly->length = 0; } void nmod_poly_init2(nmod_poly_t poly, mp_limb_t n, slong alloc) { nmod_poly_init2_preinv(poly, n, n_preinvert_limb(n), alloc); } flint-3.1.3/src/nmod_poly/inlines.c000066400000000000000000000007231461254215100172310ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_POLY_INLINES_C #include "nmod_poly.h" flint-3.1.3/src/nmod_poly/integral.c000066400000000000000000000033111461254215100173710ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" void _nmod_poly_integral(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod) { if (len > 2) { slong k; mp_limb_t t, u; res[len - 1] = poly[len - 2]; t = len - 1; for (k = len - 2; k >= 2; k--) { res[k] = n_mulmod2_preinv(poly[k - 1], t, mod.n, mod.ninv); umul_ppmm(u, t, t, k); if (u != 0) t = n_ll_mod_preinv(u, t, mod.n, mod.ninv); } if (t >= mod.n) t = n_mod2_preinv(t, mod.n, mod.ninv); t = n_invmod(t, mod.n); res[2] = n_mulmod2_preinv(res[2], t, mod.n, mod.ninv); t = n_addmod(t, t, mod.n); if (len >= 4) { res[3] = n_mulmod2_preinv(res[3], t, mod.n, mod.ninv); for (k = 4; k < len; k++) { t = n_mulmod2_preinv(t, k - 1, mod.n, mod.ninv); res[k] = n_mulmod2_preinv(res[k], t, mod.n, mod.ninv); } } } if (len >= 2) res[1] = poly[0]; res[0] = 0; } void nmod_poly_integral(nmod_poly_t x_int, const nmod_poly_t x) { nmod_poly_fit_length(x_int, x->length + 1); _nmod_poly_integral(x_int->coeffs, x->coeffs, x->length + 1, x->mod); x_int->length = x->length + 1; _nmod_poly_normalise(x_int); } flint-3.1.3/src/nmod_poly/interpolate_nmod_vec.c000066400000000000000000000156321461254215100217750ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_interpolate_nmod_vec(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) { if (n < 6) _nmod_poly_interpolate_nmod_vec_newton(poly, xs, ys, n, mod); else if (n < 16) _nmod_poly_interpolate_nmod_vec_barycentric(poly, xs, ys, n, mod); else _nmod_poly_interpolate_nmod_vec_fast(poly, xs, ys, n, mod); } void nmod_poly_interpolate_nmod_vec(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) { if (n == 0) { nmod_poly_zero(poly); } else { nmod_poly_fit_length(poly, n); poly->length = n; _nmod_poly_interpolate_nmod_vec(poly->coeffs, xs, ys, n, poly->mod); _nmod_poly_normalise(poly); } } void _nmod_poly_interpolate_nmod_vec_barycentric(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) { mp_ptr P, Q, w; slong i, j; if (n == 1) { poly[0] = ys[0]; return; } P = _nmod_vec_init(n + 1); Q = _nmod_vec_init(n); w = _nmod_vec_init(n); _nmod_poly_product_roots_nmod_vec(P, xs, n, mod); for (i = 0; i < n; i++) { w[i] = UWORD(1); for (j = 0; j < n; j++) { if (i != j) w[i] = nmod_mul(w[i], nmod_sub(xs[i], xs[j], mod), mod); } w[i] = n_invmod(w[i], mod.n); } _nmod_vec_zero(poly, n); for (i = 0; i < n; i++) { _nmod_poly_div_root(Q, P, n + 1, xs[i], mod); _nmod_vec_scalar_addmul_nmod(poly, Q, n, nmod_mul(w[i], ys[i], mod), mod); } _nmod_vec_clear(P); _nmod_vec_clear(Q); _nmod_vec_clear(w); } void nmod_poly_interpolate_nmod_vec_barycentric(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) { if (n == 0) { nmod_poly_zero(poly); } else { nmod_poly_fit_length(poly, n); poly->length = n; _nmod_poly_interpolate_nmod_vec_barycentric(poly->coeffs, xs, ys, n, poly->mod); _nmod_poly_normalise(poly); } } void _nmod_poly_interpolation_weights(mp_ptr w, const mp_ptr * tree, slong len, nmod_t mod) { mp_ptr tmp; slong i, n, height; if (len == 0) return; if (len == 1) { w[0] = 1; return; } tmp = _nmod_vec_init(len + 1); height = FLINT_CLOG2(len); n = WORD(1) << (height - 1); _nmod_poly_mul(tmp, tree[height-1], n + 1, tree[height-1] + (n + 1), (len - n + 1), mod); _nmod_poly_derivative(tmp, tmp, len + 1, mod); _nmod_poly_evaluate_nmod_vec_fast_precomp(w, tmp, len, tree, len, mod); for (i = 0; i < len; i++) w[i] = n_invmod(w[i], mod.n); _nmod_vec_clear(tmp); } void _nmod_poly_interpolate_nmod_vec_fast_precomp(mp_ptr poly, mp_srcptr ys, const mp_ptr * tree, mp_srcptr weights, slong len, nmod_t mod) { mp_ptr t, u, pa, pb; slong i, pow, left; if (len == 0) return; t = _nmod_vec_init(len); u = _nmod_vec_init(len); for (i = 0; i < len; i++) poly[i] = nmod_mul(weights[i], ys[i], mod); for (i = 0; i < FLINT_CLOG2(len); i++) { pow = (WORD(1) << i); pa = tree[i]; pb = poly; left = len; while (left >= 2 * pow) { _nmod_poly_mul(t, pa, pow + 1, pb + pow, pow, mod); _nmod_poly_mul(u, pa + pow + 1, pow + 1, pb, pow, mod); _nmod_vec_add(pb, t, u, 2 * pow, mod); left -= 2 * pow; pa += 2 * pow + 2; pb += 2 * pow; } if (left > pow) { _nmod_poly_mul(t, pa, pow + 1, pb + pow, left - pow, mod); _nmod_poly_mul(u, pb, pow, pa + pow + 1, left - pow + 1, mod); _nmod_vec_add(pb, t, u, left, mod); } } _nmod_vec_clear(t); _nmod_vec_clear(u); } void _nmod_poly_interpolate_nmod_vec_fast(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong len, nmod_t mod) { mp_ptr * tree; mp_ptr w; tree = _nmod_poly_tree_alloc(len); _nmod_poly_tree_build(tree, xs, len, mod); w = _nmod_vec_init(len); _nmod_poly_interpolation_weights(w, tree, len, mod); _nmod_poly_interpolate_nmod_vec_fast_precomp(poly, ys, tree, w, len, mod); _nmod_vec_clear(w); _nmod_poly_tree_free(tree, len); } void nmod_poly_interpolate_nmod_vec_fast(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) { if (n == 0) { nmod_poly_zero(poly); } else { nmod_poly_fit_length(poly, n); poly->length = n; _nmod_poly_interpolate_nmod_vec_fast(poly->coeffs, xs, ys, n, poly->mod); _nmod_poly_normalise(poly); } } static void _interpolate_newton(mp_ptr ys, mp_srcptr xs, slong n, nmod_t mod) { mp_limb_t p, q, t; slong i, j; for (i = 1; i < n; i++) { t = ys[i - 1]; for (j = i; j < n; j++) { p = nmod_sub(ys[j], t, mod); q = nmod_sub(xs[j], xs[j - i], mod); t = ys[j]; q = n_invmod(q, mod.n); ys[j] = n_mulmod2_preinv(p, q, mod.n, mod.ninv); } } } static void _newton_to_monomial(mp_ptr ys, mp_srcptr xs, slong n, nmod_t mod) { mp_limb_t t; slong i, j; for (i = n - 2; i >= 0; i--) { t = ys[i]; ys[i] = ys[i + 1]; for (j = i + 1; j < n - 1; j++) { ys[j] = nmod_sub(ys[j + 1], n_mulmod2_preinv(ys[j], xs[i], mod.n, mod.ninv), mod); } ys[n - 1] = nmod_sub(t, n_mulmod2_preinv(ys[n - 1], xs[i], mod.n, mod.ninv), mod); } _nmod_poly_reverse(ys, ys, n, n); } void _nmod_poly_interpolate_nmod_vec_newton(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) { if (n == 1) { poly[0] = ys[0]; } else { _nmod_vec_set(poly, ys, n); _interpolate_newton(poly, xs, n, mod); while (n > 0 && !poly[n-1]) n--; _newton_to_monomial(poly, xs, n, mod); } } void nmod_poly_interpolate_nmod_vec_newton(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n) { if (n == 0) { nmod_poly_zero(poly); } else { nmod_poly_fit_length(poly, n); poly->length = n; _nmod_poly_interpolate_nmod_vec_newton(poly->coeffs, xs, ys, n, poly->mod); _nmod_poly_normalise(poly); } } flint-3.1.3/src/nmod_poly/inv_series.c000066400000000000000000000067601461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011, 2016, 2023 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_inv_series_basecase_preinv1(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, mp_limb_t q, nmod_t mod) { Qlen = FLINT_MIN(Qlen, n); Qinv[0] = q; if (Qlen == 1) { _nmod_vec_zero(Qinv + 1, n - 1); } else { slong i, j, l; int nlimbs; mp_limb_t s; nlimbs = _nmod_vec_dot_bound_limbs(FLINT_MIN(n, Qlen), mod); for (i = 1; i < n; i++) { l = FLINT_MIN(i, Qlen - 1); NMOD_VEC_DOT(s, j, l, Q[j + 1], Qinv[i - 1 - j], mod, nlimbs); if (q == 1) Qinv[i] = nmod_neg(s, mod); else Qinv[i] = nmod_neg(nmod_mul(s, q, mod), mod); } } } void _nmod_poly_inv_series_basecase(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { mp_limb_t q; q = Q[0]; if (q != 1) q = nmod_inv(q, mod); _nmod_poly_inv_series_basecase_preinv1(Qinv, Q, Qlen, n, q, mod); } void _nmod_poly_inv_series(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { Qlen = FLINT_MIN(Qlen, n); if (Qlen <= 10) { _nmod_poly_inv_series_basecase(Qinv, Q, Qlen, n, mod); } else { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_inv_series(Qinv, Q, Qlen, n, ctx)); } } void nmod_poly_inv_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_inv_series). Division by zero.\n"); } if (Qinv != Q) { nmod_poly_fit_length(Qinv, n); _nmod_poly_inv_series(Qinv->coeffs, Q->coeffs, Qlen, n, Qinv->mod); } else { nmod_poly_t t; nmod_poly_init2(t, Qinv->mod.n, n); _nmod_poly_inv_series(t->coeffs, Q->coeffs, Qlen, n, Qinv->mod); nmod_poly_swap(Qinv, t); nmod_poly_clear(t); } Qinv->length = n; _nmod_poly_normalise(Qinv); } void nmod_poly_inv_series_basecase(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_inv_series_basecase). Division by zero.\n"); } if (Qinv != Q) { nmod_poly_fit_length(Qinv, n); _nmod_poly_inv_series_basecase(Qinv->coeffs, Q->coeffs, Qlen, n, Qinv->mod); } else { nmod_poly_t t; nmod_poly_init2(t, Qinv->mod.n, n); _nmod_poly_inv_series_basecase(t->coeffs, Q->coeffs, Qlen, n, Qinv->mod); nmod_poly_swap(Qinv, t); nmod_poly_clear(t); } Qinv->length = n; _nmod_poly_normalise(Qinv); } void _nmod_poly_inv_series_newton(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { _nmod_poly_inv_series(Qinv, Q, Qlen, n, mod); } void nmod_poly_inv_series_newton(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { nmod_poly_inv_series(Qinv, Q, n); } flint-3.1.3/src/nmod_poly/inv_series_newton.c000066400000000000000000000010251461254215100213240ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011, 2016 Fredrik Johansson Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" flint-3.1.3/src/nmod_poly/invmod.c000066400000000000000000000040341461254215100170630ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" int _nmod_poly_invmod(mp_limb_t *A, const mp_limb_t *B, slong lenB, const mp_limb_t *P, slong lenP, const nmod_t mod) { mp_limb_t *G; slong lenG; NMOD_VEC_NORM(B, lenB); G = _nmod_vec_init(lenB); lenG = _nmod_poly_gcdinv(G, A, B, lenB, P, lenP, mod); if (lenG == 1 && G[0] != WORD(1)) { mp_limb_t invG; invG = n_invmod(G[0], mod.n); _nmod_vec_scalar_mul_nmod(A, A, lenP - 1, invG, mod); } _nmod_vec_clear(G); return (lenG == 1); } int nmod_poly_invmod(nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t P) { const slong lenB = B->length, lenP = P->length; mp_limb_t *t; int ans; if (lenP < 2) flint_throw(FLINT_ERROR, "lenP < 2 in %s\n", __func__); if (lenB == 0) { nmod_poly_zero(A); return 0; } if (lenB >= lenP) { nmod_poly_t T; nmod_poly_init(T, A->mod.n); nmod_poly_rem(T, B, P); ans = nmod_poly_invmod(A, T, P); nmod_poly_clear(T); return ans; } if (A != B && A != P) { nmod_poly_fit_length(A, lenP - 1); t = A->coeffs; } else { t = _nmod_vec_init(lenP); } ans = _nmod_poly_invmod(t, B->coeffs, lenB, P->coeffs, lenP, A->mod); if (A == B || A == P) { _nmod_vec_clear(A->coeffs); A->coeffs = t; A->alloc = lenP - 1; } _nmod_poly_set_length(A, lenP - 1); _nmod_poly_normalise(A); return ans; } flint-3.1.3/src/nmod_poly/invsqrt_series.c000066400000000000000000000027271461254215100206560ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_invsqrt_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_rsqrt_series(g, h, hlen, n, ctx)); } void nmod_poly_invsqrt_series(nmod_poly_t res, const nmod_poly_t h, slong len) { slong hlen; hlen = h->length; if (h->length == 0 || h->coeffs[0] == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_invsqrt_series). Division by zero.\n"); } if (len == 0) { nmod_poly_zero(res); return; } if (hlen == 1) len = 1; if (res == h) { nmod_poly_t t; nmod_poly_init_preinv(t, h->mod.n, h->mod.ninv); nmod_poly_invsqrt_series(t, h, len); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, len); _nmod_poly_invsqrt_series(res->coeffs, h->coeffs, h->length, len, h->mod); _nmod_poly_set_length(res, len); _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/io.c000066400000000000000000000066201461254215100162010ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2010 William Hart Copyright (C) 2014 Jean-Pierre Flori This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" /* printing *******************************************************************/ int nmod_poly_fprint(FILE * f, const nmod_poly_t poly) { char * s; int r; s = nmod_poly_get_str(poly); r = fputs(s, f); flint_free(s); return (r < 0) ? r : 1; } int nmod_poly_fprint_pretty(FILE * f, const nmod_poly_t a, const char * x) { size_t r; slong i; if (a->length == 0) { r = fputc('0', f); r = ((int) r != EOF) ? 1 : EOF; return r; } else if (a->length == 1) { r = flint_fprintf(f, "%wu", a->coeffs[0]); return r; } i = a->length - 1; r = 1; if (i == 1) { switch (a->coeffs[1]) { case UWORD(0): break; case UWORD(1): r = flint_fprintf(f, "%s", x); break; default: r = flint_fprintf(f, "%wu*%s", a->coeffs[1], x); } --i; } else { switch (a->coeffs[i]) { case UWORD(0): break; case UWORD(1): r = flint_fprintf(f, "%s^%wd", x, i); break; default: r = flint_fprintf(f, "%wu*%s^%wd", a->coeffs[i], x, i); } --i; } for (; (r > 0) && (i > 1); --i) { switch (a->coeffs[i]) { case UWORD(0): break; case UWORD(1): r = flint_fprintf(f, "+%s^%wd", x, i); break; default: r = flint_fprintf(f, "+%wu*%s^%wd", a->coeffs[i], x, i); } } if (r > 0 && i == 1) { switch (a->coeffs[1]) { case UWORD(0): break; case UWORD(1): r = flint_fprintf(f, "+%s", x); break; default: r = flint_fprintf(f, "+%wu*%s", a->coeffs[1], x); } } if (r > 0) { if (a->coeffs[0] != UWORD(0)) r = flint_fprintf(f, "+%wu", a->coeffs[0]); } return (int) r; } int nmod_poly_print(const nmod_poly_t a) { return nmod_poly_fprint(stdout, a); } int nmod_poly_print_pretty(const nmod_poly_t a, const char * x) { return nmod_poly_fprint_pretty(stdout, a, x); } /* reading ********************************************************************/ int nmod_poly_fread(FILE * f, nmod_poly_t poly) { slong i, length; mp_limb_t n; if (flint_fscanf(f, "%wd %wu", &length, &n) != 2) return 0; nmod_poly_clear(poly); nmod_poly_init(poly,n); nmod_poly_fit_length(poly, length); poly->length = length; for (i = 0; i < length; i++) { if (!flint_fscanf(f, "%wu", &poly->coeffs[i])) { poly->length = i; return 0; } } _nmod_poly_normalise(poly); return 1; } int nmod_poly_read(nmod_poly_t poly) { return nmod_poly_fread(stdin, poly); } flint-3.1.3/src/nmod_poly/log_series.c000066400000000000000000000021621461254215100177220ustar00rootroot00000000000000/* Copyright (C) 2011, 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_log_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_log_series(g, h, hlen, n, ctx)); } void nmod_poly_log_series(nmod_poly_t res, const nmod_poly_t f, slong n) { slong flen = f->length; if (flen < 1 || f->coeffs[0] != UWORD(1)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_log_series). Constant term != 1.\n"); } if (flen == 1 || n < 2) { nmod_poly_zero(res); return; } nmod_poly_fit_length(res, n); _nmod_poly_log_series(res->coeffs, f->coeffs, f->length, n, res->mod); res->length = n; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/make_monic.c000066400000000000000000000021541461254215100176720ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_make_monic(mp_ptr output, mp_srcptr input, slong len, nmod_t mod) { mp_limb_t inv; inv = n_invmod(input[len - 1], mod.n); _nmod_vec_scalar_mul_nmod(output, input, len, inv, mod); } void nmod_poly_make_monic(nmod_poly_t output, const nmod_poly_t input) { if (input->length == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_make_monic). Division by zero.\n"); } nmod_poly_fit_length(output, input->length); _nmod_poly_make_monic(output->coeffs, input->coeffs, input->length, input->mod); output->length = input->length; } flint-3.1.3/src/nmod_poly/max_bits.c000066400000000000000000000010431461254215100173720ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" flint_bitcnt_t nmod_poly_max_bits(const nmod_poly_t poly) { return _nmod_vec_max_bits(poly->coeffs, poly->length); } flint-3.1.3/src/nmod_poly/mul.c000066400000000000000000000072361461254215100163730ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #ifdef FLINT_HAVE_FFT_SMALL #include "fft_small.h" /* todo: check unbalanced cutoffs */ static const short fft_mul_tab[] = {1326, 1326, 1095, 802, 674, 537, 330, 306, 290, 274, 200, 192, 182, 173, 163, 99, 97, 93, 90, 82, 80, 438, 414, 324, 393, 298, 298, 268, 187, 185, 176, 176, 168, 167, 158, 158, 97, 96, 93, 92, 89, 89, 85, 85, 80, 81, 177, 172, 163, 162, 164, 176, 171, 167, 167, 164, 163, 163, 160, 165, 95, 96, 90, 94, }; static const short fft_sqr_tab[] = {1420, 1420, 1353, 964, 689, 569, 407, 353, 321, 321, 292, 279, 200, 182, 182, 159, 159, 152, 145, 139, 723, 626, 626, 569, 597, 448, 542, 292, 292, 200, 191, 191, 182, 182, 166, 166, 166, 159, 159, 159, 152, 152, 145, 145, 93, 200, 191, 182, 182, 182, 182, 191, 191, 191, 182, 182, 174, 182, 182, 182, 152, 152, 152, 145, }; #endif void _nmod_poly_mul(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { slong bits, cutoff_len; if (len2 <= 5) { _nmod_poly_mul_classical(res, poly1, len1, poly2, len2, mod); return; } bits = NMOD_BITS(mod); cutoff_len = FLINT_MIN(len1, 2 * len2); #ifdef FLINT_HAVE_FFT_SMALL if (poly1 == poly2 && len1 == len2) { if (cutoff_len >= fft_sqr_tab[bits - 1]) { _nmod_poly_mul_mid_default_mpn_ctx(res, 0, len1 + len2 - 1, poly1, len1, poly2, len2, mod); return; } } else { if (cutoff_len >= fft_mul_tab[bits - 1]) { _nmod_poly_mul_mid_default_mpn_ctx(res, 0, len1 + len2 - 1, poly1, len1, poly2, len2, mod); return; } } #endif if (3 * cutoff_len < 2 * FLINT_MAX(bits, 10)) _nmod_poly_mul_classical(res, poly1, len1, poly2, len2, mod); else if (cutoff_len * bits < 800) _nmod_poly_mul_KS(res, poly1, len1, poly2, len2, 0, mod); else if (cutoff_len * (bits + 1) * (bits + 1) < 100000) _nmod_poly_mul_KS2(res, poly1, len1, poly2, len2, mod); else _nmod_poly_mul_KS4(res, poly1, len1, poly2, len2, mod); } void nmod_poly_mul(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { slong len1, len2, len_out; len1 = poly1->length; len2 = poly2->length; if (len1 == 0 || len2 == 0) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2(temp, poly1->mod.n, len_out); if (len1 >= len2) _nmod_poly_mul(temp->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); else _nmod_poly_mul(temp->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, poly1->mod); nmod_poly_swap(temp, res); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (len1 >= len2) _nmod_poly_mul(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); else _nmod_poly_mul(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mul_KS.c000066400000000000000000000065571461254215100167750ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod_poly.h" void _nmod_poly_mul_KS(mp_ptr out, mp_srcptr in1, slong len1, mp_srcptr in2, slong len2, flint_bitcnt_t bits, nmod_t mod) { slong len_out = len1 + len2 - 1, limbs1, limbs2; mp_ptr tmp, mpn1, mpn2, res; int squaring; TMP_INIT; squaring = (in1 == in2 && len1 == len2); if (bits == 0) { flint_bitcnt_t bits1, bits2, loglen; /* Look at the actual bits of the input? This slows down the generic case. Are there situations where we care enough about special input? */ #if 0 bits1 = _nmod_vec_max_bits2(in1, len1); bits2 = squaring ? bits1 : _nmod_vec_max_bits2(in2, len2); #else bits1 = FLINT_BITS - (slong) mod.norm; bits2 = bits1; #endif loglen = FLINT_BIT_COUNT(len2); bits = bits1 + bits2 + loglen; } limbs1 = (len1 * bits - 1) / FLINT_BITS + 1; limbs2 = (len2 * bits - 1) / FLINT_BITS + 1; TMP_START; tmp = TMP_ALLOC(sizeof(mp_limb_t) * (limbs1 + limbs2 + limbs1 + (squaring ? 0 : limbs2))); res = tmp; mpn1 = tmp + limbs1 + limbs2; mpn2 = squaring ? mpn1 : (mpn1 + limbs1); _nmod_poly_bit_pack(mpn1, in1, len1, bits); if (!squaring) _nmod_poly_bit_pack(mpn2, in2, len2, bits); if (squaring) flint_mpn_sqr(res, mpn1, limbs1); else flint_mpn_mul(res, mpn1, limbs1, mpn2, limbs2); _nmod_poly_bit_unpack(out, len_out, res, bits, mod); TMP_END; } void nmod_poly_mul_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, flint_bitcnt_t bits) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_KS(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, bits, poly1->mod); else _nmod_poly_mul_KS(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, bits, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_KS(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, bits, poly1->mod); else _nmod_poly_mul_KS(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, bits, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mul_KS2.c000066400000000000000000000155161461254215100170520ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 David Harvey (zn_poly) Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" /* Multiplication/squaring using Kronecker substitution at 2^b and -2^b. */ void _nmod_poly_mul_KS2(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod) { int sqr, v3m_neg; ulong bits, b, w; slong n1o, n1e, n2o, n2e, n3o, n3e, n3, k1, k2, k3; mp_ptr v1_buf0, v2_buf0, v1_buf1, v2_buf1, v1_buf2, v2_buf2; mp_ptr v1o, v1e, v1p, v1m, v2o, v2e, v2p, v2m, v3o, v3e, v3p, v3m; mp_ptr z; TMP_INIT; if (n2 == 1) { /* code below needs n2 > 1, so fall back on scalar multiplication */ _nmod_vec_scalar_mul_nmod(res, op1, n1, op2[0], mod); return; } TMP_START; sqr = (op1 == op2 && n1 == n2); /* bits in each output coefficient */ bits = 2 * (FLINT_BITS - mod.norm) + FLINT_CLOG2(n2); /* we're evaluating at x = B and -B, where B = 2^b, and b = ceil(bits / 2) */ b = (bits + 1) / 2; /* number of ulongs required to store each output coefficient */ w = (2*b - 1)/FLINT_BITS + 1; /* Write f1(x) = f1e(x^2) + x * f1o(x^2) f2(x) = f2e(x^2) + x * f2o(x^2) h(x) = he(x^2) + x * ho(x^2) "e" = even, "o" = odd */ n1o = n1 / 2; n1e = n1 - n1o; n2o = n2 / 2; n2e = n2 - n2o; n3 = n1 + n2 - 1; /* length of h */ n3o = n3 / 2; n3e = n3 - n3o; /* f1(B) and |f1(-B)| are at most ((n1 - 1) * b + mod->bits) bits long. However, when evaluating f1e(B^2) and B * f1o(B^2) the bitpacking routine needs room for the last chunk of 2b bits. Therefore we need to allow room for (n1 + 1) * b bits. Ditto for f2. */ k1 = ((n1 + 1)*b - 1)/FLINT_BITS + 1; k2 = ((n2 + 1)*b - 1)/FLINT_BITS + 1; k3 = k1 + k2; /* allocate space */ v1_buf0 = TMP_ALLOC(sizeof(mp_limb_t) * 3 * k3); /* k1 limbs */ v2_buf0 = v1_buf0 + k1; /* k2 limbs */ v1_buf1 = v2_buf0 + k2; /* k1 limbs */ v2_buf1 = v1_buf1 + k1; /* k2 limbs */ v1_buf2 = v2_buf1 + k2; /* k1 limbs */ v2_buf2 = v1_buf2 + k1; /* k2 limbs */ /* arrange overlapping buffers to minimise memory use "p" = plus, "m" = minus */ v1e = v1_buf0; v2e = v2_buf0; v1o = v1_buf1; v2o = v2_buf1; v1p = v1_buf2; v2p = v2_buf2; v1m = v1_buf0; v2m = v2_buf0; v3m = v1_buf1; v3p = v1_buf0; v3e = v1_buf2; v3o = v1_buf0; z = TMP_ALLOC(sizeof(mp_limb_t) * w * n3e); if (!sqr) { /* multiplication version */ /* evaluate f1e(B^2) and B * f1o(B^2) */ _nmod_poly_KS2_pack(v1e, op1, n1e, 2, 2 * b, 0, k1); _nmod_poly_KS2_pack(v1o, op1 + 1, n1o, 2, 2 * b, b, k1); /* evaluate f2e(B^2) and B * f2o(B^2) */ _nmod_poly_KS2_pack(v2e, op2, n2e, 2, 2 * b, 0, k2); _nmod_poly_KS2_pack(v2o, op2 + 1, n2o, 2, 2 * b, b, k2); /* compute f1(B) = f1e(B^2) + B * f1o(B^2) and f2(B) = f2e(B^2) + B * f2o(B^2) */ mpn_add_n(v1p, v1e, v1o, k1); mpn_add_n(v2p, v2e, v2o, k2); /* compute |f1(-B)| = |f1e(B^2) - B * f1o(B^2)| and |f2(-B)| = |f2e(B^2) - B * f2o(B^2)| */ v3m_neg = signed_mpn_sub_n(v1m, v1e, v1o, k1); v3m_neg ^= signed_mpn_sub_n(v2m, v2e, v2o, k2); /* compute h(B) = f1(B) * f2(B) compute |h(-B)| = |f1(-B)| * |f2(-B)| v3m_neg is set if h(-B) is negative */ flint_mpn_mul(v3m, v1m, k1, v2m, k2); flint_mpn_mul(v3p, v1p, k1, v2p, k2); } else { /* squaring version */ /* evaluate f1e(B^2) and B * f1o(B^2) */ _nmod_poly_KS2_pack(v1e, op1, n1e, 2, 2 * b, 0, k1); _nmod_poly_KS2_pack(v1o, op1 + 1, n1o, 2, 2 * b, b, k1); /* compute f1(B) = f1e(B^2) + B * f1o(B^2) */ mpn_add_n(v1p, v1e, v1o, k1); /* compute |f1(-B)| = |f1e(B^2) - B * f1o(B^2)| */ signed_mpn_sub_n(v1m, v1e, v1o, k1); /* compute h(B) = f1(B)^2 compute h(-B) = f1(-B)^2 v3m_neg is cleared (since f1(-B)^2 is never negative) */ flint_mpn_sqr(v3m, v1m, k1); flint_mpn_sqr(v3p, v1p, k1); v3m_neg = 0; } /* he(B^2) and B * ho(B^2) are both at most b * (n3 + 1) bits long (since the coefficients don't overlap). The buffers used below are at least b * (n1 + n2 + 2) = b * (n3 + 3) bits long. So we definitely have enough room for 2 * he(B^2) and 2 * B * ho(B^2). */ /* compute 2 * he(B^2) = h(B) + h(-B) */ if (v3m_neg) mpn_sub_n(v3e, v3p, v3m, k3); else mpn_add_n(v3e, v3p, v3m, k3); /* unpack coefficients of he, and reduce mod m */ _nmod_poly_KS2_unpack(z, v3e, n3e, 2 * b, 1); _nmod_poly_KS2_reduce(res, 2, z, n3e, w, mod); /* compute 2 * b * ho(B^2) = h(B) - h(-B) */ if (v3m_neg) mpn_add_n(v3o, v3p, v3m, k3); else mpn_sub_n(v3o, v3p, v3m, k3); /* unpack coefficients of ho, and reduce mod m */ _nmod_poly_KS2_unpack(z, v3o, n3o, 2 * b, b + 1); _nmod_poly_KS2_reduce(res + 1, 2, z, n3o, w, mod); TMP_END; } void nmod_poly_mul_KS2(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_KS2(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); else _nmod_poly_mul_KS2(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_KS2(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); else _nmod_poly_mul_KS2(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mul_KS4.c000066400000000000000000000272061461254215100170530ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 David Harvey (zn_poly) Copyright (C) 2013 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" /* Multiplication/squaring using Kronecker substitution at 2^b, -2^b, 2^(-b) and -2^(-b). */ void _nmod_poly_mul_KS4(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod) { int sqr, v3m_neg; ulong bits, b, w, a1, a2, a3; slong n1o, n1e, n2o, n2e, n3o, n3e, n3, k1, k2, k3; mp_ptr v1_buf0, v2_buf0, v1_buf1, v2_buf1, v1_buf2, v2_buf2, v1_buf3, v2_buf3, v1_buf4, v2_buf4; mp_ptr v1on, v1en, v1pn, v1mn, v2on, v2en, v2pn, v2mn, v3on, v3en, v3pn, v3mn; mp_ptr v1or, v1er, v1pr, v1mr, v2or, v2er, v2pr, v2mr, v3or, v3er, v3pr, v3mr; mp_ptr z, zn, zr; TMP_INIT; if (n2 == 1) { /* code below needs n2 > 1, so fall back on scalar multiplication */ _nmod_vec_scalar_mul_nmod(res, op1, n1, op2[0], mod); return; } TMP_START; sqr = (op1 == op2 && n1 == n2); /* bits in each output coefficient */ bits = 2 * (FLINT_BITS - mod.norm) + FLINT_CLOG2(n2); /* we're evaluating at x = B, -B, 1/B, -1/B, where B = 2^b, and b = ceil(bits / 4) */ b = (bits + 3) / 4; /* number of ulongs required to store each base-B^2 digit */ w = (2*b - 1)/FLINT_BITS + 1; /* Write f1(x) = f1e(x^2) + x * f1o(x^2) f2(x) = f2e(x^2) + x * f2o(x^2) h(x) = he(x^2) + x * ho(x^2) "e" = even, "o" = odd */ n1o = n1 / 2; n1e = n1 - n1o; n2o = n2 / 2; n2e = n2 - n2o; n3 = n1 + n2 - 1; /* length of h */ n3o = n3 / 2; n3e = n3 - n3o; /* Put k1 = number of limbs needed to store f1(B) and |f1(-B)|. In f1(B), the leading coefficient starts at bit position b * (n1 - 1) and has length 2b, and the coefficients overlap so we need an extra bit for the carry: this gives (n1 + 1) * b + 1 bits. Ditto for f2. */ k1 = ((n1 + 1) * b)/FLINT_BITS + 1; k2 = ((n2 + 1) * b)/FLINT_BITS + 1; k3 = k1 + k2; /* allocate space */ v1_buf0 = TMP_ALLOC(sizeof(mp_limb_t) * 5 * k3); /* k1 limbs */ v2_buf0 = v1_buf0 + k1; /* k2 limbs */ v1_buf1 = v2_buf0 + k2; /* k1 limbs */ v2_buf1 = v1_buf1 + k1; /* k2 limbs */ v1_buf2 = v2_buf1 + k2; /* k1 limbs */ v2_buf2 = v1_buf2 + k1; /* k2 limbs */ v1_buf3 = v2_buf2 + k2; /* k1 limbs */ v2_buf3 = v1_buf3 + k1; /* k2 limbs */ v1_buf4 = v2_buf3 + k2; /* k1 limbs */ v2_buf4 = v1_buf4 + k1; /* k2 limbs */ /* arrange overlapping buffers to minimise memory use "p" = plus, "m" = minus "n" = normal order, "r" = reciprocal order */ v1en = v1_buf0; v1on = v1_buf1; v1pn = v1_buf2; v1mn = v1_buf0; v2en = v2_buf0; v2on = v2_buf1; v2pn = v2_buf2; v2mn = v2_buf0; v3pn = v1_buf1; v3mn = v1_buf2; v3en = v1_buf0; v3on = v1_buf1; v1er = v1_buf2; v1or = v1_buf3; v1pr = v1_buf4; v1mr = v1_buf2; v2er = v2_buf2; v2or = v2_buf3; v2pr = v2_buf4; v2mr = v2_buf2; v3pr = v1_buf3; v3mr = v1_buf4; v3er = v1_buf2; v3or = v1_buf3; z = TMP_ALLOC(sizeof(mp_limb_t) * 2*w*(n3e + 1)); zn = z; zr = z + w*(n3e + 1); /* ------------------------------------------------------------------------- "normal" evaluation points */ if (!sqr) { /* multiplication version */ /* evaluate f1e(B^2) and B * f1o(B^2) We need max(2 * b*n1e, 2 * b*n1o + b) bits for this packing step, which is safe since (n1 + 1) * b + 1 >= max(2 * b*n1e, 2 * b*n1o + b). Ditto for f2 below. */ _nmod_poly_KS2_pack(v1en, op1, n1e, 2, 2 * b, 0, k1); _nmod_poly_KS2_pack(v1on, op1 + 1, n1o, 2, 2 * b, b, k1); /* compute f1(B) = f1e(B^2) + B * f1o(B^2) and |f1(-B)| = |f1e(B^2) - B * f1o(B^2)| */ mpn_add_n (v1pn, v1en, v1on, k1); v3m_neg = signed_mpn_sub_n(v1mn, v1en, v1on, k1); /* evaluate f2e(B^2) and B * f2o(B^2) */ _nmod_poly_KS2_pack(v2en, op2, n2e, 2, 2 * b, 0, k2); _nmod_poly_KS2_pack(v2on, op2 + 1, n2o, 2, 2 * b, b, k2); /* compute f2(B) = f2e(B^2) + B * f2o(B^2) and |f2(-B)| = |f2e(B^2) - B * f2o(B^2)| */ mpn_add_n(v2pn, v2en, v2on, k2); v3m_neg ^= signed_mpn_sub_n(v2mn, v2en, v2on, k2); /* compute h(B) = f1(B) * f2(B) and |h(-B)| = |f1(-B)| * |f2(-B)| hn_neg is set if h(-B) is negative */ flint_mpn_mul(v3pn, v1pn, k1, v2pn, k2); flint_mpn_mul(v3mn, v1mn, k1, v2mn, k2); } else { /* squaring version */ /* evaluate f1e(B^2) and B * f1o(B^2) */ _nmod_poly_KS2_pack(v1en, op1, n1e, 2, 2 * b, 0, k1); _nmod_poly_KS2_pack(v1on, op1 + 1, n1o, 2, 2 * b, b, k1); /* compute f1(B) = f1e(B^2) + B * f1o(B^2) and |f1(-B)| = |f1e(B^2) - B * f1o(B^2)| */ mpn_add_n (v1pn, v1en, v1on, k1); signed_mpn_sub_n(v1mn, v1en, v1on, k1); /* compute h(B) = f1(B)^2 and h(-B) = |f1(-B)|^2 hn_neg is cleared since h(-B) is never negative */ flint_mpn_sqr(v3pn, v1pn, k1); flint_mpn_sqr(v3mn, v1mn, k1); v3m_neg = 0; } /* Each coefficient of h(B) is up to 4b bits long, so h(B) needs at most ((n1 + n2 + 2) * b + 1) bits. (The extra +1 is to accommodate carries generated by overlapping coefficients.) The buffer has at least ((n1 + n2 + 2) * b + 2) bits. Therefore we can safely store 2*h(B) etc. */ /* compute 2 * he(B^2) = h(B) + h(-B) and B * 2 * ho(B^2) = h(B) - h(-B) */ if (v3m_neg) { mpn_sub_n(v3en, v3pn, v3mn, k3); mpn_add_n (v3on, v3pn, v3mn, k3); } else { mpn_add_n (v3en, v3pn, v3mn, k3); mpn_sub_n (v3on, v3pn, v3mn, k3); } /* ------------------------------------------------------------------------- "reciprocal" evaluation points */ /* correction factors to take into account that if a polynomial has even length, its even and odd coefficients are swapped when the polynomial is reversed */ a1 = (n1 & 1) ? 0 : b; a2 = (n2 & 1) ? 0 : b; a3 = (n3 & 1) ? 0 : b; if (!sqr) { /* multiplication version */ /* evaluate B^(n1-1) * f1e(1/B^2) and B^(n1-2) * f1o(1/B^2) */ _nmod_poly_KS2_pack(v1er, op1 + 2*(n1e - 1), n1e, -2, 2 * b, a1, k1); _nmod_poly_KS2_pack(v1or, op1 + 1 + 2*(n1o - 1), n1o, -2, 2 * b, b - a1, k1); /* compute B^(n1-1) * f1(1/B) = B^(n1-1) * f1e(1/B^2) + B^(n1-2) * f1o(1/B^2) and |B^(n1-1) * f1(-1/B)| = |B^(n1-1) * f1e(1/B^2) - B^(n1-2) * f1o(1/B^2)| */ mpn_add_n(v1pr, v1er, v1or, k1); v3m_neg = signed_mpn_sub_n(v1mr, v1er, v1or, k1); /* evaluate B^(n2-1) * f2e(1/B^2) and B^(n2-2) * f2o(1/B^2) */ _nmod_poly_KS2_pack(v2er, op2 + 2*(n2e - 1), n2e, -2, 2 * b, a2, k2); _nmod_poly_KS2_pack(v2or, op2 + 1 + 2*(n2o - 1), n2o, -2, 2 * b, b - a2, k2); /* compute B^(n2-1) * f2(1/B) = B^(n2-1) * f2e(1/B^2) + B^(n2-2) * f2o(1/B^2) and |B^(n1-1) * f2(-1/B)| = |B^(n2-1) * f2e(1/B^2) - B^(n2-2) * f2o(1/B^2)| */ mpn_add_n (v2pr, v2er, v2or, k2); v3m_neg ^= signed_mpn_sub_n(v2mr, v2er, v2or, k2); /* compute B^(n3-1) * h(1/B) = (B^(n1-1) * f1(1/B)) * (B^(n2-1) * f2(1/B)) and |B^(n3-1) * h(-1/B)| = |B^(n1-1) * f1(-1/B)| * |B^(n2-1) * f2(-1/B)| hr_neg is set if h(-1/B) is negative */ flint_mpn_mul(v3pr, v1pr, k1, v2pr, k2); flint_mpn_mul(v3mr, v1mr, k1, v2mr, k2); } else { /* squaring version */ /* evaluate B^(n1-1) * f1e(1/B^2) and B^(n1-2) * f1o(1/B^2) */ _nmod_poly_KS2_pack(v1er, op1 + 2*(n1e - 1), n1e, -2, 2 * b, a1, k1); _nmod_poly_KS2_pack(v1or, op1 + 1 + 2*(n1o - 1), n1o, -2, 2 * b, b - a1, k1); /* compute B^(n1-1) * f1(1/B) = B^(n1-1) * f1e(1/B^2) + B^(n1-2) * f1o(1/B^2) and |B^(n1-1) * f1(-1/B)| = |B^(n1-1) * f1e(1/B^2) - B^(n1-2) * f1o(1/B^2)| */ mpn_add_n(v1pr, v1er, v1or, k1); signed_mpn_sub_n(v1mr, v1er, v1or, k1); /* compute B^(n3-1) * h(1/B) = (B^(n1-1) * f1(1/B))^2 and B^(n3-1) * h(-1/B) = |B^(n1-1) * f1(-1/B)|^2 hr_neg is cleared since h(-1/B) is never negative */ flint_mpn_sqr(v3pr, v1pr, k1); flint_mpn_sqr(v3mr, v1mr, k1); v3m_neg = 0; } /* compute 2 * B^(n3-1) * he(1/B^2) = B^(n3-1) * h(1/B) + B^(n3-1) * h(-1/B) and 2 * B^(n3-2) * ho(1/B^2) = B^(n3-1) * h(1/B) - B^(n3-1) * h(-1/B) */ if (v3m_neg) { mpn_sub_n(v3er, v3pr, v3mr, k3); mpn_add_n(v3or, v3pr, v3mr, k3); } else { mpn_add_n (v3er, v3pr, v3mr, k3); mpn_sub_n (v3or, v3pr, v3mr, k3); } /* ------------------------------------------------------------------------- combine "normal" and "reciprocal" information */ /* decompose he(B^2) and B^(2*(n3e-1)) * he(1/B^2) into base-B^2 digits */ _nmod_poly_KS2_unpack(zn, v3en, n3e + 1, 2 * b, 1); _nmod_poly_KS2_unpack(zr, v3er, n3e + 1, 2 * b, a3 + 1); /* combine he(B^2) and he(1/B^2) information to get even coefficients of h */ _nmod_poly_KS2_recover_reduce(res, 2, zn, zr, n3e, 2 * b, mod); /* decompose ho(B^2) and B^(2*(n3o-1)) * ho(1/B^2) into base-B^2 digits */ _nmod_poly_KS2_unpack(zn, v3on, n3o + 1, 2 * b, b + 1); _nmod_poly_KS2_unpack(zr, v3or, n3o + 1, 2 * b, b - a3 + 1); /* combine ho(B^2) and ho(1/B^2) information to get odd coefficients of h */ _nmod_poly_KS2_recover_reduce(res + 1, 2, zn, zr, n3o, 2 * b, mod); TMP_END; } void nmod_poly_mul_KS4(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_KS4(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); else _nmod_poly_mul_KS4(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_KS4(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); else _nmod_poly_mul_KS4(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mul_classical.c000066400000000000000000000105631461254215100204060ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" /* Assumes poly1 and poly2 are not length 0. */ void _nmod_poly_mul_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { slong i, j, bits, log_len, nlimbs, n1, n2; int squaring; mp_limb_t c; if (len1 == 1) { res[0] = nmod_mul(poly1[0], poly2[0], mod); return; } if (len2 == 1) { _nmod_vec_scalar_mul_nmod(res, poly1, len1, poly2[0], mod); return; } squaring = (poly1 == poly2 && len1 == len2); log_len = FLINT_BIT_COUNT(len2); bits = FLINT_BITS - (slong) mod.norm; bits = 2 * bits + log_len; if (bits <= FLINT_BITS) { flint_mpn_zero(res, len1 + len2 - 1); if (squaring) { for (i = 0; i < len1; i++) { c = poly1[i]; res[2 * i] += c * c; c *= 2; for (j = i + 1; j < len1; j++) res[i + j] += poly1[j] * c; } } else { for (i = 0; i < len1; i++) { mp_limb_t c = poly1[i]; for (j = 0; j < len2; j++) res[i + j] += c * poly2[j]; } } _nmod_vec_reduce(res, res, len1 + len2 - 1, mod); return; } if (len2 == 2) { _nmod_vec_scalar_mul_nmod(res, poly1, len1, poly2[0], mod); _nmod_vec_scalar_addmul_nmod(res + 1, poly1, len1 - 1, poly2[1], mod); res[len1 + len2 - 2] = nmod_mul(poly1[len1 - 1], poly2[len2 - 1], mod); return; } if (bits <= 2 * FLINT_BITS) nlimbs = 2; else nlimbs = 3; if (squaring) { for (i = 0; i < 2 * len1 - 1; i++) { n1 = FLINT_MAX(0, i - len1 + 1); n2 = FLINT_MIN(len1 - 1, (i + 1) / 2 - 1); c = _nmod_vec_dot_rev(poly1 + n1, poly1 + i - n2, n2 - n1 + 1, mod, nlimbs); c = nmod_add(c, c, mod); if (i % 2 == 0 && i / 2 < len1) NMOD_ADDMUL(c, poly1[i / 2], poly1[i / 2], mod); res[i] = c; } } else { for (i = 0; i < len1 + len2 - 1; i++) { n1 = FLINT_MIN(len1 - 1, i); n2 = FLINT_MIN(len2 - 1, i); res[i] = _nmod_vec_dot_rev(poly1 + i - n2, poly2 + i - n1, n1 + n2 - i + 1, mod, nlimbs); } } } void nmod_poly_mul_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0)) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_classical(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); else _nmod_poly_mul_classical(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _nmod_poly_mul_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); else _nmod_poly_mul_classical(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mulhigh.c000066400000000000000000000043511461254215100172260ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void _nmod_poly_mulhigh(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) { slong bits, bits2; if (len1 + len2 <= 6) { _nmod_poly_mulhigh_classical(res, poly1, len1, poly2, len2, n, mod); return; } bits = FLINT_BITS - (slong) mod.norm; bits2 = FLINT_BIT_COUNT(len1); if (2 * bits + bits2 <= FLINT_BITS && len1 + len2 < 16) _nmod_poly_mulhigh_classical(res, poly1, len1, poly2, len2, n, mod); else _nmod_poly_mul_KS(res, poly1, len1, poly2, len2, 0, mod); } void nmod_poly_mulhigh(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong start) { slong len1, len2, len_out; len1 = poly1->length; len2 = poly2->length; len_out = len1 + len2 - 1; if (len1 == 0 || len2 == 0 || start >= len_out) { nmod_poly_zero(res); return; } if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2(temp, poly1->mod.n, len_out); if (len1 >= len2) _nmod_poly_mulhigh(temp->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, start, poly1->mod); else _nmod_poly_mulhigh(temp->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, start, poly1->mod); nmod_poly_swap(temp, res); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (len1 >= len2) _nmod_poly_mulhigh(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, start, poly1->mod); else _nmod_poly_mulhigh(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, start, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mulhigh_classical.c000066400000000000000000000111201461254215100212340ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" /* Assumes poly1 and poly2 are not length 0. */ void _nmod_poly_mulhigh_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong start, nmod_t mod) { slong m, n; _nmod_vec_zero(res, start); if (len1 == 1) /* Special case if the length of both inputs is 1 */ { if (start == 0) res[0] = n_mulmod2_preinv(poly1[0], poly2[0], mod.n, mod.ninv); } else /* Ordinary case */ { slong i; slong bits = FLINT_BITS - (slong) mod.norm; slong log_len = FLINT_BIT_COUNT(len2); if (2 * bits + log_len <= FLINT_BITS) { /* Set res[i] = poly1[i]*poly2[0] */ if (start < len1) mpn_mul_1(res + start, poly1 + start, len1 - start, poly2[0]); if (len2 != 1) { /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ m = FLINT_MAX(len1 - 1, start); FLINT_ASSERT(len2 - 1 + len1 - m > 0); mpn_mul_1(res + m, poly2 + m - len1 + 1, len2 - 1 + len1 - m, poly1[len1 - 1]); /* out[i+j] += in1[i]*in2[j] */ m = FLINT_MAX(start, len2 - 1); for (i = m - len2 + 1; i < len1 - 1; i++) { n = FLINT_MAX(i + 1, start); mpn_addmul_1(res + n, poly2 + n - i, len2 + i - n, poly1[i]); } } _nmod_vec_reduce(res, res, len1 + len2 - 1, mod); } else { /* Set res[i] = poly1[i]*poly2[0] */ if (start < len1) _nmod_vec_scalar_mul_nmod(res + start, poly1 + start, len1 - start, poly2[0], mod); if (len2 == 1) return; /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ m = FLINT_MAX(len1 - 1, start); _nmod_vec_scalar_mul_nmod(res + m, poly2 + m - len1 + 1, len2 - 1 + len1 - m, poly1[len1 - 1], mod); /* out[i+j] += in1[i]*in2[j] */ m = FLINT_MAX(start, len2 - 1); for (i = m - len2 + 1; i < len1 - 1; i++) { n = FLINT_MAX(i + 1, start); _nmod_vec_scalar_addmul_nmod(res + n, poly2 + n - i, len2 + i - n, poly1[i], mod); } } } } void nmod_poly_mulhigh_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong start) { slong len_out = poly1->length + poly2->length - 1; if (poly1->length == 0 || poly2->length == 0 || start >= len_out) { nmod_poly_zero(res); return; } if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, len_out); if (poly1->length >= poly2->length) _nmod_poly_mulhigh_classical(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, start, poly1->mod); else _nmod_poly_mulhigh_classical(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, start, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _nmod_poly_mulhigh_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, start, poly1->mod); else _nmod_poly_mulhigh_classical(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, start, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mullow.c000066400000000000000000000061441461254215100171120ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #ifdef FLINT_HAVE_FFT_SMALL #include "fft_small.h" /* todo: separate squaring table */ /* todo: check unbalanced cutoffs */ static const short fft_mullow_tab[] = {1115, 1115, 597, 569, 407, 321, 306, 279, 191, 182, 166, 159, 152, 145, 139, 89, 85, 78, 75, 75, 69, 174, 174, 166, 159, 152, 152, 152, 97, 101, 106, 111, 101, 101, 101, 139, 145, 145, 139, 145, 145, 139, 145, 145, 145, 182, 182, 182, 182, 182, 182, 191, 200, 220, 210, 200, 210, 210, 210, 210, 191, 182, 182, 174, }; #endif void _nmod_poly_mullow(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) { slong bits; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (len2 <= 5) { _nmod_poly_mullow_classical(res, poly1, len1, poly2, len2, n, mod); return; } if (n == len1 + len2 - 1) { _nmod_poly_mul(res, poly1, len1, poly2, len2, mod); return; } bits = NMOD_BITS(mod); #ifdef FLINT_HAVE_FFT_SMALL if (len2 >= fft_mullow_tab[bits - 1]) { _nmod_poly_mul_mid_default_mpn_ctx(res, 0, n, poly1, len1, poly2, len2, mod); return; } #endif if (n < 10 + bits * bits / 10) _nmod_poly_mullow_classical(res, poly1, len1, poly2, len2, n, mod); else _nmod_poly_mullow_KS(res, poly1, len1, poly2, len2, 0, n, mod); } void nmod_poly_mullow(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc) { slong len1, len2, len_out; len1 = poly1->length; len2 = poly2->length; len_out = poly1->length + poly2->length - 1; if (trunc > len_out) trunc = len_out; if (len1 == 0 || len2 == 0 || trunc == 0) { nmod_poly_zero(res); return; } if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2(temp, poly1->mod.n, trunc); if (len1 >= len2) _nmod_poly_mullow(temp->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, trunc, poly1->mod); else _nmod_poly_mullow(temp->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, trunc, poly1->mod); nmod_poly_swap(temp, res); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, trunc); if (len1 >= len2) _nmod_poly_mullow(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, trunc, poly1->mod); else _nmod_poly_mullow(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, trunc, poly1->mod); } res->length = trunc; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mullow_KS.c000066400000000000000000000067441461254215100175150ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2010 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod_poly.h" void _nmod_poly_mullow_KS(mp_ptr out, mp_srcptr in1, slong len1, mp_srcptr in2, slong len2, flint_bitcnt_t bits, slong n, nmod_t mod) { slong limbs1, limbs2; mp_ptr tmp, mpn1, mpn2, res; int squaring; TMP_INIT; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); squaring = (in1 == in2 && len1 == len2); if (bits == 0) { flint_bitcnt_t bits1, bits2, loglen; /* Look at the actual bits of the input? This slows down the generic case. Are there situations where we care enough about special input? */ #if 0 bits1 = _nmod_vec_max_bits2(in1, len1); bits2 = squaring ? bits1 : _nmod_vec_max_bits2(in2, len2); #else bits1 = FLINT_BITS - (slong) mod.norm; bits2 = bits1; #endif loglen = FLINT_BIT_COUNT(len2); bits = bits1 + bits2 + loglen; } limbs1 = (len1 * bits - 1) / FLINT_BITS + 1; limbs2 = (len2 * bits - 1) / FLINT_BITS + 1; TMP_START; tmp = TMP_ALLOC(sizeof(mp_limb_t) * (limbs1 + limbs2 + limbs1 + (squaring ? 0 : limbs2))); res = tmp; mpn1 = tmp + limbs1 + limbs2; mpn2 = squaring ? mpn1 : (mpn1 + limbs1); _nmod_poly_bit_pack(mpn1, in1, len1, bits); if (!squaring) _nmod_poly_bit_pack(mpn2, in2, len2, bits); if (squaring) flint_mpn_sqr(res, mpn1, limbs1); else flint_mpn_mul(res, mpn1, limbs1, mpn2, limbs2); _nmod_poly_bit_unpack(out, n, res, bits, mod); TMP_END; } void nmod_poly_mullow_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, flint_bitcnt_t bits, slong n) { slong len_out; if ((poly1->length == 0) || (poly2->length == 0) || n == 0) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (n > len_out) n = len_out; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, len_out); if (poly1->length >= poly2->length) _nmod_poly_mullow_KS(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, bits, n, poly1->mod); else _nmod_poly_mullow_KS(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, bits, n, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _nmod_poly_mullow_KS(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, bits, n, poly1->mod); else _nmod_poly_mullow_KS(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, bits, n, poly1->mod); } res->length = n; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mullow_classical.c000066400000000000000000000114071461254215100211260ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" /* Assumes poly1 and poly2 are not length 0 and 0 < n <= len1 + len2 - 1 */ void _nmod_poly_mullow_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) { slong i, j, bits, log_len, nlimbs, n1, n2; int squaring; mp_limb_t c; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) { res[0] = nmod_mul(poly1[0], poly2[0], mod); return; } if (len2 == 1) { _nmod_vec_scalar_mul_nmod(res, poly1, len1, poly2[0], mod); return; } squaring = (poly1 == poly2 && len1 == len2); log_len = FLINT_BIT_COUNT(len2); bits = FLINT_BITS - (slong) mod.norm; bits = 2 * bits + log_len; if (bits <= FLINT_BITS) { flint_mpn_zero(res, n); if (squaring) { for (i = 0; i < len1; i++) { c = poly1[i]; if (2 * i < n) res[2 * i] += c * c; c *= 2; for (j = i + 1; j < FLINT_MIN(len1, n - i); j++) res[i + j] += poly1[j] * c; } } else { for (i = 0; i < len1; i++) { mp_limb_t c = poly1[i]; for (j = 0; j < FLINT_MIN(len2, n - i); j++) res[i + j] += c * poly2[j]; } } _nmod_vec_reduce(res, res, n, mod); return; } if (len2 == 2) { _nmod_vec_scalar_mul_nmod(res, poly1, len1, poly2[0], mod); _nmod_vec_scalar_addmul_nmod(res + 1, poly1, len1 - 1, poly2[1], mod); if (n == len1 + len2 - 1) res[len1 + len2 - 2] = nmod_mul(poly1[len1 - 1], poly2[len2 - 1], mod); return; } if (bits <= 2 * FLINT_BITS) nlimbs = 2; else nlimbs = 3; if (squaring) { for (i = 0; i < n; i++) { n1 = FLINT_MAX(0, i - len1 + 1); n2 = FLINT_MIN(len1 - 1, (i + 1) / 2 - 1); c = _nmod_vec_dot_rev(poly1 + n1, poly1 + i - n2, n2 - n1 + 1, mod, nlimbs); c = nmod_add(c, c, mod); if (i % 2 == 0 && i / 2 < len1) NMOD_ADDMUL(c, poly1[i / 2], poly1[i / 2], mod); res[i] = c; } } else { for (i = 0; i < n; i++) { n1 = FLINT_MIN(len1 - 1, i); n2 = FLINT_MIN(len2 - 1, i); res[i] = _nmod_vec_dot_rev(poly1 + i - n2, poly2 + i - n1, n1 + n2 - i + 1, mod, nlimbs); } } } void nmod_poly_mullow_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc) { slong len_out; if (poly1->length == 0 || poly2->length == 0 || trunc == 0) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (trunc > len_out) trunc = len_out; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, trunc); if (poly1->length >= poly2->length) _nmod_poly_mullow_classical(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, trunc, poly1->mod); else _nmod_poly_mullow_classical(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, trunc, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, trunc); if (poly1->length >= poly2->length) _nmod_poly_mullow_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, trunc, poly1->mod); else _nmod_poly_mullow_classical(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, trunc, poly1->mod); } res->length = trunc; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/mulmod.c000066400000000000000000000041651461254215100170710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_mulmod(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, mp_srcptr f, slong lenf, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ; lenT = len1 + len2 - 1; lenQ = lenT - lenf + 1; T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; if (len1 >= len2) _nmod_poly_mul(T, poly1, len1, poly2, len2, mod); else _nmod_poly_mul(T, poly2, len2, poly1, len1, mod); _nmod_poly_divrem(Q, res, T, lenT, f, lenf, mod); _nmod_vec_clear(T); } void nmod_poly_mulmod(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f) { slong len1, len2, lenf; mp_ptr fcoeffs; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_mulmod). Divide by zero.\n"); } if (lenf == 1 || len1 == 0 || len2 == 0) { nmod_poly_zero(res); return; } if (len1 + len2 - lenf > 0) { if (f == res) { fcoeffs = flint_malloc(sizeof(mp_limb_t) * lenf); _nmod_vec_set(fcoeffs, f->coeffs, lenf); } else fcoeffs = f->coeffs; nmod_poly_fit_length(res, lenf - 1); _nmod_poly_mulmod(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fcoeffs, lenf, res->mod); if (f == res) flint_free(fcoeffs); res->length = lenf - 1; _nmod_poly_normalise(res); } else { nmod_poly_mul(res, poly1, poly2); } } flint-3.1.3/src/nmod_poly/mulmod_preinv.c000066400000000000000000000047461461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_mulmod_preinv(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ; lenT = len1 + len2 - 1; lenQ = lenT - lenf + 1; T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; if (len1 >= len2) _nmod_poly_mul(T, poly1, len1, poly2, len2, mod); else _nmod_poly_mul(T, poly2, len2, poly1, len1, mod); _nmod_poly_divrem_newton_n_preinv(Q, res, T, lenT, f, lenf, finv, lenfinv, mod); _nmod_vec_clear(T); } void nmod_poly_mulmod_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f, const nmod_poly_t finv) { slong len1, len2, lenf; mp_ptr fcoeffs; lenf = f->length; len1 = poly1->length; len2 = poly2->length; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_mulmod_preinv). Divide by zero.\n"); } if (lenf <= len1 || lenf <= len2) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_mulmod_preinv). Input larger than modulus.\n"); } if (lenf == 1 || len1 == 0 || len2 == 0) { nmod_poly_zero(res); return; } if (len1 + len2 - lenf > 0) { if (f == res) { fcoeffs = (mp_ptr) flint_malloc(sizeof(mp_limb_t) * lenf); _nmod_vec_set(fcoeffs, f->coeffs, lenf); } else fcoeffs = f->coeffs; nmod_poly_fit_length(res, lenf - 1); _nmod_poly_mulmod_preinv(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fcoeffs, lenf, finv->coeffs, finv->length, res->mod); if (f == res) flint_free(fcoeffs); res->length = lenf - 1; _nmod_poly_normalise(res); } else { nmod_poly_mul(res, poly1, poly2); } } flint-3.1.3/src/nmod_poly/multi_crt.c000066400000000000000000000307321461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" void nmod_poly_multi_crt_init(nmod_poly_multi_crt_t P) { P->prog = NULL; P->alloc = 0; P->length = 0; P->localsize = 1; P->temp1loc = 0; P->temp2loc = 0; P->good = 0; } static void _nmod_poly_multi_crt_fit_length(nmod_poly_multi_crt_t P, slong k) { k = FLINT_MAX(WORD(1), k); if (P->alloc == 0) { FLINT_ASSERT(P->prog == NULL); P->prog = (_nmod_poly_multi_crt_prog_instr *) flint_malloc(k *sizeof(_nmod_poly_multi_crt_prog_instr)); P->alloc = k; } else if (k > P->alloc) { FLINT_ASSERT(P->prog != NULL); P->prog = (_nmod_poly_multi_crt_prog_instr *) flint_realloc(P->prog, k *sizeof(_nmod_poly_multi_crt_prog_instr)); P->alloc = k; } } static void _nmod_poly_multi_crt_set_length(nmod_poly_multi_crt_t P, slong k) { slong i; FLINT_ASSERT(k <= P->length); for (i = k; i < P->length; i++) { nmod_poly_clear(P->prog[i].modulus); nmod_poly_clear(P->prog[i].idem); } P->length = k; } void nmod_poly_multi_crt_clear(nmod_poly_multi_crt_t P) { _nmod_poly_multi_crt_set_length(P, 0); if (P->alloc > 0) { flint_free(P->prog); } } typedef struct { slong idx; slong degree; } index_deg_pair; /* combine all moduli in [start, stop) return index of instruction that computes the result */ static slong _push_prog( nmod_poly_multi_crt_t P, const nmod_poly_struct * const * moduli, const index_deg_pair * perm, slong ret_idx, slong start, slong stop) { slong i, mid; slong b_idx, c_idx; slong lefttot, righttot; slong leftret, rightret; nmod_poly_struct * leftmodulus, * rightmodulus; /* we should have at least 2 moduli */ FLINT_ASSERT(start + 1 < stop); mid = start + (stop - start)/2; FLINT_ASSERT(start < mid); FLINT_ASSERT(mid < stop); lefttot = 0; for (i = start; i < mid; i++) { lefttot += perm[i].degree; } righttot = 0; for (i = mid; i < stop; i++) { righttot += perm[i].degree; } /* try to balance the total degree on left and right */ while (lefttot < righttot && mid + 1 < stop && perm[mid].degree < righttot - lefttot) { lefttot += perm[mid].degree; righttot -= perm[mid].degree; mid++; } P->localsize = FLINT_MAX(P->localsize, 1 + ret_idx); /* compile left [start, mid) */ if (start + 1 < mid) { b_idx = ret_idx + 1; leftret = _push_prog(P, moduli, perm, b_idx, start, mid); if (!P->good) { return -1; } leftmodulus = P->prog[leftret].modulus; } else { b_idx = -1 - perm[start].idx; leftmodulus = (nmod_poly_struct *) moduli[perm[start].idx]; } /* compile right [mid, end) */ if (mid + 1 < stop) { c_idx = ret_idx + 2; rightret = _push_prog(P, moduli, perm, c_idx, mid, stop); if (!P->good) { return -1; } rightmodulus = P->prog[rightret].modulus; } else { c_idx = -1 - perm[mid].idx; rightmodulus = (nmod_poly_struct *) moduli[perm[mid].idx]; } /* check if nmod_poly_invmod is going to throw */ if (nmod_poly_degree(leftmodulus) < 1 || nmod_poly_degree(rightmodulus) < 1) { P->good = 0; return -1; } /* compile [start, end) */ i = P->length; _nmod_poly_multi_crt_fit_length(P, i + 1); nmod_poly_init_mod(P->prog[i].modulus, rightmodulus->mod); nmod_poly_init_mod(P->prog[i].idem, rightmodulus->mod); P->good = P->good && nmod_poly_invmod(P->prog[i].modulus, leftmodulus, rightmodulus); nmod_poly_mul(P->prog[i].idem, leftmodulus, P->prog[i].modulus); nmod_poly_mul(P->prog[i].modulus, leftmodulus, rightmodulus); P->prog[i].a_idx = ret_idx; P->prog[i].b_idx = b_idx; P->prog[i].c_idx = c_idx; P->length = i + 1; return i; } static int index_deg_pair_cmp( const index_deg_pair * lhs, const index_deg_pair * rhs) { return (lhs->degree < rhs->degree) ? -1 : (lhs->degree > rhs->degree); } /* Return 1 if moduli can be CRT'ed, 0 otherwise. A return of 0 means that future calls to run will leave output undefined. */ int nmod_poly_multi_crt_precompute_p( nmod_poly_multi_crt_t P, const nmod_poly_struct * const * moduli, slong len) { slong i; index_deg_pair * perm; TMP_INIT; FLINT_ASSERT(len > 0); for (i = 1; i < len; i++) { FLINT_ASSERT(moduli[i - 1]->mod.n == moduli[i]->mod.n); } TMP_START; perm = (index_deg_pair *) TMP_ALLOC(len * sizeof(index_deg_pair)); for (i = 0; i < len; i++) { perm[i].idx = i; perm[i].degree = nmod_poly_degree(moduli[i]); } /* make perm sort the degs so that degs[perm[i-1]] <= degs[perm[i-0]] */ qsort(perm, len, sizeof(index_deg_pair), (int(*)(const void*, const void*)) index_deg_pair_cmp); for (i = 0; i < len; i++) { FLINT_ASSERT(perm[i].degree == nmod_poly_degree(moduli[perm[i].idx])); FLINT_ASSERT(i == 0 || perm[i - 1].degree <= perm[i].degree); } _nmod_poly_multi_crt_fit_length(P, FLINT_MAX(WORD(1), len - 1)); _nmod_poly_multi_crt_set_length(P, 0); P->localsize = 1; P->good = 1; if (1 < len) { _push_prog(P, moduli, perm, 0, 0, len); } else { /* There is only one modulus. Let's compute as output[0] = input[0] + 0*(input[0] - input[0]) mod moduli[0] */ i = 0; nmod_poly_init_mod(P->prog[i].modulus, moduli[0]->mod); nmod_poly_init_mod(P->prog[i].idem, moduli[0]->mod); nmod_poly_set(P->prog[i].modulus, moduli[0]); P->prog[i].a_idx = 0; P->prog[i].b_idx = -WORD(1); P->prog[i].c_idx = -WORD(1); P->length = i + 1; P->good = !nmod_poly_is_zero(moduli[0]); } if (!P->good) { _nmod_poly_multi_crt_set_length(P, 0); } /* two more spots for temporaries */ P->temp1loc = P->localsize++; P->temp2loc = P->localsize++; TMP_END; return P->good; } int nmod_poly_multi_crt_precompute( nmod_poly_multi_crt_t P, const nmod_poly_struct * moduli, slong len) { int success; slong i; const nmod_poly_struct ** m; TMP_INIT; FLINT_ASSERT(len > 0); TMP_START; m = TMP_ALLOC(len * sizeof(nmod_poly_struct *)); for (i = 0; i < len; i++) { m[i] = moduli + i; } /* GCC really wants to complain about this one */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif success = nmod_poly_multi_crt_precompute_p(P, m, len); #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif TMP_END; return success; } void nmod_poly_multi_crt_precomp( nmod_poly_t output, const nmod_poly_multi_crt_t P, const nmod_poly_struct * inputs) { slong i; nmod_poly_struct * out; TMP_INIT; TMP_START; out = (nmod_poly_struct *) TMP_ALLOC(P->localsize *sizeof(nmod_poly_struct)); for (i = 0; i < P->localsize; i++) { nmod_poly_init_mod(out + i, inputs[0].mod); } nmod_poly_swap(out + 0, output); _nmod_poly_multi_crt_run(out, P, inputs); nmod_poly_swap(out + 0, output); for (i = 0; i < P->localsize; i++) { nmod_poly_clear(out + i); } TMP_END; } void nmod_poly_multi_crt_precomp_p( nmod_poly_t output, const nmod_poly_multi_crt_t P, const nmod_poly_struct * const * inputs) { slong i; nmod_poly_struct * out; TMP_INIT; TMP_START; out = (nmod_poly_struct *) TMP_ALLOC(P->localsize *sizeof(nmod_poly_struct)); for (i = 0; i < P->localsize; i++) { nmod_poly_init_mod(out + i, inputs[0]->mod); } nmod_poly_swap(out + 0, output); _nmod_poly_multi_crt_run_p(out, P, inputs); nmod_poly_swap(out + 0, output); for (i = 0; i < P->localsize; i++) { nmod_poly_clear(out + i); } TMP_END; } int nmod_poly_multi_crt( nmod_poly_t output, const nmod_poly_struct * moduli, const nmod_poly_struct * values, slong len) { int success; slong i; nmod_poly_multi_crt_t P; nmod_poly_struct * out; TMP_INIT; FLINT_ASSERT(len > 0); TMP_START; nmod_poly_multi_crt_init(P); success = nmod_poly_multi_crt_precompute(P, moduli, len); out = (nmod_poly_struct *) TMP_ALLOC(P->localsize *sizeof(nmod_poly_struct)); for (i = 0; i < P->localsize; i++) { nmod_poly_init_mod(out + i, values[0].mod); } nmod_poly_swap(out + 0, output); _nmod_poly_multi_crt_run(out, P, values); nmod_poly_swap(out + 0, output); for (i = 0; i < P->localsize; i++) { nmod_poly_clear(out + i); } nmod_poly_multi_crt_clear(P); TMP_END; return success; } /* If P was set with a call to nmod_poly_multi_crt_compile(P, m, len), return in outputs[0] polynomial r of smallest degree such that r = inputs[0] mod m[0] r = inputs[1] mod m[1] ... r = inputs[len-1] mod m[len-1] For thread safety "outputs" is expected to have enough space for all temporaries, thus should be at least as long as P->localsize. */ void _nmod_poly_multi_crt_run( nmod_poly_struct * outputs, const nmod_poly_multi_crt_t P, const nmod_poly_struct * inputs) { slong i; slong a, b, c; const nmod_poly_struct * B, * C; nmod_poly_struct * A, * t1, * t2; t1 = outputs + P->temp1loc; t2 = outputs + P->temp2loc; for (i = 0; i < P->length; i++) { a = P->prog[i].a_idx; b = P->prog[i].b_idx; c = P->prog[i].c_idx; FLINT_ASSERT(a >= 0); A = outputs + a; B = b < 0 ? inputs + (-b-1) : outputs + b; C = c < 0 ? inputs + (-c-1) : outputs + c; FLINT_ASSERT(A->mod.n == P->prog[i].modulus->mod.n); FLINT_ASSERT(B->mod.n == P->prog[i].modulus->mod.n); FLINT_ASSERT(C->mod.n == P->prog[i].modulus->mod.n); /* A = B + I*(C - B) mod M */ nmod_poly_sub(t1, B, C); nmod_poly_mul(t2, P->prog[i].idem, t1); nmod_poly_sub(t1, B, t2); if (nmod_poly_degree(t1) < nmod_poly_degree(P->prog[i].modulus)) { nmod_poly_swap(A, t1); } else { nmod_poly_rem(A, t1, P->prog[i].modulus); } /* last calculation should write answer to outputs[0] */ if (i + 1 >= P->length) { FLINT_ASSERT(A == outputs + 0); } } } void _nmod_poly_multi_crt_run_p( nmod_poly_struct * outputs, const nmod_poly_multi_crt_t P, const nmod_poly_struct * const * inputs) { slong i; slong a, b, c; const nmod_poly_struct * B, * C; nmod_poly_struct * A, * t1, * t2; t1 = outputs + P->temp1loc; t2 = outputs + P->temp2loc; for (i = 0; i < P->length; i++) { a = P->prog[i].a_idx; b = P->prog[i].b_idx; c = P->prog[i].c_idx; FLINT_ASSERT(a >= 0); A = outputs + a; B = b < 0 ? inputs[-b-1] : outputs + b; C = c < 0 ? inputs[-c-1] : outputs + c; FLINT_ASSERT(A->mod.n == P->prog[i].modulus->mod.n); FLINT_ASSERT(B->mod.n == P->prog[i].modulus->mod.n); FLINT_ASSERT(C->mod.n == P->prog[i].modulus->mod.n); /* A = B + I*(C - B) mod M */ nmod_poly_sub(t1, B, C); nmod_poly_mul(t2, P->prog[i].idem, t1); nmod_poly_sub(t1, B, t2); if (nmod_poly_degree(t1) < nmod_poly_degree(P->prog[i].modulus)) { nmod_poly_swap(A, t1); } else { nmod_poly_rem(A, t1, P->prog[i].modulus); } /* last calculation should write answer to outputs[0] */ if (i + 1 >= P->length) { FLINT_ASSERT(A == outputs + 0); } } } flint-3.1.3/src/nmod_poly/neg.c000066400000000000000000000012521461254215100163370ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void nmod_poly_neg(nmod_poly_t res, const nmod_poly_t poly1) { nmod_poly_fit_length(res, poly1->length); _nmod_vec_neg(res->coeffs, poly1->coeffs, poly1->length, poly1->mod); res->length = poly1->length; } flint-3.1.3/src/nmod_poly/pow.c000066400000000000000000000037261461254215100164030ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" void _nmod_poly_pow(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod) { _nmod_poly_pow_binexp(res, poly, len, e, mod); } void nmod_poly_pow(nmod_poly_t res, const nmod_poly_t poly, ulong e) { const slong len = poly->length; slong rlen; if ((len < 2) | (e < UWORD(3))) { if (len == 0) { if (e == 0) nmod_poly_one(res); else nmod_poly_zero(res); } else if (len == 1) { nmod_poly_fit_length(res, 1); res->coeffs[0] = n_powmod2_ui_preinv(poly->coeffs[0], e, poly->mod.n, poly->mod.ninv); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(0)) { nmod_poly_set_coeff_ui(res, 0, UWORD(1)); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(1)) nmod_poly_set(res, poly); else /* e == UWORD(2) */ nmod_poly_mul(res, poly, poly); return; } rlen = (slong) e * (len - 1) + 1; if (res != poly) { nmod_poly_fit_length(res, rlen); _nmod_poly_pow(res->coeffs, poly->coeffs, len, e, poly->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, rlen); _nmod_poly_pow(t->coeffs, poly->coeffs, len, e, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } res->length = rlen; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/pow_binexp.c000066400000000000000000000066711461254215100177520ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_pow_binexp(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod) { ulong bit = ~((~UWORD(0)) >> 1); slong rlen; slong alloc = (slong) e * (len - 1) + 1; mp_ptr v = _nmod_vec_init(alloc); mp_ptr R, S, T; /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, len} */ _nmod_poly_mul(R, poly, len, poly, len, mod); rlen = 2 * len - 1; if ((bit & e)) { _nmod_poly_mul(S, R, rlen, poly, len, mod); rlen += len - 1; T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _nmod_poly_mul(S, R, rlen, R, rlen, mod); rlen += rlen - 1; _nmod_poly_mul(R, S, rlen, poly, len, mod); rlen += len - 1; } else { _nmod_poly_mul(S, R, rlen, R, rlen, mod); rlen += rlen - 1; T = R; R = S; S = T; } } _nmod_vec_clear(v); } void nmod_poly_pow_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e) { const slong len = poly->length; slong rlen; if ((len < 2) | (e < UWORD(3))) { if (len == 0) nmod_poly_zero(res); else if (len == 1) { nmod_poly_fit_length(res, 1); res->coeffs[0] = n_powmod2_preinv(poly->coeffs[0], e, poly->mod.n, poly->mod.ninv); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(0)) { nmod_poly_set_coeff_ui(res, 0, UWORD(1)); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(1)) nmod_poly_set(res, poly); else /* e == UWORD(2) */ nmod_poly_mul(res, poly, poly); return; } rlen = (slong) e * (len - 1) + 1; if (res != poly) { nmod_poly_fit_length(res, rlen); _nmod_poly_pow_binexp(res->coeffs, poly->coeffs, len, e, poly->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, rlen); _nmod_poly_pow_binexp(t->coeffs, poly->coeffs, len, e, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } res->length = rlen; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/pow_trunc.c000066400000000000000000000131721461254215100176120ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_pow_trunc(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod) { _nmod_poly_pow_trunc_binexp(res, poly, e, trunc, mod); } void nmod_poly_pow_trunc(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc) { const slong len = poly->length; mp_ptr p; int pcopy = 0; if (len < 2 || e < UWORD(3) || trunc == 0) { if (len == 0 || trunc == 0) nmod_poly_zero(res); else if (len == 1) { nmod_poly_fit_length(res, 1); res->coeffs[0] = n_powmod2_ui_preinv(poly->coeffs[0], e, poly->mod.n, poly->mod.ninv); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(0)) { nmod_poly_set_coeff_ui(res, 0, UWORD(1)); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(1)) { nmod_poly_set(res, poly); nmod_poly_truncate(res, trunc); } else /* e == UWORD(2) */ nmod_poly_mullow(res, poly, poly, trunc); return; } if (poly->length < trunc) { p = _nmod_vec_init(trunc); flint_mpn_copyi(p, poly->coeffs, poly->length); flint_mpn_zero(p + poly->length, trunc - poly->length); pcopy = 1; } else p = poly->coeffs; if (res != poly || pcopy) { nmod_poly_fit_length(res, trunc); _nmod_poly_pow_trunc(res->coeffs, p, e, trunc, poly->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_pow_trunc(t->coeffs, p, e, trunc, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } if (pcopy) _nmod_vec_clear(p); res->length = trunc; _nmod_poly_normalise(res); } void _nmod_poly_pow_trunc_binexp(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod) { ulong bit = ~((~UWORD(0)) >> 1); mp_ptr v = _nmod_vec_init(trunc); mp_ptr R, S, T; /* Set bits to the bitmask with a 1 one place lower than the msb of e */ while ((bit & e) == UWORD(0)) bit >>= 1; bit >>= 1; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if ((bit2 & e)) swaps = ~swaps; while (bit2 >>= 1) if ((bit2 & e) == UWORD(0)) swaps = ~swaps; if (swaps == 0U) { R = res; S = v; } else { R = v; S = res; } } /* We unroll the first step of the loop, referring to {poly, len} */ _nmod_poly_mullow(R, poly, trunc, poly, trunc, trunc, mod); if ((bit & e)) { _nmod_poly_mullow(S, R, trunc, poly, trunc, trunc, mod); T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _nmod_poly_mullow(S, R, trunc, R, trunc, trunc, mod); _nmod_poly_mullow(R, S, trunc, poly, trunc, trunc, mod); } else { _nmod_poly_mullow(S, R, trunc, R, trunc, trunc, mod); T = R; R = S; S = T; } } _nmod_vec_clear(v); } void nmod_poly_pow_trunc_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc) { const slong len = poly->length; mp_ptr p; int pcopy = 0; if (len < 2 || e < UWORD(3) || trunc == 0) { if (len == 0 || trunc == 0) nmod_poly_zero(res); else if (len == 1) { nmod_poly_fit_length(res, 1); res->coeffs[0] = n_powmod2_ui_preinv(poly->coeffs[0], e, poly->mod.n, poly->mod.ninv); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(0)) { nmod_poly_set_coeff_ui(res, 0, UWORD(1)); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(1)) { nmod_poly_set(res, poly); nmod_poly_truncate(res, trunc); } else /* e == UWORD(2) */ nmod_poly_mullow(res, poly, poly, trunc); return; } if (poly->length < trunc) { p = _nmod_vec_init(trunc); flint_mpn_copyi(p, poly->coeffs, poly->length); flint_mpn_zero(p + poly->length, trunc - poly->length); pcopy = 1; } else p = poly->coeffs; if (res != poly || pcopy) { nmod_poly_fit_length(res, trunc); _nmod_poly_pow_trunc_binexp(res->coeffs, p, e, trunc, poly->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_pow_trunc_binexp(t->coeffs, p, e, trunc, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } if (pcopy) _nmod_vec_clear(p); res->length = trunc; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/power_sums.c000066400000000000000000000144551461254215100200020ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" void _nmod_poly_power_sums(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod) { if (10 * n >= len + 75) _nmod_poly_power_sums_schoenhage(res, poly, len, n, mod); else _nmod_poly_power_sums_naive(res, poly, len, n, mod); } void nmod_poly_power_sums(nmod_poly_t res, const nmod_poly_t poly, slong n) { slong len = poly->length; size_t i = 0; if (len == 0) { flint_throw(FLINT_ERROR, "(nmod_poly_power_sums_naive): Zero polynomial.\n"); } while (poly->coeffs[i] == 0) i++; if (n <= 0 || len == 1) nmod_poly_zero(res); else if (len == i + 1) { nmod_poly_fit_length(res, 1); _nmod_poly_set_length(res, 1); NMOD_RED(res->coeffs[0], len - 1, poly->mod); } else { if (*nmod_poly_lead(poly) != 1) { nmod_poly_t t; nmod_poly_init_preinv(t, poly->mod.n, poly->mod.ninv); nmod_poly_make_monic(t, poly); nmod_poly_fit_length(res, n); _nmod_poly_power_sums(res->coeffs, t->coeffs + i, len - i, n, t->mod); nmod_poly_clear(t); } else if (poly == res) { nmod_poly_t t; nmod_poly_init_preinv(t, poly->mod.n, poly->mod.ninv); nmod_poly_fit_length(t, n); _nmod_poly_power_sums(t->coeffs, poly->coeffs + i, len - i, n, t->mod); nmod_poly_swap(t, res); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, n); _nmod_poly_power_sums(res->coeffs, poly->coeffs + i, len - i, n, poly->mod); } if (i) NMOD_RED(res->coeffs[0], len - 1, poly->mod); _nmod_poly_set_length(res, n); _nmod_poly_normalise(res); } } /* todo: should use dot products */ void _nmod_poly_power_sums_naive(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod) { slong i, k; NMOD_RED(res[0], len - 1, mod); for (k = 1; k < FLINT_MIN(n, len); k++) { res[k] = nmod_mul(poly[len - 1 - k], k, mod); for (i = 1; i < k; i++) res[k] = nmod_add(res[k], nmod_mul(poly[len - 1 - k + i], res[i], mod), mod); res[k] = nmod_neg(res[k], mod); } for (k = len; k < n; k++) { res[k] = 0; for (i = k - len + 1; i < k; i++) res[k] = nmod_add(res[k], nmod_mul(poly[len - 1 - k + i], res[i], mod), mod); res[k] = nmod_neg(res[k], mod); } } void nmod_poly_power_sums_naive(nmod_poly_t res, const nmod_poly_t poly, slong n) { if (poly->length == 0) { flint_throw(FLINT_ERROR, "(nmod_poly_power_sums_naive): Zero polynomial.\n"); } else if (n <= 0 || poly->length == 1) { nmod_poly_zero(res); } else { if (*nmod_poly_lead(poly) != 1) { nmod_poly_t t; nmod_poly_init_preinv(t, poly->mod.n, poly->mod.ninv); nmod_poly_make_monic(t, poly); nmod_poly_fit_length(res, n); _nmod_poly_power_sums_naive(res->coeffs, t->coeffs, t->length, n, t->mod); nmod_poly_clear(t); } else if (poly == res) { nmod_poly_t t; nmod_poly_init_preinv(t, poly->mod.n, poly->mod.ninv); nmod_poly_fit_length(t, n); _nmod_poly_power_sums_naive(t->coeffs, poly->coeffs, poly->length, n, t->mod); nmod_poly_swap(t, res); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, n); _nmod_poly_power_sums_naive(res->coeffs, poly->coeffs, poly->length, n, poly->mod); } _nmod_poly_set_length(res, n); _nmod_poly_normalise(res); } } void _nmod_poly_power_sums_schoenhage(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod) { mp_ptr a, b; a = (mp_ptr) flint_malloc((2 * len - 1) * sizeof(mp_limb_t)); b = a + len; _nmod_poly_reverse(a, poly, len, len); _nmod_poly_derivative(b, poly, len, mod); _nmod_poly_reverse(b, b, len - 1, len - 1); _nmod_poly_div_series(res, b, len - 1, a, len, n, mod); flint_free(a); } void nmod_poly_power_sums_schoenhage(nmod_poly_t res, const nmod_poly_t poly, slong n) { if (poly->length == 0) { flint_throw(FLINT_ERROR, "(nmod_poly_power_sums_schoenhage): Zero polynomial.\n"); } else if ((n <= 0) || (poly->length == 1)) { nmod_poly_zero(res); } else { if (*nmod_poly_lead(poly) != 1) { nmod_poly_t t; nmod_poly_init_preinv(t, poly->mod.n, poly->mod.ninv); nmod_poly_make_monic(t, poly); nmod_poly_fit_length(res, n); _nmod_poly_power_sums_schoenhage(res->coeffs, t->coeffs, t->length, n, t->mod); nmod_poly_clear(t); } else if (poly == res) { nmod_poly_t t; nmod_poly_init_preinv(t, poly->mod.n, poly->mod.ninv); nmod_poly_fit_length(t, n); _nmod_poly_power_sums_schoenhage(t->coeffs, poly->coeffs, poly->length, n, t->mod); nmod_poly_swap(t, res); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, n); _nmod_poly_power_sums_schoenhage(res->coeffs, poly->coeffs, poly->length, n, poly->mod); } _nmod_poly_set_length(res, n); _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/power_sums_to_poly.c000066400000000000000000000116121461254215100215370ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_power_sums_to_poly(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod) { if (mod.n <= 12 || poly[0] <= 10) _nmod_poly_power_sums_to_poly_naive(res, poly, len, mod); else _nmod_poly_power_sums_to_poly_schoenhage(res, poly, len, mod); } void nmod_poly_power_sums_to_poly(nmod_poly_t res, const nmod_poly_t Q) { if (Q->length == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; _nmod_poly_set_length(res, 1); } else { slong d = Q->coeffs[0]; if (Q == res) { nmod_poly_t t; nmod_poly_init_preinv(t, Q->mod.n, Q->mod.ninv); nmod_poly_fit_length(t, d + 1); _nmod_poly_power_sums_to_poly(t->coeffs, Q->coeffs, Q->length, Q->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, d + 1); _nmod_poly_power_sums_to_poly(res->coeffs, Q->coeffs, Q->length, Q->mod); } _nmod_poly_set_length(res, d + 1); _nmod_poly_normalise(res); } } /* todo: should use dot products */ void _nmod_poly_power_sums_to_poly_naive(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod) { slong i, k; slong d = poly[0]; res[d] = 1; for (k = 1; k < FLINT_MIN(d + 1, len); k++) { res[d - k] = poly[k]; for (i = 1; i < k; i++) res[d - k] = nmod_add(res[d - k], nmod_mul(res[d - k + i], poly[i], mod), mod); res[d - k] = nmod_div(res[d - k], k, mod); res[d - k] = nmod_neg(res[d - k], mod); } for (k = len; k <= d; k++) { res[d - k] = 0; for (i = 1; i < len; i++) res[d - k] = nmod_add(res[d - k], nmod_mul(res[d - k + i], poly[i], mod), mod); res[d - k] = nmod_div(res[d - k], k, mod); res[d - k] = nmod_neg(res[d - k], mod); } } void nmod_poly_power_sums_to_poly_naive(nmod_poly_t res, const nmod_poly_t Q) { if (Q->length == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; _nmod_poly_set_length(res, 1); } else { slong d = Q->coeffs[0]; if (Q == res) { nmod_poly_t t; nmod_poly_init_preinv(t, Q->mod.n, Q->mod.ninv); nmod_poly_fit_length(t, d + 1); _nmod_poly_power_sums_to_poly_naive(t->coeffs, Q->coeffs, Q->length, Q->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, d + 1); _nmod_poly_power_sums_to_poly_naive(res->coeffs, Q->coeffs, Q->length, Q->mod); } _nmod_poly_set_length(res, d + 1); _nmod_poly_normalise(res); } } void _nmod_poly_power_sums_to_poly_schoenhage(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod) { mp_ptr t; slong d = poly[0]; if (len >= d + 1) len = d + 1; t = flint_malloc(len * sizeof(mp_limb_t)); _nmod_vec_neg(t, poly + 1, len - 1, mod); _nmod_poly_integral(t, t, len, mod); _nmod_poly_exp_series(res, t, len, d + 1, mod); _nmod_poly_reverse(res, res, d + 1, d + 1); flint_free(t); } void nmod_poly_power_sums_to_poly_schoenhage(nmod_poly_t res, const nmod_poly_t Q) { if (Q->length == 0) { nmod_poly_fit_length(res, 1); (res->coeffs)[0] = 1; _nmod_poly_set_length(res, 1); } else { slong d = (Q->coeffs)[0]; if (Q == res) { nmod_poly_t t; nmod_poly_init_preinv(t, Q->mod.n, Q->mod.ninv); nmod_poly_fit_length(t, d + 1); _nmod_poly_power_sums_to_poly_schoenhage(t->coeffs, Q->coeffs, Q->length, Q->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, d + 1); _nmod_poly_power_sums_to_poly_schoenhage(res->coeffs, Q->coeffs, Q->length, Q->mod); } _nmod_poly_set_length(res, d + 1); _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/powers_mod.c000066400000000000000000000221671461254215100177540ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" typedef struct { volatile slong * j; slong k; slong n; slong glen; slong ginvlen; mp_srcptr g; mp_srcptr ginv; mp_ptr * res; nmod_t mod; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif } powers_preinv_arg_t; void _nmod_poly_powers_mod_preinv_worker(void * arg_ptr) { powers_preinv_arg_t arg = *((powers_preinv_arg_t *) arg_ptr); slong i, j, k = arg.k, n = arg.n; slong glen = arg.glen, ginvlen = arg.ginvlen; mp_ptr * res = arg.res; mp_srcptr g = arg.g, ginv = arg.ginv; const nmod_t mod = arg.mod; while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(arg.mutex); #endif j = *arg.j + k; *arg.j = j; #if FLINT_USES_PTHREAD pthread_mutex_unlock(arg.mutex); #endif if (j >= n) return; if (glen == 2) /* special case, constant polynomials */ { for (i = j + 1; i < j + k && i < n; i++) res[i][0] = n_mulmod2_preinv(res[j][0], res[i - j][0], mod.n, mod.ninv); } else { for (i = j + 1; i < j + k && i < n; i++) _nmod_poly_mulmod_preinv(res[i], res[j], glen - 1, res[i - j], glen - 1, g, glen, ginv, ginvlen, mod); } } } /* compute f^0, f^1, ..., f^(n-1) mod g, where g has length glen and f is reduced mod g and has length flen (possibly zero spaced) assumes res is an array of n arrays each with space for at least glen - 1 coefficients and that flen > 0 {ginv, ginvlen} must be set to the power series inverse of the reverse of g */ void _nmod_poly_powers_mod_preinv_threaded_pool(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod, thread_pool_handle * threads, slong num_threads) { slong i, k, shared_j = 0; powers_preinv_arg_t * args; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif if (n == 0) return; if (n == 1) { if (glen > 1) res[0][0] = 1; if (glen > 2) flint_mpn_zero(res[0] + 1, glen - 2); return; } k = n_sqrt(n); /* compute baby steps */ _nmod_poly_powers_mod_preinv_naive(res, f, flen, k + 1, g, glen, ginv, ginvlen, mod); /* compute giant steps */ /* f^(k*i) = f^(k*(i - 1))*f^k */ if (glen == 2) /* special case, constant polys */ { for (i = 2*k; i < n; i += k) res[i][0] = n_mulmod2_preinv(res[i - k][0], res[k][0], mod.n, mod.ninv); } else { for (i = 2*k; i < n; i += k) _nmod_poly_mulmod_preinv(res[i], res[i - k], glen - 1, res[k], glen - 1, g, glen, ginv, ginvlen, mod); } args = (powers_preinv_arg_t *) flint_malloc(sizeof(powers_preinv_arg_t) * (num_threads + 1)); for (i = 0; i < num_threads + 1; i++) { args[i].j = &shared_j; args[i].k = k; args[i].n = n; args[i].glen = glen; args[i].ginvlen = ginvlen; args[i].g = g; args[i].ginv = ginv; args[i].res = res; args[i].mod = mod; #if FLINT_USES_PTHREAD args[i].mutex = &mutex; #endif } #if FLINT_USES_PTHREAD pthread_mutex_init(&mutex, NULL); #endif for (i = 0; i < num_threads; i++) thread_pool_wake(global_thread_pool, threads[i], 0, _nmod_poly_powers_mod_preinv_worker, &args[i]); _nmod_poly_powers_mod_preinv_worker(&args[num_threads]); for (i = 0; i < num_threads; i++) thread_pool_wait(global_thread_pool, threads[i]); #if FLINT_USES_PTHREAD pthread_mutex_destroy(&mutex); #endif flint_free(args); } void _nmod_poly_powers_mod_preinv_threaded(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod) { thread_pool_handle * threads; slong num_threads = flint_request_threads(&threads, flint_get_num_threads()); _nmod_poly_powers_mod_preinv_threaded_pool(res, f, flen, n, g, glen, ginv, ginvlen, mod, threads, num_threads); flint_give_back_threads(threads, num_threads); } void nmod_poly_powers_mod_bsgs(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g) { slong i; nmod_poly_t ginv; mp_ptr * res_arr; if (nmod_poly_length(g) == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powers_mod_naive). Divide by zero.\n"); } if (nmod_poly_length(f) == 0 || nmod_poly_length(g) == 1) { if (n > 0) nmod_poly_one(res + 0); for (i = 1; i < n; i++) nmod_poly_zero(res + i); return; } if (nmod_poly_length(f) >= nmod_poly_length(g)) { nmod_poly_t q, r; nmod_poly_init_mod(q, f->mod); nmod_poly_init_mod(r, f->mod); nmod_poly_divrem(q, r, f, g); nmod_poly_powers_mod_bsgs(res, r, n, g); nmod_poly_clear(q); nmod_poly_clear(r); return; } res_arr = (mp_ptr *) flint_malloc(n*sizeof(mp_ptr)); nmod_poly_init_mod(ginv, g->mod); for (i = 0; i < n; i++) { nmod_poly_fit_length(res + i, nmod_poly_length(g) - 1); res_arr[i] = res[i].coeffs; _nmod_poly_set_length(res + i, nmod_poly_length(g) - 1); } nmod_poly_reverse(ginv, g, nmod_poly_length(g)); nmod_poly_inv_series(ginv, ginv, nmod_poly_length(g)); _nmod_poly_powers_mod_preinv_threaded(res_arr, f->coeffs, f->length, n, g->coeffs, g->length, ginv->coeffs, ginv->length, g->mod); for (i = 0; i < n; i++) _nmod_poly_normalise(res + i); nmod_poly_clear(ginv); flint_free(res_arr); } /* compute f^0, f^1, ..., f^(n-1) mod g, where g has length glen and f is reduced mod g and has length flen (possibly zero spaced) assumes res is an array of n arrays each with space for at least glen - 1 coefficients and that flen > 0 {ginv, ginvlen} must be set to the power series inverse of the reverse of g */ void _nmod_poly_powers_mod_preinv_naive(mp_ptr * res, mp_srcptr f, slong flen, slong n, mp_srcptr g, slong glen, mp_srcptr ginv, slong ginvlen, const nmod_t mod) { slong i; if (n == 0) return; /* f^0 = 1 */ if (glen > 1) res[0][0] = 1; if (glen > 2) flint_mpn_zero(res[0] + 1, glen - 2); if (n == 1) return; /* f^1 = f */ _nmod_vec_set(res[1], f, flen); flint_mpn_zero(res[1] + flen, glen - flen - 1); if (n == 2) return; /* f^i = f^(i - 1)*f */ if (glen == 2) /* special case, constant polys */ { for (i = 2; i < n; i++) res[i][0] = n_mulmod2_preinv(res[i - 1][0], res[1][0], mod.n, mod.ninv); } else { for (i = 2; i < n; i++) _nmod_poly_mulmod_preinv(res[i], res[i - 1], glen - 1, res[1], glen - 1, g, glen, ginv, ginvlen, mod); } } void nmod_poly_powers_mod_naive(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g) { slong i; nmod_poly_t ginv; mp_ptr * res_arr; if (nmod_poly_length(g) == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powers_mod_naive). Divide by zero.\n"); } if (nmod_poly_length(f) == 0 || nmod_poly_length(g) == 1) { if (n > 0) nmod_poly_one(res + 0); for (i = 1; i < n; i++) nmod_poly_zero(res + i); return; } if (nmod_poly_length(f) >= nmod_poly_length(g)) { nmod_poly_t q, r; nmod_poly_init_mod(q, f->mod); nmod_poly_init_mod(r, f->mod); nmod_poly_divrem(q, r, f, g); nmod_poly_powers_mod_naive(res, r, n, g); nmod_poly_clear(q); nmod_poly_clear(r); return; } res_arr = (mp_ptr *) flint_malloc(n*sizeof(mp_ptr)); nmod_poly_init_mod(ginv, g->mod); for (i = 0; i < n; i++) { nmod_poly_fit_length(res + i, nmod_poly_length(g) - 1); res_arr[i] = res[i].coeffs; _nmod_poly_set_length(res + i, nmod_poly_length(g) - 1); } nmod_poly_reverse(ginv, g, nmod_poly_length(g)); nmod_poly_inv_series(ginv, ginv, nmod_poly_length(g)); _nmod_poly_powers_mod_preinv_naive(res_arr, f->coeffs, f->length, n, g->coeffs, g->length, ginv->coeffs, ginv->length, g->mod); for (i = 0; i < n; i++) _nmod_poly_normalise(res + i); nmod_poly_clear(ginv); flint_free(res_arr); } flint-3.1.3/src/nmod_poly/powmod_binexp.c000066400000000000000000000153731461254215100204510ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010, 2020 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" void _nmod_poly_powmod_fmpz_binexp(mp_ptr res, mp_srcptr poly, fmpz_t e, mp_srcptr f, slong lenf, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ; slong bits, i; if (lenf == 2) { /* n = ndivg * g. Compute (poly[0]%ndivg)^e mod ndivg and use CRT */ if (fmpz_abs_fits_ui(e)) { ulong e_ui = fmpz_get_ui(e); res[0] = n_powmod2_ui_preinv(poly[0], e_ui, mod.n, mod.ninv); } else { fmpz_t p0, nf; fmpz_init_set_ui(p0, poly[0]); fmpz_init_set_ui(nf, mod.n); fmpz_powm(p0, p0, e, nf); res[0] = fmpz_get_ui(p0); fmpz_clear(p0); fmpz_clear(nf); } } lenT = 2*lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; _nmod_vec_set(res, poly, lenf - 1); bits = fmpz_sizeinbase(e, 2); for (i = bits - 2; i >= 0; i--) { _nmod_poly_mul(T, res, lenf - 1, res, lenf - 1, mod); _nmod_poly_divrem(Q, res, T, 2*lenf - 3, f, lenf, mod); if (fmpz_tstbit(e, i)) { _nmod_poly_mul(T, res, lenf - 1, poly, lenf - 1, mod); _nmod_poly_divrem(Q, res, T, 2*lenf - 3, f, lenf, mod); } } _nmod_vec_clear(T); } void nmod_poly_powmod_fmpz_binexp(nmod_poly_t res, const nmod_poly_t poly, fmpz_t e, const nmod_poly_t f) { mp_ptr p; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int pcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powmod_fmpz_binexp). Divide by zero.\n"); } if (lenf == 1) { nmod_poly_zero(res); return; } if (len >= lenf) { nmod_poly_t t, r; nmod_poly_init_preinv(t, res->mod.n, res->mod.ninv); nmod_poly_init_preinv(r, res->mod.n, res->mod.ninv); nmod_poly_divrem(t, r, poly, f); nmod_poly_powmod_fmpz_binexp(res, r, e, f); nmod_poly_clear(t); nmod_poly_clear(r); return; } if (fmpz_cmp_ui(e, 2) <= 0) { if (fmpz_is_zero(e)) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; res->length = 1; } else if (fmpz_is_one(e)) nmod_poly_set(res, poly); else nmod_poly_mulmod(res, poly, poly, f); return; } if (len == 0) { nmod_poly_zero(res); return; } if (len < trunc) { p = _nmod_vec_init(trunc); flint_mpn_copyi(p, poly->coeffs, len); flint_mpn_zero(p + len, trunc - len); pcopy = 1; } else p = poly->coeffs; if ((res == poly && !pcopy) || res == f) { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_powmod_fmpz_binexp(t->coeffs, p, e, f->coeffs, lenf, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, trunc); _nmod_poly_powmod_fmpz_binexp(res->coeffs, p, e, f->coeffs, lenf, poly->mod); } if (pcopy) _nmod_vec_clear(p); res->length = trunc; _nmod_poly_normalise(res); } void _nmod_poly_powmod_ui_binexp(mp_ptr res, mp_srcptr poly, ulong e, mp_srcptr f, slong lenf, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ; int i; if (lenf == 2) { res[0] = n_powmod2_ui_preinv(poly[0], e, mod.n, mod.ninv); return; } lenT = 2 * lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; _nmod_vec_set(res, poly, lenf - 1); for (i = ((int) FLINT_BIT_COUNT(e) - 2); i >= 0; i--) { _nmod_poly_mul(T, res, lenf - 1, res, lenf - 1, mod); _nmod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, mod); if (e & (UWORD(1) << i)) { _nmod_poly_mul(T, res, lenf - 1, poly, lenf - 1, mod); _nmod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, mod); } } _nmod_vec_clear(T); } void nmod_poly_powmod_ui_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, const nmod_poly_t f) { mp_ptr p; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int pcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powmod_ui_binexp). Divide by zero.\n"); } if (lenf == 1) { nmod_poly_zero(res); return; } if (len >= lenf) { nmod_poly_t t, r; nmod_poly_init_preinv(t, res->mod.n, res->mod.ninv); nmod_poly_init_preinv(r, res->mod.n, res->mod.ninv); nmod_poly_divrem(t, r, poly, f); nmod_poly_powmod_ui_binexp(res, r, e, f); nmod_poly_clear(t); nmod_poly_clear(r); return; } if (e <= 2) { if (e == UWORD(0)) { nmod_poly_fit_length(res, 1); res->coeffs[0] = UWORD(1); res->length = 1; } else if (e == UWORD(1)) { nmod_poly_set(res, poly); } else nmod_poly_mulmod(res, poly, poly, f); return; } if (len == 0) { nmod_poly_zero(res); return; } if (len < trunc) { p = _nmod_vec_init(trunc); flint_mpn_copyi(p, poly->coeffs, len); flint_mpn_zero(p + len, trunc - len); pcopy = 1; } else p = poly->coeffs; if ((res == poly && !pcopy) || (res == f)) { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_powmod_ui_binexp(t->coeffs, p, e, f->coeffs, lenf, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, trunc); _nmod_poly_powmod_ui_binexp(res->coeffs, p, e, f->coeffs, lenf, poly->mod); } if (pcopy) _nmod_vec_clear(p); res->length = trunc; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/powmod_binexp_preinv.c000066400000000000000000000163041461254215100220270ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" void _nmod_poly_powmod_fmpz_binexp_preinv (mp_ptr res, mp_srcptr poly, fmpz_t e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ; slong i, bits; if (lenf == 2) { /* n = ndivg * g. Compute (poly[0]%ndivg)^e mod ndivg and use CRT */ if (fmpz_abs_fits_ui(e)) { ulong e_ui = fmpz_get_ui(e); res[0] = n_powmod2_ui_preinv(poly[0], e_ui, mod.n, mod.ninv); } else { fmpz_t p0, nf; fmpz_init_set_ui(p0, poly[0]); fmpz_init_set_ui(nf, mod.n); fmpz_powm(p0, p0, e, nf); res[0] = fmpz_get_ui(p0); fmpz_clear(p0); fmpz_clear(nf); } return; } lenT = 2*lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; _nmod_vec_set(res, poly, lenf - 1); bits = fmpz_sizeinbase(e, 2); for (i = bits - 2; i >= 0; i--) { _nmod_poly_mul(T, res, lenf - 1, res, lenf - 1, mod); _nmod_poly_divrem_newton_n_preinv(Q, res, T, 2*lenf - 3, f, lenf, finv, lenfinv, mod); if (fmpz_tstbit(e, i)) { _nmod_poly_mul(T, res, lenf - 1, poly, lenf - 1, mod); _nmod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, mod); } } _nmod_vec_clear(T); } void nmod_poly_powmod_fmpz_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, fmpz_t e, const nmod_poly_t f, const nmod_poly_t finv) { mp_ptr p; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int pcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powmod_fmpz_binexp_preinv). Divide by zero.\n"); } if (lenf == 1) { nmod_poly_zero(res); return; } if (len >= lenf) { nmod_poly_t t, r; nmod_poly_init_mod(t, res->mod); nmod_poly_init_mod(r, res->mod); nmod_poly_divrem(t, r, poly, f); nmod_poly_powmod_fmpz_binexp_preinv(res, r, e, f, finv); nmod_poly_clear(t); nmod_poly_clear(r); return; } if (fmpz_cmp_ui(e, 2) <= 0) { if (fmpz_is_zero(e)) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; res->length = 1; } else if (fmpz_is_one(e)) nmod_poly_set(res, poly); else nmod_poly_mulmod_preinv(res, poly, poly, f, finv); return; } if (len == 0) { nmod_poly_zero(res); return; } if (len < trunc) { p = _nmod_vec_init(trunc); flint_mpn_copyi(p, poly->coeffs, len); flint_mpn_zero(p + len, trunc - len); pcopy = 1; } else p = poly->coeffs; if ((res == poly && !pcopy) || res == f || res == finv) { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_powmod_fmpz_binexp_preinv(t->coeffs, p, e, f->coeffs, lenf, finv->coeffs, finv->length, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, trunc); _nmod_poly_powmod_fmpz_binexp_preinv(res->coeffs, p, e, f->coeffs, lenf, finv->coeffs, finv->length, poly->mod); } if (pcopy) _nmod_vec_clear(p); res->length = trunc; _nmod_poly_normalise(res); } void _nmod_poly_powmod_ui_binexp_preinv(mp_ptr res, mp_srcptr poly, ulong e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ, i; if (lenf == 2) { res[0] = n_powmod2_ui_preinv(poly[0], e, mod.n, mod.ninv); return; } lenT = 2 * lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; _nmod_vec_set(res, poly, lenf - 1); for (i = FLINT_BIT_COUNT(e) - 2; i >= 0; i--) { _nmod_poly_mul(T, res, lenf - 1, res, lenf - 1, mod); _nmod_poly_divrem_newton_n_preinv(Q, res, T, 2*lenf - 3, f, lenf, finv, lenfinv, mod); if (e & (UWORD(1) << i)) { _nmod_poly_mul(T, res, lenf - 1, poly, lenf - 1, mod); _nmod_poly_divrem_newton_n_preinv(Q, res, T, 2*lenf - 3, f, lenf, finv, lenfinv, mod); } } _nmod_vec_clear(T); } void nmod_poly_powmod_ui_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, ulong e, const nmod_poly_t f, const nmod_poly_t finv) { mp_ptr p; slong len = poly->length; slong lenf = f->length; slong trunc = lenf - 1; int pcopy = 0; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powmod_ui_binexp_preinv). Divide by zero.\n"); } if (lenf == 1) { nmod_poly_zero(res); return; } if (len >= lenf) { nmod_poly_t t, r; nmod_poly_init_mod(t, res->mod); nmod_poly_init_mod(r, res->mod); nmod_poly_divrem(t, r, poly, f); nmod_poly_powmod_ui_binexp_preinv(res, r, e, f, finv); nmod_poly_clear(t); nmod_poly_clear(r); return; } if (e <= 2) { if (e == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; res->length = 1; } else if (e == 1) nmod_poly_set(res, poly); else nmod_poly_mulmod_preinv(res, poly, poly, f, finv); return; } if (len == 0) { nmod_poly_zero(res); return; } if (len < trunc) { p = _nmod_vec_init(trunc); flint_mpn_copyi(p, poly->coeffs, len); flint_mpn_zero(p + len, trunc - len); pcopy = 1; } else p = poly->coeffs; if ((res == poly && !pcopy) || res == f || res == finv) { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_powmod_ui_binexp_preinv(t->coeffs, p, e, f->coeffs, lenf, finv->coeffs, finv->length, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, trunc); _nmod_poly_powmod_ui_binexp_preinv(res->coeffs, p, e, f->coeffs, lenf, finv->coeffs, finv->length, poly->mod); } if (pcopy) _nmod_vec_clear(p); res->length = trunc; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/powmod_x_preinv.c000066400000000000000000000207151461254215100210120ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010, 2020 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "fmpz.h" void _nmod_poly_powmod_x_fmpz_preinv (mp_ptr res, fmpz_t e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ, window; slong i, l, c; lenT = 2*lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; flint_mpn_zero (res, lenf - 1); res[0] = 1; l = z_sizeinbase (lenf - 1, 2) - 2; window = (WORD(1) << l); c = l; i = fmpz_sizeinbase(e, 2) - 2; if (i <= l) { window = (WORD(1) << i); c = i; l = i; } if (c == 0) { _nmod_poly_shift_left(T, res, lenf - 1, window); _nmod_poly_divrem_newton_n_preinv(Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, mod); c = l + 1; window = 0; } for (; i >= 0; i--) { _nmod_poly_mul(T, res, lenf - 1, res, lenf - 1, mod); _nmod_poly_divrem_newton_n_preinv(Q, res, T, 2*lenf - 3, f, lenf, finv, lenfinv, mod); c--; if (fmpz_tstbit(e, i)) { if (window == 0 && i <= l - 1) c = i; if (c >= 0) window = window | (WORD(1) << c); } else if (window == 0) c = l + 1; if (c == 0) { _nmod_poly_shift_left(T, res, lenf - 1, window); _nmod_poly_divrem_newton_n_preinv(Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, mod); c = l + 1; window = 0; } } _nmod_vec_clear(T); } void nmod_poly_powmod_x_fmpz_preinv(nmod_poly_t res, fmpz_t e, const nmod_poly_t f, const nmod_poly_t finv) { slong lenf = f->length; slong trunc = lenf - 1; nmod_poly_t tmp; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powmod_x_fmpz_preinv). Divide by zero.\n"); } if (lenf == 1) { nmod_poly_zero(res); return; } if (lenf == 2) { nmod_poly_t r, poly; nmod_poly_init_mod(tmp, res->mod); nmod_poly_init_mod(r, res->mod); nmod_poly_init2_preinv(poly, res->mod.n, res->mod.ninv, 2); nmod_poly_set_coeff_ui(poly, 1, 1); nmod_poly_divrem(tmp, r, poly, f); nmod_poly_powmod_fmpz_binexp_preinv(res, r, e, f, finv); nmod_poly_clear(tmp); nmod_poly_clear(r); nmod_poly_clear(poly); return; } if (fmpz_cmp_ui(e, 2) <= 0) { if (fmpz_is_zero(e)) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; res->length = 1; } else if (fmpz_is_one(e)) { nmod_poly_t r; nmod_poly_init2_preinv(r, res->mod.n, res->mod.ninv, 2); nmod_poly_set_coeff_ui(r, 1, 1); nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv); nmod_poly_divrem (tmp, res, r, f); nmod_poly_clear(tmp); nmod_poly_clear(r); } else { nmod_poly_init2_preinv(tmp, res->mod.n, res->mod.ninv, 3); nmod_poly_set_coeff_ui(tmp, 1, 1); nmod_poly_mulmod(res, tmp, tmp, f); nmod_poly_clear(tmp); } return; } if (res == f || res == finv) { nmod_poly_init2(tmp, res->mod.n, trunc); _nmod_poly_powmod_x_fmpz_preinv(tmp->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, f->mod); nmod_poly_swap(res, tmp); nmod_poly_clear(tmp); } else { nmod_poly_fit_length(res, trunc); _nmod_poly_powmod_x_fmpz_preinv(res->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, f->mod); } res->length = trunc; _nmod_poly_normalise(res); } void _nmod_poly_powmod_x_ui_preinv(mp_ptr res, ulong e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ, window; int i, l, c; lenT = 2 * lenf - 3; lenQ = FLINT_MAX(lenT - lenf + 1, 1); T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; flint_mpn_zero(res, lenf - 1); res[0] = 1; l = (int) z_sizeinbase(lenf - 1, 2) - 2; window = (WORD(1) << l); c = l; i = (int) FLINT_BIT_COUNT(e) - 2; if (i <= l) { window = (WORD(1) << i); c = i; l = i; } if (c == 0) { _nmod_poly_shift_left(T, res, lenf - 1, window); _nmod_poly_divrem_newton_n_preinv(Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, mod); c = l + 1; window = 0; } for ( ; i >= 0; i--) { _nmod_poly_mul(T, res, lenf - 1, res, lenf - 1, mod); _nmod_poly_divrem_newton_n_preinv(Q, res, T, 2*lenf - 3, f, lenf, finv, lenfinv, mod); c--; if (e & (UWORD(1) << i)) { if (window == 0 && i <= l - 1) c = i; if ( c >= 0) window = window | (WORD(1) << c); } else if (window == 0) c = l + 1; if (c == 0) { _nmod_poly_shift_left(T, res, lenf - 1, window); _nmod_poly_divrem_newton_n_preinv(Q, res, T, lenf - 1 + window, f, lenf, finv, lenfinv, mod); c = l + 1; window = 0; } } _nmod_vec_clear(T); } void nmod_poly_powmod_x_ui_preinv(nmod_poly_t res, ulong e, const nmod_poly_t f, const nmod_poly_t finv) { slong lenf = f->length; slong trunc = lenf - 1; nmod_poly_t tmp; if (lenf == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_powmod_x_ui_preinv). Divide by zero.\n"); } if (lenf == 1) { nmod_poly_zero(res); return; } if (lenf == 2) { nmod_poly_t r, poly; nmod_poly_init_mod(tmp, res->mod); nmod_poly_init_mod(r, res->mod); nmod_poly_init2_preinv(poly, res->mod.n, res->mod.ninv, 2); nmod_poly_set_coeff_ui (poly, 1, 1); nmod_poly_divrem(tmp, r, poly, f); nmod_poly_powmod_ui_binexp_preinv(res, r, e, f, finv); nmod_poly_clear(tmp); nmod_poly_clear(r); nmod_poly_clear(poly); return; } if (e <= 2) { if (e == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; res->length = 1; } else if (e == 1) { nmod_poly_t r; nmod_poly_init2_preinv(r, res->mod.n, res->mod.ninv, 2); nmod_poly_set_coeff_ui(r, 1, 1); nmod_poly_init_mod(tmp, res->mod); nmod_poly_divrem(tmp, res, r, f); nmod_poly_clear(tmp); nmod_poly_clear(r); } else { nmod_poly_init2_preinv(tmp, res->mod.n, res->mod.ninv, 3); nmod_poly_set_coeff_ui(tmp, 1, 1); nmod_poly_mulmod(res, tmp, tmp, f); nmod_poly_clear(tmp); } return; } if (res == f || res == finv) { nmod_poly_init2(tmp, res->mod.n, trunc); _nmod_poly_powmod_x_ui_preinv(tmp->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, f->mod); nmod_poly_swap(res, tmp); nmod_poly_clear(tmp); } else { nmod_poly_fit_length(res, trunc); _nmod_poly_powmod_x_ui_preinv(res->coeffs, e, f->coeffs, lenf, finv->coeffs, finv->length, f->mod); } res->length = trunc; _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/product_roots_nmod_vec.c000066400000000000000000000033201461254215100223440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_product_roots_nmod_vec(mp_ptr poly, mp_srcptr xs, slong n, nmod_t mod) { if (n == 0) { poly[0] = UWORD(1); } else if (n < 20) { slong i, j; poly[n] = UWORD(1); poly[n - 1] = nmod_neg(xs[0], mod); for (i = 1; i < n; i++) { poly[n-i-1] = nmod_neg(n_mulmod2_preinv(poly[n-i], xs[i], mod.n, mod.ninv), mod); for (j = 0; j < i - 1; j++) { poly[n-i+j] = nmod_sub(poly[n-i+j], n_mulmod2_preinv(poly[n-i+j+1], xs[i], mod.n, mod.ninv), mod); } poly[n-1] = nmod_sub(poly[n-1], xs[i], mod); } } else { const slong m = (n + 1) / 2; mp_ptr tmp; tmp = _nmod_vec_init(n + 2); _nmod_poly_product_roots_nmod_vec(tmp, xs, m, mod); _nmod_poly_product_roots_nmod_vec(tmp + m + 1, xs + m, n - m, mod); _nmod_poly_mul(poly, tmp, m + 1, tmp + m + 1, n - m + 1, mod); _nmod_vec_clear(tmp); } } void nmod_poly_product_roots_nmod_vec(nmod_poly_t poly, mp_srcptr xs, slong n) { nmod_poly_fit_length(poly, n + 1); _nmod_poly_product_roots_nmod_vec(poly->coeffs, xs, n, poly->mod); poly->length = n + 1; } flint-3.1.3/src/nmod_poly/profile/000077500000000000000000000000001461254215100170625ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly/profile/p-evaluate_mat.c000066400000000000000000000044101461254215100221310ustar00rootroot00000000000000/* Copyright (C) 2015 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" #include "nmod_mat.h" #include #define MIN_DIMENSION 1 #define MAX_DIMENSION 501 #define DIMENSION_SCALE 5 #define MIN_LENGTH 1 #define MAX_LENGTH 40 int main(void) { slong dim, len, i; int result; nmod_mat_t A, B, C; nmod_poly_t poly; mp_limb_t n; clock_t horner_begin, paterson_begin; double horner_time, paterson_time; FLINT_TEST_INIT(state); n = n_randtest_not_zero(state); printf ("#Dimension\tLength\t\tHoner's\t\t\tPaterson\t\tBetter(0 = Horner, 1 = Paterson)\n"); for (dim = MIN_DIMENSION; dim <= MAX_DIMENSION; dim += DIMENSION_SCALE) { nmod_mat_init(A, dim, dim, n); nmod_mat_init(B, dim, dim, n); nmod_mat_init(C, dim, dim, n); do { nmod_mat_randtest(A, state); } while (nmod_mat_is_zero(A)); for (len = MIN_LENGTH; len <= MAX_LENGTH; len++) { nmod_poly_init2(poly, n, len); for (i = 0; i < len; i++) { poly->coeffs[i] = n_randint(state, n); } poly->length = len; horner_begin = clock(); nmod_poly_evaluate_mat_horner(B, poly, A); horner_time = (double) (clock() - horner_begin) / CLOCKS_PER_SEC; paterson_begin = clock(); nmod_poly_evaluate_mat_paterson_stockmeyer(C, poly, A); paterson_time = (double) (clock() - paterson_begin) / CLOCKS_PER_SEC; result = horner_time < paterson_time ? 0 : 1; flint_printf("%wd\t\t%wd\t\t%lf\t\t%lf\t\t%d\n", dim, len, horner_time, paterson_time, result); nmod_poly_clear(poly); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/nmod_poly/profile/p-gcd.c000066400000000000000000000112671461254215100202270ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" /* Profiling and benchmarking code for GCD in nmod_poly. For three different prime moduli p[i], for a sequence of degrees degs[k], we create 100 random polynomials A, B, C of degree degs[k]/2 and then compute GCD(AC, BC) repeatedly, runs[i][k] times. */ #define N 50 int main(void) { mp_limb_t p[] = {17ul, 2147483659ul, 9223372036854775837ul}; const slong degs[] = { 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 340, 360, 380, 400, 420, 440, 460, 480, 500, 520, 540, 560, 580, 600, 620, 640, 660, 680, 700, 720, 740, 760, 780, 800, 820, 840, 860, 880, 900, 920, 940, 960, 980, 1000}; const slong runs[3][N] = {{ 2000, 1000, 500, 300, 200, 200, 200, 180, 140, 140, 100, 80, 80, 80, 50, 50, 40, 30, 30, 20, 18, 16, 14, 12, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5}, { 1400, 800, 400, 260, 160, 140, 120, 100, 60, 60, 50, 50, 40, 40, 30, 30, 20, 20, 20, 15, 14, 13, 12, 11, 10, 10, 10, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4}, { 1400, 800, 400, 260, 160, 120, 100, 80, 60, 50, 50, 40, 30, 20, 20, 20, 15, 15, 15, 12, 12, 11, 11, 10, 10, 10, 10, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4}}; clock_t c0, c1; long double cpu[3][2][N]; slong i, k, c, n; nmod_poly_t A, B, C, G; FLINT_TEST_INIT(state); for (i = 0; i < 3; i++) { flint_printf("---[Modulus %wu]---\n", p[i]), fflush(stdout); for (k = 0; k < N; k++) { const slong d = degs[k]; const slong r = runs[i][k]; cpu[i][0][k] = 0; cpu[i][1][k] = 0; nmod_poly_init(A, p[i]); nmod_poly_init(B, p[i]); nmod_poly_init(C, p[i]); nmod_poly_init(G, p[i]); for (c = 0; c < 100; c++) { nmod_poly_randtest(A, state, d/2); nmod_poly_randtest(B, state, d/2); nmod_poly_randtest(C, state, d/2); nmod_poly_mul(A, A, C); nmod_poly_mul(B, B, C); c0 = clock(); for (n = 0; n < r; n++) nmod_poly_gcd_euclidean(G, A, B); c1 = clock(); cpu[i][0][k] += (c1 - c0); c0 = clock(); for (n = 0; n < r; n++) nmod_poly_gcd_hgcd(G, A, B); c1 = clock(); cpu[i][1][k] += (c1 - c0); } cpu[i][0][k] = (long double) cpu[i][0][k] / (long double) CLOCKS_PER_SEC; cpu[i][1][k] = (long double) cpu[i][1][k] / (long double) CLOCKS_PER_SEC; cpu[i][0][k] = (long double) cpu[i][0][k] / (long double) (100*r); cpu[i][1][k] = (long double) cpu[i][1][k] / (long double) (100*r); flint_printf("%4ld %10.WORD(8)f %10.WORD(8)f\n", A->length, cpu[i][0][k], cpu[i][1][k]); fflush(stdout); nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(G); } } flint_printf("cpu = ["); for (i = 0; i < 3; i++) { flint_printf("[["); for (k = 0; k < N; k++) flint_printf("%.WORD(8)f,", cpu[i][0][k]); flint_printf("],"); flint_printf("["); for (k = 0; k < N; k++) flint_printf("%.WORD(8)f,", cpu[i][1][k]); flint_printf("]],"); } flint_printf("]\n"); flint_randclear(state); return 0; } flint-3.1.3/src/nmod_poly/profile/p-mul.c000066400000000000000000000041401461254215100202570ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" typedef struct { slong n; } info_t; void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong n = info->n, i, j; slong scale; nmod_poly_t a, b, c; mp_limb_t m; FLINT_TEST_INIT(state); m = n_randint(state, 1<<((48-FLINT_BIT_COUNT(n))/2)); if (m == 0) m = 2; nmod_poly_init2(a, m, n); nmod_poly_init2(b, m, n); nmod_poly_init2(c, m, 2*n - 1); for (i = 0; i < n; i++) { a->coeffs[i] = n_randint(state, m); b->coeffs[i] = n_randint(state, m); } a->length = n; b->length = n; scale = 1; if (n < 100000) scale = 10; if (n < 10000) scale = 100; if (n < 100) scale = 1000; for (i = 0; i < count; i++) { prof_start(); for (j = 0; j < scale; j++) { nmod_poly_mul(c, a, b); } prof_stop(); if (c->coeffs[n - 2] == 123) flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); flint_randclear(state); } int main(void) { double min, max; info_t info; slong k, scale; for (k = 2; k <= 30; k++) { info.n = 1<. */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" typedef struct { slong n; slong s; slong alg; } info_t; void sample(void * arg, ulong count) { info_t * info = (info_t *) arg; slong n = info->n, i, j, s= info->s, alg=info->alg; slong scale; nmod_poly_t a, b, c, d, dinv; mp_limb_t m; FLINT_TEST_INIT(state); m = n_randint(state, 1<<((48-FLINT_BIT_COUNT(n))/2)); /* modulus */ if (m == 0) m = 2; nmod_poly_init2(a, m, n); nmod_poly_init2(b, m, n); nmod_poly_init2(c, m, 2*n - 1); nmod_poly_init2(d, m, s); nmod_poly_init2(dinv, m, s); for (i = 0; i < n; i++) { a->coeffs[i] = n_randint(state, m); b->coeffs[i] = n_randint(state, m); } for (i = 0; i < s; i++) d->coeffs[i] = n_randint(state, m); a->length = n; b->length = n; d->length = s; nmod_poly_reverse(dinv, d, s); nmod_poly_inv_series(dinv, dinv, s); scale = 1; if (n < 100000) scale = 10; if (n < 10000) scale = 100; if (n < 100) scale = 1000; for (i = 0; i < count; i++) { if (alg == 1) { prof_start(); for (j = 0; j < scale; j++) { nmod_poly_mulmod_preinv(c, a, b, d, dinv); } prof_stop(); } else { prof_start(); for (j = 0; j < scale; j++) { nmod_poly_mulmod(c, a, b, d); } prof_stop(); } if (c->coeffs[n - 2] == 123) flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); nmod_poly_clear(dinv); flint_randclear(state); } int main(void) { double min, max; info_t info; slong i, k, scale; for (k = 2; k <= 30; k++) { info.n = 1<. */ #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_randtest(nmod_poly_t poly, flint_rand_t state, slong len) { nmod_poly_fit_length(poly, len); _nmod_vec_randtest(poly->coeffs, state, len, poly->mod); poly->length = len; _nmod_poly_normalise(poly); } void nmod_poly_randtest_monic(nmod_poly_t poly, flint_rand_t state, slong len) { nmod_poly_fit_length(poly, len); _nmod_vec_randtest(poly->coeffs, state, len - 1, poly->mod); poly->coeffs[len - 1] = 1; poly->length = len; } static void nmod_poly_randtest_monic_sparse(nmod_poly_t poly, flint_rand_t state, slong len, slong nonzero) { slong i; nmod_poly_fit_length(poly, len); _nmod_vec_zero(poly->coeffs, len); poly->coeffs[0] = n_randtest(state) % poly->mod.n; for (i = 1; i < nonzero; i++) poly->coeffs[n_randint(state, len - 1) + 1] = n_randtest(state) % poly->mod.n; poly->coeffs[len - 1] = 1; _nmod_poly_set_length(poly, len); } void nmod_poly_randtest_irreducible(nmod_poly_t poly, flint_rand_t state, slong len) { do { nmod_poly_randtest(poly, state, len); } while (nmod_poly_is_zero(poly) || !(nmod_poly_is_irreducible(poly))); } void nmod_poly_randtest_monic_irreducible(nmod_poly_t poly, flint_rand_t state, slong len) { do { nmod_poly_randtest_monic(poly, state, len); } while (nmod_poly_is_zero(poly) || !(nmod_poly_is_irreducible(poly))); } static void nmod_poly_randtest_monic_irreducible_sparse(nmod_poly_t poly, flint_rand_t state, slong len) { slong i = 0; slong terms = 3; do { i++; terms += ((i % 4) == 0); if (terms >= len) terms = 3; nmod_poly_randtest_monic_sparse(poly, state, len, terms); } while (nmod_poly_is_zero(poly) || !nmod_poly_is_irreducible(poly)); } void nmod_poly_randtest_trinomial(nmod_poly_t poly, flint_rand_t state, slong len) { ulong k; nmod_poly_fit_length(poly, len); _nmod_vec_zero(poly->coeffs, len); poly->coeffs[0] = n_randtest(state) % poly->mod.n; poly->coeffs[len - 1] = 1; k = (n_randtest(state) % (len - 2)) + 1; poly->coeffs[k] = n_randtest(state) % poly->mod.n; _nmod_poly_set_length(poly, len); } void nmod_poly_randtest_pentomial(nmod_poly_t poly, flint_rand_t state, slong len) { nmod_poly_fit_length(poly, len); _nmod_vec_zero(poly->coeffs, len); poly->coeffs[0] = n_randtest(state) % poly->mod.n; poly->coeffs[1] = n_randtest(state) % poly->mod.n; poly->coeffs[2] = n_randtest(state) % poly->mod.n; poly->coeffs[3] = n_randtest(state) % poly->mod.n; poly->coeffs[len - 1] = 1; _nmod_poly_set_length(poly, len); } int nmod_poly_randtest_trinomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts) { slong i = 0; while (max_attempts == 0 || i < max_attempts) { nmod_poly_randtest_trinomial(poly, state, len); if (!nmod_poly_is_zero(poly) && nmod_poly_is_irreducible(poly)) { return 1; } i++; } return 0; } int nmod_poly_randtest_pentomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts) { slong i = 0; while (max_attempts == 0 || i < max_attempts) { nmod_poly_randtest_pentomial(poly, state, len); if (!nmod_poly_is_zero(poly) && nmod_poly_is_irreducible(poly)) { return 1; } i++; } return 0; } void nmod_poly_randtest_sparse_irreducible(nmod_poly_t poly, flint_rand_t state, slong len) { if (len < 3) { nmod_poly_randtest_monic_irreducible(poly, state, len); return; } /* Try trinomials */ if (nmod_poly_randtest_trinomial_irreducible(poly, state, len, 2*len)) return; if (len < 5) { nmod_poly_randtest_monic_irreducible(poly, state, len); return; } /* Try pentomials */ if (nmod_poly_randtest_pentomial_irreducible(poly, state, len, 2*len)) return; /* Random monic sparse */ nmod_poly_randtest_monic_irreducible_sparse(poly, state, len); } flint-3.1.3/src/nmod_poly/randtest_monic_primitive.c000066400000000000000000000016041461254215100226700ustar00rootroot00000000000000/* Copyright (C) 2018 Luca De Feo This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "fq_nmod.h" void nmod_poly_randtest_monic_primitive(nmod_poly_t poly, flint_rand_t state, slong len) { fq_nmod_ctx_t ctx; fq_nmod_t X; int primitive = 0; while (!primitive) { nmod_poly_randtest_monic_irreducible(poly, state, len); fq_nmod_ctx_init_modulus(ctx, poly, "X"); fq_nmod_init(X, ctx); fq_nmod_gen(X, ctx); primitive = fq_nmod_is_primitive(X, ctx); fq_nmod_clear(X, ctx); fq_nmod_ctx_clear(ctx); } } flint-3.1.3/src/nmod_poly/realloc.c000066400000000000000000000016231461254215100172110ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void nmod_poly_realloc(nmod_poly_t poly, slong alloc) { if (alloc == 0) { nmod_poly_clear(poly); poly->length = 0; poly->alloc = 0; poly->coeffs = NULL; return; } poly->coeffs = (mp_ptr) flint_realloc(poly->coeffs, alloc * sizeof(mp_limb_t)); poly->alloc = alloc; /* truncate poly if necessary */ if (poly->length > alloc) { poly->length = alloc; _nmod_poly_normalise(poly); } } flint-3.1.3/src/nmod_poly/rem.c000066400000000000000000000061401461254215100163520ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" void _nmod_poly_rem_q1(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { slong i; mp_limb_t invL, t, q0, q1, t1, t0, s1, s0; FLINT_ASSERT(lenA == lenB + 1); invL = (B[lenB-1] == 1) ? 1 : n_invmod(B[lenB-1], mod.n); if (lenB < 2) return; q1 = n_mulmod2_preinv(A[lenA-1], invL, mod.n, mod.ninv); t = n_mulmod2_preinv(q1, B[lenB-2], mod.n, mod.ninv); t = n_submod(t, A[lenA-2], mod.n); q0 = n_mulmod2_preinv(t, invL, mod.n, mod.ninv); q1 = nmod_neg(q1, mod); /* R = A + (q1*x + q0)*B */ t = A[0]; NMOD_ADDMUL(t, q0, B[0], mod); R[0] = t; if (mod.norm >= (FLINT_BITS + 1)/2 + 1) { for (i = 1; i < lenB - 1; i++) { NMOD_RED2(R[i], 0, A[i] + q1*B[i - 1] + q0*B[i], mod); } } else if (mod.norm != 0) { for (i = 1; i < lenB - 1; i++) { umul_ppmm(t1, t0, q1, B[i - 1]); umul_ppmm(s1, s0, q0, B[i]); add_ssaaaa(t1, t0, t1, t0, 0, A[i]); add_ssaaaa(t1, t0, t1, t0, s1, s0); t1 = FLINT_MIN(t1, t1 - mod.n); FLINT_ASSERT(t1 < mod.n); NMOD_RED2(R[i], t1, t0, mod); } } else { for (i = 1; i < lenB - 1; i++) { t = A[i]; NMOD_ADDMUL(t, q1, B[i - 1], mod); NMOD_ADDMUL(t, q0, B[i], mod); R[i] = t; } } } void _nmod_poly_rem(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenA - lenB == 1) { _nmod_poly_rem_q1(R, A, lenA, B, lenB, mod); } else if (lenB >= 2) { mp_ptr Q; TMP_INIT; TMP_START; Q = TMP_ALLOC((lenA - lenB + 1) * sizeof(mp_limb_t)); _nmod_poly_divrem(Q, R, A, lenA, B, lenB, mod); TMP_END; } } void nmod_poly_rem(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { const slong lenA = A->length, lenB = B->length; nmod_poly_t tR; mp_ptr r; if (lenB == 0) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_rem). Division by zero.\n"); } if (lenA < lenB) { nmod_poly_set(R, A); return; } if (R == B) { nmod_poly_init2_preinv(tR, B->mod.n, B->mod.ninv, lenB - 1); r = tR->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_rem(r, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (R == B) { nmod_poly_swap(R, tR); nmod_poly_clear(tR); } R->length = lenB - 1; _nmod_poly_normalise(R); } flint-3.1.3/src/nmod_poly/remove.c000066400000000000000000000020171461254215100170630ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" ulong nmod_poly_remove(nmod_poly_t f, const nmod_poly_t p) { nmod_poly_t q, r; ulong i = 0; nmod_poly_init_preinv(q, p->mod.n, p->mod.ninv); nmod_poly_init_preinv(r, p->mod.n, p->mod.ninv); while (1) { if (f->length < p->length) break; nmod_poly_divrem(q, r, f, p); if (r->length == 0) nmod_poly_swap(q, f); else break; i++; } nmod_poly_clear(q); nmod_poly_clear(r); return i; } flint-3.1.3/src/nmod_poly/resultant.c000066400000000000000000000131161461254215100176110ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" mp_limb_t _nmod_poly_resultant(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { if (poly1 == poly2) { return 0; } else if (len2 == 1) { return nmod_pow_ui(poly2[0], len1 - 1, mod); } else { slong cutoff = NMOD_BITS(mod) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; mp_limb_t res; gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); if (_gr_poly_resultant_small(&res, poly1, len1, poly2, len2, ctx) != GR_SUCCESS) { if (len2 < cutoff) res = _nmod_poly_resultant_euclidean(poly1, len1, poly2, len2, mod); else GR_MUST_SUCCEED(_gr_poly_resultant_hgcd(&res, poly1, len1, poly2, len2, NMOD_POLY_HGCD_CUTOFF, cutoff, ctx)); } return res; } } mp_limb_t nmod_poly_resultant(const nmod_poly_t f, const nmod_poly_t g) { const slong len1 = f->length; const slong len2 = g->length; mp_limb_t r; if (len1 == 0 || len2 == 0) { r = 0; } else { if (len1 >= len2) { r = _nmod_poly_resultant(f->coeffs, len1, g->coeffs, len2, f->mod); } else { r = _nmod_poly_resultant(g->coeffs, len2, f->coeffs, len1, f->mod); if (((len1 | len2) & WORD(1)) == WORD(0)) r = nmod_neg(r, f->mod); } } return r; } mp_limb_t _nmod_poly_resultant_euclidean(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { if (poly1 == poly2) { return 0; } else if (len2 == 1) { if (len1 == 1) { return 1; } else if (len1 == 2) { return poly2[0]; } else { return n_powmod2_ui_preinv(poly2[0], len1 - 1, mod.n, mod.ninv); } } else /* len1 >= len2 >= 2 */ { mp_limb_t res = 1; mp_ptr u, v, r, t, w; slong l0, l1, l2; mp_limb_t lc; w = _nmod_vec_init(3 * len1); u = w; v = w + len1; r = v + len1; _nmod_vec_set(u, poly1, len1); _nmod_vec_set(v, poly2, len2); l1 = len1; l2 = len2; do { l0 = l1; l1 = l2; lc = v[l1 - 1]; _nmod_poly_rem(r, u, l0, v, l1, mod); l2 = l1 - 1; MPN_NORM(r, l2); { t = u; u = v; v = r; r = t; } if (l2 >= 1) { lc = n_powmod2_preinv(lc, l0 - l2, mod.n, mod.ninv); res = n_mulmod2_preinv(res, lc, mod.n, mod.ninv); if (((l0 | l1) & 1) == 0) { res = nmod_neg(res, mod); } } else { if (l1 == 1) { lc = n_powmod2_preinv(lc, l0 - 1, mod.n, mod.ninv); res = n_mulmod2_preinv(res, lc, mod.n, mod.ninv); } else { res = 0; } } } while (l2 > 0); _nmod_vec_clear(w); return res; } } mp_limb_t nmod_poly_resultant_euclidean(const nmod_poly_t f, const nmod_poly_t g) { const slong len1 = f->length; const slong len2 = g->length; mp_limb_t r; if (len1 == 0 || len2 == 0) { r = 0; } else { if (len1 >= len2) { r = _nmod_poly_resultant_euclidean(f->coeffs, len1, g->coeffs, len2, f->mod); } else { r = _nmod_poly_resultant_euclidean(g->coeffs, len2, f->coeffs, len1, f->mod); if (((len1 | len2) & WORD(1)) == WORD(0)) r = nmod_neg(r, f->mod); } } return r; } mp_limb_t _nmod_poly_resultant_hgcd(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { gr_ctx_t ctx; slong cutoff = NMOD_BITS(mod) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; mp_limb_t res; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_resultant_hgcd(&res, poly1, len1, poly2, len2, NMOD_POLY_HGCD_CUTOFF, cutoff, ctx)); return res; } mp_limb_t nmod_poly_resultant_hgcd(const nmod_poly_t f, const nmod_poly_t g) { const slong len1 = f->length; const slong len2 = g->length; mp_limb_t r; if (len1 == 0 || len2 == 0) { r = 0; } else { if (len1 >= len2) { r = _nmod_poly_resultant_hgcd(f->coeffs, len1, g->coeffs, len2, f->mod); } else { r = _nmod_poly_resultant_hgcd(g->coeffs, len2, f->coeffs, len1, f->mod); if (((len1 | len2) & WORD(1)) == WORD(0)) r = nmod_neg(r, f->mod); } } return r; } flint-3.1.3/src/nmod_poly/reverse.c000066400000000000000000000023461461254215100172460ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void _nmod_poly_reverse(mp_ptr output, mp_srcptr input, slong len, slong m) { slong i, min; mp_limb_t temp; if (input != output) { min = FLINT_MIN(m, len); for (i = 0; i < min; i++) output[m - i - 1] = input[i]; for ( ; i < m; i++) output[m - i - 1] = WORD(0); } else { for (i = 0; i < m/2; i++) { temp = i < len ? input[i] : 0; output[i] = m - i - 1 < len ? input[m - i - 1] : 0; output[m - i - 1] = temp; } if (m & 1 && i >= len) output[i] = 0; } } void nmod_poly_reverse(nmod_poly_t output, const nmod_poly_t input, slong m) { nmod_poly_fit_length(output, m); _nmod_poly_reverse(output->coeffs, input->coeffs, input->length, m); output->length = m; _nmod_poly_normalise(output); } flint-3.1.3/src/nmod_poly/revert_series.c000066400000000000000000000030311461254215100204440ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr.h" #include "gr_poly.h" void _nmod_poly_revert_series(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_revert_series(Qinv, Q, Qlen, n, ctx)); } void nmod_poly_revert_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { slong Qlen = Q->length; if (Qlen < 2 || Q->coeffs[0] != 0 || Q->coeffs[1] == 0) { flint_throw(FLINT_ERROR, "(nmod_poly_revert_series): " "Input must have zero constant and an invertible coefficient of x^1.\n"); } if (Qinv != Q) { nmod_poly_fit_length(Qinv, n); _nmod_poly_revert_series(Qinv->coeffs, Q->coeffs, Q->length, n, Q->mod); } else { nmod_poly_t t; nmod_poly_init2(t, Q->mod.n, n); _nmod_poly_revert_series(t->coeffs, Q->coeffs, Q->length, n, Q->mod); nmod_poly_swap(Qinv, t); nmod_poly_clear(t); } _nmod_poly_set_length(Qinv, n); _nmod_poly_normalise(Qinv); } flint-3.1.3/src/nmod_poly/scalar.c000066400000000000000000000025421461254215100170360ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void nmod_poly_scalar_addmul_nmod(nmod_poly_t A, const nmod_poly_t B, ulong x) { slong Alen = A->length; slong Blen = B->length; if (x == 0 || Blen < 1) return; nmod_poly_fit_length(A, Blen); if (Blen > Alen) _nmod_vec_zero(A->coeffs + Alen, Blen - Alen); _nmod_vec_scalar_addmul_nmod(A->coeffs, B->coeffs, Blen, x, A->mod); _nmod_poly_set_length(A, FLINT_MAX(Alen, Blen)); _nmod_poly_normalise(A); } void nmod_poly_scalar_mul_nmod(nmod_poly_t res, const nmod_poly_t poly1, mp_limb_t c) { if ((poly1->length == 0) || (c == 0)) { nmod_poly_zero(res); return; } nmod_poly_fit_length(res, poly1->length); _nmod_vec_scalar_mul_nmod(res->coeffs, poly1->coeffs, poly1->length, c, poly1->mod); res->length = poly1->length; _nmod_poly_normalise(res); /* there may have been cancellation */ } flint-3.1.3/src/nmod_poly/set_coeff_ui.c000066400000000000000000000022211461254215100202150ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" void nmod_poly_set_coeff_ui(nmod_poly_t poly, slong j, ulong c) { if (c >= poly->mod.n) NMOD_RED(c, c, poly->mod); nmod_poly_fit_length(poly, j + 1); if (j + 1 < poly->length) /* interior */ poly->coeffs[j] = c; else if (j + 1 == poly->length) /* leading coeff */ { if (c != 0) poly->coeffs[j] = c; else { poly->length--; _nmod_poly_normalise(poly); } } else /* extend polynomial */ { if (c == 0) return; else { flint_mpn_zero(poly->coeffs + poly->length, j - poly->length); poly->coeffs[j] = c; poly->length = j + 1; } } } flint-3.1.3/src/nmod_poly/set_str.c000066400000000000000000000023041461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" int nmod_poly_set_str(nmod_poly_t poly, const char * s) { const char * whitespace = " \t\n\r"; slong i, length; mp_limb_t n; if (flint_sscanf(s, "%wd %wu", &length, &n) != 2) return 0; /* jump past length (n will be skipped in first loop iter) */ s += strcspn(s, whitespace); s += strspn(s, whitespace); nmod_poly_fit_length(poly, length); poly->length = length; for (i = 0; i < length; i++) { s += strcspn(s, whitespace); /* jump to next whitespace */ s += strspn(s, whitespace); /* skip whitespace */ if (!flint_sscanf(s, "%wu", &poly->coeffs[i])) { poly->length = i; return 0; } } _nmod_poly_normalise(poly); return 1; } flint-3.1.3/src/nmod_poly/set_trunc.c000066400000000000000000000017071461254215100176010ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void nmod_poly_set_trunc(nmod_poly_t res, const nmod_poly_t poly, slong len) { if (poly == res) { if (res->length > len) { res->length = len; _nmod_poly_normalise(res); } } else { slong rlen; rlen = FLINT_MIN(len, poly->length); while (rlen > 0 && poly->coeffs[rlen - 1] == 0) rlen--; nmod_poly_fit_length(res, rlen); _nmod_vec_set(res->coeffs, poly->coeffs, rlen); _nmod_poly_set_length(res, rlen); } } flint-3.1.3/src/nmod_poly/shift_left_right.c000066400000000000000000000025241461254215100211150ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void _nmod_poly_shift_left(mp_ptr res, mp_srcptr poly, slong len, slong k) { flint_mpn_copyd(res + k, poly, len); flint_mpn_zero(res, k); } void nmod_poly_shift_left(nmod_poly_t res, const nmod_poly_t poly, slong k) { if (nmod_poly_is_zero(poly)) { nmod_poly_zero(res); return; } nmod_poly_fit_length(res, poly->length + k); _nmod_poly_shift_left(res->coeffs, poly->coeffs, poly->length, k); res->length = poly->length + k; } void _nmod_poly_shift_right(mp_ptr res, mp_srcptr poly, slong len, slong k) { flint_mpn_copyi(res, poly + k, len); } void nmod_poly_shift_right(nmod_poly_t res, const nmod_poly_t poly, slong k) { if (k >= poly->length) /* shift all coeffs out */ res->length = 0; else { const slong len = poly->length - k; nmod_poly_fit_length(res, len); _nmod_poly_shift_right(res->coeffs, poly->coeffs, len, k); res->length = len; } } flint-3.1.3/src/nmod_poly/sin_series.c000066400000000000000000000033001461254215100177250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_sin_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) { mp_ptr t, u; t = _nmod_vec_init(n); u = _nmod_vec_init(n); /* sin(x) = 2*tan(x/2)/(1+tan(x/2)^2) */ _nmod_vec_scalar_mul_nmod(u, h, n, n_invmod(2, mod.n), mod); _nmod_poly_tan_series(t, u, n, n, mod); _nmod_poly_mullow(u, t, n, t, n, n, mod); u[0] = UWORD(1); _nmod_poly_div_series(g, t, n, u, n, n, mod); _nmod_vec_add(g, g, g, n, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_sin_series(nmod_poly_t g, const nmod_poly_t h, slong n) { mp_ptr h_coeffs; slong h_len = h->length; if (h_len > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_sin_series). Constant term != 0.\n"); } if (h_len == 1 || n < 2) { nmod_poly_zero(g); return; } nmod_poly_fit_length(g, n); if (h_len < n) { h_coeffs = _nmod_vec_init(n); flint_mpn_copyi(h_coeffs, h->coeffs, h_len); flint_mpn_zero(h_coeffs + h_len, n - h_len); } else h_coeffs = h->coeffs; _nmod_poly_sin_series(g->coeffs, h_coeffs, n, h->mod); if (h_len < n) _nmod_vec_clear(h_coeffs); g->length = n; _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/sinh_series.c000066400000000000000000000034651461254215100201110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_sinh_series(mp_ptr f, mp_srcptr h, slong n, nmod_t mod) { mp_ptr g = _nmod_vec_init(n); _nmod_poly_exp_expinv_series(f, g, h, n, n, mod); _nmod_vec_sub(f, f, g, n, mod); _nmod_vec_scalar_mul_nmod(f, f, n, n_invmod(UWORD(2), mod.n), mod); _nmod_vec_clear(g); } void nmod_poly_sinh_series(nmod_poly_t g, const nmod_poly_t h, slong n) { mp_ptr g_coeffs, h_coeffs; nmod_poly_t t1; slong h_len; h_len = h->length; if (h_len > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_sinh_series). Constant term != 0.\n"); } if (h_len == 1 || n < 2) { nmod_poly_zero(g); return; } if (h_len < n) { h_coeffs = _nmod_vec_init(n); flint_mpn_copyi(h_coeffs, h->coeffs, h_len); flint_mpn_zero(h_coeffs + h_len, n - h_len); } else h_coeffs = h->coeffs; if (h == g && h_len >= n) { nmod_poly_init2(t1, h->mod.n, n); g_coeffs = t1->coeffs; } else { nmod_poly_fit_length(g, n); g_coeffs = g->coeffs; } _nmod_poly_sinh_series(g_coeffs, h_coeffs, n, h->mod); if (h == g && h_len >= n) { nmod_poly_swap(g, t1); nmod_poly_clear(t1); } g->length = n; if (h_len < n) _nmod_vec_clear(h_coeffs); _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/sqrt.c000066400000000000000000000046701461254215100165660ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" static inline int _nmod_poly_sqrt_2(mp_ptr s, mp_srcptr p, slong len) { slong i; for (i = 1; i < len; i += 2) if (p[i] != 0) return 0; for (i = 0; i < len; i += 2) s[i / 2] = p[i]; return 1; } int _nmod_poly_sqrt(mp_ptr s, mp_srcptr p, slong len, nmod_t mod) { slong slen; int result; mp_ptr t; mp_limb_t c, d; if (len % 2 == 0) return len == 0; if (mod.n == 2) return _nmod_poly_sqrt_2(s, p, len); /* valuation must be even, and then can be reduced to 0 */ while (p[0] == 0) { if (p[1] != 0) return 0; s[0] = 0; p += 2; len -= 2; s++; } c = d = p[0]; if (c != 1) { c = n_sqrtmod(c, mod.n); if (c == 0) return 0; } if (len == 1) { s[0] = c; return 1; } slen = len / 2 + 1; t = _nmod_vec_init(len); if (c == 1) _nmod_poly_sqrt_series(s, p, slen, slen, mod); else { _nmod_vec_scalar_mul_nmod(t, p, slen, n_invmod(d, mod.n), mod); _nmod_poly_sqrt_series(s, t, slen, slen, mod); } if (c != 1) _nmod_vec_scalar_mul_nmod(s, s, slen, c, mod); _nmod_poly_mulhigh(t, s, slen, s, slen, slen, mod); result = _nmod_vec_equal(t + slen, p + slen, len - slen); _nmod_vec_clear(t); return result; } int nmod_poly_sqrt(nmod_poly_t b, const nmod_poly_t a) { slong blen, len = a->length; int result; if (len % 2 == 0) { nmod_poly_zero(b); return len == 0; } if (b == a) { nmod_poly_t tmp; nmod_poly_init_preinv(tmp, a->mod.n, a->mod.ninv); result = nmod_poly_sqrt(tmp, a); nmod_poly_swap(b, tmp); nmod_poly_clear(tmp); return result; } blen = len / 2 + 1; nmod_poly_fit_length(b, blen); b->length = blen; result = _nmod_poly_sqrt(b->coeffs, a->coeffs, len, a->mod); if (!result) b->length = 0; return result; } flint-3.1.3/src/nmod_poly/sqrt_series.c000066400000000000000000000024761461254215100201420ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_sqrt_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_sqrt_series(g, h, hlen, n, ctx)); } void nmod_poly_sqrt_series(nmod_poly_t res, const nmod_poly_t h, slong len) { slong hlen; hlen = h->length; if (hlen == 0 || len == 0) { nmod_poly_zero(res); return; } if (hlen == 1) len = 1; if (res == h) { nmod_poly_t t; nmod_poly_init_preinv(t, h->mod.n, h->mod.ninv); nmod_poly_sqrt_series(t, h, len); nmod_poly_swap(res, t); nmod_poly_clear(t); } else { nmod_poly_fit_length(res, len); _nmod_poly_sqrt_series(res->coeffs, h->coeffs, h->length, len, h->mod); _nmod_poly_set_length(res, len); _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/sub.c000066400000000000000000000026621461254215100163650ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden. Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_sub(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { slong i, min = FLINT_MIN(len1, len2); _nmod_vec_sub(res, poly1, poly2, min, mod); if (poly1 != res) /* Copy any remaining coefficients from poly1 */ for (i = min; i < len1; i++) res[i] = poly1[i]; /* Careful, it is *always* necessary to negate coeffs from poly2, even if this is already res. */ for (i = min; i < len2; i++) res[i] = nmod_neg(poly2[i], mod); } void nmod_poly_sub(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { slong max = FLINT_MAX(poly1->length, poly2->length); nmod_poly_fit_length(res, max); _nmod_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, poly1->mod); res->length = max; _nmod_poly_normalise(res); /* there may have been cancellation */ } flint-3.1.3/src/nmod_poly/sub_series.c000066400000000000000000000017711461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" void nmod_poly_sub_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n) { slong len1, len2, max = FLINT_MAX(poly1->length, poly2->length); if (n < 0) n = 0; max = FLINT_MIN(max, n); len1 = FLINT_MIN(poly1->length, max); len2 = FLINT_MIN(poly2->length, max); nmod_poly_fit_length(res, max); _nmod_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); _nmod_poly_set_length(res, max); _nmod_poly_normalise(res); } flint-3.1.3/src/nmod_poly/sub_ui.c000066400000000000000000000020161461254215100170530ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" void nmod_poly_sub_ui(nmod_poly_t res, const nmod_poly_t poly, ulong c) { if (c >= poly->mod.n) NMOD_RED(c, c, poly->mod); if (poly->length == 0) { if (c == 0) nmod_poly_zero(res); else { nmod_poly_fit_length(res, 1); nmod_poly_set_coeff_ui(res, 0, poly->mod.n - c); _nmod_poly_set_length(res, 1); } } else { nmod_poly_set(res, poly); nmod_poly_set_coeff_ui(res, 0, nmod_sub(res->coeffs[0], c, poly->mod)); _nmod_poly_normalise(res); } } flint-3.1.3/src/nmod_poly/tan_series.c000066400000000000000000000021501461254215100177200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "gr_poly.h" void _nmod_poly_tan_series(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_tan_series(g, h, hlen, n, ctx)); } void nmod_poly_tan_series(nmod_poly_t g, const nmod_poly_t h, slong n) { slong hlen = h->length; if (hlen > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_tan_series). Constant term != 0.\n"); } if (hlen <= 1 || n <= 1) { nmod_poly_zero(g); return; } nmod_poly_fit_length(g, n); _nmod_poly_tan_series(g->coeffs, h->coeffs, hlen, n, h->mod); _nmod_poly_set_length(g, n); _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/tanh_series.c000066400000000000000000000031031461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_tanh_series(mp_ptr f, mp_srcptr h, slong n, nmod_t mod) { mp_ptr t, u; t = _nmod_vec_init(n); u = _nmod_vec_init(n); _nmod_vec_add(t, h, h, n, mod); _nmod_poly_exp_series(u, t, n, n, mod); _nmod_vec_set(t, u, n); t[0] = UWORD(0); u[0] = UWORD(2); _nmod_poly_div_series(f, t, n, u, n, n, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_tanh_series(nmod_poly_t g, const nmod_poly_t h, slong n) { mp_ptr h_coeffs; slong h_len = h->length; if (h_len > 0 && h->coeffs[0] != UWORD(0)) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_tanh_series). Constant term != 0.\n"); } if (h_len == 1 || n < 2) { nmod_poly_zero(g); return; } nmod_poly_fit_length(g, n); if (h_len < n) { h_coeffs = _nmod_vec_init(n); flint_mpn_copyi(h_coeffs, h->coeffs, h_len); flint_mpn_zero(h_coeffs + h_len, n - h_len); } else h_coeffs = h->coeffs; _nmod_poly_tanh_series(g->coeffs, h_coeffs, n, h->mod); if (h_len < n) _nmod_vec_clear(h_coeffs); g->length = n; _nmod_poly_normalise(g); } flint-3.1.3/src/nmod_poly/taylor_shift.c000066400000000000000000000063471461254215100203070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_taylor_shift(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod) { if (len < 100 || len > mod.n) _nmod_poly_taylor_shift_horner(poly, c, len, mod); else if ((c == 1 || c == mod.n - 1) && len < 1000) _nmod_poly_taylor_shift_horner(poly, c, len, mod); else _nmod_poly_taylor_shift_convolution(poly, c, len, mod); } void nmod_poly_taylor_shift(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c) { if (f != g) nmod_poly_set(g, f); _nmod_poly_taylor_shift(g->coeffs, c, g->length, g->mod); } void _nmod_poly_taylor_shift_convolution(mp_ptr p, mp_limb_t c, slong len, nmod_t mod) { slong i, n = len - 1; mp_limb_t f, d; mp_ptr t, u; if (c == 0 || len <= 1) return; t = _nmod_vec_init(len); u = _nmod_vec_init(len); f = 1; for (i = 2; i <= n; i++) { f = n_mulmod2_preinv(f, i, mod.n, mod.ninv); p[i] = n_mulmod2_preinv(p[i], f, mod.n, mod.ninv); } _nmod_poly_reverse(p, p, len, len); t[n] = 1; for (i = n; i > 0; i--) t[i - 1] = n_mulmod2_preinv(t[i], i, mod.n, mod.ninv); if (c == mod.n - 1) { for (i = 1; i <= n; i += 2) t[i] = nmod_neg(t[i], mod); } else if (c != 1) { d = c; for (i = 1; i <= n; i++) { t[i] = n_mulmod2_preinv(t[i], d, mod.n, mod.ninv); d = n_mulmod2_preinv(d, c, mod.n, mod.ninv); } } _nmod_poly_mullow(u, p, len, t, len, len, mod); f = n_mulmod2_preinv(f, f, mod.n, mod.ninv); f = n_invmod(f, mod.n); for (i = n; i >= 0; i--) { p[i] = n_mulmod2_preinv(u[n - i], f, mod.n, mod.ninv); f = n_mulmod2_preinv(f, (i == 0) ? 1 : i, mod.n, mod.ninv); } _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_taylor_shift_convolution(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c) { if (f != g) nmod_poly_set(g, f); _nmod_poly_taylor_shift_convolution(g->coeffs, c, g->length, g->mod); } void _nmod_poly_taylor_shift_horner(mp_ptr poly, mp_limb_t c, slong n, nmod_t mod) { slong i, j; if (c == 1) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) poly[j] = nmod_add(poly[j], poly[j + 1], mod); } else if (c == mod.n - 1) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) poly[j] = nmod_sub(poly[j], poly[j + 1], mod); } else if (c != 0) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) NMOD_ADDMUL(poly[j], poly[j + 1], c, mod); } } void nmod_poly_taylor_shift_horner(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c) { if (f != g) nmod_poly_set(g, f); _nmod_poly_taylor_shift_horner(g->coeffs, c, g->length, g->mod); } flint-3.1.3/src/nmod_poly/test/000077500000000000000000000000001461254215100164015ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly/test/main.c000066400000000000000000000225031461254215100174730ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-add_series.c" #include "t-asinh_series.c" #include "t-asin_series.c" #include "t-atanh_series.c" #include "t-atan_series.c" #include "t-berlekamp_massey.c" #include "t-bit_pack.c" #include "t-compose.c" #include "t-compose_horner.c" #include "t-compose_mod_brent_kung.c" #include "t-compose_mod_brent_kung_precomp_preinv.c" #include "t-compose_mod_brent_kung_precomp_preinv_threaded.c" #include "t-compose_mod_brent_kung_preinv.c" #include "t-compose_mod_brent_kung_vec_preinv.c" #include "t-compose_mod_brent_kung_vec_preinv_threaded.c" #include "t-compose_mod.c" #include "t-compose_mod_horner.c" #include "t-compose_series.c" #include "t-conway.c" #include "t-cosh_series.c" #include "t-cos_series.c" #include "t-deflate.c" #include "t-derivative.c" #include "t-discriminant.c" #include "t-div.c" #include "t-divexact.c" #include "t-divides.c" #include "t-divides_classical.c" #include "t-div_newton_n_preinv.c" #include "t-divrem_basecase.c" #include "t-divrem.c" #include "t-divrem_newton_n_preinv.c" #include "t-div_root.c" #include "t-div_series_basecase.c" #include "t-div_series.c" #include "t-equal_trunc.c" #include "t-evaluate_mat_horner.c" #include "t-evaluate_mat_paterson_stockmeyer.c" #include "t-evaluate_nmod.c" #include "t-evaluate_nmod_vec_fast.c" #include "t-exp_series.c" #include "t-find_distinct_nonzero_roots.c" #include "t-fread_print.c" #include "t-gcd.c" #include "t-gcd_euclidean.c" #include "t-gcd_hgcd.c" #include "t-gcdinv.c" #include "t-get_set_coeff_ui.c" #include "t-get_set_str.c" #include "t-hgcd.c" #include "t-inflate.c" #include "t-init_realloc_clear.c" #include "t-integral.c" #include "t-interpolate_nmod_vec_barycentric.c" #include "t-interpolate_nmod_vec.c" #include "t-interpolate_nmod_vec_fast.c" #include "t-interpolate_nmod_vec_newton.c" #include "t-invmod.c" #include "t-inv_series_basecase.c" #include "t-inv_series_newton.c" #include "t-invsqrt_series.c" #include "t-log_series.c" #include "t-make_monic.c" #include "t-mul.c" #include "t-mul_classical.c" #include "t-mulhigh.c" #include "t-mulhigh_classical.c" #include "t-mul_KS2.c" #include "t-mul_KS4.c" #include "t-mul_KS.c" #include "t-mullow.c" #include "t-mullow_classical.c" #include "t-mullow_KS.c" #include "t-mulmod.c" #include "t-mulmod_preinv.c" #include "t-multi_crt.c" #include "t-neg.c" #include "t-pow_binexp.c" #include "t-pow.c" #include "t-powers_mod_bsgs.c" #include "t-powers_mod_naive.c" #include "t-power_sums.c" #include "t-power_sums_naive.c" #include "t-power_sums_schoenhage.c" #include "t-powmod_fmpz_binexp.c" #include "t-powmod_fmpz_binexp_preinv.c" #include "t-powmod_ui_binexp.c" #include "t-powmod_ui_binexp_preinv.c" #include "t-powmod_x_fmpz_preinv.c" #include "t-powmod_x_ui_preinv.c" #include "t-pow_trunc_binexp.c" #include "t-pow_trunc.c" #include "t-product_roots_nmod_vec.c" #include "t-rem.c" #include "t-resultant.c" #include "t-resultant_euclidean.c" #include "t-resultant_hgcd.c" #include "t-reverse.c" #include "t-revert_series.c" #include "t-scalar_addmul_nmod.c" #include "t-scalar_mul_nmod.c" #include "t-set_trunc.c" #include "t-shift_left_right.c" #include "t-sinh_series.c" #include "t-sin_series.c" #include "t-sqrt.c" #include "t-sqrt_series.c" #include "t-sub.c" #include "t-sub_series.c" #include "t-tanh_series.c" #include "t-tan_series.c" #include "t-taylor_shift.c" #include "t-taylor_shift_convolution.c" #include "t-taylor_shift_horner.c" #include "t-xgcd.c" #include "t-xgcd_euclidean.c" #include "t-xgcd_hgcd.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_poly_add), TEST_FUNCTION(nmod_poly_add_series), TEST_FUNCTION(nmod_poly_asinh_series), TEST_FUNCTION(nmod_poly_asin_series), TEST_FUNCTION(nmod_poly_atanh_series), TEST_FUNCTION(nmod_poly_atan_series), TEST_FUNCTION(nmod_poly_berlekamp_massey), TEST_FUNCTION(nmod_poly_bit_pack), TEST_FUNCTION(nmod_poly_compose), TEST_FUNCTION(nmod_poly_compose_horner), TEST_FUNCTION(nmod_poly_compose_mod_brent_kung), TEST_FUNCTION(nmod_poly_compose_mod_brent_kung_precomp_preinv), TEST_FUNCTION(nmod_poly_compose_mod_brent_kung_precomp_preinv_threaded), TEST_FUNCTION(nmod_poly_compose_mod_brent_kung_preinv), TEST_FUNCTION(nmod_poly_compose_mod_brent_kung_vec_preinv), TEST_FUNCTION(nmod_poly_compose_mod_brent_kung_vec_preinv_threaded), TEST_FUNCTION(nmod_poly_compose_mod), TEST_FUNCTION(nmod_poly_compose_mod_horner), TEST_FUNCTION(nmod_poly_compose_series), TEST_FUNCTION(_nmod_poly_conway), TEST_FUNCTION(_nmod_poly_conway_rand), TEST_FUNCTION(nmod_poly_cosh_series), TEST_FUNCTION(nmod_poly_cos_series), TEST_FUNCTION(nmod_poly_deflate), TEST_FUNCTION(nmod_poly_derivative), TEST_FUNCTION(nmod_poly_discriminant), TEST_FUNCTION(nmod_poly_div), TEST_FUNCTION(nmod_poly_divexact), TEST_FUNCTION(nmod_poly_divides), TEST_FUNCTION(nmod_poly_divides_classical), TEST_FUNCTION(nmod_poly_div_newton_n_preinv), TEST_FUNCTION(nmod_poly_divrem_basecase), TEST_FUNCTION(nmod_poly_divrem), TEST_FUNCTION(nmod_poly_divrem_newton_n_preinv), TEST_FUNCTION(nmod_poly_div_root), TEST_FUNCTION(nmod_poly_div_series_basecase), TEST_FUNCTION(nmod_poly_div_series), TEST_FUNCTION(nmod_poly_equal_trunc), TEST_FUNCTION(nmod_poly_evaluate_mat_horner), TEST_FUNCTION(nmod_poly_evaluate_mat_paterson_stockmeyer), TEST_FUNCTION(nmod_poly_evaluate_nmod), TEST_FUNCTION(nmod_poly_evaluate_nmod_vec_fast), TEST_FUNCTION(nmod_poly_exp_series), TEST_FUNCTION(nmod_poly_find_distinct_nonzero_roots), TEST_FUNCTION(nmod_poly_fread_print), TEST_FUNCTION(nmod_poly_gcd), TEST_FUNCTION(nmod_poly_gcd_euclidean), TEST_FUNCTION(nmod_poly_gcd_hgcd), TEST_FUNCTION(nmod_poly_gcdinv), TEST_FUNCTION(nmod_poly_get_set_coeff_ui), TEST_FUNCTION(nmod_poly_get_set_str), TEST_FUNCTION(nmod_poly_hgcd), TEST_FUNCTION(nmod_poly_inflate), TEST_FUNCTION(nmod_poly_init_realloc_clear), TEST_FUNCTION(nmod_poly_integral), TEST_FUNCTION(nmod_poly_interpolate_nmod_vec_barycentric), TEST_FUNCTION(nmod_poly_interpolate_nmod_vec), TEST_FUNCTION(nmod_poly_interpolate_nmod_vec_fast), TEST_FUNCTION(nmod_poly_interpolate_nmod_vec_newton), TEST_FUNCTION(nmod_poly_invmod), TEST_FUNCTION(nmod_poly_inv_series_basecase), TEST_FUNCTION(nmod_poly_inv_series_newton), TEST_FUNCTION(nmod_poly_invsqrt_series), TEST_FUNCTION(nmod_poly_log_series), TEST_FUNCTION(nmod_poly_make_monic), TEST_FUNCTION(nmod_poly_mul), TEST_FUNCTION(nmod_poly_mul_classical), TEST_FUNCTION(nmod_poly_mulhigh), TEST_FUNCTION(nmod_poly_mulhigh_classical), TEST_FUNCTION(nmod_poly_mul_KS2), TEST_FUNCTION(nmod_poly_mul_KS4), TEST_FUNCTION(nmod_poly_mul_KS), TEST_FUNCTION(nmod_poly_mullow), TEST_FUNCTION(nmod_poly_mullow_classical), TEST_FUNCTION(nmod_poly_mullow_KS), TEST_FUNCTION(nmod_poly_mulmod), TEST_FUNCTION(nmod_poly_mulmod_preinv), TEST_FUNCTION(nmod_poly_multi_crt), TEST_FUNCTION(nmod_poly_neg), TEST_FUNCTION(nmod_poly_pow_binexp), TEST_FUNCTION(nmod_poly_pow), TEST_FUNCTION(nmod_poly_powers_mod_bsgs), TEST_FUNCTION(nmod_poly_powers_mod_naive), TEST_FUNCTION(nmod_poly_power_sums), TEST_FUNCTION(nmod_poly_power_sums_naive), TEST_FUNCTION(nmod_poly_power_sums_schoenhage), TEST_FUNCTION(nmod_poly_powmod_fmpz_binexp), TEST_FUNCTION(nmod_poly_powmod_fmpz_binexp_preinv), TEST_FUNCTION(nmod_poly_powmod_ui_binexp), TEST_FUNCTION(nmod_poly_powmod_ui_binexp_preinv), TEST_FUNCTION(nmod_poly_powmod_x_fmpz_preinv), TEST_FUNCTION(nmod_poly_powmod_x_ui_preinv), TEST_FUNCTION(nmod_poly_pow_trunc_binexp), TEST_FUNCTION(nmod_poly_pow_trunc), TEST_FUNCTION(nmod_poly_product_roots_nmod_vec), TEST_FUNCTION(nmod_poly_rem), TEST_FUNCTION(nmod_poly_resultant), TEST_FUNCTION(nmod_poly_resultant_euclidean), TEST_FUNCTION(nmod_poly_resultant_hgcd), TEST_FUNCTION(nmod_poly_reverse), TEST_FUNCTION(nmod_poly_revert_series), TEST_FUNCTION(nmod_poly_scalar_addmul_nmod), TEST_FUNCTION(nmod_poly_scalar_mul_nmod), TEST_FUNCTION(nmod_poly_set_trunc), TEST_FUNCTION(nmod_poly_shift_left_right), TEST_FUNCTION(nmod_poly_sinh_series), TEST_FUNCTION(nmod_poly_sin_series), TEST_FUNCTION(nmod_poly_sqrt), TEST_FUNCTION(nmod_poly_sqrt_series), TEST_FUNCTION(nmod_poly_sub), TEST_FUNCTION(nmod_poly_sub_series), TEST_FUNCTION(nmod_poly_tanh_series), TEST_FUNCTION(nmod_poly_tan_series), TEST_FUNCTION(nmod_poly_taylor_shift), TEST_FUNCTION(nmod_poly_taylor_shift_convolution), TEST_FUNCTION(nmod_poly_taylor_shift_horner), TEST_FUNCTION(nmod_poly_xgcd), TEST_FUNCTION(nmod_poly_xgcd_euclidean), TEST_FUNCTION(nmod_poly_xgcd_hgcd) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod_poly/test/t-add.c000066400000000000000000000044221461254215100175400ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_add, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_add(c, a, b); nmod_poly_add(a, a, b); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_add(c, a, b); nmod_poly_add(b, a, b); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-add_series.c000066400000000000000000000072301461254215100211120ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_add_series, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { ulong p; nmod_poly_t a, b, c; slong n; p = n_randtest(state); if (p == 0) p++; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100); nmod_poly_add_series(c, a, b, n); nmod_poly_add_series(a, a, b, n); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { ulong p; nmod_poly_t a, b, c; slong n; p = n_randtest(state); if (p == 0) p++; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100); nmod_poly_add_series(c, a, b, n); nmod_poly_add_series(b, a, b, n); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check truncate(a + b, n) = add_series(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { ulong p; nmod_poly_t a, b, c, d; slong n; p = n_randtest(state); if (p == 0) p++; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); nmod_poly_init(d, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100); nmod_poly_add(c, a, b); nmod_poly_truncate(c, n); nmod_poly_add_series(d, a, b, n); result = (nmod_poly_equal(d, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-asin_series.c000066400000000000000000000057401461254215100213200ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_asin_series, state) { int i, result = 1; /* Check asin(A) = atan(A/sqrt(1-A^2)) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B, asinA, atanB; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_init(asinA, mod); nmod_poly_init(atanB, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_mullow(B, A, A, n); nmod_poly_neg(B, B); nmod_poly_set_coeff_ui(B, 0, UWORD(1)); nmod_poly_invsqrt_series(B, B, n); nmod_poly_mullow(B, A, B, n); nmod_poly_asin_series(asinA, A, n); nmod_poly_atan_series(atanB, B, n); result = nmod_poly_equal(asinA, atanB); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("asin(A): "); nmod_poly_print(asinA), flint_printf("\n\n"); flint_printf("atan(B): "); nmod_poly_print(atanB), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(asinA); nmod_poly_clear(atanB); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_asin_series(B, A, n); nmod_poly_asin_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-asinh_series.c000066400000000000000000000057301461254215100214670ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_asinh_series, state) { int i, result = 1; /* Check asinh(A) = atanh(A/sqrt(1+A^2)) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B, asinhA, atanhB; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_init(asinhA, mod); nmod_poly_init(atanhB, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_mullow(B, A, A, n); nmod_poly_set_coeff_ui(B, 0, UWORD(1)); nmod_poly_invsqrt_series(B, B, n); nmod_poly_mullow(B, A, B, n); nmod_poly_asinh_series(asinhA, A, n); nmod_poly_atanh_series(atanhB, B, n); result = nmod_poly_equal(asinhA, atanhB); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("asinh(A): "); nmod_poly_print(asinhA), flint_printf("\n\n"); flint_printf("atanh(B): "); nmod_poly_print(atanhB), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(asinhA); nmod_poly_clear(atanhB); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_asinh_series(B, A, n); nmod_poly_asinh_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-atan_series.c000066400000000000000000000057251461254215100213140ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_atan_series, state) { int i, result = 1; /* Check 2*atan(A) = atan(2*A/(1-A^2)) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B, atanA, atanB; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_init(atanA, mod); nmod_poly_init(atanB, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_mullow(B, A, A, n); nmod_poly_neg(B, B); nmod_poly_set_coeff_ui(B, 0, UWORD(1)); nmod_poly_div_series(B, A, B, n); nmod_poly_add(B, B, B); nmod_poly_atan_series(atanA, A, n); nmod_poly_atan_series(atanB, B, n); nmod_poly_add(atanA, atanA, atanA); result = nmod_poly_equal(atanA, atanB); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("2*atan(A): "); nmod_poly_print(atanA), flint_printf("\n\n"); flint_printf("atan(B): "); nmod_poly_print(atanB), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(atanA); nmod_poly_clear(atanB); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_atan_series(B, A, n); nmod_poly_atan_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-atanh_series.c000066400000000000000000000057201461254215100214570ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_atanh_series, state) { int i, result = 1; /* Check 2*atanh(A) = atanh(2*A/(1+A^2)) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B, atanhA, atanhB; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_init(atanhA, mod); nmod_poly_init(atanhB, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_mullow(B, A, A, n); nmod_poly_set_coeff_ui(B, 0, UWORD(1)); nmod_poly_div_series(B, A, B, n); nmod_poly_add(B, B, B); nmod_poly_atanh_series(atanhA, A, n); nmod_poly_atanh_series(atanhB, B, n); nmod_poly_add(atanhA, atanhA, atanhA); result = nmod_poly_equal(atanhA, atanhB); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("2*atanh(A): "); nmod_poly_print(atanhA), flint_printf("\n\n"); flint_printf("atanh(B): "); nmod_poly_print(atanhB), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(atanhA); nmod_poly_clear(atanhB); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_atanh_series(B, A, n); nmod_poly_atanh_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-berlekamp_massey.c000066400000000000000000000134151461254215100223350ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_berlekamp_massey, state) { slong i, j, k, l; { int changed; nmod_berlekamp_massey_t B; nmod_berlekamp_massey_init(B, 101); nmod_berlekamp_massey_add_point(B, 1); nmod_berlekamp_massey_add_point(B, 1); nmod_berlekamp_massey_add_point(B, 2); nmod_berlekamp_massey_add_point(B, 3); changed = nmod_berlekamp_massey_reduce(B); if ( changed != 1 || 2 != nmod_poly_degree(nmod_berlekamp_massey_V_poly(B)) || nmod_poly_degree(nmod_berlekamp_massey_R_poly(B)) > 1) { printf("FAIL\n"); flint_printf("check fibonacci 1\n"); fflush(stdout); flint_abort(); } nmod_berlekamp_massey_add_point(B, 5); nmod_berlekamp_massey_add_point(B, 8); changed = nmod_berlekamp_massey_reduce(B); if ( changed != 0 || 2 != nmod_poly_degree(nmod_berlekamp_massey_V_poly(B)) || nmod_poly_degree(nmod_berlekamp_massey_R_poly(B)) > 1) { printf("FAIL\n"); flint_printf("check fibonacci 2\n"); fflush(stdout); flint_abort(); } nmod_berlekamp_massey_clear(B); } for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_berlekamp_massey_t B1, B2; nmod_berlekamp_massey_init(B1, 2); nmod_berlekamp_massey_init(B2, 2); for (j = 0; j < 10; j++) { mp_limb_t p; p = n_randtest_prime(state, 1); nmod_berlekamp_massey_set_prime(B1, p); nmod_berlekamp_massey_set_prime(B2, p); /* check intermediate reductions match */ for (k = 0; k < 10; k++) { nmod_berlekamp_massey_add_point(B1, n_randint(state, p)); nmod_berlekamp_massey_add_zeros(B1, n_randint(state, 5)); nmod_berlekamp_massey_add_point(B1, n_randint(state, p)); if (n_randlimb(state) & 1) { nmod_berlekamp_massey_reduce(B1); } } nmod_berlekamp_massey_add_points(B2, nmod_berlekamp_massey_points(B1), nmod_berlekamp_massey_point_count(B1)); nmod_berlekamp_massey_reduce(B2); nmod_berlekamp_massey_reduce(B1); if (!nmod_poly_equal(nmod_berlekamp_massey_V_poly(B1), nmod_berlekamp_massey_V_poly(B2))) { printf("FAIL\n"); flint_printf("check intermediate reductions match\n" "i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } /* Check berlekamp-massey does its job - 2k coefficients of u a1 a2 a(2k) --- = --- + --- + ... + ------ + ... v x x^2 x^(2k) should be sufficient to reconstruct a divisor of v */ for (k = 0; k < 15; k++) { nmod_poly_t u, v, s, q, r; nmod_poly_init(u, p); nmod_poly_init(v, p); nmod_poly_init(s, p); nmod_poly_init(q, p); nmod_poly_init(r, p); /* deg(u) < deg(v), deg(v) = k */ nmod_poly_randtest(u, state, k); nmod_poly_randtest_monic(v, state, k + 1); /* q has enough coefficients of expansion of u/v at infty */ nmod_poly_shift_left(s, u, 2*k); nmod_poly_divrem(q, r, s, v); nmod_berlekamp_massey_start_over(B1); for (l = 2*k - 1; l >= 0 ; l--) { nmod_berlekamp_massey_add_point(B1, nmod_poly_get_coeff_ui(q, l)); } nmod_berlekamp_massey_reduce(B1); nmod_poly_divrem(q, r, v, nmod_berlekamp_massey_V_poly(B1)); if (!nmod_poly_is_zero(r)) { flint_printf("check berlekamp_massey does its job\n" "i = %wd, j = %wd, k = %wd\n", i, j, k); printf("v: "); nmod_poly_print_pretty(v, "#"); printf("\n"); printf("B: "); nmod_berlekamp_massey_print(B1); printf("\n"); fflush(stdout); flint_abort(); } if ( nmod_poly_degree(nmod_berlekamp_massey_R_poly(B1)) >= nmod_poly_degree(nmod_berlekamp_massey_V_poly(B1))) { flint_printf("check discrepancy\n" "i = %wd, j = %wd, k = %wd\n", i, j, k); printf("v: "); nmod_poly_print_pretty(v, "#"); printf("\n"); printf("B: "); nmod_berlekamp_massey_print(B1); printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(u); nmod_poly_clear(v); nmod_poly_clear(s); nmod_poly_clear(q); nmod_poly_clear(r); } } nmod_berlekamp_massey_clear(B1); nmod_berlekamp_massey_clear(B2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-bit_pack.c000066400000000000000000000056101461254215100205640ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" TEST_FUNCTION_START(nmod_poly_bit_pack, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n; ulong bits; mp_ptr mpn; do { n = n_randtest_not_zero(state); } while (n == 1); bits = 2 * FLINT_BIT_COUNT(n) + n_randint(state, FLINT_BITS); nmod_poly_init(a, n); nmod_poly_init(b, n); do { nmod_poly_randtest(a, state, n_randint(state, 100)); } while (a->length == 0); mpn = flint_malloc(sizeof(mp_limb_t) * ((bits * a->length - 1) / FLINT_BITS + 1)); _nmod_poly_bit_pack(mpn, a->coeffs, a->length, bits); nmod_poly_fit_length(b, a->length); _nmod_poly_bit_unpack(b->coeffs, a->length, mpn, bits, a->mod); b->length = a->length; result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); flint_free(mpn); } for (i = 0; i < 2000 * flint_test_multiplier(); i++) { fmpz_t f; nmod_poly_t A, B; slong b; mp_limb_t n; do { n = n_randtest_not_zero(state); } while (n == 1); fmpz_init(f); nmod_poly_init(A, n); nmod_poly_init(B, n); nmod_poly_randtest(A, state, 1+n_randint(state,100)); b = FLINT_BIT_COUNT(n) + n_randint(state, FLINT_BITS); nmod_poly_bit_pack(f, A, b); nmod_poly_bit_unpack(B, f, b); if (!nmod_poly_equal(A, B)) { mpz_t zz; flint_printf("FAIL:\n"); flint_printf("INPUT: "); nmod_poly_print(A); flint_printf("\n"); mpz_init(zz); fmpz_get_mpz(zz, f); flint_printf("PACKED: "); mpz_out_str(stdout, 2, zz); flint_printf("\n"); flint_printf("OUTPUT: "); nmod_poly_print(B); flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(f); nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose.c000066400000000000000000000111771461254215100204620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose, state) { int i, result = 1; /* Check (f(x-1))(x+1) == f */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, r, xp1, xm1; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(r, n); nmod_poly_init(xm1, n); nmod_poly_init(xp1, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(xm1, 1, 1); nmod_poly_set_coeff_ui(xm1, 0, n - 1); nmod_poly_set_coeff_ui(xp1, 1, 1); nmod_poly_set_coeff_ui(xp1, 0, 1); nmod_poly_compose(r, a, xm1); nmod_poly_compose(r, r, xp1); result = nmod_poly_equal(a, r); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(r); nmod_poly_clear(xm1); nmod_poly_clear(xp1); } /* Check a(c) + b(c) = (a + b)(c) */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, r1, r2; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(r1, n); nmod_poly_init(r2, n); nmod_poly_randtest(a, state, n_randint(state, 30)); nmod_poly_randtest(b, state, n_randint(state, 30)); nmod_poly_randtest(c, state, n_randint(state, 10)); nmod_poly_compose(r1, a, c); nmod_poly_compose(r2, b, c); nmod_poly_add(r1, r1, r2); nmod_poly_add(a, a, b); nmod_poly_compose(r2, a, c); result = nmod_poly_equal(r1, r2); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(r1), flint_printf("\n\n"); nmod_poly_print(r2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(r1); nmod_poly_clear(r2); } /* Compare aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, r1; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(r1, n); nmod_poly_randtest(a, state, n_randint(state, 30)); nmod_poly_randtest(b, state, n_randint(state, 15)); nmod_poly_compose(r1, a, b); nmod_poly_compose(a, a, b); result = nmod_poly_equal(r1, a); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(r1), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r1); } /* Compare other aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, r1; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(r1, n); nmod_poly_randtest(a, state, n_randint(state, 30)); nmod_poly_randtest(b, state, n_randint(state, 15)); nmod_poly_compose(r1, a, b); nmod_poly_compose(b, a, b); result = nmod_poly_equal(r1, b); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(r1), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_horner.c000066400000000000000000000056111461254215100220330ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_horner, state) { int i, result = 1; /* Check (f(x-1))(x+1) == f */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, r, xp1, xm1; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(r, n); nmod_poly_init(xm1, n); nmod_poly_init(xp1, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(xm1, 1, 1); nmod_poly_set_coeff_ui(xm1, 0, n - 1); nmod_poly_set_coeff_ui(xp1, 1, 1); nmod_poly_set_coeff_ui(xp1, 0, 1); nmod_poly_compose_horner(r, a, xm1); nmod_poly_compose_horner(r, r, xp1); result = nmod_poly_equal(a, r); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(r); nmod_poly_clear(xm1); nmod_poly_clear(xp1); } /* Check a(c) + b(c) = (a + b)(c) */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, r1, r2; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(r1, n); nmod_poly_init(r2, n); nmod_poly_randtest(a, state, n_randint(state, 30)); nmod_poly_randtest(b, state, n_randint(state, 30)); nmod_poly_randtest(c, state, n_randint(state, 10)); nmod_poly_compose_horner(r1, a, c); nmod_poly_compose_horner(r2, b, c); nmod_poly_add(r1, r1, r2); nmod_poly_add(a, a, b); nmod_poly_compose_horner(r2, a, c); result = nmod_poly_equal(r1, r2); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(r1), flint_printf("\n\n"); nmod_poly_print(r2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(r1); nmod_poly_clear(r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_mod.c000066400000000000000000000115331461254215100213150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d, e; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_init(e, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod(d, a, b, c); nmod_poly_compose(e, a, b); nmod_poly_rem(e, e, c); if (!nmod_poly_equal(d, e)) { flint_printf("FAIL (composition):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); nmod_poly_print(e); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); nmod_poly_clear(e); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod(d, a, b, c); nmod_poly_compose_mod(a, a, b, c); if (!nmod_poly_equal(d, a)) { flint_printf("FAIL (aliasing a):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod(d, a, b, c); nmod_poly_compose_mod(b, a, b, c); if (!nmod_poly_equal(d, b)) { flint_printf("FAIL (aliasing b)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod(d, a, b, c); nmod_poly_compose_mod(c, a, b, c); if (!nmod_poly_equal(d, c)) { flint_printf("FAIL (aliasing c)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000120631461254215100235320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod_brent_kung, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d, e; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_init(e, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_compose_mod_brent_kung(d, a, b, c); nmod_poly_compose(e, a, b); nmod_poly_rem(e, e, c); if (!nmod_poly_equal(d, e)) { flint_printf("FAIL (composition):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); nmod_poly_print(e); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); nmod_poly_clear(e); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_compose_mod_brent_kung(d, a, b, c); nmod_poly_compose_mod_brent_kung(a, a, b, c); if (!nmod_poly_equal(d, a)) { flint_printf("FAIL (aliasing a):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_compose_mod_brent_kung(d, a, b, c); nmod_poly_compose_mod_brent_kung(b, a, b, c); if (!nmod_poly_equal(d, b)) { flint_printf("FAIL (aliasing b)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_compose_mod_brent_kung(d, a, b, c); nmod_poly_compose_mod_brent_kung(c, a, b, c); if (!nmod_poly_equal(d, c)) { flint_printf("FAIL (aliasing c)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000155051461254215100266460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod_brent_kung_precomp_preinv, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d, e; nmod_mat_t B; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_init(e, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_mat_init (B, n_sqrt (c->length-1)+1, c->length-1, m); nmod_poly_precompute_matrix (B, b, c, cinv); nmod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv); nmod_poly_compose(e, a, b); nmod_poly_rem(e, e, c); if (!nmod_poly_equal(d, e)) { flint_printf("FAIL (composition):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); nmod_poly_print(e); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear (B); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); nmod_poly_clear(e); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; nmod_mat_t B; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_mat_init (B, n_sqrt (c->length-1)+1, c->length-1, m); nmod_poly_precompute_matrix (B, b, c, cinv); nmod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv); nmod_poly_compose_mod_brent_kung_precomp_preinv(a, a, B, c, cinv); if (!nmod_poly_equal(d, a)) { flint_printf("FAIL (aliasing a):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear (B); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; nmod_mat_t B; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_mat_init (B, n_sqrt (c->length-1)+1, c->length-1, m); nmod_poly_precompute_matrix (B, b, c, cinv); nmod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv); nmod_poly_compose_mod_brent_kung_precomp_preinv(c, a, B, c, cinv); if (!nmod_poly_equal(d, c)) { flint_printf("FAIL (aliasing c)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear (B); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } /* Test aliasing of res and cinv */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; nmod_mat_t B; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_mat_init (B, n_sqrt (c->length-1)+1, c->length-1, m); nmod_poly_precompute_matrix (B, b, c, cinv); nmod_poly_compose_mod_brent_kung_precomp_preinv(d, a, B, c, cinv); nmod_poly_compose_mod_brent_kung_precomp_preinv(cinv, a, B, c, cinv); if (!nmod_poly_equal(d, cinv)) { flint_printf("FAIL (aliasing cinv)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear (B); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_mod_brent_kung_precomp_preinv_threaded.c000066400000000000000000000175221461254215100305070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013, 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod_brent_kung_precomp_preinv_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; /* check precomputation */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv; nmod_poly_struct * tmp; nmod_mat_t B; nmod_mat_struct * C; mp_limb_t m = n_randtest_prime(state, 0); slong j, num_threads; nmod_poly_matrix_precompute_arg_t * args1; thread_pool_handle * threads; flint_set_num_threads(1 + n_randint(state, 3)); num_threads = flint_request_threads(&threads, FLINT_DEFAULT_THREAD_LIMIT); tmp = (nmod_poly_struct *) flint_malloc(sizeof(nmod_poly_struct)*(num_threads + 1)); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); for (j = 0; j < num_threads + 1; j++) nmod_poly_init(tmp + j, m); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 20)); nmod_poly_randtest_not_zero(b, state, 1 + n_randint(state, 20)); do { nmod_poly_randtest_not_zero(c, state, 1 + n_randint(state, 20)); } while (c->length < 2); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_mat_init(B, n_sqrt (c->length - 1) + 1, c->length - 1, m); nmod_poly_precompute_matrix(B, b, c, cinv); args1 = (nmod_poly_matrix_precompute_arg_t *) flint_malloc(sizeof(nmod_poly_matrix_precompute_arg_t) *(num_threads + 1)); C = (nmod_mat_struct *) flint_malloc(sizeof(nmod_mat_struct)*(num_threads + 1)); for (j = 0; j < num_threads + 1; j++) { nmod_mat_init(C + j, n_sqrt(c->length - 1) + 1, c->length - 1, m); nmod_poly_set(tmp + j, b); nmod_poly_rem(tmp + j, tmp + j, c); if (tmp[j].length < c->length - 1) { nmod_poly_fit_length(tmp + j, c->length - 1); _nmod_vec_zero(tmp[j].coeffs + tmp[j].length, c->length - 1 - b->length); } args1[j].A = C + j; args1[j].poly1 = tmp + j; args1[j].poly2 = c; args1[j].poly2inv = cinv; } for (j = 1; j < num_threads + 1; j++) { thread_pool_wake(global_thread_pool, threads[j - 1], 0, _nmod_poly_precompute_matrix_worker, &args1[j]); } _nmod_poly_precompute_matrix_worker(&args1[0]); for (j = 1; j < num_threads + 1; j++) thread_pool_wait(global_thread_pool, threads[j - 1]); for (j = 0; j < num_threads + 1; j++) { if (!nmod_mat_equal(B, C + j)) { flint_printf("FAIL (precomputation):\n"); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("\n"); flint_printf("C[j]:\n"); nmod_mat_print_pretty(C + j); flint_printf("\n"); flint_printf("a:\n"); nmod_poly_print(a); flint_printf("\n"); flint_printf("b:\n"); nmod_poly_print(b); flint_printf("\n"); flint_printf("c:\n"); nmod_poly_print(c); flint_printf("\n"); fflush(stdout); flint_abort(); } } flint_give_back_threads(threads, num_threads); nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear (B); nmod_poly_clear(c); nmod_poly_clear(cinv); for (j = 0; j < num_threads + 1; j++) { nmod_poly_clear(tmp + j); nmod_mat_clear(C + j); } flint_free(C); flint_free(tmp); flint_free(args1); } /* check composition */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; nmod_poly_struct * res; nmod_mat_t B; mp_limb_t m = n_randtest_prime(state, 0); slong j, num_threads; nmod_poly_compose_mod_precomp_preinv_arg_t * args1; thread_pool_handle * threads; flint_set_num_threads(1 + n_randint(state, 3)); num_threads = flint_request_threads(&threads, FLINT_DEFAULT_THREAD_LIMIT); res = (nmod_poly_struct *) flint_malloc(sizeof(nmod_poly_struct)*(num_threads + 1)); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); for (j = 0; j < num_threads + 1; j++) nmod_poly_init(res + j, m); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 20)); nmod_poly_randtest_not_zero(b, state, 1 + n_randint(state, 20)); do { nmod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1); } while (c->length < 2); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_mat_init(B, n_sqrt(c->length - 1) + 1, c->length - 1, m); nmod_poly_precompute_matrix(B, b, c, cinv); nmod_poly_rem(a, a, c); nmod_poly_compose_mod(d, a, b, c); args1 = (nmod_poly_compose_mod_precomp_preinv_arg_t *) flint_malloc((num_threads + 1)* sizeof(nmod_poly_compose_mod_precomp_preinv_arg_t)); for (j = 0; j < num_threads + 1; j++) { nmod_poly_fit_length(res + j, c->length - 1); _nmod_poly_set_length(res + j, c->length - 1); flint_mpn_zero(res[j].coeffs, c->length - 1); args1[j].A = B; args1[j].res = res + j; args1[j].poly1 = a; args1[j].poly3 = c; args1[j].poly3inv = cinv; } for (j = 1; j < num_threads + 1; j++) { thread_pool_wake(global_thread_pool, threads[j - 1], 0, _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker, &args1[j]); } _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker(&args1[0]); _nmod_poly_normalise(res + 0); for (j = 1; j < num_threads + 1; j++) { thread_pool_wait(global_thread_pool, threads[j - 1]); _nmod_poly_normalise(res + j); } for (j = 0; j < num_threads + 1; j++) { if (!nmod_poly_equal(d, res + j)) { flint_printf("FAIL (composition):\n"); flint_printf("res[j]:\n"); nmod_poly_print(res + j); flint_printf("\n"); flint_printf("d:\n"); nmod_poly_print(d); flint_printf("\n"); flint_printf("a:\n"); nmod_poly_print(a); flint_printf("\n"); flint_printf("b:\n"); nmod_poly_print(b); flint_printf("\n"); flint_printf("c:\n"); nmod_poly_print(c); flint_printf("\n"); fflush(stdout); flint_abort(); } } flint_give_back_threads(threads, num_threads); nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear (B); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); for (j = 0; j < num_threads + 1; j++) nmod_poly_clear(res + j); flint_free(res); flint_free(args1); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/nmod_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000166521461254215100251250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod_brent_kung_preinv, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d, e; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_init(e, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv); nmod_poly_compose(e, a, b); nmod_poly_rem(e, e, c); if (!nmod_poly_equal(d, e)) { flint_printf("FAIL (composition):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); nmod_poly_print(e); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); nmod_poly_clear(e); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv); nmod_poly_compose_mod_brent_kung_preinv(a, a, b, c, cinv); if (!nmod_poly_equal(d, a)) { flint_printf("FAIL (aliasing a):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv); nmod_poly_compose_mod_brent_kung_preinv(b, a, b, c, cinv); if (!nmod_poly_equal(d, b)) { flint_printf("FAIL (aliasing b)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv); nmod_poly_compose_mod_brent_kung_preinv(c, a, b, c, cinv); if (!nmod_poly_equal(d, c)) { flint_printf("FAIL (aliasing c)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } /* Test aliasing of res and cinv */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, cinv, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(cinv, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_rem(a, a, c); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_poly_compose_mod_brent_kung_preinv(d, a, b, c, cinv); nmod_poly_compose_mod_brent_kung_preinv(cinv, a, b, c, cinv); if (!nmod_poly_equal(d, cinv)) { flint_printf("FAIL (aliasing cinv)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(cinv); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_mod_brent_kung_vec_preinv.c000066400000000000000000000053461461254215100257600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013, 2014 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod_brent_kung_vec_preinv, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, ainv, b, c; mp_limb_t m = n_randtest_prime(state, 0); slong j, k, l; nmod_poly_struct * pow, * res; nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(ainv, m); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(a, state, 1+n_randint(state, 20)); l= n_randint(state, 20) + 1; k= n_randint(state, l ) + 1; nmod_poly_rem(b, b, a); nmod_poly_reverse(ainv, a, a->length); nmod_poly_inv_series(ainv, ainv, a->length); pow = (nmod_poly_struct *) flint_malloc((l + k)*sizeof(nmod_poly_struct)); res = pow + l; for (j = 0; j < l; j++) { nmod_poly_init(pow + j, m); nmod_poly_randtest(pow + j, state, n_randint(state, 20) + 1); nmod_poly_rem(pow + j, pow + j, a); } for (j = 0; j < k; j++) nmod_poly_init(res + j, m); nmod_poly_compose_mod_brent_kung_vec_preinv(res, pow, l, k, b, a, ainv); for (j = 0; j < k; j++) { nmod_poly_compose_mod(c, pow + j, b, a); if (!nmod_poly_equal(res + j, c)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); nmod_poly_print(a); flint_printf("\n"); flint_printf("res:\n"); nmod_poly_print(res + j); flint_printf("\n"); flint_printf("pow:\n"); nmod_poly_print(pow + j); flint_printf("\n"); flint_printf("b:\n"); nmod_poly_print(b); flint_printf("\n"); flint_printf("c:\n"); nmod_poly_print(c); flint_printf("\n"); flint_printf("j: %wd\n", j); fflush(stdout); flint_abort(); } } nmod_poly_clear(a); nmod_poly_clear(ainv); nmod_poly_clear(b); nmod_poly_clear(c); for (j = 0; j < l; j++) nmod_poly_clear(pow + j); for (j = 0; j < k; j++) nmod_poly_clear(res + j); flint_free(pow); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000060601461254215100276120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013, 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_support.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod_brent_kung_vec_preinv_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; slong max_threads = 5; for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, ainv, b, c; mp_limb_t m = n_randtest_prime(state, 0); slong j, k, l; nmod_poly_struct * pow, * res; flint_set_num_threads(n_randint(state, max_threads) + 1); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(ainv, m); nmod_poly_randtest(b, state, 1 + n_randint(state, 200)); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 200)); l = n_randint(state, 100) + 1; k = n_randint(state, l) + 1; nmod_poly_rem(b, b, a); nmod_poly_reverse(ainv, a, a->length); nmod_poly_inv_series(ainv, ainv, a->length); pow = (nmod_poly_struct *) flint_malloc((l + k)*sizeof(nmod_poly_struct)); res = pow + l; for (j = 0; j < l; j++) { nmod_poly_init(pow + j, m); nmod_poly_randtest(pow + j, state, n_randint(state, 200) + 1); nmod_poly_rem(pow + j, pow + j, a); } for (j = 0; j < k; j++) nmod_poly_init(res + j, m); nmod_poly_compose_mod_brent_kung_vec_preinv_threaded(res, pow, l, k, b, a, ainv); for (j = 0; j < k; j++) { nmod_poly_compose_mod(c, pow + j, b, a); if (!nmod_poly_equal(res + j, c)) { flint_printf("FAIL (composition):\n"); flint_printf("a:\n"); nmod_poly_print(a); flint_printf("\n"); flint_printf("res:\n"); nmod_poly_print(res + j); flint_printf("\n"); flint_printf("pow:\n"); nmod_poly_print(pow + j); flint_printf("\n"); flint_printf("b:\n"); nmod_poly_print(b); flint_printf("\n"); flint_printf("c:\n"); nmod_poly_print(c); flint_printf("\n"); flint_printf("j: %wd\n", j); fflush(stdout); flint_abort(); } } nmod_poly_clear(a); nmod_poly_clear(ainv); nmod_poly_clear(b); nmod_poly_clear(c); for (j = 0; j < l; j++) nmod_poly_clear(pow + j); for (j = 0; j < k; j++) nmod_poly_clear(res + j); flint_free(pow); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/nmod_poly/test/t-compose_mod_horner.c000066400000000000000000000116231461254215100226720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_mod_horner, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d, e; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_init(e, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod_horner(d, a, b, c); nmod_poly_compose(e, a, b); nmod_poly_rem(e, e, c); if (!nmod_poly_equal(d, e)) { flint_printf("FAIL (composition):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); nmod_poly_print(e); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); nmod_poly_clear(e); } /* Test aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod_horner(d, a, b, c); nmod_poly_compose_mod_horner(a, a, b, c); if (!nmod_poly_equal(d, a)) { flint_printf("FAIL (aliasing a):\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Test aliasing of res and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod_horner(d, a, b, c); nmod_poly_compose_mod_horner(b, a, b, c); if (!nmod_poly_equal(d, b)) { flint_printf("FAIL (aliasing b)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Test aliasing of res and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t m = n_randtest_prime(state, 0); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); nmod_poly_init(d, m); nmod_poly_randtest(a, state, 1+n_randint(state, 20)); nmod_poly_randtest(b, state, 1+n_randint(state, 20)); nmod_poly_randtest_not_zero(c, state, 1+n_randint(state, 20)); nmod_poly_compose_mod_horner(d, a, b, c); nmod_poly_compose_mod_horner(c, a, b, c); if (!nmod_poly_equal(d, c)) { flint_printf("FAIL (aliasing c)\n"); nmod_poly_print(a); flint_printf("\n"); nmod_poly_print(b); flint_printf("\n"); nmod_poly_print(c); flint_printf("\n"); nmod_poly_print(d); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-compose_series.c000066400000000000000000000076201461254215100220320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_compose_series, state) { int i, result; /* Check aliasing of the first argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h; mp_limb_t m; slong n; m = n_randtest_prime(state, 0); nmod_poly_init(f, m); nmod_poly_init(g, m); nmod_poly_init(h, m); nmod_poly_randtest(g, state, n_randint(state, 50)); nmod_poly_randtest(h, state, n_randint(state, 30)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 40); nmod_poly_compose_series(f, g, h, n); nmod_poly_compose_series(g, g, h, n); result = (nmod_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing 1):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } /* Check aliasing of the second argument */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h; mp_limb_t m; slong n; m = n_randtest_prime(state, 0); nmod_poly_init(f, m); nmod_poly_init(g, m); nmod_poly_init(h, m); nmod_poly_randtest(g, state, n_randint(state, 50)); nmod_poly_randtest(h, state, n_randint(state, 30)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 40); nmod_poly_compose_series(f, g, h, n); nmod_poly_compose_series(h, g, h, n); result = (nmod_poly_equal(f, h)); if (!result) { flint_printf("FAIL (aliasing 2):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } /* Compare with compose */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h, s, t; mp_limb_t m; slong n; m = n_randtest_prime(state, 0); nmod_poly_init(f, m); nmod_poly_init(g, m); nmod_poly_init(h, m); nmod_poly_init(s, m); nmod_poly_init(t, m); nmod_poly_randtest(g, state, n_randint(state, 50)); nmod_poly_randtest(h, state, n_randint(state, 30)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 40); nmod_poly_compose(s, g, h); nmod_poly_truncate(s, n); nmod_poly_compose_series(f, g, h, n); result = (nmod_poly_equal(f, s)); if (!result) { flint_printf("FAIL (comparison):\n"); flint_printf("n = %wd\n", n); flint_printf("g = "), nmod_poly_print(g), flint_printf("\n\n"); flint_printf("h = "), nmod_poly_print(h), flint_printf("\n\n"); flint_printf("f = "), nmod_poly_print(f), flint_printf("\n\n"); flint_printf("s = "), nmod_poly_print(s), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(s); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-conway.c000066400000000000000000000220731461254215100203120ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "nmod_poly.h" typedef struct { ulong prime; slong deg; ulong * coeffs; } conway_polynomial_t; typedef struct { ulong prime; slong degree; } prime_degree_t; /* As the source code splits it into 7 different cases, we need to check every case against some variation against CPimport.txt by Frank Lübeck. We do this by checking every available degree of some primes for each case. We also check that some non-primes and unavailable degrees return a value indicating an error. */ TEST_FUNCTION_START(_nmod_poly_conway, state) { ulong op[500]; slong ix; /* As the source code for primes < 260 does not depend on specific cases, we here simply check that a couple entries agree with the data. */ ulong cp_2_1[] = {1,1}; ulong cp_2_42[] = {1,1,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,1,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1}; ulong cp_3_263[] = {1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; ulong cp_11_1[] = {9,1}; ulong cp_257_12[] = {3,20,148,249,173,215,225,13,2,0,0,0,1}; /* For 260 < prime < 300, we have the cases deg = 1, 2, ..., 12 */ ulong cp_263_1[] = {258,1}; ulong cp_283_2[] = {3,282,1}; ulong cp_293_3[] = {291,2,0,1}; ulong cp_293_4[] = {2,166,3,0,1}; ulong cp_277_5[] = {272,1,0,0,0,1}; ulong cp_269_6[] = {2,206,101,120,1,0,1}; ulong cp_263_7[] = {258,1,0,0,0,0,0,1}; ulong cp_271_9[] = {265,186,266,10,0,0,0,0,0,1}; ulong cp_271_10[] = {6,126,74,256,10,133,1,0,0,0,1}; ulong cp_271_11[] = {265,10,0,0,0,0,0,0,0,0,0,1}; ulong cp_281_12[] = {3,191,28,58,116,103,68,202,0,0,0,0,1}; /* For 300 <= prime < 1000, we have the cases deg = 1, 2, ..., 9 */ ulong cp_311_1[] = {294,1}; ulong cp_311_2[] = {17,310,1}; ulong cp_307_3[] = {302,7,0,1}; ulong cp_409_4[] = {21,407,12,0,1}; ulong cp_419_5[] = {417,4,0,0,0,1}; ulong cp_443_6[] = {2,41,218,298,1,0,1}; ulong cp_523_7[] = {521,13,0,0,0,0,0,1}; ulong cp_787_8[] = {2,715,26,612,5,0,0,0,1}; ulong cp_919_9[] = {912,623,410,7,0,0,0,0,0,1}; /* For 1000 <= prime < 3371, we have the cases deg = 1, ..., 7, 9. However, there are seven primes that do not have degree 7 and 9. We cover them later on in the test. */ ulong cp_1009_1[] = {998,1}; ulong cp_3359_2[] = {11,3357,1}; ulong cp_2311_3[] = {2308,3,0,1}; ulong cp_2333_4[] = {2,1591,7,0,1}; ulong cp_2293_5[] = {2291,2,0,0,0,1}; ulong cp_2287_6[] = {19,233,630,1812,0,0,1}; ulong cp_2273_7[] = {2270,20,0,0,0,0,0,1}; ulong cp_3361_9[] = {3339,3147,1704,5,0,0,0,0,0,1}; /* For 3371 <= prime < 11000, we have the cases deg = 1, 2, ..., 6 */ ulong cp_3371_1[] = {3369,1}; ulong cp_5011_2[] = {2,5010,1}; ulong cp_6679_3[] = {6672,1,0,1}; ulong cp_8191_4[] = {17,8183,3,0,1}; ulong cp_9679_5[] = {9676,8,0,0,0,1}; ulong cp_10993_6[] = {7,4015,6869,8311,0,0,1}; /* For 11000 <= prime < 65536, we have the cases deg = 1, 2, ..., 4 */ ulong cp_11003_1[] = {11001,1}; ulong cp_36109_2[] = {2,36108,1}; ulong cp_38867_3[] = {38865,2,0,1}; ulong cp_65521_4[] = {17,42121,20,0,1}; /* For 65536 <= prime < 109988, we have the case deg = 4 */ ulong cp_65537_4[] = {3,48035,7,0,1}; ulong cp_65647_4[] = {3,54892,2,0,1}; ulong cp_65651_4[] = {2,58463,2,0,1}; ulong cp_65657_4[] = {3,54810,0,0,1}; ulong cp_65677_4[] = {2,52138,3,0,1}; ulong cp_77029_4[] = {2,58146,0,0,1}; ulong cp_77137_4[] = {13,71265,4,0,1}; ulong cp_88771_4[] = {11,68103,5,0,1}; ulong cp_100069_4[] = {10,65117,2,0,1}; ulong cp_109943_4[] = {5,109939,3,0,1}; ulong cp_109961_4[] = {3,109949,0,0,1}; ulong cp_109987_4[] = {3,100525,3,0,1}; /* Expected outputs */ conway_polynomial_t cp[] = { {2, 1, cp_2_1}, {2, 42, cp_2_42}, {3, 263, cp_3_263}, {11, 1, cp_11_1}, {257, 12, cp_257_12}, {263, 1, cp_263_1}, {283, 2, cp_283_2}, {293, 3, cp_293_3}, {293, 4, cp_293_4}, {277, 5, cp_277_5}, {269, 6, cp_269_6}, {263, 7, cp_263_7}, {271, 9, cp_271_9}, {271, 10, cp_271_10}, {271, 11, cp_271_11}, {281, 12, cp_281_12}, {311, 1, cp_311_1}, {311, 2, cp_311_2}, {307, 3, cp_307_3}, {409, 4, cp_409_4}, {419, 5, cp_419_5}, {443, 6, cp_443_6}, {523, 7, cp_523_7}, {787, 8, cp_787_8}, {919, 9, cp_919_9}, {1009, 1, cp_1009_1}, {3359, 2, cp_3359_2}, {2311, 3, cp_2311_3}, {2333, 4, cp_2333_4}, {2293, 5, cp_2293_5}, {2287, 6, cp_2287_6}, {2273, 7, cp_2273_7}, {3361, 9, cp_3361_9}, {3371, 1, cp_3371_1}, {5011, 2, cp_5011_2}, {6679, 3, cp_6679_3}, {8191, 4, cp_8191_4}, {9679, 5, cp_9679_5}, {10993, 6, cp_10993_6}, {11003, 1, cp_11003_1}, {36109, 2, cp_36109_2}, {38867, 3, cp_38867_3}, {65521, 4, cp_65521_4}, {65537, 4, cp_65537_4}, {65647, 4, cp_65647_4}, {65651, 4, cp_65651_4}, {65657, 4, cp_65657_4}, {65677, 4, cp_65677_4}, {77029, 4, cp_77029_4}, {77137, 4, cp_77137_4}, {88771, 4, cp_88771_4}, {100069, 4, cp_100069_4}, {109943, 4, cp_109943_4}, {109961, 4, cp_109961_4}, {109987, 4, cp_109987_4}, }; /* Expected errors */ prime_degree_t error_list[] = { {0, 1}, {1, 1}, {2, 0}, {2, -1}, {2, 408}, {2, 410}, {2, 490}, {6, 4}, {259, 4}, {263, -1}, {263, 0}, {263, 13}, {279, 4}, {297, 4}, {307, 0}, {307, 10}, {999, 0}, {999, 10}, {999, 10}, {1013, 8}, {1013, 10}, {1031, 8}, {1031, 10}, {2689, 7}, {2689, 9}, {2797, 7}, {2797, 9}, {2833, 7}, {2833, 9}, {3019, 7}, {3019, 9}, {3163, 7}, {3163, 9}, {3209, 7}, {3209, 9}, {3331, 7}, {3331, 9}, {3367, 4}, {3371, 0}, {3371, 7}, {10993, 7}, {10997, 4}, {11003, 0}, {11003, 5}, {11117, 5}, {11121, 4}, {65521, 5}, {65521, 0}, {65527, 4}, {65541, 4}, {109981, 4}, {109987, 0}, {109989, 4}, {UWORD(1782381726837121), 4}, }; for (ix = 0; ix < sizeof(cp) / sizeof(conway_polynomial_t); ix++) { ulong prime; slong deg; ulong * coeffs; int result; prime = cp[ix].prime; deg = cp[ix].deg; coeffs = cp[ix].coeffs; result = _nmod_poly_conway(op, prime, deg); result = result && !memcmp(coeffs, op, sizeof(ulong) * (deg + 1)); if (!result) flint_throw(FLINT_TEST_FAIL, "prime = %wu\n" "degree = %wd\n" "Got: %{ulong*}\n" "Expected: %{ulong*}\n", prime, deg, op, deg + 1, coeffs, deg + 1); } for (ix = 0; ix < sizeof(error_list) / sizeof(prime_degree_t); ix++) { ulong prime; slong deg; int result; prime = error_list[ix].prime; deg = error_list[ix].degree; result = _nmod_poly_conway(op, prime, deg); if (result) flint_throw(FLINT_TEST_FAIL, "Exected return value 0 for prime = %wu and degree %wd.\n" "Got return value %d.\n", prime, deg, result); } TEST_FUNCTION_END(state); } TEST_FUNCTION_START(_nmod_poly_conway_rand, state) { slong ix; int result; ulong op[500]; for (ix = 0; ix < 10000 * flint_test_multiplier(); ix++) { ulong prime; slong degree; /* Test all primes and degrees */ prime = _nmod_poly_conway_rand(°ree, state, 0); result = _nmod_poly_conway(op, prime, degree); if (!result) flint_throw(FLINT_TEST_FAIL, "Prime %wu and degree %wd not present in database.\n", prime, degree); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-cos_series.c000066400000000000000000000060621461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_cos_series, state) { int i, result = 1; /* Check 1-cos(A)^2 = sin(A)^2 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, cosA, sinA, B, C, one; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(cosA, mod); nmod_poly_init(sinA, mod); nmod_poly_init(B, mod); nmod_poly_init(C, mod); nmod_poly_init(one, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_cos_series(cosA, A, n); nmod_poly_sin_series(sinA, A, n); nmod_poly_mullow(B, cosA, cosA, n); nmod_poly_set_coeff_ui(one, 0, UWORD(1)); nmod_poly_sub(B, one, B); nmod_poly_mullow(C, sinA, sinA, n); result = nmod_poly_equal(B, C); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("cos(A): "); nmod_poly_print(cosA), flint_printf("\n\n"); flint_printf("1-cos(A)^2: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("sin(A)^2: "); nmod_poly_print(C), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(cosA); nmod_poly_clear(sinA); nmod_poly_clear(B); nmod_poly_clear(C); nmod_poly_clear(one); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_cos_series(B, A, n); nmod_poly_cos_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-cosh_series.c000066400000000000000000000061111461254215100213130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_cosh_series, state) { int i, result = 1; /* Check cosh(A)^2-1 = sinh(A)^2 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, coshA, sinhA, B, C, one; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(coshA, mod); nmod_poly_init(sinhA, mod); nmod_poly_init(B, mod); nmod_poly_init(C, mod); nmod_poly_init(one, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_cosh_series(coshA, A, n); nmod_poly_sinh_series(sinhA, A, n); nmod_poly_mullow(B, coshA, coshA, n); nmod_poly_set_coeff_ui(one, 0, UWORD(1)); nmod_poly_sub(B, B, one); nmod_poly_mullow(C, sinhA, sinhA, n); result = nmod_poly_equal(B, C); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("cosh(A): "); nmod_poly_print(coshA), flint_printf("\n\n"); flint_printf("cosh(A)^2-1: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("sinh(A)^2: "); nmod_poly_print(C), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(coshA); nmod_poly_clear(sinhA); nmod_poly_clear(B); nmod_poly_clear(C); nmod_poly_clear(one); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_cosh_series(B, A, n); nmod_poly_cosh_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-deflate.c000066400000000000000000000062301461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_deflate, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { nmod_poly_t poly1, poly2, poly3; mp_limb_t modulus; ulong infl1, infl, deflation; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly1, modulus); nmod_poly_init(poly2, modulus); nmod_poly_init(poly3, modulus); nmod_poly_randtest(poly1, state, n_randint(state, 15)); if (nmod_poly_length(poly1) <= 1) { if (nmod_poly_deflation(poly1) != nmod_poly_length(poly1)) { flint_printf("FAIL: wrong deflation for constant polynomial\n"); fflush(stdout); flint_abort(); } nmod_poly_deflate(poly2, poly1, n_randint(state, 5) + 1); if (!nmod_poly_equal(poly2, poly1)) { flint_printf("FAIL: constant polynomial changed on deflation\n"); fflush(stdout); flint_abort(); } } else { infl = n_randint(state, 13) + 1; infl1 = nmod_poly_deflation(poly1); nmod_poly_inflate(poly2, poly1, infl); deflation = nmod_poly_deflation(poly2); if (deflation != infl * infl1) { flint_printf("FAIL: deflation = %wu, inflation: %wu, %wu\n", deflation, infl, infl1); flint_printf("poly1:\n"); nmod_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); nmod_poly_print(poly2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_deflate(poly3, poly2, infl); if (!nmod_poly_equal(poly3, poly1)) { flint_printf("FAIL: deflation = %wu, inflation: %wu, %wu\n", deflation, infl, infl1); flint_printf("Deflated polynomial not equal to input:\n"); flint_printf("poly1:\n"); nmod_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); nmod_poly_print(poly2); flint_printf("\n\n"); flint_printf("poly3:\n"); nmod_poly_print(poly2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_deflate(poly2, poly2, infl); if (!nmod_poly_equal(poly3, poly2)) { flint_printf("FAIL: aliasing\n"); fflush(stdout); flint_abort(); } } nmod_poly_clear(poly1); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-derivative.c000066400000000000000000000047341461254215100211600ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" TEST_FUNCTION_START(nmod_poly_derivative, state) { int i, j, result = 1; fmpz_t t; fmpz_init(t); /* Check derivative by hand */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_derivative(b, a); if (a->length <= 1) result = (b->length == 0); else { for (j = 1; j < a->length; j++) { fmpz_set_ui(t, nmod_poly_get_coeff_ui(a, j)); fmpz_mul_ui(t, t, j); fmpz_mod_ui(t, t, n); result &= (fmpz_get_ui(t) == nmod_poly_get_coeff_ui(b, j - 1)); } } if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } fmpz_clear(t); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_derivative(b, a); nmod_poly_derivative(a, a); result = nmod_poly_equal(a, b); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-discriminant.c000066400000000000000000000053561461254215100215030ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_discriminant, state) { int i, result; /* Check disc(fg) == disc(f) * disc(g) * res(f, g)^2 */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h; mp_limb_t x, y, z, r; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_init(h, n); do { nmod_poly_randtest(f, state, n_randint(state, 200)); } while (f->length < 2); do { nmod_poly_randtest(g, state, n_randint(state, 200)); } while (g->length < 2); y = nmod_poly_discriminant(f); z = nmod_poly_discriminant(g); y = nmod_mul(y, z, f->mod); r = nmod_poly_resultant(f, g); r = nmod_mul(r, r, f->mod); y = nmod_mul(y, r, f->mod); nmod_poly_mul(h, f, g); x = nmod_poly_discriminant(h); result = (x == y); if (!result) { flint_printf("FAIL (disc(fg) == res(f, g)^2 * disc(f) * disc(g):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); nmod_poly_print(h), flint_printf("\n\n"); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("z = %wd\n", z); flint_printf("n = %wu\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } /* Check disc(f) == 0 for length < 2 */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t f; mp_limb_t y; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_randtest(f, state, 1); y = nmod_poly_discriminant(f); result = (y == 0); if (!result) { flint_printf("FAIL disc(f) == 0 for len f < 2:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("y = %wu\n", y); fflush(stdout); flint_abort(); } nmod_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-div.c000066400000000000000000000073051461254215100175750ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_div, state) { int i, result; /* Check result of div against divrem */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r, q2; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(q2, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_divrem(q, r, a, b); nmod_poly_div(q2, a, b); result = (nmod_poly_equal(q, q2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(q2), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(q2); } /* Check aliasing of a and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_div(q, a, b); nmod_poly_div(a, a, b); result = (nmod_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } /* Check aliasing of b and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_div(q, a, b); nmod_poly_div(b, a, b); result = (nmod_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-div_newton_n_preinv.c000066400000000000000000000137771461254215100231010ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_div_newton_n_preinv, state) { int i, result; /* Check result of divrem */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r, test; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(test, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_div_newton_n_preinv(q, a, b, binv); nmod_poly_divrem (test, r, a, b); result = (nmod_poly_equal(q, test)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(test), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(test); } /* Check aliasing of a and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_div_newton_n_preinv(q, a, b, binv); nmod_poly_div_newton_n_preinv(a, a, b, binv); result = (nmod_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); } /* Check aliasing of b and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_div_newton_n_preinv(q, a, b, binv); nmod_poly_div_newton_n_preinv(b, a, b, binv); result = (nmod_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); } /* Check aliasing of binv and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_div_newton_n_preinv(q, a, b, binv); nmod_poly_div_newton_n_preinv(binv, a, b, binv); result = (nmod_poly_equal(binv, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(binv), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-div_root.c000066400000000000000000000060351461254215100206370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_div_root, state) { int i, result; /* Compare with standard divrem */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t P, Q, D, DQ, DR; mp_limb_t mod, r, rem; slong n; mod = n_randtest_prime(state, 0); n = n_randint(state, 100); r = n_randint(state, mod); nmod_poly_init(P, mod); nmod_poly_init(Q, mod); nmod_poly_init(D, mod); nmod_poly_init(DQ, mod); nmod_poly_init(DR, mod); nmod_poly_randtest(P, state, n); rem = nmod_poly_div_root(Q, P, r); nmod_poly_set_coeff_ui(D, 0, n_negmod(r, mod)); nmod_poly_set_coeff_ui(D, 1, UWORD(1)); nmod_poly_divrem(DQ, DR, P, D); result = nmod_poly_equal(Q, DQ) && (rem == nmod_poly_get_coeff_ui(DR, 0)); if (!result) { flint_printf("FAIL!\n"); flint_printf("P:\n"); nmod_poly_print(P); flint_printf("\n\n"); flint_printf("Q:\n"); nmod_poly_print(Q); flint_printf("\n\n"); flint_printf("D:\n"); nmod_poly_print(D); flint_printf("\n\n"); flint_printf("DQ:\n"); nmod_poly_print(DQ); flint_printf("\n\n"); flint_printf("DR:\n"); nmod_poly_print(DR); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); nmod_poly_clear(D); nmod_poly_clear(DQ); nmod_poly_clear(DR); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t P, Q1, Q2; mp_limb_t mod, r, rem1, rem2; slong n; mod = n_randtest_prime(state, 0); n = n_randint(state, 100); r = n_randint(state, mod); nmod_poly_init(P, mod); nmod_poly_init(Q1, mod); nmod_poly_init(Q2, mod); nmod_poly_randtest(P, state, n); nmod_poly_set(Q2, P); rem1 = nmod_poly_div_root(Q1, P, r); rem2 = nmod_poly_div_root(Q2, Q2, r); result = nmod_poly_equal(Q1, Q2) && (rem1 == rem2); if (!result) { flint_printf("FAIL (aliasing)!\n"); flint_printf("P:\n"); nmod_poly_print(P); flint_printf("\n\n"); flint_printf("Q1:\n"); nmod_poly_print(Q1); flint_printf("\n\n"); flint_printf("Q2:\n"); nmod_poly_print(Q2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q1); nmod_poly_clear(Q2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-div_series.c000066400000000000000000000077451461254215100211570ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_div_series, state) { int i, result; /* Check A/B * B = A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, a, b, prod; slong m; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(prod, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0 || b->coeffs[0] == 0); m = n_randint(state, 2000) + 1; nmod_poly_div_series(q, a, b, m); nmod_poly_mullow(prod, q, b, m); nmod_poly_truncate(a, m); result = (nmod_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(prod); } /* Check aliasing of q and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, a, b; slong m; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(q, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); do nmod_poly_randtest(b, state, n_randint(state, 1000)); while (b->length == 0 || b->coeffs[0] == 0); m = n_randint(state, 1000) + 1; nmod_poly_div_series(q, a, b, m); nmod_poly_div_series(a, a, b, m); result = (nmod_poly_equal(q, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); } /* Check aliasing of q and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, a, b; slong m; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(q, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); do nmod_poly_randtest(b, state, n_randint(state, 1000)); while (b->length == 0 || b->coeffs[0] == 0); m = n_randint(state, 1000) + 1; nmod_poly_div_series(q, a, b, m); nmod_poly_div_series(b, a, b, m); result = (nmod_poly_equal(q, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-div_series_basecase.c000066400000000000000000000100331461254215100227650ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_div_series_basecase, state) { int i, result; /* Check A/B * B = A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, a, b, prod; slong m; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(prod, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0 || b->coeffs[0] == 0); m = n_randint(state, 2000) + 1; nmod_poly_div_series_basecase(q, a, b, m); nmod_poly_mullow(prod, q, b, m); nmod_poly_truncate(a, m); result = (nmod_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(prod); } /* Check aliasing of q and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, a, b; slong m; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(q, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); do nmod_poly_randtest(b, state, n_randint(state, 1000)); while (b->length == 0 || b->coeffs[0] == 0); m = n_randint(state, 1000) + 1; nmod_poly_div_series_basecase(q, a, b, m); nmod_poly_div_series_basecase(a, a, b, m); result = (nmod_poly_equal(q, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); } /* Check aliasing of q and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, a, b; slong m; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(q, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); do nmod_poly_randtest(b, state, n_randint(state, 1000)); while (b->length == 0 || b->coeffs[0] == 0); m = n_randint(state, 1000) + 1; nmod_poly_div_series_basecase(q, a, b, m); nmod_poly_div_series_basecase(b, a, b, m); result = (nmod_poly_equal(q, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-divexact.c000066400000000000000000000040151461254215100206150ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_divexact, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, ab, q; int aliasing; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(ab, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 400)); do nmod_poly_randtest(b, state, n_randint(state, 400)); while (b->length == 0); nmod_poly_mul(ab, a, b); aliasing = n_randint(state, 3); switch (aliasing) { case 0: nmod_poly_divexact(q, ab, b); break; case 1: nmod_poly_set(q, ab); nmod_poly_divexact(q, q, b); break; default: nmod_poly_set(q, b); nmod_poly_divexact(q, ab, q); break; } result = (nmod_poly_equal(q, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(ab); nmod_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-divides.c000066400000000000000000000123321461254215100204360ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_divides, state) { int i, result; /* Random polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, prod; int divides; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(prod, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); divides = nmod_poly_divides(q, a, b); nmod_poly_mul(prod, q, b); result = ((divides && nmod_poly_equal(a, prod)) || (!divides && nmod_poly_is_zero(q) && !nmod_poly_equal(prod, a))); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(prod); } /* Random divisible polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, prod; int divides; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(prod, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); nmod_poly_mul(a, b, a); divides = nmod_poly_divides(q, a, b); nmod_poly_mul(prod, q, b); result = (divides && nmod_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(prod); } /* Check aliasing of a and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q; int divides1, divides2; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 300)); nmod_poly_randtest(b, state, n_randint(state, 300)); divides1 = nmod_poly_divides(q, a, b); divides2 = nmod_poly_divides(a, a, b); result = (divides1 == divides2 && nmod_poly_equal(q, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } /* Check aliasing of b and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q; int divides1, divides2; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 300)); nmod_poly_randtest(b, state, n_randint(state, 300)); divides1 = nmod_poly_divides(q, a, b); divides2 = nmod_poly_divides(b, a, b); result = (divides1 == divides2 && nmod_poly_equal(q, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-divides_classical.c000066400000000000000000000124341461254215100224570ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_divides_classical, state) { int i, result; /* Random polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, prod; int divides; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(prod, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); divides = nmod_poly_divides_classical(q, a, b); nmod_poly_mul(prod, q, b); result = ((divides && nmod_poly_equal(a, prod)) || (!divides && nmod_poly_is_zero(q) && !nmod_poly_equal(prod, a))); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(prod); } /* Random divisible polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, prod; int divides; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(prod, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_mul(a, b, a); divides = nmod_poly_divides_classical(q, a, b); nmod_poly_mul(prod, q, b); result = (divides && nmod_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides = %d\n", divides); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(prod); } /* Check aliasing of a and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q; int divides1, divides2; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); divides1 = nmod_poly_divides_classical(q, a, b); divides2 = nmod_poly_divides_classical(a, a, b); result = (divides1 == divides2 && nmod_poly_equal(q, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } /* Check aliasing of b and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q; int divides1, divides2; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); divides1 = nmod_poly_divides_classical(q, a, b); divides2 = nmod_poly_divides_classical(b, a, b); result = (divides1 == divides2 && nmod_poly_equal(q, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-divrem.c000066400000000000000000000220201461254215100202700ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_divrem, state) { int i, result; /* Check result of divrem */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r, prod; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(prod, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_divrem(q, r, a, b); nmod_poly_mul(prod, q, b); nmod_poly_add(prod, prod, r); result = (nmod_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(prod); } /* Check aliasing of a and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_divrem(q, r, a, b); nmod_poly_divrem(a, r, a, b); result = (nmod_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of b and q */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_divrem(q, r, a, b); nmod_poly_divrem(b, r, a, b); result = (nmod_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of a and r */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_divrem(q, r, a, b); nmod_poly_divrem(q, a, a, b); result = (nmod_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of b and r */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_divrem(q, r, a, b); nmod_poly_divrem(q, b, a, b); result = (nmod_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check result of divrem_q0 */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r, prod; mp_limb_t n = n_randprime(state, n_randint(state,FLINT_BITS-1)+2, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(prod, n); do nmod_poly_randtest(a, state, n_randint(state, 400)); while (a->length < 1); nmod_poly_randtest(b, state, a->length); do b->coeffs[a->length - 1] = n_randint(state, n); while (b->coeffs[a->length - 1] == 0); b->length = a->length; nmod_poly_divrem(q, r, a, b); nmod_poly_mul(prod, q, b); nmod_poly_add(prod, prod, r); result = (nmod_poly_equal(a, prod) && r->length < b->length); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(prod); } /* Check result of divrem_q1 */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r, prod; mp_limb_t n = n_randprime(state, n_randint(state,FLINT_BITS-1)+2, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(prod, n); do nmod_poly_randtest(a, state, n_randint(state, 1000)); while (a->length < 2); nmod_poly_fit_length(b, a->length - 1); flint_mpn_zero(b->coeffs, a->length - 1); nmod_poly_randtest_not_zero(b, state, n_randint(state, 1000) + 1); do b->coeffs[a->length - 2] = n_randint(state, n); while (b->coeffs[a->length - 2] == 0); b->length = a->length - 1; nmod_poly_divrem(q, r, a, b); nmod_poly_mul(prod, q, b); nmod_poly_add(prod, prod, r); result = (nmod_poly_equal(a, prod) && r->length < b->length); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(prod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-divrem_basecase.c000066400000000000000000000150121461254215100221210ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_divrem_basecase, state) { int i, result; /* Check result of divrem */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r, prod; mp_limb_t n; do { n = n_randtest_not_zero(state); } while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(prod, n); nmod_poly_randtest(a, state, n_randint(state, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_divrem_basecase(q, r, a, b); nmod_poly_mul(prod, q, b); nmod_poly_add(prod, prod, r); result = (nmod_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(prod); } /* Check aliasing of a and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do { n = n_randtest(state); } while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_divrem_basecase(q, r, a, b); nmod_poly_divrem_basecase(a, r, a, b); result = (nmod_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of b and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do { n = n_randtest(state); } while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_divrem_basecase(q, r, a, b); nmod_poly_divrem_basecase(b, r, a, b); result = (nmod_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of a and r */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do { n = n_randtest(state); } while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_divrem_basecase(q, r, a, b); nmod_poly_divrem_basecase(q, a, a, b); result = (nmod_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of b and r */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r; mp_limb_t n; do { n = n_randtest(state); } while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_divrem_basecase(q, r, a, b); nmod_poly_divrem_basecase(q, b, a, b); result = (nmod_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000254711461254215100235770ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_divrem_newton_n_preinv, state) { int i, result; /* Check result of divrem */ for (i = 0; i < 2000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r, test; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(test, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, 2*b->length - 1); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_divrem_newton_n_preinv(q, r, a, b, binv); nmod_poly_mul(test, q, b); nmod_poly_add(test, test, r); result = (nmod_poly_equal(a, test)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a.length: %wd\n", a->length); flint_printf("b.length: %wd\n", b->length); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(test), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(test); } #if 0 /* Check aliasing of a and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_divrem_newton_n_preinv(q, r, a, b, binv); nmod_poly_divrem_newton_n_preinv(a, r, a, b, binv); result = (nmod_poly_equal(a, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of b and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_divrem_newton_n_preinv(q, r, a, b, binv); nmod_poly_divrem_newton_n_preinv(b, r, a, b, binv); result = (nmod_poly_equal(b, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of binv and q */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_divrem_newton_n_preinv(q, r, a, b, binv); nmod_poly_divrem_newton_n_preinv(binv, r, a, b, binv); result = (nmod_poly_equal(binv, q)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(binv), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of a and r */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_divrem_newton_n_preinv(q, r, a, b, binv); nmod_poly_divrem_newton_n_preinv(q, a, a, b, binv); result = (nmod_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of b and r */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_divrem_newton_n_preinv(q, r, a, b, binv); nmod_poly_divrem_newton_n_preinv(q, b, a, b, binv); result = (nmod_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); } /* Check aliasing of binv and r */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, binv, q, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(binv, n); nmod_poly_init(q, n); nmod_poly_init(r, n); do nmod_poly_randtest(b, state, n_randint(state, 200)); while (b->length <= 2); nmod_poly_randtest(a, state, n_randint(state, 200)); if (a->length > 2*(b->length)-3) nmod_poly_truncate (a, 2*(b->length)-3); nmod_poly_reverse (binv, b, b->length); nmod_poly_inv_series (binv, binv, b->length); nmod_poly_divrem_newton_n_preinv(q, r, a, b, binv); nmod_poly_divrem_newton_n_preinv(q, binv, a, b, binv); result = (nmod_poly_equal(binv, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(binv), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-equal_trunc.c000066400000000000000000000052131461254215100213310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_equal_trunc, state) { int i, result; /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; ulong c, p; slong n, j; p = n_randtest(state); if (p == 0) p++; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100); for (j = 0; j < n; j++) { c = nmod_poly_get_coeff_ui(a, j); nmod_poly_set_coeff_ui(b, j, c); } result = (nmod_poly_equal_trunc(a, b, n)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } /* unequal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; ulong c, p; slong m, n, j; p = n_randtest(state); if (p < 2) p += 2; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100) + 1; m = n_randint(state, n); for (j = 0; j < n; j++) { c = nmod_poly_get_coeff_ui(a, j); nmod_poly_set_coeff_ui(b, j, c); } c = nmod_poly_get_coeff_ui(b, m); c = n_addmod(c, 1, p); nmod_poly_set_coeff_ui(b, m, c); result = (!nmod_poly_equal_trunc(a, b, n)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("n = %wd\n", n); flint_printf("m = %wd\n", m); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-evaluate_mat_horner.c000066400000000000000000000057661461254215100230500ustar00rootroot00000000000000/* Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_mat.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_evaluate_mat_horner, state) { int i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; nmod_mat_t A, B; mp_limb_t sum, n = n_randtest_not_zero(state); slong m, k; nmod_poly_init(a, n); nmod_poly_randtest(a, state, n_randint(state, 50)); m = n_randint(state, 20); nmod_mat_init(A, m, m, n); nmod_mat_init(B, m, m, n); nmod_mat_one(A); nmod_poly_evaluate_mat_horner(B, a, A); sum = 0; for (j = 0; j < a->length; j++) sum = n_addmod(sum, nmod_poly_get_coeff_ui(a, j), n); for(k = 0; k < m; k++) nmod_mat_entry(A, k, k) = nmod_mul(nmod_mat_entry(A, k, k), sum, A->mod); if (!nmod_mat_equal(A, B)) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); flint_printf("sum = %wu\n", sum); nmod_poly_print(a), flint_printf("\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_mat_clear(A); nmod_mat_clear(B); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; nmod_mat_t A, B, C; mp_limb_t n = n_randtest_not_zero(state); slong m; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); m = n_randint(state, 20); nmod_mat_init(A, m, m, n); nmod_mat_init(B, m, m, n); nmod_mat_init(C, m, m, n); nmod_mat_randtest(A, state); nmod_poly_evaluate_mat_horner(B, a, A); nmod_poly_evaluate_mat_horner(C, b, A); nmod_mat_add(C, B, C); nmod_poly_add(a, a, b); nmod_poly_evaluate_mat_horner(B, a, A); if (!nmod_mat_equal(B, C)) { flint_printf("FAIL:\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-evaluate_mat_paterson_stockmeyer.c000066400000000000000000000060671461254215100256460ustar00rootroot00000000000000/* Copyright (C) 2014 Ashish Kedia This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_mat.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_evaluate_mat_paterson_stockmeyer, state) { int i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; nmod_mat_t A, B; mp_limb_t sum, n = n_randtest_not_zero(state); slong m, k; nmod_poly_init(a, n); nmod_poly_randtest(a, state, n_randint(state, 50)); m = n_randint(state, 20); nmod_mat_init(A, m, m, n); nmod_mat_init(B, m, m, n); nmod_mat_one(A); nmod_poly_evaluate_mat_paterson_stockmeyer(B, a, A); sum = 0; for (j = 0; j < a->length; j++) sum = n_addmod(sum, nmod_poly_get_coeff_ui(a, j), n); for(k = 0; k < m; k++) nmod_mat_entry(A, k, k) = nmod_mul(nmod_mat_entry(A, k, k), sum, A->mod); if (!nmod_mat_equal(A, B)) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); flint_printf("sum = %wu\n", sum); nmod_poly_print(a), flint_printf("\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_mat_clear(A); nmod_mat_clear(B); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; nmod_mat_t A, B, C; mp_limb_t n = n_randtest_not_zero(state); slong m; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); m = n_randint(state, 20); nmod_mat_init(A, m, m, n); nmod_mat_init(B, m, m, n); nmod_mat_init(C, m, m, n); nmod_mat_randtest(A, state); nmod_poly_evaluate_mat_paterson_stockmeyer(B, a, A); nmod_poly_evaluate_mat_paterson_stockmeyer(C, b, A); nmod_mat_add(C, B, C); nmod_poly_add(a, a, b); nmod_poly_evaluate_mat_paterson_stockmeyer(B, a, A); if (!nmod_mat_equal(B, C)) { flint_printf("FAIL:\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-evaluate_nmod.c000066400000000000000000000046611461254215100216400ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_evaluate_nmod, state) { int i, j, result = 1; /* Check evaluation at 1 gives sum of coeffs */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t sum, eval; nmod_poly_init(a, n); nmod_poly_randtest(a, state, n_randint(state, 100)); eval = nmod_poly_evaluate_nmod(a, 1); sum = 0; for (j = 0; j < a->length; j++) sum = n_addmod(sum, nmod_poly_get_coeff_ui(a, j), n); result = (sum == eval); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); flint_printf("sum = %wu, eval = %wu\n", sum, eval); nmod_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); } /* Check a(c) + b(c) = (a + b)(c) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t eval1, eval2, c; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); c = n_randint(state, n); eval1 = nmod_poly_evaluate_nmod(a, c); eval1 = n_addmod(eval1, nmod_poly_evaluate_nmod(b, c), n); nmod_poly_add(a, a, b); eval2 = nmod_poly_evaluate_nmod(a, c); result = (eval1 == eval2); if (!result) { flint_printf("FAIL:\n"); flint_printf("eval1 = %wu, eval2 = %wu\n", eval1, eval2); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-evaluate_nmod_vec_fast.c000066400000000000000000000034471461254215100235130ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011, 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_evaluate_nmod_vec_fast, state) { int i, result = 1; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t P, Q; mp_ptr x, y, z; mp_limb_t mod; slong j, n, npoints; mod = n_randtest_prime(state, 0); npoints = n_randint(state, 100); n = n_randint(state, 100); nmod_poly_init(P, mod); nmod_poly_init(Q, mod); x = _nmod_vec_init(npoints); y = _nmod_vec_init(npoints); z = _nmod_vec_init(npoints); nmod_poly_randtest(P, state, n); for (j = 0; j < npoints; j++) x[j] = n_randint(state, mod); nmod_poly_evaluate_nmod_vec_iter(y, P, x, npoints); nmod_poly_evaluate_nmod_vec_fast(z, P, x, npoints); result = _nmod_vec_equal(y, z, npoints); if (!result) { flint_printf("FAIL:\n"); flint_printf("mod=%wu, n=%wd, npoints=%wd\n\n", mod, n, npoints); flint_printf("P: "); nmod_poly_print(P); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); _nmod_vec_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-exp_series.c000066400000000000000000000074501461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_exp_series, state) { int i, result = 1; /* Check exp(A+B) = exp(A) * exp(B) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t A, B, AB, expA, expB, expAB, S; slong n; slong N = 100; mp_limb_t mod; /* Make sure to workout the Newton code */ if (n_randint(state, 100) == 1) N = 20000; mod = n_randtest_prime(state, 0); n = n_randtest(state) % N; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_init(AB, mod); nmod_poly_init(expA, mod); nmod_poly_init(expB, mod); nmod_poly_init(expAB, mod); nmod_poly_init(S, mod); nmod_poly_randtest(A, state, n_randint(state, N)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_randtest(B, state, n_randint(state, N)); nmod_poly_set_coeff_ui(B, 0, UWORD(0)); /* Randomly generate a monomial */ if (n_randlimb(state) % 100 == 0) { nmod_poly_zero(A); nmod_poly_set_coeff_ui(A, n_randlimb(state) % (n+5), \ n_randtest_not_zero(state) % mod); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); } nmod_poly_exp_series(expA, A, n); nmod_poly_exp_series(expB, B, n); nmod_poly_add(AB, A, B); nmod_poly_exp_series(expAB, AB, n); nmod_poly_mullow(S, expA, expB, n); result = nmod_poly_equal(S, expAB); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("exp(A): "); nmod_poly_print(expA), flint_printf("\n\n"); flint_printf("exp(B): "); nmod_poly_print(expB), flint_printf("\n\n"); flint_printf("exp(A+B): "); nmod_poly_print(expAB), flint_printf("\n\n"); flint_printf("exp(A)*exp(B): "); nmod_poly_print(S), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(AB); nmod_poly_clear(expA); nmod_poly_clear(expB); nmod_poly_clear(expAB); nmod_poly_clear(S); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); if (i < 30) n = n_randint(state, 20000); else n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_exp_series(B, A, n); nmod_poly_exp_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-find_distinct_nonzero_roots.c000066400000000000000000000056151461254215100246360ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_find_distinct_nonzero_roots, state) { slong i, j; for (i = 0; i < 200 * flint_test_multiplier(); i++) { int highdegreefactor; nmod_poly_t a, b, r; mp_limb_t p; p = n_randtest_prime(state, 1); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(r, p); nmod_poly_zero(a); nmod_poly_set_coeff_ui(a, 0, 1 + n_randint(state, p - 1)); highdegreefactor = 0; for (j = n_randint(state, 10); j >= 0; j--) { if (n_randint(state, 10) > 1) { nmod_poly_randtest_monic_irreducible(b, state, 1); } else { highdegreefactor = 1; nmod_poly_randtest_monic_irreducible(b, state, 2 + n_randint(state, 9)); } nmod_poly_mul(a, a, b); } nmod_poly_fit_length(r, nmod_poly_degree(a)); if (nmod_poly_find_distinct_nonzero_roots(r->coeffs, a)) { /* check that a is square free */ nmod_poly_derivative(b, a); nmod_poly_gcd(b, b, a); if (nmod_poly_degree(b) > 0) { flint_printf("FAIL\ncheck multiple roots i = %wd\n", i); fflush(stdout); flint_abort(); } /* check that each root is a root */ for (j = nmod_poly_degree(a) - 1; j >= 0; j--) { if (r->coeffs[j] == 0) { flint_printf("FAIL\ncheck zero root i = %wd\n", i); fflush(stdout); flint_abort(); } if (nmod_poly_evaluate_nmod(a, r->coeffs[j]) != 0) { flint_printf("FAIL\ncheck root is a root i = %wd\n", i); fflush(stdout); flint_abort(); } } } else { nmod_poly_derivative(b, a); nmod_poly_gcd(b, b, a); if (!highdegreefactor && nmod_poly_degree(b) == 0 && nmod_poly_evaluate_nmod(a, 0) != 0) { flint_printf("FAIL\ncheck fail return i = %wd\n", i); fflush(stdout); flint_abort(); } } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-fread_print.c000066400000000000000000000037061461254215100213110ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_fread_print, state) { int i, result, r1; #if !defined( _MSC_VER ) /* Check reading and writing to a file */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); FILE * f = fopen("nmod_poly_test", "w+"); if (!f) { flint_printf("Error: unable to open file for writing.\n"); fflush(stdout); flint_abort(); } nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_fprint(f, a); fflush(f); fclose(f); f = fopen("nmod_poly_test", "r"); r1 = nmod_poly_fread(f, b); result = (r1 && nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("r1 = %d, n = %wu\n", r1, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fclose(f); remove("nmod_poly_test"); fflush(stdout); flint_abort(); } fclose(f); if (remove("nmod_poly_test")) { flint_printf("Error, unable to delete file nmod_poly_test\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/nmod_poly/test/t-gcd.c000066400000000000000000000077051461254215100175540ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_gcd, state) { int i, result; /* Find coprime polys, multiply by another poly and check the GCD is that poly */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, g; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g, n); do { nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); nmod_poly_gcd_euclidean(g, a, b); } while (g->length != 1); do { nmod_poly_randtest(c, state, n_randint(state, 1000)); } while (c->length < 2); nmod_poly_make_monic(c, c); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd_euclidean(g, a, b); result = (nmod_poly_equal(g, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g); } /* Check aliasing of a and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); nmod_poly_gcd_euclidean(g, a, b); nmod_poly_gcd_euclidean(a, a, b); result = (nmod_poly_equal(a, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } /* Check aliasing of b and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); nmod_poly_gcd_euclidean(g, a, b); nmod_poly_gcd_euclidean(b, a, b); result = (nmod_poly_equal(b, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-gcd_euclidean.c000066400000000000000000000076361461254215100215700ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_gcd_euclidean, state) { int i, result; /* Find coprime polys, multiply by another poly and check the GCD is that poly */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, g; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g, n); do { nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_gcd_euclidean(g, a, b); } while (g->length != 1); do { nmod_poly_randtest(c, state, n_randint(state, 200)); } while (c->length < 2); nmod_poly_make_monic(c, c); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd_euclidean(g, a, b); result = (nmod_poly_equal(g, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g); } /* Check aliasing of a and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_gcd_euclidean(g, a, b); nmod_poly_gcd_euclidean(a, a, b); result = (nmod_poly_equal(a, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } /* Check aliasing of b and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_gcd_euclidean(g, a, b); nmod_poly_gcd_euclidean(b, a, b); result = (nmod_poly_equal(b, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-gcd_hgcd.c000066400000000000000000000076541461254215100205440ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_gcd_hgcd, state) { int i, result; /* Find coprime polys, multiply by another poly and check the GCD is that poly */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, g; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g, n); do { nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); nmod_poly_gcd_hgcd(g, a, b); } while (g->length != 1); do { nmod_poly_randtest(c, state, n_randint(state, 1000)); } while (c->length < 2); nmod_poly_make_monic(c, c); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd_hgcd(g, a, b); result = (nmod_poly_equal(g, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g); } /* Check aliasing of a and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); nmod_poly_gcd_hgcd(g, a, b); nmod_poly_gcd_hgcd(a, a, b); result = (nmod_poly_equal(a, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } /* Check aliasing of b and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_randtest(a, state, n_randint(state, 1000)); nmod_poly_randtest(b, state, n_randint(state, 1000)); nmod_poly_gcd_hgcd(g, a, b); nmod_poly_gcd_hgcd(b, a, b); result = (nmod_poly_equal(b, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-gcdinv.c000066400000000000000000000077111461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_gcdinv, state) { int i, result; /* Generic case, most likely co-prime arguments ******************************/ /* Compare with result from XGCD */ for (i = 0; i < 1000; i++) { mp_limb_t p; nmod_poly_t a, b, d, g, s, t, u; p = n_randtest_prime(state, 0); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(d, p); nmod_poly_init(g, p); nmod_poly_init(s, p); nmod_poly_init(t, p); nmod_poly_init(u, p); nmod_poly_randtest(a, state, n_randint(state, 100)); do nmod_poly_randtest(b, state, n_randint(state, 100)); while (b->length < 2); nmod_poly_gcdinv(d, u, a, b); nmod_poly_xgcd(g, s, t, a, b); result = ((nmod_poly_equal(d, g) && nmod_poly_equal(u, s)) || (nmod_poly_is_zero(d))); if (!result) { printf("FAIL:\n"); printf("a = "), nmod_poly_print(a), printf("\n\n"); printf("b = "), nmod_poly_print(b), printf("\n\n"); printf("d = "), nmod_poly_print(d), printf("\n\n"); printf("g = "), nmod_poly_print(g), printf("\n\n"); printf("s = "), nmod_poly_print(s), printf("\n\n"); printf("t = "), nmod_poly_print(t), printf("\n\n"); printf("u = "), nmod_poly_print(u), printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(d); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); nmod_poly_clear(u); } /* Special case, arguments share a factor ********************************/ /* Compare with result from XGCD */ for (i = 0; i < 1000; i++) { mp_limb_t p; nmod_poly_t a, b, d, f, g, s, t, u; p = n_randtest_prime(state, 0); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(d, p); nmod_poly_init(f, p); nmod_poly_init(g, p); nmod_poly_init(s, p); nmod_poly_init(t, p); nmod_poly_init(u, p); nmod_poly_randtest(a, state, n_randint(state, 100)); do nmod_poly_randtest(b, state, n_randint(state, 100)); while (b->length < 2); nmod_poly_randtest_not_zero(f, state, n_randint(state, 20) + 1); nmod_poly_mul(a, f, a); nmod_poly_mul(b, f, b); nmod_poly_gcdinv(d, u, a, b); nmod_poly_xgcd(g, s, t, a, b); result = ((nmod_poly_equal(d, g) && nmod_poly_equal(u, s)) || (nmod_poly_is_zero(d))); if (!result) { printf("FAIL:\n"); printf("a = "), nmod_poly_print(a), printf("\n\n"); printf("b = "), nmod_poly_print(b), printf("\n\n"); printf("d = "), nmod_poly_print(d), printf("\n\n"); printf("f = "), nmod_poly_print(f), printf("\n\n"); printf("g = "), nmod_poly_print(g), printf("\n\n"); printf("s = "), nmod_poly_print(s), printf("\n\n"); printf("t = "), nmod_poly_print(t), printf("\n\n"); printf("u = "), nmod_poly_print(u), printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(d); nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); nmod_poly_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-get_set_coeff_ui.c000066400000000000000000000025121461254215100222770ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_get_set_coeff_ui, state) { int i, result; ulong j; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t c1 = n_randtest(state), c2; j = n_randint(state, 100); nmod_poly_init(a, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(a, j, c1); c2 = nmod_poly_get_coeff_ui(a, j); result = (c2 == c1 % n); if (!result) { flint_printf("FAIL:\n"); flint_printf("j = %wu, c1 = %wu, c2 = %wu, n = %wu\n", j, c1, c2, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-get_set_str.c000066400000000000000000000026331461254215100213340ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_get_set_str, state) { int i, result, r1; /* Check to and from string */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); char * str; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); str = nmod_poly_get_str(a); r1 = nmod_poly_set_str(b, str); result = (r1 && nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("r1 = %d, n = %wu\n", r1, a->mod.n); flint_printf("%s\n", str); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } flint_free(str); nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-hgcd.c000066400000000000000000000170471461254215100177240ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "mpn_extras.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ _nmod_poly_mul((C), (A), (lenA), (B), (lenB), mod); \ else \ _nmod_poly_mul((C), (B), (lenB), (A), (lenA), mod); \ (lenC) = (lenA) + (lenB) - 1; \ } \ else \ { \ (lenC) = 0; \ } \ } while (0) TEST_FUNCTION_START(nmod_poly_hgcd, state) { slong i, j, result; /* check that [c1,d1] := M^{-1} [a,b] assuming that deg(M) = sgnM */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d, c1, d1, s, t; mp_ptr M[4]; slong lenM[4]; slong sgnM; mp_limb_t n = n_randprime(state, FLINT_BITS, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_init(c1, n); nmod_poly_init(d1, n); nmod_poly_init(s, n); nmod_poly_init(t, n); do { nmod_poly_randtest_not_zero(a, state, n_randint(state, 800) + 1); nmod_poly_randtest_not_zero(b, state, n_randint(state, 800) + 1); } while (a->length == b->length); if (a->length < b->length) nmod_poly_swap(a, b); M[0] = _nmod_vec_init(a->length); M[1] = _nmod_vec_init(a->length); M[2] = _nmod_vec_init(a->length); M[3] = _nmod_vec_init(a->length); nmod_poly_fit_length(c, a->length); nmod_poly_fit_length(d, b->length); sgnM = _nmod_poly_hgcd(M, lenM, c->coeffs, &(c->length), d->coeffs, &(d->length), a->coeffs, a->length, b->coeffs, b->length, a->mod); nmod_poly_fit_length(s, 2 * a->length); nmod_poly_fit_length(t, 2 * a->length); /* [c1, d1] := M^{-1} [a,b] */ { const nmod_t mod = a->mod; MPN_SWAP(M[0], lenM[0], M[3], lenM[3]); _nmod_vec_neg(M[1], M[1], lenM[1], mod); _nmod_vec_neg(M[2], M[2], lenM[2], mod); __mul(s->coeffs, s->length, M[0], lenM[0], a->coeffs, a->length); __mul(t->coeffs, t->length, M[1], lenM[1], b->coeffs, b->length); nmod_poly_add(c1, s, t); __mul(s->coeffs, s->length, M[2], lenM[2], a->coeffs, a->length); __mul(t->coeffs, t->length, M[3], lenM[3], b->coeffs, b->length); nmod_poly_add(d1, s, t); } if (sgnM < 0) { nmod_poly_neg(c1, c1); nmod_poly_neg(d1, d1); } result = (nmod_poly_equal(c, c1) && nmod_poly_equal(d, d1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), nmod_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), nmod_poly_print(c), flint_printf("\n\n"); flint_printf("d = "), nmod_poly_print(d), flint_printf("\n\n"); flint_printf("c1 = "), nmod_poly_print(c1), flint_printf("\n\n"); flint_printf("d1 = "), nmod_poly_print(d1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); nmod_poly_clear(c1); nmod_poly_clear(d1); nmod_poly_clear(s); nmod_poly_clear(t); _nmod_vec_clear(M[0]); _nmod_vec_clear(M[1]); _nmod_vec_clear(M[2]); _nmod_vec_clear(M[3]); } for (i = 0; i < 50 * flint_test_multiplier(); i++) { mp_limb_t p; slong sgnM, sgnMr; nmod_poly_t m11, m12, m21, m22, A, B, a, b; nmod_poly_t m11r, m12r, m21r, m22r, Ar, Br; nmod_poly_t q, t; p = n_randtest_prime(state, 1); nmod_poly_init(m11, p); nmod_poly_init(m12, p); nmod_poly_init(m21, p); nmod_poly_init(m22, p); nmod_poly_init(A, p); nmod_poly_init(B, p); nmod_poly_init(m11r, p); nmod_poly_init(m12r, p); nmod_poly_init(m21r, p); nmod_poly_init(m22r, p); nmod_poly_init(Ar, p); nmod_poly_init(Br, p); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(q, p); nmod_poly_init(t, p); /* prepare inputs a, b */ nmod_poly_randtest_monic(a, state, 1 + n_randint(state, 10)); nmod_poly_scalar_mul_nmod(a, a, 1 + n_randint(state, p - 1)); nmod_poly_zero(b); for (j = 1 + n_randint(state, 100); j >= 0; j--) { nmod_poly_randtest_monic(q, state, 2 + n_randint(state, 20)); nmod_poly_scalar_mul_nmod(q, q, 1 + n_randint(state, p - 1)); nmod_poly_mul(t, a, q); nmod_poly_add(b, b, t); nmod_poly_swap(a, b); } sgnMr = nmod_poly_hgcd_ref(m11r, m12r, m21r, m22r, Ar, Br, a, b); sgnM = nmod_poly_hgcd(m11, m12, m21, m22, A, B, a, b); if (sgnMr != sgnM || !nmod_poly_equal(m11r, m11) || !nmod_poly_equal(m12r, m12) || !nmod_poly_equal(m21r, m21) || !nmod_poly_equal(m22r, m22) || !nmod_poly_equal(Ar, A) || !nmod_poly_equal(Br, B)) { flint_printf("check reference match\n i = %wd\n", i); fflush(stdout); flint_abort(); } if (!(2*nmod_poly_degree(A) >= nmod_poly_degree(a) && nmod_poly_degree(a) > 2*nmod_poly_degree(B))) { flint_printf("check degrees\n i = %wd\n", i); fflush(stdout); flint_abort(); } nmod_poly_mul(q, m11, m22); nmod_poly_mul(t, m12, m21); nmod_poly_sub(t, q, t); if (sgnM < 0) { nmod_poly_neg(t, t); } if (!nmod_poly_is_one(t)) { flint_printf("check sign of determinant\n i = %wd\n", i); fflush(stdout); flint_abort(); } nmod_poly_clear(m11); nmod_poly_clear(m12); nmod_poly_clear(m21); nmod_poly_clear(m22); nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(m11r); nmod_poly_clear(m12r); nmod_poly_clear(m21r); nmod_poly_clear(m22r); nmod_poly_clear(Ar); nmod_poly_clear(Br); nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } #undef __mul flint-3.1.3/src/nmod_poly/test/t-inflate.c000066400000000000000000000042161461254215100204330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_inflate, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { nmod_poly_t poly1, poly2, poly3, xp; mp_limb_t modulus; ulong inflation; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly1, modulus); nmod_poly_init(poly2, modulus); nmod_poly_init(poly3, modulus); nmod_poly_init(xp, modulus); nmod_poly_randtest(poly1, state, n_randint(state, 20)); inflation = n_randint(state, 10); nmod_poly_inflate(poly2, poly1, inflation); nmod_poly_set_coeff_ui(xp, inflation, 1); nmod_poly_compose(poly3, poly1, xp); if (!nmod_poly_equal(poly2, poly3)) { flint_printf("FAIL: not equal to compose (inflation = %wu)\n", inflation); flint_printf("poly1:\n"); nmod_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); nmod_poly_print(poly2); flint_printf("\n\n"); flint_printf("poly3:\n"); nmod_poly_print(poly3); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_inflate(poly1, poly1, inflation); if (!nmod_poly_equal(poly1, poly2)) { flint_printf("FAIL: aliasing (inflation = %wu)\n", inflation); flint_printf("poly1:\n"); nmod_poly_print(poly1); flint_printf("\n\n"); flint_printf("poly2:\n"); nmod_poly_print(poly2); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(poly1); nmod_poly_clear(poly2); nmod_poly_clear(poly3); nmod_poly_clear(xp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-init_realloc_clear.c000066400000000000000000000025421461254215100226230ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_init_realloc_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init2(a, n, n_randint(state, 100)); nmod_poly_clear(a); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init2(a, n, n_randint(state, 100)); nmod_poly_realloc(a, n_randint(state, 100)); nmod_poly_realloc(a, n_randint(state, 100)); nmod_poly_clear(a); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-integral.c000066400000000000000000000046311461254215100206170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_integral, state) { int i, result = 1; /* Check with derivative */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; ulong len; mp_limb_t c0; mp_limb_t n = n_randtest_prime(state, 0); len = n_randint(state, 100); len = FLINT_MIN(len, n - 1); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, len); nmod_poly_integral(b, a); c0 = nmod_poly_get_coeff_ui(b, 0); nmod_poly_derivative(c, b); result = (c0 == UWORD(0)) && nmod_poly_equal(a, c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, FLINT_MIN(100, n))); nmod_poly_integral(b, a); nmod_poly_integral(a, a); result = nmod_poly_equal(a, b); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-interpolate_nmod_vec.c000066400000000000000000000033601461254215100232100ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_interpolate_nmod_vec, state) { int i, result = 1; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t P, Q; mp_ptr x, y; mp_limb_t mod; slong j, n, npoints; mod = n_randtest_prime(state, 0); npoints = n_randint(state, FLINT_MIN(100, mod)); n = n_randint(state, npoints + 1); nmod_poly_init(P, mod); nmod_poly_init(Q, mod); x = _nmod_vec_init(npoints); y = _nmod_vec_init(npoints); nmod_poly_randtest(P, state, n); for (j = 0; j < npoints; j++) x[j] = j; nmod_poly_evaluate_nmod_vec(y, P, x, npoints); nmod_poly_interpolate_nmod_vec(Q, x, y, npoints); result = nmod_poly_equal(P, Q); if (!result) { flint_printf("FAIL:\n"); flint_printf("mod=%wu, n=%wd, npoints=%wd\n\n", mod, n, npoints); nmod_poly_print(P), flint_printf("\n\n"); nmod_poly_print(Q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-interpolate_nmod_vec_barycentric.c000066400000000000000000000034101461254215100255710ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_interpolate_nmod_vec_barycentric, state) { int i, result = 1; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t P, Q; mp_ptr x, y; mp_limb_t mod; slong j, n, npoints; mod = n_randtest_prime(state, 0); npoints = n_randint(state, FLINT_MIN(100, mod)); n = n_randint(state, npoints + 1); nmod_poly_init(P, mod); nmod_poly_init(Q, mod); x = _nmod_vec_init(npoints); y = _nmod_vec_init(npoints); nmod_poly_randtest(P, state, n); for (j = 0; j < npoints; j++) x[j] = j; nmod_poly_evaluate_nmod_vec(y, P, x, npoints); nmod_poly_interpolate_nmod_vec_barycentric(Q, x, y, npoints); result = nmod_poly_equal(P, Q); if (!result) { flint_printf("FAIL:\n"); flint_printf("mod=%wu, n=%wd, npoints=%wd\n\n", mod, n, npoints); nmod_poly_print(P), flint_printf("\n\n"); nmod_poly_print(Q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-interpolate_nmod_vec_fast.c000066400000000000000000000034051461254215100242250ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011, 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_interpolate_nmod_vec_fast, state) { int i, result = 1; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t P, Q; mp_ptr x, y; mp_limb_t mod; slong j, n, npoints; mod = n_randtest_prime(state, 0); npoints = n_randint(state, FLINT_MIN(100, mod)); n = n_randint(state, npoints + 1); nmod_poly_init(P, mod); nmod_poly_init(Q, mod); x = _nmod_vec_init(npoints); y = _nmod_vec_init(npoints); nmod_poly_randtest(P, state, n); for (j = 0; j < npoints; j++) x[j] = j; nmod_poly_evaluate_nmod_vec_fast(y, P, x, npoints); nmod_poly_interpolate_nmod_vec_fast(Q, x, y, npoints); result = nmod_poly_equal(P, Q); if (!result) { flint_printf("FAIL:\n"); flint_printf("mod=%wu, n=%wd, npoints=%wd\n\n", mod, n, npoints); nmod_poly_print(P), flint_printf("\n\n"); nmod_poly_print(Q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-interpolate_nmod_vec_newton.c000066400000000000000000000033761461254215100246110ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_interpolate_nmod_vec_newton, state) { int i, result = 1; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t P, Q; mp_ptr x, y; mp_limb_t mod; slong j, n, npoints; mod = n_randtest_prime(state, 0); npoints = n_randint(state, FLINT_MIN(100, mod)); n = n_randint(state, npoints + 1); nmod_poly_init(P, mod); nmod_poly_init(Q, mod); x = _nmod_vec_init(npoints); y = _nmod_vec_init(npoints); nmod_poly_randtest(P, state, n); for (j = 0; j < npoints; j++) x[j] = j; nmod_poly_evaluate_nmod_vec(y, P, x, npoints); nmod_poly_interpolate_nmod_vec_newton(Q, x, y, npoints); result = nmod_poly_equal(P, Q); if (!result) { flint_printf("FAIL:\n"); flint_printf("mod=%wu, n=%wd, npoints=%wd\n\n", mod, n, npoints); nmod_poly_print(P), flint_printf("\n\n"); nmod_poly_print(Q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-inv_series_basecase.c000066400000000000000000000052621461254215100230070ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_inv_series_basecase, state) { int i, result; /* Check Q * Qinv = 1 mod x^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, qinv, prod; slong m; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(prod, n); nmod_poly_init(qinv, n); nmod_poly_init(q, n); do nmod_poly_randtest(q, state, n_randint(state, 2000)); while (q->length == 0 || q->coeffs[0] == 0); m = n_randint(state, 2000) + 1; nmod_poly_inv_series_basecase(qinv, q, m); nmod_poly_mul(prod, q, qinv); nmod_poly_truncate(prod, m); result = (prod->length == 1 && prod->coeffs[0] == 1); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(qinv), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(qinv); nmod_poly_clear(prod); } /* Check aliasing of q and qinv */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, qinv; slong m; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(q, n); nmod_poly_init(qinv, n); do nmod_poly_randtest(q, state, n_randint(state, 1000)); while (q->length == 0 || q->coeffs[0] == 0); m = n_randint(state, 2000) + 1; nmod_poly_inv_series_basecase(qinv, q, m); nmod_poly_inv_series_basecase(q, q, m); result = (nmod_poly_equal(q, qinv)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(qinv), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(qinv); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-inv_series_newton.c000066400000000000000000000052641461254215100225550ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_inv_series_newton, state) { int i, result; /* Check Q * Qinv = 1 mod x^n */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, qinv, prod; slong m; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(prod, n); nmod_poly_init(qinv, n); nmod_poly_init(q, n); do nmod_poly_randtest(q, state, n_randint(state, 2000)); while (q->length == 0 || q->coeffs[0] == 0); m = n_randint(state, q->length) + 1; nmod_poly_inv_series_newton(qinv, q, m); nmod_poly_mul(prod, q, qinv); nmod_poly_truncate(prod, m); result = (prod->length == 1 && prod->coeffs[0] == 1); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(qinv), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(qinv); nmod_poly_clear(prod); } /* Check aliasing of q and qinv */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t q, qinv; slong m; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(q, n); nmod_poly_init(qinv, n); do nmod_poly_randtest(q, state, n_randint(state, 1000)); while (q->length == 0 || q->coeffs[0] == 0); m = n_randint(state, q->length) + 1; nmod_poly_inv_series_newton(qinv, q, m); nmod_poly_inv_series_newton(q, q, m); result = (nmod_poly_equal(q, qinv)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(qinv), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(qinv); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-invmod.c000066400000000000000000000124711461254215100203070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_invmod, state) { int i, result; /* Test aliasing *************************************************************/ /* Aliasing c and a */ for (i = 0; i < 500; i++) { mp_limb_t p; nmod_poly_t a, b, c; int ans1, ans2; p = n_randtest_prime(state, 0); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); do nmod_poly_randtest(b, state, n_randint(state, 100)); while (b->length < 3); nmod_poly_randtest(a, state, n_randint(state, 100)); ans1 = nmod_poly_invmod(c, a, b); ans2 = nmod_poly_invmod(a, a, b); result = (ans1 == ans2 && nmod_poly_equal(a, c)); if (!result) { printf("FAIL (alias a and c):\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(c), printf("\n\n"); printf("ans1 = %d\n\n", ans1); printf("ans2 = %d\n\n", ans2); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Aliasing c and b */ for (i = 0; i < 500; i++) { mp_limb_t p; nmod_poly_t a, b, c; int ans1, ans2; p = n_randtest_prime(state, 0); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); do nmod_poly_randtest(b, state, n_randint(state, 100)); while (b->length < 3); nmod_poly_randtest(a, state, n_randint(state, 100)); ans1 = nmod_poly_invmod(c, a, b); ans2 = nmod_poly_invmod(b, a, b); result = ((ans1 == ans2) && nmod_poly_equal(b, c)); if (!result) { printf("FAIL (alias b and c):\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(c), printf("\n\n"); printf("ans1 = %d\n\n", ans1); printf("ans2 = %d\n\n", ans2); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with result from XGCD */ for (i = 0; i < 1000; i++) { mp_limb_t p; nmod_poly_t a, b, g, s, t, u; int ans; p = n_randtest_prime(state, 0); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(g, p); nmod_poly_init(s, p); nmod_poly_init(t, p); nmod_poly_init(u, p); do nmod_poly_randtest(b, state, n_randint(state, 100)); while (b->length < 3); nmod_poly_randtest(a, state, n_randint(state, 100)); ans = nmod_poly_invmod(u, a, b); nmod_poly_xgcd(g, s, t, a, b); result = (((ans) && g->length == 1 && g->coeffs[0] == WORD(1) && nmod_poly_equal(s, u)) || (!(ans) && g->length > 1)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(g), printf("\n\n"); nmod_poly_print(s), printf("\n\n"); nmod_poly_print(t), printf("\n\n"); nmod_poly_print(u), printf("\n\n"); printf("ans = %d\n\n", ans); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); nmod_poly_clear(u); } /* Special case, arguments share a factor ********************************/ /* Check correctness */ for (i = 0; i < 1000; i++) { mp_limb_t p; nmod_poly_t a, b, f, u; int ans; p = n_randtest_prime(state, 0); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(f, p); nmod_poly_init(u, p); do nmod_poly_randtest(b, state, n_randint(state, 100)); while (b->length < 2); nmod_poly_randtest(a, state, n_randint(state, 100)); do nmod_poly_randtest_not_zero(f, state, n_randint(state, 20) + 1); while (f->length < 2); nmod_poly_mul(a, f, a); nmod_poly_mul(b, f, b); ans = nmod_poly_invmod(u, a, b); result = (!ans); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(f), printf("\n\n"); nmod_poly_print(u), printf("\n\n"); printf("ans = %d\n\n", ans); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-invsqrt_series.c000066400000000000000000000052501461254215100220700ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_invsqrt_series, state) { int i, result; /* Check 1/g^2 = h mod x^m */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t h, g, r; slong m; mp_limb_t n; do n = n_randtest_prime(state, 0); while (n == UWORD(2)); nmod_poly_init(h, n); nmod_poly_init(g, n); nmod_poly_init(r, n); do nmod_poly_randtest(h, state, n_randint(state, 1000)); while (h->length == 0); nmod_poly_set_coeff_ui(h, 0, UWORD(1)); m = n_randint(state, h->length) + 1; nmod_poly_invsqrt_series(g, h, m); nmod_poly_mullow(r, g, g, m); nmod_poly_inv_series(r, r, m); nmod_poly_truncate(h, m); result = (nmod_poly_equal(r, h)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(h), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(h); nmod_poly_clear(g); nmod_poly_clear(r); } /* Check aliasing of h and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t g, h; slong m; mp_limb_t n; do n = n_randtest_prime(state, 0); while (n == UWORD(2)); nmod_poly_init(h, n); nmod_poly_init(g, n); do nmod_poly_randtest(h, state, n_randint(state, 500)); while (h->length == 0); nmod_poly_set_coeff_ui(h, 0, UWORD(1)); m = n_randint(state, h->length) + 1; nmod_poly_invsqrt_series(g, h, m); nmod_poly_invsqrt_series(h, h, m); result = (nmod_poly_equal(g, h)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(h), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(g); nmod_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-log_series.c000066400000000000000000000070641461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_log_series, state) { int i, result = 1; /* Check log(AB) = log(A) + log(B) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t A, B, AB, logA, logB, logAB, S; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_init(AB, mod); nmod_poly_init(logA, mod); nmod_poly_init(logB, mod); nmod_poly_init(logAB, mod); nmod_poly_init(S, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(1)); nmod_poly_randtest(B, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(B, 0, UWORD(1)); if (n_randlimb(state) % 100 == 0) { nmod_poly_zero(A); nmod_poly_set_coeff_ui(A, n_randlimb(state) % (n+5), \ n_randtest_not_zero(state) % mod); nmod_poly_set_coeff_ui(A, 0, UWORD(1)); } nmod_poly_log_series(logA, A, n); nmod_poly_log_series(logB, B, n); nmod_poly_mul(AB, A, B); nmod_poly_log_series(logAB, AB, n); nmod_poly_add(S, logA, logB); result = nmod_poly_equal(S, logAB); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); flint_printf("log(A): "); nmod_poly_print(logA), flint_printf("\n\n"); flint_printf("log(B): "); nmod_poly_print(logB), flint_printf("\n\n"); flint_printf("log(AB): "); nmod_poly_print(logAB), flint_printf("\n\n"); flint_printf("log(A)+log(B): "); nmod_poly_print(S), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); nmod_poly_clear(AB); nmod_poly_clear(logA); nmod_poly_clear(logB); nmod_poly_clear(logAB); nmod_poly_clear(S); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(1)); nmod_poly_log_series(B, A, n); nmod_poly_log_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-make_monic.c000066400000000000000000000046751461254215100211240ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_make_monic, state) { int i, result; /* Check new leading coeff = gcd old leading coeff and modulus */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t l; nmod_poly_init(a, n); nmod_poly_init(b, n); if (n == 1) continue; do { nmod_poly_randtest(a, state, n_randint(state, 100) + 1); } while (a->length == 0 || n_gcd(*nmod_poly_lead(a), n) != 1); nmod_poly_make_monic(b, a); l = n_gcd(a->mod.n, a->coeffs[a->length - 1]); result = (l == b->coeffs[b->length - 1]); if (!result) { flint_printf("FAIL:\n"); flint_printf("l = %wu, a->lead = %wd, n = %wu\n", l, a->coeffs[a->length - 1], a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } /* test aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t l; nmod_poly_init(a, n); if (n == 1) continue; do { nmod_poly_randtest(a, state, n_randint(state, 100) + 1); } while (a->length == 0 || n_gcd(*nmod_poly_lead(a), n) != 1); l = n_gcd(a->mod.n, a->coeffs[a->length - 1]); nmod_poly_make_monic(a, a); result = (l == a->coeffs[a->length - 1]); if (!result) { flint_printf("FAIL:\n"); flint_printf("l = %wu, a->lead = %wd, n = %wu\n", l, a->coeffs[a->length - 1], a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mul.c000066400000000000000000000064141461254215100176100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mul, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul(a, b, c); nmod_poly_mul(b, b, c); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul(a, b, c); nmod_poly_mul(c, b, c); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a1, a2, b, c, d; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a1, n); nmod_poly_init(a2, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_randtest(c, state, n_randint(state, 100)); nmod_poly_randtest(d, state, n_randint(state, 100)); nmod_poly_mul(a1, b, c); nmod_poly_mul(a2, b, d); nmod_poly_add(a1, a1, a2); nmod_poly_add(c, c, d); nmod_poly_mul(a2, b, c); result = (nmod_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a1), flint_printf("\n\n"); nmod_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mul_KS.c000066400000000000000000000061221461254215100202010ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mul_KS, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_KS(a, b, c, 0); nmod_poly_mul_KS(b, b, c, 0); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_KS(a, b, c, 0); nmod_poly_mul_KS(c, b, c, 0); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a1, a2, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a1, n); nmod_poly_init(a2, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_classical(a1, b, c); nmod_poly_mul_KS(a2, b, c, 0); result = (nmod_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a1), flint_printf("\n\n"); nmod_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mul_KS2.c000066400000000000000000000121061461254215100202620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #pragma GCC diagnostic ignored "-Woverlength-strings" TEST_FUNCTION_START(nmod_poly_mul_KS2, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_KS2(a, b, c); nmod_poly_mul_KS2(b, b, c); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_KS2(a, b, c); nmod_poly_mul_KS2(c, b, c); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a1, a2, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a1, n); nmod_poly_init(a2, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_classical(a1, b, c); nmod_poly_mul_KS2(a2, b, c); result = (nmod_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a1), flint_printf("\n\n"); nmod_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } /* Test bug */ #if FLINT64 { nmod_poly_t a, b, c, d; mp_limb_t mod = UWORD(2289285083314003039); nmod_poly_init(a, mod); nmod_poly_init(b, mod); nmod_poly_init(c, mod); nmod_poly_init(d, mod); nmod_poly_set_str(a, "33 2289285083314003039 1904046980750977501 45214318121847844 54776012950656710 1873599154826904295 870135259339956207 1979537227904177235 1077518167660740425 1914467488553877071 590032441505981152 615648453231634975 1569207985886566133 787136232386763586 263398180027397052 1072218041043012468 1506848477788670239 1400920451698857943 1647489479045838018 916805681536849287 418919486780459023 1905019227786610376 521214770020411309 1686949157600795332 1694792566051380615 859359964104912916 379633023194464188 1707896212900599917 2116886930226258819 1784312697572836983 1657809908840472396 187671865737908075 24295635882237532 1236324514297047805 1"); nmod_poly_set_str(b, "33 2289285083314003039 1248232897348310716 2007649684622883320 1745423566053694824 377131386390909586 510000530211074748 2252357745328136405 121845726568848648 1776552397423576952 1087867787512095029 1542258909416820365 333466255708033066 1369137418799234940 1019757368632255267 1708944472854199555 424720899313432606 1832061349660947209 1680133579237359807 1011480105427615896 469487889066997171 250011917413341143 1528554661920601095 1534412092525363608 1513772824610977843 1546061195142719878 2202390411223099645 1876123527101934779 777483746883723994 1298099847659446396 1845415258502877349 82593368833294076 7103430832858844 1414221645839662896 1"); nmod_poly_mul_classical(c, a, b); nmod_poly_mul_KS2(d, a, b); if (!nmod_poly_equal(c, d)) { flint_printf("FAIL: NMOD_RED2 bug!\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mul_KS4.c000066400000000000000000000120361461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #pragma GCC diagnostic ignored "-Woverlength-strings" TEST_FUNCTION_START(nmod_poly_mul_KS4, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_KS4(a, b, c); nmod_poly_mul_KS4(b, b, c); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_KS4(a, b, c); nmod_poly_mul_KS4(c, b, c); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a1, a2, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a1, n); nmod_poly_init(a2, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_classical(a1, b, c); nmod_poly_mul_KS4(a2, b, c); result = (nmod_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a1), flint_printf("\n\n"); nmod_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } /* Test bug */ #if FLINT64 { nmod_poly_t a, b, c, d; mp_limb_t mod = UWORD(2289285083314003039); nmod_poly_init(a, mod); nmod_poly_init(b, mod); nmod_poly_init(c, mod); nmod_poly_init(d, mod); nmod_poly_set_str(a, "33 1904046980750977501 45214318121847844 54776012950656710 1873599154826904295 870135259339956207 1979537227904177235 1077518167660740425 1914467488553877071 590032441505981152 615648453231634975 1569207985886566133 787136232386763586 263398180027397052 1072218041043012468 1506848477788670239 1400920451698857943 1647489479045838018 916805681536849287 418919486780459023 1905019227786610376 521214770020411309 1686949157600795332 1694792566051380615 859359964104912916 379633023194464188 1707896212900599917 2116886930226258819 1784312697572836983 1657809908840472396 187671865737908075 24295635882237532 1236324514297047805 1"); nmod_poly_set_str(b, "33 1248232897348310716 2007649684622883320 1745423566053694824 377131386390909586 510000530211074748 2252357745328136405 121845726568848648 1776552397423576952 1087867787512095029 1542258909416820365 333466255708033066 1369137418799234940 1019757368632255267 1708944472854199555 424720899313432606 1832061349660947209 1680133579237359807 1011480105427615896 469487889066997171 250011917413341143 1528554661920601095 1534412092525363608 1513772824610977843 1546061195142719878 2202390411223099645 1876123527101934779 777483746883723994 1298099847659446396 1845415258502877349 82593368833294076 7103430832858844 1414221645839662896 1"); nmod_poly_mul_classical(c, a, b); nmod_poly_mul_KS4(d, a, b); if (!nmod_poly_equal(c, d)) { flint_printf("FAIL: NMOD_RED2 bug!\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mul_classical.c000066400000000000000000000105201461254215100216170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mul_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_classical(a, b, c); nmod_poly_mul_classical(b, b, c); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_mul_classical(a, b, c); nmod_poly_mul_classical(c, b, c); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check (b*c)+(b*d) = b*(c+d) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a1, a2, b, c, d; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a1, n); nmod_poly_init(a2, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); nmod_poly_randtest(d, state, n_randint(state, 50)); nmod_poly_mul_classical(a1, b, c); nmod_poly_mul_classical(a2, b, d); nmod_poly_add(a1, a1, a2); nmod_poly_add(c, c, d); nmod_poly_mul_classical(a2, b, c); result = (nmod_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a1), flint_printf("\n\n"); nmod_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* check b^2 = b*b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a1, a2, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a1, n); nmod_poly_init(a2, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(a1, state, n_randint(state, 50)); nmod_poly_randtest(a2, state, n_randint(state, 50)); nmod_poly_set(c, b); nmod_poly_mul_classical(a1, b, b); nmod_poly_mul_classical(a2, b, c); result = (nmod_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL (squaring):\n"); nmod_poly_print(a1), flint_printf("\n\n"); nmod_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mulhigh.c000066400000000000000000000032141461254215100204430ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mulhigh, state) { int i, result; /* Compare with left truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; slong j, n; mp_limb_t m = n_randtest_not_zero(state); nmod_poly_init(a, m); nmod_poly_init(b, m); nmod_poly_init(c, m); n = n_randint(state, 50); nmod_poly_randtest(b, state, n); nmod_poly_randtest(c, state, n); nmod_poly_mulhigh(a, b, c, n); nmod_poly_mul(b, b, c); for (j = 0; j < n; j++) { if (j < a->length) a->coeffs[j] = 0; if (j < b->length) b->coeffs[j] = 0; } _nmod_poly_normalise(a); _nmod_poly_normalise(b); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mulhigh_classical.c000066400000000000000000000102711461254215100224620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mulhigh_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; slong j, start; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); start = n_randint(state, 50); nmod_poly_mulhigh_classical(a, b, c, start); nmod_poly_mulhigh_classical(b, b, c, start); for (j = 0; j < start; j++) { if (j < a->length) a->coeffs[j] = 0; if (j < b->length) b->coeffs[j] = 0; } _nmod_poly_normalise(a); _nmod_poly_normalise(b); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; slong j, start; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); start = n_randint(state, 50); nmod_poly_mulhigh_classical(a, b, c, start); nmod_poly_mulhigh_classical(c, b, c, start); for (j = 0; j < start; j++) { if (j < a->length) a->coeffs[j] = 0; if (j < c->length) c->coeffs[j] = 0; } _nmod_poly_normalise(a); _nmod_poly_normalise(c); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with mul_basecase */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; slong j, start; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); start = n_randint(state, 50); nmod_poly_mul_classical(a, b, c); nmod_poly_mulhigh_classical(d, b, c, start); for (j = 0; j < start; j++) { if (j < a->length) a->coeffs[j] = 0; if (j < d->length) d->coeffs[j] = 0; } _nmod_poly_normalise(a); _nmod_poly_normalise(d); result = (nmod_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mullow.c000066400000000000000000000026771461254215100203410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mullow, state) { int i, result; /* Compare with truncated product of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; slong trunc; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); trunc = n_randint(state, 50); nmod_poly_randtest(b, state, trunc); nmod_poly_randtest(c, state, trunc); nmod_poly_mullow(a, b, c, trunc); nmod_poly_mul(b, b, c); nmod_poly_truncate(b, trunc); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf(":\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mullow_KS.c000066400000000000000000000070321461254215100207240ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mullow_KS, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong trunc = 0; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); if (b->length > 0 && c->length > 0) trunc = n_randint(state, b->length + c->length); nmod_poly_mullow_KS(a, b, c, 0, trunc); nmod_poly_mullow_KS(b, b, c, 0, trunc); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong trunc = 0; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); if (b->length > 0 && c->length > 0) trunc = n_randint(state, b->length + c->length); nmod_poly_mullow_KS(a, b, c, 0, trunc); nmod_poly_mullow_KS(c, b, c, 0, trunc); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a1, a2, b, c; mp_limb_t n = n_randtest_not_zero(state); slong trunc = 0; nmod_poly_init(a1, n); nmod_poly_init(a2, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); if (b->length > 0 && c->length > 0) trunc = n_randint(state, b->length + c->length); nmod_poly_mullow_classical(a1, b, c, trunc); nmod_poly_mullow_KS(a2, b, c, 0, trunc); result = (nmod_poly_equal(a1, a2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a1), flint_printf("\n\n"); nmod_poly_print(a2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mullow_classical.c000066400000000000000000000077741461254215100223620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mullow_classical, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; slong len, trunc; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); len = b->length + c->length - 1; if (len <= 0) trunc = 0; else trunc = n_randint(state, b->length + c->length); nmod_poly_mullow_classical(a, b, c, trunc); nmod_poly_mullow_classical(b, b, c, trunc); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; slong len, trunc; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); len = b->length + c->length - 1; if (len <= 0) trunc = 0; else trunc = n_randint(state, b->length + c->length - 1); nmod_poly_mullow_classical(a, b, c, trunc); nmod_poly_mullow_classical(c, b, c, trunc); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with mul_basecase */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; slong len, trunc; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(b, state, n_randint(state, 50)); nmod_poly_randtest(c, state, n_randint(state, 50)); len = b->length + c->length - 1; if (len <= 0) trunc = 0; else trunc = n_randint(state, b->length + c->length - 1); if (n_randint(state, 2)) /* check squaring */ { nmod_poly_mul_classical(a, b, b); nmod_poly_truncate(a, trunc); nmod_poly_mullow_classical(d, b, b, trunc); } else { nmod_poly_mul_classical(a, b, c); nmod_poly_truncate(a, trunc); nmod_poly_mullow_classical(d, b, c, trunc); } result = (nmod_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mulmod.c000066400000000000000000000134521461254215100203100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mulmod, state) { int i, result; /* Aliasing res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res, a, b, f); nmod_poly_mulmod(a, a, b, f); result = (nmod_poly_equal(res, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res); nmod_poly_clear(t); } /* Aliasing res and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res, a, b, f); nmod_poly_mulmod(b, a, b, f); result = (nmod_poly_equal(res, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res); nmod_poly_clear(t); } /* Aliasing res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res, a, b, f); nmod_poly_mulmod(f, a, b, f); result = (nmod_poly_equal(res, f)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res); nmod_poly_clear(t); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res1, res2, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res1, a, b, f); nmod_poly_mul(res2, a, b); nmod_poly_divrem(t, res2, res2, f); result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-mulmod_preinv.c000066400000000000000000000215061461254215100216720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_mulmod_preinv, state) { int i, result; /* Aliasing res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res, t, f, finv; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); if (a->length >= f->length) nmod_poly_rem (a, a, f); if (b->length >= f->length) nmod_poly_rem (b, b, f); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_mulmod_preinv(res, a, b, f, finv); nmod_poly_mulmod_preinv(a, a, b, f, finv); result = (nmod_poly_equal(res, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res); nmod_poly_clear(t); } /* Aliasing res and b */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res, t, f, finv; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); if (a->length >= f->length) nmod_poly_rem (a, a, f); if (b->length >= f->length) nmod_poly_rem (b, b, f); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_mulmod_preinv(res, a, b, f, finv); nmod_poly_mulmod_preinv(b, a, b, f, finv); result = (nmod_poly_equal(res, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res); nmod_poly_clear(t); } /* Aliasing res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res, t, f, finv; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); if (a->length >= f->length) nmod_poly_rem (a, a, f); if (b->length >= f->length) nmod_poly_rem (b, b, f); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_mulmod_preinv(res, a, b, f, finv); nmod_poly_mulmod_preinv(f, a, b, f, finv); result = (nmod_poly_equal(res, f)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res); nmod_poly_clear(t); } /* Aliasing res and finv */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res, t, f, finv; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); if (a->length >= f->length) nmod_poly_rem (a, a, f); if (b->length >= f->length) nmod_poly_rem (b, b, f); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_mulmod_preinv(res, a, b, f, finv); nmod_poly_mulmod_preinv(finv, a, b, f, finv); result = (nmod_poly_equal(res, finv)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("finv:\n"); nmod_poly_print(finv), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res); nmod_poly_clear(t); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, res1, res2, t, f, finv; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); if (a->length >= f->length) nmod_poly_rem (a, a, f); if (b->length >= f->length) nmod_poly_rem (b, b, f); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_mulmod_preinv(res1, a, b, f, finv); nmod_poly_mul(res2, a, b); nmod_poly_divrem(t, res2, res2, f); result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b:\n"); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-multi_crt.c000066400000000000000000000345461461254215100210240ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_mpoly.h" TEST_FUNCTION_START(nmod_poly_multi_crt, state) { slong i, j, k; /* test internal interface */ { nmod_poly_multi_crt_t P; nmod_poly_struct ** moduli, ** inputs, * outputs; mp_limb_t modulus = 1009; slong moduli_count = 1000; moduli = (nmod_poly_struct **) flint_malloc(moduli_count*sizeof(nmod_poly_struct *)); inputs = (nmod_poly_struct **) flint_malloc(moduli_count*sizeof(nmod_poly_struct *)); outputs = (nmod_poly_struct *) flint_malloc(moduli_count*sizeof(nmod_poly_struct)); for (k = 0; k < moduli_count; k++) { moduli[k] = (nmod_poly_struct *) flint_malloc(sizeof(nmod_poly_struct)); inputs[k] = (nmod_poly_struct *) flint_malloc(sizeof(nmod_poly_struct)); nmod_poly_init(moduli[k], modulus); nmod_poly_init(inputs[k], modulus); nmod_poly_init(outputs + k, modulus); nmod_poly_set_coeff_ui(moduli[k], 1, 1); nmod_poly_set_coeff_ui(moduli[k], 0, modulus - k); nmod_poly_set_coeff_ui(inputs[k], 0, (k*k)^k); } nmod_poly_multi_crt_init(P); if (!nmod_poly_multi_crt_precompute_p(P, (const nmod_poly_struct * const *) moduli, moduli_count)) { printf("FAIL\n"); flint_printf("Check simple example\n"); fflush(stdout); flint_abort(); } FLINT_ASSERT(_nmod_poly_multi_crt_local_size(P) <= moduli_count); for (k = 0; k < 1; k++) { _nmod_poly_multi_crt_run_p(outputs, P, (const nmod_poly_struct * const *) inputs); } for (k = 0; k < moduli_count; k++) { nmod_poly_clear(moduli[k]); nmod_poly_clear(inputs[k]); nmod_poly_clear(outputs + k); flint_free(moduli[k]); flint_free(inputs[k]); } flint_free(moduli); flint_free(inputs); flint_free(outputs); nmod_poly_multi_crt_clear(P); } /* test pointer interface */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_multi_crt_t P; nmod_poly_t t, p; slong total_degree, moduli_length, moduli_count; nmod_poly_struct ** moduli, ** inputs; nmod_poly_t output; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_poly_init(t, modulus); nmod_poly_init(p, modulus); nmod_poly_init(output, modulus); nmod_poly_multi_crt_init(P); for (j = 0; j < 4; j++) { moduli_length = n_randint(state, 20) + 1; moduli_count = n_randint(state, 50) + 1; moduli = (nmod_poly_struct **) flint_malloc(moduli_count *sizeof(nmod_poly_struct *)); inputs = (nmod_poly_struct **) flint_malloc(moduli_count *sizeof(nmod_poly_struct *)); for (k = 0; k < moduli_count; k++) { moduli[k] = (nmod_poly_struct *) flint_malloc( sizeof(nmod_poly_struct)); inputs[k] = (nmod_poly_struct *) flint_malloc( sizeof(nmod_poly_struct)); nmod_poly_init(moduli[k], modulus); nmod_poly_init(inputs[k], modulus); nmod_poly_randtest(moduli[k], state, moduli_length); nmod_poly_randtest(inputs[k], state, moduli_length); } if (nmod_poly_multi_crt_precompute_p(P, (const nmod_poly_struct * const *) moduli, moduli_count)) { nmod_poly_multi_crt_precomp_p(output, P, (const nmod_poly_struct * const *) inputs); total_degree = 0; for (k = 0; k < moduli_count; k++) { total_degree += nmod_poly_degree(moduli[k]); nmod_poly_sub(t, output, inputs[k]); nmod_poly_rem(t, t, moduli[k]); if (!nmod_poly_is_zero(t)) { printf("FAIL\n"); flint_printf("Check remainder " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } if (nmod_poly_degree(output) >= total_degree) { printf("FAIL\n"); flint_printf("Check output degree " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } else { /* check if it was ok to fail on these moduli */ int ok = 0; nmod_poly_one(p); for (k = 0; !ok && k < moduli_count; k++) { nmod_poly_mul(p, p, moduli[k]); if (nmod_poly_degree(moduli[k]) < 1) { ok = 1; } } for (k = 0; !ok && k < moduli_count; k++) { nmod_poly_div(t, p, moduli[k]); nmod_poly_gcd(t, t, moduli[k]); if (nmod_poly_degree(t) > 0) { ok = 1; } } if (!ok) { printf("FAIL\n"); flint_printf("Check crt failure i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < moduli_count; k++) { nmod_poly_clear(moduli[k]); nmod_poly_clear(inputs[k]); flint_free(moduli[k]); flint_free(inputs[k]); } flint_free(moduli); flint_free(inputs); } nmod_poly_clear(t); nmod_poly_clear(p); nmod_poly_clear(output); nmod_poly_multi_crt_clear(P); } /* test flat interface */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_multi_crt_t P; nmod_poly_t t, p; slong total_degree, moduli_length, moduli_count; nmod_poly_struct * moduli, * inputs; nmod_poly_t output; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_poly_init(t, modulus); nmod_poly_init(p, modulus); nmod_poly_init(output, modulus); nmod_poly_multi_crt_init(P); for (j = 0; j < 4; j++) { moduli_length = n_randint(state, 20) + 1; moduli_count = n_randint(state, 50) + 1; moduli = (nmod_poly_struct *) flint_malloc(moduli_count *sizeof(nmod_poly_struct)); inputs = (nmod_poly_struct *) flint_malloc(moduli_count *sizeof(nmod_poly_struct)); for (k = 0; k < moduli_count; k++) { nmod_poly_init(moduli + k, modulus); nmod_poly_init(inputs + k, modulus); nmod_poly_randtest(moduli + k, state, moduli_length); nmod_poly_randtest(inputs + k, state, moduli_length); } if (nmod_poly_multi_crt_precompute(P, moduli, moduli_count)) { nmod_poly_multi_crt_precomp(output, P, inputs); total_degree = 0; for (k = 0; k < moduli_count; k++) { total_degree += nmod_poly_degree(moduli + k); nmod_poly_sub(t, output, inputs + k); nmod_poly_rem(t, t, moduli + k); if (!nmod_poly_is_zero(t)) { printf("FAIL\n"); flint_printf("Check remainder flat " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } if (nmod_poly_degree(output) >= total_degree) { printf("FAIL\n"); flint_printf("Check output degree flat " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } else { /* check if it was ok to fail on these moduli */ int ok = 0; nmod_poly_one(p); for (k = 0; !ok && k < moduli_count; k++) { nmod_poly_mul(p, p, moduli + k); if (nmod_poly_degree(moduli + k) < 1) { ok = 1; } } for (k = 0; !ok && k < moduli_count; k++) { nmod_poly_div(t, p, moduli + k); nmod_poly_gcd(t, t, moduli + k); if (nmod_poly_degree(t) > 0) { ok = 1; } } if (!ok) { printf("FAIL\n"); flint_printf("Check flat crt failure i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < moduli_count; k++) { nmod_poly_clear(moduli + k); nmod_poly_clear(inputs + k); } flint_free(moduli); flint_free(inputs); } nmod_poly_clear(t); nmod_poly_clear(p); nmod_poly_clear(output); nmod_poly_multi_crt_clear(P); } /* test lazy interface */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t t, p; slong total_degree, moduli_length, moduli_count; nmod_poly_struct * moduli, * inputs; nmod_poly_t output; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 1) + 1; modulus = n_randbits(state, modulus); modulus = n_nextprime(modulus, 1); nmod_poly_init(t, modulus); nmod_poly_init(p, modulus); nmod_poly_init(output, modulus); for (j = 0; j < 4; j++) { moduli_length = n_randint(state, 20) + 1; moduli_count = n_randint(state, 50) + 1; moduli = (nmod_poly_struct *) flint_malloc(moduli_count *sizeof(nmod_poly_struct)); inputs = (nmod_poly_struct *) flint_malloc(moduli_count *sizeof(nmod_poly_struct)); for (k = 0; k < moduli_count; k++) { nmod_poly_init(moduli + k, modulus); nmod_poly_init(inputs + k, modulus); nmod_poly_randtest(moduli + k, state, moduli_length); nmod_poly_randtest(inputs + k, state, moduli_length); } if (nmod_poly_multi_crt(output, moduli, inputs, moduli_count)) { total_degree = 0; for (k = 0; k < moduli_count; k++) { total_degree += nmod_poly_degree(moduli + k); nmod_poly_sub(t, output, inputs + k); nmod_poly_rem(t, t, moduli + k); if (!nmod_poly_is_zero(t)) { printf("FAIL\n"); flint_printf("Check remainder lazy " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } if (nmod_poly_degree(output) >= total_degree) { printf("FAIL\n"); flint_printf("Check output degree lazy " "i = %wd, j = %wd, k = %wd\n", i, j, k); fflush(stdout); flint_abort(); } } else { /* check if it was ok to fail on these moduli */ int ok = 0; nmod_poly_one(p); for (k = 0; !ok && k < moduli_count; k++) { nmod_poly_mul(p, p, moduli + k); if (nmod_poly_degree(moduli + k) < 1) { ok = 1; } } for (k = 0; !ok && k < moduli_count; k++) { nmod_poly_div(t, p, moduli + k); nmod_poly_gcd(t, t, moduli + k); if (nmod_poly_degree(t) > 0) { ok = 1; } } if (!ok) { printf("FAIL\n"); flint_printf("Check lazy crt failure i = %wd, j = %wd\n", i, j); fflush(stdout); flint_abort(); } } for (k = 0; k < moduli_count; k++) { nmod_poly_clear(moduli + k); nmod_poly_clear(inputs + k); } flint_free(moduli); flint_free(inputs); } nmod_poly_clear(t); nmod_poly_clear(p); nmod_poly_clear(output); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-neg.c000066400000000000000000000024561461254215100175660ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_neg, state) { int i, result; /* Check neg neg a == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_neg(b, a); nmod_poly_neg(b, b); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-pow.c000066400000000000000000000050361461254215100176170ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_pow, state) { int i, j, result; /* Check powering against naive method */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); nmod_poly_pow(b, a, e); nmod_poly_set_coeff_ui(c, 0, 1); for (j = 0; j < e; j++) nmod_poly_mul(c, c, a); result = nmod_poly_equal(b, c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd\n", a->length, a->mod.n, e); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); nmod_poly_pow(b, a, e); nmod_poly_set(c, a); nmod_poly_pow(c, c, e); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd\n", a->length, a->mod.n, e); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-pow_binexp.c000066400000000000000000000052151461254215100211630ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_pow_binexp, state) { int i, j, result; /* Check powering against naive method */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); nmod_poly_pow_binexp(b, a, e); nmod_poly_set_coeff_ui(c, 0, 1); for (j = 0; j < e; j++) nmod_poly_mul(c, c, a); result = (nmod_poly_equal(b, c) || (a->length == 0 && e == 0 && c->length == 1 && c->coeffs[0] == 1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd\n", a->length, a->mod.n, e); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); nmod_poly_pow_binexp(b, a, e); nmod_poly_set(c, a); nmod_poly_pow_binexp(c, c, e); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd\n", a->length, a->mod.n, e); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-pow_trunc.c000066400000000000000000000054261461254215100210350ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_pow_trunc, state) { int i, result; /* Check powering against naive method */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e, trunc; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); trunc = n_randint(state, 30); nmod_poly_pow_trunc(b, a, e, trunc); nmod_poly_pow(c, a, e); nmod_poly_truncate(c, trunc); result = (nmod_poly_equal(b, c) || (a->length == 0 && e == 0 && c->length == 1 && c->coeffs[0] == 1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd, trunc = %wd\n", a->length, a->mod.n, e, trunc); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e, trunc; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); trunc = n_randint(state, 30); nmod_poly_pow_trunc(b, a, e, trunc); nmod_poly_set(c, a); nmod_poly_pow_trunc(c, c, e, trunc); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd, trunc = %wd\n", a->length, a->mod.n, e, trunc); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-pow_trunc_binexp.c000066400000000000000000000054621461254215100224020ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_pow_trunc_binexp, state) { int i, result; /* Check powering against naive method */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e, trunc; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); trunc = n_randint(state, 30); nmod_poly_pow_trunc_binexp(b, a, e, trunc); nmod_poly_pow(c, a, e); nmod_poly_truncate(c, trunc); result = (nmod_poly_equal(b, c) || (a->length == 0 && e == 0 && c->length == 1 && c->coeffs[0] == 1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd, trunc = %wd\n", a->length, a->mod.n, e, trunc); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong e, trunc; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); e = n_randint(state, 20); trunc = n_randint(state, 30); nmod_poly_pow_trunc_binexp(b, a, e, trunc); nmod_poly_set(c, a); nmod_poly_pow_trunc_binexp(c, c, e, trunc); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu, exp = %wd, trunc = %wd\n", a->length, a->mod.n, e, trunc); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-power_sums.c000066400000000000000000000054221461254215100212140ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_power_sums, state) { int i, result; /* Check that the different version coincide and aliasing in nmod_poly_power_sums */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { mp_limb_t n; nmod_poly_t a, b, c, d, e; do{ n = n_randtest_prime(state, 1); }while(n < 10); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_init(e, n); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 10)); nmod_poly_power_sums_naive(b, a, 20); nmod_poly_power_sums_schoenhage(c, a, 20); nmod_poly_power_sums(d, a, 20); nmod_poly_set(e, a); nmod_poly_power_sums(e, e, 20); result = nmod_poly_equal(b, c) && nmod_poly_equal(b, d) && nmod_poly_equal(b, e); if (!result) { flint_printf ("FAIL: PowerSums(p1 p2) = PowerSums(p1) + PowerSums(p2)\n"); flint_printf("a = "), nmod_poly_print(a), flint_printf("\n"); flint_printf("b = "), nmod_poly_print(b), flint_printf("\n"); flint_printf("c = "), nmod_poly_print(c), flint_printf("\n"); flint_printf("d = "), nmod_poly_print(d), flint_printf("\n"); flint_printf("e = "), nmod_poly_print(e), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_make_monic(a, a); nmod_poly_power_sums_to_poly_schoenhage(b, b); nmod_poly_power_sums_to_poly(d, c); nmod_poly_power_sums_to_poly(c, c); result = nmod_poly_equal(a, b) && nmod_poly_equal(a, c) && nmod_poly_equal(a, d); if (!result) { flint_printf("FAIL: power_sums_to_poly\n"); flint_printf("e = "), nmod_poly_print(e), flint_printf("\n"); flint_printf("a = "), nmod_poly_print(a), flint_printf("\n"); flint_printf("b = "), nmod_poly_print(b), flint_printf("\n"); flint_printf("c = "), nmod_poly_print(c), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); nmod_poly_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-power_sums_naive.c000066400000000000000000000156271461254215100224060ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_power_sums_naive, state) { int l, result; mp_limb_t i, j, k, tot; /* Check that it is valid in degree 3 with integer roots, ie */ /* for polynomials of the form (x-i)(x-j)(x-k) */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { mp_limb_t n; nmod_t mod; nmod_poly_t a, b, c, d; do { n = n_randtest_prime(state, 1); } while(n < 4); nmod_init(&mod, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(b, state, 40); nmod_poly_randtest(c, state, 40); nmod_poly_randtest(d, state, 40); nmod_poly_set_coeff_ui(a, 0, nmod_neg((i*j*k) % n, mod)); nmod_poly_set_coeff_ui(a, 1, i * j + i * k + j * k); nmod_poly_set_coeff_ui(a, 2, nmod_neg((i + j + k) % n, mod)); nmod_poly_set_coeff_ui(a, 3, 1); nmod_poly_power_sums_naive(b, a, 20); nmod_poly_set(d, a); nmod_poly_power_sums_naive(d, d, 20); for (l = 0; l < FLINT_MIN(20, nmod_poly_length(b)); l++) { tot = nmod_add(nmod_pow_ui(i, l, mod), nmod_pow_ui(j, l, mod), mod); tot = nmod_add(tot, nmod_pow_ui(k, l, mod), mod); result = nmod_poly_get_coeff_ui(b, l) == tot && nmod_poly_get_coeff_ui(d, l) == tot; if (!result) { flint_printf("FAIL: power sums integral root\n"); flint_printf("%d %d %d %d\n", i, j, k, l); flint_printf("a = "), nmod_poly_print(a), flint_printf("\n"); flint_printf("b = "), nmod_poly_print(b), flint_printf("\n"); flint_printf("d = "), nmod_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_poly_power_sums_to_poly_naive(c, b); nmod_poly_set(d, b); nmod_poly_power_sums_to_poly_naive(d, d); result = nmod_poly_equal(a, c) && nmod_poly_equal(a, d); if (!result) { flint_printf("FAIL: power sums to poly naive\n"); flint_printf("a = "), nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), nmod_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), nmod_poly_print(c), flint_printf("\n\n"); flint_printf("d = "), nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Check that going back and forth between the power sums representation gives the identity */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t n; do{ n = n_randtest_prime(state, 1); }while(n < 50); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(c, state, 50); nmod_poly_randtest(d, state, 50); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 20)); nmod_poly_make_monic(a, a); nmod_poly_power_sums_naive(b, a, 30); nmod_poly_power_sums_to_poly_naive(c, b); nmod_poly_set(d, a); nmod_poly_power_sums_naive(d, d, 30); nmod_poly_power_sums_to_poly_naive(d, d); result = nmod_poly_equal(a, c) && nmod_poly_equal(a, d); if (!result) { flint_printf("FAIL: power sums - power sums to poly\n"); flint_printf("a = "), nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b = "), nmod_poly_print(b), flint_printf("\n\n"); flint_printf("c = "), nmod_poly_print(c), flint_printf("\n\n"); flint_printf("d = "), nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Check that the product of polynomials correspond to the sum of Power sums series */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t n; do{ n = n_randtest_prime(state, 1); }while(n < 20); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 10)); nmod_poly_randtest_not_zero(b, state, 1 + n_randint(state, 10)); nmod_poly_randtest(c, state, 30); nmod_poly_randtest(d, state, 30); nmod_poly_mul(c, a, b); nmod_poly_power_sums_naive(c, c, 20); /* NOTE: the code path is not the same if the polynomial is monic. We let only a be monic */ nmod_poly_make_monic(a, a); nmod_poly_power_sums_naive(a, a, 20); nmod_poly_power_sums_naive(b, b, 20); nmod_poly_add(d, a, b); result = nmod_poly_equal(c, d); if (!result) { flint_printf ("FAIL: PowerSums(p1 p2) = PowerSums(p1) + PowerSums(p2)\n"); flint_printf("a = "); nmod_poly_print(a), flint_printf("\n"); flint_printf("b = "); nmod_poly_print(b), flint_printf("\n"); flint_printf("c = "); nmod_poly_print(c), flint_printf("\n"); flint_printf("d = "); nmod_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-power_sums_schoenhage.c000066400000000000000000000154611461254215100234040ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_power_sums_schoenhage, state) { int l, result; mp_limb_t i, j, k, tot; /* Check that it is valid in degree 3 with integer roots, ie */ /* for polynomials of the form (x-i)(x-j)(x-k) */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { mp_limb_t n; nmod_t mod; nmod_poly_t a, b, c, d; do { n = n_randtest_prime(state, 1); } while(n < 4); nmod_init(&mod, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(b, state, 40); nmod_poly_randtest(c, state, 40); nmod_poly_randtest(d, state, 40); nmod_poly_set_coeff_ui(a, 0, nmod_neg((i*j*k) % n, mod)); nmod_poly_set_coeff_ui(a, 1, i * j + i * k + j * k); nmod_poly_set_coeff_ui(a, 2, nmod_neg((i + j + k) % n, mod)); nmod_poly_set_coeff_ui(a, 3, 1); nmod_poly_power_sums_schoenhage(b, a, 20); nmod_poly_set(d, a); nmod_poly_power_sums_naive(d, d, 20); for (l = 0; l < FLINT_MIN(20, nmod_poly_length(b)); l++) { tot = nmod_add(nmod_pow_ui(i, l, mod), nmod_pow_ui(j, l, mod), mod); tot = nmod_add(tot, nmod_pow_ui(k, l, mod), mod); result = nmod_poly_get_coeff_ui(b, l) == tot && nmod_poly_get_coeff_ui(d, l) == tot; if (!result) { flint_printf("FAIL: power sums integral root\n"); flint_printf("%d %d %d %d\n", i, j, k, l); flint_printf("a = "), nmod_poly_print(a), flint_printf("\n"); flint_printf("b = "), nmod_poly_print(b), flint_printf("\n"); flint_printf("d = "), nmod_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_poly_power_sums_to_poly_schoenhage(c, b); nmod_poly_set(d, b); nmod_poly_power_sums_to_poly_schoenhage(d, d); result = nmod_poly_equal(a, c) && nmod_poly_equal(a, d); if (!result) { flint_printf("FAIL: power sums to poly schoenhage\n"); flint_printf("a = "); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b = "); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("c = "); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Check that going back and forth between the power sums representation gives the identity */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t n; do{ n = n_randtest_prime(state, 1); }while(n < 50); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(c, state, 50); nmod_poly_randtest(d, state, 50); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 20)); nmod_poly_make_monic(a, a); nmod_poly_power_sums_schoenhage(b, a, 30); nmod_poly_power_sums_to_poly_schoenhage(c, b); nmod_poly_set(d, a); nmod_poly_power_sums_schoenhage(d, d, 30); nmod_poly_power_sums_to_poly_schoenhage(d, d); result = nmod_poly_equal(a, c) && nmod_poly_equal(a, d); if (!result) { flint_printf("FAIL: power sums - power sums to poly\n"); flint_printf("a = "); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("b = "); nmod_poly_print(b), flint_printf("\n\n"); flint_printf("c = "); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Check that the product of polynomials correspond to the sum of Power sums series */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t n; do{ n = n_randtest_prime(state, 1); }while(n < 20); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 10)); nmod_poly_randtest_not_zero(b, state, 1 + n_randint(state, 10)); nmod_poly_randtest(c, state, 30); nmod_poly_randtest(d, state, 30); nmod_poly_mul(c, a, b); nmod_poly_power_sums_schoenhage(c, c, 20); /* NOTE: the code path is not the same if the polynomial is monic. We let only a be monic */ nmod_poly_make_monic(a, a); nmod_poly_power_sums_schoenhage(a, a, 20); nmod_poly_power_sums_schoenhage(b, b, 20); nmod_poly_add(d, a, b); result = nmod_poly_equal(c, d); if (!result) { flint_printf ("FAIL: PowerSums(p1 p2) = PowerSums(p1) + PowerSums(p2)\n"); flint_printf("a = "); nmod_poly_print(a), flint_printf("\n"); flint_printf("b = "); nmod_poly_print(b), flint_printf("\n"); flint_printf("c = "); nmod_poly_print(c), flint_printf("\n"); flint_printf("d = "); nmod_poly_print(d), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-powers_mod_bsgs.c000066400000000000000000000046571461254215100222160ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_powers_mod_bsgs, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i, result, max_threads = 5; /* Compare with powmod */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t f, g, pow; nmod_poly_struct * res; mp_limb_t n; ulong exp; slong j; flint_set_num_threads(n_randint(state, max_threads)); n = n_randtest_prime(state, 0); exp = n_randint(state, 32); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_init(pow, n); res = (nmod_poly_struct *) flint_malloc(exp*sizeof(nmod_poly_struct)); for (j = 0; j < exp; j++) nmod_poly_init(res + j, n); nmod_poly_randtest(f, state, n_randint(state, 50)); do { nmod_poly_randtest(g, state, n_randint(state, 50)); } while (nmod_poly_is_zero(g)); nmod_poly_powers_mod_bsgs(res, f, exp, g); result = 1; j = 0; if (exp > 0) { nmod_poly_one(pow); result = nmod_poly_equal(res + 0, pow); } for (j = 1 ; j < exp && result; j++) { nmod_poly_mulmod(pow, pow, f, g); result &= nmod_poly_equal(res + j, pow); } j--; if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("g:\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("j: %w\n", j); flint_printf("pow:\n"); nmod_poly_print(pow), flint_printf("\n\n"); flint_printf("res[%w]:\n", j); nmod_poly_print(res + j), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(pow); for (j = 0; j < exp; j++) nmod_poly_clear(res + j); flint_free(res); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/nmod_poly/test/t-powers_mod_naive.c000066400000000000000000000045511461254215100223530ustar00rootroot00000000000000/* Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_powers_mod_naive, state) { int i, result; /* Compare with powmod */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t f, g, pow; nmod_poly_struct * res; mp_limb_t n; ulong exp; slong j; n = n_randtest_prime(state, 0); exp = n_randint(state, 32); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_init(pow, n); res = (nmod_poly_struct *) flint_malloc(exp*sizeof(nmod_poly_struct)); for (j = 0; j < exp; j++) nmod_poly_init(res + j, n); nmod_poly_randtest(f, state, n_randint(state, 50)); do { nmod_poly_randtest(g, state, n_randint(state, 50)); } while (nmod_poly_is_zero(g)); nmod_poly_powers_mod_naive(res, f, exp, g); result = 1; j = 0; if (exp > 0) { nmod_poly_one(pow); result = nmod_poly_equal(res + 0, pow); } for (j = 1 ; j < exp && result; j++) { nmod_poly_mulmod(pow, pow, f, g); result &= nmod_poly_equal(res + j, pow); } j--; if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("g:\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("j: %w\n", j); flint_printf("pow:\n"); nmod_poly_print(pow), flint_printf("\n\n"); flint_printf("res[%w]:\n", j); nmod_poly_print(res + j), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(pow); for (j = 0; j < exp; j++) nmod_poly_clear(res + j); flint_free(res); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000121631461254215100227170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" TEST_FUNCTION_START(nmod_poly_powmod_fmpz_binexp, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1);; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_powmod_fmpz_binexp(res1, a, exp, f); nmod_poly_powmod_fmpz_binexp(a, a, exp, f); result = (nmod_poly_equal(res1, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_powmod_fmpz_binexp(res1, a, exp, f); nmod_poly_powmod_fmpz_binexp(f, a, exp, f); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(t); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f; mp_limb_t n; fmpz_t exp; int j; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_powmod_fmpz_binexp(res1, a, exp, f); if (fmpz_cmp_ui(exp, 32) <= 0) { nmod_poly_zero(res2); if (nmod_poly_length(f) > 1) nmod_poly_set_coeff_ui(res2, 0, 1); for (j = 1; j <= fmpz_get_ui(exp); j++) nmod_poly_mulmod(res2, res2, a, f); } else { fmpz_sub_ui(exp, exp, 1); nmod_poly_powmod_fmpz_binexp(res2, a, exp, f); nmod_poly_mulmod(res2, res2, a, f); fmpz_add_ui(exp, exp, 1); } result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000156561461254215100243140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" TEST_FUNCTION_START(nmod_poly_powmod_fmpz_binexp_preinv, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_fmpz_binexp_preinv(res1, a, exp, f, finv); nmod_poly_powmod_fmpz_binexp_preinv(a, a, exp, f, finv); result = (nmod_poly_equal(res1, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_fmpz_binexp_preinv(res1, a, exp, f, finv); nmod_poly_powmod_fmpz_binexp_preinv(f, a, exp, f, finv); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and finv */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_fmpz_binexp_preinv(res1, a, exp, f, finv); nmod_poly_powmod_fmpz_binexp_preinv(finv, a, exp, f, finv); result = (nmod_poly_equal(res1, finv)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("finv:\n"); nmod_poly_print(finv), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f, finv; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1);; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_fmpz_binexp_preinv(res1, a, exp, f, finv); nmod_poly_powmod_fmpz_binexp(res2, a, exp, f); result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-powmod_ui_binexp.c000066400000000000000000000110071461254215100223540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_powmod_ui_binexp, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_powmod_ui_binexp(res1, a, exp, f); nmod_poly_powmod_ui_binexp(a, a, exp, f); result = (nmod_poly_equal(res1, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_powmod_ui_binexp(res1, a, exp, f); nmod_poly_powmod_ui_binexp(f, a, exp, f); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(t); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f; mp_limb_t n; ulong exp; int j; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_powmod_ui_binexp(res1, a, exp, f); nmod_poly_zero(res2); if (nmod_poly_length(f) > 1) nmod_poly_set_coeff_ui(res2, 0, 1); for (j = 1; j <= exp; j++) nmod_poly_mulmod(res2, res2, a, f); result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000151551461254215100237470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_powmod_ui_binexp_preinv, state) { int i, result; /* Aliasing of res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_ui_binexp_preinv(res1, a, exp, f, finv); nmod_poly_powmod_ui_binexp_preinv(a, a, exp, f, finv); result = (nmod_poly_equal(res1, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_ui_binexp_preinv(res1, a, exp, f, finv); nmod_poly_powmod_ui_binexp_preinv(f, a, exp, f, finv); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and finv */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_ui_binexp_preinv(res1, a, exp, f, finv); nmod_poly_powmod_ui_binexp_preinv(finv, a, exp, f, finv); result = (nmod_poly_equal(res1, finv)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("finv:\n"); nmod_poly_print(finv), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f, finv; mp_limb_t n; ulong exp; int j; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(a, n); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_ui_binexp_preinv(res1, a, exp, f, finv); nmod_poly_zero(res2); if (nmod_poly_length(f) > 1) nmod_poly_set_coeff_ui(res2, 0, 1); for (j = 1; j <= exp; j++) nmod_poly_mulmod(res2, res2, a, f); result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000120061461254215100232600ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "fmpz.h" TEST_FUNCTION_START(nmod_poly_powmod_x_fmpz_preinv, state) { int i, result; /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f, finv; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_init2(a, n, f->length-1); nmod_poly_set_coeff_ui(a, 1, 1); nmod_poly_powmod_x_fmpz_preinv(res1, exp, f, finv); nmod_poly_powmod_fmpz_binexp_preinv(res2, a, exp, f, finv); result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t res1, t, f, finv; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_x_fmpz_preinv(res1, exp, f, finv); nmod_poly_powmod_x_fmpz_preinv(f, exp, f, finv); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL: aliasing1\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and finv */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t res1, t, f, finv; mp_limb_t n; fmpz_t exp; fmpz_init(exp); n = n_randtest_prime(state, 0); fmpz_randtest_unsigned(exp, state, n_randint(state, 100) + 1); nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_x_fmpz_preinv(res1, exp, f, finv); nmod_poly_powmod_x_fmpz_preinv(finv, exp, f, finv); result = (nmod_poly_equal(res1, finv)); if (!result) { flint_printf("FAIL: aliasing2\n"); flint_printf("exp: "); fmpz_print(exp); flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("finv:\n"); nmod_poly_print(finv), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } fmpz_clear(exp); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-powmod_x_ui_preinv.c000066400000000000000000000112101461254215100227150ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_powmod_x_ui_preinv, state) { int i, result; /* No aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f, finv; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_init2 (a, n, f->length-1); nmod_poly_set_coeff_ui (a, 1, 1); nmod_poly_powmod_x_ui_preinv(res1, exp, f, finv); nmod_poly_powmod_ui_binexp_preinv (res2, a, exp, f, finv); result = (nmod_poly_equal(res1, res2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("a:\n"); nmod_poly_print(a), flint_printf("\n\n"); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); flint_printf("res2:\n"); nmod_poly_print(res2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } /* Aliasing of res and f */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t res1, t, f, finv; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_x_ui_preinv(res1, exp, f, finv); nmod_poly_powmod_x_ui_preinv(f, exp, f, finv); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } /* Aliasing of res and finv */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t res1, t, f, finv; mp_limb_t n; ulong exp; n = n_randtest_prime(state, 0); exp = n_randlimb(state) % 32; nmod_poly_init(f, n); nmod_poly_init(finv, n); nmod_poly_init(res1, n); nmod_poly_init(t, n); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_x_ui_preinv(res1, exp, f, finv); nmod_poly_powmod_x_ui_preinv(finv, exp, f, finv); result = (nmod_poly_equal(res1, finv)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp: %wu\n\n", exp); flint_printf("f:\n"); nmod_poly_print(f), flint_printf("\n\n"); flint_printf("finv:\n"); nmod_poly_print(finv), flint_printf("\n\n"); flint_printf("res1:\n"); nmod_poly_print(res1), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-product_roots_nmod_vec.c000066400000000000000000000033461461254215100235740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_product_roots_nmod_vec, state) { int i, result; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t P, Q, tmp; mp_ptr x; mp_limb_t mod; slong j, n; n = n_randint(state, 100); mod = n_randtest_prime(state, 0); nmod_poly_init(P, mod); nmod_poly_init(Q, mod); nmod_poly_init(tmp, mod); x = _nmod_vec_init(n); _nmod_vec_randtest(x, state, n, P->mod); nmod_poly_product_roots_nmod_vec(P, x, n); nmod_poly_set_coeff_ui(Q, 0, UWORD(1)); for (j = 0; j < n; j++) { nmod_poly_zero(tmp); nmod_poly_set_coeff_ui(tmp, 1, UWORD(1)); nmod_poly_set_coeff_ui(tmp, 0, n_negmod(x[j], mod)); nmod_poly_mul(Q, Q, tmp); } result = (nmod_poly_equal(P, Q)); if (!result) { flint_printf("FAIL (P != Q):\n"); nmod_poly_print(P), flint_printf("\n\n"); nmod_poly_print(Q), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); nmod_poly_clear(tmp); _nmod_vec_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-rem.c000066400000000000000000000123221461254215100175710ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_rem, state) { int i, result; /* Check result of rem */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, r, prod; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q, n); nmod_poly_init(r, n); nmod_poly_init(prod, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_div(q, a, b); nmod_poly_rem(r, a, b); nmod_poly_mul(prod, q, b); nmod_poly_add(prod, prod, r); result = (nmod_poly_equal(a, prod)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(prod), flint_printf("\n\n"); nmod_poly_print(q), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(prod); } /* Check aliasing of a and r */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_rem(r, a, b); nmod_poly_rem(a, a, b); result = (nmod_poly_equal(a, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r); } /* Check aliasing of b and r */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, r; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(r, n); nmod_poly_randtest(a, state, n_randint(state, 2000)); do nmod_poly_randtest(b, state, n_randint(state, 2000)); while (b->length == 0); nmod_poly_rem(r, a, b); nmod_poly_rem(b, a, b); result = (nmod_poly_equal(b, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r); } /* Check result of rem_q1 */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q0, r0, r; mp_limb_t n = n_randprime(state, n_randint(state,FLINT_BITS-1)+2, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(q0, n); nmod_poly_init(r0, n); nmod_poly_init(r, n); do nmod_poly_randtest(a, state, n_randint(state, 1000)); while (a->length < 2); nmod_poly_fit_length(b, a->length - 1); flint_mpn_zero(b->coeffs, a->length - 1); nmod_poly_randtest_not_zero(b, state, n_randint(state, 1000) + 1); do b->coeffs[a->length - 2] = n_randint(state, n); while (b->coeffs[a->length - 2] == 0); b->length = a->length - 1; nmod_poly_divrem(q0, r0, a, b); nmod_poly_rem(r, a, b); result = (nmod_poly_equal(r0, r)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(q0), flint_printf("\n\n"); nmod_poly_print(r0), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q0); nmod_poly_clear(r0); nmod_poly_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-resultant.c000066400000000000000000000057441461254215100210410ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_resultant, state) { int i, result; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t f, g; mp_limb_t x, y; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_randtest(f, state, n_randint(state, 200)); nmod_poly_randtest(g, state, n_randint(state, 200)); x = nmod_poly_resultant(f, g); y = nmod_poly_resultant(g, f); if ((nmod_poly_degree(f) * nmod_poly_degree(g)) % 2) y = nmod_neg(y, f->mod); result = (x == y); if (!result) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("n = %wu\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h; mp_limb_t x, y, z; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_init(h, n); nmod_poly_randtest(f, state, n_randint(state, 200)); nmod_poly_randtest(g, state, n_randint(state, 200)); nmod_poly_randtest(h, state, n_randint(state, 200)); y = nmod_poly_resultant(f, g); z = nmod_poly_resultant(h, g); y = nmod_mul(y, z, f->mod); nmod_poly_mul(f, f, h); x = nmod_poly_resultant(f, g); result = (x == y); if (!result) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); nmod_poly_print(h), flint_printf("\n\n"); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("z = %wd\n", z); flint_printf("n = %wu\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-resultant_euclidean.c000066400000000000000000000060401461254215100230400ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_resultant_euclidean, state) { int i, result; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t f, g; mp_limb_t x, y; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_randtest(f, state, n_randint(state, 200)); nmod_poly_randtest(g, state, n_randint(state, 200)); x = nmod_poly_resultant_euclidean(f, g); y = nmod_poly_resultant_euclidean(g, f); if ((nmod_poly_degree(f) * nmod_poly_degree(g)) % 2) y = nmod_neg(y, f->mod); result = (x == y); if (!result) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("n = %wu\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h; mp_limb_t x, y, z; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_init(h, n); nmod_poly_randtest(f, state, n_randint(state, 200)); nmod_poly_randtest(g, state, n_randint(state, 200)); nmod_poly_randtest(h, state, n_randint(state, 200)); y = nmod_poly_resultant_euclidean(f, g); z = nmod_poly_resultant_euclidean(h, g); y = nmod_mul(y, z, f->mod); nmod_poly_mul(f, f, h); x = nmod_poly_resultant_euclidean(f, g); result = (x == y); if (!result) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); nmod_poly_print(h), flint_printf("\n\n"); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("z = %wd\n", z); flint_printf("n = %wu\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-resultant_hgcd.c000066400000000000000000000060031461254215100220130ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_resultant_hgcd, state) { int i, result; /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t f, g; mp_limb_t x, y; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_randtest(f, state, n_randint(state, 200)); nmod_poly_randtest(g, state, n_randint(state, 200)); x = nmod_poly_resultant_hgcd(f, g); y = nmod_poly_resultant_hgcd(g, f); if ((nmod_poly_degree(f) * nmod_poly_degree(g)) % 2) y = nmod_neg(y, f->mod); result = (x == y); if (!result) { flint_printf("FAIL (res(f, g) == (-1)^(deg f deg g) res(g, f)):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("n = %wu\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Check res(f h, g) == res(f, g) res(h, g) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h; mp_limb_t x, y, z; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(f, n); nmod_poly_init(g, n); nmod_poly_init(h, n); nmod_poly_randtest(f, state, n_randint(state, 600)); nmod_poly_randtest(g, state, n_randint(state, 600)); nmod_poly_randtest(h, state, n_randint(state, 600)); y = nmod_poly_resultant_hgcd(f, g); z = nmod_poly_resultant_hgcd(h, g); y = nmod_mul(y, z, f->mod); nmod_poly_mul(f, f, h); x = nmod_poly_resultant_hgcd(f, g); result = (x == y); if (!result) { flint_printf("FAIL (res(f h, g) == res(f, g) res(h, g)):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); nmod_poly_print(h), flint_printf("\n\n"); flint_printf("x = %wu\n", x); flint_printf("y = %wu\n", y); flint_printf("z = %wd\n", z); flint_printf("n = %wu\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-reverse.c000066400000000000000000000043301461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_reverse, state) { int i, result; /* Check rev rev a == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); slong len; nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); len = nmod_poly_length(a); nmod_poly_reverse(b, a, len); nmod_poly_reverse(b, b, len); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("len = %wd, n = %wu\n", len, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } /* check reversal for m > a->len */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); slong m = n_randint(state, 100) + 1; slong len = n_randint(state, m); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, len); nmod_poly_reverse(b, a, m); nmod_poly_reverse(b, b, m); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("len = %wd, m = %wd, n = %wu\n", a->length, m, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-revert_series.c000066400000000000000000000052721461254215100216750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_revert_series, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t f, g; mp_limb_t m; slong n; m = n_randtest_prime(state, 0); nmod_poly_init(f, m); nmod_poly_init(g, m); do { nmod_poly_randtest(g, state, n_randint(state, 100)); } while (nmod_poly_get_coeff_ui(g, 1) == 0); nmod_poly_set_coeff_ui(g, 0, 0); do { n = n_randint(state, 100); } while (n >= m); nmod_poly_revert_series(f, g, n); nmod_poly_revert_series(g, g, n); result = (nmod_poly_equal(f, g)); if (!result) { flint_printf("FAIL (aliasing):\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Check f(f^(-1)) = id */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h; mp_limb_t m; slong n; m = n_randtest_prime(state, 0); nmod_poly_init(f, m); nmod_poly_init(g, m); nmod_poly_init(h, m); do { nmod_poly_randtest(g, state, n_randint(state, 100)); } while (nmod_poly_get_coeff_ui(g, 1) == 0); nmod_poly_set_coeff_ui(g, 0, 0); do { n = n_randint(state, 100); } while (n >= m); nmod_poly_revert_series(f, g, n); nmod_poly_compose_series(h, g, f, n); result = ((n <= 1 && nmod_poly_is_zero(h)) || (h->length == 2 && h->coeffs[0] == 0 && h->coeffs[1] == 1)); if (!result) { flint_printf("FAIL (comparison):\n"); nmod_poly_print(g), flint_printf("\n\n"); nmod_poly_print(f), flint_printf("\n\n"); nmod_poly_print(h), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-scalar_addmul_nmod.c000066400000000000000000000037241461254215100226240ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_scalar_addmul_nmod, state) { slong i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t x = n_randint(state, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_randtest(c, state, n_randint(state, 100)); nmod_poly_randtest(d, state, n_randint(state, 100)); nmod_poly_scalar_mul_nmod(c, b, x); nmod_poly_add(d, a, c); nmod_poly_scalar_addmul_nmod(a, b, x); if (!nmod_poly_equal(a, d)) { flint_printf("FAIL: check non-aliasing\n"); fflush(stdout); flint_abort(); } nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_randtest(c, state, n_randint(state, 100)); nmod_poly_randtest(d, state, n_randint(state, 100)); nmod_poly_scalar_mul_nmod(c, a, x); nmod_poly_add(d, a, c); nmod_poly_scalar_addmul_nmod(a, a, x); if (!nmod_poly_equal(a, d)) { flint_printf("FAIL: check aliasing\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-scalar_mul_nmod.c000066400000000000000000000045401461254215100221500ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_scalar_mul_nmod, state) { int i, result; /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t c = n_randint(state, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_scalar_mul_nmod(b, a, c); nmod_poly_scalar_mul_nmod(a, a, c); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } /* Check (a + b)*c = a*c + b*c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, d1, d2; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t c = n_randint(state, n); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(d1, n); nmod_poly_init(d2, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_add(d1, a, b); nmod_poly_scalar_mul_nmod(d1, d1, c); nmod_poly_scalar_mul_nmod(d2, a, c); nmod_poly_scalar_mul_nmod(b, b, c); nmod_poly_add(d2, d2, b); result = (nmod_poly_equal(d1, d2)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(d1), flint_printf("\n\n"); nmod_poly_print(d2), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(d1); nmod_poly_clear(d2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-set_trunc.c000066400000000000000000000034621461254215100210210ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_set_trunc, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; ulong p; slong n; p = n_randtest_prime(state, 0); nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 50); nmod_poly_set_trunc(b, a, n); nmod_poly_set(c, a); nmod_poly_truncate(c, n); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_set_trunc(a, a, n); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL (aliasing):\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-shift_left_right.c000066400000000000000000000046121461254215100223350ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_shift_left_right, state) { int i, result; /* Check a << shift >> shift == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); slong shift = n_randint(state, 100); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_shift_left(b, a, shift); nmod_poly_shift_right(b, b, shift); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("shift = %wd, a->length = %wd, n = %wu\n", shift, a->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } /* Check a << shift >> shift == a aliasing the other way */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong shift = n_randint(state, 100); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(c, state, n_randint(state, 100)); nmod_poly_set(a, c); nmod_poly_shift_left(c, c, shift); nmod_poly_shift_right(b, c, shift); result = (nmod_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("shift = %wd, c->length = %wd, n = %wu\n", shift, c->length, a->mod.n); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-sin_series.c000066400000000000000000000051761461254215100211620ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_sin_series, state) { int i, result = 1; /* Check asin(sin(A)) = A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, sinA, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(sinA, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_sin_series(sinA, A, n); nmod_poly_asin_series(B, sinA, n); nmod_poly_truncate(A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("sin(A): "); nmod_poly_print(sinA), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(sinA); nmod_poly_clear(B); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_sin_series(B, A, n); nmod_poly_sin_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-sinh_series.c000066400000000000000000000052141461254215100213230ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_sinh_series, state) { int i, result = 1; /* Check asinh(sinh(A)) = A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, sinhA, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(sinhA, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_sinh_series(sinhA, A, n); nmod_poly_asinh_series(B, sinhA, n); nmod_poly_truncate(A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("sinh(A): "); nmod_poly_print(sinhA), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(sinhA); nmod_poly_clear(B); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_sinh_series(B, A, n); nmod_poly_sinh_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-sqrt.c000066400000000000000000000077301461254215100200060ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_sqrt, state) { int i; /* Test aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b; int square1, square2; mp_limb_t mod; mod = n_randtest_prime(state, 0); nmod_poly_init(a, mod); nmod_poly_init(b, mod); nmod_poly_randtest(a, state, 1 + n_randint(state, 50)); if (n_randint(state, 2)) nmod_poly_mul(a, a, a); square1 = nmod_poly_sqrt(b, a); square2 = nmod_poly_sqrt(a, a); if ((square1 != square2) || (square1 && !nmod_poly_equal(a, b))) { flint_printf("FAIL: aliasing:\n"); flint_printf("square1 = %d, square2 = %d\n\n", square1, square2); flint_printf("a: "); nmod_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); nmod_poly_print(b); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; int square; mp_limb_t mod; mod = n_randtest_prime(state, 0); nmod_poly_init(a, mod); nmod_poly_init(b, mod); nmod_poly_init(c, mod); nmod_poly_randtest(a, state, 1 + n_randint(state, 50)); nmod_poly_mul(b, a, a); square = nmod_poly_sqrt(c, b); if (!square) { flint_printf("FAIL: square reported nonsquare:\n"); flint_printf("a: "); nmod_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); nmod_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); nmod_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_mul(c, c, c); if (!nmod_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); nmod_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); nmod_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); nmod_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Test "almost" squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; slong j; int square; mp_limb_t mod; mod = n_randtest_prime(state, 0); nmod_poly_init(a, mod); nmod_poly_init(b, mod); nmod_poly_init(c, mod); nmod_poly_randtest_not_zero(a, state, 1 + n_randint(state, 50)); nmod_poly_mul(b, a, a); j = n_randint(state, nmod_poly_length(b)); b->coeffs[j] = n_randint(state, mod); _nmod_poly_normalise(b); square = nmod_poly_sqrt(c, b); if (square) { nmod_poly_mul(c, c, c); if (!nmod_poly_equal(c, b)) { flint_printf("FAIL: sqrt(b)^2 != b:\n"); flint_printf("a: "); nmod_poly_print(a); flint_printf("\n\n"); flint_printf("b: "); nmod_poly_print(b); flint_printf("\n\n"); flint_printf("c: "); nmod_poly_print(c); flint_printf("\n\n"); fflush(stdout); flint_abort(); } } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-sqrt_series.c000066400000000000000000000051621461254215100213550ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_sqrt_series, state) { int i, result; /* Check g^2 = h mod x^m */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t h, g, r; slong m; mp_limb_t n; do n = n_randtest_prime(state, 0); while (n == UWORD(2)); nmod_poly_init(h, n); nmod_poly_init(g, n); nmod_poly_init(r, n); do nmod_poly_randtest(h, state, n_randint(state, 1000)); while (h->length == 0); nmod_poly_set_coeff_ui(h, 0, UWORD(1)); m = n_randint(state, h->length) + 1; nmod_poly_sqrt_series(g, h, m); nmod_poly_mullow(r, g, g, m); nmod_poly_truncate(h, m); result = (nmod_poly_equal(r, h)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(h), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); nmod_poly_print(r), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(h); nmod_poly_clear(g); nmod_poly_clear(r); } /* Check aliasing of h and g */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t g, h; slong m; mp_limb_t n; do n = n_randtest_prime(state, 0); while (n == UWORD(2)); nmod_poly_init(h, n); nmod_poly_init(g, n); do nmod_poly_randtest(h, state, n_randint(state, 500)); while (h->length == 0); nmod_poly_set_coeff_ui(h, 0, UWORD(1)); m = n_randint(state, h->length) + 1; nmod_poly_sqrt_series(g, h, m); nmod_poly_sqrt_series(h, h, m); result = (nmod_poly_equal(g, h)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(h), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); fflush(stdout); flint_abort(); } nmod_poly_clear(g); nmod_poly_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-sub.c000066400000000000000000000064271461254215100176100ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_sub, state) { int i, result; /* Check a - b = a + neg(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, d; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(d, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_sub(c, a, b); nmod_poly_neg(b, b); nmod_poly_add(d, a, b); result = (nmod_poly_equal(d, d)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_sub(c, a, b); nmod_poly_sub(a, a, b); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); nmod_poly_sub(c, a, b); nmod_poly_sub(b, a, b); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-sub_series.c000066400000000000000000000071761461254215100211640ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2009, 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_sub_series, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { ulong p; nmod_poly_t a, b, c; slong n; p = n_randtest(state); if (p == 0) p++; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100); nmod_poly_sub_series(c, a, b, n); nmod_poly_sub_series(a, a, b, n); result = (nmod_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { ulong p; nmod_poly_t a, b, c; slong n; p = n_randtest(state); if (p == 0) p++; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100); nmod_poly_sub_series(c, a, b, n); nmod_poly_sub_series(b, a, b, n); result = (nmod_poly_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Check truncate(a + b, n) = add_series(a, b, n) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { ulong p; nmod_poly_t a, b, c, d; slong n; p = n_randtest(state); if (p == 0) p++; nmod_poly_init(a, p); nmod_poly_init(b, p); nmod_poly_init(c, p); nmod_poly_init(d, p); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_randtest(b, state, n_randint(state, 100)); n = n_randint(state, 100); nmod_poly_sub(c, a, b); nmod_poly_truncate(c, n); nmod_poly_sub_series(d, a, b, n); result = (nmod_poly_equal(d, c)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(d), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-tan_series.c000066400000000000000000000051141461254215100211430ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_tan_series, state) { int i, result = 1; /* Check atan(tan(A)) = A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, tanA, B; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(tanA, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_tan_series(tanA, A, n); nmod_poly_atan_series(B, tanA, n); nmod_poly_truncate(A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("tan(A): "); nmod_poly_print(tanA), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(tanA); nmod_poly_clear(B); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_tan_series(B, A, n); nmod_poly_tan_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-tanh_series.c000066400000000000000000000052141461254215100213140ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_tanh_series, state) { int i, result = 1; /* Check atanh(tanh(A)) = A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, tanhA, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = 1 + n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(tanhA, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_tanh_series(tanhA, A, n); nmod_poly_atanh_series(B, tanhA, n); nmod_poly_truncate(A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("tanh(A): "); nmod_poly_print(tanhA), flint_printf("\n\n"); flint_printf("B: "); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(tanhA); nmod_poly_clear(B); } /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t A, B; slong n; mp_limb_t mod; do { mod = n_randtest_prime(state, 0); } while (mod == 2); n = n_randtest(state) % 50; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(B, mod); nmod_poly_randtest(A, state, n_randint(state, 50)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_tanh_series(B, A, n); nmod_poly_tanh_series(A, A, n); result = nmod_poly_equal(A, B); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(A), flint_printf("\n\n"); nmod_poly_print(B), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-taylor_shift.c000066400000000000000000000066051461254215100215240ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_taylor_shift, state) { int i; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t f, g; mp_limb_t c, mod; mod = n_randtest_prime(state, 0); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_randtest(f, state, 1 + n_randint(state, 50)); c = n_randtest(state) % mod; nmod_poly_taylor_shift(g, f, c); nmod_poly_taylor_shift(f, f, c); if (!nmod_poly_equal(g, f)) { flint_printf("FAIL\n"); nmod_poly_print(f); flint_printf("\n"); nmod_poly_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Compare with composition */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h1, h2; mp_limb_t mod, c; mod = n_randtest_prime(state, 0); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_init(h1, mod); nmod_poly_init(h2, mod); nmod_poly_randtest(f, state, 1 + n_randint(state, 50)); c = n_randtest(state) % mod; nmod_poly_set_coeff_ui(g, 1, 1); nmod_poly_set_coeff_ui(g, 0, c); nmod_poly_taylor_shift(h1, f, c); nmod_poly_compose(h2, f, g); if (!nmod_poly_equal(h1, h2)) { flint_printf("FAIL\n"); nmod_poly_print(f); flint_printf("\n"); nmod_poly_print(g); flint_printf("\n"); nmod_poly_print(h1); flint_printf("\n"); nmod_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h1); nmod_poly_clear(h2); } /* Check some large cases */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h1, h2; mp_limb_t mod, c; mod = n_randtest_prime(state, 0); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_init(h1, mod); nmod_poly_init(h2, mod); nmod_poly_randtest(f, state, 1 + n_randint(state, 2000)); c = n_randtest(state) % mod; nmod_poly_set_coeff_ui(g, 1, 1); nmod_poly_set_coeff_ui(g, 0, c); nmod_poly_taylor_shift(h1, f, c); nmod_poly_compose(h2, f, g); if (!nmod_poly_equal(h1, h2)) { flint_printf("FAIL\n"); nmod_poly_print(f); flint_printf("\n"); nmod_poly_print(g); flint_printf("\n"); nmod_poly_print(h1); flint_printf("\n"); nmod_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h1); nmod_poly_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-taylor_shift_convolution.c000066400000000000000000000050241461254215100241550ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_taylor_shift_convolution, state) { int i; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t f, g; slong n; mp_limb_t c, mod; n = n_randint(state, 100); do { mod = n_randtest_prime(state, 0); } while (mod <= n); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_randtest(f, state, n); c = n_randtest(state) % mod; nmod_poly_taylor_shift_convolution(g, f, c); nmod_poly_taylor_shift_convolution(f, f, c); if (!nmod_poly_equal(g, f)) { flint_printf("FAIL\n"); nmod_poly_print(f); flint_printf("\n"); nmod_poly_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Compare with composition */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h1, h2; mp_limb_t mod, c; slong n; n = n_randint(state, 100); do { mod = n_randtest_prime(state, 0); } while (mod <= n); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_init(h1, mod); nmod_poly_init(h2, mod); nmod_poly_randtest(f, state, n); c = n_randtest(state) % mod; nmod_poly_set_coeff_ui(g, 1, 1); nmod_poly_set_coeff_ui(g, 0, c); nmod_poly_taylor_shift_convolution(h1, f, c); nmod_poly_compose(h2, f, g); if (!nmod_poly_equal(h1, h2)) { flint_printf("FAIL\n"); nmod_poly_print(f); flint_printf("\n"); nmod_poly_print(g); flint_printf("\n"); nmod_poly_print(h1); flint_printf("\n"); nmod_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h1); nmod_poly_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-taylor_shift_horner.c000066400000000000000000000045541461254215100231020ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_taylor_shift_horner, state) { int i; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t f, g; mp_limb_t c, mod; mod = n_randtest_prime(state, 0); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_randtest(f, state, 1 + n_randint(state, 50)); c = n_randtest(state) % mod; nmod_poly_taylor_shift_horner(g, f, c); nmod_poly_taylor_shift_horner(f, f, c); if (!nmod_poly_equal(g, f)) { flint_printf("FAIL\n"); nmod_poly_print(f); flint_printf("\n"); nmod_poly_print(g); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Compare with composition */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t f, g, h1, h2; mp_limb_t mod, c; mod = n_randtest_prime(state, 0); nmod_poly_init(f, mod); nmod_poly_init(g, mod); nmod_poly_init(h1, mod); nmod_poly_init(h2, mod); nmod_poly_randtest(f, state, 1 + n_randint(state, 50)); c = n_randtest(state) % mod; nmod_poly_set_coeff_ui(g, 1, 1); nmod_poly_set_coeff_ui(g, 0, c); nmod_poly_taylor_shift_horner(h1, f, c); nmod_poly_compose(h2, f, g); if (!nmod_poly_equal(h1, h2)) { flint_printf("FAIL\n"); nmod_poly_print(f); flint_printf("\n"); nmod_poly_print(g); flint_printf("\n"); nmod_poly_print(h1); flint_printf("\n"); nmod_poly_print(h2); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h1); nmod_poly_clear(h2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-xgcd.c000066400000000000000000000215061461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_xgcd, state) { int i, result; /* Compare with result from gcd and check a*s + b*t = g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, g1, g2, s, t, sum, temp; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g1, n); nmod_poly_init(g2, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_init(sum, n); nmod_poly_init(temp, n); nmod_poly_randtest(a, state, n_randtest(state) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); nmod_poly_randtest(c, state, n_randtest(state) % 400); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd(g1, a, b); nmod_poly_xgcd(g2, s, t, a, b); nmod_poly_mul(sum, s, a); nmod_poly_mul(temp, t, b); nmod_poly_add(sum, sum, temp); result = (nmod_poly_equal(g1, g2) && nmod_poly_equal(g1, sum) && (g1->length == 0 || g1->coeffs[g1->length - 1] == 1)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(g1), flint_printf("\n\n"); nmod_poly_print(g2), flint_printf("\n\n"); nmod_poly_print(sum), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g1); nmod_poly_clear(g2); nmod_poly_clear(s); nmod_poly_clear(t); nmod_poly_clear(sum); nmod_poly_clear(temp); } /* Check aliasing of a and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd(g, s, t, a, b); nmod_poly_xgcd(a, s, t, a, b); result = (nmod_poly_equal(a, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of b and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd(g, s, t, a, b); nmod_poly_xgcd(b, s, t, a, b); result = (nmod_poly_equal(b, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd(g, s, t, a, b); nmod_poly_xgcd(g, a, t, a, b); result = (nmod_poly_equal(s, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd(g, s, t, a, b); nmod_poly_xgcd(g, b, t, a, b); result = (nmod_poly_equal(s, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd(g, s, t, a, b); nmod_poly_xgcd(g, s, a, a, b); result = (nmod_poly_equal(t, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd(g, s, t, a, b); nmod_poly_xgcd(g, s, b, a, b); result = (nmod_poly_equal(t, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-xgcd_euclidean.c000066400000000000000000000214071461254215100217500ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_xgcd_euclidean, state) { int i, result; /* Compare with result from gcd and check a*s + b*t = g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, g1, s, t, g2; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g1, n); nmod_poly_init(g2, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randtest(state) % 200); nmod_poly_randtest(b, state, n_randtest(state) % 200); nmod_poly_randtest(c, state, n_randtest(state) % 200); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd_euclidean(g1, a, b); nmod_poly_xgcd_euclidean(g2, s, t, a, b); nmod_poly_mul(s, s, a); nmod_poly_mul(t, t, b); nmod_poly_add(s, s, t); result = (nmod_poly_equal(g1, g2) && nmod_poly_equal(s, g1) && (g1->length == 0 || g1->coeffs[g1->length - 1] == 1)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(g1), flint_printf("\n\n"); nmod_poly_print(g2), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g1); nmod_poly_clear(g2); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of a and g */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randtest(state) % 200); nmod_poly_randtest(b, state, n_randtest(state) % 200); nmod_poly_xgcd_euclidean(g, s, t, a, b); nmod_poly_xgcd_euclidean(a, s, t, a, b); result = (nmod_poly_equal(a, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of b and g */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randtest(state) % 200); nmod_poly_randtest(b, state, n_randtest(state) % 200); nmod_poly_xgcd_euclidean(g, s, t, a, b); nmod_poly_xgcd_euclidean(b, s, t, a, b); result = (nmod_poly_equal(b, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and a */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randtest(state) % 200); nmod_poly_randtest(b, state, n_randtest(state) % 200); nmod_poly_xgcd_euclidean(g, s, t, a, b); nmod_poly_xgcd_euclidean(g, a, t, a, b); result = (nmod_poly_equal(s, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and b */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randtest(state) % 200); nmod_poly_randtest(b, state, n_randtest(state) % 200); nmod_poly_xgcd_euclidean(g, s, t, a, b); nmod_poly_xgcd_euclidean(g, b, t, a, b); result = (nmod_poly_equal(s, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and a */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randtest(state) % 200); nmod_poly_randtest(b, state, n_randtest(state) % 200); nmod_poly_xgcd_euclidean(g, s, t, a, b); nmod_poly_xgcd_euclidean(g, s, a, a, b); result = (nmod_poly_equal(t, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and b */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randtest(state) % 200); nmod_poly_randtest(b, state, n_randtest(state) % 200); nmod_poly_xgcd_euclidean(g, s, t, a, b); nmod_poly_xgcd_euclidean(g, s, b, a, b); result = (nmod_poly_equal(t, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/test/t-xgcd_hgcd.c000066400000000000000000000215421461254215100207240ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" TEST_FUNCTION_START(nmod_poly_xgcd_hgcd, state) { int i, result; /* Compare with result from gcd and check a*s + b*t = g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c, g1, g2, s, t, sum, temp; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g1, n); nmod_poly_init(g2, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_init(sum, n); nmod_poly_init(temp, n); nmod_poly_randtest(a, state, n_randtest(state) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); nmod_poly_randtest(c, state, n_randtest(state) % 400); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd(g1, a, b); nmod_poly_xgcd_hgcd(g2, s, t, a, b); nmod_poly_mul(sum, s, a); nmod_poly_mul(temp, t, b); nmod_poly_add(sum, sum, temp); result = (nmod_poly_equal(g1, g2) && nmod_poly_equal(g1, sum) && (g1->length == 0 || g1->coeffs[g1->length - 1] == 1)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(g1), flint_printf("\n\n"); nmod_poly_print(g2), flint_printf("\n\n"); nmod_poly_print(sum), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g1); nmod_poly_clear(g2); nmod_poly_clear(s); nmod_poly_clear(t); nmod_poly_clear(sum); nmod_poly_clear(temp); } /* Check aliasing of a and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(a, s, t, a, b); result = (nmod_poly_equal(a, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of b and g */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(b, s, t, a, b); result = (nmod_poly_equal(b, g)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(g), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, a, t, a, b); result = (nmod_poly_equal(s, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, b, t, a, b); result = (nmod_poly_equal(s, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(s), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and a */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, s, a, a, b); result = (nmod_poly_equal(t, a)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(a), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 20)); nmod_poly_randtest(b, state, n_randint(state, 20)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, s, b, a, b); result = (nmod_poly_equal(t, b)); if (!result) { flint_printf("FAIL:\n"); nmod_poly_print(b), flint_printf("\n\n"); nmod_poly_print(t), flint_printf("\n\n"); flint_printf("n = %wd\n", n); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly/tree.c000066400000000000000000000046061461254215100165330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" mp_ptr * _nmod_poly_tree_alloc(slong len) { mp_ptr * tree = NULL; if (len) { slong i, height = FLINT_CLOG2(len); tree = flint_malloc(sizeof(mp_ptr) * (height + 1)); for (i = 0; i <= height; i++) tree[i] = _nmod_vec_init(len + (len >> i) + 1); } return tree; } void _nmod_poly_tree_free(mp_ptr * tree, slong len) { if (len) { slong i, height = FLINT_CLOG2(len); for (i = 0; i <= height; i++) flint_free(tree[i]); flint_free(tree); } } void _nmod_poly_tree_build(mp_ptr * tree, mp_srcptr roots, slong len, nmod_t mod) { slong height, pow, left, i; mp_ptr pa, pb; if (len == 0) return; height = FLINT_CLOG2(len); /* zeroth level, (x-a) */ for (i = 0; i < len; i++) { tree[0][2 * i + 1] = 1; tree[0][2 * i] = nmod_neg(roots[i], mod); } /* first level, (x-a)(x-b) = x^2 + (-a-b)*x + a*b */ if (height > 1) { pa = tree[1]; for (i = 0; i < len / 2; i++) { mp_limb_t a, b; a = roots[2 * i]; b = roots[2 * i + 1]; pa[3 * i] = nmod_mul(a, b, mod); pa[3 * i + 1] = nmod_neg(nmod_add(a, b, mod), mod); pa[3 * i + 2] = 1; } if (len & 1) { pa[3 * (len / 2)] = nmod_neg(roots[len-1], mod); pa[3 * (len / 2) + 1] = 1; } } for (i = 1; i < height - 1; i++) { left = len; pow = WORD(1) << i; pa = tree[i]; pb = tree[i + 1]; while (left >= 2 * pow) { _nmod_poly_mul(pb, pa, pow + 1, pa + pow + 1, pow + 1, mod); left -= 2 * pow; pa += 2 * pow + 2; pb += 2 * pow + 1; } if (left > pow) _nmod_poly_mul(pb, pa, pow + 1, pa + pow + 1, left - pow + 1, mod); else if (left > 0) _nmod_vec_set(pb, pa, left + 1); } } flint-3.1.3/src/nmod_poly/xgcd.c000066400000000000000000000336111461254215100165170ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2023 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "gr_poly.h" slong _nmod_poly_xgcd(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { slong cutoff = NMOD_BITS(mod) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; if (lenB < cutoff) { return _nmod_poly_xgcd_euclidean(G, S, T, A, lenA, B, lenB, mod); } else { slong lenG = 0; gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_xgcd_hgcd(&lenG, G, S, T, A, lenA, B, lenB, NMOD_POLY_HGCD_CUTOFF, cutoff, ctx)); return lenG; } } void nmod_poly_xgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) { if (A->length < B->length) { nmod_poly_xgcd(G, T, S, B, A); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; mp_limb_t inv; if (lenA == 0) /* lenA = lenB = 0 */ { nmod_poly_zero(G); nmod_poly_zero(S); nmod_poly_zero(T); } else if (lenB == 0) /* lenA > lenB = 0 */ { inv = n_invmod(A->coeffs[lenA - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, A, inv); nmod_poly_zero(T); nmod_poly_set_coeff_ui(S, 0, inv); S->length = 1; } else if (lenB == 1) /* lenA >= lenB = 1 */ { nmod_poly_fit_length(T, 1); T->length = 1; T->coeffs[0] = n_invmod(B->coeffs[0], A->mod.n); nmod_poly_one(G); nmod_poly_zero(S); } else /* lenA >= lenB >= 2 */ { mp_ptr g, s, t; slong lenG; if (G == A || G == B) { g = _nmod_vec_init(FLINT_MIN(lenA, lenB)); } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } if (S == A || S == B) { s = _nmod_vec_init(lenB - 1); } else { nmod_poly_fit_length(S, lenB - 1); s = S->coeffs; } if (T == A || T == B) { t = _nmod_vec_init(lenA - 1); } else { nmod_poly_fit_length(T, lenA - 1); t = T->coeffs; } if (lenA >= lenB) lenG = _nmod_poly_xgcd(g, s, t, A->coeffs, lenA, B->coeffs, lenB, A->mod); else lenG = _nmod_poly_xgcd(g, t, s, B->coeffs, lenB, A->coeffs, lenA, A->mod); if (G == A || G == B) { flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { flint_free(S->coeffs); S->coeffs = s; S->alloc = lenB - 1; } if (T == A || T == B) { flint_free(T->coeffs); T->coeffs = t; T->alloc = lenA - 1; } G->length = lenG; S->length = FLINT_MAX(lenB - lenG, 1); T->length = FLINT_MAX(lenA - lenG, 1); MPN_NORM(S->coeffs, S->length); MPN_NORM(T->coeffs, T->length); if (G->coeffs[lenG - 1] != 1) { inv = n_invmod(G->coeffs[lenG - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, G, inv); nmod_poly_scalar_mul_nmod(S, S, inv); nmod_poly_scalar_mul_nmod(T, T, inv); } } } } slong _nmod_poly_xgcd_euclidean(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { flint_mpn_zero(G, lenB); flint_mpn_zero(S, lenB - 1); flint_mpn_zero(T, lenA - 1); if (lenB == 1) { G[0] = B[0]; T[0] = 1; return 1; } else { mp_ptr Q, R; slong lenQ, lenR, lenG; Q = _nmod_vec_init(2 * lenA); R = Q + lenA; _nmod_poly_divrem(Q, R, A, lenA, B, lenB, mod); lenR = lenB - 1; MPN_NORM(R, lenR); if (lenR == 0) { _nmod_vec_set(G, B, lenB); T[0] = 1; lenG = lenB; } else { mp_ptr D, U, V1, V3, W; slong lenD, lenU, lenV1, lenV3, lenW; W = _nmod_vec_init(FLINT_MAX(5 * lenB, lenA + lenB)); D = W + lenB; U = D + lenB; V1 = U + lenB; V3 = V1 + lenB; lenU = 0; _nmod_vec_set(D, B, lenB); lenD = lenB; V1[0] = 1; lenV1 = 1; lenV3 = 0; MPN_SWAP(V3, lenV3, R, lenR); do { _nmod_poly_divrem(Q, R, D, lenD, V3, lenV3, mod); lenQ = lenD - lenV3 + 1; lenR = lenV3 - 1; MPN_NORM(R, lenR); if (lenV1 >= lenQ) _nmod_poly_mul(W, V1, lenV1, Q, lenQ, mod); else _nmod_poly_mul(W, Q, lenQ, V1, lenV1, mod); lenW = lenQ + lenV1 - 1; _nmod_poly_sub(U, U, lenU, W, lenW, mod); lenU = FLINT_MAX(lenU, lenW); MPN_NORM(U, lenU); MPN_SWAP(U, lenU, V1, lenV1); { mp_ptr __t; slong __tn; __t = D; D = V3; V3 = R; R = __t; __tn = lenD; lenD = lenV3; lenV3 = lenR; lenR = __tn; } } while (lenV3 != 0); _nmod_vec_set(G, D, lenD); _nmod_vec_set(S, U, lenU); { lenQ = lenA + lenU - 1; _nmod_poly_mul(Q, A, lenA, S, lenU, mod); _nmod_vec_neg(Q, Q, lenQ, mod); _nmod_poly_add(Q, G, lenD, Q, lenQ, mod); _nmod_poly_divrem(T, W, Q, lenQ, B, lenB, mod); } _nmod_vec_clear(W); lenG = lenD; } _nmod_vec_clear(Q); return lenG; } } void nmod_poly_xgcd_euclidean(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) { if (A->length < B->length) { nmod_poly_xgcd_euclidean(G, T, S, B, A); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; mp_limb_t inv; if (lenA == 0) /* lenA = lenB = 0 */ { nmod_poly_zero(G); nmod_poly_zero(S); nmod_poly_zero(T); } else if (lenB == 0) /* lenA > lenB = 0 */ { inv = n_invmod(A->coeffs[lenA - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, A, inv); nmod_poly_zero(T); nmod_poly_set_coeff_ui(S, 0, inv); S->length = 1; } else if (lenB == 1) /* lenA >= lenB = 1 */ { nmod_poly_fit_length(T, 1); T->length = 1; T->coeffs[0] = n_invmod(B->coeffs[0], A->mod.n); nmod_poly_one(G); nmod_poly_zero(S); } else /* lenA >= lenB >= 2 */ { mp_ptr g, s, t; slong lenG; if (G == A || G == B) { g = _nmod_vec_init(FLINT_MIN(lenA, lenB)); } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } if (S == A || S == B) { s = _nmod_vec_init(lenB - 1); } else { nmod_poly_fit_length(S, lenB - 1); s = S->coeffs; } if (T == A || T == B) { t = _nmod_vec_init(lenA - 1); } else { nmod_poly_fit_length(T, lenA - 1); t = T->coeffs; } if (lenA >= lenB) lenG = _nmod_poly_xgcd_euclidean(g, s, t, A->coeffs, lenA, B->coeffs, lenB, A->mod); else lenG = _nmod_poly_xgcd_euclidean(g, t, s, B->coeffs, lenB, A->coeffs, lenA, A->mod); if (G == A || G == B) { flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { flint_free(S->coeffs); S->coeffs = s; S->alloc = lenB - 1; } if (T == A || T == B) { flint_free(T->coeffs); T->coeffs = t; T->alloc = lenA - 1; } G->length = lenG; S->length = FLINT_MAX(lenB - lenG, 1); T->length = FLINT_MAX(lenA - lenG, 1); MPN_NORM(S->coeffs, S->length); MPN_NORM(T->coeffs, T->length); if (G->coeffs[lenG - 1] != 1) { inv = n_invmod(G->coeffs[lenG - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, G, inv); nmod_poly_scalar_mul_nmod(S, S, inv); nmod_poly_scalar_mul_nmod(T, T, inv); } } } } slong _nmod_poly_xgcd_hgcd(mp_ptr G, mp_ptr S, mp_ptr T, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { slong cutoff = NMOD_BITS(mod) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; slong lenG = 0; gr_ctx_t ctx; _gr_ctx_init_nmod(ctx, &mod); GR_MUST_SUCCEED(_gr_poly_xgcd_hgcd(&lenG, G, S, T, A, lenA, B, lenB, NMOD_POLY_HGCD_CUTOFF, cutoff, ctx)); return lenG; } void nmod_poly_xgcd_hgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) { if (A->length < B->length) { nmod_poly_xgcd_hgcd(G, T, S, B, A); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; mp_limb_t inv; if (lenA == 0) /* lenA = lenB = 0 */ { nmod_poly_zero(G); nmod_poly_zero(S); nmod_poly_zero(T); } else if (lenB == 0) /* lenA > lenB = 0 */ { inv = n_invmod(A->coeffs[lenA - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, A, inv); nmod_poly_zero(T); nmod_poly_set_coeff_ui(S, 0, inv); S->length = 1; } else if (lenB == 1) /* lenA >= lenB = 1 */ { nmod_poly_fit_length(T, 1); T->length = 1; T->coeffs[0] = n_invmod(B->coeffs[0], A->mod.n); nmod_poly_one(G); nmod_poly_zero(S); } else /* lenA >= lenB >= 2 */ { mp_ptr g, s, t; slong lenG; if (G == A || G == B) { g = _nmod_vec_init(FLINT_MIN(lenA, lenB)); } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } if (S == A || S == B) { s = _nmod_vec_init(lenB - 1); } else { nmod_poly_fit_length(S, lenB - 1); s = S->coeffs; } if (T == A || T == B) { t = _nmod_vec_init(lenA - 1); } else { nmod_poly_fit_length(T, lenA - 1); t = T->coeffs; } if (lenA >= lenB) lenG = _nmod_poly_xgcd_hgcd(g, s, t, A->coeffs, lenA, B->coeffs, lenB, A->mod); else lenG = _nmod_poly_xgcd_hgcd(g, t, s, B->coeffs, lenB, A->coeffs, lenA, A->mod); if (G == A || G == B) { flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { flint_free(S->coeffs); S->coeffs = s; S->alloc = lenB - 1; } if (T == A || T == B) { flint_free(T->coeffs); T->coeffs = t; T->alloc = lenA - 1; } G->length = lenG; S->length = FLINT_MAX(lenB - lenG, 1); T->length = FLINT_MAX(lenA - lenG, 1); MPN_NORM(S->coeffs, S->length); MPN_NORM(T->coeffs, T->length); if (G->coeffs[lenG - 1] != 1) { inv = n_invmod(G->coeffs[lenG - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, G, inv); nmod_poly_scalar_mul_nmod(S, S, inv); nmod_poly_scalar_mul_nmod(T, T, inv); } } } } flint-3.1.3/src/nmod_poly_factor.h000066400000000000000000000105251461254215100171340ustar00rootroot00000000000000/* Copyright (C) 2007, David Howden Copyright (C) 2010, 2011 William Hart Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_POLY_FACTOR_H #define NMOD_POLY_FACTOR_H #ifdef NMOD_POLY_FACTOR_INLINES_C #define NMOD_POLY_FACTOR_INLINE #else #define NMOD_POLY_FACTOR_INLINE static inline #endif #include "limb_types.h" #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { nmod_poly_struct * baby; nmod_poly_struct * res; nmod_poly_struct * H; nmod_poly_struct * v; nmod_poly_struct * vinv; mp_ptr tmp; slong m; } nmod_poly_interval_poly_arg_t; /* Factoring ****************************************************************/ void nmod_poly_factor_init(nmod_poly_factor_t fac); void nmod_poly_factor_clear(nmod_poly_factor_t fac); void nmod_poly_factor_realloc(nmod_poly_factor_t fac, slong alloc); void nmod_poly_factor_fit_length(nmod_poly_factor_t fac, slong len); void nmod_poly_factor_set(nmod_poly_factor_t res, const nmod_poly_factor_t fac); NMOD_POLY_FACTOR_INLINE void nmod_poly_factor_swap(nmod_poly_factor_t a, nmod_poly_factor_t b) { nmod_poly_factor_struct t = *a; *a = *b; *b = t; } void nmod_poly_factor_get_poly(nmod_poly_t a, const nmod_poly_factor_t b, slong i); void nmod_poly_factor_insert(nmod_poly_factor_t fac, const nmod_poly_t poly, slong exp); void nmod_poly_factor_print(const nmod_poly_factor_t fac); void nmod_poly_factor_print_pretty(const nmod_poly_factor_t fac, const char *var); void nmod_poly_factor_concat(nmod_poly_factor_t res, const nmod_poly_factor_t fac); void nmod_poly_factor_pow(nmod_poly_factor_t fac, slong exp); void nmod_poly_factor_equal_deg(nmod_poly_factor_t factors, const nmod_poly_t pol, slong d); int nmod_poly_factor_equal_deg_prob(nmod_poly_t factor, flint_rand_t state, const nmod_poly_t pol, slong d); void nmod_poly_factor_distinct_deg(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const *degs); void nmod_poly_factor_distinct_deg_threaded(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const *degs); int nmod_poly_is_irreducible(const nmod_poly_t f); int nmod_poly_is_irreducible_rabin(const nmod_poly_t f); int nmod_poly_is_irreducible_ddf(const nmod_poly_t f); int _nmod_poly_is_squarefree(mp_srcptr f, slong len, nmod_t mod); int nmod_poly_is_squarefree(const nmod_poly_t f); void nmod_poly_factor_cantor_zassenhaus(nmod_poly_factor_t res, const nmod_poly_t f); void nmod_poly_factor_berlekamp(nmod_poly_factor_t factors, const nmod_poly_t f); void nmod_poly_factor_kaltofen_shoup(nmod_poly_factor_t res, const nmod_poly_t poly); void nmod_poly_factor_squarefree(nmod_poly_factor_t res, const nmod_poly_t f); mp_limb_t nmod_poly_factor_with_berlekamp(nmod_poly_factor_t result, const nmod_poly_t input); mp_limb_t nmod_poly_factor_with_cantor_zassenhaus(nmod_poly_factor_t result, const nmod_poly_t input); mp_limb_t nmod_poly_factor_with_kaltofen_shoup(nmod_poly_factor_t result, const nmod_poly_t input); mp_limb_t nmod_poly_factor(nmod_poly_factor_t result, const nmod_poly_t input); void _nmod_poly_interval_poly_worker(void* arg_ptr); /* Roots *********************************************************************/ void nmod_poly_roots(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity); int nmod_poly_roots_factored(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity, const n_factor_t * n); /* Declare dead functions ****************************************************/ #define nmod_poly_factor_get_nmod_poly _Pragma("GCC error \"'nmod_poly_factor_get_nmod_poly' is deprecated. Use 'nmod_poly_factor_get_poly' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod_poly_factor/000077500000000000000000000000001461254215100167605ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly_factor/clear.c000066400000000000000000000013751461254215100202200ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_clear(nmod_poly_factor_t fac) { slong i; for (i = 0; i < fac->alloc; i++) nmod_poly_clear(fac->p + i); flint_free(fac->p); flint_free(fac->exp); } flint-3.1.3/src/nmod_poly_factor/concat.c000066400000000000000000000013521461254215100203740ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly_factor.h" void nmod_poly_factor_concat(nmod_poly_factor_t res, const nmod_poly_factor_t fac) { slong i; for (i = 0; i < fac->num; i++) nmod_poly_factor_insert(res, fac->p + i, fac->exp[i]); } flint-3.1.3/src/nmod_poly_factor/factor.c000066400000000000000000000113071461254215100204040ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010, 2022 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "nmod_poly_factor.h" #define ZASSENHAUS 0 #define BERLEKAMP 1 #define KALTOFEN 2 static inline void __nmod_poly_factor1(nmod_poly_factor_t res, const nmod_poly_t f, int algorithm) { if (algorithm == KALTOFEN) nmod_poly_factor_kaltofen_shoup(res, f); else if (algorithm == ZASSENHAUS) nmod_poly_factor_cantor_zassenhaus(res, f); else nmod_poly_factor_berlekamp(res, f); } mp_limb_t __nmod_poly_factor(nmod_poly_factor_t result, const nmod_poly_t input, int algorithm) { nmod_poly_t monic_input; nmod_poly_factor_t sqfree_factors, factors; mp_limb_t leading_coeff; slong i, len; len = input->length; if (len <= 1) { if (len == 0) return 0; else return input->coeffs[0]; } leading_coeff = *nmod_poly_lead(input); nmod_poly_init_mod(monic_input, input->mod); nmod_poly_make_monic(monic_input, input); if (len == 2) { nmod_poly_factor_insert(result, monic_input, 1); nmod_poly_clear(monic_input); return input->coeffs[1]; } nmod_poly_factor_init(sqfree_factors); nmod_poly_factor_squarefree(sqfree_factors, monic_input); nmod_poly_clear(monic_input); /* Run CZ on each of the square-free factors */ for (i = 0; i < sqfree_factors->num; i++) { nmod_poly_factor_init(factors); __nmod_poly_factor1(factors, sqfree_factors->p + i, algorithm); nmod_poly_factor_pow(factors, sqfree_factors->exp[i]); nmod_poly_factor_concat(result, factors); nmod_poly_factor_clear(factors); } nmod_poly_factor_clear(sqfree_factors); return leading_coeff; } mp_limb_t __nmod_poly_factor_deflation(nmod_poly_factor_t result, const nmod_poly_t input, int algorithm) { slong i; ulong deflation; if (input->length <= 1) { if (input->length == 0) return 0; else return input->coeffs[0]; } deflation = nmod_poly_deflation(input); if (deflation == 1) { return __nmod_poly_factor(result, input, algorithm); } else { nmod_poly_factor_t def_res; nmod_poly_t def; mp_limb_t leading_coeff; nmod_poly_init_mod(def, input->mod); nmod_poly_deflate(def, input, deflation); nmod_poly_factor_init(def_res); leading_coeff = __nmod_poly_factor(def_res, def, algorithm); nmod_poly_clear(def); for (i = 0; i < def_res->num; i++) { /* Inflate */ nmod_poly_t pol; nmod_poly_init_mod(pol, input->mod); nmod_poly_inflate(pol, def_res->p + i, deflation); /* Factor inflation */ if (def_res->exp[i] == 1) __nmod_poly_factor(result, pol, algorithm); else { nmod_poly_factor_t t; nmod_poly_factor_init(t); __nmod_poly_factor(t, pol, algorithm); nmod_poly_factor_pow(t, def_res->exp[i]); nmod_poly_factor_concat(result, t); nmod_poly_factor_clear(t); } nmod_poly_clear(pol); } nmod_poly_factor_clear(def_res); return leading_coeff; } } mp_limb_t nmod_poly_factor_with_berlekamp(nmod_poly_factor_t result, const nmod_poly_t input) { return __nmod_poly_factor_deflation(result, input, BERLEKAMP); } mp_limb_t nmod_poly_factor_with_cantor_zassenhaus(nmod_poly_factor_t result, const nmod_poly_t input) { return __nmod_poly_factor_deflation(result, input, ZASSENHAUS); } mp_limb_t nmod_poly_factor_with_kaltofen_shoup(nmod_poly_factor_t result, const nmod_poly_t input) { return __nmod_poly_factor_deflation(result, input, KALTOFEN); } mp_limb_t nmod_poly_factor(nmod_poly_factor_t result, const nmod_poly_t input) { mp_limb_t p = input->mod.n; unsigned int bits = FLINT_BIT_COUNT (p); slong n = nmod_poly_degree(input); result->num = 0; if (n < 10 + 50 / bits) return __nmod_poly_factor_deflation(result, input, ZASSENHAUS); else return __nmod_poly_factor_deflation(result, input, KALTOFEN); } flint-3.1.3/src/nmod_poly_factor/factor_berlekamp.c000066400000000000000000000137161461254215100224340ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010, 2022 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" static void nmod_poly_to_nmod_mat_col(nmod_mat_t mat, slong col, nmod_poly_t poly) { slong i; for (i = 0; i < poly->length; i++) nmod_mat_entry(mat, i, col) = poly->coeffs[i]; for ( ; i < mat->r; i++) nmod_mat_entry(mat, i, col) = 0; } static void nmod_mat_col_to_nmod_poly_shifted(nmod_poly_t poly, nmod_mat_t mat, slong col, slong * shift) { slong i, j, rows = mat->r; nmod_poly_fit_length(poly, rows); for (i = 0, j = 0; j < rows; j++) { if (shift[j]) poly->coeffs[j] = 0; else { poly->coeffs[j] = nmod_mat_entry(mat, i, col); i++; } } poly->length = rows; _nmod_poly_normalise(poly); } static void __nmod_poly_factor_berlekamp(nmod_poly_factor_t factors, flint_rand_t state, const nmod_poly_t f) { const mp_limb_t p = nmod_poly_modulus(f); const slong n = nmod_poly_degree(f); nmod_poly_factor_t fac1, fac2; nmod_poly_t x, x_p; nmod_poly_t x_pi, x_pi2; nmod_poly_t Q; nmod_mat_t matrix; mp_limb_t coeff; slong i, nullity, col, row, *shift; nmod_poly_t *basis; if (f->length <= 2) { nmod_poly_factor_insert(factors, f, 1); return; } /* Step 1, we compute x^p mod f in F_p[X]/ */ nmod_poly_init_mod(x, f->mod); nmod_poly_init_mod(x_p, f->mod); nmod_poly_set_coeff_ui(x, 1, 1); nmod_poly_powmod_ui_binexp(x_p, x, p, f); nmod_poly_clear(x); /* Step 2, compute the matrix for the Berlekamp Map */ nmod_mat_init(matrix, n, n, p); nmod_poly_init_mod(x_pi, f->mod); nmod_poly_init_mod(x_pi2, f->mod); nmod_poly_set_coeff_ui(x_pi, 0, 1); for (i = 0; i < n; i++) { /* Q - I */ nmod_poly_set(x_pi2, x_pi); coeff = nmod_poly_get_coeff_ui(x_pi2, i); if (coeff) nmod_poly_set_coeff_ui(x_pi2, i, coeff - 1); else nmod_poly_set_coeff_ui(x_pi2, i, p - 1); nmod_poly_to_nmod_mat_col(matrix, i, x_pi2); nmod_poly_mulmod(x_pi, x_pi, x_p, f); } nmod_poly_clear(x_p); nmod_poly_clear(x_pi); nmod_poly_clear(x_pi2); /* Row reduce Q - I */ nullity = n - nmod_mat_rref(matrix); /* Find a basis for the nullspace */ basis = (nmod_poly_t *) flint_malloc(nullity * sizeof(nmod_poly_t)); shift = (slong *) flint_calloc(n, sizeof(slong)); col = 1; /* first column is always zero */ row = 0; shift[0] = 1; for (i = 1; i < nullity; i++) { nmod_poly_init_mod(basis[i], f->mod); while (nmod_mat_entry(matrix, row, col)) { row++; col++; } nmod_mat_col_to_nmod_poly_shifted(basis[i], matrix, col, shift); nmod_poly_set_coeff_ui(basis[i], col, p - 1); shift[col] = 1; col++; } flint_free(shift); nmod_mat_clear(matrix); /* we are done */ if (nullity == 1) { nmod_poly_factor_insert(factors, f, 1); flint_free(basis); } else { /* Generate random linear combinations */ nmod_poly_t factor, b, power, g; nmod_poly_init_mod(factor, f->mod); nmod_poly_init_mod(b, f->mod); nmod_poly_init_mod(power, f->mod); nmod_poly_init_mod(g, f->mod); while (1) { do { nmod_poly_zero(factor); for (i = 1; i < nullity; i++) { nmod_poly_scalar_mul_nmod(b, basis[i], n_randint(state, p)); nmod_poly_add(factor, factor, b); } nmod_poly_set_coeff_ui(factor, 0, n_randint(state, p)); if (!nmod_poly_is_zero(factor)) nmod_poly_make_monic(factor, factor); } while (nmod_poly_is_one(factor) || nmod_poly_is_zero(factor)); nmod_poly_gcd(g, f, factor); if (nmod_poly_length(g) != 1) break; if (p > 3) nmod_poly_powmod_ui_binexp(power, factor, p >> 1, f); else nmod_poly_set(power, factor); power->coeffs[0] = n_addmod(power->coeffs[0], p - 1, p); _nmod_poly_normalise(power); nmod_poly_gcd(g, power, f); if (nmod_poly_length(g) != 1) break; } for (i = 1; i < nullity; i++) nmod_poly_clear(basis[i]); flint_free(basis); nmod_poly_clear(power); nmod_poly_clear(factor); nmod_poly_clear(b); if (!nmod_poly_is_zero(g)) nmod_poly_make_monic(g, g); nmod_poly_factor_init(fac1); nmod_poly_factor_init(fac2); __nmod_poly_factor_berlekamp(fac1, state, g); nmod_poly_init_mod(Q, f->mod); nmod_poly_divexact(Q, f, g); if (!nmod_poly_is_zero(Q)) nmod_poly_make_monic(Q, Q); __nmod_poly_factor_berlekamp(fac2, state, Q); nmod_poly_factor_concat(factors, fac1); nmod_poly_factor_concat(factors, fac2); nmod_poly_factor_clear(fac1); nmod_poly_factor_clear(fac2); nmod_poly_clear(Q); nmod_poly_clear(g); } } void nmod_poly_factor_berlekamp(nmod_poly_factor_t factors, const nmod_poly_t f) { flint_rand_t r; flint_randinit(r); __nmod_poly_factor_berlekamp(factors, r, f); flint_randclear(r); } flint-3.1.3/src/nmod_poly_factor/factor_cantor_zassenhaus.c000066400000000000000000000031371461254215100242200ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010, 2022 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_cantor_zassenhaus(nmod_poly_factor_t res, const nmod_poly_t f) { nmod_poly_t h, v, g, x; slong i, j, num; nmod_poly_init_mod(h, f->mod); nmod_poly_init_mod(g, f->mod); nmod_poly_init_mod(v, f->mod); nmod_poly_init_mod(x, f->mod); nmod_poly_set_coeff_ui(h, 1, 1); nmod_poly_set_coeff_ui(x, 1, 1); nmod_poly_make_monic(v, f); i = 0; do { i++; nmod_poly_powmod_ui_binexp(h, h, f->mod.n, v); nmod_poly_sub(h, h, x); nmod_poly_gcd(g, h, v); nmod_poly_add(h, h, x); if (g->length != 1) { nmod_poly_make_monic(g, g); num = res->num; nmod_poly_factor_equal_deg(res, g, i); for (j = num; j < res->num; j++) res->exp[j] = nmod_poly_remove(v, res->p + j); } } while (v->length >= 2*i + 3); if (v->length > 1) nmod_poly_factor_insert(res, v, 1); nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(v); nmod_poly_clear(x); } flint-3.1.3/src/nmod_poly_factor/factor_distinct_deg.c000066400000000000000000000133751461254215100231330ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013, 2014 Martin Lee Copyright (C) 2020, 2022 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #ifdef __GNUC__ # define ceil __builtin_ceil # define log __builtin_log # define pow __builtin_pow #else # include #endif void nmod_poly_factor_distinct_deg(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const * degs) { nmod_poly_t f, g, v, vinv, tmp; nmod_poly_struct * h, * H, * I; slong i, j, l, m, n, index, d; nmod_mat_t HH, HHH; double beta; n = nmod_poly_degree(poly); nmod_poly_init_mod(v, poly->mod); nmod_poly_make_monic(v, poly); if (n == 1) { nmod_poly_factor_insert(res, v, 1); (*degs)[0] = 1; nmod_poly_clear(v); return; } beta = 0.5*(1. - log(2)/log(n)); l = ceil(pow(n, beta)); m = ceil(0.5*n/l); /* initialization */ nmod_poly_init_mod(f, poly->mod); nmod_poly_init_mod(g, poly->mod); nmod_poly_init_mod(vinv, poly->mod); nmod_poly_init_mod(tmp, poly->mod); h = flint_malloc((2 * m + l + 1) * sizeof(nmod_poly_struct)); H = h + (l + 1); I = H + m; for (i = 0; i < 2*m + l + 1; i++) nmod_poly_init_mod(h + i, poly->mod); nmod_poly_reverse(vinv, v, v->length); nmod_poly_inv_series(vinv, vinv, v->length); /* compute baby steps: h[i] = x^{p^i}mod v */ nmod_poly_set_coeff_ui(h + 0, 1, 1); nmod_poly_powmod_x_ui_preinv(h + 1, poly->mod.n, v, vinv); if (FLINT_BIT_COUNT(poly->mod.n) > ((n_sqrt(v->length - 1) + 1)*3)/4) { for (i = 1; i < FLINT_BIT_COUNT(l); i++) nmod_poly_compose_mod_brent_kung_vec_preinv(h + 1 + (1 << (i - 1)), h + 1, (1 << (i - 1)), (1 << (i - 1)), h + (1 << (i - 1)), v, vinv); nmod_poly_compose_mod_brent_kung_vec_preinv(h + 1 + (1 << (i - 1)), h + 1, (1 << (i - 1)), l - (1 << (i - 1)), h + (1 << (i - 1)), v, vinv); } else { for (i = 2; i < l + 1; i++) { nmod_poly_init_mod(h + i, poly->mod); nmod_poly_powmod_ui_binexp_preinv(h + i, h + i - 1, poly->mod.n, v, vinv); } } /* compute coarse distinct-degree factorisation */ index = 0; nmod_poly_set(H + 0, h + l); nmod_mat_init(HH, n_sqrt(v->length - 1) + 1, v->length - 1, poly->mod.n); nmod_poly_precompute_matrix(HH, H + 0, v, vinv); d = 1; for (j = 0; j < m; j++) { /* compute giant steps: H[j] = x^{p^(lj)}mod v */ if (j > 0) { if (I[j - 1].length > 1) { _nmod_poly_reduce_matrix_mod_poly(HHH, HH, v); nmod_mat_clear(HH); nmod_mat_init_set(HH, HHH); nmod_mat_clear(HHH); nmod_poly_rem(tmp, H + j - 1, v); nmod_poly_compose_mod_brent_kung_precomp_preinv(H + j, tmp, HH, v, vinv); } else nmod_poly_compose_mod_brent_kung_precomp_preinv(H + j, H + j - 1, HH, v, vinv); } /* compute interval polynomials */ nmod_poly_set_coeff_ui(I + j, 0, 1); for (i = l - 1; i >= 0 && 2*d <= v->length - 1; i--, d++) { nmod_poly_rem(tmp, h + i, v); nmod_poly_sub(tmp, H + j, tmp); nmod_poly_mulmod_preinv(I + j, tmp, I + j, v, vinv); } /* compute F_j=f^{[j*l+1]} * ... * f^{[j*l+l]} */ /* F_j is stored on the place of I_j */ nmod_poly_gcd(I + j, v, I + j); if (I[j].length > 1) { nmod_poly_remove(v, I + j); nmod_poly_reverse(vinv, v, v->length); nmod_poly_inv_series(vinv, vinv, v->length); } if (v->length - 1 < 2*d) break; } if (v->length > 1) { nmod_poly_factor_insert(res, v, 1); (*degs)[index++] = v->length - 1; } /* compute fine distinct-degree factorisation */ for (j = 0; j < m; j++) { if (I[j].length - 1 > (j + 1)*l || j == 0) { nmod_poly_set(g, I + j); for (i = l - 1; i >= 0 && (g->length > 1); i-- ) { /* compute f^{[l*(j+1)-i]} */ nmod_poly_sub(tmp, H + j, h + i); nmod_poly_gcd(f, g, tmp); if (f->length > 1) { /* insert f^{[l*(j+1)-i]} into res */ nmod_poly_make_monic(f, f); nmod_poly_factor_insert(res, f, 1); (*degs)[index++] = l*(j + 1) - i; nmod_poly_remove(g, f); } } } else if (I[j].length > 1) { nmod_poly_make_monic(I + j, I + j); nmod_poly_factor_insert(res, I + j, 1); (*degs)[index++] = I[j].length - 1; } } /* cleanup */ nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(v); nmod_poly_clear(vinv); nmod_poly_clear(tmp); nmod_mat_clear(HH); for (i = 0; i < l + 1; i++) nmod_poly_clear(h + i); for (i = 0; i < m; i++) { nmod_poly_clear(H + i); nmod_poly_clear(I + i); } flint_free(h); } flint-3.1.3/src/nmod_poly_factor/factor_distinct_deg_threaded.c000066400000000000000000000520141461254215100247640ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2013, 2014 Martin Lee Copyright (C) 2020, 2022 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #ifdef __GNUC__ # define ceil __builtin_ceil # define log __builtin_log # define pow __builtin_pow #else # include #endif void _nmod_poly_precompute_matrix_worker(void * arg_ptr) { nmod_poly_matrix_precompute_arg_t arg = *((nmod_poly_matrix_precompute_arg_t *) arg_ptr); /* Set rows of A to powers of poly1 */ slong i, n, m; nmod_poly_struct * poly1 = arg.poly1; nmod_poly_struct * poly2 = arg.poly2; nmod_poly_struct * poly2inv = arg.poly2inv; nmod_mat_struct * A = arg.A; nmod_t mod = poly2->mod; n = poly2->length - 1; m = n_sqrt(n) + 1; for (i = 1; i < n; i++) A->rows[0][i] = 0; A->rows[0][0] = 1; _nmod_vec_set(A->rows[1], poly1->coeffs, n); for (i = 2; i < m; i++) _nmod_poly_mulmod_preinv(A->rows[i], A->rows[i - 1], n, poly1->coeffs, n, poly2->coeffs, n + 1, poly2inv->coeffs, n + 1, mod); } void _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr) { nmod_poly_compose_mod_precomp_preinv_arg_t arg = *((nmod_poly_compose_mod_precomp_preinv_arg_t*) arg_ptr); nmod_mat_t B, C; mp_ptr t, h; slong i, n, m; nmod_poly_struct * res = arg.res; nmod_poly_struct * poly1 = arg.poly1; nmod_poly_struct * poly3 = arg.poly3; nmod_poly_struct * poly3inv = arg.poly3inv; nmod_mat_struct * A = arg.A; nmod_t mod = poly3->mod; if (poly3->length == 1) return; if (poly1->length == 1) { res->coeffs[0] = poly1->coeffs[0]; return; } if (poly3->length == 2) { res->coeffs[0] = _nmod_poly_evaluate_nmod(poly1->coeffs, poly1->length, A->rows[1][0], mod); return; } n = poly3->length - 1; m = n_sqrt(n) + 1; nmod_mat_init(B, m, m, mod.n); nmod_mat_init(C, m, n, mod.n); h = _nmod_vec_init(n); t = _nmod_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < poly1->length/m; i++) _nmod_vec_set(B->rows[i], poly1->coeffs + i * m, m); _nmod_vec_set(B->rows[i], poly1->coeffs + i * m, poly1->length % m); nmod_mat_mul(C, B, A); /* Evaluate block composition using the Horner scheme */ _nmod_vec_set(res->coeffs, C->rows[m - 1], n); _nmod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly3->coeffs, poly3->length, poly3inv->coeffs, poly3inv->length, mod); for (i = m - 2; i >= 0; i--) { _nmod_poly_mulmod_preinv(t, res->coeffs, n, h, n, poly3->coeffs, poly3->length, poly3inv->coeffs, poly3->length, mod); _nmod_poly_add(res->coeffs, t, n, C->rows[i], n, mod); } _nmod_vec_clear(h); _nmod_vec_clear(t); nmod_mat_clear(B); nmod_mat_clear(C); } void _nmod_poly_interval_poly_worker(void * arg_ptr) { nmod_poly_interval_poly_arg_t arg = *((nmod_poly_interval_poly_arg_t *) arg_ptr); slong k, m = arg.m; nmod_poly_struct * H = arg.H; nmod_poly_struct * res = arg.res; nmod_poly_struct * v = arg.v; nmod_poly_struct * vinv = arg.vinv; nmod_poly_struct * baby = arg.baby; nmod_t mod = v->mod; mp_ptr tmp = arg.tmp; res->coeffs[0] = 1; for (k = m - 1; k >= 0; k--) { flint_mpn_zero(tmp, v->length - 1); if (baby[k].length < v->length) _nmod_vec_set(tmp, baby[k].coeffs, baby[k].length); else _nmod_poly_rem(tmp, baby[k].coeffs, baby[k].length, v->coeffs, v->length, mod); _nmod_poly_sub(tmp, H->coeffs, H->length, tmp, v->length - 1, mod); _nmod_poly_mulmod_preinv(res->coeffs, tmp, v->length - 1, res->coeffs, v->length - 1, v->coeffs, v->length, vinv->coeffs, vinv->length, mod); } } void nmod_poly_factor_distinct_deg_threaded(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const * degs) { nmod_poly_t f, g, v, vinv, tmp, II; nmod_poly_struct * h, * H, * I, * scratch; slong i, j, k, l, m, n, index, d, c1 = 1, c2; nmod_mat_struct * HH; double beta; thread_pool_handle * threads; slong num_threads; nmod_poly_matrix_precompute_arg_t * args1; nmod_poly_compose_mod_precomp_preinv_arg_t * args2; nmod_poly_interval_poly_arg_t * args3; n = nmod_poly_degree(poly); nmod_poly_init_mod(v, poly->mod); nmod_poly_make_monic(v, poly); if (n == 1) { nmod_poly_factor_insert(res, v, 1); (*degs)[0] = 1; nmod_poly_clear(v); return; } beta = 0.5 * (1. - log(2)/log(n)); l = ceil(pow(n, beta)); m = ceil(0.5*n/l); /* initialization */ nmod_poly_init_mod(f, poly->mod); nmod_poly_init_mod(g, poly->mod); nmod_poly_init_mod(vinv, poly->mod); nmod_poly_init_mod(tmp, poly->mod); nmod_poly_init_mod(II, poly->mod); num_threads = flint_request_threads(&threads, flint_get_num_threads()); h = flint_malloc((2 * m + l + num_threads + 2) * sizeof(nmod_poly_struct)); for (i = 0; i < 2*m + l + 2 + num_threads; i++) nmod_poly_init_mod(h + i, poly->mod); H = h + (l + 1); I = H + m; scratch = I + m; HH = (nmod_mat_struct *) flint_malloc(sizeof(nmod_mat_struct)*(num_threads + 2)); args1 = (nmod_poly_matrix_precompute_arg_t *) flint_malloc((num_threads + 1)* sizeof(nmod_poly_matrix_precompute_arg_t)); args2 = (nmod_poly_compose_mod_precomp_preinv_arg_t *) flint_malloc((num_threads + 1)* sizeof(nmod_poly_compose_mod_precomp_preinv_arg_t)); args3 = (nmod_poly_interval_poly_arg_t *) flint_malloc((num_threads + 1)* sizeof(nmod_poly_interval_poly_arg_t)); nmod_poly_reverse(vinv, v, v->length); nmod_poly_inv_series(vinv, vinv, v->length); /* compute baby steps: h[i] = x^{p^i} mod v */ nmod_poly_set_coeff_ui(h + 0, 1, 1); nmod_poly_powmod_x_ui_preinv(h + 1, poly->mod.n, v, vinv); if (FLINT_BIT_COUNT(poly->mod.n) > ((n_sqrt(v->length - 1) + 1)*3)/4) { for (i = 1; i < FLINT_BIT_COUNT(l); i++) nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(h + 1 + (1 << (i - 1)), h + 1, 1 << (i - 1), 1 << (i - 1), h + (1 << (i - 1)), v, vinv, threads, num_threads); nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool(h + 1 + (1 << (i - 1)), h + 1, 1 << (i - 1), l - (1 << (i - 1)), h + (1 << (i - 1)), v, vinv, threads, num_threads); } else { for (i = 2; i < l + 1; i++) { nmod_poly_init_mod(h + i, poly->mod); nmod_poly_powmod_ui_binexp_preinv(h + i, h + i - 1, poly->mod.n, v, vinv); } } /* compute coarse distinct-degree factorisation */ index = 0; nmod_poly_set(H + 0, h + l); nmod_mat_init(HH + 0, n_sqrt(v->length - 1) + 1, v->length - 1, poly->mod.n); nmod_poly_precompute_matrix(HH + 0, H + 0, v, vinv); for (d = 1, j = 0; j < m/(num_threads + 1) + 1; j++) { if (j == 0) { for (i = 0; i < num_threads + 1; i++) { if (i > 0 && I[i - 1].length > 1) { _nmod_poly_reduce_matrix_mod_poly(HH + num_threads + 1, HH + 0, v); nmod_mat_clear(HH + 0); nmod_mat_init_set(HH + 0, HH + num_threads + 1); nmod_mat_clear(HH + num_threads + 1); nmod_poly_rem(tmp, H + i - 1, v); nmod_poly_compose_mod_brent_kung_precomp_preinv(H + i, tmp, HH + 0, v, vinv); } else if (i > 0) nmod_poly_compose_mod_brent_kung_precomp_preinv(H + i, H + i - 1, HH + 0, v, vinv); /* compute interval polynomials */ nmod_poly_one(I + i); for (k = l - 1; k >= 0 && 2*d <= v->length - 1; k--, d++) { nmod_poly_rem(tmp, h + k, v); nmod_poly_sub(tmp, H + i, tmp); nmod_poly_mulmod_preinv(I + i, tmp, I + i, v, vinv); } /* compute F_j=f^{[j*l+1]} * ... * f^{[j*l+l]} F_j is stored on the place of I_j */ nmod_poly_gcd(I + i, v, I + i); if (I[i].length > 1) { nmod_poly_remove(v, I + i); nmod_poly_reverse(vinv, v, v->length); nmod_poly_inv_series_newton(vinv, vinv, v->length); } if (v->length - 1 < 2*d) break; } if (v->length - 1 < 2*d) break; } else if (j == 1 && num_threads + 1 < m) { if (I[num_threads].length > 1) { _nmod_poly_reduce_matrix_mod_poly(HH + num_threads + 1, HH + 0, v); nmod_mat_clear(HH + 0); nmod_mat_init_set(HH + 0, HH + num_threads + 1); nmod_mat_clear(HH + num_threads + 1); } /* we make thread 0 the master thread, but don't use it in this loop */ for (c1 = 1, i = 1; i < num_threads + 1 && i + num_threads + 1 < m; i++, c1++) { nmod_mat_init(HH + i, n_sqrt(v->length - 1) + 1, v->length - 1, poly->mod.n); nmod_poly_rem(scratch + i, H + i, v); if (scratch[i].length < v->length - 1) { nmod_poly_fit_length(scratch + i, v->length - 1); flint_mpn_zero(scratch[i].coeffs + scratch[i].length, v->length - 1 - scratch[i].length); _nmod_poly_set_length(scratch + i, v->length - 1); } args1[i].A = HH + i; args1[i].poly1 = scratch + i; args1[i].poly2 = v; args1[i].poly2inv = vinv; thread_pool_wake(global_thread_pool, threads[i - 1], 0, _nmod_poly_precompute_matrix_worker, &args1[i]); } for (i = 1; i < c1; i++) thread_pool_wait(global_thread_pool, threads[i - 1]); nmod_poly_rem(tmp, H + num_threads, v); for (i = 0; i < c1; i++) { nmod_poly_fit_length(H + num_threads + 1 + i, v->length - 1); _nmod_poly_set_length(H + num_threads + 1 + i, v->length - 1); flint_mpn_zero(H[num_threads + 1 + i].coeffs, v->length - 1); args2[i].A = HH + i; args2[i].res = H + num_threads + i + 1; args2[i].poly1 = tmp; args2[i].poly3 = v; args2[i].poly3inv = vinv; } for (i = 1; i < c1; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker, &args2[i]); } _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker(&args2[0]); _nmod_poly_normalise(H + num_threads + 1); for (i = 1; i < c1; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _nmod_poly_normalise(H + num_threads + i + 1); } for (i = 0; i < c1; i++) { nmod_poly_fit_length(I + num_threads + i + 1, v->length - 1); _nmod_poly_set_length(I + num_threads + i + 1, v->length - 1); flint_mpn_zero(I[num_threads + i + 1].coeffs, v->length - 1); args3[i].baby = h; args3[i].H = H + num_threads + i + 1; args3[i].m = l; args3[i].res = I + num_threads + i + 1; args3[i].v = v; args3[i].vinv = vinv; args3[i].tmp = _nmod_vec_init(v->length - 1); } for (i = 1; i < c1; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _nmod_poly_interval_poly_worker, &args3[i]); } _nmod_poly_interval_poly_worker(&args3[0]); _nmod_poly_normalise(I + num_threads + 1); for (i = 1; i < c1; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _nmod_poly_normalise(I + num_threads + i + 1); } for (i = 0; i < c1; i++) { _nmod_vec_clear(args3[i].tmp); } nmod_poly_one(II); for (i = 0; i < c1; i++) nmod_poly_mulmod_preinv(II, II, I + num_threads + i + 1, v, vinv); nmod_poly_gcd(II, v, II); if (II->length > 1) { nmod_poly_remove(v, II); nmod_poly_reverse(vinv, v, v->length); nmod_poly_inv_series_newton(vinv, vinv, v->length); for (i = 0; i < c1; i++) { nmod_poly_gcd(I + num_threads + i + 1, I + num_threads + i + 1, II); if (I[num_threads + i + 1].length > 1) nmod_poly_remove(II, I + num_threads + i + 1); } } else { for (i = 0; i < c1; i++) nmod_poly_one(I + num_threads + i + 1); } d = d + c1*l; if (v->length - 1 < 2*d) break; } else if (j*(num_threads + 1) < m) { for (c2 = 0, i = 0; i < num_threads + 1 && j*(num_threads + 1) + i < m; i++, c2++) { if (HH[i].c > v->length - 1) { _nmod_poly_reduce_matrix_mod_poly(HH + num_threads + 1, HH + i, v); nmod_mat_clear(HH + i); nmod_mat_init_set(HH + i, HH + num_threads + 1); nmod_mat_clear(HH + num_threads + 1); } } nmod_poly_rem(tmp, H + j *(num_threads + 1) - 1, v); for (i = 0; i < c2; i++) { nmod_poly_fit_length(H + j*(num_threads + 1) + i, v->length - 1); _nmod_poly_set_length(H + j*(num_threads + 1) + i, v->length - 1); flint_mpn_zero(H[j*(num_threads + 1) + i].coeffs, v->length - 1); args2[i].A = HH + i; args2[i].res = H + j*(num_threads + 1) + i; args2[i].poly1 = tmp; args2[i].poly3 = v; args2[i].poly3inv = vinv; } for (i = 1; i < c2; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker, &args2[i]); } _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker(&args2[0]); _nmod_poly_normalise(H + j*(num_threads + 1)); for (i = 1; i < c2; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _nmod_poly_normalise(H + j*(num_threads + 1) + i); } for (i = 0; i < c2; i++) { nmod_poly_fit_length(I + j*(num_threads + 1) + i, v->length - 1); _nmod_poly_set_length(I + j*(num_threads + 1) + i, v->length - 1); flint_mpn_zero(I[j*(num_threads + 1) + i].coeffs, v->length - 1); args3[i].baby = h; args3[i].H = H + j*(num_threads + 1) + i; args3[i].m = l; args3[i].res = I + j*(num_threads + 1) + i; args3[i].v = v; args3[i].vinv = vinv; args3[i].tmp = _nmod_vec_init(v->length - 1); } for (i = 1; i < c2; i++) { thread_pool_wake(global_thread_pool, threads[i - 1], 0, _nmod_poly_interval_poly_worker, &args3[i]); } _nmod_poly_interval_poly_worker(&args3[0]); _nmod_poly_normalise(I + j*(num_threads + 1)); for (i = 1; i < c2; i++) { thread_pool_wait(global_thread_pool, threads[i - 1]); _nmod_poly_normalise(I + j*(num_threads + 1) + i); } for (i = 0; i < c2; i++) { _nmod_vec_clear(args3[i].tmp); } nmod_poly_one(II); for (i = 0; i < c2; i++) nmod_poly_mulmod_preinv(II, II, I + j*(num_threads + 1) + i, v, vinv); nmod_poly_gcd(II, v, II); if (II->length > 1) { nmod_poly_remove(v, II); nmod_poly_reverse(vinv, v, v->length); nmod_poly_inv_series_newton(vinv, vinv, v->length); for (i = 0; i < c2; i++) { nmod_poly_gcd(I + j*(num_threads + 1) + i, I + j*(num_threads + 1) + i, II); if (I[j*(num_threads + 1) + i].length > 1) nmod_poly_remove(II, I + j*(num_threads + 1) + i); } } else { for (i = 0; i < c2; i++) nmod_poly_one(I + j*(num_threads + 1) + i); } d = d + c2*l; if (v->length - 1 < 2*d) break; } } if (v->length > 1) { nmod_poly_factor_insert(res, v, 1); (*degs)[index++] = v->length - 1; } /* compute fine distinct-degree factorisation */ for (j = 0; j < m; j++) { if (I[j].length - 1 > (j + 1)*l || j == 0) { nmod_poly_set(g, I + j); for (i = l - 1; i >= 0 && g->length > 1; i--) { /* compute f^{[l*(j+1)-i]} */ nmod_poly_sub(tmp, H + j, h + i); nmod_poly_gcd(f, g, tmp); if (f->length > 1) { /* insert f^{[l*(j+1)-i]} into res */ nmod_poly_make_monic(f, f); nmod_poly_factor_insert(res, f, 1); (*degs)[index++] = l*(j + 1) - i; nmod_poly_remove(g, f); } } } else if (I[j].length > 1) { nmod_poly_make_monic(I + j, I + j); nmod_poly_factor_insert(res, I + j, 1); (*degs)[index++] = I[j].length-1; } } flint_give_back_threads(threads, num_threads); /* cleanup */ nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(v); nmod_poly_clear(vinv); nmod_poly_clear(tmp); nmod_poly_clear(II); for (i = 0; i < 2*m + l + num_threads + 2; i++) nmod_poly_clear(h + i); for (i = 0; i < c1; i++) nmod_mat_clear(HH + i); flint_free(h); flint_free(HH); flint_free(args1); flint_free(args2); flint_free(args3); } flint-3.1.3/src/nmod_poly_factor/factor_equal_deg.c000066400000000000000000000024161461254215100224130ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010, 2022 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_equal_deg(nmod_poly_factor_t factors, const nmod_poly_t pol, slong d) { if (pol->length == d + 1) { nmod_poly_factor_insert(factors, pol, 1); } else { nmod_poly_t f, g; flint_rand_t state; nmod_poly_init_mod(f, pol->mod); flint_randinit(state); while (!nmod_poly_factor_equal_deg_prob(f, state, pol, d)) ; flint_randclear(state); nmod_poly_init_mod(g, pol->mod); nmod_poly_divexact(g, pol, f); nmod_poly_factor_equal_deg(factors, f, d); nmod_poly_clear(f); nmod_poly_factor_equal_deg(factors, g, d); nmod_poly_clear(g); } } flint-3.1.3/src/nmod_poly_factor/factor_equal_deg_prob.c000066400000000000000000000050101461254215100234260ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2022 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" int nmod_poly_factor_equal_deg_prob(nmod_poly_t factor, flint_rand_t state, const nmod_poly_t pol, slong d) { nmod_poly_t a, b, c, polinv; fmpz_t exp; int res = 1; slong i; if (pol->length <= 1) { flint_throw(FLINT_ERROR, "Exception (nmod_poly_factor_equal_deg_prob): Input polynomial is linear.\n"); } nmod_poly_init_mod(a, pol->mod); do { nmod_poly_randtest(a, state, pol->length - 1); } while (a->length <= 1); nmod_poly_gcd(factor, a, pol); if (factor->length != 1) { nmod_poly_clear(a); return 1; } nmod_poly_init_mod(b, pol->mod); nmod_poly_init_mod(polinv, pol->mod); nmod_poly_reverse(polinv, pol, pol->length); nmod_poly_inv_series(polinv, polinv, polinv->length); fmpz_init(exp); if (pol->mod.n > 2) { /* compute a^{(p^d-1)/2} rem pol */ fmpz_ui_pow_ui(exp, pol->mod.n, d); fmpz_sub_ui(exp, exp, 1); fmpz_tdiv_q_2exp(exp, exp, 1); nmod_poly_powmod_fmpz_binexp_preinv(b, a, exp, pol, polinv); } else { /* compute b = (a^{2^{d-1}}+a^{2^{d-2}}+...+a^4+a^2+a) rem pol */ nmod_poly_rem(b, a, pol); nmod_poly_init_mod(c, pol->mod); nmod_poly_set(c, b); for (i = 1; i < d; i++) { /* c = a^{2^i} = (a^{2^{i-1}})^2 */ nmod_poly_powmod_ui_binexp_preinv(c, c, 2, pol, polinv); nmod_poly_add(b, b, c); } nmod_poly_rem(b, b, pol); nmod_poly_clear(c); } fmpz_clear(exp); nmod_poly_set_coeff_ui(b, 0, n_submod(b->coeffs[0], 1, pol->mod.n)); nmod_poly_gcd(factor, b, pol); if (factor->length <= 1 || factor->length == pol->length) res = 0; nmod_poly_clear(polinv); nmod_poly_clear(a); nmod_poly_clear(b); return res; } flint-3.1.3/src/nmod_poly_factor/factor_kaltofen_shoup.c000066400000000000000000000041471461254215100235110ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2022 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_kaltofen_shoup(nmod_poly_factor_t res, const nmod_poly_t poly) { nmod_poly_t v; nmod_poly_factor_t sq_free, dist_deg; slong i, j, k, l, res_num, dist_deg_num; slong * degs; nmod_poly_init_mod(v, poly->mod); nmod_poly_make_monic(v, poly); if (poly->length <= 2) { nmod_poly_factor_insert (res, v, 1); nmod_poly_clear (v); return; } degs = flint_malloc(nmod_poly_degree(poly) * sizeof(slong)); /* compute squarefree factorisation */ nmod_poly_factor_init(sq_free); nmod_poly_factor_squarefree(sq_free, v); /* compute distinct-degree factorisation */ nmod_poly_factor_init(dist_deg); for (i = 0; i < sq_free->num; i++) { dist_deg_num = dist_deg->num; if ((flint_get_num_threads() > 1) && ((sq_free->p + i)->length > (1024*flint_get_num_threads())/4)) nmod_poly_factor_distinct_deg_threaded(dist_deg, sq_free->p + i, °s); else nmod_poly_factor_distinct_deg(dist_deg, sq_free->p + i, °s); /* compute equal-degree factorisation */ for (j = dist_deg_num, l = 0; j < dist_deg->num; j++, l++) { res_num = res->num; nmod_poly_factor_equal_deg(res, dist_deg->p + j, degs[l]); for (k = res_num; k < res->num; k++) res->exp[k] = nmod_poly_remove(v, res->p + k); } } flint_free(degs); nmod_poly_clear(v); nmod_poly_factor_clear(dist_deg); nmod_poly_factor_clear(sq_free); } flint-3.1.3/src/nmod_poly_factor/factor_squarefree.c000066400000000000000000000072131461254215100226270ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010, 2022 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_squarefree(nmod_poly_factor_t res, const nmod_poly_t f) { nmod_poly_t f_d, g, g_1; mp_limb_t p; slong deg, i; if (f->length <= 1) { res->num = 0; return; } if (f->length == 2) { nmod_poly_factor_insert(res, f, 1); nmod_poly_make_monic(res->p + (res->num - 1), res->p + (res->num - 1)); return; } p = nmod_poly_modulus(f); deg = nmod_poly_degree(f); /* Step 1, look at f', if it is zero then we are done since f = h(x)^p for some particular h(x), clearly f(x) = sum a_k x^kp, k <= deg(f) */ nmod_poly_init_mod(g_1, f->mod); nmod_poly_init_mod(f_d, f->mod); nmod_poly_init_mod(g, f->mod); nmod_poly_derivative(f_d, f); /* Case 1 */ if (nmod_poly_is_zero(f_d)) { nmod_poly_factor_t new_res; nmod_poly_t h; nmod_poly_init_mod(h, f->mod); for (i = 0; i <= deg/p; i++) /* this will be an integer since f'=0 */ { nmod_poly_set_coeff_ui(h, i, nmod_poly_get_coeff_ui(f, i*p)); } /* Now run square-free on h, and return it to the pth power */ nmod_poly_factor_init(new_res); nmod_poly_factor_squarefree(new_res, h); nmod_poly_factor_pow(new_res, p); nmod_poly_factor_concat(res, new_res); nmod_poly_clear(h); nmod_poly_factor_clear(new_res); } else { nmod_poly_t h, z; nmod_poly_gcd(g, f, f_d); nmod_poly_divexact(g_1, f, g); i = 1; nmod_poly_init_mod(h, f->mod); nmod_poly_init_mod(z, f->mod); /* Case 2 */ while (!nmod_poly_is_one(g_1)) { nmod_poly_gcd(h, g_1, g); nmod_poly_divexact(z, g_1, h); /* out <- out.z */ if (z->length > 1) { nmod_poly_factor_insert(res, z, 1); nmod_poly_make_monic(res->p + (res->num - 1), res->p + (res->num - 1)); if (res->num) res->exp[res->num - 1] *= i; } i++; nmod_poly_set(g_1, h); nmod_poly_divexact(g, g, h); } nmod_poly_clear(h); nmod_poly_clear(z); nmod_poly_make_monic(g, g); if (!nmod_poly_is_one(g)) { /* so now we multiply res with square-free(g^1/p) ^ p */ nmod_poly_t g_p; /* g^(1/p) */ nmod_poly_factor_t new_res_2; nmod_poly_init_mod(g_p, f->mod); for (i = 0; i <= nmod_poly_degree(g)/p; i++) nmod_poly_set_coeff_ui(g_p, i, nmod_poly_get_coeff_ui(g, i*p)); nmod_poly_factor_init(new_res_2); /* square-free(g^(1/p)) */ nmod_poly_factor_squarefree(new_res_2, g_p); nmod_poly_factor_pow(new_res_2, p); nmod_poly_factor_concat(res, new_res_2); nmod_poly_clear(g_p); nmod_poly_factor_clear(new_res_2); } } nmod_poly_clear(g_1); nmod_poly_clear(f_d); nmod_poly_clear(g); } flint-3.1.3/src/nmod_poly_factor/fit_length.c000066400000000000000000000013671461254215100212560ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2008, 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_fit_length(nmod_poly_factor_t fac, slong len) { if (len > fac->alloc) { /* At least double number of allocated coeffs */ if (len < 2 * fac->alloc) len = 2 * fac->alloc; nmod_poly_factor_realloc(fac, len); } } flint-3.1.3/src/nmod_poly_factor/get_poly.c000066400000000000000000000010511461254215100207430ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_get_poly(nmod_poly_t a, const nmod_poly_factor_t b, slong i) { nmod_poly_set(a, b->p + i); } flint-3.1.3/src/nmod_poly_factor/init.c000066400000000000000000000015441461254215100200730ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_init(nmod_poly_factor_t fac) { slong i; fac->alloc = 5; fac->num = 0; fac->p = flint_malloc(sizeof(nmod_poly_struct) * 5); fac->exp = flint_malloc(sizeof(slong) * 5); for (i = 0; i < 5; i++) nmod_poly_init_preinv(fac->p + i, 1, 0); } flint-3.1.3/src/nmod_poly_factor/inlines.c000066400000000000000000000006751461254215100205750ustar00rootroot00000000000000/* Copyright (C) 2015 Tommy Hofmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_POLY_FACTOR_INLINES_C #include "nmod_poly_factor.h" flint-3.1.3/src/nmod_poly_factor/insert.c000066400000000000000000000026111461254215100204300ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_insert(nmod_poly_factor_t fac, const nmod_poly_t poly, slong exp) { slong i; if (poly->length <= 1) return; for (i = 0; i < fac->num; i++) { if (nmod_poly_equal(poly, fac->p + i)) { fac->exp[i] += exp; return; } } if (fac->alloc == fac->num) { slong new_size = 2 * fac->alloc; fac->p = flint_realloc(fac->p, sizeof(nmod_poly_struct) * new_size); fac->exp = flint_realloc(fac->exp, sizeof(slong) * new_size); for (i = fac->alloc; i < new_size; i++) nmod_poly_init_preinv(fac->p + i, 1, 0); fac->alloc = new_size; } nmod_poly_set(fac->p + (fac->num), poly); (fac->p + (fac->num))->mod = poly->mod; fac->exp[fac->num] = exp; fac->num++; } flint-3.1.3/src/nmod_poly_factor/is_irreducible.c000066400000000000000000000137601461254215100221170ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007-2010, 2020, 2022 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" int nmod_poly_is_irreducible_ddf(const nmod_poly_t poly) { nmod_poly_t f, v, vinv, tmp; nmod_poly_struct * h, * H, * I; nmod_mat_t HH; slong i, j, l, m, n, d; double beta; int result = 1; n = nmod_poly_degree(poly); if (n < 2) return 1; if (!nmod_poly_is_squarefree(poly)) return 0; beta = 0.5 * (1. - (log(2)/log(n))); l = ceil(pow (n, beta)); m = ceil(0.5*n/l); /* initialization */ nmod_poly_init_mod(f, poly->mod); nmod_poly_init_mod(v, poly->mod); nmod_poly_init_mod(vinv, poly->mod); nmod_poly_init_mod(tmp, poly->mod); h = flint_malloc((2 * m + l + 1) * sizeof(nmod_poly_struct)); H = h + (l + 1); I = H + m; for (i = 0; i < 2*m + l + 1; i++) nmod_poly_init_mod(h + i, poly->mod); nmod_poly_make_monic(v, poly); nmod_poly_reverse(vinv, v, v->length); nmod_poly_inv_series(vinv, vinv, v->length); /* compute baby steps: h[i] = x^{p^i}mod v */ nmod_poly_set_coeff_ui(h + 0, 1, 1); nmod_poly_powmod_x_ui_preinv(h + 1, poly->mod.n, v, vinv); if (FLINT_BIT_COUNT(poly->mod.n) > ((n_sqrt(v->length - 1) + 1)*3)/4) { for (i = 1; i < FLINT_BIT_COUNT (l); i++) nmod_poly_compose_mod_brent_kung_vec_preinv(h + 1 + (1 << (i - 1)), h + 1, (1 << (i - 1)), (1 << (i - 1)), h + (1 << (i - 1)), v, vinv); nmod_poly_compose_mod_brent_kung_vec_preinv(h + 1 + (1 << (i - 1)), h + 1, (1 << (i - 1)), l - (1 << (i - 1)), h + (1 << (i - 1)), v, vinv); } else { for (i = 2; i < l + 1; i++) { nmod_poly_init_mod(h + i, poly->mod); nmod_poly_powmod_ui_binexp_preinv(h + i, h + i - 1, poly->mod.n, v, vinv); } } /* compute coarse distinct-degree factorisation */ nmod_poly_set(H + 0, h + l); nmod_mat_init(HH, n_sqrt(v->length - 1) + 1, v->length - 1, poly->mod.n); nmod_poly_precompute_matrix(HH, H + 0, v, vinv); d = 1; for (j = 0; j < m; j++) { /* compute giant steps: H[j] = x^{p^(lj)}mod s */ if (j > 0) nmod_poly_compose_mod_brent_kung_precomp_preinv(H + j, H + j - 1, HH, v, vinv); /* compute interval polynomials */ nmod_poly_set_coeff_ui(I + j, 0, 1); for (i = l - 1; i >= 0 && 2*d <= v->length - 1; i--, d++) { nmod_poly_rem(tmp, h + i, v); nmod_poly_sub(tmp, H + j, tmp); nmod_poly_mulmod_preinv (I + j, tmp, I + j, v, vinv); } /* compute F_j=f^{[j*l+1]} * ... * f^{[j*l+l]} */ /* F_j is stored on the place of I_j */ nmod_poly_gcd(I + j, v, I + j); if (I[j].length > 1) { result = 0; break; } } nmod_poly_clear(f); nmod_poly_clear(v); nmod_poly_clear(vinv); nmod_poly_clear(tmp); nmod_mat_clear (HH); for (i = 0; i < l + 1; i++) nmod_poly_clear(h + i); for (i = 0; i < m; i++) { nmod_poly_clear(H + i); nmod_poly_clear(I + i); } flint_free (h); return result; } int nmod_poly_is_irreducible(const nmod_poly_t f) { if (nmod_poly_length(f) > 2) return nmod_poly_is_irreducible_ddf(f); return 1; } void nmod_poly_powpowmod(nmod_poly_t res, const nmod_poly_t pol, ulong exp, ulong exp2, const nmod_poly_t f) { nmod_poly_t pow; ulong i; nmod_poly_init_mod(pow, f->mod); nmod_poly_powmod_ui_binexp(pow, pol, exp, f); nmod_poly_set(res, pow); if (!nmod_poly_equal(pow, pol)) for (i = 1; i < exp2; i++) nmod_poly_powmod_ui_binexp(res, res, exp, f); nmod_poly_clear(pow); } int nmod_poly_is_irreducible_rabin(const nmod_poly_t f) { if (nmod_poly_length(f) > 2) { const mp_limb_t p = nmod_poly_modulus(f); const slong n = nmod_poly_degree(f); nmod_poly_t a, x, x_p; nmod_poly_init(a, p); nmod_poly_init(x, p); nmod_poly_init(x_p, p); nmod_poly_set_coeff_ui(x, 1, 1); /* Compute x^q mod f */ nmod_poly_powpowmod(x_p, x, p, n, f); if (!nmod_poly_is_zero(x_p)) nmod_poly_make_monic(x_p, x_p); /* Now do the irreducibility test */ if (!nmod_poly_equal(x_p, x)) { nmod_poly_clear(a); nmod_poly_clear(x); nmod_poly_clear(x_p); return 0; } else { n_factor_t factors; slong i; n_factor_init(&factors); n_factor(&factors, n, 1); for (i = 0; i < factors.num; i++) { nmod_poly_powpowmod(a, x, p, n/factors.p[i], f); nmod_poly_sub(a, a, x); if (!nmod_poly_is_zero(a)) nmod_poly_make_monic(a, a); nmod_poly_gcd(a, a, f); if (a->length != 1) { nmod_poly_clear(a); nmod_poly_clear(x); nmod_poly_clear(x_p); return 0; } } } nmod_poly_clear(a); nmod_poly_clear(x); nmod_poly_clear(x_p); } return 1; } flint-3.1.3/src/nmod_poly_factor/is_squarefree.c000066400000000000000000000021031461254215100217550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpn_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" int _nmod_poly_is_squarefree(mp_srcptr f, slong len, nmod_t mod) { mp_ptr fd, g; slong dlen; int res; if (len <= 2) return len != 0; fd = flint_malloc(sizeof(mp_limb_t) * 2 * (len - 1)); g = fd + len - 1; _nmod_poly_derivative(fd, f, len, mod); dlen = len - 1; MPN_NORM(fd, dlen); if (dlen) res = (_nmod_poly_gcd(g, f, len, fd, dlen, mod) == 1); else res = 0; /* gcd(f, 0) = f, and len(f) > 2 */ flint_free(fd); return res; } int nmod_poly_is_squarefree(const nmod_poly_t f) { return _nmod_poly_is_squarefree(f->coeffs, f->length, f->mod); } flint-3.1.3/src/nmod_poly_factor/pow.c000066400000000000000000000012611461254215100177310ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly_factor.h" void nmod_poly_factor_pow(nmod_poly_factor_t fac, slong exp) { slong i; for (i = 0; i < fac->num; i++) fac->exp[i] *= exp; } flint-3.1.3/src/nmod_poly_factor/print.c000066400000000000000000000020421461254215100202560ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_print(const nmod_poly_factor_t fac) { slong i; for (i = 0; i < fac->num; i++) { nmod_poly_print(fac->p + i); flint_printf(" ^ %wd\n", fac->exp[i]); } } void nmod_poly_factor_print_pretty(const nmod_poly_factor_t fac, const char *var) { slong i; for (i = 0; i < fac->num; i++) { nmod_poly_print_pretty(fac->p + i, var); flint_printf(" ^ %wd\n", fac->exp[i]); } } flint-3.1.3/src/nmod_poly_factor/profile/000077500000000000000000000000001461254215100204205ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly_factor/profile/p-factor.c000066400000000000000000000232731461254215100223060ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #define NP 100 /* number of moduli */ #define ND 8 /* number of degrees */ /* Benchmarking code for factorisation in nmod_poly. Test how the relation between n (degree of polynomial) and p affects working time for Cantor-Zassenhaus, Berlekamp and Kaltofen-Shoup algorithms. p and n are chosen independently. */ int main(void) { nmod_poly_t f, g; nmod_poly_factor_t res; mp_limb_t modulus; int i, j, k, n, num; double t, T1, T2, T3, T4; const slong degs[] = {8, 16, 32, 64, 128, 256, 512, 1024}; const int iter_count[] = {10000, 5000, 1000, 500, 300, 100, 50, 20}; FLINT_TEST_INIT(state); flint_printf("Random polynomials\n"); for (i = 0; i < NP; i++) { modulus = n_randtest_prime(state, 0); flint_printf("========== p: %wu\n", modulus); fflush(stdout); for (j = 0; j < ND; j++) { n = degs[j]; flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { nmod_poly_init(f, modulus); nmod_poly_randtest_not_zero(f, state, n); t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_cantor_zassenhaus(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_berlekamp(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_kaltofen_shoup(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; nmod_poly_clear(f); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } } /* This code checks whether nmod_poly_factor made a correct choice between CZ, B and KS */ flint_printf("Check choice correctness\n"); for (i = 0; i < NP; i++) { modulus = n_randtest_prime(state, 0); flint_printf("========== p: %wu\n", modulus); fflush(stdout); for (j = 0; j < ND; j++) { n = degs[j]; flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; T4 = 0; for (k = 0; k < iter_count[j]; k++) { nmod_poly_init(f, modulus); nmod_poly_randtest_not_zero(f, state, n); t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_cantor_zassenhaus(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_berlekamp(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_kaltofen_shoup(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T4 += t; nmod_poly_clear(f); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf F: %.2lf\n", T1, T2, T3, T4); fflush(stdout); if (T1 > T3 + 1) break; } } flint_printf("Irreducible polynomials\n"); for (i = 0; i < NP; i++) { modulus = n_randtest_prime(state, 0); flint_printf("========== p: %wu\n", modulus); fflush(stdout); for (j = 0; j < ND; j++) { n = degs[j]; flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { nmod_poly_init(f, modulus); nmod_poly_randtest_irreducible(f, state, n); t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_cantor_zassenhaus(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_berlekamp(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_kaltofen_shoup(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; nmod_poly_clear(f); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } } flint_printf("Product of two irreducible polynomials\n"); for (i = 0; i < NP; i++) { modulus = n_randtest_prime(state, 0); flint_printf("========== p: %wu\n", modulus); fflush(stdout); for (j = 0; j < ND; j++) { n = (degs[j] >> 1); flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { nmod_poly_init(f, modulus); nmod_poly_init(g, modulus); nmod_poly_randtest_irreducible(f, state, n); nmod_poly_randtest_irreducible(g, state, n); nmod_poly_mul(f, f, g); t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_cantor_zassenhaus(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_berlekamp(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_kaltofen_shoup(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; nmod_poly_clear(f); nmod_poly_clear(g); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } } flint_printf("Product of 8 small irreducible polynomials\n"); for (i = 0; i < NP; i++) { modulus = n_randtest_prime(state, 0); flint_printf("========== p: %wu\n", modulus); fflush(stdout); for (j = 1; j < ND; j++) { n = (degs[j] >> 3); flint_printf(">>>>>n: %d\n", n); fflush(stdout); T1 = 0; T2 = 0; T3 = 0; for (k = 0; k < iter_count[j]; k++) { nmod_poly_init(f, modulus); nmod_poly_init(g, modulus); nmod_poly_randtest_irreducible(f, state, n); for (num = 1; num < 8; num++) { nmod_poly_randtest_irreducible(g, state, n); nmod_poly_mul(f, f, g); } t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_cantor_zassenhaus(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T1 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_with_berlekamp(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T2 += t; t = clock(); nmod_poly_factor_init(res); nmod_poly_factor_kaltofen_shoup(res, f); nmod_poly_factor_clear(res); t = (clock() - t) / CLOCKS_PER_SEC; T3 += t; nmod_poly_clear(f); nmod_poly_clear(g); } flint_printf("CZ: %.2lf B: %.2lf KS: %.2lf\n", T1, T2, T3); fflush(stdout); if (T1 > T3 + 1) break; } } flint_randclear(state); return 0; } flint-3.1.3/src/nmod_poly_factor/profile/p-factorbench.c000066400000000000000000000030331461254215100232760ustar00rootroot00000000000000/* Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" int main (void) { double t; nmod_poly_t f, g, h; int i; for (i= 15001;i < 16000; i++) { nmod_poly_init2 (f, 17, i/2+1); nmod_poly_init2 (g, 17, i+1); nmod_poly_set_coeff_ui (f, i/2, 1); nmod_poly_set_coeff_ui (f, 1, 1); nmod_poly_set_coeff_ui (f, 0, ((i%17)*(i%17)+3) % 17); nmod_poly_set_coeff_ui (g, i, 1); nmod_poly_set_coeff_ui (g, i/2+1, 1); nmod_poly_set_coeff_ui (g, 1, ((i % 17)+1)%17); nmod_poly_set_coeff_ui (g, 0, 15); nmod_poly_init (h, 17); nmod_poly_gcd (h, f, g); if (!nmod_poly_is_one (h)) { nmod_poly_factor_t factors; flint_printf ("i= %d\n", i); nmod_poly_factor_init (factors); t= clock(); nmod_poly_factor (factors, h); t = (clock() - t) / CLOCKS_PER_SEC; flint_printf("factorization %.2lf\n", t); nmod_poly_factor_clear (factors); } nmod_poly_clear (f); nmod_poly_clear (g); nmod_poly_clear (h); } return 0; } flint-3.1.3/src/nmod_poly_factor/profile/p-roots.c000066400000000000000000000033671461254215100222000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "profiler.h" int main(int argc, char *argv[]) { slong i; { nmod_poly_t f, g; nmod_poly_factor_t r; flint_rand_t state; timeit_t timer; ulong p = n_nextprime(UWORD(1) << (SMALL_FMPZ_BITCOUNT_MAX), 1); flint_randinit(state); nmod_poly_init(f, p); nmod_poly_init(g, p); nmod_poly_factor_init(r); nmod_poly_one(f); for (i = 1; i <= 200; i++) { nmod_poly_fit_length(g, 2); g->coeffs[0] = n_randint(state, p); g->coeffs[1] = n_randint(state, p); g->coeffs[1] = FLINT_MAX(g->coeffs[1], UWORD(1)); g->length = 2; nmod_poly_mul(f, f, g); timeit_start(timer); nmod_poly_roots(r, f, 0); timeit_stop(timer); flint_printf("degree %wd time: %wd %wd", i, timer->wall, timer->wall/i); timeit_start(timer); nmod_poly_factor(r, f); timeit_stop(timer); flint_printf(" factor time: %wd %wd", timer->wall, timer->wall/i); printf("\n"); } nmod_poly_factor_clear(r); nmod_poly_clear(g); nmod_poly_clear(f); flint_randclear(state); } flint_cleanup_master(); return 0; } flint-3.1.3/src/nmod_poly_factor/realloc.c000066400000000000000000000035261461254215100205530ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_realloc(nmod_poly_factor_t fac, slong alloc) { if (alloc == 0) /* Clear up, reinitialise */ { nmod_poly_factor_clear(fac); nmod_poly_factor_init(fac); } else if (fac->alloc) /* Realloc */ { if (fac->alloc > alloc) { slong i; for (i = alloc; i < fac->num; i++) nmod_poly_clear(fac->p + i); fac->p = flint_realloc(fac->p, alloc * sizeof(nmod_poly_struct)); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); fac->alloc = alloc; } else if (fac->alloc < alloc) { slong i; fac->p = flint_realloc(fac->p, alloc * sizeof(nmod_poly_struct)); fac->exp = flint_realloc(fac->exp, alloc * sizeof(slong)); for (i = fac->alloc; i < alloc; i++) { nmod_poly_init_preinv(fac->p + i, 1, 0); fac->exp[i] = WORD(0); } fac->alloc = alloc; } } else /* Nothing allocated already so do it now */ { slong i; fac->p = flint_malloc(alloc * sizeof(nmod_poly_struct)); fac->exp = flint_calloc(alloc, sizeof(slong)); for (i = 0; i < alloc; i++) nmod_poly_init_preinv(fac->p + i, 1, 0); fac->num = 0; fac->alloc = alloc; } } flint-3.1.3/src/nmod_poly_factor/roots.c000066400000000000000000000140101461254215100202660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" /* Helper function for finding roots. The roots of a monic f are written with exponent given in mult to r. Uses Rabin's Las Vegas algorithm via gcd computations with (x + delta)^((p-1)/2) - 1. */ static void _nmod_poly_push_roots( nmod_poly_factor_t r, nmod_poly_t f, /* clobbered */ slong mult, /* expoenent to write on the roots */ nmod_poly_t t, /* temp */ nmod_poly_t t2, /* more temp */ nmod_poly_struct * stack, /* temp of size FLINT_BITS */ flint_rand_t randstate) { slong i, sp; nmod_poly_struct * a, * b; FLINT_ASSERT(nmod_poly_degree(f) >= 1); FLINT_ASSERT(f->coeffs[nmod_poly_degree(f)] == 1); FLINT_ASSERT(n_is_probabprime(f->mod.n)); /* handle at least p = 2 */ if (f->mod.n < 10) { ulong x; for (x = 0; x < f->mod.n; x++) { if (0 != nmod_poly_evaluate_nmod(f, x)) continue; nmod_poly_factor_fit_length(r, r->num + 1); nmod_poly_fit_length(r->p + r->num, 2); r->p[r->num].mod = f->mod; /* bummer */ r->p[r->num].coeffs[0] = nmod_neg(x, f->mod); r->p[r->num].coeffs[1] = 1; r->p[r->num].length = 2; r->exp[r->num] = mult; r->num++; } return; } /* handle zero roots */ if (f->coeffs[0] == 0) { nmod_poly_factor_fit_length(r, r->num + 1); nmod_poly_fit_length(r->p + r->num, 2); r->p[r->num].mod = f->mod; /* bummer */ r->p[r->num].coeffs[0] = 0; r->p[r->num].coeffs[1] = 1; r->p[r->num].length = 2; r->exp[r->num] = mult; r->num++; i = 1; while (i < f->length && f->coeffs[i] == 0) i++; nmod_poly_shift_right(f, f, i); } if (nmod_poly_degree(f) <= 1) { if (nmod_poly_degree(f) == 1) { nmod_poly_factor_fit_length(r, r->num + 1); r->p[r->num].mod = f->mod; /* bummer */ nmod_poly_swap(r->p + r->num, f); r->exp[r->num] = mult; r->num++; } return; } FLINT_ASSERT(f->coeffs[0] != 0); nmod_poly_reverse(t, f, f->length); nmod_poly_inv_series_newton(t2, t, t->length); a = stack + 0; b = stack + 1; nmod_poly_zero(a); nmod_poly_set_coeff_ui(a, 1, 1); nmod_poly_powmod_ui_binexp_preinv(t, a, (f->mod.n - 1)/2, f, t2); nmod_poly_sub_ui(t, t, 1); nmod_poly_gcd(a, t, f); nmod_poly_add_ui(t, t, 2); nmod_poly_gcd(b, t, f); /* ensure deg a >= deg b */ if (nmod_poly_degree(a) < nmod_poly_degree(b)) nmod_poly_swap(a, b); nmod_poly_factor_fit_length(r, r->num + nmod_poly_degree(a) + nmod_poly_degree(b)); /* initial split failed if b = 1 */ sp = (nmod_poly_degree(b) > 0) ? 2 : 1; while (sp > 0) { sp--; FLINT_ASSERT(sp < FLINT_BITS); nmod_poly_swap(f, stack + sp); FLINT_ASSERT(nmod_poly_degree(f) >= 0); FLINT_ASSERT(FLINT_BIT_COUNT(nmod_poly_degree(f)) <= FLINT_BITS - sp); if (nmod_poly_degree(f) <= 1) { if (nmod_poly_degree(f) == 1) { FLINT_ASSERT(r->num < r->alloc); r->p[r->num].mod = f->mod; /* bummer */ nmod_poly_set(r->p + r->num, f); r->exp[r->num] = mult; r->num++; } } else { FLINT_ASSERT(sp + 1 < FLINT_BITS); _nmod_poly_split_rabin(stack + sp + 0, stack + sp + 1, f, t, t2, randstate); FLINT_ASSERT(FLINT_BIT_COUNT(nmod_poly_degree(stack + sp + 1)) <= FLINT_BITS - (sp + 1)); FLINT_ASSERT(FLINT_BIT_COUNT(nmod_poly_degree(stack + sp + 0)) <= FLINT_BITS - (sp + 0)); sp += 2; } } } void nmod_poly_roots(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity) { slong i; flint_rand_t randstate; nmod_poly_struct t[FLINT_BITS + 3]; FLINT_ASSERT(n_is_probabprime(f->mod.n)); r->num = 0; if (nmod_poly_degree(f) < 2) { if (nmod_poly_degree(f) == 1) { nmod_poly_factor_fit_length(r, 1); r->p[0].mod = f->mod; /* bummer */ nmod_poly_make_monic(r->p + 0, f); r->exp[0] = 1; r->num = 1; } else if (nmod_poly_degree(f) < 0) { flint_throw(FLINT_ERROR, "Exception in nmod_poly_roots: " "input polynomial is zero."); } return; } flint_randinit(randstate); for (i = 0; i < FLINT_BITS + 3; i++) nmod_poly_init_mod(t + i, f->mod); if (with_multiplicity) { nmod_poly_factor_t sqf; nmod_poly_factor_init(sqf); nmod_poly_factor_squarefree(sqf, f); for (i = 0; i < sqf->num; i++) { _nmod_poly_push_roots(r, sqf->p + i, sqf->exp[i], t + 1, t + 2, t + 3, randstate); } nmod_poly_factor_clear(sqf); } else { nmod_poly_make_monic(t + 0, f); _nmod_poly_push_roots(r, t + 0, 1, t + 1, t + 2, t + 3, randstate); } flint_randclear(randstate); for (i = 0; i < FLINT_BITS + 3; i++) nmod_poly_clear(t + i); } flint-3.1.3/src/nmod_poly_factor/roots_factored.c000066400000000000000000000207551461254215100221520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "nmod.h" #include "fmpz.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" typedef nmod_poly_t n_list_t; /* lets not generate solutions lists with length longer than LENGTH_LIMIT */ #if FLINT64 #define LENGTH_LIMIT (WORD(1) << 32) #else #define LENGTH_LIMIT (WORD(1) << 25) #endif /* The modulus of b is divisible by the modulus of a. Map b via the projection. */ static void map_down(nmod_poly_t a, const nmod_poly_t b) { slong i; FLINT_ASSERT((b->mod.n % a->mod.n) == 0); nmod_poly_fit_length(a, b->length); for (i = 0; i < b->length; i++) a->coeffs[i] = b->coeffs[i] % a->mod.n; a->length = b->length; _nmod_poly_normalise(a); } /* Every lifter needs a Diophantine equation solver: Given a, b, c with a >= 0, b > 0, try to push all solutions for x to a*x + b*y = c with 0 <= x < b. */ static int dio_solve(n_list_t v, ulong A, ulong B, ulong C) { int success = 1; slong k; ulong t, d; fmpz_t xstart, xstride, xlength; fmpz_t a, b, c; fmpz_init(xstart); fmpz_init(xstride); fmpz_init(xlength); fmpz_init_set_ui(a, A); fmpz_init_set_ui(b, B); fmpz_init_set_ui(c, C); fmpz_divides_mod_list(xstart, xstride, xlength, c, a, b); k = *xlength; if ((!COEFF_IS_MPZ(k)) && (k + v->length < LENGTH_LIMIT)) { nmod_poly_fit_length(v, k + v->length); t = fmpz_get_ui(xstart); d = fmpz_get_ui(xstride); for (; k > 0; k--) { v->coeffs[v->length] = t; v->length++; t += d; } } else { /* too many solutions */ success = 0; } fmpz_clear(xstart); fmpz_clear(xstride); fmpz_clear(xlength); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); return success; } /* Fill x with the roots of fpk, where f->mod.n is p^k */ static int roots_mod_prime_power(nmod_poly_factor_t x, nmod_poly_t fpk, ulong p, slong k, int with_multiplicity) { int success = 1; slong e1, e2; slong i, j, old_length; n_list_t x1, x2; nmod_poly_t f, dfpk, tf, tr, tq; ulong pe1, pe2e1, fprime, mfpe1; FLINT_ASSERT(k >= 1); FLINT_ASSERT(n_is_probabprime(p)); nmod_poly_init_mod(tf, fpk->mod); nmod_poly_init_mod(tr, fpk->mod); nmod_poly_init_mod(tq, fpk->mod); nmod_poly_init_mod(dfpk, fpk->mod); nmod_poly_derivative(dfpk, fpk); nmod_poly_init_mod(x1, fpk->mod); nmod_poly_init_mod(x2, fpk->mod); nmod_poly_init(f, p); map_down(f, fpk); /* try to fill x1 with solutions mod p */ x1->length = 0; if (f->length > 0) { nmod_poly_factor_t r; nmod_poly_factor_init(r); nmod_poly_roots(r, f, 0); nmod_poly_fit_length(x1, r->num); for (i = 0; i < r->num; i++) x1->coeffs[i] = nmod_neg(r->p[i].coeffs[0], f->mod); x1->length = r->num; nmod_poly_factor_clear(r); } else { if (p >= LENGTH_LIMIT) { /* too many solutions mod p */ success = 0; goto cleanup; } nmod_poly_fit_length(x1, p); for (i = 0; i < p; i++) x1->coeffs[i] = i; x1->length = p; } /* lift roots mod p^e1 to roots mod p^e2 */ for (e1 = 1; e1 < k; e1 = e2) { e2 = FLINT_MIN(k, 2*e1); pe1 = n_pow(p, e1); pe2e1 = n_pow(p, e2 - e1); x2->length = 0; for (i = 0; i < x1->length; i++) { mfpe1 = nmod_poly_evaluate_nmod(fpk, x1->coeffs[i]); mfpe1 = nmod_neg(mfpe1, fpk->mod); FLINT_ASSERT((mfpe1 % pe1) == 0); mfpe1 = mfpe1/pe1; fprime = nmod_poly_evaluate_nmod(dfpk, x1->coeffs[i]); fprime = fprime % pe2e1; old_length = x2->length; if (!dio_solve(x2, fprime, pe2e1, mfpe1)) { success = 0; goto cleanup; } for (j = old_length; j < x2->length; j++) { x2->coeffs[j] = x1->coeffs[i] + x2->coeffs[j] * pe1; } } nmod_poly_swap(x1, x2); } /* fill in roots and multiplicies if wanted */ nmod_poly_factor_fit_length(x, x1->length); for (i = 0; i < x1->length; i++) { nmod_poly_fit_length(x->p + i, 2); x->p[i].mod = fpk->mod; /* bummer */ x->p[i].coeffs[1] = 1; FLINT_ASSERT(x1->coeffs[i] < fpk->mod.n); x->p[i].coeffs[0] = nmod_neg(x1->coeffs[i], fpk->mod); x->p[i].length = 2; x->exp[i] = 1; if (with_multiplicity) { if (fpk->length > 0) { nmod_poly_divrem(tf, tr, fpk, x->p + i); FLINT_ASSERT(nmod_poly_is_zero(tr)); while (nmod_poly_divrem(tq, tr, tf, x->p + i), nmod_poly_is_zero(tr)) { FLINT_ASSERT(tf->length >= (x->p + i)->length); x->exp[i]++; nmod_poly_swap(tq, tf); } } else { x->exp[i] = WORD_MAX; } } } x->num = x1->length; cleanup: nmod_poly_clear(tf); nmod_poly_clear(tr); nmod_poly_clear(tq); nmod_poly_clear(x1); nmod_poly_clear(x2); nmod_poly_clear(f); nmod_poly_clear(dfpk); return success; } int nmod_poly_roots_factored(nmod_poly_factor_t x0, const nmod_poly_t f, int with_multiplicity, const n_factor_t * fac) { int success = 1; slong i, j, k, new_length; ulong m; nmod_poly_factor_t x1, x2; nmod_poly_t fpe; if (f->length <= 0) { flint_throw(FLINT_ERROR, "Exception in nmod_poly_roots_factored: " "input polynomial is zero."); return 0; } nmod_poly_init(fpe, fac->p[0]); m = 1; nmod_poly_factor_init(x1); nmod_poly_factor_init(x2); i = 0; nmod_poly_init(fpe, n_pow(fac->p[i], fac->exp[i])); map_down(fpe, f); if (!roots_mod_prime_power(x0, fpe, fac->p[i], fac->exp[i], with_multiplicity)) { goto almost_failed; } for (i = 1; x0->num > 0 && i < fac->num; i++) { m *= fpe->mod.n; nmod_init(&fpe->mod, n_pow(fac->p[i], fac->exp[i])); map_down(fpe, f); if (!roots_mod_prime_power(x1, fpe, fac->p[i], fac->exp[i], with_multiplicity)) { goto almost_failed; } if (z_mul_checked(&new_length, x0->num, x1->num) || new_length >= LENGTH_LIMIT) { goto almost_failed; } /* combine roots with CRT, multiplicities with FLINT_MIN */ x2->num = 0; nmod_poly_factor_fit_length(x2, new_length); for (j = 0; j < x0->num; j++) for (k = 0; k < x1->num; k++) { nmod_poly_struct * r = x2->p + x2->num; nmod_poly_fit_length(r, 2); r->mod = f->mod; /* bummer */ r->coeffs[1] = 1; FLINT_ASSERT(x1->p[k].length == 2); FLINT_ASSERT(x0->p[j].length == 2); r->coeffs[0] = n_CRT(x1->p[k].coeffs[0], fpe->mod.n, x0->p[j].coeffs[0], m); r->length = 2; FLINT_ASSERT(x0->exp[j] >= 1); FLINT_ASSERT(x1->exp[k] >= 1); x2->exp[x2->num] = FLINT_MIN(x0->exp[j], x1->exp[k]); x2->num++; } nmod_poly_factor_swap(x0, x2); } cleanup: nmod_poly_factor_clear(x1); nmod_poly_factor_clear(x2); nmod_poly_clear(fpe); return success; almost_failed: /* if any prime power is lacking roots, we can still succeed */ x0->num = 0; for (i++; i < fac->num; i++) { nmod_init(&fpe->mod, n_pow(fac->p[i], fac->exp[i])); map_down(fpe, f); if (roots_mod_prime_power(x1, fpe, fac->p[i], fac->exp[i], 0) && x1->num == 0) { goto cleanup; } } success = 0; goto cleanup; } flint-3.1.3/src/nmod_poly_factor/set.c000066400000000000000000000022521461254215100177200ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" void nmod_poly_factor_set(nmod_poly_factor_t res, const nmod_poly_factor_t fac) { if (res != fac) { if (fac->num == 0) { nmod_poly_factor_clear(res); nmod_poly_factor_init(res); } else { slong i; nmod_poly_factor_fit_length(res, fac->num); for (i = 0; i < fac->num; i++) { nmod_poly_set(res->p + i, fac->p + i); (res->p + i)->mod = (fac->p + i)->mod; res->exp[i] = fac->exp[i]; } for ( ; i < res->num; i++) { nmod_poly_zero(res->p + i); res->exp[i] = 0; } res->num = fac->num; } } } flint-3.1.3/src/nmod_poly_factor/test/000077500000000000000000000000001461254215100177375ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly_factor/test/main.c000066400000000000000000000035301461254215100210300ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor_berlekamp.c" #include "t-factor.c" #include "t-factor_cantor_zassenhaus.c" #include "t-factor_distinct_deg.c" #include "t-factor_distinct_deg_threaded.c" #include "t-factor_kaltofen_shoup.c" #include "t-factor_squarefree.c" #include "t-interval_threaded.c" #include "t-is_irreducible.c" #include "t-is_irreducible_ddf.c" #include "t-is_irreducible_rabin.c" #include "t-is_squarefree.c" #include "t-roots.c" #include "t-roots_factored.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_poly_factor_berlekamp), TEST_FUNCTION(nmod_poly_factor), TEST_FUNCTION(nmod_poly_factor_cantor_zassenhaus), TEST_FUNCTION(nmod_poly_factor_distinct_deg), TEST_FUNCTION(nmod_poly_factor_distinct_deg_threaded), TEST_FUNCTION(nmod_poly_factor_kaltofen_shoup), TEST_FUNCTION(nmod_poly_factor_squarefree), TEST_FUNCTION(nmod_poly_factor_interval_threaded), TEST_FUNCTION(nmod_poly_factor_is_irreducible), TEST_FUNCTION(nmod_poly_factor_is_irreducible_ddf), TEST_FUNCTION(nmod_poly_factor_is_irreducible_rabin), TEST_FUNCTION(nmod_poly_factor_is_squarefree), TEST_FUNCTION(nmod_poly_factor_roots), TEST_FUNCTION(nmod_poly_factor_roots_factored) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod_poly_factor/test/t-factor.c000066400000000000000000000162311461254215100216250ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor, state) { int iter; /* Default algorithm */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { int result = 1; nmod_poly_t pol1, poly, quot, rem, product; nmod_poly_factor_t res; mp_limb_t modulus, lead = 1; slong length, num, i, j; ulong exp[5]; modulus = n_randtest_prime(state, 0); nmod_poly_init(pol1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(quot, modulus); nmod_poly_init(rem, modulus); nmod_poly_zero(pol1); nmod_poly_set_coeff_ui(pol1, 0, 1); length = n_randint(state, 7) + 2; do { nmod_poly_randtest(poly, state, length); if (poly->length) nmod_poly_make_monic(poly, poly); } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2)); exp[0] = n_randint(state, 30) + 1; for (i = 0; i < exp[0]; i++) nmod_poly_mul(pol1, pol1, poly); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; nmod_poly_randtest(poly, state, length); if (poly->length) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(quot, rem, pol1, poly); } } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2) || (rem->length == 0)); exp[i] = n_randint(state, 30) + 1; for (j = 0; j < exp[i]; j++) nmod_poly_mul(pol1, pol1, poly); } nmod_poly_factor_init(res); switch (n_randint(state, 3)) { case 0: lead = nmod_poly_factor(res, pol1); break; case 1: lead = nmod_poly_factor_with_berlekamp(res, pol1); break; case 2: if (modulus == 2) lead = nmod_poly_factor(res, pol1); else lead = nmod_poly_factor_with_cantor_zassenhaus(res, pol1); break; } result &= (res->num == num); if (!result) { flint_printf("Error: number of factors incorrect, %wd, %wd\n", res->num, num); fflush(stdout); flint_abort(); } nmod_poly_init(product, pol1->mod.n); nmod_poly_set_coeff_ui(product, 0, 1); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) nmod_poly_mul(product, product, res->p + i); nmod_poly_scalar_mul_nmod(product, product, lead); result &= nmod_poly_equal(pol1, product); if (!result) { flint_printf("Error: product of factors does not equal original polynomial\n"); nmod_poly_print(pol1); flint_printf("\n"); nmod_poly_print(product); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(product); nmod_poly_clear(quot); nmod_poly_clear(rem); nmod_poly_clear(pol1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } /* Test deflation trick */ for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { nmod_poly_t pol1, poly, quot, rem; nmod_poly_factor_t res, res2; mp_limb_t modulus; slong length, num, i, j; slong exp[5]; ulong inflation; int found; do { modulus = n_randtest_prime(state, 0); } while (modulus == 2); /* To compare with CZ */ nmod_poly_init(pol1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(quot, modulus); nmod_poly_init(rem, modulus); nmod_poly_zero(pol1); nmod_poly_set_coeff_ui(pol1, 0, 1); inflation = n_randint(state, 7) + 1; length = n_randint(state, 7) + 2; do { nmod_poly_randtest(poly, state, length); if (poly->length) nmod_poly_make_monic(poly, poly); } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2)); nmod_poly_inflate(poly, poly, inflation); exp[0] = n_randint(state, 6) + 1; for (i = 0; i < exp[0]; i++) nmod_poly_mul(pol1, pol1, poly); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 6) + 2; nmod_poly_randtest(poly, state, length); if (poly->length) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(quot, rem, pol1, poly); } } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2) || (rem->length == 0)); exp[i] = n_randint(state, 6) + 1; nmod_poly_inflate(poly, poly, inflation); for (j = 0; j < exp[i]; j++) nmod_poly_mul(pol1, pol1, poly); } nmod_poly_factor_init(res); nmod_poly_factor_init(res2); switch (n_randint(state, 3)) { case 0: nmod_poly_factor(res, pol1); break; case 1: nmod_poly_factor_with_berlekamp(res, pol1); break; case 2: nmod_poly_factor_with_cantor_zassenhaus(res, pol1); break; } nmod_poly_factor_cantor_zassenhaus(res2, pol1); if (res->num != res2->num) { flint_printf("FAIL: different number of factors found\n"); fflush(stdout); flint_abort(); } for (i = 0; i < res->num; i++) { found = 0; for (j = 0; j < res2->num; j++) { if (nmod_poly_equal(res->p + i, res2->p + j) && res->exp[i] == res2->exp[j]) { found = 1; break; } } if (!found) { flint_printf("FAIL: factor not found\n"); fflush(stdout); flint_abort(); } } nmod_poly_clear(quot); nmod_poly_clear(rem); nmod_poly_clear(pol1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); nmod_poly_factor_clear(res2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000046661461254215100236600ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_berlekamp, state) { int iter; for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { int result = 1; nmod_poly_t pol1, poly, quot, rem; nmod_poly_factor_t res; mp_limb_t modulus; slong i, length, num; modulus = n_randtest_prime(state, 0); nmod_poly_init(pol1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(quot, modulus); nmod_poly_init(rem, modulus); length = n_randint(state, 10) + 2; do { nmod_poly_randtest(pol1, state, length); if (pol1->length) nmod_poly_make_monic(pol1, pol1); } while ((!nmod_poly_is_irreducible(pol1)) || (pol1->length < 2)); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 10) + 2; nmod_poly_randtest(poly, state, length); if (poly->length) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(quot, rem, pol1, poly); } } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2) || (rem->length == 0)); nmod_poly_mul(pol1, pol1, poly); } nmod_poly_factor_init(res); nmod_poly_factor_berlekamp(res, pol1); result = (res->num == num); if (!result) { flint_printf("FAIL: %wu, %wd, %wd\n", modulus, num, res->num); fflush(stdout); flint_abort(); } nmod_poly_clear(quot); nmod_poly_clear(rem); nmod_poly_clear(pol1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000070051461254215100254360ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_cantor_zassenhaus, state) { int iter; for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { int result = 1; nmod_poly_t pol1, poly, quot, rem; nmod_poly_t product; nmod_poly_factor_t res; mp_limb_t modulus, lead; slong i, j, length, num; slong exp[5]; modulus = n_randtest_prime(state, 0); nmod_poly_init(pol1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(quot, modulus); nmod_poly_init(rem, modulus); nmod_poly_zero(pol1); nmod_poly_set_coeff_ui(pol1, 0, 1); length = n_randint(state, 7) + 2; do { nmod_poly_randtest(poly, state, length); if(!nmod_poly_is_zero(poly)) nmod_poly_make_monic(poly, poly); } while ((poly->length < 2) || (!nmod_poly_is_irreducible(poly))); exp[0] = n_randint(state, 30) + 1; for (i = 0; i < exp[0]; i++) nmod_poly_mul(pol1, pol1, poly); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; nmod_poly_randtest(poly, state, length); if(!nmod_poly_is_zero(poly)) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(quot, rem, pol1, poly); } } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2) || (rem->length == 0)); exp[i] = n_randint(state, 30) + 1; for (j = 0; j < exp[i]; j++) nmod_poly_mul(pol1, pol1, poly); } nmod_poly_factor_init(res); nmod_poly_factor_cantor_zassenhaus(res, pol1); result &= (res->num == num); if (!result) { flint_printf("Error: number of factors incorrect, %wd, %wd\n", res->num, num); } nmod_poly_init(product, pol1->mod.n); nmod_poly_set_coeff_ui(product, 0, 1); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) nmod_poly_mul(product, product, res->p + i); lead = pol1->coeffs[pol1->length - 1]; nmod_poly_scalar_mul_nmod(product, product, lead); result &= nmod_poly_equal(pol1, product); if (!result) { flint_printf("Error: product of factors does not equal original polynomial\n"); nmod_poly_print(pol1); flint_printf("\n"); nmod_poly_print(product); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(product); nmod_poly_clear(quot); nmod_poly_clear(rem); nmod_poly_clear(pol1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000077361461254215100243570ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #define MAX_DEG 7 TEST_FUNCTION_START(nmod_poly_factor_distinct_deg, state) { int iter; for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { nmod_poly_t poly1, poly, q, r, product; nmod_poly_factor_t res; mp_limb_t modulus, lead; slong i, length, num; slong *degs; slong num_of_deg[MAX_DEG + 1]; for (i = 0; i < MAX_DEG + 1; i++) num_of_deg[i] = 0; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(q, modulus); nmod_poly_init(r, modulus); nmod_poly_zero(poly1); nmod_poly_set_coeff_ui(poly1, 0, 1); length = n_randint(state, MAX_DEG) + 2; do { nmod_poly_randtest(poly, state, length); if (poly->length) nmod_poly_make_monic(poly, poly); } while ((poly->length < 2) || (!nmod_poly_is_irreducible(poly))); nmod_poly_mul(poly1, poly1, poly); num_of_deg[nmod_poly_degree(poly)]++; num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, MAX_DEG) + 2; nmod_poly_randtest(poly, state, length); if (poly->length) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(q, r, poly1, poly); } } while ((poly->length < 2) || (!nmod_poly_is_irreducible(poly)) || (r->length == 0)); nmod_poly_mul(poly1, poly1, poly); num_of_deg[nmod_poly_degree(poly)]++; } if (!(degs = flint_malloc((poly1->length - 1) * sizeof(slong)))) { flint_printf("Fatal error: not enough memory."); fflush(stdout); flint_abort(); } nmod_poly_factor_init(res); nmod_poly_factor_distinct_deg(res, poly1, °s); nmod_poly_init_preinv(product, poly1->mod.n, poly1->mod.ninv); nmod_poly_set_coeff_ui(product, 0, 1); for (i = 0; i < res->num; i++) { nmod_poly_mul(product, product, res->p + i); if (nmod_poly_degree(res->p + i) != degs[i]*num_of_deg[degs[i]]) { flint_printf("Error: product of factors of degree %w incorrect\n", degs[i]); flint_printf("Degree %w != %w * %w\n", nmod_poly_degree(res->p + i), degs[i], num_of_deg[degs[i]]); fflush(stdout); flint_abort(); } } lead = poly1->coeffs[poly1->length - 1]; nmod_poly_scalar_mul_nmod(product, product, lead); if (!nmod_poly_equal(poly1, product)) { flint_printf("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); nmod_poly_print(poly1); flint_printf("\n"); flint_printf("product:\n"); nmod_poly_print(product); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(degs); nmod_poly_clear(product); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(poly1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-factor_distinct_deg_threaded.c000066400000000000000000000100441461254215100262010ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010, 2020 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova Copyright (C) 2014 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #define MAX_DEG 7 TEST_FUNCTION_START(nmod_poly_factor_distinct_deg_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int iter; for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { nmod_poly_t poly1, poly, q, r, product; nmod_poly_factor_t res; mp_limb_t modulus, lead; slong i, length, num; slong *degs; slong num_of_deg[MAX_DEG + 1]; for (i = 0; i < MAX_DEG + 1; i++) num_of_deg[i] = 0; modulus = n_randtest_prime(state, 0); flint_set_num_threads(1 + n_randint(state, 3)); nmod_poly_init(poly1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(q, modulus); nmod_poly_init(r, modulus); nmod_poly_zero(poly1); nmod_poly_set_coeff_ui(poly1, 0, 1); length = n_randint(state, MAX_DEG) + 2; do { nmod_poly_randtest(poly, state, length); if (poly->length) nmod_poly_make_monic(poly, poly); } while ((poly->length < 2) || (!nmod_poly_is_irreducible(poly))); nmod_poly_mul(poly1, poly1, poly); num_of_deg[nmod_poly_degree(poly)]++; num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, MAX_DEG) + 2; nmod_poly_randtest(poly, state, length); if (poly->length) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(q, r, poly1, poly); } } while ((poly->length < 2) || (!nmod_poly_is_irreducible(poly)) || (r->length == 0)); nmod_poly_mul(poly1, poly1, poly); num_of_deg[nmod_poly_degree(poly)]++; } degs = (slong *) flint_malloc((poly1->length - 1) * sizeof(slong)); nmod_poly_factor_init(res); nmod_poly_factor_distinct_deg_threaded(res, poly1, °s); nmod_poly_init_preinv(product, poly1->mod.n, poly1->mod.ninv); nmod_poly_set_coeff_ui(product, 0, 1); for (i = 0; i < res->num; i++) { nmod_poly_mul(product, product, res->p + i); if (nmod_poly_degree(res->p + i) != degs[i]*num_of_deg[degs[i]]) { flint_printf("Error: product of factors of degree %w incorrect\n", degs[i]); flint_printf("Degree %w != %w * %w\n", nmod_poly_degree(res->p + i), degs[i], num_of_deg[degs[i]]); fflush(stdout); flint_abort(); } } lead = poly1->coeffs[poly1->length - 1]; nmod_poly_scalar_mul_nmod(product, product, lead); if (!nmod_poly_equal(poly1, product)) { flint_printf("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); nmod_poly_print(poly1); flint_printf("\n"); flint_printf("product:\n"); nmod_poly_print(product); flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(degs); nmod_poly_clear(product); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(poly1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/nmod_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000070071461254215100247270ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson Copyright (C) 2012 Lina Kulakova This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_kaltofen_shoup, state) { int iter; for (iter = 0; iter < 20 * flint_test_multiplier(); iter++) { nmod_poly_t poly1, poly, q, r, product; nmod_poly_factor_t res; mp_limb_t modulus, lead; slong i, j, length, num; slong exp[5]; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(q, modulus); nmod_poly_init(r, modulus); nmod_poly_zero(poly1); nmod_poly_set_coeff_ui(poly1, 0, 1); length = n_randint(state, 7) + 2; do { nmod_poly_randtest(poly, state, length); if (poly->length) nmod_poly_make_monic(poly, poly); } while ((poly->length < 2) || (!nmod_poly_is_irreducible(poly))); exp[0] = n_randint(state, 30) + 1; for (i = 0; i < exp[0]; i++) nmod_poly_mul(poly1, poly1, poly); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; nmod_poly_randtest(poly, state, length); if (poly->length) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(q, r, poly1, poly); } } while ((poly->length < 2) || (!nmod_poly_is_irreducible(poly)) || (r->length == 0)); exp[i] = n_randint(state, 30) + 1; for (j = 0; j < exp[i]; j++) nmod_poly_mul(poly1, poly1, poly); } nmod_poly_factor_init(res); nmod_poly_factor_kaltofen_shoup(res, poly1); if (res->num != num) { flint_printf("Error: number of factors incorrect: %wd != %wd\n", res->num, num); fflush(stdout); flint_abort(); } nmod_poly_init_preinv(product, poly1->mod.n, poly1->mod.ninv); nmod_poly_set_coeff_ui(product, 0, 1); for (i = 0; i < res->num; i++) for (j = 0; j < res->exp[i]; j++) nmod_poly_mul(product, product, res->p + i); lead = poly1->coeffs[poly1->length - 1]; nmod_poly_scalar_mul_nmod(product, product, lead); if (!nmod_poly_equal(poly1, product)) { flint_printf("Error: product of factors does not equal to the original polynomial\n"); flint_printf("poly:\n"); nmod_poly_print(poly1); flint_printf("\n"); flint_printf("product:\n"); nmod_poly_print(product); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(product); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(poly1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-factor_squarefree.c000066400000000000000000000064001461254215100240440ustar00rootroot00000000000000/* Copyright (C) 2007 David Howden Copyright (C) 2007, 2008, 2009, 2010 William Hart Copyright (C) 2008 Richard Howell-Peak Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_squarefree, state) { int iter; for (iter = 0; iter < 30 * flint_test_multiplier(); iter++) { int result = 1; nmod_poly_t pol1, poly, quot, rem; nmod_poly_factor_t res; mp_limb_t modulus; slong exp[5], prod1; slong length, i, j, num; modulus = n_randtest_prime(state, 0); nmod_poly_init(pol1, modulus); nmod_poly_init(poly, modulus); nmod_poly_init(quot, modulus); nmod_poly_init(rem, modulus); nmod_poly_zero(pol1); nmod_poly_set_coeff_ui(pol1, 0, 1); length = n_randint(state, 7) + 2; do { nmod_poly_randtest(poly, state, length); if(!nmod_poly_is_zero(poly)) nmod_poly_make_monic(poly, poly); } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2)); exp[0] = n_randprime(state, 5, 0); prod1 = exp[0]; for (i = 0; i < exp[0]; i++) nmod_poly_mul(pol1, pol1, poly); num = n_randint(state, 5) + 1; for (i = 1; i < num; i++) { do { length = n_randint(state, 7) + 2; nmod_poly_randtest(poly, state, length); if (poly->length) { nmod_poly_make_monic(poly, poly); nmod_poly_divrem(quot, rem, pol1, poly); } } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2) || (rem->length == 0)); do exp[i] = n_randprime(state, 5, 0); while (prod1 % exp[i] == 0); prod1 *= exp[i]; for (j = 0; j < exp[i]; j++) nmod_poly_mul(pol1, pol1, poly); } nmod_poly_factor_init(res); nmod_poly_factor_squarefree(res, pol1); result &= (res->num == num); if (result) { ulong prod2 = 1; for (i = 0; i < num; i++) prod2 *= res->exp[i]; result &= (prod1 == prod2); } if (!result) { flint_printf("Error: exp don't match. Modulus = %wu\n", modulus); for (i = 0; i < res->num; i++) flint_printf("%wd ", res->exp[i]); flint_printf("\n"); for (i = 0; i < num; i++) flint_printf("%wd ", exp[i]); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(quot); nmod_poly_clear(rem); nmod_poly_clear(pol1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-interval_threaded.c000066400000000000000000000107261461254215100240360ustar00rootroot00000000000000/* Copyright (C) 2014 Martin Lee Copyright (C) 2020 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_pool.h" #include "thread_support.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_interval_threaded, state) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int iter; for (iter = 0; iter < 20*flint_test_multiplier(); iter++) { nmod_poly_t a, b, c, cinv, d; nmod_poly_struct * tmp; nmod_poly_struct * e; mp_limb_t modulus; slong j, num_threads, l; nmod_poly_interval_poly_arg_t * args1; thread_pool_handle * threads; flint_set_num_threads(1 + n_randint(state, 3)); num_threads = flint_request_threads(&threads, FLINT_DEFAULT_THREAD_LIMIT); l = n_randint(state, 20) + 1; e = (nmod_poly_struct *) flint_malloc(sizeof(nmod_poly_struct)*(num_threads + 1)); tmp = (nmod_poly_struct *) flint_malloc(sizeof(nmod_poly_struct)*l); args1 = (nmod_poly_interval_poly_arg_t *) flint_malloc((num_threads + 1)* sizeof(nmod_poly_interval_poly_arg_t)); modulus = n_randtest_prime(state, 0); nmod_poly_init(a, modulus); nmod_poly_init(b, modulus); nmod_poly_init(c, modulus); nmod_poly_init(cinv, modulus); nmod_poly_init(d, modulus); for (j = 0; j < l; j++) nmod_poly_init(tmp + j, modulus); for (j = 0; j < num_threads + 1; j++) nmod_poly_init(e + j, modulus); nmod_poly_randtest_not_zero(a, state, n_randint(state, 20) + 1); do { nmod_poly_randtest_not_zero(c, state, n_randint(state, 20) + 1); } while (c->length < 3); nmod_poly_rem(a, a, c); for (j = 0; j < l; j++) nmod_poly_randtest_not_zero(tmp + j, state, n_randint(state, 20) + 1); nmod_poly_reverse(cinv, c, c->length); nmod_poly_inv_series(cinv, cinv, c->length); nmod_poly_one(b); for (j = l - 1; j >= 0; j--) { nmod_poly_rem(d, tmp + j, c); nmod_poly_sub(d, a, d); nmod_poly_mulmod_preinv(b, d, b, c, cinv); } for (j = 0; j < num_threads + 1; j++) { nmod_poly_fit_length(e + j, c->length - 1); _nmod_poly_set_length(e + j, c->length - 1); _nmod_vec_zero(e[j].coeffs, c->length - 1); args1[j].baby = tmp; args1[j].res = e + j; args1[j].H = a; args1[j].v = c; args1[j].vinv = cinv; args1[j].m = l; args1[j].tmp = _nmod_vec_init(c->length - 1); } for (j = 0; j < num_threads; j++) thread_pool_wake(global_thread_pool, threads[j], 0, _nmod_poly_interval_poly_worker, &args1[j]); _nmod_poly_interval_poly_worker(&args1[num_threads]); for (j = 0; j < num_threads; j++) thread_pool_wait(global_thread_pool, threads[j]); for (j = 0; j < num_threads + 1; j++) { _nmod_poly_normalise(e + j); _nmod_vec_clear(args1[j].tmp); } for (j = 0; j < num_threads + 1; j++) { if (!nmod_poly_equal(b, e + j)) { flint_printf("j: %wd\n", j); flint_printf("FAIL (interval_poly):\n"); flint_printf("b:\n"); nmod_poly_print(b); flint_printf("\n"); flint_printf("c:\n"); nmod_poly_print(c); flint_printf("\n"); flint_printf("e[j]:\n"); nmod_poly_print(e + j); flint_printf("\n"); fflush(stdout); flint_abort(); } } flint_give_back_threads(threads, num_threads); nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); for (j = 0; j < num_threads + 1; j++) nmod_poly_clear(e + j); for (j = 0; j < l; j++) nmod_poly_clear(tmp + j); flint_free(e); flint_free(tmp); flint_free(args1); } TEST_FUNCTION_END(state); #else TEST_FUNCTION_END_SKIPPED(state); #endif } flint-3.1.3/src/nmod_poly_factor/test/t-is_irreducible.c000066400000000000000000000046471461254215100233430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_is_irreducible, state) { int iter; for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { nmod_poly_t poly, poly2, poly3; nmod_poly_factor_t factors; mp_limb_t modulus; slong length, length2; int result = 1; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly, modulus); nmod_poly_init(poly2, modulus); nmod_poly_init(poly3, modulus); length = n_randint(state, 10) + 2; do { nmod_poly_randtest(poly, state, length); if(!nmod_poly_is_zero(poly)) nmod_poly_make_monic(poly, poly); } while ((!nmod_poly_is_irreducible(poly)) || (poly->length < 2)); nmod_poly_factor_init(factors); nmod_poly_factor_berlekamp(factors, poly); result &= (factors->num == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("Irreducible polynomial should not have non-trivial factors!\n"); flint_printf("poly = "), nmod_poly_print(poly), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_factor_clear(factors); length2 = n_randint(state, 10) + 2; do { nmod_poly_randtest(poly2, state, length2); if(!nmod_poly_is_zero(poly2)) nmod_poly_make_monic(poly2, poly2); } while ((!nmod_poly_is_irreducible(poly2)) || (poly2->length < 2)); nmod_poly_mul(poly3, poly, poly2); result &= !nmod_poly_is_irreducible(poly3); if (!result) { flint_printf("Error: reducible polynomial declared irreducible!\n"); nmod_poly_print(poly3); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(poly); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000045131461254215100241500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Martin Lee This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_is_irreducible_ddf, state) { int iter; for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { nmod_poly_t poly, poly2, poly3; mp_limb_t modulus; slong length, length2; int result = 1; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly, modulus); nmod_poly_init(poly2, modulus); nmod_poly_init(poly3, modulus); length = n_randint(state, 10) + 2; do { nmod_poly_randtest(poly, state, length); if(!nmod_poly_is_zero(poly)) nmod_poly_make_monic(poly, poly); } while ((poly->length < 2)); result &= (nmod_poly_is_irreducible_rabin (poly) == nmod_poly_is_irreducible_ddf (poly)); if (!result) { flint_printf("FAIL:\n"); flint_printf("result of is_irreducible and is_irreducible_ddf does not coincide\n"); flint_printf("poly = "), nmod_poly_print(poly), flint_printf("\n"); fflush(stdout); flint_abort(); } length2 = n_randint(state, 10) + 2; do { nmod_poly_randtest(poly2, state, length2); if(!nmod_poly_is_zero(poly2)) nmod_poly_make_monic(poly2, poly2); } while ((!nmod_poly_is_irreducible_rabin(poly2)) || (poly2->length < 2)); nmod_poly_mul(poly3, poly, poly2); result &= !nmod_poly_is_irreducible_ddf(poly3); if (!result) { flint_printf("Error: reducible polynomial declared irreducible!\n"); nmod_poly_print(poly3); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(poly); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-is_irreducible_rabin.c000066400000000000000000000046771461254215100245210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_is_irreducible_rabin, state) { int iter; for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { nmod_poly_t poly, poly2, poly3; nmod_poly_factor_t factors; mp_limb_t modulus; slong length, length2; int result = 1; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly, modulus); nmod_poly_init(poly2, modulus); nmod_poly_init(poly3, modulus); length = n_randint(state, 10) + 2; do { nmod_poly_randtest(poly, state, length); if(!nmod_poly_is_zero(poly)) nmod_poly_make_monic(poly, poly); } while ((!nmod_poly_is_irreducible_rabin(poly)) || (poly->length < 2)); nmod_poly_factor_init(factors); nmod_poly_factor_berlekamp(factors, poly); result &= (factors->num == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("Irreducible polynomial should not have non-trivial factors!\n"); flint_printf("poly = "), nmod_poly_print(poly), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_factor_clear(factors); length2 = n_randint(state, 10) + 2; do { nmod_poly_randtest(poly2, state, length2); if(!nmod_poly_is_zero(poly2)) nmod_poly_make_monic(poly2, poly2); } while ((!nmod_poly_is_irreducible_rabin(poly2)) || (poly2->length < 2)); nmod_poly_mul(poly3, poly, poly2); result &= !nmod_poly_is_irreducible_rabin(poly3); if (!result) { flint_printf("Error: reducible polynomial declared irreducible!\n"); nmod_poly_print(poly3); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(poly); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-is_squarefree.c000066400000000000000000000043271461254215100232070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" TEST_FUNCTION_START(nmod_poly_factor_is_squarefree, state) { int iter; for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { nmod_poly_t poly, Q, R, t; mp_limb_t modulus; slong i, num_factors, exp, max_exp; int v, result; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly, modulus); nmod_poly_init(t, modulus); nmod_poly_init(Q, modulus); nmod_poly_init(R, modulus); nmod_poly_set_coeff_ui(poly, 0, n_randint(state, modulus)); num_factors = n_randint(state, 5); max_exp = 0; for (i = 0; i < num_factors; i++) { do { nmod_poly_randtest(t, state, n_randint(state, 10)); } while (!nmod_poly_is_irreducible(t) || (nmod_poly_length(t) < 2)); exp = n_randint(state, 4) + 1; if (n_randint(state, 2) == 0) exp = 1; nmod_poly_divrem(Q, R, poly, t); if (!nmod_poly_is_zero(R)) { nmod_poly_pow(t, t, exp); nmod_poly_mul(poly, poly, t); max_exp = FLINT_MAX(exp, max_exp); } } v = nmod_poly_is_squarefree(poly); if (v == 1) result = (max_exp <= 1 && !nmod_poly_is_zero(poly)); else result = (max_exp > 1 || nmod_poly_is_zero(poly)); if (!result) { flint_printf("FAIL: %wu, %wd, %d\n", modulus, max_exp, v); nmod_poly_print(poly); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(poly); nmod_poly_clear(t); nmod_poly_clear(Q); nmod_poly_clear(R); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_factor/test/t-roots.c000066400000000000000000000064361461254215100215230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" /* Defined in t-roots.c and t-roots_factored.c */ #define test_poly test_poly_roots void test_poly( nmod_poly_factor_t roots, const nmod_poly_t f, int want_mult) { slong i, multiplicity; nmod_poly_t q, qt, r; nmod_poly_init_mod(q, f->mod); nmod_poly_init_mod(qt, f->mod); nmod_poly_init_mod(r, f->mod); nmod_poly_set(q, f); nmod_poly_roots(roots, f, want_mult); for (i = 0; i < roots->num; i++) { if (nmod_poly_degree(roots->p + i) != 1) { flint_printf("FAIL:\ncheck root is linear\n"); fflush(stdout); flint_abort(); } if (roots->p[i].coeffs[1] != 1) { flint_printf("FAIL:\ncheck root is monic\n"); fflush(stdout); flint_abort(); } multiplicity = 0; while (nmod_poly_divrem(qt, r, q, roots->p + i), nmod_poly_is_zero(r)) { nmod_poly_swap(q, qt); multiplicity++; } if (multiplicity <= 0) { flint_printf("FAIL:\ncheck root is a root\n"); fflush(stdout); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAIL:\ncheck root multiplicity\n"); fflush(stdout); flint_abort(); } } nmod_poly_roots(roots, q, want_mult); if (roots->num > 0) { flint_printf("FAIL:\ncheck missing roots\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(qt); nmod_poly_clear(r); } TEST_FUNCTION_START(nmod_poly_factor_roots, state) { slong i, j, k, l; for (i = 0; i < 20 * flint_test_multiplier(); i++) { mp_limb_t p; nmod_poly_t f; nmod_poly_factor_t r; p = n_randtest_prime(state, 1); nmod_poly_init(f, p); nmod_poly_factor_init(r); for (j = 0; j < 4; j++) { do { nmod_poly_randtest(f, state, n_randint(state, 25) + 1); } while (nmod_poly_is_zero(f)); for (k = 0; k < 8; k++) { nmod_poly_t ff; nmod_poly_init(ff, p); nmod_poly_set_coeff_ui(ff, 1, 1); nmod_poly_set_coeff_ui(ff, 0, n_randint(state, p)); for (l = 1 + n_randint(state, 8); l > 0; l--) nmod_poly_mul(f, f, ff); nmod_poly_clear(ff); } if (n_randint(state, 2)) { test_poly(r, f, 1); test_poly(r, f, 0); } else { test_poly(r, f, 0); test_poly(r, f, 1); } } nmod_poly_factor_clear(r); nmod_poly_clear(f); } TEST_FUNCTION_END(state); } #undef test_poly flint-3.1.3/src/nmod_poly_factor/test/t-roots_factored.c000066400000000000000000000127121461254215100233640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" /* Defined in t-roots.c and t-roots_factored.c */ #define test_poly test_poly_factored void test_poly( nmod_poly_factor_t roots, const nmod_poly_t f, int want_mult, const n_factor_t * n) { slong i, multiplicity; nmod_poly_t q, qt, r; nmod_poly_init_mod(q, f->mod); nmod_poly_init_mod(qt, f->mod); nmod_poly_init_mod(r, f->mod); if (!nmod_poly_roots_factored(roots, f, want_mult, n)) { flint_printf("FAILED:\ncheck roots could be computed\n"); fflush(stdout); flint_abort(); } for (i = 0; i < roots->num; i++) { if (nmod_poly_degree(roots->p + i) != 1) { flint_printf("FAILED:\ncheck root is linear\n"); fflush(stdout); flint_abort(); } if (roots->p[i].coeffs[1] != 1) { flint_printf("FAILED:\ncheck root is monic\n"); fflush(stdout); flint_abort(); } nmod_poly_set(q, f); multiplicity = 0; while (nmod_poly_divrem(qt, r, q, roots->p + i), nmod_poly_is_zero(r)) { nmod_poly_swap(q, qt); multiplicity++; } if (multiplicity <= 0) { flint_printf("FAILED:\ncheck root is a root\n"); fflush(stdout); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); fflush(stdout); flint_abort(); } } if (f->mod.n < 4000) { ulong k; for (k = 0; k < f->mod.n; k++) { int found = 0; if (0 != nmod_poly_evaluate_nmod(f, k)) continue; for (i = 0; i < roots->num; i++) { if (0 == nmod_poly_evaluate_nmod(roots->p + i, k)) { if (found) { flint_printf("FAILED:\ncheck duplicate roots\n"); fflush(stdout); flint_abort(); } found = 1; } } if (!found) { flint_printf("FAILED:\ncheck missing roots\n"); fflush(stdout); flint_abort(); } } } nmod_poly_clear(q); nmod_poly_clear(qt); nmod_poly_clear(r); } TEST_FUNCTION_START(nmod_poly_factor_roots_factored, state) { slong i, j, k, l; for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t f; nmod_poly_factor_t roots; mp_limb_t a, n; mp_limb_t * sqrt; n_factor_t nfac; n = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); n = FLINT_MAX(n, UWORD(2)); n_factor_init(&nfac); n_factor(&nfac, n, 0); nmod_poly_init(f, n); nmod_poly_factor_init(roots); for (j = 0; j < 50; j++) { a = n_randint(state, n); nmod_poly_zero(f); nmod_poly_set_coeff_ui(f, 2, n - 1); nmod_poly_set_coeff_ui(f, 0, a); if (!nmod_poly_roots_factored(roots, f, 0, &nfac)) { flint_printf("FAILED:\ncheck sqrt could be calculated\n"); fflush(stdout); flint_abort(); } if (roots->num != n_sqrtmodn(&sqrt, a, &nfac)) { flint_printf("FAILED:\ncheck root count against n_sqrtmodn\n"); fflush(stdout); flint_abort(); } if (sqrt) flint_free(sqrt); test_poly(roots, f, 0, &nfac); test_poly(roots, f, 1, &nfac); } nmod_poly_clear(f); nmod_poly_factor_clear(roots); } for (i = 0; i < 50 * flint_test_multiplier(); i++) { ulong p; nmod_poly_t f; nmod_poly_factor_t r; n_factor_t n; p = n_randbits(state, n_randint(state, FLINT_BITS) + 1); p = FLINT_MAX(p, UWORD(2)); n_factor_init(&n); n_factor(&n, p, 1); nmod_poly_init(f, p); nmod_poly_factor_init(r); for (j = 0; j < 4; j++) { slong m = 80/FLINT_BIT_COUNT(p); do { nmod_poly_randtest(f, state, n_randint(state, 10 + m) + 1); } while (nmod_poly_is_zero(f)); for (k = 0; k < m; k++) { nmod_poly_t ff; nmod_poly_init_mod(ff, f->mod); nmod_poly_set_coeff_ui(ff, 1, 1); nmod_poly_set_coeff_ui(ff, 0, n_randint(state, p)); for (l = n_randint(state, m); l > 0; l--) nmod_poly_mul(f, f, ff); nmod_poly_clear(ff); } test_poly(r, f, 0, &n); if (r->num < 1000) test_poly(r, f, 1, &n); } nmod_poly_factor_clear(r); nmod_poly_clear(f); } TEST_FUNCTION_END(state); } #undef test_poly flint-3.1.3/src/nmod_poly_mat.h000066400000000000000000000213571461254215100164440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_POLY_MAT_H #define NMOD_POLY_MAT_H #ifdef NMOD_POLY_MAT_INLINES_C #define NMOD_POLY_MAT_INLINE #else #define NMOD_POLY_MAT_INLINE static inline #endif #include "nmod_types.h" #ifdef __cplusplus extern "C" { #endif NMOD_POLY_MAT_INLINE nmod_poly_struct * nmod_poly_mat_entry(const nmod_poly_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } NMOD_POLY_MAT_INLINE slong nmod_poly_mat_nrows(const nmod_poly_mat_t mat) { return mat->r; } NMOD_POLY_MAT_INLINE slong nmod_poly_mat_ncols(const nmod_poly_mat_t mat) { return mat->c; } /* Memory management *********************************************************/ void nmod_poly_mat_init(nmod_poly_mat_t mat, slong rows, slong cols, mp_limb_t n); void nmod_poly_mat_init_set(nmod_poly_mat_t mat, const nmod_poly_mat_t src); NMOD_POLY_MAT_INLINE void nmod_poly_mat_swap(nmod_poly_mat_t mat1, nmod_poly_mat_t mat2) { FLINT_SWAP(nmod_poly_mat_struct, *mat1, *mat2); } NMOD_POLY_MAT_INLINE void nmod_poly_mat_swap_entrywise(nmod_poly_mat_t mat1, nmod_poly_mat_t mat2) { slong i, j; for (i = 0; i < nmod_poly_mat_nrows(mat1); i++) for (j = 0; j < nmod_poly_mat_ncols(mat1); j++) FLINT_SWAP(nmod_poly_struct, *nmod_poly_mat_entry(mat2, i, j), *nmod_poly_mat_entry(mat1, i, j)); } void nmod_poly_mat_set(nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2); void nmod_poly_mat_set_nmod_mat(nmod_poly_mat_t pmat, const nmod_mat_t cmat); void nmod_poly_mat_clear(nmod_poly_mat_t mat); /* Truncate, shift *********************************************************/ void nmod_poly_mat_set_trunc(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, long len); NMOD_POLY_MAT_INLINE void nmod_poly_mat_truncate(nmod_poly_mat_t pmat, long len) { nmod_poly_mat_set_trunc(pmat, pmat, len); } void nmod_poly_mat_shift_left(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, slong k); void nmod_poly_mat_shift_right(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, slong k); /* Basic properties **********************************************************/ NMOD_POLY_MAT_INLINE mp_limb_t nmod_poly_mat_modulus(const nmod_poly_mat_t mat) { return mat->modulus; } void nmod_poly_mat_get_coeff_mat(nmod_mat_t coeff, const nmod_poly_mat_t pmat, slong deg); void nmod_poly_mat_set_coeff_mat(nmod_poly_mat_t pmat, const nmod_mat_t coeff, slong deg); /* Comparison ****************************************************************/ int nmod_poly_mat_equal(const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2); int nmod_poly_mat_equal_nmod_mat(const nmod_poly_mat_t pmat, const nmod_mat_t cmat); int nmod_poly_mat_is_zero(const nmod_poly_mat_t mat); int nmod_poly_mat_is_one(const nmod_poly_mat_t mat); NMOD_POLY_MAT_INLINE int nmod_poly_mat_is_empty(const nmod_poly_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } NMOD_POLY_MAT_INLINE int nmod_poly_mat_is_square(const nmod_poly_mat_t mat) { return (mat->r == mat->c); } /* Standard matrices *********************************************************/ void nmod_poly_mat_zero(nmod_poly_mat_t mat); void nmod_poly_mat_one(nmod_poly_mat_t mat); /* Random matrices ***********************************************************/ void nmod_poly_mat_randtest(nmod_poly_mat_t mat, flint_rand_t state, slong len); void nmod_poly_mat_randtest_sparse(nmod_poly_mat_t A, flint_rand_t state, slong len, float density); /* Windows and concatenation */ void nmod_poly_mat_window_init(nmod_poly_mat_t window, const nmod_poly_mat_t mat, slong r1, slong c1, slong r2, slong c2); void nmod_poly_mat_window_clear(nmod_poly_mat_t window); void nmod_poly_mat_concat_horizontal(nmod_poly_mat_t res, const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2); void nmod_poly_mat_concat_vertical(nmod_poly_mat_t res, const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2); /* Input and output **********************************************************/ void nmod_poly_mat_print(const nmod_poly_mat_t mat, const char * x); /* Norms *********************************************************************/ slong nmod_poly_mat_max_length(const nmod_poly_mat_t A); NMOD_POLY_MAT_INLINE slong nmod_poly_mat_degree(const nmod_poly_mat_t pmat) { return nmod_poly_mat_max_length(pmat)-1; } /* Scalar arithmetic *********************************************************/ void nmod_poly_mat_scalar_mul_nmod_poly(nmod_poly_mat_t B, const nmod_poly_mat_t A, const nmod_poly_t c); void nmod_poly_mat_scalar_mul_nmod(nmod_poly_mat_t B, const nmod_poly_mat_t A, mp_limb_t c); /* Matrix arithmetic *********************************************************/ void nmod_poly_mat_add(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); void nmod_poly_mat_sub(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); void nmod_poly_mat_neg(nmod_poly_mat_t B, const nmod_poly_mat_t A); void nmod_poly_mat_mul(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); void nmod_poly_mat_mul_interpolate(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); void nmod_poly_mat_mul_classical(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); void nmod_poly_mat_mul_KS(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); void nmod_poly_mat_sqr(nmod_poly_mat_t B, const nmod_poly_mat_t A); void nmod_poly_mat_sqr_classical(nmod_poly_mat_t B, const nmod_poly_mat_t A); void nmod_poly_mat_sqr_KS(nmod_poly_mat_t B, const nmod_poly_mat_t A); void nmod_poly_mat_sqr_interpolate(nmod_poly_mat_t B, const nmod_poly_mat_t A); void nmod_poly_mat_pow(nmod_poly_mat_t B, const nmod_poly_mat_t A, ulong exp); /* Evaluation ****************************************************************/ void nmod_poly_mat_evaluate_nmod(nmod_mat_t B, const nmod_poly_mat_t A, mp_limb_t x); /* Row reduction *************************************************************/ slong nmod_poly_mat_find_pivot_any(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c); slong nmod_poly_mat_find_pivot_partial(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c); slong nmod_poly_mat_fflu(nmod_poly_mat_t B, nmod_poly_t den, slong * perm, const nmod_poly_mat_t A, int rank_check); slong nmod_poly_mat_rref(nmod_poly_mat_t B, nmod_poly_t den, const nmod_poly_mat_t A); /* Trace *********************************************************************/ void nmod_poly_mat_trace(nmod_poly_t trace, const nmod_poly_mat_t mat); /* Determinant and rank ******************************************************/ void nmod_poly_mat_det(nmod_poly_t det, const nmod_poly_mat_t A); void nmod_poly_mat_det_fflu(nmod_poly_t det, const nmod_poly_mat_t A); void nmod_poly_mat_det_interpolate(nmod_poly_t det, const nmod_poly_mat_t A); slong nmod_poly_mat_rank(const nmod_poly_mat_t A); /* Inverse *******************************************************************/ int nmod_poly_mat_inv(nmod_poly_mat_t Ainv, nmod_poly_t den, const nmod_poly_mat_t A); /* Nullspace *****************************************************************/ slong nmod_poly_mat_nullspace(nmod_poly_mat_t res, const nmod_poly_mat_t mat); /* Solving *******************************************************************/ int nmod_poly_mat_solve(nmod_poly_mat_t X, nmod_poly_t den, const nmod_poly_mat_t A, const nmod_poly_mat_t B); int nmod_poly_mat_solve_fflu(nmod_poly_mat_t X, nmod_poly_t den, const nmod_poly_mat_t A, const nmod_poly_mat_t B); void nmod_poly_mat_solve_fflu_precomp(nmod_poly_mat_t X, const slong * perm, const nmod_poly_mat_t FFLU, const nmod_poly_mat_t B); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod_poly_mat/000077500000000000000000000000001461254215100162635ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly_mat/add.c000066400000000000000000000014711461254215100171620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_add(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_add(nmod_poly_mat_entry(C, i, j), nmod_poly_mat_entry(A, i, j), nmod_poly_mat_entry(B, i, j)); } flint-3.1.3/src/nmod_poly_mat/clear.c000066400000000000000000000013551461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_clear(nmod_poly_mat_t A) { if (A->entries) { slong i; for (i = 0; i < A->r * A->c; i++) nmod_poly_clear(A->entries + i); flint_free(A->entries); flint_free(A->rows); } else if (A->r != 0) flint_free(A->rows); } flint-3.1.3/src/nmod_poly_mat/concat.c000066400000000000000000000031631461254215100177010ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_concat_horizontal(nmod_poly_mat_t res, const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { nmod_poly_set(nmod_poly_mat_entry(res, i, j), nmod_poly_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { nmod_poly_set(nmod_poly_mat_entry(res, i, j + c1), nmod_poly_mat_entry(mat2, i, j)); } } } void nmod_poly_mat_concat_vertical(nmod_poly_mat_t res, const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2) { slong i, j; slong r1 = mat1->r; slong c1 = mat1->c; slong r2 = mat2->r; slong c2 = mat2->c; for (i = 0; i < r1; i++) { for (j = 0; j < c1; j++) { nmod_poly_set(nmod_poly_mat_entry(res, i, j), nmod_poly_mat_entry(mat1, i, j)); } } for (i = 0; i < r2; i++) { for (j = 0; j < c2; j++) { nmod_poly_set(nmod_poly_mat_entry(res, i + r1, j), nmod_poly_mat_entry(mat2, i, j)); } } } flint-3.1.3/src/nmod_poly_mat/det.c000066400000000000000000000053071461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_det_fflu(nmod_poly_t det, const nmod_poly_mat_t A) { slong n = nmod_poly_mat_nrows(A); if (n == 0) nmod_poly_one(det); else { nmod_poly_mat_t tmp; slong * perm; nmod_poly_mat_init_set(tmp, A); perm = _perm_init(n); nmod_poly_mat_fflu(tmp, det, perm, tmp, 1); if (_perm_parity(perm, n)) nmod_poly_neg(det, det); _perm_clear(perm); nmod_poly_mat_clear(tmp); } } void nmod_poly_mat_det_interpolate(nmod_poly_t det, const nmod_poly_mat_t A) { slong i, l, n, len; nmod_mat_t X; mp_ptr x, d; n = A->r; if (n == 0) { nmod_poly_one(det); return; } l = nmod_poly_mat_max_length(A); if (l == 0) { nmod_poly_zero(det); return; } /* Bound degree based on Laplace expansion */ len = n*(l - 1) + 1; /* Not enough points to interpolate */ if (len > nmod_poly_mat_modulus(A)) { nmod_poly_mat_det_fflu(det, A); return; } x = _nmod_vec_init(len); d = _nmod_vec_init(len); nmod_mat_init(X, n, n, nmod_poly_mat_modulus(A)); for (i = 0; i < len; i++) { x[i] = i; nmod_poly_mat_evaluate_nmod(X, A, x[i]); d[i] = nmod_mat_det(X); } nmod_poly_interpolate_nmod_vec(det, x, d, len); _nmod_vec_clear(x); _nmod_vec_clear(d); nmod_mat_clear(X); } void nmod_poly_mat_det(nmod_poly_t det, const nmod_poly_mat_t A) { slong n = A->r; if (n == 0) { nmod_poly_one(det); } else if (n == 1) { nmod_poly_set(det, nmod_poly_mat_entry(A, 0, 0)); } else if (n == 2) { nmod_poly_t tmp; nmod_poly_init(tmp, nmod_poly_mat_modulus(A)); nmod_poly_mul(det, nmod_poly_mat_entry(A, 0, 0), nmod_poly_mat_entry(A, 1, 1)); nmod_poly_mul(tmp, nmod_poly_mat_entry(A, 0, 1), nmod_poly_mat_entry(A, 1, 0)); nmod_poly_sub(det, det, tmp); nmod_poly_clear(tmp); } else if (n < 15) /* should be entry sensitive too */ { nmod_poly_mat_det_fflu(det, A); } else { nmod_poly_mat_det_interpolate(det, A); } } flint-3.1.3/src/nmod_poly_mat/equal.c000066400000000000000000000024651461254215100175450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" int nmod_poly_mat_equal(const nmod_poly_mat_t A, const nmod_poly_mat_t B) { slong i, j; if (A->r != B->r || A->c != B->c) return 0; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) if (!nmod_poly_equal(nmod_poly_mat_entry(A, i, j), nmod_poly_mat_entry(B, i, j))) return 0; return 1; } int nmod_poly_mat_equal_nmod_mat(const nmod_poly_mat_t pmat, const nmod_mat_t cmat) { if (pmat->r != cmat->r || pmat->c != cmat->c) return 0; for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) if (! nmod_poly_equal_nmod(nmod_poly_mat_entry(pmat, i, j), nmod_mat_entry(cmat, i, j))) return 0; return 1; } flint-3.1.3/src/nmod_poly_mat/evaluate_nmod.c000066400000000000000000000013701461254215100212530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_evaluate_nmod(nmod_mat_t B, const nmod_poly_mat_t A, mp_limb_t x) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_mat_entry(B, i, j) = nmod_poly_evaluate_nmod( nmod_poly_mat_entry(A, i, j), x); } flint-3.1.3/src/nmod_poly_mat/fflu.c000066400000000000000000000044701461254215100173700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #define E(j,k) nmod_poly_mat_entry(B,j,k) static inline void nmod_poly_mat_swap_rows(nmod_poly_mat_t mat, slong * perm, slong r, slong s) { if (r != s) { nmod_poly_struct * u; slong t; if (perm) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } u = mat->rows[s]; mat->rows[s] = mat->rows[r]; mat->rows[r] = u; } } slong nmod_poly_mat_fflu(nmod_poly_mat_t B, nmod_poly_t den, slong * perm, const nmod_poly_mat_t A, int rank_check) { nmod_poly_t t; slong m, n, j, k, rank, r, pivot_row, pivot_col; if (nmod_poly_mat_is_empty(A)) { nmod_poly_one(den); return 0; } nmod_poly_mat_set(B, A); m = B->r; n = B->c; rank = pivot_row = pivot_col = 0; nmod_poly_init(t, nmod_poly_mat_modulus(A)); while (pivot_row < m && pivot_col < n) { r = nmod_poly_mat_find_pivot_partial(B, pivot_row, m, pivot_col); if (r == -1) { if (rank_check) { nmod_poly_zero(den); rank = 0; break; } pivot_col++; continue; } else if (r != pivot_row) nmod_poly_mat_swap_rows(B, perm, pivot_row, r); rank++; for (j = pivot_row + 1; j < m; j++) { for (k = pivot_col + 1; k < n; k++) { nmod_poly_mul(E(j, k), E(j, k), E(pivot_row, pivot_col)); nmod_poly_mul(t, E(j, pivot_col), E(pivot_row, k)); nmod_poly_sub(E(j, k), E(j, k), t); if (pivot_row > 0) nmod_poly_divexact(E(j, k), E(j, k), den); } } nmod_poly_set(den, E(pivot_row, pivot_col)); pivot_row++; pivot_col++; } nmod_poly_clear(t); return rank; } flint-3.1.3/src/nmod_poly_mat/find_pivot_any.c000066400000000000000000000013761461254215100214460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" slong nmod_poly_mat_find_pivot_any(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c) { slong r; for (r = start_row; r < end_row; r++) { if (!nmod_poly_is_zero(nmod_poly_mat_entry(mat, r, c))) return r; } return -1; } flint-3.1.3/src/nmod_poly_mat/find_pivot_partial.c000066400000000000000000000020741461254215100223070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" slong nmod_poly_mat_find_pivot_partial(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c) { slong best_row, best_length, i; best_row = start_row; best_length = nmod_poly_length(nmod_poly_mat_entry(mat, start_row, c)); for (i = start_row + 1; i < end_row; i++) { slong l; l = nmod_poly_length(nmod_poly_mat_entry(mat, i, c)); if (l != 0 && (best_length == 0 || l <= best_length)) { best_row = i; best_length = l; } } if (best_length == 0) return -1; return best_row; } flint-3.1.3/src/nmod_poly_mat/get_set_coeff_mat.c000066400000000000000000000021361461254215100220660ustar00rootroot00000000000000/* Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_get_coeff_mat(nmod_mat_t res, const nmod_poly_mat_t mat, slong deg) { for (slong i = 0; i < mat->r; i++) for (slong j = 0; j < mat->c; j++) nmod_mat_set_entry(res, i, j, nmod_poly_get_coeff_ui(nmod_poly_mat_entry(mat, i, j), deg)); } void nmod_poly_mat_set_coeff_mat(nmod_poly_mat_t pmat, const nmod_mat_t coeff, slong deg) { for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) nmod_poly_set_coeff_ui(nmod_poly_mat_entry(pmat, i, j), deg, nmod_mat_entry(coeff, i, j)); } flint-3.1.3/src/nmod_poly_mat/init.c000066400000000000000000000023201461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_init(nmod_poly_mat_t A, slong rows, slong cols, mp_limb_t n) { slong i; if (rows > 0) A->rows = (nmod_poly_struct **) flint_malloc(rows * sizeof(nmod_poly_struct *)); else A->rows = NULL; if (rows > 0 && cols > 0) { A->entries = (nmod_poly_struct *) flint_malloc(flint_mul_sizes(rows, cols) * sizeof(nmod_poly_struct)); for (i = 0; i < rows * cols; i++) nmod_poly_init(A->entries + i, n); for (i = 0; i < rows; i++) A->rows[i] = A->entries + i * cols; } else { A->entries = NULL; if (rows > 0) { for (i = 0; i < rows; i++) A->rows[i] = NULL; } } A->modulus = n; A->r = rows; A->c = cols; } flint-3.1.3/src/nmod_poly_mat/init_set.c000066400000000000000000000011571461254215100202510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_init_set(nmod_poly_mat_t A, const nmod_poly_mat_t B) { nmod_poly_mat_init(A, B->r, B->c, nmod_poly_mat_modulus(B)); nmod_poly_mat_set(A, B); } flint-3.1.3/src/nmod_poly_mat/inlines.c000066400000000000000000000007111461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_POLY_MAT_INLINES_C #include "flint.h" #include "nmod_poly_mat.h" flint-3.1.3/src/nmod_poly_mat/inv.c000066400000000000000000000043211461254215100172230ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "perm.h" #define E nmod_poly_mat_entry int nmod_poly_mat_inv(nmod_poly_mat_t Ainv, nmod_poly_t den, const nmod_poly_mat_t A) { slong n = nmod_poly_mat_nrows(A); if (n == 0) { nmod_poly_one(den); return 1; } else if (n == 1) { nmod_poly_set(den, E(A, 0, 0)); nmod_poly_one(E(Ainv, 0, 0)); return !nmod_poly_is_zero(den); } else if (n == 2) { nmod_poly_mat_det(den, A); if (nmod_poly_is_zero(den)) { return 0; } else if (Ainv == A) { nmod_poly_swap(E(A, 0, 0), E(A, 1, 1)); nmod_poly_neg(E(A, 0, 1), E(A, 0, 1)); nmod_poly_neg(E(A, 1, 0), E(A, 1, 0)); return 1; } else { nmod_poly_set(E(Ainv, 0, 0), E(A, 1, 1)); nmod_poly_set(E(Ainv, 1, 1), E(A, 0, 0)); nmod_poly_neg(E(Ainv, 0, 1), E(A, 0, 1)); nmod_poly_neg(E(Ainv, 1, 0), E(A, 1, 0)); return 1; } } else { nmod_poly_mat_t LU, I; slong * perm; int result; perm = _perm_init(n); nmod_poly_mat_init_set(LU, A); result = (nmod_poly_mat_fflu(LU, den, perm, LU, 1) == n); if (result) { nmod_poly_mat_init(I, n, n, nmod_poly_mat_modulus(A)); nmod_poly_mat_one(I); nmod_poly_mat_solve_fflu_precomp(Ainv, perm, LU, I); nmod_poly_mat_clear(I); } else nmod_poly_zero(den); if (_perm_parity(perm, n)) { nmod_poly_mat_neg(Ainv, Ainv); nmod_poly_neg(den, den); } _perm_clear(perm); nmod_poly_mat_clear(LU); return result; } } flint-3.1.3/src/nmod_poly_mat/is_one.c000066400000000000000000000017301461254215100177040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int nmod_poly_mat_is_one(const nmod_poly_mat_t A) { slong i, j; if (A->r == 0 || A->c == 0) return 1; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (i == j) { if (!nmod_poly_is_one(nmod_poly_mat_entry(A, i, j))) return 0; } else { if (!nmod_poly_is_zero(nmod_poly_mat_entry(A, i, j))) return 0; } } } return 1; } flint-3.1.3/src/nmod_poly_mat/is_zero.c000066400000000000000000000013551461254215100201050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int nmod_poly_mat_is_zero(const nmod_poly_mat_t A) { slong i, j; if (A->r == 0 || A->c == 0) return 1; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) if (!nmod_poly_is_zero(nmod_poly_mat_entry(A, i, j))) return 0; return 1; } flint-3.1.3/src/nmod_poly_mat/max_length.c000066400000000000000000000014061461254215100205560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" slong nmod_poly_mat_max_length(const nmod_poly_mat_t A) { slong i, j, len, max; max = 0; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { len = nmod_poly_length(nmod_poly_mat_entry(A, i, j)); max = FLINT_MAX(len, max); } } return max; } flint-3.1.3/src/nmod_poly_mat/mul.c000066400000000000000000000026371461254215100172340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #define KS_MIN_DIM 10 #define INTERPOLATE_MIN_DIM 60 #define KS_MAX_LENGTH 128 void nmod_poly_mat_mul(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { slong ar, bc, br, dim; ar = A->r; br = B->r; bc = B->c; dim = FLINT_MIN(FLINT_MIN(ar, br), bc); if (dim < KS_MIN_DIM) { nmod_poly_mat_mul_classical(C, A, B); } else { slong Alen, Blen; mp_limb_t mod = nmod_poly_mat_modulus(A); Alen = nmod_poly_mat_max_length(A); Blen = nmod_poly_mat_max_length(B); if ((FLINT_BIT_COUNT(mod) > FLINT_BITS / 4) && (dim > INTERPOLATE_MIN_DIM + n_sqrt(FLINT_MIN(Alen, Blen))) && (mod >= Alen + Blen - 1) && n_is_prime(mod)) nmod_poly_mat_mul_interpolate(C, A, B); else if (Alen > KS_MAX_LENGTH || Blen > KS_MAX_LENGTH) nmod_poly_mat_mul_classical(C, A, B); else nmod_poly_mat_mul_KS(C, A, B); } } flint-3.1.3/src/nmod_poly_mat/mul_KS.c000066400000000000000000000034201461254215100176200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" #include "fmpz_mat.h" void nmod_poly_mat_mul_KS(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { slong i, j; slong A_len, B_len; flint_bitcnt_t bit_size; fmpz_mat_t AA, BB, CC; if (B->r == 0) { nmod_poly_mat_zero(C); return; } A_len = nmod_poly_mat_max_length(A); B_len = nmod_poly_mat_max_length(B); bit_size = 2 * FLINT_BIT_COUNT(nmod_poly_mat_modulus(A)); bit_size += FLINT_BIT_COUNT(FLINT_MIN(A_len, B_len)); bit_size += FLINT_BIT_COUNT(B->r); fmpz_mat_init(AA, A->r, A->c); fmpz_mat_init(BB, B->r, B->c); fmpz_mat_init(CC, C->r, C->c); for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_bit_pack(fmpz_mat_entry(AA, i, j), nmod_poly_mat_entry(A, i, j), bit_size); for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) nmod_poly_bit_pack(fmpz_mat_entry(BB, i, j), nmod_poly_mat_entry(B, i, j), bit_size); fmpz_mat_mul(CC, AA, BB); for (i = 0; i < C->r; i++) for (j = 0; j < C->c; j++) nmod_poly_bit_unpack(nmod_poly_mat_entry(C, i, j), fmpz_mat_entry(CC, i, j), bit_size); fmpz_mat_clear(AA); fmpz_mat_clear(BB); fmpz_mat_clear(CC); } flint-3.1.3/src/nmod_poly_mat/mul_classical.c000066400000000000000000000032361461254215100212460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_mul_classical(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { slong ar, bc, br; slong i, j, k; nmod_poly_t t; ar = A->r; br = B->r; bc = B->c; if (br == 0 || ar == 0 || bc == 0) { nmod_poly_mat_zero(C); return; } if (C == A || C == B) { nmod_poly_mat_t T; nmod_poly_mat_init(T, ar, bc, nmod_poly_mat_modulus(A)); nmod_poly_mat_mul_classical(T, A, B); nmod_poly_mat_swap_entrywise(C, T); nmod_poly_mat_clear(T); return; } nmod_poly_init(t, nmod_poly_mat_modulus(A)); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { nmod_poly_mul(nmod_poly_mat_entry(C, i, j), nmod_poly_mat_entry(A, i, 0), nmod_poly_mat_entry(B, 0, j)); for (k = 1; k < br; k++) { nmod_poly_mul(t, nmod_poly_mat_entry(A, i, k), nmod_poly_mat_entry(B, k, j)); nmod_poly_add(nmod_poly_mat_entry(C, i, j), nmod_poly_mat_entry(C, i, j), t); } } } nmod_poly_clear(t); } flint-3.1.3/src/nmod_poly_mat/mul_interpolate.c000066400000000000000000000070421461254215100216350ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_mul_interpolate(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { slong i, j, k; slong A_len, B_len, len; nmod_mat_t *C_mod, *A_mod, *B_mod; mp_ptr xs; mp_ptr tt, uu; mp_ptr * tree; mp_ptr weights; nmod_t mod; if (B->r == 0) { nmod_poly_mat_zero(C); return; } A_len = nmod_poly_mat_max_length(A); B_len = nmod_poly_mat_max_length(B); if (A_len == 0 || B_len == 0) { nmod_poly_mat_zero(C); return; } len = A_len + B_len - 1; nmod_init(&mod, nmod_poly_mat_modulus(A)); if (mod.n < len) { flint_throw(FLINT_ERROR, "(nmod_poly_mat_mul_interpolate): Characteristic is too small.\n"); } xs = _nmod_vec_init(len); tt = _nmod_vec_init(len); uu = _nmod_vec_init(len); weights = _nmod_vec_init(len); A_mod = flint_malloc(sizeof(nmod_mat_t) * len); B_mod = flint_malloc(sizeof(nmod_mat_t) * len); C_mod = flint_malloc(sizeof(nmod_mat_t) * len); for (i = 0; i < len; i++) { xs[i] = i; nmod_mat_init(A_mod[i], A->r, A->c, mod.n); nmod_mat_init(B_mod[i], B->r, B->c, mod.n); nmod_mat_init(C_mod[i], C->r, C->c, mod.n); } tree = _nmod_poly_tree_alloc(len); _nmod_poly_tree_build(tree, xs, len, mod); _nmod_poly_interpolation_weights(weights, tree, len, mod); for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { _nmod_poly_evaluate_nmod_vec_fast_precomp(tt, nmod_poly_mat_entry(A, i, j)->coeffs, nmod_poly_mat_entry(A, i, j)->length, tree, len, mod); for (k = 0; k < len; k++) A_mod[k]->rows[i][j] = tt[k]; } } for (i = 0; i < B->r; i++) { for (j = 0; j < B->c; j++) { _nmod_poly_evaluate_nmod_vec_fast_precomp(tt, nmod_poly_mat_entry(B, i, j)->coeffs, nmod_poly_mat_entry(B, i, j)->length, tree, len, mod); for (k = 0; k < len; k++) B_mod[k]->rows[i][j] = tt[k]; } } for (i = 0; i < len; i++) nmod_mat_mul(C_mod[i], A_mod[i], B_mod[i]); for (i = 0; i < C->r; i++) { for (j = 0; j < C->c; j++) { nmod_poly_struct * poly; for (k = 0; k < len; k++) tt[k] = C_mod[k]->rows[i][j]; poly = nmod_poly_mat_entry(C, i, j); nmod_poly_fit_length(poly, len); _nmod_poly_interpolate_nmod_vec_fast_precomp(poly->coeffs, tt, tree, weights, len, mod); poly->length = len; _nmod_poly_normalise(poly); } } _nmod_poly_tree_free(tree, len); for (i = 0; i < len; i++) { nmod_mat_clear(A_mod[i]); nmod_mat_clear(B_mod[i]); nmod_mat_clear(C_mod[i]); } flint_free(A_mod); flint_free(B_mod); flint_free(C_mod); _nmod_vec_clear(xs); _nmod_vec_clear(tt); _nmod_vec_clear(uu); _nmod_vec_clear(weights); } flint-3.1.3/src/nmod_poly_mat/neg.c000066400000000000000000000013201461254215100171740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_neg(nmod_poly_mat_t B, const nmod_poly_mat_t A) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_neg(nmod_poly_mat_entry(B, i, j), nmod_poly_mat_entry(A, i, j)); } flint-3.1.3/src/nmod_poly_mat/nullspace.c000066400000000000000000000036601461254215100204220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" slong nmod_poly_mat_nullspace(nmod_poly_mat_t res, const nmod_poly_mat_t mat) { slong i, j, k, n, rank, nullity; slong * pivots; slong * nonpivots; nmod_poly_mat_t tmp; nmod_poly_t den; n = mat->c; nmod_poly_init(den, nmod_poly_mat_modulus(mat)); nmod_poly_mat_init_set(tmp, mat); rank = nmod_poly_mat_rref(tmp, den, tmp); nullity = n - rank; nmod_poly_mat_zero(res); if (rank == 0) { for (i = 0; i < nullity; i++) nmod_poly_one(res->rows[i] + i); } else if (nullity) { pivots = flint_malloc(rank * sizeof(slong)); nonpivots = flint_malloc(nullity * sizeof(slong)); for (i = j = k = 0; i < rank; i++) { while (nmod_poly_is_zero(tmp->rows[i] + j)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } nmod_poly_set(den, tmp->rows[0] + pivots[0]); for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) nmod_poly_set(res->rows[pivots[j]] + i, tmp->rows[j] + nonpivots[i]); nmod_poly_neg(res->rows[nonpivots[i]] + i, den); } flint_free(pivots); flint_free(nonpivots); } nmod_poly_clear(den); nmod_poly_mat_clear(tmp); return nullity; } flint-3.1.3/src/nmod_poly_mat/one.c000066400000000000000000000012201461254215100172030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_one(nmod_poly_mat_t A) { slong i, n; nmod_poly_mat_zero(A); n = FLINT_MIN(A->r, A->c); for (i = 0; i < n; i++) nmod_poly_one(nmod_poly_mat_entry(A, i, i)); } flint-3.1.3/src/nmod_poly_mat/pow.c000066400000000000000000000026641461254215100172440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_pow(nmod_poly_mat_t B, const nmod_poly_mat_t A, ulong exp) { slong d = nmod_poly_mat_nrows(A); if (exp == 0 || d == 0) { nmod_poly_mat_one(B); } else if (exp == 1) { nmod_poly_mat_set(B, A); } else if (exp == 2) { nmod_poly_mat_sqr(B, A); } else if (d == 1) { nmod_poly_pow(nmod_poly_mat_entry(B, 0, 0), nmod_poly_mat_entry(A, 0, 0), exp); } else { nmod_poly_mat_t T, U; slong i; nmod_poly_mat_init_set(T, A); nmod_poly_mat_init(U, d, d, nmod_poly_mat_modulus(A)); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { nmod_poly_mat_sqr(U, T); if (exp & (WORD(1) << i)) nmod_poly_mat_mul(T, U, A); else nmod_poly_mat_swap(T, U); } nmod_poly_mat_swap(B, T); nmod_poly_mat_clear(T); nmod_poly_mat_clear(U); } } flint-3.1.3/src/nmod_poly_mat/print.c000066400000000000000000000016621461254215100175700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_print(const nmod_poly_mat_t A, const char * x) { slong i, j; flint_printf("<%wd x %wd matrix over Z/nZ[%s]>\n", A->r, A->c, x); for (i = 0; i < A->r; i++) { flint_printf("["); for (j = 0; j < A->c; j++) { /* TODO: pretty */ nmod_poly_print(nmod_poly_mat_entry(A, i, j)); if (j + 1 < A->c) flint_printf(", "); } flint_printf("]\n"); } flint_printf("\n"); } flint-3.1.3/src/nmod_poly_mat/rand.c000066400000000000000000000023471461254215100173610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_randtest(nmod_poly_mat_t A, flint_rand_t state, slong len) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_randtest(nmod_poly_mat_entry(A, i, j), state, len); } void nmod_poly_mat_randtest_sparse(nmod_poly_mat_t A, flint_rand_t state, slong len, float density) { slong i, j; for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { if (n_randint(state, 1000) < density * 1000) { slong l = n_randint(state, len + 1); l = FLINT_MAX(l, 1); nmod_poly_randtest(nmod_poly_mat_entry(A, i, j), state, l); } else { nmod_poly_zero(nmod_poly_mat_entry(A, i, j)); } } } } flint-3.1.3/src/nmod_poly_mat/rank.c000066400000000000000000000015101461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" slong nmod_poly_mat_rank(const nmod_poly_mat_t A) { nmod_poly_mat_t tmp; nmod_poly_t den; slong rank; if (nmod_poly_mat_is_empty(A)) return 0; nmod_poly_mat_init_set(tmp, A); nmod_poly_init(den, nmod_poly_mat_modulus(A)); rank = nmod_poly_mat_fflu(tmp, den, NULL, tmp, 0); nmod_poly_mat_clear(tmp); nmod_poly_clear(den); return rank; } flint-3.1.3/src/nmod_poly_mat/rref.c000066400000000000000000000052411461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2011-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" slong nmod_poly_mat_rref(nmod_poly_mat_t R, nmod_poly_t den, const nmod_poly_mat_t A) { slong i, j, k, m, n, rank; slong *pivots, *nonpivots; rank = nmod_poly_mat_fflu(R, den, NULL, A, 0); m = nmod_poly_mat_nrows(R); n = nmod_poly_mat_ncols(R); /* clear bottom */ for (i = rank; i < m; i++) for (j = 0; j < n; j++) nmod_poly_zero(nmod_poly_mat_entry(R, i, j)); /* Convert row echelon form to reduced row echelon form */ if (rank > 1) { nmod_poly_t tmp, tmp2; nmod_poly_init(tmp, nmod_poly_mat_modulus(R)); nmod_poly_init(tmp2, nmod_poly_mat_modulus(R)); pivots = flint_malloc(sizeof(slong) * n); nonpivots = pivots + rank; /* find pivot positions */ for (i = j = k = 0; i < rank; i++) { while (nmod_poly_is_zero(nmod_poly_mat_entry(R, i, j))) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (k = 0; k < n - rank; k++) { for (i = rank - 2; i >= 0; i--) { nmod_poly_mul(tmp, den, nmod_poly_mat_entry(R, i, nonpivots[k])); for (j = i + 1; j < rank; j++) { nmod_poly_mul(tmp2, nmod_poly_mat_entry(R, i, pivots[j]), nmod_poly_mat_entry(R, j, nonpivots[k])); nmod_poly_sub(tmp, tmp, tmp2); } nmod_poly_divexact(nmod_poly_mat_entry(R, i, nonpivots[k]), tmp, nmod_poly_mat_entry(R, i, pivots[i])); } } /* clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { if (i == j) nmod_poly_set(nmod_poly_mat_entry(R, j, pivots[i]), den); else nmod_poly_zero(nmod_poly_mat_entry(R, j, pivots[i])); } } flint_free(pivots); nmod_poly_clear(tmp); nmod_poly_clear(tmp2); } return rank; } flint-3.1.3/src/nmod_poly_mat/scalar.c000066400000000000000000000023321461254215100176740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_scalar_mul_nmod(nmod_poly_mat_t B, const nmod_poly_mat_t A, mp_limb_t c) { slong i, j; for (i = 0; i < nmod_poly_mat_nrows(B); i++) for (j = 0; j < nmod_poly_mat_ncols(B); j++) nmod_poly_scalar_mul_nmod(nmod_poly_mat_entry(B, i, j), nmod_poly_mat_entry(A, i, j), c); } void nmod_poly_mat_scalar_mul_nmod_poly(nmod_poly_mat_t B, const nmod_poly_mat_t A, const nmod_poly_t c) { slong i, j; for (i = 0; i < nmod_poly_mat_nrows(B); i++) for (j = 0; j < nmod_poly_mat_ncols(B); j++) nmod_poly_mul(nmod_poly_mat_entry(B, i, j), nmod_poly_mat_entry(A, i, j), c); } flint-3.1.3/src/nmod_poly_mat/set.c000066400000000000000000000025021461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" void nmod_poly_mat_set(nmod_poly_mat_t B, const nmod_poly_mat_t A) { if (A != B) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_set(nmod_poly_mat_entry(B, i, j), nmod_poly_mat_entry(A, i, j)); } } void nmod_poly_mat_set_nmod_mat(nmod_poly_mat_t pmat, const nmod_mat_t cmat) { for (slong i = 0; i < cmat->r; i++) { for (slong j = 0; j < cmat->c; j++) { if (nmod_mat_entry(cmat, i, j) == 0) nmod_poly_zero(nmod_poly_mat_entry(pmat, i, j)); else { nmod_poly_realloc(nmod_poly_mat_entry(pmat, i, j), 1); nmod_poly_mat_entry(pmat, i, j)->coeffs[0] = nmod_mat_entry(cmat, i, j); } } } } flint-3.1.3/src/nmod_poly_mat/set_trunc.c000066400000000000000000000031421461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_set_trunc(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, long len) { nmod_poly_struct * res_ij; nmod_poly_struct * pmat_ij; if (pmat == res) { for (slong i = 0; i < pmat->r; i++) { for (slong j = 0; j < pmat->c; j++) { res_ij = nmod_poly_mat_entry(res, i, j); if (res_ij->length > len) { res_ij->length = len; _nmod_poly_normalise(res_ij); } } } } else { slong rlen; for (slong i = 0; i < pmat->r; i++) { for (slong j = 0; j < pmat->c; j++) { res_ij = nmod_poly_mat_entry(res, i, j); pmat_ij = nmod_poly_mat_entry(pmat, i, j); rlen = FLINT_MIN(len, pmat_ij->length); while (rlen > 0 && pmat_ij->coeffs[rlen - 1] == 0) rlen--; nmod_poly_fit_length(res_ij, rlen); _nmod_vec_set(res_ij->coeffs, pmat_ij->coeffs, rlen); _nmod_poly_set_length(res_ij, rlen); } } } } flint-3.1.3/src/nmod_poly_mat/shift_left_right.c000066400000000000000000000017361461254215100217620ustar00rootroot00000000000000/* Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_shift_left(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, slong k) { for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) nmod_poly_shift_left(nmod_poly_mat_entry(res, i, j), nmod_poly_mat_entry(pmat, i, j), k); } void nmod_poly_mat_shift_right(nmod_poly_mat_t res, const nmod_poly_mat_t pmat, slong k) { for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) nmod_poly_shift_right(nmod_poly_mat_entry(res, i, j), nmod_poly_mat_entry(pmat, i, j), k); } flint-3.1.3/src/nmod_poly_mat/solve.c000066400000000000000000000012201461254215100175520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "perm.h" int nmod_poly_mat_solve(nmod_poly_mat_t X, nmod_poly_t den, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { return nmod_poly_mat_solve_fflu(X, den, A, B); } flint-3.1.3/src/nmod_poly_mat/solve_fflu.c000066400000000000000000000023371461254215100206000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "perm.h" int nmod_poly_mat_solve_fflu(nmod_poly_mat_t X, nmod_poly_t den, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { nmod_poly_mat_t LU; slong dim, *perm; int result; if (nmod_poly_mat_is_empty(B)) { nmod_poly_one(den); return 1; } dim = nmod_poly_mat_nrows(A); perm = _perm_init(dim); nmod_poly_mat_init_set(LU, A); result = (nmod_poly_mat_fflu(LU, den, perm, LU, 1) == dim); if (result) { nmod_poly_mat_solve_fflu_precomp(X, perm, LU, B); if (_perm_parity(perm, dim)) { nmod_poly_neg(den, den); nmod_poly_mat_neg(X, X); } } else nmod_poly_zero(den); _perm_clear(perm); nmod_poly_mat_clear(LU); return result; } flint-3.1.3/src/nmod_poly_mat/solve_fflu_precomp.c000066400000000000000000000046031461254215100223230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "perm.h" #define XX(ii,jj) nmod_poly_mat_entry(X,(ii),(jj)) #define BB(ii,jj) nmod_poly_mat_entry(B,(ii),(jj)) #define LU(ii,jj) nmod_poly_mat_entry(FFLU,(ii),(jj)) void nmod_poly_mat_set_perm(nmod_poly_mat_t X, const slong * perm, const nmod_poly_mat_t B) { if (X == B) { flint_throw(FLINT_ERROR, "(%s): Not implemented\n"); } else { slong i, j; if (perm == NULL) flint_throw(FLINT_ERROR, "(%s): perm == NULL\n"); for (i = 0; i < nmod_poly_mat_nrows(B); i++) for (j = 0; j < nmod_poly_mat_ncols(B); j++) nmod_poly_set(nmod_poly_mat_entry(X, i, j), nmod_poly_mat_entry(B, perm[i], j)); } } void nmod_poly_mat_solve_fflu_precomp(nmod_poly_mat_t X, const slong * perm, const nmod_poly_mat_t FFLU, const nmod_poly_mat_t B) { nmod_poly_t T; slong i, j, k, m, n; n = X->r; m = X->c; nmod_poly_init(T, nmod_poly_mat_modulus(B)); nmod_poly_mat_set_perm(X, perm, B); for (k = 0; k < m; k++) { /* Fraction-free forward substitution */ for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { nmod_poly_mul(XX(j, k), XX(j, k), LU(i, i)); nmod_poly_mul(T, LU(j, i), XX(i, k)); nmod_poly_sub(XX(j, k), XX(j, k), T); if (i > 0) nmod_poly_divexact(XX(j, k), XX(j, k), LU(i-1, i-1)); } } /* Fraction-free back substitution */ for (i = n - 2; i >= 0; i--) { nmod_poly_mul(XX(i, k), XX(i, k), LU(n-1, n-1)); for (j = i + 1; j < n; j++) { nmod_poly_mul(T, XX(j, k), LU(i, j)); nmod_poly_sub(XX(i, k), XX(i, k), T); } nmod_poly_divexact(XX(i, k), XX(i, k), LU(i, i)); } } nmod_poly_clear(T); } flint-3.1.3/src/nmod_poly_mat/sqr.c000066400000000000000000000132001461254215100172300ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "fmpz_mat.h" #include "nmod_poly_mat.h" #define KS_MIN_DIM 10 #define INTERPOLATE_MIN_DIM 80 #define KS_MAX_LENGTH 128 void nmod_poly_mat_sqr(nmod_poly_mat_t C, const nmod_poly_mat_t A) { slong dim = A->r; if (dim < KS_MIN_DIM) { nmod_poly_mat_sqr_classical(C, A); } else { slong Alen; mp_limb_t mod = nmod_poly_mat_modulus(A); Alen = nmod_poly_mat_max_length(A); if ((FLINT_BIT_COUNT(mod) > FLINT_BITS / 4) && (dim > INTERPOLATE_MIN_DIM + n_sqrt(Alen)) && (mod >= 2 * Alen - 1) && n_is_prime(mod)) nmod_poly_mat_sqr_interpolate(C, A); if (Alen > KS_MAX_LENGTH) nmod_poly_mat_sqr_classical(C, A); else nmod_poly_mat_sqr_KS(C, A); } } static inline void nmod_poly_sqr(nmod_poly_t y, const nmod_poly_t x) { nmod_poly_mul(y, x, x); } #define E nmod_poly_mat_entry void nmod_poly_mat_sqr_classical(nmod_poly_mat_t B, const nmod_poly_mat_t A) { slong n = A->r; if (n == 0) return; if (n == 1) { nmod_poly_sqr(E(B, 0, 0), E(A, 0, 0)); return; } if (n == 2) { nmod_poly_t t, u; nmod_poly_init(t, nmod_poly_mat_modulus(A)); nmod_poly_init(u, nmod_poly_mat_modulus(A)); nmod_poly_add(t, E(A, 0, 0), E(A, 1, 1)); nmod_poly_mul(u, E(A, 0, 1), E(A, 1, 0)); nmod_poly_sqr(E(B, 0, 0), E(A, 0, 0)); nmod_poly_add(E(B, 0, 0), E(B, 0, 0), u); nmod_poly_sqr(E(B, 1, 1), E(A, 1, 1)); nmod_poly_add(E(B, 1, 1), E(B, 1, 1), u); nmod_poly_mul(E(B, 0, 1), E(A, 0, 1), t); nmod_poly_mul(E(B, 1, 0), E(A, 1, 0), t); nmod_poly_clear(t); nmod_poly_clear(u); return; } nmod_poly_mat_mul_classical(B, A, A); } void nmod_poly_mat_sqr_interpolate(nmod_poly_mat_t C, const nmod_poly_mat_t A) { slong i, j, k; slong A_len, len; nmod_mat_t *C_mod, *A_mod; mp_ptr xs; mp_ptr tt, uu; mp_ptr * tree; mp_ptr weights; nmod_t mod; if (A->c == 0) { nmod_poly_mat_zero(C); return; } A_len = nmod_poly_mat_max_length(A); if (A_len == 0) { nmod_poly_mat_zero(C); return; } len = 2 * A_len - 1; nmod_init(&mod, nmod_poly_mat_modulus(A)); if (mod.n < len) { flint_throw(FLINT_ERROR, "(nmod_poly_mat_sqr_interpolate): Characteristic is too small.\n"); } xs = _nmod_vec_init(len); tt = _nmod_vec_init(len); uu = _nmod_vec_init(len); weights = _nmod_vec_init(len); A_mod = flint_malloc(sizeof(nmod_mat_t) * len); C_mod = flint_malloc(sizeof(nmod_mat_t) * len); for (i = 0; i < len; i++) { xs[i] = i; nmod_mat_init(A_mod[i], A->r, A->c, mod.n); nmod_mat_init(C_mod[i], C->r, C->c, mod.n); } tree = _nmod_poly_tree_alloc(len); _nmod_poly_tree_build(tree, xs, len, mod); _nmod_poly_interpolation_weights(weights, tree, len, mod); for (i = 0; i < A->r; i++) { for (j = 0; j < A->c; j++) { _nmod_poly_evaluate_nmod_vec_fast_precomp(tt, nmod_poly_mat_entry(A, i, j)->coeffs, nmod_poly_mat_entry(A, i, j)->length, tree, len, mod); for (k = 0; k < len; k++) A_mod[k]->rows[i][j] = tt[k]; } } /* should be nmod_mat_sqr */ for (i = 0; i < len; i++) nmod_mat_mul(C_mod[i], A_mod[i], A_mod[i]); for (i = 0; i < C->r; i++) { for (j = 0; j < C->c; j++) { nmod_poly_struct * poly; for (k = 0; k < len; k++) tt[k] = C_mod[k]->rows[i][j]; poly = nmod_poly_mat_entry(C, i, j); nmod_poly_fit_length(poly, len); _nmod_poly_interpolate_nmod_vec_fast_precomp(poly->coeffs, tt, tree, weights, len, mod); poly->length = len; _nmod_poly_normalise(poly); } } _nmod_poly_tree_free(tree, len); for (i = 0; i < len; i++) { nmod_mat_clear(A_mod[i]); nmod_mat_clear(C_mod[i]); } flint_free(A_mod); flint_free(C_mod); _nmod_vec_clear(xs); _nmod_vec_clear(tt); _nmod_vec_clear(uu); _nmod_vec_clear(weights); } void nmod_poly_mat_sqr_KS(nmod_poly_mat_t B, const nmod_poly_mat_t A) { slong i, j, n; slong A_len; flint_bitcnt_t bit_size; fmpz_mat_t AA, BB; n = A->r; if (n == 0) { nmod_poly_mat_zero(B); return; } A_len = nmod_poly_mat_max_length(A); bit_size = 2 * FLINT_BIT_COUNT(nmod_poly_mat_modulus(A)); bit_size += FLINT_BIT_COUNT(A_len); bit_size += FLINT_BIT_COUNT(n); fmpz_mat_init(AA, n, n); fmpz_mat_init(BB, n, n); for (i = 0; i < n; i++) for (j = 0; j < A->c; j++) nmod_poly_bit_pack(fmpz_mat_entry(AA, i, j), nmod_poly_mat_entry(A, i, j), bit_size); fmpz_mat_sqr(BB, AA); for (i = 0; i < n; i++) for (j = 0; j < n; j++) nmod_poly_bit_unpack(nmod_poly_mat_entry(B, i, j), fmpz_mat_entry(BB, i, j), bit_size); fmpz_mat_clear(AA); fmpz_mat_clear(BB); } flint-3.1.3/src/nmod_poly_mat/sub.c000066400000000000000000000014711461254215100172230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_sub(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_sub(nmod_poly_mat_entry(C, i, j), nmod_poly_mat_entry(A, i, j), nmod_poly_mat_entry(B, i, j)); } flint-3.1.3/src/nmod_poly_mat/test/000077500000000000000000000000001461254215100172425ustar00rootroot00000000000000flint-3.1.3/src/nmod_poly_mat/test/main.c000066400000000000000000000050531461254215100203350ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-concat_horizontal.c" #include "t-concat_vertical.c" #include "t-det.c" #include "t-det_interpolate.c" #include "t-get_set_coeff_mat.c" #include "t-init_clear.c" #include "t-inv.c" #include "t-mul.c" #include "t-mul_interpolate.c" #include "t-mul_KS.c" #include "t-neg.c" #include "t-nullspace.c" #include "t-one.c" #include "t-pow.c" #include "t-rank.c" #include "t-rref.c" #include "t-set_nmod_mat.c" #include "t-set_trunc.c" #include "t-shift_left_right.c" #include "t-solve_fflu.c" #include "t-sqr.c" #include "t-sqr_interpolate.c" #include "t-sqr_KS.c" #include "t-sub.c" #include "t-trace.c" #include "t-window_init_clear.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_poly_mat_add), TEST_FUNCTION(nmod_poly_mat_concat_horizontal), TEST_FUNCTION(nmod_poly_mat_concat_vertical), TEST_FUNCTION(nmod_poly_mat_det), TEST_FUNCTION(nmod_poly_mat_det_interpolate), TEST_FUNCTION(nmod_poly_mat_get_set_coeff_mat), TEST_FUNCTION(nmod_poly_mat_init_clear), TEST_FUNCTION(nmod_poly_mat_inv), TEST_FUNCTION(nmod_poly_mat_mul), TEST_FUNCTION(nmod_poly_mat_mul_interpolate), TEST_FUNCTION(nmod_poly_mat_mul_KS), TEST_FUNCTION(nmod_poly_mat_neg), TEST_FUNCTION(nmod_poly_mat_nullspace), TEST_FUNCTION(nmod_poly_mat_one), TEST_FUNCTION(nmod_poly_mat_pow), TEST_FUNCTION(nmod_poly_mat_rank), TEST_FUNCTION(nmod_poly_mat_rref), TEST_FUNCTION(nmod_poly_mat_set_nmod_mat), TEST_FUNCTION(nmod_poly_mat_set_trunc), TEST_FUNCTION(nmod_poly_mat_shift_left_right), TEST_FUNCTION(nmod_poly_mat_solve_fflu), TEST_FUNCTION(nmod_poly_mat_sqr), TEST_FUNCTION(nmod_poly_mat_sqr_interpolate), TEST_FUNCTION(nmod_poly_mat_sqr_KS), TEST_FUNCTION(nmod_poly_mat_sub), TEST_FUNCTION(nmod_poly_mat_trace), TEST_FUNCTION(nmod_poly_mat_window_init_clear), TEST_FUNCTION(nmod_poly_mat_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod_poly_mat/test/t-add.c000066400000000000000000000105421461254215100204010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_add, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; nmod_mat_t a, b, c, d; mp_limb_t mod, x; slong m, n, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); mod = n_randtest_prime(state, 0); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_mat_init(a, m, n, mod); nmod_mat_init(b, m, n, mod); nmod_mat_init(c, m, n, mod); nmod_mat_init(d, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_add(C, A, B); x = n_randint(state, mod); nmod_poly_mat_evaluate_nmod(a, A, x); nmod_poly_mat_evaluate_nmod(b, B, x); nmod_poly_mat_evaluate_nmod(d, C, x); nmod_mat_add(c, a, b); if (!nmod_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); nmod_mat_clear(a); nmod_mat_clear(b); nmod_mat_clear(c); nmod_mat_clear(d); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_add(C, A, B); nmod_poly_mat_add(A, A, B); if (!nmod_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_add(C, A, B); nmod_poly_mat_add(B, A, B); if (!nmod_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-concat_horizontal.c000066400000000000000000000035201461254215100233670ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_concat_horizontal, state) { nmod_poly_mat_t A, B, C; nmod_poly_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong c1, c2, r1; mp_limb_t mod; c1 = n_randint(state, 10); c2 = n_randint(state, 10); r1 = n_randint(state, 10); mod = n_randtest_prime(state, 0); nmod_poly_mat_init(A, r1, c1, mod); nmod_poly_mat_init(B, r1, c2, mod); nmod_poly_mat_init(C, r1, c1 + c2, mod); nmod_poly_mat_randtest(A, state, n_randint(state, 10) + 1); nmod_poly_mat_randtest(B, state, n_randint(state, 10) + 1); nmod_poly_mat_randtest(C, state, n_randint(state, 10) + 1); nmod_poly_mat_concat_horizontal(C, A, B); nmod_poly_mat_window_init(window1, C, 0, 0, r1, c1); nmod_poly_mat_window_init(window2, C, 0, c1, r1, c1 + c2); if (!(nmod_poly_mat_equal(window1, A) && nmod_poly_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); nmod_poly_mat_window_clear(window1); nmod_poly_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-concat_vertical.c000066400000000000000000000035141461254215100230120ustar00rootroot00000000000000/* Copyright (C) 2015 Anubhav Srivastava Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_concat_vertical, state) { nmod_poly_mat_t A, B, C; nmod_poly_mat_t window1, window2; slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong r1, r2, c1; mp_limb_t mod; r1 = n_randint(state, 10); r2 = n_randint(state, 10); c1 = n_randint(state, 10); mod = n_randtest_prime(state, 0); nmod_poly_mat_init(A, r1, c1, mod); nmod_poly_mat_init(B, r2, c1, mod); nmod_poly_mat_init(C, r1 + r2, c1, mod); nmod_poly_mat_randtest(A, state, n_randint(state, 10) + 1); nmod_poly_mat_randtest(B, state, n_randint(state, 10) + 1); nmod_poly_mat_randtest(C, state, n_randint(state, 10) + 1); nmod_poly_mat_concat_vertical(C, A, B); nmod_poly_mat_window_init(window1, C, 0, 0, r1, c1); nmod_poly_mat_window_init(window2, C, r1, 0, r1 + r2, c1); if (!(nmod_poly_mat_equal(window1, A) && nmod_poly_mat_equal(window2, B))) { flint_printf("FAIL: results not equal\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); nmod_poly_mat_window_clear(window1); nmod_poly_mat_window_clear(window2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-det.c000066400000000000000000000046511461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_det, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; nmod_poly_t a, b, ab, c; slong n, deg; mp_limb_t mod; float density; mod = n_randtest_prime(state, 0); n = n_randint(state, 10); deg = 1 + n_randint(state, 5); density = n_randint(state, 100) * 0.01; nmod_poly_mat_init(A, n, n, mod); nmod_poly_mat_init(B, n, n, mod); nmod_poly_mat_init(C, n, n, mod); nmod_poly_init(a, mod); nmod_poly_init(b, mod); nmod_poly_init(ab, mod); nmod_poly_init(c, mod); nmod_poly_mat_randtest_sparse(A, state, deg, density); nmod_poly_mat_randtest_sparse(B, state, deg, density); nmod_poly_mat_mul(C, A, B); nmod_poly_mat_det(a, A); nmod_poly_mat_det(b, B); nmod_poly_mat_det(c, C); nmod_poly_mul(ab, a, b); if (!nmod_poly_equal(c, ab)) { flint_printf("FAIL:\n"); flint_printf("determinants don't agree!\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("det(A):\n"); nmod_poly_print(a); flint_printf("\ndet(B):\n"); nmod_poly_print(b); flint_printf("\ndet(C):\n"); nmod_poly_print(c); flint_printf("\ndet(A)*det(B):\n"); nmod_poly_print(ab); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(ab); nmod_poly_clear(c); nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-det_interpolate.c000066400000000000000000000031561461254215100230360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_det_interpolate, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A; nmod_poly_t a, b; slong n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randint(state, 10); deg = 1 + n_randint(state, 5); nmod_poly_mat_init(A, n, n, mod); nmod_poly_init(a, mod); nmod_poly_init(b, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_det(a, A); nmod_poly_mat_det_interpolate(b, A); if (!nmod_poly_equal(a, b)) { flint_printf("FAIL:\n"); flint_printf("determinants don't agree!\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("det(A):\n"); nmod_poly_print(a); flint_printf("\ndet_interpolate(A):\n"); nmod_poly_print(b); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-get_set_coeff_mat.c000066400000000000000000000051001461254215100233000ustar00rootroot00000000000000/* Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_get_set_coeff_mat, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t pmat1; nmod_poly_mat_t pmat2; nmod_mat_t cmat1; nmod_mat_t cmat2; mp_limb_t mod; slong m, n, deg; int jx; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 3 + n_randint(state, 10); nmod_poly_mat_init(pmat1, m, n, mod); nmod_poly_mat_init(pmat2, m, n, mod); nmod_mat_init(cmat1, m, n, mod); nmod_mat_init(cmat2, m, n, mod); // test 1: set then get does not change values nmod_mat_randtest(cmat1, state); nmod_poly_mat_set_coeff_mat(pmat1, cmat1, deg-1); nmod_poly_mat_get_coeff_mat(cmat2, pmat1, deg-1); if (!nmod_mat_equal(cmat1, cmat2)) { flint_printf("FAIL (set then get):\n"); flint_printf("pmat1:\n"); nmod_poly_mat_print(pmat1, "x"); flint_printf("cmat1:\n"); nmod_mat_print(cmat1); flint_printf("cmat2:\n"); nmod_mat_print(cmat2); flint_printf("\n"); fflush(stdout); flint_abort(); } // test 2: copying via repeated get-set works nmod_poly_mat_randtest(pmat1, state, deg); for (jx = 0; jx < nmod_poly_mat_max_length(pmat1); jx++) { nmod_poly_mat_get_coeff_mat(cmat1, pmat1, jx); nmod_poly_mat_set_coeff_mat(pmat2, cmat1, jx); } if (!nmod_poly_mat_equal(pmat1, pmat2)) { flint_printf("FAIL (simulate copy):\n"); flint_printf("pmat1:\n"); nmod_poly_mat_print(pmat1, "x"); flint_printf("pmat2:\n"); nmod_poly_mat_print(pmat2, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(pmat1); nmod_poly_mat_clear(pmat2); nmod_mat_clear(cmat1); nmod_mat_clear(cmat2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-init_clear.c000066400000000000000000000020771461254215100217660ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_mat_t a; mp_limb_t mod; slong j, k; slong rows = n_randint(state, 100); slong cols = n_randint(state, 100); mod = n_randtest_prime(state, 0); nmod_poly_mat_init(a, rows, cols, mod); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) nmod_poly_zero(nmod_poly_mat_entry(a, j, k)); nmod_poly_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-inv.c000066400000000000000000000077731461254215100204610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_inv, state) { slong i; /* Test aliasing */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, Ainv; nmod_poly_t den1, den2; slong n, deg; float density; int ns1, ns2, result; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randint(state, 8); deg = 1 + n_randint(state, 5); density = n_randint(state, 100) * 0.01; nmod_poly_mat_init(A, n, n, mod); nmod_poly_mat_init(Ainv, n, n, mod); nmod_poly_init(den1, mod); nmod_poly_init(den2, mod); nmod_poly_mat_randtest_sparse(A, state, deg, density); ns1 = nmod_poly_mat_inv(Ainv, den1, A); ns2 = nmod_poly_mat_inv(A, den2, A); result = ns1 == ns2; if (result && ns1 != 0) { result = nmod_poly_equal(den1, den2) && nmod_poly_mat_equal(A, Ainv); } if (!result) { flint_printf("FAIL (aliasing)!\n"); nmod_poly_mat_print(A, "x"); flint_printf("\n"); nmod_poly_mat_print(Ainv, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(Ainv); nmod_poly_clear(den1); nmod_poly_clear(den2); } /* Check A^(-1) = A = 1 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, Ainv, B, Iden; nmod_poly_t den, det; slong n, deg; float density; int nonsingular; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randint(state, 10); deg = 1 + n_randint(state, 5); density = n_randint(state, 100) * 0.01; nmod_poly_mat_init(A, n, n, mod); nmod_poly_mat_init(Ainv, n, n, mod); nmod_poly_mat_init(B, n, n, mod); nmod_poly_mat_init(Iden, n, n, mod); nmod_poly_init(den, mod); nmod_poly_init(det, mod); nmod_poly_mat_randtest_sparse(A, state, deg, density); nonsingular = nmod_poly_mat_inv(Ainv, den, A); nmod_poly_mat_det_interpolate(det, A); if (n == 0) { if (nonsingular == 0 || !nmod_poly_is_one(den)) { flint_printf("FAIL: expected empty matrix to pass\n"); fflush(stdout); flint_abort(); } } else { if (!nmod_poly_equal(den, det)) { nmod_poly_neg(det, det); flint_printf("FAIL: den != det(A)\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_mul(B, Ainv, A); nmod_poly_mat_one(Iden); nmod_poly_mat_scalar_mul_nmod_poly(Iden, Iden, den); if (!nmod_poly_mat_equal(B, Iden)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("Ainv:\n"); nmod_poly_mat_print(Ainv, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("den:\n"); nmod_poly_print(den); fflush(stdout); flint_abort(); } } nmod_poly_clear(den); nmod_poly_clear(det); nmod_poly_mat_clear(A); nmod_poly_mat_clear(Ainv); nmod_poly_mat_clear(B); nmod_poly_mat_clear(Iden); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-mul.c000066400000000000000000000111321461254215100204420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_mul, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; nmod_mat_t a, b, c, d; mp_limb_t mod, x; slong m, n, k, deg; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, n, k, mod); nmod_poly_mat_init(C, m, k, mod); nmod_mat_init(a, m, n, mod); nmod_mat_init(b, n, k, mod); nmod_mat_init(c, m, k, mod); nmod_mat_init(d, m, k, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_mul(C, A, B); x = n_randint(state, mod); nmod_poly_mat_evaluate_nmod(a, A, x); nmod_poly_mat_evaluate_nmod(b, B, x); nmod_poly_mat_evaluate_nmod(d, C, x); nmod_mat_mul(c, a, b); if (!nmod_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); nmod_mat_clear(a); nmod_mat_clear(b); nmod_mat_clear(c); nmod_mat_clear(d); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, n, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_mul(C, A, B); nmod_poly_mat_mul(A, A, B); if (!nmod_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_mul(C, A, B); nmod_poly_mat_mul(B, A, B); if (!nmod_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-mul_KS.c000066400000000000000000000104741461254215100210470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_mul_KS, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C, D; slong m, n, k, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 15); n = n_randint(state, 15); k = n_randint(state, 15); deg = 1 + n_randint(state, 15); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, n, k, mod); nmod_poly_mat_init(C, m, k, mod); nmod_poly_mat_init(D, m, k, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_mul_classical(C, A, B); nmod_poly_mat_mul_KS(D, A, B); if (!nmod_poly_mat_equal(C, D)) { flint_printf("FAIL:\n"); flint_printf("products don't agree!\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("D:\n"); nmod_poly_mat_print(D, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); nmod_poly_mat_clear(D); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, n, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_mul_KS(C, A, B); nmod_poly_mat_mul_KS(A, A, B); if (!nmod_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_mul_KS(C, A, B); nmod_poly_mat_mul_KS(B, A, B); if (!nmod_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-mul_interpolate.c000066400000000000000000000122751461254215100230610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_mul_interpolate, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; nmod_mat_t a, b, c, d; mp_limb_t mod, x; slong m, n, k, deg; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); k = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, n, k, mod); nmod_poly_mat_init(C, m, k, mod); nmod_mat_init(a, m, n, mod); nmod_mat_init(b, n, k, mod); nmod_mat_init(c, m, k, mod); nmod_mat_init(d, m, k, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ if (nmod_poly_mat_max_length(A) + nmod_poly_mat_max_length(B) - 1 <= mod) { nmod_poly_mat_mul_interpolate(C, A, B); x = n_randint(state, mod); nmod_poly_mat_evaluate_nmod(a, A, x); nmod_poly_mat_evaluate_nmod(b, B, x); nmod_poly_mat_evaluate_nmod(d, C, x); nmod_mat_mul(c, a, b); if (!nmod_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); nmod_mat_clear(a); nmod_mat_clear(b); nmod_mat_clear(c); nmod_mat_clear(d); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, n, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ if (nmod_poly_mat_max_length(A) + nmod_poly_mat_max_length(B) - 1 <= mod) { nmod_poly_mat_mul_interpolate(C, A, B); nmod_poly_mat_mul_interpolate(A, A, B); if (!nmod_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ if (nmod_poly_mat_max_length(A) + nmod_poly_mat_max_length(B) - 1 <= mod) { nmod_poly_mat_mul_interpolate(C, A, B); nmod_poly_mat_mul_interpolate(B, A, B); if (!nmod_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-neg.c000066400000000000000000000053471461254215100204310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_neg, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B; nmod_mat_t a, b, c; mp_limb_t x, mod; slong m, n, deg; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_mat_init(a, m, n, mod); nmod_mat_init(b, m, n, mod); nmod_mat_init(c, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_neg(B, A); x = n_randint(state, mod); nmod_poly_mat_evaluate_nmod(a, A, x); nmod_poly_mat_evaluate_nmod(b, B, x); nmod_mat_neg(c, a); if (!nmod_mat_equal(b, c)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_mat_clear(a); nmod_mat_clear(b); nmod_mat_clear(c); } /* Check aliasing B and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_neg(B, A); nmod_poly_mat_neg(A, A); if (!nmod_poly_mat_equal(B, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-nullspace.c000066400000000000000000000041141461254215100216350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_nullspace, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, N, AN; slong n, m, deg, rank, nullity; float density; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 13); n = n_randint(state, 13); deg = 1 + n_randint(state, 5); density = n_randint(state, 100) * 0.01; nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(N, n, n, mod); nmod_poly_mat_init(AN, m, n, mod); nmod_poly_mat_randtest_sparse(A, state, deg, density); rank = nmod_poly_mat_rank(A); nullity = nmod_poly_mat_nullspace(N, A); if (nullity + rank != n) { flint_printf("FAIL: wrong nullity!\n"); flint_printf("rank = %wd\n", rank); flint_printf("nullity = %wd\n", nullity); nmod_poly_mat_print(A, "x"); flint_printf("\n"); nmod_poly_mat_print(N, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } if (nmod_poly_mat_rank(N) != nullity) { flint_printf("FAIL: wrong rank(N) != nullity!\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_mul(AN, A, N); if (!nmod_poly_mat_is_zero(AN)) { flint_printf("FAIL: A * N != 0\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(N); nmod_poly_mat_clear(AN); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-one.c000066400000000000000000000034351461254215100204350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_one, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { nmod_poly_mat_t A; slong m, n; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 10); n = n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_randtest(A, state, n_randint(state, 5)); nmod_poly_mat_one(A); if (!nmod_poly_mat_is_one(A)) { flint_printf("FAIL: expected matrix to be one\n"); fflush(stdout); flint_abort(); } if (m > 0 && n > 0) { m = n_randint(state, m); n = n_randint(state, n); if (m != n) nmod_poly_randtest_not_zero(nmod_poly_mat_entry(A, m, n), state, 5); else do { nmod_poly_randtest_not_zero(nmod_poly_mat_entry(A, m, n), state, 5); } while (nmod_poly_is_one(nmod_poly_mat_entry(A, m, n))); if (nmod_poly_mat_is_one(A)) { flint_printf("FAIL: expected matrix not to be one\n"); fflush(stdout); flint_abort(); } } nmod_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-pow.c000066400000000000000000000052561461254215100204640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_pow, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, j, exp, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 6); deg = 1 + n_randint(state, 6); exp = n_randint(state, 20); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, m, mod); nmod_poly_mat_init(C, m, m, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_pow(B, A, exp); nmod_poly_mat_one(C); for (j = 0; j < exp; j++) nmod_poly_mat_mul(C, C, A); if (!nmod_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("exp = %wd\n", exp); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } /* Check aliasing B and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B; slong m, exp, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 6); deg = 1 + n_randint(state, 6); exp = n_randint(state, 20); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, m, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_pow(B, A, exp); nmod_poly_mat_pow(A, A, exp); if (!nmod_poly_mat_equal(A, B)) { flint_printf("FAIL (aliasing)\n"); flint_printf("exp = %wd\n", exp); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-rank.c000066400000000000000000000037531461254215100206120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_rank, state) { slong i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A; nmod_mat_t Ax; mp_limb_t mod, x; slong j, m, n, deg, rank, zrank; float density; /* Don't pick a too small modulus, to avoid failure in the probabilistic rank computation (todo: test for small moduli) */ do { mod = n_randtest_prime(state, 0); } while (mod < 20); m = n_randint(state, 15); n = n_randint(state, 15); deg = 1 + n_randint(state, 5); density = n_randint(state, 100) * 0.01; nmod_poly_mat_init(A, m, n, mod); nmod_mat_init(Ax, m, n, mod); nmod_poly_mat_randtest_sparse(A, state, deg, density); /* Probabilistic rank computation */ zrank = 0; for (j = 0; j < 5; j++) { slong r; x = n_randint(state, mod); nmod_poly_mat_evaluate_nmod(Ax, A, x); r = nmod_mat_rank(Ax); zrank = FLINT_MAX(zrank, r); } rank = nmod_poly_mat_rank(A); if (rank != zrank) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("Computed rank: %wd (zrank = %wd)\n", rank, zrank); fflush(stdout); flint_abort(); } nmod_mat_clear(Ax); nmod_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-rref.c000066400000000000000000000107471461254215100206160ustar00rootroot00000000000000/* Copyright (C) 2010-2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "perm.h" #include "nmod_poly_mat.h" /* checks that the rref has the right form */ int check_rref(const nmod_poly_mat_t A, const nmod_poly_t den, slong rank) { slong i, j, k, prev_pivot; /* bottom should be zero */ for (i = rank; i < A->r; i++) for (j = 0; j < A->c; j++) if (!nmod_poly_is_zero(nmod_poly_mat_entry(A, i, j))) return 0; prev_pivot = -1; for (i = 0; i < rank; i++) { for (j = 0; j < A->c; j++) { if (!nmod_poly_is_zero(nmod_poly_mat_entry(A, i, j))) { /* pivot should have a higher column index than previous */ if (j <= prev_pivot) return 0; /* column should be 0 ... 0 1 0 ... 0 */ for (k = 0; k < rank; k++) { if (i == k && !nmod_poly_equal(nmod_poly_mat_entry(A, k, j), den)) return 0; if (i != k && !nmod_poly_is_zero(nmod_poly_mat_entry(A, k, j))) return 0; } prev_pivot = j; break; } } } return 1; } TEST_FUNCTION_START(nmod_poly_mat_rref, state) { slong iter; for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++) { nmod_poly_mat_t A, R, B, R2; nmod_poly_t den, c, den2; slong j, k, m, n, deg, rank1, rank2; slong *perm; float density; int equal; mp_limb_t p; m = n_randint(state, 10); n = n_randint(state, 10); deg = 1 + n_randint(state, 5); density = n_randint(state, 100) * 0.01; p = n_randtest_prime(state, 0); nmod_poly_mat_init(A, m, n, p); nmod_poly_mat_init(R, m, n, p); nmod_poly_mat_init(B, 2 * m, n, p); nmod_poly_mat_init(R2, 2 * m, n, p); nmod_poly_init(c, p); nmod_poly_init(den, p); nmod_poly_init(den2, p); perm = _perm_init(2 * m); nmod_poly_mat_randtest_sparse(A, state, deg, density); rank1 = nmod_poly_mat_rref(R, den, A); check_rref(R, den, rank1); /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { nmod_poly_randtest_not_zero(c, state, deg); for (k = 0; k < n; k++) nmod_poly_mul(nmod_poly_mat_entry(B, perm[j], k), nmod_poly_mat_entry(A, j, k), c); } for (j = 0; j < m; j++) { nmod_poly_randtest_not_zero(c, state, deg); for (k = 0; k < n; k++) nmod_poly_mul(nmod_poly_mat_entry(B, perm[m + j], k), nmod_poly_mat_entry(R, j, k), c); } rank2 = nmod_poly_mat_rref(R2, den2, B); equal = (rank1 == rank2); if (equal) { nmod_poly_mat_scalar_mul_nmod_poly(R, R, den2); nmod_poly_mat_scalar_mul_nmod_poly(R2, R2, den); for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) equal = equal && nmod_poly_equal(nmod_poly_mat_entry(R, j, k), nmod_poly_mat_entry(R2, j, k)); for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) equal = equal && nmod_poly_is_zero(nmod_poly_mat_entry(R2, j, k)); } if (!equal) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); nmod_poly_mat_print(A, "x"); flint_printf("\n\n"); nmod_poly_mat_print(R, "x"); flint_printf("\n\n"); nmod_poly_mat_print(R2, "x"); flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_clear(c); nmod_poly_clear(den); nmod_poly_clear(den2); _perm_clear(perm); nmod_poly_mat_clear(A); nmod_poly_mat_clear(R); nmod_poly_mat_clear(B); nmod_poly_mat_clear(R2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-set_nmod_mat.c000066400000000000000000000035731461254215100223300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_set_nmod_mat, state) { slong i; for (i = 0; i < 400 * flint_test_multiplier(); i++) { nmod_poly_mat_t pmat; nmod_mat_t cmat; mp_limb_t mod; slong m, n, deg; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(pmat, m, n, mod); nmod_mat_init(cmat, m, n, mod); nmod_poly_mat_set_nmod_mat(pmat, cmat); if (! nmod_poly_mat_equal_nmod_mat(pmat, cmat)) { flint_printf("FAIL:\n"); flint_printf("pmat:\n"); nmod_poly_mat_print(pmat, "x"); flint_printf("cmat:\n"); nmod_mat_print(cmat); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_randtest(pmat, state, deg); nmod_poly_mat_set_nmod_mat(pmat, cmat); if (! nmod_poly_mat_equal_nmod_mat(pmat, cmat)) { flint_printf("FAIL:\n"); flint_printf("pmat:\n"); nmod_poly_mat_print(pmat, "x"); flint_printf("cmat:\n"); nmod_mat_print(cmat); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(pmat); nmod_mat_clear(cmat); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-set_trunc.c000066400000000000000000000053141461254215100216600ustar00rootroot00000000000000/* Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" void test_with_dims(ulong m, ulong n, flint_rand_t state) { int result; nmod_poly_mat_t a, b, c; ulong p; slong len; p = n_randtest_prime(state, 0); nmod_poly_mat_init(a, m, n, p); nmod_poly_mat_init(b, m, n, p); nmod_poly_mat_init(c, m, n, p); nmod_poly_mat_randtest(a, state, n_randint(state, 100)); nmod_poly_mat_randtest(b, state, n_randint(state, 100)); len = n_randint(state, 50); nmod_poly_mat_set_trunc(b, a, len); nmod_poly_t poly; nmod_poly_init(poly, p); for (int i=0; i. */ #include "test_helpers.h" #include "nmod_poly_mat.h" /* Check a << shift >> shift == a */ void test_with_dimensions1(ulong rdim, ulong cdim, flint_rand_t state) { int result; nmod_poly_mat_t a, b; mp_limb_t n = n_randtest_not_zero(state); slong shift = n_randint(state, 100); nmod_poly_mat_init(a, rdim, cdim, n); nmod_poly_mat_init(b, rdim, cdim, n); nmod_poly_mat_randtest(a, state, n_randint(state, 100)); nmod_poly_mat_shift_left(b, a, shift); nmod_poly_mat_shift_right(b, b, shift); result = (nmod_poly_mat_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("shift = %wd, rdim = %ld, cdim = %ld, n = %wu\n", shift, rdim, cdim, n); nmod_poly_mat_print(a, "X"), flint_printf("\n\n"); nmod_poly_mat_print(b, "X"), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(a); nmod_poly_mat_clear(b); } /* Check a << shift >> shift == a aliasing the other way */ void test_with_dimensions2(ulong rdim, ulong cdim, flint_rand_t state) { int result; nmod_poly_mat_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong shift = n_randint(state, 100); nmod_poly_mat_init(a, rdim, cdim, n); nmod_poly_mat_init(b, rdim, cdim, n); nmod_poly_mat_init(c, rdim, cdim, n); nmod_poly_mat_randtest(c, state, n_randint(state, 100)); nmod_poly_mat_set(a, c); nmod_poly_mat_shift_left(c, c, shift); nmod_poly_mat_shift_right(b, c, shift); result = (nmod_poly_mat_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("shift = %wd, rdim = %ld, cdim = %ld, n = %wu\n", shift, rdim, cdim, n); nmod_poly_mat_print(a, "X"), flint_printf("\n\n"); nmod_poly_mat_print(b, "X"), flint_printf("\n\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(a); nmod_poly_mat_clear(b); nmod_poly_mat_clear(c); } TEST_FUNCTION_START(nmod_poly_mat_shift_left_right, state) { int i; for (i = 0; i < 100 * flint_test_multiplier(); i++) { test_with_dimensions1(2, 5, state); test_with_dimensions1(3, 3, state); test_with_dimensions1(5, 2, state); } for (i = 0; i < 100 * flint_test_multiplier(); i++) { test_with_dimensions2(2, 5, state); test_with_dimensions2(3, 3, state); test_with_dimensions2(5, 2, state); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-solve_fflu.c000066400000000000000000000067111461254215100220200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_solve_fflu, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, X, B, AX, Bden; nmod_poly_t den, det; slong n, m, deg; float density; int solved; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randint(state, 15); m = n_randint(state, 5); deg = 1 + n_randint(state, 5); density = n_randint(state, 100) * 0.01; nmod_poly_mat_init(A, n, n, mod); nmod_poly_mat_init(B, n, m, mod); nmod_poly_mat_init(X, n, m, mod); nmod_poly_mat_init(AX, n, m, mod); nmod_poly_mat_init(Bden, n, m, mod); nmod_poly_init(den, mod); nmod_poly_init(det, mod); nmod_poly_mat_randtest_sparse(A, state, deg, density); nmod_poly_mat_randtest_sparse(B, state, deg, density); solved = nmod_poly_mat_solve_fflu(X, den, A, B); nmod_poly_mat_det_interpolate(det, A); if (m == 0 || n == 0) { if (solved == 0) { flint_printf("FAIL: expected empty system to pass\n"); fflush(stdout); flint_abort(); } } else { if (!nmod_poly_equal(den, det)) { nmod_poly_neg(det, det); flint_printf("FAIL: den != +/- det(A)\n"); flint_printf("den:\n"); nmod_poly_print(den); flint_printf("\n\n"); flint_printf("det:\n"); nmod_poly_print(det); flint_printf("\n\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("X:\n"); nmod_poly_mat_print(X, "x"); fflush(stdout); flint_abort(); } } if (solved != !nmod_poly_is_zero(den)) { flint_printf("FAIL: return value does not match denominator\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_mul(AX, A, X); nmod_poly_mat_scalar_mul_nmod_poly(Bden, B, den); if (!nmod_poly_mat_equal(AX, Bden)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("X:\n"); nmod_poly_mat_print(X, "x"); flint_printf("AX:\n"); nmod_poly_mat_print(AX, "x"); flint_printf("Bden:\n"); nmod_poly_mat_print(Bden, "x"); fflush(stdout); flint_abort(); } nmod_poly_clear(den); nmod_poly_clear(det); nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(X); nmod_poly_mat_clear(AX); nmod_poly_mat_clear(Bden); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-sqr.c000066400000000000000000000054661461254215100204670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_sqr, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, C; nmod_mat_t a, c, d; mp_limb_t x, mod; slong m, deg; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(C, m, m, mod); nmod_mat_init(a, m, m, mod); nmod_mat_init(c, m, m, mod); nmod_mat_init(d, m, m, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_sqr(C, A); x = n_randint(state, 0); nmod_poly_mat_evaluate_nmod(a, A, x); nmod_poly_mat_evaluate_nmod(d, C, x); nmod_mat_mul(c, a, a); if (!nmod_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(C); nmod_mat_clear(a); nmod_mat_clear(c); nmod_mat_clear(d); } /* Check aliasing B and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B; slong m, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, m, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); /* noise in output */ nmod_poly_mat_sqr(B, A); nmod_poly_mat_sqr(A, A); if (!nmod_poly_mat_equal(B, A)) { flint_printf("FAIL (aliasing):\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-sqr_KS.c000066400000000000000000000052611461254215100210550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_sqr_KS, state) { slong i; for (i = 0; i < 200 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); n = n_randint(state, 15); deg = 1 + n_randint(state, 15); nmod_poly_mat_init(A, n, n, mod); nmod_poly_mat_init(B, n, n, mod); nmod_poly_mat_init(C, n, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ nmod_poly_mat_sqr_classical(B, A); nmod_poly_mat_sqr_KS(C, A); if (!nmod_poly_mat_equal(B, C)) { flint_printf("FAIL:\n"); flint_printf("products don't agree!\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } /* Check aliasing B and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B; slong m, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, m, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); /* noise in output */ nmod_poly_mat_sqr_KS(B, A); nmod_poly_mat_sqr_KS(A, A); if (!nmod_poly_mat_equal(B, A)) { flint_printf("FAIL (aliasing):\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-sqr_interpolate.c000066400000000000000000000061621461254215100230670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_sqr_interpolate, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, C; nmod_mat_t a, c, d; mp_limb_t x, mod; slong m, deg; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(C, m, m, mod); nmod_mat_init(a, m, m, mod); nmod_mat_init(c, m, m, mod); nmod_mat_init(d, m, m, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(C, state, deg); /* noise in output */ if (2 * nmod_poly_mat_max_length(A) - 1 <= mod) { nmod_poly_mat_sqr_interpolate(C, A); x = n_randint(state, 0); nmod_poly_mat_evaluate_nmod(a, A, x); nmod_poly_mat_evaluate_nmod(d, C, x); nmod_mat_mul(c, a, a); if (!nmod_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_poly_mat_clear(A); nmod_poly_mat_clear(C); nmod_mat_clear(a); nmod_mat_clear(c); nmod_mat_clear(d); } /* Check aliasing B and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B; slong m, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, m, mod); nmod_poly_mat_init(B, m, m, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); /* noise in output */ if (2 * nmod_poly_mat_max_length(A) - 1 <= mod) { nmod_poly_mat_sqr_interpolate(B, A); nmod_poly_mat_sqr_interpolate(A, A); if (!nmod_poly_mat_equal(B, A)) { flint_printf("FAIL (aliasing):\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-sub.c000066400000000000000000000105421461254215100204420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_sub, state) { slong i; /* Check evaluation homomorphism */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; nmod_mat_t a, b, c, d; mp_limb_t mod, x; slong m, n, deg; m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); mod = n_randtest_prime(state, 0); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_mat_init(a, m, n, mod); nmod_mat_init(b, m, n, mod); nmod_mat_init(c, m, n, mod); nmod_mat_init(d, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_sub(C, A, B); x = n_randint(state, mod); nmod_poly_mat_evaluate_nmod(a, A, x); nmod_poly_mat_evaluate_nmod(b, B, x); nmod_poly_mat_evaluate_nmod(d, C, x); nmod_mat_sub(c, a, b); if (!nmod_mat_equal(c, d)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); nmod_mat_clear(a); nmod_mat_clear(b); nmod_mat_clear(c); nmod_mat_clear(d); } /* Check aliasing C and A */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_sub(C, A, B); nmod_poly_mat_sub(A, A, B); if (!nmod_poly_mat_equal(C, A)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } /* Check aliasing C and B */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, C; slong m, n, deg; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); deg = 1 + n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, m, n, mod); nmod_poly_mat_init(C, m, n, mod); nmod_poly_mat_randtest(A, state, deg); nmod_poly_mat_randtest(B, state, deg); nmod_poly_mat_sub(C, A, B); nmod_poly_mat_sub(B, A, B); if (!nmod_poly_mat_equal(C, B)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); nmod_poly_mat_print(A, "x"); flint_printf("B:\n"); nmod_poly_mat_print(B, "x"); flint_printf("C:\n"); nmod_poly_mat_print(C, "x"); flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-trace.c000066400000000000000000000042411461254215100207460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_trace, state) { slong i; /* Test trace(AB) = trace(BA) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_mat_t A, B, AB, BA; nmod_poly_t trab, trba; mp_limb_t mod; slong m, n; mod = n_randtest_prime(state, 0); m = n_randint(state, 10); n = n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_init(B, n, m, mod); nmod_poly_mat_init(AB, m, m, mod); nmod_poly_mat_init(BA, n, n, mod); nmod_poly_init(trab, mod); nmod_poly_init(trba, mod); nmod_poly_mat_randtest(A, state, 1 + n_randint(state, 10)); nmod_poly_mat_randtest(B, state, 1 + n_randint(state, 10)); nmod_poly_mat_mul(AB, A, B); nmod_poly_mat_mul(BA, B, A); nmod_poly_mat_trace(trab, AB); nmod_poly_mat_trace(trba, BA); if (!nmod_poly_equal(trab, trba)) { flint_printf("FAIL:\n"); nmod_poly_mat_print(A, "x"), flint_printf("\n"); nmod_poly_mat_print(B, "x"), flint_printf("\n"); nmod_poly_mat_print(AB, "x"), flint_printf("\n"); nmod_poly_mat_print(BA, "x"), flint_printf("\n"); flint_printf("tr(AB): "), nmod_poly_print(trab), flint_printf("\n"); flint_printf("tr(BA): "), nmod_poly_print(trba), flint_printf("\n"); fflush(stdout); flint_abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(AB); nmod_poly_mat_clear(BA); nmod_poly_clear(trab); nmod_poly_clear(trba); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-window_init_clear.c000066400000000000000000000030511461254215100233460ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2014 Abhinav Baid Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_window_init_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_mat_t a, w; mp_limb_t mod; slong j, k, r1, r2, c1, c2; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); mod = n_randtest_prime(state, 0); nmod_poly_mat_init(a, rows, cols, mod); nmod_poly_mat_randtest(a, state, n_randint(state, 10) + 1); r2 = n_randint(state, rows + 1); c2 = n_randint(state, cols + 1); if (r2) r1 = n_randint(state, r2); else r1 = 0; if (c2) c1 = n_randint(state, c2); else c1 = 0; nmod_poly_mat_window_init(w, a, r1, c1, r2, c2); for (j = 0; j < r2 - r1; j++) for (k = 0; k < c2 - c1; k++) nmod_poly_zero(nmod_poly_mat_entry(w, j, k)); nmod_poly_mat_window_clear(w); nmod_poly_mat_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/test/t-zero.c000066400000000000000000000030511461254215100206250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "nmod_poly_mat.h" TEST_FUNCTION_START(nmod_poly_mat_zero, state) { int iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { nmod_poly_mat_t A; slong m, n; mp_limb_t mod; mod = n_randtest_prime(state, 0); m = n_randint(state, 10); n = n_randint(state, 10); nmod_poly_mat_init(A, m, n, mod); nmod_poly_mat_randtest(A, state, n_randint(state, 5)); nmod_poly_mat_zero(A); if (!nmod_poly_mat_is_zero(A)) { flint_printf("FAIL: expected matrix to be zero\n"); fflush(stdout); flint_abort(); } if (m > 0 && n > 0) { m = n_randint(state, m); n = n_randint(state, n); nmod_poly_randtest_not_zero(nmod_poly_mat_entry(A, m, n), state, 5); if (nmod_poly_mat_is_zero(A)) { flint_printf("FAIL: expected matrix not to be zero\n"); fflush(stdout); flint_abort(); } } nmod_poly_mat_clear(A); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_poly_mat/trace.c000066400000000000000000000014471461254215100175330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_trace(nmod_poly_t trace, const nmod_poly_mat_t mat) { slong i, n = nmod_poly_mat_nrows(mat); if (n == 0) nmod_poly_zero(trace); else { nmod_poly_set(trace, nmod_poly_mat_entry(mat, 0, 0)); for (i = 1; i < n; i++) nmod_poly_add(trace, trace, nmod_poly_mat_entry(mat, i, i)); } } flint-3.1.3/src/nmod_poly_mat/window.c000066400000000000000000000021321461254215100177340ustar00rootroot00000000000000/* Copyright (C) 2015 Elena Sergeicheva This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_poly_mat.h" void nmod_poly_mat_window_init(nmod_poly_mat_t window, const nmod_poly_mat_t mat, slong r1, slong c1, slong r2, slong c2) { slong i; window->entries = NULL; if (r2 > r1) window->rows = flint_malloc((r2 - r1) * sizeof(nmod_poly_t)); else window->rows = NULL; if (mat->c > 0) for (i = 0; i < r2 - r1; i++) window->rows[i] = mat->rows[r1 + i] + c1; else for (i = 0; i < r2 - r1; i++) window->rows[i] = NULL; window->r = r2 - r1; window->c = c2 - c1; window->modulus = mat->modulus; } void nmod_poly_mat_window_clear(nmod_poly_mat_t window) { if (window->r != 0) flint_free(window->rows); } flint-3.1.3/src/nmod_poly_mat/zero.c000066400000000000000000000012011461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_zero(nmod_poly_mat_t A) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_zero(nmod_poly_mat_entry(A, i, j)); } flint-3.1.3/src/nmod_types.h000066400000000000000000000033441461254215100157600ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_TYPES_H #define NMOD_TYPES_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif typedef struct { mp_limb_t * entries; slong r; slong c; mp_limb_t ** rows; nmod_t mod; } nmod_mat_struct; typedef nmod_mat_struct nmod_mat_t[1]; typedef struct { mp_ptr coeffs; slong alloc; slong length; nmod_t mod; } nmod_poly_struct; typedef nmod_poly_struct nmod_poly_t[1]; typedef struct { nmod_poly_struct * p; slong *exp; slong num; slong alloc; } nmod_poly_factor_struct; typedef nmod_poly_factor_struct nmod_poly_factor_t[1]; typedef struct { nmod_poly_struct * entries; slong r; slong c; nmod_poly_struct ** rows; mp_limb_t modulus; } nmod_poly_mat_struct; typedef nmod_poly_mat_struct nmod_poly_mat_t[1]; typedef struct { mp_limb_t * coeffs; ulong * exps; slong length; flint_bitcnt_t bits; /* number of bits per exponent */ slong coeffs_alloc; /* abs size in mp_limb_t units */ slong exps_alloc; /* abs size in ulong units */ } nmod_mpoly_struct; typedef nmod_mpoly_struct nmod_mpoly_t[1]; typedef struct { mp_limb_t constant; nmod_mpoly_struct * poly; fmpz * exp; slong num; slong alloc; } nmod_mpoly_factor_struct; typedef nmod_mpoly_factor_struct nmod_mpoly_factor_t[1]; #ifdef __cplusplus } #endif #endif /* NMOD_TYPES_H */ flint-3.1.3/src/nmod_vec.h000066400000000000000000000202201461254215100153610ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef NMOD_VEC_H #define NMOD_VEC_H #ifdef NMOD_VEC_INLINES_C #define NMOD_VEC_INLINE #else #define NMOD_VEC_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif #define NMOD_VEC_NORM(vec, i) \ do { \ while ((i) && vec[(i) - 1] == UWORD(0)) \ (i)--; \ } while (0) NMOD_VEC_INLINE mp_ptr _nmod_vec_init(slong len) { return (mp_ptr) flint_malloc(len * sizeof(mp_limb_t)); } NMOD_VEC_INLINE void _nmod_vec_clear(mp_ptr vec) { flint_free(vec); } void _nmod_vec_randtest(mp_ptr vec, flint_rand_t state, slong len, nmod_t mod); NMOD_VEC_INLINE void _nmod_vec_zero(mp_ptr vec, slong len) { flint_mpn_zero(vec, len); } flint_bitcnt_t _nmod_vec_max_bits(mp_srcptr vec, slong len); NMOD_VEC_INLINE void _nmod_vec_set(mp_ptr res, mp_srcptr vec, slong len) { flint_mpn_copyi(res, vec, len); } NMOD_VEC_INLINE void _nmod_vec_swap(mp_ptr a, mp_ptr b, slong length) { slong i; for (i = 0; i < length; i++) { mp_limb_t t = a[i]; a[i] = b[i]; b[i] = t; } } NMOD_VEC_INLINE int _nmod_vec_equal(mp_srcptr vec, mp_srcptr vec2, slong len) { slong i; for (i = 0; i < len; i++) if (vec[i] != vec2[i]) return 0; return 1; } NMOD_VEC_INLINE int _nmod_vec_is_zero(mp_srcptr vec, slong len) { slong i; for (i = 0; i < len; i++) if (vec[i] != 0) return 0; return 1; } void _nmod_vec_reduce(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod); void _nmod_vec_add(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod); void _nmod_vec_sub(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod); void _nmod_vec_neg(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod); void _nmod_vec_scalar_mul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod); void _nmod_vec_scalar_mul_nmod_shoup(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod); void _nmod_vec_scalar_addmul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod); int _nmod_vec_dot_bound_limbs(slong len, nmod_t mod); #define NMOD_VEC_DOT(res, i, len, expr1, expr2, mod, nlimbs) \ do \ { \ mp_limb_t s0, s1, s2, t0, t1; \ s0 = s1 = s2 = UWORD(0); \ switch (nlimbs) \ { \ case 1: \ for (i = 0; i < (len); i++) \ { \ s0 += (expr1) * (expr2); \ } \ NMOD_RED(s0, s0, mod); \ break; \ case 2: \ if (mod.n <= (UWORD(1) << (FLINT_BITS / 2))) \ { \ for (i = 0; i < (len); i++) \ { \ t0 = (expr1) * (expr2); \ add_ssaaaa(s1, s0, s1, s0, 0, t0); \ } \ } \ else if ((len) < 8) \ { \ for (i = 0; i < len; i++) \ { \ umul_ppmm(t1, t0, (expr1), (expr2)); \ add_ssaaaa(s1, s0, s1, s0, t1, t0); \ } \ } \ else \ { \ mp_limb_t v0, v1, u0, u1; \ i = 0; \ if ((len) & 1) \ umul_ppmm(v1, v0, (expr1), (expr2)); \ else \ v0 = v1 = 0; \ for (i = (len) & 1; i < (len); i++) \ { \ umul_ppmm(t1, t0, (expr1), (expr2)); \ add_ssaaaa(s1, s0, s1, s0, t1, t0); \ i++; \ umul_ppmm(u1, u0, (expr1), (expr2)); \ add_ssaaaa(v1, v0, v1, v0, u1, u0); \ } \ add_ssaaaa(s1, s0, s1, s0, v1, v0); \ } \ NMOD2_RED2(s0, s1, s0, mod); \ break; \ default: \ for (i = 0; i < (len); i++) \ { \ umul_ppmm(t1, t0, (expr1), (expr2)); \ add_sssaaaaaa(s2, s1, s0, s2, s1, s0, 0, t1, t0); \ } \ NMOD_RED(s2, s2, mod); \ NMOD_RED3(s0, s2, s1, s0, mod); \ break; \ } \ res = s0; \ } while (0); mp_limb_t _nmod_vec_dot(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs); mp_limb_t _nmod_vec_dot_rev(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs); mp_limb_t _nmod_vec_dot_ptr(mp_srcptr vec1, const mp_ptr * vec2, slong offset, slong len, nmod_t mod, int nlimbs); /* some IO functions */ #ifdef FLINT_HAVE_FILE int _nmod_vec_fprint_pretty(FILE * file, mp_srcptr vec, slong len, nmod_t mod); int _nmod_vec_fprint(FILE * f, mp_srcptr vec, slong len, nmod_t mod); #endif void _nmod_vec_print_pretty(mp_srcptr vec, slong len, nmod_t mod); int _nmod_vec_print(mp_srcptr vec, slong len, nmod_t mod); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/nmod_vec/000077500000000000000000000000001461254215100152145ustar00rootroot00000000000000flint-3.1.3/src/nmod_vec/add.c000066400000000000000000000013701461254215100161110ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" void _nmod_vec_add(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod) { slong i; if (mod.norm) { for (i = 0 ; i < len; i++) res[i] = _nmod_add(vec1[i], vec2[i], mod); } else { for (i = 0 ; i < len; i++) res[i] = nmod_add(vec1[i], vec2[i], mod); } } flint-3.1.3/src/nmod_vec/discrete_log_pohlig_hellman.c000066400000000000000000000220251461254215100230660ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "nmod.h" #include "nmod_vec.h" #include "fmpz.h" static int nmod_discrete_log_pohlig_hellman_table_entry_struct_cmp( const nmod_discrete_log_pohlig_hellman_table_entry_struct * lhs, const nmod_discrete_log_pohlig_hellman_table_entry_struct * rhs) { return (lhs->gammapow < rhs->gammapow) ? -1 : (lhs->gammapow > rhs->gammapow); } void nmod_discrete_log_pohlig_hellman_init(nmod_discrete_log_pohlig_hellman_t L) { L->num_factors = 0; L->entries = NULL; nmod_init(&L->mod, 2); } void nmod_discrete_log_pohlig_hellman_clear(nmod_discrete_log_pohlig_hellman_t L) { slong i; nmod_discrete_log_pohlig_hellman_entry_struct * Li; for (i = 0; i < L->num_factors; i++) { Li = L->entries + i; flint_free(Li->table); } if (L->entries) { flint_free(L->entries); } } static slong _pow_ui_cost(ulong pow) { slong cost = -2; while (pow != 0) { cost += 1 + (pow&1); pow = pow/2; } return FLINT_MAX(cost, 0); } /* Assume that p is prime, don't check. Return an estimate on the number of multiplications need for one run. */ double nmod_discrete_log_pohlig_hellman_precompute_prime(nmod_discrete_log_pohlig_hellman_t L, mp_limb_t p) { slong i; ulong c; nmod_discrete_log_pohlig_hellman_entry_struct * Li; n_factor_t factors; double total_cost; /* just free everything and allocate again for now */ nmod_discrete_log_pohlig_hellman_clear(L); n_factor_init(&factors); n_factor(&factors, p - 1, 1); nmod_init(&L->mod, p); L->entries = NULL; L->num_factors = factors.num; if (L->num_factors > 0) { L->entries = (nmod_discrete_log_pohlig_hellman_entry_struct*) flint_malloc( L->num_factors*sizeof(nmod_discrete_log_pohlig_hellman_entry_struct)); } for (i = 0; i < L->num_factors; i++) { fmpz_t pipow, pm1, temp, recp; Li = L->entries + i; Li->exp = factors.exp[i]; Li->prime = factors.p[i]; fmpz_init(recp); fmpz_init(temp); fmpz_init_set_ui(pipow, Li->prime); fmpz_pow_ui(pipow, pipow, Li->exp); fmpz_init_set_ui(pm1, p - 1); fmpz_divexact(recp, pm1, pipow); fmpz_invmod(temp, recp, pipow); fmpz_mul(temp, temp, recp); Li->idem = fmpz_fdiv_ui(temp, p - 1); Li->co = fmpz_get_ui(recp); Li->startinge = fmpz_get_ui(pipow)/Li->prime; fmpz_clear(pipow); fmpz_clear(pm1); fmpz_clear(temp); fmpz_clear(recp); } /* alpha will be a primitive root */ L->alpha = 0; try_alpha: L->alpha++; if (L->alpha >= p) { /* L is corrupted */ /* factors appears to need no cleanup */ flint_throw(FLINT_ERROR, "Exception in nmod_discrete_log_pohlig" "_hellman_precompute_prime: Could not find primitive root."); } for (i = 0; i < L->num_factors; i++) { Li = L->entries + i; Li->gamma = nmod_pow_ui(L->alpha, (p - 1) / Li->prime, L->mod); if (Li->gamma == 1) { goto try_alpha; } } L->alphainv = nmod_inv(L->alpha, L->mod); for (i = 0; i < L->num_factors; i++) { Li = L->entries + i; Li->gammainv = nmod_inv(Li->gamma, L->mod); Li->startingbeta = nmod_pow_ui(L->alphainv, Li->co, L->mod); Li->dbound = ceil(sqrt((double) Li->prime)); Li->cbound = (Li->prime + Li->dbound - 1)/Li->dbound; while (Li->cbound > 100) { Li->dbound *= 2; Li->cbound = (Li->prime + Li->dbound - 1)/Li->dbound; } FLINT_ASSERT(Li->dbound > 0); FLINT_ASSERT(Li->cbound > 0); Li->table = (nmod_discrete_log_pohlig_hellman_table_entry_struct *) flint_malloc( Li->cbound*sizeof(nmod_discrete_log_pohlig_hellman_table_entry_struct)); for (c = 0; c < Li->cbound; c++) { Li->table[c].cm = c*Li->dbound; Li->table[c].gammapow = nmod_pow_ui(Li->gamma, Li->table[c].cm, L->mod); } qsort(Li->table, Li->cbound, sizeof(nmod_discrete_log_pohlig_hellman_table_entry_struct), (int(*)(const void*, const void*)) nmod_discrete_log_pohlig_hellman_table_entry_struct_cmp); for (c = 1; c < Li->cbound; c++) { FLINT_ASSERT(Li->table[c - 1].gammapow < Li->table[c].gammapow); FLINT_ASSERT(Li->table[c].gammapow == nmod_pow_ui(Li->gamma, Li->table[c].cm, L->mod)); } } total_cost = 0; for (i = 0; i < L->num_factors; i++) { double this_cost = 0; ulong e; slong j; Li = L->entries + i; this_cost += _pow_ui_cost(Li->co); e = Li->startinge; j = 0; do { this_cost += _pow_ui_cost(e); this_cost += Li->dbound*(1 + log(Li->cbound)); /* bsgs search */ this_cost += 2*log(Li->prime); /* some power < Li->prime */ e = e / Li->prime; } while (++j < Li->exp); total_cost += this_cost; } return total_cost; } /* return x such that y = alpha^x mod p, alpha is the p.r. L->alpha*/ ulong nmod_discrete_log_pohlig_hellman_run(const nmod_discrete_log_pohlig_hellman_t L, mp_limb_t y) { slong i, j; ulong x, q, r, e, x0 = 0, x1 = 0, x2 = 0, pp0, pp1, acc, g, pipow; ulong lo, mid, hi, d; mp_limb_t beta, z, w; nmod_discrete_log_pohlig_hellman_entry_struct * Li; FLINT_ASSERT(y != 0); FLINT_ASSERT(y < L->mod.n); i = 0; if (i < L->num_factors && L->entries[i].prime == 2) { Li = L->entries + i; FLINT_ASSERT(Li->prime == 2); z = nmod_pow_ui(y, Li->co, L->mod); beta = Li->startingbeta; e = Li->startinge; j = 0; pipow = 1; /* Li->prime^j */ acc = 0; do { w = nmod_pow_ui(z, e, L->mod); /* solve Li->gamma ^ g == w mod p */ if (w == 1) { g = 0; } else { if (w != Li->gamma) { goto cleanup_and_throw; } g = 1; z = nmod_mul(z, beta, L->mod); } beta = nmod_mul(beta, beta, L->mod); acc += g*pipow; pipow = pipow*2; e = e / 2; } while (++j < Li->exp); umul_ppmm(pp1, pp0, acc, Li->idem); add_sssaaaaaa(x2, x1, x0, x2, x1, x0, WORD(0), pp1, pp0); i = 1; } for (; i < L->num_factors; i++) { Li = L->entries + i; z = nmod_pow_ui(y, Li->co, L->mod); beta = Li->startingbeta; e = Li->startinge; j = 0; pipow = 1; /* Li->prime^j */ acc = 0; do { w = nmod_pow_ui(z, e, L->mod); /* solve Li->gamma ^ g == w mod p */ d = 0; while (1) { lo = 0; hi = Li->cbound; while (hi - lo > 4) { mid = lo + (hi - lo)/2; if (Li->table[mid].gammapow == w) { g = Li->table[mid].cm + d; goto found_g; } if (Li->table[mid].gammapow > w) hi = mid; else lo = mid; } while (lo < hi) { if (Li->table[lo].gammapow == w) { g = Li->table[lo].cm + d; goto found_g; } lo++; } w = nmod_mul(w, Li->gammainv, L->mod); d++; if (d >= Li->dbound) { goto cleanup_and_throw; } } found_g: FLINT_ASSERT(g < Li->prime); z = nmod_mul(z, nmod_pow_ui(beta, g, L->mod), L->mod); beta = nmod_pow_ui(beta, Li->prime, L->mod); acc += g*pipow; pipow = pipow*Li->prime; e = e / Li->prime; } while (++j < Li->exp); umul_ppmm(pp1, pp0, acc, Li->idem); add_sssaaaaaa(x2, x1, x0, x2, x1, x0, WORD(0), pp1, pp0); } udiv_qrnnd(q, r, x2, x1, L->mod.n - 1); udiv_qrnnd(q, x, r, x0, L->mod.n - 1); return x; cleanup_and_throw: /* nothing currently to cleanup */ flint_throw(FLINT_ERROR, "Exception in nmod_discrete_log_pohlig" "_hellman_run: Could not find log."); return 0; } flint-3.1.3/src/nmod_vec/dot.c000066400000000000000000000035161461254215100161530ustar00rootroot00000000000000/* Copyright (C) 2011, 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" mp_limb_t _nmod_vec_dot(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs) { mp_limb_t res; slong i; NMOD_VEC_DOT(res, i, len, vec1[i], vec2[i], mod, nlimbs); return res; } int _nmod_vec_dot_bound_limbs(slong len, nmod_t mod) { mp_limb_t t2, t1, t0, u1, u0; umul_ppmm(t1, t0, mod.n - 1, mod.n - 1); umul_ppmm(t2, t1, t1, len); umul_ppmm(u1, u0, t0, len); add_sssaaaaaa(t2, t1, t0, t2, t1, UWORD(0), UWORD(0), u1, u0); if (t2 != 0) return 3; if (t1 != 0) return 2; return (t0 != 0); } mp_limb_t _nmod_vec_dot_ptr(mp_srcptr vec1, const mp_ptr * vec2, slong offset, slong len, nmod_t mod, int nlimbs) { mp_limb_t res; slong i; NMOD_VEC_DOT(res, i, len, vec1[i], vec2[i][offset], mod, nlimbs); return res; } static mp_limb_t nmod_fmma(mp_limb_t a, mp_limb_t b, mp_limb_t c, mp_limb_t d, nmod_t mod) { a = nmod_mul(a, b, mod); NMOD_ADDMUL(a, c, d, mod); return a; } mp_limb_t _nmod_vec_dot_rev(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs) { mp_limb_t res; slong i; if (len <= 2 && nlimbs >= 2) { if (len == 2) return nmod_fmma(vec1[0], vec2[1], vec1[1], vec2[0], mod); if (len == 1) return nmod_mul(vec1[0], vec2[0], mod); return 0; } NMOD_VEC_DOT(res, i, len, vec1[i], vec2[len - 1 - i], mod, nlimbs); return res; } flint-3.1.3/src/nmod_vec/inlines.c000066400000000000000000000006541461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define NMOD_VEC_INLINES_C #include "nmod_vec.h" flint-3.1.3/src/nmod_vec/io.c000066400000000000000000000030731461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2023 Vincent Neiger This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "nmod_vec.h" int _nmod_vec_fprint_pretty(FILE * file, mp_srcptr vec, slong len, nmod_t mod) { slong j; int z, width; char fmt[FLINT_BITS + 5]; z = flint_fprintf(file, "\n", len, mod.n); if (z <= 0) return z; if (!len) return z; width = n_sizeinbase(mod.n, 10); z = flint_sprintf(fmt, "%%%dwu", width); if (z <= 0) return z; z = flint_printf("["); if (z <= 0) return z; for (j = 0; j < len; j++) { z = flint_printf(fmt, vec[j]); if (z <= 0) return z; if (j + 1 < len) { z = flint_printf(" "); if (z <= 0) return z; } } z = flint_printf("]\n"); return z; } void _nmod_vec_print_pretty(mp_srcptr vec, slong len, nmod_t mod) { _nmod_vec_fprint_pretty(stdout, vec, len, mod); } int _nmod_vec_print(mp_srcptr vec, slong len, nmod_t mod) { return _nmod_vec_fprint_pretty(stdout, vec, len, mod); } int _nmod_vec_fprint(FILE * f, mp_srcptr vec, slong len, nmod_t mod) { return _nmod_vec_fprint_pretty(f, vec, len, mod); } flint-3.1.3/src/nmod_vec/max_bits.c000066400000000000000000000013311461254215100171640ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" flint_bitcnt_t _nmod_vec_max_bits(mp_srcptr vec, slong len) { slong i; mp_limb_t mask = 0; for (i = 0; i < len; i++) { mask |= vec[i]; if (mask >= (UWORD(1) << (FLINT_BITS - 1))) return FLINT_BITS; } return FLINT_BIT_COUNT(mask); } flint-3.1.3/src/nmod_vec/neg.c000066400000000000000000000011001461254215100161210ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" void _nmod_vec_neg(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod) { slong i; for (i = 0 ; i < len; i++) res[i] = nmod_neg(vec[i], mod); } flint-3.1.3/src/nmod_vec/profile/000077500000000000000000000000001461254215100166545ustar00rootroot00000000000000flint-3.1.3/src/nmod_vec/profile/p-add.c000066400000000000000000000063141461254215100200110ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_vec.h" void _nmod_vec_add_fast(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod); #define NUMTYPES 1 void (* funcs[])(mp_ptr, mp_srcptr, mp_srcptr, slong, nmod_t) = {_nmod_vec_add /*, _nmod_vec_add_fast */}; char * str[] = {"_nmod_vec_add" /*, "_nmod_vec_add_fast" */}; typedef struct { flint_bitcnt_t mod_bits; flint_bitcnt_t len; double timers[NUMTYPES]; } info_t; #define COUNT 10000 void sample(void * arg, ulong unused) { mp_limb_t n; nmod_t mod; info_t * info = (info_t *) arg; flint_bitcnt_t mod_bits = info->mod_bits; flint_bitcnt_t len = info->len; slong type; slong ix; mp_ptr vec1, vec2, res; double * timers = info->timers; double start; FLINT_TEST_INIT(state); n = n_randbits(state, mod_bits); if (n == UWORD(0)) n++; nmod_init(&mod, n); /* warmup */ for (type = 0; type < NUMTYPES * COUNT / 10; type++) { vec1 = _nmod_vec_init(len); vec2 = _nmod_vec_init(len); res = _nmod_vec_init(len); for (ix = 0; ix < len; ix++) { vec1[ix] = n_randint(state, n); vec2[ix] = n_randint(state, n); } for (ix = 0; ix < COUNT / len; ix++) funcs[type % NUMTYPES](res, vec1, vec2, len, mod); _nmod_vec_clear(vec1); _nmod_vec_clear(vec2); } /* real deal */ for (type = 0; type < NUMTYPES * COUNT; type++) { vec1 = _nmod_vec_init(len); vec2 = _nmod_vec_init(len); res = _nmod_vec_init(len); for (ix = 0; ix < len; ix++) { vec1[ix] = n_randint(state, n); vec2[ix] = n_randint(state, n); } prof_start(); start = clock(); for (ix = 0; ix < COUNT / len; ix++) funcs[type % NUMTYPES](res, vec1, vec2, len, mod); timers[type % NUMTYPES] += (double) (clock() - start) / CLOCKS_PER_SEC; prof_stop(); _nmod_vec_clear(vec1); _nmod_vec_clear(vec2); } flint_randclear(state); } int main(int argc, char ** argv) { info_t info = {0}; flint_bitcnt_t mod_bits; slong len; int ix; for (ix = 0; ix < NUMTYPES; ix++) printf("%25s", str[ix]); printf("\n"); for (mod_bits = 3; mod_bits <= FLINT_BITS; mod_bits += 20) { info.mod_bits = mod_bits; for (len = 1; len <= 1200; len = 2 * len + 7) { info.len = len; prof_repeat(NULL, NULL, sample, (void *) &info); for (ix = 0; ix < NUMTYPES; ix++) { printf("%25.3lf", info.timers[ix]); info.timers[ix] = 0; } printf(" " WORD_FMT "d mod bits, " WORD_FMT "d len\n", mod_bits, len); } } return 0; } flint-3.1.3/src/nmod_vec/profile/p-add_sub_neg.c000066400000000000000000000044671461254215100215220ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_vec.h" typedef struct { flint_bitcnt_t bits; int type; } info_t; void sample(void * arg, ulong count) { mp_limb_t n; nmod_t mod; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; int type = info->type; mp_size_t j; slong i; mp_ptr vec1, vec2, res; FLINT_TEST_INIT(state); n = n_randbits(state, bits); if (n == UWORD(0)) n++; nmod_init(&mod, n); vec1 = _nmod_vec_init(1000); vec2 = _nmod_vec_init(1000); res = _nmod_vec_init(1000); for (j = 0; j < 1000; j++) vec1[j] = n_randint(state, n); for (j = 0; j < 1000; j++) vec2[j] = n_randint(state, n); switch (type) { case 1: prof_start(); for (i = 0; i < count; i++) { _nmod_vec_add(res, vec1, vec2, 1000, mod); } prof_stop(); break; case 2: prof_start(); for (i = 0; i < count; i++) { _nmod_vec_sub(res, vec1, vec2, 1000, mod); } prof_stop(); break; case 3: prof_start(); for (i = 0; i < count; i++) { _nmod_vec_neg(res, vec1, 1000, mod); } prof_stop(); break; } flint_randclear(state); _nmod_vec_clear(vec1); _nmod_vec_clear(vec2); } int main(void) { double min1, min2, min3, max; info_t info; flint_bitcnt_t i; for (i = 2; i <= FLINT_BITS; i++) { info.bits = i; info.type = 1; prof_repeat(&min1, &max, sample, (void *) &info); info.type = 2; prof_repeat(&min2, &max, sample, (void *) &info); info.type = 3; prof_repeat(&min3, &max, sample, (void *) &info); flint_printf("bits %wd, add = %.1lf c/l, sub = %.1lf c/l, neg = %.1lf c/l\n", i, (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/1000, (min2/(double)FLINT_CLOCK_SCALE_FACTOR)/1000, (min3/(double)FLINT_CLOCK_SCALE_FACTOR)/1000 ); } return 0; } flint-3.1.3/src/nmod_vec/profile/p-mul.c000066400000000000000000000044441461254215100200600ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_vec.h" typedef struct { flint_bitcnt_t bits; int fullword; } info_t; void sample(void * arg, ulong count) { mp_limb_t n; nmod_t mod; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; int fullword = info->fullword; mp_size_t j; slong i; mp_ptr vec1, vec2, res; FLINT_TEST_INIT(state); n = n_randbits(state, bits); if (n == UWORD(0)) n++; nmod_init(&mod, n); vec1 = _nmod_vec_init(1000); vec2 = _nmod_vec_init(1000); res = _nmod_vec_init(1000); for (j = 0; j < 1000; j++) vec1[j] = n_randint(state, n); for (j = 0; j < 1000; j++) vec2[j] = n_randint(state, n); switch (fullword) { case 0: prof_start(); for (i = 0; i < count; i++) for (j = 0; j < 1000; j++) res[j] = nmod_mul(vec1[j], vec2[j], mod); prof_stop(); break; case 1: prof_start(); for (i = 0; i < count; i++) for (j = 0; j < 1000; j++) res[j] = _nmod_mul_fullword(vec1[j], vec2[j], mod); prof_stop(); break; } flint_randclear(state); _nmod_vec_clear(vec1); _nmod_vec_clear(vec2); } int main(void) { double min1, min2, max; info_t info; flint_bitcnt_t i; for (i = 2; i <= FLINT_BITS; i++) { info.bits = i; info.fullword = 0; prof_repeat(&min1, &max, sample, (void *) &info); if (i != FLINT_BITS) { flint_printf("bits %wd, mul = %.1lf c/l\n", i, (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/1000); } else { info.fullword = 1; prof_repeat(&min2, &max, sample, (void *) &info); flint_printf("bits %wd, mul = %.1lf c/l, mul_fullword = %.1lf c/l\n", i, (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/1000, (min2/(double)FLINT_CLOCK_SCALE_FACTOR)/1000); } } return 0; } flint-3.1.3/src/nmod_vec/profile/p-reduce.c000066400000000000000000000027171461254215100205330ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_vec.h" typedef struct { flint_bitcnt_t bits; } info_t; void sample(void * arg, ulong count) { mp_limb_t n; nmod_t mod; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; mp_ptr vec = _nmod_vec_init(1000); mp_ptr vec2 = _nmod_vec_init(1000); mp_size_t j; slong i; FLINT_TEST_INIT(state); for (j = 0; j < 1000; j++) vec[j] = n_randlimb(state); prof_start(); for (i = 0; i < count; i++) { n = n_randbits(state, bits); if (n == UWORD(0)) n++; nmod_init(&mod, n); _nmod_vec_reduce(vec2, vec, 1000, mod); } prof_stop(); flint_randclear(state); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); } int main(void) { double min, max; info_t info; flint_bitcnt_t i; for (i = 2; i <= FLINT_BITS; i++) { info.bits = i; prof_repeat(&min, &max, sample, (void *) &info); flint_printf("bits %wd, c/l = %.1lf\n", i, (min/(double)FLINT_CLOCK_SCALE_FACTOR)/1000 ); } return 0; } flint-3.1.3/src/nmod_vec/profile/p-scalar_addmul.c000066400000000000000000000040171461254215100220520ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_vec.h" typedef struct { flint_bitcnt_t bits; slong length; } info_t; void sample(void * arg, ulong count) { mp_limb_t n, c; nmod_t mod; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; slong length = info->length; slong i, j; mp_ptr vec = _nmod_vec_init(length); mp_ptr vec2 = _nmod_vec_init(length); FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { n = n_randbits(state, bits); if (n == UWORD(0)) n++; c = n_randint(state, n); for (j = 0; j < length; j++) vec[j] = n_randint(state, n); for (j = 0; j < length; j++) vec2[j] = n_randint(state, n); nmod_init(&mod, n); prof_start(); for (j = 0; j < 30; j++) _nmod_vec_scalar_addmul_nmod(vec2, vec, length, c, mod); prof_stop(); } flint_randclear(state); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); } int main(void) { double min0, min1, min2, max; info_t info; flint_bitcnt_t i; for (i = 2; i <= FLINT_BITS; i++) { info.bits = i; info.length = 4; prof_repeat(&min0, &max, sample, (void *) &info); info.length = 1024; prof_repeat(&min1, &max, sample, (void *) &info); info.length = 65536; prof_repeat(&min2, &max, sample, (void *) &info); flint_printf("bits %wd, length 4 %.1lf c/l, length 128 %.1lf c/l, length 65536 %.1lf c/l\n", i, (min0/(double)FLINT_CLOCK_SCALE_FACTOR)/(4*30), (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/(1024*30), (min2/(double)FLINT_CLOCK_SCALE_FACTOR)/(65536*30) ); } return 0; } flint-3.1.3/src/nmod_vec/profile/p-scalar_mul.c000066400000000000000000000037011461254215100214000ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_vec.h" typedef struct { flint_bitcnt_t bits; slong length; } info_t; void sample(void * arg, ulong count) { mp_limb_t n, c; nmod_t mod; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; slong length = info->length; slong i, j; mp_ptr vec = _nmod_vec_init(length); mp_ptr vec2 = _nmod_vec_init(length); FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { n = n_randbits(state, bits); if (n == UWORD(0)) n++; c = n_randint(state, n); for (j = 0; j < length; j++) vec[j] = n_randint(state, n); nmod_init(&mod, n); prof_start(); for (j = 0; j < 30; j++) _nmod_vec_scalar_mul_nmod(vec2, vec, length, c, mod); prof_stop(); } flint_randclear(state); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); } int main(void) { double min0, min1, min2, max; info_t info; flint_bitcnt_t i; for (i = 2; i <= FLINT_BITS; i++) { info.bits = i; info.length = 4; prof_repeat(&min0, &max, sample, (void *) &info); info.length = 1024; prof_repeat(&min1, &max, sample, (void *) &info); info.length = 65536; prof_repeat(&min2, &max, sample, (void *) &info); flint_printf("bits %wd, length 4 %.1lf c/l, length 128 %.1lf c/l, length 65536 %.1lf c/l\n", i, (min0/(double)FLINT_CLOCK_SCALE_FACTOR)/(4*30), (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/(1024*30), (min2/(double)FLINT_CLOCK_SCALE_FACTOR)/(65536*30) ); } return 0; } flint-3.1.3/src/nmod_vec/randtest.c000066400000000000000000000016541461254215100172120ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" void _nmod_vec_randtest(mp_ptr vec, flint_rand_t state, slong len, nmod_t mod) { slong i, sparseness; if (n_randint(state, 2)) { for (i = 0; i < len; i++) vec[i] = n_randtest(state) % mod.n; } else { sparseness = 1 + n_randint(state, FLINT_MAX(2, len)); for (i = 0; i < len; i++) { if (n_randint(state, sparseness)) vec[i] = 0; else vec[i] = n_randtest(state) % mod.n; } } } flint-3.1.3/src/nmod_vec/reduce.c000066400000000000000000000011021461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" void _nmod_vec_reduce(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod) { slong i; for (i = 0 ; i < len; i++) NMOD_RED(res[i], vec[i], mod); } flint-3.1.3/src/nmod_vec/scalar.c000066400000000000000000000057071461254215100166360ustar00rootroot00000000000000/* Copyright (C) 2010, 2015 William Hart Copyright (C) 2015 Vladimir Glazachev Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" void _nmod_vec_scalar_addmul_nmod_fullword(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; mp_limb_t t; for (i = 0; i < len; i++) { NMOD_MUL_FULLWORD(t, vec[i], c, mod); res[i] = nmod_add(res[i], t, mod); } } void _nmod_vec_scalar_addmul_nmod_generic(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; mp_limb_t t; for (i = 0; i < len; i++) { NMOD_MUL_PRENORM(t, vec[i], c << mod.norm, mod); res[i] = _nmod_add(res[i], t, mod); } } void _nmod_vec_scalar_addmul_nmod_shoup(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; mp_limb_t t, cinv; cinv = n_mulmod_precomp_shoup(c, mod.n); for (i = 0; i < len; i++) { t = n_mulmod_shoup(c, vec[i], cinv, mod.n); res[i] = _nmod_add(res[i], t, mod); } } void _nmod_vec_scalar_addmul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { if (NMOD_BITS(mod) == FLINT_BITS) _nmod_vec_scalar_addmul_nmod_fullword(res, vec, len, c, mod); else if (len > 10) _nmod_vec_scalar_addmul_nmod_shoup(res, vec, len, c, mod); else _nmod_vec_scalar_addmul_nmod_generic(res, vec, len, c, mod); } void _nmod_vec_scalar_mul_nmod_fullword(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; for (i = 0; i < len; i++) NMOD_MUL_FULLWORD(res[i], vec[i], c, mod); } void _nmod_vec_scalar_mul_nmod_generic(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; for (i = 0; i < len; i++) NMOD_MUL_PRENORM(res[i], vec[i], c << mod.norm, mod); } void _nmod_vec_scalar_mul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { if (NMOD_BITS(mod) == FLINT_BITS) _nmod_vec_scalar_mul_nmod_fullword(res, vec, len, c, mod); else if (len > 10) _nmod_vec_scalar_mul_nmod_shoup(res, vec, len, c, mod); else _nmod_vec_scalar_mul_nmod_generic(res, vec, len, c, mod); } void _nmod_vec_scalar_mul_nmod_shoup(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { slong i; mp_limb_t w_pr; w_pr = n_mulmod_precomp_shoup(c, mod.n); for (i = 0; i < len; i++) res[i] = n_mulmod_shoup(c, vec[i], w_pr, mod.n); } flint-3.1.3/src/nmod_vec/sub.c000066400000000000000000000013771461254215100161610ustar00rootroot00000000000000/* Copyright (C) 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod.h" #include "nmod_vec.h" void _nmod_vec_sub(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod) { slong i; if (mod.norm) { for (i = 0 ; i < len; i++) res[i] = _nmod_sub(vec1[i], vec2[i], mod); } else { for (i = 0 ; i < len; i++) res[i] = nmod_sub(vec1[i], vec2[i], mod); } } flint-3.1.3/src/nmod_vec/test/000077500000000000000000000000001461254215100161735ustar00rootroot00000000000000flint-3.1.3/src/nmod_vec/test/main.c000066400000000000000000000027271461254215100172730ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_sub_neg.c" #include "t-discrete_log_pohlig_hellman.c" #include "t-dot_bound_limbs.c" #include "t-dot.c" #include "t-dot_ptr.c" #include "t-nmod.c" #include "t-nmod_pow_fmpz.c" #include "t-reduce.c" #include "t-scalar_addmul_nmod.c" #include "t-scalar_mul_nmod.c" #include "t-scalar_mul_nmod_shoup.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(nmod_vec_add_sub_neg), TEST_FUNCTION(nmod_vec_discrete_log_pohlig_hellman), TEST_FUNCTION(nmod_vec_dot_bound_limbs), TEST_FUNCTION(nmod_vec_dot), TEST_FUNCTION(nmod_vec_dot_ptr), TEST_FUNCTION(nmod_vec_nmod), TEST_FUNCTION(nmod_vec_nmod_pow_fmpz), TEST_FUNCTION(nmod_vec_reduce), TEST_FUNCTION(nmod_vec_scalar_addmul_nmod), TEST_FUNCTION(nmod_vec_scalar_mul_nmod), TEST_FUNCTION(nmod_vec_scalar_mul_nmod_shoup) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/nmod_vec/test/t-add_sub_neg.c000066400000000000000000000042461461254215100210400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_add_sub_neg, state) { int i, result; /* Check (a + b) - b == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong len = n_randint(state, 100) + 1; nmod_t mod; mp_limb_t n = n_randtest_not_zero(state); mp_ptr vec = _nmod_vec_init(len); mp_ptr vec2 = _nmod_vec_init(len); mp_ptr vec3 = _nmod_vec_init(len); nmod_init(&mod, n); _nmod_vec_randtest(vec, state, len, mod); _nmod_vec_randtest(vec2, state, len, mod); _nmod_vec_add(vec3, vec, vec2, len, mod); _nmod_vec_sub(vec3, vec3, vec2, len, mod); result = _nmod_vec_equal(vec, vec3, len); if (!result) TEST_FUNCTION_FAIL("len = %wd, n = %wd\n", len, n); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } /* Check (a + -b) == a - b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong len = n_randint(state, 100) + 1; mp_limb_t n = n_randtest_not_zero(state); nmod_t mod; mp_ptr vec = _nmod_vec_init(len); mp_ptr vec2 = _nmod_vec_init(len); mp_ptr vec3 = _nmod_vec_init(len); nmod_init(&mod, n); _nmod_vec_randtest(vec, state, len, mod); _nmod_vec_randtest(vec2, state, len, mod); _nmod_vec_sub(vec3, vec, vec2, len, mod); _nmod_vec_neg(vec2, vec2, len, mod); _nmod_vec_add(vec, vec, vec2, len, mod); result = _nmod_vec_equal(vec, vec3, len); if (!result) TEST_FUNCTION_FAIL("len = %wd, n = %wd\n", len, n); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-discrete_log_pohlig_hellman.c000066400000000000000000000031041461254215100243030ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_discrete_log_pohlig_hellman, state) { slong i, j, k; for (i = 0; i < 20 * flint_test_multiplier(); i++) { nmod_discrete_log_pohlig_hellman_t L; nmod_discrete_log_pohlig_hellman_init(L); for (j = 0; j < 10; j++) { double score; nmod_t fpctx; mp_limb_t p; p = n_randtest_prime(state, 1); nmod_init(&fpctx, p); score = nmod_discrete_log_pohlig_hellman_precompute_prime(L, p); if (score > 10000) { continue; } for (k = 0; k < 10; k++) { ulong x; mp_limb_t y, alpha = nmod_discrete_log_pohlig_hellman_primitive_root(L); x = n_urandint(state, p - 1); y = nmod_pow_ui(alpha, x, fpctx); if (x != nmod_discrete_log_pohlig_hellman_run(L, y)) TEST_FUNCTION_FAIL("modulo %wu log base %wu of %wu should be %wu\n", p, alpha, y, x); } } nmod_discrete_log_pohlig_hellman_clear(L); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-dot.c000066400000000000000000000032331461254215100173670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_dot, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong len; nmod_t mod; mp_limb_t m, res; mp_ptr x, y; int limbs1; mpz_t s, t; slong j; len = n_randint(state, 1000) + 1; m = n_randtest_not_zero(state); nmod_init(&mod, m); x = _nmod_vec_init(len); y = _nmod_vec_init(len); _nmod_vec_randtest(x, state, len, mod); _nmod_vec_randtest(y, state, len, mod); limbs1 = _nmod_vec_dot_bound_limbs(len, mod); res = _nmod_vec_dot(x, y, len, mod, limbs1); mpz_init(s); mpz_init(t); for (j = 0; j < len; j++) { flint_mpz_set_ui(t, x[j]); flint_mpz_addmul_ui(s, t, y[j]); } flint_mpz_mod_ui(s, s, m); if (flint_mpz_get_ui(s) != res) TEST_FUNCTION_FAIL( "m = %wu\n" "len = %wd\n" "limbs1 = %d\n", m, len, limbs1); mpz_clear(s); mpz_clear(t); _nmod_vec_clear(x); _nmod_vec_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-dot_bound_limbs.c000066400000000000000000000025601461254215100217460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_dot_bound_limbs, state) { int i; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { slong len; nmod_t mod; mp_limb_t m; int limbs1, limbs2; mpz_t t; len = n_randint(state, 10000) + 1; m = n_randtest_not_zero(state); nmod_init(&mod, m); limbs1 = _nmod_vec_dot_bound_limbs(len, mod); mpz_init2(t, 4*FLINT_BITS); flint_mpz_set_ui(t, m-1); mpz_mul(t, t, t); flint_mpz_mul_ui(t, t, len); limbs2 = mpz_size(t); if (limbs1 != limbs2) TEST_FUNCTION_FAIL( "m = %wu\n" "len = %wd\n" "limbs1 = %d\n" "limbs2 = %d\n" "bound: %{mpz}\n", m, len, limbs1, limbs2, t); mpz_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-dot_ptr.c000066400000000000000000000031671461254215100202620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_dot_ptr, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong len; nmod_t mod; mp_limb_t m, res, res2; mp_ptr x, y; mp_ptr * z; int limbs1; slong j, offset; len = n_randint(state, 1000) + 1; m = n_randtest_not_zero(state); offset = n_randint(state, 10); nmod_init(&mod, m); x = _nmod_vec_init(len); y = _nmod_vec_init(len); z = flint_malloc(sizeof(mp_ptr) * len); _nmod_vec_randtest(x, state, len, mod); _nmod_vec_randtest(y, state, len, mod); for (j = 0; j < len; j++) z[j] = &y[j] + offset; limbs1 = _nmod_vec_dot_bound_limbs(len, mod); res = _nmod_vec_dot_ptr(x, z, -offset, len, mod, limbs1); res2 = _nmod_vec_dot(x, y, len, mod, limbs1); if (res != res2) TEST_FUNCTION_FAIL( "m = %wu\n" "len = %wd\n" "limbs1 = %d\n", m, len, limbs1); _nmod_vec_clear(x); _nmod_vec_clear(y); flint_free(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-nmod.c000066400000000000000000000110421461254215100175330ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_nmod, state) { int i; /* nmod_add */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t m, a, b, c; mpz_t x, y, z; m = n_randtest_not_zero(state); nmod_init(&mod, m); a = n_randlimb(state) % m; b = n_randlimb(state) % m; c = nmod_add(a, b, mod); mpz_init(x); mpz_init(y); mpz_init(z); flint_mpz_set_ui(x, a); flint_mpz_set_ui(y, b); mpz_add(z, x, y); flint_mpz_mod_ui(z, z, m); if (flint_mpz_cmp_ui(z, c) != 0) TEST_FUNCTION_FAIL("(add) m = %wu\n", m); mpz_clear(x); mpz_clear(y); mpz_clear(z); } /* nmod_sub */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t m, a, b, c; mpz_t x, y, z; m = n_randtest_not_zero(state); nmod_init(&mod, m); a = n_randlimb(state) % m; b = n_randlimb(state) % m; c = nmod_sub(a, b, mod); mpz_init(x); mpz_init(y); mpz_init(z); flint_mpz_set_ui(x, a); flint_mpz_set_ui(y, b); mpz_sub(z, x, y); flint_mpz_mod_ui(z, z, m); if (flint_mpz_cmp_ui(z, c) != 0) TEST_FUNCTION_FAIL("(sub) m = %wu\n", m); mpz_clear(x); mpz_clear(y); mpz_clear(z); } /* nmod_mul */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t m, a, b, c; mpz_t x, y, z; m = n_randtest_not_zero(state); nmod_init(&mod, m); a = n_randlimb(state) % m; b = n_randlimb(state) % m; c = nmod_mul(a, b, mod); mpz_init(x); mpz_init(y); mpz_init(z); flint_mpz_set_ui(x, a); flint_mpz_set_ui(y, b); mpz_mul(z, x, y); flint_mpz_mod_ui(z, z, m); if (flint_mpz_cmp_ui(z, c) != 0) TEST_FUNCTION_FAIL("(mul) m = %wu\n", m); mpz_clear(x); mpz_clear(y); mpz_clear(z); } /* nmod_div */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t m, a, b, c; mpz_t x, y, z; m = n_randtest_prime(state, 0); nmod_init(&mod, m); a = n_randlimb(state) % m; do { b = n_randlimb(state) % m; } while (b == 0); c = nmod_div(a, b, mod); mpz_init(x); mpz_init(y); mpz_init(z); flint_mpz_set_ui(x, a); flint_mpz_set_ui(y, b); flint_mpz_set_ui(z, m); mpz_invert(z, y, z); mpz_mul(z, x, z); flint_mpz_mod_ui(z, z, m); if (flint_mpz_cmp_ui(z, c) != 0) TEST_FUNCTION_FAIL("(div) m = %wu\n", m); mpz_clear(x); mpz_clear(y); mpz_clear(z); } /* nmod_inv */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t m, b, c; mpz_t y, z; m = n_randtest_prime(state, 0); nmod_init(&mod, m); do { b = n_randlimb(state) % m; } while (b == 0); c = nmod_inv(b, mod); mpz_init(y); mpz_init(z); flint_mpz_set_ui(y, b); flint_mpz_set_ui(z, m); mpz_invert(z, y, z); if (flint_mpz_cmp_ui(z, c) != 0) TEST_FUNCTION_FAIL("(inv) m = %wu\n", m); mpz_clear(y); mpz_clear(z); } /* nmod_pow_ui */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t m, b, c; mpz_t y, z; ulong exp; m = n_randtest_prime(state, 0); exp = n_randtest(state); nmod_init(&mod, m); b = n_randlimb(state) % m; c = nmod_pow_ui(b, exp, mod); mpz_init(y); mpz_init(z); flint_mpz_set_ui(y, b); flint_mpz_set_ui(z, m); flint_mpz_powm_ui(z, y, exp, z); if (flint_mpz_cmp_ui(z, c) != 0) TEST_FUNCTION_FAIL("(pow) m = %wu\n", m); mpz_clear(y); mpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-nmod_pow_fmpz.c000066400000000000000000000041011461254215100214520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" #include "fmpz.h" TEST_FUNCTION_START(nmod_vec_nmod_pow_fmpz, state) { int i; /* check nmod_pow_fmpz matches nmod_pow_ui */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t b, c1, c2; ulong exp1; fmpz_t exp2; nmod_init(&mod, n_randtest_not_zero(state)); exp1 = n_randtest(state); fmpz_init_set_ui(exp2, exp1); b = n_randlimb(state) % mod.n; c1 = nmod_pow_ui(b, exp1, mod); c2 = nmod_pow_fmpz(b, exp2, mod); if (c1 != c2) TEST_FUNCTION_FAIL( "check nmod_pow_fmpz matches nmod_pow_ui\n" "i = %wd\n", i); fmpz_clear(exp2); } /* check b^e1*b^e2 = b^(e1+e2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_t mod; mp_limb_t b, c1, c2, c3; fmpz_t exp1, exp2, exp3; nmod_init(&mod, n_randtest_not_zero(state)); fmpz_init(exp1); fmpz_init(exp2); fmpz_init(exp3); fmpz_randtest_unsigned(exp1, state, 500); fmpz_randtest_unsigned(exp2, state, 500); fmpz_add(exp3, exp1, exp2); b = n_randlimb(state) % mod.n; c1 = nmod_pow_fmpz(b, exp1, mod); c2 = nmod_pow_fmpz(b, exp2, mod); c3 = nmod_pow_fmpz(b, exp3, mod); if (c3 != nmod_mul(c1, c2, mod)) TEST_FUNCTION_FAIL( "check b^e1*b^e2 = b^(e1+e2)\n" "i = %wd\n", i); fmpz_clear(exp3); fmpz_clear(exp2); fmpz_clear(exp1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-reduce.c000066400000000000000000000024421461254215100200510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_reduce, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong j, len = n_randint(state, 100) + 1; mp_ptr vec = _nmod_vec_init(len); mp_ptr vec2 = _nmod_vec_init(len); mp_limb_t n = n_randtest_not_zero(state); nmod_t mod; nmod_init(&mod, n); for (j = 0; j < len; j++) { vec[j] = n_randtest(state); vec2[j] = vec[j]; } _nmod_vec_reduce(vec, vec, len, mod); for (j = 0; j < len; j++) vec2[j] = n_mod2_preinv(vec2[j], mod.n, mod.ninv); result = _nmod_vec_equal(vec, vec2, len); if (!result) TEST_FUNCTION_FAIL("len = %wd, n = %wd\n", len, n); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-scalar_addmul_nmod.c000066400000000000000000000027721461254215100224200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_scalar_addmul_nmod, state) { int i, result; /* Check (a + b*c) == a + (b*c) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong len = n_randint(state, 100) + 1; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t c = n_randint(state, n); nmod_t mod; mp_ptr vec = _nmod_vec_init(len); mp_ptr vec2 = _nmod_vec_init(len); mp_ptr vec3 = _nmod_vec_init(len); nmod_init(&mod, n); _nmod_vec_randtest(vec, state, len, mod); _nmod_vec_randtest(vec2, state, len, mod); flint_mpn_copyi(vec3, vec2, len); _nmod_vec_scalar_mul_nmod(vec3, vec, len, c, mod); _nmod_vec_add(vec3, vec3, vec2, len, mod); _nmod_vec_scalar_addmul_nmod(vec2, vec, len, c, mod); result = _nmod_vec_equal(vec2, vec3, len); if (!result) TEST_FUNCTION_FAIL("len = %wd, n = %wd\n", len, n); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-scalar_mul_nmod.c000066400000000000000000000032541461254215100217430ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_scalar_mul_nmod, state) { int i, result; { nmod_t mod; nmod_init(&mod, 2); _nmod_vec_scalar_mul_nmod(NULL, NULL, 0, 1, mod); } /* Check (a + b)*c == a*c + b*c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong len = n_randint(state, 100) + 1; mp_limb_t n = n_randtest_not_zero(state); mp_limb_t c = n_randint(state, n); nmod_t mod; mp_ptr vec = _nmod_vec_init(len); mp_ptr vec2 = _nmod_vec_init(len); mp_ptr vec3 = _nmod_vec_init(len); nmod_init(&mod, n); _nmod_vec_randtest(vec, state, len, mod); _nmod_vec_randtest(vec2, state, len, mod); _nmod_vec_add(vec3, vec, vec2, len, mod); _nmod_vec_scalar_mul_nmod(vec3, vec3, len, c, mod); _nmod_vec_scalar_mul_nmod(vec, vec, len, c, mod); _nmod_vec_scalar_mul_nmod(vec2, vec2, len, c, mod); _nmod_vec_add(vec, vec, vec2, len, mod); result = _nmod_vec_equal(vec, vec3, len); if (!result) TEST_FUNCTION_FAIL("len = %wd, n = %wd\n", len, n); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/nmod_vec/test/t-scalar_mul_nmod_shoup.c000066400000000000000000000032041461254215100231540ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "nmod.h" #include "nmod_vec.h" TEST_FUNCTION_START(nmod_vec_scalar_mul_nmod_shoup, state) { int i, result; /* Check (a + b)*c == a*c + b*c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong len = n_randint(state, 100) + 1; mp_limb_t n = n_randtest_not_zero(state) / 2 + 1; mp_limb_t c = n_randint(state, n) / 2; nmod_t mod; mp_ptr vec = _nmod_vec_init(len); mp_ptr vec2 = _nmod_vec_init(len); mp_ptr vec3 = _nmod_vec_init(len); nmod_init(&mod, n); _nmod_vec_randtest(vec, state, len, mod); _nmod_vec_randtest(vec2, state, len, mod); _nmod_vec_add(vec3, vec, vec2, len, mod); _nmod_vec_scalar_mul_nmod_shoup(vec3, vec3, len, c, mod); _nmod_vec_scalar_mul_nmod_shoup(vec, vec, len, c, mod); _nmod_vec_scalar_mul_nmod_shoup(vec2, vec2, len, c, mod); _nmod_vec_add(vec, vec, vec2, len, mod); result = _nmod_vec_equal(vec, vec3, len); if (!result) TEST_FUNCTION_FAIL("len = %wd, n = %wd\n", len, n); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic.h000066400000000000000000000206071461254215100146600ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef PADIC_H #define PADIC_H #ifdef PADIC_INLINES_C #define PADIC_INLINE #else #define PADIC_INLINE static inline #endif #include "fmpz.h" #include "padic_types.h" #ifdef __cplusplus extern "C" { #endif #define PADIC_DEFAULT_PREC WORD(20) #define PADIC_TEST_PREC_MIN WORD(-100) #define PADIC_TEST_PREC_MAX WORD(100) #define padic_val(x) ((x)->v) #define padic_prec(x) ((x)->N) PADIC_INLINE fmpz * padic_unit(const padic_t x) { return (fmpz *)(&(x->u)); } PADIC_INLINE slong padic_get_val(const padic_t x) { return x->v; } PADIC_INLINE slong padic_get_prec(const padic_t x) { return x->N; } /* Context *******************************************************************/ void padic_ctx_init(padic_ctx_t ctx, const fmpz_t p, slong min, slong max, enum padic_print_mode mode); void padic_ctx_clear(padic_ctx_t ctx); PADIC_INLINE int _padic_ctx_pow_ui(fmpz_t rop, ulong e, const padic_ctx_t ctx) { if (ctx->min <= (slong) e && (slong) e < ctx->max) { *rop = *(ctx->pow + (e - ctx->min)); return 0; } else { slong l = (slong) e; if (l < 0) { flint_throw(FLINT_ERROR, "Exception (_padic_ctx_pow_ui). Power too large.\ne = %wu\nl = %wd\n", e, l); } fmpz_init(rop); fmpz_pow_ui(rop, ctx->p, e); return 1; } } PADIC_INLINE void padic_ctx_pow_ui(fmpz_t rop, ulong e, const padic_ctx_t ctx) { if (ctx->min <= (slong) e && (slong) e < ctx->max) fmpz_set(rop, ctx->pow + (e - ctx->min)); else { slong l = (slong) e; if (l < 0) { flint_throw(FLINT_ERROR, "Exception (padic_ctx_pow_ui). Power too large.\ne = %wu\nl = %wd\n", e, l); } fmpz_pow_ui(rop, ctx->p, e); } } /* Memory management *********************************************************/ void padic_init(padic_t rop); void padic_init2(padic_t rop, slong N); void padic_clear(padic_t rop); PADIC_INLINE void _padic_canonicalise(padic_t rop, const padic_ctx_t ctx) { if (!fmpz_is_zero(padic_unit(rop))) { padic_val(rop) += _fmpz_remove(padic_unit(rop), ctx->p, ctx->pinv); } else { padic_val(rop) = 0; } } void _padic_reduce(padic_t rop, const padic_ctx_t ctx); void padic_reduce(padic_t rop, const padic_ctx_t ctx); /* Randomisation *************************************************************/ void padic_randtest(padic_t rop, flint_rand_t state, const padic_ctx_t ctx); void padic_randtest_not_zero(padic_t rop, flint_rand_t state, const padic_ctx_t ctx); void padic_randtest_int(padic_t rop, flint_rand_t state, const padic_ctx_t ctx); /* Assignments and conversions ***********************************************/ void padic_set(padic_t rop, const padic_t op, const padic_ctx_t ctx); void padic_set_si(padic_t rop, slong op, const padic_ctx_t ctx); void padic_set_ui(padic_t rop, ulong op, const padic_ctx_t ctx); void padic_set_fmpz(padic_t rop, const fmpz_t op, const padic_ctx_t ctx); void padic_set_fmpq(padic_t rop, const fmpq_t op, const padic_ctx_t ctx); void padic_set_mpz(padic_t rop, const mpz_t op, const padic_ctx_t ctx); void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx); void padic_get_fmpz(fmpz_t rop, const padic_t op, const padic_ctx_t ctx); void padic_get_fmpq(fmpq_t rop, const padic_t op, const padic_ctx_t ctx); void padic_get_mpz(mpz_t rop, const padic_t op, const padic_ctx_t ctx); void padic_get_mpq(mpq_t rop, const padic_t op, const padic_ctx_t ctx); PADIC_INLINE void padic_swap(padic_t op1, padic_t op2) { FLINT_SWAP(padic_struct, *op1, *op2); } PADIC_INLINE void padic_zero(padic_t rop) { fmpz_zero(padic_unit(rop)); padic_val(rop) = 0; } PADIC_INLINE void padic_one(padic_t rop) { if (padic_prec(rop) > 0) { fmpz_one(padic_unit(rop)); padic_val(rop) = 0; } else { padic_zero(rop); } } /* Comparison ****************************************************************/ PADIC_INLINE int padic_is_zero(const padic_t op) { return fmpz_is_zero(padic_unit(op)); } PADIC_INLINE int padic_is_one(const padic_t op) { return fmpz_is_one(padic_unit(op)) && (padic_val(op) == 0); } PADIC_INLINE int padic_equal(const padic_t op1, const padic_t op2) { return (padic_val(op1) == padic_val(op2)) && (fmpz_equal(padic_unit(op1), padic_unit(op2))); } /* Arithmetic operations *****************************************************/ slong * _padic_lifts_exps(slong *n, slong N); void _padic_lifts_pows(fmpz *pow, const slong *a, slong n, const fmpz_t p); void padic_add(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); void padic_sub(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); void padic_neg(padic_t rop, const padic_t op, const padic_ctx_t ctx); void padic_mul(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); void padic_shift(padic_t rop, const padic_t op, slong v, const padic_ctx_t ctx); void padic_div(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); void _padic_inv_precompute(padic_inv_t S, const fmpz_t p, slong N); void _padic_inv_clear(padic_inv_t S); void _padic_inv_precomp(fmpz_t rop, const fmpz_t op, const padic_inv_t S); void _padic_inv(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N); void padic_inv(padic_t rop, const padic_t op, const padic_ctx_t ctx); int padic_sqrt(padic_t rop, const padic_t op, const padic_ctx_t ctx); void padic_pow_si(padic_t rop, const padic_t op, slong e, const padic_ctx_t ctx); /* Exponential ***************************************************************/ slong _padic_exp_bound(slong v, slong N, const fmpz_t p); void _padic_exp(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); void _padic_exp_rectangular(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); void _padic_exp_balanced(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); int padic_exp(padic_t rop, const padic_t op, const padic_ctx_t ctx); int padic_exp_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx); int padic_exp_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx); /* Logarithm *****************************************************************/ slong _padic_log_bound(slong v, slong N, const fmpz_t p); void _padic_log(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); void _padic_log_rectangular(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); void _padic_log_satoh(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); void _padic_log_balanced(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); int padic_log(padic_t rop, const padic_t op, const padic_ctx_t ctx); int padic_log_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx); int padic_log_satoh(padic_t rop, const padic_t op, const padic_ctx_t ctx); int padic_log_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx); /* Special functions *********************************************************/ void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N); void padic_teichmuller(padic_t rop, const padic_t op, const padic_ctx_t ctx); ulong padic_val_fac_ui_2(ulong N); ulong padic_val_fac_ui(ulong N, const fmpz_t p); void padic_val_fac(fmpz_t rop, const fmpz_t op, const fmpz_t p); /* Input and output **********************************************************/ char * _padic_get_str(char * str, const padic_t op, const fmpz_t p, enum padic_print_mode mode); char * padic_get_str(char * str, const padic_t op, const padic_ctx_t ctx); #ifdef FLINT_HAVE_FILE int _padic_fprint(FILE * file, const fmpz_t u, slong v, const padic_ctx_t ctx); int padic_fprint(FILE * file, const padic_t op, const padic_ctx_t ctx); #endif int _padic_print(const fmpz_t u, slong v, const padic_ctx_t ctx); int padic_print(const padic_t op, const padic_ctx_t ctx); void padic_debug(const padic_t op); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/padic/000077500000000000000000000000001461254215100145025ustar00rootroot00000000000000flint-3.1.3/src/padic/add.c000066400000000000000000000054001461254215100153750ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_add(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) { if (padic_prec(rop) <= FLINT_MIN(padic_val(op1), padic_val(op2))) { padic_zero(rop); return; } if (padic_is_zero(op1)) { padic_set(rop, op2, ctx); } else if (padic_is_zero(op2)) { padic_set(rop, op1, ctx); } else { if (padic_val(op1) == padic_val(op2)) { fmpz_add(padic_unit(rop), padic_unit(op1), padic_unit(op2)); padic_val(rop) = padic_val(op1); _padic_canonicalise(rop, ctx); if (padic_prec(rop) <= padic_val(rop)) { padic_zero(rop); return; } } else if (padic_val(op1) < padic_val(op2)) { fmpz_t f; fmpz_init(f); fmpz_pow_ui(f, ctx->p, padic_val(op2) - padic_val(op1)); if (rop != op2) { fmpz_set(padic_unit(rop), padic_unit(op1)); fmpz_addmul(padic_unit(rop), f, padic_unit(op2)); } else { fmpz_mul(padic_unit(rop), f, padic_unit(op2)); fmpz_add(padic_unit(rop), padic_unit(rop), padic_unit(op1)); } fmpz_clear(f); padic_val(rop) = padic_val(op1); } else /* padic_val(op1) > padic_val(op2) */ { fmpz_t f; fmpz_init(f); fmpz_pow_ui(f, ctx->p, padic_val(op1) - padic_val(op2)); if (rop != op1) { fmpz_set(padic_unit(rop), padic_unit(op2)); fmpz_addmul(padic_unit(rop), f, padic_unit(op1)); } else { fmpz_mul(padic_unit(rop), f, padic_unit(op1)); fmpz_add(padic_unit(rop), padic_unit(rop), padic_unit(op2)); } fmpz_clear(f); padic_val(rop) = padic_val(op2); } /* Reduce */ { int alloc; fmpz_t pow; alloc = _padic_ctx_pow_ui(pow, padic_prec(rop) - padic_val(rop), ctx); fmpz_mod(padic_unit(rop), padic_unit(rop), pow); if (fmpz_is_zero(padic_unit(rop))) padic_val(rop) = 0; if (alloc) fmpz_clear(pow); } } } flint-3.1.3/src/padic/clear.c000066400000000000000000000007351461254215100157410ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_clear(padic_t rop) { fmpz_clear(padic_unit(rop)); } flint-3.1.3/src/padic/ctx_clear.c000066400000000000000000000011031461254215100166050ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" void padic_ctx_clear(padic_ctx_t ctx) { fmpz_clear(ctx->p); if (ctx->pow) { _fmpz_vec_clear(ctx->pow, ctx->max - ctx->min); } } flint-3.1.3/src/padic/ctx_init.c000066400000000000000000000023261461254215100164720ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "padic.h" void padic_ctx_init(padic_ctx_t ctx, const fmpz_t p, slong min, slong max, enum padic_print_mode mode) { if (!(0 <= min && min <= max)) { flint_throw(FLINT_ERROR, "Exception (padic_ctx_init). Require 0 <= min <= max."); } fmpz_init_set(ctx->p, p); ctx->min = min; ctx->max = max; ctx->pinv = (!COEFF_IS_MPZ(*p)) ? n_precompute_inverse(fmpz_get_ui(p)) : 0; if (max - min > 0) { slong i, len = max - min; ctx->pow = _fmpz_vec_init(len); fmpz_pow_ui(ctx->pow, p, ctx->min); for (i = 1; i < len; i++) fmpz_mul(ctx->pow + i, ctx->pow + (i - 1), p); } else { ctx->min = 0; ctx->max = 0; ctx->pow = NULL; } ctx->mode = mode; } flint-3.1.3/src/padic/div.c000066400000000000000000000020501461254215100154250ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_div(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) { if (padic_is_zero(op2)) { flint_throw(FLINT_ERROR, "Exception (padic_div). op2 is zero.\n"); } if (padic_is_zero(op1) || padic_val(op1) - padic_val(op2) >= padic_prec(rop)) { padic_zero(rop); } else { padic_t inv; padic_init(inv); _padic_inv(padic_unit(inv), padic_unit(op2), ctx->p, padic_prec(rop) - padic_val(op1) + padic_val(op2)); padic_val(inv) = - padic_val(op2); padic_mul(rop, op1, inv, ctx); padic_clear(inv); } } flint-3.1.3/src/padic/exp.c000066400000000000000000000034151461254215100154450ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" slong _padic_exp_bound(slong v, slong N, const fmpz_t p) { if (fmpz_fits_si(p)) { fmpz_t n, d, f; slong i; fmpz_init(n); fmpz_init(d); fmpz_init(f); fmpz_sub_ui(f, p, 1); fmpz_mul_ui(n, f, N); fmpz_sub_ui(n, n, 1); fmpz_mul_ui(d, f, v); fmpz_sub_ui(d, d, 1); fmpz_cdiv_q(f, n, d); i = fmpz_get_si(f); fmpz_clear(n); fmpz_clear(d); fmpz_clear(f); return i; } else { return (N + (v - 1)) / v; } } void _padic_exp(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) { if (N < 1024) _padic_exp_rectangular(rop, u, v, p, N); else _padic_exp_balanced(rop, u, v, p, N); } int padic_exp(padic_t rop, const padic_t op, const padic_ctx_t ctx) { const slong N = padic_prec(rop); const slong v = padic_val(op); const fmpz *p = ctx->p; if (padic_is_zero(op)) { padic_one(rop); return 1; } if ((fmpz_equal_ui(p, 2) && v <= 1) || (v <= 0)) { return 0; } else { if (v < N) { _padic_exp(padic_unit(rop), padic_unit(op), padic_val(op), p, N); padic_val(rop) = 0; } else { padic_one(rop); } return 1; } } flint-3.1.3/src/padic/exp_balanced.c000066400000000000000000000122021461254215100172500ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" /* Computes the sum \begin{equation*} (a-1)! x^{1-a} \sum_{i=a}^{b-1} \frac{x^i}{i!}. \end{equation*} in the rational $(T, Q)$. Assumes that $1 \leq a < b$. If $a + 1 = b$, sets $P = x$, $Q = a$, and $T = x$. If $a + 2 = b$, sets $P = x^2$, $Q = a (a + 1)$, $T = x (a + 1) + x^2$. In general, sets \begin{align*} P & = x^{b-a}, \\ Q & = \frac{(b-1)!}{(a-1)!}, \\ T & = (b-1)! x^{1-a} \sum_{i=a}^{b-1} \frac{x^i}{i!}. \end{align*} */ static void _padic_exp_bsplit_series(fmpz_t P, fmpz_t Q, fmpz_t T, const fmpz_t x, slong a, slong b) { if (b - a == 1) { fmpz_set(P, x); fmpz_set_ui(Q, a); fmpz_set(T, x); } else if (b - a == 2) { fmpz_mul(P, x, x); fmpz_set_ui(Q, a); fmpz_mul_ui(Q, Q, a + 1); fmpz_mul_ui(T, x, a + 1); fmpz_add(T, T, P); } else { const slong m = (a + b) / 2; fmpz_t PR, QR, TR; fmpz_init(PR); fmpz_init(QR); fmpz_init(TR); _padic_exp_bsplit_series(P, Q, T, x, a, m); _padic_exp_bsplit_series(PR, QR, TR, x, m, b); fmpz_mul(T, T, QR); fmpz_addmul(T, P, TR); fmpz_mul(P, P, PR); fmpz_mul(Q, Q, QR); fmpz_clear(PR); fmpz_clear(QR); fmpz_clear(TR); } } /* Assumes that $x$ is such that $\exp(x)$ converges. Assumes that $v = \ord_p(x)$ with $v < N$, which also forces $N$ to positive. The result $y$ might not be reduced modulo $p^N$. Supports aliasing between $x$ and $y$. */ static void _padic_exp_bsplit(fmpz_t y, const fmpz_t x, slong v, const fmpz_t p, slong N) { const slong n = _padic_exp_bound(v, N, p); if (n == 1) { fmpz_one(y); } else { fmpz_t P, Q, T; fmpz_init(P); fmpz_init(Q); fmpz_init(T); _padic_exp_bsplit_series(P, Q, T, x, 1, n); fmpz_add(T, T, Q); /* (T,Q) := (T,Q) + 1 */ /* Note exp(x) is a unit so val(T) == val(Q). */ if (fmpz_remove(T, T, p)) fmpz_remove(Q, Q, p); _padic_inv(Q, Q, p, N); fmpz_mul(y, T, Q); fmpz_clear(P); fmpz_clear(Q); fmpz_clear(T); } } void _padic_exp_balanced_2(fmpz_t rop, const fmpz_t xu, slong xv, slong N) { const fmpz_t p = {WORD(2)}; fmpz_t r, t; slong w; fmpz_init(r); fmpz_init(t); w = 1; fmpz_mul_2exp(t, xu, xv); fmpz_fdiv_r_2exp(t, t, N); fmpz_one(rop); while (!fmpz_is_zero(t)) { fmpz_fdiv_r_2exp(r, t, 2*w); fmpz_sub(t, t, r); if (!fmpz_is_zero(r)) { _padic_exp_bsplit(r, r, w, p, N); fmpz_mul(rop, rop, r); fmpz_fdiv_r_2exp(rop, rop, N); } w *= 2; } fmpz_clear(r); fmpz_clear(t); } void _padic_exp_balanced_p(fmpz_t rop, const fmpz_t xu, slong xv, const fmpz_t p, slong N) { fmpz_t r, t, pw, pN; slong w; fmpz_init(r); fmpz_init(t); fmpz_init(pw); fmpz_init(pN); fmpz_set(pw, p); fmpz_pow_ui(pN, p, N); w = 1; fmpz_pow_ui(t, p, xv); fmpz_mul(t, t, xu); fmpz_mod(t, t, pN); fmpz_one(rop); while (!fmpz_is_zero(t)) { fmpz_mul(pw, pw, pw); fmpz_fdiv_r(r, t, pw); fmpz_sub(t, t, r); if (!fmpz_is_zero(r)) { _padic_exp_bsplit(r, r, w, p, N); fmpz_mul(rop, rop, r); fmpz_mod(rop, rop, pN); } w *= 2; } fmpz_clear(r); fmpz_clear(t); fmpz_clear(pw); fmpz_clear(pN); } /* Assumes that the exponential series converges at $x \neq 0$, and that $\ord_p(x) < N$. Supports aliasing between $x$ and $y$. TODO: Take advantage of additional factors of $p$ in $x$. */ void _padic_exp_balanced(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) { if (fmpz_equal_ui(p, 2)) _padic_exp_balanced_2(rop, u, v, N); else _padic_exp_balanced_p(rop, u, v, p, N); } int padic_exp_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx) { const slong N = padic_prec(rop); const slong v = padic_val(op); const fmpz *p = ctx->p; if (padic_is_zero(op)) { padic_one(rop); return 1; } if ((fmpz_equal_ui(p, 2) && v <= 1) || (v <= 0)) { return 0; } else { if (v < N) { _padic_exp_balanced(padic_unit(rop), padic_unit(op), padic_val(op), p, N); padic_val(rop) = 0; } else { padic_one(rop); } return 1; } } flint-3.1.3/src/padic/exp_rectangular.c000066400000000000000000000103601461254215100200310ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "padic.h" /* Computes the sum $1 + x + x^2 / 2$ reduced modulo $p^N$, where $x = p^v u$. Supports aliasing between \code{rop} and $u$. */ static void _padic_exp_small(fmpz_t rop, const fmpz_t u, slong v, slong n, const fmpz_t p, const fmpz_t pN) { if (n == 1) /* rop = 1 */ { fmpz_one(rop); } else if (n == 2) /* rop = 1 + x */ { fmpz_t f; fmpz_init(f); fmpz_pow_ui(f, p, v); fmpz_mul(rop, f, u); fmpz_add_ui(rop, rop, 1); fmpz_mod(rop, rop, pN); fmpz_clear(f); } else /* n == 3, rop = 1 + x + x^2 / 2 */ { fmpz_t f; fmpz_init(f); fmpz_pow_ui(f, p, v); fmpz_mul(rop, f, u); fmpz_mul(f, rop, rop); if (fmpz_is_odd(f)) fmpz_add(f, f, pN); fmpz_fdiv_q_2exp(f, f, 1); fmpz_add(rop, rop, f); fmpz_add_ui(rop, rop, 1); fmpz_clear(f); } } void _padic_exp_rectangular(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) { const slong n = _padic_exp_bound(v, N, p); fmpz_t pN; fmpz_init(pN); fmpz_pow_ui(pN, p, N); if (n <= 3) { _padic_exp_small(rop, u, v, n, p, pN); } else { const slong k = fmpz_fits_si(p) ? (n - 1 - 1) / (fmpz_get_si(p) - 1) : 0; slong i, npows, nsums; fmpz_t c, f, s, t, sum, pNk; fmpz *pows; fmpz_init(pNk); fmpz_pow_ui(pNk, p, N + k); npows = n_sqrt(n); nsums = (n + npows - 1) / npows; fmpz_init(c); fmpz_init(f); fmpz_init(s); fmpz_init(t); fmpz_init(sum); /* Compute pows; pows[i] = x^i. */ pows = _fmpz_vec_init(npows + 1); fmpz_one(pows + 0); fmpz_pow_ui(f, p, v); fmpz_mul(pows + 1, f, u); for (i = 2; i <= npows; i++) { fmpz_mul(pows + i, pows + i - 1, pows + 1); fmpz_mod(pows + i, pows + i, pNk); } fmpz_zero(sum); fmpz_one(f); for (i = nsums - 1; i >= 0; i--) { slong lo = i * npows; slong hi = FLINT_MIN(n - 1, lo + npows - 1); fmpz_zero(s); fmpz_one(c); for ( ; hi >= lo; hi--) { fmpz_addmul(s, pows + hi - lo, c); if (hi != 0) fmpz_mul_ui(c, c, hi); } fmpz_mul(t, pows + npows, sum); fmpz_mul(sum, s, f); fmpz_add(sum, sum, t); fmpz_mod(sum, sum, pNk); fmpz_mul(f, f, c); } /* Divide by factorial, TODO: Improve */ /* Note exp(x) is a unit so val(sum) == val(f) */ if (fmpz_remove(sum, sum, p)) fmpz_remove(f, f, p); _padic_inv(f, f, p, N); fmpz_mul(rop, sum, f); _fmpz_vec_clear(pows, npows + 1); fmpz_clear(c); fmpz_clear(f); fmpz_clear(s); fmpz_clear(t); fmpz_clear(sum); fmpz_clear(pNk); } fmpz_mod(rop, rop, pN); fmpz_clear(pN); } int padic_exp_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx) { const slong N = padic_prec(rop); const slong v = padic_val(op); const fmpz *p = ctx->p; if (padic_is_zero(op)) { padic_one(rop); return 1; } if ((fmpz_equal_ui(p, 2) && v <= 1) || (v <= 0)) { return 0; } else { if (v < N) { _padic_exp_rectangular(padic_unit(rop), padic_unit(op), padic_val(op), p, N); padic_val(rop) = 0; } else { padic_one(rop); } return 1; } } flint-3.1.3/src/padic/get_fmpq.c000066400000000000000000000023741461254215100164560ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "padic.h" void padic_get_fmpq(fmpq_t rop, const padic_t op, const padic_ctx_t ctx) { if (padic_is_zero(op)) { fmpq_zero(rop); } else { fmpz_t pow; int alloc = 0; if (padic_val(op) == 0) { fmpz_set(fmpq_numref(rop), padic_unit(op)); fmpz_one(fmpq_denref(rop)); } else if (padic_val(op) > 0) { alloc = _padic_ctx_pow_ui(pow, padic_val(op), ctx); fmpz_mul(fmpq_numref(rop), padic_unit(op), pow); fmpz_one(fmpq_denref(rop)); } else /* padic_val(op) < 0 */ { alloc = _padic_ctx_pow_ui(pow, - padic_val(op), ctx); fmpz_set(fmpq_numref(rop), padic_unit(op)); fmpz_set(fmpq_denref(rop), pow); } if (alloc) fmpz_clear(pow); } } flint-3.1.3/src/padic/get_fmpz.c000066400000000000000000000017201461254215100164610ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_get_fmpz(fmpz_t rop, const padic_t op, const padic_ctx_t ctx) { if (padic_val(op) < 0) { flint_throw(FLINT_ERROR, "Exception (padic_get_fmpz). Negative valuation.\n"); } if (padic_is_zero(op)) { fmpz_zero(rop); } else if (padic_val(op) == 0) { fmpz_set(rop, padic_unit(op)); } else { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, padic_val(op), ctx); fmpz_mul(rop, padic_unit(op), pow); if (alloc) fmpz_clear(pow); } } flint-3.1.3/src/padic/get_mpq.c000066400000000000000000000011371461254215100163040ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "padic.h" void padic_get_mpq(mpq_t rop, const padic_t op, const padic_ctx_t ctx) { fmpq_t t; fmpq_init(t); padic_get_fmpq(t, op, ctx); fmpq_get_mpq(rop, t); fmpq_clear(t); } flint-3.1.3/src/padic/get_mpz.c000066400000000000000000000011151461254215100163110ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_get_mpz(mpz_t rop, const padic_t op, const padic_ctx_t ctx) { fmpz_t t; fmpz_init(t); padic_get_fmpz(t, op, ctx); fmpz_get_mpz(rop, t); fmpz_clear(t); } flint-3.1.3/src/padic/get_str.c000066400000000000000000000117071461254215100163230ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "long_extras.h" #include "fmpq.h" #include "padic.h" char * _padic_get_str(char *str, const padic_t op, const fmpz_t p, enum padic_print_mode mode) { const fmpz *u = padic_unit(op); const slong v = padic_val(op); if (fmpz_is_zero(u)) { if (!str) { str = flint_malloc(2); } str[0] = '0'; str[1] = '\0'; return str; } if (mode == PADIC_TERSE) { if (v == 0) { str = fmpz_get_str(str, 10, u); } else if (v > 0) { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, v); fmpz_mul(t, t, u); str = fmpz_get_str(str, 10, t); fmpz_clear(t); } else /* v < 0 */ { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, -v); str = _fmpq_get_str(str, 10, u, t); fmpz_clear(t); } } else if (mode == PADIC_SERIES) { char *s; fmpz_t x; fmpz_t d; slong j, N; N = fmpz_clog(u, p) + v + 1; if (!str) { slong b = (N - v) * (2 * fmpz_sizeinbase(p, 10) + z_sizeinbase(FLINT_MAX(FLINT_ABS(v), FLINT_ABS(N)), 10) + 5) + 1; str = flint_malloc(b); if (!str) { flint_throw(FLINT_ERROR, "Exception (padic_get_str). Memory allocation failed.\n"); } } s = str; fmpz_init(d); fmpz_init(x); fmpz_set(x, u); /* Unroll first step */ j = 0; { fmpz_mod(d, x, p); /* d = u mod p^{j+1} */ fmpz_sub(x, x, d); /* x = x - d */ fmpz_divexact(x, x, p); /* x = x / p */ if (!fmpz_is_zero(d)) { if (j + v != 0) { fmpz_get_str(s, 10, d); while (*++s != '\0') ; *s++ = '*'; fmpz_get_str(s, 10, p); while (*++s != '\0') ; *s++ = '^'; flint_sprintf(s, "%wd", j + v); while (*++s != '\0') ; } else { fmpz_get_str(s, 10, d); while (*++s != '\0') ; } } j++; } for ( ; !fmpz_is_zero(x); j++) { fmpz_mod(d, x, p); /* d = u mod p^{j+1} */ fmpz_sub(x, x, d); /* x = x - d */ fmpz_divexact(x, x, p); /* x = x / p */ if (!fmpz_is_zero(d)) { if (j + v != 0) { *s++ = ' '; *s++ = '+'; *s++ = ' '; fmpz_get_str(s, 10, d); while (*++s != '\0') ; *s++ = '*'; fmpz_get_str(s, 10, p); while (*++s != '\0') ; *s++ = '^'; flint_sprintf(s, "%wd", j + v); while (*++s != '\0') ; } else { *s++ = ' '; *s++ = '+'; *s++ = ' '; fmpz_get_str(s, 10, d); while (*++s != '\0') ; } } } fmpz_clear(x); fmpz_clear(d); } else /* ctx->mode == PADIC_VAL_UNIT */ { if (!str) { slong b = fmpz_sizeinbase(u, 10) + fmpz_sizeinbase(p, 10) + z_sizeinbase(v, 10) + 4; str = flint_malloc(b); if (!str) { flint_throw(FLINT_ERROR, "Exception (padic_get_str). Memory allocation failed.\n"); } } if (v == 0) { str = fmpz_get_str(str, 10, u); } else if (v == 1) { char *s = str; fmpz_get_str(s, 10, u); while (*++s != '\0') ; *s++ = '*'; fmpz_get_str(s, 10, p); } else { char *s = str; fmpz_get_str(s, 10, u); while (*++s != '\0') ; *s++ = '*'; fmpz_get_str(s, 10, p); while (*++s != '\0') ; *s++ = '^'; flint_sprintf(s, "%wd", v); } } return str; } char * padic_get_str(char *str, const padic_t op, const padic_ctx_t ctx) { return _padic_get_str(str, op, ctx->p, ctx->mode); } flint-3.1.3/src/padic/init.c000066400000000000000000000012341461254215100156110ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_init(padic_t rop) { fmpz_init(padic_unit(rop)); padic_val(rop) = 0; padic_prec(rop) = PADIC_DEFAULT_PREC; } void padic_init2(padic_t rop, slong N) { fmpz_init(padic_unit(rop)); padic_val(rop) = 0; padic_prec(rop) = N; } flint-3.1.3/src/padic/inlines.c000066400000000000000000000011111461254215100163010ustar00rootroot00000000000000/* Copyright (C) 2014 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define PADIC_INLINES_C #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "padic.h" void padic_get_unit(fmpz_t f, padic_t p) { fmpz_set(f, padic_unit(p)); } flint-3.1.3/src/padic/inv.c000066400000000000000000000044571461254215100154540ustar00rootroot00000000000000/* Copyright (C) 2011 Jan Tuitman Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" #define n (S->n) #define pow (S->pow) void _padic_inv_precompute(padic_inv_t S, const fmpz_t p, slong N) { slong *a; a = _padic_lifts_exps(&n, N); pow = _fmpz_vec_init(2 * n + 2); _padic_lifts_pows(pow, a, n, p); flint_free(a); } void _padic_inv_clear(padic_inv_t S) { _fmpz_vec_clear(pow, 2 * n + 2); } void _padic_inv_precomp(fmpz_t rop, const fmpz_t op, const padic_inv_t S) { slong i; fmpz *t, *u; u = pow + n; t = pow + 2 * n; /* Compute reduced units */ { fmpz_mod(u + 0, op, pow + 0); } for (i = 1; i < n; i++) { fmpz_mod(u + i, u + (i - 1), pow + i); } /* Run Newton iteration */ i = n - 1; { fmpz_invmod(rop, u + i, pow + i); } for (i--; i >= 0; i--) { fmpz_mul(t, rop, rop); fmpz_mul(t + 1, u + i, t); fmpz_mul_2exp(rop, rop, 1); fmpz_sub(rop, rop, t + 1); fmpz_mod(rop, rop, pow + i); } } #undef n #undef pow void _padic_inv(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) { if (N == 1) { fmpz_invmod(rop, op, p); } else { padic_inv_t S; _padic_inv_precompute(S, p, N); _padic_inv_precomp(rop, op, S); _padic_inv_clear(S); } } void padic_inv(padic_t rop, const padic_t op, const padic_ctx_t ctx) { if (padic_is_zero(op)) { flint_throw(FLINT_ERROR, "Exception (padic_inv). Zero is not invertible.\n"); } /* If x = u p^v has negative valuation with N <= -v then the exact inverse of x is zero when reduced modulo $p^N$ */ if (padic_prec(rop) + padic_val(op) <= 0) { padic_zero(rop); } else { _padic_inv(padic_unit(rop), padic_unit(op), ctx->p, padic_prec(rop) + padic_val(op)); padic_val(rop) = - padic_val(op); } } flint-3.1.3/src/padic/io.c000066400000000000000000000076741461254215100152730ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "padic.h" /* printing *******************************************************************/ int _padic_fprint(FILE * file, const fmpz_t u, slong v, const padic_ctx_t ctx) { const fmpz *p = ctx->p; if (fmpz_is_zero(u)) { fputc('0', file); return 1; } if (ctx->mode == PADIC_TERSE) { if (v == 0) { fmpz_fprint(file, u); } else if (v > 0) { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, v); fmpz_mul(t, t, u); fmpz_fprint(file, t); fmpz_clear(t); } else /* v < 0 */ { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, -v); _fmpq_fprint(file, u, t); fmpz_clear(t); } } else if (ctx->mode == PADIC_SERIES) { fmpz_t x; fmpz_t d; slong j; fmpz_init(d); fmpz_init(x); fmpz_set(x, u); /* Unroll first step */ j = 0; { fmpz_mod(d, x, p); /* d = u mod p^{j+1} */ fmpz_sub(x, x, d); /* x = x - d */ fmpz_divexact(x, x, p); /* x = x / p */ if (!fmpz_is_zero(d)) { if (j + v != 0) { fmpz_fprint(file, d); fputc('*', file); fmpz_fprint(file, p); flint_fprintf(file, "^%wd", j + v); } else { fmpz_fprint(file, d); } } j++; } for ( ; !fmpz_is_zero(x); j++) { fmpz_mod(d, x, p); /* d = u mod p^{j+1} */ fmpz_sub(x, x, d); /* x = x - d */ fmpz_divexact(x, x, p); /* x = x / p */ if (!fmpz_is_zero(d)) { if (j + v != 0) { flint_fprintf(file, " + "); fmpz_fprint(file, d); fputc('*', file); fmpz_fprint(file, p); flint_fprintf(file, "^%wd", j + v); } else { flint_fprintf(file, " + "); fmpz_fprint(file, d); } } } fmpz_clear(x); fmpz_clear(d); } else if (ctx->mode == PADIC_VAL_UNIT) { if (v == 0) { fmpz_fprint(file, u); } else if (v == 1) { fmpz_fprint(file, u); fputc('*', file); fmpz_fprint(file, p); } else { fmpz_fprint(file, u); fputc('*', file); fmpz_fprint(file, p); flint_fprintf(file, "^%wd", v); } } else { flint_throw(FLINT_ERROR, "Exception (_padic_fprint). Unknown print mode.\n"); } return 1; } int padic_fprint(FILE * file, const padic_t op, const padic_ctx_t ctx) { return _padic_fprint(file, padic_unit(op), padic_val(op), ctx); } int _padic_print(const fmpz_t u, slong v, const padic_ctx_t ctx) { return _padic_fprint(stdout, u, v, ctx); } int padic_print(const padic_t op, const padic_ctx_t ctx) { return padic_fprint(stdout, op, ctx); } /* debugging ******************************************************************/ void padic_debug(const padic_t op) { flint_printf("("); fmpz_print(padic_unit(op)); flint_printf(" %wd %wd)", padic_val(op), padic_prec(op)); } flint-3.1.3/src/padic/lifts.c000066400000000000000000000026671461254215100160020ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" slong * _padic_lifts_exps(slong *n, slong N) { slong *a, i; *n = FLINT_CLOG2(N) + 1; a = flint_malloc((*n) * sizeof(slong)); for (a[i = 0] = N; a[i] > 1; i++) a[i + 1] = (a[i] + 1) / 2; return a; } void _padic_lifts_pows(fmpz *pow, const slong *a, slong n, const fmpz_t p) { if (n == 1) { fmpz_set(pow + 0, p); } else /* n > 1 */ { slong i = n - 1; fmpz_t t = {WORD(1)}; fmpz_set(pow + i, p); for (i--; i >= 1; i--) { if (a[i] & WORD(1)) { fmpz_mul(pow + i, t, pow + (i + 1)); fmpz_mul(t, t, t); } else { fmpz_mul(t, t, pow + (i + 1)); fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } } { if (a[i] & WORD(1)) fmpz_mul(pow + i, t, pow + (i + 1)); else fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } fmpz_clear(t); } } flint-3.1.3/src/padic/log.c000066400000000000000000000073011461254215100154300ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "padic.h" #include "ulong_extras.h" /* Assumes that $1 \leq v$ or $2 \leq v$ as $p$ is even or odd, respectively, and that $v < N < 2^{f-2}$ where $f$ is \code{FLINT_BITS}. Under the assumption that $1 \leq v < N$, or $2 \leq v < N$, one can easily prove that with $c = N - \floor{\log_p v}$ the number $b = \ceil{(c + \ceil{\log_p c} + 1) / b}$ is such that for all $i \geq b$, $i v - \ord_p(i) \geq N$. Under the additional condition that $N < 2^{f-2}$ one can show that the code branch for primes that fit into a \code{slong} does not cause overflow. Moreover, independently of this, it follows that the above value $b$ is less than $2^{f-1}$. In the first branch, we have that $b v - log_p(b) \geq N$. We need to show that we can replace $\log_p$ by $\ord_p$ here. That is, we need that $iv - \ord_p(i) \geq iv - \log_p(i) \geq N$, i.e., $\log_p(i) \geq \ord_p(i)$, which is true. We then work backwards to find the first $i$ such that this fails, then using that the function is strictly increasing for $i \geq 2$. In the second branch we use that using signed indices in the summation is still sufficient and hence that all terms $1/i$ are units. Then $ord_p(x^i/i) \geq N$ provided that $i v \geq N$. */ slong _padic_log_bound(slong v, slong N, const fmpz_t prime) { if (N >= (WORD(1) << (SMALL_FMPZ_BITCOUNT_MAX))) { flint_throw(FLINT_ERROR, "Exception (_padic_log_bound). N = %wd is too large.\n", N); } if (fmpz_fits_si(prime)) { slong b, c, p = fmpz_get_si(prime); c = N - n_flog(v, p); b = ((c + n_clog(c, p) + 1) + (v - 1)) / v; while (--b >= 2) { slong t = b * v - n_clog(b, p); if (t < N) return b + 1; } return 2; } else { return (N + v - 1) / v; } } void _padic_log(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) { if (N < (WORD(1) << 9) / (slong) fmpz_bits(p)) { _padic_log_rectangular(z, y, v, p, N); } else { _padic_log_balanced(z, y, v, p, N); } } int padic_log(padic_t rop, const padic_t op, const padic_ctx_t ctx) { const fmpz *p = ctx->p; const slong N = padic_prec(rop); if (padic_val(op) < 0) { return 0; } else { fmpz_t x; int ans; fmpz_init(x); padic_get_fmpz(x, op, ctx); fmpz_sub_ui(x, x, 1); fmpz_neg(x, x); if (fmpz_is_zero(x)) { padic_zero(rop); ans = 1; } else { fmpz_t t; slong v; fmpz_init(t); v = fmpz_remove(t, x, p); fmpz_clear(t); if (v >= 2 || (!fmpz_equal_ui(p, 2) && v >= 1)) { if (v >= N) { padic_zero(rop); } else { _padic_log(padic_unit(rop), x, v, p, N); padic_val(rop) = 0; _padic_canonicalise(rop, ctx); } ans = 1; } else { ans = 0; } } fmpz_clear(x); return ans; } } flint-3.1.3/src/padic/log_balanced.c000066400000000000000000000104061461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "ulong_extras.h" static void _padic_log_bsplit_series(fmpz_t P, fmpz_t B, fmpz_t T, const fmpz_t x, slong a, slong b) { if (b - a == 1) { fmpz_set(P, x); fmpz_set_si(B, a); fmpz_set(T, x); } else if (b - a == 2) { fmpz_mul(P, x, x); fmpz_set_si(B, a); fmpz_mul_si(B, B, a + 1); fmpz_mul_si(T, x, a + 1); fmpz_addmul_ui(T, P, a); } else { const slong m = (a + b) / 2; fmpz_t RP, RB, RT; _padic_log_bsplit_series(P, B, T, x, a, m); fmpz_init(RP); fmpz_init(RB); fmpz_init(RT); _padic_log_bsplit_series(RP, RB, RT, x, m, b); fmpz_mul(RT, RT, P); fmpz_mul(T, T, RB); fmpz_addmul(T, RT, B); fmpz_mul(P, P, RP); fmpz_mul(B, B, RB); fmpz_clear(RP); fmpz_clear(RB); fmpz_clear(RT); } } /* Assumes that $y = 1 - x$ is such that $\log(x)$ converges. Assumes that $v = \ord_p(y)$ with $v < N$, which also forces $N$ to be positive. The result $z$ might not be reduced modulo $p^N$. Supports aliasing between $y$ and $z$. */ static void _padic_log_bsplit(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) { fmpz_t P, B, T; slong k, n; n = _padic_log_bound(v, N, p); n = FLINT_MAX(n, 2); fmpz_init(P); fmpz_init(B); fmpz_init(T); _padic_log_bsplit_series(P, B, T, y, 1, n); k = fmpz_remove(B, B, p); fmpz_pow_ui(P, p, k); fmpz_divexact(T, T, P); _padic_inv(B, B, p, N); fmpz_mul(z, T, B); fmpz_clear(P); fmpz_clear(B); fmpz_clear(T); } void _padic_log_balanced(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) { fmpz_t pv, pN, r, t, u; slong w; padic_inv_t S; fmpz_init(pv); fmpz_init(pN); fmpz_init(r); fmpz_init(t); fmpz_init(u); _padic_inv_precompute(S, p, N); fmpz_set(pv, p); fmpz_pow_ui(pN, p, N); fmpz_mod(t, y, pN); fmpz_zero(z); w = 1; while (!fmpz_is_zero(t)) { fmpz_mul(pv, pv, pv); fmpz_fdiv_qr(t, r, t, pv); if (!fmpz_is_zero(t)) { fmpz_mul(t, t, pv); fmpz_sub_ui(u, r, 1); fmpz_neg(u, u); _padic_inv_precomp(u, u, S); fmpz_mul(t, t, u); fmpz_mod(t, t, pN); } if (!fmpz_is_zero(r)) { _padic_log_bsplit(r, r, w, p, N); fmpz_sub(z, z, r); } w *= 2; } fmpz_mod(z, z, pN); fmpz_clear(pv); fmpz_clear(pN); fmpz_clear(r); fmpz_clear(t); fmpz_clear(u); _padic_inv_clear(S); } int padic_log_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx) { const fmpz *p = ctx->p; const slong N = padic_prec(rop); if (padic_val(op) < 0) { return 0; } else { fmpz_t x; int ans; fmpz_init(x); padic_get_fmpz(x, op, ctx); fmpz_sub_ui(x, x, 1); fmpz_neg(x, x); if (fmpz_is_zero(x)) { padic_zero(rop); ans = 1; } else { fmpz_t t; slong v; fmpz_init(t); v = fmpz_remove(t, x, p); fmpz_clear(t); if (v >= 2 || (!fmpz_equal_ui(p, 2) && v >= 1)) { if (v >= N) { padic_zero(rop); } else { _padic_log_balanced(padic_unit(rop), x, v, p, N); padic_val(rop) = 0; _padic_canonicalise(rop, ctx); } ans = 1; } else { ans = 0; } } fmpz_clear(x); return ans; } } flint-3.1.3/src/padic/log_rectangular.c000066400000000000000000000111361461254215100200200ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "padic.h" /* Carries out the finite series evaluation for the logarithm \begin{equation*} \sum_{i=1}^{n} a_i x^i = \sum_{j=0}^{\ceil{n/b} - 1} \Bigl( \sum_{i=1}^b a_{i+jb} x^i \Bigr) x^{jb} \end{equation*} where $a_i = 1/i$ with the choice $b = \floor{\sqrt{n}}$, all modulo $p^N$, where also $P = p^N$. Does not support aliasing. */ static void _padic_log_rectangular_series(fmpz_t z, const fmpz_t y, slong n, const fmpz_t p, slong N, const fmpz_t P0) { if (n <= 2) { if (n == 1) { fmpz_mod(z, y, P0); } else /* n == 2; z = y(1 + y/2) */ { if (fmpz_is_even(y)) { fmpz_fdiv_q_2exp(z, y, 1); } else /* => p and y are odd */ { fmpz_add(z, y, P0); fmpz_fdiv_q_2exp(z, z, 1); } fmpz_add_ui(z, z, 1); fmpz_mul(z, z, y); fmpz_mod(z, z, P0); } } else { const slong b = n_sqrt(n); const slong k = fmpz_fits_si(p) ? n_flog(n, fmpz_get_si(p)) : 0; slong i, j; fmpz_t c, f, t, P1; fmpz *ypow; ypow = _fmpz_vec_init(b + 1); fmpz_init(c); fmpz_init(f); fmpz_init(t); fmpz_init(P1); fmpz_pow_ui(P1, p, N + k); fmpz_one(ypow + 0); for (i = 1; i <= b; i++) { fmpz_mul(ypow + i, ypow + (i - 1), y); fmpz_mod(ypow + i, ypow + i, P1); } fmpz_zero(z); for (j = (n + (b - 1)) / b - 1; j >= 0; j--) { const slong hi = FLINT_MIN(b, n - j*b); slong w; /* Compute inner sum in c */ fmpz_rfac_uiui(f, 1 + j*b, hi); fmpz_zero(c); for (i = 1; i <= hi; i++) { fmpz_divexact_ui(t, f, i + j*b); fmpz_addmul(c, t, ypow + i); } /* Multiply c by p^k f^{-1} */ w = fmpz_remove(f, f, p); _padic_inv(f, f, p, N); if (w > k) { fmpz_pow_ui(t, p, w - k); fmpz_divexact(c, c, t); } else { fmpz_pow_ui(t, p, k - w); fmpz_mul(c, c, t); } fmpz_mul(c, c, f); /* Set z = z y^b + c */ fmpz_mul(t, z, ypow + b); fmpz_add(z, c, t); fmpz_mod(z, z, P1); } fmpz_pow_ui(f, p, k); fmpz_divexact(z, z, f); fmpz_clear(c); fmpz_clear(f); fmpz_clear(t); fmpz_clear(P1); _fmpz_vec_clear(ypow, b + 1); } } void _padic_log_rectangular(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) { const slong n = _padic_log_bound(v, N, p) - 1; fmpz_t pN; fmpz_init(pN); fmpz_pow_ui(pN, p, N); _padic_log_rectangular_series(z, y, n, p, N, pN); fmpz_sub(z, pN, z); fmpz_clear(pN); } int padic_log_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx) { const fmpz *p = ctx->p; const slong N = padic_prec(rop); if (padic_val(op) < 0) { return 0; } else { fmpz_t x; int ans; fmpz_init(x); padic_get_fmpz(x, op, ctx); fmpz_sub_ui(x, x, 1); fmpz_neg(x, x); if (fmpz_is_zero(x)) { padic_zero(rop); ans = 1; } else { fmpz_t t; slong v; fmpz_init(t); v = fmpz_remove(t, x, p); fmpz_clear(t); if (v >= 2 || (!fmpz_equal_ui(p, 2) && v >= 1)) { if (v >= N) { padic_zero(rop); } else { _padic_log_rectangular(padic_unit(rop), x, v, p, N); padic_val(rop) = 0; _padic_canonicalise(rop, ctx); } ans = 1; } else { ans = 0; } } fmpz_clear(x); return ans; } } flint-3.1.3/src/padic/log_satoh.c000066400000000000000000000045221461254215100166300ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "padic.h" #include "ulong_extras.h" void _padic_log_satoh(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) { if (N < 16) { _padic_log_rectangular(z, y, v, p, N); } else { const slong k = n_sqrt(N); fmpz_t t, pk, pNk; fmpz_init(t); fmpz_init(pk); fmpz_init(pNk); fmpz_pow_ui(pk, p, k); fmpz_pow_ui(pNk, p, N + k); fmpz_sub_ui(t, y, 1); fmpz_neg(t, t); fmpz_powm(t, t, pk, pNk); fmpz_sub_ui(t, t, 1); fmpz_neg(t, t); /* TODO: Improve suggested valuation */ _padic_log_rectangular(z, t, k + 1, p, N + k); fmpz_divexact(z, z, pk); fmpz_clear(t); fmpz_clear(pk); fmpz_clear(pNk); } } int padic_log_satoh(padic_t rop, const padic_t op, const padic_ctx_t ctx) { const fmpz *p = ctx->p; const slong N = padic_prec(rop); if (padic_val(op) < 0) { return 0; } else { fmpz_t y; int ans; fmpz_init(y); padic_get_fmpz(y, op, ctx); fmpz_sub_ui(y, y, 1); fmpz_neg(y, y); if (fmpz_is_zero(y)) { padic_zero(rop); ans = 1; } else { fmpz_t t; slong v; fmpz_init(t); v = fmpz_remove(t, y, ctx->p); fmpz_clear(t); if (v >= 2 || (!fmpz_equal_ui(p, 2) && v >= 1)) { if (v >= N) { padic_zero(rop); } else { _padic_log_satoh(padic_unit(rop), y, v, p, N); padic_val(rop) = 0; padic_reduce(rop, ctx); } ans = 1; } else { ans = 0; } } fmpz_clear(y); return ans; } } flint-3.1.3/src/padic/mul.c000066400000000000000000000015211461254215100154420ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_mul(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) { if (padic_is_zero(op1) || padic_is_zero(op2) || padic_val(op1) + padic_val(op2) >= padic_prec(rop)) { padic_zero(rop); } else { fmpz_mul(padic_unit(rop), padic_unit(op1), padic_unit(op2)); padic_val(rop) = padic_val(op1) + padic_val(op2); _padic_reduce(rop, ctx); } } flint-3.1.3/src/padic/neg.c000066400000000000000000000016061461254215100154220ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_neg(padic_t rop, const padic_t op, const padic_ctx_t ctx) { if (padic_is_zero(op) || padic_val(op) >= padic_prec(rop)) { padic_zero(rop); } else { fmpz_t pow; int alloc; padic_val(rop) = padic_val(op); alloc = _padic_ctx_pow_ui(pow, padic_prec(rop) - padic_val(rop), ctx); fmpz_sub(padic_unit(rop), pow, padic_unit(op)); if (alloc) fmpz_clear(pow); _padic_reduce(rop, ctx); } } flint-3.1.3/src/padic/pow_si.c000066400000000000000000000023771461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_pow_si(padic_t rop, const padic_t op, slong e, const padic_ctx_t ctx) { if (e == 0) { padic_one(rop); } else if (padic_is_zero(op) || e * padic_val(op) >= padic_prec(rop)) { padic_zero(rop); } else { fmpz_t pow; int alloc; padic_val(rop) = e * padic_val(op); alloc = _padic_ctx_pow_ui(pow, padic_prec(rop) - padic_val(rop), ctx); if (e > 0) { fmpz_powm_ui(padic_unit(rop), padic_unit(op), e, pow); } else /* e < 0 */ { /* u^{-1} to precision (N - v) */ _padic_inv(padic_unit(rop), padic_unit(op), ctx->p, padic_prec(rop) - padic_val(rop)); fmpz_powm_ui(padic_unit(rop), padic_unit(rop), -e, pow); } if (alloc) fmpz_clear(pow); } } flint-3.1.3/src/padic/profile/000077500000000000000000000000001461254215100161425ustar00rootroot00000000000000flint-3.1.3/src/padic/profile/p-exp_balanced_2.c000066400000000000000000000046421461254215100213770ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic exponential method, balanced. We consider the set-up with p = 2, N = 2^i, i = 0, ..., 19, and compute the exponential of d = 4 a, a = 3^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 100000000, 100000000, 1000000, 100000, 100000, 100000, 10000, 10000, 10000, 10000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1, 1 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic exponential (balanced).\n"); fflush(stdout); for (l = 0; l < len; l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t d, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 2); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(d); padic_init(z); if (n > 1) { fmpz_t f = {WORD(3)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n - 2); fmpz_pow_ui(padic_unit(d), f, 3 * n); fmpz_mod(padic_unit(d), padic_unit(d), pow); padic_val(d) = 2; fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_exp_balanced(z, d, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %9ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(d); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-exp_balanced_p.c000066400000000000000000000046351461254215100214770ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic exponential method, balanced. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the exponential of d = 17 a, a = 3^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 100000000, 1000000, 100000, 100000, 100000, 10000, 10000, 10000, 10000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1, 1, 1 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic exponential (balanced).\n"); fflush(stdout); for (l = 0; l < len; l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t d, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(d); padic_init(z); if (n > 1) { fmpz_t f = {WORD(3)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n - 1); fmpz_pow_ui(padic_unit(d), f, 3 * n); fmpz_mod(padic_unit(d), padic_unit(d), pow); padic_val(d) = 1; fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_exp_balanced(z, d, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %9ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(d); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-exp_rectangular.c000066400000000000000000000046641461254215100217400ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic exponential method, rectangular. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the exponential of d = 17 a, a = 3^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 100000000, 1000000, 1000000, 1000000, 100000, 100000, 10000, 10000, 10000, 1000, 100, 100, 10, 1, 1, 1, 1, 1, 1, 1 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic exponential (rectangular).\n"); fflush(stdout); for (l = 0; l < FLINT_MIN(17, len); l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t d, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(d); padic_init(z); if (n > 1) { fmpz_t f = {WORD(3)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n - 1); fmpz_pow_ui(padic_unit(d), f, 3 * n); fmpz_mod(padic_unit(d), padic_unit(d), pow); padic_val(d) = 1; fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_exp_rectangular(z, d, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %9ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(d); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-inv.c000066400000000000000000000045051461254215100173430ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic inversion routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and invert a = 3^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { slong l, len = 20; slong runs[] = { 10000000, 1000000, 1000000, 1000000, 1000000, 100000, 100000, 100000, 100000, 10000, 10000, 1000, 1000, 1000, 10, 10, 10, 10, 10, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for p-adic inversion.\n"); fflush(stdout); for (l = 0; l < len; l++) { slong n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t a, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(a); padic_init(z); { fmpz_t f = {WORD(3)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(padic_unit(a), f, 3 * n); fmpz_mod(padic_unit(a), padic_unit(a), pow); fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_inv(z, a, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(a); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-log_balanced.c000066400000000000000000000056041461254215100211420ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic exponential method, balanced. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the logarithm of e = 17 a + 1, a = 3^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 10000000, 1000000, 100000, 100000, 100000, 10000, 10000, 10000, 1000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1, 1, 1 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic logarithm (balanced).\n"); fflush(stdout); for (l = 0; l < len; l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t e, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(e); padic_init(z); { fmpz_t f = {WORD(3)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(padic_unit(e), f, 3 * n); fmpz_mul_ui(padic_unit(e), padic_unit(e), 17); fmpz_add_ui(padic_unit(e), padic_unit(e), 1); fmpz_mod(padic_unit(e), padic_unit(e), pow); fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_log_balanced(z, e, ctx); padic_zero(z); } c1 = clock(); padic_log_balanced(z, e, ctx); padic_exp_balanced(z, z, ctx); if (!padic_equal(e, z)) { flint_printf("FAIL:\n"); flint_printf("e = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("z = "), padic_print(z, ctx), flint_printf("\n"); flint_printf("p = %wd\n", *p), flint_printf("\n"); flint_printf("N = %wd\n", n), flint_printf("\n"); flint_abort(); } cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(e); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-log_rectangular.c000066400000000000000000000056371461254215100217260ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic exponential method, rectangular. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the logarithm of e = 17 a + 1, a = 3^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 10000000, 1000000, 1000000, 100000, 100000, 10000, 10000, 10000, 1000, 1000, 100, 100, 10, 1, 1, 1, 1, 1, 1, 1 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic logarithm (rectangular).\n"); fflush(stdout); for (l = 0; l < FLINT_MIN(16, len); l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t e, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(e); padic_init(z); { fmpz_t f = {WORD(3)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(padic_unit(e), f, 3 * n); fmpz_mul_ui(padic_unit(e), padic_unit(e), 17); fmpz_add_ui(padic_unit(e), padic_unit(e), 1); fmpz_mod(padic_unit(e), padic_unit(e), pow); fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_log_rectangular(z, e, ctx); padic_zero(z); } c1 = clock(); padic_log_rectangular(z, e, ctx); padic_exp_rectangular(z, z, ctx); if (!padic_equal(e, z)) { flint_printf("FAIL:\n"); flint_printf("e = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("z = "), padic_print(z, ctx), flint_printf("\n"); flint_printf("p = %wd\n", *p), flint_printf("\n"); flint_printf("N = %wd\n", n), flint_printf("\n"); flint_abort(); } cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(e); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-mul.c000066400000000000000000000050071461254215100173420ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic multiplication routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and multiply a = 3^{3 N}, b = 5^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 10000000, 10000000, 10000000, 10000000, 1000000, 1000000, 1000000, 1000000, 100000, 100000, 100000, 10000, 10000, 1000, 1000, 100, 100, 10, 10, 10 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic multiplication.\n"); fflush(stdout); for (l = 0; l < len; l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t a, b, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(a); padic_init(b); padic_init(z); { fmpz_t f = {WORD(3)}, g = {WORD(5)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(padic_unit(a), f, 3 * n); fmpz_pow_ui(padic_unit(b), g, 3 * n); fmpz_mod(padic_unit(a), padic_unit(a), pow); fmpz_mod(padic_unit(b), padic_unit(b), pow); fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_mul(z, a, b, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(a); padic_clear(b); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-sqrt.c000066400000000000000000000047641461254215100175470ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic square root routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute a square root of b = a^2, a = 3^{3 N} mod p^N. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 1000000, 1000000, 1000000, 1000000, 1000000, 100000, 100000, 100000, 100000, 10000, 10000, 1000, 1000, 1000, 10, 10, 10, 10, 10, 1 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic square root.\n"); fflush(stdout); for (l = 0; l < len; l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t a, b, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(a); padic_init(b); padic_init(z); { fmpz_t f = {WORD(3)}, pow; fmpz_init(pow); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(padic_unit(a), f, 3 * n); fmpz_mod(padic_unit(a), padic_unit(a), pow); fmpz_pow_ui(padic_unit(b), padic_unit(a), 2); fmpz_mod(padic_unit(b), padic_unit(b), pow); fmpz_clear(pow); } c0 = clock(); for (r = runs[l]; (r); r--) { padic_sqrt(z, b, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(a); padic_clear(b); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/profile/p-teichmuller.c000066400000000000000000000042211461254215100210570ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the p-adic Teichmuller routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the Teichmuller lift of c = 3. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic.h" int main(void) { long l, len = 20; long runs[] = { 1000000, 1000000, 1000000, 1000000, 100000, 100000, 100000, 100000, 10000, 10000, 10000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1 }; long N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; long T[20] = {0}; flint_printf("Benchmark for p-adic Teichmuller.\n"); fflush(stdout); for (l = 0; l < len; l++) { long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t c, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT); padic_init(c); padic_init(z); fmpz_set_ui(padic_unit(c), 3); c0 = clock(); for (r = runs[l]; (r); r--) { padic_teichmuller(z, c, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %7ld, %wd\n", l, cputime, runs[l], T[l]); padic_clear(c); padic_clear(z); fmpz_clear(p); padic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/padic/randtest.c000066400000000000000000000037141461254215100164770ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #define PADIC_RANDTEST_TRIES 10 void padic_randtest(padic_t rop, flint_rand_t state, const padic_ctx_t ctx) { const slong N = padic_prec(rop); slong min, max; fmpz_t pow; int alloc; if (N > 0) { min = - ((N + 9) / 10); max = N; } else if (N < 0) { min = N - ((-N + 9) / 10); max = N; } else /* ctx->N == 0 */ { min = -10; max = 0; } padic_val(rop) = n_randint(state, max - min) + min; alloc = _padic_ctx_pow_ui(pow, N - padic_val(rop), ctx); fmpz_randm(padic_unit(rop), state, pow); _padic_canonicalise(rop, ctx); if (alloc) fmpz_clear(pow); } void padic_randtest_not_zero(padic_t rop, flint_rand_t state, const padic_ctx_t ctx) { slong i; padic_randtest(rop, state, ctx); for (i = 1; !padic_is_zero(rop) && i < PADIC_RANDTEST_TRIES; i++) padic_randtest(rop, state, ctx); if (padic_is_zero(rop)) { fmpz_one(padic_unit(rop)); padic_val(rop) = padic_prec(rop) - 1; } } void padic_randtest_int(padic_t rop, flint_rand_t state, const padic_ctx_t ctx) { const slong N = padic_prec(rop); if (N <= 0) { padic_zero(rop); } else { fmpz_t pow; int alloc; padic_val(rop) = n_randint(state, N); alloc = _padic_ctx_pow_ui(pow, N - padic_val(rop), ctx); fmpz_randm(padic_unit(rop), state, pow); _padic_canonicalise(rop, ctx); if (alloc) fmpz_clear(pow); } } flint-3.1.3/src/padic/reduce.c000066400000000000000000000017601461254215100161210ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void _padic_reduce(padic_t rop, const padic_ctx_t ctx) { if (!fmpz_is_zero(padic_unit(rop))) { if (padic_val(rop) < padic_prec(rop)) { int c; fmpz_t pow; c = _padic_ctx_pow_ui(pow, padic_prec(rop) - padic_val(rop), ctx); fmpz_mod(padic_unit(rop), padic_unit(rop), pow); if (c) fmpz_clear(pow); } else { padic_zero(rop); } } } void padic_reduce(padic_t rop, const padic_ctx_t ctx) { _padic_canonicalise(rop, ctx); _padic_reduce(rop, ctx); } flint-3.1.3/src/padic/set.c000066400000000000000000000011241461254215100154370ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_set(padic_t rop, const padic_t op, const padic_ctx_t ctx) { fmpz_set(padic_unit(rop), padic_unit(op)); padic_val(rop) = padic_val(op); _padic_reduce(rop, ctx); } flint-3.1.3/src/padic/set_fmpq.c000066400000000000000000000022251461254215100164650ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "padic.h" void padic_set_fmpq(padic_t rop, const fmpq_t op, const padic_ctx_t ctx) { if (fmpq_is_zero(op)) { padic_zero(rop); } else { fmpq_t t; fmpq_init(t); padic_val(rop) = fmpz_remove(fmpq_numref(t), fmpq_numref(op), ctx->p); padic_val(rop) -= fmpz_remove(fmpq_denref(t), fmpq_denref(op), ctx->p); if (padic_val(rop) >= padic_prec(rop)) { padic_zero(rop); } else { _padic_inv(fmpq_denref(t), fmpq_denref(t), ctx->p, padic_prec(rop) - padic_val(rop)); fmpz_mul(padic_unit(rop), fmpq_numref(t), fmpq_denref(t)); _padic_reduce(rop, ctx); } fmpq_clear(t); } } flint-3.1.3/src/padic/set_fmpz.c000066400000000000000000000012401461254215100164720ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_set_fmpz(padic_t rop, const fmpz_t op, const padic_ctx_t ctx) { if (!fmpz_is_zero(op)) { padic_val(rop) = fmpz_remove(padic_unit(rop), op, ctx->p); _padic_reduce(rop, ctx); } else { padic_zero(rop); } } flint-3.1.3/src/padic/set_mpq.c000066400000000000000000000011371461254215100163200ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "padic.h" void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx) { fmpq_t t; fmpq_init(t); fmpq_set_mpq(t, op); padic_set_fmpq(rop, t, ctx); fmpq_clear(t); } flint-3.1.3/src/padic/set_mpz.c000066400000000000000000000011231461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_set_mpz(padic_t rop, const mpz_t op, const padic_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_set_mpz(t, op); padic_set_fmpz(rop, t, ctx); fmpz_clear(t); } flint-3.1.3/src/padic/set_si.c000066400000000000000000000010701461254215100161320ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_set_si(padic_t rop, slong op, const padic_ctx_t ctx) { fmpz_set_si(padic_unit(rop), op); padic_val(rop) = 0; padic_reduce(rop, ctx); } flint-3.1.3/src/padic/set_ui.c000066400000000000000000000021031461254215100161320ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" void padic_set_ui(padic_t rop, ulong op, const padic_ctx_t ctx) { if (op == 0) { padic_zero(rop); } else if (fmpz_cmp_ui(ctx->p, op) > 0) { fmpz_set_ui(padic_unit(rop), op); padic_val(rop) = 0; } else { ulong p = fmpz_get_ui(ctx->p), q, r; /* Remove factors of p */ padic_val(rop) = 0; r = n_divrem2_precomp(&q, op, p, ctx->pinv); while (r == 0) { op = q; padic_val(rop)++; r = n_divrem2_precomp(&q, op, p, ctx->pinv); } fmpz_set_ui(padic_unit(rop), op); _padic_reduce(rop, ctx); } } flint-3.1.3/src/padic/shift.c000066400000000000000000000013551461254215100157670ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_shift(padic_t rop, const padic_t op, slong v, const padic_ctx_t ctx) { if (padic_is_zero(op) || (padic_val(op) + v >= padic_prec(rop))) { padic_zero(rop); } else { fmpz_set(padic_unit(rop), padic_unit(op)); padic_val(rop) = padic_val(op) + v; _padic_reduce(rop, ctx); } } flint-3.1.3/src/padic/sqrt.c000066400000000000000000000130261461254215100156410ustar00rootroot00000000000000/* Copyright (C) 2011 Jan Tuitman Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" /* Returns whether \code{op} has a square root modulo $p^N$ and if so sets \code{rop} to such an element. Assumes that \code{op} is a unit modulo $p^N$. Assumes $p$ is an odd prime. In the current implementation, allows aliasing. */ static int _padic_sqrt_p(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) { int ans; if (N == 1) { ans = fmpz_sqrtmod(rop, op, p); return ans; } else { slong *e, i, n; fmpz *W, *pow, *u; e = _padic_lifts_exps(&n, N); W = _fmpz_vec_init(2 + 2 * n); pow = W + 2; u = W + (2 + n); _padic_lifts_pows(pow, e, n, p); /* Compute reduced units */ { fmpz_mod(u, op, pow); } for (i = 1; i < n; i++) { fmpz_mod(u + i, u + (i - 1), pow + i); } /* Run Newton iteration for the inverse square root, using the update formula z := z - z (u z^2 - 1) / 2 for all but the last step. The last step is replaced with b := u z mod p^{N'} z := b + z (u - b^2) / 2 mod p^{N}. */ i = n - 1; { ans = fmpz_sqrtmod(rop, u + i, p); if (!ans) goto exit; fmpz_invmod(rop, rop, p); } for (i--; i >= 1; i--) { fmpz_mul(W, rop, rop); fmpz_mul(W + 1, u + i, W); fmpz_sub_ui(W + 1, W + 1, 1); if (fmpz_is_odd(W + 1)) fmpz_add(W + 1, W + 1, pow + i); fmpz_fdiv_q_2exp(W + 1, W + 1, 1); fmpz_mul(W, W + 1, rop); fmpz_sub(rop, rop, W); fmpz_mod(rop, rop, pow + i); } { fmpz_mul(W, u + 1, rop); fmpz_mul(W + 1, W, W); fmpz_sub(W + 1, u + 0, W + 1); if (fmpz_is_odd(W + 1)) fmpz_add(W + 1, W + 1, pow + 0); fmpz_fdiv_q_2exp(W + 1, W + 1, 1); fmpz_mul(rop, rop, W + 1); fmpz_add(rop, W, rop); fmpz_mod(rop, rop, pow + 0); } exit: flint_free(e); _fmpz_vec_clear(W, 2 + 2 * n); return ans; } } /* Returns whether \code{op} has a square root modulo $2^N$ and if so sets \code{rop} to such an element. Assumes that \code{op} is a unit modulo $2^N$. In the current implementation, allows aliasing. */ static int _padic_sqrt_2(fmpz_t rop, const fmpz_t op, slong N) { if (fmpz_fdiv_ui(op, 8) != 1) return 0; if (N <= 3) { fmpz_one(rop); } else { slong *e, i, n; fmpz *W, *u; i = FLINT_CLOG2(N); /* Compute sequence of exponents */ e = flint_malloc((i + 2) * sizeof(slong)); for (e[i = 0] = N; e[i] > 3; i++) e[i + 1] = (e[i] + 3) / 2; n = i + 1; W = _fmpz_vec_init(2 + n); u = W + 2; /* Compute reduced units */ { fmpz_fdiv_r_2exp(u, op, e[0]); } for (i = 1; i < n; i++) { fmpz_fdiv_r_2exp(u + i, u + (i - 1), e[i]); } /* Run Newton iteration */ fmpz_one(rop); for (i = n - 2; i >= 1; i--) /* z := z - z (a z^2 - 1) / 2 */ { fmpz_mul(W, rop, rop); fmpz_mul(W + 1, u + i, W); fmpz_sub_ui(W + 1, W + 1, 1); fmpz_fdiv_q_2exp(W + 1, W + 1, 1); fmpz_mul(W, W + 1, rop); fmpz_sub(rop, rop, W); fmpz_fdiv_r_2exp(rop, rop, e[i]); } { fmpz_mul(W, u + 1, rop); fmpz_mul(W + 1, W, W); fmpz_sub(W + 1, u + 0, W + 1); fmpz_fdiv_q_2exp(W + 1, W + 1, 1); fmpz_mul(rop, rop, W + 1); fmpz_add(rop, W, rop); } fmpz_fdiv_r_2exp(rop, rop, e[0]); flint_free(e); _fmpz_vec_clear(W, 2 + n); } return 1; } int _padic_sqrt(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) { if (fmpz_equal_ui(p, 2)) { return _padic_sqrt_2(rop, op, N); } else { return _padic_sqrt_p(rop, op, p, N); } } int padic_sqrt(padic_t rop, const padic_t op, const padic_ctx_t ctx) { if (padic_is_zero(op)) { padic_zero(rop); return 1; } if (padic_val(op) & WORD(1)) { return 0; } padic_val(rop) = padic_val(op) / 2; /* In this case, if there is a square root it will be zero modulo $p^N$. We only have to establish whether or not the element \code{op} is a square. */ if (padic_val(rop) >= padic_prec(rop)) { int ans; if (fmpz_equal_ui(ctx->p, 2)) { ans = (fmpz_fdiv_ui(padic_unit(op), 8) == 1); } else { ans = fmpz_sqrtmod(padic_unit(rop), padic_unit(op), ctx->p); } padic_zero(rop); return ans; } return _padic_sqrt(padic_unit(rop), padic_unit(op), ctx->p, padic_prec(rop) - padic_val(rop)); } flint-3.1.3/src/padic/sub.c000066400000000000000000000054461461254215100154500ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" void padic_sub(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx) { if (padic_prec(rop) <= FLINT_MIN(padic_val(op1), padic_val(op2))) { padic_zero(rop); return; } if (padic_is_zero(op1)) { padic_neg(rop, op2, ctx); } else if (padic_is_zero(op2)) { padic_set(rop, op1, ctx); } else { if (padic_val(op1) == padic_val(op2)) { fmpz_sub(padic_unit(rop), padic_unit(op1), padic_unit(op2)); padic_val(rop) = padic_val(op1); _padic_canonicalise(rop, ctx); if (padic_prec(rop) <= padic_val(rop)) { padic_zero(rop); return; } } else if (padic_val(op1) < padic_val(op2)) { fmpz_t f; fmpz_init(f); fmpz_pow_ui(f, ctx->p, padic_val(op2) - padic_val(op1)); if (rop != op2) { fmpz_set(padic_unit(rop), padic_unit(op1)); fmpz_submul(padic_unit(rop), f, padic_unit(op2)); } else { fmpz_mul(padic_unit(rop), f, padic_unit(op2)); fmpz_sub(padic_unit(rop), padic_unit(rop), padic_unit(op1)); fmpz_neg(padic_unit(rop), padic_unit(rop)); } fmpz_clear(f); padic_val(rop) = padic_val(op1); } else /* padic_val(op1) > padic_val(op2) */ { fmpz_t f; fmpz_init(f); fmpz_pow_ui(f, ctx->p, padic_val(op1) - padic_val(op2)); if (rop != op1) { fmpz_neg(padic_unit(rop), padic_unit(op2)); fmpz_addmul(padic_unit(rop), f, padic_unit(op1)); } else { fmpz_mul(padic_unit(rop), f, padic_unit(op1)); fmpz_sub(padic_unit(rop), padic_unit(rop), padic_unit(op2)); } fmpz_clear(f); padic_val(rop) = padic_val(op2); } { int alloc; fmpz_t pow; alloc = _padic_ctx_pow_ui(pow, padic_prec(rop) - padic_val(rop), ctx); fmpz_mod(padic_unit(rop), padic_unit(rop), pow); if (fmpz_is_zero(padic_unit(rop))) padic_val(rop) = 0; if (alloc) fmpz_clear(pow); } } } flint-3.1.3/src/padic/teichmuller.c000066400000000000000000000050111461254215100171600ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) { if (fmpz_equal_ui(p, 2)) { fmpz_one(rop); } else if (N == 1) { fmpz_mod(rop, op, p); } else { slong *a, i, n; fmpz *pow, *u; fmpz_t s, t; fmpz_t inv; fmpz_t pm1; a = _padic_lifts_exps(&n, N); pow = _fmpz_vec_init(2 * n); u = pow + n; _padic_lifts_pows(pow, a, n, p); fmpz_init(s); fmpz_init(t); fmpz_init(inv); fmpz_init(pm1); fmpz_sub_ui(pm1, p, 1); /* Compute reduced units for (p-1) */ { fmpz_mod(u + 0, pm1, pow + 0); } for (i = 1; i < n; i++) { fmpz_mod(u + i, u + (i - 1), pow + i); } /* Run Newton iteration */ i = n - 1; { fmpz_mod(rop, op, pow + i); fmpz_set(inv, pm1); } for (i--; i >= 0; i--) { /* Lift rop */ fmpz_powm(s, rop, p, pow + i); fmpz_sub(s, s, rop); fmpz_mul(t, s, inv); fmpz_sub(rop, rop, t); fmpz_mod(rop, rop, pow + i); /* Lift inv */ if (i > 0) { fmpz_mul(s, inv, inv); fmpz_mul(t, u + i, s); fmpz_mul_2exp(inv, inv, 1); fmpz_sub(inv, inv, t); fmpz_mod(inv, inv, pow + i); } } fmpz_clear(s); fmpz_clear(t); fmpz_clear(inv); fmpz_clear(pm1); _fmpz_vec_clear(pow, 2 * n); flint_free(a); } } void padic_teichmuller(padic_t rop, const padic_t op, const padic_ctx_t ctx) { if (padic_val(op) < 0) { flint_throw(FLINT_ERROR, "Exception (padic_teichmuller). op is not a p-adic integer.\n"); } if (padic_is_zero(op) || padic_val(op) > 0 || padic_prec(rop) <= 0) { padic_zero(rop); } else { _padic_teichmuller(padic_unit(rop), padic_unit(op), ctx->p, padic_prec(rop)); padic_val(rop) = 0; } } flint-3.1.3/src/padic/test/000077500000000000000000000000001461254215100154615ustar00rootroot00000000000000flint-3.1.3/src/padic/test/main.c000066400000000000000000000037641461254215100165630ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-div.c" #include "t-exp_balanced.c" #include "t-exp.c" #include "t-exp_rectangular.c" #include "t-get_set_fmpz.c" #include "t-get_set_mpq.c" #include "t-get_set_mpz.c" #include "t-get_str.c" #include "t-inv.c" #include "t-log_balanced.c" #include "t-log.c" #include "t-log_rectangular.c" #include "t-log_satoh.c" #include "t-mul.c" #include "t-neg.c" #include "t-pow_si.c" #include "t-randtest.c" #include "t-shift.c" #include "t-sqrt.c" #include "t-sub.c" #include "t-teichmuller.c" #include "t-val_fac.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(padic_add), TEST_FUNCTION(padic_div), TEST_FUNCTION(padic_exp_balanced), TEST_FUNCTION(padic_exp), TEST_FUNCTION(padic_exp_rectangular), TEST_FUNCTION(padic_get_set_fmpz), TEST_FUNCTION(padic_get_set_mpq), TEST_FUNCTION(padic_get_set_mpz), TEST_FUNCTION(padic_get_str), TEST_FUNCTION(padic_inv), TEST_FUNCTION(padic_log_balanced), TEST_FUNCTION(padic_log), TEST_FUNCTION(padic_log_rectangular), TEST_FUNCTION(padic_log_satoh), TEST_FUNCTION(padic_mul), TEST_FUNCTION(padic_neg), TEST_FUNCTION(padic_pow_si), TEST_FUNCTION(padic_randtest), TEST_FUNCTION(padic_shift), TEST_FUNCTION(padic_sqrt), TEST_FUNCTION(padic_sub), TEST_FUNCTION(padic_teichmuller), TEST_FUNCTION(padic_val_fac) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/padic/test/t-add.c000066400000000000000000000173231461254215100166240ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_add, state) { int i, result; /* Check aliasing: a = a + b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(d, a, b, ctx); padic_add(a, a, b, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: b = a + b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(d, a, b, ctx); padic_add(b, a, b, ctx); result = (padic_equal(b, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: a = a + a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_add(d, a, a, ctx); padic_add(a, a, a, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a + b == b + a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(c, a, b, ctx); padic_add(d, b, a, ctx); result = (padic_equal(c, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that (a + b) + c == a + (b + c) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_randtest(c, state, ctx); padic_add(d, a, b, ctx); padic_add(d, d, c, ctx); padic_add(e, b, c, ctx); padic_add(e, a, e, ctx); result = (padic_equal(d, e)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = "), padic_print(e, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a + 0 == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_zero(b); padic_add(b, a, b, ctx); result = (padic_equal(a, b)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-div.c000066400000000000000000000122141461254215100166500ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_div, state) { int i, result; /* Check aliasing: a = a / b (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest_not_zero(b, state, ctx); padic_div(d, a, b, ctx); padic_div(a, a, b, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL (aliasing a = a/b) :\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: b = a / b (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest_not_zero(b, state, ctx); padic_div(d, a, b, ctx); padic_div(b, a, b, ctx); result = (padic_equal(b, d)); if (!result) { flint_printf("FAIL (aliasing b = a/b):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: a = a / a (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest_not_zero(a, state, ctx); padic_div(d, a, a, ctx); padic_div(a, a, a, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL (aliasing a = a/a):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a / 1 == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(c, N); padic_init2(b, FLINT_MAX(N, 1)); padic_randtest(a, state, ctx); padic_one(b); padic_div(c, a, b, ctx); result = (padic_equal(a, c)); if (!result) { flint_printf("FAIL (a/1 == a):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-exp.c000066400000000000000000000157521461254215100166740ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_exp, state) { int i, result; /** p == 2 *******************************************************************/ /* Check aliasing: a = exp(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); ans2 = padic_exp(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(c, a, b, ctx); ans1 = padic_exp(d, a, ctx); ans2 = padic_exp(e, b, ctx); padic_mul(f, d, e, ctx); ans3 = padic_exp(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } /** p > 2 ********************************************************************/ /* Check aliasing: a = exp(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); ans2 = padic_exp(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(c, a, b, ctx); ans1 = padic_exp(d, a, ctx); ans2 = padic_exp(e, b, ctx); padic_mul(f, d, e, ctx); ans3 = padic_exp(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-exp_balanced.c000066400000000000000000000161151461254215100204770ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_exp_balanced, state) { int i, result; /** p == 2 *******************************************************************/ /* Check aliasing: a = exp(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); ans1 = padic_exp_balanced(b, a, ctx); ans2 = padic_exp_balanced(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(c, a, b, ctx); ans1 = padic_exp_balanced(d, a, ctx); ans2 = padic_exp_balanced(e, b, ctx); padic_mul(f, d, e, ctx); ans3 = padic_exp_balanced(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } /** p > 2 ********************************************************************/ /* Check aliasing: a = exp(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); ans1 = padic_exp_balanced(b, a, ctx); ans2 = padic_exp_balanced(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(c, a, b, ctx); ans1 = padic_exp_balanced(d, a, ctx); ans2 = padic_exp_balanced(e, b, ctx); padic_mul(f, d, e, ctx); ans3 = padic_exp_balanced(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-exp_rectangular.c000066400000000000000000000161561461254215100212620ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_exp_rectangular, state) { int i, result; /** p == 2 *******************************************************************/ /* Check aliasing: a = exp(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); ans1 = padic_exp_rectangular(b, a, ctx); ans2 = padic_exp_rectangular(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(c, a, b, ctx); ans1 = padic_exp_rectangular(d, a, ctx); ans2 = padic_exp_rectangular(e, b, ctx); padic_mul(f, d, e, ctx); ans3 = padic_exp_rectangular(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } /** p > 2 ********************************************************************/ /* Check aliasing: a = exp(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); ans1 = padic_exp_rectangular(b, a, ctx); ans2 = padic_exp_rectangular(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_add(c, a, b, ctx); ans1 = padic_exp_rectangular(d, a, ctx); ans2 = padic_exp_rectangular(e, b, ctx); padic_mul(f, d, e, ctx); ans3 = padic_exp_rectangular(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-get_set_fmpz.c000066400000000000000000000033071461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_get_set_fmpz, state) { int i, result; /* Check that Zp(ZZ(x)) == x. */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; fmpz_t c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); fmpz_init(c); padic_randtest_int(a, state, ctx); padic_get_fmpz(c, a, ctx); padic_set_fmpz(b, c, ctx); result = (padic_equal(a, b)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-get_set_mpq.c000066400000000000000000000032401461254215100203740ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_get_set_mpq, state) { int i, result; /* Check that Zp(QQ(x)) == x. */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; mpq_t c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); mpq_init(c); padic_randtest(a, state, ctx); padic_get_mpq(c, a, ctx); padic_set_mpq(b, c, ctx); result = (padic_equal(a, b)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(b, ctx), flint_printf("\n"); gmp_printf("b = %Qd\n", b); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); mpq_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-get_set_mpz.c000066400000000000000000000032361461254215100204120ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_get_set_mpz, state) { int i, result; /* Check that Zp(QQ(x)) == x. */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; mpz_t c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); mpz_init(c); padic_randtest_int(a, state, ctx); padic_get_mpz(c, a, ctx); padic_set_mpz(b, c, ctx); result = (padic_equal(a, b)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); gmp_printf("c = %Zd\n", c); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); mpz_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-get_str.c000066400000000000000000000033511461254215100175370ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq.h" #include "padic.h" #ifdef __GNUC__ # define strcmp __builtin_strcmp #else # include #endif TEST_FUNCTION_START(padic_get_str, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t x; fmpq_t y; char *s, *t; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_TERSE); padic_init2(x, N); fmpq_init(y); padic_randtest(x, state, ctx); padic_get_fmpq(y, x, ctx); s = padic_get_str(NULL, x, ctx); t = fmpq_get_str(NULL, 10, y); result = strcmp(s, t) == 0; if (!result) { flint_printf("FAIL:\n\n"); flint_printf("x = "), padic_print(x, ctx), flint_printf("\n"); flint_printf("y = "), fmpq_print(y), flint_printf("\n"); fflush(stdout); flint_abort(); } flint_free(s); flint_free(t); padic_clear(x); fmpq_clear(y); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-inv.c000066400000000000000000000130601461254215100166620ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_inv, state) { int i, result; /* PRIME p = 2 ***************************************************************/ /* Check aliasing: a = a^{-1} (mod p^N) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest_not_zero(a, state, ctx); padic_inv(d, a, ctx); padic_inv(a, a, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that correct only mod p^{N} */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; slong v; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest_not_zero(a, state, ctx); v = padic_val(a); if (-v < N) /* Otherwise, no precision left */ { slong N2 = N - FLINT_ABS(v); padic_prec(d) = N2; padic_inv(b, a, ctx); padic_mul(d, a, b, ctx); result = (padic_is_one(d)); if (!result) { flint_printf("FAIL (a * a^{-1} == 1):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* PRIME p > 2 ***************************************************************/ /* Check aliasing: a = a^{-1} (mod p^N) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest_not_zero(a, state, ctx); padic_inv(d, a, ctx); padic_inv(a, a, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that correct only mod p^{N} */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; slong v; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest_not_zero(a, state, ctx); v = padic_val(a); if (-v < N) /* Otherwise, no precision left */ { slong N2 = N - FLINT_ABS(v); padic_prec(d) = N2; padic_inv(b, a, ctx); padic_mul(d, a, b, ctx); result = (padic_is_one(d)); if (!result) { flint_printf("FAIL (a * a^{-1} == 1):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-log.c000066400000000000000000000234371461254215100166600ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" /* Defined in t-log.c, t-log_balanced.c, t-log_rectangular.c, t-log_satoh.c */ #ifndef __rand_prec #define __rand_prec __rand_prec /* Set-up. Currently we only test the logarithm for positive values of N. This is important as for negative N, exp(0) is 1, which is 0 mod p^N, and then log(0) does not converge. */ static slong __rand_prec(flint_rand_t state, slong i) { return n_randint(state, PADIC_TEST_PREC_MAX) + 1; } #endif TEST_FUNCTION_START(padic_log, state) { int i, result; /** p == 2 *******************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log(b, a, ctx); ans2 = padic_log(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log(d, a, ctx); ans2 = padic_log(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_ctx_clear(ctx); } /** p > 2 ********************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log(b, a, ctx); ans2 = padic_log(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; /* fmpz_init_set_ui(p, n_randtest_prime(state, 0)); */ fmpz_init_set_ui(p, n_randprime(state, 5, 1)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_one(c); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log(d, a, ctx); ans2 = padic_log(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); flint_printf("ans3 = %d\n", ans3); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-log_balanced.c000066400000000000000000000237171461254215100204720ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" /* Defined in t-log.c, t-log_balanced.c, t-log_rectangular.c, t-log_satoh.c */ #ifndef __rand_prec #define __rand_prec __rand_prec /* Set-up. Currently we only test the logarithm for positive values of N. This is important as for negative N, exp(0) is 1, which is 0 mod p^N, and then log(0) does not converge. */ static slong __rand_prec(flint_rand_t state, slong i) { return n_randint(state, PADIC_TEST_PREC_MAX) + 1; } #endif TEST_FUNCTION_START(padic_log_balanced, state) { int i, result; /** p == 2 *******************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log_balanced(b, a, ctx); ans2 = padic_log_balanced(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log_balanced(d, a, ctx); ans2 = padic_log_balanced(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log_balanced(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log_balanced(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_ctx_clear(ctx); } /** p > 2 ********************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log_balanced(b, a, ctx); ans2 = padic_log_balanced(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); /* fmpz_init_set_ui(p, n_randprime(state, 5, 1));*/ N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_one(c); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log_balanced(d, a, ctx); ans2 = padic_log_balanced(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log_balanced(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); flint_printf("ans3 = %d\n", ans3); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; /* fmpz_init_set_ui(p, n_randtest_prime(state, 0)); */ fmpz_init_set_ui(p, n_randprime(state, 5, 1)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log_balanced(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-log_rectangular.c000066400000000000000000000236731461254215100212510ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" /* Defined in t-log.c, t-log_balanced.c, t-log_rectangular.c, t-log_satoh.c */ #ifndef __rand_prec #define __rand_prec __rand_prec /* Set-up. Currently we only test the logarithm for positive values of N. This is important as for negative N, exp(0) is 1, which is 0 mod p^N, and then log(0) does not converge. */ static slong __rand_prec(flint_rand_t state, slong i) { return n_randint(state, PADIC_TEST_PREC_MAX) + 1; } #endif TEST_FUNCTION_START(padic_log_rectangular, state) { int i, result; /** p == 2 *******************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log_rectangular(b, a, ctx); ans2 = padic_log_rectangular(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log_rectangular(d, a, ctx); ans2 = padic_log_rectangular(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log_rectangular(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log_rectangular(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_ctx_clear(ctx); } /** p > 2 ********************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log_rectangular(b, a, ctx); ans2 = padic_log_rectangular(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_one(c); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log_rectangular(d, a, ctx); ans2 = padic_log_rectangular(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log_rectangular(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); flint_printf("ans3 = %d\n", ans3); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; /* fmpz_init_set_ui(p, n_randtest_prime(state, 0)); */ fmpz_init_set_ui(p, n_randprime(state, 5, 1)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log_rectangular(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-log_satoh.c000066400000000000000000000234531461254215100200540ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" /* Defined in t-log.c, t-log_balanced.c, t-log_rectangular.c, t-log_satoh.c */ #ifndef __rand_prec #define __rand_prec __rand_prec /* Set-up. Currently we only test the logarithm for positive values of N. This is important as for negative N, exp(0) is 1, which is 0 mod p^N, and then log(0) does not converge. */ static slong __rand_prec(flint_rand_t state, slong i) { return n_randint(state, PADIC_TEST_PREC_MAX) + 1; } #endif TEST_FUNCTION_START(padic_log_satoh, state) { int i, result; /** p == 2 *******************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log_satoh(b, a, ctx); ans2 = padic_log_satoh(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log_satoh(d, a, ctx); ans2 = padic_log_satoh(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log_satoh(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log_satoh(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_ctx_clear(ctx); } /** p > 2 ********************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; int ans1, ans2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_one(b); padic_add(a, a, b, ctx); ans1 = padic_log_satoh(b, a, ctx); ans2 = padic_log_satoh(a, a, ctx); result = (ans1 == ans2) && (!ans1 || padic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randprime(state, 5, 1)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_init2(f, N); padic_init2(g, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_one(c); padic_add(a, a, c, ctx); padic_one(c); padic_add(b, b, c, ctx); padic_mul(c, a, b, ctx); ans1 = padic_log_satoh(d, a, ctx); ans2 = padic_log_satoh(e, b, ctx); padic_add(f, d, e, ctx); ans3 = padic_log_satoh(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && padic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), padic_print(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), padic_print(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), padic_print(g, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); flint_printf("ans3 = %d\n", ans3); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); padic_clear(f); padic_clear(g); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; int ans1, ans2; fmpz_init_set_ui(p, n_randprime(state, 5, 1)); N = __rand_prec(state, i); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); ans1 = padic_exp(b, a, ctx); if (ans1) ans2 = padic_log_satoh(c, b, ctx); result = !ans1 || (ans1 == ans2 && padic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-mul.c000066400000000000000000000205331461254215100166660ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_mul, state) { int i, result; /* Check aliasing: a = a * b (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_mul(d, a, b, ctx); padic_mul(a, a, b, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL (alias a = a*b):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: b = a * b (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_mul(d, a, b, ctx); padic_mul(b, a, b, ctx); result = (padic_equal(b, d)); if (!result) { flint_printf("FAIL (alias b = a*b):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: a = a * a (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_mul(d, a, a, ctx); padic_mul(a, a, a, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL (alias a = a*a):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a * b == b * a (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_mul(c, a, b, ctx); padic_mul(d, b, a, ctx); result = (padic_equal(c, d)); if (!result) { flint_printf("FAIL (a*b = b*a):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that (a * b) * c == a * (b * c) (mod p^N) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, lhs1, lhs2, rhs1, rhs2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_randtest(c, state, ctx); padic_init2(lhs1, N - padic_val(c)); padic_init2(lhs2, N); padic_init2(rhs1, N - padic_val(a)); padic_init2(rhs2, N); padic_mul(lhs1, a, b, ctx); padic_mul(lhs2, lhs1, c, ctx); padic_mul(rhs1, b, c, ctx); padic_mul(rhs2, a, rhs1, ctx); result = (padic_equal(lhs2, rhs2)); if (!result) { flint_printf("FAIL ((a*b)*c = a*(b*c) mod p^N):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("lhs1 = "), padic_print(lhs1, ctx), flint_printf("\n"); flint_printf("lhs2 = "), padic_print(lhs2, ctx), flint_printf("\n"); flint_printf("rhs1 = "), padic_print(rhs1, ctx), flint_printf("\n"); flint_printf("rhs2 = "), padic_print(rhs2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(lhs1); padic_clear(lhs2); padic_clear(rhs1); padic_clear(rhs2); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a * 1 == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, 1); padic_init2(c, N); padic_randtest(a, state, ctx); padic_one(b); padic_mul(c, a, b, ctx); result = (padic_equal(a, c)); if (!result) { flint_printf("FAIL (a*1 = a):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-neg.c000066400000000000000000000070451461254215100166450ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_neg, state) { int i, result; /* Check aliasing: a = - a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_neg(d, a, ctx); padic_neg(a, a, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that - (- a) == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_neg(d, a, ctx); padic_neg(d, d, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a + (-a) == 0 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_neg(b, a, ctx); padic_add(b, a, b, ctx); result = (padic_is_zero(b)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-pow_si.c000066400000000000000000000153331461254215100173730ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "fmpq.h" #include "padic.h" TEST_FUNCTION_START(padic_pow_si, state) { int i, result; /* Check aliasing */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; slong e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); padic_set(b, a, ctx); e = z_randint(state, 20); padic_pow_si(c, b, e, ctx); padic_pow_si(b, b, e, ctx); result = (padic_equal(b, c)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } /* Compare with multiplication for e >= 0 and val(a) >= 0 */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; slong j, e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest_int(a, state, ctx); padic_val(a) = FLINT_ABS(padic_val(a)); e = n_randint(state, 50); padic_pow_si(b, a, e, ctx); padic_one(c); for (j = 0; j < e; j++) padic_mul(c, c, a, ctx); result = (padic_equal(b, c)); if (!result) { flint_printf("FAIL (cmp with multiplication):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } /* Compare with fmpq, check precision */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong N, N2; padic_ctx_t ctx; padic_t a, b, c; fmpq_t s, t; slong e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); fmpq_init(s); fmpq_init(t); padic_randtest(a, state, ctx); e = n_randint(state, 50) + 1; N2 = N + (e - 1) * padic_val(a); padic_prec(b) = N2; padic_prec(c) = N2; padic_pow_si(b, a, e, ctx); padic_get_fmpq(s, a, ctx); fmpq_pow_si(t, s, e); padic_set_fmpq(c, t, ctx); result = (padic_equal(b, c)); if (!result) { flint_printf("FAIL (cmp with fmpq):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("s = "), fmpq_print(s), flint_printf("\n"); flint_printf("t = "), fmpq_print(t), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpq_clear(s); fmpq_clear(t); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check precision */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong N_lo, N_hi, N_res; padic_ctx_t ctx; padic_t a, b, c, d, t; slong e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N_lo = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; N_hi = N_lo + n_randint(state, 20); padic_ctx_init(ctx, p, FLINT_MAX(0, N_lo-10), FLINT_MAX(0, N_hi+10), PADIC_SERIES); padic_init2(a, N_hi); padic_init2(b, N_hi); padic_init2(t, N_lo); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_sub(t, a, b, ctx); padic_add(b, b, t, ctx); e = n_randint(state, 50) + 1; N_res = N_lo + (e - 1) * FLINT_MIN(padic_val(a), padic_val(b)); padic_init2(c, N_res); padic_init2(d, N_res); padic_pow_si(c, a, e, ctx); padic_pow_si(d, b, e, ctx); result = (padic_equal(c, d)); if (!result) { flint_printf("FAIL (cmp with fmpq):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); flint_printf("N_lo = %wd\n", N_lo); flint_printf("N_hi = %wd\n", N_hi); flint_printf("N_res = %wd\n", N_res); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(t); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-randtest.c000066400000000000000000000056061461254215100177210ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_randtest, state) { int i, result; /* Check randtest() */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong lo, hi, N; padic_ctx_t ctx; padic_t a; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_randtest(a, state, ctx); if (N > 0) { lo = -((N + 9) / 10); hi = N; } else if (N < 0) { lo = N - ((-N + 9) / 10); hi = N; } else { lo = -10; hi = 0; } result = padic_is_zero(a) || (lo <= padic_val(a) && padic_val(a) < hi); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("N = %wd\n", N); fflush(stdout); flint_abort(); } padic_clear(a); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check randtest_not_zero() */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong lo, hi, N; padic_ctx_t ctx; padic_t a; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_randtest_not_zero(a, state, ctx); if (N > 0) { lo = -((N + 9) / 10); hi = N; } else if (N < 0) { lo = N - ((-N + 9) / 10); hi = N; } else { lo = -10; hi = 0; } result = !padic_is_zero(a) && (lo <= padic_val(a) && padic_val(a) < hi); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("N = %wd\n", N); fflush(stdout); flint_abort(); } padic_clear(a); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-shift.c000066400000000000000000000071051461254215100172060ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_shift, state) { int i, result; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; slong v; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); v = z_randint(state, (FLINT_ABS(N) + 4) / 3); padic_set(b, a, ctx); padic_shift(c, b, v, ctx); padic_shift(b, b, v, ctx); result = (padic_equal(b, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that (a * b) * c == a * (b * c), correct only mod p^{N-v} */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; slong v, v1, v2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest(a, state, ctx); v1 = z_randint(state, (FLINT_ABS(N) + 4) / 3); v2 = z_randint(state, (FLINT_ABS(N) + 4) / 3); padic_shift(b, a, v1, ctx); padic_shift(b, b, v2, ctx); padic_shift(c, a, v2, ctx); padic_shift(c, c, v1, ctx); v = FLINT_MIN(v1, v2); v = FLINT_MIN(v, padic_val(a)); v = FLINT_MIN(v, 0); if ((v >= 0) || (-v < N)) /* Otherwise, no precision left */ { slong N2 = (v >= 0) ? N : N + v; padic_prec(b) = N2; padic_prec(c) = N2; padic_reduce(b, ctx); padic_reduce(c, ctx); result = (padic_equal(b, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-sqrt.c000066400000000000000000000317401461254215100170640ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_sqrt, state) { int i, result; /* PRIME p = 2 ***************************************************************/ /* Check aliasing: a = sqrt(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; int ans1, ans2; padic_t a, d; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest(a, state, ctx); ans1 = padic_sqrt(d, a, ctx); ans2 = padic_sqrt(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, d))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Test random elements */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; int ans; padic_t a, b, d; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); ans = padic_sqrt(b, a, ctx); padic_mul(d, b, b, ctx); if (ans && padic_val(a) < 0) { slong N2 = N + padic_val(a); padic_t a2, d2; padic_init2(a2, N2); padic_init2(d2, N2); padic_set(a2, a, ctx); padic_set(d2, d, ctx); result = (padic_equal(a2, d2)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("a2 = "), padic_print(a2, ctx), flint_printf("\n"); flint_printf("d2 = "), padic_print(d2, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } padic_clear(a2); padic_clear(d2); } else { result = (!ans || padic_equal(a, d)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Test random squares */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; int ans; padic_t a, b, c, d; fmpz_init_set_ui(p, 2); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_randtest(b, state, ctx); padic_mul(a, b, b, ctx); ans = padic_sqrt(c, a, ctx); padic_mul(d, c, c, ctx); if (ans && padic_val(a) < 0) { slong N2 = N + padic_val(a); padic_t a2, d2; padic_init2(a2, N2); padic_init2(d2, N2); padic_set(a2, a, ctx); padic_set(d2, d, ctx); result = (padic_equal(a2, d2)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("a2 = "), padic_print(a2, ctx), flint_printf("\n"); flint_printf("d2 = "), padic_print(d2, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } padic_clear(a2); padic_clear(d2); } else { result = (ans && padic_equal(a, d)); if (!result) { flint_printf("FAIL (random squares):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* PRIME p > 2 ***************************************************************/ /* Check aliasing: a = sqrt(a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; int ans1, ans2; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest(a, state, ctx); ans1 = padic_sqrt(d, a, ctx); ans2 = padic_sqrt(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || padic_equal(a, d))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Test random elements */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; int ans; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); ans = padic_sqrt(b, a, ctx); padic_mul(d, b, b, ctx); if (ans && padic_val(a) < 0) { slong N2 = N + padic_val(a); padic_t a2, d2; padic_init2(a2, N2); padic_init2(d2, N2); padic_set(a2, a, ctx); padic_set(d2, d, ctx); result = (padic_equal(a2, d2)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("a2 = "), padic_print(a2, ctx), flint_printf("\n"); flint_printf("d2 = "), padic_print(d2, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } padic_clear(a2); padic_clear(d2); } else { result = (!ans || padic_equal(a, d)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Test random squares */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; int ans; padic_t a, b, c, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_randtest(b, state, ctx); padic_mul(a, b, b, ctx); ans = padic_sqrt(c, a, ctx); padic_mul(d, c, c, ctx); if (ans && padic_val(a) < 0) { slong N2 = N + padic_val(a); padic_t a2, d2; padic_init2(a2, N2); padic_init2(d2, N2); padic_set(a2, a, ctx); padic_set(d2, d, ctx); result = (padic_equal(a2, d2)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("a2 = "), padic_print(a2, ctx), flint_printf("\n"); flint_printf("d2 = "), padic_print(d2, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } padic_clear(a2); padic_clear(d2); } else { result = (ans && padic_equal(a, d)); if (!result) { flint_printf("FAIL (random squares):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-sub.c000066400000000000000000000174301461254215100166640ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_sub, state) { int i, result; /* Check aliasing: a = a - b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_sub(d, a, b, ctx); padic_sub(a, a, b, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL (alias a = a - b):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: b = a - b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_sub(d, a, b, ctx); padic_sub(b, a, b, ctx); result = (padic_equal(b, d)); if (!result) { flint_printf("FAIL (alias b = a - b):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: a = a - a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_sub(d, a, a, ctx); padic_sub(a, a, a, ctx); result = (padic_equal(a, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a - b == -(b - a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_sub(c, a, b, ctx); padic_sub(d, b, a, ctx); padic_neg(d, d, ctx); result = (padic_equal(c, d)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that (a - b) - c == a - (b + c) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c, d, e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_init2(d, N); padic_init2(e, N); padic_randtest(a, state, ctx); padic_randtest(b, state, ctx); padic_randtest(c, state, ctx); padic_sub(d, a, b, ctx); padic_sub(d, d, c, ctx); padic_add(e, b, c, ctx); padic_sub(e, a, e, ctx); result = (padic_equal(d, e)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_print(d, ctx), flint_printf("\n"); flint_printf("e = "), padic_print(e, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(e); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check that a - 0 == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_randtest(a, state, ctx); padic_zero(b); padic_sub(b, a, b, ctx); result = (padic_equal(a, b)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-teichmuller.c000066400000000000000000000055771461254215100204210ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_teichmuller, state) { int i, result; /* Check aliasing (x 1,000) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest_int(a, state, ctx); padic_set(b, a, ctx); padic_teichmuller(c, b, ctx); padic_teichmuller(b, b, ctx); result = (padic_equal(b, c)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check x^p == x for word-sized p (x 10,000)*/ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong prime, N; padic_ctx_t ctx; padic_t a, b, c; prime = n_randprime(state, 2 + n_randint(state, SMALL_FMPZ_BITCOUNT_MAX), 0); fmpz_init_set_ui(p, prime); N = n_randint(state, PADIC_TEST_PREC_MAX); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_init2(a, N); padic_init2(b, N); padic_init2(c, N); padic_randtest_int(a, state, ctx); padic_teichmuller(b, a, ctx); padic_pow_si(c, b, fmpz_get_si(p), ctx); result = (padic_equal(b, c)); if (!result) { flint_printf("FAIL (x^p == x):\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_print(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/test/t-val_fac.c000066400000000000000000000110321461254215100174560ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic.h" TEST_FUNCTION_START(padic_val_fac, state) { int i, result; /* Check aliasing for padic_val_fac() */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, c, p; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(p); fmpz_randtest_unsigned(a, state, (flint_bitcnt_t) (1.5 * FLINT_BITS)); fmpz_set(b, a); fmpz_set_ui(p, n_randtest_prime(state, 0)); padic_val_fac(c, b, p); padic_val_fac(b, b, p); result = fmpz_equal(b, c); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(p); } /* Check correctness for padic_val_fac_ui(), p == 2 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, p; ulong s, t, N; fmpz_init(a); fmpz_init(b); fmpz_init(p); N = n_randint(state, WORD(1) < 13); fmpz_set_ui(p, 2); fmpz_fac_ui(a, N); s = padic_val_fac_ui_2(N); t = fmpz_remove(b, a, p); result = (s == t); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("N = %wu\n", N); flint_printf("s = %wu\n", s); flint_printf("t = %wu\n", t); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(p); } /* Check correctness for padic_val_fac_ui(), any p */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, p; ulong s, t, N; fmpz_init(a); fmpz_init(b); fmpz_init(p); N = n_randint(state, WORD(1) < 13); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, FLINT_BITS - 4), 0)); fmpz_fac_ui(a, N); s = padic_val_fac_ui(N, p); t = fmpz_remove(b, a, p); result = (s == t); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("N = %wu\n", N); flint_printf("s = %wu\n", s); flint_printf("t = %wu\n", t); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(p); } /* Compare padic_val_fac_ui() with padic_val_fac() */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, p, t, z; ulong s, n; fmpz_init(a); fmpz_init(p); fmpz_init(t); fmpz_init(z); n = n_randint(state, WORD(1) < 13); fmpz_set_ui(z, n); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, FLINT_BITS - 4), 0)); fmpz_fac_ui(a, n); s = padic_val_fac_ui(n, p); padic_val_fac(t, z, p); result = (fmpz_equal_ui(t, s)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("n = %wu\n", n); flint_printf("s = %wu\n", s); flint_printf("t = "), fmpz_print(t), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); fflush(stdout); flint_abort(); } fmpz_clear(a); fmpz_clear(p); fmpz_clear(t); fmpz_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic/val_fac.c000066400000000000000000000024251461254215100162440ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" ulong padic_val_fac_ui_2(ulong N) { ulong s = 0, t = N; do { t /= 2; s += t; } while (t); return s; } ulong padic_val_fac_ui(ulong N, const fmpz_t prime) { if (fmpz_abs_fits_ui(prime)) { const ulong p = fmpz_get_ui(prime); ulong s = 0, t = N; do { t /= p; s += t; } while (t); return s; } else { return 0; } } void padic_val_fac(fmpz_t rop, const fmpz_t op, const fmpz_t p) { fmpz_t s, t; if (fmpz_sgn(op) < 0) { flint_throw(FLINT_ERROR, "Exception (padic_val_fac). op is negative.\n"); } fmpz_init(s); fmpz_init_set(t, op); do { fmpz_fdiv_q(t, t, p); fmpz_add(s, s, t); } while (!fmpz_is_zero(t)); fmpz_swap(rop, s); fmpz_clear(s); fmpz_clear(t); } flint-3.1.3/src/padic_mat.h000066400000000000000000000143351461254215100155220ustar00rootroot00000000000000/* Copyright (C) 2011, 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef PADIC_MAT_H #define PADIC_MAT_H #ifdef PADIC_MAT_INLINES_C #define PADIC_MAT_INLINE #else #define PADIC_MAT_INLINE static inline #endif #include "fmpq_types.h" #include "padic_types.h" #ifdef __cplusplus extern "C" { #endif /* Macros *******************************************************************/ PADIC_MAT_INLINE fmpz_mat_struct * padic_mat(const padic_mat_t A) { return (fmpz_mat_struct *)(&(A->mat)); } PADIC_MAT_INLINE fmpz * padic_mat_entry(const padic_mat_t A, slong i, slong j) { return A->mat.rows[i] + j; } #define padic_mat_val(A) ((A)->val) #define padic_mat_prec(A) ((A)->N) PADIC_MAT_INLINE slong padic_mat_get_val(const padic_mat_t A) { return A->val; } PADIC_MAT_INLINE slong padic_mat_get_prec(const padic_mat_t A) { return A->N; } PADIC_MAT_INLINE slong padic_mat_nrows(const padic_mat_t A) { return (A->mat).r; } PADIC_MAT_INLINE slong padic_mat_ncols(const padic_mat_t A) { return (A->mat).c; } /* Memory management ********************************************************/ void padic_mat_init(padic_mat_t A, slong r, slong c); void padic_mat_init2(padic_mat_t A, slong r, slong c, slong prec); void padic_mat_clear(padic_mat_t A); void _padic_mat_canonicalise(padic_mat_t A, const padic_ctx_t ctx); void _padic_mat_reduce(padic_mat_t A, const padic_ctx_t ctx); void padic_mat_reduce(padic_mat_t A, const padic_ctx_t ctx); PADIC_MAT_INLINE int padic_mat_is_empty(const padic_mat_t A) { return padic_mat_nrows(A) == 0 || padic_mat_ncols(A) == 0; } PADIC_MAT_INLINE int padic_mat_is_square(const padic_mat_t A) { return padic_mat_nrows(A) == padic_mat_ncols(A); } int padic_mat_is_canonical(const padic_mat_t A, const padic_ctx_t ctx); int padic_mat_is_reduced(const padic_mat_t A, const padic_ctx_t ctx); /* Basic assignment **********************************************************/ void padic_mat_set(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx); void padic_mat_swap(padic_mat_t A, padic_mat_t B); PADIC_MAT_INLINE void padic_mat_swap_entrywise(padic_mat_t mat1, padic_mat_t mat2) { slong i, j; for (i = 0; i < padic_mat_nrows(mat1); i++) for (j = 0; j < padic_mat_ncols(mat1); j++) FLINT_SWAP(fmpz, *padic_mat_entry(mat2, i, j), *padic_mat_entry(mat1, i, j)); } void padic_mat_zero(padic_mat_t A); void padic_mat_one(padic_mat_t A); /* Conversions ***************************************************************/ void padic_mat_set_fmpq_mat(padic_mat_t B, const fmpq_mat_t A, const padic_ctx_t ctx); void padic_mat_get_fmpq_mat(fmpq_mat_t B, const padic_mat_t A, const padic_ctx_t ctx); /* Entries *******************************************************************/ void padic_mat_get_entry_padic(padic_t rop, const padic_mat_t op, slong i, slong j, const padic_ctx_t ctx); void padic_mat_set_entry_padic(padic_mat_t rop, slong i, slong j, const padic_t op, const padic_ctx_t ctx); /* Comparison ****************************************************************/ int padic_mat_equal(const padic_mat_t A, const padic_mat_t B); int padic_mat_is_zero(const padic_mat_t A); /* Input and output *********************************************************/ #ifdef FLINT_HAVE_FILE int padic_mat_fprint(FILE * file, const padic_mat_t A, const padic_ctx_t ctx); int padic_mat_fprint_pretty(FILE * file, const padic_mat_t A, const padic_ctx_t ctx); #endif int padic_mat_print(const padic_mat_t A, const padic_ctx_t ctx); int padic_mat_print_pretty(const padic_mat_t A, const padic_ctx_t ctx); /* Random matrix generation *************************************************/ void padic_mat_randtest(padic_mat_t mat, flint_rand_t state, const padic_ctx_t ctx); /* Transpose *****************************************************************/ void padic_mat_transpose(padic_mat_t B, const padic_mat_t A); /* Addition and subtraction **************************************************/ void _padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); void padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); void _padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); void padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); void _padic_mat_neg(padic_mat_t B, const padic_mat_t A); void padic_mat_neg(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx); /* Scalar operations *********************************************************/ void _padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx); void padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx); void _padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx); void padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx); void padic_mat_scalar_div_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx); /* Multiplication ************************************************************/ void padic_mat_mul(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/padic_mat/000077500000000000000000000000001461254215100153435ustar00rootroot00000000000000flint-3.1.3/src/padic_mat/add.c000066400000000000000000000054501461254215100162430ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "padic.h" #include "padic_mat.h" /* Assumptions: o That the matrix dimensions be compatible. o That the matrices be non-empty. o That ord_p(A) >= ord_p(B). */ void _padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) { if (padic_mat_is_zero(A)) { padic_mat_set(C, B, ctx); return; } if (padic_mat_is_zero(B)) { padic_mat_set(C, A, ctx); return; } if (padic_mat_val(B) >= padic_mat_prec(C)) { padic_mat_zero(C); return; } if (padic_mat_val(A) == padic_mat_val(B)) { fmpz_mat_add(padic_mat(C), padic_mat(A), padic_mat(B)); padic_mat_val(C) = padic_mat_val(B); _padic_mat_canonicalise(C, ctx); } else /* padic_mat_val(A) > padic_mat_val(B) */ { fmpz_t x; fmpz_init(x); fmpz_pow_ui(x, ctx->p, padic_mat_val(A) - padic_mat_val(B)); if (C == B) { fmpz_mat_scalar_addmul_fmpz(padic_mat(C), padic_mat(A), x); } else if (C == A) { fmpz_mat_scalar_mul_fmpz(padic_mat(C), padic_mat(A), x); fmpz_mat_add(padic_mat(C), padic_mat(B), padic_mat(C)); padic_mat_val(C) = padic_mat_val(B); } else { fmpz_mat_set(padic_mat(C), padic_mat(B)); fmpz_mat_scalar_addmul_fmpz(padic_mat(C), padic_mat(A), x); padic_mat_val(C) = padic_mat_val(B); } fmpz_clear(x); } /* Reduction */ { fmpz_t pow; int alloc = _padic_ctx_pow_ui(pow, padic_mat_prec(C)- padic_mat_val(C), ctx); /* TODO: Improve, use input precision */ _fmpz_vec_scalar_mod_fmpz(padic_mat(C)->entries, padic_mat(C)->entries, padic_mat_nrows(C)*padic_mat_ncols(C), pow); if (fmpz_mat_is_zero(padic_mat(C))) { padic_mat_val(C) = 0; } if (alloc) fmpz_clear(pow); } } void padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) { if (padic_mat_is_empty(C)) { return; } if (padic_mat_val(A) >= padic_mat_val(B)) { _padic_mat_add(C, A, B, ctx); } else { _padic_mat_add(C, B, A, ctx); } } flint-3.1.3/src/padic_mat/canonicalise.c000066400000000000000000000050111461254215100201340ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "padic_poly.h" #include "padic_mat.h" static void _padic_mat_canonicalise_fmpz(fmpz *vec, slong len, slong *val, const fmpz_t p) { int nonzero = 0; slong i; for (i = 0; i < len; i++) { if (vec[i] != WORD(0)) { nonzero = 1; if (!fmpz_divisible(vec + i, p)) { return; } } } if (nonzero) { _fmpz_vec_scalar_divexact_fmpz(vec, vec, len, p); (*val)++; while (1) { for (i = 0; i < len; i++) { if (!fmpz_divisible(vec + i, p)) { return; } } _fmpz_vec_scalar_divexact_fmpz(vec, vec, len, p); (*val)++; } } else { *val = 0; } } static void _padic_mat_canonicalise_si(fmpz *vec, slong len, slong *val, slong p) { int nonzero = 0; slong i; for (i = 0; i < len; i++) { if (vec[i] != WORD(0)) { nonzero = 1; if (!fmpz_divisible_si(vec + i, p)) { return; } } } if (nonzero) { _fmpz_vec_scalar_divexact_ui(vec, vec, len, p); (*val)++; while (1) { for (i = 0; i < len; i++) { if (!fmpz_divisible_si(vec + i, p)) { return; } } _fmpz_vec_scalar_divexact_ui(vec, vec, len, p); (*val)++; } } else { *val = 0; } } void _padic_mat_canonicalise(padic_mat_t A, const padic_ctx_t ctx) { if (COEFF_IS_MPZ(*(ctx->p))) { _padic_mat_canonicalise_fmpz(padic_mat(A)->entries, padic_mat(A)->r * padic_mat(A)->c, &(A->val), ctx->p); } else { _padic_mat_canonicalise_si(padic_mat(A)->entries, padic_mat(A)->r * padic_mat(A)->c, &(A->val), *(ctx->p)); } } flint-3.1.3/src/padic_mat/clear.c000066400000000000000000000010101461254215100165650ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_clear(padic_mat_t A) { fmpz_mat_clear(padic_mat(A)); A->val = 0; } flint-3.1.3/src/padic_mat/equal.c000066400000000000000000000011701461254215100166150ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" int padic_mat_equal(const padic_mat_t A, const padic_mat_t B) { if (A->val == B->val) { return fmpz_mat_equal(padic_mat(A), padic_mat(B)); } else { return 0; } } flint-3.1.3/src/padic_mat/get_entry_padic.c000066400000000000000000000013561461254215100206540ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "padic.h" #include "padic_mat.h" void padic_mat_get_entry_padic(padic_t rop, const padic_mat_t op, slong i, slong j, const padic_ctx_t ctx) { fmpz_set(padic_unit(rop), padic_mat_entry(op, i, j)); padic_val(rop) = padic_mat_val(op); padic_reduce(rop, ctx); } flint-3.1.3/src/padic_mat/get_fmpq_mat.c000066400000000000000000000030141461254215100201500ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" #include "padic_mat.h" void padic_mat_get_fmpq_mat(fmpq_mat_t B, const padic_mat_t A, const padic_ctx_t ctx) { if (!padic_mat_is_empty(A)) { if (padic_mat_is_zero(A)) { fmpq_mat_zero(B); } else { fmpz_t f; slong i, j; fmpz_init(f); fmpz_pow_ui(f, ctx->p, FLINT_ABS(padic_mat_val(A))); for (i = 0; i < B->r; i++) for (j = 0; j < B->c; j++) { if (padic_mat_val(A) >= 0) { fmpz_mul(fmpq_mat_entry_num(B, i, j), padic_mat_entry(A, i, j), f); fmpz_one(fmpq_mat_entry_den(B, i, j)); } else { fmpz_set(fmpq_mat_entry_num(B, i, j), padic_mat_entry(A, i, j)); fmpz_set(fmpq_mat_entry_den(B, i, j), f); fmpq_canonicalise(fmpq_mat_entry(B, i, j)); } } fmpz_clear(f); } } } flint-3.1.3/src/padic_mat/init.c000066400000000000000000000013431461254215100164530ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic.h" #include "padic_mat.h" void padic_mat_init(padic_mat_t A, slong r, slong c) { fmpz_mat_init(padic_mat(A), r, c); A->val = 0; A->N = PADIC_DEFAULT_PREC; } void padic_mat_init2(padic_mat_t A, slong r, slong c, slong prec) { fmpz_mat_init(padic_mat(A), r, c); A->val = 0; A->N = prec; } flint-3.1.3/src/padic_mat/inlines.c000066400000000000000000000006561461254215100171570ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define PADIC_MAT_INLINES_C #include "padic_mat.h" flint-3.1.3/src/padic_mat/io.c000066400000000000000000000104771461254215100161270ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "padic.h" #include "padic_mat.h" /* printing *******************************************************************/ int padic_mat_fprint(FILE * file, const padic_mat_t A, const padic_ctx_t ctx) { const slong r = padic_mat(A)->r; const slong c = padic_mat(A)->c; if (padic_mat_is_empty(A)) { flint_fprintf(file, "%wd %wd\n", r, c); return 1; } if (ctx->mode == PADIC_TERSE) { slong i, j, v; fmpz_t s, t; fmpz_init(s); fmpz_init(t); flint_fprintf(file, "%wd %wd ", r, c); for (i = 0; i < r; i++) for (j = 0; j < c; j++) { flint_fprintf(file, " "); if (fmpz_is_zero(padic_mat_entry(A, i, j))) { flint_fprintf(file, "0"); } else { v = A->val + fmpz_remove(t, padic_mat_entry(A, i, j), ctx->p); if (v == 0) { fmpz_fprint(file, t); } else if (v > 0) { fmpz_pow_ui(s, ctx->p, v); fmpz_mul(t, s, t); fmpz_fprint(file, t); } else /* v < 0 */ { fmpz_pow_ui(s, ctx->p, -v); _fmpq_fprint(file, t, s); } } } fmpz_clear(s); fmpz_clear(t); } else if (ctx->mode == PADIC_SERIES) { flint_throw(FLINT_ERROR, "ERROR (_padic_mat_fprint). Mode PADIC_SERIES not implemented yet.\n"); } else if (ctx->mode == PADIC_VAL_UNIT) { slong i, j, v; fmpz_t t; fmpz_init(t); flint_fprintf(file, "%wd %wd ", r, c); for (i = 0; i < r; i++) for (j = 0; j < c; j++) { flint_fprintf(file, " "); if (fmpz_is_zero(padic_mat_entry(A, i, j))) { flint_fprintf(file, "0"); } else { v = A->val + fmpz_remove(t, padic_mat_entry(A, i, j), ctx->p); if (v == 0) { fmpz_fprint(file, t); } else if (v == 1) { fmpz_fprint(file, ctx->p); flint_fprintf(file, "*"); fmpz_fprint(file, t); } else { fmpz_fprint(file, ctx->p); flint_fprintf(file, "^%wd*", v); fmpz_fprint(file, t); } } } fmpz_clear(t); } else { flint_throw(FLINT_ERROR, "ERROR (_padic_mat_fprint). Unknown print mode.\n"); } return 1; } int padic_mat_fprint_pretty(FILE * file, const padic_mat_t A, const padic_ctx_t ctx) { const slong r = padic_mat(A)->r; const slong c = padic_mat(A)->c; slong i, j, v; fmpz_t u; fmpz_init(u); fputc('[', file); for (i = 0; i < r; i++) { fputc('[', file); for (j = 0; j < c; j++) { v = A->val + fmpz_remove(u, padic_mat_entry(A, i, j), ctx->p); _padic_fprint(file, u, v, ctx); if (j != c - 1) fputc(' ', file); } fputc(']', file); if (i != r - 1) fputc('\n', file); } fputc(']', file); fmpz_clear(u); return 1; } int padic_mat_print(const padic_mat_t A, const padic_ctx_t ctx) { return padic_mat_fprint(stdout, A, ctx); } int padic_mat_print_pretty(const padic_mat_t A, const padic_ctx_t ctx) { return padic_mat_fprint_pretty(stdout, A, ctx); } flint-3.1.3/src/padic_mat/is_canonical.c000066400000000000000000000016341461254215100201350ustar00rootroot00000000000000/* Copyright (C) 2011, 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "padic_mat.h" int padic_mat_is_canonical(const padic_mat_t A, const padic_ctx_t ctx) { if (fmpz_mat_is_zero(padic_mat(A))) { return (padic_mat_val(A) == 0); } else { slong i, j; int canonical = 0; for (i = 0; i < padic_mat(A)->r; i++) for (j = 0; j < padic_mat(A)->c; j++) if (!fmpz_divisible(padic_mat_entry(A, i, j), ctx->p)) canonical = 1; return canonical; } } flint-3.1.3/src/padic_mat/is_reduced.c000066400000000000000000000025721461254215100176230ustar00rootroot00000000000000/* Copyright (C) 2011, 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic.h" #include "padic_mat.h" int padic_mat_is_reduced(const padic_mat_t A, const padic_ctx_t ctx) { if (padic_mat_is_empty(A)) { return 1; } else if (fmpz_mat_is_zero(padic_mat(A))) { return (padic_mat_val(A) == 0); } else if (padic_mat_is_canonical(A, ctx)) { const slong v = padic_mat_val(A); const slong N = padic_mat_prec(A); if (v >= N) { return 0; } else { slong i, j; fmpz_t pN; int reduced = 1; int alloc = _padic_ctx_pow_ui(pN, N - v, ctx); for (i = 0; (i < padic_mat_nrows(A)) && reduced; i++) for (j = 0; (j < padic_mat_ncols(A)) && reduced; j++) reduced = (fmpz_cmp(padic_mat_entry(A, i, j), pN) < 0); if (alloc) fmpz_clear(pN); return reduced; } } else { return 0; } } flint-3.1.3/src/padic_mat/is_zero.c000066400000000000000000000011241461254215100171570ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" int padic_mat_is_zero(const padic_mat_t A) { if (A->val == 0) { return fmpz_mat_is_zero(padic_mat(A)); } else { return 0; } } flint-3.1.3/src/padic_mat/mul.c000066400000000000000000000016171461254215100163110ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_mul(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) { if (padic_mat_is_empty(C)) { return; } if (padic_mat_is_zero(A) || padic_mat_is_zero(B)) { padic_mat_zero(C); } else { fmpz_mat_mul(padic_mat(C), padic_mat(A), padic_mat(B)); padic_mat_val(C) = padic_mat_val(A) + padic_mat_val(B); padic_mat_reduce(C, ctx); } } flint-3.1.3/src/padic_mat/neg.c000066400000000000000000000013511461254215100162600ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void _padic_mat_neg(padic_mat_t B, const padic_mat_t A) { if (padic_mat_is_empty(B)) return; fmpz_mat_neg(padic_mat(B), padic_mat(A)); B->val = A->val; } void padic_mat_neg(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx) { _padic_mat_neg(B, A); _padic_mat_reduce(B, ctx); } flint-3.1.3/src/padic_mat/one.c000066400000000000000000000012051461254215100162660ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_one(padic_mat_t A) { if (padic_mat_prec(A) > 0) { fmpz_mat_one(padic_mat(A)); A->val = 0; } else { fmpz_mat_zero(padic_mat(A)); A->val = 0; } } flint-3.1.3/src/padic_mat/randtest.c000066400000000000000000000025221461254215100173340ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_randtest(padic_mat_t mat, flint_rand_t state, const padic_ctx_t ctx) { if (!padic_mat_is_empty(mat)) { const slong N = padic_mat_prec(mat); slong i, j, min, max; fmpz_t pow; if (N > 0) { min = - ((N + 9) / 10); max = N; } else if (N < 0) { min = N - ((-N + 9) / 10); max = N; } else /* ctx->N == 0 */ { min = -10; max = 0; } padic_mat_val(mat) = n_randint(state, max - min) + min; fmpz_init(pow); fmpz_pow_ui(pow, ctx->p, N - padic_mat_val(mat)); for (i = 0; i < padic_mat(mat)->r; i++) for (j = 0; j < padic_mat(mat)->c; j++) fmpz_randm(padic_mat_entry(mat, i, j), state, pow); fmpz_clear(pow); _padic_mat_canonicalise(mat, ctx); } } flint-3.1.3/src/padic_mat/reduce.c000066400000000000000000000025001461254215100167530ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "padic_mat.h" void _padic_mat_reduce(padic_mat_t mat, const padic_ctx_t ctx) { if (!padic_mat_is_empty(mat) && !padic_mat_is_zero(mat)) { if (mat->val >= padic_mat_prec(mat)) { padic_mat_zero(mat); } else { slong i; fmpz_t pow; fmpz_init(pow); fmpz_pow_ui(pow, ctx->p, padic_mat_prec(mat) - mat->val); for (i = 0; i < padic_mat(mat)->r * padic_mat(mat)->c; i++) { fmpz_mod(padic_mat(mat)->entries + i, padic_mat(mat)->entries + i, pow); } fmpz_clear(pow); if (padic_mat_is_zero(mat)) { mat->val = 0; } } } } void padic_mat_reduce(padic_mat_t mat, const padic_ctx_t ctx) { _padic_mat_canonicalise(mat, ctx); _padic_mat_reduce(mat, ctx); } flint-3.1.3/src/padic_mat/scalar.c000066400000000000000000000056421461254215100167630ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "padic.h" #include "padic_mat.h" void padic_mat_scalar_div_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx) { if (padic_mat_is_empty(B)) { return; } if (fmpz_is_zero(c)) { flint_throw(FLINT_ERROR, "ERROR (padic_mat_scalar_div_fmpz). c is zero.\n"); } if (padic_mat_is_zero(A)) { padic_mat_zero(B); } else { fmpz_t d; slong v; fmpz_init(d); v = fmpz_remove(d, c, ctx->p); if (padic_mat_val(A) - v >= padic_mat_prec(B)) { padic_mat_zero(B); } else { _padic_inv(d, d, ctx->p, padic_mat_prec(B) - padic_mat_val(A) + v); fmpz_mat_scalar_mul_fmpz(padic_mat(B), padic_mat(A), d); padic_mat_val(B) = padic_mat_val(A) - v; _padic_mat_reduce(B, ctx); } fmpz_clear(d); } } void _padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx) { if (padic_mat_is_empty(B)) { return; } if (fmpz_is_zero(c) || padic_mat_is_zero(A)) { padic_mat_zero(B); } else { fmpz_t d; slong v; fmpz_init(d); v = fmpz_remove(d, c, ctx->p); fmpz_mat_scalar_mul_fmpz(padic_mat(B), padic_mat(A), d); padic_mat_val(B) = padic_mat_val(A) + v; fmpz_clear(d); } } void padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx) { _padic_mat_scalar_mul_fmpz(B, A, c, ctx); _padic_mat_reduce(B, ctx); } void _padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx) { if (padic_mat_is_empty(B)) { return; } if (padic_is_zero(c) || padic_mat_is_zero(A)) { padic_mat_zero(B); return; } fmpz_mat_scalar_mul_fmpz(padic_mat(B), padic_mat(A), padic_unit(c)); padic_mat_val(B) = padic_mat_val(A) + padic_val(c); } void padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx) { _padic_mat_scalar_mul_padic(B, A, c, ctx); _padic_mat_reduce(B, ctx); } flint-3.1.3/src/padic_mat/set.c000066400000000000000000000020101461254215100162730ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_set(padic_mat_t rop, const padic_mat_t op, const padic_ctx_t ctx) { if (op != rop) { if (padic_mat_val(op) >= padic_mat_prec(rop)) { padic_mat_zero(rop); } else if (padic_mat_prec(rop) >= padic_mat_prec(op)) { fmpz_mat_set(padic_mat(rop), padic_mat(op)); padic_mat_val(rop) = padic_mat_val(op); } else { fmpz_mat_set(padic_mat(rop), padic_mat(op)); padic_mat_val(rop) = padic_mat_val(op); _padic_mat_reduce(rop, ctx); } } } flint-3.1.3/src/padic_mat/set_entry_padic.c000066400000000000000000000032311461254215100206620ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "padic.h" #include "padic_mat.h" void padic_mat_set_entry_padic(padic_mat_t rop, slong i, slong j, const padic_t op, const padic_ctx_t ctx) { if (padic_is_zero(op)) { fmpz_zero(padic_mat_entry(rop, i, j)); _padic_mat_canonicalise(rop, ctx); return; } if (padic_mat_val(rop) == padic_val(op)) { fmpz_set(padic_mat_entry(rop, i, j), padic_unit(op)); } else if (padic_mat_val(rop) < padic_val(op)) { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, ctx->p, padic_val(op) - padic_mat_val(rop)); fmpz_mul(padic_mat_entry(rop, i, j), padic_unit(op), t); fmpz_clear(t); _padic_mat_canonicalise(rop, ctx); } else /* rop->val > op->val */ { fmpz_t pow; fmpz_init(pow); fmpz_pow_ui(pow, ctx->p, padic_mat_val(rop) - padic_val(op)); _fmpz_vec_scalar_mul_fmpz(padic_mat(rop)->entries, padic_mat(rop)->entries, padic_mat(rop)->r * padic_mat(rop)->c, pow); fmpz_clear(pow); fmpz_set(padic_mat_entry(rop, i, j), padic_unit(op)); padic_mat_val(rop) = padic_val(op); } } flint-3.1.3/src/padic_mat/set_fmpq_mat.c000066400000000000000000000051231461254215100201670ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_mat.h" #include "padic.h" #include "padic_mat.h" void padic_mat_set_fmpq_mat(padic_mat_t B, const fmpq_mat_t A, const padic_ctx_t ctx) { if (!fmpq_mat_is_empty(A)) { const slong N = padic_mat_prec(B); slong i, j, m = WORD_MAX, v, w; fmpz_t f, g, s, t; fmpz_init(f); fmpz_init(g); fmpz_init(s); fmpz_init(t); /* Find min valuation m */ for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) if (!fmpq_is_zero(fmpq_mat_entry(A, i, j))) { v = fmpz_remove(t, fmpq_mat_entry_num(A, i, j), ctx->p); w = fmpz_remove(t, fmpq_mat_entry_den(A, i, j), ctx->p); m = FLINT_MIN(m, v - w); } if (m >= N) { padic_mat_zero(B); } else { for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) if (fmpq_is_zero(fmpq_mat_entry(A, i, j))) { fmpz_zero(padic_mat_entry(B, i, j)); } else { v = fmpz_remove(s, fmpq_mat_entry_num(A, i, j), ctx->p); w = fmpz_remove(t, fmpq_mat_entry_den(A, i, j), ctx->p); if (v - w >= N) { fmpz_zero(padic_mat_entry(B, i, j)); } else { fmpz_pow_ui(f, ctx->p, (v - w) - m); fmpz_pow_ui(g, ctx->p, N - (v - w)); _padic_inv(t, t, ctx->p, N - (v - w)); fmpz_mul(padic_mat_entry(B, i, j), s, t); fmpz_mod(padic_mat_entry(B, i, j), padic_mat_entry(B, i, j), g); fmpz_mul(padic_mat_entry(B, i, j), padic_mat_entry(B, i, j), f); } } padic_mat_val(B) = m; } fmpz_clear(f); fmpz_clear(g); fmpz_clear(s); fmpz_clear(t); } } flint-3.1.3/src/padic_mat/sub.c000066400000000000000000000056231461254215100163060ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "padic_mat.h" /* Assumptions: o That the matrix dimensions be compatible. o That the matrices be non-empty. o That ord_p(A) >= ord_p(B). */ void _padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) { if (padic_mat_is_zero(A)) { padic_mat_neg(C, B, ctx); return; } if (padic_mat_is_zero(B)) { padic_mat_set(C, A, ctx); return; } if (FLINT_MIN(padic_mat_val(A), padic_mat_val(B)) >= padic_mat_prec(C)) { padic_mat_zero(C); return; } if (padic_mat_val(A) == padic_mat_val(B)) { fmpz_mat_sub(padic_mat(C), padic_mat(A), padic_mat(B)); padic_mat_val(C) = padic_mat_val(A); _padic_mat_canonicalise(C, ctx); } else { fmpz_t x; fmpz_init(x); if (padic_mat_val(A) < padic_mat_val(B)) { fmpz_pow_ui(x, ctx->p, padic_mat_val(B) - padic_mat_val(A)); if (C == A) { fmpz_mat_scalar_submul_fmpz(padic_mat(C), padic_mat(B), x); } else if (C == B) { fmpz_neg(x, x); fmpz_mat_scalar_mul_fmpz(padic_mat(C), padic_mat(B), x); fmpz_mat_add(padic_mat(C), padic_mat(A), padic_mat(C)); padic_mat_val(C) = padic_mat_val(A); } else { fmpz_mat_set(padic_mat(C), padic_mat(A)); fmpz_mat_scalar_submul_fmpz(padic_mat(C), padic_mat(B), x); padic_mat_val(C) = padic_mat_val(A); } } else /* A->val > B->val */ { fmpz_pow_ui(x, ctx->p, padic_mat_val(A) - padic_mat_val(B)); if (C == B) { fmpz_mat_scalar_submul_fmpz(padic_mat(C), padic_mat(A), x); fmpz_mat_neg(padic_mat(C), padic_mat(C)); } else { fmpz_mat_scalar_mul_fmpz(padic_mat(C), padic_mat(A), x); fmpz_mat_sub(padic_mat(C), padic_mat(C), padic_mat(B)); padic_mat_val(C) = padic_mat_val(B); } } fmpz_clear(x); } } void padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx) { if (padic_mat_is_empty(C)) { return; } _padic_mat_sub(C, A, B, ctx); _padic_mat_reduce(C, ctx); } flint-3.1.3/src/padic_mat/swap.c000066400000000000000000000010161461254215100164570ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_swap(padic_mat_t A, padic_mat_t B) { FLINT_SWAP(padic_mat_struct, *A, *B); } flint-3.1.3/src/padic_mat/test/000077500000000000000000000000001461254215100163225ustar00rootroot00000000000000flint-3.1.3/src/padic_mat/test/main.c000066400000000000000000000024461461254215100174200ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-get_set_entry_padic.c" #include "t-get_set_fmpq_mat.c" #include "t-mul.c" #include "t-neg.c" #include "t-scalar_div_fmpz.c" #include "t-scalar_mul_fmpz.c" #include "t-scalar_mul_padic.c" #include "t-sub.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(padic_mat_add), TEST_FUNCTION(padic_mat_get_set_entry_padic), TEST_FUNCTION(padic_mat_get_set_fmpq_mat), TEST_FUNCTION(padic_mat_mul), TEST_FUNCTION(padic_mat_neg), TEST_FUNCTION(padic_mat_scalar_div_fmpz), TEST_FUNCTION(padic_mat_scalar_mul_fmpz), TEST_FUNCTION(padic_mat_scalar_mul_padic), TEST_FUNCTION(padic_mat_sub) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/padic_mat/test/t-add.c000066400000000000000000000162461461254215100174700ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" #include "padic.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_add, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Check aliasing: a = a + b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_add(d, a, b, ctx); padic_mat_add(a, a, b, ctx); result = (padic_mat_equal(a, d) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: b = a + b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_add(d, a, b, ctx); padic_mat_add(b, a, b, ctx); result = (padic_mat_equal(b, d) && padic_mat_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: a = a + a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(c, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_set(b, a, ctx); padic_mat_add(c, b, b, ctx); padic_mat_add(b, b, b, ctx); result = (padic_mat_equal(b, c) && padic_mat_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL (alias b = b + b):\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_mat_print(c, ctx), flint_printf("\n"); flint_printf("N = %wd\n", N); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check commutativity: a + b == b + a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, c, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 10); n = n_randint(state, 10); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(c, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_add(c, a, b, ctx); padic_mat_add(d, b, a, ctx); result = (padic_mat_equal(c, d) && padic_mat_is_reduced(c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_mat_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print_pretty(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(c); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check zero element: a + 0 == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_add(b, a, b, ctx); result = (padic_mat_equal(a, b) && padic_mat_is_canonical(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-get_set_entry_padic.c000066400000000000000000000037461461254215100227540ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_get_set_entry_padic, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a; padic_t x, y; slong r, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20) + 1; n = n_randint(state, 20) + 1; padic_mat_init2(a, m, n, N); padic_init2(x, N); padic_init2(y, N); padic_mat_randtest(a, state, ctx); padic_randtest_not_zero(x, state, ctx); r = n_randint(state, m); c = n_randint(state, n); padic_mat_set_entry_padic(a, r, c, x, ctx); padic_mat_get_entry_padic(y, a, r, c, ctx); result = (padic_equal(x, y) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("x = "), padic_print(x, ctx), flint_printf("\n"); flint_printf("y = "), padic_print(y, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_clear(x); padic_clear(y); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-get_set_fmpq_mat.c000066400000000000000000000036331461254215100222520ustar00rootroot00000000000000/* Copyright (C) 2011, 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_mat.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_get_set_fmpq_mat, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Qp -> QQ -> Qp */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_mat_t a, c; fmpq_mat_t b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 10); n = n_randint(state, 10); padic_mat_init2(a, m, n, N); padic_mat_init2(c, m, n, N); fmpq_mat_init(b, m, n); padic_mat_randtest(a, state, ctx); padic_mat_get_fmpq_mat(b, a, ctx); padic_mat_set_fmpq_mat(c, b, ctx); result = (padic_mat_equal(a, c) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("c = "), padic_mat_print(c, ctx), flint_printf("\n"); flint_printf("b = "), fmpq_mat_print(b), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(c); fmpq_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-mul.c000066400000000000000000000251521461254215100175310ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_mul, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Check aliasing: a = a * b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_mat_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 10); n = m; padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_mul(d, a, b, ctx); padic_mat_mul(a, a, b, ctx); result = (padic_mat_equal(a, d) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_mat_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 10); n = m; padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_mul(d, a, b, ctx); padic_mat_mul(b, a, b, ctx); result = (padic_mat_equal(b, d) && padic_mat_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: a = a * a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_mat_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 10); n = m; padic_mat_init2(a, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_mul(d, a, a, ctx); padic_mat_mul(a, a, a, ctx); result = (padic_mat_equal(a, d) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check identity: a * Id == a, for N > 0 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_mat_t a, b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; N = FLINT_MAX(1, N); padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); m = n_randint(state, 10); n = m; padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_one(b); padic_mat_mul(b, a, b, ctx); result = (padic_mat_equal(a, b) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL (A * Id == A):\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("N = %wd\n", N); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check associativity: (a*b)*c == a*(b*c) mod p^{N-v} */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_mat_t a, b, c, d, e, t1, t2; slong k, l, v; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); k = n_randint(state, 10); l = n_randint(state, 10); m = n_randint(state, 10); n = n_randint(state, 10); padic_mat_init2(a, k, l, N); padic_mat_init2(b, l, m, N); padic_mat_init2(c, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_randtest(c, state, ctx); /* v = min(val(a), val(b), val(c), 0) */ v = FLINT_MIN(padic_mat_val(a), padic_mat_val(b)); v = FLINT_MIN(v, padic_mat_val(c)); v = FLINT_MIN(v, 0); if ((v >= 0) || (-v < N)) /* Otherwise, no precision left */ { slong N2 = (v >= 0) ? N : N + v; padic_mat_init2(d, k, n, N2); padic_mat_init2(e, k, n, N2); padic_mat_init2(t1, k, m, N); padic_mat_init2(t2, l, n, N); padic_mat_mul(t1, a, b, ctx); padic_mat_mul(d, t1, c, ctx); padic_mat_mul(t2, b, c, ctx); padic_mat_mul(e, a, t2, ctx); result = (padic_mat_equal(d, e) && padic_mat_is_reduced(d, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_mat_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = "), padic_mat_print_pretty(e, ctx), flint_printf("\n"); flint_printf("t1 = "), padic_mat_print_pretty(t1, ctx), flint_printf("\n"); flint_printf("t2 = "), padic_mat_print_pretty(t2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(d); padic_mat_clear(e); padic_mat_clear(t1); padic_mat_clear(t2); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check distributivity: a(b + c) == ab + ac, precision loss */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_mat_t a, b, c; slong l; slong v; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_VAL_UNIT); l = n_randint(state, 10); m = n_randint(state, 10); n = n_randint(state, 10); padic_mat_init2(a, l, m, N); padic_mat_init2(b, m, n, N); padic_mat_init2(c, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_randtest(c, state, ctx); v = FLINT_MIN(a->val, b->val); v = FLINT_MIN(v, c->val); v = FLINT_MIN(v, 0); if (v >= 0 || -v < N) /* Otherwise, no precision left */ { slong N2 = (v >= 0) ? N : N + v; padic_mat_t lhs, rhs, s, t; padic_mat_init2(lhs, l, n, N2); padic_mat_init2(rhs, l, n, N2); padic_mat_init2(s, m, n, N); padic_mat_init2(t, l, n, N2); padic_mat_add(s, b, c, ctx); padic_mat_mul(lhs, a, s, ctx); padic_mat_mul(rhs, a, b, ctx); padic_mat_mul(t, a, c, ctx); padic_mat_add(rhs, rhs, t, ctx); result = (padic_mat_equal(lhs, rhs) && padic_mat_is_reduced(lhs, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("Hier...\n"); flint_printf("l m n = %wd %wd %wd\n", l, m, n); flint_printf("N = %wd\n", N); flint_printf("N2 = %wd\n", N2); flint_printf("a = "), padic_mat_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_mat_print_pretty(c, ctx), flint_printf("\n"); flint_printf("lhs = "), padic_mat_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), padic_mat_print_pretty(rhs, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(lhs); padic_mat_clear(rhs); padic_mat_clear(s); padic_mat_clear(t); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-neg.c000066400000000000000000000056651461254215100175140ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_neg, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_neg(b, a, ctx); padic_mat_neg(a, a, ctx); result = (padic_mat_equal(a, b) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check a + (-a) == 0 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(c, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_neg(b, a, ctx); padic_mat_add(c, a, b, ctx); result = (padic_mat_is_zero(c) && padic_mat_is_reduced(c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_mat_print(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-scalar_div_fmpz.c000066400000000000000000000036351461254215100221010ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_scalar_div_fmpz, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b; fmpz_t x; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); fmpz_init(x); padic_mat_randtest(a, state, ctx); fmpz_randtest_not_zero(x, state, 10); padic_mat_scalar_div_fmpz(b, a, x, ctx); padic_mat_scalar_div_fmpz(a, a, x, ctx); result = (padic_mat_equal(a, b) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(x); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000036241461254215100221120ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_scalar_mul_fmpz, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b; fmpz_t x; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); fmpz_init(x); padic_mat_randtest(a, state, ctx); fmpz_randtest(x, state, 10); padic_mat_scalar_mul_fmpz(b, a, x, ctx); padic_mat_scalar_mul_fmpz(a, a, x, ctx); result = (padic_mat_equal(a, b) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(x); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-scalar_mul_padic.c000066400000000000000000000036461461254215100222220ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_scalar_mul_padic, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b; padic_t x; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_init2(x, N); padic_mat_randtest(a, state, ctx); padic_randtest(x, state, ctx); padic_mat_scalar_mul_padic(b, a, x, ctx); padic_mat_scalar_mul_padic(a, a, x, ctx); result = (padic_mat_equal(a, b) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("x = "), padic_print(x, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_clear(x); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/test/t-sub.c000066400000000000000000000155231461254215100175260ustar00rootroot00000000000000/* Copyright (C) 2011, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_mat.h" TEST_FUNCTION_START(padic_mat_sub, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; /* Check aliasing: a = a - b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_sub(d, a, b, ctx); padic_mat_sub(a, a, b, ctx); result = (padic_mat_equal(a, d) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: b = a - b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_sub(d, a, b, ctx); padic_mat_sub(b, a, b, ctx); result = (padic_mat_equal(b, d) && padic_mat_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing: a = a - a == 0 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_sub(d, a, a, ctx); padic_mat_sub(a, a, a, ctx); result = (padic_mat_equal(a, d) && padic_mat_is_zero(a)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check commutativity: a - b == -(b - a) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b, c, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 10); n = n_randint(state, 10); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_init2(c, m, n, N); padic_mat_init2(d, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_randtest(b, state, ctx); padic_mat_sub(c, a, b, ctx); padic_mat_sub(d, b, a, ctx); padic_mat_neg(d, d, ctx); result = (padic_mat_equal(c, d) && padic_mat_is_reduced(c, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), padic_mat_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), padic_mat_print_pretty(d, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(c); padic_mat_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check a - 0 == a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_mat_t a, b; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); m = n_randint(state, 20); n = n_randint(state, 20); padic_mat_init2(a, m, n, N); padic_mat_init2(b, m, n, N); padic_mat_randtest(a, state, ctx); padic_mat_sub(b, a, b, ctx); result = (padic_mat_equal(a, b) && padic_mat_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), padic_mat_print(a, ctx), flint_printf("\n"); flint_printf("b = "), padic_mat_print(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_mat/transpose.c000066400000000000000000000010701461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_transpose(padic_mat_t B, const padic_mat_t A) { fmpz_mat_transpose(padic_mat(B), padic_mat(A)); B->val = A->val; } flint-3.1.3/src/padic_mat/zero.c000066400000000000000000000010061461254215100164630ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" void padic_mat_zero(padic_mat_t A) { fmpz_mat_zero(padic_mat(A)); A->val = 0; } flint-3.1.3/src/padic_poly.h000066400000000000000000000271371461254215100157300ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef PADIC_POLY_H #define PADIC_POLY_H #ifdef PADIC_POLY_INLINES_C #define PADIC_POLY_INLINE #else #define PADIC_POLY_INLINE static inline #endif #include "fmpq_types.h" #include "padic_types.h" #include "fmpz.h" #ifdef __cplusplus extern "C" { #endif /* Helper functions ********************************************************/ /* Returns the minimum $p$-adic valuation of \code{(vec, len)}, assuming this fits into a \code{signed long}. If \code{len} is zero, returns $0$. */ PADIC_POLY_INLINE slong _fmpz_vec_ord_p(const fmpz *vec, slong len, const fmpz_t p) { if (len == 0) { return 0; } else { fmpz_t t; slong i, min = WORD_MAX, v; fmpz_init(t); for (i = 0; (min > 0) && (i < len); i++) { if (!fmpz_is_zero(vec + i)) { v = fmpz_remove(t, vec + i, p); min = FLINT_MIN(min, v); } } fmpz_clear(t); return (min < WORD_MAX) ? min : 0; } } /* Memory management *******************************************************/ void padic_poly_init(padic_poly_t poly); void padic_poly_init2(padic_poly_t poly, slong alloc, slong prec); void padic_poly_clear(padic_poly_t poly); void padic_poly_realloc(padic_poly_t f, slong alloc, const fmpz_t p); void padic_poly_fit_length(padic_poly_t f, slong len); PADIC_POLY_INLINE void _padic_poly_set_length(padic_poly_t poly, slong len) { if (poly->length > len) { slong i; for (i = len; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); } poly->length = len; } void _padic_poly_normalise(padic_poly_t f); void _padic_poly_canonicalise(fmpz *poly, slong *v, slong len, const fmpz_t p); void padic_poly_canonicalise(padic_poly_t poly, const fmpz_t p); void padic_poly_reduce(padic_poly_t f, const padic_ctx_t ctx); PADIC_POLY_INLINE void padic_poly_truncate(padic_poly_t poly, slong n, const fmpz_t p) { if (poly->length > n) { slong i; for (i = n; i < poly->length; i++) _fmpz_demote(poly->coeffs + i); poly->length = n; _padic_poly_normalise(poly); padic_poly_canonicalise(poly, p); } } /* Polynomial parameters ***************************************************/ PADIC_POLY_INLINE slong padic_poly_degree(const padic_poly_t poly) { return poly->length - 1; } PADIC_POLY_INLINE slong padic_poly_length(const padic_poly_t poly) { return poly->length; } PADIC_POLY_INLINE slong padic_poly_val(const padic_poly_t poly) { return poly->val; } #define padic_poly_val(poly) ((poly)->val) #define padic_poly_prec(poly) ((poly)->N) /* Randomisation ***********************************************************/ void padic_poly_randtest(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx); void padic_poly_randtest_not_zero(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx); void padic_poly_randtest_val(padic_poly_t f, flint_rand_t state, slong val, slong len, const padic_ctx_t ctx); /* Assignment and basic manipulation ***************************************/ void padic_poly_set(padic_poly_t f, const padic_poly_t g, const padic_ctx_t ctx); void padic_poly_set_padic(padic_poly_t poly, const padic_t x, const padic_ctx_t ctx); void padic_poly_set_si(padic_poly_t poly, slong x, const padic_ctx_t ctx); void padic_poly_set_ui(padic_poly_t poly, ulong x, const padic_ctx_t ctx); void padic_poly_set_fmpz(padic_poly_t poly, const fmpz_t x, const padic_ctx_t ctx); void padic_poly_set_fmpq(padic_poly_t poly, const fmpq_t x, const padic_ctx_t ctx); void padic_poly_set_fmpz_poly(padic_poly_t rop, const fmpz_poly_t op, const padic_ctx_t ctx); void padic_poly_set_fmpq_poly(padic_poly_t rop, const fmpq_poly_t op, const padic_ctx_t ctx); int padic_poly_get_fmpz_poly(fmpz_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx); void padic_poly_get_fmpq_poly(fmpq_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx); PADIC_POLY_INLINE void padic_poly_zero(padic_poly_t poly) { _padic_poly_set_length(poly, 0); poly->val = 0; } PADIC_POLY_INLINE void padic_poly_one(padic_poly_t poly) { if (padic_poly_prec(poly) > 0) { padic_poly_fit_length(poly, 1); fmpz_one(poly->coeffs); _padic_poly_set_length(poly, 1); poly->val = 0; } else { padic_poly_zero(poly); } } void padic_poly_swap(padic_poly_t poly1, padic_poly_t poly2); /* Getting and setting coefficients ****************************************/ void padic_poly_get_coeff_padic(padic_t c, const padic_poly_t poly, slong n, const padic_ctx_t ctx); void padic_poly_set_coeff_padic(padic_poly_t f, slong n, const padic_t c, const padic_ctx_t ctx); /* Comparison **************************************************************/ int padic_poly_equal(const padic_poly_t f, const padic_poly_t g); PADIC_POLY_INLINE int padic_poly_is_zero(const padic_poly_t poly) { return poly->length == 0; } PADIC_POLY_INLINE int padic_poly_is_one(const padic_poly_t poly) { return (poly->length == 1) && fmpz_is_one(poly->coeffs) && (poly->val == 0); } /* Addition and subtraction ************************************************/ void _padic_poly_add(fmpz *rop, slong *rval, slong N, const fmpz *op1, slong val1, slong len1, slong N1, const fmpz *op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx); void padic_poly_add(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx); void _padic_poly_sub(fmpz *rop, slong *rval, slong N, const fmpz *op1, slong val1, slong len1, slong N1, const fmpz *op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx); void padic_poly_sub(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx); void padic_poly_neg(padic_poly_t f, const padic_poly_t g, const padic_ctx_t ctx); /* Scalar multiplication and division **************************************/ void _padic_poly_scalar_mul_padic(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, const padic_t c, const padic_ctx_t ctx); void padic_poly_scalar_mul_padic(padic_poly_t rop, const padic_poly_t op, const padic_t c, const padic_ctx_t ctx); /* Multiplication **********************************************************/ void _padic_poly_mul(fmpz *rop, slong *rval, slong N, const fmpz *op1, slong val1, slong len1, const fmpz *op2, slong val2, slong len2, const padic_ctx_t ctx); void padic_poly_mul(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx); /* Powering ****************************************************************/ void _padic_poly_pow(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, ulong e, const padic_ctx_t ctx); void padic_poly_pow(padic_poly_t rop, const padic_poly_t op, ulong e, const padic_ctx_t ctx); /* Series inversion ********************************************************/ void padic_poly_inv_series(padic_poly_t Qinv, const padic_poly_t Q, slong n, const padic_ctx_t ctx); /* Derivative **************************************************************/ void _padic_poly_derivative(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, const padic_ctx_t ctx); void padic_poly_derivative(padic_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx); /* Shifting ****************************************************************/ void padic_poly_shift_left(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx); void padic_poly_shift_right(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx); /* Evaluation **************************************************************/ void _padic_poly_evaluate_padic(fmpz_t u, slong *v, slong N, const fmpz *poly, slong val, slong len, const fmpz_t a, slong b, const padic_ctx_t ctx); void padic_poly_evaluate_padic(padic_t y, const padic_poly_t poly, const padic_t x, const padic_ctx_t ctx); /* Composition *************************************************************/ void _padic_poly_compose(fmpz *rop, slong *rval, slong N, const fmpz *op1, slong val1, slong len1, const fmpz *op2, slong val2, slong len2, const padic_ctx_t ctx); void padic_poly_compose(padic_poly_t rop, const padic_poly_t op1, const padic_poly_t op2, const padic_ctx_t ctx); void _padic_poly_compose_pow(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, slong k, const padic_ctx_t ctx); void padic_poly_compose_pow(padic_poly_t rop, const padic_poly_t op, slong k, const padic_ctx_t ctx); /* Input and output ********************************************************/ #ifdef FLINT_HAVE_FILE int _padic_poly_fprint(FILE * file, const fmpz * poly, slong val, slong len, const padic_ctx_t ctx); int padic_poly_fprint(FILE * file, const padic_poly_t poly, const padic_ctx_t ctx); int _padic_poly_fprint_pretty(FILE * file, const fmpz * poly, slong val, slong len, const char * var, const padic_ctx_t ctx); int padic_poly_fprint_pretty(FILE * file, const padic_poly_t poly, const char * var, const padic_ctx_t ctx); #endif int _padic_poly_print(const fmpz * poly, slong val, slong len, const padic_ctx_t ctx); int padic_poly_print(const padic_poly_t poly, const padic_ctx_t ctx); int _padic_poly_print_pretty(const fmpz * poly, slong val, slong len, const char * var, const padic_ctx_t ctx); int padic_poly_print_pretty(const padic_poly_t poly, const char * var, const padic_ctx_t ctx); int padic_poly_debug(const padic_poly_t poly); /* Testing *****************************************************************/ int _padic_poly_is_canonical(const fmpz *op, slong val, slong len, const padic_ctx_t ctx); int padic_poly_is_canonical(const padic_poly_t op, const padic_ctx_t ctx); int _padic_poly_is_reduced(const fmpz *op, slong val, slong len, slong N, const padic_ctx_t ctx); int padic_poly_is_reduced(const padic_poly_t op, const padic_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/padic_poly/000077500000000000000000000000001461254215100155455ustar00rootroot00000000000000flint-3.1.3/src/padic_poly/add.c000066400000000000000000000061701461254215100164450ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "padic.h" #include "padic_poly.h" void _padic_poly_add(fmpz *rop, slong *val, slong N, const fmpz *op1, slong val1, slong len1, slong N1, const fmpz *op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx) { const slong len = FLINT_MAX(len1, len2); *val = FLINT_MIN(val1, val2); if (val1 == val2) { _fmpz_poly_add(rop, op1, len1, op2, len2); _padic_poly_canonicalise(rop, val, len, ctx->p); } else /* => (op1 != op2) */ { fmpz_t x; fmpz_init(x); if (val1 < val2) /* F := p^g (G + p^{h-g} H) */ { fmpz_pow_ui(x, ctx->p, val2 - val1); if (rop == op1) { _fmpz_vec_zero(rop + len1, len2 - len1); _fmpz_vec_scalar_addmul_fmpz(rop, op2, len2, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op2, len2, x); _fmpz_poly_add(rop, op1, len1, rop, len2); } } else /* F := p^h (p^{g-h} G + H) */ { fmpz_pow_ui(x, ctx->p, val1 - val2); if (rop == op2) { _fmpz_vec_zero(rop + len2, len1 - len2); _fmpz_vec_scalar_addmul_fmpz(rop, op1, len1, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op1, len1, x); _fmpz_poly_add(rop, rop, len1, op2, len2); } } fmpz_clear(x); } /* Reduce */ if (N - *val > 0) { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N - *val, ctx); _fmpz_vec_scalar_mod_fmpz(rop, rop, len, pow); if (_fmpz_vec_is_zero(rop, len)) *val = 0; if (alloc) fmpz_clear(pow); } else { _fmpz_vec_zero(rop, len); *val = 0; } } void padic_poly_add(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx) { const slong lenG = g->length; const slong lenH = h->length; const slong lenF = FLINT_MAX(lenG, lenH); if (lenG == 0) { padic_poly_set(f, h, ctx); return; } if (lenH == 0) { padic_poly_set(f, g, ctx); return; } if ((lenG == 0 && lenH == 0) || (FLINT_MIN(g->val, h->val) >= f->N)) { padic_poly_zero(f); return; } padic_poly_fit_length(f, lenF); _padic_poly_add(f->coeffs, &(f->val), f->N, g->coeffs, g->val, lenG, g->N, h->coeffs, h->val, lenH, h->N, ctx); _padic_poly_set_length(f, lenF); _padic_poly_normalise(f); } flint-3.1.3/src/padic_poly/canonicalise.c000066400000000000000000000020021461254215100203330ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic_poly.h" void _padic_poly_canonicalise(fmpz *poly, slong *v, slong len, const fmpz_t p) { const slong min = _fmpz_vec_ord_p(poly, len, p); if (min == 0) { if (_fmpz_vec_is_zero(poly, len)) *v = 0; } else /* min > 0 */ { fmpz_t pow; fmpz_init(pow); fmpz_pow_ui(pow, p, min); _fmpz_vec_scalar_divexact_fmpz(poly, poly, len, pow); fmpz_clear(pow); *v += min; } } void padic_poly_canonicalise(padic_poly_t poly, const fmpz_t p) { _padic_poly_canonicalise(poly->coeffs, &(poly->val), poly->length, p); } flint-3.1.3/src/padic_poly/clear.c000066400000000000000000000012651461254215100170030ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2010, 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "padic_poly.h" void padic_poly_clear(padic_poly_t poly) { if (poly->coeffs) { slong i; for (i = 0; i < poly->alloc; i++) _fmpz_demote(poly->coeffs + i); flint_free(poly->coeffs); } } flint-3.1.3/src/padic_poly/compose.c000066400000000000000000000125211461254215100173570ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "padic.h" #include "padic_poly.h" /* TODO: Move this bit of code into "padic". */ static void __padic_reduce(fmpz_t u, slong *v, slong N, const padic_ctx_t ctx) { if (!fmpz_is_zero(u)) { if (*v < N) { int alloc; fmpz_t pow; alloc = _padic_ctx_pow_ui(pow, N - *v, ctx); fmpz_mod(u, u, pow); if (alloc) fmpz_clear(pow); } else { fmpz_zero(u); *v = 0; } } } /* Assumes that len1 > 0. */ void _padic_poly_compose(fmpz *rop, slong *rval, slong N, const fmpz *op1, slong val1, slong len1, const fmpz *op2, slong val2, slong len2, const padic_ctx_t ctx) { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (len1 == 1 || len2 == 0) { fmpz_set(rop, op1); *rval = val1; __padic_reduce(rop, rval, N, ctx); } else if (val2 >= 0) { if (val1 >= N) { _fmpz_vec_zero(rop, lenr); *rval = 0; } else { fmpz *vec1, *vec2; fmpz_t f; fmpz_t pow; int alloc; vec1 = _fmpz_vec_init(len1); vec2 = _fmpz_vec_init(len2); fmpz_init(f); fmpz_pow_ui(f, ctx->p, val2); _fmpz_vec_scalar_mul_fmpz(vec2, op2, len2, f); alloc = _padic_ctx_pow_ui(pow, N - val1, ctx); _fmpz_vec_scalar_mod_fmpz(vec1, op1, len1, pow); _fmpz_vec_scalar_mod_fmpz(vec2, vec2, len2, pow); fmpz_mod_ctx_t nctx; fmpz_mod_ctx_init(nctx, pow); _fmpz_mod_poly_compose(rop, vec1, len1, vec2, len2, nctx); fmpz_mod_ctx_clear(nctx); *rval= val1; _padic_poly_canonicalise(rop, rval, lenr, ctx->p); _fmpz_vec_clear(vec2, len2); _fmpz_vec_clear(vec1, len1); fmpz_clear(f); if (alloc) fmpz_clear(pow); } } else /* val2 < 0 */ { const slong n = len1 - 1; if (val1 + n*val2 >= N) { _fmpz_vec_zero(rop, lenr); *rval = 0; } else { fmpz_t pow; int alloc; fmpz *vec1, *vec2; fmpz_t s, t; slong i; vec1 = _fmpz_vec_init(len1); vec2 = _fmpz_vec_init(len2); fmpz_init(s); fmpz_init(t); alloc = _padic_ctx_pow_ui(pow, N - val1 - n*val2, ctx); fmpz_pow_ui(s, ctx->p, -val2); fmpz_one(t); fmpz_set(vec1 + (len1 - 1), op1 + (len1 - 1)); for (i = len1 - 2; i >= 0; i--) { fmpz_mul(t, t, s); fmpz_mul(vec1 + i, op1 + i, t); } _fmpz_vec_scalar_mod_fmpz(vec1, vec1, len1, pow); _fmpz_vec_scalar_mod_fmpz(vec2, op2, len2, pow); fmpz_mod_ctx_t nctx; fmpz_mod_ctx_init(nctx, pow); _fmpz_mod_poly_compose(rop, vec1, len1, vec2, len2, nctx); fmpz_mod_ctx_clear(nctx); *rval = val1 + n*val2; _padic_poly_canonicalise(rop, rval, lenr, ctx->p); _fmpz_vec_clear(vec1, len1); _fmpz_vec_clear(vec2, len2); fmpz_clear(s); fmpz_clear(t); if (alloc) fmpz_clear(pow); } } } void padic_poly_compose(padic_poly_t rop, const padic_poly_t op1, const padic_poly_t op2, const padic_ctx_t ctx) { const slong len1 = op1->length, len2 = op2->length; if (len1 == 0) { padic_poly_zero(rop); } else if (len1 == 1 || len2 == 0) { padic_poly_fit_length(rop, 1); fmpz_set(rop->coeffs, op1->coeffs); rop->val = op1->val; _padic_poly_set_length(rop, 1); padic_poly_canonicalise(rop, ctx->p); padic_poly_reduce(rop, ctx); } else { const slong lenr = (len1 - 1) * (len2 - 1) + 1; if (rop != op1 && rop != op2) { padic_poly_fit_length(rop, lenr); _padic_poly_compose(rop->coeffs, &(rop->val), rop->N, op1->coeffs, op1->val, op1->length, op2->coeffs, op2->val, op2->length, ctx); _padic_poly_set_length(rop, lenr); } else { fmpz *t = _fmpz_vec_init(lenr); _padic_poly_compose(t, &(rop->val), rop->N, op1->coeffs, op1->val, op1->length, op2->coeffs, op2->val, op2->length, ctx); _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = lenr; rop->length = lenr; } _padic_poly_normalise(rop); } } flint-3.1.3/src/padic_poly/compose_pow.c000066400000000000000000000042771461254215100202550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "padic.h" #include "padic_poly.h" /* TODO: Move this bit of code into "padic". */ static void __padic_reduce(fmpz_t u, slong *v, slong N, const padic_ctx_t ctx) { if (!fmpz_is_zero(u)) { if (*v < N) { int alloc; fmpz_t pow; alloc = _padic_ctx_pow_ui(pow, N - *v, ctx); fmpz_mod(u, u, pow); if (alloc) fmpz_clear(pow); } else { fmpz_zero(u); *v = 0; } } } void _padic_poly_compose_pow(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, slong k, const padic_ctx_t ctx) { if (k == 1) { if (rop != op) { _fmpz_vec_set(rop, op, len); *rval = val; } } else if (len == 1) { fmpz_set(rop, op); *rval = val; __padic_reduce(rop, rval, N, ctx); } else { slong i, j, h; for (i = len - 1, j = (len - 1) * k ; i >= 0; i--, j -= k) { fmpz_set(rop + j, op + i); if (i) for (h = 1; h < k; h++) fmpz_zero(rop + (j - h)); } *rval = val; } } void padic_poly_compose_pow(padic_poly_t rop, const padic_poly_t op, slong k, const padic_ctx_t ctx) { const slong len = op->length; const slong lenr = (len - 1) * k + 1; if (len == 0) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, lenr); _padic_poly_compose_pow(rop->coeffs, &(rop->val), rop->N, op->coeffs, op->val, op->length, k, ctx); _padic_poly_set_length(rop, lenr); } } flint-3.1.3/src/padic_poly/derivative.c000066400000000000000000000026731461254215100200630ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "padic.h" #include "padic_poly.h" void _padic_poly_derivative(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, const padic_ctx_t ctx) { fmpz_t pow; int alloc; _fmpz_poly_derivative(rop, op, len); *rval = val; alloc = _padic_ctx_pow_ui(pow, N - *rval, ctx); _fmpz_vec_scalar_mod_fmpz(rop, rop, len - 1, pow); _padic_poly_canonicalise(rop, rval, len - 1, ctx->p); if (alloc) fmpz_clear(pow); } void padic_poly_derivative(padic_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx) { const slong len = op->length; if (len < 2 || op->val >= rop->N) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, len - 1); _padic_poly_derivative(rop->coeffs, &(rop->val), rop->N, op->coeffs, op->val, len, ctx); _padic_poly_set_length(rop, len - 1); _padic_poly_normalise(rop); } } flint-3.1.3/src/padic_poly/equal.c000066400000000000000000000012631461254215100170220ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic_poly.h" int padic_poly_equal(const padic_poly_t f, const padic_poly_t g) { if (f == g) { return 1; } if (f->length != g->length || f->val != g->val) { return 0; } return _fmpz_vec_equal(f->coeffs, g->coeffs, f->length); } flint-3.1.3/src/padic_poly/evaluate_padic.c000066400000000000000000000124651461254215100206670ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "padic.h" #include "padic_poly.h" static void _fmpz_mod_poly_evaluate_fmpz_horner(fmpz_t res, const fmpz *poly, slong len, const fmpz_t a, const fmpz_t p) { if (len == 0) { fmpz_zero(res); } else if (len == 1 || fmpz_is_zero(a)) { fmpz_set(res, poly); } else { slong i = len - 1; fmpz_t t; fmpz_init(t); fmpz_set(res, poly + i); for (i = len - 2; i >= 0; i--) { fmpz_mul(t, res, a); fmpz_mod(t, t, p); fmpz_add(res, poly + i, t); } fmpz_clear(t); if (fmpz_cmpabs(res, p) >= 0) fmpz_sub(res, res, p); } } /* TODO: Move this bit of code into "padic". */ static void __padic_reduce(fmpz_t u, slong *v, slong N, const padic_ctx_t ctx) { if (!fmpz_is_zero(u)) { if (*v < N) { int alloc; fmpz_t pow; alloc = _padic_ctx_pow_ui(pow, N - *v, ctx); fmpz_mod(u, u, pow); if (alloc) fmpz_clear(pow); } else { fmpz_zero(u); *v = 0; } } } /* Evaluates the polynomial $F(x) = p^w f(x)$ at $x = p^b a$, setting $y = p^v u$ to the result reduced modulo $p^N$. Suppose first that $b \geq 0$, in which case we can quickly relay the call to the \code{fmpz_mod_poly} module. Namely, we need to compute $f(x) \bmod {p^{N-w}}$ where we know $f(x)$ to be integral. Otherwise, suppose now that $b < 0$ and we still wish to evaluate $f(x) \bmod {p^{N-w}}$. \begin{align*} f(x) & = \sum_{i = 0}^{n} a_i x^i \\ & = \sum_{i = 0}^{n} a_i p^{i b} a^i \\ \intertext{Multiplying through by $p^{- n b} \in \mathbf{Z}$, } p^{-nb} f(x) & = \sum_{i = 0}^{n} a_i p^{-(n-i)b} a \end{align*} which leaves the right hand side integral. As we want to compute $f(x)$ to precision $N-w$, we have to compute $p^{-nb} f(x)$ to precision $N-w-nb$. */ void _padic_poly_evaluate_padic(fmpz_t u, slong *v, slong N, const fmpz *poly, slong val, slong len, const fmpz_t a, slong b, const padic_ctx_t ctx) { if (len == 0) { fmpz_zero(u); *v = 0; } else if (len == 1) { fmpz_set(u, poly); *v = val; __padic_reduce(u, v, N, ctx); } else if (b >= 0) { if (val >= N) { fmpz_zero(u); *v = 0; } else { fmpz_t x; fmpz_t pow; int alloc; fmpz_init(x); alloc = _padic_ctx_pow_ui(pow, N - val, ctx); fmpz_pow_ui(x, ctx->p, b); fmpz_mul(x, x, a); _fmpz_mod_poly_evaluate_fmpz_horner(u, poly, len, x, pow); if (!fmpz_is_zero(u)) *v = val + _fmpz_remove(u, ctx->p, ctx->pinv); else *v = 0; fmpz_clear(x); if (alloc) fmpz_clear(pow); } } else /* b < 0 */ { const slong n = len - 1; if (val + n*b >= N) { fmpz_zero(u); *v = 0; } else { fmpz_t pow; int alloc; slong i; fmpz_t s, t; fmpz *vec = _fmpz_vec_init(len); fmpz_init(s); fmpz_init(t); alloc = _padic_ctx_pow_ui(pow, N - val - n*b, ctx); fmpz_pow_ui(s, ctx->p, -b); fmpz_one(t); fmpz_set(vec + (len - 1), poly + (len - 1)); for (i = len - 2; i >= 0; i--) { fmpz_mul(t, t, s); fmpz_mul(vec + i, poly + i, t); } _fmpz_mod_poly_evaluate_fmpz_horner(u, vec, len, a, pow); if (!fmpz_is_zero(u)) *v = val + n*b + _fmpz_remove(u, ctx->p, ctx->pinv); else *v = 0; if (alloc) fmpz_clear(pow); fmpz_clear(s); fmpz_clear(t); _fmpz_vec_clear(vec, len); } } } void padic_poly_evaluate_padic(padic_t y, const padic_poly_t poly, const padic_t x, const padic_ctx_t ctx) { if (y == x) { padic_t t; padic_init2(t, padic_prec(y)); _padic_poly_evaluate_padic(padic_unit(t), &padic_val(t), padic_prec(t), poly->coeffs, poly->val, poly->length, padic_unit(x), padic_val(x), ctx); padic_swap(y, t); padic_clear(t); } else { _padic_poly_evaluate_padic(padic_unit(y), &padic_val(y), padic_prec(y), poly->coeffs, poly->val, poly->length, padic_unit(x), padic_val(x), ctx); } } flint-3.1.3/src/padic_poly/fit_length.c000066400000000000000000000020601461254215100200320ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "padic_poly.h" void padic_poly_fit_length(padic_poly_t poly, slong len) { if (len > poly->alloc) { if (len < 2 * poly->alloc) len = 2 * poly->alloc; if (poly->alloc) /* Realloc */ { poly->coeffs = (fmpz *) flint_realloc(poly->coeffs, len * sizeof(fmpz)); mpn_zero((mp_ptr) (poly->coeffs + poly->alloc), len - poly->alloc); } else /* Nothing allocated already so do it now */ { poly->coeffs = (fmpz *) flint_calloc(len, sizeof(fmpz)); } poly->alloc = len; } } flint-3.1.3/src/padic_poly/get_coeff_padic.c000066400000000000000000000014611461254215100207740ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_get_coeff_padic(padic_t x, const padic_poly_t f, slong n, const padic_ctx_t ctx) { if (n < f->length && !fmpz_is_zero(f->coeffs + n)) { fmpz_set(padic_unit(x), f->coeffs + n); padic_val(x) = f->val; padic_prec(x) = f->N; padic_reduce(x, ctx); } else { padic_zero(x); } } flint-3.1.3/src/padic_poly/get_fmpq_poly.c000066400000000000000000000031561461254215100205630ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_poly.h" #include "padic_poly.h" /* Assumes that len > 0. */ static void _padic_poly_get_fmpq_poly(fmpz *rop, fmpz_t den, const fmpz *op, slong val, slong len, const fmpz_t p) { if (val == 0) { _fmpz_vec_set(rop, op, len); fmpz_one(den); } else if (val == 1) { _fmpz_vec_scalar_mul_fmpz(rop, op, len, p); fmpz_one(den); } else if (val > 1) { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, val); _fmpz_vec_scalar_mul_fmpz(rop, op, len, t); fmpz_one(den); fmpz_clear(t); } else { _fmpz_vec_set(rop, op, len); fmpz_pow_ui(den, p, -val); } } void padic_poly_get_fmpq_poly(fmpq_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx) { const slong len = op->length; if (len == 0) { fmpq_poly_zero(rop); } else { fmpq_poly_fit_length(rop, len); _padic_poly_get_fmpq_poly(rop->coeffs, rop->den, op->coeffs, op->val, op->length, ctx->p); _fmpq_poly_set_length(rop, len); } } flint-3.1.3/src/padic_poly/get_fmpz_poly.c000066400000000000000000000022051461254215100205660ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "padic_poly.h" int padic_poly_get_fmpz_poly(fmpz_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx) { const slong len = op->length; if (op->val < 0) { return 0; } if (padic_poly_is_zero(op)) { fmpz_poly_zero(rop); return 1; } fmpz_poly_fit_length(rop, len); _fmpz_poly_set_length(rop, len); if (op->val == 0) { _fmpz_vec_set(rop->coeffs, op->coeffs, len); } else /* op->val > 0 */ { fmpz_t pow; fmpz_init(pow); fmpz_pow_ui(pow, ctx->p, op->val); _fmpz_vec_scalar_mul_fmpz(rop->coeffs, op->coeffs, len, pow); fmpz_clear(pow); } return 1; } flint-3.1.3/src/padic_poly/init.c000066400000000000000000000015761461254215100166650ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_init(padic_poly_t poly) { poly->coeffs = NULL; poly->alloc = 0; poly->length = 0; poly->val = 0; poly->N = PADIC_DEFAULT_PREC; } void padic_poly_init2(padic_poly_t poly, slong alloc, slong prec) { poly->coeffs = alloc ? (fmpz *) flint_calloc(alloc, sizeof(fmpz)) : NULL; poly->alloc = alloc; poly->length = 0; poly->val = 0; poly->N = prec; } flint-3.1.3/src/padic_poly/inlines.c000066400000000000000000000007031461254215100173520ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define PADIC_POLY_INLINES_C #include "flint.h" #include "padic_poly.h" flint-3.1.3/src/padic_poly/inv_series.c000066400000000000000000000071011461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz Copyright (C) 2023 This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "padic.h" #include "padic_poly.h" /* The tests fail if one reduces the coefficients modulo N before doing the calculation in Z/NZ. Therefore _fmpz_mod_poly_inv_series cannot be used. To do: explain why this particular algorithm, given non-normalized input, gives the expected result. */ static void _fmpz_mod_poly_inv_series_pure_newton(fmpz * Qinv, const fmpz * Q, slong n, const fmpz_t cinv, const fmpz_t p) { if (n == 1) { fmpz_set(Qinv, cinv); } else { const slong alloc = FLINT_MAX(n, 3); slong a[FLINT_BITS], i, m; fmpz *W; W = _fmpz_vec_init(alloc); for (i = 1; (WORD(1) << i) < n; i++) ; a[i = 0] = n; while (n >= 2) a[++i] = (n = (n + 1) / 2); /* Base case */ fmpz_set(Qinv, cinv); for (i--; i >= 0; i--) { m = n; n = a[i]; _fmpz_poly_mullow(W, Q, n, Qinv, m, n); _fmpz_vec_scalar_mod_fmpz(W, W, n, p); _fmpz_poly_mullow(Qinv + m, Qinv, m, W + m, n - m, n - m); _fmpz_vec_neg(Qinv + m, Qinv + m, n - m); _fmpz_vec_scalar_mod_fmpz(Qinv + m, Qinv + m, n - m, p); } _fmpz_vec_clear(W, alloc); } } void padic_poly_inv_series(padic_poly_t Qinv, const padic_poly_t Q, slong n, const padic_ctx_t ctx) { fmpz_t cinv; fmpz_t pow; int palloc; fmpz *Qcopy; int Qalloc; if (Q->length == 0 || fmpz_is_zero(Q->coeffs + 0)) { flint_throw(FLINT_ERROR, "Exception (padic_poly_inv_series): Constant term is zero.\n"); } if (fmpz_divisible(Q->coeffs + 0, ctx->p)) { flint_throw(FLINT_ERROR, "Exception (padic_poly_inv_series):\nValuation of constant term is not minimal.\n"); } if (- Q->val >= Qinv->N) { padic_poly_zero(Qinv); return; } if (Q->length >= n) { Qcopy = Q->coeffs; Qalloc = 0; } else { slong i; Qcopy = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < Q->length; i++) Qcopy[i] = Q->coeffs[i]; mpn_zero((mp_ptr) Qcopy + i, n - i); Qalloc = 1; } fmpz_init(cinv); fmpz_init(pow); _padic_inv(cinv, Q->coeffs, ctx->p, Qinv->N + Q->val); palloc = _padic_ctx_pow_ui(pow, Qinv->N + Q->val, ctx); if (Qinv != Q) { padic_poly_fit_length(Qinv, n); /* fails: _fmpz_vec_scalar_mod_fmpz(Qcopy, Qcopy, n, pow); */ _fmpz_mod_poly_inv_series_pure_newton(Qinv->coeffs, Qcopy, n, cinv, pow); } else { fmpz *t = _fmpz_vec_init(n); /* fails: _fmpz_vec_scalar_mod_fmpz(Qcopy, Qcopy, n, pow); */ _fmpz_mod_poly_inv_series_pure_newton(t, Qcopy, n, cinv, pow); _fmpz_vec_clear(Qinv->coeffs, Qinv->alloc); Qinv->coeffs = t; Qinv->alloc = n; Qinv->length = n; } Qinv->val = - Q->val; _padic_poly_set_length(Qinv, n); _padic_poly_normalise(Qinv); fmpz_clear(cinv); if (palloc) fmpz_clear(pow); if (Qalloc) flint_free(Qcopy); } flint-3.1.3/src/padic_poly/io.c000066400000000000000000000136131461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.h" #include "padic.h" #include "padic_poly.h" int _padic_poly_fprint(FILE *file, const fmpz *poly, slong val, slong len, const padic_ctx_t ctx) { slong i, v; fmpz_t u; if (len == 0) { flint_fprintf(file, "0"); return 1; } fmpz_init(u); flint_fprintf(file, "%wd ", len); for (i = 0; i < len; i++) { flint_fprintf(file, " "); if (fmpz_is_zero(poly + i)) { flint_fprintf(file, "0"); } else { v = val + fmpz_remove(u, poly + i, ctx->p); _padic_fprint(file, u, v, ctx); } } fmpz_clear(u); return 1; } int _padic_poly_fprint_pretty(FILE *file, const fmpz *poly, slong len, slong val, const char *var, const padic_ctx_t ctx) { slong i; padic_t x; padic_init(x); /* Precision is not used anywhere! */ if (len == 0) { fputc('0', file); } else if (len == 1) { _padic_fprint(file, poly + 0, val, ctx); } else if (len == 2) { fmpz_set(padic_unit(x), poly + 1); padic_val(x) = val; _padic_canonicalise(x, ctx); if (padic_is_one(x)) { flint_fprintf(file, "%s", var); } else if (*(padic_unit(x)) == WORD(-1) && padic_val(x) == 0) { flint_fprintf(file, "-%s", var); } else { fputc('(', file); padic_fprint(file, x, ctx); fputc(')', file); flint_fprintf(file, "*%s", var); } fmpz_abs(padic_unit(x), poly); padic_val(x) = val; _padic_canonicalise(x, ctx); if (fmpz_sgn(poly) > 0) { fputc('+', file); } else if (fmpz_sgn(poly) < 0) { fputc('-', file); } fputc('(', file); padic_fprint(file, x, ctx); fputc(')', file); } else /* len >= 3 */ { i = len - 1; /* i >= 2 */ { fmpz_set(padic_unit(x), poly + i); padic_val(x) = val; _padic_canonicalise(x, ctx); if (padic_is_one(x)) flint_fprintf(file, "%s^%wd", var, i); else if (*(padic_unit(x)) == WORD(-1) && padic_val(x) == 0) flint_fprintf(file, "-%s^%wd", var, i); else { fputc('(', file); padic_fprint(file, x, ctx); fputc(')', file); flint_fprintf(file, "*%s^%wd", var, i); } --i; } for (; i > 1; --i) { if (*(poly + i) == 0) continue; fmpz_abs(padic_unit(x), poly + i); padic_val(x) = val; _padic_canonicalise(x, ctx); if (fmpz_sgn(poly + i) > 0) fputc('+', file); else fputc('-', file); if (padic_is_one(x)) flint_fprintf(file, "%s^%wd", var, i); else { fputc('(', file); padic_fprint(file, x, ctx); fputc(')', file); flint_fprintf(file, "*%s^%wd", var, i); } } if (*(poly + 1)) { fmpz_abs(padic_unit(x), poly + 1); padic_val(x) = val; _padic_canonicalise(x, ctx); fputc(fmpz_sgn(poly + 1) > 0 ? '+' : '-', file); if (padic_is_one(x)) fputs(var, file); else { fputc('(', file); padic_fprint(file, x, ctx); fputc(')', file); fputc('*', file); fputs(var, file); } } if (*(poly)) { fmpz_abs(padic_unit(x), poly); padic_val(x) = val; _padic_canonicalise(x, ctx); fputc(fmpz_sgn(poly) > 0 ? '+' : '-', file); fputc('(', file); padic_fprint(file, x, ctx); fputc(')', file); } } padic_clear(x); return 1; } int padic_poly_fprint(FILE *file, const padic_poly_t poly, const padic_ctx_t ctx) { return _padic_poly_fprint(file, poly->coeffs, poly->val, poly->length, ctx); } int padic_poly_fprint_pretty(FILE * file, const padic_poly_t poly, const char * var, const padic_ctx_t ctx) { return _padic_poly_fprint_pretty(file, poly->coeffs, poly->length, poly->val, var, ctx); } int _padic_poly_print(const fmpz *poly, slong val, slong len, const padic_ctx_t ctx) { return _padic_poly_fprint(stdout, poly, val, len, ctx); } int padic_poly_print(const padic_poly_t poly, const padic_ctx_t ctx) { return padic_poly_fprint(stdout, poly, ctx); } int _padic_poly_print_pretty(const fmpz *poly, slong val, slong len, const char *var, const padic_ctx_t ctx) { return _padic_poly_fprint_pretty(stdout, poly, val, len, var, ctx); } int padic_poly_print_pretty(const padic_poly_t poly, const char *var, const padic_ctx_t ctx) { return padic_poly_fprint_pretty(stdout, poly, var, ctx); } int padic_poly_debug(const padic_poly_t poly) { flint_printf("(alloc = %wd, length = %wd, val = %wd, N = %wd, vec = ", poly->alloc, poly->length, poly->val, poly->N); if (poly->coeffs) { flint_printf("{"); _fmpz_vec_print(poly->coeffs, poly->alloc); flint_printf("}"); } else { flint_printf("NULL"); } flint_printf(")"); return 1; } flint-3.1.3/src/padic_poly/is_canonical.c000066400000000000000000000015121461254215100203320ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic_poly.h" int _padic_poly_is_canonical(const fmpz *op, slong val, slong len, const padic_ctx_t ctx) { if (len == 0) { return (val == 0); } else { slong w = _fmpz_vec_ord_p(op, len, ctx->p); return (w == 0); } } int padic_poly_is_canonical(const padic_poly_t op, const padic_ctx_t ctx) { return _padic_poly_is_canonical(op->coeffs, op->val, op->length, ctx); } flint-3.1.3/src/padic_poly/is_reduced.c000066400000000000000000000023171461254215100200220ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" int _padic_poly_is_reduced(const fmpz *op, slong val, slong len, slong N, const padic_ctx_t ctx) { slong w; if (len == 0) { return (val == 0); } w = _fmpz_vec_ord_p(op, len, ctx->p); if (w != 0 || val >= N) { return 0; } { fmpz_t pow; int r, alloc; slong i; alloc = _padic_ctx_pow_ui(pow, N - val, ctx); r = 1; for (i = 0; (i < len) && (r); i++) if (fmpz_sgn(op + i) < 0 || fmpz_cmp(op + i, pow) >= 0) r = 0; if (alloc) fmpz_clear(pow); return r; } } int padic_poly_is_reduced(const padic_poly_t op, const padic_ctx_t ctx) { return _padic_poly_is_reduced(op->coeffs, op->val, op->length, op->N, ctx); } flint-3.1.3/src/padic_poly/mul.c000066400000000000000000000041101461254215100165020ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "padic.h" #include "padic_poly.h" void _padic_poly_mul(fmpz *rop, slong *rval, slong N, const fmpz *op1, slong val1, slong len1, const fmpz *op2, slong val2, slong len2, const padic_ctx_t ctx) { fmpz_t pow; int alloc; *rval = val1 + val2; alloc = _padic_ctx_pow_ui(pow, N - *rval, ctx); _fmpz_poly_mul(rop, op1, len1, op2, len2); _fmpz_vec_scalar_mod_fmpz(rop, rop, len1 + len2 - 1, pow); if (alloc) fmpz_clear(pow); } void padic_poly_mul(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx) { const slong lenG = g->length; const slong lenH = h->length; const slong lenF = lenG + lenH - 1; if (lenG == 0 || lenH == 0 || g->val + h->val >= f->N) { padic_poly_zero(f); } else { fmpz *t; if (f == g || f == h) { t = _fmpz_vec_init(lenF); } else { padic_poly_fit_length(f, lenF); t = f->coeffs; } if (lenG >= lenH) _padic_poly_mul(t, &(f->val), f->N, g->coeffs, g->val, lenG, h->coeffs, h->val, lenH, ctx); else _padic_poly_mul(t, &(f->val), f->N, h->coeffs, h->val, lenH, g->coeffs, g->val, lenG, ctx); if (f == g || f == h) { _fmpz_vec_clear(f->coeffs, f->alloc); f->coeffs = t; f->alloc = lenF; } _padic_poly_set_length(f, lenF); _padic_poly_normalise(f); } } flint-3.1.3/src/padic_poly/neg.c000066400000000000000000000031501461254215100164610ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "padic.h" #include "padic_poly.h" static void _fmpz_vec_neg_mod(fmpz * a, const fmpz * b, slong len, const fmpz_t m) { slong i; for (i = 0; i < len; i++) { fmpz_neg(a + i, b + i); if (fmpz_sgn(a + i) < 0) fmpz_add(a + i, a + i, m); } } void padic_poly_neg(padic_poly_t f, const padic_poly_t g, const padic_ctx_t ctx) { const slong len = g->length; if (len == 0 || g->val >= padic_poly_prec(f)) { padic_poly_zero(f); } else { fmpz_t pow; int alloc; padic_poly_fit_length(f, len); _padic_poly_set_length(f, len); f->val = g->val; alloc = _padic_ctx_pow_ui(pow, padic_poly_prec(f) - f->val, ctx); if (padic_poly_prec(f) >= padic_poly_prec(g)) /* No reduction */ { _fmpz_vec_neg_mod(f->coeffs, g->coeffs, len, pow); } else /* Reduction necessary? */ { _fmpz_vec_scalar_mod_fmpz(f->coeffs, g->coeffs, len, pow); _fmpz_vec_neg_mod(f->coeffs, f->coeffs, len, pow); _padic_poly_normalise(f); } if (alloc) fmpz_clear(pow); } } flint-3.1.3/src/padic_poly/normalise.c000066400000000000000000000011511461254215100177000ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic_poly.h" void _padic_poly_normalise(padic_poly_t poly) { slong len = poly->length; FMPZ_VEC_NORM(poly->coeffs, len); poly->length = len; } flint-3.1.3/src/padic_poly/pow.c000066400000000000000000000041051461254215100165160ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "padic.h" #include "padic_poly.h" void _padic_poly_pow(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, ulong e, const padic_ctx_t ctx) { fmpz_t pow; int alloc; *rval = (slong) e * val; alloc = _padic_ctx_pow_ui(pow, N - *rval, ctx); { fmpz * t; fmpz_mod_ctx_t mod; fmpz_mod_ctx_init(mod, pow); t = _fmpz_vec_init(len); _fmpz_vec_scalar_mod_fmpz(t, op, len, pow); _fmpz_mod_poly_pow(rop, op, len, e, mod); fmpz_mod_ctx_clear(mod); _fmpz_vec_clear(t, len); } if (alloc) fmpz_clear(pow); } void padic_poly_pow(padic_poly_t rop, const padic_poly_t op, ulong e, const padic_ctx_t ctx) { if (e == 0) { padic_poly_one(rop); } else if (op->length == 0 || (slong) e * op->val >= rop->N) { padic_poly_zero(rop); } else if (e == 1) { padic_poly_set(rop, op, ctx); } else { const slong rlen = (slong) e * (op->length - 1) + 1; fmpz *t; if (rop == op) { t = _fmpz_vec_init(rlen); } else { padic_poly_fit_length(rop, rlen); t = rop->coeffs; } _padic_poly_pow(t, &(rop->val), rop->N, op->coeffs, op->val, op->length, e, ctx); if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = rlen; } _padic_poly_set_length(rop, rlen); _padic_poly_normalise(rop); } } flint-3.1.3/src/padic_poly/randtest.c000066400000000000000000000047261461254215100175460ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_randtest_val(padic_poly_t f, flint_rand_t state, slong val, slong len, const padic_ctx_t ctx) { const slong N = padic_poly_prec(f); if (len == 0) return; if (val >= N) { padic_poly_zero(f); } else { slong i; fmpz_t pow; int alloc; f->val = val; padic_poly_fit_length(f, len); alloc = _padic_ctx_pow_ui(pow, N - f->val, ctx); for (i = 0; i < len; i++) fmpz_randm(f->coeffs + i, state, pow); if (alloc) fmpz_clear(pow); for (i = 0; i < len; i++) if (!fmpz_divisible(f->coeffs + i, ctx->p)) break; if (i == len) fmpz_one(f->coeffs + n_randint(state, len)); _padic_poly_set_length(f, len); _padic_poly_normalise(f); padic_poly_reduce(f, ctx); } } void padic_poly_randtest(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx) { const slong N = padic_poly_prec(f); slong min, max, val; if (N > 0) { min = - ((N + 9) / 10); max = N; } else if (N < 0) { min = N - ((-N + 9) / 10); max = N; } else /* N == 0 */ { min = -10; max = 0; } val = n_randint(state, max - min) + min; padic_poly_randtest_val(f, state, val, len, ctx); } void padic_poly_randtest_not_zero(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx) { slong i; if (len == 0) { flint_throw(FLINT_ERROR, "Exception (padic_poly_randtest_not_zero). len == 0.\n"); } padic_poly_randtest(f, state, len, ctx); for (i = 0; !padic_poly_is_zero(f) && (i < 10); i++) padic_poly_randtest(f, state, len, ctx); if (padic_poly_is_zero(f)) { padic_poly_fit_length(f, 1); _padic_poly_set_length(f, 1); fmpz_one(f->coeffs + 0); f->val = f->N - 1; } } flint-3.1.3/src/padic_poly/realloc.c000066400000000000000000000023061461254215100173330ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "padic_poly.h" void padic_poly_realloc(padic_poly_t poly, slong alloc, const fmpz_t p) { if (alloc == 0) /* Clear up, reinitialise */ { padic_poly_clear(poly); padic_poly_init(poly); return; } if (poly->alloc) /* Realloc */ { padic_poly_truncate(poly, alloc, p); poly->coeffs = (fmpz *) flint_realloc(poly->coeffs, alloc * sizeof(fmpz)); if (alloc > poly->alloc) mpn_zero((mp_ptr) (poly->coeffs + poly->alloc), alloc - poly->alloc); } else /* Nothing allocated already so do it now */ { poly->coeffs = (fmpz *) flint_calloc(alloc, sizeof(fmpz)); } poly->alloc = alloc; } flint-3.1.3/src/padic_poly/reduce.c000066400000000000000000000021341461254215100171600ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" #include "padic_poly.h" void padic_poly_reduce(padic_poly_t poly, const padic_ctx_t ctx) { const slong N = padic_poly_prec(poly); if (poly->length > 0) { if (poly->val >= N) { padic_poly_zero(poly); } else { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N - poly->val, ctx); _fmpz_vec_scalar_mod_fmpz(poly->coeffs, poly->coeffs, poly->length, pow); if (alloc) fmpz_clear(pow); _padic_poly_normalise(poly); if (poly->length == 0) { poly->val = 0; } } } } flint-3.1.3/src/padic_poly/scalar_mul_padic.c000066400000000000000000000032121461254215100211710ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" #include "padic_poly.h" void _padic_poly_scalar_mul_padic(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, const padic_t c, const padic_ctx_t ctx) { if (padic_is_zero(c) || val + padic_val(c) >= N) { _fmpz_vec_zero(rop, len); *rval = 0; } else { fmpz_t pow; int alloc; *rval = val + padic_val(c); alloc = _padic_ctx_pow_ui(pow, N - *rval, ctx); _fmpz_vec_scalar_mul_fmpz(rop, op, len, padic_unit(c)); _fmpz_vec_scalar_mod_fmpz(rop, rop, len, pow); if (alloc) fmpz_clear(pow); } } void padic_poly_scalar_mul_padic(padic_poly_t rop, const padic_poly_t op, const padic_t c, const padic_ctx_t ctx) { if (padic_poly_is_zero(op) || padic_is_zero(c) || op->val + padic_val(c) >= rop->N) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, op->length); _padic_poly_set_length(rop, op->length); _padic_poly_scalar_mul_padic(rop->coeffs, &(rop->val), rop->N, op->coeffs, op->val, op->length, c, ctx); } } flint-3.1.3/src/padic_poly/set.c000066400000000000000000000032731461254215100165110ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" #include "padic_poly.h" void padic_poly_set(padic_poly_t poly1, const padic_poly_t poly2, const padic_ctx_t ctx) { if (poly1 != poly2) /* Aliasing is trivial */ { slong len2 = poly2->length, N1 = padic_poly_prec(poly1); if (len2 == 0 || poly2->val >= N1) { padic_poly_zero(poly1); } else { padic_poly_fit_length(poly1, len2); _padic_poly_set_length(poly1, len2); poly1->val = poly2->val; if (N1 >= padic_poly_prec(poly2)) /* No reduction */ { _fmpz_vec_set(poly1->coeffs, poly2->coeffs, len2); } else /* Reduction necessary */ { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N1 - poly1->val, ctx); _fmpz_vec_scalar_mod_fmpz(poly1->coeffs, poly2->coeffs, len2, pow); if (alloc) fmpz_clear(pow); _padic_poly_normalise(poly1); /* Length cannot be zero, so no need to check */ /* if (poly->length == 0) */ /* poly->val = 0; */ } } } } flint-3.1.3/src/padic_poly/set_coeff_padic.c000066400000000000000000000040741461254215100210130ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" #include "padic_poly.h" void padic_poly_set_coeff_padic(padic_poly_t poly, slong n, const padic_t x, const padic_ctx_t ctx) { if (padic_is_zero(x) || padic_val(x) >= padic_poly_prec(poly)) { if (n < poly->length) { fmpz_zero(poly->coeffs + n); padic_poly_canonicalise(poly, ctx->p); } return; } padic_poly_fit_length(poly, n + 1); if (n + 1 > poly->length) { mpn_zero((mp_ptr) (poly->coeffs + poly->length), n - poly->length); poly->length = n + 1; } if (padic_val(x) == poly->val) { fmpz_set(poly->coeffs + n, padic_unit(x)); } else if (poly->val < padic_val(x)) { fmpz_t y; fmpz_init(y); fmpz_pow_ui(y, ctx->p, padic_val(x) - poly->val); fmpz_mul(poly->coeffs + n, padic_unit(x), y); fmpz_clear(y); padic_poly_canonicalise(poly, ctx->p); } else /* poly->val > x->val */ { fmpz_t pow; fmpz_init(pow); fmpz_pow_ui(pow, ctx->p, poly->val - padic_val(x)); _fmpz_vec_scalar_mul_fmpz(poly->coeffs, poly->coeffs, poly->length, pow); fmpz_set(poly->coeffs + n, padic_unit(x)); fmpz_clear(pow); poly->val = padic_val(x); } if (padic_poly_prec(poly) < padic_prec(x)) /* Reduction? */ { int c; fmpz_t pow; c = _padic_ctx_pow_ui(pow, padic_poly_prec(poly) - padic_poly_val(poly), ctx); fmpz_mod(poly->coeffs + n, poly->coeffs + n, pow); if (c) fmpz_clear(pow); } _padic_poly_normalise(poly); } flint-3.1.3/src/padic_poly/set_fmpq.c000066400000000000000000000012701461254215100175270ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_set_fmpq(padic_poly_t poly, const fmpq_t x, const padic_ctx_t ctx) { padic_t y; padic_init2(y, padic_poly_prec(poly)); padic_set_fmpq(y, x, ctx); padic_poly_set_padic(poly, y, ctx); padic_clear(y); } flint-3.1.3/src/padic_poly/set_fmpq_poly.c000066400000000000000000000024061461254215100205740ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" #include "padic_poly.h" void padic_poly_set_fmpq_poly(padic_poly_t f, const fmpq_poly_t g, const padic_ctx_t ctx) { const slong len = g->length; if (len == 0) { padic_poly_zero(f); } else { const slong N = padic_poly_prec(f); fmpz_t t; fmpz_init(t); f->val = - fmpz_remove(t, g->den, ctx->p); if (f->val < N) { padic_poly_fit_length(f, len); _padic_poly_set_length(f, len); _padic_inv(t, t, ctx->p, N - f->val); _fmpz_vec_scalar_mul_fmpz(f->coeffs, g->coeffs, len, t); if (f->val == 0) padic_poly_canonicalise(f, ctx->p); padic_poly_reduce(f, ctx); } else { padic_poly_zero(f); } fmpz_clear(t); } } flint-3.1.3/src/padic_poly/set_fmpz.c000066400000000000000000000012701461254215100175400ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_set_fmpz(padic_poly_t poly, const fmpz_t x, const padic_ctx_t ctx) { padic_t y; padic_init2(y, padic_poly_prec(poly)); padic_set_fmpz(y, x, ctx); padic_poly_set_padic(poly, y, ctx); padic_clear(y); } flint-3.1.3/src/padic_poly/set_fmpz_poly.c000066400000000000000000000014321461254215100206030ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic_poly.h" void padic_poly_set_fmpz_poly(padic_poly_t f, const fmpz_poly_t g, const padic_ctx_t ctx) { const slong len = g->length; padic_poly_fit_length(f, len); _padic_poly_set_length(f, len); _fmpz_vec_set(f->coeffs, g->coeffs, len); f->val = 0; padic_poly_canonicalise(f, ctx->p); padic_poly_reduce(f, ctx); } flint-3.1.3/src/padic_poly/set_padic.c000066400000000000000000000023041461254215100176430ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_set_padic(padic_poly_t poly, const padic_t x, const padic_ctx_t ctx) { slong N1 = padic_poly_prec(poly); if (padic_is_zero(x) || padic_val(x) >= N1) { padic_poly_zero(poly); } else { padic_poly_fit_length(poly, 1); _padic_poly_set_length(poly, 1); poly->val = padic_val(x); if (N1 >= padic_prec(x)) /* No reduction */ { fmpz_set(poly->coeffs, padic_unit(x)); } else /* Reduction */ { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N1 - padic_val(x), ctx); fmpz_mod(poly->coeffs, padic_unit(x), pow); if (alloc) fmpz_clear(pow); } } } flint-3.1.3/src/padic_poly/set_si.c000066400000000000000000000012241461254215100171760ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_set_si(padic_poly_t poly, slong x, const padic_ctx_t ctx) { padic_t y; padic_init2(y, padic_poly_prec(poly)); padic_set_si(y, x, ctx); padic_poly_set_padic(poly, y, ctx); padic_clear(y); } flint-3.1.3/src/padic_poly/set_ui.c000066400000000000000000000012241461254215100172000ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "padic_poly.h" void padic_poly_set_ui(padic_poly_t poly, ulong x, const padic_ctx_t ctx) { padic_t y; padic_init2(y, padic_poly_prec(poly)); padic_set_ui(y, x, ctx); padic_poly_set_padic(poly, y, ctx); padic_clear(y); } flint-3.1.3/src/padic_poly/shift_left.c000066400000000000000000000020711461254215100200400ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "padic_poly.h" void padic_poly_shift_left(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx) { if (rop->N < op->N) { flint_throw(FLINT_ERROR, "Exception (padic_poly_shift_left). rop->N < op->N.\n"); } if (n == 0) { padic_poly_set(rop, op, ctx); } else if (op->length == 0) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, op->length + n); _fmpz_poly_shift_left(rop->coeffs, op->coeffs, op->length, n); rop->val = op->val; _padic_poly_set_length(rop, op->length + n); /* TODO: Reduce */ } } flint-3.1.3/src/padic_poly/shift_right.c000066400000000000000000000020161461254215100202220ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "padic_poly.h" void padic_poly_shift_right(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx) { if (n == 0) { padic_poly_set(rop, op, ctx); } else if (op->length <= n) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, op->length - n); _fmpz_poly_shift_right(rop->coeffs, op->coeffs, op->length, n); rop->val = op->val; _padic_poly_set_length(rop, op->length - n); _padic_poly_normalise(rop); padic_poly_canonicalise(rop, ctx->p); /* TODO: Reduce */ } } flint-3.1.3/src/padic_poly/sub.c000066400000000000000000000062771461254215100165160ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly.h" #include "padic.h" #include "padic_poly.h" void _padic_poly_sub(fmpz *rop, slong *val, slong N, const fmpz *op1, slong val1, slong len1, slong N1, const fmpz *op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx) { const slong len = FLINT_MAX(len1, len2); *val = FLINT_MIN(val1, val2); if (val1 == val2) { _fmpz_poly_sub(rop, op1, len1, op2, len2); _padic_poly_canonicalise(rop, val, len, ctx->p); } else { fmpz_t x; fmpz_init(x); if (val1 < val2) /* F := p^g (G - p^{h-g} H) */ { fmpz_pow_ui(x, ctx->p, val2 - val1); if (rop == op1) { _fmpz_vec_zero(rop + len1, len2 - len1); _fmpz_vec_scalar_submul_fmpz(rop, op2, len2, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op2, len2, x); _fmpz_vec_neg(rop, rop, len2); _fmpz_poly_add(rop, op1, len1, rop, len2); } } else /* F := p^h (p^(g-h) G - H) */ { fmpz_pow_ui(x, ctx->p, val1 - val2); if (rop == op2) { _fmpz_vec_neg(rop, op2, len2); _fmpz_vec_zero(rop + len2, len1 - len2); _fmpz_vec_scalar_addmul_fmpz(rop, op1, len1, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op1, len1, x); _fmpz_poly_sub(rop, rop, len1, op2, len2); } } fmpz_clear(x); } /* Reduce */ if (N - *val > 0) { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N - *val, ctx); _fmpz_vec_scalar_mod_fmpz(rop, rop, len, pow); if (_fmpz_vec_is_zero(rop, len)) *val = 0; if (alloc) fmpz_clear(pow); } else { _fmpz_vec_zero(rop, len); *val = 0; } } void padic_poly_sub(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx) { const slong lenG = g->length; const slong lenH = h->length; const slong lenF = FLINT_MAX(lenG, lenH); if (lenG == 0) { padic_poly_neg(f, h, ctx); return; } if (lenH == 0) { padic_poly_set(f, g, ctx); return; } if ((lenG == 0 && lenH == 0) || (FLINT_MIN(g->val, h->val) >= f->N)) { padic_poly_zero(f); return; } padic_poly_fit_length(f, lenF); _padic_poly_sub(f->coeffs, &(f->val), f->N, g->coeffs, g->val, lenG, g->N, h->coeffs, h->val, lenH, h->N, ctx); _padic_poly_set_length(f, lenF); _padic_poly_normalise(f); } flint-3.1.3/src/padic_poly/swap.c000066400000000000000000000010231461254215100166570ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "padic_poly.h" void padic_poly_swap(padic_poly_t poly1, padic_poly_t poly2) { FLINT_SWAP(padic_poly_struct, *poly1, *poly2); } flint-3.1.3/src/padic_poly/test/000077500000000000000000000000001461254215100165245ustar00rootroot00000000000000flint-3.1.3/src/padic_poly/test/main.c000066400000000000000000000033171461254215100176200ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-compose.c" #include "t-compose_pow.c" #include "t-derivative.c" #include "t-evaluate_padic.c" #include "t-get_set_fmpq_poly.c" #include "t-init_realloc_clear.c" #include "t-inv_series.c" #include "t-mul.c" #include "t-neg.c" #include "t-one.c" #include "t-pow.c" #include "t-shift_left_right.c" #include "t-sub.c" #include "t-truncate.c" #include "t-zero.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(padic_poly_add), TEST_FUNCTION(padic_poly_compose), TEST_FUNCTION(padic_poly_compose_pow), TEST_FUNCTION(padic_poly_derivative), TEST_FUNCTION(padic_poly_evaluate_padic), TEST_FUNCTION(padic_poly_get_set_fmpq_poly), TEST_FUNCTION(padic_poly_init_realloc_clear), TEST_FUNCTION(padic_poly_inv_series), TEST_FUNCTION(padic_poly_mul), TEST_FUNCTION(padic_poly_neg), TEST_FUNCTION(padic_poly_one), TEST_FUNCTION(padic_poly_pow), TEST_FUNCTION(padic_poly_shift_left_right), TEST_FUNCTION(padic_poly_sub), TEST_FUNCTION(padic_poly_truncate), TEST_FUNCTION(padic_poly_zero) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/padic_poly/test/t-add.c000066400000000000000000000116271461254215100176700ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" #include "padic.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_add, state) { int i, result; /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_randtest(b, state, n_randint(state, 100), ctx); padic_poly_add(c, a, b, ctx); padic_poly_add(a, a, b, ctx); result = (padic_poly_equal(a, c) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL (alias a, c):\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), padic_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_randtest(b, state, n_randint(state, 100), ctx); padic_poly_add(c, a, b, ctx); padic_poly_add(b, a, b, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL (alias b, c):\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Compare with Q */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t p; slong N; padic_ctx_t ctx; padic_poly_t a, b, c, d; fmpq_poly_t x, y, z; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_init2(d, 0, N); fmpq_poly_init(x); fmpq_poly_init(y); fmpq_poly_init(z); padic_poly_randtest(b, state, n_randint(state, 50), ctx); padic_poly_randtest(c, state, n_randint(state, 50), ctx); padic_poly_add(a, b, c, ctx); padic_poly_get_fmpq_poly(y, b, ctx); padic_poly_get_fmpq_poly(z, c, ctx); fmpq_poly_add(x, y, z); padic_poly_set_fmpq_poly(d, x, ctx); result = (padic_poly_equal(a, d) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL (cmp with Q):\n"); flint_printf("N = %wd, val(b) = %wd, val(c) = %wd\n", N, b->val, c->val); padic_poly_print(c, ctx), flint_printf("\n\n"); padic_poly_print(d, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_poly_clear(d); fmpq_poly_clear(x); fmpq_poly_clear(y); fmpq_poly_clear(z); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-compose.c000066400000000000000000000077611461254215100206110ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_compose, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Compare with the computation over QQ */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { padic_poly_t f, g, h, h2; fmpq_poly_t fQQ, gQQ, hQQ; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(f, 0, N); padic_poly_init2(g, 0, N); padic_poly_init2(h, 0, N); padic_poly_init2(h2, 0, N); fmpq_poly_init(fQQ); fmpq_poly_init(gQQ); fmpq_poly_init(hQQ); padic_poly_randtest(f, state, n_randint(state, 40), ctx); padic_poly_randtest(g, state, n_randint(state, 15), ctx); padic_poly_get_fmpq_poly(fQQ, f, ctx); padic_poly_get_fmpq_poly(gQQ, g, ctx); padic_poly_compose(h, f, g, ctx); fmpq_poly_compose(hQQ, fQQ, gQQ); padic_poly_set_fmpq_poly(h2, hQQ, ctx); if (padic_poly_val(g) >= 0) { result = (padic_poly_equal(h, h2) && padic_poly_is_reduced(h, ctx)); if (!result) { flint_printf("FAIL (cmp with QQ, ord_p(g) >= 0):\n"); flint_printf("f = "), padic_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("g = "), padic_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("h = "), padic_poly_debug(h), flint_printf("\n\n"); flint_printf("h2 = "), padic_poly_debug(h2), flint_printf("\n\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("N = %wd\n\n", N); fflush(stdout); flint_abort(); } } else { slong N2 = N + (f->length - 1) * padic_poly_val(g); padic_poly_t hX, h2X; padic_poly_init2(hX, 0, N2); padic_poly_init2(h2X, 0, N2); padic_poly_set(hX, h, ctx); padic_poly_set(h2X, h2, ctx); result = (padic_poly_equal(hX, h2X) && padic_poly_is_reduced(hX, ctx)); if (!result) { flint_printf("FAIL (cmp with QQ, ord_p(g) < 0):\n"); flint_printf("f = "), padic_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("g = "), padic_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("h = "), padic_poly_print(h, ctx), flint_printf("\n\n"); flint_printf("h2 = "), padic_poly_print(h2, ctx), flint_printf("\n\n"); flint_printf("hX = "), padic_poly_print(hX, ctx), flint_printf("\n\n"); flint_printf("h2X = "), padic_poly_print(h2X, ctx), flint_printf("\n\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("N2 = %wd\n\n", N2); fflush(stdout); flint_abort(); } padic_poly_clear(hX); padic_poly_clear(h2X); } padic_poly_clear(f); padic_poly_clear(g); padic_poly_clear(h); padic_poly_clear(h2); fmpq_poly_clear(fQQ); fmpq_poly_clear(gQQ); fmpq_poly_clear(hQQ); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-compose_pow.c000066400000000000000000000071531461254215100214710ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_compose_pow, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong k; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_set(b, a, ctx); k = n_randint(state, 20) + 1; padic_poly_compose_pow(c, b, k, ctx); padic_poly_compose_pow(b, b, k, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL (aliasing):\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Compare with usual composition */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t f, g, h1, h2; slong k; padic_t one; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(f, 0, N); padic_poly_init2(g, 0, WORD_MAX); /* TODO: Check this is OK */ padic_poly_init2(h1, 0, N); padic_poly_init2(h2, 0, N); padic_poly_randtest(f, state, n_randint(state, 40), ctx); k = n_randint(state, 20) + 1; padic_poly_compose_pow(h1, f, k, ctx); padic_init(one); padic_one(one); padic_poly_set_coeff_padic(g, k, one, ctx); padic_clear(one); padic_poly_compose(h2, f, g, ctx); result = (padic_poly_equal(h1, h2) && padic_poly_is_reduced(h1, ctx)); if (!result) { flint_printf("FAIL (cmp with composition):\n"); flint_printf("f = "), padic_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("g = "), padic_poly_print(g, ctx), flint_printf("\n\n"); flint_printf("h1 = "), padic_poly_print(h1, ctx), flint_printf("\n\n"); flint_printf("h2 = "), padic_poly_print(h2, ctx), flint_printf("\n\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n\n"); flint_printf("N = %wd\n\n", N); fflush(stdout); flint_abort(); } padic_poly_clear(f); padic_poly_clear(g); padic_poly_clear(h1); padic_poly_clear(h2); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-derivative.c000066400000000000000000000070311461254215100212740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_derivative, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_set(b, a, ctx); padic_poly_derivative(c, b, ctx); padic_poly_derivative(b, b, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL (alias):\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), padic_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Compare with derivative over QQ */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpq_poly_t aQQ, bQQ; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); fmpq_poly_init(aQQ); fmpq_poly_init(bQQ); padic_poly_derivative(b, a, ctx); padic_poly_get_fmpq_poly(aQQ, a, ctx); fmpq_poly_derivative(bQQ, aQQ); padic_poly_set_fmpq_poly(c, bQQ, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL (cmp with QQ):\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), padic_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), padic_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("aQQ = "), fmpq_poly_print(aQQ), flint_printf("\n\n"); flint_printf("bQQ = "), fmpq_poly_print(bQQ), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); fmpq_poly_clear(aQQ); fmpq_poly_clear(bQQ); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-evaluate_padic.c000066400000000000000000000066741461254215100221140ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq.h" #include "fmpq_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_evaluate_padic, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Compare with the computation over QQ */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { padic_poly_t f; fmpq_poly_t fQQ; padic_t a, y, z; fmpq_t aQQ, yQQ; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(f, 0, N); fmpq_poly_init(fQQ); padic_init2(a, N); padic_init2(y, N); padic_init2(z, N); fmpq_init(aQQ); fmpq_init(yQQ); padic_poly_randtest(f, state, n_randint(state, 80), ctx); padic_randtest(a, state, ctx); padic_poly_get_fmpq_poly(fQQ, f, ctx); padic_get_fmpq(aQQ, a, ctx); padic_poly_evaluate_padic(y, f, a, ctx); fmpq_poly_evaluate_fmpq(yQQ, fQQ, aQQ); padic_set_fmpq(z, yQQ, ctx); if (padic_val(a) >= 0) { result = (padic_equal(y, z)); if (!result) { flint_printf("FAIL (cmp with QQ):\n"); flint_printf("f = "), padic_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n\n"); flint_printf("y = "), padic_print(y, ctx), flint_printf("\n\n"); flint_printf("z = "), padic_print(z, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } else { slong N2 = N + (f->length - 1) * padic_val(a); padic_t y2, z2; padic_init2(y2, N2); padic_init2(z2, N2); padic_set(y2, y, ctx); padic_set(z2, z, ctx); result = (padic_equal(y2, z2)); if (!result) { flint_printf("FAIL (cmp with QQ):\n"); flint_printf("f = "), padic_poly_print(f, ctx), flint_printf("\n\n"); flint_printf("a = "), padic_print(a, ctx), flint_printf("\n\n"); flint_printf("y = "), padic_print(y, ctx), flint_printf("\n\n"); flint_printf("z = "), padic_print(z, ctx), flint_printf("\n\n"); flint_printf("y2 = "), padic_print(y2, ctx), flint_printf("\n\n"); flint_printf("z2 = "), padic_print(z2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_clear(y2); padic_clear(z2); } padic_poly_clear(f); fmpq_poly_clear(fQQ); padic_clear(a); padic_clear(y); padic_clear(z); fmpq_clear(aQQ); fmpq_clear(yQQ); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-get_set_fmpq_poly.c000066400000000000000000000035321461254215100226540ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_get_set_fmpq_poly, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Qp -> Q -> Qp */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b; fmpq_poly_t c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); fmpq_poly_init(c); padic_poly_randtest(a, state, n_randint(state, 10), ctx); padic_poly_get_fmpq_poly(c, a, ctx); padic_poly_set_fmpq_poly(b, c, ctx); result = (padic_poly_equal(a, b) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), padic_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), padic_poly_debug(b), flint_printf("\n\n"); flint_printf("c = "), fmpq_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); fmpq_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-init_realloc_clear.c000066400000000000000000000034321461254215100227450ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_init_realloc_clear, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a; padic_poly_init2(a, n_randint(state, 100), PADIC_DEFAULT_PREC); padic_poly_clear(a); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong N; fmpz_t p; padic_poly_t a; fmpz_init_set_ui(p, 7); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_poly_init2(a, n_randint(state, 100), N); padic_poly_realloc(a, n_randint(state, 100), p); padic_poly_clear(a); fmpz_clear(p); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_ctx_t ctx; fmpz_t p; slong N; padic_poly_t a; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_clear(a); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-inv_series.c000066400000000000000000000105261461254215100213030ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_inv_series, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong n; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100) + 1, ctx); if (fmpz_is_zero(a->coeffs)) { fmpz_randtest_not_zero(a->coeffs, state, 20); fmpz_remove(a->coeffs, a->coeffs, p); padic_poly_reduce(a, ctx); } else fmpz_remove(a->coeffs, a->coeffs, p); padic_poly_set(b, a, ctx); n = n_randint(state, 100) + 1; padic_poly_inv_series(c, b, n, ctx); padic_poly_inv_series(b, b, n, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), padic_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Check correctness: If ord_p(a) = v then we can compute b = a^{-1} mod p^N and we will have a b = 1 mod p^{N-|v|}. Thus, require that N - |v| > 0. */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong n, N2; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - 1) + 1; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); { slong i, len = n_randint(state, 10) + 1; int alloc; fmpz_t pow; padic_poly_fit_length(a, len); _padic_poly_set_length(a, len); a->val = n_randint(state, N); if (n_randint(state, 2)) a->val = - a->val; alloc = _padic_ctx_pow_ui(pow, N - a->val, ctx); for (i = 0; i < len; i++) fmpz_randm(a->coeffs + i, state, pow); while (fmpz_is_zero(a->coeffs)) fmpz_randm(a->coeffs, state, pow); fmpz_remove(a->coeffs, a->coeffs, p); _padic_poly_normalise(a); if (alloc) fmpz_clear(pow); } n = n_randint(state, 100) + 1; N2 = N - FLINT_ABS(a->val); padic_poly_init2(c, 0, N2); padic_poly_inv_series(b, a, n, ctx); padic_poly_mul(c, a, b, ctx); padic_poly_truncate(c, n, p); result = (padic_poly_is_one(c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), padic_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), padic_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("N = %wd\n", N); flint_printf("N2 = %wd\n", N2); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-mul.c000066400000000000000000000157331461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_mul, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Check aliasing of a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(b, state, n_randint(state, 50), ctx); padic_poly_randtest(c, state, n_randint(state, 50), ctx); padic_poly_mul(a, b, c, ctx); padic_poly_mul(b, b, c, ctx); result = (padic_poly_equal(a, b) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL (aliasing a and b):\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(b, state, n_randint(state, 50), ctx); padic_poly_randtest(c, state, n_randint(state, 50), ctx); padic_poly_mul(a, b, c, ctx); padic_poly_mul(c, b, c, ctx); result = (padic_poly_equal(a, c) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL (aliasing a and c):\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Check (b * c) + (b * d) = b * (c + d) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a1, a2, b, c, d, t; slong v; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_init2(d, 0, N); padic_poly_init2(t, 0, N); padic_poly_randtest(b, state, n_randint(state, 100), ctx); padic_poly_randtest(c, state, n_randint(state, 100), ctx); padic_poly_randtest(d, state, n_randint(state, 100), ctx); v = FLINT_MIN(b->val, c->val); v = FLINT_MIN(v, d->val); v = FLINT_MIN(v, 0); if (v >= 0 || -v < N) /* Otherwise, no precision left */ { slong N2 = (v >= 0) ? N : N + v; padic_poly_init2(a1, 0, N2); padic_poly_init2(a2, 0, N2); padic_poly_mul(a1, b, c, ctx); padic_poly_mul(t, b, d, ctx); padic_poly_add(a1, a1, t, ctx); /* Lower precision */ padic_poly_add(t, c, d, ctx); padic_poly_mul(a2, b, t, ctx); /* Lower precision */ result = (padic_poly_equal(a1, a2) && padic_poly_is_reduced(a1, ctx)); if (!result) { flint_printf("FAIL (distributivity):\n"); flint_printf("p = "), fmpz_print(ctx->p), flint_printf("\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("b = "), padic_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), padic_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("d = "), padic_poly_print(d, ctx), flint_printf("\n\n"); flint_printf("a1 = "), padic_poly_print(a1, ctx), flint_printf("\n\n"); flint_printf("a2 = "), padic_poly_print(a2, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a1); padic_poly_clear(a2); } padic_poly_clear(b); padic_poly_clear(c); padic_poly_clear(d); padic_poly_clear(t); padic_ctx_clear(ctx); fmpz_clear(p); } /* Compare with Q */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c, d; fmpq_poly_t x, y, z; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_init2(d, 0, N); fmpq_poly_init(x); fmpq_poly_init(y); fmpq_poly_init(z); padic_poly_randtest(b, state, n_randint(state, 50), ctx); padic_poly_randtest(c, state, n_randint(state, 50), ctx); padic_poly_mul(a, b, c, ctx); padic_poly_get_fmpq_poly(y, b, ctx); padic_poly_get_fmpq_poly(z, c, ctx); fmpq_poly_mul(x, y, z); padic_poly_set_fmpq_poly(d, x, ctx); result = (padic_poly_equal(a, d) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL (cmp with Q):\n"); flint_printf("N = %wd, val(b) = %wd, val(c) = %wd\n", N, b->val, c->val); padic_poly_print(c, ctx), flint_printf("\n\n"); padic_poly_print(d, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_poly_clear(d); fmpq_poly_clear(x); fmpq_poly_clear(y); fmpq_poly_clear(z); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-neg.c000066400000000000000000000056461461254215100177150ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_neg, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; /* Aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_set(b, a, ctx); padic_poly_neg(c, b, ctx); padic_poly_neg(b, b, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Check that --a = a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_neg(b, a, ctx); padic_poly_neg(c, b, ctx); result = (padic_poly_equal(a, c) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-one.c000066400000000000000000000027571461254215100177250ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_one, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_one(a); result = (padic_poly_is_one(a) || N <= 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("N = %wd\n\n", N); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-pow.c000066400000000000000000000112011461254215100177310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_pow, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_set(b, a, ctx); e = n_randint(state, 10); padic_poly_pow(c, b, e, ctx); padic_poly_pow(b, b, e, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("e = %wd\n\n", e); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Compare with the computation over QQ */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpq_poly_t aQQ, bQQ; slong e; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); fmpq_poly_init(aQQ); fmpq_poly_init(bQQ); padic_poly_randtest(a, state, n_randint(state, 10), ctx); e = n_randint(state, 10); padic_poly_pow(b, a, e, ctx); padic_poly_get_fmpq_poly(aQQ, a, ctx); fmpq_poly_pow(bQQ, aQQ, e); padic_poly_set_fmpq_poly(c, bQQ, ctx); if (e == 0) { result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL (cmp with QQ):\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } } else { padic_poly_t blo, clo; slong N2 = N + (e - 1) * a->val; padic_poly_init2(blo, 0, N2); padic_poly_init2(clo, 0, N2); padic_poly_set(blo, b, ctx); padic_poly_set(clo, c, ctx); result = (padic_poly_equal(blo, clo) && padic_poly_is_reduced(blo, ctx)); if (!result) { flint_printf("FAIL (cmp with QQ):\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); flint_printf("b = "), padic_poly_print(b, ctx), flint_printf("\n\n"); flint_printf("c = "), padic_poly_print(c, ctx), flint_printf("\n\n"); flint_printf("blo = "), padic_poly_print(blo, ctx), flint_printf("\n\n"); flint_printf("clo = "), padic_poly_print(clo, ctx), flint_printf("\n\n"); flint_printf("N = %wd\n\n", N); flint_printf("e = %wd\n\n", e); flint_printf("N + (e - 1) v = %wd\n\n", N + (e - 1) * a->val); fflush(stdout); flint_abort(); } padic_poly_clear(blo); padic_poly_clear(clo); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); fmpq_poly_clear(aQQ); fmpq_poly_clear(bQQ); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-shift_left_right.c000066400000000000000000000105441461254215100224610ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_shift_left_right, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Aliasing for left shift */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong shift = n_randint(state, 100); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_set(b, a, ctx); padic_poly_shift_left(c, b, shift, ctx); padic_poly_shift_left(b, b, shift, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Aliasing for shift right */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong shift = n_randint(state, 100); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_set(b, a, ctx); padic_poly_shift_right(c, b, shift, ctx); padic_poly_shift_right(b, b, shift, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Check shift left then right does nothing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong shift = n_randint(state, 100); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_shift_left(b, a, shift, ctx); padic_poly_shift_right(c, b, shift, ctx); result = (padic_poly_equal(a, c) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-sub.c000066400000000000000000000106361461254215100177300ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2009 Bill Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_sub, state) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; /* Check a - b = a + neg(b) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c, d; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_init2(d, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_randtest(b, state, n_randint(state, 100), ctx); padic_poly_sub(c, a, b, ctx); padic_poly_neg(b, b, ctx); padic_poly_add(d, a, b, ctx); result = (padic_poly_equal(c, d) && padic_poly_is_reduced(c, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); padic_poly_print(d, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_poly_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_randtest(b, state, n_randint(state, 100), ctx); padic_poly_sub(c, a, b, ctx); padic_poly_sub(a, a, b, ctx); result = (padic_poly_equal(a, c) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_randtest(b, state, n_randint(state, 100), ctx); padic_poly_sub(c, a, b, ctx); padic_poly_sub(b, a, b, ctx); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-truncate.c000066400000000000000000000063611461254215100207640ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq_poly.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_truncate, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; /* Check repeated truncating */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a, b, c; slong m, n; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_init2(b, 0, N); padic_poly_init2(c, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_set(b, a, ctx); padic_poly_set(c, a, ctx); m = n_randint(state, 100); n = n_randint(state, m + 1); padic_poly_truncate(b, m, ctx->p); padic_poly_truncate(b, n, ctx->p); padic_poly_truncate(c, n, ctx->p); result = (padic_poly_equal(b, c) && padic_poly_is_reduced(b, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); padic_poly_print(b, ctx), flint_printf("\n\n"); padic_poly_print(c, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } /* Compare with Q */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a; fmpq_poly_t b, c; slong n; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); fmpq_poly_init(b); fmpq_poly_init(c); padic_poly_randtest(a, state, n_randint(state, 100), ctx); n = n_randint(state, 100); padic_poly_get_fmpq_poly(b, a, ctx); fmpq_poly_truncate(b, n); padic_poly_truncate(a, n, ctx->p); padic_poly_get_fmpq_poly(c, a, ctx); result = (fmpq_poly_equal(b, c) && padic_poly_is_reduced(a, ctx)); if (!result) { flint_printf("FAIL:\n"); padic_poly_print(a, ctx), flint_printf("\n\n"); fmpq_poly_print(b), flint_printf("\n\n"); fmpq_poly_print(c), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_poly/test/t-zero.c000066400000000000000000000026741461254215100201210ustar00rootroot00000000000000/* Copyright (C) 2010, 2011 Sebastian Pancratz Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "padic_poly.h" TEST_FUNCTION_START(padic_poly_zero, state) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { padic_poly_t a; fmpz_init_set_ui(p, n_randtest_prime(state, 0)); N = n_randint(state, PADIC_TEST_PREC_MAX - PADIC_TEST_PREC_MIN) + PADIC_TEST_PREC_MIN; padic_ctx_init(ctx, p, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), PADIC_SERIES); padic_poly_init2(a, 0, N); padic_poly_randtest(a, state, n_randint(state, 100), ctx); padic_poly_zero(a); result = (padic_poly_is_zero(a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), padic_poly_print(a, ctx), flint_printf("\n\n"); fflush(stdout); flint_abort(); } padic_poly_clear(a); padic_ctx_clear(ctx); fmpz_clear(p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/padic_types.h000066400000000000000000000025021461254215100160760ustar00rootroot00000000000000/* Copyright (C) 2011, 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef PADIC_TYPES_H #define PADIC_TYPES_H #include "fmpz_types.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz u; slong v; slong N; } padic_struct; typedef padic_struct padic_t[1]; enum padic_print_mode { PADIC_TERSE, PADIC_SERIES, PADIC_VAL_UNIT }; typedef struct { fmpz_t p; double pinv; fmpz * pow; slong min; slong max; enum padic_print_mode mode; } padic_ctx_struct; typedef padic_ctx_struct padic_ctx_t[1]; typedef struct { slong n; fmpz * pow; } padic_inv_struct; typedef padic_inv_struct padic_inv_t[1]; typedef struct { fmpz_mat_struct mat; slong val; slong N; } padic_mat_struct; typedef padic_mat_struct padic_mat_t[1]; typedef struct { fmpz * coeffs; slong alloc; slong length; slong val; slong N; } padic_poly_struct; typedef padic_poly_struct padic_poly_t[1]; #ifdef __cplusplus } #endif #endif /* PADIC_TYPES_H */ flint-3.1.3/src/partitions.h000066400000000000000000000016661461254215100160000ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef PARTITIONS_H #define PARTITIONS_H #include "arb_types.h" #ifdef __cplusplus extern "C" { #endif void partitions_rademacher_bound(arf_t b, const fmpz_t n, ulong N); void partitions_hrr_sum_arb(arb_t x, const fmpz_t n, slong N0, slong N, int use_doubles); void partitions_fmpz_fmpz(fmpz_t p, const fmpz_t n, int use_doubles); void partitions_fmpz_ui(fmpz_t p, ulong n); /* deprecated */ #define partitions_fmpz_ui_using_doubles partitions_fmpz_ui void partitions_leading_fmpz(arb_t res, const fmpz_t n, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/partitions/000077500000000000000000000000001461254215100156165ustar00rootroot00000000000000flint-3.1.3/src/partitions/fmpz_fmpz.c000066400000000000000000000127771461254215100200100ustar00rootroot00000000000000/* Copyright (C) 2013-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "partitions.h" #ifdef __GNUC__ # define sqrt __builtin_sqrt #else # include #endif /* This nice round number precisely fits on 32 bits */ #define NUMBER_OF_SMALL_PARTITIONS 128 const unsigned int partitions_lookup[NUMBER_OF_SMALL_PARTITIONS] = { UWORD(1),UWORD(1),UWORD(2),UWORD(3),UWORD(5),UWORD(7),UWORD(11),UWORD(15),UWORD(22),UWORD(30),UWORD(42),UWORD(56),UWORD(77),UWORD(101),UWORD(135), UWORD(176),UWORD(231),UWORD(297),UWORD(385),UWORD(490),UWORD(627),UWORD(792),UWORD(1002),UWORD(1255),UWORD(1575),UWORD(1958), UWORD(2436),UWORD(3010),UWORD(3718),UWORD(4565),UWORD(5604),UWORD(6842),UWORD(8349),UWORD(10143),UWORD(12310),UWORD(14883), UWORD(17977),UWORD(21637),UWORD(26015),UWORD(31185),UWORD(37338),UWORD(44583),UWORD(53174),UWORD(63261),UWORD(75175), UWORD(89134),UWORD(105558),UWORD(124754),UWORD(147273),UWORD(173525),UWORD(204226),UWORD(239943),UWORD(281589), UWORD(329931),UWORD(386155),UWORD(451276),UWORD(526823),UWORD(614154),UWORD(715220),UWORD(831820),UWORD(966467), UWORD(1121505),UWORD(1300156),UWORD(1505499),UWORD(1741630),UWORD(2012558),UWORD(2323520),UWORD(2679689), UWORD(3087735),UWORD(3554345),UWORD(4087968),UWORD(4697205),UWORD(5392783),UWORD(6185689),UWORD(7089500), UWORD(8118264),UWORD(9289091),UWORD(10619863),UWORD(12132164),UWORD(13848650),UWORD(15796476),UWORD(18004327), UWORD(20506255),UWORD(23338469),UWORD(26543660),UWORD(30167357),UWORD(34262962),UWORD(38887673), UWORD(44108109),UWORD(49995925),UWORD(56634173),UWORD(64112359),UWORD(72533807),UWORD(82010177), UWORD(92669720),UWORD(104651419),UWORD(118114304),UWORD(133230930),UWORD(150198136),UWORD(169229875), UWORD(190569292),UWORD(214481126),UWORD(241265379),UWORD(271248950),UWORD(304801365),UWORD(342325709), UWORD(384276336),UWORD(431149389),UWORD(483502844),UWORD(541946240),UWORD(607163746),UWORD(679903203), UWORD(761002156),UWORD(851376628),UWORD(952050665),UWORD(1064144451),UWORD(1188908248),UWORD(1327710076), UWORD(1482074143),UWORD(1653668665),UWORD(1844349560),UWORD(2056148051),UWORD(2291320912), UWORD(2552338241),UWORD(2841940500),UWORD(3163127352),UWORD(3519222692),UWORD(3913864295) }; slong partitions_hrr_needed_terms(double n); void partitions_fmpz_fmpz_hrr(fmpz_t p, const fmpz_t n, int use_doubles) { arb_t x; arf_t bound; slong N; arb_init(x); arf_init(bound); N = partitions_hrr_needed_terms(fmpz_get_d(n)); partitions_hrr_sum_arb(x, n, 1, N, use_doubles); partitions_rademacher_bound(bound, n, N); arb_add_error_arf(x, bound); if (!arb_get_unique_fmpz(p, x)) { flint_throw(FLINT_ERROR, "not unique!\n%s\n", arb_get_str(x, 50, 0)); } arb_clear(x); arf_clear(bound); } /* To compute p(n) mod 2^64. */ static void partitions_vec(mp_ptr v, slong len) { slong i, j, n; mp_limb_t p; for (n = 0; n < FLINT_MIN(len, NUMBER_OF_SMALL_PARTITIONS); n++) v[n] = partitions_lookup[n]; for (n = NUMBER_OF_SMALL_PARTITIONS; n < len; n++) { p = 0; for (i = 1, j = 1; j <= n; j += 3 * i + 1, i++) p = v[n - j] - p; if ((i & 1) == 0) p = -p; for (i = 1, j = 2; j <= n; j += 3 * i + 2, i++) p = v[n - j] - p; if ((i & 1) != 0) p = -p; v[n] = p; } } /* The floor+vec method *requires* n <= 1498 for floor(p(n)/2^64) to be equal to floor(T/2^64). It is faster up to n ~= 1200. With doubles, it is faster up to n ~= 500. */ void _partitions_fmpz_ui(fmpz_t res, ulong n, int use_doubles) { if (n < NUMBER_OF_SMALL_PARTITIONS) { fmpz_set_ui(res, partitions_lookup[n]); } else if (FLINT_BITS == 64 && (n < 500 || (!use_doubles && n < 1200))) { mp_ptr tmp = flint_malloc((n + 1) * sizeof(mp_limb_t)); if (n < 417) /* p(n) < 2^64 */ { partitions_vec(tmp, n + 1); fmpz_set_ui(res, tmp[n]); } else { arb_t x; arb_init(x); fmpz_set_ui(res, n); partitions_leading_fmpz(x, res, 4 * sqrt(n) - 50); arb_mul_2exp_si(x, x, -64); arb_floor(x, x, 4 * sqrt(n) - 50); if (arb_get_unique_fmpz(res, x)) { fmpz_mul_2exp(res, res, 64); partitions_vec(tmp, n + 1); fmpz_add_ui(res, res, tmp[n]); } else { flint_printf("warning: failed at %wu\n", n); fmpz_set_ui(res, n); partitions_fmpz_fmpz_hrr(res, res, use_doubles); } arb_clear(x); } flint_free(tmp); } else { fmpz_set_ui(res, n); partitions_fmpz_fmpz_hrr(res, res, use_doubles); } } void partitions_fmpz_fmpz(fmpz_t res, const fmpz_t n, int use_doubles) { if (fmpz_cmp_ui(n, 2000) < 0) { if (fmpz_sgn(n) < 0) fmpz_zero(res); else _partitions_fmpz_ui(res, *n, use_doubles); } else { partitions_fmpz_fmpz_hrr(res, n, use_doubles); } } void partitions_fmpz_ui(fmpz_t res, ulong n) { _partitions_fmpz_ui(res, n, 0); } flint-3.1.3/src/partitions/hrr_sum_arb.c000066400000000000000000000210571461254215100202720ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_support.h" #include "ulong_extras.h" #include "arb.h" #include "arith.h" #include "partitions.h" #ifdef __GNUC__ # define log __builtin_log # define sinh __builtin_sinh # define sqrt __builtin_sqrt #else # include #endif #define VERBOSE 0 #define DOUBLE_CUTOFF 40 #define DOUBLE_ERR 1e-12 #define DOUBLE_PREC 53 #define MIN_PREC 20 #define PI 3.141592653589793238462643 #define INV_LOG2 (1.44269504088896340735992468 + 1e-12) #define HRR_A (1.1143183348516376904 + 1e-12) /* 44*pi^2/(225*sqrt(3)) */ #define HRR_B (0.0592384391754448833 + 1e-12) /* pi*sqrt(2)/75 */ #define HRR_C (2.5650996603237281911 + 1e-12) /* pi*sqrt(2/3) */ #define HRR_D (1.2424533248940001551 + 1e-12) /* log(2) + log(3)/2 */ static double partitions_remainder_bound(double n, double terms) { return HRR_A/sqrt(terms) + HRR_B*sqrt(terms/(n-1)) * sinh(HRR_C * sqrt(n)/terms); } /* Crude upper bound, sufficient to estimate the precision */ static double log_sinh(double x) { if (x > 4) return x; else return log(x) + x*x*(1/6.); } static double partitions_remainder_bound_log2(double n, double N) { double t1, t2; t1 = log(HRR_A) - 0.5*log(N); t2 = log(HRR_B) + 0.5*(log(N) - log(n-1)) + log_sinh(HRR_C * sqrt(n)/N); return (FLINT_MAX(t1, t2) + 1) * INV_LOG2; } slong partitions_hrr_needed_terms(double n) { slong N; for (N = 1; partitions_remainder_bound_log2(n, N) > 10; N++); for ( ; partitions_remainder_bound(n, N) > 0.4; N++); return N; } static double partitions_term_bound(double n, double k) { return ((PI*sqrt(24*n-1) / (6.0*k)) + HRR_D - log(24.0*n-1) + 0.5*log(k)) * INV_LOG2; } /* Bound number of prime factors in k */ static mp_limb_t primorial_tab[] = { 1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690, 223092870, #if FLINT64 UWORD(6469693230), UWORD(200560490130), UWORD(7420738134810), UWORD(304250263527210), UWORD(13082761331670030), UWORD(614889782588491410) #endif }; static inline int bound_primes(ulong k) { int i; for (i = 0; i < sizeof(primorial_tab) / sizeof(mp_limb_t); i++) if (k <= primorial_tab[i]) return i; return i; } static inline slong log2_ceil(double x) { /* ceil(log2(n)) = bitcount(n-1); this is too large if x is a power of two */ return FLINT_BIT_COUNT((slong) x); } static slong partitions_prec_bound(double n, slong k, slong N) { slong prec; prec = partitions_term_bound(n, k); prec += log2_ceil(8 * N * (26 * (sqrt(n) / k) + 7 * bound_primes(k) + 22)); return prec; } static void eval_trig_prod(arb_t sum, trig_prod_t prod, slong prec) { int i; mp_limb_t v; arb_t t; if (prod->prefactor == 0) { arb_zero(sum); return; } arb_init(t); arb_set_si(sum, prod->prefactor); v = n_gcd(FLINT_MAX(prod->sqrt_p, prod->sqrt_q), FLINT_MIN(prod->sqrt_p, prod->sqrt_q)); prod->sqrt_p /= v; prod->sqrt_q /= v; if (prod->sqrt_p != 1) { arb_sqrt_ui(t, prod->sqrt_p, prec); arb_mul(sum, sum, t, prec); } if (prod->sqrt_q != 1) { arb_rsqrt_ui(t, prod->sqrt_q, prec); arb_mul(sum, sum, t, prec); } for (i = 0; i < prod->n; i++) { fmpq_t pq; *fmpq_numref(pq) = prod->cos_p[i]; *fmpq_denref(pq) = prod->cos_q[i]; arb_cos_pi_fmpq(t, pq, prec); arb_mul(sum, sum, t, prec); } arb_clear(t); } static void sinh_cosh_divk_precomp(arb_t sh, arb_t ch, const arb_t ex, slong k, slong prec) { arb_t t; arb_init(t); arb_set_round(t, ex, prec); arb_root_ui(ch, t, k, prec); /* The second term doesn't need full precision, but this doesn't affect performance that much... */ arb_inv(t, ch, prec); arb_sub(sh, ch, t, prec); arb_add(ch, ch, t, prec); arb_mul_2exp_si(ch, ch, -1); arb_mul_2exp_si(sh, sh, -1); arb_clear(t); } static void partitions_hrr_sum_arb_range(arb_t x, const fmpz_t n, const arb_t C, const arb_t exp1, const fmpz_t n24, slong start, slong N, slong step, slong prec, slong acc_prec, slong res_prec) { arb_t acc, t1, t2, t3, t4; trig_prod_t prod; slong k; double nd; arb_init(acc); arb_init(t1); arb_init(t2); arb_init(t3); arb_init(t4); nd = fmpz_get_d(n); for (k = start; k <= N; k += step) { trig_prod_init(prod); arith_hrr_expsum_factored(prod, k, fmpz_fdiv_ui(n, k)); if (prod->prefactor != 0) { if (prec > MIN_PREC) prec = partitions_prec_bound(nd, k, N); prod->prefactor *= 4; prod->sqrt_p *= 3; prod->sqrt_q *= k; /* Compute A_k(n) * sqrt(3/k) * 4 / (24*n-1) */ eval_trig_prod(t1, prod, prec); arb_div_fmpz(t1, t1, n24, prec); /* Multiply by (cosh(z) - sinh(z)/z) where z = C / k */ arb_set_round(t2, C, prec); arb_div_ui(t2, t2, k, prec); if (k < 35 && prec > 1000) sinh_cosh_divk_precomp(t3, t4, exp1, k, prec); else arb_sinh_cosh(t3, t4, t2, prec); arb_div(t3, t3, t2, prec); arb_sub(t2, t4, t3, prec); arb_mul(t1, t1, t2, prec); /* Add to accumulator */ arb_add(acc, acc, t1, acc_prec); if (acc_prec > 2 * prec + 32) { arb_add(x, x, acc, res_prec); arb_zero(acc); acc_prec = prec + 32; } } } arb_add(x, x, acc, res_prec); arb_clear(acc); arb_clear(t1); arb_clear(t2); arb_clear(t3); arb_clear(t4); } typedef struct { arb_ptr x; const fmpz * n; arb_srcptr C; arb_srcptr exp1; const fmpz * n24; slong N0; slong N; slong step; slong prec; slong acc_prec; slong res_prec; } work_t; static void worker(slong i, work_t * work) { partitions_hrr_sum_arb_range(work->x + i, work->n, work->C, work->exp1, work->n24, work->N0 + i, work->N, work->step, work->prec, work->acc_prec, work->res_prec); } void partitions_hrr_sum_arb(arb_t x, const fmpz_t n, slong N0, slong N, int use_doubles) { arb_t C, t, exp1; fmpz_t n24; slong prec, res_prec, acc_prec, guard_bits; slong num_threads; double nd; if (fmpz_cmp_ui(n, 2) <= 0) { flint_throw(FLINT_ERROR, "(%s)\n", __func__); } nd = fmpz_get_d(n); /* compute initial precision */ guard_bits = 2 * FLINT_BIT_COUNT(N) + 32; prec = partitions_remainder_bound_log2(nd, N0) + guard_bits; prec = FLINT_MAX(prec, DOUBLE_PREC); res_prec = acc_prec = prec; #if VERBOSE flint_printf("prec %wd N %wd\n", prec, N); #endif arb_init(C); arb_init(exp1); fmpz_init(n24); arb_zero(x); /* n24 = 24n - 1 */ fmpz_set(n24, n); fmpz_mul_ui(n24, n24, 24); fmpz_sub_ui(n24, n24, 1); /* C = (pi/6) sqrt(24n-1) */ #if VERBOSE TIMEIT_ONCE_START arb_const_pi(C, prec); TIMEIT_ONCE_STOP #else arb_const_pi(C, prec); #endif arb_init(t); arb_sqrt_fmpz(t, n24, prec); arb_mul(C, C, t, prec); arb_div_ui(C, C, 6, prec); arb_clear(t); /* exp1 = exp(C) */ #if VERBOSE TIMEIT_ONCE_START arb_exp(exp1, C, prec); TIMEIT_ONCE_STOP #else arb_exp(exp1, C, prec); #endif num_threads = flint_get_num_threads(); if (num_threads == 1) { partitions_hrr_sum_arb_range(x, n, C, exp1, n24, N0, N, 1, prec, acc_prec, res_prec); } else { arb_ptr s; slong i; work_t work; num_threads = FLINT_MIN(num_threads, 8); num_threads = FLINT_MAX(num_threads, 1); s = _arb_vec_init(num_threads); work.x = s; work.n = n; work.C = C; work.exp1 = exp1; work.n24 = n24; work.N0 = N0; work.N = N; work.step = num_threads; work.prec = prec; work.acc_prec = acc_prec; work.res_prec = res_prec; flint_parallel_do((do_func_t) worker, &work, num_threads, -1, FLINT_PARALLEL_UNIFORM); for (i = 0; i < num_threads; i++) arb_add(x, x, s + i, prec); _arb_vec_clear(s, num_threads); } fmpz_clear(n24); arb_clear(exp1); arb_clear(C); } flint-3.1.3/src/partitions/leading_fmpz.c000066400000000000000000000022221461254215100204170ustar00rootroot00000000000000/* Copyright (C) 2016 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "partitions.h" void partitions_leading_fmpz(arb_t res, const fmpz_t n, slong prec) { arb_t t; fmpz_t c; slong eprec; arb_init(t); fmpz_init(c); eprec = prec + fmpz_bits(n) / 2; /* c = 24n-1 */ fmpz_mul_ui(c, n, 24); fmpz_sub_ui(c, c, 1); /* t = pi sqrt(24n-1) / 6 */ arb_sqrt_fmpz(t, c, eprec); arb_const_pi(res, eprec); arb_mul(t, t, res, eprec); arb_div_ui(t, t, 6, eprec); /* res = exp(t) - exp(t) / t */ /* todo: eprec only needed for argument reduction */ arb_exp(res, t, eprec); arb_div(t, res, t, prec); arb_sub(res, res, t, prec); arb_sqrt_ui(t, 12, prec); arb_mul(res, res, t, prec); arb_div_fmpz(res, res, c, prec); arb_clear(t); fmpz_clear(c); } flint-3.1.3/src/partitions/rademacher_bound.c000066400000000000000000000035431461254215100212510ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb.h" #include "partitions.h" static void _arf_sinh(arf_t y, const arf_t x, slong prec) { arb_t t; arb_init(t); arb_set_arf(t, x); arb_sinh(t, t, prec); arb_get_abs_ubound_arf(y, t, prec); arb_clear(t); } /* Equation (1.8) in the paper */ void partitions_rademacher_bound(arf_t b, const fmpz_t n, ulong N) { arf_t A, B, C, t, u; fmpz_t n1; arf_init(A); arf_init(B); arf_init(C); arf_init(t); arf_init(u); fmpz_init(n1); /* bound for 44*pi^2/(225*sqrt(3)) */ arf_set_si_2exp_si(A, 18695160, -24); /* bound for pi*sqrt(2)/75 */ arf_set_si_2exp_si(B, 993857, -24); /* bound for pi*sqrt(2/3) */ arf_set_si_2exp_si(C, 43035232, -24); /* first term: A / sqrt(N) */ arf_sqrt_ui(t, N, MAG_BITS, ARF_RND_DOWN); arf_div(b, A, t, MAG_BITS, ARF_RND_UP); /* B * sqrt(N/(n-1)) */ arf_set_ui(t, N); fmpz_sub_ui(n1, n, 1); arf_div_fmpz(t, t, n1, MAG_BITS, ARF_RND_UP); arf_sqrt(t, t, MAG_BITS, ARF_RND_UP); arf_mul(t, B, t, MAG_BITS, ARF_RND_UP); /* sinh(C*sqrt(n)/N) */ arf_sqrt_fmpz(u, n, MAG_BITS, ARF_RND_UP); arf_div_ui(u, u, N, MAG_BITS, ARF_RND_UP); arf_mul(u, C, u, MAG_BITS, ARF_RND_UP); _arf_sinh(u, u, MAG_BITS); /* second term: B * ... * sinh... */ arf_mul(t, t, u, MAG_BITS, ARF_RND_UP); arf_add(b, b, t, MAG_BITS, ARF_RND_UP); arf_clear(A); arf_clear(B); arf_clear(C); arf_clear(t); arf_clear(u); fmpz_clear(n1); } flint-3.1.3/src/partitions/test/000077500000000000000000000000001461254215100165755ustar00rootroot00000000000000flint-3.1.3/src/partitions/test/main.c000066400000000000000000000015511461254215100176670ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-partitions_fmpz_ui.c" #include "t-partitions_fmpz_ui_threaded.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(partitions_fmpz_ui), TEST_FUNCTION(partitions_fmpz_ui_threaded) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/partitions/test/t-partitions_fmpz_ui.c000066400000000000000000000070511461254215100231320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" #include "partitions.h" /* Defined in t-partitions_fmpz_ui.c and t-partitions_fmpz_ui_threaded.c */ #define testdata testdata_fmpz_ui /* Values mod 10^9 generated with Sage */ static const ulong testdata[][2] = { {100000, 421098519}, {100001, 33940350}, {100002, 579731933}, {100003, 625213730}, {100004, 539454200}, {100005, 69672418}, {100006, 865684292}, {100007, 641916724}, {100008, 36737908}, {100009, 293498270}, {100010, 177812057}, {100011, 756857293}, {100012, 950821113}, {100013, 824882014}, {100014, 533894560}, {100015, 660734788}, {100016, 835912257}, {100017, 302982816}, {100018, 468609888}, {100019, 221646940}, {1000000, 104673818}, {1000001, 980212296}, {1000002, 709795681}, {1000003, 530913758}, {1000004, 955452980}, {1000005, 384388683}, {1000006, 138665072}, {1000007, 144832602}, {1000008, 182646067}, {1000009, 659145045}, {1000010, 17911162}, {1000011, 606326324}, {1000012, 99495156}, {1000013, 314860251}, {1000014, 497563335}, {1000015, 726842109}, {1000016, 301469541}, {1000017, 227491620}, {1000018, 704160927}, {1000019, 995311980}, {10000000, 677288980}, {10000001, 433805210}, {10000002, 365406948}, {10000003, 120899894}, {10000004, 272822040}, {10000005, 71938624}, {10000006, 637670808}, {10000007, 766947591}, {10000008, 980210244}, {10000009, 965734705}, {10000010, 187411691}, {10000011, 485652153}, {10000012, 825498761}, {10000013, 895802660}, {10000014, 152775845}, {10000015, 791493402}, {10000016, 299640598}, {10000017, 383615481}, {10000018, 378922331}, {10000019, 37059200}, {100000000, 836637702}, {100000001, 66421565}, {100000002, 747849093}, {100000003, 465329748}, {100000004, 166747980}, {0, 0}, }; #define NUM 5000 TEST_FUNCTION_START(partitions_fmpz_ui, state) { slong i; { fmpz_t p; fmpz * v; fmpz_init(p); v = _fmpz_vec_init(NUM); arith_number_of_partitions_vec(v, NUM); for (i = 0; i < NUM; i++) { partitions_fmpz_ui(p, i); if (!fmpz_equal(p, v + i)) { flint_printf("FAIL:\n"); flint_printf("p(%wd) does not agree with power series\n", i); flint_printf("Computed p(%wd): ", i); fmpz_print(p); flint_printf("\n"); flint_printf("Expected: "); fmpz_print(v + i); flint_printf("\n"); flint_abort(); } } _fmpz_vec_clear(v, NUM); for (i = 0; testdata[i][0] != 0; i++) { partitions_fmpz_ui(p, testdata[i][0]); if (fmpz_fdiv_ui(p, 1000000000) != testdata[i][1]) { flint_printf("FAIL:\n"); flint_printf("p(%wd) does not agree with known value mod 10^9\n", testdata[i][0]); flint_printf("Computed: %wu\n", fmpz_fdiv_ui(p, 1000000000)); flint_printf("Expected: %wu\n", testdata[i][1]); flint_abort(); } } fmpz_clear(p); } TEST_FUNCTION_END(state); } #undef testdata flint-3.1.3/src/partitions/test/t-partitions_fmpz_ui_threaded.c000066400000000000000000000072421461254215100247740ustar00rootroot00000000000000/* Copyright (C) 2011-2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" #include "partitions.h" /* Defined in t-partitions_fmpz_ui.c and t-partitions_fmpz_ui_threaded.c */ #define testdata testdata_fmpz_ui_threaded /* Values mod 10^9 */ static const ulong testdata[][2] = { {100000, 421098519}, {100001, 33940350}, {100002, 579731933}, {100003, 625213730}, {100004, 539454200}, {100005, 69672418}, {100006, 865684292}, {100007, 641916724}, {100008, 36737908}, {100009, 293498270}, {100010, 177812057}, {100011, 756857293}, {100012, 950821113}, {100013, 824882014}, {100014, 533894560}, {100015, 660734788}, {100016, 835912257}, {100017, 302982816}, {100018, 468609888}, {100019, 221646940}, {1000000, 104673818}, {1000001, 980212296}, {1000002, 709795681}, {1000003, 530913758}, {1000004, 955452980}, {1000005, 384388683}, {1000006, 138665072}, {1000007, 144832602}, {1000008, 182646067}, {1000009, 659145045}, {1000010, 17911162}, {1000011, 606326324}, {1000012, 99495156}, {1000013, 314860251}, {1000014, 497563335}, {1000015, 726842109}, {1000016, 301469541}, {1000017, 227491620}, {1000018, 704160927}, {1000019, 995311980}, {10000000, 677288980}, {10000001, 433805210}, {10000002, 365406948}, {10000003, 120899894}, {10000004, 272822040}, {10000005, 71938624}, {10000006, 637670808}, {10000007, 766947591}, {10000008, 980210244}, {10000009, 965734705}, {10000010, 187411691}, {10000011, 485652153}, {10000012, 825498761}, {10000013, 895802660}, {10000014, 152775845}, {10000015, 791493402}, {10000016, 299640598}, {10000017, 383615481}, {10000018, 378922331}, {10000019, 37059200}, {100000000, 836637702}, {100000001, 66421565}, {100000002, 747849093}, {100000003, 465329748}, {100000004, 166747980}, {500000000, 143535392}, {1000000000, 685688339}, {UWORD(4000000000), 525944299}, {0, 0}, }; #define NUM 5000 TEST_FUNCTION_START(partitions_fmpz_ui_threaded, state) { slong i; flint_set_num_threads(2); { fmpz_t p; fmpz * v; fmpz_init(p); v = _fmpz_vec_init(NUM); arith_number_of_partitions_vec(v, NUM); for (i = 0; i < NUM; i++) { partitions_fmpz_ui(p, i); if (!fmpz_equal(p, v + i)) { flint_printf("FAIL:\n"); flint_printf("p(%wd) does not agree with power series\n", i); flint_printf("Computed p(%wd): ", i); fmpz_print(p); flint_printf("\n"); flint_printf("Expected: "); fmpz_print(v + i); flint_printf("\n"); flint_abort(); } } _fmpz_vec_clear(v, NUM); for (i = 0; testdata[i][0] != 0; i++) { partitions_fmpz_ui(p, testdata[i][0]); if (fmpz_fdiv_ui(p, 1000000000) != testdata[i][1]) { flint_printf("FAIL:\n"); flint_printf("p(%wd) does not agree with known value mod 10^9\n", testdata[i][0]); flint_printf("Computed: %wu\n", fmpz_fdiv_ui(p, 1000000000)); flint_printf("Expected: %wu\n", testdata[i][1]); flint_abort(); } } fmpz_clear(p); } TEST_FUNCTION_END(state); } #undef testdata flint-3.1.3/src/perm.h000066400000000000000000000062471461254215100145470ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef PERM_H #define PERM_H #ifdef PERM_INLINES_C #define PERM_INLINE #else #define PERM_INLINE static inline #endif #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *********************************************************/ PERM_INLINE slong * _perm_init(slong n) { slong i, *vec; vec = (slong *) flint_malloc(n * sizeof(slong)); if (!vec) { flint_throw(FLINT_ERROR, "ERROR (_perm_init).\n\n"); } for (i = 0; i < n; i++) vec[i] = i; return vec; } PERM_INLINE void _perm_clear(slong * vec) { flint_free(vec); } /* Assignment ****************************************************************/ PERM_INLINE slong _perm_equal(const slong *vec1, const slong *vec2, slong n) { slong i; for (i = 0; i < n; i++) if (vec1[i] != vec2[i]) return 0; return 1; } PERM_INLINE void _perm_set(slong *res, const slong *vec, slong n) { slong i; for (i = 0; i < n; i++) res[i] = vec[i]; } PERM_INLINE void _perm_one(slong *vec, slong n) { slong i; for (i = 0; i < n; i++) vec[i] = i; } PERM_INLINE void _perm_inv(slong *res, const slong *vec, slong n) { slong i; if (res == vec) { slong *t = (slong *) flint_malloc(n * sizeof(slong)); if (!t) { flint_throw(FLINT_ERROR, "ERROR (_perm_inv).\n\n"); } for (i = 0; i < n; i++) t[i] = vec[i]; for (i = 0; i < n; i++) res[t[i]] = i; flint_free(t); } else { for (i = 0; i < n; i++) res[vec[i]] = i; } } /* Composition ***************************************************************/ PERM_INLINE void _perm_compose(slong *res, const slong *vec1, const slong *vec2, slong n) { slong i; if (res == vec1) { slong *t = (slong *) flint_malloc(n * sizeof(slong)); for (i = 0; i < n; i++) t[i] = vec1[i]; for (i = 0; i < n; i++) res[i] = t[vec2[i]]; flint_free(t); } else { for (i = 0; i < n; i++) res[i] = vec1[vec2[i]]; } } /* Randomisation *************************************************************/ int _perm_randtest(slong * vec, slong n, flint_rand_t state); /* Parity ********************************************************************/ int _perm_parity(const slong * vec, slong n); #define _long_vec_print _Pragma("GCC error \"'_long_vec_print(vec, len)' is deprecated. Use 'flint_printf(\"%{slong*}\", vec, len)' instead.\"") #define _perm_print _Pragma("GCC error \"'_perm_print(vec, len)' is deprecated. Use 'flint_printf(\"%{slong*}\", vec, len)' instead.\"") #define _perm_set_one _Pragma("GCC error \"'_perm_set_one' is deprecated. Use '_perm_one' instead.\"") #ifdef __cplusplus } #endif #endif flint-3.1.3/src/perm/000077500000000000000000000000001461254215100143655ustar00rootroot00000000000000flint-3.1.3/src/perm/inlines.c000066400000000000000000000006671461254215100162030ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define PERM_INLINES_C #include "flint.h" #include "perm.h" flint-3.1.3/src/perm/parity.c000066400000000000000000000020131461254215100160350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" int _perm_parity(const slong *vec, slong n) { slong i, k; int * encountered; int parity; TMP_INIT; if (n <= 1) return 0; TMP_START; parity = 0; encountered = (int *) TMP_ALLOC(n*sizeof(int)); for (i = 0; i < n; i++) encountered[i] = 0; for (i = 0; i < n; i++) { if (encountered[i] != 0) { parity ^= 1; } else { k = i; do { k = vec[k]; encountered[k] = 1; } while (k != i); } } TMP_END; return parity; } flint-3.1.3/src/perm/randtest.c000066400000000000000000000015051461254215100163560ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "perm.h" #include "flint.h" #include "ulong_extras.h" int _perm_randtest(slong *vec, slong n, flint_rand_t state) { slong i, j, t; int parity = 0; for (i = 0; i < n; i++) vec[i] = i; for (i = n - 1; i > 0; i--) { j = n_randint(state, i + 1); parity ^= (i != j); t = vec[i]; vec[i] = vec[j]; vec[j] = t; } return parity; } flint-3.1.3/src/perm/test/000077500000000000000000000000001461254215100153445ustar00rootroot00000000000000flint-3.1.3/src/perm/test/main.c000066400000000000000000000015431461254215100164370ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-compose.c" #include "t-inv.c" #include "t-parity.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(perm_compose), TEST_FUNCTION(perm_inv), TEST_FUNCTION(perm_parity) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/perm/test/t-compose.c000066400000000000000000000042711461254215100174220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" TEST_FUNCTION_START(perm_compose, state) { int i; /* check (b^(-1))(b(a)) = a */ for (i = 0; i < 10000; i++) { slong n, *a, *b, *binv, *c; n = n_randint(state, 100); a = _perm_init(n); b = _perm_init(n); binv = _perm_init(n); c = _perm_init(n); _perm_randtest(a, n, state); _perm_randtest(b, n, state); _perm_inv(binv, b, n); _perm_compose(c, b, a, n); _perm_compose(c, binv, c, n); if (!_perm_equal(a, c, n)) TEST_FUNCTION_FAIL( "n = %wd\n" "a = %{slong*}\n\n" "b = %{slong*}\n\n" "binv = %{slong*}\n\n" "c = %{slong*}\n\n", n, a, n, b, n, binv, n, c, n); _perm_clear(a); _perm_clear(b); _perm_clear(binv); _perm_clear(c); } /* check aliasing with first argument */ for (i = 0; i < 10000; i++) { slong n, *a, *b, *c; n = n_randint(state, 100); a = _perm_init(n); b = _perm_init(n); c = _perm_init(n); _perm_randtest(a, n, state); _perm_randtest(b, n, state); _perm_compose(c, b, a, n); _perm_compose(b, b, a, n); if (!_perm_equal(b, c, n)) TEST_FUNCTION_FAIL( "n = %wd\n" "a = %{slong*}\n\n" "b = %{slong*}\n\n" "c = %{slong*}\n\n", n, a, n, b, n, c, n); _perm_clear(a); _perm_clear(b); _perm_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/perm/test/t-inv.c000066400000000000000000000034261461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" TEST_FUNCTION_START(perm_inv, state) { int i; /* check inv(inv(a)) == a */ for (i = 0; i < 10000; i++) { slong n, *a, *b, *c; n = n_randint(state, 100); a = _perm_init(n); b = _perm_init(n); c = _perm_init(n); _perm_randtest(a, n, state); _perm_inv(b, a, n); _perm_inv(c, b, n); if (!_perm_equal(a, c, n)) TEST_FUNCTION_FAIL( "n = %wd\n" "a = %{slong*}\n\n" "b = %{slong*}\n\n" "c = %{slong*}\n\n", n, a, n, b, n, c, n); _perm_clear(a); _perm_clear(b); _perm_clear(c); } /* check aliasing */ for (i = 0; i < 10000; i++) { slong n, *a, *b; n = n_randint(state, 100); a = _perm_init(n); b = _perm_init(n); _perm_randtest(a, n, state); _perm_inv(b, a, n); _perm_inv(a, a, n); if (!_perm_equal(a, b, n)) TEST_FUNCTION_FAIL( "n = %wd\n" "a = %{slong*}\n\n" "b = %{slong*}\n\n", n, a, n, b, n); _perm_clear(a); _perm_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/perm/test/t-parity.c000066400000000000000000000030741461254215100172650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "perm.h" TEST_FUNCTION_START(perm_parity, state) { int i; /* check inv(inv(a)) == a */ for (i = 0; i < 10000; i++) { slong n, *a, *b, *c; int ap, bp, cp, ap2, bp2, cp2; n = n_randint(state, 100); a = _perm_init(n); b = _perm_init(n); c = _perm_init(n); ap = _perm_randtest(a, n, state); bp = _perm_randtest(b, n, state); _perm_compose(c, a, b, n); cp = ap ^ bp; ap2 = _perm_parity(a, n); bp2 = _perm_parity(b, n); cp2 = _perm_parity(c, n); if (ap != ap2 || bp != bp2 || cp != cp2) TEST_FUNCTION_FAIL( "n = %wd\n" "a = %{slong*}\n\n" "b = %{slong*}\n\n" "c = %{slong*}\n\n" "ap = %d\n" "bp = %d\n" "cp = %d\n" "ap2 = %d\n" "bp2 = %d\n" "cp2 = %d\n", n, a, n, b, n, c, n, ap, bp, cp, ap2, bp2, cp2); _perm_clear(a); _perm_clear(b); _perm_clear(c); } TEST_FUNCTION_END(state); } flint-3.1.3/src/profile/000077500000000000000000000000001461254215100150625ustar00rootroot00000000000000flint-3.1.3/src/profile/p-invert_limb.c000066400000000000000000000040321461254215100177740ustar00rootroot00000000000000/* Copyright 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" typedef struct { int algo; } algo_s; #define invert_limb_naive(ninv, n) \ do { \ mp_limb_t dummy; \ udiv_qrnnd (ninv, dummy, ~(n), ~(WORD(0)), n); \ } while (0) void sample(void * arg, ulong count) { ulong * array = (ulong *) flint_malloc(200 * sizeof(ulong)); ulong i, ninv, sum = 0; slong j; algo_s * alg = (algo_s *) arg; FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { for (j = 0; j < 200; j++) { array[j] = n_randlimb(state) | (UWORD(1) << (FLINT_BITS - 1)); } prof_start(); if (alg->algo == 0) { for (j = 0; j < 200; j++) { ninv = n_preinvert_limb_prenorm(array[j]); sum += ninv; } } else { for (j = 0; j < 200; j++) { invert_limb_naive(ninv, array[j]); sum += ninv; } } prof_stop(); if (sum == 0) flint_printf("\r"); } flint_randclear(state); flint_free(array); } int main(void) { double min, max; algo_s alg; alg.algo = 0; prof_repeat(&min, &max, sample, &alg); flint_printf("invert_limb min time is %.3f cycles, max time is %.3f cycles\n", min/FLINT_CLOCK_SCALE_FACTOR/200, max/FLINT_CLOCK_SCALE_FACTOR/200); alg.algo = 1; prof_repeat(&min, &max, sample, &alg); flint_printf("invert_limb_naive min time is %.3f cycles, max time is %.3f cycles\n", min/FLINT_CLOCK_SCALE_FACTOR/200, max/FLINT_CLOCK_SCALE_FACTOR/200); return 0; } flint-3.1.3/src/profile/p-udiv_qrnnd.c000066400000000000000000000026531461254215100176420ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t d; mp_ptr array = (mp_ptr) flint_malloc(200 * sizeof(mp_limb_t)); ulong i; int j; FLINT_TEST_INIT(state); d = n_randtest_not_zero(state); for (i = 0; i < count; i++) { for (j = 0; j < 200; j+=2) { do { array[j] = n_randtest(state); } while (array[j] >= d); array[j + 1] = n_randtest(state); } prof_start(); for (j = 0; j < 200; j+=2) { udiv_qrnnd(array[j], array[j+1], array[j], array[j+1], d); } prof_stop(); for (j = 0; j < 200; j++) if (array[j] == 0) flint_printf("\r"); } flint_randclear(state); flint_free(array); } int main(void) { double min, max; prof_repeat(&min, &max, sample, NULL); flint_printf("udiv_qrnnd min time is %.3f cycles, max time is %.3f cycles\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); return 0; } flint-3.1.3/src/profile/p-udiv_qrnnd_preinv.c000066400000000000000000000027551461254215100212300ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t d, q, r, dinv, norm; mp_ptr array = (mp_ptr) flint_malloc(200 * sizeof(mp_limb_t)); ulong i; int j; FLINT_TEST_INIT(state); d = n_randtest_not_zero(state); norm = flint_clz(d); d <<= norm; for (i = 0; i < count; i++) { for (j = 0; j < 200; j+=2) { do { array[j] = n_randtest(state); } while (array[j] >= d); array[j + 1] = n_randtest(state); } dinv = n_preinvert_limb_prenorm(d); prof_start(); for (j = 0; j < 200; j+=2) { udiv_qrnnd_preinv(q, r, array[j], array[j+1], d, dinv); } prof_stop(); if (q + r == 0) flint_printf("\r"); } flint_randclear(state); flint_free(array); } int main(void) { double min, max; prof_repeat(&min, &max, sample, NULL); flint_printf("udiv_qrnnd_preinv min time is %.3f cycles, max time is %.3f cycles\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/100, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/100); return 0; } flint-3.1.3/src/profile/timings.txt000066400000000000000000000002721461254215100172760ustar00rootroot00000000000000udiv_qrnnd(q, r, nh, nl, d) Core2 53.4 cycles K8 74.3 cycles K10 80.6 cycles udiv_qrnnd_preinv(q, r, nh, nl, d, di) Core2 21.7 cycles K8 14.9 cycles K10 17.0 cycles flint-3.1.3/src/profiler.h000066400000000000000000000137771461254215100154340ustar00rootroot00000000000000/* Copyright 2007 William Hart and David Harvey This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef FLINT_PROFILER_H #define FLINT_PROFILER_H #include "flint.h" #include #if defined( _MSC_VER ) #include #include "gettimeofday.h" #pragma intrinsic( __rdtsc ) #else #include #endif #if defined (__WIN32) && !defined(__CYGWIN__) #ifdef __cplusplus void GetSystemTimeAsFileTime(FILETIME*); static inline int gettimeofday(struct timeval * p, void * tz) { union { slong slong ns100; FILETIME ft; } now; GetSystemTimeAsFileTime(&(now.ft)); p->tv_usec=(slong)((now.ns100 / WORD(10)L) % WORD(1000000)L ); p->tv_sec= (slong)((now.ns100-(WORD(116444736000000000)L))/WORD(10000000)L); return 0; } #else int gettimeofday(struct timeval * p, void * tz); #endif #elif !defined(_MSC_VER) #include #endif #ifdef __cplusplus extern "C" { #endif typedef struct { ulong size; ulong peak; ulong hwm; ulong rss; } meminfo_t[1]; void get_memory_usage(meminfo_t meminfo); typedef struct { slong cpu; slong wall; } timeit_t[1]; static inline void timeit_start(timeit_t t) { struct timeval tv; gettimeofday(&tv, 0); t->wall = - tv.tv_sec * 1000 - tv.tv_usec / 1000; t->cpu = - clock() * 1000 / CLOCKS_PER_SEC; } static inline slong timeit_query_wall(timeit_t t) { struct timeval tv; gettimeofday(&tv, 0); return t->wall + tv.tv_sec * 1000 + tv.tv_usec / 1000; } static inline void timeit_stop(timeit_t t) { struct timeval tv; gettimeofday(&tv, 0); t->wall += tv.tv_sec * 1000 + tv.tv_usec / 1000; t->cpu += clock() * 1000 / CLOCKS_PER_SEC; } static inline void timeit_start_us(timeit_t t) { struct timeval tv; gettimeofday(&tv, 0); t->wall = - tv.tv_sec * 1000000 - tv.tv_usec; } static inline void timeit_stop_us(timeit_t t) { struct timeval tv; gettimeofday(&tv, 0); t->wall += tv.tv_sec * 1000000 + tv.tv_usec; } /****************************************************************************** Timer based on the x86 cycle counter ******************************************************************************/ #if (defined( _MSC_VER ) || (GMP_LIMB_BITS == 64 && defined (__amd64__)) || \ (GMP_LIMB_BITS == 32 && (defined (__i386__) || \ defined (__i486__) || defined(__amd64__)))) #define FLINT_NUM_CLOCKS 20 #define FLINT_CLOCKSPEED 3100000000.0 FLINT_DLL extern double clock_last[FLINT_NUM_CLOCKS]; FLINT_DLL extern double clock_accum[FLINT_NUM_CLOCKS]; static inline double get_cycle_counter(void) { #if defined( _MSC_VER ) return (double)__rdtsc(); #else unsigned int hi; unsigned int lo; __asm("rdtsc; movl %%edx,%0; movl %%eax,%1" : "=r" (hi), "=r" (lo) : : "%edx", "%eax"); return (double) hi * (1 << 30) * 4 + lo; #endif } #define FLINT_CLOCK_SCALE_FACTOR (1000000.0 / FLINT_CLOCKSPEED) static inline void init_clock(int n) { clock_accum[n] = 0.0; } static inline void init_all_clocks(void) { int i; for (i = 0; i < FLINT_NUM_CLOCKS; i++) clock_accum[i] = 0.0; } static inline double get_clock(int n) { return clock_accum[n] * FLINT_CLOCK_SCALE_FACTOR; } static inline void start_clock(int n) { clock_last[n] = get_cycle_counter(); } static inline void stop_clock(int n) { double now = get_cycle_counter(); clock_accum[n] += (now - clock_last[n]); } /****************************************************************************** Framework for repeatedly sampling a single target ******************************************************************************/ static inline void prof_start(void) { start_clock(0); } static inline void prof_stop(void) { stop_clock(0); } typedef void (*profile_target_t)(void* arg, ulong count); void prof_repeat(double* min, double* max, profile_target_t target, void* arg); #define DURATION_THRESHOLD 5000.0 #define DURATION_TARGET 10000.0 #endif /****************************************************************************** Simple timing macros ******************************************************************************/ #define TIMEIT_PRINT(__timer, __reps) \ flint_printf("cpu/wall(s): %g %g\n", \ __timer->cpu*0.001/__reps, __timer->wall*0.001 / __reps); #define TIMEIT_REPEAT(__timer, __reps) \ do \ { \ slong __timeit_k; \ __reps = 1; \ while (1) \ { \ timeit_start(__timer); \ for (__timeit_k = 0; __timeit_k < __reps; __timeit_k++) \ { #define TIMEIT_END_REPEAT(__timer, __reps) \ } \ timeit_stop(__timer); \ if (__timer->cpu >= 100) \ break; \ __reps *= 10; \ } \ } while (0); #define TIMEIT_START \ do { \ timeit_t __timer; slong __reps; \ TIMEIT_REPEAT(__timer, __reps) #define TIMEIT_STOP \ TIMEIT_END_REPEAT(__timer, __reps) \ TIMEIT_PRINT(__timer, __reps) \ } while (0); #define TIMEIT_STOP_VALUES(tcpu, twall) \ TIMEIT_END_REPEAT(__timer, __reps) \ (tcpu) = __timer->cpu*0.001 / __reps; \ (twall) = __timer->wall*0.001 / __reps; \ } while (0); #define TIMEIT_ONCE_START \ do \ { \ timeit_t __timer; \ timeit_start(__timer); \ do { \ #define TIMEIT_ONCE_STOP \ } while (0); \ timeit_stop(__timer); \ TIMEIT_PRINT(__timer, 1) \ } while (0); \ #define SHOW_MEMORY_USAGE \ do { \ meminfo_t meminfo; \ get_memory_usage(meminfo); \ flint_printf("virt/peak/res/peak(MB): %.2f %.2f %.2f %.2f\n", \ meminfo->size / 1024.0, meminfo->peak / 1024.0, \ meminfo->rss / 1024.0, meminfo->hwm / 1024.0); \ } while (0); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/python/000077500000000000000000000000001461254215100147435ustar00rootroot00000000000000flint-3.1.3/src/python/CCmath.py000066400000000000000000000003051461254215100164520ustar00rootroot00000000000000import flint2 CC = flint2.CC __exclude = set(["prec"]) __globals = globals() for __obj in set(dir(CC)) - __exclude: if __obj not in __exclude: __globals[__obj] = getattr(CC, __obj) flint-3.1.3/src/python/RRmath.py000066400000000000000000000003051461254215100165100ustar00rootroot00000000000000import flint2 RR = flint2.RR __exclude = set(["prec"]) __globals = globals() for __obj in set(dir(RR)) - __exclude: if __obj not in __exclude: __globals[__obj] = getattr(RR, __obj) flint-3.1.3/src/python/flint2.py000066400000000000000000000000341461254215100165100ustar00rootroot00000000000000from flint_ctypes import * flint-3.1.3/src/python/flint_ctypes.py000066400000000000000000010736731461254215100200410ustar00rootroot00000000000000import ctypes import ctypes.util import sys libflint_path = ctypes.util.find_library('flint') if libflint_path == None: raise ValueError('Could not find libflint.') libflint = ctypes.CDLL(libflint_path) libcalcium = libarb = libgr = libflint T_TRUE = 0 T_FALSE = 1 T_UNKNOWN = 2 GR_SUCCESS = 0 GR_DOMAIN = 1 GR_UNABLE = 2 HUGE_LENGTH = 2**40 c_slong = ctypes.c_long c_ulong = ctypes.c_ulong if sys.maxsize < 2**32: FLINT_BITS = 32 else: FLINT_BITS = 64 if ctypes.sizeof(c_slong) == 4: c_slong = ctypes.c_longlong c_ulong = ctypes.c_ulonglong assert ctypes.sizeof(c_slong) == 8 assert ctypes.sizeof(c_ulong) == 8 UWORD_MAX = (1<= 1 assert n <= 65536 libflint.flint_set_num_threads(n) def get_num_threads(): return libflint.flint_get_num_threads() class FlintException(Exception): __module__ = Exception.__module__ def __str__(self): if isinstance(self.args[0], str): return self.args[0] ctx, status, rstr, args = self.args[0] rstr2 = rstr.replace("$", "") argnames = [] for i, c in enumerate(rstr): if c == "$": argname = "" for j in range(i + 1, len(rstr)): if rstr[j].isalnum(): argname += rstr[j] else: break argnames.append(argname) if status & GR_UNABLE: s = "failed to compute " + rstr2 + " in " + "{" + str(ctx) + "}" else: s = rstr2 + " is not an element of " + "{" + str(ctx) + "}" if args: s += " for " for i, arg in enumerate(args): s += "{" if argnames: s += argnames[i] + " = " else: s += "input " argstr = str(arg) if len(argstr) > 200: argstr = argstr[:80] + ("{{{...}}}") + argstr[-80:] s += argstr s += "}" if i < len(args) - 1: s += ", " return s class FlintDomainError(ValueError, FlintException): """ Raised when an operation does not have a well-defined result in the target domain. """ __module__ = Exception.__module__ class FlintUnableError(NotImplementedError, FlintException): """ Raised when an operation cannot be performed because the algorithm is not implemented or there is insufficient precision, memory, etc. """ __module__ = Exception.__module__ def _handle_error(ctx, status, rstr, *args): if status & GR_UNABLE: raise FlintUnableError((ctx, status, rstr, args)) else: raise FlintDomainError((ctx, status, rstr, args)) class flint_rand_struct(ctypes.Structure): # todo: use the real size _fields_ = [('data', c_slong * 16)] _flint_rand = flint_rand_struct() libflint.flint_randinit(ctypes.byref(_flint_rand)) class fmpz_struct(ctypes.Structure): _fields_ = [('val', c_slong)] class fmpq_struct(ctypes.Structure): _fields_ = [('num', c_slong), ('den', c_slong)] class fmpzi_struct(ctypes.Structure): _fields_ = [('real', c_slong), ('imag', c_slong)] class fmpz_poly_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong)] class fmpq_poly_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong), ('den', c_slong)] class fmpz_mpoly_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('exp', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong), ('bits', c_slong)] class fmpz_mpoly_q_struct(ctypes.Structure): _fields_ = [('num', fmpz_mpoly_struct), ('den', fmpz_mpoly_struct)] # todo: actually a union class nf_elem_struct(ctypes.Structure): _fields_ = [('poly', fmpq_poly_struct)] class arf_struct(ctypes.Structure): _fields_ = [('data', c_slong * 4)] class acf_struct(ctypes.Structure): _fields_ = [('real', arf_struct), ('imag', arf_struct)] class arb_struct(ctypes.Structure): _fields_ = [('data', c_slong * 6)] class acb_struct(ctypes.Structure): _fields_ = [('real', arb_struct), ('imag', arb_struct)] class fexpr_struct(ctypes.Structure): _fields_ = [('data', ctypes.c_void_p), ('alloc', c_slong)] class qqbar_struct(ctypes.Structure): _fields_ = [('poly', fmpz_poly_struct), ('enclosure', acb_struct)] class ca_struct(ctypes.Structure): _fields_ = [('data', c_slong * 5)] class nmod_struct(ctypes.Structure): _fields_ = [('val', c_ulong)] class nmod_poly_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong), ('n', c_ulong), ('ninv', c_ulong), ('nnorm', c_slong)] class fq_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong)] class fq_nmod_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong), ('n', c_ulong), ('ninv', c_ulong), ('nnorm', c_slong)] class fq_zech_struct(ctypes.Structure): _fields_ = [('n', ctypes.c_ulong)] class gr_vec_struct(ctypes.Structure): _fields_ = [('entries', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong)] class gr_poly_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong)] class gr_series_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('alloc', c_slong), ('length', c_slong), ('error', c_slong)] class gr_mpoly_struct(ctypes.Structure): _fields_ = [('coeffs', ctypes.c_void_p), ('exps', ctypes.c_void_p), ('length', c_slong), ('bits', c_slong), ('coeffs_alloc', c_slong), ('exps_alloc', c_slong)] class psl2z_struct(ctypes.Structure): _fields_ = [('a', c_slong), ('b', c_slong), ('c', c_slong), ('d', c_slong)] class dirichlet_char_struct(ctypes.Structure): _fields_ = [('n', c_ulong), ('log', ctypes.POINTER(c_ulong))] class perm_struct(ctypes.Structure): _fields_ = [('entries', ctypes.POINTER(c_slong))] class gr_mat_struct(ctypes.Structure): _fields_ = [('entries', ctypes.c_void_p), ('r', c_slong), ('c', c_slong), ('rows', ctypes.c_void_p)] # todo: efficiently def fmpz_to_python_int(xref): ptr = libflint.fmpz_get_str(None, 10, xref) try: return int(ctypes.cast(ptr, ctypes.c_char_p).value.decode()) finally: libflint.flint_free(ptr) # todo def fmpq_set_python(cref, x): assert isinstance(x, int) and WORD_MIN <= x <= WORD_MAX libflint.fmpq_set_si(cref, x, 1) class Undecidable(NotImplementedError): pass class gr_ctx_struct(ctypes.Structure): _fields_ = [('content', ctypes.c_char * libgr.gr_ctx_sizeof_ctx())] libflint.flint_malloc.restype = ctypes.c_void_p libflint.flint_free.argtypes = (ctypes.c_void_p,) libflint.fmpz_set_str.argtypes = ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int libflint.fmpz_get_str.argtypes = ctypes.c_char_p, ctypes.c_int, ctypes.POINTER(fmpz_struct) libflint.fmpz_get_str.restype = ctypes.c_void_p libgr.gr_heap_init.argtypes = (ctypes.POINTER(gr_ctx_struct),) libgr.gr_heap_init.restype = ctypes.c_void_p libgr.gr_ctx_data_as_ptr.argtypes = (ctypes.c_void_p,) libgr.gr_ctx_data_as_ptr.restype = ctypes.c_void_p libgr.gr_set_si.argtypes = (ctypes.c_void_p, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_add_si.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_sub_si.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_mul_si.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_div_si.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_pow_si.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_set_d.argtypes = (ctypes.c_void_p, ctypes.c_double, ctypes.POINTER(gr_ctx_struct)) libgr.gr_set_str.argtypes = (ctypes.c_void_p, ctypes.c_char_p, ctypes.POINTER(gr_ctx_struct)) libgr.gr_get_str.argtypes = (ctypes.POINTER(ctypes.c_char_p), ctypes.c_void_p, ctypes.POINTER(gr_ctx_struct)) libgr.gr_get_str_n.argtypes = (ctypes.POINTER(ctypes.c_char_p), ctypes.c_void_p, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_cmp.argtypes = (ctypes.POINTER(ctypes.c_int), ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(gr_ctx_struct)) libgr.gr_cmpabs.argtypes = (ctypes.POINTER(ctypes.c_int), ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(gr_ctx_struct)) libgr.gr_heap_clear.argtypes = (ctypes.c_void_p, ctypes.POINTER(gr_ctx_struct)) libgr.gr_ctx_init_nmod.argtypes = (ctypes.POINTER(gr_ctx_struct), c_ulong) libgr.gr_ctx_init_dirichlet_group.argtypes = (ctypes.POINTER(gr_ctx_struct), c_ulong) _add_methods = [libgr.gr_add, libgr.gr_add_si, libgr.gr_add_fmpz, libgr.gr_add_other, libgr.gr_other_add] _sub_methods = [libgr.gr_sub, libgr.gr_sub_si, libgr.gr_sub_fmpz, libgr.gr_sub_other, libgr.gr_other_sub] _mul_methods = [libgr.gr_mul, libgr.gr_mul_si, libgr.gr_mul_fmpz, libgr.gr_mul_other, libgr.gr_other_mul] _div_methods = [libgr.gr_div, libgr.gr_div_si, libgr.gr_div_fmpz, libgr.gr_div_other, libgr.gr_other_div] _pow_methods = [libgr.gr_pow, libgr.gr_pow_si, libgr.gr_pow_fmpz, libgr.gr_pow_other, libgr.gr_other_pow] _gr_logic = 0 class Truth: def __init__(self, value): self.value = value def __repr__(self): if self.value == T_TRUE: return "TRUE" if self.value == T_FALSE: return "FALSE" return "UNKNOWN" def __bool__(self): if self.value == T_UNKNOWN: raise ValueError("unknown truth value") return self.value == T_TRUE class LogicContext(object): """ Handle the result of predicates (experimental): >>> a = (RR_arb(1) / 3) * 3 >>> a [1.00000000000000 +/- 3.89e-16] >>> with strict_logic: ... a == 1 ... Traceback (most recent call last): ... Undecidable: unable to decide x == y for x = [1.00000000000000 +/- 3.89e-16], y = 1 over Real numbers (arb, prec = 53) >>> with pessimistic_logic: ... a == 1 ... False >>> with optimistic_logic: ... a == 1 ... True """ def __init__(self, value): self.logic = value def __enter__(self): global _gr_logic self.original = _gr_logic _gr_logic = self.logic def __exit__(self, type, value, traceback): global _gr_logic _gr_logic = self.original strict_logic = LogicContext(0) pessimistic_logic = LogicContext(-1) optimistic_logic = LogicContext(1) none_logic = LogicContext(2) triple_logic = LogicContext(3) def set_logic(which_logic): global _gr_logic _gr_logic = which_logic.logic class gr_ctx: @property def _as_parameter_(self): return self._ref @staticmethod def from_param(arg): return arg def __init__(self): self._data = gr_ctx_struct() self._ref = ctypes.byref(self._data) self._str = None self._refcount = 1 def _repr(self): if self._str is None: arr = ctypes.c_char_p() if libgr.gr_ctx_get_str(ctypes.byref(arr), self._ref) != GR_SUCCESS: raise NotImplementedError try: self._str = ctypes.cast(arr, ctypes.c_char_p).value.decode("ascii") finally: libflint.flint_free(arr) return self._str def _ctx_predicate(self, op, rstr): truth = op(self._ref) if _gr_logic == 3: return Truth(truth) if truth == T_TRUE: return True if truth == T_FALSE: return False if _gr_logic == 1: return True if _gr_logic == -1: return False if _gr_logic == 2: return None raise Undecidable(f"unable to decide {rstr} for ctx = {self}") def is_ring(self): """ Return whether this structure is a ring. >>> RR.is_ring() True >>> PolynomialRing(QQbar).is_ring() True >>> RF.is_ring() # floats do not satisfy the ring laws False >>> Mat(ZZ, 2).is_ring() True >>> Mat(ZZ, 2, 3).is_ring() # nonrectangular matrices False >>> Mat(ZZ).is_ring() # matrices of mixed shape do not form a ring False >>> Mat(RF, 2).is_ring() False >>> Vec(RR, 3).is_ring() True >>> Vec(RR).is_ring() # vectors of mixed length do not form a ring False >>> Vec(RF, 3).is_ring() False >>> Vec(RF, 0).is_ring() # empty vectors form a ring True >>> DirichletGroup(3).is_ring() False >>> PSL2Z.is_ring() False >>> PolynomialRing(RF).is_ring() False >>> PowerSeriesRing(RF).is_ring() False >>> PowerSeriesModRing(RF, 1).is_ring() False >>> PowerSeriesModRing(RF, 0).is_ring() # is the zero ring True """ return self._ctx_predicate(libflint.gr_ctx_is_ring, "is_ring") def is_commutative_ring(self): """ Return whether this structure is a commutative ring. >>> QQbar.is_commutative_ring() True >>> CC.is_commutative_ring() True >>> PolynomialRing(QQ).is_commutative_ring() True >>> Mat(ZZ, 2).is_commutative_ring() False >>> PolynomialRing(Mat(ZZ, 2)).is_commutative_ring() False >>> PowerSeriesRing(QQ).is_commutative_ring() True >>> PowerSeriesRing(Mat(ZZ, 2)).is_commutative_ring() False >>> Mat(ZZ, 0).is_commutative_ring() True >>> Mat(ZZ, 1).is_commutative_ring() True >>> Mat(ZZ).is_commutative_ring() False >>> Mat(ZZ, 0, 1).is_commutative_ring() False >>> Mat(ZZmod(2), 2, 2).is_commutative_ring() False >>> Mat(ZZmod(1), 2, 2).is_commutative_ring() True >>> Mat(PowerSeriesModRing(ZZ, 0), 2, 2).is_commutative_ring() True >>> Mat(RF, 1).is_commutative_ring() False >>> Mat(RF, 0).is_commutative_ring() True >>> Vec(ZZ, 3).is_commutative_ring() True >>> Vec(Mat(ZZ, 2), 3).is_commutative_ring() False >>> FractionField_fmpz_mpoly_q(3).is_commutative_ring() True """ return self._ctx_predicate(libflint.gr_ctx_is_commutative_ring, "is_commutative_ring") def _set_gen_name(self, s): status = libflint.gr_ctx_set_gen_name(self._ref, ctypes.c_char_p(str(s).encode('ascii'))) self._str = None assert not status def _set_gen_names(self, s): arr = (ctypes.c_char_p * len(s))() for i in range(len(s)): arr[i] = ctypes.c_char_p(str(s[i]).encode('ascii')) status = libflint.gr_ctx_set_gen_names(self._ref, arr) self._str = None assert not status def __call__(self, *args, **kwargs): kwargs['context'] = self return self._elem_type(*args, **kwargs) def __repr__(self): return self._repr() def __del__(self): self._decrement_refcount() def _decrement_refcount(self): self._refcount -= 1 if not self._refcount: libgr.gr_ctx_clear(self._ref) @property def prec(self): p = c_slong() status = libgr.gr_ctx_get_real_prec(ctypes.byref(p), self._ref) assert not status return p.value @prec.setter def prec(self, prec): status = libgr.gr_ctx_set_real_prec(self._ref, prec) assert not status # constants, sequences etc. with elements in this parent # todo: element shortcuts to allow both RR.pi() and RR().pi() @staticmethod def _constant(ctx, op, rstr): res = ctx._elem_type(context=ctx) status = op(res._ref, ctx._ref) if status: _handle_error(ctx, status, rstr) return res @staticmethod def _as_ui(x): type_x = type(x) if type_x is not int: if type_x is not fmpz: x = ZZ(x) x = int(x) assert 0 <= x <= UWORD_MAX return x @staticmethod def _as_si(x): type_x = type(x) if type_x is not int: if type_x is not fmpz: x = ZZ(x) x = int(x) assert WORD_MIN <= x <= WORD_MAX return x @staticmethod def _as_fmpz(x): if type(x) is not fmpz: x = ZZ(x) return x def _as_elem(ctx, x): if type(x) is not ctx._elem_type or x._ctx_python is not ctx: x = ctx(x) return x def _as_vec(ctx, x): if type(x) is not gr_vec or x._ctx_python._element_ring is not ctx: x = Vec(ctx)(x) return x def _unary_op(ctx, x, op, rstr): x = ctx._as_elem(x) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res def _unary_unary_op(ctx, x, op, rstr): x = ctx._as_elem(x) res1 = ctx._elem_type(context=ctx) res2 = ctx._elem_type(context=ctx) status = op(res1._ref, res2._ref, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res1, res2 def _unary_op_with_flag(ctx, x, flag, op, rstr): x = ctx._as_elem(x) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, flag, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res def _unary_unary_op_with_flag(ctx, x, flag, op, rstr): x = ctx._as_elem(x) res1 = ctx._elem_type(context=ctx) res2 = ctx._elem_type(context=ctx) status = op(res1._ref, res2._ref, x._ref, flag, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res1, res2 def _unary_op_fmpz(ctx, x, op, rstr): x = ctx._as_fmpz(x) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res def _unary_op_with_fmpz_fmpq_overloads(ctx, x, op, op_ui=None, op_fmpz=None, op_fmpq=None, rstr=None): type_x = type(x) res = ctx._elem_type(context=ctx) if type_x is not ctx._elem_type or x._ctx_python is not ctx: if type_x is fmpq and op_fmpq is not None: status = op_fmpq(res._ref, x._ref, ctx._ref) elif type_x is fmpz and op_fmpz is not None: status = op_fmpz(res._ref, x._ref, ctx._ref) elif type_x is int and op_fmpz is not None: x = ZZ(x) status = op_fmpz(res._ref, x._ref, ctx._ref) elif type_x in (fmpz, int) and op_ui is not None: try: x = ctx._as_ui(x) op_ui.argtypes = (ctypes.c_void_p, c_ulong, ctypes.c_void_p) status = op_ui(res._ref, x, ctx._ref) except: x = ctx(x) status = op(res._ref, x._ref, ctx._ref) else: x = ctx(x) status = op(res._ref, x._ref, ctx._ref) else: status = op(res._ref, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res def _binary_op_with_overloads(ctx, x, y, op, op_ui=None, op_fmpz=None, op_fmpq=None, fmpz_op=None, rstr=None): type_x = type(x) if fmpz_op is not None and (type_x is fmpz or type_x is int): x = ZZ(x) type_y = type(y) if type_y is not ctx._elem_type or y._ctx_python is not ctx: y = ctx(y) res = ctx._elem_type(context=ctx) status = fmpz_op(res._ref, x._ref, y._ref, ctx._ref) else: if type_x is not ctx._elem_type or x._ctx_python is not ctx: x = ctx(x) type_y = type(y) res = ctx._elem_type(context=ctx) if type_y is not ctx._elem_type or y._ctx_python is not ctx: if type_y is fmpq and op_fmpq is not None: status = op_fmpq(res._ref, x._ref, y._ref, ctx._ref) elif type_y is fmpz and op_fmpz is not None: status = op_fmpz(res._ref, x._ref, y._ref, ctx._ref) elif type_y is int and op_fmpz is not None: y = ZZ(y) status = op_fmpz(res._ref, x._ref, y._ref, ctx._ref) elif type_y in (fmpz, int) and op_ui is not None: y = ctx._as_ui(y) op_ui.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_ulong, ctypes.c_void_p) status = op_ui(res._ref, x._ref, y, ctx._ref) else: y = ctx(y) status = op(res._ref, x._ref, y._ref, ctx._ref) else: status = op(res._ref, x._ref, y._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res def _binary_op(ctx, x, y, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, y._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y) return res def _binary_binary_op(ctx, x, y, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) res1 = ctx._elem_type(context=ctx) res2 = ctx._elem_type(context=ctx) status = op(res1._ref, res2._ref, x._ref, y._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y) return res1, res2 def _binary_op_with_flag(ctx, x, y, flag, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, y._ref, flag, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y) return res def _ternary_op(ctx, x, y, z, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) z = ctx._as_elem(z) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, y._ref, z._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y, z) return res def _ternary_op_with_flag(ctx, x, y, z, flag, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) z = ctx._as_elem(z) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, y._ref, z._ref, flag, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y, z) return res def _quaternary_op(ctx, x, y, z, w, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) z = ctx._as_elem(z) w = ctx._as_elem(w) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, y._ref, z._ref, w._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y, z, w) return res def _quaternary_op_with_flag(ctx, x, y, z, w, flag, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) z = ctx._as_elem(z) w = ctx._as_elem(w) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, y._ref, z._ref, w._ref, flag, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y, z, w) return res def _ternary_unary_op(ctx, x, op, rstr): x = ctx._as_elem(x) res1 = ctx._elem_type(context=ctx) res2 = ctx._elem_type(context=ctx) res3 = ctx._elem_type(context=ctx) status = op(res1._ref, res2._ref, res3._ref, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return (res1, res2, res3) def _quaternary_unary_op(ctx, x, op, rstr): x = ctx._as_elem(x) res1 = ctx._elem_type(context=ctx) res2 = ctx._elem_type(context=ctx) res3 = ctx._elem_type(context=ctx) res4 = ctx._elem_type(context=ctx) status = op(res1._ref, res2._ref, res3._ref, res4._ref, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return (res1, res2, res3, res4) def _quaternary_binary_op(ctx, x, y, op, rstr): x = ctx._as_elem(x) y = ctx._as_elem(y) res1 = ctx._elem_type(context=ctx) res2 = ctx._elem_type(context=ctx) res3 = ctx._elem_type(context=ctx) res4 = ctx._elem_type(context=ctx) status = op(res1._ref, res2._ref, res3._ref, res4._ref, x._ref, y._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y) return (res1, res2, res3, res4) def _binary_op_fmpz(ctx, x, y, op, rstr): x = ctx._as_elem(x) y = ctx._as_fmpz(y) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, y._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y) return res def _ui_binary_op(ctx, n, x, op, rstr): n = ctx._as_ui(n) x = ctx._as_elem(x) res = ctx._elem_type(context=ctx) status = op(res._ref, n, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, n, x) return res def _op_fmpz(ctx, x, op, rstr): x = ctx._as_fmpz(x) res = ctx._elem_type(context=ctx) status = op(res._ref, x._ref, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res def _op_ui(ctx, x, op, rstr): x = ctx._as_ui(x) res = ctx._elem_type(context=ctx) op.argtypes = (ctypes.c_void_p, c_ulong, ctypes.c_void_p) status = op(res._ref, x, ctx._ref) if status: _handle_error(ctx, status, rstr, x) return res def _op_uiui(ctx, x, y, op, rstr): x = ctx._as_ui(x) y = ctx._as_ui(y) res = ctx._elem_type(context=ctx) op.argtypes = (ctypes.c_void_p, c_ulong, c_ulong, ctypes.c_void_p) status = op(res._ref, x, y, ctx._ref) if status: _handle_error(ctx, status, rstr, x, y) return res def _op_vec_ctx(ctx, op, rstr): op.argtypes = (ctypes.c_void_p, ctypes.c_void_p) res = Vec(ctx)() status = op(res._ref, ctx._ref) if status: _handle_error(ctx, status, rstr) return res def _op_vec_len(ctx, n, op, rstr): n = ctx._as_si(n) assert n >= 0 assert n <= HUGE_LENGTH op.argtypes = (ctypes.c_void_p, c_slong, ctypes.c_void_p) res = Vec(ctx)() assert not libgr.gr_vec_set_length(res._ref, n, ctx._ref) status = op(libgr.gr_vec_entry_ptr(res._ref, 0, ctx._ref), n, ctx._ref) if status: _handle_error(ctx, status, rstr, n) return res def _op_vec_arg_len(ctx, x, n, op, rstr): x = ctx._as_elem(x) n = ctx._as_si(n) assert n >= 0 assert n <= HUGE_LENGTH op.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.c_void_p) res = Vec(ctx)() assert not libgr.gr_vec_set_length(res._ref, n, ctx._ref) status = op(libgr.gr_vec_entry_ptr(res._ref, 0, ctx._ref), x._ref, n, ctx._ref) if status: _handle_error(ctx, status, rstr, n) return res def _op_vec_ui_len(ctx, x, n, op, rstr): x = ctx._as_ui(x) n = ctx._as_si(n) assert n >= 0 assert n <= HUGE_LENGTH op.argtypes = (ctypes.c_void_p, c_ulong, c_slong, ctypes.c_void_p) res = Vec(ctx)() assert not libgr.gr_vec_set_length(res._ref, n, ctx._ref) status = op(libgr.gr_vec_entry_ptr(res._ref, 0, ctx._ref), x, n, ctx._ref) if status: _handle_error(ctx, status, rstr, x, n) return res def _op_vec_fmpz_len(ctx, x, n, op, rstr): x = ctx._as_fmpz(x) n = ctx._as_si(n) assert n >= 0 assert n <= HUGE_LENGTH op.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.c_void_p) res = Vec(ctx)() assert not libgr.gr_vec_set_length(res._ref, n, ctx._ref) status = op(libgr.gr_vec_entry_ptr(res._ref, 0, ctx._ref), x._ref, n, ctx._ref) if status: _handle_error(ctx, status, rstr, x, n) return res def gen(ctx): """ Gives a generator of this ring. >>> ZZi.gen() I >>> ZZx.gen() x >>> FiniteField_fq(3, 5).gen() ** 9 2*a^4+a+2 >>> (1 + PowerSeriesModRing(QQ, 5).gen())**10 1 + 10*x + 45*x^2 + 120*x^3 + 210*x^4 (mod x^5) >>> (1 + PowerSeriesRing(QQ, 5).gen())**10 1 + 10*x + 45*x^2 + 120*x^3 + 210*x^4 + O(x^5) """ return ctx._constant(ctx, libgr.gr_gen, "gen") def gens(ctx, recursive=False): """ Gives a vector of generators of this ring. If recursive=True, includes the generators of all base rings. >>> ZZx.gens() [x] >>> PolynomialRing(QQ, "v").gens() [v] >>> FiniteField_fq(3, 2).gens() [a] >>> NumberField(ZZx.gen()**2+1).gens() [a] >>> ZZ.gens() [] >>> PolynomialRing(PolynomialRing(ZZi, "x"), "y").gens(recursive=True) [I, x, y] >>> PolynomialRing_fmpz_mpoly(3).gens() [x1, x2, x3] >>> PolynomialRing(PowerSeriesRing(ZZ, var="b"), "t").gens() [t] >>> PolynomialRing(PowerSeriesRing(ZZ, var="b"), "t").gens(recursive=True) [b, t] >>> PowerSeriesRing(ZZx, 3, var="y").gens() [y] >>> PowerSeriesRing(ZZx, 3, var="y").gens(recursive=True) [x, y] """ if recursive: return ctx._op_vec_ctx(libgr.gr_gens_recursive, "gens") else: return ctx._op_vec_ctx(libgr.gr_gens, "gens") def zero(ctx): """ The zero element of this domain. >>> ZZ.zero() 0 >>> Vec(ZZ,3).zero() [0, 0, 0] >>> Vec(ZZ).zero() Traceback (most recent call last): ... FlintDomainError: zero is not an element of {Vectors (any length) over Integer ring (fmpz)} """ return ctx._constant(ctx, libgr.gr_zero, "zero") def one(ctx): """ The one element of this domain. >>> ZZ.one() 1 >>> Vec(ZZ,3).one() [1, 1, 1] >>> Vec(ZZ).one() Traceback (most recent call last): ... FlintDomainError: one is not an element of {Vectors (any length) over Integer ring (fmpz)} """ return ctx._constant(ctx, libgr.gr_one, "one") def neg_one(ctx): """ The negative one element of this domain. >>> ZZ.neg_one() -1 >>> Vec(ZZ,3).neg_one() [-1, -1, -1] >>> Vec(ZZ).neg_one() Traceback (most recent call last): ... FlintDomainError: neg_one is not an element of {Vectors (any length) over Integer ring (fmpz)} """ return ctx._constant(ctx, libgr.gr_neg_one, "neg_one") def i(ctx): """ Imaginary unit as an element of this domain. >>> QQbar.i() Root a = 1.00000*I of a^2+1 >>> QQ.i() Traceback (most recent call last): ... FlintDomainError: i is not an element of {Rational field (fmpq)} """ return ctx._constant(ctx, libgr.gr_i, "i") def pi(ctx): """ The number pi as an element of this domain. >>> RR.pi() [3.141592653589793 +/- 3.39e-16] >>> QQbar.pi() Traceback (most recent call last): ... FlintDomainError: pi is not an element of {Complex algebraic numbers (qqbar)} >>> Vec(RR, 2).pi() [[3.141592653589793 +/- 3.39e-16], [3.141592653589793 +/- 3.39e-16]] """ return ctx._constant(ctx, libgr.gr_pi, "pi") def euler(ctx): """ Euler's constant as an element of this domain. >>> RR.euler() [0.5772156649015329 +/- 9.00e-17] We do not know whether Euler's constant is rational: >>> QQ.euler() Traceback (most recent call last): ... FlintUnableError: failed to compute euler in {Rational field (fmpq)} """ return ctx._constant(ctx, libgr.gr_euler, "euler") def catalan(ctx): """ Catalan's constant as an element of this domain. >>> RR.catalan() [0.915965594177219 +/- 1.23e-16] """ return ctx._constant(ctx, libgr.gr_catalan, "catalan") def khinchin(ctx): """ Khinchin's constant as an element of this domain. >>> RR.khinchin() [2.685452001065306 +/- 6.82e-16] """ return ctx._constant(ctx, libgr.gr_khinchin, "khinchin") def glaisher(ctx): """ Khinchin's constant as an element of this domain. >>> RR.glaisher() [1.282427129100623 +/- 6.02e-16] """ return ctx._constant(ctx, libgr.gr_glaisher, "glaisher") def inv(ctx, x): """ Multiplicative inverse. >>> ZZ.inv(2) Traceback (most recent call last): ... FlintDomainError: inv(x) is not an element of {Integer ring (fmpz)} for {x = 2} >>> QQ.inv(2) 1/2 >>> RR.inv(2) 0.5000000000000000 """ return ctx._unary_op(x, libgr.gr_inv, "inv($x)") def sqrt(ctx, x): """ Square root. >>> ZZ(25).sqrt() 5 >>> RR(10).sqrt() [3.162277660168379 +/- 5.23e-16] """ return ctx._unary_op(x, libgr.gr_sqrt, "sqrt($x)") def rsqrt(ctx, x): return ctx._unary_op(x, libgr.gr_rsqrt, "rsqrt($x)") def numerator(ctx, x): return ctx._unary_op(x, libgr.gr_numerator, "numerator($x)") def denominator(ctx, x): return ctx._unary_op(x, libgr.gr_denominator, "denominator($x)") def floor(ctx, x): return ctx._unary_op(x, libgr.gr_floor, "floor($x)") def ceil(ctx, x): return ctx._unary_op(x, libgr.gr_ceil, "ceil($x)") def trunc(ctx, x): return ctx._unary_op(x, libgr.gr_trunc, "trunc($x)") def nint(ctx, x): return ctx._unary_op(x, libgr.gr_nint, "nint($x)") def abs(ctx, x): return ctx._unary_op(x, libgr.gr_abs, "abs($x)") def conj(ctx, x): return ctx._unary_op(x, libgr.gr_conj, "conj($x)") def re(ctx, x): return ctx._unary_op(x, libgr.gr_re, "re($x)") def im(ctx, x): return ctx._unary_op(x, libgr.gr_im, "im($x)") def sgn(ctx, x): return ctx._unary_op(x, libgr.gr_sgn, "sgn($x)") def csgn(ctx, x): return ctx._unary_op(x, libgr.gr_csgn, "csgn($x)") def arg(ctx, x): return ctx._unary_op(x, libgr.gr_arg, "arg($x)") def inf(ctx): """ Positive infinity (for extended number sets which support it). >>> CF.inf() +inf >>> ComplexExtended_ca().inf() +Infinity >>> RR.inf() Traceback (most recent call last): ... FlintUnableError: failed to compute inf in {Real numbers (arb, prec = 53)} """ return ctx._constant(ctx, libgr.gr_pos_inf, "inf") def neg_inf(ctx): """ Negative infinity (for extended number sets which support it). >>> CF.neg_inf() -inf >>> ComplexExtended_ca().neg_inf() -Infinity >>> RR.neg_inf() Traceback (most recent call last): ... FlintUnableError: failed to compute neg_inf in {Real numbers (arb, prec = 53)} """ return ctx._constant(ctx, libgr.gr_neg_inf, "neg_inf") def uinf(ctx): """ Unsigned infinity (for extended number sets which support it). >>> CF.uinf() Traceback (most recent call last): ... FlintDomainError: uinf is not an element of {Complex floating-point numbers (acf, prec = 53)} >>> ComplexExtended_ca().uinf() UnsignedInfinity """ return ctx._constant(ctx, libgr.gr_uinf, "uinf") def undefined(ctx): """ Undefined value (for extended number sets which support it). >>> CF.undefined() (nan + nan*I) >>> ComplexExtended_ca().undefined() Undefined """ return ctx._constant(ctx, libgr.gr_undefined, "undefined") def unknown(ctx): """ Unknown value (for enclosures and other types which support it). >>> ComplexExtended_ca().unknown() Unknown """ return ctx._constant(ctx, libgr.gr_unknown, "unknown") def mul_2exp(ctx, x, y): return ctx._binary_op_fmpz(x, y, libgr.gr_mul_2exp_fmpz, "mul_2exp($x, $y)") def exp(ctx, x): """ Exponential function. >>> RR.exp(1) [2.718281828459045 +/- 5.41e-16] >>> RR(1).exp() [2.718281828459045 +/- 5.41e-16] Matrix exponentials: >>> MatRR.exp([[1,2],[3,4]]) [[[51.96895619870500 +/- 8.39e-15], [74.7365645670032 +/- 1.48e-14]], [[112.1048468505048 +/- 2.77e-14], [164.0738030492098 +/- 2.90e-14]]] >>> MatCC.exp([[1,2+1j],[3,4]]) [[([44.75490138773069 +/- 7.60e-15] + [36.14044247515163 +/- 7.33e-15]*I), ([58.81526453925295 +/- 7.84e-15] + [61.26937858302805 +/- 7.52e-15]*I)], [([107.3399445969204 +/- 3.89e-14] + [38.23409557608189 +/- 8.58e-15]*I), ([152.0948459846510 +/- 7.30e-14] + [74.3745380512335 +/- 2.88e-14]*I)]] >>> Mat(CC_ca)([[1,2],[0,3]]).exp() [[2.71828 {a where a = 2.71828 [Exp(1)]}, 17.3673 {b^3-b where a = 20.0855 [Exp(3)], b = 2.71828 [Exp(1)]}], [0, 20.0855 {a where a = 20.0855 [Exp(3)]}]] >>> Mat(CC_ca)([[1,2],[3,4]]).exp()[0,0] 51.9690 {(-a*c+11*a+b*c+11*b)/22 where a = 215.354 [Exp(5.37228 {(c+5)/2})], b = 0.689160 [Exp(-0.372281 {(-c+5)/2})], c = 5.74456 [c^2-33=0]} >>> Mat(CC_ca)([[0,0,1],[1,0,0],[0,1,0]]).exp().det() 1 >>> Mat(CC_ca)([[0,1,0,0,0],[0,0,2,0,0],[0,0,0,3,0],[0,0,0,0,4],[0,0,0,0,0]]).exp() [[1, 1, 1, 1, 1], [0, 1, 2, 3, 4], [0, 0, 1, 3, 6], [0, 0, 0, 1, 4], [0, 0, 0, 0, 1]] >>> MatQQ([[0,1,0,0,0],[0,0,2,0,0],[0,0,0,3,0],[0,0,0,0,4],[0,0,0,0,0]]).exp() [[1, 1, 1, 1, 1], [0, 1, 2, 3, 4], [0, 0, 1, 3, 6], [0, 0, 0, 1, 4], [0, 0, 0, 0, 1]] """ return ctx._unary_op(x, libgr.gr_exp, "exp($x)") def exp2(ctx, x): return ctx._unary_op(x, libgr.gr_exp2, "exp2($x)") def exp10(ctx, x): return ctx._unary_op(x, libgr.gr_exp10, "exp10($x)") def expm1(ctx, x): """ >>> RR.expm1(1) [1.718281828459045 +/- 3.19e-16] """ return ctx._unary_op(x, libgr.gr_expm1, "expm1($x)") def exp_pi_i(ctx, x): """ >>> QQbar.exp_pi_i(QQ(1) / 3) Root a = 0.500000 + 0.866025*I of a^2-a+1 >>> CC.exp_pi_i(QQ(1) / 3) ([0.500000000000000 +/- 3.94e-16] + [0.866025403784439 +/- 6.79e-16]*I) """ return ctx._unary_op(x, libgr.gr_exp_pi_i, "exp_pi_i($x)") def log(ctx, x): """ Natural logarithm: >>> QQ.log(1) 0 >>> QQ.log(2) Traceback (most recent call last): ... FlintUnableError: failed to compute log(x) in {Rational field (fmpq)} for {x = 2} >>> RR.log(2) [0.693147180559945 +/- 4.12e-16] >>> CC.log(1j) [1.570796326794897 +/- 5.54e-16]*I Matrix logarithms: >>> Mat(CC_ca)([[4,2],[2,4]]).log().det() == CC_ca.log(2)*CC_ca.log(6) True >>> Mat(QQ)([[1,1],[0,1]]).log() [[0, 1], [0, 0]] >>> Mat(QQ)([[0,1],[0,0]]).log() Traceback (most recent call last): ... FlintDomainError: log(x) is not an element of {Matrices (any shape) over Rational field (fmpq)} for {x = [[0, 1], [0, 0]]} >>> Mat(CC_ca)([[0,1],[0,0]]).log() Traceback (most recent call last): ... FlintDomainError: log(x) is not an element of {Matrices (any shape) over Complex numbers (ca)} for {x = [[0, 1], [0, 0]]} >>> Mat(CC_ca)([[0,0,1],[0,1,0],[1,0,0]]).log() / (CC_ca.pi() * CC_ca.i()) [[0.500000 {1/2}, 0, -0.500000 {-1/2}], [0, 0, 0], [-0.500000 {-1/2}, 0, 0.500000 {1/2}]] >>> Mat(CC_ca)([[0,0,1],[0,1,0],[1,0,0]]).log().exp() [[0, 0, 1], [0, 1, 0], [1, 0, 0]] """ return ctx._unary_op(x, libgr.gr_log, "log($x)") def log1p(ctx, x): """ >>> RR.log1p(1) [0.693147180559945 +/- 4.12e-16] >>> CC.log1p(1j) ([0.346573590279973 +/- 4.20e-16] + [0.7853981633974483 +/- 7.66e-17]*I) """ return ctx._unary_op(x, libgr.gr_log1p, "log1p($x)") def log_pi_i(ctx, x): """ >>> QQbar.log_pi_i(-1j) -1/2 >>> CC.log_pi_i(1j) [0.5000000000000000 +/- 7.07e-17] """ return ctx._unary_op(x, libgr.gr_log_pi_i, "log_pi_i($x)") def log2(ctx, x): """ >>> RR.log2(16) [4.00000000000000 +/- 1.45e-15] """ return ctx._unary_op(x, libgr.gr_log2, "log2($x)") def log10(ctx, x): """ >>> RR.log10(100) [2.000000000000000 +/- 7.72e-16] """ return ctx._unary_op(x, libgr.gr_log10, "log10($x)") def sin(ctx, x): """ >>> QQ.sin(0) 0 >>> QQ.sin(1) Traceback (most recent call last): ... FlintUnableError: failed to compute sin(x) in {Rational field (fmpq)} for {x = 1} >>> RR.sin(1) [0.841470984807897 +/- 6.08e-16] """ return ctx._unary_op(x, libgr.gr_sin, "sin($x)") def cos(ctx, x): """ >>> QQ.cos(0) 1 >>> QQ.cos(1) Traceback (most recent call last): ... FlintUnableError: failed to compute cos(x) in {Rational field (fmpq)} for {x = 1} >>> RR.cos(1) [0.540302305868140 +/- 4.59e-16] """ return ctx._unary_op(x, libgr.gr_cos, "cos($x)") def sin_cos(ctx, x): """ >>> RR.sin_cos(1) ([0.841470984807897 +/- 6.08e-16], [0.540302305868140 +/- 4.59e-16]) """ return ctx._unary_unary_op(x, libgr.gr_sin_cos, "sin_cos($x)") def tan(ctx, x): """ >>> RR.tan(1) [1.557407724654902 +/- 3.26e-16] >>> CC.tan(1+1j) ([0.2717525853195117 +/- 9.11e-17] + [1.083923327338694 +/- 5.77e-16]*I) >>> x = RRser.gen(); RRser.tan(x) x + [0.333333333333333 +/- 3.99e-16]*x^3 + [0.1333333333333333 +/- 8.32e-17]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_tan, "tan($x)") def cot(ctx, x): """ >>> RR.cot(1) [0.642092615934331 +/- 4.79e-16] """ return ctx._unary_op(x, libgr.gr_cot, "cot($x)") def sec(ctx, x): """ >>> RR.sec(1) [1.850815717680925 +/- 7.00e-16] """ return ctx._unary_op(x, libgr.gr_sec, "sec($x)") def csc(ctx, x): """ >>> RR.csc(1) [1.188395105778121 +/- 2.52e-16] """ return ctx._unary_op(x, libgr.gr_csc, "csc($x)") def sin_pi(ctx, x): """ >>> QQbar.sin_pi(QQ(1) / 3) Root a = 0.866025 of 4*a^2-3 """ return ctx._unary_op(x, libgr.gr_sin_pi, "sin_pi($x)") def cos_pi(ctx, x): """ >>> QQbar.cos_pi(QQ(1) / 3) 1/2 """ return ctx._unary_op(x, libgr.gr_cos_pi, "cos_pi($x)") def sin_cos_pi(ctx, x): return ctx._unary_unary_op(x, libgr.gr_sin_cos_pi, "sin_cos_pi($x)") def tan_pi(ctx, x): """ >>> QQbar.tan_pi(QQ(1) / 3) Root a = 1.73205 of a^2-3 """ return ctx._unary_op(x, libgr.gr_tan_pi, "tan_pi($x)") def cot_pi(ctx, x): """ >>> QQbar.cot_pi(QQ(1) / 3) Root a = 0.577350 of 3*a^2-1 """ return ctx._unary_op(x, libgr.gr_cot_pi, "cot_pi($x)") def sec_pi(ctx, x): """ >>> QQbar.sec_pi(QQ(1) / 3) 2 """ return ctx._unary_op(x, libgr.gr_sec_pi, "sec_pi($x)") def csc_pi(ctx, x): """ >>> QQbar.csc_pi(QQ(1) / 3) Root a = 1.15470 of 3*a^2-4 """ return ctx._unary_op(x, libgr.gr_csc_pi, "csc_pi($x)") def sinc(ctx, x): """ >>> RR.sinc(2) [0.4546487134128408 +/- 7.07e-17] >>> CC.sinc(1j) [1.175201193643801 +/- 6.61e-16] """ return ctx._unary_op(x, libgr.gr_sinc, "sinc($x)") def sinc_pi(ctx, x): """ >>> RR.sinc_pi(0.5) [0.636619772367581 +/- 4.04e-16] >>> CC.sinc_pi(1j) [3.67607791037498 +/- 3.11e-15] """ return ctx._unary_op(x, libgr.gr_sinc_pi, "sinc_pi($x)") def sinh(ctx, x): """ >>> RR.sinh(1) [1.175201193643801 +/- 6.18e-16] >>> CC.sinh(1+1j) ([0.634963914784736 +/- 4.68e-16] + [1.298457581415977 +/- 7.11e-16]*I) """ return ctx._unary_op(x, libgr.gr_sinh, "sinh($x)") def cosh(ctx, x): """ >>> RR.cosh(1) [1.543080634815244 +/- 5.28e-16] >>> CC.cosh(1+1j) ([0.833730025131149 +/- 5.04e-16] + [0.988897705762865 +/- 4.92e-16]*I) """ return ctx._unary_op(x, libgr.gr_cosh, "cosh($x)") def sinh_cosh(ctx, x): """ >>> RR.sinh_cosh(1) ([1.175201193643801 +/- 6.18e-16], [1.543080634815244 +/- 5.28e-16]) >>> CC.sinh_cosh(1j) ([0.841470984807897 +/- 6.08e-16]*I, [0.540302305868140 +/- 4.59e-16]) """ return ctx._unary_unary_op(x, libgr.gr_sinh_cosh, "sinh_cos($x)") def tanh(ctx, x): """ >>> RR.tanh(1) [0.761594155955765 +/- 2.81e-16] >>> CC.tanh(1+1j) ([1.083923327338694 +/- 5.77e-16] + [0.2717525853195117 +/- 9.11e-17]*I) """ return ctx._unary_op(x, libgr.gr_tanh, "tanh($x)") def coth(ctx, x): """ >>> RR.coth(1) [1.313035285499331 +/- 4.97e-16] >>> CC.coth(1+1j) ([0.868014142895925 +/- 1.88e-16] + [-0.2176215618544027 +/- 9.31e-17]*I) """ return ctx._unary_op(x, libgr.gr_coth, "coth($x)") def sech(ctx, x): """ >>> RR.sech(1) [0.648054273663885 +/- 4.67e-16] """ return ctx._unary_op(x, libgr.gr_sech, "sech($x)") def csch(ctx, x): """ >>> RR.csch(1) [0.850918128239321 +/- 5.70e-16] """ return ctx._unary_op(x, libgr.gr_csch, "csch($x)") def asin(ctx, x): """ >>> RR.asin(0.5) [0.523598775598299 +/- 3.79e-16] >>> CC.asin(1+1j) ([0.66623943249252 +/- 5.40e-15] + [1.06127506190504 +/- 5.04e-15]*I) >>> x = RRser.gen(); RRser.asin(x) x + [0.1666666666666667 +/- 7.04e-17]*x^3 + [0.0750000000000000 +/- 1.67e-17]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_asin, "asin($x)") def acos(ctx, x): """ >>> RR.acos(0.5) [1.047197551196598 +/- 8.97e-16] >>> CC.acos(1+1j) ([0.90455689430238 +/- 2.07e-15] + [-1.06127506190504 +/- 5.04e-15]*I) >>> x = RRser.gen(); RRser.acos(x) [1.570796326794897 +/- 5.54e-16] - x + [-0.1666666666666667 +/- 7.04e-17]*x^3 + [-0.0750000000000000 +/- 1.67e-17]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_acos, "acos($x)") def atan(ctx, x): """ Inverse tangent. >>> QQ.atan(0) 0 >>> RR.atan(1) [0.7853981633974483 +/- 7.66e-17] >>> RR_ca.atan(1) 0.785398 {(a)/4 where a = 3.14159 [Pi]} >>> CC.atan(0.5j) [0.549306144334055 +/- 3.32e-16]*I >>> CC.atan(1j) Traceback (most recent call last): ... FlintDomainError: atan(x) is not an element of {Complex numbers (acb, prec = 53)} for {x = 1.000000000000000*I} >>> x = RRser.gen(); RRser.atan(x) x + [-0.3333333333333333 +/- 7.04e-17]*x^3 + [0.2000000000000000 +/- 4.45e-17]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_atan, "atan($x)") def atan2(ctx, y, x): """ >>> RR.atan2(1,2) [0.4636476090008061 +/- 6.22e-17] """ return ctx._binary_op(y, x, libgr.gr_atan2, "atan2($y, $x)") def acot(ctx, x): """ >>> RR.acot(2) [0.4636476090008061 +/- 6.22e-17] >>> CC.acot(1+1j) ([0.553574358897045 +/- 5.74e-16] + [-0.402359478108525 +/- 4.46e-16]*I) >>> x = RRser.gen(); RRser.acot(1+x) [0.7853981633974483 +/- 7.66e-17] - 0.5000000000000000*x + 0.2500000000000000*x^2 + [-0.0833333333333333 +/- 4.26e-17]*x^3 + [0.02500000000000000 +/- 5.56e-18]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_acot, "acot($x)") def asec(ctx, x): """ >>> RR.asec(2) [1.047197551196598 +/- 8.97e-16] >>> CC.asec(1+1j) ([1.118517879643706 +/- 7.12e-16] + [0.530637530952518 +/- 6.32e-16]*I) """ return ctx._unary_op(x, libgr.gr_asec, "asec($x)") def acsc(ctx, x): """ >>> RR.acsc(2) [0.523598775598299 +/- 3.79e-16] >>> CC.acsc(1+1j) ([0.452278447151191 +/- 5.95e-16] + [-0.530637530952518 +/- 6.32e-16]*I) """ return ctx._unary_op(x, libgr.gr_acsc, "acsc($x)") def asin_pi(ctx, x): """ >>> QQbar.asin_pi(QQ(1) / 2) 1/6 """ return ctx._unary_op(x, libgr.gr_asin_pi, "asin_pi($x)") def acos_pi(ctx, x): """ >>> QQbar.acos_pi(QQ(1) / 2) 1/3 """ return ctx._unary_op(x, libgr.gr_acos_pi, "acos_pi($x)") def atan_pi(ctx, x): """ >>> QQbar.atan_pi(QQbar(2).sqrt() - 1) 1/8 """ return ctx._unary_op(x, libgr.gr_atan_pi, "atan_pi($x)") def acot_pi(ctx, x): """ >>> QQbar.acot_pi(QQbar(2).sqrt() - 1) 3/8 """ return ctx._unary_op(x, libgr.gr_acot_pi, "acot_pi($x)") def asec_pi(ctx, x): """ >>> QQbar.asec_pi(2) 1/3 """ return ctx._unary_op(x, libgr.gr_asec_pi, "asec_pi($x)") def acsc_pi(ctx, x): """ >>> QQbar.acsc_pi(2) 1/6 """ return ctx._unary_op(x, libgr.gr_acsc_pi, "acsc_pi($x)") def asinh(ctx, x): """ >>> RR.asinh(1) [0.881373587019543 +/- 1.87e-16] >>> CC.asinh(1+1j) ([1.06127506190504 +/- 5.04e-15] + [0.66623943249252 +/- 5.40e-15]*I) >>> x = RRser.gen(); RRser.asinh(x) x + [-0.1666666666666667 +/- 7.04e-17]*x^3 + [0.0750000000000000 +/- 1.67e-17]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_asinh, "asinh($x)") def acosh(ctx, x): """ >>> RR.acosh(2) [1.316957896924817 +/- 6.61e-16] >>> CC.acosh(1+1j) ([1.061275061905035 +/- 8.44e-16] + [0.904556894302381 +/- 8.22e-16]*I) >>> x = RRser.gen(); RRser.acosh(2+x) [1.316957896924817 +/- 6.61e-16] + [0.577350269189626 +/- 4.54e-16]*x + [-0.192450089729875 +/- 4.24e-16]*x^2 + [0.096225044864938 +/- 6.92e-16]*x^3 + [-0.058804194084128 +/- 7.16e-16]*x^4 + [0.040450157748779 +/- 4.91e-16]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_acosh, "acosh($x)") def atanh(ctx, x): """ >>> RR.atanh(0.5) [0.549306144334055 +/- 3.32e-16] >>> CC.atanh(1+1j) ([0.4023594781085251 +/- 8.52e-17] + [1.017221967897851 +/- 4.37e-16]*I) >>> x = RRser.gen(); RRser.atanh(x) x + [0.3333333333333333 +/- 7.04e-17]*x^3 + [0.2000000000000000 +/- 4.45e-17]*x^5 + O(x^6) """ return ctx._unary_op(x, libgr.gr_atanh, "atanh($x)") def acoth(ctx, x): """ >>> RR.acoth(2) [0.549306144334055 +/- 3.32e-16] >>> CC.acoth(1+1j) ([0.4023594781085251 +/- 8.52e-17] + [-0.553574358897045 +/- 3.16e-16]*I) """ return ctx._unary_op(x, libgr.gr_acoth, "acoth($x)") def asech(ctx, x): """ >>> RR.asech(0.5) [1.316957896924817 +/- 6.61e-16] >>> CC.asech(1+1j) ([0.530637530952518 +/- 9.50e-16] + [-1.118517879643706 +/- 9.45e-16]*I) """ return ctx._unary_op(x, libgr.gr_asech, "asech($x)") def acsch(ctx, x): """ >>> RR.acsch(0.5) [1.443635475178810 +/- 5.32e-16] >>> CC.acsch(1+1j) ([0.530637530952518 +/- 5.66e-16] + [-0.452278447151191 +/- 7.14e-16]*I) """ return ctx._unary_op(x, libgr.gr_acsch, "acsch($x)") def erf(ctx, x): """ >>> RR.erf(1) [0.842700792949715 +/- 3.28e-16] """ return ctx._unary_op(x, libgr.gr_erf, "erf($x)") def erfc(ctx, x): """ >>> RR.erfc(1) [0.1572992070502851 +/- 3.71e-17] """ return ctx._unary_op(x, libgr.gr_erfc, "erfc($x)") def erfi(ctx, x): """ >>> RR.erfi(1) [1.650425758797543 +/- 4.58e-16] """ return ctx._unary_op(x, libgr.gr_erfi, "erfi($x)") def erfcx(ctx, x): """ >>> RR.erfcx(100) [0.00564161378298943 +/- 3.69e-18] """ return ctx._unary_op(x, libgr.gr_erfcx, "erfcx($x)") def erfinv(ctx, x): """ >>> RR.erfinv(0.5) [0.4769362762044698 +/- 7.79e-17] """ return ctx._unary_op(x, libgr.gr_erfinv, "erfinv($x)") def erfcinv(ctx, x): """ >>> RR.erfc(RR.erfcinv(0.25)) [0.250000000000000 +/- 1.24e-16] """ return ctx._unary_op(x, libgr.gr_erfcinv, "erfcinv($x)") def fresnel_s(ctx, x, normalized=False): """ >>> RR.fresnel_s(1) [0.3102683017233811 +/- 2.67e-18] >>> RR.fresnel_s(1, normalized=True) [0.4382591473903548 +/- 9.24e-17] """ return ctx._unary_op_with_flag(x, normalized, libgr.gr_fresnel_s, "fresnel_s($x)") def fresnel_c(ctx, x, normalized=False): """ >>> RR.fresnel_c(1) [0.904524237900272 +/- 1.46e-16] >>> RR.fresnel_c(1, normalized=True) [0.779893400376823 +/- 3.59e-16] """ return ctx._unary_op_with_flag(x, normalized, libgr.gr_fresnel_c, "fresnel_c($x)") def fresnel(ctx, x, normalized=False): """ >>> RR.fresnel(1) ([0.3102683017233811 +/- 2.67e-18], [0.904524237900272 +/- 1.46e-16]) >>> RR.fresnel(1, normalized=True) ([0.4382591473903548 +/- 9.24e-17], [0.779893400376823 +/- 3.59e-16]) """ return ctx._unary_unary_op_with_flag(x, normalized, libgr.gr_fresnel, "fresnel($x)") def gamma_upper(ctx, x, y, regularized=0): """ >>> RR.gamma_upper(3, 4) [0.476206611107089 +/- 5.30e-16] >>> RR.gamma_upper(3, 4, regularized=True) [0.2381033055535443 +/- 8.24e-17] """ return ctx._binary_op_with_flag(x, y, regularized, libgr.gr_gamma_upper, "gamma_upper($x, $y)") def gamma_lower(ctx, x, y, regularized=0): """ >>> RR.gamma_lower(3, 4) [1.52379338889291 +/- 2.89e-15] >>> RR.gamma_lower(3, 4, regularized=True) [0.76189669444646 +/- 6.52e-15] """ return ctx._binary_op_with_flag(x, y, regularized, libgr.gr_gamma_lower, "gamma_lower($x, $y)") def beta_lower(ctx, a, b, x, regularized=0): """ >>> RR.beta_lower(2, 3, 0.5) [0.0572916666666667 +/- 6.08e-17] >>> RR.beta_lower(2, 3, 0.5, regularized=True) [0.687500000000000 +/- 5.24e-16] """ return ctx._ternary_op_with_flag(a, b, x, regularized, libgr.gr_beta_lower, "beta_lower($a, $b, $x)") def exp_integral(ctx, x, y): """ >>> RR.exp_integral(1, 2) [0.04890051070806 +/- 2.63e-15] """ return ctx._binary_op(x, y, libgr.gr_exp_integral, "exp_integral($x, $y)") def exp_integral_ei(ctx, x): """ >>> RR.exp_integral_ei(1) [1.89511781635594 +/- 5.11e-15] """ return ctx._unary_op(x, libgr.gr_exp_integral_ei, "exp_integral_ei($x)") def sin_integral(ctx, x): """ >>> RR.sin_integral(1) [0.946083070367183 +/- 1.35e-16] """ return ctx._unary_op(x, libgr.gr_sin_integral, "sin_integral($x)") def cos_integral(ctx, x): """ >>> RR.cos_integral(1) [0.3374039229009681 +/- 5.63e-17] """ return ctx._unary_op(x, libgr.gr_cos_integral, "cos_integral($x)") def sinh_integral(ctx, x): """ >>> RR.sinh_integral(1) [1.05725087537573 +/- 2.77e-15] """ return ctx._unary_op(x, libgr.gr_sinh_integral, "sinh_integral($x)") def cosh_integral(ctx, x): """ >>> RR.cosh_integral(1) [0.837866940980208 +/- 4.78e-16] """ return ctx._unary_op(x, libgr.gr_cosh_integral, "cosh_integral($x)") def log_integral(ctx, x, offset=False): """ >>> RR.log_integral(2) [1.04516378011749 +/- 4.01e-15] >>> RR.log_integral(2, offset=True) 0 """ return ctx._unary_op_with_flag(x, offset, libgr.gr_log_integral, "log_integral($x)") def dilog(ctx, x): """ >>> RR.dilog(1) [1.644934066848226 +/- 6.45e-16] """ return ctx._unary_op(x, libgr.gr_dilog, "dilog($x)") def bessel_j(ctx, x, y): """ >>> RR.bessel_j(2, 3) [0.486091260585891 +/- 4.75e-16] """ return ctx._binary_op(x, y, libgr.gr_bessel_j, "bessel_j($n, $x)") def bessel_y(ctx, x, y): """ >>> RR.bessel_y(2, 3) [-0.16040039348492 +/- 5.80e-15] """ return ctx._binary_op(x, y, libgr.gr_bessel_y, "bessel_y($n, $x)") def bessel_i(ctx, x, y, scaled=False): """ >>> RR.bessel_i(2, 3) [2.24521244092995 +/- 1.88e-15] >>> RR.bessel_i(2, 3, scaled=True) [0.111782545296958 +/- 2.09e-16] """ if scaled: return ctx._binary_op(x, y, libgr.gr_bessel_i_scaled, "bessel_i($n, $x, scaled=True)") else: return ctx._binary_op(x, y, libgr.gr_bessel_i, "bessel_i($n, $x)") def bessel_k(ctx, x, y, scaled=False): """ >>> RR.bessel_k(2, 3) [0.06151045847174 +/- 8.87e-15] >>> RR.bessel_k(2, 3, scaled=True) [1.235470584796 +/- 5.14e-13] """ if scaled: return ctx._binary_op(x, y, libgr.gr_bessel_k_scaled, "bessel_k($n, $x, scaled=True)") else: return ctx._binary_op(x, y, libgr.gr_bessel_k, "bessel_k($n, $x)") def bessel_j_y(ctx, x, y): """ >>> RR.bessel_j_y(1, 1) ([0.4400505857449335 +/- 5.91e-17], [-0.78121282130029 +/- 4.55e-15]) >>> CC.bessel_j_y(1, 1j) ([0.565159103992485 +/- 1.89e-16]*I, ([-0.56515910399248 +/- 8.81e-15] + [0.38318604387456 +/- 8.19e-15]*I)) """ return ctx._binary_binary_op(x, y, libgr.gr_bessel_j_y, "bessel_j_y($n, $x)") def airy(ctx, x): """ >>> RR.airy(1) ([0.1352924163128814 +/- 4.17e-17], [-0.1591474412967932 +/- 2.95e-17], [1.207423594952871 +/- 3.27e-16], [0.932435933392776 +/- 5.83e-16]) >>> CC.airy(1) ([0.1352924163128814 +/- 4.17e-17], [-0.1591474412967932 +/- 2.95e-17], [1.207423594952871 +/- 3.27e-16], [0.932435933392776 +/- 5.83e-16]) """ return ctx._quaternary_unary_op(x, libgr.gr_airy, "airy($x)") def airy_ai(ctx, x): """ >>> RR.airy_ai(1) [0.1352924163128814 +/- 4.17e-17] """ return ctx._unary_op(x, libgr.gr_airy_ai, "airy_ai($x)") def airy_bi(ctx, x): """ >>> RR.airy_bi(1) [1.207423594952871 +/- 3.27e-16] """ return ctx._unary_op(x, libgr.gr_airy_bi, "airy_bi($x)") def airy_ai_prime(ctx, x): """ >>> RR.airy_ai_prime(1) [-0.1591474412967932 +/- 2.95e-17] """ return ctx._unary_op(x, libgr.gr_airy_ai_prime, "airy_ai_prime($x)") def airy_bi_prime(ctx, x): """ >>> RR.airy_bi_prime(1) [0.932435933392776 +/- 5.83e-16] """ return ctx._unary_op(x, libgr.gr_airy_bi_prime, "airy_bi_prime($x)") def airy_ai_zero(ctx, n): """ >>> RR.airy_ai(RR.airy_ai_zero(1)) [+/- 3.51e-16] """ return ctx._unary_op_fmpz(n, libgr.gr_airy_ai_zero, "airy_ai_zero($n)") def airy_bi_zero(ctx, n): """ >>> RR.airy_bi(RR.airy_bi_zero(1)) [+/- 2.08e-16] """ return ctx._unary_op_fmpz(n, libgr.gr_airy_bi_zero, "airy_bi_zero($n)") def airy_ai_prime_zero(ctx, n): """ >>> RR.airy_ai_prime(RR.airy_ai_prime_zero(1)) [+/- 1.44e-16] """ return ctx._unary_op_fmpz(n, libgr.gr_airy_ai_prime_zero, "airy_ai_prime_zero($n)") def airy_bi_prime_zero(ctx, n): """ >>> RR.airy_bi_prime(RR.airy_bi_prime_zero(1)) [+/- 6.18e-16] """ return ctx._unary_op_fmpz(n, libgr.gr_airy_bi_prime_zero, "airy_bi_prime_zero($n)") # todo: coulomb() def coulomb_f(ctx, x, y, z): """ >>> CC.coulomb_f(2, 3, 4) [0.101631502833431 +/- 8.03e-16] """ return ctx._ternary_op(x, y, z, libgr.gr_coulomb_f, "coulomb_f($x)") def coulomb_g(ctx, x, y, z): """ >>> CC.coulomb_g(2, 3, 4) [5.371722466 +/- 6.15e-10] """ return ctx._ternary_op(x, y, z, libgr.gr_coulomb_g, "coulomb_g($x)") def coulomb_hpos(ctx, x, y, z): """ >>> CC.coulomb_hpos(2, 3, 4) ([5.371722466 +/- 6.15e-10] + [0.101631502833431 +/- 8.03e-16]*I) """ return ctx._ternary_op(x, y, z, libgr.gr_coulomb_hpos, "coulomb_hpos($x)") def coulomb_hneg(ctx, x, y, z): """ >>> CC.coulomb_hneg(2, 3, 4) ([5.371722466 +/- 6.15e-10] + [-0.101631502833431 +/- 8.03e-16]*I) """ return ctx._ternary_op(x, y, z, libgr.gr_coulomb_hneg, "coulomb_hneg($x)") def chebyshev_t(ctx, n, x): """ Chebyshev polynomial of the first kind. >>> [ZZ.chebyshev_t(n, 2) for n in range(5)] [1, 2, 7, 26, 97] >>> RR.chebyshev_t(0.5, 0.75) [0.935414346693485 +/- 5.18e-16] >>> ZZx.chebyshev_t(4, [0, 1]) 8*x^4-8*x^2+1 """ return ctx._binary_op_with_overloads(n, x, libgr.gr_chebyshev_t, fmpz_op=libgr.gr_chebyshev_t_fmpz, rstr="chebyshev_t($n, $x)") def chebyshev_u(ctx, n, x): """ Chebyshev polynomial of the second kind. >>> [ZZ.chebyshev_u(n, 2) for n in range(5)] [1, 4, 15, 56, 209] >>> RR.chebyshev_u(0.5, 0.75) [1.33630620956212 +/- 2.68e-15] >>> ZZx.chebyshev_u(4, [0, 1]) 16*x^4-12*x^2+1 """ return ctx._binary_op_with_overloads(n, x, libgr.gr_chebyshev_u, fmpz_op=libgr.gr_chebyshev_u_fmpz, rstr="chebyshev_u($n, $x)") def jacobi_p(ctx, n, a, b, x): """ Jacobi polynomial. >>> RR.jacobi_p(3, 1, 2, 4) [602.500000000000 +/- 3.28e-13] """ return ctx._quaternary_op(n, a, b, x, libgr.gr_jacobi_p, rstr="jacobi_p($n, $a, $b, $x)") def gegenbauer_c(ctx, n, m, x): """ Gegenbauer polynomial. >>> RR.gegenbauer_c(3, 2, 4) [2000.00000000000 +/- 3.60e-12] """ return ctx._ternary_op(n, m, x, libgr.gr_gegenbauer_c, rstr="gegenbauer_c($n, $m, $x)") def laguerre_l(ctx, n, m, x): """ Associated Laguerre polynomial (or Laguerre function). >>> RR.laguerre_l(3, 2, 4) [-0.66666666666667 +/- 5.71e-15] """ return ctx._ternary_op(n, m, x, libgr.gr_laguerre_l, rstr="laguerre_l($n, $m, $x)") def hermite_h(ctx, n, x): """ Hermite polynomial (Hermite function). >>> RR.hermite_h(3, 4) 464.0000000000000 """ return ctx._binary_op(n, x, libgr.gr_hermite_h, rstr="hermite_h($n, $x)") def legendre_p(ctx, n, m, x, typ=0): """ Associated Legendre function of the first kind. >>> RR.legendre_p(3, 1, 0.5) [-0.324759526419164 +/- 5.23e-16] >>> CC.legendre_p(3, 1, 0.5) [-0.324759526419164 +/- 5.23e-16] >>> CC.legendre_p(3, 1, 0.5, 1) [0.324759526419164 +/- 5.52e-16]*I """ assert typ in (0, 1) return ctx._ternary_op_with_flag(n, m, x, typ, libgr.gr_legendre_p, rstr="legendre_p($n, $m, $x, $typ)") def legendre_q(ctx, n, m, x, typ=0): """ Associated Legendre function of the second kind. >>> RR.legendre_q(3, 1, 0.5) [2.4918525917090 +/- 5.45e-14] >>> CC.legendre_q(3, 1, 0.5) [2.4918525917090 +/- 5.45e-14] >>> CC.legendre_q(3, 1, 0.5, 1) ([0.51013107119087 +/- 4.02e-15] + [-2.4918525917090 +/- 5.73e-14]*I) """ assert typ in (0, 1) return ctx._ternary_op_with_flag(n, m, x, typ, libgr.gr_legendre_q, rstr="legendre_q($n, $m, $x, $typ)") def spherical_y(ctx, n, m, theta, phi): """ Spherical harmonic. >>> CC.spherical_y(4, 3, 0.5, 0.75) ([0.076036396941350 +/- 2.18e-16] + [-0.094180781089734 +/- 4.96e-16]*I) """ n = ctx._as_si(n) m = ctx._as_si(m) theta = ctx._as_elem(theta) phi = ctx._as_elem(phi) res = ctx._elem_type(context=ctx) status = libgr.gr_spherical_y_si(res._ref, n, m, theta._ref, phi._ref, ctx._ref) if status: _handle_error(ctx, status, "spherical_y($n, $m, $theta, $phi)", n, m, theta, phi) return res def legendre_p_root(ctx, n, k, weight=False): """ Root of Legendre polynomial. With weight=True, also returns the corresponding weight for Gauss-Legendre quadrature. >>> RR.legendre_p_root(5, 1) [0.538469310105683 +/- 1.15e-16] >>> RR.legendre_p(5, 0, RR.legendre_p_root(5, 1)) [+/- 8.15e-16] >>> RR.legendre_p_root(5, 1, weight=True) ([0.538469310105683 +/- 1.15e-16], [0.4786286704993664 +/- 7.10e-17]) """ n = ctx._as_si(n) k = ctx._as_si(k) if weight: res1 = ctx._elem_type(context=ctx) res2 = ctx._elem_type(context=ctx) status = libgr.gr_legendre_p_root_ui(res1._ref, res2._ref, n, k, ctx._ref) else: res1 = ctx._elem_type(context=ctx) res2 = None status = libgr.gr_legendre_p_root_ui(res1._ref, res2, n, k, ctx._ref) if status: _handle_error(ctx, status, "legendre_p_root($n, $k)", n, k) if weight: return (res1, res2) else: return res1 def hypgeom_0f1(ctx, a, z, regularized=False): """ Hypergeometric function 0F1, optionally regularized. >>> RR.hypgeom_0f1(3, 4) [3.21109468764205 +/- 5.00e-15] >>> RR.hypgeom_0f1(3, 4, regularized=True) [1.60554734382103 +/- 5.20e-15] >>> CC.hypgeom_0f1(1, 2+2j) ([2.435598449671389 +/- 7.27e-16] + [4.43452765355337 +/- 4.91e-15]*I) """ flags = int(regularized) return ctx._binary_op_with_flag(a, z, flags, libgr.gr_hypgeom_0f1, rstr="hypgeom_0f1($a, $x)") def hypgeom_1f1(ctx, a, b, z, regularized=False): """ Hypergeometric function 1F1, optionally regularized. >>> RR.hypgeom_1f1(3, 4, 5) [60.504568913851 +/- 3.82e-13] >>> RR.hypgeom_1f1(3, 4, 5, regularized=True) [10.0840948189752 +/- 3.31e-14] """ flags = int(regularized) return ctx._ternary_op_with_flag(a, b, z, flags, libgr.gr_hypgeom_1f1, rstr="hypgeom_1f1($a, $b, $x)") def hypgeom_u(ctx, a, b, z): """ Hypergeometric function U. >>> RR.hypgeom_u(1, 2, 3) [0.3333333333333333 +/- 7.04e-17] """ flags = 0 return ctx._ternary_op_with_flag(a, b, z, flags, libgr.gr_hypgeom_u, rstr="hypgeom_u($a, $b, $x)") def hypgeom_2f1(ctx, a, b, c, z, regularized=False): """ Hypergeometric function 2F1, optionally regularized. >>> RR.hypgeom_2f1(1, 2, 3, -4) [0.29882026094574 +/- 8.48e-15] >>> RR.hypgeom_2f1(1, 2, 3, -4, regularized=True) [0.14941013047287 +/- 4.24e-15] """ flags = int(regularized) return ctx._quaternary_op_with_flag(a, b, c, z, flags, libgr.gr_hypgeom_2f1, rstr="hypgeom_2f1($a, $b, $c, $x)") def hypgeom_pfq(ctx, a, b, z, regularized=False): """ Generalized hypergeometric function, optionally regularized. >>> RR.hypgeom_pfq([1,2], [3,4], 0.5) [1.09002619782383 +/- 4.32e-15] >>> RR.hypgeom_pfq([1, 2], [3, 4], 0.5, regularized=True) [0.090835516485319 +/- 2.36e-16] >>> CC.hypgeom_pfq([1,2], [3,4], 0.5+0.5j) ([1.08239550393928 +/- 2.16e-15] + [0.096660812453003 +/- 5.55e-16]*I) >>> x = CCser.gen() >>> CCser.hypgeom_pfq([1, 2+x], [3+x], CC(-0.5)+x) [0.75627913513468 +/- 8.06e-15] + [0.32390309682858 +/- 8.68e-15]*x + [0.2403726319128 +/- 9.25e-14]*x^2 + [0.11701345954 +/- 2.11e-12]*x^3 + [0.0806045925 +/- 6.82e-11]*x^4 + [0.043967479 +/- 9.09e-10]*x^5 + O(x^6) >>> CCser.hypgeom_pfq([2+x], [3+x], CC(-0.5)+x) [0.72163208344840 +/- 3.62e-15] + [0.41823982602421 +/- 4.49e-15]*x + [0.24476273640228 +/- 2.45e-15]*x^2 + [0.0532046593049 +/- 2.33e-14]*x^3 + [0.021808666094 +/- 4.11e-13]*x^4 + [0.000742930119 +/- 5.65e-13]*x^5 + O(x^6) """ a = ctx._as_vec(a) b = ctx._as_vec(b) z = ctx._as_elem(z) res = ctx._elem_type(context=ctx) flags = int(regularized) status = libgr.gr_hypgeom_pfq(res._ref, a._ref, b._ref, z._ref, flags, ctx._ref) if status: _handle_error(ctx, status, "hypgeom_pfq($a, $b, $x)", a, b, z) return res def fac(ctx, x): """ Factorial. >>> ZZ.fac(10) 3628800 >>> ZZ.fac(-1) Traceback (most recent call last): ... FlintDomainError: fac(x) is not an element of {Integer ring (fmpz)} for {x = -1} Real and complex factorials extend using the gamma function: >>> RR.fac(10**20) [1.93284951431010e+1956570551809674817245 +/- 3.03e+1956570551809674817230] >>> RR.fac(0.5) [0.886226925452758 +/- 1.78e-16] >>> CC.fac(1+1j) ([0.652965496420167 +/- 6.21e-16] + [0.343065839816545 +/- 5.38e-16]*I) Factorials mod N: >>> ZZmod(10**7 + 19).fac(10**7) 2343096 More tests: >>> RF.fac(10**6) 8.263931688331239e+5565708 >>> RF.fac(10**20) 1.932849514310098e+1956570551809674817245 """ return ctx._unary_op_with_fmpz_fmpq_overloads(x, libgr.gr_fac, op_fmpz=libgr.gr_fac_fmpz, rstr="fac($x)") def fac_vec(ctx, length): """ Vector of factorials. >>> ZZ.fac_vec(10) [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] >>> QQ.fac_vec(10) / 3 [1/3, 1/3, 2/3, 2, 8, 40, 240, 1680, 13440, 120960] >>> ZZmod(7).fac_vec(10) [1, 1, 2, 6, 3, 1, 6, 0, 0, 0] >>> sum(RR.fac_vec(100)) [9.427862397658e+155 +/- 3.19e+142] """ return ctx._op_vec_len(length, libgr.gr_fac_vec, "fac_vec($length)") def rfac(ctx, x): """ Reciprocal factorial. >>> QQ.rfac(5) 1/120 >>> ZZ.rfac(-2) 0 >>> ZZ.rfac(2) Traceback (most recent call last): ... FlintDomainError: rfac(x) is not an element of {Integer ring (fmpz)} for {x = 2} >>> RR.rfac(0.5) [1.128379167095513 +/- 7.02e-16] """ return ctx._unary_op_with_fmpz_fmpq_overloads(x, libgr.gr_rfac, op_fmpz=libgr.gr_rfac_fmpz, rstr="rfac($x)") def rfac_vec(ctx, length): """ Vector of reciprocal factorials. >>> QQ.rfac_vec(8) [1, 1, 1/2, 1/6, 1/24, 1/120, 1/720, 1/5040] >>> ZZmod(7).rfac_vec(7) [1, 1, 4, 6, 5, 1, 6] >>> ZZmod(7).rfac_vec(8) Traceback (most recent call last): ... FlintDomainError: rfac_vec(length) is not an element of {Integers mod 7 (_gr_nmod)} for {length = 8} >>> sum(RR.rfac_vec(20)) [2.71828182845904 +/- 8.66e-15] """ return ctx._op_vec_len(length, libgr.gr_rfac_vec, "rfac_vec($length)") def rising(ctx, x, n): """ Rising factorial. >>> [ZZ.rising(3, k) for k in range(5)] [1, 3, 12, 60, 360] >>> ZZx.rising(ZZx([0,1]), 5) x^5+10*x^4+35*x^3+50*x^2+24*x >>> RR.rising(1, 10**7) [1.202423400515903e+65657059 +/- 5.57e+65657043] """ return ctx._binary_op_with_overloads(x, n, libgr.gr_rising, op_ui=libgr.gr_rising_ui, rstr="rising($x, $n)") def falling(ctx, x, n): """ Falling factorial. >>> [ZZ.falling(3, k) for k in range(5)] [1, 3, 6, 6, 0] >>> ZZx.falling(ZZx([0,1]), 5) x^5-10*x^4+35*x^3-50*x^2+24*x >>> RR.log(RR.falling(RR.pi(), 10**7)) [151180898.7174084 +/- 9.72e-8] >>> RR.falling(10.5, 3.5) [2360.99664364330 +/- 4.00e-12] """ return ctx._binary_op_with_overloads(x, n, libgr.gr_falling, op_ui=libgr.gr_falling_ui, rstr="falling($x, $n)") def bin(ctx, x, y): """ Binomial coefficient. >>> [ZZ.bin(5, k) for k in range(7)] [1, 5, 10, 10, 5, 1, 0] >>> RR.bin(100000, 50000) [2.52060836892200e+30100 +/- 5.36e+30085] >>> ZZmod(1000).bin(10000, 3000) 200 >>> ZZp64.bin(100000, 50000) 5763493550349629692 >>> ZZp64.bin(10**30, 2) 998763921924463582 >>> RR.bin(1.5, 0.75) [1.57378746535479 +/- 5.62e-15] """ try: x = ctx._as_ui(x) y = ctx._as_ui(y) return ctx._op_uiui(x, y, libgr.gr_bin_uiui, "bin($x, $y)") except: return ctx._binary_op_with_overloads(x, y, libgr.gr_bin, op_ui=libgr.gr_bin_ui, rstr="bin($x, $y)") def bin_vec(ctx, n, length=None): """ Vector of binomial coefficients, optionally truncated to specified length. >>> ZZ.bin_vec(8) [1, 8, 28, 56, 70, 56, 28, 8, 1] >>> ZZmod(5).bin_vec(8) [1, 3, 3, 1, 0, 1, 3, 3, 1] >>> ZZ.bin_vec(0) [1] >>> ZZ.bin_vec(1000, 3) [1, 1000, 499500] >>> ZZ.bin_vec(4, 8) [1, 4, 6, 4, 1, 0, 0, 0] >>> QQ.bin_vec(QQ(1)/2, 5) [1, 1/2, -1/8, 1/16, -5/128] >>> ZZmod(7).bin_vec(10) [1, 3, 3, 1, 0, 0, 0, 1, 3, 3, 1] >>> ZZmod(7).bin_vec(3) [1, 3, 3, 1] >>> ZZmod(7).bin_vec(10, 1) [1] """ try: n = ctx._as_ui(n) except: return ctx._op_vec_arg_len(n, length, libgr.gr_bin_vec, "bin_vec($n, $length)") if length is None: length = n + 1 return ctx._op_vec_ui_len(n, length, libgr.gr_bin_ui_vec, "bin_vec($n, $length)") def gamma(ctx, x): """ >>> RR.gamma(10) 362880.0000000000 >>> RR.gamma(0.5) [1.772453850905516 +/- 3.41e-16] >>> RR.gamma(QQ(1) / 3) [2.678938534707747 +/- 8.99e-16] >>> CC.gamma(1+1j) / CC.gamma(1j) ([+/- 6.32e-16] + [1.0000000000000 +/- 1.03e-15]*I) """ return ctx._unary_op_with_fmpz_fmpq_overloads(x, libgr.gr_gamma, op_fmpz=libgr.gr_gamma_fmpz, op_fmpq=libgr.gr_gamma_fmpq, rstr="gamma($x)") def lgamma(ctx, x): """ >>> RR.lgamma(10) [12.80182748008147 +/- 2.69e-15] >>> CC.lgamma(10j) ([-15.94031728124131 +/- 6.90e-15] + [12.23211664743500 +/- 4.89e-15]*I) """ return ctx._unary_op(x, libgr.gr_lgamma, "lgamma($x)") def rgamma(ctx, x): """ >>> RR.rgamma(10) [2.755731922398589e-6 +/- 5.96e-22] >>> CC.rgamma(10+1j) ([-1.83246026966323e-6 +/- 5.08e-21] + [-2.25314671311995e-6 +/- 5.78e-21]*I) """ return ctx._unary_op(x, libgr.gr_rgamma, "lgamma($x)") def digamma(ctx, x): """ >>> RR.digamma(2) [0.4227843350984671 +/- 4.84e-17] >>> CC.digamma(2j) ([0.714591515373977 +/- 6.06e-16] + [1.820807282642230 +/- 3.65e-16]*I) """ return ctx._unary_op(x, libgr.gr_digamma, "digamma($x)") def doublefac(ctx, x): """ Double factorial (semifactorial). >>> [ZZ.doublefac(n) for n in range(10)] [1, 1, 2, 3, 8, 15, 48, 105, 384, 945] >>> RR.doublefac(2.5) [2.40706945611604 +/- 5.54e-15] >>> CC.doublefac(1+1j) ([0.250650779545753 +/- 7.56e-16] + [0.100474421235437 +/- 4.14e-16]*I) """ return ctx._unary_op_with_fmpz_fmpq_overloads(x, libgr.gr_doublefac, op_ui=libgr.gr_doublefac_ui, rstr="doublefac($x)") def harmonic(ctx, x): """ Harmonic numbers. >>> [QQ.harmonic(n) for n in range(6)] [0, 1, 3/2, 11/6, 25/12, 137/60] >>> RR.harmonic(10**9) [21.30048150234794 +/- 8.48e-15] >>> ZZp64.harmonic(1000) 6514760847963681162 >>> RR.harmonic(10.5) [2.97545479443731 +/- 5.16e-15] >>> RR.harmonic(15092688622113788323693563264538101449859497) [100.000000000000 +/- 4.35e-14] """ return ctx._unary_op_with_fmpz_fmpq_overloads(x, libgr.gr_harmonic, op_ui=libgr.gr_harmonic_ui, rstr="harmonic($x)") def beta(ctx, x, y): """ Beta function. >>> RR.beta(3, 4.5) [0.01243201243201243 +/- 6.93e-18] >>> CC.beta(1j, 1+1j) ([-1.18807306241087 +/- 5.32e-15] + [-1.31978426013907 +/- 4.09e-15]*I) """ return ctx._binary_op(y, x, libgr.gr_beta, "beta($x, $y)") def barnes_g(ctx, x): """ Barnes G-function. >>> RR.barnes_g(7) 34560.00000000000 >>> CC.barnes_g(1+2j) ([0.54596949228965 +/- 7.69e-15] + [-3.98421873125106 +/- 8.76e-15]*I) """ return ctx._unary_op(x, libgr.gr_barnes_g, "barnes_g($x)") def log_barnes_g(ctx, x): """ Logarithmic Barnes G-function. >>> RR.log_barnes_g(100) [15258.0613921488 +/- 3.87e-11] >>> CC.log_barnes_g(10+20j) ([-452.057343313397 +/- 6.85e-13] + [121.014356688943 +/- 2.52e-13]*I) """ return ctx._unary_op(x, libgr.gr_log_barnes_g, "log_barnes_g($x)") def zeta(ctx, s): """ Riemann zeta function. >>> RR.zeta(2) [1.644934066848226 +/- 4.57e-16] >>> CC.zeta(1+1j) ([0.5821580597520036 +/- 5.17e-17] + [-0.9268485643308071 +/- 2.75e-17]*I) """ return ctx._unary_op(s, libgr.gr_zeta, "zeta($s)") def hurwitz_zeta(ctx, s, a): """ Hurwitz zeta function. >>> RR.hurwitz_zeta(2, 2) [0.6449340668482264 +/- 3.72e-17] >>> CC.hurwitz_zeta(1j, 1) ([0.0033002236853241 +/- 2.42e-17] + [-0.4181554491413217 +/- 4.51e-17]*I) """ return ctx._binary_op(s, a, libgr.gr_hurwitz_zeta, "hurwitz_zeta($s, $a)") def stieltjes(ctx, n, a=1): """ Stieltjes constant. >>> CC.stieltjes(1) [-0.0728158454836767 +/- 2.78e-17] >>> CC.stieltjes(1, a=0.5) [-1.353459680804942 +/- 7.22e-16] """ n = ctx._as_fmpz(n) a = ctx._as_elem(a) res = ctx._elem_type(context=ctx) libgr.gr_stieltjes.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) status = libgr.gr_stieltjes(res._ref, n._ref, a._ref, ctx._ref) if status: _handle_error(ctx, status, "stieltjes($n, $a)", n, a) return res def polylog(ctx, s, z): """ Polylogarithm. >>> CC.polylog(2, -1) [-0.822467033424113 +/- 3.22e-16] """ return ctx._binary_op(s, z, libgr.gr_polylog, "polylog($s, $z)") def polygamma(ctx, s, z): """ Polygamma function. >>> CC.polygamma(2, 3) [-0.1541138063191886 +/- 7.16e-17] """ return ctx._binary_op(s, z, libgr.gr_polygamma, "polygamma($s, $z)") def lerch_phi(ctx, z, s, a): """ >>> CC.lerch_phi(2, 3, 4) ([-0.00213902437921 +/- 1.70e-15] + [-0.04716836434127 +/- 5.28e-15]*I) """ return ctx._ternary_op(z, s, a, libgr.gr_lerch_phi, "lerch_phi($z, $s, $a)") def dirichlet_eta(ctx, x): """ Dirichlet eta function. >>> CC.dirichlet_eta(1) [0.6931471805599453 +/- 6.93e-17] >>> CC.dirichlet_eta(2) [0.822467033424113 +/- 2.36e-16] """ return ctx._unary_op(x, libgr.gr_dirichlet_eta, "dirichlet_eta($x)") def riemann_xi(ctx, x): """ Riemann xi function. >>> s = 2+3j; CC.riemann_xi(s); CC.riemann_xi(1-s) ([0.41627125989962 +/- 4.65e-15] + [0.08882330496564 +/- 1.43e-15]*I) ([0.41627125989962 +/- 4.65e-15] + [0.08882330496564 +/- 1.43e-15]*I) """ return ctx._unary_op(x, libgr.gr_riemann_xi, "riemann_xi($x)") def lambertw(ctx, x, k=None): """ >>> RR.lambertw(1) [0.567143290409784 +/- 2.72e-16] >>> RR.lambertw(-0.25) [-0.3574029561813889 +/- 5.91e-17] >>> RR.lambertw(-0.25, -1) [-2.153292364110349 +/- 8.59e-16] >>> CC.lambertw(-1) ([-0.318131505204764 +/- 1.92e-16] + [1.337235701430689 +/- 5.99e-16]*I) >>> CC.lambertw(1, 5) ([-3.398692196764719 +/- 6.76e-16] + [29.73131070782852 +/- 7.03e-15]*I) """ if k is None: return ctx._unary_op(x, libgr.gr_lambertw, "lambertw($x)") else: return ctx._binary_op_fmpz(x, k, libgr.gr_lambertw_fmpz, "lambertw($x, $k)") def bernoulli(ctx, n): """ Bernoulli number `B_n` as an element of this domain. >>> QQ.bernoulli(10) 5/66 >>> RR.bernoulli(10) [0.0757575757575757 +/- 5.97e-17] >>> ZZ.bernoulli(0) 1 >>> ZZ.bernoulli(1) Traceback (most recent call last): ... FlintDomainError: bernoulli(n) is not an element of {Integer ring (fmpz)} for {n = 1} Huge Bernoulli numbers can be computed numerically: >>> RR.bernoulli(10**20) [-1.220421181609039e+1876752564973863312289 +/- 4.69e+1876752564973863312273] >>> RF.bernoulli(10**20) -1.220421181609039e+1876752564973863312289 >>> QQ.bernoulli(10**20) Traceback (most recent call last): ... FlintUnableError: failed to compute bernoulli(n) in {Rational field (fmpq)} for {n = 100000000000000000000} """ return ctx._op_fmpz(n, libgr.gr_bernoulli_fmpz, "bernoulli($n)") def bernoulli_vec(ctx, length): """ Vector of Bernoulli numbers. >>> QQ.bernoulli_vec(12) [1, -1/2, 1/6, 0, -1/30, 0, 1/42, 0, -1/30, 0, 5/66, 0] >>> CC_ca.bernoulli_vec(5) [1, -0.500000 {-1/2}, 0.166667 {1/6}, 0, -0.0333333 {-1/30}] >>> sum(RR.bernoulli_vec(100)) [1.127124216595034e+76 +/- 6.74e+60] >>> sum(RF.bernoulli_vec(100)) 1.127124216595034e+76 >>> sum(CC.bernoulli_vec(100)) [1.127124216595034e+76 +/- 6.74e+60] """ return ctx._op_vec_len(length, libgr.gr_bernoulli_vec, "bernoulli_vec($length)") def eulernum(ctx, n): """ Euler number `E_n` as an element of this domain. >>> ZZ.eulernum(10) -50521 >>> RR.eulernum(10) -50521.00000000000 Huge Euler numbers can be computed numerically: >>> RR.eulernum(10**20) [4.346791453661149e+1936958564106659551331 +/- 8.35e+1936958564106659551315] >>> RF.eulernum(10**20) 4.346791453661149e+1936958564106659551331 >>> ZZ.eulernum(10**20) Traceback (most recent call last): ... FlintUnableError: failed to compute eulernum(n) in {Integer ring (fmpz)} for {n = 100000000000000000000} """ return ctx._op_fmpz(n, libgr.gr_eulernum_fmpz, "eulernum($n)") def eulernum_vec(ctx, length): """ Vector of Euler numbers. >>> ZZ.eulernum_vec(12) [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521, 0] >>> QQ.eulernum_vec(12) / 3 [1/3, 0, -1/3, 0, 5/3, 0, -61/3, 0, 1385/3, 0, -50521/3, 0] >>> sum(RR.eulernum_vec(100)) [-7.23465655613392e+134 +/- 3.20e+119] >>> sum(RF.eulernum_vec(100)) -7.234656556133921e+134 """ return ctx._op_vec_len(length, libgr.gr_eulernum_vec, "eulernum_vec($length)") def fib(ctx, n): """ Fibonacci number `F_n` as an element of this domain. >>> ZZ.fib(10) 55 >>> RR.fib(10) 55.00000000000000 >>> ZZ.fib(-10) -55 Huge Fibonacci numbers can be computed numerically and in modular arithmetic: >>> RR.fib(10**20) [3.78202087472056e+20898764024997873376 +/- 4.02e+20898764024997873361] >>> RF.fib(10**20) 3.782020874720557e+20898764024997873376 >>> F = FiniteField_fq(17, 1) >>> n = 10**20; F.fib(n); F.fib(n-1) + F.fib(n-2) 13 13 """ return ctx._op_fmpz(n, libgr.gr_fib_fmpz, "fib($n)") def fib_vec(ctx, length): """ Vector of Fibonacci numbers. >>> ZZ.fib_vec(10) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] >>> QQ.fib_vec(10) / 3 [0, 1/3, 1/3, 2/3, 1, 5/3, 8/3, 13/3, 7, 34/3] >>> sum(RR.fib_vec(100)) # doctest: +ELLIPSIS [5.7314784401...e+20 +/- ...] >>> sum(RF.fib_vec(100)) 5.731478440138172e+20 """ return ctx._op_vec_len(length, libgr.gr_fib_vec, "fib($length)") def stirling_s1u(ctx, n, k): """ Unsigned Stirling number of the first kind. >>> ZZ.stirling_s1u(5, 2) 50 >>> QQ.stirling_s1u(5, 2) 50 >>> ZZ.stirling_s1u(50, 21) 33187391298039120738041153829116024033357291261862000 >>> RR.stirling_s1u(50, 21) [3.318739129803912e+52 +/- 8.66e+36] """ return ctx._op_uiui(n, k, libgr.gr_stirling_s1u_uiui, "stirling_s1u($n, $k)") def stirling_s1(ctx, n, k): """ Signed Stirling number of the first kind. >>> ZZ.stirling_s1(5, 2) -50 >>> QQ.stirling_s1(5, 2) -50 >>> RR.stirling_s1(5, 2) -50.00000000000000 """ return ctx._op_uiui(n, k, libgr.gr_stirling_s1_uiui, "stirling_s1($n, $k)") def stirling_s2(ctx, n, k): """ Stirling number of the second kind. >>> ZZ.stirling_s2(5, 2) 15 >>> QQ.stirling_s2(5, 2) 15 >>> RR.stirling_s2(5, 2) 15.00000000000000 >>> RR.stirling_s2(50, 20) [7.59792160686099e+45 +/- 5.27e+30] """ return ctx._op_uiui(n, k, libgr.gr_stirling_s2_uiui, "stirling_s2($n, $k)") def stirling_s1u_vec(ctx, n, length=None): """ Vector of unsigned Stirling numbers of the first kind, optionally truncated to specified length. >>> ZZ.stirling_s1u_vec(5) [0, 24, 50, 35, 10, 1] >>> QQ.stirling_s1u_vec(5) / 3 [0, 8, 50/3, 35/3, 10/3, 1/3] >>> RR.stirling_s1u_vec(5, 3) [0, 24.00000000000000, 50.00000000000000] """ if length is None: length = n + 1 return ctx._op_vec_ui_len(n, length, libgr.gr_stirling_s1u_ui_vec, "stirling_s1u_vec($n, $length)") def stirling_s1_vec(ctx, n, length=None): """ Vector of signed Stirling numbers of the first kind, optionally truncated to specified length. >>> ZZ.stirling_s1_vec(5) [0, 24, -50, 35, -10, 1] >>> QQ.stirling_s1_vec(5) / 3 [0, 8, -50/3, 35/3, -10/3, 1/3] >>> RR.stirling_s1_vec(5, 3) [0, 24.00000000000000, -50.00000000000000] """ if length is None: length = n + 1 return ctx._op_vec_ui_len(n, length, libgr.gr_stirling_s1_ui_vec, "stirling_s1_vec($n, $length)") def stirling_s2_vec(ctx, n, length=None): """ Vector of Stirling numbers of the second kind, optionally truncated to specified length. >>> ZZ.stirling_s2_vec(5) [0, 1, 15, 25, 10, 1] >>> QQ.stirling_s2_vec(5) / 3 [0, 1/3, 5, 25/3, 10/3, 1/3] >>> RR.stirling_s2_vec(5, 3) [0, 1, 15.00000000000000] """ if length is None: length = n + 1 return ctx._op_vec_ui_len(n, length, libgr.gr_stirling_s2_ui_vec, "stirling_s2_vec($n, $length)") def bellnum(ctx, n): """ Bell number `E_n` as an element of this domain. >>> ZZ.bellnum(10) 115975 >>> RR.bellnum(10) 115975.0000000000 >>> ZZp64.bellnum(10000) 355901145009109239 >>> ZZmod(1000).bellnum(10000) 635 Huge Bell numbers can be computed numerically: >>> RR.bellnum(10**20) [5.38270113176282e+1794956117137290721328 +/- 5.44e+1794956117137290721313] >>> ZZ.bellnum(10**20) Traceback (most recent call last): ... FlintUnableError: failed to compute bellnum(n) in {Integer ring (fmpz)} for {n = 100000000000000000000} """ return ctx._op_fmpz(n, libgr.gr_bellnum_fmpz, "bellnum($n)") def bellnum_vec(ctx, length): """ Vector of Bell numbers. >>> ZZ.bellnum_vec(10) [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147] >>> QQ.bellnum_vec(10) / 3 [1/3, 1/3, 2/3, 5/3, 5, 52/3, 203/3, 877/3, 1380, 7049] >>> RR.bellnum_vec(100).sum() [1.67618752079292e+114 +/- 4.30e+99] >>> RF.bellnum_vec(100).sum() 1.676187520792924e+114 >>> ZZmod(10000).bellnum_vec(10000).sum() 7337 """ return ctx._op_vec_len(length, libgr.gr_bellnum_vec, "bellnum_vec($length)") def partitions(ctx, n): """ Partition function `p(n)` as an element of this domain. >>> ZZ.partitions(10) 42 >>> QQ.partitions(10) / 5 42/5 >>> RR.partitions(10) 42.00000000000000 >>> RR.partitions(10**20) [1.838176508344883e+11140086259 +/- 8.18e+11140086243] """ return ctx._op_fmpz(n, libgr.gr_partitions_fmpz, "partitions($n)") def partitions_vec(ctx, length): """ Vector of partition numbers. >>> ZZ.partitions_vec(10) [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] >>> QQ.partitions_vec(10) / 3 [1/3, 1/3, 2/3, 1, 5/3, 7/3, 11/3, 5, 22/3, 10] >>> ZZmod(10).partitions_vec(10) [1, 1, 2, 3, 5, 7, 1, 5, 2, 0] >>> sum(ZZmod(10).partitions_vec(100)) 6 >>> sum(RR.partitions_vec(100)) 1452423276.000000 """ return ctx._op_vec_len(length, libgr.gr_partitions_vec, "partitions($length)") def zeta_zero(ctx, n): """ Zero of the Riemann zeta function. >>> CC.zeta_zero(1) (0.5000000000000000 + [14.13472514173469 +/- 4.71e-15]*I) >>> CC.zeta_zero(2) (0.5000000000000000 + [21.02203963877155 +/- 6.02e-15]*I) """ return ctx._unary_op_fmpz(n, libgr.gr_zeta_zero, "zeta_zero($n)") def zeta_zeros(ctx, num, start=1): """ Zeros of the Riemann zeta function. >>> [x.im() for x in CC.zeta_zeros(4)] [[14.13472514173469 +/- 4.71e-15], [21.02203963877155 +/- 6.02e-15], [25.01085758014569 +/- 7.84e-15], [30.42487612585951 +/- 5.96e-15]] >>> [x.im() for x in CC.zeta_zeros(2, start=100)] [[236.5242296658162 +/- 3.51e-14], [237.7698204809252 +/- 5.29e-14]] """ return ctx._op_vec_fmpz_len(start, num, libgr.gr_zeta_zero_vec, "zeta_zeros($n)") def zeta_nzeros(ctx, t): """ Number of zeros of Riemann zeta function up to given height. >>> CC.zeta_nzeros(100) 29.00000000000000 """ return ctx._unary_op(t, libgr.gr_zeta_nzeros, "zeta_nzeros($t)") def dirichlet_l(ctx, s, chi): """ Dirichlet L-function with character chi. >>> CC.dirichlet_l(2, DirichletGroup(1)(1)) [1.644934066848226 +/- 4.57e-16] >>> RR.dirichlet_l(2, DirichletGroup(4)(3)) [0.915965594177219 +/- 2.68e-16] >>> CC.dirichlet_l(2+3j, DirichletGroup(7)(3)) ([1.273313649440491 +/- 9.69e-16] + [-0.074323294425594 +/- 6.96e-16]*I) """ s = ctx._as_elem(s) assert isinstance(chi, dirichlet_char) res = ctx._elem_type(context=ctx) libgr.gr_dirichlet_l.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) G = libgr.gr_ctx_data_as_ptr(chi.parent()._ref) status = libgr.gr_dirichlet_l(res._ref, G, chi._ref, s._ref, ctx._ref) if status: _handle_error(ctx, status, "dirichlet_l($s, $chi)", s, chi) return res def hardy_theta(ctx, s, chi=None): """ Hardy theta function. >>> CC.hardy_theta(10) [-3.06707439628989 +/- 6.66e-15] >>> RR.hardy_theta(2) [-2.525910918816132 +/- 9.34e-16] >>> CC.hardy_theta(10, DirichletGroup(4)(3)) [4.64979557270698 +/- 4.41e-15] """ s = ctx._as_elem(s) res = ctx._elem_type(context=ctx) libgr.gr_dirichlet_hardy_theta.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) if chi is None: chi_ref = G = None else: assert isinstance(chi, dirichlet_char) G = libgr.gr_ctx_data_as_ptr(chi.parent()._ref) chi_ref = chi._ref status = libgr.gr_dirichlet_hardy_theta(res._ref, G, chi_ref, s._ref, ctx._ref) if status: _handle_error(ctx, status, "hardy_theta($s, $chi)", s, chi) return res def hardy_z(ctx, s, chi=None): """ Hardy Z-function. >>> CC.hardy_z(2) [-0.539633125646145 +/- 8.59e-16] >>> RR.hardy_z(2) [-0.539633125646145 +/- 8.59e-16] >>> CC.hardy_z(2, DirichletGroup(4)(3)) [1.15107760668266 +/- 5.01e-15] """ s = ctx._as_elem(s) res = ctx._elem_type(context=ctx) libgr.gr_dirichlet_hardy_z.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) if chi is None: chi_ref = G = None else: assert isinstance(chi, dirichlet_char) G = libgr.gr_ctx_data_as_ptr(chi.parent()._ref) chi_ref = chi._ref status = libgr.gr_dirichlet_hardy_z(res._ref, G, chi_ref, s._ref, ctx._ref) if status: _handle_error(ctx, status, "hardy_z($s, $chi)", s, chi) return res def dirichlet_chi(ctx, n, chi): """ Value of the Dirichlet character chi(n). >>> chi = DirichletGroup(5)(3) >>> [CC.dirichlet_chi(n, chi) for n in range(5)] [0, 1, -1.000000000000000*I, 1.000000000000000*I, -1] """ n = ctx._as_fmpz(n) assert isinstance(chi, dirichlet_char) res = ctx._elem_type(context=ctx) libgr.gr_dirichlet_chi_fmpz.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) G = libgr.gr_ctx_data_as_ptr(chi.parent()._ref) status = libgr.gr_dirichlet_chi_fmpz(res._ref, G, chi._ref, n._ref, ctx._ref) if status: _handle_error(ctx, status, "dirichlet_chi($n, $chi)", n, chi) return res def dirichlet_chi_vec(ctx, chi, n): """ Vector of values of the given Dirichlet character. >>> CC.dirichlet_chi_vec(DirichletGroup(4)(3), 5) [0, 1, 0, -1, 0] """ n = ctx._as_si(n) assert n >= 0 assert n <= HUGE_LENGTH assert isinstance(chi, dirichlet_char) libgr.gr_dirichlet_chi_vec.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, c_slong, ctypes.c_void_p) G = libgr.gr_ctx_data_as_ptr(chi.parent()._ref) res = Vec(ctx)() assert not libgr.gr_vec_set_length(res._ref, n, ctx._ref) status = libgr.gr_dirichlet_chi_vec(libgr.gr_vec_entry_ptr(res._ref, 0, ctx._ref), G, chi._ref, n, ctx._ref) if status: _handle_error(ctx, status, "dirichlet_chi_vec($chi, $n)", chi, n) return res def modular_j(ctx, tau): """ j-invariant j(tau). >>> CC.modular_j(1j) [1728.0000000000 +/- 5.10e-11] """ return ctx._unary_op(tau, libgr.gr_modular_j, "modular_j($tau)") def modular_lambda(ctx, tau): """ Modular lambda function lambda(tau). >>> CC.modular_lambda(1j) [0.50000000000000 +/- 2.16e-15] """ return ctx._unary_op(tau, libgr.gr_modular_lambda, "modular_lambda($tau)") def modular_delta(ctx, tau): """ Modular discriminant delta(tau). >>> CC.modular_delta(1j) [0.0017853698506421 +/- 6.01e-17] """ return ctx._unary_op(tau, libgr.gr_modular_delta, "modular_delta($tau)") def dedekind_eta(ctx, tau): """ Dedekind eta function eta(tau). >>> CC.dedekind_eta(1j) [0.768225422326057 +/- 9.03e-16] """ return ctx._unary_op(tau, libgr.gr_dedekind_eta, "dedekind_eta($tau)") def hilbert_class_poly(ctx, D, x): """ Hilbert class polynomial H_D(x) evaluated at x. >>> ZZx.hilbert_class_poly(-20, ZZx.gen()) x^2-1264000*x-681472000 >>> CC.hilbert_class_poly(-20, 1+1j) (-682736000.0000000 - 1263998.000000000*I) >>> ZZx.hilbert_class_poly(-21, ZZx.gen()) Traceback (most recent call last): ... FlintDomainError: hilbert_class_poly(D, x) is not an element of {Polynomials over integers (fmpz_poly)} for {D = -21}, {x = x} """ D = ctx._as_si(D) x = ctx._as_elem(x) res = ctx._elem_type(context=ctx) libgr.gr_hilbert_class_poly.argtypes = (ctypes.c_void_p, c_slong, ctypes.c_void_p, ctypes.c_void_p) status = libgr.gr_hilbert_class_poly(res._ref, D, x._ref, ctx._ref) if status: _handle_error(ctx, status, "hilbert_class_poly($D, $x)", D, x) return res def eisenstein_g(ctx, n, tau): """ Eisenstein series G_n(tau). >>> CC.eisenstein_g(2, 1j) [3.14159265358979 +/- 8.71e-15] >>> CC.eisenstein_g(4, 1j); RR.gamma(0.25)**8 / (960 * RR.pi()**2) [3.1512120021539 +/- 3.41e-14] [3.15121200215390 +/- 7.72e-15] """ return ctx._ui_binary_op(n, tau, libgr.gr_eisenstein_g, "eisenstein_g($n, $tau)") def eisenstein_e(ctx, n, tau): """ Eisenstein series E_n(tau). >>> CC.eisenstein_e(2, 1j) [0.95492965855137 +/- 3.85e-15] >>> CC.eisenstein_e(4, 1j); 3*RR.gamma(0.25)**8/(64*RR.pi()**6) [1.4557628922687 +/- 1.32e-14] [1.45576289226871 +/- 3.76e-15] """ return ctx._ui_binary_op(n, tau, libgr.gr_eisenstein_e, "eisenstein_e($n, $tau)") def eisenstein_g_vec(ctx, tau, n): """ Vector of Eisenstein series [G_4(tau), G_6(tau), ...]. Note that G_2(tau) is omitted. >>> CC.eisenstein_g_vec(1j, 3) [[3.1512120021539 +/- 3.41e-14], [+/- 4.40e-14], [4.255773035365 +/- 2.12e-13]] """ return ctx._op_vec_arg_len(tau, n, libgr.gr_eisenstein_g_vec, "eisenstein_g_vec($tau, $n)") def agm(ctx, x, y=None): """ Arithmetic-geometric mean. >>> RR.agm(2) [1.45679103104691 +/- 3.98e-15] >>> RR.agm(2, 3) [2.47468043623630 +/- 4.68e-15] """ if y is None: return ctx._unary_op(x, libgr.gr_agm1, "agm1($x)") else: return ctx._binary_op(x, y, libgr.gr_agm, "agm($x, $y)") def elliptic_k(ctx, m): return ctx._unary_op(m, libgr.gr_elliptic_k, "elliptic_k($m)") def elliptic_e(ctx, m): return ctx._unary_op(m, libgr.gr_elliptic_e, "elliptic_e($m)") def elliptic_pi(ctx, n, m): return ctx._binary_op(n, m, libgr.gr_elliptic_pi, "elliptic_pi($n, $m)") def elliptic_f(ctx, phi, m, pi=0): return ctx._binary_op_with_flag(phi, m, pi, libgr.gr_elliptic_f, "elliptic_f($phi, $m, $pi)") def elliptic_e_inc(ctx, phi, m, pi=0): return ctx._binary_op_with_flag(phi, m, pi, libgr.gr_elliptic_e_inc, "elliptic_e_inc($phi, $m, $pi)") def elliptic_pi_inc(ctx, n, phi, m, pi=0): return ctx._ternary_op_with_flag(n, phi, m, pi, libgr.gr_elliptic_pi_inc, "elliptic_pi_inc($n, $phi, $m, $pi)") def carlson_rc(ctx, x, y, flags=0): return ctx._binary_op_with_flag(x, y, flags, libgr.gr_carlson_rc, "carlson_rc($x, $y)") def carlson_rf(ctx, x, y, z, flags=0): return ctx._ternary_op_with_flag(x, y, z, flags, libgr.gr_carlson_rf, "carlson_rf($x, $y, $z)") def carlson_rg(ctx, x, y, z, flags=0): return ctx._ternary_op_with_flag(x, y, z, flags, libgr.gr_carlson_rg, "carlson_rg($x, $y, $z)") def carlson_rd(ctx, x, y, z, flags=0): return ctx._ternary_op_with_flag(x, y, z, flags, libgr.gr_carlson_rd, "carlson_rd($x, $y, $z)") def carlson_rj(ctx, x, y, z, w, flags=0): return ctx._quaternary_op_with_flag(x, y, z, w, flags, libgr.gr_carlson_rd, "carlson_rj($x, $y, $z, $w)") def jacobi_theta(ctx, z, tau): """ Simultaneous computation of the four Jacobi theta functions. >>> CC.jacobi_theta(0.125, 1j) ([0.347386687929454 +/- 3.21e-16], [0.843115469091413 +/- 8.18e-16], [1.061113709291166 +/- 5.74e-16], [0.938886290708834 +/- 3.52e-16]) """ return ctx._quaternary_binary_op(z, tau, libgr.gr_jacobi_theta, "jacobi_theta($z, $tau)") def jacobi_theta_1(ctx, z, tau): """ Jacobi theta function. >>> CC.jacobi_theta_1(0.125, 1j) [0.347386687929454 +/- 3.21e-16] """ return ctx._binary_op(z, tau, libgr.gr_jacobi_theta_1, "jacobi_theta_1($z, $tau)") def jacobi_theta_2(ctx, z, tau): """ Jacobi theta function. >>> CC.jacobi_theta_2(0.125, 1j) [0.843115469091413 +/- 8.18e-16] """ return ctx._binary_op(z, tau, libgr.gr_jacobi_theta_2, "jacobi_theta_2($z, $tau)") def jacobi_theta_3(ctx, z, tau): """ Jacobi theta function. >>> CC.jacobi_theta_3(0.125, 1j) [1.061113709291166 +/- 5.74e-16] """ return ctx._binary_op(z, tau, libgr.gr_jacobi_theta_3, "jacobi_theta_3($z, $tau)") def jacobi_theta_4(ctx, z, tau): """ Jacobi theta function. >>> CC.jacobi_theta_4(0.125, 1j) [0.938886290708834 +/- 3.52e-16] """ return ctx._binary_op(z, tau, libgr.gr_jacobi_theta_4, "jacobi_theta_4($z, $tau)") def elliptic_invariants(ctx, tau): """ >>> g2, g3 = CC.elliptic_invariants(1j) >>> CC.weierstrass_p_prime(0.25, 1j)**2; 4*CC.weierstrass_p(0.25, 1j)**3 - g2*CC.weierstrass_p(0.25, 1j) - g3 [15152.862386715 +/- 7.03e-10] [15152.86238672 +/- 5.09e-9] """ return ctx._unary_unary_op(tau, libgr.gr_elliptic_invariants, "elliptic_invariants($tau)") def elliptic_roots(ctx, tau): """ >>> e1, e2, e3 = CC.elliptic_roots(1j) >>> g2, g3 = CC.elliptic_invariants(1j) >>> 4*e1**3 - g2*e1 - g3 [+/- 3.12e-11] >>> 4*e2**3 - g2*e2 - g3 [+/- 8.29e-12] >>> 4*e3**3 - g2*e3 - g3 [+/- 3.14e-11] """ return ctx._ternary_unary_op(tau, libgr.gr_elliptic_roots, "elliptic_roots($tau)") def weierstrass_p(ctx, z, tau): return ctx._binary_op(z, tau, libgr.gr_weierstrass_p, "weierstrass_p($z, $tau)") def weierstrass_p_prime(ctx, z, tau): return ctx._binary_op(z, tau, libgr.gr_weierstrass_p_prime, "weierstrass_p_prime($z, $tau)") def weierstrass_p_inv(ctx, z, tau): """ Inverse Weierstrass elliptic function. >>> CC.weierstrass_p(CC.weierstrass_p_inv(0.5, 1j), 1j) ([0.50000000000 +/- 4.61e-12] + [+/- 6.98e-12]*I) """ return ctx._binary_op(z, tau, libgr.gr_weierstrass_p_inv, "weierstrass_p_inv($z, $tau)") def weierstrass_zeta(ctx, z, tau): return ctx._binary_op(z, tau, libgr.gr_weierstrass_zeta, "weierstrass_zeta($z, $tau)") def weierstrass_sigma(ctx, z, tau): return ctx._binary_op(z, tau, libgr.gr_weierstrass_sigma, "weierstrass_sigma($z, $tau)") def _gr_set_int(self, val): if WORD_MIN <= val <= WORD_MAX: status = libgr.gr_set_si(self._ref, val, self._ctx) else: n = fmpz_struct() nref = ctypes.byref(n) libflint.fmpz_init(nref) libflint.fmpz_set_str(nref, ctypes.c_char_p(str(val).encode('ascii')), 10) status = libgr.gr_set_fmpz(self._ref, nref, self._ctx) libflint.fmpz_clear(nref) return status class gr_elem: """ Base class for elements. """ @staticmethod def _default_context(): return None @property def _as_parameter_(self): return self._ref @staticmethod def from_param(arg): return arg def __init__(self, val=None, context=None, random=False): """ >>> ZZ(QQ(1)) 1 >>> ZZ(QQ(1) / 3) Traceback (most recent call last): ... FlintDomainError: 1/3 is not defined in Integer ring (fmpz) """ if context is None: context = self._default_context() if context is None: raise ValueError("a context object is needed") self._ctx_python = context self._ctx = self._ctx_python._ref self._data = self._struct_type() self._ref = ctypes.byref(self._data) libgr.gr_init(self._ref, self._ctx) self._ctx_python._refcount += 1 if val is not None: typ = type(val) status = GR_UNABLE if typ is int: status = _gr_set_int(self, val) elif isinstance(val, gr_elem): status = libgr.gr_set_other(self._ref, val._ref, val._ctx, self._ctx) elif typ is str: status = libgr.gr_set_str(self._ref, ctypes.c_char_p(str(val).encode('ascii')), self._ctx) elif typ is float: status = libgr.gr_set_d(self._ref, val, self._ctx) elif typ is complex: # todo x = context(val.real) + context(val.imag) * context.i() status = libgr.gr_set(self._ref, x._ref, self._ctx) elif typ is fexpr: # XXX xvec = yvec = Vec(context)() status = libgr.gr_set_fexpr(self._ref, xvec._ref, yvec._ref, val._ref, self._ctx) elif hasattr(val, "_gr_elem_"): val = val._gr_elem_(context) assert val.parent() is context status = libgr.gr_set_other(self._ref, val._ref, val._ctx, self._ctx) elif typ.__name__ == "mpz": status = _gr_set_int(self, int(val)) else: status = GR_UNABLE if status: if status & GR_UNABLE: raise FlintUnableError(f"unable to create element of {self.parent()} from {val} of type {type(val)}") if status & GR_DOMAIN: raise FlintDomainError(f"{val} is not defined in {self.parent()}") elif random: libgr.gr_randtest(self._ref, ctypes.byref(_flint_rand), self._ctx) def __del__(self): libgr.gr_clear(self._ref, self._ctx) self._ctx_python._decrement_refcount() def parent(self): """ Return the parent object of this element. >>> ZZ(0).parent() Integer ring (fmpz) >>> ZZ(0).parent() is ZZ True """ return self._ctx_python def __repr__(self): arr = ctypes.c_char_p() if libgr.gr_get_str(ctypes.byref(arr), self._ref, self._ctx) != GR_SUCCESS: raise NotImplementedError try: return ctypes.cast(arr, ctypes.c_char_p).value.decode("ascii") finally: libflint.flint_free(arr) def nstr(self, n): """ Return a string representation of this element, where real and complex numbers may be rounded to n digits. >>> RR.pi().nstr(10) '3.141592654' >>> CC(1+1j).exp().nstr(10) '(1.468693940 + 2.287355287*I)' """ arr = ctypes.c_char_p() n = self._ctx_python._as_si(n) if libgr.gr_get_str_n(ctypes.byref(arr), self._ref, n, self._ctx) != GR_SUCCESS: raise NotImplementedError try: return ctypes.cast(arr, ctypes.c_char_p).value.decode("ascii") finally: libflint.flint_free(arr) def nprint(self, n): """ Print a string representation of this element, where real and complex numbers may be rounded to *n* digits. >>> RR.pi().nprint(10) 3.141592654 >>> CC(1+1j).exp().nprint(10) (1.468693940 + 2.287355287*I) """ print(self.nstr(n)) def fexpr(self, serialize=True): res = fexpr() if serialize: status = libflint.gr_get_fexpr_serialize(res._ref, self._ref, self._ctx) else: status = libflint.gr_get_fexpr(res._ref, self._ref, self._ctx) if status: _handle_error(self.parent(), status, "fexpr($x)") return res def latex(self): return self.fexpr(serialize=False).latex() def _repr_latex_(self): return "$$" + self.latex() + "$$" @staticmethod def _binary_coercion(self, other): elem_type = type(self) other_type = type(other) if elem_type is not other_type: if not isinstance(other, gr_elem): other = self.parent()(other) elif not isinstance(self, gr_elem): self = other.parent()(self) if self._ctx_python is not other._ctx_python: c = libgr.gr_ctx_cmp_coercion(self._ctx, other._ctx) if c >= 0: other = self.parent()(other) else: self = other.parent()(self) return self, other @staticmethod def _binary_op(self, other, op, rstr): self, other = gr_elem._binary_coercion(self, other) res = type(self)(context=self._ctx_python) status = op(res._ref, self._ref, other._ref, self._ctx) if status: _handle_error(self.parent(), status, rstr, self, other) return res @staticmethod def _binary_op2(self, other, ops, rstr): self_type = type(self) other_type = type(other) if self_type is other_type and self._ctx_python is other._ctx_python: res = type(self)(context=self._ctx_python) status = ops[0](res._ref, self._ref, other._ref, self._ctx) elif isinstance(self, gr_elem) and isinstance(other, gr_elem): c = libgr.gr_ctx_cmp_coercion(self._ctx, other._ctx) if c >= 0: # other -> self # print("trying", other, "into", self) res = type(self)(context=self._ctx_python) status = ops[3](res._ref, self._ref, other._ref, other._ctx, self._ctx) else: # self -> other # print("trying", self, "into", other) res = type(other)(context=other._ctx_python) status = ops[4](res._ref, self._ref, self._ctx, other._ref, other._ctx) # needed? if status: if c >= 0: other = self.parent()(other) else: self = other.parent()(self) res = type(self)(context=self._ctx_python) status = ops[0](res._ref, self._ref, other._ref, self._ctx) elif other_type is int: if WORD_MIN <= other <= WORD_MAX: # todo: efficient code from left also res = type(self)(context=self._ctx_python) status = ops[1](res._ref, self._ref, other, self._ctx) else: other = ZZ(other) res = type(self)(context=self._ctx_python) status = ops[2](res._ref, self._ref, other._ref, self._ctx) elif self_type is int: return other._binary_op2(ZZ(self), other, ops, rstr) else: if not isinstance(other, gr_elem): other = self.parent()(other) elif not isinstance(self, gr_elem): self = other.parent()(self) return self._binary_op2(self, other, ops, rstr) if status: _handle_error(self.parent(), status, rstr, self, other) # if status & GR_UNABLE: raise NotImplementedError(f"unable to compute {rstr} for x = {self}, y = {other} over {self.parent()}") # if status & GR_DOMAIN: raise ValueError(f"{rstr} is not defined for x = {self}, y = {other} over {self.parent()}") return res @staticmethod def _unary_predicate(self, op, rstr): truth = op(self._ref, self._ctx) if _gr_logic == 3: return Truth(truth) if truth == T_TRUE: return True if truth == T_FALSE: return False if _gr_logic == 1: return True if _gr_logic == -1: return False if _gr_logic == 2: return None raise Undecidable(f"unable to decide {rstr} for x = {self} over {self.parent()}") @staticmethod def _binary_predicate(self, other, op, rstr): self, other = gr_elem._binary_coercion(self, other) truth = op(self._ref, other._ref, self._ctx) if _gr_logic == 3: return Truth(truth) if truth == T_TRUE: return True if truth == T_FALSE: return False if _gr_logic == 1: return True if _gr_logic == -1: return False if _gr_logic == 2: return None raise Undecidable(f"unable to decide {rstr} for x = {self}, y = {other} over {self.parent()}") @staticmethod def _unary_op(self, op, rstr): elem_type = type(self) res = elem_type(context=self._ctx_python) status = op(res._ref, self._ref, self._ctx) if status: _handle_error(self.parent(), status, rstr, self) return res @staticmethod def _unary_op_get_fmpz(self, op, rstr): res = ZZ() status = op(res._ref, self._ref, self._ctx) if status: _handle_error(self.parent(), status, rstr, self) return res @staticmethod def _binary_op_fmpz(self, other, op, rstr): other = ZZ(other) elem_type = type(self) res = elem_type(context=self._ctx_python) status = op(res._ref, self._ref, other._ref, self._ctx) if status: _handle_error(self.parent(), status, rstr, self, other) return res @staticmethod def _constant(self, op, rstr): elem_type = type(self) res = elem_type(context=self._ctx_python) status = op(res._ref, self._ctx) if status: _handle_error(self.parent(), status, rstr) return res def __eq__(self, other): return self._binary_predicate(self, other, libgr.gr_equal, "x == y") def __ne__(self, other): return self._binary_predicate(self, other, libgr.gr_not_equal, "x != y") def _cmp(self, other): self, other = gr_elem._binary_coercion(self, other) c = (ctypes.c_int * 1)() status = libgr.gr_cmp(c, self._ref, other._ref, self._ctx) if status: if status & GR_UNABLE: raise Undecidable(f"unable to compare x = {self} and y = {other} in {self.parent()}") if status & GR_DOMAIN: raise ValueError(f"ordering not defined for x = {self} and y = {other} in {self.parent()}") return c[0] def __lt__(self, other): return gr_elem._cmp(self, other) < 0 def __le__(self, other): return gr_elem._cmp(self, other) <= 0 def __gt__(self, other): return gr_elem._cmp(self, other) > 0 def __ge__(self, other): return gr_elem._cmp(self, other) >= 0 def __neg__(self): return self._unary_op(self, libgr.gr_neg, "-x") def __pos__(self): return self def __abs__(self): return self._unary_op(self, libgr.gr_abs, "abs(x)") def __add__(self, other): return self._binary_op2(self, other, _add_methods, "$x + $y") def __radd__(self, other): return self._binary_op2(other, self, _add_methods, "$x + $y") def __sub__(self, other): return self._binary_op2(self, other, _sub_methods, "$x - $y") def __rsub__(self, other): return self._binary_op2(other, self, _sub_methods, "$x - $y") def __mul__(self, other): return self._binary_op2(self, other, _mul_methods, "$x * $y") def __rmul__(self, other): return self._binary_op2(other, self, _mul_methods, "$x * $y") def __truediv__(self, other): return self._binary_op2(self, other, _div_methods, "$x / $y") def __rtruediv__(self, other): return self._binary_op2(other, self, _div_methods, "$x / $y") def __pow__(self, other): return self._binary_op2(self, other, _pow_methods, "$x ** $y") def __rpow__(self, other): return self._binary_op2(other, self, _pow_methods, "$x ** $y") def __floordiv__(self, other): return self._binary_op(self, other, libgr.gr_euclidean_div, "$x // $y") def __rfloordiv__(self, other): return self._binary_op(self, other, libgr.gr_euclidean_div, "$x // $y") def __mod__(self, other): return self._binary_op(self, other, libgr.gr_euclidean_rem, "$x % $y") def __rmod__(self, other): return self._binary_op(self, other, libgr.gr_euclidean_rem, "$x % $y") def is_invertible(self): """ Return whether self has a multiplicative inverse in its domain. >>> >>> ZZ(3).is_invertible() False >>> ZZ(-1).is_invertible() True """ return self._unary_predicate(self, libgr.gr_is_invertible, "is_invertible") def divides(self, other): """ Return whether self divides other. >>> ZZ(5).divides(10) True >>> ZZ(5).divides(12) False """ return self._binary_predicate(self, other, libgr.gr_divides, "divides") def gcd(self, other): """ Greatest common divisor. >>> ZZ(24).gcd(30) 6 >>> pi = CC_ca.pi(); i = CC_ca.i(); x = PolynomialRing(CC_ca).gen(); (x**2 + pi**2).gcd(x+i*pi) (3.14159*I {a*b where a = 3.14159 [Pi], b = I [b^2+1=0]}) + x >>> QQx([1,1,2,-1,3]).gcd(QQx([1,-1,1])) 1 - x + x^2 """ return self._binary_op(self, other, libgr.gr_gcd, "gcd") def lcm(self, other): """ Least common multiple. >>> ZZ(24).lcm(30) 120 """ return self._binary_op(self, other, libgr.gr_lcm, "lcm") def factor(self): """ Returns a factorization of self as a tuple (prefactor, factors, exponents). >>> ZZ(-120).factor() (-1, [2, 3, 5], [3, 1, 1]) """ elem_type = type(self) c = elem_type(context=self._ctx_python) factors = Vec(self._ctx_python)() exponents = VecZZ() # print("c", c) # print("factors", factors) # print("c", exponents) status = libgr.gr_factor(c._ref, factors._ref, exponents._ref, self._ref, 0, self._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return (c, factors, exponents) def is_square(self): """ Return whether self is a perfect square in its domain. >>> ZZ(3).is_square() False >>> ZZ(4).is_square() True >>> QQbar(3).is_square() True """ return self._unary_predicate(self, libgr.gr_is_square, "is_square") def __index__(self): n = fmpz_struct() nref = ctypes.byref(n) libflint.fmpz_init(nref) status = libgr.gr_get_fmpz(nref, self._ref, self._ctx) v = fmpz_to_python_int(nref) libflint.fmpz_clear(nref) if status: if status & GR_UNABLE: raise NotImplementedError(f"unable to convert x = {self} to integer in {self.parent()}") if status & GR_DOMAIN: raise ValueError(f"x = {self} is not an integer in {self.parent()}") return v def __int__(self): return self.trunc().__index__() def __float__(self): c = (ctypes.c_double * 1)() status = libgr.gr_get_d(c, self._ref, self._ctx) if status: if status & GR_UNABLE: raise NotImplementedError(f"x = {self} is not a float in {self.parent()}") if status & GR_DOMAIN: raise ValueError(f"x = {self} is not a float in {self.parent()}") return c[0] # todo def __complex__(self): return float(self.re()) + float(self.im()) * 1j def inv(self): """ Multiplicative inverse of this element. >>> QQ(3).inv() 1/3 >>> QQ(0).inv() Traceback (most recent call last): ... FlintDomainError: inv(x) is not an element of {Rational field (fmpq)} for {x = 0} """ return self._unary_op(self, libgr.gr_inv, "inv($x)") def sqrt(self): """ Square root of this element. >>> ZZ(4).sqrt() 2 >>> ZZ(2).sqrt() Traceback (most recent call last): ... FlintDomainError: sqrt(x) is not an element of {Integer ring (fmpz)} for {x = 2} >>> QQbar(2).sqrt() Root a = 1.41421 of a^2-2 >>> (QQ(25)/16).sqrt() 5/4 >>> QQbar(-1).sqrt() Root a = 1.00000*I of a^2+1 >>> RR(-1).sqrt() Traceback (most recent call last): ... FlintDomainError: sqrt(x) is not an element of {Real numbers (arb, prec = 53)} for {x = -1} >>> RF(-1).sqrt() nan """ return self._unary_op(self, libgr.gr_sqrt, "sqrt($x)") def rsqrt(self): """ Reciprocal square root of this element. >>> QQ(25).rsqrt() 1/5 """ return self._unary_op(self, libgr.gr_rsqrt, "rsqrt($x)") def numerator(self): r""" Numerator of this element. >>> (QQ(-2) / 3).numerator() -2 >>> ZZ(5).numerator() 5 """ return self._unary_op(self, libgr.gr_numerator, "numerator($x)") def denominator(self): r""" Denominator of this element. >>> (QQ(-2) / 3).denominator() 3 >>> ZZ(5).denominator() 1 Depending on the ring, the denominator need not be minimal. This is currently not the case for algebraic numbers: >>> a = ((2 + QQbar.i()) / 4) >>> a.numerator() Root a = 8.00000 + 4.00000*I of a^2-16*a+80 >>> a.denominator() 16 """ return self._unary_op(self, libgr.gr_denominator, "denominator($x)") def floor(self): r""" Floor function: closest integer in the direction of `-\infty`. >>> (QQ(3) / 2).floor() 1 >>> (QQ(3) / 2).ceil() 2 >>> (QQ(3) / 2).nint() 2 >>> (QQ(3) / 2).trunc() 1 """ return self._unary_op(self, libgr.gr_floor, "floor($x)") def ceil(self): r""" Ceiling function: closest integer in the direction of `+\infty`. >>> (QQ(3) / 2).ceil() 2 """ return self._unary_op(self, libgr.gr_ceil, "ceil($x)") def trunc(self): r""" Truncate to integer: closest integer in the direction of zero. >>> (QQ(3) / 2).trunc() 1 """ return self._unary_op(self, libgr.gr_trunc, "trunc($x)") def nint(self): r""" Nearest integer function: nearest integer, rounding to even on a tie. >>> (QQ(3) / 2).nint() 2 """ return self._unary_op(self, libgr.gr_nint, "nint($x)") def abs(self): return self._unary_op(self, libgr.gr_abs, "abs($x)") def conj(self): """ Complex conjugate. >>> QQbar.i().conj() Root a = -1.00000*I of a^2+1 >>> CC(-2).log().conj() ([0.693147180559945 +/- 4.12e-16] + [-3.141592653589793 +/- 3.39e-16]*I) >>> QQ(3).conj() 3 """ return self._unary_op(self, libgr.gr_conj, "conj($x)") def re(self): """ Real part. >>> QQ(1).re() 1 >>> (QQbar(-1) ** (QQ(1) / 3)).re() 1/2 """ return self._unary_op(self, libgr.gr_re, "re($x)") def im(self): """ Imaginary part. >>> QQ(1).im() 0 >>> (QQbar(-1) ** (QQ(1) / 3)).im() Root a = 0.866025 of 4*a^2-3 """ return self._unary_op(self, libgr.gr_im, "im($x)") def sgn(self): """ Sign function. >>> QQ(-5).sgn() -1 >>> CC(-10).sqrt().sgn() 1.000000000000000*I """ return self._unary_op(self, libgr.gr_sgn, "sgn($x)") def csgn(self): """ Real-valued extension of the sign function: gives the sign of the real part when nonzero, and the sign of the imaginary part when on the imaginary axis. >>> QQbar(-10).sqrt().csgn() 1 >>> (-QQbar(-10).sqrt()).csgn() -1 """ return self._unary_op(self, libgr.gr_csgn, "csgn($x)") def arg(self): """ >>> RR(1).arg() 0 >>> RR(-1).arg() [3.141592653589793 +/- 3.39e-16] >>> CC(1j).arg() [1.570796326794897 +/- 5.54e-16] >>> CC_ca.i().arg() 1.57080 {(a)/2 where a = 3.14159 [Pi]} >>> RR("+/- 0.1").arg() [+/- 3.15] """ return self._unary_op(self, libgr.gr_arg, "arg($x)") def mul_2exp(self, other): """ Exact multiplication by a dyadic number `2^y`. >>> QQ(3).mul_2exp(5) 96 >>> QQ(3).mul_2exp(-5) 3/32 >>> ZZ(100).mul_2exp(-2) 25 >>> ZZ(100).mul_2exp(-3) Traceback (most recent call last): ... FlintDomainError: mul_2exp(x, y) is not an element of {Integer ring (fmpz)} for {x = 100}, {y = -3} """ return self._binary_op_fmpz(self, other, libgr.gr_mul_2exp_fmpz, "mul_2exp($x, $y)") def exp(self): """ Exponential function. >>> RR(1).exp() [2.718281828459045 +/- 5.41e-16] >>> RR_ca(1).exp() 2.71828 {a where a = 2.71828 [Exp(1)]} >>> QQ(0).exp() 1 >>> QQ(1).exp() Traceback (most recent call last): ... FlintUnableError: failed to compute exp(x) in {Rational field (fmpq)} for {x = 1} >>> QQser.gen().exp() 1 + x + (1/2)*x^2 + (1/6)*x^3 + (1/24)*x^4 + (1/120)*x^5 + O(x^6) """ return self._unary_op(self, libgr.gr_exp, "exp($x)") def expm1(self): """ Exponential function minus 1. >>> RR("1e-10").expm1() [1.000000000050000e-10 +/- 3.86e-26] >>> CC(RR("1e-10")).expm1() [1.000000000050000e-10 +/- 3.86e-26] >>> RF("1e-10").expm1() 1.000000000050000e-10 >>> CF(RF("1e-10")).expm1() 1.000000000050000e-10 >>> QQ(0).expm1() 0 >>> QQ(1).expm1() Traceback (most recent call last): ... FlintUnableError: failed to compute expm1(x) in {Rational field (fmpq)} for {x = 1} >>> PowerSeriesModRing(RR, 4).gen().expm1() x + 0.5000000000000000*x^2 + [0.1666666666666667 +/- 7.04e-17]*x^3 (mod x^4) >>> (PowerSeriesModRing(RR, 2).gen() + 1).expm1() [1.718281828459045 +/- 5.41e-16] + [2.718281828459045 +/- 5.41e-16]*x (mod x^2) """ return self._unary_op(self, libgr.gr_expm1, "expm1($x)") def exp2(self): """ Exponential function with base 2. >>> QQ(5).exp2() 32 >>> RF(0.5).exp2() 1.414213562373095 """ return self._unary_op(self, libgr.gr_exp2, "exp2($x)") def exp10(self): """ Exponential function with base 10. >>> QQ(5).exp2() 32 >>> RF(0.5).exp10() 3.162277660168380 """ return self._unary_op(self, libgr.gr_exp10, "exp10($x)") def log(self): """ Natural logarithm. >>> QQ(1).log() 0 >>> QQ(2).log() Traceback (most recent call last): ... FlintUnableError: failed to compute log(x) in {Rational field (fmpq)} for {x = 2} >>> RF(2).log() 0.6931471805599453 >>> QQser(QQx([1, 1])).log() x + (-1/2)*x^2 + (1/3)*x^3 + (-1/4)*x^4 + (1/5)*x^5 + O(x^6) >>> QQser(1).log() 0 """ return self._unary_op(self, libgr.gr_log, "log($x)") def log1p(self): """ Natural logarithm with one added to the argument. >>> QQ(0).log1p() 0 >>> RF(-0.5).log1p() -0.6931471805599453 >>> RR(1).log1p() [0.693147180559945 +/- 4.12e-16] """ return self._unary_op(self, libgr.gr_log1p, "log1p($x)") def sin(self): return self._unary_op(self, libgr.gr_sin, "sin($x)") def cos(self): return self._unary_op(self, libgr.gr_cos, "cos($x)") def tan(self): return self._unary_op(self, libgr.gr_tan, "tan($x)") def sinh(self): return self._unary_op(self, libgr.gr_sinh, "sinh($x)") def cosh(self): return self._unary_op(self, libgr.gr_cosh, "cosh($x)") def tanh(self): return self._unary_op(self, libgr.gr_tanh, "tanh($x)") def atan(self): return self._unary_op(self, libgr.gr_atan, "atan($x)") def exp_pi_i(self): r""" `\exp(\pi i x)` evaluated at self. >>> (QQbar(1) / 3).exp_pi_i() Root a = 0.500000 + 0.866025*I of a^2-a+1 >>> (QQbar(2).sqrt()).exp_pi_i() Traceback (most recent call last): ... FlintDomainError: exp_pi_i(x) is not an element of {Complex algebraic numbers (qqbar)} for {x = Root a = 1.41421 of a^2-2} """ return self._unary_op(self, libgr.gr_exp_pi_i, "exp_pi_i($x)") def log_pi_i(self): r""" `\log(x) / (\pi i)` evaluated at self. >>> (QQbar(-1) ** (QQbar(7) / 5)).log_pi_i() -3/5 >>> (QQbar(1) / 2).log_pi_i() Traceback (most recent call last): ... FlintDomainError: log_pi_i(x) is not an element of {Complex algebraic numbers (qqbar)} for {x = 1/2} """ return self._unary_op(self, libgr.gr_log_pi_i, "log_pi_i($x)") def sin_pi(self): r""" `\sin(\pi x)` evaluated at self. >>> (QQbar(1) / 3).sin_pi() Root a = 0.866025 of 4*a^2-3 """ return self._unary_op(self, libgr.gr_sin_pi, "sin_pi($x)") def cos_pi(self): r""" `\cos(\pi x)` evaluated at self. >>> (QQbar(1) / 3).cos_pi() 1/2 """ return self._unary_op(self, libgr.gr_cos_pi, "cos_pi($x)") def tan_pi(self): r""" `\tan(\pi x)` evaluated at self. >>> (QQbar(1) / 3).tan_pi() Root a = 1.73205 of a^2-3 """ return self._unary_op(self, libgr.gr_tan_pi, "tan_pi($x)") def cot_pi(self): r""" `\cot(\pi x)` evaluated at self. >>> (QQbar(1) / 3).cot_pi() Root a = 0.577350 of 3*a^2-1 """ return self._unary_op(self, libgr.gr_cot_pi, "cot_pi($x)") def sec_pi(self): r""" `\sec(\pi x)` evaluated at self. >>> (QQbar(1) / 3).sec_pi() 2 """ return self._unary_op(self, libgr.gr_sec_pi, "sec_pi($x)") def csc_pi(self): r""" `\csc(\pi x)` evaluated at self. >>> (QQbar(1) / 3).csc_pi() Root a = 1.15470 of 3*a^2-4 """ return self._unary_op(self, libgr.gr_csc_pi, "csc_pi($x)") def asin_pi(self): return self._unary_op(self, libgr.gr_asin_pi, "asin_pi($x)") def acos_pi(self): return self._unary_op(self, libgr.gr_acos_pi, "acos_pi($x)") def atan_pi(self): return self._unary_op(self, libgr.gr_atan_pi, "atan_pi($x)") def acot_pi(self): return self._unary_op(self, libgr.gr_acot_pi, "acot_pi($x)") def asec_pi(self): return self._unary_op(self, libgr.gr_asec_pi, "asec_pi($x)") def acsc_pi(self): return self._unary_op(self, libgr.gr_acsc_pi, "acsc_pi($x)") def erf(self): return self._unary_op(self, libgr.gr_erf, "erf($x)") def erfi(self): return self._unary_op(self, libgr.gr_erfi, "erfi($x)") def erfc(self): return self._unary_op(self, libgr.gr_erfc, "erfc($x)") def gamma(self): return self._unary_op(self, libgr.gr_gamma, "gamma($x)") def lgamma(self): return self._unary_op(self, libgr.gr_lgamma, "lgamma($x)") def rgamma(self): return self._unary_op(self, libgr.gr_rgamma, "lgamma($x)") def digamma(self): return self._unary_op(self, libgr.gr_digamma, "digamma($x)") def zeta(self): return self._unary_op(self, libgr.gr_zeta, "zeta($x)") class IntegerRing_fmpz(gr_ctx): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_fmpz(self._ref) self._elem_type = fmpz class RationalField_fmpq(gr_ctx): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_fmpq(self._ref) self._elem_type = fmpq class GaussianIntegerRing_fmpzi(gr_ctx): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_fmpzi(self._ref) self._elem_type = fmpzi class QQbarField(gr_ctx): def set_limits(self, deg_limit=-1, bits_limit=-1): """ Set evaluation limits preventing the creation of excessively large (degree or bits) algebraic numbers. Warning: currently not all methods respect these limits. >>> QQbar Complex algebraic numbers (qqbar) >>> QQbar.set_limits(deg_limit=6, bits_limit=100) >>> QQbar Complex algebraic numbers (qqbar), deg_limit = 6, bits_limit = 100 >>> QQbar(2).sqrt() + QQbar(3).sqrt() + QQbar(5).sqrt() Traceback (most recent call last): ... FlintUnableError: failed to compute x + y in {Complex algebraic numbers (qqbar), deg_limit = 6, bits_limit = 100} for {x = Root a = 3.14626 of a^4-10*a^2+1}, {y = Root a = 2.23607 of a^2-5} >>> (QQbar(2).sqrt() + 1) ** 100 Traceback (most recent call last): ... FlintUnableError: failed to compute x ** y in {Complex algebraic numbers (qqbar), deg_limit = 6, bits_limit = 100} for {x = Root a = 2.41421 of a^2-2*a-1}, {y = 100} >>> QQbar.set_limits(deg_limit=-1, bits_limit=-1) >>> (QQbar(2).sqrt() + 1) ** 100 Root a = 1.89482e+38 of a^2-189482250299273866835746159841800035874*a+1 """ libgr._gr_ctx_qqbar_set_limits(self._ref, deg_limit, bits_limit) self._str = None class ComplexAlgebraicField_qqbar(QQbarField): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_complex_qqbar(self._ref) self._elem_type = qqbar class RealAlgebraicField_qqbar(QQbarField): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_real_qqbar(self._ref) self._elem_type = qqbar class gr_arb_ctx(gr_ctx): pass class RealField_arb(gr_arb_ctx): def __init__(self, prec=53): gr_ctx.__init__(self) libgr.gr_ctx_init_real_arb(self._ref, prec) self._elem_type = arb class ComplexField_acb(gr_arb_ctx): def __init__(self, prec=53): gr_ctx.__init__(self) libgr.gr_ctx_init_complex_acb(self._ref, prec) self._elem_type = acb _ca_options = [ "verbose", "print_flags", "mpoly_ord", "prec_limit", "qqbar_deg_limit", "low_prec", "smooth_limit", "lll_prec", "pow_limit", "use_gb", "gb_length_limit", "gb_poly_length_limit", "gb_poly_bits_limit", "vieta_limit", "trig_form"] class gr_ctx_ca(gr_ctx): def _set_options(self, kwargs): for w in kwargs: i = _ca_options.index(w) if i == -1: raise ValueError(f"unknown option {w}") libgr.gr_ctx_ca_set_option(self._ref, i, kwargs[w]) def options(self): opts = {_ca_options[i] : libgr.gr_ctx_ca_get_option(self._ref, i) for i in range(len(_ca_options))} return opts class RealAlgebraicField_ca(gr_ctx_ca): def __init__(self, **kwargs): gr_ctx.__init__(self) libgr.gr_ctx_init_real_algebraic_ca(self._ref) self._elem_type = ca self._set_options(kwargs) class ComplexAlgebraicField_ca(gr_ctx_ca): def __init__(self, **kwargs): gr_ctx.__init__(self) libgr.gr_ctx_init_complex_algebraic_ca(self._ref) self._elem_type = ca self._set_options(kwargs) class RealField_ca(gr_ctx_ca): def __init__(self, **kwargs): gr_ctx.__init__(self) libgr.gr_ctx_init_real_ca(self._ref) self._elem_type = ca self._set_options(kwargs) class ComplexField_ca(gr_ctx_ca): def __init__(self, **kwargs): gr_ctx.__init__(self) libgr.gr_ctx_init_complex_ca(self._ref) self._elem_type = ca self._set_options(kwargs) class ComplexExtended_ca(gr_ctx_ca): def __init__(self, **kwargs): gr_ctx.__init__(self) libgr.gr_ctx_init_complex_extended_ca(self._ref) self._elem_type = ca self._set_options(kwargs) class PolynomialRing_gr_poly(gr_ctx): def __init__(self, coefficient_ring, var=None): assert isinstance(coefficient_ring, gr_ctx) gr_ctx.__init__(self) #if libgr.gr_ctx_is_ring(coefficient_ring._ref) != T_TRUE: # raise ValueError("coefficient structure must be a ring") libgr.gr_ctx_init_gr_poly(self._ref, coefficient_ring._ref) coefficient_ring._refcount += 1 self._coefficient_ring = coefficient_ring self._elem_type = gr_poly if var is not None: self._set_gen_name(var) def __del__(self): self._coefficient_ring._decrement_refcount() class PowerSeriesRing_gr_series(gr_ctx): def __init__(self, coefficient_ring, prec=6, var=None): """ >>> PowerSeriesRing(QQ, 5, var="y") Power series over Rational field (fmpq) with precision O(y^5) """ assert isinstance(coefficient_ring, gr_ctx) gr_ctx.__init__(self) libgr.gr_ctx_init_gr_series(self._ref, coefficient_ring._ref, prec) coefficient_ring._refcount += 1 self._coefficient_ring = coefficient_ring self._elem_type = gr_series if var is not None: self._set_gen_name(var) def __del__(self): self._coefficient_ring._decrement_refcount() class PowerSeriesModRing_gr_series(gr_ctx): def __init__(self, coefficient_ring, mod=6, var=None): assert isinstance(coefficient_ring, gr_ctx) gr_ctx.__init__(self) libgr.gr_ctx_init_gr_series_mod(self._ref, coefficient_ring._ref, mod) coefficient_ring._refcount += 1 self._coefficient_ring = coefficient_ring self._elem_type = gr_series if var is not None: self._set_gen_name(var) def __del__(self): self._coefficient_ring._decrement_refcount() class fmpz(gr_elem): _struct_type = fmpz_struct @staticmethod def _default_context(): return ZZ def __index__(self): return fmpz_to_python_int(self._ref) def __int__(self): return fmpz_to_python_int(self._ref) def is_prime(self): return bool(libflint.fmpz_is_prime(self._ref)) class fmpq(gr_elem): _struct_type = fmpq_struct @staticmethod def _default_context(): return QQ class fmpzi(gr_elem): _struct_type = fmpzi_struct @staticmethod def _default_context(): return ZZi class qqbar(gr_elem): """ Wrapper around the qqbar type, representing an algebraic number. >>> (qqbar(2).sqrt() / qqbar(-2).sqrt()) ** 2 -1 >>> qqbar(0.5) == qqbar(1) / 2 True >>> qqbar(0.1) == qqbar(1) / 10 False >>> qqbar(3+4j) Root a = 3.00000 + 4.00000*I of a^2-6*a+25 >>> qqbar(3+4j).root(5) Root a = 1.35607 + 0.254419*I of a^10-6*a^5+25 >>> qqbar(3+4j).root(5) ** 5 Root a = 3.00000 + 4.00000*I of a^2-6*a+25 The constructor can evaluate fexpr symbolic expressions provided that the expressions are constant and composed strictly of algebraic-valued basic operations applied to algebraic numbers. >>> fexpr.inject() >>> qqbar(Pow(0, 0)) 1 >>> qqbar(Sqrt(2) * Abs(1+1j) + (+Re(3-4j)) + (-Im(5+6j))) -1 >>> qqbar((Floor(Sqrt(1000)) + Ceil(Sqrt(1000)) + Sign(1+1j) / Sign(1-1j) + Csgn(1j) + Conjugate(1j)) ** Div(-1, 3)) 1/4 >>> [qqbar(RootOfUnity(3)), qqbar(RootOfUnity(3,2))] [Root a = -0.500000 + 0.866025*I of a^2+a+1, Root a = -0.500000 - 0.866025*I of a^2+a+1] >>> qqbar(Decimal("0.125")) == qqbar(125)/1000 True >>> qqbar(Decimal("-2.7e5")) == -270000 True """ _struct_type = qqbar_struct @staticmethod def _default_context(): return QQbar # todo: generic def root(self, n): return self ** (qqbar(1) / n) def fexpr(self, formula=True, root_index=False, serialize=False, gaussians=True, quadratics=True, cyclotomics=True, cubics=True, quartics=True, quintics=True, depression=True, deflation=True, separation=True): """ """ res = fexpr() if serialize: libcalcium.qqbar_get_fexpr_repr(res, self) return res if formula: flags = 0 if gaussians: flags |= 1 if quadratics: flags |= 2 if cyclotomics: flags |= 4 if cubics: flags |= 8 if quartics: flags |= 16 if quintics: flags |= 32 if depression: flags |= 64 if deflation: flags |= 128 if separation: flags |= 256 if libcalcium.qqbar_get_fexpr_formula(res, self, flags): return res if root_index: libcalcium.qqbar_get_fexpr_root_indexed(res, self) return res libcalcium.qqbar_get_fexpr_root_nearest(res, self) return res def fexpr_repr(self): """ """ res = fexpr() libcalcium.qqbar_get_fexpr_repr(res, self) return res class ca(gr_elem): _struct_type = ca_struct @staticmethod def _default_context(): return CC_ca class arb(gr_elem): _struct_type = arb_struct @staticmethod def _default_context(): return RR_arb class acb(gr_elem): _struct_type = acb_struct @staticmethod def _default_context(): return CC_acb class gr_arf_ctx(gr_ctx): pass class RealFloat_arf(gr_arf_ctx): def __init__(self, prec=53): gr_ctx.__init__(self) libgr.gr_ctx_init_real_float_arf(self._ref, prec) self._elem_type = arf class ComplexFloat_acf(gr_arf_ctx): def __init__(self, prec=53): gr_ctx.__init__(self) libgr.gr_ctx_init_complex_float_acf(self._ref, prec) self._elem_type = acf class arf(gr_elem): _struct_type = arf_struct @staticmethod def _default_context(): return RF def __hash__(self): # todo return hash(float(str(self))) class acf(gr_elem): _struct_type = acf_struct @staticmethod def _default_context(): return CF class IntegersMod_nmod(gr_ctx): def __init__(self, n): n = self._as_ui(n) assert n >= 1 gr_ctx.__init__(self) libgr.gr_ctx_init_nmod(self._ref, n) self._elem_type = nmod class nmod(gr_elem): _struct_type = nmod_struct """ .. function:: int gr_ctx_fq_prime(fmpz_t p, gr_ctx_t ctx) .. function:: int gr_ctx_fq_degree(slong * deg, gr_ctx_t ctx) .. function:: int gr_ctx_fq_order(fmpz_t q, gr_ctx_t ctx) """ class FiniteField_base(gr_ctx): def prime(self): res = ZZ() status = libgr.gr_ctx_fq_prime(res._ref, self._ref, self._ref) assert not status return res def degree(self): res = ZZ() c = c_slong() status = libgr.gr_ctx_fq_degree(ctypes.byref(c), self._ref, self._ref) assert not status libflint.fmpz_set_si(res._ref, c) return res def order(self): res = ZZ() status = libgr.gr_ctx_fq_order(res._ref, self._ref, self._ref) assert not status return res class FiniteField_fq(FiniteField_base): def __init__(self, p, n, var=None): gr_ctx.__init__(self) p = ZZ(p) n = int(n) assert p.is_prime() assert n >= 1 if var is not None: var = ctypes.c_char_p(str(var).encode('ascii')) libgr.gr_ctx_init_fq(self._ref, p._ref, n, var) self._elem_type = fq class FiniteField_fq_nmod(FiniteField_base): def __init__(self, p, n, var=None): gr_ctx.__init__(self) p = self._as_ui(p) n = int(n) assert ZZ(p).is_prime() assert n >= 1 if var is not None: var = ctypes.c_char_p(str(var).encode('ascii')) libgr.gr_ctx_init_fq_nmod(self._ref, p, n, var) self._elem_type = fq_nmod class FiniteField_fq_zech(FiniteField_base): def __init__(self, p, n, var=None): gr_ctx.__init__(self) p = self._as_ui(p) n = int(n) assert ZZ(p).is_prime() assert n >= 1 if var is not None: var = ctypes.c_char_p(str(var).encode('ascii')) libgr.gr_ctx_init_fq_zech(self._ref, p, n, var) self._elem_type = fq_zech class fq_elem(gr_elem): #def frobenius(self): # return self._binary_op_si(self, libgr.gr_fq_frobenius, "frobenius") def multiplicative_order(self): return self._unary_op_get_fmpz(self, libgr.gr_fq_multiplicative_order, "multiplicative_order") def norm(self): return self._unary_op_get_fmpz(self, libgr.gr_fq_norm, "norm") def trace(self): return self._unary_op_get_fmpz(self, libgr.gr_fq_trace, "trace") def is_primitive(self): return self._unary_predicate(self, libgr.gr_fq_is_primitive, "is_primitive") def pth_root(self): return self._unary_op(self, libgr.gr_fq_pth_root, "pth_root") class fq(fq_elem): _struct_type = fq_struct class fq_nmod(fq_elem): _struct_type = fq_nmod_struct class fq_zech(fq_elem): _struct_type = fq_zech_struct class NumberField_nf(gr_ctx): def __init__(self, pol, var=None): pol = ZZx(pol) # assert pol.is_irreducible() gr_ctx.__init__(self) libgr.gr_ctx_init_nf_fmpz_poly(self._ref, pol._ref) self._elem_type = nf_elem if var is not None: self._set_gen_name(var) class nf_elem(gr_elem): _struct_type = nf_elem_struct class gr_poly(gr_elem): _struct_type = gr_poly_struct def __init__(self, val=None, context=None, random=False): # todo: also iterables if isinstance(val, (list, tuple)): gr_elem.__init__(self, None, context) coefficient_ring = self.parent()._coefficient_ring val = [coefficient_ring(c) for c in val] for i in range(len(val)): status = libgr.gr_poly_set_coeff_scalar(self._ref, i, val[i]._ref, coefficient_ring._ref) if status: raise NotImplementedError else: gr_elem.__init__(self, val, context) # todo: refactor if random: libgr.gr_randtest(self._ref, ctypes.byref(_flint_rand), self._ctx) def __len__(self): return self._data.length def __getitem__(self, i): n = len(self) R = self.parent()._coefficient_ring c = R() status = libgr.gr_poly_get_coeff_scalar(c._ref, self._ref, i, R._ref) if status: raise NotImplementedError return c def __iter__(self): for i in range(len(self)): yield self[i] def __call__(self, x, algorithm=None): f_R = self.parent()._coefficient_ring x_R = x.parent() res = x_R() if f_R is x_R: if algorithm is None: status = libgr.gr_poly_evaluate(res._ref, self._ref, x._ref, x_R._ref, f_R._ref) elif algorithm == "rectangular": status = libgr.gr_poly_evaluate_rectangular(res._ref, self._ref, x._ref, x_R._ref, f_R._ref) else: raise ValueError else: if algorithm is None: status = libgr.gr_poly_evaluate_other_horner(res._ref, self._ref, x._ref, x_R._ref, f_R._ref) elif algorithm == "rectangular": status = libgr.gr_poly_evaluate_other_rectangular(res._ref, self._ref, x._ref, x_R._ref, f_R._ref) else: raise ValueError if status: raise NotImplementedError return res def is_monic(self): """ >>> RRx([2,3,4]).is_monic() False >>> RRx([2,3,1]).is_monic() True >>> RRx([]).is_monic() False """ R = self.parent()._coefficient_ring truth = libgr.gr_poly_is_monic(self._ref, R._ref) def op(*args): return truth return gr_elem._unary_predicate(self, op, "is_monic") def monic(self): """ Return self rescaled to a monic polynomial. >>> f = RRx([1,RR.pi()]) >>> f.monic() [0.318309886183791 +/- 4.43e-16] + x >>> RRx([]).monic() # the zero polynomial cannot be made monic Traceback (most recent call last): ... ValueError >>> (f - f).monic() # unknown whether it is the zero polynomial Traceback (most recent call last): ... NotImplementedError """ Rx = self.parent() R = Rx._coefficient_ring res = Rx() status = libgr.gr_poly_make_monic(res._ref, self._ref, R._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def derivative(self): Rx = self.parent() R = Rx._coefficient_ring res = Rx() status = libgr.gr_poly_derivative(res._ref, self._ref, R._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def integral(self): Rx = self.parent() R = Rx._coefficient_ring res = Rx() status = libgr.gr_poly_integral(res._ref, self._ref, R._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def roots(self, domain=None): """ Computes the roots in the coefficient ring of this polynomial, returning a tuple (``roots``, ``multiplicities``). If the ring is not algebraically closed, the sum of multiplicities can be smaller than the degree of the polynomial. If ``domain`` is given, returns roots in that ring instead. >>> (ZZx([3,2]) * ZZx([15,1])**2 * ZZx([-10,1])).roots() ([10, -15], [1, 2]) >>> ZZx([1]).roots() ([], []) We consider roots of the zero polynomial to be ill-defined: >>> ZZx([]).roots() Traceback (most recent call last): ... ValueError We construct an integer polynomial with rational, real algebraic and complex algebraic roots and extract its roots over different domains: >>> f = ZZx([-2,0,1]) * ZZx([1, 0, 1]) * ZZx([3, 2])**2 >>> f.roots() # integer roots (there are none) ([], []) >>> f.roots(domain=QQ) # rational roots ([-3/2], [2]) >>> f.roots(domain=AA) # real algebraic roots ([Root a = 1.41421 of a^2-2, Root a = -1.41421 of a^2-2, -3/2], [1, 1, 2]) >>> f.roots(domain=QQbar) # complex algebraic roots ([Root a = 1.00000*I of a^2+1, Root a = -1.00000*I of a^2+1, Root a = 1.41421 of a^2-2, Root a = -1.41421 of a^2-2, -3/2], [1, 1, 1, 1, 2]) >>> f.roots(domain=RR) # real ball roots ([[-1.414213562373095 +/- 4.89e-17], [1.414213562373095 +/- 4.89e-17], -1.500000000000000], [1, 1, 2]) >>> f.roots(domain=CC) # complex ball roots ([[-1.414213562373095 +/- 4.89e-17], [1.414213562373095 +/- 4.89e-17], 1.000000000000000*I, -1.000000000000000*I, -1.500000000000000], [1, 1, 1, 1, 2]) >>> f.roots(RF) # real floating-point roots ([-1.414213562373095, 1.414213562373095, -1.500000000000000], [1, 1, 2]) >>> f.roots(CF) # complex floating-point roots ([-1.414213562373095, 1.414213562373095, 1.000000000000000*I, -1.000000000000000*I, -1.500000000000000], [1, 1, 1, 1, 2]) Calcium examples/tests: >>> PolynomialRing(CC_ca)([2,11,20,12]).roots() ([-0.666667 {-2/3}, -0.500000 {-1/2}], [1, 2]) >>> PolynomialRing(RR_ca)([1,-1,0,1]).roots() ([-1.32472 {a where a = -1.32472 [a^3-a+1=0]}], [1]) >>> PolynomialRing(CC_ca)([1,-1,0,1]).roots() ([-1.32472 {a where a = -1.32472 [a^3-a+1=0]}, 0.662359 + 0.562280*I {a where a = 0.662359 + 0.562280*I [a^3-a+1=0]}, 0.662359 - 0.562280*I {a where a = 0.662359 - 0.562280*I [a^3-a+1=0]}], [1, 1, 1]) """ Rx = self.parent() R = Rx._coefficient_ring mult = VecZZ() if domain is None: roots = Vec(R)() status = libgr.gr_poly_roots(roots._ref, mult._ref, self._ref, 0, R._ref) else: C = domain roots = Vec(C)() status = libgr.gr_poly_roots_other(roots._ref, mult._ref, self._ref, R._ref, 0, C._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return (roots, mult) def _series_op(self, n, op, rstr): Rx = self.parent() R = Rx._coefficient_ring res = Rx() n = int(n) status = op(res._ref, self._ref, n, R._ref) if status: return _handle_error(Rx, status, rstr, self, n) return res def _series_op_fmpz_fmpq_overloads(self, other, n, op, op_fmpz, op_fmpq, rstr): Rx = self.parent() R = Rx._coefficient_ring res = Rx() n = int(n) # todo: variants other = QQ(other) status = op_fmpq(res._ref, self._ref, other._ref, n, R._ref) if status: return _handle_error(Rx, status, rstr, self, other, n) return res def _series_binary_op(self, other, n, op, rstr): Rx = self.parent() R = Rx._coefficient_ring # fixme other = Rx(other) res = Rx() n = int(n) status = op(res._ref, self._ref, other._ref, n, R._ref) if status: return _handle_error(Rx, status, rstr, self, n) return res def inv_series(self, n): """ Reciprocal of this polynomial viewed as a power series, truncated to length n. >>> ZZx([1,2,3]).inv_series(10) 22*x^9+73*x^8-56*x^7+13*x^6+10*x^5-11*x^4+4*x^3+x^2-2*x+1 >>> ZZx([2,3,4]).inv_series(5) Traceback (most recent call last): ... FlintDomainError: f.inv_series(n) is not an element of {Polynomials over integers (fmpz_poly)} for {f = 4*x^2+3*x+2}, {n = 5} >>> QQx([2,3,4]).inv_series(5) (1/2) + (-3/4)*x + (1/8)*x^2 + (21/16)*x^3 + (-71/32)*x^4 """ return self._series_op(n, libgr.gr_poly_inv_series, "$f.inv_series($n)") def div_series(self, other, n): return self._series_binary_op(other, n, libgr.gr_poly_div_series, "$f.div_series(%g, $n)") def log_series(self, n): """ Logarithm of this polynomial viewed as a power series, truncated to length n. >>> QQx([1,1]).log_series(8) x + (-1/2)*x^2 + (1/3)*x^3 + (-1/4)*x^4 + (1/5)*x^5 + (-1/6)*x^6 + (1/7)*x^7 >>> RRx([2,1]).log_series(3) [0.693147180559945 +/- 4.12e-16] + 0.5000000000000000*x - 0.1250000000000000*x^2 >>> RRx([0,0]).log_series(3) Traceback (most recent call last): ... FlintDomainError: f.log_series(n) is not an element of {Ring of polynomials over Real numbers (arb, prec = 53)} for {f = 0}, {n = 3} """ return self._series_op(n, libgr.gr_poly_log_series, "$f.log_series($n)") def exp_series(self, n): """ Exponential of this polynomial viewed as a power series, truncated to length n. >>> QQx([0,1]).exp_series(8) 1 + x + (1/2)*x^2 + (1/6)*x^3 + (1/24)*x^4 + (1/120)*x^5 + (1/720)*x^6 + (1/5040)*x^7 >>> QQx([1,1]).exp_series(2) Traceback (most recent call last): ... FlintUnableError: failed to compute f.exp_series(n) in {Ring of polynomials over Rational field (fmpq)} for {f = 1 + x}, {n = 2} >>> RRx([1,1]).exp_series(2) [2.718281828459045 +/- 5.41e-16] + [2.718281828459045 +/- 5.41e-16]*x >>> RRx([2,3]).log_series(3).exp_series(3) [2.000000000000000 +/- 6.97e-16] + [3.00000000000000 +/- 1.61e-15]*x + [+/- 1.49e-15]*x^2 """ return self._series_op(n, libgr.gr_poly_exp_series, "$f.exp_series($n)") def pow_series(self, other, n): """ Power of this polynomial viewed as a power series, truncated to length n. >>> QQx([4,3,2]).pow_series(QQ(1) / 2, 6) 2 + (3/4)*x + (23/64)*x^2 + (-69/512)*x^3 + (299/16384)*x^4 + (2277/131072)*x^5 >>> (QQx([4,3,2]) ** 2).pow_series(QQ(1) / 2, 6) 4 + 3*x + 2*x^2 """ # todo return self._series_op_fmpz_fmpq_overloads(other, n, None, None, libgr.gr_poly_pow_series_fmpq_recurrence, "$f.pow_series($g, $n)") def atan_series(self, n): """ Inverse tangent of this polynomial viewed as a power series, truncated to length n. >>> f = PolynomialRing(CC_ca)([2,3,4]) >>> 2*f.atan_series(5) - ((2*f).div_series(1-f**2, 5)).atan_series(5) == CC_ca.pi() True """ return self._series_op(n, libgr.gr_poly_atan_series, "$f.atan_series($n)") def atanh_series(self, n): return self._series_op(n, libgr.gr_poly_atanh_series, "$f.atanh_series($n)") def sqrt_series(self, n): return self._series_op(n, libgr.gr_poly_sqrt_series, "$f.sqrt_series($n)") def rsqrt_series(self, n): return self._series_op(n, libgr.gr_poly_rsqrt_series, "$f.rsqrt_series($n)") class gr_series(gr_elem): _struct_type = gr_series_struct def __init__(self, val=None, error=None, context=None, random=False): gr_elem.__init__(self, val, context, random) if error is not None: raise NotImplementedError class ModularGroup_psl2z(gr_ctx_ca): def __init__(self, **kwargs): gr_ctx.__init__(self) libgr.gr_ctx_init_psl2z(self._ref) self._elem_type = psl2z # todo: C function def generators(self): S = self() T = self() S._data.a = 0 S._data.b = -1 S._data.c = 1 S._data.d = 0 T._data.b = 1 return (S, T) class psl2z(gr_elem): _struct_type = psl2z_struct class DirichletGroup_dirichlet_char(gr_ctx_ca): """ Group of Dirichlet characters of given modulus. >>> G = DirichletGroup(10) >>> G.q 10 >>> len(G) 4 >>> [G(i) for i in [1,3,7,9]] [chi_10(1, .), chi_10(3, .), chi_10(7, .), chi_10(9, .)] """ def __init__(self, q, **kwargs): # todo: automatic range checking with ctypes int -> c_ulong cast? if q <= 0: raise ValueError(f"modulus must not be zero") if q > UWORD_MAX: raise NotImplementedError(f"only word-size moduli are supported") gr_ctx.__init__(self) status = libgr.gr_ctx_init_dirichlet_group(self._ref, q) if status & GR_UNABLE: raise NotImplementedError(f"modulus with prime factor p > 10^16 is not currently supported") if status & GR_DOMAIN: raise ValueError(f"modulus must not be zero") self._elem_type = dirichlet_char self.q = int(q) # for easy access def __len__(self): libarb.dirichlet_group_size.restype = c_slong libarb.dirichlet_group_size.argtypes = (ctypes.c_void_p,) return libarb.dirichlet_group_size(libgr.gr_ctx_data_as_ptr(self._ref)) def __call__(self, n): n = int(n) assert 1 <= n <= max(self.q, 2) - 1 assert ZZ(n).gcd(self.q) == 1 x = dirichlet_char(context=self) libarb.dirichlet_char_log.argtypes = (ctypes.c_void_p, ctypes.c_void_p, c_ulong) libarb.dirichlet_char_log(x._ref, libgr.gr_ctx_data_as_ptr(self._ref), n) return x class dirichlet_char(gr_elem): _struct_type = dirichlet_char_struct class SymmetricGroup_perm(gr_ctx_ca): def __init__(self, n, **kwargs): # todo: automatic range checking with ctypes int -> c_ulong cast? if n < 0: raise ValueError(f"n must be positive") if n > WORD_MAX: raise NotImplementedError(f"only word-size moduli n are supported") gr_ctx.__init__(self) libgr.gr_ctx_init_perm(self._ref, n) self._elem_type = perm class perm(gr_elem): _struct_type = perm_struct class Mat(gr_ctx): """ Parent class for matrix domains. There are two kinds of matrix domains: - Mat(R), the set of matrices of any size over the domain R. - Mat(R, n, m), the set of n x m matrices over the domain R. If R is a ring and n = m, then this is also a ring. While Mat(R) may be more convenient, e.g. for representing linear transformations of arbitrary dimension under a single parent, fixed-shape matrix domains have advantages such as allowing automatic conversion from scalars to scalar matrices of the right size. >>> Mat(ZZ) Matrices (any shape) over Integer ring (fmpz) >>> Mat(ZZ, 2) Ring of 2 x 2 matrices over Integer ring (fmpz) >>> Mat(ZZ, 2, 3) Space of 2 x 3 matrices over Integer ring (fmpz) >>> Mat(ZZ)([[1, 2, 3], [4, 5, 6]]) [[1, 2, 3], [4, 5, 6]] >>> Mat(ZZ, 2, 2)(5) [[5, 0], [0, 5]] """ def __init__(self, element_domain, nrows=None, ncols=None): assert isinstance(element_domain, gr_ctx) assert (nrows is None) or (0 <= nrows <= WORD_MAX) assert (ncols is None) or (0 <= ncols <= WORD_MAX) gr_ctx.__init__(self) if nrows is None and ncols is None: libgr.gr_ctx_init_matrix_domain(self._ref, element_domain._ref) else: if ncols is None: ncols = nrows libgr.gr_ctx_init_matrix_space(self._ref, element_domain._ref, nrows, ncols) self._element_ring = element_domain self._elem_type = gr_mat self._element_ring._refcount += 1 def __del__(self): self._element_ring._decrement_refcount() def MatrixRing(element_ring, n): assert isinstance(element_ring, gr_ctx) assert 0 <= n <= WORD_MAX if libgr.gr_ctx_is_ring(element_ring._ref) != T_TRUE: raise ValueError("element structure must be a ring") return Mat(element_ring, n) class gr_mat(gr_elem): _struct_type = gr_mat_struct def __init__(self, *args, **kwargs): context = kwargs['context'] gr_elem.__init__(self, None, context) element_ring = context._element_ring if kwargs.get('random'): libgr.gr_randtest(self._ref, ctypes.byref(_flint_rand), self._ctx) return if len(args) == 1: val = args[0] if val is not None: status = GR_UNABLE if isinstance(val, (list, tuple)): m = len(val) n = 0 if m != 0: if not isinstance(val[0], (list, tuple)): raise TypeError("single input to gr_mat must be a list of lists") n = len(val[0]) for i in range(1, m): if len(val[i]) != n: raise ValueError("input rows have different lengths") status = libgr._gr_mat_check_resize(self._ref, m, n, self._ctx) if not status: for i in range(m): row = val[i] for j in range(n): x = element_ring(row[j]) ijptr = libgr.gr_mat_entry_ptr(self._ref, i, j, x._ctx) status |= libgr.gr_set(ijptr, x._ref, x._ctx) elif libgr.gr_ctx_matrix_is_fixed_size(self._ctx) == T_TRUE: if not isinstance(val, gr_elem): val = element_ring(val) status = libgr.gr_set_other(self._ref, val._ref, val._ctx, self._ctx) elif isinstance(val, gr_mat): status = libgr.gr_set_other(self._ref, val._ref, val._ctx, self._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError elif len(args) in (2, 3): if len(args) == 2: m, n = args entries = None else: m, n, entries = args entries = list(entries) if len(entries) != m*n: raise ValueError("list of entries has the wrong length") status = libgr._gr_mat_check_resize(self._ref, m, n, self._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError("wrong matrix shape for this domain") if entries is None: status = libgr.gr_mat_zero(self._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError else: for i in range(m): for j in range(n): x = element_ring(entries[i*n + j]) ijptr = libgr.gr_mat_entry_ptr(self._ref, i, j, x._ctx) status = libgr.gr_set(ijptr, x._ref, x._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError def nrows(self): return self._data.r def ncols(self): return self._data.c def shape(self): return (self._data.r, self._data.c) def __getitem__(self, ij): i, j = ij i = int(i) j = int(j) assert 0 <= i < self.nrows() assert 0 <= j < self.ncols() element_ring = self.parent()._element_ring res = element_ring() ijptr = libgr.gr_mat_entry_ptr(self._ref, i, j, res._ctx) status = libgr.gr_set(res._ref, ijptr, res._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def __setitem__(self, ij, v): i, j = ij i = int(i) j = int(j) assert 0 <= i < self.nrows() assert 0 <= j < self.ncols() element_ring = self.parent()._element_ring # todo: avoid copy x = element_ring(v) ijptr = libgr.gr_mat_entry_ptr(self._ref, i, j, x._ctx) status = libgr.gr_set(ijptr, x._ref, x._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return x def det(self, algorithm=None): """ Determinant of this matrix. >>> MatZZ(3, 3, ZZ.fac_vec(9)).det() 233280 >>> MatRR(3, 3, ZZ.fac_vec(9)).det() 233280.0000000000 >>> MatRR(3, 3, ZZ.fac_vec(9)).det(algorithm="lu") [233280.000000000 +/- 2.67e-10] """ element_ring = self.parent()._element_ring res = element_ring() if algorithm is None: status = libgr.gr_mat_det(res._ref, self._ref, element_ring._ref) elif algorithm == "lu": status = libgr.gr_mat_det_lu(res._ref, self._ref, element_ring._ref) elif algorithm == "fflu": status = libgr.gr_mat_det_fflu(res._ref, self._ref, element_ring._ref) elif algorithm == "berkowitz": status = libgr.gr_mat_det_berkowitz(res._ref, self._ref, element_ring._ref) elif algorithm == "cofactor": status = libgr.gr_mat_det_cofactor(res._ref, self._ref, element_ring._ref) else: raise ValueError("unknown algorithm") if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def trace(self): """ >>> MatZZ([[3,4],[5,6]]).trace() 9 """ element_ring = self.parent()._element_ring res = element_ring() status = libgr.gr_mat_trace(res._ref, self._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def rank(self): """ >>> MatZZ([[1,2,3],[4,5,6],[7,8,9]]).rank() 2 >>> Mat(CC_ca)([[1, 0, 0], [0, 1-(CC_ca(2)**-10).exp(), 0]]).rank() 2 >>> Mat(CC_ca)([[1, 0, 0], [0, 1-(CC_ca(2)**-10000).exp(), 0]]).rank() Traceback (most recent call last): ... NotImplementedError """ element_ring = self.parent()._element_ring r = (ctypes.c_long * 1)() status = libgr.gr_mat_rank(r, self._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return ZZ(r[0]) def solve(self, B): """ Solves `AX = B` where `A` is given by self. Allows the system to be singular, undetermined, or overdetermined. If there are multiple solutions, an arbitrary solution is returned. This function currently only makes sense over fields. >>> A = MatQQ([[1,2,0], [0,1,0], [2,-2,0]]) >>> B = MatQQ([[9], [2], [6]]) >>> A.nonsingular_solve(B) Traceback (most recent call last): ... ValueError >>> A.solve(B) [[5], [2], [0]] >>> X = A.solve(B) >>> X [[5], [2], [0]] >>> A * X == B True """ r = self.nrows() c = self.ncols() if r != c or r != B.nrows(): raise ValueError element_ring = self.parent()._element_ring X = self.parent()(r, B.ncols()) status = libgr.gr_mat_solve_field(X._ref, self._ref, B._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return X def nonsingular_solve(self, B, algorithm=None): """ Proves invertibility of A (self) over the corresponding fraction field and solves `AX = B`. >>> A = MatQQ([[1,2],[3,4]]) >>> B = MatQQ([[4],[5]]) >>> X = A.nonsingular_solve(B) >>> A * X == B True The optional algorithm can be "lu" or "fflu". >>> MatZZ([[3,5],[1,2]]).nonsingular_solve(MatZZ([[1],[2]]), algorithm="fflu") [[-8], [5]] """ r = self.nrows() c = self.ncols() if r != c or r != B.nrows(): raise ValueError element_ring = self.parent()._element_ring X = self.parent()(r, B.ncols()) if algorithm is None: status = libgr.gr_mat_nonsingular_solve(X._ref, self._ref, B._ref, element_ring._ref) elif algorithm == "lu": status = libgr.gr_mat_nonsingular_solve_lu(X._ref, self._ref, B._ref, element_ring._ref) elif algorithm == "fflu": status = libgr.gr_mat_nonsingular_solve_fflu(X._ref, self._ref, B._ref, element_ring._ref) else: raise ValueError("unknown algorithm") if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return X def nonsingular_solve_den(self, B): """ Proves invertibility of A (self) over the corresponding fraction field and solves `A(X/d) = B`. >>> A = MatZZ([[3,4],[5,8]]); B = MatZZ([[1],[1]]) >>> X, d = A.nonsingular_solve_den(B) >>> X [[4], [-2]] >>> d 4 >>> A*X == B*d True """ r = self.nrows() c = self.ncols() if r != c or r != B.nrows(): raise ValueError element_ring = self.parent()._element_ring X = self.parent()(r, B.ncols()) den = element_ring() status = libgr.gr_mat_nonsingular_solve_den(X._ref, den._ref, self._ref, B._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return X, den def pascal(self, triangular=0): """ Returns a Pascal matrix of the same shape. >>> MatZZ(4,5).pascal() [[1, 1, 1, 1, 1], [1, 2, 3, 4, 5], [1, 3, 6, 10, 15], [1, 4, 10, 20, 35]] >>> MatZZ(4,5).pascal(1) [[1, 1, 1, 1, 1], [0, 1, 2, 3, 4], [0, 0, 1, 3, 6], [0, 0, 0, 1, 4]] >>> MatZZ(4,5).pascal(-1) [[1, 0, 0, 0, 0], [1, 1, 0, 0, 0], [1, 2, 1, 0, 0], [1, 3, 3, 1, 0]] """ element_ring = self.parent()._element_ring res = self.parent()(self.nrows(), self.ncols()) status = libgr.gr_mat_pascal(res._ref, triangular, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def stirling(self, kind=0): """ Returns a Stirling matrix of the same shape. >>> MatZZ(4,5).stirling() [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 1, 0, 0], [0, 2, 3, 1, 0]] >>> MatZZ(4,5).stirling(1) [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, -1, 1, 0, 0], [0, 2, -3, 1, 0]] >>> MatZZ(4,5).stirling(2) [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 1, 0, 0], [0, 1, 3, 1, 0]] """ element_ring = self.parent()._element_ring res = self.parent()(self.nrows(), self.ncols()) status = libgr.gr_mat_stirling(res._ref, kind, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def hilbert(self): """ Returns a Hilbert matrix of the same shape. >>> MatQQ(2,3).hilbert() [[1, 1/2, 1/3], [1/2, 1/3, 1/4]] """ element_ring = self.parent()._element_ring res = self.parent()(self.nrows(), self.ncols()) status = libgr.gr_mat_hilbert(res._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def hadamard(self): """ Returns a Hadamard matrix of the same shape. >>> MatZZ(4,4).hadamard() [[1, 1, 1, 1], [1, -1, 1, -1], [1, 1, -1, -1], [1, -1, -1, 1]] >>> MatZZ(3,3).hadamard() Traceback (most recent call last): ... ValueError """ element_ring = self.parent()._element_ring res = self.parent()(self.nrows(), self.ncols()) status = libgr.gr_mat_hadamard(res._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def charpoly(self, R=None, algorithm=None): """ Characteristic polynomial of this matrix. >>> MatZZ([[1,0,1],[0,0,0],[1,0,1]]).charpoly() -2*x^2 + x^3 >>> MatRR([[1,0,1],[0,0,0],[1,0,1]]).charpoly() -2.000000000000000*x^2 + x^3 >>> Mat(CC_ca)([[5,CC_ca.pi()],[1,-1]]).charpoly() (-8.14159 {-a-5 where a = 3.14159 [Pi]}) - 4*x + x^2 """ mat_ring = self.parent() element_ring = mat_ring._element_ring poly_ring = R if poly_ring is None: poly_ring = PolynomialRing_gr_poly(element_ring) poly_element_ring = poly_ring._coefficient_ring assert element_ring is poly_element_ring res = poly_ring() if algorithm is None: status = libgr.gr_mat_charpoly(res._ref, self._ref, element_ring._ref) elif algorithm == "berkowitz": status = libgr.gr_mat_charpoly_berkowitz(res._ref, self._ref, element_ring._ref) elif algorithm == "gauss": status = libgr.gr_mat_charpoly_gauss(res._ref, self._ref, element_ring._ref) elif algorithm == "householder": status = libgr.gr_mat_charpoly_householder(res._ref, self._ref, element_ring._ref) elif algorithm == "danilevsky": status = libgr.gr_mat_charpoly_danilevsky(res._ref, self._ref, element_ring._ref) elif algorithm == "faddeev": status = libgr.gr_mat_charpoly_faddeev(res._ref, None, self._ref, element_ring._ref) elif algorithm == "faddeev_bsgs": status = libgr.gr_mat_charpoly_faddeev_bsgs(res._ref, None, self._ref, element_ring._ref) else: raise ValueError("unknown algorithm") if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def minpoly(self, R=None): """ Minimal polynomial of this matrix. This currently only makes sense over fields. >>> A = MatrixRing(QQ,3)([[1,0,1],[0,0,0],[1,0,1]]) >>> A.minpoly() -2*x + x^2 >>> A.minpoly()(A) [[0, 0, 0], [0, 0, 0], [0, 0, 0]] """ mat_ring = self.parent() element_ring = mat_ring._element_ring poly_ring = R if poly_ring is None: poly_ring = PolynomialRing_gr_poly(element_ring) poly_element_ring = poly_ring._coefficient_ring assert element_ring is poly_element_ring res = poly_ring() status = libgr.gr_mat_minpoly_field(res._ref, self._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def transpose(self): """ >>> MatZZ(3,4,range(12)).transpose() [[0, 4, 8], [1, 5, 9], [2, 6, 10], [3, 7, 11]] """ r = self.nrows() c = self.ncols() element_ring = self.parent()._element_ring res = gr_mat(c, r, context=self.parent()) status = libgr.gr_mat_transpose(res._ref, self._ref, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def is_scalar(self): """ Return whether this matrix is a scalar matrix. """ R = self.parent()._element_ring truth = libgr.gr_mat_is_scalar(self._ref, R._ref) def op(*args): return truth return gr_elem._unary_predicate(self, op, "is_scalar") def is_diagonal(self): """ Return whether this matrix is a diagonal matrix. """ R = self.parent()._element_ring truth = libgr.gr_mat_is_diagonal(self._ref, R._ref) def op(*args): return truth return gr_elem._unary_predicate(self, op, "is_diagonal") def is_upper_triangular(self): """ Return whether this matrix is upper triangular. """ R = self.parent()._element_ring truth = libgr.gr_mat_is_upper_triangular(self._ref, R._ref) def op(*args): return truth return gr_elem._unary_predicate(self, op, "is_upper_triangular") def is_lower_triangular(self): """ Return whether this matrix is lower triangular. """ R = self.parent()._element_ring truth = libgr.gr_mat_is_lower_triangular(self._ref, R._ref) def op(*args): return truth return gr_elem._unary_predicate(self, op, "is_lower_triangular") def hessenberg(self, algorithm=None): """ Return this matrix reduced to upper Hessenberg form:: >>> B = Mat(QQ, 3, 3)([[4, 2, 3], [-1, 5, -3], [-4, 1, 2]]); >>> B.hessenberg() [[4, 14, 3], [-1, -7, -3], [0, 37, 14]] Options: - algorithm: ``None`` (default), ``"gauss"`` or ``"householder"`` """ element_ring = self.parent()._element_ring res = self.parent()() if algorithm is None: status = libgr.gr_mat_hessenberg(res._ref, self._ref, element_ring._ref) elif algorithm == "gauss": status = libgr.gr_mat_hessenberg_gauss(res._ref, self._ref, element_ring._ref) elif algorithm == "householder": status = libgr.gr_mat_hessenberg_householder(res._ref, self._ref, element_ring._ref) else: raise ValueError("unknown algorithm") if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def is_hessenberg(self): """ Return whether this matrix is in upper Hessenberg form. """ R = self.parent()._element_ring truth = libgr.gr_mat_is_hessenberg(self._ref, R._ref) def op(*args): return truth return gr_elem._unary_predicate(self, op, "is_hessenberg") def eigenvalues(self, domain=None): """ Computes the eigenvalues in the coefficient ring of this matrix, returning a tuple (``eigenvalues``, ``multiplicities``). If the ring is not algebraically closed, the sum of multiplicities can be smaller than the dimension of the matrix. If ``domain`` is given, returns eigenvalues in that ring instead. >>> Mat(ZZ)([[1,2],[3,4]]).eigenvalues() ([], []) >>> Mat(ZZ)([[1,2],[3,-4]]).eigenvalues() ([2, -5], [1, 1]) >>> Mat(ZZ)([[1,2],[3,4]]).eigenvalues(domain=QQbar) ([Root a = 5.37228 of a^2-5*a-2, Root a = -0.372281 of a^2-5*a-2], [1, 1]) >>> Mat(ZZ)([[1,2],[3,4]]).eigenvalues(domain=RR) ([[-0.3722813232690143 +/- 3.01e-17], [5.372281323269014 +/- 3.31e-16]], [1, 1]) The matrix must be square: >>> Mat(ZZ)([[1,2,3],[4,5,6]]).eigenvalues() Traceback (most recent call last): ... ValueError """ Rmat = self.parent() R = Rmat._element_ring mult = VecZZ() if domain is None: roots = Vec(R)() status = libgr.gr_mat_eigenvalues(roots._ref, mult._ref, self._ref, 0, R._ref) else: C = domain roots = Vec(C)() status = libgr.gr_mat_eigenvalues_other(roots._ref, mult._ref, self._ref, R._ref, 0, C._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return (roots, mult) def diagonalization(self): """ Matrix diagonalization: returns (D, L, R) where D is a vector of eigenvalues, LAR = diag(D) and LR = 1. >>> A = Mat(QQ)([[1,2],[-1,4]]) >>> D, L, R = A.diagonalization() >>> L*A*R [[3, 0], [0, 2]] >>> D [3, 2] >>> L*R [[1, 0], [0, 1]] >>> A = Mat(CC)([[1,2],[-1,4]]) >>> D, L, R = A.diagonalization() >>> D [([2.00000000000000 +/- 1.86e-15] + [+/- 1.86e-15]*I), ([3.00000000000000 +/- 2.90e-15] + [+/- 1.86e-15]*I)] >>> L*A*R [[([2.00000000000 +/- 1.10e-12] + [+/- 1.08e-12]*I), ([+/- 1.44e-12] + [+/- 1.42e-12]*I)], [([+/- 9.76e-13] + [+/- 9.63e-13]*I), ([3.00000000000 +/- 1.27e-12] + [+/- 1.25e-12]*I)]] >>> L*R [[([1.00000000000 +/- 3.26e-13] + [+/- 3.20e-13]*I), ([+/- 3.72e-13] + [+/- 3.67e-13]*I)], [([+/- 2.77e-13] + [+/- 2.73e-13]*I), ([1.00000000000 +/- 3.17e-13] + [+/- 3.13e-13]*I)]] >>> A = Mat(CF)([[1,2],[-1,4]]) >>> D, L, R = A.diagonalization() >>> D [2.000000000000000, 3.000000000000000] >>> L*A*R [[2.000000000000000, -8.275113827716402e-16], [0, 3.000000000000000]] >>> L*R [[1.000000000000000, -8.275113803054639e-17], [0, 1.000000000000000]] >>> M = Mat(CC_ca) >>> A = M([[1,2],[3,4]]) >>> D, L, R = A.diagonalization() >>> D [5.37228 {(a+5)/2 where a = 5.74456 [a^2-33=0]}, -0.372281 {(-a+5)/2 where a = 5.74456 [a^2-33=0]}] >>> R * M([[D[0], 0], [0, D[1]]]) * L [[1, 2], [3, 4]] A diagonalizable matrix without distinct eigenvalues: >>> A = M([[-1,3,-1],[-3,5,-1],[-3,3,1]]) >>> D, L, R = A.diagonalization() >>> D [1, 2, 2] >>> L [[3, -3, 1], [-3, 4, -1], [-3, 3, 0]] >>> R [[1, 1, -0.333333 {-1/3}], [1, 1, 0], [1, 0, 1]] >>> R * M([[D[0],0,0],[0,D[1],0],[0,0,D[2]]]) * L == A True """ Rmat = self.parent() C = Rmat._element_ring D = Vec(C)() n = self.nrows() L = gr_mat(n, n, context=self.parent()) R = gr_mat(n, n, context=self.parent()) status = libgr.gr_mat_diagonalization(D._ref, L._ref, R._ref, self._ref, 0, C._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return (D, L, R) #def __getitem__(self, i): # pass libgr.gr_mat_entry_ptr.argtypes = (ctypes.c_void_p, c_slong, c_slong, ctypes.POINTER(gr_ctx_struct)) libgr.gr_mat_entry_ptr.restype = ctypes.POINTER(ctypes.c_char) libgr.gr_vec_entry_ptr.restype = ctypes.POINTER(ctypes.c_char) # todo singleton/cached domains (also for matrices, etc...) class Vec(gr_ctx): """ Parent class for vector domains. """ def __init__(self, element_domain, n=None): assert isinstance(element_domain, gr_ctx) assert (n is None) or (0 <= n <= WORD_MAX) gr_ctx.__init__(self) if n is None: libgr.gr_ctx_init_vector_gr_vec(self._ref, element_domain._ref) else: libgr.gr_ctx_init_vector_space_gr_vec(self._ref, element_domain._ref, n) self._element_ring = element_domain self._elem_type = gr_vec self._element_ring._refcount += 1 def __del__(self): self._element_ring._decrement_refcount() class gr_vec(gr_elem): _struct_type = gr_vec_struct def __init__(self, *args, **kwargs): """ >>> VecZZ(range(3, 20, 3)) [3, 6, 9, 12, 15, 18] """ context = kwargs['context'] gr_elem.__init__(self, None, context) element_ring = context._element_ring if kwargs.get('random'): libgr.gr_randtest(self._ref, ctypes.byref(_flint_rand), self._ctx) return if len(args) == 1: val = args[0] if val is not None: status = GR_UNABLE if isinstance(val, (list, tuple)): n = len(val) status = libgr._gr_vec_check_resize(self._ref, n, self._ctx) if not status: for i in range(n): x = element_ring(val[i]) iptr = libgr.gr_vec_entry_ptr(self._ref, i, x._ctx) status |= libgr.gr_set(iptr, x._ref, x._ctx) elif isinstance(val, gr_elem): status = libgr.gr_set_other(self._ref, val._ref, val._ctx, self._ctx) elif isinstance(val, range): start = val.start step = val.step n = len(val) # todo: watch for slong -> int status = libgr._gr_vec_check_resize(self._ref, n, self._ctx) if not status: start = element_ring(start) step = element_ring(step) iptr = libgr.gr_vec_entry_ptr(self._ref, 0, element_ring._ref) status = libgr._gr_vec_step(iptr, start._ref, step._ref, n, element_ring._ref) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError def __len__(self): return self._data.length def __getitem__(self, i): i = int(i) if not 0 <= i < len(self): raise IndexError element_ring = self.parent()._element_ring res = element_ring() iptr = libgr.gr_vec_entry_ptr(self._ref, i, res._ctx) status = libgr.gr_set(res._ref, iptr, res._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def __setitem__(self, i, v): i = int(i) if not 0 <= i < len(self): raise IndexError element_ring = self.parent()._element_ring # todo: avoid copy x = element_ring(v) iptr = libgr.gr_vec_entry_ptr(self._ref, i, x._ctx) status = libgr.gr_set(iptr, x._ref, x._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return x def sum(self): """ Sum of the elements in this vector. >>> VecZZ(list(range(1,101))).sum() 5050 >>> VecZZ([]).sum() 0 >>> Vec(ZZmod(100))(list(range(1,101))).sum() 50 """ element_ring = self.parent()._element_ring res = element_ring() ptr = libgr.gr_vec_entry_ptr(self._ref, 0, res._ctx) status = libgr._gr_vec_sum(res._ref, ptr, len(self), res._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res def product(self): """ Product of the elements in this vector. >>> VecZZ(list(range(1,11))).product() 3628800 >>> VecZZ([]).product() 1 >>> Vec(ZZmod(103))(list(range(1,101))).product() 51 """ element_ring = self.parent()._element_ring res = element_ring() ptr = libgr.gr_vec_entry_ptr(self._ref, 0, res._ctx) status = libgr._gr_vec_product(res._ref, ptr, len(self), res._ctx) if status: if status & GR_UNABLE: raise NotImplementedError if status & GR_DOMAIN: raise ValueError return res class fmpz_poly(gr_poly): _struct_type = fmpz_poly_struct @staticmethod def _default_context(): return ZZx_fmpz_poly def __init__(self, val=None, context=None): if isinstance(val, (list, tuple)): gr_elem.__init__(self, ZZx_gr_poly(val), context) else: gr_elem.__init__(self, val, context) class fmpq_poly(gr_elem): _struct_type = fmpq_poly_struct @staticmethod def _default_context(): return QQx_fmpq_poly def __init__(self, val=None, context=None): if isinstance(val, (list, tuple)): gr_elem.__init__(self, QQx_gr_poly(val), context) else: gr_elem.__init__(self, val, context) class PolynomialRing_fmpz_poly(gr_ctx): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_fmpz_poly(self._ref) self._elem_type = fmpz_poly @property def _coefficient_ring(self): return ZZ class PolynomialRing_fmpq_poly(gr_ctx): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_fmpq_poly(self._ref) self._elem_type = fmpq_poly ZZx_fmpz_poly = PolynomialRing_fmpz_poly() QQx_fmpq_poly = PolynomialRing_fmpq_poly() class fmpz_poly(gr_poly): _struct_type = fmpz_poly_struct @staticmethod def _default_context(): return ZZx_fmpz_poly def __init__(self, val=None, context=None): if isinstance(val, (list, tuple)): gr_elem.__init__(self, ZZx_gr_poly(val), context) else: gr_elem.__init__(self, val, context) class fmpz_mpoly(gr_elem): _struct_type = fmpz_mpoly_struct class PolynomialRing_fmpz_mpoly(gr_ctx): def __init__(self, nvars, vars=None): gr_ctx.__init__(self) nvars = gr_ctx._as_si(nvars) assert nvars >= 0 libgr.gr_ctx_init_fmpz_mpoly(self._ref, nvars, 0) self._elem_type = fmpz_mpoly if vars is not None: assert len(vars) == nvars self._set_gen_names(vars) @property def _coefficient_ring(self): return ZZ class gr_mpoly(gr_elem): _struct_type = gr_mpoly_struct class PolynomialRing_gr_mpoly(gr_ctx): def __init__(self, coefficient_ring, nvars, vars=None): assert isinstance(coefficient_ring, gr_ctx) gr_ctx.__init__(self) gr_ctx.__init__(self) nvars = gr_ctx._as_si(nvars) assert nvars >= 0 libgr.gr_ctx_init_gr_mpoly(self._ref, coefficient_ring._ref, nvars, 0) self._elem_type = fmpz_mpoly coefficient_ring._refcount += 1 self._coefficient_ring = coefficient_ring self._elem_type = gr_mpoly if vars is not None: assert len(vars) == nvars self._set_gen_names(vars) def __del__(self): self._coefficient_ring._decrement_refcount() class fmpz_mpoly_q(gr_elem): _struct_type = fmpz_mpoly_q_struct class FractionField_fmpz_mpoly_q(gr_ctx): def __init__(self, nvars, vars=None): gr_ctx.__init__(self) nvars = gr_ctx._as_si(nvars) assert nvars >= 0 libgr.gr_ctx_init_fmpz_mpoly_q(self._ref, nvars, 0) self._elem_type = fmpz_mpoly_q if vars is not None: assert len(vars) == nvars self._set_gen_names(vars) @property def _coefficient_ring(self): return QQ class fexpr(gr_elem): _struct_type = fexpr_struct @staticmethod def inject(vars=False): """ Inject all builtin symbol names into the calling namespace. For interactive use only! >>> fexpr.inject() >>> n = fexpr("n") >>> Sum(Sin(Pi*n/3)/Factorial(n), For(n,0,Infinity)) Sum(Div(Sin(Div(Mul(Pi, n), 3)), Factorial(n)), For(n, 0, Infinity)) """ from inspect import currentframe frame = currentframe().f_back num = libflint.fexpr_builtin_length() for i in range(num): # memory leak symbol_name = libflint.fexpr_builtin_name(i) symbol_name = symbol_name.decode('ascii') if not symbol_name[0].islower(): frame.f_globals[symbol_name] = fexpr(symbol_name) if vars: def inject_vars(string): for s in string.split(): for symbol_name in [s, s + "_"]: frame.f_globals[symbol_name] = fexpr(symbol_name) inject_vars("""a b c d e f g h i j k l m n o p q r s t u v w x y z""") inject_vars("""A B C D E F G H I J K L M N O P Q R S T U V W X Y Z""") inject_vars("""alpha beta gamma delta epsilon zeta eta theta iota kappa lamda mu nu xi pi rho sigma tau phi chi psi omega ell varphi vartheta""") inject_vars("""Alpha Beta GreekGamma Delta Epsilon Zeta Eta Theta Iota Kappa Lamda Mu Nu Xi GreekPi Rho Sigma Tau Phi Chi Psi Omega""") del frame def inject_dict(): vs = {} num = libflint.fexpr_builtin_length() for i in range(num): # memory leak symbol_name = libflint.fexpr_builtin_name(i) symbol_name = symbol_name.decode('ascii') if not symbol_name[0].islower(): vs[symbol_name] = fexpr(symbol_name) def inject_vars(string): for s in string.split(): for symbol_name in [s, s + "_"]: vs[symbol_name] = fexpr(symbol_name) inject_vars("""a b c d e f g h i j k l m n o p q r s t u v w x y z""") inject_vars("""A B C D E F G H I J K L M N O P Q R S T U V W X Y Z""") inject_vars("""alpha beta gamma delta epsilon zeta eta theta iota kappa lamda mu nu xi pi rho sigma tau phi chi psi omega ell varphi vartheta""") inject_vars("""Alpha Beta GreekGamma Delta Epsilon Zeta Eta Theta Iota Kappa Lamda Mu Nu Xi GreekPi Rho Sigma Tau Phi Chi Psi Omega""") return vs def builtins(): num = libflint.fexpr_builtin_length() names = [] for i in range(num): # memory leak symbol_name = libflint.fexpr_builtin_name(i) symbol_name = symbol_name.decode('ascii') names.append(symbol_name) return names # todo: deduplicate conversion code def __init__(self, val=None, context=None): if context is None: context = FExpressions gr_elem.__init__(self, None, context) #self._data = fexpr_struct() #self._ref = ctypes.byref(self._data) #libflint.fexpr_init(self) if val is not None: typ = type(val) if typ is int: b = sys.maxsize if -b <= val <= b: libflint.fexpr_set_si(self, val) else: n = fmpz_struct() nref = ctypes.byref(n) libflint.fmpz_init(nref) libflint.fmpz_set_str(nref, ctypes.c_char_p(str(val).encode('ascii')), 10) libflint.fexpr_set_fmpz(self, nref) libflint.fmpz_clear(nref) elif typ is str: if val[0] == "'" or val[0] == '"': libflint.fexpr_set_string(self, val[1:-1].encode('ascii')) else: libflint.fexpr_set_symbol_str(self, val.encode('ascii')) elif typ is float: libflint.fexpr_set_d(self, val) elif typ is complex: libflint.fexpr_set_re_im_d(self, val.real, val.imag) elif typ is bool: if val: libflint.fexpr_set_symbol_str(self, ("True").encode('ascii')) else: libflint.fexpr_set_symbol_str(self, ("False").encode('ascii')) elif issubclass(typ, gr_elem): status = libflint.gr_get_fexpr(self, val._ref, val._ctx) if status: _handle_error(context, status, "fexpr($x)", val) #elif typ is qqbar: # #libflint.qqbar_get_fexpr_repr(self, val, val._ctx) # tmp = val.fexpr() # libflint.fexpr_set(self, tmp) #elif typ is ca: # libflint.ca_get_fexpr(self, val, 0, val._ctx) #elif typ is ca_mat: # libflint.ca_mat_get_fexpr(self, val, 0, val._ctx) #elif typ is ca_poly: # libflint.ca_poly_get_fexpr(self, val, 0, val._ctx) elif typ is tuple: tmp = fexpr("Tuple")(*val) # todo: create without copying libflint.fexpr_set(self, tmp) elif typ is list: tmp = fexpr("List")(*val) libflint.fexpr_set(self, tmp) elif typ is set: tmp = fexpr("Set")(*val) libflint.fexpr_set(self, tmp) else: raise TypeError def __del__(self): libflint.fexpr_clear(self) @property def _as_parameter_(self): return self._ref @staticmethod def from_param(arg): return arg def __repr__(self): ptr = libflint.fexpr_get_str(self) try: return ctypes.cast(ptr, ctypes.c_char_p).value.decode("ascii") finally: libflint.flint_free(ptr) def latex(self): ptr = libflint.fexpr_get_str_latex(self, 0) try: return ctypes.cast(ptr, ctypes.c_char_p).value.decode() finally: libflint.flint_free(ptr) def _repr_latex_(self): return "$$" + self.latex() + "$$" def nwords(self): return libflint.fexpr_size(self) def size_bytes(self): return libflint.fexpr_size_bytes(self) def allocated_bytes(self): return libflint.fexpr_allocated_bytes(self) def num_leaves(self): return libflint.fexpr_num_leaves(self) def depth(self): return libflint.fexpr_depth(self) def __eq__(self, other): if type(self) is not type(other): return NotImplemented if libflint.fexpr_equal(self, other): return True return False def is_atom(self): return bool(libflint.fexpr_is_atom(self)) def is_atom_integer(self): return bool(libflint.fexpr_is_integer(self)) def is_symbol(self): return bool(libflint.fexpr_is_symbol(self)) def head(self): if libflint.fexpr_is_atom(self): return None res = fexpr() libflint.fexpr_func(res, self) return res def nargs(self): # todo: long if self.is_atom(): return None return libflint.fexpr_nargs(self) def args(self): if libflint.fexpr_is_atom(self): return None n = self.nargs() args = [fexpr() for i in range(n)] for i in range(n): libflint.fexpr_arg(args[i], self, i) return tuple(args) def __hash__(self): return libflint.fexpr_hash(self) def __call__(self, *args): args2 = [] for arg in args: tp = type(arg) if tp is not fexpr: if tp is str: arg = "'" + arg + "'" arg = fexpr(arg) args2.append(arg) n = len(args2) res = fexpr() if n == 0: libflint.fexpr_call0(res, self) elif n == 1: libflint.fexpr_call1(res, self, args2[0]) elif n == 2: libflint.fexpr_call2(res, self, args2[0], args2[1]) elif n == 3: libflint.fexpr_call3(res, self, args2[0], args2[1], args2[2]) elif n == 4: libflint.fexpr_call4(res, self, args2[0], args2[1], args2[2], args2[3]) else: vec = libflint.flint_malloc(n * ctypes.sizeof(fexpr_struct)) vec = ctypes.cast(vec, ctypes.POINTER(fexpr_struct)) for i in range(n): vec[i] = args2[i]._data libflint.fexpr_call_vec(res, self, vec, n) libflint.flint_free(vec) return res def contains(self, x): """ Check if *x* appears exactly as a subexpression in *self*. >>> f = fexpr("f"); x = fexpr("x"); y = fexpr("y") >>> (f(x+1).contains(f), f(x+1).contains(x), f(x+1).contains(y)) (True, True, False) >>> (f(x+1).contains(1), f(x+1).contains(2)) (True, False) >>> (f(x+1).contains(x+1), f(x+1).contains(f(x+1))) (True, True) """ if type(x) is not fexpr: x = fexpr(x) if libflint.fexpr_contains(self, x): return True return False def replace(self, old, new=None): """ Replace subexpression. >>> f = fexpr("f"); x = fexpr("x"); y = fexpr("y") >>> f(x+1, x-1).replace(x, y) f(Add(y, 1), Sub(y, 1)) >>> f(x+1, x-1).replace(x+1, y-1) f(Sub(y, 1), Sub(x, 1)) >>> f(x+1, x-1).replace(f, f+1) Add(f, 1)(Add(x, 1), Sub(x, 1)) >>> f(x+1, x-1).replace(x+2, y) f(Add(x, 1), Sub(x, 1)) """ # todo: dict replacement if type(old) is not fexpr: old = fexpr(old) if type(new) is not fexpr: new = fexpr(new) res = fexpr() libflint.fexpr_replace(res, self, old, new) return res def __add__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_add(res, self, other) return res def __radd__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_add(res, other, self) return res def __sub__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_sub(res, self, other) return res def __rsub__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_sub(res, other, self) return res def __mul__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_mul(res, self, other) return res def __rmul__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_mul(res, other, self) return res def __truediv__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_div(res, self, other) return res def __rtruediv__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_div(res, other, self) return res def __pow__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_pow(res, self, other) return res def __rpow__(self, other): if type(self) is not type(other): try: other = fexpr(other) except TypeError: return NotImplemented res = fexpr() libflint.fexpr_pow(res, other, self) return res # def __floordiv__(self, other): # return (self / other).floor() # def __rfloordiv__(self, other): # return (other / self).floor() def __bool__(self): return True def __abs__(self): return fexpr("Abs")(self) def __neg__(self): res = fexpr() libflint.fexpr_neg(res, self) return res def __pos__(self): return fexpr("Pos")(self) def expanded_normal_form(self): """ Converts this expression to expanded normal form as a formal rational function of its non-arithmetic subexpressions. >>> x = fexpr("x"); y = fexpr("y") >>> (x / x**2).expanded_normal_form() Div(1, x) >>> (((x ** 0) + 3) ** 5).expanded_normal_form() 1024 >>> ((x+y+1)**3 - (y+1)**3 - (x+y)**3 - (x+1)**3).expanded_normal_form() Add(Mul(-1, Pow(x, 3)), Mul(6, x, y), Mul(-1, Pow(y, 3)), -1) >>> (1/((1/y + 1/x))).expanded_normal_form() Div(Mul(x, y), Add(x, y)) >>> (((x+y)**5 * (x-y)) / (x**2 - y**2)).expanded_normal_form() Add(Pow(x, 4), Mul(4, Pow(x, 3), y), Mul(6, Pow(x, 2), Pow(y, 2)), Mul(4, x, Pow(y, 3)), Pow(y, 4)) >>> (1 / (x - x)).expanded_normal_form() Traceback (most recent call last): ... ValueError: expanded_normal_form: overflow, formal division by zero or unsupported expression """ res = fexpr() if not libflint.fexpr_expanded_normal_form(res, self, 0): raise ValueError("expanded_normal_form: overflow, formal division by zero or unsupported expression") return res def nstr(self, n=16): """ Evaluates this expression numerically using Arb, returning a decimal string correct within 1 ulp in the last output digit. Attempts to obtain *n* digits (but the actual output accuracy may be lower). >>> Exp = fexpr("Exp"); Exp(1).nstr() '2.718281828459045' >>> Pi = fexpr("Pi"); Pi.nstr(30) '3.14159265358979323846264338328' >>> Log = fexpr("Log"); Log(-2).nstr() '0.6931471805599453 + 3.141592653589793*I' >>> Im = fexpr("Im") >>> Im(Log(2)).nstr() # exact zero '0' Here the imaginary part is zero, but Arb is not able to compute so exactly. The output ``0e-N`` indicates only that the absolute value is bounded by ``1e-N``: >>> Exp(Log(-2)).nstr() '-2.000000000000000 + 0e-22*I' >>> Im(Exp(Log(-2))).nstr() '0e-731' The algorithm fails if the expression or any subexpression is not a finite complex number: >>> Log(0).nstr() Traceback (most recent call last): ... ValueError: nstr: unable to evaluate to a number Expressions must be constant: >>> fexpr("x").nstr() Traceback (most recent call last): ... ValueError: nstr: unable to evaluate to a number """ ptr = libflint.fexpr_get_decimal_str(self, n, 0) try: s = ctypes.cast(ptr, ctypes.c_char_p).value.decode("ascii") if s == "?": raise ValueError("nstr: unable to evaluate to a number") return s finally: libflint.flint_free(ptr) class Expressions_fexpr(gr_ctx): def __init__(self): gr_ctx.__init__(self) libgr.gr_ctx_init_fexpr(self._ref) self._elem_type = fexpr FExpressions = Expressions_fexpr() libflint.fexpr_builtin_name.restype = ctypes.c_char_p libflint.fexpr_set_symbol_str.argtypes = ctypes.c_void_p, ctypes.c_char_p libflint.fexpr_get_str.restype = ctypes.c_void_p libflint.fexpr_get_str_latex.restype = ctypes.c_void_p libflint.fexpr_set_si.argtypes = fexpr, ctypes.c_long libflint.fexpr_set_d.argtypes = fexpr, ctypes.c_double libflint.fexpr_set_re_im_d.argtypes = fexpr, ctypes.c_double, ctypes.c_double libflint.fexpr_get_decimal_str.restype = ctypes.c_void_p # todo: def .one() PolynomialRing = PolynomialRing_gr_poly PowerSeriesRing = PowerSeriesRing_gr_series PowerSeriesModRing = PowerSeriesModRing_gr_series NumberField = NumberField_nf ZZ = IntegerRing_fmpz() QQ = RationalField_fmpq() ZZi = GaussianIntegerRing_fmpzi() AA = RealAlgebraicField_qqbar() AA_ca = RealAlgebraicField_ca() QQbar = ComplexAlgebraicField_qqbar() QQbar_ca = ComplexAlgebraicField_ca() RR = RR_arb = RealField_arb() CC = CC_acb = ComplexField_acb() RR_ca = RealField_ca() CC_ca = ComplexField_ca() RF = RealFloat_arf() CF = ComplexFloat_acf() def ZZmod(n): # todo: selection return IntegersMod_nmod(n) ZZp16 = ZZmod((1 << 15) + 3) ZZp32 = ZZmod((1 << 31) + 11) ZZp63 = ZZmod((1 << 62) + 135) ZZp64 = ZZmod((1 << 63) + 29) VecZZ = Vec(ZZ) VecQQ = Vec(QQ) VecRR = Vec(RR) VecCC = Vec(CC) VecRF = Vec(RF) VecCF = Vec(CF) MatZZ = Mat(ZZ) MatQQ = Mat(QQ) MatRR = Mat(RR) MatCC = Mat(CC) MatRF = Mat(RF) MatCF = Mat(CF) ZZx_gr_poly = PolynomialRing_gr_poly(ZZ) ZZx = ZZx_fmpz_poly QQx = QQx_gr_poly = PolynomialRing_gr_poly(QQ) RRx = RRx_arb = PolynomialRing_gr_poly(RR_arb) CCx = CCx_acb = PolynomialRing_gr_poly(CC_acb) RRx_ca = PolynomialRing_gr_poly(RR_ca) CCx_ca = PolynomialRing_gr_poly(CC_ca) ZZser = PowerSeriesRing(ZZ) QQser = PowerSeriesRing(QQ) RRser = RRser_arb = PowerSeriesRing(RR_arb) CCser = CCser_acb = PowerSeriesRing(CC_acb) RRser_ca = PowerSeriesRing(RR_ca) CCser_ca = PowerSeriesRing(CC_ca) # QQx = QQx_fmpq_poly ModularGroup = ModularGroup_psl2z DirichletGroup = DirichletGroup_dirichlet_char PSL2Z = ModularGroup() SymmetricGroup = SymmetricGroup_perm def timing(f, *args, **kwargs): once = kwargs.get('once') if 'once' in kwargs: del kwargs['once'] if args or kwargs: if len(args) == 1 and not kwargs: arg = args[0] g = lambda: f(arg) else: g = lambda: f(*args, **kwargs) else: g = f from timeit import default_timer as clock t1=clock(); v=g(); t2=clock(); t=t2-t1 if t > 0.05 or once: return t for i in range(3): t1=clock(); # Evaluate multiple times because the timer function # has a significant overhead g();g();g();g();g();g();g();g();g();g() t2=clock() t=min(t,(t2-t1)/10) return t def raises(f, exception): try: f() except exception: return True return False def test_perm(): S = SymmetricGroup(3) M = Mat(ZZ) A = M([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) assert S(A).parent() is S assert S(A).inv() == S(A.inv()) assert raises(lambda: S(-A), ValueError) assert raises(lambda: S(M([[0, 1, 0], [1, 0, 0], [0, 0, 0]])), ValueError) assert raises(lambda: S(M([[0, 1, 0], [1, 0, 0], [1, 0, 0]])), ValueError) assert raises(lambda: S(M([[0, 1, 0], [1, 0, 0], [0, 1, 1]])), ValueError) def test_psl2z(): M = Mat(ZZ) A = M([[2, 1], [5, 3]]) a = PSL2Z(A) assert a.parent() is PSL2Z assert a == PSL2Z(-A) assert a.inv() == PSL2Z(A.inv()) assert raises(lambda: PSL2Z(M([[1], [2]])), ValueError) assert raises(lambda: PSL2Z(M([[1, 3, 4], [4, 5, 6]])), ValueError) assert raises(lambda: PSL2Z(M([[1, 2], [3, 4]])), ValueError) def test_polynomial(): poly_types = [ZZx_fmpz_poly, ZZx_gr_poly, QQx_fmpq_poly, QQx_gr_poly] for A in poly_types: for B in poly_types + [VecZZ, VecQQ]: for C in poly_types: assert A(B([1,2,3])) == C([1,2,3]) def test_matrix(): M = Mat(ZZ, 2) I = M([[1, 0], [0, 1]]) assert M(1) == M(ZZ(1)) == I == M(2, 2, [1, 0, 0, 1]) assert raises(lambda: M(3, 1, [1, 2, 3]), ValueError) assert 2 * I == M(2 * I) == I + I == 1 + I == I + 1 assert Mat(ZZ)([[1],[3]]) * ZZ(5) == Mat(ZZ)([[5],[15]]) M = Mat(ZZ) A = M([[1,2,3],[4,5,6]]) assert A == M(2, 3, [1,2,3,4,5,6]) assert A == M(2, 3, [1,2,QQ(3),4,5,6]) assert Mat(ZZ, 2, 3)(A) == A assert Mat(QQ, 2, 3)(A) == A assert M(2, 1) == M([[0], [0]]) assert raises(lambda: M(2, 1, [1,2,3]), ValueError) assert raises(lambda: M([[QQ(1)/3]]), ValueError) assert raises(lambda: Mat(ZZ, 3, 1)(A), ValueError) assert Mat(QQ, 2)(M([[1, 2], [3, 4]])) ** 2 == M([[7,10],[15,22]]) A[1, 2] = 10 assert A == M([[1,2,3],[4,5,10]]) assert A[0,1] == 2 assert raises(lambda: A[3,4], Exception) assert raises(lambda: A.__setitem__((3, 4), 1), Exception) MatZZ = Mat(ZZ) A = MatZZ([[1, 2, 3], [0, 4, 5], [0, 0, 6]]) assert A.is_upper_triangular() assert not A.is_lower_triangular() assert A.transpose().is_lower_triangular() assert not A.transpose().is_upper_triangular() A = MatZZ([[1, 2, 3], [1, 4, 5], [0, 5, 6]]) assert A.is_hessenberg() assert not A.transpose().is_hessenberg() assert not A.is_diagonal() assert MatZZ([[1, 0, 0], [0, 2, 0], [0, 0, 3]]).is_diagonal() assert not A.is_scalar() assert not MatZZ([[1,0],[0,2]]).is_scalar() assert MatZZ([[1,0],[0,1]]).is_scalar() def test_fq(): Fq = FiniteField_fq(3, 5) x = Fq(random=True) y = Fq(random=True) assert 3*(x+y) == 4*x+3*y-x assert Fq.prime() == 3 assert Fq.degree() == 5 assert Fq.order() == 243 assert x.pth_root() ** 3 == x assert (x**2).sqrt() in (x, -x) def test_floor_ceil_trunc_nint(): assert ZZ(3).floor() == 3 assert ZZ(3).ceil() == 3 assert ZZ(3).trunc() == 3 assert ZZ(3).nint() == 3 assert QQ(3).floor() == 3 assert QQ(3).ceil() == 3 assert QQ(3).trunc() == 3 assert QQ(3).nint() == 3 assert RR(3).nint() == 3 assert 2.9 < RR("3.5 +/- 0.1").nint() < 4.1 for R in [QQ, QQbar, QQbar_ca, AA, AA_ca, RR, RR_ca, CC, CC_ca, RF]: x = R(3) / 2 assert x.floor() == 1 assert x.ceil() == 2 assert x.trunc() == 1 assert (-x).floor() == -2 assert (-x).ceil() == -1 assert (-x).trunc() == -1 assert x.nint() == 2 assert (-x).nint() == -2 assert (x+1).nint() == 2 assert (x+2).nint() == 4 for R in [QQbar, QQbar_ca, CC, CC_ca]: x = R(3) / 2 + R.i() assert x.floor() == 1 assert x.ceil() == 2 assert x.trunc() == 1 assert (-x).floor() == -2 assert (-x).ceil() == -1 assert (-x).trunc() == -1 assert x.nint() == 2 assert (-x).nint() == -2 assert (x+1).nint() == 2 assert (x+2).nint() == 4 def test_zz(): assert ZZ(1).factor() == (1, [], []) assert ZZ(0).factor() == (0, [], []) assert (-ZZ(12)).factor() == (-1, [2, 3], [2, 1]) def test_qq(): assert QQ(1).factor() == (1, [], []) assert QQ(0).factor() == (0, [], []) assert (-QQ(12)/175).factor() == (-1, [2, 3, 5, 7], [2, 1, -2, -1]) x = QQ.bernoulli(50) sign, primes, exponents = x.factor() assert (sign * (primes ** exponents)).product() == x def test_qqbar(): a = (-23 + 5*ZZi.i()) assert ZZi(QQbar(a**2).sqrt()) == -a x = (1 + 100*qqbar(2)**(-1000)).root(100) y = (1 + 101*qqbar(2)**(-1000)).root(101) assert x > y assert QQ(ComplexAlgebraicField_qqbar()(ca(-3).sqrt())**2) == -3 def test_nf(): a = NumberField_nf(ZZx([1,2,3])).gen() assert (a+5)**(-1) * (2*a+10) == 2 def test_ca(): R = ComplexField_ca() X = ComplexExtended_ca() assert X.inf() == -X.neg_inf() assert 1 / X(0) == X.uinf() assert 0 / X(0) == X.undefined() assert X(0).log() == X.neg_inf() assert X.inf().exp() == X.inf() assert raises(lambda: R(X.inf()), FlintDomainError) assert raises(lambda: R(X.undefined()), FlintDomainError) assert raises(lambda: R(X.unknown()), FlintUnableError) assert X(R(1)) == 1 assert R(X(1)) == 1 def test_ca_more(): sqrt = CC_ca.sqrt exp = CC_ca.exp log = CC_ca.log tan = CC_ca.tan tanh = CC_ca.tanh sin = CC_ca.sin cos = CC_ca.cos acos = CC_ca.acos sqrt = CC_ca.sqrt arg = CC_ca.arg atan = CC_ca.atan re = CC_ca.re im = CC_ca.im floor = CC_ca.floor ceil = CC_ca.ceil pi = CC_ca.pi() i = CC_ca.i() e = CC_ca.exp(1) erf = CC_ca.erf erfc = CC_ca.erfc erfi = CC_ca.erfi Sqrt = fexpr("Sqrt") def gd(x): return 2*atan(exp(x))-pi/2 # todo: proper gr versions def cosh(x): y = exp(x) return (y + 1/y)/2 def sinh(x): y = exp(x) return (y - 1/y)/2 def tanh(x): return sinh(x)/cosh(x) def gamma(x): return CC_ca(x).gamma() assert floor(sqrt(2)) == 1 assert ceil(sqrt(2)) == 2 assert (sqrt(2)**sqrt(2))**sqrt(2) == 2 assert (sqrt(-2)**sqrt(2))**sqrt(2) == -2 assert (sqrt(3)**sqrt(3))**sqrt(3) == 3*sqrt(3) assert sqrt(-pi)**2 == -pi assert log(1+pi) - log(pi) - log(1+1/pi) == 0 assert log(log(-log(log(exp(exp(-exp(exp(3)))))))) == 3 assert exp(pi*i) + 1 == 0 assert exp(pi*i) == -1 assert exp(log(2)*log(3)) > 2 assert e**2 == exp(2) assert erf(2*log(sqrt(ca(1)/2-sqrt(2)/4))+log(4)) - erf(log(2-sqrt(2))) == 0 assert 1-erf(pi)-erfc(pi) == 0 assert erf(sqrt(2))**2 + erfi(sqrt(-2))**2 == 0 assert sin(gd(1)) == tanh(1) assert tan(gd(1)) == sinh(1) assert sin(gd(sqrt(2))) == tanh(sqrt(2)) assert tan(gd(1)/2) - tanh(ca(1)/2) == 0 assert gamma(1) == 1 assert gamma(ca(1)/2) == sqrt(pi) assert gamma(sqrt(2)*sqrt(3)) == gamma(sqrt(6)) assert gamma(pi+1)/gamma(pi) == pi assert gamma(pi)/gamma(pi-1) == pi-1 assert log(gamma(pi+1)) - log(gamma(pi)) - log(pi) == 0 assert log(gamma(-pi+1)) - log(gamma(-pi)) - log(pi) == pi * i assert raises(lambda: gamma(0), FlintDomainError) assert 1/ComplexExtended_ca()(0).gamma() == 0 assert ca(qqbar(sqrt(2))) == sqrt(2) assert ca(fexpr(ca(Sqrt(2)))) == sqrt(2) assert sqrt(2)*(1+i)/2 * pi - exp(pi*i/4) * pi == 0 assert (sqrt(3) + i)/2 * pi - exp(pi*i/6) * pi == 0 assert arg(sqrt(-pi*i)) == -pi/4 assert (pi + sqrt(2) + sqrt(3)) / (pi + sqrt(5 + 2*sqrt(6))) == 1 assert log(1/exp(sqrt(2)+1)) == -sqrt(2)-1 assert abs(exp(sqrt(1+i))) == exp(re(sqrt(1+i))) assert tan(pi*sqrt(2))*tan(pi*sqrt(3)) == (cos(pi*sqrt(5-2*sqrt(6))) - cos(pi*sqrt(5+2*sqrt(6))))/(cos(pi*sqrt(5-2*sqrt(6))) + cos(pi*sqrt(5+2*sqrt(6)))) assert log(exp(i) / exp(-i)) == 2*i v = cos(acos(sqrt(2) - sqrt(3))/3) assert 1 - 90*v**2 + 321*v**4 - 592*v**6 + 864*v**8 - 768*v**10 + 256*v**12 == 0 def expect_not_implemented(f): try: v = f() assert v except NotImplementedError: return raise AssertionError expect_not_implemented(lambda: acos(cos(1)) == 1) expect_not_implemented(lambda: acos(cos(sqrt(2) - 1)) == sqrt(2) - 1) expect_not_implemented(lambda: tan(sqrt(pi*2))*tan(sqrt(pi*3)) == \ (cos(sqrt(pi*(5-2*sqrt(6)))) - cos(sqrt(pi*(5+2*sqrt(6)))))/(cos(sqrt(pi*(5-2*sqrt(6)))) + cos(sqrt(pi*(5+2*sqrt(6)))))) expect_not_implemented(lambda: sqrt(exp(2*sqrt(2)) + exp(-2*sqrt(2)) - 2) == (exp(2*sqrt(2))-1)/sqrt(exp(2*sqrt(2)))) # Some examples from Stoutemyer z = pi assert str(i*((3-5*i)*z+1)/(((5+3*i)*z+i)*z)) == "0.318310 {(1)/(a) where a = 3.14159 [Pi], b = I [b^2+1=0]}" assert str(ca(-1)**(ca(1)/8) * sqrt(i+1) / ca(2)**(ca(3)/4) + i*exp(i*pi/2)) == "-0.500000 + 0.500000*I {(a-1)/2 where a = I [a^2+1=0]}" assert sin(2*atan(z)) + (15*sqrt(3)+26)**(ca(1)/3) == 2*z/(z**2+1) + sqrt(3) + 2 def test_ca_comparisons(): R = ComplexExtended_ca() inf = R.inf() uinf = R.uinf() undefined = R.undefined() i = R.i() pi = R.pi() sqrt = R.sqrt exp = R.exp sin = R.sin cos = R.cos asin = R.asin assert inf >= inf assert inf >= -inf assert inf >= 3 assert not -inf >= inf assert -inf >= -inf assert not -inf >= 3 assert not inf > inf assert inf > -inf assert inf > 3 assert not -inf > inf assert not -inf > -inf assert not -inf >= 3 assert inf <= inf assert not inf <= -inf assert not inf <= 3 assert -inf <= inf assert -inf <= -inf assert -inf <= 3 assert not inf < inf assert not inf < -inf assert not inf < 3 assert -inf < inf assert not -inf < -inf assert -inf < 3 # as currently implemented, these comparisons raise #for a in [inf, -inf, ca(3)]: # for b in [uinf, undefined, inf*i, 2+i]: # assert not a < b # assert not a <= b # assert not a > b # assert not a >= b # assert not b < a # assert not b <= a # assert not b > a # assert not b >= a assert pi + sqrt(2) + sqrt(3) <= pi + sqrt(5 + 2 * sqrt(6)) assert not pi + sqrt(2) + sqrt(3) < pi + sqrt(5 + 2 * sqrt(6)) assert pi + sqrt(2) + sqrt(3) >= pi + sqrt(5 + 2 * sqrt(6)) assert not pi + sqrt(2) + sqrt(3) > pi + sqrt(5 + 2 * sqrt(6)) assert pi + exp(-1000) > pi assert pi - exp(-1000) < pi assert sin(1) < 1 assert sin(1) <= sqrt(1 - cos(1)**2) assert asin(ca(1)/10) > ca(1)/10 def test_latex(): latex_test_cases = [ ("""f(0)""", "f(0)"), ("""f("Hello, world!")""", "f(\\text{``Hello, world!''})"), ("f", r"f"), ("f_", r"f"), ("f_(0)", r"f_{0}"), ("f()", r"f()"), ("Add(Add(Add(f(a, b), c_(n)), f_(x, y)), f_())", r"f(a, b) + c_{n} + f_{x, y} + f_{}"), ("f(alpha, beta, chi, delta, ell, epsilon, eta)", r"f(\alpha, \beta, \chi, \delta, \ell, \varepsilon, \eta)"), ("f(gamma, iota, kappa, lamda, mu, nu, omega, phi)", r"f(\gamma, \iota, \kappa, \lambda, \mu, \nu, \omega, \phi)"), ("f(pi, rho, sigma, tau, theta, varphi, vartheta, xi, zeta)", r"f(\pi, \rho, \sigma, \tau, \theta, \varphi, \vartheta, \xi, \zeta)"), ("f(Delta, GreekGamma, GreekPi, Lamda, Omega, Phi, Psi, Sigma, Theta, Xi)", r"f(\Delta, \Gamma, \Pi, \Lambda, \Omega, \Phi, \Psi, \Sigma, \Theta, \Xi)"), ("f(alpha_, beta_, chi_, delta_, ell_, epsilon_, eta_)", r"f(\alpha, \beta, \chi, \delta, \ell, \varepsilon, \eta)"), ("f(gamma_, iota_, kappa_, lamda_, mu_, nu_, omega_, phi_)", r"f(\gamma, \iota, \kappa, \lambda, \mu, \nu, \omega, \phi)"), ("f(pi_, rho_, sigma_, tau_, theta_, varphi_, vartheta_, xi_, zeta)", r"f(\pi, \rho, \sigma, \tau, \theta, \varphi, \vartheta, \xi, \zeta)"), ("f(Delta_, GreekGamma_, GreekPi_, Lamda_, Omega_, Phi_, Psi_, Sigma_, Theta_, Xi_)", r"f(\Delta, \Gamma, \Pi, \Lambda, \Omega, \Phi, \Psi, \Sigma, \Theta, \Xi)"), ("f(alpha(x), beta(x), chi(x), delta(x), ell(x), epsilon(x), eta(x))", r"f\!\left(\alpha(x), \beta(x), \chi(x), \delta(x), \ell(x), \varepsilon(x), \eta(x)\right)"), ("f(gamma(x), iota(x), kappa(x), lamda(x), mu(x), nu(x), omega(x), phi(x))", r"f\!\left(\gamma(x), \iota(x), \kappa(x), \lambda(x), \mu(x), \nu(x), \omega(x), \phi(x)\right)"), ("f(pi(x), rho(x), sigma(x), tau(x), theta(x), varphi(x), vartheta(x), xi(x), zeta(x))", r"f\!\left(\pi(x), \rho(x), \sigma(x), \tau(x), \theta(x), \varphi(x), \vartheta(x), \xi(x), \zeta(x)\right)"), ("f(Delta(x), GreekGamma(x), GreekPi(x), Lamda(x), Omega(x), Phi(x), Psi(x), Sigma(x), Theta(x), Xi(x))", r"f\!\left(\Delta(x), \Gamma(x), \Pi(x), \Lambda(x), \Omega(x), \Phi(x), \Psi(x), \Sigma(x), \Theta(x), \Xi(x)\right)"), ("f(alpha_(n), beta_(n), chi_(n), delta_(n), ell_(n), epsilon_(n), eta_(n))", r"f\!\left(\alpha_{n}, \beta_{n}, \chi_{n}, \delta_{n}, \ell_{n}, \varepsilon_{n}, \eta_{n}\right)"), ("f(gamma_(n), iota_(n), kappa_(n), lamda_(n), mu_(n), nu_(n), omega_(n), phi_(n))", r"f\!\left(\gamma_{n}, \iota_{n}, \kappa_{n}, \lambda_{n}, \mu_{n}, \nu_{n}, \omega_{n}, \phi_{n}\right)"), ("f(pi_(n), rho_(n), sigma_(n), tau_(n), theta_(n), varphi_(n), vartheta_(n), xi_(n), zeta_(n))", r"f\!\left(\pi_{n}, \rho_{n}, \sigma_{n}, \tau_{n}, \theta_{n}, \varphi_{n}, \vartheta_{n}, \xi_{n}, \zeta_{n}\right)"), ("f(Delta_(n), GreekGamma_(n), GreekPi_(n), Lamda_(n), Omega_(n), Phi_(n), Psi_(n), Sigma_(n), Theta_(n), Xi_(n))", r"f\!\left(\Delta_{n}, \Gamma_{n}, \Pi_{n}, \Lambda_{n}, \Omega_{n}, \Phi_{n}, \Psi_{n}, \Sigma_{n}, \Theta_{n}, \Xi_{n}\right)"), ("f(a)(b)", r"f(a)(b)"), ("Mul(f, g)(x)", r"\left(f g\right)(x)"), ("Add(f, g)(x)", r"\left(f + g\right)(x)"), ("c_(m, n, p)(x, y, z)", r"c_{m, n, p}(x, y, z)"), ("f_(Div(-3, 2))(Div(-3, 2))", r"f_{-3 / 2}\!\left(-\frac{3}{2}\right)"), ("Mul(2, Pi, NumberI)", r"2 \pi i"), ("Mul(-2, Pi, NumberI)", r"-2 \pi i"), ("Mul(1)", r"1"), ("Mul(-1)", r"-1"), ("Mul(1, x, y)", r" x y"), ("Mul(-1, x, y)", r"- x y"), ("Mul(1, 2, 3)", r"1 \cdot 2 \cdot 3"), ("Mul(-1, 2, 3)", r"-1 \cdot 2 \cdot 3"), ("Mul(-1, -1)", r"-1 \cdot \left(-1\right)"), ("Add(2, x)", r"2 + x"), ("Sub(2, x)", r"2 - x"), ("Add(2, Neg(x))", r"2 + \left(-x\right)"), ("Sub(2, Neg(x))", r"2 - \left(-x\right)"), ("Add(2, Sub(x, y))", r"2 + \left(x - y\right)"), ("Sub(2, Add(x, y))", r"2 - \left(x + y\right)"), ("Sub(2, Sub(x, y))", r"2 - \left(x - y\right)"), ("Add(-3, -4, -5)", r"-3-4-5"), ("Add(-3, Mul(-4, x), -5)", r"-3-4 x-5"), ("Add(-3, Mul(-4, x), Pos(5))", r"-3-4 x+5"), ("Add(-3, Div(Mul(-4, x), 7), -5)", r"-3-\frac{4 x}{7}-5"), ("Add(-3, Div(Mul(4, x), 7), -5)", r"-3 + \frac{4 x}{7}-5"), ("Mul(0, 1)", r"0 \cdot 1"), ("Mul(3, Pow(2, n))", r"3 \cdot {2}^{n}"), ("Mul(3, Pow(-1, n))", r"3 \cdot {\left(-1\right)}^{n}"), ("Mul(-3, Pow(-1, n))", r"-3 \cdot {\left(-1\right)}^{n}"), ("Mul(-1, -2, -3)", r"-1 \cdot \left(-2\right) \cdot \left(-3\right)"), ("Div(-1, 3)", r"-\frac{1}{3}"), ("Div(Mul(-5, Pi), 3)", r"-\frac{5 \pi}{3}"), ("Div(Neg(Mul(5, Pi)), 3)", r"-\frac{5 \pi}{3}"), ("Div(Add(Add(Mul(-5, Pow(x, 2)), Mul(4, x)), 1), Add(Mul(3, x), y))", r"\frac{-5 {x}^{2} + 4 x + 1}{3 x + y}"), ("Pow(2, n)", r"{2}^{n}"), ("Pow(-1, n)", r"{\left(-1\right)}^{n}"), ("Pow(10, Pow(10, -10))", r"{10}^{{10}^{-10}}"), ("Pow(2, Div(-1, 3))", r"{2}^{-1 / 3}"), ("Pow(2, Div(-1, Mul(3, n)))", r"{2}^{-1 / \left(3 n\right)}"), ("Equal(Add(Pow(Sin(x), 2), Pow(Cos(x), 2)), 1)", r"\sin^{2}\!\left(x\right) + \cos^{2}\!\left(x\right) = 1"), ("Set(Set(), Set(1), Set(1, 2, 3))", r"\left\{\left\{\right\}, \left\{1\right\}, \left\{1, 2, 3\right\}\right\}"), ("Tuple(Tuple(), Tuple(1), Tuple(1, 2, 3))", r"\left(\left(\right), \left(1\right), \left(1, 2, 3\right)\right)"), ("List(List(), List(1), List(1, 2, 3))", r"\left[\left[\right], \left[1\right], \left[1, 2, 3\right]\right]"), ("Set(f(x), For(x, CC))", r"\left\{ f(x) : x \in \mathbb{C} \right\}"), ("Set(f(x), For(x, CC), NotEqual(x, 0))", r"\left\{ f(x) : x \in \mathbb{C}\,\mathbin{\operatorname{and}}\, x \ne 0 \right\}"), ("List(Floor(x), Ceil(x), Abs(x), RealAbs(x), Conjugate(z), Sqrt(x))", r"\left[\left\lfloor x \right\rfloor, \left\lceil x\right\rceil, \left|x\right|, \left|x\right|, \overline{z}, \sqrt{x}\right]"), ("List(Floor(Div(1, 2)), Ceil(Div(1, 2)), Abs(Div(1, 2)), RealAbs(Div(1, 2)), Conjugate(Div(1, 2)), Sqrt(Div(1, 2)))", r"\left[\left\lfloor \frac{1}{2} \right\rfloor, \left\lceil \frac{1}{2}\right\rceil, \left|\frac{1}{2}\right|, \left|\frac{1}{2}\right|, \overline{\frac{1}{2}}, \sqrt{\frac{1}{2}}\right]"), ("And(Equal(Length(Tuple(1, 2, 3)), 3), Equal(Cardinality(Set()), 0))", r"\# \left(1, 2, 3\right) = 3 \;\mathbin{\operatorname{and}}\; \# \left\{\right\} = 0"), ("Tuple(Parentheses(x), Brackets(x), Braces(x), AngleBrackets(x))", r"\left(\left(x\right), \left[x\right], \left\{x\right\}, \left\langle x\right\rangle\right)"), ("Tuple(Parentheses(Div(1, 2)), Brackets(Div(1, 2)), Braces(Div(1, 2)), AngleBrackets(Div(1, 2)))", r"\left(\left(\frac{1}{2}\right), \left[\frac{1}{2}\right], \left\{\frac{1}{2}\right\}, \left\langle \frac{1}{2}\right\rangle\right)"), ("Concatenation(A, B)", r"A \,^\frown B"), ("Equal(Concatenation(Tuple(a, b), Tuple(c, d, e), Tuple()), Tuple(a, b, c, d, e))", r"\left(a, b\right) \,^\frown \left(c, d, e\right) \,^\frown \left(\right) = \left(a, b, c, d, e\right)"), ("Equal(f(x), Cases(Case(y, P(x)), Case(Neg(y), Q(x))))", r"f(x) = \begin{cases} y, & P(x)\\-y, & Q(x)\\ \end{cases}"), ("Equal(f(x), Cases(Case(y, P(x)), Case(Neg(y), Q(x)), Case(0, Otherwise)))", r"f(x) = \begin{cases} y, & P(x)\\-y, & Q(x)\\0, & \text{otherwise}\\ \end{cases}"), ("And(Equal(True, Not(False)), Equal(False, Not(True)))", r"\operatorname{True} = \operatorname{not} \operatorname{False} \;\mathbin{\operatorname{and}}\; \operatorname{False} = \operatorname{not} \operatorname{True}"), ("All(Greater(x, 0), For(x, S))", r"x > 0 \;\text{ for all } x \in S"), ("All(Greater(x, 0), For(x, S), P(x))", r"x > 0 \;\text{ for all } x \in S \text{ with } P(x)"), ("Exists(Greater(x, 0), For(x, S))", r"x > 0 \;\text{ for some } x \in S"), ("Exists(Greater(x, 0), For(x, S), P(x))", r"x > 0 \;\text{ for some } x \in S \text{ with } P(x)"), ("Logic(All(Greater(x, 0), For(x, S)))", r"\forall x \in S : \, x > 0"), ("Logic(All(Greater(x, 0), For(x, S), P(x)))", r"\forall x \in S, \,P(x) : \, x > 0"), ("Logic(Exists(Greater(x, 0), For(x, S)))", r"\exists x \in S : \, x > 0"), ("Logic(Exists(Greater(x, 0), For(x, S), P(x)))", r"\exists x \in S, \,P(x) : \, x > 0"), ("Or(Q, And(P, Q, Not(P), Or(Q, P), Not(Or(Q, P))))", r"Q \;\mathbin{\operatorname{or}}\; \left(P \;\mathbin{\operatorname{and}}\; Q \;\mathbin{\operatorname{and}}\; \operatorname{not} P \;\mathbin{\operatorname{and}}\; \left(Q \;\mathbin{\operatorname{or}}\; P\right) \;\mathbin{\operatorname{and}}\; \operatorname{not} \,\left(Q \;\mathbin{\operatorname{or}}\; P\right)\right)"), ("Logic(Or(Q, And(P, Q, Not(P), Or(Q, P), Not(Or(Q, P)))))", r"Q \,\lor\, \left(P \,\land\, Q \,\land\, \neg P \,\land\, \left(Q \,\lor\, P\right) \,\land\, \neg \left(Q \,\lor\, P\right)\right)"), ("Equivalent(A, B)", r"A \iff B"), ("Equivalent(Not(Equal(x, y)), NotEqual(x, y))", r"\left(\operatorname{not} \,\left(x = y\right)\right) \iff \left(x \ne y\right)"), ("Implies(P, And(R, S))", r"P \;\implies\; \left(R \;\mathbin{\operatorname{and}}\; S\right)"), ("Implies(Element(x, QQ), Element(x, RR))", r"x \in \mathbb{Q} \;\implies\; x \in \mathbb{R}"), ("And(Less(x, y), Less(x, y, z), LessEqual(x, y), LessEqual(x, y, z))", r"x < y \;\mathbin{\operatorname{and}}\; x < y < z \;\mathbin{\operatorname{and}}\; x \le y \;\mathbin{\operatorname{and}}\; x \le y \le z"), ("And(Greater(x, y), Greater(x, y, z), GreaterEqual(x, y), GreaterEqual(x, y, z))", r"x > y \;\mathbin{\operatorname{and}}\; x > y > z \;\mathbin{\operatorname{and}}\; x \ge y \;\mathbin{\operatorname{and}}\; x \ge y \ge z"), ("Subset(Primes, NN, ZZ, QQ, RR, CC)", r"\mathbb{P} \subset \mathbb{N} \subset \mathbb{Z} \subset \mathbb{Q} \subset \mathbb{R} \subset \mathbb{C}"), ("Subset(QQ, AlgebraicNumbers, CC)", r"\mathbb{Q} \subset \overline{\mathbb{Q}} \subset \mathbb{C}"), ("SubsetEqual(S, QQ)", r"S \subseteq \mathbb{Q}"), ("NotElement(123456789012345678901234567890, SetMinus(QQ, ZZ))", r"123456789012345678901234567890 \notin \mathbb{Q} \setminus \mathbb{Z}"), ("KroneckerDelta(x, Div(1, 2))", r"\delta_{(x,1 / 2)}"), ("Set(Interval(a, b), OpenInterval(a, b), ClosedOpenInterval(a, b), OpenClosedInterval(a, b))", r"\left\{\left[a, b\right], \left(a, b\right), \left[a, b\right), \left(a, b\right]\right\}"), ("Set(Interval(a, Div(1, 2)), OpenInterval(a, Div(1, 2)), ClosedOpenInterval(a, Div(1, 2)), OpenClosedInterval(a, Div(1, 2)))", r"\left\{\left[a, 1 / 2\right], \left(a, 1 / 2\right), \left[a, 1 / 2\right), \left(a, 1 / 2\right]\right\}"), ("Set(RealBall(m, r), OpenRealBall(m, r))", r"\left\{\left[m \pm r\right], \left(m \pm r\right)\right\}"), ("Set(ClosedComplexDisk(m, r), OpenComplexDisk(m, r))", r"\left\{\overline{D}(m, r), D(m, r)\right\}"), ("Set(Undefined, UnsignedInfinity, Pos(Infinity), Neg(Infinity))", r"\left\{\mathfrak{u}, \hat{\infty}, +\infty, -\infty\right\}"), ("Equal(RealSignedInfinities, Set(Pos(Infinity), Neg(Infinity)))", r"\{\pm \infty\} = \left\{+\infty, -\infty\right\}"), ("Equal(ComplexSignedInfinities, Set(Mul(Exp(Mul(NumberI, theta)), Infinity), For(theta, OpenClosedInterval(Neg(Pi), Pi))))", r"\{[e^{i \theta}] \infty\} = \left\{ e^{i \theta} \cdot \infty : \theta \in \left(-\pi, \pi\right] \right\}"), ("Equal(RealInfinities, Union(RealSignedInfinities, Set(UnsignedInfinity)))", r"\{\hat{\infty}, \pm \infty\} = \{\pm \infty\} \cup \left\{\hat{\infty}\right\}"), ("Equal(ComplexInfinities, Union(ComplexSignedInfinities, Set(UnsignedInfinity)))", r"\{\hat{\infty}, [e^{i \theta}] \infty\} = \{[e^{i \theta}] \infty\} \cup \left\{\hat{\infty}\right\}"), ("Equal(ExtendedRealNumbers, Union(RR, RealSignedInfinities))", r"\overline{\mathbb{R}} = \mathbb{R} \cup \{\pm \infty\}"), ("Equal(SignExtendedComplexNumbers, Union(CC, ComplexSignedInfinities))", r"\overline{\mathbb{C}}_{[e^{i \theta}] \infty} = \mathbb{C} \cup \{[e^{i \theta}] \infty\}"), ("Equal(ProjectiveRealNumbers, Union(RR, Set(UnsignedInfinity)))", r"\hat{\mathbb{R}}_{\infty} = \mathbb{R} \cup \left\{\hat{\infty}\right\}"), ("Equal(ProjectiveComplexNumbers, Union(CC, Set(UnsignedInfinity)))", r"\hat{\mathbb{C}}_{\infty} = \mathbb{C} \cup \left\{\hat{\infty}\right\}"), ("Equal(RealSingularityClosure, Union(RR, Set(UnsignedInfinity), RealSignedInfinities, Set(Undefined)))", r"\overline{\mathbb{R}}_{\text{Sing}} = \mathbb{R} \cup \left\{\hat{\infty}\right\} \cup \{\pm \infty\} \cup \left\{\mathfrak{u}\right\}"), ("Equal(ComplexSingularityClosure, Union(CC, Set(UnsignedInfinity), ComplexSignedInfinities, Set(Undefined)))", r"\overline{\mathbb{C}}_{\text{Sing}} = \mathbb{C} \cup \left\{\hat{\infty}\right\} \cup \{[e^{i \theta}] \infty\} \cup \left\{\mathfrak{u}\right\}"), ("Set(Mul(Infinity, Infinity), Mul(Mul(a, b), Infinity), Mul(NumberI, Infinity), Mul(Infinity, NumberI))", r"\left\{\infty \cdot \infty, a b \cdot \infty, i \cdot \infty, \infty i\right\}"), ("ArgMin(Add(f(x), g(x)), For(x, RR), NotEqual(x, 0))", r"\mathop{\operatorname{arg\,min}\,}\limits_{x \in \mathbb{R},\,x \ne 0} \left[f(x) + g(x)\right]"), ("List(ArgMin(f(x), For(x, S)), ArgMax(f(x), For(x, S)), ArgMin(f(x), For(x, S), P(x)), ArgMax(f(x), For(x, S), P(x)))", r"\left[\mathop{\operatorname{arg\,min}\,}\limits_{x \in S} f(x), \mathop{\operatorname{arg\,max}\,}\limits_{x \in S} f(x), \mathop{\operatorname{arg\,min}\,}\limits_{x \in S,\,P(x)} f(x), \mathop{\operatorname{arg\,max}\,}\limits_{x \in S,\,P(x)} f(x)\right]"), ("List(Minimum(f(x), For(x, S)), Maximum(f(x), For(x, S)), Minimum(f(x), For(x, S), P(x)), Maximum(f(x), For(x, S), P(x)))", r"\left[\mathop{\min\,}\limits_{x \in S} f(x), \mathop{\max\,}\limits_{x \in S} f(x), \mathop{\min\,}\limits_{x \in S,\,P(x)} f(x), \mathop{\max\,}\limits_{x \in S,\,P(x)} f(x)\right]"), ("List(ArgMinUnique(f(x), For(x, S)), ArgMaxUnique(f(x), For(x, S)), ArgMinUnique(f(x), For(x, S), P(x)), ArgMaxUnique(f(x), For(x, S), P(x)))", r"\left[\mathop{\operatorname{arg\,min*}\,}\limits_{x \in S} f(x), \mathop{\operatorname{arg\,max*}\,}\limits_{x \in S} f(x), \mathop{\operatorname{arg\,min*}\,}\limits_{x \in S,\,P(x)} f(x), \mathop{\operatorname{arg\,max*}\,}\limits_{x \in S,\,P(x)} f(x)\right]"), ("List(Infimum(f(x), For(x, S)), Supremum(f(x), For(x, S)), Infimum(f(x), For(x, S), P(x)), Supremum(f(x), For(x, S), P(x)))", r"\left[\mathop{\operatorname{inf}\,}\limits_{x \in S} f(x), \mathop{\operatorname{sup}\,}\limits_{x \in S} f(x), \mathop{\operatorname{inf}\,}\limits_{x \in S,\,P(x)} f(x), \mathop{\operatorname{sup}\,}\limits_{x \in S,\,P(x)} f(x)\right]"), ("List(Solutions(Q(x), For(x, S)), Zeros(f(x), For(x, S)), Solutions(Q(x), For(x, S), P(x)), Zeros(f(x), For(x, S), P(x)))", r"\left[\mathop{\operatorname{solutions}\,}\limits_{x \in S} Q(x), \mathop{\operatorname{zeros}\,}\limits_{x \in S} f(x), \mathop{\operatorname{solutions}\,}\limits_{x \in S,\,P(x)} Q(x), \mathop{\operatorname{zeros}\,}\limits_{x \in S,\,P(x)} f(x)\right]"), ("List(UniqueSolution(Q(x), For(x, S)), UniqueZero(f(x), For(x, S)), UniqueSolution(Q(x), For(x, S), P(x)), UniqueZero(f(x), For(x, S), P(x)))", r"\left[\mathop{\operatorname{solution*}\,}\limits_{x \in S} Q(x), \mathop{\operatorname{zero*}\,}\limits_{x \in S} f(x), \mathop{\operatorname{solution*}\,}\limits_{x \in S,\,P(x)} Q(x), \mathop{\operatorname{zero*}\,}\limits_{x \in S,\,P(x)} f(x)\right]"), ("Sum(f(n) + g(n), For(n, a, b))", r"\sum_{n=a}^{b} \left(f(n) + g(n)\right)"), ("Sum(f(n), For(n, ZZ))", r"\sum_{n \in \mathbb{Z}} f(n)"), ("Sum(f(n), For(n, ZZ), NotEqual(n, 0))", r"\sum_{\textstyle{n \in \mathbb{Z} \atop n \ne 0}} f(n)"), ("Sum(f(n), For(n, a, b), NotEqual(n, 0))", r"\sum_{\textstyle{n=a \atop n \ne 0}}^{b} f(n)"), ("Sum(f(n), For(n, a, b))", r"\sum_{n=a}^{b} f(n)"), ("Product(f(n) + g(n), For(n, a, b))", r"\prod_{n=a}^{b} \left(f(n) + g(n)\right)"), ("Product(f(n), For(n, NN))", r"\prod_{n \in \mathbb{N}} f(n)"), ("Product(f(n), For(n, NN), NotEqual(g(n), 0))", r"\prod_{\textstyle{n \in \mathbb{N} \atop g(n) \ne 0}} f(n)"), ("Product(f(n), For(n, a, b), NotEqual(n, 0))", r"\prod_{\textstyle{n=a \atop n \ne 0}}^{b} f(n)"), ("Product(f(n), For(n, a, b))", r"\prod_{n=a}^{b} f(n)"), ("Equal(Set(f(n), For(n, ZZ)), Union(Set(f(n), For(n, ZZ), IsEven(n)), Set(f(n), For(n, ZZ), IsOdd(n))))", r"\left\{ f(n) : n \in \mathbb{Z} \right\} = \left\{ f(n) : n \in \mathbb{Z}\,\mathbin{\operatorname{and}}\, n \text{ even} \right\} \cup \left\{ f(n) : n \in \mathbb{Z}\,\mathbin{\operatorname{and}}\, n \text{ odd} \right\}"), ("Equal(Primes, Set(p, For(p, NN), IsPrime(p)))", r"\mathbb{P} = \left\{ p : p \in \mathbb{N}\,\mathbin{\operatorname{and}}\, p \text{ prime} \right\}"), ("Equal(Sum(f(n), Element(n, ZZ)), Add(Sum(f(n), Element(n, ZZ), IsOdd(n)), Sum(f(n), Element(n, ZZ), IsEven(n))))", r"\sum_{n \in \mathbb{Z}} f(n) = \sum_{\textstyle{n \in \mathbb{Z} \atop n \text{ odd}}} f(n) + \sum_{\textstyle{n \in \mathbb{Z} \atop n \text{ even}}} f(n)"), ("Set(DivisorSum(f(d), For(d, n)), DivisorSum(f(d), For(d, n), IsOdd(d)), DivisorSum(Add(f(d), g(d)), For(d, n)))", r"\left\{\sum_{d \mid n} f(d), \sum_{d \mid n,\, d \text{ odd}} f(d), \sum_{d \mid n} \left(f(d) + g(d)\right)\right\}"), ("Set(DivisorProduct(f(d), For(d, n)), DivisorProduct(f(d), For(d, n), IsOdd(d)), DivisorProduct(Add(f(d), g(d)), For(d, n)))", r"\left\{\prod_{d \mid n} f(d), \prod_{d \mid n,\, d \text{ odd}} f(d), \prod_{d \mid n} \left(f(d) + g(d)\right)\right\}"), ("Set(PrimeSum(f(p), For(p)), PrimeSum(f(p), For(p), NotElement(p, S)), PrimeProduct(f(p), For(p)), PrimeProduct(f(p), For(p), NotElement(p, S)))", r"\left\{\sum_{p} f(p), \sum_{p \notin S} f(p), \prod_{p} f(p), \prod_{p \notin S} f(p)\right\}"), ("Integral(f(x), For(x, -Infinity, Infinity))", r"\int_{-\infty}^{\infty} f(x) \, dx"), ("Integral(f(x), For(x, RR))", r"\int_{x \in \mathbb{R}} f(x) \, dx"), ("Integral(f(x) + g(x) / h(x), For(x, a, b))", r"\int_{a}^{b} \left(f(x) + \frac{g(x)}{h(x)}\right) \, dx"), ("Set(Derivative(f(x_), For(x_, x)), Derivative(f(x_), For(x_, Div(x, y))), Derivative(Gamma(x_), For(x_, 1)))", r"\left\{f'\!\left(x\right), f'\!\left(\frac{x}{y}\right), \Gamma'\!\left(1\right)\right\}"), ("Set(Derivative(f(x_), For(x_, x, 0)), Derivative(f(x_), For(x_, x, 1)), Derivative(f(x_), For(x_, x, 2)), Derivative(f(x_), For(x_, x, 3)), Derivative(f(x_), For(x_, x, 4)), Derivative(f(x_), For(x_, x, n)), Derivative(f(x_), For(x_, x, Add(Mul(2, n), 3))))", r"\left\{{f}^{(0)}\!\left(x\right), f'\!\left(x\right), f''\!\left(x\right), f'''\!\left(x\right), {f}^{(4)}\!\left(x\right), {f}^{(n)}\!\left(x\right), {f}^{(2 n + 3)}\!\left(x\right)\right\}"), ("Set(Derivative(f(Add(x, 1)), For(x, x)), Derivative(f(Add(x, 1)), For(x, x, 0)), Derivative(f(Add(x, 1)), For(x, x, 1)), Derivative(f(Add(x, 1)), For(x, x, n)))", r"\left\{\frac{d}{d x}\, f\!\left(x + 1\right), \frac{d^{0}}{{d x}^{0}}\, f\!\left(x + 1\right), \frac{d}{d x}\, f\!\left(x + 1\right), \frac{d^{n}}{{d x}^{n}}\, f\!\left(x + 1\right)\right\}"), ("Set(Derivative(Add(f(x), g(x)), For(x, Add(y, 3))), Derivative(Add(f(x), g(x)), For(x, Add(y, 3), 5)))", r"\left\{\left[\frac{d}{d x}\, \left[f(x) + g(x)\right] \right]_{x = y + 3}, \left[\frac{d^{5}}{{d x}^{5}}\, \left[f(x) + g(x)\right] \right]_{x = y + 3}\right\}"), ("Set(RealDerivative(f(x), For(x, 1)), ComplexDerivative(f(x), For(x, 1)), ComplexBranchDerivative(f(x), For(x, 1)), MeromorphicDerivative(f(x), For(x, 1)))", r"\left\{f'\!\left(1\right), f'\!\left(1\right), f'\!\left(1\right), f'\!\left(1\right)\right\}"), ("Set(Limit(f(x), For(x, a)), Limit(f(x), For(x, a), P(x)))", r"\left\{\lim_{x \to a} f(x), \lim_{x \to a,\,P(x)} f(x)\right\}"), ("Set(Limit(f(x), For(x, a)), RealLimit(f(x), For(x, a)), ComplexLimit(f(x), For(x, a)), MeromorphicLimit(f(x), For(x, a)))", r"\left\{\lim_{x \to a} f(x), \lim_{x \to a} f(x), \lim_{x \to a} f(x), \lim_{x \to a} f(x)\right\}"), ("Set(LeftLimit(f(x), For(x, 0)), RightLimit(f(x), For(x, 0)))", r"\left\{\lim_{x \to {0}^{-}} f(x), \lim_{x \to {0}^{+}} f(x)\right\}"), ("Set(SequenceLimit(f(n), For(n, Infinity)), SequenceLimitInferior(f(n), For(n, Infinity)), SequenceLimitSuperior(f(n), For(n, Infinity)))", r"\left\{\lim_{n \to \infty} f(n), \liminf_{n \to \infty} f(n), \limsup_{n \to \infty} f(n)\right\}"), ("Sub(Limit(Add(f(x), g(x)), For(x, a)), Limit(Sub(f(x), g(x)), For(x, a)))", r"\lim_{x \to a} \left[f(x) + g(x)\right] - \lim_{x \to a} \left[f(x) - g(x)\right]"), ("Divides(GCD(a, b), LCM(a, b))", r"\gcd(a, b) \mid \operatorname{lcm}(a, b)"), ("Set(Exp(x), Exp(Div(3, 2)), Exp(Add(Neg(Pow(x, 2)), x)), Exp(Abs(Im(z))), Exp(Div(3, Add(2, x))), Exp(Sin(x)))", r"\left\{e^{x}, e^{3 / 2}, e^{-{x}^{2} + x}, e^{\left|\operatorname{Im}(z)\right|}, \exp\!\left(\frac{3}{2 + x}\right), \exp\!\left(\sin(x)\right)\right\}"), ("Add(Sin(x), Cos(x), Tan(x), Cot(x), Sec(x), Csc(x))", r"\sin(x) + \cos(x) + \tan(x) + \cot(x) + \sec(x) + \csc(x)"), ("Add(Sinh(x), Cosh(x), Tanh(x), Coth(x), Sech(x), Csch(x))", r"\sinh(x) + \cosh(x) + \tanh(x) + \coth(x) + \operatorname{sech}(x) + \operatorname{csch}(x)"), ("Add(Asin(x), Acos(x), Atan(x), Acot(x), Asec(x), Acsc(x))", r"\operatorname{asin}(x) + \operatorname{acos}(x) + \operatorname{atan}(x) + \operatorname{acot}(x) + \operatorname{asec}(x) + \operatorname{acsc}(x)"), ("Add(Asinh(x), Acosh(x), Atanh(x), Acoth(x), Asech(x), Acsch(x))", r"\operatorname{asinh}(x) + \operatorname{acosh}(x) + \operatorname{atanh}(x) + \operatorname{acoth}(x) + \operatorname{asech}(x) + \operatorname{acsch}(x)"), ("Exp(Neg(Euler))", r"e^{-\gamma}"), ("Set(Re(z), Im(z), Atan2(y, x))", r"\left\{\operatorname{Re}(z), \operatorname{Im}(z), \operatorname{atan2}(y, x)\right\}"), ("Add(NumberE, GoldenRatio, CatalanConstant)", r"e + \varphi + G"), ("Add(Sinc(x), Pow(Sinc(x), 2))", r"\operatorname{sinc}(x) + \operatorname{sinc}^{2}\!\left(x\right)"), ("AGM(a, b)", r"\operatorname{agm}(a, b)"), ("And(Equal(LogBarnesG(z), Log(BarnesG(z))), Equal(LogGamma(z), Log(Gamma(z))))", r"\log G(z) = \log\!\left(G(z)\right) \;\mathbin{\operatorname{and}}\; \log \Gamma(z) = \log\!\left(\Gamma(z)\right)"), ("DirichletL(s, chi)", r"L(s, \chi)"), ("DirichletLambda(s, chi)", r"\Lambda(s, \chi)"), ("Implies(GeneralizedRiemannHypothesis, RiemannHypothesis)", r"\operatorname{GRH} \;\implies\; \operatorname{RH}"), ("Set(ModularJ(tau), ModularLambda(tau), JacobiTheta(n, z, tau))", r"\left\{j(\tau), \lambda(\tau), \theta_{n}\!\left(z, \tau\right)\right\}"), ("Set(WeierstrassP(z, tau), WeierstrassSigma(z, tau), WeierstrassZeta(z, tau))", r"\left\{\wp(z, \tau), \sigma(z, \tau), \zeta(z, \tau)\right\}"), ("Mul(ChebyshevT(n, x), ChebyshevU(n, x))", r"T_{n}\!\left(x\right) U_{n}\!\left(x\right)"), ("Add(FresnelC(z), FresnelS(z))", r"C(z) + S(z)"), ("Div(EisensteinE(Mul(2, n), tau), EisensteinG(Mul(2, n), tau))", r"\frac{E_{2 n}\!\left(\tau\right)}{G_{2 n}\!\left(\tau\right)}"), ("Equal(Div(IncompleteBeta(z, a, b), IncompleteBetaRegularized(z, a, b)), BetaFunction(a, b))", r"\frac{\mathrm{B}_{z}\!\left(a, b\right)}{I_{z}\!\left(a, b\right)} = \mathrm{B}(a, b)"), ("Set(PolyLog(s, z), HurwitzZeta(s, z), LerchPhi(z, s, a))", r"\left\{\operatorname{Li}_{s}\!\left(z\right), \zeta(s, z), \Phi(z, s, a)\right\}"), ("Equal(PartitionsP(n), Mul(Div(1, n), Sum(Mul(DivisorSigma(1, Sub(n, k)), PartitionsP(k)), For(k, 0, Sub(n, 1)))))", r"p(n) = \frac{1}{n} \sum_{k=0}^{n - 1} \sigma_{1}\!\left(n - k\right) p(k)"), ("MultiZetaValue(a, b, c)", r"\zeta(a, b, c)"), ("RiemannXi(s)", r"\xi(s)"), ("Mul(LiouvilleLambda(n), EulerPhi(n), MoebiusMu(n))", r"\lambda(n) \varphi(n) \mu(n)"), ("BetaFunction(a, b)", r"\mathrm{B}(a, b)"), ("PrimePi(x)", r"\pi(x)"), ("Equal(Min(a, b), Neg(Max(Neg(a), Neg(b))))", r"\min(a, b) = -\max\!\left(-a, -b\right)"), ("Equal(Arg(z), Div(Pi, 2))", r"\arg(z) = \frac{\pi}{2}"), ("NotEqual(Csgn(z), Sign(z))", r"\operatorname{csgn}(z) \ne \operatorname{sgn}(z)"), ("Add(Factorial(0), Factorial(1), Div(1, Factorial(-3)), Factorial(Div(1, 2)), Factorial(Factorial(n)), DoubleFactorial(n))", r"0! + 1! + \frac{1}{\left(-3\right)!} + \left(\frac{1}{2}\right)! + \left(n!\right)! + n!!"), ("List(Binomial(x, n), RisingFactorial(x, n), FallingFactorial(x, n), StirlingCycle(x, n), StirlingS1(x, n), StirlingS2(x, n))", r"\left[{x \choose n}, \left(x\right)_{n}, \left(x\right)^{\underline{n}}, \left[{x \atop n}\right], s\!\left(x, n\right), \left\{{x \atop n}\right\}\right]"), ("Add(BellNumber(5), BernoulliB(5), EulerE(5), Fibonacci(5), HarmonicNumber(5), Prime(5), RiemannZetaZero(5))", r"\operatorname{B}_{5} + B_{5} + E_{5} + F_{5} + H_{5} + p_{5} + \rho_{5}"), ("List(LegendreSymbol(p, q), JacobiSymbol(p, q), KroneckerSymbol(p, q))", r"\left[\left(\frac{p}{q}\right), \left(\frac{p}{q}\right), \left(\frac{p}{q}\right)\right]"), ("Add(ExpIntegralEi(x), ExpIntegralE(n, x), SinIntegral(x), SinhIntegral(x), CosIntegral(x), CoshIntegral(x), LogIntegral(x))", r"\operatorname{Ei}(x) + E_{n}\!\left(x\right) + \operatorname{Si}(x) + \operatorname{Shi}(x) + \operatorname{Ci}(x) + \operatorname{Chi}(x) + \operatorname{li}(x)"), ("Mul(BesselJ(nu, z), BesselI(nu, z), BesselY(nu, z), BesselK(nu, z))", r"J_{\nu}\!\left(z\right) I_{\nu}\!\left(z\right) Y_{\nu}\!\left(z\right) K_{\nu}\!\left(z\right)"), ("Equal(AiryAi(AiryAiZero(n)), AiryBi(AiryBiZero(n)), 0)", r"\operatorname{Ai}\!\left(a_{n}\right) = \operatorname{Bi}\!\left(b_{n}\right) = 0"), ("Equal(BesselJ(nu, BesselJZero(nu, n)), BesselY(nu, BesselYZero(nu, n)), 0)", r"J_{\nu}\!\left(j_{\nu, n}\right) = Y_{\nu}\!\left(y_{\nu, n}\right) = 0"), ("Equal(RiemannZeta(s), Mul(Mul(Mul(Mul(2, Pow(Mul(2, Pi), Sub(s, 1))), Sin(Div(Mul(Pi, s), 2))), Gamma(Sub(1, s))), RiemannZeta(Sub(1, s))))", r"\zeta(s) = 2 {\left(2 \pi\right)}^{s - 1} \sin\!\left(\frac{\pi s}{2}\right) \Gamma\!\left(1 - s\right) \zeta\!\left(1 - s\right)"), ("Pow(Div(Pow(DedekindEta(Mul(2, tau)), 2), Mul(DedekindEta(tau), DedekindEta(Mul(4, tau)))), 24)", r"{\left(\frac{\eta^{2}\!\left(2 \tau\right)}{\eta(\tau) \eta\!\left(4 \tau\right)}\right)}^{24}"), ("Mul(Mul(Erf(z), Erfc(z)), Erfi(z))", r"\operatorname{erf}(z) \operatorname{erfc}(z) \operatorname{erfi}(z)"), ("Mul(EllipticK(m), EllipticE(m), EllipticPi(n, m))", r"K(m) E(m) \Pi(n, m)"), ("Mul(IncompleteEllipticE(z, m), IncompleteEllipticF(z, m), IncompleteEllipticPi(n, z, m))", r"E(z, m) F(z, m) \Pi(n, z, m)"), ("Add(CarlsonRF(x, y, z), CarlsonRG(x, y, z), CarlsonRJ(x, y, z, w), CarlsonRD(x, y, z), CarlsonRC(x, y))", r"R_F(x, y, z) + R_G(x, y, z) + R_J(x, y, z, w) + R_D(x, y, z) + R_C(x, y)"), ("Mul(Hypergeometric0F1(b, z), Hypergeometric0F1Regularized(b, z))", r"\,{}_0F_1(b, z) \,{}_0{\textbf F}_1(b, z)"), ("Mul(Hypergeometric1F1(a, b, z), Hypergeometric1F1Regularized(a, b, z))", r"\,{}_1F_1(a, b, z) \,{}_1{\textbf F}_1(a, b, z)"), ("Hypergeometric2F0(a, b, z)", r"\,{}_2F_0(a, b, z)"), ("Mul(HypergeometricU(a, b, z), HypergeometricUStar(a, b, z))", r"U(a, b, z) U^{*}(a, b, z)"), ("Mul(Hypergeometric2F1(a, b, c, z), Hypergeometric2F1Regularized(a, b, c, z))", r"\,{}_2F_1(a, b, c, z) \,{}_2{\textbf F}_1(a, b, c, z)"), ("Mul(Hypergeometric1F2(a, b, c, z), Hypergeometric1F2Regularized(a, b, c, z))", r"\,{}_1F_2(a, b, c, z) \,{}_1{\textbf F}_2(a, b, c, z)"), ("Mul(Hypergeometric2F2(a, b, c, d, z), Hypergeometric2F2Regularized(a, b, c, d, z))", r"\,{}_2F_2(a, b, c, d, z) \,{}_2{\textbf F}_2(a, b, c, d, z)"), ("Mul(Hypergeometric3F2(a, b, c, d, e, z), Hypergeometric3F2Regularized(a, b, c, d, e, z))", r"\,{}_3F_2(a, b, c, d, e, z) \,{}_3{\textbf F}_2(a, b, c, d, e, z)"), ("(Hypergeometric2F1Regularized(Div(-1,4),Div(1,4),1/2, (x-1)/2)**2)", r"{\left(\,{}_2{\textbf F}_1\!\left(-\frac{1}{4}, \frac{1}{4}, \frac{1}{2}, \frac{x - 1}{2}\right)\right)}^{2}"), ("Matrix(List(List(a, b, c), List(d, e, f), List(g, h, 0)))", r"\displaystyle{\begin{pmatrix}a & b & c \\d & e & f \\g & h & 0\end{pmatrix}}"), ("Matrix2x2(a, b, c, d)", r"\displaystyle{\begin{pmatrix}a & b \\ c & d\end{pmatrix}}"), ("Set(RowMatrix(), RowMatrix(a), RowMatrix(a, b), RowMatrix(a, b, c), RowMatrix(a, b, c, d))", r"\left\{\displaystyle{\begin{pmatrix}\end{pmatrix}}, \displaystyle{\begin{pmatrix}a\end{pmatrix}}, \displaystyle{\begin{pmatrix}a & b\end{pmatrix}}, \displaystyle{\begin{pmatrix}a & b & c\end{pmatrix}}, \displaystyle{\begin{pmatrix}a & b & c & d\end{pmatrix}}\right\}"), ("Set(ColumnMatrix(), ColumnMatrix(a), ColumnMatrix(a, b), ColumnMatrix(a, b, c), ColumnMatrix(a, b, c, d))", r"\left\{\displaystyle{\begin{pmatrix}\end{pmatrix}}, \displaystyle{\begin{pmatrix}a\end{pmatrix}}, \displaystyle{\begin{pmatrix}a \\ b\end{pmatrix}}, \displaystyle{\begin{pmatrix}a \\ b \\ c\end{pmatrix}}, \displaystyle{\begin{pmatrix}a \\ b \\ c \\ d\end{pmatrix}}\right\}"), ("Set(DiagonalMatrix(), DiagonalMatrix(a), DiagonalMatrix(a, b), DiagonalMatrix(a, b, c), DiagonalMatrix(a, b, c, d))", r"\left\{\displaystyle{\begin{pmatrix}\end{pmatrix}}, \displaystyle{\begin{pmatrix}a\end{pmatrix}}, \displaystyle{\begin{pmatrix}a & \\ & b\end{pmatrix}}, \displaystyle{\begin{pmatrix}a & & \\ & b & \\ & & c\end{pmatrix}}, \displaystyle{\begin{pmatrix}a & & & \\ & b & & \\ & & c & \\ & & & d\end{pmatrix}}\right\}"), ("Matrix(c_(m, n), For(m, 1, N), For(n, 1, 10))", r"\displaystyle{\begin{pmatrix} c_{1, 1} & c_{1, 2} & \cdots & c_{1, 10} \\ c_{2, 1} & c_{2, 2} & \cdots & c_{2, 10} \\ \vdots & \vdots & \ddots & \vdots \\ c_{N, 1} & c_{N, 2} & \cdots & c_{N, 10} \end{pmatrix}}"), ("Matrix(ShowExpandedNormalForm(Div(1, Sub(Add(m, n), 1))), For(m, 1, 10), For(n, 1, 10))", r"\displaystyle{\begin{pmatrix} 1 & \frac{1}{2} & \cdots & \frac{1}{10} \\ \frac{1}{2} & \frac{1}{3} & \cdots & \frac{1}{11} \\ \vdots & \vdots & \ddots & \vdots \\ \frac{1}{10} & \frac{1}{11} & \cdots & \frac{1}{19} \end{pmatrix}}"), ("Add(ZeroMatrix(2), IdentityMatrix(2), HilbertMatrix(2))", r"0_{2} + I_{2} + H_{2}"), ("Set(SpecialLinearGroup(n, ZZ), GeneralLinearGroup(n, ZZ))", r"\left\{\operatorname{SL}_{n}\!\left(\mathbb{Z}\right), \operatorname{GL}_{n}\!\left(\mathbb{Z}\right)\right\}"), ("Equal(One(QQ), 1)", r"1_{\mathbb{Q}} = 1"), ("Equal(Zero(QQ), 0)", r"0_{\mathbb{Q}} = 0"), ("List(Polynomials(QQ, x), Polynomials(QQ, x, y), Polynomials(QQ, Tuple()), Polynomials(QQ, Tuple(x)), Polynomials(QQ, Tuple(x, y)))", r"\left[\mathbb{Q}[x], \mathbb{Q}[x, y], \mathbb{Q}[], \mathbb{Q}[x], \mathbb{Q}[x, y]\right]"), ("List(Polynomials(QQ, x), PolynomialFractions(QQ, x), FormalPowerSeries(QQ, x), FormalLaurentSeries(QQ, x), FormalPuiseuxSeries(QQ, x))", r"\left[\mathbb{Q}[x], \mathbb{Q}(x), \mathbb{Q}[[x]], \mathbb{Q}(\!(x)\!), \mathbb{Q}\!\left\langle\!\left\langle x \right\rangle\!\right\rangle\right]"), ("Set(IntegersGreaterEqual(0), IntegersGreaterEqual(n), IntegersLessEqual(0), IntegersLessEqual(n))", r"\left\{\mathbb{Z}_{\ge 0}, \mathbb{Z}_{\ge n}, \{0, -1, \ldots\}, \mathbb{Z}_{\le n}\right\}"), ("List(Range(a, b), Range(1, b), Range(-3, 5))", r"\left[\{a, a + 1, \ldots, b\}, \{1, 2, \ldots, b\}, \{-3, -2, \ldots, 5\}\right]"), ("CongruentMod(f(n), 0, p)", r"f(n) \equiv 0 \pmod {p }"), ("PrimitiveReducedPositiveIntegralBinaryQuadraticForms(D)", r"\mathcal{Q}^{*}_{D}"), ("Set(EllipticRootE(1, tau), EllipticRootE(2, tau), EllipticRootE(3, tau))", r"\left\{e_{1}\!\left(\tau\right), e_{2}\!\left(\tau\right), e_{3}\!\left(\tau\right)\right\}"), ("GaussSum(n, chi)", r"G_{n}\!\left(\chi\right)"), ("Set(GlaisherConstant, KhinchinConstant)", r"\left\{A, K\right\}"), ('Decimal("0.3141")', r"0.3141"), ('Decimal("0.3141e-27")', r"0.3141 \cdot 10^{-27}"), ("Set(DigammaFunction(z), DigammaFunction(z, 1), DigammaFunction(z, n))", r"\left\{\psi(z), \psi'\!\left(z\right), {\psi}^{(n)}\!\left(z\right)\right\}"), ("Set(AiryAi(z, 1), AiryAi(z, 2), AiryBi(z, n), BesselJ(n, z, 1), BesselY(n, z, 2), BesselK(n, z, Add(Mul(3, r), 1)))", r"\left\{\operatorname{Ai}'\!\left(z\right), \operatorname{Ai}''\!\left(z\right), {\operatorname{Bi}}^{(n)}\!\left(z\right), J'_{n}\!\left(z\right), Y''_{n}\!\left(z\right), {K}^{(3 r + 1)}_{n}\!\left(z\right)\right\}"), ("Set(HankelH1(n, z), HankelH2(n, z))", r"\left\{H^{(1)}_{n}\!\left(z\right), H^{(2)}_{n}\!\left(z\right)\right\}"), ("Element(DirichletCharacter(q, k), PrimitiveDirichletCharacters(q))", r"\chi_{q \, . \, k} \in G^{\text{Primitive}}_{q}"), ("DirichletCharacter(q, k, n)", r"\chi_{q \, . \, k}(n)"), ("JacobiTheta(3, z, tau, 2)", r"\theta''_{3}\!\left(z, \tau\right)"), ("Set(RiemannZeta(s, 1), RiemannZeta(s, r))", r"\left\{\zeta'\!\left(s\right), {\zeta}^{(r)}\!\left(s\right)\right\}"), ("Subscript(x, y)", r"{x}_{y}"), ("Set(BernsteinEllipse(r), UnitCircle, PSL2Z, AGMSequence(n, a, b), CarlsonHypergeometricR, CarlsonHypergeometricT)", r"\left\{\mathcal{E}_{r}, \mathbb{T}, \operatorname{PSL}_2(\mathbb{Z}), \operatorname{agm}_{n}\!\left(a, b\right), R, T\right\}"), ("Mul(Mul(Pow(Fibonacci(n), 2), Pow(x_(a), 2)), Pow(alpha_(n), 2))", r"F_{n}^{2} x_{a}^{2} \alpha_{n}^{2}"), ("Set(Derivative(ChebyshevT(n, x_), For(x_, x)), Derivative(ChebyshevT(n, x_), For(x_, x, 2)), Derivative(ChebyshevT(n, x_), For(x_, x, 4)))", r"\left\{T'_{n}\!\left(x\right), T''_{n}\!\left(x\right), {T}^{(4)}_{n}\!\left(x\right)\right\}"), ("Poles(Gamma(z), For(z, CC))", r"\mathop{\operatorname{poles}\,}\limits_{z \in \mathbb{C}} \Gamma(z)"), ("Equal(Item(Tuple(a, b, c), 2), b)", r"{\left(a, b, c\right)}_{2} = b"), ("Set(Tuple(n, For(n, a, b)), List(Pow(Neg(n), 2), For(n, 1, 100)), Set(f_(n), For(n, 0, N)))", r"\left\{\left(a, a + 1, \ldots, b\right), \left[{\left(-1\right)}^{2}, {\left(-2\right)}^{2}, \ldots, {\left(-100\right)}^{2}\right], \left\{f_{0}, f_{1}, \ldots, f_{N}\right\}\right\}"), ("Set(Tuple(1, 0, Repeat(3, N)), Tuple(1, 0, Repeat(1, 2, 3, N)))", r"\left\{\left(1, 0, \underbrace{3, \ldots, 3}_{N \text{ times}}\right), \left(1, 0, \underbrace{1, 2, 3, \ldots, 1, 2, 3}_{\left(1, 2, 3\right) \; N \text{ times}}\right)\right\}"), ("Tuple(Sub(A, 2), Sub(A, 1), Step(n, For(n, A, B)), Add(B, 1), Add(B, 2))", r"\left(A - 2, A - 1, A, A + 1, \ldots, B, B + 1, B + 2\right)"), ("Lattice(1, tau)", r"\Lambda_{(1, \tau)}"), ("DiscreteLog(n, 2, q)", r"(\epsilon : {2}^{\epsilon} \equiv n \text{ mod }q)"), ("AsymptoticTo(f(n), g(n), n, Infinity)", r"f(n) \sim g(n), \; n \to \infty"), ("Set(CoulombF(l, eta, z), CoulombG(l, eta, z), CoulombH(1, l, eta, z), CoulombH(-1, l, eta, z), CoulombH(omega, l, eta, z))", r"\left\{F_{l,\eta}(z), G_{l,\eta}(z), H^{+}_{l,\eta}(z), H^{-}_{l,\eta}(z), H^{\omega}_{l,\eta}(z)\right\}"), ("Set(Matrices(CC, n), Matrices(CC, n, m))", r"\left\{\operatorname{M}_{n}(\mathbb{C}), \operatorname{M}_{n \times m}(\mathbb{C})\right\}"), ('Set(SloaneA(40, n), SloaneA(12345, n), SloaneA("A553322", n))', r"\left\{\text{A000040}\!\left(n\right), \text{A012345}\!\left(n\right), \text{A553322}\!\left(n\right)\right\}"), ('And(EqualAndElement(x, Pi, RR), EqualNearestDecimal(Pi, Decimal("3.14"), 3))', r"x = \pi \in \mathbb{R} \;\mathbin{\operatorname{and}}\; \pi = 3.14 \;\, {\scriptstyle (\text{nearest } 3 \text{ digits})}"), ("Less(0, Same(Div(1, Sqrt(2)), Div(Sqrt(2), 2)), 1)", r"0 < \frac{1}{\sqrt{2}} = \frac{\sqrt{2}}{2} < 1"), ("Fun(x, Pow(x, 2))", r"x \mapsto {x}^{2}"), ("GeneralizedBernoulliB(n, chi)", r"B_{n, \chi}"), ("HurwitzZeta(s, a, 2)", r"\zeta''\!\left(s, a\right)"), ("Set(StieltjesGamma(n), StieltjesGamma(n, a))", r"\left\{\gamma_{n}, \gamma_{n}\!\left(a\right)\right\}"), ("And(IsHolomorphicOn(f(z), For(z, CC)), IsMeromorphicOn(g(z), For(z, CC)))", r"f(z) \text{ is holomorphic on } z \in \mathbb{C} \;\mathbin{\operatorname{and}}\; g(z) \text{ is meromorphic on } z \in \mathbb{C}"), ("Set(StirlingSeriesRemainder(N, z), LogBarnesGRemainder(N, z))", r"\left\{R_{N}\!\left(z\right), R_{N}\!\left(z\right)\right\}"), ("AnalyticContinuation(f(z), For(z, a, b))", r"\mathop{\text{Continuation}}\limits_{\displaystyle{z: a \rightsquigarrow b}} \, f(z)"), ("AnalyticContinuation(f(z), For(z, CurvePath(g(t), For(t, a, b))))", r"\mathop{\text{Continuation}}\limits_{\displaystyle{z: \left(g(t),\, t : a \rightsquigarrow b\right)}} \, f(z)"), ("BernoulliPolynomial(n, x)", r"B_{n}\!\left(x\right)"), ("Call(f, x)", r"f(x)"), ("CallIndeterminate(f, x, v)", r"f(v)"), ("CartesianProduct(ZZ, QQ)", r"\mathbb{Z} \times \mathbb{Q}"), ("CartesianPower(RR, 3)", r"{\mathbb{R}}^{3}"), ("Characteristic(R)", r"\operatorname{char}(R)"), ("Coefficient(f, x, 2)", r"[{x}^{2}] f"), ("ComplexZeroMultiplicity(f(z), For(z, a))", r"\mathop{\operatorname{ord}}\limits_{z=a} f(z)"), ("Residue(f(z), For(z, a))", r"\mathop{\operatorname{res}}\limits_{z=a} f(z)"), ("ConreyGenerator(q)", r"g_{q}"), ("CoulombC(l, eta)", r"C_{l}\!\left(\eta\right)"), ("CoulombSigma(l, eta)", r"\sigma_{l}\!\left(\eta\right)"), ("Cyclotomic(n, x)", r"\Phi_{n}\!\left(x\right)"), ("DedekindEtaEpsilon(a, b, c, d)", r"\varepsilon(a, b, c, d)"), ("DedekindSum(a, b)", r"s(a, b)"), ("Where(f(Add(x, 1)), Def(f(t), Div(1, t)))", r"f\!\left(x + 1\right)\; \text{ where } f(t) = \frac{1}{t}"), ("Det(Matrix2x2(a, b, c, d))", r"\operatorname{det} \displaystyle{\begin{pmatrix}a & b \\ c & d\end{pmatrix}}"), ("Det(A)", r"\operatorname{det}(A)"), ("f(a, b, Ellipsis, z)", r"f(a, b, \ldots, z)"), ("Equal(DirichletL(DirichletLZero(n, chi), chi), 0)", r"L\!\left(\rho_{n, \chi}, \chi\right) = 0"), ("DirichletGroup(q)", r"G_{q}"), ("Set(ModularGroupFundamentalDomain, ModularLambdaFundamentalDomain)", r"\left\{\mathcal{F}, \mathcal{F}_{\lambda}\right\}"), ("Path(a, b, c, d)", r"a \rightsquigarrow b \rightsquigarrow c \rightsquigarrow d"), ("PolynomialDegree(f)", r"\deg(f)"), ("RootOfUnity(5)", r"\zeta_{5}"), ("SL2Z", r"\operatorname{SL}_2(\mathbb{Z})"), ("UpperHalfPlane", r"\mathbb{H}"), ("XGCD(m, n)", r"\operatorname{xgcd}(m, n)"), ("JacobiThetaQ(3, z, q)", r"\theta_{3}\!\left(z, q\right)"), ("KeiperLiLambda(n)", r"\lambda_{n}"), ("Set(LambertW(z), LambertW(z, n), LambertW(z, n, 1), LambertW(z, n, r))", r"\left\{W(z), W_{n}(z), W'_{n}(z), {W}^{(r)}_{n}(z)\right\}"), ("LandauG(n)", r"g(n)"), ("SquaresR(k, n)", r"r_{k}\!\left(n\right)"), ("ModularGroupAction(gamma, tau)", r"\gamma \circ \tau"), ("Mod(n, p)", r"n \bmod p"), ("LessEqual(0, Step(f(n), For(n, a, b)), 1)", r"0 \le f(a) \le f\!\left(a + 1\right) \le \ldots \le f(b) \le 1"), ("LessEqual(0, Step(f(n), For(n, 1, b)), 1)", r"0 \le f(1) \le f(2) \le \ldots \le f(b) \le 1"), ("Add(LowerGamma(s, z), UpperGamma(s, z))", r"\gamma(s, z) + \Gamma(s, z)"), ("DigammaFunctionZero(n)", r"x_{n}"), ("Set(EulerPolynomial(n, x), HermiteH(n, x), HilbertClassPolynomial(n, x))", r"\left\{E_{n}\!\left(x\right), H_{n}\!\left(x\right), H_{n}\!\left(x\right)\right\}"), ("JacobiThetaEpsilon(j, a, b, c, d)", r"\varepsilon_{j}\!\left(a, b, c, d\right)"), ("JacobiThetaPermutation(j, a, b, c, d)", r"S_{j}\!\left(a, b, c, d\right)"), ("SymmetricPolynomial(k, List(X_(t), For(t, 1, n)))", r"e_{k}\!\left(\left[X_{1}, X_{2}, \ldots, X_{n}\right]\right)"), ("Intersection(A, B)", r"A \cap B"), ("RealAlgebraicNumbers", r"\overline{\mathbb{Q}}_{\mathbb{R}}"), ] def test_latex(fexpr): namespace = fexpr.inject_dict() for formula, expected in latex_test_cases: expr = eval(formula, globals(), namespace) latex = expr.latex() if latex != expected: raise AssertionError("%s: got '%s', expected '%s'" % (formula, latex, expected)) test_latex(fexpr) def latex_report(fexpr): namespace = fexpr.inject_dict() formulas = [eval(formula, globals(), namespace) for formula, expected in latex_test_cases] from os.path import expanduser from time import time fp = open(expanduser("~/Desktop/latex_report.html"), "w") fp.write(""" fexpr to LaTeX test sheet """) output = [formula.latex() for formula in formulas] one_big = fexpr("BigLatex")(*formulas) t1 = time() one_big_latex = one_big.latex() t2 = time() fp.write("""

fexpr to LaTeX test sheet

""") fp.write("""

Converted %i formulas (%i leaves, %i bytes) to LaTeX in %f seconds.

""" % (len(formulas), one_big.num_leaves(), one_big.size_bytes(), (t2-t1))) fp.write("""""") fp.write("""""") for formula, latex in zip(formulas, output): fp.write("""""") fp.write("""""" % formula) fp.write("""""" % latex) fp.write("""""" % latex) fp.write("""""") fp.write("""
fexpr Generated LaTeX KaTeX display
%s%s$$%s$$
""") fp.write("""

Untested builtins:

""") s = str(one_big) for c in '-+()_,"': s = s.replace(c, " ") used = set(s.split()) builtins = [name.strip("_") for name in fexpr.builtins()] unused = [name for name in builtins if name not in used] for name in unused: fp.write(name) fp.write(" ") fp.write("""

""") fp.write("""""") fp.close() # latex_report(fexpr) def test_ca_trigonometric(): def expect_not_implemented(f): try: v = f() assert v except NotImplementedError: return raise AssertionError sqrt = CC_ca.sqrt pi = CC_ca.pi() xsin = CC_ca.sin xcos = CC_ca.cos xtan = CC_ca.tan a = 1+sqrt(2) b = 2+sqrt(2) assert xsin(a)**2 + xcos(a)**2 == 1 assert xsin(-a)**2 + xcos(a)**2 == 1 assert xsin(a) == -xsin(-a) assert xcos(a) == xcos(-a) assert xtan(a) == -xtan(-a) assert xsin(a+2*pi) == xsin(a) assert xcos(a+2*pi) == xcos(a) assert xtan(a+pi) == xtan(a) assert xsin(a+pi) == -xsin(a) assert xcos(a+pi) == -xcos(a) assert xtan(a+pi/2) == -1/xtan(a) assert xsin(a+pi/2) == xcos(a) assert xcos(a+pi/2) == -xsin(a) assert xsin(a-pi/2) == -xcos(a) assert xcos(a-pi/2) == xsin(a) assert xtan(a+pi/4) == (xtan(a)+1)/(1-xtan(a)) assert xtan(a-pi/4) == (xtan(a)-1)/(1+xtan(a)) assert xsin(pi/2 - a) == xcos(a) assert xcos(pi/2 - a) == xsin(a) assert xtan(pi/2 - a) == 1 / xtan(a) assert xsin(pi - a) == xsin(a) assert xcos(pi - a) == -xcos(a) assert xtan(pi - a) == -xtan(a) assert xsin(2*pi - a) == -xsin(a) assert xcos(2*pi - a) == xcos(a) assert xsin(a+b) == xsin(a)*xcos(b) + xcos(a)*xsin(b) assert xsin(a-b) == xsin(a)*xcos(b) - xcos(a)*xsin(b) assert xcos(a+b) == xcos(a)*xcos(b) - xsin(a)*xsin(b) assert xcos(a-b) == xcos(a)*xcos(b) + xsin(a)*xsin(b) assert xtan(a+b) == (xtan(a)+xtan(b)) / (1 - xtan(a)*xtan(b)) assert xtan(a-b) == (xtan(a)-xtan(b)) / (1 + xtan(a)*xtan(b)) assert xsin(2*a) == 2*xsin(a)*xcos(a) assert xsin(2*a) == 2*xtan(a)/(1+xtan(a)**2) assert xcos(2*a) == xcos(a)**2 - xsin(a)**2 assert xcos(2*a) == 2*xcos(a)**2 - 1 assert xcos(2*a) == 1 - 2*xsin(a)**2 assert xcos(2*a) == (1 - xtan(a)**2) / (1 + xtan(a)**2) assert xtan(2*a) == (2*xtan(a)) / (1 - xtan(a)**2) assert xsin(3*a) == 3*xsin(a) - 4*xsin(a)**3 assert xcos(3*a) == 4*xcos(a)**3 - 3*xcos(a) assert xtan(3*a) == (3*xtan(a) - xtan(a)**3) / (1 - 3*xtan(a)**2) assert xsin(a/2)**2 == (1-xcos(a))/2 assert xcos(a/2)**2 == (1+xcos(a))/2 assert xtan((a-b)/2) == (xsin(a) - xsin(b)) / (xcos(a) + xcos(b)) assert 2*xcos(a)*xcos(b) == xcos(a-b) + xcos(a+b) assert 2*xsin(a)*xsin(b) == xcos(a-b) - xcos(a+b) assert 2*xsin(a)*xcos(b) == xsin(a+b) + xsin(a-b) assert 2*xcos(a)*xsin(b) == xsin(a+b) - xsin(a-b) assert xsin(a) + xsin(b) == 2*xsin((a+b)/2)*xcos((a-b)/2) assert xsin(a) - xsin(b) == 2*xsin((a-b)/2)*xcos((a+b)/2) assert xcos(a) + xcos(b) == 2*xcos((a+b)/2)*xcos((a-b)/2) assert xcos(a) - xcos(b) == -2*xsin((a+b)/2)*xsin((a-b)/2) assert xsin(a) == sqrt(1 - xcos(a)**2) for N in range(1,17): assert sum(xcos(n*a) for n in range(1,N+1)) == xsin((N+ca(1)/2)*a)/(2*xsin(a/2)) - ca(1)/2 assert xcos(a) == -sqrt(1 - xsin(a)**2) assert xsin(a/2) == sqrt((1-xcos(a))/2) expect_not_implemented(lambda: xsin(3*a) == 4*xsin(a)*xsin(pi/3-a)*xsin(pi/3+a)) assert xtan((a+b)/2) == (xsin(a) + xsin(b)) / (xcos(a) + xcos(b)) assert xtan((a+b)/2) == (xsin(a) + xsin(b)) / (xcos(a) + xcos(b)) assert xtan(a)*xtan(b) == ((xcos(a-b)-xcos(a+b))/(xcos(a-b)+xcos(a+b))) def test_arb(): a = arb(2.5) assert a == arb("2.5") b = acb(2.5) assert a == b c = acb(2.5+1j) assert c == b + 1j assert raises(lambda: arb(2.5+1j), ValueError) assert acb(3+1j) == acb(ZZi(3+1j)) assert arb(ZZi(3)) == 3 assert raises(lambda: arb(ZZi(2.5+1j)), ValueError) def test_vec(): a = VecZZ([1,2,3]) b = VecQQ([2,3,4]) assert a[0] == 1 assert a[2] == 3 assert raises(lambda: a[-1], IndexError) assert raises(lambda: a[3], IndexError) assert a + a == VecZZ([2,4,6]) assert a + b == VecQQ([3,5,7]) assert b + a == VecQQ([3,5,7]) assert a + ZZ(1) == VecZZ([2,3,4]) assert ZZ(1) + a == VecZZ([2,3,4]) assert b + ZZ(1) == VecQQ([3,4,5]) assert ZZ(1) + b == VecQQ([3,4,5]) assert b ** -5 == 1 / b ** 5 assert raises(lambda: Vec(ZZi).i(), ValueError) i = ZZi.i() V = Vec(ZZi,3) assert V.i() == V([i,i,1j]) def test_all(): x = ZZ(23) y = ZZ(-1) assert str(x) == "23" assert x.parent() is ZZ assert int(x) == 23 assert x + y == ZZ(22) assert x - y == ZZ(24) assert x * y == ZZ(-23) assert -x == ZZ(-23) assert ZZ(3) != 4 assert ZZ(3) <= 5 assert ZZ(3) > 2 x = QQ(-10000000000000000000075) / QQ(3) assert str(x) == "-10000000000000000000075/3" assert x.parent() is QQ x = QQbar(-2) y = QQbar(1) / QQbar(3) assert x.parent() is QQbar xy = x ** y assert (xy ** QQbar(3)) == QQbar(-2) assert str(xy) == "Root a = 0.629961 + 1.09112*I of a^3+2" i = QQbar(-1) ** (QQ(1)/2) assert str(i) == 'Root a = 1.00000*I of a^2+1' assert str(-i) == 'Root a = -1.00000*I of a^2+1' assert str(1-i) == 'Root a = 1.00000 - 1.00000*I of a^2-2*a+2' assert raises(lambda: i > 0, ValueError) assert QQ(-3)/2 < i**2 < QQ(1)/2 assert abs(QQ(-5)) == QQ(5) assert QQ(8) ** (QQ(1) / QQ(3)) == QQ(2) assert raises(lambda: QQ(2) ** (QQ(1) / QQ(3)), ValueError) assert QQ(1) + 2 == QQ(3) assert 2 + QQ(1) == QQ(3) assert QQ(1) + ZZ(5) == QQ(6) assert (QQ(1) + ZZ(5)).parent() is QQ assert raises(lambda: ZZ(1) / 2, ValueError) assert raises(lambda: (-1) ** (QQ(1) / 2), ValueError) assert ((-1) ** (QQbar(1) / 2)) ** 2 == QQbar(-1) f = ZZx([1,2,3]) + QQx([1,2]) assert f == ZZx([2,4,3]) assert f.parent() is QQx assert RRx([1,QQ(2),AA(3)]) != ZZx([1,2,3,4]) assert RRx([1,QQ(2),AA(3),4]) == ZZx([1,2,3,4]) assert ZZx(3) + ZZx(2) == ZZx([5]) assert ZZx(3) + 2 == ZZx([5]) assert ZZx(QQ(5)) == 5 v = f(ZZ(3)) assert v == 41 assert v.parent() is ZZ QM2 = Mat(QQ,2,2) A = QM2([[1,2],[3,4]]) v = f(A) assert v == QM2([[27,38],[57,84]]) assert v.parent() is QM2 A = Mat(RR,2,2)([[1,2],[3,4]]) B = ZZx(list(range(10)))(A, algorithm="rectangular") assert B == Mat(QQ,2,2)([[9596853, 13986714], [20980071, 30576924]]) assert B.parent() is A.parent() assert CF(2+3j) * (1+1j) == CF((2+3j) * (1+1j)) assert ZZp64(QQ(1) / 3) * 3 == ZZp64(1) assert ZZp64(QQ(1)) ** (QQ(1) / 2) == 1 assert ZZp64(QQ(5)) ** (QQ(5)) == 3125 assert ZZp32(10001).sqrt() ** 2 == 10001 assert abs(VecZZ([-3,2,5])) == [3, 2, 5] b, t = PolynomialRing(PowerSeriesModRing(ZZ, 6, var="b"), "t").gens(recursive=True) assert (5+2*b+3*t)**5 / (5+2*b+3*t)**5 == 1 assert CCser(1+ZZser.gen()) == 1 + RRser.gen() def test_float(): assert RF(5).mul_2exp(-1) == RF(2.5) assert CF(2+3j).mul_2exp(-1) == CF(1+1.5j) def test_special(): a = ZZ.fib_vec(100) for i in range(100): assert ZZ.fib(i) == a[i] F = FiniteField_fq(17, 1) for i in range(-10,10): assert QQ.fib(i) == QQ.fib(i-1) + QQ.fib(i-2) assert F.fib(i) == F.fib(i-1) + F.fib(i-2) def test_mpoly(): ZZxyz = PolynomialRing_fmpz_mpoly(3) x, y, z = ZZxyz.gens() f = (-72 * (1+x)**2 * (y+z+1)) c, fac, exp = f.factor() assert c == -72 assert ((fac, exp) == ([1+x, y+z+1], [2, 1])) or ((fac, exp) == ([y+z+1, 1+x], [1, 2])) assert f.gcd(-100-100*x) == 4+4*x assert str(PolynomialRing_fmpz_mpoly(2).gens()) == '[x1, x2]' assert str(PolynomialRing_fmpz_mpoly(2, ["a", "b"]).gens()) == '[a, b]' assert str(PolynomialRing_gr_mpoly(ZZi, 2).gens()) == '[x1, x2]' I, x, y, z = PolynomialRing_gr_mpoly(ZZi, 3, ["x", "y", "z"]).gens(recursive=True) assert str(x) == "x" assert str(y) == "y" assert str(z) == "z" assert str(x-y) == "x - y" assert str(x+2*y) == "x + 2*y" assert str(x-2*y) == "x - 2*y" assert str(-x) == "-x" assert str(-3*x) == "-3*x" assert str(x+1) == "x + 1" assert str(x-1) == "x - 1" assert str(x+2) == "x + 2" assert str(x-2) == "x - 2" assert str(x*0) == "0" assert str(x**0) == "1" assert str(-x**0) == "-1" assert str(-2*x**0) == "-2" assert str(x*y*z) == "x*y*z" assert str(x*y**2*z) == "x*y^2*z" assert str(3*x*y**2*z) == "3*x*y^2*z" assert str((1+I)*x + I*y) == "(1+I)*x + I*y" assert str((1+I)*x - I*y) == "(1+I)*x - I*y" assert str(x+1+I) == "x + (1+I)" x, y = PolynomialRing_gr_mpoly(ZZx, 1, ["y"]).gens(recursive=True) assert str(x+1) == "(x+1)" assert str((x+1)*y) == "(x+1)*y" assert str((x+1)*y + (x+2)) == "(x+1)*y + (x+2)" assert str((x+1)*y**2 + (x+2)*y) assert str((x+1)*y**2 - (x+2)*y) == "(x+1)*y^2 + (-x-2)*y" assert str(FiniteField_fq(3, 2, "c").gen()) == "c" assert str(FiniteField_fq_nmod(3, 2, "d").gen()) == "d" assert str(FiniteField_fq_zech(3, 2, "e").gen()) == "e^1" def test_mpoly_q(): assert str(FractionField_fmpz_mpoly_q(2).gens()) == '[x1, x2]' assert str(FractionField_fmpz_mpoly_q(2, ["a", "b"]).gens()) == '[a, b]' def test_set_str(): assert RR("1/4") == RR(1)/4 v = RR("pi ^ (1 / 2)") assert 1.77 < v < 1.78 assert CC("1/2 + i/4") == 0.5+0.25j assert CC("(-1)^(1/2)") == 1j assert CF("(-1)^(1/2)") == 1j assert abs(RF("2^(1/2)") ** 2) - 2 < 1e-14 assert CC_ca("i*pi/2").exp() == CC_ca.i() assert ZZ("1 + 2^10") == 1025 x = ZZx.gen(); R = PolynomialRing_gr_mpoly(NumberField(x**3+x+1), 3, ["x", "y", "z"]) a, x, y, z = R.gens(recursive=True) assert R("((a-x+1)*y + (a^2+1)*y^2 + z)^2") == ((a-x+1)*y + (a**2+1)*y**2 + z)**2 x = ZZx.gen() R = NumberField(x**2+1, "b") assert R("b-1") == R.gen()-1 R = FractionField_fmpz_mpoly_q(2, ["x", "y"]) x, y = R.gens() assert R("(4+4*x-y*(-4))^2 / (1+x+y) / 16") == 1+x+y assert RRx("1 +/- 0") == RR(1) def test_ca_notebook_examples(): # algebraic number identity NumberI = fexpr("NumberI") Sqrt = fexpr("Sqrt") Div = fexpr("Div") I = NumberI lhs = Sqrt(36 + 3*(-54+35*I*Sqrt(3))**Div(1,3)*3**Div(1,3) + \ 117/(-162+105*I*Sqrt(3))**Div(1,3))/3 + \ Sqrt(5)*(1296*I+840*Sqrt(3)-35*3**Div(5,6)*(-54+35*I*Sqrt(3))**Div(1,3)-\ 54*I*(-162+105*I*Sqrt(3))**Div(1,3)+13*I*(-162+105*I*Sqrt(3))**Div(2,3))/(5*(162*I+105*Sqrt(3))) rhs = Sqrt(5) + Sqrt(7) i = CC_ca.i() pi = CC_ca.pi() exp = CC_ca.exp log = CC_ca.log sqrt = CC_ca.sqrt assert qqbar(lhs) == qqbar(rhs) assert ca(lhs) == ca(rhs) assert fexpr(ca(lhs) - ca(rhs)) == fexpr(0) # misc assert fexpr(exp(pi) * exp(-pi + log(2))) == fexpr(2) assert i**i - exp(pi / ((sqrt(-2)**sqrt(2)) ** sqrt(2))) == 0 assert log(sqrt(2)+sqrt(3)) / log(5 + 2*sqrt(6)) == ca(1)/2 assert ca(10)**-30 < (640320**3 + 744)/exp(pi*sqrt(163)) - 1 < ca(10)**-29 M = Mat(CC_ca, 2, 2) A = M([[5, pi], [1, -1]])**4 assert A.charpoly()(A) == M([[0,0],[0,0]]) # comparison with higher precision ctx = ComplexField_ca() ctx._set_options({"prec_limit":65536}) eps = ca(10, context=ctx) ** (-10000) assert (eps.exp() == 1) == False assert ZZ("0.000") == 0 assert ZZ("3.0") == 3 assert ZZ("-0.03e+2") == -3 assert ZZ("0e-100000000000000") == 0 assert raises(lambda: ZZ("0.1"), FlintUnableError) assert str(RR("(+/- 1e-3) + 0.1")) == "[0.1 +/- 1.01e-3]" assert str(RR("1/2 +/- 1/100000")) == "[0.5000 +/- 1.01e-5]" assert str(CC("(1+i) +/- (1e-5 + 1e-7*i)")) == "([1.0000 +/- 1.01e-5] + [1.000000 +/- 1.01e-7]*I)" assert str(CC("-1e23 +/- -5e12")) == "[-1.000000000e+23 +/- 5.01e+12]" assert RR("0.5 + 1") == 1.5 assert QQ("0.01") == QQ(1) / 100 assert QQ("1.01") == QQ(101) / 100 assert QQ("1.01e+1 + 1") == QQ(111) / 10 assert QQ("1.01e1 + 1") == QQ(111) / 10 assert QQ("1.01e-1 + 1") == QQ(1101) / 1000 assert RRx("0.75") == RRx(3)/4 assert CCx("0.75") == RRx(3)/4 assert str(RRx("(0.5 +/- 1e-10) + (0.6 +/- 1e-11)*x")) == "[0.500000000 +/- 1.01e-10] + [0.6000000000 +/- 1.01e-11]*x" assert str(RRx("(1 + x + x^2) +/- 0.003")) == "[1.00 +/- 3.01e-3] + x + x^2" assert str(RRx("(1 + x + x^2) +/- (0.003 + 0.004*x + 0.005*x^2 + 0.006*x^3)")) == "[1.00 +/- 3.01e-3] + [1.00 +/- 4.01e-3]*x + [1.00 +/- 5.01e-3]*x^2 + [+/- 6.01e-3]*x^3" assert str(RRx("1 + (+/- 1e-10)*x")) == "1 + [+/- 1.01e-10]*x" assert str(CCx("x +/- 1e-6*I*x")) == "(1.000000000000000 + [+/- 1.01e-6]*I)*x" with optimistic_logic: RRx(str(RRx("1+2*x")/3)) == RRx([1,2])/3 if __name__ == "__main__": from time import time print("Testing flint_ctypes") print("----------------------------------------------------------") for fname in dir(): if fname.startswith("test_"): print(fname + "...", end="") import sys sys.stdout.flush() t1 = time() globals()[fname]() t2 = time() print("PASS", end=" ") print("%.2f" % (t2-t1)) print("----------------------------------------------------------") import doctest __r = doctest.testmod(optionflags=(doctest.FAIL_FAST | doctest.ELLIPSIS), verbose=False)[0] if __r: sys.exit(__r) print("----------------------------------------------------------") flint-3.1.3/src/python/mpmath2.py000066400000000000000000000311401461254215100166640ustar00rootroot00000000000000# just for fun from mpmath.ctx_base import StandardBaseContext import flint2 import mpmath.libmp from mpmath.libmp import prec_to_dps, dps_to_prec class RFContext(StandardBaseContext): def __init__(ctx, RR, CC, QQ, ZZ): ctx.R = RR ctx.RR = RR ctx.CC = CC ctx.QQ = QQ ctx.ZZ = ZZ ctx._type = ctx.R() ctx.R.prec = 53 ctx._dps = prec_to_dps(53) StandardBaseContext.__init__(ctx) #ctx.pretty = False #ctx._init_aliases() ctx.zero = ctx.R() ctx.one = ctx.R(1) ctx.inf = ctx.R("inf") ctx.ninf = -ctx.inf ctx.nan = ctx.R("nan") # .j = ... @property def pi(ctx): return ctx.R.pi() @property def eps(ctx): return ctx.one * ctx.R(2)**(1 - ctx.prec) def mpf(ctx, val): return ctx.R(val) def mpc(ctx, val): return ctx.R(val) def _mpq(ctx, x): a, b = x return ctx.QQ(a) / b def convert(ctx, x): # todo: avoid copying return ctx.R(x) NoConvergence = mpmath.libmp.NoConvergence def _get_prec(ctx): return ctx.R.prec def _set_prec(ctx, p): p = max(1, int(p)) ctx.R.prec = p ctx._dps = prec_to_dps(p) def _get_dps(ctx): return ctx._dps def _set_dps(ctx, d): d = max(1, int(d)) ctx.R.prec = dps_to_prec(d) ctx._dps = d _fixed_precision = False prec = property(_get_prec, _set_prec) dps = property(_get_dps, _set_dps) def is_special(ctx, x): return x - x != 0.0 def isnan(ctx, x): return x != x def isinf(ctx, x): return abs(x) == ctx.inf def isnormal(ctx, x): if x: return x - x == 0.0 return False # todo def _is_real_type(ctx, x): return True def ldexp(ctx, x, n): return ctx.R.mul_2exp(x, n) def sqrt(ctx, x, prec=0): return ctx.R.sqrt(x) def log(ctx, x, prec=0): return ctx.R.log(x) ln = log # todo def nthroot(ctx, x, n): return ctx.R(x) ** (1 / ctx.R(n)) def exp(ctx, x, prec=0): return ctx.R.exp(x) def sin(ctx, x, prec=0): return ctx.R.sin(x) def atan(ctx, x, prec=0): return ctx.R.atan(x) def gamma(ctx, x, prec=0): return ctx.R.gamma(x) def factorial(ctx, x, prec=0): return ctx.R.fac(x) fac = factorial def bernoulli(ctx, n): return ctx.R.bernoulli(n) # todo: def nstr(ctx, x, n=6, **kwargs): return str(x) ''' # Called by SpecialFunctions.__init__() @classmethod def _wrap_specfun(cls, name, f, wrap): if wrap: def f_wrapped(ctx, *args, **kwargs): convert = ctx.convert args = [convert(a) for a in args] return f(ctx, *args, **kwargs) else: f_wrapped = f f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__) setattr(cls, name, f_wrapped) pi = math2.pi e = math2.e euler = math2.euler sqrt2 = 1.4142135623730950488 sqrt5 = 2.2360679774997896964 phi = 1.6180339887498948482 ln2 = 0.69314718055994530942 ln10 = 2.302585092994045684 euler = 0.57721566490153286061 catalan = 0.91596559417721901505 khinchin = 2.6854520010653064453 apery = 1.2020569031595942854 glaisher = 1.2824271291006226369 absmin = absmax = abs def isnpint(ctx, x): if type(x) is complex: if x.imag: return False x = x.real return x <= 0.0 and round(x) == x power = staticmethod(math2.pow) sqrt = staticmethod(math2.sqrt) exp = staticmethod(math2.exp) ln = log = staticmethod(math2.log) cos = staticmethod(math2.cos) sin = staticmethod(math2.sin) tan = staticmethod(math2.tan) cos_sin = staticmethod(math2.cos_sin) acos = staticmethod(math2.acos) asin = staticmethod(math2.asin) atan = staticmethod(math2.atan) cosh = staticmethod(math2.cosh) sinh = staticmethod(math2.sinh) tanh = staticmethod(math2.tanh) gamma = staticmethod(math2.gamma) rgamma = staticmethod(math2.rgamma) fac = factorial = staticmethod(math2.factorial) floor = staticmethod(math2.floor) ceil = staticmethod(math2.ceil) cospi = staticmethod(math2.cospi) sinpi = staticmethod(math2.sinpi) cbrt = staticmethod(math2.cbrt) _nthroot = staticmethod(math2.nthroot) _ei = staticmethod(math2.ei) _e1 = staticmethod(math2.e1) _zeta = _zeta_int = staticmethod(math2.zeta) # XXX: math2 def arg(ctx, z): z = complex(z) return math.atan2(z.imag, z.real) def expj(ctx, x): return ctx.exp(ctx.j*x) def expjpi(ctx, x): return ctx.exp(ctx.j*ctx.pi*x) ldexp = math.ldexp frexp = math.frexp def mag(ctx, z): if z: return ctx.frexp(abs(z))[1] return ctx.ninf def isint(ctx, z): if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 if z.imag: return False z = z.real try: return z == int(z) except: return False def nint_distance(ctx, z): if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 n = round(z.real) else: n = round(z) if n == z: return n, ctx.ninf return n, ctx.mag(abs(z-n)) def _convert_param(ctx, z): if type(z) is tuple: p, q = z return ctx.mpf(p) / q, 'R' if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 intz = int(z.real) else: intz = int(z) if z == intz: return intz, 'Z' return z, 'R' def _is_real_type(ctx, z): return isinstance(z, float) or isinstance(z, int_types) def _is_complex_type(ctx, z): return isinstance(z, complex) def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs): coeffs = list(coeffs) num = range(p) den = range(p,p+q) tol = ctx.eps s = t = 1.0 k = 0 while 1: for i in num: t *= (coeffs[i]+k) for i in den: t /= (coeffs[i]+k) k += 1; t /= k; t *= z; s += t if abs(t) < tol: return s if k > maxterms: raise ctx.NoConvergence def atan2(ctx, x, y): return math.atan2(x, y) def psi(ctx, m, z): m = int(m) if m == 0: return ctx.digamma(z) return (-1)**(m+1) * ctx.fac(m) * ctx.zeta(m+1, z) digamma = staticmethod(math2.digamma) def harmonic(ctx, x): x = ctx.convert(x) if x == 0 or x == 1: return x return ctx.digamma(x+1) + ctx.euler nstr = str def to_fixed(ctx, x, prec): return int(math.ldexp(x, prec)) def rand(ctx): import random return random.random() _erf = staticmethod(math2.erf) _erfc = staticmethod(math2.erfc) def sum_accurately(ctx, terms, check_step=1): s = ctx.zero k = 0 for term in terms(): s += term if (not k % check_step) and term: if abs(term) <= 1e-18*abs(s): break k += 1 return s ''' mp = RFContext(flint2.RF, flint2.CF, flint2.QQ, flint2.ZZ) sqrt = mp.sqrt log = mp.log ln = mp.ln sin = mp.sin exp = mp.exp atan = mp.atan gamma = mp.gamma zeta = mp.zeta fac = mp.fac root = mp.root chop = mp.chop inf = mp.inf quad = mp.quad quadosc = mp.quadosc diff = mp.diff nsum = mp.nsum nprod = mp.nprod limit = mp.limit """ from mpmath2 import * mp.dps = 50 nsum(lambda n: 1/n**2, [1, inf]) nsum(lambda n: 1/n**2, [1, inf], method='e') diff(lambda x: gamma(x), 1) quadosc(lambda x: sin(x)/x, [0, inf], omega=1) from mpmath2 import * mp.dps = 50; mp.pretty = True +pi 180*degree 4*atan(1) 16*acot(5)-4*acot(239) 48*acot(49)+128*acot(57)-20*acot(239)+48*acot(110443) chop(2*j*log((1-j)/(1+j))) chop(-2j*asinh(1j)) chop(ci(-inf)/1j) gamma(0.5)**2 beta(0.5,0.5) (2/diff(erf, 0))**2 findroot(sin, 3) findroot(cos, 1)*2 chop(-2j*lambertw(-pi/2)) besseljzero(0.5,1) 3*sqrt(3)/2/hyp2f1((-1,3),(1,3),1,1) 8/(hyp2f1(0.5,0.5,1,0.5)*gamma(0.75)/gamma(1.25))**2 4*(hyp1f2(1,1.5,1,1) / struvel(-0.5, 2))**2 1/meijerg([[],[]], [[0],[0.5]], 0)**2 (meijerg([[],[2]], [[1,1.5],[]], 1, 0.5) / erfc(1))**2 (1-e) / meijerg([[1],[0.5]], [[1],[0.5,0]], 1) sqrt(psi(1,0.25)-8*catalan) elliprc(1,2)*4 elliprg(0,1,1)*4 2*agm(1,0.5)*ellipk(0.75) (gamma(0.75)*jtheta(3,0,exp(-pi)))**4 cbrt(gamma(0.25)**4*agm(1,sqrt(2))**2/8) sqrt(6*zeta(2)) sqrt(6*(zeta(2,3)+5./4)) sqrt(zeta(2,(3,4))+8*catalan) exp(-2*zeta(0,1,1))/2 sqrt(12*altzeta(2)) 4*dirichlet(1,[0,1,0,-1]) 2*catalan/dirichlet(-1,[0,1,0,-1],1) exp(-dirichlet(0,[0,1,0,-1],1))*gamma(0.25)**2/(2*sqrt(2)) sqrt(7*zeta(3)/(4*diff(lerchphi, (-1,-2,1), (0,1,0)))) sqrt(-12*polylog(2,-1)) sqrt(6*log(2)**2+12*polylog(2,0.5)) chop(root(-81j*(polylog(3,root(1,3,1))+4*zeta(3)/9)/2,3)) 2*clsin(1,1)+1 (3+sqrt(3)*sqrt(1+8*clcos(2,1)))/2 root(2,6)*sqrt(e)/(glaisher**6*barnesg(0.5)**4) nsum(lambda k: 4*(-1)**(k+1)/(2*k-1), [1,inf]) nsum(lambda k: (3**k-1)/4**k*zeta(k+1), [1,inf]) nsum(lambda k: 8/(2*k-1)**2, [1,inf])**0.5 nsum(lambda k: 2*fac(k)/fac2(2*k+1), [0,inf]) nsum(lambda k: fac(k)**2/fac(2*k+1), [0,inf])*3*sqrt(3)/2 nsum(lambda k: fac(k)**2/(phi**(2*k+1)*fac(2*k+1)), [0,inf])*(5*sqrt(phi+2))/2 nsum(lambda k: (4/(8*k+1)-2/(8*k+4)-1/(8*k+5)-1/(8*k+6))/16**k, [0,inf]) 2/nsum(lambda k: (-1)**k*(4*k+1)*(fac2(2*k-1)/fac2(2*k))**3, [0,inf]) nsum(lambda k: 72/(k*expm1(k*pi))-96/(k*expm1(2*pi*k))+24/(k*expm1(4*pi*k)), [1,inf]) 1/nsum(lambda k: binomial(2*k,k)**3*(42*k+5)/2**(12*k+4), [0,inf]) 4/nsum(lambda k: (-1)**k*(1123+21460*k)*fac2(2*k-1)*fac2(4*k-1)/(882**(2*k+1)*32**k*fac(k)**3), [0,inf]) 9801/sqrt(8)/nsum(lambda k: fac(4*k)*(1103+26390*k)/(fac(k)**4*396**(4*k)), [0,inf]) 426880*sqrt(10005)/nsum(lambda k: (-1)**k*fac(6*k)*(13591409+545140134*k)/(fac(k)**3*fac(3*k)*(640320**3)**k), [0,inf]) 4/nsum(lambda k: (6*k+1)*rf(0.5,k)**3/(4**k*fac(k)**3), [0,inf]) (ln(8)+sqrt(48*nsum(lambda m,n: (-1)**(m+n)/(m**2+n**2), [1,inf],[1,inf]) + 9*log(2)**2))/2 -nsum(lambda x,y: (-1)**(x+y)/(x**2+y**2), [-inf,inf], [-inf,inf], ignore=True)/ln2 2*nsum(lambda k: sin(k)/k, [1,inf])+1 quad(lambda x: 2/(x**2+1), [0,inf]) quad(lambda x: exp(-x**2), [-inf,inf])**2 2*quad(lambda x: sqrt(1-x**2), [-1,1]) chop(quad(lambda z: 1/(2j*z), [1,j,-1,-j,1])) 3*(4*log(2+sqrt(3))-quad(lambda x,y: 1/sqrt(1+x**2+y**2), [-1,1],[-1,1]))/2 sqrt(8*quad(lambda x,y: 1/(1-(x*y)**2), [0,1],[0,1])) sqrt(6*quad(lambda x,y: 1/(1-x*y), [0,1],[0,1])) sqrt(6*quad(lambda x: x/expm1(x), [0,inf])) quad(lambda x: (16*x-16)/(x**4-2*x**3+4*x-4), [0,1]) quad(lambda x: sqrt(x-x**2), [0,0.25])*24+3*sqrt(3)/4 mpf(22)/7 - quad(lambda x: x**4*(1-x)**4/(1+x**2), [0,1]) mpf(355)/113 - quad(lambda x: x**8*(1-x)**8*(25+816*x**2)/(1+x**2), [0,1])/3164 2*quadosc(lambda x: sin(x)/x, [0,inf], omega=1) 40*quadosc(lambda x: sin(x)**6/x**6, [0,inf], omega=1)/11 e*quadosc(lambda x: cos(x)/(1+x**2), [-inf,inf], omega=1) 8*quadosc(lambda x: cos(x**2), [0,inf], zeros=lambda n: sqrt(n))**2 2*quadosc(lambda x: sin(exp(x)), [1,inf], zeros=ln)+2*si(e) exp(2*quad(loggamma, [0,1]))/2 2*nprod(lambda k: sec(pi/2**k), [2,inf]) s=lambda k: sqrt(0.5+s(k-1)/2) if k else 0; 2/nprod(s, [1,inf]) s=lambda k: sqrt(2+s(k-1)) if k else 0; limit(lambda k: sqrt(2-s(k))*2**(k+1), inf) 2*nprod(lambda k: (2*k)**2/((2*k-1)*(2*k+1)), [1,inf]) 2*nprod(lambda k: (4*k**2)/(4*k**2-1), [1, inf]) sqrt(6*ln(nprod(lambda k: exp(1/k**2), [1,inf]))) nprod(lambda k: (k**2-1)/(k**2+1), [2,inf])/csch(pi) nprod(lambda k: (k**2-1)/(k**2+1), [2,inf])*sinh(pi) nprod(lambda k: (k**4-1)/(k**4+1), [2, inf])*(cosh(sqrt(2)*pi)-cos(sqrt(2)*pi))/sinh(pi) sinh(pi)/nprod(lambda k: (1-1/k**4), [2, inf])/4 sinh(pi)/nprod(lambda k: (1+1/k**2), [2, inf])/2 (exp(1+euler/2)/nprod(lambda n: (1+1/n)**n * exp(1/(2*n)-1), [1, inf]))**2/2 3*sqrt(2)*cosh(pi*sqrt(3)/2)**2*csch(pi*sqrt(2))/nprod(lambda k: (1+1/k+1/k**2)**2/(1+2/k+3/k**2), [1, inf]) 2/e*nprod(lambda k: (1+2/k)**((-1)**(k+1)*k), [1,inf]) limit(lambda k: 16**k/(k*binomial(2*k,k)**2), inf) limit(lambda x: 4*x*hyp1f2(0.5,1.5,1.5,-x**2), inf) 1/log(limit(lambda n: nprod(lambda k: pi/(2*atan(k)), [n,2*n]), inf),4) limit(lambda k: 2**(4*k+1)*fac(k)**4/(2*k+1)/fac(2*k)**2, inf) limit(lambda k: fac(k) / (sqrt(k)*(k/e)**k), inf)**2/2 limit(lambda k: (-(-1)**k*bernoulli(2*k)*2**(2*k-1)/fac(2*k))**(-1/(2*k)), inf) limit(lambda k: besseljzero(1,k)/k, inf) 1/limit(lambda x: airyai(x)*2*x**0.25*exp(2*x**1.5/3), inf, exp=True)**2 1/limit(lambda x: airybi(x)*x**0.25*exp(-2*x**1.5/3), inf, exp=True)**2 """ flint-3.1.3/src/qadic.h000066400000000000000000000301661461254215100146620ustar00rootroot00000000000000/* Copyright (C) 2011, 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef QADIC_H #define QADIC_H #ifdef QADIC_INLINES_C #define QADIC_INLINE #else #define QADIC_INLINE static inline #endif #include "fmpz_vec.h" #include "padic.h" #include "padic_poly.h" #ifdef __cplusplus extern "C" { #endif /* Data types and context ****************************************************/ typedef padic_poly_t qadic_t; typedef padic_poly_struct qadic_struct; QADIC_INLINE slong qadic_val(const qadic_t op) { return padic_poly_val(op); } QADIC_INLINE slong qadic_prec(const qadic_t op) { return padic_poly_prec(op); } typedef struct { padic_ctx_struct pctx; fmpz *a; slong *j; slong len; char *var; } qadic_ctx_struct; typedef qadic_ctx_struct qadic_ctx_t[1]; int _qadic_ctx_init_conway_ui(qadic_ctx_t ctx, ulong p, slong d, slong min, slong max, const char * var, enum padic_print_mode mode); void qadic_ctx_init_conway(qadic_ctx_t ctx, const fmpz_t p, slong d, slong min, slong max, const char *var, enum padic_print_mode mode); void qadic_ctx_init(qadic_ctx_t ctx, const fmpz_t p, slong d, slong min, slong max, const char *var, enum padic_print_mode mode); void qadic_ctx_clear(qadic_ctx_t ctx); QADIC_INLINE slong qadic_ctx_degree(const qadic_ctx_t ctx) { return ctx->j[ctx->len - 1]; } QADIC_INLINE void qadic_ctx_print(const qadic_ctx_t ctx) { slong i, k; flint_printf("p = "), fmpz_print((&ctx->pctx)->p), flint_printf("\n"); flint_printf("d = %wd\n", ctx->j[ctx->len - 1]); flint_printf("f(X) = "); fmpz_print(ctx->a + 0); for (k = 1; k < ctx->len; k++) { i = ctx->j[k]; flint_printf(" + "); if (fmpz_is_one(ctx->a + k)) { if (i == 1) flint_printf("X"); else flint_printf("X^%wd", i); } else { fmpz_print(ctx->a + k); if (i == 1) flint_printf("*X"); else flint_printf("*X^%wd", i); } } flint_printf("\n"); } /* Memory management *********************************************************/ QADIC_INLINE void qadic_init(qadic_t x) { padic_poly_init(x); } QADIC_INLINE void qadic_init2(qadic_t rop, slong prec) { padic_poly_init2(rop, 0, prec); } QADIC_INLINE void qadic_clear(qadic_t x) { padic_poly_clear(x); } /* TODO: Consider renaming this function, prefix for the "qadic" module. */ QADIC_INLINE void _fmpz_poly_reduce(fmpz *R, slong lenR, const fmpz *a, const slong *j, slong len) { const slong d = j[len - 1]; slong i, k; FMPZ_VEC_NORM(R, lenR); for (i = lenR - 1; i >= d; i--) { for (k = len - 2; k >= 0; k--) { fmpz_submul(R + j[k] + i - d, R + i, a + k); } fmpz_zero(R + i); } } /* TODO: Consider renaming this function, prefix for the "qadic" module. */ QADIC_INLINE void _fmpz_mod_poly_reduce(fmpz *R, slong lenR, const fmpz *a, const slong *j, slong len, const fmpz_t p) { const slong d = j[len - 1]; if (lenR > d) { _fmpz_poly_reduce(R, lenR, a, j, len); _fmpz_vec_scalar_mod_fmpz(R, R, d, p); } else { _fmpz_vec_scalar_mod_fmpz(R, R, lenR, p); } } QADIC_INLINE void qadic_reduce(qadic_t x, const qadic_ctx_t ctx) { const slong N = qadic_prec(x); const slong d = ctx->j[ctx->len - 1]; if (x->length == 0 || x->val >= N) { padic_poly_zero(x); } else { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N - x->val, &ctx->pctx); _fmpz_mod_poly_reduce(x->coeffs, x->length, ctx->a, ctx->j, ctx->len, pow); _padic_poly_set_length(x, FLINT_MIN(x->length, d)); _padic_poly_normalise(x); padic_poly_canonicalise(x, (&ctx->pctx)->p); if (alloc) fmpz_clear(pow); } } /* Randomisation *************************************************************/ QADIC_INLINE void qadic_randtest(qadic_t x, flint_rand_t state, const qadic_ctx_t ctx) { padic_poly_randtest(x, state, qadic_ctx_degree(ctx), &ctx->pctx); } QADIC_INLINE void qadic_randtest_not_zero(qadic_t x, flint_rand_t state, const qadic_ctx_t ctx) { padic_poly_randtest_not_zero(x, state, qadic_ctx_degree(ctx), &ctx->pctx); } QADIC_INLINE void qadic_randtest_val(qadic_t x, flint_rand_t state, slong val, const qadic_ctx_t ctx) { padic_poly_randtest_val(x, state, val, qadic_ctx_degree(ctx), &ctx->pctx); } QADIC_INLINE void qadic_randtest_int(qadic_t x, flint_rand_t state, const qadic_ctx_t ctx) { const slong N = qadic_prec(x); if (N <= 0) { padic_poly_zero(x); } else { padic_poly_randtest_val(x, state, n_randint(state, N), qadic_ctx_degree(ctx), &ctx->pctx); } } /* Assignments and conversions ***********************************************/ QADIC_INLINE void qadic_zero(qadic_t op) { padic_poly_zero(op); } QADIC_INLINE void qadic_one(qadic_t op) { padic_poly_one(op); } QADIC_INLINE void qadic_gen(qadic_t x, const qadic_ctx_t ctx) { const slong N = qadic_prec(x); const slong d = qadic_ctx_degree(ctx); if (d > 1) { if (N > 0) { padic_poly_fit_length(x, 2); fmpz_zero(x->coeffs + 0); fmpz_one(x->coeffs + 1); _padic_poly_set_length(x, 2); x->val = 0; } else { padic_poly_zero(x); } } else { padic_poly_fit_length(x, 1); fmpz_neg(x->coeffs + 0, ctx->a + 0); _padic_poly_set_length(x, 1); x->val = 0; } } QADIC_INLINE void qadic_set_ui(qadic_t rop, ulong op, const qadic_ctx_t ctx) { padic_poly_set_ui(rop, op, &ctx->pctx); } QADIC_INLINE int qadic_get_padic(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) { if (op->length > 0) { if (_fmpz_vec_is_zero(op->coeffs + 1, op->length - 1)) { fmpz_set(padic_unit(rop), op->coeffs + 0); padic_val(rop) = op->val; _padic_canonicalise(rop, &ctx->pctx); return 1; } else { return 0; } } else { padic_zero(rop); return 1; } } QADIC_INLINE void qadic_set(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { padic_poly_set(rop, op, &(ctx->pctx)); } void qadic_set_fmpz_poly(qadic_t rop, const fmpz_poly_t op, const qadic_ctx_t ctx); /* Comparison ****************************************************************/ QADIC_INLINE int qadic_is_zero(const qadic_t op) { return padic_poly_is_zero(op); } QADIC_INLINE int qadic_is_one(const qadic_t op) { return padic_poly_is_one(op); } QADIC_INLINE int qadic_equal(const qadic_t op1, const qadic_t op2) { return padic_poly_equal(op1, op2); } /* Basic arithmetic **********************************************************/ QADIC_INLINE void qadic_add(qadic_t x, const qadic_t y, const qadic_t z, const qadic_ctx_t ctx) { padic_poly_add(x, y, z, &ctx->pctx); } QADIC_INLINE void qadic_sub(qadic_t x, const qadic_t y, const qadic_t z, const qadic_ctx_t ctx) { padic_poly_sub(x, y, z, &ctx->pctx); } QADIC_INLINE void qadic_neg(qadic_t x, const qadic_t y, const qadic_ctx_t ctx) { padic_poly_neg(x, y, &ctx->pctx); } void qadic_mul(qadic_t x, const qadic_t y, const qadic_t z, const qadic_ctx_t ctx); void _qadic_inv(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); void qadic_inv(qadic_t x, const qadic_t y, const qadic_ctx_t ctx); void _qadic_pow(fmpz *rop, const fmpz *op, slong len, const fmpz_t e, const fmpz *a, const slong *j, slong lena, const fmpz_t p); void qadic_pow(qadic_t x, const qadic_t y, const fmpz_t e, const qadic_ctx_t ctx); /* Special functions *********************************************************/ void _qadic_exp_rectangular(fmpz *rop, const fmpz *op, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN); int qadic_exp_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_exp_balanced(fmpz *rop, const fmpz *op, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN); int qadic_exp_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_exp(fmpz *rop, const fmpz *op, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN); int qadic_exp(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_log_rectangular(fmpz *z, const fmpz *y, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN); int qadic_log_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_log_balanced(fmpz *z, const fmpz *y, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN); int qadic_log_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_log(fmpz *z, const fmpz *y, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN); int qadic_log(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_frobenius_a(fmpz *rop, slong exp, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); void _qadic_frobenius(fmpz *rop, const fmpz *op, slong len, slong e, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); void qadic_frobenius(qadic_t rop, const qadic_t op, slong e, const qadic_ctx_t ctx); void _qadic_teichmuller(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); void qadic_teichmuller(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_trace(fmpz_t rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t pN); void qadic_trace(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); void _qadic_norm_resultant(fmpz_t rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); void _qadic_norm_analytic(fmpz_t rop, const fmpz *y, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); void _qadic_norm(fmpz_t rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); void qadic_norm(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); void qadic_norm_analytic(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); void qadic_norm_resultant(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); int qadic_sqrt(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); /* Output ********************************************************************/ #ifdef FLINT_HAVE_FILE int qadic_fprint_pretty(FILE * file, const qadic_t op, const qadic_ctx_t ctx); #endif int qadic_print_pretty(const qadic_t op, const qadic_ctx_t ctx); int qadic_debug(const qadic_t op); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/qadic/000077500000000000000000000000001461254215100145035ustar00rootroot00000000000000flint-3.1.3/src/qadic/ctx_clear.c000066400000000000000000000011411461254215100166100ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "padic.h" #include "qadic.h" void qadic_ctx_clear(qadic_ctx_t ctx) { padic_ctx_clear(&ctx->pctx); _fmpz_vec_clear(ctx->a, ctx->len); flint_free(ctx->j); flint_free(ctx->var); } flint-3.1.3/src/qadic/ctx_init.c000066400000000000000000000074651461254215100165040ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2020 Claus Fieker Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "fmpz_vec.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "padic.h" #include "qadic.h" int _qadic_ctx_init_conway_ui(qadic_ctx_t ctx, ulong p, slong d, slong min, slong max, const char * var, enum padic_print_mode mode) { int result; ulong tmp[410]; /* Largest degree is 409 */ slong num_nzcoeffs; slong * idx_nzcoeffs; mp_ptr nzcoeffs; slong ix, jx; result = _nmod_poly_conway(tmp, p, d); if (!result) return 0; /* Find number of non-zero coefficients */ num_nzcoeffs = 2; for (ix = 1; ix < d; ix++) if (tmp[ix]) num_nzcoeffs++; idx_nzcoeffs = flint_malloc(sizeof(slong) * num_nzcoeffs); nzcoeffs = flint_malloc(sizeof(fmpz) * num_nzcoeffs); /* Copy the polynomial */ for (ix = 0, jx = 0; ix < d; ix++) { if (tmp[ix]) { nzcoeffs[jx] = tmp[ix]; idx_nzcoeffs[jx] = ix; jx++; } } nzcoeffs[jx] = 1; idx_nzcoeffs[jx] = d; ctx->len = num_nzcoeffs; ctx->j = idx_nzcoeffs; ctx->a = (fmpz *) nzcoeffs; /* Complete the initialisation of the context */ padic_ctx_init(&ctx->pctx, (fmpz *) &p, min, max, mode); ctx->var = flint_malloc(strlen(var) + 1); strcpy(ctx->var, var); return 1; } void qadic_ctx_init_conway(qadic_ctx_t ctx, const fmpz_t p, slong d, slong min, slong max, const char * var, enum padic_print_mode mode) { int result; if (*p < 2 || *p > 109987) /* NOTE: This works. */ flint_throw(FLINT_ERROR, "Exception (qadic_ctx_init_conway). " "Conway polynomials are only available for primes up to 109987.\n"); result = _qadic_ctx_init_conway_ui(ctx, *p, d, min, max, var, mode); if (!result) flint_throw(FLINT_ERROR, "Exception (qadic_ctx_init_conway). " "The polynomial for (p, d) = (%{fmpz}, %wd) is not present " "in the database.\n", p, d); } void qadic_ctx_init(qadic_ctx_t ctx, const fmpz_t p, slong d, slong min, slong max, const char * var, enum padic_print_mode mode) { flint_rand_t state; fmpz_mod_poly_t poly; slong i, j; fmpz_mod_ctx_t ctxp; if (*p >= 2 && *p <= 109987) if (_qadic_ctx_init_conway_ui(ctx, *p, d, min, max, var, mode)) return; flint_randinit(state); fmpz_mod_ctx_init(ctxp, p); fmpz_mod_poly_init2(poly, d + 1, ctxp); fmpz_mod_poly_randtest_sparse_irreducible(poly, state, d + 1, ctxp); flint_randclear(state); /* Find number of non-zero coefficients */ ctx->len = 1; for (i = 0; i < d; i++) { if (!fmpz_is_zero(poly->coeffs + i)) ctx->len ++; } ctx->a = _fmpz_vec_init(ctx->len); ctx->j = flint_malloc(ctx->len*sizeof(slong)); /* Copy the polynomial */ j = 0; for (i = 0; i < d; i++) { if (!fmpz_is_zero(poly->coeffs+i)) { fmpz_set(ctx->a + j, poly->coeffs + i); ctx->j[j] = i; j++; } } fmpz_set_ui(ctx->a + j, 1); ctx->j[j] = d; /* Complete the initialisation of the context */ padic_ctx_init(&ctx->pctx, p, min, max, mode); ctx->var = flint_malloc(strlen(var) + 1); strcpy(ctx->var, var); fmpz_mod_poly_clear(poly, ctxp); fmpz_mod_ctx_clear(ctxp); } flint-3.1.3/src/qadic/exp.c000066400000000000000000000044521461254215100154500ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "qadic.h" void _qadic_exp(fmpz *rop, const fmpz *op, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { if (N < (WORD(1) << 13) / (slong) fmpz_bits(p)) { _qadic_exp_rectangular(rop, op, v, len, a, j, lena, p, N, pN); } else { const slong d = j[lena - 1]; _qadic_exp_balanced(rop, op, v, len, a, j, lena, p, N, pN); _fmpz_vec_zero(rop + d, d - 1); } } int qadic_exp(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = qadic_prec(rop); const slong v = op->val; const fmpz *p = (&ctx->pctx)->p; if (padic_poly_is_zero(op)) { padic_poly_one(rop); return 1; } if ((*p == WORD(2) && v <= 1) || (v <= 0)) { return 0; } else { if (v < N) { const slong d = qadic_ctx_degree(ctx); fmpz *t; fmpz_t pN; int alloc; alloc = _padic_ctx_pow_ui(pN, N, &ctx->pctx); if (rop == op) { t = _fmpz_vec_init(2 * d - 1); } else { padic_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } _qadic_exp(t, op->coeffs, v, op->length, ctx->a, ctx->j, ctx->len, p, N, pN); rop->val = 0; if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); if (alloc) fmpz_clear(pN); } else { padic_poly_one(rop); } return 1; } } flint-3.1.3/src/qadic/exp_balanced.c000066400000000000000000000124731461254215100172630ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qadic.h" static void _qadic_exp_bsplit_series(fmpz *P, fmpz_t Q, fmpz *T, const fmpz *x, slong len, slong lo, slong hi, const fmpz *a, const slong *j, slong lena) { const slong d = j[lena - 1]; if (hi - lo == 1) { _fmpz_vec_set(P, x, len); _fmpz_vec_zero(P + len, 2*d - 1 - len); fmpz_set_si(Q, lo); _fmpz_vec_set(T, P, 2*d - 1); } else if (hi - lo == 2) { _fmpz_poly_sqr(P, x, len); _fmpz_vec_zero(P + (2*len - 1), d - (2*len - 1)); _fmpz_poly_reduce(P, 2*len - 1, a, j, lena); fmpz_set_si(Q, lo); fmpz_mul_si(Q, Q, lo + 1); _fmpz_vec_scalar_mul_si(T, x, len, lo + 1); _fmpz_vec_zero(T + len, d - len); _fmpz_vec_add(T, T, P, d); } else { const slong m = (lo + hi) / 2; fmpz *PR, *TR, *W; fmpz_t QR; PR = _fmpz_vec_init(2*d - 1); TR = _fmpz_vec_init(2*d - 1); W = _fmpz_vec_init(2*d - 1); fmpz_init(QR); _qadic_exp_bsplit_series(P, Q, T, x, len, lo, m, a, j, lena); _qadic_exp_bsplit_series(PR, QR, TR, x, len, m, hi, a, j, lena); _fmpz_poly_mul(W, TR, d, P, d); _fmpz_poly_reduce(W, 2*d - 1, a, j, lena); _fmpz_vec_scalar_mul_fmpz(T, T, d, QR); _fmpz_vec_add(T, T, W, d); _fmpz_poly_mul(W, P, d, PR, d); _fmpz_poly_reduce(W, 2*d - 1, a, j, lena); _fmpz_vec_swap(P, W, d); fmpz_mul(Q, Q, QR); _fmpz_vec_clear(PR, 2*d - 1); _fmpz_vec_clear(TR, 2*d - 1); _fmpz_vec_clear(W, 2*d - 1); fmpz_clear(QR); } } static void _qadic_exp_bsplit(fmpz *y, const fmpz *x, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; const slong n = _padic_exp_bound(v, N, p); if (n == 1) { fmpz_one(y + 0); _fmpz_vec_zero(y + 1, d - 1); } else { fmpz *P, *T; fmpz_t Q, R; slong f; P = _fmpz_vec_init(2*d - 1); T = _fmpz_vec_init(2*d - 1); fmpz_init(Q); fmpz_init(R); _qadic_exp_bsplit_series(P, Q, T, x, len, 1, n, a, j, lena); fmpz_add(T + 0, T + 0, Q); /* (T,Q) := (T,Q) + 1 */ /* Note exp(x) is a unit so val(T) == val(Q). */ f = fmpz_remove(Q, Q, p); fmpz_pow_ui(R, p, f); _fmpz_vec_scalar_divexact_fmpz(T, T, d, R); _padic_inv(Q, Q, p, N); _fmpz_vec_scalar_mul_fmpz(y, T, d, Q); _fmpz_vec_clear(P, 2*d - 1); _fmpz_vec_clear(T, 2*d - 1); fmpz_clear(Q); fmpz_clear(R); } } void _qadic_exp_balanced(fmpz *rop, const fmpz *x, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { const slong d = j[lena - 1]; fmpz_t pw; fmpz *r, *s, *t; slong i, w; r = _fmpz_vec_init(d); s = _fmpz_vec_init(2*d - 1); t = _fmpz_vec_init(d); fmpz_init(pw); fmpz_pow_ui(pw, p, v); _fmpz_vec_scalar_mul_fmpz(t, x, len, pw); _fmpz_vec_scalar_mod_fmpz(t, t, len, pN); _fmpz_vec_zero(t + len, d - len); fmpz_set(pw, p); fmpz_one(rop + 0); _fmpz_vec_zero(rop + 1, d - 1); w = 1; while (!_fmpz_vec_is_zero(t, d)) { fmpz_mul(pw, pw, pw); for (i = 0; i < d; i++) { fmpz_fdiv_r(r + i, t + i, pw); fmpz_sub(t + i, t + i, r + i); } if (!_fmpz_vec_is_zero(r, d)) { _qadic_exp_bsplit(r, r, w, d, a, j, lena, p, N); _fmpz_poly_mul(s, rop, d, r, d); _fmpz_poly_reduce(s, 2*d - 1, a, j, lena); _fmpz_vec_scalar_mod_fmpz(rop, s, d, pN); } w *= 2; } _fmpz_vec_clear(r, d); _fmpz_vec_clear(s, 2*d - 1); _fmpz_vec_clear(t, d); fmpz_clear(pw); } int qadic_exp_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = qadic_prec(rop); const slong v = op->val; const fmpz *p = (&ctx->pctx)->p; if (padic_poly_is_zero(op)) { padic_poly_one(rop); return 1; } if ((*p == WORD(2) && v <= 1) || (v <= 0)) { return 0; } else { if (v < N) { const slong d = qadic_ctx_degree(ctx); fmpz_t pN; int alloc; alloc = _padic_ctx_pow_ui(pN, N, &ctx->pctx); padic_poly_fit_length(rop, d); _qadic_exp_balanced(rop->coeffs, op->coeffs, v, op->length, ctx->a, ctx->j, ctx->len, p, N, pN); rop->val = 0; _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); if (alloc) fmpz_clear(pN); } else { padic_poly_one(rop); } return 1; } } flint-3.1.3/src/qadic/exp_rectangular.c000066400000000000000000000146021461254215100200350ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "qadic.h" static void __fmpz_mod_poly_add(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { slong i, len = FLINT_MAX(len1, len2); _fmpz_poly_add(res, poly1, len1, poly2, len2); for (i = 0; i < len; i++) { if (fmpz_cmpabs(res + i, p) >= 0) fmpz_sub(res + i, res + i, p); } } static void __fmpz_mod_poly_mul(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { _fmpz_poly_mul(res, poly1, len1, poly2, len2); _fmpz_vec_scalar_mod_fmpz(res, res, len1 + len2 - 1, p); } void _qadic_exp_rectangular(fmpz *rop, const fmpz *op, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { const slong d = j[lena - 1]; const slong n = _padic_exp_bound(v, N, p); if (n < 4) { if (n == 1) /* y := 1 */ { fmpz_one(rop); _fmpz_vec_zero(rop + 1, d - 1); } else if (n == 2) /* y := 1 + x */ { fmpz_t f; fmpz_init(f); fmpz_pow_ui(f, p, v); _fmpz_vec_scalar_mul_fmpz(rop, op, len, f); _fmpz_vec_zero(rop + len, d - len); fmpz_add_ui(rop, rop, 1); _fmpz_vec_scalar_mod_fmpz(rop, rop, len, pN); fmpz_clear(f); } else /* y := 1 + x + x^2/2 */ { slong i; fmpz *x = _fmpz_vec_init(len + 1); fmpz_pow_ui(x + len, p, v); _fmpz_vec_scalar_mul_fmpz(x, op, len, x + len); _fmpz_poly_mul(rop, x, len, x, len); if (*p != WORD(2)) { for (i = 0; i < 2 * len - 1; i++) if (fmpz_is_odd(rop + i)) fmpz_add(rop + i, rop + i, pN); } _fmpz_vec_scalar_fdiv_q_2exp(rop, rop, 2 * len - 1, 1); _fmpz_mod_poly_reduce(rop, 2 * len - 1, a, j, lena, pN); _fmpz_vec_zero(rop + (2 * len - 1), d - (2 * len - 1)); __fmpz_mod_poly_add(rop, rop, d, x, len, pN); fmpz_add_ui(rop, rop, 1); if (fmpz_equal(rop, pN)) fmpz_zero(rop); _fmpz_vec_clear(x, len + 1); } } else /* n >= 4 */ { const slong k = fmpz_fits_si(p) ? (n - 1 - 1) / (fmpz_get_si(p) - 1) : 0; const slong b = n_sqrt(n); slong i; fmpz_t c, f, pNk; fmpz *s, *t, *x; fmpz_init(c); fmpz_init(f); fmpz_init(pNk); s = _fmpz_vec_init(2 * d - 1); t = _fmpz_vec_init(2 * d - 1); x = _fmpz_vec_init(d * (b + 1) + d - 1); fmpz_pow_ui(f, p, v); fmpz_pow_ui(pNk, p, N + k); /* Compute powers x^i of the argument */ fmpz_one(x); _fmpz_vec_scalar_mul_fmpz(x + d, op, len, f); _fmpz_vec_zero(x + d + len, d - len); for (i = 2; i <= b; i++) { __fmpz_mod_poly_mul(x + i * d, x + (i - 1) * d, d, x + d, d, pNk); _fmpz_mod_poly_reduce(x + i * d, 2 * d - 1, a, j, lena, pNk); } _fmpz_vec_zero(rop, d); fmpz_one(f); for (i = (n + b - 1) / b - 1; i >= 0; i--) { slong lo = i * b; slong hi = FLINT_MIN(n - 1, lo + b - 1); _fmpz_vec_zero(s, d); fmpz_one(c); for ( ; hi >= lo; hi--) { _fmpz_vec_scalar_addmul_fmpz(s, x + (hi - lo) * d, d, c); if (hi != 0) fmpz_mul_ui(c, c, hi); } _fmpz_poly_mul(t, x + b * d, d, rop, d); _fmpz_mod_poly_reduce(t, 2 * d - 1, a, j, lena, pNk); _fmpz_vec_scalar_mul_fmpz(rop, s, d, f); _fmpz_vec_add(rop, rop, t, d); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, pNk); fmpz_mul(f, f, c); } /* Note exp(x) is a unit so val(sum) == val(f). */ i = fmpz_remove(f, f, p); if (i) { fmpz_pow_ui(c, p, i); _fmpz_vec_scalar_divexact_fmpz(rop, rop, d, c); } _padic_inv(f, f, p, N); _fmpz_vec_scalar_mul_fmpz(rop, rop, d, f); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, pN); _fmpz_vec_clear(s, 2 * d - 1); _fmpz_vec_clear(t, 2 * d - 1); _fmpz_vec_clear(x, d * (b + 1) + d - 1); fmpz_clear(c); fmpz_clear(f); fmpz_clear(pNk); } } int qadic_exp_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = qadic_prec(rop); const slong v = op->val; const fmpz *p = (&ctx->pctx)->p; if (padic_poly_is_zero(op)) { padic_poly_one(rop); return 1; } if ((*p == WORD(2) && v <= 1) || (v <= 0)) { return 0; } else { if (v < N) { const slong d = qadic_ctx_degree(ctx); fmpz *t; fmpz_t pN; int alloc; alloc = _padic_ctx_pow_ui(pN, N, &ctx->pctx); if (rop == op) { t = _fmpz_vec_init(2 * d - 1); } else { padic_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } _qadic_exp_rectangular(t, op->coeffs, v, op->length, ctx->a, ctx->j, ctx->len, p, N, pN); rop->val = 0; if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); if (alloc) fmpz_clear(pN); } else { padic_poly_one(rop); } return 1; } } flint-3.1.3/src/qadic/frobenius.c000066400000000000000000000251571461254215100166550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "qadic.h" static void __fmpz_mod_poly_neg(fmpz *res, const fmpz *poly, slong len, const fmpz_t p) { slong i; for (i = 0; i < len; i++) { if (!fmpz_is_zero(poly + i)) fmpz_sub(res + i, p, poly + i); else fmpz_zero(res + i); } } static void __fmpz_mod_poly_sub(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { slong i, len = FLINT_MAX(len1, len2); _fmpz_poly_sub(res, poly1, len1, poly2, len2); for (i = 0; i < len; i++) { if (fmpz_sgn(res + i) < 0) fmpz_add(res + i, res + i, p); } } static void __fmpz_mod_poly_mul(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { _fmpz_poly_mul(res, poly1, len1, poly2, len2); _fmpz_vec_scalar_mod_fmpz(res, res, len1 + len2 - 1, p); } static void __fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz *poly, slong len, const fmpz_t a, const fmpz_t p) { if (len == 0) { fmpz_zero(res); } else if (len == 1 || fmpz_is_zero(a)) { fmpz_set(res, poly); } else { slong i = len - 1; fmpz_t t; fmpz_init(t); fmpz_set(res, poly + i); for (i = len - 2; i >= 0; i--) { fmpz_mul(t, res, a); fmpz_mod(t, t, p); fmpz_add(res, poly + i, t); } fmpz_clear(t); if (fmpz_cmpabs(res, p) >= 0) fmpz_sub(res, res, p); } } /* Assumes that \code{len1} and \code{len2} are positive but at most~$d$, and also that \code{len1} is at least $6$. The latter assumption guarantees that $\ceil{n/B} \geq 2$, i.e.\ $n \geq 2B$ so $n \geq 2 \ceil{\sqrt{n}}$. */ static void _fmpz_mod_poly_compose_smod_rectangular(fmpz *rop, const fmpz *op1, slong len1, const fmpz *op2, slong len2, const fmpz *a, const slong *j, slong lena, const fmpz_t p) { const slong d = j[lena - 1]; if (len2 == 1) { __fmpz_mod_poly_evaluate_fmpz(rop, op1, len1, op2, p); _fmpz_vec_zero(rop + 1, d - 1); } else { const slong B = n_sqrt(len1); slong i, k; fmpz *pows, *t; pows = _fmpz_vec_init((B + 2) * d); t = _fmpz_vec_init(2 * d - 1); fmpz_one(pows + 0 * d + 0); _fmpz_vec_set(pows + 1 * d, op2, len2); for (i = 2; i <= B; i++) { _fmpz_poly_mul(pows + i * d, pows + (i - 1) * d, d, op2, len2); _fmpz_poly_reduce(pows + i * d, d + len2 - 1, a, j, lena); _fmpz_vec_scalar_mod_fmpz(pows + i * d, pows + i * d, d, p); } _fmpz_vec_zero(rop, d); for (i = (len1 + B - 1) / B - 1; i >= 0; i--) { _fmpz_poly_mul(t, rop, d, pows + B * d, d); _fmpz_poly_reduce(t, 2 * d - 1, a, j, lena); _fmpz_vec_set(rop, t, d); fmpz_add(rop + 0, rop + 0, op1 + i*B); for (k = FLINT_MIN(B, len1 - i*B) - 1; k > 0; k--) { _fmpz_vec_scalar_addmul_fmpz(rop, pows + k * d, d, op1 + (i*B + k)); } _fmpz_vec_scalar_mod_fmpz(rop, rop, d, p); } _fmpz_vec_clear(pows, (B + 2) * d); _fmpz_vec_clear(t, 2 * d - 1); } } static void _fmpz_mod_poly_compose_smod_horner(fmpz *rop, const fmpz *op1, slong len1, const fmpz *op2, slong len2, const fmpz *a, const slong *j, slong lena, const fmpz_t p) { const slong d = j[lena - 1]; if (len1 == 1) { fmpz_set(rop, op1); _fmpz_vec_zero(rop + 1, d - 1); } else if (len2 == 1) { __fmpz_mod_poly_evaluate_fmpz(rop, op1, len1, op2, p); _fmpz_vec_zero(rop + 1, d - 1); } else { slong i; fmpz *t; t = _fmpz_vec_init(2*d - 1); _fmpz_vec_zero(rop, d); for (i = len1 - 1; i >= 0; i--) { _fmpz_poly_mul(t, rop, d, op2, len2); _fmpz_poly_reduce(t, d + len2 - 1, a, j, lena); _fmpz_poly_add(rop, t, d, op1 + i, 1); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, p); } _fmpz_vec_clear(t, 2*d - 1); } } /* Computes the composition $f(g(X))$ modulo the sparse polynomial given by the data \code{(a, j, lena)}, which is assumed to be of degree~$d \geq 2$. Sets the vector \code{(rop, d)}. Assumes that \code{len1} and \code{len2} are positive but at most~$d$. Does not support aliasing. */ void _fmpz_mod_poly_compose_smod(fmpz *rop, const fmpz *op1, slong len1, const fmpz *op2, slong len2, const fmpz *a, const slong *j, slong lena, const fmpz_t p) { if (len1 < 6) { _fmpz_mod_poly_compose_smod_horner(rop, op1, len1, op2, len2, a, j, lena, p); } else { _fmpz_mod_poly_compose_smod_rectangular(rop, op1, len1, op2, len2, a, j, lena, p); } } void _qadic_frobenius_a(fmpz *rop, slong exp, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; slong *e, i, n; fmpz *pow, *f1, *f2, *inv, *s, *t; n = FLINT_CLOG2(N) + 1; e = flint_malloc(n * sizeof(slong)); for (e[i = 0] = N; e[i] > 1; i++) e[i + 1] = (e[i] + 1) / 2; pow = _fmpz_vec_init(n); f1 = _fmpz_vec_init(d + 1); f2 = _fmpz_vec_init(d); inv = _fmpz_vec_init(2*d - 1); s = _fmpz_vec_init(2*d - 1); t = _fmpz_vec_init(2*d - 1); /* Compute powers of p */ { fmpz_one(t); fmpz_set(pow + i, p); } for (i--; i >= 1; i--) { if (e[i] & WORD(1)) { fmpz_mul(pow + i, t, pow + (i + 1)); fmpz_mul(t, t, t); } else { fmpz_mul(t, t, pow + (i + 1)); fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } } { if (e[i] & WORD(1)) fmpz_mul(pow + i, t, pow + (i + 1)); else fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } /* Dense representation of f and f' */ { slong k; for (k = 0; k < lena; k++) fmpz_set(f1 + j[k], a + k); for (k = 1; k < lena; k++) fmpz_mul_ui(f2 + (j[k] - 1), a + k, j[k]); } /* Run Newton iteration */ i = n - 1; { fmpz op[2] = {WORD(0), WORD(1)}; fmpz_pow_ui(t, p, exp); _qadic_pow(rop, op, 2, t, a, j, lena, pow + i); _fmpz_mod_poly_compose_smod(t, f2, d, rop, d, a, j, lena, pow + i); _qadic_inv(inv, t, d, a, j, lena, p, 1); } for (i--; i >= 0; i--) { _fmpz_mod_poly_compose_smod(s, f1, d + 1, rop, d, a, j, lena, pow + i); __fmpz_mod_poly_mul(t, s, d, inv, d, pow + i); _fmpz_mod_poly_reduce(t, 2*d - 1, a, j, lena, pow + i); __fmpz_mod_poly_sub(rop, rop, d, t, d, pow + i); if (i > 0) { _fmpz_mod_poly_compose_smod(s, f2, d, rop, d, a, j, lena, pow + i); __fmpz_mod_poly_mul(t, inv, d, s, d, pow + i); _fmpz_mod_poly_reduce(t, 2*d - 1, a, j, lena, pow + i); fmpz_sub_ui(t, t, 2); if (fmpz_sgn(t) < 0) fmpz_add(t, t, pow + i); __fmpz_mod_poly_neg(t, t, d, pow + i); __fmpz_mod_poly_mul(s, inv, d, t, d, pow + i); _fmpz_mod_poly_reduce(s, 2*d - 1, a, j, lena, pow + i); /* SWAP(inv, s). Requires the arrays to be of the same size. */ { fmpz *__t; __t = inv; inv = s; s = __t; } } } _fmpz_vec_clear(pow, n); _fmpz_vec_clear(f1, d + 1); _fmpz_vec_clear(f2, d); _fmpz_vec_clear(inv, 2*d - 1); _fmpz_vec_clear(s, 2*d - 1); _fmpz_vec_clear(t, 2*d - 1); flint_free(e); } /* Sets (rop, 2d-1) to the image of (op, len) under the Frobenius operator raised to the e-th power. */ void _qadic_frobenius(fmpz *rop, const fmpz *op, slong len, slong e, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; if (len == 1) /* op is in Zp, not just Zq */ { _fmpz_vec_set(rop, op, len); _fmpz_vec_zero(rop + len, (2*d - 1) - len); } else if (N == 1) { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, e); _qadic_pow(rop, op, len, t, a, j, lena, p); fmpz_clear(t); } else { fmpz *t; fmpz_t pow; t = _fmpz_vec_init(2*d - 1); fmpz_init(pow); fmpz_pow_ui(pow, p, N); _qadic_frobenius_a(t, e, a, j, lena, p, N); _fmpz_mod_poly_compose_smod(rop, op, len, t, d, a, j, lena, pow); _fmpz_vec_zero(rop + d, d - 1); _fmpz_vec_clear(t, 2*d - 1); fmpz_clear(pow); } } void qadic_frobenius(qadic_t rop, const qadic_t op, slong e, const qadic_ctx_t ctx) { const slong N = qadic_prec(rop); const slong d = qadic_ctx_degree(ctx); e = e % d; if (e < 0) e += d; if (qadic_is_zero(op) || op->val >= N) { qadic_zero(rop); } else if (e == 0) { padic_poly_set(rop, op, &ctx->pctx); } else { fmpz *t; if (rop == op) { t = _fmpz_vec_init(2 * d - 1); } else { padic_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } _qadic_frobenius(t, op->coeffs, op->length, e, ctx->a, ctx->j, ctx->len, (&ctx->pctx)->p, N - op->val); if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } else { rop->val = op->val; _padic_poly_set_length(rop, d); } _padic_poly_normalise(rop); } } flint-3.1.3/src/qadic/inlines.c000066400000000000000000000006711461254215100163140ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define QADIC_INLINES_C #include "flint.h" #include "qadic.h" flint-3.1.3/src/qadic/inv.c000066400000000000000000000117521461254215100154510ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "qadic.h" static int __fmpz_mod_poly_invmod(fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_t p) { fmpz * t, * u; fmpz_mod_ctx_t mod; int res; t = _fmpz_vec_init(lenB); u = _fmpz_vec_init(lenP); fmpz_mod_ctx_init(mod, p); _fmpz_vec_scalar_mod_fmpz(t, B, lenB, p); _fmpz_vec_scalar_mod_fmpz(u, P, lenP, p); res = _fmpz_mod_poly_invmod(A, t, lenB, u, lenP, mod); fmpz_mod_ctx_clear(mod); _fmpz_vec_clear(t, lenB); _fmpz_vec_clear(u, lenP); return res; } void _qadic_inv(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; if (len == 1) { _padic_inv(rop, op, p, N); _fmpz_vec_zero(rop + 1, d - 1); } else if (N == 1) { fmpz *P = _fmpz_vec_init(d + 1); slong k; for (k = 0; k < lena; k++) fmpz_set(P + j[k], a + k); __fmpz_mod_poly_invmod(rop, op, len, P, d + 1, p); _fmpz_vec_clear(P, d + 1); } else /* d, N >= 2 */ { slong *e, i, n; fmpz *pow, *u; fmpz *s, *t; n = FLINT_CLOG2(N) + 1; /* Compute sequence of exponents */ e = flint_malloc(n * sizeof(slong)); for (e[i = 0] = N; e[i] > 1; i++) e[i + 1] = (e[i] + 1) / 2; pow = _fmpz_vec_init(n); u = _fmpz_vec_init(len * n); s = _fmpz_vec_init(2 * d - 1); t = _fmpz_vec_init(2 * d - 1); /* Compute powers of p */ { fmpz_one(t); fmpz_set(pow + i, p); } for (i--; i >= 1; i--) { if (e[i] & WORD(1)) { fmpz_mul(pow + i, t, pow + (i + 1)); fmpz_mul(t, t, t); } else { fmpz_mul(t, t, pow + (i + 1)); fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } } { if (e[i] & WORD(1)) fmpz_mul(pow + i, t, pow + (i + 1)); else fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } /* Compute reduced units */ { _fmpz_vec_scalar_mod_fmpz(u + 0 * len, op, len, pow + 0); } for (i = 1; i < n; i++) { _fmpz_vec_scalar_mod_fmpz(u + i * len, u + (i - 1) * len, len, pow + i); } /* Run Newton iteration */ i = n - 1; { fmpz *P = _fmpz_vec_init(d + 1); slong k; for (k = 0; k < lena; k++) fmpz_set(P + j[k], a + k); __fmpz_mod_poly_invmod(rop, u + i * len, len, P, d + 1, pow + i); _fmpz_vec_clear(P, d + 1); } for (i--; i >= 0; i--) /* z' := 2 z - a z^2 */ { _fmpz_poly_sqr(s, rop, d); _fmpz_poly_reduce(s, 2 * d - 1, a, j, lena); _fmpz_poly_mul(t, s, d, u + i * len, len); _fmpz_poly_reduce(t, d + len - 1, a, j, lena); _fmpz_vec_scalar_mul_2exp(rop, rop, d, 1); _fmpz_poly_sub(rop, rop, d, t, d); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, pow + i); } _fmpz_vec_clear(pow, n); _fmpz_vec_clear(u, len * n); _fmpz_vec_clear(s, 2 * d - 1); _fmpz_vec_clear(t, 2 * d - 1); flint_free(e); } } void qadic_inv(qadic_t x, const qadic_t y, const qadic_ctx_t ctx) { const slong N = qadic_prec(x); if (qadic_is_zero(y)) { flint_throw(FLINT_ERROR, "Exception (qadic_inv). Zero is not invertible.\n"); } /* If y = u p^v has negative valuation with N <= -v then the exact inverse of y is zero when reduced modulo $p^N$ */ if (N + y->val <= 0) { qadic_zero(x); } else { const slong d = qadic_ctx_degree(ctx); fmpz *t; if (x == y) { t = _fmpz_vec_init(d); } else { padic_poly_fit_length(x, d); t = x->coeffs; } _qadic_inv(t, y->coeffs, y->length, ctx->a, ctx->j, ctx->len, (&ctx->pctx)->p, N + y->val); x->val = - y->val; if (x == y) { _fmpz_vec_clear(x->coeffs, x->alloc); x->coeffs = t; x->alloc = d; x->length = d; } else { _padic_poly_set_length(x, d); } _padic_poly_normalise(x); } } flint-3.1.3/src/qadic/io.c000066400000000000000000000112131461254215100152540ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.h" #include "fmpq_poly.h" #include "qadic.h" /* printing *******************************************************************/ int _qadic_fprint_pretty(FILE * file, const fmpz * u, slong len, slong v, const qadic_ctx_t ctx) { const fmpz *p = (&ctx->pctx)->p; if (_fmpz_vec_is_zero(u, len)) { fputc('0', file); return 1; } if ((&ctx->pctx)->mode == PADIC_TERSE) { if (v == 0) { _fmpz_poly_fprint_pretty(file, u, len, ctx->var); } else if (v > 0) { fmpz *t = _fmpz_vec_init(len + 1); fmpz_pow_ui(t + len, p, v); _fmpz_vec_scalar_mul_fmpz(t, u, len, t + len); _fmpz_poly_fprint_pretty(file, t, len, ctx->var); _fmpz_vec_clear(t, len + 1); } else /* v < 0 */ { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, -v); _fmpq_poly_fprint_pretty(file, u, t, len, ctx->var); fmpz_clear(t); } } else if ((&ctx->pctx)->mode == PADIC_SERIES) { fmpz *x, *d; slong i, j; for (i = 0; i < len; i++) if (fmpz_sgn(u + i) < 0) break; if (i < len) { flint_throw(FLINT_ERROR, "ERROR (qadic_fprint_pretty). u < 0 in SERIES mode.\n"); } x = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_set(x, u, len); /* Unroll first step */ j = 0; { _fmpz_vec_scalar_mod_fmpz(d, x, len, p); /* d = u mod p^{j+1} */ _fmpz_vec_sub(x, x, d, len); /* x = x - d */ _fmpz_vec_scalar_divexact_fmpz(x, x, len, p); /* x = x / p */ if (!_fmpz_vec_is_zero(d, len)) { fputc('(', file); _fmpz_poly_fprint_pretty(file, d, len, ctx->var); fputc(')', file); if (j + v != 0) { fputc('*', file); fmpz_fprint(file, p); if (j + v != 1) flint_fprintf(file, "^%wd", j + v); } } j++; } for ( ; !_fmpz_vec_is_zero(x, len); j++) { _fmpz_vec_scalar_mod_fmpz(d, x, len, p); /* d = u mod p^{j+1} */ _fmpz_vec_sub(x, x, d, len); /* x = x - d */ _fmpz_vec_scalar_divexact_fmpz(x, x, len, p); /* x = x / p */ if (!_fmpz_vec_is_zero(d, len)) { flint_fprintf(file, " + "); fputc('(', file); _fmpz_poly_fprint_pretty(file, d, len, ctx->var); fputc(')', file); if (j + v != 0) { fputc('*', file); fmpz_fprint(file, p); if (j + v != 1) flint_fprintf(file, "^%wd", j + v); } } } _fmpz_vec_clear(x, len); _fmpz_vec_clear(d, len); } else if ((&ctx->pctx)->mode == PADIC_VAL_UNIT) { if (v == 0) { _fmpz_poly_fprint_pretty(file, u, len, ctx->var); } else if (v == 1) { fputc('(', file); _fmpz_poly_fprint_pretty(file, u, len, ctx->var); fputc(')', file); fputc('*', file); fmpz_fprint(file, p); } else { fputc('(', file); _fmpz_poly_fprint_pretty(file, u, len, ctx->var); fputc(')', file); fputc('*', file); fmpz_fprint(file, p); flint_fprintf(file, "^%wd", v); } } else { flint_throw(FLINT_ERROR, "Exception (qadic_fprint_pretty). Unknown print mode.\n"); } return 1; } int qadic_fprint_pretty(FILE *file, const qadic_t op, const qadic_ctx_t ctx) { return _qadic_fprint_pretty(file, op->coeffs, op->length, op->val, ctx); } int qadic_print_pretty(const qadic_t op, const qadic_ctx_t ctx) { return qadic_fprint_pretty(stdout, op, ctx); } /* debugging ******************************************************************/ int qadic_debug(const qadic_t op) { return padic_poly_debug(op); } flint-3.1.3/src/qadic/log.c000066400000000000000000000047361461254215100154420ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qadic.h" void _qadic_log(fmpz *z, const fmpz *y, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { if (N < (WORD(1) < 10) / (slong) fmpz_bits(p)) { _qadic_log_rectangular(z, y, v, len, a, j, lena, p, N, pN); } else { _qadic_log_balanced(z, y, len, a, j, lena, p, N, pN); } } int qadic_log(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const fmpz *p = (&ctx->pctx)->p; const slong d = qadic_ctx_degree(ctx); const slong N = qadic_prec(rop); const slong len = op->length; if (op->val < 0) { return 0; } else { fmpz *x; fmpz_t pN; int alloc, ans; x = _fmpz_vec_init(len + 1); alloc = _padic_ctx_pow_ui(pN, N, &ctx->pctx); /* Set x := (1 - op) mod p^N */ fmpz_pow_ui(x + len, p, op->val); _fmpz_vec_scalar_mul_fmpz(x, op->coeffs, len, x + len); fmpz_sub_ui(x, x, 1); _fmpz_vec_neg(x, x, len); _fmpz_vec_scalar_mod_fmpz(x, x, len, pN); if (_fmpz_vec_is_zero(x, len)) { padic_poly_zero(rop); ans = 1; } else { const slong v = _fmpz_vec_ord_p(x, len, p); if (v >= 2 || (*p != WORD(2) && v >= 1)) { if (v >= N) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, d); _qadic_log(rop->coeffs, x, v, len, ctx->a, ctx->j, ctx->len, p, N, pN); rop->val = 0; _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); padic_poly_canonicalise(rop, p); } ans = 1; } else { ans = 0; } } _fmpz_vec_clear(x, len + 1); if (alloc) fmpz_clear(pN); return ans; } } flint-3.1.3/src/qadic/log_balanced.c000066400000000000000000000163331461254215100172470ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qadic.h" /* Assumes that P, T are vectors of length 2 d - 1. Assumes that 0 < len <= d. Assumes that 1 <= lo < hi. Does not support aliasing. */ static void _qadic_log_bsplit_series(fmpz *P, fmpz_t B, fmpz *T, const fmpz *y, slong len, slong lo, slong hi, const fmpz *a, const slong *j, slong lena) { const slong d = j[lena - 1]; if (hi - lo == 1) { _fmpz_vec_set(P, y, len); _fmpz_vec_zero(P + len, 2*d - 1 - len); fmpz_set_si(B, lo); _fmpz_vec_set(T, P, 2*d - 1); } else if (hi - lo == 2) { _fmpz_poly_sqr(P, y, len); _fmpz_vec_zero(P + (2*len - 1), d - (2*len - 1)); _fmpz_poly_reduce(P, 2*len - 1, a, j, lena); fmpz_set_si(B, lo); fmpz_mul_si(B, B, lo + 1); _fmpz_vec_scalar_mul_si(T, y, len, lo + 1); _fmpz_vec_zero(T + len, d - len); _fmpz_vec_scalar_addmul_si(T, P, d, lo); } else { const slong m = (lo + hi) / 2; fmpz *RP, *RT, *W; fmpz_t RB; RP = _fmpz_vec_init(2*d - 1); RT = _fmpz_vec_init(2*d - 1); W = _fmpz_vec_init(2*d - 1); fmpz_init(RB); _qadic_log_bsplit_series(P, B, T, y, len, lo, m, a, j, lena); _qadic_log_bsplit_series(RP, RB, RT, y, len, m, hi, a, j, lena); _fmpz_poly_mul(W, RT, d, P, d); _fmpz_poly_reduce(W, 2*d - 1, a, j, lena); _fmpz_vec_swap(RT, W, d); _fmpz_vec_scalar_mul_fmpz(T, T, d, RB); _fmpz_vec_scalar_addmul_fmpz(T, RT, d, B); _fmpz_poly_mul(W, P, d, RP, d); _fmpz_poly_reduce(W, 2*d - 1, a, j, lena); _fmpz_vec_swap(P, W, d); fmpz_mul(B, B, RB); _fmpz_vec_clear(RP, 2*d - 1); _fmpz_vec_clear(RT, 2*d - 1); _fmpz_vec_clear(W, 2*d - 1); fmpz_clear(RB); } } /* Sets (z, d) to the sum sum_{i=1}^{\infty} y^i / i mod p^N. The result may not be reduced modulo p^N, but it is reduced modulo f(X) given by the data (a, j, lena). Supports aliasing between y and z. */ static void _qadic_log_bsplit(fmpz *z, const fmpz *y, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; fmpz *P, *T; fmpz_t B, C; slong n; n = _padic_log_bound(v, N, p); n = FLINT_MAX(n, 2); P = _fmpz_vec_init(2*d - 1); T = _fmpz_vec_init(2*d - 1); fmpz_init(B); fmpz_init(C); _qadic_log_bsplit_series(P, B, T, y, len, 1, n, a, j, lena); n = fmpz_remove(B, B, p); fmpz_pow_ui(C, p, n); _fmpz_vec_scalar_divexact_fmpz(T, T, d, C); _padic_inv(B, B, p, N); _fmpz_vec_scalar_mul_fmpz(z, T, d, B); _fmpz_vec_clear(P, 2*d - 1); _fmpz_vec_clear(T, 2*d - 1); fmpz_clear(B); fmpz_clear(C); } /* Computes \begin{equation*} z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}. \end{equation*} Note that this can be used to compute the $p$-adic logarithm via the equation \begin{align*} \log(x) & = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} \\ & = - \sum_{i=1}^{\infty} \frac{(1-x)^i}{i}. \end{align*} Assumes that $y = 1 - x$ is non-zero and that $v = \ord_p(y)$ is at least $1$ when $p$ is odd and at least $2$ when $p = 2$ so that the series converges. Assumes that $v < N$. Sets $(z, d)$. Ensures that the result is reduced modulo $p^N$. Does not support aliasing between $y$ and $z$. */ void _qadic_log_balanced(fmpz *z, const fmpz *y, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { const slong d = j[lena - 1]; fmpz_t pv; fmpz *r, *s, *t, *u; slong i, w; r = _fmpz_vec_init(d); s = _fmpz_vec_init(2*d - 1); t = _fmpz_vec_init(d); u = _fmpz_vec_init(d); fmpz_init(pv); fmpz_set(pv, p); _fmpz_vec_scalar_mod_fmpz(t, y, len, pN); _fmpz_vec_zero(z, d); w = 1; while (!_fmpz_vec_is_zero(t, d)) { fmpz_mul(pv, pv, pv); for (i = 0; i < d; i++) { fmpz_fdiv_qr(t + i, r + i, t + i, pv); } if (!_fmpz_vec_is_zero(t, d)) { _fmpz_vec_scalar_mul_fmpz(t, t, d, pv); /* Temporarily set r = 1 - r to compute u = (1-r)^{-1} */ fmpz_sub_ui(r + 0, r + 0, 1); _fmpz_vec_neg(r, r, d); _qadic_inv(u, r, d, a, j, lena, p, N); _fmpz_vec_neg(r, r, d); fmpz_add_ui(r + 0, r + 0, 1); _fmpz_poly_mul(s, t, d, u, d); _fmpz_poly_reduce(s, 2 * d - 1, a, j, lena); _fmpz_vec_scalar_mod_fmpz(t, s, d, pN); } if (!_fmpz_vec_is_zero(r, d)) { _qadic_log_bsplit(r, r, w, d, a, j, lena, p, N); _fmpz_vec_sub(z, z, r, d); _fmpz_vec_scalar_mod_fmpz(z, z, d, pN); } w *= 2; } _fmpz_vec_clear(r, d); _fmpz_vec_clear(s, 2*d - 1); _fmpz_vec_clear(t, d); _fmpz_vec_clear(u, d); fmpz_clear(pv); } int qadic_log_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const fmpz *p = (&ctx->pctx)->p; const slong d = qadic_ctx_degree(ctx); const slong N = qadic_prec(rop); const slong len = op->length; if (op->val < 0) { return 0; } else { fmpz *x; fmpz_t pN; int alloc, ans; x = _fmpz_vec_init(len + 1); alloc = _padic_ctx_pow_ui(pN, N, &ctx->pctx); /* Set x := (1 - op) mod p^N */ fmpz_pow_ui(x + len, p, op->val); _fmpz_vec_scalar_mul_fmpz(x, op->coeffs, len, x + len); fmpz_sub_ui(x + 0, x + 0, 1); _fmpz_vec_neg(x, x, len); _fmpz_vec_scalar_mod_fmpz(x, x, len, pN); if (_fmpz_vec_is_zero(x, len)) { padic_poly_zero(rop); ans = 1; } else { const slong v = _fmpz_vec_ord_p(x, len, p); if (v >= 2 || (*p != WORD(2) && v >= 1)) { if (v >= N) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, d); _qadic_log_balanced(rop->coeffs, x, len, ctx->a, ctx->j, ctx->len, p, N, pN); rop->val = 0; _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); padic_poly_canonicalise(rop, p); } ans = 1; } else { ans = 0; } } _fmpz_vec_clear(x, len + 1); if (alloc) fmpz_clear(pN); return ans; } } flint-3.1.3/src/qadic/log_rectangular.c000066400000000000000000000164571461254215100200340ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "qadic.h" static void __fmpz_mod_poly_neg(fmpz *res, const fmpz *poly, slong len, const fmpz_t p) { slong i; for (i = 0; i < len; i++) { if (!fmpz_is_zero(poly + i)) fmpz_sub(res + i, p, poly + i); else fmpz_zero(res + i); } } static void __fmpz_mod_poly_add(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { slong i, len = FLINT_MAX(len1, len2); _fmpz_poly_add(res, poly1, len1, poly2, len2); for (i = 0; i < len; i++) { if (fmpz_cmpabs(res + i, p) >= 0) fmpz_sub(res + i, res + i, p); } } static void __fmpz_mod_poly_mul(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { _fmpz_poly_mul(res, poly1, len1, poly2, len2); _fmpz_vec_scalar_mod_fmpz(res, res, len1 + len2 - 1, p); } /* Carries out the finite series evaluation for the logarithm \begin{equation*} \sum_{i=1}^{n} a_i y^i = \sum_{j=0}^{\ceil{n/b}-1} \Bigl(\sum_{i=1}^b a_{i+jb} y^i\Bigr) y^{jb} \end{equation*} where $a_i = 1/i$ with the choice $b = \floor{\sqrt{n}}$, all modulo $p^N$, where also $P = p^N$. Assumes that $y$ is reduced modulo $p^N$. Assumes that $z$ has space for $2d - 1$ coefficients, but sets only the first $d$ to meaningful values on exit. Supports aliasing between $y$ and $z$. */ static void _qadic_log_rectangular_series(fmpz *z, const fmpz *y, slong len, slong n, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { const slong d = j[lena - 1]; if (n <= 2) { if (n == 1) /* n == 1; z = y */ { _fmpz_vec_set(z, y, len); _fmpz_vec_zero(z + len, d - len); } else /* n == 2; z = y + y^2/2 */ { slong i; fmpz *t; t = _fmpz_vec_init(2 * len - 1); _fmpz_poly_sqr(t, y, len); for (i = 0; i < 2 * len - 1; i++) if (fmpz_is_even(t + i)) { fmpz_fdiv_q_2exp(t + i, t + i, 1); } else /* => p and t(i) are odd */ { fmpz_add(t + i, t + i, pN); fmpz_fdiv_q_2exp(t + i, t + i, 1); } _fmpz_mod_poly_reduce(t, 2 * len - 1, a, j, lena, pN); __fmpz_mod_poly_add(z, y, len, t, FLINT_MIN(d, 2 * len - 1), pN); _fmpz_vec_clear(t, 2 * len - 1); } } else /* n >= 3 */ { const slong b = n_sqrt(n); const slong k = fmpz_fits_si(p) ? n_flog(n, fmpz_get_si(p)) : 0; slong i, h; fmpz_t f, pNk; fmpz *c, *t, *ypow; c = _fmpz_vec_init(d); t = _fmpz_vec_init(2 * d - 1); ypow = _fmpz_vec_init((b + 1) * d + d - 1); fmpz_init(f); fmpz_init(pNk); fmpz_pow_ui(pNk, p, N + k); fmpz_one(ypow); _fmpz_vec_set(ypow + d, y, len); for (i = 2; i <= b; i++) { __fmpz_mod_poly_mul(ypow + i * d, ypow + (i - 1) * d, d, y, len, pNk); _fmpz_mod_poly_reduce(ypow + i * d, d + len - 1, a, j, lena, pNk); } _fmpz_vec_zero(z, d); for (h = (n + (b - 1)) / b - 1; h >= 0; h--) { const slong hi = FLINT_MIN(b, n - h*b); slong w; /* Compute inner sum in c */ fmpz_rfac_uiui(f, 1 + h*b, hi); _fmpz_vec_zero(c, d); for (i = 1; i <= hi; i++) { fmpz_divexact_ui(t, f, i + h*b); _fmpz_vec_scalar_addmul_fmpz(c, ypow + i * d, d, t); } /* Multiply c by p^k f */ w = fmpz_remove(f, f, p); _padic_inv(f, f, p, N + k); if (w > k) { fmpz_pow_ui(t, p, w - k); _fmpz_vec_scalar_divexact_fmpz(c, c, d, t); } else if (w < k) { fmpz_pow_ui(t, p, k - w); _fmpz_vec_scalar_mul_fmpz(c, c, d, t); } _fmpz_vec_scalar_mul_fmpz(c, c, d, f); /* Set z = z y^b + c */ __fmpz_mod_poly_mul(t, z, d, ypow + b * d, d, pNk); _fmpz_mod_poly_reduce(t, 2 * d - 1, a, j, lena, pNk); _fmpz_vec_add(z, c, t, d); _fmpz_vec_scalar_mod_fmpz(z, z, d, pNk); } fmpz_pow_ui(f, p, k); _fmpz_vec_scalar_divexact_fmpz(z, z, d, f); fmpz_clear(f); fmpz_clear(pNk); _fmpz_vec_clear(c, d); _fmpz_vec_clear(t, 2 * d - 1); _fmpz_vec_clear(ypow, (b + 1) * d + d - 1); } } void _qadic_log_rectangular(fmpz *z, const fmpz *y, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { const slong d = j[lena - 1]; const slong n = _padic_log_bound(v, N, p) - 1; _qadic_log_rectangular_series(z, y, len, n, a, j, lena, p, N, pN); __fmpz_mod_poly_neg(z, z, d, pN); } int qadic_log_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const fmpz *p = (&ctx->pctx)->p; const slong d = qadic_ctx_degree(ctx); const slong N = qadic_prec(rop); const slong len = op->length; if (op->val < 0) { return 0; } else { fmpz *x; fmpz_t pN; int alloc, ans; x = _fmpz_vec_init(len + 1); alloc = _padic_ctx_pow_ui(pN, N, &ctx->pctx); /* Set x := (1 - op) mod p^N */ fmpz_pow_ui(x + len, p, op->val); _fmpz_vec_scalar_mul_fmpz(x, op->coeffs, len, x + len); fmpz_sub_ui(x, x, 1); _fmpz_vec_neg(x, x, len); _fmpz_vec_scalar_mod_fmpz(x, x, len, pN); if (_fmpz_vec_is_zero(x, len)) { padic_poly_zero(rop); ans = 1; } else { const slong v = _fmpz_vec_ord_p(x, len, p); if (v >= 2 || (*p != WORD(2) && v >= 1)) { if (v >= N) { padic_poly_zero(rop); } else { padic_poly_fit_length(rop, d); _qadic_log_rectangular(rop->coeffs, x, v, len, ctx->a, ctx->j, ctx->len, p, N, pN); rop->val = 0; _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); padic_poly_canonicalise(rop, p); } ans = 1; } else { ans = 0; } } _fmpz_vec_clear(x, len + 1); if (alloc) fmpz_clear(pN); return ans; } } flint-3.1.3/src/qadic/mul.c000066400000000000000000000043011461254215100154420ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qadic.h" /* Forms the product of (op1,len1) and (op2,len2) modulo (a,j,lena) and pN. Assumes that len1 >= len2 > 0. Requires rop to be of size at least len1 + len2 - 1. */ static void _qadic_mul(fmpz *rop, const fmpz *op1, slong len1, const fmpz *op2, slong len2, const fmpz *a, const slong *j, slong lena, const fmpz_t pN) { _fmpz_poly_mul(rop, op1, len1, op2, len2); _fmpz_mod_poly_reduce(rop, len1 + len2 - 1, a, j, lena, pN); } void qadic_mul(qadic_t x, const qadic_t y, const qadic_t z, const qadic_ctx_t ctx) { const slong leny = y->length; const slong lenz = z->length; const slong lenx = leny + lenz - 1; const slong N = qadic_prec(x); const slong d = qadic_ctx_degree(ctx); if (leny == 0 || lenz == 0 || y->val + z->val >= N) { qadic_zero(x); } else { fmpz *t; fmpz_t pN; int alloc; x->val = y->val + z->val; alloc = _padic_ctx_pow_ui(pN, N - x->val, &ctx->pctx); if (x == y || x == z) { t = _fmpz_vec_init(lenx); } else { padic_poly_fit_length(x, lenx); t = x->coeffs; } if (leny >= lenz) _qadic_mul(t, y->coeffs, leny, z->coeffs, lenz, ctx->a, ctx->j, ctx->len, pN); else _qadic_mul(t, z->coeffs, lenz, y->coeffs, leny, ctx->a, ctx->j, ctx->len, pN); if (x == y || x == z) { _fmpz_vec_clear(x->coeffs, x->alloc); x->coeffs = t; x->alloc = lenx; } _padic_poly_set_length(x, FLINT_MIN(lenx, d)); _padic_poly_normalise(x); if (alloc) fmpz_clear(pN); } } flint-3.1.3/src/qadic/norm.c000066400000000000000000000051251461254215100156250ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qadic.h" /* Discussion on the choice of the norm algorithm. When the logarithm function does not converge for x, the only choice is the resultant method. However, when the logarithm function converges, we can choose between the analytic method and the resultant method. Roughly speaking, we postulate that the analytic method has runtime A (log N)^2 mu(p,d,N), where mu(p,d,N) is (d log d) M(N log p). The resultant method has runtime B d^4 M(N log p). Experimentally, we find that A/B is somewhere around 4. TODO: Repeat the experiments with p=2, which is an important special case. */ void _qadic_norm(fmpz_t rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; if (len == 1) { fmpz_t pN; fmpz_init(pN); fmpz_pow_ui(pN, p, N); fmpz_powm_ui(rop, op + 0, d, pN); fmpz_clear(pN); } else { fmpz *y; slong w; y = _fmpz_vec_init(len); /* (y,len) := 1 - (op,len) */ _fmpz_vec_neg(y, op, len); fmpz_add_ui(y + 0, y + 0, 1); w = _fmpz_vec_ord_p(y, len, p); if (w >= 2 || (*p != WORD(2) && w >= 1)) { if (4 * FLINT_FLOG2(N) * FLINT_FLOG2(N) * FLINT_FLOG2(d) < d*d*d) { _qadic_norm_analytic(rop, y, w, len, a, j, lena, p, N); } else { _qadic_norm_resultant(rop, op, len, a, j, lena, p, N); } } else { _qadic_norm_resultant(rop, op, len, a, j, lena, p, N); } _fmpz_vec_clear(y, len); } } void qadic_norm(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = padic_prec(rop); const slong d = qadic_ctx_degree(ctx); const fmpz *p = (&ctx->pctx)->p; /* N(p^v u) = p^{dv} N(u) */ if (qadic_is_zero(op) || d * op->val >= N) { padic_zero(rop); } else { _qadic_norm(padic_unit(rop), op->coeffs, op->length, ctx->a, ctx->j, ctx->len, p, N - d * op->val); padic_val(rop) = d * op->val; } } flint-3.1.3/src/qadic/norm_analytic.c000066400000000000000000000050751461254215100175150ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qadic.h" /* Computes the norm of an element $x$ of $\mathbf{Z}_q$ via the identity $\Norm(x) = \exp \Trace \log (x)$ whenever $y = 1-x$ has valuation $v$ greater than $(p-1)^{-1}$. Assumes that $y$ is non-zero. */ void _qadic_norm_analytic(fmpz_t rop, const fmpz *y, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; fmpz_t pN, tru; slong trv; fmpz *lg; fmpz_init(pN); fmpz_init(tru); lg = _fmpz_vec_init(d); fmpz_pow_ui(pN, p, N); _qadic_log(lg, y, v, len, a, j, lena, p, N, pN); _qadic_trace(tru, lg, d, a, j, lena, pN); if (!fmpz_is_zero(tru)) { trv = fmpz_remove(tru, tru, p); _padic_exp(rop, tru, trv, p, N); fmpz_mod(rop, rop, pN); } else { fmpz_one(rop); } fmpz_clear(pN); fmpz_clear(tru); _fmpz_vec_clear(lg, d); } void qadic_norm_analytic(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = padic_prec(rop); const slong d = qadic_ctx_degree(ctx); const fmpz *p = (&ctx->pctx)->p; /* N(p^v u) = p^{dv} N(u) */ if (qadic_is_zero(op) || d * op->val >= N) { padic_zero(rop); } else if (op->length == 1) { fmpz_t pN; int alloc; alloc = _padic_ctx_pow_ui(pN, N - d * op->val, (&ctx->pctx)); fmpz_powm_ui(padic_unit(rop), op->coeffs + 0, d, pN); padic_val(rop) = d * op->val; if (alloc) fmpz_clear(pN); } else /* len >= 2 */ { fmpz *y; slong w; y = _fmpz_vec_init(op->length); _fmpz_vec_neg(y, op->coeffs, op->length); fmpz_add_ui(y + 0, y + 0, 1); w = _fmpz_vec_ord_p(y, op->length, p); if ((w < 2 && *p == WORD(2)) || w < 1) { flint_throw(FLINT_ERROR, "ERROR (qadic_norm_analytic). w = %wd.\n", w); } _qadic_norm_analytic(padic_unit(rop), y, w, op->length, ctx->a, ctx->j, ctx->len, p, N - d * op->val); padic_val(rop) = d * op->val; _fmpz_vec_clear(y, op->length); } } flint-3.1.3/src/qadic/norm_resultant.c000066400000000000000000000047741461254215100177370ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qadic.h" #include "fmpz_mod.h" #include "fmpz_mod_mat.h" void _qadic_norm_resultant(fmpz_t rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; fmpz_t pN; fmpz_init(pN); fmpz_pow_ui(pN, p, N); if (len == 1) { fmpz_powm_ui(rop, op + 0, d, pN); } else /* len >= 2 */ { fmpz_mod_ctx_t ctx; fmpz_mod_mat_t M; slong n = d + len - 1, i, k; /* todo: should use fmpz_mod_poly_resultant when that exists */ fmpz_mod_ctx_init(ctx, pN); fmpz_mod_mat_init(M, n, n, ctx); for (k = 0; k < len-1; k++) for (i = 0; i < lena; i++) fmpz_mod_set_fmpz(fmpz_mod_mat_entry(M, k, k + d - j[i]), a + i, ctx); for (k = 0; k < d; k++) for (i = 0; i < len; i++) fmpz_mod_set_fmpz(fmpz_mod_mat_entry(M, len - 1 + k, k + len -1 - i), op + i, ctx); fmpz_mod_mat_det(rop, M, ctx); fmpz_mod_mat_clear(M, ctx); fmpz_mod_ctx_clear(ctx); /* XXX: This part of the code is currently untested as the Conway polynomials used for the extension Qq/Qp are monic. */ if (!fmpz_is_one(a + (lena - 1))) { fmpz_t f; fmpz_init(f); fmpz_powm_ui(f, a + (lena - 1), len - 1, pN); _padic_inv(f, f, p, N); fmpz_mul(rop, f, rop); fmpz_mod(rop, rop, pN); fmpz_clear(f); } } fmpz_clear(pN); } void qadic_norm_resultant(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = padic_prec(rop); const slong d = qadic_ctx_degree(ctx); /* N(p^v u) = p^{dv} N(u) */ if (qadic_is_zero(op) || d * op->val >= N) { padic_zero(rop); } else { _qadic_norm_resultant(padic_unit(rop), op->coeffs, op->length, ctx->a, ctx->j, ctx->len, (&ctx->pctx)->p, N - d * op->val); padic_val(rop) = d * op->val; } } flint-3.1.3/src/qadic/pow.c000066400000000000000000000105741461254215100154630ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qadic.h" void _qadic_pow(fmpz *rop, const fmpz *op, slong len, const fmpz_t e, const fmpz *a, const slong *j, slong lena, const fmpz_t p) { const slong d = j[lena - 1]; if (fmpz_is_zero(e)) { fmpz_one(rop); _fmpz_vec_zero(rop + 1, 2 * d - 1 - 1); } else if (fmpz_is_one(e)) { _fmpz_vec_set(rop, op, len); _fmpz_vec_zero(rop + len, 2 * d - 1 - len); } else { ulong bit; fmpz *v = _fmpz_vec_init(2 * d - 1); fmpz *R, *S, *T; _fmpz_vec_zero(rop, 2 * d - 1); /* Set bits to the bitmask with a 1 one place lower than the msb of e */ bit = fmpz_bits(e) - 2; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if (fmpz_tstbit(e, bit2)) swaps = ~swaps; while (bit2--) if (!fmpz_tstbit(e, bit2)) swaps = ~swaps; if (swaps == 0U) { R = rop; S = v; } else { R = v; S = rop; } } /* We unroll the first step of the loop, referring to {op, len} */ _fmpz_poly_sqr(R, op, len); _fmpz_mod_poly_reduce(R, 2 * len - 1, a, j, lena, p); if (fmpz_tstbit(e, bit)) { _fmpz_poly_mul(S, R, d, op, len); _fmpz_mod_poly_reduce(S, d + len - 1, a, j, lena, p); T = R; R = S; S = T; } while (bit--) { if (fmpz_tstbit(e, bit)) { _fmpz_poly_sqr(S, R, d); _fmpz_mod_poly_reduce(S, 2 * d - 1, a, j, lena, p); _fmpz_poly_mul(R, S, d, op, len); _fmpz_mod_poly_reduce(R, d + len - 1, a, j, lena, p); } else { _fmpz_poly_sqr(S, R, d); _fmpz_mod_poly_reduce(S, 2 * d - 1, a, j, lena, p); T = R; R = S; S = T; } } _fmpz_vec_clear(v, 2 * d - 1); } } void qadic_pow(qadic_t x, const qadic_t y, const fmpz_t e, const qadic_ctx_t ctx) { const slong N = qadic_prec(x); if (fmpz_sgn(e) < 0) { flint_throw(FLINT_ERROR, "Exception (qadic_pow). e < 0.\n"); } if (fmpz_is_zero(e)) { qadic_one(x); } else if (qadic_is_zero(y)) { qadic_zero(x); } else { fmpz_t val; /* N - e * val(y) */ fmpz_init_set(val, e); fmpz_mul_si(val, val, y->val); if (fmpz_cmp_si(val, N) >= 0) { qadic_zero(x); } else if (fmpz_is_one(e)) { qadic_set(x, y, ctx); } else { const slong d = qadic_ctx_degree(ctx); fmpz *t; fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N - fmpz_get_si(val), &ctx->pctx); if (x == y) { t = _fmpz_vec_init(2 * d - 1); } else { padic_poly_fit_length(x, 2 * d - 1); t = x->coeffs; } _qadic_pow(t, y->coeffs, y->length, e, ctx->a, ctx->j, ctx->len, pow); x->val = fmpz_get_si(val); if (x == y) { _fmpz_vec_clear(x->coeffs, x->alloc); x->coeffs = t; x->alloc = 2 * d - 1; x->length = d; } else { _padic_poly_set_length(x, d); } _padic_poly_normalise(x); if (alloc) fmpz_clear(pow); } fmpz_clear(val); } } flint-3.1.3/src/qadic/profile/000077500000000000000000000000001461254215100161435ustar00rootroot00000000000000flint-3.1.3/src/qadic/profile/p-exp_balanced.c000066400000000000000000000051231461254215100211520ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic exponential (balanced) routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the norm of p A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 10000000, 1000000, 100000, 100000, 10000, 10000, 1000, 1000, 1000, 100, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic exponential (balanced).\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 5, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t b; qadic_t z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(b); qadic_init(z); padic_poly_fit_length(b, d); _padic_poly_set_length(b, d); b->val = 1; for (i = 0; i < d; i++) { fmpz_t f, pN; fmpz_init(f); fmpz_init(pN); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pN, p, n - 1); fmpz_powm_ui(b->coeffs + i, f, 3 * n, pN); fmpz_clear(f); fmpz_clear(pN); } _padic_poly_normalise(b); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_exp_balanced(z, b, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(b); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-exp_rectangular.c000066400000000000000000000051521461254215100217320ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic exponential (rectangular) routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the norm of p A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 10000000, 1000000, 100000, 100000, 10000, 10000, 1000, 1000, 1000, 100, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic exponential (rectangular).\n"); fflush(stdout); for (l = 0; l < FLINT_MIN(16, len); l++) { slong d = 5, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t b; qadic_t z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(b); qadic_init(z); padic_poly_fit_length(b, d); _padic_poly_set_length(b, d); b->val = 1; for (i = 0; i < d; i++) { fmpz_t f, pN; fmpz_init(f); fmpz_init(pN); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pN, p, n - 1); fmpz_powm_ui(b->coeffs + i, f, 3 * n, pN); fmpz_clear(f); fmpz_clear(pN); } _padic_poly_normalise(b); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_exp_rectangular(z, b, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(b); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-frobenius.c000066400000000000000000000051141461254215100205410ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic Frobenius routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute Sigma(A) mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 10000, 1000, 100, 100, 100, 100, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic Frobenius.\n"); fflush(stdout); for (l = 0; l < FLINT_MIN(16, len); l++) { slong d = 97, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t a, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(a); qadic_init(z); padic_poly_fit_length(a, d); _padic_poly_set_length(a, d); a->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(a->coeffs + i, f, 3 * n); fmpz_mod(a->coeffs + i, a->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(a); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_frobenius(z, a, 1, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %6XYXYXYXY, %5ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(a); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-inv.c000066400000000000000000000050671461254215100173500ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic inversion routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and invert A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 1000, 1000, 1000, 1000, 1000, 1000, 100, 100, 100, 100, 100, 10, 10, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic inversion.\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 97, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t a, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(a); qadic_init(z); padic_poly_fit_length(a, d); _padic_poly_set_length(a, d); a->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(a->coeffs + i, f, 3 * n); fmpz_mod(a->coeffs + i, a->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(a); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_inv(z, a, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(a); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-log_balanced.c000066400000000000000000000053641461254215100211460ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic logarithm (balanced). We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the logarithm of E = 1 + p A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 10000000, 100000, 100000, 10000, 10000, 1000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic logarithm (balanced).\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 5, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t e, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(e); qadic_init(z); padic_poly_fit_length(e, d); _padic_poly_set_length(e, d); e->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(e->coeffs + i, f, 3 * n); fmpz_mul(e->coeffs + i, e->coeffs + i, p); if (i == 0) fmpz_add_ui(e->coeffs + 0, e->coeffs + 0, 1); fmpz_mod(e->coeffs + i, e->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(e); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_log_balanced(z, e, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(e); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-log_rectangular.c000066400000000000000000000054141461254215100217200ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic logarithm (rectangular). We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the logarithm of E = 1 + p A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 10000000, 100000, 100000, 10000, 10000, 1000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic logarithm (rectangular).\n"); fflush(stdout); for (l = 0; l < FLINT_MIN(16, len); l++) { slong d = 5, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t e, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(e); qadic_init(z); padic_poly_fit_length(e, d); _padic_poly_set_length(e, d); e->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(e->coeffs + i, f, 3 * n); fmpz_mul(e->coeffs + i, e->coeffs + i, p); if (i == 0) fmpz_add_ui(e->coeffs + 0, e->coeffs + 0, 1); fmpz_mod(e->coeffs + i, e->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(e); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_log_rectangular(z, e, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(e); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-mul.c000066400000000000000000000056561461254215100173550ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic multiplication routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute A*B mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}, B = [b{0},...,b{d-1}], where b{i} = (5+2*i)^{3N}, */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 100000, 10000, 10000, 10000, 10000, 1000, 1000, 1000, 1000, 100, 100, 10, 10, 10, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic multiplication.\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 97, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t a, b, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(a); qadic_init(b); qadic_init(z); padic_poly_fit_length(a, d); _padic_poly_set_length(a, d); a->val = 0; padic_poly_fit_length(b, d); _padic_poly_set_length(b, d); b->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_pow_ui(pow, p, n); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(a->coeffs + i, f, 3 * n); fmpz_mod(a->coeffs + i, a->coeffs + i, pow); fmpz_set_ui(f, 5 + 2*i); fmpz_pow_ui(b->coeffs + i, f, 3 * n); fmpz_mod(b->coeffs + i, b->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(a); _padic_poly_normalise(b); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_mul(z, a, b, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(a); qadic_clear(b); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-norm_analytic.c000066400000000000000000000053561461254215100214140ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic norm routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the norm of E = 1 + p A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 10000000, 100000, 10000, 10000, 10000, 1000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic norm (analytic).\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 5, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t e; padic_t z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(e); padic_init(z); padic_poly_fit_length(e, d); _padic_poly_set_length(e, d); e->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(e->coeffs + i, f, 3 * n); fmpz_mul(e->coeffs + i, e->coeffs + i, p); if (i == 0) fmpz_add_ui(e->coeffs + 0, e->coeffs + 0, 1); fmpz_mod(e->coeffs + i, e->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(e); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_norm_analytic(z, e, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(e); padic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-norm_resultant.c000066400000000000000000000053661461254215100216320ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic norm routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the norm of E = 1 + p A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 1000000, 10000, 10000, 10000, 10000, 10000, 10000, 1000, 1000, 1000, 100, 100, 10, 10, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic norm (resultant).\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 5, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t e; padic_t z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(e); padic_init(z); padic_poly_fit_length(e, d); _padic_poly_set_length(e, d); e->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(e->coeffs + i, f, 3 * n); fmpz_mul(e->coeffs + i, e->coeffs + i, p); if (i == 0) fmpz_add_ui(e->coeffs + 0, e->coeffs + 0, 1); fmpz_mod(e->coeffs + i, e->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(e); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_norm_resultant(z, e, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(e); padic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-sqrt.c000066400000000000000000000054501461254215100175410ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic square root routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the square root of B = A^2, A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic square root.\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 97, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t a, b, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(a); qadic_init(b); qadic_init(z); padic_poly_fit_length(a, d); _padic_poly_set_length(a, d); a->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(a->coeffs + i, f, 3 * n); fmpz_mod(a->coeffs + i, a->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(a); qadic_mul(b, a, a, ctx); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_sqrt(z, b, ctx); qadic_zero(z); } c1 = clock(); qadic_sqrt(z, b, ctx); qadic_mul(z, z, z, ctx); if (!qadic_equal(b, z)) { flint_printf("FAIL:\n"); flint_abort(); } cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(a); qadic_clear(b); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-teichmuller.c000066400000000000000000000046121461254215100210640ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic square root routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the Teichmuller lift of C where C = [c{0},...,c{d-1}], where c{i} = (3+i) mod p. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 100, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic Teichmuller.\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 97, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t c, z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(c); qadic_init(z); padic_poly_fit_length(c, d); _padic_poly_set_length(c, d); c->val = 0; for (i = 0; i < d; i++) { fmpz_set_ui(c->coeffs + i, 3 + i); fmpz_mod(c->coeffs + i, c->coeffs + i, p); } _padic_poly_normalise(c); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_teichmuller(z, c, ctx); qadic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(c); qadic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/profile/p-trace.c000066400000000000000000000051671461254215100176530ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /* Benchmarks for the q-adic trace routine. We consider the set-up with p = 17, N = 2^i, i = 0, ..., 19, and compute the trace of A mod p^N, where A = [a{0},...,a{d-1}], where a{i} = (3+i)^{3N}. */ #include #include #include #include "flint.h" #include "fmpz.h" #include "qadic.h" int main(void) { slong l, len = 20; slong runs[] = { 100000, 100000, 100000, 100000, 100000, 100000, 100000, 100000, 100000, 100000, 10000, 10000, 1000, 1000, 1000, 100, 100, 10, 10, 10 }; slong N[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19 }; slong T[20] = {0}; flint_printf("Benchmark for q-adic trace.\n"); fflush(stdout); for (l = 0; l < len; l++) { slong d = 97, i, n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; qadic_ctx_t ctx; qadic_t a; padic_t z; FLINT_TEST_INIT(state); fmpz_init_set_ui(p, 17); qadic_ctx_init_conway(ctx, p, d, n, n, "X", PADIC_VAL_UNIT); qadic_init(a); padic_init(z); padic_poly_fit_length(a, d); _padic_poly_set_length(a, d); a->val = 0; for (i = 0; i < d; i++) { fmpz_t f, pow; fmpz_init(f); fmpz_init(pow); fmpz_set_ui(f, 3 + i); fmpz_pow_ui(pow, p, n); fmpz_pow_ui(a->coeffs + i, f, 3 * n); fmpz_mod(a->coeffs + i, a->coeffs + i, pow); fmpz_clear(f); fmpz_clear(pow); } _padic_poly_normalise(a); c0 = clock(); for (r = runs[l]; (r); r--) { qadic_trace(z, a, ctx); padic_zero(z); } c1 = clock(); cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC; T[l] = (slong) (cputime * (1000000000 / runs[l])); flint_printf("%2ld, %4XYXYXYXY, %8ld, %wd\n", l, cputime, runs[l], T[l]); qadic_clear(a); padic_clear(z); fmpz_clear(p); qadic_ctx_clear(ctx); flint_randclear(state); } flint_printf("Output as a list:\n"); for (l = 0; l < len; l++) flint_printf("%wd, ", T[l]); flint_printf("\n"); return 0; } flint-3.1.3/src/qadic/set_fmpz_poly.c000066400000000000000000000014701461254215100175430ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qadic.h" void qadic_set_fmpz_poly(qadic_t rop, const fmpz_poly_t op, const qadic_ctx_t ctx) { const slong len = op->length; if (len == 0) { qadic_zero(rop); } else { padic_poly_fit_length(rop, len); _padic_poly_set_length(rop, len); _fmpz_vec_set(rop->coeffs, op->coeffs, len); rop->val = 0; qadic_reduce(rop, ctx); } } flint-3.1.3/src/qadic/sqrt.c000066400000000000000000000603061461254215100156450ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mod_poly.h" #include "qadic.h" static int __fmpz_mod_poly_invmod(fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_t p) { fmpz * t, * u; fmpz_mod_ctx_t mod; int res; t = _fmpz_vec_init(lenB); u = _fmpz_vec_init(lenP); fmpz_mod_ctx_init(mod, p); _fmpz_vec_scalar_mod_fmpz(t, B, lenB, p); _fmpz_vec_scalar_mod_fmpz(u, P, lenP, p); res = _fmpz_mod_poly_invmod(A, t, lenB, u, lenP, mod); fmpz_mod_ctx_clear(mod); _fmpz_vec_clear(t, lenB); _fmpz_vec_clear(u, lenP); return res; } /* FILE DOCUMENTATION. This file contains routines for computing square roots in finite fields and Hensel lifting. - _find_nonresidue() - _artin_schreier_preimage() - _fmpz_mod_poly_sqrtmod_p() - _fmpz_mod_poly_sqrtmod_2() - _qadic_sqrt_p() - _qadic_sqrt() - qadic_sqrt() */ /* Sets \code{(rop,d)} to a non-residue in $\mathbf{F_q}$ for odd $p$ and $d \geq 2$. */ static void _find_nonresidue(fmpz *rop, const fmpz *a, const slong *j, slong lena, const fmpz_t p) { const slong d = j[lena - 1]; fmpz *w; fmpz_t pm1, z; slong i; w = _fmpz_vec_init(2 * d - 1); fmpz_init(pm1); fmpz_init(z); fmpz_sub_ui(pm1, p, 1); fmpz_pow_ui(z, p, d); fmpz_sub_ui(z, z, 1); fmpz_fdiv_q_2exp(z, z, 1); /* Find a non-residue g; uses stack-based depth first traversal starting from [0,...,0,1] */ _fmpz_vec_zero(rop, d); fmpz_one(rop + (d - 1)); for (i = d; i > 0; ) { if (i == d) { /* Consider this element, rop^{(q-1)/2} == -1 ? */ _qadic_pow(w, rop, d, z, a, j, lena, p); if (fmpz_equal(w + 0, pm1) && _fmpz_vec_is_zero(w + 1, d - 1)) break; /* Backtrace, find the next element */ for (i--; i >= 0 && fmpz_equal(rop + i, pm1); i--) ; if (i >= 0) { fmpz_add_ui(rop + i, rop + i, 1); i++; } } else { _fmpz_vec_zero(rop + i, d - i); i = d; } } _fmpz_vec_clear(w, 2 * d - 1); fmpz_clear(pm1); fmpz_clear(z); } /* Given an element $d$ as \code{(op,len)}, returns whether it has a preimage $u$ under the Artin Schreier map $Y \mapsto Y^2 + Y$, and if so sets \code{(rop,d)} to $u$. In this case, the other preimage is given by $u + 1$. This completes the set of preimages as the kernel of the Artin Schreier map is $\mathbf{F}_2$. The value of \code{(rop,d)}$ is undefined when the return value is zero. */ int _artin_schreier_preimage(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena) { const slong d = j[lena - 1]; const fmpz_t p = {WORD(2)}; int ans; fmpz *e, *f; nmod_mat_t A; slong i, k, *P; e = _fmpz_vec_init(d); f = _fmpz_vec_init(2 * d - 1); nmod_mat_init(A, d, d, 2); P = flint_malloc(d * sizeof(slong)); /* Construct Artin Schreier matrix ------------------------------------- */ for (i = 0; i < d; i++) { fmpz_one(e + i); _fmpz_poly_sqr(f, e, i+1); _fmpz_poly_reduce(f, 2*(i+1)-1, a, j, lena); fmpz_add_ui(f + i, f + i, 1); _fmpz_vec_scalar_mod_fmpz(f, f, d, p); for (k = 0; k < d; k++) { nmod_mat_entry(A, k, i) = (mp_limb_t) f[k]; } fmpz_zero(e + i); } /* Perform LUP decomposition ------------------------------------------- */ /* Write LU = PA and r = rank(A) so that U is in row echelon form with only the top r rows non-zero, and L is lower unit triangular truncated to r columns. We know that Y^2 + Y = 0 if and only if Y is in the base field, i.e., dim ker(A) = 1 and rank(A) = d-1. Consider the linear system A x = b, which we can then write as LU x = Pb, hence L y = Pb and U x = y. */ #if FLINT_WANT_ASSERT { slong res = nmod_mat_lu(P, A, 0); FLINT_ASSERT(res == d - 1); } #else nmod_mat_lu(P, A, 0); #endif /* Solve for a preimage of (op,len) ------------------------------------ */ _fmpz_vec_zero(rop, d); for (i = 0; i < d; i++) { rop[i] = P[i] < len ? op[P[i]] : 0; for (k = 0; k < i; k++) rop[i] ^= nmod_mat_entry(A, i, k) & rop[k]; } ans = (rop[d-1] == 0); if (ans) { slong c; for (c = 0; c < d; c++) if (nmod_mat_entry(A, c, c) == 0) break; for (k = d - 1; k > c; k--) { rop[k] = rop[k-1]; if ((rop[k])) for (i = k - 2; i >= 0; i--) rop[i] ^= nmod_mat_entry(A, i, k); } rop[k] = 0; for (k--; k >= 0; k--) { if ((rop[k])) for (i = k - 1; i >= 0; i--) rop[i] ^= nmod_mat_entry(A, i, k); } } /* Clean-up ------------------------------------------------------------ */ _fmpz_vec_clear(e, d); _fmpz_vec_clear(f, 2 * d - 1); nmod_mat_clear(A); flint_free(P); return ans; } /* Returns whether the non-zero element \code{(op, len)} is a square, and if so sets \code{(rop, 2 * d - 1)} to its square root. Assumes that $p$ is an odd prime. Assumes that $d \geq 1$. Does not support aliasing. */ static int _fmpz_mod_poly_sqrtmod_p(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p) { const slong d = j[lena - 1]; int ans; /* When $q \equiv 3 \pmod{4}$... A non-zero element $x$ is a square if and only if $x^{(q-1)/2} = 1$, and in this case one of its square roots is given by $x^{(q+1)/4}$. To avoid recomputation of powers of $x$, we compute $x^{(q-3)/4}$, multiply this by $x$ to obtain the potential square root $x^{(q+1)/4}$, and then combine these two powers to find $x^{(q-1)/2}$. */ if (fmpz_fdiv_ui(p, 4) == 3 && (d & WORD(1))) { fmpz_t z; fmpz *v, *w; fmpz_init(z); v = _fmpz_vec_init(4 * d - 2); w = v + (2 * d - 1); fmpz_pow_ui(z, p, d); fmpz_sub_ui(z, z, 3); fmpz_fdiv_q_2exp(z, z, 2); _qadic_pow(v, op, len, z, a, j, lena, p); _fmpz_poly_mul(rop, v, d, op, len); _fmpz_vec_zero(rop + d + len - 1, d - len); _fmpz_mod_poly_reduce(rop, d + len - 1, a, j, lena, p); _fmpz_poly_mul(w, rop, d, v, d); _fmpz_mod_poly_reduce(w, 2 * d - 1, a, j, lena, p); ans = fmpz_is_one(w + 0); fmpz_clear(z); _fmpz_vec_clear(v, 4 * d - 2); } /* When $q \equiv 5 \pmod{8}$... A non-zero element $x$ is a square if and only if $y = x^{(q-1)/4}$ is $\pm 1$. If $y = +1$, a square root is given by $x^{(q+3)/8}$, otherwise it is $(2x) (4x)^{(q-5)/8}$. We begin by computing $v = x^{(q-5)/8}$, $w = x v = x^{(q+3)/8}$ and $y = v w = x^{(q-1)/4}$. If $y = +1$ we return $w$, and if $y = -1$ we return $2^{(q-1)/4} x^{(q+3)/8} = 2^{(q-1)/4} w$. */ else if (fmpz_fdiv_ui(p, 8) == 5 && (d & WORD(1))) { fmpz_t f, g, pm1; fmpz *v; /* v = x^{(q-5)/8} */ fmpz *w; /* w = x^{(q+3)/8} */ fmpz *y; /* y = x^{(q-1)/4} */ fmpz_init(f); fmpz_init(g); fmpz_init(pm1); fmpz_sub_ui(pm1, p, 1); v = _fmpz_vec_init(2 * d - 1); w = _fmpz_vec_init(2 * d - 1); y = _fmpz_vec_init(2 * d - 1); fmpz_pow_ui(g, p, d); fmpz_sub_ui(g, g, 5); fmpz_fdiv_q_2exp(g, g, 3); _qadic_pow(v, op, len, g, a, j, lena, p); _fmpz_poly_mul(w, v, d, op, len); _fmpz_mod_poly_reduce(w, d + len - 1, a, j, lena, p); _fmpz_poly_mul(y, v, d, w, d); _fmpz_mod_poly_reduce(y, 2 * d - 1, a, j, lena, p); if ((fmpz_is_one(y + 0) || fmpz_equal(y + 0, pm1)) /* q.r. */ && _fmpz_vec_is_zero(y + 1, d - 1)) { if (fmpz_is_one(y + 0)) { _fmpz_vec_set(rop, w, d); } else { fmpz_t two = {WORD(2)}; fmpz_zero(g); fmpz_pow_ui(g, p, d); fmpz_sub_ui(g, g, 1); fmpz_fdiv_q_2exp(g, g, 2); _fmpz_vec_set(rop, v, d); fmpz_powm(f, two, g, p); _fmpz_vec_scalar_mul_fmpz(rop, w, d, f); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, p); } _fmpz_vec_zero(rop + d, d - 1); ans = 1; } else /* q.n.r. */ { ans = 0; } fmpz_clear(f); fmpz_clear(g); fmpz_clear(pm1); _fmpz_vec_clear(v, 2 * d - 1); _fmpz_vec_clear(w, 2 * d - 1); _fmpz_vec_clear(y, 2 * d - 1); } /* General case for odd $q$... TODO: Find a better way to integrate the check for square-ness into the computation of a potential square root. */ else { slong i, s; fmpz_t t, pm1, qm1, z; fmpz *b, *g, *bpow, *gpow, *w; fmpz_init(t); fmpz_init(pm1); fmpz_init(qm1); fmpz_init(z); fmpz_sub_ui(pm1, p, 1); fmpz_pow_ui(qm1, p, d); fmpz_sub_ui(qm1, qm1, 1); b = _fmpz_vec_init(2 * d - 1); g = _fmpz_vec_init(2 * d - 1); bpow = _fmpz_vec_init(2 * d - 1); gpow = _fmpz_vec_init(2 * d - 1); w = _fmpz_vec_init(2 * d - 1); /* Check whether op is a square, i.e. op^{(q-1}/2} == 1 */ fmpz_fdiv_q_2exp(z, qm1, 1); _qadic_pow(w, op, len, z, a, j, lena, p); ans = fmpz_is_one(w); if (ans) { /* Find a non-residue g */ _find_nonresidue(g, a, j, lena, p); /* Write q - 1 = 2^s t */ for (s = 0, fmpz_set(t, qm1); fmpz_is_even(t); s++) fmpz_fdiv_q_2exp(t, t, 1); /* Set g = g^t */ _qadic_pow(w, g, d, t, a, j, lena, p); _fmpz_vec_set(g, w, d); /* Set rop = op^{(t+1)/2} */ fmpz_add_ui(z, t, 1); fmpz_fdiv_q_2exp(z, z, 1); _qadic_pow(rop, op, len, z, a, j, lena, p); /* Set b = op^t */ _qadic_pow(b, op, len, t, a, j, lena, p); while (!_fmpz_poly_is_one(b, d)) { slong k; _fmpz_vec_set(bpow, b, d); for (k = 1; (k < s) && !_fmpz_poly_is_one(bpow, d); k++) { _fmpz_poly_sqr(w, bpow, d); _fmpz_mod_poly_reduce(w, 2 * d - 1, a, j, lena, p); _fmpz_vec_scalar_mod_fmpz(bpow, w, d, p); } _fmpz_vec_set(gpow, g, d); for (i = 1; i < s - k; i++) { _fmpz_poly_sqr(w, gpow, d); _fmpz_mod_poly_reduce(w, 2 * d - 1, a, j, lena, p); _fmpz_vec_scalar_mod_fmpz(gpow, w, d, p); } _fmpz_poly_mul(w, rop, d, gpow, d); _fmpz_mod_poly_reduce(w, 2 * d - 1, a, j, lena, p); _fmpz_vec_scalar_mod_fmpz(rop, w, d, p); _fmpz_poly_sqr(w, gpow, d); _fmpz_mod_poly_reduce(w, 2 * d - 1, a, j, lena, p); _fmpz_vec_scalar_mod_fmpz(gpow, w, d, p); _fmpz_poly_mul(w, b, d, gpow, d); _fmpz_mod_poly_reduce(w, 2 * d - 1, a, j, lena, p); _fmpz_vec_scalar_mod_fmpz(b, w, d, p); s = k; } } fmpz_clear(t); fmpz_clear(pm1); fmpz_clear(qm1); fmpz_clear(z); _fmpz_vec_clear(b, 2 * d - 1); _fmpz_vec_clear(g, 2 * d - 1); _fmpz_vec_clear(bpow, 2 * d - 1); _fmpz_vec_clear(gpow, 2 * d - 1); _fmpz_vec_clear(w, 2 * d - 1); } return ans; } /* Sets \code{(rop, 2 * d - 1)} to the square root of \code{(op, len)}. Note that the group of units of $\mathbf{F}_q$ is cyclic of order $q - 1$, which is odd if $p = 2$. We have $x^{q-1} = 1$ for every non-zero $x$, so $x^q = x$ for every $x$ and $u = x^{q/2}$ satisfies $u^2 = x$. Assumes that $d \geq 1$. */ static void _fmpz_mod_poly_sqrtmod_2(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena) { const fmpz_t p = {WORD(2)}; const slong d = j[lena - 1]; fmpz_t z; fmpz_init(z); fmpz_setbit(z, d - 1); _qadic_pow(rop, op, len, z, a, j, lena, p); fmpz_clear(z); } /* Returns whether \code{(op, len)} is a square, and if so sets \code{(rop, 2 * d - 1)} to a square root mod $p^N$. Assumes that \code{(op, len)} has valuation $0$. */ static int _qadic_sqrt_p(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; int ans; if (N == 1) { ans = _fmpz_mod_poly_sqrtmod_p(rop, op, len, a, j, lena, p); return ans; } else { slong *e, i, k, n; fmpz *pow, *u; fmpz *r, *s, *t, *f; n = FLINT_CLOG2(N) + 1; /* Compute sequence of exponents */ e = flint_malloc(n * sizeof(slong)); for (e[i = 0] = N; e[i] > 1; i++) e[i + 1] = (e[i] + 1) / 2; pow = _fmpz_vec_init(n); u = _fmpz_vec_init(len * n); r = _fmpz_vec_init(2 * d - 1); s = _fmpz_vec_init(2 * d - 1); t = _fmpz_vec_init(2 * d - 1); f = _fmpz_vec_init(d + 1); /* Compute powers of p */ { fmpz_one(t); fmpz_set(pow + i, p); } for (i--; i >= 1; i--) { if (e[i] & WORD(1)) { fmpz_mul(pow + i, t, pow + (i + 1)); fmpz_mul(t, t, t); } else { fmpz_mul(t, t, pow + (i + 1)); fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } } { if (e[i] & WORD(1)) fmpz_mul(pow + i, t, pow + (i + 1)); else fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } /* Compute reduced units */ { _fmpz_vec_scalar_mod_fmpz(u + 0 * len, op, len, pow + 0); } for (i = 1; i < n; i++) { _fmpz_vec_scalar_mod_fmpz(u + i * len, u + (i - 1) * len, len, pow + i); } /* Run Newton iteration */ i = n - 1; { ans = _fmpz_mod_poly_sqrtmod_p(t, u + i * len, len, a, j, lena, p); if (!ans) goto exit; /* Dense copy of f, used for inversion */ for (k = 0; k < lena; k++) fmpz_set(f + j[k], a + k); __fmpz_mod_poly_invmod(rop, t, d, f, d + 1, p); } for (i--; i >= 1; i--) /* z := z - z (a z^2 - 1) / 2 */ { _fmpz_poly_sqr(s, rop, d); _fmpz_poly_reduce(s, 2 * d - 1, a, j, lena); _fmpz_poly_mul(t, s, d, u + i * len, len); _fmpz_poly_reduce(t, d + len - 1, a, j, lena); fmpz_sub_ui(t, t, 1); for (k = 0; k < d; k++) { if (fmpz_is_odd(t + k)) fmpz_add(t + k, t + k, pow + i); fmpz_fdiv_q_2exp(t + k, t + k, 1); } _fmpz_poly_mul(s, t, d, rop, d); _fmpz_poly_reduce(s, 2 * d - 1, a, j, lena); _fmpz_poly_sub(rop, rop, d, s, d); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, pow + i); } { _fmpz_poly_mul(s, rop, d, u + 1 * len, len); _fmpz_poly_reduce(s, d + len - 1, a, j, lena); _fmpz_poly_sqr(t, s, d); _fmpz_poly_reduce(t, 2 * d - 1, a, j, lena); _fmpz_poly_sub(t, u + 0 * len, len, t, d); for (k = 0; k < d; k++) { if (fmpz_is_odd(t + k)) fmpz_add(t + k, t + k, pow + 0); fmpz_fdiv_q_2exp(t + k, t + k, 1); } _fmpz_poly_mul(r, rop, d, t, d); _fmpz_poly_reduce(r, 2 * d - 1, a, j, lena); _fmpz_poly_add(rop, r, d, s, d); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, pow + 0); } exit: _fmpz_vec_clear(pow, n); _fmpz_vec_clear(u, len * n); _fmpz_vec_clear(r, 2 * d - 1); _fmpz_vec_clear(s, 2 * d - 1); _fmpz_vec_clear(t, 2 * d - 1); _fmpz_vec_clear(f, d + 1); flint_free(e); return ans; } } /* Returns whether \code{(op, len)} is a square, and if so sets \code{(rop, 2 * d - 1)} to a square root mod $2^N$. Assumes that \code{(op, len)} has valuation $0$. */ static int _qadic_sqrt_2(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, slong N) { int ans; const slong d = j[lena - 1]; const fmpz_t p = {WORD(2)}; fmpz *g, *r, *s, *t; slong i; g = _fmpz_vec_init(2 * d - 1); r = _fmpz_vec_init(2 * d - 1); s = _fmpz_vec_init(2 * d - 1); t = _fmpz_vec_init(2 * d - 1); /* Compute r = 1/op (mod 8) */ _qadic_inv(r, op, len, a, j, lena, p, 3); /* Compute s = invsqrt(op) (mod 2) */ _fmpz_vec_scalar_fdiv_r_2exp(t, r, d, 1); _fmpz_mod_poly_sqrtmod_2(s, r, d, a, j, lena); /* Compute t = (1/op - s^2) / 4 (mod 2) if that makes sense */ _fmpz_poly_sqr(t, s, d); _fmpz_poly_reduce(t, 2*d - 1, a, j, lena); _fmpz_vec_sub(t, r, t, d); _fmpz_vec_zero(rop, 2 * d - 1); ans = 1; for (i = 0; i < d; i++) { if (fmpz_val2(t + i) == 1) ans = 0; } if (ans) { _fmpz_vec_scalar_fdiv_q_2exp(t, t, d, 2); _fmpz_vec_scalar_fdiv_r_2exp(t, t, d, 1); /* Check whether X^2 + s X = t (mod 2) has a solution */ /* u = (op,len) is a square in Zq iff it is a square modulo 8, which is the case iff X^2 + s X + t == 0 (mod 2) is soluble. Let g be t/s^2. Then the above quadratic is soluble iff Y^2 + Y + d = 0 is soluble. We can observe that 1/s^2 = op (mod 2). */ _fmpz_vec_scalar_fdiv_r_2exp(r, op, len, 1); _fmpz_poly_mul(g, t, d, r, len); _fmpz_mod_poly_reduce(g, 2 * d - 1, a, j, lena, p); ans = _artin_schreier_preimage(r, g, d, a, j, lena); if (ans) { if (N == 1) { _fmpz_mod_poly_sqrtmod_2(rop, op, len, a, j, lena); } else { /* Set t = r s, a root of X^2 + s X = t (mod 2) */ _fmpz_poly_mul(t, r, d, s, d); _fmpz_mod_poly_reduce(t, 2 * d - 1, a, j, lena, p); /* Now s + 2t is an invsqrt of (op, len) to precision 4. */ _fmpz_vec_scalar_addmul_si(s, t, d, 2); if (N == 2) { _qadic_inv(rop, s, d, a, j, lena, p, 2); } else /* N >= 3 */ { slong *e, n; fmpz *u; n = FLINT_CLOG2(N - 1) + 1; /* Compute sequence of exponents */ e = flint_malloc(n * sizeof(slong)); for (e[i = 0] = N; e[i] > 2; i++) e[i + 1] = e[i] / 2 + 1; u = _fmpz_vec_init(len * n); /* Compute reduced units */ { _fmpz_vec_scalar_fdiv_r_2exp(u + 0 * len, op, len, e[0]); } for (i = 1; i < n; i++) { _fmpz_vec_scalar_fdiv_r_2exp(u + i * len, u + (i - 1) * len, len, e[i] + 1); } /* Run Newton iteration */ { _fmpz_vec_set(rop, s, d); } for (i = n - 2; i >= 1; i--) /* z := z - z (a z^2 - 1) / 2 */ { _fmpz_poly_sqr(s, rop, d); _fmpz_poly_reduce(s, 2 * d - 1, a, j, lena); _fmpz_poly_mul(t, s, d, u + i * len, len); _fmpz_poly_reduce(t, d + len - 1, a, j, lena); fmpz_sub_ui(t, t, 1); _fmpz_vec_scalar_fdiv_q_2exp(t, t, d, 1); _fmpz_poly_mul(s, t, d, rop, d); _fmpz_poly_reduce(s, 2 * d - 1, a, j, lena); _fmpz_poly_sub(rop, rop, d, s, d); _fmpz_vec_scalar_fdiv_r_2exp(rop, rop, d, e[i]); } /* z := a z + z (a - (a z)^2) / 2 */ { _fmpz_poly_mul(s, rop, d, u + len, len); _fmpz_poly_reduce(s, d + len - 1, a, j, lena); _fmpz_poly_sqr(t, s, d); _fmpz_poly_reduce(t, 2 * d - 1, a, j, lena); _fmpz_poly_sub(t, u + 0 * len, len, t, d); _fmpz_vec_scalar_fdiv_q_2exp(t, t, d, 1); _fmpz_poly_mul(r, rop, d, t, d); _fmpz_poly_reduce(r, 2 * d - 1, a, j, lena); _fmpz_poly_add(rop, r, d, s, d); _fmpz_vec_scalar_fdiv_r_2exp(rop, rop, d, e[0]); } _fmpz_vec_clear(u, len * n); flint_free(e); } } } } _fmpz_vec_clear(g, 2 * d - 1); _fmpz_vec_clear(r, 2 * d - 1); _fmpz_vec_clear(s, 2 * d - 1); _fmpz_vec_clear(t, 2 * d - 1); return ans; } /* Returns whether \code{(op, len)} is a square, and if so sets \code{(rop, 2 * d - 1)} to a square root, reduced modulo $2^N$. Assumes that \code{(op, len)} has valuation $0$. */ int _qadic_sqrt(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { if (*p == WORD(2)) { return _qadic_sqrt_2(rop, op, len, a, j, lena, N); } else { return _qadic_sqrt_p(rop, op, len, a, j, lena, p, N); } } int qadic_sqrt(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const fmpz *p = (&ctx->pctx)->p; const slong d = qadic_ctx_degree(ctx); const slong N = qadic_prec(rop); const slong vop = qadic_val(op); fmpz *t; int ans; if (qadic_is_zero(op)) { qadic_zero(rop); return 1; } if (op->val & WORD(1)) { return 0; } rop->val = op->val / 2; if (rop == op) { t = _fmpz_vec_init(2*d - 1); } else { padic_poly_fit_length(rop, 2*d - 1); t = rop->coeffs; } if (rop->val >= N) /* must check square even if rop prec will be <= valuation */ { slong prec = FLINT_MIN(qadic_prec(op) - vop, 1 + (fmpz_cmp_ui(p, 2) == 0)); ans = prec <= 0 ? 1 : _qadic_sqrt(t, op->coeffs, op->length, ctx->a, ctx->j, ctx->len, p, prec); } else ans = _qadic_sqrt(t, op->coeffs, op->length, ctx->a, ctx->j, ctx->len, p, N - rop->val); if (rop == op) { _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = 2 * d - 1; rop->length = d; } if (rop->val >= N) qadic_zero(rop); else { _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); if (padic_poly_length(rop) == 0) padic_poly_val(rop) = 0; } return ans; } flint-3.1.3/src/qadic/teichmuller.c000066400000000000000000000102731461254215100171670ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qadic.h" /* Uses Hensel lifting along the polynomial $X^q - X$, which yields the formula $z' = z - (z^q - z) / (q z^{q-1} - 1)$. We observe that the denominator is an approximation to $q - 1$, which allows us to use the formula $z' = z - (q-1)^{-1} (z^q - z)$ during the iteration. Supports aliasing between \code{rop} and \code{op}. */ void _qadic_teichmuller(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; if (len == 1) { _padic_teichmuller(rop, op, p, N); _fmpz_vec_zero(rop + 1, d - 1); } else if (N == 1) { _fmpz_vec_scalar_mod_fmpz(rop, op, len, p); _fmpz_vec_zero(rop + len, d - len); } else /* d, N >= 2 */ { slong *e, i, n; fmpz *pow, *u, *t, *w; fmpz_t inv, q, qm1; n = FLINT_CLOG2(N) + 1; e = flint_malloc(n * sizeof(slong)); for (e[i = 0] = N; e[i] > 1; i++) e[i + 1] = (e[i] + 1) / 2; w = _fmpz_vec_init(n + n + (2 * d - 1)); pow = w; u = w + n; t = w + 2 * n; fmpz_init(inv); fmpz_init(q); fmpz_init(qm1); fmpz_pow_ui(q, p, d); fmpz_sub_ui(qm1, q, 1); /* Compute powers of p */ { fmpz_one(t); fmpz_set(pow + i, p); } for (i--; i >= 1; i--) { if (e[i] & WORD(1)) { fmpz_mul(pow + i, t, pow + (i + 1)); fmpz_mul(t, t, t); } else { fmpz_mul(t, t, pow + (i + 1)); fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } } { if (e[i] & WORD(1)) fmpz_mul(pow + i, t, pow + (i + 1)); else fmpz_mul(pow + i, pow + (i + 1), pow + (i + 1)); } /* Compute reduced units for (q-1) */ { fmpz_mod(u + 0, qm1, pow + 0); } for (i = 1; i < n; i++) { fmpz_mod(u + i, u + (i - 1), pow + i); } /* Run Newton iteration */ i = n - 1; { _fmpz_vec_scalar_mod_fmpz(rop, op, len, pow + i); _fmpz_vec_zero(rop + len, d - len); fmpz_sub_ui(inv, p, 1); } for (i--; i >= 0; i--) { /* Lift rop */ _qadic_pow(t, rop, d, q, a, j, lena, pow + i); _fmpz_poly_sub(t, t, d, rop, d); _fmpz_vec_scalar_submul_fmpz(rop, t, d, inv); _fmpz_vec_scalar_mod_fmpz(rop, rop, d, pow + i); /* Lift inv */ if (i > 0) { fmpz_mul(t, inv, inv); fmpz_mul(t + 1, u + i, t); fmpz_mul_2exp(inv, inv, 1); fmpz_sub(inv, inv, t + 1); fmpz_mod(inv, inv, pow + i); } } _fmpz_vec_clear(w, n + n + (2 * d - 1)); fmpz_clear(inv); fmpz_clear(q); fmpz_clear(qm1); flint_free(e); } } void qadic_teichmuller(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = qadic_prec(rop); if (op->val < 0) { flint_throw(FLINT_ERROR, "Exception (qadic_teichmuller). val(op) is negative.\n"); } if (qadic_is_zero(op) || op->val > 0 || N <= 0) { qadic_zero(rop); } else { const slong d = qadic_ctx_degree(ctx); padic_poly_fit_length(rop, d); _qadic_teichmuller(rop->coeffs, op->coeffs, op->length, ctx->a, ctx->j, ctx->len, (&ctx->pctx)->p, N); rop->val = 0; _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); } } flint-3.1.3/src/qadic/test/000077500000000000000000000000001461254215100154625ustar00rootroot00000000000000flint-3.1.3/src/qadic/test/main.c000066400000000000000000000034121461254215100165520ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add.c" #include "t-exp_balanced.c" #include "t-exp.c" #include "t-exp_rectangular.c" #include "t-frobenius.c" #include "t-inv.c" #include "t-log_balanced.c" #include "t-log.c" #include "t-log_rectangular.c" #include "t-mul.c" #include "t-neg.c" #include "t-norm_analytic.c" #include "t-norm.c" #include "t-norm_resultant.c" #include "t-pow.c" #include "t-sqrt.c" #include "t-sub.c" #include "t-teichmuller.c" #include "t-trace.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(qadic_add), TEST_FUNCTION(qadic_exp_balanced), TEST_FUNCTION(qadic_exp), TEST_FUNCTION(qadic_exp_rectangular), TEST_FUNCTION(qadic_frobenius), TEST_FUNCTION(qadic_inv), TEST_FUNCTION(qadic_log_balanced), TEST_FUNCTION(qadic_log), TEST_FUNCTION(qadic_log_rectangular), TEST_FUNCTION(qadic_mul), TEST_FUNCTION(qadic_neg), TEST_FUNCTION(qadic_norm_analytic), TEST_FUNCTION(qadic_norm), TEST_FUNCTION(qadic_norm_resultant), TEST_FUNCTION(qadic_pow), TEST_FUNCTION(qadic_sqrt), TEST_FUNCTION(qadic_sub), TEST_FUNCTION(qadic_teichmuller), TEST_FUNCTION(qadic_trace) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/qadic/test/t-add.c000066400000000000000000000160601461254215100166220ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_add, state) { int i, result; /* Check aliasing: a = a + b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_add(c, a, b, ctx); qadic_add(a, a, b, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check aliasing: b = a + b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_add(c, a, b, ctx); qadic_add(b, a, b, ctx); result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check aliasing: a = a + a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_add(c, a, a, ctx); qadic_add(a, a, a, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check that a + b == b + a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c1, c2; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c1, N); qadic_init2(c2, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_add(c1, a, b, ctx); qadic_add(c2, b, a, ctx); result = (qadic_equal(c1, c2)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c1 = "), qadic_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), qadic_print_pretty(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c1); qadic_clear(c2); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check that (a + b) + c == a + (b + c) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c, lhs, rhs; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(lhs, N); qadic_init2(rhs, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_randtest(c, state, ctx); qadic_add(lhs, a, b, ctx); qadic_add(lhs, lhs, c, ctx); qadic_add(rhs, b, c, ctx); qadic_add(rhs, a, rhs, ctx); result = (qadic_equal(lhs, rhs)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("lhs = "), qadic_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), qadic_print_pretty(rhs, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("N = %wd\n", N); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-exp.c000066400000000000000000000076621461254215100166760ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_exp, state) { int i, result; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; int ans1, ans2; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_set(b, a, ctx); ans1 = qadic_exp(c, b, ctx); ans2 = qadic_exp(b, b, ctx); result = ((ans1 == ans2) && (!ans1 || qadic_equal(b, c))); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(d, N); qadic_init2(e, N); qadic_init2(f, N); qadic_init2(g, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_add(c, a, b, ctx); ans1 = qadic_exp(d, a, ctx); ans2 = qadic_exp(e, b, ctx); qadic_mul(f, d, e, ctx); ans3 = qadic_exp(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && qadic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), qadic_print_pretty(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), qadic_print_pretty(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(d); qadic_clear(e); qadic_clear(f); qadic_clear(g); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-exp_balanced.c000066400000000000000000000077501461254215100205050ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_exp_balanced, state) { int i, result; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; int ans1, ans2; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_set(b, a, ctx); ans1 = qadic_exp_balanced(c, b, ctx); ans2 = qadic_exp_balanced(b, b, ctx); result = ((ans1 == ans2) && (!ans1 || qadic_equal(b, c))); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(d, N); qadic_init2(e, N); qadic_init2(f, N); qadic_init2(g, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_add(c, a, b, ctx); ans1 = qadic_exp_balanced(d, a, ctx); ans2 = qadic_exp_balanced(e, b, ctx); qadic_mul(f, d, e, ctx); ans3 = qadic_exp_balanced(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && qadic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), qadic_print_pretty(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), qadic_print_pretty(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(d); qadic_clear(e); qadic_clear(f); qadic_clear(g); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-exp_rectangular.c000066400000000000000000000077721461254215100212670ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_exp_rectangular, state) { int i, result; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; int ans1, ans2; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_set(b, a, ctx); ans1 = qadic_exp_rectangular(c, b, ctx); ans2 = qadic_exp_rectangular(b, b, ctx); result = ((ans1 == ans2) && (!ans1 || qadic_equal(b, c))); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Functional equation: exp(a + b) == exp(a) exp(b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c, d, e, f, g; int ans1, ans2, ans3; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(d, N); qadic_init2(e, N); qadic_init2(f, N); qadic_init2(g, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_add(c, a, b, ctx); ans1 = qadic_exp_rectangular(d, a, ctx); ans2 = qadic_exp_rectangular(e, b, ctx); qadic_mul(f, d, e, ctx); ans3 = qadic_exp_rectangular(g, c, ctx); result = (!ans1 || !ans2 || (ans3 && qadic_equal(f, g))); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = a + b = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = exp(a) = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = exp(b) = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("f = exp(a) exp(b) = "), qadic_print_pretty(f, ctx), flint_printf("\n"); flint_printf("g = exp(a + b) = "), qadic_print_pretty(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(d); qadic_clear(e); qadic_clear(f); qadic_clear(g); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-frobenius.c000066400000000000000000000174021461254215100200670ustar00rootroot00000000000000/* Copyright (C) 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_frobenius, state) { int i, result; /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; slong e; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_set(b, a, ctx); e = n_randint(state, 10) % d; qadic_frobenius(c, b, e, ctx); qadic_frobenius(b, b, e, ctx); result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check sigma^e(x) == x^{p^e} mod p for integral values */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c, lhs, rhs; slong e; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(lhs, 1); qadic_init2(rhs, 1); qadic_randtest_int(a, state, ctx); e = n_randint(state, 10) % d; qadic_frobenius(b, a, e, ctx); { fmpz_t t; fmpz_init(t); fmpz_pow_ui(t, p, e); qadic_pow(c, a, t, ctx); fmpz_clear(t); } qadic_set(lhs, b, ctx); qadic_set(rhs, c, ctx); result = (qadic_equal(lhs, rhs)); if (!result) { flint_printf("FAIL (sigma^e(x) = x^{p^e} mod p):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("lhs = "), qadic_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), qadic_print_pretty(rhs, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check sigma^e(x + y) = sigma^e(x) + sigma^e(y) on Zq */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, s, s1, s2, lhs, rhs; slong e; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 10) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(s, N); qadic_init2(s1, N); qadic_init2(s2, N); qadic_init2(lhs, N); qadic_init2(rhs, N); qadic_randtest_int(a, state, ctx); qadic_randtest_int(b, state, ctx); e = n_randint(state, 10) % d; qadic_add(s, a, b, ctx); qadic_frobenius(lhs, s, e, ctx); qadic_frobenius(s1, a, e, ctx); qadic_frobenius(s2, b, e, ctx); qadic_add(rhs, s1, s2, ctx); result = (qadic_equal(lhs, rhs)); if (!result) { flint_printf("FAIL (sigma(a+b) = sigma(a) + sigma(b)):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("s = "), qadic_print_pretty(s, ctx), flint_printf("\n"); flint_printf("s1 = "), qadic_print_pretty(s1, ctx), flint_printf("\n"); flint_printf("s2 = "), qadic_print_pretty(s2, ctx), flint_printf("\n"); flint_printf("lhs = "), qadic_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), qadic_print_pretty(rhs, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(s); qadic_clear(s1); qadic_clear(s2); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check sigma^e(x * y) = sigma^e(x) * sigma^e(y) on Zq */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, s, s1, s2, lhs, rhs; slong e; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 10) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(s, N); qadic_init2(s1, N); qadic_init2(s2, N); qadic_init2(lhs, N); qadic_init2(rhs, N); qadic_randtest_int(a, state, ctx); qadic_randtest_int(b, state, ctx); e = n_randint(state, 10) % d; qadic_mul(s, a, b, ctx); qadic_frobenius(lhs, s, e, ctx); qadic_frobenius(s1, a, e, ctx); qadic_frobenius(s2, b, e, ctx); qadic_mul(rhs, s1, s2, ctx); result = (qadic_equal(lhs, rhs)); if (!result) { flint_printf("FAIL (sigma(a*b) = sigma(a) * sigma(b)):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("s = "), qadic_print_pretty(s, ctx), flint_printf("\n"); flint_printf("s1 = "), qadic_print_pretty(s1, ctx), flint_printf("\n"); flint_printf("s2 = "), qadic_print_pretty(s2, ctx), flint_printf("\n"); flint_printf("lhs = "), qadic_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), qadic_print_pretty(rhs, ctx), flint_printf("\n"); flint_printf("e = %wd\n", e); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(s); qadic_clear(s1); qadic_clear(s2); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-inv.c000066400000000000000000000054741461254215100166750ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_inv, state) { int i, result; /* Check aliasing: a = ~a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest_not_zero(a, state, ctx); qadic_set(b, a, ctx); qadic_inv(c, b, ctx); qadic_inv(b, b, ctx); result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check a * ~a == 1 for units */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); do qadic_randtest_val(a, state, 0, ctx); while (qadic_is_zero(a)); qadic_inv(b, a, ctx); qadic_mul(b, a, b, ctx); result = qadic_is_one(b); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-log.c000066400000000000000000000127501461254215100166550ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_log, state) { int i, result; /** p == 2 *******************************************************************/ /** p > 2 ********************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; slong ans1, ans2; qadic_ctx_t ctx; qadic_t a, b; fmpz_init_set_ui(p, n_randprime(state, 3 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_randtest_not_zero(a, state, ctx); if (a->val < 1) a->val = 1; padic_poly_reduce(a, &ctx->pctx); qadic_one(b); qadic_add(a, a, b, ctx); ans1 = qadic_log(b, a, ctx); ans2 = qadic_log(a, a, ctx); result = (ans1 == ans2) && (!ans1 || qadic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c, d, e, f, g; fmpz_init_set_ui(p, n_randprime(state, 3 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(d, N); qadic_init2(e, N); qadic_init2(f, N); qadic_init2(g, N); qadic_randtest_not_zero(a, state, ctx); if (a->val < 1) a->val = 1; padic_poly_reduce(a, &ctx->pctx); qadic_one(c); qadic_add(a, a, c, ctx); qadic_randtest_not_zero(b, state, ctx); if (b->val < 1) b->val = 1; padic_poly_reduce(b, &ctx->pctx); qadic_one(c); qadic_add(b, b, c, ctx); qadic_mul(c, a, b, ctx); qadic_log(d, a, ctx); qadic_log(e, b, ctx); qadic_add(f, d, e, ctx); qadic_log(g, c, ctx); result = (qadic_equal(f, g)); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), qadic_print_pretty(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), qadic_print_pretty(g, ctx), flint_printf("\n"); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(d); qadic_clear(e); qadic_clear(f); qadic_clear(g); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 3 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest_val(a, state, (*p == WORD(2)) + 1, ctx); qadic_exp(b, a, ctx); qadic_log(c, b, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = exp(a) = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = log(b) = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-log_balanced.c000066400000000000000000000130571461254215100204670ustar00rootroot00000000000000/* Copyright (C) 2011, 2012, 2013 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_log_balanced, state) { int i, result; /** p == 2 *******************************************************************/ /** p > 2 ********************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; slong ans1, ans2; qadic_ctx_t ctx; qadic_t a, b; fmpz_init_set_ui(p, n_randprime(state, 3 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_randtest_not_zero(a, state, ctx); if (a->val < 1) a->val = 1; padic_poly_reduce(a, &ctx->pctx); qadic_one(b); qadic_add(a, a, b, ctx); ans1 = qadic_log_balanced(b, a, ctx); ans2 = qadic_log_balanced(a, a, ctx); result = (ans1 == ans2) && (!ans1 || qadic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c, d, e, f, g; fmpz_init_set_ui(p, n_randprime(state, 3 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(d, N); qadic_init2(e, N); qadic_init2(f, N); qadic_init2(g, N); qadic_randtest_not_zero(a, state, ctx); if (a->val < 1) a->val = 1; padic_poly_reduce(a, &ctx->pctx); qadic_one(c); qadic_add(a, a, c, ctx); qadic_randtest_not_zero(b, state, ctx); if (b->val < 1) b->val = 1; padic_poly_reduce(b, &ctx->pctx); qadic_one(c); qadic_add(b, b, c, ctx); qadic_mul(c, a, b, ctx); qadic_log_balanced(d, a, ctx); qadic_log_balanced(e, b, ctx); qadic_add(f, d, e, ctx); qadic_log_balanced(g, c, ctx); result = (qadic_equal(f, g)); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), qadic_print_pretty(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), qadic_print_pretty(g, ctx), flint_printf("\n"); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(d); qadic_clear(e); qadic_clear(f); qadic_clear(g); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 3 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest_val(a, state, (*p == WORD(2)) + 1, ctx); qadic_exp(b, a, ctx); qadic_log_balanced(c, b, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = exp(a) = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = log(b) = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-log_rectangular.c000066400000000000000000000127771461254215100212550ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_log_rectangular, state) { int i, result; /** p == 2 *******************************************************************/ /** p > 2 ********************************************************************/ /* Check aliasing: a = log(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; slong ans1, ans2; qadic_ctx_t ctx; qadic_t a, b; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_randtest_not_zero(a, state, ctx); if (a->val < 1) a->val = 1; padic_poly_reduce(a, &ctx->pctx); qadic_one(b); qadic_add(a, a, b, ctx); ans1 = qadic_log_rectangular(b, a, ctx); ans2 = qadic_log_rectangular(a, a, ctx); result = (ans1 == ans2) && (!ans1 || qadic_equal(a, b)); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check: log(a) + log(b) == log(a * b) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c, d, e, f, g; fmpz_init_set_ui(p, n_randprime(state, 3 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(d, N); qadic_init2(e, N); qadic_init2(f, N); qadic_init2(g, N); qadic_randtest_not_zero(a, state, ctx); if (a->val < 1) a->val = 1; padic_poly_reduce(a, &ctx->pctx); qadic_one(c); qadic_add(a, a, c, ctx); qadic_randtest_not_zero(b, state, ctx); if (b->val < 1) b->val = 1; padic_poly_reduce(b, &ctx->pctx); qadic_one(c); qadic_add(b, b, c, ctx); qadic_mul(c, a, b, ctx); qadic_log_rectangular(d, a, ctx); qadic_log_rectangular(e, b, ctx); qadic_add(f, d, e, ctx); qadic_log_rectangular(g, c, ctx); result = (qadic_equal(f, g)); if (!result) { flint_printf("FAIL (functional equation):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = a * b = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = log(a) = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = log(b) = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("f = log(a) + log(b) = "), qadic_print_pretty(f, ctx), flint_printf("\n"); flint_printf("g = log(a * b) = "), qadic_print_pretty(g, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(d); qadic_clear(e); qadic_clear(f); qadic_clear(g); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check: log(exp(x)) == x */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); deg = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest_val(a, state, (*p == WORD(2)) + 1, ctx); qadic_exp(b, a, ctx); qadic_log_rectangular(c, b, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL (log(exp(x)) == x):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-mul.c000066400000000000000000000157251461254215100166760ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_mul, state) { int i, result; /* Check aliasing: a = a * b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_mul(c, a, b, ctx); qadic_mul(a, a, b, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check aliasing: b = a * b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_mul(c, a, b, ctx); qadic_mul(b, a, b, ctx); result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check aliasing: a = a + a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_add(c, a, a, ctx); qadic_add(a, a, a, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check that a * b == b * a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c1, c2; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c1, N); qadic_init2(c2, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_mul(c1, a, b, ctx); qadic_mul(c2, b, a, ctx); result = (qadic_equal(c1, c2)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c1 = "), qadic_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), qadic_print_pretty(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c1); qadic_clear(c2); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check that (a * b) * c == a * (b * c) for integral values */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c, lhs, rhs; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(lhs, N); qadic_init2(rhs, N); qadic_randtest_int(a, state, ctx); qadic_randtest_int(b, state, ctx); qadic_randtest_int(c, state, ctx); qadic_mul(lhs, a, b, ctx); qadic_mul(lhs, lhs, c, ctx); qadic_mul(rhs, b, c, ctx); qadic_mul(rhs, a, rhs, ctx); result = (qadic_equal(lhs, rhs)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("lhs = "), qadic_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), qadic_print_pretty(rhs, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-neg.c000066400000000000000000000061531461254215100166450ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_neg, state) { int i, result; /* Check aliasing: a = -a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_set(b, a, ctx); qadic_neg(c, b, ctx); qadic_neg(b, b, ctx); result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check a - b == a + (-b) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c1, c2; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c1, N); qadic_init2(c2, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_sub(c1, a, b, ctx); qadic_neg(c2, b, ctx); qadic_add(c2, a, c2, ctx); result = (qadic_equal(c1, c2)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c1 = "), qadic_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), qadic_print_pretty(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c1); qadic_clear(c2); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-norm.c000066400000000000000000000046501461254215100170470ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_norm, state) { int i, result; /* Compare with product of Galois conjugates */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; padic_t x, y; slong j; int ans; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); padic_init2(x, N); padic_init2(y, N); qadic_randtest_val(a, state, 0, ctx); qadic_reduce(a, ctx); qadic_norm(x, a, ctx); qadic_one(b); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); qadic_mul(b, b, c, ctx); } ans = qadic_get_padic(y, b, ctx); result = (ans && padic_equal(x, y)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = "), padic_print(x, &ctx->pctx), flint_printf("\n"); flint_printf("y = "), padic_print(y, &ctx->pctx), flint_printf("\n"); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); flint_printf("sigma^%wd = ", j), qadic_print_pretty(c, ctx), flint_printf("\n"); } flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-norm_analytic.c000066400000000000000000000050161461254215100207300ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_norm_analytic, state) { int i, result; /* Compare with product of Galois conjugates */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; padic_t x, y; slong j; int ans; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); padic_init2(x, N); padic_init2(y, N); qadic_randtest_val(a, state, fmpz_cmp_ui(p, 2) == 0 ? 2 : 1, ctx); qadic_reduce(a, ctx); qadic_one(b); qadic_add(a, a, b, ctx); qadic_norm_analytic(x, a, ctx); qadic_one(b); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); qadic_mul(b, b, c, ctx); } ans = qadic_get_padic(y, b, ctx); result = (ans && padic_equal(x, y)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = "), padic_print(x, &ctx->pctx), flint_printf("\n"); flint_printf("y = "), padic_print(y, &ctx->pctx), flint_printf("\n"); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); flint_printf("sigma^%wd = ", j), qadic_print_pretty(c, ctx), flint_printf("\n"); } flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-norm_resultant.c000066400000000000000000000046741461254215100211560ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_norm_resultant, state) { int i, result; /* Compare with product of Galois conjugates */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; padic_t x, y; slong j; int ans; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); padic_init2(x, N); padic_init2(y, N); qadic_randtest_val(a, state, 0, ctx); qadic_reduce(a, ctx); qadic_norm_resultant(x, a, ctx); qadic_one(b); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); qadic_mul(b, b, c, ctx); } ans = qadic_get_padic(y, b, ctx); result = (ans && padic_equal(x, y)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = "), padic_print(x, &ctx->pctx), flint_printf("\n"); flint_printf("y = "), padic_print(y, &ctx->pctx), flint_printf("\n"); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); flint_printf("sigma^%wd = ", j), qadic_print_pretty(c, ctx), flint_printf("\n"); } flint_printf("ans = %d\n", ans); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-pow.c000066400000000000000000000063471461254215100167060ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_pow, state) { int i, result; /* Check aliasing: a = a^e */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b; fmpz_t e; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); fmpz_init(e); qadic_randtest(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); qadic_pow(b, a, e, ctx); qadic_pow(a, a, e, ctx); result = (qadic_equal(a, b)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); fmpz_clear(e); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Compare with multiplication, for integral values */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_t e, f; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); fmpz_init(f); fmpz_init(e); qadic_randtest_int(a, state, ctx); fmpz_randtest_unsigned(e, state, 6); qadic_pow(b, a, e, ctx); qadic_one(c); for (fmpz_one(f); fmpz_cmp(f, e) <= 0; fmpz_add_ui(f, f, 1)) { qadic_mul(c, c, a, ctx); } result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL (cmp with mul):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("e = "), fmpz_print(e), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(e); fmpz_clear(f); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-sqrt.c000066400000000000000000000611071461254215100170650ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" int _artin_schreier_preimage(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena); TEST_FUNCTION_START(qadic_sqrt, state) { int i, result; /* PRIME p = 2 ***************************************************************/ /* Check Artin Schreier preimages */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong d; qadic_ctx_t ctx; int ans; qadic_t a, b, c; d = n_randint(state, 10) + 1; qadic_ctx_init_conway(ctx, p, d, 1, 1, "X", PADIC_SERIES); qadic_init2(a, 1); qadic_init2(b, 1); qadic_init2(c, 1); qadic_randtest_val(a, state, 0, ctx); padic_poly_fit_length(b, d); ans = _artin_schreier_preimage(b->coeffs, a->coeffs, a->length, ctx->a, ctx->j, ctx->len); b->val = 0; _padic_poly_set_length(b, d); _padic_poly_normalise(b); if (ans) { qadic_mul(c, b, b, ctx); qadic_add(c, c, b, ctx); result = qadic_equal(a, c); if (!result) { flint_printf("FAIL (Artin Schreier preimages):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_ctx_clear(ctx); } /* Check aliasing: a = sqrt(a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong d, N; qadic_ctx_t ctx; int ans1, ans2; qadic_t a, b, c; d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_set(c, a, ctx); ans1 = qadic_sqrt(b, a, ctx); ans2 = qadic_sqrt(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || qadic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans1,ans2 = %d,%d\n", ans1, ans2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_ctx_clear(ctx); } /* Test random squares over finite fields */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong deg, N; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, c, c2; deg = n_randint(state, 10) + 1; N = 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(c2, 0); qadic_randtest_val(b, state, 0, ctx); qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, a, ctx); ans2 = qadic_sqrt(c2, a, ctx); if (ans) { qadic_t d, e; qadic_init2(d, N + qadic_val(a)/2); qadic_init2(e, N + qadic_val(a)/2); qadic_mul(d, c, c, ctx); qadic_set(e, a, ctx); result = (qadic_equal(d, e)); if (!result) { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } result = (ans == ans2); if (!result) { flint_printf("FAIL (zero output precision, random squares over finite field)\n\n"); fflush(stdout); flint_abort(); } qadic_clear(d); qadic_clear(e); } /* there is no reason for that to work */ /*else { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); }*/ qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(c2); qadic_ctx_clear(ctx); } /* Test random elements over finite fields */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong d, N; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, b2; d = n_randint(state, 10) + 1; N = 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(b2, 0); qadic_randtest_val(a, state, 0, ctx); ans = qadic_sqrt(b, a, ctx); ans2 = qadic_sqrt(b2, a, ctx); result = (ans == ans2); if (!result) { flint_printf("FAIL (zero output precision, random elements):\n\n"); fflush(stdout); flint_abort(); } if (ans) { qadic_t c, d; qadic_init2(c, N + qadic_val(a)/2); qadic_init2(d, N + qadic_val(a)/2); qadic_mul(c, b, b, ctx); qadic_set(d, a, ctx); result = (qadic_equal(c, d)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); qadic_clear(b2); qadic_ctx_clear(ctx); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong deg, N, N2; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, c, c2; deg = n_randint(state, 10) + 1; /* N >= 3 */ N = n_randint(state, 50) + 3; N2 = FLINT_MAX(n_randint(state, N), 3); qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(c2, N2); qadic_randtest_val(b, state, 0, ctx); qadic_randtest_int(b, state, ctx); qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, a, ctx); ans2 = qadic_sqrt(c2, a, ctx); result = (ans == ans2); if (!result) { flint_printf("FAIL (output prec lower than input prec, random squares):\n\n"); fflush(stdout); flint_abort(); } if (ans) { qadic_t d, e, u, v, w; qadic_init2(d, N + qadic_val(a)/2); qadic_init2(e, N + qadic_val(a)/2); qadic_init2(u, N); qadic_init2(v, N + qadic_val(a)/2); qadic_init2(w, N + qadic_val(a)/2); qadic_mul(d, c, c, ctx); qadic_set(e, a, ctx); result = (qadic_equal(d, e)); if (!result) { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(d); qadic_clear(e); qadic_clear(u); qadic_clear(v); qadic_clear(w); } else { if (N - qadic_val(a) >= 3) { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(c2); qadic_ctx_clear(ctx); } /* Test random elements */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong d, N, N2; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, b2; d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; N2 = N - n_randint(state, 10); qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(b2, N2); qadic_randtest(a, state, ctx); ans = qadic_sqrt(b, a, ctx); ans2 = qadic_sqrt(b2, a, ctx); result = (ans == ans2); if (!result) { flint_printf("FAIL (output prec lower than input prec, random elements):\n\n"); fflush(stdout); flint_abort(); } if (ans) { qadic_t c, d; qadic_init2(c, N + qadic_val(a)/2); qadic_init2(d, N + qadic_val(a)/2); qadic_mul(c, b, b, ctx); qadic_set(d, a, ctx); result = (qadic_equal(c, d)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); qadic_clear(b2); qadic_ctx_clear(ctx); } /* PRIME p != 2 **************************************************************/ /* Check aliasing: a = sqrt(a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N, q; qadic_ctx_t ctx; int ans1, ans2; qadic_t a, b, c; q = 2; while (q == 2) q = n_randprime(state, 2 + n_randint(state, 3), 1); fmpz_init_set_ui(p, q); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_set(c, a, ctx); ans1 = qadic_sqrt(b, a, ctx); ans2 = qadic_sqrt(a, a, ctx); result = ((ans1 == ans2) && (!ans1 || qadic_equal(a, b))); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans1,ans2 = %d,%d\n", ans1, ans2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Test random squares over finite fields */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N, q; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, c, c2; q = 2; while (q == 2) q = n_randprime(state, 2 + n_randint(state, 3), 1); fmpz_init_set_ui(p, q); deg = n_randint(state, 10) + 1; N = 1; qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(c2, 0); qadic_randtest_val(b, state, 0, ctx); qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, a, ctx); ans2 = qadic_sqrt(c2, a, ctx); result = (ans == ans2); if (!result) { flint_printf("FAIL (output prec lower than input prec, random squares over finite field):\n\n"); fflush(stdout); flint_abort(); } if (ans) { qadic_t d, e; qadic_init2(d, N + qadic_val(a)/2); qadic_init2(e, N + qadic_val(a)/2); qadic_mul(d, c, c, ctx); qadic_set(e, a, ctx); result = (qadic_equal(d, e)); if (!result) { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(d); qadic_clear(e); } else { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(c2); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Test random elements over finite fields */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N, q; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, b2; q = 2; while (q == 2) q = n_randprime(state, 2 + n_randint(state, 3), 1); fmpz_init_set_ui(p, q); d = n_randint(state, 10) + 1; N = 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(b2, 0); qadic_randtest_val(a, state, 0, ctx); ans = qadic_sqrt(b, a, ctx); ans2 = qadic_sqrt(b2, a, ctx); result = (ans == ans2); if (!result) { flint_printf("FAIL (output prec lower than input prec, random elements over finite field):\n\n"); fflush(stdout); flint_abort(); } if (ans) { qadic_t c, d; qadic_init2(c, N + qadic_val(a)/2); qadic_init2(d, N + qadic_val(a)/2); qadic_mul(c, b, b, ctx); qadic_set(d, a, ctx); result = (qadic_equal(c, d)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); qadic_clear(b2); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong deg, N, N2, q; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, c, c2; q = 2; while (q == 2) q = n_randprime(state, 2 + n_randint(state, 3), 1); fmpz_init_set_ui(p, q); deg = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; N2 = N - n_randint(state, 10); qadic_ctx_init_conway(ctx, p, deg, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(c2, N2); qadic_randtest_val(b, state, 0, ctx); /* XXX */ qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, a, ctx); ans2 = qadic_sqrt(c2, a, ctx); result = (ans == ans2); if (!result) { flint_printf("FAIL (output prec lower than input prec, random squares):\n\n"); fflush(stdout); flint_abort(); } if (ans) { qadic_t d, e; qadic_init2(d, N + qadic_val(a)/2); qadic_init2(e, N + qadic_val(a)/2); qadic_mul(d, c, c, ctx); qadic_set(e, a, ctx); result = (qadic_equal(d, e)); if (!result) { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("e = "), qadic_print_pretty(e, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(d); qadic_clear(e); } else { flint_printf("FAIL (a = b^2, c = sqrt(a), d = c^2 == a):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(c2); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Test random elements */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N, N2, q; qadic_ctx_t ctx; int ans, ans2; qadic_t a, b, b2; q = 2; while (q == 2) q = n_randprime(state, 2 + n_randint(state, 3), 1); fmpz_init_set_ui(p, q); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; N2 = N - n_randint(state, 10); qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "X", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(b2, N2); qadic_randtest(a, state, ctx); ans = qadic_sqrt(b, a, ctx); ans2 = qadic_sqrt(b2, a, ctx); result = (ans == ans2); if (!result) { flint_printf("FAIL (output prec lower than input prec, random elements):\n\n"); fflush(stdout); flint_abort(); } if (ans) { qadic_t c, d; qadic_init2(c, N + qadic_val(a)/2); qadic_init2(d, N + qadic_val(a)/2); qadic_mul(c, b, b, ctx); qadic_set(d, a, ctx); result = (qadic_equal(c, d)); if (!result) { flint_printf("FAIL (random elements):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("d = "), qadic_print_pretty(d, ctx), flint_printf("\n"); flint_printf("ans = %d\n", ans); flint_printf("N = %wd\n", N); flint_printf("N + val(a)/2 = %wd\n", N + qadic_val(a)/2); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); qadic_clear(b2); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-sub.c000066400000000000000000000157341461254215100166720ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_sub, state) { int i, result; /* Check aliasing: a = a - b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_sub(c, a, b, ctx); qadic_sub(a, a, b, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check aliasing: b = a - b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_sub(c, a, b, ctx); qadic_sub(b, a, b, ctx); result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check aliasing: a = a - a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(c, N); qadic_randtest(a, state, ctx); qadic_sub(c, a, a, ctx); qadic_sub(a, a, a, ctx); result = (qadic_equal(a, c)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check that a - b == -(b - a) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c1, c2; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c1, N); qadic_init2(c2, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_sub(c1, a, b, ctx); qadic_sub(c2, b, a, ctx); qadic_neg(c2, c2, ctx); result = (qadic_equal(c1, c2)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c1 = "), qadic_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), qadic_print_pretty(c2, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c1); qadic_clear(c2); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check that (a - b) - c == a - (b + c) */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c, lhs, rhs; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_init2(lhs, N); qadic_init2(rhs, N); qadic_randtest(a, state, ctx); qadic_randtest(b, state, ctx); qadic_randtest(c, state, ctx); qadic_sub(lhs, a, b, ctx); qadic_sub(lhs, lhs, c, ctx); qadic_add(rhs, b, c, ctx); qadic_sub(rhs, a, rhs, ctx); result = (qadic_equal(lhs, rhs)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("lhs = "), qadic_print_pretty(lhs, ctx), flint_printf("\n"); flint_printf("rhs = "), qadic_print_pretty(rhs, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-teichmuller.c000066400000000000000000000062541461254215100204130ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_teichmuller, state) { int i, result; /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest_int(a, state, ctx); qadic_set(b, a, ctx); qadic_teichmuller(c, b, ctx); qadic_teichmuller(b, b, ctx); result = (qadic_equal(b, c)); if (!result) { flint_printf("FAIL (alias):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } /* Check x^q == x for units */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_t p, q; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = n_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0, N-10), FLINT_MAX(0, N+10), "a", PADIC_SERIES); fmpz_init(q); fmpz_pow_ui(q, p, d); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); qadic_randtest_val(a, state, 0, ctx); qadic_teichmuller(b, a, ctx); qadic_pow(c, b, q, ctx); result = (qadic_equal(c, b)); if (!result) { flint_printf("FAIL (x^q == x):\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("c = "), qadic_print_pretty(c, ctx), flint_printf("\n"); flint_printf("p = "), fmpz_print(p), flint_printf("\n"); flint_printf("d = %wd\n", d); flint_printf("N = %wd\n", N); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); fmpz_clear(q); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/test/t-trace.c000066400000000000000000000046441461254215100171750ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "long_extras.h" #include "qadic.h" TEST_FUNCTION_START(qadic_trace, state) { int i, result; /* Compare with sum of Galois conjugates */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p; slong d, N; qadic_ctx_t ctx; qadic_t a, b, c; padic_t x, y; slong j; int ans; fmpz_init_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; N = z_randint(state, 50) + 1; qadic_ctx_init_conway(ctx, p, d, FLINT_MAX(0,N-10), FLINT_MAX(0,N+10), "a", PADIC_SERIES); qadic_init2(a, N); qadic_init2(b, N); qadic_init2(c, N); padic_init2(x, N); padic_init2(y, N); qadic_randtest(a, state, ctx); qadic_trace(x, a, ctx); qadic_zero(b); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); qadic_add(b, b, c, ctx); } ans = qadic_get_padic(y, b, ctx); result = (ans && padic_equal(x, y)); if (!result) { flint_printf("FAIL:\n\n"); flint_printf("a = "), qadic_print_pretty(a, ctx), flint_printf("\n"); flint_printf("b = "), qadic_print_pretty(b, ctx), flint_printf("\n"); flint_printf("x = "), padic_print(x, &ctx->pctx), flint_printf("\n"); flint_printf("y = "), padic_print(y, &ctx->pctx), flint_printf("\n"); for (j = 0; j < d; j++) { qadic_frobenius(c, a, j, ctx); flint_printf("sigma^%wd = ", j), qadic_print_pretty(c, ctx), flint_printf("\n"); } flint_printf("ans = %d\n", ans); qadic_ctx_print(ctx); fflush(stdout); flint_abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qadic/trace.c000066400000000000000000000036521461254215100157530ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qadic.h" void _qadic_trace(fmpz_t rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t pN) { const slong d = j[lena - 1]; slong i, l; fmpz *t; t = _fmpz_vec_init(d); fmpz_set_ui(t + 0, d); for (i = 1; i < len; i++) /* simple Newton identities to */ /* compute power sums = traces of basis elements */ /* we don't need them past len */ { for (l = lena - 2; l >= 0 && j[l] >= d - (i - 1); l--) { fmpz_addmul(t + i, t + (j[l] + i - d), a + l); } if (l >= 0 && j[l] == d - i) { fmpz_addmul_ui(t + i, a + l, i); } fmpz_neg(t + i, t + i); fmpz_mod(t + i, t + i, pN); } fmpz_zero(rop); for (i = 0; i < len; i++) { fmpz_addmul(rop, op + i, t + i); } fmpz_mod(rop, rop, pN); _fmpz_vec_clear(t, d); } void qadic_trace(padic_t rop, const qadic_t op, const qadic_ctx_t ctx) { const slong N = padic_prec(rop); if (qadic_is_zero(op) || op->val >= N) { padic_zero(rop); } else { fmpz_t pN; int alloc; alloc = _padic_ctx_pow_ui(pN, N - op->val, &ctx->pctx); _qadic_trace(padic_unit(rop), op->coeffs, op->length, ctx->a, ctx->j, ctx->len, pN); padic_val(rop) = op->val; _padic_canonicalise(rop, &ctx->pctx); if (alloc) fmpz_clear(pN); } } flint-3.1.3/src/qfb.h000066400000000000000000000071231461254215100143460ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef QFB_H #define QFB_H #ifdef QFB_INLINES_C #define QFB_INLINE #else #define QFB_INLINE static inline #endif #include "fmpz.h" #ifdef __cplusplus extern "C" { #endif typedef struct qfb { fmpz_t a; fmpz_t b; fmpz_t c; } qfb; typedef qfb qfb_t[1]; typedef struct { qfb_t q; qfb_t q2; slong iter; } qfb_hash_t; QFB_INLINE void qfb_init(qfb_t q) { fmpz_init(q->a); fmpz_init(q->b); fmpz_init(q->c); } QFB_INLINE void qfb_clear(qfb_t q) { fmpz_clear(q->a); fmpz_clear(q->b); fmpz_clear(q->c); } QFB_INLINE int qfb_equal(qfb_t f, qfb_t g) { return (fmpz_equal(f->a, g->a) && fmpz_equal(f->b, g->b) && fmpz_equal(f->c, g->c)); } QFB_INLINE void qfb_set(qfb_t f, qfb_t g) { fmpz_set(f->a, g->a); fmpz_set(f->b, g->b); fmpz_set(f->c, g->c); } QFB_INLINE void qfb_discriminant(fmpz_t D, qfb_t f) { fmpz_t t; fmpz_init(t); fmpz_mul(t, f->a, f->c); fmpz_mul_2exp(t, t, 2); fmpz_mul(D, f->b, f->b); fmpz_sub(D, D, t); fmpz_clear(t); } void qfb_print(qfb_t q); QFB_INLINE void qfb_array_clear(qfb ** forms, slong num) { slong k; for (k = 0; k < num; k++) { fmpz_clear((*forms)[k].a); fmpz_clear((*forms)[k].b); fmpz_clear((*forms)[k].c); } flint_free(*forms); } qfb_hash_t * qfb_hash_init(slong depth); void qfb_hash_clear(qfb_hash_t * qhash, slong depth); void qfb_hash_insert(qfb_hash_t * qhash, qfb_t q, qfb_t q2, slong iter, slong depth); slong qfb_hash_find(qfb_hash_t * qhash, qfb_t q, slong depth); void qfb_reduce(qfb_t r, qfb_t f, fmpz_t D); int qfb_is_reduced(qfb_t r); slong qfb_reduced_forms(qfb ** forms, slong d); slong qfb_reduced_forms_large(qfb ** forms, slong d); void qfb_nucomp(qfb_t r, const qfb_t f, const qfb_t g, fmpz_t D, fmpz_t L); void qfb_nudupl(qfb_t r, const qfb_t f, fmpz_t D, fmpz_t L); void qfb_pow_ui(qfb_t r, qfb_t f, fmpz_t D, ulong exp); void qfb_pow(qfb_t r, qfb_t f, fmpz_t D, fmpz_t exp); void qfb_pow_with_root(qfb_t r, qfb_t f, fmpz_t D, fmpz_t e, fmpz_t L); QFB_INLINE void qfb_inverse(qfb_t r, qfb_t f) { qfb_set(r, f); if (fmpz_equal(f->a, f->c) || fmpz_equal(f->a, f->b)) return; fmpz_neg(r->b, r->b); } QFB_INLINE int qfb_is_principal_form(qfb_t f, fmpz_t D) { if (!fmpz_is_one(f->a)) return 0; if (fmpz_is_odd(D)) /* D = 1 mod 4 */ return fmpz_is_one(f->b); return fmpz_is_zero(f->b); /* D = 0 mod 4 */ } QFB_INLINE void qfb_principal_form(qfb_t f, fmpz_t D) { fmpz_set_ui(f->a, 1); if (fmpz_is_odd(D)) /* D = 1 mod 4 */ fmpz_set_ui(f->b, 1); else /* D = 0 mod 4 */ fmpz_set_ui(f->b, 0); fmpz_sub(f->c, f->b, D); fmpz_fdiv_q_2exp(f->c, f->c, 2); } QFB_INLINE int qfb_is_primitive(qfb_t f) { fmpz_t g; int res; fmpz_init(g); fmpz_gcd3(g, f->a, f->b, f->c); res = fmpz_is_pm1(g); fmpz_clear(g); return res; } void qfb_prime_form(qfb_t r, fmpz_t D, fmpz_t p); int qfb_exponent_element(fmpz_t exponent, qfb_t f, fmpz_t n, ulong B1, ulong B2_sqrt); int qfb_exponent(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt, slong c); int qfb_exponent_grh(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/qfb/000077500000000000000000000000001461254215100141725ustar00rootroot00000000000000flint-3.1.3/src/qfb/exponent.c000066400000000000000000000045511461254215100162030ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" int qfb_exponent(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt, slong c) { fmpz_t p, exp, n2; slong i; qfb_t f; ulong pr, nmodpr, s; int ret = 1; n_primes_t iter; n_primes_init(iter); fmpz_init(p); fmpz_init(n2); fmpz_init(exp); qfb_init(f); fmpz_set_ui(exponent, 1); /* find odd prime such that n is a square mod p */ pr = 0; for (i = 0; i < c + 2; ) { i--; do { pr = n_primes_next(iter); nmodpr = fmpz_fdiv_ui(n, pr); i++; } while ((pr == 2 && ((s = fmpz_fdiv_ui(n, 8)) == 2 || s == 3 || s == 5)) || (pr != 2 && nmodpr != 0 && n_jacobi(nmodpr, pr) < 0)); if (i < c + 2) { fmpz_set_ui(p, pr); /* find prime form of discriminant n */ qfb_prime_form(f, n, p); fmpz_set(n2, n); /* deal with non-fundamental discriminant */ if (nmodpr == 0 && fmpz_fdiv_ui(f->c, pr) == 0) { fmpz_fdiv_q_ui(f->a, f->a, pr); fmpz_fdiv_q_ui(f->b, f->b, pr); fmpz_fdiv_q_ui(f->c, f->c, pr); fmpz_fdiv_q_ui(n2, n2, pr*pr); } if (pr == 2 && fmpz_is_even(f->a) && fmpz_is_even(f->b) && fmpz_is_even(f->c)) { fmpz_fdiv_q_2exp(f->a, f->a, 1); fmpz_fdiv_q_2exp(f->b, f->b, 1); fmpz_fdiv_q_2exp(f->c, f->c, 1); fmpz_fdiv_q_2exp(n2, n2, 2); } qfb_reduce(f, f, n2); if (!fmpz_is_one(exponent)) qfb_pow(f, f, n2, exponent); if (!qfb_exponent_element(exp, f, n2, B1, B2_sqrt)) { ret = 0; goto cleanup; } if (fmpz_is_one(exp)) i++; else fmpz_mul(exponent, exponent, exp); } } cleanup: qfb_clear(f); fmpz_clear(p); fmpz_clear(n2); fmpz_clear(exp); n_primes_clear(iter); return ret; } flint-3.1.3/src/qfb/exponent_element.c000066400000000000000000000207051461254215100177130ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "qfb.h" /* find which power of the base is the exponent of f */ ulong find_power(qfb_t f, fmpz_t n, ulong base) { ulong s = 1; do { qfb_pow_ui(f, f, n, base); s *= base; } while (!qfb_is_principal_form(f, n)); return s; } ulong qfb_exponent_element_stage2(qfb_t f, fmpz_t n, ulong B2_sqrt) { qfb_t pow, pow2, f2; fmpz_t L, r; slong i, i2, ret = 0; slong depth = FLINT_BIT_COUNT(B2_sqrt) + 1; qfb_hash_t * qhash = qfb_hash_init(depth); fmpz_init(L); fmpz_init(r); fmpz_abs(L, n); fmpz_root(L, L, 4); qfb_init(f2); qfb_init(pow); qfb_init(pow2); qfb_hash_insert(qhash, f, NULL, 1, depth); qfb_nucomp(f2, f, f, n, L); /* large primes are odd */ qfb_reduce(f2, f2, n); qfb_set(pow, f); for (i = 1; i < B2_sqrt - 1; i += 2) /* baby steps */ { qfb_nucomp(pow, pow, f2, n, L); qfb_reduce(pow, pow, n); qfb_hash_insert(qhash, pow, NULL, i + 2, depth); } qfb_nucomp(pow, pow, f, n, L); /* compute f^B2_sqrt */ qfb_reduce(pow, pow, n); qfb_nucomp(pow, pow, pow, n, L); /* we hash for a form or its inverse, so we can jump by f^(2x B2_sqrt) */ qfb_reduce(pow, pow, n); qfb_set(pow2, pow); for(i = 2; i <= B2_sqrt; i += 2) /* giant steps */ { i2 = qfb_hash_find(qhash, pow2, depth); if (i2 != -1) /* found collision */ { fmpz_set_ui(r, B2_sqrt); fmpz_mul_ui(r, r, i); if (fmpz_sgn(qhash[i2].q->b) == fmpz_sgn(pow2->b)) fmpz_sub_ui(r, r, qhash[i2].iter); else fmpz_add_ui(r, r, qhash[i2].iter); ret = (fmpz_size(r) > 1 ? 0 : fmpz_get_ui(r)); /* we probably should be more aggressive here */ break; } qfb_nucomp(pow2, pow2, pow, n, L); qfb_reduce(pow2, pow2, n); } fmpz_clear(r); fmpz_clear(L); qfb_clear(f2); qfb_clear(pow); qfb_clear(pow2); qfb_hash_clear(qhash, depth); return ret; } typedef struct { ulong pr; qfb_t pow; slong i; } qfb_restart_t; #define go_restart \ do { \ need_restarts = 0; \ if (j == 0) \ { \ qfb_pow(f2, f2, n, exponent); \ goto do_restart1; \ } \ j--; \ qfb_set(pow, restart[j].pow); \ qfb_pow(pow, pow, n, exponent); \ i = restart[j].i; \ n_primes_jump_after(iter, restart[j].pr); \ pr = restart[j].pr; \ goto do_restart; \ } while (0) int qfb_exponent_element(fmpz_t exponent, qfb_t f, fmpz_t n, ulong B1, ulong B2_sqrt) { slong i, j, iters = 1024, restart_inc; qfb_t pow, oldpow, f2; ulong pr, oldpr, s2, sqrt, exp; fmpz_t prod, L, pow2; int ret = 1, num_restarts = 0, need_restarts = 1, clean2 = 0; qfb_restart_t restart[128]; n_primes_t iter; ulong hi, lo; double quot; mp_bitcnt_t bits0; n_primes_init(iter); sqrt = n_sqrt(B1); bits0 = FLINT_BIT_COUNT(B1); fmpz_set_ui(exponent, 1); qfb_init(f2); qfb_init(pow); qfb_init(oldpow); fmpz_init(pow2); fmpz_init(prod); fmpz_init(L); fmpz_abs(L, n); fmpz_root(L, L, 4); qfb_set(f2, f); do_restart1: if (qfb_is_principal_form(f2, n)) goto cleanup2; /* raise to appropriate power of 2 */ qfb_set(oldpow, f2); fmpz_set_ui(pow2, 2); fmpz_pow_ui(pow2, pow2, bits0); qfb_pow(pow, oldpow, n, pow2); if (qfb_is_principal_form(pow, n)) { ulong s = find_power(oldpow, n, 2); fmpz_mul_ui(exponent, exponent, s); goto cleanup2; } for (i = 0; i < 128; i++) qfb_init(restart[i].pow); clean2 = 1; n_prime_pi_bounds(&lo, &hi, B1); restart_inc = (((hi/1024 + 127)/128))*1024; quot = (double) B2_sqrt/(double) lo; pr = 2; n_primes_jump_after(iter, 2); i = 0; do_restart: /* keep raising iters by a factor of 2 until pr exceeds B1 or exponent found */ do { /* raise to prime powers until the identity is found */ for ( ; i < iters; ) { if ((i % restart_inc) == 0 && need_restarts) { qfb_set(restart[num_restarts].pow, pow); restart[num_restarts].i = i; restart[num_restarts].pr = pr; num_restarts++; } j = FLINT_MIN(i + 1024, iters); qfb_set(oldpow, pow); oldpr = pr; for ( ; i < j; i+=4) { pr = n_primes_next(iter); fmpz_set_ui(prod, pr); if (pr < sqrt) { exp = bits0/FLINT_BIT_COUNT(pr); fmpz_pow_ui(prod, prod, exp); } pr = n_primes_next(iter); if (pr < sqrt) { exp = bits0/FLINT_BIT_COUNT(pr); fmpz_set_ui(pow2, pr); fmpz_pow_ui(pow2, pow2, exp); fmpz_mul(prod, prod, pow2); } else fmpz_mul_ui(prod, prod, pr); pr = n_primes_next(iter); if (pr < sqrt) { exp = bits0/FLINT_BIT_COUNT(pr); fmpz_set_ui(pow2, pr); fmpz_pow_ui(pow2, pow2, exp); fmpz_mul(prod, prod, pow2); } else fmpz_mul_ui(prod, prod, pr); pr = n_primes_next(iter); if (pr < sqrt) { exp = bits0/FLINT_BIT_COUNT(pr); fmpz_set_ui(pow2, pr); fmpz_pow_ui(pow2, pow2, exp); fmpz_mul(prod, prod, pow2); } else fmpz_mul_ui(prod, prod, pr); qfb_pow_with_root(pow, pow, n, prod, L); } /* identity is found, compute exponent recursively */ if (qfb_is_principal_form(pow, n)) { qfb_set(pow, oldpow); n_primes_jump_after(iter, oldpr); pr = oldpr; while (1) { pr = n_primes_next(iter); if (pr < sqrt) { ulong k; exp = bits0/FLINT_BIT_COUNT(pr); for (k = 1; k <= exp; k++) { qfb_pow_ui(pow, pow, n, pr); if (qfb_is_principal_form(pow, n)) { fmpz_set_ui(pow2, pr); fmpz_pow_ui(pow2, pow2, k); fmpz_mul(exponent, exponent, pow2); for (j = 0; j < num_restarts; j++) { qfb_set(pow, restart[j].pow); qfb_pow(pow, pow, n, exponent); if (qfb_is_principal_form(pow, n)) break; } go_restart; } } } else { qfb_pow_ui(pow, pow, n, pr); if (qfb_is_principal_form(pow, n)) { fmpz_mul_ui(exponent, exponent, pr); for (j = 0; j < num_restarts; j++) { qfb_set(pow, restart[j].pow); qfb_pow(pow, pow, n, exponent); if (qfb_is_principal_form(pow, n)) break; } go_restart; } } } } } /* stage 2 */ s2 = qfb_exponent_element_stage2(pow, n, (ulong) ((double) iters * quot)); if (s2 && n_is_prime(s2)) /* we probably should be more aggressive here */ { fmpz_mul_ui(exponent, exponent, s2); for (j = 0; j < num_restarts; j++) { qfb_set(pow, restart[j].pow); qfb_pow(pow, pow, n, exponent); if (qfb_is_principal_form(pow, n)) break; } go_restart; } iters = FLINT_MIN(2*iters, hi); } while (pr <= B1); ret = 0; cleanup2: if (clean2) for (i = 0; i < 128; i++) qfb_clear(restart[i].pow); qfb_clear(f2); qfb_clear(pow); qfb_clear(oldpow); fmpz_clear(pow2); fmpz_clear(prod); fmpz_clear(L); n_primes_clear(iter); return ret; } flint-3.1.3/src/qfb/exponent_grh.c000066400000000000000000000052061461254215100170410ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "qfb.h" int qfb_exponent_grh(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt) { fmpz_t p, exp, n2; mpz_t mn; qfb_t f; ulong pr, nmodpr, s, grh_limit; mpfr_t lim; int ret = 1; n_primes_t iter; n_primes_init(iter); fmpz_init(p); fmpz_init(n2); fmpz_init(exp); qfb_init(f); flint_mpz_init_set_readonly(mn, n); mpfr_init_set_z(lim, mn, MPFR_RNDA); mpfr_abs(lim, lim, MPFR_RNDU); mpfr_log(lim, lim, MPFR_RNDU); mpfr_mul(lim, lim, lim, MPFR_RNDU); mpfr_mul_ui(lim, lim, 6, MPFR_RNDU); grh_limit = mpfr_get_ui(lim, MPFR_RNDU); fmpz_set_ui(exponent, 1); /* find odd prime such that n is a square mod p */ pr = 0; for (pr = 1; pr < grh_limit; ) { do { pr = n_primes_next(iter); nmodpr = fmpz_fdiv_ui(n, pr); } while ((pr == 2 && ((s = fmpz_fdiv_ui(n, 8)) == 2 || s == 3 || s == 5)) || (pr != 2 && nmodpr != 0 && n_jacobi(nmodpr, pr) < 0)); if (pr < grh_limit) { fmpz_set_ui(p, pr); /* find prime form of discriminant n */ qfb_prime_form(f, n, p); fmpz_set(n2, n); /* deal with non-fundamental discriminants */ if (nmodpr == 0 && fmpz_fdiv_ui(f->c, pr) == 0) { fmpz_fdiv_q_ui(f->a, f->a, pr); fmpz_fdiv_q_ui(f->b, f->b, pr); fmpz_fdiv_q_ui(f->c, f->c, pr); fmpz_fdiv_q_ui(n2, n2, pr*pr); } if (pr == 2 && fmpz_is_even(f->a) && fmpz_is_even(f->b) && fmpz_is_even(f->c)) { fmpz_fdiv_q_2exp(f->a, f->a, 1); fmpz_fdiv_q_2exp(f->b, f->b, 1); fmpz_fdiv_q_2exp(f->c, f->c, 1); fmpz_fdiv_q_2exp(n2, n2, 2); } qfb_reduce(f, f, n2); if (!fmpz_is_one(exponent)) qfb_pow(f, f, n2, exponent); if (!qfb_exponent_element(exp, f, n2, B1, B2_sqrt)) { ret = 0; goto cleanup; } if (!fmpz_is_one(exp)) fmpz_mul(exponent, exponent, exp); } } cleanup: qfb_clear(f); fmpz_clear(p); fmpz_clear(n2); fmpz_clear(exp); n_primes_clear(iter); mpfr_clear(lim); flint_mpz_clear_readonly(mn); return ret; } flint-3.1.3/src/qfb/hash_clear.c000066400000000000000000000011401461254215100164230ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qfb.h" void qfb_hash_clear(qfb_hash_t * qhash, slong depth) { slong i, size = (1L<. */ #include "fmpz.h" #include "qfb.h" slong qfb_hash_find(qfb_hash_t * qhash, qfb_t q, slong depth) { slong size = (1L<a, depth); i = fmpz_get_ui(r); while (!fmpz_is_zero(qhash[i].q->a)) { if (fmpz_cmp(qhash[i].q->a, q->a) == 0) { if (fmpz_cmpabs(qhash[i].q->b, q->b) == 0) { fmpz_clear(r); return i; } } i++; if (i == size) i = 0; } fmpz_clear(r); return -1; } flint-3.1.3/src/qfb/hash_init.c000066400000000000000000000012131461254215100163010ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qfb.h" qfb_hash_t * qfb_hash_init(slong depth) { slong i, size = (1L<. */ #include "fmpz.h" #include "qfb.h" void qfb_hash_insert(qfb_hash_t * qhash, qfb_t q, qfb_t q2, slong iter, slong depth) { slong size = (1L<a, depth); i = fmpz_get_ui(r); while (!fmpz_is_zero(qhash[i].q->a)) { i++; if (i == size) i = 0; } qfb_set(qhash[i].q, q); qhash[i].iter = iter; if (q2 != NULL) qfb_set(qhash[i].q2, q2); fmpz_clear(r); } flint-3.1.3/src/qfb/inlines.c000066400000000000000000000006421461254215100160010ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define QFB_INLINES_C #include "qfb.h" flint-3.1.3/src/qfb/io.c000066400000000000000000000012131461254215100147420ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "qfb.h" /* printing *******************************************************************/ void qfb_print(qfb_t q) { printf("("); fmpz_print(q->a); printf(", "); fmpz_print(q->b); printf(", "); fmpz_print(q->c); printf(")"); } flint-3.1.3/src/qfb/is_reduced.c000066400000000000000000000013231461254215100164430ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" int qfb_is_reduced(qfb_t r) { if (fmpz_cmp(r->c, r->a) < 0) return 0; if (fmpz_cmpabs(r->b, r->a) > 0) return 0; if (fmpz_cmpabs(r->a, r->b) == 0 || fmpz_cmp(r->a, r->c) == 0) if (fmpz_sgn(r->b) < 0) return 0; return 1; } flint-3.1.3/src/qfb/nucomp.c000066400000000000000000000073371461254215100156510ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart Copyright (C) 2020 Chia Network Inc This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qfb.h" /* This is based (with permission) on an implementation of NUCOMP by Michael Jacobson which is an adaption to binary quadratic forms of the algorithm presented in Appendix A of "Solving the Pell Equation", Michael Jacobson and High Williams, CMS Books in Mathematics, Springer 2009. */ void qfb_nucomp(qfb_t r, const qfb_t f, const qfb_t g, fmpz_t D, fmpz_t L) { fmpz_t a1, a2, c2, ca, cb, cc, k, s, sp, ss, m, t, u2, v1, v2; if (fmpz_cmp(f->a, g->a) > 0) { qfb_nucomp(r, g, f, D, L); return; } fmpz_init(a1); fmpz_init(a2); fmpz_init(c2); fmpz_init(ca); fmpz_init(cb); fmpz_init(cc); fmpz_init(k); fmpz_init(m); fmpz_init(s); fmpz_init(sp); fmpz_init(ss); fmpz_init(t); fmpz_init(u2); fmpz_init(v1); fmpz_init(v2); /* nucomp calculation */ fmpz_set(a1, f->a); fmpz_set(a2, g->a); fmpz_set(c2, g->c); fmpz_add(ss, f->b, g->b); fmpz_fdiv_q_2exp(ss, ss, 1); fmpz_sub(m, f->b, g->b); fmpz_fdiv_q_2exp(m, m, 1); fmpz_fdiv_r(t, a2, a1); if (fmpz_is_zero(t)) { fmpz_set_ui(v1, 0); fmpz_set(sp, a1); } else fmpz_gcdinv(sp, v1, t, a1); fmpz_mul(k, m, v1); fmpz_fdiv_r(k, k, a1); if (!fmpz_is_one(sp)) { fmpz_xgcd(s, v2, u2, ss, sp); fmpz_mul(k, k, u2); fmpz_mul(t, v2, c2); fmpz_sub(k, k, t); if (!fmpz_is_one(s)) { fmpz_divexact(a1, a1, s); fmpz_divexact(a2, a2, s); fmpz_mul(c2, c2, s); } fmpz_fdiv_r(k, k, a1); } if (fmpz_cmp(a1, L) < 0) { fmpz_mul(t, a2, k); fmpz_mul(ca, a2, a1); fmpz_mul_2exp(cb, t, 1); fmpz_add(cb, cb, g->b); fmpz_add(cc, g->b, t); fmpz_mul(cc, cc, k); fmpz_add(cc, cc, c2); fmpz_divexact(cc, cc, a1); } else { fmpz_t m1, m2, r1, r2, co1, co2, temp; fmpz_init(m1); fmpz_init(m2); fmpz_init(r1); fmpz_init(r2); fmpz_init(co1); fmpz_init(co2); fmpz_init(temp); fmpz_set(r2, a1); fmpz_set(r1, k); fmpz_xgcd_partial(co2, co1, r2, r1, L); fmpz_mul(t, a2, r1); fmpz_mul(m1, m, co1); fmpz_add(m1, m1, t); fmpz_divexact(m1, m1, a1); fmpz_mul(m2, ss, r1); fmpz_mul(temp, c2, co1); fmpz_sub(m2, m2, temp); fmpz_divexact(m2, m2, a1); fmpz_mul(ca, r1, m1); fmpz_mul(temp, co1, m2); if (fmpz_sgn(co1) < 0) fmpz_sub(ca, ca, temp); else fmpz_sub(ca, temp, ca); fmpz_mul(cb, ca, co2); fmpz_sub(cb, t, cb); fmpz_mul_2exp(cb, cb, 1); fmpz_divexact(cb, cb, co1); fmpz_sub(cb, cb, g->b); fmpz_mul_2exp(temp, ca, 1); fmpz_fdiv_r(cb, cb, temp); fmpz_mul(cc, cb, cb); fmpz_sub(cc, cc, D); fmpz_divexact(cc, cc, ca); fmpz_fdiv_q_2exp(cc, cc, 2); if (fmpz_sgn(ca) < 0) { fmpz_neg(ca, ca); fmpz_neg(cc, cc); } fmpz_clear(m1); fmpz_clear(m2); fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(co1); fmpz_clear(co2); fmpz_clear(temp); } fmpz_set(r->a, ca); fmpz_set(r->b, cb); fmpz_set(r->c, cc); fmpz_clear(ca); fmpz_clear(cb); fmpz_clear(cc); fmpz_clear(k); fmpz_clear(m); fmpz_clear(s); fmpz_clear(sp); fmpz_clear(ss); fmpz_clear(t); fmpz_clear(u2); fmpz_clear(v1); fmpz_clear(v2); fmpz_clear(a1); fmpz_clear(a2); fmpz_clear(c2); } flint-3.1.3/src/qfb/nudupl.c000066400000000000000000000062471461254215100156560ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart Copyright (C) 2020 Chia Network Inc This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" static void qfb_nudupl_gcdinv(fmpz_t d, fmpz_t a, fmpz_t t, const fmpz_t f, const fmpz_t g) { if (fmpz_cmp(f, g) < 0) fmpz_gcdinv(d, a, f, g); else { fmpz_fdiv_r(t, f, g); fmpz_gcdinv(d, a, t, g); } } void qfb_nudupl(qfb_t r, const qfb_t f, fmpz_t D, fmpz_t L) { fmpz_t a1, b1, c1, ca, cb, cc, k, s, t, u2, v1, v2; fmpz_init(a1); fmpz_init(b1); fmpz_init(c1); fmpz_init(ca); fmpz_init(cb); fmpz_init(cc); fmpz_init(k); fmpz_init(s); fmpz_init(t); fmpz_init(u2); fmpz_init(v1); fmpz_init(v2); /* nucomp calculation */ fmpz_set(a1, f->a); fmpz_set(c1, f->c); fmpz_zero(k); if (fmpz_cmpabs(b1, a1) == 0) { fmpz_set(s, a1); fmpz_zero(v2); } else if (fmpz_sgn(f->b) < 0) { fmpz_neg(b1, f->b); qfb_nudupl_gcdinv(s, v2, t, b1, a1); fmpz_neg(v2, v2); } else qfb_nudupl_gcdinv(s, v2, t, f->b, a1); fmpz_mul(t, v2, c1); fmpz_neg(k, t); if (!fmpz_is_one(s)) { fmpz_divexact(a1, a1, s); fmpz_mul(c1, c1, s); } fmpz_fdiv_r(k, k, a1); if (fmpz_cmp(a1, L) < 0) { fmpz_mul(t, a1, k); fmpz_mul(ca, a1, a1); fmpz_mul_2exp(cb, t, 1); fmpz_add(cb, cb, f->b); fmpz_add(cc, f->b, t); fmpz_mul(cc, cc, k); fmpz_add(cc, cc, c1); fmpz_divexact(cc, cc, a1); } else { fmpz_t m2, r1, r2, co1, co2, temp; fmpz_init(m2); fmpz_init(r1); fmpz_init(r2); fmpz_init(co1); fmpz_init(co2); fmpz_init(temp); fmpz_set(r2, a1); fmpz_set(r1, k); fmpz_xgcd_partial(co2, co1, r2, r1, L); fmpz_mul(t, a1, r1); fmpz_mul(m2, f->b, r1); fmpz_mul(temp, c1, co1); fmpz_sub(m2, m2, temp); fmpz_divexact(m2, m2, a1); fmpz_mul(ca, r1, r1); fmpz_mul(temp, co1, m2); if (fmpz_sgn(co1) < 0) fmpz_sub(ca, ca, temp); else fmpz_sub(ca, temp, ca); fmpz_mul(cb, ca, co2); fmpz_sub(cb, t, cb); fmpz_mul_2exp(cb, cb, 1); fmpz_divexact(cb, cb, co1); fmpz_sub(cb, cb, f->b); fmpz_mul_2exp(temp, ca, 1); fmpz_fdiv_r(cb, cb, temp); fmpz_mul(cc, cb, cb); fmpz_sub(cc, cc, D); fmpz_divexact(cc, cc, ca); fmpz_fdiv_q_2exp(cc, cc, 2); if (fmpz_sgn(ca) < 0) { fmpz_neg(ca, ca); fmpz_neg(cc, cc); } fmpz_clear(m2); fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(co1); fmpz_clear(co2); fmpz_clear(temp); } fmpz_set(r->a, ca); fmpz_set(r->b, cb); fmpz_set(r->c, cc); fmpz_clear(ca); fmpz_clear(cb); fmpz_clear(cc); fmpz_clear(k); fmpz_clear(s); fmpz_clear(t); fmpz_clear(u2); fmpz_clear(v2); fmpz_clear(a1); fmpz_clear(b1); fmpz_clear(c1); } flint-3.1.3/src/qfb/pow.c000066400000000000000000000041771461254215100151540ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" void qfb_pow(qfb_t r, qfb_t f, fmpz_t D, fmpz_t e) { fmpz_t L, exp; qfb_t pow; if (fmpz_is_zero(e)) { qfb_principal_form(r, D); return; } if (fmpz_is_one(e)) { qfb_set(r, f); return; } fmpz_init(L); fmpz_init(exp); fmpz_set(exp, e); fmpz_abs(L, D); fmpz_root(L, L, 4); qfb_init(pow); qfb_set(pow, f); while (fmpz_is_even(exp)) { qfb_nudupl(pow, pow, D, L); qfb_reduce(pow, pow, D); fmpz_fdiv_q_2exp(exp, exp, 1); } qfb_set(r, pow); fmpz_fdiv_q_2exp(exp, exp, 1); while (!fmpz_is_zero(exp)) { qfb_nudupl(pow, pow, D, L); qfb_reduce(pow, pow, D); if (fmpz_is_odd(exp)) { qfb_nucomp(r, r, pow, D, L); qfb_reduce(r, r, D); } fmpz_fdiv_q_2exp(exp, exp, 1); } qfb_clear(pow); fmpz_clear(L); fmpz_clear(exp); } void qfb_pow_with_root(qfb_t r, qfb_t f, fmpz_t D, fmpz_t e, fmpz_t L) { fmpz_t exp; qfb_t pow; if (fmpz_is_zero(e)) { qfb_principal_form(r, D); return; } if (fmpz_is_one(e)) { qfb_set(r, f); return; } fmpz_init(exp); fmpz_set(exp, e); qfb_init(pow); qfb_set(pow, f); while (fmpz_is_even(exp)) { qfb_nudupl(pow, pow, D, L); qfb_reduce(pow, pow, D); fmpz_fdiv_q_2exp(exp, exp, 1); } qfb_set(r, pow); fmpz_fdiv_q_2exp(exp, exp, 1); while (!fmpz_is_zero(exp)) { qfb_nudupl(pow, pow, D, L); qfb_reduce(pow, pow, D); if (fmpz_is_odd(exp)) { qfb_nucomp(r, r, pow, D, L); qfb_reduce(r, r, D); } fmpz_fdiv_q_2exp(exp, exp, 1); } qfb_clear(pow); fmpz_clear(exp); } flint-3.1.3/src/qfb/pow_ui.c000066400000000000000000000021631461254215100156420ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "qfb.h" void qfb_pow_ui(qfb_t r, qfb_t f, fmpz_t D, ulong exp) { fmpz_t L; qfb_t pow; if (exp == 0) { qfb_principal_form(r, D); return; } if (exp == 1) { qfb_set(r, f); return; } fmpz_init(L); fmpz_abs(L, D); fmpz_root(L, L, 4); qfb_init(pow); qfb_set(pow, f); while ((exp & 1) == 0) { qfb_nudupl(pow, pow, D, L); qfb_reduce(pow, pow, D); exp >>= 1; } qfb_set(r, pow); exp >>= 1; while (exp) { qfb_nudupl(pow, pow, D, L); qfb_reduce(pow, pow, D); if (exp & 1) { qfb_nucomp(r, r, pow, D, L); qfb_reduce(r, r, D); } exp >>= 1; } qfb_clear(pow); fmpz_clear(L); } flint-3.1.3/src/qfb/prime_form.c000066400000000000000000000043131461254215100164760ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" void qfb_prime_form(qfb_t r, fmpz_t D, fmpz_t p) { fmpz_t q, rem, s, t; fmpz_init(s); if (fmpz_cmp_ui(p, 2) == 0) /* special case, p = 2 */ { ulong m8 = fmpz_fdiv_ui(D, 8); if (m8 == 4) fmpz_set_ui(r->b, 2); else fmpz_set_ui(r->b, m8); fmpz_sub_ui(s, D, m8); fmpz_neg(s, s); fmpz_fdiv_q_2exp(r->c, s, 3); fmpz_set(r->a, p); fmpz_clear(s); return; } fmpz_init(t); fmpz_mod(t, D, p); if (fmpz_is_zero(t)) /* special case, p | D */ { fmpz_init(q); fmpz_init(rem); fmpz_fdiv_q(s, D, p); /* s = D/p */ if (fmpz_is_zero(s)) fmpz_set(t, s); else fmpz_sub(t, p, s); /* t = -s mod p */ while (fmpz_fdiv_ui(t, 4) != 0) /* ensure t is divisible by 4 */ fmpz_add(t, t, p); fmpz_add(t, t, s); /* t = first possible value for d/p + 4c */ fmpz_fdiv_q(t, t, p); fmpz_sqrtrem(q, rem, t); if (!fmpz_is_zero(rem)) /* t/p is not a square */ { if (fmpz_is_even(t)) /* b/p is even as t/p is */ fmpz_add_ui(q, q, 1 + fmpz_is_even(q)); else fmpz_add_ui(q, q, 1 + fmpz_is_odd(q)); } /* q = b/p */ fmpz_mul(r->b, q, p); fmpz_mul(q, q, q); fmpz_mul(q, q, p); fmpz_sub(q, q, s); fmpz_fdiv_q_2exp(r->c, q, 2); fmpz_set(r->a, p); fmpz_clear(q); fmpz_clear(rem); } else { fmpz_sqrtmod(t, t, p); fmpz_sub(s, D, t); if (fmpz_is_odd(s)) fmpz_sub(t, p, t); fmpz_set(r->a, p); fmpz_set(r->b, t); fmpz_mul(r->c, r->b, r->b); fmpz_sub(r->c, r->c, D); fmpz_divexact(r->c, r->c, r->a); fmpz_fdiv_q_2exp(r->c, r->c, 2); } fmpz_clear(s); fmpz_clear(t); } flint-3.1.3/src/qfb/profile/000077500000000000000000000000001461254215100156325ustar00rootroot00000000000000flint-3.1.3/src/qfb/profile/p-exponent_element_grh.c000066400000000000000000000027261461254215100224530ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" int main(int argc, char *argv[]) { slong exp, val, num, B1, B2, i; if (argc != 6) { printf("usage: %s exp val num B1 B2\n", argv[0]); printf("where D = -4*(10^exp + i) for i in [val..val + num)\n"); printf("with prime bound B1 and large prime bound B2\n"); return 1; } exp = atol(argv[1]); val = atol(argv[2]); num = atol(argv[3]); B1 = atol(argv[4]); B2 = atol(argv[5]); for (i = 0; i < num; i++) { fmpz_t D, exponent; fmpz_init(D); fmpz_init(exponent); fmpz_set_ui(D, 10); fmpz_pow_ui(D, D, exp); fmpz_add_ui(D, D, val + i); fmpz_mul_2exp(D, D, 2); fmpz_neg(D, D); if (qfb_exponent_grh(exponent, D, B1, B2)) { printf("Discriminant: "); fmpz_print(D); printf("\n"); printf("Exponent: "); fmpz_print(exponent); printf("\n\n"); } fmpz_clear(D); fmpz_clear(exponent); } _fmpz_cleanup(); return 0; } flint-3.1.3/src/qfb/profile/p-factor_qfb.c000066400000000000000000000133161461254215100203450ustar00rootroot00000000000000/* Copyright 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" int main(void) { fmpz_t g, n, n0, p, L; slong iters, i, j, depth, jmax = 10; qfb_t pow, twopow; ulong pr, nmodpr, mult; qfb_hash_t * qhash; int done; fmpz_init(g); fmpz_init(n); fmpz_init(n0); fmpz_init(p); fmpz_init(L); qfb_init(pow); qfb_init(twopow); printf("Enter number to be factored: "); fflush(stdout); if (!fmpz_read(n0)) { printf("Read failed\n"); abort(); } fmpz_neg(n0, n0); iters = 10; /* find prime such that n is a square mod p (or p divides n) */ if (fmpz_is_even(n0)) { printf("Factor: 2\n"); return 0; } mult = 1; while (1) /* keep increasing iterations for each multiplier until done */ { printf("iters = %ld, multipliers = %ld\n", iters, jmax); for (j = 0; j < jmax; j++) /* loop over jmax different multipliers */ { done = 1; if (mult != 1 && fmpz_fdiv_ui(n0, mult) == 0) { printf("Factor: %ld\n", mult); return 0; } fmpz_mul_ui(n, n0, mult); if (fmpz_fdiv_ui(n, 4) == 3) fmpz_mul_2exp(n, n, 2); pr = 2; fmpz_abs(L, n); fmpz_root(L, L, 4); do { pr = n_nextprime(pr, 0); while (mult % pr == 0) pr = n_nextprime(pr, 0); nmodpr = fmpz_fdiv_ui(n, pr); if (nmodpr == 0) /* pr is a factor */ { printf("Factor: %lu\n", pr); return 0; } } while (n_jacobi(nmodpr, pr) < 0); fmpz_set_ui(p, pr); /* find prime form of discriminant n */ qfb_prime_form(pow, n, p); /* raise to various powers of small primes */ qfb_pow_ui(pow, pow, n, 59049); /* 3^10 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 390625); /* 5^8 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 117649); /* 7^6 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 14641); /* 11^4 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 169); /* 13^2 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; depth = FLINT_BIT_COUNT(iters) + 1; qhash = qfb_hash_init(depth); pr = 13; for (i = 0; i < iters; i++) { pr = n_nextprime(pr, 0); qfb_pow_ui(pow, pow, n, pr*pr); qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) /* found factor */ break; qfb_hash_insert(qhash, twopow, pow, i, depth); } if (i == iters) /* stage 2 */ { ulong jump = iters*iters; slong iters2; for (i = 0; i < iters; i++) { qfb_pow_ui(pow, pow, n, jump); qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) /* found factor */ break; iters2 = qfb_hash_find(qhash, twopow, depth); if (iters2 != -1) /* found factor */ { if (fmpz_sgn(qhash[iters2].q->b) == fmpz_sgn(twopow->b)) qfb_inverse(qhash[iters2].q2, qhash[iters2].q2); qfb_nucomp(pow, pow, qhash[iters2].q2, n, L); qfb_reduce(pow, pow, n); break; } } if (i == iters) done = 0; } done: if (done) { for (i = 0; i < 12; i++) { qfb_pow_ui(twopow, pow, n, 2); if (qfb_is_principal_form(twopow, n)) { if (fmpz_cmpabs(pow->a, pow->b) != 0) { fmpz_abs(pow->b, pow->b); fmpz_sub(g, pow->b, pow->a); fmpz_sub(pow->a, g, pow->a); } fmpz_gcd(g, pow->a, n0); if (!fmpz_is_one(g)) /* Success! */ { printf("Factor: "); fmpz_print(g); printf("\n"); return 0; } done = 0; break; } qfb_set(pow, twopow); } } mult += 2; /* GCC really wants to complain about this one */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif qfb_hash_clear(qhash, depth); #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic pop #endif } iters *= 2; jmax = (slong) (jmax * 1.15); mult = iters/10; mult |= 1; } qfb_clear(pow); qfb_clear(twopow); fmpz_clear(g); fmpz_clear(n); fmpz_clear(n0); fmpz_clear(p); fmpz_clear(L); return 0; } flint-3.1.3/src/qfb/profile/p-factor_qfb_simple.c000066400000000000000000000067721461254215100217260ustar00rootroot00000000000000/* Copyright 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qfb.h" int main(void) { fmpz_t n, p; slong iters, i, j; qfb_t pow, oldpow, twopow; ulong pr, oldpr, nmodpr; int done = 1; fmpz_init(n); fmpz_init(p); qfb_init(pow); qfb_init(oldpow); qfb_init(twopow); printf("Enter number to be factored: "); fflush(stdout); if (!fmpz_read(n)) { printf("Read failed\n"); abort(); } fmpz_neg(n, n); printf("Enter a number of iterations: "); fflush(stdout); if (!scanf("%ld", &iters)) { printf("Read failed\n"); abort(); } /* find prime such that n is a square mod p (or p divides n) */ if (fmpz_is_even(n)) { printf("Factor: 2\n"); return 0; } pr = 2; if (fmpz_fdiv_ui(n, 4) == 3) { if (fmpz_fdiv_ui(n, 3) == 0) { printf("Factor: 3\n"); return 0; } fmpz_mul_ui(n, n, 3); pr = 3; } do { pr = n_nextprime(pr, 0); nmodpr = fmpz_fdiv_ui(n, pr); if (nmodpr == 0) /* pr is a factor */ { printf("Factor: %lu\n", pr); return 0; } } while (n_jacobi(nmodpr, pr) < 0); fmpz_set_ui(p, pr); /* find prime form of discriminant n */ qfb_prime_form(pow, n, p); /* raise to various powers of small primes */ qfb_pow_ui(pow, pow, n, 59049); /* 3^10 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 390625); /* 5^8 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 117649); /* 7^6 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 14641); /* 11^4 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; qfb_pow_ui(pow, pow, n, 169); /* 13^2 */ qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; pr = 13; for (i = 0; i < iters; ) { j = FLINT_MIN(i + 1024, iters); qfb_set(oldpow, pow); oldpr = pr; for ( ; i < j; i++) { pr = n_nextprime(pr, 0); qfb_pow_ui(pow, pow, n, pr*pr); } qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) { qfb_set(pow, oldpow); pr = oldpr; while (1) { pr = n_nextprime(pr, 0); qfb_pow_ui(pow, pow, n, pr*pr); qfb_pow_ui(twopow, pow, n, 4096); if (qfb_is_principal_form(twopow, n)) goto done; } } } if (i == iters) done = 0; done: if (done) { for (i = 0; i < 12; i++) { qfb_pow_ui(twopow, pow, n, 2); if (qfb_is_principal_form(twopow, n)) { qfb_print(pow); printf("\n"); return 0; } qfb_set(pow, twopow); } } else printf("Failed\n"); qfb_clear(pow); qfb_clear(oldpow); qfb_clear(twopow); fmpz_clear(n); fmpz_clear(p); return 0; } flint-3.1.3/src/qfb/reduce.c000066400000000000000000000022571461254215100156130ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qfb.h" void qfb_reduce(qfb_t r, qfb_t f, fmpz_t D) { int done = 0; fmpz_t t; qfb_set(r, f); fmpz_init(t); while(!done) { done = 1; if (fmpz_cmp(r->c, r->a) < 0) { fmpz_swap(r->a, r->c); fmpz_neg(r->b, r->b); done = 0; } if (fmpz_cmpabs(r->b, r->a) > 0) { fmpz_add(t, r->a, r->a); fmpz_fdiv_r(r->b, r->b, t); if (fmpz_cmp(r->b, r->a) > 0) fmpz_sub(r->b, r->b, t); fmpz_add(t, t, t); fmpz_mul(r->c, r->b, r->b); fmpz_sub(r->c, r->c, D); fmpz_divexact(r->c, r->c, t); done = 0; } } if (fmpz_cmpabs(r->a, r->b) == 0 || fmpz_cmp(r->a, r->c) == 0) if (fmpz_sgn(r->b) < 0) fmpz_neg(r->b, r->b); fmpz_clear(t); } flint-3.1.3/src/qfb/reduced_forms.c000066400000000000000000000212531461254215100171620ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "qfb.h" /* Iterate through all factors of a number given factorisation into n prime powers whose maximum values are stored in exp, storing the values at the current iteration in pows. */ int pow_incr(int * pows, int * exp, int n) { int i; for (i = 0; i < n; i++) { pows[i]++; if (pows[i] > exp[i]) pows[i] = 0; else return 1; } return 0; } slong qfb_reduced_forms_large(qfb ** forms, slong d) { slong a, j, k, p, alim, alloc, num, roots, sqrt, i, prod, prime_i; mp_srcptr primes; const double * prime_inverses; mp_limb_t a2; n_factor_t * fac; if (d >= 0) flint_throw(FLINT_ERROR, "%s not implemented for positive discriminant\n", __func__); alim = n_sqrt(-d/3); /* maximum a value to check */ (*forms) = NULL; alloc = 0; if ((-d & 3) == 2 || (-d & 3) == 1) /* ensure d is 0, 1 mod 4 */ return 0; fac = flint_calloc(alim + 1, sizeof(n_factor_t)); for (a = 2; a <= alim; a += 2) /* find powers of 2 dividing 4a values */ { a2 = a; fac[a].exp[0] = n_remove(&a2, 2) + 2; fac[a].p[0] = 2; fac[a].num = 1; } for (a = 1; a <= alim; a += 2) { fac[a].exp[0] = 2; fac[a].p[0] = 2; fac[a].num = 1; } sqrt = n_sqrt(alim); primes = n_primes_arr_readonly(FLINT_MAX(sqrt, 10000)); prime_inverses = n_prime_inverses_arr_readonly(FLINT_MAX(sqrt, 10000)); prime_i = 1; while ((p = primes[prime_i]) <= sqrt) /* sieve for factors of 4a values */ { for (a = p; a <= alim; a+= p) { a2 = a; num = fac[a].num; fac[a].exp[num] = n_remove2_precomp(&a2, p, prime_inverses[prime_i]); fac[a].p[num] = p; fac[a].num++; } prime_i++; } for (a = 1; a <= alim; a++) /* write any remaining prime factor of each 4a value */ { prod = 1; for (i = 0; i < fac[a].num; i++) prod *= n_pow(fac[a].p[i], fac[a].exp[i]); p = (4*a)/prod; if (p != 1) { num = fac[a].num; fac[a].exp[num] = 1; fac[a].p[num] = p; fac[a].num++; } } num = 0; for (a = 1; a <= alim; a++) /* loop through possible a's */ { mp_limb_t * s; roots = n_sqrtmodn(&s, n_negmod((-d)%(4*a), 4*a), fac + a); for (j = 0; j < roots; j++) /* loop through all square roots of d mod 4a */ { mp_limb_signed_t b = s[j]; if (b > 2*a) b -= 4*a; if (-a < b && b <= a) /* we may have a form */ { /* let B = FLINT_BITS -sqrt(2^(B-1)/3) < b < sqrt(2^(B-1)/3) 0 < -d < 2^(B-1) */ mp_limb_t c = ((mp_limb_t) (b*b) + (mp_limb_t) (-d))/(4*(mp_limb_t) a); if (c >= (mp_limb_t) a && (b >= 0 || a != c)) /* we have a form */ { mp_limb_t g; if (b) { g = n_gcd(c, FLINT_ABS(b)); g = n_gcd(a, g); } else g = n_gcd(c, a); if (g == 1) /* we have a primitive form */ { if (num == alloc) /* realloc if necessary */ { (*forms) = flint_realloc(*forms, (alloc + FLINT_MIN(alim, 100))*sizeof(qfb)); alloc += FLINT_MIN(alim, 100); for (k = num; k < alloc; k++) qfb_init((*forms) + k); } fmpz_set_si((*forms)[num].a, a); /* record form */ fmpz_set_si((*forms)[num].b, b); fmpz_set_si((*forms)[num++].c, c); } } } } flint_free(s); } flint_free(fac); return num; } slong qfb_reduced_forms(qfb ** forms, slong d) { slong a, b, k, c, p, blim, alloc, num, sqrt, i, prod, prime_i; mp_srcptr primes; const double * prime_inverses; mp_limb_t b2, exp, primes_cutoff = 0; n_factor_t * fac; mp_limb_t * s; if (d >= 0) flint_throw(FLINT_ERROR, "%s not implemented for positive discriminant\n", __func__); blim = n_sqrt(-d/3); /* maximum a value to check */ (*forms) = NULL; alloc = 0; if ((-d & 3) == 2 || (-d & 3) == 1) /* ensure d is 0, 1 mod 4 */ return 0; sqrt = n_sqrt(blim*blim - d); n_nth_prime_bounds(&primes_cutoff, &primes_cutoff, sqrt); if (primes_cutoff > FLINT_PRIMES_SMALL_CUTOFF*FLINT_PRIMES_SMALL_CUTOFF) return qfb_reduced_forms_large(forms, d); primes = n_primes_arr_readonly(FLINT_MAX(sqrt, 10000)); prime_inverses = n_prime_inverses_arr_readonly(FLINT_MAX(sqrt, 10000)); fac = flint_calloc(blim + 1, sizeof(n_factor_t)); prime_i = 1; while ((p = primes[prime_i]) <= sqrt) /* sieve for factors of p^exp */ { num = n_sqrtmod_primepow(&s, n_negmod((-d) % p, p), p, 1); for (i = 0; i < num; i++) /* sieve with each sqrt mod p */ { mp_limb_t off = s[i]; while (off <= blim) { b2 = (off*off - (mp_limb_t) d)/4; fac[off].p[fac[off].num] = p; fac[off].exp[fac[off].num] = n_remove2_precomp(&b2, p, prime_inverses[prime_i]); fac[off].num++; off += p; } } prime_i++; flint_free(s); } for (b = (d & 1); b <= blim; b += 2) /* write any remaining factors, including 2^exp */ { b2 = ((mp_limb_t)(b*b - d))/4; exp = flint_ctz(b2); /* powers of 2 */ if (exp) { fac[b].p[fac[b].num] = 2; fac[b].exp[fac[b].num] = exp; fac[b].num++; } prod = 1; for (i = 0; i < fac[b].num; i++) prod *= n_pow(fac[b].p[i], fac[b].exp[i]); b2 /= prod; if (b2 != 1) { fac[b].p[fac[b].num] = b2; fac[b].exp[fac[b].num] = 1; fac[b].num++; } } num = 0; for (b = (d & 1); b <= blim; b += 2) /* compute forms for each b */ { int pows[FLINT_MAX_FACTORS_IN_LIMB]; int n = fac[b].num; b2 = ((mp_limb_t)(b*b - d))/4; for (i = 0; i < n; i++) pows[i] = 0; do { a = 1; for (i = 0; i < n; i++) a *= n_pow(fac[b].p[i], pows[i]); c = b2 / a; if (a <= c && b <= a) /* we have a form */ { mp_limb_t g; if (b) { g = n_gcd(c, b); g = n_gcd(a, g); } else g = n_gcd(c, a); if (g == 1) /* primitive form */ { if (num == alloc) /* realloc if necessary */ { (*forms) = flint_realloc(*forms, (alloc + FLINT_MIN(blim, 100))*sizeof(qfb)); alloc += FLINT_MIN(blim, 100); for (k = num; k < alloc; k++) qfb_init((*forms) + k); } fmpz_set_si((*forms)[num].a, a); /* record form */ fmpz_set_si((*forms)[num].b, b); fmpz_set_si((*forms)[num++].c, c); if (b && a != c && b != a) { if (num == alloc) /* realloc if necessary */ { (*forms) = flint_realloc(*forms, (alloc + FLINT_MIN(blim, 100))*sizeof(qfb)); alloc += FLINT_MIN(blim, 100); for (k = num; k < alloc; k++) qfb_init((*forms) + k); } fmpz_set_si((*forms)[num].a, a); /* record opposite form */ fmpz_set_si((*forms)[num].b, -b); fmpz_set_si((*forms)[num++].c, c); } } } } while (pow_incr(pows, fac[b].exp, n)); } flint_free(fac); return num; } flint-3.1.3/src/qfb/test/000077500000000000000000000000001461254215100151515ustar00rootroot00000000000000flint-3.1.3/src/qfb/test/main.c000066400000000000000000000025021461254215100162400ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-exponent.c" #include "t-exponent_element.c" #include "t-exponent_grh.c" #include "t-inverse.c" #include "t-nucomp.c" #include "t-nudupl.c" #include "t-pow.c" #include "t-pow_ui.c" #include "t-prime_form.c" #include "t-reduce.c" #include "t-reduced_forms.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(qfb_exponent), TEST_FUNCTION(qfb_exponent_element), TEST_FUNCTION(qfb_exponent_grh), TEST_FUNCTION(qfb_inverse), TEST_FUNCTION(qfb_nucomp), TEST_FUNCTION(qfb_nudupl), TEST_FUNCTION(qfb_pow), TEST_FUNCTION(qfb_pow_ui), TEST_FUNCTION(qfb_prime_form), TEST_FUNCTION(qfb_reduce), TEST_FUNCTION(qfb_reduced_forms) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/qfb/test/t-exponent.c000066400000000000000000000044431461254215100174230ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_exponent, state) { int result; qfb * forms; slong i, k, i1, d, num; /* Check exponent divides class number */ for (i = 1; i < 1000; i++) { fmpz_t D, exp; qfb_t pow; slong e; d = n_randint(state, 100000) + 1; num = qfb_reduced_forms(&forms, -d); if (num) { fmpz_init(D); fmpz_init(exp); qfb_init(pow); fmpz_set_si(D, -d); result = qfb_exponent(exp, D, 1000000, 100000, 20); if (!result) { printf("FAIL:\n"); printf("Exponent not computed\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); flint_abort(); } e = fmpz_get_si(exp); result = ((num % e) == 0); if (!result) { printf("FAIL:\n"); printf("Exponent does not divide class number\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); flint_printf("%wd does not divide %wd\n", e, num); flint_abort(); } for (k = 0; k < 5; k++) { i1 = n_randint(state, num); qfb_pow_ui(pow, forms + i1, D, e); result = (qfb_is_principal_form(pow, D)); if (!result) { printf("FAIL:\n"); printf("Exponent does not annihilate form\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); printf("Form: "); qfb_print(forms + i1); printf("\n"); flint_printf("Exponent: %wd\n", e); flint_abort(); } } qfb_clear(pow); fmpz_clear(D); fmpz_clear(exp); } qfb_array_clear(&forms, num); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-exponent_element.c000066400000000000000000000050651461254215100211350ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_exponent_element, state) { int result; qfb * forms; slong i, k, i1, d, num; /* Check correct exponent is returned */ for (i = 1; i < 500; i++) { qfb_t r, pow; fmpz_t root, D, exp1, exp2; d = n_randint(state, 100000); num = qfb_reduced_forms(&forms, -d); if (num) { fmpz_init(D); fmpz_init(exp1); fmpz_init(exp2); fmpz_init(root); qfb_init(r); qfb_init(pow); fmpz_set_ui(root, d); fmpz_root(root, root, 4); for (k = 0; k < 3; k++) { i1 = n_randint(state, num); fmpz_set_si(D, -d); fmpz_set_ui(exp1, 1); qfb_set(pow, forms + i1); while (!qfb_is_principal_form(pow, D)) { qfb_nucomp(pow, pow, forms + i1, D, root); qfb_reduce(pow, pow, D); fmpz_add_ui(exp1, exp1, 1); } result = qfb_exponent_element(exp2, forms + i1, D, 1000000, 100000); if (!result) { printf("FAIL:\n"); printf("Exponent not found\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); printf("Form: "); qfb_print(forms + i1); printf("\n"); flint_abort(); } result = (fmpz_cmp(exp1, exp2) == 0); if (!result) { printf("FAIL:\n"); printf("Incorrect exponent\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); printf("Form: "); qfb_print(forms + i1); printf("\n"); printf("Exponent "); fmpz_print(exp2); printf(" should be "); fmpz_print(exp1); printf("\n"); flint_abort(); } } fmpz_clear(root); fmpz_clear(D); fmpz_clear(exp1); fmpz_clear(exp2); qfb_clear(r); } qfb_array_clear(&forms, num); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-exponent_grh.c000066400000000000000000000044471461254215100202670ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_exponent_grh, state) { int result; qfb * forms; slong i, k, i1, d, num; /* Check exponent divides class number */ for (i = 1; i < 1000; i++) { fmpz_t D, exp; qfb_t pow; slong e; d = n_randint(state, 100000) + 1; num = qfb_reduced_forms(&forms, -d); if (num) { fmpz_init(D); fmpz_init(exp); qfb_init(pow); fmpz_set_si(D, -d); result = qfb_exponent_grh(exp, D, 1000000, 100000); if (!result) { printf("FAIL:\n"); printf("Exponent not computed\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); flint_abort(); } e = fmpz_get_si(exp); result = ((num % e) == 0); if (!result) { printf("FAIL:\n"); printf("Exponent does not divide class number\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); flint_printf("%wd does not divide %wd\n", e, num); flint_abort(); } for (k = 0; k < 5; k++) { i1 = n_randint(state, num); qfb_pow_ui(pow, forms + i1, D, e); result = (qfb_is_principal_form(pow, D)); if (!result) { printf("FAIL:\n"); printf("Exponent does not annihilate form\n"); printf("Discriminant: "); fmpz_print(D); printf("\n"); printf("Form: "); qfb_print(forms + i1); printf("\n"); flint_printf("Exponent: %wd\n", e); flint_abort(); } } qfb_clear(pow); fmpz_clear(D); fmpz_clear(exp); } qfb_array_clear(&forms, num); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-inverse.c000066400000000000000000000030051461254215100172270ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_inverse, state) { int result; slong i; for (i = 1; i < 100000; i++) { fmpz_t D, L; qfb_t r, s, t; fmpz_init(D); fmpz_init(L); qfb_init(r); qfb_init(s); qfb_init(t); do { fmpz_randtest_unsigned(r->a, state, 100); if (fmpz_is_zero(r->a)) fmpz_set_ui(r->a, 1); fmpz_randtest(r->b, state, 100); fmpz_randtest(r->c, state, 100); qfb_discriminant(D, r); } while (fmpz_sgn(D) >= 0); qfb_reduce(r, r, D); qfb_inverse(s, r); fmpz_abs(L, D); fmpz_root(L, L, 4); qfb_nucomp(t, r, s, D, L); qfb_reduce(t, t, D); result = (qfb_is_principal_form(t, D)); if (!result) { printf("FAIL:\n"); qfb_print(r); printf("\n"); qfb_print(s); printf("\n"); flint_abort(); } fmpz_clear(D); fmpz_clear(L); qfb_clear(r); qfb_clear(s); qfb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-nucomp.c000066400000000000000000000062551461254215100170670ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_nucomp, state) { int result; qfb * forms; slong i, k, i1, i2, i3, num; /* Check discriminants of composed forms are correct */ for (i = 1; i < 10000; i++) { qfb_t r; fmpz_t root, D; num = qfb_reduced_forms(&forms, -i); if (num) { fmpz_init(root); fmpz_init(D); qfb_init(r); fmpz_set_ui(root, i); fmpz_root(root, root, 4); for (k = 0; k < 20; k++) { i1 = n_randint(state, num); i2 = n_randint(state, num); fmpz_set_si(D, -i); qfb_nucomp(r, forms + i1, forms + i2, D, root); qfb_discriminant(D, r); result = (fmpz_cmp_si(D, -i) == 0); if (!result) { printf("FAIL:\n"); printf("Incorrect discriminant\n"); fmpz_print(D); flint_printf(" should be %wd\n", -i); flint_abort(); } } fmpz_clear(D); fmpz_clear(root); qfb_clear(r); } qfb_array_clear(&forms, num); } /* Associativity test (Q1 o Q2) o Q3 == Q1 o (Q2 o Q3) */ for (i = 1; i < 10000; i++) { qfb_t r, s; fmpz_t root, t1, t2, D; num = qfb_reduced_forms(&forms, -i); if (num) { fmpz_init(root); fmpz_init(t1); fmpz_init(t2); fmpz_init(D); qfb_init(r); qfb_init(s); fmpz_set_si(D, -i); fmpz_set_ui(root, i); fmpz_root(root, root, 4); for (k = 0; k < 20; k++) { i1 = n_randint(state, num); i2 = n_randint(state, num); i3 = n_randint(state, num); qfb_nucomp(r, forms + i1, forms + i2, D, root); qfb_reduce(r, r, D); qfb_nucomp(r, r, forms + i3, D, root); qfb_reduce(r, r, D); qfb_nucomp(s, forms + i2, forms + i3, D, root); qfb_reduce(s, s, D); qfb_nucomp(s, forms + i1, s, D, root); qfb_reduce(s, s, D); result = (qfb_equal(r, s)); if (!result) { printf("FAIL:\n"); printf("Associativity fails\n"); printf("r = "); qfb_print(r); printf("\n"); printf("s = "); qfb_print(s); printf("\n"); flint_abort(); } } fmpz_clear(t1); fmpz_clear(t2); fmpz_clear(D); fmpz_clear(root); qfb_clear(r); qfb_clear(s); } qfb_array_clear(&forms, num); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-nudupl.c000066400000000000000000000033211461254215100170640ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_nudupl, state) { int result; qfb * forms; slong i, k, i1, num; for (i = 1; i < 10000; i++) { qfb_t r, s; fmpz_t root, D; num = qfb_reduced_forms(&forms, -i); if (num) { fmpz_init(root); fmpz_init(D); qfb_init(r); qfb_init(s); fmpz_set_ui(root, i); fmpz_root(root, root, 4); for (k = 0; k < 20; k++) { i1 = n_randint(state, num); qfb_discriminant(D, forms + i1); qfb_nucomp(r, forms + i1, forms + i1, D, root); qfb_nudupl(s, forms + i1, D, root); qfb_reduce(r, r, D); qfb_reduce(s, s, D); result = (qfb_equal(r, s)); if (!result) { printf("FAIL:\n"); printf("NUDUPL does not agree with NUCOMP\n"); printf("f = "); qfb_print(forms + i1); printf("\n"); qfb_print(r); printf(" != "); qfb_print(s); flint_abort(); } } fmpz_clear(D); fmpz_clear(root); qfb_clear(r); qfb_clear(s); } qfb_array_clear(&forms, num); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-pow.c000066400000000000000000000035701461254215100163700ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_pow, state) { int result; slong i, j; for (i = 1; i < 1000; i++) { fmpz_t D, L, fexp; qfb_t r, s, t; ulong exp; fmpz_init(D); fmpz_init(L); fmpz_init(fexp); qfb_init(r); qfb_init(s); qfb_init(t); do { fmpz_randtest_unsigned(r->a, state, 100); if (fmpz_is_zero(r->a)) fmpz_set_ui(r->a, 1); fmpz_randtest(r->b, state, 100); fmpz_randtest(r->c, state, 100); qfb_discriminant(D, r); } while (fmpz_sgn(D) >= 0 || !qfb_is_primitive(r)); fmpz_abs(L, D); fmpz_root(L, L, 4); qfb_reduce(r, r, D); exp = n_randint(state, 1000); fmpz_set_ui(fexp, exp); qfb_pow(s, r, D, fexp); qfb_reduce(s, s, D); qfb_principal_form(t, D); for (j = 0; j < exp; j++) { qfb_nucomp(t, t, r, D, L); qfb_reduce(t, t, D); } result = (qfb_equal(s, t)); if (!result) { printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); qfb_print(r); printf("\n"); qfb_print(s); printf("\n"); qfb_print(t); printf("\n"); flint_abort(); } fmpz_clear(fexp); fmpz_clear(D); fmpz_clear(L); qfb_clear(r); qfb_clear(s); qfb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-pow_ui.c000066400000000000000000000034441461254215100170650ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_pow_ui, state) { int result; slong i, j; for (i = 1; i < 1000; i++) { fmpz_t D, L; qfb_t r, s, t; ulong exp; fmpz_init(D); fmpz_init(L); qfb_init(r); qfb_init(s); qfb_init(t); do { fmpz_randtest_unsigned(r->a, state, 100); if (fmpz_is_zero(r->a)) fmpz_set_ui(r->a, 1); fmpz_randtest(r->b, state, 100); fmpz_randtest(r->c, state, 100); qfb_discriminant(D, r); } while (fmpz_sgn(D) >= 0 || !qfb_is_primitive(r)); fmpz_abs(L, D); fmpz_root(L, L, 4); qfb_reduce(r, r, D); exp = n_randint(state, 1000); qfb_pow_ui(s, r, D, exp); qfb_reduce(s, s, D); qfb_principal_form(t, D); for (j = 0; j < exp; j++) { qfb_nucomp(t, t, r, D, L); qfb_reduce(t, t, D); } result = (qfb_equal(s, t)); if (!result) { printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); qfb_print(r); printf("\n"); qfb_print(s); printf("\n"); qfb_print(t); printf("\n"); flint_abort(); } fmpz_clear(D); fmpz_clear(L); qfb_clear(r); qfb_clear(s); qfb_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-prime_form.c000066400000000000000000000040031461254215100177120ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qfb.h" TEST_FUNCTION_START(qfb_prime_form, state) { int result; slong i; for (i = 1; i < 50000; i++) { fmpz_t D, D2, p; qfb_t r, s; ulong n, q, Dmodp; fmpz_init(D); fmpz_init(D2); fmpz_init(p); qfb_init(r); qfb_init(s); do { fmpz_randtest_unsigned(r->a, state, 100); if (fmpz_is_zero(r->a)) fmpz_set_ui(r->a, 1); fmpz_randtest(r->b, state, 100); fmpz_randtest(r->c, state, 100); qfb_discriminant(D, r); } while (fmpz_sgn(D) >= 0); do { n = n_randprime(state, n_randint(state, FLINT_BITS - 1) + 2, 0); fmpz_set_ui(p, n); Dmodp = fmpz_fdiv_ui(D, n); } while ((mp_limb_signed_t) Dmodp < 0 /* Jacobi can't handle this */ || (n == 2 && ((q = fmpz_fdiv_ui(D, 8)) == 2 || q == 3 || q == 5)) || (n != 2 && Dmodp != 0 && n_jacobi(Dmodp, n) < 0)); qfb_prime_form(s, D, p); qfb_discriminant(D2, s); result = (fmpz_equal(s->a, p) && fmpz_equal(D2, D) && fmpz_sgn(s->b) >= 0); if (!result) { printf("FAIL:\n"); qfb_print(s); printf("\n"); printf("p = \n"); fmpz_print(p); printf("\n"); printf("D = \n"); fmpz_print(D); printf("\n"); printf("D2 = \n"); fmpz_print(D2); printf("\n"); flint_abort(); } fmpz_clear(D); fmpz_clear(D2); fmpz_clear(p); qfb_clear(r); qfb_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-reduce.c000066400000000000000000000022701461254215100170260ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_reduce, state) { int result; slong i; for (i = 1; i < 100000; i++) { fmpz_t D; qfb_t r; fmpz_init(D); qfb_init(r); do { fmpz_randtest_unsigned(r->a, state, 100); if (fmpz_is_zero(r->a)) fmpz_set_ui(r->a, 1); fmpz_randtest(r->b, state, 100); fmpz_randtest(r->c, state, 100); qfb_discriminant(D, r); } while (fmpz_sgn(D) >= 0); qfb_reduce(r, r, D); result = (qfb_is_reduced(r)); if (!result) { printf("FAIL:\n"); qfb_print(r); printf("\n"); flint_abort(); } fmpz_clear(D); qfb_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qfb/test/t-reduced_forms.c000066400000000000000000000026561461254215100204100ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qfb.h" TEST_FUNCTION_START(qfb_reduced_forms, state) { int result; qfb * forms; qfb * forms2; slong i, j, k, num, num2; for (i = 1; i < 30000; i++) { num = qfb_reduced_forms(&forms, -i); num2 = qfb_reduced_forms_large(&forms2, -i); result = (num == num2); for (j = 0; result == 1 && j < num; j++) { for (k = 0; k < num; k++) if (qfb_equal(forms + j, forms2 + k)) break; result &= (k != num); if (!result) break; } if (!result) { printf("FAIL:\n"); if (num == num2) { qfb_print(forms + j); printf(" != "); qfb_print(forms2 + j); printf("\n"); } else flint_printf("%wd != %wd\n", num, num2); flint_abort(); } qfb_array_clear(&forms, num); qfb_array_clear(&forms2, num2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar.h000066400000000000000000000326461461254215100147140ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef QQBAR_H #define QQBAR_H #ifdef QQBAR_INLINES_C #define QQBAR_INLINE #else #define QQBAR_INLINE static inline #endif #ifdef __cplusplus extern "C" { #endif #include "fmpz_types.h" #include "fmpq_types.h" #include "mpoly_types.h" #include "acb.h" typedef struct { fmpz_poly_struct poly; acb_struct enclosure; } qqbar_struct; typedef qqbar_struct qqbar_t[1]; typedef qqbar_struct * qqbar_ptr; typedef const qqbar_struct * qqbar_srcptr; #define QQBAR_POLY(x) (&((x)->poly)) #define QQBAR_COEFFS(x) ((&((x)->poly))->coeffs) #define QQBAR_ENCLOSURE(x) (&((x)->enclosure)) #define QQBAR_DEFAULT_PREC 128 /* Memory management */ void qqbar_init(qqbar_t res); void qqbar_clear(qqbar_t res); QQBAR_INLINE qqbar_ptr _qqbar_vec_init(slong len) { slong i; qqbar_ptr vec = (qqbar_ptr) flint_malloc(len * sizeof(qqbar_struct)); for (i = 0; i < len; i++) qqbar_init(vec + i); return vec; } QQBAR_INLINE void _qqbar_vec_clear(qqbar_ptr vec, slong len) { slong i; for (i = 0; i < len; i++) qqbar_clear(vec + i); flint_free(vec); } /* Assignment */ void qqbar_swap(qqbar_t x, qqbar_t y); void qqbar_set(qqbar_t res, const qqbar_t x); void qqbar_set_si(qqbar_t res, slong x); void qqbar_set_ui(qqbar_t res, ulong x); void qqbar_set_fmpz(qqbar_t res, const fmpz_t x); void qqbar_set_fmpq(qqbar_t res, const fmpq_t x); void qqbar_set_re_im(qqbar_t res, const qqbar_t x, const qqbar_t y); int qqbar_set_d(qqbar_t res, double x); int qqbar_set_re_im_d(qqbar_t res, double x, double y); /* Properties */ QQBAR_INLINE slong qqbar_degree(const qqbar_t x) { return QQBAR_POLY(x)->length - 1; } QQBAR_INLINE int qqbar_is_rational(const qqbar_t x) { return (qqbar_degree(x) == 1); } QQBAR_INLINE int qqbar_is_integer(const qqbar_t x) { return qqbar_is_rational(x) && fmpz_is_one(QQBAR_COEFFS(x) + 1); } QQBAR_INLINE int qqbar_is_algebraic_integer(const qqbar_t x) { return fmpz_is_one(QQBAR_COEFFS(x) + qqbar_degree(x)); } QQBAR_INLINE int qqbar_is_zero(const qqbar_t x) { return qqbar_is_integer(x) && fmpz_is_zero(QQBAR_COEFFS(x)); } QQBAR_INLINE int qqbar_is_one(const qqbar_t x) { return qqbar_is_integer(x) && (fmpz_equal_si(QQBAR_COEFFS(x), -1)); } QQBAR_INLINE int qqbar_is_neg_one(const qqbar_t x) { return qqbar_is_integer(x) && fmpz_is_one(QQBAR_COEFFS(x)); } QQBAR_INLINE int qqbar_is_i(const qqbar_t x) { return (qqbar_degree(x) == 2) && fmpz_is_one(QQBAR_COEFFS(x)) && fmpz_is_zero(QQBAR_COEFFS(x) + 1) && fmpz_is_one(QQBAR_COEFFS(x) + 2) && arf_sgn(arb_midref(acb_imagref(QQBAR_ENCLOSURE(x)))) > 0; } QQBAR_INLINE int qqbar_is_neg_i(const qqbar_t x) { return (qqbar_degree(x) == 2) && fmpz_is_one(QQBAR_COEFFS(x)) && fmpz_is_zero(QQBAR_COEFFS(x) + 1) && fmpz_is_one(QQBAR_COEFFS(x) + 2) && arf_sgn(arb_midref(acb_imagref(QQBAR_ENCLOSURE(x)))) < 0; } int qqbar_sgn_re(const qqbar_t x); int qqbar_sgn_im(const qqbar_t x); QQBAR_INLINE int qqbar_is_real(const qqbar_t x) { return qqbar_sgn_im(x) == 0; } slong qqbar_height_bits(const qqbar_t x); void qqbar_height(fmpz_t res, const qqbar_t x); QQBAR_INLINE int qqbar_within_limits(const qqbar_t x, slong deg_limit, slong bits_limit) { return (deg_limit == 0 || (qqbar_degree(x) <= deg_limit)) && (bits_limit == 0 || (qqbar_height_bits(x) <= bits_limit)); } QQBAR_INLINE int qqbar_binop_within_limits(const qqbar_t x, const qqbar_t y, slong deg_limit, slong bits_limit) { return (deg_limit == 0 || (qqbar_degree(x) * qqbar_degree(y) <= deg_limit)) && (bits_limit == 0 || (qqbar_height_bits(x) + qqbar_height_bits(y) <= bits_limit)); } /* Conversions */ void _qqbar_get_fmpq(fmpz_t num, fmpz_t den, const qqbar_t x); void qqbar_get_fmpq(fmpq_t res, const qqbar_t x); void qqbar_get_fmpz(fmpz_t res, const qqbar_t x); /* Special values */ QQBAR_INLINE void qqbar_zero(qqbar_t res) { qqbar_set_ui(res, 0); } QQBAR_INLINE void qqbar_one(qqbar_t res) { qqbar_set_ui(res, 1); } void qqbar_i(qqbar_t res); void qqbar_phi(qqbar_t res); /* Random generation */ void qqbar_randtest(qqbar_t res, flint_rand_t state, slong deg, slong bits); void qqbar_randtest_real(qqbar_t res, flint_rand_t state, slong deg, slong bits); void qqbar_randtest_nonreal(qqbar_t res, flint_rand_t state, slong deg, slong bits); /* Input and output */ void qqbar_print(const qqbar_t x); void qqbar_printn(const qqbar_t x, slong n); void qqbar_printnd(const qqbar_t x, slong n); /* Comparisons */ int qqbar_equal(const qqbar_t x, const qqbar_t y); int qqbar_equal_fmpq_poly_val(const qqbar_t x, const fmpq_poly_t f, const qqbar_t y); int qqbar_cmp_re(const qqbar_t x, const qqbar_t y); int qqbar_cmp_im(const qqbar_t x, const qqbar_t y); int qqbar_cmpabs_re(const qqbar_t x, const qqbar_t y); int qqbar_cmpabs_im(const qqbar_t x, const qqbar_t y); int qqbar_cmpabs(const qqbar_t x, const qqbar_t y); int qqbar_cmp_root_order(const qqbar_t x, const qqbar_t y); ulong qqbar_hash(const qqbar_t x); /* Complex parts */ void qqbar_conj(qqbar_t res, const qqbar_t x); void qqbar_re(qqbar_t res, const qqbar_t x); void qqbar_im(qqbar_t res, const qqbar_t x); void qqbar_re_im(qqbar_t res1, qqbar_t res2, const qqbar_t x); void qqbar_abs(qqbar_t res, const qqbar_t x); void qqbar_abs2(qqbar_t res, const qqbar_t x); void qqbar_sgn(qqbar_t res, const qqbar_t x); int qqbar_csgn(const qqbar_t x); /* Integer parts */ void qqbar_floor(fmpz_t res, const qqbar_t x); void qqbar_ceil(fmpz_t res, const qqbar_t x); void qqbar_numerator(qqbar_t res, const qqbar_t y); void qqbar_denominator(fmpz_t res, const qqbar_t y); /* Arithmetic */ void qqbar_neg(qqbar_t res, const qqbar_t x); void qqbar_add(qqbar_t res, const qqbar_t x, const qqbar_t y); void qqbar_add_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y); void qqbar_add_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y); void qqbar_add_ui(qqbar_t res, const qqbar_t x, ulong y); void qqbar_add_si(qqbar_t res, const qqbar_t x, slong y); void qqbar_sub(qqbar_t res, const qqbar_t x, const qqbar_t y); void qqbar_sub_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y); void qqbar_sub_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y); void qqbar_sub_ui(qqbar_t res, const qqbar_t x, ulong y); void qqbar_sub_si(qqbar_t res, const qqbar_t x, slong y); void qqbar_fmpq_sub(qqbar_t res, const fmpq_t x, const qqbar_t y); void qqbar_fmpz_sub(qqbar_t res, const fmpz_t x, const qqbar_t y); void qqbar_ui_sub(qqbar_t res, ulong x, const qqbar_t y); void qqbar_si_sub(qqbar_t res, slong x, const qqbar_t y); void qqbar_mul(qqbar_t res, const qqbar_t x, const qqbar_t y); void qqbar_mul_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y); void qqbar_mul_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y); void qqbar_mul_ui(qqbar_t res, const qqbar_t x, ulong y); void qqbar_mul_si(qqbar_t res, const qqbar_t x, slong y); void qqbar_div(qqbar_t res, const qqbar_t x, const qqbar_t y); void qqbar_div_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y); void qqbar_div_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y); void qqbar_div_ui(qqbar_t res, const qqbar_t x, ulong y); void qqbar_div_si(qqbar_t res, const qqbar_t x, slong y); void qqbar_fmpq_div(qqbar_t res, const fmpq_t x, const qqbar_t y); void qqbar_fmpz_div(qqbar_t res, const fmpz_t x, const qqbar_t y); void qqbar_ui_div(qqbar_t res, ulong x, const qqbar_t y); void qqbar_si_div(qqbar_t res, slong x, const qqbar_t y); QQBAR_INLINE void qqbar_sqr(qqbar_t res, const qqbar_t x) { qqbar_mul(res, x, x); } void qqbar_inv(qqbar_t res, const qqbar_t x); void qqbar_mul_2exp_si(qqbar_t res, const qqbar_t x, slong exp); void qqbar_pow_ui(qqbar_t res, const qqbar_t x, ulong e); void qqbar_pow_si(qqbar_t res, const qqbar_t x, slong n); void qqbar_pow_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t n); void qqbar_pow_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t n); int qqbar_pow(qqbar_t res, const qqbar_t x, const qqbar_t e); /* Check if x = (p/q)^(1/n), p > 0 */ int _qqbar_fast_detect_simple_principal_surd(const qqbar_t x); void qqbar_root_ui(qqbar_t res, const qqbar_t x, ulong n); QQBAR_INLINE void qqbar_sqrt(qqbar_t res, const qqbar_t x) { qqbar_root_ui(res, x, 2); } QQBAR_INLINE void qqbar_sqrt_ui(qqbar_t res, ulong x) { qqbar_set_ui(res, x); qqbar_sqrt(res, res); } QQBAR_INLINE void qqbar_rsqrt(qqbar_t res, const qqbar_t x) { qqbar_sqrt(res, x); qqbar_inv(res, res); } void qqbar_fmpq_root_ui(qqbar_t res, const fmpq_t x, ulong b); void qqbar_fmpq_pow_si_ui(qqbar_t res, const fmpq_t x, slong a, ulong b); /* Numerical enclosure */ void qqbar_cache_enclosure(qqbar_t res, slong prec); void qqbar_get_acb(acb_t res, const qqbar_t x, slong prec); void qqbar_get_arb(arb_t res, const qqbar_t x, slong prec); void qqbar_get_arb_re(arb_t res, const qqbar_t x, slong prec); void qqbar_get_arb_im(arb_t res, const qqbar_t x, slong prec); /* Conjugates */ void qqbar_conjugates(qqbar_ptr res, const qqbar_t x); /* Polynomial operations */ void _qqbar_evaluate_fmpq_poly(qqbar_t res, const fmpz * poly, const fmpz_t den, slong len, const qqbar_t x); void qqbar_evaluate_fmpq_poly(qqbar_t res, const fmpq_poly_t poly, const qqbar_t x); void _qqbar_evaluate_fmpz_poly(qqbar_t res, const fmpz * poly, slong len, const qqbar_t x); void qqbar_evaluate_fmpz_poly(qqbar_t res, const fmpz_poly_t poly, const qqbar_t x); int qqbar_evaluate_fmpz_mpoly_iter(qqbar_t res, const fmpz_mpoly_t f, qqbar_srcptr x, slong deg_limit, slong bits_limit, const fmpz_mpoly_ctx_t ctx); int qqbar_evaluate_fmpz_mpoly_horner(qqbar_t res, const fmpz_mpoly_t f, qqbar_srcptr x, slong deg_limit, slong bits_limit, const fmpz_mpoly_ctx_t ctx); int qqbar_evaluate_fmpz_mpoly(qqbar_t res, const fmpz_mpoly_t f, qqbar_srcptr x, slong deg_limit, slong bits_limit, const fmpz_mpoly_ctx_t ctx); #define QQBAR_ROOTS_IRREDUCIBLE 1 #define QQBAR_ROOTS_UNSORTED 2 void qqbar_roots_fmpz_poly(qqbar_ptr res, const fmpz_poly_t poly, int flags); void qqbar_roots_fmpq_poly(qqbar_ptr res, const fmpq_poly_t poly, int flags); void qqbar_eigenvalues_fmpz_mat(qqbar_ptr res, const fmpz_mat_t mat, int flags); void qqbar_eigenvalues_fmpq_mat(qqbar_ptr res, const fmpq_mat_t mat, int flags); /* Roots of unity and trigonometric functions */ void qqbar_root_of_unity(qqbar_t res, slong p, ulong q); int qqbar_is_root_of_unity(slong * p, ulong * q, const qqbar_t x); void qqbar_exp_pi_i(qqbar_t res, slong p, ulong q); void qqbar_cos_pi(qqbar_t res, slong p, ulong q); void qqbar_sin_pi(qqbar_t res, slong p, ulong q); int qqbar_tan_pi(qqbar_t res, slong p, ulong q); int qqbar_cot_pi(qqbar_t res, slong p, ulong q); int qqbar_sec_pi(qqbar_t res, slong p, ulong q); int qqbar_csc_pi(qqbar_t res, slong p, ulong q); int qqbar_log_pi_i(slong * p, ulong * q, const qqbar_t x); int qqbar_atan_pi(slong * p, ulong * q, const qqbar_t x); int qqbar_asin_pi(slong * p, ulong * q, const qqbar_t x); int qqbar_acos_pi(slong * p, ulong * q, const qqbar_t x); int qqbar_acot_pi(slong * p, ulong * q, const qqbar_t x); int qqbar_asec_pi(slong * p, ulong * q, const qqbar_t x); int qqbar_acsc_pi(slong * p, ulong * q, const qqbar_t x); /* Guessing and simplification */ int qqbar_guess(qqbar_t res, const acb_t z, slong max_deg, slong max_bits, int flags, slong prec); int qqbar_express_in_field(fmpq_poly_t res, const qqbar_t alpha, const qqbar_t x, slong max_bits, int flags, slong prec); /* Conversions to radicals and expressions */ void qqbar_get_quadratic(fmpz_t res_a, fmpz_t res_b, fmpz_t res_c, fmpz_t res_q, const qqbar_t x, int factoring); #ifdef FEXPR_H void qqbar_get_fexpr_repr(fexpr_t res, const qqbar_t x); void qqbar_get_fexpr_root_nearest(fexpr_t res, const qqbar_t x); void qqbar_get_fexpr_root_indexed(fexpr_t res, const qqbar_t x); int qqbar_get_fexpr_formula(fexpr_t res, const qqbar_t x, ulong flags); #define QQBAR_FORMULA_GAUSSIANS 1 #define QQBAR_FORMULA_QUADRATICS 2 #define QQBAR_FORMULA_CYCLOTOMICS 4 #define QQBAR_FORMULA_CUBICS 8 #define QQBAR_FORMULA_QUARTICS 16 #define QQBAR_FORMULA_QUINTICS 32 #define QQBAR_FORMULA_DEPRESSION 64 #define QQBAR_FORMULA_DEFLATION 128 #define QQBAR_FORMULA_SEPARATION 256 #define QQBAR_FORMULA_EXP_FORM 2048 #define QQBAR_FORMULA_TRIG_FORM 4096 #define QQBAR_FORMULA_RADICAL_FORM 8192 #define QQBAR_FORMULA_AUTO_FORM 0 #define QQBAR_FORMULA_ALL ((2 * QQBAR_FORMULA_SEPARATION - 1) | QQBAR_FORMULA_AUTO_FORM) int qqbar_set_fexpr(qqbar_t res, const fexpr_t expr); #endif /* Internal functions */ void qqbar_scalar_op(qqbar_t res, const qqbar_t x, const fmpz_t a, const fmpz_t b, const fmpz_t c); void qqbar_fmpz_poly_composed_op(fmpz_poly_t res, const fmpz_poly_t A, const fmpz_poly_t B, int op); void qqbar_binary_op(qqbar_t res, const qqbar_t x, const qqbar_t y, int op); int _qqbar_validate_uniqueness(acb_t res, const fmpz_poly_t poly, const acb_t z, slong max_prec); int _qqbar_validate_existence_uniqueness(acb_t res, const fmpz_poly_t poly, const acb_t z, slong prec); void _qqbar_enclosure_raw(acb_t res, const fmpz_poly_t poly, const acb_t zin, slong prec); void qqbar_enclosure_raw(acb_t res, const qqbar_t x, slong prec); int _qqbar_acb_lindep(fmpz * rel, acb_srcptr vec, slong len, int check, slong prec); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/qqbar/000077500000000000000000000000001461254215100145305ustar00rootroot00000000000000flint-3.1.3/src/qqbar/abs.c000066400000000000000000000022611461254215100154420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" /* todo: might be worth it to detect p/q * root of unity */ void qqbar_abs(qqbar_t res, const qqbar_t x) { if (qqbar_is_real(x)) { if (qqbar_sgn_re(x) >= 0) qqbar_set(res, x); else qqbar_neg(res, x); } else if (qqbar_is_root_of_unity(NULL, NULL, x)) { qqbar_one(res); } else { qqbar_t t; qqbar_init(t); if (qqbar_sgn_re(x) == 0) { qqbar_i(t); qqbar_mul(res, x, t); if (qqbar_sgn_re(res) < 0) qqbar_neg(res, res); } else { qqbar_conj(t, x); qqbar_mul(t, x, t); qqbar_sqrt(res, t); } qqbar_clear(t); } arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); } flint-3.1.3/src/qqbar/abs2.c000066400000000000000000000020271461254215100155240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" /* todo: might be worth it to detect p/q * root of unity */ void qqbar_abs2(qqbar_t res, const qqbar_t x) { if (qqbar_is_real(x)) { qqbar_sqr(res, x); } else if (qqbar_is_root_of_unity(NULL, NULL, x)) { qqbar_one(res); } else { qqbar_t t; qqbar_init(t); if (qqbar_sgn_re(x) == 0) { qqbar_i(t); qqbar_mul(res, x, t); qqbar_sqr(res, res); } else { qqbar_conj(t, x); qqbar_mul(res, x, t); } qqbar_clear(t); } arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); } flint-3.1.3/src/qqbar/acb_lindep.c000066400000000000000000000074661461254215100167710ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #include "qqbar.h" int _qqbar_acb_lindep(fmpz * rel, acb_srcptr vec, slong len, int check, slong prec) { arf_t tmpr, halfr; fmpz_mat_t A; fmpz_lll_t ctx; fmpz_t scale_exp; int nonreal, found; slong i, accuracy; acb_t z2; mag_t max_size, max_rad, tmpmag; for (i = 0; i < len; i++) if (!acb_is_finite(vec + i)) return 0; found = 0; nonreal = 0; for (i = 0; i < len; i++) if (!arb_contains_zero(acb_imagref(vec + i))) nonreal = 1; fmpz_mat_init(A, len, len + 1 + nonreal); fmpz_init(scale_exp); acb_init(z2); arf_init(tmpr); arf_init(halfr); mag_init(max_size); mag_init(max_rad); mag_init(tmpmag); arf_set_d(halfr, 0.5); for (i = 0; i < len; i++) { arf_get_mag(tmpmag, arb_midref(acb_realref(vec + i))); mag_max(max_size, max_size, tmpmag); arf_get_mag(tmpmag, arb_midref(acb_imagref(vec + i))); mag_max(max_size, max_size, tmpmag); mag_max(max_rad, max_rad, arb_radref(acb_realref(vec + i))); mag_max(max_rad, max_rad, arb_radref(acb_imagref(vec + i))); } prec = FLINT_MAX(prec, 2); if (!mag_is_zero(max_size) && !mag_is_zero(max_rad)) { accuracy = _fmpz_sub_small(MAG_EXPREF(max_size), MAG_EXPREF(max_rad)); accuracy = FLINT_MAX(accuracy, 10); prec = FLINT_MIN(prec, accuracy); } if (mag_is_zero(max_size)) { fmpz_zero(scale_exp); /* todo: quick return? */ } else { fmpz_neg(scale_exp, MAG_EXPREF(max_size)); fmpz_add_ui(scale_exp, scale_exp, prec); } /* Using 5% of the bits for checking will provide some protection against spurious relations */ fmpz_sub_ui(scale_exp, scale_exp, FLINT_MAX(10, prec * 0.05)); /* Create matrix */ for (i = 0; i < len; i++) fmpz_one(fmpz_mat_entry(A, i, i)); for (i = 0; i < len; i++) { arf_mul_2exp_fmpz(tmpr, arb_midref(acb_realref(vec + i)), scale_exp); arf_add(tmpr, tmpr, halfr, prec, ARF_RND_NEAR); arf_floor(tmpr, tmpr); arf_get_fmpz(fmpz_mat_entry(A, i, len), tmpr, ARF_RND_NEAR); if (nonreal) { arf_mul_2exp_fmpz(tmpr, arb_midref(acb_imagref(vec + i)), scale_exp); arf_add(tmpr, tmpr, halfr, prec, ARF_RND_NEAR); arf_floor(tmpr, tmpr); arf_get_fmpz(fmpz_mat_entry(A, i, len + 1), tmpr, ARF_RND_NEAR); } } /* LLL reduction */ fmpz_lll_context_init(ctx, 0.75, 0.51, 1, 0); fmpz_lll(A, NULL, ctx); for (i = 0; i < len; i++) fmpz_set(rel + i, fmpz_mat_entry(A, 0, i)); #if 0 flint_printf("rel "); for (i = 0; i < len; i++) { fmpz_print(rel + i); flint_printf(" "); } flint_printf("\n"); #endif /* Heuristic check */ if (check) { for (i = 0; i < len; i++) acb_addmul_fmpz(z2, vec + i, rel + i, prec + 10); found = !_fmpz_vec_is_zero(rel, len) && acb_contains_zero(z2); } else { found = !_fmpz_vec_is_zero(rel, len); } /* if (found) { flint_printf("REL:\n"); fmpz_mat_print_pretty(A); flint_printf("\n\n"); } */ fmpz_mat_clear(A); fmpz_clear(scale_exp); acb_clear(z2); arf_clear(tmpr); arf_clear(halfr); mag_clear(max_size); mag_clear(max_rad); mag_clear(tmpmag); return found; } flint-3.1.3/src/qqbar/acos_pi.c000066400000000000000000000015101461254215100163060ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "qqbar.h" int qqbar_acos_pi(slong * p, ulong * q, const qqbar_t x) { if (qqbar_asin_pi(p, q, x)) { slong a, b, g; a = *p; b = *q; /* 1/2 - a/b */ a = b - 2 * a; b = 2 * b; g = n_gcd(FLINT_ABS(a), b); if (g != 1) { a /= g; b /= g; } *p = a; *q = b; return 1; } return 0; } flint-3.1.3/src/qqbar/acot_pi.c000066400000000000000000000051771461254215100163240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_acot_pi(slong * p, ulong * q, const qqbar_t x) { slong deg = qqbar_degree(x); *p = 0; *q = 1; if (deg == 1) { if (qqbar_is_zero(x)) { *p = 1; *q = 2; return 1; } if (qqbar_is_one(x)) { *p = 1; *q = 4; return 1; } if (qqbar_is_neg_one(x)) { *p = -1; *q = 4; return 1; } return 0; } else if (deg == 2) { fmpz a, b, c; a = QQBAR_COEFFS(x)[0]; b = QQBAR_COEFFS(x)[1]; c = QQBAR_COEFFS(x)[2]; if (a == -3 && b == 0 && c == 1) { *p = qqbar_sgn_re(x); *q = 6; return 1; } if (a == -1 && b == 0 && c == 3) { *p = qqbar_sgn_re(x); *q = 3; return 1; } if (a == -1 && b == 2 && c == 1) { *p = (qqbar_sgn_re(x) == 1) ? 3 : -1; *q = 8; return 1; } if (a == -1 && b == -2 && c == 1) { *p = (qqbar_sgn_re(x) == 1) ? 1 : -3; *q = 8; return 1; } if (a == 1 && b == -4 && c == 1) { /* root is ~0.267 or ~3.73 -- accuracy should not be that bad */ if (arb_contains_si(acb_realref(QQBAR_ENCLOSURE(x)), 1)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); *p = (arf_cmpabs_2exp_si(arb_midref(acb_realref(QQBAR_ENCLOSURE(x))), 0) < 0) ? 5 : 1; *q = 12; return 1; } if (a == 1 && b == 4 && c == 1) { if (arb_contains_si(acb_realref(QQBAR_ENCLOSURE(x)), -1)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); *p = (arf_cmpabs_2exp_si(arb_midref(acb_realref(QQBAR_ENCLOSURE(x))), 0) < 0) ? -5 : -1; *q = 12; return 1; } return 0; } else if ((deg % 2 != 0) || !qqbar_is_real(x)) { return 0; } else { int res; qqbar_t t; qqbar_init(t); qqbar_inv(t, x); res = qqbar_atan_pi(p, q, t); qqbar_clear(t); return res; } } flint-3.1.3/src/qqbar/acsc_pi.c000066400000000000000000000013431461254215100162760ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_acsc_pi(slong * p, ulong * q, const qqbar_t x) { if (qqbar_is_zero(x)) { *p = 0; *q = 1; return 0; } else { int res; qqbar_t t; qqbar_init(t); qqbar_inv(t, x); res = qqbar_asin_pi(p, q, t); qqbar_clear(t); return res; } } flint-3.1.3/src/qqbar/add.c000066400000000000000000000034401461254215100154250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_add(qqbar_t res, const qqbar_t x, const qqbar_t y) { if (qqbar_is_zero(x)) { qqbar_set(res, y); } else if (qqbar_is_zero(y)) { qqbar_set(res, x); } else if (qqbar_is_rational(y)) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); _qqbar_get_fmpq(b, a, y); qqbar_scalar_op(res, x, a, b, a); fmpz_clear(a); fmpz_clear(b); } else if (qqbar_is_rational(x)) { fmpz_t a, b; fmpz_init(a); fmpz_init(b); _qqbar_get_fmpq(b, a, x); qqbar_scalar_op(res, y, a, b, a); fmpz_clear(a); fmpz_clear(b); } else { qqbar_binary_op(res, x, y, 0); } } void qqbar_add_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpq(t, y); qqbar_add(res, x, t); qqbar_clear(t); } void qqbar_add_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpz(t, y); qqbar_add(res, x, t); qqbar_clear(t); } void qqbar_add_ui(qqbar_t res, const qqbar_t x, ulong y) { qqbar_t t; qqbar_init(t); qqbar_set_ui(t, y); qqbar_add(res, x, t); qqbar_clear(t); } void qqbar_add_si(qqbar_t res, const qqbar_t x, slong y) { qqbar_t t; qqbar_init(t); qqbar_set_si(t, y); qqbar_add(res, x, t); qqbar_clear(t); } flint-3.1.3/src/qqbar/affine_transform.c000066400000000000000000000076621461254215100202320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq.h" #include "fmpq_poly.h" #include "arb_fmpz_poly.h" #include "qqbar.h" static void _fmpq_poly_compose2(fmpz * res, const fmpz * poly1, const fmpz_t den1, slong len1, const fmpz * poly2, const fmpz_t den2, slong len2) { fmpz_t den; slong len; len = (len1 - WORD(1)) * (len2 - WORD(1)) + WORD(1); fmpz_init(den); if (fmpz_is_one(den2)) { _fmpz_poly_compose(res, poly1, len1, poly2, len2); } else { fmpz_t one; fmpz * v = _fmpz_vec_init(len1); fmpz_init(one); fmpz_one(one); _fmpq_poly_rescale(v, den, poly1, den1, len1, one, den2); _fmpz_poly_compose(res, v, len1, poly2, len2); fmpz_clear(one); _fmpz_vec_clear(v, len1); } _fmpz_vec_content(den, res, len); if (fmpz_sgn(res + len - 1) < 0) fmpz_neg(den, den); _fmpz_vec_scalar_divexact_fmpz(res, res, len, den); fmpz_clear(den); } void qqbar_scalar_op(qqbar_t res, const qqbar_t x, const fmpz_t a, const fmpz_t b, const fmpz_t c) { fmpz_poly_t H; fmpz_t one, Gden; fmpz G[2]; acb_t z, t, w; slong d, prec; if (fmpz_is_zero(c)) { flint_throw(FLINT_ERROR, "qqbar_scalar_op: division by zero\n"); } /* Special case: set to rational */ if (fmpz_is_zero(a)) { fmpq_t t; fmpq_init(t); fmpq_set_fmpz_frac(t, b, c); qqbar_set_fmpq(res, t); fmpq_clear(t); return; } d = qqbar_degree(x); /* Special case: rational arithmetic */ if (d == 1) { fmpq_t t; fmpq_init(t); fmpz_neg(fmpq_numref(t), QQBAR_POLY(x)->coeffs); fmpz_set(fmpq_denref(t), QQBAR_POLY(x)->coeffs + 1); if (!fmpz_is_one(a)) fmpq_mul_fmpz(t, t, a); if (!fmpz_is_zero(b)) fmpq_add_fmpz(t, t, b); if (!fmpz_is_one(c)) fmpq_div_fmpz(t, t, c); qqbar_set_fmpq(res, t); fmpq_clear(t); return; } fmpz_poly_init2(H, d + 1); fmpz_init(one); fmpz_init(G); fmpz_init(G + 1); fmpz_init(Gden); /* (ax+b)/c -> inverse transformation (-b+cx)/a */ fmpz_one(one); if (fmpz_sgn(a) > 0) { fmpz_neg(G, b); fmpz_set(G + 1, c); fmpz_set(Gden, a); } else { fmpz_set(G, b); fmpz_neg(G + 1, c); fmpz_neg(Gden, a); } _fmpq_poly_compose2(H->coeffs, QQBAR_POLY(x)->coeffs, one, d + 1, G, Gden, 2); _fmpz_poly_set_length(H, d + 1); acb_init(z); acb_init(t); acb_init(w); acb_set(z, QQBAR_ENCLOSURE(x)); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); if (fmpz_is_one(a)) acb_set(w, z); else if (fmpz_equal_si(a, -1)) acb_neg(w, z); else acb_mul_fmpz(w, z, a, prec); if (!fmpz_is_zero(b)) acb_add_fmpz(w, w, b, prec); if (!fmpz_is_one(c)) { if (fmpz_equal_si(c, -1)) acb_neg(w, w); else acb_div_fmpz(w, w, c, prec); } if (_qqbar_validate_uniqueness(t, H, w, 2 * prec) /* && acb_rel_accuracy_bits(t) >= QQBAR_DEFAULT_PREC / 2 */) { fmpz_poly_set(QQBAR_POLY(res), H); acb_set(QQBAR_ENCLOSURE(res), t); break; } } acb_clear(z); acb_clear(t); acb_clear(w); fmpz_poly_clear(H); fmpz_clear(one); fmpz_clear(G); fmpz_clear(G + 1); fmpz_clear(Gden); } flint-3.1.3/src/qqbar/asec_pi.c000066400000000000000000000013431461254215100163000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_asec_pi(slong * p, ulong * q, const qqbar_t x) { if (qqbar_is_zero(x)) { *p = 0; *q = 1; return 0; } else { int res; qqbar_t t; qqbar_init(t); qqbar_inv(t, x); res = qqbar_acos_pi(p, q, t); qqbar_clear(t); return res; } } flint-3.1.3/src/qqbar/asin_pi.c000066400000000000000000000063721461254215100163260ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "qqbar.h" void best_rational_fast(slong * p, ulong * q, double x, slong N); int qqbar_asin_pi(slong * p, ulong * q, const qqbar_t x) { slong deg = qqbar_degree(x); *p = 0; *q = 0; if (deg == 1) { if (qqbar_is_zero(x)) { *p = 0; *q = 1; return 1; } if (qqbar_is_one(x)) { *p = 1; *q = 2; return 1; } if (qqbar_is_neg_one(x)) { *p = -1; *q = 2; return 1; } if (QQBAR_COEFFS(x)[1] == 2 && QQBAR_COEFFS(x)[0] == -1) { *p = 1; *q = 6; return 1; } if (QQBAR_COEFFS(x)[1] == 2 && QQBAR_COEFFS(x)[0] == 1) { *p = -1; *q = 6; return 1; } return 0; } else if (deg == 2) { fmpz a, b, c; a = QQBAR_COEFFS(x)[0]; b = QQBAR_COEFFS(x)[1]; c = QQBAR_COEFFS(x)[2]; if (a == -3 && b == 0 && c == 4) { *p = qqbar_sgn_re(x); *q = 3; return 1; } if (a == -1 && b == 0 && c == 2) { *p = qqbar_sgn_re(x); *q = 4; return 1; } if (a == -1 && b == 2 && c == 4) { *p = (qqbar_sgn_re(x) == 1) ? 1 : -3; *q = 10; return 1; } if (a == -1 && b == -2 && c == 4) { *p = (qqbar_sgn_re(x) == 1) ? 3 : -1; *q = 10; return 1; } return 0; } else if (!qqbar_is_real(x)) { return 0; } else { slong degq; slong prec; arb_t z, pi; int res; prec = 64; /* More than enough -- the fractions will only ever be tiny */ res = 0; arb_init(z); arb_init(pi); qqbar_get_arb(z, x, prec); if (arf_cmpabs_2exp_si(arb_midref(z), 0) < 0 && arf_cmpabs_2exp_si(arb_midref(z), -20) > 0) { arb_asin(z, z, prec); arb_const_pi(pi, prec); arb_div(z, z, pi, prec); best_rational_fast(p, q, arf_get_d(arb_midref(z), ARF_RND_NEAR), 1000000); arb_mul_ui(z, z, *q, prec); if (arb_contains_si(z, *p)) { if ((*q) % 2 == 1 || (*q) % 4 == 0) degq = n_euler_phi(*q); else degq = n_euler_phi(*q) / 2; if (deg == degq) { qqbar_t v; qqbar_init(v); qqbar_sin_pi(v, *p, *q); res = qqbar_equal(v, x); qqbar_clear(v); } } } arb_clear(z); arb_clear(pi); return res; } } flint-3.1.3/src/qqbar/atan_pi.c000066400000000000000000000117311461254215100163120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "qqbar.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define floor __builtin_floor #else # include #endif void best_rational_fast(slong * p, ulong * q, double x, slong N) { slong a, b, c, d; double m, t, u, eps; if (x > 1.0 || x < 0.0) { double n = floor(x); best_rational_fast(p, q, x - n, N); *p = *p + n * (*q); return; } a = 0; b = 1; c = 1; d = 1; eps = 0.1 / N; if (fabs(x) < eps) { *p = 0; *q = 1; return; } while (b <= N && d <= N) { m = (a + c) / ((double) (b + d)); if (fabs(m - x) < eps) { if (b + d <= N) { *p = a + c; *q = b + d; } else if (d > b) { *p = c; *q = d; } else { *p = a; *q = b; } return; } else { t = a + c; u = b + d; if (x > m) { a = t; b = u; } else { c = t; d = u; } } } if (b > N) { *p = c; *q = d; } else { *p = a; *q = b; } } int qqbar_atan_pi(slong * p, ulong * q, const qqbar_t x) { slong deg = qqbar_degree(x); *p = 0; *q = 1; if (deg == 1) { if (qqbar_is_zero(x)) { *p = 0; *q = 1; return 1; } if (qqbar_is_one(x)) { *p = 1; *q = 4; return 1; } if (qqbar_is_neg_one(x)) { *p = -1; *q = 4; return 1; } return 0; } else if (deg == 2) { fmpz a, b, c; a = QQBAR_COEFFS(x)[0]; b = QQBAR_COEFFS(x)[1]; c = QQBAR_COEFFS(x)[2]; if (a == -3 && b == 0 && c == 1) { *p = qqbar_sgn_re(x); *q = 3; return 1; } if (a == -1 && b == 0 && c == 3) { *p = qqbar_sgn_re(x); *q = 6; return 1; } if (a == -1 && b == 2 && c == 1) { *p = (qqbar_sgn_re(x) == 1) ? 1 : -3; *q = 8; return 1; } if (a == -1 && b == -2 && c == 1) { *p = (qqbar_sgn_re(x) == 1) ? 3 : -1; *q = 8; return 1; } if (a == 1 && b == -4 && c == 1) { /* root is ~0.267 or ~3.73 -- accuracy should not be that bad */ if (arb_contains_si(acb_realref(QQBAR_ENCLOSURE(x)), 1)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); *p = (arf_cmpabs_2exp_si(arb_midref(acb_realref(QQBAR_ENCLOSURE(x))), 0) < 0) ? 1 : 5; *q = 12; return 1; } if (a == 1 && b == 4 && c == 1) { if (arb_contains_si(acb_realref(QQBAR_ENCLOSURE(x)), -1)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); *p = (arf_cmpabs_2exp_si(arb_midref(acb_realref(QQBAR_ENCLOSURE(x))), 0) < 0) ? -1 : -5; *q = 12; return 1; } return 0; } else if ((deg % 2 != 0) || !qqbar_is_real(x)) { return 0; } else { slong degq; slong prec; arb_t z, pi; int res; prec = 64; /* More than enough -- the fractions will only ever be tiny */ res = 0; arb_init(z); arb_init(pi); qqbar_get_arb(z, x, prec); if (arf_cmpabs_2exp_si(arb_midref(z), 20) < 0 && arf_cmpabs_2exp_si(arb_midref(z), -20) > 0) { arb_atan(z, z, prec); arb_const_pi(pi, prec); arb_div(z, z, pi, prec); best_rational_fast(p, q, arf_get_d(arb_midref(z), ARF_RND_NEAR), 1000000); arb_mul_ui(z, z, *q, prec); if (arb_contains_si(z, *p)) { if ((*q) % 4 == 0) degq = n_euler_phi(*q) / 2; else degq = n_euler_phi(*q); if (deg == degq) { qqbar_t v; qqbar_init(v); qqbar_tan_pi(v, *p, *q); res = qqbar_equal(v, x); qqbar_clear(v); } } } arb_clear(z); arb_clear(pi); return res; } } flint-3.1.3/src/qqbar/cache_enclosure.c000066400000000000000000000013241461254215100200160ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_cache_enclosure(qqbar_t res, slong prec) { acb_t t; slong want_prec; want_prec = FLINT_MAX(QQBAR_DEFAULT_PREC, prec) * 1.1 + 32; acb_init(t); qqbar_get_acb(t, res, want_prec); if (acb_contains(QQBAR_ENCLOSURE(res), t)) acb_swap(QQBAR_ENCLOSURE(res), t); acb_clear(t); } flint-3.1.3/src/qqbar/ceil.c000066400000000000000000000040231461254215100156070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_ceil(fmpz_t res, const qqbar_t x) { if (qqbar_is_rational(x)) { fmpz_fdiv_q(res, QQBAR_COEFFS(x), QQBAR_COEFFS(x) + 1); fmpz_neg(res, res); } else { arb_t v; arb_init(v); arb_ceil(v, acb_realref(QQBAR_ENCLOSURE(x)), QQBAR_DEFAULT_PREC); if (!arb_get_unique_fmpz(res, v)) { mag_t t; slong size, prec; acb_t z; mag_init(t); acb_init(z); acb_get_mag(t, QQBAR_ENCLOSURE(x)); if (mag_cmp_2exp_si(t, 0) < 0) mag_one(t); size = *MAG_EXPREF(t); prec = FLINT_MAX(QQBAR_DEFAULT_PREC * 2, 2 * size + 32); acb_set(z, QQBAR_ENCLOSURE(x)); _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); arb_ceil(v, acb_realref(z), prec); /* Do an exact computation */ if (!arb_get_unique_fmpz(res, v)) { qqbar_t u; qqbar_init(u); arb_set_d(v, -0.5); arb_add(v, v, acb_realref(z), prec); arb_ceil(v, v, prec); if (!arb_get_unique_fmpz(res, v)) { flint_throw(FLINT_ERROR, "qqbar_ceil: either ceil(x) or ceil(x-1/2) should evaluate numerically\n"); } qqbar_set_fmpz(u, res); qqbar_sub(u, x, u); if (qqbar_sgn_re(u) > 0) fmpz_add_ui(res, res, 1); qqbar_clear(u); } mag_clear(t); acb_clear(z); } arb_clear(v); } } flint-3.1.3/src/qqbar/clear.c000066400000000000000000000010271461254215100157620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_clear(qqbar_t res) { fmpz_poly_clear(QQBAR_POLY(res)); acb_clear(QQBAR_ENCLOSURE(res)); } flint-3.1.3/src/qqbar/cmp_im.c000066400000000000000000000036431461254215100161460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_cmp_im(const qqbar_t x, const qqbar_t y) { slong prec; acb_t z1, z2; int res; if (!arb_overlaps(acb_imagref(QQBAR_ENCLOSURE(x)), acb_imagref(QQBAR_ENCLOSURE(y)))) { return arf_cmp(arb_midref(acb_imagref(QQBAR_ENCLOSURE(x))), arb_midref(acb_imagref(QQBAR_ENCLOSURE(y)))); } if (qqbar_sgn_im(y) == 0) return qqbar_sgn_im(x); if (qqbar_sgn_im(x) == 0) return -qqbar_sgn_im(y); if (qqbar_equal(x, y)) return 0; { qqbar_t t; qqbar_init(t); qqbar_neg(t, y); qqbar_conj(t, t); res = qqbar_equal(x, t); qqbar_clear(t); if (res == 1) return 0; } acb_init(z1); acb_init(z2); acb_set(z1, QQBAR_ENCLOSURE(x)); acb_set(z2, QQBAR_ENCLOSURE(y)); res = 0; for (prec = QQBAR_DEFAULT_PREC; ; prec *= 2) { _qqbar_enclosure_raw(z1, QQBAR_POLY(x), z1, prec); _qqbar_enclosure_raw(z2, QQBAR_POLY(y), z2, prec); if (!arb_overlaps(acb_imagref(z1), acb_imagref(z2))) { res = arf_cmp(arb_midref(acb_imagref(z1)), arb_midref(acb_imagref(z2))); break; } /* Force an exact computation (may be slow) */ if (prec >= 4 * QQBAR_DEFAULT_PREC) { qqbar_t t; qqbar_init(t); qqbar_sub(t, x, y); res = qqbar_sgn_im(t); qqbar_clear(t); break; } } acb_clear(z1); acb_clear(z2); return res; } flint-3.1.3/src/qqbar/cmp_re.c000066400000000000000000000060311461254215100161410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_poly.h" #include "qqbar.h" int qqbar_cmp_re(const qqbar_t x, const qqbar_t y) { slong prec; acb_t z1, z2; int res, both_real; if (!arb_overlaps(acb_realref(QQBAR_ENCLOSURE(x)), acb_realref(QQBAR_ENCLOSURE(y)))) { return arf_cmp(arb_midref(acb_realref(QQBAR_ENCLOSURE(x))), arb_midref(acb_realref(QQBAR_ENCLOSURE(y)))); } if (qqbar_sgn_re(y) == 0) return qqbar_sgn_re(x); if (qqbar_sgn_re(x) == 0) return -qqbar_sgn_re(y); if (qqbar_degree(x) == 1 && qqbar_degree(y) == 1) { /* Reversed order since the signs are reversed */ return _fmpq_cmp(QQBAR_COEFFS(y), QQBAR_COEFFS(y) + 1, QQBAR_COEFFS(x), QQBAR_COEFFS(x) + 1); } /* Likely complex conjugates */ if (fmpz_poly_equal(QQBAR_POLY(x), QQBAR_POLY(y))) { qqbar_t t; /* Complex conjugate quadratics */ if (qqbar_degree(x) == 2 && !arb_overlaps(acb_imagref(QQBAR_ENCLOSURE(x)), acb_imagref(QQBAR_ENCLOSURE(y)))) return 0; qqbar_init(t); qqbar_conj(t, y); res = qqbar_equal(x, t); qqbar_clear(t); if (res == 1) return 0; } /* Subtraction is a scalar operation and will be quick */ if ((qqbar_degree(x) == 1 || qqbar_degree(y) == 1)) { qqbar_t t; qqbar_init(t); qqbar_sub(t, x, y); res = qqbar_sgn_re(t); qqbar_clear(t); return res; } acb_init(z1); acb_init(z2); acb_set(z1, QQBAR_ENCLOSURE(x)); acb_set(z2, QQBAR_ENCLOSURE(y)); both_real = -1; res = 0; for (prec = QQBAR_DEFAULT_PREC; ; prec *= 2) { _qqbar_enclosure_raw(z1, QQBAR_POLY(x), z1, prec); _qqbar_enclosure_raw(z2, QQBAR_POLY(y), z2, prec); if (!arb_overlaps(acb_realref(z1), acb_realref(z2))) { res = arf_cmp(arb_midref(acb_realref(z1)), arb_midref(acb_realref(z2))); break; } if (both_real == -1) both_real = qqbar_is_real(x) && qqbar_is_real(y); /* Force an exact computation (may be slow) */ /* Todo: tune the cutoff based on degrees, bit sizes. */ /* Todo: use the improved closures we have computed. */ /* Todo: when is it better to compute and compare the real parts? */ if (!both_real && prec >= 4 * QQBAR_DEFAULT_PREC) { qqbar_t t; qqbar_init(t); qqbar_sub(t, x, y); res = qqbar_sgn_re(t); qqbar_clear(t); break; } } acb_clear(z1); acb_clear(z2); return res; } flint-3.1.3/src/qqbar/cmp_root_order.c000066400000000000000000000014151461254215100177120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_cmp_root_order(const qqbar_t x, const qqbar_t y) { int xreal, yreal, cmp; xreal = qqbar_is_real(x); yreal = qqbar_is_real(y); if (xreal != yreal) return xreal ? -1 : 1; cmp = qqbar_cmp_re(x, y); if (cmp != 0) return -cmp; cmp = qqbar_cmpabs_im(x, y); if (cmp != 0) return cmp; return qqbar_sgn_im(y); } flint-3.1.3/src/qqbar/cmpabs.c000066400000000000000000000035251461254215100161460ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_cmpabs(const qqbar_t x, const qqbar_t y) { slong prec; acb_t z1, z2; arb_t z3, z4; int res; if (qqbar_sgn_im(x) == 0 && qqbar_sgn_im(y) == 0) return qqbar_cmpabs_re(x, y); if (qqbar_sgn_re(x) == 0 && qqbar_sgn_re(y) == 0) return qqbar_cmpabs_im(x, y); { acb_init(z1); acb_init(z2); arb_init(z3); arb_init(z4); acb_set(z1, QQBAR_ENCLOSURE(x)); acb_set(z2, QQBAR_ENCLOSURE(y)); res = 0; for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z1, QQBAR_POLY(x), z1, prec); _qqbar_enclosure_raw(z2, QQBAR_POLY(y), z2, prec); acb_abs(z3, z1, prec); acb_abs(z4, z2, prec); if (!arb_overlaps(z3, z4)) { res = arf_cmpabs(arb_midref(z3), arb_midref(z4)); break; } /* Force an exact computation (may be slow) */ if (prec >= 4 * QQBAR_DEFAULT_PREC) { qqbar_t t, u; qqbar_init(t); qqbar_init(u); qqbar_abs2(t, x); qqbar_abs2(u, y); res = qqbar_cmp_re(t, u); qqbar_clear(t); qqbar_clear(u); break; } } acb_clear(z1); acb_clear(z2); arb_clear(z3); arb_clear(z4); } return res; } flint-3.1.3/src/qqbar/cmpabs_im.c000066400000000000000000000032001461254215100166210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" static int _arb_overlaps_abs(const arb_t x, const arb_t y) { arb_t t, u; *t = *x; *u = *y; if (arf_sgn(arb_midref(t)) < 0) ARF_NEG(arb_midref(t)); if (arf_sgn(arb_midref(u)) < 0) ARF_NEG(arb_midref(u)); return arb_overlaps(t, u); } int qqbar_cmpabs_im(const qqbar_t x, const qqbar_t y) { int sx, sy; if (!_arb_overlaps_abs(acb_imagref(QQBAR_ENCLOSURE(x)), acb_imagref(QQBAR_ENCLOSURE(y)))) { return arf_cmpabs(arb_midref(acb_imagref(QQBAR_ENCLOSURE(x))), arb_midref(acb_imagref(QQBAR_ENCLOSURE(y)))); } sx = qqbar_sgn_im(x); sy = qqbar_sgn_im(y); if (sx == 0 && sy == 0) return 0; if (sy == 0 && sx != 0) return 1; if (sx == 0 && sy != 0) return -1; if (sx > 0 && sy > 0) return qqbar_cmp_im(x, y); if (sx < 0 && sy < 0) return -qqbar_cmp_im(x, y); /* opposite signs */ { int res; qqbar_t t; qqbar_init(t); if (sx > 0) { qqbar_neg(t, y); res = qqbar_cmp_im(x, t); } else { qqbar_neg(t, x); res = qqbar_cmp_im(t, y); } qqbar_clear(t); return res; } } flint-3.1.3/src/qqbar/cmpabs_re.c000066400000000000000000000032001461254215100166220ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" static int _arb_overlaps_abs(const arb_t x, const arb_t y) { arb_t t, u; *t = *x; *u = *y; if (arf_sgn(arb_midref(t)) < 0) ARF_NEG(arb_midref(t)); if (arf_sgn(arb_midref(u)) < 0) ARF_NEG(arb_midref(u)); return arb_overlaps(t, u); } int qqbar_cmpabs_re(const qqbar_t x, const qqbar_t y) { int sx, sy; if (!_arb_overlaps_abs(acb_realref(QQBAR_ENCLOSURE(x)), acb_realref(QQBAR_ENCLOSURE(y)))) { return arf_cmpabs(arb_midref(acb_realref(QQBAR_ENCLOSURE(x))), arb_midref(acb_realref(QQBAR_ENCLOSURE(y)))); } sx = qqbar_sgn_re(x); sy = qqbar_sgn_re(y); if (sx == 0 && sy == 0) return 0; if (sy == 0 && sx != 0) return 1; if (sx == 0 && sy != 0) return -1; if (sx > 0 && sy > 0) return qqbar_cmp_re(x, y); if (sx < 0 && sy < 0) return -qqbar_cmp_re(x, y); /* opposite signs */ { int res; qqbar_t t; qqbar_init(t); if (sx > 0) { qqbar_neg(t, y); res = qqbar_cmp_re(x, t); } else { qqbar_neg(t, x); res = qqbar_cmp_re(t, y); } qqbar_clear(t); return res; } } flint-3.1.3/src/qqbar/composed_op.c000066400000000000000000000214531461254215100172100ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" #include "fmpq_poly.h" #include "arb_fmpz_poly.h" #include "qqbar.h" #define OP_ADD 0 #define OP_SUB 1 #define OP_MUL 2 #define OP_DIV 3 static void fmpq_poly_hadamard_product(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2) { slong i, len; len = FLINT_MIN(fmpq_poly_length(poly1), fmpq_poly_length(poly2)); fmpq_poly_fit_length(res, len); for (i = 0; i < len; i++) fmpz_mul(res->coeffs + i, poly1->coeffs + i, poly2->coeffs + i); fmpz_mul(res->den, poly1->den, poly2->den); _fmpq_poly_set_length(res, len); _fmpq_poly_canonicalise(res->coeffs, res->den, len); } static void fmpq_poly_borel_transform(fmpq_poly_t res, const fmpq_poly_t poly) { slong i, len; len = fmpq_poly_length(poly); if (len <= 2) { fmpq_poly_set(res, poly); } else { fmpz_t c; fmpz_init(c); fmpz_one(c); fmpq_poly_fit_length(res, len); for (i = len - 1; i >= 0; i--) { fmpz_mul(res->coeffs + i, poly->coeffs + i, c); if (i > 1) fmpz_mul_ui(c, c, i); } fmpz_mul(fmpq_poly_denref(res), fmpq_poly_denref(poly), c); _fmpq_poly_set_length(res, len); _fmpq_poly_canonicalise(res->coeffs, res->den, len); fmpz_clear(c); } } static void fmpq_poly_inv_borel_transform(fmpq_poly_t res, const fmpq_poly_t poly) { slong i, len; len = fmpq_poly_length(poly); if (len <= 2) { fmpq_poly_set(res, poly); } else { fmpz_t c; fmpz_init(c); fmpz_one(c); fmpq_poly_fit_length(res, len); fmpz_set(fmpq_poly_denref(res), fmpq_poly_denref(poly)); fmpz_set(res->coeffs, poly->coeffs); fmpz_set(res->coeffs + 1, poly->coeffs + 1); for (i = 2; i < len; i++) { fmpz_mul_ui(c, c, i); fmpz_mul(res->coeffs + i, poly->coeffs + i, c); } _fmpq_poly_set_length(res, len); _fmpq_poly_canonicalise(res->coeffs, res->den, len); fmpz_clear(c); } } void qqbar_fmpz_poly_composed_op(fmpz_poly_t res, const fmpz_poly_t A, const fmpz_poly_t B, int op) { slong d1, d2, n, i; fmpq_poly_t P1, P2, P1rev, P1drev, P2rev, P2drev; d1 = fmpz_poly_degree(A); d2 = fmpz_poly_degree(B); if (d1 <= 0 || d2 <= 0) { flint_throw(FLINT_ERROR, "composed_op: inputs must not be constants\n"); } n = d1 * d2 + 1; fmpq_poly_init(P1); fmpq_poly_init(P2); fmpq_poly_init(P1rev); fmpq_poly_init(P1drev); fmpq_poly_init(P2rev); fmpq_poly_init(P2drev); fmpq_poly_set_fmpz_poly(P1, A); fmpq_poly_set_fmpz_poly(P2, B); if (op == OP_DIV) { if (fmpz_is_zero(P2->coeffs)) { flint_throw(FLINT_ERROR, "composed_op: division by zero\n"); } fmpq_poly_reverse(P2, P2, d2 + 1); } if (op == OP_SUB) for (i = 1; i <= d2; i += 2) fmpz_neg(P2->coeffs + i, P2->coeffs + i); fmpq_poly_reverse(P1rev, P1, d1 + 1); fmpq_poly_derivative(P1drev, P1); fmpq_poly_reverse(P1drev, P1drev, d1); fmpq_poly_reverse(P2rev, P2, d2 + 1); fmpq_poly_derivative(P2drev, P2); fmpq_poly_reverse(P2drev, P2drev, d2); fmpq_poly_div_series(P1, P1drev, P1rev, n); fmpq_poly_div_series(P2, P2drev, P2rev, n); if (op == OP_MUL || op == OP_DIV) { fmpq_poly_hadamard_product(P1, P1, P2); fmpq_poly_shift_right(P1, P1, 1); fmpq_poly_neg(P1, P1); fmpq_poly_integral(P1, P1); } else { fmpq_poly_borel_transform(P1, P1); fmpq_poly_borel_transform(P2, P2); fmpq_poly_mullow(P1, P1, P2, n); fmpq_poly_shift_right(P1, P1, 1); fmpq_poly_inv_borel_transform(P1, P1); fmpq_poly_neg(P1, P1); fmpq_poly_shift_left(P1, P1, 1); } fmpq_poly_exp_series(P1, P1, n); fmpq_poly_reverse(P1, P1, n); fmpq_poly_get_numerator(res, P1); fmpq_poly_clear(P1); fmpq_poly_clear(P2); fmpq_poly_clear(P1rev); fmpq_poly_clear(P1drev); fmpq_poly_clear(P2rev); fmpq_poly_clear(P2drev); } #define TIMING 0 #if TIMING #include "profiler.h" #endif void qqbar_binary_op_without_guess(qqbar_t res, const qqbar_t x, const qqbar_t y, int op) { slong i, prec, found; fmpz_poly_t H; fmpz_poly_factor_t fac; acb_t z1, z2, w, t; fmpz_poly_init(H); fmpz_poly_factor_init(fac); acb_init(z1); acb_init(z2); acb_init(w); acb_init(t); /* flint_printf("BEGIN COMPOSED OP %wd %wd %wd %wd\n", fmpz_poly_degree(QQBAR_POLY(x)), fmpz_poly_max_bits(QQBAR_POLY(x)), fmpz_poly_degree(QQBAR_POLY(y)), fmpz_poly_max_bits(QQBAR_POLY(y))); */ #if TIMING { flint_printf("composed op: "); TIMEIT_ONCE_START qqbar_fmpz_poly_composed_op(H, QQBAR_POLY(x), QQBAR_POLY(y), op); TIMEIT_ONCE_STOP flint_printf("factoring: "); TIMEIT_ONCE_START fmpz_poly_factor(fac, H); TIMEIT_ONCE_STOP } #else qqbar_fmpz_poly_composed_op(H, QQBAR_POLY(x), QQBAR_POLY(y), op); fmpz_poly_factor(fac, H); #endif acb_set(z1, QQBAR_ENCLOSURE(x)); acb_set(z2, QQBAR_ENCLOSURE(y)); /* qqbar_print(x); printf("\n"); qqbar_print(y); printf("\n"); */ for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { /* printf("binop %ld\n", prec); */ _qqbar_enclosure_raw(z1, QQBAR_POLY(x), z1, prec); _qqbar_enclosure_raw(z2, QQBAR_POLY(y), z2, prec); /* acb_printd(z1, 30); printf("\n"); acb_printd(z2, 30); printf("\n"); */ if (op == 0) acb_add(w, z1, z2, prec); else if (op == 1) acb_sub(w, z1, z2, prec); else if (op == 2) acb_mul(w, z1, z2, prec); else acb_div(w, z1, z2, prec); /* Look for potential roots -- we want exactly one */ found = -1; for (i = 0; i < fac->num && found != -2; i++) { arb_fmpz_poly_evaluate_acb(t, fac->p + i, w, prec); if (acb_contains_zero(t)) { if (found == -1) found = i; else found = -2; } } /* printf("found: %ld\n", found); */ /* Check if the enclosure is good enough */ if (found >= 0) { if (_qqbar_validate_uniqueness(t, fac->p + found, w, 2 * prec)) { fmpz_poly_set(QQBAR_POLY(res), fac->p + found); acb_set(QQBAR_ENCLOSURE(res), t); break; } } } fmpz_poly_clear(H); fmpz_poly_factor_clear(fac); acb_clear(z1); acb_clear(z2); acb_clear(w); acb_clear(t); } void qqbar_binary_op(qqbar_t res, const qqbar_t x, const qqbar_t y, int op) { slong dx, dy; dx = qqbar_degree(x); dy = qqbar_degree(y); /* Guess and verify rational result; this could be generalized to higher degree results. */ if (dx >= 4 && dy >= 4 && dx == dy) { qqbar_t t, u; acb_t z; slong prec; int found; found = 0; prec = QQBAR_DEFAULT_PREC; /* Could be set dynamically (with recomputation...) */ qqbar_init(t); qqbar_init(u); acb_init(z); if (op == 0) acb_add(z, QQBAR_ENCLOSURE(x), QQBAR_ENCLOSURE(y), prec); else if (op == 1) acb_sub(z, QQBAR_ENCLOSURE(x), QQBAR_ENCLOSURE(y), prec); else if (op == 2) acb_mul(z, QQBAR_ENCLOSURE(x), QQBAR_ENCLOSURE(y), prec); else if (op == 3) acb_div(z, QQBAR_ENCLOSURE(x), QQBAR_ENCLOSURE(y), prec); if (qqbar_guess(t, z, 1, prec, 0, prec)) { /* x + y = t <=> x = t - y */ /* x - y = t <=> x = t + y */ /* x * y = t <=> x = t / y */ /* x / y = t <=> x = t * y */ if (op == 0) qqbar_sub(u, t, y); else if (op == 1) qqbar_add(u, t, y); else if (op == 2) qqbar_div(u, t, y); else if (op == 3) qqbar_mul(u, t, y); if (qqbar_equal(x, u)) { qqbar_swap(res, t); found = 1; } } qqbar_clear(t); qqbar_clear(u); acb_clear(z); if (found) return; } qqbar_binary_op_without_guess(res, x, y, op); } flint-3.1.3/src/qqbar/conj.c000066400000000000000000000011071461254215100156240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_conj(qqbar_t res, const qqbar_t x) { fmpz_poly_set(QQBAR_POLY(res), QQBAR_POLY(x)); acb_conj(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(x)); } flint-3.1.3/src/qqbar/conjugates.c000066400000000000000000000011331461254215100170340ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_conjugates(qqbar_ptr res, const qqbar_t x) { if (qqbar_degree(x) == 1) qqbar_set(res, x); else qqbar_roots_fmpz_poly(res, QQBAR_POLY(x), QQBAR_ROOTS_IRREDUCIBLE); } flint-3.1.3/src/qqbar/cos_pi.c000066400000000000000000000035321461254215100161530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_poly.h" #include "qqbar.h" void qqbar_cos_pi(qqbar_t res, slong p, ulong q) { fmpq_t t; ulong a, b; slong prec; fmpq_init(t); if (q == 0) { flint_throw(FLINT_ERROR, "qqbar_cos_pi: q = 0\n"); } fmpq_set_si(t, p, q); fmpq_div_2exp(t, t, 1); fmpz_fdiv_r(fmpq_numref(t), fmpq_numref(t), fmpq_denref(t)); a = fmpz_get_ui(fmpq_numref(t)); b = fmpz_get_ui(fmpq_denref(t)); if (a == 0) { qqbar_one(res); } else if (b == 2) { qqbar_set_si(res, -1); } else if (b == 3) { qqbar_one(res); qqbar_neg(res, res); qqbar_mul_2exp_si(res, res, -1); } else if (b == 4) { qqbar_zero(res); } else if (b == 6) { qqbar_one(res); qqbar_mul_2exp_si(res, res, -1); } else { fmpz_poly_cos_minpoly(QQBAR_POLY(res), b); fmpq_mul_2exp(t, t, 1); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { arb_cos_pi_fmpq(acb_realref(QQBAR_ENCLOSURE(res)), t, prec); arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); acb_mul_2exp_si(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(res), 1); if (_qqbar_validate_uniqueness(QQBAR_ENCLOSURE(res), QQBAR_POLY(res), QQBAR_ENCLOSURE(res), prec * 2)) { break; } } qqbar_mul_2exp_si(res, res, -1); } fmpq_clear(t); } flint-3.1.3/src/qqbar/cot_pi.c000066400000000000000000000014271461254215100161550ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "qqbar.h" int qqbar_cot_pi(qqbar_t res, slong p, ulong q) { slong g; g = n_gcd(FLINT_ABS(p), q); if (g != 1) { p /= g; q /= g; } if (q == 1) { return 0; } else if (q == 2) { qqbar_zero(res); } else { qqbar_tan_pi(res, p, q); qqbar_inv(res, res); } return 1; } flint-3.1.3/src/qqbar/csc_pi.c000066400000000000000000000010711461254215100161330ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_csc_pi(qqbar_t res, slong p, ulong q) { qqbar_sin_pi(res, p, q); if (qqbar_is_zero(res)) return 0; qqbar_inv(res, res); return 1; } flint-3.1.3/src/qqbar/csgn.c000066400000000000000000000010271461254215100156260ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_csgn(const qqbar_t x) { int re = qqbar_sgn_re(x); if (re != 0) return re; return qqbar_sgn_im(x); } flint-3.1.3/src/qqbar/denominator.c000066400000000000000000000010011461254215100172030ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_denominator(fmpz_t res, const qqbar_t y) { fmpz_set(res, QQBAR_COEFFS(y) + qqbar_degree(y)); } flint-3.1.3/src/qqbar/div.c000066400000000000000000000075151461254215100154660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" #include "qqbar.h" void qqbar_div(qqbar_t res, const qqbar_t x, const qqbar_t y) { if (qqbar_is_zero(y)) { flint_throw(FLINT_ERROR, "qqbar_div: division by zero\n"); } else if (qqbar_is_zero(x)) { qqbar_zero(res); } else if (qqbar_is_one(x)) { qqbar_inv(res, y); } else if (qqbar_is_one(y)) { qqbar_set(res, x); } else if (qqbar_is_neg_one(x)) { qqbar_inv(res, y); qqbar_neg(res, res); } else if (qqbar_is_neg_one(y)) { qqbar_neg(res, x); } else if (qqbar_is_rational(y)) { fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); _qqbar_get_fmpq(c, a, y); qqbar_scalar_op(res, x, a, b, c); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } else if (qqbar_is_rational(x)) { fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); _qqbar_get_fmpq(a, c, x); qqbar_inv(res, y); qqbar_scalar_op(res, res, a, b, c); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } else if (_qqbar_fast_detect_simple_principal_surd(x) && _qqbar_fast_detect_simple_principal_surd(y)) { /* (p/q)^(1/d) * (r/s)^(1/e) */ fmpq_t t, u; ulong d, e, f, g; d = qqbar_degree(x); e = qqbar_degree(y); g = n_gcd(d, e); f = (d / g) * e; fmpq_init(t); fmpq_init(u); fmpz_neg(fmpq_numref(t), QQBAR_COEFFS(x)); fmpz_set(fmpq_denref(t), QQBAR_COEFFS(x) + d); fmpz_neg(fmpq_numref(u), QQBAR_COEFFS(y)); fmpz_set(fmpq_denref(u), QQBAR_COEFFS(y) + e); fmpq_pow_si(t, t, e / g); fmpq_pow_si(u, u, d / g); fmpq_div(t, t, u); /* todo: recycle the existing enclosures instead of computing a numerical f-th root from scratch */ qqbar_fmpq_root_ui(res, t, f); fmpq_clear(t); fmpq_clear(u); } else { qqbar_binary_op(res, x, y, 3); } } void qqbar_div_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpq(t, y); qqbar_div(res, x, t); qqbar_clear(t); } void qqbar_div_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpz(t, y); qqbar_div(res, x, t); qqbar_clear(t); } void qqbar_div_ui(qqbar_t res, const qqbar_t x, ulong y) { qqbar_t t; qqbar_init(t); qqbar_set_ui(t, y); qqbar_div(res, x, t); qqbar_clear(t); } void qqbar_div_si(qqbar_t res, const qqbar_t x, slong y) { qqbar_t t; qqbar_init(t); qqbar_set_si(t, y); qqbar_div(res, x, t); qqbar_clear(t); } void qqbar_fmpq_div(qqbar_t res, const fmpq_t x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpq(t, x); qqbar_div(res, t, y); qqbar_clear(t); } void qqbar_fmpz_div(qqbar_t res, const fmpz_t x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpz(t, x); qqbar_div(res, t, y); qqbar_clear(t); } void qqbar_ui_div(qqbar_t res, ulong x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_ui(t, x); qqbar_div(res, t, y); qqbar_clear(t); } void qqbar_si_div(qqbar_t res, slong x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_si(t, x); qqbar_div(res, t, y); qqbar_clear(t); } flint-3.1.3/src/qqbar/eigenvalues_fmpq_mat.c000066400000000000000000000012371461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "fmpq_mat.h" #include "qqbar.h" void qqbar_eigenvalues_fmpq_mat(qqbar_ptr res, const fmpq_mat_t mat, int flags) { fmpq_poly_t t; fmpq_poly_init(t); fmpq_mat_charpoly(t, mat); qqbar_roots_fmpq_poly(res, t, flags); fmpq_poly_clear(t); } flint-3.1.3/src/qqbar/eigenvalues_fmpz_mat.c000066400000000000000000000012371461254215100211030ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz_poly.h" #include "qqbar.h" void qqbar_eigenvalues_fmpz_mat(qqbar_ptr res, const fmpz_mat_t mat, int flags) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_mat_charpoly(t, mat); qqbar_roots_fmpz_poly(res, t, flags); fmpz_poly_clear(t); } flint-3.1.3/src/qqbar/enclosure_raw.c000066400000000000000000000074701461254215100175540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_fmpz_poly.h" #include "qqbar.h" void _qqbar_enclosure_raw(acb_t res, const fmpz_poly_t poly, const acb_t zin, slong prec) { slong d, orig_prec, step, acc; fmpz_poly_t deriv; acb_t z, zmid, t, u; if (acb_rel_accuracy_bits(zin) >= prec - 3) { acb_set(res, zin); return; } d = fmpz_poly_degree(poly); if (d == 1) { arb_set_fmpz(acb_realref(res), poly->coeffs); arb_div_fmpz(acb_realref(res), acb_realref(res), poly->coeffs + 1, prec); arb_neg(acb_realref(res), acb_realref(res)); arb_zero(acb_imagref(res)); return; } orig_prec = prec; acc = acb_rel_accuracy_bits(zin); prec = FLINT_MAX(acc, 32) + 10; fmpz_poly_init(deriv); fmpz_poly_derivative(deriv, poly); acb_init(z); acb_init(zmid); acb_init(t); acb_init(u); acb_set(z, zin); for (step = 0; ; step++) { /* printf("trying %ld, %ld\n", step, prec); acb_printn(z, prec, ARB_STR_CONDENSE * 10); printf("\n"); */ if (step > 40 || prec > 1000000000) { flint_throw(FLINT_ERROR, "qqbar_enclosure_raw: root refinement not converging\n"); } prec *= 2; /* Interval Newton refinement */ acb_get_mid(zmid, z); arb_fmpz_poly_evaluate_acb(t, poly, zmid, prec); arb_fmpz_poly_evaluate_acb(u, deriv, z, prec); acb_div(t, t, u, prec); acb_sub(t, zmid, t, prec); if (acb_contains(z, t) && acb_rel_accuracy_bits(t) >= 1.1 * orig_prec) { acb_set(res, t); break; } if (acb_contains(z, t) && acb_rel_accuracy_bits(t) > 1.5 * acb_rel_accuracy_bits(z)) { /* Use refined value for next iteration */ acb_set(z, t); } else { /* Newton refinement seems to be converging too slowly -- force a slow recomputation of all roots (this could be improved...) */ acb_ptr roots; slong found, i; /* printf("recompute %ld %ld\n", d, prec); */ roots = _acb_vec_init(d); /* fmpz_poly_print(poly); printf("\n"); */ if (!fmpz_poly_is_squarefree(poly)) flint_throw(FLINT_ERROR, "(%s)\n", __func__); arb_fmpz_poly_complex_roots(roots, poly, 0, 2 * prec); /* Check for unique root */ found = -1; for (i = 0; i < d && found != -2; i++) { if (acb_overlaps(roots + i, z)) { if (found == -1) found = i; else found = -2; } } if (found >= 0) acb_set(t, roots + found); _acb_vec_clear(roots, d); if (found >= 0 && acb_rel_accuracy_bits(t) >= 1.1 * orig_prec) { acb_set(res, t); break; } if (found >= 0 && acb_rel_accuracy_bits(t) > 1.5 * acb_rel_accuracy_bits(z) + 1) { /* Use refined value for next iteration */ acb_set(z, t); } } } fmpz_poly_clear(deriv); acb_clear(z); acb_clear(zmid); acb_clear(t); acb_clear(u); } void qqbar_enclosure_raw(acb_t res, const qqbar_t x, slong prec) { _qqbar_enclosure_raw(res, QQBAR_POLY(x), QQBAR_ENCLOSURE(x), prec); } flint-3.1.3/src/qqbar/equal.c000066400000000000000000000031041461254215100160010ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" int qqbar_equal(const qqbar_t x, const qqbar_t y) { slong prec; acb_t z1, z2, z3; int res; if (x == y) return 1; if (!fmpz_poly_equal(QQBAR_POLY(x), QQBAR_POLY(y))) return 0; if (qqbar_degree(x) == 1) return 1; if (!acb_overlaps(QQBAR_ENCLOSURE(x), QQBAR_ENCLOSURE(y))) return 0; if (acb_contains(QQBAR_ENCLOSURE(x), QQBAR_ENCLOSURE(y))) return 1; if (acb_contains(QQBAR_ENCLOSURE(y), QQBAR_ENCLOSURE(x))) return 1; acb_init(z1); acb_init(z2); acb_init(z3); acb_set(z1, QQBAR_ENCLOSURE(x)); acb_set(z2, QQBAR_ENCLOSURE(y)); res = 0; for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z1, QQBAR_POLY(x), z1, prec); _qqbar_enclosure_raw(z2, QQBAR_POLY(y), z2, prec); if (!acb_overlaps(z1, z2)) { res = 0; break; } acb_union(z3, z1, z2, prec); if (_qqbar_validate_uniqueness(z3, QQBAR_POLY(x), z3, 2 * prec)) { res = 1; break; } } acb_clear(z1); acb_clear(z2); acb_clear(z3); return res; } flint-3.1.3/src/qqbar/equal_fmpq_poly_val.c000066400000000000000000000051371461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "arb_fmpz_poly.h" #include "qqbar.h" /* Algorithm based on Cohen section 4.5.1 */ /* C = A o P mod B */ /* todo: rem P by B initially if larger */ /* todo: brent-kung or something more clever */ void fmpq_poly_compose_fmpz_poly_mod_fmpz_poly(fmpq_poly_t C, const fmpz_poly_t A, const fmpq_poly_t P, const fmpz_poly_t B) { slong i, m; fmpq_poly_t B2; fmpq_poly_init(B2); fmpq_poly_set_fmpz_poly(B2, B); m = fmpz_poly_degree(A); fmpq_poly_set_fmpz(C, A->coeffs + m); for (i = m - 1; i >= 0; i--) { fmpq_poly_mul(C, C, P); fmpq_poly_add_fmpz(C, C, A->coeffs + i); fmpq_poly_rem(C, C, B2); } fmpq_poly_clear(B2); } int qqbar_equal_fmpq_poly_val(const qqbar_t x, const fmpq_poly_t f, const qqbar_t y) { slong prec; acb_t z1, z2, z3; fmpq_poly_t C; int res; /* todo: should this be used for f->length == 2 too? */ if (f->length <= 1 || qqbar_degree(y) == 1) { qqbar_t v; qqbar_init(v); qqbar_evaluate_fmpq_poly(v, f, y); res = qqbar_equal(v, x); qqbar_clear(v); return res; } acb_init(z1); acb_init(z2); acb_init(z3); fmpq_poly_init(C); acb_set(z1, QQBAR_ENCLOSURE(x)); acb_set(z2, QQBAR_ENCLOSURE(y)); res = 0; for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z1, QQBAR_POLY(x), z1, prec); _qqbar_enclosure_raw(z2, QQBAR_POLY(y), z2, prec); _arb_fmpz_poly_evaluate_acb(z3, f->coeffs, f->length, z2, 2 * prec); acb_div_fmpz(z3, z3, f->den, 2 * prec); if (!acb_overlaps(z1, z3)) { res = 0; break; } if (prec == QQBAR_DEFAULT_PREC / 2) { fmpq_poly_compose_fmpz_poly_mod_fmpz_poly(C, QQBAR_POLY(x), f, QQBAR_POLY(y)); if (!fmpq_poly_is_zero(C)) { res = 0; break; } } acb_union(z3, z1, z3, prec); if (_qqbar_validate_uniqueness(z3, QQBAR_POLY(x), z3, 2 * prec)) { res = 1; break; } } acb_clear(z1); acb_clear(z2); acb_clear(z3); fmpq_poly_clear(C); return res; } flint-3.1.3/src/qqbar/evaluate_fmpq_poly.c000066400000000000000000000113521461254215100205720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_mat.h" #include "fmpq_poly.h" #include "nf.h" #include "nf_elem.h" #include "arb_fmpz_poly.h" #include "qqbar.h" void _qqbar_evaluate_fmpq_poly(qqbar_t res, const fmpz * poly, const fmpz_t den, slong len, const qqbar_t x) { slong d = qqbar_degree(x); if (len == 0) { qqbar_zero(res); } else if (len == 1) { if (fmpz_is_one(den)) { qqbar_set_fmpz(res, poly); } else { fmpq_t t; fmpq_init(t); fmpq_set_fmpz_frac(t, poly, den); qqbar_set_fmpq(res, t); fmpq_clear(t); } } else if (qqbar_is_rational(x)) { fmpq_t t, u; fmpq_init(t); fmpq_init(u); qqbar_get_fmpq(u, x); _fmpq_poly_evaluate_fmpq(fmpq_numref(t), fmpq_denref(t), poly, den, len, fmpq_numref(u), fmpq_denref(u)); qqbar_set_fmpq(res, t); fmpq_clear(t); fmpq_clear(u); } else if (len == 2) { qqbar_scalar_op(res, x, poly + 1, poly, den); } else if (len > d) { fmpz * tmp; fmpz_t r, one; slong len2; tmp = _fmpz_vec_init(len); fmpz_init(r); fmpz_init(one); fmpz_one(one); _fmpq_poly_rem(tmp, r, poly, den, len, QQBAR_COEFFS(x), one, d + 1, NULL); len2 = d; while (len2 >= 1 && fmpz_is_zero(tmp + len2 - 1)) len2--; _qqbar_evaluate_fmpq_poly(res, tmp, r, len2, x); fmpz_clear(r); fmpz_clear(one); _fmpz_vec_clear(tmp, d); } else { fmpq_poly_t t, minpoly; nf_t nf; nf_elem_t elem; fmpq_mat_t mat; int is_power; /* todo: detect squaring. x^4, x^8, ...? */ /* todo: other special cases; deflation? */ is_power = _fmpz_vec_is_zero(poly, len - 1); /* nf_init wants an fmpq_poly_t, so mock up one */ t->coeffs = QQBAR_POLY(x)->coeffs; t->den[0] = 1; t->length = QQBAR_POLY(x)->length; t->alloc = QQBAR_POLY(x)->alloc; nf_init(nf, t); nf_elem_init(elem, nf); t->coeffs = (fmpz *) poly; t->length = len; t->den[0] = *den; t->alloc = len; nf_elem_set_fmpq_poly(elem, t, nf); fmpq_mat_init(mat, d, d); nf_elem_rep_mat(mat, elem, nf); fmpq_poly_init(minpoly); fmpq_mat_minpoly(minpoly, mat); fmpq_mat_clear(mat); { fmpz_poly_t A; acb_t z, t, w; slong prec; int pure_real, pure_imag; A->coeffs = minpoly->coeffs; A->length = minpoly->length; A->alloc = A->length; acb_init(z); acb_init(t); acb_init(w); acb_set(z, QQBAR_ENCLOSURE(x)); pure_real = (qqbar_sgn_im(x) == 0); pure_imag = (qqbar_sgn_re(x) == 0); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); if (pure_real) arb_zero(acb_imagref(z)); if (pure_imag) arb_zero(acb_realref(z)); if (is_power) { acb_pow_ui(w, z, len - 1, prec); if (!fmpz_is_one(poly + len - 1)) acb_mul_fmpz(w, w, poly + len - 1, prec); if (!fmpz_is_one(den)) acb_div_fmpz(w, w, den, prec); } else { _arb_fmpz_poly_evaluate_acb(w, poly, len, z, prec); if (!fmpz_is_one(den)) acb_div_fmpz(w, w, den, prec); } if (_qqbar_validate_uniqueness(t, A, w, 2 * prec)) { fmpz_poly_set(QQBAR_POLY(res), A); acb_set(QQBAR_ENCLOSURE(res), t); break; } } acb_clear(z); acb_clear(t); acb_clear(w); } fmpq_poly_clear(minpoly); nf_elem_clear(elem, nf); nf_clear(nf); } } void qqbar_evaluate_fmpq_poly(qqbar_t res, const fmpq_poly_t poly, const qqbar_t x) { _qqbar_evaluate_fmpq_poly(res, poly->coeffs, poly->den, poly->length, x); } flint-3.1.3/src/qqbar/evaluate_fmpz_mpoly.c000066400000000000000000000017461461254215100207660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz Copyright (C) 2020, 2024 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "fmpz_mpoly.h" #include "qqbar.h" #include "gr.h" #include "gr_generic.h" int qqbar_evaluate_fmpz_mpoly(qqbar_t res, const fmpz_mpoly_t f, qqbar_srcptr x, slong deg_limit, slong bits_limit, const fmpz_mpoly_ctx_t ctx) { gr_ctx_t QQbar; gr_ctx_init_complex_qqbar(QQbar); _gr_ctx_qqbar_set_limits(QQbar, deg_limit, bits_limit); if (f->length <= 1) return (gr_fmpz_mpoly_evaluate_iter(res, f, x, ctx, QQbar) == GR_SUCCESS); else return (gr_fmpz_mpoly_evaluate_horner(res, f, x, ctx, QQbar) == GR_SUCCESS); } flint-3.1.3/src/qqbar/evaluate_fmpz_poly.c000066400000000000000000000014541461254215100206050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_fmpz_poly.h" #include "qqbar.h" void _qqbar_evaluate_fmpz_poly(qqbar_t res, const fmpz * poly, slong len, const qqbar_t x) { fmpz_t den; fmpz_init(den); fmpz_one(den); _qqbar_evaluate_fmpq_poly(res, poly, den, len, x); fmpz_clear(den); } void qqbar_evaluate_fmpz_poly(qqbar_t res, const fmpz_poly_t poly, const qqbar_t x) { _qqbar_evaluate_fmpz_poly(res, poly->coeffs, poly->length, x); } flint-3.1.3/src/qqbar/exp_pi_i.c000066400000000000000000000007621461254215100164750ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_exp_pi_i(qqbar_t res, slong p, ulong q) { qqbar_root_of_unity(res, p, q * 2); } flint-3.1.3/src/qqbar/express_in_field.c000066400000000000000000000030431461254215100202160ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpq_poly.h" #include "qqbar.h" int qqbar_express_in_field(fmpq_poly_t res, const qqbar_t alpha, const qqbar_t x, slong max_bits, int flags, slong prec) { slong d, dx; acb_ptr vec; acb_t z; int found; d = qqbar_degree(alpha); dx = qqbar_degree(x); if (dx == 1) { fmpq_t t; fmpq_init(t); qqbar_get_fmpq(t, x); fmpq_poly_set_fmpq(res, t); fmpq_clear(t); return 1; } found = 0; if (d % dx != 0 || (qqbar_is_real(alpha) && !qqbar_is_real(x))) return 0; acb_init(z); vec = _acb_vec_init(d + 1); qqbar_get_acb(z, alpha, prec); _acb_vec_set_powers(vec, z, d, prec); qqbar_get_acb(vec + d, x, prec); fmpq_poly_fit_length(res, d + 1); if (_qqbar_acb_lindep(res->coeffs, vec, d + 1, 1, prec) && !fmpz_is_zero(res->coeffs + d)) { fmpz_neg(res->den, res->coeffs + d); _fmpq_poly_set_length(res, d); _fmpq_poly_normalise(res); fmpq_poly_canonicalise(res); found = qqbar_equal_fmpq_poly_val(x, res, alpha); } acb_clear(z); _acb_vec_clear(vec, d + 1); return found; } flint-3.1.3/src/qqbar/floor.c000066400000000000000000000040311461254215100160130ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_floor(fmpz_t res, const qqbar_t x) { if (qqbar_is_rational(x)) { fmpz_cdiv_q(res, QQBAR_COEFFS(x), QQBAR_COEFFS(x) + 1); fmpz_neg(res, res); } else { arb_t v; arb_init(v); arb_floor(v, acb_realref(QQBAR_ENCLOSURE(x)), QQBAR_DEFAULT_PREC); if (!arb_get_unique_fmpz(res, v)) { mag_t t; slong size, prec; acb_t z; mag_init(t); acb_init(z); acb_get_mag(t, QQBAR_ENCLOSURE(x)); if (mag_cmp_2exp_si(t, 0) < 0) mag_one(t); size = *MAG_EXPREF(t); prec = FLINT_MAX(QQBAR_DEFAULT_PREC * 2, 2 * size + 32); acb_set(z, QQBAR_ENCLOSURE(x)); _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); arb_floor(v, acb_realref(z), prec); /* Do an exact computation */ if (!arb_get_unique_fmpz(res, v)) { qqbar_t u; qqbar_init(u); arb_set_d(v, 0.5); arb_add(v, v, acb_realref(z), prec); arb_floor(v, v, prec); if (!arb_get_unique_fmpz(res, v)) { flint_throw(FLINT_ERROR, "qqbar_floor: either floor(x) or floor(x+1/2) should evaluate numerically\n"); } qqbar_set_fmpz(u, res); qqbar_sub(u, x, u); if (qqbar_sgn_re(u) < 0) fmpz_sub_ui(res, res, 1); qqbar_clear(u); } mag_clear(t); acb_clear(z); } arb_clear(v); } } flint-3.1.3/src/qqbar/fmpq_pow_si_ui.c000066400000000000000000000021301461254215100177100ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "qqbar.h" void qqbar_fmpq_pow_si_ui(qqbar_t res, const fmpq_t x, slong a, ulong b) { if (b == 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (a == 0) { qqbar_one(res); } else if (a == 1) { qqbar_fmpq_root_ui(res, x, b); } else if (fmpq_sgn(x) >= 0) { fmpq_t t; fmpq_init(t); fmpq_pow_si(t, x, a); qqbar_fmpq_root_ui(res, t, b); fmpq_clear(t); } else { qqbar_fmpq_root_ui(res, x, b); if (a > 0) { qqbar_pow_ui(res, res, a); } else { qqbar_inv(res, res); qqbar_pow_ui(res, res, -a); } } } flint-3.1.3/src/qqbar/fmpq_root_ui.c000066400000000000000000000070041461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_poly.h" #include "qqbar.h" static int check_root(fmpz_t p, const fmpz_t x, fmpz_t t, ulong d) { if (fmpz_is_one(x)) { fmpz_one(p); return 1; } else if (d == 2) { fmpz_sqrtrem(p, t, x); return fmpz_is_zero(t); } else { /* todo: need a rootrem function */ fmpz_root(p, x, d); fmpz_pow_ui(t, p, d); return fmpz_equal(t, x); } } void qqbar_fmpq_root_ui(qqbar_t res, const fmpq_t x, ulong b) { ulong d; fmpz_t p, q, t; if (b == 0) flint_throw(FLINT_ERROR, "(%s)\n", __func__); if (b == 1 || fmpq_is_zero(x) || fmpq_is_one(x)) { qqbar_set_fmpq(res, x); return; } if (b == 2) { if (fmpz_is_square(fmpq_numref(x)) && fmpz_is_square(fmpq_denref(x))) { fmpz_poly_fit_length(QQBAR_POLY(res), 2); _fmpz_poly_set_length(QQBAR_POLY(res), 2); fmpz_sqrt(QQBAR_COEFFS(res) + 0, fmpq_numref(x)); fmpz_neg(QQBAR_COEFFS(res) + 0, QQBAR_COEFFS(res) + 0); fmpz_sqrt(QQBAR_COEFFS(res) + 1, fmpq_denref(x)); acb_set_fmpz(QQBAR_ENCLOSURE(res), QQBAR_COEFFS(res) + 0); acb_neg(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(res)); acb_div_fmpz(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(res), QQBAR_COEFFS(res) + 1, QQBAR_DEFAULT_PREC); } else { fmpz_poly_fit_length(QQBAR_POLY(res), 3); _fmpz_poly_set_length(QQBAR_POLY(res), 3); fmpz_set(QQBAR_COEFFS(res) + 0, fmpq_numref(x)); fmpz_neg(QQBAR_COEFFS(res) + 0, QQBAR_COEFFS(res) + 0); fmpz_zero(QQBAR_COEFFS(res) + 1); fmpz_set(QQBAR_COEFFS(res) + 2, fmpq_denref(x)); acb_set_fmpq(QQBAR_ENCLOSURE(res), x, QQBAR_DEFAULT_PREC); acb_sqrt(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(res), QQBAR_DEFAULT_PREC); } return; } if (fmpq_sgn(x) < 0) { qqbar_set_fmpq(res, x); qqbar_root_ui(res, res, b); return; } fmpz_init(p); fmpz_init(q); fmpz_init(t); for (d = b; d >= 1; d--) { if (d == 1) { fmpz_set(p, fmpq_numref(x)); fmpz_set(q, fmpq_denref(x)); } else if (b % d == 0) { if (check_root(p, fmpq_numref(x), t, d) && check_root(q, fmpq_denref(x), t, d)) { b /= d; break; } } } fmpz_poly_set_fmpz(QQBAR_POLY(res), p); fmpz_poly_neg(QQBAR_POLY(res), QQBAR_POLY(res)); fmpz_poly_set_coeff_fmpz(QQBAR_POLY(res), b, q); arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); arb_set_fmpz(acb_realref(QQBAR_ENCLOSURE(res)), p); arb_div_fmpz(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), q, QQBAR_DEFAULT_PREC); if (b != 1) arb_root_ui(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), b, QQBAR_DEFAULT_PREC); if (!arb_is_positive(acb_realref(QQBAR_ENCLOSURE(res)))) flint_throw(FLINT_ERROR, "(%s)\n", __func__); fmpz_clear(p); fmpz_clear(q); fmpz_clear(t); } flint-3.1.3/src/qqbar/get_acb.c000066400000000000000000000052171461254215100162650ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" /* Todo: could special-case quadratics, in particular Gaussian rationals */ void qqbar_get_acb(acb_t res, const qqbar_t x, slong prec) { if (qqbar_degree(x) == 1) { arb_set_fmpz(acb_realref(res), QQBAR_COEFFS(x)); arb_div_fmpz(acb_realref(res), acb_realref(res), QQBAR_COEFFS(x) + 1, prec); arb_neg(acb_realref(res), acb_realref(res)); arb_zero(acb_imagref(res)); } else { arb_t t; fmpz_t n; slong wp; int imag_zero, real_zero; imag_zero = (qqbar_sgn_im(x) == 0); real_zero = (qqbar_sgn_re(x) == 0); acb_set(res, QQBAR_ENCLOSURE(x)); for (wp = prec + 30; ; wp *= 2) { _qqbar_enclosure_raw(res, QQBAR_POLY(x), res, wp); if (imag_zero) arb_zero(acb_imagref(res)); if (real_zero) arb_zero(acb_realref(res)); if (arb_rel_accuracy_bits(acb_realref(res)) > prec + 5 && arb_rel_accuracy_bits(acb_imagref(res)) > prec + 5) break; } /* Detect exact (dyadic real/imag parts) */ arb_init(t); fmpz_init(n); arb_mul_2exp_si(t, acb_realref(res), wp); if (!arb_is_exact(t) && arb_get_unique_fmpz(n, t)) { qqbar_t u; qqbar_init(u); qqbar_set_fmpz(u, n); qqbar_mul_2exp_si(u, u, wp); qqbar_sub(u, x, u); if (qqbar_sgn_re(u) == 0) { arb_set_fmpz(acb_realref(res), n); arb_mul_2exp_si(acb_realref(res), acb_realref(res), wp); } qqbar_clear(u); } arb_mul_2exp_si(t, acb_imagref(res), wp); if (!arb_is_exact(t) && arb_get_unique_fmpz(n, t)) { qqbar_t u; qqbar_init(u); qqbar_i(u); qqbar_mul_fmpz(u, u, n); qqbar_mul_2exp_si(u, u, wp); qqbar_sub(u, x, u); if (qqbar_sgn_im(u) == 0) { arb_set_fmpz(acb_imagref(res), n); arb_mul_2exp_si(acb_imagref(res), acb_imagref(res), wp); } qqbar_clear(u); } acb_set_round(res, res, prec); arb_clear(t); fmpz_clear(n); } } flint-3.1.3/src/qqbar/get_arb.c000066400000000000000000000012671461254215100163050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_get_arb(arb_t res, const qqbar_t x, slong prec) { if (qqbar_sgn_im(x) == 0) { acb_t t; acb_init(t); qqbar_get_acb(t, x, prec); arb_swap(res, acb_realref(t)); acb_clear(t); } else { arb_indeterminate(res); } } flint-3.1.3/src/qqbar/get_arb_im.c000066400000000000000000000012611461254215100167640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_get_arb_im(arb_t res, const qqbar_t x, slong prec) { if (qqbar_sgn_im(x) == 0) { arb_zero(res); } else { acb_t t; acb_init(t); qqbar_get_acb(t, x, prec); arb_swap(res, acb_imagref(t)); acb_clear(t); } } flint-3.1.3/src/qqbar/get_arb_re.c000066400000000000000000000012611461254215100167650ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_get_arb_re(arb_t res, const qqbar_t x, slong prec) { if (qqbar_sgn_re(x) == 0) { arb_zero(res); } else { acb_t t; acb_init(t); qqbar_get_acb(t, x, prec); arb_swap(res, acb_realref(t)); acb_clear(t); } } flint-3.1.3/src/qqbar/get_fexpr.c000066400000000000000000000607221461254215100166660ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "fmpq_poly.h" #include "arb_fmpz_poly.h" #include "acb_poly.h" #include "fexpr_builtin.h" #include "ulong_extras.h" #include "qqbar.h" static ulong _deflation(const fmpz * poly, slong len) { fmpz_poly_t t; t->alloc = t->length = len; t->coeffs = (fmpz *) poly; return arb_fmpz_poly_deflation(t); } void fexpr_set_arb(fexpr_t res, const arb_t x) { fexpr_t mid, rad, h; arf_t r; fexpr_init(mid); fexpr_init(rad); fexpr_init(h); fexpr_set_symbol_builtin(h, FEXPR_RealBall); fexpr_set_arf(mid, arb_midref(x)); arf_init_set_mag_shallow(r, arb_radref(x)); fexpr_set_arf(rad, r); fexpr_call2(res, h, mid, rad); fexpr_clear(mid); fexpr_clear(rad); fexpr_clear(h); } void fexpr_set_acb(fexpr_t res, const acb_t x) { if (arb_is_zero(acb_imagref(x))) { fexpr_set_arb(res, acb_realref(x)); } else if (arb_is_zero(acb_realref(x))) { fexpr_t v, i; fexpr_init(v); fexpr_init(i); fexpr_set_arb(v, acb_imagref(x)); fexpr_set_symbol_builtin(i, FEXPR_NumberI); fexpr_mul(res, v, i); fexpr_clear(v); fexpr_clear(i); } else { fexpr_t r, v, i; fexpr_init(r); fexpr_init(v); fexpr_init(i); fexpr_set_arb(v, acb_imagref(x)); fexpr_set_symbol_builtin(i, FEXPR_NumberI); fexpr_mul(r, v, i); fexpr_set_arb(v, acb_realref(x)); fexpr_add(res, v, r); fexpr_clear(r); fexpr_clear(v); fexpr_clear(i); } } /* todo: better code (no temporaries) */ void fexpr_set_list_fmpz_poly(fexpr_t res, const fmpz_poly_t poly) { fexpr_struct * coeffs; fexpr_t t; slong i, len; len = poly->length; coeffs = _fexpr_vec_init(len); fexpr_init(t); for (i = 0; i < len; i++) fexpr_set_fmpz(coeffs + i, poly->coeffs + i); fexpr_set_symbol_builtin(t, FEXPR_List); fexpr_call_vec(res, t, coeffs, len); _fexpr_vec_clear(coeffs, len); fexpr_clear(t); } void qqbar_get_fexpr_repr(fexpr_t res, const qqbar_t x) { slong j, d; /* todo: better fexpr construction code */ fexpr_struct * coeffs; fexpr_t t, u, v, w; d = qqbar_degree(x); coeffs = _fexpr_vec_init(d + 1); fexpr_init(t); fexpr_init(u); fexpr_init(v); fexpr_init(w); for (j = 0; j <= d; j++) fexpr_set_fmpz(coeffs + j, QQBAR_COEFFS(x) + j); fexpr_set_symbol_builtin(u, FEXPR_List); fexpr_call_vec(t, u, coeffs, d + 1); fexpr_set_symbol_builtin(v, FEXPR_AlgebraicNumberSerialized); fexpr_set_acb(u, QQBAR_ENCLOSURE(x)); fexpr_call2(res, v, t, u); _fexpr_vec_clear(coeffs, d + 1); fexpr_clear(t); fexpr_clear(u); fexpr_clear(v); fexpr_clear(w); } void _qqbar_get_fexpr_root_nearest(fexpr_t res, const fmpz_poly_t poly, const char * re_s, const char * im_s) { fexpr_t Decimal, a, b, I, s; fexpr_init(Decimal); fexpr_init(a); fexpr_init(b); fexpr_init(I); fexpr_init(s); fexpr_set_symbol_builtin(Decimal, FEXPR_Decimal); if (re_s == NULL && im_s == NULL) { fexpr_set_string(s, "0.0"); fexpr_call1(a, Decimal, s); } else { if (re_s != NULL) { fexpr_set_string(s, re_s); fexpr_call1(a, Decimal, s); } if (im_s != NULL) { fexpr_set_string(s, im_s); fexpr_call1(b, Decimal, s); fexpr_set_symbol_builtin(I, FEXPR_NumberI); fexpr_mul(s, b, I); fexpr_swap(b, s); } } if (im_s == NULL) fexpr_swap(s, a); else if (re_s == NULL) fexpr_swap(s, b); else fexpr_add(s, a, b); fexpr_set_list_fmpz_poly(b, poly); fexpr_set_symbol_builtin(a, FEXPR_PolynomialRootNearest); fexpr_call2(res, a, b, s); fexpr_clear(Decimal); fexpr_clear(a); fexpr_clear(b); fexpr_clear(I); fexpr_clear(s); } void qqbar_get_decimal_root_nearest(char ** re_s, char ** im_s, const qqbar_t x, slong default_digits) { acb_t z, point, delta; acb_poly_t poly; arb_t lhs, rhs, R, Rpow, tmpr; slong k, d, digits, prec, wp; int success; int imag_zero, real_zero; d = qqbar_degree(x); /* For rational numbers, any numerical approximation will suffice */ if (d == 1) { arb_t t; arb_init(t); digits = default_digits; qqbar_get_arb(t, x, 3.333 * digits + 10); re_s[0] = arb_get_str(t, digits, ARB_STR_NO_RADIUS); im_s[0] = NULL; arb_clear(t); return; } imag_zero = (qqbar_sgn_im(x) == 0); real_zero = (qqbar_sgn_re(x) == 0); /* For nonreal quadratics, getting the correct sign of the imaginary part (guaranteed by qqbar_get_acb) is sufficient. */ if (d == 2 && !imag_zero) { acb_t t; acb_init(t); digits = default_digits; qqbar_get_acb(t, x, 3.333 * digits + 10); if (real_zero) re_s[0] = NULL; else re_s[0] = arb_get_str(acb_realref(t), digits, ARB_STR_NO_RADIUS); im_s[0] = arb_get_str(acb_imagref(t), digits, ARB_STR_NO_RADIUS); acb_clear(t); return; } acb_init(z); acb_init(point); acb_init(delta); acb_poly_init(poly); arb_init(lhs); arb_init(rhs); arb_init(R); arb_init(Rpow); arb_init(tmpr); acb_set(z, QQBAR_ENCLOSURE(x)); if (imag_zero) arb_zero(acb_imagref(z)); if (real_zero) arb_zero(acb_realref(z)); re_s[0] = im_s[0] = NULL; success = 0; for (digits = default_digits; !success; digits *= 2) { prec = digits * 3.333 + 10; if (digits != 6 && 0) printf("digits " WORD_FMT "d\n", digits); if (acb_rel_accuracy_bits(z) < prec) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); if (imag_zero) arb_zero(acb_imagref(z)); if (real_zero) arb_zero(acb_realref(z)); } flint_free(re_s[0]); flint_free(im_s[0]); re_s[0] = arb_get_str(acb_realref(z), digits, ARB_STR_NO_RADIUS); im_s[0] = arb_get_str(acb_imagref(z), digits, ARB_STR_NO_RADIUS); /* Let x be the true root and let z = a + bi be the approximate point. */ /* Verify that D(z, C*|z-x|) contains a unique root, for some C > 1. */ for (wp = prec; ; wp *= 2) { /* printf("inner loop %ld / %ld, acc %ld\n", wp, prec, acb_rel_accuracy_bits(z)); */ if (acb_rel_accuracy_bits(z) < wp) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, wp); if (imag_zero) arb_zero(acb_imagref(z)); if (real_zero) arb_zero(acb_realref(z)); } arb_set_str(acb_realref(point), re_s[0], wp); arb_set_str(acb_imagref(point), im_s[0], wp); acb_sub(delta, z, point, wp); acb_abs(R, delta, wp); /* need more precision */ if (arb_contains_zero(R)) { success = 0; continue; } /* C = 1.25 */ arb_mul_ui(R, R, 5, wp); arb_mul_2exp_si(R, R, -2); acb_poly_set_fmpz_poly(poly, QQBAR_POLY(x), wp); acb_poly_taylor_shift(poly, poly, point, wp); /* |a_1| R > (pi/3) (|a_0| + |a_2| R^2 + ... + |a_d| R^d) */ acb_abs(lhs, poly->coeffs + 1, wp); arb_mul(lhs, lhs, R, wp); acb_abs(rhs, poly->coeffs, wp); arb_set(Rpow, R); for (k = 2; k <= d; k++) { arb_mul(Rpow, Rpow, R, wp); acb_abs(tmpr, poly->coeffs + k, wp); arb_addmul(rhs, tmpr, Rpow, wp); } arb_const_pi(tmpr, wp); arb_mul(rhs, rhs, tmpr, wp); arb_div_ui(rhs, rhs, 3, wp); if (arb_overlaps(lhs, rhs)) continue; success = arb_gt(lhs, rhs); break; } } if (real_zero) { flint_free(re_s[0]); re_s[0] = NULL; } if (imag_zero) { flint_free(im_s[0]); im_s[0] = NULL; } acb_clear(z); acb_clear(point); acb_clear(delta); acb_poly_clear(poly); arb_clear(lhs); arb_clear(rhs); arb_clear(R); arb_clear(Rpow); arb_clear(tmpr); } void qqbar_get_fexpr_root_nearest(fexpr_t res, const qqbar_t x) { char * re_s; char * im_s; qqbar_get_decimal_root_nearest(&re_s, &im_s, x, 6); _qqbar_get_fexpr_root_nearest(res, QQBAR_POLY(x), re_s, im_s); flint_free(re_s); flint_free(im_s); } void qqbar_get_fexpr_root_indexed(fexpr_t res, const qqbar_t x) { qqbar_ptr conjugates; slong d, i, j; d = qqbar_degree(x); conjugates = _qqbar_vec_init(d); qqbar_conjugates(conjugates, x); for (i = 0; i < d; i++) { if (qqbar_equal(conjugates + i, x)) { /* todo: better fexpr construction code */ fexpr_struct * coeffs; fexpr_t t, u, v; coeffs = _fexpr_vec_init(d + 1); fexpr_init(t); fexpr_init(u); fexpr_init(v); for (j = 0; j <= d; j++) fexpr_set_fmpz(coeffs + j, QQBAR_COEFFS(x) + j); fexpr_set_symbol_builtin(u, FEXPR_List); fexpr_call_vec(t, u, coeffs, d + 1); fexpr_set_si(u, i + 1); fexpr_set_symbol_builtin(v, FEXPR_PolynomialRootIndexed); fexpr_call2(res, v, t, u); _fexpr_vec_clear(coeffs, d + 1); fexpr_clear(t); fexpr_clear(u); fexpr_clear(v); break; } } _qqbar_vec_clear(conjugates, d); } void fexpr_sqrt(fexpr_t res, const fexpr_t a) { /* todo: handle aliasing in call1 */ if (res == a) { fexpr_t tmp; fexpr_init(tmp); fexpr_set(tmp, a); fexpr_sqrt(res, tmp); fexpr_clear(tmp); } else { /* todo: avoid tmp alloc */ fexpr_t tmp; fexpr_init(tmp); fexpr_set_symbol_builtin(tmp, FEXPR_Sqrt); fexpr_call1(res, tmp, a); fexpr_clear(tmp); } } void fexpr_div_ui(fexpr_t res, const fexpr_t a, ulong c) { fexpr_t t, u; fexpr_init(t); fexpr_init(u); fexpr_set_ui(u, c); fexpr_div(t, a, u); fexpr_swap(res, t); fexpr_clear(t); fexpr_clear(u); } /* cos(pi p/q) */ void _fexpr_cos_pi_pq(fexpr_t res, slong p, ulong q) { int sign = 1; int sine = 0; ulong g; fexpr_t t, u; if (p < 0) { _fexpr_cos_pi_pq(res, -p, q); return; } p = p % (2 * q); if (p > q) { p = 2 * q - p; } if (2 * p > q) { p = q - p; sign = -1; } if (p == 0) { fexpr_set_si(res, sign); return; } if (2 * p == q) { fexpr_set_ui(res, 0); return; } if (3 * p == q) { fexpr_set_si(res, sign); fexpr_div_ui(res, res, 2); return; } if (4 * p == q) { fexpr_set_ui(res, 2); fexpr_sqrt(res, res); fexpr_div_ui(res, res, 2); if (sign == -1) fexpr_neg(res, res); return; } if (6 * p == q) { fexpr_set_ui(res, 3); fexpr_sqrt(res, res); fexpr_div_ui(res, res, 2); if (sign == -1) fexpr_neg(res, res); return; } if (12 * p == q || 12 * p == 5 * q) { fexpr_init(t); fexpr_init(u); fexpr_set_ui(t, 3); fexpr_sqrt(t, t); fexpr_set_ui(u, 1); if (12 * p == q) fexpr_add(res, t, u); else fexpr_sub(res, t, u); fexpr_set_ui(t, 2); fexpr_sqrt(t, t); fexpr_mul(u, t, res); fexpr_div_ui(res, u, 4); if (sign == -1) fexpr_neg(res, res); fexpr_clear(t); fexpr_clear(u); return; } if (4 * p > q) { p = q - 2 * p; q = 2 * q; sine = 1; } g = n_gcd(p, q); if (g != 1) { p /= g; q /= g; } fexpr_init(t); fexpr_init(u); if (p == 1) { fexpr_set_symbol_builtin(res, FEXPR_Pi); } else { fexpr_set_ui(t, p); fexpr_set_symbol_builtin(u, FEXPR_Pi); fexpr_mul(res, t, u); } fexpr_div_ui(t, res, q); if (sine) fexpr_set_symbol_builtin(u, FEXPR_Sin); else fexpr_set_symbol_builtin(u, FEXPR_Cos); fexpr_call1(res, u, t); if (sign == -1) fexpr_neg(res, res); fexpr_clear(t); fexpr_clear(u); } ulong qqbar_try_as_cyclotomic(qqbar_t zeta, fmpq_poly_t poly, const qqbar_t x) { ulong * phi; ulong N1, N2, d2, order, d; slong p, q, i; double U; slong bits; int success; d = qqbar_degree(x); success = 0; order = 0; bits = 2 * qqbar_height_bits(x) /*+ 20 * d */ + 40; d2 = 4 * d; /* Compute inverse image of the totient function for d, 2*d and 4*d. */ /* Determine lower and upper bounds [N1, N2) */ U = d2; for (p = 2; p <= d2; p++) if (d2 % (p - 1) == 0 && n_is_prime(p)) U = (U * p) / (p - 1); N1 = d + 1; N2 = U + 3; /* +3 as safety for possible floating-point rounding */ /* N2 = FLINT_MIN(N2, 1 + 30); */ phi = flint_malloc(N2 * sizeof(ulong)); for (i = 0; i < N2; i++) phi[i] = i; for (p = 2; p < N2; p++) { if (phi[p] == p) { phi[p] = p - 1; for (q = 2 * p; q < N2; q += p) phi[q] = (phi[q] / p) * (p - 1); } } for (i = N1; i < N2 && !success; i++) { if (phi[i] == d || phi[i] == 2 * d || phi[i] == 4 * d) { qqbar_root_of_unity(zeta, 1, i); if (qqbar_express_in_field(poly, zeta, x, bits, 0, bits)) { order = i; success = 1; break; } } } flint_free(phi); return order; } /* poly(exp(2 pi i / n)) */ void _qqbar_get_fexpr_cyclotomic(fexpr_t res, const fmpq_poly_t poly, slong n, int pure_real, int pure_imag) { fexpr_vec_t terms; fexpr_t term, t, u, v, w; ulong p, q, g; slong i; fexpr_vec_init(terms, 0); fexpr_init(term); fexpr_init(t); fexpr_init(u); fexpr_init(v); fexpr_init(w); for (i = 0; i < poly->length; i++) { if (!fmpz_is_zero(poly->coeffs + i)) { if (i == 0) { fexpr_set_fmpz(term, poly->coeffs + i); } else { p = 2 * i; q = n; g = n_gcd(p, q); p /= g; q /= g; if (pure_real) { _fexpr_cos_pi_pq(v, p, q); } else { fexpr_set_ui(t, p); fexpr_set_symbol_builtin(u, FEXPR_Pi); fexpr_set_symbol_builtin(v, FEXPR_NumberI); fexpr_set_symbol_builtin(w, FEXPR_Mul); if (p == 1) fexpr_call2(term, w, u, v); else fexpr_call3(term, w, t, u, v); fexpr_set_ui(t, q); fexpr_div(u, term, t); fexpr_set_symbol_builtin(w, FEXPR_Exp); fexpr_call1(v, w, u); } if (fmpz_is_one(poly->coeffs + i)) fexpr_swap(term, v); else { fexpr_set_fmpz(t, poly->coeffs + i); fexpr_mul(term, t, v); } } fexpr_vec_append(terms, term); } } fexpr_set_symbol_builtin(t, FEXPR_Add); fexpr_call_vec(res, t, terms->entries, terms->length); if (!fmpz_is_one(poly->den)) { fexpr_set_fmpz(t, poly->den); fexpr_div(u, res, t); fexpr_swap(res, u); } /* todo: also want this with expanded exponentials */ if (pure_real) { fexpr_expanded_normal_form(res, res, 0); } fexpr_vec_clear(terms); fexpr_clear(term); fexpr_clear(t); fexpr_clear(u); fexpr_clear(v); fexpr_clear(w); } int qqbar_get_fexpr_formula(fexpr_t res, const qqbar_t x, ulong flags) { slong d; int success; d = qqbar_degree(x); if (d == 1) { fmpq_t r; fmpz_t t; fmpq_init(r); fmpz_init(t); qqbar_get_quadratic(fmpq_numref(r), t, t, fmpq_denref(r), x, 0); fexpr_set_fmpq(res, r); fmpq_clear(r); fmpz_clear(t); return 1; } if (d <= 2 && (flags & (QQBAR_FORMULA_QUADRATICS | QQBAR_FORMULA_GAUSSIANS))) { fmpz_t a, b, c, q; fexpr_t t, u, v; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(q); fexpr_init(t); fexpr_init(u); fexpr_init(v); qqbar_get_quadratic(a, b, c, q, x, 2); if (fmpz_equal_si(c, -1) && (flags & QQBAR_FORMULA_GAUSSIANS)) { fexpr_set_symbol_builtin(t, FEXPR_NumberI); success = 1; } else if (flags & QQBAR_FORMULA_QUADRATICS) { fexpr_set_fmpz(u, c); fexpr_set_symbol_builtin(v, FEXPR_Sqrt); fexpr_call1(t, v, u); success = 1; } else { success = 0; } if (success) { if (fmpz_is_zero(a)) { if (fmpz_equal_si(b, -1)) fexpr_neg(u, t); else if (fmpz_equal_si(b, 1)) fexpr_swap(u, t); else { fexpr_set_fmpz(v, b); fexpr_mul(u, v, t); } } else { if (fmpz_equal_si(b, -1)) { fexpr_set_fmpz(v, a); fexpr_sub(u, v, t); } else if (fmpz_equal_si(b, 1)) { fexpr_set_fmpz(v, a); fexpr_add(u, v, t); } else { fexpr_set_fmpz(u, b); fexpr_mul(v, u, t); fexpr_set_fmpz(t, a); fexpr_add(u, t, v); } } if (fmpz_is_one(q)) { fexpr_swap(res, u); } else { fexpr_set_fmpz(t, q); fexpr_div(res, u, t); } } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(q); fexpr_clear(t); fexpr_clear(u); fexpr_clear(v); if (success) return 1; } /* Identify special constants */ if (flags & QQBAR_FORMULA_CYCLOTOMICS) { slong p; ulong q; /* Quick detection of roots of unity. Todo: could also detect rational multiples of roots of unity. */ if (qqbar_is_root_of_unity(&p, &q, x)) { fexpr_t s, t, u, v, w; /* exp(2 p pi i / q) */ if (q % 2 == 0) q /= 2; else p *= 2; fexpr_init(s); fexpr_init(t); fexpr_init(u); fexpr_init(v); fexpr_init(w); fexpr_set_symbol_builtin(s, FEXPR_Mul); fexpr_set_si(t, p); fexpr_set_symbol_builtin(u, FEXPR_Pi); fexpr_set_symbol_builtin(v, FEXPR_NumberI); if (p == 1) fexpr_call2(w, s, u, v); else fexpr_call3(w, s, t, u, v); fexpr_set_si(t, q); fexpr_div(u, w, t); fexpr_set_symbol_builtin(t, FEXPR_Exp); fexpr_call1(res, t, u); fexpr_clear(s); fexpr_clear(t); fexpr_clear(u); fexpr_clear(v); fexpr_clear(w); return 1; } } /* Check for elements of cyclotomic fields */ if (flags & QQBAR_FORMULA_CYCLOTOMICS) { fmpq_poly_t poly; qqbar_t zeta; ulong q; fmpq_poly_init(poly); qqbar_init(zeta); q = qqbar_try_as_cyclotomic(zeta, poly, x); if (q != 0) _qqbar_get_fexpr_cyclotomic(res, poly, q, qqbar_sgn_im(x) == 0, qqbar_sgn_re(x) == 0); fmpq_poly_clear(poly); qqbar_clear(zeta); if (q != 0) return 1; } if (flags & QQBAR_FORMULA_DEFLATION) { slong deflation; ulong flags2; deflation = _deflation(QQBAR_COEFFS(x), d + 1); if (deflation > 1) { int neg; qqbar_t t, u, v; /* Avoid possible cases of infinite recursion. */ /* Todo: in some cases, we might want to carefully allow deflation recursively. */ flags2 = flags & ~QQBAR_FORMULA_DEFLATION; neg = qqbar_is_real(x) && qqbar_sgn_re(x) < 0; qqbar_init(t); qqbar_init(u); qqbar_init(v); if (neg) qqbar_neg(t, x); else qqbar_set(t, x); qqbar_pow_ui(u, t, deflation); success = qqbar_get_fexpr_formula(res, u, flags2); if (success) { fexpr_t a, b; fexpr_init(a); fexpr_init(b); /* todo: compute the root of unity more efficiently */ qqbar_root_ui(v, u, deflation); qqbar_div(u, x, v); if (deflation == 2) { fexpr_sqrt(b, res); } else { fexpr_set_ui(b, 1); fexpr_div_ui(a, b, deflation); fexpr_pow(b, res, a); } if (qqbar_is_one(u)) fexpr_set(res, b); else if (qqbar_is_neg_one(u)) fexpr_neg(res, b); else { /* Todo: | flags by GAUSSIANS, CYCLOTOMICS etc. to always express the root of unity? */ success = qqbar_get_fexpr_formula(a, u, flags2); if (success) fexpr_mul(res, b, a); } fexpr_clear(a); fexpr_clear(b); } qqbar_clear(t); qqbar_clear(u); qqbar_clear(v); if (success) return 1; } } /* Try a+bi or |x|*s separation. */ if ((flags & QQBAR_FORMULA_SEPARATION) && !qqbar_is_real(x)) { qqbar_t a, b; fexpr_t t, u, v; ulong flags2; qqbar_init(a); qqbar_init(b); fexpr_init(t); fexpr_init(u); fexpr_init(v); qqbar_re_im(a, b, x); /* Avoid possible cases of infinite recursion. */ /* Todo: in some cases, we might want to carefully allow separation recursively, e.g. if the degree has been strictly decreased. */ flags2 = flags & ~QQBAR_FORMULA_SEPARATION; success = (qqbar_degree(a) <= d) && (qqbar_degree(b) <= d) && qqbar_get_fexpr_formula(t, a, flags2) && qqbar_get_fexpr_formula(u, b, flags2); if (success) { fexpr_set_symbol_builtin(res, FEXPR_NumberI); fexpr_mul(v, u, res); if (qqbar_is_zero(a)) fexpr_swap(res, v); else fexpr_add(res, t, v); } else { qqbar_abs(a, x); if (qqbar_degree(a) <= d && qqbar_get_fexpr_formula(t, a, flags2)) { qqbar_div(b, x, a); if (qqbar_get_fexpr_formula(u, b, flags2)) { fexpr_mul(res, t, u); success = 1; } } } qqbar_clear(a); qqbar_clear(b); fexpr_clear(t); fexpr_clear(u); fexpr_clear(v); if (success) return 1; } return 0; } flint-3.1.3/src/qqbar/get_fmpq.c000066400000000000000000000014131461254215100164750ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void _qqbar_get_fmpq(fmpz_t num, fmpz_t den, const qqbar_t x) { if (qqbar_degree(x) != 1) { flint_throw(FLINT_ERROR, "_qqbar_get_fmpq: not a rational value\n"); } fmpz_neg(num, QQBAR_COEFFS(x)); fmpz_set(den, QQBAR_COEFFS(x) + 1); } void qqbar_get_fmpq(fmpq_t res, const qqbar_t x) { _qqbar_get_fmpq(fmpq_numref(res), fmpq_denref(res), x); } flint-3.1.3/src/qqbar/get_fmpz.c000066400000000000000000000012021461254215100165020ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_get_fmpz(fmpz_t res, const qqbar_t x) { if (qqbar_degree(x) != 1 || !fmpz_is_one(QQBAR_COEFFS(x) + 1)) { flint_throw(FLINT_ERROR, "qqbar_get_fmpz: not an integer\n"); } fmpz_neg(res, QQBAR_COEFFS(x)); } flint-3.1.3/src/qqbar/get_quadratic.c000066400000000000000000000125471461254215100175210ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_factor.h" #include "qqbar.h" /* Write |n| = A * B^2 factoring = 0 -> no factoring except for powers of two factoring = 1 -> complete factoring factoring = 2 -> smooth factoring */ static void _fmpz_factor_square_root(fmpz_t A, fmpz_t B, const fmpz_t n, int factoring) { if (factoring == 0) { slong v; v = fmpz_val2(n); fmpz_abs(A, n); fmpz_one(B); if (v >= 2) { fmpz_tdiv_q_2exp(A, A, v - (v & 1)); fmpz_mul_2exp(B, B, v / 2); } } else { fmpz_factor_t fac; fmpz_t t; slong i; fmpz_factor_init(fac); if (factoring == 1) fmpz_factor(fac, n); else fmpz_factor_smooth(fac, n, 32, -1); /* 32 bit factors, -1 => no primality test */ fmpz_one(A); fmpz_one(B); fmpz_init(t); for (i = 0; i < fac->num; i++) { if (fac->exp[i] == 1) { fmpz_mul(A, A, fac->p + i); } else if (fac->exp[i] == 2) { fmpz_mul(B, B, fac->p + i); } else { fmpz_pow_ui(t, fac->p + i, fac->exp[i] / 2); fmpz_mul(B, B, t); if (fac->exp[i] % 2) fmpz_mul(A, A, fac->p + i); } } fmpz_factor_clear(fac); fmpz_clear(t); } } void qqbar_get_quadratic(fmpz_t res_a, fmpz_t res_b, fmpz_t res_c, fmpz_t res_q, const qqbar_t x, int factoring) { const fmpz *a, *b, *c; fmpz_t D; if (qqbar_degree(x) == 1) { fmpz_zero(res_b); fmpz_zero(res_c); _qqbar_get_fmpq(res_a, res_q, x); return; } if (qqbar_degree(x) != 2) { flint_throw(FLINT_ERROR, "qqbar_get_quadratic: degree 1 or 2 is required\n"); } a = QQBAR_COEFFS(x) + 2; b = QQBAR_COEFFS(x) + 1; c = QQBAR_COEFFS(x) + 0; /* x = (-b +/- sqrt(b^2 - 4ac))/(2a) */ fmpz_init(D); fmpz_mul(D, a, c); fmpz_mul_2exp(D, D, 2); fmpz_submul(D, b, b); /* -D is a square <=> element of Q(i) */ if (fmpz_is_square(D)) { fmpz_sqrt(D, D); fmpz_set_si(res_c, -1); if (qqbar_sgn_im(x) > 0) fmpz_set(res_b, D); else fmpz_neg(res_b, D); fmpz_neg(res_a, b); fmpz_mul_2exp(res_q, a, 1); fmpz_gcd(D, res_a, res_b); fmpz_gcd(D, D, res_q); if (!fmpz_is_one(D)) { fmpz_divexact(res_a, res_a, D); fmpz_divexact(res_b, res_b, D); fmpz_divexact(res_q, res_q, D); } } else { fmpz_t A, B; fmpz_neg(D, D); fmpz_init(A); fmpz_init(B); /* sqrt(|D|) = A * B^2 => sqrt(D) = sqrt(A) * B (D > 0) sqrt(-A) * B (D < 0) */ _fmpz_factor_square_root(A, B, D, factoring); if (fmpz_sgn(D) < 0) fmpz_neg(A, A); fmpz_set(res_c, A); /* x = (-b +/- B*sqrt(A))/(2a) */ fmpz_neg(res_a, b); fmpz_mul_2exp(res_q, a, 1); /* determine the correct sign */ if (fmpz_sgn(D) < 0) { if (qqbar_sgn_im(x) > 0) fmpz_set(res_b, B); else fmpz_neg(res_b, B); } else if (fmpz_is_zero(b)) { if (qqbar_sgn_re(x) > 0) fmpz_set(res_b, B); else fmpz_neg(res_b, B); } else { arb_t r1, r2; slong prec; arb_init(r1); arb_init(r2); for (prec = 64; ; prec *= 2) { arb_sqrt_fmpz(r1, A, prec); arb_mul_fmpz(r1, r1, B, prec); arb_add_fmpz(r2, r1, b, prec); arb_neg(r2, r2); arb_sub_fmpz(r1, r1, b, prec); arb_div_fmpz(r1, r1, a, prec); arb_div_fmpz(r2, r2, a, prec); arb_mul_2exp_si(r1, r1, -1); arb_mul_2exp_si(r2, r2, -1); if (arb_overlaps(r1, acb_realref(QQBAR_ENCLOSURE(x))) && !arb_overlaps(r2, acb_realref(QQBAR_ENCLOSURE(x)))) { fmpz_set(res_b, B); break; } if (arb_overlaps(r2, acb_realref(QQBAR_ENCLOSURE(x))) && !arb_overlaps(r1, acb_realref(QQBAR_ENCLOSURE(x)))) { fmpz_neg(res_b, B); break; } } arb_clear(r1); arb_clear(r2); } fmpz_gcd(D, res_a, res_b); fmpz_gcd(D, D, res_q); if (!fmpz_is_one(D)) { fmpz_divexact(res_a, res_a, D); fmpz_divexact(res_b, res_b, D); fmpz_divexact(res_q, res_q, D); } fmpz_clear(A); fmpz_clear(B); } fmpz_clear(D); } flint-3.1.3/src/qqbar/guess.c000066400000000000000000000072001461254215100160210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_factor.h" #include "fmpz_lll.h" #include "arb_fmpz_poly.h" #include "qqbar.h" #define QQBAR_GUESS_TRY_SMALLER 1 #define QQBAR_GUESS_CHECK 2 int qqbar_guess(qqbar_t res, const acb_t z, slong max_deg, slong max_bits, int flags, slong prec) { acb_ptr zpow; int found; slong i, j, fac_bits, prec2; fmpz_poly_t poly; fmpz_poly_factor_t fac; acb_t z2; mag_t rad; if (!acb_is_finite(z)) return 0; if (max_deg > 8 && (flags & QQBAR_GUESS_TRY_SMALLER)) { if (qqbar_guess(res, z, max_deg / 4, max_bits, flags, prec)) return 1; } found = 0; fmpz_poly_init2(poly, max_deg + 1); fmpz_poly_factor_init(fac); acb_init(z2); mag_init(rad); zpow = _acb_vec_init(max_deg + 1); _acb_vec_set_powers(zpow, z, max_deg + 1, prec); _fmpz_poly_set_length(poly, max_deg + 1); if (_qqbar_acb_lindep(poly->coeffs, zpow, max_deg + 1, 1, prec)) { _fmpz_poly_normalise(poly); fmpz_poly_factor(fac, poly); for (i = 0; i < fac->num; i++) { fac_bits = fmpz_poly_max_bits(fac->p + i); fac_bits = FLINT_ABS(fac_bits); if (fac_bits <= max_bits) { slong deg; qqbar_ptr roots; /* Rule out p(x) != 0 */ arb_fmpz_poly_evaluate_acb(z2, fac->p + i, z, prec); if (acb_contains_zero(z2)) { /* Try to use the original interval, to avoid computing the polynomial roots... */ if (acb_rel_accuracy_bits(z) >= QQBAR_DEFAULT_PREC - 3) { for (prec2 = QQBAR_DEFAULT_PREC / 2; prec2 < 2 * prec; prec2 *= 2) { acb_set(z2, z); acb_get_mag(rad, z); mag_mul_2exp_si(rad, rad, -prec2); acb_add_error_mag(z2, rad); if (_qqbar_validate_existence_uniqueness(z2, fac->p + i, z2, 2 * prec2)) { fmpz_poly_set(QQBAR_POLY(res), fac->p + i); acb_set(QQBAR_ENCLOSURE(res), z2); found = 1; break; } } } deg = fmpz_poly_degree(fac->p + i); roots = _qqbar_vec_init(deg); qqbar_roots_fmpz_poly(roots, fac->p + i, QQBAR_ROOTS_IRREDUCIBLE); for (j = 0; j < deg; j++) { qqbar_get_acb(z2, roots + j, prec); if (acb_overlaps(z, z2)) { qqbar_swap(res, roots + j); found = 1; break; } } _qqbar_vec_clear(roots, deg); if (found) break; } } } } fmpz_poly_clear(poly); fmpz_poly_factor_clear(fac); _acb_vec_clear(zpow, max_deg + 1); acb_clear(z2); mag_clear(rad); return found; } flint-3.1.3/src/qqbar/hash.c000066400000000000000000000014301461254215100156150ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "calcium.h" #include "qqbar.h" ulong qqbar_hash(const qqbar_t x) { ulong s; slong i, len; const fmpz * c; len = QQBAR_POLY(x)->length; c = QQBAR_COEFFS(x); s = 1234567; for (i = 0; i < len; i++) s = calcium_fmpz_hash(c + i) * 1000003 + s; /* todo: add in some bits describing the enclosure, e.g. a floor value or just the signs */ return s; } flint-3.1.3/src/qqbar/height.c000066400000000000000000000010071461254215100161420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_height(fmpz_t res, const qqbar_t x) { fmpz_poly_height(res, QQBAR_POLY(x)); } flint-3.1.3/src/qqbar/height_bits.c000066400000000000000000000010621461254215100171640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" slong qqbar_height_bits(const qqbar_t x) { slong bits; bits = fmpz_poly_max_bits(QQBAR_POLY(x)); return FLINT_ABS(bits); } flint-3.1.3/src/qqbar/i.c000066400000000000000000000011671461254215100151310ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_i(qqbar_t res) { fmpz_poly_zero(QQBAR_POLY(res)); fmpz_poly_set_coeff_si(QQBAR_POLY(res), 2, 1); fmpz_poly_set_coeff_si(QQBAR_POLY(res), 0, 1); acb_onei(QQBAR_ENCLOSURE(res)); } flint-3.1.3/src/qqbar/im.c000066400000000000000000000020201461254215100152730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_im(qqbar_t res, const qqbar_t x) { if (qqbar_sgn_im(x) == 0) { qqbar_zero(res); } else { qqbar_t t; qqbar_init(t); if (qqbar_sgn_re(x) == 0) { qqbar_i(t); qqbar_mul(res, x, t); qqbar_neg(res, res); } else { qqbar_conj(t, x); qqbar_sub(res, x, t); qqbar_i(t); qqbar_mul(res, res, t); qqbar_neg(res, res); qqbar_mul_2exp_si(res, res, -1); } arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); qqbar_clear(t); } } flint-3.1.3/src/qqbar/init.c000066400000000000000000000011071461254215100156360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_init(qqbar_t res) { fmpz_poly_init(QQBAR_POLY(res)); fmpz_poly_set_coeff_si(QQBAR_POLY(res), 1, 1); acb_init(QQBAR_ENCLOSURE(res)); } flint-3.1.3/src/qqbar/inlines.c000066400000000000000000000006521461254215100163400ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define QQBAR_INLINES_C #include "qqbar.h" flint-3.1.3/src/qqbar/inv.c000066400000000000000000000037331461254215100154760ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_fmpz_poly.h" #include "qqbar.h" void qqbar_inv(qqbar_t res, const qqbar_t x) { slong d; if (qqbar_is_zero(x)) { flint_throw(FLINT_ERROR, "qqbar_inv: division by zero\n"); } if (qqbar_is_one(x) || qqbar_is_neg_one(x)) { qqbar_set(res, x); return; } d = qqbar_degree(x); if (d == 1) { fmpz_poly_reverse(QQBAR_POLY(res), QQBAR_POLY(x), d + 1); if (fmpz_sgn(QQBAR_COEFFS(res) + d) < 0) fmpz_poly_neg(QQBAR_POLY(res), QQBAR_POLY(res)); arb_fmpz_div_fmpz(acb_realref(QQBAR_ENCLOSURE(res)), QQBAR_COEFFS(res), QQBAR_COEFFS(res) + 1, QQBAR_DEFAULT_PREC); arb_neg(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res))); arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); } else { fmpz_poly_t pol; slong prec; acb_t z, t; fmpz_poly_init(pol); acb_init(z); acb_init(t); fmpz_poly_reverse(pol, QQBAR_POLY(x), d + 1); if (fmpz_sgn(pol->coeffs + d) < 0) fmpz_poly_neg(pol, pol); acb_set(z, QQBAR_ENCLOSURE(x)); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); acb_inv(t, z, prec); if (_qqbar_validate_uniqueness(t, pol, t, 2 * prec)) { fmpz_poly_set(QQBAR_POLY(res), pol); acb_set(QQBAR_ENCLOSURE(res), t); break; } } fmpz_poly_clear(pol); acb_clear(z); acb_clear(t); } } flint-3.1.3/src/qqbar/log_pi_i.c000066400000000000000000000013061461254215100164550ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_log_pi_i(slong * p, ulong * q, const qqbar_t x) { int ok; ok = qqbar_is_root_of_unity(p, q, x); if (ok) { if (*q % 2 == 0) *q /= 2; else *p *= 2; while (*p > (slong) *q) *p -= 2 * (slong) (*q); } return ok; } flint-3.1.3/src/qqbar/mul.c000066400000000000000000000062421461254215100154750ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq.h" #include "qqbar.h" void qqbar_mul(qqbar_t res, const qqbar_t x, const qqbar_t y) { if (qqbar_is_zero(x) || qqbar_is_zero(y)) { qqbar_zero(res); } else if (qqbar_is_one(x)) { qqbar_set(res, y); } else if (qqbar_is_one(y)) { qqbar_set(res, x); } else if (qqbar_is_neg_one(x)) { qqbar_neg(res, y); } else if (qqbar_is_neg_one(y)) { qqbar_neg(res, x); } else if (qqbar_is_rational(y)) { fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); _qqbar_get_fmpq(a, c, y); qqbar_scalar_op(res, x, a, b, c); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } else if (qqbar_is_rational(x)) { fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); _qqbar_get_fmpq(a, c, x); qqbar_scalar_op(res, y, a, b, c); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } else if (qqbar_equal(x, y)) { /* This may detect exact square roots and other special cases. */ qqbar_pow_ui(res, x, 2); } else if (_qqbar_fast_detect_simple_principal_surd(x) && _qqbar_fast_detect_simple_principal_surd(y)) { /* (p/q)^(1/d) * (r/s)^(1/e) */ fmpq_t t, u; ulong d, e, f, g; d = qqbar_degree(x); e = qqbar_degree(y); g = n_gcd(d, e); f = (d / g) * e; fmpq_init(t); fmpq_init(u); fmpz_neg(fmpq_numref(t), QQBAR_COEFFS(x)); fmpz_set(fmpq_denref(t), QQBAR_COEFFS(x) + d); fmpz_neg(fmpq_numref(u), QQBAR_COEFFS(y)); fmpz_set(fmpq_denref(u), QQBAR_COEFFS(y) + e); fmpq_pow_si(t, t, e / g); fmpq_pow_si(u, u, d / g); fmpq_mul(t, t, u); /* todo: recycle the existing enclosures instead of computing a numerical f-th root from scratch */ qqbar_fmpq_root_ui(res, t, f); fmpq_clear(t); fmpq_clear(u); } else { qqbar_binary_op(res, x, y, 2); } } void qqbar_mul_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpq(t, y); qqbar_mul(res, x, t); qqbar_clear(t); } void qqbar_mul_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpz(t, y); qqbar_mul(res, x, t); qqbar_clear(t); } void qqbar_mul_ui(qqbar_t res, const qqbar_t x, ulong y) { qqbar_t t; qqbar_init(t); qqbar_set_ui(t, y); qqbar_mul(res, x, t); qqbar_clear(t); } void qqbar_mul_si(qqbar_t res, const qqbar_t x, slong y) { qqbar_t t; qqbar_init(t); qqbar_set_si(t, y); qqbar_mul(res, x, t); qqbar_clear(t); } flint-3.1.3/src/qqbar/mul_2exp_si.c000066400000000000000000000030561461254215100171260ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_mul_2exp_si(qqbar_t res, const qqbar_t x, slong exp) { slong i, d, g, h; fmpz * coeffs; d = qqbar_degree(x); if (qqbar_is_zero(x) || exp == 0) { qqbar_set(res, x); return; } if (FLINT_BIT_COUNT(d) + FLINT_BIT_COUNT((ulong) FLINT_ABS(exp)) > FLINT_BITS - 8) { flint_throw(FLINT_ERROR, "qqbar_mul_2exp_si: ludicrously large coefficients\n"); } fmpz_poly_set(QQBAR_POLY(res), QQBAR_POLY(x)); acb_mul_2exp_si(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(x), exp); coeffs = QQBAR_COEFFS(res); /* todo: compute valuations in advance */ if (exp >= 0) { for (i = 1; i <= d; i++) fmpz_mul_2exp(coeffs + d - i, coeffs + d - i, i * exp); } else { for (i = 1; i <= d; i++) fmpz_mul_2exp(coeffs + i, coeffs + i, i * (-exp)); } g = fmpz_val2(coeffs); for (i = 1; i <= d; i++) { if (!fmpz_is_zero(coeffs + i)) { h = fmpz_val2(coeffs + i); g = FLINT_MIN(g, h); } } if (g != 0) fmpz_poly_scalar_tdiv_2exp(QQBAR_POLY(res), QQBAR_POLY(res), g); } flint-3.1.3/src/qqbar/neg.c000066400000000000000000000013301461254215100154420ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_neg(qqbar_t res, const qqbar_t x) { slong i; fmpz_poly_set(QQBAR_POLY(res), QQBAR_POLY(x)); for (i = fmpz_poly_degree(QQBAR_POLY(res)) - 1; i >= 0; i -= 2) fmpz_neg(QQBAR_COEFFS(res) + i, QQBAR_COEFFS(res) + i); acb_neg(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(x)); } flint-3.1.3/src/qqbar/numerator.c000066400000000000000000000012601461254215100167070ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_numerator(qqbar_t res, const qqbar_t y) { if (qqbar_is_algebraic_integer(y)) { qqbar_set(res, y); } else { fmpz_t t; fmpz_init(t); qqbar_denominator(t, y); qqbar_mul_fmpz(res, y, t); fmpz_clear(t); } } flint-3.1.3/src/qqbar/phi.c000066400000000000000000000017231461254215100154570ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_phi(qqbar_t res) { fmpz_poly_zero(QQBAR_POLY(res)); fmpz_poly_set_coeff_si(QQBAR_POLY(res), 2, 1); fmpz_poly_set_coeff_si(QQBAR_POLY(res), 1, -1); fmpz_poly_set_coeff_si(QQBAR_POLY(res), 0, -1); arb_sqrt_ui(acb_realref(QQBAR_ENCLOSURE(res)), 5, QQBAR_DEFAULT_PREC); arb_add_ui(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), 1, QQBAR_DEFAULT_PREC); arb_mul_2exp_si(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), -1); arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); } flint-3.1.3/src/qqbar/pow.c000066400000000000000000000175141461254215100155110ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz_vec.h" #include "fmpq.h" #include "fmpz_poly_factor.h" #include "arb_fmpz_poly.h" #include "qqbar.h" void _qqbar_sqr_undeflatable(qqbar_t res, const qqbar_t x) { fmpz_poly_t A, B; acb_t z, t, w; slong i, prec, d; int pure_real, pure_imag; fmpz_poly_init(A); fmpz_poly_init(B); acb_init(z); acb_init(t); acb_init(w); d = fmpz_poly_degree(QQBAR_POLY(x)); for (i = 0; i <= d; i++) { if (i % 2 == 0) fmpz_poly_set_coeff_fmpz(A, i / 2, QQBAR_POLY(x)->coeffs + i); else fmpz_poly_set_coeff_fmpz(B, i / 2, QQBAR_POLY(x)->coeffs + i); } fmpz_poly_sqr(A, A); fmpz_poly_sqr(B, B); fmpz_poly_shift_left(B, B, 1); fmpz_poly_sub(A, A, B); if (fmpz_sgn(A->coeffs + A->length - 1) < 0) fmpz_poly_neg(A, A); acb_set(z, QQBAR_ENCLOSURE(x)); pure_real = (qqbar_sgn_im(x) == 0); pure_imag = (qqbar_sgn_re(x) == 0); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); if (pure_real) arb_zero(acb_imagref(z)); if (pure_imag) arb_zero(acb_realref(z)); acb_sqr(w, z, prec); if (_qqbar_validate_uniqueness(t, A, w, 2 * prec)) { fmpz_poly_set(QQBAR_POLY(res), A); acb_set(QQBAR_ENCLOSURE(res), t); break; } } fmpz_poly_clear(A); fmpz_poly_clear(B); acb_clear(z); acb_clear(t); acb_clear(w); } /* todo: use number field arithmetic, other optimisations ... */ void qqbar_pow_ui(qqbar_t res, const qqbar_t x, ulong n) { if (n == 0) { qqbar_one(res); } else if (n == 1) { qqbar_set(res, x); } else if (qqbar_is_rational(x)) { fmpq_t t; fmpq_init(t); qqbar_get_fmpq(t, x); fmpz_pow_ui(fmpq_numref(t), fmpq_numref(t), n); fmpz_pow_ui(fmpq_denref(t), fmpq_denref(t), n); qqbar_set_fmpq(res, t); fmpq_clear(t); } else { slong p; ulong q; ulong f; /* Fast path for roots of unity. Todo: generalize to rational multiples of roots of unity. */ if (qqbar_is_root_of_unity(&p, &q, x)) { if (p < 0) p += 2 * q; p = n_mulmod2(p, n, 2 * q); qqbar_root_of_unity(res, p, q); return; } /* Fast detection of perfect powers */ f = arb_fmpz_poly_deflation(QQBAR_POLY(x)); if (f % n == 0) { acb_t z, t, w; fmpz_poly_t H; slong prec; int pure_real, pure_imag; fmpz_poly_init(H); acb_init(z); acb_init(t); acb_init(w); arb_fmpz_poly_deflate(H, QQBAR_POLY(x), n); acb_set(z, QQBAR_ENCLOSURE(x)); pure_real = (qqbar_sgn_im(x) == 0); pure_imag = (qqbar_sgn_re(x) == 0); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); if (pure_real) arb_zero(acb_imagref(z)); if (pure_imag) arb_zero(acb_realref(z)); acb_pow_ui(w, z, n, prec); if (_qqbar_validate_uniqueness(t, H, w, 2 * prec)) { fmpz_poly_set(QQBAR_POLY(res), H); acb_set(QQBAR_ENCLOSURE(res), t); break; } } fmpz_poly_clear(H); acb_clear(z); acb_clear(t); acb_clear(w); return; } /* fast path for principal roots of positive rational numbers */ if (_qqbar_fast_detect_simple_principal_surd(x)) { fmpq_t t; fmpq_init(t); fmpz_neg(fmpq_numref(t), QQBAR_COEFFS(x)); fmpz_set(fmpq_denref(t), QQBAR_COEFFS(x) + qqbar_degree(x)); fmpq_pow_si(t, t, n); qqbar_fmpq_root_ui(res, t, qqbar_degree(x)); fmpq_clear(t); return; } if (n == 2) { _qqbar_sqr_undeflatable(res, x); } else { /* todo: don't construct this polynomial when n is huge */ fmpz * coeffs; fmpz_t den; coeffs = _fmpz_vec_init(n + 1); fmpz_one(coeffs + n); *den = 1; _qqbar_evaluate_fmpq_poly(res, coeffs, den, n + 1, x); _fmpz_vec_clear(coeffs, n + 1); } } } void qqbar_pow_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) { if (fmpq_is_zero(y)) { qqbar_one(res); } else if (fmpq_is_one(y)) { qqbar_set(res, x); } else if (qqbar_is_one(x)) { qqbar_one(res); } else if (qqbar_is_zero(x)) { if (fmpq_sgn(y) <= 0) { flint_throw(FLINT_ERROR, "qqbar_pow_fmpq: division by zero\n"); } qqbar_zero(res); } else { fmpq_t t; fmpz_t r; slong p; ulong q; fmpq_init(t); fmpz_init(r); fmpq_set(t, y); /* Fast path for roots of unity. */ if (qqbar_is_root_of_unity(&p, &q, x)) { fmpz_mul_si(fmpq_numref(t), fmpq_numref(t), p); fmpz_mul_ui(fmpq_denref(t), fmpq_denref(t), q); fmpz_mul_ui(r, fmpq_denref(t), 2); fmpz_fdiv_r(fmpq_numref(t), fmpq_numref(t), r); fmpq_canonicalise(t); if (COEFF_IS_MPZ(*fmpq_denref(t))) { flint_throw(FLINT_ERROR, "qqbar_pow: excessive exponent\n"); } qqbar_root_of_unity(res, *fmpq_numref(t), *fmpq_denref(t)); } else { if (COEFF_IS_MPZ(*fmpq_numref(t)) || COEFF_IS_MPZ(*fmpq_denref(t))) { flint_throw(FLINT_ERROR, "qqbar_pow: excessive exponent\n"); } p = *fmpq_numref(t); q = *fmpq_denref(t); qqbar_root_ui(res, x, q); if (p >= 0) qqbar_pow_ui(res, res, p); else { qqbar_pow_ui(res, res, -p); qqbar_inv(res, res); } } fmpq_clear(t); fmpz_clear(r); } } void qqbar_pow_si(qqbar_t res, const qqbar_t x, slong n) { if (n >= 0) { qqbar_pow_ui(res, x, n); } else { fmpq_t t; fmpq_init(t); fmpz_set_si(fmpq_numref(t), n); qqbar_pow_fmpq(res, x, t); fmpq_clear(t); } } void qqbar_pow_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t n) { fmpq_t t; fmpq_init(t); fmpz_set(fmpq_numref(t), n); qqbar_pow_fmpq(res, x, t); fmpq_clear(t); } int qqbar_pow(qqbar_t res, const qqbar_t x, const qqbar_t y) { if (qqbar_is_zero(y)) { qqbar_one(res); return 1; } else if (qqbar_is_one(y)) { qqbar_set(res, x); return 1; } else if (qqbar_is_one(x)) { qqbar_one(res); return 1; } else if (qqbar_is_zero(x)) { if (qqbar_sgn_re(y) <= 0) return 0; qqbar_zero(res); return 1; } else if (qqbar_is_rational(y)) { fmpq_t t; fmpq_init(t); qqbar_get_fmpq(t, y); qqbar_pow_fmpq(res, x, t); fmpq_clear(t); return 1; } else { return 0; } } flint-3.1.3/src/qqbar/print.c000066400000000000000000000015011461254215100160250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_print(const qqbar_t x) { slong i, d; d = qqbar_degree(x); flint_printf("deg %wd [", qqbar_degree(x)); for (i = 0; i <= d; i++) { fmpz_print(QQBAR_COEFFS(x) + i); if (i < d) flint_printf(", "); } flint_printf("] "); acb_printn(QQBAR_ENCLOSURE(x), FLINT_MAX(6, FLINT_MIN(acb_rel_accuracy_bits(QQBAR_ENCLOSURE(x)), acb_bits(QQBAR_ENCLOSURE(x)))), 0); } flint-3.1.3/src/qqbar/printn.c000066400000000000000000000013751461254215100162140ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_printn(const qqbar_t x, slong n) { acb_t t; slong prec; n = FLINT_MAX(1, n); prec = n * 3.333 + 10; acb_init(t); qqbar_get_acb(t, x, prec); acb_printn(t, n, ARB_STR_NO_RADIUS); acb_clear(t); } void qqbar_printnd(const qqbar_t x, slong n) { qqbar_printn(x, n); flint_printf(" (deg %wd)", qqbar_degree(x)); } flint-3.1.3/src/qqbar/randtest.c000066400000000000000000000050111461254215100165150ustar00rootroot00000000000000/* Copyright (C) 2016 Vincent Delecroix Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "arb_fmpz_poly.h" #include "qqbar.h" void _qqbar_randtest(qqbar_t res, flint_rand_t state, slong deg, slong bits, int real) { fmpz_poly_t pol; slong prec, i, rdeg, r1, r2; acb_ptr roots; deg = FLINT_MAX(deg, 1); bits = FLINT_MAX(bits, 1); if ((deg == 1 || n_randint(state, 4) == 0) && real != 2) { fmpq_t t; fmpq_init(t); do { fmpq_randtest(t, state, bits); } while (fmpz_bits(fmpq_numref(t)) > bits || fmpz_bits(fmpq_denref(t)) > bits); qqbar_set_fmpq(res, t); fmpq_clear(t); return; } fmpz_poly_init(pol); do { fmpz_poly_randtest_irreducible(pol, state, deg + 1, bits); rdeg = fmpz_poly_degree(pol); r1 = rdeg; r2 = 0; if (real) fmpz_poly_signature(&r1, &r2, pol); } while (rdeg < 1 || (real == 1 && r1 < 1) || (real == 2 && r2 < 1)); if (fmpz_sgn(pol->coeffs + rdeg) < 0) fmpz_poly_neg(pol, pol); roots = _acb_vec_init(rdeg); if (real == 0) i = n_randint(state, rdeg); else if (real == 1) i = n_randint(state, r1); else i = r1 + n_randint(state, 2 * r2); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { arb_fmpz_poly_complex_roots(roots, pol, 0, prec); if (_qqbar_validate_uniqueness(roots + i, pol, roots + i, 2 * prec)) { fmpz_poly_set(QQBAR_POLY(res), pol); acb_set(QQBAR_ENCLOSURE(res), roots + i); break; } } _acb_vec_clear(roots, rdeg); fmpz_poly_clear(pol); } void qqbar_randtest(qqbar_t res, flint_rand_t state, slong deg, slong bits) { _qqbar_randtest(res, state, deg, bits, 0); } void qqbar_randtest_real(qqbar_t res, flint_rand_t state, slong deg, slong bits) { _qqbar_randtest(res, state, deg, bits, 1); } void qqbar_randtest_nonreal(qqbar_t res, flint_rand_t state, slong deg, slong bits) { if (deg <= 1) { flint_throw(FLINT_ERROR, "qqbar_randtest_nonreal: must have deg >= 2\n"); } _qqbar_randtest(res, state, deg, bits, 2); } flint-3.1.3/src/qqbar/re.c000066400000000000000000000014751461254215100153110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_re(qqbar_t res, const qqbar_t x) { if (qqbar_sgn_im(x) == 0) { qqbar_set(res, x); } else if (qqbar_sgn_re(x) == 0) { qqbar_zero(res); } else { qqbar_t t; qqbar_init(t); qqbar_conj(t, x); qqbar_add(res, x, t); arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); qqbar_mul_2exp_si(res, res, -1); qqbar_clear(t); } } flint-3.1.3/src/qqbar/re_im.c000066400000000000000000000011651461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_re_im(qqbar_t res1, qqbar_t res2, const qqbar_t x) { if (res1 == x) { qqbar_im(res2, x); qqbar_re(res1, x); } else { qqbar_re(res1, x); qqbar_im(res2, x); } } flint-3.1.3/src/qqbar/root_of_unity.c000066400000000000000000000061451461254215100176010ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpq.h" #include "qqbar.h" int qqbar_is_root_of_unity(slong * p, ulong * q, const qqbar_t x) { ulong n; n = fmpz_poly_is_cyclotomic(QQBAR_POLY(x)); if (n == 0) return 0; if (q != NULL) *q = n; if (n == 1) { if (p != NULL) *p = 0; } else if (n == 2) { if (p != NULL) *p = 1; } else if (n == 3) { if (p != NULL) *p = (qqbar_sgn_im(x) > 0) ? 1 : 2; } else if (n == 4) { if (p != NULL) *p = (qqbar_sgn_im(x) > 0) ? 1 : 3; } else { if (p != NULL) { arb_t t, u; acb_t z; fmpz_t k; slong prec; acb_init(z); arb_init(t); arb_init(u); fmpz_init(k); prec = 64; /* more than enough */ qqbar_get_acb(z, x, prec); acb_arg(t, z, prec); arb_const_pi(u, prec); arb_div(t, t, u, prec); arb_mul_2exp_si(t, t, -1); arb_mul_ui(t, t, n, prec); if (!arb_get_unique_fmpz(k, t)) { flint_throw(FLINT_ERROR, "qqbar_is_root_of_unity: unexpected precision issue\n"); } if (fmpz_sgn(k) < 0) fmpz_add_ui(k, k, n); *p = fmpz_get_si(k); acb_clear(z); arb_clear(t); arb_clear(u); fmpz_clear(k); } } return 1; } void qqbar_root_of_unity(qqbar_t res, slong p, ulong q) { fmpq_t t; ulong a, b; slong prec; fmpq_init(t); if (q == 0) { flint_throw(FLINT_ERROR, "qqbar_root_of_unity: q = 0\n"); } fmpq_set_si(t, p, q); fmpz_fdiv_r(fmpq_numref(t), fmpq_numref(t), fmpq_denref(t)); a = fmpz_get_ui(fmpq_numref(t)); b = fmpz_get_ui(fmpq_denref(t)); if (a == 0) { qqbar_one(res); } else if (a == 1 && b == 2) { qqbar_set_si(res, -1); } else if (a == 1 && b == 4) { qqbar_i(res); } else if (a == 3 && b == 4) { qqbar_i(res); qqbar_conj(res, res); } else { fmpz_poly_cyclotomic(QQBAR_POLY(res), b); fmpq_mul_2exp(t, t, 1); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { arb_sin_cos_pi_fmpq(acb_imagref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), t, prec); /* todo: this is really unnecessary... */ if (_qqbar_validate_uniqueness(QQBAR_ENCLOSURE(res), QQBAR_POLY(res), QQBAR_ENCLOSURE(res), prec * 2)) { break; } } } fmpq_clear(t); } flint-3.1.3/src/qqbar/root_ui.c000066400000000000000000000110131461254215100163500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpz_poly_factor.h" #include "fmpq.h" #include "arb_fmpz_poly.h" #include "qqbar.h" int _qqbar_fast_detect_simple_principal_surd(const qqbar_t x) { slong d; d = qqbar_degree(x); if (d == 1) return 0; if (fmpz_sgn(QQBAR_COEFFS(x)) > 0) return 0; if (!_fmpz_vec_is_zero(QQBAR_COEFFS(x) + 1, d - 1)) return 0; /* Slow exact version, but we only want a fast check here. */ /* return qqbar_is_real(x) && qqbar_sgn_re(x) > 0; */ if (arb_is_zero(acb_imagref(QQBAR_ENCLOSURE(x)))) { if (arb_is_positive(acb_realref(QQBAR_ENCLOSURE(x)))) return 1; return 0; } if (!arb_contains_zero(acb_imagref(QQBAR_ENCLOSURE(x)))) return 0; /* The imaginary part enclosure may not be exactly zero; we can still use the enclosure if it is precise enough to guarantee that there are no collisions with the conjugate roots. */ if (acb_rel_accuracy_bits(QQBAR_ENCLOSURE(x)) > FLINT_BIT_COUNT(d) + 5) return arb_is_positive(acb_realref(QQBAR_ENCLOSURE(x))); return 0; } void qqbar_root_ui(qqbar_t res, const qqbar_t x, ulong n) { if (n == 0) { flint_printf("qqbar_root_ui: n >= 1 is required"); return; } else if (n == 1 || qqbar_is_zero(x) || qqbar_is_one(x)) { qqbar_set(res, x); } else { slong i, d, prec, found; fmpz_poly_t H; fmpz_poly_factor_t fac; acb_t z, w, t; int pure_real; d = qqbar_degree(x); if (FLINT_BIT_COUNT(n) + FLINT_BIT_COUNT(d) > 30) { flint_printf("qqbar_root_ui: ludicrously high degree %wd * %wu", d, n); return; } /* handle principal roots of positive rational numbers */ /* todo: could also handle conjugates of such roots */ if ((d == 1 && (n == 2 || qqbar_sgn_re(x) > 0)) || _qqbar_fast_detect_simple_principal_surd(x)) { fmpq_t t; fmpq_init(t); fmpz_neg(fmpq_numref(t), QQBAR_COEFFS(x)); fmpz_set(fmpq_denref(t), QQBAR_COEFFS(x) + d); qqbar_fmpq_root_ui(res, t, d * n); fmpq_clear(t); return; } /* special-case roots of unity */ /* todo: also specialize rational multiples of roots of unity */ { slong p; ulong q; if (qqbar_is_root_of_unity(&p, &q, x)) { if (2 * p > q) p -= q; qqbar_root_of_unity(res, p, q * n); return; } } fmpz_poly_init(H); fmpz_poly_factor_init(fac); acb_init(z); acb_init(w); acb_init(t); for (i = d; i >= 0; i--) { fmpz_poly_set_coeff_fmpz(H, i * n, QQBAR_COEFFS(x) + i); } fmpz_poly_factor(fac, H); acb_set(z, QQBAR_ENCLOSURE(x)); pure_real = qqbar_is_real(x); for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(z, QQBAR_POLY(x), z, prec); if (pure_real) arb_zero(acb_imagref(z)); acb_root_ui(w, z, n, prec); /* Look for potential roots -- we want exactly one */ found = -1; for (i = 0; i < fac->num && found != -2; i++) { arb_fmpz_poly_evaluate_acb(t, fac->p + i, w, prec); if (acb_contains_zero(t)) { if (found == -1) found = i; else found = -2; } } /* Check if the enclosure is good enough */ if (found >= 0) { if (_qqbar_validate_uniqueness(t, fac->p + found, w, 2 * prec)) { fmpz_poly_set(QQBAR_POLY(res), fac->p + found); acb_set(QQBAR_ENCLOSURE(res), t); break; } } } fmpz_poly_clear(H); fmpz_poly_factor_clear(fac); acb_clear(z); acb_clear(w); acb_clear(t); } } flint-3.1.3/src/qqbar/roots_fmpq_poly.c000066400000000000000000000012211461254215100201240ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_roots_fmpq_poly(qqbar_ptr res, const fmpq_poly_t poly, int flags) { fmpz_poly_t t; /* fake an fmpz_poly */ t->coeffs = poly->coeffs; t->length = poly->length; t->alloc = poly->alloc; qqbar_roots_fmpz_poly(res, t, flags); } flint-3.1.3/src/qqbar/roots_fmpz_poly.c000066400000000000000000000061371461254215100201500ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "fmpq.h" #include "fmpz_poly_factor.h" #include "arb_fmpz_poly.h" #include "qqbar.h" void qqbar_roots_fmpz_poly(qqbar_ptr res, const fmpz_poly_t poly, int flags) { slong d = fmpz_poly_degree(poly); if (d == 0 || d == -1) return; if (d == 1) { fmpq_t t; fmpq_init(t); fmpz_neg(fmpq_numref(t), poly->coeffs); fmpz_set(fmpq_denref(t), poly->coeffs + 1); fmpq_canonicalise(t); /* irreducible, but may still have content */ qqbar_set_fmpq(res, t); fmpq_clear(t); return; } if (flags & QQBAR_ROOTS_IRREDUCIBLE) { slong prec, i, checked; fmpz_t c; acb_ptr croots; croots = _acb_vec_init(d); fmpz_init(c); fmpz_poly_content(c, poly); if (fmpz_sgn(poly->coeffs + d) < 0) fmpz_neg(c, c); for (prec = QQBAR_DEFAULT_PREC; ; prec *= 2) { arb_fmpz_poly_complex_roots(croots, poly, 0, prec); checked = 0; for (i = 0; i < d; i++) { if (_qqbar_validate_uniqueness(croots + i, poly, croots + i, prec)) checked++; else break; } if (checked == d) { for (i = 0; i < d; i++) { if (fmpz_is_one(c)) fmpz_poly_set(QQBAR_POLY(res + i), poly); else fmpz_poly_scalar_divexact_fmpz(QQBAR_POLY(res + i), poly, c); acb_set(QQBAR_ENCLOSURE(res + i), croots + i); } break; } } _acb_vec_clear(croots, d); fmpz_clear(c); } else { fmpz_poly_factor_t fac; qqbar_ptr out; slong i, j, k, e, facd; fmpz_poly_factor_init(fac); fmpz_poly_factor(fac, poly); out = res; for (i = 0; i < fac->num; i++) { facd = fmpz_poly_degree(fac->p + i); qqbar_roots_fmpz_poly(out, fac->p + i, QQBAR_ROOTS_IRREDUCIBLE); e = fac->exp[i]; /* duplicate entries with higher multiplicity */ if (e > 1) { for (j = facd - 1; j >= 0; j--) { qqbar_set(out + j * e, out + j); for (k = 1; k < e; k++) qqbar_set(out + j * e + k, out + j * e); } } out += e * facd; } fmpz_poly_factor_clear(fac); } if (!(flags & QQBAR_ROOTS_UNSORTED)) { qsort(res, d, sizeof(qqbar_struct), (int (*)(const void *, const void *)) qqbar_cmp_root_order); } } flint-3.1.3/src/qqbar/sec_pi.c000066400000000000000000000010711461254215100161350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_sec_pi(qqbar_t res, slong p, ulong q) { qqbar_cos_pi(res, p, q); if (qqbar_is_zero(res)) return 0; qqbar_inv(res, res); return 1; } flint-3.1.3/src/qqbar/set.c000066400000000000000000000011051461254215100154640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_set(qqbar_t res, const qqbar_t x) { fmpz_poly_set(QQBAR_POLY(res), QQBAR_POLY(x)); acb_set(QQBAR_ENCLOSURE(res), QQBAR_ENCLOSURE(x)); } flint-3.1.3/src/qqbar/set_d.c000066400000000000000000000014051461254215100157720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "qqbar.h" int qqbar_set_d(qqbar_t res, double x) { arf_t t; fmpq_t u; int ok; arf_init(t); arf_set_d(t, x); if (arf_is_finite(t)) { fmpq_init(u); arf_get_fmpq(u, t); qqbar_set_fmpq(res, u); ok = 1; fmpq_clear(u); } else { ok = 0; } arf_clear(t); return ok; } flint-3.1.3/src/qqbar/set_fexpr.c000066400000000000000000000733141461254215100167030ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_poly.h" #include "qqbar.h" #include "fexpr.h" #include "fexpr_builtin.h" #ifdef __GNUC__ # define fabs __builtin_fabs # define strchr __builtin_strchr # define strlen __builtin_strlen #else # include # include #endif int qqbar_set_fexpr(qqbar_t res, const fexpr_t expr); int _fexpr_parse_arf(arf_t res, const fexpr_t expr) { if (fexpr_is_integer(expr)) { fmpz_t m; fmpz_init(m); fexpr_get_fmpz(m, expr); arf_set_fmpz(res, m); fmpz_clear(m); return 1; } if (fexpr_is_builtin_call(expr, FEXPR_Neg) && fexpr_nargs(expr) == 1) { int success; fexpr_t t; fexpr_view_arg(t, expr, 0); success = _fexpr_parse_arf(res, t); arf_neg(res, res); return success; } if (fexpr_is_builtin_call(expr, FEXPR_Div) && fexpr_nargs(expr) == 2) { int success; fexpr_t num, den; fmpz_t p, q; fexpr_view_arg(num, expr, 0); fexpr_view_arg(den, expr, 1); fmpz_init(p); fmpz_init(q); success = fexpr_get_fmpz(p, num) && fexpr_get_fmpz(q, den); success = success && (fmpz_sgn(q) > 0) && (fmpz_val2(q) == fmpz_bits(q) - 1); if (success) { arf_set_fmpz(res, p); arf_mul_2exp_si(res, res, -(fmpz_bits(q) - 1)); } fmpz_clear(p); fmpz_clear(q); return success; } if (fexpr_is_builtin_call(expr, FEXPR_Pow) && fexpr_nargs(expr) == 2) { fexpr_t base, exp; fexpr_view_arg(base, expr, 0); fexpr_view_arg(exp, expr, 1); if (fexpr_equal_ui(base, 2)) { fmpz_t m, e; int success; fmpz_init(m); fmpz_init(e); success = fexpr_get_fmpz(e, exp); if (success) { arf_one(res); arf_mul_2exp_fmpz(res, res, e); } fmpz_clear(m); fmpz_clear(e); return success; } } if (fexpr_is_builtin_call(expr, FEXPR_Mul) && fexpr_nargs(expr) == 2) { fexpr_t man, pow, base, exp; fexpr_view_arg(man, expr, 0); fexpr_view_arg(pow, expr, 1); if (fexpr_is_builtin_call(pow, FEXPR_Pow) && fexpr_nargs(expr) == 2) { fexpr_view_arg(base, pow, 0); fexpr_view_arg(exp, pow, 1); if (fexpr_equal_ui(base, 2)) { fmpz_t m, e; int success; fmpz_init(m); fmpz_init(e); success = fexpr_get_fmpz(m, man) && fexpr_get_fmpz(e, exp); if (success) { arf_set_fmpz(res, m); arf_mul_2exp_fmpz(res, res, e); } fmpz_clear(m); fmpz_clear(e); return success; } } } return 0; } int _fexpr_parse_mag(mag_t res, const fexpr_t expr) { int success; arf_t t; arf_init(t); success = _fexpr_parse_arf(t, expr); success = success && (arf_sgn(t) >= 0) && arf_is_finite(t) && (arf_bits(t) <= MAG_BITS); if (success) { fmpz_t m, e; fmpz_init(m); fmpz_init(e); arf_get_fmpz_2exp(m, e, t); mag_set_ui(res, fmpz_get_ui(m)); mag_mul_2exp_fmpz(res, res, e); fmpz_clear(m); fmpz_clear(e); } arf_clear(t); return success; } int _fexpr_parse_arb(arb_t res, const fexpr_t expr) { if (fexpr_is_builtin_call(expr, FEXPR_RealBall) && fexpr_nargs(expr) == 2) { fexpr_t t, u; fexpr_view_arg(t, expr, 0); fexpr_view_arg(u, expr, 1); return _fexpr_parse_arf(arb_midref(res), t) && _fexpr_parse_mag(arb_radref(res), u); } return 0; } int _fexpr_parse_acb(acb_t res, const fexpr_t expr) { fexpr_t t, u; if (fexpr_is_builtin_call(expr, FEXPR_RealBall) && fexpr_nargs(expr) == 2) { arb_zero(acb_imagref(res)); return _fexpr_parse_arb(acb_realref(res), expr); } if (fexpr_is_builtin_call(expr, FEXPR_Mul) && fexpr_nargs(expr) == 2) { fexpr_view_arg(t, expr, 1); if (!fexpr_is_builtin_symbol(t, FEXPR_NumberI)) return 0; fexpr_view_arg(u, expr, 0); arb_zero(acb_realref(res)); return _fexpr_parse_arb(acb_imagref(res), u); } if (fexpr_is_builtin_call(expr, FEXPR_Add) && fexpr_nargs(expr) == 2) { fexpr_view_arg(t, expr, 0); fexpr_view_arg(u, expr, 1); if (_fexpr_parse_acb(res, u) && arb_is_zero(acb_realref(res))) return _fexpr_parse_arb(acb_realref(res), t); } return 0; } int fmpq_set_decimal(fmpq_t res, const char * inp, slong max_bits) { char * emarker; char * buf; int success; slong i; fmpz_t exp; fmpz_t man; slong num_int, num_frac; int after_radix; if (inp[0] == '+') { return fmpq_set_decimal(res, inp + 1, max_bits); } if (inp[0] == '-') { success = fmpq_set_decimal(res, inp + 1, max_bits); fmpq_neg(res, res); return success; } success = 1; fmpz_init(exp); fmpz_init(man); buf = flint_malloc(strlen(inp) + 1); emarker = strchr(inp, 'e'); if (emarker == NULL) emarker = strchr(inp, 'E'); /* parse exponent (0 by default) */ if (emarker != NULL) { /* allow e+42 as well as e42 */ if (emarker[1] == '+') { if (!(emarker[2] >= '0' && emarker[2] <= '9')) success = 0; else success = !fmpz_set_str(exp, emarker + 2, 10); } else success = !fmpz_set_str(exp, emarker + 1, 10); if (!success) goto cleanup; } /* parse floating-point part */ { num_int = 0; num_frac = 0; after_radix = 0; for (i = 0; inp + i != emarker && inp[i] != '\0'; i++) { if (inp[i] == '.' && !after_radix) { after_radix = 1; } else if (inp[i] >= '0' && inp[i] <= '9') { buf[num_int + num_frac] = inp[i]; num_frac += after_radix; num_int += !after_radix; } else { success = 0; goto cleanup; } } buf[num_int + num_frac] = '\0'; /* put trailing zeros into the exponent */ while (num_int + num_frac > 1 && buf[num_int + num_frac - 1] == '0') { buf[num_int + num_frac - 1] = '\0'; num_frac--; } fmpz_sub_si(exp, exp, num_frac); success = !fmpz_set_str(man, buf, 10); if (!success) goto cleanup; } if (fmpz_is_zero(man)) { fmpq_zero(res); } else if (COEFF_IS_MPZ(*exp)) { success = 0; } else { slong e = *exp; double size; size = fmpz_bits(man) + e * 3.321928094887; size = fabs(size); if (size > max_bits) { success = 0; } else { if (e >= 0) { fmpz_set_ui(exp, 10); fmpz_pow_ui(exp, exp, e); fmpz_mul(fmpq_numref(res), man, exp); fmpz_one(fmpq_denref(res)); } else { fmpz_set_ui(exp, 10); fmpz_pow_ui(exp, exp, -e); fmpz_set(fmpq_numref(res), man); fmpz_set(fmpq_denref(res), exp); fmpq_canonicalise(res); } } } if (!success) { fmpq_zero(res); } cleanup: fmpz_clear(exp); fmpz_clear(man); flint_free(buf); return success; } static int _fexpr_check_pi_in_product(const fexpr_t expr) { fexpr_t func, arg, arg2; slong i, nargs; int status, arg_status; if (fexpr_is_atom(expr)) { if (fexpr_is_builtin_symbol(expr, FEXPR_Pi)) return 1; return 0; } nargs = fexpr_nargs(expr); fexpr_view_func(func, expr); if (nargs == 1 && (fexpr_is_builtin_symbol(func, FEXPR_Neg) || fexpr_is_builtin_symbol(func, FEXPR_Pos))) { fexpr_view_arg(arg, expr, 0); return _fexpr_check_pi_in_product(arg); } if (nargs == 2 && (fexpr_is_builtin_symbol(func, FEXPR_Div))) { fexpr_view_arg(arg, expr, 0); fexpr_view_arg(arg2, expr, 1); if (_fexpr_check_pi_in_product(arg2) != 0) return -1; return _fexpr_check_pi_in_product(arg); } if (nargs >= 1 && (fexpr_is_builtin_symbol(func, FEXPR_Mul))) { status = 0; fexpr_view_arg(arg, expr, 0); for (i = 0; i < nargs; i++) { arg_status = _fexpr_check_pi_in_product(arg); if (arg_status == -1) return -1; if (arg_status == 1 && status == 1) return -1; if (arg_status == 1) status = 1; fexpr_view_next(arg); } return status; } return -1; } static int _fexpr_get_rational_arg_pi(fmpq_t res, const fexpr_t expr, int times_i) { int status, success; status = _fexpr_check_pi_in_product(expr); if (status == 0 || status == 1) { fexpr_t tmp, pi, one; qqbar_t v, i; fexpr_init(tmp); fexpr_init(pi); fexpr_init(one); qqbar_init(v); fexpr_set_symbol_builtin(pi, FEXPR_Pi); fexpr_set_si(one, 1); fexpr_replace(tmp, expr, pi, one); success = qqbar_set_fexpr(v, tmp); if (success) { if (times_i) { qqbar_init(i); qqbar_i(i); qqbar_div(v, v, i); qqbar_clear(i); } success = qqbar_is_rational(v); if (success) { fmpz_neg(fmpq_numref(res), QQBAR_COEFFS(v)); fmpz_set(fmpq_denref(res), QQBAR_COEFFS(v) + 1); } } fexpr_clear(tmp); fexpr_clear(pi); fexpr_clear(one); qqbar_clear(v); return success; } return 0; } void qqbar_set_fmpz_poly_root_indexed(qqbar_t res, const fmpz_poly_t poly, slong root_index) { qqbar_ptr roots; slong d; d = fmpz_poly_degree(poly); roots = _qqbar_vec_init(d); qqbar_roots_fmpz_poly(roots, poly, 0); qqbar_set(res, roots + root_index - 1); _qqbar_vec_clear(roots, d); } void qqbar_set_fmpz_poly_root_nearest(qqbar_t res, const fmpz_poly_t poly, const qqbar_t point) { qqbar_ptr roots; slong i, best, d; acb_t t; arb_t distance, best_distance; int overlapping; d = fmpz_poly_degree(poly); roots = _qqbar_vec_init(d); acb_init(t); arb_init(distance); arb_init(best_distance); qqbar_roots_fmpz_poly(roots, poly, 0); acb_sub(t, QQBAR_ENCLOSURE(point), QQBAR_ENCLOSURE(roots), QQBAR_DEFAULT_PREC); acb_abs(best_distance, t, QQBAR_DEFAULT_PREC); best = 0; overlapping = 0; for (i = 1; i < d; i++) { acb_sub(t, QQBAR_ENCLOSURE(point), QQBAR_ENCLOSURE(roots + i), QQBAR_DEFAULT_PREC); acb_abs(distance, t, QQBAR_DEFAULT_PREC); if (arb_lt(distance, best_distance)) { arb_swap(best_distance, distance); best = i; overlapping = 0; } else if (arb_overlaps(distance, best_distance)) { overlapping = 1; } } if (overlapping) { qqbar_t exact_distance, best_exact_distance; qqbar_init(exact_distance); qqbar_init(best_exact_distance); qqbar_sub(best_exact_distance, point, roots + best); qqbar_abs2(best_exact_distance, best_exact_distance); for (i = 0; i < d; i++) { if (i != best) { acb_sub(t, QQBAR_ENCLOSURE(point), QQBAR_ENCLOSURE(roots + i), QQBAR_DEFAULT_PREC); acb_abs(distance, t, QQBAR_DEFAULT_PREC); if (arb_gt(distance, best_distance)) continue; qqbar_sub(exact_distance, point, roots + i); qqbar_abs2(exact_distance, exact_distance); if (qqbar_cmp_re(exact_distance, best_exact_distance) < 0) { qqbar_swap(best_exact_distance, exact_distance); best = i; } } } qqbar_clear(exact_distance); qqbar_clear(best_exact_distance); } qqbar_swap(res, roots + best); acb_clear(t); arb_clear(distance); arb_clear(best_distance); _qqbar_vec_clear(roots, d); } int qqbar_set_fexpr(qqbar_t res, const fexpr_t expr) { fexpr_t func, arg; slong id, i, nargs; qqbar_t t; fmpq_t q; int success; if (fexpr_is_integer(expr)) { fmpz_t t; fmpz_init(t); fexpr_get_fmpz(t, expr); qqbar_set_fmpz(res, t); fmpz_clear(t); return 1; } if (fexpr_is_atom(expr)) { if (fexpr_is_builtin_symbol(expr, FEXPR_NumberI)) { qqbar_i(res); return 1; } if (fexpr_is_builtin_symbol(expr, FEXPR_GoldenRatio)) { qqbar_phi(res); return 1; } return 0; } nargs = fexpr_nargs(expr); fexpr_view_func(func, expr); id = FEXPR_BUILTIN_ID(func->data[0]); switch (id) { case FEXPR_AlgebraicNumberSerialized: case FEXPR_PolynomialRootIndexed: case FEXPR_PolynomialRootNearest: if (nargs == 2) { slong root_index = 0; fexpr_view_arg(arg, expr, 1); if (id == FEXPR_PolynomialRootIndexed) { fmpz_t tmp; fmpz_init(tmp); success = fexpr_get_fmpz(tmp, arg); root_index = *tmp; success = success && (root_index >= 1 && root_index <= COEFF_MAX); fmpz_clear(tmp); } else if (id == FEXPR_PolynomialRootNearest) { root_index = 1; success = qqbar_set_fexpr(res, arg); } else { success = _fexpr_parse_acb(QQBAR_ENCLOSURE(res), arg); } fexpr_view_arg(arg, expr, 0); success = success && fexpr_is_builtin_call(arg, FEXPR_List); if (success) { slong deg, len; len = fexpr_nargs(arg); deg = len - 1; success = (deg >= 1) && (deg >= root_index); if (success) { fmpz_poly_t poly; fexpr_t c; fmpz_poly_init2(poly, len); _fmpz_poly_set_length(poly, len); fexpr_view_arg(c, arg, 0); for (i = 0; i < len && success; i++) { success = fexpr_get_fmpz(poly->coeffs + i, c); fexpr_view_next(c); } if (success) { _fmpz_poly_normalise(poly); deg = fmpz_poly_degree(poly); success = (deg >= root_index); if (success && id == FEXPR_PolynomialRootIndexed) qqbar_set_fmpz_poly_root_indexed(res, poly, root_index); else if (success && id == FEXPR_PolynomialRootNearest) qqbar_set_fmpz_poly_root_nearest(res, poly, res); else if (success) fmpz_poly_swap(QQBAR_POLY(res), poly); } fmpz_poly_clear(poly); return success; } } } break; case FEXPR_Decimal: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = fexpr_is_string(arg); if (success) { char * s = fexpr_get_string(arg); fmpq_init(q); success = fmpq_set_decimal(q, s, COEFF_MAX); if (success) { qqbar_set_fmpq(res, q); } flint_free(s); fmpq_clear(q); } return success; } break; case FEXPR_RootOfUnity: if (nargs == 1 || nargs == 2) { fmpz_t n, k; fmpz_init(n); fmpz_init(k); qqbar_init(t); fmpz_one(k); fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(t, arg) && qqbar_is_integer(t) && (qqbar_sgn_re(t) == 1); if (success) fmpz_neg(n, QQBAR_COEFFS(t)); success = success && !COEFF_IS_MPZ(*n); if (success && nargs == 2) { fexpr_view_arg(arg, expr, 1); success = qqbar_set_fexpr(res, arg) && qqbar_is_integer(res); if (success) { fmpz_neg(k, QQBAR_COEFFS(res)); fmpz_fdiv_r(k, k, n); } } if (success) qqbar_root_of_unity(res, *k, *n); fmpz_clear(n); fmpz_clear(k); qqbar_clear(t); return success; } break; case FEXPR_Exp: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); fmpq_init(q); success = _fexpr_get_rational_arg_pi(q, arg, 1); if (success && !COEFF_IS_MPZ(*fmpq_numref(q)) && !COEFF_IS_MPZ(*fmpq_denref(q))) qqbar_exp_pi_i(res, *fmpq_numref(q), *fmpq_denref(q)); fmpq_clear(q); return success; } break; case FEXPR_Sin: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); fmpq_init(q); success = _fexpr_get_rational_arg_pi(q, arg, 0); if (success && !COEFF_IS_MPZ(*fmpq_numref(q)) && !COEFF_IS_MPZ(*fmpq_denref(q))) qqbar_sin_pi(res, *fmpq_numref(q), *fmpq_denref(q)); fmpq_clear(q); return success; } break; case FEXPR_Cos: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); fmpq_init(q); success = _fexpr_get_rational_arg_pi(q, arg, 0); if (success && !COEFF_IS_MPZ(*fmpq_numref(q)) && !COEFF_IS_MPZ(*fmpq_denref(q))) qqbar_cos_pi(res, *fmpq_numref(q), *fmpq_denref(q)); fmpq_clear(q); return success; } break; case FEXPR_Tan: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); fmpq_init(q); success = _fexpr_get_rational_arg_pi(q, arg, 0); if (success && !COEFF_IS_MPZ(*fmpq_numref(q)) && !COEFF_IS_MPZ(*fmpq_denref(q))) success = qqbar_tan_pi(res, *fmpq_numref(q), *fmpq_denref(q)); fmpq_clear(q); return success; } break; case FEXPR_Cot: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); fmpq_init(q); success = _fexpr_get_rational_arg_pi(q, arg, 0); if (success && !COEFF_IS_MPZ(*fmpq_numref(q)) && !COEFF_IS_MPZ(*fmpq_denref(q))) success = qqbar_cot_pi(res, *fmpq_numref(q), *fmpq_denref(q)); fmpq_clear(q); return success; } break; case FEXPR_Sec: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); fmpq_init(q); success = _fexpr_get_rational_arg_pi(q, arg, 0); if (success && !COEFF_IS_MPZ(*fmpq_numref(q)) && !COEFF_IS_MPZ(*fmpq_denref(q))) success = qqbar_sec_pi(res, *fmpq_numref(q), *fmpq_denref(q)); fmpq_clear(q); return success; } break; case FEXPR_Csc: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); fmpq_init(q); success = _fexpr_get_rational_arg_pi(q, arg, 0); if (success && !COEFF_IS_MPZ(*fmpq_numref(q)) && !COEFF_IS_MPZ(*fmpq_denref(q))) success = qqbar_csc_pi(res, *fmpq_numref(q), *fmpq_denref(q)); fmpq_clear(q); return success; } break; case FEXPR_Pos: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); return success; } break; case FEXPR_Neg: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_neg(res, res); return success; } break; case FEXPR_Sqrt: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_sqrt(res, res); return success; } break; case FEXPR_Conjugate: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_conj(res, res); return success; } break; case FEXPR_Re: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_re(res, res); return success; } break; case FEXPR_Im: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_im(res, res); return success; } break; case FEXPR_Floor: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) { fmpz_t n; fmpz_init(n); qqbar_floor(n, res); qqbar_set_fmpz(res, n); fmpz_clear(n); } return success; } break; case FEXPR_Ceil: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) { fmpz_t n; fmpz_init(n); qqbar_ceil(n, res); qqbar_set_fmpz(res, n); fmpz_clear(n); } return success; } break; case FEXPR_Abs: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_abs(res, res); return success; } break; case FEXPR_Sign: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_sgn(res, res); return success; } break; case FEXPR_Csgn: if (nargs == 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) qqbar_set_si(res, qqbar_csgn(res)); return success; } break; case FEXPR_Sub: if (nargs == 2) { qqbar_init(t); fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) { fexpr_view_next(arg); success = qqbar_set_fexpr(t, arg); if (success) qqbar_sub(res, res, t); } qqbar_clear(t); return success; } break; case FEXPR_Div: if (nargs == 2) { qqbar_init(t); fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) { fexpr_view_next(arg); success = qqbar_set_fexpr(t, arg); success = success && !qqbar_is_zero(t); if (success) qqbar_div(res, res, t); } qqbar_clear(t); return success; } break; case FEXPR_Pow: if (nargs == 2) { qqbar_init(t); fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success) { fexpr_view_next(arg); success = qqbar_set_fexpr(t, arg); success = success && qqbar_is_rational(t) && (!qqbar_is_zero(res) || qqbar_sgn_re(t) >= 0); if (success) { fmpz_t p, q; fmpz_init(p); fmpz_init(q); fmpz_neg(p, QQBAR_COEFFS(t)); fmpz_set(q, QQBAR_COEFFS(t) + 1); success = (fmpz_bits(q) <= 20 && fmpz_bits(p) <= FLINT_BITS - 4); if (success) { qqbar_root_ui(res, res, *q); if (*p >= 0) qqbar_pow_ui(res, res, *p); else { qqbar_pow_ui(res, res, -(*p)); qqbar_inv(res, res); } } } } qqbar_clear(t); return success; } break; case FEXPR_Add: if (nargs == 0) { qqbar_zero(res); return 1; } fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success && nargs > 1) { qqbar_init(t); for (i = 1; i < nargs && success; i++) { fexpr_view_next(arg); success = qqbar_set_fexpr(t, arg); if (success) qqbar_add(res, res, t); } qqbar_clear(t); } return success; case FEXPR_Mul: if (nargs == 0) { qqbar_one(res); return 1; } fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg); if (success && nargs > 1) { qqbar_init(t); for (i = 1; i < nargs && success; i++) { fexpr_view_next(arg); success = qqbar_set_fexpr(t, arg); if (success) qqbar_mul(res, res, t); } qqbar_clear(t); } return success; case FEXPR_Min: case FEXPR_Max: if (nargs >= 1) { fexpr_view_arg(arg, expr, 0); success = qqbar_set_fexpr(res, arg) && qqbar_is_real(res); if (success && nargs >= 2) { qqbar_init(t); for (i = 1; i < nargs && success; i++) { fexpr_view_next(arg); success = qqbar_set_fexpr(t, arg) && qqbar_is_real(t); if (success) { if ((qqbar_cmp_re(res, t) < 0) == (id == FEXPR_Max)) qqbar_swap(res, t); } } qqbar_clear(t); } return success; } default: break; } return 0; } flint-3.1.3/src/qqbar/set_fmpq.c000066400000000000000000000013101461254215100165050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpq.h" #include "qqbar.h" void qqbar_set_fmpq(qqbar_t res, const fmpq_t x) { fmpz_poly_zero(QQBAR_POLY(res)); fmpz_poly_set_coeff_fmpz(QQBAR_POLY(res), 1, fmpq_denref(x)); fmpz_neg(QQBAR_COEFFS(res), fmpq_numref(x)); acb_set_fmpq(QQBAR_ENCLOSURE(res), x, QQBAR_DEFAULT_PREC); } flint-3.1.3/src/qqbar/set_fmpz.c000066400000000000000000000012401461254215100165200ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_set_fmpz(qqbar_t res, const fmpz_t x) { fmpz_poly_zero(QQBAR_POLY(res)); fmpz_poly_set_coeff_si(QQBAR_POLY(res), 1, 1); fmpz_neg(QQBAR_COEFFS(res), x); acb_set_round_fmpz(QQBAR_ENCLOSURE(res), x, QQBAR_DEFAULT_PREC); } flint-3.1.3/src/qqbar/set_re_im.c000066400000000000000000000014161461254215100166440ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_set_re_im(qqbar_t res, const qqbar_t x, const qqbar_t y) { if (qqbar_is_zero(y)) { qqbar_set(res, x); } else { qqbar_t t, u; qqbar_init(t); qqbar_init(u); qqbar_set(t, y); qqbar_i(u); qqbar_mul(t, t, u); qqbar_add(res, x, t); qqbar_clear(t); qqbar_clear(u); } } flint-3.1.3/src/qqbar/set_re_im_d.c000066400000000000000000000016301461254215100171450ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_set_re_im_d(qqbar_t res, double x, double y) { int ok; if (y == 0.0) { ok = qqbar_set_d(res, x); } else { ok = qqbar_set_d(res, y); if (ok) { qqbar_t t; qqbar_init(t); qqbar_i(t); qqbar_mul(res, res, t); if (x != 0) { ok = qqbar_set_d(t, x); qqbar_add(res, res, t); } qqbar_clear(t); } } return ok; } flint-3.1.3/src/qqbar/set_si.c000066400000000000000000000010301461254215100161540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_set_si(qqbar_t res, slong x) { fmpz_t t; fmpz_init_set_si(t, x); qqbar_set_fmpz(res, t); fmpz_clear(t); } flint-3.1.3/src/qqbar/set_ui.c000066400000000000000000000010301461254215100161560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_set_ui(qqbar_t res, ulong x) { fmpz_t t; fmpz_init_set_ui(t, x); qqbar_set_fmpz(res, t); fmpz_clear(t); } flint-3.1.3/src/qqbar/sgn.c000066400000000000000000000015011461254215100154600ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_sgn(qqbar_t res, const qqbar_t x) { int re, im; re = qqbar_sgn_re(x); im = qqbar_sgn_im(x); if (im == 0) { qqbar_set_si(res, re); } else if (re == 0) { qqbar_i(res); if (im < 0) qqbar_neg(res, res); } else { qqbar_t t; qqbar_init(t); qqbar_abs(t, x); qqbar_div(res, x, t); qqbar_clear(t); } } flint-3.1.3/src/qqbar/sgn_im.c000066400000000000000000000032111461254215100161450ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_sgn_im(const qqbar_t x) { if (qqbar_degree(x) == 1) { return 0; } else if (arb_is_zero(acb_imagref(QQBAR_ENCLOSURE(x)))) { return 0; } else if (!arb_contains_zero(acb_imagref(QQBAR_ENCLOSURE(x)))) { return arf_sgn(arb_midref(acb_imagref(QQBAR_ENCLOSURE(x)))); } else { slong prec; int res; acb_t t, u; acb_init(t); acb_init(u); acb_set(t, QQBAR_ENCLOSURE(x)); res = 0; for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(t, QQBAR_POLY(x), t, prec); if (!arb_contains_zero(acb_imagref(t)) || arb_is_zero(acb_imagref(t))) { res = arf_sgn(arb_midref(acb_imagref(t))); break; } #if 0 acb_conj(u, t); acb_union(u, u, t, prec); if (_qqbar_validate_uniqueness(u, QQBAR_POLY(x), u, 2 * prec)) break; #else acb_set(u, t); arb_zero(acb_imagref(u)); if (_qqbar_validate_existence_uniqueness(u, QQBAR_POLY(x), u, 2 * prec)) break; #endif } acb_clear(t); acb_clear(u); return res; } } flint-3.1.3/src/qqbar/sgn_re.c000066400000000000000000000035171461254215100161570ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" int qqbar_sgn_re(const qqbar_t x) { if (qqbar_degree(x) == 1) { return -fmpz_sgn(QQBAR_COEFFS(x)); } else if (arb_is_zero(acb_realref(QQBAR_ENCLOSURE(x)))) { return 0; } else if (!arb_contains_zero(acb_realref(QQBAR_ENCLOSURE(x)))) { return arf_sgn(arb_midref(acb_realref(QQBAR_ENCLOSURE(x)))); } else { slong d, i; slong prec; int res, maybe_zero; acb_t t, u; acb_init(t); acb_init(u); d = qqbar_degree(x); maybe_zero = 1; for (i = 1; i < d && maybe_zero; i += 2) if (!fmpz_is_zero(QQBAR_COEFFS(x) + i)) maybe_zero = 0; acb_set(t, QQBAR_ENCLOSURE(x)); res = 0; for (prec = QQBAR_DEFAULT_PREC / 2; ; prec *= 2) { _qqbar_enclosure_raw(t, QQBAR_POLY(x), t, prec); if (!arb_contains_zero(acb_realref(t)) || arb_is_zero(acb_realref(t))) { res = arf_sgn(arb_midref(acb_realref(t))); break; } if (maybe_zero) { acb_set(u, t); arb_zero(acb_realref(u)); if (_qqbar_validate_existence_uniqueness(u, QQBAR_POLY(x), u, prec * 2)) { res = 0; break; } } } acb_clear(t); acb_clear(u); return res; } } flint-3.1.3/src/qqbar/sin_pi.c000066400000000000000000000010261461254215100161540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_sin_pi(qqbar_t res, slong p, ulong q) { p = p % (2 * (slong) q); qqbar_cos_pi(res, (slong) q - 2 * p, 2 * q); } flint-3.1.3/src/qqbar/sub.c000066400000000000000000000053401461254215100154670ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "qqbar.h" void qqbar_sub(qqbar_t res, const qqbar_t x, const qqbar_t y) { if (qqbar_is_zero(x)) { qqbar_neg(res, y); } else if (qqbar_is_zero(y)) { qqbar_set(res, x); } else if (qqbar_is_rational(y)) { fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_set(a, QQBAR_COEFFS(y) + 1); fmpz_set(b, QQBAR_COEFFS(y)); fmpz_set(c, QQBAR_COEFFS(y) + 1); qqbar_scalar_op(res, x, a, b, c); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } else if (qqbar_is_rational(x)) { fmpz_t a, b, c; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_neg(a, QQBAR_COEFFS(x) + 1); fmpz_neg(b, QQBAR_COEFFS(x)); fmpz_set(c, QQBAR_COEFFS(x) + 1); qqbar_scalar_op(res, y, a, b, c); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } else { qqbar_binary_op(res, x, y, 1); } } void qqbar_sub_fmpq(qqbar_t res, const qqbar_t x, const fmpq_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpq(t, y); qqbar_sub(res, x, t); qqbar_clear(t); } void qqbar_sub_fmpz(qqbar_t res, const qqbar_t x, const fmpz_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpz(t, y); qqbar_sub(res, x, t); qqbar_clear(t); } void qqbar_sub_ui(qqbar_t res, const qqbar_t x, ulong y) { qqbar_t t; qqbar_init(t); qqbar_set_ui(t, y); qqbar_sub(res, x, t); qqbar_clear(t); } void qqbar_sub_si(qqbar_t res, const qqbar_t x, slong y) { qqbar_t t; qqbar_init(t); qqbar_set_si(t, y); qqbar_sub(res, x, t); qqbar_clear(t); } void qqbar_fmpq_sub(qqbar_t res, const fmpq_t x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpq(t, x); qqbar_sub(res, t, y); qqbar_clear(t); } void qqbar_fmpz_sub(qqbar_t res, const fmpz_t x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_fmpz(t, x); qqbar_sub(res, t, y); qqbar_clear(t); } void qqbar_ui_sub(qqbar_t res, ulong x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_ui(t, x); qqbar_sub(res, t, y); qqbar_clear(t); } void qqbar_si_sub(qqbar_t res, slong x, const qqbar_t y) { qqbar_t t; qqbar_init(t); qqbar_set_si(t, x); qqbar_sub(res, t, y); qqbar_clear(t); } flint-3.1.3/src/qqbar/swap.c000066400000000000000000000007721461254215100156540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "qqbar.h" void qqbar_swap(qqbar_t x, qqbar_t y) { FLINT_SWAP(qqbar_struct, *x, *y); } flint-3.1.3/src/qqbar/tan_pi.c000066400000000000000000000030641461254215100161510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "qqbar.h" int qqbar_tan_pi(qqbar_t res, slong p, ulong q) { slong g; g = n_gcd(FLINT_ABS(p), q); if (g != 1) { p /= g; q /= g; } if (q == 1) { qqbar_zero(res); } else if (q == 2) { return 0; } else if (q == 4) { if (p % 4 == 1 || p % 4 == -3) qqbar_one(res); else qqbar_set_si(res, -1); } else if (q == 3) { qqbar_set_ui(res, 3); qqbar_sqrt(res, res); if (p % 3 == -1 || p % 3 == 2) qqbar_neg(res, res); } else if (q == 6) { qqbar_set_ui(res, 3); qqbar_sqrt(res, res); qqbar_inv(res, res); if (p % 6 == -1 || p % 6 == 5) qqbar_neg(res, res); } else { qqbar_t t; qqbar_init(t); qqbar_exp_pi_i(res, 2 * p, q); qqbar_add_ui(res, res, 1); qqbar_inv(res, res); qqbar_mul_2exp_si(res, res, 1); qqbar_sub_ui(res, res, 1); qqbar_i(t); qqbar_mul(res, res, t); arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); qqbar_clear(t); } return 1; } flint-3.1.3/src/qqbar/test/000077500000000000000000000000001461254215100155075ustar00rootroot00000000000000flint-3.1.3/src/qqbar/test/main.c000066400000000000000000000075711461254215100166110ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "fexpr.h" /* Include functions *********************************************************/ #include "t-abs2.c" #include "t-abs.c" #include "t-acos_pi.c" #include "t-acot_pi.c" #include "t-acsc_pi.c" #include "t-add.c" #include "t-asec_pi.c" #include "t-asin_pi.c" #include "t-atan_pi.c" #include "t-ceil.c" #include "t-cmpabs.c" #include "t-cmpabs_im.c" #include "t-cmpabs_re.c" #include "t-cmp_im.c" #include "t-cmp_re.c" #include "t-conjugates.c" #include "t-cos_pi.c" #include "t-cot_pi.c" #include "t-csc_pi.c" #include "t-csgn.c" #include "t-div.c" #include "t-equal_fmpq_poly_val.c" #include "t-evaluate_fmpq_poly.c" #include "t-evaluate_fmpz_mpoly.c" #include "t-exp_pi_i.c" #include "t-express_in_field.c" #include "t-floor.c" #include "t-fmpz_poly_composed_op.c" #include "t-get_acb.c" #include "t-get_fexpr.c" #include "t-get_fexpr_formula.c" #include "t-get_quadratic.c" #include "t-guess.c" #include "t-inv.c" #include "t-log_pi_i.c" #include "t-mul_2exp_si.c" #include "t-mul.c" #include "t-pow.c" #include "t-pow_fmpq.c" #include "t-pow_fmpz.c" #include "t-pow_si.c" #include "t-pow_ui.c" #include "t-randtest.c" #include "t-re_im.c" #include "t-root_of_unity.c" #include "t-roots_fmpz_poly.c" #include "t-root_ui.c" #include "t-sec_pi.c" #include "t-set_d.c" #include "t-set_re_im_d.c" #include "t-sgn.c" #include "t-sgn_re.c" #include "t-sin_pi.c" #include "t-sub.c" #include "t-tan_pi.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(qqbar_abs2), TEST_FUNCTION(qqbar_abs), TEST_FUNCTION(qqbar_acos_pi), TEST_FUNCTION(qqbar_acot_pi), TEST_FUNCTION(qqbar_acsc_pi), TEST_FUNCTION(qqbar_add), TEST_FUNCTION(qqbar_asec_pi), TEST_FUNCTION(qqbar_asin_pi), TEST_FUNCTION(qqbar_atan_pi), TEST_FUNCTION(qqbar_ceil), TEST_FUNCTION(qqbar_cmpabs), TEST_FUNCTION(qqbar_cmpabs_im), TEST_FUNCTION(qqbar_cmpabs_re), TEST_FUNCTION(qqbar_cmp_im), TEST_FUNCTION(qqbar_cmp_re), TEST_FUNCTION(qqbar_conjugates), TEST_FUNCTION(qqbar_cos_pi), TEST_FUNCTION(qqbar_cot_pi), TEST_FUNCTION(qqbar_csc_pi), TEST_FUNCTION(qqbar_csgn), TEST_FUNCTION(qqbar_div), TEST_FUNCTION(qqbar_equal_fmpq_poly_val), TEST_FUNCTION(qqbar_evaluate_fmpq_poly), TEST_FUNCTION(qqbar_evaluate_fmpz_mpoly), TEST_FUNCTION(qqbar_exp_pi_i), TEST_FUNCTION(qqbar_express_in_field), TEST_FUNCTION(qqbar_floor), TEST_FUNCTION(qqbar_fmpz_poly_composed_op), TEST_FUNCTION(qqbar_get_acb), TEST_FUNCTION(qqbar_get_fexpr), TEST_FUNCTION(qqbar_get_fexpr_formula), TEST_FUNCTION(qqbar_get_quadratic), TEST_FUNCTION(qqbar_guess), TEST_FUNCTION(qqbar_inv), TEST_FUNCTION(qqbar_log_pi_i), TEST_FUNCTION(qqbar_mul_2exp_si), TEST_FUNCTION(qqbar_mul), TEST_FUNCTION(qqbar_pow), TEST_FUNCTION(qqbar_pow_fmpq), TEST_FUNCTION(qqbar_pow_fmpz), TEST_FUNCTION(qqbar_pow_si), TEST_FUNCTION(qqbar_pow_ui), TEST_FUNCTION(qqbar_randtest), TEST_FUNCTION(qqbar_re_im), TEST_FUNCTION(qqbar_root_of_unity), TEST_FUNCTION(qqbar_roots_fmpz_poly), TEST_FUNCTION(qqbar_root_ui), TEST_FUNCTION(qqbar_sec_pi), TEST_FUNCTION(qqbar_set_d), TEST_FUNCTION(qqbar_set_re_im_d), TEST_FUNCTION(qqbar_sgn), TEST_FUNCTION(qqbar_sgn_re), TEST_FUNCTION(qqbar_sin_pi), TEST_FUNCTION(qqbar_sub), TEST_FUNCTION(qqbar_tan_pi) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/qqbar/test/t-abs.c000066400000000000000000000030611461254215100166610ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_abs, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, t, u; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(t); qqbar_init(u); qqbar_randtest(x, state, 3, 10); qqbar_randtest(y, state, 3, 10); qqbar_abs(z, x); qqbar_abs(t, y); qqbar_mul(t, t, z); qqbar_mul(u, x, y); qqbar_abs(u, u); if (!qqbar_equal(t, u) || !qqbar_is_real(t)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("t = "); qqbar_print(t); flint_printf("\n\n"); flint_printf("u = "); qqbar_print(t); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(t); qqbar_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-abs2.c000066400000000000000000000023111461254215100167400ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_abs2, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_randtest(x, state, 3, 10); qqbar_abs2(y, x); qqbar_abs(z, x); qqbar_sqr(z, z); if (!qqbar_equal(y, z)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-acos_pi.c000066400000000000000000000030331461254215100175300ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_acos_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int res; qqbar_init(x); qqbar_init(y); q = 1 + n_randint(state, 30); q = 1 + n_randint(state, q); p = n_randint(state, 1000); p -= 500; qqbar_cos_pi(x, p, q); res = qqbar_acos_pi(&p2, &q2, x); if (res) qqbar_cos_pi(y, p2, q2); if (!res || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || !(0 <= p2 && p2 <= (slong) q2)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("res = %d\n\n", res); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-acot_pi.c000066400000000000000000000032051461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_acot_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int res; qqbar_init(x); qqbar_init(y); do { q = 1 + n_randint(state, 15); p = n_randint(state, 1000); p -= 500; /* Don't generate poles */ } while ((q / n_gcd(FLINT_ABS(p), q) == 1)); qqbar_cot_pi(x, p, q); res = qqbar_acot_pi(&p2, &q2, x); if (res) qqbar_cot_pi(y, p2, q2); if (!res || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || !(-(slong) q2 < 2 * p2 && 2 * p2 <= (slong) q2)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("res = %d\n\n", res); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-acsc_pi.c000066400000000000000000000032061461254215100175160ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_acsc_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int res; qqbar_init(x); qqbar_init(y); do { q = 1 + n_randint(state, 15); p = n_randint(state, 1000); p -= 500; /* Don't generate poles */ } while ((q / n_gcd(FLINT_ABS(p), q) == 1)); qqbar_csc_pi(x, p, q); res = qqbar_acsc_pi(&p2, &q2, x); if (res) qqbar_csc_pi(y, p2, q2); if (!res || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || !(-(slong) q2 <= 2 * p2 && 2 * p2 <= (slong) q2)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("res = %d\n\n", res); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-add.c000066400000000000000000000121061461254215100166440ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_add, state) { slong iter; /* Check addition with degree-1 terms, large coefficients */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 20, 100); qqbar_randtest(y, state, 1, 100); qqbar_randtest(z, state, 1, 100); /* check (x + y) + z = x + (y + z) */ qqbar_add(a, x, y); qqbar_add(a, a, z); qqbar_add(b, y, z); qqbar_add(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check addition with degree-1 terms, small coefficients */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 30, 10); qqbar_randtest(y, state, 1, 10); qqbar_randtest(z, state, 1, 10); /* check (x + y) + z = x + (y + z) */ qqbar_add(a, x, y); qqbar_add(a, a, z); qqbar_add(b, y, z); qqbar_add(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check addition with higher-degree terms */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 6, 10); qqbar_randtest(y, state, 6, 10); qqbar_randtest(z, state, 2, 10); /* check (x + y) + z = x + (y + z) */ qqbar_add(a, x, y); qqbar_add(a, a, z); qqbar_add(b, y, z); qqbar_add(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* More iterations, low degree */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 4, 10); qqbar_randtest(y, state, 3, 10); qqbar_randtest(z, state, 2, 10); /* check (x + y) + z = x + (y + z) */ qqbar_add(a, x, y); qqbar_add(a, a, z); qqbar_add(b, y, z); qqbar_add(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-asec_pi.c000066400000000000000000000031641461254215100175230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_asec_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int res; qqbar_init(x); qqbar_init(y); do { q = 1 + n_randint(state, 15); p = n_randint(state, 1000); p -= 500; /* Don't generate poles */ } while ((q / n_gcd(FLINT_ABS(p), q) == 2)); qqbar_sec_pi(x, p, q); res = qqbar_asec_pi(&p2, &q2, x); if (res) qqbar_sec_pi(y, p2, q2); if (!res || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || !(0 <= p2 && p2 <= (slong) q2)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("res = %d\n\n", res); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-asin_pi.c000066400000000000000000000030551461254215100175410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_asin_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int res; qqbar_init(x); qqbar_init(y); q = 1 + n_randint(state, 30); q = 1 + n_randint(state, q); p = n_randint(state, 1000); p -= 500; qqbar_sin_pi(x, p, q); res = qqbar_asin_pi(&p2, &q2, x); if (res) qqbar_sin_pi(y, p2, q2); if (!res || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || !(-(slong) q2 <= 2 * p2 && 2 * p2 <= (slong) q2)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("res = %d\n\n", res); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-atan_pi.c000066400000000000000000000032531461254215100175320ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_atan_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int res; qqbar_init(x); qqbar_init(y); do { q = 1 + n_randint(state, 15); q = 1 + n_randint(state, q); p = n_randint(state, 1000); p -= 500; /* Don't generate poles */ } while (q / n_gcd(FLINT_ABS(p), q) == 2); qqbar_tan_pi(x, p, q); res = qqbar_atan_pi(&p2, &q2, x); if (res) qqbar_tan_pi(y, p2, q2); if (!res || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || !(-(slong) q2 < 2 * p2 && 2 * p2 < (slong) q2)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("res = %d\n\n", res); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-ceil.c000066400000000000000000000037161461254215100170370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_ceil, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, t, u; fmpz_t n, n1; int ok; qqbar_init(x); qqbar_init(y); qqbar_init(t); qqbar_init(u); fmpz_init(n); fmpz_init(n1); if (n_randint(state, 2)) { qqbar_randtest(x, state, 4, 200); } else { fmpq_t c; fmpq_init(c); fmpz_randtest(n, state, 400); fmpq_randtest(c, state, 400); fmpq_add_fmpz(c, c, n); fmpz_zero(n); qqbar_set_fmpq(x, c); qqbar_randtest(y, state, 1, 100); qqbar_i(t); qqbar_mul(y, y, t); qqbar_add(x, x, y); fmpq_clear(c); } qqbar_ceil(n, x); fmpz_sub_ui(n1, n, 1); qqbar_set_fmpz(t, n); qqbar_set_fmpz(u, n1); ok = (qqbar_cmp_re(u, x) < 0 && qqbar_cmp_re(x, t) <= 0); if (!ok) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("n1 = "); fmpz_print(n1); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(t); qqbar_clear(u); fmpz_clear(n); fmpz_clear(n1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-cmp_im.c000066400000000000000000000127041461254215100173640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_cmp_im, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, xr, yr, t, u; int c1, c2; qqbar_init(x); qqbar_init(y); qqbar_init(xr); qqbar_init(yr); qqbar_init(t); qqbar_init(u); qqbar_randtest(x, state, 3, 100); if (n_randint(state, 2)) qqbar_set(y, x); else qqbar_randtest(y, state, 3, 10); if (n_randint(state, 2)) qqbar_conj(y, y); qqbar_randtest_real(t, state, 1, 100); qqbar_i(u); qqbar_mul(t, t, u); qqbar_add(x, x, t); qqbar_im(xr, x); qqbar_im(yr, y); c1 = qqbar_cmp_im(x, y); c2 = qqbar_cmp_re(xr, yr); if (c1 != c2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("%d\n\n", c1); flint_printf("%d\n\n", c2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(xr); qqbar_clear(yr); qqbar_clear(t); qqbar_clear(u); } /* Some branches are difficult to reach with random test cases. */ { qqbar_t x, y, z, i; mag_t eps; int which, ans, want; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(i); mag_init(eps); qqbar_i(i); for (which = 0; which <= 8; which++) { if (which <= 4) { qqbar_set_si(x, 5); qqbar_mul_si(z, i, 3); qqbar_add(x, x, z); qqbar_set_si(y, 6); qqbar_mul_si(z, i, 3); qqbar_add(y, y, z); if (which == 0) { qqbar_set_d(z, 1e-30); qqbar_mul(z, z, i); qqbar_add(x, x, z); want = 1; } else if (which == 1) { qqbar_set_d(z, -1e-30); qqbar_mul(z, z, i); qqbar_add(x, x, z); want = -1; } else if (which == 2) { qqbar_set_d(z, -1e-30); qqbar_mul(z, z, i); qqbar_add(x, x, z); mag_set_d(eps, 1e-15); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(y)), eps); want = -1; } else if (which == 3) { qqbar_set_d(z, 1e-30); qqbar_mul(z, z, i); qqbar_add(x, x, z); mag_set_d(eps, 1e-15); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(y)), eps); want = 1; } else if (which == 4) { mag_set_d(eps, 1e-10); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(x)), eps); mag_set_d(eps, 1e-15); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(y)), eps); want = 0; } } else if (which == 5) { qqbar_set_si(x, 5); qqbar_set_si(y, 6); mag_set_d(eps, 1e-10); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(y)), eps); want = 0; } else if (which == 6) { qqbar_sqrt_ui(x, 2); qqbar_set_si(y, 1); qqbar_add(y, y, i); mag_set_d(eps, 1.1); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(y)), eps); want = -1; } else if (which == 7) { qqbar_sqrt_ui(x, 2); qqbar_set_si(y, 1); qqbar_sub(y, y, i); mag_set_d(eps, 1.1); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(y)), eps); want = 1; } else if (which == 8) { qqbar_sqrt_ui(x, 2); qqbar_sqrt_ui(y, 3); mag_set_d(eps, 0.5); arb_add_error_mag(acb_imagref(QQBAR_ENCLOSURE(y)), eps); want = 0; } ans = qqbar_cmp_im(x, y); if (ans != want) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("%d\n\n", ans); flint_printf("%d\n\n", want); flint_abort(); } } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(i); mag_clear(eps); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-cmp_re.c000066400000000000000000000033601461254215100173630ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_cmp_re, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, xr, yr, t, u; int c1, c2; qqbar_init(x); qqbar_init(y); qqbar_init(xr); qqbar_init(yr); qqbar_init(t); qqbar_init(u); qqbar_randtest(x, state, 3, 100); if (n_randint(state, 2)) qqbar_set(y, x); else qqbar_randtest(y, state, 3, 10); if (n_randint(state, 2)) qqbar_conj(y, y); qqbar_randtest_real(t, state, 1, 100); qqbar_i(u); qqbar_mul(t, t, u); qqbar_add(x, x, t); qqbar_re(xr, x); qqbar_re(yr, y); qqbar_sub(t, xr, yr); c1 = qqbar_cmp_re(x, y); c2 = qqbar_sgn_re(t); if (c1 != c2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("%d\n\n", c1); flint_printf("%d\n\n", c2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(xr); qqbar_clear(yr); qqbar_clear(t); qqbar_clear(u); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-cmpabs.c000066400000000000000000000030001461254215100173520ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_cmpabs, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, xr, yr; int c1, c2; qqbar_init(x); qqbar_init(y); qqbar_init(xr); qqbar_init(yr); qqbar_randtest(x, state, 3, 100); qqbar_randtest(y, state, 3, 100); qqbar_abs(xr, x); qqbar_abs(yr, y); c1 = qqbar_cmpabs(x, y); c2 = qqbar_cmp_re(xr, yr); if (c1 != c2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("xr = "); qqbar_print(xr); flint_printf("\n\n"); flint_printf("yr = "); qqbar_print(yr); flint_printf("\n\n"); flint_printf("%d\n\n", c1); flint_printf("%d\n\n", c2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(xr); qqbar_clear(yr); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-cmpabs_im.c000066400000000000000000000034741461254215100200560ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_cmpabs_im, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, xr, yr, z, i; int c1, c2; qqbar_init(x); qqbar_init(y); qqbar_init(xr); qqbar_init(yr); qqbar_init(z); qqbar_init(i); qqbar_randtest(x, state, 3, 100); if (n_randint(state, 4) == 0) qqbar_conj(y, x); else qqbar_randtest(y, state, 3, 100); qqbar_im(xr, x); qqbar_im(yr, y); qqbar_abs(xr, xr); qqbar_abs(yr, yr); if (n_randint(state, 2)) { qqbar_i(i); qqbar_randtest(z, state, 1, 100); qqbar_mul(z, z, i); qqbar_add(x, x, z); qqbar_sub(x, x, z); } c1 = qqbar_cmpabs_im(x, y); c2 = qqbar_cmp_re(xr, yr); if (c1 != c2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("%d\n\n", c1); flint_printf("%d\n\n", c2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(xr); qqbar_clear(yr); qqbar_clear(z); qqbar_clear(i); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-cmpabs_re.c000066400000000000000000000032361461254215100200530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_cmpabs_re, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, xr, yr, z; int c1, c2; qqbar_init(x); qqbar_init(y); qqbar_init(xr); qqbar_init(yr); qqbar_init(z); qqbar_randtest(x, state, 3, 100); qqbar_randtest(y, state, 3, 100); qqbar_re(xr, x); qqbar_re(yr, y); qqbar_abs(xr, xr); qqbar_abs(yr, yr); qqbar_randtest(z, state, 1, 100); qqbar_add(x, x, z); qqbar_sub(x, x, z); qqbar_randtest(z, state, 1, 100); qqbar_add(y, y, z); qqbar_sub(y, y, z); c1 = qqbar_cmpabs_re(x, y); c2 = qqbar_cmp_re(xr, yr); if (c1 != c2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("%d\n\n", c1); flint_printf("%d\n\n", c2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(xr); qqbar_clear(yr); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-conjugates.c000066400000000000000000000033351461254215100202620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_conjugates, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; qqbar_ptr r; fmpq_t s; slong i, d; qqbar_init(x); qqbar_init(y); qqbar_init(z); fmpq_init(s); qqbar_randtest(x, state, 4, 10); d = qqbar_degree(x); r = _qqbar_vec_init(d); qqbar_conjugates(r, x); for (i = 0; i < d; i++) qqbar_add(y, y, r + i); fmpq_set_fmpz_frac(s, QQBAR_COEFFS(x) + d - 1, QQBAR_COEFFS(x) + d); fmpq_neg(s, s); qqbar_set_fmpq(z, s); if (!qqbar_equal(y, z)) { flint_printf("FAIL! %d\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); for (i = 0; i < d; i++) { flint_printf("r%wd = ", i); qqbar_print(r + i); flint_printf("\n\n"); } flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); _qqbar_vec_clear(r, d); fmpq_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-cos_pi.c000066400000000000000000000030641461254215100173730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_cos_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; arb_t z, w; fmpq_t t; slong p; ulong q; slong prec; qqbar_init(x); arb_init(z); arb_init(w); fmpq_init(t); q = 1 + n_randint(state, 30); p = n_randint(state, 1000); p -= 500; prec = 2 + n_randint(state, 1000); qqbar_cos_pi(x, p, q); qqbar_get_arb(z, x, prec); fmpq_set_si(t, p, q); arb_cos_pi_fmpq(w, t, prec); if (!arb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 200, 0); flint_printf("\n\n"); flint_printf("w = "); arb_printn(w, 200, 0); flint_printf("\n\n"); flint_printf("p, q = %wd %wu\n\n", p, q); flint_abort(); } qqbar_clear(x); arb_clear(z); arb_clear(w); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-cot_pi.c000066400000000000000000000033261461254215100173750ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_cot_pi, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; arb_t z, w; fmpq_t t; slong p; ulong q; slong prec; qqbar_init(x); arb_init(z); arb_init(w); fmpq_init(t); q = 1 + n_randint(state, 20); p = n_randint(state, 1000); p -= 500; prec = 2 + n_randint(state, 1000); fmpq_set_si(t, p, q); arb_sin_pi_fmpq(w, t, prec); arb_cos_pi_fmpq(z, t, prec); arb_div(w, z, w, prec); if (arb_is_finite(w)) { qqbar_cot_pi(x, p, q); qqbar_get_arb(z, x, prec); if (!arb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 200, 0); flint_printf("\n\n"); flint_printf("w = "); arb_printn(w, 200, 0); flint_printf("\n\n"); flint_printf("p, q = %wd %wu\n\n", p, q); flint_abort(); } } qqbar_clear(x); arb_clear(z); arb_clear(w); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-csc_pi.c000066400000000000000000000032561461254215100173620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_csc_pi, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; arb_t z, w; fmpq_t t; slong p; ulong q; slong prec; qqbar_init(x); arb_init(z); arb_init(w); fmpq_init(t); q = 1 + n_randint(state, 20); p = n_randint(state, 1000); p -= 500; prec = 2 + n_randint(state, 1000); fmpq_set_si(t, p, q); arb_sin_pi_fmpq(w, t, prec); arb_inv(w, w, prec); if (arb_is_finite(w)) { qqbar_csc_pi(x, p, q); qqbar_get_arb(z, x, prec); if (!arb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 200, 0); flint_printf("\n\n"); flint_printf("w = "); arb_printn(w, 200, 0); flint_printf("\n\n"); flint_printf("p, q = %wd %wu\n\n", p, q); flint_abort(); } } qqbar_clear(x); arb_clear(z); arb_clear(w); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-csgn.c000066400000000000000000000025541461254215100170540ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_csgn, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_randtest(x, state, 4, 8); qqbar_set_si(y, qqbar_csgn(x)); if (qqbar_is_zero(x)) { qqbar_zero(z); } else { qqbar_sqr(z, x); qqbar_sqrt(z, z); qqbar_div(z, z, x); } if (!qqbar_equal(y, z)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-div.c000066400000000000000000000132671461254215100167070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_div, state) { slong iter; /* Check division with degree-1 terms, large coefficients */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); do { qqbar_randtest(x, state, 20, 100); } while (qqbar_is_zero(x)); do { qqbar_randtest(y, state, 1, 100); } while (qqbar_is_zero(y)); qqbar_randtest(z, state, 1, 100); /* check z / (x / y) = (z / x) * y */ qqbar_div(a, x, y); qqbar_div(a, z, a); qqbar_div(b, z, x); qqbar_mul(b, b, y); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check division with degree-1 terms, small coefficients */ for (iter = 0; iter < 100; iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); do { qqbar_randtest(x, state, 30, 10); } while (qqbar_is_zero(x)); do { qqbar_randtest(y, state, 1, 10); } while (qqbar_is_zero(y)); qqbar_randtest(z, state, 1, 10); /* check z / (x / y) = (z / x) * y */ qqbar_div(a, x, y); qqbar_div(a, z, a); qqbar_div(b, z, x); qqbar_mul(b, b, y); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check division with higher-degree terms */ for (iter = 0; iter < 100; iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); do { qqbar_randtest(x, state, 6, 10); } while (qqbar_is_zero(x)); do { qqbar_randtest(y, state, 6, 10); } while (qqbar_is_zero(y)); qqbar_randtest(z, state, 2, 10); /* check z / (x / y) = (z / x) * y */ qqbar_div(a, x, y); qqbar_div(a, z, a); qqbar_div(b, z, x); qqbar_mul(b, b, y); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check roots of rational numbers, which are special-cased. */ for (iter = 0; iter < 100; iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); do { qqbar_randtest(x, state, 1, 10); } while (qqbar_is_zero(x)); qqbar_pow_ui(x, x, 1 + n_randint(state, 3)); qqbar_abs(x, x); qqbar_root_ui(x, x, 1 + n_randint(state, 10)); do { qqbar_randtest(y, state, 1, 10); } while (qqbar_is_zero(y)); qqbar_pow_ui(y, y, 1 + n_randint(state, 3)); qqbar_abs(y, y); qqbar_root_ui(y, y, 1 + n_randint(state, 10)); qqbar_randtest(z, state, 2, 10); /* check z / (x / y) = (z / x) * y */ qqbar_div(a, x, y); qqbar_div(a, z, a); qqbar_div(b, z, x); qqbar_mul(b, b, y); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-equal_fmpq_poly_val.c000066400000000000000000000044671461254215100221660ustar00rootroot00000000000000/* Copyright (C) 2021 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "qqbar.h" int qqbar_equal_fmpq_poly_val2(const qqbar_t x, const fmpq_poly_t f, const qqbar_t y) { int found; qqbar_t v; qqbar_init(v); qqbar_evaluate_fmpq_poly(v, f, y); found = qqbar_equal(v, x); qqbar_clear(v); return found; } TEST_FUNCTION_START(qqbar_equal_fmpq_poly_val, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; qqbar_ptr v; fmpq_poly_t f; int equal1, equal2; slong d; qqbar_init(x); qqbar_init(y); fmpq_poly_init(f); if (n_randint(state, 2)) qqbar_randtest(y, state, 4, 10); else qqbar_randtest(y, state, 2, 100); do { fmpq_poly_randtest(f, state, 10, 10); } while (f->length == 0); switch (n_randint(state, 3)) { case 0: qqbar_randtest(x, state, 4, 20); break; case 1: qqbar_evaluate_fmpq_poly(x, f, y); break; default: qqbar_evaluate_fmpq_poly(x, f, y); d = qqbar_degree(x); v = _qqbar_vec_init(d); qqbar_conjugates(v, x); qqbar_set(x, v + n_randint(state, d)); _qqbar_vec_clear(v, d); } equal1 = qqbar_equal_fmpq_poly_val(x, f, y); equal2 = qqbar_equal_fmpq_poly_val2(x, f, y); if (equal1 != equal2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("f = "); fmpq_poly_print(f); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); fmpq_poly_clear(f); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-evaluate_fmpq_poly.c000066400000000000000000000042231461254215100220110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq_poly.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_evaluate_fmpq_poly, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpq_poly_t f, g, h; qqbar_t x, fx, gx, hx, y; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_init(h); qqbar_init(x); qqbar_init(fx); qqbar_init(gx); qqbar_init(hx); qqbar_init(y); qqbar_randtest(x, state, 4, 10); qqbar_randtest(y, state, 4, 10); fmpq_poly_randtest(f, state, 8, 10); fmpq_poly_randtest(g, state, 5, 10); fmpq_poly_add(h, f, g); qqbar_evaluate_fmpq_poly(fx, f, x); qqbar_evaluate_fmpq_poly(gx, g, x); qqbar_evaluate_fmpq_poly(hx, h, x); qqbar_add(y, fx, gx); if (!qqbar_equal(y, hx)) { flint_printf("FAIL!\n"); flint_printf("f = "); fmpq_poly_print(f); flint_printf("\n\n"); flint_printf("g = "); fmpq_poly_print(g); flint_printf("\n\n"); flint_printf("h = "); fmpq_poly_print(h); flint_printf("\n\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("fx = "); qqbar_print(fx); flint_printf("\n\n"); flint_printf("gx = "); qqbar_print(gx); flint_printf("\n\n"); flint_printf("hx = "); qqbar_print(hx); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); qqbar_clear(x); qqbar_clear(fx); qqbar_clear(gx); qqbar_clear(hx); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-evaluate_fmpz_mpoly.c000066400000000000000000000054151461254215100222030ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_mpoly.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_evaluate_fmpz_mpoly, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong i, n; fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; qqbar_ptr x; qqbar_t fx, gx, hx, y; int s1, s2, s3; n = 1 + n_randint(state, 5); fmpz_mpoly_ctx_init(ctx, n, ORD_LEX); fmpz_mpoly_init(f, ctx); fmpz_mpoly_init(g, ctx); fmpz_mpoly_init(h, ctx); x = _qqbar_vec_init(n); qqbar_init(fx); qqbar_init(gx); qqbar_init(hx); qqbar_init(y); for (i = 0; i < n; i++) qqbar_randtest(x + i, state, 1 + n_randint(state, 2), 10); fmpz_mpoly_randtest_bound(f, state, 1 + n_randint(state, 30), 10, 1 + n_randint(state, 4), ctx); fmpz_mpoly_randtest_bound(g, state, 1 + n_randint(state, 30), 10, 1 + n_randint(state, 4), ctx); fmpz_mpoly_add(h, f, g, ctx); s1 = qqbar_evaluate_fmpz_mpoly(fx, f, x, 40, 1000, ctx); s2 = qqbar_evaluate_fmpz_mpoly(gx, g, x, 40, 1000, ctx); s3 = qqbar_evaluate_fmpz_mpoly(hx, h, x, 40, 1000, ctx); qqbar_add(y, fx, gx); if (s1 && s2 && s3 && !qqbar_equal(y, hx)) { flint_printf("FAIL!\n"); flint_printf("f = "); fmpz_mpoly_print_pretty(f, NULL, ctx); flint_printf("\n\n"); flint_printf("g = "); fmpz_mpoly_print_pretty(g, NULL, ctx); flint_printf("\n\n"); flint_printf("h = "); fmpz_mpoly_print_pretty(h, NULL, ctx); flint_printf("\n\n"); for (i = 0; i < n; i++) { flint_printf("x%wd = ", i + 1); qqbar_print(x + i); flint_printf("\n\n"); } flint_printf("fx = "); qqbar_print(fx); flint_printf("\n\n"); flint_printf("gx = "); qqbar_print(gx); flint_printf("\n\n"); flint_printf("hx = "); qqbar_print(hx); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); _qqbar_vec_clear(x, n); qqbar_clear(fx); qqbar_clear(gx); qqbar_clear(hx); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-exp_pi_i.c000066400000000000000000000031301461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_exp_pi_i, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; acb_t z, w; fmpq_t t; slong p; ulong q; slong prec; qqbar_init(x); acb_init(z); acb_init(w); fmpq_init(t); q = 1 + n_randint(state, 20); p = n_randint(state, 1000); p -= 500; prec = 2 + n_randint(state, 1000); fmpq_set_si(t, p, q); arb_sin_cos_pi_fmpq(acb_imagref(w), acb_realref(w), t, prec); qqbar_exp_pi_i(x, p, q); qqbar_get_acb(z, x, prec); if (!acb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 200, 0); flint_printf("\n\n"); flint_printf("w = "); acb_printn(w, 200, 0); flint_printf("\n\n"); flint_printf("p, q = %wd %wu\n\n", p, q); flint_abort(); } qqbar_clear(x); acb_clear(z); acb_clear(w); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-express_in_field.c000066400000000000000000000041551461254215100214430ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpq_poly.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_express_in_field, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { fmpq_poly_t f, g; qqbar_t x, alpha; slong prec, max_bits; fmpq_poly_init(f); fmpq_poly_init(g); qqbar_init(x); qqbar_init(alpha); if (n_randint(state, 2)) qqbar_randtest(alpha, state, 4, 100); else qqbar_randtest(alpha, state, 6, 10); if (n_randint(state, 4) == 0) fmpq_poly_randtest(f, state, qqbar_degree(alpha), 100); else fmpq_poly_randtest(f, state, qqbar_degree(alpha), 8); max_bits = _fmpz_vec_max_bits(f->coeffs, f->length); max_bits = FLINT_ABS(max_bits); max_bits = FLINT_MAX(max_bits, fmpz_bits(f->den)); qqbar_evaluate_fmpq_poly(x, f, alpha); for (prec = 64; ; prec *= 2) { if (qqbar_express_in_field(g, alpha, x, max_bits, 0, prec)) break; if (prec > 10000) { flint_printf("FAIL!\n"); flint_printf("alpha = "); qqbar_print(alpha); flint_printf("\n\n"); flint_printf("f = "); fmpq_poly_print(f); flint_printf("\n\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("g = "); fmpq_poly_print(g); flint_printf("\n\n"); flint_printf("prec = %wd\n\n", prec); flint_abort(); } } fmpq_poly_clear(f); fmpq_poly_clear(g); qqbar_clear(alpha); qqbar_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-floor.c000066400000000000000000000037201461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_floor, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, t, u; fmpz_t n, n1; int ok; qqbar_init(x); qqbar_init(y); qqbar_init(t); qqbar_init(u); fmpz_init(n); fmpz_init(n1); if (n_randint(state, 2)) { qqbar_randtest(x, state, 4, 200); } else { fmpq_t c; fmpq_init(c); fmpz_randtest(n, state, 400); fmpq_randtest(c, state, 400); fmpq_add_fmpz(c, c, n); fmpz_zero(n); qqbar_set_fmpq(x, c); qqbar_randtest(y, state, 1, 100); qqbar_i(t); qqbar_mul(y, y, t); qqbar_add(x, x, y); fmpq_clear(c); } qqbar_floor(n, x); fmpz_add_ui(n1, n, 1); qqbar_set_fmpz(t, n); qqbar_set_fmpz(u, n1); ok = (qqbar_cmp_re(t, x) <= 0 && qqbar_cmp_re(x, u) < 0); if (!ok) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("n1 = "); fmpz_print(n1); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(t); qqbar_clear(u); fmpz_clear(n); fmpz_clear(n1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-fmpz_poly_composed_op.c000066400000000000000000000066361461254215100225350ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq.h" #include "fmpq_poly.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_fmpz_poly_composed_op, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { slong m, n, i, j, k; fmpz *r1, *r2; fmpz_poly_t A, B, C; fmpq_t x, y; int op; m = 1 + n_randint(state, 8); n = 1 + n_randint(state, 8); op = n_randint(state, 4); i = n_randint(state, m); j = n_randint(state, n); op = n_randint(state, 4); r1 = _fmpz_vec_init(m); r2 = _fmpz_vec_init(n); fmpz_poly_init(A); fmpz_poly_init(B); fmpz_poly_init(C); fmpq_init(x); fmpq_init(y); _fmpz_vec_randtest(r1, state, m, 10); _fmpz_vec_randtest(r2, state, n, 10); /* Don't divide by zero */ if (op == 3) { for (k = 0; k < n; k++) { if (fmpz_is_zero(r2 + k)) fmpz_one(r2 + k); } } fmpz_poly_product_roots_fmpz_vec(A, r1, m); fmpz_poly_product_roots_fmpz_vec(B, r2, n); if (n_randint(state, 2)) { fmpz_randtest_not_zero(fmpq_numref(x), state, 10); fmpz_poly_scalar_mul_fmpz(A, A, fmpq_numref(x)); fmpz_randtest_not_zero(fmpq_numref(x), state, 10); fmpz_poly_scalar_mul_fmpz(B, B, fmpq_numref(x)); } /* output noise */ fmpz_poly_randtest(C, state, 10, 100); qqbar_fmpz_poly_composed_op(C, A, B, op); if (op == 0) { fmpz_add(fmpq_numref(x), r1 + i, r2 + j); fmpz_one(fmpq_denref(x)); } else if (op == 1) { fmpz_sub(fmpq_numref(x), r1 + i, r2 + j); fmpz_one(fmpq_denref(x)); } else if (op == 2) { fmpz_mul(fmpq_numref(x), r1 + i, r2 + j); fmpz_one(fmpq_denref(x)); } else { fmpq_set_fmpz_frac(x, r1 + i, r2 + j); } fmpz_poly_evaluate_fmpq(y, C, x); if (!fmpq_is_zero(y)) { flint_printf("FAIL!\n"); flint_printf("op = %d\n", op); flint_printf("A = "); fmpz_poly_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpz_poly_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpz_poly_print(C); flint_printf("\n\n"); flint_printf("r1 = "); fmpz_print(r1 + i); flint_printf("\n\n"); flint_printf("r2 = "); fmpz_print(r2 + j); flint_printf("\n\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\n\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n\n"); flint_abort(); } _fmpz_vec_clear(r1, m); _fmpz_vec_clear(r2, n); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(C); fmpq_clear(x); fmpq_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-get_acb.c000066400000000000000000000057251461254215100175110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_get_acb, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; acb_t z, w; slong prec1, prec2, acc1, acc2; qqbar_init(x); acb_init(z); acb_init(w); qqbar_randtest(x, state, 3, 400); prec1 = 2 + n_randint(state, 800); prec2 = prec1 + 2 + n_randint(state, 400); qqbar_get_acb(z, x, prec1); qqbar_get_acb(w, x, prec2); acc1 = arb_rel_accuracy_bits(acb_realref(z)); acc2 = arb_rel_accuracy_bits(acb_imagref(z)); if (acc1 < prec1 - 2 || acc2 < prec1 - 2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); acb_printn(z, 1000, ARB_STR_CONDENSE * 30); flint_printf("\n\n"); flint_printf("prec1 = %wd, acc1 = %wd, acc2 = %wd\n\n", prec1, acc1, acc2); flint_abort(); } acc1 = arb_rel_accuracy_bits(acb_realref(w)); acc2 = arb_rel_accuracy_bits(acb_imagref(w)); if (acc1 < prec2 - 2 || acc2 < prec2 - 2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("w = "); acb_printn(w, 1000, ARB_STR_CONDENSE * 30); flint_printf("\n\n"); flint_printf("prec2 = %wd, acc1 = %wd, acc2 = %wd\n\n", prec2, acc1, acc2); flint_abort(); } if (!acb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z re = "); arb_printn(acb_realref(z), 1000, 0); flint_printf("\n\n"); flint_printf("z im = "); arb_printn(acb_imagref(z), 1000, 0); flint_printf("\n\n"); flint_printf("w re = "); arb_printn(acb_realref(w), 1000, 0); flint_printf("\n\n"); flint_printf("w im = "); arb_printn(acb_imagref(w), 1000, 0); flint_printf("\n\n"); flint_printf("z re = "); arb_print(acb_realref(z)); flint_printf("\n\n"); flint_printf("z im = "); arb_print(acb_imagref(z)); flint_printf("\n\n"); flint_printf("w re = "); arb_print(acb_realref(w)); flint_printf("\n\n"); flint_printf("w im = "); arb_print(acb_imagref(w)); flint_printf("\n\n"); flint_printf("prec1 = %wd, prec2 = %wd\n\n", prec1, prec2); flint_abort(); } qqbar_clear(x); acb_clear(z); acb_clear(w); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-get_fexpr.c000066400000000000000000000050201461254215100200740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fexpr.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_get_fexpr, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; fexpr_t e; qqbar_init(x); qqbar_init(y); fexpr_init(e); if (n_randint(state, 2)) qqbar_randtest(x, state, 2, 10); else if (n_randint(state, 2)) qqbar_randtest(x, state, 5, 100); else qqbar_randtest(x, state, 20, 20); qqbar_get_fexpr_repr(e, x); if (!qqbar_set_fexpr(y, e) || !qqbar_equal(x, y)) { flint_printf("FAIL! (repr)\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("e = "); fexpr_print(e); flint_printf("\n\n"); flint_abort(); } qqbar_get_fexpr_root_indexed(e, x); qqbar_zero(y); if (!qqbar_set_fexpr(y, e) || !qqbar_equal(x, y)) { flint_printf("FAIL! (root_indexed)\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("e = "); fexpr_print(e); flint_printf("\n\n"); flint_abort(); } /* flint_printf("%wd\n", iter); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); */ qqbar_get_fexpr_root_nearest(e, x); qqbar_zero(y); /* flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("e = "); fexpr_print(e); flint_printf("\n\n"); */ if (!qqbar_set_fexpr(y, e) || !qqbar_equal(x, y)) { flint_printf("FAIL! (root_nearest)\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("e = "); fexpr_print(e); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); fexpr_clear(e); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-get_fexpr_formula.c000066400000000000000000000075261461254215100216360ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpq.h" #include "fexpr.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_get_fexpr_formula, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; fexpr_t e; ulong flags; qqbar_init(x); qqbar_init(y); fexpr_init(e); qqbar_randtest(x, state, 5, 10); if (n_randint(state, 2)) flags = n_randlimb(state); else flags = QQBAR_FORMULA_ALL; if (qqbar_get_fexpr_formula(e, x, flags)) { qqbar_set_fexpr(y, e); if (!qqbar_equal(x, y)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("e = "); fexpr_print(e); flint_printf("\n\n"); flint_abort(); } } qqbar_clear(x); qqbar_clear(y); fexpr_clear(e); } /* test trigonometrics and exponentials */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; fexpr_t e; slong p, q; fmpq_t a; qqbar_init(x); qqbar_init(y); fexpr_init(e); fmpq_init(a); p = -10 + n_randint(state, 100); if (n_randint(state, 10)) q = 1 + n_randint(state, 6); else q = 1 + n_randint(state, 10); switch (n_randint(state, 7)) { case 0: qqbar_exp_pi_i(x, p, q); break; case 1: qqbar_sin_pi(x, p, q); break; case 2: qqbar_cos_pi(x, p, q); break; case 3: qqbar_tan_pi(x, p, q); break; case 4: qqbar_cot_pi(x, p, q); break; case 5: qqbar_sec_pi(x, p, q); break; case 6: qqbar_csc_pi(x, p, q); break; } fmpq_randtest(a, state, 3); qqbar_add_fmpq(x, x, a); fmpq_randtest(a, state, 3); qqbar_mul_fmpq(x, x, a); if (qqbar_degree(x) <= 2) { p = -10 + n_randint(state, 100); q = 1 + n_randint(state, 6); switch (n_randint(state, 7)) { case 0: qqbar_exp_pi_i(y, p, q); break; case 1: qqbar_sin_pi(y, p, q); break; case 2: qqbar_cos_pi(y, p, q); break; case 3: qqbar_tan_pi(y, p, q); break; case 4: qqbar_cot_pi(y, p, q); break; case 5: qqbar_sec_pi(y, p, q); break; case 6: qqbar_csc_pi(y, p, q); break; } qqbar_add(x, x, y); qqbar_zero(y); } if (qqbar_get_fexpr_formula(e, x, QQBAR_FORMULA_ALL)) { qqbar_set_fexpr(y, e); if (!qqbar_equal(x, y)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("e = "); fexpr_print(e); flint_printf("\n\n"); flint_abort(); } } else { flint_printf("Unexpected:\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); } qqbar_clear(x); qqbar_clear(y); fexpr_clear(e); fmpq_clear(a); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-get_quadratic.c000066400000000000000000000055631461254215100207410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_get_quadratic, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; fmpz_t a, b, c, q, d, n; qqbar_init(x); qqbar_init(y); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(q); fmpz_init(d); fmpz_init(n); switch (n_randint(state, 3)) { case 0: qqbar_randtest(x, state, 2, 2 + n_randint(state, 20)); qqbar_get_quadratic(a, b, c, q, x, 1); break; case 1: qqbar_randtest(x, state, 2, 2 + n_randint(state, 40)); qqbar_get_quadratic(a, b, c, q, x, 2); break; default: qqbar_randtest(x, state, 2, 2 + n_randint(state, 80)); qqbar_get_quadratic(a, b, c, q, x, 0); break; } qqbar_set_fmpz(y, c); qqbar_sqrt(y, y); qqbar_mul_fmpz(y, y, b); qqbar_add_fmpz(y, y, a); qqbar_div_fmpz(y, y, q); if (!qqbar_equal(x, y)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n\n"); flint_abort(); } fmpz_gcd(d, a, b); fmpz_gcd(d, d, q); if (!fmpz_is_one(d) || fmpz_sgn(q) < 0 || (qqbar_degree(x) == 2 && (fmpz_is_square(c) || fmpz_val2(c) >= 2))) { flint_printf("FAIL (normalization)\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("a = "); fmpz_print(a); flint_printf("\n\n"); flint_printf("b = "); fmpz_print(b); flint_printf("\n\n"); flint_printf("c = "); fmpz_print(c); flint_printf("\n\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(q); fmpz_clear(d); fmpz_clear(n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-guess.c000066400000000000000000000030151461254215100172410ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_guess, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; acb_t z; slong prec, max_deg, max_bits; qqbar_init(x); qqbar_init(y); acb_init(z); if (n_randint(state, 2)) qqbar_randtest(x, state, 4, 100); else qqbar_randtest(x, state, 12, 10); max_deg = qqbar_degree(x) + n_randint(state, 2); max_bits = qqbar_height_bits(x) + n_randint(state, 100); for (prec = 64; ; prec *= 2) { qqbar_get_acb(z, x, prec); if (qqbar_guess(y, z, max_deg, max_bits, 0, prec) && qqbar_equal(x, y)) break; if (prec > 10000) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("prec = %wd\n\n", prec); flint_abort(); } } qqbar_clear(x); qqbar_clear(y); acb_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-inv.c000066400000000000000000000023711461254215100167130ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_inv, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; qqbar_init(x); qqbar_init(y); qqbar_init(z); do { qqbar_randtest(x, state, 8, 2 + n_randint(state, 100)); } while (qqbar_is_zero(x)); qqbar_inv(y, x); qqbar_inv(z, y); if (!qqbar_equal(x, z)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-log_pi_i.c000066400000000000000000000030061461254215100176740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_log_pi_i, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int res; qqbar_init(x); qqbar_init(y); q = 1 + n_randint(state, 30); p = n_randint(state, 1000); p -= 500; qqbar_exp_pi_i(x, p, q); res = qqbar_log_pi_i(&p2, &q2, x); if (res) qqbar_exp_pi_i(y, p2, q2); if (res == 0 || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || p2 > (slong) q2 || p2 <= -(slong) q2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("res = %d\n\n", res); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-mul.c000066400000000000000000000151121461254215100167110ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_mul, state) { slong iter; /* Check multiplication with degree-1 terms, large coefficients */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 20, 100); qqbar_randtest(y, state, 1, 100); qqbar_randtest(z, state, 1, 100); /* check (x * y) * z = x * (y * z) */ qqbar_mul(a, x, y); qqbar_mul(a, a, z); qqbar_mul(b, y, z); qqbar_mul(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check multiplication with degree-1 terms, small coefficients */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 30, 10); qqbar_randtest(y, state, 1, 10); qqbar_randtest(z, state, 1, 10); /* check (x * y) * z = x * (y * z) */ qqbar_mul(a, x, y); qqbar_mul(a, a, z); qqbar_mul(b, y, z); qqbar_mul(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check multiplication with higher-degree terms */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 6, 10); qqbar_randtest(y, state, 6, 10); qqbar_randtest(z, state, 2, 10); /* check (x * y) * z = x * (y * z) */ qqbar_mul(a, x, y); qqbar_mul(a, a, z); qqbar_mul(b, y, z); qqbar_mul(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* More iterations, low degree */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 4, 10); qqbar_randtest(y, state, 3, 10); qqbar_randtest(z, state, 2, 10); /* check (x * y) * z = x * (y * z) */ qqbar_mul(a, x, y); qqbar_mul(a, a, z); qqbar_mul(b, y, z); qqbar_mul(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check roots of rational numbers, which are special-cased. */ for (iter = 0; iter < 100; iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); do { qqbar_randtest(x, state, 1, 10); } while (qqbar_is_zero(x)); qqbar_pow_ui(x, x, 1 + n_randint(state, 3)); qqbar_abs(x, x); qqbar_root_ui(x, x, 1 + n_randint(state, 10)); do { qqbar_randtest(y, state, 1, 10); } while (qqbar_is_zero(y)); qqbar_pow_ui(y, y, 1 + n_randint(state, 3)); qqbar_abs(y, y); qqbar_root_ui(y, y, 1 + n_randint(state, 10)); qqbar_randtest(z, state, 2, 10); /* check (x * y) * z = x * (y * z) */ qqbar_mul(a, x, y); qqbar_mul(a, a, z); qqbar_mul(b, y, z); qqbar_mul(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-mul_2exp_si.c000066400000000000000000000027621461254215100203510ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_mul_2exp_si, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; slong e; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_randtest(x, state, 6, 10); e = n_randint(state, 100) - (slong) 50; if (n_randint(state, 2)) qqbar_mul_2exp_si(y, x, e); else { qqbar_set(y, x); qqbar_mul_2exp_si(y, y, e); } qqbar_one(z); qqbar_mul_2exp_si(z, z, e); qqbar_mul(z, z, x); if (!qqbar_equal(z, y)) { flint_printf("FAIL!\n"); flint_printf("%wd\n\n", e); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-pow.c000066400000000000000000000046221461254215100167250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_pow, state) { slong iter; /* Check x^m x^n = x^(m+n) */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, m, n, mn, xm, xn, xmxn, xmn; qqbar_init(x); qqbar_init(m); qqbar_init(n); qqbar_init(mn); qqbar_init(xm); qqbar_init(xn); qqbar_init(xmxn); qqbar_init(xmn); if (n_randint(state, 2)) { qqbar_root_of_unity(x, n_randint(state, 100), 1 + n_randint(state, 10)); qqbar_set_si(m, n_randtest(state)); qqbar_div_ui(m, m, 1 + n_randint(state, 5)); qqbar_set_si(n, n_randtest(state)); qqbar_div_ui(n, n, 1 + n_randint(state, 5)); } else { qqbar_randtest(x, state, 4, 10); qqbar_randtest(m, state, 4, 3); qqbar_randtest(n, state, 4, 3); } qqbar_add(mn, m, n); if (qqbar_pow(xm, x, m) && qqbar_pow(xn, x, n) && qqbar_pow(xmn, x, mn)) { qqbar_mul(xmxn, xm, xn); if (!qqbar_equal(xmxn, xmn)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("m = "); qqbar_print(m); flint_printf("\n\n"); flint_printf("n = "); qqbar_print(n); flint_printf("\n\n"); flint_printf("xm = "); qqbar_print(xm); flint_printf("\n\n"); flint_printf("xn = "); qqbar_print(xn); flint_printf("\n\n"); flint_printf("xmxn = "); qqbar_print(xmxn); flint_printf("\n\n"); flint_printf("xmn = "); qqbar_print(xmn); flint_printf("\n\n"); flint_abort(); } } qqbar_clear(x); qqbar_clear(m); qqbar_clear(n); qqbar_clear(mn); qqbar_clear(xm); qqbar_clear(xn); qqbar_clear(xmxn); qqbar_clear(xmn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-pow_fmpq.c000066400000000000000000000046431461254215100177530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_pow_fmpq, state) { slong iter; /* Check x^m x^n = x^(m+n) */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, xm, xn, xmxn, xmn; fmpq_t m, n, mn; qqbar_init(x); qqbar_init(xm); qqbar_init(xn); qqbar_init(xmxn); qqbar_init(xmn); fmpq_init(m); fmpq_init(n); fmpq_init(mn); if (n_randint(state, 2)) { qqbar_root_of_unity(x, n_randint(state, 100), 1 + n_randint(state, 10)); fmpq_set_si(m, n_randtest(state), 1 + n_randint(state, 5)); fmpq_set_si(n, n_randtest(state), 1 + n_randint(state, 5)); } else { do { qqbar_randtest(x, state, 4, 10); fmpq_randtest(m, state, 3); fmpq_randtest(n, state, 3); } while (qqbar_is_zero(x) && (fmpq_sgn(m) < 0 || fmpq_sgn(n) < 0)); } fmpq_add(mn, m, n); qqbar_pow_fmpq(xm, x, m); qqbar_pow_fmpq(xn, x, n); qqbar_pow_fmpq(xmn, x, mn); qqbar_mul(xmxn, xm, xn); if (!qqbar_equal(xmxn, xmn)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("m = "); fmpq_print(m); flint_printf("\n\n"); flint_printf("n = "); fmpq_print(n); flint_printf("\n\n"); flint_printf("xm = "); qqbar_print(xm); flint_printf("\n\n"); flint_printf("xn = "); qqbar_print(xn); flint_printf("\n\n"); flint_printf("xmxn = "); qqbar_print(xmxn); flint_printf("\n\n"); flint_printf("xmn = "); qqbar_print(xmn); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(xm); qqbar_clear(xn); qqbar_clear(xmxn); qqbar_clear(xmn); fmpq_clear(m); fmpq_clear(n); fmpq_clear(mn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-pow_fmpz.c000066400000000000000000000045371461254215100177660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_pow_fmpz, state) { slong iter; /* Check x^m x^n = x^(m+n) */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, xm, xn, xmxn, xmn; fmpz_t m, n, mn; qqbar_init(x); qqbar_init(xm); qqbar_init(xn); qqbar_init(xmxn); qqbar_init(xmn); fmpz_init(m); fmpz_init(n); fmpz_init(mn); if (n_randint(state, 2)) { qqbar_root_of_unity(x, n_randint(state, 100), 1 + n_randint(state, 10)); fmpz_set_si(m, n_randtest(state)); fmpz_set_si(n, n_randtest(state)); } else { do { qqbar_randtest(x, state, 4, 10); fmpz_randtest(m, state, 5); fmpz_randtest(n, state, 5); } while (qqbar_is_zero(x) && (fmpz_sgn(m) < 0 || fmpz_sgn(n) < 0)); } fmpz_add(mn, m, n); qqbar_pow_fmpz(xm, x, m); qqbar_pow_fmpz(xn, x, n); qqbar_pow_fmpz(xmn, x, mn); qqbar_mul(xmxn, xm, xn); if (!qqbar_equal(xmxn, xmn)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("m = "); fmpz_print(m); flint_printf("\n\n"); flint_printf("n = "); fmpz_print(n); flint_printf("\n\n"); flint_printf("xm = "); qqbar_print(xm); flint_printf("\n\n"); flint_printf("xn = "); qqbar_print(xn); flint_printf("\n\n"); flint_printf("xmxn = "); qqbar_print(xmxn); flint_printf("\n\n"); flint_printf("xmn = "); qqbar_print(xmn); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(xm); qqbar_clear(xn); qqbar_clear(xmxn); qqbar_clear(xmn); fmpz_clear(m); fmpz_clear(n); fmpz_clear(mn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-pow_si.c000066400000000000000000000100361461254215100174140ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_pow_si, state) { slong iter; /* Check x^m x^n = x^(m+n) */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, xm, xn, xmxn, xmn; slong m, n; qqbar_init(x); qqbar_init(xm); qqbar_init(xn); qqbar_init(xmxn); qqbar_init(xmn); if (n_randint(state, 2)) { qqbar_randtest(x, state, 4, 10); } else { /* check powers of rationals which are special-cased */ qqbar_randtest(x, state, 1, 10); qqbar_pow_ui(x, x, 1 + n_randint(state, 3)); qqbar_abs(x, x); qqbar_root_ui(x, x, 1 + n_randint(state, 10)); } m = n_randint(state, 7) - 4; n = n_randint(state, 7) - 4; while ((m < 0 || n < 0) && qqbar_is_zero(x)) qqbar_randtest(x, state, 2, 10); qqbar_pow_si(xm, x, m); qqbar_pow_si(xn, x, n); qqbar_mul(xmxn, xm, xn); qqbar_pow_si(xmn, x, m + n); if (!qqbar_equal(xmxn, xmn)) { flint_printf("FAIL!\n"); flint_printf("m = %wd\n\n", m); flint_printf("n = %wd\n\n", n); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("xm = "); qqbar_print(xm); flint_printf("\n\n"); flint_printf("xn = "); qqbar_print(xn); flint_printf("\n\n"); flint_printf("xmxn = "); qqbar_print(xmxn); flint_printf("\n\n"); flint_printf("xmn = "); qqbar_print(xmn); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(xm); qqbar_clear(xn); qqbar_clear(xmxn); qqbar_clear(xmn); } /* Check (xy)^n = x^n y^n */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, xyn, xn, yn, xnyn; slong n; qqbar_init(x); qqbar_init(y); qqbar_init(xyn); qqbar_init(xn); qqbar_init(yn); qqbar_init(xnyn); if (n_randint(state, 2)) { qqbar_randtest(x, state, 4, 10); } else { /* check powers of rationals which are special-cased */ qqbar_randtest(x, state, 1, 10); qqbar_pow_ui(x, x, 1 + n_randint(state, 3)); qqbar_abs(x, x); qqbar_root_ui(x, x, 1 + n_randint(state, 10)); } qqbar_randtest(y, state, 4, 10); n = n_randint(state, 7) - 4; while (n < 0 && qqbar_is_zero(x)) qqbar_randtest(x, state, 2, 10); while (n < 0 && qqbar_is_zero(y)) qqbar_randtest(y, state, 2, 10); qqbar_mul(xyn, x, y); qqbar_pow_si(xyn, xyn, n); qqbar_pow_si(xn, x, n); qqbar_pow_si(yn, y, n); qqbar_mul(xnyn, xn, yn); if (!qqbar_equal(xyn, xnyn)) { flint_printf("FAIL!\n"); flint_printf("n = %wd\n\n", n); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("xyn = "); qqbar_print(xyn); flint_printf("\n\n"); flint_printf("xn = "); qqbar_print(xn); flint_printf("\n\n"); flint_printf("yn = "); qqbar_print(yn); flint_printf("\n\n"); flint_printf("xnyn = "); qqbar_print(xnyn); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(xyn); qqbar_clear(xn); qqbar_clear(yn); qqbar_clear(xnyn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-pow_ui.c000066400000000000000000000073771461254215100174340ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_pow_ui, state) { slong iter; /* Check x^m x^n = x^(m+n) */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, xm, xn, xmxn, xmn; ulong m, n; qqbar_init(x); qqbar_init(xm); qqbar_init(xn); qqbar_init(xmxn); qqbar_init(xmn); if (n_randint(state, 2)) { qqbar_randtest(x, state, 4, 10); } else { /* check powers of rationals which are special-cased */ qqbar_randtest(x, state, 1, 10); qqbar_pow_ui(x, x, 1 + n_randint(state, 3)); qqbar_abs(x, x); qqbar_root_ui(x, x, 1 + n_randint(state, 10)); } m = n_randint(state, 7); n = n_randint(state, 7); qqbar_pow_ui(xm, x, m); qqbar_pow_ui(xn, x, n); qqbar_mul(xmxn, xm, xn); qqbar_pow_ui(xmn, x, m + n); if (!qqbar_equal(xmxn, xmn)) { flint_printf("FAIL!\n"); flint_printf("m = %wu\n\n", m); flint_printf("n = %wu\n\n", n); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("xm = "); qqbar_print(xm); flint_printf("\n\n"); flint_printf("xn = "); qqbar_print(xn); flint_printf("\n\n"); flint_printf("xmxn = "); qqbar_print(xmxn); flint_printf("\n\n"); flint_printf("xmn = "); qqbar_print(xmn); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(xm); qqbar_clear(xn); qqbar_clear(xmxn); qqbar_clear(xmn); } /* Check (xy)^n = x^n y^n */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, xyn, xn, yn, xnyn; ulong n; qqbar_init(x); qqbar_init(y); qqbar_init(xyn); qqbar_init(xn); qqbar_init(yn); qqbar_init(xnyn); if (n_randint(state, 2)) { qqbar_randtest(x, state, 4, 10); } else { /* check powers of rationals which are special-cased */ qqbar_randtest(x, state, 1, 10); qqbar_pow_ui(x, x, 1 + n_randint(state, 3)); qqbar_abs(x, x); qqbar_root_ui(x, x, 1 + n_randint(state, 10)); } qqbar_randtest(y, state, 4, 10); n = n_randint(state, 7); qqbar_mul(xyn, x, y); qqbar_pow_ui(xyn, xyn, n); qqbar_pow_ui(xn, x, n); qqbar_pow_ui(yn, y, n); qqbar_mul(xnyn, xn, yn); if (!qqbar_equal(xyn, xnyn)) { flint_printf("FAIL!\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("xyn = "); qqbar_print(xyn); flint_printf("\n\n"); flint_printf("xn = "); qqbar_print(xn); flint_printf("\n\n"); flint_printf("yn = "); qqbar_print(yn); flint_printf("\n\n"); flint_printf("xnyn = "); qqbar_print(xnyn); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(xyn); qqbar_clear(xn); qqbar_clear(yn); qqbar_clear(xnyn); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-randtest.c000066400000000000000000000026671461254215100177530ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_randtest, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; slong deg, bits; int real; qqbar_init(x); real = n_randint(state, 3); deg = 1 + n_randint(state, 4) + (real == 2); bits = 1 + n_randint(state, 4); if (real == 0) qqbar_randtest(x, state, deg, bits); else if (real == 1) qqbar_randtest_real(x, state, deg, bits); else if (real == 2) qqbar_randtest_nonreal(x, state, deg, bits); if (qqbar_degree(x) > deg || qqbar_height_bits(x) > bits || (real == 1 && !qqbar_is_real(x)) || (real == 2 && qqbar_is_real(x))) { flint_printf("FAIL\n"); flint_printf("deg = %wd, bits = %wd, real = %d\n", deg, bits, real); qqbar_print(x); flint_printf("\n"); flint_abort(); } qqbar_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-re_im.c000066400000000000000000000030461461254215100172120ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_re_im, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, t; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(t); qqbar_randtest(x, state, 4, 10); qqbar_re(y, x); qqbar_im(z, x); if (n_randint(state, 2)) { qqbar_set_re_im(t, y, z); } else { qqbar_i(t); qqbar_mul(t, t, z); qqbar_add(t, t, y); } if (!qqbar_equal(t, x) || !qqbar_is_real(y) || !qqbar_is_real(z)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("t = "); qqbar_print(t); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-root_of_unity.c000066400000000000000000000036631461254215100210230ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_root_of_unity, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y; slong p, p2; ulong q, q2; int ok; qqbar_init(x); qqbar_init(y); q = 1 + n_randint(state, 30); p = n_randint(state, 1000); p -= 500; qqbar_root_of_unity(x, p, q); ok = qqbar_is_root_of_unity(&p2, &q2, x); qqbar_root_of_unity(y, p2, q2); if (!ok || !qqbar_equal(x, y) || n_gcd(FLINT_ABS(p2), q2) != 1 || !(0 <= p2 && p2 < (slong) 2 * q2)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } if (q <= 10) { qqbar_pow_ui(y, x, q); if (!qqbar_is_one(y)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("p, p2 = %wd %wd\n\n", p, p2); flint_printf("q, q2 = %wu %wu\n\n", q, q2); flint_abort(); } } qqbar_clear(x); qqbar_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-root_ui.c000066400000000000000000000037621461254215100176040ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_root_ui, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; ulong n; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_randtest(x, state, 4, 10); /* generate noise */ qqbar_randtest(y, state, 2, 10); qqbar_add(x, x, y); qqbar_sub(x, x, y); n = 1 + n_randint(state, 4); qqbar_root_ui(y, x, n); if (n_randint(state, 2)) { qqbar_pow_ui(z, y, n); } else { if (n == 1) { qqbar_set(z, y); } else if (n == 2) { qqbar_binary_op(z, y, y, 2); } else if (n == 3) { qqbar_binary_op(z, y, y, 2); qqbar_binary_op(z, z, y, 2); } else { qqbar_binary_op(z, y, y, 2); qqbar_binary_op(z, z, z, 2); } } if (!qqbar_equal(x, z) || (n > 1 && qqbar_csgn(y) == -1)) { flint_printf("FAIL!\n"); flint_printf("n = %wu\n\n", n); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-roots_fmpz_poly.c000066400000000000000000000040611461254215100213620ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "arb_fmpz_poly.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_roots_fmpz_poly, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { fmpz_poly_t poly, f; qqbar_ptr r; acb_t x, y; slong i, d, prec; fmpz_poly_init(poly); fmpz_poly_init(f); fmpz_poly_randtest(poly, state, 10, 100); if (n_randint(state, 2)) { fmpz_poly_randtest_not_zero(f, state, 5, 10); fmpz_poly_pow(f, f, 1 + n_randint(state, 3)); fmpz_poly_mul(poly, poly, f); } d = fmpz_poly_degree(poly); d = FLINT_MAX(d, 0); acb_init(x); acb_init(y); r = _qqbar_vec_init(d); qqbar_roots_fmpz_poly(r, poly, 0); for (i = 0; i < d; i++) { prec = 2 * QQBAR_DEFAULT_PREC; qqbar_get_acb(x, r + i, prec); arb_fmpz_poly_evaluate_acb(y, poly, x, prec); if (!acb_contains_zero(y)) { flint_printf("FAIL!\n"); flint_printf("i = %wd\n\n", i); flint_printf("poly = "); fmpz_poly_print(poly); flint_printf("\n\n"); flint_printf("r = "); qqbar_print(r + i); flint_printf("\n\n"); flint_printf("x = "); acb_printn(x, 100, 0); flint_printf("\n\n"); flint_printf("y = "); acb_printn(y, 100, 0); flint_printf("\n\n"); flint_abort(); } } fmpz_poly_clear(poly); fmpz_poly_clear(f); _qqbar_vec_clear(r, d); acb_clear(x); acb_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-sec_pi.c000066400000000000000000000032561461254215100173640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_sec_pi, state) { slong iter; for (iter = 0; iter < 200 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; arb_t z, w; fmpq_t t; slong p; ulong q; slong prec; qqbar_init(x); arb_init(z); arb_init(w); fmpq_init(t); q = 1 + n_randint(state, 20); p = n_randint(state, 1000); p -= 500; prec = 2 + n_randint(state, 1000); fmpq_set_si(t, p, q); arb_cos_pi_fmpq(w, t, prec); arb_inv(w, w, prec); if (arb_is_finite(w)) { qqbar_sec_pi(x, p, q); qqbar_get_arb(z, x, prec); if (!arb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 200, 0); flint_printf("\n\n"); flint_printf("w = "); arb_printn(w, 200, 0); flint_printf("\n\n"); flint_printf("p, q = %wd %wu\n\n", p, q); flint_abort(); } } qqbar_clear(x); arb_clear(z); arb_clear(w); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-set_d.c000066400000000000000000000033561461254215100172210ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "double_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_set_d, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { double x; qqbar_t z; arb_t a, b; int ok; qqbar_init(z); arb_init(a); arb_init(b); x = d_randtest_special(state, -1100, 1100); ok = qqbar_set_d(z, x); qqbar_get_arb(a, z, 53); arb_set_d(b, x); if (ok) { if (!arb_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } } else { if (arb_is_finite(b)) { flint_printf("FAIL!\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_abort(); } } arb_clear(a); arb_clear(b); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-set_re_im_d.c000066400000000000000000000034711461254215100203720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "double_extras.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_set_re_im_d, state) { slong iter; for (iter = 0; iter < 10000 * 0.1 * flint_test_multiplier(); iter++) { double x, y; qqbar_t z; acb_t a, b; int ok; qqbar_init(z); acb_init(a); acb_init(b); x = d_randtest_special(state, -1100, 1100); y = d_randtest_special(state, -1100, 1100); ok = qqbar_set_re_im_d(z, x, y); qqbar_get_acb(a, z, 53); acb_set_d_d(b, x, y); if (ok) { if (!acb_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } } else { if (acb_is_finite(b)) { flint_printf("FAIL!\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); flint_abort(); } } acb_clear(a); acb_clear(b); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-sgn.c000066400000000000000000000023071461254215100167050ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_sgn, state) { slong iter; for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_randtest(x, state, 4, 8); qqbar_sgn(y, x); qqbar_abs(z, x); qqbar_mul(z, z, y); if (!qqbar_equal(x, z)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-sgn_re.c000066400000000000000000000054031461254215100173730ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_sgn_re, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z; int s1, s2, s3, s4; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_randtest(x, state, 4, 10); qqbar_i(y); qqbar_mul(y, y, x); s1 = qqbar_sgn_re(x); s2 = qqbar_sgn_im(y); if (s1 != s2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("s1 = %d", s1); flint_printf("\n\n"); flint_printf("s2 = %d", s2); flint_printf("\n\n"); flint_abort(); } qqbar_randtest(x, state, 4, 10); qqbar_randtest(y, state, 4, 10); if (n_randint(state, 2)) qqbar_add(x, x, y); else qqbar_mul(x, x, y); qqbar_i(y); qqbar_mul(y, y, x); s1 = qqbar_sgn_re(x); s2 = qqbar_sgn_im(y); if (s1 != s2) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("s1 = %d", s1); flint_printf("\n\n"); flint_printf("s2 = %d", s2); flint_printf("\n\n"); flint_abort(); } qqbar_randtest_real(x, state, 2, 100); qqbar_randtest_real(y, state, 2, 100); s1 = qqbar_sgn_re(x); s2 = qqbar_sgn_re(y); qqbar_i(z); qqbar_mul(y, y, z); qqbar_add(x, x, y); s3 = qqbar_sgn_re(x); s4 = qqbar_sgn_im(x); if (s1 != s3 || s2 != s4) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("s1 = %d", s1); flint_printf("\n\n"); flint_printf("s2 = %d", s2); flint_printf("\n\n"); flint_printf("s3 = %d", s3); flint_printf("\n\n"); flint_printf("s4 = %d", s4); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-sin_pi.c000066400000000000000000000030641461254215100174000ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_sin_pi, state) { slong iter; for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; arb_t z, w; fmpq_t t; slong p; ulong q; slong prec; qqbar_init(x); arb_init(z); arb_init(w); fmpq_init(t); q = 1 + n_randint(state, 30); p = n_randint(state, 1000); p -= 500; prec = 2 + n_randint(state, 1000); qqbar_sin_pi(x, p, q); qqbar_get_arb(z, x, prec); fmpq_set_si(t, p, q); arb_sin_pi_fmpq(w, t, prec); if (!arb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 200, 0); flint_printf("\n\n"); flint_printf("w = "); arb_printn(w, 200, 0); flint_printf("\n\n"); flint_printf("p, q = %wd %wu\n\n", p, q); flint_abort(); } qqbar_clear(x); arb_clear(z); arb_clear(w); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-sub.c000066400000000000000000000121171461254215100167070ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_sub, state) { slong iter; /* Check subtraction with degree-1 terms, large coefficients */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 20, 100); qqbar_randtest(y, state, 1, 100); qqbar_randtest(z, state, 1, 100); /* check (x - y) - z = x - (z + y) */ qqbar_sub(a, x, y); qqbar_sub(a, a, z); qqbar_add(b, z, y); qqbar_sub(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check subtraction with degree-1 terms, small coefficients */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 30, 10); qqbar_randtest(y, state, 1, 10); qqbar_randtest(z, state, 1, 10); /* check (x - y) - z = x - (z + y) */ qqbar_sub(a, x, y); qqbar_sub(a, a, z); qqbar_add(b, z, y); qqbar_sub(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* Check subtraction with higher-degree terms */ for (iter = 0; iter < 100 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 6, 10); qqbar_randtest(y, state, 6, 10); qqbar_randtest(z, state, 2, 10); /* check (x - y) - z = x - (z + y) */ qqbar_sub(a, x, y); qqbar_sub(a, a, z); qqbar_add(b, z, y); qqbar_sub(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } /* More iterations, low degree */ for (iter = 0; iter < 1000 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x, y, z, a, b; qqbar_init(x); qqbar_init(y); qqbar_init(z); qqbar_init(a); qqbar_init(b); qqbar_randtest(x, state, 4, 10); qqbar_randtest(y, state, 3, 10); qqbar_randtest(z, state, 2, 10); /* check (x - y) - z = x - (z + y) */ qqbar_sub(a, x, y); qqbar_sub(a, a, z); qqbar_add(b, z, y); qqbar_sub(b, x, b); if (!qqbar_equal(a, b)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("y = "); qqbar_print(y); flint_printf("\n\n"); flint_printf("z = "); qqbar_print(z); flint_printf("\n\n"); flint_printf("a = "); qqbar_print(a); flint_printf("\n\n"); flint_printf("b = "); qqbar_print(b); flint_printf("\n\n"); flint_abort(); } qqbar_clear(x); qqbar_clear(y); qqbar_clear(z); qqbar_clear(a); qqbar_clear(b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/test/t-tan_pi.c000066400000000000000000000033261461254215100173720ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpq.h" #include "qqbar.h" TEST_FUNCTION_START(qqbar_tan_pi, state) { slong iter; for (iter = 0; iter < 500 * 0.1 * flint_test_multiplier(); iter++) { qqbar_t x; arb_t z, w; fmpq_t t; slong p; ulong q; slong prec; qqbar_init(x); arb_init(z); arb_init(w); fmpq_init(t); q = 1 + n_randint(state, 30); p = n_randint(state, 1000); p -= 500; prec = 2 + n_randint(state, 1000); fmpq_set_si(t, p, q); arb_sin_pi_fmpq(w, t, prec); arb_cos_pi_fmpq(z, t, prec); arb_div(w, w, z, prec); if (arb_is_finite(w)) { qqbar_tan_pi(x, p, q); qqbar_get_arb(z, x, prec); if (!arb_overlaps(z, w)) { flint_printf("FAIL!\n"); flint_printf("x = "); qqbar_print(x); flint_printf("\n\n"); flint_printf("z = "); arb_printn(z, 200, 0); flint_printf("\n\n"); flint_printf("w = "); arb_printn(w, 200, 0); flint_printf("\n\n"); flint_printf("p, q = %wd %wu\n\n", p, q); flint_abort(); } } qqbar_clear(x); arb_clear(z); arb_clear(w); fmpq_clear(t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/qqbar/validate_enclosure.c000066400000000000000000000124771461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "arb_fmpz_poly.h" #include "qqbar.h" int _qqbar_validate_uniqueness(acb_t res, const fmpz_poly_t poly, const acb_t z, slong prec) { if (!acb_is_finite(z) || fmpz_poly_degree(poly) < 1) { if (res != NULL) acb_set(res, z); return 0; } else if (acb_is_exact(z) || fmpz_poly_degree(poly) == 1) { if (res != NULL) acb_set(res, z); return 1; } else { slong acc; acb_t z2, zmid, t, u; fmpz_poly_t deriv; mag_t zmag, eps; int pure_real, pure_imag, ans; /* int attempt; */ pure_real = acb_is_real(z); pure_imag = arb_is_zero(acb_realref(z)); if (prec == 0) { acc = acb_rel_accuracy_bits(z); /* todo: maybe use the bits * degree of poly instead as bound */ acc = FLINT_MIN(acc, ARF_PREC_EXACT / 4); prec = FLINT_MAX(acc, 32) * 2 + 10; } acb_init(z2); acb_init(zmid); acb_init(t); acb_init(u); mag_init(eps); mag_init(zmag); fmpz_poly_init(deriv); ans = 0; /* for (attempt = 0; attempt < 2 && ans == 0; attempt++) */ { acb_get_mag(zmag, z); /* Slightly inflate enclosure -- needed e.g. in case of complex interval with one very narrow real/imaginary part */ if (1) { mag_mul_2exp_si(zmag, zmag, -3 * prec / 4); mag_hypot(eps, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul_2exp_si(eps, eps, -4); mag_max(eps, eps, zmag); } acb_set(z2, z); if (pure_real) arb_add_error_mag(acb_realref(z2), eps); else if (pure_imag) arb_add_error_mag(acb_imagref(z2), eps); else acb_add_error_mag(z2, eps); acb_get_mid(zmid, z2); fmpz_poly_derivative(deriv, poly); /* Do one interval Newton step, t = zmid - poly(zmid) / poly'(z2) */ arb_fmpz_poly_evaluate_acb(t, poly, zmid, prec); arb_fmpz_poly_evaluate_acb(u, deriv, z2, prec); acb_div(t, t, u, prec); acb_sub(t, zmid, t, prec); if (pure_real) { ans = arb_contains_interior(acb_realref(z2), acb_realref(t)); arb_zero(acb_imagref(t)); } else if (pure_imag) { ans = arb_contains_interior(acb_imagref(z2), acb_imagref(t)); arb_zero(acb_realref(t)); } else { ans = acb_contains_interior(z2, t); } } if (res != NULL) { if (ans) acb_set(res, t); else acb_set(res, z); } acb_clear(z2); acb_clear(zmid); acb_clear(t); acb_clear(u); mag_clear(eps); mag_clear(zmag); fmpz_poly_clear(deriv); return ans; } } int _qqbar_validate_existence_uniqueness(acb_t res, const fmpz_poly_t poly, const acb_t z, slong prec) { if (!acb_is_finite(z) || fmpz_poly_degree(poly) < 1) { if (res != NULL) acb_set(res, z); return 0; } else { slong acc; acb_t zmid, t, u; fmpz_poly_t deriv; int pure_real, pure_imag, ans, attempt; pure_real = acb_is_real(z); pure_imag = arb_is_zero(acb_realref(z)); if (prec == 0) { acc = acb_rel_accuracy_bits(z); /* todo: maybe use the bits * degree of poly instead as bound */ acc = FLINT_MIN(acc, ARF_PREC_EXACT / 4); prec = FLINT_MAX(acc, 32) * 2 + 10; } acb_init(zmid); acb_init(t); acb_init(u); fmpz_poly_init(deriv); ans = 0; for (attempt = 0; attempt < 2 && ans == 0; attempt++, prec *= 2) { acb_get_mid(zmid, z); fmpz_poly_derivative(deriv, poly); /* Do one interval Newton step, t = zmid - poly(zmid) / poly'(z) */ arb_fmpz_poly_evaluate_acb(t, poly, zmid, prec); arb_fmpz_poly_evaluate_acb(u, deriv, z, prec); acb_div(t, t, u, prec); acb_sub(t, zmid, t, prec); if (pure_real) ans = arb_contains_interior(acb_realref(z), acb_realref(t)) && arb_is_zero(acb_imagref(t)); else if (pure_imag) ans = arb_contains_interior(acb_imagref(z), acb_imagref(t)) && arb_is_zero(acb_realref(t)); else ans = acb_contains_interior(z, t); } if (res != NULL) { if (ans) acb_set(res, t); else acb_set(res, z); } acb_clear(zmid); acb_clear(t); acb_clear(u); fmpz_poly_clear(deriv); return ans; } } flint-3.1.3/src/qqbar/write.c000066400000000000000000000023131461254215100160250ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "calcium.h" #include "qqbar.h" /* Todo: document, unify and generalize. This is currently only used for the Python interface, but other wrappers will want good printing code too. */ void qqbar_writen(calcium_stream_t out, const qqbar_t x, slong n) { acb_t t; slong prec; n = FLINT_MAX(1, n); prec = n * 3.333 + 10; acb_init(t); qqbar_get_acb(t, x, prec); calcium_write_acb(out, t, n, ARB_STR_NO_RADIUS); acb_clear(t); } void qqbar_writend(calcium_stream_t out, const qqbar_t x, slong n) { qqbar_writen(out, x, n); calcium_write(out, " (deg "); calcium_write_si(out, qqbar_degree(x)); calcium_write(out, ")"); } char * qqbar_get_str_nd(const qqbar_t x, slong n) { calcium_stream_t out; calcium_stream_init_str(out); qqbar_writend(out, x, n); return out->s; } flint-3.1.3/src/qsieve.h000066400000000000000000000365311461254215100150770ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef QSIEVE_H #define QSIEVE_H #include #include "fmpz_types.h" #if FLINT_USES_PTHREAD # include #endif #ifdef __cplusplus extern "C" { #endif #define QS_DEBUG 0 /* level of debug information printed, 0 = none */ #define BITS_ADJUST 25 /* add to sieve entries to compensate approximations */ #define BLOCK_SIZE (4*65536) /* size of sieving cache block */ typedef struct { mp_limb_t pinv; /* precomputed inverse */ int p; /* prime */ char size; } prime_t; typedef struct /* struct for factors of relations */ { slong ind; slong exp; } fac_t; typedef struct /* matrix column */ { slong * data; /* The list of occupied rows in this column */ slong weight; /* Number of nonzero entries in this column */ slong orig; /* Original relation number */ } la_col_t; typedef struct /* entry in hash table */ { mp_limb_t prime; /* value of prime */ mp_limb_t next; /* next prime which have same hash value as 'prime' */ mp_limb_t count; /* number of occurrence of 'prime' */ } hash_t; typedef struct /* format for relation */ { mp_limb_t lp; /* large prime, is 1, if relation is full */ slong num_factors; /* number of factors, excluding small factor */ slong small_primes; /* number of small factors */ slong * small; /* exponent of small factors */ fac_t * factor; /* factor of relation */ fmpz_t Y; /* square root of sieve value for relation */ } relation_t; typedef struct { fmpz_t B; /* current B coeff of poly */ int * soln1; /* first start position in sieve per prime */ int * soln2; /* second start position in sieve per prime */ int * posn1; /* temp space for sieving */ int * posn2; /* temp space for sieving */ slong * small; /* exponents of small prime factors in relations */ fac_t * factor; /* factors for a relation */ slong num_factors; /* number of factors found in a relation */ } qs_poly_s; typedef qs_poly_s qs_poly_t[1]; typedef struct { volatile slong index_j; #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif thread_pool_handle * handles; slong num_handles; fmpz_t n; /* Number to factor */ flint_bitcnt_t bits; /* Number of bits of n */ ulong ks_primes; /* number of Knuth-Schroeppel primes */ mp_limb_t k; /* Multiplier */ fmpz_t kn; /* kn as a multiprecision integer */ slong num_primes; /* number of factor base primes including k and 2 */ prime_t * factor_base; /* data about factor base primes */ int * sqrts; /* square roots of kn mod factor base primes */ slong small_primes; /* number of primes to not sieve with */ slong second_prime; /* index of first prime bigger than block size */ slong sieve_size; /* size of sieve to use */ unsigned char sieve_bits; /* sieve threshold */ unsigned char sieve_fill; /* for biasing sieve values */ /*************************************************************************** POLYNOMIAL DATA **************************************************************************/ fmpz_t A; /* current value of coeff A of poly Ax^2 + Bx + C */ fmpz_t B; /* B value of poly */ mp_limb_t * A_ind; /* indices of factor base primes dividing A */ fmpz_t * A_divp; /* A_divp[i] = (A/p_i), where the p_i are the prime factors of A */ mp_limb_t * B0_terms; /* B0_terms[i] = min(gamma_i, p - gamma_i) where gamma_i = (sqrt(kn)*(A_divp[i])^(-1)) mod p_i, where the p_i are the prime factors of A */ fmpz_t * B_terms; /* B_terms[i] = A_divp[i]*B0_terms[i] (multprec) */ mp_limb_t * A_inv; /* A_inv[k] = A^(-1) mod p_k, for FB prime p_k */ mp_limb_t ** A_inv2B; /* A_inv2B[i][k] = 2 * B_terms[i] * A^(-1) mod p_k for FB prime p_k */ int * soln1; /* soln1[k] = first poly root mod FB prime p_k */ int * soln2; /* soln2[k] = second poly root mod FB prime p_k */ fmpz_t target_A; /* approximate target value for A coeff of poly */ fmpz_t upp_bound; /* upper bound on desired A = 2*target_A */ fmpz_t low_bound; /* lower bound on desired A = target_A/2 */ slong s; /* number of prime factors of A */ slong low; /* minimum offset in factor base, for possible factors of A */ slong high; /* maximum offset in factor base, for possible factors of A */ slong span; /* total number of possible factors for A */ /* parameters for calculating next subset of possible factors of A, giving a lexicographic ordering of all such tuples */ slong h; /* tuple entry we just set, numbered from 1 at end of tuple */ slong m; /* last value we just set a tuple entry to */ slong A_ind_diff; /* diff. between indices of (s-1) and (s-2)-th A-factor */ mp_limb_t * curr_subset; /* current tuple */ mp_limb_t * first_subset; /* first tuple, in case of restart */ mp_limb_t j; /* index of s-th factor of first A, if s > 3 */ #if QS_DEBUG slong poly_count; /* keep track of the number of polynomials used */ #endif qs_poly_s * poly; /* poly data per thread */ /*************************************************************************** RELATION DATA ***************************************************************************/ FLINT_FILE * siqs; /* pointer to file for storing relations */ char * fname; /* name of file used for relations */ slong full_relation; /* number of full relations */ slong num_cycles; /* number of possible full relations from partials */ slong vertices; /* number of different primes in partials */ slong components; /* equal to 1 */ slong edges; /* total number of partials */ slong table_size; /* size of table */ hash_t * table; /* store 'prime' occurring in partial */ mp_limb_t * hash_table; /* to keep track of location of primes in 'table' */ slong extra_rels; /* number of extra relations beyond num_primes */ slong max_factors; /* maximum number of factors a relation can have */ fmpz * Y_arr; /* array of Y's corresponding to relations */ slong * curr_rel; /* current relation in array of relations */ slong * relation; /* relation array */ slong buffer_size; /* size of buffer of relations */ slong num_relations; /* number of relations so far */ ulong small_factor; /* small factor found when merging relations */ /*************************************************************************** LINEAR ALGEBRA DATA ***************************************************************************/ la_col_t * matrix; /* the main matrix over GF(2) in sparse format */ la_col_t ** qsort_arr; /* array of columns ready to be sorted */ slong columns; /* number of columns in matrix so far */ /*************************************************************************** SQUARE ROOT DATA ***************************************************************************/ slong * prime_count; /* counts of the exponents of primes appearing in the square */ } qs_s; typedef qs_s qs_t[1]; /* Tuning parameters { bits, ks_primes, fb_primes, small_primes, sieve_size} for qsieve_factor_threaded where: * bits is the number of bits of n * ks_primes is the max number of primes to try in Knuth-Schroeppel function * fb_primes is the number of factor base primes to use (including k and 2) * small_primes is the number of small primes to not factor with (including k and 2) * sieve_size is the size of the sieve to use * sieve_bits - sieve_fill */ #if 0 /* TODO have the tuning values taken from here if multithreaded */ static const mp_limb_t qsieve_tune[][6] = { {10, 50, 100, 5, 2 * 2000, 30}, /* */ {20, 50, 120, 6, 2 * 2500, 30}, /* */ {30, 50, 150, 6, 2 * 2000, 31}, /* */ {40, 50, 150, 8, 2 * 3000, 32}, /* 12 digits */ {50, 50, 150, 8, 2 * 3000, 34}, /* 15 digits */ {60, 50, 150, 9, 2 * 3500, 36}, /* 18 digits */ {70, 100, 200, 9, 2 * 4000, 42}, /* 21 digits */ {80, 100, 200, 9, 2 * 6000, 44}, /* 24 digits */ {90, 100, 200, 9, 2 * 6000, 50}, /* */ {100, 100, 300, 9, 2 * 7000, 54}, /* */ {110, 100, 500, 9, 2 * 25000, 62}, /* 31 digits */ {120, 100, 800, 9, 2 * 30000, 64}, /* */ {130, 100, 1000, 9, 2 * 30000, 64}, /* 41 digits */ {140, 100, 1200, 9, 2 * 30000, 66}, /* */ {150, 100, 1500, 10, 2 * 32000, 68}, /* 45 digit */ {160, 150, 1800, 11, 2 * 32000, 70}, /* */ {170, 150, 2000, 12, 2 * 32000, 72}, /* 50 digits */ {180, 150, 2500, 12, 2 * 32000, 73}, /* */ {190, 150, 2800, 12, 2 * 32000, 76}, /* */ {200, 200, 4000, 12, 2 * 32000, 80}, /* 60 digits */ {210, 100, 3600, 12, 2 * 32000, 83}, /* */ {220, 300, 6000, 15, 2 * 65536, 87}, /* */ {230, 350, 8500, 17, 3 * 65536, 90}, /* 70 digits */ {240, 400, 10000, 19, 4 * 65536, 93}, /* */ {250, 500, 15000, 19, 4 * 65536, 97}, /* 75 digits */ {260, 600, 25000, 25, 4 * 65536, 100}, /* 80 digits */ {270, 800, 35000, 27, 5 * 65536, 104} /* */ }; #else /* currently tuned for four threads */ static const mp_limb_t qsieve_tune[][6] = { {10, 50, 90, 5, 2 * 1500, 18}, /* */ {20, 50, 90, 6, 2 * 1600, 18}, /* */ {30, 50, 100, 6, 2 * 1800, 19}, /* */ {40, 50, 100, 8, 2 * 2000, 20}, /* 13 digits */ {50, 50, 100, 8, 2 * 2500, 22}, /* 16 digits */ {60, 50, 100, 9, 2 * 3000, 24}, /* 19 digits */ {70, 100, 250, 9, 2 * 6000, 25}, /* 22 digits */ {80, 100, 250, 9, 2 * 8000, 26}, /* 25 digits */ {90, 100, 250, 9, 2 * 9000, 30}, /* 28 digits */ {100, 100, 250, 9, 2 * 10000, 34}, /* 31 digits */ {110, 100, 250, 9, 2 * 30000, 38}, /* 34 digits */ {120, 100, 700, 9, 2 * 40000, 49}, /* 37 digits */ {130, 100, 800, 9, 2 * 50000, 59}, /* 40 digits */ {140, 100, 1200, 9, 2 * 65536, 66}, /* 43 digits */ {150, 100, 1500, 10, 2 * 65536, 70}, /* 46 digit */ {160, 150, 2000, 11, 4 * 65536, 73}, /* 49 digit */ {170, 150, 2000, 12, 4 * 65536, 75}, /* 52 digits */ {180, 150, 3000, 12, 4 * 65536, 76}, /* 55 digits */ {190, 150, 3000, 13, 4 * 65536, 78}, /* 58 digit */ {200, 200, 4500, 14, 4 * 65536, 81}, /* 61 digits */ {210, 100, 8000, 14, 12 * 65536, 84}, /* 64 digits */ {220, 300, 10000, 15, 12 * 65536, 88}, /* 67 digits */ {230, 400, 20000, 17, 20 * 65536, 90}, /* 70 digits */ {240, 450, 20000, 19, 20 * 65536, 93}, /* 73 digis */ {250, 500, 22000, 22, 24 * 65536, 97}, /* 76 digits */ {260, 600, 25000, 25, 24 * 65536, 100}, /* 79 digits */ {270, 800, 35000, 27, 28 * 65536, 102}, /* 82 digits */ {280, 900, 40000, 29, 28 * 65536, 104}, /* 85 digits */ {290, 1000, 60000, 29, 32 * 65536, 106}, /* 88 digits */ {300, 1100, 140000, 30, 32 * 65536, 108} /* 91 digits */ }; #endif /* number of entries in the tuning table */ #define QS_TUNE_SIZE (sizeof(qsieve_tune)/(6*sizeof(mp_limb_t))) void qsieve_init(qs_t qs_inf, const fmpz_t n); mp_limb_t qsieve_knuth_schroeppel(qs_t qs_inf); void qsieve_clear(qs_t qs_inf); void qsieve_factor(fmpz_factor_t factors, const fmpz_t n); prime_t * compute_factor_base(mp_limb_t * small_factor, qs_t qs_inf, slong num_primes); mp_limb_t qsieve_primes_init(qs_t qs_inf); mp_limb_t qsieve_primes_increment(qs_t qs_inf, mp_limb_t delta); mp_limb_t qsieve_poly_init(qs_t qs_inf); int qsieve_init_A(qs_t qs_inf); void qsieve_reinit_A(qs_t qs_inf); int qsieve_next_A(qs_t qs_inf); void qsieve_init_poly_first(qs_t qs_inf); void qsieve_init_poly_next(qs_t qs_inf, slong i); void qsieve_compute_C(fmpz_t C, qs_t qs_inf, qs_poly_t poly); void qsieve_poly_copy(qs_poly_t poly, qs_t qs_inf); void qsieve_poly_clear(qs_t qs_inf); void qsieve_do_sieving(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly); void qsieve_do_sieving2(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly); slong qsieve_evaluate_candidate(qs_t qs_inf, ulong i, unsigned char * sieve, qs_poly_t poly); slong qsieve_evaluate_sieve(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly); slong qsieve_collect_relations(qs_t qs_inf, unsigned char * sieve); void qsieve_linalg_init(qs_t qs_inf); void qsieve_linalg_realloc(qs_t qs_inf); void qsieve_linalg_clear(qs_t qs_inf); int qsieve_relations_cmp(const void * a, const void * b); slong qsieve_merge_relations(qs_t qs_inf); void qsieve_write_to_file(qs_t qs_inf, mp_limb_t prime, const fmpz_t Y, const qs_poly_t poly); hash_t * qsieve_get_table_entry(qs_t qs_inf, mp_limb_t prime); void qsieve_add_to_hashtable(qs_t qs_inf, mp_limb_t prime); relation_t qsieve_parse_relation(qs_t qs_inf); relation_t qsieve_merge_relation(qs_t qs_inf, relation_t a, relation_t b); int qsieve_compare_relation(const void * a, const void * b); int qsieve_remove_duplicates(relation_t * rel_list, slong num_relations); void qsieve_insert_relation(qs_t qs_inf, relation_t * rel_list, slong num_relations); int qsieve_process_relation(qs_t qs_inf); static inline void insert_col_entry(la_col_t * col, slong entry) { if (((col->weight >> 4) << 4) == col->weight) /* need more space */ { if (col->weight != 0) col->data = (slong *) flint_realloc(col->data, (col->weight + 16)*sizeof(slong)); else col->data = (slong *) flint_malloc(16*sizeof(slong)); } col->data[col->weight] = entry; col->weight++; } static inline void swap_cols(la_col_t * col2, la_col_t * col1) { la_col_t temp; temp.weight = col1->weight; temp.data = col1->data; temp.orig = col1->orig; col1->weight = col2->weight; col1->data = col2->data; col1->orig = col2->orig; col2->weight = temp.weight; col2->data = temp.data; col2->orig = temp.orig; } static inline void clear_col(la_col_t * col) { col->weight = 0; } static inline void free_col(la_col_t * col) { if (col->weight) flint_free(col->data); } uint64_t get_null_entry(uint64_t * nullrows, slong i, slong l); void reduce_matrix(qs_t qs_inf, slong *nrows, slong *ncols, la_col_t *cols); uint64_t * block_lanczos(flint_rand_t state, slong nrows, slong dense_rows, slong ncols, la_col_t *B); void qsieve_square_root(fmpz_t X, fmpz_t Y, qs_t qs_inf, uint64_t * nullrows, slong ncols, slong l, fmpz_t N); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/qsieve/000077500000000000000000000000001461254215100147165ustar00rootroot00000000000000flint-3.1.3/src/qsieve/block_lanczos.c000066400000000000000000000600701461254215100177100ustar00rootroot00000000000000/* Copyright 2006 Jason Papadopoulos. Copyright 2006, 2011 William Hart. This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ /*------------------------------------------------------------------- Optionally, please be nice and tell me if you find this source to be useful. Again optionally, if you add to the functionality present here please consider making those additions public too, so that others may benefit from your work. --jasonp@boo.net 9/8/06 --------------------------------------------------------------------*/ #include "ulong_extras.h" #include "qsieve.h" #ifdef __GNUC__ # define memcpy __builtin_memcpy # define memset __builtin_memset #else # include #endif #define BIT(x) (((uint64_t)(1)) << (x)) static const uint64_t bitmask[64] = { BIT( 0), BIT( 1), BIT( 2), BIT( 3), BIT( 4), BIT( 5), BIT( 6), BIT( 7), BIT( 8), BIT( 9), BIT(10), BIT(11), BIT(12), BIT(13), BIT(14), BIT(15), BIT(16), BIT(17), BIT(18), BIT(19), BIT(20), BIT(21), BIT(22), BIT(23), BIT(24), BIT(25), BIT(26), BIT(27), BIT(28), BIT(29), BIT(30), BIT(31), BIT(32), BIT(33), BIT(34), BIT(35), BIT(36), BIT(37), BIT(38), BIT(39), BIT(40), BIT(41), BIT(42), BIT(43), BIT(44), BIT(45), BIT(46), BIT(47), BIT(48), BIT(49), BIT(50), BIT(51), BIT(52), BIT(53), BIT(54), BIT(55), BIT(56), BIT(57), BIT(58), BIT(59), BIT(60), BIT(61), BIT(62), BIT(63), }; /*--------------------------------------------------------------------*/ uint64_t get_null_entry(uint64_t * nullrows, slong i, slong l) { /* Returns true if the entry with indices i,l is 1 in the supplied 64xN matrix. This is used to read the nullspace vectors which are output by the Lanczos routine */ return nullrows[i]&bitmask[l]; } /*--------------------------------------------------------------------*/ void reduce_matrix(qs_t qs_inf, slong *nrows, slong *ncols, la_col_t *cols) { /* Perform light filtering on the nrows x ncols matrix specified by cols[]. The processing here is limited to deleting columns that contain a singleton row, then resizing the matrix to have a few more columns than rows. Because deleting a column reduces the counts in several different rows, the process must iterate to convergence. Note that this step is not intended to make the Lanczos iteration run any faster (though it will); it's just that if we don't go to this trouble then there are factorizations for which the matrix step will fail outright */ slong r, c, i, j, k; slong *counts; slong reduced_rows; slong reduced_cols; #if QS_DEBUG slong passes = 0; #endif /* count the number of nonzero entries in each row */ counts = (slong *)flint_calloc((size_t)*nrows, sizeof(slong)); for (i = 0; i < *ncols; i++) { for (j = 0; j < cols[i].weight; j++) counts[cols[i].data[j]]++; } reduced_rows = *nrows; reduced_cols = *ncols; do { r = reduced_rows; /* remove any columns that contain the only entry in one or more rows, then update the row counts to reflect the missing column. Iterate until no more columns can be deleted */ do { c = reduced_cols; for (i = j = 0; i < reduced_cols; i++) { la_col_t *col = cols + i; for (k = 0; k < col->weight; k++) { if (counts[col->data[k]] < 2) break; } if (k < col->weight) { for (k = 0; k < col->weight; k++) { counts[col->data[k]]--; } free_col(col); clear_col(col); } else { cols[j++] = cols[i]; if (j-1 != i) clear_col(col); } } reduced_cols = j; } while (c != reduced_cols); /* count the number of rows that contain a nonzero entry */ for (i = reduced_rows = 0; i < *nrows; i++) { if (counts[i]) reduced_rows++; } /* Because deleting a column reduces the weight of many rows, the number of nonzero rows may be much less than the number of columns. Delete more columns until the matrix has the correct aspect ratio. Columns at the end of cols[] are the heaviest, so delete those (and update the row counts again) */ if (reduced_cols > reduced_rows + qs_inf->extra_rels) { for (i = reduced_rows + qs_inf->extra_rels; i < reduced_cols; i++) { la_col_t *col = cols + i; for (j = 0; j < col->weight; j++) { counts[col->data[j]]--; } free_col(col); clear_col(col); } reduced_cols = reduced_rows + qs_inf->extra_rels; } /* if any columns were deleted in the previous step, then the matrix is less dense and more columns can be deleted; iterate until no further deletions are possible */ #if QS_DEBUG passes++; #endif } while (r != reduced_rows); #if QS_DEBUG flint_printf("reduce to %wd x %wd in %wd passes\n", reduced_rows, reduced_cols, passes); #endif for (i = 0, j = 0; i < *nrows; i++) { if (counts[i] > 0) counts[i] = j++; } for (i = 0; i < reduced_cols; i++) { la_col_t *col = cols + i; for (j = 0; j < col->weight; j++) col->data[j] = counts[col->data[j]]; } flint_free(counts); *ncols = reduced_cols; *nrows = reduced_rows; } /*-------------------------------------------------------------------*/ static void mul_64x64_64x64(uint64_t *a, uint64_t *b, uint64_t *c ) { /* c[][] = x[][] * y[][], where all operands are 64 x 64 (i.e. contain 64 words of 64 bits each). The result may overwrite a or b. */ uint64_t ai, bj, accum; uint64_t tmp[64]; ulong i, j; for (i = 0; i < 64; i++) { j = 0; accum = 0; ai = a[i]; while (ai) { bj = b[j]; if( ai & 1 ) accum ^= bj; ai >>= 1; j++; } tmp[i] = accum; } memcpy(c, tmp, sizeof(tmp)); } /*-----------------------------------------------------------------------*/ static void precompute_Nx64_64x64(uint64_t *x, uint64_t *c) { /* Let x[][] be a 64 x 64 matrix in GF(2), represented as 64 words of 64 bits each. Let c[][] be an 8 x 256 matrix of 64-bit words. This code fills c[][] with a bunch of "partial matrix multiplies". For 0<=i<256, the j_th row of c[][] contains the matrix product ( i << (8*j) ) * x[][] where the quantity in parentheses is considered a 1 x 64 vector of elements in GF(2). The resulting table can dramatically speed up matrix multiplies by x[][]. */ uint64_t accum, xk; ulong i, j, k, index; for (j = 0; j < 8; j++) { for (i = 0; i < 256; i++) { k = 0; index = i; accum = 0; while (index) { xk = x[k]; if (index & 1) accum ^= xk; index >>= 1; k++; } c[i] = accum; } x += 8; c += 256; } } /*-------------------------------------------------------------------*/ static void mul_Nx64_64x64_acc(uint64_t *v, uint64_t *x, uint64_t *c, uint64_t *y, slong n) { /* let v[][] be a n x 64 matrix with elements in GF(2), represented as an array of n 64-bit words. Let c[][] be an 8 x 256 scratch matrix of 64-bit words. This code multiplies v[][] by the 64x64 matrix x[][], then XORs the n x 64 result into y[][] */ slong i; uint64_t word; precompute_Nx64_64x64(x, c); for (i = 0; i < n; i++) { word = v[i]; y[i] ^= c[ 0*256 + ((word>> 0) & 0xff) ] ^ c[ 1*256 + ((word>> 8) & 0xff) ] ^ c[ 2*256 + ((word>>16) & 0xff) ] ^ c[ 3*256 + ((word>>24) & 0xff) ] ^ c[ 4*256 + ((word>>32) & 0xff) ] ^ c[ 5*256 + ((word>>40) & 0xff) ] ^ c[ 6*256 + ((word>>48) & 0xff) ] ^ c[ 7*256 + ((word>>56) ) ]; } } /*-------------------------------------------------------------------*/ static void mul_64xN_Nx64(uint64_t *x, uint64_t *y, uint64_t *c, uint64_t *xy, slong n) { /* Let x and y be n x 64 matrices. This routine computes the 64 x 64 matrix xy[][] given by transpose(x) * y. c[][] is a 256 x 8 scratch matrix of 64-bit words. */ slong i; memset(c, 0, 256 * 8 * sizeof(uint64_t)); memset(xy, 0, 64 * sizeof(uint64_t)); for (i = 0; i < n; i++) { uint64_t xi = x[i]; uint64_t yi = y[i]; c[ 0*256 + ( xi & 0xff) ] ^= yi; c[ 1*256 + ((xi >> 8) & 0xff) ] ^= yi; c[ 2*256 + ((xi >> 16) & 0xff) ] ^= yi; c[ 3*256 + ((xi >> 24) & 0xff) ] ^= yi; c[ 4*256 + ((xi >> 32) & 0xff) ] ^= yi; c[ 5*256 + ((xi >> 40) & 0xff) ] ^= yi; c[ 6*256 + ((xi >> 48) & 0xff) ] ^= yi; c[ 7*256 + ((xi >> 56) ) ] ^= yi; } for(i = 0; i < 8; i++) { ulong j; uint64_t a0, a1, a2, a3, a4, a5, a6, a7; a0 = a1 = a2 = a3 = 0; a4 = a5 = a6 = a7 = 0; for (j = 0; j < 256; j++) { if ((j >> i) & 1) { a0 ^= c[0*256 + j]; a1 ^= c[1*256 + j]; a2 ^= c[2*256 + j]; a3 ^= c[3*256 + j]; a4 ^= c[4*256 + j]; a5 ^= c[5*256 + j]; a6 ^= c[6*256 + j]; a7 ^= c[7*256 + j]; } } xy[ 0] = a0; xy[ 8] = a1; xy[16] = a2; xy[24] = a3; xy[32] = a4; xy[40] = a5; xy[48] = a6; xy[56] = a7; xy++; } } /*-------------------------------------------------------------------*/ static slong find_nonsingular_sub(uint64_t *t, slong *s, slong *last_s, slong last_dim, uint64_t *w) { /* given a 64x64 matrix t[][] (i.e. sixty-four 64-bit words) and a list of 'last_dim' column indices enumerated in last_s[]: - find a submatrix of t that is invertible - invert it and copy to w[][] - enumerate in s[] the columns represented in w[][] */ slong i, j; slong dim; slong cols[64]; uint64_t M[64][2]; uint64_t mask, *row_i, *row_j; uint64_t m0, m1; /* M = [t | I] for I the 64x64 identity matrix */ for (i = 0; i < 64; i++) { M[i][0] = t[i]; M[i][1] = bitmask[i]; } /* put the column indices from last_s[] into the back of cols[], and copy to the beginning of cols[] any column indices not in last_s[] */ mask = 0; for (i = 0; i < last_dim; i++) { cols[63 - i] = last_s[i]; mask |= bitmask[last_s[i]]; } for (i = j = 0; i < 64; i++) { if (!(mask & bitmask[i])) cols[j++] = i; } /* compute the inverse of t[][] */ for (i = dim = 0; i < 64; i++) { /* find the next pivot row and put in row i */ mask = bitmask[cols[i]]; row_i = M[cols[i]]; for (j = i; j < 64; j++) { row_j = M[cols[j]]; if (row_j[0] & mask) { m0 = row_j[0]; m1 = row_j[1]; row_j[0] = row_i[0]; row_j[1] = row_i[1]; row_i[0] = m0; row_i[1] = m1; break; } } /* if a pivot row was found, eliminate the pivot column from all other rows */ if (j < 64) { for (j = 0; j < 64; j++) { row_j = M[cols[j]]; if ((row_i != row_j) && (row_j[0] & mask)) { row_j[0] ^= row_i[0]; row_j[1] ^= row_i[1]; } } /* add the pivot column to the list of accepted columns */ s[dim++] = cols[i]; continue; } /* otherwise, use the right-hand half of M[] to compensate for the absence of a pivot column */ for (j = i; j < 64; j++) { row_j = M[cols[j]]; if (row_j[1] & mask) { m0 = row_j[0]; m1 = row_j[1]; row_j[0] = row_i[0]; row_j[1] = row_i[1]; row_i[0] = m0; row_i[1] = m1; break; } } if (j == 64) { #if QS_DEBUG flint_printf("lanczos error: submatrix " "is not invertible\n"); #endif return 0; } /* eliminate the pivot column from the other rows of the inverse */ for (j = 0; j < 64; j++) { row_j = M[cols[j]]; if ((row_i != row_j) && (row_j[1] & mask)) { row_j[0] ^= row_i[0]; row_j[1] ^= row_i[1]; } } /* wipe out the pivot row */ row_i[0] = row_i[1] = 0; } /* the right-hand half of M[] is the desired inverse */ for (i = 0; i < 64; i++) w[i] = M[i][1]; /* The block Lanczos recurrence depends on all columns of t[][] appearing in s[] and/or last_s[]. Verify that condition here */ mask = 0; for (i = 0; i < dim; i++) mask |= bitmask[s[i]]; for (i = 0; i < last_dim; i++) mask |= bitmask[last_s[i]]; if (mask != (uint64_t)(-1)) { #if QS_DEBUG flint_printf("lanczos error: not all columns used\n"); #endif return 0; } return dim; } /*-------------------------------------------------------------------*/ void mul_MxN_Nx64(slong vsize, slong dense_rows, slong ncols, la_col_t *A, uint64_t *x, uint64_t *b) { /* Multiply the vector x[] by the matrix A (stored columnwise) and put the result in b[]. vsize refers to the number of uint64_t's allocated for x[] and b[]; vsize is probably different from ncols */ slong i, j; memset(b, 0, vsize * sizeof(uint64_t)); for (i = 0; i < ncols; i++) { la_col_t *col = A + i; slong *row_entries = col->data; uint64_t tmp = x[i]; for (j = 0; j < col->weight; j++) { b[row_entries[j]] ^= tmp; } } if (dense_rows) { for (i = 0; i < ncols; i++) { la_col_t *col = A + i; slong *row_entries = col->data + col->weight; uint64_t tmp = x[i]; for (j = 0; j < dense_rows; j++) { if (row_entries[j / 32] & ((slong)1 << (j % 32))) { b[j] ^= tmp; } } } } } /*-------------------------------------------------------------------*/ void mul_trans_MxN_Nx64(slong dense_rows, slong ncols, la_col_t *A, uint64_t *x, uint64_t *b) { /* Multiply the vector x[] by the transpose of the matrix A and put the result in b[]. Since A is stored by columns, this is just a matrix-vector product */ slong i, j; for (i = 0; i < ncols; i++) { la_col_t *col = A + i; slong *row_entries = col->data; uint64_t accum = 0; for (j = 0; j < col->weight; j++) { accum ^= x[row_entries[j]]; } b[i] = accum; } if (dense_rows) { for (i = 0; i < ncols; i++) { la_col_t *col = A + i; slong *row_entries = col->data + col->weight; uint64_t accum = b[i]; for (j = 0; j < dense_rows; j++) { if (row_entries[j / 32] & ((slong)1 << (j % 32))) { accum ^= x[j]; } } b[i] = accum; } } } /*-----------------------------------------------------------------------*/ static void transpose_vector(slong ncols, uint64_t *v, uint64_t **trans) { /* Hideously inefficient routine to transpose a vector v[] of 64-bit words into a 2-D array trans[][] of 64-bit words */ slong i, j; slong col; uint64_t mask, word; for (i = 0; i < ncols; i++) { col = i / 64; mask = bitmask[i % 64]; word = v[i]; j = 0; while (word) { if (word & 1) trans[j][col] |= mask; word = word >> 1; j++; } } } /*-----------------------------------------------------------------------*/ void combine_cols(slong ncols, uint64_t *x, uint64_t *v, uint64_t *ax, uint64_t *av) { /* Once the block Lanczos iteration has finished, x[] and v[] will contain mostly nullspace vectors between them, as well as possibly some columns that are linear combinations of nullspace vectors. Given vectors ax[] and av[] that are the result of multiplying x[] and v[] by the matrix, this routine will use Gauss elimination on the columns of [ax | av] to find all of the linearly dependent columns. The column operations needed to accomplish this are mir- rored in [x | v] and the columns that are independent are skipped. Finally, the dependent columns are copied back into x[] and represent the nullspace vector output of the block Lanczos code. v[] and av[] can be NULL, in which case the elimination process assumes 64 dependencies instead of 128 */ slong i, j, k, bitpos, col, col_words, num_deps; uint64_t mask; uint64_t *matrix[128], *amatrix[128], *tmp; num_deps = 128; if (v == NULL || av == NULL) num_deps = 64; col_words = (ncols + 63) / 64; for (i = 0; i < num_deps; i++) { matrix[i] = (uint64_t *)flint_calloc((size_t)col_words, sizeof(uint64_t)); amatrix[i] = (uint64_t *)flint_calloc((size_t)col_words, sizeof(uint64_t)); } /* operations on columns can more conveniently become operations on rows if all the vectors are first transposed */ transpose_vector(ncols, x, matrix); transpose_vector(ncols, ax, amatrix); if (num_deps == 128) { transpose_vector(ncols, v, matrix + 64); transpose_vector(ncols, av, amatrix + 64); } /* Keep eliminating rows until the unprocessed part of amatrix[][] is all zero. The rows where this happens correspond to linearly dependent vectors in the nullspace */ for (i = bitpos = 0; i < num_deps && bitpos < ncols; bitpos++) { /* find the next pivot row */ mask = bitmask[bitpos % 64]; col = bitpos / 64; for (j = i; j < num_deps; j++) { if (amatrix[j][col] & mask) { tmp = matrix[i]; matrix[i] = matrix[j]; matrix[j] = tmp; tmp = amatrix[i]; amatrix[i] = amatrix[j]; amatrix[j] = tmp; break; } } if (j == num_deps) continue; /* a pivot was found; eliminate it from the remaining rows */ for (j++; j < num_deps; j++) { if (amatrix[j][col] & mask) { /* Note that the entire row, *not* just the nonzero part of it, must be eliminated; this is because the corresponding (dense) row of matrix[][] must have the same operation applied */ for (k = 0; k < col_words; k++) { amatrix[j][k] ^= amatrix[i][k]; matrix[j][k] ^= matrix[i][k]; } } } i++; } /* transpose rows i to 64 back into x[] */ for (j = 0; j < ncols; j++) { uint64_t word = 0; col = j / 64; mask = bitmask[j % 64]; for (k = i; k < 64; k++) { if (matrix[k][col] & mask) word |= bitmask[k]; } x[j] = word; } for (i = 0; i < num_deps; i++) { flint_free(matrix[i]); flint_free(amatrix[i]); } } /*-----------------------------------------------------------------------*/ uint64_t * block_lanczos(flint_rand_t state, slong nrows, slong dense_rows, slong ncols, la_col_t *B) { /* Solve Bx = 0 for some nonzero x; the computed solution, containing up to 64 of these nullspace vectors, is returned */ uint64_t *vnext, *v[3], *x, *v0; uint64_t *winv[3]; uint64_t *vt_a_v[2], *vt_a2_v[2]; uint64_t *scratch; uint64_t *d, *e, *f, *f2; uint64_t *tmp; slong s[2][64]; slong i; slong n = ncols; slong dim0, dim1; uint64_t mask0, mask1; slong vsize; /* allocate all of the size-n variables. Note that because B has been preprocessed to ignore singleton rows, the number of rows may really be less than nrows and may be greater than ncols. vsize is the maximum of these two numbers */ vsize = FLINT_MAX(nrows, ncols); v[0] = (uint64_t *)flint_malloc(vsize * sizeof(uint64_t)); v[1] = (uint64_t *)flint_malloc(vsize * sizeof(uint64_t)); v[2] = (uint64_t *)flint_malloc(vsize * sizeof(uint64_t)); vnext = (uint64_t *)flint_malloc(vsize * sizeof(uint64_t)); x = (uint64_t *)flint_malloc(vsize * sizeof(uint64_t)); v0 = (uint64_t *)flint_malloc(vsize * sizeof(uint64_t)); scratch = (uint64_t *)flint_malloc(FLINT_MAX(vsize, 256 * 8) * sizeof(uint64_t)); /* allocate all the 64x64 variables */ winv[0] = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); winv[1] = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); winv[2] = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); vt_a_v[0] = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); vt_a_v[1] = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); vt_a2_v[0] = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); vt_a2_v[1] = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); d = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); e = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); f = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); f2 = (uint64_t *)flint_malloc(64 * sizeof(uint64_t)); /* The iterations computes v[0], vt_a_v[0], vt_a2_v[0], s[0] and winv[0]. Subscripts larger than zero represent past versions of these quantities, which start off empty (except for the past version of s[], which contains all the column indices */ memset(v[1], 0, vsize * sizeof(uint64_t)); memset(v[2], 0, vsize * sizeof(uint64_t)); for (i = 0; i < 64; i++) { s[1][i] = i; vt_a_v[1][i] = 0; vt_a2_v[1][i] = 0; winv[1][i] = 0; winv[2][i] = 0; } dim0 = 0; dim1 = 64; mask1 = (uint64_t)(-1); #if QS_DEBUG slong iter = 0; #endif /* The computed solution 'x' starts off random, and v[0] starts off as B*x. This initial copy of v[0] must be saved off separately */ for (i = 0; i < n; i++) #if FLINT_BITS==64 v[0][i] = (uint64_t) n_randlimb(state); #else v[0][i] = (uint64_t) n_randlimb(state) + ((uint64_t) n_randlimb(state) << 32); #endif memcpy(x, v[0], vsize * sizeof(uint64_t)); mul_MxN_Nx64(vsize, dense_rows, ncols, B, v[0], scratch); mul_trans_MxN_Nx64(dense_rows, ncols, B, scratch, v[0]); memcpy(v0, v[0], vsize * sizeof(uint64_t)); /* perform the iteration */ while (1) { #if QS_DEBUG iter++; #endif /* multiply the current v[0] by a symmetrized version of B, or B'B (apostrophe means transpose). Use "A" to refer to B'B */ mul_MxN_Nx64(vsize, dense_rows, ncols, B, v[0], scratch); mul_trans_MxN_Nx64(dense_rows, ncols, B, scratch, vnext); /* compute v0'*A*v0 and (A*v0)'(A*v0) */ mul_64xN_Nx64(v[0], vnext, scratch, vt_a_v[0], n); mul_64xN_Nx64(vnext, vnext, scratch, vt_a2_v[0], n); /* if the former is orthogonal to itself, then the iteration has finished */ for (i = 0; i < 64; i++) { if (vt_a_v[0][i] != 0) break; } if (i == 64) { break; } /* Find the size-'dim0' nonsingular submatrix of v0'*A*v0, invert it, and list the column indices present in the submatrix */ dim0 = find_nonsingular_sub(vt_a_v[0], s[0], s[1], dim1, winv[0]); if (dim0 == 0) break; /* mask0 contains one set bit for every column that participates in the inverted submatrix computed above */ mask0 = 0; for (i = 0; i < dim0; i++) mask0 |= bitmask[s[0][i]]; /* compute d */ for (i = 0; i < 64; i++) d[i] = (vt_a2_v[0][i] & mask0) ^ vt_a_v[0][i]; mul_64x64_64x64(winv[0], d, d); for (i = 0; i < 64; i++) d[i] = d[i] ^ bitmask[i]; /* compute e */ mul_64x64_64x64(winv[1], vt_a_v[0], e); for (i = 0; i < 64; i++) e[i] = e[i] & mask0; /* compute f */ mul_64x64_64x64(vt_a_v[1], winv[1], f); for (i = 0; i < 64; i++) f[i] = f[i] ^ bitmask[i]; mul_64x64_64x64(winv[2], f, f); for (i = 0; i < 64; i++) f2[i] = ((vt_a2_v[1][i] & mask1) ^ vt_a_v[1][i]) & mask0; mul_64x64_64x64(f, f2, f); /* compute the next v */ for (i = 0; i < n; i++) vnext[i] = vnext[i] & mask0; mul_Nx64_64x64_acc(v[0], d, scratch, vnext, n); mul_Nx64_64x64_acc(v[1], e, scratch, vnext, n); mul_Nx64_64x64_acc(v[2], f, scratch, vnext, n); /* update the computed solution 'x' */ mul_64xN_Nx64(v[0], v0, scratch, d, n); mul_64x64_64x64(winv[0], d, d); mul_Nx64_64x64_acc(v[0], d, scratch, x, n); /* rotate all the variables */ tmp = v[2]; v[2] = v[1]; v[1] = v[0]; v[0] = vnext; vnext = tmp; tmp = winv[2]; winv[2] = winv[1]; winv[1] = winv[0]; winv[0] = tmp; tmp = vt_a_v[1]; vt_a_v[1] = vt_a_v[0]; vt_a_v[0] = tmp; tmp = vt_a2_v[1]; vt_a2_v[1] = vt_a2_v[0]; vt_a2_v[0] = tmp; memcpy(s[1], s[0], 64 * sizeof(slong)); mask1 = mask0; dim1 = dim0; } #if QS_DEBUG flint_printf("lanczos halted after %wd iterations\n", iter); #endif /* free unneeded storage */ flint_free(vnext); flint_free(scratch); flint_free(v0); flint_free(vt_a_v[0]); flint_free(vt_a_v[1]); flint_free(vt_a2_v[0]); flint_free(vt_a2_v[1]); flint_free(winv[0]); flint_free(winv[1]); flint_free(winv[2]); flint_free(d); flint_free(e); flint_free(f); flint_free(f2); /* if a recoverable failure occurred, start everything over again */ if (dim0 == 0) { #if QS_DEBUG flint_printf("linear algebra failed; retrying...\n"); #endif flint_free(x); flint_free(v[0]); flint_free(v[1]); flint_free(v[2]); return NULL; } /* convert the output of the iteration to an actual collection of nullspace vectors */ mul_MxN_Nx64(vsize, dense_rows, ncols, B, x, v[1]); mul_MxN_Nx64(vsize, dense_rows, ncols, B, v[0], v[2]); combine_cols(ncols, x, v[0], v[1], v[2]); /* verify that these really are linear dependencies of B */ mul_MxN_Nx64(vsize, dense_rows, ncols, B, x, v[0]); for (i = 0; i < ncols; i++) { if (v[0][i] != 0) break; } if (i < ncols) flint_throw(FLINT_ERROR, "lanczos error: dependencies don't work %wd\n", i); flint_free(v[0]); flint_free(v[1]); flint_free(v[2]); return x; } flint-3.1.3/src/qsieve/clear.c000066400000000000000000000013201461254215100161440ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "qsieve.h" void qsieve_clear(qs_t qs_inf) { fmpz_clear(qs_inf->n); fmpz_clear(qs_inf->kn); flint_free(qs_inf->factor_base); flint_free(qs_inf->sqrts); qs_inf->factor_base = NULL; qs_inf->sqrts = NULL; flint_free(qs_inf->fname); } flint-3.1.3/src/qsieve/collect_relations.c000066400000000000000000000377231461254215100206030ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016, 2020 William Hart Copyright (C) 2015 Nitin Kumar Copyright (C) 2020 Dan Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "ulong_extras.h" #include "fmpz.h" #include "qsieve.h" #ifdef __GNUC__ # define memset __builtin_memset #else # include #endif /* The actual sieving part of the quadratic sieve. This version is only run if the sieve block is small, i.e. less than 2*BLOCK_SIZE. */ void qsieve_do_sieving(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly) { slong num_primes = qs_inf->num_primes; int * soln1 = poly->soln1; int * soln2 = poly->soln2; prime_t * factor_base = qs_inf->factor_base; mp_limb_t p; unsigned char * end = sieve + qs_inf->sieve_size; register unsigned char * pos1; register unsigned char * pos2; register unsigned char * bound; slong size; slong diff; slong pind; /* set entries in sieve to initial value and put a sentinel at the end */ memset(sieve, qs_inf->sieve_fill, qs_inf->sieve_size + sizeof(ulong)); *end = (char) 255; for (pind = qs_inf->small_primes; pind < num_primes; pind++) { if (soln2[pind] == 0) continue; /* don't sieve with A factors */ p = factor_base[pind].p; size = factor_base[pind].size; pos1 = sieve + soln1[pind]; pos2 = sieve + soln2[pind]; diff = pos2 - pos1; bound = end - 2*p; /* mark off entries in sieve, unrolled by 2 */ while (bound - pos1 > 0) { (*pos1) += size, (*(pos1 + diff)) += size, pos1 += p; (*pos1) += size, (*(pos1 + diff)) += size, pos1 += p; } /* deal with final entries at the end, missed by unrolled loop */ while ((end - pos1 > 0) && (end - pos1 - diff > 0)) { (*pos1) += size, (*(pos1 + diff)) += size, pos1 += p; } pos2 = pos1 + diff; if (end - pos2 > 0) { (*pos2) += size; } if (end - pos1 > 0) { (*pos1) += size; } } } /* Second sieving routine. This version breaks sieve array into blocks then sieves each block, with the whole factor base at once. */ void qsieve_do_sieving2(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly) { slong b, d1, d2, i; slong pind, size; mp_limb_t p; slong num_primes = qs_inf->num_primes; int * soln1 = poly->soln1; int * soln2 = poly->soln2; int * posn1 = poly->posn1; int * posn2 = poly->posn2; prime_t * factor_base = qs_inf->factor_base; unsigned char * B; register unsigned char * Bp; register unsigned char * pos; /* fill sieve with initial values and put sentinel at end */ memset(sieve, qs_inf->sieve_fill, qs_inf->sieve_size + sizeof(ulong)); sieve[qs_inf->sieve_size] = (char) 255; /* initial values for positions (which must be saved at the end of each sieve block in preparation for start of next sieve block) */ for (i = 0; i < num_primes; i++) { posn1[i] = soln1[i]; posn2[i] = soln2[i] - posn1[i]; } /* break sieve into blocks of size BLOCK_SIZE */ for (b = 1; b <= qs_inf->sieve_size / BLOCK_SIZE; b++) { /* end of current sieve block */ B = sieve + b * BLOCK_SIZE; /* deal with small to medium sized primes first these hit sieve block multiple times, making unrolling worthwhile */ for (pind = qs_inf->small_primes; pind < qs_inf->second_prime; pind++) { if (soln2[pind] == 0) /* skip primes dividing A */ continue; p = factor_base[pind].p; size = factor_base[pind].size; d1 = posn2[pind]; d2 = p - d1; Bp = B - 2*d1 - d2; pos = sieve + posn1[pind]; while (pos < Bp) { (*pos) += size, (*(pos + d1)) += size, pos += p; (*pos) += size, (*(pos + d1)) += size, pos += p; } Bp = B - d1; while (pos < Bp) { (*pos) += size, (*(pos + d1)) += size, pos += p; } if (pos < B) { (*pos) += size, pos += d1; posn2[pind] = d2; } else { posn2[pind] = d1; } posn1[pind] = (pos - sieve); } /* now deal with larger primes which are likely to only hit sieve block once, if at all */ for (pind = qs_inf->second_prime; pind < num_primes; pind++) { p = factor_base[pind].p; if (soln2[pind] == 0) continue; size = factor_base[pind].size; pos = sieve + posn1[pind]; if (pos < B) /* hits the sieve block */ { (*pos) += size; pos += posn2[pind]; if (pos < B) { (*pos) += size; pos += p - posn2[pind]; } else { posn2[pind] = p - posn2[pind]; } posn1[pind] = (pos - sieve); } else /* doesn't hit this sieve block, save posn for next block */ { posn1[pind] = (pos - sieve); } } } } /* check position i in sieve array for smoothness */ slong qsieve_evaluate_candidate(qs_t qs_inf, ulong i, unsigned char * sieve, qs_poly_t poly) { slong bits, exp, extra_bits; mp_limb_t modp, prime; slong num_primes = qs_inf->num_primes; prime_t * factor_base = qs_inf->factor_base; slong * small = poly->small; /* exponents of small primes and mult. */ fac_t * factor = poly->factor; int * soln1 = poly->soln1; int * soln2 = poly->soln2; mp_limb_t * A_ind = qs_inf->A_ind; mp_limb_t pinv; slong num_factors = 0; slong relations = 0; slong j, k; fmpz_t X, Y, C, res, p; fmpz_init(X); fmpz_init(Y); fmpz_init(res); fmpz_init(p); fmpz_init(C); qsieve_compute_C(C, qs_inf, poly); fmpz_set_si(X, i - qs_inf->sieve_size / 2); /* X */ fmpz_mul(Y, X, qs_inf->A); fmpz_add(Y, Y, poly->B); /* Y = AX+B */ fmpz_add(res, Y, poly->B); /* Y = AX+2B */ fmpz_mul(res, res, X); fmpz_add(res, res, C); /* res = AX^2 + 2BX + C */ #if QS_DEBUG & 128 flint_printf("res = "); fmpz_print(res); flint_printf("\n"); flint_printf("Poly: "); fmpz_print(qs_inf->A); flint_printf("*x^2 + 2*"); fmpz_print(poly->B); flint_printf("*x + "); fmpz_print(C); flint_printf("\n"); flint_printf("x = %wd\n", i - qs_inf->sieve_size / 2); #endif sieve[i] -= qs_inf->sieve_fill; /* adjust sieve entry to number of bits */ bits = FLINT_ABS(fmpz_bits(res)); /* compute bits of poly value */ bits -= BITS_ADJUST; /* adjust for log approximations */ extra_bits = 0; /* bits for mult. and small primes we didn't sieve with */ if (factor_base[0].p != 1) /* divide out powers of the multiplier */ { fmpz_set_ui(p, factor_base[0].p); exp = fmpz_remove(res, res, p); if (exp) extra_bits += exp*qs_inf->factor_base[0].size; small[0] = exp; #if QS_DEBUG & 128 if (exp) flint_printf("%ld^%ld ", factor_base[0].p, exp); #endif } else { small[0] = 0; } fmpz_set_ui(p, 2); /* divide out by powers of 2 */ exp = fmpz_remove(res, res, p); #if QS_DEBUG & 128 if (exp) flint_printf("%ld^%ld ", 2, exp); #endif extra_bits += exp; small[1] = exp; for (j = 3; j < qs_inf->small_primes; j++) /* pull out small primes */ { prime = factor_base[j].p; pinv = factor_base[j].pinv; modp = n_mod2_preinv(i, prime, pinv); if (modp == soln1[j] || modp == soln2[j]) { fmpz_set_ui(p, prime); exp = fmpz_remove(res, res, p); if (exp) extra_bits += qs_inf->factor_base[j].size; small[j] = exp; #if QS_DEBUG & 128 if (exp) flint_printf("%ld^%ld ", prime, exp); #endif } else { small[j] = 0; } } /* if we have a chance of being a candidate */ if (extra_bits + sieve[i] > bits) { sieve[i] += extra_bits; /* add bits from small primes and mult. */ /* pull out remaining primes we stop once we have reached the same number of bits as indicated in the sieve entry */ for (j = qs_inf->small_primes; j < num_primes && extra_bits < sieve[i]; j++) { prime = factor_base[j].p; pinv = factor_base[j].pinv; modp = n_mod2_preinv(i, prime, pinv); if (soln2[j] != 0) /* not a prime dividing A */ { if (modp == soln1[j] || modp == soln2[j]) { fmpz_set_ui(p, prime); exp = fmpz_remove(res, res, p); extra_bits += qs_inf->factor_base[j].size; factor[num_factors].ind = j; factor[num_factors++].exp = exp; #if QS_DEBUG & 128 flint_printf("%ld^%ld ", prime, exp); #endif } } else /* prime dividing A */ { fmpz_set_ui(p, prime); exp = fmpz_remove(res, res, p); factor[num_factors].ind = j; factor[num_factors++].exp = exp + 1; /* really factoring A*f(i) */ #if QS_DEBUG & 128 if (exp) flint_printf("%ld^%ld ", prime, exp); #endif } } #if QS_DEBUG & 128 if (num_factors > 0) flint_printf("\n"); #endif if (fmpz_cmp_ui(res, 1) == 0 || fmpz_cmp_si(res, -1) == 0) /* We've found a relation */ { #if QS_DEBUG if (qs_inf->full_relation % 100 == 0) flint_printf("%ld relations\n", qs_inf->full_relation); #endif /* set sign amongst small factors */ if (fmpz_cmp_si(res, -1) == 0) small[2] = 1; else small[2] = 0; for (k = 0; k < qs_inf->s; k++) /* Commit any outstanding A factors */ { if (A_ind[k] >= j) /* check it is beyond where loop above ended */ { factor[num_factors].ind = A_ind[k]; factor[num_factors++].exp = 1; } } poly->num_factors = num_factors; #if FLINT_USES_PTHREAD pthread_mutex_lock(&qs_inf->mutex); #endif qsieve_write_to_file(qs_inf, 1, Y, poly); qs_inf->full_relation++; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&qs_inf->mutex); #endif relations++; } else /* not a relation, perhaps a partial? */ { /* set sign */ if (fmpz_sgn(res) < 0) { fmpz_neg(res, res); small[2] = 1; } else small[2] = 0; /* if we have a small cofactor (at most 30 bits) */ if (fmpz_bits(res) <= 30) { prime = fmpz_get_ui(res); /* a large prime is taken heuristically to be < 60 times largest FB prime; skip values not coprime with multiplier, as this will lead to factors of kn, not n */ if (prime < 60*factor_base[qs_inf->num_primes - 1].p && n_gcd(prime, qs_inf->k) == 1) { for (k = 0; k < qs_inf->s; k++) /* commit any outstanding A factors */ { if (A_ind[k] >= j) /* check beyond where loop above ended */ { factor[num_factors].ind = A_ind[k]; factor[num_factors++].exp = 1; } } poly->num_factors = num_factors; #if FLINT_USES_PTHREAD pthread_mutex_lock(&qs_inf->mutex); #endif /* store this partial in file */ qsieve_write_to_file(qs_inf, prime, Y, poly); qs_inf->edges++; qsieve_add_to_hashtable(qs_inf, prime); #if FLINT_USES_PTHREAD pthread_mutex_unlock(&qs_inf->mutex); #endif } } } goto cleanup; } cleanup: fmpz_clear(X); fmpz_clear(Y); fmpz_clear(C); fmpz_clear(res); fmpz_clear(p); return relations; } /* scan sieve array for possible candidates for smooth relations and process those relations to check for smoothness */ slong qsieve_evaluate_sieve(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly) { slong i = 0, j = 0; ulong * sieve2 = (ulong *) sieve; unsigned char bits = qs_inf->sieve_bits; slong rels = 0; while (j < qs_inf->sieve_size / sizeof(ulong)) { /* scan 4 or 8 bytes at once for sieve entries over threshold */ #if FLINT64 while ((sieve2[j] & UWORD(0xC0C0C0C0C0C0C0C0)) == 0) #else while ((sieve2[j] & UWORD(0xC0C0C0C0)) == 0) #endif { j++; /* advance to next word */ } i = j * sizeof(ulong); /* check bytes individually in word */ while (i < (j + 1) * sizeof(ulong) && i < qs_inf->sieve_size) { /* if we are over the threshold, check candidate for smoothness */ if (sieve[i] > bits) rels += qsieve_evaluate_candidate(qs_inf, i, sieve, poly); i++; } j++; } return rels; } /* procedure to call polynomial initialization and sieving procedure */ typedef struct { qs_s * inf; unsigned char * sieve; slong thread_idx; qs_poly_s * thread_poly; unsigned char * thread_sieve; slong rels; } _worker_arg_struct; static void qsieve_collect_relations_worker(void * varg) { _worker_arg_struct * arg = (_worker_arg_struct *) varg; qs_s * qs_inf = arg->inf; qs_poly_s * thread_poly = arg->thread_poly; unsigned char * thread_sieve = arg->thread_sieve; slong j, iterations = (1 << (qs_inf->s - 1)); while (1) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&qs_inf->mutex); #endif j = qs_inf->index_j; qs_inf->index_j = j + 1; if (j < iterations) { /* copy poly data for thread we are in */ if (j > 0) qsieve_init_poly_next(qs_inf, j); qsieve_poly_copy(thread_poly, qs_inf); } #if FLINT_USES_PTHREAD pthread_mutex_unlock(&qs_inf->mutex); #endif if (j >= iterations) return; if (qs_inf->sieve_size < 2*BLOCK_SIZE) qsieve_do_sieving(qs_inf, thread_sieve, thread_poly); else qsieve_do_sieving2(qs_inf, thread_sieve, thread_poly); arg->rels += qsieve_evaluate_sieve(qs_inf, thread_sieve, thread_poly); } } slong qsieve_collect_relations(qs_t qs_inf, unsigned char * sieve) { slong i; _worker_arg_struct * args; slong relations; const thread_pool_handle* handles = qs_inf->handles; slong num_handles = qs_inf->num_handles; args = (_worker_arg_struct *) flint_malloc((1 + num_handles) *sizeof(_worker_arg_struct)); qs_inf->index_j = 0; qsieve_init_poly_first(qs_inf); for (i = 0; i <= num_handles; i++) { args[i].inf = qs_inf; args[i].thread_idx = i; args[i].thread_poly = qs_inf->poly + i; args[i].thread_sieve = sieve + (qs_inf->sieve_size + sizeof(ulong) + 64)*i; args[i].rels = 0; } for (i = 0; i < num_handles; i++) { thread_pool_wake(global_thread_pool, handles[i], 0, qsieve_collect_relations_worker, &args[i]); } qsieve_collect_relations_worker(&args[num_handles]); relations = args[num_handles].rels; for (i = 0; i < num_handles; i++) { thread_pool_wait(global_thread_pool, handles[i]); relations += args[i].rels; } flint_free(args); return relations; } flint-3.1.3/src/qsieve/compute_poly_data.c000066400000000000000000000522231461254215100205760ustar00rootroot00000000000000/* Copyright (C) 2016, 2020 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "qsieve.h" /* * compute bounds for optimal A (coeff of poly f(x) = Ax^2 + 2Bx + C, where C = (B^2 - kn)/A; note (Ax + B)^2 - kn = A*f(x)) * compute optimal number of factors of A * allocate space for polynomial data * compute first A value (a product of factor base primes) * set up data for lexicographic ordering for subsequent A coeffs We try to compute A such that: (i) A is close to it's ideal value which is, sqrt(2 * kn) / M, where kn is the number to be factored and M is the size of sieve (ii) A should not contain "small" prime factors, it will decrease number of relations (iii) A should not contain primes factor that are too large, or (i) will be difficult (iv) A should have as many factors as possible, to obtain a large number of polynomials If the optimal number of factors of A is <= 3 we simply take every possible product of three factor base primes in the allowed range, as we will need as many possible A's as we can get, as the number of polynomials we get from any given A is just 2^(s-1) where s is the number of prime factors of A. Otherwise, we pick s-1 factors using a lexicographic ordering so that we don't get any duplicate A's. The factors are chosen from the array of factor base primes such that their indices (starting with index 0 corresponding to the smallest allowed factor) aren't divisible by 4. Then we choose the final factor of A to optimise the value of A as above, and such that it's index (as just described) is divisible by 4. Return value indicates success. Should always succeed unless tuning parameters are really screwed up! */ int qsieve_init_A(qs_t qs_inf) { slong i, j; slong s, low, high, span, m, h; mp_limb_t bits, num_factors, rem, mid; mp_limb_t factor_bound[40]; mp_limb_t * A_ind; mp_limb_t * curr_subset, * first_subset; prime_t * factor_base = qs_inf->factor_base; fmpz_t prod, temp, upper_bound, lower_bound; int ret = 1, found_j; fmpz_init(temp); fmpz_init(upper_bound); fmpz_init(lower_bound); fmpz_init_set_ui(prod, 1); fmpz_fdiv_q_ui(lower_bound, qs_inf->target_A, 2); fmpz_mul_ui(upper_bound, qs_inf->target_A, 2); bits = fmpz_bits(qs_inf->target_A); /* compute indices of points in factor base where number of bits of primes increases, starting with the first non-small prime, i.e. factor_bound[0] will be the index of the first non-small prime, and then factor_bound[j] will be the first prime that has more than j bits */ for (i = 0; i < 40; i++) factor_bound[i] = 0; for (j = 0, i = qs_inf->small_primes; i < qs_inf->num_primes; i++) { if (qs_inf->factor_base[i].size != j) { factor_bound[j] = i; j = qs_inf->factor_base[i].size; } } /* the following loop is taken from msieve, it tries to determine number of factors, such that we have enough primes to choose factors of A from */ if (bits > 210) i = 15; else if (bits > 190) i = 13; else if (bits > 180) i = 12; else i = 11; high = low = 0; for ( ; i > 7; i--) { num_factors = bits / i; rem = bits % i; if (factor_bound[i] == 0 || num_factors == 1) continue; /* factor too large or not enough factors */ /* let n = bits, num_factors = floor(n/i), rem = n - i*num_factors we can only guarantee that bounds cover [2^(n - 1), 2^n] when factor base is very small, the algorithm is forced to use very small primes which grow too rapidly; to compensate we allow primes that are half the size on the lower end */ if (rem == 0 && num_factors > 2 && factor_bound[i + 1] > 0 && factor_bound[i - 1 - (i <= 10)] > 0) { /* optimal case, primes in range [2^(i-1), 2^(i+1)] products cover [2^(n - n/i), 2^(n + n/i)] */ low = factor_bound[i - 1 - (i <= 10)]; high = factor_bound[i + 1]; break; } else if (rem <= num_factors) { /* some left over bits, let primes be in [2^i, 2^(i+2)] products in [2^(n - rem), 2^(n - rem + 2*num_factors)] */ if (num_factors > 2 && factor_bound[i + 2] > 0 && factor_bound[i + - (i <= 9)] > 0) { low = factor_bound[i - (i <= 9)]; high = factor_bound[i + 2]; break; } } else if (i - rem <= num_factors) { /* nearly enough bits for extra factor primes will be in range [2^(i-1), 2^(i+1)] product will be in [2^(n + (i - rem) - num_factors - 1), 2^(n + (i - rem) + num_factors + 1)] */ if (factor_bound[i + 1] > 0 && factor_bound[i - 1 - (i <= 10)] > 0) { num_factors++; low = factor_bound[i - 1 - (i <= 10)]; high = factor_bound[i + 1]; break; } } } /* not successful, must be a small factorisation */ if (i == 7) { num_factors = (bits >= 15) ? 3 : 2; low = qs_inf->small_primes; high = qs_inf->num_primes; } s = num_factors; qs_inf->s = s; #if QS_DEBUG flint_printf("s = %wd\n", s); flint_printf("high = %wd\n", high); flint_printf("low = %wd\n", low); flint_printf("span = %wd\n", high - low); #endif qsieve_poly_init(qs_inf); /* allocate space for poly data */ A_ind = qs_inf->A_ind; /* indices of primes dividing A */ curr_subset = qs_inf->curr_subset; first_subset = qs_inf->first_subset; span = high - low; /* factors of A : if number of factors is at most 3 just generate 3-subset of possible range from factor base lexicographically else generate (s - 1) - subset of indices 1, 2, 3 mod 4 from possible range from factor base lexicographically and choose last factor from index 0 mod 4 so that product of values is close to the approximate optimal value for hypercube */ if (s <= 3) /* small factorisation, will need all possible triples */ { m = 0; h = s; for (j = 0; j < s; j++) /* start with first s allowed primes */ { curr_subset[j] = j; first_subset[j] = j; /* save first tuple in case of restart */ } fmpz_set_ui(prod, 1); for (j = 0; j < s; j++) { fmpz_mul_ui(prod, prod, factor_base[curr_subset[j] + low].p); A_ind[j] = curr_subset[j] + low; } } else { m = 0; h = s - 1; for (j = 0; j < s - 1; j++) /* first s - 1 allowed primes, indices not 0 mod 4 */ curr_subset[j] = j; /* search until we find A of the right size, or until we run out of allowed primes */ while (1) { if (4*(curr_subset[0] + s - 2)/3 >= span) { ret = 0; goto init_A_cleanup; } fmpz_set_ui(prod, 1); for (j = 0; j < s - 1; j++) { /* only pick primes whose indices are not 0 mod 4 */ fmpz_mul_ui(prod, prod, factor_base[4*curr_subset[j]/3 + 1 + low].p); } /* binary search for final prime */ i = 0; j = span/4 - 1; found_j = 0; while (i < j) { mid = i + (j - i) / 2; fmpz_mul_ui(temp, prod, factor_base[4*mid + low].p); if (fmpz_cmp(lower_bound, temp) > 0) { i = mid + (i == mid); } else if (fmpz_cmp(temp, upper_bound) > 0) { j = mid - (j == mid); } else { j = 4*mid + low; found_j = 1; break; } } if (found_j) break; /* success */ /* (s - 1)-tuple failed, step to next (s - 1)-tuple */ h = (4*(m + h + 1)/3 >= span) ? h + 1 : 1; m = curr_subset[s - h - 1] + 1; for (j = 0; j < h; j++) curr_subset[s + j - h - 1] = m + j; } A_ind[s - 1] = j; fmpz_mul_ui(prod, prod, qs_inf->factor_base[A_ind[s - 1]].p); for (j = 0; j < s - 1; j++) A_ind[j] = 4*curr_subset[j]/3 + 1 + low; for (j = 0; j < s; j++) first_subset[j] = curr_subset[j]; /* save 1st tuple for restarts */ #if QS_DEBUG flint_printf("First A_ind = ("); for (i = 0; i < s - 1; i++) flint_printf("%ld, ", A_ind[i]); flint_printf("%ld", A_ind[s - 1]); flint_printf(")\n"); #endif } if (s > 3) { qs_inf->j = A_ind[s - 1]; /* save s-th factor of A if s > 3 (restart) */ qs_inf->A_ind_diff = 1; } qs_inf->h = h; qs_inf->m = m; qs_inf->low = low; qs_inf->high = high; qs_inf->span = span; fmpz_set(qs_inf->A, prod); fmpz_set(qs_inf->low_bound, lower_bound); fmpz_set(qs_inf->upp_bound, upper_bound); #if QS_DEBUG flint_printf("number of factors in hypercube = %wd\n", qs_inf->s); flint_printf("factor base size = %wd max prime = %wu\n", qs_inf->num_primes, qs_inf->factor_base[qs_inf->num_primes - 1].p); flint_printf("possible candidate in range [ %wd, %wd ]\n", qs_inf->low, qs_inf->high); flint_printf("optimal value of hypercube = "); fmpz_print(qs_inf->target_A); flint_printf("\n"); flint_printf("lower bound = "); fmpz_print(lower_bound); flint_printf("\n"); flint_printf("upper bound = "); fmpz_print(upper_bound); flint_printf("\n"); flint_printf("initial hypercube = "); fmpz_print(qs_inf->A); flint_printf("\n"); #endif init_A_cleanup: fmpz_clear(prod); fmpz_clear(temp); fmpz_clear(upper_bound); fmpz_clear(lower_bound); return ret; /* success */ } /* If the factorisation fails due to the factor base being too small we restart the computation with a new factor base. As the size of factors and the number of factors of A will not change, we simply recompute A from the data that was already computed for the original factor base, starting again from the first A. */ void qsieve_reinit_A(qs_t qs_inf) { slong low, s, j; mp_limb_t * A_ind = qs_inf->A_ind; mp_limb_t * curr_subset = qs_inf->curr_subset; mp_limb_t * first_subset = qs_inf->first_subset; prime_t * factor_base = qs_inf->factor_base; low = qs_inf->low; s = qs_inf->s; fmpz_set_ui(qs_inf->A, UWORD(1)); if (s <= 3) { for (j = 0; j < s; j++) { curr_subset[j] = first_subset[j]; /* restore first tuple */ A_ind[j] = curr_subset[j] + low; } } else { for (j = 0; j < s - 1; j++) { curr_subset[j] = first_subset[j]; /* restore first tuple */ A_ind[j] = 4*curr_subset[j]/3 + low; } A_ind[s - 1] = qs_inf->j; } for (j = 0; j < s; j++) fmpz_mul_ui(qs_inf->A, qs_inf->A, factor_base[A_ind[j]].p); qs_inf->m = 0; qs_inf->h = s; } /* Compute next A coefficient (differing from previous tuple in at least two positions). This is called every time we run out of B coefficients for a given A coefficient and need to compute a new A coefficient. If the return value is 0, we have run out of possible coefficients (should not ever happen unless tuning parameters are way off). */ int qsieve_next_A(qs_t qs_inf) { slong i, j, mid, diff; slong s = qs_inf->s; slong low = qs_inf->low; slong span = qs_inf->span; slong h = qs_inf->h; slong m = qs_inf->m; mp_limb_t ret = 1; mp_limb_t * curr_subset = qs_inf->curr_subset; mp_limb_t * A_ind = qs_inf->A_ind; prime_t * factor_base = qs_inf->factor_base; fmpz_t prod, temp; int found_j, inc_diff; fmpz_init(prod); fmpz_init(temp); /* generate next value of A */ if (s <= 3) { if (curr_subset[0] != span - s + 1) { h = (m >= span - h) ? h + 1 : 1; m = curr_subset[s - h] + 1; for (j = 0; j < h; j++) curr_subset[s + j - h] = m + j; fmpz_set_ui(prod, UWORD(1)); for (j = 0; j < s; j++) fmpz_mul_ui(prod, prod, factor_base[curr_subset[j] + low].p); for (j = 0; j < s; j++) A_ind[j] = curr_subset[j] + low; } else ret = 0; } else { diff = qs_inf->A_ind_diff; inc_diff = 0; while (1) { if (4*(curr_subset[0] + s + diff)/3 + 1 >= span) /* have run out of A's */ { ret = 0; goto next_A_cleanup; } h = (4*(m + diff + h + 1)/3 >= span) ? h + 1 : 1; m = curr_subset[s - 2 - h] + 1 + ((m%diff) == 0); if (h == 2) inc_diff = 1; else if (h > 2) diff = 1; for (j = 0; j < h; j++) curr_subset[s + j - h - 2] = m + j; curr_subset[s - 2] = curr_subset[s - 3] + diff; fmpz_set_ui(prod, 1); for (j = 0; j < s - 1; j++) fmpz_mul_ui(prod, prod, factor_base[4*curr_subset[j]/3 + 1 + low].p); /* binary search for final prime */ i = 0; j = span/4 - 1; found_j = 0; while (i < j) { mid = i + (j - i) / 2; fmpz_mul_ui(temp, prod, factor_base[4*mid + low].p); if (fmpz_cmp(qs_inf->low_bound, temp) > 0) { i = mid + (i == mid); } else if (fmpz_cmp(temp, qs_inf->upp_bound) > 0) { j = mid - (j == mid); } else { j = 4*mid + low; found_j = 1; if (inc_diff) { diff += 1; qs_inf->A_ind_diff = diff; } break; } } if (found_j) { A_ind[s - 1] = j; fmpz_mul_ui(prod, prod, qs_inf->factor_base[j].p); for (j = 0; j < s - 1; j++) A_ind[j] = 4*curr_subset[j]/3 + 1 + low; break; } } } #if QS_DEBUG flint_printf("A_ind = ("); for (i = 0; i < s - 1; i++) flint_printf("%ld, ", A_ind[i]); flint_printf("%ld", A_ind[s - 1]); flint_printf(")\n"); #endif qs_inf->h = h; qs_inf->m = m; fmpz_set(qs_inf->A, prod); next_A_cleanup: fmpz_clear(prod); fmpz_clear(temp); return ret; } /* * Precompute data for polynomials which depends only on current A and the factor base primes and not on the current B coeff: A_inv, A_divp, B0_terms, B_terms, A_inv2B * Compute the first B coeff */ void qsieve_init_poly_first(qs_t qs_inf) { slong i, k; slong s = qs_inf->s; mp_limb_t * A_ind = qs_inf->A_ind; mp_limb_t * A_inv = qs_inf->A_inv; mp_limb_t * B0_terms = qs_inf->B0_terms; mp_limb_t ** A_inv2B = qs_inf->A_inv2B; fmpz_t * B_terms = qs_inf->B_terms; fmpz_t * A_divp = qs_inf->A_divp; prime_t * factor_base = qs_inf->factor_base; int * sqrts = qs_inf->sqrts; int * soln1 = qs_inf->soln1; int * soln2 = qs_inf->soln2; mp_limb_t p, pinv, temp, temp2; #if QS_DEBUG qs_inf->poly_count += 1; #endif fmpz_zero(qs_inf->B); /* calculate: * A_divp[i] = A/p_i and * B0_terms[i] = min(gamma_i, p - gamma_i) where gamma_i = (sqrt(kn)*(A_divp[i])^(-1)) mod p_i, where the p_i are the prime factors of A * B_terms[i] = A_divp[i]*B0_terms[i] (multi prec.) * first B coeff for current A */ for (i = 0; i < s; i++) { p = factor_base[A_ind[i]].p; pinv = factor_base[A_ind[i]].pinv; /* compute A_divp[i] */ fmpz_divexact_ui(A_divp[i], qs_inf->A, p); /* compute B0_terms[i] */ temp = fmpz_fdiv_ui(A_divp[i], p); temp = n_invmod(temp, p); B0_terms[i] = n_mulmod2_preinv(temp, sqrts[A_ind[i]], p, pinv); if (B0_terms[i] > p/2) B0_terms[i] = p - B0_terms[i]; /* compute B_terms[i] */ fmpz_mul_ui(B_terms[i], A_divp[i], B0_terms[i]); /* compute first B */ fmpz_add(qs_inf->B, qs_inf->B, B_terms[i]); } /* calculate A_inv[k] = A^-1 modulo p_k for p_k in the factor base */ for (k = 3; k < qs_inf->num_primes; k++) { p = factor_base[k].p; temp = fmpz_fdiv_ui(qs_inf->A, p); A_inv[k] = temp == 0 ? 0 : n_invmod(temp, p); } /* calculate A_inv2B[i][k] = 2 * B_terms[i] * A^-1 modulo p_k for factor base primes p_k, will be multiplied by A_inv[k] below */ for (k = 3; k < qs_inf->num_primes; k++) { p = factor_base[k].p; pinv = factor_base[k].pinv; for (i = 0; i < s; i++) { temp = fmpz_fdiv_ui(B_terms[i], p); temp *= 2; if (temp >= p) temp -= p; A_inv2B[i][k] = n_mulmod2_preinv(temp, A_inv[k], p, pinv); } } /* compute roots of first polynomial modulo factor base primes */ for (k = 3; k < qs_inf->num_primes; k++) { p = factor_base[k].p; pinv = factor_base[k].pinv; /* compute first root of poly */ temp = fmpz_fdiv_ui(qs_inf->B, p); temp = sqrts[k] + p - temp; temp = n_mulmod2_preinv(temp, A_inv[k], p, pinv); temp += qs_inf->sieve_size / 2; temp = n_mod2_preinv(temp, p, pinv); /* compute second root of poly */ temp2 = n_mulmod2_preinv(sqrts[k], A_inv[k], p, pinv); temp2 *= 2; if (temp2 >= p) temp2 -= p; temp2 = temp + p - temp2; if (temp2 >= p) temp2 -= p; if (temp2 > temp) { soln1[k] = temp; soln2[k] = temp2; } else { soln1[k] = temp2; soln2[k] = temp; } } /* zero out roots corresponding to factors of A */ for (i = 0; i < s; i++) { soln1[A_ind[i]] = soln2[A_ind[i]] = 0; } } /* Generate (i + 1)-th B coefficient from i-th B coefficient using Gray-code */ void qsieve_init_poly_next(qs_t qs_inf, slong i) { slong j, v; slong s = qs_inf->s; prime_t * factor_base = qs_inf->factor_base; int * soln1 = qs_inf->soln1; int * soln2 = qs_inf->soln2; mp_limb_t ** A_inv2B = qs_inf->A_inv2B; mp_limb_t sign, p, r1, r2; fmpz_t temp; fmpz_init(temp); #if QS_DEBUG qs_inf->poly_count += 1; #endif /* we have B_i, calculating B_{i+1} using Gray code */ for (v = 0; v < s; v++) { if (((i >> v) & 1)) break; } sign = (i >> v) & 2; fmpz_mul_ui(temp, qs_inf->B_terms[v], UWORD(2)); if (sign) fmpz_add(qs_inf->B, qs_inf->B, temp); else fmpz_sub(qs_inf->B, qs_inf->B, temp); /* updating roots of poly for B_{i+1} */ for (j = 3; j < qs_inf->num_primes; j++) { p = factor_base[j].p; if (sign) { r1 = soln1[j] + p - A_inv2B[v][j]; r2 = soln2[j] + p - A_inv2B[v][j]; } else { r1 = soln1[j] + A_inv2B[v][j]; r2 = soln2[j] + A_inv2B[v][j]; } if (r1 >= p) r1 -= p; if (r2 >= p) r2 -= p; if (r1 < r2) { soln1[j] = r1; soln2[j] = r2; } else { soln1[j] = r2; soln2[j] = r1; } } fmpz_clear(temp); } /* Calculate coefficient C for current A and B where C = (B^2 - kn)/A */ void qsieve_compute_C(fmpz_t C, qs_t qs_inf, qs_poly_t poly) { fmpz_t r; fmpz_init(r); fmpz_mul(C, poly->B, poly->B); fmpz_sub(C, C, qs_inf->kn); #if QS_DEBUG fmpz_mod(r, C, qs_inf->A); if (!fmpz_is_zero(r)) { flint_throw(FLINT_ERROR, "B^2 - kn not divisible by A\n"); } #endif fmpz_divexact(C, C, qs_inf->A); fmpz_clear(r); } /* Make a copy of a poly structure. Used by threads so they have their own poly structure to modify. */ void qsieve_poly_copy(qs_poly_t poly, qs_t qs_inf) { slong i; fmpz_set(poly->B, qs_inf->B); for (i = 0; i < qs_inf->num_primes; i++) { poly->soln1[i] = qs_inf->soln1[i]; poly->soln2[i] = qs_inf->soln2[i]; } } flint-3.1.3/src/qsieve/factor.c000066400000000000000000000355231461254215100163500ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016, 2020 William Hart Copyright (C) 2015 Nitin Kumar Copyright (C) 2020 Dan Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define _STDC_FORMAT_MACROS #ifdef __GNUC__ # define strcpy __builtin_strcpy #else # include #endif /* try to get fdopen, mkstemp declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #include #include #include "thread_support.h" #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "qsieve.h" /* Use Windows API for temporary files under MSVC and MinGW */ #if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) #include #endif int compare_facs(const void * a, const void * b) { fmpz * x = (fmpz *) a; fmpz * y = (fmpz *) b; return fmpz_cmp(x, y); } /* Finds at least one nontrivial factor of n using the self initialising multiple polynomial quadratic sieve with single large prime variation. Assumes n is not prime and not a perfect power. */ void qsieve_factor(fmpz_factor_t factors, const fmpz_t n) { qs_t qs_inf; mp_limb_t small_factor, delta; ulong expt = 0; unsigned char * sieve; slong ncols, nrows, i, j = 0, count, num_primes; uint64_t * nullrows = NULL; uint64_t mask; flint_rand_t state; fmpz_t temp, temp2, X, Y; slong num_facs; fmpz * facs; #if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) char temp_path[MAX_PATH]; #else int fd; #endif if (fmpz_sgn(n) < 0) { fmpz_t n2; fmpz_init(n2); fmpz_abs(n2, n); factors->sign *= -1; qsieve_factor(factors, n2); fmpz_clear(n2); return; } /************************************************************************** INITIALISATION: Initialise the qs_t structure. **************************************************************************/ #if QS_DEBUG flint_printf("\nstart\n"); #endif qsieve_init(qs_inf, n); #if QS_DEBUG flint_printf("factoring "); fmpz_print(qs_inf->n); flint_printf(" of %wu bits\n", qs_inf->bits); #endif /************************************************************************** KNUTH SCHROEPPEL: Try to compute a multiplier k such that there are a lot of small primes which are quadratic residues modulo kn. If a small factor of n is found during this process it is returned. **************************************************************************/ #if QS_DEBUG flint_printf("\nKnuth_Schroeppel\n"); #endif small_factor = qsieve_knuth_schroeppel(qs_inf); if (small_factor) { #if QS_DEBUG flint_printf("found small factor %wu in Knuth-Schroeppel\n", small_factor); #endif fmpz_init_set_ui(temp, small_factor); expt += fmpz_remove(temp, qs_inf->n, temp); _fmpz_factor_append_ui(factors, small_factor, expt); qsieve_clear(qs_inf); fmpz_factor_no_trial(factors, temp); fmpz_clear(temp); return; } /* compute kn */ fmpz_mul_ui(qs_inf->kn, qs_inf->n, qs_inf->k); /* refine qs_inf->bits */ qs_inf->bits = fmpz_bits(qs_inf->kn); #if QS_DEBUG flint_printf("kn bits = %wd\n", qs_inf->bits); #endif /************************************************************************** COMPUTE FACTOR BASE: **************************************************************************/ #if QS_DEBUG flint_printf("\nCompute factor-base\n"); #endif /* compute factor base primes and associated data */ small_factor = qsieve_primes_init(qs_inf); if (small_factor) { #if QS_DEBUG flint_printf("found small factor %wu while generating factor base\n", small_factor); #endif fmpz_init_set_ui(temp, small_factor); expt += fmpz_remove(temp, qs_inf->n, temp); _fmpz_factor_append_ui(factors, small_factor, expt); qsieve_clear(qs_inf); fmpz_factor_no_trial(factors, temp); fmpz_clear(temp); return; } fmpz_init(temp); fmpz_init(temp2); fmpz_init(X); fmpz_init(Y); /************************************************************************** INITIALISE RELATION/LINEAR ALGEBRA DATA: Create space for all the relations and matrix information **************************************************************************/ #if QS_DEBUG flint_printf("\nInitializing Relations and Linear Algebra\n"); #endif qsieve_linalg_init(qs_inf); /************************************************************************** POLYNOMIAL INITIALIZATION AND SIEVING: Sieve for relations **************************************************************************/ #if QS_DEBUG flint_printf("\nPolynomial Initialisation and Sieving\n"); #endif qs_inf->num_handles = flint_request_threads(&qs_inf->handles, flint_get_num_threads()); /* ensure cache lines don't overlap if num_handles > 0 */ sieve = flint_malloc((qs_inf->sieve_size + sizeof(ulong) + (qs_inf->num_handles > 0 ? 64 : 0))*(qs_inf->num_handles + 1)); #if FLINT_USES_PTHREAD pthread_mutex_init(&qs_inf->mutex, NULL); #endif #if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) if (GetTempPathA(MAX_PATH, temp_path) == 0) { flint_throw(FLINT_ERROR, "Exception (qsieve_factor). GetTempPathA() failed.\n"); } /* uUnique = 0 means the we *do* want a unique filename (obviously!). */ if (GetTempFileNameA(temp_path, "siq", /*uUnique*/ 0, qs_inf->fname) == 0) { flint_throw(FLINT_ERROR, "Exception (qsieve_factor). GetTempFileNameA() failed.\n"); } qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "wb"); if (qs_inf->siqs == NULL) flint_throw(FLINT_ERROR, "fopen failed\n"); #else strcpy(qs_inf->fname, "/tmp/siqsXXXXXX"); /* must be shorter than fname_alloc_size in init.c */ fd = mkstemp(qs_inf->fname); if (fd == -1) flint_throw(FLINT_ERROR, "mkstemp failed\n"); qs_inf->siqs = (FLINT_FILE *) fdopen(fd, "wb"); if (qs_inf->siqs == NULL) flint_throw(FLINT_ERROR, "fdopen failed\n"); #endif /* * The code here and in large_prime_variant.c opens and closes the file * qs_inf->fname in several different places. On Windows all file handles * need to be closed before the file can be removed in cleanup at function * exit. The invariant that needs to be preserved at each open/close is * that either * qs_inf->siqs is NULL and there are no open handles to the file, * or * qs_inf->siqs is not NULL and is the *only* open handle to the file. */ for (j = qs_inf->small_primes; j < qs_inf->num_primes; j++) { if (qs_inf->factor_base[j].p > BLOCK_SIZE) break; } qs_inf->second_prime = j; #if QS_DEBUG flint_printf("second prime index = %wd\n", qs_inf->second_prime); #endif while (1) { if (qs_inf->s) /* we have already tried factoring, so restart */ qsieve_reinit_A(qs_inf); else { if (!qsieve_init_A(qs_inf)) goto more_primes; /* initialisation failed, increase FB */ } do { qsieve_collect_relations(qs_inf, sieve); qs_inf->num_cycles = qs_inf->edges + qs_inf->components - qs_inf->vertices; #if QS_DEBUG flint_printf("full relations = %wd, num cycles = %wd, ks_primes = %wd, " "extra rels = %wd, poly_count = %wd, num_primes = %wd\n", qs_inf->full_relation, qs_inf->num_cycles, qs_inf->ks_primes, qs_inf->extra_rels, qs_inf->poly_count, qs_inf->num_primes); #endif if (qs_inf->full_relation + qs_inf->num_cycles >= ((slong) (1.10*qs_inf->num_primes) + qs_inf->ks_primes + qs_inf->extra_rels)) { int ok; if (fclose((FILE *) qs_inf->siqs)) flint_throw(FLINT_ERROR, "fclose fail\n"); qs_inf->siqs = NULL; ok = qsieve_process_relation(qs_inf); if (ok == -1) { small_factor = qs_inf->small_factor; #if QS_DEBUG flint_printf("found small factor %wu while incrementing factor base\n, small_factor"); #endif goto found_small_factor; } if (ok) { /************************************************************************** REDUCE MATRIX: Perform some light filtering on the matrix **************************************************************************/ num_primes = qs_inf->num_primes; qs_inf->num_primes += qs_inf->ks_primes; ncols = qs_inf->num_primes + qs_inf->extra_rels; nrows = qs_inf->num_primes; reduce_matrix(qs_inf, &nrows, &ncols, qs_inf->matrix); /************************************************************************** BLOCK LANCZOS: Find extra_rels nullspace vectors (if they exist) **************************************************************************/ #if QS_DEBUG flint_printf("\nBlock Lanczos\n"); #endif flint_randinit(state); /* initialise the random generator */ do /* repeat block lanczos until it succeeds */ { nullrows = block_lanczos(state, nrows, 0, ncols, qs_inf->matrix); } while (nullrows == NULL); for (i = 0, mask = 0; i < ncols; i++) /* create mask of nullspace vectors */ mask |= nullrows[i]; for (i = count = 0; i < 64; i++) /* count nullspace vectors found */ { if (mask & ((uint64_t)(1) << i)) count++; } flint_randclear(state); /* clean up random state */ /************************************************************************** SQUARE ROOT: Compute the square root and take the GCD of X-Y with N **************************************************************************/ #if QS_DEBUG flint_printf("\nSquare Root\n"); flint_printf("Found %ld kernel vectors\n", count); #endif facs = _fmpz_vec_init(100); num_facs = 0; for (i = 0; i < 64; i++) { if (mask & ((uint64_t)(1) << i)) { qsieve_square_root(X, Y, qs_inf, nullrows, ncols, i, qs_inf->kn); fmpz_sub(X, X, Y); fmpz_gcd(X, X, qs_inf->n); if (fmpz_cmp(X, qs_inf->n) != 0 && fmpz_cmp_ui(X, 1) != 0) /* have a factor */ fmpz_set(facs + num_facs++, X); } } flint_free(nullrows); if (num_facs > 0) { _fmpz_factor_append(factors, qs_inf->n, 1); qsort((void *) facs, num_facs, sizeof(fmpz), compare_facs); for (i = 0; i < num_facs; i++) { fmpz_gcd(temp, factors->p + factors->num - 1, facs + i); if (!fmpz_is_one(temp)) { factors->exp[factors->num - 1] = fmpz_remove(temp2, factors->p + factors->num - 1, temp); fmpz_set(factors->p + factors->num - 1, temp); if (fmpz_is_one(temp2)) break; else _fmpz_factor_append(factors, temp2, 1); } } _fmpz_vec_clear(facs, 100); goto cleanup; } _fmpz_vec_clear(facs, 100); qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "wb"); if (qs_inf->siqs == NULL) flint_throw(FLINT_ERROR, "fopen fail\n"); qs_inf->num_primes = num_primes; /* linear algebra adjusts this */ goto more_primes; /* factoring failed, may need more primes */ } } } while (qsieve_next_A(qs_inf)); more_primes: /* ran out of A's in init/sieving of linalg failed, increase FB */ #if QS_DEBUG flint_printf("Increasing factor base.\n"); #endif delta = qs_inf->num_primes / 10; delta = FLINT_MAX(delta, 100); /* add at least 100 more primes */ #if QS_DEBUG flint_printf("\nfactor base increment\n"); #endif qsieve_poly_clear(qs_inf); small_factor = qsieve_primes_increment(qs_inf, delta); for (j = qs_inf->small_primes; j < qs_inf->num_primes; j++) { if (qs_inf->factor_base[j].p > BLOCK_SIZE) break; } qs_inf->second_prime = j; qs_inf->s = 0; /* indicate polynomials need setting up again */ #if QS_DEBUG flint_printf("Now %ld primes\n", qs_inf->num_primes); #endif if (small_factor) { #if QS_DEBUG flint_printf("found small factor %wu while incrementing factor base\n, small_factor"); #endif found_small_factor: fmpz_set_ui(temp, small_factor); expt += fmpz_remove(temp, qs_inf->n, temp); _fmpz_factor_append_ui(factors, small_factor, expt); fmpz_factor_no_trial(factors, temp); goto cleanup; } qsieve_linalg_realloc(qs_inf); } /************************************************************************** CLEANUP: Clean up allocated memory **************************************************************************/ cleanup: #if QS_DEBUG flint_printf("\nCleanup\n"); #endif #if FLINT_USES_PTHREAD pthread_mutex_destroy(&qs_inf->mutex); #endif flint_give_back_threads(qs_inf->handles, qs_inf->num_handles); flint_free(sieve); if (qs_inf->siqs != NULL && fclose((FILE *) qs_inf->siqs)) flint_throw(FLINT_ERROR, "fclose fail\n"); if (remove(qs_inf->fname)) { flint_throw(FLINT_ERROR, "remove fail\n"); } qsieve_clear(qs_inf); qsieve_linalg_clear(qs_inf); qsieve_poly_clear(qs_inf); fmpz_clear(X); fmpz_clear(Y); fmpz_clear(temp); fmpz_clear(temp2); } flint-3.1.3/src/qsieve/init.c000066400000000000000000000032471461254215100160330ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "qsieve.h" #if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) #include #endif void qsieve_init(qs_t qs_inf, const fmpz_t n) { size_t fname_alloc_size; slong i; #if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) fname_alloc_size = MAX_PATH; #else fname_alloc_size = 20; #endif qs_inf->fname = (char *) flint_malloc(fname_alloc_size); /* space for filename */ /* store n in struct */ fmpz_init_set(qs_inf->n, n); /* determine the number of bits of n */ qs_inf->bits = fmpz_bits(n); /* determine which index in the tuning table n corresponds to */ for (i = 1; i < QS_TUNE_SIZE; i++) { if (qsieve_tune[i][0] > qs_inf->bits) break; } i--; qs_inf->ks_primes = qsieve_tune[i][1]; /* number of Knuth-Schroeppel primes */ qs_inf->num_primes = 0; qs_inf->num_relations = 0; qs_inf->full_relation = 0; qs_inf->num_cycles = 0; qs_inf->columns = 0; qs_inf->vertices = 0; qs_inf->components = 0; qs_inf->edges = 0; #if QS_DEBUG qs_inf->poly_count = 0; #endif fmpz_init(qs_inf->kn); /* initialise kn */ qs_inf->factor_base = NULL; qs_inf->sqrts = NULL; qs_inf->s = 0; } flint-3.1.3/src/qsieve/knuth_schroeppel.c000066400000000000000000000076201461254215100204440ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "qsieve.h" #ifdef __GNUC__ # define log __builtin_log #else # include #endif /* Array of possible Knuth-Schroeppel multipliers */ static const mp_limb_t multipliers[] = {1, 2, 3, 5, 6, 7, 10, 11, 13, 14, 15, 17, 19, 21, 22, 23, 26, 29, 30, 31, 33, 34, 35, 37, 38, 41, 42, 43, 47}; /* Number of possible Knuth-Schroeppel multipliers */ #define KS_MULTIPLIERS (sizeof(multipliers)/sizeof(mp_limb_t)) /* Try to compute a multiplier k such that there are a lot of small primes which are quadratic residues modulo kn. If a small weight of n is found during this process it is returned. */ mp_limb_t qsieve_knuth_schroeppel(qs_t qs_inf) { float weights[KS_MULTIPLIERS]; /* array of Knuth-Schroeppel weights */ float best_weight = -10.0f; /* best weight so far */ ulong i, num_primes, max; float logpdivp; mp_limb_t nmod8, mod8, p, nmod, pinv, mult; int kron, jac; n_primes_t iter; if (fmpz_is_even(qs_inf->n)) /* check 2 is not a factor */ return 2; /* initialise weights for each multiplier k depending on kn mod 8 */ nmod8 = fmpz_fdiv_ui(qs_inf->n, 8); /* n modulo 8 */ for (i = 0; i < KS_MULTIPLIERS; i++) { mod8 = ((nmod8*multipliers[i]) % 8); /* kn modulo 8 */ weights[i] = 0.34657359; /* ln2/2 */ if (mod8 == 1) weights[i] *= 4.0; if (mod8 == 5) weights[i] *= 2.0; weights[i] -= (log((float) multipliers[i]) / 2.0); } /* maximum number of primes to try may not exceed number of factor base primes (recall k and 2 and -1 are factor base primes) */ max = FLINT_MIN(qs_inf->ks_primes, qs_inf->num_primes - 3); n_primes_init(iter); n_primes_next(iter); p = n_primes_next(iter); for (num_primes = 0; num_primes < max; num_primes++) { pinv = n_preinvert_limb(p); /* compute precomputed inverse */ logpdivp = log((float) p) / (float) p; /* log p / p */ nmod = fmpz_fdiv_ui(qs_inf->n, p); if (nmod == 0) return p; /* we found a small factor */ kron = 1; /* n mod p is even, not handled by n_jacobi */ while (nmod % 2 == 0) { if (p % 8 == 3 || p % 8 == 5) kron *= -1; nmod /= 2; } kron *= n_jacobi(nmod, p); for (i = 0; i < KS_MULTIPLIERS; i++) { mult = multipliers[i]; if (mult >= p) mult = n_mod2_preinv(mult, p, pinv); /* k mod p */ if (mult == 0) weights[i] += logpdivp; /* kn == 0 mod p */ else { jac = 1; while (mult % 2 == 0) /* k mod p is even, not handled by n_jacobi */ { if (p % 8 == 3 || p % 8 == 5) jac *= -1; mult /= 2; } if (kron*jac*n_jacobi(mult, p) == 1) /* kn is a square mod p */ weights[i] += 2.0*logpdivp; } } p = n_primes_next(iter); } n_primes_clear(iter); /* search for the multiplier with the best weight and set qs_inf->k */ for (i = 0; i < KS_MULTIPLIERS; i++) { if (weights[i] > best_weight) { best_weight = weights[i]; qs_inf->k = multipliers[i]; } } #if QS_DEBUG flint_printf("Using Knuth-Schroeppel multiplier %wd\n", qs_inf->k); #endif return 0; /* we didn't find any small factors */ } flint-3.1.3/src/qsieve/large_prime_variant.c000066400000000000000000000442631461254215100211050ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz.h" #include "qsieve.h" #ifdef __GNUC__ # define memset __builtin_memset #else # include #endif #define HASH_MULT (2654435761U) /* hash function, taken from 'msieve' */ #define HASH(a) ((ulong)((((unsigned int) a) * HASH_MULT) >> (12))) /****************************************************************************** * * Some helper function, used for debugging * *****************************************************************************/ /* Display a relation for debugging purposes */ void qsieve_display_relation(qs_t qs_inf, relation_t a) { slong i; flint_printf("%wu ", a.lp); for (i = 0; i < qs_inf->small_primes; i++) flint_printf("%wd ", a.small[i]); flint_printf("%wd ", a.num_factors); for (i = 0; i < a.num_factors; i++) flint_printf("%wd %wu ", a.factor[i].ind, a.factor[i].exp); fmpz_print(a.Y); flint_printf("\n"); } /* Check a relation is valid (debugging) */ int qsieve_is_relation(qs_t qs_inf, relation_t a) { slong i; fmpz_t temp, temp2; fmpz_init(temp); fmpz_init_set_ui(temp2, 1); for (i = 0; i < qs_inf->small_primes; i++) { fmpz_set_si(temp, qs_inf->factor_base[i].p); fmpz_pow_ui(temp, temp, a.small[i]); fmpz_mul(temp2, temp2, temp); } if (a.num_factors > qs_inf->max_factors) { return 0; } for (i = 0; i < a.num_factors; i++) { fmpz_set_ui(temp, qs_inf->factor_base[a.factor[i].ind].p); fmpz_pow_ui(temp, temp, a.factor[i].exp); fmpz_mul(temp2, temp2, temp); } fmpz_mul_ui(temp2, temp2, a.lp); fmpz_pow_ui(temp, a.Y, UWORD(2)); fmpz_mod(temp, temp, qs_inf->kn); fmpz_mod(temp2, temp2, qs_inf->kn); if (fmpz_cmp(temp, temp2) != 0) { return 0; } fmpz_clear(temp); fmpz_clear(temp2); return 1; } /* Write partial or full relation to file The layout is as follows: total write size of relation (including this write size) large prime (1 * mp_limb_t) number of small primes (1 * slong) small primes (number of small primes * slong) number of factors (1 * slong) (factor, exponent) (number of factors * fac_t) Y->_mp_size (1 * slong) Y->_mp_d (Y->_mp_size * mp_limb_t) */ void qsieve_write_to_file(qs_t qs_inf, mp_limb_t prime, const fmpz_t Y, const qs_poly_t poly) { slong num_factors = poly->num_factors; slong * small = poly->small; fac_t * factor = poly->factor; slong Ysz; slong write_size; /* Get size of Y */ Ysz = COEFF_IS_MPZ(*Y) ? COEFF_TO_PTR(*Y)->_mp_size : FLINT_SGN(*Y); /* Write size of relation */ write_size = sizeof(slong) /* total write size */ + sizeof(mp_limb_t) /* large prime */ + sizeof(slong) /* number of small primes */ + sizeof(slong) * qs_inf->small_primes /* small primes */ + sizeof(slong) /* number of factors */ + sizeof(fac_t) * num_factors /* factors */ + sizeof(slong) /* Y->_mp_size */ + sizeof(mp_limb_t) * (Ysz != 0 ? FLINT_ABS(Ysz) : 1); /* Y->_mp_d */ fwrite(&write_size, sizeof(slong), 1, (FILE *) qs_inf->siqs); /* Write large prime */ fwrite(&prime, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); /* NOTE: We do not have to write small primes. */ /* Write number of small primes */ fwrite(&qs_inf->small_primes, sizeof(slong), 1, (FILE *) qs_inf->siqs); /* Write small primes */ fwrite(small, sizeof(slong), qs_inf->small_primes, (FILE *) qs_inf->siqs); /* Write number of factors */ fwrite(&num_factors, sizeof(slong), 1, (FILE *) qs_inf->siqs); /* Write factors and exponents */ fwrite(factor, sizeof(fac_t), num_factors, (FILE *) qs_inf->siqs); /* Write Y->_mp_size (or mock it) */ fwrite(&Ysz, sizeof(slong), 1, (FILE *) qs_inf->siqs); /* Write Y->_mp_d (or mock it) */ if (!COEFF_IS_MPZ(*Y)) { slong abslimb = FLINT_ABS(*Y); /* Write mock Y->_mp_d */ fwrite(&abslimb, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); } else { mp_srcptr Yd = COEFF_TO_PTR(*Y)->_mp_d; /* Write Y->_mp_d */ fwrite(Yd, sizeof(mp_limb_t), FLINT_ABS(Ysz), (FILE *) qs_inf->siqs); } } /****************************************************************************** * * Hash table * *****************************************************************************/ /* Hash table used to keep count of large primes, idea is taken from msieve Each new prime is filled at last unoccupied position in array and primes which have same hash value are linked with each other keeping offset */ /* return a pointer to location of 'prime' in table if it exists else create an entry for it and return pointer to that */ hash_t * qsieve_get_table_entry(qs_t qs_inf, mp_limb_t prime) { mp_limb_t offset, first_offset; hash_t * entry; mp_limb_t * hash_table = qs_inf->hash_table; hash_t * table = qs_inf->table; slong table_size = qs_inf->table_size; /* reallocate table if not large enough */ if (3*qs_inf->vertices/2 + 1 >= table_size) { table_size *= 1.4; table = flint_realloc(table, table_size*sizeof(hash_t)); qs_inf->table_size = table_size; qs_inf->table = table; } /* find first offset with that hash */ first_offset = HASH(prime); offset = hash_table[first_offset]; /* check linked offsets to see if prime is there, return if so */ while (offset != 0) { entry = table + offset; if (entry->prime == prime) break; offset = entry->next; } /* if we didn't find it, make a new entry in hash table and return it */ if (offset == 0) { qs_inf->vertices++; entry = table + qs_inf->vertices; entry->prime = prime; entry->next = hash_table[first_offset]; entry->count = 0; hash_table[first_offset] = qs_inf->vertices; } return entry; } /* add prime to hashtable, increase size of table if necessary and increment count for the added prime */ void qsieve_add_to_hashtable(qs_t qs_inf, mp_limb_t prime) { hash_t * entry; entry = qsieve_get_table_entry(qs_inf, prime); entry->count++; } /****************************************************************************** * * Large prime functionality * *****************************************************************************/ /* given a string representing a relation, parse it to obtain relation */ relation_t qsieve_parse_relation(qs_t qs_inf) { relation_t rel; slong Ysz; /* NOTE: write_size and large prime is already read in * qsieve_process_relation. */ /* Get large prime (is always one) */ rel.lp = UWORD(1); /* NOTE: We can use qs_inf->small_primes here instead of reading. */ /* Get number of small primes */ fread(&rel.small_primes, sizeof(slong), 1, (FILE *) qs_inf->siqs); /* Get small primes */ rel.small = flint_malloc(rel.small_primes * sizeof(slong)); fread(rel.small, sizeof(slong), rel.small_primes, (FILE *) qs_inf->siqs); /* Get number of factors */ fread(&rel.num_factors, sizeof(slong), 1, (FILE *) qs_inf->siqs); /* Get factors */ rel.factor = flint_malloc(rel.num_factors * sizeof(fac_t)); fread(rel.factor, sizeof(fac_t), rel.num_factors, (FILE *) qs_inf->siqs); /* Get Ysz */ Ysz = 0; fread(&Ysz, sizeof(slong), 1, (FILE *) qs_inf->siqs); /* Get Y */ fmpz_init(rel.Y); if (FLINT_ABS(Ysz) <= 1) { mp_limb_t abslimb = 0; fread(&abslimb, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); #if COEFF_MAX != -COEFF_MIN # error #endif fmpz_set_ui(rel.Y, abslimb); if (Ysz < 0) fmpz_neg(rel.Y, rel.Y); } else { mpz_ptr mY = _fmpz_new_mpz(); mY->_mp_size = Ysz; if (mY->_mp_alloc < FLINT_ABS(Ysz)) _mpz_realloc(mY, FLINT_ABS(Ysz)); fread(mY->_mp_d, sizeof(mp_limb_t), FLINT_ABS(Ysz), (FILE *) qs_inf->siqs); *rel.Y = PTR_TO_COEFF(mY); } return rel; } /* given two partials with same large prime, merge them to obtain a full relation */ relation_t qsieve_merge_relation(qs_t qs_inf, relation_t a, relation_t b) { slong i = 0, j = 0, k = 0; relation_t c; fmpz_t temp; c.lp = UWORD(1); c.small = flint_malloc(qs_inf->small_primes * sizeof(slong)); c.factor = flint_malloc(qs_inf->max_factors * sizeof(fac_t)); fmpz_init(c.Y); for (i = 0; i < qs_inf->small_primes; i++) c.small[i] = (a.small[i] + b.small[i]); i = 0; while (i < a.num_factors && j < b.num_factors) { if (a.factor[i].ind == b.factor[j].ind) { c.factor[k].ind = a.factor[i].ind; c.factor[k++].exp = a.factor[i++].exp + b.factor[j++].exp; } else if (a.factor[i].ind < b.factor[j].ind) { c.factor[k].ind = a.factor[i].ind; c.factor[k++].exp = a.factor[i++].exp; } else { c.factor[k].ind = b.factor[j].ind; c.factor[k++].exp = b.factor[j++].exp; } if (k >= qs_inf->max_factors) { flint_throw(FLINT_ERROR, "more than max_factor !!\n"); } } while (i < a.num_factors) { c.factor[k].ind = a.factor[i].ind; c.factor[k++].exp = a.factor[i++].exp; if (k >= qs_inf->max_factors) { flint_throw(FLINT_ERROR, "more than max_factor !!\n"); } } while (j < b.num_factors) { c.factor[k].ind = b.factor[j].ind; c.factor[k++].exp = b.factor[j++].exp; if (k >= qs_inf->max_factors) { flint_throw(FLINT_ERROR, "more than max_factor !!\n"); } } c.num_factors = k; c.small_primes = qs_inf->small_primes; fmpz_init_set_ui(temp, a.lp); if (fmpz_invmod(temp, temp, qs_inf->kn) == 0) { flint_throw(FLINT_ERROR, "Inverse doesn't exist !!\n"); } fmpz_mul(c.Y, a.Y, b.Y); fmpz_mul(c.Y, c.Y, temp); if (fmpz_cmp(qs_inf->kn, c.Y) <= 0) fmpz_mod(c.Y, c.Y, qs_inf->kn); fmpz_clear(temp); return c; } /* compare two relations in the following order, large_prime, number of factors, factor, small_prime */ int qsieve_compare_relation(const void * a, const void * b) { slong i; relation_t * r1 = (relation_t *) a; relation_t * r2 = (relation_t *) b; if (r1->lp > r2->lp) return 1; if (r1->lp < r2->lp) return -1; if (r1->num_factors > r2->num_factors) return 1; if (r1->num_factors < r2->num_factors) return -1; for (i = 0; i < r1->num_factors; i++) { if (r1->factor[i].ind > r2->factor[i].ind) return 1; if (r1->factor[i].ind < r2->factor[i].ind) return -1; if (r1->factor[i].exp > r2->factor[i].exp) return 1; if (r1->factor[i].exp < r2->factor[i].exp) return -1; } for (i = 0; i < r1->small_primes; i++) { if (r1->small[i] > r2->small[i]) return 1; if (r1->small[i] < r2->small[i]) return -1; } return 0; } /* given a list of relations, remove duplicate relations from it */ int qsieve_remove_duplicates(relation_t * rel_list, slong num_relations) { slong i, j; if (num_relations < 2) return 1; qsort(rel_list, (size_t) num_relations, sizeof(relation_t), qsieve_compare_relation); for (i = 1, j = 0; i < num_relations; i++) { if (qsieve_compare_relation(rel_list + j, rel_list + i) == 0) { rel_list[i].num_factors = 0; flint_free(rel_list[i].small); flint_free(rel_list[i].factor); fmpz_clear(rel_list[i].Y); } else { rel_list[++j] = rel_list[i]; } } j++; #if QS_DEBUG flint_printf("%wd duplicates out of %wd\n", num_relations - j, num_relations); #endif return j; } /* give a list of relations, add those relations to matrix */ void qsieve_insert_relation(qs_t qs_inf, relation_t * rel_list, slong num_relations) { slong i, j, num_factors, fac_num; slong * small; slong * curr_rel; fac_t * factor; la_col_t * matrix = qs_inf->matrix; qs_inf->num_relations = 0; for (j = 0; j < num_relations; j++) { small = rel_list[j].small; num_factors = rel_list[j].num_factors; factor = rel_list[j].factor; curr_rel = qs_inf->curr_rel; fac_num = 0; clear_col(matrix + j); for (i = 0; i < qs_inf->small_primes; i++) { if (small[i] & 1) insert_col_entry(matrix + j, i); if (small[i]) { curr_rel[2*fac_num + 1] = i; curr_rel[2*fac_num + 2] = small[i]; fac_num++; } } for (i = 0; i < num_factors; i++) { if (factor[i].exp & 1) insert_col_entry(matrix + j, factor[i].ind); curr_rel[2*fac_num + 1] = factor[i].ind; curr_rel[2*fac_num + 2] = factor[i].exp; fac_num++; } curr_rel[0] = fac_num; matrix[j].orig = qs_inf->num_relations; fmpz_set(qs_inf->Y_arr + qs_inf->num_relations, rel_list[j].Y); qs_inf->curr_rel += qs_inf->max_factors*2; qs_inf->num_relations++; } qs_inf->columns = qs_inf->num_relations; } /* process relations from the file */ int qsieve_process_relation(qs_t qs_inf) { slong i, num_relations = 0, num_relations2; slong rel_list_length; slong rlist_length; mp_limb_t prime; hash_t * entry; mp_limb_t * hash_table = qs_inf->hash_table; slong rel_size = 50000; relation_t * rel_list = (relation_t *) flint_malloc(rel_size * sizeof(relation_t)); relation_t * rlist; int done = 0; if (qs_inf->siqs != NULL && fclose((FILE *) qs_inf->siqs)) flint_throw(FLINT_ERROR, "fclose fail\n"); qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "rb"); if (qs_inf->siqs == NULL) flint_throw(FLINT_ERROR, "fopen fail\n"); #if QS_DEBUG & 64 flint_printf("Getting relations\n"); #endif while (1) { int siqs_eof; slong write_size = 0; siqs_eof = !fread(&write_size, sizeof(slong), 1, (FILE *) qs_inf->siqs); if (siqs_eof) break; fread(&prime, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); entry = qsieve_get_table_entry(qs_inf, prime); if (num_relations == rel_size) { rel_list = (relation_t *) flint_realloc(rel_list, 2 * rel_size * sizeof(relation_t)); rel_size *= 2; } if (prime == 1 || entry->count >= 2) { rel_list[num_relations] = qsieve_parse_relation(qs_inf); rel_list[num_relations].lp = prime; num_relations++; } else { /* We have to get to the next relation in the file. We have already * read write_size (is a slong) and large prime (is an mp_limb_t).*/ fseek((FILE *) qs_inf->siqs, write_size - sizeof(slong) - sizeof(mp_limb_t), SEEK_CUR); } } if(fclose((FILE *) qs_inf->siqs)) flint_throw(FLINT_ERROR, "fclose fail\n"); qs_inf->siqs = NULL; #if QS_DEBUG & 64 flint_printf("Removing duplicates\n"); #endif num_relations = qsieve_remove_duplicates(rel_list, num_relations); rel_list_length = num_relations; #if QS_DEBUG & 64 flint_printf("Merging relations\n"); #endif rlist = flint_malloc(num_relations * sizeof(relation_t)); memset(hash_table, 0, (1 << 20) * sizeof(mp_limb_t)); qs_inf->vertices = 0; rlist_length = 0; for (i = 0; i < num_relations; i++) { if (rel_list[i].lp == UWORD(1)) { rlist[rlist_length++] = rel_list[i]; } else { entry = qsieve_get_table_entry(qs_inf, rel_list[i].lp); if (entry->count == 0) entry->count = i; else { if (fmpz_fdiv_ui(qs_inf->kn, rel_list[i].lp) == 0) { qs_inf->small_factor = rel_list[i].lp; done = -1; goto cleanup; } rlist[rlist_length++] = qsieve_merge_relation(qs_inf, rel_list[i], rel_list[entry->count]); } } } num_relations = rlist_length; #if QS_DEBUG & 64 flint_printf("Sorting relations\n"); #endif if (rlist_length < qs_inf->num_primes + qs_inf->ks_primes + qs_inf->extra_rels) { qs_inf->edges -= 100; done = 0; if (qs_inf->siqs != NULL && fclose((FILE *) qs_inf->siqs)) flint_throw(FLINT_ERROR, "fclose fail\n"); qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "ab"); if (qs_inf->siqs == NULL) flint_throw(FLINT_ERROR, "fopen fail\n"); } else { done = 1; num_relations2 = qs_inf->num_primes + qs_inf->ks_primes + qs_inf->extra_rels; qsort(rlist, (size_t) num_relations2, sizeof(relation_t), qsieve_compare_relation); qsieve_insert_relation(qs_inf, rlist, num_relations2); } cleanup: for (i = 0; i < rel_list_length; i++) { /* it looks like rlist stole our data if rel_list[i].lp == UWORD(1)) */ if (rel_list[i].lp != UWORD(1)) { flint_free(rel_list[i].small); flint_free(rel_list[i].factor); fmpz_clear(rel_list[i].Y); } } flint_free(rel_list); for (i = 0; i < rlist_length; i++) { flint_free(rlist[i].small); flint_free(rlist[i].factor); fmpz_clear(rlist[i].Y); } flint_free(rlist); return done; } flint-3.1.3/src/qsieve/linalg.c000066400000000000000000000105541461254215100163350ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifdef __GNUC__ # define memset __builtin_memset #else # include #endif #include "fmpz.h" #include "qsieve.h" void qsieve_linalg_init(qs_t qs_inf) { slong i, num_primes; qs_inf->extra_rels = 64; /* number of opportunities to factor n */ qs_inf->max_factors = 60; /* maximum number of factors a (merged) relation can have */ /* allow as many dups as relations */ num_primes = qs_inf->num_primes; qs_inf->num_primes += qs_inf->ks_primes; qs_inf->buffer_size = 2*(qs_inf->num_primes + qs_inf->extra_rels); qs_inf->matrix = flint_malloc((qs_inf->buffer_size)*sizeof(la_col_t)); qs_inf->Y_arr = flint_malloc(qs_inf->buffer_size*sizeof(fmpz)); qs_inf->curr_rel = qs_inf->relation = flint_malloc(2*qs_inf->buffer_size*qs_inf->max_factors*sizeof(slong)); for (i = 0; i < qs_inf->buffer_size; i++) { fmpz_init(qs_inf->Y_arr + i); qs_inf->matrix[i].weight = 0; qs_inf->matrix[i].data = NULL; } qs_inf->prime_count = flint_malloc(qs_inf->num_primes*sizeof(slong)); qs_inf->num_primes = num_primes; qs_inf->columns = 0; qs_inf->num_relations = 0; /* parameter related to partials */ qs_inf->full_relation = 0; qs_inf->edges = 0; qs_inf->vertices = 0; qs_inf->components = 1; qs_inf->num_cycles = 0; qs_inf->table_size = 10000; qs_inf->hash_table = flint_calloc((1 << 20), sizeof(mp_limb_t)); qs_inf->table = flint_malloc(qs_inf->table_size * sizeof(hash_t)); } /* Increase size of linear algebra allocations after factor base increment */ void qsieve_linalg_realloc(qs_t qs_inf) { slong i, num_primes; slong old_buffer_size = qs_inf->buffer_size; num_primes = qs_inf->num_primes; qs_inf->num_primes += qs_inf->ks_primes; qs_inf->buffer_size = 2*(qs_inf->num_primes + qs_inf->extra_rels); qs_inf->matrix = flint_realloc(qs_inf->matrix, qs_inf->buffer_size*sizeof(la_col_t)); qs_inf->Y_arr = flint_realloc(qs_inf->Y_arr, qs_inf->buffer_size*sizeof(fmpz)); qs_inf->curr_rel = qs_inf->relation = flint_realloc(qs_inf->relation, 2*qs_inf->buffer_size*qs_inf->max_factors*sizeof(slong)); qs_inf->prime_count = flint_realloc(qs_inf->prime_count, qs_inf->num_primes*sizeof(slong)); qs_inf->num_primes = num_primes; qs_inf->extra_rels = 64; /* number of opportunities to factor n */ qs_inf->max_factors = 60; /* maximum number of factors a (merged) relation can have */ for (i = 0; i < old_buffer_size; i++) { fmpz_zero(qs_inf->Y_arr + i); if (qs_inf->matrix[i].weight) flint_free(qs_inf->matrix[i].data); qs_inf->matrix[i].weight = 0; qs_inf->matrix[i].data = NULL; } for ( ; i < qs_inf->buffer_size; i++) { fmpz_init(qs_inf->Y_arr + i); qs_inf->matrix[i].weight = 0; qs_inf->matrix[i].data = NULL; } qs_inf->columns = 0; qs_inf->num_relations = 0; /* parameter related to partials */ qs_inf->full_relation = 0; qs_inf->edges = 0; qs_inf->vertices = 0; qs_inf->components = 1; qs_inf->num_cycles = 0; memset(qs_inf->hash_table, 0, (1 << 20)*sizeof(mp_limb_t)); } void qsieve_linalg_clear(qs_t qs_inf) { slong i; flint_free(qs_inf->relation); flint_free(qs_inf->hash_table); flint_free(qs_inf->table); if (qs_inf->matrix != NULL) { for (i = 0; i < qs_inf->buffer_size; i++) { la_col_t * col = qs_inf->matrix + i; if (col->weight) flint_free(col->data); } flint_free(qs_inf->matrix); } if (qs_inf->Y_arr != NULL) { for (i = 0; i < qs_inf->buffer_size; i++) fmpz_clear(qs_inf->Y_arr + i); flint_free(qs_inf->Y_arr); } flint_free(qs_inf->prime_count); qs_inf->relation = NULL; qs_inf->matrix = NULL; qs_inf->Y_arr = NULL; qs_inf->prime_count = NULL; qs_inf->hash_table = NULL; qs_inf->table = NULL; } flint-3.1.3/src/qsieve/poly.c000066400000000000000000000071671461254215100160600ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "qsieve.h" mp_limb_t qsieve_poly_init(qs_t qs_inf) { ulong num_primes = qs_inf->num_primes; ulong s = qs_inf->s; /* number of prime factors in A coeff */ mp_limb_t ** A_inv2B; slong i; fmpz_init(qs_inf->A); fmpz_init(qs_inf->B); fmpz_init(qs_inf->upp_bound); fmpz_init(qs_inf->low_bound); qs_inf->curr_subset = flint_malloc(s * sizeof(mp_limb_t)); qs_inf->first_subset = flint_malloc(s * sizeof(mp_limb_t)); qs_inf->B_terms = flint_malloc(s * sizeof(mp_limb_t)); qs_inf->A_ind = flint_malloc(s * sizeof(mp_limb_t)); qs_inf->A_divp = flint_malloc(s * sizeof(mp_limb_t)); qs_inf->B0_terms = flint_malloc(s * sizeof(mp_limb_t)); qs_inf->A_inv2B = flint_malloc(s * sizeof(mp_limb_t *)); qs_inf->A_inv = flint_malloc(num_primes * sizeof(mp_limb_t)); qs_inf->soln1 = flint_malloc(num_primes * sizeof(mp_limb_t)); qs_inf->soln2 = flint_malloc(num_primes * sizeof(mp_limb_t)); qs_inf->poly = flint_malloc((qs_inf->num_handles + 1)* sizeof(qs_poly_s)); for (i = 0; i <= qs_inf->num_handles ; i++) { fmpz_init(qs_inf->poly[i].B); qs_inf->poly[i].posn1 = flint_malloc((num_primes + 16)*sizeof(mp_limb_t)); qs_inf->poly[i].posn2 = flint_malloc((num_primes + 16)*sizeof(mp_limb_t)); qs_inf->poly[i].soln1 = flint_malloc((num_primes + 16)*sizeof(mp_limb_t)); qs_inf->poly[i].soln2 = flint_malloc((num_primes + 16)*sizeof(mp_limb_t)); qs_inf->poly[i].small = flint_malloc(qs_inf->small_primes*sizeof(mp_limb_t)); qs_inf->poly[i].factor = flint_malloc(qs_inf->max_factors*sizeof(fac_t)); } A_inv2B = qs_inf->A_inv2B; for (i = 0; i < s; i++) A_inv2B[i] = flint_malloc(num_primes * sizeof(mp_limb_t)); for (i = 0; i < s; i++) { fmpz_init(qs_inf->A_divp[i]); fmpz_init(qs_inf->B_terms[i]); } return 0; } void qsieve_poly_clear(qs_t qs_inf) { slong i; fmpz_clear(qs_inf->A); fmpz_clear(qs_inf->B); fmpz_clear(qs_inf->target_A); fmpz_clear(qs_inf->low_bound); fmpz_clear(qs_inf->upp_bound); for (i = 0; i < qs_inf->s; i++) { fmpz_clear(qs_inf->A_divp[i]); fmpz_clear(qs_inf->B_terms[i]); } flint_free(qs_inf->B_terms); flint_free(qs_inf->A_ind); flint_free(qs_inf->A_divp); flint_free(qs_inf->B0_terms); flint_free(qs_inf->A_inv); flint_free(qs_inf->soln1); flint_free(qs_inf->soln2); flint_free(qs_inf->curr_subset); flint_free(qs_inf->first_subset); if (qs_inf->A_inv2B != NULL) { for (i = 0; i < qs_inf->s; i++) { flint_free(qs_inf->A_inv2B[i]); } } flint_free(qs_inf->A_inv2B); for (i = 0; i <= qs_inf->num_handles; i++) { fmpz_clear(qs_inf->poly[i].B); flint_free(qs_inf->poly[i].posn1); flint_free(qs_inf->poly[i].posn2); flint_free(qs_inf->poly[i].soln1); flint_free(qs_inf->poly[i].soln2); flint_free(qs_inf->poly[i].small); flint_free(qs_inf->poly[i].factor); } flint_free(qs_inf->poly); qs_inf->B_terms = NULL; qs_inf->A_ind = NULL; qs_inf->A_divp = NULL; qs_inf->B0_terms = NULL; qs_inf->A_inv = NULL; qs_inf->soln1 = NULL; qs_inf->soln2 = NULL; qs_inf->A_inv2B = NULL; qs_inf->curr_subset = NULL; } flint-3.1.3/src/qsieve/primes_init.c000066400000000000000000000117561461254215100174160ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" #include "qsieve.h" prime_t * compute_factor_base(mp_limb_t * small_factor, qs_t qs_inf, slong num_primes) { mp_limb_t p, nmod, nmod2; mp_limb_t pinv; mp_limb_t k = qs_inf->k; slong num = qs_inf->num_primes; slong fb_prime = 2; prime_t * factor_base = NULL; int * sqrts; int kron; n_primes_t iter; /* (re)allocate space for factor base */ factor_base = (prime_t *) flint_realloc(qs_inf->factor_base, num_primes*sizeof(prime_t)); qs_inf->factor_base = factor_base; /* allocate space for square roots kn mod factor base primes */ sqrts = flint_realloc(qs_inf->sqrts, sizeof(int)*num_primes); qs_inf->sqrts = sqrts; /* compute the last prime in factor base */ p = num == 0 ? 2 : factor_base[num - 1].p; if (num == 0) num = 3; n_primes_init(iter); n_primes_jump_after(iter, p); /* factor base already contains num primes */ for (fb_prime = num; fb_prime < num_primes; ) { p = n_primes_next(iter); pinv = n_preinvert_limb(p); nmod = fmpz_fdiv_ui(qs_inf->n, p); /* n mod p */ if (nmod == 0) { n_primes_clear(iter); *small_factor = p; return factor_base; } nmod2 = n_mulmod2_preinv(nmod, k, p, pinv); /* kn mod p */ if (nmod2 == 0) /* don't sieve with factors of multiplier */ continue; nmod = nmod2; /* save nmod2 */ kron = 1; /* n mod p is even, not handled by n_jacobi */ while (nmod2 % 2 == 0) { if (p % 8 == 3 || p % 8 == 5) kron *= -1; nmod2 /= 2; } kron *= n_jacobi(nmod2, p); if (kron == 1) /* kn is a quadratic residue mod p (and hence a FB prime) */ { factor_base[fb_prime].p = p; factor_base[fb_prime].pinv = pinv; factor_base[fb_prime].size = FLINT_BIT_COUNT(p); sqrts[fb_prime] = n_sqrtmod(nmod, p); fb_prime++; } } n_primes_clear(iter); *small_factor = 0; return factor_base; } mp_limb_t qsieve_primes_init(qs_t qs_inf) { slong num_primes; slong i; mp_limb_t k = qs_inf->k; mp_limb_t small_factor = 0; slong bits; prime_t * factor_base; /* determine which index in the tuning table n corresponds to */ for (i = 1; i < QS_TUNE_SIZE; i++) { if (qsieve_tune[i][0] > qs_inf->bits) break; } i--; num_primes = qsieve_tune[i][2]; /* number of factor base primes */ if (num_primes < 3) { flint_throw(FLINT_ERROR, "Too few factor base primes\n"); } qs_inf->sieve_size = qsieve_tune[i][4]; /* size of sieve to use */ qs_inf->small_primes = qsieve_tune[i][3]; /* number of primes to not sieve with */ bits = qsieve_tune[i][5]; if (bits >= 64) { qs_inf->sieve_bits = bits; qs_inf->sieve_fill = 0; } else { qs_inf->sieve_bits = 64; qs_inf->sieve_fill = 64 - bits; } if (qs_inf->small_primes > num_primes) { flint_throw(FLINT_ERROR, "Too few factor base primes\n"); } /* build up FB */ factor_base = compute_factor_base(&small_factor, qs_inf, num_primes + qs_inf->ks_primes); if (small_factor) return small_factor; qs_inf->num_primes = num_primes; /* calculating optimal A coefficient size for hypercube */ fmpz_init(qs_inf->target_A); fmpz_mul_2exp(qs_inf->target_A, qs_inf->kn, 1); fmpz_sqrt(qs_inf->target_A, qs_inf->target_A); fmpz_tdiv_q_ui(qs_inf->target_A, qs_inf->target_A, qs_inf->sieve_size/2); /* consider k and 2 and -1 as factor base primes */ factor_base[0].p = k; factor_base[0].pinv = n_preinvert_limb(k); factor_base[0].size = FLINT_BIT_COUNT(k); factor_base[1].p = 2; factor_base[1].size = 2; factor_base[2].p = -1; return 0; } /* function to call for incrementing number of factor base prime by 'delta' */ mp_limb_t qsieve_primes_increment(qs_t qs_inf, mp_limb_t delta) { slong num_primes = qs_inf->num_primes + delta; mp_limb_t small_factor = 0; compute_factor_base(&small_factor, qs_inf, num_primes + qs_inf->ks_primes); /* calculating optimal A coefficient size for hypercube */ fmpz_init(qs_inf->target_A); fmpz_mul_2exp(qs_inf->target_A, qs_inf->kn, 1); fmpz_sqrt(qs_inf->target_A, qs_inf->target_A); fmpz_tdiv_q_ui(qs_inf->target_A, qs_inf->target_A, qs_inf->sieve_size/2); qs_inf->num_primes = num_primes; if (small_factor) return small_factor; return 0; } flint-3.1.3/src/qsieve/square_root.c000066400000000000000000000040151461254215100174250ustar00rootroot00000000000000/* Copyright (C) 2006, 2011, 2016 William Hart Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "qsieve.h" #ifdef __GNUC__ # define memset __builtin_memset #else # include #endif void qsieve_square_root(fmpz_t X, fmpz_t Y, qs_t qs_inf, uint64_t * nullrows, slong ncols, slong l, fmpz_t N) { slong position, i, j; slong * relation = qs_inf->relation; prime_t * factor_base = qs_inf->factor_base; slong * prime_count = qs_inf->prime_count; slong num_primes = qs_inf->num_primes; fmpz * Y_arr = qs_inf->Y_arr; fmpz_t pow; fmpz_init(pow); memset(prime_count, 0, num_primes*sizeof(slong)); fmpz_one(X); fmpz_one(Y); for (i = 0; i < ncols; i++) { if (get_null_entry(nullrows, i, l)) { position = qs_inf->matrix[i].orig*2*qs_inf->max_factors; for (j = 0; j < relation[position]; j++) { prime_count[relation[position+2*j+1]] += (relation[position+2*j+2]); } fmpz_mul(Y, Y, Y_arr + qs_inf->matrix[i].orig); if (i % 10 == 0) fmpz_mod(Y, Y, N); } } for (i = 0; i < num_primes; i++) { #if QS_DEBUG if (prime_count[i] & 1) { flint_printf("Not a square in square root, %ld^%ld\n", factor_base[i].p, prime_count[i]); flint_printf("This is prime %ld of %ld factor base primes and %ld ks primes\n", i, qs_inf->num_primes, qs_inf->ks_primes); } #endif if (prime_count[i]) { fmpz_set_si(pow, factor_base[i].p); fmpz_powm_ui(pow, pow, prime_count[i]/2, N); fmpz_mul(X, X, pow); } if (i % 10 == 0 || i == num_primes - 1) fmpz_mod(X, X, N); } fmpz_clear(pow); } flint-3.1.3/src/qsieve/test/000077500000000000000000000000001461254215100156755ustar00rootroot00000000000000flint-3.1.3/src/qsieve/test/main.c000066400000000000000000000014771461254215100167760ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-factor.c" #include "t-primes_init.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(qsieve_factor), TEST_FUNCTION(qsieve_primes_init) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/qsieve/test/t-factor.c000066400000000000000000000074111461254215100175630ustar00rootroot00000000000000/* Copyright (C) 2015 Nitin Kumar Copyright (C) 2016 William Hart Copyright (C) 2020 Dan Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "fmpz.h" #include "fmpz_factor.h" #include "qsieve.h" void randprime(fmpz_t p, flint_rand_t state, slong bits) { fmpz_randbits(p, state, bits); if (fmpz_sgn(p) < 0) fmpz_neg(p, p); if (fmpz_is_even(p)) fmpz_add_ui(p, p, 1); while (!fmpz_is_probabprime(p)) fmpz_add_ui(p, p, 2); } TEST_FUNCTION_START(qsieve_factor, state) { slong i; fmpz_t n, x, y, z; fmpz_factor_t factors; slong max_threads = 5; slong tmul = 3; #ifdef _WIN32 tmul = 1; #endif fmpz_init(x); fmpz_init(y); fmpz_init(z); fmpz_init(n); /* Test n with large prime factor */ { fmpz_set_str(n, "12387192837918273918723981291837121933111751252512531193171", 10); fmpz_factor_init(factors); qsieve_factor(factors, n); if (factors->num < 5) { flint_printf("FAIL:\n"); flint_printf("Test n with large prime factor\n"); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } /* Test random n, two factors */ for (i = 0; i < tmul*flint_test_multiplier(); i++) { slong bits = 40; randprime(x, state, bits); do { randprime(y, state, bits); } while (fmpz_equal(x, y)); fmpz_mul(n, x, y); fmpz_factor_init(factors); flint_set_num_threads(n_randint(state, max_threads) + 1); qsieve_factor(factors, n); if (factors->num < 2) { flint_printf("FAIL:\n"); flint_printf("Test random n, two factors\ni = %wd\n", i); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } /* Test random n, three factors */ for (i = 0; i < tmul*flint_test_multiplier(); i++) { randprime(x, state, 40); do { randprime(y, state, 40); } while (fmpz_equal(x, y)); do { randprime(z, state, 40); } while (fmpz_equal(x, z) || fmpz_equal(y, z)); fmpz_mul(n, x, y); fmpz_mul(n, n, z); fmpz_factor_init(factors); flint_set_num_threads(n_randint(state, max_threads) + 1); qsieve_factor(factors, n); if (factors->num < 3) { flint_printf("FAIL:\n"); flint_printf("Test random n, three factors\ni = %wd\n", i); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } /* Test random n, small factors */ for (i = 0; i < tmul*flint_test_multiplier(); i++) { randprime(x, state, 10); do { randprime(y, state, 10); } while (fmpz_equal(x, y)); randprime(z, state, 40); fmpz_mul(n, x, y); fmpz_mul(n, n, z); fmpz_factor_init(factors); flint_set_num_threads(n_randint(state, max_threads) + 1); qsieve_factor(factors, n); if (factors->num < 3) { flint_printf("FAIL:\n"); flint_printf("Test random n, small factors\ni = %wd\n", i); flint_printf("%ld factors found\n", factors->num); fflush(stdout); flint_abort(); } fmpz_factor_clear(factors); } fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); TEST_FUNCTION_END(state); } flint-3.1.3/src/qsieve/test/t-primes_init.c000066400000000000000000000172041461254215100206300ustar00rootroot00000000000000/* Copyright (C) 2015 Nitin Kumar This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qsieve.h" TEST_FUNCTION_START(qsieve_primes_init, state) { int i; slong j, k; mp_limb_t small_factor, pmod; qs_t qs_inf; fmpz_t n, x, y; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_init(n); fmpz_init(x); fmpz_init(y); fmpz_randtest_unsigned(n, state, 130); if (fmpz_is_zero(n) || fmpz_is_one(n)) goto cleanup2; qsieve_init(qs_inf, n); small_factor = qsieve_knuth_schroeppel(qs_inf); if (small_factor) goto cleanup1; fmpz_mul_ui(qs_inf->kn, qs_inf->n, qs_inf->k); /* haven't calculated earlier */ small_factor = qsieve_primes_init(qs_inf); if (small_factor != 0) { /* check if factor, if returned by factor base function is actually a factor of n */ if (fmpz_fdiv_ui(n, small_factor) != 0) { flint_printf("%wd is not a factor of ", small_factor); fmpz_print(qs_inf->n); flint_printf("\n"); fflush(stdout); flint_abort(); } else goto cleanup1; } for (j = 3; j < qs_inf->num_primes; j++) { /* check if square root of kn modulo factor base prime p are correct */ fmpz_set_si(x, qs_inf->sqrts[j]); fmpz_mul(y, x, x); fmpz_mod_ui(x, y, qs_inf->factor_base[j].p); fmpz_mod_ui(y, qs_inf->kn, qs_inf->factor_base[j].p); if (fmpz_cmp(x, y) != 0) { flint_printf("%d is not a square root of ", qs_inf->sqrts[j]); fmpz_print(qs_inf->kn); flint_printf(" modulo %d\n", qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } /* check if inverse of factor base primes are correct */ fmpz_randtest_unsigned(x, state, FLINT_BITS); fmpz_mod_ui(y, x, qs_inf->factor_base[j].p); pmod = n_mod2_preinv(fmpz_get_ui(x), qs_inf->factor_base[j].p, qs_inf->factor_base[j].pinv); if (fmpz_get_ui(y) != pmod) { flint_printf("%wd is not an inverse of %wd\n", qs_inf->factor_base[j].pinv, qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } } /* add next 50 primes to factor base */ k = qs_inf->num_primes; small_factor = qsieve_primes_increment(qs_inf, 50); if (small_factor != 0) { if (fmpz_fdiv_ui(qs_inf->n, small_factor) != 0) { flint_printf("%wd is not a factor of ", small_factor); fmpz_print(qs_inf->n); flint_printf("\n"); fflush(stdout); flint_abort(); } else goto cleanup1; } for (j = k; j < qs_inf->num_primes; j++) { fmpz_set_si(x, qs_inf->sqrts[j]); fmpz_mul(y, x, x); fmpz_mod_ui(x, y, qs_inf->factor_base[j].p); fmpz_mod_ui(y, qs_inf->kn, qs_inf->factor_base[j].p); if (fmpz_cmp(x, y) != 0) { flint_printf("%d is not a square root of ", qs_inf->sqrts[j]); fmpz_print(qs_inf->kn); flint_printf(" modulo %d\n", qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } fmpz_randtest_unsigned(x, state, FLINT_BITS); fmpz_mod_ui(y, x, qs_inf->factor_base[j].p); pmod = n_mod2_preinv(fmpz_get_ui(x), qs_inf->factor_base[j].p, qs_inf->factor_base[j].pinv); if (fmpz_get_ui(y) != pmod) { flint_printf("%wd is not an inverse of %wd\n", qs_inf->factor_base[j].pinv, qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } } /* add next 30 primes to factor base */ k = qs_inf->num_primes; small_factor = qsieve_primes_increment(qs_inf, 30); if (small_factor != 0) { if (fmpz_fdiv_ui(qs_inf->n, small_factor) != 0) { flint_printf("%wd is not a factor of ", small_factor); fmpz_print(n); flint_printf("\n"); fflush(stdout); flint_abort(); } else goto cleanup1; } for (j = k; j < qs_inf->num_primes; j++) { fmpz_set_si(x, qs_inf->sqrts[j]); fmpz_mul(y, x, x); fmpz_mod_ui(x, y, qs_inf->factor_base[j].p); fmpz_mod_ui(y, qs_inf->kn, qs_inf->factor_base[j].p); if (fmpz_cmp(x, y) != 0) { flint_printf("%d is not a square root of ", qs_inf->sqrts[j]); fmpz_print(qs_inf->kn); flint_printf(" modulo %d\n", qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } fmpz_randtest_unsigned(x, state, FLINT_BITS); fmpz_mod_ui(y, x, qs_inf->factor_base[j].p); pmod = n_mod2_preinv(fmpz_get_ui(x), qs_inf->factor_base[j].p, qs_inf->factor_base[j].pinv); if (fmpz_get_ui(y) != pmod) { flint_printf("%wd is not an inverse of %wd\n", qs_inf->factor_base[j].pinv, qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } } /* add next 10 primes to factor base*/ k = qs_inf->num_primes; small_factor = qsieve_primes_increment(qs_inf, 10); if (small_factor != 0) { if (fmpz_fdiv_ui(qs_inf->n, small_factor) != 0) { flint_printf("%wd is not a factor of ", small_factor); fmpz_print(n); flint_printf("\n"); fflush(stdout); flint_abort(); } else goto cleanup1; } for (j = k; j < qs_inf->num_primes; j++) { fmpz_set_si(x, qs_inf->sqrts[j]); fmpz_mul(y, x, x); fmpz_mod_ui(x, y, qs_inf->factor_base[j].p); fmpz_mod_ui(y, qs_inf->kn, qs_inf->factor_base[j].p); if (fmpz_cmp(x, y) != 0) { flint_printf("%d is not a square root of ", qs_inf->sqrts[j]); fmpz_print(qs_inf->kn); flint_printf(" modulo %d\n", qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } fmpz_randtest_unsigned(x, state, FLINT_BITS); fmpz_mod_ui(y, x, qs_inf->factor_base[j].p); pmod = n_mod2_preinv(fmpz_get_ui(x), qs_inf->factor_base[j].p, qs_inf->factor_base[j].pinv); if (fmpz_get_ui(y) != pmod) { flint_printf("%wd is not an inverse of %wd\n", qs_inf->factor_base[j].pinv, qs_inf->factor_base[j].p); fflush(stdout); flint_abort(); } } cleanup1: qsieve_clear(qs_inf); cleanup2: fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/templates.h000066400000000000000000000026111461254215100155710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef TEMPLATES_H_ #define TEMPLATES_H_ #define CAT(X,Y) X##_##Y #define CAT3(X,Y,Z) X##_##Y##_##Z #define CAT4(X,Y,Z,A) X##_##Y##_##Z##_##A #define CAT5(X,Y,Z,A,B) X##_##Y##_##Z##_##A##_##B #define CAT6(X,Y,Z,A,B,C) X##_##Y##_##Z##_##A##_##B##_##C #define _CAT(X,Y) _##X##_##Y #define _CAT3(X,Y,Z) _##X##_##Y##_##Z #define _CAT4(X,Y,Z,A) _##X##_##Y##_##Z##_##A #define __CAT(X,Y) __##X##_##Y #define __CAT3(X,Y,Z) __##X##_##Y##_##Z #define __CAT4(X,Y,Z,A) __##X##_##Y##_##Z##_##A #define TEMPLATE(X,Y) CAT(X,Y) #define TEMPLATE3(X,Y,Z) CAT3(X,Y,Z) #define TEMPLATE4(X,Y,Z,A) CAT4(X,Y,Z,A) #define TEMPLATE5(X,Y,Z,A,B) CAT5(X,Y,Z,A,B) #define _TEMPLATE(X,Y) _CAT(X,Y) #define _TEMPLATE3(X,Y,Z) _CAT3(X,Y,Z) #define _TEMPLATE4(X,Y,Z,A) _CAT4(X,Y,Z,A) #define __TEMPLATE(X,Y) __CAT(X,Y) #define __TEMPLATE3(X,Y,Z) __CAT3(X,Y,Z) #define __TEMPLATE4(X,Y,Z,A) __CAT4(X,Y,Z,A) #define TEMPLATE_STR(x) #x #define TEMPLATE_PRINT(x) flint_printf("%s", TEMPLATE_STR(x)); #define TEMPLATE_PRINTF(s, x) flint_printf(s, TEMPLATE_STR(x)); #endif flint-3.1.3/src/test/000077500000000000000000000000001461254215100144015ustar00rootroot00000000000000flint-3.1.3/src/test/main.c000066400000000000000000000031341461254215100154720ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-add_ssaaaa.c" #include "t-add_sssaaaaaa.c" #include "t-add_ssssaaaaaaaa.c" #include "t-byte_swap.c" #include "t-flint_clz.c" #include "t-flint_ctz.c" #include "t-io.c" #include "t-memory_manager.c" #include "t-sdiv_qrnnd.c" #include "t-smul_ppmm.c" #include "t-sub_dddmmmsss.c" #include "t-sub_ddmmss.c" #include "t-udiv_qrnnd.c" #include "t-udiv_qrnnd_preinv.c" #include "t-umul_ppmm.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(add_ssaaaa), TEST_FUNCTION(add_sssaaaaaa), TEST_FUNCTION(add_ssssaaaaaaaa), TEST_FUNCTION(byte_swap), TEST_FUNCTION(flint_clz), TEST_FUNCTION(flint_ctz), TEST_FUNCTION(flint_fprintf), TEST_FUNCTION(flint_printf), TEST_FUNCTION(memory_manager), TEST_FUNCTION(sdiv_qrnnd), TEST_FUNCTION(smul_ppmm), TEST_FUNCTION(sub_dddmmmsss), TEST_FUNCTION(sub_ddmmss), TEST_FUNCTION(udiv_qrnnd), TEST_FUNCTION(udiv_qrnnd_preinv), TEST_FUNCTION(umul_ppmm) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/test/t-add_ssaaaa.c000066400000000000000000000025341461254215100170530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(add_ssaaaa, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t sh1, sl1, sh2, sl2, ah1, al1, ah2, al2; ah1 = n_randtest(state); al1 = n_randtest(state); ah2 = n_randtest(state); al2 = n_randtest(state); if (n_randint(state, 10) == 0) add_ssaaaa(sh1, sl1, (slong) ah1, (slong) al1, (slong) ah2, (slong) al2); else add_ssaaaa(sh1, sl1, ah1, al1, ah2, al2); sl2 = al1 + al2; sh2 = (sl1 < al1); sh2 += ah1; sh2 += ah2; result = ((sh2 == sh1) && (sl2 == sl1)); if (!result) TEST_FUNCTION_FAIL( "ah1 = %wu, al1 = %wu, ah2 = %wu, al1 = %wu\n" "sh2 = %wu, sh1 = %wu, sl2 = %wu, sl1 = %wu\n", ah1, al1, ah2, al1, sh2, sh1, sl2, sl1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-add_sssaaaaaa.c000066400000000000000000000027531461254215100175430ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(add_sssaaaaaa, state) { int i, j, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t s[3], t[3], a[3], b[3]; for (j = 0; j < 3; j++) { s[j] = n_randtest(state); t[j] = n_randtest(state); a[j] = n_randtest(state); b[j] = n_randtest(state); } add_sssaaaaaa(s[2], s[1], s[0], a[2], a[1], a[0], b[2], b[1], b[0]); mpn_add_n(t, a, b, 3); result = ((s[2] == t[2]) && (s[1] == t[1]) && (s[0] == t[0])); if (!result) TEST_FUNCTION_FAIL( "a[2] = %wu, a[1] = %wu, a[0] = %wu\n" "b[2] = %wu, b[1] = %wu, b[0] = %wu\n" "s[2] = %wu, s[1] = %wu, s[0] = %wu\n" "t[2] = %wu, t[1] = %wu, t[0] = %wu\n", a[2], a[1], a[0], b[2], b[1], b[0], s[2], s[1], s[0], t[2], t[1], t[0]); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-add_ssssaaaaaaaa.c000066400000000000000000000040311461254215100202170ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(add_ssssaaaaaaaa, state) { int i, j, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t s[4], t[4], a[4], b[4]; int aliasing; for (j = 0; j < 4; j++) { s[j] = n_randtest(state); t[j] = n_randtest(state); a[j] = n_randtest(state); b[j] = n_randtest(state); } aliasing = n_randint(state, 2); if (aliasing) { for (j = 0; j < 4; j++) s[j] = a[j]; add_ssssaaaaaaaa(s[3], s[2], s[1], s[0], s[3], s[2], s[1], s[0], b[3], b[2], b[1], b[0]); } else { add_ssssaaaaaaaa(s[3], s[2], s[1], s[0], a[3], a[2], a[1], a[0], b[3], b[2], b[1], b[0]); } mpn_add_n(t, a, b, 4); result = ((s[3] == t[3]) && (s[2] == t[2]) && (s[1] == t[1]) && (s[0] == t[0])); if (!result) TEST_FUNCTION_FAIL( "Aliasing: %d\n" "a[3] = %wu, a[2] = %wu, a[1] = %wu, a[0] = %wu\n" "b[3] = %wu, b[2] = %wu, b[1] = %wu, b[0] = %wu\n" "s[3] = %wu, s[2] = %wu, s[1] = %wu, s[0] = %wu\n" "t[3] = %wu, t[2] = %wu, t[1] = %wu, t[0] = %wu\n", aliasing, a[3], a[2], a[1], a[0], b[3], b[2], b[1], b[0], s[3], s[2], s[1], s[0], t[3], t[2], t[1], t[0]); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-byte_swap.c000066400000000000000000000026441461254215100170110ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" ulong byte_swap_naive(ulong n) { ulong r = 0; slong i; for (i = 0; i < sizeof(ulong); i++) { r <<= 8; r |= (n & 0xFF); n >>= 8; } return r; } TEST_FUNCTION_START(byte_swap, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong n, r1, r2; int cs; n = n_randtest(state); r1 = n; cs = n_randint(state, 2); if (cs == 0) { /* byte_swap(byte_swap(n)) == n */ r2 = n; byte_swap(r2); byte_swap(r2); } else { /* byte_swap(n) == byte_swap_naive(n) */ r1 = n; byte_swap(r1); r2 = byte_swap_naive(n); } result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "case %d\n" "n = %wx, r1 = %wx, r2 = %wx\n", n, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-flint_clz.c000066400000000000000000000016571461254215100170030ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(flint_clz, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t n; unsigned int count = 0; n = n_randtest(state); if (n != 0) count = flint_clz(n); result = ((n == UWORD(0)) || (((slong)(n << count) < WORD(0)) && (r_shift(n, FLINT_BITS-count) == UWORD(0)))); if (!result) TEST_FUNCTION_FAIL("n = %wu, count = %u\n", n, count); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-flint_ctz.c000066400000000000000000000016251461254215100170060ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(flint_ctz, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t n; unsigned int count = 0; n = n_randtest(state); if (n != 0) count = flint_ctz(n); result = ((n == UWORD(0)) || (((n >> count) & UWORD(1)) && (l_shift(n, FLINT_BITS-count) == UWORD(0)))); if (!result) TEST_FUNCTION_FAIL("n = %wu, count = %u\n", n, count); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-io.c000066400000000000000000001152551461254215100154260ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* intmax_t */ #include #include /* wchar_t and wint_t */ #include "test_helpers.h" #include "nmod.h" #include "fmpz.h" #include "fmpz_mod.h" #include "fmpq.h" #include "mag.h" #include "arf.h" #include "arb.h" #include "acb.h" #include "nmod_vec.h" #include "fmpz_vec.h" #include "fmpq_vec.h" #include "nmod_mat.h" #include "fmpz_mat.h" #include "fmpq_mat.h" #include "arb_mat.h" #include "acb_mat.h" #include "nmod_poly.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "arb_poly.h" #include "acb_poly.h" #define STR(x) TEMPLATE_STR(x) /* Basetypes *****************************************************************/ #define NMOD_MOD 5 #define NMOD_INIT(x) nmod_init(&(x), NMOD_MOD) #define NMOD_CLEAR(x) do { } while (0) #define NMOD_SET(x) do { } while (0) #define NMOD_STRING "mod " STR(NMOD_MOD) #define FMPZ1_ENTRY 1337 #define FMPZ1_INIT(x) fmpz_init(x) #define FMPZ1_CLEAR(x) fmpz_clear(x) #define FMPZ1_SET(x) fmpz_set_si(x, FMPZ1_ENTRY) #define FMPZ1_STRING STR(FMPZ1_ENTRY) #define FMPZ2_ENTRY -187236816283761872638123 #define FMPZ2_INIT(x) fmpz_init(x) #define FMPZ2_CLEAR(x) fmpz_clear(x) #define FMPZ2_SET(x) fmpz_set_str(x, STR(FMPZ2_ENTRY), 10) #define FMPZ2_STRING STR(FMPZ2_ENTRY) #define FMPZ_MOD_CTX_ENTRY 808 #define FMPZ_MOD_CTX_INIT(x) fmpz_mod_ctx_init_ui(x, FMPZ_MOD_CTX_ENTRY) #define FMPZ_MOD_CTX_CLEAR(x) fmpz_mod_ctx_clear(x) #define FMPZ_MOD_CTX_SET(x) do { } while (0) #define FMPZ_MOD_CTX_STRING "mod " STR(FMPZ_MOD_CTX_ENTRY) #define FMPQ1_ENTRY 1337 #define FMPQ1_INIT(x) fmpq_init(x) #define FMPQ1_CLEAR(x) fmpq_clear(x) #define FMPQ1_SET(x) fmpq_set_si(x, FMPQ1_ENTRY, 1) #define FMPQ1_STRING STR(FMPQ1_ENTRY) #define FMPQ2_ENTRY_N -1024 #define FMPQ2_ENTRY_D 3 #define FMPQ2_INIT(x) fmpq_init(x) #define FMPQ2_CLEAR(x) fmpq_clear(x) #define FMPQ2_SET(x) fmpq_set_si(x, FMPQ2_ENTRY_N, FMPQ2_ENTRY_D) #define FMPQ2_STRING STR(FMPQ2_ENTRY_N) " / " STR(FMPQ2_ENTRY_D) #define ARF1_INIT(x) arf_init(x) #define ARF1_CLEAR(x) arf_clear(x) #define ARF1_SET(x) do { } while (0) #define ARF1_STRING "0.00000" #define ARF2_ENTRY 3.00000 #define ARF2_INIT(x) arf_init(x) #define ARF2_CLEAR(x) arf_clear(x) #define ARF2_SET(x) arf_set_d(x, ARF2_ENTRY) #define ARF2_STRING STR(ARF2_ENTRY) #define ARF3_ENTRY 3.14150 #define ARF3_INIT(x) arf_init(x) #define ARF3_CLEAR(x) arf_clear(x) #define ARF3_SET(x) arf_set_d(x, ARF3_ENTRY) #define ARF3_STRING STR(ARF3_ENTRY) #define MAG1_INIT(x) mag_init(x) #define MAG1_CLEAR(x) mag_clear(x) #define MAG1_SET(x) do { } while (0) #define MAG1_STRING "0.00000" #define MAG2_ENTRY 3.00000 #define MAG2_INIT(x) mag_init(x) #define MAG2_CLEAR(x) mag_clear(x) #define MAG2_SET(x) mag_set_d(x, MAG2_ENTRY) #define MAG2_STRING STR(MAG2_ENTRY) #define MAG3_ENTRY 3.14150 #define MAG3_INIT(x) mag_init(x) #define MAG3_CLEAR(x) mag_clear(x) #define MAG3_SET(x) mag_set_d(x, MAG3_ENTRY) #define MAG3_STRING STR(MAG3_ENTRY) #define ARB1_INIT(x) arb_init(x) #define ARB1_CLEAR(x) arb_clear(x) #define ARB1_SET(x) do { } while (0) #define ARB1_STRING "0" #define ARB2_ENTRY 3 #define ARB2_INIT(x) arb_init(x) #define ARB2_CLEAR(x) arb_clear(x) #define ARB2_SET(x) arb_set_si(x, ARB2_ENTRY) #define ARB2_STRING STR(ARB2_ENTRY) #define ARB3_ENTRY "3.1415926535897 +/- 0.0000000000001" #define ARB3_PREC 30 #define ARB3_INIT(x) arb_init(x) #define ARB3_CLEAR(x) arb_clear(x) #define ARB3_SET(x) arb_set_str(x, ARB3_ENTRY, 30) #define ARB3_STRING "[3.14159 +/- 2.66e-6]" #define ACB1_INIT(x) acb_init(x) #define ACB1_CLEAR(x) acb_clear(x) #define ACB1_SET(x) do { } while (0) #define ACB1_STRING "0" #define ACB2_ENTRY 3 #define ACB2_INIT(x) acb_init(x) #define ACB2_CLEAR(x) acb_clear(x) #define ACB2_SET(x) acb_set_si(x, ACB2_ENTRY) #define ACB2_STRING STR(ACB2_ENTRY) #define ACB3_ENTRY 3 #define ACB3_INIT(x) acb_init(x) #define ACB3_CLEAR(x) acb_clear(x) #define ACB3_SET(x) arb_set_si(acb_imagref(x), ACB3_ENTRY) #define ACB3_STRING STR(ACB3_ENTRY) " * i" #define ACB4_ENTRY -3 #define ACB4_INIT(x) acb_init(x) #define ACB4_CLEAR(x) acb_clear(x) #define ACB4_SET(x) arb_set_si(acb_imagref(x), ACB4_ENTRY) #define ACB4_STRING STR(ACB4_ENTRY) " * i" #define ACB5_ENTRY_RE 5 #define ACB5_ENTRY_IM -3 #define ACB5_INIT(x) acb_init(x) #define ACB5_CLEAR(x) acb_clear(x) #define ACB5_SET(x) \ do \ { \ arb_set_si(acb_realref(x), ACB5_ENTRY_RE); \ arb_set_si(acb_imagref(x), ACB5_ENTRY_IM); \ } while (0) #define ACB5_STRING "5 - 3 * i" #define ACB6_ENTRY "3.1415926535897 +/- 0.0000000000001" #define ACB6_PREC 30 #define ACB6_INIT(x) acb_init(x) #define ACB6_CLEAR(x) acb_clear(x) #define ACB6_SET(x) arb_set_str(acb_realref(x), ACB6_ENTRY, ACB6_PREC) #define ACB6_STRING "[3.14159 +/- 2.66e-6]" #define ACB7_ENTRY "-3.1415926535897 +/- 0.0000000000001" #define ACB7_PREC 30 #define ACB7_INIT(x) acb_init(x) #define ACB7_CLEAR(x) acb_clear(x) #define ACB7_SET(x) arb_set_str(acb_imagref(x), ACB7_ENTRY, ACB7_PREC) #define ACB7_STRING "[-3.14159 +/- 2.66e-6] * i" #define ACB8_ENTRY_RE "-1.337 +/- 0.001" #define ACB8_ENTRY_IM "-3.1415926535897 +/- 0.0000000000001" #define ACB8_PREC 30 #define ACB8_INIT(x) acb_init(x) #define ACB8_CLEAR(x) acb_clear(x) #define ACB8_SET(x) \ do \ { \ arb_set_str(acb_realref(x), ACB8_ENTRY_RE, ACB8_PREC); \ arb_set_str(acb_imagref(x), ACB8_ENTRY_IM, ACB8_PREC); \ } while (0) #define ACB8_STRING "[-1.34 +/- 4.01e-3] - [3.14159 +/- 2.66e-6] * i" #define MPZ1_ENTRY 808 #define MPZ1_INIT(x) mpz_init(x) #define MPZ1_CLEAR(x) mpz_clear(x) #define MPZ1_SET(x) mpz_set_si(x, MPZ1_ENTRY) #define MPZ1_STRING STR(MPZ1_ENTRY) #define MPZ2_ENTRY "18927346981726349871629387469182763489761289376419827364" #define MPZ2_INIT(x) mpz_init(x) #define MPZ2_CLEAR(x) mpz_clear(x) #define MPZ2_SET(x) mpz_set_str(x, MPZ2_ENTRY, 10) #define MPZ2_STRING MPZ2_ENTRY #define MPQ1_ENTRY "123 / 2" #define MPQ1_INIT(x) mpq_init(x) #define MPQ1_CLEAR(x) mpq_clear(x) #define MPQ1_SET(x) mpq_set_str(x, MPQ1_ENTRY, 10) #define MPQ1_STRING MPQ1_ENTRY #define MPQ2_ENTRY "26936026936026936026936026936026936026936026936026936026936026936026936026936 / 101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" #define MPQ2_INIT(x) mpq_init(x) #define MPQ2_CLEAR(x) mpq_clear(x) #define MPQ2_SET(x) mpq_set_str(x, MPQ2_ENTRY, 10) #define MPQ2_STRING MPQ2_ENTRY /* Vectors *******************************************************************/ /* NOTE: The lengths has to be put into flint_fprintf as slongs. GCC and MSVC * handles it without specifying them as slongs, but at least Clang messes it * up. */ #define SLONG_VEC_LEN WORD(4) #define SLONG_VEC_INIT(x) do { } while (0) #define SLONG_VEC_CLEAR(x) do { } while (0) #define SLONG_VEC_ENTRIES ((slong[]) {WORD(-1), WORD(0), WORD(1), WORD(2)}) #define SLONG_VEC_SET(x) memcpy((x), SLONG_VEC_ENTRIES, sizeof(slong) * SLONG_VEC_LEN) #define SLONG_VEC_STRING "[-1, 0, 1, 2]" #define NMOD_VEC_LEN WORD(3) #define NMOD_VEC_INIT(x) do { (x) = _nmod_vec_init(NMOD_VEC_LEN); } while (0) #define NMOD_VEC_CLEAR(x) _nmod_vec_clear(x) #define NMOD_VEC_ENTRIES ((ulong[]) {UWORD(1), UWORD(2), UWORD(3)}) #define NMOD_VEC_SET(x) memcpy((x), NMOD_VEC_ENTRIES, sizeof(ulong) * NMOD_VEC_LEN) #define NMOD_VEC_STRING "[1, 2, 3]" #define FMPZ_VEC_LEN WORD(2) #define FMPZ_VEC_INIT(x) do { (x) = _fmpz_vec_init(FMPZ_VEC_LEN); } while (0) #define FMPZ_VEC_CLEAR(x) _fmpz_vec_clear(x, FMPZ_VEC_LEN) #define FMPZ_VEC_ENTRIES ((fmpz[]) {WORD(10), WORD(-2)}) #define FMPZ_VEC_SET(x) memcpy(x, FMPZ_VEC_ENTRIES, sizeof(fmpz) * FMPZ_VEC_LEN) #define FMPZ_VEC_STRING "[10, -2]" /* NOTE: The entries has to be in a canonical form */ #define FMPQ_VEC_LEN WORD(3) #define FMPQ_VEC_INIT(x) do { (x) = _fmpq_vec_init(FMPQ_VEC_LEN); } while (0) #define FMPQ_VEC_CLEAR(x) _fmpq_vec_clear(x, FMPQ_VEC_LEN) #define FMPQ_VEC_ENTRIES ((fmpq[]) {{WORD(10), WORD(3)}, {WORD(-2), WORD(1)}, {WORD(-2000), WORD(7)}}) #define FMPQ_VEC_SET(x) memcpy(x, FMPQ_VEC_ENTRIES, sizeof(fmpq) * FMPQ_VEC_LEN) #define FMPQ_VEC_STRING "[10 / 3, -2, -2000 / 7]" #define ARB_VEC_LEN WORD(2) #define ARB_VEC_INIT(x) do { (x) = _arb_vec_init(ARB_VEC_LEN); } while (0) #define ARB_VEC_CLEAR(x) _arb_vec_clear(x, ARB_VEC_LEN) #define ARB_VEC_PREC 30 #define ARB_VEC_ENTRY(ix) (ix == 0) ? "12.1 +/- 1" : "3" #define ARB_VEC_SET(x) \ do \ { \ slong jx; \ for (jx = 0; jx < ARB_VEC_LEN; jx++) \ arb_set_str((x) + jx, ARB_VEC_ENTRY(jx), ARB_VEC_PREC); \ } while (0) #define ARB_VEC_STRING "[[1e+1 +/- 3.11], 3]" #define ACB_VEC_LEN WORD(1) #define ACB_VEC_INIT(x) do { (x) = _acb_vec_init(ACB_VEC_LEN); } while (0) #define ACB_VEC_CLEAR(x) _acb_vec_clear(x, ACB_VEC_LEN) #define ACB_VEC_PREC 30 #define ACB_VEC_ENTRY_REAL(ix) "12.1 +/- 1" #define ACB_VEC_ENTRY_IMAG(ix) "3" #define ACB_VEC_SET(x) \ do \ { \ slong jx; \ for (jx = 0; jx < ACB_VEC_LEN; jx++) \ { \ arb_set_str(acb_realref((x) + jx), ACB_VEC_ENTRY_REAL(jx), ACB_VEC_PREC); \ arb_set_str(acb_imagref((x) + jx), ACB_VEC_ENTRY_IMAG(jx), ACB_VEC_PREC); \ } \ } while (0) #define ACB_VEC_STRING "[[1e+1 +/- 3.11] + 3 * i]" /* Matrices ******************************************************************/ #define FMPZ_MAT_EMPTY_R 8 #define FMPZ_MAT_EMPTY_C 0 #define FMPZ_MAT_EMPTY_INIT(mat) fmpz_mat_init(mat, FMPZ_MAT_EMPTY_R, FMPZ_MAT_EMPTY_C) #define FMPZ_MAT_EMPTY_CLEAR(mat) fmpz_mat_clear(mat) #define FMPZ_MAT_EMPTY_SET(mat) do { } while (0) #define FMPZ_MAT_EMTPY_STRING STR(FMPZ_MAT_EMPTY_R) " by " STR(FMPZ_MAT_EMPTY_C) " empty matrix" #define NMOD_MAT_R 3 #define NMOD_MAT_C 2 #define NMOD_MAT_MOD 8 #define NMOD_MAT_WINDOW_R1 1 #define NMOD_MAT_WINDOW_R2 3 #define NMOD_MAT_WINDOW_C1 1 #define NMOD_MAT_WINDOW_C2 2 #define NMOD_MAT_WITH_WINDOW_INIT(mat, mat_window) \ do \ { \ nmod_mat_init(mat, NMOD_MAT_R, NMOD_MAT_C, NMOD_MAT_MOD); \ nmod_mat_window_init(mat_window, mat, \ NMOD_MAT_WINDOW_R1, NMOD_MAT_WINDOW_C1, \ NMOD_MAT_WINDOW_R2, NMOD_MAT_WINDOW_C2);\ } while (0) #define NMOD_MAT_WITH_WINDOW_CLEAR(mat, mat_window) \ do \ { \ nmod_mat_clear(mat); \ nmod_mat_window_clear(mat_window); \ } while (0) #define NMOD_MAT_WITH_WINDOW_ENTRIES \ ((ulong[]) {UWORD(0), UWORD(1), UWORD(2), UWORD(3), UWORD(4), UWORD(5)}) #define NMOD_MAT_WITH_WINDOW_SET(mat, mat_window) \ memcpy((mat)->entries, NMOD_MAT_WITH_WINDOW_ENTRIES, sizeof(ulong) * NMOD_MAT_R * NMOD_MAT_C) #define NMOD_MAT_WITH_WINDOW_STRING \ "[[3], [5]]" #define FMPZ_MAT_R 2 #define FMPZ_MAT_C 3 #define FMPZ_MAT_INIT(mat) fmpz_mat_init(mat, FMPZ_MAT_R, FMPZ_MAT_C) #define FMPZ_MAT_CLEAR(mat) fmpz_mat_clear(mat) #define FMPZ_MAT_ENTRIES \ ((fmpz[]) {WORD(0), WORD(1), WORD(2), WORD(3), WORD(4), WORD(5)}) #define FMPZ_MAT_SET(mat) \ memcpy((mat)->entries, FMPZ_MAT_ENTRIES, sizeof(fmpz) * FMPZ_MAT_R * FMPZ_MAT_C) #define FMPZ_MAT_STRING \ "[[0, 1, 2], [3, 4, 5]]" /* Polynomials ***************************************************************/ #define NMOD_POLY_ZERO_MOD 6 #define NMOD_POLY_ZERO_INIT(x) nmod_poly_init(x, NMOD_POLY_ZERO_MOD) #define NMOD_POLY_ZERO_CLEAR(x) nmod_poly_clear(x) #define NMOD_POLY_ZERO_SET(x) do { } while (0) #define NMOD_POLY_ZERO_STRING "0" #define NMOD_POLY_CONSTANT_MOD 1338 #define NMOD_POLY_CONSTANT_COEFF 1337 #define NMOD_POLY_CONSTANT_INIT(x) nmod_poly_init2(x, NMOD_POLY_CONSTANT_MOD, 1) #define NMOD_POLY_CONSTANT_CLEAR(x) nmod_poly_clear(x) #define NMOD_POLY_CONSTANT_SET(x) nmod_poly_set_coeff_ui(x, 0, NMOD_POLY_CONSTANT_COEFF) #define NMOD_POLY_CONSTANT_STRING STR(NMOD_POLY_CONSTANT_COEFF) #define NMOD_POLY_MOD 9 #define NMOD_POLY_LENGTH 4 #define NMOD_POLY_INIT(x) nmod_poly_init2(x, NMOD_POLY_MOD, NMOD_POLY_LENGTH) #define NMOD_POLY_CLEAR(x) nmod_poly_clear(x) #define NMOD_POLY_ENTRIES \ ((ulong[]) {UWORD(3), UWORD(0), UWORD(1), UWORD(3)}) #define NMOD_POLY_SET(x) \ do \ { \ _nmod_poly_set_length(x, NMOD_POLY_LENGTH); \ memcpy((x)->coeffs, NMOD_POLY_ENTRIES, sizeof(ulong) * NMOD_POLY_LENGTH); \ } while (0) #define NMOD_POLY_STRING "3 * x^3 + x^2 + 3" #define FMPZ_POLY_LENGTH 4 #define FMPZ_POLY_INIT(x) fmpz_poly_init2(x, FMPZ_POLY_LENGTH) #define FMPZ_POLY_CLEAR(x) fmpz_poly_clear(x) #define FMPZ_POLY_ENTRIES \ ((fmpz[]) {WORD(0), WORD(-3), WORD(-1), WORD(-1)}) #define FMPZ_POLY_SET(x) \ do \ { \ _fmpz_poly_set_length(x, FMPZ_POLY_LENGTH); \ memcpy((x)->coeffs, FMPZ_POLY_ENTRIES, sizeof(fmpz) * FMPZ_POLY_LENGTH); \ } while (0) #define FMPZ_POLY_STRING "-x^3 - x^2 - 3 * x" #define FMPQ_POLY_ZERO_INIT(x) fmpq_poly_init(x) #define FMPQ_POLY_ZERO_CLEAR(x) fmpq_poly_clear(x) #define FMPQ_POLY_ZERO_SET(x) do { } while (0) #define FMPQ_POLY_ZERO_STRING "0" #define FMPQ_POLY_CONSTANT_COEFF "-1337/10937" #define FMPQ_POLY_CONSTANT_INIT(x) fmpq_poly_init2(x, 1) #define FMPQ_POLY_CONSTANT_CLEAR(x) fmpq_poly_clear(x) #define FMPQ_POLY_CONSTANT_SET(x) fmpq_poly_set_str(x, "1 " FMPQ_POLY_CONSTANT_COEFF) #define FMPQ_POLY_CONSTANT_STRING "-1337 / 10937" #define FMPQ_POLY1_LENGTH 4 #define FMPQ_POLY1_INIT(x) fmpq_poly_init2(x, FMPQ_POLY1_LENGTH) #define FMPQ_POLY1_CLEAR(x) fmpq_poly_clear(x) #define FMPQ_POLY1_SET(x) \ fmpq_poly_set_str(x, STR(FMPQ_POLY1_LENGTH) " " \ "-3/10 -3 0 -1") #define FMPQ_POLY1_STRING "-x^3 - 3 * x - 3 / 10" #define FMPQ_POLY2_LENGTH 4 #define FMPQ_POLY2_INIT(x) fmpq_poly_init2(x, FMPQ_POLY2_LENGTH) #define FMPQ_POLY2_CLEAR(x) fmpq_poly_clear(x) #define FMPQ_POLY2_SET(x) \ fmpq_poly_set_str(x, STR(FMPQ_POLY2_LENGTH) " " \ "0 10/3 -3 8") #define FMPQ_POLY2_STRING "8 * x^3 - 3 * x^2 + 10 / 3 * x" #define ARB_POLY_LENGTH 5 #define ARB_POLY_PREC 30 #define ARB_POLY_INIT(x) arb_poly_init2(x, ARB_POLY_LENGTH) #define ARB_POLY_CLEAR(x) arb_poly_clear(x) #define ARB_POLY_SET(x) \ do \ { \ arb_poly_set_coeff_si(x, ARB_POLY_LENGTH - 1, 1); \ arb_poly_set_coeff_si(x, 3, -1); \ arb_set_str((x)->coeffs + 2, "12.1 +/- 1", ARB_POLY_PREC); \ arb_set_str((x)->coeffs + 1, "-12.1 +/- 1", ARB_POLY_PREC); \ arb_set_str((x)->coeffs + 0, "-12.1 +/- 1", ARB_POLY_PREC); \ } while (0) #define ARB_POLY_STRING "x^4 - x^3 + [1e+1 +/- 3.11] * x^2 - [1e+1 +/- 3.11] * x - [1e+1 +/- 3.11]" #define ACB_POLY_LENGTH 4 #define ACB_POLY_PREC 30 #define ACB_POLY_INIT(x) acb_poly_init2(x, ACB_POLY_LENGTH) #define ACB_POLY_CLEAR(x) acb_poly_clear(x) #define ACB_POLY_SET(x) \ do \ { \ _acb_poly_set_length(x, ACB_POLY_LENGTH); \ arb_set_str(acb_realref((x)->coeffs + ACB_POLY_LENGTH - 1), "-12.1 +/- 1", ACB_POLY_PREC); \ arb_set_si(acb_imagref((x)->coeffs + ACB_POLY_LENGTH - 1), -1); \ acb_poly_set_coeff_si(x, 2, 1); \ acb_poly_set_coeff_si(x, 1, -1); \ acb_poly_set_coeff_si(x, 0, 0); \ } while (0) #define ACB_POLY_STRING "([-1e+1 +/- 3.11] - i) * x^3 + x^2 - x" #define TMP_FILENAME "tmp" TEST_FUNCTION_START(flint_fprintf, state) { FILE * fs; fs = fopen(TMP_FILENAME, "w+"); if (fs == NULL) TEST_FUNCTION_FAIL("Could not open temporary file \"" TMP_FILENAME "\"\n"); { int res1, res2; char * str1, * str2; ulong xulong1 = UWORD(93112), xulong2 = UWORD(8721); slong xslong = WORD(-1982); double xdouble = 0.123456; char xchar = 'p'; short xshort = 1872; int xint = -13214; size_t xsize = 41121; char xcharp[] = "julafton"; wint_t xwint = L'a'; long int xlong = -1872381273; long long int xlonglong = LLONG_MIN; intmax_t xintmax = INTMAX_MAX; ptrdiff_t xptrdiff = 10241; long double xlongdouble = 123.12398128738172381287L; void * xpointer = (void *) 123; wchar_t xwcharp[] = L"a b c"; nmod_t xnmod; fmpz_t xfmpz1, xfmpz2; fmpz_mod_ctx_t xfmpz_mod_ctx; fmpq_t xfmpq1, xfmpq2; arf_t xarf1, xarf2, xarf3; mag_t xmag1, xmag2, xmag3; arb_t xarb1, xarb2, xarb3; acb_t xacb1, xacb2, xacb3, xacb4, xacb5, xacb6, xacb7, xacb8; mpz_t xmpz1, xmpz2; mpq_t xmpq1, xmpq2; slong xslong_vec[SLONG_VEC_LEN]; mp_ptr xnmod_vec; fmpz * xfmpz_vec; fmpq * xfmpq_vec; arb_ptr xarb_vec; acb_ptr xacb_vec; /* Matrix printing relies on vector printing, so no need to check other * types */ fmpz_mat_t empty_matrix; nmod_mat_t xnmod_mat; nmod_mat_t xnmod_mat_window; fmpz_mat_t xfmpz_mat; /* NOTE: We need extra checks with fmpq_poly as it is treated differntly in * __flint_poly_fprint. */ nmod_poly_t xnmod_poly_zero, xnmod_poly_constant, xnmod_poly; fmpz_poly_t xfmpz_poly; fmpq_poly_t xfmpq_poly_zero, xfmpq_poly_constant, xfmpq_poly1, xfmpq_poly2; arb_poly_t xarb_poly; acb_poly_t xacb_poly; /* Initialize ************************************************************/ NMOD_INIT(xnmod); FMPZ1_INIT(xfmpz1); FMPZ2_INIT(xfmpz2); FMPZ_MOD_CTX_INIT(xfmpz_mod_ctx); FMPQ1_INIT(xfmpq1); FMPQ2_INIT(xfmpq2); ARF1_INIT(xarf1); ARF2_INIT(xarf2); ARF3_INIT(xarf3); MAG1_INIT(xmag1); MAG2_INIT(xmag2); MAG3_INIT(xmag3); ARB1_INIT(xarb1); ARB2_INIT(xarb2); ARB3_INIT(xarb3); ACB1_INIT(xacb1); ACB2_INIT(xacb2); ACB3_INIT(xacb3); ACB4_INIT(xacb4); ACB5_INIT(xacb5); ACB6_INIT(xacb6); ACB7_INIT(xacb7); ACB8_INIT(xacb8); MPZ1_INIT(xmpz1); MPZ2_INIT(xmpz2); MPQ1_INIT(xmpq1); MPQ2_INIT(xmpq2); SLONG_VEC_INIT(xslong_vec); NMOD_VEC_INIT(xnmod_vec); FMPZ_VEC_INIT(xfmpz_vec); FMPQ_VEC_INIT(xfmpq_vec); ARB_VEC_INIT(xarb_vec); ACB_VEC_INIT(xacb_vec); NMOD_MAT_WITH_WINDOW_INIT(xnmod_mat, xnmod_mat_window); FMPZ_MAT_INIT(xfmpz_mat); FMPZ_MAT_EMPTY_INIT(empty_matrix); NMOD_POLY_ZERO_INIT(xnmod_poly_zero); NMOD_POLY_CONSTANT_INIT(xnmod_poly_constant); NMOD_POLY_INIT(xnmod_poly); FMPZ_POLY_INIT(xfmpz_poly); FMPQ_POLY_ZERO_INIT(xfmpq_poly_zero); FMPQ_POLY_CONSTANT_INIT(xfmpq_poly_constant); FMPQ_POLY1_INIT(xfmpq_poly1); FMPQ_POLY2_INIT(xfmpq_poly2); ARB_POLY_INIT(xarb_poly); ACB_POLY_INIT(xacb_poly); /* Set *******************************************************************/ NMOD_SET(xnmod); FMPZ1_SET(xfmpz1); FMPZ2_SET(xfmpz2); FMPZ_MOD_CTX_SET(xfmpz_mod_ctx); FMPQ1_SET(xfmpq1); FMPQ2_SET(xfmpq2); ARF1_SET(xarf1); ARF2_SET(xarf2); ARF3_SET(xarf3); MAG1_SET(xmag1); MAG2_SET(xmag2); MAG3_SET(xmag3); ARB1_SET(xarb1); ARB2_SET(xarb2); ARB3_SET(xarb3); ACB1_SET(xacb1); ACB2_SET(xacb2); ACB3_SET(xacb3); ACB4_SET(xacb4); ACB5_SET(xacb5); ACB6_SET(xacb6); ACB7_SET(xacb7); ACB8_SET(xacb8); MPZ1_SET(xmpz1); MPZ2_SET(xmpz2); MPQ1_SET(xmpq1); MPQ2_SET(xmpq2); SLONG_VEC_SET(xslong_vec); NMOD_VEC_SET(xnmod_vec); FMPZ_VEC_SET(xfmpz_vec); FMPQ_VEC_SET(xfmpq_vec); ARB_VEC_SET(xarb_vec); ACB_VEC_SET(xacb_vec); NMOD_MAT_WITH_WINDOW_SET(xnmod_mat, xnmod_mat_window); FMPZ_MAT_SET(xfmpz_mat); FMPZ_MAT_EMPTY_SET(empty_matrix); NMOD_POLY_ZERO_SET(xnmod_poly_zero); NMOD_POLY_CONSTANT_SET(xnmod_poly_constant); NMOD_POLY_SET(xnmod_poly); FMPZ_POLY_SET(xfmpz_poly); FMPQ_POLY_ZERO_SET(xfmpq_poly_zero); FMPQ_POLY_CONSTANT_SET(xfmpq_poly_constant); FMPQ_POLY1_SET(xfmpq_poly1); FMPQ_POLY2_SET(xfmpq_poly2); ARB_POLY_SET(xarb_poly); ACB_POLY_SET(xacb_poly); /* Print *****************************************************************/ #define STR_SIZE 10000 /* 10 kB should suffice. */ str1 = flint_calloc(STR_SIZE, sizeof(char)); str2 = flint_calloc(STR_SIZE, sizeof(char)); #if defined(_LONG_LONG_LIMB) # define ULONG_SLONG_STR \ "Here we print a ulong: %020llu\n" \ "Here we print a slong: %20lld\n" #else # define ULONG_SLONG_STR \ "Here we print a ulong: %020lu\n" \ "Here we print a slong: %20ld\n" #endif res1 = snprintf(str1, STR_SIZE, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut " "enim ad minim veniam, quis nostrud exercitation ullamco laboris " "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor " "in reprehenderit in voluptate velit esse cillum dolore eu fugiat " "nulla pariatur. Excepteur sint occaecat cupidatat non proident, " "sunt in culpa qui officia deserunt mollit anim id est laborum.\n" "\n" "Here are some %% characters: %%, %% and %%%%\n" "\n" "We will now start printing primitive types...\n" "\n" ULONG_SLONG_STR "Here we print a ulong in hexadecimal: " WORD_FMT "x\n" "Here we print a double with flags: %05.2f\n" "Here we print another double: %le\n" "\n" "We will now start printing FLINT types...\n" "\n" "ulong: " WORD_FMT "u\n" "slong: " WORD_FMT "d\n" "nmod: " NMOD_STRING "\n" "small fmpz: " FMPZ1_STRING "\n" "big fmpz: " FMPZ2_STRING "\n" "fmpz_mod_ctx: " FMPZ_MOD_CTX_STRING "\n" "integer fmpq: " FMPQ1_STRING "\n" "fmpq: " FMPQ2_STRING "\n" "zero arf: " ARF1_STRING "\n" "integer arf: " ARF2_STRING "\n" "arf: " ARF3_STRING "\n" "zero mag: " MAG1_STRING "\n" "integer mag: " MAG2_STRING "\n" "mag: " MAG3_STRING "\n" "zero arb: " ARB1_STRING "\n" "integer arb: " ARB2_STRING "\n" "arb: " ARB3_STRING "\n" "zero acb: " ACB1_STRING "\n" "half gaussian acb: " ACB2_STRING "\n" "other half gaussian acb: " ACB3_STRING "\n" "another half gaussian acb: " ACB4_STRING "\n" "gaussian integer acb: " ACB5_STRING "\n" "real acb: " ACB6_STRING "\n" "imaginary acb: " ACB7_STRING "\n" "acb: " ACB8_STRING "\n" "small mpz: " MPZ1_STRING "\n" "big mpz: " MPZ2_STRING "\n" "small mpq: " MPQ1_STRING "\n" "big mpq: " MPQ2_STRING "\n" "\n" "We intersect with some other primitive types...\n" "\n" "char: % 20hhd\n" "short: %-20hx\n" "int: %.*i\n" "size_t: %zo\n" "char *: %.20s\n" "wint_t: %lc\n" "long int: %.*lX\n" "long long int: %3llu\n" "intmax_t: %ji\n" "ptrdiff_t: %tu\n" "long double: %+33.12LG\n" "pointer: %p\n" "wchar_t *: %ls\n" "\n" "And now we go back to printing FLINT types...\n" "\n" "slong_vec: " SLONG_VEC_STRING "\n" "nmod_vec: " NMOD_VEC_STRING "\n" "fmpz_vec: " FMPZ_VEC_STRING "\n" "fmpq_vec: " FMPQ_VEC_STRING "\n" "arb_vec: " ARB_VEC_STRING "\n" "acb_vec: " ACB_VEC_STRING "\n" "\n" "empty fmpz_mat: " FMPZ_MAT_EMTPY_STRING "\n" "window nmod_mat: " NMOD_MAT_WITH_WINDOW_STRING "\n" "fmpz_mat: " FMPZ_MAT_STRING "\n" "\n" "zero nmod_poly: " NMOD_POLY_ZERO_STRING "\n" "constant nmod_poly: " NMOD_POLY_CONSTANT_STRING "\n" "nmod_poly: " NMOD_POLY_STRING "\n" "fmpz_poly: " FMPZ_POLY_STRING "\n" "zero fmpq_poly: " FMPQ_POLY_ZERO_STRING "\n" "constant fmpq_poly: " FMPQ_POLY_CONSTANT_STRING "\n" "fmpq_poly (1): " FMPQ_POLY1_STRING "\n" "fmpq_poly (2): " FMPQ_POLY2_STRING "\n" "arb_poly: " ARB_POLY_STRING "\n" "acb_poly: " ACB_POLY_STRING "\n", xulong1, xslong, xulong2, xdouble, xdouble, xulong1, xslong, xchar, xshort, 10, xint, xsize, xcharp, xwint, 4, xlong, xlonglong, xintmax, xptrdiff, xlongdouble, xpointer, xwcharp); #undef ULONG_SLONG_STR if (res1 == STR_SIZE - 1) TEST_FUNCTION_FAIL( "Could not print expected string into str1.\n"); if (res1 < 0) TEST_FUNCTION_FAIL( "Negative return value from snprintf.\n"); res2 = flint_fprintf(fs, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut " "enim ad minim veniam, quis nostrud exercitation ullamco laboris " "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor " "in reprehenderit in voluptate velit esse cillum dolore eu fugiat " "nulla pariatur. Excepteur sint occaecat cupidatat non proident, " "sunt in culpa qui officia deserunt mollit anim id est laborum.\n" "\n" "Here are some %% characters: %%, %% and %%%%\n" "\n" "We will now start printing primitive types...\n" "\n" "Here we print a ulong: %020wu\n" "Here we print a slong: %20wd\n" "Here we print a ulong in hexadecimal: %wx\n" "Here we print a double with flags: %05.2f\n" "Here we print another double: %le\n" "\n" "We will now start printing FLINT types...\n" "\n" "ulong: %{ulong}\n" "slong: %{slong}\n" "nmod: %{nmod}\n" "small fmpz: %{fmpz}\n" "big fmpz: %{fmpz}\n" "fmpz_mod_ctx: %{fmpz_mod_ctx}\n" "integer fmpq: %{fmpq}\n" "fmpq: %{fmpq}\n" "zero arf: %{arf}\n" "integer arf: %{arf}\n" "arf: %{arf}\n" "zero mag: %{mag}\n" "integer mag: %{mag}\n" "mag: %{mag}\n" "zero arb: %{arb}\n" "integer arb: %{arb}\n" "arb: %{arb}\n" "zero acb: %{acb}\n" "half gaussian acb: %{acb}\n" "other half gaussian acb: %{acb}\n" "another half gaussian acb: %{acb}\n" "gaussian integer acb: %{acb}\n" "real acb: %{acb}\n" "imaginary acb: %{acb}\n" "acb: %{acb}\n" "small mpz: %{mpz}\n" "big mpz: %{mpz}\n" "small mpq: %{mpq}\n" "big mpq: %{mpq}\n" "\n" "We intersect with some other primitive types...\n" "\n" "char: % 20hhd\n" "short: %-20hx\n" "int: %.*i\n" "size_t: %zo\n" "char *: %.20s\n" "wint_t: %lc\n" "long int: %.*lX\n" "long long int: %3llu\n" "intmax_t: %ji\n" "ptrdiff_t: %tu\n" "long double: %+33.12LG\n" "pointer: %p\n" "wchar_t *: %ls\n" "\n" "And now we go back to printing FLINT types...\n" "\n" "slong_vec: %{slong*}\n" "nmod_vec: %{ulong*}\n" "fmpz_vec: %{fmpz*}\n" "fmpq_vec: %{fmpq*}\n" "arb_vec: %{arb*}\n" "acb_vec: %{acb*}\n" "\n" "empty fmpz_mat: %{fmpz_mat}\n" "window nmod_mat: %{nmod_mat}\n" "fmpz_mat: %{fmpz_mat}\n" "\n" "zero nmod_poly: %{nmod_poly}\n" "constant nmod_poly: %{nmod_poly}\n" "nmod_poly: %{nmod_poly}\n" "fmpz_poly: %{fmpz_poly}\n" "zero fmpq_poly: %{fmpq_poly}\n" "constant fmpq_poly: %{fmpq_poly}\n" "fmpq_poly (1): %{fmpq_poly}\n" "fmpq_poly (2): %{fmpq_poly}\n" "arb_poly: %{arb_poly}\n" "acb_poly: %{acb_poly}\n", xulong1, xslong, xulong2, xdouble, xdouble, xulong1, xslong, xnmod, xfmpz1, xfmpz2, xfmpz_mod_ctx, xfmpq1, xfmpq2, xarf1, xarf2, xarf3, xmag1, xmag2, xmag3, xarb1, xarb2, xarb3, xacb1, xacb2, xacb3, xacb4, xacb5, xacb6, xacb7, xacb8, xmpz1, xmpz2, xmpq1, xmpq2, xchar, xshort, 10, xint, xsize, xcharp, xwint, 4, xlong, xlonglong, xintmax, xptrdiff, xlongdouble, xpointer, xwcharp, xslong_vec, SLONG_VEC_LEN, xnmod_vec, NMOD_VEC_LEN, xfmpz_vec, FMPZ_VEC_LEN, xfmpq_vec, FMPQ_VEC_LEN, xarb_vec, ARB_VEC_LEN, xacb_vec, ACB_VEC_LEN, empty_matrix, xnmod_mat_window, xfmpz_mat, xnmod_poly_zero, xnmod_poly_constant, xnmod_poly, xfmpz_poly, xfmpq_poly_zero, xfmpq_poly_constant, xfmpq_poly1, xfmpq_poly2, xarb_poly, xacb_poly); if (res2 > STR_SIZE - 1) TEST_FUNCTION_FAIL( "Printed more than expected into fs.\n"); if (res2 < 0) TEST_FUNCTION_FAIL( "Negative return value from flint_fprintf.\n"); #undef STR_SIZE /* Check *****************************************************************/ fseek(fs, 0, SEEK_SET); if (fread(str2, sizeof(char), res2, fs) != res2) TEST_FUNCTION_FAIL( "Could not read %d bytes from filestream.\n", res2); /* Check strings line by line */ { const char * str1cur, * str2cur; size_t lnsz1, lnsz2; int line; /* Check line by line to make debugging easier */ str1cur = str1; str2cur = str2; line = 0; while (1) { /* NOTE: The newline or null character will occur at strXcur[lnszX] */ lnsz1 = strcspn(str1cur, "\n"); lnsz2 = strcspn(str2cur, "\n"); if (lnsz1 != lnsz2) TEST_FUNCTION_FAIL( "Line size at line %d differs.\n" "Expected: %zu\n" "Got: %zu\n" "\n" "Expected string at line %d:\n" "\n" "%.*s\n" "\n" "Got string at line %d:\n" "\n" "%.*s\n", line, lnsz1, lnsz2, line, lnsz1, str1cur, line, lnsz2, str2cur); if (memcmp(str1cur, str2cur, sizeof(char) * lnsz1)) TEST_FUNCTION_FAIL( "String at line %d differs.\n" "\n" "Expected:\n" "\n" "%.*s\n" "\n" "Got:\n" "\n" "%.*s\n", line, lnsz1, str1cur, lnsz2, str2cur); if (str1cur[lnsz1] == '\0' && str2cur[lnsz2] == '\0') break; else if (str1cur[lnsz1] == '\0' || str2cur[lnsz2] == '\0') TEST_FUNCTION_FAIL( "Reached end of string in str%d at line %d.\n" "\n" "Expected string at line %d:\n" "\n" "%.*s\n" "\n" "Got string at line %d:\n" "\n" "%.*s\n", str1cur[lnsz1] == '\0' ? 1 : 2, line, line, lnsz1, str1cur, line, lnsz2, str2cur); str1cur += lnsz1 + 1; str2cur += lnsz2 + 1; line++; } } /* Check return value */ if (res1 != res2) TEST_FUNCTION_FAIL( "Result from flint_fprintf differed.\n" "Expected: %d\n" "Got: %d\n", res1, res2); /* Clear *****************************************************************/ flint_free(str1); flint_free(str2); NMOD_CLEAR(xnmod); FMPZ1_CLEAR(xfmpz1); FMPZ2_CLEAR(xfmpz2); FMPZ_MOD_CTX_CLEAR(xfmpz_mod_ctx); FMPQ1_CLEAR(xfmpq1); FMPQ2_CLEAR(xfmpq2); ARF1_CLEAR(xarf1); ARF2_CLEAR(xarf2); ARF3_CLEAR(xarf3); MAG1_CLEAR(xmag1); MAG2_CLEAR(xmag2); MAG3_CLEAR(xmag3); ARB1_CLEAR(xarb1); ARB2_CLEAR(xarb2); ARB3_CLEAR(xarb3); ACB1_CLEAR(xacb1); ACB2_CLEAR(xacb2); ACB3_CLEAR(xacb3); ACB4_CLEAR(xacb4); ACB5_CLEAR(xacb5); ACB6_CLEAR(xacb6); ACB7_CLEAR(xacb7); ACB8_CLEAR(xacb8); MPZ1_CLEAR(xmpz1); MPZ2_CLEAR(xmpz2); SLONG_VEC_CLEAR(xslong_vec); NMOD_VEC_CLEAR(xnmod_vec); FMPZ_VEC_CLEAR(xfmpz_vec); FMPQ_VEC_CLEAR(xfmpq_vec); ARB_VEC_CLEAR(xarb_vec); ACB_VEC_CLEAR(xacb_vec); NMOD_MAT_WITH_WINDOW_CLEAR(xnmod_mat, xnmod_mat_window); FMPZ_MAT_CLEAR(xfmpz_mat); FMPZ_MAT_EMPTY_CLEAR(empty_matrix); NMOD_POLY_ZERO_CLEAR(xnmod_poly_zero); NMOD_POLY_CONSTANT_CLEAR(xnmod_poly_constant); NMOD_POLY_CLEAR(xnmod_poly); FMPZ_POLY_CLEAR(xfmpz_poly); FMPQ_POLY_ZERO_CLEAR(xfmpq_poly_zero); FMPQ_POLY_CONSTANT_CLEAR(xfmpq_poly_constant); FMPQ_POLY1_CLEAR(xfmpq_poly1); FMPQ_POLY2_CLEAR(xfmpq_poly2); ARB_POLY_CLEAR(xarb_poly); ACB_POLY_CLEAR(xacb_poly); } fs = freopen(TMP_FILENAME, "w+", fs); if (fs == NULL) TEST_FUNCTION_FAIL("Could not reopen temporary file \"" TMP_FILENAME "\"\n"); if (fclose(fs)) TEST_FUNCTION_FAIL("Could not close temporary file \"" TMP_FILENAME "\"\n"); if (remove(TMP_FILENAME)) TEST_FUNCTION_FAIL("Could not remove temporary file \"" TMP_FILENAME "\"\n"); TEST_FUNCTION_END(state); } #if HAVE_UNISTD_H && FLINT_COVERAGE #include TEST_FUNCTION_START(flint_printf, state) { FILE * fs; ulong xulong = 9812; slong xslong = -123; char str[128]; int res; int original_stdout_fd = dup(fileno(stdout)); fflush(stdout); fs = freopen(TMP_FILENAME, "w", stdout); if (fs == NULL) TEST_FUNCTION_FAIL("Could not redirect stdout to \"" TMP_FILENAME "\"\n"); res = flint_printf( "Tjingeling!\n" "ulong = %wu\n" "slong = %wd\n", xulong, xslong); fputc('\0', stdout); fflush(stdout); if (res < 0) TEST_FUNCTION_FAIL("res = %d\n", res); if (dup2(original_stdout_fd, fileno(stdout)) == -1) TEST_FUNCTION_FAIL("Could not restore stdout\n"); fs = fopen(TMP_FILENAME, "r"); if (fs == NULL) TEST_FUNCTION_FAIL("Could not open \"" TMP_FILENAME "\"\n"); res = fread(str, sizeof(char), res + 1, fs); if (strcmp(str, "Tjingeling!\nulong = 9812\nslong = -123\n")) TEST_FUNCTION_FAIL("Strings not equal.\n"); if (fclose(fs)) TEST_FUNCTION_FAIL("Could not close temporary file \"" TMP_FILENAME "\"\n"); if (remove(TMP_FILENAME)) TEST_FUNCTION_FAIL("Could not remove temporary file \"" TMP_FILENAME "\"\n"); TEST_FUNCTION_END(state); } #else TEST_FUNCTION_START(flint_printf, state) { TEST_FUNCTION_END_SKIPPED(state); } #endif #undef TMP_FILENAME flint-3.1.3/src/test/t-memory_manager.c000066400000000000000000000056711461254215100200210ustar00rootroot00000000000000/* Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "test_helpers.h" #include "flint.h" TEST_FUNCTION_START(memory_manager, state) { int result; size_t alignment; void * (* fmalloc)(size_t); void * (* fcalloc)(size_t, size_t); void * (* frealloc)(void *, size_t); void (* ffree)(void *); void * (* faligned_alloc)(size_t, size_t); void (* faligned_free)(void *); /* Standard FLINT align functions */ for (alignment = sizeof(ulong); alignment < (WORD(1) << 14); alignment <<= 1) { slong ix; for (ix = 0; ix < 10 * flint_test_multiplier(); ix++) { size_t size; void * ptr; /* Allocate at most around 1 MB */ size = alignment * (1 + n_randint(state, 100)); ptr = flint_aligned_alloc(alignment, size); /* Set memory */ memset(ptr, 0, size); flint_aligned_free(ptr); } } /* Use non-aligned backend */ __flint_set_memory_functions(malloc, calloc, realloc, free); __flint_get_memory_functions(&fmalloc, &fcalloc, &frealloc, &ffree); result = (fmalloc == malloc && fcalloc == calloc && frealloc == realloc && ffree == free); if (!result) TEST_FUNCTION_FAIL("Non-standard non-aligned memory functions are different."); for (alignment = sizeof(ulong); alignment < (WORD(1) << 14); alignment <<= 1) { slong ix; for (ix = 0; ix < 10 * flint_test_multiplier(); ix++) { size_t size; void * ptr; /* Allocate at most around 1 MB */ size = alignment * (1 + n_randint(state, 100)); ptr = flint_aligned_alloc(alignment, size); /* Set memory */ memset(ptr, 0, size); flint_aligned_free(ptr); } } #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) # define aligned_alloc _aligned_malloc # define aligned_free _aligned_free #else # define aligned_free free #endif __flint_set_all_memory_functions(malloc, calloc, realloc, free, aligned_alloc, aligned_free); __flint_get_all_memory_functions(&fmalloc, &fcalloc, &frealloc, &ffree, &faligned_alloc, &faligned_free); result = (fmalloc == malloc && fcalloc == calloc && frealloc == realloc && ffree == free && faligned_alloc == aligned_alloc && faligned_free == aligned_free); if (!result) TEST_FUNCTION_FAIL("Non-standard aligned memory functions are different."); TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-sdiv_qrnnd.c000066400000000000000000000041251461254215100171570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(sdiv_qrnnd, state) { slong i; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { int nsgn; mp_limb_signed_t d, nh, nl, q, r, ph, pl; do { d = n_randtest_not_zero(state); nh = n_randtest(state); } while ((nh == WORD_MIN) || (FLINT_ABS(nh) >= FLINT_ABS(d)/2)); nl = n_randtest(state); if (nh < 0) nsgn = -1; else if (nh > 0 || nl != 0) nsgn = +1; else nsgn = 0; sdiv_qrnnd(q, r, nh, nl, d); smul_ppmm(ph, pl, d, q); add_ssaaaa(ph, pl, ph, pl, FLINT_SIGN_EXT(r), r); /* check n = q*d + r */ if (ph != nh || pl != nl) TEST_FUNCTION_FAIL( "Check n = q * d + r failed\n" "nh = %wd, nl = %wd\n" "d = %wd\n" "q = %wd\n" "r = %wd\n" "ph = %wu, pl = %wu\n", nh, nl, d, q, r, ph, pl); /* check rounding of q was towards zero */ if ((nsgn >= 0 && d > 0 && !(0 <= r && r < d)) || (nsgn >= 0 && d < 0 && WORD_MAX + d >= 0 && !(0 <= r && r < -d)) || (nsgn < 0 && d > 0 && WORD_MIN + d <= 0 && !(-d < r && r <= 0)) || (nsgn < 0 && d < 0 && !(d < r && r <= 0))) TEST_FUNCTION_FAIL( "Remainder check failed\n" "nsgn = %d\n" "nh = %wd, nl = %wd\n" "d = %wd\n" "q = %wd\n" "r = %wd\n", nsgn, nh, nl, d, q, r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-smul_ppmm.c000066400000000000000000000034631461254215100170250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(smul_ppmm, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t ph1, pl1, ph2, pl2, pl2old, n1, n2, m1, m2, bit; int j, sign; n1 = n_randtest(state); n2 = n_randtest(state); smul_ppmm(ph1, pl1, n1, n2); m1 = n1; m2 = n2; sign = 1; if ((mp_limb_signed_t) m1 < WORD(0)) { sign = -1; m1 = -m1; } if ((mp_limb_signed_t) m2 < WORD(0)) { sign = -sign; m2 = -m2; } pl2old = UWORD(0); pl2 = UWORD(0); ph2 = UWORD(0); bit = UWORD(1); for (j = 0; j < FLINT_BITS; j++) { if (m2 & bit) { pl2 += (m1 << j); ph2 += (pl2 < pl2old); ph2 += r_shift(m1, FLINT_BITS - j); pl2old = pl2; } bit <<= 1; } if (sign == -1) sub_ddmmss(ph2, pl2, 0, 0, ph2, pl2); result = ((ph2 == ph1) && (pl2 == pl1)); if (!result) TEST_FUNCTION_FAIL( "Inputs: u = %wd, v = %wd\n\n" "Got: r1 = %wd, r0 = %wd\n" "Expected: r1 = %wd, r0 = %wd\n", n1, n2, ph1, pl1, ph2, pl2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-sub_dddmmmsss.c000066400000000000000000000027531461254215100176610ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(sub_dddmmmsss, state) { int i, j, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t s[3], t[3], a[3], b[3]; for (j = 0; j < 3; j++) { s[j] = n_randtest(state); t[j] = n_randtest(state); a[j] = n_randtest(state); b[j] = n_randtest(state); } sub_dddmmmsss(s[2], s[1], s[0], a[2], a[1], a[0], b[2], b[1], b[0]); mpn_sub_n(t, a, b, 3); result = ((s[2] == t[2]) && (s[1] == t[1]) && (s[0] == t[0])); if (!result) TEST_FUNCTION_FAIL( "a[2] = %wu, a[1] = %wu, a[0] = %wu\n" "b[2] = %wu, b[1] = %wu, b[0] = %wu\n" "s[2] = %wu, s[1] = %wu, s[0] = %wu\n" "t[2] = %wu, t[1] = %wu, t[0] = %wu\n", a[2], a[1], a[0], b[2], b[1], b[0], s[2], s[1], s[0], t[2], t[1], t[0]); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-sub_ddmmss.c000066400000000000000000000024251461254215100171510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(sub_ddmmss, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t dh1, dl1, dh2, dl2, mh, ml, sh, sl; mh = n_randtest(state); ml = n_randtest(state); sh = n_randtest(state); sl = n_randtest(state); if (n_randint(state, 10) == 0) sub_ddmmss(dh1, dl1, (slong) mh, (slong) ml, (slong) sh, (slong) sl); else sub_ddmmss(dh1, dl1, mh, ml, sh, sl); dl2 = ml - sl; dh2 = -(sl > ml); dh2 += mh; dh2 -= sh; result = ((dh2 == dh1) && (dl2 == dl1)); if (!result) TEST_FUNCTION_FAIL( "mh = %wu, ml = %wu, sh = %wu, sl = %wu\n" "dh2 = %wu, dh1 = %wu, dl2 = %wu, dl1 = %wu\n", mh, ml, sh, sl, dh2, dh1, dl2, dl1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-udiv_qrnnd.c000066400000000000000000000022041461254215100171550ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(udiv_qrnnd, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t d, nh, nl, q, r, ph, pl; do { d = n_randtest_not_zero(state); nh = n_randtest(state); } while (nh >= d); nl = n_randtest(state); udiv_qrnnd(q, r, nh, nl, d); umul_ppmm(ph, pl, d, q); add_ssaaaa(ph, pl, ph, pl, UWORD(0), r); result = ((ph == nh) && (pl == nl)); if (!result) TEST_FUNCTION_FAIL( "nh = %wu, nl = %wu, d = %wu\n" "ph = %wu, pl = %wu\n", nh, nl, d, ph, pl); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-udiv_qrnnd_preinv.c000066400000000000000000000024201461254215100205400ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(udiv_qrnnd_preinv, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t d, dinv, nh, nl, q1, r1, q2, r2, norm; do { d = n_randtest_not_zero(state); nh = n_randtest(state); norm = flint_clz(d); d <<= norm; } while (nh >= d); nl = n_randtest(state); dinv = n_preinvert_limb_prenorm(d); udiv_qrnnd_preinv(q1, r1, nh, nl, d, dinv); udiv_qrnnd(q2, r2, nh, nl, d); result = ((q1 == q2) && (r1 == r2)); if (!result) TEST_FUNCTION_FAIL( "nh = %wu, nl = %wu, d = %wu, dinv = %wu\n" "q1 = %wu, q2 = %wu, r1 = %wu, r2 = %wu\n", nh, nl, d, dinv, q1, q2, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test/t-umul_ppmm.c000066400000000000000000000026111461254215100170210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "test_helpers.h" TEST_FUNCTION_START(umul_ppmm, state) { int i, j, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t ph1, pl1, ph2, pl2, pl2old, m1, m2, bit; m1 = n_randtest(state); m2 = n_randtest(state); umul_ppmm(ph1, pl1, m1, m2); pl2old = UWORD(0); pl2 = UWORD(0); ph2 = UWORD(0); bit = UWORD(1); for (j = 0; j < FLINT_BITS; j++) { if (m2 & bit) { pl2 += (m1 << j); ph2 += (pl2 < pl2old); ph2 += r_shift(m1, FLINT_BITS - j); pl2old = pl2; } bit <<= 1; } result = ((ph2 == ph1) && (pl2 == pl1)); if (!result) TEST_FUNCTION_FAIL( "m1 = %wu, m2 = %wu\n" "ph2 = %wu, ph1 = %wu, pl2 = %wu, pl1 = %wu\n", m1, m2, ph2, ph1, pl2, pl1); } TEST_FUNCTION_END(state); } flint-3.1.3/src/test_helpers.h000066400000000000000000000343471461254215100163070ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz Copyright (C) 2023, 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef TEST_HELPERS_H #define TEST_HELPERS_H #include #include #include "templates.h" #include "flint.h" #if FLINT_WANT_PRETTY_TESTS # define _RED "\033[0;31m" # define _RED_B "\033[1;31m" # define _GREEN "\033[0;32m" # define _GREEN_B "\033[1;32m" # define _YELLOW "\033[0;33m" # define _YELLOW_B "\033[1;33m" # define _RESET "\033[0m" #else # define _RED # define _RED_B # define _GREEN # define _GREEN_B # define _YELLOW # define _YELLOW_B # define _RESET #endif /* easy way to test a condition in test code */ #define FLINT_TEST(e) \ do { \ if (!(e)) \ { \ flint_throw(FLINT_ERROR, "test %s FAILED\n%s:%d", #e, __FILE__, __LINE__); \ } \ } while (0) /* test function macro *******************************************************/ typedef struct { int (* test_function)(void); char * name; } test_struct; #define TEST_FUNCTION(label) { CAT(test, label), #label } #define TEST_FUNCTION_START(label, state) \ int CAT(test, label)(void) \ { \ double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \ char _test_io_string_[128] = #label " "; \ const int _label_len_ = sizeof(#label) - 1; \ puts(#label "..."); \ FLINT_TEST_INIT(state); \ _start_time_ = clock(); #define TEST_GR_FUNCTION_START(label, state, count_success, count_domain, count_unable) \ int CAT(test, label)(void) \ { \ slong count_success = 0, count_unable = 0, count_domain = 0; \ double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \ char _test_io_string_[128] = #label " "; \ const int _label_len_ = sizeof(#label) - 1; \ puts(#label "..."); \ FLINT_TEST_INIT(state); \ _start_time_ = clock(); #define TEST_TEMPLATE_FUNCTION_START(T, label, state) \ int TEMPLATE3(test, T, label)(void) \ { \ double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \ char _test_io_string_[128] = TEMPLATE_STR(T) "_" #label " "; \ const int _label_len_ = sizeof(TEMPLATE_STR(T) "_" #label) - 1; \ puts(TEMPLATE_STR(T) "_" #label "..."); \ FLINT_TEST_INIT(state); \ _start_time_ = clock(); #define TEST_TEMPLATE2_FUNCTION_START(T, label1, label2, state)\ int TEMPLATE5(test, T, label1, T, label2)(void) \ { \ double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \ char _test_io_string_[128] = TEMPLATE_STR(T) "_" #label1 "_" TEMPLATE_STR(T) "_" #label2 " "; \ const int _label_len_ = sizeof(TEMPLATE_STR(T) "_" #label1 "_" TEMPLATE_STR(T) "_" #label2) - 1; \ puts(TEMPLATE_STR(T) "_" #label1 "_" TEMPLATE_STR(T) "_" #label2 "..."); \ FLINT_TEST_INIT(state); \ _start_time_ = clock(); #define TEST_FUNCTION_END(state) \ _end_time_ = clock(); \ FLINT_TEST_CLEANUP(state); \ if (_label_len_ < 48) \ printf("%.48s%6.2f (" _GREEN_B "PASS" _RESET ")\n", \ _test_io_string_, \ (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \ else \ printf("%.*s\n%54.2f (" _GREEN_B "PASS" _RESET ")\n", \ _label_len_, _test_io_string_, \ (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \ return 0; \ } #define TEST_GR_FUNCTION_END(state, count_success, count_domain, count_unable) \ _end_time_ = clock(); \ FLINT_TEST_CLEANUP(state); \ printf("%.*s\n " \ "%5" _WORD_FMT "d success, " \ "%5" _WORD_FMT "d domain, " \ "%5" _WORD_FMT "d unable" \ "%11.2f " \ "(" _GREEN_B "PASS" _RESET ")\n", \ _label_len_, _test_io_string_, \ count_success, count_domain, count_unable, \ (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \ return 0; \ } #define TEST_FUNCTION_END_SKIPPED(state) \ FLINT_TEST_CLEANUP(state); \ if (_label_len_ < 54) \ printf("%.*s(" _YELLOW_B "SKIPPED" _RESET ")\n", \ 54, _test_io_string_); \ else \ printf("%.*s\n%*s(" _YELLOW_B "SKIPPED" _RESET ")\n", \ _label_len_, _test_io_string_, \ 54, ""); \ return 0; \ } #define TEST_FUNCTION_FAIL(...) \ do \ { \ _end_time_ = clock(); \ if (_label_len_ < 48) \ printf("%.48s%6.2f (" _RED_B "FAIL" _RESET ")\n", \ _test_io_string_, \ (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \ else \ printf("%.*s\n%54.2f (" _RED_B "FAIL" _RESET ")\n", \ _label_len_, _test_io_string_, \ (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \ flint_printf(__VA_ARGS__); \ return 1; \ } while (0) #define TEST_MAIN(tests) \ int \ main(int argc, char ** argv) \ { \ char numthreads_str[] = "--numthreads="; \ char thread_str[] = "--thread="; \ size_t numthreads_str_len = sizeof(numthreads_str) / sizeof(char) - 1; \ size_t thread_str_len = sizeof(thread_str) / sizeof(char) - 1; \ long int numthreads, thread; \ int ix, ix_max, numtests; \ \ numtests = sizeof(tests) / sizeof(test_struct); \ \ /* If no arguments was put in, simply run all tests. */ \ if (argc < 2) \ { \ for (ix = 0; ix < numtests; ix++) \ if ((tests)[ix].test_function()) \ flint_abort(); \ \ return 0; \ } \ \ /* If no options not specified, then run the set of functions specified */\ if (argv[1][0] != '-' && argv[1][1] != '-') \ { \ int jx; \ \ for (jx = 1; jx < argc; jx++) \ { \ for (ix = 0; ix < numtests; ix++) \ { \ /* If argument equals to test name, run it */ \ if (strcmp(argv[jx], (tests)[ix].name) == 0) \ { \ if ((tests)[ix].test_function()) \ flint_abort(); \ break; \ } \ } \ \ if (ix == numtests) \ { \ flint_throw(FLINT_ERROR, "Could not find test function for %s\n", argv[jx]); \ } \ } \ \ return 0; \ } \ \ /* If the length of first argument is less or equal to the the length of\ * "--numthreads=" or that the first argument does not start with \ * "--numthreads=", then exit. */ \ if (strlen(argv[1]) <= numthreads_str_len \ || strncmp(argv[1], numthreads_str, numthreads_str_len) != 0) \ { \ printf("Invalid first option, must be --numthreads=NUM.\n"); \ return 1; \ } \ \ /* Parse the argument. An invalid argument is either returned as LONG_MIN,\ * LONG_MAX or 0. Moreover, we require the argument to be strictly positive.\ * If the argument is invalid or non-positive, exit. */ \ numthreads = strtol(argv[1] + numthreads_str_len, NULL, 10); \ if (numthreads == LONG_MAX || numthreads <= 0) \ { \ printf("Invalid parameter for option --numthreads=NUM.\n"); \ return 1; \ } \ \ /* Same goes here as for the first argument */ \ if (strlen(argv[2]) <= thread_str_len \ || strncmp(argv[2], thread_str, thread_str_len) != 0) \ { \ printf("Invalid second option, must be --thread=NUM.\n"); \ return 1; \ } \ \ /* Same goes here as for the first argument, with the addition that the \ * parameter for this option must be less or equal to the previous argument. */\ thread = strtol(argv[2] + thread_str_len, NULL, 10); \ if (thread == LONG_MAX || thread <= 0 || thread > numthreads) \ { \ printf("Invalid parameter for option --thread=NUM.\n"); \ return 1; \ } \ \ /* We split the tests into `numthreads_par' partitions, and run the \ * `thread_par'-th partition. */ \ ix = (thread - 1) * ((numtests + numthreads - 1) / numthreads); \ ix_max = FLINT_MIN(thread * ((numtests + numthreads - 1) / numthreads), numtests);\ for (; ix < ix_max; ix++) \ if ((tests)[ix].test_function()) \ flint_abort(); \ \ return 0; \ } #endif flint-3.1.3/src/thread_pool.h000066400000000000000000000050741461254215100161010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef THREAD_POOL_H #define THREAD_POOL_H #include "flint.h" #if FLINT_USES_PTHREAD #include #endif #ifdef __cplusplus extern "C" { #endif typedef struct { #if FLINT_USES_PTHREAD pthread_t pth; pthread_mutex_t mutex; pthread_cond_t sleep1; pthread_cond_t sleep2; #endif volatile int idx; volatile int available; volatile int max_workers; void (* fxn)(void *); void * fxnarg; volatile int working; volatile int exit; } thread_pool_entry_struct; typedef thread_pool_entry_struct thread_pool_entry_t[1]; typedef struct { #if FLINT_USES_CPUSET && FLINT_USES_PTHREAD void * original_affinity; #endif #if FLINT_USES_PTHREAD pthread_mutex_t mutex; #endif thread_pool_entry_struct * tdata; slong length; } thread_pool_struct; typedef thread_pool_struct thread_pool_t[1]; FLINT_DLL extern thread_pool_t global_thread_pool; FLINT_DLL extern int global_thread_pool_initialized; void * thread_pool_idle_loop(void * varg); void thread_pool_init(thread_pool_t T, slong l); int thread_pool_set_affinity(thread_pool_t T, int * cpus, slong length); int thread_pool_restore_affinity(thread_pool_t T); slong thread_pool_get_size(thread_pool_t T); int thread_pool_set_size(thread_pool_t T, slong new_size); slong thread_pool_request(thread_pool_t T, thread_pool_handle * out, slong requested); void thread_pool_wake(thread_pool_t T, thread_pool_handle i, int max_workers, void (*f)(void*), void * a); void thread_pool_wait(thread_pool_t T, thread_pool_handle i); void thread_pool_give_back(thread_pool_t T, thread_pool_handle i); void thread_pool_clear(thread_pool_t T); /* misc internal helpers *****************************************************/ void _thread_pool_distribute_work_2(slong start, slong stop, slong * Astart, slong * Astop, slong Alen, slong * Bstart, slong * Bstop, slong Blen); ulong _thread_pool_find_work_2(ulong a, ulong alpha, ulong b, ulong beta, ulong yn, ulong yd); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/thread_pool/000077500000000000000000000000001461254215100157225ustar00rootroot00000000000000flint-3.1.3/src/thread_pool/clear.c000066400000000000000000000027161461254215100171620ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" void thread_pool_clear(thread_pool_t T) { slong i, size; thread_pool_entry_struct * D; #if FLINT_USES_PTHREAD pthread_mutex_lock(&T->mutex); #endif D = T->tdata; size = T->length; for (i = 0; i < size; i++) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&D[i].mutex); #endif /* all threads should be given back */ FLINT_ASSERT(D[i].available == 1); D[i].exit = 1; #if FLINT_USES_PTHREAD pthread_cond_signal(&D[i].sleep1); pthread_mutex_unlock(&D[i].mutex); pthread_join(D[i].pth, NULL); pthread_cond_destroy(&D[i].sleep2); pthread_cond_destroy(&D[i].sleep1); pthread_mutex_destroy(&D[i].mutex); #endif } if (D != NULL) { flint_free(D); } #if FLINT_USES_CPUSET && FLINT_USES_PTHREAD if (T->original_affinity != NULL) { flint_free(T->original_affinity); T->original_affinity = NULL; } #endif #if FLINT_USES_PTHREAD pthread_mutex_unlock(&T->mutex); pthread_mutex_destroy(&T->mutex); #endif T->length = -1; T->tdata = NULL; } flint-3.1.3/src/thread_pool/distribute_work.c000066400000000000000000000025721461254215100213140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" /* given a range of jobs with numbers in [start, stop), where jobs with number in [0, Alen) belong to A and where jobs with number in [Alen, Blen + Alen) belong to B set [Astart, Astop) and [Bstart, Bstop) to be the ranges of jobs for A and B respectively. The code is simpler than this explanation. */ void _thread_pool_distribute_work_2( slong start, slong stop, slong * Astart, slong * Astop, slong Alen, slong * Bstart, slong * Bstop, slong Blen) { FLINT_ASSERT(0 <= start); FLINT_ASSERT(start <= stop); FLINT_ASSERT(stop <= Alen + Blen); if (start >= Alen) { *Astart = 0; *Astop = 0; *Bstart = start - Alen; *Bstop = stop - Alen; } else if (stop <= Alen) { *Astart = start; *Astop = stop; *Bstart = 0; *Bstop = 0; } else { *Astart = start; *Astop = Alen; *Bstart = 0; *Bstop = stop - Alen; } } flint-3.1.3/src/thread_pool/find_work.c000066400000000000000000000016421461254215100200530ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" /* if f is continuous with f(0) = 0 f'(x) = alpha for 0 < x < a f'(x) = beta for a < x < a + b return solution for x to f(x) = (a*alpha + b*beta)*yn/yd for 0 <= yn/yd <= 1 */ ulong _thread_pool_find_work_2( ulong a, ulong alpha, ulong b, ulong beta, ulong yn, ulong yd) { /* very low priority TODO: this can overflow only in very extreme cases */ ulong y = yn*(a*alpha + b*beta)/yd; if (y <= a*alpha) return y/alpha; return a + (y - a*alpha)/beta; } flint-3.1.3/src/thread_pool/get_size.c000066400000000000000000000011771461254215100177050ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" slong thread_pool_get_size(thread_pool_t T) { slong ret; #if FLINT_USES_PTHREAD pthread_mutex_lock(&T->mutex); #endif ret = T->length; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&T->mutex); #endif return ret; } flint-3.1.3/src/thread_pool/give_back.c000066400000000000000000000016611461254215100200040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" void thread_pool_give_back(thread_pool_t T, thread_pool_handle i) { thread_pool_entry_struct * D; #if FLINT_USES_PTHREAD pthread_mutex_lock(&T->mutex); #endif D = T->tdata; #if FLINT_USES_PTHREAD pthread_mutex_lock(&D[i].mutex); #endif /* thread we are giving back should not be available nor working */ FLINT_ASSERT(D[i].available == 0); FLINT_ASSERT(D[i].working == 0); D[i].available = 1; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&D[i].mutex); pthread_mutex_unlock(&T->mutex); #endif } flint-3.1.3/src/thread_pool/init.c000066400000000000000000000054461461254215100170420ustar00rootroot00000000000000/* Copyright (C) 2018-2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define _GNU_SOURCE #include #include "thread_pool.h" #if FLINT_USES_PTHREAD && defined(HAVE_PTHREAD_NP_H) # include #endif thread_pool_t global_thread_pool; int global_thread_pool_initialized = 0; void * thread_pool_idle_loop(void * varg) { thread_pool_entry_struct * arg = (thread_pool_entry_struct *) varg; goto thread_pool_Lock; thread_pool_DoWork: _flint_set_num_workers(arg->max_workers); arg->fxn(arg->fxnarg); thread_pool_Lock: #if FLINT_USES_PTHREAD pthread_mutex_lock(&arg->mutex); #endif arg->working = 0; thread_pool_CheckExit: if (arg->exit != 0) goto thread_pool_Unlock; #if FLINT_USES_PTHREAD pthread_cond_signal(&arg->sleep2); pthread_cond_wait(&arg->sleep1, &arg->mutex); #endif if (arg->working == 0) goto thread_pool_CheckExit; thread_pool_Unlock: #if FLINT_USES_PTHREAD pthread_mutex_unlock(&arg->mutex); #endif if (arg->exit == 0) goto thread_pool_DoWork; flint_cleanup(); return NULL; } void thread_pool_init(thread_pool_t T, slong size) { slong i; thread_pool_entry_struct * D; size = FLINT_MAX(size, WORD(0)); #if FLINT_USES_PTHREAD pthread_mutex_init(&T->mutex, NULL); #endif T->length = size; #if FLINT_USES_CPUSET && FLINT_USES_PTHREAD T->original_affinity = flint_malloc(sizeof(cpu_set_t)); if (0 != pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), (cpu_set_t *)T->original_affinity)) { CPU_ZERO((cpu_set_t *)T->original_affinity); } #endif if (size == 0) { T->tdata = NULL; return; } D = (thread_pool_entry_struct *) flint_malloc( size * sizeof(thread_pool_entry_struct)); T->tdata = D; for (i = 0; i < size; i++) { #if FLINT_USES_PTHREAD pthread_mutex_init(&D[i].mutex, NULL); pthread_cond_init(&D[i].sleep1, NULL); pthread_cond_init(&D[i].sleep2, NULL); #endif D[i].idx = i; D[i].available = 1; D[i].fxn = NULL; D[i].fxnarg = NULL; D[i].working = -1; D[i].max_workers = 0; D[i].exit = 0; #if FLINT_USES_PTHREAD pthread_mutex_lock(&D[i].mutex); pthread_create(&D[i].pth, NULL, thread_pool_idle_loop, &D[i]); while (D[i].working != 0) pthread_cond_wait(&D[i].sleep2, &D[i].mutex); pthread_mutex_unlock(&D[i].mutex); #endif } } flint-3.1.3/src/thread_pool/request.c000066400000000000000000000021671461254215100175640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" slong thread_pool_request(thread_pool_t T, thread_pool_handle * out, slong requested) { slong i, ret = 0; thread_pool_entry_struct * D; if (requested <= 0) return 0; #if FLINT_USES_PTHREAD pthread_mutex_lock(&T->mutex); #endif D = T->tdata; if (T->length > 0) { for (i = 0; i < T->length; i++) { if (D[i].available == 1) { D[i].available = 0; out[ret] = i; ret++; if (ret >= requested) break; } } } #if FLINT_USES_PTHREAD pthread_mutex_unlock(&T->mutex); #endif return ret; } flint-3.1.3/src/thread_pool/restore_affinity.c000066400000000000000000000023621461254215100214450ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define _GNU_SOURCE #include #include "thread_pool.h" #if FLINT_USES_PTHREAD && defined(HAVE_PTHREAD_NP_H) # include #endif int thread_pool_restore_affinity(thread_pool_t T) { #if FLINT_USES_CPUSET && FLINT_USES_PTHREAD slong i; int errorno; thread_pool_entry_struct * D; /* restore affinities for workers */ D = T->tdata; for (i = 0; i < T->length; i++) { errorno = pthread_setaffinity_np(D[i].pth, sizeof(cpu_set_t), (cpu_set_t *)T->original_affinity); if (errorno != 0) return errorno; } /* restore affinity for main thread */ errorno = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), (cpu_set_t *)T->original_affinity); if (errorno != 0) return errorno; #endif return 0; } flint-3.1.3/src/thread_pool/set_affinity.c000066400000000000000000000027061461254215100205570ustar00rootroot00000000000000/* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define _GNU_SOURCE #include #include "thread_pool.h" #if FLINT_USES_PTHREAD && defined(HAVE_PTHREAD_NP_H) # include #endif /* cpus[0] is cpu number for main thread cpus[1], ..., cpus[length - 1] are cpu numbers for elements of pool */ int thread_pool_set_affinity(thread_pool_t T, int * cpus, slong length) { #if FLINT_USES_CPUSET && FLINT_USES_PTHREAD slong i; int errorno; cpu_set_t mask; thread_pool_entry_struct * D; if (length <= 0) return 0; /* set affinities for workers */ D = T->tdata; for (i = 0; i + 1 < length && i < T->length; i++) { CPU_ZERO(&mask); CPU_SET(cpus[i + 1] % CPU_SETSIZE, &mask); errorno = pthread_setaffinity_np(D[i].pth, sizeof(cpu_set_t), &mask); if (errorno != 0) return errorno; } /* set affinity for main thread */ CPU_ZERO(&mask); CPU_SET(cpus[0] % CPU_SETSIZE, &mask); errorno = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mask); if (errorno != 0) return errorno; #endif return 0; } flint-3.1.3/src/thread_pool/set_size.c000066400000000000000000000046731461254215100177250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" int thread_pool_set_size(thread_pool_t T, slong new_size) { thread_pool_entry_struct * D; slong i; slong old_size; new_size = FLINT_MAX(new_size, WORD(0)); #if FLINT_USES_PTHREAD pthread_mutex_lock(&T->mutex); #endif D = T->tdata; old_size = T->length; /* check if T is in use */ for (i = 0; i < old_size; i++) { if (D[i].available != 1) { #if FLINT_USES_PTHREAD pthread_mutex_unlock(&T->mutex); #endif return 0; } } /* destroy all old data */ for (i = 0; i < old_size; i++) { #if FLINT_USES_PTHREAD pthread_mutex_lock(&D[i].mutex); #endif D[i].exit = 1; #if FLINT_USES_PTHREAD pthread_cond_signal(&D[i].sleep1); pthread_mutex_unlock(&D[i].mutex); pthread_join(D[i].pth, NULL); pthread_cond_destroy(&D[i].sleep2); pthread_cond_destroy(&D[i].sleep1); pthread_mutex_destroy(&D[i].mutex); #endif } if (D != NULL) { flint_free(D); } T->tdata = NULL; /* create new data */ if (new_size > 0) { D = T->tdata = (thread_pool_entry_struct *) flint_malloc(new_size * sizeof(thread_pool_entry_struct)); for (i = 0; i < new_size; i++) { #if FLINT_USES_PTHREAD pthread_mutex_init(&D[i].mutex, NULL); pthread_cond_init(&D[i].sleep1, NULL); pthread_cond_init(&D[i].sleep2, NULL); #endif D[i].idx = i; D[i].available = 1; D[i].fxn = NULL; D[i].fxnarg = NULL; D[i].working = -1; D[i].exit = 0; #if FLINT_USES_PTHREAD pthread_mutex_lock(&D[i].mutex); pthread_create(&D[i].pth, NULL, thread_pool_idle_loop, &D[i]); while (D[i].working != 0) pthread_cond_wait(&D[i].sleep2, &D[i].mutex); pthread_mutex_unlock(&D[i].mutex); #endif } } T->length = new_size; #if FLINT_USES_PTHREAD pthread_mutex_unlock(&T->mutex); #endif return 1; } flint-3.1.3/src/thread_pool/test/000077500000000000000000000000001461254215100167015ustar00rootroot00000000000000flint-3.1.3/src/thread_pool/test/main.c000066400000000000000000000014001461254215100177640ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-thread_pool.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(thread_pool) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/thread_pool/test/t-thread_pool.c000066400000000000000000000123511461254215100216100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_pool.h" #include "fmpz.h" /****************************************************************************** test1: calculate x = n! using a simple non-recursive residue scheme the master thread also participates in the calculation *******************************************************************************/ typedef struct { ulong modulus; ulong residue; ulong n; fmpz_t ans; } worker1_arg_struct; void worker1(void * varg) { worker1_arg_struct * arg = (worker1_arg_struct *) varg; ulong i; fmpz_one(arg->ans); for (i = arg->residue; i <= arg->n; i += arg->modulus) { fmpz_mul_ui(arg->ans, arg->ans, i); } } void test1(fmpz_t x, ulong n) { ulong i, modulus; slong k, req, num_workers; worker1_arg_struct * args; thread_pool_handle * handles; /* request as many workers as possible */ req = thread_pool_get_size(global_thread_pool); handles = (thread_pool_handle *) flint_malloc(req *sizeof(thread_pool_handle)); num_workers = thread_pool_request(global_thread_pool, handles, req); args = (worker1_arg_struct *) flint_malloc(FLINT_MAX(num_workers, 1) *sizeof(worker1_arg_struct)); modulus = num_workers + 1; /* start up each of the available workers */ for (k = 0; k < num_workers; k++) { args[k].residue = k + 1; args[k].modulus = modulus; args[k].n = n; fmpz_init(args[k].ans); /* worker expects an inited ans */ thread_pool_wake(global_thread_pool, handles[k], 0, worker1, &args[k]); } /* do some work ourselves */ fmpz_one(x); for (i = modulus; i <= n; i += modulus) { fmpz_mul_ui(x, x, i); } /* wait for each of the workers and combine their answers */ for (k = 0; k < num_workers; k++) { thread_pool_wait(global_thread_pool, handles[k]); fmpz_mul(x, x, args[k].ans); fmpz_clear(args[k].ans); /* worker of course did not clean up its ans */ thread_pool_give_back(global_thread_pool, handles[k]); } flint_free(args); flint_free(handles); } /****************************************************************************** test2 - calculate x = n! by recursively splitting the work when necessary *******************************************************************************/ typedef struct { ulong min; ulong max; fmpz_t ans; } worker2_arg_struct; void test2_helper(fmpz_t x, ulong min, ulong max); void worker2(void * varg) { worker2_arg_struct * arg = (worker2_arg_struct *) varg; test2_helper(arg->ans, arg->min, arg->max); } /* set x = product of numbers in (min, max] */ void test2_helper(fmpz_t x, ulong min, ulong max) { ulong i, mid; slong num_workers; thread_pool_handle handles[1]; worker2_arg_struct args[1]; FLINT_ASSERT(max >= min); if (max - min > UWORD(20) && ((num_workers = thread_pool_request(global_thread_pool, handles, 1)) != 0)) { FLINT_ASSERT(num_workers == 1); mid = min + ((max - min)/UWORD(2)); /* start up the worker */ args[0].min = min; args[0].max = mid; fmpz_init(args[0].ans); thread_pool_wake(global_thread_pool, handles[0], 0, worker2, &args[0]); /* do some work ourselves */ test2_helper(x, mid, max); /* wait for the worker and combine its answer */ thread_pool_wait(global_thread_pool, handles[0]); fmpz_mul(x, x, args[0].ans); fmpz_clear(args[0].ans); thread_pool_give_back(global_thread_pool, handles[0]); } else { fmpz_one(x); for (i = max; i > min; i--) { fmpz_mul_ui(x, x, i); } } } void test2(fmpz_t x, ulong n) { test2_helper(x, 0, n); } TEST_FUNCTION_START(thread_pool, state) { slong i, j; for (i = 0; i < 10*flint_test_multiplier(); i++) { fmpz_t x, y; fmpz_init(x); fmpz_init(y); flint_set_num_threads(n_randint(state, 10) + 1); for (j = 0; j < 10; j++) { ulong n = n_randint(state, 1000); fmpz_fac_ui(y, n); test1(x, n); if (!fmpz_equal(x, y)) TEST_FUNCTION_FAIL( "Test 1 failed\n" "n: %wu\n" "x: %{fmpz}\n" "y: %{fmpz}\n", n, x, y); test2(x, n); if (!fmpz_equal(x, y)) TEST_FUNCTION_FAIL( "Test 2 failed\n" "n: %wu\n" "x: %{fmpz}\n" "y: %{fmpz}\n", n, x, y); } fmpz_clear(y); fmpz_clear(x); } TEST_FUNCTION_END(state); } flint-3.1.3/src/thread_pool/wait.c000066400000000000000000000015211461254215100170310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" void thread_pool_wait(thread_pool_t T, thread_pool_handle i) { thread_pool_entry_struct * D; D = T->tdata; #if FLINT_USES_PTHREAD pthread_mutex_lock(&D[i].mutex); #endif /* should not be trying to wait on a available thread */ FLINT_ASSERT(D[i].available == 0); #if FLINT_USES_PTHREAD while (D[i].working != 0) pthread_cond_wait(&D[i].sleep2, &D[i].mutex); pthread_mutex_unlock(&D[i].mutex); #endif } flint-3.1.3/src/thread_pool/wake.c000066400000000000000000000021351461254215100170160ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" void thread_pool_wake(thread_pool_t T, thread_pool_handle i, int max_workers, void (*f)(void*), void * a) { thread_pool_entry_struct * D; #if FLINT_USES_PTHREAD pthread_mutex_lock(&T->mutex); #endif FLINT_ASSERT(i < T->length); D = T->tdata; #if FLINT_USES_PTHREAD pthread_mutex_lock(&D[i].mutex); #endif /* should not be trying to wake an available thread */ FLINT_ASSERT(D[i].available == 0); D[i].max_workers = max_workers; D[i].working = 1; D[i].fxn = f; D[i].fxnarg = a; #if FLINT_USES_PTHREAD pthread_cond_signal(&D[i].sleep1); pthread_mutex_unlock(&D[i].mutex); pthread_mutex_unlock(&T->mutex); #endif } flint-3.1.3/src/thread_support.h000066400000000000000000000031701461254215100166370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef THREAD_SUPPORT_H #define THREAD_SUPPORT_H #include "flint.h" #ifdef __cplusplus extern "C" { #endif #define FLINT_DEFAULT_THREAD_LIMIT 99999 slong flint_request_threads(thread_pool_handle ** handles, slong thread_limit); void flint_give_back_threads(thread_pool_handle * handles, slong num_handles); slong flint_get_num_available_threads(void); #define FLINT_PARALLEL_UNIFORM 1 #define FLINT_PARALLEL_STRIDED 2 #define FLINT_PARALLEL_DYNAMIC 4 #define FLINT_PARALLEL_BSPLIT_LEFT_INPLACE 8 #define FLINT_PARALLEL_VERBOSE 512 typedef void (* do_func_t)(slong i, void * args); void flint_parallel_do(do_func_t f, void * args, slong n, int thread_limit, int flags); typedef void (* bsplit_merge_func_t)(void *, void *, void *, void *); typedef void (* bsplit_basecase_func_t)(void *, slong, slong, void *); typedef void (* bsplit_init_func_t)(void *, void *); typedef void (* bsplit_clear_func_t)(void *, void *); void flint_parallel_binary_splitting(void * res, bsplit_basecase_func_t basecase, bsplit_merge_func_t merge, size_t sizeof_res, bsplit_init_func_t init, bsplit_clear_func_t clear, void * args, slong a, slong b, slong basecase_cutoff, int thread_limit, int flags); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/thread_support/000077500000000000000000000000001461254215100164655ustar00rootroot00000000000000flint-3.1.3/src/thread_support/get_num_available_threads.c000066400000000000000000000017761461254215100240140ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" slong flint_thread_pool_num_available(thread_pool_t T) { slong i, num = 0; thread_pool_entry_struct * D; #if FLINT_USES_PTHREAD pthread_mutex_lock(&T->mutex); #endif D = T->tdata; if (T->length > 0) { for (i = 0; i < T->length; i++) { num += D[i].available; } } #if FLINT_USES_PTHREAD pthread_mutex_unlock(&T->mutex); #endif return num; } slong flint_get_num_available_threads(void) { if (global_thread_pool_initialized) return flint_thread_pool_num_available(global_thread_pool) + 1; return flint_get_num_threads(); } flint-3.1.3/src/thread_support/test/000077500000000000000000000000001461254215100174445ustar00rootroot00000000000000flint-3.1.3/src/thread_support/test/main.c000066400000000000000000000015651461254215100205430ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-parallel_binary_splitting.c" #include "t-parallel_do.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(thread_support_parallel_binary_splitting), TEST_FUNCTION(thread_support_parallel_do) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/thread_support/test/t-parallel_binary_splitting.c000066400000000000000000000055721461254215100253170ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_support.h" #include "fmpz.h" typedef struct { fmpz r; } product_res_t; typedef struct { mp_srcptr factors; int left_inplace; } product_args_t; static void product_init(product_res_t * x, product_args_t * args) { fmpz_init(&x->r); } static void product_clear(product_res_t * x, product_args_t * args) { fmpz_clear(&x->r); } static void product_combine(product_res_t * res, product_res_t * left, product_res_t * right, product_args_t * args) { if (((res == left) != args->left_inplace) || res == right) { flint_abort(); } fmpz_mul(&res->r, &left->r, &right->r); } static void product_basecase(product_res_t * res, slong a, slong b, product_args_t * args) { slong i; fmpz_one(&res->r); for (i = a; i < b; i++) fmpz_mul_ui(&res->r, &res->r, args->factors[i]); } static void bsplit_product(fmpz_t r, mp_srcptr factors, slong len, slong thread_limit, int flags) { product_res_t res; product_args_t args; res.r = *r; args.factors = factors; args.left_inplace = (flags & FLINT_PARALLEL_BSPLIT_LEFT_INPLACE) ? 1 : 0; flint_parallel_binary_splitting(&res, (bsplit_basecase_func_t) product_basecase, (bsplit_merge_func_t) product_combine, sizeof(product_res_t), (bsplit_init_func_t) product_init, (bsplit_clear_func_t) product_clear, &args, 0, len, 4, thread_limit, flags); *r = res.r; } TEST_FUNCTION_START(thread_support_parallel_binary_splitting, state) { slong iter; for (iter = 0; iter < 100 * flint_test_multiplier(); iter++) { fmpz_t r, s; mp_ptr factors; slong i, n; int flags; n = n_randint(state, 100); flint_set_num_threads(n_randint(state, 10) + 1); factors = flint_malloc(n * sizeof(mp_limb_t)); fmpz_init(r); fmpz_init(s); for (i = 0; i < n; i++) factors[i] = n_randint(state, 300); flags = 0; if (n_randint(state, 2)) flags = FLINT_PARALLEL_BSPLIT_LEFT_INPLACE; bsplit_product(r, factors, n, n_randint(state, 5), flags); fmpz_one(s); for (i = 0; i < n; i++) fmpz_mul_ui(s, s, factors[i]); if (!fmpz_equal(r, s)) TEST_FUNCTION_FAIL( "num_threads = %wd, i = %wd/%wd\n", flint_get_num_threads(), i, n); flint_free(factors); fmpz_clear(r); fmpz_clear(s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/thread_support/test/t-parallel_do.c000066400000000000000000000031051461254215100223260ustar00rootroot00000000000000/* Copyright (C) 2022 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "thread_support.h" #include "fmpz.h" typedef struct { int * res; } f_param_t; void f(slong i, void * param) { f_param_t * p = (f_param_t *) param; p->res[i] = i * i; } TEST_FUNCTION_START(thread_support_parallel_do, state) { slong iter; for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { int * resx; int * resy; slong i, n; f_param_t workx, worky; n = n_randint(state, 1000); flint_set_num_threads(n_randint(state, 10) + 1); resx = flint_malloc(n * sizeof(int)); resy = flint_malloc(n * sizeof(int)); workx.res = resx; worky.res = resy; flint_parallel_do(f, &workx, n, n_randint(state, 5), FLINT_PARALLEL_UNIFORM); flint_parallel_do(f, &worky, n, n_randint(state, 5), FLINT_PARALLEL_STRIDED); for (i = 0; i < n; i++) { if (resx[i] != resy[i] || resx[i] != i * i) TEST_FUNCTION_FAIL( "num_threads = %wd, i = %wd/%wd\n", flint_get_num_threads(), i, n); } flint_free(resx); flint_free(resy); } TEST_FUNCTION_END(state); } flint-3.1.3/src/thread_support/thread_support.c000066400000000000000000000227221461254215100217010ustar00rootroot00000000000000/* Copyright (C) 2013, 2022 Fredrik Johansson Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "thread_pool.h" #include "thread_support.h" /* Automatically initialised to zero when threads are started */ FLINT_TLS_PREFIX int _flint_num_workers = 0; int flint_get_num_threads(void) { return _flint_num_workers + 1; } void flint_set_num_threads(int num_threads) { #if !FLINT_USES_PTHREAD num_threads = 1; #endif _flint_num_workers = num_threads - 1; if (global_thread_pool_initialized) { if (!thread_pool_set_size(global_thread_pool, num_threads - 1)) { flint_throw(FLINT_ERROR, "flint_set_num_threads called while global thread pool in use"); } } else { thread_pool_init(global_thread_pool, num_threads - 1); global_thread_pool_initialized = 1; } } void _flint_set_num_workers(int num_workers) { _flint_num_workers = num_workers; } int flint_set_num_workers(int num_workers) { int old_num_workers; #if !FLINT_USES_PTHREAD num_workers = 0; #endif old_num_workers = _flint_num_workers; _flint_num_workers = FLINT_MIN(_flint_num_workers, num_workers); return old_num_workers; } void flint_reset_num_workers(int num_workers) { _flint_num_workers = num_workers; } /* return zero for success, nonzero for error */ int flint_set_thread_affinity(int * cpus, slong length) { if (!global_thread_pool_initialized) return 1; return thread_pool_set_affinity(global_thread_pool, cpus, length); } /* return zero for success, nonzero for error */ int flint_restore_thread_affinity(void) { if (!global_thread_pool_initialized) return 1; return thread_pool_restore_affinity(global_thread_pool); } /* Takes in the *thread limit* but returns the number of **handles**. That is, * the maximum return value is `thread_limit - 1`. */ slong flint_request_threads(thread_pool_handle ** handles, slong thread_limit) { slong num_handles = 0; slong num_threads = flint_get_num_threads(); thread_limit = FLINT_MIN(thread_limit, num_threads); *handles = NULL; if (global_thread_pool_initialized && thread_limit > 1) { slong max_num_handles; max_num_handles = thread_pool_get_size(global_thread_pool); max_num_handles = FLINT_MIN(thread_limit - 1, max_num_handles); if (max_num_handles > 0) { *handles = (thread_pool_handle *) flint_malloc( max_num_handles*sizeof(thread_pool_handle)); num_handles = thread_pool_request(global_thread_pool, *handles, max_num_handles); } } return num_handles; } void flint_give_back_threads(thread_pool_handle * handles, slong num_handles) { slong i; for (i = 0; i < num_handles; i++) thread_pool_give_back(global_thread_pool, handles[i]); if (handles) flint_free(handles); } typedef struct { do_func_t f; void * args; slong a; slong b; slong step; } work_chunk_t; static void worker(void * _work) { work_chunk_t work = *((work_chunk_t *) _work); slong i; for (i = work.a; i < work.b; i += work.step) work.f(i, work.args); } void flint_parallel_do(do_func_t f, void * args, slong n, int thread_limit, int flags) { slong i; if (thread_limit <= 0) thread_limit = flint_get_num_threads(); thread_limit = FLINT_MIN(thread_limit, n); if (thread_limit <= 1) { for (i = 0; i < n; i++) f(i, args); } else { slong i, num_threads, num_workers; thread_pool_handle * handles; num_workers = flint_request_threads(&handles, thread_limit); num_threads = num_workers + 1; if (flags & FLINT_PARALLEL_VERBOSE) flint_printf("parallel_do with num_threads = %wd\n", num_threads); if (num_workers < 1) { flint_give_back_threads(handles, num_workers); for (i = 0; i < n; i++) f(i, args); } else { work_chunk_t * work; slong chunk_size; TMP_INIT; TMP_START; work = TMP_ALLOC(num_threads * sizeof(work_chunk_t)); if (flags & FLINT_PARALLEL_STRIDED) { for (i = 0; i < num_threads; i++) { work[i].f = f; work[i].args = args; work[i].a = i; work[i].b = n; work[i].step = num_threads; } } else { chunk_size = (n + num_threads - 1) / num_threads; for (i = 0; i < num_threads; i++) { work[i].f = f; work[i].args = args; work[i].a = i * chunk_size; work[i].b = FLINT_MIN((i + 1) * chunk_size, n); work[i].step = 1; } } if (flags & FLINT_PARALLEL_VERBOSE) { for (i = 0; i < num_threads; i++) { flint_printf("thread #%wd allocated a = %wd, b = %wd, step = %wd\n", i, work[i].a, work[i].b, work[i].step); } } for (i = 0; i < num_workers; i++) thread_pool_wake(global_thread_pool, handles[i], 0, worker, &work[i]); worker(&work[num_workers]); for (i = 0; i < num_workers; i++) thread_pool_wait(global_thread_pool, handles[i]); flint_give_back_threads(handles, num_workers); TMP_END; } } } typedef struct { void * res; bsplit_basecase_func_t basecase; bsplit_merge_func_t merge; size_t sizeof_res; bsplit_init_func_t init; bsplit_clear_func_t clear; void * args; slong a; slong b; slong basecase_cutoff; slong thread_limit; int flags; } flint_parallel_binary_splitting_t; static void _bsplit_worker(void * _args) { flint_parallel_binary_splitting_t * args = (flint_parallel_binary_splitting_t *) _args; flint_parallel_binary_splitting(args->res, args->basecase, args->merge, args->sizeof_res, args->init, args->clear, args->args, args->a, args->b, args->basecase_cutoff, args->thread_limit, args->flags); } void flint_parallel_binary_splitting(void * res, bsplit_basecase_func_t basecase, bsplit_merge_func_t merge, size_t sizeof_res, bsplit_init_func_t init, bsplit_clear_func_t clear, void * args, slong a, slong b, slong basecase_cutoff, int thread_limit, int flags) { basecase_cutoff = FLINT_MAX(basecase_cutoff, 1); if (b - a <= basecase_cutoff) { basecase(res, a, b, args); } else { void * left, * right; slong m = a + (b - a) / 2; slong nw; slong nw_save; slong nt; thread_pool_handle * threads; TMP_INIT; TMP_START; if (flags & FLINT_PARALLEL_BSPLIT_LEFT_INPLACE) { left = res; right = TMP_ALLOC(sizeof_res); init(right, args); } else { left = TMP_ALLOC(2 * sizeof_res); right = (void *) (((char *) left) + sizeof_res); init(left, args); init(right, args); } if (thread_limit <= 0) thread_limit = flint_get_num_threads(); nt = thread_limit; nw = flint_request_threads(&threads, FLINT_MIN(nt, 2)); /* request one extra worker */ if (nw == 0) { flint_parallel_binary_splitting(left, basecase, merge, sizeof_res, init, clear, args, a, m, basecase_cutoff, thread_limit, flags); flint_parallel_binary_splitting(right, basecase, merge, sizeof_res, init, clear, args, m, b, basecase_cutoff, thread_limit, flags); } else { flint_parallel_binary_splitting_t right_args; FLINT_ASSERT(nt >= 2); nw_save = flint_set_num_workers(nt - nt / 2 - 1); right_args.res = right; right_args.basecase = basecase; right_args.merge = merge; right_args.sizeof_res = sizeof_res; right_args.init = init; right_args.clear = clear; right_args.args = args; right_args.a = m; right_args.b = b; right_args.basecase_cutoff = basecase_cutoff; right_args.thread_limit = thread_limit; right_args.flags = flags; thread_pool_wake(global_thread_pool, threads[0], nt / 2 - 1, _bsplit_worker, &right_args); flint_parallel_binary_splitting(left, basecase, merge, sizeof_res, init, clear, args, a, m, basecase_cutoff, thread_limit, flags); flint_reset_num_workers(nw_save); thread_pool_wait(global_thread_pool, threads[0]); } flint_give_back_threads(threads, nw); merge(res, left, right, args); if (flags & FLINT_PARALLEL_BSPLIT_LEFT_INPLACE) { clear(right, args); } else { clear(left, args); clear(right, args); } TMP_END; } } flint-3.1.3/src/ulong_extras.h000066400000000000000000000276261461254215100163220ustar00rootroot00000000000000/* Copyright (C) 2006, 2007, 2008, 2009, 2016 William Hart Copyright (C) 2008 Peter Shrimpton Copyright (C) 2009 Tom Boothby Copyright (C) 2010 Fredrik Johansson Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #ifndef ULONG_EXTRAS_H #define ULONG_EXTRAS_H #ifdef ULONG_EXTRAS_INLINES_C #define ULONG_EXTRAS_INLINE #else #define ULONG_EXTRAS_INLINE static inline #endif #include "limb_types.h" #ifdef __cplusplus extern "C" { #endif /* Randomisation *************************************************************/ ulong n_randlimb(flint_rand_t state); ulong n_randint(flint_rand_t state, ulong limit); ulong n_urandint(flint_rand_t state, ulong limit); ulong n_randbits(flint_rand_t state, unsigned int bits); ulong n_randprime(flint_rand_t state, ulong bits, int proved); ulong n_randtest_bits(flint_rand_t state, int bits); ulong n_randtest(flint_rand_t state); ulong n_randtest_not_zero(flint_rand_t state); ulong n_randtest_prime(flint_rand_t state, int proved); /* Basic arithmetic **********************************************************/ ulong n_revbin(ulong in, ulong bits); int n_divides(mp_limb_t * q, mp_limb_t n, mp_limb_t p); ulong n_divrem2_precomp(ulong * q, ulong a, ulong n, double npre); ulong n_divrem2_preinv(ulong * q, ulong a, ulong n, ulong ninv); ulong n_div2_preinv(ulong a, ulong n, ulong ninv); ulong n_factorial_mod2_preinv(ulong n, ulong p, ulong pinv); ulong n_factorial_fast_mod2_preinv(ulong n, ulong p, ulong pinv); ulong n_sqrt(ulong a); ulong n_sqrtrem(ulong * r, ulong a); int n_is_square(ulong x); int n_is_squarefree(ulong n); double n_cbrt_estimate(double a); ulong n_cbrt(ulong a); ulong n_cbrt_binary_search(ulong x); ulong n_cbrt_newton_iteration(ulong n); ulong n_cbrt_chebyshev_approx(ulong n); ulong n_cbrtrem(ulong* remainder, ulong n); ulong n_pow(ulong n, ulong exp); ulong _n_pow_check(ulong n, ulong exp); ulong n_root(ulong n, ulong root); ulong n_rootrem(ulong* remainder, ulong n, ulong root); ulong n_root_estimate(double a, int n); int n_is_perfect_power235(ulong n); int n_is_perfect_power(ulong * root, ulong n); int n_sizeinbase(ulong n, int base); ulong n_flog(ulong n, ulong b); ulong n_clog(ulong n, ulong b); ulong n_clog_2exp(ulong n, ulong b); ULONG_EXTRAS_INLINE ulong n_gcd(ulong x, ulong y) { if (x != 0 && y != 0) { #ifdef FLINT_WANT_GMP_INTERNALS ulong mx, my, res; mx = flint_ctz(x); my = flint_ctz(y); x >>= mx; y >>= my; res = (x != 1 && y != 1) ? mpn_gcd_11(x, y) : 1; res <<= FLINT_MIN(mx, my); return res; #else return mpn_gcd_1(&x, 1, y); #endif } else return x + y; } ulong n_xgcd(ulong * a, ulong * b, ulong x, ulong y); ulong n_gcdinv(ulong * a, ulong x, ulong y); ulong n_CRT(ulong r1, ulong m1, ulong r2, ulong m2); /* Checked arithmetic ********************************************************/ ULONG_EXTRAS_INLINE int n_mul_checked(ulong * a, ulong b, ulong c) { ulong ahi, alo; umul_ppmm(ahi, alo, b, c); *a = alo; return 0 != ahi; } ULONG_EXTRAS_INLINE int n_add_checked(ulong * a, ulong b, ulong c) { int of = b + c < b; *a = b + c; return of; } ULONG_EXTRAS_INLINE int n_sub_checked(ulong * a, ulong b, ulong c) { int of = b < c; *a = b - c; return of; } /* Modular arithmetic ********************************************************/ ULONG_EXTRAS_INLINE double n_precompute_inverse(ulong n) { return (double) 1 / (double) n; } ulong n_preinvert_limb(ulong n); ulong n_preinvert_limb_prenorm(ulong n); /* deprecated -- originally defined in longlong.h */ #define invert_limb(dinv, d) do { (dinv) = n_preinvert_limb_prenorm(d); } while (0) ulong n_mod_precomp(ulong a, ulong n, double ninv); ulong n_mod2_precomp(ulong a, ulong n, double ninv); ulong n_mod2_preinv(ulong a, ulong n, ulong ninv); ulong n_ll_mod_preinv(ulong a_hi, ulong a_lo, ulong n, ulong ninv); ulong n_lll_mod_preinv(ulong a_hi, ulong a_mi, ulong a_lo, ulong n, ulong ninv); ulong n_mulmod_precomp(ulong a, ulong b, ulong n, double ninv); ulong n_mulmod_preinv(ulong a, ulong b, ulong n, ulong ninv, ulong norm); mp_limb_t n_mulmod_precomp_shoup(mp_limb_t w, mp_limb_t p); ULONG_EXTRAS_INLINE mp_limb_t n_mulmod_shoup(mp_limb_t w, mp_limb_t t, mp_limb_t w_precomp, mp_limb_t p) { mp_limb_t q, r, p_hi, p_lo; umul_ppmm(p_hi, p_lo, w_precomp, t); q = p_hi; (void) p_lo; /* unused */ r = w * t; r -= q * p; if (r >= p) r -= p; return r; } ULONG_EXTRAS_INLINE ulong n_mulmod2_preinv(ulong a, ulong b, ulong n, ulong ninv) { ulong p1, p2; FLINT_ASSERT(n != 0); umul_ppmm(p1, p2, a, b); return n_ll_mod_preinv(p1, p2, n, ninv); } ULONG_EXTRAS_INLINE ulong n_mulmod2(ulong a, ulong b, ulong n) { ulong p1, p2, ninv; FLINT_ASSERT(n != 0); ninv = n_preinvert_limb(n); umul_ppmm(p1, p2, a, b); return n_ll_mod_preinv(p1, p2, n, ninv); } ulong n_powmod_ui_precomp(ulong a, ulong exp, ulong n, double npre); ulong n_powmod_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv, ulong norm); ulong n_powmod_precomp(ulong a, slong exp, ulong n, double npre); ULONG_EXTRAS_INLINE ulong n_powmod(ulong a, slong exp, ulong n) { double npre = n_precompute_inverse(n); return n_powmod_precomp(a, exp, n, npre); } ulong n_powmod2_fmpz_preinv(ulong a, const fmpz_t exp, ulong n, ulong ninv); ulong n_powmod2_preinv(ulong a, slong exp, ulong n, ulong ninv); ulong n_powmod2_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv); ULONG_EXTRAS_INLINE ulong n_powmod2(ulong a, slong exp, ulong n) { ulong ninv; FLINT_ASSERT(n != 0); ninv = n_preinvert_limb(n); return n_powmod2_preinv(a, exp, n, ninv); } ULONG_EXTRAS_INLINE ulong n_addmod(ulong x, ulong y, ulong n) { FLINT_ASSERT(x < n); FLINT_ASSERT(y < n); FLINT_ASSERT(n != 0); return (n - y > x ? x + y : x + y - n); } ULONG_EXTRAS_INLINE ulong n_submod(ulong x, ulong y, ulong n) { FLINT_ASSERT(x < n); FLINT_ASSERT(y < n); FLINT_ASSERT(n != 0); return (y > x ? x - y + n : x - y); } ULONG_EXTRAS_INLINE ulong n_negmod(ulong x, ulong n) { FLINT_ASSERT(x < n); FLINT_ASSERT(n != 0); return n_submod(0, x, n); } ulong n_sqrtmod(ulong a, ulong p); slong n_sqrtmod_2pow(ulong ** sqrt, ulong a, slong exp); slong n_sqrtmod_primepow(ulong ** sqrt, ulong a, ulong p, slong exp); slong n_sqrtmodn(ulong ** sqrt, ulong a, n_factor_t * fac); ULONG_EXTRAS_INLINE ulong n_invmod(ulong x, ulong y) { ulong r, g; g = n_gcdinv(&r, x, y); if (g != 1) flint_throw(FLINT_IMPINV, "Cannot invert modulo %wd*%wd\n", g, y/g); return r; } /* Primitive roots and discrete logarithms ***********************************/ ulong n_primitive_root_prime_prefactor(ulong p, n_factor_t * factors); ulong n_primitive_root_prime(ulong p); ulong n_discrete_log_bsgs(ulong b, ulong a, ulong n); /* Special functions *********************************************************/ int n_jacobi(slong x, ulong y); int n_jacobi_unsigned(ulong x, ulong y); int _n_jacobi_unsigned(ulong x, ulong y, unsigned int r); int n_moebius_mu(ulong n); void n_moebius_mu_vec(int * mu, ulong len); ulong n_euler_phi(ulong n); /* Primality *****************************************************************/ #define FLINT_ODDPRIME_SMALL_CUTOFF 4096 #define FLINT_NUM_PRIMES_SMALL 172 #define FLINT_PRIMES_SMALL_CUTOFF 1030 #define FLINT_PSEUDOSQUARES_CUTOFF 1000 #define FLINT_PRIMES_TAB_DEFAULT_CUTOFF 1000000 #define FLINT_PRIME_PI_ODD_LOOKUP_CUTOFF 311 #define FLINT_SIEVE_SIZE 65536 #if FLINT64 # define UWORD_MAX_PRIME UWORD(18446744073709551557) #else # define UWORD_MAX_PRIME UWORD(4294967291) #endif FLINT_DLL extern const unsigned int flint_primes_small[]; extern FLINT_TLS_PREFIX ulong * _flint_primes[FLINT_BITS]; extern FLINT_TLS_PREFIX double * _flint_prime_inverses[FLINT_BITS]; extern FLINT_TLS_PREFIX int _flint_primes_used; void n_primes_init(n_primes_t iter); void n_primes_clear(n_primes_t iter); void n_primes_extend_small(n_primes_t iter, ulong bound); void n_primes_sieve_range(n_primes_t iter, ulong a, ulong b); void n_primes_jump_after(n_primes_t iter, ulong n); ulong n_primes_next(n_primes_t iter); void n_compute_primes(ulong num_primes); void n_cleanup_primes(void); const ulong * n_primes_arr_readonly(ulong n); const double * n_prime_inverses_arr_readonly(ulong n); int n_is_oddprime_small(ulong n); int n_is_oddprime_binary(ulong n); int n_is_probabprime(ulong n); int n_is_probabprime_fermat(ulong n, ulong i); int n_is_probabprime_fibonacci(ulong n); int n_is_probabprime_lucas(ulong n); int n_is_probabprime_BPSW(ulong n); int n_is_strong_probabprime_precomp(ulong n, double npre, ulong a, ulong d); int n_is_strong_probabprime2_preinv(ulong n, ulong ninv, ulong a, ulong d); int n_is_prime(ulong n); int n_is_prime_pseudosquare(ulong n); int n_is_prime_pocklington(ulong n, ulong iterations); ulong n_nth_prime(ulong n); void n_nth_prime_bounds(ulong *lo, ulong *hi, ulong n); ulong n_prime_pi(ulong n); void n_prime_pi_bounds(ulong *lo, ulong *hi, ulong n); ulong n_nextprime(ulong n, int proved); /* Factorisation *************************************************************/ #define FLINT_FACTOR_TRIAL_PRIMES 3000 #define FLINT_FACTOR_TRIAL_PRIMES_PRIME UWORD(27449) #define FLINT_FACTOR_TRIAL_CUTOFF (UWORD(27449) * UWORD(27449)) #define FLINT_FACTOR_SQUFOF_ITERS 50000 #define FLINT_FACTOR_ONE_LINE_MAX (UWORD(1)<<39) #define FLINT_FACTOR_ONE_LINE_ITERS 40000 ULONG_EXTRAS_INLINE void n_factor_init(n_factor_t * factors) { factors->num = UWORD(0); } void n_factor(n_factor_t * factors, ulong n, int proved); void n_factor_insert(n_factor_t * factors, ulong p, ulong exp); ulong n_factor_trial_range(n_factor_t * factors, ulong n, ulong start, ulong num_primes); ulong n_factor_trial_partial(n_factor_t * factors, ulong n, ulong * prod, ulong num_primes, ulong limit); ulong n_factor_trial(n_factor_t * factors, ulong n, ulong num_primes); ulong n_factor_partial(n_factor_t * factors, ulong n, ulong limit, int proved); ulong n_factor_power235(ulong *exp, ulong n); ulong n_factor_one_line(ulong n, ulong iters); ulong n_factor_lehman(ulong n); ulong n_factor_SQUFOF(ulong n, ulong iters); ulong n_factor_pp1(ulong n, ulong B1, ulong c); ulong n_factor_pp1_wrapper(ulong n); int n_factor_pollard_brent_single(ulong *factor, ulong n, ulong ninv, ulong ai, ulong xi, ulong normbits, ulong max_iters); int n_factor_pollard_brent(ulong *factor, flint_rand_t state, ulong n_in, ulong max_tries, ulong max_iters); int n_remove(ulong * n, ulong p); int n_remove2_precomp(ulong * n, ulong p, double ppre); /* ECM functions *************************************************************/ typedef struct { ulong x, z; /* the coordinates */ ulong a24; /* value (a + 2)/4 */ ulong ninv; ulong normbits; ulong one; unsigned char *GCD_table; /* checks whether baby step int is coprime to Primorial or not */ unsigned char **prime_table; } n_ecm_s; typedef n_ecm_s n_ecm_t[1]; void n_factor_ecm_double(ulong *x, ulong *z, ulong x0, ulong z0, ulong n, n_ecm_t n_ecm_inf); void n_factor_ecm_add(ulong *x, ulong *z, ulong x1, ulong z1, ulong x2, ulong z2, ulong x0, ulong z0, ulong n, n_ecm_t n_ecm_inf); void n_factor_ecm_mul_montgomery_ladder(ulong *x, ulong *z, ulong x0, ulong z0, ulong k, ulong n, n_ecm_t n_ecm_inf); int n_factor_ecm_select_curve(ulong *f, ulong sig, ulong n, n_ecm_t n_ecm_inf); int n_factor_ecm(ulong *f, ulong curves, ulong B1, ulong B2, flint_rand_t state, ulong n); int n_factor_ecm_stage_I(ulong *f, const ulong *prime_array, ulong num, ulong B1, ulong n, n_ecm_t n_ecm_inf); int n_factor_ecm_stage_II(ulong *f, ulong B1, ulong B2, ulong P, ulong n, n_ecm_t n_ecm_inf); #ifdef __cplusplus } #endif #endif flint-3.1.3/src/ulong_extras/000077500000000000000000000000001461254215100161345ustar00rootroot00000000000000flint-3.1.3/src/ulong_extras/CRT.c000066400000000000000000000017131461254215100167320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" /* TODO: improve the implementation of this function */ ulong n_CRT(ulong A1, ulong M1, ulong A2, ulong M2) { ulong R; fmpz_t r, a1, m1, a2, m2; fmpz_init(r); fmpz_init_set_ui(a1, A1); fmpz_init_set_ui(m1, M1); fmpz_init_set_ui(a2, A2); fmpz_init_set_ui(m2, M2); fmpz_CRT(r, a1, m1, a2, m2, 0); FLINT_ASSERT(fmpz_abs_fits_ui(r)); R = fmpz_get_ui(r); fmpz_clear(r); fmpz_clear(a1); fmpz_clear(m1); fmpz_clear(a2); fmpz_clear(m2); return R; } flint-3.1.3/src/ulong_extras/cbrt.c000066400000000000000000000243131461254215100172350ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Fredrik Johansson Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" mp_limb_t n_cbrt(mp_limb_t n) { int bits; double val, x, xcub, num, den; mp_limb_t ret, upper_limit; /* Taking care of smaller roots */ if (n < 125) return (n >= 1) + (n >= 8) + (n >= 27) + (n >= 64); if (n < 1331) return 5 + (n >= 216) + (n >= 343) + (n >= 512) + (n >= 729) + (n >= 1000); if (n < 4913) return 11 + (n >= 1728) + (n >= 2197) + (n >= 2744) + (n >= 3375) + (n >= 4096); val = (double)n; #ifdef FLINT64 bits = FLINT_BIT_COUNT(n); if (bits > 46) /* for larger numbers chebyshev approximation method is faster */ return n_cbrt_chebyshev_approx(n); #endif /* upper_limit is the max cube root possible for one word */ #ifdef FLINT64 upper_limit = 2642245; /* 2642245 = floor((2^64)^(1/3)) */ #else upper_limit = 1625; /* 1625 = floor((2^32)^(1/3)) */ #endif x = n_cbrt_estimate((double)n); /* initial estimate */ /* Kahan's iterations to get cube root */ xcub = x * x * x; num = (xcub - val) * x; den = (xcub + xcub + val); x -= (num / den); ret = x; /* In case ret^3 or (ret+1)^3 will cause overflow */ if (ret >= upper_limit) { #ifndef FLINT64 /* If bits(n) > 46, then Chebyshev is used. Hence, this is only possible * for 32-bit systems. */ if (n >= upper_limit * upper_limit * upper_limit) return upper_limit; #endif ret = upper_limit - 1; } while (ret * ret * ret <= n) { (ret) += 1; if (ret == upper_limit) break; } while (ret * ret * ret > n) (ret) -= 1; return ret; } mp_limb_t n_cbrt_newton_iteration(mp_limb_t n) { int iter, bits; mp_limb_t ret; double val, x, xsq, dx; /* upper_limit is the max cube root possible for one word */ #ifdef FLINT64 const mp_limb_t upper_limit = 2642245; /* 2642245 < (2^64)^(1/3) */ #else const mp_limb_t upper_limit = 1625; /* 1625 < (2^32)^(1/3) */ #endif val = (double)n; bits = FLINT_BIT_COUNT(n); if (bits < 46) /* one iteration seems to be sufficient for n < 2^46 */ iter = 1; else iter = 2; /* 2 gives us a precise enough answer for any mp_limb_t */ x = n_cbrt_estimate((double)n); /* initial estimate */ /* Newton's iterations to get cube root */ val = (double)n; while(iter--) { xsq = x * x; dx = val / xsq; dx -= x; dx *= 0.333333333333333; /* dx = dx * (1/3) */ x += dx; } /* In case ret^3 or (ret+1)^3 will cause overflow */ ret = x; if (ret >= upper_limit) { if (n >= upper_limit * upper_limit * upper_limit) return upper_limit; ret = upper_limit - 1; } while (ret * ret * ret <= n) { (ret) += 1; if (ret == upper_limit) break; } while (ret * ret * ret > n) (ret) -= 1; return ret; } /* Coefficients of Chebyshev's approximation polynomial (deg 2) {c0, c1, c2} splitting 0.5 to 1 into 8 equal intervals Values of these coefficients of Chebyshev's approximation polynomial have been calculated from the python module, "mpmath" - https://mpmath.org/ function call: mpmath.chebyfit(lambda x: mpmath.root(x,3), [i, j], 3, error=True) where (i, j) is the range */ static const float factor_table[] = {1.000000, 1.259921, 1.587401}; /* {1^(1/3), 2^(1/3), 4^(1/3)} */ /* c0 c1 c2 range */ static const float coeff[16][3] = {{0.445434042, 0.864136635, -0.335205926}, /* [0.50000, 0.53125] */ {0.454263239, 0.830878907, -0.303884962}, /* [0.53125, 0.56250] */ {0.462761624, 0.800647514, -0.276997626}, /* [0.56250, 0.59375] */ {0.470958569, 0.773024522, -0.253724515}, /* [0.59375, 0.62500] */ {0.478879482, 0.747667468, -0.233429710}, /* [0.62500, 0.65625] */ {0.486546506, 0.724292830, -0.215613166}, /* [0.65625, 0.68750] */ {0.493979069, 0.702663686, -0.199877008}, /* [0.68750, 0.71875] */ {0.501194325, 0.682580388, -0.185901247}, /* [0.71875, 0.75000] */ {0.508207500, 0.663873398, -0.173426009}, /* [0.75000, 0.78125] */ {0.515032183, 0.646397742, -0.162238357}, /* [0.78125, 0.81250] */ {0.521680556, 0.630028647, -0.152162376}, /* [0.81250, 0.84375] */ {0.528163588, 0.614658092, -0.143051642}, /* [0.84375, 0.87500] */ {0.534491194, 0.600192044, -0.134783425}, /* [0.87500, 0.90625] */ {0.540672371, 0.586548233, -0.127254189}, /* [0.90625, 0.93750] */ {0.546715310, 0.573654340, -0.120376066}, /* [0.93750, 0.96875] */ {0.552627494, 0.561446514, -0.114074068}}; /* [0.96875, 1.00000] */ mp_limb_t n_cbrt_chebyshev_approx(mp_limb_t n) { typedef union { mp_limb_t uword_val; #ifdef FLINT64 double double_val; #else float double_val; #endif } uni; int rem, mul; double factor, root, dec, dec2; mp_limb_t ret, expo, table_index; uni alias; /* upper_limit is the max cube root possible for one word */ #ifdef FLINT64 const mp_limb_t upper_limit = 2642245; /* 2642245 < (2^64)^(1/3) */ const mp_limb_t expo_mask = 0x7FF0000000000000; /* exponent bits in double */ const mp_limb_t mantissa_mask = 0x000FFFFFFFFFFFFF; /* mantissa bits in float */ const mp_limb_t table_mask = 0x000F000000000000; /* first 4 bits of mantissa */ const int mantissa_bits = 52; const mp_limb_t bias_hex = 0x3FE0000000000000; const int bias = 1022; alias.double_val = (double)n; #else const mp_limb_t upper_limit = 1625; /* 1625 < (2^32)^(1/3) */ const mp_limb_t expo_mask = 0x7F800000; /* exponent bits in float */ const mp_limb_t mantissa_mask = 0x007FFFFF; /* mantissa bits in float */ const mp_limb_t table_mask = 0x00780000; /* first 4 bits of mantissa */ const int mantissa_bits = 23; const mp_limb_t bias_hex = 0x3F000000; const int bias = 126; alias.double_val = (float)n; #endif expo = alias.uword_val & expo_mask; /* extracting exponent */ expo >>= mantissa_bits; expo -= bias; /* Subtracting bias */ /* extracting first 4 bits of mantissa, this will help select correct poly */ /* note mantissa of 0.5 is 0x0000000000000 not 0x1000000000000 */ table_index = alias.uword_val & table_mask; table_index >>= (mantissa_bits - 4); /* extracting decimal part, 0.5 <= dec <= 1 */ ret = alias.uword_val & mantissa_mask; ret |= bias_hex; alias.uword_val = ret; dec = alias.double_val; rem = expo % 3; expo /= 3; /* cube root of 2^expo */ factor = factor_table[rem]; /* select factor */ /* Calculating cube root of dec using chebyshev approximation polynomial */ /* Evaluating approx polynomial at (dec) by Estrin's scheme */ dec2 = dec*dec; root = (coeff[table_index][0] + coeff[table_index][1] * dec); root += (coeff[table_index][2] * dec2); mul = UWORD(1) << expo; /* mul = 2^expo */ root *= mul; /* dec^(1/3) * 2^(expo/3) */ root *= factor; /* root*= (expo%3)^(1/3) */ ret = root; /* In case ret^3 or (ret+1)^3 will cause overflow */ if (ret >= upper_limit) { if (n >= upper_limit * upper_limit * upper_limit) return upper_limit; ret = upper_limit - 1; } while (ret * ret * ret <= n) { (ret) += 1; if (ret == upper_limit) break; } while (ret * ret * ret > n) (ret) -= 1; return ret; } mp_limb_t n_cbrt_binary_search(mp_limb_t x) { mp_limb_t low, high, mid, p, upper_limit; /* upper_limit is the max cube root possible for one word */ #ifdef FLINT64 upper_limit = 2642245; /* 2642245 < (2^64)^(1/3) */ #else upper_limit = 1625; /* 1625 < (2^32)^(1/3) */ #endif low = 0; high = UWORD(1) << ((FLINT_BIT_COUNT(x) + 2) / 3); if (high > upper_limit) /* cube cannot be greater than upper_limit */ high = upper_limit; /* binary search for cube root */ while (low < high) { mid = (high + low) / 2; p = mid + 1; p = p * p * p; if (p == x) return mid + 1; else if (p > x) high = mid; else low = mid + 1; } return low; } double n_cbrt_estimate(double a) { typedef union { slong uword_val; #if FLINT64 double double_val; #else float double_val; #endif } uni; uni alias; ulong n, hi, lo; #ifdef FLINT64 const mp_limb_t mul_factor = UWORD(6148914691236517205); slong s = UWORD(4607182418800017408); /* ((1 << 10) - 1) << 52 */ #else const mp_limb_t mul_factor = UWORD(1431655765); slong s = UWORD(1065353216); /* ((1 << 7) - 1 << 23) */ #endif alias.double_val = a; n = alias.uword_val; n -= s; umul_ppmm(hi, lo, n, mul_factor); n = hi; n += s; alias.uword_val = n; return alias.double_val; } mp_limb_t n_cbrtrem(mp_limb_t* remainder, mp_limb_t n) { mp_limb_t base; if (!n) { *remainder = 0; return 0; } base = n_cbrt(n); *remainder = n - base * base * base; return base; } flint-3.1.3/src/ulong_extras/cleanup_primes.c000066400000000000000000000013541461254215100213110ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" void n_cleanup_primes(void) { int i; for (i = 0; i < _flint_primes_used; i++) { if (i < _flint_primes_used - 1 && _flint_primes[i] == _flint_primes[i+1]) continue; flint_free(_flint_primes[i]); flint_free(_flint_prime_inverses[i]); } _flint_primes_used = 0; } flint-3.1.3/src/ulong_extras/clog.c000066400000000000000000000041631461254215100172300ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "gmpcompat.h" #include "ulong_extras.h" mp_limb_t n_clog(mp_limb_t n, mp_limb_t b) { mp_limb_t r, p, t, phi; r = 0; p = 1; while (1) { umul_ppmm(phi, t, p, b); if (t <= n && !phi) { r++; p = t; } else return r + (p != n); } } /* return ceil(log_b(2^n)) */ ulong n_clog_2exp(ulong n, ulong b) { slong prec = FLINT_BITS; mpfr_t A, B, C; mpz_t Z; ulong r; if (n == 0) return 0; if ((b & (b - 1)) == 0) { ulong log2b = 1; while (b > 2) { b = b >> 1; log2b++; } return n/log2b + (n%log2b != 0); } mpfr_init2(A, prec); mpfr_init2(B, prec); mpfr_init2(C, prec); mpz_init(Z); do { mpfr_set_prec(A, prec); mpfr_set_prec(B, prec); mpfr_set_prec(C, prec); /* compute A >= n/log2(b) */ flint_mpz_set_ui(Z, n); mpfr_set_z(C, Z, MPFR_RNDA); flint_mpz_set_ui(Z, b); mpfr_set_z(B, Z, MPFR_RNDZ); mpfr_log2(B, B, MPFR_RNDZ); mpfr_div(A, C, B, MPFR_RNDA); mpfr_get_z(Z, A, MPFR_RNDA); r = flint_mpz_get_ui(Z); /* compute A <= n/log2(b) */ flint_mpz_set_ui(Z, n); mpfr_set_z(C, Z, MPFR_RNDZ); flint_mpz_set_ui(Z, b); mpfr_set_z(B, Z, MPFR_RNDA); mpfr_log2(B, B, MPFR_RNDA); mpfr_div(A, C, B, MPFR_RNDZ); mpfr_get_z(Z, A, MPFR_RNDA); prec += FLINT_BITS; } while (r != flint_mpz_get_ui(Z)); mpfr_clear(A); mpfr_clear(B); mpfr_clear(C); mpz_clear(Z); return r; } flint-3.1.3/src/ulong_extras/compute_primes.c000066400000000000000000000057771461254215100213530ustar00rootroot00000000000000/* Copyright (C) 2009 Tom Boothby Copyright (C) 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD #include static pthread_once_t primes_initialised = PTHREAD_ONCE_INIT; pthread_mutex_t primes_lock; #endif const unsigned int flint_primes_small[] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97, 101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181, 191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277, 281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383, 389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487, 491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601, 607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709, 719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827, 829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947, 953,967,971,977,983,991,997,1009,1013,1019,1021 }; /* _flint_primes[i] holds an array of 2^i primes */ FLINT_TLS_PREFIX mp_limb_t * _flint_primes[FLINT_BITS]; FLINT_TLS_PREFIX double * _flint_prime_inverses[FLINT_BITS]; FLINT_TLS_PREFIX int _flint_primes_used = 0; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD void n_compute_primes_init() { pthread_mutex_init(&primes_lock, NULL); } #endif void n_compute_primes(ulong num_primes) { int i, m; ulong num_computed; #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_once(&primes_initialised, n_compute_primes_init); pthread_mutex_lock(&primes_lock); #endif m = FLINT_CLOG2(num_primes); if (_flint_primes_used == 0) flint_register_cleanup_function(n_cleanup_primes); if (m >= _flint_primes_used) { n_primes_t iter; num_computed = UWORD(1) << m; _flint_primes[m] = flint_malloc(sizeof(mp_limb_t) * num_computed); _flint_prime_inverses[m] = flint_malloc(sizeof(double) * num_computed); n_primes_init(iter); for (i = 0; i < num_computed; i++) { _flint_primes[m][i] = n_primes_next(iter); _flint_prime_inverses[m][i] = n_precompute_inverse(_flint_primes[m][i]); } n_primes_clear(iter); /* copy to lower power-of-two slots */ for (i = m - 1; i >= _flint_primes_used; i--) { _flint_primes[i] = _flint_primes[m]; _flint_prime_inverses[i] = _flint_prime_inverses[m]; } _flint_primes_used = m + 1; } #if FLINT_REENTRANT && !FLINT_USES_TLS && FLINT_USES_PTHREAD pthread_mutex_unlock(&primes_lock); #endif } flint-3.1.3/src/ulong_extras/discrete_log_bsgs.c000066400000000000000000000042001461254215100217550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2016 Pascal Molin This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" typedef struct apow { ulong k; ulong ak; } apow_t; typedef struct { ulong n; double ninv; ulong m; ulong am; apow_t * table; } bsgs_struct; typedef bsgs_struct bsgs_t[1]; static int apow_cmp(const apow_t * x, const apow_t * y) { return (x->ak < y->ak) ? -1 : (x->ak > y->ak); } /* set size of table m=sqrt(nk) to compute k logs in a group of size n */ static void bsgs_table_init(bsgs_t t, ulong a, ulong n, ulong m) { ulong k, ak; t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); t->n = n; t->ninv = n_precompute_inverse(n); t->m = m; for (k = 0, ak = 1; k < m; k++) { t->table[k].k = k; t->table[k].ak = ak; ak = n_mulmod_precomp(ak, a, n, t->ninv); } t->am = n_invmod(ak, n); qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); } static void bsgs_table_clear(bsgs_t t) { flint_free(t->table); } ulong n_discrete_log_bsgs_table(const bsgs_t t, ulong b) { ulong i; apow_t c, * x; c.k = 0; c.ak = b; for (i = 0; i < t->m; i++) { x = bsearch(&c, t->table, t->m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); if (x != NULL) return i * t->m + x->k; c.ak = n_mulmod_precomp(c.ak, t->am, t->n, t->ninv); } flint_throw(FLINT_ERROR, "Exception (n_discrete_log_bsgs). discrete log not found.\n"); } ulong n_discrete_log_bsgs(ulong b, ulong a, ulong n) { ulong m; bsgs_t table; m = ceil(sqrt((double) n)); bsgs_table_init(table, a, n, m); m = n_discrete_log_bsgs_table(table, b); bsgs_table_clear(table); return m; } flint-3.1.3/src/ulong_extras/div2_preinv.c000066400000000000000000000021201461254215100205220ustar00rootroot00000000000000/* Copyright (C) 2009, 2010, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" /* Method of Niels Moller and Torbjorn Granlund see paper: Improved Division by Invariant Integers: (algorithm 4) https://gmplib.org/~tege/division-paper.pdf */ ulong n_div2_preinv(ulong a, ulong n, ulong ninv) { ulong norm, q1, q0, r; FLINT_ASSERT(n != 0); norm = flint_clz(n); n <<= norm; { const ulong u1 = r_shift(a, FLINT_BITS - norm); const ulong u0 = (a << norm); umul_ppmm(q1, q0, ninv, u1); add_ssaaaa(q1, q0, q1, q0, u1, u0); q1++; r = u0 - q1 * n; if (r > q0) { r += n; q1--; } return (r < n) ? q1 : q1 + 1; } } flint-3.1.3/src/ulong_extras/divides.c000066400000000000000000000013551461254215100177330ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" int n_divides(mp_limb_t * q, mp_limb_t n, mp_limb_t p) { mp_limb_t quo, rem; if (p == 0) { *q = 0; return n == 0; } /* purportedly the compiler optimises this */ quo = n/p; rem = n%p; if (rem == 0) { *q = quo; return 1; } else { *q = 0; return 0; } } flint-3.1.3/src/ulong_extras/divrem2_precomp.c000066400000000000000000000026531461254215100214030ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_divrem2_precomp(mp_limb_t * q, mp_limb_t a, mp_limb_t n, double npre) { mp_limb_t quot; slong rem; if (a < n) { (*q) = UWORD(0); return a; } if ((mp_limb_signed_t) n < WORD(0)) { (*q) = UWORD(1); return a - n; } if (n == 1) { quot = a; rem = 0; } else { quot = (ulong) ( a * npre); rem = a - quot * n; } if (rem < (mp_limb_signed_t) (-n)) quot -= (mp_limb_t) ((double) (-rem) * npre); else if (rem >= (slong) n) quot += (mp_limb_t) ((double) rem * npre); else if (rem < WORD(0)) { (*q) = quot - 1; return rem + n; } else { (*q) = quot; return rem; } rem = a - quot * n; if (rem >= (slong) n) { (*q) = quot + 1; return rem - n; } else if (rem < WORD(0)) { (*q) = quot - 1; return rem + n; } else { (*q) = quot; return rem; } } flint-3.1.3/src/ulong_extras/divrem2_preinv.c000066400000000000000000000022601461254215100212330ustar00rootroot00000000000000/* Copyright (C) 2009, 2010, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" /* Method of Niels Moller and Torbjorn Granlund see paper: Improved Division by Invariant Integers: (algorithm 4) https://gmplib.org/~tege/division-paper.pdf */ ulong n_divrem2_preinv(ulong * q, ulong a, ulong n, ulong ninv) { ulong norm, q1, q0, r; FLINT_ASSERT(n != 0); norm = flint_clz(n); n <<= norm; { const ulong u1 = r_shift(a, FLINT_BITS - norm); const ulong u0 = (a << norm); umul_ppmm(q1, q0, ninv, u1); add_ssaaaa(q1, q0, q1, q0, u1, u0); (*q) = q1 + 1; r = u0 - (*q) * n; if (r > q0) { r += n; (*q)--; } if (r >= n) { (*q)++; r -= n; } return r >> norm; } } flint-3.1.3/src/ulong_extras/euler_phi.c000066400000000000000000000013451461254215100202570ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_euler_phi(mp_limb_t n) { int i; mp_limb_t phi; n_factor_t fac; if (n < 2) return n; n_factor_init(&fac); n_factor(&fac, n, 1); phi = UWORD(1); for (i = 0; i < fac.num; i++) phi *= (fac.p[i] - 1) * n_pow(fac.p[i], fac.exp[i] - 1); return phi; } flint-3.1.3/src/ulong_extras/factor.c000066400000000000000000000045431461254215100175640ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" static int is_prime(mp_limb_t n, int proved) { return proved ? n_is_prime(n) : n_is_probabprime(n); } void n_factor(n_factor_t * factors, mp_limb_t n, int proved) { ulong factor_arr[FLINT_MAX_FACTORS_IN_LIMB]; ulong exp_arr[FLINT_MAX_FACTORS_IN_LIMB]; ulong factors_left; ulong exp; mp_limb_t cofactor, factor, cutoff; factors->num = 0; cofactor = n_factor_trial(factors, n, FLINT_FACTOR_TRIAL_PRIMES); if (cofactor == UWORD(1)) return; if (is_prime(cofactor, proved)) { n_factor_insert(factors, cofactor, UWORD(1)); return; } factor_arr[0] = cofactor; factors_left = 1; exp_arr[0] = 1; cutoff = FLINT_FACTOR_TRIAL_CUTOFF; while (factors_left > 0) { factor = factor_arr[factors_left - 1]; if (factor >= cutoff) { if ((cofactor = n_factor_power235(&exp, factor))) { exp_arr[factors_left - 1] *= exp; factor_arr[factors_left - 1] = factor = cofactor; } if ((factor >= cutoff) && !is_prime(factor, proved)) { if (( #if FLINT64 (factor < FLINT_FACTOR_ONE_LINE_MAX) && #endif (cofactor = n_factor_one_line(factor, FLINT_FACTOR_ONE_LINE_ITERS))) || (cofactor = n_factor_pp1_wrapper(factor)) || (cofactor = n_factor_SQUFOF(factor, FLINT_FACTOR_SQUFOF_ITERS))) { exp_arr[factors_left] = exp_arr[factors_left - 1]; factor_arr[factors_left] = cofactor; factor_arr[factors_left - 1] /= cofactor; factors_left++; } else { flint_throw(FLINT_ERROR, "Exception (n_factor). Failed to factor %wd.\n", n); } } else { n_factor_insert(factors, factor, exp_arr[factors_left - 1]); factors_left--; } } else { n_factor_insert(factors, factor, exp_arr[factors_left - 1]); factors_left--; } } } flint-3.1.3/src/ulong_extras/factor_SQUFOF.c000066400000000000000000000067101461254215100206450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t _ll_factor_SQUFOF(mp_limb_t n_hi, mp_limb_t n_lo, ulong max_iters) { mp_limb_t n[2]; mp_limb_t sqrt[2]; mp_limb_t rem[2]; slong num, sqroot, p, q; mp_limb_t l, l2, iq, pnext; mp_limb_t qarr[50]; mp_limb_t qupto, qlast, t, r = 0; ulong i, j; n[0] = n_lo; n[1] = n_hi; if (n_hi) num = mpn_sqrtrem(sqrt, rem, n, 2); else num = ((sqrt[0] = n_sqrtrem(rem, n_lo)) != UWORD(0)); sqroot = sqrt[0]; p = sqroot; q = rem[0]; if ((q == 0) || (num == 0)) { return sqroot; } l = 1 + 2*n_sqrt(2*p); l2 = l/2; qupto = 0; qlast = 1; for (i = 0; i < max_iters; i++) { iq = (sqroot + p)/q; pnext = iq*q - p; if (q <= l) { if ((q & UWORD(1)) == UWORD(0)) { qarr[qupto] = q/2; qupto++; if (qupto >= UWORD(50)) return UWORD(0); } else if (q <= l2) { qarr[qupto] = q; qupto++; if (qupto >= UWORD(50)) return UWORD(0); } } t = qlast + iq*(p - pnext); qlast = q; q = t; p = pnext; if ((i & 1) == 1) continue; if (!n_is_square(q)) continue; r = n_sqrt(q); if (qupto == UWORD(0)) break; for (j = 0; j < qupto; j++) if (r == qarr[j]) goto cont; break; cont: ; if (r == UWORD(1)) return UWORD(0); } if (i == max_iters) return UWORD(0); /* taken too much time, give up */ qlast = r; p = p + r*((sqroot - p)/r); umul_ppmm(rem[1], rem[0], p, p); sub_ddmmss(sqrt[1], sqrt[0], n[1], n[0], rem[1], rem[0]); if (sqrt[1]) { int norm; norm = flint_clz(qlast); udiv_qrnnd(q, rem[0], (sqrt[1] << norm) + r_shift(sqrt[0], FLINT_BITS - norm), sqrt[0] << norm, qlast << norm); rem[0] >>= norm; } else { q = sqrt[0]/qlast; } for (j = 0; j < max_iters; j++) { iq = (sqroot + p)/q; pnext = iq*q - p; if (p == pnext) break; t = qlast + iq*(p - pnext); qlast = q; q = t; p = pnext; } if (j == max_iters) return UWORD(0); /* taken too much time, give up */ if ((q & UWORD(1)) == UWORD(0)) q /= UWORD(2); return q; } mp_limb_t n_factor_SQUFOF(mp_limb_t n, ulong iters) { mp_limb_t factor = _ll_factor_SQUFOF(UWORD(0), n, iters); mp_limb_t multiplier; mp_limb_t quot, rem; ulong i; for (i = 1; (i < FLINT_NUM_PRIMES_SMALL) && !factor; i++) { mp_limb_t multn[2]; multiplier = flint_primes_small[i]; umul_ppmm(multn[1], multn[0], multiplier, n); factor = _ll_factor_SQUFOF(multn[1], multn[0], iters); if (factor) { quot = factor/multiplier; rem = factor - quot*multiplier; if (!rem) factor = quot; if ((factor == UWORD(1)) || (factor == n)) factor = UWORD(0); } } if (i == FLINT_NUM_PRIMES_SMALL) return UWORD(0); return factor; } flint-3.1.3/src/ulong_extras/factor_ecm.c000066400000000000000000000345221461254215100204100ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "nmod_vec.h" static ulong n_ecm_primorial[] = { #ifdef FLINT64 UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030), UWORD(510510), UWORD(9699690), UWORD(223092870), UWORD(6469693230), UWORD(200560490130), UWORD(7420738134810), UWORD(304250263527210), UWORD(13082761331670030), UWORD(614889782588491410) #else UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030), UWORD(510510), UWORD(9699690) #endif }; #ifdef FLINT64 #define num_n_ecm_primorials 15 #else #define num_n_ecm_primorials 9 #endif int n_factor_ecm(mp_limb_t *f, mp_limb_t curves, mp_limb_t B1, mp_limb_t B2, flint_rand_t state, mp_limb_t n) { mp_limb_t P, num, maxD, mmin, mmax, mdiff, prod, maxj, sig; int i, j, ret; n_ecm_t n_ecm_inf; const mp_limb_t *prime_array; n_ecm_inf->normbits = flint_clz(n); n <<= n_ecm_inf->normbits; n_ecm_inf->ninv = n_preinvert_limb(n); n_ecm_inf->one = UWORD(1) << n_ecm_inf->normbits; ret = 0; /************************ STAGE I PRECOMPUTATIONS ************************/ num = n_prime_pi(B1); /* number of primes under B1 */ /* compute list of primes under B1 for stage I */ prime_array = n_primes_arr_readonly(num); /************************ STAGE II PRECOMPUTATIONS ***********************/ maxD = n_sqrt(B2); /* Selecting primorial */ j = 1; while ((j < num_n_ecm_primorials) && (n_ecm_primorial[j] < maxD)) j += 1; P = n_ecm_primorial[j - 1]; mmin = (B1 + (P/2)) / P; mmax = ((B2 - P/2) + P - 1)/P; /* ceil */ maxj = (P + 1)/2; mdiff = mmax - mmin + 1; /* compute GCD_table */ n_ecm_inf->GCD_table = flint_malloc(maxj + 1); for (j = 1; j <= maxj; j += 2) { if ((j%2) && n_gcd(j, P) == 1) n_ecm_inf->GCD_table[j] = 1; else n_ecm_inf->GCD_table[j] = 0; } /* compute prime table */ n_ecm_inf->prime_table = flint_malloc(mdiff * sizeof(unsigned char*)); for (i = 0; i < mdiff; i++) n_ecm_inf->prime_table[i] = flint_malloc((maxj + 1) * sizeof(unsigned char)); for (i = 0; i < mdiff; i++) { for (j = 1; j <= maxj; j += 2) { n_ecm_inf->prime_table[i][j] = 0; /* if (i + mmin)*D + j is prime, mark 1. Can be possibly prime only if gcd(j, D) = 1 */ if (n_ecm_inf->GCD_table[j] == 1) { prod = (i + mmin)*P + j; if (n_is_prime(prod)) n_ecm_inf->prime_table[i][j] = 1; prod = (i + mmin)*P - j; if (n_is_prime(prod)) n_ecm_inf->prime_table[i][j] = 1; } } } /****************************** TRY "CURVES" *****************************/ for (j = 0; j < curves; j++) { sig = n_randint(state, n >> n_ecm_inf->normbits); sig = n_addmod(sig, 7, n >> n_ecm_inf->normbits); sig <<= n_ecm_inf->normbits; /************************ SELECT CURVE ************************/ if (n_factor_ecm_select_curve(f, sig, n, n_ecm_inf)) { /* Found factor while selecting curve, very very lucky :) */ (*f) >>= n_ecm_inf->normbits; ret = -1; goto cleanup; } /************************** STAGE I ***************************/ ret = n_factor_ecm_stage_I(f, prime_array, num, B1, n, n_ecm_inf); if (ret) { /* Found factor after stage I */ (*f) >>= n_ecm_inf->normbits; ret = 1; goto cleanup; } /************************** STAGE II ***************************/ ret = n_factor_ecm_stage_II(f, B1, B2, P, n, n_ecm_inf); if (ret) { /* Found factor after stage II */ (*f) >>= n_ecm_inf->normbits; ret = 2; goto cleanup; } } cleanup: flint_free(n_ecm_inf->GCD_table); for (i = 0; i < mdiff; i++) flint_free(n_ecm_inf->prime_table[i]); flint_free(n_ecm_inf->prime_table); return ret; } /* P (x : z) = P1 (x1 : z1) + P2 (x2 : z2) where P0 (x0 : zo) is P - Q */ /* Coordinates of P : x = 4 * z0 * (x1 * x2 - z1 * z2)^2 mod n z = 4 * x0 * (x2 * z1 - x1 * z2)^2 mod n */ void n_factor_ecm_add(mp_limb_t *x, mp_limb_t *z, mp_limb_t x1, mp_limb_t z1, mp_limb_t x2, mp_limb_t z2, mp_limb_t x0, mp_limb_t z0, mp_limb_t n, n_ecm_t n_ecm_inf) { mp_limb_t u, v, w; if (z1 == 0) { *x = x2; *z = z2; return; } if (z2 == 0) { *x = x1; *z = z1; return; } if (z0 == 0) { n_factor_ecm_double(x, z, x1, z1, n, n_ecm_inf); return; } u = n_submod(x2, z2, n); /* u = (x2 - z2) */ v = n_addmod(x1, z1, n); /* v = (x1 + z1) */ /* u = (x2 - z2) * (x1 + z1) */ u = n_mulmod_preinv(u, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); v = n_submod(x1, z1, n); /* v = (x1 - z1) */ w = n_addmod(x2, z2, n); /* w = (x2 + z2) */ /* v = (x1 - z1) * (x2 + z2) */ v = n_mulmod_preinv(v, w, n, n_ecm_inf->ninv, n_ecm_inf->normbits); w = n_addmod(u, v, n); /* w = 2 * (x1 * x2 - z1 * z2) */ v = n_submod(v, u, n); /* v = 2 * (x2 * z1 - x1 * z2) */ /* w = 4 * (x1 * x2 - z1 * z2)^2 */ w = n_mulmod_preinv(w, w, n, n_ecm_inf->ninv, n_ecm_inf->normbits); /* v = 4 * (x2 * z1 - x1 * z2)^2 */ v = n_mulmod_preinv(v, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); /* x = 4 * z0 * (x1 * x2 - z1 * z2)^2 */ *x = n_mulmod_preinv(z0, w, n, n_ecm_inf->ninv, n_ecm_inf->normbits); /* z = 4 * x0 * (x2 * z1 - x1 * z2)^2 */ *z = n_mulmod_preinv(x0, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); } /* P (x : z) = 2 * P1 (x0 : z0) */ /* Coordinates of P : x = (x0 + z0)^2 * (x0 - z0)^2 mod n z = 4 * x0 * z0 * ((x0 - z0)^2 + a24 * 4 * x0 * z0) mod n */ /* a24 = (a + 2) / 4 mod n */ void n_factor_ecm_double(mp_limb_t *x, mp_limb_t *z, mp_limb_t x0, mp_limb_t z0, mp_limb_t n, n_ecm_t n_ecm_inf) { mp_limb_t u, v, w; if (z0 == 0) { *x = x0; *z = 0; return; } u = n_addmod(x0, z0, n); u = n_mulmod_preinv(u, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits); v = n_submod(x0, z0, n); v = n_mulmod_preinv(v, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); *x = n_mulmod_preinv(u, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); w = n_submod(u, v, n); u = n_mulmod_preinv(w, n_ecm_inf->a24, n, n_ecm_inf->ninv, n_ecm_inf->normbits); u = n_addmod(u, v, n); *z = n_mulmod_preinv(w, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits); } /* P (x0 : z0) <- kP using Montgomery ladder algorithm */ void n_factor_ecm_mul_montgomery_ladder(mp_limb_t *x, mp_limb_t *z, mp_limb_t x0, mp_limb_t z0, mp_limb_t k, mp_limb_t n, n_ecm_t n_ecm_inf) { mp_limb_t x1, z1, x2, z2, len; /* Q (x1 : z1), P (x2 : z2) */ if (k == 0) { *x = 0; *z = 0; return; } if (k == 1) { *x = x0; *z = z0; return; } x1 = x0; /* Q <- P0 */ z1 = z0; x2 = 0; z2 = 0; n_factor_ecm_double(&x2, &z2, x0, z0, n, n_ecm_inf); /* P <- 2P0 */ len = n_sizeinbase(k, 2) - 2; while (1) { if (((UWORD(1) << len) & k) != 0) /* ith bit is 1 */ { /* Q <- P + Q */ n_factor_ecm_add(&x1, &z1, x1, z1, x2, z2, x0, z0, n, n_ecm_inf); /* P <- 2 * P */ n_factor_ecm_double(&x2, &z2, x2, z2, n, n_ecm_inf); } else { /* P <- P + Q */ n_factor_ecm_add(&x2, &z2, x1, z1, x2, z2, x0, z0, n, n_ecm_inf); /* Q <- 2 * Q */ n_factor_ecm_double(&x1, &z1, x1, z1, n, n_ecm_inf); } if (len == 0) break; else len -= 1; } *x = x1; *z = z1; } int n_factor_ecm_select_curve(mp_limb_t *f, mp_limb_t sig, mp_limb_t n, n_ecm_t n_ecm_inf) { mp_limb_t u, v, w, t, hi, lo; mp_ptr a; int ret = 0; TMP_INIT; TMP_START; a = TMP_ALLOC(2 * sizeof(mp_limb_t)); u = sig; /* v = sig * 4 */ v = n_mulmod_preinv(u, UWORD(4) << n_ecm_inf->normbits, n, n_ecm_inf->ninv, n_ecm_inf->normbits); /* w = sig ^ 2 */ w = n_mulmod_preinv(u, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits); u = n_submod(w, UWORD(5) << n_ecm_inf->normbits, n); /* u = sig^2 - 5 */ /* w = u * u */ w = n_mulmod_preinv(u, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits); /* x = u * u * u */ n_ecm_inf->x = n_mulmod_preinv(w, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits); /* w = v * v */ w = n_mulmod_preinv(v, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); /* z = v * v * v */ n_ecm_inf->z = n_mulmod_preinv(w, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); w = n_mulmod_preinv(n_ecm_inf->x, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); t = n_mulmod_preinv(w, UWORD(4) << n_ecm_inf->normbits, n, n_ecm_inf->ninv, n_ecm_inf->normbits); w = n_mulmod_preinv(u, UWORD(3) << n_ecm_inf->normbits, n, n_ecm_inf->ninv, n_ecm_inf->normbits); u = n_submod(v, u, n); v = n_addmod(v, w, n); w = n_mulmod_preinv(u, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits); u = n_mulmod_preinv(u, w, n, n_ecm_inf->ninv, n_ecm_inf->normbits); n_ecm_inf->a24 = n_mulmod_preinv(u, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); v = n_mulmod_preinv(t, n_ecm_inf->z, n, n_ecm_inf->ninv, n_ecm_inf->normbits); *f = n_gcdinv(&u, v, n); if (*f == n) { goto cleanup; } else if (*f > n_ecm_inf->one) { ret = 1; goto cleanup; } a[1] = UWORD(0); a[0] = u; mpn_lshift(a, a, 2, n_ecm_inf->normbits); /* shifting back right */ hi = a[1]; lo = a[0]; u = n_ll_mod_preinv(hi, lo, n, n_ecm_inf->ninv); v = n_mulmod_preinv(u, t, n, n_ecm_inf->ninv, n_ecm_inf->normbits); n_ecm_inf->x = n_mulmod_preinv(n_ecm_inf->x, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); v = n_mulmod_preinv(u, n_ecm_inf->z, n, n_ecm_inf->ninv, n_ecm_inf->normbits); w = n_mulmod_preinv(n_ecm_inf->a24, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits); n_ecm_inf->a24 = n_addmod(w, UWORD(2) << n_ecm_inf->normbits, n); n_ecm_inf->a24 >>= 2; n_ecm_inf->a24 >>= n_ecm_inf->normbits; n_ecm_inf->a24 <<= n_ecm_inf->normbits; n_ecm_inf->z = n_ecm_inf->one; cleanup: TMP_END; return ret; } int n_factor_ecm_stage_I(mp_limb_t *f, const mp_limb_t *prime_array, mp_limb_t num, mp_limb_t B1, mp_limb_t n, n_ecm_t n_ecm_inf) { mp_limb_t times; int i, j, p; for (i = 0; i < num; i++) { p = n_flog(B1, prime_array[i]); times = prime_array[i]; for (j = 1; j <= p; j ++) { n_factor_ecm_mul_montgomery_ladder(&(n_ecm_inf->x), &(n_ecm_inf->z), n_ecm_inf->x, n_ecm_inf->z, times, n, n_ecm_inf); } *f = n_gcd(n_ecm_inf->z, n); if ((*f > n_ecm_inf->one) && (*f < n)) { /* Found factor in stage I */ return 1; } } return 0; } int n_factor_ecm_stage_II(mp_limb_t *f, mp_limb_t B1, mp_limb_t B2, mp_limb_t P, mp_limb_t n, n_ecm_t n_ecm_inf) { mp_limb_t g, Qx, Qz, Rx, Rz, Qdx, Qdz, a, b; mp_limb_t mmin, mmax, maxj, Q0x2, Q0z2; int i, j, ret; mp_ptr arrx, arrz; mmin = (B1 + (P/2)) / P; mmax = ((B2 - P/2) + P - 1)/P; /* ceil */ maxj = (P + 1)/2; g = n_ecm_inf->one; arrx = _nmod_vec_init((maxj >> 1) + 1); arrz = _nmod_vec_init((maxj >> 1) + 1); ret = 0; /* arr[0] = Q0 */ arrx[0] = n_ecm_inf->x; arrz[0] = n_ecm_inf->z; /* Q0x2, Q0z2 = 2Q0 */ n_factor_ecm_double(&Q0x2, &Q0z2, arrx[0], arrz[0], n, n_ecm_inf); /* arr[1] = 3Q0 */ n_factor_ecm_add(arrx + 1, arrz + 1, Q0x2, Q0z2, arrx[0], arrz[0], arrx[0], arrz[0], n, n_ecm_inf); /* For each odd j (j > 3) , compute j * Q0 [x0 :: z0] */ /* jth stored in arr[j/2] */ /* We are adding 2Q0 every time. Need to calculate all j's as (j - 2)Q0 is required for (j + 2)Q0 */ for (j = 2; j <= (maxj >> 1); j += 1) { /* jQ0 = (j - 2)Q0 + 2Q0 Difference is (j - 4)Q0 */ n_factor_ecm_add(arrx + j, arrz + j, arrx[j - 1], arrz[j - 1], Q0x2, Q0z2, arrx[j - 2], arrz[j - 2], n, n_ecm_inf); } /* Q = D * Q_0 */ n_factor_ecm_mul_montgomery_ladder(&Qx, &Qz, n_ecm_inf->x, n_ecm_inf->z, P, n, n_ecm_inf); /* R = mmin * Q */ n_factor_ecm_mul_montgomery_ladder(&Rx, &Rz, Qx, Qz, mmin, n, n_ecm_inf); /* Qd = (mmin - 1) * Q */ n_factor_ecm_mul_montgomery_ladder(&Qdx, &Qdz, Qx, Qz, mmin - 1, n, n_ecm_inf); /* main stage II step */ for (i = mmin; i <= mmax; i ++) { for (j = 1; j <= maxj; j += 2) { if (n_ecm_inf->prime_table[i - mmin][j] == 1) { a = n_mulmod_preinv(Rx, arrz[j >> 1], n, n_ecm_inf->ninv, n_ecm_inf->normbits); b = n_mulmod_preinv(Rz, arrx[j >> 1], n, n_ecm_inf->ninv, n_ecm_inf->normbits); a = n_submod(a, b, n); g = n_mulmod_preinv(g, a, n, n_ecm_inf->ninv, n_ecm_inf->normbits); } } a = Rx; b = Rz; /* R = R + Q difference is stored in Qd, initially (Mmin - 1)Q */ n_factor_ecm_add(&Rx, &Rz, Rx, Rz, Qx, Qz, Qdx, Qdz, n, n_ecm_inf); Qdx = a; Qdz = b; } *f = n_gcd(g, n); if ((*f > n_ecm_inf->one) && (*f < n)) { /* Found factor in stage I */ ret = 1; } _nmod_vec_clear(arrx); _nmod_vec_clear(arrz); return ret; } flint-3.1.3/src/ulong_extras/factor_insert.c000066400000000000000000000013571461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" void n_factor_insert(n_factor_t * factors, mp_limb_t p, ulong exp) { ulong i; for (i = 0; i < factors->num; i++) { if (factors->p[i] == p) break; } if (i != factors->num) { factors->exp[i] += exp; } else { factors->p[i] = p; factors->exp[i] = exp; factors->num++; } } flint-3.1.3/src/ulong_extras/factor_lehman.c000066400000000000000000000032171461254215100211050ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" mp_limb_t n_factor_lehman(mp_limb_t n) { double limit; mp_limb_t cuberoot, k; n_factor_t factors; slong bound; #if FLINT64 /* cannot compute enough primes */ if (n > UWORD(10000000000000000)) return n; #endif if ((n & 1) == 0) return 2; limit = pow(n, 1.0/3.0); cuberoot = (mp_limb_t) ceil(limit); bound = n_prime_pi(cuberoot); n_factor_init(&factors); if (n_factor_trial_range(&factors, n, 0, bound) != n) return factors.p[0]; if ((factors.p[0] = n_factor_one_line(n, FLINT_FACTOR_ONE_LINE_ITERS))) if (factors.p[0] != n) return factors.p[0]; for (k = 1; k <= cuberoot + 1; k++) { double low = 2.0*sqrt((double) k)*sqrt((double) n); mp_limb_t x = (mp_limb_t) ceil(low - 0.0001); mp_limb_t end = (mp_limb_t) floor(0.0001 + low + pow(n, 1.0/6.0)/((double) 4.0*sqrt((double) k))); mp_limb_t sub = k*n*4; for ( ; x <= end; x++) { mp_limb_t p, sq = x*x - sub; if (n_is_square(sq)) { sq = sqrt((double) sq); p = n_gcd(n, x - sq); if (p != 1) return p; } } } return n; } flint-3.1.3/src/ulong_extras/factor_one_line.c000066400000000000000000000022351461254215100214300ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2009 Thomas Boothby This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #define FLINT_ONE_LINE_MULTIPLIER 480 mp_limb_t n_factor_one_line(mp_limb_t n, ulong iters) { mp_limb_t orig_n = n, in, square, sqrti, mod, factor, factoring = iters, iin; n *= FLINT_ONE_LINE_MULTIPLIER; iin = 0; in = n; while (factoring && (iin < in)) { sqrti = n_sqrt(in); sqrti++; square = sqrti*sqrti; mod = square - in; if (n_is_square(mod)) { factor = n_sqrt(mod); sqrti -= factor; factor = n_gcd(orig_n, sqrti); if (factor != UWORD(1)) { return factor; } } factoring--; iin = in; in += n; } return 0; } flint-3.1.3/src/ulong_extras/factor_partial.c000066400000000000000000000050011461254215100212660ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" int is_prime2(mp_limb_t n, int proved) { if (proved) return n_is_prime(n); else return n_is_probabprime(n); } mp_limb_t n_factor_partial(n_factor_t * factors, mp_limb_t n, mp_limb_t limit, int proved) { ulong factor_arr[FLINT_MAX_FACTORS_IN_LIMB]; ulong exp_arr[FLINT_MAX_FACTORS_IN_LIMB]; ulong factors_left; ulong exp; mp_limb_t cofactor, factor, cutoff, prod; cofactor = n_factor_trial_partial(factors, n, &prod, FLINT_FACTOR_TRIAL_PRIMES, limit); if (prod > limit) return cofactor; if ( cofactor == 1 ) { return cofactor; } if (is_prime2(cofactor, proved)) { n_factor_insert(factors, cofactor, UWORD(1)); return 1; } factor_arr[0] = cofactor; factors_left = 1; exp_arr[0] = 1; cutoff = FLINT_FACTOR_TRIAL_CUTOFF; while (factors_left > 0 && prod <= limit) { factor = factor_arr[factors_left - 1]; if (factor >= cutoff) { if ((cofactor = n_factor_power235(&exp, factor))) { exp_arr[factors_left - 1] *= exp; factor_arr[factors_left - 1] = factor = cofactor; } if ((factor >= cutoff) && !is_prime2(factor, proved)) { if (( #if FLINT64 (factor < FLINT_FACTOR_ONE_LINE_MAX) && #endif (cofactor = n_factor_one_line(factor, FLINT_FACTOR_ONE_LINE_ITERS))) || (cofactor = n_factor_SQUFOF(factor, FLINT_FACTOR_SQUFOF_ITERS))) { exp_arr[factors_left] = exp_arr[factors_left - 1]; factor_arr[factors_left] = cofactor; factor_arr[factors_left - 1] /= cofactor; factors_left++; } else { flint_throw(FLINT_ERROR, "Error (n_factor_partial). Failed to factor %wd.\n", n); } } else { n_factor_insert(factors, factor, exp_arr[factors_left - 1]); prod *= n_pow(factor, exp_arr[factors_left - 1]); factors_left--; } } else { n_factor_insert(factors, factor, exp_arr[factors_left - 1]); prod *= n_pow(factor, exp_arr[factors_left - 1]); factors_left--; } } return n/prod; } flint-3.1.3/src/ulong_extras/factor_pollard_brent.c000066400000000000000000000071441461254215100224730ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_sqr_and_add_a(mp_limb_t y, mp_limb_t a, mp_limb_t n, mp_limb_t ninv, mp_limb_t normbits) { mp_limb_t hi, lo; y = n_mulmod_preinv(y, y, n, ninv, normbits); add_ssaaaa(hi, lo, UWORD(0), y, UWORD(0), a); if (hi == 0) { y = lo; if (y > n) y -= n; } else sub_ddmmss(hi, y, hi, lo, 0, n); return y; } int n_factor_pollard_brent_single(mp_limb_t *factor, mp_limb_t n, mp_limb_t ninv, mp_limb_t ai, mp_limb_t xi, mp_limb_t normbits, mp_limb_t max_iters) { mp_limb_t iter, i, k, j, minval, m, one_shift_norm, x, y, a, q, ys, subval; int ret; if (n < 4) return 0; /* one shifted by normbits, used for comparisons */ one_shift_norm = UWORD(1) << normbits; q = one_shift_norm; (*factor) = one_shift_norm; y = xi; a = ai; m = 100; iter = 1; do { x = y; k = 0; for (i = 0; i < iter; i++) y = n_sqr_and_add_a(y, a, n, ninv, normbits); do { minval = iter - k; if (m < minval) minval = m; ys = y; for (i = 0; i < minval; i++) { y = n_sqr_and_add_a(y, a, n, ninv, normbits); if (x > y) subval = x - y; else subval = y - x; q = n_mulmod_preinv(q, subval, n, ninv, normbits); } if (q == 0) (*factor) = n; else (*factor) = n_gcd(q, n); k += m; j = ((*factor) == one_shift_norm); } while ((k < iter) && (j)); if (iter > max_iters) break; iter *= 2; } while (j); if ((*factor) == n) { do { ys = n_sqr_and_add_a(ys, a, n, ninv, normbits); if (x > ys) subval = x - ys; else subval = ys - x; if (q == 0) (*factor) = n; else (*factor) = n_gcd(q, n); (*factor) = n_gcd(subval, n); } while ((*factor) == one_shift_norm); /* gcd == 1 */ } ret = 1; if ((*factor) == one_shift_norm) /* gcd == 1 */ ret = 0; else if ((*factor) == n) /* gcd == n*/ ret = 0; return ret; } int n_factor_pollard_brent(mp_limb_t *factor, flint_rand_t state, mp_limb_t n_in, mp_limb_t max_tries, mp_limb_t max_iters) { mp_limb_t normbits, a, x, n, ninv, max; int ret; ret = 0; max = n_in -3; /* 1 <= a <= n - 3 */ normbits = flint_clz(n_in); n = n_in; n <<= normbits; ninv = n_preinvert_limb(n); while (max_tries--) { a = n_randint(state, max); a += 1; max += 1; /* 1 <= x <= n - 1 */ x = n_randint(state, max); x += 1; a <<= normbits; x <<= normbits; ret = n_factor_pollard_brent_single(factor, n, ninv, a, x, normbits, max_iters); if (ret == 1) { if (normbits) (*factor) >>= normbits; return 1; } } return ret; } flint-3.1.3/src/ulong_extras/factor_power235.c000066400000000000000000000037351461254215100212340ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart Copyright (C) 2009 Thomas Boothby This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" mp_limb_t n_factor_power235(ulong * exp, mp_limb_t n) { static char mod63[63] = {7,7,4,0,5,4,0,5,6,5,4,4,0,4,4,0,5,4,5,4,4,0, 5,4,0,5,4,6,7,4,0,4,4,0,4,6,7,5,4,0,4,4,0,5, 4,4,5,4,0,5,4,0,4,4,4,6,4,0,5,4,0,4,6}; static char mod61[61] = {7,7,0,3,1,1,0,0,2,3,0,6,1,5,5,1,1,0,0,1,3,4, 1,2,2,1,0,3,2,4,0,0,4,2,3,0,1,2,2,1,4,3,1,0, 0,1,1,5,5,1,6,0,3,2,0,0,1,1,3,0,7}; static char mod44[44] = {7,7,0,2,3,3,0,2,2,3,0,6,7,2,0,2,3,2,0,2,3,6, 0,6,2,3,0,2,2,2,0,2,6,7,0,2,3,3,0,2,2,2,0,6}; static char mod31[31] = {7,7,3,0,3,5,4,1,3,1,1,0,0,0,1,2,3,0,1,1,1,0, 0,2,0,5,4,2,1,2,6}; char t; t = mod31[n%31]; if (!t) return UWORD(0); t &= mod44[n%44]; if (!t) return UWORD(0); t &= mod61[n%61]; if (!t) return UWORD(0); t&= mod63[n%63]; if (t & 1) { double x = sqrt((double) n); mp_limb_t y = (mp_limb_t) (x + 0.5); if (n == n_pow(y, 2)) { *exp = 2; return y; } } if (t & 2) { double x = pow((double) n, 1.0 / 3.0); mp_limb_t y = (mp_limb_t) (x + 0.5); if (n == n_pow(y, 3)) { *exp = 3; return y; } } if (t & 4) { double x = pow((double) n, 1.0 / 5.0); mp_limb_t y = (mp_limb_t) (x + 0.5); if (n == n_pow(y, 5)) { *exp = 5; return y; } } return UWORD(0); } flint-3.1.3/src/ulong_extras/factor_pp1.c000066400000000000000000000127361461254215100203470ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" /* bits of n, B1, count */ slong n_factor_pp1_table[][2] = { {2784, 5}, {1208, 2}, {2924, 3}, { 286, 5}, { 58, 5}, { 61, 4}, { 815, 2}, { 944, 2}, { 61, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 606, 1}, {2403, 1}, {2524, 1}, {2924, 1}, {3735, 2}, { 669, 2}, {6092, 3}, {2179, 3}, {3922, 3}, {6717, 4}, {4119, 4}, {2288, 4}, {9004, 3}, {9004, 3}, {9004, 3}}; #define n_pp1_set(x1, y1, x2, y2) \ do { \ x1 = x2; \ y1 = y2; \ } while (0) #define n_pp1_set_ui(x, norm, c) \ do { \ x = (c << norm); \ } while (0) #if 0 /* For debugging */ void n_pp1_print(mp_limb_t x, mp_limb_t y, ulong norm) { if (norm) { x >>= norm; y >>= norm; } flint_printf("[%wu, %wu]", x, y); } #endif #define n_pp1_2k(x, y, n, ninv, x0, norm) \ do { \ const mp_limb_t two = (UWORD(2) << norm); \ y = n_mulmod_preinv(y, x, n, ninv, norm); \ y = n_submod(y, x0, n); \ x = n_mulmod_preinv(x, x, n, ninv, norm); \ x = n_submod(x, two, n); \ } while (0) #define n_pp1_2kp1(x, y, n, ninv, x0, norm) \ do { \ const mp_limb_t two = (UWORD(2) << norm); \ x = n_mulmod_preinv(x, y, n, ninv, norm); \ x = n_submod(x, x0, n); \ y = n_mulmod_preinv(y, y, n, ninv, norm); \ y = n_submod(y, two, n); \ } while (0) void n_pp1_pow_ui(mp_limb_t * x, mp_limb_t * y, ulong exp, mp_limb_t n, mp_limb_t ninv, ulong norm) { const mp_limb_t x0 = *x; const mp_limb_t two = (UWORD(2) << norm); ulong bit = ((UWORD(1) << FLINT_BIT_COUNT(exp)) >> 2); (*y) = n_mulmod_preinv(*x, *x, n, ninv, norm); (*y) = n_submod(*y, two, n); while (bit) { if (exp & bit) n_pp1_2kp1(*x, *y, n, ninv, x0, norm); else n_pp1_2k(*x, *y, n, ninv, x0, norm); bit >>= 1; } } mp_limb_t n_pp1_factor(mp_limb_t n, mp_limb_t x, ulong norm) { if (norm) { n >>= norm; x >>= norm; } x = n_submod(x, 2, n); if (x == 0) return 0; return n_gcd(n, x); } mp_limb_t n_pp1_find_power(mp_limb_t * x, mp_limb_t * y, ulong p, mp_limb_t n, mp_limb_t ninv, ulong norm) { mp_limb_t factor; do { n_pp1_pow_ui(x, y, p, n, ninv, norm); factor = n_pp1_factor(n, *x, norm); } while (factor == 1); return factor; } mp_limb_t n_factor_pp1(mp_limb_t n, ulong B1, ulong c) { slong i, j; mp_limb_t factor = 0; mp_limb_t x, y = 0, oldx, oldy, ninv; ulong pr, oldpr, sqrt, bits0, norm; n_primes_t iter; if ((n % 2) == 0) return 2; n_primes_init(iter); sqrt = n_sqrt(B1); bits0 = FLINT_BIT_COUNT(B1); norm = flint_clz(n); n <<= norm; ninv = n_preinvert_limb(n); n_pp1_set_ui(x, norm, c); /* mul by various prime powers */ pr = 0; oldpr = 0; for (i = 0; pr < B1; ) { j = i + 1024; oldpr = pr; n_pp1_set(oldx, oldy, x, y); for ( ; i < j; i++) { pr = n_primes_next(iter); if (pr < sqrt) { ulong bits = FLINT_BIT_COUNT(pr); ulong exp = bits0 / bits; n_pp1_pow_ui(&x, &y, n_pow(pr, exp), n, ninv, norm); } else n_pp1_pow_ui(&x, &y, pr, n, ninv, norm); } factor = n_pp1_factor(n, x, norm); if (factor == 0) break; if (factor != 1) goto cleanup; } if (pr < B1) /* factor = 0 */ { n_primes_jump_after(iter, oldpr); n_pp1_set(x, y, oldx, oldy); do { pr = n_primes_next(iter); n_pp1_set(oldx, oldy, x, y); if (pr < sqrt) { ulong bits = FLINT_BIT_COUNT(pr); ulong exp = bits0 / bits; n_pp1_pow_ui(&x, &y, n_pow(pr, exp), n, ninv, norm); } else n_pp1_pow_ui(&x, &y, pr, n, ninv, norm); factor = n_pp1_factor(n, x, norm); if (factor == 0) break; if (factor != 1) goto cleanup; } while (1); } else { factor = 0; goto cleanup; } /* factor still 0 */ factor = n_pp1_find_power(&oldx, &oldy, pr, n, ninv, norm); cleanup: n_primes_clear(iter); return factor; } mp_limb_t n_factor_pp1_wrapper(mp_limb_t n) { slong bits = FLINT_BIT_COUNT(n); ulong B1; slong count, i; flint_rand_t state; /* silently fail if trial factoring would always succeed */ if (bits < 31) return 0; B1 = n_factor_pp1_table[bits - 31][0]; count = n_factor_pp1_table[bits - 31][1]; flint_randinit(state); for (i = 0; i < count; i++) { ulong factor; factor = n_factor_pp1(n, B1, n_randint(state, n - 3) + 3); if (factor != 0) { flint_randclear(state); return factor; } } flint_randclear(state); return 0; } flint-3.1.3/src/ulong_extras/factor_trial.c000066400000000000000000000034151461254215100207540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" mp_limb_t n_factor_trial(n_factor_t * factors, mp_limb_t n, ulong num_primes) { return n_factor_trial_range(factors, n, UWORD(0), num_primes); } mp_limb_t n_factor_trial_partial(n_factor_t * factors, mp_limb_t n, mp_limb_t * prod, ulong num_primes, mp_limb_t limit) { unsigned int exp; mp_limb_t p; double ppre; ulong i; const mp_limb_t * primes; const double * inverses; (*prod) = 1; primes = n_primes_arr_readonly(num_primes); inverses = n_prime_inverses_arr_readonly(num_primes); for (i = 0; i < num_primes; i++) { p = primes[i]; if (p*p > n) break; ppre = inverses[i]; exp = n_remove2_precomp(&n, p, ppre); if (exp) { n_factor_insert(factors, p, exp); (*prod) *= n_pow(p, exp); if (*prod > limit) break; } } return n; } mp_limb_t n_factor_trial_range(n_factor_t * factors, mp_limb_t n, ulong start, ulong num_primes) { unsigned int exp; mp_limb_t p; double ppre; ulong i; const mp_limb_t * primes; const double * inverses; primes = n_primes_arr_readonly(num_primes); inverses = n_prime_inverses_arr_readonly(num_primes); for (i = start; i < num_primes; i++) { p = primes[i]; if (p*p > n) break; ppre = inverses[i]; exp = n_remove2_precomp(&n, p, ppre); if (exp) n_factor_insert(factors, p, exp); } return n; } flint-3.1.3/src/ulong_extras/factorial_fast_mod2_preinv.c000066400000000000000000000026551461254215100235750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "nmod.h" #include "nmod_vec.h" #include "nmod_poly.h" mp_limb_t n_factorial_fast_mod2_preinv(ulong n, mp_limb_t p, mp_limb_t pinv) { slong i, m; nmod_t mod; mp_ptr t, u, v; mp_limb_t r, s; if (p == UWORD(1) || n >= p) return UWORD(0); if (n <= 1) return UWORD(1); nmod_init(&mod, p); m = n_sqrt(n); t = _nmod_vec_init(m + 1); u = _nmod_vec_init(m + 1); v = _nmod_vec_init(m + 1); t[0] = UWORD(0); for (i = 1; i < m; i++) t[i] = n_submod(t[i-1], UWORD(1), p); _nmod_poly_product_roots_nmod_vec(u, t, m, mod); for (i = 0; i < m; i++) t[i] = n_mod2_preinv(i * m + 1, p, pinv); _nmod_poly_evaluate_nmod_vec_fast(v, u, m + 1, t, m, mod); r = 1; for (i = 0; i < m; i++) r = n_mulmod2_preinv(r, v[i], mod.n, mod.ninv); for (s = m * m + 1; s <= n; s++) r = n_mulmod2_preinv(r, s, mod.n, mod.ninv); _nmod_vec_clear(t); _nmod_vec_clear(u); _nmod_vec_clear(v); return r; } flint-3.1.3/src/ulong_extras/factorial_mod2_preinv.c000066400000000000000000000033171461254215100225540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" static const mp_limb_t small_factorials[] = { UWORD(1), UWORD(1), UWORD(2), UWORD(6), UWORD(24), UWORD(120), UWORD(720), UWORD(5040), UWORD(40320), UWORD(362880), UWORD(3628800), UWORD(39916800), UWORD(479001600), #if FLINT64 UWORD(6227020800), UWORD(87178291200), UWORD(1307674368000), UWORD(20922789888000), UWORD(355687428096000), UWORD(6402373705728000), UWORD(121645100408832000), UWORD(2432902008176640000), #endif }; #if FLINT64 #define MAX_SMALL_FACTORIAL 20 #else #define MAX_SMALL_FACTORIAL 12 #endif mp_limb_t n_factorial_mod2_preinv(ulong n, mp_limb_t p, mp_limb_t pinv) { mp_limb_t prod, hi, lo; if (n <= MAX_SMALL_FACTORIAL) return n_mod2_preinv(small_factorials[n], p, pinv); if (n >= p) return UWORD(0); if (n >= UWORD(1000000)) return n_factorial_fast_mod2_preinv(n, p, pinv); prod = small_factorials[MAX_SMALL_FACTORIAL]; lo = n; n--; /* TODO: speedup for n in the range of sqrt(UWORD_MAX) */ while (n > MAX_SMALL_FACTORIAL) { umul_ppmm(hi, lo, lo, n); if (hi) { lo = n_ll_mod_preinv(hi, lo, p, pinv); prod = n_mulmod2_preinv(prod, lo, p, pinv); lo = UWORD(1); } n--; } return n_mulmod2_preinv(prod, lo, p, pinv); } flint-3.1.3/src/ulong_extras/flog.c000066400000000000000000000013031461254215100172240ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_flog(mp_limb_t n, mp_limb_t b) { mp_limb_t r, p, phi; r = 0; p = 1; while (1) { umul_ppmm(phi, p, p, b); if (p <= n && !phi) r++; else return r; } } flint-3.1.3/src/ulong_extras/gcdinv.c000066400000000000000000000047561461254215100175660ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" ulong n_gcdinv(ulong * s, ulong x, ulong y) { slong v1, v2, t2; ulong d, r, quot, rem; FLINT_ASSERT(y > x); v1 = 0; v2 = 1; r = x; x = y; /* y and x both have top bit set */ if ((slong) (x & r) < 0) { d = x - r; t2 = v2; x = r; v2 = v1 - v2; v1 = t2; r = d; } /* second value has second msb set */ while ((slong) (r << 1) < 0) { d = x - r; if (d < r) /* quot = 1 */ { t2 = v2; x = r; v2 = v1 - v2; v1 = t2; r = d; } else if (d < (r << 1)) /* quot = 2 */ { x = r; t2 = v2; v2 = v1 - (v2 << 1); v1 = t2; r = d - x; } else /* quot = 3 */ { x = r; t2 = v2; v2 = v1 - 3 * v2; v1 = t2; r = d - (x << 1); } } while (r) { /* overflow not possible due to top 2 bits of r not being set */ if (x < (r << 2)) /* if quot < 4 */ { d = x - r; if (d < r) /* quot = 1 */ { t2 = v2; x = r; v2 = v1 - v2; v1 = t2; r = d; } else if (d < (r << 1)) /* quot = 2 */ { x = r; t2 = v2; v2 = v1 - (v2 << 1); v1 = t2; r = d - x; } else /* quot = 3 */ { x = r; t2 = v2; v2 = v1 - 3 * v2; v1 = t2; r = d - (x << 1); } } else { quot = x / r; rem = x - r * quot; x = r; t2 = v2; v2 = v1 - quot * v2; v1 = t2; r = rem; } } if (v1 < WORD(0)) v1 += y; (*s) = v1; return x; } flint-3.1.3/src/ulong_extras/inlines.c000066400000000000000000000007071461254215100177450ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #define ULONG_EXTRAS_INLINES_C #include "flint.h" #include "ulong_extras.h" flint-3.1.3/src/ulong_extras/is_oddprime.c000066400000000000000000000070461461254215100206050ustar00rootroot00000000000000/* Copyright (C) 2009 Tom Boothby Copyright (C) 2009 William Hart Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #if FLINT64 mp_limb_t FLINT_ODD_PRIME_LOOKUP[] = { 0x816d129a64b4cb6eUL, UWORD(0x2196820d864a4c32), UWORD(0xa48961205a0434c9), UWORD(0x4a2882d129861144), UWORD(0x834992132424030), 0x148a48844225064bUL, UWORD(0xb40b4086c304205), UWORD(0x65048928125108a0), UWORD(0x80124496804c3098), UWORD(0xc02104c941124221), UWORD(0x804490000982d32), UWORD(0x220825b082689681), UWORD(0x9004265940a28948), UWORD(0x6900924430434006), UWORD(0x12410da408088210), UWORD(0x86122d22400c060), UWORD(0x110d301821b0484), UWORD(0x14916022c044a002), 0x92094d204a6400cUL, UWORD(0x4ca2100800522094), UWORD(0xa48b081051018200), UWORD(0x34c108144309a25), UWORD(0x2084490880522502), UWORD(0x241140a218003250), UWORD(0xa41a00101840128), UWORD(0x2926000836004512), UWORD(0x10100480c0618283), 0xc20c26584822006dUL, UWORD(0x4520582024894810), UWORD(0x10c0250219002488), UWORD(0x802832ca01140868), UWORD(0x60901300264b0400) }; #else mp_limb_t FLINT_ODD_PRIME_LOOKUP[] = { 0x64b4cb6eUL, 0x816d129aUL, UWORD(0x864a4c32), 0x2196820dUL, UWORD(0x5a0434c9), UWORD(0xa4896120), UWORD(0x29861144), UWORD(0x4a2882d1), UWORD(0x32424030), UWORD(0x8349921), 0x4225064bUL, UWORD(0x148a4884), UWORD(0x6c304205), UWORD(0xb40b408), UWORD(0x125108a0), UWORD(0x65048928), UWORD(0x804c3098), UWORD(0x80124496), UWORD(0x41124221), UWORD(0xc02104c9), UWORD(0x982d32), UWORD(0x8044900), UWORD(0x82689681), UWORD(0x220825b0), UWORD(0x40a28948), UWORD(0x90042659), UWORD(0x30434006), UWORD(0x69009244), UWORD(0x8088210), UWORD(0x12410da4), UWORD(0x2400c060), UWORD(0x86122d2), UWORD(0x821b0484), UWORD(0x110d301), UWORD(0xc044a002), UWORD(0x14916022), 0x4a6400cUL, UWORD(0x92094d2), UWORD(0x522094), UWORD(0x4ca21008), UWORD(0x51018200), UWORD(0xa48b0810), UWORD(0x44309a25), UWORD(0x34c1081), UWORD(0x80522502), UWORD(0x20844908), UWORD(0x18003250), UWORD(0x241140a2), UWORD(0x1840128), UWORD(0xa41a001), UWORD(0x36004512), UWORD(0x29260008), UWORD(0xc0618283), UWORD(0x10100480), 0x4822006dUL, UWORD(0xc20c2658), UWORD(0x24894810), UWORD(0x45205820), UWORD(0x19002488), UWORD(0x10c02502), UWORD(0x1140868), 0x802832caUL, UWORD(0x264b0400), UWORD(0x60901300) }; #endif int n_is_oddprime_small(mp_limb_t n) { mp_limb_t q = n / 2; mp_limb_t x = (q & (FLINT_BITS - UWORD(1))); return (FLINT_ODD_PRIME_LOOKUP[q / FLINT_BITS] & (UWORD(1) << x)) >> x; } int n_is_oddprime_binary(mp_limb_t n) { ulong diff, prime_lo, prime_hi; const mp_limb_t * primes; n_prime_pi_bounds(&prime_lo, &prime_hi, n); primes = n_primes_arr_readonly(prime_hi + 1); prime_hi--; /* convert to indices of primes in table */ prime_lo--; if (n == primes[prime_hi]) return 1; if (n > primes[prime_hi]) return 0; diff = (prime_hi - prime_lo + 1) / 2; while (1) { ulong diff2; if (primes[prime_lo + diff] <= n) prime_lo += diff; if (diff <= UWORD(1)) break; diff = (diff + 1)/2; diff2 = (prime_hi - prime_lo + 1)/2; if (diff > diff2) diff = diff2; } return (n == primes[prime_lo]); } flint-3.1.3/src/ulong_extras/is_perfect_power.c000066400000000000000000000123271461254215100216440ustar00rootroot00000000000000/* Copyright (C) 2009 Thomas Boothby Copyright (C) 2009, 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int n_is_perfect_power(ulong * root, ulong n) { static unsigned char mod63[63] = {7,7,4,0,5,4,0,5,6,5,4,4,0,4,4,0,5,4,5,4, 4,0,5,4,0,5,4,6,7,4,0,4,4,0,4,6,7,5,4,0,4,4,0,5, 4,4,5,4,0,5,4,0,4,4,4,6,4,0,5,4,0,4,6}; static unsigned char mod61[61] = {7,7,0,3,1,1,0,0,2,3,0,6,1,5,5,1,1,0,0,1, 3,4,1,2,2,1,0,3,2,4,0,0,4,2,3,0,1,2,2,1,4,3,1,0, 0,1,1,5,5,1,6,0,3,2,0,0,1,1,3,0,7}; static unsigned char mod44[44] = {7,7,0,2,3,3,0,2,2,3,0,6,7,2,0,2,3,2,0,2, 3,6,0,6,2,3,0,2,2,2,0,2,6,7,0,2,3,3,0,2,2,2,0,6}; static unsigned char mod31[31] = {7,7,3,0,3,5,4,1,3,1,1,0,0,0,1,2,3,0,1,1, 1,0,0,2,0,5,4,2,1,2,6}; static unsigned char mod72[72] = {7,7,0,0,0,7,0,7,7,7,0,7,0,7,0,0,7,7,0,7, 0,0,0,7,0,7,0,7,0,7,0,7,7,0,0,7,0,7,0,0,7,7,0,7, 0,7,0,7,0,7,0,0,0,7,0,7,7,0,0,7,0,7,0,7,7,7,0,7, 0,0,0,7}; static unsigned char mod49[49] = {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, 0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1}; static unsigned char mod67[67] = {2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}; static unsigned char mod79[79] = {4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,4}; unsigned char t; ulong count, exp, r; /* check for powers 2, 3, 5 */ t = mod31[n%31]; t &= mod44[n%44]; t &= mod61[n%61]; t &= mod63[n%63]; if (t & 1) { ulong y = n_sqrtrem(&r, n); if (r == 0) { *root = y; return 2; } } if (t & 2) { ulong y = n_cbrtrem(&r, n); if (r == 0) if (n == n_pow(y, 3)) { *root = y; return 3; } } if (t & 4) { ulong y = n_rootrem(&r, n, 5); if (r == 0) { *root = y; return 5; } } /* check for power 7, 11, 13 */ t = mod49[n%49]; t |= mod67[n%67]; t |= mod79[n%79]; t &= mod72[n%72]; if (t & 1) { ulong y = n_rootrem(&r, n, 7); if (r == 0) { *root = y; return 7; } } if (t & 2) { ulong y = n_rootrem(&r, n, 11); if (r == 0) { *root = y; return 11; } } if (t & 13) { ulong y = n_rootrem(&r, n, 13); if (r == 0) { *root = y; return 13; } } /* highest power of 2 */ count = flint_ctz(n); n >>= count; if (n == 1) { if (count == 1) return 0; *root = 2; return count; } /* check other powers (exp >= 17, root <= 13 and odd) */ exp = 0; while ((n % 3) == 0) { n /= 3; exp += 1; } if (exp > 0) { if (n == 1 && exp > 1) { if (count == 0) { *root = 3; return exp; } else if (count == exp) { *root = 6; return exp; } else if (count == 2*exp) { *root = 12; return exp; } } return 0; } #if FLINT64 exp = 0; while ((n % 5) == 0) { n /= 5; exp += 1; } if (exp > 0) { if (n == 1 && exp > 1) { if (count == 0) { *root = 5; return exp; } else if (count == exp) { *root = 10; return exp; } } return 0; } if (count > 0) return 0; exp = 0; while ((n % 7) == 0) { n /= 7; exp += 1; } if (exp > 0) { if (n == 1 && exp > 1) { *root = 7; return exp; } return 0; } exp = 0; while ((n % 11) == 0) { n /= 11; exp += 1; } if (exp > 0) { if (n == 1 && exp > 1) { *root = 11; return exp; } return 0; } exp = 0; while ((n % 13) == 0) { n /= 13; exp += 1; } if (exp > 0) { if (n == 1 && exp > 1) { *root = 13; return exp; } return 0; } #endif return 0; } flint-3.1.3/src/ulong_extras/is_perfect_power235.c000066400000000000000000000036131461254215100220740ustar00rootroot00000000000000/* Copyright (C) 2009 Thomas Boothby Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int n_is_perfect_power235(mp_limb_t n) { static unsigned char mod63[63] = {7,7,4,0,5,4,0,5,6,5,4,4,0,4,4,0,5,4,5,4, 4,0,5,4,0,5,4,6,7,4,0,4,4,0,4,6,7,5,4,0,4,4,0,5, 4,4,5,4,0,5,4,0,4,4,4,6,4,0,5,4,0,4,6}; static unsigned char mod61[61] = {7,7,0,3,1,1,0,0,2,3,0,6,1,5,5,1,1,0,0,1, 3,4,1,2,2,1,0,3,2,4,0,0,4,2,3,0,1,2,2,1,4,3,1,0, 0,1,1,5,5,1,6,0,3,2,0,0,1,1,3,0,7}; static unsigned char mod44[44] = {7,7,0,2,3,3,0,2,2,3,0,6,7,2,0,2,3,2,0,2, 3,6,0,6,2,3,0,2,2,2,0,2,6,7,0,2,3,3,0,2,2,2,0,6}; static unsigned char mod31[31] = {7,7,3,0,3,5,4,1,3,1,1,0,0,0,1,2,3,0,1,1, 1,0,0,2,0,5,4,2,1,2,6}; unsigned char t; t = mod31[n%31]; if (!t) return 0; t &= mod44[n%44]; if (!t) return 0; t &= mod61[n%61]; if (!t) return 0; t &= mod63[n%63]; if (t & 1) { double x = sqrt((double) n); mp_limb_t y = (mp_limb_t) (x + 0.5); if (n == n_pow(y, 2)) return 1; } if (t & 2) { double x = pow((double) n, 1.0 / 3.0); mp_limb_t y = (mp_limb_t) (x + 0.5); if (n == n_pow(y, 3)) return 1; } if (t & 4) { double x = pow((double) n, 1.0 / 5.0); mp_limb_t y = (mp_limb_t) (x + 0.5); if (n == n_pow(y, 5)) return 1; } return 0; } flint-3.1.3/src/ulong_extras/is_prime.c000066400000000000000000000157111461254215100201140ustar00rootroot00000000000000/* Copyright (C) 2008 Peter Shrimpton Copyright (C) 2009 William Hart Copyright (C) 2014, 2015 Dana Jacobsen Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" int n_is_prime(mp_limb_t n) { /* flint's "BPSW" checked against Feitsma and Galway's database [1, 2] up to 2^64 by Dana Jacobsen. [1] http://www.janfeitsma.nl/math/psp2/database [2] http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html */ if (n < 11) { if (n == 2 || n == 3 || n == 5 || n == 7) return 1; else return 0; } if (!(n%2) || !(n%3) || !(n%5) || !(n%7)) return 0; if (n < 121) /* 11*11 */ return 1; if (!(n%11) || !(n%13) || !(n%17) || !(n%19) || !(n%23) || !(n%29) || !(n%31) || !(n%37) || !(n%41) || !(n%43) || !(n%47) || !(n%53)) return 0; if (n < 3481) /* 59*59 */ return 1; if (n > 1000000 && (!(n% 59) || !(n% 61) || !(n% 67) || !(n% 71) || !(n% 73) || !(n% 79) || !(n% 83) || !(n% 89) || !(n% 97) || !(n%101) || !(n%103) || !(n%107) || !(n%109) || !(n%113) || !(n%127) || !(n%131) || !(n%137) || !(n%139) || !(n%149))) return 0; return n_is_probabprime(n); } int n_is_prime_pocklington(mp_limb_t n, ulong iterations) { int i, j, pass; mp_limb_t n1, cofactor, b, c, ninv, limit, F, Fsq, det, rootn, val, c1, c2, upper_limit; n_factor_t factors; c = 0; #if FLINT64 upper_limit = 2642246; /* 2642246^3 is approximately 2^64 */ #else upper_limit = 1626; /* 1626^3 is approximately 2^32 */ #endif if (n == 1) return 0; else if (n % 2 == 0) return (n == UWORD(2)); rootn = n_sqrt(n); /* floor(sqrt(n)) */ if (n == rootn*rootn) return 0; n1 = n - 1; n_factor_init(&factors); limit = (mp_limb_t) pow((double)n1, 1.0/3); val = n_pow(limit, 3); while (val < n1 && limit < upper_limit) /* ensuring that limit >= n1^(1/3) */ { limit++; val = n_pow(limit, 3); } cofactor = n_factor_partial(&factors, n1, limit, 1); if (cofactor != 1) /* check that cofactor is coprime to factors found */ { for (i = 0; i < factors.num; i++) { if (factors.p[i] > FLINT_FACTOR_TRIAL_PRIMES_PRIME) { while (cofactor >= factors.p[i] && (cofactor % factors.p[i]) == 0) { factors.exp[i]++; cofactor /= factors.p[i]; } } } } F = n1/cofactor; /* n1 = F*cofactor */ Fsq = F*F; if (F <= rootn) /* cube root method applicable only if n^1/3 <= F < n^1/2 */ { c2 = n1/(Fsq); /* expressing n as c2*F^2 + c1*F + 1 */ c1 = (n1 - c2*Fsq )/F; det = c1*c1 - 4*c2; if (n_is_square(det)) /* BSL's test for (n^1/3 <= F < n^1/2) */ return 0; } ninv = n_preinvert_limb(n); c = 1; for (i = factors.num - 1; i >= 0; i--) { mp_limb_t exp = n1 / factors.p[i]; pass = 0; for (j = 2; j < iterations && pass == 0; j++) { b = n_powmod2_preinv(j, exp, n, ninv); if (n_powmod2_ui_preinv(b, factors.p[i], n, ninv) != UWORD(1)) return 0; b = n_submod(b, UWORD(1), n); if (b != UWORD(0)) { c = n_mulmod2_preinv(c, b, n, ninv); pass = 1; } else if (c == 0) return 0; } if (j == iterations) return -1; } return (n_gcd(n, c) == UWORD(1)); } mp_limb_t flint_pseudosquares[] = {17, 73, 241, 1009, 2641, 8089, 18001, 53881, 87481, 117049, 515761, 1083289, 3206641, 3818929, 9257329, 22000801, 48473881, 48473881, 175244281, 427733329, 427733329, 898716289u, 2805544681u, 2805544681u, 2805544681u #ifndef FLINT64 }; #else , 10310263441u, 23616331489u, 85157610409u, 85157610409u, 196265095009u, 196265095009u, 2871842842801u, 2871842842801u, 2871842842801u, 26250887023729u, 26250887023729u, 112434732901969u, 112434732901969u, 112434732901969u, 178936222537081u, 178936222537081u, 696161110209049u, 696161110209049u, 2854909648103881u, 6450045516630769u, 6450045516630769u, 11641399247947921u, 11641399247947921u, 190621428905186449u, 196640248121928601u, 712624335095093521u, 1773855791877850321u }; #endif #if FLINT64 #define FLINT_NUM_PSEUDOSQUARES 52 #else #define FLINT_NUM_PSEUDOSQUARES 25 #endif int n_is_prime_pseudosquare(mp_limb_t n) { unsigned int i, j, m1; mp_limb_t p, B, NB, exp, mod8; const mp_limb_t * primes; const double * inverses; if (n < UWORD(2)) return 0; else if ((n & UWORD(1)) == UWORD(0)) return (n == UWORD(2)); primes = n_primes_arr_readonly(FLINT_PSEUDOSQUARES_CUTOFF+1); inverses = n_prime_inverses_arr_readonly(FLINT_PSEUDOSQUARES_CUTOFF+1); for (i = 0; i < FLINT_PSEUDOSQUARES_CUTOFF; i++) { double ppre; p = primes[i]; if (p*p > n) return 1; ppre = inverses[i]; if (!n_mod2_precomp(n, p, ppre)) return 0; } B = primes[FLINT_PSEUDOSQUARES_CUTOFF]; NB = (n - 1)/B + 1; m1 = 0; for (i = 0; i < FLINT_NUM_PSEUDOSQUARES; i++) if (flint_pseudosquares[i] > NB) break; exp = (n - 1)/2; for (j = 0; j <= i; j++) { mp_limb_t mod = n_powmod2(primes[j], exp, n); if ((mod != UWORD(1)) && (mod != n - 1)) return 0; else if (mod == n - 1) m1 = 1; } mod8 = n % 8; if ((mod8 == 3) || (mod8 == 7)) return 1; else if (mod8 == 5) { mp_limb_t mod = n_powmod2(UWORD(2), exp, n); if (mod == n - 1) return 1; else flint_throw(FLINT_ERROR, "Whoah, %wu is a probable prime, but not prime, please report!!\n", n); } else { if (m1) return 1; for (j = i + 1; j < FLINT_NUM_PSEUDOSQUARES + 1; j++) { mp_limb_t mod = n_powmod2(primes[j], exp, n); if (mod == n - 1) return 1; else if (mod != 1) flint_throw(FLINT_ERROR, "Whoah, %wu is a probable prime, but not prime, please report!!\n", n); } flint_throw(FLINT_ERROR, "Whoah, %wu is a probable prime, but not prime, please report!!\n", n); } } flint-3.1.3/src/ulong_extras/is_probabprime.c000066400000000000000000000232351461254215100213020ustar00rootroot00000000000000/* Copyright (C) 2008 Peter Shrimpton Copyright (C) 2009 William Hart Copyright (C) 2014 Dana Jacobsen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" typedef struct { ulong x; ulong y; } n_pair_t; /* This function is used by n_is_prime up to 2^64 and *must* therefore act as a primality proof up to that limit. Currently it acts as such all the way up to 2^64. */ int n_is_probabprime(mp_limb_t n) { mp_limb_t d; unsigned int norm; int isprime; #if FLINT64 double npre; #else mp_limb_t ninv; #endif if (n <= UWORD(1)) return 0; if (n == UWORD(2)) return 1; if ((n & UWORD(1)) == 0) return 0; if (n < FLINT_ODDPRIME_SMALL_CUTOFF) return n_is_oddprime_small(n); if (n < FLINT_PRIMES_TAB_DEFAULT_CUTOFF) return n_is_oddprime_binary(n); #if FLINT64 /* Avoid the unnecessary inverse */ if (n >= UWORD(1050535501)) return n_is_probabprime_BPSW(n); #endif isprime = 0; d = n - 1; norm = flint_ctz(d); d >>= norm; #if !FLINT64 /* For 32-bit, just the 2-base or 3-base Miller-Rabin is enough */ /* The preinv functions are faster on 32-bit, and work up to 2^32 (precomp only works up to 2^31) */ ninv = n_preinvert_limb(n); if (n < UWORD(9080191)) { isprime = n_is_strong_probabprime2_preinv(n, ninv, UWORD(31), d) && n_is_strong_probabprime2_preinv(n, ninv, UWORD(73), d); } else { isprime = n_is_strong_probabprime2_preinv(n, ninv, UWORD(2), d) && n_is_strong_probabprime2_preinv(n, ninv, UWORD(7), d) && n_is_strong_probabprime2_preinv(n, ninv, UWORD(61), d); } #else npre = n_precompute_inverse(n); /* For 64-bit, BPSW seems to be a little bit faster than 3 bases. */ if (n < UWORD(341531)) { isprime = n_is_strong_probabprime_precomp(n, npre, UWORD(9345883071009581737), d); } else if (n < UWORD(1050535501)) { isprime = n_is_strong_probabprime_precomp(n, npre, UWORD(336781006125), d) && n_is_strong_probabprime_precomp(n, npre, UWORD(9639812373923155), d); } #if 0 else if (n < UWORD(350269456337)) { isprime = n_is_strong_probabprime_precomp(n, npre, UWORD(4230279247111683200), d) && n_is_strong_probabprime_precomp(n, npre, UWORD(14694767155120705706), d) && n_is_strong_probabprime_precomp(n, npre, UWORD(16641139526367750375), d); } #endif else { isprime = n_is_probabprime_BPSW(n); } #endif return isprime; } int n_is_probabprime_BPSW(mp_limb_t n) { if (n <= UWORD(1)) return 0; if ((n & UWORD(1)) == UWORD(0)) { if (n == UWORD(2)) return 1; return 0; } if (((n % 10) == 3) || ((n % 10) == 7)) { if (n_is_probabprime_fermat(n, 2) == 0) return 0; return n_is_probabprime_fibonacci(n); } else { mp_limb_t d; d = n - UWORD(1); while ((d & UWORD(1)) == UWORD(0)) d >>= 1; if (FLINT_BIT_COUNT(n) <= FLINT_D_BITS) { double npre = n_precompute_inverse(n); if (n_is_strong_probabprime_precomp(n, npre, WORD(2), d) == 0) return 0; } else { mp_limb_t ninv = n_preinvert_limb(n); if (n_is_strong_probabprime2_preinv(n, ninv, WORD(2), d) == 0) return 0; } return (n_is_probabprime_lucas(n) == 1); } } int n_is_probabprime_fermat(mp_limb_t n, mp_limb_t i) { if (FLINT_BIT_COUNT(n) <= FLINT_D_BITS) return (n_powmod(i, n - 1, n) == UWORD(1)); else return n_powmod2_ui_preinv(i, n - 1, n, n_preinvert_limb(n)) == UWORD(1); } n_pair_t fchain_precomp(mp_limb_t m, mp_limb_t n, double npre) { n_pair_t current = {0, 0}, old; int length; mp_limb_t power, xy; old.x = UWORD(2); old.y = n - UWORD(3); length = FLINT_BIT_COUNT(m); power = (UWORD(1) << (length - 1)); for (; length > 0; length--) { xy = n_mulmod_precomp(old.x, old.y, n, npre); xy = n_addmod(xy, UWORD(3), n); if (m & power) { current.y = n_submod(n_mulmod_precomp(old.y, old.y, n, npre), UWORD(2), n); current.x = xy; } else { current.x = n_submod(n_mulmod_precomp(old.x, old.x, n, npre), UWORD(2), n); current.y = xy; } power >>= 1; old = current; } return current; } n_pair_t fchain2_preinv(mp_limb_t m, mp_limb_t n, mp_limb_t ninv) { n_pair_t current = {0, 0}, old; int length; mp_limb_t power, xy; old.x = UWORD(2); old.y = n - UWORD(3); length = FLINT_BIT_COUNT(m); power = (UWORD(1) << (length - 1)); for (; length > 0; length--) { xy = n_mulmod2_preinv(old.x, old.y, n, ninv); xy = n_addmod(xy, UWORD(3), n); if (m & power) { current.y = n_submod(n_mulmod2_preinv(old.y, old.y, n, ninv), UWORD(2), n); current.x = xy; } else { current.x = n_submod(n_mulmod2_preinv(old.x, old.x, n, ninv), UWORD(2), n); current.y = xy; } power >>= 1; old = current; } return current; } int n_is_probabprime_fibonacci(mp_limb_t n) { mp_limb_t m; n_pair_t V; if (FLINT_ABS((mp_limb_signed_t) n) <= UWORD(3)) { if (n >= UWORD(2)) return 1; return 0; } m = (n - n_jacobi(WORD(5), n)) / 2; /* cannot overflow as (5/n) = 0 for n = 2^64-1 */ if (FLINT_BIT_COUNT(n) <= FLINT_D_BITS) { double npre = n_precompute_inverse(n); V = fchain_precomp(m, n, npre); return (n_mulmod_precomp(n - UWORD(3), V.x, n, npre) == n_mulmod_precomp(UWORD(2), V.y, n, npre)); } else { mp_limb_t ninv = n_preinvert_limb(n); V = fchain2_preinv(m, n, ninv); return (n_mulmod2_preinv(n - UWORD(3), V.x, n, ninv) == n_mulmod2_preinv(UWORD(2), V.y, n, ninv)); } } n_pair_t lchain_precomp(mp_limb_t m, mp_limb_t a, mp_limb_t n, double npre) { n_pair_t current = {0, 0}, old; int length, i; mp_limb_t power, xy, xx, yy; old.x = UWORD(2); old.y = a; length = FLINT_BIT_COUNT(m); power = (UWORD(1) << (length - 1)); for (i = 0; i < length; i++) { xy = n_submod(n_mulmod_precomp(old.x, old.y, n, npre), a, n); if (m & power) { yy = n_submod(n_mulmod_precomp(old.y, old.y, n, npre), UWORD(2), n); current.x = xy; current.y = yy; } else { xx = n_submod(n_mulmod_precomp(old.x, old.x, n, npre), UWORD(2), n); current.x = xx; current.y = xy; } power >>= 1; old = current; } return current; } n_pair_t lchain2_preinv(mp_limb_t m, mp_limb_t a, mp_limb_t n, mp_limb_t ninv) { n_pair_t current = {0, 0}, old; int length, i; mp_limb_t power, xy, xx, yy; old.x = UWORD(2); old.y = a; length = FLINT_BIT_COUNT(m); power = (UWORD(1) << (length - 1)); for (i = 0; i < length; i++) { xy = n_submod(n_mulmod2_preinv(old.x, old.y, n, ninv), a, n); if (m & power) { yy = n_submod(n_mulmod2_preinv(old.y, old.y, n, ninv), UWORD(2), n); current.x = xy; current.y = yy; } else { xx = n_submod(n_mulmod2_preinv(old.x, old.x, n, ninv), UWORD(2), n); current.x = xx; current.y = xy; } power >>= 1; old = current; } return current; } int n_is_probabprime_lucas(mp_limb_t n) { int i, D, Q; mp_limb_t A; mp_limb_t left, right; n_pair_t V; D = 0; Q = 0; if (((n % 2) == 0) || (FLINT_ABS((mp_limb_signed_t) n) <= 2)) { return (n == UWORD(2)); } for (i = 0; i < 100; i++) { D = 5 + 2 * i; if (n_gcd(D, n % D) != UWORD(1)) { if (n == D) continue; else return 0; } if (i % 2 == 1) D = -D; if (n_jacobi(D, n) == -1) break; } if (i == 100) { return (n_is_square(n) ? -1 : 1); } Q = (1 - D) / 4; if (Q < 0) { if (n < UWORD(52)) { while (Q < 0) Q += n; A = n_submod(n_invmod(Q, n), UWORD(2), n); } else A = n_submod(n_invmod(Q + n, n), UWORD(2), n); } else { if (n < UWORD(52)) { while (Q >= n) Q -= n; A = n_submod(n_invmod(Q, n), UWORD(2), n); } else A = n_submod(n_invmod(Q, n), UWORD(2), n); } if (FLINT_BIT_COUNT(n) <= FLINT_D_BITS) { double npre = n_precompute_inverse(n); V = lchain_precomp(n + 1, A, n, npre); left = n_mulmod_precomp(A, V.x, n, npre); right = n_mulmod_precomp(2, V.y, n, npre); } else { mp_limb_t ninv = n_preinvert_limb(n); V = lchain2_preinv(n + 1, A, n, ninv); left = n_mulmod_precomp(A, V.x, n, ninv); right = n_mulmod_precomp(2, V.y, n, ninv); } return (left == right); } flint-3.1.3/src/ulong_extras/is_square.c000066400000000000000000000023331461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int mod64[64] = {1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0, 0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1, 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0}; int mod65[65] = {1,1,0,0,1,0,0,0,0,1,1,0,0,0,1,0,1,0,0,0,0,0, 0,0,0,1,1,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0, 0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,1}; int mod63[63] = {1,1,0,0,1,0,0,1,0,1,0,0,0,0,1,0,1,0,1,0,0, 0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0, 0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0}; int n_is_square(mp_limb_t x) { mp_limb_t sq; if (!mod64[x % UWORD(64)]) return 0; if (!mod63[x % UWORD(63)]) return 0; if (!mod65[x % UWORD(65)]) return 0; sq = (mp_limb_t) (sqrt((double) x) + 0.5); return (x == sq*sq); } flint-3.1.3/src/ulong_extras/is_squarefree.c000066400000000000000000000007631461254215100211430ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" int n_is_squarefree(mp_limb_t n) { return n_moebius_mu(n) != 0; } flint-3.1.3/src/ulong_extras/is_strong_probabprime2_preinv.c000066400000000000000000000017041461254215100243400ustar00rootroot00000000000000/* Copyright (C) 2008, Peter Shrimpton Copyright (C) 2009 William Hart Copyright (C) 2014 Dana Jacobsen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" int n_is_strong_probabprime2_preinv(mp_limb_t n, mp_limb_t ninv, mp_limb_t a, mp_limb_t d) { mp_limb_t t = d; mp_limb_t y; FLINT_ASSERT(a < n); if (a <= 1 || a == n - 1) return 1; y = n_powmod2_ui_preinv(a, t, n, ninv); if (y == UWORD(1)) return 1; t <<= 1; while ((t != n - 1) && (y != n - 1)) { y = n_mulmod2_preinv(y, y, n, ninv); t <<= 1; } return (y == n - 1); } flint-3.1.3/src/ulong_extras/is_strong_probabprime_precomp.c000066400000000000000000000020321461254215100244130ustar00rootroot00000000000000/* Copyright (C) 2008 Peter Shrimpton Copyright (C) 2009 William Hart Copyright (C) 2014 Dana Jacobsen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" int n_is_strong_probabprime_precomp(mp_limb_t n, double npre, mp_limb_t a, mp_limb_t d) { mp_limb_t t = d; mp_limb_t y; /* Map large base to range 2 ... n - 1 */ if (a >= n) a = n_mod2_precomp(a, n, npre); if ((a <= 1) || (a == n-1)) return 1; y = n_powmod_ui_precomp(a, t, n, npre); if (y == UWORD(1)) return 1; t <<= 1; while ((t != n - 1) && (y != n - 1)) { y = n_mulmod_precomp(y, y, n, npre); t <<= 1; } return (y == n - 1); } flint-3.1.3/src/ulong_extras/jacobi.c000066400000000000000000000024571461254215100175370ustar00rootroot00000000000000/* Copyright (C) 2008 Peter Shrimpton Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" /* return (x|y)*(-1)^tstbit(r,1) */ int _n_jacobi_unsigned(mp_limb_t x, mp_limb_t y, unsigned int r) { mp_limb_t t, st; int e; FLINT_ASSERT(y & 1); r ^= 2; while (y > 1) { if (x == 0) return 0; /* x = odd part of x */ e = flint_ctz(x); x >>= e; r ^= ((y ^ (y>>1)) & (2*e)); /* (2|y) = (-1)^((y^2-1)/8) */ /* (x, y) = (|x - y|, min(x, y)) */ sub_ddmmss(st, t, UWORD(0), x, UWORD(0), y); r ^= (x & y & st); /* if y > x, (x|y) = (y|x)*(-1)^((x-1)(y-1)/4) */ y += (st & t); x = (t ^ st) - st; } return (int)(r & 2) - 1; } int n_jacobi_unsigned(mp_limb_t x, mp_limb_t y) { return _n_jacobi_unsigned(x, y, 0); } int n_jacobi(mp_limb_signed_t x, mp_limb_t y) { return _n_jacobi_unsigned(FLINT_ABS(x), y, FLINT_SIGN_EXT(x) & y); } flint-3.1.3/src/ulong_extras/ll_mod_preinv.c000066400000000000000000000030671461254215100211370ustar00rootroot00000000000000/* Copyright (C) 2009, 2010, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" /* Method of Niels Moller and Torbjorn Granlund, see "Improved Division by Invariant Integers: (Algorithm 4) https://gmplib.org/~tege/division-paper.pdf */ ulong n_ll_mod_preinv(ulong a_hi, ulong a_lo, ulong n, ulong ninv) { ulong q0, q1, r, norm; FLINT_ASSERT(n != 0); norm = flint_clz(n); /* reduce a_hi modulo n */ if (a_hi >= n) { const ulong u1 = r_shift(a_hi, FLINT_BITS - norm); const ulong u0 = (a_hi << norm); n <<= norm; umul_ppmm(q1, q0, ninv, u1); add_ssaaaa(q1, q0, q1, q0, u1, u0); a_hi = (u0 - (q1 + 1) * n); if (a_hi > q0) a_hi += n; if (a_hi >= n) a_hi -= n; } else { n <<= norm; a_hi <<= norm; } /* now reduce the rest of the way */ { const ulong u1 = a_hi + r_shift(a_lo, FLINT_BITS - norm); const ulong u0 = (a_lo << norm); umul_ppmm(q1, q0, ninv, u1); add_ssaaaa(q1, q0, q1, q0, u1, u0); r = (u0 - (q1 + 1) * n); if (r > q0) r += n; return (r < n) ? (r >> norm) : ((r - n) >> norm); } } flint-3.1.3/src/ulong_extras/lll_mod_preinv.c000066400000000000000000000030661461254215100213120ustar00rootroot00000000000000/* Copyright (C) 2009, 2010, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" /* Method of Niels Moller and Torbjorn Granlund, see "Improved Division by Invariant Integers: (Algorithm 4) https://gmplib.org/~tege/division-paper.pdf */ ulong n_lll_mod_preinv(ulong a_hi, ulong a_mi, ulong a_lo, ulong n, ulong ninv) { ulong q0, q1, r, norm; norm = flint_clz(n); n <<= norm; /* a_hi is already reduced, so first reduce a_hi, a_mi mod n */ { const ulong u1 = (a_hi << norm) + r_shift(a_mi, FLINT_BITS - norm); const ulong u0 = (a_mi << norm); umul_ppmm(q1, q0, ninv, u1); add_ssaaaa(q1, q0, q1, q0, u1, u0); a_mi = (u0 - (q1 + 1) * n); if (a_mi > q0) a_mi += n; if (a_mi >= n) a_mi -= n; } /* a_mi is now reduced mod n, so reduce a_mi, a_lo mod n */ { const ulong u1 = a_mi + r_shift(a_lo, FLINT_BITS - norm); const ulong u0 = (a_lo << norm); umul_ppmm(q1, q0, ninv, u1); add_ssaaaa(q1, q0, q1, q0, u1, u0); r = (u0 - (q1 + 1) * n); if (r > q0) r += n; return (r < n) ? (r >> norm) : ((r - n) >> norm); } } flint-3.1.3/src/ulong_extras/mod2_precomp.c000066400000000000000000000022521461254215100206670ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_mod2_precomp(mp_limb_t a, mp_limb_t n, double npre) { mp_limb_t quot; slong rem; if (a < n) return a; if ((mp_limb_signed_t) n < WORD(0)) return a - n; if (n == 1) { quot = a; rem = 0; } else { quot = (mp_limb_t) ((double) a * npre); rem = a - quot * n; } if (rem < (mp_limb_signed_t) (-n)) quot -= (mp_limb_t) ((double) (-rem) * npre); else if (rem >= (slong) n) quot += (mp_limb_t) ((double) rem * npre); else if (rem < WORD(0)) return rem + n; else return rem; rem = a - quot * n; if (rem >= (slong) n) return rem - n; else if (rem < WORD(0)) return rem + n; else return rem; } flint-3.1.3/src/ulong_extras/mod2_preinv.c000066400000000000000000000020661461254215100205300ustar00rootroot00000000000000/* Copyright (C) 2009, 2010, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" /* Method of Niels Moller and Torbjorn Granlund see paper: Improved Division by Invariant Integers: (algorithm 4) https://gmplib.org/~tege/division-paper.pdf */ ulong n_mod2_preinv(ulong a, ulong n, ulong ninv) { ulong norm, q1, q0, r; FLINT_ASSERT(n != 0); norm = flint_clz(n); n <<= norm; { const ulong u1 = r_shift(a, FLINT_BITS - norm); const ulong u0 = (a << norm); umul_ppmm(q1, q0, ninv, u1); add_ssaaaa(q1, q0, q1, q0, u1, u0); r = u0 - (q1 + 1) * n; if (r > q0) r += n; return (r < n) ? (r >> norm) : ((r - n) >> norm); } } flint-3.1.3/src/ulong_extras/mod_precomp.c000066400000000000000000000013201461254215100206000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_mod_precomp(mp_limb_t a, mp_limb_t n, double npre) { mp_limb_t quot, rem; quot = (mp_limb_t) ((double) a * npre); rem = a - quot*n; if ((slong) rem < 0) /* unlikely */ rem += n; return rem - (n & (((mp_limb_signed_t) (n - rem - 1)) >> (FLINT_BITS-1))); } flint-3.1.3/src/ulong_extras/moebius_mu.c000066400000000000000000000054761461254215100204600ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #define FLINT_MU_LOOKUP_CUTOFF 1024 #if FLINT64 const mp_limb_t FLINT_MOEBIUS_ODD[] = { UWORD(0x4289108a05208102), UWORD(0x19988004a8a12422), UWORD(0x1a8245028906a062), UWORD(0x229428012aa26a00), UWORD(0x8422a98980440a18), 0x224925084068929aUL, UWORD(0xa1200942a8980a84), UWORD(0x8622622216a00428), UWORD(0x6060829286a590a9), UWORD(0x5a2190081420a1a8), UWORD(0x8a92a284a8018200), UWORD(0x980a2602491a2248), UWORD(0x8106a08982a26848), UWORD(0xa60085a6004a5919), UWORD(0x88a188245a221228), UWORD(0x0108884a22186025) }; #else const mp_limb_t FLINT_MOEBIUS_ODD[] = { UWORD(0x05208102), 0x4289108aUL, UWORD(0xa8a12422), UWORD(0x19988004), UWORD(0x8906a062), UWORD(0x1a824502), UWORD(0x2aa26a00), UWORD(0x22942801), UWORD(0x80440a18), UWORD(0x8422a989), 0x4068929aUL, UWORD(0x22492508), UWORD(0xa8980a84), UWORD(0xa1200942), UWORD(0x16a00428), UWORD(0x86226222), UWORD(0x86a590a9), UWORD(0x60608292), UWORD(0x1420a1a8), UWORD(0x5a219008), UWORD(0xa8018200), UWORD(0x8a92a284), UWORD(0x491a2248), UWORD(0x980a2602), UWORD(0x82a26848), UWORD(0x8106a089), UWORD(0x004a5919), UWORD(0xa60085a6), UWORD(0x5a221228), UWORD(0x88a18824), UWORD(0x22186025), 0x0108884aUL }; #endif void n_moebius_mu_vec(int * mu, ulong len) { slong k; ulong pi; const mp_limb_t * primes; mp_limb_t p, q; pi = n_prime_pi(len); primes = n_primes_arr_readonly(pi); if (len) mu[0] = 0; for (k = 1; k < len; k++) mu[k] = 1; for (k = 0; k < pi; k++) { p = primes[k]; for (q = p; q < len; q += p) mu[q] = -mu[q]; p = p * p; for (q = p; q < len; q += p) mu[q] = 0; } } int n_moebius_mu(mp_limb_t n) { int i; n_factor_t fac; if (n % 2 == 0) { if (n % 4 == 0) return 0; return -n_moebius_mu(n / 2); } if (n < FLINT_MU_LOOKUP_CUTOFF) { mp_limb_t m; n -= 1; m = FLINT_MOEBIUS_ODD[n / FLINT_BITS]; m &= (UWORD(3) << (n % FLINT_BITS)); m >>= (n % FLINT_BITS); return ((int) m) - 1; } /* Weed out just a few more common squares first */ if (n % 9 == 0 || n % 25 == 0) return 0; n_factor_init(&fac); n_factor(&fac, n, 1); for (i = 0; i < fac.num; i++) { if (fac.exp[i] != 1) return 0; } if (fac.num % 2) return -1; else return 1; } flint-3.1.3/src/ulong_extras/mulmod_precomp.c000066400000000000000000000014131461254215100213210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_mulmod_precomp(mp_limb_t a, mp_limb_t b, mp_limb_t n, double npre) { mp_limb_t quot; mp_limb_signed_t rem; quot = (mp_limb_t) ((double) a * (double) b * npre); rem = a * b - quot * n; if (rem < 0) { rem += n; if (rem < 0) return rem + n; } else if (rem >= n) return rem - n; return rem; } flint-3.1.3/src/ulong_extras/mulmod_precomp_shoup.c000066400000000000000000000012201461254215100225330ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" /* Computes the W' = [w * b / p] (b = mp_limb_t power) */ mp_limb_t n_mulmod_precomp_shoup(mp_limb_t w, mp_limb_t p) { mp_limb_t q, r; udiv_qrnnd(q, r, w, UWORD(0), p); return q; } flint-3.1.3/src/ulong_extras/mulmod_preinv.c000066400000000000000000000020411461254215100211550ustar00rootroot00000000000000/* Copyright (C) 2009, 2010, 2012, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" ulong n_mulmod_preinv(ulong a, ulong b, ulong n, ulong ninv, ulong norm) { ulong q0, q1, r, p_hi, p_lo; /* check normalisation */ FLINT_ASSERT((n & (UWORD(1) << (FLINT_BITS - 1))) != 0); FLINT_ASSERT(a < n); FLINT_ASSERT(b < n); FLINT_ASSERT(n != 0); /* renormalise product */ a >>= norm; /* multiply */ umul_ppmm(p_hi, p_lo, a, b); /* reduce mod n */ { umul_ppmm(q1, q0, ninv, p_hi); add_ssaaaa(q1, q0, q1, q0, p_hi, p_lo); r = (p_lo - (q1 + 1) * n); if (r > q0) r += n; return (r < n ? r : r - n); } } flint-3.1.3/src/ulong_extras/nextprime.c000066400000000000000000000053651461254215100203240ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2008 Peter Shrimpton Copyright (C) 2010 Fredrik Johansson Copyright (C) 2015 Dana Jacobsen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" static unsigned int nextmod30[] = { 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2 }; static unsigned int nextindex[] = { 1, 7, 7, 7, 7, 7, 7, 11, 11, 11, 11, 13, 13, 17, 17, 17, 17, 19, 19, 23, 23, 23, 23, 29, 29, 29, 29, 29, 29, 1 }; /* first 64 primes used for modular arithmetic */ #define N_MODULUS (UWORD(1) << (FLINT_BITS - 1)) #define N_MOD_TAB 64 static const unsigned short n_modular_primes_tab[N_MOD_TAB] = { #if FLINT_BITS == 64 29, 99, 123, 131, 155, 255, 269, 359, 435, 449, 453, 485, 491, 543, 585, 599, 753, 849, 879, 885, 903, 995, 1209, 1251, 1311, 1373, 1403, 1485, 1533, 1535, 1545, 1551, 1575, 1601, 1625, 1655, 1701, 1709, 1845, 1859, 1913, 1995, 2045, 2219, 2229, 2321, 2363, 2385, 2483, 2499, 2523, 2543, 2613, 2639, 2679, 2829, 2931, 3089, 3165, 3189, 3245, 3273, 3291, 3341 #else 11, 45, 65, 95, 129, 135, 165, 209, 219, 221, 239, 245, 281, 303, 345, 351, 359, 389, 393, 395, 413, 435, 461, 513, 519, 549, 555, 573, 575, 585, 591, 611, 623, 629, 683, 689, 701, 729, 785, 791, 813, 843, 851, 869, 879, 893, 905, 921, 953, 963, 965, 969, 993, 1031, 1049, 1073, 1085, 1103, 1143, 1173, 1203, 1221, 1229, 1271 #endif }; static mp_limb_t bsearch_uint(mp_limb_t n, const unsigned int *t, int tlen) { int lo = 0; int hi = tlen-1; while (lo < hi) { int mid = lo + (hi-lo)/2; if (t[mid] <= n) lo = mid+1; else hi = mid; } return t[lo]; } mp_limb_t n_nextprime(mp_limb_t n, int proved) { ulong i, index; /* For tiny inputs, bsearch in small primes table */ if (n < flint_primes_small[FLINT_NUM_PRIMES_SMALL-1]) return bsearch_uint(n, flint_primes_small, FLINT_NUM_PRIMES_SMALL); if (n >= N_MODULUS && n < N_MODULUS + n_modular_primes_tab[N_MOD_TAB-1]) { for (i = 0; i < N_MOD_TAB; i++) if (N_MODULUS + n_modular_primes_tab[i] > n) return N_MODULUS + n_modular_primes_tab[i]; } if (n >= UWORD_MAX_PRIME) { flint_throw(FLINT_ERROR, "Exception (n_nextprime). No larger single-limb prime exists.\n"); } index = n % 30; do { n += nextmod30[index]; index = nextindex[index]; } while (!n_is_prime(n)); return n; } flint-3.1.3/src/ulong_extras/nth_prime.c000066400000000000000000000021771461254215100202740ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" mp_limb_t n_nth_prime(ulong n) { if (n == 0) { flint_throw(FLINT_ERROR, "Exception (n_nth_prime). n_nth_prime(0) is undefined.\n"); } return n_primes_arr_readonly(n)[n-1]; } void n_nth_prime_bounds(mp_limb_t *lo, mp_limb_t *hi, ulong n) { int bits, ll; double llo, lhi; /* Lower and upper bounds for ln(n) */ bits = FLINT_BIT_COUNT(n); llo = (bits-1) * 0.6931471; lhi = bits * 0.6931472; /* Lower bound for ln(ln(n)) */ if (n < 16) ll = 0; else if (n < 1619) ll = 1; else if (n < 528491312) ll = 2; else ll = 3; *lo = (mp_limb_t) (n * (llo + ll - 1)); *hi = (mp_limb_t) (n * (lhi + (ll+1) - (n >= 15985 ? 0.9427 : 0.0))); } flint-3.1.3/src/ulong_extras/pow.c000066400000000000000000000016061461254215100171100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" ulong _n_pow_check(ulong n, ulong exp) { ulong ix, rl, rh; if (n == 0) FLINT_UNREACHABLE; rl = UWORD(1); for (ix = 0; ix < exp; ix++) { umul_ppmm(rh, rl, n, rl); if (rh) return 0; } return rl; } ulong n_pow(ulong n, ulong exp) { ulong ix; ulong res; res = UWORD(1); for (ix = 0; ix < exp; ix++) res *= n; return res; } flint-3.1.3/src/ulong_extras/powmod2_preinv.c000066400000000000000000000016351461254215100212570ustar00rootroot00000000000000/* Copyright (C) 2009, 2013, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" ulong n_powmod2_preinv(ulong a, slong exp, ulong n, ulong ninv) { ulong norm; FLINT_ASSERT(n != 0); if (a >= n) a = n_mod2_preinv(a, n, ninv); if (exp < 0) { ulong g = n_gcdinv(&a, a, n); if (g != 1) flint_throw(FLINT_IMPINV, "Cannot invert modulo %wd*%wd\n", g, n / g); exp = -exp; } norm = flint_clz(n); return n_powmod_ui_preinv(a << norm, exp, n << norm, ninv, norm) >> norm; } flint-3.1.3/src/ulong_extras/powmod2_ui_preinv.c000066400000000000000000000021221461254215100217440ustar00rootroot00000000000000/* Copyright (C) 2009, 2013, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" ulong n_powmod2_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv) { ulong x, norm; FLINT_ASSERT(n != 0); if (exp == 0) { /* anything modulo 1 is 0 */ return n == 1 ? 0 : 1; } if (a == 0) return 0; if (a >= n) a = n_mod2_preinv(a, n, ninv); norm = flint_clz(n); a <<= norm; n <<= norm; while ((exp & 1) == 0) { a = n_mulmod_preinv(a, a, n, ninv, norm); exp >>= 1; } x = a; while (exp >>= 1) { a = n_mulmod_preinv(a, a, n, ninv, norm); if (exp & 1) x = n_mulmod_preinv(x, a, n, ninv, norm); } return x >> norm; } flint-3.1.3/src/ulong_extras/powmod_precomp.c000066400000000000000000000020131461254215100213260ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_powmod_ui_precomp(mp_limb_t a, mp_limb_t exp, mp_limb_t n, double npre) { mp_limb_t x, y; if (n == UWORD(1)) return WORD(0); x = UWORD(1); y = a; while (exp) { if (exp & WORD(1)) x = n_mulmod_precomp(x, y, n, npre); exp >>= 1; if (exp) y = n_mulmod_precomp(y, y, n, npre); } return x; } mp_limb_t n_powmod_precomp(mp_limb_t a, mp_limb_signed_t exp, mp_limb_t n, double npre) { if (exp < 0) { a = n_invmod(a, n); exp = -exp; } return n_powmod_ui_precomp(a, exp, n, npre); } flint-3.1.3/src/ulong_extras/powmod_ui_preinv.c000066400000000000000000000022671461254215100216740ustar00rootroot00000000000000/* Copyright (C) 2013, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" ulong n_powmod_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv, ulong norm) { ulong x; /* check normalisation */ FLINT_ASSERT((n & (UWORD(1) << (FLINT_BITS - 1))) != 0); FLINT_ASSERT(a < n); FLINT_ASSERT(n != 0); if (exp == 0) { x = UWORD(1) << norm; /* anything modulo 1 is 0 */ return x == n ? 0 : x; } if (a == 0) return 0; /* find first 1 in binary repn of exp */ while ((exp & 1) == 0) { a = n_mulmod_preinv(a, a, n, ninv, norm); exp >>= 1; } x = a; /* binary exponentiation */ while (exp >>= 1) { a = n_mulmod_preinv(a, a, n, ninv, norm); if (exp & 1) x = n_mulmod_preinv(x, a, n, ninv, norm); } return x; } flint-3.1.3/src/ulong_extras/preinvert_limb.c000066400000000000000000000207211461254215100213230ustar00rootroot00000000000000/* Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Copyright 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #if FLINT_BITS == 32 /* rec_word_tab[i] = div(2^24 - 2^14 + 2^9, 2^9 + i) */ static const unsigned short rec_word_tab[512] = { 32737, 32673, 32609, 32546, 32483, 32420, 32357, 32295, 32233, 32171, 32109, 32048, 31987, 31926, 31865, 31805, 31744, 31684, 31625, 31565, 31506, 31447, 31388, 31329, 31271, 31212, 31154, 31097, 31039, 30982, 30924, 30868, 30811, 30754, 30698, 30642, 30586, 30530, 30475, 30419, 30364, 30309, 30255, 30200, 30146, 30092, 30038, 29984, 29930, 29877, 29824, 29771, 29718, 29666, 29613, 29561, 29509, 29457, 29405, 29354, 29303, 29251, 29200, 29150, 29099, 29049, 28998, 28948, 28898, 28849, 28799, 28750, 28700, 28651, 28602, 28554, 28505, 28457, 28409, 28360, 28313, 28265, 28217, 28170, 28123, 28075, 28029, 27982, 27935, 27889, 27842, 27796, 27750, 27704, 27658, 27613, 27568, 27522, 27477, 27432, 27387, 27343, 27298, 27254, 27209, 27165, 27121, 27078, 27034, 26990, 26947, 26904, 26861, 26818, 26775, 26732, 26690, 26647, 26605, 26563, 26521, 26479, 26437, 26395, 26354, 26312, 26271, 26230, 26189, 26148, 26108, 26067, 26026, 25986, 25946, 25906, 25866, 25826, 25786, 25747, 25707, 25668, 25628, 25589, 25550, 25511, 25473, 25434, 25395, 25357, 25319, 25281, 25242, 25205, 25167, 25129, 25091, 25054, 25016, 24979, 24942, 24905, 24868, 24831, 24794, 24758, 24721, 24685, 24649, 24612, 24576, 24540, 24504, 24469, 24433, 24397, 24362, 24327, 24291, 24256, 24221, 24186, 24151, 24117, 24082, 24047, 24013, 23979, 23944, 23910, 23876, 23842, 23808, 23774, 23741, 23707, 23674, 23640, 23607, 23574, 23541, 23508, 23475, 23442, 23409, 23377, 23344, 23312, 23279, 23247, 23215, 23183, 23151, 23119, 23087, 23055, 23023, 22992, 22960, 22929, 22898, 22866, 22835, 22804, 22773, 22742, 22711, 22681, 22650, 22619, 22589, 22559, 22528, 22498, 22468, 22438, 22408, 22378, 22348, 22318, 22289, 22259, 22229, 22200, 22171, 22141, 22112, 22083, 22054, 22025, 21996, 21967, 21938, 21910, 21881, 21853, 21824, 21796, 21767, 21739, 21711, 21683, 21655, 21627, 21599, 21571, 21544, 21516, 21488, 21461, 21433, 21406, 21379, 21352, 21324, 21297, 21270, 21243, 21216, 21190, 21163, 21136, 21110, 21083, 21056, 21030, 21004, 20977, 20951, 20925, 20899, 20873, 20847, 20821, 20795, 20769, 20744, 20718, 20693, 20667, 20642, 20616, 20591, 20566, 20540, 20515, 20490, 20465, 20440, 20415, 20390, 20366, 20341, 20316, 20292, 20267, 20243, 20218, 20194, 20170, 20145, 20121, 20097, 20073, 20049, 20025, 20001, 19977, 19953, 19930, 19906, 19882, 19859, 19835, 19812, 19789, 19765, 19742, 19719, 19696, 19672, 19649, 19626, 19603, 19581, 19558, 19535, 19512, 19489, 19467, 19444, 19422, 19399, 19377, 19354, 19332, 19310, 19288, 19265, 19243, 19221, 19199, 19177, 19155, 19133, 19112, 19090, 19068, 19046, 19025, 19003, 18982, 18960, 18939, 18917, 18896, 18875, 18854, 18832, 18811, 18790, 18769, 18748, 18727, 18706, 18686, 18665, 18644, 18623, 18603, 18582, 18561, 18541, 18520, 18500, 18479, 18459, 18439, 18419, 18398, 18378, 18358, 18338, 18318, 18298, 18278, 18258, 18238, 18218, 18199, 18179, 18159, 18139, 18120, 18100, 18081, 18061, 18042, 18022, 18003, 17984, 17964, 17945, 17926, 17907, 17888, 17869, 17850, 17831, 17812, 17793, 17774, 17755, 17736, 17718, 17699, 17680, 17662, 17643, 17624, 17606, 17587, 17569, 17551, 17532, 17514, 17496, 17477, 17459, 17441, 17423, 17405, 17387, 17369, 17351, 17333, 17315, 17297, 17279, 17261, 17244, 17226, 17208, 17191, 17173, 17155, 17138, 17120, 17103, 17085, 17068, 17051, 17033, 17016, 16999, 16982, 16964, 16947, 16930, 16913, 16896, 16879, 16862, 16845, 16828, 16811, 16794, 16778, 16761, 16744, 16727, 16711, 16694, 16677, 16661, 16644, 16628, 16611, 16595, 16578, 16562, 16546, 16529, 16513, 16497, 16481, 16464, 16448, 16432, 16416, 16400, 16384 }; #define _invert_limb(dinv, d) \ do { \ mp_limb_t _v0, _v1, _v2, _d21, _e, _m0; \ FLINT_ASSERT(((d) & (UWORD(1)<<(FLINT_BITS - 1))) != 0); \ _v0 = rec_word_tab[((d) >> 22) & 0x1FF]; \ _d21 = ((d) >> 11) + 1; \ _m0 = _v0*_v0; \ umul_ppmm(_v1, _e, _m0, _d21); \ _v1 = (_v0 << 4) - _v1 - 1; \ _e = -_v1*((d) >> 1); \ _m0 = -((d) & (mp_limb_t) 1); \ _e -= ((_v1 - (_v1 >> 1)) & _m0); \ umul_ppmm(_v2, _m0, _v1, _e); \ _v2 = (_v1 << 15) + (_v2 >> 1); \ umul_ppmm(_v0, _d21, _v2, (d)); \ add_ssaaaa(_v0, _d21, _v0, _d21, (mp_limb_t) 0, (d)); \ (dinv) = _v2 - (_v0 + (d)); \ } while(0) #else /* rec_word_tab[i] = div(2^19 - 3*2^8, 2^8 + i) */ static const unsigned short rec_word_tab[256] = { 2045, 2037, 2029, 2021, 2013, 2005, 1998, 1990, 1983, 1975, 1968, 1960, 1953, 1946, 1938, 1931, 1924, 1917, 1910, 1903, 1896, 1889, 1883, 1876, 1869, 1863, 1856, 1849, 1843, 1836, 1830, 1824, 1817, 1811, 1805, 1799, 1792, 1786, 1780, 1774, 1768, 1762, 1756, 1750, 1745, 1739, 1733, 1727, 1722, 1716, 1710, 1705, 1699, 1694, 1688, 1683, 1677, 1672, 1667, 1661, 1656, 1651, 1646, 1641, 1636, 1630, 1625, 1620, 1615, 1610, 1605, 1600, 1596, 1591, 1586, 1581, 1576, 1572, 1567, 1562, 1558, 1553, 1548, 1544, 1539, 1535, 1530, 1526, 1521, 1517, 1513, 1508, 1504, 1500, 1495, 1491, 1487, 1483, 1478, 1474, 1470, 1466, 1462, 1458, 1454, 1450, 1446, 1442, 1438, 1434, 1430, 1426, 1422, 1418, 1414, 1411, 1407, 1403, 1399, 1396, 1392, 1388, 1384, 1381, 1377, 1374, 1370, 1366, 1363, 1359, 1356, 1352, 1349, 1345, 1342, 1338, 1335, 1332, 1328, 1325, 1322, 1318, 1315, 1312, 1308, 1305, 1302, 1299, 1295, 1292, 1289, 1286, 1283, 1280, 1276, 1273, 1270, 1267, 1264, 1261, 1258, 1255, 1252, 1249, 1246, 1243, 1240, 1237, 1234, 1231, 1228, 1226, 1223, 1220, 1217, 1214, 1211, 1209, 1206, 1203, 1200, 1197, 1195, 1192, 1189, 1187, 1184, 1181, 1179, 1176, 1173, 1171, 1168, 1165, 1163, 1160, 1158, 1155, 1153, 1150, 1148, 1145, 1143, 1140, 1138, 1135, 1133, 1130, 1128, 1125, 1123, 1121, 1118, 1116, 1113, 1111, 1109, 1106, 1104, 1102, 1099, 1097, 1095, 1092, 1090, 1088, 1086, 1083, 1081, 1079, 1077, 1074, 1072, 1070, 1068, 1066, 1064, 1061, 1059, 1057, 1055, 1053, 1051, 1049, 1047, 1044, 1042, 1040, 1038, 1036, 1034, 1032, 1030, 1028, 1026, 1024 }; #define _invert_limb(dinv, d) \ do { \ mp_limb_t _v0, _v2, _d40, _e, _m0; \ FLINT_ASSERT(((d) & (UWORD(1)<<(FLINT_BITS - 1))) != 0); \ _d40 = ((d) >> 24) + 1; \ _v0 = rec_word_tab[((d) >> 55) & 0xFF]; \ _v0 = (_v0 << 11) - ((_v0*_v0*_d40) >> 40) - 1; \ _v2 = ((_v0*((((mp_limb_t) 1) << 60) - _v0*_d40)) >> 47); \ _v2 += (_v0 << 13); \ _e = -_v2*((d) >> 1); \ _m0 = -((d) & (mp_limb_t) 1); \ _e -= ((_v2 - (_v2 >> 1)) & _m0); \ umul_ppmm(_v0, _d40, _v2, _e); \ _v2 = (_v2 << 31) + (_v0 >> 1); \ umul_ppmm(_v0, _d40, _v2, (d)); \ add_ssaaaa(_v0, _d40, _v0, _d40, (mp_limb_t) 0, (d)); \ (dinv) = _v2 - (_v0 + (d)); \ } while (0) #endif /* 64 bits */ ulong n_preinvert_limb(ulong n) { ulong norm, ninv; norm = flint_clz(n); _invert_limb(ninv, n << norm); return ninv; } ulong n_preinvert_limb_prenorm(ulong n) { ulong ninv; _invert_limb(ninv, n); return ninv; } flint-3.1.3/src/ulong_extras/prime_inverses_arr_readonly.c000066400000000000000000000012701461254215100240730ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" const double * n_prime_inverses_arr_readonly(ulong num_primes) { int m; if (num_primes < 1) return NULL; m = FLINT_CLOG2(num_primes); if (m >= _flint_primes_used) n_compute_primes(num_primes); return _flint_prime_inverses[m]; } flint-3.1.3/src/ulong_extras/prime_pi.c000066400000000000000000000026761461254215100201170ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" const unsigned char FLINT_PRIME_PI_ODD_LOOKUP[] = { 0,2,3,4,4,5,6,6,7,8,8,9,9,9,10,11,11,11,12,12,13,14,14,15,15,15,16,16,16,17, 18,18,18,19,19,20,21,21,21,22,22,23,23,23,24,24,24,24,25,25,26,27,27,28,29, 29,30,30,30,30,30,30,30,31,31,32,32,32,33,34,34,34,34,34,35,36,36,36,37,37, 37,38,38,39,39,39,40,40,40,41,42,42,42,42,42,43,44,44,45,46,46,46,46,46,46, 47,47,47,47,47,47,48,48,49,50,50,51,51,51,52,53,53,53,53,53,54,54,54,55,55, 55,56,56,56,57,58,58,58,59,59,60,61,61,61,61,61,62,62,62,62,62,62,62,63,63 }; ulong n_prime_pi(mp_limb_t n) { ulong low, mid, high; const mp_limb_t * primes; if (n < FLINT_PRIME_PI_ODD_LOOKUP_CUTOFF) { if (n < 3) return (n == 2); return FLINT_PRIME_PI_ODD_LOOKUP[(n-1)/2]; } n_prime_pi_bounds(&low, &high, n); primes = n_primes_arr_readonly(high + 1); while (low < high) { mid = (low + high) / 2; if (n < primes[mid-1]) high = mid; else low = mid + 1; } return low-1; } flint-3.1.3/src/ulong_extras/prime_pi_bounds.c000066400000000000000000000017141461254215100214610ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2010, 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" FLINT_DLL extern const unsigned char FLINT_PRIME_PI_ODD_LOOKUP[]; void n_prime_pi_bounds(ulong *lo, ulong *hi, mp_limb_t n) { if (n < FLINT_PRIME_PI_ODD_LOOKUP_CUTOFF) { if (n < 3) *lo = *hi = (n == 2); else *lo = *hi = FLINT_PRIME_PI_ODD_LOOKUP[(n-1)/2]; } else { /* 14/10 < 1/log(2)*/ *lo = (n / (10 * FLINT_CLOG2(n))) * 14; /* 19/10 > 1.25506/log(2) */ *hi = (n / (10 * FLINT_FLOG2(n)) + 1) * 19; } } flint-3.1.3/src/ulong_extras/primes_arr_readonly.c000066400000000000000000000012531461254215100223410ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" const mp_limb_t * n_primes_arr_readonly(ulong num_primes) { int m; if (num_primes < 1) return NULL; m = FLINT_CLOG2(num_primes); if (m >= _flint_primes_used) n_compute_primes(num_primes); return _flint_primes[m]; } flint-3.1.3/src/ulong_extras/primes_clear.c000066400000000000000000000011341461254215100207440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" void n_primes_clear(n_primes_t iter) { if (iter->small_primes != flint_primes_small) flint_free(iter->small_primes); if (iter->sieve != NULL) flint_free(iter->sieve); } flint-3.1.3/src/ulong_extras/primes_extend_small.c000066400000000000000000000021401461254215100223330ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" void n_primes_extend_small(n_primes_t iter, mp_limb_t bound) { while (iter->small_primes[iter->small_num - 2] < bound) { n_primes_t iter2; slong i, num; num = iter->small_num * 2; if (iter->small_primes == flint_primes_small) iter->small_primes = flint_malloc(num * sizeof(unsigned int)); else iter->small_primes = flint_realloc(iter->small_primes, num * sizeof(unsigned int)); n_primes_init(iter2); for (i = 0; i < num; i++) iter->small_primes[i] = n_primes_next(iter2); n_primes_clear(iter2); iter->small_num = num; iter->small_i = num; } } flint-3.1.3/src/ulong_extras/primes_init.c000066400000000000000000000012741461254215100206260ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" void n_primes_init(n_primes_t iter) { iter->small_i = 0; iter->small_primes = (unsigned int *) flint_primes_small; iter->small_num = FLINT_NUM_PRIMES_SMALL; iter->sieve_i = 0; iter->sieve_num = 0; iter->sieve_a = 0; iter->sieve_b = 0; iter->sieve = NULL; } flint-3.1.3/src/ulong_extras/primes_jump_after.c000066400000000000000000000014331461254215100220140ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" void n_primes_jump_after(n_primes_t iter, mp_limb_t n) { if (n < iter->small_primes[iter->small_num - 1]) { iter->small_i = n_prime_pi(n); iter->sieve_a = iter->sieve_b = iter->sieve_num = 0; } else { iter->small_i = iter->small_num; n_primes_sieve_range(iter, n + 1, n + 1 + FLINT_MIN(n, FLINT_SIEVE_SIZE) - 2); } } flint-3.1.3/src/ulong_extras/primes_next.c000066400000000000000000000016161461254215100206410ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" ulong n_primes_next(n_primes_t iter) { if (iter->small_i < iter->small_num) return iter->small_primes[(iter->small_i)++]; for (;;) { while (iter->sieve_i < iter->sieve_num) if (iter->sieve[iter->sieve_i++] != 0) return iter->sieve_a + 2 * (iter->sieve_i - 1); if (iter->sieve_b == 0) n_primes_jump_after(iter, iter->small_primes[iter->small_num-1]); else n_primes_jump_after(iter, iter->sieve_b); } } flint-3.1.3/src/ulong_extras/primes_sieve_range.c000066400000000000000000000034321461254215100221500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" static void mark(char * sieve, mp_limb_t a, slong len, mp_limb_t p) { mp_limb_t t; t = p * p; if (t >= a) { t = (t - a) / 2; } else { t = p - ((a - p) / 2) % p; if (t == p) t = 0; } while (t < len) { sieve[t] = 0; t += p; } } void n_sieve_odd(char * sieve, ulong n, mp_limb_t a, unsigned int * sieve_primes, mp_limb_t bound) { slong i; mp_limb_t p; for (i = 0; i < n / 2; i++) sieve[i] = 1; i = 0; while (1) { i++; p = sieve_primes[i]; if (p > bound) break; mark(sieve, a, n / 2, p); } } void n_primes_sieve_range(n_primes_t iter, mp_limb_t a, mp_limb_t b) { mp_limb_t bound; ulong len, odd_len; /* a and b must be odd */ a += (a % 2 == 0); b -= (b % 2 == 0); len = b - a + 2; odd_len = len / 2; if (a < 3 || b < a || len > FLINT_SIEVE_SIZE) { flint_throw(FLINT_ERROR, "invalid sieve range %wu,%wu!\n", a, b); } bound = n_sqrt(b) + 1; if (iter->sieve == NULL) iter->sieve = flint_malloc(FLINT_SIEVE_SIZE / 2 * sizeof(char)); n_primes_extend_small(iter, bound); n_sieve_odd(iter->sieve, len, a, iter->small_primes, bound); iter->sieve_i = 0; iter->sieve_num = odd_len; iter->sieve_a = a; iter->sieve_b = b; } flint-3.1.3/src/ulong_extras/primitive_root_prime.c000066400000000000000000000025321461254215100225510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_primitive_root_prime_prefactor(mp_limb_t p, n_factor_t * factors) { slong i; int found; mp_limb_t result, a, pm1; double pinv; if (p == 2) { return 1; } pm1 = p - 1; pinv = n_precompute_inverse(p); for (a = 2; a < p; a++) { found = 1; for (i = 0; i < factors->num; i++) { result = n_powmod_precomp(a, pm1 / factors->p[i], p, pinv); if (result == 1) { found = 0; break; } } if (found) { return a; } } flint_throw(FLINT_ERROR, "Exception (n_primitive_root_prime_prefactor). root not found.\n"); } mp_limb_t n_primitive_root_prime(mp_limb_t p) { mp_limb_t a; n_factor_t factors; n_factor_init(&factors); n_factor(&factors, p - 1, 1); a = n_primitive_root_prime_prefactor(p, &factors); return a; } flint-3.1.3/src/ulong_extras/profile/000077500000000000000000000000001461254215100175745ustar00rootroot00000000000000flint-3.1.3/src/ulong_extras/profile/p-factor.c000066400000000000000000000040361461254215100214560ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #define ITERS 1000 typedef struct { ulong * composites; flint_bitcnt_t bits; } fac_one_line_t; void sample(void * arg, ulong count) { fac_one_line_t * params = (fac_one_line_t *) arg; ulong i, j; mp_limb_t n2; for (i = 0; i < count; i++) { prof_start(); for (j = 0; j < ITERS; j++) { /*n_factor_init(&factors); n_factor(&factors, params->composites[j & 1023], 0); if ((factors.num == 0) || (factors.num == 1 && factors.exp[0] < 2)) flint_printf("Error %wd\n", params->composites[j & 1023]);*/ n2 = n_factor_lehman(params->composites[j & 1023]); if (n2 == params->composites[j & 1023]) flint_printf("Error n = %wd\n", params->composites[j & 1023]); } prof_stop(); } } void fill_array(ulong * ret, flint_bitcnt_t bits, flint_rand_t state) { ulong n; n_factor_t factors; ulong i, primes = (1<<(bits/3))/10 + 1; for (i = 0; i < 1024; i++) { do { n_factor_init(&factors); n = n_randbits(state, bits); } while (n_is_probabprime(n) || (n_factor_trial(&factors, n, primes) != n)); ret[i] = n; } } int main(void) { double min, max; fac_one_line_t params; int i; FLINT_TEST_INIT(state); params.composites = flint_malloc(1024*sizeof(ulong)); flint_printf("factor_one_line:\n"); for (i = 4; i <= 64; i++) { fill_array(params.composites, i, state); params.bits = i; prof_repeat(&min, &max, sample, ¶ms); flint_printf("bits = %d, time is %.3f us\n", i, max/(double)ITERS); } flint_randclear(state); flint_free(params.composites); return 0; } flint-3.1.3/src/ulong_extras/profile/p-factor_pp1.c000066400000000000000000000036651461254215100222450ustar00rootroot00000000000000#include #include "flint.h" #include "ulong_extras.h" #include "profiler.h" #define cpumin 2 FLINT_DLL extern slong n_factor_pp1_table[][2]; void n_factor_pp1_table_insert(slong bits, slong B1, slong count) { n_factor_pp1_table[bits][0] = B1; n_factor_pp1_table[bits][1] = count; } int main(int argc, char** argv) { double tbest = 1.0e300; mp_limb_t nums[1000]; slong i; slong bits, B1, count; mp_limb_t n, cofactor; n_factor_t fac; FLINT_TEST_INIT(state); bits = atol(argv[1]); flint_printf("Looking for 1000 numbers with %ld bits cofactors\n", bits); for (i = 0; i < 1000; ) { n_factor_init(&fac); n = n_randbits(state, bits + n_randint(state, FLINT_BITS - bits + 1)); cofactor = n_factor_trial(&fac, n, FLINT_FACTOR_TRIAL_PRIMES); if (FLINT_BIT_COUNT(cofactor) == bits && !n_is_prime(cofactor)) { nums[i++] = n; if (i % 100 == 0) printf("i = %ld\n", i); } } printf("Done computing table\n"); for (count = 0; count < 6; count++) { for (B1 = 1; ((count == 0 && B1 == 1) || count > 0) && B1 < 10000; B1 = (slong) (1.05*(double)B1) + 1) { double t; int l, loops = 1; n_factor_pp1_table_insert(bits, B1, count); loop: t = 0.0; init_clock(0); prof_start(); for (l = 0; l < loops; l++) { for (i = 0; i < 1000; i++) { n_factor_init(&fac); n_factor(&fac, nums[i], 0); } } prof_stop(); t += get_clock(0); if (t * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } if (t/loops < tbest) { flint_printf("%wd, %wd, %wd, %20f\n", bits, B1, count, t/loops); tbest = t/loops; } } } FLINT_TEST_CLEANUP(state); return 0; } flint-3.1.3/src/ulong_extras/profile/p-gcd.c000066400000000000000000000031771461254215100207420ustar00rootroot00000000000000/* Copyright 2014 Abhinav Baid This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" #define ITERS 1000 typedef struct { ulong * rnums1; ulong * rnums2; flint_bitcnt_t bits1; flint_bitcnt_t bits2; } gcd_t; void sample(void * arg, ulong count) { gcd_t * params = (gcd_t *) arg; ulong i, j; for (i = 0; i < count; i++) { prof_start(); for (j = 0; j < ITERS; j++) { n_gcd(params->rnums2[j & 1023], params->rnums1[j & 1023]); } prof_stop(); } } void fill_array(ulong * ret, flint_bitcnt_t bits, flint_rand_t state) { ulong n; ulong i; for (i = 0; i < 1024; i++) { n = n_randbits(state, bits); ret[i] = n; } } int main(void) { double min, max; gcd_t params; int i; FLINT_TEST_INIT(state); params.rnums1 = flint_malloc(1024*sizeof(ulong)); params.rnums2 = flint_malloc(1024*sizeof(ulong)); flint_printf("n_gcd:\n"); for (i = 1; i <= 64; i++) { fill_array(params.rnums1, i, state); params.bits1 = i; fill_array(params.rnums2, i, state); prof_repeat(&min, &max, sample, ¶ms); flint_printf("bits1 = %d, bits2 = %d, time is %.3f us\n", i, i, max/(double)ITERS); } flint_randclear(state); flint_free(params.rnums1); flint_free(params.rnums2); return 0; } flint-3.1.3/src/ulong_extras/profile/p-is_probabprime_BPSW.c000066400000000000000000000025731461254215100240340ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" typedef struct { ulong bits; } BPSW_t; void sample(void * arg, ulong count) { BPSW_t * params = (BPSW_t *) arg; ulong bits = params->bits; ulong i; mp_limb_t d; FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { int j, res = 1; d = n_randbits(state, bits); while (!n_is_prime(d)) d++; prof_start(); for (j = 0; j < 1000000; j++) res &= n_is_probabprime_BPSW(d); prof_stop(); if (!res) flint_printf("Error\n"); } flint_randclear(state); } int main(void) { double min, max; BPSW_t params; int i; flint_printf("is_probabprime_BPSW:\n"); for (i = 1; i <= 64; i++) { params.bits = i; prof_repeat(&min, &max, sample, ¶ms); flint_printf("bits = %d, min time is %.3f cycles, max time is %.3f cycles\n", i, (min/(double)FLINT_CLOCK_SCALE_FACTOR)/1000000, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/1000000); } return 0; } flint-3.1.3/src/ulong_extras/profile/p-lll_mod_preinv.c000066400000000000000000000035161461254215100232070ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" typedef struct { flint_bitcnt_t bits; ulong type; } info_t; void sample(void * arg, ulong count) { mp_limb_t d, dinv, r = 0; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; ulong type = info->type; ulong i; mp_ptr arr, arr2; FLINT_TEST_INIT(state); arr = (mp_ptr) flint_malloc(1024*sizeof(mp_limb_t)); arr2 = (mp_ptr) flint_malloc(1024*sizeof(mp_limb_t)); for (i = 0; i < count; i++) { int j; d = n_randbits(state, bits); if (d == UWORD(0)) d++; dinv = n_preinvert_limb(d); for (j = 0; j < 1024; j++) { arr[j] = n_randbits(state, FLINT_BITS); arr2[j] = n_randint(state, d); } switch (type) { case 1: prof_start(); for (j = 0; j < UWORD(10000); j++) { r += n_lll_mod_preinv(arr2[j&1023], arr[j&1023], arr[(j+1)&1023], d, dinv); } prof_stop(); break; } } if (r == UWORD(9879875897)) flint_abort(); flint_randclear(state); flint_free(arr); flint_free(arr2); } int main(void) { double min1, max; info_t info; int i; for (i = FLINT_BITS/2 + 1; i <= FLINT_BITS; i++) { info.bits = i; info.type = 1; prof_repeat(&min1, &max, sample, (void *) &info); flint_printf("bits %d, ll_inv %.1f c/l\n", i, (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/10000 ); } return 0; } flint-3.1.3/src/ulong_extras/profile/p-mod2_precomp.c000066400000000000000000000025471461254215100225730ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t d, r = 0; double dpre; ulong i; mp_ptr array = (mp_ptr) flint_malloc(1024*sizeof(mp_limb_t)); FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { int j; d = n_randtest(state); if (d == UWORD(0)) d++; dpre = n_precompute_inverse(d); for (j = 0; j < 1024; j++) { array[j] = n_randtest(state); } prof_start(); for (j = 0; j < 10000; j++) { r += n_mod2_precomp(array[j&1023], d, dpre); } prof_stop(); } if (r == 0) flint_abort(); flint_randclear(state); flint_free(array); } int main(void) { double min, max; prof_repeat(&min, &max, sample, NULL); flint_printf("mod2_precomp min time is %.3f cycles, max time is %.3f cycles\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/10000.0, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/10000.0); return 0; } flint-3.1.3/src/ulong_extras/profile/p-mod2_preinv.c000066400000000000000000000066721461254215100224340ustar00rootroot00000000000000/* Copyright 2010 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" typedef struct { flint_bitcnt_t bits; ulong type; } info_t; void sample(void * arg, ulong count) { mp_limb_t d, dinv, r = 0; double dpre; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; ulong type = info->type; ulong i; mp_ptr arr = (mp_ptr) flint_malloc(1024*sizeof(mp_limb_t)); FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { int j; d = n_randbits(state, bits); if (d == UWORD(0)) d++; dinv = n_preinvert_limb(d); dpre = n_precompute_inverse(d); for (j = 0; j < 1024; j++) { arr[j] = n_randbits(state, FLINT_BITS); } switch (type) { /*case 1: prof_start(); for (mp_size_t j = 0; j < UWORD(10000); j++) { r += n_empty(arr[j&1023], d, dinv); } prof_stop(); break;*/ case 2: prof_start(); for (j = 0; j < 10000; j++) { r += n_mod2_preinv(arr[j&1023], d, dinv); } prof_stop(); break; /*case 3: prof_start(); for (mp_size_t j = 0; j < UWORD(10000); j++) { r += n_mod3_preinv(arr[j&1023], d, dinv); } prof_stop(); break;*/ case 4: prof_start(); for (j = 0; j < 10000; j++) { r += n_mod2_precomp(arr[j&1023], d, dpre); } prof_stop(); break; case 5: prof_start(); for (j = 0; j < 10000; j++) { r += n_mod_precomp(arr[j&1023], d, dpre); } prof_stop(); break; } } if (r == UWORD(9879875897)) flint_abort(); flint_randclear(state); flint_free(arr); } int main(void) { double min2, min4, min5, max; info_t info; int i; for (i = 1; i <= FLINT_BITS; i++) { info.bits = i; /* info.type = 1; prof_repeat(&min1, &max, sample, (void *) &info); */ info.type = 2; prof_repeat(&min2, &max, sample, (void *) &info); /* info.type = 3; prof_repeat(&min3, &max, sample, (void *) &info); */ info.type = 4; prof_repeat(&min4, &max, sample, (void *) &info); if (i >= 32 && i <= 53) { info.type = 5; prof_repeat(&min5, &max, sample, (void *) &info); flint_printf("bits %d, inv2 %.1f c/l, pre2 %.1f c/l, pre %.1f c/l\n", i, /* (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/10000, */ (min2/(double)FLINT_CLOCK_SCALE_FACTOR)/10000, /* (min3/(double)FLINT_CLOCK_SCALE_FACTOR)/10000, */ (min4/(double)FLINT_CLOCK_SCALE_FACTOR)/10000, (min5/(double)FLINT_CLOCK_SCALE_FACTOR)/10000 ); } else { flint_printf("bits %d, inv2 %.1f c/l, pre2 %.1f c/l\n", i, /* (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/10000, */ (min2/(double)FLINT_CLOCK_SCALE_FACTOR)/10000, /* (min3/(double)FLINT_CLOCK_SCALE_FACTOR)/10000, */ (min4/(double)FLINT_CLOCK_SCALE_FACTOR)/10000 ); } } return 0; } flint-3.1.3/src/ulong_extras/profile/p-mod_precomp.c000066400000000000000000000026151461254215100225050ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t d, bits; double dpre; ulong i; mp_ptr array = (mp_ptr) flint_malloc(1000*sizeof(mp_limb_t)); FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { int j; bits = n_randint(state, 53) + 1; d = n_randbits(state, bits); dpre = n_precompute_inverse(d); for (j = 0; j < 1000; j++) { if (bits <= 32) array[j] = n_randint(state, d*d); else array[j] = n_randtest(state); } prof_start(); for (j = 0; j < 1000; j++) { array[j] = n_mod_precomp(array[j], d, dpre); } prof_stop(); } flint_randclear(state); flint_free(array); } int main(void) { double min, max; prof_repeat(&min, &max, sample, NULL); flint_printf("mod_precomp min time is %.3f cycles, max time is %.3f cycles\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/1000, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/1000); return 0; } flint-3.1.3/src/ulong_extras/profile/p-mulmod2_preinv.c000066400000000000000000000025611461254215100231430ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t a, d, dinv; mp_ptr array = (mp_ptr) flint_malloc(1000*sizeof(mp_limb_t)); ulong i; FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { int j; mp_limb_t bits = n_randint(state, 53) + 1; d = n_randbits(state, bits); a = n_randint(state, d); dinv = n_preinvert_limb(d); for (j = 0; j < 1000; j++) { array[j] = n_randint(state, d); } prof_start(); for (j = 0; j < 1000; j++) { array[j] = n_mulmod2_preinv(a, array[j], d, dinv); } prof_stop(); } flint_randclear(state); flint_free(array); } int main(void) { double min, max; prof_repeat(&min, &max, sample, NULL); flint_printf("mulmod2_precomp min time is %.3f cycles, max time is %.3f cycles\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/1000, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/1000); return 0; } flint-3.1.3/src/ulong_extras/profile/p-mulmod_precomp.c000066400000000000000000000025761461254215100232310ustar00rootroot00000000000000/* Copyright 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { ulong i; mp_limb_t a, d; double dpre; mp_ptr array = (mp_ptr) flint_malloc(1000*sizeof(mp_limb_t)); FLINT_TEST_INIT(state); for (i = 0; i < count; i++) { int j; mp_limb_t bits = n_randint(state, 53) + 1; d = n_randbits(state, bits); a = n_randint(state, d); dpre = n_precompute_inverse(d); for (j = 0; j < 1000; j++) { array[i] = n_randint(state, d); } prof_start(); for (j = 0; j < 1000; j++) { array[j] = n_mulmod_precomp(a, array[j], d, dpre); } prof_stop(); } flint_randclear(state); flint_free(array); } int main(void) { double min, max; prof_repeat(&min, &max, sample, NULL); flint_printf("mulmod_precomp min time is %.3f cycles, max time is %.3f cycles\n", (min/(double)FLINT_CLOCK_SCALE_FACTOR)/1000, (max/(double)FLINT_CLOCK_SCALE_FACTOR)/1000); return 0; } flint-3.1.3/src/ulong_extras/profile/timings.txt000066400000000000000000000162731461254215100220200ustar00rootroot00000000000000K10-2: Comparing an empty function with the old n_mod2_preinv, the new n_mod2_preinv, n_mod2_precomp and n_mod_precomp. The timings are all for a%n with a of FLINT_BITS bits and n of the given number of bits. bits 1, empty 12.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 73.6 c/l bits 2, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 74.5 c/l bits 3, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 71.4 c/l bits 4, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 68.1 c/l bits 5, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 67.4 c/l bits 6, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 68.8 c/l bits 7, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 67.7 c/l bits 8, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 69.7 c/l bits 9, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 71.4 c/l bits 10, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 71.5 c/l bits 11, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 61.4 c/l bits 12, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 52.2 c/l bits 13, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 46.1 c/l bits 14, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 40.1 c/l bits 15, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 37.5 c/l bits 16, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 36.3 c/l bits 17, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.7 c/l bits 18, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.4 c/l bits 19, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.2 c/l bits 20, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.1 c/l bits 21, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.1 c/l bits 22, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 23, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 24, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 25, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 26, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 27, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 28, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 29, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 30, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 31, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 32, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 33, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 34, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 35, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 36, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 37, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 38, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 39, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 40, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 41, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 42, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 43, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 44, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 45, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 46, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 47, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 48, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 49, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 50, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 51, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 52, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 53, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l, pre 29.0 c/l bits 54, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 55, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 56, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 57, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 58, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 59, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 60, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 61, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 62, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 63, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 35.0 c/l bits 64, empty 9.0 c/l, old 27.0 c/l, new 21.0 c/l, pre2 16.2 c/l timings for n_ll_mod_preinv (old function was about 60 c/l (note empty function takes about 11 cycles) bits 1, ll_inv 43.0 c/l bits 2, ll_inv 43.1 c/l bits 3, ll_inv 41.4 c/l bits 4, ll_inv 40.5 c/l bits 5, ll_inv 39.1 c/l bits 6, ll_inv 39.9 c/l bits 7, ll_inv 39.3 c/l bits 8, ll_inv 39.5 c/l bits 9, ll_inv 39.4 c/l bits 10, ll_inv 39.3 c/l bits 11, ll_inv 38.9 c/l bits 12, ll_inv 38.5 c/l bits 13, ll_inv 40.4 c/l bits 14, ll_inv 37.8 c/l bits 15, ll_inv 39.0 c/l bits 16, ll_inv 38.9 c/l bits 17, ll_inv 39.0 c/l bits 18, ll_inv 39.6 c/l bits 19, ll_inv 38.1 c/l bits 20, ll_inv 38.9 c/l bits 21, ll_inv 39.3 c/l bits 22, ll_inv 38.4 c/l bits 23, ll_inv 39.1 c/l bits 24, ll_inv 39.5 c/l bits 25, ll_inv 39.2 c/l bits 26, ll_inv 38.9 c/l bits 27, ll_inv 39.8 c/l bits 28, ll_inv 38.9 c/l bits 29, ll_inv 40.0 c/l bits 30, ll_inv 38.3 c/l bits 31, ll_inv 39.3 c/l bits 32, ll_inv 39.1 c/l bits 33, ll_inv 39.2 c/l bits 34, ll_inv 39.8 c/l bits 35, ll_inv 39.8 c/l bits 36, ll_inv 39.1 c/l bits 37, ll_inv 39.4 c/l bits 38, ll_inv 38.5 c/l bits 39, ll_inv 39.1 c/l bits 40, ll_inv 39.5 c/l bits 41, ll_inv 39.5 c/l bits 42, ll_inv 40.5 c/l bits 43, ll_inv 38.5 c/l bits 44, ll_inv 37.6 c/l bits 45, ll_inv 38.8 c/l bits 46, ll_inv 38.1 c/l bits 47, ll_inv 39.5 c/l bits 48, ll_inv 38.9 c/l bits 49, ll_inv 39.5 c/l bits 50, ll_inv 39.1 c/l bits 51, ll_inv 38.5 c/l bits 52, ll_inv 39.3 c/l bits 53, ll_inv 38.5 c/l bits 54, ll_inv 40.0 c/l bits 55, ll_inv 38.9 c/l bits 56, ll_inv 39.4 c/l bits 57, ll_inv 38.4 c/l bits 58, ll_inv 38.6 c/l bits 59, ll_inv 39.0 c/l bits 60, ll_inv 39.5 c/l bits 61, ll_inv 38.8 c/l bits 62, ll_inv 39.4 c/l bits 63, ll_inv 38.4 c/l bits 64, ll_inv 38.1 c/l n_lll_mod_preinv (there was no old function, but it would have been something like 113 cycles) - empty takes 13 cycles bits 33, ll_inv 135.1 c/l bits 34, ll_inv 135.2 c/l bits 35, ll_inv 45.1 c/l bits 36, ll_inv 45.1 c/l bits 37, ll_inv 45.0 c/l bits 38, ll_inv 45.1 c/l bits 39, ll_inv 45.1 c/l bits 40, ll_inv 45.1 c/l bits 41, ll_inv 45.1 c/l bits 42, ll_inv 45.0 c/l bits 43, ll_inv 45.0 c/l bits 44, ll_inv 45.1 c/l bits 45, ll_inv 45.1 c/l bits 46, ll_inv 45.1 c/l bits 47, ll_inv 45.1 c/l bits 48, ll_inv 45.1 c/l bits 49, ll_inv 45.1 c/l bits 50, ll_inv 45.1 c/l bits 51, ll_inv 45.0 c/l bits 52, ll_inv 45.1 c/l bits 53, ll_inv 45.0 c/l bits 54, ll_inv 45.1 c/l bits 55, ll_inv 45.1 c/l bits 56, ll_inv 45.0 c/l bits 57, ll_inv 45.0 c/l bits 58, ll_inv 45.1 c/l bits 59, ll_inv 45.1 c/l bits 60, ll_inv 45.1 c/l bits 61, ll_inv 45.1 c/l bits 62, ll_inv 45.1 c/l bits 63, ll_inv 45.1 c/l bits 64, ll_inv 44.8 c/l flint-3.1.3/src/ulong_extras/randomisation.c000066400000000000000000000103251461254215100211500ustar00rootroot00000000000000/* Copyright (C) 2007-2009 William Hart Copyright (C) 2008 Peter Shrimpton Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2011 Fredrik Johansson Copyright (C) 2017 Apoorv Mishra This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" mp_limb_t n_randbits(flint_rand_t state, unsigned int bits) { if (bits == 0) return UWORD(0); else return (UWORD(1) << (bits - 1)) | n_randint(state, l_shift(UWORD(1), bits)); } ulong n_randint(flint_rand_t state, ulong limit) { if (limit == UWORD(0)) return n_randlimb(state); else return n_randlimb(state) % limit; } mp_limb_t n_urandint(flint_rand_t state, mp_limb_t limit) { if ((limit & (limit - 1)) == 0) { return n_randlimb(state) & (limit - 1); } else { const mp_limb_t rand_max = UWORD_MAX; mp_limb_t bucket_size, num_of_buckets, rand_within_range; bucket_size = 1 + (rand_max - limit + 1)/limit; num_of_buckets = bucket_size*limit; do { rand_within_range = n_randlimb(state); } while (rand_within_range >= num_of_buckets); return rand_within_range/bucket_size; } } #if FLINT64 mp_limb_t n_randlimb(flint_rand_t state) { state->__randval = (state->__randval*UWORD(13282407956253574709) + UWORD(286824421)); state->__randval2 = (state->__randval2*UWORD(7557322358563246341) + UWORD(286824421)); return (state->__randval>>32) + ((state->__randval2>>32) << 32); } #else mp_limb_t n_randlimb(flint_rand_t state) { state->__randval = (state->__randval*UWORD(1543932465) + UWORD(1626832771)); state->__randval2 = (state->__randval2*UWORD(2495927737) + UWORD(1626832771)); return (state->__randval>>16) + ((state->__randval2>>16) << 16); } #endif mp_limb_t n_randtest_bits(flint_rand_t state, int bits) { mp_limb_t m; mp_limb_t n; m = n_randlimb(state); if (m & UWORD(7)) { n = n_randbits(state, bits); } else { m >>= 3; switch (m & UWORD(7)) { case 0: n = 0; break; case 1: n = 1; break; case 2: n = COEFF_MAX; break; case 3: n = WORD_MAX; break; case 4: n = UWORD_MAX; break; case 5: n = (UWORD(1)<= UWORD_MAX_PRIME); rand = n_nextprime(rand, proved); } else if (bits == 2) { rand = 2 + n_randint(state, 2); } else { do { rand = n_randbits(state, bits); rand = n_nextprime(rand, proved); } while ((rand >> bits) > WORD(0)); } return rand; } mp_limb_t n_randtest_prime(flint_rand_t state, int proved) { return n_randprime(state, 2 + n_randint(state, FLINT_BITS - 1), proved); } flint-3.1.3/src/ulong_extras/remove.c000066400000000000000000000023401461254215100175740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" int n_remove(mp_limb_t * n, mp_limb_t p) { int exp, i; mp_limb_t powp[6]; mp_limb_t quot, rem; if (p == 2) { exp = flint_ctz(*n); if (exp) (*n) >>= exp; return exp; } powp[0] = p; for (i = 0; ; i++) { if ((*n) < powp[i]) break; quot = (*n) / powp[i]; rem = (*n) - quot * powp[i]; if (rem != UWORD(0)) break; powp[i + 1] = powp[i] * powp[i]; (*n) = quot; } exp = (1 << i) - 1; while (i > 0) { i--; if ((*n) < powp[i]) continue; quot = (*n) / powp[i]; rem = (*n) - quot * powp[i]; if (rem == UWORD(0)) { exp += (UWORD(1) << i); (*n) = quot; } } return exp; } flint-3.1.3/src/ulong_extras/remove2_precomp.c000066400000000000000000000015601461254215100214060ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" int n_remove2_precomp(mp_limb_t * n, mp_limb_t p, double ppre) { int exp = 0; mp_limb_t quot, rem = UWORD(0); if (p == 2) { exp = flint_ctz(*n); if (exp) (*n) >>= exp; return exp; } do { if ((*n) < p) break; rem = n_divrem2_precomp(", *n, p, ppre); if (rem) break; exp++; (*n) = quot; } while (1); return exp; } flint-3.1.3/src/ulong_extras/revbin.c000066400000000000000000000061411461254215100175670ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" static const unsigned char flint_revtab[] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; /* Computes the reverse binary representation of a number of b bits. */ ulong n_revbin(ulong n, ulong b) { FLINT_ASSERT(b <= FLINT_BITS); if (b <= 8) return flint_revtab[n & 0xFF] >> (8 - b); else { #if FLINT64 /* swap adjacent bits */ n = (((n & 0xaaaaaaaaaaaaaaaa) >> 1) | ((n & 0x5555555555555555) << 1)); /* swap adjacent pairs of bits */ n = (((n & 0xcccccccccccccccc) >> 2) | ((n & 0x3333333333333333) << 2)); /* swap adjacent nibbles */ n = (((n & 0xf0f0f0f0f0f0f0f0) >> 4) | ((n & 0x0f0f0f0f0f0f0f0f) << 4)); #else /* swap adjacent bits */ n = (((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)); /* swap adjacent pairs of bits */ n = (((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)); /* swap adjacent nibbles */ n = (((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)); #endif byte_swap(n); return n >> (FLINT_BITS - b); } } flint-3.1.3/src/ulong_extras/root.c000066400000000000000000000124551461254215100172720ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Fredrik Johansson Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" /* A table of precomputed inverses of values from 1 to 64 inv_table[n] = i/n for all n in range[1, 64] inv_table[0] is set to 0, albeit it will never be called */ static const double inv_table[] = { 0.000000000000000, 1.000000000000000, 0.500000000000000, 0.333333333333333, 0.250000000000000, 0.200000000000000, 0.166666666666667, 0.142857142857143, 0.125000000000000, 0.111111111111111, 0.100000000000000, 0.090909090909091, 0.083333333333333, 0.076923076923077, 0.071428571428571, 0.066666666666667, 0.062500000000000, 0.058823529411765, 0.055555555555556, 0.052631578947368, 0.050000000000000, 0.047619047619048, 0.045454545454545, 0.043478260869565, 0.041666666666667, 0.040000000000000, 0.038461538461538, 0.037037037037037, 0.035714285714286, 0.034482758620690, 0.033333333333333, 0.032258064516129, 0.031250000000000, 0.030303030303030, 0.029411764705882, 0.028571428571429, 0.027777777777778, 0.027027027027027, 0.026315789473684, 0.025641025641026, 0.025000000000000, 0.024390243902439, 0.023809523809524, 0.023255813953488, 0.022727272727273, 0.022222222222222, 0.021739130434783, 0.021276595744681, 0.020833333333333, 0.020408163265306, 0.020000000000000, 0.019607843137255, 0.019230769230769, 0.018867924528302, 0.018518518518519, 0.018181818181818, 0.017857142857143, 0.017543859649123, 0.017241379310345, 0.016949152542373, 0.016666666666667, 0.016393442622951, 0.016129032258065, 0.015873015873016, 0.015625000000000 }; /* this table consists 65 values */ /* This table has the max possible base for a given root. max_base[n] = UWORD_MAX^(1/n) for n in range [1, FLINT_BITS] max_base[0] is set to 0, although it will never be called */ static const mp_limb_t max_base[] = { #ifdef FLINT64 UWORD(0), UWORD_MAX, UWORD(4294967296), UWORD(2642245), UWORD(65536), UWORD(7131), UWORD(1625), UWORD(565), UWORD(256), UWORD(138), UWORD(84), UWORD(56), UWORD(40), UWORD(30), UWORD(23), UWORD(19), UWORD(16), UWORD(13), UWORD(11), UWORD(10), UWORD(9), UWORD(8), UWORD(7), UWORD(6), UWORD(6), UWORD(5), UWORD(5), UWORD(5), UWORD(4), UWORD(4), UWORD(4), UWORD(4), UWORD(4), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2) #else UWORD(0), UWORD(4294967295), UWORD(65535), UWORD(1625), UWORD(255), UWORD(84), UWORD(40), UWORD(23), UWORD(15), UWORD(11), UWORD(9), UWORD(7), UWORD(6), UWORD(5), UWORD(4), UWORD(4), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2) #endif }; /* this table consists of 65 values in case of FLINT64, otherwise 33 */ mp_limb_t n_root(mp_limb_t n, mp_limb_t root) { mp_limb_t x, currval, base, upper_limit; double dx; if (!n || !root) return 0; if (root == 1) return n; if (root == 2) return n_sqrt(n); if (root == 3) return n_cbrt(n); if (root >= FLINT_BITS || (UWORD(1) << root) > n) return 1; upper_limit = max_base[root]; /* n <= upper_limit^root */ x = n_root_estimate((double)n, root); /* one round of newton iteration */ currval = n_pow(x, root-1); dx = n / currval; dx -= x; dx *= inv_table[root]; dx = floor(dx); x += dx; base = x; if (base >= upper_limit) base = upper_limit - 1; currval = n_pow(base, root); if (currval == n) goto final; while (currval <= n) { (base) += 1; currval = n_pow(base, root); if (base == upper_limit) break; } while (currval > n) { (base) -= 1; currval = n_pow(base, root); } final: return base; } flint-3.1.3/src/ulong_extras/root_estimate.c000066400000000000000000000116321461254215100211610ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Fredrik Johansson Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" /* this table contains the value of UWORD_MAX / n, for n in range [1, FLINT_BITS] */ static const mp_limb_t mul_factor[] = { #ifdef FLINT64 UWORD(0), UWORD_MAX, UWORD(9223372036854775807), UWORD(6148914691236517205), UWORD(4611686018427387903), UWORD(3689348814741910323), UWORD(3074457345618258602), UWORD(2635249153387078802), UWORD(2305843009213693951), UWORD(2049638230412172401), UWORD(1844674407370955161), UWORD(1676976733973595601), UWORD(1537228672809129301), UWORD(1418980313362273201), UWORD(1317624576693539401), UWORD(1229782938247303441), UWORD(1152921504606846975), UWORD(1085102592571150095), UWORD(1024819115206086200), UWORD(970881267037344821), UWORD(922337203685477580), UWORD(878416384462359600), UWORD(838488366986797800), UWORD(802032351030850070), UWORD(768614336404564650), UWORD(737869762948382064), UWORD(709490156681136600), UWORD(683212743470724133), UWORD(658812288346769700), UWORD(636094623231363848), UWORD(614891469123651720), UWORD(595056260442243600), UWORD(576460752303423487), UWORD(558992244657865200), UWORD(542551296285575047), UWORD(527049830677415760), UWORD(512409557603043100), UWORD(498560650640798692), UWORD(485440633518672410), UWORD(472993437787424400), UWORD(461168601842738790), UWORD(449920587163647600), UWORD(439208192231179800), UWORD(428994048225803525), UWORD(419244183493398900), UWORD(409927646082434480), UWORD(401016175515425035), UWORD(392483916461905353), UWORD(384307168202282325), UWORD(376464164769582686), UWORD(368934881474191032), UWORD(361700864190383365), UWORD(354745078340568300), UWORD(348051774975651917), UWORD(341606371735362066), UWORD(335395346794719120), UWORD(329406144173384850), UWORD(323627089012448273), UWORD(318047311615681924), UWORD(312656679215416129), UWORD(307445734561825860), UWORD(302405640552615600), UWORD(297528130221121800), UWORD(292805461487453200), UWORD(288230376151711743) #else UWORD(0), UWORD_MAX, UWORD(2147483647), UWORD(1431655765), UWORD(1073741823), UWORD(858993459), UWORD(715827882), UWORD(613566756), UWORD(536870911), UWORD(477218588), UWORD(429496729), UWORD(390451572), UWORD(357913941), UWORD(330382099), UWORD(306783378), UWORD(286331153), UWORD(268435455), UWORD(252645135), UWORD(238609294), UWORD(226050910), UWORD(214748364), UWORD(204522252), UWORD(195225786), UWORD(186737708), UWORD(178956970), UWORD(171798691), UWORD(165191049), UWORD(159072862), UWORD(153391689), UWORD(148102320), UWORD(143165576), UWORD(138547332), UWORD(134217727), #endif }; /* this table consists of 65 values in case of FLINT64, otherwise 33 */ /* function to get a good approximation of the cube root */ /* Algorithm for this approximation is mentioned in this article */ /* https://en.wikipedia.org/wiki/Fast_inverse_square_root */ /* Instead of the inverse square root, we calculate the nth root */ mp_limb_t n_root_estimate(double a, int n) { typedef union { slong uword_val; #ifdef FLINT64 double double_val; #else float double_val; #endif } uni; uni alias; ulong i, hi, lo, s; alias.double_val = a; #ifdef FLINT64 s = ((1 << 10) - 1); s <<= 52; #else s = ((1 << 7) - 1); s <<= 23; #endif i = alias.uword_val; i -= s; umul_ppmm(hi, lo, i, mul_factor[n]); i = hi; i += s; alias.uword_val = i; return (mp_limb_t)alias.double_val; } flint-3.1.3/src/ulong_extras/rootrem.c000066400000000000000000000130461461254215100177730ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Fredrik Johansson Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" /* A table of precomputed inverses of values from 1 to 64 inv_table[n] = i/n for all n in range[1, 64] inv_table[0] is set to 0, albeit it will never be called */ static const double inv_table[] = { 0.000000000000000, 1.000000000000000, 0.500000000000000, 0.333333333333333, 0.250000000000000, 0.200000000000000, 0.166666666666667, 0.142857142857143, 0.125000000000000, 0.111111111111111, 0.100000000000000, 0.090909090909091, 0.083333333333333, 0.076923076923077, 0.071428571428571, 0.066666666666667, 0.062500000000000, 0.058823529411765, 0.055555555555556, 0.052631578947368, 0.050000000000000, 0.047619047619048, 0.045454545454545, 0.043478260869565, 0.041666666666667, 0.040000000000000, 0.038461538461538, 0.037037037037037, 0.035714285714286, 0.034482758620690, 0.033333333333333, 0.032258064516129, 0.031250000000000, 0.030303030303030, 0.029411764705882, 0.028571428571429, 0.027777777777778, 0.027027027027027, 0.026315789473684, 0.025641025641026, 0.025000000000000, 0.024390243902439, 0.023809523809524, 0.023255813953488, 0.022727272727273, 0.022222222222222, 0.021739130434783, 0.021276595744681, 0.020833333333333, 0.020408163265306, 0.020000000000000, 0.019607843137255, 0.019230769230769, 0.018867924528302, 0.018518518518519, 0.018181818181818, 0.017857142857143, 0.017543859649123, 0.017241379310345, 0.016949152542373, 0.016666666666667, 0.016393442622951, 0.016129032258065, 0.015873015873016, 0.015625000000000 }; /* this table consists 65 values */ /* This table has the max possible base for a given root. max_base[n] = UWORD_MAX^(1/n) for n in range [1, FLINT_BITS] max_base[0] is set to 0, although it will never be called */ static const mp_limb_t max_base[] = { #ifdef FLINT64 UWORD(0), UWORD_MAX, UWORD(4294967296), UWORD(2642245), UWORD(65536), UWORD(7131), UWORD(1625), UWORD(565), UWORD(256), UWORD(138), UWORD(84), UWORD(56), UWORD(40), UWORD(30), UWORD(23), UWORD(19), UWORD(16), UWORD(13), UWORD(11), UWORD(10), UWORD(9), UWORD(8), UWORD(7), UWORD(6), UWORD(6), UWORD(5), UWORD(5), UWORD(5), UWORD(4), UWORD(4), UWORD(4), UWORD(4), UWORD(4), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2) #else UWORD(0), UWORD(4294967295), UWORD(65535), UWORD(1625), UWORD(255), UWORD(84), UWORD(40), UWORD(23), UWORD(15), UWORD(11), UWORD(9), UWORD(7), UWORD(6), UWORD(5), UWORD(4), UWORD(4), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2) #endif }; /* this table consists of 65 values in case of FLINT64, otherwise 33 */ mp_limb_t n_rootrem(mp_limb_t* remainder, mp_limb_t n, mp_limb_t root) { mp_limb_t x, currval, base, upper_limit; double dx; if (!root) return 0; if (n == 0 || root == 1) { *remainder = 0; return n; } if (root == 2) return n_sqrtrem(remainder, n); if (root == 3) return n_cbrtrem(remainder, n); if (root >= FLINT_BITS || (UWORD(1) << root) > n) { *remainder = n - 1; return 1; } upper_limit = max_base[root]; /* n <= upper_limit^root */ x = n_root_estimate((double)n, root); /* one round of newton iteration */ currval = n_pow(x, root-1); dx = n / currval; dx -= x; dx *= inv_table[root]; dx = floor(dx); x += dx; base = x; if (base >= upper_limit) base = upper_limit - 1; currval = n_pow(base, root); if (currval == n) goto final; while (currval <= n) { (base) += 1; currval = n_pow(base, root); if (base == upper_limit) break; } while (currval > n) { (base) -= 1; currval = n_pow(base, root); } final: *remainder = base; *remainder = n_pow(*remainder, root); *remainder = n - *remainder; return base; } flint-3.1.3/src/ulong_extras/sizeinbase.c000066400000000000000000000010561461254215100204360ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int n_sizeinbase(mp_limb_t n, int base) { if (n == 0) return 1; return n_flog(n, base) + 1; } flint-3.1.3/src/ulong_extras/sqrt.c000066400000000000000000000011671461254215100172760ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" mp_limb_t n_sqrt(mp_limb_t a) { mp_limb_t is; is = (mp_limb_t) sqrt((double) a); is -= (is*is > a); #if FLINT64 if (is == UWORD(4294967296)) is--; #endif return is; } flint-3.1.3/src/ulong_extras/sqrtmod.c000066400000000000000000000053351461254215100177770ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" mp_limb_t n_sqrtmod(mp_limb_t a, mp_limb_t p) { slong i, r, m, iter; mp_limb_t p1, k, b, g, bpow, gpow, res; mp_limb_t pinv; if (a <= 1) { return a; } /* just do a brute force search */ if (p < 600) { mp_limb_t t, t2; if (p > 50 && n_jacobi_unsigned(a, p) == -1) return 0; t = t2 = 0; while (t < (p - 1) / 2) { t2 = n_addmod(t2, 2*t + 1, p); t++; if (t2 == a) return t; } return 0; } if (n_is_square(p)) /* modulus is a square */ return 0; if ((p & 1) == 0) /* modulus is even */ return 0; pinv = n_preinvert_limb(p); if (n_jacobi_unsigned(a, p) == -1) return 0; if ((p & UWORD(3)) == 3) { return n_powmod2_ui_preinv(a, (p + 1)/4, p, pinv); /* p == 2^B - 1 isn't prime */ } if ((p & UWORD(7)) == 5) { b = n_powmod2_ui_preinv(a, (p + 3)/8, p, pinv); /* p == 2^B - 3 isn't prime */ g = n_mulmod2_preinv(b, b, p, pinv); if (g == a) return b; g = n_powmod2_ui_preinv(2, (p - 1)/4, p, pinv); return n_mulmod2_preinv(g, b, p, pinv); } r = 0; p1 = p - 1; do { p1 >>= UWORD(1); r++; } while ((p1 & UWORD(1)) == 0); b = n_powmod2_ui_preinv(a, p1, p, pinv); for (k = 3; ; k+=2) /* 2 is a quadratic residue mod p = 8k + 1 */ { if (n_jacobi_unsigned(k, p) == -1) break; } g = n_powmod2_ui_preinv(k, p1, p, pinv); res = n_powmod2_ui_preinv(a, (p1 + 1) / 2, p, pinv); iter = r - 1; /* maximum number of iterations possible if p is prime */ while (b != 1) { bpow = b; m = 0; do { bpow = n_mulmod2_preinv(bpow, bpow, p, pinv); m++; } while (m < r && bpow != 1); gpow = g; for (i = 1; i < r - m; i++) { gpow = n_mulmod2_preinv(gpow, gpow, p, pinv); } res = n_mulmod2_preinv(res, gpow, p, pinv); g = n_mulmod2_preinv(gpow, gpow, p, pinv); b = n_mulmod2_preinv(b, g, p, pinv); r = m; if (iter-- == 0) return 0; /* too many iterations, p is not prime, prevents hang */ } return res; } flint-3.1.3/src/ulong_extras/sqrtmod_primepow.c000066400000000000000000000165311461254215100217210ustar00rootroot00000000000000/* Copyright (C) 2012 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" slong n_sqrtmod_2pow(mp_limb_t ** sqrt, mp_limb_t a, slong exp) { mp_limb_t r = (a & 1); mp_limb_t * s; if (exp == 0) /* special case for sqrt of 0 mod 1 */ { *sqrt = flint_malloc(sizeof(mp_limb_t)); (*sqrt)[0] = 0; return 1; } if (exp == 1) /* special case mod 2 */ { *sqrt = flint_malloc(sizeof(mp_limb_t)); if (r) (*sqrt)[0] = 1; else (*sqrt)[0] = 0; return 1; } if (exp == 2) /* special case mod 4 */ { r = (a & 3); if (r < 2) /* 0, 1 mod 4 */ { *sqrt = flint_malloc(sizeof(mp_limb_t)*2); (*sqrt)[0] = r; (*sqrt)[1] = r + 2; return 2; } else /* 2, 3 mod 4 */ { *sqrt = NULL; return 0; } } if (r) /* a is odd */ { mp_limb_t roots[2]; slong i, ex, pow; if ((a & 7) != 1) /* check square root exists */ { *sqrt = NULL; return 0; } roots[0] = 1; /* one of each pair of square roots mod 8 */ roots[1] = 3; pow = 8; for (ex = 3; ex < exp; ex++, pow *= 2) /* lift roots */ { i = 0; r = roots[0]; if (((r*r) & (2*pow - 1)) == (a & (2*pow - 1))) roots[i++] = r; r = pow - r; if (((r*r) & (2*pow - 1)) == (a & (2*pow - 1))) { roots[i++] = r; if (i == 2) continue; } r = roots[1]; if (((r*r) & (2*pow - 1)) == (a & (2*pow - 1))) { roots[i++] = r; if (i == 2) continue; } r = pow - r; roots[i] = r; } *sqrt = flint_malloc(sizeof(mp_limb_t)*4); (*sqrt)[0] = roots[0]; /* write out both pairs of roots */ (*sqrt)[1] = pow - roots[0]; (*sqrt)[2] = roots[1]; (*sqrt)[3] = pow - roots[1]; return 4; } else /* a is even */ { slong i, k, num, pow; for (k = 2; k <= exp; k++) /* find highest power of 2 dividing a */ { if (a & ((UWORD(1)<. */ #include "ulong_extras.h" /* compute square roots of a modulo m given factorisation of m */ slong n_sqrtmodn(mp_limb_t ** sqrt, mp_limb_t a, n_factor_t * fac) { mp_limb_t m = 1, minv = 1; slong i, j, num; mp_limb_t * x, * sn, * ind, ** s; /* Check if modulus is one, that is, it has a trivial representation */ if (fac->num == 0) { *sqrt = flint_malloc(sizeof(mp_limb_t)); (*sqrt)[0] = 0; return 1; } x = flint_malloc(sizeof(mp_limb_t)*fac->num); sn = flint_malloc(sizeof(mp_limb_t)*fac->num); ind = flint_malloc(sizeof(mp_limb_t)*fac->num); s = flint_malloc(sizeof(mp_limb_t *)*fac->num); /* compute prime powers and square roots of a mod x_i = p_i^r_i*/ num = 1; for (i = 0; i < fac->num; i++) { ind[i] = 0; x[i] = n_pow(fac->p[i], fac->exp[i]); sn[i] = n_sqrtmod_primepow(s + i, a % x[i], fac->p[i], fac->exp[i]); num *= sn[i]; if (num == 0) { for (j = 0; j < i; j++) flint_free(s[j]); flint_free(ind); flint_free(x); flint_free(s); flint_free(sn); *sqrt = NULL; return 0; } } *sqrt = flint_malloc(num*sizeof(mp_limb_t)); /* compute values s_i = 1 mod x_i and s_i = 0 mod x_j for j != i then replace sqrts a_i with a_i * s_i mod m = x_1*x_2*...*x_n */ for (i = 0; i < fac->num; i++) { mp_limb_t xp = 1, si; /* compute product of x_j for j != i */ for (j = 0; j < i; j++) xp *= x[j]; for (j = i + 1; j < fac->num; j++) xp *= x[j]; /* compute m and precomputed inverse */ if (i == 0) { m = xp*x[i]; minv = n_preinvert_limb(m); } /* compute s_i */ si = xp*n_invmod(xp % x[i], x[i]); /* a_i*s_i mod m for each sqrt a_i of a mod x_i*/ for (j = 0; j < sn[i]; j++) s[i][j] = n_mulmod2_preinv(si, s[i][j], m, minv); } /* compute all the square roots by computing sum_{i=0}^{fac->num} s[i][j] for each different permutation of j's, all modulo m */ for (i = 0; i < num; i++) /* loop through every possibility */ { /* compute next root */ (*sqrt)[i] = 0; for (j = 0; j < fac->num; j++) (*sqrt)[i] = n_addmod((*sqrt)[i], s[j][ind[j]], m); /* increment to next set of indices */ for (j = 0; j < fac->num; j++) { ind[j]++; if (ind[j] != sn[j]) break; ind[j] = 0; } } /* clean up */ for (i = 0; i < fac->num; i++) flint_free(s[i]); flint_free(ind); flint_free(x); flint_free(s); flint_free(sn); return num; } flint-3.1.3/src/ulong_extras/sqrtrem.c000066400000000000000000000012401461254215100177720ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" mp_limb_t n_sqrtrem(mp_limb_t * r, mp_limb_t a) { mp_limb_t is; is = (mp_limb_t) sqrt((double) a); is -= (is*is > a); #if FLINT64 if (is == UWORD(4294967296)) is--; #endif (*r) = a - is*is; return is; } flint-3.1.3/src/ulong_extras/test/000077500000000000000000000000001461254215100171135ustar00rootroot00000000000000flint-3.1.3/src/ulong_extras/test/main.c000066400000000000000000000147311461254215100202110ustar00rootroot00000000000000/* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include /* Include functions *********************************************************/ #include "t-addmod.c" #include "t-cbrt_binary_search.c" #include "t-cbrt.c" #include "t-cbrt_chebyshev_approx.c" #include "t-cbrt_newton_iteration.c" #include "t-cbrtrem.c" #include "t-clog_2exp.c" #include "t-clog.c" #include "t-compute_primes.c" #include "t-CRT.c" #include "t-discrete_log_bsgs.c" #include "t-div2_preinv.c" #include "t-divides.c" #include "t-divrem2_precomp.c" #include "t-divrem2_preinv.c" #include "t-euler_phi.c" #include "t-factor.c" #include "t-factor_ecm.c" #include "t-factorial_fast_mod2_preinv.c" #include "t-factorial_mod2_preinv.c" #include "t-factor_lehman.c" #include "t-factor_one_line.c" #include "t-factor_partial.c" #include "t-factor_pollard_brent.c" #include "t-factor_power235.c" #include "t-factor_pp1.c" #include "t-factor_SQUFOF.c" #include "t-factor_trial.c" #include "t-factor_trial_partial.c" #include "t-factor_trial_range.c" #include "t-flog.c" #include "t-gcd.c" #include "t-gcdinv.c" #include "t-invmod.c" #include "t-is_oddprime_binary.c" #include "t-is_oddprime_small.c" #include "t-is_perfect_power235.c" #include "t-is_perfect_power.c" #include "t-is_prime.c" #include "t-is_prime_pocklington.c" #include "t-is_prime_pseudosquare.c" #include "t-is_probabprime_BPSW.c" #include "t-is_probabprime.c" #include "t-is_probabprime_fermat.c" #include "t-is_probabprime_fibonacci.c" #include "t-is_probabprime_lucas.c" #include "t-is_square.c" #include "t-is_squarefree.c" #include "t-is_strong_probabprime2_preinv.c" #include "t-is_strong_probabprime_precomp.c" #include "t-jacobi.c" #include "t-lll_mod_preinv.c" #include "t-ll_mod_preinv.c" #include "t-mod2_precomp.c" #include "t-mod2_preinv.c" #include "t-mod_precomp.c" #include "t-moebius_mu.c" #include "t-mulmod2.c" #include "t-mulmod2_preinv.c" #include "t-mulmod_precomp.c" #include "t-mulmod_preinv.c" #include "t-mulmod_shoup.c" #include "t-nextprime.c" #include "t-nth_prime_bounds.c" #include "t-urandint.c" #include "t-pow.c" #include "t-powmod2.c" #include "t-powmod2_preinv.c" #include "t-powmod2_ui_preinv.c" #include "t-powmod.c" #include "t-powmod_precomp.c" #include "t-powmod_ui_precomp.c" #include "t-powmod_ui_preinv.c" #include "t-preinvert_limb_prenorm.c" #include "t-prime_pi_bounds.c" #include "t-prime_pi.c" #include "t-primes.c" #include "t-primes_jump_after.c" #include "t-primitive_root_prime.c" #include "t-remove2_precomp.c" #include "t-remove.c" #include "t-revbin.c" #include "t-root.c" #include "t-rootrem.c" #include "t-sizeinbase.c" #include "t-sqrt.c" #include "t-sqrtmod.c" #include "t-sqrtmodn.c" #include "t-sqrtmod_primepow.c" #include "t-sqrtrem.c" #include "t-submod.c" #include "t-xgcd.c" /* Array of test functions ***************************************************/ test_struct tests[] = { TEST_FUNCTION(n_addmod), TEST_FUNCTION(n_cbrt_binary_search), TEST_FUNCTION(n_cbrt), TEST_FUNCTION(n_cbrt_chebyshev_approx), TEST_FUNCTION(n_cbrt_newton_iteration), TEST_FUNCTION(n_cbrtrem), TEST_FUNCTION(n_clog_2exp), TEST_FUNCTION(n_clog), TEST_FUNCTION(compute_primes), TEST_FUNCTION(n_CRT), TEST_FUNCTION(n_discrete_log_bsgs), TEST_FUNCTION(n_div2_preinv), TEST_FUNCTION(n_divides), TEST_FUNCTION(n_divrem2_precomp), TEST_FUNCTION(n_divrem2_preinv), TEST_FUNCTION(n_euler_phi), TEST_FUNCTION(n_factor), TEST_FUNCTION(n_factor_ecm), TEST_FUNCTION(n_factorial_fast_mod2_preinv), TEST_FUNCTION(n_factorial_mod2_preinv), TEST_FUNCTION(n_factor_lehman), TEST_FUNCTION(n_factor_one_line), TEST_FUNCTION(n_factor_partial), TEST_FUNCTION(n_factor_pollard_brent), TEST_FUNCTION(n_factor_power235), TEST_FUNCTION(n_factor_pp1), TEST_FUNCTION(n_factor_SQUFOF), TEST_FUNCTION(n_factor_trial), TEST_FUNCTION(n_factor_trial_partial), TEST_FUNCTION(n_factor_trial_range), TEST_FUNCTION(n_flog), TEST_FUNCTION(n_gcd), TEST_FUNCTION(n_gcdinv), TEST_FUNCTION(n_invmod), TEST_FUNCTION(n_is_oddprime_binary), TEST_FUNCTION(n_is_oddprime_small), TEST_FUNCTION(n_is_perfect_power235), TEST_FUNCTION(n_is_perfect_power), TEST_FUNCTION(n_is_prime), TEST_FUNCTION(n_is_prime_pocklington), TEST_FUNCTION(n_is_prime_pseudosquare), TEST_FUNCTION(n_is_probabprime_BPSW), TEST_FUNCTION(n_is_probabprime), TEST_FUNCTION(n_is_probabprime_fermat), TEST_FUNCTION(n_is_probabprime_fibonacci), TEST_FUNCTION(n_is_probabprime_lucas), TEST_FUNCTION(n_is_square), TEST_FUNCTION(n_is_squarefree), TEST_FUNCTION(n_is_strong_probabprime2_preinv), TEST_FUNCTION(n_is_strong_probabprime_precomp), TEST_FUNCTION(n_jacobi), TEST_FUNCTION(n_lll_mod_preinv), TEST_FUNCTION(n_ll_mod_preinv), TEST_FUNCTION(n_mod2_precomp), TEST_FUNCTION(n_mod2_preinv), TEST_FUNCTION(n_mod_precomp), TEST_FUNCTION(n_moebius_mu), TEST_FUNCTION(n_mulmod2), TEST_FUNCTION(n_mulmod2_preinv), TEST_FUNCTION(n_mulmod_precomp), TEST_FUNCTION(n_mulmod_preinv), TEST_FUNCTION(n_mulmod_shoup), TEST_FUNCTION(n_nextprime), TEST_FUNCTION(n_nth_prime_bounds), TEST_FUNCTION(n_urandint), TEST_FUNCTION(n_pow), TEST_FUNCTION(n_powmod2), TEST_FUNCTION(n_powmod2_preinv), TEST_FUNCTION(n_powmod2_ui_preinv), TEST_FUNCTION(n_powmod), TEST_FUNCTION(n_powmod_precomp), TEST_FUNCTION(n_powmod_ui_precomp), TEST_FUNCTION(n_powmod_ui_preinv), TEST_FUNCTION(n_preinvert_limb_prenorm), TEST_FUNCTION(n_prime_pi_bounds), TEST_FUNCTION(n_prime_pi), TEST_FUNCTION(n_primes), TEST_FUNCTION(n_primes_jump_after), TEST_FUNCTION(n_primitive_root_prime), TEST_FUNCTION(n_remove2_precomp), TEST_FUNCTION(n_remove), TEST_FUNCTION(n_revbin), TEST_FUNCTION(n_root), TEST_FUNCTION(n_rootrem), TEST_FUNCTION(n_sizeinbase), TEST_FUNCTION(n_sqrt), TEST_FUNCTION(n_sqrtmod), TEST_FUNCTION(n_sqrtmodn), TEST_FUNCTION(n_sqrtmod_primepow), TEST_FUNCTION(n_sqrtrem), TEST_FUNCTION(n_submod), TEST_FUNCTION(n_xgcd) }; /* main function *************************************************************/ TEST_MAIN(tests) flint-3.1.3/src/ulong_extras/test/t-CRT.c000066400000000000000000000040031461254215100201450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(n_CRT, state) { slong i, j; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t m1, m2, m1m2, a1, a2, r; flint_bitcnt_t b1 = n_randint(state, FLINT_BITS) + 1; flint_bitcnt_t b2 = n_randint(state, FLINT_BITS + 1 - b1) + 1; fmpz_init(m1); fmpz_init(m2); fmpz_init(m1m2); fmpz_init(a1); fmpz_init(a2); fmpz_init(r); fmpz_randtest_not_zero(m1, state, b1); fmpz_randtest_not_zero(m2, state, b2); fmpz_abs(m1, m1); fmpz_abs(m2, m2); fmpz_mul(m1m2, m1, m2); fmpz_gcd(r, m1, m2); if (fmpz_is_one(r) && fmpz_abs_fits_ui(m1) && fmpz_abs_fits_ui(m2) && fmpz_abs_fits_ui(m1m2)) { for (j = 0; j < 50; j++) { fmpz_randm(a1, state, m1); fmpz_randm(a2, state, m2); fmpz_CRT(r, a1, m1, a2, m2, 0); if (fmpz_get_ui(r) != n_CRT(fmpz_get_ui(a1), fmpz_get_ui(m1), fmpz_get_ui(a2), fmpz_get_ui(m2))) TEST_FUNCTION_FAIL( "a1: %{fmpz}\n" "m1: %{fmpz}\n" "a2: %{fmpz}\n" "m2: %{fmpz}\n", a1, m1, a2, m2); } } fmpz_clear(m1); fmpz_clear(m2); fmpz_clear(m1m2); fmpz_clear(a1); fmpz_clear(a2); fmpz_clear(r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-addmod.c000066400000000000000000000021171461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_addmod, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong a, b, d, r1, r2, s1; d = n_randtest_not_zero(state); a = n_randtest(state) % d; b = n_randtest(state) % d; r1 = n_addmod(a, b, d); add_ssaaaa(s1, r2, UWORD(0), a, UWORD(0), b); if (s1 != 0 || r2 >= d) r2 -= d; result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, b = %wu, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, b, d, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-cbrt.c000066400000000000000000000061651461254215100204620ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_cbrt, state) { int i, result; /* random n */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); n = n_randtest(state); val = n_cbrt(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + k */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += (n_randint(state, 100) - 50); val = n_cbrt(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += 1; val = n_cbrt(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 - 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n -= 1; val = n_cbrt(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-cbrt_binary_search.c000066400000000000000000000062671461254215100233560ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_cbrt_binary_search, state) { int i, result; /* random n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); n = n_randtest(state); val = n_cbrt_binary_search(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + k */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += (n_randint(state, 100) - 50); val = n_cbrt_binary_search(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + 1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += 1; val = n_cbrt_binary_search(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 - 1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n -= 1; val = n_cbrt_binary_search(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-cbrt_chebyshev_approx.c000066400000000000000000000063051461254215100241070ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_cbrt_chebyshev_approx, state) { int i, result; /* random n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); n = n_randtest(state); val = n_cbrt_chebyshev_approx(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + k */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += (n_randint(state, 100) - 50); val = n_cbrt_chebyshev_approx(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + 1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += 1; val = n_cbrt_chebyshev_approx(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 - 1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n -= 1; val = n_cbrt_chebyshev_approx(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-cbrt_newton_iteration.c000066400000000000000000000063051461254215100241260ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_cbrt_newton_iteration, state) { int i, result; /* random n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); n = n_randtest(state); val = n_cbrt_newton_iteration(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + k */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += (n_randint(state, 100) - 50); val = n_cbrt_newton_iteration(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 + 1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n += 1; val = n_cbrt_newton_iteration(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } /* type n^3 - 1 */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, val, ans, bits; mpz_t mpz_n, mpz_val; mpz_init(mpz_n); mpz_init(mpz_val); bits = n_randint(state, FLINT_BITS/3 + 1); n = n_randtest_bits(state, bits); n = n*n*n; n -= 1; val = n_cbrt_newton_iteration(n); flint_mpz_set_ui(mpz_n, n); mpz_root(mpz_val, mpz_n, 3); ans = flint_mpz_get_ui(mpz_val); result = (val == ans); if (!result) TEST_FUNCTION_FAIL("n = %wu, val = %wd, ans = %wu\n", n, val, ans); mpz_clear(mpz_n); mpz_clear(mpz_val); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-cbrtrem.c000066400000000000000000000024651461254215100211650ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_cbrtrem, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, b, c, i, j; mpz_t e, f, g; mpz_init(e); mpz_init(f); mpz_init(g); c = n_randint(state, 0); /*number */ flint_mpz_set_ui(g, c); a = n_cbrtrem(&b, c); mpz_rootrem(e, f, g, 3); i = flint_mpz_get_ui(e); j = flint_mpz_get_ui(f); result = ((a == i) && (b == j)); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters: n = %wu" "Answer generated: base = %wu remainder = %wu" "Expected answer: base = %wu remainder = %wu", c, a, b, i, j); mpz_clear(e); mpz_clear(f); mpz_clear(g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-clog.c000066400000000000000000000021271461254215100204460ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_clog, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a = 0, b = 0, k, x; while (a < 1) a = n_randtest(state); while (b < 2) b = n_randtest(state); k = n_clog(a, b); x = (k > 0) ? n_pow(b, k - 1) : 0; result = (x < a && ((k > 0) ? ((a + b - 1) / b <= x) : (a <= 1))); if (!result) TEST_FUNCTION_FAIL( "a = %wu\n" "b = %wu\n" "x = %wu\n" "k = %wu\n", a, b, x, k); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-clog_2exp.c000066400000000000000000000032521461254215100214040ustar00rootroot00000000000000/* Copyright (C) 2021 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_clog_2exp, state) { slong i; ulong t[][3] = {{1, 2, 1}, {2, 2, 2}, {698, 127, 100}, {699, 127, 101}, {700, 127, 101}, {701, 127, 101}, {699, 128, 100}, {700, 128, 100}, {701, 128, 101}, {694, 129, 99}, {695, 129, 100}, {696, 129, 100}, {697, 129, 100}, {698, 129, 100}, {699, 129, 100}, {700, 129, 100}, {701, 129, 100}, {702, 129, 101}, {0, UWORD_MAX, 0}, {1, UWORD_MAX, 1}, {2, UWORD_MAX, 1}, {FLINT_BITS - 1, UWORD_MAX, 1}, {FLINT_BITS, UWORD_MAX, 2}}; for (i = 0; i < sizeof(t)/sizeof(t[0]); i++) { ulong r = n_clog_2exp(t[i][0], t[i][1]); if (r != t[i][2]) TEST_FUNCTION_FAIL( "clog_2exp(%wu, %wu) = %wu\n" "but computed %wu\n", t[i][0], t[i][1], t[i][2], r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-compute_primes.c000066400000000000000000000031561461254215100225600ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(compute_primes, state) { slong i, lim = 1000000; n_primes_t pg; mp_limb_t * ref_primes; double * ref_inverses; ref_primes = flint_malloc(sizeof(mp_limb_t) * lim); ref_inverses = flint_malloc(sizeof(double) * lim); n_primes_init(pg); for (i = 0; i < lim; i++) { ref_primes[i] = n_primes_next(pg); ref_inverses[i] = n_precompute_inverse(ref_primes[i]); } n_primes_clear(pg); for (i = 0; i < 250; i++) { slong n; const mp_limb_t * primes; const double * inverses; n = n_randtest(state) % lim; primes = n_primes_arr_readonly(n + 1); inverses = n_prime_inverses_arr_readonly(n + 1); if (primes[n] != ref_primes[n] || inverses[n] != ref_inverses[n]) TEST_FUNCTION_FAIL( "n = %wd, p1 = %wu, p2 = %wu\n" "inv1 = %g, inv2 = %g\n", n, primes[n], ref_primes[n], inverses[n], ref_inverses[n]); if (n_randint(state, 20) == 0) n_cleanup_primes(); } flint_free(ref_primes); flint_free(ref_inverses); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-discrete_log_bsgs.c000066400000000000000000000020741461254215100232040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_discrete_log_bsgs, state) { int i; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { ulong p, root, b, d, result; double pinv; p = n_randprime(state, 2 + n_randint(state, 26), 1); pinv = n_precompute_inverse(p); root = n_primitive_root_prime(p); b = n_randint(state, p - 1) + 1; d = n_discrete_log_bsgs(b, root, p); result = n_powmod_precomp(root, d, p, pinv); if (result != b) TEST_FUNCTION_FAIL("%wu ** (%wu) == %wu != %wu\n", root, d, result, b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-div2_preinv.c000066400000000000000000000020061461254215100217450ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_div2_preinv, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong d, dinv, n, q1, q2; d = n_randtest_not_zero(state); n = n_randtest(state); dinv = n_preinvert_limb(d); q1 = n_div2_preinv(n, d, dinv); q2 = n / d; result = (q1 == q2); if (!result) TEST_FUNCTION_FAIL( "n = %wu, d = %wu, dinv = %wu\n" "q1 = %wu, q2 = %wu\n", n, d, dinv, q1, q2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-divides.c000066400000000000000000000031721461254215100211520ustar00rootroot00000000000000/* Copyright (C) 2021 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_divides, state) { int i, result; for (i = 0; i < 2000 * flint_test_multiplier(); i++) { mp_limb_t n, p, q; int nbits, pbits; int flag, type; type = n_randint(state, 2); pbits = n_randint(state, FLINT_BITS + 1); if (type == 0) { /* test random values */ nbits = n_randint(state, FLINT_BITS + 1); n = n_randtest_bits(state, nbits); p = n_randtest_bits(state, pbits); flag = n_divides(&q, n, p); result = ((flag && ((p == 0 && n == 0) || p*q == n)) || (!flag && q == 0 && ((p == 0 && n != 0) || p*q != n))); } else { /* test known divisible values */ ulong s; int sbits = n_randint(state, FLINT_BITS - pbits + 1); p = n_randtest_bits(state, pbits); s = n_randtest_bits(state, sbits); n = p * s; flag = n_divides(&q, n, p); result = (flag && ((p == 0 && n == 0) || p*q == n)); } if (!result) TEST_FUNCTION_FAIL("n = %wu, p = %wu, q = %wu\n", n, p, q); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-divrem2_precomp.c000066400000000000000000000021651461254215100226210ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_divrem2_precomp, state) { int result; ulong i; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t d, n, r1, r2, q1, q2; double dpre; d = n_randtest_not_zero(state); n = n_randtest(state); dpre = n_precompute_inverse(d); r1 = n_divrem2_precomp(&q1, n, d, dpre); r2 = n % d; q2 = n / d; result = ((r1 == r2) && (q1 == q2)); if (!result) TEST_FUNCTION_FAIL( "n = %wu, d = %wu, dpre = %f\n" "q1 = %wu, q2 = %wu, r1 = %wu, r2 = %wu\n", n, d, dpre, q1, q2, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-divrem2_preinv.c000066400000000000000000000021541461254215100224550ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_divrem2_preinv, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong d, dinv, n, q1, q2, r1, r2; d = n_randtest_not_zero(state); n = n_randtest(state); dinv = n_preinvert_limb(d); r1 = n_divrem2_preinv(&q1, n, d, dinv); q2 = n / d; r2 = n % d; result = (q1 == q2 && r1 == r2); if (!result) TEST_FUNCTION_FAIL( "n = %wu, d = %wu, dinv = %wu\n" "q1 = %wu, q2 = %wu\n" "r1 = %wu, r2 = %wu\n", n, d, dinv, q1, q2, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-euler_phi.c000066400000000000000000000020201461254215100214660ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_euler_phi, state) { slong ix; int result; for (ix = 0; ix < 100 * flint_test_multiplier(); ix++) { ulong nx, kx; ulong r1, r2; nx = n_randbits(state, n_randint(state, 18)); r1 = 0; for (kx = 1; kx <= nx; kx++) r1 += (n_gcd(nx, kx) == 1); r2 = n_euler_phi(nx); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "phi(%wu) = %wu, got %wu\n", nx, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor.c000066400000000000000000000024301461254215100207750ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor, state) { int i, j, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n1, n2; n_factor_t factors; int type; n_factor_init(&factors); type = n_randint(state, 2); if (type == 0) { /* Test random numbers */ n1 = n_randtest_not_zero(state); } else { /* Test random prime */ n1 = n_randprime(state, 2 + n_randint(state, FLINT_BITS - 1), 1); } n_factor(&factors, n1, 0); n2 = UWORD(1); for (j = 0; j < factors.num; j++) { n2 *= n_pow(factors.p[j], factors.exp[j]); } result = (n1 == n2); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_SQUFOF.c000066400000000000000000000023341461254215100220630ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_SQUFOF, state) { int i, result; ulong count = UWORD(0); for (i = 0; i < 300 * flint_test_multiplier(); i++) /* Test random numbers */ { mp_limb_t n1, n2; do { n1 = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); } while (n_is_prime(n1) || (n1 < UWORD(2))); #if FLINT64 n2 = n_factor_SQUFOF(n1, 10000); #else n2 = n_factor_SQUFOF(n1, 2000); #endif if (n2) { count++; result = ((n1%n2) == UWORD(0)); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } } if (count < 280 * flint_test_multiplier()) TEST_FUNCTION_FAIL("Only %wu numbers factored\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_ecm.c000066400000000000000000000031611461254215100216230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_ecm, state) { int i, j, k, result, fails; mp_limb_t prime1, prime2, prod, f, mod; fails = 0; for (i = 10; i < 64; i += 5) { for (j = i; j < 64 - i; j += 5) { for (k = 0; k < flint_test_multiplier(); k++) { prime1 = n_randprime(state, i, 1); prime2 = n_randprime(state, j, 1); prod = prime1 * prime2; result = n_factor_ecm(&f, (i + j) << 2, 1000, 50000, state, prod); if (result) { mod = prod % f; if ((mod != 0) || (f == prod) || (f == 1)) TEST_FUNCTION_FAIL( "Wrong answer from stage %d\n" "Number: %wu = %wu * %wu\n" "Factor found: %wu\n", result, prod, prime1, prime2, f); } else fails += 1; } } } if (fails > 2 * flint_test_multiplier()) TEST_FUNCTION_FAIL("Too many unsuccessful factorizations, %d\n", fails); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_lehman.c000066400000000000000000000032171461254215100223250ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_lehman, state) { slong ix; int result; for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { ulong n1, n2; int type; type = n_randint(state, 10); if (type == 0) { /* Test random products of two primes */ int bits1, bits2; bits1 = 2 + n_randint(state, FLINT_MIN(FLINT_BITS, 53) - 3); bits2 = 2 + n_randint(state, FLINT_MIN(FLINT_BITS, 53) - 1 - bits1); n1 = n_randprime(state, bits1, 1) * n_randprime(state, bits2, 1); } else { /* Test random numbers */ do { int bits = 2 + n_randint(state, FLINT_MIN(FLINT_BITS, 53) - 1); n1 = n_randtest_bits(state, bits); } while (n_is_prime(n1)); } #if FLINT64 /* Test a specific bug (FIXME: What bug?) */ if (ix == 0) n1 = UWORD(72528697) * UWORD(73339073); #endif n2 = n_factor_lehman(n1); result = ((n1 % n2) == UWORD(0) && n1 != n2); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_one_line.c000066400000000000000000000024511461254215100226500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_one_line, state) { int i, result; slong num_iter; ulong count = UWORD(0); num_iter = 500 * FLINT_MAX(1, flint_test_multiplier()); for (i = 0; i < num_iter; i++) /* Test random numbers */ { mp_limb_t n1, n2, bits; do { #if FLINT64 bits = n_randint(state, 44); #else bits = n_randint(state, 20); #endif n1 = n_randtest_bits(state, bits + 1); } while (n_is_prime(n1) || (n1 == UWORD(1))); n2 = n_factor_one_line(n1, 50000); if (n2) { count++; result = ((n1 % n2) == UWORD(0)); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } } if (count < 0.9 * num_iter) TEST_FUNCTION_FAIL("Only %wu numbers factored\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_partial.c000066400000000000000000000021761461254215100225200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_partial, state) { int i, j, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random numbers */ { mp_limb_t n1, n2, prod, limit; n_factor_t factors; n_factor_init(&factors); n1 = n_randtest_not_zero(state); limit = n_sqrt(n1); n2 = n_factor_partial(&factors, n1, limit, 0); prod = 1; for (j = 0; j < factors.num; j++) { prod *= n_pow(factors.p[j], factors.exp[j]); } result = ((n1 == n2 * prod) && ((prod > limit) || (n1 == 1))); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_pollard_brent.c000066400000000000000000000033021461254215100237030ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_pollard_brent, state) { ulong prime1, prime2, primeprod, fac, modval; int i, j, k, l, fails; fails = 0; for (l = 5; l < 26; l += 5) { for (i = l; i < 26 && i + l <= FLINT_BITS; i += 5) { for (j = 0; j < 10 * flint_test_multiplier(); j++) { do { prime1 = n_randtest_bits(state, l); prime2 = n_randtest_bits(state, i); primeprod = prime1 * prime2; } while (primeprod < 1); k = n_factor_pollard_brent(&fac, state, primeprod, 5, 2500); if (k == 0) fails += 1; else { modval = primeprod % fac; if (modval != 0) TEST_FUNCTION_FAIL( "n: %wu\n" "Factor calculated: %wn\n", primeprod, fac); } } } } #if FLINT64 if (fails > flint_test_multiplier()) #else if (fails > 2 * flint_test_multiplier()) #endif TEST_FUNCTION_FAIL("Pollard Rho - Brent failed too many times (%d times)\n", fails); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_power235.c000066400000000000000000000037131461254215100224500ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_power235, state) { slong ix; int result; for (ix = 0; ix < 3000 * flint_test_multiplier(); ix++) { ulong factor, exp, n1, n2, n1pow; int bits, type; type = n_randint(state, 4); if (type == 0) { /* Test random squares */ bits = n_randint(state, FLINT_BITS / 2) + 1; n1 = n_randtest_bits(state, bits); n1pow = n1 * n1; } else if (type == 1) { /* Test random cubes */ bits = n_randint(state, FLINT_BITS / 3) + 1; n1 = n_randtest_bits(state, bits); n1pow = n1 * n1 * n1; } else if (type == 2) { /* Test random fifth powers */ bits = n_randint(state, FLINT_BITS / 5) + 1; n1 = n_randtest_bits(state, bits); n1pow = n1 * n1 * n1 * n1 * n1; } else { /* Test non 235-powers */ do n1 = n_randtest(state); while (n_is_perfect_power235(n1)); result = (!n_factor_power235(&exp, n1)); } if (type < 3) { factor = n_factor_power235(&exp, n1pow); n2 = n_pow(factor, exp); result = (n1pow == n2); } if (!result) TEST_FUNCTION_FAIL( "type %d\n" "n1 = %wu, exp = %wu\n", type, n1, exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_pp1.c000066400000000000000000000024201461254215100215540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_pp1, state) { int i, j, result; ulong count = UWORD(0); for (i = 0; i < 300 * flint_test_multiplier(); i++) /* Test random numbers */ { ulong n1, n2; do { n1 = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); } while (n_is_prime(n1) || (n1 < UWORD(2))); for (j = 0; j < 20; j++) { n2 = n_factor_pp1(n1, 1000000, n_randint(state, n1 - 3) + 3); if (n2 > 1) break; } if (n2 > 1) { count++; result = ((n1%n2) == UWORD(0)); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } } if (count < 295 * flint_test_multiplier()) TEST_FUNCTION_FAIL("Only %wu numbers factored\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_trial.c000066400000000000000000000020471461254215100221740ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_trial, state) { slong ix, jx; int result; for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) /* Test random numbers */ { ulong n1, n2; n_factor_t factors; n_factor_init(&factors); n1 = n_randtest_not_zero(state); n2 = n_factor_trial(&factors, n1, UWORD(10000)); for (jx = 0; jx < factors.num; jx++) { n2 *= n_pow(factors.p[jx], factors.exp[jx]); } result = (n1 == n2); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_trial_partial.c000066400000000000000000000023241461254215100237060ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_trial_partial, state) { slong ix, jx; int result; for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) /* Test random numbers */ { mp_limb_t n1, n2, prod, limit; n_factor_t factors; n_factor_init(&factors); n1 = n_randtest_not_zero(state); limit = n_sqrt(n1); n2 = n_factor_trial_partial(&factors, n1, &prod, UWORD(10000), limit); if (n1 != n2 * prod) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu, prod = %wu\n", n1, n2, prod); for (jx = 0; jx < factors.num; jx++) n2 *= n_pow(factors.p[jx], factors.exp[jx]); result = (n1 == n2); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2, prod); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factor_trial_range.c000066400000000000000000000020341461254215100233440ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_factor_trial_range, state) { int i, j, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random numbers */ { mp_limb_t n1, n2; n_factor_t factors; n_factor_init(&factors); n1 = n_randtest_not_zero(state); n2 = n_factor_trial_range(&factors, n1, UWORD(100), UWORD(10000)); for (j = 0; j < factors.num; j++) n2 *= n_pow(factors.p[j], factors.exp[j]); result = (n1 == n2); if (!result) TEST_FUNCTION_FAIL("n1 = %wu, n2 = %wu\n", n1, n2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factorial_fast_mod2_preinv.c000066400000000000000000000027071461254215100250130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #ifndef n_factorial_mod2_foolproof #define n_factorial_mod2_foolproof n_factorial_mod2_foolproof static mp_limb_t n_factorial_mod2_foolproof(ulong n, mp_limb_t p, mp_limb_t pinv) { mp_limb_t prod = UWORD(1) % p; while (n) { prod = n_mulmod2_preinv(prod, n, p, pinv); n--; } return prod; } #endif TEST_FUNCTION_START(n_factorial_fast_mod2_preinv, state) { ulong n; int j; for (n = 0; n < 500 * flint_test_multiplier(); n++) { ulong p, pinv, x, y; for (j = 0; j < 5; j++) { p = n_randtest_not_zero(state); pinv = n_preinvert_limb(p); x = n_factorial_fast_mod2_preinv(n, p, pinv); y = n_factorial_mod2_foolproof(n, p, pinv); if (x != y) TEST_FUNCTION_FAIL( "n = %wu\n" "p = %wu\n" "x = %wu\n" "y = %wu\n", n, p, x, y); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-factorial_mod2_preinv.c000066400000000000000000000032311461254215100237670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #ifndef n_factorial_mod2_foolproof #define n_factorial_mod2_foolproof n_factorial_mod2_foolproof static ulong n_factorial_mod2_foolproof(ulong n, ulong p, ulong pinv) { ulong prod = UWORD(1) % p; while (n) { prod = n_mulmod2_preinv(prod, n, p, pinv); n--; } return prod; } #endif TEST_FUNCTION_START(n_factorial_mod2_preinv, state) { slong ix; for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { ulong n, p, pinv, x, y; int type; type = n_randint(state, 100); if (type == 0) { /* n is big */ n = n_randint(state, 1000000); } else { /* n is small */ n = n_randint(state, 1000); } p = n_randtest_not_zero(state); pinv = n_preinvert_limb(p); x = n_factorial_mod2_preinv(n, p, pinv); y = n_factorial_mod2_foolproof(n, p, pinv); if (x != y) TEST_FUNCTION_FAIL( "n = %wu\n" "p = %wu\n" "x = %wu\n" "y = %wu\n", n, p, x, y); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-flog.c000066400000000000000000000020541461254215100204500ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_flog, state) { slong ix; int result; for (ix = 0; ix < 10000 * flint_test_multiplier(); ix++) { ulong a = 0, b = 0, k, x; while (a < 1) a = n_randtest(state); while (b < 2) b = n_randtest(state); k = n_flog(a, b); x = n_pow(b, k); result = (x <= a && a / b < x); if (!result) TEST_FUNCTION_FAIL( "a = %wu\n" "b = %wu\n" "x = %wu\n" "k = %wu\n", a, b, x, k); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-gcd.c000066400000000000000000000040671461254215100202640ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_gcd, state) { int i, result; if (n_gcd(0, 0) != 0) TEST_FUNCTION_FAIL("gcd(0, 0) != 0\n"); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, b, c, g; int type; type = n_randint(state, 30); if (type == 0) { /* gcd(a, 0) == a */ a = n_randtest(state); b = 0; c = 0; g = n_gcd(a, b); result = (g == a); } else if (type == 1) { /* gcd(0, b) == b */ a = 0; b = n_randtest(state); c = 0; g = n_gcd(a, b); result = (g == b); } else { /* gcd(ac, bc) == gcd(a, b) */ int bits1, bits2, bits3, mbits; bits1 = n_randint(state, FLINT_BITS - 1) + 1; bits2 = n_randint(state, FLINT_BITS - 1) + 1; mbits = FLINT_MAX(bits1, bits2); bits3 = mbits == FLINT_BITS ? 0 : n_randint(state, FLINT_BITS - mbits) + 1; do { a = n_randtest_bits(state, bits1); b = n_randtest_bits(state, bits2); } while (n_gcd(a, b) != UWORD(1)); c = bits3 == 0 ? 1 : n_randtest_bits(state, bits3); g = n_gcd(a * c, b * c); result = (g == c); } if (!result) TEST_FUNCTION_FAIL( "type %d\n" "a = %wu, b = %wu, c = %wu, g = %wu\n", type, a, b, c, g); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-gcdinv.c000066400000000000000000000055151461254215100210000ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_gcdinv, state) { slong ix; int result; /* test modulo 1 */ { ulong a, b, s, g; a = 0; b = 1; g = n_gcdinv(&s, a, b); result = (g == 1 && s == 0); if (!result) TEST_FUNCTION_FAIL( "GCD modulo 1 does not return g = 1 and s = 0\n" "g = %wu, s = %wu\n", g, s); } /* check gcd not 1 when a = 0 (and b != 1) */ for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { ulong a, b, s, g; a = 0; b = n_randtest_not_zero(state); g = n_gcdinv(&s, a, b); result = (g != 1 || b == 1); if (!result) TEST_FUNCTION_FAIL( "gcd(0, b) == 1\n" "b = %wu, s = %wu\n", b, s); } for (ix = 0; ix < 10000 * flint_test_multiplier(); ix++) { ulong a, b, c, g, g2, s, t2, t, bits1, bits2, bits3, ainv; bits1 = n_randint(state, FLINT_BITS - 1) + 2; bits2 = n_randint(state, bits1) + 1; bits3 = bits1 == FLINT_BITS ? 0 : n_randint(state, FLINT_BITS - bits1) + 1; do { a = n_randtest_bits(state, bits1); b = n_randtest_bits(state, bits2); } while (n_gcd(a, b) != UWORD(1) || b >= a); c = bits3 == 0 ? 1 : n_randtest_bits(state, bits3); /* compare n_gcdinv with n_xgcd */ g = n_xgcd(&s, &t, a * c, b * c); g2 = n_gcdinv(&t2, b * c, a * c); /* compute second cofactor modulo ac */ t %= (a * c); /* t is non-negative... */ t = a * c - t; /* ... but minus the actual cofactor */ result = (g == g2 && t == t2); if (!result) TEST_FUNCTION_FAIL( "Cofactor doesn't agree with n_xgcd\n" "a = %wu, b = %wu, c = %wu\n" "g = %wu, g2 = %wu, t = %wd, t2 = %wd\n", a, b, c, g, g2, t, t2); /* test b*t2 == 1 mod a */ ainv = n_preinvert_limb(a); s = n_mulmod2_preinv(t2, b, a, ainv); result = (s == 1); if (!result) TEST_FUNCTION_FAIL( "Incorrect inverse\n" "a = %wu, b = %wu, c = %wu\n" "g2 = %wu, s = %wd, t2 = %wd\n", a, b, c, g2, s, t2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-invmod.c000066400000000000000000000021211461254215100210100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_invmod, state) { slong ix; int result; for (ix = 0; ix < 10000 * flint_test_multiplier(); ix++) { ulong a, b, t, r, binv, ph, pl; do { a = n_randtest(state); b = n_randtest(state); } while ((a >= b) || (n_gcd(b, a) != UWORD(1))); t = n_invmod(a, b); binv = n_preinvert_limb(b); umul_ppmm(ph, pl, t, a); r = n_ll_mod_preinv(ph, pl, b, binv); result = ((r == UWORD(0) && b == UWORD(1)) || r == UWORD(1)); if (!result) TEST_FUNCTION_FAIL("a = %wu, b = %wu, r = %wd\n", a, b, r); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_oddprime_binary.c000066400000000000000000000027621461254215100233710ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_oddprime_binary, state) { slong ix; slong cutoff = 100000; int result; for (ix = 0; ix < 20000 * flint_test_multiplier(); ix++) { ulong d; int type; type = n_randint(state, 2); /* NOTE: n_is_oddprime_binary(n) requires n to be odd and n > 16 */ if (type == 0) { /* Test that primes pass the test */ int bits = 5 + n_randint(state, 13); do d = n_randprime(state, bits, 1); while (d > cutoff); result = n_is_oddprime_binary(d); } else { /* Test that not too many composites pass */ do d = (17 + n_randint(state, cutoff - 17)) | 1; while (n_is_probabprime(d)); result = !n_is_oddprime_binary(d); } if (!result) TEST_FUNCTION_FAIL( "type %d\n" "d = %wu\n", type, d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_oddprime_small.c000066400000000000000000000027551461254215100232170ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2024 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_oddprime_small, state) { slong ix; int result; for (ix = 0; ix < 10000 * flint_test_multiplier(); ix++) { ulong d; int type; type = n_randint(state, 2); if (type == 0) { /* Test that primes pass the test */ int bits = 2 + n_randint(state, FLINT_BIT_COUNT(FLINT_ODDPRIME_SMALL_CUTOFF - 1) - 1); do d = n_randprime(state, bits, 1); while (d > FLINT_ODDPRIME_SMALL_CUTOFF); result = n_is_oddprime_small(d); } else { /* Test that not too many composites pass */ do d = n_randint(state, FLINT_ODDPRIME_SMALL_CUTOFF) | 1; while (n_is_probabprime(d)); result = !n_is_oddprime_small(d); } if (!result) TEST_FUNCTION_FAIL( "type %d\n" "d = %wu\n", type, d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_perfect_power.c000066400000000000000000000056031461254215100230630ustar00rootroot00000000000000/* Copyright (C) 2009, 2017 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_perfect_power, state) { int i, result; ulong bits, root, hi, n; mp_limb_t d; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that squares pass the test */ { bits = n_randint(state, FLINT_BITS/2) + 1; d = n_randtest_bits(state, bits); result = n_is_perfect_power(&root, n_pow(d, 2)); if (result == 0) TEST_FUNCTION_FAIL("d^2 = %wu is declared not a perfect power\n", d*d); if (n_pow(root, result) != n_pow(d, 2)) TEST_FUNCTION_FAIL("%wu^%wu != %wu\n", root, result, d*d); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that cubes pass the test */ { bits = n_randint(state, FLINT_BITS/3) + 1; d = n_randtest_bits(state, bits); result = n_is_perfect_power(&root, n_pow(d, 3)); if (result == 0) TEST_FUNCTION_FAIL("d^3 = %wu is declared not a perfect power\n", d*d*d); if (n_pow(root, result) != n_pow(d, 3)) TEST_FUNCTION_FAIL("%wu^%wu != %wu\n", root, result, d*d*d); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that fifth powers pass the test */ { bits = n_randint(state, FLINT_BITS/5) + 1; d = n_randtest_bits(state, bits); result = n_is_perfect_power(&root, n_pow(d, 5)); if (result == 0) TEST_FUNCTION_FAIL("d^5 = %wu is declared not a perfect power\n", d*d*d*d*d); if (n_pow(root, result) != n_pow(d, 5)) TEST_FUNCTION_FAIL("%wu^%wu != %wu\n", root, result, d*d*d*d*d); } /* exhaustively test all other powers */ for (d = 2; d < (UWORD(1) << (FLINT_BITS/5)); d++) { hi = 0; n = d*d; while (hi == 0) { result = n_is_perfect_power(&root, n); if (n_pow(root, result) != n) TEST_FUNCTION_FAIL("%wu^%wu != %wu\n", root, result, n); umul_ppmm(hi, n, n, d); } } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that non perfect powers fail */ { mpz_t d_m; mpz_init(d_m); do { d = n_randtest(state); flint_mpz_set_ui(d_m, d); } while (mpz_perfect_power_p(d_m)); result = !n_is_perfect_power(&root, d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared a perfect power\n", d); mpz_clear(d_m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_perfect_power235.c000066400000000000000000000040741461254215100233160ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_perfect_power235, state) { int i, result; ulong bits; mp_limb_t d; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that square pass the test */ { bits = n_randint(state, FLINT_BITS/2) + 1; d = n_randtest_bits(state, bits); result = n_is_perfect_power235(n_pow(d, 2)); if (!result) TEST_FUNCTION_FAIL("d^2 = %wu is declared not a perfect power\n", d * d); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that cubes pass the test */ { bits = n_randint(state, FLINT_BITS/3) + 1; d = n_randtest_bits(state, bits); result = n_is_perfect_power235(n_pow(d, 3)); if (!result) TEST_FUNCTION_FAIL("d^3 = %wu is declared not a perfect power\n", d * d * d); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that fifth powers pass the test */ { bits = n_randint(state, FLINT_BITS/5) + 1; d = n_randtest_bits(state, bits); result = n_is_perfect_power235(n_pow(d, 5)); if (!result) TEST_FUNCTION_FAIL("d^5 = %wu is declared not a perfect power\n", d * d * d * d * d); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that non prefect powers fail */ { mpz_t d_m; mpz_init(d_m); do { d = n_randtest(state); flint_mpz_set_ui(d_m, d); } while (mpz_perfect_power_p(d_m)); result = !n_is_perfect_power235(d); if (!result) flint_printf("d = %wu is declared a perfect power\n", d); mpz_clear(d_m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_prime.c000066400000000000000000000125531461254215100213350ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #if FLINT64 /* n < 10^16 that pass base 2, 3, 7, 61 and 24251 sprp test */ mp_limb_t composites[] = { UWORD(669094855201), UWORD(1052516956501), UWORD(2007193456621), UWORD(2744715551581), UWORD(9542968210729), UWORD(17699592963781), UWORD(19671510288601), UWORD(24983920772821), UWORD(24984938689453), UWORD(29661584268781), UWORD(37473222618541), UWORD(46856248255981), UWORD(47922612926653), UWORD(48103703944453), UWORD(49110566041153), UWORD(49752242681221), UWORD(91206655032481), UWORD(91481980096033), UWORD(119034193492321), UWORD(123645258399601), UWORD(128928036060253), UWORD(137364148720147), UWORD(150753857310253), UWORD(153131886327421), UWORD(155216912613121), UWORD(185610214763821), UWORD(224334357392701), UWORD(227752294950181), UWORD(230058334559041), UWORD(304562854940401), UWORD(306001576998253), UWORD(335788261073821), UWORD(377133492079081), UWORD(379242177424951), UWORD(389970770948461), UWORD(397319638319521), UWORD(448114903362253), UWORD(523235160050221), UWORD(628999496281621), UWORD(699349238838253), UWORD(746667678235753), UWORD(790198268451301), UWORD(794036495175661), UWORD(823820871230281), UWORD(867739535711821), UWORD(1039918661294761), UWORD(1099127938585141), UWORD(1104388025338153), UWORD(1173374598605653), UWORD(1262797719066157), UWORD(1265872947674653), UWORD(1325898212229667), UWORD(1327034517143653), UWORD(1418575746675583), UWORD(1666122072463621), UWORD(1837400535259453), UWORD(1857422490084961), UWORD(1870756820971741), UWORD(1914550540480717), UWORD(2018963273468221), UWORD(2163829000939453), UWORD(2206020317369221), UWORD(2301037384029121), UWORD(2416062055125421), UWORD(2435076500074921), UWORD(2545656135020833), UWORD(2594428516569781), UWORD(2669983768115821), UWORD(2690937050990653), UWORD(2758640869506607), UWORD(2833525461416653), UWORD(2876662942007221), UWORD(2932155806957821), UWORD(2957010595723801), UWORD(3183606449929153), UWORD(3220133449185901), UWORD(3424103775720253), UWORD(3625360152399541), UWORD(3939300299037421), UWORD(3947917710714841), UWORD(3980273496750253), UWORD(4182256679324041), UWORD(4450605887818261), UWORD(4727893739521501), UWORD(4750350311306953), UWORD(4755334362931153), UWORD(5756440863559753), UWORD(5760976603475341), UWORD(5794399356078761), UWORD(5954850603819253), UWORD(6125544931991761), UWORD(6320931714094861), UWORD(6347593619672581), UWORD(6406268028524101), UWORD(6510632945054941), UWORD(6620082224794741), UWORD(6627325072566061), UWORD(6844056606431101), UWORD(6989404981060153), UWORD(7144293947609521), UWORD(7288348593229021), UWORD(7288539837129253), UWORD(7406102904971689), UWORD(7430233301822341), UWORD(7576425305871193), UWORD(7601696719033861), UWORD(7803926845356487), UWORD(7892007967006633), UWORD(7947797946559453), UWORD(8207000460596953), UWORD(8295064717807513), UWORD(8337196000698841), UWORD(8352714234009421), UWORD(8389755717406381), UWORD(8509654470665701), UWORD(8757647355282841), UWORD(8903933671696381), UWORD(8996133652295653), UWORD(9074421465661261), UWORD(9157536631454221), UWORD(9188353522314541) }; #endif TEST_FUNCTION_START(n_is_prime, state) { int i, result; mp_limb_t d; mpz_t d_m; slong pow; ulong bits; /* Test that primes pass the test */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mpz_init(d_m); do { d = n_randtest(state) | 1; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_prime(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } /* Test that composites do not pass */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mpz_init(d_m); do { d = n_randtest(state) | 1; if (d == UWORD(1)) d++; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); result = !n_is_prime(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared prime\n", d); mpz_clear(d_m); } /* Test that powers do not pass */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { pow = n_randint(state, 6) + 2; bits = n_randint(state, FLINT_BITS) + 1; bits /= pow; d = n_randbits(state, bits); d = n_pow(d, pow); result = !n_is_prime(d); if (!result) TEST_FUNCTION_FAIL("Perfect power d = %wu is declared prime\n", d); } #if FLINT64 for (i = 0; i < sizeof(composites) / sizeof(mp_limb_t); i++) { d = composites[i]; result = !n_is_prime(d); if (!result) TEST_FUNCTION_FAIL("Known composite d = %wu is declared prime\n", d); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_prime_pocklington.c000066400000000000000000000034371461254215100237450ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_prime_pocklington, state) { int i, result; ulong count = 0; mp_limb_t d; mpz_t d_m; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest(state) | 1; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_prime_pocklington(d, 100); if (result == -1) count++; if (result == 0) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that composites do not pass */ { mpz_init(d_m); do { d = n_randtest(state) | 1; if (d == UWORD(1)) d++; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); result = n_is_prime_pocklington(d, 100); if (result == -1) count++; if (result == 1) TEST_FUNCTION_FAIL("d = %wu is declared prime\n", d); mpz_clear(d_m); } if (count > 200 * flint_test_multiplier()) TEST_FUNCTION_FAIL("FAIL: Pocklington-Lehmer failed too many times (%wu times)\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_prime_pseudosquare.c000066400000000000000000000030401461254215100241240ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_prime_pseudosquare, state) { int i, result; mp_limb_t d; mpz_t d_m; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest(state) | 1; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_prime_pseudosquare(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test that composites don't pass */ { mpz_init(d_m); do { d = n_randtest(state) | 1; if (d == UWORD(1)) d++; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); result = !n_is_prime_pseudosquare(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared prime\n", d); mpz_clear(d_m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_probabprime.c000066400000000000000000000043471461254215100225250ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_probabprime, state) { int i, result; mp_limb_t d; mpz_t d_m; slong pow; ulong bits; for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest(state) | 1; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_probabprime(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that composites do not pass */ { mpz_init(d_m); do { d = n_randtest(state) | 1; if (d == UWORD(1)) d++; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); result = !n_is_probabprime(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared prime\n", d); mpz_clear(d_m); } /* Test that powers do not pass */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { pow = n_randint(state, 6) + 2; bits = n_randint(state, FLINT_BITS) + 1; bits /= pow; d = n_randbits(state, bits); d = n_pow(d, pow); result = !n_is_probabprime(d); if (!result) TEST_FUNCTION_FAIL("Perfect power d = %wu is declared prime\n", d); } /* Regression test, check certain composites do not pass */ #if FLINT64 { d = UWORD(2007193456621); result = !n_is_probabprime(d); if (!result) TEST_FUNCTION_FAIL("Known composite d = %wu is declared prime\n", d); } #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_probabprime_BPSW.c000066400000000000000000000030061461254215100233470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_probabprime_BPSW, state) { int i, result; mp_limb_t d; mpz_t d_m; for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest_not_zero(state); flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_probabprime_BPSW(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that not too many composites pass */ { mpz_init(d_m); do { d = n_randtest(state); flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); result = (n_is_probabprime_BPSW(d) == 0); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared prime\n", d); mpz_clear(d_m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_probabprime_fermat.c000066400000000000000000000040251461254215100240540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_probabprime_fermat, state) { int i, result; ulong count = UWORD(0); mp_limb_t d, j; mpz_t d_m; for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest_not_zero(state); if (d == UWORD(1)) d++; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); do { j = n_randtest(state) % d; if ((j == WORD(1)) && (d != UWORD(2))) j++; } while (n_gcd(d, j) != UWORD(1)); result = n_is_probabprime_fermat(d, j); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that not too many composites pass */ { mpz_init(d_m); do { d = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); if (d < UWORD(2)) d = 2; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); do { j = n_randtest(state) % d; if ((j == WORD(1)) && (d != UWORD(2))) j++; } while (n_gcd(d, j) != UWORD(1)); if (n_is_probabprime_fermat(d, j)) count++; mpz_clear(d_m); } result = (count < 200 * flint_test_multiplier()); if (!result) TEST_FUNCTION_FAIL("%wu composites declared prime\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_probabprime_fibonacci.c000066400000000000000000000033241461254215100245140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_probabprime_fibonacci, state) { int i, result; ulong count = UWORD(0); mp_limb_t d; mpz_t d_m; slong test_multiplier; test_multiplier = FLINT_MAX(1, flint_test_multiplier()); for (i = 0; i < 10000 * test_multiplier; i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest_not_zero(state); flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_probabprime_fibonacci(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } for (i = 0; i < 10000 * test_multiplier; i++) /* Test that not too many composites pass */ { mpz_init(d_m); do { d = n_randtest(state) | UWORD(1); if ((d % 5) == 0) d+=2; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); if (n_is_probabprime_fibonacci(d)) count++; mpz_clear(d_m); } result = (count < 20 * test_multiplier); if (!result) TEST_FUNCTION_FAIL("%wu composites declared prime\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_probabprime_lucas.c000066400000000000000000000032361461254215100237100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_probabprime_lucas, state) { int i, result; ulong count = UWORD(0); mp_limb_t d; mpz_t d_m; slong test_multiplier; test_multiplier = FLINT_MAX(1, flint_test_multiplier()); for (i = 0; i < 10000 * test_multiplier; i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest_not_zero(state); flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_probabprime_lucas(d); if (!result) TEST_FUNCTION_FAIL("d = %wu is declared composite\n", d); mpz_clear(d_m); } for (i = 0; i < 10000 * test_multiplier; i++) /* Test that not too many composites pass */ { mpz_init(d_m); do { d = n_randtest(state); flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); if (n_is_probabprime_lucas(d) == 1) count++; mpz_clear(d_m); } result = (count < 20 * test_multiplier); if (!result) TEST_FUNCTION_FAIL("%wu composites declared prime\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_square.c000066400000000000000000000024101461254215100215100ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_square, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that non-squares pass */ { mp_limb_t a, s, bits; bits = n_randint(state, FLINT_BITS/2) + 1; a = n_randtest_bits(state, bits); s = a*a + n_randtest(state) % (2*a) + 1; result = !n_is_square(s); if (!result) TEST_FUNCTION_FAIL("s = %wu is declared square\n", s); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that squares pass */ { mp_limb_t a, s, bits; bits = n_randint(state, FLINT_BITS/2); a = n_randtest_bits(state, bits); s = a*a; result = n_is_square(s); if (!result) TEST_FUNCTION_FAIL("s = %wu is not declared square\n", s); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_squarefree.c000066400000000000000000000032071461254215100223570ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #ifndef check #define check(n, s1, s2) \ do \ { \ if (s1 != s2) \ TEST_FUNCTION_FAIL("%wu: got %d instead of %d\n", n, s1, s2); \ } while (0) #endif TEST_FUNCTION_START(n_is_squarefree, state) { int s, k; check(0, n_is_squarefree(0), 0); check(1, n_is_squarefree(1), 1); check(2, n_is_squarefree(2), 1); check(3, n_is_squarefree(3), 1); check(4, n_is_squarefree(4), 0); check(5, n_is_squarefree(5), 1); check(16, n_is_squarefree(16), 0); check(25, n_is_squarefree(25), 0); check(49, n_is_squarefree(49), 0); check(16*3, n_is_squarefree(16*3), 0); check(25*3, n_is_squarefree(25*3), 0); check(49*3, n_is_squarefree(49*3), 0); check(101*103, n_is_squarefree(101*103), 1); check(101*101, n_is_squarefree(101*101), 0); check(101*103*4, n_is_squarefree(101*103*4), 0); check(101*103*5, n_is_squarefree(101*103*5), 1); check(101*103*103*5, n_is_squarefree(101*103*103*5), 0); check(101*103*25, n_is_squarefree(101*103*25), 0); s = 0; for (k = 0; k <= 10000; k++) s += n_is_squarefree(k); if (s != 6083) TEST_FUNCTION_FAIL("expected %d squarefree numbers <= 10000 (got %d)\n", 6083, s); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_strong_probabprime2_preinv.c000066400000000000000000000045651461254215100255700ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_strong_probabprime2_preinv, state) { int i, result; ulong count = UWORD(0); slong test_multiplier; test_multiplier = FLINT_MAX(1, flint_test_multiplier()); for (i = 0; i < 100 * test_multiplier; i++) /* Test that primes pass the test */ { mp_limb_t a, d, dinv, norm; mpz_t d_m; ulong j; mpz_init(d_m); do { d = n_randtest(state) | 1; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); if (d == UWORD(2)) d++; for (j = 0; j < 100; j++) { do a = n_randtest(state) % d; while (a == UWORD(0)); dinv = n_preinvert_limb(d); norm = flint_ctz(d - 1); result = n_is_strong_probabprime2_preinv(d, dinv, a, (d - 1)>>norm); if (!result) TEST_FUNCTION_FAIL("a = %wu, d = %wu\n", a, d); } mpz_clear(d_m); } for (i = 0; i < 100 * test_multiplier; i++) /* Test that not too many composites pass */ { mp_limb_t a, d, dinv, norm; mpz_t d_m; ulong j; mpz_init(d_m); do { d = n_randtest(state) | 1; if (d == UWORD(1)) d++; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); for (j = 0; j < 100; j++) { do a = n_randtest(state) % d; while (a == UWORD(0)); dinv = n_preinvert_limb(d); norm = flint_ctz(d - 1); result = !n_is_strong_probabprime2_preinv(d, dinv, a, (d - 1)>>norm); if (!result) count++; } mpz_clear(d_m); } #if FLINT64 if (count > 220 * test_multiplier) #else if (count > 432 * test_multiplier) #endif TEST_FUNCTION_FAIL("count = %wu\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-is_strong_probabprime_precomp.c000066400000000000000000000046561461254215100256510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_is_strong_probabprime_precomp, state) { int i, j, result; ulong count = UWORD(0); slong test_multiplier; test_multiplier = FLINT_MAX(1, flint_test_multiplier()); for (i = 0; i < 100 * test_multiplier; i++) /* Test that primes pass the test */ { mp_limb_t a, d, norm; mpz_t d_m; double dpre; mp_limb_t bits = n_randint(state, FLINT_D_BITS-1) + 2; mpz_init(d_m); do { d = n_randbits(state, bits) | 1; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (FLINT_BIT_COUNT(d) > FLINT_D_BITS); if (d == UWORD(2)) d++; for (j = 0; j < 100; j++) { do a = n_randint(state, d); while (a == UWORD(0)); dpre = n_precompute_inverse(d); norm = flint_ctz(d - 1); result = n_is_strong_probabprime_precomp(d, dpre, a, (d - 1)>>norm); if (!result) TEST_FUNCTION_FAIL("a = %wu, d = %wu\n", a, d); } mpz_clear(d_m); } for (i = 0; i < 100 * test_multiplier; i++) /* Test that not too many composites pass */ { mp_limb_t a, d, norm; mpz_t d_m; double dpre; mp_limb_t bits = n_randint(state, FLINT_D_BITS-3) + 4; mpz_init(d_m); do { d = n_randbits(state, bits) | 1; flint_mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); for (j = 0; j < 100; j++) { do a = n_randint(state, d); while (a == UWORD(0)); dpre = n_precompute_inverse(d); norm = flint_ctz(d - 1); result = !n_is_strong_probabprime_precomp(d, dpre, a, (d - 1)>>norm); if (!result) count++; } mpz_clear(d_m); } if (count > 220 * test_multiplier) TEST_FUNCTION_FAIL("count = %wu\n", count); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-jacobi.c000066400000000000000000000021541461254215100207510ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_jacobi, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t d; mpz_t a_m, d_m; mp_limb_signed_t a; int r1, r2; mpz_init(a_m); mpz_init(d_m); a = n_randtest(state); d = n_randtest_not_zero(state) | WORD(1); r1 = n_jacobi(a, d); flint_mpz_set_si(a_m, a); flint_mpz_set_ui(d_m, d); r2 = mpz_jacobi(a_m, d_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL("a = %wu, d = %wu\n", a, d); mpz_clear(a_m); mpz_clear(d_m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-ll_mod_preinv.c000066400000000000000000000042601461254215100223530ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #include "fmpz.h" TEST_FUNCTION_START(n_ll_mod_preinv, state) { int i, result; fmpz_t n; /* check (m*d + r1) % d == r1 */ for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong d, dinv, nh, nl, r1, r2, m; d = n_randtest_not_zero(state); m = n_randtest(state); r1 = n_randtest(state) % d; /* = m*d + r1 < (m + 1)*d <= 2^FLINT_BITS * d */ umul_ppmm(nh, nl, m, d); add_ssaaaa(nh, nl, nh, nl, UWORD(0), r1); dinv = n_preinvert_limb(d); r2 = n_ll_mod_preinv(nh, nl, d, dinv); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( " = (m*d + r1) but %% d != r1\n" "nh = %wu, nl = %wu, d = %wu, dinv = %wu\n" "r1 = %wu, r2 = %wu\n", nh, nl, d, dinv, r1, r2); } fmpz_init(n); /* compare with fmpz_fdiv_ui */ for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong d, dinv, nh, nl, r1, r2; d = n_randtest_not_zero(state); nh = n_randtest(state); nl = n_randtest(state); dinv = n_preinvert_limb(d); /* n = */ fmpz_set_ui(n, nh); fmpz_mul_2exp(n, n, FLINT_BITS); fmpz_add_ui(n, n, nl); r1 = n_ll_mod_preinv(nh, nl, d, dinv); r2 = fmpz_fdiv_ui(n, d); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "n = but n % d does not agree with fmpz_fdiv_ui\n" "nh = %wu, nl = %wu, d = %wu, dinv = %wu\n" "r1 = %wu, r2 = %wu\n", nh, nl, d, dinv, r1, r2); } fmpz_clear(n); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-lll_mod_preinv.c000066400000000000000000000024101461254215100225220ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_lll_mod_preinv, state) { int i, result; /* test n_lll_mod_preinv against n_ll_mod_preinv */ for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong d, dinv, nh, nm, nl, r1, r2, rm; d = n_randtest_not_zero(state); nh = n_randtest(state) % d; nm = n_randtest(state); nl = n_randtest(state); dinv = n_preinvert_limb(d); r2 = n_lll_mod_preinv(nh, nm, nl, d, dinv); rm = n_ll_mod_preinv(nh, nm, d, dinv); r1 = n_ll_mod_preinv(rm, nl, d, dinv); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "nh = %wu, nm = %wd, nl = %wu, d = %wu, dinv = %wu\n" "r1 = %wu, r2 = %wu\n", nh, nm, nl, d, dinv, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mod2_precomp.c000066400000000000000000000020271461254215100221070ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mod2_precomp, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t d, n, r1, r2; double dpre; d = n_randtest_not_zero(state); n = n_randtest(state); dpre = n_precompute_inverse(d); r1 = n_mod2_precomp(n, d, dpre); r2 = n%d; result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "n = %wu, d = %wu, dpre = %f\n" "r1 = %wu, r2 = %wu\n", n, d, dpre, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mod2_preinv.c000066400000000000000000000020061461254215100217420ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mod2_preinv, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong d, dinv, n, r1, r2; d = n_randtest_not_zero(state); n = n_randtest(state); dinv = n_preinvert_limb(d); r1 = n_mod2_preinv(n, d, dinv); r2 = n % d; result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "n = %wu, d = %wu, dinv = %wu\n" "r1 = %wu, r2 = %wu\n", n, d, dinv, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mod_precomp.c000066400000000000000000000024121461254215100220230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mod_precomp, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t bits, d, n, r1, r2; double dpre; bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); if (bits <= (FLINT_BITS/2)) n = n_randtest(state) % (d*d); else n = n_randtest(state); /* must have n < 2^(FLINT_BITS - 1) */ if (FLINT_BIT_COUNT(n) == FLINT_BITS) n >>= 1; dpre = n_precompute_inverse(d); r1 = n_mod_precomp(n, d, dpre); r2 = n%d; result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "n = %wu, d = %wu, dinv = %g\n" "r1 = %wu, r2 = %wu\n", n, d, dpre, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-moebius_mu.c000066400000000000000000000034271461254215100216720ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #ifndef check #define check(n, s1, s2) \ do \ { \ if (s1 != s2) \ TEST_FUNCTION_FAIL("%wu: got %d instead of %d\n", n, s1, s2); \ } while (0) #endif TEST_FUNCTION_START(n_moebius_mu, state) { int n, k, s; int * mu; check(0, n_moebius_mu(0), 0); check(1, n_moebius_mu(1), 1); for (n = 1; n < 100; n++) { mu = flint_malloc(sizeof(int) * n); n_moebius_mu_vec(mu, n); for (k = 0; k < n; k++) check(k, mu[k], n_moebius_mu(k)); flint_free(mu); } mu = flint_malloc(sizeof(int) * 10000); n_moebius_mu_vec(mu, 10000); for (k = 0; k < n; k++) check(k, mu[k], n_moebius_mu(k)); flint_free(mu); check(10000, n_moebius_mu(10000), 0); check(10001, n_moebius_mu(10001), 1); check(10002, n_moebius_mu(10002), -1); check(10003, n_moebius_mu(10003), 1); check(10004, n_moebius_mu(10004), 0); check(10005, n_moebius_mu(10005), 1); check(10006, n_moebius_mu(10006), 1); check(10007, n_moebius_mu(10007), -1); check(10008, n_moebius_mu(10008), 0); check(10009, n_moebius_mu(10009), -1); check(10010, n_moebius_mu(10010), -1); s = 0; for (k = 0; k <= 10000; k++) s += n_moebius_mu(k); if (s != -23) TEST_FUNCTION_FAIL("expected mu(k), k <= 10000 to sum to %d (got %d)\n", -23, s); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mulmod2.c000066400000000000000000000021201461254215100210720ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mulmod2, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong a, b, d, r1, r2, q, p1, p2; d = n_randtest_not_zero(state); a = n_randtest(state) % d; b = n_randtest(state) % d; r1 = n_mulmod2(a, b, d); umul_ppmm(p1, p2, a, b); p1 %= d; udiv_qrnnd(q, r2, p1, p2, d); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, b = %wu, d = %wu\n" "q = %wu, r1 = %wu, r2 = %wu\n", a, b, d, q, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mulmod2_preinv.c000066400000000000000000000022411461254215100224610ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mulmod2_preinv, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong a, b, d, r1, r2, q, p1, p2, dinv; d = n_randtest_not_zero(state); a = n_randtest(state) % d; b = n_randtest(state) % d; dinv = n_preinvert_limb(d); r1 = n_mulmod2_preinv(a, b, d, dinv); umul_ppmm(p1, p2, a, b); p1 %= d; udiv_qrnnd(q, r2, p1, p2, d); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, b = %wu, d = %wu, dinv = %wu\n" "q = %wu, r1 = %wu, r2 = %wu\n", a, b, d, dinv, q, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mulmod_precomp.c000066400000000000000000000024031461254215100225410ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mulmod_precomp, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t a, b, d, r1, r2, p1, p2, dinv; double dpre; mp_limb_t bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); a = n_randtest(state) % d; b = n_randtest(state) % d; dpre = n_precompute_inverse(d); r1 = n_mulmod_precomp(a, b, d, dpre); umul_ppmm(p1, p2, a, b); dinv = n_preinvert_limb(d); r2 = n_ll_mod_preinv(p1, p2, d, dinv); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, b = %wu, d = %wu, dinv = %f\n" "r1 = %wu, r2 = %wu\n", a, b, d, dpre, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mulmod_preinv.c000066400000000000000000000024161461254215100224030ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mulmod_preinv, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong a, b, d, r1, r2, q, p1, p2, dinv, norm; d = n_randtest_not_zero(state); a = n_randtest(state) % d; b = n_randtest(state) % d; norm = flint_clz(d); dinv = n_preinvert_limb(d << norm); r1 = n_mulmod_preinv(a << norm, b << norm, d << norm, dinv, norm) >> norm; umul_ppmm(p1, p2, a, b); p1 %= d; udiv_qrnnd(q, r2, p1, p2, d); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, b = %wu, d = %wu, dinv = %wu\n" "q = %wu, r1 = %wu, r2 = %wu\n", a, b, d, dinv, q, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-mulmod_shoup.c000066400000000000000000000023251461254215100222350ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart Copyright (C) 2015 Vladimir Glazachev This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_mulmod_shoup, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, b, d, r1, r2, q, p1, p2, w_pr; d = n_randtest_not_zero(state) / 2 + 1; a = n_randtest(state) % d; b = n_randtest(state) % d; w_pr = n_mulmod_precomp_shoup(a, d); r1 = n_mulmod_shoup(a, b, w_pr, d); umul_ppmm(p1, p2, a, b); p1 %= d; udiv_qrnnd(q, r2, p1, p2, d); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, b = %wu, d = %wu, w_pr = %wu\n" "q = %wu, r1 = %wu, r2 = %wu\n", a, b, d, w_pr, q, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-nextprime.c000066400000000000000000000034001461254215100215300ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2008 Peter Shrimpton Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_nextprime, state) { mp_limb_t n; mp_limb_t res1, res2; slong rep; mpz_t mpz_n; if (n_nextprime(0, 0) != 2) TEST_FUNCTION_FAIL("FAIL: expected n_nextprime(0) = 2"); if (n_nextprime(UWORD_MAX_PRIME - 1, 0) != UWORD_MAX_PRIME) TEST_FUNCTION_FAIL("FAIL: expected n_nextprime(UWORD_MAX_PRIME-1) = UWORD_MAX_PRIME"); mpz_init(mpz_n); for (rep = 0; rep < 10000 * flint_test_multiplier(); rep++) { ulong bits = n_randint(state, FLINT_D_BITS-1)+1; n = n_randtest(state) % ((UWORD(1)<. */ #include "test_helpers.h" #include "ulong_extras.h" #define check_prime_bounds(n, ans) \ do { \ int ok, reasonable; \ mp_limb_t lo, hi; \ n_nth_prime_bounds(&lo, &hi, n); \ \ ok = lo <= ans && ans <= hi; \ reasonable = (n < 1000) || (ans/2 < lo && hi < ans*2); \ \ if (!(ok && reasonable)) \ TEST_FUNCTION_FAIL("n = %wu: %wu < %wu < %wu\n", n, lo, ans, hi); \ } while (0) TEST_FUNCTION_START(n_nth_prime_bounds, state) { int n; for (n=6; n<7500 * FLINT_MIN(10, flint_test_multiplier()); n++) { check_prime_bounds(n, n_nth_prime(n)); } /* Some known large primes */ check_prime_bounds(UWORD(10), UWORD(29)); check_prime_bounds(UWORD(100), UWORD(541)); check_prime_bounds(UWORD(1000), UWORD(7919)); check_prime_bounds(UWORD(10000), UWORD(104729)); check_prime_bounds(UWORD(100000), UWORD(1299709)); check_prime_bounds(UWORD(1000000), UWORD(15485863)); check_prime_bounds(UWORD(10000000), UWORD(179424673)); check_prime_bounds(UWORD(100000000), UWORD(2038074743)); #if FLINT64 check_prime_bounds(UWORD(1000000000), UWORD(22801763489)); check_prime_bounds(UWORD(10000000000), UWORD(252097800623)); check_prime_bounds(UWORD(100000000000), UWORD(2760727302517)); check_prime_bounds(UWORD(1000000000000), UWORD(29996224275833)); check_prime_bounds(UWORD(10000000000000), UWORD(323780508946331)); check_prime_bounds(UWORD(100000000000000), UWORD(3475385758524527)); check_prime_bounds(UWORD(1000000000000000), UWORD(37124508045065437)); check_prime_bounds(UWORD(10000000000000000), UWORD(394906913903735329)); check_prime_bounds(UWORD(100000000000000000), UWORD(4185296581467695669)); #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-pow.c000066400000000000000000000022551461254215100203310ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_pow, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test a^e1 * a^e2 = a^(e1 + e2) */ { mp_limb_t exp1, exp2, n, bits, r1, r2; bits = n_randint(state, 55) + 10; exp1 = n_randint(state, 5); exp2 = n_randint(state, 5); if ((exp1 == WORD(0)) && (exp2 == WORD(0))) bits = n_randint(state, 64) + 1; else bits /= (exp1 + exp2); n = n_randtest_bits(state, bits); r1 = n_pow(n, exp1)*n_pow(n, exp2); r2 = n_pow(n, exp1 + exp2); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL("n = %wu, exp1 = %wu, exp2 = %wu, r1 = %wu, r2 = %wu\n", n, exp1, exp2, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-powmod.c000066400000000000000000000040031461254215100210220ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_powmod, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t bits, a, d, r1, r2; mpz_t a_m, d_m, r2_m; mp_limb_signed_t exp; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); do { a = n_randtest(state) % d; } while (n_gcd(d, a) != UWORD(1)); exp = n_randtest(state); r1 = n_powmod(a, exp, d); flint_mpz_set_ui(a_m, a); flint_mpz_set_ui(d_m, d); if (exp < WORD(0)) { flint_mpz_powm_ui(r2_m, a_m, -exp, d_m); mpz_invert(r2_m, r2_m, d_m); } else flint_mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = flint_mpz_get_ui(r2_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, exp = %wd, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, exp, d, r1, r2); mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } /* check 0^0 = 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t bits, d, r; bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); if (d == 0) d++; r = n_powmod(0, 0, d); result = (r == 1 || (d == 1 && r == 0)); if (!result) TEST_FUNCTION_FAIL("0^0 != 1 mod %wd\n", d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-powmod2.c000066400000000000000000000042741461254215100211160ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "long_extras.h" TEST_FUNCTION_START(n_powmod2, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, d, r1, r2; mpz_t a_m, d_m, r2_m; slong exp; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); d = n_randtest_not_zero(state); do { a = n_randtest(state); } while (n_gcd(d, a) != 1); exp = z_randtest(state); r1 = n_powmod2(a, exp, d); flint_mpz_set_ui(a_m, a); flint_mpz_set_ui(d_m, d); if (exp < WORD(0)) { flint_mpz_powm_ui(r2_m, a_m, -exp, d_m); mpz_invert(r2_m, r2_m, d_m); } else flint_mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = flint_mpz_get_ui(r2_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, exp = %wd, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, exp, d, r1, r2); mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } /* check 0^0 = 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong d, r; d = n_randtest_not_zero(state); r = n_powmod2(0, 0, d); result = (r == 1 || (d == 1 && r == 0)); if (!result) TEST_FUNCTION_FAIL("0^0 != 1 mod %wd\n", d); } /* check 0^exp = 0 mod 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong r; slong exp; exp = z_randtest(state); r = n_powmod2(0, exp, 1); result = (r == 0); if (!result) TEST_FUNCTION_FAIL("0^%wd != 0 mod 1\n", exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-powmod2_preinv.c000066400000000000000000000045641461254215100225030ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" #include "long_extras.h" TEST_FUNCTION_START(n_powmod2_preinv, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, d, r1, r2, dinv; mpz_t a_m, d_m, r2_m; slong exp; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); d = n_randtest_not_zero(state); do { a = n_randtest(state); } while (n_gcd(d, a) != 1); exp = z_randtest(state); dinv = n_preinvert_limb(d); r1 = n_powmod2_preinv(a, exp, d, dinv); flint_mpz_set_ui(a_m, a); flint_mpz_set_ui(d_m, d); if (exp < 0) { flint_mpz_powm_ui(r2_m, a_m, -exp, d_m); mpz_invert(r2_m, r2_m, d_m); } else flint_mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = flint_mpz_get_ui(r2_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, exp = %wd, d = %wu, dinv = %wu\n" "r1 = %wu, r2 = %wu\n", a, exp, d, dinv, r1, r2); mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } /* check 0^0 = 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong d, r, dinv; d = n_randtest_not_zero(state); dinv = n_preinvert_limb(d); r = n_powmod2_preinv(0, 0, d, dinv); result = (r == 1 || (d == 1 && r == 0)); if (!result) TEST_FUNCTION_FAIL("0^0 != 1 mod %wd\n", d); } /* check 0^exp = 0 mod 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong r, dinv; slong exp; exp = z_randtest(state); dinv = n_preinvert_limb(1); r = n_powmod2_preinv(0, exp, 1, dinv); result = (r == 0); if (!result) TEST_FUNCTION_FAIL("0^%wd != 0 mod 1\n", exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-powmod2_ui_preinv.c000066400000000000000000000042411461254215100231700ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_powmod2_ui_preinv, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, d, r1, r2, dinv, exp; mpz_t a_m, d_m, r2_m; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); d = n_randtest_not_zero(state); do { a = n_randtest(state); } while (n_gcd(d, a) != 1); exp = n_randtest(state); dinv = n_preinvert_limb(d); r1 = n_powmod2_ui_preinv(a, exp, d, dinv); flint_mpz_set_ui(a_m, a); flint_mpz_set_ui(d_m, d); flint_mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = flint_mpz_get_ui(r2_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, exp = %wu, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, exp, d, r1, r2); mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } /* check 0^0 = 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong d, r, dinv; d = n_randtest_not_zero(state); dinv = n_preinvert_limb(d); r = n_powmod2_ui_preinv(0, 0, d, dinv); result = (r == 1 || (d == 1 && r == 0)); if (!result) TEST_FUNCTION_FAIL("0^0 != 1 mod %wd\n", d); } /* check 0^exp = 0 mod 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong r, dinv, exp; exp = n_randtest(state); dinv = n_preinvert_limb(1); r = n_powmod2_ui_preinv(0, exp, 1, dinv); result = (r == 0); if (!result) TEST_FUNCTION_FAIL("0^%wd != 0 mod 1\n", exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-powmod_precomp.c000066400000000000000000000042411461254215100225530ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_powmod_precomp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, d, r1, r2, bits; mpz_t a_m, d_m, r2_m; mp_limb_signed_t exp; double dpre; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); do { a = n_randtest(state) % d; } while (n_gcd(d, a) != UWORD(1)); exp = n_randtest(state); dpre = n_precompute_inverse(d); r1 = n_powmod_precomp(a, exp, d, dpre); flint_mpz_set_ui(a_m, a); flint_mpz_set_ui(d_m, d); if (exp < WORD(0)) { flint_mpz_powm_ui(r2_m, a_m, -exp, d_m); mpz_invert(r2_m, r2_m, d_m); } else flint_mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = flint_mpz_get_ui(r2_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, exp = %wd, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, exp, d, r1, r2); mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } /* check 0^0 = 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t bits, d, r; double dpre; bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); if (d == 0) d++; dpre = n_precompute_inverse(d); r = n_powmod_precomp(0, 0, d, dpre); result = (r == 1 || (d == 1 && r == 0)); if (!result) TEST_FUNCTION_FAIL("0^0 != 1 mod %wd\n", d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-powmod_ui_precomp.c000066400000000000000000000040151461254215100232470ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_powmod_ui_precomp, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, d, r1, r2, bits; mpz_t a_m, d_m, r2_m; mp_limb_t exp; double dpre; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); do { a = n_randtest(state) % d; } while (n_gcd(d, a) != UWORD(1)); exp = n_randtest(state); dpre = n_precompute_inverse(d); r1 = n_powmod_ui_precomp(a, exp, d, dpre); flint_mpz_set_ui(a_m, a); flint_mpz_set_ui(d_m, d); flint_mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = flint_mpz_get_ui(r2_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, exp = %wd, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, exp, d, r1, r2); mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } /* check 0^0 = 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t bits, d, r; double dpre; bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); if (d == 0) d++; dpre = n_precompute_inverse(d); r = n_powmod_ui_precomp(0, 0, d, dpre); result = (r == 1 || (d == 1 && r == 0)); if (!result) TEST_FUNCTION_FAIL("0^0 != 1 mod %wd\n", d); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-powmod_ui_preinv.c000066400000000000000000000046441461254215100231150ustar00rootroot00000000000000/* Copyright (C) 2009, 2013, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_powmod_ui_preinv, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, d, r1, r2, dinv, exp, norm; mpz_t a_m, d_m, r2_m; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); d = n_randtest_not_zero(state); do { a = n_randtest(state) % d; } while (n_gcd(d, a) != UWORD(1)); exp = n_randtest(state); norm = flint_clz(d); dinv = n_preinvert_limb(d); r1 = n_powmod_ui_preinv(a << norm, exp, d << norm, dinv, norm) >> norm; flint_mpz_set_ui(a_m, a); flint_mpz_set_ui(d_m, d); flint_mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = flint_mpz_get_ui(r2_m); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, exp = %wu, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, exp, d, r1, r2); mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } /* check 0^0 = 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong d, r, dinv, norm; d = n_randtest_not_zero(state); norm = flint_clz(d); dinv = n_preinvert_limb(d); r = n_powmod_ui_preinv(0, 0, d << norm, dinv, norm) >> norm; /* 0^0 = 0 mod 1 and 0^0 = 1 mod d for d != 1 */ result = (r == 1 || (d == 1 && r == 0)); if (!result) TEST_FUNCTION_FAIL("0^0 != 1 mod %wd\n", d); } /* check 0^exp = 0 mod 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong r, dinv, norm, exp; exp = n_randtest(state); norm = flint_clz(1); dinv = n_preinvert_limb(1); r = n_powmod_ui_preinv(0, exp, UWORD(1) << norm, dinv, norm) >> norm; result = (r == 0); if (!result) TEST_FUNCTION_FAIL("0^%wd != 0 mod 1\n", exp); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-preinvert_limb_prenorm.c000066400000000000000000000022451461254215100243060ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #define invert_limb_naive(ninv, n) \ do { \ mp_limb_t dummy; \ udiv_qrnnd (ninv, dummy, ~(n), ~(WORD(0)), n); \ } while (0) TEST_FUNCTION_START(n_preinvert_limb_prenorm, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t n, ninv1, ninv2; n = n_randtest(state); n |= (UWORD(1) << (FLINT_BITS - 1)); ninv1 = n_preinvert_limb_prenorm(n); invert_limb_naive(ninv2, n); result = (ninv1 == ninv2); if (!result) TEST_FUNCTION_FAIL("n = %wx, ninv1 = %wx, ninv2 = %wx\n", n, ninv1, ninv2); } TEST_FUNCTION_END(state) } flint-3.1.3/src/ulong_extras/test/t-prime_pi.c000066400000000000000000000016551461254215100213330ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_prime_pi, state) { int n; for (n=1; n<10000 * FLINT_MIN(10, flint_test_multiplier()); n++) { if ((n_prime_pi(n-1)+1 == n_prime_pi(n)) != n_is_prime(n)) TEST_FUNCTION_FAIL("expected pi(%d) + 1 = pi(%d)\n", n-1, n); } for (n=1; n<5000 * FLINT_MIN(10, flint_test_multiplier()); n++) { if (n_prime_pi(n_nth_prime(n)) != n) TEST_FUNCTION_FAIL("expected pi(prime(%d)) = %d\n", n, n); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-prime_pi_bounds.c000066400000000000000000000040511461254215100226760ustar00rootroot00000000000000/* Copyright (C) 2010 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" #define check_prime_pi_bound(n, ans) \ do { \ int ok, reasonable; \ ulong lo, hi; \ n_prime_pi_bounds(&lo, &hi, n); \ \ ok = lo <= ans && ans <= hi; \ reasonable = (n < 1000) || (ans/2 < lo && hi < ans*2); \ \ if (!(ok && reasonable)) \ TEST_FUNCTION_FAIL("n = %wu: %wu < %wu < %wu\n", n, lo, ans, hi); \ } while (0) TEST_FUNCTION_START(n_prime_pi_bounds, state) { int n; for (n=17; n<10000 * FLINT_MIN(10, flint_test_multiplier()); n++) { check_prime_pi_bound(n, n_prime_pi(n)); } check_prime_pi_bound(UWORD(10), UWORD(4)); check_prime_pi_bound(UWORD(100), UWORD(25)); check_prime_pi_bound(UWORD(1000), UWORD(168)); check_prime_pi_bound(UWORD(10000), UWORD(1229)); check_prime_pi_bound(UWORD(100000), UWORD(9592)); check_prime_pi_bound(UWORD(1000000), UWORD(78498)); check_prime_pi_bound(UWORD(10000000), UWORD(664579)); check_prime_pi_bound(UWORD(100000000), UWORD(5761455)); check_prime_pi_bound(UWORD(1000000000), UWORD(50847534)); #if FLINT64 check_prime_pi_bound(UWORD(10000000000), UWORD(455052511)); check_prime_pi_bound(UWORD(100000000000), UWORD(4118054813)); check_prime_pi_bound(UWORD(1000000000000), UWORD(37607912018)); check_prime_pi_bound(UWORD(10000000000000), UWORD(346065536839)); check_prime_pi_bound(UWORD(100000000000000), UWORD(3204941750802)); check_prime_pi_bound(UWORD(1000000000000000), UWORD(29844570422669)); check_prime_pi_bound(UWORD(10000000000000000), UWORD(279238341033925)); check_prime_pi_bound(UWORD(100000000000000000), UWORD(2623557157654233)); #endif TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-primes.c000066400000000000000000000026751461254215100210310ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_primes, state) { slong n; /* compare with n_nextprime */ { n_primes_t iter; slong i; mp_limb_t p, q; n_primes_init(iter); q = 0; for (i = 0; i < 200000; i++) { p = n_primes_next(iter); q = n_nextprime(q, 0); if (p != q) TEST_FUNCTION_FAIL("i = %wu, p = %wu, q = %wu\n", i, p, q); } n_primes_clear(iter); } /* count primes */ for (n = 0; n < 10; n++) { n_primes_t iter; mp_limb_t s, p, r; const unsigned int primepi[10] = { 0, 4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534 }; r = n_pow(10, n); n_primes_init(iter); s = 0; while ((p = n_primes_next(iter)) <= r) s++; if (s != primepi[n]) TEST_FUNCTION_FAIL("pi(10^%wd) = %u, computed = %wu\n", n, primepi[n], s); n_primes_clear(iter); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-primes_jump_after.c000066400000000000000000000021041461254215100232300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_primes_jump_after, state) { slong j, k, l; for (j = 0; j < 10; j++) { n_primes_t iter; n_primes_init(iter); for (k = 0; k < 100; k++) { mp_limb_t p, q; q = n_randtest(state) % UWORD(1000000000); n_primes_jump_after(iter, q); for (l = 0; l < 100; l++) { p = n_primes_next(iter); q = n_nextprime(q, 0); if (p != q) TEST_FUNCTION_FAIL("p = %wu, q = %wu\n", p, q); } } n_primes_clear(iter); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-primitive_root_prime.c000066400000000000000000000020741461254215100237720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_primitive_root_prime, state) { int i, j; for (i = 0; i < 100; i++) { n_factor_t factors; mp_limb_t p, root; double pinv; n_factor_init(&factors); p = n_randtest_prime(state, 1); pinv = n_precompute_inverse(p); n_factor(&factors, p - 1, 1); root = n_primitive_root_prime(p); for (j = 0; j < factors.num; j++) { if (n_powmod_precomp(root, (p-1) / factors.p[j], p, pinv) == 1) TEST_FUNCTION_FAIL("%wu ** (%wu / %wu) == 1 mod %wu\n", root, p-1, factors.p[j], p); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-remove.c000066400000000000000000000050531461254215100210200ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_remove, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test random numbers */ { mp_limb_t n1, n2, orig_n; mpz_t d_n2, d_n1, d_p; int exp1, exp2; ulong j; mpz_init(d_n1); mpz_init(d_n2); mpz_init(d_p); n1 = n_randtest_not_zero(state); orig_n = n1; for (j = 0; j < FLINT_NUM_PRIMES_SMALL/10; j++) { flint_mpz_set_ui(d_n1, n1); flint_mpz_set_ui(d_p, flint_primes_small[j]); exp1 = n_remove(&n1, flint_primes_small[j]); exp2 = mpz_remove(d_n2, d_n1, d_p); n2 = flint_mpz_get_ui(d_n2); result = ((exp1 == exp2) && (n1 == n2)); if (!result) TEST_FUNCTION_FAIL("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); } mpz_clear(d_n1); mpz_clear(d_n2); mpz_clear(d_p); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test perfect powers */ { mp_limb_t n1, n2, orig_n, base; mpz_t d_n2, d_n1, d_p; int exp1, exp2, exp; ulong j; mpz_init(d_n1); mpz_init(d_n2); mpz_init(d_p); base = n_randtest_not_zero(state); n1 = base; exp = n_randint(state, FLINT_BITS/FLINT_BIT_COUNT(n1)) + 1; n1 = n_pow(base, exp); orig_n = n1; for (j = 0; j < FLINT_NUM_PRIMES_SMALL/10; j++) { flint_mpz_set_ui(d_n1, n1); flint_mpz_set_ui(d_p, flint_primes_small[j]); exp1 = n_remove(&n1, flint_primes_small[j]); exp2 = mpz_remove(d_n2, d_n1, d_p); n2 = flint_mpz_get_ui(d_n2); result = ((exp1 == exp2) && (n1 == n2)); if (!result) TEST_FUNCTION_FAIL("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); } mpz_clear(d_n1); mpz_clear(d_n2); mpz_clear(d_p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-remove2_precomp.c000066400000000000000000000053441461254215100226320ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_remove2_precomp, state) { int i, result; const mp_limb_t * primes; const double * inverses; primes = n_primes_arr_readonly(10000); inverses = n_prime_inverses_arr_readonly(10000); for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test random numbers */ { mp_limb_t n1, n2, orig_n; mpz_t d_n2, d_n1, d_p; int exp1, exp2; ulong j; mpz_init(d_n1); mpz_init(d_n2); mpz_init(d_p); n1 = n_randtest_not_zero(state); orig_n = n1; for (j = 0; j < FLINT_NUM_PRIMES_SMALL/10; j++) { flint_mpz_set_ui(d_n1, n1); flint_mpz_set_ui(d_p, flint_primes_small[j]); exp1 = n_remove2_precomp(&n1, primes[j], inverses[j]); exp2 = mpz_remove(d_n2, d_n1, d_p); n2 = flint_mpz_get_ui(d_n2); result = ((exp1 == exp2) && (n1 == n2)); if (!result) TEST_FUNCTION_FAIL("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); } mpz_clear(d_n1); mpz_clear(d_n2); mpz_clear(d_p); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test perfect powers */ { mp_limb_t n1, n2, orig_n, base; mpz_t d_n2, d_n1, d_p; int exp1, exp2, exp; ulong j; mpz_init(d_n1); mpz_init(d_n2); mpz_init(d_p); base = n_randtest_not_zero(state); n1 = base; exp = n_randint(state, FLINT_BITS/FLINT_BIT_COUNT(n1)) + 1; n1 = n_pow(base, exp); orig_n = n1; for (j = 0; j < FLINT_NUM_PRIMES_SMALL/10; j++) { flint_mpz_set_ui(d_n1, n1); flint_mpz_set_ui(d_p, flint_primes_small[j]); exp1 = n_remove2_precomp(&n1, primes[j], inverses[j]); exp2 = mpz_remove(d_n2, d_n1, d_p); n2 = flint_mpz_get_ui(d_n2); result = ((exp1 == exp2) && (n1 == n2)); if (!result) TEST_FUNCTION_FAIL("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); } mpz_clear(d_n1); mpz_clear(d_n2); mpz_clear(d_p); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-revbin.c000066400000000000000000000055531461254215100210150ustar00rootroot00000000000000/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" ulong n_revbin_naive(ulong n, ulong b) { ulong r = 0, i; for (i = 0; i < b; i++) { r <<= 1; r += (n & 1); n >>= 1; } return r; } TEST_FUNCTION_START(n_revbin, state) { int i, result; /* 0 bits */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong n, b, r; n = n_randlimb(state); b = 0; r = n_revbin(n, b); result = (r == 0); if (!result) TEST_FUNCTION_FAIL( "b = %wu\n" "n = %wx\n" "r = %wx\n", b, n, r); } /* at most 8 bits */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { ulong n, b, d, r1, r2, mask; for (b = 1; b <= 8; b++) { mask = ~((UWORD(1) << b) - UWORD(1)); /* 1111..11100..0 */ for (d = 0; d < UWORD(1) << b; d++) { /* garbage in top FLINT_BITS - b bits */ n = (n_randlimb(state) & mask); n |= d; r1 = n_revbin(n, b); r2 = n_revbin_naive(d, b); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "b = %wu\n" "n = %wx\n" "d = %wx\n" "r1 = %wx\n" "r2 = %wx\n" , b, n, d, r1, r2); } } } /* random number of bits */ for (i = 0; i < 100; i++) { ulong n, b, d, j, r1, r2, mask; b = n_randint(state, FLINT_BITS) + 1; /* 1111..11100..0 */ mask = b == FLINT_BITS ? UWORD(0) : ~((UWORD(1) << b) - UWORD(1)); for (j = 0; j < 1000 * flint_test_multiplier(); j++) { /* garbage in top FLINT_BITS - b bits */ n = (n_randlimb(state) & mask); d = n_randbits(state, n_randint(state, b) + 1); n |= d; r1 = n_revbin(n, b); r2 = n_revbin_naive(d, b); result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "b = %wu\n" "n = %wx\n" "d = %wx\n" "r1 = %wx\n" "r2 = %wx\n" , b, n, d, r1, r2); } } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-root.c000066400000000000000000000077601461254215100205150ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_root, state) { int i, result; mp_limb_t upper_limit; #if FLINT64 upper_limit = 2642245; #else upper_limit = 1625; #endif /* random n and root */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, c, d, val; mpz_t e, f, g; mpz_init(e); mpz_init(f); mpz_init(g); c = n_randint(state, 0); /*number */ flint_mpz_set_ui(g, c); d = n_randint(state, 0); /*root */ flint_mpz_set_ui(f, d); a = n_root(c, d); mpz_root(e, g, d); val = flint_mpz_get_ui(e); result = (a == val); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu\n" "Expected answer : base = %wu\n", c, d, a, val); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* n of type a^b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, c, d, max_pow, base; base = n_randint(state, upper_limit - 2) + 2; /* base form 2 to 2642245*/ max_pow = n_flog(UWORD_MAX, base); d = n_randint(state, max_pow); /* root */ if (!d) d+=1; c = n_pow(base, d); /* number */ a = n_root(c, d); result = (a == base); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu\n" "Expected answer : base = %wu\n", c, d, a, base); } /* n of type a^b + 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, c, d, max_pow, base; base = n_randint(state, upper_limit - 2) + 2; /* base between 2 to 2642245*/ max_pow = n_flog(UWORD_MAX, base); d = n_randint(state, max_pow); if (d < 2) /* root between 2 to max_pow */ d = 2; c = n_pow(base, d) + 1; /* number */ a = n_root(c, d); result = (a == base); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu\n" "Expected answer : base = %wu\n", c, d, a, base); } /* n of type a^b - 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, c, d, max_pow, base, val; mpz_t e, g, h; mpz_init(e); mpz_init(g); mpz_init(h); base = n_randint(state, upper_limit - 2) + 2; /* base between 2 to 2642245*/ max_pow = n_flog(UWORD_MAX, base); d = n_randint(state, max_pow); if (d < 2) /* root between 2 to max_pow */ d = 2; flint_mpz_set_ui(h, d); c = n_pow(base, d) - 1; /* number */ flint_mpz_set_ui(g, c); a = n_root(c, d); mpz_root(e, g, d); val = flint_mpz_get_ui(e); result = (a == val); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu\n" "Expected answer : base = %wu\n", c, d, a, val); mpz_clear(e); mpz_clear(g); mpz_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-rootrem.c000066400000000000000000000106661461254215100212200ustar00rootroot00000000000000/* Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_rootrem, state) { int i, result; mp_limb_t upper_limit; #if FLINT64 upper_limit = 2642245; #else upper_limit = 1625; #endif /* random n and root */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, b, c, d, val, j; mpz_t e, f, g, h; mpz_init(e); mpz_init(f); mpz_init(g); mpz_init(h); c = n_randint(state, 0); /*number */ flint_mpz_set_ui(g, c); d = n_randint(state, 0); /*root */ flint_mpz_set_ui(h, d); a = n_rootrem(&b, c, d); mpz_rootrem(e, f, g, flint_mpz_get_ui(h)); val = flint_mpz_get_ui(e); j = flint_mpz_get_ui(f); result = ((a == val) && (b == j)); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu remainder = %wu\n" "Expected answer : base = %wu remainder = %wu\n", c, d, a, b, val, j); mpz_clear(e); mpz_clear(f); mpz_clear(g); mpz_clear(h); } /* n of type a^b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, b, c, d, max_pow, base; base = n_randint(state, upper_limit - 2) + 2; /* base form 2 to 2642245*/ max_pow = n_flog(UWORD_MAX, base); d = n_randint(state, max_pow); /* root */ if (!d) d+=1; c = n_pow(base, d); /* number */ a = n_rootrem(&b, c, d); result = ((a == base) && (b == 0)); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu remainder = %wu\n" "Expected answer : base = %wu remainder = 0\n", c, d, a, b, base); } /* n of type a^b + 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, b, c, d, max_pow, base; base = n_randint(state, upper_limit - 2) + 2; /* base between 2 to 2642245*/ max_pow = n_flog(UWORD_MAX, base); d = n_randint(state, max_pow); if (d < 2) /* root between 2 to max_pow */ d = 2; c = n_pow(base, d) + 1; /* number */ a = n_rootrem(&b, c, d); result = ((a == base) && (b == 1)); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu remainder = %wu\n" "Expected answer : base = %wu remainder = 1\n", c, d, a, b, base); } /* n of type a^b - 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, b, c, d, j, val, max_pow, base; mpz_t e, f, g, h; mpz_init(e); mpz_init(f); mpz_init(g); mpz_init(h); base = n_randint(state, upper_limit - 2) + 2; /* base between 2 to 2642245*/ max_pow = n_flog(UWORD_MAX, base); d = n_randint(state, max_pow); if (d < 2) /* root between 2 to max_pow */ d = 2; flint_mpz_set_ui(h, d); c = n_pow(base, d) - 1; /* number */ flint_mpz_set_ui(g, c); a = n_rootrem(&b, c, d); mpz_rootrem(e, f, g, flint_mpz_get_ui(h)); val = flint_mpz_get_ui(e); j = flint_mpz_get_ui(f); result = ((a == val) && (b == j)); if (!result) TEST_FUNCTION_FAIL( "Passed Parameters : n = %wu root = %wu\n" "Answer generated : base = %wu remainder = %wu\n" "Expected answer : base = %wu remainder = %wu\n", c, d, a, b, val, j); mpz_clear(e); mpz_clear(f); mpz_clear(g); mpz_clear(h); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-sizeinbase.c000066400000000000000000000023371461254215100216610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_sizeinbase, state) { mp_limb_t n; int base, size1, size2; slong rep; mpz_t t; char * str; mpz_init(t); str = flint_malloc((FLINT_BITS + 1) * sizeof(char)); for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { n = n_randtest(state); base = 2 + n_randint(state, 34); size1 = n_sizeinbase(n, base); flint_mpz_set_ui(t, n); mpz_get_str(str, base, t); size2 = strlen(str); if (size1 != size2) TEST_FUNCTION_FAIL( "n = %wu, base = %d\n" "n_sizeinbase: %d, strlen: %d\n", n, base, size1, size2); } flint_free(str); mpz_clear(t); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-sqrt.c000066400000000000000000000032261461254215100205140ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_sqrt, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, s1, s2; mpz_t a_m, s2_m; mpz_init(a_m); mpz_init(s2_m); a = n_randtest(state); s1 = n_sqrt(a); flint_mpz_set_ui(a_m, a); mpz_sqrt(s2_m, a_m); s2 = flint_mpz_get_ui(s2_m); result = (s1 == s2); if (!result) TEST_FUNCTION_FAIL("a = %wu, s1 = %wd, s2 = %wu\n", a, s1, s2); mpz_clear(a_m); mpz_clear(s2_m); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, s1, s2, bits; mpz_t a_m, s2_m; mpz_init(a_m); mpz_init(s2_m); bits = n_randint(state, FLINT_BITS/2 + 1); a = n_randtest_bits(state, bits); a = a*a; a += (n_randint(state, 100) - 50); s1 = n_sqrt(a); flint_mpz_set_ui(a_m, a); mpz_sqrt(s2_m, a_m); s2 = flint_mpz_get_ui(s2_m); result = (s1 == s2); if (!result) TEST_FUNCTION_FAIL("a = %wu, s1 = %wd, s2 = %wu\n", a, s1, s2); mpz_clear(a_m); mpz_clear(s2_m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-sqrtmod.c000066400000000000000000000031541461254215100212140ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_sqrtmod, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random integers */ { mp_limb_t a, b, p, pinv; p = n_randtest_prime(state, 0); a = n_randtest(state) % p; b = n_sqrtmod(a, p); pinv = n_preinvert_limb(p); result = (b == 0 || n_mulmod2_preinv(b, b, p, pinv) == a); if (!result) TEST_FUNCTION_FAIL( "p = %wu\n" "a = %wu\n" "b = %wu\n", p, a, b); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random squares */ { mp_limb_t a, b, p, pinv; p = n_randtest_prime(state, 0); do b = n_randtest(state) % p; while (b == 0); pinv = n_preinvert_limb(p); a = n_mulmod2_preinv(b, b, p, pinv); b = n_sqrtmod(a, p); result = (n_mulmod2_preinv(b, b, p, pinv) == a); if (!result) TEST_FUNCTION_FAIL( "p = %wu\n" "a = %wu\n" "b = %wu\n", p, a, b); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-sqrtmod_primepow.c000066400000000000000000000107331461254215100231370ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_sqrtmod_primepow, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random squares mod a power of 2 */ { mp_limb_t a, b, p, pow, pow2, pinv; slong exp, num, i; mp_limb_t * sqrt; int btest; p = 2; exp = n_randint(state, FLINT_BITS - 1) + 1; pow = n_pow(p, exp); b = n_randtest(state) % pow; pow2 = p; while (FLINT_BIT_COUNT(p*pow2) <= 12) pow2 *= p; if ((b % (p*pow2)) == 0) { b += pow2; b %= pow; } pinv = n_preinvert_limb(pow); a = n_mulmod2_preinv(b, b, pow, pinv); num = n_sqrtmod_primepow(&sqrt, a, p, exp); btest = 0; for (i = 0; i < num; i++) { if (a != n_mulmod2_preinv(sqrt[i], sqrt[i], pow, pinv)) break; if (sqrt[i] == b) btest = 1; } result = btest & (i == num); if (!result) TEST_FUNCTION_FAIL( "p = %wu\n" "exp = %wd\n" "a = %wu\n" "b = %wu\n" "num = %wd\n" "btest = %d\n" "i != num = %d\n", p, exp, a, b, num, btest, i != num); flint_free(sqrt); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random squares mod other prime powers */ { mp_limb_t a, b, p, pow, pow2, pinv; slong exp, maxexp, num, i; flint_bitcnt_t bits; mp_limb_t * sqrt; int btest; bits = n_randint(state, 18) + 2; p = n_randprime(state, bits, 0); maxexp = FLINT_BITS/bits; exp = n_randint(state, maxexp) + 1; pow = n_pow(p, exp); b = n_randtest(state) % pow; if (bits <= FLINT_BITS/2) { pow2 = p; while (FLINT_BIT_COUNT(p*pow2) <= 12) pow2 *= p; if ((b % (p*pow2)) == 0) b += pow2; b %= pow; } pinv = n_preinvert_limb(pow); a = n_mulmod2_preinv(b, b, pow, pinv); num = n_sqrtmod_primepow(&sqrt, a, p, exp); btest = 0; for (i = 0; i < num; i++) { if (a != n_mulmod2_preinv(sqrt[i], sqrt[i], pow, pinv)) break; if (sqrt[i] == b) btest = 1; } result = btest & (i == num); if (!result) TEST_FUNCTION_FAIL( "p = %wu\n" "exp = %wd\n" "a = %wu\n" "b = %wu\n" "num = %wd\n" "btest = %d\n" "i != num = %d\n", p, exp, a, b, num, btest, i != num); flint_free(sqrt); } for (i = 0; i < 500 * flint_test_multiplier(); i++) /* Test random nonsquares */ { mp_limb_t a, b, p, pow, pinv; slong exp, maxexp; flint_bitcnt_t bits; mp_limb_t * sqrt; bits = n_randint(state, 18) + 2; p = n_randprime(state, bits, 0); maxexp = 20/bits; exp = n_randint(state, maxexp) + 1 + (p == 2); pow = n_pow(p, exp); pinv = n_preinvert_limb(pow); a = n_randtest(state) % pow; while (n_sqrtmod_primepow(&sqrt, a, p, exp)) { if (n_mulmod2_preinv(sqrt[0], sqrt[0], pow, pinv) != a) TEST_FUNCTION_FAIL("%wu^2 is not %wu mod %wu\n", sqrt[0], a, pow); flint_free(sqrt); a = n_randtest(state) % pow; } for (b = 0; b < pow; b++) { if (n_mulmod2_preinv(b, b, pow, pinv) == a) break; } result = (b == pow); if (!result) TEST_FUNCTION_FAIL( "p = %wu\n" "exp = %wd\n" "a = %wu\n" "b = %wu\n", p, exp, a, b); flint_free(sqrt); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-sqrtmodn.c000066400000000000000000000053331461254215100213730ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_sqrtmodn, state) { int i, result; for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random squares mod n */ { mp_limb_t a, b, n, ninv; slong num, i; flint_bitcnt_t bits; mp_limb_t * sqrt; int btest; n_factor_t fac; bits = n_randint(state, 18) + 1; n = n_randtest_bits(state, bits); b = n_randtest(state) % n; n_factor_init(&fac); n_factor(&fac, n, 0); ninv = n_preinvert_limb(n); a = n_mulmod2_preinv(b, b, n, ninv); num = n_sqrtmodn(&sqrt, a, &fac); btest = 0; for (i = 0; i < num; i++) { if (a != n_mulmod2_preinv(sqrt[i], sqrt[i], n, ninv)) break; if (sqrt[i] == b) btest = 1; } result = btest & (i == num); if (!result) TEST_FUNCTION_FAIL( "n = %wu\n" "a = %wu\n" "b = %wu\n" "num = %wd\n" "btest = %d\n" "i != num = %d\n", n, a, b, num, btest, i != num); flint_free(sqrt); } for (i = 0; i < 500 * flint_test_multiplier(); i++) /* test random nonsquares */ { mp_limb_t a, b, n, ninv; flint_bitcnt_t bits; mp_limb_t * sqrt; n_factor_t fac; bits = n_randint(state, 18) + 2; n = n_randtest_bits(state, bits); if (n == 2) n++; n_factor_init(&fac); n_factor(&fac, n, 0); ninv = n_preinvert_limb(n); a = n_randtest(state) % n; while (n_sqrtmodn(&sqrt, a, &fac)) { if (n_mulmod2_preinv(sqrt[0], sqrt[0], n, ninv) != a) TEST_FUNCTION_FAIL("%wu^2 is not %wu mod %wu\n", sqrt[0], a, n); flint_free(sqrt); a = n_randtest(state) % n; } for (b = 0; b < n; b++) { if (n_mulmod2_preinv(b, b, n, ninv) == a) break; } result = (b == n); if (!result) TEST_FUNCTION_FAIL( "n = %wu\n" "a = %wu\n" "b = %wu\n", n, a, b); flint_free(sqrt); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-sqrtrem.c000066400000000000000000000037331461254215100212230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "gmpcompat.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_sqrtrem, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, r1, r2, s1, s2; mpz_t a_m, r2_m, s2_m; mpz_init(a_m); mpz_init(r2_m); mpz_init(s2_m); a = n_randtest(state); s1 = n_sqrtrem(&r1, a); flint_mpz_set_ui(a_m, a); mpz_sqrtrem(s2_m, r2_m, a_m); r2 = flint_mpz_get_ui(r2_m); s2 = flint_mpz_get_ui(s2_m); result = ((r1 == r2) && (s1 == s2)); if (!result) TEST_FUNCTION_FAIL("a = %wu, r1 = %wd, r2 = %wu, s1 = %wd, s2 = %wu\n", a, r1, r2, s1, s2); mpz_clear(a_m); mpz_clear(r2_m); mpz_clear(s2_m); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t a, r1, r2, s1, s2, bits; mpz_t a_m, r2_m, s2_m; mpz_init(a_m); mpz_init(r2_m); mpz_init(s2_m); bits = n_randint(state, FLINT_BITS/2 + 1); a = n_randtest_bits(state, bits); a = a*a; a += (n_randint(state, 100) - 50); s1 = n_sqrtrem(&r1, a); flint_mpz_set_ui(a_m, a); mpz_sqrtrem(s2_m, r2_m, a_m); r2 = flint_mpz_get_ui(r2_m); s2 = flint_mpz_get_ui(s2_m); result = ((r1 == r2) && (s1 == s2)); if (!result) TEST_FUNCTION_FAIL("a = %wu, r1 = %wd, r2 = %wu, s1 = %wd, s2 = %wu\n", a, r1, r2, s1, s2); mpz_clear(a_m); mpz_clear(r2_m); mpz_clear(s2_m); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-submod.c000066400000000000000000000021771461254215100210200ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_submod, state) { int i, result; for (i = 0; i < 100000 * flint_test_multiplier(); i++) { ulong a, b, d, r1, r2, s1; d = n_randtest_not_zero(state); a = n_randtest(state) % d; b = n_randtest(state) % d; r1 = n_submod(a, b, d); add_ssaaaa(s1, r2, UWORD(0), a, UWORD(0), d); sub_ddmmss(s1, r2, s1, r2, UWORD(0), b); if (s1 != 0 || r2 >= d) r2 -= d; result = (r1 == r2); if (!result) TEST_FUNCTION_FAIL( "a = %wu, b = %wu, d = %wu\n" "r1 = %wu, r2 = %wu\n", a, b, d, r1, r2); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-urandint.c000066400000000000000000000055141461254215100213510ustar00rootroot00000000000000/* Copyright (C) 2017 Apoorv Mishra This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_urandint, state) { ulong limit, rand_num; slong deviation; int i, j, result; int * count; int * count_in_subrange; slong test_multiplier; test_multiplier = FLINT_MAX(1, flint_test_multiplier()); /* Test for limit <= 1000 */ count = flint_malloc(sizeof(int) * 1000); for (limit = 1; limit <= 1000; limit+=10) { for (i = 0; i < limit; i++) { count[i] = 0; } for (i = 0; i < 1000 * test_multiplier; i++) { rand_num = n_urandint(state, limit); count[rand_num]++; } result = 1; for (i = 0; i < limit; i++) { deviation = count[i] - (1000 * (int) test_multiplier)/limit; if (deviation >= WORD(100) * test_multiplier || deviation <= WORD(-100) * test_multiplier) { result = 0; break; } } if (!result) TEST_FUNCTION_FAIL("limit = %wu, deviation = %wd\n", limit, deviation); } flint_free(count); /* Test for larger values of limit */ count_in_subrange = flint_malloc(sizeof(int) * 4); for (i = 0; i < 1000; i+=10) { for (j = 0; j < 4; j++) { count_in_subrange[j] = 0; } limit = UWORD_MAX/(i + 2)*(i + 1); for (j = 0; j < 1000 * test_multiplier; j++) { rand_num = n_urandint(state, limit); if (rand_num >= 3*(limit >> 2)) { count_in_subrange[3]++; } else if (rand_num >= 2*(limit >> 2)) { count_in_subrange[2]++; } else if (rand_num >= (limit >> 2)) { count_in_subrange[1]++; } else { count_in_subrange[0]++; } } result = 1; for (j = 0; j < 4; j++) { deviation = count_in_subrange[j] - ((1000 * (int) test_multiplier) >> 2); if (deviation >= WORD(100) * test_multiplier || deviation <= WORD(-100) * test_multiplier) { result = 0; break; } } if (!result) TEST_FUNCTION_FAIL("limit = %wu, deviation = %wd\n", limit, deviation); } flint_free(count_in_subrange); TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/test/t-xgcd.c000066400000000000000000000052621461254215100204520ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "test_helpers.h" #include "ulong_extras.h" TEST_FUNCTION_START(n_xgcd, state) { int i, result; for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, b, c, g, bits1, bits2, bits3, ph, pl, qh, ql; ulong s, t; bits1 = n_randint(state, FLINT_BITS - 1) + 2; bits2 = n_randint(state, bits1) + 1; bits3 = bits1 == FLINT_BITS ? 0 : n_randint(state, FLINT_BITS - bits1) + 1; do { a = n_randtest_bits(state, bits1); b = n_randtest_bits(state, bits2); } while (n_gcd(a, b) != UWORD(1) || b > a); c = bits3 == 0 ? 1 : n_randtest_bits(state, bits3); g = n_xgcd(&s, &t, a * c, b * c); /* s*ac + t*bc */ umul_ppmm(ph, pl, a * c, s); umul_ppmm(qh, ql, b * c, t); sub_ddmmss(ph, pl, ph, pl, qh, ql); result = (s <= b * c || b * c == 0); if (!result) TEST_FUNCTION_FAIL( "s >= b*c\n" "a = %wu, b = %wu, c = %wu, g = %wu, s = %wu, t = %wu\n", a, b, c, g, s, t); result = (t <= a * c || a * c == 0); if (!result) TEST_FUNCTION_FAIL( "t >= a*c\n" "a = %wu, b = %wu, c = %wu, g = %wu, s = %wu, t = %wu\n", a, b, c, g, s, t); result = (g == c && ph == UWORD(0) && pl == c); if (!result) TEST_FUNCTION_FAIL( "g != c or s*ac + t*bc != c\n" "a = %wu, b = %wu, c = %wu, g = %wu, s = %wu, t = %wu\n", a, b, c, g, s, t); } /* a = 0, b = 0 */ { ulong g, s, t; g = n_xgcd(&s, &t, 0, 0); result = (g == 0 && s == 1 && t == 0); if (!result) TEST_FUNCTION_FAIL( "Case a = 0, b = 0\n" "g = %wu, s = %wu, t = %wu\n", g, s, t); } /* b = 0 */ { ulong a, g, s, t; a = n_randtest(state); g = n_xgcd(&s, &t, a, 0); result = (g == a && s == 1 && t == 0); if (!result) TEST_FUNCTION_FAIL( "Case a = 0\n" "a = %wu, g = %wu, s = %wu, t = %wu\n", a, g, s, t); } TEST_FUNCTION_END(state); } flint-3.1.3/src/ulong_extras/xgcd.c000066400000000000000000000063471461254215100172370ustar00rootroot00000000000000/* Copyright (C) 2009, 2016 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" ulong n_xgcd(ulong * a, ulong * b, ulong x, ulong y) { slong u1, u2, v1, v2, t1, t2; ulong u3, v3, quot, rem, d; FLINT_ASSERT(x >= y); u1 = v2 = 1; u2 = v1 = 0; u3 = x; v3 = y; /* x and y both have top bit set */ if ((slong) (x & y) < WORD(0)) { d = u3 - v3; t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } /* second value has second msb set */ while ((slong) (v3 << 1) < WORD(0)) { d = u3 - v3; if (d < v3) /* quot = 1 */ { t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } else if (d < (v3 << 1)) /* quot = 2 */ { t1 = u2; u2 = u1 - (u2 << 1); u1 = t1; u3 = v3; t2 = v2; v2 = v1 - (v2 << 1); v1 = t2; v3 = d - u3; } else /* quot = 3 */ { t1 = u2; u2 = u1 - 3 * u2; u1 = t1; u3 = v3; t2 = v2; v2 = v1 - 3 * v2; v1 = t2; v3 = d - (u3 << 1); } } while (v3) { d = u3 - v3; /* overflow not possible, top 2 bits of v3 not set */ if (u3 < (v3 << 2)) { if (d < v3) /* quot = 1 */ { t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } else if (d < (v3 << 1)) /* quot = 2 */ { t1 = u2; u2 = u1 - (u2 << 1); u1 = t1; u3 = v3; t2 = v2; v2 = v1 - (v2 << 1); v1 = t2; v3 = d - u3; } else /* quot = 3 */ { t1 = u2; u2 = u1 - 3 * u2; u1 = t1; u3 = v3; t2 = v2; v2 = v1 - 3 * v2; v1 = t2; v3 = d - (u3 << 1); } } else { quot = u3 / v3; rem = u3 - v3 * quot; t1 = u2; u2 = u1 - quot * u2; u1 = t1; u3 = v3; t2 = v2; v2 = v1 - quot * v2; v1 = t2; v3 = rem; } } /* Remarkably, |u1| < x/2, thus comparison with 0 is valid */ if (u1 <= WORD(0)) { u1 += y; v1 -= x; } *a = u1; *b = -v1; return u3; } flint-3.1.3/todo.txt000066400000000000000000000272131461254215100143460ustar00rootroot00000000000000TODO ==== fmpz ---- * [maybe] figure out how to write robust test code for fmpz_read (which reads from stdin), perhaps using a pipe * [maybe] Avoid the double allocation of both an mpz struct and limb data, having an fmpz point directly to a combined structure. This would require writing replacements for most mpz functions. ulong_extras ------------ * in is_prime_pocklington allow the cofactor to be a perfect power not just prime * factor out some common code between n_is_perfect_power235 and n_factor_power235 * n_mod2_preinv may be slower than the chip on Core2 due to the fact that it can pipeline 2 divisions. Check all occurrences of this function and replace with divisions where it will speed things up on Core2. Beware, this will slow things down on AMD, so it is necessary to do this per architecture. The macros in nmod_vec will also be faster than the functions in ulong_extras, thus they should be tried first. * add profile code for factor_trial, factor_one_line, factor_SQUFOF * [maybe] make n_factor_t an array of length 1 so it can be passed by reference automatically, as per mpz_t's, etc * [enhancement] Implement a primality test which only requires factoring of n-1 up to n^1/3 or n^1/4 * [enhancement] Implement a combined p-1 and p+1 primality test as per http://primes.utm.edu/prove/prove3_3.html * [enhancement] Implement a quadratic sieve and use it in n_factor once things get too large for SQUFOF * Claus Fieker suggested that in BPSW we should do Miller-Rabin rather than Fermat test. The advantage is it will throw out more composites before the Fibonacci or Lucas tests are run, but still ensures you have a base-2 probable prime. This should speed the test up. long_extras ----------- * write and use z_invert in fmpz_invert fmpz_factor ----------- * Tune Brent-Pollard Rho for optimal values * Find optimal values for B1, B2 for ECM. * Use multipoint polynomial evaluation in ECM stage II. fmpz_mpoly ---------- * Implement array version of divrem_ideal. * Don't restart division if upgrading to multiprecision. * Check quotient and remainder coefficients are normalised the same way for small vs multiprecision division functions. Beware one normalisation may require an extra bit for either q or r in signed integer division in small case. This is probably why C division is normalised the way it is. * Implement fmpz_mpoly_ui/si/fmpz_sub functions for Nemo. * Add references to Monagan and Pearce papers to bibtex and reference in heap multiplication, powering and division functions. * Move functions in mpoly/MISSING_FXNS.c and decarations in mpoly.h to their appropriate places. nmod_poly --------- * Make some assembly optimisations to nmod_poly module. * Add basecase versions of log, sqrt, invsqrt series * Add O(M(n)) powering mod x^n based on exp and log * Implement fast mulmid and use to improve Newton iteration * Determine cutoffs for compose_series_divconquer for default use in compose_series (only when one polynomial is small). * Optimise, write an underscore version of, and test nmod_poly_remove * Improve powmod and powpowmod using precomputed Newton inverse and 2^k-ary/sliding window powering. * Maybe restructure the code in factor.c * Add a (fast) function to convert an nmod_poly_factor_t to an expanded polynomial fmpz_poly --------- * add test code for fmpz_poly_max_limbs * Improve the implementations of fmpz_poly_divrem, _div, and _rem, check that the documentations still apply, and write test code for this --- all of this makes more sense once there is a choice of algorithms * Include test code for fmpz_poly_inv_series, once this method does anything better than aliasing fmpz_poly_inv_newton * Sort out the fmpz_poly_pseudo_div and _rem code. Currently this is just a hack to call fmpz_poly_pseudo_divrem * Fix the inefficient cases in CRT_ui, and move the relevant parts of this function to the fmpz_vec module * Avoid redundant work and memory allocation in fmpz_poly_bit_unpack and fmpz_poly_bit_unpack_unsigned. * Add functions for composition, multiplication and division by a monic linear factor, i.e. P(x +/- c), P * (x +/- c), P / (x +/- c). * xgcd_modular is really slow. But it is not clear why. 1/3 of the time is spent in resultant, but the CRT code or the nmod_poly_xgcd code may also be to blame. * Make resultants use fast GCD? * In fmpz_poly_pseudo_divrem_divconquer, fix the repeated memory allocation of size O(lenA) in the case when lenA >> lenB. fmpq_poly --------- * add fmpq_poly_fprint_pretty * Rewrite _fmpq_poly_interpolate_fmpz_vec to use the Newton form as done in the fmpz_poly interpolation function. In general this should be much faster. * Add versions of fmpq_poly_interpolate_fmpz_vec for fmpq y values, and fmpq values of both x and y. * Add mulhigh * Add asymptotically fast resultants? * Add pow_trunc * Add gcdinv * Add discriminant fmpz_mod_poly ------------- * Replace fmpz_mod_poly_rem by a proper implementation which actually saves work over divrem. Then, also add test code. * Implement a faster GCD function then the euclidean one, then make the wrapping GCD function choose the appropriate algorithm, and add some test code fmpz_poly_mat ------------- * Tune multiplication cutoffs. * Take sparseness into account when selecting between algorithms. * Investigate more clever pivoting strategies in row reduction. arith ----- * Think of a better name for this module and/or move parts of it to other modules. * Write profiling code. * Write a faster arith_divisors using the merge sort algorithm (see Sage's implementation). Alternatively (or as a complement) write a supernaturally fast _fmpz_vec_sort. * Improve arith_divisors by using long and longlong arithmetic for divisors that fit in 1 or 2 limbs. * Optimise memory management in mpq_harmonic. * Maybe move the helper functions in primorial.c to the mpn_extras module. * Implement computation of generalised harmonic numbers. * Maybe: move Stirling number matrix functions to the fmpz_mat module. * Implement computation of Bernoulli numbers modulo a prime (e.g. porting the code from flint 1) * Implement multimodular computation of large Bernoulli numbers (e.g. porting bernmm) * Implement rising factorials and falling factorials (x)_n, (x)^n as fmpz_poly functions, and add fmpz functions for their direct evaluation. * Implement the binomial coefficient binomial(x,n) as an fmpq_poly function. * Implement Fibonacci polynomials and fmpz Fibonacci numbers. * Implement orthogonal polynomials (Jacobi, Hermite, Laguerre, Gegenbauer). * Implement hypergeometric polynomials and series. * Change the partition function code to use an fmpz (or mpz) instead of ulong for n, to allow n larger than 10^9 on 32 bits (or 10^19 on 64 bits!) * Write tests for the arith_hrr_expsum_factored functions. fmpz_mat -------- * Add fmpz_mat/randajtai2.c based on Stehle's matrix.cpp in fpLLL (requires mpfr_t's). * Add element getter and setter methods. * Implement Strassen multiplication. * Implement fast multiplication when when results are smaller than 2^(FLINT_BITS-1) by using fmpz arithmetic directly. Also use 2^FLINT_BITS as one of the "primes" for multimodular multiplication, along with fast CRT code for this purpose. * Write multiplication functions optimised for sparse matrices by changing the loop order and discarding zero multipliers. * Implement fast null space computation. * The Dixon p-adic solver should implement output-sensitive termination. * The Dixon p-adic solver currently spends most of the time computing integer matrix-vector products. Instead of using a single prime, it is likely to be faster to use a product of primes to increase the proportion of time spent on modular linear algebra. The code should also use fast radix conversion instead of building up the result incrementally to improve performance when the output gets large. * Maybe optimise multimodular multiplication by pre-transposing so that transposed nmod_mat multiplication can be used directly instead of creating a transposed copy in nmod_mat_mul. However, this doesn't help in the Strassen range unless there also is a transpose version of nmod_mat_mul_strassen. * Use _fmpz_vec functions instead of for loops in some more places. * Add transpose versions of common functions, in-place addmul etc. * Take sparseness into account when selecting between algorithms. * Maybe simplify the interface for row reduction by guaranteeing that the denominator is the determinant. fmpz_lll -------- * Improve the wrapper strategy, if possible. * Add an mpf version of is_reduced functions so that the dependency on MPFR can be removed. * Componentize the is_reduced code so that the R computed during LLL can be reused. nmod_mat -------- * Support BLAS and use this for multiplication when entries fit in a double before reduction. Even for large moduli, it might be faster to use repeated BLAS multiplications modulo a few small primes followed by CRT. Linear algebra operations would benefit from BLAS versions of triangular solving as well. * Improve multiplication with packed entries using SSE. Maybe also write a Strassen for packed entries that does additions faster. * Investigate why the constant of solving/rref/inverse compared to multiplication appears to be worse than in theory (recent paper by Jeannerod, Pernet and Storjohann). * See if Strassen can be improved using combined addmul operations. * Consider getting rid of the row pointer array, using offsets instead of window matrices. The row pointer is only useful for Gaussian elimination, but there we end up working with a separate permutation array anyway. * Add element getter and setter methods, more convenience functions for setting the zero matrix, identity matrix, etc. * Implement nmod_mat_pow. * Add functions for computing A*B^T and A^T*B, using transpose multiplications directly to avoid creating a temporary copy. * Maybe: add asserts to check that the modulus is a prime where this is assumed. * Add transpose versions of common functions, in-place addmul etc. * The current addmul/submul functions are misnamed since they implement a more general operation. * Improve rref and inverse to perform everything in-place. fmpq ---- * Add more functions for generating random numbers. * Write a subquadratic fmpq_get_cfrac * Implement subquadratic rational reconstruction. Also improve detection of integers, etc. and perhaps add CRT functions to hide the intermediate step going from residues -> integer -> rational. fmpq_mat -------- * Add more random functions. * Add a user-friendly function for LUP decomposition. * Add a nullspace function. padic ----- * Add test code for the various output formats; perhaps in the form of examples? * Implement padic_val_fac for generic inputs mpf_vec/mat ----------- * _mpf_vec_approx_equal uses the bizarre mpf notion of equal; it should be either renamed equal_bits or the absolute value of the difference should be compared with zero * The conditions used in mpf_mat_qr/gso (similarly for d_mat module) work, but don't match those used in the algorithm in the paper referenced in the docs. This is possibly because mpf doesn't do exact rounding. The tests could probably be improved. d_mat ----- * d_mat_transpose tries to be clever with the cache, but it could use L1 sized blocks and optimise for sequential reading/writing. It could also handle in-place much more efficiently. * d_mat_is_reduced doesn't seem to make any guarantees about reducedness, just approximately checks the Lovasz conditions in double arithmetic. I think this is superseded now and can be removed. It is not used anywhere.